From fdee50d4cd0b578b7f7ed89bb6480844adbc7704 Mon Sep 17 00:00:00 2001 From: conrevo Date: Wed, 24 Apr 2024 21:13:24 -0400 Subject: [PATCH 01/89] finish sampler, next step implement operator for single table aggregation --- src/include/duckdb/storage/table/scan_state.hpp | 3 +++ src/storage/table/row_group.cpp | 7 +++++++ src/storage/table/scan_state.cpp | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/include/duckdb/storage/table/scan_state.hpp b/src/include/duckdb/storage/table/scan_state.hpp index 7b8160fdc08..5c477d15fc0 100644 --- a/src/include/duckdb/storage/table/scan_state.hpp +++ b/src/include/duckdb/storage/table/scan_state.hpp @@ -12,6 +12,7 @@ #include "duckdb/storage/buffer/buffer_handle.hpp" #include "duckdb/storage/storage_lock.hpp" #include "duckdb/common/enums/scan_options.hpp" +#include "duckdb/common/random_engine.hpp" #include "duckdb/execution/adaptive_filter.hpp" #include "duckdb/storage/table/segment_lock.hpp" @@ -128,6 +129,8 @@ class CollectionScanState { //! The current batch index idx_t batch_index; + RandomEngine random; + public: void Initialize(const vector &types); const vector &GetColumnIds(); diff --git a/src/storage/table/row_group.cpp b/src/storage/table/row_group.cpp index 69b4c607620..68f9137b36c 100644 --- a/src/storage/table/row_group.cpp +++ b/src/storage/table/row_group.cpp @@ -22,6 +22,7 @@ #include "duckdb/common/serializer/binary_serializer.hpp" #include "duckdb/planner/filter/conjunction_filter.hpp" #include "duckdb/planner/filter/struct_filter.hpp" +// #include "duckdb/common/printer.hpp" namespace duckdb { @@ -405,6 +406,12 @@ static idx_t GetFilterScanCount(ColumnScanState &state, TableFilter &filter) { } bool RowGroup::CheckZonemapSegments(CollectionScanState &state) { + // table sample blocks + if (state.random.NextRandom() > 0.1) { + NextVector(state); + return false; + } + auto &column_ids = state.GetColumnIds(); auto filters = state.GetFilters(); if (!filters) { diff --git a/src/storage/table/scan_state.cpp b/src/storage/table/scan_state.cpp index 6931d1056fd..addb19483ef 100644 --- a/src/storage/table/scan_state.cpp +++ b/src/storage/table/scan_state.cpp @@ -76,7 +76,7 @@ ParallelCollectionScanState::ParallelCollectionScanState() } CollectionScanState::CollectionScanState(TableScanState &parent_p) - : row_group(nullptr), vector_index(0), max_row_group_row(0), row_groups(nullptr), max_row(0), batch_index(0), + : row_group(nullptr), vector_index(0), max_row_group_row(0), row_groups(nullptr), max_row(0), batch_index(0), random(-1), parent(parent_p) { } From 6a3e38f8bfd8abf69b509709da6520d228ccbdc3 Mon Sep 17 00:00:00 2001 From: conrevo Date: Wed, 24 Apr 2024 23:05:29 -0400 Subject: [PATCH 02/89] try to make chunk sample work for single table, but failed to compile --- scripts/generate_enum_util.py | 2 +- src/common/enum_util.cpp | 3 +++ .../helper/physical_streaming_sample.cpp | 2 ++ src/execution/physical_plan/plan_sample.cpp | 1 + src/include/duckdb/common/types/data_chunk.hpp | 3 +++ .../execution/physical_operator_states.hpp | 1 + .../parser/parsed_data/sample_options.hpp | 2 +- src/parallel/pipeline_executor.cpp | 2 +- .../transform/helpers/transform_sample.cpp | 2 ++ src/storage/table/row_group.cpp | 18 ++++++++++++------ 10 files changed, 27 insertions(+), 9 deletions(-) diff --git a/scripts/generate_enum_util.py b/scripts/generate_enum_util.py index 5244050842f..7c83fc43ef7 100644 --- a/scripts/generate_enum_util.py +++ b/scripts/generate_enum_util.py @@ -31,7 +31,7 @@ "NULLS_FIRST": ["NULLS_FIRST", "NULLS FIRST"], "NULLS_LAST": ["NULLS_LAST", "NULLS LAST"], }, - "SampleMethod": {"SYSTEM_SAMPLE": "System", "BERNOULLI_SAMPLE": "Bernoulli", "RESERVOIR_SAMPLE": "Reservoir"}, + "SampleMethod": {"SYSTEM_SAMPLE": "System", "BERNOULLI_SAMPLE": "Bernoulli", "RESERVOIR_SAMPLE": "Reservoir", "CHUNK_SAMPLE": "Chunk"}, "TableReferenceType": {"EMPTY_FROM": "EMPTY"}, } diff --git a/src/common/enum_util.cpp b/src/common/enum_util.cpp index 12a94a2b0f1..ec9ed238830 100644 --- a/src/common/enum_util.cpp +++ b/src/common/enum_util.cpp @@ -5571,6 +5571,9 @@ SampleMethod EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "Reservoir")) { return SampleMethod::RESERVOIR_SAMPLE; } + if (StringUtil::Equals(value, "Chunk")) { + return SampleMethod::CHUNK_SAMPLE; + } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } diff --git a/src/execution/operator/helper/physical_streaming_sample.cpp b/src/execution/operator/helper/physical_streaming_sample.cpp index cda2fa251ee..ec16f6527f5 100644 --- a/src/execution/operator/helper/physical_streaming_sample.cpp +++ b/src/execution/operator/helper/physical_streaming_sample.cpp @@ -62,6 +62,8 @@ OperatorResultType PhysicalStreamingSample::Execute(ExecutionContext &context, D case SampleMethod::SYSTEM_SAMPLE: SystemSample(input, chunk, state); break; + case SampleMethod::CHUNK_SAMPLE: + break; default: throw InternalException("Unsupported sample method for streaming sample"); } diff --git a/src/execution/physical_plan/plan_sample.cpp b/src/execution/physical_plan/plan_sample.cpp index e13ef8eb1f7..50a9d72a5bc 100644 --- a/src/execution/physical_plan/plan_sample.cpp +++ b/src/execution/physical_plan/plan_sample.cpp @@ -18,6 +18,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalSample &op break; case SampleMethod::SYSTEM_SAMPLE: case SampleMethod::BERNOULLI_SAMPLE: + case SampleMethod::CHUNK_SAMPLE: if (!op.sample_options->is_percentage) { throw ParserException("Sample method %s cannot be used with a discrete sample count, either switch to " "reservoir sampling or use a sample_size", diff --git a/src/include/duckdb/common/types/data_chunk.hpp b/src/include/duckdb/common/types/data_chunk.hpp index 353fdf582c0..9f70e8a1d9c 100644 --- a/src/include/duckdb/common/types/data_chunk.hpp +++ b/src/include/duckdb/common/types/data_chunk.hpp @@ -13,6 +13,7 @@ #include "duckdb/common/common.hpp" #include "duckdb/common/types/vector.hpp" #include "duckdb/common/winapi.hpp" +#include "duckdb/parallel/pipeline.hpp" namespace duckdb { class Allocator; @@ -49,6 +50,8 @@ class DataChunk { //! The vectors owned by the DataChunk. vector data; + Pipeline* pipeline; + public: inline idx_t size() const { // NOLINT return count; diff --git a/src/include/duckdb/execution/physical_operator_states.hpp b/src/include/duckdb/execution/physical_operator_states.hpp index 621c8124338..c48da01d2e7 100644 --- a/src/include/duckdb/execution/physical_operator_states.hpp +++ b/src/include/duckdb/execution/physical_operator_states.hpp @@ -167,6 +167,7 @@ struct OperatorSourceInput { GlobalSourceState &global_state; LocalSourceState &local_state; InterruptState &interrupt_state; + Pipeline *pipeline; }; struct OperatorSinkCombineInput { diff --git a/src/include/duckdb/parser/parsed_data/sample_options.hpp b/src/include/duckdb/parser/parsed_data/sample_options.hpp index 201469bcf2a..e395fb8be42 100644 --- a/src/include/duckdb/parser/parsed_data/sample_options.hpp +++ b/src/include/duckdb/parser/parsed_data/sample_options.hpp @@ -15,7 +15,7 @@ namespace duckdb { -enum class SampleMethod : uint8_t { SYSTEM_SAMPLE = 0, BERNOULLI_SAMPLE = 1, RESERVOIR_SAMPLE = 2 }; +enum class SampleMethod : uint8_t { SYSTEM_SAMPLE = 0, BERNOULLI_SAMPLE = 1, RESERVOIR_SAMPLE = 2, CHUNK_SAMPLE = 3}; // **DEPRECATED**: Use EnumUtil directly instead. string SampleMethodToString(SampleMethod method); diff --git a/src/parallel/pipeline_executor.cpp b/src/parallel/pipeline_executor.cpp index 18bb5e745f0..7255454cb7d 100644 --- a/src/parallel/pipeline_executor.cpp +++ b/src/parallel/pipeline_executor.cpp @@ -462,7 +462,7 @@ SourceResultType PipelineExecutor::GetData(DataChunk &chunk, OperatorSourceInput return SourceResultType::BLOCKED; } #endif - + chunk.pipeline = &pipeline; return pipeline.source->GetData(context, chunk, input); } diff --git a/src/parser/transform/helpers/transform_sample.cpp b/src/parser/transform/helpers/transform_sample.cpp index 0cffebfed4a..a6582f6673e 100644 --- a/src/parser/transform/helpers/transform_sample.cpp +++ b/src/parser/transform/helpers/transform_sample.cpp @@ -13,6 +13,8 @@ static SampleMethod GetSampleMethod(const string &method) { return SampleMethod::BERNOULLI_SAMPLE; } else if (lmethod == "reservoir") { return SampleMethod::RESERVOIR_SAMPLE; + } else if (lmethod == "chunk") { + return SampleMethod::CHUNK_SAMPLE; } else { throw ParserException("Unrecognized sampling method %s, expected system, bernoulli or reservoir", method); } diff --git a/src/storage/table/row_group.cpp b/src/storage/table/row_group.cpp index 68f9137b36c..ce7d6316319 100644 --- a/src/storage/table/row_group.cpp +++ b/src/storage/table/row_group.cpp @@ -22,6 +22,7 @@ #include "duckdb/common/serializer/binary_serializer.hpp" #include "duckdb/planner/filter/conjunction_filter.hpp" #include "duckdb/planner/filter/struct_filter.hpp" +#include "duckdb/parser/parsed_data/sample_options.hpp" // #include "duckdb/common/printer.hpp" namespace duckdb { @@ -406,12 +407,6 @@ static idx_t GetFilterScanCount(ColumnScanState &state, TableFilter &filter) { } bool RowGroup::CheckZonemapSegments(CollectionScanState &state) { - // table sample blocks - if (state.random.NextRandom() > 0.1) { - NextVector(state); - return false; - } - auto &column_ids = state.GetColumnIds(); auto filters = state.GetFilters(); if (!filters) { @@ -463,6 +458,17 @@ void RowGroup::TemplatedScan(TransactionData transaction, CollectionScanState &s idx_t current_row = state.vector_index * STANDARD_VECTOR_SIZE; auto max_count = MinValue(STANDARD_VECTOR_SIZE, state.max_row_group_row - current_row); + // table sample blocks + if (result.pipeline->operators.size() > 0) { + auto op = result.pipeline->operators[0].get() + if (op->method == SampleMethod::CHUNK_SAMPLE) { + if (state.random.NextRandom() > op->percentage) { + NextVector(state); + continue; + } + } + } + //! first check the zonemap if we have to scan this partition if (!CheckZonemapSegments(state)) { continue; From b093e650878934205848a5fb2cdb3801c3a863e8 Mon Sep 17 00:00:00 2001 From: conrevo Date: Wed, 24 Apr 2024 23:46:24 -0400 Subject: [PATCH 03/89] 2nd try --- src/include/duckdb/common/types/data_chunk.hpp | 9 +++++++-- .../duckdb/execution/physical_operator_states.hpp | 1 - src/parallel/pipeline_executor.cpp | 12 +++++++++++- src/storage/table/row_group.cpp | 13 ++++--------- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/include/duckdb/common/types/data_chunk.hpp b/src/include/duckdb/common/types/data_chunk.hpp index 9f70e8a1d9c..f3a7304d2f1 100644 --- a/src/include/duckdb/common/types/data_chunk.hpp +++ b/src/include/duckdb/common/types/data_chunk.hpp @@ -13,7 +13,7 @@ #include "duckdb/common/common.hpp" #include "duckdb/common/types/vector.hpp" #include "duckdb/common/winapi.hpp" -#include "duckdb/parallel/pipeline.hpp" +// #include "duckdb/parallel/pipeline.hpp" namespace duckdb { class Allocator; @@ -41,6 +41,11 @@ class Deserializer; In addition to holding the data of the vectors, the DataChunk also owns the selection vector that underlying vectors can point to. */ +struct ChunkSampleOp { + bool do_chunk_sample = false; + double percentage = 0; +}; + class DataChunk { public: //! Creates an empty DataChunk @@ -50,7 +55,7 @@ class DataChunk { //! The vectors owned by the DataChunk. vector data; - Pipeline* pipeline; + ChunkSampleOp chunk_sample_op; public: inline idx_t size() const { // NOLINT diff --git a/src/include/duckdb/execution/physical_operator_states.hpp b/src/include/duckdb/execution/physical_operator_states.hpp index c48da01d2e7..621c8124338 100644 --- a/src/include/duckdb/execution/physical_operator_states.hpp +++ b/src/include/duckdb/execution/physical_operator_states.hpp @@ -167,7 +167,6 @@ struct OperatorSourceInput { GlobalSourceState &global_state; LocalSourceState &local_state; InterruptState &interrupt_state; - Pipeline *pipeline; }; struct OperatorSinkCombineInput { diff --git a/src/parallel/pipeline_executor.cpp b/src/parallel/pipeline_executor.cpp index 7255454cb7d..4580f49417a 100644 --- a/src/parallel/pipeline_executor.cpp +++ b/src/parallel/pipeline_executor.cpp @@ -1,6 +1,7 @@ #include "duckdb/parallel/pipeline_executor.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/common/limits.hpp" +#include "duckdb/execution/operator/helper/physical_streaming_sample.hpp" #ifdef DUCKDB_DEBUG_ASYNC_SINK_SOURCE #include @@ -462,7 +463,16 @@ SourceResultType PipelineExecutor::GetData(DataChunk &chunk, OperatorSourceInput return SourceResultType::BLOCKED; } #endif - chunk.pipeline = &pipeline; + if (pipeline.operators.size() > 0) { + auto& op = pipeline.operators[0].get(); + if (op.type == PhysicalStreamingSample::TYPE) { + auto& cast_op = op.Cast(); + if (cast_op.method == SampleMethod::CHUNK_SAMPLE) { + chunk.chunk_sample_op.do_chunk_sample = true; + chunk.chunk_sample_op.percentage = cast_op.percentage; + } + } + } return pipeline.source->GetData(context, chunk, input); } diff --git a/src/storage/table/row_group.cpp b/src/storage/table/row_group.cpp index ce7d6316319..8c90272dba3 100644 --- a/src/storage/table/row_group.cpp +++ b/src/storage/table/row_group.cpp @@ -22,8 +22,6 @@ #include "duckdb/common/serializer/binary_serializer.hpp" #include "duckdb/planner/filter/conjunction_filter.hpp" #include "duckdb/planner/filter/struct_filter.hpp" -#include "duckdb/parser/parsed_data/sample_options.hpp" -// #include "duckdb/common/printer.hpp" namespace duckdb { @@ -459,13 +457,10 @@ void RowGroup::TemplatedScan(TransactionData transaction, CollectionScanState &s auto max_count = MinValue(STANDARD_VECTOR_SIZE, state.max_row_group_row - current_row); // table sample blocks - if (result.pipeline->operators.size() > 0) { - auto op = result.pipeline->operators[0].get() - if (op->method == SampleMethod::CHUNK_SAMPLE) { - if (state.random.NextRandom() > op->percentage) { - NextVector(state); - continue; - } + if (result.chunk_sample_op.do_chunk_sample) { + if (state.random.NextRandom() > result.chunk_sample_op.percentage) { + NextVector(state); + continue; } } From b0acdb7b4d5e484804c7d05600a0545510e02674 Mon Sep 17 00:00:00 2001 From: conrevo Date: Thu, 25 Apr 2024 02:03:38 -0400 Subject: [PATCH 04/89] works for simple query with 1 table. next step support join queries --- src/common/enum_util.cpp | 2 ++ src/execution/operator/helper/physical_streaming_sample.cpp | 6 ++++++ .../execution/operator/helper/physical_streaming_sample.hpp | 1 + 3 files changed, 9 insertions(+) diff --git a/src/common/enum_util.cpp b/src/common/enum_util.cpp index ec9ed238830..f9913e89a5c 100644 --- a/src/common/enum_util.cpp +++ b/src/common/enum_util.cpp @@ -5555,6 +5555,8 @@ const char* EnumUtil::ToChars(SampleMethod value) { return "Bernoulli"; case SampleMethod::RESERVOIR_SAMPLE: return "Reservoir"; + case SampleMethod::CHUNK_SAMPLE: + return "Chunk"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } diff --git a/src/execution/operator/helper/physical_streaming_sample.cpp b/src/execution/operator/helper/physical_streaming_sample.cpp index ec16f6527f5..264b6c22a73 100644 --- a/src/execution/operator/helper/physical_streaming_sample.cpp +++ b/src/execution/operator/helper/physical_streaming_sample.cpp @@ -49,6 +49,11 @@ void PhysicalStreamingSample::BernoulliSample(DataChunk &input, DataChunk &resul } } +void PhysicalStreamingSample::ChunkSample(DataChunk &input, DataChunk &result, OperatorState &state_p) const { + // chunk sampling: identity function + result.Reference(input); +} + unique_ptr PhysicalStreamingSample::GetOperatorState(ExecutionContext &context) const { return make_uniq(seed); } @@ -63,6 +68,7 @@ OperatorResultType PhysicalStreamingSample::Execute(ExecutionContext &context, D SystemSample(input, chunk, state); break; case SampleMethod::CHUNK_SAMPLE: + ChunkSample(input, chunk, state); break; default: throw InternalException("Unsupported sample method for streaming sample"); diff --git a/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp b/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp index 40445cf52ee..0009de20c8d 100644 --- a/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp +++ b/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp @@ -41,6 +41,7 @@ class PhysicalStreamingSample : public PhysicalOperator { private: void SystemSample(DataChunk &input, DataChunk &result, OperatorState &state) const; void BernoulliSample(DataChunk &input, DataChunk &result, OperatorState &state) const; + void ChunkSample(DataChunk &input, DataChunk &result, OperatorState &state) const; }; } // namespace duckdb From 05b126fe2c81cfaea90240a5a8346f2661f073f3 Mon Sep 17 00:00:00 2001 From: Yuxuan Zhu <90142950+yuxuan18@users.noreply.github.com> Date: Fri, 21 Jun 2024 21:17:22 -0400 Subject: [PATCH 05/89] fix format (#1) --- scripts/generate_enum_util.py | 7 ++++++- src/include/duckdb/parser/parsed_data/sample_options.hpp | 2 +- src/parallel/pipeline_executor.cpp | 4 ++-- src/storage/table/scan_state.cpp | 4 ++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/scripts/generate_enum_util.py b/scripts/generate_enum_util.py index 7c83fc43ef7..4c35b4b0794 100644 --- a/scripts/generate_enum_util.py +++ b/scripts/generate_enum_util.py @@ -31,7 +31,12 @@ "NULLS_FIRST": ["NULLS_FIRST", "NULLS FIRST"], "NULLS_LAST": ["NULLS_LAST", "NULLS LAST"], }, - "SampleMethod": {"SYSTEM_SAMPLE": "System", "BERNOULLI_SAMPLE": "Bernoulli", "RESERVOIR_SAMPLE": "Reservoir", "CHUNK_SAMPLE": "Chunk"}, + "SampleMethod": { + "SYSTEM_SAMPLE": "System", + "BERNOULLI_SAMPLE": "Bernoulli", + "RESERVOIR_SAMPLE": "Reservoir", + "CHUNK_SAMPLE": "Chunk", + }, "TableReferenceType": {"EMPTY_FROM": "EMPTY"}, } diff --git a/src/include/duckdb/parser/parsed_data/sample_options.hpp b/src/include/duckdb/parser/parsed_data/sample_options.hpp index e395fb8be42..95b5b6729da 100644 --- a/src/include/duckdb/parser/parsed_data/sample_options.hpp +++ b/src/include/duckdb/parser/parsed_data/sample_options.hpp @@ -15,7 +15,7 @@ namespace duckdb { -enum class SampleMethod : uint8_t { SYSTEM_SAMPLE = 0, BERNOULLI_SAMPLE = 1, RESERVOIR_SAMPLE = 2, CHUNK_SAMPLE = 3}; +enum class SampleMethod : uint8_t { SYSTEM_SAMPLE = 0, BERNOULLI_SAMPLE = 1, RESERVOIR_SAMPLE = 2, CHUNK_SAMPLE = 3 }; // **DEPRECATED**: Use EnumUtil directly instead. string SampleMethodToString(SampleMethod method); diff --git a/src/parallel/pipeline_executor.cpp b/src/parallel/pipeline_executor.cpp index 4580f49417a..ba89449b06f 100644 --- a/src/parallel/pipeline_executor.cpp +++ b/src/parallel/pipeline_executor.cpp @@ -464,9 +464,9 @@ SourceResultType PipelineExecutor::GetData(DataChunk &chunk, OperatorSourceInput } #endif if (pipeline.operators.size() > 0) { - auto& op = pipeline.operators[0].get(); + auto &op = pipeline.operators[0].get(); if (op.type == PhysicalStreamingSample::TYPE) { - auto& cast_op = op.Cast(); + auto &cast_op = op.Cast(); if (cast_op.method == SampleMethod::CHUNK_SAMPLE) { chunk.chunk_sample_op.do_chunk_sample = true; chunk.chunk_sample_op.percentage = cast_op.percentage; diff --git a/src/storage/table/scan_state.cpp b/src/storage/table/scan_state.cpp index addb19483ef..baa4c310e0c 100644 --- a/src/storage/table/scan_state.cpp +++ b/src/storage/table/scan_state.cpp @@ -76,8 +76,8 @@ ParallelCollectionScanState::ParallelCollectionScanState() } CollectionScanState::CollectionScanState(TableScanState &parent_p) - : row_group(nullptr), vector_index(0), max_row_group_row(0), row_groups(nullptr), max_row(0), batch_index(0), random(-1), - parent(parent_p) { + : row_group(nullptr), vector_index(0), max_row_group_row(0), row_groups(nullptr), max_row(0), batch_index(0), + random(-1), parent(parent_p) { } bool CollectionScanState::Scan(DuckTransaction &transaction, DataChunk &result) { From 2684b801894832e53cec6bb461402a51ca5933bc Mon Sep 17 00:00:00 2001 From: continue revolution Date: Sat, 22 Jun 2024 22:06:09 +0800 Subject: [PATCH 06/89] conflict (#2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Run formatter also on src/include/duckdb/core_functions/... * fix numpy issues with the 'string' dtype changes * Use numeric_limits * Format fix * Fix duckdb/duckdb#12467 changes to stddev calculation * Format fix * Update min/max to cache allocations and prevent unnecessary re-allocation * missed some constants in FixedSizeBuffer * first step ci run for android * baby steps * typo * explicit platform * extension static build * more env and ninja * add arm64 * wrong flag * extensions, fingers crossed * container * using default containers * removing it in more places * patch vss * port changes of 'python_datetime_and_deltatime_missing_stride' from 'feature' to 'main' * Switch arg_min/arg_max to use sort key instead of vectors * Clean up unused functions * AddStringOrBlob * Skip only built-in optimizers * Add support for arg_min(ANY, ANY) * revert extension patch with optional_idx * Correct count * Format fix * Format fix * Switch fallback implementation of FIRST to use sort keys instead of vectors * WIP - clean up histogram function, avoid using ListVector::Push * Move many tests to slow * Add support for all types to the histogram function * dont WaitOnTask if there are no tasks available * Rework list_distinct/list_unique to support arbitrary types and to no longer use values and ListVector::Push * Format fix * fix compilation * Avoid overriding types in PrepareTypeForCast when not required * Use string_t and the arena allocator to allocate strings in the histogram function, instead of std::string * this is soooo much better * forgot to add new file * apply feedback * prevent the undefined behaviour of std::tolower() by casting the input to uint_8 * Binned histograms WIP * format * fix up test * More tests * Format fix + use string_map_t here * Detect duplicate bounds, sort bounds, and allow empty bounds * Binned histograms working for all types * Add binned histogram test to test all types * Unify/clean up histogram and binned histogram * RequiresExtract * Add TPC-H tests * Improve error message * Format * Add equi-width binning method for integers * More clean-up and testing, add support for doubles * lets start with this * Update .github/workflows/Android.yml Co-authored-by: Carlo Piovesan * add missing headers * Make equi-width-bins always return the input type * treat NOTHING different from REPLACE/UPDATE, the filtered tuples should not be added to the returning chunk * format * nits, use ExtensionHelper to check for spatial extension * np.NaN -> np.nan * remove pyarrow version lock * cxxheaderparser * commit generated code * add reqs * Update CodeQuality.yml * name capi enums * rewrite verify_enum_integrity.py to use cxxheaderparser * fix dependency installation * Add equi-width binning support for dates/timestamps * update messages * remove dead code * format * Make typeof a constant function (removing its argument) so that the optimizer can optimize branches away * Format * Binning test * Revert "Make typeof a constant function (removing its argument) so that the optimizer can optimize branches away" This reverts commit 4455c462d1834138a0fad3a8c40e74e9b919de4c. * Fix test * Remove duplicate test * Re-generate functions * Use / * Add bind_expression function, and make typeof return a constant expression when possible * Set function pointer * Add function can_cast_implicitly that, given a source and target type, states whether or not the source can be implicitly cast to the target * This is optimized away * This is moved * change np.NaN -> np.nan * Fixes for equi_width_bins with timestamps - cap bins at bin_count, propagate fractional months/days downwards (i.e. 0.2 months becomes 6 days) and handle bin_count > time_diff in micros * Add histogram and histogram_values table macros + infrastructure for creating default table macros * Feature #1272: Window Executor State PR feedback. * More testing for histogram function * Allow min as boundary (when there are few values this might occur) * Format * Add missing include * Fix tests * Move mode function to owning string map * Format fix * Use correct map type in list aggregate for histogram * Make mode work for all types by using sort keys * Remove N from this test as there is a duplicate * "benchmark/micro/*" >> "benchmark/micro/*.benchmark" * add copy_to_select hook, rework unsupported types in copy_to and export * optimize * remove unused variable * Modify test to be deterministic * pass along options to select * nit * allow ducktyping of lists/dicts * add enum for copy to info * move type visit functions into TypeVisitor helper * When dropping a table - clear the local storage of any appended data to that table * Add include * Set flags again in test * Also call OnDropEntry for CREATE OR REPLACE * Add HTTP error code to extension install failures * Issue #12600: Streaming Positive LAG Use buffering to support streaming computation of constant positive LAGs and negative LEADs that are at most one vector away. This doesn't fix the "look ahead" problem, but the benchmark shows it is about 5x faster than the non-streaming version. * Issue #12600: Streaming Positive LAG Add new benchmark. * Feature #1272: Window Group Preparation Move the construction of the row data collections and masks to the Finalize phase. These are relatively fast and will use data that is still hot (e.g., the sort keys). This will make it easier parallelise the remaining two passes over the data (build and execute). * Feature #1272: Window Group Preparation Code cleanup and cast fixes. * Turn window_start and window_end into idx_t * Initialize payload collection DataChunk with payload_count to prevent resizing * Format * VectorOperations::Copy - fast path when copying an aligned flat validity mask into a flat vector * Set is_dropped flag instead of actually dropping data, as other scans might be depending on the local storage (in particular when running CREATE OR REPLACE tbl AS SELECT * FROM tbl) * Add missing include * Create sort key helper class and use it in min/max * Simplify histogram combine * StateCombine for binned histogram * Rework mode to also use sort key helpers * Remove specialized decimal implementation of minmax * Disable android CI on pushes/PRs * Quantile clean-up part 1: move bind data and sort tree to separate files * Move quantile window state into separate struct * Move MAD and quantile states/operations to separate files * Rework median - allow median(ANY) instead of having different function overloads * Avoid usage of std::string in quantiles, and switch to arena allocated strings as well * Add fallback option to discrete quantile * Issue #12600: Streaming Positive LAG Incorporate various PR feedback improvements: * Cached Executors * Validity Mask reset * Small Buffers Along with the mask copy improvement in VectorOperations::Copy these reduce the benchmark runtime by another 3x. * quantile_disc scalar and lists working for arbitrary types * Remove pre-allocation for now * Feature 1272: Window Payload Preallocation Only preallocate payloads for the value window functions (LEAD, LAG, FIRST, LAST, VALUE) instad of all of them. * Quantile binding clean-up, add test_all_types for quantile_disc and median * Test + CI fixes * Format * Clean up old deserialization code * Set destructor, remove some more dead code --------- Co-authored-by: Carlo Piovesan Co-authored-by: Tishj Co-authored-by: Mark Raasveldt Co-authored-by: taniabogatsch <44262898+taniabogatsch@users.noreply.github.com> Co-authored-by: Hannes Mühleisen Co-authored-by: Christina Sioula Co-authored-by: Hannes Mühleisen Co-authored-by: Richard Wesley <13156216+hawkfish@users.noreply.github.com> Co-authored-by: Max Gabrielsson Co-authored-by: Elliana May Co-authored-by: Richard Wesley Co-authored-by: Maia --- .github/ISSUE_TEMPLATE/bug_report.yml | 3 + .github/actions/build_extensions/action.yml | 19 +- .github/actions/ubuntu_18_setup/action.yml | 6 +- .github/config/bundled_extensions.cmake | 2 - .github/config/extensions.csv | 4 +- .github/config/in_tree_extensions.cmake | 2 - .github/config/out_of_tree_extensions.cmake | 47 +- .github/config/uncovered_files.csv | 2 - .../patches/extensions/arrow/shared_ptr.patch | 1134 - .../extensions/aws/0001-update-tests.patch | 53 - .../patches/extensions/aws/shared_ptr.patch | 37 - .../patches/extensions/azure/shared_ptr.patch | 400 - .../postgres_scanner/shared_ptr.patch | 241 - .../sqlite_scanner/binder_update.patch | 27 - .../substrait/pushdown_semi_anti.patch | 40 + .../extensions/substrait/shared_ptr.patch | 130 - .github/regression/micro_extended.csv | 12 + .github/workflows/Android.yml | 101 + .github/workflows/CodeQuality.yml | 9 +- .github/workflows/InvokeCI.yml | 4 +- .github/workflows/Java.yml | 366 - .github/workflows/LinuxRelease.yml | 60 +- .github/workflows/Main.yml | 4 +- .github/workflows/NightlyTests.yml | 181 +- .github/workflows/OnTag.yml | 4 +- .github/workflows/Pyodide.yml | 51 +- .github/workflows/Python.yml | 3 +- .github/workflows/Regression.yml | 9 +- .github/workflows/StagedUpload.yml | 4 + .github/workflows/Windows.yml | 5 + .github/workflows/_extension_deploy.yml | 122 - .github/workflows/_extension_distribution.yml | 396 - .github/workflows/coverity.yml | 2 - .github/workflows/lcov_exclude | 1 - .sanitizer-thread-suppressions.txt | 10 +- CMakeLists.txt | 223 +- CONTRIBUTING.md | 5 +- Makefile | 28 +- README.md | 16 +- benchmark/benchmark_runner.cpp | 13 +- benchmark/include/benchmark.hpp | 6 +- benchmark/include/benchmark_configuration.hpp | 6 + benchmark/include/interpreted_benchmark.hpp | 1 + benchmark/interpreted_benchmark.cpp | 18 +- .../micro/aggregate/any_value_uuid.benchmark | 13 + .../aggregate/quantile/quantile.benchmark | 1 - benchmark/micro/append_mix.cpp | 2 +- .../cte/stacked_materialized_cte.benchmark | 71 + benchmark/micro/date/extract_month.benchmark | 2 +- benchmark/micro/date/extract_year.benchmark | 2 +- .../distinct/distinct_on_pushdown.benchmark | 21 + .../micro/filter/in_conversion.benchmark | 18 + .../micro/join/hashjoin_dups_rhs.benchmark | 16 + benchmark/micro/list/list_min_max.benchmark | 16 + benchmark/micro/list/list_order_by.benchmark | 2 +- benchmark/micro/list/list_value.benchmark | 16 + .../optimizer/topn_optimization.benchmark | 14 + .../window_partition_pushdown.benchmark | 20 + .../batched_stream_query.benchmark | 17 + .../micro/update/update_with_join.benchmark | 27 + .../micro/window/streaming_lag.benchmark | 27 + data/csv/date_specificity.csv | 3 + data/csv/file_error.csv | 4 + data/csv/glob/f_1.csv | 4 + data/csv/glob/f_2.csv | 3 + data/csv/glob/f_3.csv | 4 + data/csv/headers/escaped_quote.csv | 3 + data/csv/headers/unescaped_quote.csv | 3 + data/csv/rejects/dr_who.csv | 2 + data/csv/special_date.csv | 4 + data/csv/test_default_option.csv | 20481 +++++++ data/csv/test_default_option_2.csv | 20481 +++++++ data/csv/test_ignore_errors.csv | 2 + data/csv/timestamp.csv | 2 + data/csv/union-by-name/type_mismatch/f_1.csv | 4 + data/csv/union-by-name/type_mismatch/f_2.csv | 3 + data/csv/weather.csv | 367 + data/json/12188.ndjson | 2 + data/json/map_50_50.jsonl | 14 + data/json/map_incompatible.jsonl | 14 + data/json/map_of_dates.jsonl | 29 + data/json/map_of_map.jsonl | 52 + data/json/map_of_mixed_date_timestamps.jsonl | 29 + data/json/map_of_nulls.jsonl | 100 + data/json/map_of_struct_with_nulls.jsonl | 34 + data/json/map_of_structs.jsonl | 100 + data/json/simple_map.jsonl | 100 + data/json/top_level_map.jsonl | 100 + .../parquet-testing/parquet_with_json.parquet | Bin 0 -> 428 bytes data/parquet-testing/timetz-nanos.parquet | Bin 0 -> 1004 bytes data/storage/bc_0102.db.gz | Bin 0 -> 654 bytes data/storage/german_collation.db.gz | Bin 0 -> 1020 bytes data/storage/huggingface_index.db.gz | Bin 0 -> 53218 bytes examples/embedded-c++/CMakeLists.txt | 2 +- examples/embedded-c/CMakeLists.txt | 2 +- examples/jdbc/.gitignore | 2 - examples/jdbc/DuckDBExample.java | 47 - examples/jdbc/Makefile | 17 - examples/jdbc/pom.xml | 23 - examples/python/duckdb-python.py | 6 +- examples/standalone-window/CMakeLists.txt | 2 +- extension/README.md | 1 + extension/autocomplete/CMakeLists.txt | 2 +- .../autocomplete/autocomplete_extension.cpp | 8 + .../include/autocomplete_extension.hpp | 1 + extension/delta/CMakeLists.txt | 131 + extension/delta/Makefile | 25 + extension/delta/README.md | 71 + extension/delta/extension_config.cmake | 14 + extension/delta/src/delta_extension.cpp | 43 + extension/delta/src/delta_functions.cpp | 17 + extension/delta/src/delta_utils.cpp | 322 + extension/delta/src/functions/delta_scan.cpp | 628 + .../delta/src/include/delta_extension.hpp | 13 + .../delta/src/include/delta_functions.hpp | 22 + extension/delta/src/include/delta_utils.hpp | 155 + .../src/include/functions/delta_scan.hpp | 146 + extension/delta/vcpkg.json | 5 + extension/excel/CMakeLists.txt | 18 - extension/excel/excel_config.py | 16 - extension/excel/excel_extension.cpp | 93 - extension/excel/numformat/CMakeLists.txt | 9 - extension/excel/numformat/LICENSE | 118 - .../excel/numformat/include/nf_calendar.h | 842 - .../excel/numformat/include/nf_localedata.h | 220 - .../excel/numformat/include/nf_zformat.h | 1008 - extension/excel/numformat/nf_calendar.cpp | 1326 - extension/excel/numformat/nf_localedata.cpp | 186 - extension/excel/numformat/nf_zformat.cpp | 8712 --- extension/fts/CMakeLists.txt | 2 +- extension/fts/fts_extension.cpp | 8 + extension/fts/fts_indexing.cpp | 2 +- extension/fts/include/fts_extension.hpp | 1 + extension/httpfs/CMakeLists.txt | 13 +- extension/httpfs/create_secret_functions.cpp | 116 + extension/httpfs/hffs.cpp | 418 + extension/httpfs/httpfs.cpp | 73 +- extension/httpfs/httpfs_config.py | 9 +- extension/httpfs/httpfs_extension.cpp | 15 + .../include/create_secret_functions.hpp | 19 + extension/httpfs/include/hffs.hpp | 71 + extension/httpfs/include/httpfs.hpp | 21 +- extension/httpfs/include/httpfs_extension.hpp | 1 + extension/httpfs/include/s3fs.hpp | 2 +- extension/httpfs/s3fs.cpp | 24 +- extension/icu/CMakeLists.txt | 2 +- extension/icu/icu-strptime.cpp | 12 +- extension/icu/icu-table-range.cpp | 165 +- extension/icu/icu_extension.cpp | 114 +- extension/icu/include/icu_extension.hpp | 1 + .../icu/third_party/icu/i18n/basictz.cpp | 10 +- extension/inet/CMakeLists.txt | 2 +- extension/inet/include/inet_extension.hpp | 1 + extension/inet/inet_extension.cpp | 8 + extension/jemalloc/CMakeLists.txt | 2 +- .../jemalloc/include/jemalloc_extension.hpp | 4 + extension/jemalloc/jemalloc/CMakeLists.txt | 141 +- extension/jemalloc/jemalloc/README.md | 133 + .../jemalloc/internal/activity_callback.h | 4 +- .../include/jemalloc/internal/arena_externs.h | 30 +- .../jemalloc/internal/arena_inlines_a.h | 5 +- .../jemalloc/internal/arena_inlines_b.h | 219 +- .../include/jemalloc/internal/arena_stats.h | 7 +- .../include/jemalloc/internal/arena_structs.h | 15 +- .../include/jemalloc/internal/arena_types.h | 8 +- .../include/jemalloc/internal/assert.h | 16 +- .../include/jemalloc/internal/atomic.h | 8 +- .../include/jemalloc/internal/atomic_c11.h | 5 +- .../jemalloc/internal/atomic_gcc_atomic.h | 9 +- .../jemalloc/internal/atomic_gcc_sync.h | 6 +- .../include/jemalloc/internal/atomic_msvc.h | 6 +- .../internal/background_thread_externs.h | 7 +- .../internal/background_thread_inlines.h | 7 +- .../internal/background_thread_structs.h | 5 +- .../jemalloc/include/jemalloc/internal/base.h | 18 +- .../jemalloc/include/jemalloc/internal/bin.h | 7 +- .../include/jemalloc/internal/bin_info.h | 6 +- .../include/jemalloc/internal/bin_stats.h | 6 +- .../include/jemalloc/internal/bin_types.h | 5 +- .../include/jemalloc/internal/bit_util.h | 8 +- .../include/jemalloc/internal/bitmap.h | 7 +- .../include/jemalloc/internal/buf_writer.h | 6 +- .../include/jemalloc/internal/cache_bin.h | 283 +- .../jemalloc/include/jemalloc/internal/ckh.h | 5 +- .../include/jemalloc/internal/counter.h | 6 +- .../jemalloc/include/jemalloc/internal/ctl.h | 21 +- .../include/jemalloc/internal/decay.h | 6 +- .../jemalloc/include/jemalloc/internal/div.h | 5 +- .../include/jemalloc/internal/ecache.h | 7 +- .../include/jemalloc/internal/edata.h | 59 +- .../include/jemalloc/internal/edata_cache.h | 5 +- .../include/jemalloc/internal/ehooks.h | 9 +- .../jemalloc/include/jemalloc/internal/emap.h | 5 +- .../include/jemalloc/internal/emitter.h | 16 +- .../jemalloc/include/jemalloc/internal/eset.h | 7 +- .../include/jemalloc/internal/exp_grow.h | 6 +- .../include/jemalloc/internal/extent.h | 8 +- .../include/jemalloc/internal/extent_dss.h | 8 +- .../include/jemalloc/internal/extent_mmap.h | 4 +- .../jemalloc/include/jemalloc/internal/fb.h | 6 +- .../jemalloc/include/jemalloc/internal/fxp.h | 5 +- .../jemalloc/include/jemalloc/internal/hash.h | 5 +- .../jemalloc/include/jemalloc/internal/hook.h | 10 +- .../jemalloc/include/jemalloc/internal/hpa.h | 16 +- .../include/jemalloc/internal/hpa_hooks.h | 7 +- .../include/jemalloc/internal/hpa_opts.h | 5 +- .../include/jemalloc/internal/hpdata.h | 13 +- .../include/jemalloc/internal/inspect.h | 5 +- .../internal/jemalloc_internal_decls.h | 38 +- .../internal/jemalloc_internal_defs.h | 137 +- .../internal/jemalloc_internal_externs.h | 22 +- .../internal/jemalloc_internal_includes.h | 9 +- ..._inl_a.h => jemalloc_internal_inlines_a.h} | 17 +- ..._inl_b.h => jemalloc_internal_inlines_b.h} | 8 +- ..._inl_c.h => jemalloc_internal_inlines_c.h} | 293 +- .../internal/jemalloc_internal_macros.h | 22 +- .../internal/jemalloc_internal_overrides.h | 21 + .../internal/jemalloc_internal_types.h | 38 +- .../jemalloc/internal/jemalloc_preamble.h | 27 +- .../include/jemalloc/internal/large_externs.h | 6 +- .../include/jemalloc/internal/lockedint.h | 7 +- .../jemalloc/include/jemalloc/internal/log.h | 12 +- .../include/jemalloc/internal/malloc_io.h | 98 +- .../include/jemalloc/internal/mpsc_queue.h | 5 +- .../include/jemalloc/internal/mutex.h | 31 +- .../include/jemalloc/internal/mutex_prof.h | 5 +- .../include/jemalloc/internal/nstime.h | 7 +- .../jemalloc/include/jemalloc/internal/pa.h | 11 +- .../jemalloc/include/jemalloc/internal/pac.h | 9 +- .../include/jemalloc/internal/pages.h | 14 +- .../jemalloc/include/jemalloc/internal/pai.h | 18 +- .../jemalloc/include/jemalloc/internal/peak.h | 4 +- .../include/jemalloc/internal/peak_event.h | 5 +- .../jemalloc/include/jemalloc/internal/ph.h | 264 +- .../jemalloc/internal/private_namespace.gen.h | 726 + .../jemalloc/internal/private_namespace.h | 764 + .../jemalloc/include/jemalloc/internal/prng.h | 5 +- .../include/jemalloc/internal/prof_data.h | 8 +- .../include/jemalloc/internal/prof_externs.h | 23 +- .../include/jemalloc/internal/prof_hook.h | 8 +- .../include/jemalloc/internal/prof_inlines.h | 87 +- .../include/jemalloc/internal/prof_log.h | 5 +- .../include/jemalloc/internal/prof_recent.h | 10 +- .../include/jemalloc/internal/prof_stats.h | 5 +- .../include/jemalloc/internal/prof_structs.h | 19 +- .../include/jemalloc/internal/prof_sys.h | 12 +- .../include/jemalloc/internal/prof_types.h | 25 +- .../include/jemalloc/internal/psset.h | 5 +- .../jemalloc/internal/public_namespace.h | 6 +- .../jemalloc/internal/public_unnamespace.h | 6 +- .../jemalloc/include/jemalloc/internal/ql.h | 5 +- .../jemalloc/include/jemalloc/internal/qr.h | 4 - .../include/jemalloc/internal/quantum.h | 2 +- .../jemalloc/include/jemalloc/internal/rb.h | 23 +- .../include/jemalloc/internal/rtree.h | 17 +- .../include/jemalloc/internal/rtree_tsd.h | 4 +- .../include/jemalloc/internal/safety_check.h | 44 +- .../jemalloc/include/jemalloc/internal/san.h | 12 +- .../include/jemalloc/internal/san_bump.h | 8 +- .../jemalloc/include/jemalloc/internal/sc.h | 73 +- .../jemalloc/include/jemalloc/internal/sec.h | 8 +- .../include/jemalloc/internal/sec_opts.h | 3 +- .../jemalloc/include/jemalloc/internal/seq.h | 5 +- .../include/jemalloc/internal/slab_data.h | 5 +- .../include/jemalloc/internal/smoothstep.h | 4 - .../jemalloc/include/jemalloc/internal/spin.h | 6 +- .../include/jemalloc/internal/stats.h | 6 +- .../jemalloc/include/jemalloc/internal/sz.h | 21 +- .../jemalloc/internal/tcache_externs.h | 47 +- .../jemalloc/internal/tcache_inlines.h | 116 +- .../jemalloc/internal/tcache_structs.h | 9 +- .../include/jemalloc/internal/tcache_types.h | 20 +- .../include/jemalloc/internal/test_hooks.h | 7 +- .../include/jemalloc/internal/thread_event.h | 5 +- .../include/jemalloc/internal/ticker.h | 38 +- .../jemalloc/include/jemalloc/internal/tsd.h | 305 +- .../include/jemalloc/internal/tsd_generic.h | 15 +- .../include/jemalloc/internal/tsd_internals.h | 304 + .../internal/tsd_malloc_thread_cleanup.h | 6 +- .../include/jemalloc/internal/tsd_tls.h | 8 +- .../include/jemalloc/internal/tsd_types.h | 6 +- .../include/jemalloc/internal/tsd_win.h | 12 +- .../include/jemalloc/internal/typed_list.h | 4 - .../jemalloc/include/jemalloc/internal/util.h | 41 +- .../include/jemalloc/internal/witness.h | 9 +- .../jemalloc/include/jemalloc/jemalloc.h | 566 +- .../jemalloc/include/jemalloc/jemalloc_defs.h | 9 +- .../include/jemalloc/jemalloc_macros.h | 43 +- .../include/jemalloc/jemalloc_mangle.h | 9 +- .../include/jemalloc/jemalloc_mangle_jet.h | 9 +- .../include/jemalloc/jemalloc_protos.h | 11 +- .../include/jemalloc/jemalloc_protos_jet.h | 11 +- .../include/jemalloc/jemalloc_rename.h | 52 +- .../include/jemalloc/jemalloc_typedefs.h | 16 +- .../include/msvc_compat/C99/stdbool.h | 20 + .../jemalloc/include/msvc_compat/C99/stdint.h | 247 + .../jemalloc/include/msvc_compat/strings.h | 4 - .../include/msvc_compat/windows_extra.h | 6 +- .../jemalloc/src/{arena.cpp => arena.c} | 437 +- ...kground_thread.cpp => background_thread.c} | 119 +- .../jemalloc/src/{base.cpp => base.c} | 200 +- .../jemalloc/jemalloc/src/{bin.cpp => bin.c} | 4 - .../jemalloc/src/{bin_info.cpp => bin_info.c} | 4 - .../jemalloc/src/{bitmap.cpp => bitmap.c} | 4 - .../src/{buf_writer.cpp => buf_writer.c} | 6 +- .../src/{cache_bin.cpp => cache_bin.c} | 60 +- .../jemalloc/jemalloc/src/{ckh.cpp => ckh.c} | 7 +- .../jemalloc/src/{counter.cpp => counter.c} | 4 - .../jemalloc/jemalloc/src/{ctl.cpp => ctl.c} | 433 +- .../jemalloc/src/{decay.cpp => decay.c} | 7 +- .../jemalloc/jemalloc/src/{div.cpp => div.c} | 5 - .../jemalloc/src/{ecache.cpp => ecache.c} | 4 - .../jemalloc/src/{edata.cpp => edata.c} | 4 - .../src/{edata_cache.cpp => edata_cache.c} | 4 - .../jemalloc/src/{ehooks.cpp => ehooks.c} | 14 +- .../jemalloc/src/{emap.cpp => emap.c} | 6 +- .../jemalloc/src/{eset.cpp => eset.c} | 4 - .../jemalloc/src/{exp_grow.cpp => exp_grow.c} | 4 - .../jemalloc/src/{extent.cpp => extent.c} | 52 +- .../src/{extent_dss.cpp => extent_dss.c} | 27 +- .../src/{extent_mmap.cpp => extent_mmap.c} | 4 - .../jemalloc/jemalloc/src/{fxp.cpp => fxp.c} | 8 +- .../jemalloc/src/{hook.cpp => hook.c} | 9 +- .../jemalloc/jemalloc/src/{hpa.cpp => hpa.c} | 47 +- .../src/{hpa_hooks.cpp => hpa_hooks.c} | 6 +- .../jemalloc/src/{hpdata.cpp => hpdata.c} | 8 +- .../jemalloc/src/{inspect.cpp => inspect.c} | 5 +- .../jemalloc/src/{jemalloc.cpp => jemalloc.c} | 799 +- .../jemalloc/jemalloc/src/jemalloc_cpp.cpp | 308 + .../jemalloc/src/{large.cpp => large.c} | 14 +- .../jemalloc/jemalloc/src/{log.cpp => log.c} | 4 - .../src/{malloc_io.cpp => malloc_io.c} | 36 +- .../jemalloc/src/{mutex.cpp => mutex.c} | 11 +- .../jemalloc/src/{nstime.cpp => nstime.c} | 6 +- .../jemalloc/jemalloc/src/{pa.cpp => pa.c} | 17 +- .../jemalloc/src/{pa_extra.cpp => pa_extra.c} | 33 +- .../jemalloc/jemalloc/src/{pac.cpp => pac.c} | 13 +- .../jemalloc/src/{pages.cpp => pages.c} | 59 +- .../jemalloc/jemalloc/src/{pai.cpp => pai.c} | 11 +- .../src/{peak_event.cpp => peak_event.c} | 4 - .../jemalloc/src/{prof.cpp => prof.c} | 106 +- .../src/{prof_data.cpp => prof_data.c} | 110 +- .../jemalloc/src/{prof_log.cpp => prof_log.c} | 42 +- .../src/{prof_recent.cpp => prof_recent.c} | 26 +- .../src/{prof_stats.cpp => prof_stats.c} | 4 - .../jemalloc/src/{prof_sys.cpp => prof_sys.c} | 339 +- .../jemalloc/src/{psset.cpp => psset.c} | 51 +- .../jemalloc/src/{rtree.cpp => rtree.c} | 16 +- .../src/{safety_check.cpp => safety_check.c} | 38 +- .../jemalloc/jemalloc/src/{san.cpp => san.c} | 42 +- .../jemalloc/src/{san_bump.cpp => san_bump.c} | 7 +- .../jemalloc/jemalloc/src/{sc.cpp => sc.c} | 4 - .../jemalloc/jemalloc/src/{sec.cpp => sec.c} | 11 +- .../jemalloc/src/{stats.cpp => stats.c} | 118 +- .../jemalloc/jemalloc/src/{sz.cpp => sz.c} | 7 +- .../jemalloc/src/{tcache.cpp => tcache.c} | 631 +- .../src/{test_hooks.cpp => test_hooks.c} | 12 +- .../src/{thread_event.cpp => thread_event.c} | 4 - .../jemalloc/src/{ticker.cpp => ticker.c} | 4 - .../jemalloc/jemalloc/src/{tsd.cpp => tsd.c} | 37 +- extension/jemalloc/jemalloc/src/util.c | 49 + .../jemalloc/src/{witness.cpp => witness.c} | 12 +- extension/jemalloc/jemalloc/src/zone.c | 469 + extension/jemalloc/jemalloc_config.py | 126 +- extension/jemalloc/jemalloc_extension.cpp | 48 +- extension/json/CMakeLists.txt | 7 +- extension/json/include/json.json | 6 + extension/json/include/json_common.hpp | 7 +- extension/json/include/json_executors.hpp | 10 +- extension/json/include/json_extension.hpp | 1 + extension/json/include/json_functions.hpp | 4 +- extension/json/include/json_scan.hpp | 5 +- extension/json/include/json_serializer.hpp | 4 +- extension/json/include/json_structure.hpp | 5 +- extension/json/json_common.cpp | 112 +- extension/json/json_config.py | 5 +- extension/json/json_extension.cpp | 8 + extension/json/json_functions.cpp | 7 +- extension/json/json_functions/copy_json.cpp | 30 +- extension/json/json_functions/json_create.cpp | 6 +- .../json/json_functions/json_structure.cpp | 276 +- .../json/json_functions/json_transform.cpp | 6 +- extension/json/json_functions/json_type.cpp | 4 +- extension/json/json_functions/read_json.cpp | 23 +- .../json/json_functions/read_json_objects.cpp | 8 +- extension/json/json_scan.cpp | 32 +- extension/json/serialize_json.cpp | 2 + extension/json/yyjson/CMakeLists.txt | 8 - extension/parquet/CMakeLists.txt | 41 +- extension/parquet/column_reader.cpp | 194 +- extension/parquet/column_writer.cpp | 196 +- extension/parquet/geo_parquet.cpp | 384 + .../parquet/include/boolean_column_reader.hpp | 21 +- extension/parquet/include/column_reader.hpp | 49 +- extension/parquet/include/column_writer.hpp | 22 +- .../include/expression_column_reader.hpp | 52 + extension/parquet/include/geo_parquet.hpp | 138 + extension/parquet/include/parquet.json | 4 +- .../parquet/include/parquet_extension.hpp | 1 + .../include/parquet_file_metadata_cache.hpp | 10 +- extension/parquet/include/parquet_reader.hpp | 10 +- .../include/parquet_rle_bp_decoder.hpp | 6 +- .../include/parquet_rle_bp_encoder.hpp | 2 +- .../parquet/include/parquet_timestamp.hpp | 8 + extension/parquet/include/parquet_writer.hpp | 23 +- .../parquet/include/resizable_buffer.hpp | 44 +- .../parquet/include/string_column_reader.hpp | 7 +- .../include/templated_column_reader.hpp | 66 +- extension/parquet/parquet_config.py | 43 + extension/parquet/parquet_crypto.cpp | 32 +- extension/parquet/parquet_extension.cpp | 525 +- extension/parquet/parquet_metadata.cpp | 76 +- extension/parquet/parquet_reader.cpp | 81 +- extension/parquet/parquet_statistics.cpp | 41 +- extension/parquet/parquet_timestamp.cpp | 43 +- extension/parquet/parquet_writer.cpp | 152 +- extension/parquet/serialize_parquet.cpp | 4 +- extension/sqlsmith/CMakeLists.txt | 21 - extension/sqlsmith/fuzzyduck.cpp | 161 - extension/sqlsmith/include/fuzzyduck.hpp | 54 - .../sqlsmith/include/statement_generator.hpp | 148 - .../sqlsmith/include/statement_simplifier.hpp | 89 - extension/sqlsmith/sqlsmith_extension.cpp | 223 - extension/sqlsmith/statement_generator.cpp | 1261 - extension/sqlsmith/statement_simplifier.cpp | 453 - extension/sqlsmith/third_party/CMakeLists.txt | 5 - .../third_party/sqlsmith/CMakeLists.txt | 20 - .../sqlsmith/third_party/sqlsmith/duckdb.cc | 177 - .../sqlsmith/third_party/sqlsmith/dump.cc | 60 - .../sqlsmith/third_party/sqlsmith/expr.cc | 352 - .../sqlsmith/third_party/sqlsmith/grammar.cc | 618 - .../third_party/sqlsmith/impedance.cc | 88 - .../third_party/sqlsmith/include/duckdb.hh | 33 - .../third_party/sqlsmith/include/dump.hh | 27 - .../third_party/sqlsmith/include/dut.hh | 47 - .../third_party/sqlsmith/include/expr.hh | 208 - .../third_party/sqlsmith/include/grammar.hh | 367 - .../third_party/sqlsmith/include/impedance.hh | 62 - .../third_party/sqlsmith/include/log.hh | 55 - .../third_party/sqlsmith/include/prod.hh | 59 - .../third_party/sqlsmith/include/random.hh | 45 - .../third_party/sqlsmith/include/relmodel.hh | 163 - .../third_party/sqlsmith/include/schema.hh | 84 - .../third_party/sqlsmith/include/sqlsmith.hh | 27 - .../third_party/sqlsmith/include/util.hh | 25 - .../sqlsmith/third_party/sqlsmith/log.cc | 107 - .../sqlsmith/third_party/sqlsmith/prod.cc | 41 - .../sqlsmith/third_party/sqlsmith/random.cc | 35 - .../sqlsmith/third_party/sqlsmith/relmodel.cc | 23 - .../sqlsmith/third_party/sqlsmith/schema.cc | 59 - .../sqlsmith/third_party/sqlsmith/sqlsmith.cc | 202 - extension/tpcds/CMakeLists.txt | 2 +- extension/tpcds/include/tpcds_extension.hpp | 1 + extension/tpcds/tpcds_extension.cpp | 11 +- extension/tpch/CMakeLists.txt | 2 +- extension/tpch/dbgen/bm_utils.cpp | 9 +- extension/tpch/dbgen/build.cpp | 34 +- extension/tpch/dbgen/dbgen.cpp | 202 +- extension/tpch/dbgen/include/dbgen/dss.h | 14 +- extension/tpch/dbgen/permute.cpp | 19 +- extension/tpch/include/tpch_extension.hpp | 1 + extension/tpch/tpch_extension.cpp | 11 +- scripts/append_metadata.cmake | 2 +- scripts/apply_extension_patches.py | 2 +- scripts/coverage_check.sh | 4 +- scripts/exported_symbols_check.py | 1 + scripts/format.py | 23 +- scripts/generate_extensions_function.py | 32 +- scripts/generate_serialization.py | 84 +- scripts/generate_storage_info.py | 64 + scripts/jdbc_maven_deploy.py | 201 - scripts/package_build.py | 6 + scripts/plan_cost_runner.py | 16 +- scripts/reduce_sql.py | 46 +- scripts/regression_test_python.py | 177 +- scripts/run_extension_medata_tests.sh | 177 + scripts/run_fuzzer.py | 26 +- scripts/run_sqlancer.py | 2 +- scripts/run_tests_one_by_one.py | 46 +- scripts/sqllogictest/result.py | 59 +- scripts/test_block_sizes.py | 26 +- scripts/test_docker_images.sh | 26 +- scripts/test_vector_sizes.py | 20 +- scripts/verify_enum_integrity.py | 61 +- src/CMakeLists.txt | 6 +- src/catalog/CMakeLists.txt | 1 + src/catalog/catalog.cpp | 58 +- src/catalog/catalog_entry.cpp | 7 + .../catalog_entry/duck_index_entry.cpp | 12 +- .../catalog_entry/duck_schema_entry.cpp | 98 +- .../catalog_entry/duck_table_entry.cpp | 71 +- .../catalog_entry/index_catalog_entry.cpp | 3 + .../catalog_entry/macro_catalog_entry.cpp | 4 + .../catalog_entry/schema_catalog_entry.cpp | 7 + .../catalog_entry/sequence_catalog_entry.cpp | 5 +- .../catalog_entry/table_catalog_entry.cpp | 4 + .../catalog_entry/type_catalog_entry.cpp | 8 +- .../catalog_entry/view_catalog_entry.cpp | 4 + src/catalog/catalog_entry_retriever.cpp | 64 + src/catalog/catalog_set.cpp | 61 +- src/catalog/default/CMakeLists.txt | 11 +- src/catalog/default/default_functions.cpp | 22 +- src/catalog/default/default_generator.cpp | 24 + src/catalog/default/default_schemas.cpp | 7 +- .../default/default_table_functions.cpp | 137 + src/catalog/default/default_views.cpp | 2 +- src/catalog/dependency_manager.cpp | 142 +- src/catalog/duck_catalog.cpp | 5 + src/common/CMakeLists.txt | 1 + src/common/allocator.cpp | 47 +- src/common/arrow/appender/bool_data.cpp | 15 +- src/common/arrow/appender/union_data.cpp | 6 +- src/common/arrow/arrow_appender.cpp | 32 +- src/common/arrow/arrow_converter.cpp | 26 +- src/common/box_renderer.cpp | 7 +- src/common/enum_util.cpp | 458 +- src/common/enums/logical_operator_type.cpp | 2 + src/common/enums/optimizer_type.cpp | 2 + src/common/enums/physical_operator_type.cpp | 2 + src/common/enums/relation_type.cpp | 2 + src/common/enums/statement_type.cpp | 2 + src/common/error_data.cpp | 19 +- src/common/extra_type_info.cpp | 86 +- src/common/file_system.cpp | 12 +- src/common/filename_pattern.cpp | 1 + src/common/gzip_file_system.cpp | 29 +- src/common/hive_partitioning.cpp | 3 + src/common/local_file_system.cpp | 15 +- src/common/multi_file_list.cpp | 285 + src/common/multi_file_reader.cpp | 218 +- src/common/operator/cast_operators.cpp | 324 +- src/common/operator/string_cast.cpp | 52 +- src/common/printer.cpp | 2 +- src/common/row_operations/row_heap_gather.cpp | 8 +- .../row_operations/row_heap_scatter.cpp | 21 +- src/common/row_operations/row_matcher.cpp | 40 + .../row_operations/row_radix_scatter.cpp | 2 +- .../serializer/buffered_file_writer.cpp | 20 +- src/common/serializer/memory_stream.cpp | 10 +- src/common/serializer/serializer.cpp | 2 +- src/common/sort/partition_state.cpp | 30 +- src/common/sort/radix_sort.cpp | 2 +- src/common/string_util.cpp | 228 +- src/common/symbols.cpp | 2 - src/common/tree_renderer.cpp | 10 +- src/common/types.cpp | 153 +- src/common/types/blob.cpp | 17 +- src/common/types/cast_helpers.cpp | 197 + .../types/column/column_data_collection.cpp | 12 +- src/common/types/conflict_info.cpp | 2 +- src/common/types/data_chunk.cpp | 11 +- src/common/types/date.cpp | 16 - src/common/types/decimal.cpp | 16 +- src/common/types/hugeint.cpp | 8 + src/common/types/row/tuple_data_allocator.cpp | 41 +- .../types/row/tuple_data_collection.cpp | 16 +- .../types/row/tuple_data_scatter_gather.cpp | 3 +- src/common/types/row/tuple_data_segment.cpp | 7 + src/common/types/selection_vector.cpp | 15 + src/common/types/string_heap.cpp | 4 + src/common/types/time.cpp | 47 +- src/common/types/timestamp.cpp | 101 +- src/common/types/validity_mask.cpp | 28 +- src/common/types/value.cpp | 55 +- src/common/types/vector.cpp | 211 +- src/common/types/vector_buffer.cpp | 4 + src/common/vector_operations/generators.cpp | 20 +- .../vector_operations/is_distinct_from.cpp | 20 + src/common/vector_operations/vector_copy.cpp | 23 +- .../aggregate/distributive/approx_count.cpp | 191 +- .../aggregate/distributive/arg_min_max.cpp | 160 +- .../aggregate/distributive/bitagg.cpp | 8 +- .../aggregate/distributive/entropy.cpp | 5 +- .../aggregate/distributive/functions.json | 4 +- .../aggregate/distributive/minmax.cpp | 402 +- .../aggregate/holistic/CMakeLists.txt | 10 +- .../holistic/approximate_quantile.cpp | 101 +- src/core_functions/aggregate/holistic/mad.cpp | 330 + .../aggregate/holistic/mode.cpp | 233 +- .../aggregate/holistic/quantile.cpp | 2057 +- .../aggregate/holistic/reservoir_quantile.cpp | 12 +- .../aggregate/nested/CMakeLists.txt | 3 +- .../aggregate/nested/binned_histogram.cpp | 260 + .../aggregate/nested/functions.json | 2 +- .../aggregate/nested/histogram.cpp | 301 +- src/core_functions/function_list.cpp | 7 +- .../scalar/array/array_functions.cpp | 22 +- .../scalar/blob/create_sort_key.cpp | 384 +- src/core_functions/scalar/date/date_part.cpp | 118 +- src/core_functions/scalar/date/epoch.cpp | 17 + src/core_functions/scalar/date/functions.json | 23 + src/core_functions/scalar/date/strftime.cpp | 204 +- .../scalar/date/to_interval.cpp | 19 + .../scalar/debug/vector_type.cpp | 11 +- .../scalar/generic/CMakeLists.txt | 1 + .../scalar/generic/can_implicitly_cast.cpp | 40 + .../scalar/generic/current_setting.cpp | 5 +- .../scalar/generic/functions.json | 14 + src/core_functions/scalar/generic/typeof.cpp | 13 + .../scalar/list/array_slice.cpp | 25 +- .../scalar/list/list_aggregates.cpp | 126 +- src/core_functions/scalar/list/list_sort.cpp | 2 - src/core_functions/scalar/list/list_value.cpp | 115 +- src/core_functions/scalar/map/map_concat.cpp | 21 +- src/core_functions/scalar/map/map_entries.cpp | 43 +- src/core_functions/scalar/map/map_extract.cpp | 35 +- .../scalar/map/map_keys_values.cpp | 20 +- src/core_functions/scalar/string/chr.cpp | 2 +- src/core_functions/scalar/string/repeat.cpp | 22 +- src/core_functions/scalar/string/reverse.cpp | 9 +- src/execution/aggregate_hashtable.cpp | 26 +- src/execution/index/CMakeLists.txt | 10 +- src/execution/index/art/art.cpp | 199 +- src/execution/index/bound_index.cpp | 115 + src/execution/index/fixed_size_allocator.cpp | 12 +- src/execution/index/fixed_size_buffer.cpp | 4 +- src/execution/index/unbound_index.cpp | 30 + src/execution/index/unknown_index.cpp | 65 - src/execution/join_hashtable.cpp | 659 +- .../operator/aggregate/aggregate_object.cpp | 2 +- .../aggregate/physical_streaming_window.cpp | 411 +- .../operator/aggregate/physical_window.cpp | 293 +- .../buffer_manager/csv_buffer_manager.cpp | 19 +- .../csv_scanner/scanner/base_scanner.cpp | 32 +- .../scanner/column_count_scanner.cpp | 16 +- .../csv_scanner/scanner/scanner_boundary.cpp | 48 +- .../csv_scanner/scanner/skip_scanner.cpp | 17 +- .../scanner/string_value_scanner.cpp | 475 +- .../csv_scanner/sniffer/dialect_detection.cpp | 56 +- .../csv_scanner/sniffer/header_detection.cpp | 4 +- .../csv_scanner/sniffer/type_detection.cpp | 90 +- .../table_function/csv_file_scanner.cpp | 53 +- .../table_function/global_csv_state.cpp | 35 +- .../csv_scanner/util/csv_reader_options.cpp | 33 +- src/execution/operator/helper/CMakeLists.txt | 2 + .../physical_buffered_batch_collector.cpp | 109 + .../helper/physical_buffered_collector.cpp | 18 +- .../operator/helper/physical_load.cpp | 26 +- .../helper/physical_result_collector.cpp | 3 +- .../operator/helper/physical_transaction.cpp | 3 + .../helper/physical_update_extensions.cpp | 57 + .../helper/physical_verify_vector.cpp | 21 +- .../operator/join/physical_hash_join.cpp | 12 +- .../join/physical_left_delim_join.cpp | 2 +- .../physical_batch_copy_to_file.cpp | 41 +- .../persistent/physical_batch_insert.cpp | 6 +- .../persistent/physical_copy_database.cpp | 4 +- .../persistent/physical_copy_to_file.cpp | 150 +- .../operator/persistent/physical_delete.cpp | 2 +- .../operator/persistent/physical_export.cpp | 68 +- .../operator/persistent/physical_insert.cpp | 23 +- .../physical_tableinout_function.cpp | 26 +- .../operator/projection/physical_unnest.cpp | 3 + .../scan/physical_column_data_scan.cpp | 5 +- .../scan/physical_expression_scan.cpp | 29 +- .../operator/scan/physical_table_scan.cpp | 37 +- .../operator/schema/physical_attach.cpp | 82 +- .../schema/physical_create_art_index.cpp | 38 +- .../physical_plan/plan_column_data_get.cpp | 6 +- .../physical_plan/plan_copy_to_file.cpp | 11 +- .../physical_plan/plan_delim_get.cpp | 4 +- src/execution/physical_plan/plan_distinct.cpp | 1 + .../physical_plan/plan_expression_get.cpp | 9 +- src/execution/physical_plan/plan_get.cpp | 46 +- src/execution/physical_plan/plan_limit.cpp | 21 +- src/execution/physical_plan/plan_simple.cpp | 4 + src/execution/physical_plan/plan_window.cpp | 27 +- src/execution/physical_plan_generator.cpp | 3 + src/execution/radix_partitioned_hashtable.cpp | 56 +- src/execution/reservoir_sample.cpp | 73 +- src/execution/window_executor.cpp | 496 +- src/execution/window_segment_tree.cpp | 610 +- src/function/CMakeLists.txt | 1 + src/function/aggregate/distributive/first.cpp | 186 +- src/function/cast/cast_function_set.cpp | 11 +- src/function/cast/decimal_cast.cpp | 11 +- src/function/cast/string_cast.cpp | 16 +- src/function/cast/time_casts.cpp | 4 +- src/function/cast_rules.cpp | 4 + src/function/compression_config.cpp | 52 +- src/function/copy_function.cpp | 27 + src/function/function_binder.cpp | 57 +- src/function/pragma/pragma_functions.cpp | 3 +- src/function/pragma/pragma_queries.cpp | 3 +- src/function/scalar/generic/CMakeLists.txt | 3 +- src/function/scalar/generic/binning.cpp | 451 + src/function/scalar/list/CMakeLists.txt | 1 - src/function/scalar/list/list_concat.cpp | 143 - src/function/scalar/list/list_resize.cpp | 6 +- src/function/scalar/list/list_select.cpp | 6 + src/function/scalar/list/list_zip.cpp | 4 +- src/function/scalar/operators/add.cpp | 28 +- src/function/scalar/operators/arithmetic.cpp | 5 +- src/function/scalar/sequence/nextval.cpp | 125 +- src/function/scalar/strftime_format.cpp | 231 +- src/function/scalar/string/CMakeLists.txt | 1 + src/function/scalar/string/caseconvert.cpp | 16 +- src/function/scalar/string/concat.cpp | 352 +- src/function/scalar/string/concat_ws.cpp | 149 + src/function/scalar/string/substring.cpp | 17 +- src/function/scalar/string_functions.cpp | 1 + src/function/scalar_function.cpp | 6 +- src/function/table/CMakeLists.txt | 1 + src/function/table/arrow.cpp | 134 +- src/function/table/arrow/CMakeLists.txt | 2 +- .../table/arrow/arrow_duck_schema.cpp | 59 +- src/function/table/arrow/arrow_type_info.cpp | 135 + src/function/table/arrow_conversion.cpp | 212 +- src/function/table/copy_csv.cpp | 34 +- src/function/table/glob.cpp | 26 +- src/function/table/query_function.cpp | 75 + src/function/table/range.cpp | 364 +- src/function/table/read_csv.cpp | 58 +- src/function/table/read_file.cpp | 5 +- src/function/table/repeat.cpp | 6 +- src/function/table/sniff_csv.cpp | 10 +- .../table/system/duckdb_databases.cpp | 5 + .../table/system/duckdb_extensions.cpp | 59 +- .../table/system/duckdb_functions.cpp | 6 + src/function/table/system/duckdb_indexes.cpp | 5 + src/function/table/system/duckdb_schemas.cpp | 5 + .../table/system/duckdb_sequences.cpp | 5 + src/function/table/system/duckdb_tables.cpp | 5 + src/function/table/system/duckdb_types.cpp | 5 + src/function/table/system/duckdb_views.cpp | 5 + src/function/table/table_scan.cpp | 31 +- src/function/table/unnest.cpp | 5 +- src/function/table_function.cpp | 9 +- src/include/duckdb.h | 342 +- src/include/duckdb/catalog/catalog.hpp | 11 +- src/include/duckdb/catalog/catalog_entry.hpp | 4 + .../catalog_entry/duck_index_entry.hpp | 2 +- .../catalog_entry/duck_schema_entry.hpp | 7 +- .../catalog_entry/duck_table_entry.hpp | 3 +- .../catalog/catalog_entry/function_entry.hpp | 1 + .../catalog_entry/schema_catalog_entry.hpp | 5 +- .../catalog_entry/sequence_catalog_entry.hpp | 7 +- .../catalog_entry/type_catalog_entry.hpp | 2 + .../catalog/catalog_entry_retriever.hpp | 72 + .../duckdb/catalog/catalog_transaction.hpp | 3 + .../catalog/default/default_functions.hpp | 5 +- .../catalog/default/default_generator.hpp | 9 +- .../catalog/default/default_schemas.hpp | 3 +- .../default/default_table_functions.hpp | 47 + src/include/duckdb/catalog/dependency.hpp | 4 + .../duckdb/catalog/dependency_list.hpp | 8 +- .../duckdb/catalog/dependency_manager.hpp | 4 +- src/include/duckdb/catalog/standard_entry.hpp | 2 + src/include/duckdb/common/allocator.hpp | 7 + .../common/arrow/appender/append_data.hpp | 46 +- .../common/arrow/appender/enum_data.hpp | 17 +- .../duckdb/common/arrow/appender/list.hpp | 1 + .../common/arrow/appender/list_data.hpp | 10 +- .../common/arrow/appender/list_view_data.hpp | 92 + .../duckdb/common/arrow/appender/map_data.hpp | 4 +- .../common/arrow/appender/scalar_data.hpp | 24 +- .../common/arrow/appender/varchar_data.hpp | 100 +- .../duckdb/common/arrow/arrow_buffer.hpp | 2 +- src/include/duckdb/common/bswap.hpp | 34 +- src/include/duckdb/common/constants.hpp | 2 + ...is.ipp => enable_shared_from_this_ipp.hpp} | 0 src/include/duckdb/common/enum_util.hpp | 94 +- .../duckdb/common/enums/checkpoint_type.hpp | 38 + .../common/enums/copy_overwrite_mode.hpp | 15 +- src/include/duckdb/common/enums/join_type.hpp | 4 +- .../common/enums/logical_operator_type.hpp | 1 + .../duckdb/common/enums/optimizer_type.hpp | 2 + .../common/enums/physical_operator_type.hpp | 1 + .../duckdb/common/enums/relation_type.hpp | 1 + .../duckdb/common/enums/scan_options.hpp | 4 +- .../duckdb/common/enums/scan_vector_type.hpp | 10 +- .../duckdb/common/enums/statement_type.hpp | 1 + .../duckdb/common/enums/tableref_type.hpp | 3 +- .../duckdb/common/enums/undo_flags.hpp | 3 +- src/include/duckdb/common/exception.hpp | 2 +- .../duckdb/common/extra_operator_info.hpp | 12 + src/include/duckdb/common/extra_type_info.hpp | 16 +- src/include/duckdb/common/file_buffer.hpp | 2 + src/include/duckdb/common/file_opener.hpp | 4 + src/include/duckdb/common/file_system.hpp | 1 + .../duckdb/common/filename_pattern.hpp | 4 + src/include/duckdb/common/fsst.hpp | 5 + .../duckdb/common/gzip_file_system.hpp | 3 + .../duckdb/common/hive_partitioning.hpp | 5 +- .../common/insertion_order_preserving_map.hpp | 129 + src/include/duckdb/common/multi_file_list.hpp | 151 + .../duckdb/common/multi_file_reader.hpp | 185 +- .../common/multi_file_reader_options.hpp | 15 +- src/include/duckdb/common/operator/add.hpp | 2 + .../duckdb/common/operator/cast_operators.hpp | 10 +- .../operator/decimal_cast_operators.hpp | 255 + .../duckdb/common/operator/numeric_cast.hpp | 4 + .../duckdb/common/operator/string_cast.hpp | 2 + src/include/duckdb/common/optional_ptr.hpp | 5 + .../duckdb/common/optionally_owned_ptr.hpp | 91 + .../duckdb/common/owning_string_map.hpp | 155 + src/include/duckdb/common/radix.hpp | 199 +- .../common/row_operations/row_matcher.hpp | 12 + .../common/row_operations/row_operations.hpp | 2 + .../common/serializer/binary_deserializer.hpp | 3 +- .../common/serializer/binary_serializer.hpp | 14 +- .../serializer/buffered_file_writer.hpp | 8 +- .../serializer/deserialization_data.hpp | 19 + .../duckdb/common/serializer/deserializer.hpp | 36 + .../common/serializer/memory_stream.hpp | 4 +- .../serializer/serialization_traits.hpp | 54 + .../duckdb/common/serializer/serializer.hpp | 58 +- src/include/duckdb/common/shared_ptr.hpp | 6 +- .../{shared_ptr.ipp => shared_ptr_ipp.hpp} | 0 .../duckdb/common/sort/partition_state.hpp | 13 +- src/include/duckdb/common/string.hpp | 5 +- src/include/duckdb/common/string_util.hpp | 3 + src/include/duckdb/common/type_visitor.hpp | 96 + src/include/duckdb/common/types.hpp | 54 +- .../common/types/arrow_string_view_type.hpp | 84 + .../duckdb/common/types/cast_helpers.hpp | 218 +- .../duckdb/common/types/data_chunk.hpp | 2 + src/include/duckdb/common/types/date.hpp | 3 - .../duckdb/common/types/date_lookup_cache.hpp | 65 + src/include/duckdb/common/types/datetime.hpp | 43 +- .../types/row/tuple_data_collection.hpp | 2 + .../common/types/row/tuple_data_segment.hpp | 8 +- .../duckdb/common/types/selection_vector.hpp | 4 + .../duckdb/common/types/string_type.hpp | 2 + src/include/duckdb/common/types/time.hpp | 17 +- src/include/duckdb/common/types/timestamp.hpp | 18 +- .../duckdb/common/types/validity_mask.hpp | 3 + src/include/duckdb/common/types/value.hpp | 3 + src/include/duckdb/common/types/vector.hpp | 27 +- .../vector_operations/generic_executor.hpp | 29 + .../vector_operations/unary_executor.hpp | 7 - .../common/{weak_ptr.ipp => weak_ptr_ipp.hpp} | 0 .../aggregate/algebraic/covar.hpp | 12 +- .../aggregate/algebraic/stddev.hpp | 12 +- .../aggregate/distributive_functions.hpp | 4 +- .../aggregate/histogram_helpers.hpp | 99 + .../aggregate/nested_functions.hpp | 1 + .../aggregate/quantile_helpers.hpp | 65 + .../aggregate/quantile_sort_tree.hpp | 340 + .../aggregate/quantile_state.hpp | 300 + .../aggregate/regression/regr_slope.hpp | 2 +- .../aggregate/sort_key_helpers.hpp | 55 + .../duckdb/core_functions/create_sort_key.hpp | 53 + .../core_functions/scalar/date_functions.hpp | 27 + .../scalar/generic_functions.hpp | 18 + .../duckdb/execution/adaptive_filter.hpp | 1 + .../duckdb/execution/aggregate_hashtable.hpp | 50 +- src/include/duckdb/execution/executor.hpp | 7 + .../duckdb/execution/expression_executor.hpp | 2 +- src/include/duckdb/execution/ht_entry.hpp | 94 + .../duckdb/execution/index/art/art.hpp | 19 +- .../duckdb/execution/index/bound_index.hpp | 145 + .../duckdb/execution/index/index_type.hpp | 4 +- .../duckdb/execution/index/unbound_index.hpp | 63 + .../duckdb/execution/index/unknown_index.hpp | 65 - .../duckdb/execution/join_hashtable.hpp | 107 +- .../operator/aggregate/aggregate_object.hpp | 2 +- .../aggregate/physical_streaming_window.hpp | 5 + .../operator/csv_scanner/base_scanner.hpp | 24 +- .../csv_scanner/column_count_scanner.hpp | 2 +- .../csv_scanner/csv_buffer_manager.hpp | 3 +- .../operator/csv_scanner/csv_file_scanner.hpp | 5 +- .../csv_scanner/csv_reader_options.hpp | 11 +- .../operator/csv_scanner/csv_sniffer.hpp | 3 +- .../operator/csv_scanner/scanner_boundary.hpp | 15 +- .../csv_scanner/string_value_scanner.hpp | 114 +- .../physical_buffered_batch_collector.hpp | 49 + .../helper/physical_update_extensions.hpp | 52 + .../persistent/batch_memory_manager.hpp | 4 - .../physical_batch_copy_to_file.hpp | 9 +- .../persistent/physical_copy_to_file.hpp | 10 +- .../operator/persistent/physical_export.hpp | 1 + .../physical_tableinout_function.hpp | 2 + .../scan/physical_column_data_scan.hpp | 9 +- .../scan/physical_expression_scan.hpp | 8 +- .../operator/scan/physical_table_scan.hpp | 6 +- .../duckdb/execution/reservoir_sample.hpp | 71 +- .../duckdb/execution/window_executor.hpp | 169 +- .../duckdb/execution/window_segment_tree.hpp | 166 +- .../function/compression/compression.hpp | 20 +- .../duckdb/function/compression_function.hpp | 51 +- src/include/duckdb/function/copy_function.hpp | 35 +- src/include/duckdb/function/function.hpp | 5 - .../duckdb/function/function_binder.hpp | 13 +- .../duckdb/function/replacement_scan.hpp | 26 +- .../function/scalar/generic_functions.hpp | 2 + src/include/duckdb/function/scalar/regexp.hpp | 9 +- .../function/scalar/sequence_functions.hpp | 7 +- .../function/scalar/strftime_format.hpp | 33 +- .../function/scalar/string_functions.hpp | 14 +- .../duckdb/function/scalar_function.hpp | 46 + src/include/duckdb/function/table/arrow.hpp | 10 +- .../table/arrow/arrow_duck_schema.hpp | 68 +- .../function/table/arrow/arrow_type_info.hpp | 142 + .../table/arrow/enum/arrow_datetime_type.hpp | 18 + .../table/arrow/enum/arrow_type_info_type.hpp | 7 + .../arrow/enum/arrow_variable_size_type.hpp | 10 + src/include/duckdb/function/table/range.hpp | 4 + .../duckdb/function/table/read_csv.hpp | 1 + .../duckdb/function/table_function.hpp | 17 +- src/include/duckdb/logging/http_logger.hpp | 81 + src/include/duckdb/main/appender.hpp | 22 +- src/include/duckdb/main/attached_database.hpp | 38 +- .../buffered_data/batched_buffered_data.hpp | 79 + .../main/buffered_data/buffered_data.hpp | 23 +- .../buffered_data/simple_buffered_data.hpp | 17 +- .../duckdb/main/capi/capi_internal.hpp | 5 + src/include/duckdb/main/capi/cast/generic.hpp | 4 +- src/include/duckdb/main/client_config.hpp | 20 +- src/include/duckdb/main/client_context.hpp | 28 +- .../duckdb/main/client_context_state.hpp | 12 +- .../duckdb/main/client_context_wrapper.hpp | 27 + src/include/duckdb/main/client_data.hpp | 4 + src/include/duckdb/main/client_properties.hpp | 8 +- src/include/duckdb/main/config.hpp | 55 +- .../duckdb/main/connection_manager.hpp | 24 +- src/include/duckdb/main/database.hpp | 42 +- src/include/duckdb/main/database_manager.hpp | 9 +- src/include/duckdb/main/extension.hpp | 25 + src/include/duckdb/main/extension_entries.hpp | 170 +- src/include/duckdb/main/extension_helper.hpp | 91 +- .../duckdb/main/extension_install_info.hpp | 91 + src/include/duckdb/main/extension_util.hpp | 4 +- .../duckdb/main/external_dependencies.hpp | 50 +- .../duckdb/main/materialized_query_result.hpp | 3 + .../duckdb/main/pending_query_result.hpp | 2 + src/include/duckdb/main/profiling_info.hpp | 83 + src/include/duckdb/main/query_profiler.hpp | 53 +- src/include/duckdb/main/relation.hpp | 7 +- .../main/relation/materialized_relation.hpp | 35 + .../duckdb/main/relation/query_relation.hpp | 1 + src/include/duckdb/main/settings.hpp | 115 + .../duckdb/main/stream_query_result.hpp | 1 + .../optimizer/build_probe_side_optimizer.hpp | 32 + .../duckdb/optimizer/filter_pushdown.hpp | 5 + .../join_order/cardinality_estimator.hpp | 60 +- .../optimizer/join_order/cost_model.hpp | 1 + .../join_order/estimated_properties.hpp | 57 - .../duckdb/optimizer/join_order/join_node.hpp | 39 +- .../join_order/join_order_optimizer.hpp | 51 - .../optimizer/join_order/plan_enumerator.hpp | 11 +- .../optimizer/join_order/query_graph.hpp | 2 +- .../join_order/query_graph_manager.hpp | 31 +- .../optimizer/join_order/relation_manager.hpp | 2 +- .../duckdb/optimizer/limit_pushdown.hpp | 25 + src/include/duckdb/optimizer/optimizer.hpp | 1 + .../duckdb/optimizer/optimizer_extension.hpp | 12 +- .../optimizer/rule/join_dependent_filter.hpp | 37 + src/include/duckdb/optimizer/rule/list.hpp | 1 + .../optimizer/rule/timestamp_comparison.hpp | 30 + .../duckdb/parallel/task_scheduler.hpp | 4 + .../duckdb/parser/column_definition.hpp | 2 + .../parser/expression/function_expression.hpp | 3 + .../parser/expression/star_expression.hpp | 5 + .../duckdb/parser/parsed_data/alter_info.hpp | 1 + .../alter_scalar_function_info.hpp | 1 + .../parsed_data/alter_table_function_info.hpp | 1 + .../parser/parsed_data/alter_table_info.hpp | 12 + .../duckdb/parser/parsed_data/attach_info.hpp | 6 + .../parsed_data/comment_on_column_info.hpp | 4 +- .../duckdb/parser/parsed_data/copy_info.hpp | 22 +- .../duckdb/parser/parsed_data/create_info.hpp | 4 + .../parser/parsed_data/create_type_info.hpp | 13 +- .../duckdb/parser/parsed_data/detach_info.hpp | 1 + .../duckdb/parser/parsed_data/drop_info.hpp | 1 + .../duckdb/parser/parsed_data/load_info.hpp | 11 +- .../duckdb/parser/parsed_data/parse_info.hpp | 5 +- .../duckdb/parser/parsed_data/pragma_info.hpp | 13 +- .../parser/parsed_data/transaction_info.hpp | 11 + .../parsed_data/update_extensions_info.hpp | 36 + .../duckdb/parser/parsed_data/vacuum_info.hpp | 1 + .../duckdb/parser/parser_extension.hpp | 1 + src/include/duckdb/parser/query_node.hpp | 4 +- src/include/duckdb/parser/sql_statement.hpp | 5 +- .../parser/statement/alter_statement.hpp | 1 + .../parser/statement/attach_statement.hpp | 1 + .../parser/statement/call_statement.hpp | 1 + .../statement/copy_database_statement.hpp | 3 +- .../parser/statement/copy_statement.hpp | 5 +- .../parser/statement/detach_statement.hpp | 1 + .../parser/statement/drop_statement.hpp | 1 + .../parser/statement/execute_statement.hpp | 1 + .../parser/statement/explain_statement.hpp | 1 + .../parser/statement/export_statement.hpp | 1 + .../parser/statement/extension_statement.hpp | 1 + src/include/duckdb/parser/statement/list.hpp | 1 + .../parser/statement/load_statement.hpp | 1 + .../statement/logical_plan_statement.hpp | 3 + .../parser/statement/multi_statement.hpp | 1 + .../parser/statement/pragma_statement.hpp | 1 + .../parser/statement/prepare_statement.hpp | 1 + .../parser/statement/relation_statement.hpp | 1 + .../duckdb/parser/statement/set_statement.hpp | 10 +- .../statement/transaction_statement.hpp | 3 +- .../statement/update_extensions_statement.hpp | 36 + .../parser/statement/vacuum_statement.hpp | 1 + src/include/duckdb/parser/tableref.hpp | 5 + .../duckdb/parser/tableref/basetableref.hpp | 2 - .../parser/tableref/column_data_ref.hpp | 46 + src/include/duckdb/parser/tableref/list.hpp | 1 + .../duckdb/parser/tableref/pivotref.hpp | 2 - .../duckdb/parser/tableref/subqueryref.hpp | 2 - .../parser/tableref/table_function_ref.hpp | 5 - src/include/duckdb/parser/tokens.hpp | 2 + src/include/duckdb/parser/transformer.hpp | 10 +- src/include/duckdb/planner/binder.hpp | 57 +- src/include/duckdb/planner/bound_tokens.hpp | 1 + .../duckdb/planner/collation_binding.hpp | 44 + .../duckdb/planner/expression_binder.hpp | 24 +- .../expression_binder/alter_binder.hpp | 13 +- .../expression_binder/having_binder.hpp | 3 +- .../expression_binder/index_binder.hpp | 6 +- .../duckdb/planner/logical_operator.hpp | 1 - .../planner/logical_operator_visitor.hpp | 3 +- .../operator/logical_column_data_get.hpp | 8 +- .../operator/logical_comparison_join.hpp | 14 +- .../planner/operator/logical_copy_to_file.hpp | 8 +- .../planner/operator/logical_execute.hpp | 2 +- .../planner/operator/logical_export.hpp | 7 + src/include/duckdb/planner/table_binding.hpp | 8 +- .../tableref/bound_column_data_ref.hpp | 30 + .../duckdb/planner/tableref/bound_joinref.hpp | 2 + .../planner/tableref/bound_subqueryref.hpp | 2 +- .../planner/tableref/bound_table_function.hpp | 2 + src/include/duckdb/planner/tableref/list.hpp | 1 + src/include/duckdb/storage/block.hpp | 4 +- src/include/duckdb/storage/block_manager.hpp | 41 +- .../duckdb/storage/buffer/block_handle.hpp | 9 +- .../duckdb/storage/buffer/buffer_pool.hpp | 62 +- src/include/duckdb/storage/buffer_manager.hpp | 11 +- .../storage/checkpoint/row_group_writer.hpp | 17 +- .../checkpoint/string_checkpoint_state.hpp | 5 +- .../storage/checkpoint/table_data_writer.hpp | 2 + .../write_overflow_strings_to_disk.hpp | 3 +- .../duckdb/storage/checkpoint_manager.hpp | 39 +- .../storage/compression/alp/alp_analyze.hpp | 10 +- .../storage/compression/alp/alp_compress.hpp | 31 +- .../compression/alprd/alprd_analyze.hpp | 16 +- .../compression/alprd/alprd_compress.hpp | 33 +- src/include/duckdb/storage/data_pointer.hpp | 1 + src/include/duckdb/storage/data_table.hpp | 37 +- .../storage/in_memory_block_manager.hpp | 9 + src/include/duckdb/storage/index.hpp | 130 +- .../storage/metadata/metadata_manager.hpp | 14 +- .../duckdb/storage/optimistic_data_writer.hpp | 2 +- .../duckdb/storage/partial_block_manager.hpp | 10 +- .../storage/serialization/create_info.json | 15 +- .../storage/serialization/dependency.json | 56 + .../serialization/extension_install_info.json | 35 + .../serialization/logical_operator.json | 8 +- .../duckdb/storage/serialization/nodes.json | 114 +- .../storage/serialization/parse_info.json | 35 + .../serialization/parsed_expression.json | 5 + .../storage/serialization/tableref.json | 18 + .../duckdb/storage/serialization/types.json | 12 + .../storage/single_file_block_manager.hpp | 24 +- .../storage/standard_buffer_manager.hpp | 17 +- .../duckdb/storage/storage_extension.hpp | 7 + src/include/duckdb/storage/storage_info.hpp | 47 +- src/include/duckdb/storage/storage_lock.hpp | 30 +- .../duckdb/storage/storage_manager.hpp | 46 +- .../duckdb/storage/string_uncompressed.hpp | 30 +- .../duckdb/storage/table/append_state.hpp | 1 + .../storage/table/array_column_data.hpp | 10 +- .../duckdb/storage/table/column_data.hpp | 48 +- .../duckdb/storage/table/column_segment.hpp | 33 +- .../duckdb/storage/table/data_table_info.hpp | 38 +- .../duckdb/storage/table/list_column_data.hpp | 10 +- .../duckdb/storage/table/row_group.hpp | 17 +- .../storage/table/row_group_collection.hpp | 5 +- .../duckdb/storage/table/scan_state.hpp | 15 + .../storage/table/standard_column_data.hpp | 13 +- .../storage/table/struct_column_data.hpp | 10 +- .../duckdb/storage/table/table_index_list.hpp | 26 +- .../duckdb/storage/table/table_statistics.hpp | 7 +- .../storage/table/validity_column_data.hpp | 1 + .../duckdb/storage/write_ahead_log.hpp | 24 +- .../duckdb/transaction/commit_state.hpp | 20 +- .../duckdb/transaction/duck_transaction.hpp | 32 +- .../transaction/duck_transaction_manager.hpp | 39 +- .../duckdb/transaction/local_storage.hpp | 16 +- .../duckdb/transaction/meta_transaction.hpp | 7 +- .../duckdb/transaction/transaction.hpp | 7 + .../transaction/transaction_context.hpp | 2 + .../duckdb/transaction/undo_buffer.hpp | 14 +- .../duckdb/transaction/wal_write_state.hpp | 47 + src/main/CMakeLists.txt | 4 + src/main/appender.cpp | 60 +- src/main/attached_database.cpp | 111 +- src/main/buffered_data/CMakeLists.txt | 3 +- .../buffered_data/batched_buffered_data.cpp | 212 + src/main/buffered_data/buffered_data.cpp | 16 + .../buffered_data/simple_buffered_data.cpp | 25 +- src/main/capi/CMakeLists.txt | 2 + src/main/capi/appender-c.cpp | 25 +- src/main/capi/config-c.cpp | 6 +- src/main/capi/helper-c.cpp | 6 +- src/main/capi/prepared-c.cpp | 13 +- src/main/capi/replacement_scan-c.cpp | 11 +- src/main/capi/result-c.cpp | 20 +- src/main/capi/scalar_function-c.cpp | 151 + src/main/capi/stream-c.cpp | 25 +- src/main/capi/table_description-c.cpp | 82 + src/main/capi/table_function-c.cpp | 243 +- src/main/client_config.cpp | 17 + src/main/client_context.cpp | 27 +- src/main/client_context_file_opener.cpp | 31 + src/main/client_context_wrapper.cpp | 22 + src/main/client_data.cpp | 8 +- src/main/config.cpp | 64 +- src/main/connection_manager.cpp | 32 +- src/main/database.cpp | 54 +- src/main/database_manager.cpp | 46 +- src/main/extension.cpp | 56 + src/main/extension/CMakeLists.txt | 2 +- src/main/extension/extension_helper.cpp | 408 +- src/main/extension/extension_install.cpp | 412 +- src/main/extension/extension_load.cpp | 272 +- src/main/extension/extension_util.cpp | 10 +- src/main/extension_install_info.cpp | 116 + src/main/materialized_query_result.cpp | 11 + src/main/pending_query_result.cpp | 24 +- src/main/profiling_info.cpp | 65 + src/main/query_profiler.cpp | 166 +- src/main/query_result.cpp | 2 +- src/main/relation.cpp | 8 +- src/main/relation/CMakeLists.txt | 1 + src/main/relation/create_view_relation.cpp | 6 + src/main/relation/materialized_relation.cpp | 58 + src/main/relation/query_relation.cpp | 43 + src/main/relation/read_csv_relation.cpp | 4 +- src/main/relation/write_csv_relation.cpp | 2 +- src/main/relation/write_parquet_relation.cpp | 2 +- src/main/settings/settings.cpp | 267 + src/main/stream_query_result.cpp | 3 + src/optimizer/CMakeLists.txt | 2 + src/optimizer/build_probe_side_optimizer.cpp | 151 + src/optimizer/column_lifetime_analyzer.cpp | 31 +- src/optimizer/filter_combiner.cpp | 10 + src/optimizer/filter_pullup.cpp | 7 +- src/optimizer/filter_pushdown.cpp | 3 + src/optimizer/join_order/CMakeLists.txt | 1 - .../join_order/cardinality_estimator.cpp | 304 +- .../join_order/estimated_properties.cpp | 36 - src/optimizer/join_order/join_node.cpp | 32 - .../join_order/join_order_optimizer.cpp | 31 +- .../join_order/join_relation_set.cpp | 8 +- src/optimizer/join_order/plan_enumerator.cpp | 75 +- .../join_order/query_graph_manager.cpp | 246 +- src/optimizer/join_order/relation_manager.cpp | 29 +- .../join_order/relation_statistics_helper.cpp | 14 +- src/optimizer/limit_pushdown.cpp | 42 + src/optimizer/optimizer.cpp | 45 +- src/optimizer/pushdown/CMakeLists.txt | 3 +- src/optimizer/pushdown/pushdown_aggregate.cpp | 25 +- .../pushdown/pushdown_cross_product.cpp | 14 +- src/optimizer/pushdown/pushdown_window.cpp | 91 + src/optimizer/remove_unused_columns.cpp | 27 +- src/optimizer/rule/CMakeLists.txt | 4 +- src/optimizer/rule/join_dependent_filter.cpp | 135 + src/optimizer/rule/move_constants.cpp | 4 + src/optimizer/rule/timestamp_comparison.cpp | 107 + .../statistics/operator/propagate_filter.cpp | 7 +- src/optimizer/topn_optimizer.cpp | 48 +- src/parallel/executor.cpp | 21 +- src/parallel/task_scheduler.cpp | 42 +- src/parallel/thread_context.cpp | 2 +- src/parser/column_definition.cpp | 1 + src/parser/expression/function_expression.cpp | 14 + src/parser/expression/star_expression.cpp | 37 +- src/parser/parsed_data/CMakeLists.txt | 3 + .../alter_scalar_function_info.cpp | 4 + .../parsed_data/alter_table_function_info.cpp | 4 + src/parser/parsed_data/alter_table_info.cpp | 183 + src/parser/parsed_data/attach_info.cpp | 40 + .../parsed_data/comment_on_column_info.cpp | 17 +- src/parser/parsed_data/copy_info.cpp | 100 + src/parser/parsed_data/create_info.cpp | 2 + src/parser/parsed_data/create_type_info.cpp | 8 +- src/parser/parsed_data/detach_info.cpp | 12 + src/parser/parsed_data/drop_info.cpp | 21 + src/parser/parsed_data/load_info.cpp | 46 + src/parser/parsed_data/pragma_info.cpp | 33 + src/parser/parsed_data/transaction_info.cpp | 44 +- src/parser/parsed_data/vacuum_info.cpp | 20 + src/parser/parsed_expression_iterator.cpp | 1 + src/parser/parser.cpp | 42 +- src/parser/query_node.cpp | 8 +- src/parser/statement/CMakeLists.txt | 1 + src/parser/statement/alter_statement.cpp | 4 + src/parser/statement/attach_statement.cpp | 4 + src/parser/statement/call_statement.cpp | 8 + src/parser/statement/copy_statement.cpp | 87 +- src/parser/statement/detach_statement.cpp | 4 + src/parser/statement/drop_statement.cpp | 4 + src/parser/statement/execute_statement.cpp | 15 + src/parser/statement/explain_statement.cpp | 19 + src/parser/statement/export_statement.cpp | 18 + src/parser/statement/extension_statement.cpp | 4 + src/parser/statement/load_statement.cpp | 4 + src/parser/statement/multi_statement.cpp | 8 + src/parser/statement/pragma_statement.cpp | 4 + src/parser/statement/prepare_statement.cpp | 13 + src/parser/statement/relation_statement.cpp | 4 + src/parser/statement/set_statement.cpp | 37 +- .../statement/transaction_statement.cpp | 10 +- .../statement/update_extensions_statement.cpp | 34 + src/parser/statement/vacuum_statement.cpp | 4 + src/parser/tableref.cpp | 1 + src/parser/tableref/CMakeLists.txt | 1 + src/parser/tableref/column_data_ref.cpp | 81 + .../constraint/transform_constraint.cpp | 64 +- .../expression/transform_array_access.cpp | 64 +- .../expression/transform_columnref.cpp | 3 +- .../expression/transform_function.cpp | 5 + .../expression/transform_interval.cpp | 7 +- .../transform_multi_assign_reference.cpp | 70 +- .../expression/transform_subquery.cpp | 16 + .../transform/helpers/nodetype_to_string.cpp | 2 + .../transform/helpers/transform_alias.cpp | 3 +- .../transform/helpers/transform_cte.cpp | 4 +- .../transform/helpers/transform_orderby.cpp | 59 +- .../transform/helpers/transform_typename.cpp | 154 +- .../statement/transform_alter_table.cpp | 52 +- .../statement/transform_checkpoint.cpp | 2 + .../transform/statement/transform_copy.cpp | 2 +- .../statement/transform_create_table.cpp | 12 +- .../transform/statement/transform_load.cpp | 6 +- .../statement/transform_transaction.cpp | 33 +- .../transform/statement/transform_update.cpp | 24 +- .../transform/statement/transform_upsert.cpp | 23 +- .../transform/statement/transform_vacuum.cpp | 6 +- .../transform/tableref/transform_join.cpp | 26 +- src/parser/transformer.cpp | 3 + src/planner/CMakeLists.txt | 1 + src/planner/binder.cpp | 98 +- src/planner/binder/expression/CMakeLists.txt | 1 + .../expression/bind_aggregate_expression.cpp | 43 +- .../expression/bind_between_expression.cpp | 6 +- .../expression/bind_cast_expression.cpp | 2 +- .../expression/bind_collate_expression.cpp | 2 +- .../expression/bind_columnref_expression.cpp | 5 +- .../expression/bind_comparison_expression.cpp | 59 +- .../expression/bind_function_expression.cpp | 24 +- .../expression/bind_macro_expression.cpp | 26 +- .../expression/bind_operator_expression.cpp | 2 +- .../expression/bind_star_expression.cpp | 30 +- .../bind_unpacked_star_expression.cpp | 91 + .../expression/bind_window_expression.cpp | 4 +- .../binder/query_node/bind_select_node.cpp | 6 +- src/planner/binder/query_node/plan_setop.cpp | 37 +- .../binder/query_node/plan_subquery.cpp | 6 +- src/planner/binder/statement/CMakeLists.txt | 1 + src/planner/binder/statement/bind_attach.cpp | 2 + src/planner/binder/statement/bind_call.cpp | 2 + src/planner/binder/statement/bind_copy.cpp | 141 +- .../binder/statement/bind_copy_database.cpp | 87 +- src/planner/binder/statement/bind_create.cpp | 180 +- .../binder/statement/bind_create_table.cpp | 23 +- src/planner/binder/statement/bind_delete.cpp | 3 + src/planner/binder/statement/bind_detach.cpp | 2 + src/planner/binder/statement/bind_drop.cpp | 2 + src/planner/binder/statement/bind_execute.cpp | 6 +- src/planner/binder/statement/bind_explain.cpp | 2 + src/planner/binder/statement/bind_export.cpp | 113 +- .../binder/statement/bind_extension.cpp | 1 + src/planner/binder/statement/bind_insert.cpp | 134 +- src/planner/binder/statement/bind_load.cpp | 13 + .../binder/statement/bind_logical_plan.cpp | 2 + src/planner/binder/statement/bind_pragma.cpp | 2 + src/planner/binder/statement/bind_prepare.cpp | 1 + src/planner/binder/statement/bind_select.cpp | 1 + src/planner/binder/statement/bind_set.cpp | 4 + src/planner/binder/statement/bind_simple.cpp | 13 +- .../binder/statement/bind_summarize.cpp | 7 +- src/planner/binder/statement/bind_update.cpp | 3 + .../statement/bind_update_extensions.cpp | 28 + src/planner/binder/statement/bind_vacuum.cpp | 7 +- src/planner/binder/tableref/CMakeLists.txt | 2 + .../binder/tableref/bind_basetableref.cpp | 134 +- .../binder/tableref/bind_column_data_ref.cpp | 16 + src/planner/binder/tableref/bind_joinref.cpp | 9 +- src/planner/binder/tableref/bind_pivot.cpp | 5 +- .../binder/tableref/bind_table_function.cpp | 194 +- .../binder/tableref/plan_column_data_ref.cpp | 15 + src/planner/binder/tableref/plan_joinref.cpp | 49 +- .../binder/tableref/plan_table_function.cpp | 4 + src/planner/collation_binding.cpp | 99 + .../expression/bound_cast_expression.cpp | 12 +- src/planner/expression/bound_expression.cpp | 5 +- src/planner/expression_binder.cpp | 16 +- .../expression_binder/alter_binder.cpp | 31 +- .../expression_binder/base_select_binder.cpp | 29 +- .../expression_binder/having_binder.cpp | 53 +- .../expression_binder/index_binder.cpp | 33 + .../expression_binder/order_binder.cpp | 8 + src/planner/expression_iterator.cpp | 31 +- src/planner/filter/constant_filter.cpp | 2 +- .../operator/logical_column_data_get.cpp | 18 +- src/planner/operator/logical_copy_to_file.cpp | 24 +- src/planner/operator/logical_get.cpp | 12 +- src/planner/operator/logical_vacuum.cpp | 2 +- src/planner/planner.cpp | 42 +- .../subquery/flatten_dependent_join.cpp | 46 +- src/storage/arena_allocator.cpp | 1 + src/storage/block.cpp | 5 +- src/storage/buffer/block_handle.cpp | 26 +- src/storage/buffer/block_manager.cpp | 9 +- src/storage/buffer/buffer_handle.cpp | 2 +- src/storage/buffer/buffer_pool.cpp | 401 +- src/storage/buffer_manager.cpp | 6 +- src/storage/checkpoint/row_group_writer.cpp | 9 + src/storage/checkpoint/table_data_writer.cpp | 9 +- .../write_overflow_strings_to_disk.cpp | 18 +- src/storage/checkpoint_manager.cpp | 178 +- src/storage/compression/alp/alp.cpp | 17 +- src/storage/compression/alprd.cpp | 14 +- src/storage/compression/bitpacking.cpp | 41 +- src/storage/compression/chimp/chimp.cpp | 14 +- .../compression/dictionary_compression.cpp | 120 +- .../compression/fixed_size_uncompressed.cpp | 18 +- src/storage/compression/fsst.cpp | 49 +- src/storage/compression/numeric_constant.cpp | 9 +- src/storage/compression/patas.cpp | 23 +- src/storage/compression/rle.cpp | 31 +- .../compression/string_uncompressed.cpp | 101 +- src/storage/compression/uncompressed.cpp | 4 +- .../compression/validity_uncompressed.cpp | 15 +- src/storage/data_pointer.cpp | 5 +- src/storage/data_table.cpp | 230 +- src/storage/index.cpp | 108 +- src/storage/local_storage.cpp | 82 +- src/storage/metadata/metadata_manager.cpp | 46 +- src/storage/metadata/metadata_reader.cpp | 8 +- src/storage/metadata/metadata_writer.cpp | 6 +- src/storage/optimistic_data_writer.cpp | 20 +- src/storage/partial_block_manager.cpp | 31 +- src/storage/serialization/CMakeLists.txt | 2 + .../serialization/serialize_create_info.cpp | 8 + .../serialization/serialize_dependency.cpp | 49 + .../serialize_extension_install_info.cpp | 30 + .../serialize_logical_operator.cpp | 7 +- src/storage/serialization/serialize_nodes.cpp | 82 +- .../serialization/serialize_parse_info.cpp | 23 + .../serialize_parsed_expression.cpp | 2 + .../serialization/serialize_tableref.cpp | 16 + src/storage/serialization/serialize_types.cpp | 5 + src/storage/single_file_block_manager.cpp | 134 +- src/storage/standard_buffer_manager.cpp | 239 +- src/storage/storage_info.cpp | 115 +- src/storage/storage_lock.cpp | 94 +- src/storage/storage_manager.cpp | 216 +- src/storage/table/array_column_data.cpp | 26 +- src/storage/table/column_checkpoint_state.cpp | 5 +- src/storage/table/column_data.cpp | 144 +- .../table/column_data_checkpointer.cpp | 9 +- src/storage/table/column_segment.cpp | 91 +- src/storage/table/list_column_data.cpp | 35 +- src/storage/table/row_group.cpp | 71 +- src/storage/table/row_group_collection.cpp | 52 +- src/storage/table/scan_state.cpp | 9 +- src/storage/table/standard_column_data.cpp | 50 +- src/storage/table/struct_column_data.cpp | 44 +- src/storage/table/table_statistics.cpp | 35 +- src/storage/table/validity_column_data.cpp | 5 + src/storage/table_index_list.cpp | 109 +- src/storage/version_map.json | 52 + src/storage/wal_replay.cpp | 43 +- src/storage/write_ahead_log.cpp | 106 +- src/transaction/CMakeLists.txt | 3 +- src/transaction/cleanup_state.cpp | 7 +- src/transaction/commit_state.cpp | 178 +- src/transaction/duck_transaction.cpp | 130 +- src/transaction/duck_transaction_manager.cpp | 299 +- src/transaction/meta_transaction.cpp | 37 +- src/transaction/rollback_state.cpp | 2 + src/transaction/transaction.cpp | 14 +- src/transaction/transaction_context.cpp | 4 + src/transaction/undo_buffer.cpp | 76 +- src/transaction/wal_write_state.cpp | 291 + test/api/adbc/test_adbc.cpp | 9 +- test/api/capi/CMakeLists.txt | 5 +- test/api/capi/capi_scalar_functions.cpp | 184 + test/api/capi/capi_table_functions.cpp | 17 +- test/api/capi/test_capi.cpp | 32 + test/api/capi/test_capi_appender.cpp | 161 +- test/api/capi/test_capi_complex_types.cpp | 4 + test/api/capi/test_capi_data_chunk.cpp | 71 + test/api/capi/test_capi_prepared.cpp | 8 + test/api/capi/test_capi_table_description.cpp | 47 + .../capi/test_without_disabled_functions.cpp | 41 + test/api/serialized_plans/queries.sql | 3 + .../serialized_plans/serialized_plans.binary | Bin 71317 -> 71756 bytes test/api/test_api.cpp | 14 +- test/api/test_get_table_names.cpp | 5 + test/api/test_relation_api.cpp | 11 + test/api/test_reset.cpp | 28 +- test/api/test_results.cpp | 7 +- test/appender/test_appender.cpp | 107 + test/arrow/arrow_roundtrip.cpp | 27 + test/common/CMakeLists.txt | 1 + test/extension/CMakeLists.txt | 1 + test/extension/duckdb_extensions.test | 47 + test/extension/install_extension.test | 39 + test/extension/install_extension.test_slow | 2 +- test/extension/install_version.test | 31 + test/extension/load_extension.test | 5 + test/extension/loadable_extension_demo.cpp | 301 +- .../loadable_extension_optimizer_demo.cpp | 5 +- test/extension/test_alias_point.test | 2 + .../test_custom_type_modifier.test_slow | 199 + test/extension/test_tags.test | 24 + test/extension/update_extensions.test | 67 + test/extension/update_extensions_ci.test | 391 + .../duckfuzz/array_const_columndatacopy.test | 19 + test/fuzzer/duckfuzz/array_distance.test | 22 + .../duckfuzz/array_group_by_sample.test | 27 +- test/fuzzer/duckfuzz/array_hash.test | 2 +- .../fuzzer/duckfuzz/array_slice_nullness.test | 16 + .../duckfuzz/create_sort_key_strings.test | 23 + .../duck_fuzz_column_binding_tests.test | 20 +- .../duckfuzz_tests/test_duckfuzz.test | 16 - .../duckfuzz/generate_null_timestamp.test | 3 +- test/fuzzer/duckfuzz/repeat_wrong_number.test | 38 + .../try_cast_string_to_list.test_slow | 18 + .../duckfuzz/tuple_data_empty_heap.test | 14 + test/fuzzer/duckfuzz/vector_type.test | 34 + .../pedro/alter_dependency_conflict.test | 7 +- .../pedro/currval_sequence_dependency.test | 5 +- .../pedro/nested_subquery_table_function.test | 12 +- .../vacuum_table_with_generated_column.test | 21 +- test/fuzzer/pedro/view_not_rebound_error.test | 17 +- ...ot_rebound_error_no_view_dependencies.test | 24 + .../sqlsmith/timestamptz_null_range.test | 6 +- test/helpers/test_helpers.cpp | 1 + test/issues/general/test_11391.test | 2 +- test/issues/general/test_11566.test | 18 + test/issues/general/test_5614.test | 3 + .../{test_9399.test => test_9399.test_slow} | 2 +- ...must_visit_operator_expressions_first.test | 19 + test/optimizer/deliminator.test | 1 + test/optimizer/issue_12181.test | 22 + test/optimizer/join_dependent_filter.test | 254 + ...ns_and_one_non_reorderable_join.test_slow} | 2 +- test/optimizer/joins/pushdown_semi_anti.test | 29 + ...st => update_nodes_in_full_path.test_slow} | 4 +- ...oin_node_hash_map_has_no_errors.test_slow} | 3 +- test/optimizer/limit_pushdown.test | 65 + test/optimizer/perfect_ht.test | 2 + ...final_projected_columns_on_probe_side.test | 34 + .../pushdown/pushdown_in_to_parquet.test | 25 + .../pushdown_window_partition_filter.test | 153 + .../pushdown/timestamp_to_date_pushdown.test | 79 + .../optimizer/statistics/statistics_case.test | 1 + test/optimizer/topn/complex_top_n.test | 8 +- test/optimizer/topn/topn_optimizer.test | 20 + ...ewriter.test => unnest_rewriter.test_slow} | 2 +- .../distinct_on_projection_pushdown.test | 50 + test/parquet/test_filename_column.test | 58 + .../test_parquet_reader_compression.test | 287 +- test/parquet/timetz_parquet.test | 21 + test/serialize/serialization_test.cpp | 26 +- .../arg_min_max_all_types.test_slow | 23 + test/sql/aggregate/aggregates/binning.test | 269 + .../aggregates/first_test_all_types.test_slow | 22 + .../aggregates/histogram_table_function.test | 149 + .../histogram_test_all_types.test_slow | 30 + .../aggregates/histogram_tpch.test_slow | 99 + .../aggregates/mode_test_all_types.test_slow | 29 + .../aggregate/aggregates/mode_tpch.test_slow | 34 + .../quantile_test_all_types.test_slow | 26 + .../aggregates/test_approx_quantile.test | 24 + .../test_approximate_distinct_count.test | 8 +- .../aggregates/test_arg_min_max.test | 35 + ...test => test_arg_min_max_nested.test_slow} | 2 +- ...=> test_arg_min_max_null_nested.test_slow} | 2 +- ...> test_arg_min_max_null_strings.test_slow} | 2 +- .../aggregates/test_binned_histogram.test | 122 + .../aggregate/aggregates/test_histogram.test | 2 +- .../sql/aggregate/aggregates/test_median.test | 25 +- .../sql/aggregate/aggregates/test_minmax.test | 2 +- .../aggregates/test_quantile_disc.test | 10 + .../aggregates/test_quantile_disc_list.test | 17 + .../aggregates/test_state_export.test | 6 + .../aggregate/aggregates/test_string_agg.test | 38 + ...distinct_and_non_distinct_mixed.test_slow} | 2 +- .../grouped/multiple_grouping_sets.test | 13 + .../aggregate/qualify/test_qualify_view.test | 19 +- ...est_qualify_view_no_view_dependencies.test | 73 + ...st_rename_table_with_dependency_check.test | 6 +- .../attach_checkpoint_deadlock.test_slow | 2 +- .../attach_concurrent_checkpoint.test_slow | 2 +- test/sql/attach/attach_create_index.test | 14 + test/sql/attach/attach_custom_block_size.test | 85 + test/sql/attach/attach_huggingface_index.test | 15 + test/sql/attach/attach_icu_collation.test | 45 + .../attach/attach_read_only_transaction.test | 33 + test/sql/attach/attach_remote.test | 20 + test/sql/attach/attach_reserved.test | 15 + test/sql/attach/attach_s3_tpch.test_slow | 17 + test/sql/attach/attach_wal_alter.test | 49 + test/sql/binder/order_by_view.test | 32 +- ...cast.test => string_to_map_cast.test_slow} | 2 +- .../string_to_nested_types_cast.test_slow | 4 +- test/sql/cast/test_boolean_cast.test | 49 + test/sql/catalog/comment_on.test | 5 + test/sql/catalog/comment_on_dependencies.test | 47 +- .../add_column_to_table_referenced_by_fk.test | 33 + ...d_column_to_table_referenced_by_macro.test | 27 + ...dd_column_to_table_referenced_by_view.test | 27 + ...e_of_table_column_referenced_by_index.test | 16 + ...move_table_column_referenced_by_index.test | 16 + ...name_table_column_referenced_by_index.test | 16 + ...rename_view_referenced_by_table_macro.test | 27 + ...t_of_table_column_referenced_by_index.test | 17 + .../test_alter_dependency_ownership.test | 29 +- .../dependencies/test_alter_owning_table.test | 4 +- .../dependencies/test_concurrent_drop.test | 2 +- .../test_default_value_dependency.test | 33 +- ...est_prepare_dependencies_transactions.test | 1 + .../dependencies/test_schema_dependency.test | 5 +- test/sql/catalog/function/query_function.test | 283 + .../function/test_cross_catalog_macros.test | 16 + .../function/test_macro_default_arg.test | 3 + ...t_macro_default_arg_with_dependencies.test | 107 + .../function/test_recursive_macro.test | 17 +- .../test_recursive_macro_no_dependency.test | 53 + test/sql/catalog/sequence/test_sequence.test | 24 +- test/sql/catalog/test_catalog_errors.test | 15 +- test/sql/catalog/test_schema.test | 4 +- test/sql/catalog/view/recursive_view.test | 3 + .../recursive_view_with_dependencies.test | 39 + .../catalog/view/test_view_schema_change.test | 3 + ..._view_schema_change_with_dependencies.test | 115 + test/sql/catalog/view/test_view_sql.test | 3 + .../view/test_view_sql_with_dependencies.test | 111 + .../test_collate_and_grouping_sets.test | 84 + test/sql/collate/test_icu_collate.test | 32 + .../constraints/foreignkey/test_fk_alter.test | 36 + .../foreignkey/test_fk_multiple.test | 32 +- .../foreignkey/test_fk_rollback.test | 1 + .../copy/csv/auto/test_type_detection.test | 2 + .../batch_csv_mixed_batches.test_slow | 9 + .../csv_parallel_clickbench.test_slow | 2 +- test/sql/copy/csv/read_csv_subquery.test | 2 +- .../copy/csv/recursive_query_csv.test_slow | 192 +- ...test => csv_buffer_size_rejects.test_slow} | 11 +- .../csv_incorrect_columns_amount_rejects.test | 16 + .../csv/rejects/csv_rejects_flush_cast.test | 6 +- .../rejects/csv_rejects_flush_message.test | 9 +- .../copy/csv/rejects/csv_rejects_read.test | 19 + .../csv/rejects/csv_rejects_two_tables.test | 16 +- test/sql/copy/csv/test_11840.test | 19 + test/sql/copy/csv/test_12314.test_slow | 15 + test/sql/copy/csv/test_big_header.test | 2 + test/sql/copy/csv/test_bug_9952.test | 12 - test/sql/copy/csv/test_bug_9952.test_slow | 16 + .../copy/csv/test_column_inconsistencies.test | 2 + .../copy/csv/test_csv_error_message_type.test | 27 +- test/sql/copy/csv/test_csv_remote.test | 2 +- test/sql/copy/csv/test_headers_12089.test | 17 + test/sql/copy/csv/test_ignore_errors.test | 11 +- test/sql/copy/csv/test_insert_into_types.test | 245 + test/sql/copy/csv/test_lineitem_gz.test | 38 + .../sql/copy/csv/test_mixed_line_endings.test | 7 + ..._lines.test => test_mixed_lines.test_slow} | 2 +- .../copy/csv/test_partition_compression.test | 63 + test/sql/copy/csv/test_quote_default.test | 13 + test/sql/copy/csv/test_skip.test_slow | 284 + test/sql/copy/csv/test_sniff_csv.test | 18 +- test/sql/copy/csv/test_sniff_csv_options.test | 36 +- test/sql/copy/file_size_bytes.test | 6 +- test/sql/copy/format_uuid.test | 12 +- .../{hive_types.test => hive_types.test_slow} | 4 +- .../parquet_write_mixed_batches.test_slow | 11 + .../parquet/broken/broken_structure.parquet | Bin 0 -> 212 bytes test/sql/copy/parquet/broken_parquet.test | 5 + test/sql/copy/parquet/parquet_encryption.test | 17 +- test/sql/copy/parquet/parquet_stats.test | 14 + .../copy/parquet/parquet_write_codecs.test | 46 +- .../recursive_parquet_union_by_name.test | 2 +- .../parquet/test_parquet_force_download.test | 6 +- .../writer/parquet_test_all_types.test | 25 +- .../writer/parquet_write_timestamp.test | 38 +- .../partitioned/hive_filter_pushdown.test | 6 +- .../partitioned/hive_partition_append.test | 63 + .../hive_partitioning_overwrite.test | 11 +- test/sql/copy/per_thread_output.test | 30 +- test/sql/copy/return_files.test | 45 + test/sql/copy/row_groups_per_file.test | 153 + .../copy/row_groups_per_file_large.test_slow | 48 + test/sql/copy/s3/s3_hive_partition.test | 4 + .../copy_database_different_types.test | 3 + .../copy_database/copy_database_index.test | 27 + test/sql/create/create_as_issue_11968.test | 16 + .../materialized/dml_materialized_cte.test | 72 +- .../materialized_cte_prepared.test | 51 + ...correlated_recursive_cte_materialized.test | 8 +- .../test_cte_in_cte_materialized.test | 5 + .../cte/test_correlated_recursive_cte.test | 8 +- .../delete/large_deletes_transactions.test | 40 + test/sql/excel/test_excel_numformat.test | 568 - test/sql/explain/test_explain_analyze.test | 4 +- test/sql/extensions/checked_load.test | 6 +- test/sql/extensions/description_is_valid.test | 19 + test/sql/filter/test_struct_pushdown.test | 6 +- test/sql/fts/issue_12330.test | 34 + test/sql/fts/test_indexing.test_slow | 4 +- test/sql/fts/test_issue_10254.test | 2 +- test/sql/function/array/array_and_map.test | 23 + test/sql/function/date/test_date_part.test | 12 + test/sql/function/date/test_extract.test | 7 + .../function/generic/can_cast_implicitly.test | 31 + test/sql/function/generic/test_set.test | 4 + .../sql/function/interval/test_date_part.test | 10 + .../aggregates/approx_count_distinct.test | 8 +- test/sql/function/list/aggregates/median.test | 2 +- .../aggregates/minmax_all_types.test_slow | 24 + .../list/aggregates/minmax_nested.test | 227 + test/sql/function/list/aggregates/mode.test | 2 - test/sql/function/list/aggregates/types.test | 7 +- .../function/list/lambdas/lambda_scope.test | 4 +- .../list/lambdas/lambdas_and_group_by.test | 13 + .../lambdas/{reduce.test => reduce.test_slow} | 2 +- .../list/lambdas/table_functions.test | 16 + test/sql/function/list/list_distinct.test | 35 +- ..._grade_up.test => list_grade_up.test_slow} | 2 +- test/sql/function/list/list_intersect.test | 5 +- test/sql/function/list/list_resize.test | 11 + ...list_select.test => list_select.test_slow} | 9 +- test/sql/function/list/list_unique.test | 7 +- test/sql/function/list/list_where.test | 13 +- test/sql/function/list/list_zip.test | 9 + .../operator/test_date_arithmetic.test | 24 +- test/sql/function/string/test_concat.test | 1 - .../function/string/test_concat_binding.test | 69 + test/sql/function/time/test_date_part.test | 8 + .../function/timestamp/test_date_part.test | 90 + .../timestamp/test_icu_datetrunc.test | 8 + .../function/timestamp/test_icu_strptime.test | 90 + .../timestamp/test_strftime_timestamp_ns.test | 398 + .../sql/function/timestamp/test_strptime.test | 4 +- test/sql/function/timetz/test_date_part.test | 16 + .../virtual/cascading_delete.test | 1 + test/sql/httpfs/hffs.test | 42 + test/sql/httpfs/hffs.test_slow | 122 + .../art/storage/test_art_auto_checkpoint.test | 6 +- ..._vacuum.test => test_art_vacuum.test_slow} | 2 +- ... => insert_non_order_preserving.test_slow} | 2 +- test/sql/join/asof/test_asof_join.test | 47 +- .../join/asof/test_asof_join_pushdown.test | 36 + .../simple_external_join.test_coverage | 2 +- ....test => test_join_perfect_hash.test_slow} | 2 +- test/sql/join/test_complex_join_expr.test | 2 +- test/sql/join/test_nested_keys.test | 3 - ...ds.test => test_nested_payloads.test_slow} | 2 +- test/sql/json/issues/issue11804.test | 20 + test/sql/json/issues/issue12188.test | 20 + test/sql/json/scalar/test_json_create.test | 6 + test/sql/json/scalar/test_json_extract.test | 38 + .../json/scalar/test_json_merge_patch.test | 16 +- test/sql/json/scalar/test_json_structure.test | 11 +- test/sql/json/table/read_json_auto.test_slow | 101 +- test/sql/json/test_json_empty_object.test | 6 +- .../expression/test_timestamp_offset.test | 50 + test/sql/order/issue_11936.test | 21 + .../leftover_temp_files_issue_6420.test_slow | 10 +- ...ncurrent_append_metadata_queries.test_slow | 92 + ...rent_append_transactions_indexes.test_slow | 4 - .../concurrent_force_checkpoint.test | 72 + ...oncurrent_index_scans_while_appending.test | 34 + .../concurrent_mix_operations.test_slow | 55 + .../concurrent_reads_append_list.test_slow | 40 + .../concurrent_reads_while_altering.test | 47 + ...concurrent_reads_while_appending.test_slow | 38 + ...rent_reads_while_appending_nulls.test_slow | 39 + .../concurrent_reads_while_renaming.test | 40 + .../concurrent_reads_while_updating.test_slow | 38 + .../interquery/test_concurrent_index.cpp | 35 +- .../tpch_concurrent_operations.test_slow | 63 + .../test_aggregations_parallelism.test_slow | 4 +- .../dollar_quotes_internal_issue2224.test | 81 + test/sql/parser/star_expression.test | 2 +- test/sql/parser/test_columns_lists.test | 5 + test/sql/parser/test_columns_unpacked.test | 190 + test/sql/pg_catalog/pg_type.test | 117 + test/sql/pg_catalog/sqlalchemy.test | 30 +- test/sql/pivot/pivot_struct_aggregate.test | 23 + test/sql/pragma/not_a_valid.json | 10 + .../test_custom_profiling_settings.test | 181 + test/sql/pragma/test_enable_http_logging.test | 18 + ...e.test => same_seed_same_sample.test_slow} | 2 +- test/sql/secrets/create_secret_hffs.test | 39 + .../secrets/create_secret_hffs_autoload.test | 37 + test/sql/show_select/test_summarize.test | 19 + .../sql/storage/bc/internal_schemas_0102.test | 22 + test/sql/storage/buffer_manager_temp_dir.test | 4 + .../catalog/test_view_explicit_aliases.test | 26 +- .../storage/catalog/test_view_storage.test | 28 +- ...est_view_storage_no_view_dependencies.test | 79 + .../compact_block_size.test | 3 +- .../default_block_size.test | 4 +- ...ments.test => alp_many_segments.test_slow} | 2 +- ...test => alp_many_segments_float.test_slow} | 2 +- ..._flush.test => alp_middle_flush.test_slow} | 2 +- ...nts.test => alprd_many_segments.test_slow} | 2 +- ...st => alprd_many_segments_float.test_slow} | 2 +- ...lush.test => alprd_middle_flush.test_slow} | 2 +- .../{chimp_read.test => chimp_read.test_slow} | 2 +- .../{patas_read.test => patas_read.test_slow} | 2 +- test/sql/storage/compression/string/blob.test | 3 + .../string/{null.test => null.test_slow} | 2 +- .../concurrent_table_insertion.test_slow | 6 +- test/sql/storage/force_checkpoint_abort.test | 38 - test/sql/storage/icu_collation.test | 44 + test/sql/storage/issue7582_list_storage.test | 10 +- ...tionary.test => list_dictionary.test_slow} | 2 +- ...le_clients_checkpoing_dependents.test_slow | 6 +- ...le_clients_checkpoint_pending_updates.test | 36 +- .../batch_insert_mix_batches.test_slow | 6 + .../batch_insert_small_batches.test_slow | 12 +- .../memory_limit_batch_load.test_slow | 4 + ...ace_drop_column_overflow_strings.test_slow | 25 +- .../test_reclaim_space_alter_type.test_slow | 15 +- .../test_reclaim_space_update.test_slow | 25 +- test/sql/storage/relocate_metadata.test_slow | 53 + test/sql/storage/storage_types.test | 19 +- .../temp_directory/max_swap_space_error.test | 20 +- .../max_swap_space_inmemory.test | 4 + .../max_swap_space_persistent.test | 91 +- test/sql/storage/test_empty_table.test | 7 +- ..._queue.test => test_purge_queue.test_slow} | 2 +- .../storage/types/test_timestamp_storage.test | 8 +- .../test_truncate_after_delete.test_slow | 17 +- .../storage/wal/wal_create_insert_drop.test | 107 + test/sql/storage/wal/wal_lazy_creation.test | 38 + .../wal/wal_view_explicit_aliases.test | 25 +- ...explicit_aliases_no_view_dependencies.test | 74 + test/sql/storage/wal/wal_view_storage.test | 60 +- ...wal_view_storage_no_view_dependencies.test | 97 + test/sql/storage/wal_torn_write.cpp | 2 + test/sql/storage_version/storage_version.db | Bin 798720 -> 3420160 bytes .../storage_version/storage_version.test_slow | 10 +- .../complex/nested_correlated_list.test_slow | 3 - .../exists/test_exists_union_by_name.test | 24 + .../lateral/lateral_binding_views.test | 19 + .../subquery/lateral/test_lateral_join.test | 12 + .../subquery/scalar/array_order_subquery.test | 20 +- .../scalar/nested_subquery_window.test | 21 + .../scalar/test_correlated_window.test | 54 + test/sql/table_function/duckdb_columns.test | 3 + ...ctions.test => duckdb_functions.test_slow} | 2 +- .../range_function_lateral.test | 134 + test/sql/table_function/range_timestamp.test | 11 + .../test_read_only_transactions.test | 30 + test/sql/types/date/date_implicit_cast.test | 25 + .../types/decimal/decimal_automatic_cast.test | 2 +- test/sql/types/decimal/test_decimal.test | 11 + .../decimal/test_decimal_from_string.test | 5 + ...ry.test => test_enum_from_query.test_slow} | 2 +- test/sql/types/interval/test_interval.test | 5 + ...test => unnest_many_empty_lists.test_slow} | 2 +- .../sql/types/list/unnest_table_function.test | 39 +- .../{array_sort.test => array_sort.test_slow} | 21 +- ...orage_2.test => array_storage_2.test_slow} | 2 +- .../sql/types/nested/map/test_map_concat.test | 11 + .../types/nested/map/test_map_entries.test | 25 + test/sql/types/nested/map/test_map_keys.test | 25 + .../types/nested/map/test_map_subscript.test | 25 + .../sql/types/nested/map/test_map_values.test | 25 + .../nested/map/test_null_map_interaction.test | 45 + .../combinations/decimal_combinations.test | 4 +- test/sql/types/struct/update_empty_row.test | 6 +- test/sql/types/test_all_types.test_slow | 4 +- test/sql/types/time/test_time_tz_collate.test | 249 + .../alternative_timestamp_casts.test | 48 + test/sql/types/timestamp/test_timestamp.test | 6 + .../types/timestamp/test_timestamp_types.test | 49 +- .../types/timestamp/timestamp_precision.test | 5 +- test/sql/update/test_cascading_updates.test | 71 + test/sql/update/test_multiple_assignment.test | 4 +- .../insert_or_replace/returning_nothing.test | 31 + test/sql/upsert/postgres/composite_key.test | 2 +- .../upsert_conflict_in_different_chunk.test | 41 + test/sql/upsert/upsert_lambda.test | 91 + test/sql/vacuum/test_analyze.test | 66 +- test/sql/vacuum/vacuum_nested_types.test | 4 +- test/sql/window/test_order_by_all.test | 16 + test/sql/window/test_streaming_lead_lag.test | 156 + test/sql/window/test_streaming_window.test | 92 +- .../test_streaming_window_distinct.test | 87 + test/sql/window/test_window_cse.test | 2 +- test/sql/window/test_window_fusion.test | 18 +- test/sqlite/result_helper.cpp | 81 +- test/sqlite/result_helper.hpp | 2 +- test/sqlite/select4.test_slow | 1 - test/sqlite/sqllogic_command.cpp | 95 +- test/sqlite/sqllogic_command.hpp | 11 +- test/sqlite/sqllogic_test_logger.cpp | 18 +- test/sqlite/sqllogic_test_logger.hpp | 8 +- test/sqlite/sqllogic_test_runner.cpp | 130 +- test/sqlite/sqllogic_test_runner.hpp | 2 +- test/sqlite/test_sqllogictest.cpp | 9 + test/sqlsmith/sql_reduce.test | 79 - third_party/CMakeLists.txt | 1 + third_party/brotli/LICENSE | 19 + third_party/brotli/VERSION | 1 + third_party/brotli/common/brotli_constants.h | 204 + third_party/brotli/common/brotli_platform.h | 543 + third_party/brotli/common/constants.cpp | 17 + third_party/brotli/common/context.cpp | 156 + third_party/brotli/common/context.h | 110 + third_party/brotli/common/dictionary.cpp | 5912 ++ third_party/brotli/common/dictionary.h | 60 + third_party/brotli/common/platform.cpp | 24 + .../brotli/common/shared_dictionary.cpp | 517 + .../common/shared_dictionary_internal.h | 71 + third_party/brotli/common/transform.cpp | 287 + third_party/brotli/common/transform.h | 77 + third_party/brotli/common/version.h | 51 + third_party/brotli/dec/bit_reader.cpp | 74 + third_party/brotli/dec/bit_reader.h | 419 + third_party/brotli/dec/decode.cpp | 2758 + third_party/brotli/dec/huffman.cpp | 338 + third_party/brotli/dec/huffman.h | 118 + third_party/brotli/dec/prefix.h | 733 + third_party/brotli/dec/state.cpp | 178 + third_party/brotli/dec/state.h | 386 + .../brotli/enc/backward_references.cpp | 3775 ++ third_party/brotli/enc/backward_references.h | 36 + .../brotli/enc/backward_references_hq.cpp | 935 + .../brotli/enc/backward_references_hq.h | 92 + third_party/brotli/enc/bit_cost.cpp | 410 + third_party/brotli/enc/bit_cost.h | 60 + third_party/brotli/enc/block_splitter.cpp | 1653 + third_party/brotli/enc/block_splitter.h | 48 + third_party/brotli/enc/brotli_bit_stream.cpp | 1431 + third_party/brotli/enc/brotli_bit_stream.h | 85 + third_party/brotli/enc/brotli_hash.h | 4352 ++ third_party/brotli/enc/brotli_params.h | 47 + third_party/brotli/enc/cluster.cpp | 1025 + third_party/brotli/enc/cluster.h | 1017 + third_party/brotli/enc/command.cpp | 24 + third_party/brotli/enc/command.h | 187 + .../brotli/enc/compound_dictionary.cpp | 209 + third_party/brotli/enc/compound_dictionary.h | 75 + third_party/brotli/enc/compress_fragment.cpp | 796 + third_party/brotli/enc/compress_fragment.h | 82 + .../brotli/enc/compress_fragment_two_pass.cpp | 653 + .../brotli/enc/compress_fragment_two_pass.h | 68 + third_party/brotli/enc/dictionary_hash.cpp | 1844 + third_party/brotli/enc/dictionary_hash.h | 21 + third_party/brotli/enc/encode.cpp | 1990 + third_party/brotli/enc/encoder_dict.cpp | 636 + third_party/brotli/enc/encoder_dict.h | 153 + third_party/brotli/enc/entropy_encode.cpp | 500 + third_party/brotli/enc/entropy_encode.h | 119 + .../brotli/enc/entropy_encode_static.h | 538 + third_party/brotli/enc/fast_log.cpp | 101 + third_party/brotli/enc/fast_log.h | 63 + third_party/brotli/enc/find_match_length.h | 68 + third_party/brotli/enc/histogram.cpp | 96 + third_party/brotli/enc/histogram.h | 210 + third_party/brotli/enc/literal_cost.cpp | 176 + third_party/brotli/enc/literal_cost.h | 28 + third_party/brotli/enc/memory.cpp | 190 + third_party/brotli/enc/memory.h | 127 + third_party/brotli/enc/metablock.cpp | 1225 + third_party/brotli/enc/metablock.h | 102 + third_party/brotli/enc/prefix.h | 50 + third_party/brotli/enc/quality.h | 202 + .../brotli/enc/resolve-multi-includes.py | 24 + third_party/brotli/enc/ringbuffer.h | 164 + third_party/brotli/enc/state.h | 106 + third_party/brotli/enc/static_dict.cpp | 538 + third_party/brotli/enc/static_dict.h | 37 + third_party/brotli/enc/static_dict_lut.h | 5862 ++ third_party/brotli/enc/utf8_util.cpp | 81 + third_party/brotli/enc/utf8_util.h | 29 + third_party/brotli/enc/write_bits.h | 84 + third_party/brotli/include/brotli/decode.h | 405 + third_party/brotli/include/brotli/encode.h | 489 + third_party/brotli/include/brotli/port.h | 238 + .../brotli/include/brotli/shared_dictionary.h | 96 + third_party/brotli/include/brotli/types.h | 83 + third_party/hyperloglog/hyperloglog.hpp | 4 + third_party/imdb/CMakeLists.txt | 2 +- third_party/libpg_query/CMakeLists.txt | 2 +- third_party/libpg_query/grammar/grammar.y | 2 + .../grammar/keywords/unreserved_keywords.list | 3 + .../libpg_query/grammar/statements.list | 1 + .../libpg_query/grammar/statements/explain.y | 1 + .../libpg_query/grammar/statements/load.y | 62 +- .../libpg_query/grammar/statements/select.y | 15 + .../grammar/statements/transaction.y | 16 +- .../grammar/statements/update_extensions.y | 22 + third_party/libpg_query/grammar/types/load.yh | 3 +- .../libpg_query/grammar/types/transaction.yh | 1 + .../libpg_query/include/nodes/nodes.hpp | 1 + .../libpg_query/include/nodes/parsenodes.hpp | 26 +- .../libpg_query/include/parser/gram.hpp | 1588 +- .../libpg_query/include/parser/kwlist.hpp | 3 + .../libpg_query/include/utils/datetime.hpp | 1 + third_party/libpg_query/pg_functions.cpp | 19 +- .../libpg_query/src_backend_parser_gram.cpp | 47340 ++++++++-------- .../libpg_query/src_backend_parser_scan.cpp | 837 +- third_party/re2/CMakeLists.txt | 4 +- third_party/re2/re2/compile.cc | 4 +- third_party/re2/re2/dfa.cc | 11 +- third_party/re2/re2/onepass.cc | 7 +- third_party/re2/re2/prog.cc | 24 +- third_party/re2/re2/prog.h | 16 +- third_party/snappy/snappy-stubs-internal.h | 7 + third_party/snowball/CMakeLists.txt | 2 +- third_party/tpce-tool/CMakeLists.txt | 2 +- third_party/utf8proc/include/utf8proc.hpp | 170 +- .../utf8proc/include/utf8proc_wrapper.hpp | 53 + third_party/utf8proc/utf8proc.cpp | 1305 +- third_party/utf8proc/utf8proc_data.cpp | 27876 ++++----- third_party/utf8proc/utf8proc_wrapper.cpp | 214 +- third_party/yyjson/CMakeLists.txt | 17 + third_party/yyjson/LICENSE | 21 + .../yyjson/include/yyjson.hpp | 2515 +- .../json => third_party}/yyjson/yyjson.cpp | 3794 +- tools/CMakeLists.txt | 3 - tools/jdbc/CMakeLists.txt | 44 - tools/jdbc/META-INF/services/java.sql.Driver | 1 - tools/jdbc/Makefile | 18 - tools/jdbc/README | 1 + tools/jdbc/README.md | 27 - tools/jdbc/duckdb_extension_config.cmake | 8 - tools/jdbc/generator.py | 28 - tools/jdbc/header2whatever.yaml | 8 - tools/jdbc/src/jni/duckdb_java.cpp | 1171 - tools/jdbc/src/jni/functions.cpp | 411 - tools/jdbc/src/jni/functions.cpp.template | 24 - tools/jdbc/src/jni/functions.hpp | 204 - tools/jdbc/src/jni/functions.hpp.template | 16 - .../main/java/org/duckdb/DuckDBAppender.java | 98 - .../src/main/java/org/duckdb/DuckDBArray.java | 90 - .../java/org/duckdb/DuckDBArrayResultSet.java | 1045 - .../java/org/duckdb/DuckDBColumnType.java | 39 - .../org/duckdb/DuckDBColumnTypeMetaData.java | 19 - .../java/org/duckdb/DuckDBConnection.java | 367 - .../org/duckdb/DuckDBDatabaseMetaData.java | 1253 - .../src/main/java/org/duckdb/DuckDBDate.java | 17 - .../main/java/org/duckdb/DuckDBDriver.java | 68 - .../main/java/org/duckdb/DuckDBNative.java | 171 - .../org/duckdb/DuckDBParameterMetaData.java | 71 - .../org/duckdb/DuckDBPreparedStatement.java | 943 - .../main/java/org/duckdb/DuckDBResultSet.java | 1301 - .../org/duckdb/DuckDBResultSetMetaData.java | 303 - .../main/java/org/duckdb/DuckDBStruct.java | 61 - .../main/java/org/duckdb/DuckDBTimestamp.java | 157 - .../java/org/duckdb/DuckDBTimestampTZ.java | 14 - .../main/java/org/duckdb/DuckDBVector.java | 593 - .../src/main/java/org/duckdb/JdbcUtils.java | 32 - .../src/main/java/org/duckdb/JsonNode.java | 49 - .../java/org/duckdb/StatementReturnType.java | 7 - .../main/java/org/duckdb/package-info.java | 9 - .../test/java/org/duckdb/TestDuckDBJDBC.java | 4252 -- .../java/org/duckdb/TestExtensionTypes.java | 53 - .../test/java/org/duckdb/test/Assertions.java | 82 - .../src/test/java/org/duckdb/test/Runner.java | 67 - .../test/java/org/duckdb/test/Thrower.java | 5 - tools/juliapkg/Project.toml | 4 +- tools/juliapkg/release.py | 8 +- tools/juliapkg/src/appender.jl | 10 +- tools/juliapkg/src/result.jl | 63 +- tools/juliapkg/test/test_all_types.jl | 2 +- tools/juliapkg/test/test_appender.jl | 22 +- tools/juliapkg/test/test_basic_queries.jl | 12 + tools/pythonpkg/MANIFEST.in | 4 +- tools/pythonpkg/duckdb-stubs/__init__.pyi | 162 +- tools/pythonpkg/duckdb/__init__.py | 763 +- .../experimental/spark/sql/dataframe.py | 9 +- .../experimental/spark/sql/functions.py | 723 +- .../duckdb/experimental/spark/sql/session.py | 18 +- .../duckdb/experimental/spark/sql/udf.py | 30 +- tools/pythonpkg/duckdb_python.cpp | 884 + tools/pythonpkg/pyproject.toml | 6 +- tools/pythonpkg/requirements-dev.txt | 9 +- tools/pythonpkg/scripts/cache_data.json | 41 +- .../pythonpkg/scripts/connection_methods.json | 11 +- .../scripts/connection_wrapper_methods.json | 109 +- .../generate_connection_wrapper_methods.py | 270 +- .../generate_connection_wrapper_stubs.py | 2 +- tools/pythonpkg/scripts/get_cpp_methods.py | 87 + tools/pythonpkg/scripts/imports.py | 7 + .../scripts/optional_requirements.py | 43 + tools/pythonpkg/src/CMakeLists.txt | 2 + .../src/arrow/arrow_array_stream.cpp | 8 +- tools/pythonpkg/src/dataframe.cpp | 12 + .../duckdb_python/expression/pyexpression.hpp | 1 + .../modules/collections_module.hpp | 46 + .../import_cache/modules/numpy_module.hpp | 5 + .../import_cache/modules/types_module.hpp | 4 +- .../import_cache/python_import_cache.hpp | 1 + .../python_import_cache_modules.hpp | 1 + .../duckdb_python/numpy/numpy_type.hpp | 1 + .../duckdb_python/pandas/pandas_analyzer.hpp | 11 +- .../duckdb_python/pybind11/dataframe.hpp | 1 + .../duckdb_python/pybind11/pybind_wrapper.hpp | 2 + .../pyconnection/pyconnection.hpp | 17 +- .../include/duckdb_python/pyfilesystem.hpp | 3 +- .../src/include/duckdb_python/pyrelation.hpp | 34 +- .../src/include/duckdb_python/pyresult.hpp | 2 +- .../duckdb_python/python_dependency.hpp | 25 + .../duckdb_python/python_replacement_scan.hpp | 16 + tools/pythonpkg/src/numpy/numpy_bind.cpp | 6 +- tools/pythonpkg/src/numpy/numpy_scan.cpp | 14 +- tools/pythonpkg/src/numpy/type.cpp | 8 +- tools/pythonpkg/src/pandas/analyzer.cpp | 57 +- tools/pythonpkg/src/pandas/bind.cpp | 3 +- tools/pythonpkg/src/pandas/scan.cpp | 22 +- tools/pythonpkg/src/path_like.cpp | 5 +- .../pythonpkg/src/pybind11/pybind_wrapper.cpp | 21 + tools/pythonpkg/src/pyconnection.cpp | 504 +- .../src/pyconnection/type_creation.cpp | 2 +- tools/pythonpkg/src/pyexpression.cpp | 21 + .../pythonpkg/src/pyexpression/initialize.cpp | 6 +- tools/pythonpkg/src/pyfilesystem.cpp | 9 + tools/pythonpkg/src/pyrelation.cpp | 43 +- tools/pythonpkg/src/pyrelation/initialize.cpp | 7 +- tools/pythonpkg/src/python_dependency.cpp | 23 + .../pythonpkg/src/python_replacement_scan.cpp | 201 + tools/pythonpkg/src/python_udf.cpp | 7 +- .../extensions/test_extensions_loading.py | 7 + .../fast/api/test_connection_interrupt.py | 8 +- .../tests/fast/api/test_duckdb_connection.py | 8 + .../tests/fast/api/test_duckdb_execute.py | 48 +- .../tests/fast/api/test_native_tz.py | 13 +- .../tests/fast/api/test_query_interrupt.py | 8 +- .../pythonpkg/tests/fast/api/test_read_csv.py | 53 +- .../tests/fast/api/test_streaming_result.py | 7 +- tools/pythonpkg/tests/fast/api/test_to_csv.py | 3 +- tools/pythonpkg/tests/fast/arrow/test_5547.py | 3 +- tools/pythonpkg/tests/fast/arrow/test_9443.py | 3 +- .../tests/fast/arrow/test_arrow_list.py | 110 +- .../arrow/test_arrow_recordbatchreader.py | 26 +- .../fast/arrow/test_arrow_run_end_encoding.py | 28 +- .../fast/arrow/test_arrow_string_view.py | 153 + .../tests/fast/arrow/test_filter_pushdown.py | 2 +- .../tests/fast/arrow/test_nested_arrow.py | 97 +- .../pythonpkg/tests/fast/arrow/test_polars.py | 7 + .../tests/fast/pandas/test_df_analyze.py | 16 +- .../fast/pandas/test_df_object_resolution.py | 5 + .../tests/fast/pandas/test_pandas_category.py | 12 + .../tests/fast/pandas/test_pandas_na.py | 19 +- .../tests/fast/pandas/test_pandas_object.py | 13 + .../tests/fast/pandas/test_stride.py | 37 + .../tests/fast/pandas/test_timedelta.py | 3 +- .../tests/fast/pandas/test_timestamp.py | 7 +- .../fast/relational_api/test_rapi_query.py | 22 +- .../relational_api/test_table_function.py | 17 + .../fast/spark/test_spark_drop_duplicates.py | 56 +- .../fast/spark/test_spark_functions_date.py | 140 + .../fast/spark/test_spark_functions_hash.py | 30 + .../fast/spark/test_spark_functions_null.py | 46 + ...ons.py => test_spark_functions_numeric.py} | 4 +- ...ions.py => test_spark_functions_string.py} | 4 +- .../tests/fast/spark/test_spark_join.py | 56 +- .../tests/fast/spark/test_spark_session.py | 20 +- .../tests/fast/spark/test_spark_udf.py | 13 + .../tests/fast/spark/test_spark_union.py | 18 +- .../tests/fast/test_alex_multithread.py | 10 +- tools/pythonpkg/tests/fast/test_all_types.py | 6 +- tools/pythonpkg/tests/fast/test_expression.py | 120 +- .../pythonpkg/tests/fast/test_memory_leaks.py | 5 +- .../pythonpkg/tests/fast/test_multithread.py | 24 +- tools/pythonpkg/tests/fast/test_pytorch.py | 9 +- tools/pythonpkg/tests/fast/test_relation.py | 206 + .../fast/test_relation_dependency_leak.py | 6 +- .../tests/fast/test_replacement_scan.py | 373 + .../tests/fast/test_runtime_error.py | 7 +- tools/pythonpkg/tests/fast/test_union.py | 69 + tools/pythonpkg/tests/fast/types/test_nan.py | 4 +- tools/shell/linenoise/highlighting.cpp | 36 +- .../shell/linenoise/include/highlighting.hpp | 2 +- tools/shell/linenoise/include/linenoise.hpp | 1 + tools/shell/linenoise/linenoise.cpp | 2 +- tools/shell/linenoise/rendering.cpp | 7 +- tools/shell/shell.c | 31 +- tools/shell/tests/test_http_logging.py | 38 + .../sqlite3_api_wrapper.cpp | 4 +- .../sqlite3_udf_api/include/cast_sqlite.hpp | 3 +- tools/swift/duckdb-swift/README.md | 2 +- .../DuckDBTests/TypeConversionTests.swift | 2 +- 2088 files changed, 195717 insertions(+), 94267 deletions(-) delete mode 100644 .github/patches/extensions/arrow/shared_ptr.patch delete mode 100644 .github/patches/extensions/aws/0001-update-tests.patch delete mode 100644 .github/patches/extensions/aws/shared_ptr.patch delete mode 100644 .github/patches/extensions/azure/shared_ptr.patch delete mode 100644 .github/patches/extensions/postgres_scanner/shared_ptr.patch delete mode 100644 .github/patches/extensions/sqlite_scanner/binder_update.patch create mode 100644 .github/patches/extensions/substrait/pushdown_semi_anti.patch delete mode 100644 .github/patches/extensions/substrait/shared_ptr.patch create mode 100644 .github/workflows/Android.yml delete mode 100644 .github/workflows/Java.yml delete mode 100644 .github/workflows/_extension_deploy.yml delete mode 100644 .github/workflows/_extension_distribution.yml create mode 100644 benchmark/micro/aggregate/any_value_uuid.benchmark create mode 100644 benchmark/micro/cte/stacked_materialized_cte.benchmark create mode 100644 benchmark/micro/distinct/distinct_on_pushdown.benchmark create mode 100644 benchmark/micro/filter/in_conversion.benchmark create mode 100644 benchmark/micro/join/hashjoin_dups_rhs.benchmark create mode 100644 benchmark/micro/list/list_min_max.benchmark create mode 100644 benchmark/micro/list/list_value.benchmark create mode 100644 benchmark/micro/optimizer/topn_optimization.benchmark create mode 100644 benchmark/micro/pushdown/window_partition_pushdown.benchmark create mode 100644 benchmark/micro/result_collection/batched_stream_query.benchmark create mode 100644 benchmark/micro/update/update_with_join.benchmark create mode 100644 benchmark/micro/window/streaming_lag.benchmark create mode 100644 data/csv/date_specificity.csv create mode 100644 data/csv/file_error.csv create mode 100644 data/csv/glob/f_1.csv create mode 100644 data/csv/glob/f_2.csv create mode 100644 data/csv/glob/f_3.csv create mode 100644 data/csv/headers/escaped_quote.csv create mode 100644 data/csv/headers/unescaped_quote.csv create mode 100644 data/csv/rejects/dr_who.csv create mode 100644 data/csv/special_date.csv create mode 100644 data/csv/test_default_option.csv create mode 100644 data/csv/test_default_option_2.csv create mode 100644 data/csv/test_ignore_errors.csv create mode 100644 data/csv/timestamp.csv create mode 100644 data/csv/union-by-name/type_mismatch/f_1.csv create mode 100644 data/csv/union-by-name/type_mismatch/f_2.csv create mode 100644 data/csv/weather.csv create mode 100644 data/json/12188.ndjson create mode 100644 data/json/map_50_50.jsonl create mode 100644 data/json/map_incompatible.jsonl create mode 100644 data/json/map_of_dates.jsonl create mode 100644 data/json/map_of_map.jsonl create mode 100644 data/json/map_of_mixed_date_timestamps.jsonl create mode 100644 data/json/map_of_nulls.jsonl create mode 100644 data/json/map_of_struct_with_nulls.jsonl create mode 100644 data/json/map_of_structs.jsonl create mode 100644 data/json/simple_map.jsonl create mode 100644 data/json/top_level_map.jsonl create mode 100644 data/parquet-testing/parquet_with_json.parquet create mode 100644 data/parquet-testing/timetz-nanos.parquet create mode 100644 data/storage/bc_0102.db.gz create mode 100644 data/storage/german_collation.db.gz create mode 100644 data/storage/huggingface_index.db.gz delete mode 100644 examples/jdbc/.gitignore delete mode 100644 examples/jdbc/DuckDBExample.java delete mode 100644 examples/jdbc/Makefile delete mode 100644 examples/jdbc/pom.xml create mode 100644 extension/delta/CMakeLists.txt create mode 100644 extension/delta/Makefile create mode 100644 extension/delta/README.md create mode 100644 extension/delta/extension_config.cmake create mode 100644 extension/delta/src/delta_extension.cpp create mode 100644 extension/delta/src/delta_functions.cpp create mode 100644 extension/delta/src/delta_utils.cpp create mode 100644 extension/delta/src/functions/delta_scan.cpp create mode 100644 extension/delta/src/include/delta_extension.hpp create mode 100644 extension/delta/src/include/delta_functions.hpp create mode 100644 extension/delta/src/include/delta_utils.hpp create mode 100644 extension/delta/src/include/functions/delta_scan.hpp create mode 100644 extension/delta/vcpkg.json delete mode 100644 extension/excel/CMakeLists.txt delete mode 100644 extension/excel/excel_config.py delete mode 100644 extension/excel/excel_extension.cpp delete mode 100644 extension/excel/numformat/CMakeLists.txt delete mode 100644 extension/excel/numformat/LICENSE delete mode 100644 extension/excel/numformat/include/nf_calendar.h delete mode 100644 extension/excel/numformat/include/nf_localedata.h delete mode 100644 extension/excel/numformat/include/nf_zformat.h delete mode 100644 extension/excel/numformat/nf_calendar.cpp delete mode 100644 extension/excel/numformat/nf_localedata.cpp delete mode 100644 extension/excel/numformat/nf_zformat.cpp create mode 100644 extension/httpfs/hffs.cpp create mode 100644 extension/httpfs/include/hffs.hpp create mode 100644 extension/jemalloc/jemalloc/README.md rename extension/jemalloc/jemalloc/include/jemalloc/internal/{jemalloc_int_inl_a.h => jemalloc_internal_inlines_a.h} (84%) rename extension/jemalloc/jemalloc/include/jemalloc/internal/{jemalloc_int_inl_b.h => jemalloc_internal_inlines_b.h} (93%) rename extension/jemalloc/jemalloc/include/jemalloc/internal/{jemalloc_int_inl_c.h => jemalloc_internal_inlines_c.h} (50%) create mode 100644 extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_overrides.h create mode 100644 extension/jemalloc/jemalloc/include/jemalloc/internal/private_namespace.gen.h create mode 100644 extension/jemalloc/jemalloc/include/jemalloc/internal/private_namespace.h create mode 100644 extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_internals.h create mode 100644 extension/jemalloc/jemalloc/include/msvc_compat/C99/stdbool.h create mode 100644 extension/jemalloc/jemalloc/include/msvc_compat/C99/stdint.h rename extension/jemalloc/jemalloc/src/{arena.cpp => arena.c} (86%) rename extension/jemalloc/jemalloc/src/{background_thread.cpp => background_thread.c} (94%) rename extension/jemalloc/jemalloc/src/{base.cpp => base.c} (72%) rename extension/jemalloc/jemalloc/src/{bin.cpp => bin.c} (96%) rename extension/jemalloc/jemalloc/src/{bin_info.cpp => bin_info.c} (94%) rename extension/jemalloc/jemalloc/src/{bitmap.cpp => bitmap.c} (98%) rename extension/jemalloc/jemalloc/src/{buf_writer.cpp => buf_writer.c} (96%) rename extension/jemalloc/jemalloc/src/{cache_bin.cpp => cache_bin.c} (57%) rename extension/jemalloc/jemalloc/src/{ckh.cpp => ckh.c} (99%) rename extension/jemalloc/jemalloc/src/{counter.cpp => counter.c} (93%) rename extension/jemalloc/jemalloc/src/{ctl.cpp => ctl.c} (92%) rename extension/jemalloc/jemalloc/src/{decay.cpp => decay.c} (99%) rename extension/jemalloc/jemalloc/src/{div.cpp => div.c} (92%) rename extension/jemalloc/jemalloc/src/{ecache.cpp => ecache.c} (93%) rename extension/jemalloc/jemalloc/src/{edata.cpp => edata.c} (79%) rename extension/jemalloc/jemalloc/src/{edata_cache.cpp => edata_cache.c} (98%) rename extension/jemalloc/jemalloc/src/{ehooks.cpp => ehooks.c} (95%) rename extension/jemalloc/jemalloc/src/{emap.cpp => emap.c} (98%) rename extension/jemalloc/jemalloc/src/{eset.cpp => eset.c} (99%) rename extension/jemalloc/jemalloc/src/{exp_grow.cpp => exp_grow.c} (79%) rename extension/jemalloc/jemalloc/src/{extent.cpp => extent.c} (97%) rename extension/jemalloc/jemalloc/src/{extent_dss.cpp => extent_dss.c} (92%) rename extension/jemalloc/jemalloc/src/{extent_mmap.cpp => extent_mmap.c} (93%) rename extension/jemalloc/jemalloc/src/{fxp.cpp => fxp.c} (94%) rename extension/jemalloc/jemalloc/src/{hook.cpp => hook.c} (97%) rename extension/jemalloc/jemalloc/src/{hpa.cpp => hpa.c} (96%) rename extension/jemalloc/jemalloc/src/{hpa_hooks.cpp => hpa_hooks.c} (93%) rename extension/jemalloc/jemalloc/src/{hpdata.cpp => hpdata.c} (98%) rename extension/jemalloc/jemalloc/src/{inspect.cpp => inspect.c} (97%) rename extension/jemalloc/jemalloc/src/{jemalloc.cpp => jemalloc.c} (88%) create mode 100644 extension/jemalloc/jemalloc/src/jemalloc_cpp.cpp rename extension/jemalloc/jemalloc/src/{large.cpp => large.c} (96%) rename extension/jemalloc/jemalloc/src/{log.cpp => log.c} (97%) rename extension/jemalloc/jemalloc/src/{malloc_io.cpp => malloc_io.c} (96%) rename extension/jemalloc/jemalloc/src/{mutex.cpp => mutex.c} (97%) rename extension/jemalloc/jemalloc/src/{nstime.cpp => nstime.c} (98%) rename extension/jemalloc/jemalloc/src/{pa.cpp => pa.c} (94%) rename extension/jemalloc/jemalloc/src/{pa_extra.cpp => pa_extra.c} (91%) rename extension/jemalloc/jemalloc/src/{pac.cpp => pac.c} (99%) rename extension/jemalloc/jemalloc/src/{pages.cpp => pages.c} (94%) rename extension/jemalloc/jemalloc/src/{pai.cpp => pai.c} (79%) rename extension/jemalloc/jemalloc/src/{peak_event.cpp => peak_event.c} (97%) rename extension/jemalloc/jemalloc/src/{prof.cpp => prof.c} (89%) rename extension/jemalloc/jemalloc/src/{prof_data.cpp => prof_data.c} (95%) rename extension/jemalloc/jemalloc/src/{prof_log.cpp => prof_log.c} (96%) rename extension/jemalloc/jemalloc/src/{prof_recent.cpp => prof_recent.c} (97%) rename extension/jemalloc/jemalloc/src/{prof_stats.cpp => prof_stats.c} (96%) rename extension/jemalloc/jemalloc/src/{prof_sys.cpp => prof_sys.c} (68%) rename extension/jemalloc/jemalloc/src/{psset.cpp => psset.c} (91%) rename extension/jemalloc/jemalloc/src/{rtree.cpp => rtree.c} (93%) rename extension/jemalloc/jemalloc/src/{safety_check.cpp => safety_check.c} (56%) rename extension/jemalloc/jemalloc/src/{san.cpp => san.c} (86%) rename extension/jemalloc/jemalloc/src/{san_bump.cpp => san_bump.c} (95%) rename extension/jemalloc/jemalloc/src/{sc.cpp => sc.c} (99%) rename extension/jemalloc/jemalloc/src/{sec.cpp => sec.c} (98%) rename extension/jemalloc/jemalloc/src/{stats.cpp => stats.c} (94%) rename extension/jemalloc/jemalloc/src/{sz.cpp => sz.c} (96%) rename extension/jemalloc/jemalloc/src/{tcache.cpp => tcache.c} (68%) rename extension/jemalloc/jemalloc/src/{test_hooks.cpp => test_hooks.c} (60%) rename extension/jemalloc/jemalloc/src/{thread_event.cpp => thread_event.c} (99%) rename extension/jemalloc/jemalloc/src/{ticker.cpp => ticker.c} (95%) rename extension/jemalloc/jemalloc/src/{tsd.cpp => tsd.c} (93%) create mode 100644 extension/jemalloc/jemalloc/src/util.c rename extension/jemalloc/jemalloc/src/{witness.cpp => witness.c} (95%) create mode 100644 extension/jemalloc/jemalloc/src/zone.c delete mode 100644 extension/json/yyjson/CMakeLists.txt create mode 100644 extension/parquet/geo_parquet.cpp create mode 100644 extension/parquet/include/expression_column_reader.hpp create mode 100644 extension/parquet/include/geo_parquet.hpp delete mode 100644 extension/sqlsmith/CMakeLists.txt delete mode 100644 extension/sqlsmith/fuzzyduck.cpp delete mode 100644 extension/sqlsmith/include/fuzzyduck.hpp delete mode 100644 extension/sqlsmith/include/statement_generator.hpp delete mode 100644 extension/sqlsmith/include/statement_simplifier.hpp delete mode 100644 extension/sqlsmith/sqlsmith_extension.cpp delete mode 100644 extension/sqlsmith/statement_generator.cpp delete mode 100644 extension/sqlsmith/statement_simplifier.cpp delete mode 100644 extension/sqlsmith/third_party/CMakeLists.txt delete mode 100644 extension/sqlsmith/third_party/sqlsmith/CMakeLists.txt delete mode 100644 extension/sqlsmith/third_party/sqlsmith/duckdb.cc delete mode 100644 extension/sqlsmith/third_party/sqlsmith/dump.cc delete mode 100644 extension/sqlsmith/third_party/sqlsmith/expr.cc delete mode 100644 extension/sqlsmith/third_party/sqlsmith/grammar.cc delete mode 100644 extension/sqlsmith/third_party/sqlsmith/impedance.cc delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/duckdb.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/dump.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/dut.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/expr.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/grammar.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/impedance.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/log.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/prod.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/random.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/relmodel.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/schema.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/sqlsmith.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/include/util.hh delete mode 100644 extension/sqlsmith/third_party/sqlsmith/log.cc delete mode 100644 extension/sqlsmith/third_party/sqlsmith/prod.cc delete mode 100644 extension/sqlsmith/third_party/sqlsmith/random.cc delete mode 100644 extension/sqlsmith/third_party/sqlsmith/relmodel.cc delete mode 100644 extension/sqlsmith/third_party/sqlsmith/schema.cc delete mode 100644 extension/sqlsmith/third_party/sqlsmith/sqlsmith.cc create mode 100644 scripts/generate_storage_info.py delete mode 100644 scripts/jdbc_maven_deploy.py create mode 100755 scripts/run_extension_medata_tests.sh create mode 100644 src/catalog/catalog_entry_retriever.cpp create mode 100644 src/catalog/default/default_generator.cpp create mode 100644 src/catalog/default/default_table_functions.cpp create mode 100644 src/common/multi_file_list.cpp create mode 100644 src/core_functions/aggregate/holistic/mad.cpp create mode 100644 src/core_functions/aggregate/nested/binned_histogram.cpp create mode 100644 src/core_functions/scalar/generic/can_implicitly_cast.cpp create mode 100644 src/execution/index/bound_index.cpp create mode 100644 src/execution/index/unbound_index.cpp delete mode 100644 src/execution/index/unknown_index.cpp create mode 100644 src/execution/operator/helper/physical_buffered_batch_collector.cpp create mode 100644 src/execution/operator/helper/physical_update_extensions.cpp create mode 100644 src/function/copy_function.cpp create mode 100644 src/function/scalar/generic/binning.cpp delete mode 100644 src/function/scalar/list/list_concat.cpp create mode 100644 src/function/scalar/string/concat_ws.cpp create mode 100644 src/function/table/arrow/arrow_type_info.cpp create mode 100644 src/function/table/query_function.cpp create mode 100644 src/include/duckdb/catalog/catalog_entry_retriever.hpp create mode 100644 src/include/duckdb/catalog/default/default_table_functions.hpp create mode 100644 src/include/duckdb/common/arrow/appender/list_view_data.hpp rename src/include/duckdb/common/{enable_shared_from_this.ipp => enable_shared_from_this_ipp.hpp} (100%) create mode 100644 src/include/duckdb/common/enums/checkpoint_type.hpp rename extension/excel/include/excel_extension.hpp => src/include/duckdb/common/enums/copy_overwrite_mode.hpp (50%) rename extension/sqlsmith/include/sqlsmith_extension.hpp => src/include/duckdb/common/enums/scan_vector_type.hpp (61%) create mode 100644 src/include/duckdb/common/insertion_order_preserving_map.hpp create mode 100644 src/include/duckdb/common/multi_file_list.hpp create mode 100644 src/include/duckdb/common/optionally_owned_ptr.hpp create mode 100644 src/include/duckdb/common/owning_string_map.hpp rename src/include/duckdb/common/{shared_ptr.ipp => shared_ptr_ipp.hpp} (100%) create mode 100644 src/include/duckdb/common/type_visitor.hpp create mode 100644 src/include/duckdb/common/types/arrow_string_view_type.hpp create mode 100644 src/include/duckdb/common/types/date_lookup_cache.hpp rename src/include/duckdb/common/{weak_ptr.ipp => weak_ptr_ipp.hpp} (100%) create mode 100644 src/include/duckdb/core_functions/aggregate/histogram_helpers.hpp create mode 100644 src/include/duckdb/core_functions/aggregate/quantile_helpers.hpp create mode 100644 src/include/duckdb/core_functions/aggregate/quantile_sort_tree.hpp create mode 100644 src/include/duckdb/core_functions/aggregate/quantile_state.hpp create mode 100644 src/include/duckdb/core_functions/aggregate/sort_key_helpers.hpp create mode 100644 src/include/duckdb/core_functions/create_sort_key.hpp create mode 100644 src/include/duckdb/execution/ht_entry.hpp create mode 100644 src/include/duckdb/execution/index/bound_index.hpp create mode 100644 src/include/duckdb/execution/index/unbound_index.hpp delete mode 100644 src/include/duckdb/execution/index/unknown_index.hpp create mode 100644 src/include/duckdb/execution/operator/helper/physical_buffered_batch_collector.hpp create mode 100644 src/include/duckdb/execution/operator/helper/physical_update_extensions.hpp create mode 100644 src/include/duckdb/function/table/arrow/arrow_type_info.hpp create mode 100644 src/include/duckdb/function/table/arrow/enum/arrow_datetime_type.hpp create mode 100644 src/include/duckdb/function/table/arrow/enum/arrow_type_info_type.hpp create mode 100644 src/include/duckdb/function/table/arrow/enum/arrow_variable_size_type.hpp create mode 100644 src/include/duckdb/logging/http_logger.hpp create mode 100644 src/include/duckdb/main/buffered_data/batched_buffered_data.hpp create mode 100644 src/include/duckdb/main/client_context_wrapper.hpp create mode 100644 src/include/duckdb/main/extension_install_info.hpp create mode 100644 src/include/duckdb/main/profiling_info.hpp create mode 100644 src/include/duckdb/main/relation/materialized_relation.hpp create mode 100644 src/include/duckdb/optimizer/build_probe_side_optimizer.hpp delete mode 100644 src/include/duckdb/optimizer/join_order/estimated_properties.hpp create mode 100644 src/include/duckdb/optimizer/limit_pushdown.hpp create mode 100644 src/include/duckdb/optimizer/rule/join_dependent_filter.hpp create mode 100644 src/include/duckdb/optimizer/rule/timestamp_comparison.hpp create mode 100644 src/include/duckdb/parser/parsed_data/update_extensions_info.hpp create mode 100644 src/include/duckdb/parser/statement/update_extensions_statement.hpp create mode 100644 src/include/duckdb/parser/tableref/column_data_ref.hpp create mode 100644 src/include/duckdb/planner/collation_binding.hpp create mode 100644 src/include/duckdb/planner/tableref/bound_column_data_ref.hpp create mode 100644 src/include/duckdb/storage/serialization/dependency.json create mode 100644 src/include/duckdb/storage/serialization/extension_install_info.json create mode 100644 src/include/duckdb/transaction/wal_write_state.hpp create mode 100644 src/main/buffered_data/batched_buffered_data.cpp create mode 100644 src/main/buffered_data/buffered_data.cpp create mode 100644 src/main/capi/scalar_function-c.cpp create mode 100644 src/main/capi/table_description-c.cpp create mode 100644 src/main/client_config.cpp create mode 100644 src/main/client_context_wrapper.cpp create mode 100644 src/main/extension_install_info.cpp create mode 100644 src/main/profiling_info.cpp create mode 100644 src/main/relation/materialized_relation.cpp create mode 100644 src/optimizer/build_probe_side_optimizer.cpp delete mode 100644 src/optimizer/join_order/estimated_properties.cpp create mode 100644 src/optimizer/limit_pushdown.cpp create mode 100644 src/optimizer/pushdown/pushdown_window.cpp create mode 100644 src/optimizer/rule/join_dependent_filter.cpp create mode 100644 src/optimizer/rule/timestamp_comparison.cpp create mode 100644 src/parser/parsed_data/copy_info.cpp create mode 100644 src/parser/parsed_data/load_info.cpp create mode 100644 src/parser/parsed_data/pragma_info.cpp create mode 100644 src/parser/statement/update_extensions_statement.cpp create mode 100644 src/parser/tableref/column_data_ref.cpp create mode 100644 src/planner/binder/expression/bind_unpacked_star_expression.cpp create mode 100644 src/planner/binder/statement/bind_update_extensions.cpp create mode 100644 src/planner/binder/tableref/bind_column_data_ref.cpp create mode 100644 src/planner/binder/tableref/plan_column_data_ref.cpp create mode 100644 src/planner/collation_binding.cpp create mode 100644 src/storage/serialization/serialize_dependency.cpp create mode 100644 src/storage/serialization/serialize_extension_install_info.cpp create mode 100644 src/storage/version_map.json create mode 100644 src/transaction/wal_write_state.cpp create mode 100644 test/api/capi/capi_scalar_functions.cpp create mode 100644 test/api/capi/test_capi_table_description.cpp create mode 100644 test/api/capi/test_without_disabled_functions.cpp create mode 100644 test/extension/duckdb_extensions.test create mode 100644 test/extension/install_extension.test create mode 100644 test/extension/install_version.test create mode 100644 test/extension/test_custom_type_modifier.test_slow create mode 100644 test/extension/test_tags.test create mode 100644 test/extension/update_extensions.test create mode 100644 test/extension/update_extensions_ci.test create mode 100644 test/fuzzer/duckfuzz/array_const_columndatacopy.test create mode 100644 test/fuzzer/duckfuzz/array_distance.test create mode 100644 test/fuzzer/duckfuzz/array_slice_nullness.test create mode 100644 test/fuzzer/duckfuzz/create_sort_key_strings.test delete mode 100644 test/fuzzer/duckfuzz/duckfuzz_tests/test_duckfuzz.test create mode 100644 test/fuzzer/duckfuzz/repeat_wrong_number.test create mode 100644 test/fuzzer/duckfuzz/try_cast_string_to_list.test_slow create mode 100644 test/fuzzer/duckfuzz/tuple_data_empty_heap.test create mode 100644 test/fuzzer/duckfuzz/vector_type.test create mode 100644 test/fuzzer/pedro/view_not_rebound_error_no_view_dependencies.test create mode 100644 test/issues/general/test_11566.test rename test/issues/general/{test_9399.test => test_9399.test_slow} (93%) create mode 100644 test/optimizer/column_lifetime_analyzer/must_visit_operator_expressions_first.test create mode 100644 test/optimizer/issue_12181.test create mode 100644 test/optimizer/join_dependent_filter.test rename test/optimizer/joins/{many_joins_and_one_non_reorderable_join.test => many_joins_and_one_non_reorderable_join.test_slow} (97%) create mode 100644 test/optimizer/joins/pushdown_semi_anti.test rename test/optimizer/joins/{update_nodes_in_full_path.test => update_nodes_in_full_path.test_slow} (95%) rename test/optimizer/joins/{updating_the_join_node_hash_map_has_no_errors.test => updating_the_join_node_hash_map_has_no_errors.test_slow} (98%) create mode 100644 test/optimizer/limit_pushdown.test create mode 100644 test/optimizer/prefer_final_projected_columns_on_probe_side.test create mode 100644 test/optimizer/pushdown/pushdown_in_to_parquet.test create mode 100644 test/optimizer/pushdown/pushdown_window_partition_filter.test create mode 100644 test/optimizer/pushdown/timestamp_to_date_pushdown.test rename test/optimizer/{unnest_rewriter.test => unnest_rewriter.test_slow} (99%) create mode 100644 test/optimizer/unused_columns/distinct_on_projection_pushdown.test create mode 100644 test/parquet/test_filename_column.test create mode 100644 test/sql/aggregate/aggregates/arg_min_max_all_types.test_slow create mode 100644 test/sql/aggregate/aggregates/binning.test create mode 100644 test/sql/aggregate/aggregates/first_test_all_types.test_slow create mode 100644 test/sql/aggregate/aggregates/histogram_table_function.test create mode 100644 test/sql/aggregate/aggregates/histogram_test_all_types.test_slow create mode 100644 test/sql/aggregate/aggregates/histogram_tpch.test_slow create mode 100644 test/sql/aggregate/aggregates/mode_test_all_types.test_slow create mode 100644 test/sql/aggregate/aggregates/mode_tpch.test_slow create mode 100644 test/sql/aggregate/aggregates/quantile_test_all_types.test_slow rename test/sql/aggregate/aggregates/{test_arg_min_max_nested.test => test_arg_min_max_nested.test_slow} (99%) rename test/sql/aggregate/aggregates/{test_arg_min_max_null_nested.test => test_arg_min_max_null_nested.test_slow} (99%) rename test/sql/aggregate/aggregates/{test_arg_min_max_null_strings.test => test_arg_min_max_null_strings.test_slow} (99%) create mode 100644 test/sql/aggregate/aggregates/test_binned_histogram.test rename test/sql/aggregate/distinct/grouped/{distinct_and_non_distinct_mixed.test => distinct_and_non_distinct_mixed.test_slow} (99%) create mode 100644 test/sql/aggregate/qualify/test_qualify_view_no_view_dependencies.test create mode 100644 test/sql/attach/attach_create_index.test create mode 100644 test/sql/attach/attach_custom_block_size.test create mode 100644 test/sql/attach/attach_huggingface_index.test create mode 100644 test/sql/attach/attach_icu_collation.test create mode 100644 test/sql/attach/attach_read_only_transaction.test create mode 100644 test/sql/attach/attach_remote.test create mode 100644 test/sql/attach/attach_wal_alter.test rename test/sql/cast/{string_to_map_cast.test => string_to_map_cast.test_slow} (99%) create mode 100644 test/sql/catalog/dependencies/add_column_to_table_referenced_by_fk.test create mode 100644 test/sql/catalog/dependencies/add_column_to_table_referenced_by_macro.test create mode 100644 test/sql/catalog/dependencies/add_column_to_table_referenced_by_view.test create mode 100644 test/sql/catalog/dependencies/change_type_of_table_column_referenced_by_index.test create mode 100644 test/sql/catalog/dependencies/remove_table_column_referenced_by_index.test create mode 100644 test/sql/catalog/dependencies/rename_table_column_referenced_by_index.test create mode 100644 test/sql/catalog/dependencies/rename_view_referenced_by_table_macro.test create mode 100644 test/sql/catalog/dependencies/set_default_of_table_column_referenced_by_index.test create mode 100644 test/sql/catalog/function/query_function.test create mode 100644 test/sql/catalog/function/test_cross_catalog_macros.test create mode 100644 test/sql/catalog/function/test_macro_default_arg_with_dependencies.test create mode 100644 test/sql/catalog/function/test_recursive_macro_no_dependency.test create mode 100644 test/sql/catalog/view/recursive_view_with_dependencies.test create mode 100644 test/sql/catalog/view/test_view_schema_change_with_dependencies.test create mode 100644 test/sql/catalog/view/test_view_sql_with_dependencies.test create mode 100644 test/sql/collate/test_collate_and_grouping_sets.test create mode 100644 test/sql/constraints/foreignkey/test_fk_alter.test rename test/sql/copy/csv/rejects/{csv_buffer_size_rejects.test => csv_buffer_size_rejects.test_slow} (74%) create mode 100644 test/sql/copy/csv/test_11840.test create mode 100644 test/sql/copy/csv/test_12314.test_slow delete mode 100644 test/sql/copy/csv/test_bug_9952.test create mode 100644 test/sql/copy/csv/test_bug_9952.test_slow create mode 100644 test/sql/copy/csv/test_headers_12089.test create mode 100644 test/sql/copy/csv/test_insert_into_types.test create mode 100644 test/sql/copy/csv/test_lineitem_gz.test rename test/sql/copy/csv/{test_mixed_lines.test => test_mixed_lines.test_slow} (99%) create mode 100644 test/sql/copy/csv/test_partition_compression.test create mode 100644 test/sql/copy/csv/test_quote_default.test create mode 100644 test/sql/copy/csv/test_skip.test_slow rename test/sql/copy/{hive_types.test => hive_types.test_slow} (95%) create mode 100644 test/sql/copy/parquet/broken/broken_structure.parquet create mode 100644 test/sql/copy/partitioned/hive_partition_append.test create mode 100644 test/sql/copy/return_files.test create mode 100644 test/sql/copy/row_groups_per_file.test create mode 100644 test/sql/copy/row_groups_per_file_large.test_slow create mode 100644 test/sql/copy_database/copy_database_index.test create mode 100644 test/sql/create/create_as_issue_11968.test create mode 100644 test/sql/cte/materialized/materialized_cte_prepared.test create mode 100644 test/sql/delete/large_deletes_transactions.test delete mode 100644 test/sql/excel/test_excel_numformat.test create mode 100644 test/sql/extensions/description_is_valid.test create mode 100644 test/sql/fts/issue_12330.test create mode 100644 test/sql/function/array/array_and_map.test create mode 100644 test/sql/function/generic/can_cast_implicitly.test create mode 100644 test/sql/function/list/aggregates/minmax_all_types.test_slow create mode 100644 test/sql/function/list/aggregates/minmax_nested.test rename test/sql/function/list/lambdas/{reduce.test => reduce.test_slow} (99%) rename test/sql/function/list/{list_grade_up.test => list_grade_up.test_slow} (98%) rename test/sql/function/list/{list_select.test => list_select.test_slow} (97%) create mode 100644 test/sql/function/string/test_concat_binding.test create mode 100644 test/sql/function/timestamp/test_strftime_timestamp_ns.test create mode 100644 test/sql/httpfs/hffs.test create mode 100644 test/sql/httpfs/hffs.test_slow rename test/sql/index/art/vacuum/{test_art_vacuum.test => test_art_vacuum.test_slow} (93%) rename test/sql/insert/{insert_non_order_preserving.test => insert_non_order_preserving.test_slow} (95%) rename test/sql/join/inner/{test_join_perfect_hash.test => test_join_perfect_hash.test_slow} (98%) rename test/sql/join/{test_nested_payloads.test => test_nested_payloads.test_slow} (99%) create mode 100644 test/sql/json/issues/issue11804.test create mode 100644 test/sql/json/issues/issue12188.test create mode 100644 test/sql/optimizer/expression/test_timestamp_offset.test create mode 100644 test/sql/order/issue_11936.test create mode 100644 test/sql/parallelism/interquery/concurrent_append_metadata_queries.test_slow create mode 100644 test/sql/parallelism/interquery/concurrent_force_checkpoint.test create mode 100644 test/sql/parallelism/interquery/concurrent_index_scans_while_appending.test create mode 100644 test/sql/parallelism/interquery/concurrent_mix_operations.test_slow create mode 100644 test/sql/parallelism/interquery/concurrent_reads_append_list.test_slow create mode 100644 test/sql/parallelism/interquery/concurrent_reads_while_altering.test create mode 100644 test/sql/parallelism/interquery/concurrent_reads_while_appending.test_slow create mode 100644 test/sql/parallelism/interquery/concurrent_reads_while_appending_nulls.test_slow create mode 100644 test/sql/parallelism/interquery/concurrent_reads_while_renaming.test create mode 100644 test/sql/parallelism/interquery/concurrent_reads_while_updating.test_slow create mode 100644 test/sql/parallelism/interquery/tpch_concurrent_operations.test_slow create mode 100644 test/sql/parser/dollar_quotes_internal_issue2224.test create mode 100644 test/sql/parser/test_columns_unpacked.test create mode 100644 test/sql/pg_catalog/pg_type.test create mode 100644 test/sql/pivot/pivot_struct_aggregate.test create mode 100644 test/sql/pragma/not_a_valid.json create mode 100644 test/sql/pragma/test_custom_profiling_settings.test create mode 100644 test/sql/pragma/test_enable_http_logging.test rename test/sql/sample/{same_seed_same_sample.test => same_seed_same_sample.test_slow} (94%) create mode 100644 test/sql/secrets/create_secret_hffs.test create mode 100644 test/sql/secrets/create_secret_hffs_autoload.test create mode 100644 test/sql/storage/bc/internal_schemas_0102.test create mode 100644 test/sql/storage/catalog/test_view_storage_no_view_dependencies.test rename test/sql/storage/compression/alp/{alp_many_segments.test => alp_many_segments.test_slow} (94%) rename test/sql/storage/compression/alp/{alp_many_segments_float.test => alp_many_segments_float.test_slow} (99%) rename test/sql/storage/compression/alp/{alp_middle_flush.test => alp_middle_flush.test_slow} (94%) rename test/sql/storage/compression/alprd/{alprd_many_segments.test => alprd_many_segments.test_slow} (99%) rename test/sql/storage/compression/alprd/{alprd_many_segments_float.test => alprd_many_segments_float.test_slow} (98%) rename test/sql/storage/compression/alprd/{alprd_middle_flush.test => alprd_middle_flush.test_slow} (99%) rename test/sql/storage/compression/chimp/{chimp_read.test => chimp_read.test_slow} (93%) rename test/sql/storage/compression/patas/{patas_read.test => patas_read.test_slow} (93%) rename test/sql/storage/compression/string/{null.test => null.test_slow} (96%) delete mode 100644 test/sql/storage/force_checkpoint_abort.test create mode 100644 test/sql/storage/icu_collation.test rename test/sql/storage/{list_dictionary.test => list_dictionary.test_slow} (97%) create mode 100644 test/sql/storage/relocate_metadata.test_slow rename test/sql/storage/{test_purge_queue.test => test_purge_queue.test_slow} (91%) create mode 100644 test/sql/storage/wal/wal_create_insert_drop.test create mode 100644 test/sql/storage/wal/wal_lazy_creation.test create mode 100644 test/sql/storage/wal/wal_view_explicit_aliases_no_view_dependencies.test create mode 100644 test/sql/storage/wal/wal_view_storage_no_view_dependencies.test create mode 100644 test/sql/subquery/exists/test_exists_union_by_name.test create mode 100644 test/sql/subquery/lateral/lateral_binding_views.test create mode 100644 test/sql/subquery/scalar/nested_subquery_window.test create mode 100644 test/sql/subquery/scalar/test_correlated_window.test rename test/sql/table_function/{duckdb_functions.test => duckdb_functions.test_slow} (93%) create mode 100644 test/sql/table_function/range_function_lateral.test create mode 100644 test/sql/transactions/test_read_only_transactions.test create mode 100644 test/sql/types/date/date_implicit_cast.test rename test/sql/types/enum/{test_enum_from_query.test => test_enum_from_query.test_slow} (97%) rename test/sql/types/list/{unnest_many_empty_lists.test => unnest_many_empty_lists.test_slow} (82%) rename test/sql/types/nested/array/{array_sort.test => array_sort.test_slow} (95%) rename test/sql/types/nested/array/{array_storage_2.test => array_storage_2.test_slow} (88%) create mode 100644 test/sql/types/nested/map/test_null_map_interaction.test create mode 100644 test/sql/types/time/test_time_tz_collate.test create mode 100644 test/sql/update/test_cascading_updates.test create mode 100644 test/sql/upsert/insert_or_replace/returning_nothing.test create mode 100644 test/sql/upsert/upsert_conflict_in_different_chunk.test create mode 100644 test/sql/upsert/upsert_lambda.test create mode 100644 test/sql/window/test_order_by_all.test create mode 100644 test/sql/window/test_streaming_lead_lag.test create mode 100644 test/sql/window/test_streaming_window_distinct.test delete mode 100644 test/sqlsmith/sql_reduce.test create mode 100644 third_party/brotli/LICENSE create mode 100644 third_party/brotli/VERSION create mode 100644 third_party/brotli/common/brotli_constants.h create mode 100644 third_party/brotli/common/brotli_platform.h create mode 100644 third_party/brotli/common/constants.cpp create mode 100644 third_party/brotli/common/context.cpp create mode 100644 third_party/brotli/common/context.h create mode 100644 third_party/brotli/common/dictionary.cpp create mode 100644 third_party/brotli/common/dictionary.h create mode 100644 third_party/brotli/common/platform.cpp create mode 100644 third_party/brotli/common/shared_dictionary.cpp create mode 100644 third_party/brotli/common/shared_dictionary_internal.h create mode 100644 third_party/brotli/common/transform.cpp create mode 100644 third_party/brotli/common/transform.h create mode 100644 third_party/brotli/common/version.h create mode 100644 third_party/brotli/dec/bit_reader.cpp create mode 100644 third_party/brotli/dec/bit_reader.h create mode 100644 third_party/brotli/dec/decode.cpp create mode 100644 third_party/brotli/dec/huffman.cpp create mode 100644 third_party/brotli/dec/huffman.h create mode 100644 third_party/brotli/dec/prefix.h create mode 100644 third_party/brotli/dec/state.cpp create mode 100644 third_party/brotli/dec/state.h create mode 100644 third_party/brotli/enc/backward_references.cpp create mode 100644 third_party/brotli/enc/backward_references.h create mode 100644 third_party/brotli/enc/backward_references_hq.cpp create mode 100644 third_party/brotli/enc/backward_references_hq.h create mode 100644 third_party/brotli/enc/bit_cost.cpp create mode 100644 third_party/brotli/enc/bit_cost.h create mode 100644 third_party/brotli/enc/block_splitter.cpp create mode 100644 third_party/brotli/enc/block_splitter.h create mode 100644 third_party/brotli/enc/brotli_bit_stream.cpp create mode 100644 third_party/brotli/enc/brotli_bit_stream.h create mode 100644 third_party/brotli/enc/brotli_hash.h create mode 100644 third_party/brotli/enc/brotli_params.h create mode 100644 third_party/brotli/enc/cluster.cpp create mode 100644 third_party/brotli/enc/cluster.h create mode 100644 third_party/brotli/enc/command.cpp create mode 100644 third_party/brotli/enc/command.h create mode 100644 third_party/brotli/enc/compound_dictionary.cpp create mode 100644 third_party/brotli/enc/compound_dictionary.h create mode 100644 third_party/brotli/enc/compress_fragment.cpp create mode 100644 third_party/brotli/enc/compress_fragment.h create mode 100644 third_party/brotli/enc/compress_fragment_two_pass.cpp create mode 100644 third_party/brotli/enc/compress_fragment_two_pass.h create mode 100644 third_party/brotli/enc/dictionary_hash.cpp create mode 100644 third_party/brotli/enc/dictionary_hash.h create mode 100644 third_party/brotli/enc/encode.cpp create mode 100644 third_party/brotli/enc/encoder_dict.cpp create mode 100644 third_party/brotli/enc/encoder_dict.h create mode 100644 third_party/brotli/enc/entropy_encode.cpp create mode 100644 third_party/brotli/enc/entropy_encode.h create mode 100644 third_party/brotli/enc/entropy_encode_static.h create mode 100644 third_party/brotli/enc/fast_log.cpp create mode 100644 third_party/brotli/enc/fast_log.h create mode 100644 third_party/brotli/enc/find_match_length.h create mode 100644 third_party/brotli/enc/histogram.cpp create mode 100644 third_party/brotli/enc/histogram.h create mode 100644 third_party/brotli/enc/literal_cost.cpp create mode 100644 third_party/brotli/enc/literal_cost.h create mode 100644 third_party/brotli/enc/memory.cpp create mode 100644 third_party/brotli/enc/memory.h create mode 100644 third_party/brotli/enc/metablock.cpp create mode 100644 third_party/brotli/enc/metablock.h create mode 100644 third_party/brotli/enc/prefix.h create mode 100644 third_party/brotli/enc/quality.h create mode 100755 third_party/brotli/enc/resolve-multi-includes.py create mode 100644 third_party/brotli/enc/ringbuffer.h create mode 100644 third_party/brotli/enc/state.h create mode 100644 third_party/brotli/enc/static_dict.cpp create mode 100644 third_party/brotli/enc/static_dict.h create mode 100644 third_party/brotli/enc/static_dict_lut.h create mode 100644 third_party/brotli/enc/utf8_util.cpp create mode 100644 third_party/brotli/enc/utf8_util.h create mode 100644 third_party/brotli/enc/write_bits.h create mode 100644 third_party/brotli/include/brotli/decode.h create mode 100644 third_party/brotli/include/brotli/encode.h create mode 100644 third_party/brotli/include/brotli/port.h create mode 100644 third_party/brotli/include/brotli/shared_dictionary.h create mode 100644 third_party/brotli/include/brotli/types.h create mode 100644 third_party/libpg_query/grammar/statements/update_extensions.y create mode 100644 third_party/libpg_query/grammar/types/transaction.yh create mode 100644 third_party/yyjson/CMakeLists.txt create mode 100644 third_party/yyjson/LICENSE rename {extension/json => third_party}/yyjson/include/yyjson.hpp (70%) rename {extension/json => third_party}/yyjson/yyjson.cpp (77%) delete mode 100644 tools/jdbc/CMakeLists.txt delete mode 100644 tools/jdbc/META-INF/services/java.sql.Driver delete mode 100644 tools/jdbc/Makefile create mode 100644 tools/jdbc/README delete mode 100644 tools/jdbc/README.md delete mode 100644 tools/jdbc/duckdb_extension_config.cmake delete mode 100644 tools/jdbc/generator.py delete mode 100644 tools/jdbc/header2whatever.yaml delete mode 100644 tools/jdbc/src/jni/duckdb_java.cpp delete mode 100644 tools/jdbc/src/jni/functions.cpp delete mode 100644 tools/jdbc/src/jni/functions.cpp.template delete mode 100644 tools/jdbc/src/jni/functions.hpp delete mode 100644 tools/jdbc/src/jni/functions.hpp.template delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBAppender.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBArray.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBArrayResultSet.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBColumnType.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBColumnTypeMetaData.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBConnection.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBDatabaseMetaData.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBDate.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBDriver.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBNative.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBParameterMetaData.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBPreparedStatement.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBResultSet.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBResultSetMetaData.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBStruct.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBTimestamp.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBTimestampTZ.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/DuckDBVector.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/JdbcUtils.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/JsonNode.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/StatementReturnType.java delete mode 100644 tools/jdbc/src/main/java/org/duckdb/package-info.java delete mode 100644 tools/jdbc/src/test/java/org/duckdb/TestDuckDBJDBC.java delete mode 100644 tools/jdbc/src/test/java/org/duckdb/TestExtensionTypes.java delete mode 100644 tools/jdbc/src/test/java/org/duckdb/test/Assertions.java delete mode 100644 tools/jdbc/src/test/java/org/duckdb/test/Runner.java delete mode 100644 tools/jdbc/src/test/java/org/duckdb/test/Thrower.java create mode 100644 tools/pythonpkg/scripts/get_cpp_methods.py create mode 100644 tools/pythonpkg/scripts/optional_requirements.py create mode 100644 tools/pythonpkg/src/include/duckdb_python/import_cache/modules/collections_module.hpp create mode 100644 tools/pythonpkg/src/include/duckdb_python/python_dependency.hpp create mode 100644 tools/pythonpkg/src/include/duckdb_python/python_replacement_scan.hpp create mode 100644 tools/pythonpkg/src/python_dependency.cpp create mode 100644 tools/pythonpkg/src/python_replacement_scan.cpp create mode 100644 tools/pythonpkg/tests/fast/arrow/test_arrow_string_view.py create mode 100644 tools/pythonpkg/tests/fast/relational_api/test_table_function.py create mode 100644 tools/pythonpkg/tests/fast/spark/test_spark_functions_date.py create mode 100644 tools/pythonpkg/tests/fast/spark/test_spark_functions_hash.py create mode 100644 tools/pythonpkg/tests/fast/spark/test_spark_functions_null.py rename tools/pythonpkg/tests/fast/spark/{test_spark_numeric_functions.py => test_spark_functions_numeric.py} (98%) rename tools/pythonpkg/tests/fast/spark/{test_spark_string_functions.py => test_spark_functions_string.py} (98%) create mode 100644 tools/pythonpkg/tests/fast/spark/test_spark_udf.py create mode 100644 tools/pythonpkg/tests/fast/test_union.py create mode 100644 tools/shell/tests/test_http_logging.py diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 79962938728..ca039872843 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -10,6 +10,7 @@ body: * [Documentation/website](https://github.com/duckdb/duckdb-web/issues/new) * APIs: + * [duckdb-java](https://github.com/duckdb/duckdb-java/issues/new) * [duckdb-node](https://github.com/duckdb/duckdb-node/issues/new) * [duckdb-r](https://github.com/duckdb/duckdb-r/issues/new) * [duckdb-rs](https://github.com/duckdb/duckdb-rs/issues/new) @@ -19,11 +20,13 @@ body: * [Arrow extension](https://github.com/duckdb/duckdb_arrow/issues/new) * [AWS extension](https://github.com/duckdb/duckdb_aws/issues/new) * [Azure extension](https://github.com/duckdb/duckdb_azure/issues/new) + * [Delta extension](https://github.com/duckdb/duckdb_delta/issues/new) * [Iceberg extension](https://github.com/duckdb/duckdb_iceberg/issues/new) * [MySQL extension](https://github.com/duckdb/duckdb_mysql/issues/new) * [Postgres scanner](https://github.com/duckdb/postgres_scanner/issues/new) * [Spatial extension](https://github.com/duckdb/duckdb_spatial/issues/new) * [SQLite scanner](https://github.com/duckdb/sqlite_scanner/issues/new) + * [VSS extension](https://github.com/duckdb/duckdb_vss/issues/new) * Connectors: * [dbt-duckdb](https://github.com/duckdb/dbt-duckdb) diff --git a/.github/actions/build_extensions/action.yml b/.github/actions/build_extensions/action.yml index 3012050e2eb..8d59440ed6e 100644 --- a/.github/actions/build_extensions/action.yml +++ b/.github/actions/build_extensions/action.yml @@ -81,6 +81,9 @@ inputs: unittest_script: description: 'Script/program to execute the unittests' default: 'python3 scripts/run_tests_one_by_one.py ./build/release/test/unittest' + cmake_flags: + description: 'Flags to be passed to cmake' + default: '' runs: using: "composite" @@ -104,7 +107,7 @@ runs: run: | echo "VCPKG_TOOLCHAIN_PATH=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" >> $GITHUB_ENV echo "VCPKG_TARGET_TRIPLET=${{ inputs.vcpkg_target_triplet }}" >> $GITHUB_ENV - + - name: workaround for https://github.com/duckdb/duckdb/issues/8360 if: inputs.vcpkg_target_triplet == 'x64-windows-static-md' shell: bash @@ -116,17 +119,6 @@ runs: ls -al pwd - - name: Fix for MSVC issue (see e.g. https://github.com/TileDB-Inc/TileDB/pull/4759) - shell: bash - if: inputs.deploy_as == 'windows_amd64' - env: - OVERLAY_TRIPLET_SRC: ${{ github.workspace }}/vcpkg/triplets/community/x64-windows-static-md.cmake - OVERLAY_TRIPLET_DST: ${{ github.workspace }}/overlay_triplets/x64-windows-static-md.cmake - run: | - mkdir overlay_triplets - cp $OVERLAY_TRIPLET_SRC $OVERLAY_TRIPLET_DST - echo "set(VCPKG_PLATFORM_TOOLSET_VERSION "14.38")" >> $OVERLAY_TRIPLET_DST - - name: Set Openssl dir if: inputs.openssl_path != '' shell: bash @@ -155,7 +147,8 @@ runs: GEN: ${{ inputs.ninja == 1 && 'ninja' || '' }} USE_MERGED_VCPKG_MANIFEST: 1 DUCKDB_PLATFORM: ${{ inputs.duckdb_arch }} - VCPKG_OVERLAY_TRIPLETS: "${{ github.workspace }}/overlay_triplets" + CMAKE_VARS_BUILD: ${{ inputs.cmake_flags }} + run: | ls mkdir -p ~/.ssh diff --git a/.github/actions/ubuntu_18_setup/action.yml b/.github/actions/ubuntu_18_setup/action.yml index d8938ab1b91..079cd2303d9 100644 --- a/.github/actions/ubuntu_18_setup/action.yml +++ b/.github/actions/ubuntu_18_setup/action.yml @@ -16,6 +16,9 @@ inputs: ccache: description: 'Install ccache' default: 0 + git_ref: + description: 'git reference to checkout' + default: '' runs: using: "composite" @@ -27,7 +30,7 @@ runs: apt-get install -y -qq software-properties-common add-apt-repository ppa:git-core/ppa apt-get update -y -qq - apt-get install -y -qq ninja-build make gcc-multilib g++-multilib libssl-dev wget openjdk-8-jdk zip maven unixodbc-dev libc6-dev-i386 lib32readline6-dev libssl-dev libcurl4-gnutls-dev libexpat1-dev gettext unzip build-essential checkinstall libffi-dev curl libz-dev openssh-client pkg-config + apt-get install -y -qq --fix-missing ninja-build make gcc-multilib g++-multilib libssl-dev wget openjdk-8-jdk zip maven unixodbc-dev libc6-dev-i386 lib32readline6-dev libssl-dev libcurl4-gnutls-dev libexpat1-dev gettext unzip build-essential checkinstall libffi-dev curl libz-dev openssh-client pkg-config - name: Install shell: bash @@ -48,6 +51,7 @@ runs: - uses: actions/checkout@v3 with: fetch-depth: 0 + ref: ${{ inputs.git_ref }} - name: Install CMake 3.21 shell: bash diff --git a/.github/config/bundled_extensions.cmake b/.github/config/bundled_extensions.cmake index ca2f5c03d77..dc9a0931078 100644 --- a/.github/config/bundled_extensions.cmake +++ b/.github/config/bundled_extensions.cmake @@ -20,11 +20,9 @@ duckdb_extension_load(tpch) duckdb_extension_load(json) duckdb_extension_load(fts) duckdb_extension_load(parquet) -duckdb_extension_load(excel) duckdb_extension_load(autocomplete) # ## Extensions that are not linked, but we do want to test them as part of the release build # -duckdb_extension_load(sqlsmith DONT_LINK) duckdb_extension_load(tpcds DONT_LINK) diff --git a/.github/config/extensions.csv b/.github/config/extensions.csv index 453ee59d3a8..1a48feb7d2e 100644 --- a/.github/config/extensions.csv +++ b/.github/config/extensions.csv @@ -13,6 +13,6 @@ substrait,https://github.com/duckdb/substrait,1116fb580edd3e26e675436dbdbdf4a0aa arrow,https://github.com/duckdb/arrow,9e10240da11f61ea7fbfe3fc9988ffe672ccd40f,no-windows aws,https://github.com/duckdb/duckdb_aws,f7b8729f1cce5ada5d4add70e1486de50763fb97, azure,https://github.com/duckdb/duckdb_azure,09623777a366572bfb8fa53e47acdf72133a360e, -spatial,https://github.com/duckdb/duckdb_spatial,8ac803e986ccda34f32dee82a7faae95b72b3492, +spatial,https://github.com/duckdb/duckdb_spatial,dbb9971c900c5888e3e3598af91de3b9b884aca6, iceberg,https://github.com/duckdb/duckdb_iceberg,d89423c2ff90a0b98a093a133c8dfe2a55b9e092, -vss,https://github.com/duckdb/duckdb_vss,8145f41d97178e82bed3376215eb8d02bcf1eec5, +vss,https://github.com/duckdb/duckdb_vss,dbf5b74298384a9dc8e78353e628259b020cd4eb, diff --git a/.github/config/in_tree_extensions.cmake b/.github/config/in_tree_extensions.cmake index 9587ea54461..6b52aafe6d7 100644 --- a/.github/config/in_tree_extensions.cmake +++ b/.github/config/in_tree_extensions.cmake @@ -6,13 +6,11 @@ # duckdb_extension_load(autocomplete) -duckdb_extension_load(excel) duckdb_extension_load(fts) duckdb_extension_load(httpfs) duckdb_extension_load(inet) duckdb_extension_load(icu) duckdb_extension_load(json) duckdb_extension_load(parquet) -duckdb_extension_load(sqlsmith) duckdb_extension_load(tpcds) duckdb_extension_load(tpch) diff --git a/.github/config/out_of_tree_extensions.cmake b/.github/config/out_of_tree_extensions.cmake index 159ed15ebe6..8120865fdc0 100644 --- a/.github/config/out_of_tree_extensions.cmake +++ b/.github/config/out_of_tree_extensions.cmake @@ -20,8 +20,7 @@ if (NOT MINGW) duckdb_extension_load(arrow LOAD_TESTS DONT_LINK GIT_URL https://github.com/duckdb/arrow - GIT_TAG 9e10240da11f61ea7fbfe3fc9988ffe672ccd40f - APPLY_PATCHES + GIT_TAG fa40ec56236953aa5978cf1b4c65ed521424ce69 ) endif() @@ -30,8 +29,7 @@ if (NOT MINGW) duckdb_extension_load(aws LOAD_TESTS GIT_URL https://github.com/duckdb/duckdb_aws - GIT_TAG f7b8729f1cce5ada5d4add70e1486de50763fb97 - APPLY_PATCHES + GIT_TAG 42c78d3f99e1a188a2b178ea59e3c17907af4fb2 ) endif() @@ -40,11 +38,18 @@ if (NOT MINGW) duckdb_extension_load(azure LOAD_TESTS GIT_URL https://github.com/duckdb/duckdb_azure - GIT_TAG 09623777a366572bfb8fa53e47acdf72133a360e - APPLY_PATCHES + GIT_TAG 49b63dc8cd166952a0a34dfd54e6cfe5b823e05e ) endif() +################# EXCEL +duckdb_extension_load(excel + LOAD_TESTS + GIT_URL https://github.com/duckdb/duckdb_excel + GIT_TAG 391b36dfdcc1c8c187529376efb4f7ddc9f57261 + INCLUDE_DIR extension/excel/include + ) + ################# ICEBERG # Windows tests for iceberg currently not working if (NOT WIN32) @@ -57,7 +62,7 @@ if (NOT MINGW) duckdb_extension_load(iceberg ${LOAD_ICEBERG_TESTS} GIT_URL https://github.com/duckdb/duckdb_iceberg - GIT_TAG d89423c2ff90a0b98a093a133c8dfe2a55b9e092 + GIT_TAG fe0471671924ce57308924c79f72efd18103e66b ) endif() @@ -68,8 +73,7 @@ if (NOT MINGW) duckdb_extension_load(postgres_scanner DONT_LINK GIT_URL https://github.com/duckdb/postgres_scanner - GIT_TAG 96206f41d5ca7015920a66b54e936c986fe0b0f8 - APPLY_PATCHES + GIT_TAG 120c0b12258d27758e240d61f5dc22a4238a14a6 ) endif() @@ -77,7 +81,7 @@ endif() duckdb_extension_load(spatial DONT_LINK LOAD_TESTS GIT_URL https://github.com/duckdb/duckdb_spatial.git - GIT_TAG 8ac803e986ccda34f32dee82a7faae95b72b3492 + GIT_TAG dbb9971c900c5888e3e3598af91de3b9b884aca6 INCLUDE_DIR spatial/include TEST_DIR test/sql ) @@ -93,8 +97,12 @@ endif() duckdb_extension_load(sqlite_scanner ${STATIC_LINK_SQLITE} LOAD_TESTS GIT_URL https://github.com/duckdb/sqlite_scanner - GIT_TAG 091197efb34579c7195afa43dfb5925023c915c0 - APPLY_PATCHES + GIT_TAG 50b7870be099186f195bc72bac5e9e11247ee2f9 + ) + +duckdb_extension_load(sqlsmith + GIT_URL https://github.com/duckdb/duckdb_sqlsmith + GIT_TAG 721460ff1f31ce1dc1e4a9c4a55c0faf0b466dcb ) ################# SUBSTRAIT @@ -102,7 +110,7 @@ if (NOT WIN32) duckdb_extension_load(substrait LOAD_TESTS DONT_LINK GIT_URL https://github.com/duckdb/substrait - GIT_TAG 1116fb580edd3e26e675436dbdbdf4a0aa5e456e + GIT_TAG 237931391ebc7e6aee7aa81052fa1411f6c4128e APPLY_PATCHES ) endif() @@ -111,7 +119,18 @@ endif() ################# VSS duckdb_extension_load(vss LOAD_TESTS + DONT_LINK GIT_URL https://github.com/duckdb/duckdb_vss - GIT_TAG 8145f41d97178e82bed3376215eb8d02bcf1eec5 + GIT_TAG 690bfc56c82b54f4580dabbc2769e2925db61499 TEST_DIR test/sql ) + +################# MYSQL +if (NOT MINGW) + duckdb_extension_load(mysql_scanner + DONT_LINK + LOAD_TESTS + GIT_URL https://github.com/duckdb/duckdb_mysql + GIT_TAG 4dd5963cc5f7f04f81a0ea308b104e65791d9975 + ) +endif() diff --git a/.github/config/uncovered_files.csv b/.github/config/uncovered_files.csv index 4bff1a13c06..89b2ca141ee 100644 --- a/.github/config/uncovered_files.csv +++ b/.github/config/uncovered_files.csv @@ -435,7 +435,6 @@ include/duckdb/main/query_result.hpp 12 include/duckdb/main/relation.hpp 3 include/duckdb/main/relation/subquery_relation.hpp 3 include/duckdb/main/relation/write_parquet_relation.hpp 3 -include/duckdb/optimizer/join_order/estimated_properties.hpp 1 include/duckdb/optimizer/matcher/function_matcher.hpp 2 include/duckdb/optimizer/matcher/set_matcher.hpp 2 include/duckdb/parallel/base_pipeline_event.hpp 2 @@ -543,7 +542,6 @@ optimizer/join_order/join_order_optimizer.cpp 96 optimizer/join_order/query_graph.cpp 2 optimizer/join_order/relation_manager.cpp 4 optimizer/join_order/query_graph_manager.cpp 3 -optimizer/join_order/estimated_properties.cpp 16 optimizer/join_order/plan_enumerator.cpp 11 optimizer/join_order/relation_statistics_helper.cpp 2 optimizer/matcher/expression_matcher.cpp 2 diff --git a/.github/patches/extensions/arrow/shared_ptr.patch b/.github/patches/extensions/arrow/shared_ptr.patch deleted file mode 100644 index d523ffe0111..00000000000 --- a/.github/patches/extensions/arrow/shared_ptr.patch +++ /dev/null @@ -1,1134 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 72b1370..c95486c 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -7,56 +7,55 @@ set(EXTENSION_NAME ${TARGET_NAME}_extension) - project(${TARGET_NAME}) - include_directories(src/include) - --set(EXTENSION_SOURCES -- src/arrow_extension.cpp -- src/arrow_stream_buffer.cpp -- src/arrow_scan_ipc.cpp -- src/arrow_to_ipc.cpp) -+set(EXTENSION_SOURCES src/arrow_extension.cpp src/arrow_stream_buffer.cpp -+ src/arrow_scan_ipc.cpp src/arrow_to_ipc.cpp) - - if(NOT "${OSX_BUILD_ARCH}" STREQUAL "") -- set(OSX_ARCH_FLAG -DCMAKE_OSX_ARCHITECTURES=${OSX_BUILD_ARCH}) -+ set(OSX_ARCH_FLAG -DCMAKE_OSX_ARCHITECTURES=${OSX_BUILD_ARCH}) - else() -- set(OSX_ARCH_FLAG "") -+ set(OSX_ARCH_FLAG "") - endif() - - # Building Arrow - include(ExternalProject) - ExternalProject_Add( -- ARROW_EP -- GIT_REPOSITORY "https://github.com/apache/arrow" -- GIT_TAG ea6875fd2a3ac66547a9a33c5506da94f3ff07f2 -- PREFIX "${CMAKE_BINARY_DIR}/third_party/arrow" -- INSTALL_DIR "${CMAKE_BINARY_DIR}/third_party/arrow/install" -- BUILD_BYPRODUCTS /lib/libarrow.a -- CONFIGURE_COMMAND -- ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ${OSX_ARCH_FLAG} -- -DCMAKE_BUILD_TYPE=Release -- -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/third_party/arrow/install -- -DCMAKE_INSTALL_LIBDIR=lib -DARROW_BUILD_STATIC=ON -DARROW_BUILD_SHARED=OFF -- -DARROW_NO_DEPRECATED_API=ON -DARROW_POSITION_INDEPENDENT_CODE=ON -- -DARROW_SIMD_LEVEL=NONE -DARROW_ENABLE_TIMING_TESTS=OFF -DARROW_IPC=ON -- -DARROW_JEMALLOC=OFF -DARROW_DEPENDENCY_SOURCE=BUNDLED -- -DARROW_VERBOSE_THIRDPARTY_BUILD=OFF -DARROW_DEPENDENCY_USE_SHARED=OFF -- -DARROW_BOOST_USE_SHARED=OFF -DARROW_BROTLI_USE_SHARED=OFF -- -DARROW_BZ2_USE_SHARED=OFF -DARROW_GFLAGS_USE_SHARED=OFF -- -DARROW_GRPC_USE_SHARED=OFF -DARROW_JEMALLOC_USE_SHARED=OFF -- -DARROW_LZ4_USE_SHARED=OFF -DARROW_OPENSSL_USE_SHARED=OFF -- -DARROW_PROTOBUF_USE_SHARED=OFF -DARROW_SNAPPY_USE_SHARED=OFF -- -DARROW_THRIFT_USE_SHARED=OFF -DARROW_UTF8PROC_USE_SHARED=OFF -- -DARROW_ZSTD_USE_SHARED=OFF -DARROW_USE_GLOG=OFF -DARROW_WITH_BACKTRACE=OFF -- -DARROW_WITH_OPENTELEMETRY=OFF -DARROW_WITH_BROTLI=OFF -DARROW_WITH_BZ2=OFF -- -DARROW_WITH_LZ4=OFF -DARROW_WITH_SNAPPY=OFF -DARROW_WITH_ZLIB=OFF -- -DARROW_WITH_ZSTD=OFF -DARROW_WITH_UCX=OFF -DARROW_WITH_UTF8PROC=OFF -- -DARROW_WITH_RE2=OFF /cpp -- CMAKE_ARGS -Wno-dev -- UPDATE_COMMAND "") -+ ARROW_EP -+ GIT_REPOSITORY "https://github.com/apache/arrow" -+ GIT_TAG ea6875fd2a3ac66547a9a33c5506da94f3ff07f2 -+ PREFIX "${CMAKE_BINARY_DIR}/third_party/arrow" -+ INSTALL_DIR "${CMAKE_BINARY_DIR}/third_party/arrow/install" -+ BUILD_BYPRODUCTS /lib/libarrow.a -+ CONFIGURE_COMMAND -+ ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ${OSX_ARCH_FLAG} -+ -DCMAKE_BUILD_TYPE=Release -+ -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/third_party/arrow/install -+ -DCMAKE_INSTALL_LIBDIR=lib -DARROW_BUILD_STATIC=ON -DARROW_BUILD_SHARED=OFF -+ -DARROW_NO_DEPRECATED_API=ON -DARROW_POSITION_INDEPENDENT_CODE=ON -+ -DARROW_SIMD_LEVEL=NONE -DARROW_ENABLE_TIMING_TESTS=OFF -DARROW_IPC=ON -+ -DARROW_JEMALLOC=OFF -DARROW_DEPENDENCY_SOURCE=BUNDLED -+ -DARROW_VERBOSE_THIRDPARTY_BUILD=OFF -DARROW_DEPENDENCY_USE_SHARED=OFF -+ -DARROW_BOOST_USE_SHARED=OFF -DARROW_BROTLI_USE_SHARED=OFF -+ -DARROW_BZ2_USE_SHARED=OFF -DARROW_GFLAGS_USE_SHARED=OFF -+ -DARROW_GRPC_USE_SHARED=OFF -DARROW_JEMALLOC_USE_SHARED=OFF -+ -DARROW_LZ4_USE_SHARED=OFF -DARROW_OPENSSL_USE_SHARED=OFF -+ -DARROW_PROTOBUF_USE_SHARED=OFF -DARROW_SNAPPY_USE_SHARED=OFF -+ -DARROW_THRIFT_USE_SHARED=OFF -DARROW_UTF8PROC_USE_SHARED=OFF -+ -DARROW_ZSTD_USE_SHARED=OFF -DARROW_USE_GLOG=OFF -DARROW_WITH_BACKTRACE=OFF -+ -DARROW_WITH_OPENTELEMETRY=OFF -DARROW_WITH_BROTLI=OFF -DARROW_WITH_BZ2=OFF -+ -DARROW_WITH_LZ4=OFF -DARROW_WITH_SNAPPY=OFF -DARROW_WITH_ZLIB=OFF -+ -DARROW_WITH_ZSTD=OFF -DARROW_WITH_UCX=OFF -DARROW_WITH_UTF8PROC=OFF -+ -DARROW_WITH_RE2=OFF /cpp -+ CMAKE_ARGS -Wno-dev -+ UPDATE_COMMAND "") - - ExternalProject_Get_Property(ARROW_EP install_dir) - add_library(arrow STATIC IMPORTED GLOBAL) - if(WIN32) -- set_target_properties(arrow PROPERTIES IMPORTED_LOCATION ${install_dir}/lib/arrow_static.lib) -+ set_target_properties(arrow PROPERTIES IMPORTED_LOCATION -+ ${install_dir}/lib/arrow_static.lib) - else() -- set_target_properties(arrow PROPERTIES IMPORTED_LOCATION ${install_dir}/lib/libarrow.a) -+ set_target_properties(arrow PROPERTIES IMPORTED_LOCATION -+ ${install_dir}/lib/libarrow.a) - endif() - - # create static library -@@ -71,12 +70,14 @@ build_loadable_extension(${TARGET_NAME} ${PARAMETERS} ${EXTENSION_SOURCES}) - add_dependencies(${TARGET_NAME}_loadable_extension ARROW_EP) - target_link_libraries(${TARGET_NAME}_loadable_extension arrow) - if(WIN32) -- target_compile_definitions(${TARGET_NAME}_loadable_extension PUBLIC ARROW_STATIC) -+ target_compile_definitions(${TARGET_NAME}_loadable_extension -+ PUBLIC ARROW_STATIC) - endif() --target_include_directories(${TARGET_NAME}_loadable_extension PRIVATE ${install_dir}/include) -+target_include_directories(${TARGET_NAME}_loadable_extension -+ PRIVATE ${install_dir}/include) - - install( -- TARGETS ${EXTENSION_NAME} -- EXPORT "${DUCKDB_EXPORT_SET}" -- LIBRARY DESTINATION "${INSTALL_LIB_DIR}" -- ARCHIVE DESTINATION "${INSTALL_LIB_DIR}") -\ No newline at end of file -+ TARGETS ${EXTENSION_NAME} -+ EXPORT "${DUCKDB_EXPORT_SET}" -+ LIBRARY DESTINATION "${INSTALL_LIB_DIR}" -+ ARCHIVE DESTINATION "${INSTALL_LIB_DIR}") -diff --git a/src/arrow_extension.cpp b/src/arrow_extension.cpp -index e4daf26..6fadec0 100644 ---- a/src/arrow_extension.cpp -+++ b/src/arrow_extension.cpp -@@ -18,27 +18,24 @@ - namespace duckdb { - - static void LoadInternal(DatabaseInstance &instance) { -- ExtensionUtil::RegisterFunction(instance, ToArrowIPCFunction::GetFunction()); -- ExtensionUtil::RegisterFunction(instance, ArrowIPCTableFunction::GetFunction()); -+ ExtensionUtil::RegisterFunction(instance, ToArrowIPCFunction::GetFunction()); -+ ExtensionUtil::RegisterFunction(instance, -+ ArrowIPCTableFunction::GetFunction()); - } - --void ArrowExtension::Load(DuckDB &db) { -- LoadInternal(*db.instance); --} --std::string ArrowExtension::Name() { -- return "arrow"; --} -+void ArrowExtension::Load(DuckDB &db) { LoadInternal(*db.instance); } -+std::string ArrowExtension::Name() { return "arrow"; } - - } // namespace duckdb - - extern "C" { - - DUCKDB_EXTENSION_API void arrow_init(duckdb::DatabaseInstance &db) { -- LoadInternal(db); -+ LoadInternal(db); - } - - DUCKDB_EXTENSION_API const char *arrow_version() { -- return duckdb::DuckDB::LibraryVersion(); -+ return duckdb::DuckDB::LibraryVersion(); - } - } - -diff --git a/src/arrow_scan_ipc.cpp b/src/arrow_scan_ipc.cpp -index 7d5b2ff..a60d255 100644 ---- a/src/arrow_scan_ipc.cpp -+++ b/src/arrow_scan_ipc.cpp -@@ -3,111 +3,131 @@ - namespace duckdb { - - TableFunction ArrowIPCTableFunction::GetFunction() { -- child_list_t make_buffer_struct_children{{"ptr", LogicalType::UBIGINT}, -- {"size", LogicalType::UBIGINT}}; -- -- TableFunction scan_arrow_ipc_func( -- "scan_arrow_ipc", {LogicalType::LIST(LogicalType::STRUCT(make_buffer_struct_children))}, -- ArrowIPCTableFunction::ArrowScanFunction, ArrowIPCTableFunction::ArrowScanBind, -- ArrowTableFunction::ArrowScanInitGlobal, ArrowTableFunction::ArrowScanInitLocal); -- -- scan_arrow_ipc_func.cardinality = ArrowTableFunction::ArrowScanCardinality; -- scan_arrow_ipc_func.get_batch_index = nullptr; // TODO implement -- scan_arrow_ipc_func.projection_pushdown = true; -- scan_arrow_ipc_func.filter_pushdown = false; -- -- return scan_arrow_ipc_func; -+ child_list_t make_buffer_struct_children{ -+ {"ptr", LogicalType::UBIGINT}, {"size", LogicalType::UBIGINT}}; -+ -+ TableFunction scan_arrow_ipc_func( -+ "scan_arrow_ipc", -+ {LogicalType::LIST(LogicalType::STRUCT(make_buffer_struct_children))}, -+ ArrowIPCTableFunction::ArrowScanFunction, -+ ArrowIPCTableFunction::ArrowScanBind, -+ ArrowTableFunction::ArrowScanInitGlobal, -+ ArrowTableFunction::ArrowScanInitLocal); -+ -+ scan_arrow_ipc_func.cardinality = ArrowTableFunction::ArrowScanCardinality; -+ scan_arrow_ipc_func.get_batch_index = nullptr; // TODO implement -+ scan_arrow_ipc_func.projection_pushdown = true; -+ scan_arrow_ipc_func.filter_pushdown = false; -+ -+ return scan_arrow_ipc_func; - } - --unique_ptr ArrowIPCTableFunction::ArrowScanBind(ClientContext &context, TableFunctionBindInput &input, -- vector &return_types, vector &names) { -- auto stream_decoder = make_uniq(); -+unique_ptr ArrowIPCTableFunction::ArrowScanBind( -+ ClientContext &context, TableFunctionBindInput &input, -+ vector &return_types, vector &names) { -+ auto stream_decoder = make_uniq(); - -- // Decode buffer ptr list -- auto buffer_ptr_list = ListValue::GetChildren(input.inputs[0]); -- for (auto &buffer_ptr_struct: buffer_ptr_list) { -- auto unpacked = StructValue::GetChildren(buffer_ptr_struct); -- uint64_t ptr = unpacked[0].GetValue(); -- uint64_t size = unpacked[1].GetValue(); -+ // Decode buffer ptr list -+ auto buffer_ptr_list = ListValue::GetChildren(input.inputs[0]); -+ for (auto &buffer_ptr_struct : buffer_ptr_list) { -+ auto unpacked = StructValue::GetChildren(buffer_ptr_struct); -+ uint64_t ptr = unpacked[0].GetValue(); -+ uint64_t size = unpacked[1].GetValue(); - -- // Feed stream into decoder -- auto res = stream_decoder->Consume((const uint8_t *) ptr, size); -+ // Feed stream into decoder -+ auto res = stream_decoder->Consume((const uint8_t *)ptr, size); - -- if (!res.ok()) { -- throw IOException("Invalid IPC stream"); -- } -+ if (!res.ok()) { -+ throw IOException("Invalid IPC stream"); - } -- -- if (!stream_decoder->buffer()->is_eos()) { -- throw IOException("IPC buffers passed to arrow scan should contain entire stream"); -+ } -+ -+ if (!stream_decoder->buffer()->is_eos()) { -+ throw IOException( -+ "IPC buffers passed to arrow scan should contain entire stream"); -+ } -+ -+ // These are the params I need to produce from the ipc buffers using the -+ // WebDB.cc code -+ auto stream_factory_ptr = (uintptr_t)&stream_decoder->buffer(); -+ auto stream_factory_produce = -+ (stream_factory_produce_t)&ArrowIPCStreamBufferReader::CreateStream; -+ auto stream_factory_get_schema = -+ (stream_factory_get_schema_t)&ArrowIPCStreamBufferReader::GetSchema; -+ auto res = make_uniq(stream_factory_produce, -+ stream_factory_ptr); -+ -+ // Store decoder -+ res->stream_decoder = std::move(stream_decoder); -+ -+ // TODO Everything below this is identical to the bind in -+ // duckdb/src/function/table/arrow.cpp -+ auto &data = *res; -+ stream_factory_get_schema((ArrowArrayStream *)stream_factory_ptr, -+ data.schema_root.arrow_schema); -+ for (idx_t col_idx = 0; -+ col_idx < (idx_t)data.schema_root.arrow_schema.n_children; col_idx++) { -+ auto &schema = *data.schema_root.arrow_schema.children[col_idx]; -+ if (!schema.release) { -+ throw InvalidInputException("arrow_scan: released schema passed"); - } -- -- // These are the params I need to produce from the ipc buffers using the WebDB.cc code -- auto stream_factory_ptr = (uintptr_t) & stream_decoder->buffer(); -- auto stream_factory_produce = (stream_factory_produce_t) & ArrowIPCStreamBufferReader::CreateStream; -- auto stream_factory_get_schema = (stream_factory_get_schema_t) & ArrowIPCStreamBufferReader::GetSchema; -- auto res = make_uniq(stream_factory_produce, stream_factory_ptr); -- -- // Store decoder -- res->stream_decoder = std::move(stream_decoder); -- -- // TODO Everything below this is identical to the bind in duckdb/src/function/table/arrow.cpp -- auto &data = *res; -- stream_factory_get_schema((ArrowArrayStream *) stream_factory_ptr, data.schema_root.arrow_schema); -- for (idx_t col_idx = 0; col_idx < (idx_t) data.schema_root.arrow_schema.n_children; col_idx++) { -- auto &schema = *data.schema_root.arrow_schema.children[col_idx]; -- if (!schema.release) { -- throw InvalidInputException("arrow_scan: released schema passed"); -- } -- auto arrow_type = GetArrowLogicalType(schema); -- if (schema.dictionary) { -- auto dictionary_type = GetArrowLogicalType(*schema.dictionary); -- return_types.emplace_back(dictionary_type->GetDuckType()); -- arrow_type->SetDictionary(std::move(dictionary_type)); -- } else { -- return_types.emplace_back(arrow_type->GetDuckType()); -- } -- res->arrow_table.AddColumn(col_idx, std::move(arrow_type)); -- auto format = string(schema.format); -- auto name = string(schema.name); -- if (name.empty()) { -- name = string("v") + to_string(col_idx); -- } -- names.push_back(name); -+ auto arrow_type = GetArrowLogicalType(schema); -+ if (schema.dictionary) { -+ auto dictionary_type = GetArrowLogicalType(*schema.dictionary); -+ return_types.emplace_back(dictionary_type->GetDuckType()); -+ arrow_type->SetDictionary(std::move(dictionary_type)); -+ } else { -+ return_types.emplace_back(arrow_type->GetDuckType()); - } -- QueryResult::DeduplicateColumns(names); -- return std::move(res); -+ res->arrow_table.AddColumn(col_idx, std::move(arrow_type)); -+ auto format = string(schema.format); -+ auto name = string(schema.name); -+ if (name.empty()) { -+ name = string("v") + to_string(col_idx); -+ } -+ names.push_back(name); -+ } -+ QueryResult::DeduplicateColumns(names); -+ return std::move(res); - } - --// Same as regular arrow scan, except ArrowToDuckDB call TODO: refactor to allow nicely overriding this --void ArrowIPCTableFunction::ArrowScanFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { -- if (!data_p.local_state) { -- return; -- } -- auto &data = data_p.bind_data->CastNoConst(); -- auto &state = data_p.local_state->Cast(); -- auto &global_state = data_p.global_state->Cast(); -- -- //! Out of tuples in this chunk -- if (state.chunk_offset >= (idx_t)state.chunk->arrow_array.length) { -- if (!ArrowScanParallelStateNext(context, data_p.bind_data.get(), state, global_state)) { -- return; -- } -+// Same as regular arrow scan, except ArrowToDuckDB call TODO: refactor to allow -+// nicely overriding this -+void ArrowIPCTableFunction::ArrowScanFunction(ClientContext &context, -+ TableFunctionInput &data_p, -+ DataChunk &output) { -+ if (!data_p.local_state) { -+ return; -+ } -+ auto &data = data_p.bind_data->CastNoConst(); -+ auto &state = data_p.local_state->Cast(); -+ auto &global_state = data_p.global_state->Cast(); -+ -+ //! Out of tuples in this chunk -+ if (state.chunk_offset >= (idx_t)state.chunk->arrow_array.length) { -+ if (!ArrowScanParallelStateNext(context, data_p.bind_data.get(), state, -+ global_state)) { -+ return; - } -- int64_t output_size = MinValue(STANDARD_VECTOR_SIZE, state.chunk->arrow_array.length - state.chunk_offset); -- data.lines_read += output_size; -- if (global_state.CanRemoveFilterColumns()) { -- state.all_columns.Reset(); -- state.all_columns.SetCardinality(output_size); -- ArrowToDuckDB(state, data.arrow_table.GetColumns(), state.all_columns, data.lines_read - output_size, false); -- output.ReferenceColumns(state.all_columns, global_state.projection_ids); -- } else { -- output.SetCardinality(output_size); -- ArrowToDuckDB(state, data.arrow_table.GetColumns(), output, data.lines_read - output_size, false); -- } -- -- output.Verify(); -- state.chunk_offset += output.size(); -+ } -+ int64_t output_size = -+ MinValue(STANDARD_VECTOR_SIZE, -+ state.chunk->arrow_array.length - state.chunk_offset); -+ data.lines_read += output_size; -+ if (global_state.CanRemoveFilterColumns()) { -+ state.all_columns.Reset(); -+ state.all_columns.SetCardinality(output_size); -+ ArrowToDuckDB(state, data.arrow_table.GetColumns(), state.all_columns, -+ data.lines_read - output_size, false); -+ output.ReferenceColumns(state.all_columns, global_state.projection_ids); -+ } else { -+ output.SetCardinality(output_size); -+ ArrowToDuckDB(state, data.arrow_table.GetColumns(), output, -+ data.lines_read - output_size, false); -+ } -+ -+ output.Verify(); -+ state.chunk_offset += output.size(); - } - - } // namespace duckdb -\ No newline at end of file -diff --git a/src/arrow_stream_buffer.cpp b/src/arrow_stream_buffer.cpp -index f097ca1..c9791e4 100644 ---- a/src/arrow_stream_buffer.cpp -+++ b/src/arrow_stream_buffer.cpp -@@ -1,95 +1,108 @@ - #include "arrow_stream_buffer.hpp" - - #include -+#include - - /// File copied from - /// https://github.com/duckdb/duckdb-wasm/blob/0ad10e7db4ef4025f5f4120be37addc4ebe29618/lib/src/arrow_stream_buffer.cc - namespace duckdb { - - /// Constructor --ArrowIPCStreamBuffer::ArrowIPCStreamBuffer() : schema_(nullptr), batches_(), is_eos_(false) { --} -+ArrowIPCStreamBuffer::ArrowIPCStreamBuffer() -+ : schema_(nullptr), batches_(), is_eos_(false) {} - /// Decoded a schema --arrow::Status ArrowIPCStreamBuffer::OnSchemaDecoded(std::shared_ptr s) { -- schema_ = s; -- return arrow::Status::OK(); -+arrow::Status -+ArrowIPCStreamBuffer::OnSchemaDecoded(std::shared_ptr s) { -+ schema_ = s; -+ return arrow::Status::OK(); - } - /// Decoded a record batch --arrow::Status ArrowIPCStreamBuffer::OnRecordBatchDecoded(std::shared_ptr batch) { -- batches_.push_back(batch); -- return arrow::Status::OK(); -+arrow::Status ArrowIPCStreamBuffer::OnRecordBatchDecoded( -+ std::shared_ptr batch) { -+ batches_.push_back(batch); -+ return arrow::Status::OK(); - } - /// Reached end of stream - arrow::Status ArrowIPCStreamBuffer::OnEOS() { -- is_eos_ = true; -- return arrow::Status::OK(); -+ is_eos_ = true; -+ return arrow::Status::OK(); - } - - /// Constructor --ArrowIPCStreamBufferReader::ArrowIPCStreamBufferReader(std::shared_ptr buffer) -- : buffer_(buffer), next_batch_id_(0) { --} -+ArrowIPCStreamBufferReader::ArrowIPCStreamBufferReader( -+ std::shared_ptr buffer) -+ : buffer_(buffer), next_batch_id_(0) {} - - /// Get the schema - std::shared_ptr ArrowIPCStreamBufferReader::schema() const { -- return buffer_->schema(); -+ return buffer_->schema(); - } - /// Read the next record batch in the stream. Return null for batch when - /// reaching end of stream --arrow::Status ArrowIPCStreamBufferReader::ReadNext(std::shared_ptr *batch) { -- if (next_batch_id_ >= buffer_->batches().size()) { -- *batch = nullptr; -- return arrow::Status::OK(); -- } -- *batch = buffer_->batches()[next_batch_id_++]; -- return arrow::Status::OK(); -+arrow::Status ArrowIPCStreamBufferReader::ReadNext( -+ std::shared_ptr *batch) { -+ if (next_batch_id_ >= buffer_->batches().size()) { -+ *batch = nullptr; -+ return arrow::Status::OK(); -+ } -+ *batch = buffer_->batches()[next_batch_id_++]; -+ return arrow::Status::OK(); - } - - /// Arrow array stream factory function - duckdb::unique_ptr --ArrowIPCStreamBufferReader::CreateStream(uintptr_t buffer_ptr, ArrowStreamParameters ¶meters) { -- assert(buffer_ptr != 0); -- auto buffer = reinterpret_cast *>(buffer_ptr); -- auto reader = std::make_shared(*buffer); -+ArrowIPCStreamBufferReader::CreateStream(uintptr_t buffer_ptr, -+ ArrowStreamParameters ¶meters) { -+ assert(buffer_ptr != 0); -+ auto buffer = -+ reinterpret_cast *>(buffer_ptr); -+ auto reader = std::make_shared(*buffer); - -- // Create arrow stream -- auto stream_wrapper = duckdb::make_uniq(); -- stream_wrapper->arrow_array_stream.release = nullptr; -- auto maybe_ok = arrow::ExportRecordBatchReader(reader, &stream_wrapper->arrow_array_stream); -- if (!maybe_ok.ok()) { -- if (stream_wrapper->arrow_array_stream.release) { -- stream_wrapper->arrow_array_stream.release(&stream_wrapper->arrow_array_stream); -- } -- return nullptr; -- } -+ // Create arrow stream -+ auto stream_wrapper = duckdb::make_uniq(); -+ stream_wrapper->arrow_array_stream.release = nullptr; -+ auto maybe_ok = arrow::ExportRecordBatchReader( -+ reader, &stream_wrapper->arrow_array_stream); -+ if (!maybe_ok.ok()) { -+ if (stream_wrapper->arrow_array_stream.release) { -+ stream_wrapper->arrow_array_stream.release( -+ &stream_wrapper->arrow_array_stream); -+ } -+ return nullptr; -+ } - -- // Release the stream -- return stream_wrapper; -+ // Release the stream -+ return stream_wrapper; - } - --void ArrowIPCStreamBufferReader::GetSchema(uintptr_t buffer_ptr, duckdb::ArrowSchemaWrapper &schema) { -- assert(buffer_ptr != 0); -- auto buffer = reinterpret_cast *>(buffer_ptr); -- auto reader = std::make_shared(*buffer); -+void ArrowIPCStreamBufferReader::GetSchema(uintptr_t buffer_ptr, -+ duckdb::ArrowSchemaWrapper &schema) { -+ assert(buffer_ptr != 0); -+ auto buffer = -+ reinterpret_cast *>(buffer_ptr); -+ auto reader = std::make_shared(*buffer); - -- // Create arrow stream -- auto stream_wrapper = duckdb::make_uniq(); -- stream_wrapper->arrow_array_stream.release = nullptr; -- auto maybe_ok = arrow::ExportRecordBatchReader(reader, &stream_wrapper->arrow_array_stream); -- if (!maybe_ok.ok()) { -- if (stream_wrapper->arrow_array_stream.release) { -- stream_wrapper->arrow_array_stream.release(&stream_wrapper->arrow_array_stream); -- } -- return; -- } -+ // Create arrow stream -+ auto stream_wrapper = duckdb::make_uniq(); -+ stream_wrapper->arrow_array_stream.release = nullptr; -+ auto maybe_ok = arrow::ExportRecordBatchReader( -+ reader, &stream_wrapper->arrow_array_stream); -+ if (!maybe_ok.ok()) { -+ if (stream_wrapper->arrow_array_stream.release) { -+ stream_wrapper->arrow_array_stream.release( -+ &stream_wrapper->arrow_array_stream); -+ } -+ return; -+ } - -- // Pass ownership to caller -- stream_wrapper->arrow_array_stream.get_schema(&stream_wrapper->arrow_array_stream, &schema.arrow_schema); -+ // Pass ownership to caller -+ stream_wrapper->arrow_array_stream.get_schema( -+ &stream_wrapper->arrow_array_stream, &schema.arrow_schema); - } - - /// Constructor --BufferingArrowIPCStreamDecoder::BufferingArrowIPCStreamDecoder(std::shared_ptr buffer) -- : arrow::ipc::StreamDecoder(buffer), buffer_(buffer) { --} -+BufferingArrowIPCStreamDecoder::BufferingArrowIPCStreamDecoder( -+ std::shared_ptr buffer) -+ : arrow::ipc::StreamDecoder(buffer), buffer_(buffer) {} - - } // namespace duckdb -diff --git a/src/arrow_to_ipc.cpp b/src/arrow_to_ipc.cpp -index e282612..c316d85 100644 ---- a/src/arrow_to_ipc.cpp -+++ b/src/arrow_to_ipc.cpp -@@ -15,6 +15,8 @@ - #include "arrow/type_fwd.h" - #include "arrow/c/bridge.h" - -+#include -+ - #include "duckdb.hpp" - #ifndef DUCKDB_AMALGAMATION - #include "duckdb/common/arrow/result_arrow_wrapper.hpp" -@@ -28,165 +30,180 @@ - namespace duckdb { - - struct ToArrowIpcFunctionData : public TableFunctionData { -- ToArrowIpcFunctionData() { -- } -- shared_ptr schema; -- idx_t chunk_size; -+ ToArrowIpcFunctionData() {} -+ std::shared_ptr schema; -+ idx_t chunk_size; - }; - - struct ToArrowIpcGlobalState : public GlobalTableFunctionState { -- ToArrowIpcGlobalState() : sent_schema(false) { -- } -- atomic sent_schema; -- mutex lock; -+ ToArrowIpcGlobalState() : sent_schema(false) {} -+ atomic sent_schema; -+ mutex lock; - }; - - struct ToArrowIpcLocalState : public LocalTableFunctionState { -- unique_ptr appender; -- idx_t current_count = 0; -- bool checked_schema = false; -+ unique_ptr appender; -+ idx_t current_count = 0; -+ bool checked_schema = false; - }; - -- --unique_ptr ToArrowIPCFunction::InitLocal(ExecutionContext &context, TableFunctionInitInput &input, -- GlobalTableFunctionState *global_state) { -- return make_uniq(); -+unique_ptr -+ToArrowIPCFunction::InitLocal(ExecutionContext &context, -+ TableFunctionInitInput &input, -+ GlobalTableFunctionState *global_state) { -+ return make_uniq(); - } - --unique_ptr ToArrowIPCFunction::InitGlobal(ClientContext &context, -- TableFunctionInitInput &input) { -- return make_uniq(); -+unique_ptr -+ToArrowIPCFunction::InitGlobal(ClientContext &context, -+ TableFunctionInitInput &input) { -+ return make_uniq(); - } - --unique_ptr ToArrowIPCFunction::Bind(ClientContext &context, TableFunctionBindInput &input, -- vector &return_types, vector &names) { -- auto result = make_uniq(); -+unique_ptr -+ToArrowIPCFunction::Bind(ClientContext &context, TableFunctionBindInput &input, -+ vector &return_types, -+ vector &names) { -+ auto result = make_uniq(); - -- result->chunk_size = DEFAULT_CHUNK_SIZE * STANDARD_VECTOR_SIZE; -+ result->chunk_size = DEFAULT_CHUNK_SIZE * STANDARD_VECTOR_SIZE; - -- // Set return schema -- return_types.emplace_back(LogicalType::BLOB); -- names.emplace_back("ipc"); -- return_types.emplace_back(LogicalType::BOOLEAN); -- names.emplace_back("header"); -+ // Set return schema -+ return_types.emplace_back(LogicalType::BLOB); -+ names.emplace_back("ipc"); -+ return_types.emplace_back(LogicalType::BOOLEAN); -+ names.emplace_back("header"); - -- // Create the Arrow schema -- ArrowSchema schema; -- ArrowConverter::ToArrowSchema(&schema, input.input_table_types, input.input_table_names, context.GetClientProperties()); -- result->schema = arrow::ImportSchema(&schema).ValueOrDie(); -+ // Create the Arrow schema -+ ArrowSchema schema; -+ ArrowConverter::ToArrowSchema(&schema, input.input_table_types, -+ input.input_table_names, -+ context.GetClientProperties()); -+ result->schema = arrow::ImportSchema(&schema).ValueOrDie(); - -- return std::move(result); -+ return std::move(result); - } - --OperatorResultType ToArrowIPCFunction::Function(ExecutionContext &context, TableFunctionInput &data_p, DataChunk &input, -- DataChunk &output) { -- std::shared_ptr arrow_serialized_ipc_buffer; -- auto &data = (ToArrowIpcFunctionData &)*data_p.bind_data; -- auto &local_state = (ToArrowIpcLocalState &)*data_p.local_state; -- auto &global_state = (ToArrowIpcGlobalState &)*data_p.global_state; -- -- bool sending_schema = false; -- -- bool caching_disabled = !PhysicalOperator::OperatorCachingAllowed(context); -- -- if (!local_state.checked_schema) { -- if (!global_state.sent_schema) { -- lock_guard init_lock(global_state.lock); -- if (!global_state.sent_schema) { -- // This run will send the schema, other threads can just send the buffers -- global_state.sent_schema = true; -- sending_schema = true; -- } -- } -- local_state.checked_schema = true; -+OperatorResultType ToArrowIPCFunction::Function(ExecutionContext &context, -+ TableFunctionInput &data_p, -+ DataChunk &input, -+ DataChunk &output) { -+ std::shared_ptr arrow_serialized_ipc_buffer; -+ auto &data = (ToArrowIpcFunctionData &)*data_p.bind_data; -+ auto &local_state = (ToArrowIpcLocalState &)*data_p.local_state; -+ auto &global_state = (ToArrowIpcGlobalState &)*data_p.global_state; -+ -+ bool sending_schema = false; -+ -+ bool caching_disabled = !PhysicalOperator::OperatorCachingAllowed(context); -+ -+ if (!local_state.checked_schema) { -+ if (!global_state.sent_schema) { -+ lock_guard init_lock(global_state.lock); -+ if (!global_state.sent_schema) { -+ // This run will send the schema, other threads can just send the -+ // buffers -+ global_state.sent_schema = true; -+ sending_schema = true; -+ } -+ } -+ local_state.checked_schema = true; -+ } -+ -+ if (sending_schema) { -+ auto result = arrow::ipc::SerializeSchema(*data.schema); -+ arrow_serialized_ipc_buffer = result.ValueOrDie(); -+ output.data[1].SetValue(0, Value::BOOLEAN(1)); -+ } else { -+ if (!local_state.appender) { -+ local_state.appender = -+ make_uniq(input.GetTypes(), data.chunk_size, -+ context.client.GetClientProperties()); - } - -- if (sending_schema) { -- auto result = arrow::ipc::SerializeSchema(*data.schema); -- arrow_serialized_ipc_buffer = result.ValueOrDie(); -- output.data[1].SetValue(0, Value::BOOLEAN(1)); -+ // Append input chunk -+ local_state.appender->Append(input, 0, input.size(), input.size()); -+ local_state.current_count += input.size(); -+ -+ // If chunk size is reached, we can flush to IPC blob -+ if (caching_disabled || local_state.current_count >= data.chunk_size) { -+ // Construct record batch from DataChunk -+ ArrowArray arr = local_state.appender->Finalize(); -+ auto record_batch = -+ arrow::ImportRecordBatch(&arr, data.schema).ValueOrDie(); -+ -+ // Serialize recordbatch -+ auto options = arrow::ipc::IpcWriteOptions::Defaults(); -+ auto result = arrow::ipc::SerializeRecordBatch(*record_batch, options); -+ arrow_serialized_ipc_buffer = result.ValueOrDie(); -+ -+ // Reset appender -+ local_state.appender.reset(); -+ local_state.current_count = 0; -+ -+ output.data[1].SetValue(0, Value::BOOLEAN(0)); - } else { -- if (!local_state.appender) { -- local_state.appender = make_uniq(input.GetTypes(), data.chunk_size, context.client.GetClientProperties()); -- } -- -- // Append input chunk -- local_state.appender->Append(input, 0, input.size(), input.size()); -- local_state.current_count += input.size(); -- -- // If chunk size is reached, we can flush to IPC blob -- if (caching_disabled || local_state.current_count >= data.chunk_size) { -- // Construct record batch from DataChunk -- ArrowArray arr = local_state.appender->Finalize(); -- auto record_batch = arrow::ImportRecordBatch(&arr, data.schema).ValueOrDie(); -- -- // Serialize recordbatch -- auto options = arrow::ipc::IpcWriteOptions::Defaults(); -- auto result = arrow::ipc::SerializeRecordBatch(*record_batch, options); -- arrow_serialized_ipc_buffer = result.ValueOrDie(); -- -- // Reset appender -- local_state.appender.reset(); -- local_state.current_count = 0; -- -- output.data[1].SetValue(0, Value::BOOLEAN(0)); -- } else { -- return OperatorResultType::NEED_MORE_INPUT; -- } -+ return OperatorResultType::NEED_MORE_INPUT; - } -+ } -+ -+ // TODO clean up -+ auto wrapped_buffer = -+ make_buffer(arrow_serialized_ipc_buffer); -+ auto &vector = output.data[0]; -+ StringVector::AddBuffer(vector, wrapped_buffer); -+ auto data_ptr = (string_t *)vector.GetData(); -+ *data_ptr = string_t((const char *)arrow_serialized_ipc_buffer->data(), -+ arrow_serialized_ipc_buffer->size()); -+ output.SetCardinality(1); -+ -+ if (sending_schema) { -+ return OperatorResultType::HAVE_MORE_OUTPUT; -+ } else { -+ return OperatorResultType::NEED_MORE_INPUT; -+ } -+} - -- // TODO clean up -- auto wrapped_buffer = make_buffer(arrow_serialized_ipc_buffer); -+OperatorFinalizeResultType ToArrowIPCFunction::FunctionFinal( -+ ExecutionContext &context, TableFunctionInput &data_p, DataChunk &output) { -+ auto &data = (ToArrowIpcFunctionData &)*data_p.bind_data; -+ auto &local_state = (ToArrowIpcLocalState &)*data_p.local_state; -+ std::shared_ptr arrow_serialized_ipc_buffer; -+ -+ // TODO clean up -+ if (local_state.appender) { -+ ArrowArray arr = local_state.appender->Finalize(); -+ auto record_batch = -+ arrow::ImportRecordBatch(&arr, data.schema).ValueOrDie(); -+ -+ // Serialize recordbatch -+ auto options = arrow::ipc::IpcWriteOptions::Defaults(); -+ auto result = arrow::ipc::SerializeRecordBatch(*record_batch, options); -+ arrow_serialized_ipc_buffer = result.ValueOrDie(); -+ -+ auto wrapped_buffer = -+ make_buffer(arrow_serialized_ipc_buffer); - auto &vector = output.data[0]; - StringVector::AddBuffer(vector, wrapped_buffer); - auto data_ptr = (string_t *)vector.GetData(); -- *data_ptr = string_t((const char *)arrow_serialized_ipc_buffer->data(), arrow_serialized_ipc_buffer->size()); -+ *data_ptr = string_t((const char *)arrow_serialized_ipc_buffer->data(), -+ arrow_serialized_ipc_buffer->size()); - output.SetCardinality(1); -+ local_state.appender.reset(); -+ output.data[1].SetValue(0, Value::BOOLEAN(0)); -+ } - -- if (sending_schema) { -- return OperatorResultType::HAVE_MORE_OUTPUT; -- } else { -- return OperatorResultType::NEED_MORE_INPUT; -- } --} -- --OperatorFinalizeResultType ToArrowIPCFunction::FunctionFinal(ExecutionContext &context, TableFunctionInput &data_p, -- DataChunk &output) { -- auto &data = (ToArrowIpcFunctionData &)*data_p.bind_data; -- auto &local_state = (ToArrowIpcLocalState &)*data_p.local_state; -- std::shared_ptr arrow_serialized_ipc_buffer; -- -- // TODO clean up -- if (local_state.appender) { -- ArrowArray arr = local_state.appender->Finalize(); -- auto record_batch = arrow::ImportRecordBatch(&arr, data.schema).ValueOrDie(); -- -- // Serialize recordbatch -- auto options = arrow::ipc::IpcWriteOptions::Defaults(); -- auto result = arrow::ipc::SerializeRecordBatch(*record_batch, options); -- arrow_serialized_ipc_buffer = result.ValueOrDie(); -- -- auto wrapped_buffer = make_buffer(arrow_serialized_ipc_buffer); -- auto &vector = output.data[0]; -- StringVector::AddBuffer(vector, wrapped_buffer); -- auto data_ptr = (string_t *)vector.GetData(); -- *data_ptr = string_t((const char *)arrow_serialized_ipc_buffer->data(), arrow_serialized_ipc_buffer->size()); -- output.SetCardinality(1); -- local_state.appender.reset(); -- output.data[1].SetValue(0, Value::BOOLEAN(0)); -- } -- -- return OperatorFinalizeResultType::FINISHED; -+ return OperatorFinalizeResultType::FINISHED; - } - -- - TableFunction ToArrowIPCFunction::GetFunction() { -- TableFunction fun("to_arrow_ipc", {LogicalType::TABLE}, nullptr, ToArrowIPCFunction::Bind, -- ToArrowIPCFunction::InitGlobal,ToArrowIPCFunction::InitLocal); -- fun.in_out_function = ToArrowIPCFunction::Function; -- fun.in_out_function_final = ToArrowIPCFunction::FunctionFinal; -+ TableFunction fun("to_arrow_ipc", {LogicalType::TABLE}, nullptr, -+ ToArrowIPCFunction::Bind, ToArrowIPCFunction::InitGlobal, -+ ToArrowIPCFunction::InitLocal); -+ fun.in_out_function = ToArrowIPCFunction::Function; -+ fun.in_out_function_final = ToArrowIPCFunction::FunctionFinal; - -- return fun; -+ return fun; - } - - } // namespace duckdb -\ No newline at end of file -diff --git a/src/include/arrow_extension.hpp b/src/include/arrow_extension.hpp -index 8ad174e..7d600d1 100644 ---- a/src/include/arrow_extension.hpp -+++ b/src/include/arrow_extension.hpp -@@ -6,8 +6,8 @@ namespace duckdb { - - class ArrowExtension : public Extension { - public: -- void Load(DuckDB &db) override; -- std::string Name() override; -+ void Load(DuckDB &db) override; -+ std::string Name() override; - }; - - } // namespace duckdb -diff --git a/src/include/arrow_scan_ipc.hpp b/src/include/arrow_scan_ipc.hpp -index 4ec1b9f..66a7827 100644 ---- a/src/include/arrow_scan_ipc.hpp -+++ b/src/include/arrow_scan_ipc.hpp -@@ -9,20 +9,23 @@ namespace duckdb { - - struct ArrowIPCScanFunctionData : public ArrowScanFunctionData { - public: -- using ArrowScanFunctionData::ArrowScanFunctionData; -- unique_ptr stream_decoder = nullptr; -+ using ArrowScanFunctionData::ArrowScanFunctionData; -+ unique_ptr stream_decoder = nullptr; - }; - --// IPC Table scan is identical to ArrowTableFunction arrow scan except instead of CDataInterface header pointers, it --// takes a bunch of pointers pointing to buffers containing data in Arrow IPC format -+// IPC Table scan is identical to ArrowTableFunction arrow scan except instead -+// of CDataInterface header pointers, it takes a bunch of pointers pointing to -+// buffers containing data in Arrow IPC format - struct ArrowIPCTableFunction : public ArrowTableFunction { - public: -- static TableFunction GetFunction(); -+ static TableFunction GetFunction(); - - private: -- static unique_ptr ArrowScanBind(ClientContext &context, TableFunctionBindInput &input, -- vector &return_types, vector &names); -- static void ArrowScanFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output); -+ static unique_ptr -+ ArrowScanBind(ClientContext &context, TableFunctionBindInput &input, -+ vector &return_types, vector &names); -+ static void ArrowScanFunction(ClientContext &context, -+ TableFunctionInput &data_p, DataChunk &output); - }; - - } // namespace duckdb -diff --git a/src/include/arrow_stream_buffer.hpp b/src/include/arrow_stream_buffer.hpp -index a4cbe97..e486c72 100644 ---- a/src/include/arrow_stream_buffer.hpp -+++ b/src/include/arrow_stream_buffer.hpp -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - /// File copied from - /// https://github.com/duckdb/duckdb-wasm/blob/0ad10e7db4ef4025f5f4120be37addc4ebe29618/lib/include/duckdb/web/arrow_stream_buffer.h -@@ -21,76 +22,72 @@ namespace duckdb { - - struct ArrowIPCStreamBuffer : public arrow::ipc::Listener { - protected: -- /// The schema -- std::shared_ptr schema_; -- /// The batches -- std::vector> batches_; -- /// Is eos? -- bool is_eos_; -+ /// The schema -+ std::shared_ptr schema_; -+ /// The batches -+ std::vector> batches_; -+ /// Is eos? -+ bool is_eos_; - -- /// Decoded a record batch -- arrow::Status OnSchemaDecoded(std::shared_ptr schema); -- /// Decoded a record batch -- arrow::Status OnRecordBatchDecoded(std::shared_ptr record_batch); -- /// Reached end of stream -- arrow::Status OnEOS(); -+ /// Decoded a record batch -+ arrow::Status OnSchemaDecoded(std::shared_ptr schema); -+ /// Decoded a record batch -+ arrow::Status -+ OnRecordBatchDecoded(std::shared_ptr record_batch); -+ /// Reached end of stream -+ arrow::Status OnEOS(); - - public: -- /// Constructor -- ArrowIPCStreamBuffer(); -+ /// Constructor -+ ArrowIPCStreamBuffer(); - -- /// Is end of stream? -- bool is_eos() const { -- return is_eos_; -- } -- /// Return the schema -- std::shared_ptr &schema() { -- return schema_; -- } -- /// Return the batches -- std::vector> &batches() { -- return batches_; -- } -+ /// Is end of stream? -+ bool is_eos() const { return is_eos_; } -+ /// Return the schema -+ std::shared_ptr &schema() { return schema_; } -+ /// Return the batches -+ std::vector> &batches() { -+ return batches_; -+ } - }; - - struct ArrowIPCStreamBufferReader : public arrow::RecordBatchReader { - protected: -- /// The buffer -- std::shared_ptr buffer_; -- /// The batch index -- size_t next_batch_id_; -+ /// The buffer -+ std::shared_ptr buffer_; -+ /// The batch index -+ size_t next_batch_id_; - - public: -- /// Constructor -- ArrowIPCStreamBufferReader(std::shared_ptr buffer); -- /// Destructor -- ~ArrowIPCStreamBufferReader() = default; -+ /// Constructor -+ ArrowIPCStreamBufferReader(std::shared_ptr buffer); -+ /// Destructor -+ ~ArrowIPCStreamBufferReader() = default; - -- /// Get the schema -- std::shared_ptr schema() const override; -- /// Read the next record batch in the stream. Return null for batch when reaching end of stream -- arrow::Status ReadNext(std::shared_ptr *batch) override; -+ /// Get the schema -+ std::shared_ptr schema() const override; -+ /// Read the next record batch in the stream. Return null for batch when -+ /// reaching end of stream -+ arrow::Status ReadNext(std::shared_ptr *batch) override; - -- /// Create arrow array stream wrapper -- static duckdb::unique_ptr CreateStream(uintptr_t buffer_ptr, -- ArrowStreamParameters ¶meters); -- /// Create arrow array stream wrapper -- static void GetSchema(uintptr_t buffer_ptr, ArrowSchemaWrapper &schema); -+ /// Create arrow array stream wrapper -+ static duckdb::unique_ptr -+ CreateStream(uintptr_t buffer_ptr, ArrowStreamParameters ¶meters); -+ /// Create arrow array stream wrapper -+ static void GetSchema(uintptr_t buffer_ptr, ArrowSchemaWrapper &schema); - }; - - struct BufferingArrowIPCStreamDecoder : public arrow::ipc::StreamDecoder { - protected: -- /// The buffer -- std::shared_ptr buffer_; -+ /// The buffer -+ std::shared_ptr buffer_; - - public: -- /// Constructor -- BufferingArrowIPCStreamDecoder( -- std::shared_ptr buffer = std::make_shared()); -- /// Get the buffer -- std::shared_ptr &buffer() { -- return buffer_; -- } -+ /// Constructor -+ BufferingArrowIPCStreamDecoder(std::shared_ptr buffer = -+ std::make_shared()); -+ /// Get the buffer -+ std::shared_ptr &buffer() { return buffer_; } - }; - - } // namespace duckdb -diff --git a/src/include/arrow_to_ipc.hpp b/src/include/arrow_to_ipc.hpp -index b4eb9d4..6c8995a 100644 ---- a/src/include/arrow_to_ipc.hpp -+++ b/src/include/arrow_to_ipc.hpp -@@ -3,36 +3,42 @@ - #include "arrow/buffer.h" - #include "duckdb.hpp" - -+#include -+ - namespace duckdb { - - class ArrowStringVectorBuffer : public VectorBuffer { - public: -- explicit ArrowStringVectorBuffer(std::shared_ptr buffer_p) -- : VectorBuffer(VectorBufferType::OPAQUE_BUFFER), buffer(std::move(buffer_p)) { -- } -+ explicit ArrowStringVectorBuffer(std::shared_ptr buffer_p) -+ : VectorBuffer(VectorBufferType::OPAQUE_BUFFER), -+ buffer(std::move(buffer_p)) {} - - private: -- std::shared_ptr buffer; -+ std::shared_ptr buffer; - }; - -- - class ToArrowIPCFunction { - public: -- //! note: this is the number of vectors per chunk -- static constexpr idx_t DEFAULT_CHUNK_SIZE = 120; -+ //! note: this is the number of vectors per chunk -+ static constexpr idx_t DEFAULT_CHUNK_SIZE = 120; - -- static TableFunction GetFunction(); -+ static TableFunction GetFunction(); - - private: -- static unique_ptr InitLocal(ExecutionContext &context, TableFunctionInitInput &input, -- GlobalTableFunctionState *global_state); -- static unique_ptr InitGlobal(ClientContext &context, -- TableFunctionInitInput &input); -- static unique_ptr Bind(ClientContext &context, TableFunctionBindInput &input, -- vector &return_types, vector &names); -- static OperatorResultType Function(ExecutionContext &context, TableFunctionInput &data_p, DataChunk &input, -- DataChunk &output); -- static OperatorFinalizeResultType FunctionFinal(ExecutionContext &context, TableFunctionInput &data_p, -- DataChunk &output); -+ static unique_ptr -+ InitLocal(ExecutionContext &context, TableFunctionInitInput &input, -+ GlobalTableFunctionState *global_state); -+ static unique_ptr -+ InitGlobal(ClientContext &context, TableFunctionInitInput &input); -+ static unique_ptr Bind(ClientContext &context, -+ TableFunctionBindInput &input, -+ vector &return_types, -+ vector &names); -+ static OperatorResultType Function(ExecutionContext &context, -+ TableFunctionInput &data_p, -+ DataChunk &input, DataChunk &output); -+ static OperatorFinalizeResultType FunctionFinal(ExecutionContext &context, -+ TableFunctionInput &data_p, -+ DataChunk &output); - }; // namespace duckdb --} -+} // namespace duckdb diff --git a/.github/patches/extensions/aws/0001-update-tests.patch b/.github/patches/extensions/aws/0001-update-tests.patch deleted file mode 100644 index 8e668b4e061..00000000000 --- a/.github/patches/extensions/aws/0001-update-tests.patch +++ /dev/null @@ -1,53 +0,0 @@ -From e8e6c286376d97e0a695284fc32b3b67a77e35af Mon Sep 17 00:00:00 2001 -From: stephaniewang -Date: Thu, 18 Apr 2024 21:41:29 -0400 -Subject: [PATCH] update tests - ---- - test/sql/aws_minio_secret.test | 2 +- - test/sql/aws_secret_gcs.test | 2 +- - test/sql/aws_secret_r2.test | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/test/sql/aws_minio_secret.test b/test/sql/aws_minio_secret.test -index 2ddc29f..34c4c92 100644 ---- a/test/sql/aws_minio_secret.test -+++ b/test/sql/aws_minio_secret.test -@@ -28,7 +28,7 @@ CREATE SECRET my_aws_secret ( - ); - - query I --SELECT which_secret('s3://test-bucket/aws_minio_secret/secret1/test.csv', 's3') -+SELECT name FROM which_secret('s3://test-bucket/aws_minio_secret/secret1/test.csv', 's3') - ---- - my_aws_secret - -diff --git a/test/sql/aws_secret_gcs.test b/test/sql/aws_secret_gcs.test -index 0b1fd40..cbed048 100644 ---- a/test/sql/aws_secret_gcs.test -+++ b/test/sql/aws_secret_gcs.test -@@ -18,7 +18,7 @@ CREATE SECRET s1 ( - ); - - query I --SELECT which_secret('gcs://haha/hoehoe.parkoe', 'gcs') -+SELECT name FROM which_secret('gcs://haha/hoehoe.parkoe', 'gcs') - ---- - s1 - -diff --git a/test/sql/aws_secret_r2.test b/test/sql/aws_secret_r2.test -index 01be38b..19ebd1e 100644 ---- a/test/sql/aws_secret_r2.test -+++ b/test/sql/aws_secret_r2.test -@@ -19,7 +19,7 @@ CREATE SECRET s1 ( - ); - - query I --SELECT which_secret('r2://haha/hoehoe.parkoe', 'r2') -+SELECT name FROM which_secret('r2://haha/hoehoe.parkoe', 'r2') - ---- - s1 - --- -2.39.2 (Apple Git-143) - diff --git a/.github/patches/extensions/aws/shared_ptr.patch b/.github/patches/extensions/aws/shared_ptr.patch deleted file mode 100644 index 7cd90185e26..00000000000 --- a/.github/patches/extensions/aws/shared_ptr.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff --git a/src/aws_secret.cpp b/src/aws_secret.cpp -index 75062b9..179cc29 100644 ---- a/src/aws_secret.cpp -+++ b/src/aws_secret.cpp -@@ -40,24 +40,24 @@ public: - - for (const auto &item : chain_list) { - if (item == "sts") { -- AddProvider(make_shared()); -+ AddProvider(std::make_shared()); - } else if (item == "sso") { - if (profile.empty()) { -- AddProvider(make_shared()); -+ AddProvider(std::make_shared()); - } else { -- AddProvider(make_shared(profile)); -+ AddProvider(std::make_shared(profile)); - } - } else if (item == "env") { -- AddProvider(make_shared()); -+ AddProvider(std::make_shared()); - } else if (item == "instance") { -- AddProvider(make_shared()); -+ AddProvider(std::make_shared()); - } else if (item == "process") { -- AddProvider(make_shared()); -+ AddProvider(std::make_shared()); - } else if (item == "config") { - if (profile.empty()) { -- AddProvider(make_shared()); -+ AddProvider(std::make_shared()); - } else { -- AddProvider(make_shared(profile.c_str())); -+ AddProvider(std::make_shared(profile.c_str())); - } - } else { - throw InvalidInputException("Unknown provider found while parsing AWS credential chain string: '%s'", diff --git a/.github/patches/extensions/azure/shared_ptr.patch b/.github/patches/extensions/azure/shared_ptr.patch deleted file mode 100644 index bee19cfb4b8..00000000000 --- a/.github/patches/extensions/azure/shared_ptr.patch +++ /dev/null @@ -1,400 +0,0 @@ -diff --git a/src/azure_blob_filesystem.cpp b/src/azure_blob_filesystem.cpp -index bc34eb9..42f9323 100644 ---- a/src/azure_blob_filesystem.cpp -+++ b/src/azure_blob_filesystem.cpp -@@ -3,6 +3,8 @@ - #include "azure_storage_account_client.hpp" - #include "duckdb.hpp" - #include "duckdb/common/exception.hpp" -+#include "duckdb/common/helper.hpp" -+#include "duckdb/common/shared_ptr.hpp" - #include "duckdb/common/http_state.hpp" - #include "duckdb/common/file_opener.hpp" - #include "duckdb/common/string_util.hpp" -@@ -201,13 +203,13 @@ void AzureBlobStorageFileSystem::ReadRange(AzureFileHandle &handle, idx_t file_o - } - } - --std::shared_ptr AzureBlobStorageFileSystem::CreateStorageContext(optional_ptr opener, -- const string &path, -- const AzureParsedUrl &parsed_url) { -+shared_ptr AzureBlobStorageFileSystem::CreateStorageContext(optional_ptr opener, -+ const string &path, -+ const AzureParsedUrl &parsed_url) { - auto azure_read_options = ParseAzureReadOptions(opener); - -- return std::make_shared(ConnectToBlobStorageAccount(opener, path, parsed_url), -- azure_read_options); -+ return make_shared_ptr(ConnectToBlobStorageAccount(opener, path, parsed_url), -+ azure_read_options); - } - - } // namespace duckdb -diff --git a/src/azure_dfs_filesystem.cpp b/src/azure_dfs_filesystem.cpp -index 5ccbed0..739078c 100644 ---- a/src/azure_dfs_filesystem.cpp -+++ b/src/azure_dfs_filesystem.cpp -@@ -1,6 +1,8 @@ - #include "azure_dfs_filesystem.hpp" - #include "azure_storage_account_client.hpp" - #include "duckdb/common/exception.hpp" -+#include "duckdb/common/helper.hpp" -+#include "duckdb/common/shared_ptr.hpp" - #include "duckdb/function/scalar/string_functions.hpp" - #include - #include -@@ -185,13 +187,13 @@ void AzureDfsStorageFileSystem::ReadRange(AzureFileHandle &handle, idx_t file_of - } - } - --std::shared_ptr AzureDfsStorageFileSystem::CreateStorageContext(optional_ptr opener, -- const string &path, -- const AzureParsedUrl &parsed_url) { -+shared_ptr AzureDfsStorageFileSystem::CreateStorageContext(optional_ptr opener, -+ const string &path, -+ const AzureParsedUrl &parsed_url) { - auto azure_read_options = ParseAzureReadOptions(opener); - -- return std::make_shared(ConnectToDfsStorageAccount(opener, path, parsed_url), -- azure_read_options); -+ return make_shared_ptr(ConnectToDfsStorageAccount(opener, path, parsed_url), -+ azure_read_options); - } - - } // namespace duckdb -diff --git a/src/azure_filesystem.cpp b/src/azure_filesystem.cpp -index bbf5275..6175421 100644 ---- a/src/azure_filesystem.cpp -+++ b/src/azure_filesystem.cpp -@@ -1,5 +1,6 @@ - #include "azure_filesystem.hpp" - #include "duckdb/common/exception.hpp" -+#include "duckdb/common/shared_ptr.hpp" - #include "duckdb/common/types/value.hpp" - #include "duckdb/main/client_context.hpp" - #include -@@ -53,8 +54,8 @@ void AzureStorageFileSystem::LoadFileInfo(AzureFileHandle &handle) { - } - } - --unique_ptr AzureStorageFileSystem::OpenFile(const string &path,FileOpenFlags flags, -- optional_ptr opener) { -+unique_ptr AzureStorageFileSystem::OpenFile(const string &path, FileOpenFlags flags, -+ optional_ptr opener) { - D_ASSERT(flags.Compression() == FileCompressionType::UNCOMPRESSED); - - if (flags.OpenForWriting()) { -@@ -153,16 +154,16 @@ int64_t AzureStorageFileSystem::Read(FileHandle &handle, void *buffer, int64_t n - return nr_bytes; - } - --std::shared_ptr AzureStorageFileSystem::GetOrCreateStorageContext(optional_ptr opener, -- const string &path, -- const AzureParsedUrl &parsed_url) { -+shared_ptr AzureStorageFileSystem::GetOrCreateStorageContext(optional_ptr opener, -+ const string &path, -+ const AzureParsedUrl &parsed_url) { - Value value; - bool azure_context_caching = true; - if (FileOpener::TryGetCurrentSetting(opener, "azure_context_caching", value)) { - azure_context_caching = value.GetValue(); - } - -- std::shared_ptr result; -+ shared_ptr result; - if (azure_context_caching) { - auto client_context = FileOpener::TryGetClientContext(opener); - -@@ -182,7 +183,7 @@ std::shared_ptr AzureStorageFileSystem::GetOrCreateStorageCon - result = CreateStorageContext(opener, path, parsed_url); - registered_state[context_key] = result; - } else { -- result = std::shared_ptr(storage_account_it->second, azure_context_state); -+ result = shared_ptr(storage_account_it->second, azure_context_state); - } - } - } else { -diff --git a/src/azure_storage_account_client.cpp b/src/azure_storage_account_client.cpp -index 5a22e60..11ad859 100644 ---- a/src/azure_storage_account_client.cpp -+++ b/src/azure_storage_account_client.cpp -@@ -3,6 +3,8 @@ - #include "duckdb/catalog/catalog_transaction.hpp" - #include "duckdb/common/enums/statement_type.hpp" - #include "duckdb/common/exception.hpp" -+#include "duckdb/common/shared_ptr.hpp" -+#include "duckdb/common/helper.hpp" - #include "duckdb/common/file_opener.hpp" - #include "duckdb/common/string_util.hpp" - #include "duckdb/main/client_context.hpp" -@@ -75,12 +77,12 @@ static std::string AccountUrl(const AzureParsedUrl &azure_parsed_url) { - - template - static T ToClientOptions(const Azure::Core::Http::Policies::TransportOptions &transport_options, -- std::shared_ptr http_state) { -+ shared_ptr http_state) { - static_assert(std::is_base_of::value, - "type parameter must be an Azure ClientOptions"); - T options; - options.Transport = transport_options; -- if (nullptr != http_state) { -+ if (http_state != nullptr) { - // Because we mainly want to have stats on what has been needed and not on - // what has been used on the network, we register the policy on `PerOperationPolicies` - // part and not the `PerRetryPolicies`. Network issues will result in retry that can -@@ -92,13 +94,13 @@ static T ToClientOptions(const Azure::Core::Http::Policies::TransportOptions &tr - - static Azure::Storage::Blobs::BlobClientOptions - ToBlobClientOptions(const Azure::Core::Http::Policies::TransportOptions &transport_options, -- std::shared_ptr http_state) { -+ shared_ptr http_state) { - return ToClientOptions(transport_options, std::move(http_state)); - } - - static Azure::Storage::Files::DataLake::DataLakeClientOptions - ToDfsClientOptions(const Azure::Core::Http::Policies::TransportOptions &transport_options, -- std::shared_ptr http_state) { -+ shared_ptr http_state) { - return ToClientOptions(transport_options, - std::move(http_state)); - } -@@ -110,14 +112,14 @@ ToTokenCredentialOptions(const Azure::Core::Http::Policies::TransportOptions &tr - return options; - } - --static std::shared_ptr GetHttpState(optional_ptr opener) { -+static shared_ptr GetHttpState(optional_ptr opener) { - Value value; - bool enable_http_stats = false; - if (FileOpener::TryGetCurrentSetting(opener, "azure_http_stats", value)) { - enable_http_stats = value.GetValue(); - } - -- std::shared_ptr http_state; -+ shared_ptr http_state; - if (enable_http_stats) { - http_state = HTTPState::TryGetState(opener); - } -@@ -168,7 +170,7 @@ CreateClientCredential(const std::string &tenant_id, const std::string &client_i - auto credential_options = ToTokenCredentialOptions(transport_options); - if (!client_secret.empty()) { - return std::make_shared(tenant_id, client_id, client_secret, -- credential_options); -+ credential_options); - } else if (!client_certificate_path.empty()) { - return std::make_shared( - tenant_id, client_id, client_certificate_path, credential_options); -@@ -408,8 +410,9 @@ GetDfsStorageAccountClientFromServicePrincipalProvider(optional_ptr - return Azure::Storage::Files::DataLake::DataLakeServiceClient(account_url, token_credential, dfs_options); - } - --static Azure::Storage::Blobs::BlobServiceClient --GetBlobStorageAccountClient(optional_ptr opener, const KeyValueSecret &secret, const AzureParsedUrl &azure_parsed_url) { -+static Azure::Storage::Blobs::BlobServiceClient GetBlobStorageAccountClient(optional_ptr opener, -+ const KeyValueSecret &secret, -+ const AzureParsedUrl &azure_parsed_url) { - auto &provider = secret.GetProvider(); - // default provider - if (provider == "config") { -@@ -424,7 +427,8 @@ GetBlobStorageAccountClient(optional_ptr opener, const KeyValueSecre - } - - static Azure::Storage::Files::DataLake::DataLakeServiceClient --GetDfsStorageAccountClient(optional_ptr opener, const KeyValueSecret &secret, const AzureParsedUrl &azure_parsed_url) { -+GetDfsStorageAccountClient(optional_ptr opener, const KeyValueSecret &secret, -+ const AzureParsedUrl &azure_parsed_url) { - auto &provider = secret.GetProvider(); - // default provider - if (provider == "config") { -@@ -505,7 +509,8 @@ const SecretMatch LookupSecret(optional_ptr opener, const std::strin - return {}; - } - --Azure::Storage::Blobs::BlobServiceClient ConnectToBlobStorageAccount(optional_ptr opener, const std::string &path, -+Azure::Storage::Blobs::BlobServiceClient ConnectToBlobStorageAccount(optional_ptr opener, -+ const std::string &path, - const AzureParsedUrl &azure_parsed_url) { - - auto secret_match = LookupSecret(opener, path); -@@ -519,7 +524,8 @@ Azure::Storage::Blobs::BlobServiceClient ConnectToBlobStorageAccount(optional_pt - } - - Azure::Storage::Files::DataLake::DataLakeServiceClient --ConnectToDfsStorageAccount(optional_ptr opener, const std::string &path, const AzureParsedUrl &azure_parsed_url) { -+ConnectToDfsStorageAccount(optional_ptr opener, const std::string &path, -+ const AzureParsedUrl &azure_parsed_url) { - auto secret_match = LookupSecret(opener, path); - if (secret_match.HasMatch()) { - const auto &base_secret = secret_match.GetSecret(); -diff --git a/src/http_state_policy.cpp b/src/http_state_policy.cpp -index be2d61d..baa3f97 100644 ---- a/src/http_state_policy.cpp -+++ b/src/http_state_policy.cpp -@@ -1,5 +1,6 @@ - #include "http_state_policy.hpp" - #include -+#include "duckdb/common/shared_ptr.hpp" - #include - #include - #include -@@ -8,7 +9,7 @@ const static std::string CONTENT_LENGTH = "content-length"; - - namespace duckdb { - --HttpStatePolicy::HttpStatePolicy(std::shared_ptr http_state) : http_state(std::move(http_state)) { -+HttpStatePolicy::HttpStatePolicy(shared_ptr http_state) : http_state(std::move(http_state)) { - } - - std::unique_ptr -@@ -34,12 +35,12 @@ HttpStatePolicy::Send(Azure::Core::Http::Request &request, Azure::Core::Http::Po - } - - const auto *body_stream = request.GetBodyStream(); -- if (nullptr != body_stream) { -+ if (body_stream != nullptr) { - http_state->total_bytes_sent += body_stream->Length(); - } - - auto result = next_policy.Send(request, context); -- if (nullptr != result) { -+ if (result != nullptr) { - const auto &response_body = result->GetBody(); - if (response_body.size() != 0) { - http_state->total_bytes_received += response_body.size(); -diff --git a/src/include/azure_blob_filesystem.hpp b/src/include/azure_blob_filesystem.hpp -index 4d10ebe..638864a 100644 ---- a/src/include/azure_blob_filesystem.hpp -+++ b/src/include/azure_blob_filesystem.hpp -@@ -1,6 +1,8 @@ - #pragma once - - #include "duckdb.hpp" -+#include "duckdb/common/shared_ptr.hpp" -+#include "duckdb/common/unique_ptr.hpp" - #include "azure_parsed_url.hpp" - #include "azure_filesystem.hpp" - #include -@@ -57,10 +59,10 @@ protected: - const string &GetContextPrefix() const override { - return PATH_PREFIX; - } -- std::shared_ptr CreateStorageContext(optional_ptr opener, const string &path, -- const AzureParsedUrl &parsed_url) override; -- duckdb::unique_ptr CreateHandle(const string &path, FileOpenFlags flags, -- optional_ptr opener) override; -+ shared_ptr CreateStorageContext(optional_ptr opener, const string &path, -+ const AzureParsedUrl &parsed_url) override; -+ unique_ptr CreateHandle(const string &path, FileOpenFlags flags, -+ optional_ptr opener) override; - - void ReadRange(AzureFileHandle &handle, idx_t file_offset, char *buffer_out, idx_t buffer_out_len) override; - }; -diff --git a/src/include/azure_dfs_filesystem.hpp b/src/include/azure_dfs_filesystem.hpp -index cdcdb23..8f35dc7 100644 ---- a/src/include/azure_dfs_filesystem.hpp -+++ b/src/include/azure_dfs_filesystem.hpp -@@ -2,6 +2,8 @@ - - #include "azure_filesystem.hpp" - #include "duckdb/common/file_opener.hpp" -+#include "duckdb/common/shared_ptr.hpp" -+#include "duckdb/common/unique_ptr.hpp" - #include - #include - #include -@@ -55,10 +57,10 @@ protected: - const string &GetContextPrefix() const override { - return PATH_PREFIX; - } -- std::shared_ptr CreateStorageContext(optional_ptr opener, const string &path, -- const AzureParsedUrl &parsed_url) override; -- duckdb::unique_ptr CreateHandle(const string &path, FileOpenFlags flags, -- optional_ptr opener) override; -+ shared_ptr CreateStorageContext(optional_ptr opener, const string &path, -+ const AzureParsedUrl &parsed_url) override; -+ unique_ptr CreateHandle(const string &path, FileOpenFlags flags, -+ optional_ptr opener) override; - - void ReadRange(AzureFileHandle &handle, idx_t file_offset, char *buffer_out, idx_t buffer_out_len) override; - }; -diff --git a/src/include/azure_filesystem.hpp b/src/include/azure_filesystem.hpp -index 338c744..02ed44b 100644 ---- a/src/include/azure_filesystem.hpp -+++ b/src/include/azure_filesystem.hpp -@@ -3,6 +3,7 @@ - #include "azure_parsed_url.hpp" - #include "duckdb/common/assert.hpp" - #include "duckdb/common/file_opener.hpp" -+#include "duckdb/common/shared_ptr.hpp" - #include "duckdb/common/file_system.hpp" - #include "duckdb/main/client_context_state.hpp" - #include -@@ -99,14 +100,14 @@ public: - - protected: - virtual duckdb::unique_ptr CreateHandle(const string &path, FileOpenFlags flags, -- optional_ptr opener) = 0; -+ optional_ptr opener) = 0; - virtual void ReadRange(AzureFileHandle &handle, idx_t file_offset, char *buffer_out, idx_t buffer_out_len) = 0; - - virtual const string &GetContextPrefix() const = 0; -- std::shared_ptr GetOrCreateStorageContext(optional_ptr opener, const string &path, -- const AzureParsedUrl &parsed_url); -- virtual std::shared_ptr CreateStorageContext(optional_ptr opener, const string &path, -- const AzureParsedUrl &parsed_url) = 0; -+ shared_ptr GetOrCreateStorageContext(optional_ptr opener, const string &path, -+ const AzureParsedUrl &parsed_url); -+ virtual shared_ptr CreateStorageContext(optional_ptr opener, const string &path, -+ const AzureParsedUrl &parsed_url) = 0; - - virtual void LoadRemoteFileInfo(AzureFileHandle &handle) = 0; - static AzureReadOptions ParseAzureReadOptions(optional_ptr opener); -diff --git a/src/include/azure_storage_account_client.hpp b/src/include/azure_storage_account_client.hpp -index 600fa10..aa9a6e5 100644 ---- a/src/include/azure_storage_account_client.hpp -+++ b/src/include/azure_storage_account_client.hpp -@@ -8,10 +8,12 @@ - - namespace duckdb { - --Azure::Storage::Blobs::BlobServiceClient ConnectToBlobStorageAccount(optional_ptr opener, const std::string &path, -+Azure::Storage::Blobs::BlobServiceClient ConnectToBlobStorageAccount(optional_ptr opener, -+ const std::string &path, - const AzureParsedUrl &azure_parsed_url); - - Azure::Storage::Files::DataLake::DataLakeServiceClient --ConnectToDfsStorageAccount(optional_ptr opener, const std::string &path, const AzureParsedUrl &azure_parsed_url); -+ConnectToDfsStorageAccount(optional_ptr opener, const std::string &path, -+ const AzureParsedUrl &azure_parsed_url); - - } // namespace duckdb -diff --git a/src/include/http_state_policy.hpp b/src/include/http_state_policy.hpp -index 310b9c3..9db73b6 100644 ---- a/src/include/http_state_policy.hpp -+++ b/src/include/http_state_policy.hpp -@@ -1,6 +1,7 @@ - #pragma once - - #include "duckdb/common/http_state.hpp" -+#include "duckdb/common/shared_ptr.hpp" - #include - #include - #include -@@ -11,7 +12,7 @@ namespace duckdb { - - class HttpStatePolicy : public Azure::Core::Http::Policies::HttpPolicy { - public: -- HttpStatePolicy(std::shared_ptr http_state); -+ HttpStatePolicy(shared_ptr http_state); - - std::unique_ptr Send(Azure::Core::Http::Request &request, - Azure::Core::Http::Policies::NextHttpPolicy next_policy, -@@ -20,7 +21,7 @@ public: - std::unique_ptr Clone() const override; - - private: -- std::shared_ptr http_state; -+ shared_ptr http_state; - }; - - } // namespace duckdb diff --git a/.github/patches/extensions/postgres_scanner/shared_ptr.patch b/.github/patches/extensions/postgres_scanner/shared_ptr.patch deleted file mode 100644 index e9492082973..00000000000 --- a/.github/patches/extensions/postgres_scanner/shared_ptr.patch +++ /dev/null @@ -1,241 +0,0 @@ -diff --git a/src/include/postgres_binary_copy.hpp b/src/include/postgres_binary_copy.hpp -index 4d49b00..f69e4fa 100644 ---- a/src/include/postgres_binary_copy.hpp -+++ b/src/include/postgres_binary_copy.hpp -@@ -19,18 +19,19 @@ public: - PostgresBinaryCopyFunction(); - - static unique_ptr PostgresBinaryWriteBind(ClientContext &context, CopyFunctionBindInput &input, -- const vector &names, const vector &sql_types); -- -- static unique_ptr PostgresBinaryWriteInitializeGlobal(ClientContext &context, FunctionData &bind_data, -- const string &file_path); -- static unique_ptr PostgresBinaryWriteInitializeLocal(ExecutionContext &context, FunctionData &bind_data_p); -- static void PostgresBinaryWriteSink(ExecutionContext &context, FunctionData &bind_data_p, GlobalFunctionData &gstate, -- LocalFunctionData &lstate, DataChunk &input); -- static void PostgresBinaryWriteCombine(ExecutionContext &context, FunctionData &bind_data, GlobalFunctionData &gstate, -- LocalFunctionData &lstate); -- static void PostgresBinaryWriteFinalize(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate); -+ const vector &names, -+ const vector &sql_types); -+ -+ static unique_ptr -+ PostgresBinaryWriteInitializeGlobal(ClientContext &context, FunctionData &bind_data, const string &file_path); -+ static unique_ptr PostgresBinaryWriteInitializeLocal(ExecutionContext &context, -+ FunctionData &bind_data_p); -+ static void PostgresBinaryWriteSink(ExecutionContext &context, FunctionData &bind_data_p, -+ GlobalFunctionData &gstate, LocalFunctionData &lstate, DataChunk &input); -+ static void PostgresBinaryWriteCombine(ExecutionContext &context, FunctionData &bind_data, -+ GlobalFunctionData &gstate, LocalFunctionData &lstate); -+ static void PostgresBinaryWriteFinalize(ClientContext &context, FunctionData &bind_data, -+ GlobalFunctionData &gstate); - }; - -- -- - } // namespace duckdb -diff --git a/src/include/postgres_connection.hpp b/src/include/postgres_connection.hpp -index e4595e2..08fd19c 100644 ---- a/src/include/postgres_connection.hpp -+++ b/src/include/postgres_connection.hpp -@@ -10,6 +10,7 @@ - - #include "postgres_utils.hpp" - #include "postgres_result.hpp" -+#include "duckdb/common/shared_ptr.hpp" - - namespace duckdb { - class PostgresBinaryWriter; -diff --git a/src/include/storage/postgres_catalog_set.hpp b/src/include/storage/postgres_catalog_set.hpp -index e20a803..4fe45f6 100644 ---- a/src/include/storage/postgres_catalog_set.hpp -+++ b/src/include/storage/postgres_catalog_set.hpp -@@ -11,6 +11,7 @@ - #include "duckdb/transaction/transaction.hpp" - #include "duckdb/common/case_insensitive_map.hpp" - #include "duckdb/common/mutex.hpp" -+#include "duckdb/common/shared_ptr.hpp" - - namespace duckdb { - struct DropInfo; -diff --git a/src/include/storage/postgres_table_entry.hpp b/src/include/storage/postgres_table_entry.hpp -index d96dfad..529c234 100644 ---- a/src/include/storage/postgres_table_entry.hpp -+++ b/src/include/storage/postgres_table_entry.hpp -@@ -50,7 +50,7 @@ public: - - TableStorageInfo GetStorageInfo(ClientContext &context) override; - -- void BindUpdateConstraints(LogicalGet &get, LogicalProjection &proj, LogicalUpdate &update, -+ void BindUpdateConstraints(Binder &binder, LogicalGet &get, LogicalProjection &proj, LogicalUpdate &update, - ClientContext &context) override; - - //! Get the copy format (text or binary) that should be used when writing data to this table -diff --git a/src/postgres_binary_copy.cpp b/src/postgres_binary_copy.cpp -index f0d86a3..4c89c3f 100644 ---- a/src/postgres_binary_copy.cpp -+++ b/src/postgres_binary_copy.cpp -@@ -5,8 +5,7 @@ - - namespace duckdb { - --PostgresBinaryCopyFunction::PostgresBinaryCopyFunction() : -- CopyFunction("postgres_binary") { -+PostgresBinaryCopyFunction::PostgresBinaryCopyFunction() : CopyFunction("postgres_binary") { - - copy_to_bind = PostgresBinaryWriteBind; - copy_to_initialize_global = PostgresBinaryWriteInitializeGlobal; -@@ -54,16 +53,18 @@ struct PostgresBinaryCopyGlobalState : public GlobalFunctionData { - } - }; - --struct PostgresBinaryWriteBindData : public TableFunctionData { --}; -+struct PostgresBinaryWriteBindData : public TableFunctionData {}; - --unique_ptr PostgresBinaryCopyFunction::PostgresBinaryWriteBind(ClientContext &context, CopyFunctionBindInput &input, -- const vector &names, const vector &sql_types) { -+unique_ptr PostgresBinaryCopyFunction::PostgresBinaryWriteBind(ClientContext &context, -+ CopyFunctionBindInput &input, -+ const vector &names, -+ const vector &sql_types) { - return make_uniq(); - } - --unique_ptr PostgresBinaryCopyFunction::PostgresBinaryWriteInitializeGlobal(ClientContext &context, FunctionData &bind_data, -- const string &file_path) { -+unique_ptr -+PostgresBinaryCopyFunction::PostgresBinaryWriteInitializeGlobal(ClientContext &context, FunctionData &bind_data, -+ const string &file_path) { - auto result = make_uniq(); - auto &fs = FileSystem::GetFileSystem(context); - result->file_writer = make_uniq(fs, file_path); -@@ -72,25 +73,27 @@ unique_ptr PostgresBinaryCopyFunction::PostgresBinaryWriteIn - return std::move(result); - } - --unique_ptr PostgresBinaryCopyFunction::PostgresBinaryWriteInitializeLocal(ExecutionContext &context, FunctionData &bind_data_p) { -+unique_ptr -+PostgresBinaryCopyFunction::PostgresBinaryWriteInitializeLocal(ExecutionContext &context, FunctionData &bind_data_p) { - return make_uniq(); - } - --void PostgresBinaryCopyFunction::PostgresBinaryWriteSink(ExecutionContext &context, FunctionData &bind_data_p, GlobalFunctionData &gstate_p, -- LocalFunctionData &lstate, DataChunk &input) { -+void PostgresBinaryCopyFunction::PostgresBinaryWriteSink(ExecutionContext &context, FunctionData &bind_data_p, -+ GlobalFunctionData &gstate_p, LocalFunctionData &lstate, -+ DataChunk &input) { - auto &gstate = gstate_p.Cast(); - gstate.WriteChunk(input); - } - --void PostgresBinaryCopyFunction::PostgresBinaryWriteCombine(ExecutionContext &context, FunctionData &bind_data, GlobalFunctionData &gstate, -- LocalFunctionData &lstate) { -+void PostgresBinaryCopyFunction::PostgresBinaryWriteCombine(ExecutionContext &context, FunctionData &bind_data, -+ GlobalFunctionData &gstate, LocalFunctionData &lstate) { - } - --void PostgresBinaryCopyFunction::PostgresBinaryWriteFinalize(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate_p) { -+void PostgresBinaryCopyFunction::PostgresBinaryWriteFinalize(ClientContext &context, FunctionData &bind_data, -+ GlobalFunctionData &gstate_p) { - auto &gstate = gstate_p.Cast(); - // write the footer and close the file - gstate.Flush(); - } - -- --} -\ No newline at end of file -+} // namespace duckdb -\ No newline at end of file -diff --git a/src/postgres_connection.cpp b/src/postgres_connection.cpp -index 6372055..18fbd77 100644 ---- a/src/postgres_connection.cpp -+++ b/src/postgres_connection.cpp -@@ -3,6 +3,8 @@ - #include "duckdb/parser/parser.hpp" - #include "postgres_connection.hpp" - #include "duckdb/common/types/uuid.hpp" -+#include "duckdb/common/shared_ptr.hpp" -+#include "duckdb/common/helper.hpp" - - namespace duckdb { - -@@ -40,7 +42,7 @@ PostgresConnection &PostgresConnection::operator=(PostgresConnection &&other) no - - PostgresConnection PostgresConnection::Open(const string &connection_string) { - PostgresConnection result; -- result.connection = make_shared(PostgresUtils::PGConnect(connection_string)); -+ result.connection = make_shared_ptr(PostgresUtils::PGConnect(connection_string)); - result.dsn = connection_string; - return result; - } -diff --git a/src/postgres_extension.cpp b/src/postgres_extension.cpp -index 34d46d0..95988f2 100644 ---- a/src/postgres_extension.cpp -+++ b/src/postgres_extension.cpp -@@ -9,6 +9,7 @@ - #include "duckdb/catalog/catalog.hpp" - #include "duckdb/parser/parsed_data/create_table_function_info.hpp" - #include "duckdb/main/extension_util.hpp" -+#include "duckdb/common/helper.hpp" - #include "duckdb/main/database_manager.hpp" - #include "duckdb/main/attached_database.hpp" - #include "storage/postgres_catalog.hpp" -@@ -47,7 +48,7 @@ public: - class PostgresExtensionCallback : public ExtensionCallback { - public: - void OnConnectionOpened(ClientContext &context) override { -- context.registered_state.insert(make_pair("postgres_extension", make_shared())); -+ context.registered_state.insert(make_pair("postgres_extension", make_shared_ptr())); - } - }; - -@@ -123,7 +124,7 @@ static void LoadInternal(DatabaseInstance &db) { - - config.extension_callbacks.push_back(make_uniq()); - for (auto &connection : ConnectionManager::Get(db).GetConnectionList()) { -- connection->registered_state.insert(make_pair("postgres_extension", make_shared())); -+ connection->registered_state.insert(make_pair("postgres_extension", make_shared_ptr())); - } - } - -diff --git a/src/postgres_scanner.cpp b/src/postgres_scanner.cpp -index 449df0b..75c029f 100644 ---- a/src/postgres_scanner.cpp -+++ b/src/postgres_scanner.cpp -@@ -3,6 +3,8 @@ - #include - - #include "duckdb/main/extension_util.hpp" -+#include "duckdb/common/shared_ptr.hpp" -+#include "duckdb/common/helper.hpp" - #include "duckdb/parser/parsed_data/create_table_function_info.hpp" - #include "postgres_filter_pushdown.hpp" - #include "postgres_scanner.hpp" -diff --git a/src/storage/postgres_schema_set.cpp b/src/storage/postgres_schema_set.cpp -index 93c3f28..cd3b46f 100644 ---- a/src/storage/postgres_schema_set.cpp -+++ b/src/storage/postgres_schema_set.cpp -@@ -6,6 +6,7 @@ - #include "duckdb/parser/parsed_data/create_schema_info.hpp" - #include "storage/postgres_table_set.hpp" - #include "storage/postgres_catalog.hpp" -+#include "duckdb/common/shared_ptr.hpp" - - namespace duckdb { - -diff --git a/src/storage/postgres_table_entry.cpp b/src/storage/postgres_table_entry.cpp -index d791678..7ba1ad6 100644 ---- a/src/storage/postgres_table_entry.cpp -+++ b/src/storage/postgres_table_entry.cpp -@@ -31,7 +31,8 @@ unique_ptr PostgresTableEntry::GetStatistics(ClientContext &cont - return nullptr; - } - --void PostgresTableEntry::BindUpdateConstraints(LogicalGet &, LogicalProjection &, LogicalUpdate &, ClientContext &) { -+void PostgresTableEntry::BindUpdateConstraints(Binder &binder, LogicalGet &, LogicalProjection &, LogicalUpdate &, -+ ClientContext &) { - } - - TableFunction PostgresTableEntry::GetScanFunction(ClientContext &context, unique_ptr &bind_data) { diff --git a/.github/patches/extensions/sqlite_scanner/binder_update.patch b/.github/patches/extensions/sqlite_scanner/binder_update.patch deleted file mode 100644 index 7973f54281e..00000000000 --- a/.github/patches/extensions/sqlite_scanner/binder_update.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/src/include/storage/sqlite_table_entry.hpp b/src/include/storage/sqlite_table_entry.hpp -index 6e64d55..b08319b 100644 ---- a/src/include/storage/sqlite_table_entry.hpp -+++ b/src/include/storage/sqlite_table_entry.hpp -@@ -25,7 +25,7 @@ public: - - TableStorageInfo GetStorageInfo(ClientContext &context) override; - -- void BindUpdateConstraints(LogicalGet &get, LogicalProjection &proj, LogicalUpdate &update, -+ void BindUpdateConstraints(Binder &binder, LogicalGet &get, LogicalProjection &proj, LogicalUpdate &update, - ClientContext &context) override; - }; - -diff --git a/src/storage/sqlite_table_entry.cpp b/src/storage/sqlite_table_entry.cpp -index fadbb39..47378b0 100644 ---- a/src/storage/sqlite_table_entry.cpp -+++ b/src/storage/sqlite_table_entry.cpp -@@ -16,7 +16,8 @@ unique_ptr SQLiteTableEntry::GetStatistics(ClientContext &contex - return nullptr; - } - --void SQLiteTableEntry::BindUpdateConstraints(LogicalGet &, LogicalProjection &, LogicalUpdate &, ClientContext &) { -+void SQLiteTableEntry::BindUpdateConstraints(Binder &, LogicalGet &, LogicalProjection &, LogicalUpdate &, -+ ClientContext &) { - } - - TableFunction SQLiteTableEntry::GetScanFunction(ClientContext &context, unique_ptr &bind_data) { diff --git a/.github/patches/extensions/substrait/pushdown_semi_anti.patch b/.github/patches/extensions/substrait/pushdown_semi_anti.patch new file mode 100644 index 00000000000..5163fbde9d5 --- /dev/null +++ b/.github/patches/extensions/substrait/pushdown_semi_anti.patch @@ -0,0 +1,40 @@ +diff --git a/src/to_substrait.cpp b/src/to_substrait.cpp +index de0ffb3..ece0f5d 100644 +--- a/src/to_substrait.cpp ++++ b/src/to_substrait.cpp +@@ -864,7 +864,11 @@ substrait::Rel *DuckDBToSubstrait::TransformComparisonJoin(LogicalOperator &dop) + auto left_col_count = dop.children[0]->types.size(); + if (dop.children[0]->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN) { + auto child_join = (LogicalComparisonJoin *)dop.children[0].get(); +- left_col_count = child_join->left_projection_map.size() + child_join->right_projection_map.size(); ++ if (child_join->join_type != JoinType::SEMI && child_join->join_type != JoinType::ANTI) { ++ left_col_count = child_join->left_projection_map.size() + child_join->right_projection_map.size(); ++ } else { ++ left_col_count = child_join->left_projection_map.size(); ++ } + } + sjoin->set_allocated_expression( + CreateConjunction(djoin.conditions, [&](JoinCondition &in) { return TransformJoinCond(in, left_col_count); })); +diff --git a/test/sql/test_substrait_types.test b/test/sql/test_substrait_types.test +index 2bc47da..f3d2c65 100644 +--- a/test/sql/test_substrait_types.test ++++ b/test/sql/test_substrait_types.test +@@ -148,6 +148,9 @@ INSERT INTO timestz VALUES ('2021-11-26 10:15:13.123456+00'); + statement ok + CALL get_substrait('SELECT s FROM timestz WHERE s > ''2001-11-26 05:02:23.123456+00'' '); + ++# not supported because TIMETZ comparisons generate a UBIGINT ++mode skip ++ + statement ok + CREATE table times_tz (s TIMETZ); + +@@ -157,6 +160,8 @@ INSERT INTO times_tz VALUES ('05:40:00.000001'); + statement ok + CALL get_substrait('SELECT s FROM times_tz WHERE s = ''05:40:00.000001'' '); + ++mode unskip ++ + statement ok + CREATE table times (s TIME); + diff --git a/.github/patches/extensions/substrait/shared_ptr.patch b/.github/patches/extensions/substrait/shared_ptr.patch deleted file mode 100644 index d04cfb9655a..00000000000 --- a/.github/patches/extensions/substrait/shared_ptr.patch +++ /dev/null @@ -1,130 +0,0 @@ -diff --git a/src/from_substrait.cpp b/src/from_substrait.cpp -index 566e21d..afbbb0b 100644 ---- a/src/from_substrait.cpp -+++ b/src/from_substrait.cpp -@@ -14,6 +14,8 @@ - #include "duckdb/main/connection.hpp" - #include "duckdb/parser/parser.hpp" - #include "duckdb/common/exception.hpp" -+#include "duckdb/common/helper.hpp" -+#include "duckdb/common/shared_ptr.hpp" - #include "duckdb/common/types.hpp" - #include "duckdb/common/enums/set_operation_type.hpp" - -@@ -404,25 +406,25 @@ shared_ptr SubstraitToDuckDB::TransformJoinOp(const substrait::Rel &so - throw InternalException("Unsupported join type"); - } - unique_ptr join_condition = TransformExpr(sjoin.expression()); -- return make_shared(TransformOp(sjoin.left())->Alias("left"), -+ return make_shared_ptr(TransformOp(sjoin.left())->Alias("left"), - TransformOp(sjoin.right())->Alias("right"), std::move(join_condition), djointype); - } - - shared_ptr SubstraitToDuckDB::TransformCrossProductOp(const substrait::Rel &sop) { - auto &sub_cross = sop.cross(); - -- return make_shared(TransformOp(sub_cross.left())->Alias("left"), -+ return make_shared_ptr(TransformOp(sub_cross.left())->Alias("left"), - TransformOp(sub_cross.right())->Alias("right")); - } - - shared_ptr SubstraitToDuckDB::TransformFetchOp(const substrait::Rel &sop) { - auto &slimit = sop.fetch(); -- return make_shared(TransformOp(slimit.input()), slimit.count(), slimit.offset()); -+ return make_shared_ptr(TransformOp(slimit.input()), slimit.count(), slimit.offset()); - } - - shared_ptr SubstraitToDuckDB::TransformFilterOp(const substrait::Rel &sop) { - auto &sfilter = sop.filter(); -- return make_shared(TransformOp(sfilter.input()), TransformExpr(sfilter.condition())); -+ return make_shared_ptr(TransformOp(sfilter.input()), TransformExpr(sfilter.condition())); - } - - shared_ptr SubstraitToDuckDB::TransformProjectOp(const substrait::Rel &sop) { -@@ -435,7 +437,7 @@ shared_ptr SubstraitToDuckDB::TransformProjectOp(const substrait::Rel - for (size_t i = 0; i < expressions.size(); i++) { - mock_aliases.push_back("expr_" + to_string(i)); - } -- return make_shared(TransformOp(sop.project().input()), std::move(expressions), -+ return make_shared_ptr(TransformOp(sop.project().input()), std::move(expressions), - std::move(mock_aliases)); - } - -@@ -463,7 +465,7 @@ shared_ptr SubstraitToDuckDB::TransformAggregateOp(const substrait::Re - expressions.push_back(make_uniq(RemapFunctionName(function_name), std::move(children))); - } - -- return make_shared(TransformOp(sop.aggregate().input()), std::move(expressions), -+ return make_shared_ptr(TransformOp(sop.aggregate().input()), std::move(expressions), - std::move(groups)); - } - -@@ -502,7 +504,7 @@ shared_ptr SubstraitToDuckDB::TransformReadOp(const substrait::Rel &so - } - - if (sget.has_filter()) { -- scan = make_shared(std::move(scan), TransformExpr(sget.filter())); -+ scan = make_shared_ptr(std::move(scan), TransformExpr(sget.filter())); - } - - if (sget.has_projection()) { -@@ -516,7 +518,7 @@ shared_ptr SubstraitToDuckDB::TransformReadOp(const substrait::Rel &so - expressions.push_back(make_uniq(sproj.field() + 1)); - } - -- scan = make_shared(std::move(scan), std::move(expressions), std::move(aliases)); -+ scan = make_shared_ptr(std::move(scan), std::move(expressions), std::move(aliases)); - } - - return scan; -@@ -527,7 +529,7 @@ shared_ptr SubstraitToDuckDB::TransformSortOp(const substrait::Rel &so - for (auto &sordf : sop.sort().sorts()) { - order_nodes.push_back(TransformOrder(sordf)); - } -- return make_shared(TransformOp(sop.sort().input()), std::move(order_nodes)); -+ return make_shared_ptr(TransformOp(sop.sort().input()), std::move(order_nodes)); - } - - static duckdb::SetOperationType TransformSetOperationType(substrait::SetRel_SetOp setop) { -@@ -562,7 +564,7 @@ shared_ptr SubstraitToDuckDB::TransformSetOp(const substrait::Rel &sop - auto lhs = TransformOp(inputs[0]); - auto rhs = TransformOp(inputs[1]); - -- return make_shared(std::move(lhs), std::move(rhs), type); -+ return make_shared_ptr(std::move(lhs), std::move(rhs), type); - } - - shared_ptr SubstraitToDuckDB::TransformOp(const substrait::Rel &sop) { -@@ -599,7 +601,7 @@ shared_ptr SubstraitToDuckDB::TransformRootOp(const substrait::RelRoot - aliases.push_back(column_name); - expressions.push_back(make_uniq(id++)); - } -- return make_shared(TransformOp(sop.input()), std::move(expressions), aliases); -+ return make_shared_ptr(TransformOp(sop.input()), std::move(expressions), aliases); - } - - shared_ptr SubstraitToDuckDB::TransformPlan() { -diff --git a/src/include/from_substrait.hpp b/src/include/from_substrait.hpp -index 8ea96cd..3a632ce 100644 ---- a/src/include/from_substrait.hpp -+++ b/src/include/from_substrait.hpp -@@ -5,6 +5,7 @@ - #include - #include "substrait/plan.pb.h" - #include "duckdb/main/connection.hpp" -+#include "duckdb/common/shared_ptr.hpp" - - namespace duckdb { - class SubstraitToDuckDB { -diff --git a/src/substrait_extension.cpp b/src/substrait_extension.cpp -index fae645c..6422ebd 100644 ---- a/src/substrait_extension.cpp -+++ b/src/substrait_extension.cpp -@@ -6,6 +6,7 @@ - - #ifndef DUCKDB_AMALGAMATION - #include "duckdb/common/enums/optimizer_type.hpp" -+#include "duckdb/common/shared_ptr.hpp" - #include "duckdb/function/table_function.hpp" - #include "duckdb/parser/parsed_data/create_table_function_info.hpp" - #include "duckdb/parser/parsed_data/create_pragma_function_info.hpp" diff --git a/.github/regression/micro_extended.csv b/.github/regression/micro_extended.csv index f6bbc79bc85..b90437a9bbe 100644 --- a/.github/regression/micro_extended.csv +++ b/.github/regression/micro_extended.csv @@ -1,3 +1,4 @@ +benchmark/micro/aggregate/any_value_uuid.benchmark benchmark/micro/aggregate/bitstring_aggregate.benchmark benchmark/micro/aggregate/bitwise_aggregate.benchmark benchmark/micro/aggregate/grouped_distinct.benchmark @@ -91,12 +92,15 @@ benchmark/micro/csv/sniffer_quotes.benchmark benchmark/micro/csv/time_type.benchmark benchmark/micro/cte/cte.benchmark benchmark/micro/cte/materialized_cte.benchmark +benchmark/micro/cte/stacked_materialized_cte.benchmark benchmark/micro/date/extract_month.benchmark benchmark/micro/date/extract_multiple.benchmark benchmark/micro/date/extract_multiple_icu.benchmark benchmark/micro/date/extract_struct.benchmark benchmark/micro/date/extract_struct_icu.benchmark benchmark/micro/date/extract_year.benchmark +benchmark/micro/distinct/distinct_on_pushdown.benchmark +benchmark/micro/filter/in_conversion.benchmark benchmark/micro/filter/parallel_complex_filter.benchmark benchmark/micro/functions/random.benchmark benchmark/micro/functions/random_uuid.benchmark @@ -126,6 +130,7 @@ benchmark/micro/join/asof_join.benchmark benchmark/micro/join/asof_join_small_probe.benchmark benchmark/micro/join/blockwise_nl_join.benchmark benchmark/micro/join/delim_join_no_blowup.benchmark +benchmark/micro/join/hashjoin_dups_rhs.benchmark benchmark/micro/join/hashjoin_highcardinality.benchmark benchmark/micro/join/hashjoin_lhsarithmetic.benchmark benchmark/micro/join/iejoin_employees.benchmark @@ -159,7 +164,9 @@ benchmark/micro/list/column_data_collection_copy/small_lists.benchmark benchmark/micro/list/column_data_collection_copy/unnest.benchmark benchmark/micro/list/list_few_rows.benchmark benchmark/micro/list/list_many_rows.benchmark +benchmark/micro/list/list_min_max.benchmark benchmark/micro/list/list_order_by.benchmark +benchmark/micro/list/list_value.benchmark benchmark/micro/list/string_split.benchmark benchmark/micro/list/string_split_regexp.benchmark benchmark/micro/list/string_split_unicode.benchmark @@ -169,8 +176,11 @@ benchmark/micro/map/map_extract.benchmark benchmark/micro/map/map_lookup.benchmark benchmark/micro/nulls/no_nulls_addition.benchmark benchmark/micro/nulls/null_addition.benchmark +benchmark/micro/optimizer/topn_optimization.benchmark benchmark/micro/order/orderby.benchmark benchmark/micro/pushdown/or_pushdown.benchmark +benchmark/micro/pushdown/window_partition_pushdown.benchmark +benchmark/micro/result_collection/batched_stream_query.benchmark benchmark/micro/simd/auto-vectorization.benchmark benchmark/micro/string/bitstring.benchmark benchmark/micro/string/concat_long.benchmark @@ -194,7 +204,9 @@ benchmark/micro/string/string_agg_order_by.benchmark benchmark/micro/string/string_agg_short.benchmark benchmark/micro/timestamp/extract_month.benchmark benchmark/micro/timestamp/extract_year.benchmark +benchmark/micro/update/update_with_join.benchmark benchmark/micro/view/many_values.benchmark +benchmark/micro/window/streaming_lag.benchmark benchmark/micro/window/window_constant_aggregates.benchmark benchmark/micro/window/window_constant_count.benchmark benchmark/micro/window/window_count_star_fixed_100.benchmark diff --git a/.github/workflows/Android.yml b/.github/workflows/Android.yml new file mode 100644 index 00000000000..28718a69420 --- /dev/null +++ b/.github/workflows/Android.yml @@ -0,0 +1,101 @@ +name: Android +on: + workflow_call: + inputs: + override_git_describe: + type: string + git_ref: + type: string + skip_tests: + type: string + workflow_dispatch: + inputs: + override_git_describe: + type: string + git_ref: + type: string + skip_tests: + type: string + repository_dispatch: + push: + branches: + - '**' + - '!main' + - '!feature' + paths-ignore: + - '**' + - '!.github/workflows/Android.yml' + pull_request: + types: [opened, reopened, ready_for_review] + paths-ignore: + - '**' + - '!.github/workflows/Android.yml' + - '!.github/patches/duckdb-wasm/**' + + +concurrency: + group: android-${{ github.workflow }}-${{ github.ref }}-${{ github.head_ref || '' }}-${{ github.base_ref || '' }}-${{ github.ref != 'refs/heads/main' || github.sha }}-${{ inputs.override_git_describe }} + cancel-in-progress: true + +env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + OVERRIDE_GIT_DESCRIBE: ${{ inputs.override_git_describe }} + +jobs: + android: + name: Android + runs-on: ubuntu-latest + container: ubuntu:18.04 + + strategy: + matrix: + arch: [ armeabi-v7a, arm64-v8a ] + + env: + ENABLE_EXTENSION_AUTOLOADING: 1 + ENABLE_EXTENSION_AUTOINSTALL: 1 + GEN: ninja + EXTENSION_STATIC_BUILD: 1 + DUCKDB_PLATFORM: android_${{ matrix.arch}} + DUCKDB_CUSTOM_PLATFORM: android_${{ matrix.arch}} + CMAKE_VARS_BUILD: -DBUILD_UNITTESTS=0 -DBUILD_SHELL=0 -DANDROID_ABI=${{ matrix.arch}} -DCMAKE_TOOLCHAIN_FILE=./android-ndk/build/cmake/android.toolchain.cmake + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ inputs.git_ref }} + + - uses: ./.github/actions/ubuntu_18_setup + with: + ccache: 1 + + - name: Checkout (again) + shell: bash + run: git checkout ${{ inputs.git_ref }} + + - name: Install Android NDK + shell: bash + run: | + wget https://dl.google.com/android/repository/android-ndk-r26d-linux.zip + unzip android-ndk-r26d-linux.zip + mv android-ndk-r26d android-ndk + + - name: Build + shell: bash + run: make + + - name: Deploy + shell: bash + env: + AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} + run: | + zip -j libduckdb-android_${{matrix.arch}}.zip build/release/src/libduckdb*.* src/include/duckdb.h + ./scripts/upload-assets-to-staging.sh github_release libduckdb-android_${{matrix.arch}}.zip + + - uses: actions/upload-artifact@v3 + with: + name: duckdb-binaries-android-${{matrix.arch}} + path: | + libduckdb-android_${{matrix.arch}}.zip \ No newline at end of file diff --git a/.github/workflows/CodeQuality.yml b/.github/workflows/CodeQuality.yml index 250aabdde9a..37c0e33b066 100644 --- a/.github/workflows/CodeQuality.yml +++ b/.github/workflows/CodeQuality.yml @@ -47,7 +47,7 @@ jobs: - name: Install shell: bash - run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build clang-format-11 && sudo pip3 install cmake-format black + run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build clang-format-11 && sudo pip3 install cmake-format black cxxheaderparser pcpp - name: Format Check shell: bash @@ -81,12 +81,7 @@ jobs: - name: Install python dependencies if: ${{ !startsWith(github.ref, 'refs/tags/v') }} shell: bash - run: python -m pip install libclang - - - name: Install libclang - if: ${{ !startsWith(github.ref, 'refs/tags/v') }} - shell: bash - run: sudo apt-get update && sudo apt install llvm-dev && sudo apt install libclang-dev + run: python -m pip install cxxheaderparser pcpp - name: Verify C enum integrity if: ${{ !startsWith(github.ref, 'refs/tags/v') }} diff --git a/.github/workflows/InvokeCI.yml b/.github/workflows/InvokeCI.yml index 4044335501f..04a7b2b83af 100644 --- a/.github/workflows/InvokeCI.yml +++ b/.github/workflows/InvokeCI.yml @@ -46,8 +46,8 @@ jobs: git_ref: ${{ inputs.git_ref }} skip_tests: ${{ inputs.skip_tests }} - java: - uses: ./.github/workflows/Java.yml + pyodide: + uses: ./.github/workflows/Pyodide.yml secrets: inherit with: override_git_describe: ${{ inputs.override_git_describe }} diff --git a/.github/workflows/Java.yml b/.github/workflows/Java.yml deleted file mode 100644 index ae3de256c76..00000000000 --- a/.github/workflows/Java.yml +++ /dev/null @@ -1,366 +0,0 @@ -name: Java JDBC -on: - workflow_call: - inputs: - override_git_describe: - type: string - git_ref: - type: string - skip_tests: - type: string - workflow_dispatch: - inputs: - override_git_describe: - type: string - git_ref: - type: string - skip_tests: - type: string - repository_dispatch: - push: - branches: - - '**' - - '!main' - - '!feature' - tags: - - '**' - paths-ignore: - - '**.md' - - 'examples/**' - - 'test/**' - - 'tools/**' - - '!tools/jdbc/**' - - '.github/patches/duckdb-wasm/**' - - '.github/workflows/**' - - '!.github/workflows/Java.yml' - - pull_request: - types: [opened, reopened, ready_for_review] - paths-ignore: - - '**.md' - - 'examples/**' - - 'test/**' - - 'tools/**' - - '!tools/jdbc/**' - - '.github/patches/duckdb-wasm/**' - - '.github/workflows/**' - - '!.github/workflows/Java.yml' - -concurrency: - group: java-${{ github.workflow }}-${{ github.ref }}-${{ github.head_ref || '' }}-${{ - github.base_ref || '' }}-${{ github.ref != 'refs/heads/main' || github.sha - }}-${{ inputs.override_git_describe }} - cancel-in-progress: true -env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - OVERRIDE_GIT_DESCRIBE: ${{ inputs.override_git_describe }} - -jobs: - java-linux-amd64: - name: Java Linux (amd64) - runs-on: ubuntu-latest - container: - image: quay.io/pypa/manylinux2014_x86_64 - env: - GEN: ninja - ENABLE_EXTENSION_AUTOLOADING: 1 - ENABLE_EXTENSION_AUTOINSTALL: 1 - BUILD_JDBC: 1 - BUILD_JEMALLOC: 1 - BUILD_JSON: 1 - FORCE_WARN_UNUSED: 1 - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ inputs.git_ref }} - - - uses: ./.github/actions/manylinux_2014_setup - with: - ninja-build: 1 - ccache: 1 - jdk: 1 - python_alias: 1 - aws-cli: 1 - - - name: Build - shell: bash - run: make - - - name: Java Tests - shell: bash - if: ${{ inputs.skip_tests != 'true' }} - working-directory: tools/jdbc - run: make test_release - - - name: Deploy - shell: bash - env: - AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} - run: | - cp build/release/tools/jdbc/duckdb_jdbc.jar duckdb_jdbc-linux-amd64.jar - ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-linux-amd64.jar - - uses: actions/upload-artifact@v3 - with: - name: java-linux-amd64 - path: | - build/release/tools/jdbc/duckdb_jdbc.jar - - java-linux-aarch64: - name: Java Linux (aarch64) - runs-on: ubuntu-latest - container: ubuntu:18.04 - needs: java-linux-amd64 - env: - GEN: ninja - BUILD_JDBC: 1 - ENABLE_EXTENSION_AUTOLOADING: 1 - ENABLE_EXTENSION_AUTOINSTALL: 1 - OVERRIDE_JDBC_OS_ARCH: arm64 - JAVA_HOME: ../../jdk8u345-b01 - DUCKDB_PLATFORM: linux_arm64 - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ inputs.git_ref }} - - - uses: ./.github/actions/ubuntu_18_setup - with: - ccache: 1 - aarch64_cross_compile: 1 - - - name: Install Stuff - shell: bash - run: > - curl -L https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u345-b01/OpenJDK8U-jdk_x64_linux_hotspot_8u345b01.tar.gz | tar xvz - - - name: Build - shell: bash - run: CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ make - - - name: Deploy - shell: bash - env: - AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} - run: | - cp build/release/tools/jdbc/duckdb_jdbc.jar duckdb_jdbc-linux-aarch64.jar - ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-linux-aarch64.jar - - - uses: actions/upload-artifact@v3 - with: - name: java-linux-aarch64 - path: | - build/release/tools/jdbc/duckdb_jdbc.jar - - - java-windows-amd64: - name: Java Windows (arm64) - runs-on: windows-latest - needs: java-linux-amd64 - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ inputs.git_ref }} - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - name: Setup Ccache - uses: hendrikmuhs/ccache-action@main - with: - key: ${{ github.job }} - save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }} - - - name: Build - shell: bash - run: > - python scripts/windows_ci.py - - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_GENERATOR_PLATFORM=x64 -DJDBC_DRIVER=1 -DBUILD_EXTENSIONS=json -DENABLE_EXTENSION_AUTOLOADING=1 -DENABLE_EXTENSION_AUTOINSTALL=1 -DBUILD_SHELL=0 -DOVERRIDE_GIT_DESCRIBE="$OVERRIDE_GIT_DESCRIBE" - - cmake --build . --config Release - - name: Java Tests - if: ${{ inputs.skip_tests != 'true' }} - shell: bash - working-directory: tools/jdbc - run: make test_release - - name: Deploy - shell: bash - env: - AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} - run: | - cp tools/jdbc/duckdb_jdbc.jar duckdb_jdbc-windows-amd64.jar - ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-windows-amd64.jar - - uses: actions/upload-artifact@v3 - with: - name: java-windows-amd64 - path: | - tools/jdbc/duckdb_jdbc.jar - - - java-osx-universal: - name: Java OSX (Universal) - runs-on: macos-14 - needs: java-linux-amd64 - env: - BUILD_JDBC: 1 - BUILD_JSON: 1 - OSX_BUILD_UNIVERSAL: 1 - ENABLE_EXTENSION_AUTOLOADING: 1 - ENABLE_EXTENSION_AUTOINSTALL: 1 - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ inputs.git_ref }} - - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - name: Setup Ccache - uses: hendrikmuhs/ccache-action@main - with: - key: ${{ github.job }} - save: ${{ github.ref == 'refs/heads/main' }} - - name: Build - shell: bash - run: make - - name: Java Tests - if: ${{ inputs.skip_tests != 'true' }} - shell: bash - working-directory: tools/jdbc - run: make test_release - - name: Java Example - shell: bash - run: | - (cd examples/jdbc; make; make maven) - - name: Deploy - shell: bash - env: - AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} - run: | - cp build/release/tools/jdbc/duckdb_jdbc.jar duckdb_jdbc-osx-universal.jar - ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-osx-universal.jar - - uses: actions/upload-artifact@v3 - with: - name: java-osx-universal - path: | - build/release/tools/jdbc/duckdb_jdbc.jar - - - java-combine: - if: ${{ inputs.override_git_describe == '' }} - name: Java Combine - runs-on: ubuntu-latest - needs: - - java-linux-aarch64 - - java-linux-amd64 - - java-windows-amd64 - - java-osx-universal - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ inputs.git_ref }} - - - shell: bash - run: mkdir jdbc-artifacts - - - uses: actions/download-artifact@v3 - with: - name: java-linux-aarch64 - path: jdbc-artifacts/java-linux-aarch64 - - - uses: actions/download-artifact@v3 - with: - name: java-linux-amd64 - path: jdbc-artifacts/java-linux-amd64 - - - uses: actions/download-artifact@v3 - with: - name: java-windows-amd64 - path: jdbc-artifacts/java-windows-amd64 - - - uses: actions/download-artifact@v3 - with: - name: java-osx-universal - path: jdbc-artifacts/java-osx-universal - - - name: Combine JARs - shell: bash - run: | - if [[ "$GITHUB_REF" =~ ^(refs/heads/main|refs/tags/v.+)$ && "$GITHUB_REPOSITORY" = "duckdb/duckdb" ]] ; then - export XML=' - - - - ossrh - hfmuehleisen - PASSWORD - - - ' - mkdir ~/.m2 - echo $XML | sed "s/PASSWORD/${{ secrets.MAVEN_PASSWORD }}/" > ~/.m2/settings.xml - echo "${{ secrets.MAVEN_PGP_PK }}" | base64 -d > maven_pgp_key - gpg --import maven_pgp_key - python scripts/jdbc_maven_deploy.py ${{ github.ref_name }} jdbc-artifacts tools/jdbc - fi - ls -lahR jdbc-artifacts - - - uses: actions/upload-artifact@v3 - with: - name: java-jars - path: | - jdbc-artifacts - - jdbc-compliance: - name: JDBC Compliance - runs-on: ubuntu-20.04 - if: ${{ inputs.skip_tests != 'true' }} - needs: java-linux-amd64 - container: quay.io/pypa/manylinux2014_x86_64 - env: - BUILD_JDBC: 1 - GEN: ninja - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ inputs.git_ref }} - - - uses: ./.github/actions/manylinux_2014_setup - with: - ninja-build: 1 - ccache: 1 - jdk: 1 - python_alias: 1 - aws-cli: 1 - - - name: Install - shell: bash - run: | - git clone https://github.com/cwida/jdbccts.git - - - name: Setup Ccache - uses: hendrikmuhs/ccache-action@v1.2.11 # Note: pinned due to GLIBC incompatibility in later releases - with: - key: ${{ github.job }} - save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }} - - - name: Build - shell: bash - run: make release - - - name: Test - shell: bash - run: (cd jdbccts && make DUCKDB_JAR=../build/release/tools/jdbc/duckdb_jdbc.jar test) diff --git a/.github/workflows/LinuxRelease.yml b/.github/workflows/LinuxRelease.yml index a1ff2fc4c16..ebea54dbef3 100644 --- a/.github/workflows/LinuxRelease.yml +++ b/.github/workflows/LinuxRelease.yml @@ -166,6 +166,7 @@ jobs: with: ccache: 1 aarch64_cross_compile: 1 + git_ref: ${{ inputs.git_ref }} - name: Install unixODBC shell: bash @@ -220,6 +221,7 @@ jobs: vcpkg: 1 openssl: 1 ccache: 1 + git_ref: ${{ inputs.git_ref }} - uses: ./.github/actions/build_extensions with: @@ -260,6 +262,7 @@ jobs: openssl: 1 aarch64_cross_compile: 1 ccache: 1 + git_ref: ${{ inputs.git_ref }} - uses: ./.github/actions/build_extensions with: @@ -381,63 +384,6 @@ jobs: shell: bash run: python3 scripts/exported_symbols_check.py build/release/src/libduckdb*.so - linux-httpfs: - name: Linux HTTPFS - if: ${{ inputs.skip_tests != 'true' }} - runs-on: ubuntu-20.04 - needs: linux-release-64 - env: - BUILD_HTTPFS: 1 - BUILD_TPCH: 1 - BUILD_TPCDS: 1 - BUILD_PARQUET: 1 - BUILD_JSON: 1 - S3_TEST_SERVER_AVAILABLE: 1 - AWS_DEFAULT_REGION: eu-west-1 - AWS_ACCESS_KEY_ID: minio_duckdb_user - AWS_SECRET_ACCESS_KEY: minio_duckdb_user_password - DUCKDB_S3_ENDPOINT: duckdb-minio.com:9000 - DUCKDB_S3_USE_SSL: false - - GEN: ninja - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ inputs.git_ref }} - - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - - name: Install Ninja - shell: bash - run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build - - - name: Setup Ccache - uses: hendrikmuhs/ccache-action@main - with: - key: ${{ github.job }} - save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }} - - - name: Build - shell: bash - run: make - - - name: Start test server & run tests - shell: bash - run: | - sudo ./scripts/install_s3_test_server.sh - ./scripts/generate_presigned_url.sh - source ./scripts/run_s3_test_server.sh - source ./scripts/set_s3_test_server_variables.sh - sleep 60 - - python3 scripts/get_test_list.py --file-contains 'require httpfs' --list '"*"' > test.list - python3 scripts/run_tests_one_by_one.py ./build/release/test/unittest '-f test.list' - python3 scripts/run_tests_one_by_one.py ./build/release/test/unittest '[secret]' - amalgamation-tests: name: Amalgamation Tests if: ${{ inputs.skip_tests != 'true' }} diff --git a/.github/workflows/Main.yml b/.github/workflows/Main.yml index 9d99beb22d6..574de064eff 100644 --- a/.github/workflows/Main.yml +++ b/.github/workflows/Main.yml @@ -103,8 +103,8 @@ jobs: BUILD_TPCDS: 1 BUILD_FTS: 1 BUILD_JSON: 1 - BUILD_EXCEL: 1 BUILD_JEMALLOC: 1 + BUILD_EXTENSIONS: "" RUN_SLOW_VERIFIERS: 1 steps: @@ -149,8 +149,8 @@ jobs: BUILD_TPCDS: 1 BUILD_FTS: 1 BUILD_JSON: 1 - BUILD_EXCEL: 1 BUILD_JEMALLOC: 1 + BUILD_EXTENSIONS: "inet" steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/NightlyTests.yml b/.github/workflows/NightlyTests.yml index 9615157a5cb..fc5f6ff50a3 100644 --- a/.github/workflows/NightlyTests.yml +++ b/.github/workflows/NightlyTests.yml @@ -67,20 +67,17 @@ jobs: name: Release Assertions runs-on: ubuntu-20.04 needs: linux-memory-leaks - timeout-minutes: 120 env: CC: gcc-10 CXX: g++-10 GEN: ninja BUILD_ICU: 1 - BUILD_INET: 1 BUILD_TPCH: 1 BUILD_TPCDS: 1 BUILD_FTS: 1 - BUILD_EXCEL: 1 - BUILD_VISUALIZER: 1 BUILD_JSON: 1 BUILD_JEMALLOC: 1 + BUILD_EXTENSIONS: "inet" DISABLE_SANITIZER: 1 CRASH_ON_ASSERT: 1 RUN_SLOW_VERIFIERS: 1 @@ -107,7 +104,7 @@ jobs: - name: Test shell: bash run: | - python3 scripts/run_tests_one_by_one.py build/relassert/test/unittest "*" --no-exit --timeout 600 + python3 scripts/run_tests_one_by_one.py build/relassert/test/unittest "*" --no-exit --timeout 1200 linux-clang: @@ -201,7 +198,7 @@ jobs: shell: bash run: | mkdir -p build/release - (cd build/release && cmake -G "Ninja" -DSTATIC_LIBCPP=1 -DBUILD_EXTENSIONS='icu;parquet;fts;json;excel' -DFORCE_32_BIT=1 -DCMAKE_BUILD_TYPE=Release ../.. && cmake --build .) + (cd build/release && cmake -G "Ninja" -DSTATIC_LIBCPP=1 -DBUILD_EXTENSIONS='icu;parquet;fts;json' -DFORCE_32_BIT=1 -DCMAKE_BUILD_TYPE=Release ../.. && cmake --build .) - name: Test shell: bash @@ -401,6 +398,56 @@ jobs: shell: bash run: python3 scripts/test_zero_initialize.py + extension-updating: + name: Extension updating test + runs-on: ubuntu-20.04 +# needs: linux-memory-leaks TODO revert + env: + CC: gcc-10 + CXX: g++-10 + GEN: ninja + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install + shell: bash + run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build + + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Install + shell: bash + run: pip install awscli + + - name: Setup Ccache + uses: hendrikmuhs/ccache-action@main + with: + key: ${{ github.job }} + save: ${{ env.CCACHE_SAVE }} + + - name: Build + shell: bash + run: BUILD_TPCH=1 make + + - name: Start Minio + shell: bash + run: | + sudo ./scripts/install_s3_test_server.sh + ./scripts/generate_presigned_url.sh + source ./scripts/run_s3_test_server.sh + source ./scripts/set_s3_test_server_variables.sh + sleep 60 + + - name: Build + shell: bash + run: | + ./scripts/run_extension_medata_tests.sh + no-string-inline: name: No String Inline / Destroy Unpinned Blocks runs-on: ubuntu-20.04 @@ -410,14 +457,12 @@ jobs: CXX: g++-10 GEN: ninja BUILD_ICU: 1 - BUILD_INET: 1 BUILD_PARQUET: 1 BUILD_TPCH: 1 BUILD_TPCDS: 1 BUILD_FTS: 1 - BUILD_VISUALIZER: 1 BUILD_JSON: 1 - BUILD_EXCEL: 1 + BUILD_EXTENSIONS: "inet" DISABLE_STRING_INLINE: 1 DESTROY_UNPINNED_BLOCKS: 1 ALTERNATIVE_VERIFY: 1 @@ -468,14 +513,12 @@ jobs: CXX: g++-10 GEN: ninja BUILD_ICU: 1 - BUILD_INET: 1 BUILD_PARQUET: 1 BUILD_TPCH: 1 BUILD_TPCDS: 1 BUILD_FTS: 1 - BUILD_VISUALIZER: 1 BUILD_JSON: 1 - BUILD_EXCEL: 1 + BUILD_EXTENSIONS: "inet" VERIFY_VECTOR: ${{ matrix.vector_type }} steps: @@ -510,14 +553,12 @@ jobs: CXX: g++-10 GEN: ninja BUILD_ICU: 1 - BUILD_INET: 1 BUILD_PARQUET: 1 BUILD_TPCH: 1 BUILD_TPCDS: 1 BUILD_FTS: 1 - BUILD_VISUALIZER: 1 BUILD_JSON: 1 - BUILD_EXCEL: 1 + BUILD_EXTENSIONS: "inet" FORCE_ASYNC_SINK_SOURCE: 1 steps: @@ -636,14 +677,12 @@ jobs: CXX: g++-10 GEN: ninja BUILD_ICU: 1 - BUILD_INET: 1 BUILD_TPCH: 1 BUILD_TPCDS: 1 BUILD_FTS: 1 - BUILD_VISUALIZER: 1 BUILD_JSON: 1 - BUILD_EXCEL: 1 BUILD_JEMALLOC: 1 + BUILD_EXTENSIONS: "inet" TSAN_OPTIONS: suppressions=${{ github.workspace }}/.sanitizer-thread-suppressions.txt steps: @@ -670,54 +709,12 @@ jobs: run: | python3 scripts/run_tests_one_by_one.py build/reldebug/test/unittest --no-exit --timeout 600 python3 scripts/run_tests_one_by_one.py build/reldebug/test/unittest "[intraquery]" --no-exit --timeout 600 - python3 scripts/run_tests_one_by_one.py build/reldebug/test/unittest "[interquery]" --no-exit --timeout 600 + python3 scripts/run_tests_one_by_one.py build/reldebug/test/unittest "[interquery]" --no-exit --timeout 1800 + python3 scripts/run_tests_one_by_one.py build/reldebug/test/unittest "[interquery]" --no-exit --timeout 1800 --force-storage + python3 scripts/run_tests_one_by_one.py build/reldebug/test/unittest "[interquery]" --no-exit --timeout 1800 --force-storage --force-reload python3 scripts/run_tests_one_by_one.py build/reldebug/test/unittest "[detailed_profiler]" --no-exit --timeout 600 python3 scripts/run_tests_one_by_one.py build/reldebug/test/unittest test/sql/tpch/tpch_sf01.test_slow --no-exit --timeout 600 - - threadsan-relassert-all: - name: Thread Sanitizer (Relassert + All tests) - runs-on: ubuntu-latest - needs: linux-memory-leaks - env: - GEN: ninja - EXTENSION_STATIC_BUILD: 1 - BUILD_ICU: 1 - BUILD_INET: 1 - BUILD_TPCH: 1 - BUILD_TPCDS: 1 - BUILD_FTS: 1 - BUILD_VISUALIZER: 1 - BUILD_JSON: 1 - BUILD_EXCEL: 1 - BUILD_JEMALLOC: 1 - DUCKDB_PLATFORM: linux_amd64 - TSAN_OPTIONS: suppressions=${{ github.workspace }}/.sanitizer-thread-suppressions.txt - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Install - shell: bash - run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build - - - name: Setup Ccache - uses: hendrikmuhs/ccache-action@main - with: - key: ${{ github.job }} - save: ${{ env.CCACHE_SAVE }} - - - name: Build - shell: bash - run: THREADSAN=1 make relassert - - - name: Test - shell: bash - run: | - python3 scripts/run_tests_one_by_one.py build/relassert/test/unittest "*" --no-exit - vector-sizes: name: Vector Sizes runs-on: ubuntu-20.04 @@ -880,3 +877,61 @@ jobs: name: coverage path: coverage.zip if-no-files-found: error + + pyodide: + uses: ./.github/workflows/Pyodide.yml + secrets: inherit + + linux-httpfs: + name: Linux HTTPFS + runs-on: ubuntu-20.04 + env: + BUILD_HTTPFS: 1 + BUILD_TPCH: 1 + BUILD_TPCDS: 1 + BUILD_PARQUET: 1 + BUILD_JSON: 1 + S3_TEST_SERVER_AVAILABLE: 1 + AWS_DEFAULT_REGION: eu-west-1 + AWS_ACCESS_KEY_ID: minio_duckdb_user + AWS_SECRET_ACCESS_KEY: minio_duckdb_user_password + DUCKDB_S3_ENDPOINT: duckdb-minio.com:9000 + DUCKDB_S3_USE_SSL: false + + GEN: ninja + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install Ninja + shell: bash + run: sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build + + - name: Setup Ccache + uses: hendrikmuhs/ccache-action@main + with: + key: ${{ github.job }} + save: ${{ github.ref == 'refs/heads/main' || github.repository != 'duckdb/duckdb' }} + + - name: Build + shell: bash + run: make + + - name: Start test server & run tests + shell: bash + run: | + sudo ./scripts/install_s3_test_server.sh + ./scripts/generate_presigned_url.sh + source ./scripts/run_s3_test_server.sh + source ./scripts/set_s3_test_server_variables.sh + sleep 60 + + python3 scripts/get_test_list.py --file-contains 'require httpfs' --list '"*"' > test.list + python3 scripts/run_tests_one_by_one.py ./build/release/test/unittest '-f test.list' + python3 scripts/run_tests_one_by_one.py ./build/release/test/unittest '[secret]' diff --git a/.github/workflows/OnTag.yml b/.github/workflows/OnTag.yml index a88b6eb3df6..b94e7a05bda 100644 --- a/.github/workflows/OnTag.yml +++ b/.github/workflows/OnTag.yml @@ -13,10 +13,10 @@ jobs: uses: ./.github/workflows/TwineUpload.yml secrets: inherit with: - override_git_describe: ${{ inputs.override_git_describe || github.event.release.tag_name }} + override_git_describe: ${{ inputs.override_git_describe || github.ref_name }} staged_upload: uses: ./.github/workflows/StagedUpload.yml secrets: inherit with: - override_git_describe: ${{ inputs.override_git_describe || github.event.release.tag_name }} + override_git_describe: ${{ inputs.override_git_describe || github.ref_name }} diff --git a/.github/workflows/Pyodide.yml b/.github/workflows/Pyodide.yml index 160bcc759f5..af5cbf472eb 100644 --- a/.github/workflows/Pyodide.yml +++ b/.github/workflows/Pyodide.yml @@ -16,7 +16,6 @@ on: type: string skip_tests: type: string - repository_dispatch: push: branches: - "**" @@ -44,14 +43,31 @@ jobs: version: - python: "3.10" pyodide-build: "0.22.1" + node: "16" - python: "3.11" pyodide-build: "0.25.1" + node: "18" steps: - uses: actions/checkout@v4 with: # fetch everything so that the version on the built wheel path is # correct fetch-depth: 0 + ref: ${{ inputs.git_ref }} + + - name: Check/Act on inputs.override_git_describe + shell: bash + run: | + if [[ "${{ inputs.override_git_describe }}" == *-* ]]; then + echo "override_git_describe ${{ inputs.override_git_describe }}: provide either vX.Y.Z or empty string" + exit 1 + elif [[ -z "${{ inputs.override_git_describe }}" ]]; then + echo "No override_git_describe provided" + else + echo "UPLOAD_ASSETS_TO_STAGING_TARGET=$(git log -1 --format=%h)" >> "$GITHUB_ENV" + echo "override_git_describe ${{ inputs.override_git_describe }}: add tag" + git tag ${{ inputs.override_git_describe }} + fi - uses: actions/setup-python@v5 with: @@ -76,22 +92,31 @@ jobs: CFLAGS: "-fexceptions" LDFLAGS: "-fexceptions" - - name: smoke test duckdb on pyodide + - name: install node + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.version.node }} + + - name: create pyodide environment + run: pyodide venv .venv-pyodide + + - name: install deps into environment run: | - pyodide venv .venv-pyodide source .venv-pyodide/bin/activate - pip install ./tools/pythonpkg/dist/*.whl + pip install pytest numpy pandas mypy - python -V - - python < .github/regression/updated_micro_benchmarks.csv + target_branch="${{ github.event.pull_request.base.ref }}" + + git remote add base ${{ github.event.pull_request.base.repo.html_url }} + git fetch base + + git diff --name-only "base/$target_branch" | (grep "benchmark/micro/*.benchmark" || true) > .github/regression/updated_micro_benchmarks.csv if [ $(wc -l < .github/regression/updated_micro_benchmarks.csv) -gt 0 ]; then echo "Detected the following modified benchmarks. Running a regression test" cat .github/regression/updated_micro_benchmarks.csv @@ -244,7 +249,7 @@ jobs: shell: bash run: | sudo apt-get update -y -qq && sudo apt-get install -y -qq ninja-build - pip install numpy pytest pandas mypy psutil "pyarrow<=11.0.0" + pip install numpy pytest pandas mypy psutil pyarrow - name: Setup Ccache uses: hendrikmuhs/ccache-action@main diff --git a/.github/workflows/StagedUpload.yml b/.github/workflows/StagedUpload.yml index 654070aeff2..ad16a973ec4 100644 --- a/.github/workflows/StagedUpload.yml +++ b/.github/workflows/StagedUpload.yml @@ -1,5 +1,9 @@ name: Staged Upload on: + workflow_call: + inputs: + override_git_describe: + type: string workflow_dispatch: inputs: target_git_describe: diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index 664d209a847..c34e53ca8e9 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -60,6 +60,7 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 + ref: ${{ inputs.git_ref }} - uses: actions/setup-python@v5 with: @@ -189,6 +190,7 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 + ref: ${{ inputs.git_ref }} - uses: actions/setup-python@v5 with: @@ -227,6 +229,8 @@ jobs: needs: win-release-64 steps: - uses: actions/checkout@v3 + with: + ref: ${{ inputs.git_ref }} - uses: msys2/setup-msys2@v2 with: msystem: MINGW64 @@ -276,6 +280,7 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 + ref: ${{ inputs.git_ref }} - uses: actions/setup-python@v5 with: diff --git a/.github/workflows/_extension_deploy.yml b/.github/workflows/_extension_deploy.yml deleted file mode 100644 index 81aaa211d20..00000000000 --- a/.github/workflows/_extension_deploy.yml +++ /dev/null @@ -1,122 +0,0 @@ -# -# Reusable workflow that deploys the artifacts produced by .github/workflows/_extension_distribution.yml -# -# Note: this workflow can be used to deploy an extension from a GH artifact. It is intended for Out-of-tree -# extensions that live the duckdb GitHub organisation (only repo's within the same organisation can share secrets -# through reusable workflows) - - -name: Extension Deployment -on: - workflow_call: - inputs: - # The name of the extension - extension_name: - required: true - type: string - # DuckDB version to build against - duckdb_version: - required: true - type: string - # ';' separated list of architectures to exclude, for example: 'linux_amd64;osx_arm64' - exclude_archs: - required: false - type: string - default: "" - # Whether to upload this deployment as the latest. This may overwrite a previous deployment. - deploy_latest: - required: false - type: boolean - default: false - # Whether to upload this deployment under a versioned path. These will not be deleted automatically - deploy_versioned: - required: false - type: boolean - default: false - # Postfix added to artifact names. Can be used to guarantee unique names when this workflow is called multiple times - artifact_postfix: - required: false - type: string - default: "" - # Override the default deploy script with a custom script - deploy_script: - required: false - type: string - default: "./duckdb/scripts/extension-upload-single.sh" - # Override the default matrix parse script with a custom script - matrix_parse_script: - required: false - type: string - default: "./duckdb/scripts/modify_distribution_matrix.py" - -jobs: - generate_matrix: - name: Generate matrix - runs-on: ubuntu-latest - outputs: - deploy_matrix: ${{ steps.parse-matrices.outputs.deploy_matrix }} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - submodules: 'true' - - - name: Checkout DuckDB to version - run: | - cd duckdb - git checkout ${{ inputs.duckdb_version }} - - - id: parse-matrices - run: | - python3 ${{ inputs.matrix_parse_script }} --input ./duckdb/.github/config/distribution_matrix.json --deploy_matrix --output deploy_matrix.json --exclude "${{ inputs.exclude_archs }}" --pretty - deploy_matrix="`cat deploy_matrix.json`" - echo deploy_matrix=$deploy_matrix >> $GITHUB_OUTPUT - echo `cat $GITHUB_OUTPUT` - - deploy: - name: Deploy - runs-on: ubuntu-latest - needs: generate_matrix - if: ${{ needs.generate_matrix.outputs.deploy_matrix != '{}' && needs.generate_matrix.outputs.deploy_matrix != '' }} - strategy: - matrix: ${{fromJson(needs.generate_matrix.outputs.deploy_matrix)}} - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - submodules: 'true' - - - name: Checkout DuckDB to version - run: | - cd duckdb - git checkout ${{ inputs.duckdb_version }} - - - uses: actions/download-artifact@v2 - with: - name: ${{ inputs.extension_name }}-${{ inputs.duckdb_version }}-extension-${{matrix.duckdb_arch}}${{inputs.artifact_postfix}}${{startsWith(matrix.duckdb, 'wasm') && '.wasm' || ''}} - path: | - /tmp/extension - - - name: Deploy - shell: bash - env: - AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_ORG_DEPLOY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_ORG_DEPLOY_KEY }} - AWS_DEFAULT_REGION: ${{ secrets.S3_DUCKDB_ORG_REGION }} - BUCKET_NAME: ${{ secrets.S3_DUCKDB_ORG_BUCKET }} - DUCKDB_EXTENSION_SIGNING_PK: ${{ secrets.S3_DUCKDB_ORG_EXTENSION_SIGNING_PK }} - DUCKDB_DEPLOY_SCRIPT_MODE: for_real - run: | - pwd - python3 -m pip install pip awscli - git config --global --add safe.directory '*' - cd duckdb - git fetch --tags - export DUCKDB_VERSION=`git tag --points-at HEAD` - export DUCKDB_VERSION=${DUCKDB_VERSION:=`git log -1 --format=%h`} - cd .. - git fetch --tags - export EXT_VERSION=`git tag --points-at HEAD` - export EXT_VERSION=${EXT_VERSION:=`git log -1 --format=%h`} - ${{ inputs.deploy_script }} ${{ inputs.extension_name }} $EXT_VERSION $DUCKDB_VERSION ${{ matrix.duckdb_arch }} $BUCKET_NAME ${{inputs.deploy_latest || 'true' && 'false'}} ${{inputs.deploy_versioned || 'true' && 'false'}} diff --git a/.github/workflows/_extension_distribution.yml b/.github/workflows/_extension_distribution.yml deleted file mode 100644 index 6a36b501ab6..00000000000 --- a/.github/workflows/_extension_distribution.yml +++ /dev/null @@ -1,396 +0,0 @@ -# Reusable workflow for building DuckDB extensions using a standardized environment -# -# The workflow: -# - builds the extension using the CI workflow from the corresponding DuckDB version -# - uploads the extensions as gh actions artifacts in the following format: -# --extension- -# -# note: extensions are simply uploaded to GitHub actions, deploying the extensions is done a separate step. More info on -# this can be found in https://github.com/duckdb/extension-template - -name: Extension distribution -on: - workflow_call: - inputs: - # The name with which the extension will be built - extension_name: - required: true - type: string - # DuckDB version to build against, should in most cases be identical to - duckdb_version: - required: true - type: string - # ';' separated list of architectures to exclude, for example: 'linux_amd64;osx_arm64' - exclude_archs: - required: false - type: string - default: "" - # Postfix added to artifact names. Can be used to guarantee unique names when this workflow is called multiple times - artifact_postfix: - required: false - type: string - default: "" - # Override the default vcpkg commit used by this version of DuckDB - vcpkg_commit: - required: false - type: string - default: "a1a1cbc975abf909a6c8985a6a2b8fe20bbd9bd6" - # Override the default script producing the matrices. Allows specifying custom matrices. - matrix_parse_script: - required: false - type: string - default: "./duckdb/scripts/modify_distribution_matrix.py" - # Enable building the DuckDB Shell - build_duckdb_shell: - required: false - type: boolean - default: true - # Patch file to patch the extension's sources before building - patch: - required: false - type: string - default: "" - -jobs: - generate_matrix: - name: Generate matrix - runs-on: ubuntu-latest - outputs: - linux_matrix: ${{ steps.set-matrix-linux.outputs.linux_matrix }} - windows_matrix: ${{ steps.set-matrix-windows.outputs.windows_matrix }} - osx_matrix: ${{ steps.set-matrix-osx.outputs.osx_matrix }} - wasm_matrix: ${{ steps.set-matrix-wasm.outputs.wasm_matrix }} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - submodules: 'true' - - - if: ${{ inputs.patch != '' }} - run: | - patch -p1 < ${{ inputs.patch }} - shell: bash - - - name: Checkout DuckDB to version - run: | - cd duckdb - git checkout ${{ inputs.duckdb_version }} - - - id: parse-matrices - run: | - python3 ${{ inputs.matrix_parse_script }} --input ./duckdb/.github/config/distribution_matrix.json --select_os linux --output linux_matrix.json --exclude "${{ inputs.exclude_archs }}" --pretty - python3 ${{ inputs.matrix_parse_script }} --input ./duckdb/.github/config/distribution_matrix.json --select_os osx --output osx_matrix.json --exclude "${{ inputs.exclude_archs }}" --pretty - python3 ${{ inputs.matrix_parse_script }} --input ./duckdb/.github/config/distribution_matrix.json --select_os windows --output windows_matrix.json --exclude "${{ inputs.exclude_archs }}" --pretty - python3 ${{ inputs.matrix_parse_script }} --input ./duckdb/.github/config/distribution_matrix.json --select_os wasm --output wasm_matrix.json --exclude "${{ inputs.exclude_archs }}" --pretty - - - id: set-matrix-linux - run: | - linux_matrix="`cat linux_matrix.json`" - echo linux_matrix=$linux_matrix >> $GITHUB_OUTPUT - echo `cat $GITHUB_OUTPUT` - - - id: set-matrix-osx - run: | - osx_matrix="`cat osx_matrix.json`" - echo osx_matrix=$osx_matrix >> $GITHUB_OUTPUT - echo `cat $GITHUB_OUTPUT` - - - id: set-matrix-windows - run: | - windows_matrix="`cat windows_matrix.json`" - echo windows_matrix=$windows_matrix >> $GITHUB_OUTPUT - echo `cat $GITHUB_OUTPUT` - - - id: set-matrix-wasm - run: | - wasm_matrix="`cat wasm_matrix.json`" - echo wasm_matrix=$wasm_matrix >> $GITHUB_OUTPUT - echo `cat $GITHUB_OUTPUT` - - linux: - name: Linux - runs-on: ubuntu-latest - container: ${{ matrix.container }} - needs: generate_matrix - if: ${{ needs.generate_matrix.outputs.linux_matrix != '{}' && needs.generate_matrix.outputs.linux_matrix != '' }} - strategy: - matrix: ${{fromJson(needs.generate_matrix.outputs.linux_matrix)}} - env: - VCPKG_TARGET_TRIPLET: ${{ matrix.vcpkg_triplet }} - VCPKG_TOOLCHAIN_PATH: ${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake - GEN: Ninja - BUILD_SHELL: ${{ inputs.build_duckdb_shell && '1' || '0' }} - DUCKDB_PLATFORM: ${{ matrix.duckdb_arch }} - - steps: - - name: Install required ubuntu packages - if: ${{ matrix.duckdb_arch == 'linux_amd64' || matrix.duckdb_arch == 'linux_arm64' }} - run: | - apt-get update -y -qq - apt-get install -y -qq software-properties-common - add-apt-repository ppa:git-core/ppa - apt-get update -y -qq - apt-get install -y -qq ninja-build make gcc-multilib g++-multilib libssl-dev wget openjdk-8-jdk zip maven unixodbc-dev libc6-dev-i386 lib32readline6-dev libssl-dev libcurl4-gnutls-dev libexpat1-dev gettext unzip build-essential checkinstall libffi-dev curl libz-dev openssh-client - - - name: Install Git 2.18.5 - if: ${{ matrix.duckdb_arch == 'linux_amd64' || matrix.duckdb_arch == 'linux_arm64' }} - run: | - wget https://github.com/git/git/archive/refs/tags/v2.18.5.tar.gz - tar xvf v2.18.5.tar.gz - cd git-2.18.5 - make - make prefix=/usr install - git --version - - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - submodules: 'true' - - - if: ${{ inputs.patch != '' }} - run: | - patch -p1 < ${{ inputs.patch }} - shell: bash - - - name: Checkout DuckDB to version - run: | - cd duckdb - git checkout ${{ inputs.duckdb_version }} - - - name: Setup ManyLinux2014 - if: ${{ matrix.duckdb_arch == 'linux_amd64_gcc4' }} - run: | - ./duckdb/scripts/setup_manylinux2014.sh general aws-cli ccache ssh python_alias openssl - - - name: Setup Ccache - uses: hendrikmuhs/ccache-action@v1.2.11 # Note: pinned due to GLIBC incompatibility in later releases - with: - key: ${{ github.job }}-${{ matrix.duckdb_arch }} - - - name: Setup Ubuntu - if: ${{ matrix.duckdb_arch == 'linux_amd64' || matrix.duckdb_arch == 'linux_arm64' }} - uses: ./duckdb/.github/actions/ubuntu_18_setup - with: - aarch64_cross_compile: ${{ matrix.duckdb_arch == 'linux_arm64' && 1 }} - - - name: Setup vcpkg - uses: lukka/run-vcpkg@v11.1 - with: - vcpkgGitCommitId: ${{ inputs.vcpkg_commit }} - - - name: Build extension - env: - GEN: ninja - CC: ${{ matrix.duckdb_arch == 'linux_arm64' && 'aarch64-linux-gnu-gcc' || '' }} - CXX: ${{ matrix.duckdb_arch == 'linux_arm64' && 'aarch64-linux-gnu-g++' || '' }} - DUCKDB_PLATFORM: ${{ matrix.duckdb_arch }} - run: | - make release - - - name: Test extension - if: ${{ matrix.duckdb_arch != 'linux_arm64'}} - run: | - make test - - - uses: actions/upload-artifact@v2 - with: - name: ${{ inputs.extension_name }}-${{ inputs.duckdb_version }}-extension-${{matrix.duckdb_arch}}${{inputs.artifact_postfix}} - path: | - build/release/extension/${{ inputs.extension_name }}/${{ inputs.extension_name }}.duckdb_extension - - macos: - name: MacOS - runs-on: macos-14 - needs: generate_matrix - if: ${{ needs.generate_matrix.outputs.osx_matrix != '{}' && needs.generate_matrix.outputs.osx_matrix != '' }} - strategy: - matrix: ${{fromJson(needs.generate_matrix.outputs.osx_matrix)}} - env: - VCPKG_TOOLCHAIN_PATH: ${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake - VCPKG_TARGET_TRIPLET: ${{ matrix.vcpkg_triplet }} - OSX_BUILD_ARCH: ${{ matrix.osx_build_arch }} - GEN: Ninja - BUILD_SHELL: ${{ inputs.build_duckdb_shell && '1' || '0' }} - DUCKDB_PLATFORM: ${{ matrix.duckdb_arch }} - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - submodules: 'true' - - - if: ${{ inputs.patch != '' }} - run: | - patch -p1 < ${{ inputs.patch }} - shell: bash - - - name: Install Ninja - run: | - brew install ninja - - - name: Setup Ccache - uses: hendrikmuhs/ccache-action@main - with: - key: ${{ github.job }}-${{ matrix.duckdb_arch }} - - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - - name: Checkout DuckDB to version - run: | - cd duckdb - git checkout ${{ inputs.duckdb_version }} - - - name: Setup vcpkg - uses: lukka/run-vcpkg@v11.1 - with: - vcpkgGitCommitId: ${{ inputs.vcpkg_commit }} - - - name: Build extension - shell: bash - env: - DUCKDB_PLATFORM: ${{ matrix.duckdb_arch }} - run: | - make release - - - name: Test Extension - if: ${{ matrix.osx_build_arch == 'x86_64'}} - shell: bash - run: | - make test - - - uses: actions/upload-artifact@v2 - with: - name: ${{ inputs.extension_name }}-${{ inputs.duckdb_version }}-extension-${{matrix.duckdb_arch}}${{inputs.artifact_postfix}} - path: | - build/release/extension/${{ inputs.extension_name }}/${{ inputs.extension_name }}.duckdb_extension - - windows: - name: Windows - runs-on: windows-latest - needs: generate_matrix - if: ${{ needs.generate_matrix.outputs.windows_matrix != '{}' && needs.generate_matrix.outputs.windows_matrix != '' }} - strategy: - matrix: ${{fromJson(needs.generate_matrix.outputs.windows_matrix)}} - env: - GEN: Ninja - VCPKG_TOOLCHAIN_PATH: ${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake - VCPKG_TARGET_TRIPLET: ${{ matrix.vcpkg_triplet }} - BUILD_SHELL: ${{ inputs.build_duckdb_shell && '1' || '0' }} - DUCKDB_PLATFORM: ${{ matrix.duckdb_arch }} - CC: ${{ matrix.duckdb_arch == 'windows_amd64_rtools' && 'gcc' || '' }} - CXX: ${{ matrix.duckdb_arch == 'windows_amd64_rtools' && 'g++' || '' }} - - steps: - - name: Keep \n line endings - shell: bash - run: | - git config --global core.autocrlf false - git config --global core.eol lf - - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - submodules: 'true' - - - if: ${{ inputs.patch != '' }} - run: | - patch -p1 < ${{ inputs.patch }} - shell: bash - - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - - uses: r-lib/actions/setup-r@v2 - if: matrix.duckdb_arch == 'windows_amd64_rtools' - with: - r-version: 'devel' - update-rtools: true - rtools-version: '42' # linker bug in 43 - - - name: Checkout DuckDB to version - run: | - cd duckdb - git checkout ${{ inputs.duckdb_version }} - - - name: Setup Ccache - uses: hendrikmuhs/ccache-action@main - with: - key: ${{ github.job }}-${{ matrix.duckdb_arch }} - - - name: Setup vcpkg - uses: lukka/run-vcpkg@v11.1 - with: - vcpkgGitCommitId: ${{ inputs.vcpkg_commit }} - - - name: Build extension - env: - DUCKDB_PLATFORM: ${{ matrix.duckdb_arch }} - run: | - make release - - - name: Test Extension - shell: bash - run: | - make test - - - uses: actions/upload-artifact@v2 - with: - name: ${{ inputs.extension_name }}-${{ inputs.duckdb_version }}-extension-${{matrix.duckdb_arch}}${{inputs.artifact_postfix}} - path: | - build/release/extension/${{ inputs.extension_name }}/${{ inputs.extension_name }}.duckdb_extension - - wasm: - name: DuckDB-Wasm - runs-on: ubuntu-latest - needs: generate_matrix - if: ${{ needs.generate_matrix.outputs.wasm_matrix != '{}' && needs.generate_matrix.outputs.wasm_matrix != '' }} - strategy: - matrix: ${{fromJson(needs.generate_matrix.outputs.wasm_matrix)}} - env: - VCPKG_TARGET_TRIPLET: ${{ matrix.vcpkg_triplet }} - VCPKG_TOOLCHAIN_PATH: ${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake - GEN: Ninja - DUCKDB_PLATFORM: ${{ matrix.duckdb_arch }} - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - submodules: 'true' - - - if: ${{ inputs.patch != '' }} - run: | - patch -p1 < ${{ inputs.patch }} - shell: bash - - - name: Checkout DuckDB to version - run: | - cd duckdb - git checkout ${{ inputs.duckdb_version }} - - - uses: mymindstorm/setup-emsdk@v13 - with: - version: 'latest' - - - name: Setup vcpkg - uses: lukka/run-vcpkg@v11.1 - with: - vcpkgGitCommitId: ${{ inputs.vcpkg_commit }} - - - name: Setup Ccache - uses: hendrikmuhs/ccache-action@main - with: - key: ${{ github.job }}-${{ matrix.duckdb_arch }} - - - name: Build Wasm module - run: | - make ${{ matrix.duckdb_arch }} - - - uses: actions/upload-artifact@v3 - with: - name: ${{ inputs.extension_name }}-${{ inputs.duckdb_version }}-extension-${{matrix.duckdb_arch}}${{inputs.artifact_postfix}} - path: | - build/${{ matrix.duckdb_arch }}/${{ inputs.extension_name }}.duckdb_extension.wasm diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 979cce42830..93a37770c52 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -41,7 +41,6 @@ jobs: env: PYTHON_USER_SPACE: 1 BUILD_PYTHON: 1 - BUILD_JDBC: 1 BUILD_ODBC: 1 BUILD_AUTOCOMPLETE: 1 BUILD_ICU: 1 @@ -51,7 +50,6 @@ jobs: BUILD_HTTPFS: 1 BUILD_JSON: 1 BUILD_INET: 1 - BUILD_SQLSMITH: 1 - name: Upload the result run: | diff --git a/.github/workflows/lcov_exclude b/.github/workflows/lcov_exclude index dfad3defa65..cdcff20fb9d 100644 --- a/.github/workflows/lcov_exclude +++ b/.github/workflows/lcov_exclude @@ -1,6 +1,5 @@ /usr* */cl.hpp -*/tools/jdbc/* */tools/odbc/* */tools/shell/* */tools/sqlite3_api_wrapper/* diff --git a/.sanitizer-thread-suppressions.txt b/.sanitizer-thread-suppressions.txt index 3dd166809ab..5d3c828970b 100644 --- a/.sanitizer-thread-suppressions.txt +++ b/.sanitizer-thread-suppressions.txt @@ -1,11 +1,7 @@ -deadlock:LockClients -deadlock:RollbackTransaction -deadlock:Checkpoint -deadlock:MetaTransaction::GetTransaction +deadlock:InitializeIndexes race:NextInnerJoin -race:~ColumnSegment +race:NextRightSemiOrAntiJoin race:duckdb_moodycamel race:duckdb_jemalloc race:AddToEvictionQueue -race:CanHaveNull -race:CanHaveNoNull +race:ValidityAppend diff --git a/CMakeLists.txt b/CMakeLists.txt index ec210f00016..2175797c223 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.5...3.29) if(NOT CLANG_TIDY) find_package(Python3) @@ -48,19 +48,22 @@ else() endif() # Determine install paths +# default to gnu standard installation directories (lib, bin, include) +# https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html +include(GNUInstallDirs) set(INSTALL_LIB_DIR - lib + ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Installation directory for libraries") set(INSTALL_BIN_DIR - bin + ${CMAKE_INSTALL_BINDIR} CACHE PATH "Installation directory for executables") set(INSTALL_INCLUDE_DIR - include + ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "Installation directory for header files") if(WIN32 AND NOT CYGWIN) set(DEF_INSTALL_CMAKE_DIR cmake) else() - set(DEF_INSTALL_CMAKE_DIR lib/cmake/DuckDB) + set(DEF_INSTALL_CMAKE_DIR ${INSTALL_LIB_DIR}/cmake/DuckDB) endif() set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} @@ -87,6 +90,8 @@ endif() option(DISABLE_UNITY "Disable unity builds." FALSE) option(USE_WASM_THREADS "Should threads be used" FALSE) if (${USE_WASM_THREADS}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") set(WASM_THREAD_FLAGS -pthread -sSHARED_MEMORY=1 @@ -264,6 +269,10 @@ if (OVERRIDE_GIT_DESCRIBE) OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE) set(GIT_DESCRIBE "${OVERRIDE_GIT_DESCRIBE}-0-g${GIT_COMMIT_HASH}") + if (GIT_RESULT) + message(WARNING "git is available (at ${GIT_EXECUTABLE}) but has failed to execute 'log -1 --format=%h'. Consider providing explicit GIT_COMMIT_HASH") + set(GIT_DESCRIBE "${OVERRIDE_GIT_DESCRIBE}-0-g0123456789") + endif() else() set(GIT_DESCRIBE "${OVERRIDE_GIT_DESCRIBE}-0-g0123456789") endif() @@ -280,18 +289,31 @@ else() RESULT_VARIABLE GIT_RESULT OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE) + if (GIT_RESULT) + message(WARNING "git is available (at ${GIT_EXECUTABLE}) but has failed to execute 'log -1 --format=%h'. Consider providing explicit GIT_COMMIT_HASH or OVERRIDE_GIT_DESCRIBE") + set(GIT_COMMIT_HASH "0123456789") + endif() endif() execute_process( COMMAND ${GIT_EXECUTABLE} describe --tags --long WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE GIT_RESULT OUTPUT_VARIABLE GIT_DESCRIBE OUTPUT_STRIP_TRAILING_WHITESPACE) + if (GIT_RESULT) + message(WARNING "git is available (at ${GIT_EXECUTABLE}) but has failed to execute 'describe --tags --long', likely due to shallow clone. Consider providing explicit OVERRIDE_GIT_DESCRIBE or clone with tags. Continuing with dummy version v0.0.1") + set(GIT_DESCRIBE "v0.0.1-0-g${GIT_COMMIT_HASH}") + endif() else() - message("Git NOT FOUND and EXTERNAL_GIT_DESCRIBE not provided, continuing with dummy version v0.0.1") + message(WARNING "Git NOT FOUND and EXTERNAL_GIT_DESCRIBE not provided, continuing with dummy version v0.0.1") set(GIT_DESCRIBE "v0.0.1-0-g0123456789") endif() endif() +if (NOT GIT_DESCRIBE MATCHES "^v[0-9]+\.[0-9]+\.[0-9]+\-[0-9]+\-g[a-f0-9]+$") + message(FATAL_ERROR "Computed GIT_DESCRIBE '${GIT_DESCRIBE}' is not in the expected form 'vX.Y.Z-N-gGITHASH123'. Consider providing OVERRIDE_GIT_DESCRIBE explicitly to CMake") +endif() + string(REGEX REPLACE "v([0-9]+)\.[0-9]+\.[0-9]+\-.*" "\\1" DUCKDB_MAJOR_VERSION "${GIT_DESCRIBE}") string(REGEX REPLACE "v[0-9]+\.([0-9]+)\.[0-9]+\-.*" "\\1" DUCKDB_MINOR_VERSION "${GIT_DESCRIBE}") string(REGEX REPLACE "v[0-9]+\.[0-9]+\.([0-9]+)\-.*" "\\1" DUCKDB_PATCH_VERSION "${GIT_DESCRIBE}") @@ -307,7 +329,9 @@ endif() string(SUBSTRING "${GIT_COMMIT_HASH}" 0 10 GIT_COMMIT_HASH) -if(DUCKDB_DEV_ITERATION EQUAL 0) +if(NOT "${DUCKDB_EXPLICIT_VERSION}" STREQUAL "") + set(DUCKDB_VERSION "${DUCKDB_EXPLICIT_VERSION}") +elseif(DUCKDB_DEV_ITERATION EQUAL 0) # on a tag; directly use the version set(DUCKDB_VERSION "v${DUCKDB_MAJOR_VERSION}.${DUCKDB_MINOR_VERSION}.${DUCKDB_PATCH_VERSION}") else() @@ -325,9 +349,9 @@ else() endif() if(EMSCRIPTEN) - set(EXTENSION_POSTFIX "duckdb_extension.wasm") + set(EXTENSION_POSTFIX ".wasm") else() - set(EXTENSION_POSTFIX "duckdb_extension") + set(EXTENSION_POSTFIX "") endif() message(STATUS "git hash ${GIT_COMMIT_HASH}, version ${DUCKDB_VERSION}, extension folder ${DUCKDB_NORMALIZED_VERSION}") @@ -352,7 +376,6 @@ option(BUILD_CORE_FUNCTIONS_EXTENSION "Build the core functions." TRUE) option(BUILD_BENCHMARKS "Enable building of the benchmark suite." FALSE) option(BUILD_TPCE "Enable building of the TPC-E tool." FALSE) option(DISABLE_BUILTIN_EXTENSIONS "Disable linking extensions." FALSE) -option(JDBC_DRIVER "Build the DuckDB JDBC driver" FALSE) option(BUILD_ODBC_DRIVER "Build the DuckDB ODBC driver" FALSE) option(BUILD_PYTHON "Build the DuckDB Python extension" FALSE) option(USER_SPACE "Build the DuckDB Python in the user space" FALSE) @@ -479,6 +502,37 @@ else() endif() endif() +function(is_number input_string return_var) + if("${input_string}" MATCHES "^[0-9]+$") + set(${return_var} TRUE PARENT_SCOPE) + else() + set(${return_var} FALSE PARENT_SCOPE) + endif() +endfunction() + +set(STANDARD_VECTOR_SIZE "" CACHE STRING "Set a custom STANDARD_VECTOR_SIZE at compile time") +set(BLOCK_ALLOC_SIZE "" CACHE STRING "Set a custom BLOCK_ALLOC_SIZE at compile time") + +if(DEFINED STANDARD_VECTOR_SIZE AND NOT STANDARD_VECTOR_SIZE STREQUAL "") + is_number(${STANDARD_VECTOR_SIZE} is_number_result) + if(is_number_result) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTANDARD_VECTOR_SIZE=${STANDARD_VECTOR_SIZE}") + message(STATUS "STANDARD_VECTOR_SIZE is set to ${STANDARD_VECTOR_SIZE}") + else() + message(FATAL_ERROR "STANDARD_VECTOR_SIZE must be a number, not ${STANDARD_VECTOR_SIZE}") + endif() +endif() + +if(DEFINED BLOCK_ALLOC_SIZE AND NOT BLOCK_ALLOC_SIZE STREQUAL "") + is_number(${BLOCK_ALLOC_SIZE} is_number_result) + if(is_number_result) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDUCKDB_BLOCK_ALLOC_SIZE=${BLOCK_ALLOC_SIZE}") + message(STATUS "BLOCK_ALLOC_SIZE is set to ${BLOCK_ALLOC_SIZE}") + else() + message(FATAL_ERROR "BLOCK_ALLOC_SIZE must be a number, not ${BLOCK_ALLOC_SIZE}") + endif() +endif() + if(CUSTOM_LINKER) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=${CUSTOM_LINKER}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=${CUSTOM_LINKER}") @@ -567,6 +621,7 @@ include_directories(third_party/pcg) include_directories(third_party/tdigest) include_directories(third_party/mbedtls/include) include_directories(third_party/jaro_winkler) +include_directories(third_party/yyjson/include) # todo only regenerate ub file if one of the input files changed hack alert function(enable_unity_build UB_SUFFIX SOURCE_VARIABLE_NAME) @@ -724,7 +779,7 @@ if (NOT EXTENSION_CONFIG_BUILD AND NOT ${EXTENSION_TESTS_ONLY} AND NOT CLANG_TID add_custom_target( duckdb_local_extension_repo ALL COMMAND - ${Python3_EXECUTABLE} scripts/create_local_extension_repo.py "${DUCKDB_NORMALIZED_VERSION}" "${CMAKE_CURRENT_BINARY_DIR}/duckdb_platform_out" "${CMAKE_CURRENT_BINARY_DIR}" "${LOCAL_EXTENSION_REPO_DIR}" "${EXTENSION_POSTFIX}" + ${Python3_EXECUTABLE} scripts/create_local_extension_repo.py "${DUCKDB_NORMALIZED_VERSION}" "${CMAKE_CURRENT_BINARY_DIR}/duckdb_platform_out" "${CMAKE_CURRENT_BINARY_DIR}" "${LOCAL_EXTENSION_REPO_DIR}" "duckdb_extension${EXTENSION_POSTFIX}" WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMENT Create local extension repository) add_dependencies(duckdb_local_extension_repo duckdb_platform) @@ -746,7 +801,11 @@ function(build_loadable_extension_directory NAME OUTPUT_DIRECTORY EXTENSION_VERS # parse parameters string(FIND "${PARAMETERS}" "-no-warnings" IGNORE_WARNINGS) - add_library(${TARGET_NAME} SHARED ${FILES}) + if(EMSCRIPTEN) + add_library(${TARGET_NAME} STATIC ${FILES}) + else() + add_library(${TARGET_NAME} SHARED ${FILES}) + endif() # this disables the -Dsome_target_EXPORTS define being added by cmake which otherwise trips clang-tidy (yay) set_target_properties(${TARGET_NAME} PROPERTIES DEFINE_SYMBOL "") set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${NAME}) @@ -799,10 +858,6 @@ function(build_loadable_extension_directory NAME OUTPUT_DIRECTORY EXTENSION_VERS set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".duckdb_extension") - if(EMSCRIPTEN) - set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".duckdb_extension.wasm") - endif() - if(MSVC) set_target_properties( ${TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG @@ -813,25 +868,20 @@ function(build_loadable_extension_directory NAME OUTPUT_DIRECTORY EXTENSION_VERS endif() if(EMSCRIPTEN) - # Copy file.duckdb_extension.wasm to file.duckdb_extension.wasm.lib - add_custom_command( - TARGET ${TARGET_NAME} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy $ $.lib - ) # Compile the library into the actual wasm file string(TOUPPER ${NAME} EXTENSION_NAME_UPPERCASE) + string(REPLACE ";" " " TO_BE_LINKED "${DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_LINKED_LIBS}") add_custom_command( TARGET ${TARGET_NAME} POST_BUILD - COMMAND emcc $.lib -o $ -O3 -sSIDE_MODULE=2 -sEXPORTED_FUNCTIONS="_${NAME}_init" ${WASM_THREAD_FLAGS} ${DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_LINKED_LIBS} + COMMAND emcc $ -o $.wasm -O3 -sSIDE_MODULE=2 -sEXPORTED_FUNCTIONS="_${NAME}_init,_${NAME}_version" ${WASM_THREAD_FLAGS} ${TO_BE_LINKED} ) endif() add_custom_command( TARGET ${TARGET_NAME} POST_BUILD COMMAND - ${CMAKE_COMMAND} -DEXTENSION=$ -DPLATFORM_FILE=${DuckDB_BINARY_DIR}/duckdb_platform_out -DDUCKDB_VERSION="${DUCKDB_NORMALIZED_VERSION}" -DEXTENSION_VERSION="${EXTENSION_VERSION}" -DNULL_FILE=${DUCKDB_MODULE_BASE_DIR}/scripts/null.txt -P ${DUCKDB_MODULE_BASE_DIR}/scripts/append_metadata.cmake + ${CMAKE_COMMAND} -DEXTENSION=$${EXTENSION_POSTFIX} -DPLATFORM_FILE=${DuckDB_BINARY_DIR}/duckdb_platform_out -DDUCKDB_VERSION="${DUCKDB_NORMALIZED_VERSION}" -DEXTENSION_VERSION="${EXTENSION_VERSION}" -DNULL_FILE=${DUCKDB_MODULE_BASE_DIR}/scripts/null.txt -P ${DUCKDB_MODULE_BASE_DIR}/scripts/append_metadata.cmake ) add_dependencies(${TARGET_NAME} duckdb_platform) if (NOT EXTENSION_CONFIG_BUILD AND NOT ${EXTENSION_TESTS_ONLY} AND NOT CLANG_TIDY) @@ -857,7 +907,7 @@ function(build_static_extension NAME PARAMETERS) endfunction() # Internal extension register function -function(register_extension NAME DONT_LINK DONT_BUILD LOAD_TESTS PATH INCLUDE_PATH TEST_PATH LINKED_LIBS) +function(register_extension NAME DONT_LINK DONT_BUILD LOAD_TESTS PATH INCLUDE_PATH TEST_PATH LINKED_LIBS EXTENSION_VERSION) string(TOLOWER ${NAME} EXTENSION_NAME_LOWERCASE) string(TOUPPER ${NAME} EXTENSION_NAME_UPPERCASE) @@ -902,11 +952,11 @@ function(register_extension NAME DONT_LINK DONT_BUILD LOAD_TESTS PATH INCLUDE_PA set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_PATH ${PATH} PARENT_SCOPE) set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_INCLUDE_PATH ${INCLUDE_PATH} PARENT_SCOPE) set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_TEST_PATH ${TEST_PATH} PARENT_SCOPE) - set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION ${GIT_COMMIT_HASH} PARENT_SCOPE) + set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION ${EXTENSION_VERSION} PARENT_SCOPE) endfunction() # Downloads the external extension repo at the specified commit and calls register_extension -macro(register_external_extension NAME URL COMMIT DONT_LINK DONT_BUILD LOAD_TESTS PATH INCLUDE_PATH TEST_PATH APPLY_PATCHES LINKED_LIBS SUBMODULES) +macro(register_external_extension NAME URL COMMIT DONT_LINK DONT_BUILD LOAD_TESTS PATH INCLUDE_PATH TEST_PATH APPLY_PATCHES LINKED_LIBS SUBMODULES EXTENSION_VERSION) include(FetchContent) if (${APPLY_PATCHES}) set(PATCH_COMMAND python3 ${CMAKE_SOURCE_DIR}/scripts/apply_extension_patches.py ${CMAKE_SOURCE_DIR}/.github/patches/extensions/${NAME}/) @@ -920,23 +970,17 @@ macro(register_external_extension NAME URL COMMIT DONT_LINK DONT_BUILD LOAD_TEST ) FETCHCONTENT_POPULATE(${NAME}_EXTENSION_FC) - find_package(Git) - if(Git_FOUND) - execute_process( - COMMAND ${GIT_EXECUTABLE} log -1 --format=%h - WORKING_DIRECTORY "${${NAME}_extension_fc_SOURCE_DIR}" - RESULT_VARIABLE GIT_RESULT - OUTPUT_VARIABLE GIT_SHORT_COMMIT - OUTPUT_STRIP_TRAILING_WHITESPACE) + # Autogenerate version tag if not provided + if ("${EXTENSION_VERSION}" STREQUAL "") + duckdb_extension_generate_version(EXTERNAL_EXTENSION_VERSION ${${NAME}_extension_fc_SOURCE_DIR}) else() - message(WARNING "Git not found, using ${COMMIT} as GIT_SHORT_COMMIT") - set(GIT_SHORT_COMMIT "${COMMIT}") + set(EXTERNAL_EXTENSION_VERSION "${EXTENSION_VERSION}") endif() - message(STATUS "Load extension '${NAME}' from ${URL} @ ${GIT_SHORT_COMMIT}") + message(STATUS "Load extension '${NAME}' from ${URL} @ ${EXTERNAL_EXTENSION_VERSION}") string(TOUPPER ${NAME} EXTENSION_NAME_UPPERCASE) - set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION "${GIT_SHORT_COMMIT}" PARENT_SCOPE) + set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION "${EXTERNAL_EXTENSION_VERSION}" PARENT_SCOPE) if ("${INCLUDE_PATH}" STREQUAL "") set(INCLUDE_FULL_PATH "${${NAME}_extension_fc_SOURCE_DIR}/src/include") @@ -950,9 +994,46 @@ macro(register_external_extension NAME URL COMMIT DONT_LINK DONT_BUILD LOAD_TEST set(TEST_FULL_PATH "${${NAME}_extension_fc_SOURCE_DIR}/${TEST_PATH}") endif() - register_extension(${NAME} ${DONT_LINK} ${DONT_BUILD} ${LOAD_TESTS} ${${NAME}_extension_fc_SOURCE_DIR}/${PATH} "${INCLUDE_FULL_PATH}" "${TEST_FULL_PATH}" "${LINKED_LIBS}") + register_extension(${NAME} ${DONT_LINK} ${DONT_BUILD} ${LOAD_TESTS} ${${NAME}_extension_fc_SOURCE_DIR}/${PATH} "${INCLUDE_FULL_PATH}" "${TEST_FULL_PATH}" "${LINKED_LIBS}" "${EXTERNAL_EXTENSION_VERSION}") endmacro() +# This function sets OUTPUT_VAR to the VERSION using DuckDB's standard versioning convention (using WORKING_DIR) +# TODO: unify this with the base DuckDB logic (note that this is slightly different as it has ReleaseCandidate tag support +function(duckdb_extension_generate_version OUTPUT_VAR WORKING_DIR) + find_package(Git) + if(Git_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} log -1 --format=%h + WORKING_DIRECTORY ${WORKING_DIR} + RESULT_VARIABLE GIT_RESULT + OUTPUT_VARIABLE GIT_COMMIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (GIT_RESULT) + message(FATAL_ERROR "git is available (at ${GIT_EXECUTABLE}) but has failed to execute 'log -1 --format=%h'.") + endif() + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --tags --always + WORKING_DIRECTORY ${WORKING_DIR} + RESULT_VARIABLE GIT_RESULT + OUTPUT_VARIABLE GIT_DESCRIBE + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (GIT_RESULT) + set(VERSION "${GIT_COMMIT_HASH}") + elseif (GIT_DESCRIBE MATCHES "^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9\.]+)?$") + # We are on a valid SemVer version in the format v{MAJOR}.{MINOR}.{PATH}(-{RC}) + set(VERSION "${GIT_DESCRIBE}") + else() + set(VERSION "${GIT_COMMIT_HASH}") + endif() + else() + # No git found, we set empty string + set(VERSION "") + endif() + + # Propagate the version + set(${OUTPUT_VAR} ${VERSION} PARENT_SCOPE) +endfunction() + function(duckdb_extension_load NAME) # Parameter parsing set(options DONT_LINK DONT_BUILD LOAD_TESTS APPLY_PATCHES) @@ -975,18 +1056,25 @@ function(duckdb_extension_load NAME) # Remote Git extension if (${duckdb_extension_load_DONT_BUILD}) - register_extension(${NAME} "${duckdb_extension_load_DONT_LINK}" "${duckdb_extension_load_DONT_BUILD}" "" "" "" "" "") + register_extension(${NAME} "${duckdb_extension_load_DONT_LINK}" "${duckdb_extension_load_DONT_BUILD}" "" "" "" "" "" "${duckdb_extension_load_EXTENSION_VERSION}") elseif (NOT "${duckdb_extension_load_GIT_URL}" STREQUAL "") if ("${duckdb_extension_load_GIT_TAG}" STREQUAL "") error("Git URL specified but no valid GIT_TAG was found for ${NAME} extension") endif() - register_external_extension(${NAME} "${duckdb_extension_load_GIT_URL}" "${duckdb_extension_load_GIT_TAG}" "${duckdb_extension_load_DONT_LINK}" "${duckdb_extension_load_DONT_BUILD}" "${duckdb_extension_load_LOAD_TESTS}" "${duckdb_extension_load_SOURCE_DIR}" "${duckdb_extension_load_INCLUDE_DIR}" "${duckdb_extension_load_TEST_DIR}" "${duckdb_extension_load_APPLY_PATCHES}" "${duckdb_extension_load_LINKED_LIBS}" "${duckdb_extension_load_SUBMODULES}") + register_external_extension(${NAME} "${duckdb_extension_load_GIT_URL}" "${duckdb_extension_load_GIT_TAG}" "${duckdb_extension_load_DONT_LINK}" "${duckdb_extension_load_DONT_BUILD}" "${duckdb_extension_load_LOAD_TESTS}" "${duckdb_extension_load_SOURCE_DIR}" "${duckdb_extension_load_INCLUDE_DIR}" "${duckdb_extension_load_TEST_DIR}" "${duckdb_extension_load_APPLY_PATCHES}" "${duckdb_extension_load_LINKED_LIBS}" "${duckdb_extension_load_SUBMODULES}" "${duckdb_extension_load_EXTENSION_VERSION}") if (NOT "${duckdb_extension_load_EXTENSION_VERSION}" STREQUAL "") set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION "${duckdb_extension_load_EXTENSION_VERSION}" PARENT_SCOPE) endif() elseif (NOT "${duckdb_extension_load_SOURCE_DIR}" STREQUAL "") + # Version detection + if ("${duckdb_extension_load_EXTENSION_VERSION}" STREQUAL "") + duckdb_extension_generate_version(EXT_VERSION ${CMAKE_CURRENT_LIST_DIR}) + else() + set(EXT_VERSION ${duckdb_extension_load_EXTENSION_VERSION}) + endif() + # Local extension, custom path - message(STATUS "Load extension '${NAME}' from '${duckdb_extension_load_SOURCE_DIR}'") + message(STATUS "Load extension '${NAME}' from '${duckdb_extension_load_SOURCE_DIR}' @ ${EXT_VERSION}") # If no include path specified, use default if ("${duckdb_extension_load_INCLUDE_DIR}" STREQUAL "") @@ -1002,33 +1090,21 @@ function(duckdb_extension_load NAME) set(TEST_PATH_DEFAULT ${duckdb_extension_load_TEST_DIR}) endif() - if (NOT "${duckdb_extension_load_EXTENSION_VERSION}" STREQUAL "") - set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION "${duckdb_extension_load_EXTENSION_VERSION}" PARENT_SCOPE) - else() - find_package(Git) - if(Git_FOUND) - execute_process( - COMMAND ${GIT_EXECUTABLE} log -1 --format=%h - WORKING_DIRECTORY ${duckdb_extension_load_SOURCE_DIR} - RESULT_VARIABLE GIT_RESULT - OUTPUT_VARIABLE GIT_COMMIT - OUTPUT_STRIP_TRAILING_WHITESPACE) - set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION "${GIT_COMMIT}" PARENT_SCOPE) - else() - set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION "" PARENT_SCOPE) - endif() - endif() - register_extension(${NAME} "${duckdb_extension_load_DONT_LINK}" "${duckdb_extension_load_DONT_BUILD}" "${duckdb_extension_load_LOAD_TESTS}" "${duckdb_extension_load_SOURCE_DIR}" "${INCLUDE_PATH_DEFAULT}" "${TEST_PATH_DEFAULT}" "${duckdb_extension_load_LINKED_LIBS}") + register_extension(${NAME} "${duckdb_extension_load_DONT_LINK}" "${duckdb_extension_load_DONT_BUILD}" "${duckdb_extension_load_LOAD_TESTS}" "${duckdb_extension_load_SOURCE_DIR}" "${INCLUDE_PATH_DEFAULT}" "${TEST_PATH_DEFAULT}" "${duckdb_extension_load_LINKED_LIBS}" "${EXT_VERSION}") elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/extension_external/${NAME}) # Local extension, default path - message(STATUS "Load extension '${NAME}' from '${CMAKE_CURRENT_SOURCE_DIR}/extension_external'") - register_extension(${NAME} ${duckdb_extension_load_DONT_LINK} "${duckdb_extension_load_DONT_BUILD}" "${duckdb_extension_load_LOAD_TESTS}" "${CMAKE_CURRENT_SOURCE_DIR}/extension_external/${NAME}" "${CMAKE_CURRENT_SOURCE_DIR}/extension_external/${NAME}/src/include" "${CMAKE_CURRENT_SOURCE_DIR}/extension_external/${NAME}/test/sql") - set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION "${DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION}" PARENT_SCOPE) + message(STATUS "Load extension '${NAME}' from '${CMAKE_CURRENT_SOURCE_DIR}/extension_external' @ ${duckdb_extension_load_EXTENSION_VERSION}") + register_extension(${NAME} ${duckdb_extension_load_DONT_LINK} "${duckdb_extension_load_DONT_BUILD}" "${duckdb_extension_load_LOAD_TESTS}" "${CMAKE_CURRENT_SOURCE_DIR}/extension_external/${NAME}" "${CMAKE_CURRENT_SOURCE_DIR}/extension_external/${NAME}/src/include" "${CMAKE_CURRENT_SOURCE_DIR}/extension_external/${NAME}/test/sql" "${duckdb_extension_load_LINKED_LIBS}" "${duckdb_extension_load_EXTENSION_VERSION}") else() + # For in-tree extensions of the default path, we set the extension version to GIT_COMMIT_HASH by default + if ("${duckdb_extension_load_EXTENSION_VERSION}" STREQUAL "") + set(duckdb_extension_load_EXTENSION_VERSION ${GIT_COMMIT_HASH}) + endif() + # Local extension, default path - message(STATUS "Load extension '${NAME}' from '${CMAKE_CURRENT_SOURCE_DIR}/extensions'") - register_extension(${NAME} ${duckdb_extension_load_DONT_LINK} "${duckdb_extension_load_DONT_BUILD}" "${duckdb_extension_load_LOAD_TESTS}" "${CMAKE_CURRENT_SOURCE_DIR}/extension/${NAME}" "${CMAKE_CURRENT_SOURCE_DIR}/extension/${NAME}/include" "${CMAKE_CURRENT_SOURCE_DIR}/extension/${NAME}/test/sql" "${duckdb_extension_load_LINKED_LIBS}") - set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION "${DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION}" PARENT_SCOPE) + message(STATUS "Load extension '${NAME}' from '${CMAKE_CURRENT_SOURCE_DIR}/extensions' @ ${duckdb_extension_load_EXTENSION_VERSION}") + + register_extension(${NAME} ${duckdb_extension_load_DONT_LINK} "${duckdb_extension_load_DONT_BUILD}" "${duckdb_extension_load_LOAD_TESTS}" "${CMAKE_CURRENT_SOURCE_DIR}/extension/${NAME}" "${CMAKE_CURRENT_SOURCE_DIR}/extension/${NAME}/include" "${CMAKE_CURRENT_SOURCE_DIR}/extension/${NAME}/test/sql" "${duckdb_extension_load_LINKED_LIBS}" "${duckdb_extension_load_EXTENSION_VERSION}") endif() # Propagate variables set by register_extension @@ -1040,6 +1116,7 @@ function(duckdb_extension_load NAME) set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_INCLUDE_PATH ${DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_INCLUDE_PATH} PARENT_SCOPE) set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_TEST_PATH ${DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_TEST_PATH} PARENT_SCOPE) set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_LINKED_LIBS ${DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_LINKED_LIBS} PARENT_SCOPE) + set(DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION "${DUCKDB_EXTENSION_${EXTENSION_NAME_UPPERCASE}_EXT_VERSION}" PARENT_SCOPE) endfunction() if(${EXPORT_DLL_SYMBOLS}) @@ -1078,9 +1155,6 @@ endif() if(BUILD_PYTHON) include(${CMAKE_CURRENT_SOURCE_DIR}/tools/pythonpkg/duckdb_extension_config.cmake) endif() -if (JDBC_DRIVER) - include(${CMAKE_CURRENT_SOURCE_DIR}/tools/jdbc/duckdb_extension_config.cmake) -endif() # Load base extension config include(${CMAKE_CURRENT_SOURCE_DIR}/extension/extension_config.cmake) @@ -1117,6 +1191,10 @@ foreach(EXT_NAME IN LISTS DUCKDB_EXTENSION_NAMES) message(WARNING "Extension '${EXT_NAME}' has a vcpkg.json, but build was not run with VCPKG. If build fails, check out VCPKG build instructions in 'duckdb/extension/README.md' or try manually installing the dependencies in ${DUCKDB_EXTENSION_${EXT_NAME_UPPERCASE}_PATH}vcpkg.json") endif() + if (NOT "${DUCKDB_EXTENSION_${EXT_NAME_UPPERCASE}_EXT_VERSION}" STREQUAL "") + add_definitions(-DEXT_VERSION_${EXT_NAME_UPPERCASE}="${DUCKDB_EXTENSION_${EXT_NAME_UPPERCASE}_EXT_VERSION}") + endif() + if (DEFINED DUCKDB_EXTENSION_${EXT_NAME_UPPERCASE}_PATH) add_subdirectory(${DUCKDB_EXTENSION_${EXT_NAME_UPPERCASE}_PATH} extension/${EXT_NAME}) else() @@ -1183,11 +1261,12 @@ if(${EXTENSION_CONFIG_BUILD}) Message(STATUS "Combined vcpkg manifest created from extensions: ${VCPKG_NAMES_COMMAS}") # Write linked extensions that will be built to extensions_linked.txt - FILE(WRITE ${CMAKE_BINARY_DIR}/extensions.txt "") + FILE(WRITE ${CMAKE_BINARY_DIR}/extensions.csv "") + FILE(APPEND ${CMAKE_BINARY_DIR}/extensions.csv "name, version\r") foreach(EXT_NAME IN LISTS DUCKDB_EXTENSION_NAMES) string(TOUPPER ${EXT_NAME} EXT_NAME_UPPERCASE) if (${DUCKDB_EXTENSION_${EXT_NAME_UPPERCASE}_SHOULD_BUILD}) - FILE(APPEND ${CMAKE_BINARY_DIR}/extensions.txt "${EXT_NAME}\r") + FILE(APPEND ${CMAKE_BINARY_DIR}/extensions.csv "${EXT_NAME}, \"${DUCKDB_EXTENSION_${EXT_NAME_UPPERCASE}_EXT_VERSION}\"\r") endif() endforeach() @@ -1215,7 +1294,7 @@ if(BUILD_PYTHON) DUCKDB_BINARY_DIR=${PROJECT_BINARY_DIR} DUCKDB_COMPILE_FLAGS=${ALL_COMPILE_FLAGS} DUCKDB_LIBS="${duckdb_libs}" - ) + ) if(PYTHON_EDITABLE_BUILD) set(PIP_COMMAND ${PIP_COMMAND} python3 -m pip install --editable .) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dcd05187023..8c89f548fe9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,9 +49,10 @@ This project and everyone participating in it is governed by a [Code of Conduct] * To build the project, run `make`. * To build the project for debugging, run `make debug`. -* To build optional components, use the flags defined in the Makefile, e.g. to build the JDBC driver, run `BUILD_JDBC=1 make`. +* To build optional components, use the flags defined in the Makefile, e.g. to build the ODBC driver, run `BUILD_ODBC=1 make`. * For parallel builds, you can use the [Ninja](https://ninja-build.org/) build system: `GEN=ninja make`. - * The default number of parallel processes can lockup the system depending on the CPU-to-memory ratio. If this happens, restrict the maximum number of build processes: `CMAKE_BUILD_PARALLEL_LEVEL=4 GEN=ninja make`. + * The default number of parallel processes can lock up the system depending on the CPU-to-memory ratio. If this happens, restrict the maximum number of build processes: `CMAKE_BUILD_PARALLEL_LEVEL=4 GEN=ninja make`. + * Without using Ninja, build times can still be reduced by setting `CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)`. ## Testing diff --git a/Makefile b/Makefile index 248c541c2d5..4969ad6178f 100644 --- a/Makefile +++ b/Makefile @@ -121,12 +121,6 @@ endif ifeq (${BUILD_JEMALLOC}, 1) BUILD_EXTENSIONS:=${BUILD_EXTENSIONS};jemalloc endif -ifeq (${BUILD_EXCEL}, 1) - BUILD_EXTENSIONS:=${BUILD_EXTENSIONS};excel -endif -ifeq (${BUILD_INET}, 1) - BUILD_EXTENSIONS:=${BUILD_EXTENSIONS};inet -endif ifeq (${BUILD_ALL_EXT}, 1) CMAKE_VARS:=${CMAKE_VARS} -DDUCKDB_EXTENSION_CONFIGS=".github/config/in_tree_extensions.cmake;.github/config/out_of_tree_extensions.cmake" else ifeq (${BUILD_ALL_IT_EXT}, 1) @@ -137,18 +131,9 @@ endif ifeq (${STATIC_OPENSSL}, 1) CMAKE_VARS:=${CMAKE_VARS} -DOPENSSL_USE_STATIC_LIBS=1 endif -ifeq (${BUILD_SQLSMITH}, 1) - BUILD_EXTENSIONS:=${BUILD_EXTENSIONS};sqlsmith -endif ifeq (${BUILD_TPCE}, 1) CMAKE_VARS:=${CMAKE_VARS} -DBUILD_TPCE=1 endif -ifeq (${BUILD_JDBC}, 1) - CMAKE_VARS:=${CMAKE_VARS} -DJDBC_DRIVER=1 -endif -ifneq ($(OVERRIDE_JDBC_OS_ARCH),) - CMAKE_VARS:=${CMAKE_VARS} -DOVERRIDE_JDBC_OS_ARCH=$(OVERRIDE_JDBC_OS_ARCH) -endif ifeq (${BUILD_ODBC}, 1) CMAKE_VARS:=${CMAKE_VARS} -DBUILD_ODBC_DRIVER=1 endif @@ -250,6 +235,14 @@ ifdef DEBUG_STACKTRACE CMAKE_VARS:=${CMAKE_VARS} -DDEBUG_STACKTRACE=1 endif +# Optional overrides +ifneq (${STANDARD_VECTOR_SIZE}, ) + CMAKE_VARS:=${CMAKE_VARS} -DSTANDARD_VECTOR_SIZE=${STANDARD_VECTOR_SIZE} +endif +ifneq (${BLOCK_ALLOC_SIZE}, ) + CMAKE_VARS:=${CMAKE_VARS} -DBLOCK_ALLOC_SIZE=${BLOCK_ALLOC_SIZE} +endif + # Enable VCPKG for this build ifneq ("${VCPKG_TOOLCHAIN_PATH}", "") CMAKE_VARS_BUILD:=${CMAKE_VARS_BUILD} -DCMAKE_TOOLCHAIN_FILE='${VCPKG_TOOLCHAIN_PATH}' -DVCPKG_BUILD=1 @@ -414,6 +407,9 @@ format-changes: format-main: python3 scripts/format.py main --fix --noconfirm +format-feature: + python3 scripts/format.py feature --fix --noconfirm + third_party/sqllogictest: git clone --depth=1 --branch hawkfish-statistical-rounding https://github.com/cwida/sqllogictest.git third_party/sqllogictest @@ -446,7 +442,7 @@ generate-files: python3 scripts/generate_functions.py python3 scripts/generate_serialization.py python3 scripts/generate_enum_util.py - python3 tools/pythonpkg/scripts/generate_connection_code.py + -@python3 tools/pythonpkg/scripts/generate_connection_code.py || echo "Warning: generate_connection_code.py failed, cxxheaderparser & pcpp are required to perform this step" ./scripts/generate_micro_extended.sh # Run the formatter again after (re)generating the files $(MAKE) format-main diff --git a/README.md b/README.md index 008093b62cb..d40913d46ca 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,19 @@

## DuckDB -DuckDB is a high-performance analytical database system. It is designed to be fast, reliable, portable, and easy to use. DuckDB provides a rich SQL dialect, with support far beyond basic SQL. DuckDB supports arbitrary and nested correlated subqueries, window functions, collations, complex types (arrays, structs), and more. For more information on using DuckDB, please refer to the [DuckDB documentation](https://duckdb.org/docs/). + +DuckDB is a high-performance analytical database system. It is designed to be fast, reliable, portable, and easy to use. DuckDB provides a rich SQL dialect, with support far beyond basic SQL. DuckDB supports arbitrary and nested correlated subqueries, window functions, collations, complex types (arrays, structs, maps), and [several extensions designed to make SQL easier to use](https://duckdb.org/docs/guides/sql_features/friendly_sql). + +DuckDB is available as a [standalone CLI application](https://duckdb.org/docs/api/cli/overview) and has clients for [Python](https://duckdb.org/docs/api/python/overview), [R](https://duckdb.org/docs/api/r), [Java](https://duckdb.org/docs/api/java), [Wasm](https://duckdb.org/docs/api/wasm/overview), etc., with deep integrations with packages such as [pandas](https://duckdb.org/docs/guides/python/sql_on_pandas) and [dplyr](https://duckdblabs.github.io/duckplyr/). + +For more information on using DuckDB, please refer to the [DuckDB documentation](https://duckdb.org/docs/). ## Installation -If you want to install and use DuckDB, please see [our website](https://www.duckdb.org) for installation and usage instructions. + +If you want to install DuckDB, please see [our installation page](https://www.duckdb.org/docs/installation) for instructions. ## Data Import + For CSV files and Parquet files, data import is as simple as referencing the file in the FROM clause: ```sql @@ -30,12 +37,15 @@ SELECT * FROM 'myfile.parquet'; Refer to our [Data Import](https://duckdb.org/docs/data/overview) section for more information. ## SQL Reference -The [website](https://duckdb.org/docs/sql/introduction) contains a reference of functions and SQL constructs available in DuckDB. + +The documentation contains a [SQL introduction and reference](https://duckdb.org/docs/sql/introduction). ## Development + For development, DuckDB requires [CMake](https://cmake.org), Python3 and a `C++11` compliant compiler. Run `make` in the root directory to compile the sources. For development, use `make debug` to build a non-optimized debug version. You should run `make unit` and `make allunit` to verify that your version works properly after making changes. To test performance, you can run `BUILD_BENCHMARK=1 BUILD_TPCH=1 make` and then perform several standard benchmarks from the root directory by executing `./build/release/benchmark/benchmark_runner`. The details of benchmarks are in our [Benchmark Guide](benchmark/README.md). Please also refer to our [Build Guide](https://duckdb.org/dev/building) and [Contribution Guide](CONTRIBUTING.md). ## Support + See the [Support Options](https://duckdblabs.com/support/) page. diff --git a/benchmark/benchmark_runner.cpp b/benchmark/benchmark_runner.cpp index 04549b0c3ab..65f5b9af787 100644 --- a/benchmark/benchmark_runner.cpp +++ b/benchmark/benchmark_runner.cpp @@ -59,10 +59,12 @@ atomic is_active; atomic timeout; void sleep_thread(Benchmark *benchmark, BenchmarkRunner *runner, BenchmarkState *state, bool hotrun, - int timeout_duration) { - if (timeout_duration < 0) { + const optional_idx &optional_timeout) { + if (!optional_timeout.IsValid()) { return; } + auto timeout_duration = optional_timeout.GetIndex(); + // timeout is given in seconds // we wait 10ms per iteration, so timeout * 100 gives us the amount of // iterations @@ -130,7 +132,8 @@ void BenchmarkRunner::RunBenchmark(Benchmark *benchmark) { } is_active = true; timeout = false; - std::thread interrupt_thread(sleep_thread, benchmark, this, state.get(), hotrun, benchmark->Timeout()); + std::thread interrupt_thread(sleep_thread, benchmark, this, state.get(), hotrun, + benchmark->Timeout(configuration)); profiler.Start(); benchmark->Run(state.get()); @@ -183,6 +186,8 @@ void print_help() { fprintf(stderr, " --query Prints query of the benchmark\n"); fprintf(stderr, " --root-dir Sets the root directory for where to store temp data and " "look for the 'benchmarks' directory\n"); + fprintf(stderr, " --disable-timeout Disables killing the run after a certain amount of time has " + "passed (30 seconds by default)\n"); fprintf(stderr, " [name_pattern] Run only the benchmark which names match the specified name pattern, " "e.g., DS.* for TPC-DS benchmarks\n"); @@ -253,6 +258,8 @@ void parse_arguments(const int arg_counter, char const *const *arg_values) { } else if (arg == "--query") { // write group of benchmark instance.configuration.meta = BenchmarkMetaType::QUERY; + } else if (arg == "--disable-timeout") { + instance.configuration.timeout_duration = optional_idx(); } else if (StringUtil::StartsWith(arg, "--out=") || StringUtil::StartsWith(arg, "--log=")) { auto splits = StringUtil::Split(arg, '='); if (splits.size() != 2) { diff --git a/benchmark/include/benchmark.hpp b/benchmark/include/benchmark.hpp index b1d8efe660c..ece2dda3d3d 100644 --- a/benchmark/include/benchmark.hpp +++ b/benchmark/include/benchmark.hpp @@ -29,8 +29,6 @@ struct BenchmarkState { //! new benchmarks class Benchmark { constexpr static size_t DEFAULT_NRUNS = 5; - constexpr static size_t DEFAULT_TIMEOUT = 30; - Benchmark(Benchmark &) = delete; public: @@ -87,8 +85,8 @@ class Benchmark { return DEFAULT_NRUNS; } //! The timeout for this benchmark (in seconds) - virtual size_t Timeout() { - return DEFAULT_TIMEOUT; + virtual optional_idx Timeout(const BenchmarkConfiguration &config) { + return config.timeout_duration; } }; diff --git a/benchmark/include/benchmark_configuration.hpp b/benchmark/include/benchmark_configuration.hpp index f8ed43de8d1..02faf77c5ca 100644 --- a/benchmark/include/benchmark_configuration.hpp +++ b/benchmark/include/benchmark_configuration.hpp @@ -12,6 +12,7 @@ #include "duckdb/common/string.hpp" #include "duckdb/common/vector.hpp" #include "duckdb/common/helper.hpp" +#include "duckdb/common/optional_idx.hpp" namespace duckdb { @@ -19,9 +20,14 @@ enum class BenchmarkMetaType { NONE, INFO, QUERY }; enum class BenchmarkProfileInfo { NONE, NORMAL, DETAILED }; struct BenchmarkConfiguration { +public: + constexpr static size_t DEFAULT_TIMEOUT = 30; + +public: string name_pattern {}; BenchmarkMetaType meta = BenchmarkMetaType::NONE; BenchmarkProfileInfo profile_info = BenchmarkProfileInfo::NONE; + optional_idx timeout_duration = optional_idx(DEFAULT_TIMEOUT); }; } // namespace duckdb diff --git a/benchmark/include/interpreted_benchmark.hpp b/benchmark/include/interpreted_benchmark.hpp index 1edc565d694..6d5fe958a71 100644 --- a/benchmark/include/interpreted_benchmark.hpp +++ b/benchmark/include/interpreted_benchmark.hpp @@ -83,6 +83,7 @@ class InterpretedBenchmark : public Benchmark { string subgroup; bool in_memory = true; + bool streaming = false; bool require_reinit = false; }; diff --git a/benchmark/interpreted_benchmark.cpp b/benchmark/interpreted_benchmark.cpp index 84f7ae2043a..f017e7a4589 100644 --- a/benchmark/interpreted_benchmark.cpp +++ b/benchmark/interpreted_benchmark.cpp @@ -177,6 +177,15 @@ void InterpretedBenchmark::LoadBenchmark() { throw std::runtime_error(reader.FormatException("require requires a single parameter")); } extensions.insert(splits[1]); + } else if (splits[0] == "resultmode") { + if (splits.size() != 2) { + throw std::runtime_error(reader.FormatException("resultmode requires a single parameter")); + } + if (splits[1] != "streaming") { + throw std::runtime_error( + reader.FormatException("Invalid argument for resultmode, valid option is 'streaming'")); + } + streaming = true; } else if (splits[0] == "cache") { if (splits.size() == 2) { cache_db = splits[1]; @@ -421,7 +430,14 @@ string InterpretedBenchmark::GetQuery() { void InterpretedBenchmark::Run(BenchmarkState *state_p) { auto &state = (InterpretedBenchmarkState &)*state_p; - state.result = state.con.Query(run_query); + auto &context = state.con.context; + auto temp_result = context->Query(run_query, streaming); + if (temp_result->type == QueryResultType::STREAM_RESULT) { + auto &stream_query = temp_result->Cast(); + state.result = stream_query.Materialize(); + } else { + state.result = unique_ptr_cast(std::move(temp_result)); + } } void InterpretedBenchmark::Cleanup(BenchmarkState *state_p) { diff --git a/benchmark/micro/aggregate/any_value_uuid.benchmark b/benchmark/micro/aggregate/any_value_uuid.benchmark new file mode 100644 index 00000000000..6abfd518955 --- /dev/null +++ b/benchmark/micro/aggregate/any_value_uuid.benchmark @@ -0,0 +1,13 @@ +# name: benchmark/micro/aggregate/any_value_uuid.benchmark +# description: ANY_VALUE(uuid) over a bunch of uuids +# group: [aggregate] + +name Any Value (UUID) +group aggregate + +load +CREATE TABLE t AS SELECT uuid() AS uuid FROM range(100000000) tbl(i); + +run +SELECT ANY_VALUE(uuid) FROM t; + diff --git a/benchmark/micro/aggregate/quantile/quantile.benchmark b/benchmark/micro/aggregate/quantile/quantile.benchmark index b21e8ab30c8..c6406480556 100644 --- a/benchmark/micro/aggregate/quantile/quantile.benchmark +++ b/benchmark/micro/aggregate/quantile/quantile.benchmark @@ -10,4 +10,3 @@ create table quantile as select range r, random() from range(10000000) union all run SELECT quantile(r, 0.5) FROM quantile - diff --git a/benchmark/micro/append_mix.cpp b/benchmark/micro/append_mix.cpp index 13446f79499..33801e9f657 100644 --- a/benchmark/micro/append_mix.cpp +++ b/benchmark/micro/append_mix.cpp @@ -62,7 +62,7 @@ using namespace duckdb; string BenchmarkInfo() override { \ return "Append 10M rows to a table using an Appender"; \ } \ - size_t Timeout() override { \ + optional_idx Timeout(const BenchmarkConfiguration &config) override { \ return 600; \ } diff --git a/benchmark/micro/cte/stacked_materialized_cte.benchmark b/benchmark/micro/cte/stacked_materialized_cte.benchmark new file mode 100644 index 00000000000..0f98a21cd59 --- /dev/null +++ b/benchmark/micro/cte/stacked_materialized_cte.benchmark @@ -0,0 +1,71 @@ +# name: benchmark/micro/cte/stacked_materialized_cte.benchmark +# description: Benchmark of stacked materialized CTEs +# group: [cte] + +name Stacked Materialized CTE +group micro +subgroup cte + +load +create table t1 as select range id from range(1000000); + +run +with +mat_t1 as materialized (select * from t1), +mat_t2 as materialized (select * from mat_t1), +mat_t3 as materialized (select * from mat_t2 where id not in ( + select id % 20 from mat_t2 + )), +mat_t4 as materialized (select * from mat_t1 where id not in ( + select (id % 20) + 20 from mat_t2 + UNION ALL + select (id % 20) + 40 from mat_t3 + )), +mat_t5 as materialized (select * from mat_t1 where id not in ( + select (id % 20) + 20 from mat_t2 + UNION ALL + select (id % 20) + 40 from mat_t3 + UNION ALL + select (id % 20) + 60 from mat_t4 + )), +mat_t6 as materialized (select * from mat_t1 where id not in ( + select (id % 20) + 20 from mat_t2 + UNION ALL + select (id % 20) + 40 from mat_t3 + UNION ALL + select (id % 20) + 60 from mat_t4 + UNION ALL + select (id % 20) + 80 from mat_t5 + )), +mat_t7 as materialized (select * from mat_t1 where id not in ( + select (id % 20) + 20 from mat_t2 + UNION ALL + select (id % 20) + 40 from mat_t3 + UNION ALL + select (id % 20) + 60 from mat_t4 + UNION ALL + select (id % 20) + 80 from mat_t5 + UNION ALL + select (id % 20) + 80 from mat_t6 + )), +mat_t8 as materialized (select * from mat_t1 where id not in ( + select (id % 20) + 20 from mat_t2 + UNION ALL + select (id % 20) + 40 from mat_t3 + UNION ALL + select (id % 20) + 60 from mat_t4 + UNION ALL + select (id % 20) + 80 from mat_t5 + UNION ALL + select (id % 20) + 80 from mat_t6 + UNION ALL + select (id % 20) + 80 from mat_t7 + )) +Select * from mat_t1 UNION ALL +select * from mat_t2 UNION ALL +select * from mat_t3 UNION ALL +select * from mat_t4 UNION ALL +select * from mat_t5 UNION ALL +select * from mat_t6 UNION ALL +select * from mat_t7 UNION ALL +select * from mat_t8; \ No newline at end of file diff --git a/benchmark/micro/date/extract_month.benchmark b/benchmark/micro/date/extract_month.benchmark index 08a790e812f..75bbf984e65 100644 --- a/benchmark/micro/date/extract_month.benchmark +++ b/benchmark/micro/date/extract_month.benchmark @@ -6,7 +6,7 @@ name Extract Month group date load -CREATE TABLE dates AS SELECT DATE '1992-01-01' + concat(i % 10000, ' days')::interval AS d FROM range(0, 10000000) tbl(i); +CREATE TABLE dates AS SELECT DATE '1992-01-01' + (i % 10000)::INT AS d FROM range(0, 1000000000) tbl(i); run SELECT MIN(EXTRACT(MONTH FROM d)) FROM dates diff --git a/benchmark/micro/date/extract_year.benchmark b/benchmark/micro/date/extract_year.benchmark index 3012fa268dd..a96787ad00b 100644 --- a/benchmark/micro/date/extract_year.benchmark +++ b/benchmark/micro/date/extract_year.benchmark @@ -6,7 +6,7 @@ name Extract Year group date load -CREATE TABLE dates AS SELECT DATE '1992-01-01' + concat(i % 10000, ' days')::interval AS d FROM range(0, 10000000) tbl(i); +CREATE TABLE dates AS SELECT DATE '1992-01-01' + (i % 10000)::INT AS d FROM range(0, 1000000000) tbl(i); run SELECT MIN(EXTRACT(YEAR FROM d)) FROM dates diff --git a/benchmark/micro/distinct/distinct_on_pushdown.benchmark b/benchmark/micro/distinct/distinct_on_pushdown.benchmark new file mode 100644 index 00000000000..2433722b614 --- /dev/null +++ b/benchmark/micro/distinct/distinct_on_pushdown.benchmark @@ -0,0 +1,21 @@ +# name: benchmark/micro/distinct/distinct_on_pushdown.benchmark +# description: pushdown columns using distinct on. +# group: [distinct] + +name Distinct on pushdown +group micro +subgroup filter + +load +create table t0 as select random()%100000 col0, random()*10000 col1, random()*100 col2, '1' col3, '2' col4, '3' col5 from range(10000000); + +run +SELECT col0 +FROM +( + SELECT + DISTINCT ON (floor(col0)) + * + FROM t0 + ORDER by col0 DESC +); diff --git a/benchmark/micro/filter/in_conversion.benchmark b/benchmark/micro/filter/in_conversion.benchmark new file mode 100644 index 00000000000..a8cc8558eac --- /dev/null +++ b/benchmark/micro/filter/in_conversion.benchmark @@ -0,0 +1,18 @@ +# name: benchmark/micro/filter/in_conversion.benchmark +# description: IN can be converted to = if there is one argument. for parquet files. +# group: [filter] + +name OrPushdown +group micro +subgroup pushdown + +require tpch + +cache tpch_sf1_lineitem_parquet.duckdb + +load +call dbgen(sf=1); +COPY lineitem TO '${BENCHMARK_DIR}/lineitem.parquet'; + +run +select * from '${BENCHMARK_DIR}/lineitem.parquet' where l_shipinstruct IN ('DELIVER IN PERSON'); diff --git a/benchmark/micro/join/hashjoin_dups_rhs.benchmark b/benchmark/micro/join/hashjoin_dups_rhs.benchmark new file mode 100644 index 00000000000..9b9ef9cdc49 --- /dev/null +++ b/benchmark/micro/join/hashjoin_dups_rhs.benchmark @@ -0,0 +1,16 @@ +# name: benchmark/micro/join/hashjoin_dups_rhs.benchmark +# description: Inner hash join using string comparisons with 4x duplicates on the rhs and 4096x duplicates on the lhs +# group: [join] + +name Inner Join (dups on rhs) +group join + +load +create table t1 as select 'verylargestring' || range % 32768 i from range(131072); +create table t2 as select 'verylargestring' || range % 32768 i from range(134217728); + +run +select count(*) from t1 join t2 using (i) + +result I +536870912 \ No newline at end of file diff --git a/benchmark/micro/list/list_min_max.benchmark b/benchmark/micro/list/list_min_max.benchmark new file mode 100644 index 00000000000..165120f9e57 --- /dev/null +++ b/benchmark/micro/list/list_min_max.benchmark @@ -0,0 +1,16 @@ +# name: benchmark/micro/list/list_min_max.benchmark +# description: List min/max +# group: [list] + +name List min/max +group micro +subgroup list + +load +CREATE TABLE lists AS SELECT [i, i + 1, i + 2] l FROM range(100000001) t(i); + +run +SELECT MIN(l), MAX(l) FROM lists; + +result II +[0, 1, 2] [100000000, 100000001, 100000002] diff --git a/benchmark/micro/list/list_order_by.benchmark b/benchmark/micro/list/list_order_by.benchmark index 961724c3615..69f4fe39089 100644 --- a/benchmark/micro/list/list_order_by.benchmark +++ b/benchmark/micro/list/list_order_by.benchmark @@ -2,7 +2,7 @@ # description: Ordered LIST aggregation # group: [list] -name String Split Regexp +name List Order By group micro subgroup list diff --git a/benchmark/micro/list/list_value.benchmark b/benchmark/micro/list/list_value.benchmark new file mode 100644 index 00000000000..ae70c9d815d --- /dev/null +++ b/benchmark/micro/list/list_value.benchmark @@ -0,0 +1,16 @@ +# name: benchmark/micro/list/list_value.benchmark +# description: LIST_VALUE performance +# group: [list] + +name List Value +group micro +subgroup list + +load +CREATE TABLE uuids AS SELECT uuid() AS uuid FROM range(100000000) tbl(i) UNION ALL SELECT UUID '00000000-0000-0000-0000-000000000000'; + +run +SELECT MIN(l::VARCHAR) FROM (SELECT [uuid] AS l FROM uuids) + +result I +[00000000-0000-0000-0000-000000000000] diff --git a/benchmark/micro/optimizer/topn_optimization.benchmark b/benchmark/micro/optimizer/topn_optimization.benchmark new file mode 100644 index 00000000000..25302101158 --- /dev/null +++ b/benchmark/micro/optimizer/topn_optimization.benchmark @@ -0,0 +1,14 @@ +# name: benchmark/micro/optimizer/topn_optimization.benchmark +# description: Benchmark of top n optimization +# group: [optimizer] + +name TopN Optimization +group micro +subgroup optimizer + +load +CREATE TABLE integers AS SELECT * FROM range(100000000) tbl(i); +CREATE TABLE other_table AS SELECT 337 i UNION ALL SELECT 948247 UNION ALL SELECT 17797934 UNION ALL SELECT 99999998 UNION ALL SELECT 99999999 + +run +SELECT * FROM integers WHERE i IN (SELECT * FROM other_table) ORDER BY i LIMIT 4 diff --git a/benchmark/micro/pushdown/window_partition_pushdown.benchmark b/benchmark/micro/pushdown/window_partition_pushdown.benchmark new file mode 100644 index 00000000000..fe06696a971 --- /dev/null +++ b/benchmark/micro/pushdown/window_partition_pushdown.benchmark @@ -0,0 +1,20 @@ +# name: benchmark/micro/pushdown/window_partition_pushdown.benchmark +# description: measure performance improvement of pushing down filters on window paritions +# group: [pushdown] + +name Window_parition +group micro +subgroup pushdown + +require tpch + +cache tpch_partition_lineitem.duckdb + +load +CALL dbgen(sf=1); +COPY lineitem to '${BENCHMARK_DIR}/lineitem_partitioned' (FORMAT PARQUET, PARTITION_BY l_shipmode); + +run +select * from (select l_shipmode, l_quantity, sum(l_quantity) OVER (PARTITION BY l_shipmode) +from read_parquet('${BENCHMARK_DIR}/lineitem_partitioned/*/*.parquet', hive_partitioning = true)) +where l_shipmode = 'SHIP'; diff --git a/benchmark/micro/result_collection/batched_stream_query.benchmark b/benchmark/micro/result_collection/batched_stream_query.benchmark new file mode 100644 index 00000000000..3c0c97219a6 --- /dev/null +++ b/benchmark/micro/result_collection/batched_stream_query.benchmark @@ -0,0 +1,17 @@ +# name: benchmark/micro/result_collection/batched_stream_query.benchmark +# description: Show the performance of the Batched StreamQueryResult +# group: [result_collection] + +name batched_stream_query +group micro +subgroup result_collection + +resultmode streaming + +load +set streaming_buffer_size = '100gb'; +create table tbl (a varchar); +insert into tbl select 'this is a long string' from range(500000000) t(i) where i % 20 == 0; + +run +select * from tbl; diff --git a/benchmark/micro/update/update_with_join.benchmark b/benchmark/micro/update/update_with_join.benchmark new file mode 100644 index 00000000000..e492b551567 --- /dev/null +++ b/benchmark/micro/update/update_with_join.benchmark @@ -0,0 +1,27 @@ +# name: benchmark/micro/update/update_with_join.benchmark +# description: updated table scan should be on probe side +# group: [update] + +load +create table t(ts_start timestamptz, ts_stop timestamptz, id text); +with dates as ( + select '2023-01-01'::timestamp + i * interval '1 DAY' as x + from generate_series(0, 999) as t(i) +), +ids as ( + select 'id_' || lpad(i::text, 4, '0') as y + from generate_series(0, 999) as t(i) +) +insert into t(ts_start, ts_stop, id) + select d.x, null, i.y from dates d, ids i; + + +run +update t as this +set ts_stop = next.ts_start_next +from ( + select id, ts_start, LEAD(ts_start) over (partition by id order by ts_start) + as ts_start_next + from t +) as next +where this.id=next.id and this.ts_start=next.ts_start; diff --git a/benchmark/micro/window/streaming_lag.benchmark b/benchmark/micro/window/streaming_lag.benchmark new file mode 100644 index 00000000000..5e546bdbd88 --- /dev/null +++ b/benchmark/micro/window/streaming_lag.benchmark @@ -0,0 +1,27 @@ +# name: benchmark/micro/window/streaming_lag.benchmark +# description: Verify performance of streaming LAG +# group: [window] + +load +SELECT SETSEED(0.8675309); +CREATE OR REPLACE TABLE df AS + SELECT + RANDOM() AS a, + RANDOM() AS b, + RANDOM() AS c, + FROM range(10_000_000); + +run +SELECT sum(a_1 + a_2 + b_1 + b_2) +FROM ( + SELECT + LAG(a, 1) OVER () AS a_1, + LAG(a, 2) OVER () AS a_2, + LAG(b, 1) OVER () AS b_1, + LAG(b, 2) OVER () AS b_2 + FROM df +) t +; + +result I +20000902.549240764 diff --git a/data/csv/date_specificity.csv b/data/csv/date_specificity.csv new file mode 100644 index 00000000000..01c608af2df --- /dev/null +++ b/data/csv/date_specificity.csv @@ -0,0 +1,3 @@ +a +0.00 +12/17/2019 \ No newline at end of file diff --git a/data/csv/file_error.csv b/data/csv/file_error.csv new file mode 100644 index 00000000000..e68dc39f352 --- /dev/null +++ b/data/csv/file_error.csv @@ -0,0 +1,4 @@ +id,name,email +1,alice,alice@email.com +2,eve, +3r,bob, \ No newline at end of file diff --git a/data/csv/glob/f_1.csv b/data/csv/glob/f_1.csv new file mode 100644 index 00000000000..6e0c5b6353e --- /dev/null +++ b/data/csv/glob/f_1.csv @@ -0,0 +1,4 @@ +id,name,email +1,alice,alice@email.com +2,eve,eve@email.com +3r,bob, \ No newline at end of file diff --git a/data/csv/glob/f_2.csv b/data/csv/glob/f_2.csv new file mode 100644 index 00000000000..3877315fdfa --- /dev/null +++ b/data/csv/glob/f_2.csv @@ -0,0 +1,3 @@ +id,name,email +1,alice,alice@email.com +3,bob,bob@email.com diff --git a/data/csv/glob/f_3.csv b/data/csv/glob/f_3.csv new file mode 100644 index 00000000000..4c899ed4aee --- /dev/null +++ b/data/csv/glob/f_3.csv @@ -0,0 +1,4 @@ +id,name,email +1,alice,alice@email.com +bla,eve,eve@email.com +3,bob,bob@email.com \ No newline at end of file diff --git a/data/csv/headers/escaped_quote.csv b/data/csv/headers/escaped_quote.csv new file mode 100644 index 00000000000..2b53efcf8cf --- /dev/null +++ b/data/csv/headers/escaped_quote.csv @@ -0,0 +1,3 @@ +Name,Escaped''Quote +Alice,123 +Bob,456 diff --git a/data/csv/headers/unescaped_quote.csv b/data/csv/headers/unescaped_quote.csv new file mode 100644 index 00000000000..95a39b97a7d --- /dev/null +++ b/data/csv/headers/unescaped_quote.csv @@ -0,0 +1,3 @@ +Name,Unescaped'Quote +Alice,123 +Bob,456 diff --git a/data/csv/rejects/dr_who.csv b/data/csv/rejects/dr_who.csv new file mode 100644 index 00000000000..5d9ccbd863f --- /dev/null +++ b/data/csv/rejects/dr_who.csv @@ -0,0 +1,2 @@ +date,datetime,time,timestamp,time_tz +not-a-date,not-a-datetime,not-a-time,not-a-timestamp,not-a-time-tz \ No newline at end of file diff --git a/data/csv/special_date.csv b/data/csv/special_date.csv new file mode 100644 index 00000000000..c7bd42e3c17 --- /dev/null +++ b/data/csv/special_date.csv @@ -0,0 +1,4 @@ +t,d +12:12:12,2000.01.01 +14:15:30,2002.02.02 +15:16:17,2004.12.13 diff --git a/data/csv/test_default_option.csv b/data/csv/test_default_option.csv new file mode 100644 index 00000000000..52f011b41ae --- /dev/null +++ b/data/csv/test_default_option.csv @@ -0,0 +1,20481 @@ +col1,col2 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +a,0 +"x,y",1 diff --git a/data/csv/test_default_option_2.csv b/data/csv/test_default_option_2.csv new file mode 100644 index 00000000000..9596111c706 --- /dev/null +++ b/data/csv/test_default_option_2.csv @@ -0,0 +1,20481 @@ +col1|col2 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +a|0 +"x|y"|1 diff --git a/data/csv/test_ignore_errors.csv b/data/csv/test_ignore_errors.csv new file mode 100644 index 00000000000..3af7ee80471 --- /dev/null +++ b/data/csv/test_ignore_errors.csv @@ -0,0 +1,2 @@ +SourceFileName,Order ID,Order ref ID,Aggregator Order ID,Channel,Order State,Store,Kitchen Legal Entity,RID Legal Entity,RIDs Validated LE,Store Name Key,My Master RIDs,PQ RIDs Master Sheet,City RIDs Master Sheet,State,Kitchen Handlers,Order date-time,Order Time,Item ID,Item ref ID,Item Name,Alter Product Name,Quantity,Unit Price,Total Taxes,Liability On,Total Charges,Total Price,options,option_ids,Coupon applied,city,brand,ItemsCount,Merchant Discount,Total Taxes From Orders,Charges,Item_Wise_Merchant_Discount,Item_Wise_Total_Taxes,Item_Wise_Charges,Cooked/Traded,HSN,Actual Tax Rate,Cess,to_Check +40243121-bechamelfoodsin@gmail_com_item_01_2024.csv,523944955,163178211923806,163178211923806,swiggy,Completed,AMD_VASTRAPUR_JUNOS,NFD,-,-,AMD_VASTRAPUR_JUNOS_swiggy_JP,675029,NFD,NFD,NFD,-,2024-01-02,20:46:54,2235571,474092,Exotica Pizza,exotica pizza,1,539.0,26.95,aggregator,10.0,575.95,"Medium | 1mm"" Thin Crust",1797632 | 1876675,None,Ahmedabad,JP,1.0,0.0,27.45,10.0,0.0,27.45,10.0,Cooked,996331,5.0,0.0,549.0 diff --git a/data/csv/timestamp.csv b/data/csv/timestamp.csv new file mode 100644 index 00000000000..013d63bc91b --- /dev/null +++ b/data/csv/timestamp.csv @@ -0,0 +1,2 @@ +ts +2020-01-01 01:02:03 \ No newline at end of file diff --git a/data/csv/union-by-name/type_mismatch/f_1.csv b/data/csv/union-by-name/type_mismatch/f_1.csv new file mode 100644 index 00000000000..6e0c5b6353e --- /dev/null +++ b/data/csv/union-by-name/type_mismatch/f_1.csv @@ -0,0 +1,4 @@ +id,name,email +1,alice,alice@email.com +2,eve,eve@email.com +3r,bob, \ No newline at end of file diff --git a/data/csv/union-by-name/type_mismatch/f_2.csv b/data/csv/union-by-name/type_mismatch/f_2.csv new file mode 100644 index 00000000000..b153c2ff11c --- /dev/null +++ b/data/csv/union-by-name/type_mismatch/f_2.csv @@ -0,0 +1,3 @@ +id,name,age +1,alice,20 +3,bob,32 diff --git a/data/csv/weather.csv b/data/csv/weather.csv new file mode 100644 index 00000000000..17f3c27dc7a --- /dev/null +++ b/data/csv/weather.csv @@ -0,0 +1,367 @@ +date,maximum_temperature,minimum_temperature,average_temperature,precipitation,snow_fall,snow_depth +1-1-2016,42,34,38.0,0.00,0.0,0 +2-1-2016,40,32,36.0,0.00,0.0,0 +3-1-2016,45,35,40.0,0.00,0.0,0 +4-1-2016,36,14,25.0,0.00,0.0,0 +5-1-2016,29,11,20.0,0.00,0.0,0 +6-1-2016,41,25,33.0,0.00,0.0,0 +7-1-2016,46,31,38.5,0.00,0.0,0 +8-1-2016,46,31,38.5,0.00,0.0,0 +9-1-2016,47,40,43.5,T,0.0,0 +10-1-2016,59,40,49.5,1.80,0.0,0 +11-1-2016,40,26,33.0,0.00,0.0,0 +12-1-2016,44,25,34.5,0.00,T,0 +13-1-2016,30,22,26.0,0.00,0.0,0 +14-1-2016,38,22,30.0,0.00,T,0 +15-1-2016,51,34,42.5,T,0.0,0 +16-1-2016,52,42,47.0,0.24,0.0,0 +17-1-2016,42,30,36.0,0.05,0.4,0 +18-1-2016,31,18,24.5,T,T,T +19-1-2016,28,16,22.0,0.00,0.0,T +20-1-2016,37,27,32.0,0.00,0.0,T +21-1-2016,36,26,31.0,0.00,0.0,0 +22-1-2016,30,21,25.5,0.01,0.2,0 +23-1-2016,27,24,25.5,2.31,27.3,6 +24-1-2016,35,20,27.5,T,T,22 +25-1-2016,39,28,33.5,0.00,0.0,19 +26-1-2016,48,38,43.0,0.00,0.0,17 +27-1-2016,47,34,40.5,T,0.0,9 +28-1-2016,42,32,37.0,0.00,0.0,6 +29-1-2016,41,30,35.5,0.00,0.0,6 +30-1-2016,39,28,33.5,0.00,0.0,6 +31-1-2016,56,36,46.0,0.00,0.0,4 +1-2-2016,59,44,51.5,0.01,0.0,2 +2-2-2016,50,38,44.0,0.00,0.0,T +3-2-2016,59,42,50.5,0.73,0.0,0 +4-2-2016,59,44,51.5,T,0.0,0 +5-2-2016,44,31,37.5,0.53,2.5,1 +6-2-2016,40,30,35.0,0.00,0.0,0 +7-2-2016,47,33,40.0,0.00,0.0,0 +8-2-2016,39,28,33.5,0.05,0.1,0 +9-2-2016,36,27,31.5,0.00,T,T +10-2-2016,39,31,35.0,0.01,T,0 +11-2-2016,31,18,24.5,T,T,0 +12-2-2016,27,15,21.0,0.00,0.0,0 +13-2-2016,22,6,14.0,0.00,0.0,0 +14-2-2016,15,-1,7.0,0.00,0.0,0 +15-2-2016,35,13,24.0,0.44,1.4,0 +16-2-2016,54,35,44.5,1.01,0.0,0 +17-2-2016,39,35,37.0,0.00,0.0,0 +18-2-2016,36,27,31.5,0.00,0.0,0 +19-2-2016,39,24,31.5,0.00,0.0,0 +20-2-2016,61,39,50.0,0.00,0.0,0 +21-2-2016,55,44,49.5,0.03,0.0,0 +22-2-2016,52,38,45.0,0.00,0.0,0 +23-2-2016,40,35,37.5,0.30,T,0 +24-2-2016,60,36,48.0,1.22,0.0,0 +25-2-2016,61,37,49.0,0.02,0.0,0 +26-2-2016,39,27,33.0,0.00,0.0,0 +27-2-2016,41,26,33.5,0.00,0.0,0 +28-2-2016,60,38,49.0,0.00,0.0,0 +29-2-2016,61,47,54.0,0.05,0.0,0 +1-3-2016,52,39,45.5,0.00,0.0,0 +2-3-2016,55,29,42.0,0.14,0.0,0 +3-3-2016,36,26,31.0,0.00,0.0,0 +4-3-2016,39,30,34.5,0.11,0.4,T +5-3-2016,41,28,34.5,0.00,0.0,0 +6-3-2016,44,32,38.0,0.00,0.0,0 +7-3-2016,60,36,48.0,0.00,0.0,0 +8-3-2016,67,47,57.0,0.00,0.0,0 +9-3-2016,77,44,60.5,0.00,0.0,0 +10-3-2016,79,63,71.0,0.00,0.0,0 +11-3-2016,68,48,58.0,0.06,0.0,0 +12-3-2016,59,40,49.5,0.00,0.0,0 +13-3-2016,62,50,56.0,T,0.0,0 +14-3-2016,51,40,45.5,0.29,0.0,0 +15-3-2016,57,44,50.5,0.00,0.0,0 +16-3-2016,65,48,56.5,0.02,0.0,0 +17-3-2016,63,45,54.0,T,0.0,0 +18-3-2016,57,42,49.5,0.00,0.0,0 +19-3-2016,46,36,41.0,0.00,0.0,0 +20-3-2016,43,32,37.5,0.07,T,0 +21-3-2016,50,32,41.0,0.06,0.5,T +22-3-2016,56,35,45.5,0.00,0.0,0 +23-3-2016,71,48,59.5,0.00,0.0,0 +24-3-2016,55,44,49.5,0.00,0.0,0 +25-3-2016,72,44,58.0,0.04,0.0,0 +26-3-2016,55,38,46.5,0.00,0.0,0 +27-3-2016,55,43,49.0,0.00,0.0,0 +28-3-2016,62,42,52.0,0.38,0.0,0 +29-3-2016,53,40,46.5,0.00,0.0,0 +30-3-2016,56,37,46.5,0.00,0.0,0 +31-3-2016,73,49,61.0,0.00,0.0,0 +1-4-2016,79,61,70.0,0.02,0.0,0 +2-4-2016,61,49,55.0,0.16,0.0,0 +3-4-2016,50,34,42.0,0.09,T,0 +4-4-2016,45,29,37.0,0.47,T,0 +5-4-2016,43,26,34.5,0.00,0.0,0 +6-4-2016,48,30,39.0,0.00,0.0,0 +7-4-2016,58,48,53.0,0.09,0.0,0 +8-4-2016,50,40,45.0,0.01,0.0,0 +9-4-2016,43,36,39.5,0.11,T,0 +10-4-2016,50,31,40.5,0.00,0.0,0 +11-4-2016,65,43,54.0,0.01,0.0,0 +12-4-2016,59,45,52.0,0.20,0.0,0 +13-4-2016,58,40,49.0,0.00,0.0,0 +14-4-2016,62,43,52.5,0.00,0.0,0 +15-4-2016,65,42,53.5,0.00,0.0,0 +16-4-2016,68,43,55.5,0.00,0.0,0 +17-4-2016,75,44,59.5,0.00,0.0,0 +18-4-2016,82,51,66.5,0.00,0.0,0 +19-4-2016,73,55,64.0,0.00,0.0,0 +20-4-2016,69,49,59.0,0.00,0.0,0 +21-4-2016,73,49,61.0,0.00,0.0,0 +22-4-2016,79,62,70.5,T,0.0,0 +23-4-2016,71,54,62.5,0.16,0.0,0 +24-4-2016,68,47,57.5,0.00,0.0,0 +25-4-2016,69,50,59.5,0.00,0.0,0 +26-4-2016,60,47,53.5,0.24,0.0,0 +27-4-2016,62,46,54.0,0.00,0.0,0 +28-4-2016,59,48,53.5,0.00,0.0,0 +29-4-2016,58,45,51.5,0.05,0.0,0 +30-4-2016,65,46,55.5,0.00,0.0,0 +1-5-2016,51,45,48.0,0.16,0.0,0 +2-5-2016,60,45,52.5,0.04,0.0,0 +3-5-2016,56,51,53.5,0.61,0.0,0 +4-5-2016,52,48,50.0,0.01,0.0,0 +5-5-2016,57,46,51.5,0.00,0.0,0 +6-5-2016,54,48,51.0,0.54,0.0,0 +7-5-2016,60,48,54.0,0.00,0.0,0 +8-5-2016,66,49,57.5,0.16,0.0,0 +9-5-2016,72,52,62.0,0.00,0.0,0 +10-5-2016,63,50,56.5,0.00,0.0,0 +11-5-2016,76,50,63.0,0.00,0.0,0 +12-5-2016,80,56,68.0,0.00,0.0,0 +13-5-2016,65,57,61.0,0.25,0.0,0 +14-5-2016,73,56,64.5,0.00,0.0,0 +15-5-2016,59,46,52.5,0.00,0.0,0 +16-5-2016,66,43,54.5,0.00,0.0,0 +17-5-2016,64,52,58.0,0.00,0.0,0 +18-5-2016,68,52,60.0,T,0.0,0 +19-5-2016,73,54,63.5,0.00,0.0,0 +20-5-2016,76,53,64.5,0.00,0.0,0 +21-5-2016,66,54,60.0,0.04,0.0,0 +22-5-2016,70,52,61.0,0.09,0.0,0 +23-5-2016,78,56,67.0,0.02,0.0,0 +24-5-2016,73,58,65.5,0.18,0.0,0 +25-5-2016,88,61,74.5,0.00,0.0,0 +26-5-2016,90,69,79.5,0.00,0.0,0 +27-5-2016,87,73,80.0,0.00,0.0,0 +28-5-2016,92,71,81.5,0.00,0.0,0 +29-5-2016,87,70,78.5,T,0.0,0 +30-5-2016,82,68,75.0,1.65,0.0,0 +31-5-2016,85,71,78.0,0.00,0.0,0 +1-6-2016,83,66,74.5,0.00,0.0,0 +2-6-2016,78,62,70.0,0.00,0.0,0 +3-6-2016,70,63,66.5,0.04,0.0,0 +4-6-2016,83,66,74.5,0.40,0.0,0 +5-6-2016,71,65,68.0,0.91,0.0,0 +6-6-2016,83,65,74.0,0.00,0.0,0 +7-6-2016,85,64,74.5,T,0.0,0 +8-6-2016,67,52,59.5,0.45,0.0,0 +9-6-2016,71,54,62.5,0.00,0.0,0 +10-6-2016,77,57,67.0,0.00,0.0,0 +11-6-2016,88,59,73.5,0.00,0.0,0 +12-6-2016,83,62,72.5,0.00,0.0,0 +13-6-2016,74,57,65.5,0.00,0.0,0 +14-6-2016,79,58,68.5,0.00,0.0,0 +15-6-2016,85,62,73.5,0.00,0.0,0 +16-6-2016,74,65,69.5,0.22,0.0,0 +17-6-2016,78,63,70.5,0.00,0.0,0 +18-6-2016,87,61,74.0,0.00,0.0,0 +19-6-2016,88,66,77.0,0.00,0.0,0 +20-6-2016,84,64,74.0,0.00,0.0,0 +21-6-2016,87,72,79.5,T,0.0,0 +22-6-2016,86,68,77.0,0.00,0.0,0 +23-6-2016,83,69,76.0,0.00,0.0,0 +24-6-2016,84,67,75.5,0.00,0.0,0 +25-6-2016,86,64,75.0,0.00,0.0,0 +26-6-2016,87,67,77.0,0.00,0.0,0 +27-6-2016,83,67,75.0,0.45,0.0,0 +28-6-2016,76,68,72.0,0.12,0.0,0 +29-6-2016,83,67,75.0,0.01,0.0,0 +30-6-2016,85,67,76.0,0.00,0.0,0 +1-7-2016,79,66,72.5,0.83,0,0 +2-7-2016,76,63,69.5,0,0,0 +3-7-2016,78,64,71,0,0,0 +4-7-2016,84,66,75,0.49,0,0 +5-7-2016,86,69,77.5,0.66,0,0 +6-7-2016,91,75,83,0,0,0 +7-7-2016,89,77,83,0.04,0,0 +8-7-2016,86,67,76.5,0.08,0,0 +9-7-2016,72,65,68.5,0.53,0,0 +10-7-2016,80,66,73,T,0,0 +11-7-2016,81,65,73,0,0,0 +12-7-2016,82,68,75,0,0,0 +13-7-2016,85,71,78,0,0,0 +14-7-2016,88,73,80.5,0.62,0,0 +15-7-2016,88,79,83.5,0,0,0 +16-7-2016,90,75,82.5,T,0,0 +17-7-2016,89,75,82,0,0,0 +18-7-2016,93,72,82.5,0.35,0,0 +19-7-2016,83,73,78,0,0,0 +20-7-2016,85,68,76.5,0,0,0 +21-7-2016,90,71,80.5,0,0,0 +22-7-2016,94,74,84,0,0,0 +23-7-2016,96,80,88,0,0,0 +24-7-2016,94,75,84.5,0,0,0 +25-7-2016,93,73,83,1,0,0 +26-7-2016,89,72,80.5,0,0,0 +27-7-2016,91,74,82.5,0,0,0 +28-7-2016,95,75,85,T,0,0 +29-7-2016,85,69,77,1.09,0,0 +30-7-2016,84,73,78.5,0.25,0,0 +31-7-2016,78,71,74.5,1.08,0,0 +1-8-2016,80,69,74.5,T,0,0 +2-8-2016,79,68,73.5,0,0,0 +3-8-2016,80,66,73,0,0,0 +4-8-2016,81,67,74,0,0,0 +5-8-2016,83,69,76,0,0,0 +6-8-2016,87,72,79.5,0.05,0,0 +7-8-2016,86,70,78,0,0,0 +8-8-2016,86,71,78.5,0,0,0 +9-8-2016,87,71,79,0,0,0 +10-8-2016,86,75,80.5,0.09,0,0 +11-8-2016,91,74,82.5,0.15,0,0 +12-8-2016,93,73,83,0.32,0,0 +13-8-2016,96,81,88.5,0,0,0 +14-8-2016,94,78,86,0.06,0,0 +15-8-2016,92,77,84.5,0,0,0 +16-8-2016,87,78,82.5,0.11,0,0 +17-8-2016,85,77,81,0.01,0,0 +18-8-2016,85,72,78.5,0.03,0,0 +19-8-2016,88,74,81,0.01,0,0 +20-8-2016,83,70,76.5,0.82,0,0 +21-8-2016,86,73,79.5,0.31,0,0 +22-8-2016,79,65,72,0,0,0 +23-8-2016,82,61,71.5,0,0,0 +24-8-2016,88,68,78,0,0,0 +25-8-2016,86,69,77.5,0.01,0,0 +26-8-2016,90,75,82.5,0,0,0 +27-8-2016,89,73,81,0,0,0 +28-8-2016,89,72,80.5,0,0,0 +29-8-2016,91,74,82.5,0,0,0 +30-8-2016,86,69,77.5,0,0,0 +31-8-2016,89,74,81.5,T,0,0 +1-9-2016,79,69,74,0.5,0,0 +2-9-2016,81,66,73.5,0,0,0 +3-9-2016,75,66,70.5,0,0,0 +4-9-2016,80,65,72.5,0,0,0 +5-9-2016,84,65,74.5,0,0,0 +6-9-2016,80,71,75.5,T,0,0 +7-9-2016,85,71,78,0,0,0 +8-9-2016,89,71,80,0,0,0 +9-9-2016,91,75,83,0.22,0,0 +10-9-2016,90,74,82,T,0,0 +11-9-2016,83,67,75,0,0,0 +12-9-2016,78,62,70,0,0,0 +13-9-2016,83,64,73.5,0,0,0 +14-9-2016,91,67,79,0.56,0,0 +15-9-2016,74,61,67.5,0,0,0 +16-9-2016,73,61,67,0,0,0 +17-9-2016,77,59,68,0,0,0 +18-9-2016,82,70,76,0,0,0 +19-9-2016,76,69,72.5,0.68,0,0 +20-9-2016,82,68,75,0,0,0 +21-9-2016,84,68,76,0,0,0 +22-9-2016,86,65,75.5,0,0,0 +23-9-2016,87,64,75.5,0.01,0,0 +24-9-2016,71,58,64.5,0.2,0,0 +25-9-2016,70,54,62,0,0,0 +26-9-2016,74,54,64,0,0,0 +27-9-2016,74,64,69,0.22,0,0 +28-9-2016,69,56,62.5,0,0,0 +29-9-2016,64,57,60.5,0,0,0 +30-9-2016,59,56,57.5,0.4,0,0 +1-10-2016,62,56,59,0,0,0 +2-10-2016,63,57,60,0,0,0 +3-10-2016,72,60,66,0,0,0 +4-10-2016,69,60,64.5,0,0,0 +5-10-2016,67,53,60,0,0,0 +6-10-2016,73,55,64,0,0,0 +7-10-2016,75,57,66,0,0,0 +8-10-2016,68,58,63,0.23,0,0 +9-10-2016,65,51,58,0.55,0,0 +10-10-2016,64,47,55.5,0,0,0 +11-10-2016,63,46,54.5,0,0,0 +12-10-2016,66,53,59.5,0,0,0 +13-10-2016,67,53,60,T,0,0 +14-10-2016,62,47,54.5,0,0,0 +15-10-2016,65,45,55,0,0,0 +16-10-2016,69,53,61,0,0,0 +17-10-2016,81,63,72,0,0,0 +18-10-2016,81,67,74,0,0,0 +19-10-2016,85,65,75,0,0,0 +20-10-2016,70,62,66,0,0,0 +21-10-2016,69,57,63,1.11,0,0 +22-10-2016,57,47,52,0.29,0,0 +23-10-2016,61,45,53,0,0,0 +24-10-2016,62,47,54.5,T,0,0 +25-10-2016,52,43,47.5,0,0,0 +26-10-2016,51,38,44.5,0,0,0 +27-10-2016,55,40,47.5,1.41,0,0 +28-10-2016,51,42,46.5,0,0,0 +29-10-2016,64,39,51.5,0,0,0 +30-10-2016,76,54,65,0.56,0,0 +31-10-2016,54,44,49,0,0,0 +1-11-2016,58,40,49,0,0,0 +2-11-2016,70,54,62,0,0,0 +3-11-2016,72,57,64.5,0,0,0 +4-11-2016,61,47,54,0,0,0 +5-11-2016,62,44,53,0,0,0 +6-11-2016,59,45,52,0,0,0 +7-11-2016,53,41,47,0,0,0 +8-11-2016,66,41,53.5,0,0,0 +9-11-2016,59,49,54,0.06,0,0 +10-11-2016,56,40,48,0,0,0 +11-11-2016,63,41,52,0,0,0 +12-11-2016,50,37,43.5,0,0,0 +13-11-2016,61,41,51,0,0,0 +14-11-2016,62,46,54,0,0,0 +15-11-2016,56,47,51.5,1.81,0,0 +16-11-2016,61,45,53,0,0,0 +17-11-2016,61,49,55,0,0,0 +18-11-2016,64,44,54,0,0,0 +19-11-2016,63,37,50,0.25,0,0 +20-11-2016,42,34,38,0.31,T,0 +21-11-2016,41,36,38.5,0,0,0 +22-11-2016,41,37,39,0,0,0 +23-11-2016,45,35,40,0,0,0 +24-11-2016,48,38,43,0.03,0,0 +25-11-2016,54,45,49.5,0.02,0,0 +26-11-2016,50,40,45,0,0,0 +27-11-2016,50,39,44.5,0,0,0 +28-11-2016,52,38,45,0,0,0 +29-11-2016,60,51,55.5,2.2,0,0 +30-11-2016,58,50,54,0.73,0,0 +1-12-2016,54,42,48,0.07,0,0 +2-12-2016,51,40,45.5,0,0,0 +3-12-2016,47,41,44,T,0,0 +4-12-2016,47,39,43,0,0,0 +5-12-2016,49,38,43.5,0.19,0,0 +6-12-2016,46,37,41.5,0.35,0,0 +7-12-2016,46,40,43,0.09,0,0 +8-12-2016,45,35,40,0,0,0 +9-12-2016,39,29,34,0,0,0 +10-12-2016,35,28,31.5,0,0,0 +11-12-2016,35,28,31.5,0.03,0.4,0 +12-12-2016,46,34,40,0.5,0,0 +13-12-2016,43,35,39,0,0,0 +14-12-2016,42,34,38,0,0,0 +15-12-2016,34,19,26.5,0,T,0 +16-12-2016,27,17,22,0,0,0 +17-12-2016,39,24,31.5,0.73,2.8,2 +18-12-2016,58,31,44.5,0.04,0,1 +19-12-2016,31,23,27,0,0,0 +20-12-2016,33,20,26.5,0,0,0 +21-12-2016,40,30,35,0,0,0 +22-12-2016,49,37,43,0,0,0 +23-12-2016,47,38,42.5,0,0,0 +24-12-2016,47,38,42.5,0.47,0,0 +25-12-2016,50,36,43,0,0,0 +26-12-2016,50,33,41.5,0.02,0,0 +27-12-2016,60,40,50,0,0,0 +28-12-2016,40,34,37,0,0,0 +29-12-2016,46,33,39.5,0.39,0,0 +30-12-2016,40,33,36.5,0.01,T,0 +31-12-2016,44,31,37.5,0,0,0 \ No newline at end of file diff --git a/data/json/12188.ndjson b/data/json/12188.ndjson new file mode 100644 index 00000000000..2c5b5e06f9b --- /dev/null +++ b/data/json/12188.ndjson @@ -0,0 +1,2 @@ +{"field1": "value1", "field2": {"subfield1": "subvalue1"}} +{"field1": "value2", "field2": {"subfield2": "subvalue2"}} diff --git a/data/json/map_50_50.jsonl b/data/json/map_50_50.jsonl new file mode 100644 index 00000000000..d8219fdf8f0 --- /dev/null +++ b/data/json/map_50_50.jsonl @@ -0,0 +1,14 @@ +{ + "a": { + "s1": {"f1": [1]}, + "s2": {"f2": [1]}, + "s3": {"f1": [1]}, + "s4": {"f2": [1]}, + "s5": {"f1": [1]}, + "s6": {"f2": [1]}, + "s7": {"f1": [1]}, + "s8": {"f2": [1]}, + "s9": {"f1": [1]}, + "s10": {"f2": [1]} + } +} \ No newline at end of file diff --git a/data/json/map_incompatible.jsonl b/data/json/map_incompatible.jsonl new file mode 100644 index 00000000000..8419a7665bf --- /dev/null +++ b/data/json/map_incompatible.jsonl @@ -0,0 +1,14 @@ +{ + "a": { + "s1": {"1": null}, + "s2": {"1": {}}, + "s3": {"1": "1"}, + "s4": {"1": [1]}, + "s5": {"1": 1}, + "s6": {"1": "1"}, + "s7": {"1": [1]}, + "s8": {"1": 1}, + "s9": {"1": "1"}, + "s10": {"1": [1]} + } +} \ No newline at end of file diff --git a/data/json/map_of_dates.jsonl b/data/json/map_of_dates.jsonl new file mode 100644 index 00000000000..c72c594fdb7 --- /dev/null +++ b/data/json/map_of_dates.jsonl @@ -0,0 +1,29 @@ +{ + "a": { + "1": null, + "2": "2024-01-01", + "3": "2024-01-01", + "4": "2024-01-01", + "5": "2024-01-01", + "6": "2024-01-01", + "7": "2024-01-01", + "8": "2024-01-01", + "9": null, + "10": "2024-01-01", + "11": "2024-01-01", + "12": "2024-01-01", + "13": "2024-01-01", + "14": "2024-01-01", + "15": "2024-01-01", + "16": "2024-01-01", + "17": "2024-01-01", + "18": "2024-01-01", + "19": "2024-01-01", + "20": "2024-01-01", + "21": "2024-01-01", + "22": "2024-01-01", + "23": "2024-01-01", + "24": "2024-01-01", + "25": "2024-01-01" + } +} diff --git a/data/json/map_of_map.jsonl b/data/json/map_of_map.jsonl new file mode 100644 index 00000000000..0b445937127 --- /dev/null +++ b/data/json/map_of_map.jsonl @@ -0,0 +1,52 @@ +{ + "a": { + "l1k2": { + "l2k1": 1 + }, + "l1k1": { + "l2k1": 1, + "l2k2": 2, + "l2k3": 3, + "l2k4": 4, + "l2k5": 5, + "l2k6": 6, + "l2k7": 7, + "l2k8": 8, + "l2k9": 9, + "l2k10": 10 + }, + "l1k3": { + "l2k1": 1 + }, + "l1k4": { + "l2k1": 1 + }, + "l1k5": { + "l2k1": null, + "l2k2": null, + "l2k3": null, + "l2k4": null, + "l2k5": null, + "l2k6": null, + "l2k7": null, + "l2k8": null, + "l2k9": null, + "l2k10": null + }, + "l1k6": { + "l2k1": 1 + }, + "l1k7": { + "l2k1": 1 + }, + "l1k8": { + "l2k1": 1 + }, + "l1k9": { + "l2k1": 1 + }, + "l1k10": { + "l2k1": 1 + } + } +} \ No newline at end of file diff --git a/data/json/map_of_mixed_date_timestamps.jsonl b/data/json/map_of_mixed_date_timestamps.jsonl new file mode 100644 index 00000000000..a6ac1c8c9c5 --- /dev/null +++ b/data/json/map_of_mixed_date_timestamps.jsonl @@ -0,0 +1,29 @@ +{ + "a": { + "1": null, + "2": "2024-01-01", + "3": "2024-01-01T00:00:00Z", + "4": "2024-01-01", + "5": "2024-01-01", + "6": "2024-01-01", + "7": "2024-01-01", + "8": "2024-01-01", + "9": null, + "10": "2024-01-01", + "11": "2024-01-01", + "12": "2024-01-01", + "13": "2024-01-01T00:00:00Z", + "14": "2024-01-01", + "15": "2024-01-01", + "16": "2024-01-01", + "17": "2024-01-01", + "18": "2024-01-01T00:00:00Z", + "19": "2024-01-01T00:00:00Z", + "20": "2024-01-01", + "21": "2024-01-01", + "22": "2024-01-01", + "23": "2024-01-01", + "24": "2024-01-01", + "25": "2024-01-01T00:00:00Z" + } +} diff --git a/data/json/map_of_nulls.jsonl b/data/json/map_of_nulls.jsonl new file mode 100644 index 00000000000..2a6726228eb --- /dev/null +++ b/data/json/map_of_nulls.jsonl @@ -0,0 +1,100 @@ +{"a": {"1": null}} +{"a": {"2": null}} +{"a": {"3": null}} +{"a": {"4": null}} +{"a": {"5": null}} +{"a": {"6": null}} +{"a": {"7": null}} +{"a": {"8": null}} +{"a": {"9": null}} +{"a": {"10": null}} +{"a": {"11": null}} +{"a": {"12": null}} +{"a": {"13": null}} +{"a": {"14": null}} +{"a": {"15": null}} +{"a": {"16": null}} +{"a": {"17": null}} +{"a": {"18": null}} +{"a": {"19": null}} +{"a": {"20": null}} +{"a": {"21": null}} +{"a": {"22": null}} +{"a": {"23": null}} +{"a": {"24": null}} +{"a": {"25": null}} +{"a": {"26": null}} +{"a": {"27": null}} +{"a": {"28": null}} +{"a": {"29": null}} +{"a": {"30": null}} +{"a": {"31": null}} +{"a": {"32": null}} +{"a": {"33": null}} +{"a": {"34": null}} +{"a": {"35": null}} +{"a": {"36": null}} +{"a": {"37": null}} +{"a": {"38": null}} +{"a": {"39": null}} +{"a": {"40": null}} +{"a": {"41": null}} +{"a": {"42": null}} +{"a": {"43": null}} +{"a": {"44": null}} +{"a": {"45": null}} +{"a": {"46": null}} +{"a": {"47": null}} +{"a": {"48": null}} +{"a": {"49": null}} +{"a": {"50": null}} +{"a": {"51": null}} +{"a": {"52": null}} +{"a": {"53": null}} +{"a": {"54": null}} +{"a": {"55": null}} +{"a": {"56": null}} +{"a": {"57": null}} +{"a": {"58": null}} +{"a": {"59": null}} +{"a": {"60": null}} +{"a": {"61": null}} +{"a": {"62": null}} +{"a": {"63": null}} +{"a": {"64": null}} +{"a": {"65": null}} +{"a": {"66": null}} +{"a": {"67": null}} +{"a": {"68": null}} +{"a": {"69": null}} +{"a": {"70": null}} +{"a": {"71": null}} +{"a": {"72": null}} +{"a": {"73": null}} +{"a": {"74": null}} +{"a": {"75": null}} +{"a": {"76": null}} +{"a": {"77": null}} +{"a": {"78": null}} +{"a": {"79": null}} +{"a": {"80": null}} +{"a": {"81": null}} +{"a": {"82": null}} +{"a": {"83": null}} +{"a": {"84": null}} +{"a": {"85": null}} +{"a": {"86": null}} +{"a": {"87": null}} +{"a": {"88": null}} +{"a": {"89": null}} +{"a": {"90": null}} +{"a": {"91": null}} +{"a": {"92": null}} +{"a": {"93": null}} +{"a": {"94": null}} +{"a": {"95": null}} +{"a": {"96": null}} +{"a": {"97": null}} +{"a": {"98": null}} +{"a": {"99": null}} +{"a": {"100": null}} diff --git a/data/json/map_of_struct_with_nulls.jsonl b/data/json/map_of_struct_with_nulls.jsonl new file mode 100644 index 00000000000..ca631293c3a --- /dev/null +++ b/data/json/map_of_struct_with_nulls.jsonl @@ -0,0 +1,34 @@ +{ + "a": { + "1": { + "a": null + }, + "2": { + "a": [null] + }, + "3": { + "a": [null] + }, + "4": { + "a": [null] + }, + "5": { + "a": [null] + }, + "6": { + "a": null + }, + "7": { + "a": [null] + }, + "8": { + "a": [null] + }, + "9": { + "a": [null] + }, + "10": { + "a": null + } + } +} \ No newline at end of file diff --git a/data/json/map_of_structs.jsonl b/data/json/map_of_structs.jsonl new file mode 100644 index 00000000000..02bfe14732b --- /dev/null +++ b/data/json/map_of_structs.jsonl @@ -0,0 +1,100 @@ +{"a": {"1": {}}} +{"a": {"2": null}} +{"a": {"3": {"b": 3}}} +{"a": {"4": {}}} +{"a": {"5": {"b": 5}}} +{"a": {"6": {"b": 6}}} +{"a": {"7": null}} +{"a": {"8": {"b": 8}}} +{"a": {"9": {}}} +{"a": {"10": {"b": 10}}} +{"a": {"11": {"b": 11}}} +{"a": {"12": {"b": 12}}} +{"a": {"13": {"b": 13}}} +{"a": {}} +{"a": {"15": {"b": 15}}} +{"a": {"16": {"b": 16}}} +{"a": {"17": {"b": 17}}} +{"a": null} +{"a": {"19": {"b": 19}}} +{"a": {"20": {"b": 20}}} +{"a": {"21": {"b": 21}}} +{} +{"a": {"23": {"b": 23}}} +{"a": {"24": {"b": 24}}} +{"a": {"25": {"b": 25}}} +{"a": {"26": {"b": 26}}} +{"a": {"27": {"b": 27}}} +{"a": {"28": {"b": 28}}} +{"a": {"29": {"b": 29}}} +{"a": {"30": {"b": 30}}} +{"a": {"31": {"b": 31}}} +{"a": {"32": {"b": 32}}} +{"a": {"33": {"b": 33}}} +{"a": {"34": {"b": 34}}} +{"a": {"35": {"b": 35}}} +{"a": {"36": {"b": 36}}} +{"a": {"37": {"b": 37}}} +{"a": {"38": {"b": 38}}} +{"a": {"39": {"b": 39}}} +{"a": {"40": {"b": 40}}} +{"a": {"41": {"b": 41}}} +{"a": {"42": {"b": 42}}} +{"a": {"43": {"b": 43}}} +{"a": {"44": {"b": 44}}} +{"a": {"45": {"b": 45}}} +{"a": {"46": {"b": 46}}} +{"a": {"47": {"b": 47}}} +{"a": {"48": {"b": 48}}} +{"a": {"49": {"b": 49}}} +{"a": {"50": {"b": 50}}} +{"a": {"51": {"b": 51}}} +{"a": {"52": {"b": 52}}} +{"a": {"53": {"b": 53}}} +{"a": {"54": {"b": 54}}} +{"a": {"55": {"b": 55}}} +{"a": {"56": {"b": 56}}} +{"a": {"57": {"b": 57}}} +{"a": {"58": {"b": 58}}} +{"a": {"59": {"b": 59}}} +{"a": {"60": {"b": 60}}} +{"a": {"61": {"b": 61}}} +{"a": {"62": {"b": 62}}} +{"a": {"63": {"b": 63}}} +{"a": {"64": {"b": 64}}} +{"a": {"65": {"b": 65}}} +{"a": {"66": {"b": 66}}} +{"a": {"67": {"b": 67}}} +{"a": {"68": {"b": 68}}} +{"a": {"69": {"b": 69}}} +{"a": {"70": {"b": 70}}} +{"a": {"71": {"b": 71}}} +{"a": {"72": {"b": 72}}} +{"a": {"73": {"b": 73}}} +{"a": {"74": {"b": 74}}} +{"a": {"75": {"b": 75}}} +{"a": {"76": {"b": 76}}} +{"a": {"77": {"b": 77}}} +{"a": {"78": {"b": 78}}} +{"a": {"79": {"b": 79}}} +{"a": {"80": {"b": 80}}} +{"a": {"81": {"b": 81}}} +{"a": {"82": {"b": 82}}} +{"a": {"83": {"b": 83}}} +{"a": {"84": {"b": 84}}} +{"a": {"85": {"b": 85}}} +{"a": {"86": {"b": 86}}} +{"a": {"87": {"b": 87}}} +{"a": {"88": {"b": 88}}} +{"a": {"89": {"b": 89}}} +{"a": {"90": {"b": 90}}} +{"a": {"91": {"b": 91}}} +{"a": {"92": {"b": 92}}} +{"a": {"93": {"b": 93}}} +{"a": {"94": {"b": 94}}} +{"a": {"95": {"b": 95}}} +{"a": {"96": {"b": 96}}} +{"a": {"97": {"b": 97}}} +{"a": {"98": {"b": 98}}} +{"a": {"99": {"b": 99}}} +{"a": {"100": {"b": 100}}} diff --git a/data/json/simple_map.jsonl b/data/json/simple_map.jsonl new file mode 100644 index 00000000000..c6df9aac32e --- /dev/null +++ b/data/json/simple_map.jsonl @@ -0,0 +1,100 @@ +{"a": {"1": null}} +{"a": {"2": 2}} +{"a": {"3": 3}} +{"a": {"4": 4}} +{"a": {"5": 5}} +{"a": {"6": 6}} +{"a": {"7": 7}} +{"a": {"8": 8}} +{"a": {"9": 9}} +{"a": {"10": 10}} +{"a": {"11": 11}} +{"a": {"12": 12}} +{"a": {"13": 13}} +{"a": {"14": 14}} +{"a": {"15": 15}} +{"a": {"16": null}} +{"a": {"17": 17}} +{"a": {"18": 18}} +{"a": {"19": 19}} +{"a": {"20": 20}} +{"a": {"21": 21}} +{"a": {"22": 22}} +{"a": {"23": 23}} +{"a": {"24": 24}} +{"a": {"25": 25}} +{"a": {"26": 26}} +{"a": {"27": 27}} +{"a": {"28": 28}} +{"a": {"29": 29}} +{"a": {"30": 30}} +{"a": {"31": 31}} +{"a": {"32": 32}} +{"a": {"33": 33}} +{"a": {"34": 34}} +{"a": {"35": 35}} +{"a": {"36": 36}} +{"a": {"37": 37}} +{"a": {"38": 38}} +{"a": {"39": 39}} +{"a": {"40": 40}} +{"a": {"41": 41}} +{"a": {"42": 42}} +{"a": {"43": 43}} +{"a": {"44": 44}} +{"a": {"45": 45}} +{"a": {"46": 46}} +{"a": {"47": 47}} +{"a": {"48": 48}} +{"a": {"49": 49}} +{"a": {"50": 50}} +{"a": {"51": 51}} +{"a": {"52": 52}} +{"a": {"53": 53}} +{"a": {"54": 54}} +{"a": {"55": 55}} +{"a": {"56": 56}} +{"a": {"57": 57}} +{"a": {"58": 58}} +{"a": {"59": 59}} +{"a": {"60": 60}} +{"a": {"61": 61}} +{"a": {"62": 62}} +{"a": {"63": 63}} +{"a": {"64": 64}} +{"a": {"65": 65}} +{"a": {"66": 66}} +{"a": {"67": 67}} +{"a": {"68": 68}} +{"a": {"69": 69}} +{"a": {"70": 70}} +{"a": {"71": 71}} +{"a": {"72": 72}} +{"a": {"73": 73}} +{"a": {"74": 74}} +{"a": {"75": 75}} +{"a": {"76": 76}} +{"a": {"77": 77}} +{"a": {"78": 78}} +{"a": {"79": 79}} +{"a": {"80": 80}} +{"a": {"81": 81}} +{"a": {"82": 82}} +{"a": {"83": 83}} +{"a": {"84": 84}} +{"a": {"85": 85}} +{"a": {"86": 86}} +{"a": {"87": 87}} +{"a": {"88": 88}} +{"a": {"89": 89}} +{"a": {"90": 90}} +{"a": {"91": 91}} +{"a": {"92": 92}} +{"a": {"93": 93}} +{"a": {"94": 94}} +{"a": {"95": 95}} +{"a": {"96": 96}} +{"a": {"97": 97}} +{"a": {"98": 98}} +{"a": {"99": 99}} +{"a": {"100": 100}} diff --git a/data/json/top_level_map.jsonl b/data/json/top_level_map.jsonl new file mode 100644 index 00000000000..8211ac8402f --- /dev/null +++ b/data/json/top_level_map.jsonl @@ -0,0 +1,100 @@ +{"1": 1} +{"2": 2} +{"3": 3} +{"4": 4} +{"5": 5} +{"6": 6} +{"7": 7} +{"8": 8} +{"9": 9} +{"10": 10} +{"11": 11} +{"12": 12} +{"13": 13} +{"14": 14} +{"15": 15} +{"16": 16} +{"17": 17} +{"18": 18} +{"19": 19} +{"20": 20} +{"21": 21} +{"22": 22} +{"23": 23} +{"24": 24} +{"25": 25} +{"26": 26} +{"27": 27} +{"28": 28} +{"29": 29} +{"30": 30} +{"31": 31} +{"32": 32} +{"33": 33} +{"34": 34} +{"35": 35} +{"36": 36} +{"37": 37} +{"38": 38} +{"39": 39} +{"40": 40} +{"41": 41} +{"42": 42} +{"43": 43} +{"44": 44} +{"45": 45} +{"46": 46} +{"47": 47} +{"48": 48} +{"49": 49} +{"50": 50} +{"51": 51} +{"52": 52} +{"53": 53} +{"54": 54} +{"55": 55} +{"56": 56} +{"57": 57} +{"58": 58} +{"59": 59} +{"60": 60} +{"61": 61} +{"62": 62} +{"63": 63} +{"64": 64} +{"65": 65} +{"66": 66} +{"67": 67} +{"68": 68} +{"69": 69} +{"70": 70} +{"71": 71} +{"72": 72} +{"73": 73} +{"74": 74} +{"75": 75} +{"76": 76} +{"77": 77} +{"78": 78} +{"79": 79} +{"80": 80} +{"81": 81} +{"82": 82} +{"83": 83} +{"84": 84} +{"85": 85} +{"86": 86} +{"87": 87} +{"88": 88} +{"89": 89} +{"90": 90} +{"91": 91} +{"92": 92} +{"93": 93} +{"94": 94} +{"95": 95} +{"96": 96} +{"97": 97} +{"98": 98} +{"99": 99} +{"100": 100} diff --git a/data/parquet-testing/parquet_with_json.parquet b/data/parquet-testing/parquet_with_json.parquet new file mode 100644 index 0000000000000000000000000000000000000000..e37dfa0337fea9f1597fbbfe126be1d8b83a0e6c GIT binary patch literal 428 zcmWG=3^EjD5Va9?&=F+;GT21f7#QSAm>3usSQt5gq*7U8PHC#45`t}{1XS0+D4K_) z!yy8qLlUT?TB*1+DJ?TKC&f_7ijhYKYCx@-EQ5uSk`+i6EM%lqE6OBkW6B`Gn^Kyb zostw^oSc!Gn<&b{Aj+f4B*6wTLsbo#YXszqu}I2D>Zmcui1J8^GDyM{iZY3@h{cH| zsd3mya6p`Gqy%FbDv2>@U=ann7u_Huut7^0#U?STW!XqbBK(8qdSoe}SK%HrRH_A9 iMwULHbHtu>aEP&}aWH7Gxd4O3#fd?Uk%1uq7*7DWMPhFN literal 0 HcmV?d00001 diff --git a/data/parquet-testing/timetz-nanos.parquet b/data/parquet-testing/timetz-nanos.parquet new file mode 100644 index 0000000000000000000000000000000000000000..b5020d3d5cb5a87f69c61511cb6119bb0175c444 GIT binary patch literal 1004 zcmcgrO>War5T5s9MG;geMSa$DWmVZ=d6Aa3YNUc%iE)2u1BfOI+H_OdsYxO^iE$bt z5C`B0T~uPjvL~oma)@34#D+UC|kWi&o|FA-;C`8tga|S<<;C%GH@3lXNO+_ zzRwC!piDJiR4%2nDr;+lQEhPE1ox*10B*aIv@3*$%opcU*h*R@$mT6Q6DR%fW#BhE zC#_Q@P1n2-=11YIJGsA=w2DkfNv4q}12E<(M?B%thbyTGzsWN<&gh9}-f}1Y6is;> zq_xP*iv@5l3|ko^-go>Y2wP{plOSxgI-QjHCt-dT&ijmWE$wNUsrQFAznjI{D1pxQ z>dmn2D}x5TCx2ZP%}dY?7SX#|dxHqm8*nY#D*l^I|Gzz$*YrU+IrE#G1F&p8gVpNu z!-vDQ=yQ3WWxatU6;>oq5C`Zra2K(GTWJbC5Ahi%w-EQ)QarX4vFp`FIGx<)q7?3w zcNiQNNnH*R*XZ_|^>#V(kE(BvR?E@xYSa&?7uBaewMid3xQ)XnE9g}ie~efskV{Yp zwk(zXls}Q@Al0nWb9>&K)590-T6?z}L=WQQVU|b_xZWPmIT9}&3O6@F7h*qo)ep}W l>v6p3CrNiucpWCaR<~1FDJ?B8En7t!fG&vW=Q*JN{0I38&^`bF literal 0 HcmV?d00001 diff --git a/data/storage/bc_0102.db.gz b/data/storage/bc_0102.db.gz new file mode 100644 index 0000000000000000000000000000000000000000..c8060dad234040ae8420c76a4d4549b749bfd1e4 GIT binary patch literal 654 zcmb2|=HU3TB`uAKIVm~bz|g=*FC~fL?H$ML%Lx+fAIwXewKyJm3fS=SD=A9`uTXd7 zZ~FY=U~|tcwamoqqiwNYrB}!wIlQm+=w|_zkJ%O7k(bxpioEH1P57ru%AZLyum3`DyC)pLy$}OTHib`7$kg(j1Y+ zk%nH*yFJuh=NyUl{a?HzWY4YHZB>U1*0P14HsVjbpc5i9{odKobcrdcVvF{?+qDyD zvBCBee?x2fHfj0oxAnWR*3pz}v)75$GIrVbHBY}hnK5zy|BpwH7PDO4qIG!w!#OW& z3>VA_<+r<6@hK_&_*|xQ+q3l;8UDP#aOscb&Q8&b^0OP?-V9q<>k#o%IBK2#e)b2? WyDEXUj6ksZ4--?;9zg~J76t&g@X|j3 literal 0 HcmV?d00001 diff --git a/data/storage/german_collation.db.gz b/data/storage/german_collation.db.gz new file mode 100644 index 0000000000000000000000000000000000000000..c9fcf3e1f285d9a6c1b2dbe040faacdecaf11228 GIT binary patch literal 1020 zcmb2|=HNKA-zANSIX$%~H!&|hIX@>Su_QA;PcJ2j;q9&c*};x73?Hgr@+N(N z3lduCG}lF2a837v1rH{e>1QhVF5#5jb*0|HwV?D1|AmE{FD(r%6xhx2=+UD$kHX%o z9?QsdT<8^TCtq~Zy!?3i4);$#?(IFx?|$A_H+H{q?dMNhyC0s{5moDI?cBV(PyD=i z*VL6KUtLLI0D^Cg+vDx+l1qK|5kjK zm!BJYIAg8(t6xBi4#Y`Z`MdF(+}bqP>acn0pAES-X02}v=nk#j7c$RRy6~SH&-F0t z(}p#olddaP3V&+0+BZL0_4LHwy2l?(Y_iZ@`6u<)yMG5W%&YUcA6@)$HQLyC-Ti|l z*M&aB^F}uPO|0K|wY0K-uRfr+=U2*7lE|*Y~j`M|q=ccdpL1k2m~|PV1d|EzJ6JX3czG r>7`+dHwEOGZQl1ZNc$|?sg3uum_}YuA$)w`;Ro57`WfFC3^*77{)Pu5 literal 0 HcmV?d00001 diff --git a/data/storage/huggingface_index.db.gz b/data/storage/huggingface_index.db.gz new file mode 100644 index 0000000000000000000000000000000000000000..8ed8595dfaa4c4f7d3cfcd1777b92508d024749d GIT binary patch literal 53218 zcmeGDWmg`!*Y9~m_bXL zD}-=I)3DpcQnS<8-HTpydU;ttu_Rq^ZoR!6aa#YIVJ`1E6yDGCqbC)z-!FKM3N0gU zy%^l@o2j%L`X`#%@Dj!ol+Q>0oSaK@hWP?g@n=YtFIBJ9{NG0)jPFr38f(Dg!aeNk zVh{@omp@9ESkyu0|KoQw-y9hNtrs|~n~{P{-tHc)u8;0b{(m7ftKNKHdV8LdynN^rj;X3f1lcnBdnbN{URBd^2Th^m>aFnU3=O-hZnnw zVV%l)%ozRH#jnj{E5rPH+#MLOepsErDHR~L!eS7Ks_#3hEDg4xr*Rj89r4#Rw}xC1;=9+x>&M z^?s%j|4DS4%RF{poQ7fVGW38)I0HP0aE8C>HZaoTXq*)MU1R#Xc-Ef!ZKJzW^7QP= z_y-R!##+zDw_C-C9NCdmpzF>|wIZBu-v_au*S%k)>-cR-XSZ_yL<8zfw(f_W_aZlM zuC?1dJ!e3xl^ursf2!N*`*UI_`1!Q^sn4H~#w4k;sW)FAAB2M}2m4+pIxdKu+m)EG z@>BZ;7`&V(4`UvDm&leFla!~Y%PHcGEOBxQfo|(wBZKFikKQs*gmr{0J$8KO20&nQ zHE!)SEMeVah}X9KLn9i260YGe#;ewCDcSBaX3|9oV{Ho6mR$>ys956Ocm9t-s+xx` zVOvp8n+HsTIp)+l+5Wu!KLReATMa}~n_Op(M=5vuzAqb_u>kTdYVEZ1&hv~v){1sm zeynAeOLpf9yx|}}?*?XNe;n?i@|rAZUN)NVRdQ8WtPlD%4azWJ6ETUh?oz_s%rItE zzEH-pzxKRU9zAegS?8jzK8~|`d0fa-GoFcWCvBP&^ir8z;yw5KlR#5$!VttmY!h1} z;xbD-_ZwB{#6U|mr@lb}s5RMf*W}Om@Ng!fEthq2BCE#4>ufoh+iUi?m#`Rfq0n~c zsbKEOlH8EH5T5E7kbKYkWIsq-RF zB+5^v4+n*qMqVlxt5S@@F}$_T>vy+>%nFOozjg21N!qIV=4Ab&7iHBI!)(a%L&j5(6F3|Tu^b=6F+x0rgv}l$J*^fv+78{X4oO%%+mfbX~oqTi)7WJhvA&_ z3m|34Q@jyDyRZ|)UL3V_<VU7U7oVpAw+1>+r2F=Fs`}`_QDZzhVrNiLR=?vEqzCS;18A1`A)A zRM>2?((6RXJ&QcpBSGSO_H)MT^CsytPl9l;VcY~tm=u7?aHB|a?47Nz38TH|%;QeZ^@88&Yr<|x&oVqw9x)zPNOrmOZ#c)?XR-u& z5>Q@?3*=azQ+Qkt7)*LKY-6v(9hl=gQk(jyO%{HVn{vL|TQzI??7n_oIlA6t_wq)+ z^Qhj=o=sZ69tluSdv;pyd+^k|c!Y&YtKa^a4=N0%iR59Srt1mYXG}JFnXXgEM3gDg zW-<;|G12jgiy{<>8}*Hg?Fk&eHLi2y)O(GvV7_*iZHj*WrEHmY#bMvm+%@9*>nF68 zQud;Sw3RiS%_ z;+U}d@aI3Ys*~T9MCL?)=^^DNJ@~gnmxJD%sEylDz$4dhKipPiL|JC6wBlp8!77oWotgud(+@LJoqDvC?DI)Ooep_E2LJ>=%P$oOMmH7L(lqH)>*&$y2;eq zbzn>Euwg|in^a_@+pwJ{wlFn0-D7cS!K2H0p4#K2Y2L=S6JhY0C;PkU$-`o)lNzn3 z=NRI2BsNKWtN?Gv<+Vi@)!3H4Ny`m)b#rch)69X=cZ9(i&lY*XwRJDuD`+DnDO;Ct}^X) zv5*>UBHS=J|H49O(VGpKMzd`^yk6X0>9L5GHvm<5PBr+4asZ&4HnuF@lHL*?oKtR= zS~u>w?5&@PRGTMP32$Jt39JQE>*`wU&-s6fWv04M)Tev4MbSA=mSJ9=d zNWDBK$Sqm6k~6*M8E}hMx9ZqgU@F+1hPSFRX!}BfnndFcpu+s)tDp%yPf9~zy||{5 zY{-@0<3(lunJ^b`r{?pfecj(Wpz&OLc5wF~z{$M0;eT%6-PXjyr9Nq} zRv7b=lXTG9*HUN`;aN3F{AXYWiC6g_ULNx@Qygq4a!{m~#1twCGX49d>DHvMz$*Ct zdc+fdyd<&kU2y6QsgpqM_ugPFrXIW2rI%%M{}#vOtpDb9Ep?#t!{Sb}Kr_?X#KB4X z`mUfc%_1tNb}V>tHqC3x740Ie4Lnr#WeZA=Yqs5c>s~DO7@QDjCapD3ZN0U2 zX+}zG%`b>wD#fwVHJVI*{84zQ4}iW5g)E?aH;FCUi@% zk)^h|+^!)`VC%cTk$%H&5A%udO~>HLoV!h-1QLnB4DTQIBkv+q`u|=eaZstVYQ>YY(WR7(7XxJShb*lfIy#)2QQnRXI#8Ln znb)cW$F^4eCbKqRZTke6es+!kZt?WiAEo5QG44DZtNp1n9RxC6_HaIk+#r5+GU_uf z2o>ZH=XHfTNIBaWReRxEFlzpC8>G4)I1T;ZB{)#hygtpD<-~M(E|Wasy`}=?nA1?H z$NiG~S+ES;2g+#dSsR;xZFHM!w8FaOmP;#CBB!;QODkoA*`M__L8EPvd2<>RqR=$7ThC1UcEvbXsd3a%}i0yC#OVFE*@^r`T z_h|6ETETI%6FWyk8M1$diktP~7b=C)pN6X};NH@F#hh)DI`vj8KeMqLUTz zQ+C!@uO(TW5uMsUNbRpZ#Y3@UTIXO5-%pC9M(M_B^|?;kcT5rYE1nFw>;K(~)83?w zIoETK$O@R@?|dMV44HhP8ADXpUmCRyP(m*Fy*7_+Z(f$(s#Apm&-3c$Xo>Rn*K7^? z48d_!Mwzdi-S0#oF<*uIyLGa_A6#u8ABo(v3ePOrdxO@Nrp1_oVSKm^=t=oCI@JqI zk6Y&(djB(Xqv4rbRuUwxTmIm-13r0S+WCY!)0pQgl}qK#-rJynx{}xD+E=78>b}Py ziMg$|my7w|{V>@w-ChMF3T4M{O!UtBTpqOx->%E*x*yh%4Rl%g4VOCMyqlsNjKqQ; ziG=&THj1o3*H2j_>Ps1Oo+hu$zxn)H4#3&O>IZp^5B;9Yi~VVO-q+`j8BRX%BF(A( z)r`!FnxHrvf=W$y9sldZe7=S!YG@6}TD(18em70r>C$h*kd+z3H z5USs-8BUH@&joQZn=vO3eDRYr?ky+rKj^ekpIlO zvpFOq2&}sNe$nONTSXcAVUq$GkSC(5Lhw@hD0xm9i z#eL&wtKU%8d`UO`+3nPjDU8jnnTDWLWlSp&HW*=_(!Npa7{s&}hkraKBFwbqrS$5N z(>~^BoY7b}hn}lVi;V~nw`6_Gw4UVFTNJOJvtnv%hpOHa!ULIivIi|v zR~&}BU#)?k=ZUjg%_GeTDrbK&jMFJ(krI|3P}h84-OL^3%b3e+G5-pI$1&O1(eb$W zyH2$AJ2nTEvTA9(f9pOTEA)JI%t>n(|JzCQKT1HWs()9MN3cY+mHqUdm84p7tJRi+ z_Wd>r(I(NR!|)9yqE0dMmEUB0T0Vizty~TWK22$6|8$+f1eBvFU@hp`^(vQHo5i%J zKL=W>;WoU=wqNZq`$3PiKOt^-)e#_}r9Dn>aCVc;n74TtX>|RMdqbd6x^^U~TiK|5 zgs>I0d1hTheNqhPq~~WSgy7*kjb-N_k4h;rgYr?%Q2#xwfC0O4l1*{z8vd4Y81UO|G=>-gL++5faR z_Y4|#`vi=ZO}R)wwI**N^)_*=pM@3M^WPsRXwUsz59CeqGm^7&kyk2LekGX4Zf6?R{iNTA_w2F-|BUnJTz6&9fmVA;>a44sgUTVW32!|)@i-!1inZ$j z-%ZE#SL)Ran73WC=->^%yTfNE*M0L#+U)&vd^Ywg-u=*?=q`!y%IRpV-)xx9WQ z2fU<6f!(P66cX1jI(0D;<=&cVWMspy($x7qM}SihJ4%ebi<@R{CRW_sm3%rPs+8qA_JyUS{SeFHlk6yJ`KuaJGF>+bKAUDmybXF7mw z`uPCz-D<^YMcRL(D35i9UE@k&+IR_YUiPbdD6GW>rK5O-UVKU8uK%F%oEt4? zbXZn5*=_7eRJLD>Yq=ubK=<}mkO(;+Y?iLG+$0ySohy;v2JDv68`sT><4Bd;qE?TX z@;}k6WTI1Z!t=}&Jjw2#UcB7_E&icI*-i2GHfrf{Jbx|*HvBH8ZrZQ@HSIGynD_M; zz-Ild^yV^dZy8xblILxqKU4hG{vxsz7bxNEb3+Bs>%^$j_p3@>4t{2RYsJiQNe4b# zU~`5qe$$bfYB|vsR-o0dp<1N2PAhV2-vhU{HiOQdyY#HKmd@FDebCD2+jU)=d#TZ- z@+*s9UK~!GX)(9*vaCc1E=lO)60cJV?@LP|f2~$;S~z!r#8a2iR1S|KRC zi>W_FXG<8kOGiVq`UsYy4>$mlEQR)W_8c;<-X2JIFp?U%eM3KX%0SfqNf&()Rc&BKQLy2ri;^?8B z2@wo@I0wU-Kpw+SIs;lj=ygP|!Iw+6XT-c;j-pVY-JcmeIj)uWNWJnlwRan|#C_X&g;e8;^`iJ%b zk_K$j5R*YWZ`eTiivfXqEPv#n(2Iesn18sB;z9UO1_L(Bgq~lGAXURd4LJg06Qcnd z$Wc&pU~a&M9iLbttGD4gP|m|6w_S8U&JNl^kc7J#@xBw}z7Xeazfb>0>%~QvVJ1wG z9Z=Q=sPm>q-=OqvqB*PauSp3rtv5`U;(y2kj6cFCb|65!yKg9RWp4;^WMd2ck&4tUb9W2Ue|@cj{6 z1KF1>&mTpC>$me8AQ{3k!T*#!WP^`}Wr}%<@-$2iY1iOga^&|cS8ZcwpuH0tso|$| z2o_1!VcLgCAdU6`Z7{h3Dlb$Ef+48>@OB6!;qN*9QQy8g5AuHH`r?fLVb~OD8FO?P zW*NaV6x6_aiUvQ7%!g?;gun)G#)ikCic&rR1u0>q0sz4fjdz%J+vz`g0`Lo=FoLDL zaW=ntZA;wai$n&An||g&c`^MI8{yJ`atb9H4r&lp3@zT~`y@fEt_oc~bOc1rfyWz6 z1#&}(V6Ya5#uO^Et^!kP`_NInpv3zGt}KNCBJ8GzrrchLM2yC#JDlJGx-ZbPPX_k?}nJ4y}k_%Oo& zNT-|ute2t7hPWU_{DQxe5XSTyLQAmkkb}uTqkSK8)kR<(V7!FuL3!`D*-PGg zT7R^W&?qwGutGM>wg`jZwnFNoI=nnXncup7ei4%J>Fb>NYHl>y6n z!x@L^Y`0(H`hUnD!n;(_MccsFy^HwBhRqZCi;a|KfJGJcX}AywLySZ#j(s4GSOw7% z0j4mdZS{A)C4#^JDQyTEQnyGvu!lGFW-uD$Jp2$~N&x8s=pZl{q{Bz+9w22SK>d2e zhNT?#iRv?SE08ef<}pdPWM##<2c_^a5aWfHQ}P z$w$wy4S@498fq{BcDRtMKm&y2?zaDv%S8#$r)%8DVf1$>dM|(c7Y2e{10o23Tsa@!sZtBb@g7I2 z0Ux4DVCfE$^Uz4J&Lx)+TKzE5C8_@>G6*wy-NW_4z8%~%{(&upsBRcUb)R8q1}z}W zv`xo{3pw3#LNFm83PiiNp*oQ3!m79RAw>)o+%|?NZ>04$>^nPM48dQr`@=$7m%IaZ z7xxeJ3xE?JWo@91?W1RSuc-;&2h?y%0Pa*U-4AkTpNio8L4yDF+yBJioe%!Q_&Yq` zQxE$;O~HnA?m&N`0f8fQ%FqXVIEW_TBdra={2$KagR&YTZYY4lObBM$14C%$aF7~8 zR-x~jiHJ6cb;;H9p?*-X0reFo2trkYbcAxo5+=(K{>5d(Z3~TRKzhb58{pzYv>J>; zk3jrS5+GHcaVZ?FJHv zV2bf8hT8)9h>y%C z+CZ#5Na&5TIOO*Zs#nx4aUe1eBD5(RawG>n{Mv9`13ZMvzq?#8?_F1FR+t%!5XoCM z9Vv$IThyphWzJHc?saw9ud{;urRXw|rOqtq^u)F`!t^u&Hv<%Qm|BL=TjdlNTSO%3JC?V<0Wf# zdxmDpi?n$TOXk&-vy}I99LAOTTL}brARZ6R8RY}475||LeYe_g$*pESbqTXBu8fHd z)ip3W+v1hFS$u9~-aOOv=01T`cDQQa^j0cxre$($#v6;sI}xwqG{bVdN27EL4XIM} zb=rR*Snr1vN>Uh+$cGil$ze4nrqGB31Sjq^W>b|Cl{P$%GSxLXkdxAY3ZldIfp9w} zxlKu#F#Y=cf<$u3*`4kTd94(->KV~in1!n_YR%)6b@|AaXNt@tSSr>Mpacy72);l0 zifRG03ht2<&Qhjv;N4@2&sAQz(i9+?KG2|AgR!WDxHPbDVy!VL3hN(Oe0qe*Et3`FIfagQ6YCf%FYZh;9Mi{v zkrp(A-#o5aqJb}66}^`{qQ&ErSJ%Q!f2>P)0<=8EF#yi(DY1l->w(?*(v|hEy}SS?&T^1gTfTU8pKfk6>W2CZrjfaQk(>mwN6RL#MIpxEn*D7=P zu=rCUGmkPv$O+l5|PRR3$={qk8@_bVP0RsWl|g()NwwLJCEg614+;Zn{yF zxTfXJdWPb0mE8nY!Z@lSs-vS&yKd%s45+E%cG;Szp9Eb$mxZ6mN2)8gLhcPazkhtA z_v%aDt&}&o<`@~FZ#h=gu34Sf(W!DXP8c}7F7)Pd6jG*1nbgvNz2aLAptCOL@Szo_ z$^i;#JC=_N(>n6=yd{63z(`Ip%cc?n$Sr^-SnknX3X>{V{s{G?o-M13s^j*t~zn zkX@Wv0mKTbi={=L+LTdH_D$ecPnnJ%*;OTYQSl2c@$@O%5tZu3o$>KMQQ0Z#*PWT_ zSh$PCEKSf}gA5%xa+J5VDg<1znZ8F8M9+R6@G<8tq0e+7j%K12p^mwsk!r!`Td%>H zrDglX82^UCUzP<(x@XRw7--y~og)yG3A8-vrSZW`YWo5fcBQBLvE zt=bk;f?XQUeuQz;S{g6sXUAf<8gJ*HK-HWDgU;Qf*ouvFp2(Rb&zO>swZA?0LvYM3 zwY4)^b#y`sDBeVFD|1+OBS}5)A(3p+PLOw;lC%^32sHl+B z>Vl_ z5~4i|!x`DomcByX@s!mFlV%8x!Cpf)M{jw~2wVE}(^VgvDLvuf^B96He9^*likl*1 z1oxQ37+XZ5Cj;VG>Rs-*t~f`?#tagh02wvg9@o}N_bQ%D*>c8G=8+H= z&G<^!ZhBDlL0xM%WGS;C#_Art0OvO(0$brJ#%9QrmaTH!`z z4LJ0$GLQ6V~#_j*${zeg8^IC2^7L>L0n0iU}pQgI;r_l5_lo)t^=fM#n63 z5sAIEvKW8*RZs0v@0L1&i5QrZBywWAzeRPtc_}Lh_vSwrWsOGRH1pfZt zR6EJ(j)jtEa>{hclL}km_`eLxOL|9hU38hS2YvX?RgU~w9JIo!?vqfc+3@CQ9Rusq zva+TQ+;IK^h@)8kDQKHTpAx8)?;<=ynXqfg=(oWr>B~M_hHwnkl%m=G`ZXO{x;2?v z5{a!qsAF}SWEWq)JMXT!qrDo|rrAt)JO2Ajmd80+5EPr5V5N@9!b5we&61y-r$5TI zoP$1_Cp(Xl7+9EMvG|v;h)c+U9hRXqf5xihh|7ru(7iz~@JP?jP(wI&AP}Adl9cH( z!DTM=7Vu3lO#dNW(sWq*giWFLd&ga#DL4_n7^yog0ttw7bDblIHv|Ob5FSa6%+1Xa zBu8bGrIOO%fKV zvEsf%Lg1JkWVMRBYqp#?!N$v~mW~y+GbcP1nQOQ9SAk!JPHZj~EBP3kWAh6kcV$RY zv@FyO1|A8@ucWY&dKGdvr$#Y-j>q9vIa}cp`uf5zbRW9)tGJ)EBYP?`mFsoZeh}us zD9Y!uW`xPMJ9Gb*2qxS-SrhY<_{R$zXkuPR~6Tx5y6$=14iTvcKSMp)0v zn<&(vK+DB+cK0s$sH^||H$R%YYF3CUj6jcVr->6lenjx2RE|2X(w~EgB*6}uLY~Ox zu!J)kZ%dM&>iQSr7)TQs#%2FkbC{ho!ZIJ9a=GDI)qGUftylGttFoeH&^;1?(x*}^ z%*oZpJ2r8Nuk2i~jXfX-)&pLYsLXI^kLJwjlR0|;m%gforCVD|S-cT-riAELTh+rt z8XzJTaZ1i%iZN2O)X;wFON+FSw7&1N6thge6h8BeM1H$OYJ zTxHAp15ku%gMy(M+3x6Tf>6Zxo->Dxha6DY&O7H{EdJrtrD2WcdYBTU7>~s<^UyNd z)4c3F)h~&*jbCzY6GY?tC4C)~j$V8UMK&5kf0M4H)irFBO3TU8XN+Pc*J4#bjj={b z=jb~6q~$!6#RZBXG*srJ20Mj~gZ>oqw3Jkf)?M2iVW|gSo6-_9+^;!C2__S$HN*&{ z@%3b9qrotF@cqh0KjztwmB;zuyh00q1+;OV*M#4T&8dRfYS=nW<&1F9WOL@t(o4Rd z&83%Ok#M`=D|7t-M#|HiS@V#uI5B+%NHP!t&}jo;eK90+@^mXO-|zsZdZ7=$B$`V7 zG|AiIKE^0TT709d>&PPgzU(wpgqG1VG`H|wJF~5m&|0pVoi#sATUWY)%jc-(IcJ)E zHAdapcIQU7IHiU9HqII62&hXVn6z_oU8!3kzs{E{@AAcr=gM2$7k5Wm5vA~@Xq^Bt zdmt9WE$M+kpWJy{$!X$CDrp^ZW!zX%eJW0Se)Ny2Z!9zs%nOufl1f3*g!#%{$%eWN zJV~F*Z@pwvVTdf@keyR_RsiK=mq(SdF(NdnOD4TKY=lx9 zF*)^7qRve1qBPI=Vh#?dPvDsSWXwrgj(7_j9!Udqj^c0L@iTD`%GH#(lI?tqBWm!kcY#5igh}jxu$(b!894))lic#_=>e1k+UTBK*e0AS+++)D!82BsXq-ch<(%SX+(Rx3${6{f z>x=I$YxC?-9~zvjyq!>-BaoOT?O10I<`B%xu-7s`u>DJ73;Rb)H4G#3ATIknLy^Vo zqh580y-#x?08W7e`Y;1QEk-D{QZaLJaXXaBs&U5xWA{D>={RKl_Z=@6vJ*-IX|1Wb@ipU+*(FQjh9PVq`lWdt`Gi$_!E ze3!oq_M9g_!2~#CAHZpEf)?Z{Ev;Gzkj78rv$52?)CH18t2OHFOWFZddacx>4(A*h zgM=t1n`wh-u_PnOe&-vSA8e5@+q`S_V@(+1rnJI-z|;_CR?#F|I+y@JAE;KB&p_k; zD)KajMV?G70SlT;%wD)PS%`uTf}0s?S&@(Rh2HC2p=t!S;}+VQ6jo(7W(2-F5AMKX<_{e6*-EQcGv95>;}psQGxA7D%zGS4uiD8oo47-9cAVjS ztq?OX%XTsrW%My0AIh*2ldN8;M#+4Z5YS0DKJV=F!;au@rV-e6!E>-j-lRq3d5(dW zX>+kD5;<^=e$(`#7M=u=%-`>oD3EgO?za5CYauw3PxFIw{56nh;z~3YJ6Al%HRrqg z(~?vluEUsgWtp(H$)&n6AvaDlDqSIJ*1RU0Jb+`TU2%5vb{ltrmy%O(t}li&xo1S} zN=YESjJeR+Mr#ttm{dCww-~Xn4Km8 z>&4PA0sW!g|u32q(ou6)xS@%8V#*F225Jg2c`oT%)X6k0*j5fvwfjmOvG(bm zJS_NWAg-)05g*A36B(=L7r3aAt4o)@IVT@Agb|!rmaL`8O``nb`jr9~nWZgSV<{VV zQ8UCdg{+ur`%uMXa6Qu4idC%9>8;zVin(7q$mxmFuMr9<2<^Z9h(L^=@ ze*9p&l`zpXNEnrV9UH;5L^Pu$5UkRF1LOEi4D9R@0FZ&o*h(a9 zS$l%#s9RujL(FYVW`d4vXuNc$bm|3m%|cn3rqtyTSzmmCLqVKe!J;~;Abc_4GM zD#vz1x75GoO;$;=&jqm$Kd>f&8&h}ybDReYfs@;T>YgXAG%u5>x+IQo6Fs&Q(USA7 z!`$kLDw+S19?jQ9eDYH;l1SL^{4ALEr$O=;Umh< zCntk!Inm5yY>K8s;3mY&DCU$Wnu=2YD$mWWk1MLCxYlE<5OY5;xsh;y$(#3gys$8k z=_Qxg!|2CHcCCmN^I55OSvmV^i<)uLK>BOFiFit7oh?lJ-!eMYT@22tvj2ja+PkUl zVx~;fB_o^YISYx>aBx?sJim}*=`~LE?A0iuW(@o_hm^MlQzp?|(-Fih;_DroG>czVgC$a}9tV5P z>0fL*Q6!NPX0#3F&MoP~HH?y&M4qIq86B4;2Yxh8HzTVSyG$ehD&G=F}ev86Hb7w%Gk z>4J^+m9yAS|5`Gq6QpLw68^i`fH(QuEf>ChXnFT-L`*B(@#VKhkoII4PcDj@|0X1I3o+ z{5L8;NCg)?7Ey9`5injqC{Uwy<2<3#Xpj9%qS6R49L953FnIOSpt2&cNy2%xs;8r? z678Jr&B#6{Rj+>uj(~oC4bgzn_kkAYH4mby?zR^^_-Yo^eE0dcwIe`N5oUePUByV# z`%8g={e{70_ZXhX%@a{{T}Pl_0k~^K#GK=`EDgs7_wCD#h8JUOg?B=P;fc0Q!nIQv zX?P^BQmq54+e>GIf*i2Bh*~qtJv*=eOkxoQv=IJM% zZt3ca#!D}EP!op;$2s@ZzMwCev`qij{>#P^Qnw%AND8b*OC4dN>wYqiRPN|I5@S%? zjE3(9?$pp`%I3E-b-8-h%FL}3`0aZT@h4-_gx`LQsAw3E3^-YmsX*)0_S{P}5x?21 zbJyI27f0j{Zjs#^(4aM5-Yp|AAr`%ALK?E9j7-mKosEu~Jm%?rDWTPwToloR@Xl0^*2LMC>Q*%}Vb;5lRn z>~{gfj~O4yj~?x8^ZGrIzl`KP~V5JAhY){Jg}BG$>NaU zW#3(2!gny^MF2U(tU~^$m$L*7IgA|Qf(WiP6@s|3d@oQ}p#S~bBypvKxP-*<%@V@6 zED9I>ydbgndIk45I#&IH#&3a~>u_E}8$ec}KfMZj^t!P2+gjdOBA1)g*Wq_8iMN~G zlD^&-nDpTvH=iVVLYaHKqGNA18JlwNoD!oN7*9X?4P*16qlQTILiFl-lNB>E>@E-k zz6xoR-IeD5I=3!2Ib9*+!@Hq(vkjEWfE&b`61?SoLF7aB3X?xz0!F%rhm;VfySB!i zxrB8CFJiz-70w)BkO2d6gf*}#hKE9i=fv^B=H$q@RHmeSK#m+J>!B53-JNk#4C1EJ zwHxF#q97$8(fcYK-sq%vn;K24emWq=OB#szX-H=CNxm#wZ2IAR98NR{*QMV-Mo{fp`&o zE?9lgUO$ixoAlnL`|tMlOFmx4S`c_8?l&Mfz!d|C9gx4}+JesjGRq{8EeE-NAV!WH`~_sn`J`46_TGZ3@P`B9 z7XfsK!)6elS(rW8sss8w_zBGJ-L~CJN2|B;SFW`QYFb`XkN?78D(w2Bc{S6+RMxDd zxJa@8Z+&HE_}`k@9-QVRSiWQ&a;!QZuAh@?PUS|ZE9xq0)2J)` zsmRGqEVL6$9pcgSOpVBcR_?pLnON=jd-nJVSxC2;%&_-}pBJ%{Nf| zOM1*TFmBRofWY=J;uZQm&E|Yb6VE%RDDBDB8LFTpGXHTjbIX%un^rB7s#?_jy$>ve z^85$IT?{&w`I?rK8~3XWdP`}unNMq45B^li=_BP)t3B%z(}y+0Kduo(iaC7JlezXe zUE85fB}Gyj7@0j)Kt=sMQy3GNf@2QR6I_^?IW+l{Y00&%`{ItSWhs$EO^ciOn&Q;f=J>m~FHRBNCiL_^t1_>$zZZiz(ZsZt zb5c0!_S{?d5)hi45@a(zGvsr~IJ4NwPy4f1Bkg&{z_7cSPhl6$tNO+p_|gCsD?#Oo z?A_XoTVK-BLFF}riKR*L^vVxmnsNS`2UF$#d^oO4bL-oQPuKJh2^(%cnYmMY*H)co z@lz@t)!5Vqz0OWw$`0mM92{Ag=M&{7b<>~1t0#})eJqN=F?to`hubmhp%eoH)St?W zTQLvj_`7LndG~u3Y|KgS6zas&2GB7Y=MoSsLNu5d)J_6GnK=CPHx=Kqnbi~Bnt+=W z#d{JgEGqs|)3}qaZ!;kM9lW_Jsu~8On$unvnAEj6NY-sVxPShJ3feomM62CA}`nQ zr*k_WD9rdzFqqiMA_mb~rZ(-N+6$yAOU|bjuDV-xQN-C!Z2Wa+BKiLSM?kp0u5ycl z-;EKZ+{-6qH9NULkTMTmBx(s$X;~2El1fY2r(`J@PN~L8S=GijITdDUwfUa1j1QFC z7CHGyS?)sWTC=9!e5Rsuhl}rgrjoT%@X6XFH9CnEC(}76Q7fNvZ%ML4!lV>uQr3Le z$`rTpux75?N``8~@{tUsYR%JSwaJ7NmG#Xz`7n2A)0GL^aT1p6mE<#OzDf<^LvHz) z)yb5YlQ65G*vkz=-iK`9N4f7Lt2e82@=Gt<+L)S?mI-q!#MfLphPRbF=CXW4R?XzY z`AweJlqXtk%f^-2W0SUAm5Wker9=qAQYaL5I%8Jj)w=Bzp0L6erxYWou*I0i4as!fdw(W#PWyA$RC9a*|74}i#%FM7P1f1V zV!({7moi_ii1*Esr+&=hQ?GkSC@q``_%vomh#~Mv-R4sak09hdmBdx>uxayTtpp)l zx;aO}?I6jLDOn{R;wV|XAs;k*;(E>F?m6$Fcew*URu;ax53tDnc+*K0V>I8~Tdm|l zB%78M+Y$4CSX?%EUqfLWIUjlV`K7VB5Pkk0tEn%rDyoKG%pyj##@KDVS`zSQRq z%Zz$?VQ(+&(`-JtU;TWr7xwqU0bV%J3kP}OCSEw$3x{~&P%j+jg`0ZeW?oo7Pd&m5 zH}}FV>LxGNF@H{U(-wQAB!VA4{u@_$Cg%^9_ zC0=-`7hdLtmwVwAUU+3Qd!OptxPI-w)t~)O`>~&Fpr2~XAMM-B-<;m8of+B8f41c} zoBO}!er`%LKXz~@{ng>k{7+kcr@24rsvl`y?>nl8mo=+@7d5Ld`?uk*r#17#o%O%7 zy69h{{~`bQpZ14mwBhGE>)+b)YnM0kW3qrMVE!w@N4cR{Ze#v)zt#WU7@B2QW>0sk zzu_G2(e+{d_QtcxmSDrN^;?S?u3LC6f0NI`bIP}%IjZRu0u9F&#?xPr%Eq(?z4X?n zC1{Q)^7afCQ)>x!kldqdyM6rqwov^@YU8PY|=2EYwyHSyW<;oHtE^Y zq8FpLIC{QxCl3;w#^b-nRSBJ!kxU-RpNJitjpca%J!L5BlBEKNjCx{cNx8dw+1u z3v>Q>-__r*vG&_{)7N`X-}&zO=T~mO<8g0%ck!gs6ApFmxn#s=Rq@B~+d5sl_WsTP z{^;+X`23m+Px<5hv;Y0w*+2bc-uU@LFMY4u9+OrKd~oqudyE-1_0pA7qSKcxn)SDJ z17Cmmxf7px<z{x2*Nyt}`W{oq z?K@=C8CTT4cH@9&Z{L59p0Cy{dEFYf^L6JQ`Q{N<{p-v-j`-=8v+n2=B4UmtYq()n9|8rk}$E1&%G%!%`#ni?7Q z^zT;gwbg{v|9NM4{eW33kN@pf7mnOE{Es)+KD+1TKbe2Xw8-H5ukiI={*%Q|JsbV| zMBme8XHA@+U*qf7YweSLt0taOJ18(>o0-4*`qc?PyJ&tiF#5{X1J3%%**(^rc-n!( z&*}T8L!RF9g4B6C4u9wC-!5DI=VYq(+s)R!y46#sex1ymGWxn_#{6lQh5h?x&wcAp zZ~Qj)(64shK2`DUTOY__{qIRFTy*swzwb8b;bkw*OYeB~o58bRUQzqirPfWyzqReI zyFGH?gv^Lb-dp$CA9sEHje~vN%9kwPJysWR*7$~TLyj`GVah+i={u4V*D;hX+dAC7z^NXh}KXFW{zsI!c3kEpn1y3Hv*GwSz=`EqH%AV>`dcFVT zTYSai2F`r`@VW)<#9`n0J&&GqZ|zf`6i@tU?c?tqb^4IC*LOQ3GTAxqy^JdanlEf3|(2abi(4v&sTiDV6!!MMz&u%|B14fPapixIp^=O zc2T#|mruW-w!G-4AIaD#9JTGplJccPHo11`6^jlT+4HD}XAZo&?!IwH zhI-Ce99aE!)v~R(-M;&@+XI6>{X_A#pH3|rG4S*u_tYKU$6T#^@LfxbUtRG28M8kM z40)im+wE%)?lZ5VX!DxK&fazT4gC_IFBniXwm7L zzF9YM_cb^4JMDm{H~sVvCHwAlW9d01!Oi-9an4se2dwkwoKaTgE16PyW4}b*(;ti) z*<=4Rru9F)?wKtHU3AvE6`%A!bLR1*HeFV7vbA8qp-ZQ1wb$gH2c5DmW50IBxOMr3 zhep>8y5;j*wx0Awk7?(v%UpGPaNIuq&wcim6$5X-@|pL?f6?RQcfy;TeaVz{$G+e5 z_@(;{e(;=qw|j5Pg)>jtf0KJ}e|Fn#7eBnu($Ku6*Pr>s8LupQdfp9vA1`@s!jqRQ z+C8%_v*p?|2iD!NXzQ!D>vzTNPp>;;^2FJtHx2#O(jgQ3KGge<&&^->vm?&h>BcY4 zoAu26VXG!RH*vrFAAWQ9n}$7C*KOcmjynJ814qrfJM-+Mp<^$YTX*{K*Gl)F^ynAo zXXiY<+3R)3?DFx_(<>7<4Saj?8M_QV=HWMvefq@TeDv)5(`NL^54vg7{G7A5etTKp z(GL_2e79`7-QV8ryo?jsbnS%hJKs0&;b)gD81d}w`|ZB{`&Z=F_S)jKt%KWqIr+kq zN@q;{S4pt^psz2OvN*KG`R8;Ww(`9pHP3`L|8CAldw=I&eA@Bhc_%+|_MWSk_B(m) zHY4vUnKHWPE2U>_`^+_&2`kHoXG<3ZqdW8r9WZjGumAjQQ#`ee`bd> z=S&^8`nSg)STkn8=w(BOZ5z0F;pe+d89Dj+skaY;pXzalec*^2zr6I>i+o?CG(0A;@XZlCBd1~cBN4@ma zfV;o@OJ?T#=l1w+=gaP@vK~D8hSlq4?lbt_1O71nre#BB^&Q(|;Ft@B9@pcnnRkTy z9(u}|^P*pzJL|qXc0Ky)Ew?;k>lfC2H{kMRbipwuw+iUxiUwPsE&qmFE;=Iw@U$uC@6Q=*G zc%^?j$WPfFL5sFDR>^prYcqfVeBl zE}MwBAj&Av03p&Us|#%wE@?(K^$;H~YbcXFpox$v)U77@j?8M*EY+FCL6M)NH}N?VT#_ zx!|tDjjve$QvFN!7Pkm@2bt`6$nW{S^_0*48ul;g6RIqk_2(b9H+}xayMhxv7k%vB zTX)UIyEfc%#_}!amFF~Q`)1Dc@9+D|#@#JuS8p5Hs(kqq^&ZOERcCqD-Jjm~X@l~~ zpIvp%rMGDcaZQHt}_k90IbL-fTE52(puW^;Ow{qj9%kG-}Xtx7h-mGfycBA7(E6+L9urPh? z_f7xy#paBIOZ&DNeE$90W;W>c^RaW{$DX_YhkHK{Z@q9{R?g}(-(6CE&6o2>rSE;G z%}wq&dF(VTh832GwXf4K4-|PS=XHWYUs^}t(+O>rQiS4mvcY0@JL<1x z{dNv1|E=rFx=XiT&}3kYiC~Zg+jg^m^T!)ay`D);O~5==(<&pK)9}>*TV1 zN1FC))9`q^ymOBhm1k^iFuPFiIOC3efA9R4m5l-!H?{ob!0qnRncMz6D6i@Chc}cq zPixxt9DVkfH`-p`{K4}_Kh>?I!CQBH(JpQCt4Dj!`m(5P&tXe8&3G)oPTrc&eoMP+ z^v|E=J<{dvqel;~YQE}@{FBoM%^4fbnQ^e9P4hXsFMBxm(hK7y3)gJ@+?}!Y{!xcB zZn|jB+jHxk@lf`jqkY}ix0$&t{LlsO?HHd`cIK?x-+kz_6L$>A?OHr8TKaI0@T`8@ zt~nHWbnT06ChzEeU9)C)Z~pw!i`ts~PY!I>se1F84m-7Lm$mLUJ?Da1{g(E-wlHUT z)`O*8(%+n3P`GUK(YxQxc&GQ8yz7eh-_!I&i^9K`HyTyJDqQlx@O3x!cw+p8=~v-zeeE6```xZla~jWId&_fAw1{oK z{^{N$o^878iFz50#~fHN;;DIkpD~B+9{uamJ|m_WZNjCU@;{t7;&~W!R{O6PmL`fbKi#jJ#OFf(x8?@^aF!G{IOna zO=I`R%ch^V`AXL~cZbRIM;!_exNL50)$Z}%Pe1U=(V1u+HuK&+@{OYl*Uf6HP5AZ0 zL0gJ0TkGmQ!S(%(qc*v;&Nm+Xx;*RarRPuZWjFZ2b=Hudm!5`Av$EUDe>Cx3`|E{o zO?ZC&g+Dj(ooqDfVEFKi2M+G87%=AgeKRUwoT~So|8u^%^Y%pxS6=XD!-6flKDpzO zXCLZ#yxw(rw>5m`=!~g#j)yL4?`?7X%pPYve49D=mE3OCgO-fWKie4k^^!V`_N}|< z>bvUytKkQ)fi-(?L$|AG#;DipJ#yBX?57zUQ4sSi+&Kq;4ows*V-SZzG_Ry|(AKm}vW80TLKJ3g9 zuBY2A3`g_6+VWwYsbF<>dep!3twz0bp5C_U%zoqEe`~?S?5v; z@5G$NY40sh@bds_Ww&@7R^&+T6U|Z};4>;F>3k zmwnZI$j2wv>>4|8_zQh5e04;JKV83S;)tK`9R9d(+9PMYdgq8un->0Qlrd~n=DdqC zCcXFM`;#x9@>~;NR^Gwg^FCa+XwxyH)A>zyA6vM7OFQ@E`CsS%WypC~Eqim1FXvB7 zC!{TYY}?LbzAn8!YV>%E2cMW`o>lTt>-V4XJ-7PeV55`!KRj~cXuT#wHr2gwXX9Nb z7F;kxKc~*gu44`^?>y$)i}$uMe!b}6)_(u9cG?R$C8Ne3+}`i`rw{IqJ@wAUulpSC zS>5ElSc{4k^&eULV$O?0&iG|ii?1iV(DLjLc2^snF8Z!(`c*xO>-C#k^3ivX4QuTi z*1qFT5SU%J=e~8pxzXsiO-_`3-@4wx##7#ZXndO;RU5uChEAC|b+7yRb{oDpGVO&a zOEw=pT6D)1rRSd8;15AK{=TQ>tUlpsH?28#=$H44 zul-?7sL`D72mLbmjGjHKw+|oi%A5@+KEG~zL7!Wz=a;s5waZ6~!mFB=j5_p>lSl9R z&75)TuU}vC&trY_wr?uB{rU&bJUMn%mxl&^d;9(0%^BH!-Q7or=##Hn{$>-;sJu2G z?i-)~@PNyA6W)6(7^KhT@j_2}Bxm+ie` z_O6PfUGB)M|L|aa@{aI>V;9}=(8MRVjxSxl@b&sHw7jwVgW>f*HvV)(q;J+=_H`Tj zaM`Gb?|5l+VV5Ep+4!z!_3bpG%blIpwrqF&*_Qi{&Fns-$*7GdpKIBtzPr=ISG6~r z?9AHVeE;}6^B+FH`GspYUi_5q+c9cm-93ctP`}e>t+N{?2QnPxz;p9~^zW>CS?IC&I@1mY0poFF4uesReDi7QS)$&UWv> zew*{kyB#vuWKFsG(Sgej4ZZA9*CX?$nJ?kjp7E_J^u0I!{wL1wa7}#KmM|H+rjvj-fWF=6B2`Xy`2k52H_Jx|kG zb^iXZ9glzZ{&Np5eDbp1y&KGZ=lvDO_cS~^Z)(H+kH7!IhmBW<`!20tbf@dyiHGk7 z)z+Zr?Zs#BdG4vnEB-Y0%ZX3F+TxA6+ur_q-0@xOj3cqpyPr8Q{@1Ub*)mygb4%O) z8^=C>;I$JKPu~O+)o0(j4JU_h`2P6d`0?Ezk6ByQ=<}JOTMvvG|J_$rm)!c!->&Vx z<>Qkt-?QP@CtGfH7d0I=^|r<%$KG}0!TXA`RxaLf?B>5!zqkA28UK88O^d^IrySol z9%BsN2~%I+v2pxA@4x%?Z}w#0a-R0d+6FsbJ@(ntQ?A>7!-@LGUMrX~=*Cw@d{S>) z)oUyCP@jXl$DiEWq|Fa~T~mfmnEtO1Cw1T8%FNyF>b5uHTJykh_n_s6pIiOn%q|^H z_%n|ghmKx;Bs@0fjvMBVx!~xX--pKzm_2#-<^wbCTz~nF4o}@Mxc8w?TOSzT@Y+MK z?s~sYyNp&18f1O+>N#&r?Koh<_>;~4e57gR%dbVj5IneAC9Pc z`TWYlSa9~1(S4p>w`cBC(Mx;kU-c{R*)KCI_HeIN8@wZX4ZNw@>h-%DAAfe=Sx4PN zD%ZWU(bcnJ)g=Q6zM9@3vs1~M zf!}}p%%(*@pV=yKu+D9RyU*OVZPnPlWA1CWq&)lAYmQ`npLf>Cqu;ju#hjJ%UCGcL ze|e$V&+Goy|M){Y(^sr){EfSR-M=l}e00%e&;GI@`?~g%AK0+A{F)&h-p!sCxNX=| zBO6??WK+F+n`*9t%^l6(vZsD?M_#)fRm1DTo?qVjaL;G1oD&$3edEc2D{pxB#qA5X zPHQ>yi#9oPC-mN*_3hL~{+;Q=zG``YgSt)qpwAv2aDDwNI%{V(ao0UQGq+)|=<*eJ zAI=;2?52fVk4(ELy0i4f!!4sl;aJwNdA-sHWSAA5^SiB^P_ONhO^vfcE!^vFYyOXJ z_-@l@mtAt^++8^hp4vFRZJQ$v|Iw`b(uLoa&C2^=_^?*1+IML@@{nZwj?9Ycyw0Uc-W%GutlQHzV!Yk&OdC^l7=j{W%?qR^2cn(&Xe z!F$`%hwa+lE$i&IozAPLeQ|ltmm%D?QGR@u&F}fk!6UD2-|;|~uJvYpy`+AhwFCN9y6cT^oO|Hp{|i2;pEya$b0`gKPD(+1HPFW>d!}R%dPnSsFZh;P6MfR-C+k^;z#X zsB^A1wN5kFrdLPo+|?vJwQjq8z3X1Qb{9te+Ipte1LN=PCpM0Mrpd52-uAnv?%c7k z&TWh9nP1MB@mg`e^~=(VU+?^^)926Sr0;03=*edfoH*x=nZ1gha<3>T z82!w*ckemWwd)FS@~@cRebLJ3S@JUh>KhM)s{&%^6$YDj)r2ht9vgym2~K?lQXgP2<7l^EW>+u;1Z14F(l0Sh{0wS@+>@>??0^zJABr z{Im+~p$8hiv25Sfe|>71xyM^&rb2U%K$ZDYMTvwr{xa!U}EuEA6!9hYtsy>}`)y_5RqFEEi|8;Bnz@PSae&Vt3 zgPEg0Kk{z;g$G_5yrSyYtylfc$gV0r(r{L<9eo-d-Fx}qO&1(Lw5by;Yz(Zev7^Rb z@WD%WcWl3zetT@@fD2a+p3wCRwA8zt;XS6G)xfsYTWx&x;t`!)4VqN^{n-Q8{y6)s ztxH#W8hp{JE?h9<_-b8Vu;lQp2Y&eI=o2p&o?CJF?%xj0ssGLPw_f?qDsTH~dcEI9 zcXm~*eBfl=jI^Jcb?)YEvht2&OX_qzx%P~D{u`#4t#;LG0Z*7P{@hNjT=nYjyY>0H zE42oXZK!u=pWnhKRyNGc=+kkw_~#eqIgid6QaQLKp76~l?wi)^-SJJvRpgJWTwL16 zwffUL^71!4GHqt-PW8^+usf&K%SH8P91f4~Hm`o`T~lAlxwmf9sTKMEdcSk`dK)LT zZZK`~z{;GbXZAj$agPxVmQBnKU0?cOs~>$gOmDa3o#Wf@%kFvitywR(obl$svh!De zab!`aX|Lb>X!ybzZ$GiU-I6=+-+SN56BYe)TW2@^;l$(L?eEZk%7x4CzUA4)qrdp< z$i97RU1NKUf4RxtexDBS+W3dAjf&r?==bUBK~t8#Yiyl8x8U6V`(OI)$%`+|?0BS4 zpW7$D=)e534quKv=cgBLUp1|9!*QP<8S5)vuy-|Iu%PIkJKsH{bx!;KMK8BJ`_NsN zW^A~qf6o2wI$CtFYEQu zpeTOAoYaR1_FPd(p$rWqL7Gkd{_g%1~Y=vdHj*3%o-MzgPLylTUZ z6H8t%+MnN`@simOpEqm8i4Ko-J$wFv>PDr@{uzBF=ghy{y6DD|-rs=XHRrY=e?Qt| z#jcD;uYGdO?w1F=|HS4=XN_9XYUC>Kh{drT-N&`>boDcLp8w>@X`OHAF!-+5<}Y}1 z`tT>VP0ky&`>P8(%-nlU`TD#u#}2>u#DXoEi&}p@df~gn`$g|)Ic3$RPN4};zh3|S zwYOa}xKHNVQES6rb-wGv!m@KO9kuPNhbF(;`3$}Bq&e%`)LGZyIoGIWlUr>(adiCL zj4#aUDIW~Ee|u(wu4QMQ>v?)dpZAU3bG8h=_}5Xp7DU(2+jgk5^Pu8gSqsCz?JnQ` z&lVXwhdlqxOAq@KnFFX6xR4 zaM5$kt{yw7Lq#^_nyy*i{#euLdtPeNbnVOw_l&=2ddqRWpKp6<^MS)IYgn-L`SZVx zWClteeQnR^!)?;mA3wThQ`l-4QIfyZHGR) zc-~8si?XcM8xL*ic%a#?nP*tXpIv(XeC(rU7fk!7fNGydC3f9(0+>fbQ3e0K;;`B`~eitC1Ry4Q2PqPzY!@wG|2 zL!~WW{nPhPWxhVS1%JB_0XKR=04(HvGUvf7hkP6yz<4( z4LWc7~l+d^*9Wo9OxO2cKg2Trc{(tKoB#={ zUi5Fj1)q=M^OJyRz`pDY;L{F19pQ5odS87_-ugB8}Qi; zpO4{lO!QG>5A}uc=_Gold&8$cd`d-M^d0b70iQLZ@A)nGd?fmszlBfZdhmVtTnV2( zqBnUsd~Ogu$v4Ai7JTj(J;&?evsd&Le+-`!@cAcvT8SRvUZN*>i0A{J44*0Rxfecb z;PX6uHo|8&d=9|pOVO))R(+SNndr&QgilZS41|vdK9%s94xc%qm-ZR>?1j%q@c9Zp zzt-m-*jDiA0-rqil)$G9KGWdyD13In=L6A;`cL>Y1ffWSPj~nXgikqqs^N2+=pTIs zK3m}Prsx61zRyeH(-l6~ik{Aif`fhzd{zsd`3((O&I*Z)OhXnjtw_?18Ik_PCZ;i~ z$#9!E%rc!r@D;cL4Hi!8gUm(RNXc_#*|+VBv_(eH6Nl9% zMk52oNpKqJ{-OazT7hJHG2rUZM3Y6vPcMu_KSKp^kyaG4qQ#ovEyA_|=T}RKn?Woa zaup@~(F_=PTbLZJf6Vk6#mG-&kFwB7MAT0*3~6c()U*~#a-cZAMj#w@iUz!tRzy3a zpcG^Tp~Xr@^w$_?*ogEYjvkP2`~3=uu*ZN+p;HToSXCp!(hk>_Fk8=Hq~+0a8LwLX z5gzFq!E8KQJ^>{63x&L}#)v*?--2m(N|5g8!KVg@7-!Q|-?Z3t4j5VEIMLX0&qzN~!Z$i-xqmL~FpRB2-;!R7bTwh?T z&DI7G(lU?2vExe_BD=_dIkM5J^9WNKo+B`(3k7m?o&yiMuZ{I=A7RCe)eL78A}7P? z;fY01otG#)=Ha8VhZoo?4&D>@01D6jQE%?1XzVDksbhHa2QBs%(_C>|D_VR>XjuD42N+yy-kjN(e9$H8;XN z%E{1RI9dUrL4t-6e=8Een5?%35DaEt1h~XQ--r&>EAvm|*6`Hcw-V;Krg;M0t^ zw|bO1M-rYk7||kO9K4;uWZ&Anj;nLaI`dfJLcF8bO5_M9e$Sqw*KYd zTew}Wzky?NS2oz1UBE8w=5p2R;c~rwh08TQ2khgXF4wSLF4uY2!1KV%d9An0^?o0h z>x{nO)AR>>et^q$%^jAtG^_kZ9%cZ2;s-{o3) zkIVJNy)M_bMJ`ut3E1Pyz*k!i|Ggi^uoB*375GIDfqnfj_y()t-5-T{UgL5_z%lFc zB={0f!~CpuxvJKIzp@_e?`Pq;&%r&Pce&gzg5U8H_&YDde7y=j#A`0s_Saz@HpBC` zxLn_F2OE6{T(=A6a*xaP;+rm4`dcnn=Y25mZ-edr4t(c5nEL}R*SZf}uINWD*PuUx z%LdM1?;|c({ZC!4oWH`DK8N}H+U44G9KQDrtjD+D$9)HDdIHAyqsw*tC-7(f4(s_V zJo7i0hks)4LLKn?>bTxHqmC~N&}Ma9qt35Ga+V9mxo*L+ z;dCIXDnc4H7;A763Fv%-WR_5o4Gnff1sHg6QXtN}hQJ^ig3)UNGu_J4hJ)pZ03@0O zCWdeM=tLQYW~o~%tuT1=VVg7ltxzy2(?x=CS<67mWkV}7H0-|CD$GDf{^|hYT6WW@ z@CzkG){H}9U{);<*CetxVP#7gYD=2Oxe>h#j0U{5+`G~s zhg%iKHEN931ih7JT0OO+QWb?MG=vqwS-1kR#ipFaO7q%rXnjyXWSlpc(01d9uE>edACuUmt^NGfVnWCQ^W zFESKY74L){=^ArW!(qucB})M20tet$LxLBh#l{CI90N^qrJ;!f&k~5n^dpXnL3Ryw zyR5+oGeAzM#tv#0Eh!>8OCdo_%tv27DwfLy~1Z>%O`O5;04i+>$fPSH6(A(tp$;@Hoqb?3X$G1RmX;@PXz&159WJu+qXs#8t`6xEr@I=jMGL2HxDQaEFKLnC0>mj)Cf3Z3tPt^XSHnHpZVoGLZvbZvr&33-tM>kVarEzZk`z$rN8B<+GV8K;eKa>NjD zQs|~}7JB4>#wRKW9!+2ls0m6InzV!~7y-g!gAoVH{rR?7pYGuJ3>m{@+gkNFw^kOz zc_ZKwF~eZf^0L^I$+BMSKtZ|(8Ae!s3(p03K3)x9Lf9(&ub2inAbfm!L{PGYC-0H= zuv?xVeuHNYHyX+!!vSe&U~|V&{ituWOQW^KYsD)HP0kZQkHF!mFR(SHcmW3CYPr*%8^Bai;HPmmYG5AuN58|t4G6_76 zkh)LZBaF}X(saTM6DqwyE;_FsU51oqq*#aulBO%7Ay1v(tiU)BC=-x*WR(Jife;#} zpF*=HrQMOkWTn#oHbcw%5$vK(d;DrIRo)f%&QC)-ejLzC0wuode+{gfe3q3f$wOn zGkR)incA3IzA-LMo$TauYm$qTja>03`RGf(2$oUPDgWqkzKN33-iA;;?l~}(h5MiAae{}#e}+=pu4h7 z=82&)o@(*ByxKYqli15q$&*4ZB2+bv8F26t=btqJafIUob5ij6!sHW`4Z20?Xe8nB zj^s>u83}BaQRbX>vUsXOS{&)<#g~W(%gbBQC({{T74yWeLU|B$#?hJD6nWo1!}lu`=gc(yIvTI?oS73_V|^YGmeb10M30OGe4QdBQW zVf_fHU!=%J1(Io1=(xj39iv!eX?bvPkY*6`oiLfKs$glH>m^KK25q}8g|4zNeHO9P zXSKR|>{#)&2^xx6ZE!T`F`*QpuJ6*BuC#8NuFDC3kD>&TB_3|;7n*%h=gX;5gU}VmSESh7X(A#Z_t;W z(g*95aAQI9W~regW*E^S^L+Rm$4kJOg+RtYgJFyzF1#x&N9XL;PyDve|>xW;_oEivr{ z-h4!7zgdmNx-KonLV79t%sE`1G!lB6GGS>_1Vu-OCZ2FP1t(0g`vml(h9Gp(RKu5{ zMZzy3iK68+B9T5jLcoZ01B4q31>gtr3UtjMB6$!&8P;baRHHFllR+=ZrY4Qla=ZW; z-RhnUamb!yfrj{=d_yqsZCj47wzm@P(BzlEcPP;47(}vW?T& zlZH`2R0i-8*QJT02~@HQ0ivQ-VkhEf>I@U$dUSdkDm+H@0|CwqDZQy%lSo|Q{6vSs zov1JoeUTh%kr&amqT+lGMMc$gzym7`G%|Z?CGsu>$Rq4!Q^$?rf7~*71TkTr^uw?6m>17P z(XF96@f`?E7!7Fg{$%)Lj7uQedh8hy)(lLcQzfO+e^JT?mYih9Vj_{<_#LF?LC zo+9`=;vhEc$b_J#L>a{#EAi5Ss28&|^N^6b+Psl`n3Hafpy! zAPUZk#U>fqPFhS%144-!S!s?9!X6CN4aCf#B;*A}ZcRDCCRN|yFNl^JXNHiMVF~Gd#oK$`uyDGa6rsNvQBSJ< zX>k#hlFM*%5tML80u+FvH9}v3zlK+1kkH~`#e&jymBg4r+8h?Od>@Y?95*=Gkz5v2 z(Qui48%_w|Y+KP7(WT2Z5ynaxMvMIhrz?a7tV!}$lckX&FC;8f_6LvDH~G-1_yXa$m=Q6Q;y}f zxqiU|fu-YUJ&qQA6FTEH>CQ;{Vn6P2BW%eOV*!0fx#}8W*vnz~$znot0Sr0a#GnhY zvl^-Vu>Q#GTWQ{?#5sZBC{u20+3w$_>!Dic2{r2#zf{a)i3eYQXU6C@{n`&{1y6GLDmaJh6z( z5(s{1G@3-HO_w&a?flUbMF2o;TCTB zu4s@*51n$2SnY(RDGz5`@P{g_PuPV)jpZzJ#{S z>INB*;f=j=UELgCb(FtY>L{cH6s@n!5s`6^u>FQez)C@q=b%^vrBkHzVA41ZU$qJg zWi(G5hNO+j8JE&SO;O4!v`qyv!&Vs5%|yQSxI=T6N$Z->_}O}3gFgHb1Ra^TqVCb~9dQeI&lF+fL$s^u|) z$hpC*ExDNui-lD>3hv|tMog9+Ak4KkG3G4~$jG#xvg}mP#8Dw}klC7?$lv)4C?-N( zxi`o>2|Maw>4voSYS!#Xh=_F32qZJI+)#2_C{Y0B1INM)!xBCw3yFGNkpkDf-Utc4 z)82}}bHNNUWm=z5u^m1W>@YN2P~FQ+eU^qr3N-1Q_YZpg;z+RXLwlJ`I8?;yYR+MU z$b(Z=t_!CmXq0m{1XMI7uY%6kOr?iCTz?%9_18)hr}i;w54#{Oxr(KL0Q$^o6}Ft(Q(A&{jd~WAY_b-LOfsSl z*PmQy&Q6k)R*7tCIyyzF%u{>~=^!*D44`9&Pwxsn$Vq4w=0;i*;c}G4;53VJ(Lh0Z zKqFoP;b%}BSUd^kkHQ;ZQAwhH6|{#t7pjk1fq zqFP@`5;<_XBT5mZ#Zg~K@JeOrkYT%MwkKF&*mr@OM_?!Nfr{V%Z>+z16oxueMOX%z zhF_~RH6KFZTi0pyvxxz+N)s$my*!j6Gmfu3Jp>o z01r`(i5fJKiRAc7h*Kp!;d${ggT<$1$%#R1F#t4ryo@!VOTAnHoSNNPV19yohYY zr1`W%l{}oM_i+LNMsrd(|DR~tppp* zGATl*{0cG>lg7!mpzy?K)FM~_OF*>0uH&hQwn&goBd~O%`1mLulMxa1)ZO$G7G%*W z$C*jYO<@q(P4N=8M}^;Piu@NTBJDDvMMNn=FlhMUZ^ZHuLtCC&JGkDC+)tEe$|iEA z4WmV9`&YtU<aQh|dK)$a@ zx5zowEl>K*j_H&}1W};z{jj=(7Lq+5x-CYa`?1-@myn*t1&D^yG|7j<4wDCd;z~!c z#rTj=Wj8U{MWL`L(+bwQf?P(x2Csd)EUffLo0fGZ4Z&gw!m5Zl zqnDGmi{fG-Pab3j8BXlON4SER7*K16iCmgllR_;TmFLhB!G=F&qCjaxvgN5(7@lG9 zUcl6Gg1O5?&cfEU6hFgIXUoi#q_xXQnZ$))!S`Qbdu;}@Wc1uZumhP|anV29 zi5C5#mfY4U3QB4zb(Zf?6q;lNKmg$_SOrjdgBIprTjDGV=%iTj@8oGwSq*+Qw+I6y z_(<@9f?hgxQl%!a{fJLttV<~4E=m3`N6+Xv;G0I`sv5FpzO;t1O`T$vI?X9;m^d?H z-3==J&^1s{iRL25AZodtiM4xW6n7SeLv15u`=+*e9}ISprEF%JLua&!cLw@()lm^E z52$R7)Td*{soEY{MZ#KyqHZWa1@bKtCdO6-WRt>`SUn$(MgJQEq8o7mGsgiOL7wF6 zGdk9I0bYryc#19}T#k|?M}CjfosQJD&`8>tF5|Qe`2*j8!)>ad7f(J5bVto=((MX7 z{;g6{U1|&#Y|b()M=_n*iHx$2wOt6~L-r{7CgNION5>Ylm1KD+1p7J*HdNw{iHiQB zL|?_Sos}RRJ(w2==w1qYNS7lk@yX8bCnfGcP$?8)I@MdMTauUK9AeFH8!5jGJ^~f~ zI=}CbRaM(rCV~OA-zTZOjcTqbUZi|wQ#FIR6D5gE7d;#nc{kH(qfElCX*Nmd|8W{_ zPUW*X-C2SVpoa{vta#lt&}t*7nP( z;EH7=3@oAMhD-kJv&tERPBuIe3K#95k*utcwJmNg(v3T;L=}jF8MS9I!M!tmj=e7i z8d1r`YqT89aj40IUvzP6YWm>E9&V*8uhF`?H8FjBVZ!*F=`(w_kkuBYBQ3v2hv-#( z%6%!r#ZG*HaxxMNWWB5C@~~T1k_~*-fWxgKwC{XqXraGqe+^?T*tBSfX^D`u>u@XN z?xeNQz^mhmqfs1mc7A`T@@P>iVo`EJ6Z=u?Z;~?Vwl-!lqI?55n=EEXI-h22h9yE4<(e%-6aeLW8d^tdMOFC?+hJqrJ zsO{JnrivD?aAG4~XB=PZSdoV()0q0nFlSEI11_TpFJ#cFmBq^0at1|-t=mS#ov`hb z60^=;GAd=MO&f$|TXqQ4w%w2>i*+=ELY#a*TP4r{6I>F9_EIy5>GojKJSNRss%7;# zz&FYWe51++-$>N&Ry5`%OVaNEnV=p-77%t5?E@}Z*$OAgaetAemZ?@{7`VCaUHqAc z#ibT9l|VWNYi3~4D6d~iH5fENtn9F#TFVRCmNxg4(9OsJu&W@{phT!pJVBW*wi4vJ zInn2*?n#kkN8~rm+EF*WW{AT%G|K&Xlq?kJ3K4CZci|qy+#Vn6p)4u zmKuVgiOENNclbJ$_<6Vk#8B`t>Kqe!DrferHjnz>xo2X|s%C+6aaVW}H!xdpC z988i0PuI&tdXm%1$y2pIImfU3;973`JFP7eiA3H>M2k??VpQbAqbT!-JdB20escT9dmn*3%`KMTA8n+@n?idRXp`)fD(o#D5uufusX zJQX1=J&!4+HN;M;gyRX`tf!W)W#LqdpEEl4O8Yl_IRoLBtbgBkv%mklj+%Wbr*2Ni zDWmWFzvqFOqMgsyNGV+~>L&?FJgaaBL&c5)O9!-7CKZgp8!F6!Q;PI=i{*3_awIsg}=)7$+hj0%FHjfs`z!$^deKxLDk= zs-mJ()VJ^|GPgXZh2T9RrYGi)1vI&#qawvc_i{VivZ;H`-tTnW!m~{Bp=(yZ)<{*` zBg7d|;B^vHE~RVlrJQPQXTN%VN1K!-ipuF*mb-RSN!?6nkc6bS6%Uk!{3^>BFf0dT z0OuX?-Zh-|T75C}X9Hqjb|DYlfZ7?wcWE2>M4$dCN9PRkkalzy+wn}vCvlynr-Hst znY3~fC)f&OA#qB>m%7)Z3?YSRIL4`4AsoG6*l!x5@(6*uK)13Zzm;IdMiW;=N~o$J z!%R9>k6WUO9Kl?u@<1HZqNVi|TB6oamlLFge24@@7ssTgFl&=v0`FOD1ak5^!(W-u43?0|b%cFu-oP>CK z#T_#pZoTZMFaZjj`# zcAb_kUR@V}CZeL3a;8`!C2Ehc=SDOITROv9nGx{pDzH;4@wGjkP{b>0Bl$8^Na`ew z*!UrYEy9&ps=gmpGF`8vk56MB8+U#U99haiFM$)8o+_Ed8#6J~Xrtp|d0K?fSWR)> z`u%1(xlcmr)CergRabFdRiS}KNP+=kcT<6EhOrA@n7s^_VxI+~UO?gWeN|BeSr2lHRYJL^M|S|}f^1?5yeF!fv$3d1^BHj1 z6Ks^|zp!KqKg#upj$Zjn`ZIWkR9v5wF{08{Ix-x=E-Y?0WGs|S0|Fn_Jk&Zy0e%ak z2Cx=>wCD+q6+^6c^ANup%{Nxkap07ScoP=HIcVBgj)ifHG*Be*K(=+FS`sOySeeUC zWjwihr>B;d%jIYkn>77iA0@slssUszPfEbT(p8D(WyHB~%rXoSji&lwM;p8+mNTlUtNebu& z3`L`gu@iy}h%2ImoJvzeF{z*%A5S?lk;79umNI1^G)DInE)5)h5`p^^&=|4@)1hJU z#6(FK7#t3S6Nz`A9G(PYPyi&v3SO zK8;7@K1EG^qS;A}!swU;u(&^r3D|NY%9bVKUD|0bEK4TXV%pp_nnG-ubb`Sr#QnsT zBGbl)R+3|#V7TCol%XQ4!3?)V53&RGg{akdIeyEIStTxo9ZDCzwlLn!pff$G&P&QK zdu60v1Wy?9xs?m@Wt9B853?;+Ry#7=;`Hl&g9&qowc)r`XnTD4wo4^$UW{+ zLNV|g8J!+3jI^J4Y0gk-7Rl|32pDJK{%7FXGP{i+TmzENA zhv^hlrrQvqucVX)ITkf8P5{$M;Xg<T`H2qNt#N1r&V z!_2aHCaJ}QViOD9VnB{1C=M}Fc$^#C0$Z!l?9^#^L z)dfM%@Wmq3UxUf*`0uu;!-R8NGHr8&B$Yj}e!a}_lgEj5>ow+7_m_uY$}3cNa{(&w z6hW7Oquj!Z3XCY}kV_X<9nC)7s=#4}Nf+5!a0>0C|L(3m5C&gI)D%ZFsLIeIzgyoc zzs9JOqLAdjk6WTHiNtlW#HnnVHKE<7r_DIe?++=9P9jr{%p z&V*46A59=CEG)qKRchx_??5vX#1Op=l9>D|r*lj&w^7Y$gNw>yUi3P-0#NPR6#EoL z8*uK@FdUVb*ZJM8%3u87I~BxRz^bW?goF)rD#!3k(@wQ3J62S%New;T%fL~Pzrz3+5AWeXv@jK5^_XK z!9DQ#@Q*egpsY+z8CNUQk=RY3F8Kr&MlI#ywZ}H}pgnGZR+l(9Mr?9CL~&WzD2^14 zfz20{MYGs_n_>UDBgqA+11@Yt+yG9X*mV{XSwcz_Ht^E3(f5x?fMF_bS8|^8?o^eP z{PM5~x@6^n|2;{T9AL=9AJP$F0Kd(q+$tQM43L(e89~(QNfGAH#;3)*>=|CDa{Nl+&Hdt z=RjE~PS|o@t$SvU=8Z*EmKYpB{C5R{^k=1xbr2h)RE@SO2#2X2zzQIE6K!lpQY7W0 zfWnPn1(j9U80A7A;E2USBHW!-Bk4%uj|C+l0o?sgK_=eQ!YOydMEMNq{Ru^hSR6Eo z0#ps*7?4pyY;6(_5)~&Tel?Ab7I6|TStuw@Gbb(_>Vps-{SjSN&IgF0QN*5*)5s2% zkjaG8gfAt~jjTVmt}MXpgu@zUdJP}lP2xQeBpBgWBKMU_%3?n%O(lk2dUQr*3C>dm zcn6xt@Ec`}Es=7~!%VtqNzzRZWAdrBS73{N#;m9vn$c!oN<^SiUOq)o5;B~XA(NnP ze0~+Y7+Jg*9W;r$h(6BMDTwY$fLog;3OlC0ICxE5>xnOp|L}ea0SjW{j<6YBdvZ zbn+{n5bfopCs4(d>IGz#0&34ciMyTX*d$i9gc?RX`zU+mwzmUWq(Z^jMOK!x@_}5# z5Enm?(l;F7?1T(#2Nw+iVo4%{s`?LZQ_i-?U>V0j#e6!-NGf6ZGRyUd*AVY6Dh5j6 zuN7Kuz`)|WlY}QWs5PM890!O8pRyA)n=Bfp1j3~ zKPk?Wo`~2E#s+RBCPWaxH@cUs8yL7fUQi`Oiz9quDf0>!l3#+tkd{I>#Y~Qu4t7tJ zkBC3EBnm@YAvw!sfF%xx{G6v_boPn3AL#gpYY8hvI9`5l%H{AVg5dxW3=1L)r;#K1 z4}vy%2wjU=UYvZXz|q(Xits$c?_<>*=IB9}@*zZ%EWH4`liKcHw(*N`{C`wo;m|qI z6gKr>NdAW5`KXP;FH$Vn{*!zJl34?e3qndL*-0IRLI!3Tg{s+uNwti`?q(VSp^?H( z+(sc+laXqw5R}Wd*JxloZsD0Ils_Nbo@deojMAq#n6%YtZQ$xyfg?&>vF znu*sJF^>PxtR~VCf_IncGsSDAqr+OLM;J`q2DdS%n}yMJ|B^TPN(x$tB3{Q@qPx2cNju;5mH4c60$s@ zFxzi2rV()4xZV{h8?vMCXy@` z;;_DlnU0;b7tZ=@m^-qWXp2QtN^^yz4o^_ZLX&dRR`QmChP!*dvCQS)if`K0a7{u9cl9+JBB>oDSY$JtiNz4JM)Zq?7^OK-dF*{xu z+%^P`Wy?vX`MC0#D{h%cCow+~P>bE^4A=|*7rag3V~xK_R*LLE?H ztPZ0Z7@7hjMyIN6`6ST?7}6J&>}q0yG&YZ@p8pTpIIyM&qb}SL*uPwTD`K_s{#Fbv zM3MoNQVXFO8BWi#RIeGg(x*OJ!KnzsDwGS4!okv);C`s2uk-~HtDvb10ewJOnMrVh zA>pUcx{*L7sJ0r_p!C73zD%hRC8`>k zJ$n4#^-+1Y>39i}QzQBZWb(riz?TanbWkK_RZt)zbzT8W*{IT&m7v^BiSbDaO4Oup zrf-O1I41}@`J4&cGI6sDMS%P$5fR1PMKXy$Q@87ba{er}#Mx3WU29fh>oCuMSdY+5EpLTMW~TuR!Oq*wK14 z5VFD*=s0P4L%YhdLUCFe0=7Y&$DT;cwElpR5B@vo3vv_^&m6g~$$=6lJ%p4Ufzzp+ zX&HY+74SXIJpccJ7Nne z;#4MqA7oH7vBjE`xEOBI0N;glfdG zvfax;^x!En%di5~|l4Lw*7gMSDr2NJr zG$Wy4fEZ;~q}n9$P`Oz>oBAF5-9xaE zr`Qi53%UaJ=Y35p5~^)`Bx?dbGHgkfcfj{nb(QjvvW*N(l_2#FmVa`f(?cZBmf))3 z7Pnwh()qLw4O_u_@WXLR^Ndn$a)ooy@Yv1L;>ZL?@pR@( zfXdQwhq;jo(;u=z;R;bzZo%%eH*TtV1r6YwPEqR|iU^uIThPRq-JCu^QV2@_xk=un zHN&2jBwZJNDA!SefGp5=Mx?+>ThMb=*qix&Wr0WRjB7FT zPsw>lCxN3}KtgxND9R^F4@4~s)zC|Q?pEbG(i2p5{_s2S{J~x#QbAl;&U2_bdI73N z7P~_Y%C;xFqMmsOIWmNfHTBLBXb$@y%HyK!Nhs5dX2wZ7`+f4A{@8NjQR-MxI4!*) zk`3`I_#0ys<4Gj}+{*D**6$^~C{u@baMu!>3 zxUscOK%f#KA`zLJhC;N!Q`U*rqRvPWVt~_z1UqGWw^7M7keM9Rw-Z1z0H(&oFH6f$ zBzEYw=@uPN_!~d^ST^{JTMn9m9G${aC3;ihjyi5)lH-!kGA_}hU;%4z>B{`xj-(zR zs{*uWC`A3J)gHs|XRcFjpv|L3Y)su1qdDlMVim7QnvqxPtz?c;LLg1G?&Z4W$4pJa zn#YKTv5e_!1NIsu#ukW{DQF4~2?BKxK+$eIGEozXh$$Xdp!Frh4}(fGy^HM@)LyPk z!XXDK7@A<#{S;=2+C^YQYy>xO)aN4K6CEi9s$&r2%ow>65>3=7YDV!<>6R$oD**4G z_7kCCVTCB{3oHN=v^f;K@X9KVgd1`vy`@)4TB1{2o2B(3RCw4n>DZUXa0$2x>7gTO zEXXS*zg*4~M3QQXrZAckYQ`VK@Q{b=WyKHhiVkqki0Z{d1Dr49`s0{@9ui-pOXV?& z)vJ=(CE@091R0FuMkcb{{PqI{snx$9a+VLWZz<5431^szS_Hwy02oHeq?q4NO`lvJ zfwkd@-!#%r)#{xqVLWQb5Rt4Jw)b8GbeF4C)rqC(wPY2Ku)t0qTto%(6eBb5dQmz9 zgH}KS3C)6{!%5^P8TwFA3nikQ2()EBkIMBhe?xY`s3b;hFDudQZRih1rxEpzA@?!TgH@eObU7Xbh*M}EONGF@Km>N zVDnWO$Z<#pp(C=AvXR2!?K@XP*YXNWWD+ZNj^Cqujer0LI#s|jp*TxWc}pz{KCmfD z-I7=>QHM}v75RK@N)U?@SH|E1*FBv6w(dYplsm#-R5RNp zC$nph)ZT~06w-<%?(y1g;@~)M^MxbuvP=qP>xE)v^v5K2GAjiZovoIq~4iwX%%vOgrme^-A=OQG8(s4zmfT0OI~#m^HheAX#DXlx%hxowKhMm-?# zB=D3}83#u}K&>s9szWZJ;EAR$(?N^^ms4gJjc&XAUV(Ih$3SVOkYuixPc;q2n8Xx` zr=yhhfWvP!i-<0@OBd|M(+c(K)Cs!)mMwcjMAk^tQIk_w^$k+>QXsA{#zNdN%vNSC z&4dX=?apVMRwH4memrrbR1JCg^k*kPJ@z49nVEw;dr=A$*?(f1OM;uB%!XSkX%Ch` z(iJy}dtT1_zQ6-(lp`>b#u=MEM8NCgzxI?ReVyGh5 zQo%kLoI&OOxCd=L!Ek5yB_}c`=#D8(MMzyTY_N^ej3gh(0x0|pNdtyDjua!gX7VQ+ zeTQ66i*|-rODhr~VB}01ZZTt0+E9!lTWL(4R1!l627gY3v6RG^zl$HP23(aAjoJy# zE*x`C97N&*<4u^df-CU9U%vbuy!r9q%_wG zpOuZiFgF3$4)jVSrEX>j!TL$V=a0+nOd*>JW<0S$TueI@%NaP(H`Hdp@p}1ix8t-c zi2V;1LuQ45qA3Utc>KyF8f@SvuLCEhYjPqm*YM3{5KsDA0=HB;TnTO#OhQ7P zslzYhLyoL?xBYugl!HT7789aLCYqO*lXwBJBnEK-u}02MxT+QLa7Yv`MFrLt_s!Zj z<)X;b2u(SQq)~JT0x^J3!u**YoJ5ry8vBm2g_!yZf_A-RN^{<)Bi#`%TP=n>9V$$4w^x#Y3h9iNM>r`sKC_5ke3B87Hj^Px87GKegYT(j!r2lliv^>xo}zI%yUYw` zgQ-<9f&FcKdqEn=W`@86E+;pHkpSH`w7L`R0>dy_Sy@`B40{tSu5lJar%e^(K)U1B z(g64B0ge<2C=JY6W2+#i<8+M0P-~OchY}(NCY-T#hXJWYL5IyRNl7eZRx_|^0@I(2 zh#RN87r20i4Wy~yDI;1zkwi!*Ja`$rwX5+RSwE`VC!;JRZV02}XiW|D4`nC$F^;El zjxjuCVU`G!!JbV8lZ2H97Sj5n-&!6LYR^uTfXz{@%v5}Og18eBijY~7LDI<7{s7B~ zjlQ^3k^jdas0F+4SFqqv1&-2=(i)~vhaO~@5reUlWfWg=FWcr=qRA@GKyM;YjX*0- zGPr92$fT0pfGJlvg5~ifb(yU57%k_th*uIvklNtA8SZ)t>IXD~>?>GgRktJj0hDC#67zxpU(!#-TuaQoAr34fFy5Hya#>{Gviry0F zN^2$PsiER@C$2SBn@T6i?(DP-!#XXBC5k5f*Qw0B|Bi=L^?#MhEKrN%RE2?uSU6?A z1$ zyoSfLgrlL{547GfST9SJoFMG7g+{anIDjX(2u5-#U|NoATe&sOlbB{yjrBx_b836R z?#xuMI2LX?%-vV&qKlG}OS&lh_7eDPG@jBvD96Ufgiea&`S!(-O@Kv~-~ic0Q}`^R zPqnN})ryFSnU`U7;*_vY!m=*_3#Ysys=%5Q36rp<;s^>ZB0tVB7KZpGf()fuxeY@U z^qWKogY{50bD7f&$6e#oE3sOUa{GU5p%d53F#$Ms!h+*sh>&RAvO_Edaxo3>sn8jn zz-}0RmbG1uM`5TfPPviP0bKL}NX%1jBw1{YMvxhHVnB(SJI%wzVE;1#f5k@%RWEQ$Wa5z;Mk<&2RaobU~i`sdjZ4R6Kuo*te4V`IOc{;bL z$;vG0Ys)%T<*iUijqCPfj}Z#4OG_Q} z!^AvwIni68FII|^8W5nhlT4~_v>&7{%paW9HWbYB@Vj}oR zp`a?|g3TKYfm>|EoTcJEvmDn#q6MT|iu0yS7EH1i1JX-%k4PMa9lV144Td4IGm5Dm z6U^YT>Du*_9+*`B-6OTg(qhuu2{xE03WIV1oyeaMtMb zg>|;u%iE#9#sbMnoJ?$nBfrbTG{fjCTD+~%siO#bCAGkSVHX#fQj{smYl{Yq>yA!c zL0ipn&Z*)G5OI<&;xVu*OD#>Z)YUljf=O&lqScsF9Cl@bs(9h{Yd!@OCJMJrc_JZ+ z^WiKW!@~q;m|}R`S4t5zI!UQ)=i5i#wSKx6}H z!Ny?Au^%Pe3LiwGv5yZRgQ~?uC$U97V3dMkRRnqujta&84)q zGO0$@ahcuY&K4LOi{v@TE;%lx z#KR5akpgKH+bp=FN11%KaLS{D1hC-f)TIFj+$OS;F&G&hjSS|XOJN4_&T&|XdsrJpK+#cEJ4e+0T;2g&9y4O3`_X(M zm0NCjVL=My=x9~YyT{0?6HWwUmW=Epc?`Hsn=`K#LDNgg!Z>X(7L6zmT-3hNQLelK zq*;OKp?DX%_xy^?@WN)Btx&=C)MZg_S;MVJQ^~Sw&Vz zRV;eZBBbKgSXe;JN}_}~C`@^-;7OF=S=6vp#pIVbavG@G@Fp@ z*_)1u6j7mB9+T-~=dQJtSwOEg1EO@=6xRG{z@p$LlJ)SlybP7nVa2#C;^*dj>WCL! z7v7q1E=8+0h-W4l685a7M%G}`jZ-YEqQelK^L{@!zj1$xg_TV;a;LKNSRFnLfe}>D zx?q$rfG=#KGV%@ZcZL&HDX0^yT0%{q6A{R{fJ&semX%UAa7s|Ax7!H=5M)3C++qR> zjRnd!ENVM6PiqYmFvycgL~1NrMMxZ3xc|A|$qxDwJPo`J)+5x8z6F}L0yUnM+H%S* z5Y{GFoIBICDKq0#u__+vpeb~84#?(jkqJ#j(V7TfBxjtdKg;bZVSBM_@IHxxqr|-? z4qeflfO3yI8PTe#vrAzEOSYHhqp5ON0!j(RCQ9xPpNtfd zr>T;ysa!He*}%kD1;c|=^`a+!8WBQ=ouQKsqfj-2ujysp5U2mp-bvZZfE>pnfO0x5 z49R5@jDwc|{DQ-y5!ud}BV>Zx$I9;D6g%6oR~h^v znqr5?$CeH)dB8BDHVOcl;OUmFPRm2YOj;Y;Wr3*(C1sXiE(Mev7m+)N}q7`BTNnK8ll z=<|o@xW;=%K?t!u-Hv?=y(jbzTJ(6>d6*5tnPr?L$Q0#Wl*ve-mLj@{kl3eFB_wJ! z1m1~-!p3bge2V(LY+I+43$7|Z%|a`djaXPv(GmQqo%o?X3DplHY-|N^?-sr29!I~E z%A7G&m$1ESkrKJ5f@q4HRLQPJ?zF8WS%SzRM0G|ir59%OM-dt`ISwlN@XN?iKn^=M zmlYC_6N!_+(xjeq4|UH`wT+N}s>ex|sYy;caa*R7DJN z0oMbB{89U1V;k%~Q*=vVCoJ~-^CpH_PsR%-N5yGKCh&o&Vkc*RZH>jQ{aBGw?njVJ z-j^Iba~=|QjR1|$bV6`RCKnGu4w!mEn3Vn?9HHM`V9`oy*WR;z>;nS`L(w68fgna9 zF>DaU(82GnaDWd0)>s_HGfrWLre0bV&!R_ED`hZ*D(xL!VBM6ey(o7hV z1Qz<;b@GJDgN!LGfP_(7Gh}bv?F2bg+nJnI~ozw#(>F1%=zc5Zc9 zM&!hbCko@Rzb4d_Ov4N8m{UNV)glzh(HRB@G^BqYpwMMRpamhJHm!Yo&qSV??%GyLr=l4kn zdZBVW9oNLkjiE*+95=Q$9TKDpAhAdSM39&pQwvK}?Xy#wq5r47v)gSYIqvudxyeK1 zLh+4kKu2C9m%iHANY==Q4H$`$I}gP<5_3q7G8Co5V;I=SNPq-+nLNopNxHuJV>m}~=C`2B9y-W7+#>7MSY>ZK5Dbep>;=pC+2MXZFj-!R%~yA?g(T+erM-6FdQ$yv}WmgV-wW&lNJ z#~g<+oric72YtEitf!eF;*$5zRX267&w530QuK`Oby-ON?{E51lm>qL&`T%Bwax^q zI&WKzYOT9}>_V@2&khpXEO|1+_uEP~`zlhGtC=l3X)g9r42L)a_hbvZEB8ON)k^rV zo>(z4C+wW#raDD+F&_6`&uv6;NhBF3cS6l=K;rc4?3nkamKxUvBW_rf_6envcvO>z zCUM?iEynJrt#=;&e2Fk$6=}C*#nDpnt0VjOn|`}qo-()-0=Prqfs>`4G=;JUv%>->@&eR5Bq?$hD z##W8Kuk7OX^VX%2hNg*nlcv?SfAt~C-S*XwX(fcOA2**qb=S+GlC+V8z~1XUr6l9d z4aT(F9!viswHM#sHEQZAw1&H+VrZpe$y4{kEo=E9rkTme+G)#7TdCYM@jL^=UfB}i z$-zi5JtE&*YzjNLw_+I$6WSR_)^4=S*YM`vWQtb3HN(y~tJ>;h84CY*^Q4)n+>`lQ%awSz!2llw_swhB3N+_Uj^Kwf@e-_9#Nlccna|^hZio zyXP-Nh;n8OtDL>G(Tu0ZS}v$kL`)B}f9Z7ZAB&r>uhk%5Q(9||A45w;)WGII zX?7_r>sy)$gZDX!|E-pTk8dN{lXcw6nR9N)r53mCmLDu<@^k(0yTRRh4syirJ z!c*O`aJhq>lsgH)ekyr;(7S23Y1kUiRacxHWbH)Ud&aAAQiX0_2hgemzO9%$l|Wg1$u2pMyN0D z-h7Ra?HT)Wy5!w_Z0c*;otUVe?`b^%UyJlAw_E-~q!{g7{a=q=sm1b!+85v5%AMV5kzsexs=F$ZqdmB17u)i#Nh8X4tJ6FA zXD)Kgws*3`pIy1bEbyC2PG!mCFFB!`oabl#*2==}LJH;RNWLS|AZ1wJk^<1CF3Yry zE&^KEAWOw^AT3(?FAa*jS;JU~*i1xv^*;5CE-rR@b)W_l9y;_*vvlofHoufwfWyz( zsu)M^o!@8@g!-YDqPWDVENeFRtzgV7nONgn7b}K2I=Y9u_4(VQYX`g^J6ET-b8j=Q zJxTTT(K%gyb9|6~fN}8`XfiI{?Ax?cvA0)Vr_!;NUEt4q4m4?yMYbNG$Q$ zGiYtYYO=&HkK{yIOh!?ML;{1p5nC@M-QJIn%if$str~5P+WgDHo0D4a?P*jmc9m8R z_l_S<(z`1A)8BscZ!g2kx8MAGBMat{Kl^yxXoSSmWFI&8N6Yl<_F?<%q)hm}kBZ8o z|6s4W*gM{oY@;>s9^HQ!h7uT*`@E@!cB2o|`wU7(a6Sf#BsHCv+AP~bGu{$(wb@$% z`N@TE_O_HCa&u3KChAZuq$M|ln4W(6i2P6;##oUBnr-qt!6kurII8m7jn0`udcoS{_{JLTZ70 zdT)Iothe=eD%v-rXaAK7S{aRMriqnTUSbdQ*Z!uKMoH;?y)>p@BKt$k-coibV)r)L zcGm7%J0y3qB3@eq*Vo=Vd8i?sHC#}^X^N`f9OBaW>&s9wM0D$4TiZJ6mXutP&v4%+ z#ixxq@6v8#r1qB#v3Q96V>f0Ak=^VjR{~s%HQ<^89UIIfJTUcn+Pz5 zT7Bp(W=OGM?71CsE|}zXJq{)ym{yq6#h1%u%g;pH>kO(|RxF!S_Bm?|Tc+@xg<5U< z(flIQVz;Igc1)Xob%?XuC8Hh6q0weP+$9t8T)o|${JLel$AzMt>qb2n^#G;LS1#IZ zhkNUErspj=QZEHglJ?^jE4D|bUHBmxAD{XXU)J9$5#?Ry-mbj&x7J2l1l2acLgx z)5vYx1|IXV5*@Pc(QF^9W*s+eMy?80`NETH`fCyL($rd#HFY<$j83h4%ijHaDS|wt zK_7=*r>2N&va7*e>7z=8jTG9S8$9-OiXl~+yQ<_-ej8<)il=r{Nn7Q4X{u*?@#2rwi(oN~Os4U=PP7QgWRngtk-IT4CqNy-dtp#yBOM$k`Bc-3XcMavN*p zoE(=8x#k*jncEnqjcv9af5P_<_`d&y_Ya@<^SqzW^LnEpSg;i@SVa*$8Y#b9B`aJT z@H;7g@L5`j)8&5l<7AURmW;-A&(|w9I?x=7c)1H1@=EAF_`s@QvBXJa`fWwrL z!LgY1z*8%iAuvK8`Snu5#e>vVNs5p4y()jB@3~yxrs>M>&23M3)e8ExlOyF-P^!b%X4N-YP@}f;+~CAL_IwHA z><_?vo&sJplDCq}ja8C0K~iIB#!kpIkB4@*31$$X8-$??v{_J*&uCRY7z>L>DM)yE zlD!Y+r~o~XkiLWA@FNax8F4fZ1i2l3=qy1c<|%RJf=`r>jQfqZ-2At!Tjz<=8$5B+ z4Oo-DW|owKDbmf_`}z#*M}JdVO|*fMsCcNiSbs1L3~ z;Y*}o!u$~~%zPv8{<`CF!_e-}obom2@rDG;R|&tCvI1(0X4?5T2N<^wgM(ndgTmN6 z(ey)_%qi}@`JyVf?F25ZLQTpPop$gBD%+!*CtL#CWIB2jD z6Kj#cpTL!fN1>#(__q9`uH5F4X|=dOz#PE*>(I+@1I3nZGYK9PgLDnBmx{Aa2+}F* zhQfK4=;n{n7plyXiB}ShvUq0O-NEd9ZIB(1&Z`ibCrRJ@$bZ+qlQC&hheFU?6efwu zjnDkw$_wiF8&Br&xj^jWP&qs8f{SZ{`A`Dib-66HK>kR{;E?NFYePWFdQL|E13D0I zCqVmA(VX2lVt#3or_YEagltOcPpX7lH~9+N-HlkDIX+x9Fux zF;5K17`+bZBXma4l>2T^E)%-%euo=%$^!8RbhZj6qZc(-o6EV?Ep&ev;F5 zrhd;uej!2FIb9#9W+KpZ)U^^G^=KK;D>&27PCh`NXl@J=9sfnY#X;eW_T$U(atI|FfpX3Y*zb%FZ;p6d1yZ_8D&EgOOREXS)}f)3@d zbfz05uG%oO>JiEcyCH^nr`H)mVnu%oDkeh!#&2t zYugfL*eLyeP5JpT$SD|Ry=uCbT;Z#kYUAEQK>u@VzrYhUxu{`sfwe&Pahh7cPSy09 z`K|GAbx*;>pPA;-86%I}D8k{kHE?^JWQ=!ldRZhr7)u3xHhv-6w&{aEl(G7LTdxy& zIp)@vmz5l|m2v(VpXxf};om%B;c!VRNEv%;V%whEIDFKRRo&W?;vPg^E}PT?9Qi? zrWqSwfF)maOh?9~g6o+;Xi)hOZExSmY+hZtiB&ozUXl`Dk^ltO@?%{R460CqpSLDg zDw0O_tM@xlw6S${ws4z%vV(}pvG^hnEdvAVH!b&w;_9YnTkn&+&3Ge8vP97pD@T4eU=I_>oz%OZ>&}Jn@oef& zyy~j>>Qf+;u6_cV57$mafL4M*-ReD=s=jkx7YsG%JA2#MkDytgy9kt!9n0BCX>9|{ z*Z(4~nmmsUzk+%6J{K){mRTk*=57AG%-@A-3Zp`Poj&`7{q9;{v0;Mo-`wWBf0E2Vtx+#GO9Mn8r0+0)@2@p9nCbXX8EhkWmO(qCQa}?wPt7EvDC9VT0}YI+<@A4z-ZI#ozbN4}E~!Kv%a%T9 z;Hj{NnwD7-qVRr|7tpy}e+UN9y0WNBm5JN-m*oP|8< zz{ZzZbY)5YV}PY`u%i~fG2l(`Bm;&9B)mzHYe8$Q#jSj8NUG~8T1I0&P#diJ`ZH34 z$G!f>;3$YZm(XfxSM8$+XnQzd$YB-uRRzeMVw$x>hSz9%?5F_WI}(DEV4+9Q-{#Mk flPnW4+a1K%9}fLr|Dyvrk{_tHCd!AdNFVwSE3boV literal 0 HcmV?d00001 diff --git a/examples/embedded-c++/CMakeLists.txt b/examples/embedded-c++/CMakeLists.txt index 1a490256d73..7721543a232 100644 --- a/examples/embedded-c++/CMakeLists.txt +++ b/examples/embedded-c++/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(example-c++) set(CMAKE_CXX_STANDARD 11) diff --git a/examples/embedded-c/CMakeLists.txt b/examples/embedded-c/CMakeLists.txt index 1c3fb646a43..60468275982 100644 --- a/examples/embedded-c/CMakeLists.txt +++ b/examples/embedded-c/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(example-c) include_directories(../../src/include) diff --git a/examples/jdbc/.gitignore b/examples/jdbc/.gitignore deleted file mode 100644 index a1236bada99..00000000000 --- a/examples/jdbc/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.class -target \ No newline at end of file diff --git a/examples/jdbc/DuckDBExample.java b/examples/jdbc/DuckDBExample.java deleted file mode 100644 index 186b4d05e46..00000000000 --- a/examples/jdbc/DuckDBExample.java +++ /dev/null @@ -1,47 +0,0 @@ -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; - -public class DuckDBExample { - public static void main(String[] args) throws SQLException, ClassNotFoundException { - Class.forName("org.duckdb.DuckDBDriver"); - - // this JDBC url creates a temporary in-memory database. If you want to use a - // persistent DB, append its file name - Connection conn = DriverManager.getConnection("jdbc:duckdb:"); - - Statement stmt = conn.createStatement(); - stmt.execute("CREATE TABLE test (a INTEGER, b VARCHAR)"); - - PreparedStatement p_stmt = conn.prepareStatement("INSERT INTO test VALUES (?, ?);"); - - p_stmt.setInt(1, 42); - p_stmt.setString(2, "Hello"); - p_stmt.execute(); - - p_stmt.setInt(1, 43); - p_stmt.setString(2, "World"); - p_stmt.execute(); - - p_stmt.close(); - - ResultSet rs = stmt.executeQuery("SELECT * FROM test"); - ResultSetMetaData md = rs.getMetaData(); - int row = 1; - while (rs.next()) { - for (int col = 1; col <= md.getColumnCount(); col++) { - System.out.println(md.getColumnName(col) + "[" + row + "]=" + rs.getString(col) + " (" + - md.getColumnTypeName(col) + ")"); - } - row++; - } - - rs.close(); - stmt.close(); - conn.close(); - } -} diff --git a/examples/jdbc/Makefile b/examples/jdbc/Makefile deleted file mode 100644 index 17e2419436f..00000000000 --- a/examples/jdbc/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -.PHONY: duckdb clean main - -all: duckdb main - -clean: - rm -f *.class - rm -rf target - -duckdb: - BUILD_JDBC=1 make -C ../.. - -main: - javac DuckDBExample.java - java -cp .:../../build/release/tools/jdbc/duckdb_jdbc.jar DuckDBExample - -maven: - mvn compile exec:java -Dexec.mainClass="DuckDBExample" \ No newline at end of file diff --git a/examples/jdbc/pom.xml b/examples/jdbc/pom.xml deleted file mode 100644 index c12e44c6968..00000000000 --- a/examples/jdbc/pom.xml +++ /dev/null @@ -1,23 +0,0 @@ - - 4.0.0 - org.duckdb - duckdb_jdbc_example - 0.0.1-SNAPSHOT - - . - - - 1.8 - 1.8 - - - - - org.duckdb - duckdb_jdbc - 0.6.1 - - - - - \ No newline at end of file diff --git a/examples/python/duckdb-python.py b/examples/python/duckdb-python.py index bca56078408..1a4105800ad 100644 --- a/examples/python/duckdb-python.py +++ b/examples/python/duckdb-python.py @@ -100,7 +100,7 @@ print(rel.limit(2, offset=1)) # of course these things can be chained -print(rel.filter('i > 1').project('i + 1').order('j').limit(2)) +print(rel.filter('i > 1').project('i + 1, j').order('j').limit(2)) # aggregate the relation print(rel.aggregate("sum(i)")) @@ -136,7 +136,7 @@ print(duckdb.distinct(test_df)) # when chaining only the first call needs to include the data frame parameter -print(duckdb.filter(test_df, 'i > 1').project('i + 1').order('j').limit(2)) +print(duckdb.filter(test_df, 'i > 1').project('i + 1, j').order('j').limit(2)) # turn the relation into something else again @@ -181,5 +181,5 @@ print(res.df()) # this also works directly on data frames -res = duckdb.query(test_df, 'my_name_for_test_df', 'SELECT * FROM my_name_for_test_df') +res = duckdb.query_df(test_df, 'my_name_for_test_df', 'SELECT * FROM my_name_for_test_df') print(res.df()) diff --git a/examples/standalone-window/CMakeLists.txt b/examples/standalone-window/CMakeLists.txt index 455651f05a9..7b1221de75e 100644 --- a/examples/standalone-window/CMakeLists.txt +++ b/examples/standalone-window/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(example-window) set(CMAKE_CXX_STANDARD 11) diff --git a/extension/README.md b/extension/README.md index 6b154b6f18f..0ba4511c520 100644 --- a/extension/README.md +++ b/extension/README.md @@ -170,6 +170,7 @@ duckdb_extension_load(extension_2 GIT_TAG some_git_hash ) ``` + Now to merge the vcpkg.json manifests from these two extension run: ```shell make extension_configuration diff --git a/extension/autocomplete/CMakeLists.txt b/extension/autocomplete/CMakeLists.txt index 285523758a4..10222a7e87d 100644 --- a/extension/autocomplete/CMakeLists.txt +++ b/extension/autocomplete/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(AutoCompleteExtension) diff --git a/extension/autocomplete/autocomplete_extension.cpp b/extension/autocomplete/autocomplete_extension.cpp index 77df23c1058..c5b53be0ed1 100644 --- a/extension/autocomplete/autocomplete_extension.cpp +++ b/extension/autocomplete/autocomplete_extension.cpp @@ -426,6 +426,14 @@ std::string AutocompleteExtension::Name() { return "autocomplete"; } +std::string AutocompleteExtension::Version() const { +#ifdef EXT_VERSION_AUTOCOMPLETE + return EXT_VERSION_AUTOCOMPLETE; +#else + return ""; +#endif +} + } // namespace duckdb extern "C" { diff --git a/extension/autocomplete/include/autocomplete_extension.hpp b/extension/autocomplete/include/autocomplete_extension.hpp index a3c5b0df712..90f561d2f67 100644 --- a/extension/autocomplete/include/autocomplete_extension.hpp +++ b/extension/autocomplete/include/autocomplete_extension.hpp @@ -16,6 +16,7 @@ class AutocompleteExtension : public Extension { public: void Load(DuckDB &db) override; std::string Name() override; + std::string Version() const override; }; } // namespace duckdb diff --git a/extension/delta/CMakeLists.txt b/extension/delta/CMakeLists.txt new file mode 100644 index 00000000000..c2fa100c362 --- /dev/null +++ b/extension/delta/CMakeLists.txt @@ -0,0 +1,131 @@ +cmake_minimum_required(VERSION 2.8.12) +include(ExternalProject) + +# Core config +set(TARGET_NAME delta) + +set(EXTENSION_NAME ${TARGET_NAME}_extension) +set(LOADABLE_EXTENSION_NAME ${TARGET_NAME}_loadable_extension) + +project(${TARGET_NAME}) + +include_directories(src/include) + +set(EXTENSION_SOURCES src/delta_extension.cpp src/delta_functions.cpp + src/delta_utils.cpp src/functions/delta_scan.cpp) + +# Custom config TODO: figure out if we really need this? +if(APPLE) + set(PLATFORM_LIBS + m + c + System + resolv + "-framework Corefoundation -framework SystemConfiguration -framework Security" + ) +elseif(UNIX) + set(PLATFORM_LIBS m c resolv) +elseif(WIN32) + set(PLATFORM_LIBS ws2_32 userenv advapi32) +else() + message(STATUS "UNKNOWN OS") +endif() + +# Setup delta-kernel-rs dependency +set(KERNEL_NAME delta_kernel) + +# Set default ExternalProject root directory +set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/rust) + +# Propagate arch to rust build for CI +set(RUST_PLATFORM_TARGET "") +if("${OS_NAME}" STREQUAL "linux") + if("${OS_ARCH}" STREQUAL "arm64") + set(RUST_PLATFORM_TARGET "aarch64-unknown-linux-gnu") + else() + set(RUST_PLATFORM_TARGET "x86_64-unknown-linux-gnu") + endif() +elseif("${OS_NAME}" STREQUAL "osx") + # TODO: clean up upstream; we are not correctly setting OS_ARCH for cross + # compile + if("${OSX_BUILD_ARCH}" STREQUAL "arm64") + set(RUST_PLATFORM_TARGET "aarch64-apple-darwin") + elseif("${OSX_BUILD_ARCH}" STREQUAL "x86_64") + set(RUST_PLATFORM_TARGET "x86_64-apple-darwin") + elseif("${OS_ARCH}" STREQUAL "arm64") + set(RUST_PLATFORM_TARGET "aarch64-apple-darwin") + else() + set(RUST_PLATFORM_TARGET "x86_64-apple-darwin") + endif() +endif() + +# Add rust_example as a CMake target +ExternalProject_Add( + ${KERNEL_NAME} + GIT_REPOSITORY "https://github.com/delta-incubator/delta-kernel-rs" + GIT_TAG 08f0764a00e89f42136fd478823d28278adc7ee8 + CONFIGURE_COMMAND "" + UPDATE_COMMAND "" + BUILD_IN_SOURCE 1 + # Build debug build + BUILD_COMMAND cargo build --package delta_kernel_ffi --workspace + --all-features --target=${RUST_PLATFORM_TARGET} + # Build release build + COMMAND cargo build --package delta_kernel_ffi --workspace --all-features + --release --target=${RUST_PLATFORM_TARGET} + # Build DATs + COMMAND + cargo build + --manifest-path=${CMAKE_BINARY_DIR}/rust/src/delta_kernel/acceptance/Cargo.toml + BUILD_BYPRODUCTS + "${CMAKE_BINARY_DIR}/rust/src/delta_kernel/target/${RUST_PLATFORM_TARGET}/debug/libdelta_kernel_ffi.a" + BUILD_BYPRODUCTS + "${CMAKE_BINARY_DIR}/rust/src/delta_kernel/target/${RUST_PLATFORM_TARGET}/release/libdelta_kernel_ffi.a" + BUILD_BYPRODUCTS + "${CMAKE_BINARY_DIR}/rust/src/delta_kernel/target/ffi-headers/delta_kernel_ffi.h" + BUILD_BYPRODUCTS + "${CMAKE_BINARY_DIR}/rust/src/delta_kernel/target/ffi-headers/delta_kernel_ffi.hpp" + INSTALL_COMMAND "" + LOG_BUILD ON) + +build_static_extension(${TARGET_NAME} ${EXTENSION_SOURCES}) +build_loadable_extension(${TARGET_NAME} " " ${EXTENSION_SOURCES}) + +include_directories( + ${CMAKE_BINARY_DIR}/rust/src/delta_kernel/target/ffi-headers) +include_directories( + ${CMAKE_BINARY_DIR}/rust/src/delta_kernel/target/ffi-headers) + +# Hides annoying linker warnings +set(CMAKE_OSX_DEPLOYMENT_TARGET + 13.3 + CACHE STRING "Minimum OS X deployment version" FORCE) + +# Add the default client +add_compile_definitions(DEFINE_DEFAULT_ENGINE) + +# Link delta-kernal-rs to static lib +target_link_libraries( + ${EXTENSION_NAME} + debug + "${CMAKE_BINARY_DIR}/rust/src/delta_kernel/target/${RUST_PLATFORM_TARGET}/debug/libdelta_kernel_ffi.a" + optimized + "${CMAKE_BINARY_DIR}/rust/src/delta_kernel/target/${RUST_PLATFORM_TARGET}/release/libdelta_kernel_ffi.a" + ${PLATFORM_LIBS}) +add_dependencies(${EXTENSION_NAME} delta_kernel) + +# Link delta-kernal-rs to dynamic lib +target_link_libraries( + ${LOADABLE_EXTENSION_NAME} + debug + "${CMAKE_BINARY_DIR}/rust/src/delta_kernel/target/${RUST_PLATFORM_TARGET}/debug/libdelta_kernel_ffi.a" + optimized + "${CMAKE_BINARY_DIR}/rust/src/delta_kernel/target/${RUST_PLATFORM_TARGET}/release/libdelta_kernel_ffi.a" + ${PLATFORM_LIBS}) +add_dependencies(${LOADABLE_EXTENSION_NAME} delta_kernel) + +install( + TARGETS ${EXTENSION_NAME} + EXPORT "${DUCKDB_EXPORT_SET}" + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}") diff --git a/extension/delta/Makefile b/extension/delta/Makefile new file mode 100644 index 00000000000..05db9579f22 --- /dev/null +++ b/extension/delta/Makefile @@ -0,0 +1,25 @@ +PROJ_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +# Configuration of extension +EXT_NAME=deltatable +EXT_CONFIG=${PROJ_DIR}extension_config.cmake + +# Set test paths +test_release: export DELTA_KERNEL_TESTS_PATH=./build/release/rust/src/delta_kernel/kernel/tests/data +test_release: export DAT_PATH=./build/release/rust/src/delta_kernel/acceptance/tests/dat + +test_debug: export DELTA_KERNEL_TESTS_PATH=./build/debug/rust/src/delta_kernel/kernel/tests/data +test_debug: export DAT_PATH=./build/debug/rust/src/delta_kernel/acceptance/tests/dat + +# Include the Makefile from extension-ci-tools +include extension-ci-tools/makefiles/duckdb_extension.Makefile + +reldebug: + mkdir -p build/reldebug && \ + cmake $(GENERATOR) $(BUILD_FLAGS) $(EXT_RELEASE_FLAGS) -DCMAKE_BUILD_TYPE=RelWithDebInfo -S ./duckdb/ -B build/reldebug && \ + cmake --build build/reldebug --config RelWithDebInfo + +# Generate some test data to test with +generate-data: + python3 -m pip install delta-spark duckdb pandas deltalake pyspark delta + python3 scripts/generate_test_data.py diff --git a/extension/delta/README.md b/extension/delta/README.md new file mode 100644 index 00000000000..910c002b7dd --- /dev/null +++ b/extension/delta/README.md @@ -0,0 +1,71 @@ +# DuckDB Delta Extension +This is the experimental DuckDB extension for [Delta](https://delta.io/). It is built using the (also experimental) +[Delta Kernel](https://github.com/delta-incubator/delta-kernel-rs). The extension (currently) offers **read** support for delta +tables, both local and remote. + +# Supported platforms +The supported platforms are: +- `linux_amd64` and `linux_amd64_gcc4` +- `osx_amd64` and `osx_arm64` + +Support for the [other](https://duckdb.org/docs/extensions/working_with_extensions#platforms) DuckDB platforms is +work-in-progress + +# How to use +**NOTE: this extension requires the DuckDB v0.10.3 or higher** + +This extension is distributed as a binary extension. To use it, simply use one of its functions from DuckDB and the extension will be autoloaded: +```SQL +FROM delta_scan('s3://some/delta/table'); +``` + +Note that using DuckDB [Secrets](https://duckdb.org/docs/configuration/secrets_manager.html) for S3 authentication is supported: + +```SQL +CREATE SECRET (TYPE S3, provider credential_chain); +FROM delta_scan('s3://some/delta/table/with/auth'); +``` + +To scan a local table, use the full path prefixes with `file://` +```SQL +FROM delta_scan('file:///some/path/on/local/machine'); +``` + +# Features +While still experimental, many (scanning) features/optimizations are already supported in this extension as it reuses most of DuckDB's +regular parquet scanning logic: +- multithreaded scans and parquet metadata reading +- data skipping/filter pushdown + - skipping row-groups in file (based on parquet metadata) + - skipping complete files (based on delta partition info) +- projection pushdown +- scanning tables with deletion vectors +- all primitive types +- structs +- S3 support with secrets + +More features coming soon! + +# Building +See the [Extension Template](https://github.com/duckdb/extension-template) for generic build instructions + +# Running tests +There are various tests available for the delta extension: +1. Delta Acceptence Test (DAT) based tests in `/test/sql/dat` +2. delta-kernel-rs based tests in `/test/sql/delta_kernel_rs` +3. Generated data based tests in `tests/sql/generated` (generated using [delta-rs](https://delta-io.github.io/delta-rs/), [PySpark](https://spark.apache.org/docs/latest/api/python/index.html), and DuckDB) + +To run the first 2 sets of tests: +```shell +make test_debug +``` +or in release mode +```shell +make test +``` + +To also run the tests on generated data: +```shell +make generate-data +GENERATED_DATA_AVAILABLE=1 make test +``` \ No newline at end of file diff --git a/extension/delta/extension_config.cmake b/extension/delta/extension_config.cmake new file mode 100644 index 00000000000..46e7a27b769 --- /dev/null +++ b/extension/delta/extension_config.cmake @@ -0,0 +1,14 @@ +# This file is included by DuckDB's build system. It specifies which extension to load + +# Extension from this repo +duckdb_extension_load(delta + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} + LOAD_TESTS +) + +# Build the httpfs extension to test with s3/http +duckdb_extension_load(httpfs) + +# Build the tpch and tpcds extension for testing/benchmarking +duckdb_extension_load(tpch) +duckdb_extension_load(tpcds) diff --git a/extension/delta/src/delta_extension.cpp b/extension/delta/src/delta_extension.cpp new file mode 100644 index 00000000000..e1f464a6b05 --- /dev/null +++ b/extension/delta/src/delta_extension.cpp @@ -0,0 +1,43 @@ +#define DUCKDB_EXTENSION_MAIN + +#include "delta_extension.hpp" +#include "delta_functions.hpp" + +#include "duckdb.hpp" +#include "duckdb/common/exception.hpp" +#include "duckdb/main/extension_util.hpp" + +namespace duckdb { + +static void LoadInternal(DatabaseInstance &instance) { + // Load functions + for (const auto &function : DeltaFunctions::GetTableFunctions(instance)) { + ExtensionUtil::RegisterFunction(instance, function); + } +} + +void DeltaExtension::Load(DuckDB &db) { + LoadInternal(*db.instance); +} + +std::string DeltaExtension::Name() { + return "delta"; +} + +} // namespace duckdb + +extern "C" { + +DUCKDB_EXTENSION_API void delta_init(duckdb::DatabaseInstance &db) { + duckdb::DuckDB db_wrapper(db); + db_wrapper.LoadExtension(); +} + +DUCKDB_EXTENSION_API const char *delta_version() { + return duckdb::DuckDB::LibraryVersion(); +} +} + +#ifndef DUCKDB_EXTENSION_MAIN +#error DUCKDB_EXTENSION_MAIN not defined +#endif diff --git a/extension/delta/src/delta_functions.cpp b/extension/delta/src/delta_functions.cpp new file mode 100644 index 00000000000..da80b05b4f3 --- /dev/null +++ b/extension/delta/src/delta_functions.cpp @@ -0,0 +1,17 @@ +#include "delta_functions.hpp" + +#include "duckdb.hpp" +#include "duckdb/main/extension_util.hpp" +#include + +namespace duckdb { + +vector DeltaFunctions::GetTableFunctions(DatabaseInstance &instance) { + vector functions; + + functions.push_back(GetDeltaScanFunction(instance)); + + return functions; +} + +}; // namespace duckdb diff --git a/extension/delta/src/delta_utils.cpp b/extension/delta/src/delta_utils.cpp new file mode 100644 index 00000000000..5f909f19f79 --- /dev/null +++ b/extension/delta/src/delta_utils.cpp @@ -0,0 +1,322 @@ +#include "delta_utils.hpp" + +#include "duckdb.hpp" +#include "duckdb/main/extension_util.hpp" +#include + +namespace duckdb { + +unique_ptr SchemaVisitor::VisitSnapshotSchema(ffi::SharedSnapshot *snapshot) { + SchemaVisitor state; + ffi::EngineSchemaVisitor visitor; + + visitor.data = &state; + visitor.make_field_list = (uintptr_t(*)(void *, uintptr_t)) & MakeFieldList; + visitor.visit_struct = (void (*)(void *, uintptr_t, ffi::KernelStringSlice, uintptr_t)) & VisitStruct; + visitor.visit_array = (void (*)(void *, uintptr_t, ffi::KernelStringSlice, bool, uintptr_t)) & VisitArray; + visitor.visit_map = (void (*)(void *, uintptr_t, ffi::KernelStringSlice, bool, uintptr_t)) & VisitMap; + visitor.visit_decimal = (void (*)(void *, uintptr_t, ffi::KernelStringSlice, uint8_t, uint8_t)) & VisitDecimal; + visitor.visit_string = VisitSimpleType(); + visitor.visit_long = VisitSimpleType(); + visitor.visit_integer = VisitSimpleType(); + visitor.visit_short = VisitSimpleType(); + visitor.visit_byte = VisitSimpleType(); + visitor.visit_float = VisitSimpleType(); + visitor.visit_double = VisitSimpleType(); + visitor.visit_boolean = VisitSimpleType(); + visitor.visit_binary = VisitSimpleType(); + visitor.visit_date = VisitSimpleType(); + visitor.visit_timestamp = VisitSimpleType(); + visitor.visit_timestamp_ntz = VisitSimpleType(); + + uintptr_t result = visit_schema(snapshot, &visitor); + return state.TakeFieldList(result); +} + +void SchemaVisitor::VisitDecimal(SchemaVisitor *state, uintptr_t sibling_list_id, ffi::KernelStringSlice name, + uint8_t precision, uint8_t scale) { + state->AppendToList(sibling_list_id, name, LogicalType::DECIMAL(precision, scale)); +} + +uintptr_t SchemaVisitor::MakeFieldList(SchemaVisitor *state, uintptr_t capacity_hint) { + return state->MakeFieldListImpl(capacity_hint); +} + +void SchemaVisitor::VisitStruct(SchemaVisitor *state, uintptr_t sibling_list_id, ffi::KernelStringSlice name, + uintptr_t child_list_id) { + auto children = state->TakeFieldList(child_list_id); + state->AppendToList(sibling_list_id, name, LogicalType::STRUCT(std::move(*children))); +} + +void SchemaVisitor::VisitArray(SchemaVisitor *state, uintptr_t sibling_list_id, ffi::KernelStringSlice name, + bool contains_null, uintptr_t child_list_id) { + auto children = state->TakeFieldList(child_list_id); + + D_ASSERT(children->size() == 1); + state->AppendToList(sibling_list_id, name, LogicalType::LIST(children->front().second)); +} + +void SchemaVisitor::VisitMap(SchemaVisitor *state, uintptr_t sibling_list_id, ffi::KernelStringSlice name, + bool contains_null, uintptr_t child_list_id) { + auto children = state->TakeFieldList(child_list_id); + + D_ASSERT(children->size() == 2); + state->AppendToList(sibling_list_id, name, LogicalType::MAP(LogicalType::STRUCT(std::move(*children)))); +} + +uintptr_t SchemaVisitor::MakeFieldListImpl(uintptr_t capacity_hint) { + uintptr_t id = next_id++; + auto list = make_uniq(); + if (capacity_hint > 0) { + list->reserve(capacity_hint); + } + inflight_lists.emplace(id, std::move(list)); + return id; +} + +void SchemaVisitor::AppendToList(uintptr_t id, ffi::KernelStringSlice name, LogicalType &&child) { + auto it = inflight_lists.find(id); + if (it == inflight_lists.end()) { + // TODO... some error... + throw InternalException("WEIRD SHIT"); + } else { + it->second->emplace_back(std::make_pair(string(name.ptr, name.len), std::move(child))); + } +} + +unique_ptr SchemaVisitor::TakeFieldList(uintptr_t id) { + auto it = inflight_lists.find(id); + if (it == inflight_lists.end()) { + // TODO: Raise some kind of error. + throw InternalException("WEIRD SHIT 2"); + } + auto rval = std::move(it->second); + inflight_lists.erase(it); + return rval; +} + +ffi::EngineError *DuckDBEngineError::AllocateError(ffi::KernelError etype, ffi::KernelStringSlice msg) { + auto error = new DuckDBEngineError; + error->etype = etype; + error->error_message = string(msg.ptr, msg.len); + return error; +} + +string DuckDBEngineError::KernelErrorEnumToString(ffi::KernelError err) { + const char *KERNEL_ERROR_ENUM_STRINGS[] = { + "UnknownError", + "FFIError", + "ArrowError", + "EngineDataTypeError", + "ExtractError", + "GenericError", + "IOErrorError", + "ParquetError", + "ObjectStoreError", + "ObjectStorePathError", + "Reqwest", + "FileNotFoundError", + "MissingColumnError", + "UnexpectedColumnTypeError", + "MissingDataError", + "MissingVersionError", + "DeletionVectorError", + "InvalidUrlError", + "MalformedJsonError", + "MissingMetadataError", + "MissingProtocolError", + "MissingMetadataAndProtocolError", + "ParseError", + "JoinFailureError", + "Utf8Error", + "ParseIntError", + "InvalidColumnMappingMode", + "InvalidTableLocation", + "InvalidDecimalError", + }; + + static_assert(sizeof(KERNEL_ERROR_ENUM_STRINGS) / sizeof(char *) - 1 == (int)ffi::KernelError::InvalidDecimalError, + "KernelErrorEnumStrings mismatched with kernel"); + + if ((int)err < sizeof(KERNEL_ERROR_ENUM_STRINGS) / sizeof(char *)) { + return KERNEL_ERROR_ENUM_STRINGS[(int)err]; + } + + return StringUtil::Format("EnumOutOfRange (enum val out of range: %d)", (int)err); +} + +void DuckDBEngineError::Throw(string from_where) { + // Make copies before calling delete this + auto etype_copy = etype; + auto message_copy = error_message; + + // Consume error by calling delete this (remember this error is created by kernel using AllocateError) + delete this; + throw IOException("Hit DeltaKernel FFI error (from: %s): Hit error: %u (%s) with message (%s)", from_where.c_str(), + etype_copy, KernelErrorEnumToString(etype_copy), message_copy); +} + +ffi::KernelStringSlice KernelUtils::ToDeltaString(const string &str) { + return {str.data(), str.size()}; +} + +string KernelUtils::FromDeltaString(const struct ffi::KernelStringSlice slice) { + return {slice.ptr, slice.len}; +} + +vector KernelUtils::FromDeltaBoolSlice(const struct ffi::KernelBoolSlice slice) { + vector result; + result.assign(slice.ptr, slice.ptr + slice.len); + return result; +} + +PredicateVisitor::PredicateVisitor(const vector &column_names, optional_ptr filters) + : EnginePredicate {.predicate = this, + .visitor = (uintptr_t(*)(void *, ffi::KernelExpressionVisitorState *)) & VisitPredicate} { + if (filters) { + for (auto &filter : filters->filters) { + column_filters[column_names[filter.first]] = filter.second.get(); + } + } +} + +// Template wrapper function that implements get_next for EngineIteratorFromCallable. +template +static auto GetNextFromCallable(Callable *callable) -> decltype(std::declval()()) { + return callable->operator()(); +} + +// Wraps a callable object (e.g. C++11 lambda) as an EngineIterator. +template +ffi::EngineIterator EngineIteratorFromCallable(Callable &callable) { + auto *get_next = &GetNextFromCallable; + return {.data = &callable, .get_next = (const void *(*)(void *))get_next}; +}; + +// Helper function to prevent pushing down filters kernel cant handle +// TODO: remove once kernel handles this properly? +static bool CanHandleFilter(TableFilter *filter) { + switch (filter->filter_type) { + case TableFilterType::CONSTANT_COMPARISON: + return true; + case TableFilterType::CONJUNCTION_AND: { + auto &conjunction = static_cast(*filter); + bool can_handle = true; + for (const auto &child : conjunction.child_filters) { + can_handle = can_handle && CanHandleFilter(child.get()); + } + return can_handle; + } + + default: + return false; + } +} + +// Prunes the list of predicates to ones that we can handle +static unordered_map PrunePredicates(unordered_map predicates) { + unordered_map result; + for (const auto &predicate : predicates) { + if (CanHandleFilter(predicate.second)) { + result[predicate.first] = predicate.second; + } + } + return result; +} + +uintptr_t PredicateVisitor::VisitPredicate(PredicateVisitor *predicate, ffi::KernelExpressionVisitorState *state) { + auto filters = PrunePredicates(predicate->column_filters); + + auto it = filters.begin(); + auto end = filters.end(); + auto get_next = [predicate, state, &it, &end]() -> uintptr_t { + if (it == end) { + return 0; + } + auto &filter = *it++; + return predicate->VisitFilter(filter.first, *filter.second, state); + }; + auto eit = EngineIteratorFromCallable(get_next); + + // TODO: this should be fixed upstream? + try { + return visit_expression_and(state, &eit); + } catch (...) { + return ~0; + } +} + +uintptr_t PredicateVisitor::VisitConstantFilter(const string &col_name, const ConstantFilter &filter, + ffi::KernelExpressionVisitorState *state) { + auto maybe_left = + ffi::visit_expression_column(state, KernelUtils::ToDeltaString(col_name), DuckDBEngineError::AllocateError); + uintptr_t left = KernelUtils::UnpackResult(maybe_left, "VisitConstantFilter failed to visit_expression_column"); + + uintptr_t right = ~0; + auto &value = filter.constant; + switch (value.type().id()) { + case LogicalType::BIGINT: + right = visit_expression_literal_long(state, BigIntValue::Get(value)); + break; + + case LogicalType::VARCHAR: { + // WARNING: C++ lifetime extension rules don't protect calls of the form foo(std::string(...).c_str()) + auto str = StringValue::Get(value); + auto maybe_right = ffi::visit_expression_literal_string(state, KernelUtils::ToDeltaString(col_name), + DuckDBEngineError::AllocateError); + right = KernelUtils::UnpackResult(maybe_right, "VisitConstantFilter failed to visit_expression_literal_string"); + break; + } + + default: + break; // unsupported type + } + + // TODO support other comparison types? + switch (filter.comparison_type) { + case ExpressionType::COMPARE_LESSTHAN: + return visit_expression_lt(state, left, right); + case ExpressionType::COMPARE_LESSTHANOREQUALTO: + return visit_expression_le(state, left, right); + case ExpressionType::COMPARE_GREATERTHAN: + return visit_expression_gt(state, left, right); + case ExpressionType::COMPARE_GREATERTHANOREQUALTO: + return visit_expression_ge(state, left, right); + case ExpressionType::COMPARE_EQUAL: + return visit_expression_eq(state, left, right); + + default: + std::cout << " Unsupported operation: " << (int)filter.comparison_type << std::endl; + return ~0; // Unsupported operation + } +} + +uintptr_t PredicateVisitor::VisitAndFilter(const string &col_name, const ConjunctionAndFilter &filter, + ffi::KernelExpressionVisitorState *state) { + auto it = filter.child_filters.begin(); + auto end = filter.child_filters.end(); + auto get_next = [this, col_name, state, &it, &end]() -> uintptr_t { + if (it == end) { + return 0; + } + auto &child_filter = *it++; + return VisitFilter(col_name, *child_filter, state); + }; + auto eit = EngineIteratorFromCallable(get_next); + return visit_expression_and(state, &eit); +} + +uintptr_t PredicateVisitor::VisitFilter(const string &col_name, const TableFilter &filter, + ffi::KernelExpressionVisitorState *state) { + switch (filter.filter_type) { + case TableFilterType::CONSTANT_COMPARISON: + return VisitConstantFilter(col_name, static_cast(filter), state); + case TableFilterType::CONJUNCTION_AND: + return VisitAndFilter(col_name, static_cast(filter), state); + default: + throw NotImplementedException("Attempted to push down unimplemented filter type: '%s'", + EnumUtil::ToString(filter.filter_type)); + } +} + +}; // namespace duckdb diff --git a/extension/delta/src/functions/delta_scan.cpp b/extension/delta/src/functions/delta_scan.cpp new file mode 100644 index 00000000000..a01bd5f4c42 --- /dev/null +++ b/extension/delta/src/functions/delta_scan.cpp @@ -0,0 +1,628 @@ +#include "duckdb/function/table_function.hpp" + +#include "delta_functions.hpp" +#include "functions/delta_scan.hpp" +#include "duckdb/optimizer/filter_combiner.hpp" +#include "duckdb/planner/operator/logical_get.hpp" +#include "duckdb/main/extension_util.hpp" +#include "duckdb/catalog/catalog_entry/table_function_catalog_entry.hpp" +#include "duckdb/common/local_file_system.hpp" +#include "duckdb/common/types/data_chunk.hpp" +#include "duckdb/parser/expression/constant_expression.hpp" +#include "duckdb/parser/expression/function_expression.hpp" +#include "duckdb/parser/parsed_expression.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/planner/binder.hpp" +#include "duckdb/main/secret/secret_manager.hpp" + +#include +#include + +namespace duckdb { + +static void *allocate_string(const struct ffi::KernelStringSlice slice) { + return new string(slice.ptr, slice.len); +} + +static void visit_callback(ffi::NullableCvoid engine_context, struct ffi::KernelStringSlice path, int64_t size, + const ffi::DvInfo *dv_info, const struct ffi::CStringMap *partition_values) { + auto context = (DeltaSnapshot *)engine_context; + auto path_string = context->GetPath(); + StringUtil::RTrim(path_string, "/"); + path_string += "/" + KernelUtils::FromDeltaString(path); + + // First we append the file to our resolved files + context->resolved_files.push_back(DeltaSnapshot::ToDuckDBPath(path_string)); + context->metadata.emplace_back(make_uniq()); + + D_ASSERT(context->resolved_files.size() == context->metadata.size()); + + // Initialize the file metadata + context->metadata.back()->delta_snapshot_version = context->version; + context->metadata.back()->file_number = context->resolved_files.size() - 1; + + // Fetch the deletion vector + auto selection_vector_res = + ffi::selection_vector_from_dv(dv_info, context->extern_engine.get(), context->global_state.get()); + auto selection_vector = + KernelUtils::UnpackResult(selection_vector_res, "selection_vector_from_dv for path " + context->GetPath()); + if (selection_vector.ptr) { + context->metadata.back()->selection_vector = selection_vector; + } + + // Lookup all columns for potential hits in the constant map + case_insensitive_map_t constant_map; + for (const auto &col : context->names) { + auto key = KernelUtils::ToDeltaString(col); + auto *partition_val = (string *)ffi::get_from_map(partition_values, key, allocate_string); + if (partition_val) { + constant_map[col] = *partition_val; + delete partition_val; + } + } + context->metadata.back()->partition_map = std::move(constant_map); +} + +static void visit_data(void *engine_context, ffi::EngineData *engine_data, + const struct ffi::KernelBoolSlice selection_vec) { + ffi::visit_scan_data(engine_data, selection_vec, engine_context, visit_callback); +} + +static ffi::EngineBuilder *CreateBuilder(ClientContext &context, const string &path) { + ffi::EngineBuilder *builder; + + // For "regular" paths we early out with the default builder config + if (!StringUtil::StartsWith(path, "s3://")) { + auto interface_builder_res = + ffi::get_engine_builder(KernelUtils::ToDeltaString(path), DuckDBEngineError::AllocateError); + return KernelUtils::UnpackResult(interface_builder_res, "get_engine_interface_builder for path " + path); + } + + auto end_of_container = path.find('/', 5); + + if (end_of_container == string::npos) { + throw IOException("Invalid s3 url passed to delta scan: %s", path); + } + auto bucket = path.substr(5, end_of_container - 5); + auto path_in_bucket = path.substr(end_of_container); + + auto interface_builder_res = + ffi::get_engine_builder(KernelUtils::ToDeltaString(path), DuckDBEngineError::AllocateError); + builder = KernelUtils::UnpackResult(interface_builder_res, "get_engine_interface_builder for path " + path); + + // For S3 paths we need to trim the url, set the container, and fetch a potential secret + auto &secret_manager = SecretManager::Get(context); + auto transaction = CatalogTransaction::GetSystemCatalogTransaction(context); + + auto secret_match = secret_manager.LookupSecret(transaction, path, "s3"); + + // No secret: nothing left to do here! + if (!secret_match.HasMatch()) { + return builder; + } + const auto &kv_secret = dynamic_cast(*secret_match.secret_entry->secret); + + auto key_id = kv_secret.TryGetValue("key_id").ToString(); + auto secret = kv_secret.TryGetValue("secret").ToString(); + auto session_token = kv_secret.TryGetValue("session_token").ToString(); + auto region = kv_secret.TryGetValue("region").ToString(); + + if (key_id.empty() && secret.empty()) { + ffi::set_builder_option(builder, KernelUtils::ToDeltaString("skip_signature"), + KernelUtils::ToDeltaString("true")); + } + + if (!key_id.empty()) { + ffi::set_builder_option(builder, KernelUtils::ToDeltaString("aws_access_key_id"), + KernelUtils::ToDeltaString(key_id)); + } + if (!secret.empty()) { + ffi::set_builder_option(builder, KernelUtils::ToDeltaString("aws_secret_access_key"), + KernelUtils::ToDeltaString(secret)); + } + if (!session_token.empty()) { + ffi::set_builder_option(builder, KernelUtils::ToDeltaString("aws_session_token"), + KernelUtils::ToDeltaString(session_token)); + } + ffi::set_builder_option(builder, KernelUtils::ToDeltaString("aws_region"), KernelUtils::ToDeltaString(region)); + + return builder; +} + +DeltaSnapshot::DeltaSnapshot(ClientContext &context_p, const string &path) + : MultiFileList({ToDeltaPath(path)}, FileGlobOptions::ALLOW_EMPTY), context(context_p) { +} + +string DeltaSnapshot::GetPath() { + return GetPaths()[0]; +} + +string DeltaSnapshot::ToDuckDBPath(const string &raw_path) { + if (StringUtil::StartsWith(raw_path, "file://")) { + return raw_path.substr(7); + } + return raw_path; +} + +string DeltaSnapshot::ToDeltaPath(const string &raw_path) { + string path; + if (StringUtil::StartsWith(raw_path, "./")) { + LocalFileSystem fs; + path = fs.JoinPath(fs.GetWorkingDirectory(), raw_path.substr(2)); + path = "file://" + path; + } else { + path = raw_path; + } + + // Paths always end in a slash (kernel likes it that way for now) + if (path[path.size() - 1] != '/') { + path = path + '/'; + } + + return path; +} + +void DeltaSnapshot::Bind(vector &return_types, vector &names) { + if (!initialized) { + InitializeFiles(); + } + auto schema = SchemaVisitor::VisitSnapshotSchema(snapshot.get()); + for (const auto &field : *schema) { + names.push_back(field.first); + return_types.push_back(field.second); + } + // Store the bound names for resolving the complex filter pushdown later + this->names = names; +} + +string DeltaSnapshot::GetFile(idx_t i) { + if (!initialized) { + InitializeFiles(); + } + // We already have this file + if (i < resolved_files.size()) { + return resolved_files[i]; + } + + if (files_exhausted) { + return ""; + } + + while (i >= resolved_files.size()) { + auto have_scan_data_res = ffi::kernel_scan_data_next(scan_data_iterator.get(), this, visit_data); + + auto have_scan_data = TryUnpackKernelResult(have_scan_data_res); + + // kernel has indicated that we have no more data to scan + if (!have_scan_data) { + files_exhausted = true; + return ""; + } + } + + // The kernel scan visitor should have resolved a file OR returned + if (i >= resolved_files.size()) { + throw IOException("Delta Kernel seems to have failed to resolve a new file"); + } + + return resolved_files[i]; +} + +void DeltaSnapshot::InitializeFiles() { + auto path_slice = KernelUtils::ToDeltaString(paths[0]); + + // Register engine + auto interface_builder = CreateBuilder(context, paths[0]); + extern_engine = TryUnpackKernelResult(ffi::builder_build(interface_builder)); + + // Initialize Snapshot + snapshot = TryUnpackKernelResult(ffi::snapshot(path_slice, extern_engine.get())); + + // Create Scan + PredicateVisitor visitor(names, &table_filters); + scan = TryUnpackKernelResult(ffi::scan(snapshot.get(), extern_engine.get(), &visitor)); + + // Create GlobalState + global_state = ffi::get_global_scan_state(scan.get()); + + // Set version + this->version = ffi::version(snapshot.get()); + + // Create scan data iterator + scan_data_iterator = TryUnpackKernelResult(ffi::kernel_scan_data_init(extern_engine.get(), scan.get())); + + initialized = true; +} + +unique_ptr DeltaSnapshot::ComplexFilterPushdown(ClientContext &context, + const MultiFileReaderOptions &options, LogicalGet &get, + vector> &filters) { + FilterCombiner combiner(context); + for (const auto &filter : filters) { + combiner.AddFilter(filter->Copy()); + } + auto filterstmp = combiner.GenerateTableScanFilters(get.column_ids); + + // TODO: can/should we figure out if this filtered anything? + auto filtered_list = make_uniq(context, paths[0]); + filtered_list->table_filters = std::move(filterstmp); + filtered_list->names = names; + + return std::move(filtered_list); +} + +vector DeltaSnapshot::GetAllFiles() { + idx_t i = resolved_files.size(); + // TODO: this can probably be improved + while (!GetFile(i).empty()) { + i++; + } + return resolved_files; +} + +FileExpandResult DeltaSnapshot::GetExpandResult() { + // GetFile(1) will ensure at least the first 2 files are expanded if they are available + GetFile(1); + + if (resolved_files.size() > 1) { + return FileExpandResult::MULTIPLE_FILES; + } else if (resolved_files.size() == 1) { + return FileExpandResult::SINGLE_FILE; + } + + return FileExpandResult::NO_FILES; +} + +idx_t DeltaSnapshot::GetTotalFileCount() { + // TODO: this can probably be improved + idx_t i = resolved_files.size(); + while (!GetFile(i).empty()) { + i++; + } + return resolved_files.size(); +} + +unique_ptr DeltaMultiFileReader::CreateInstance() { + return std::move(make_uniq()); +} + +bool DeltaMultiFileReader::Bind(MultiFileReaderOptions &options, MultiFileList &files, + vector &return_types, vector &names, + MultiFileReaderBindData &bind_data) { + auto &delta_snapshot = dynamic_cast(files); + + delta_snapshot.Bind(return_types, names); + + // We need to parse this option + bool file_row_number_enabled = options.custom_options.find("file_row_number") != options.custom_options.end(); + if (file_row_number_enabled) { + bind_data.file_row_number_idx = names.size(); + return_types.emplace_back(LogicalType::BIGINT); + names.emplace_back("file_row_number"); + } else { + // TODO: this is a bogus ID? Change for flag indicating it should be enabled? + bind_data.file_row_number_idx = names.size(); + } + + return true; +}; + +void DeltaMultiFileReader::BindOptions(MultiFileReaderOptions &options, MultiFileList &files, + vector &return_types, vector &names, + MultiFileReaderBindData &bind_data) { + + // Disable all other multifilereader options + options.auto_detect_hive_partitioning = false; + options.hive_partitioning = false; + options.union_by_name = false; + + MultiFileReader::BindOptions(options, files, return_types, names, bind_data); + + auto demo_gen_col_opt = options.custom_options.find("delta_file_number"); + if (demo_gen_col_opt != options.custom_options.end()) { + if (demo_gen_col_opt->second.GetValue()) { + names.push_back("delta_file_number"); + return_types.push_back(LogicalType::UBIGINT); + } + } +} + +void DeltaMultiFileReader::FinalizeBind(const MultiFileReaderOptions &file_options, + const MultiFileReaderBindData &options, const string &filename, + const vector &local_names, const vector &global_types, + const vector &global_names, const vector &global_column_ids, + MultiFileReaderData &reader_data, ClientContext &context, + optional_ptr global_state) { + MultiFileReader::FinalizeBind(file_options, options, filename, local_names, global_types, global_names, + global_column_ids, reader_data, context, global_state); + + // Handle custom delta option set in MultiFileReaderOptions::custom_options + auto file_number_opt = file_options.custom_options.find("delta_file_number"); + if (file_number_opt != file_options.custom_options.end()) { + if (file_number_opt->second.GetValue()) { + D_ASSERT(global_state); + auto &delta_global_state = global_state->Cast(); + D_ASSERT(delta_global_state.delta_file_number_idx != DConstants::INVALID_INDEX); + + // We add the constant column for the delta_file_number option + // NOTE: we add a placeholder here, to demonstrate how we can also populate extra columns in the + // FinalizeChunk + reader_data.constant_map.emplace_back(delta_global_state.delta_file_number_idx, Value::UBIGINT(0)); + } + } + + // Get the metadata for this file + D_ASSERT(global_state->file_list); + const auto &snapshot = dynamic_cast(*global_state->file_list); + auto &file_metadata = snapshot.metadata[reader_data.file_list_idx.GetIndex()]; + + if (!file_metadata->partition_map.empty()) { + for (idx_t i = 0; i < global_column_ids.size(); i++) { + column_t col_id = global_column_ids[i]; + auto col_partition_entry = file_metadata->partition_map.find(global_names[col_id]); + if (col_partition_entry != file_metadata->partition_map.end()) { + // Todo: use https://github.com/delta-io/delta/blob/master/PROTOCOL.md#partition-value-serialization + auto maybe_value = Value(col_partition_entry->second).DefaultCastAs(global_types[i]); + reader_data.constant_map.emplace_back(i, maybe_value); + } + } + } +} + +unique_ptr DeltaMultiFileReader::CreateFileList(ClientContext &context, const vector &paths, + FileGlobOptions options) { + if (paths.size() != 1) { + throw BinderException("'delta_scan' only supports single path as input"); + } + + return make_uniq(context, paths[0]); +} + +// Generate the correct Selection Vector Based on the Raw delta KernelBoolSlice dv and the row_id_column +// TODO: this probably is slower than needed (we can do with less branches in the for loop for most cases) +static SelectionVector DuckSVFromDeltaSV(const ffi::KernelBoolSlice &dv, Vector row_id_column, idx_t count, + idx_t &select_count) { + D_ASSERT(row_id_column.GetType() == LogicalType::BIGINT); + + UnifiedVectorFormat data; + row_id_column.ToUnifiedFormat(count, data); + auto row_ids = UnifiedVectorFormat::GetData(data); + + SelectionVector result {count}; + idx_t current_select = 0; + for (idx_t i = 0; i < count; i++) { + auto row_id = row_ids[data.sel->get_index(i)]; + + // TODO: why are deletion vectors not spanning whole data? + if (row_id >= dv.len || dv.ptr[row_id]) { + result.data()[current_select] = i; + current_select++; + } + } + + select_count = current_select; + + return result; +} + +// Parses the columns that are used by the delta extension into +void DeltaMultiFileReaderGlobalState::SetColumnIdx(const string &column, idx_t idx) { + if (column == "file_row_number") { + file_row_number_idx = idx; + return; + } else if (column == "delta_file_number") { + delta_file_number_idx = idx; + return; + } + throw IOException("Unknown column '%s' found as required by the DeltaMultiFileReader"); +} + +unique_ptr DeltaMultiFileReader::InitializeGlobalState( + duckdb::ClientContext &context, const duckdb::MultiFileReaderOptions &file_options, + const duckdb::MultiFileReaderBindData &bind_data, const duckdb::MultiFileList &file_list, + const vector &global_types, const vector &global_names, + const vector &global_column_ids) { + vector extra_columns; + vector> mapped_columns; + + // Create a map of the columns that are in the projection + case_insensitive_map_t selected_columns; + for (idx_t i = 0; i < global_column_ids.size(); i++) { + auto global_id = global_column_ids[i]; + if (IsRowIdColumnId(global_id)) { + continue; + } + + auto &global_name = global_names[global_id]; + selected_columns.insert({global_name, i}); + } + + // TODO: only add file_row_number column if there are deletes + case_insensitive_map_t columns_to_map = { + {"file_row_number", LogicalType::BIGINT}, + }; + + // Add the delta_file_number column to the columns to map + auto demo_gen_col_opt = file_options.custom_options.find("delta_file_number"); + if (demo_gen_col_opt != file_options.custom_options.end()) { + if (demo_gen_col_opt->second.GetValue()) { + columns_to_map.insert({"delta_file_number", LogicalType::UBIGINT}); + } + } + + // Map every column to either a column in the projection, or add it to the extra columns if it doesn't exist + idx_t col_offset = 0; + for (const auto &required_column : columns_to_map) { + // First check if the column is in the projection + auto res = selected_columns.find(required_column.first); + if (res != selected_columns.end()) { + // The column is in the projection, no special handling is required; we simply store the index + mapped_columns.push_back({required_column.first, res->second}); + continue; + } + + // The column is NOT in the projection: it needs to be added as an extra_column + + // Calculate the index of the added column (extra columns are added after all other columns) + idx_t current_col_idx = global_column_ids.size() + col_offset++; + + // Add column to the map, to ensure the MultiFileReader can find it when processing the Chunk + mapped_columns.push_back({required_column.first, current_col_idx}); + + // Ensure the result DataChunk has a vector of the correct type to store this column + extra_columns.push_back(required_column.second); + } + + auto res = make_uniq(extra_columns, &file_list); + + // Parse all the mapped columns into the DeltaMultiFileReaderGlobalState for easy use; + for (const auto &mapped_column : mapped_columns) { + res->SetColumnIdx(mapped_column.first, mapped_column.second); + } + + return std::move(res); +} + +void DeltaMultiFileReader::CreateNameMapping(const string &file_name, const vector &local_types, + const vector &local_names, const vector &global_types, + const vector &global_names, + const vector &global_column_ids, + MultiFileReaderData &reader_data, const string &initial_file, + optional_ptr global_state) { + // First call the base implementation to do most mapping + MultiFileReader::CreateNameMapping(file_name, local_types, local_names, global_types, global_names, + global_column_ids, reader_data, initial_file, global_state); + + // Then we handle delta specific mapping + D_ASSERT(global_state); + auto &delta_global_state = global_state->Cast(); + + // Check if the file_row_number column is an "extra_column" which is not part of the projection + if (delta_global_state.file_row_number_idx >= global_column_ids.size()) { + D_ASSERT(delta_global_state.file_row_number_idx != DConstants::INVALID_INDEX); + + // Build the name map + case_insensitive_map_t name_map; + for (idx_t col_idx = 0; col_idx < local_names.size(); col_idx++) { + name_map[local_names[col_idx]] = col_idx; + } + + // Lookup the required column in the local map + auto entry = name_map.find("file_row_number"); + if (entry == name_map.end()) { + throw IOException("Failed to find the file_row_number column"); + } + + // Register the column to be scanned from this file + reader_data.column_ids.push_back(entry->second); + reader_data.column_mapping.push_back(delta_global_state.file_row_number_idx); + } + + // This may have changed: update it + reader_data.empty_columns = reader_data.column_ids.empty(); +} + +void DeltaMultiFileReader::FinalizeChunk(ClientContext &context, const MultiFileReaderBindData &bind_data, + const MultiFileReaderData &reader_data, DataChunk &chunk, + optional_ptr global_state) { + // Base class finalization first + MultiFileReader::FinalizeChunk(context, bind_data, reader_data, chunk, global_state); + + D_ASSERT(global_state); + auto &delta_global_state = global_state->Cast(); + D_ASSERT(delta_global_state.file_list); + + // Get the metadata for this file + const auto &snapshot = dynamic_cast(*global_state->file_list); + auto &metadata = snapshot.metadata[reader_data.file_list_idx.GetIndex()]; + + if (metadata->selection_vector.ptr && chunk.size() != 0) { + D_ASSERT(delta_global_state.file_row_number_idx != DConstants::INVALID_INDEX); + auto &file_row_number_column = chunk.data[delta_global_state.file_row_number_idx]; + + // Construct the selection vector using the file_row_number column and the raw selection vector from delta + idx_t select_count; + auto sv = DuckSVFromDeltaSV(metadata->selection_vector, file_row_number_column, chunk.size(), select_count); + chunk.Slice(sv, select_count); + } + + // Note: this demo function shows how we can use DuckDB's Binder create expression-based generated columns + if (delta_global_state.delta_file_number_idx != DConstants::INVALID_INDEX) { + //! Create Dummy expression (0 + file_number) + vector> child_expr; + child_expr.push_back(make_uniq(Value::UBIGINT(0))); + child_expr.push_back(make_uniq(Value::UBIGINT(7))); + unique_ptr expr = + make_uniq("+", std::move(child_expr), nullptr, nullptr, false, true); + + //! s dummy expression + auto binder = Binder::CreateBinder(context); + ExpressionBinder expr_binder(*binder, context); + auto bound_expr = expr_binder.Bind(expr, nullptr); + + //! Execute dummy expression into result column + ExpressionExecutor expr_executor(context); + expr_executor.AddExpression(*bound_expr); + + //! Execute the expression directly into the output Chunk + expr_executor.ExecuteExpression(chunk.data[delta_global_state.delta_file_number_idx]); + } +}; + +bool DeltaMultiFileReader::ParseOption(const string &key, const Value &val, MultiFileReaderOptions &options, + ClientContext &context) { + auto loption = StringUtil::Lower(key); + + if (loption == "delta_file_number") { + options.custom_options[loption] = val; + return true; + } + + // We need to capture this one to know whether to emit + if (loption == "file_row_number") { + options.custom_options[loption] = val; + return true; + } + + return MultiFileReader::ParseOption(key, val, options, context); +} +// +// DeltaMultiFileReaderBindData::DeltaMultiFileReaderBindData(DeltaSnapshot & delta_snapshot): +// current_snapshot(delta_snapshot){ +// +//} + +TableFunctionSet DeltaFunctions::GetDeltaScanFunction(DatabaseInstance &instance) { + // The delta_scan function is constructed by grabbing the parquet scan from the Catalog, then injecting the + // DeltaMultiFileReader into it to create a Delta-based multi file read + + auto &parquet_scan = ExtensionUtil::GetTableFunction(instance, "parquet_scan"); + auto parquet_scan_copy = parquet_scan.functions; + + for (auto &function : parquet_scan_copy.functions) { + // Register the MultiFileReader as the driver for reads + function.get_multi_file_reader = DeltaMultiFileReader::CreateInstance; + + // Unset all of these: they are either broken, very inefficient. + // TODO: implement/fix these + function.serialize = nullptr; + function.deserialize = nullptr; + function.statistics = nullptr; + function.table_scan_progress = nullptr; + function.cardinality = nullptr; + function.get_bind_info = nullptr; + + // Schema param is just confusing here + function.named_parameters.erase("schema"); + + // Demonstration of a generated column based on information from DeltaSnapshot + function.named_parameters["delta_file_number"] = LogicalType::BOOLEAN; + + function.name = "delta_scan"; + } + + parquet_scan_copy.name = "delta_scan"; + return parquet_scan_copy; +} + +} // namespace duckdb diff --git a/extension/delta/src/include/delta_extension.hpp b/extension/delta/src/include/delta_extension.hpp new file mode 100644 index 00000000000..d6b13f236b8 --- /dev/null +++ b/extension/delta/src/include/delta_extension.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "duckdb.hpp" + +namespace duckdb { + +class DeltaExtension : public Extension { +public: + void Load(DuckDB &db) override; + std::string Name() override; +}; + +} // namespace duckdb diff --git a/extension/delta/src/include/delta_functions.hpp b/extension/delta/src/include/delta_functions.hpp new file mode 100644 index 00000000000..4f819cbfd63 --- /dev/null +++ b/extension/delta/src/include/delta_functions.hpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// delta_functions.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/parser/parsed_data/create_table_function_info.hpp" + +namespace duckdb { + +class DeltaFunctions { +public: + static vector GetTableFunctions(DatabaseInstance &instance); + +private: + static TableFunctionSet GetDeltaScanFunction(DatabaseInstance &instance); +}; +} // namespace duckdb diff --git a/extension/delta/src/include/delta_utils.hpp b/extension/delta/src/include/delta_utils.hpp new file mode 100644 index 00000000000..4b478c998f6 --- /dev/null +++ b/extension/delta/src/include/delta_utils.hpp @@ -0,0 +1,155 @@ +#pragma once + +#include "delta_kernel_ffi.hpp" +#include "duckdb/planner/filter/constant_filter.hpp" +#include "duckdb/planner/filter/conjunction_filter.hpp" +#include "duckdb/common/enum_util.hpp" +#include + +// TODO: clean up this file as we go + +namespace duckdb { + +// SchemaVisitor is used to parse the schema of a Delta table from the Kernel +class SchemaVisitor { +public: + using FieldList = child_list_t; + + static unique_ptr VisitSnapshotSchema(ffi::SharedSnapshot *snapshot); + +private: + unordered_map> inflight_lists; + uintptr_t next_id = 1; + + typedef void(SimpleTypeVisitorFunction)(void *, uintptr_t, ffi::KernelStringSlice); + + template + static SimpleTypeVisitorFunction *VisitSimpleType() { + return (SimpleTypeVisitorFunction *)&VisitSimpleTypeImpl; + } + template + static void VisitSimpleTypeImpl(SchemaVisitor *state, uintptr_t sibling_list_id, ffi::KernelStringSlice name) { + state->AppendToList(sibling_list_id, name, TypeId); + } + + static void VisitDecimal(SchemaVisitor *state, uintptr_t sibling_list_id, ffi::KernelStringSlice name, + uint8_t precision, uint8_t scale); + static uintptr_t MakeFieldList(SchemaVisitor *state, uintptr_t capacity_hint); + static void VisitStruct(SchemaVisitor *state, uintptr_t sibling_list_id, ffi::KernelStringSlice name, + uintptr_t child_list_id); + static void VisitArray(SchemaVisitor *state, uintptr_t sibling_list_id, ffi::KernelStringSlice name, + bool contains_null, uintptr_t child_list_id); + static void VisitMap(SchemaVisitor *state, uintptr_t sibling_list_id, ffi::KernelStringSlice name, + bool contains_null, uintptr_t child_list_id); + + uintptr_t MakeFieldListImpl(uintptr_t capacity_hint); + void AppendToList(uintptr_t id, ffi::KernelStringSlice name, LogicalType &&child); + unique_ptr TakeFieldList(uintptr_t id); +}; + +// Allocator for errors that the kernel might throw +struct DuckDBEngineError : ffi::EngineError { + // Allocate a DuckDBEngineError, function ptr passed to kernel for error allocation + static ffi::EngineError *AllocateError(ffi::KernelError etype, ffi::KernelStringSlice msg); + // Convert a kernel error enum to a string + static string KernelErrorEnumToString(ffi::KernelError err); + + // Throw the error as an IOException + [[noreturn]] void Throw(string from_info); + + // The error message from Kernel + string error_message; +}; + +// RAII wrapper that returns ownership of a kernel pointer to kernel when it goes out of +// scope. Similar to std::unique_ptr. but does not define operator->() and does not require the +// kernel type to be complete. +template +struct UniqueKernelPointer { + UniqueKernelPointer() : ptr(nullptr), free(nullptr) { + } + + // Takes ownership of a pointer with associated deleter. + UniqueKernelPointer(KernelType *ptr, void (*free)(KernelType *)) : ptr(ptr), free(free) { + } + + // movable but not copyable + UniqueKernelPointer(UniqueKernelPointer &&other) : ptr(other.ptr) { + other.ptr = nullptr; + } + UniqueKernelPointer &operator=(UniqueKernelPointer &&other) { + std::swap(ptr, other.ptr); + std::swap(free, other.free); + return *this; + } + UniqueKernelPointer(const UniqueKernelPointer &) = delete; + UniqueKernelPointer &operator=(const UniqueKernelPointer &) = delete; + + ~UniqueKernelPointer() { + if (ptr && free) { + free(ptr); + } + } + + KernelType *get() const { + return ptr; + } + +private: + KernelType *ptr; + void (*free)(KernelType *) = nullptr; +}; + +// Syntactic sugar around the different kernel types +template +struct TemplatedUniqueKernelPointer : public UniqueKernelPointer { + TemplatedUniqueKernelPointer() : UniqueKernelPointer() {}; + TemplatedUniqueKernelPointer(KernelType *ptr) : UniqueKernelPointer(ptr, DeleteFunction) {}; +}; + +typedef TemplatedUniqueKernelPointer KernelSnapshot; +typedef TemplatedUniqueKernelPointer KernelExternEngine; +typedef TemplatedUniqueKernelPointer KernelScan; +typedef TemplatedUniqueKernelPointer KernelGlobalScanState; +typedef TemplatedUniqueKernelPointer KernelScanDataIterator; + +struct KernelUtils { + static ffi::KernelStringSlice ToDeltaString(const string &str); + static string FromDeltaString(const struct ffi::KernelStringSlice slice); + static vector FromDeltaBoolSlice(const struct ffi::KernelBoolSlice slice); + + // TODO: all kernel results need to be unpacked, not doing so will result in an error. This should be cleaned up + template + static T UnpackResult(ffi::ExternResult result, const string &from_where) { + if (result.tag == ffi::ExternResult::Tag::Err) { + if (result.err._0) { + auto error_cast = static_cast(result.err._0); + error_cast->Throw(from_where); + } else { + throw IOException("Hit DeltaKernel FFI error (from: %s): Hit error, but error was nullptr", + from_where.c_str()); + } + } else if (result.tag == ffi::ExternResult::Tag::Ok) { + return result.ok._0; + } + throw IOException("Invalid error ExternResult tag found!"); + } +}; + +class PredicateVisitor : public ffi::EnginePredicate { +public: + PredicateVisitor(const vector &column_names, optional_ptr filters); + +private: + unordered_map column_filters; + + static uintptr_t VisitPredicate(PredicateVisitor *predicate, ffi::KernelExpressionVisitorState *state); + + uintptr_t VisitConstantFilter(const string &col_name, const ConstantFilter &filter, + ffi::KernelExpressionVisitorState *state); + uintptr_t VisitAndFilter(const string &col_name, const ConjunctionAndFilter &filter, + ffi::KernelExpressionVisitorState *state); + uintptr_t VisitFilter(const string &col_name, const TableFilter &filter, ffi::KernelExpressionVisitorState *state); +}; + +} // namespace duckdb diff --git a/extension/delta/src/include/functions/delta_scan.hpp b/extension/delta/src/include/functions/delta_scan.hpp new file mode 100644 index 00000000000..32d681fa3db --- /dev/null +++ b/extension/delta/src/include/functions/delta_scan.hpp @@ -0,0 +1,146 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// functions/delta_scan.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "delta_utils.hpp" +#include "duckdb/common/multi_file_reader.hpp" + +namespace duckdb { + +struct DeltaFileMetaData { + DeltaFileMetaData() {}; + + // No copying pls + DeltaFileMetaData(const DeltaFileMetaData &) = delete; + DeltaFileMetaData &operator=(const DeltaFileMetaData &) = delete; + + ~DeltaFileMetaData() { + if (selection_vector.ptr) { + ffi::drop_bool_slice(selection_vector); + } + } + + idx_t delta_snapshot_version = DConstants::INVALID_INDEX; + idx_t file_number = DConstants::INVALID_INDEX; + ffi::KernelBoolSlice selection_vector = {nullptr, 0}; + case_insensitive_map_t partition_map; +}; + +//! The DeltaSnapshot implements the MultiFileList API to allow injecting it into the regular DuckDB parquet scan +struct DeltaSnapshot : public MultiFileList { + DeltaSnapshot(ClientContext &context, const string &path); + string GetPath(); + static string ToDuckDBPath(const string &raw_path); + static string ToDeltaPath(const string &raw_path); + + //! MultiFileList API +public: + void Bind(vector &return_types, vector &names); + unique_ptr ComplexFilterPushdown(ClientContext &context, const MultiFileReaderOptions &options, + LogicalGet &get, vector> &filters) override; + vector GetAllFiles() override; + FileExpandResult GetExpandResult() override; + idx_t GetTotalFileCount() override; + +protected: + //! Get the i-th expanded file + string GetFile(idx_t i) override; + +protected: + // TODO: How to guarantee we only call this after the filter pushdown? + void InitializeFiles(); + + template + T TryUnpackKernelResult(ffi::ExternResult result) { + return KernelUtils::UnpackResult( + result, StringUtil::Format("While trying to read from delta table: '%s'", paths[0])); + } + + // TODO: change back to protected +public: + idx_t version; + + //! Delta Kernel Structures + KernelSnapshot snapshot; + KernelExternEngine extern_engine; + KernelScan scan; + KernelGlobalScanState global_state; + KernelScanDataIterator scan_data_iterator; + + //! Names + vector names; + + //! Metadata map for files + vector> metadata; + + //! Current file list resolution state + bool initialized = false; + bool files_exhausted = false; + vector resolved_files; + TableFilterSet table_filters; + + ClientContext &context; +}; + +struct DeltaMultiFileReaderGlobalState : public MultiFileReaderGlobalState { + DeltaMultiFileReaderGlobalState(vector extra_columns_p, optional_ptr file_list_p) + : MultiFileReaderGlobalState(extra_columns_p, file_list_p) { + } + //! The idx of the file number column in the result chunk + idx_t delta_file_number_idx = DConstants::INVALID_INDEX; + //! The idx of the file_row_number column in the result chunk + idx_t file_row_number_idx = DConstants::INVALID_INDEX; + + void SetColumnIdx(const string &column, idx_t idx); +}; + +struct DeltaMultiFileReader : public MultiFileReader { + static unique_ptr CreateInstance(); + //! Return a DeltaSnapshot + unique_ptr CreateFileList(ClientContext &context, const vector &paths, + FileGlobOptions options) override; + + //! Override the regular parquet bind using the MultiFileReader Bind. The bind from these are what DuckDB's file + //! readers will try read + bool Bind(MultiFileReaderOptions &options, MultiFileList &files, vector &return_types, + vector &names, MultiFileReaderBindData &bind_data) override; + + //! Override the Options bind + void BindOptions(MultiFileReaderOptions &options, MultiFileList &files, vector &return_types, + vector &names, MultiFileReaderBindData &bind_data) override; + + void CreateNameMapping(const string &file_name, const vector &local_types, + const vector &local_names, const vector &global_types, + const vector &global_names, const vector &global_column_ids, + MultiFileReaderData &reader_data, const string &initial_file, + optional_ptr global_state) override; + + unique_ptr + InitializeGlobalState(ClientContext &context, const MultiFileReaderOptions &file_options, + const MultiFileReaderBindData &bind_data, const MultiFileList &file_list, + const vector &global_types, const vector &global_names, + const vector &global_column_ids) override; + + void FinalizeBind(const MultiFileReaderOptions &file_options, const MultiFileReaderBindData &options, + const string &filename, const vector &local_names, + const vector &global_types, const vector &global_names, + const vector &global_column_ids, MultiFileReaderData &reader_data, + ClientContext &context, optional_ptr global_state) override; + + //! Override the FinalizeChunk method + void FinalizeChunk(ClientContext &context, const MultiFileReaderBindData &bind_data, + const MultiFileReaderData &reader_data, DataChunk &chunk, + optional_ptr global_state) override; + + //! Override the ParseOption call to parse delta_scan specific options + bool ParseOption(const string &key, const Value &val, MultiFileReaderOptions &options, + ClientContext &context) override; +}; + +} // namespace duckdb diff --git a/extension/delta/vcpkg.json b/extension/delta/vcpkg.json new file mode 100644 index 00000000000..85936bf44cc --- /dev/null +++ b/extension/delta/vcpkg.json @@ -0,0 +1,5 @@ +{ + "dependencies": [ + "openssl" + ] +} \ No newline at end of file diff --git a/extension/excel/CMakeLists.txt b/extension/excel/CMakeLists.txt deleted file mode 100644 index 5e9df318cbf..00000000000 --- a/extension/excel/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12) - -project(ExcelExtension) - -include_directories(numformat/include) -include_directories(include) -add_subdirectory(numformat) - -build_static_extension(excel excel_extension.cpp ${NUMFORMAT_OBJECT_FILES}) -set(PARAMETERS "-warnings") -build_loadable_extension(excel ${PARAMETERS} excel_extension.cpp - ${NUMFORMAT_OBJECT_FILES}) - -install( - TARGETS excel_extension - EXPORT "${DUCKDB_EXPORT_SET}" - LIBRARY DESTINATION "${INSTALL_LIB_DIR}" - ARCHIVE DESTINATION "${INSTALL_LIB_DIR}") diff --git a/extension/excel/excel_config.py b/extension/excel/excel_config.py deleted file mode 100644 index 6509469ab04..00000000000 --- a/extension/excel/excel_config.py +++ /dev/null @@ -1,16 +0,0 @@ -import os - -# list all include directories -include_directories = [ - os.path.sep.join(x.split('/')) for x in ['extension/excel/include', 'extension/excel/numformat/include'] -] -# source files -source_files = [os.path.sep.join(x.split('/')) for x in ['extension/excel/excel_extension.cpp']] -source_files += [ - os.path.sep.join(x.split('/')) - for x in [ - 'extension/excel/numformat/nf_calendar.cpp', - 'extension/excel/numformat/nf_localedata.cpp', - 'extension/excel/numformat/nf_zformat.cpp', - ] -] diff --git a/extension/excel/excel_extension.cpp b/extension/excel/excel_extension.cpp deleted file mode 100644 index 3391be26332..00000000000 --- a/extension/excel/excel_extension.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#define DUCKDB_EXTENSION_MAIN - -#include "duckdb.hpp" -#include "duckdb/common/exception.hpp" -#include "duckdb/common/string_util.hpp" -#include "duckdb/function/scalar_function.hpp" -#include "duckdb/main/extension_util.hpp" -#include "excel_extension.hpp" -#include "nf_calendar.h" -#include "nf_localedata.h" -#include "nf_zformat.h" - -namespace duckdb { - -static std::string GetNumberFormatString(std::string &format, double num_value) { - duckdb_excel::LocaleData locale_data; - duckdb_excel::ImpSvNumberInputScan input_scan(&locale_data); - uint16_t nCheckPos; - std::string out_str; - - duckdb_excel::SvNumberformat num_format(format, &locale_data, &input_scan, nCheckPos); - - if (!num_format.GetOutputString(num_value, out_str)) { - return out_str; - } - - return ""; -} - -static string_t NumberFormatScalarFunction(Vector &result, double num_value, string_t format) { - try { - string in_str = format.GetString(); - string out_str = GetNumberFormatString(in_str, num_value); - - if (out_str.length() > 0) { - auto result_string = StringVector::EmptyString(result, out_str.size()); - auto result_data = result_string.GetDataWriteable(); - memcpy(result_data, out_str.c_str(), out_str.size()); - result_string.Finalize(); - return result_string; - } else { - auto result_string = StringVector::EmptyString(result, 0); - result_string.Finalize(); - return result_string; - } - } catch (...) { - throw InternalException("Unexpected result for number format"); - } - - return string_t(); -} - -static void NumberFormatFunction(DataChunk &args, ExpressionState &state, Vector &result) { - auto &number_vector = args.data[0]; - auto &format_vector = args.data[1]; - BinaryExecutor::Execute( - number_vector, format_vector, result, args.size(), - [&](double value, string_t format) { return NumberFormatScalarFunction(result, value, format); }); -} - -void ExcelExtension::Load(DuckDB &db) { - auto &db_instance = *db.instance; - - ScalarFunction text_func("text", {LogicalType::DOUBLE, LogicalType::VARCHAR}, LogicalType::VARCHAR, - NumberFormatFunction); - ExtensionUtil::RegisterFunction(db_instance, text_func); - - ScalarFunction excel_text_func("excel_text", {LogicalType::DOUBLE, LogicalType::VARCHAR}, LogicalType::VARCHAR, - NumberFormatFunction); - ExtensionUtil::RegisterFunction(db_instance, excel_text_func); -} - -std::string ExcelExtension::Name() { - return "excel"; -} - -} // namespace duckdb - -extern "C" { - -DUCKDB_EXTENSION_API void excel_init(duckdb::DatabaseInstance &db) { - duckdb::DuckDB db_wrapper(db); - db_wrapper.LoadExtension(); -} - -DUCKDB_EXTENSION_API const char *excel_version() { - return duckdb::DuckDB::LibraryVersion(); -} -} - -#ifndef DUCKDB_EXTENSION_MAIN -#error DUCKDB_EXTENSION_MAIN not defined -#endif diff --git a/extension/excel/numformat/CMakeLists.txt b/extension/excel/numformat/CMakeLists.txt deleted file mode 100644 index b916052358f..00000000000 --- a/extension/excel/numformat/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -include_directories(include) - -add_library(numformat OBJECT nf_calendar.cpp nf_localedata.cpp nf_zformat.cpp) - -set(NUMFORMAT_OBJECT_FILES - ${NUMFORMAT_OBJECT_FILES} $ - PARENT_SCOPE) - -disable_target_warnings(numformat) diff --git a/extension/excel/numformat/LICENSE b/extension/excel/numformat/LICENSE deleted file mode 100644 index bfb8d6b857b..00000000000 --- a/extension/excel/numformat/LICENSE +++ /dev/null @@ -1,118 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/extension/excel/numformat/include/nf_calendar.h b/extension/excel/numformat/include/nf_calendar.h deleted file mode 100644 index e12044d74e6..00000000000 --- a/extension/excel/numformat/include/nf_calendar.h +++ /dev/null @@ -1,842 +0,0 @@ -/************************************************************** - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - *************************************************************/ - -#ifndef _NF_CALENDAR_H -#define _NF_CALENDAR_H - -#include -#include -#include -#include "duckdb/common/vector.hpp" - - -namespace duckdb_excel { - - -// ------------------------------ define.h ------------------------------------------------- - -typedef int8_t sal_Char; -typedef int8_t sal_sChar; -typedef uint8_t sal_uChar; -typedef int8_t sal_Int8; -typedef uint8_t sal_uInt8; -typedef int16_t sal_Int16; -typedef uint16_t sal_uInt16; -typedef int32_t sal_Int32; -typedef uint32_t sal_uInt32; -typedef int64_t sal_Int64; -typedef uint64_t sal_uInt64; -typedef unsigned long sal_uLong; -typedef wchar_t sal_Unicode; -typedef std::wstring String; -typedef sal_Int64 sal_IntPtr; -typedef sal_uInt64 sal_uIntPtr; - -#define SAL_CONST_INT64(x) x -#define SAL_CONST_UINT64(x) x - -#define TOOLS_DLLPUBLIC -#define SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS 0x000e -#define SV_NUMBERFORMATTER_VERSION 0x000e -#if defined(ULONG_MAX) -#undef ULONG_MAX -#endif -#define ULONG_MAX 0xffffffffffffffffUL - -// Format types -#ifndef NUMBERFORMAT_ALL -// also defined in com/sun/star/util/NumberFormat.hpp -//! => put in single .idl file and include here -#define NUMBERFORMAT_ALL 0x000 /// Just for Output of total list, not a real format type -#define NUMBERFORMAT_DEFINED 0x001 /// Format defined by user -#define NUMBERFORMAT_DATE 0x002 /// Number as date -#define NUMBERFORMAT_TIME 0x004 /// Number as time -#define NUMBERFORMAT_CURRENCY 0x008 /// Number as currency -#define NUMBERFORMAT_NUMBER 0x010 /// Any "normal" number format -#define NUMBERFORMAT_SCIENTIFIC 0x020 /// Number as scientific -#define NUMBERFORMAT_FRACTION 0x040 /// Number as fraction -#define NUMBERFORMAT_PERCENT 0x080 /// Number as percent -#define NUMBERFORMAT_TEXT 0x100 /// Text format -#define NUMBERFORMAT_DATETIME 0x006 /// Number as date and time -#define NUMBERFORMAT_LOGICAL 0x400 /// Number as boolean value -#define NUMBERFORMAT_UNDEFINED 0x800 /// Format undefined yet in analyzing -#endif -#define NUMBERFORMAT_ENTRY_NOT_FOUND (sal_uInt32)(0xffffffff) /// MAX_ULONG -#define STRING_NOTFOUND ((uint16_t)-1) -#define SAL_MAX_ENUM 0x7fffffff -#define SAL_MAX_UINT16 ((sal_uInt16)0xFFFF) -#define SAL_MAX_INT32 ((sal_Int32)0x7FFFFFFF) -#if defined(_WIN32) -#define localtime_r(A, B) localtime_s(B, A) -#define gmtime_r(A, B) gmtime_s(B, A) -#endif - -#define EraseAllChars(A, B) A.erase(std::remove(A.begin(), A.end(), B), A.end()) -#define EraseTrailingChars(A, B) A.erase(A.find_last_not_of(B) + 1, std::string::npos) -#define EraseLeadingChars(A, B) A.erase(0, std::min(A.find_first_not_of(B), A.size() - 1)) -#define ConvertToUpper(A) std::transform(A.begin(), A.end(), A.begin(), ::toupper) -#define ConvertToLower(A) std::transform(A.begin(), A.end(), A.begin(), ::tolower) - -namespace CalendarFieldIndex { -/// Get AmPmValue. -const short AM_PM = 0; -/// Get/Set day of month [1-31]. -const short DAY_OF_MONTH = 1; -/// Get day of week [0-6]. -const short DAY_OF_WEEK = 2; -/// Get day of year. -const short DAY_OF_YEAR = 3; -const short DST_OFFSET = 4; -/// Get/Set hour [0-23]. -const short CFI_HOUR = 5; -/// Get/Set minute [0-59]. -const short CFI_MINUTE = 6; -/// Get/Set second [0-59]. -const short CFI_SECOND = 7; -/// Get/Set milliseconds [0-999]. -const short CFI_MILLISECOND = 8; -/// Get week of month. -const short WEEK_OF_MONTH = 9; -/// Get week of year. -const short WEEK_OF_YEAR = 10; -/// Get/Set year. -const short CFI_YEAR = 11; -const short CFI_MONTH = 12; -/// Get/Set era, for example, 0:= Before Christ, 1:= After Christ. -const short ERA = 13; -/// Get/Set time zone offset in minutes, e.g. [-14*60..14*60] -const short ZONE_OFFSET = 14; - -/// Total number of fields for < OpenOffice 3.1 -const short FIELD_COUNT = 15; - -const short ZONE_OFFSET_SECOND_MILLIS = 15; - -const short DST_OFFSET_SECOND_MILLIS = 16; - -const short FIELD_COUNT2 = 17; - -} // namespace CalendarFieldIndex - -enum NfEvalDateFormat { - /** DateFormat only from International, default. */ - NF_EVALDATEFORMAT_INTL, - - /** DateFormat only from date format passed to function (if any). - If no date format is passed then the DateFormat is taken from International. */ - NF_EVALDATEFORMAT_FORMAT, - - /** First try the DateFormat from International. If it doesn't match a - valid date try the DateFormat from the date format passed. */ - NF_EVALDATEFORMAT_INTL_FORMAT, - - /** First try the DateFormat from the date format passed. If it doesn't - match a valid date try the DateFormat from International. */ - NF_EVALDATEFORMAT_FORMAT_INTL -}; - -enum DateFormat { MDY, DMY, YMD }; - -enum LocaleIndentifier { - LocaleId_en_US = 0, - LocaleId_fr_FR, - - LocaleIndentifierCount -}; -typedef LocaleIndentifier LanguageType; - -namespace CalendarDisplayCode { -/// Day of month, one or two digits, no leading zero. -const long SHORT_DAY = 1; -/// Day of month, two digits, with leading zero. -const long LONG_DAY = 2; -/// Day of week, abbreviated name. -const long SHORT_DAY_NAME = 3; -/// Day of week, full name. -const long LONG_DAY_NAME = 4; - -/// Month of year, one or two digits, no leading zero. -const long SHORT_MONTH = 5; -/// Month of year, with leading zero. -const long LONG_MONTH = 6; -/// Full month name. -const long SHORT_MONTH_NAME = 7; -/// Abbreviated month name. -const long LONG_MONTH_NAME = 8; - -/// Year, two digits. -const long SHORT_YEAR = 9; -/// Year, four digits. -const long LONG_YEAR = 10; -/// Full era name, for example, "Before Christ" or "Anno Dominus". -const long SHORT_ERA = 11; -/// Abbreviated era name, for example, BC or AD. -const long LONG_ERA = 12; -/// Combined short year and era, order depends on locale/calendar. -const long SHORT_YEAR_AND_ERA = 13; -/// Combined full year and era, order depends on locale/calendar. -const long LONG_YEAR_AND_ERA = 14; - -/// Short quarter, for example, "Q1" -const long SHORT_QUARTER = 15; -/// Long quarter, for example, "1st quarter" -const long LONG_QUARTER = 16; -} // namespace CalendarDisplayCode - -namespace reservedWords { -/// "true" -const short TRUE_WORD = 0; -/// "false" -const short FALSE_WORD = 1; -/// "1st quarter" -const short QUARTER1_WORD = 2; -/// "2nd quarter" -const short QUARTER2_WORD = 3; -/// "3rd quarter" -const short QUARTER3_WORD = 4; -/// "4th quarter" -const short QUARTER4_WORD = 5; -/// "above" -const short ABOVE_WORD = 6; -/// "below" -const short BELOW_WORD = 7; -/// "Q1" -const short QUARTER1_ABBREVIATION = 8; -/// "Q2" -const short QUARTER2_ABBREVIATION = 9; -/// "Q3" -const short QUARTER3_ABBREVIATION = 10; -/// "Q4" -const short QUARTER4_ABBREVIATION = 11; - -//! Yes, this must be the count of known reserved words and one more than -//! the maximum number used above! -/// Count of known reserved words. -const short COUNT = 12; -} // namespace reservedWords - -enum rtl_math_StringFormat { - /** Like sprintf() %E. - */ - rtl_math_StringFormat_E, - - /** Like sprintf() %f. - */ - rtl_math_StringFormat_F, - - /** Like sprintf() %G, 'F' or 'E' format is used depending on which one is - more compact. - */ - rtl_math_StringFormat_G, - - /** Automatic, 'F' or 'E' format is used depending on the numeric value to - be formatted. - */ - rtl_math_StringFormat_Automatic, - - /** @internal - */ - rtl_math_StringFormat_FORCE_EQUAL_SIZE = SAL_MAX_ENUM -}; - -enum rtl_math_DecimalPlaces { - /** Value to be used with rtl_math_StringFormat_Automatic. - */ - rtl_math_DecimalPlaces_Max = 0x7ffffff, - - /** Value to be used with rtl_math_StringFormat_G. - In fact the same value as rtl_math_DecimalPlaces_Max, just an alias for - better understanding. - */ - rtl_math_DecimalPlaces_DefaultSignificance = 0x7ffffff -}; - -/** Rounding modes for rtl_math_round. - */ -enum rtl_math_RoundingMode { - /** Like HalfUp, but corrects roundoff errors, preferred. - */ - rtl_math_RoundingMode_Corrected, - - /** Floor of absolute value, signed return (commercial). - */ - rtl_math_RoundingMode_Down, - - /** Ceil of absolute value, signed return (commercial). - */ - rtl_math_RoundingMode_Up, - - /** Floor of signed value. - */ - rtl_math_RoundingMode_Floor, - - /** Ceil of signed value. - */ - rtl_math_RoundingMode_Ceiling, - - /** Frac <= 0.5 ? floor of abs : ceil of abs, signed return. - */ - rtl_math_RoundingMode_HalfDown, - - /** Frac < 0.5 ? floor of abs : ceil of abs, signed return (mathematical). - */ - rtl_math_RoundingMode_HalfUp, - - /** IEEE rounding mode (statistical). - */ - rtl_math_RoundingMode_HalfEven, - - /** @internal - */ - rtl_math_RoundingMode_FORCE_EQUAL_SIZE = SAL_MAX_ENUM -}; - -enum NfKeywordIndex -{ - NF_KEY_NONE = 0, - NF_KEY_E, // exponential symbol - NF_KEY_AMPM, // AM/PM - NF_KEY_AP, // a/p - NF_KEY_MI, // minute (!) - NF_KEY_MMI, // minute 02 (!) - NF_KEY_M, // month (!) - NF_KEY_MM, // month 02 (!) - NF_KEY_MMM, // month short name - NF_KEY_MMMM, // month long name - NF_KEY_H, // hour - NF_KEY_HH, // hour 02 - NF_KEY_S, // second - NF_KEY_SS, // second 02 - NF_KEY_Q, // quarter - NF_KEY_QQ, // quarter 02 - NF_KEY_D, // day of month - NF_KEY_DD, // day of month 02 - NF_KEY_DDD, // day of week short - NF_KEY_DDDD, // day of week long - NF_KEY_YY, // year two digits - NF_KEY_YYYY, // year four digits - NF_KEY_NN, // day of week short - NF_KEY_NNNN, // day of week long with separator - NF_KEY_CCC, // currency bank symbol (old version) - NF_KEY_GENERAL, // General / Standard - NF_KEY_LASTOLDKEYWORD = NF_KEY_GENERAL, - NF_KEY_NNN, // day of week long without separator, as of version 6, 10.10.97 - NF_KEY_WW, // week of year, as of version 8, 19.06.98 - NF_KEY_MMMMM, // first letter of month name - NF_KEY_LASTKEYWORD = NF_KEY_MMMMM, - NF_KEY_UNUSED4, - NF_KEY_QUARTER, // was quarter word, not used anymore from SRC631 on (26.04.01) - NF_KEY_TRUE, // boolean true - NF_KEY_FALSE, // boolean false - NF_KEY_BOOLEAN, // boolean - NF_KEY_COLOR, // color - NF_KEY_FIRSTCOLOR, - NF_KEY_BLACK = NF_KEY_FIRSTCOLOR, // you do know colors, don't you? - NF_KEY_BLUE, - NF_KEY_GREEN, - NF_KEY_CYAN, - NF_KEY_RED, - NF_KEY_MAGENTA, - NF_KEY_BROWN, - NF_KEY_GREY, - NF_KEY_YELLOW, - NF_KEY_WHITE, - NF_KEY_LASTCOLOR = NF_KEY_WHITE, - NF_KEY_LASTKEYWORD_SO5 = NF_KEY_LASTCOLOR, - //! Keys from here on can't be saved in SO5 file format and MUST be - //! converted to string which means losing any information. - NF_KEY_AAA, // abbreviated day name from Japanese Xcl, same as DDD or NN English - NF_KEY_AAAA, // full day name from Japanese Xcl, same as DDDD or NNN English - NF_KEY_EC, // E non-gregorian calendar year without preceding 0 - NF_KEY_EEC, // EE non-gregorian calendar year with preceding 0 (two digit) - NF_KEY_G, // abbreviated era name, latin characters M T S or H for Gengou calendar - NF_KEY_GG, // abbreviated era name - NF_KEY_GGG, // full era name - NF_KEY_R, // acts as EE (Xcl) => GR==GEE, GGR==GGEE, GGGR==GGGEE - NF_KEY_RR, // acts as GGGEE (Xcl) - NF_KEY_THAI_T, // Thai T modifier, speciality of Thai Excel, only used with Thai locale and converted to [NatNum1] - NF_KEYWORD_ENTRIES_COUNT -}; - -class NfKeywordTable -{ - typedef duckdb::vector Keywords_t; - Keywords_t m_keywords; - -public: - NfKeywordTable() : m_keywords(NF_KEYWORD_ENTRIES_COUNT) {}; - virtual ~NfKeywordTable() {} - - String & operator[] (Keywords_t::size_type n) { return m_keywords[n]; } - const String & operator[] (Keywords_t::size_type n) const { return m_keywords[n]; } -}; - -/// Number formatter's symbol types of a token, if not key words, which are >0 -enum NfSymbolType -{ - NF_SYMBOLTYPE_STRING = -1, // literal string in output - NF_SYMBOLTYPE_DEL = -2, // special character - NF_SYMBOLTYPE_BLANK = -3, // blank for '_' - NF_SYMBOLTYPE_STAR = -4, // *-character - NF_SYMBOLTYPE_DIGIT = -5, // digit place holder - NF_SYMBOLTYPE_DECSEP = -6, // decimal separator - NF_SYMBOLTYPE_THSEP = -7, // group AKA thousand separator - NF_SYMBOLTYPE_EXP = -8, // exponent E - NF_SYMBOLTYPE_FRAC = -9, // fraction / - NF_SYMBOLTYPE_EMPTY = -10, // deleted symbols - NF_SYMBOLTYPE_FRACBLANK = -11, // delimiter between integer and fraction - NF_SYMBOLTYPE_COMMENT = -12, // comment is following - NF_SYMBOLTYPE_CURRENCY = -13, // currency symbol - NF_SYMBOLTYPE_CURRDEL = -14, // currency symbol delimiter [$] - NF_SYMBOLTYPE_CURREXT = -15, // currency symbol extension -xxx - NF_SYMBOLTYPE_CALENDAR = -16, // calendar ID - NF_SYMBOLTYPE_CALDEL = -17, // calendar delimiter [~] - NF_SYMBOLTYPE_DATESEP = -18, // date separator - NF_SYMBOLTYPE_TIMESEP = -19, // time separator - NF_SYMBOLTYPE_TIME100SECSEP = -20, // time 100th seconds separator - NF_SYMBOLTYPE_PERCENT = -21 // percent % -}; - - -// ------------------------- digitgroupingiterator.hxx ----------------------------------------- - -class DigitGroupingIterator -{ - duckdb::vector maGroupings; - sal_Int32 mnGroup; // current active grouping - sal_Int32 mnDigits; // current active digits per group - sal_Int32 mnNextPos; // position (in digits) of next grouping - - void setInfinite() - { - mnGroup = maGroupings.size(); - } - - bool isInfinite() const - { - return mnGroup >= (sal_Int32)maGroupings.size(); - } - - sal_Int32 getGrouping() const - { - if (mnGroup < (sal_Int32)maGroupings.size()) - { - sal_Int32 n = maGroupings[mnGroup]; - //OSL_ENSURE( 0 <= n && n <= SAL_MAX_UINT16, "DigitGroupingIterator::getGrouping: far out"); - if (n < 0) - n = 0; // sanitize ... - else if (n > SAL_MAX_UINT16) - n = SAL_MAX_UINT16; // limit for use with uint16_t - return n; - } - return 0; - } - - void setPos() - { - // someone might be playing jokes on us, so check for overflow - if (mnNextPos <= SAL_MAX_INT32 - mnDigits) - mnNextPos += mnDigits; - } - - void setDigits() - { - sal_Int32 nPrev = mnDigits; - mnDigits = getGrouping(); - if (!mnDigits) - { - mnDigits = nPrev; - setInfinite(); - } - setPos(); - } - - void initGrouping() - { - mnDigits = 3; // just in case of constructed with empty grouping - mnGroup = 0; - mnNextPos = 0; - setDigits(); - } - - // not implemented, prevent usage - DigitGroupingIterator(); - DigitGroupingIterator( const DigitGroupingIterator & ); - DigitGroupingIterator & operator=( const DigitGroupingIterator & ); - -public: - - explicit DigitGroupingIterator(duckdb::vector& digit_grouping) - : maGroupings(digit_grouping) - { - initGrouping(); - } - - /** Advance iterator to next grouping. */ - DigitGroupingIterator & advance() - { - if (isInfinite()) - setPos(); - else - { - ++mnGroup; - setDigits(); - } - return *this; - } - - /** Obtain current grouping. Always > 0. */ - sal_Int32 get() const - { - return mnDigits; - } - - /** The next position (in integer digits) from the right where to insert a - group separator. */ - sal_Int32 getPos() - { - return mnNextPos; - } - - /** Reset iterator to start again from the right beginning. */ - void reset() - { - initGrouping(); - } -}; - - -// ------------------------------------------ date.hxx ------------------------------------------------------- - -class ResId; - -enum DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, - SATURDAY, SUNDAY }; - -class TOOLS_DLLPUBLIC Date -{ -private: - sal_uInt32 nDate; - -public: - Date(); - Date( const ResId & rResId ); - Date( sal_uInt32 _nDate ) { Date::nDate = _nDate; } - Date( const Date& rDate ) - { nDate = rDate.nDate; } - Date( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) - { nDate = ( sal_uInt32( nDay % 100 ) ) + - ( ( sal_uInt32( nMonth % 100 ) ) * 100 ) + - ( ( sal_uInt32( nYear % 10000 ) ) * 10000); } - - void SetDate( sal_uInt32 nNewDate ) { nDate = nNewDate; } - sal_uInt32 GetDate() const { return nDate; } - - void SetDay( sal_uInt16 nNewDay ); - void SetMonth( sal_uInt16 nNewMonth ); - void SetYear( sal_uInt16 nNewYear ); - sal_uInt16 GetDay() const { return (sal_uInt16)(nDate % 100); } - sal_uInt16 GetMonth() const { return (sal_uInt16)((nDate / 100) % 100); } - sal_uInt16 GetYear() const { return (sal_uInt16)(nDate / 10000); } - - DayOfWeek GetDayOfWeek() const; - sal_uInt16 GetDayOfYear() const; - /** nMinimumNumberOfDaysInWeek: how many days of a week must reside in the - first week of a year. */ - sal_uInt16 GetWeekOfYear( DayOfWeek eStartDay = MONDAY, - sal_Int16 nMinimumNumberOfDaysInWeek = 4 ) const; - - sal_uInt16 GetDaysInMonth() const; - sal_uInt16 GetDaysInYear() const { return (IsLeapYear()) ? 366 : 365; } - bool IsLeapYear() const; - bool IsValid() const; - - bool IsBetween( const Date& rFrom, const Date& rTo ) const - { return ((nDate >= rFrom.nDate) && - (nDate <= rTo.nDate)); } - - bool operator ==( const Date& rDate ) const - { return (nDate == rDate.nDate); } - bool operator !=( const Date& rDate ) const - { return (nDate != rDate.nDate); } - bool operator >( const Date& rDate ) const - { return (nDate > rDate.nDate); } - bool operator <( const Date& rDate ) const - { return (nDate < rDate.nDate); } - bool operator >=( const Date& rDate ) const - { return (nDate >= rDate.nDate); } - bool operator <=( const Date& rDate ) const - { return (nDate <= rDate.nDate); } - - Date& operator =( const Date& rDate ) - { nDate = rDate.nDate; return *this; } - Date& operator +=( long nDays ); - Date& operator -=( long nDays ); - Date& operator ++(); - Date& operator --(); -#ifndef MPW33 - Date operator ++( int ); - Date operator --( int ); -#endif - - TOOLS_DLLPUBLIC friend Date operator +( const Date& rDate, long nDays ); - TOOLS_DLLPUBLIC friend Date operator -( const Date& rDate, long nDays ); - TOOLS_DLLPUBLIC friend long operator -( const Date& rDate1, const Date& rDate2 ); - - static long DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ); - -}; - - -// ----------------------------------------- time.hxx ----------------------------------------------------- - -class TOOLS_DLLPUBLIC Time -{ -private: - sal_Int32 nTime; - -public: - Time(); - Time( const ResId & rResId ); - Time( sal_Int32 _nTime ) { Time::nTime = _nTime; } - Time( const Time& rTime ); - Time( sal_uIntPtr nHour, sal_uIntPtr nMin, - sal_uIntPtr nSec = 0, sal_uIntPtr n100Sec = 0 ); - - void SetTime( sal_Int32 nNewTime ) { nTime = nNewTime; } - sal_Int32 GetTime() const { return nTime; } - - void SetHour( sal_uInt16 nNewHour ); - void SetMin( sal_uInt16 nNewMin ); - void SetSec( sal_uInt16 nNewSec ); - void Set100Sec( sal_uInt16 nNew100Sec ); - sal_uInt16 GetHour() const - { sal_uIntPtr nTempTime = (nTime >= 0) ? nTime : nTime*-1; - return (sal_uInt16)(nTempTime / 1000000); } - sal_uInt16 GetMin() const - { sal_uIntPtr nTempTime = (nTime >= 0) ? nTime : nTime*-1; - return (sal_uInt16)((nTempTime / 10000) % 100); } - sal_uInt16 GetSec() const - { sal_uIntPtr nTempTime = (nTime >= 0) ? nTime : nTime*-1; - return (sal_uInt16)((nTempTime / 100) % 100); } - sal_uInt16 Get100Sec() const - { sal_uIntPtr nTempTime = (nTime >= 0) ? nTime : nTime*-1; - return (sal_uInt16)(nTempTime % 100); } - - sal_Int32 GetMSFromTime() const; - void MakeTimeFromMS( sal_Int32 nMS ); - - /// 12 hours == 0.5 days - double GetTimeInDays() const; - - bool IsBetween( const Time& rFrom, const Time& rTo ) const - { return ((nTime >= rFrom.nTime) && (nTime <= rTo.nTime)); } - - bool IsEqualIgnore100Sec( const Time& rTime ) const; - - bool operator ==( const Time& rTime ) const - { return (nTime == rTime.nTime); } - bool operator !=( const Time& rTime ) const - { return (nTime != rTime.nTime); } - bool operator >( const Time& rTime ) const - { return (nTime > rTime.nTime); } - bool operator <( const Time& rTime ) const - { return (nTime < rTime.nTime); } - bool operator >=( const Time& rTime ) const - { return (nTime >= rTime.nTime); } - bool operator <=( const Time& rTime ) const - { return (nTime <= rTime.nTime); } - - static Time GetUTCOffset(); - static sal_uIntPtr GetSystemTicks(); // Elapsed time - static sal_uIntPtr GetProcessTicks(); // CPU time - - void ConvertToUTC() { *this -= Time::GetUTCOffset(); } - void ConvertToLocalTime() { *this += Time::GetUTCOffset(); } - - Time& operator =( const Time& rTime ); - Time operator -() const - { return Time( nTime * -1 ); } - Time& operator +=( const Time& rTime ); - Time& operator -=( const Time& rTime ); - TOOLS_DLLPUBLIC friend Time operator +( const Time& rTime1, const Time& rTime2 ); - TOOLS_DLLPUBLIC friend Time operator -( const Time& rTime1, const Time& rTime2 ); -}; - - -// --------------------------------------------- datetime.hxx --------------------------------------------------- - -class TOOLS_DLLPUBLIC DateTime : public Date, public Time -{ -public: - DateTime() : Date(), Time() {} - DateTime( const DateTime& rDateTime ) : - Date( rDateTime ), Time( rDateTime ) {} - DateTime( const Date& rDate ) : Date( rDate ), Time(0) {} - DateTime( const Time& rTime ) : Date(0), Time( rTime ) {} - DateTime( const Date& rDate, const Time& rTime ) : - Date( rDate ), Time( rTime ) {} - - bool IsBetween( const DateTime& rFrom, - const DateTime& rTo ) const; - - bool IsEqualIgnore100Sec( const DateTime& rDateTime ) const - { - if ( Date::operator!=( rDateTime ) ) - return false; - return Time::IsEqualIgnore100Sec( rDateTime ); - } - - bool operator ==( const DateTime& rDateTime ) const - { return (Date::operator==( rDateTime ) && - Time::operator==( rDateTime )); } - bool operator !=( const DateTime& rDateTime ) const - { return (Date::operator!=( rDateTime ) || - Time::operator!=( rDateTime )); } - bool operator >( const DateTime& rDateTime ) const; - bool operator <( const DateTime& rDateTime ) const; - bool operator >=( const DateTime& rDateTime ) const; - bool operator <=( const DateTime& rDateTime ) const; - - long GetSecFromDateTime( const Date& rDate ) const; - void MakeDateTimeFromSec( const Date& rDate, sal_uIntPtr nSec ); - - void ConvertToUTC() { *this -= Time::GetUTCOffset(); } - void ConvertToLocalTime() { *this += Time::GetUTCOffset(); } - - DateTime& operator +=( long nDays ) - { Date::operator+=( nDays ); return *this; } - DateTime& operator -=( long nDays ) - { Date::operator-=( nDays ); return *this; } - DateTime& operator +=( double fTimeInDays ); - DateTime& operator -=( double fTimeInDays ) - { return operator+=( -fTimeInDays ); } - DateTime& operator +=( const Time& rTime ); - DateTime& operator -=( const Time& rTime ); - - TOOLS_DLLPUBLIC friend DateTime operator +( const DateTime& rDateTime, long nDays ); - TOOLS_DLLPUBLIC friend DateTime operator -( const DateTime& rDateTime, long nDays ); - TOOLS_DLLPUBLIC friend DateTime operator +( const DateTime& rDateTime, double fTimeInDays ); - TOOLS_DLLPUBLIC friend DateTime operator -( const DateTime& rDateTime, double fTimeInDays ) - { return operator+( rDateTime, -fTimeInDays ); } - TOOLS_DLLPUBLIC friend DateTime operator +( const DateTime& rDateTime, const Time& rTime ); - TOOLS_DLLPUBLIC friend DateTime operator -( const DateTime& rDateTime, const Time& rTime ); - TOOLS_DLLPUBLIC friend double operator -( const DateTime& rDateTime1, const DateTime& rDateTime2 ); - TOOLS_DLLPUBLIC friend long operator -( const DateTime& rDateTime, const Date& rDate ) - { return (const Date&) rDateTime - rDate; } - - DateTime& operator =( const DateTime& rDateTime ); - - void GetWin32FileDateTime( sal_uInt32 & rLower, sal_uInt32 & rUpper ); - static DateTime CreateFromWin32FileDateTime( const sal_uInt32 & rLower, const sal_uInt32 & rUpper ); -}; - -inline DateTime& DateTime::operator =( const DateTime& rDateTime ) -{ - Date::operator=( rDateTime ); - Time::operator=( rDateTime ); - return *this; -} - - -// ---------------------------------------- calendar.hxx ----------------------------------------------------------- - -struct Era { - sal_Int32 year; - sal_Int32 month; - sal_Int32 day; -}; - -const sal_Int16 FIELD_INDEX_COUNT = CalendarFieldIndex::FIELD_COUNT2; - -class LocaleData; - -class Calendar { -public: - // Constructors - Calendar(LocaleData *pFormatter); - Calendar(Era *_eraArray); - void init(Era *_eraArray); - - ~Calendar(); - - void setValue(sal_Int16 nFieldIndex, sal_Int16 nValue); - sal_Int16 getValue(sal_Int16 nFieldIndex); - bool isValid(); - std::wstring getDisplayName(sal_Int16 nCalendarDisplayIndex, sal_Int16 nIdx, sal_Int16 nNameType); - - // Methods in XExtendedCalendar - std::wstring getDisplayString(sal_Int32 nCalendarDisplayCode, sal_Int16 nNativeNumberMode); - void setDateTime(double timeInDays); - double getDateTime(); - double getLocalDateTime(); - void setLocalDateTime(double nTimeInDays); - DateTime getEpochStart() { - return aEpochStart; - } - Date *GetNullDate() const { - return pNullDate; - } - inline void setGregorianDateTime(const DateTime &rDateTime) { - setLocalDateTime(rDateTime - aEpochStart); - } - /// set reference date for offset calculation - void ChangeNullDate(const sal_uInt16 nDay, const sal_uInt16 nMonth, - const sal_uInt16 nYear); // exchanges reference date - -protected: - Era *eraArray; - // NativeNumberSupplier aNatNum; - sal_uInt32 fieldSet; - sal_Int16 fieldValue[FIELD_INDEX_COUNT]; - -private: - LocaleData *pFormatter; - // Calendar aCalendar; - - DateTime aEpochStart; - Date *pNullDate; // 30Dec1899 - double timeInDays; - - /** Submit fieldSetValue array according to fieldSet. */ - void submitFields(); - /** Submit fieldSetValue array according to fieldSet, plus YMDhms if >=0, - plus zone and DST if != 0 */ - void submitValues(sal_Int32 nYear, sal_Int32 nMonth, sal_Int32 nDay, sal_Int32 nHour, sal_Int32 nMinute, - sal_Int32 nSecond, sal_Int32 nMilliSecond, sal_Int32 nZone, sal_Int32 nDST); - /** Obtain combined field values for timezone offset (minutes+secondmillis) - in milliseconds and whether fields were set. */ - bool getZoneOffset(sal_Int32 &o_nOffset) const; - /** Obtain combined field values for DST offset (minutes+secondmillis) in - milliseconds and whether fields were set. */ - bool getDSTOffset(sal_Int32 &o_nOffset) const; - /** Used by getZoneOffset() and getDSTOffset(). Parent is - CalendarFieldIndex for offset in minutes, child is CalendarFieldIndex - for offset in milliseconds. */ - bool getCombinedOffset(sal_Int32 &o_nOffset, sal_Int16 nParentFieldIndex, sal_Int16 nChildFieldIndex) const; - sal_Int32 getCombinedOffsetInMillis(sal_Int16 nParentFieldIndex, sal_Int16 nChildFieldIndex); - sal_Int32 getZoneOffsetInMillis(); - sal_Int32 getDSTOffsetInMillis(); -}; - -} // namespace duckdb_excel - -#endif // _NF_CALENDAR_H diff --git a/extension/excel/numformat/include/nf_localedata.h b/extension/excel/numformat/include/nf_localedata.h deleted file mode 100644 index 7e920571ad8..00000000000 --- a/extension/excel/numformat/include/nf_localedata.h +++ /dev/null @@ -1,220 +0,0 @@ -#ifndef _NF_LOCALEDATA_H -#define _NF_LOCALEDATA_H - -#include -#include "duckdb/common/vector.hpp" -#include -#include "nf_calendar.h" -#include "nf_zformat.h" - - -namespace duckdb_excel { - -#define MLD_ABBRVFULLNAME_CHECK_INDEX_RANGE(A, B) \ - if (B < 0 || B >= (sal_Int32)m_locale_list[m_cur_locale_id].A.size()) \ - return L"" -#define MLD_ABBRVFULLNAME_GET_FULL_NAME(A, B) m_locale_list[m_cur_locale_id].A[B].full_name -#define MLD_ABBRVFULLNAME_GET_ABBRV_NAME(A, B) m_locale_list[m_cur_locale_id].A[B].abbrv_name -#define MLD_ABBRVFULLNAME_GET_SIZE(A) m_locale_list[m_cur_locale_id].A.size() - -struct SeparatorInfo { - std::wstring date; - std::wstring thousand; - std::wstring decimal; - std::wstring time; - std::wstring time100sec; - std::wstring list; - std::wstring longdatedayofweek; - std::wstring longdateday; - std::wstring longdatemonth; - std::wstring longdateyear; -}; - -struct CurrencyInfo { - std::wstring currency_symbol; // "$" - std::wstring bank_symbol; // "USD" - std::wstring currency_name; // "US Dollar" - int32_t decimal_places; // 2 -}; - -struct AbbrvFullNameInfo { - std::wstring id; - std::wstring abbrv_name; - std::wstring full_name; -}; - -struct FormatCodeInfo { - std::wstring fixed_format_key1; - std::wstring scientific_format_key1; - std::wstring percent_format_key1; - std::wstring currency_format_key1; - std::wstring date_format_key1; - std::wstring date_format_key9; - std::wstring datetime_format_key1; -}; - -struct LocaleInfo { - SeparatorInfo seperators; - // std::wstring num_thousand_separator; // ',' - duckdb::vector digit_grouping; // {3, 0} or {3, 2, 0} (India and Bhutan) - std::wstring cur_currency_id; // "USD" - std::map currency; - std::wstring time_am; - std::wstring time_pm; - DateFormat date_format; - duckdb::vector months_of_year; - duckdb::vector days_of_week; - std::wstring reserved_words[reservedWords::COUNT]; - FormatCodeInfo format_codes; - duckdb::vector eras; - -public: - std::wstring &getCurrentCurrencyId() { - return cur_currency_id; - } - void setCurrentCurrencyId(std::wstring ¤cy_id) { - cur_currency_id = currency_id; - } -}; - -class Calendar; -class ImpSvNumberInputScan; -class ImpSvNumberformatScan; - -class LocaleData { -public: - LocaleData(); - ~LocaleData(); - - void LoadLocaleData(); - LocaleIndentifier GetLocaleId() { - return m_cur_locale_id; - } - void SetLocaleId(LocaleIndentifier locale_id) { - m_cur_locale_id = locale_id; - } - Calendar *GetCalendar() { - return m_calendar_ptr; - } - - NfEvalDateFormat GetEvalDateFormat() { - return m_eval_date_format; - } - void SetEvalDateFormat(NfEvalDateFormat eval_date_format) { - m_eval_date_format = eval_date_format; - } - - std::wstring &GetDateSep() { - return m_locale_list[m_cur_locale_id].seperators.date; - } - std::wstring &GetNumThousandSep() { - return m_locale_list[m_cur_locale_id].seperators.thousand; - } - std::wstring &GetNumDecimalSep() { - return m_locale_list[m_cur_locale_id].seperators.decimal; - } - std::wstring &getTimeSep() { - return m_locale_list[m_cur_locale_id].seperators.time; - } - std::wstring &getTime100SecSep() { - return m_locale_list[m_cur_locale_id].seperators.time100sec; - } - std::wstring &getLongDateMonthSep() { - return m_locale_list[m_cur_locale_id].seperators.longdatemonth; - } - std::wstring &getLongDateDayOfWeekSep() { - return m_locale_list[m_cur_locale_id].seperators.longdatedayofweek; - } - std::wstring &getLongDateDaySep() { - return m_locale_list[m_cur_locale_id].seperators.longdateday; - } - - duckdb::vector &getDigitGrouping() { - return m_locale_list[m_cur_locale_id].digit_grouping; - } - - ImpSvNumberformatScan *GetFormatScanner() { - return m_num_format_scan_ptr; - } - - std::wstring &getCurrSymbol() { - return m_locale_list[m_cur_locale_id] - .currency[m_locale_list[m_cur_locale_id].getCurrentCurrencyId()] - .currency_symbol; - } - std::wstring &getCurrBankSymbol() { - return m_locale_list[m_cur_locale_id] - .currency[m_locale_list[m_cur_locale_id].getCurrentCurrencyId()] - .bank_symbol; - } - - std::wstring &getTimeAM() { - return m_locale_list[m_cur_locale_id].time_am; - } - std::wstring &getTimePM() { - return m_locale_list[m_cur_locale_id].time_pm; - } - - DateFormat getDateFormat() { - return m_locale_list[m_cur_locale_id].date_format; - } - DateFormat getLongDateFormat() { - return m_locale_list[m_cur_locale_id].date_format; - } - int32_t getMonthsOfYearSize() { - return MLD_ABBRVFULLNAME_GET_SIZE(months_of_year); - } - std::wstring getMonthsOfYearFullName(int16_t idx) { - MLD_ABBRVFULLNAME_CHECK_INDEX_RANGE(months_of_year, idx); - return MLD_ABBRVFULLNAME_GET_FULL_NAME(months_of_year, idx); - } - std::wstring getMonthsOfYearAbbrvName(int16_t idx) { - MLD_ABBRVFULLNAME_CHECK_INDEX_RANGE(months_of_year, idx); - return MLD_ABBRVFULLNAME_GET_ABBRV_NAME(months_of_year, idx); - } - int32_t getDayOfWeekSize() { - return MLD_ABBRVFULLNAME_GET_SIZE(days_of_week); - } - std::wstring getDayOfWeekFullName(int16_t idx) { - MLD_ABBRVFULLNAME_CHECK_INDEX_RANGE(days_of_week, idx); - return MLD_ABBRVFULLNAME_GET_FULL_NAME(days_of_week, idx); - } - std::wstring getDayOfWeekAbbrvName(int16_t idx) { - MLD_ABBRVFULLNAME_CHECK_INDEX_RANGE(days_of_week, idx); - return MLD_ABBRVFULLNAME_GET_ABBRV_NAME(days_of_week, idx); - } - - std::wstring getReservedWord(int16_t idx) { - if (idx < 0 || idx >= reservedWords::COUNT) - return L""; - return m_locale_list[m_cur_locale_id].reserved_words[idx]; - } - - std::wstring &getFormatCodeNumberStandard() { - return m_locale_list[m_cur_locale_id].format_codes.fixed_format_key1; - } - - int32_t getEraSize() { - return MLD_ABBRVFULLNAME_GET_SIZE(eras); - } - std::wstring getEraFullName(int16_t idx) { - MLD_ABBRVFULLNAME_CHECK_INDEX_RANGE(eras, idx); - return MLD_ABBRVFULLNAME_GET_FULL_NAME(eras, idx); - } - std::wstring getEraAbbrvName(int16_t idx) { - MLD_ABBRVFULLNAME_CHECK_INDEX_RANGE(eras, idx); - return MLD_ABBRVFULLNAME_GET_ABBRV_NAME(eras, idx); - } - -private: - LocaleIndentifier m_cur_locale_id; - LocaleInfo m_locale_list[LocaleIndentifierCount]; - NfEvalDateFormat m_eval_date_format; - Calendar *m_calendar_ptr; - - ImpSvNumberformatScan *m_num_format_scan_ptr; -}; - -} // namespace duckdb_excel - -#endif // _NF_LOCALEDATA_H diff --git a/extension/excel/numformat/include/nf_zformat.h b/extension/excel/numformat/include/nf_zformat.h deleted file mode 100644 index 9e8f4dfbd2e..00000000000 --- a/extension/excel/numformat/include/nf_zformat.h +++ /dev/null @@ -1,1008 +0,0 @@ -/************************************************************** - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - *************************************************************/ - -#ifndef _NF_ZFORMAT_H -#define _NF_ZFORMAT_H - -#include -#include "nf_calendar.h" -#include "nf_localedata.h" - - -namespace duckdb_excel { - -class Date; -class SvNumberformat; - -#define SV_MAX_ANZ_INPUT_STRINGS 20 // max count of substrings in input scanner - - -class LocaleData; - -class ImpSvNumberInputScan -{ -public: - ImpSvNumberInputScan( LocaleData* pFormatter ); - ~ImpSvNumberInputScan(); - -/*!*/ void ChangeIntl(); // MUST be called if language changes - - /// convert input string to number - bool IsNumberFormat( - const String& rString, /// input string - short& F_Type, /// format type (in + out) - double& fOutNumber, /// value determined (out) - const SvNumberformat* pFormat = NULL /// optional a number format to which compare against - ); - - /// after IsNumberFormat: get decimal position - short GetDecPos() const { return nDecPos; } - /// after IsNumberFormat: get count of numeric substrings in input string - sal_uInt16 GetAnzNums() const { return nAnzNums; } - - /// set threshold of two-digit year input - void SetYear2000( sal_uInt16 nVal ) { nYear2000 = nVal; } - /// get threshold of two-digit year input - sal_uInt16 GetYear2000() const { return nYear2000; } - -private: - LocaleData* pFormatter; // SvNumberFormatter * - String* pUpperMonthText; // Array of month names, uppercase - String* pUpperAbbrevMonthText; // Array of month names, abbreviated, uppercase - String* pUpperDayText; // Array of day of week names, uppercase - String* pUpperAbbrevDayText; // Array of day of week names, abbreviated, uppercase - String aUpperCurrSymbol; // Currency symbol, uppercase - bool bTextInitialized; // Whether days and months are initialized - // Variables for provisional results: - String sStrArray[SV_MAX_ANZ_INPUT_STRINGS]; // Array of scanned substrings - bool IsNum[SV_MAX_ANZ_INPUT_STRINGS]; // Whether a substring is numeric - sal_uInt16 nNums[SV_MAX_ANZ_INPUT_STRINGS]; // Sequence of offsets to numeric strings - sal_uInt16 nAnzStrings; // Total count of scanned substrings - sal_uInt16 nAnzNums; // Count of numeric substrings - bool bDecSepInDateSeps; // True <=> DecSep in {.,-,/,DateSep} - sal_uInt8 nMatchedAllStrings; // Scan...String() matched all substrings, - // bit mask of nMatched... constants - - static const sal_uInt8 nMatchedEndString; // 0x01 - static const sal_uInt8 nMatchedMidString; // 0x02 - static const sal_uInt8 nMatchedStartString; // 0x04 - static const sal_uInt8 nMatchedVirgin; // 0x08 - static const sal_uInt8 nMatchedUsedAsReturn; // 0x10 - - int nSign; // Sign of number - short nMonth; // Month (1..x) if date - // negative => short format - short nMonthPos; // 1 = front, 2 = middle - // 3 = end - sal_uInt16 nTimePos; // Index of first time separator (+1) - short nDecPos; // Index of substring containing "," (+1) - short nNegCheck; // '( )' for negative - short nESign; // Sign of exponent - short nAmPm; // +1 AM, -1 PM, 0 if none - short nLogical; // -1 => False, 1 => True - sal_uInt16 nThousand; // Count of group (AKA thousand) separators - sal_uInt16 nPosThousandString; // Position of concatenaded 000,000,000 string - short eScannedType; // Scanned type - short eSetType; // Preset Type - - sal_uInt16 nStringScanNumFor; // Fixed strings recognized in - // pFormat->NumFor[nNumForStringScan] - short nStringScanSign; // Sign resulting of FixString - sal_uInt16 nYear2000; // Two-digit threshold - // Year as 20xx - // default 18 - // number <= nYear2000 => 20xx - // number > nYear2000 => 19xx - sal_uInt16 nTimezonePos; // Index of timezone separator (+1) - sal_uInt8 nMayBeIso8601; // 0:=dontknowyet, 1:=yes, 2:=no - - void Reset(); // Reset all variables before start of analysis - - void InitText(); // Init of months and days of week - - double StringToDouble( - const String& rStr, - bool bForceFraction = false ); - - bool NextNumberStringSymbol( // Next number/string symbol - const sal_Unicode*& pStr, - String& rSymbol ); - - bool SkipThousands( // Concatenate ,000,23 blocks - const sal_Unicode*& pStr, // in input to 000123 - String& rSymbol ); - - void NumberStringDivision( // Divide numbers/strings into - const String& rString ); // arrays and variables above. - // Leading blanks and blanks - // after numbers are thrown away - - - // optimized substring versions - - static inline bool StringContains( // Whether rString contains rWhat at nPos - const String& rWhat, - const String& rString, - uint16_t nPos ) - { // mostly used with one character - if ( rWhat.size() <= 0 || nPos >= rString.size() || rWhat.at(0) != rString.at(nPos) ) - return false; - return StringContainsImpl( rWhat, rString, nPos ); - } - static inline bool StringPtrContains( // Whether pString contains rWhat at nPos - const String& rWhat, - const sal_Unicode* pString, - uint16_t nPos ) // nPos MUST be a valid offset from pString - { // mostly used with one character - if ( rWhat.at(0) != *(pString+nPos) ) - return false; - return StringPtrContainsImpl( rWhat, pString, nPos ); - } - static bool StringContainsImpl( //! DO NOT use directly - const String& rWhat, - const String& rString, - uint16_t nPos ); - static bool StringPtrContainsImpl( //! DO NOT use directly - const String& rWhat, - const sal_Unicode* pString, - uint16_t nPos ); - - - static inline bool SkipChar( // Skip a special character - sal_Unicode c, - const String& rString, - uint16_t& nPos ); - static inline void SkipBlanks( // Skip blank - const String& rString, - uint16_t& nPos ); - static inline bool SkipString( // Jump over rWhat in rString at nPos - const String& rWhat, - const String& rString, - uint16_t& nPos ); - - inline bool GetThousandSep( // Recognizes exactly ,111 as group separator - const String& rString, - uint16_t& nPos, - sal_uInt16 nStringPos ); - short GetLogical( // Get boolean value - const String& rString ); - short GetMonth( // Get month and advance string position - const String& rString, - uint16_t& nPos ); - int GetDayOfWeek( // Get day of week and advance string position - const String& rString, - uint16_t& nPos ); - bool GetCurrency( // Get currency symbol and advance string position - const String& rString, - uint16_t& nPos, - const SvNumberformat* pFormat = NULL ); // optional number format to match against - bool GetTimeAmPm( // Get symbol AM or PM and advance string position - const String& rString, - uint16_t& nPos ); - inline bool GetDecSep( // Get decimal separator and advance string position - const String& rString, - uint16_t& nPos ); - inline bool GetTime100SecSep( // Get hundredth seconds separator and advance string position - const String& rString, - uint16_t& nPos ); - int GetSign( // Get sign and advance string position - const String& rString, // Including special case '(' - uint16_t& nPos ); - short GetESign( // Get sign of exponent and advance string position - const String& rString, - uint16_t& nPos ); - - inline bool GetNextNumber( // Get next number as array offset - sal_uInt16& i, - sal_uInt16& j ); - - void GetTimeRef( // Converts time -> double (only decimals) - double& fOutNumber, // result as double - sal_uInt16 nIndex, // Index of hour in input - sal_uInt16 nAnz ); // Count of time substrings in input - sal_uInt16 ImplGetDay ( sal_uInt16 nIndex ); // Day input, 0 if no match - sal_uInt16 ImplGetMonth( sal_uInt16 nIndex ); // Month input, zero based return, NumberOfMonths if no match - sal_uInt16 ImplGetYear ( sal_uInt16 nIndex ); // Year input, 0 if no match - bool GetDateRef( // Conversion of date to number - double& fDays, // OUT: days diff to null date - sal_uInt16& nCounter, // Count of date substrings - const SvNumberformat* pFormat = NULL ); // optional number format to match against - - bool ScanStartString( // Analyze start of string - const String& rString, - const SvNumberformat* pFormat = NULL ); - bool ScanMidString( // Analyze middle substring - const String& rString, - sal_uInt16 nStringPos, - const SvNumberformat* pFormat = NULL ); - bool ScanEndString( // Analyze end of string - const String& rString, - const SvNumberformat* pFormat = NULL ); - - // Whether input may be a ISO 8601 date format, yyyy-mm-dd... - // checks if at least 3 numbers and first number>31 - bool MayBeIso8601(); - - // Compare rString to substring of array indexed by nString - // nString == 0xFFFF => last substring - bool ScanStringNumFor( - const String& rString, - uint16_t nPos, - const SvNumberformat* pFormat, - sal_uInt16 nString, - bool bDontDetectNegation = false ); - - // if nMatchedAllStrings set nMatchedUsedAsReturn and return true, - // else do nothing and return false - bool MatchedReturn(); - - //! Be sure that the string to be analyzed is already converted to upper - //! case and if it contained native humber digits that they are already - //! converted to ASCII. - bool IsNumberFormatMain( // Main anlyzing function - const String& rString, - double& fOutNumber, // return value if string is numeric - const SvNumberformat* pFormat = NULL // optional number format to match against - ); - - static inline bool MyIsdigit( sal_Unicode c ); - -}; - -class LocaleData; -struct ImpSvNumberformatInfo; - - -const size_t NF_MAX_FORMAT_SYMBOLS = 100; -const size_t NF_MAX_DEFAULT_COLORS = 10; - -// Hack: nThousand==1000 => "Default" occurs in format string -const sal_uInt16 FLAG_STANDARD_IN_FORMAT = 1000; - -class LocaleData; - -class ImpSvNumberformatScan -{ -public: - - ImpSvNumberformatScan( LocaleData* pFormatter ); - ~ImpSvNumberformatScan(); - void ChangeIntl(); // swap keywords - - void ChangeStandardPrec(sal_uInt16 nPrec); // exchanges standard precision - - uint16_t ScanFormat( String& rString, String& rComment ); // Calling up the scan analysis - - void CopyInfo(ImpSvNumberformatInfo* pInfo, - sal_uInt16 nAnz); // Copies the FormatInfo - sal_uInt16 GetAnzResStrings() const { return nAnzResStrings; } - - const NfKeywordTable & GetKeywords() const - { - if ( bKeywordsNeedInit ) - InitKeywords(); - return sKeyword; - } - // Keywords used in output like true and false - const String& GetSpecialKeyword( NfKeywordIndex eIdx ) const - { - if ( !sKeyword[eIdx].size() ) - InitSpecialKeyword( eIdx ); - return sKeyword[eIdx]; - } - const String& GetTrueString() const { return GetSpecialKeyword( NF_KEY_TRUE ); } - const String& GetFalseString() const { return GetSpecialKeyword( NF_KEY_FALSE ); } - const String& GetColorString() const { return GetKeywords()[NF_KEY_COLOR]; } - const String& GetRedString() const { return GetKeywords()[NF_KEY_RED]; } - const String& GetBooleanString() const { return GetKeywords()[NF_KEY_BOOLEAN]; } - const String& GetErrorString() const { return sErrStr; } - - const String& GetStandardName() const - { - if ( bKeywordsNeedInit ) - InitKeywords(); - return sNameStandardFormat; - } - sal_uInt16 GetStandardPrec() const { return nStandardPrec; } - // definierte Farben - - // the compatibility currency symbol for old automatic currency formats - const String& GetCurSymbol() const - { - if ( bCompatCurNeedInit ) - InitCompatCur(); - return sCurSymbol; - } - - // the compatibility currency abbreviation for CCC format code - const String& GetCurAbbrev() const - { - if ( bCompatCurNeedInit ) - InitCompatCur(); - return sCurAbbrev; - } - - // the compatibility currency symbol upper case for old automatic currency formats - const String& GetCurString() const - { - if ( bCompatCurNeedInit ) - InitCompatCur(); - return sCurString; - } - - void SetConvertMode(LanguageType eTmpLge, LanguageType eNewLge, - bool bSystemToSystem = false ) - { - bConvertMode = true; - eNewLnge = eNewLge; - eTmpLnge = eTmpLge; - bConvertSystemToSystem = bSystemToSystem; - } - void SetConvertMode(bool bMode) { bConvertMode = bMode; } - bool GetConvertMode() const { return bConvertMode; } - LanguageType GetNewLnge() const { return eNewLnge; } - LanguageType GetTmpLnge() const { return eTmpLnge; } - sal_uInt8 GetNatNumModifier() const { return nNatNumModifier; } - void SetNatNumModifier( sal_uInt8 n ) { nNatNumModifier = n; } - - LocaleData* GetNumberformatter() { return pFormatter; } - - -private: - NfKeywordTable sKeyword; - String sNameStandardFormat; - sal_uInt16 nStandardPrec; - LocaleData* pFormatter; - - String sStrArray[NF_MAX_FORMAT_SYMBOLS]; // array of symbols - short nTypeArray[NF_MAX_FORMAT_SYMBOLS]; // array of info - // External Info: - sal_uInt16 nAnzResStrings; // Number of result symbols -#if !(defined SOLARIS && defined X86) - short eScannedType; // Typ gemaess Scan -#else - int eScannedType; // according to optimization -#endif - bool bThousand; // With a thousand point - sal_uInt16 nThousand; // Counts .... episodes - sal_uInt16 nCntPre; // Counts digits before the decimal point - sal_uInt16 nCntPost; // Counts decimal places - sal_uInt16 nCntExp; // Counts Exp.Jobs, AM/PM - sal_uInt32 nExpVal; - // Internal Info: - sal_uInt16 nAnzStrings; // number of symbols - sal_uInt16 nRepPos; // position of one '*' - sal_uInt16 nExpPos; // internal Position of E - sal_uInt16 nBlankPos; // internal position of the blank - short nDecPos; // internal Pos. from , - bool bExp; // is set when the E is read - bool bFrac; // is set when reading the / - bool bBlank; // becomes sat with ' '(Fraction). - bool bDecSep; // Is set at the first - mutable bool bKeywordsNeedInit; // Locale dependent keywords need to be initialized - mutable bool bCompatCurNeedInit; // Locale dependent compatibility currency need to be initialized - String sCurSymbol; // Currency symbol for compatibility format codes - String sCurString; // Currency symbol in upper case - String sCurAbbrev; // Currency abbreviation - String sErrStr; // String for error output - - bool bConvertMode; // Is set in convert mode - // Country/language in which the - LanguageType eNewLnge; // scanned string converted - // will (for Excel filters) - // Country/language from which the - LanguageType eTmpLnge; // scanned string converted - // will (for Excel filters) - bool bConvertSystemToSystem; // Whether the conversion is - // from one system locale to - // another system locale (in - // this case the automatic - // currency symbol is converted - // too). - - uint16_t nCurrPos; // Position of the Waehrungssymbols - - sal_uInt8 nNatNumModifier; // Thai T speciality - - void InitKeywords() const; - void InitSpecialKeyword( NfKeywordIndex eIdx ) const; - void InitCompatCur() const; - - void SetDependentKeywords(); - // Sets the language depend. keyword. - void SkipStrings(sal_uInt16& i,uint16_t& nPos);// Skips string symbols - sal_uInt16 PreviousKeyword(sal_uInt16 i); // Returns index of prev. - // Key words or 0 - sal_uInt16 NextKeyword(sal_uInt16 i); // Returns index of next - // Key words or 0 - sal_Unicode PreviousChar(sal_uInt16 i); // Gives last letter - // before the position, - // skip EMPTY, STRING, STAR, BLANK - sal_Unicode NextChar(sal_uInt16 i); // Gives first letter after - short PreviousType( sal_uInt16 i ); // gives type before position, - // skip EMPTY - bool IsLastBlankBeforeFrac(sal_uInt16 i); // True <=> there is none ' ' - // more up to the '/' - void Reset(); // Reset all variables - // before start of analysis - short GetKeyWord( const String& sSymbol, // determine keyword at nPos - uint16_t nPos ); // return 0 <=> not found - - inline bool IsAmbiguousE( short nKey ) // whether nKey is ambiguous E of NF_KEY_E/NF_KEY_EC - { - return (nKey == NF_KEY_EC || nKey == NF_KEY_E) && - (GetKeywords()[NF_KEY_EC] == GetKeywords()[NF_KEY_E]); - } - - bool Is100SecZero( sal_uInt16 i, bool bHadDecSep ); - - short Next_Symbol(const String& rStr, - uint16_t& nPos, - String& sSymbol); // next icon - uint16_t Symbol_Division(const String& rString);// lexical pre-analysis - uint16_t ScanType(const String& rString); // Formattyp Analysis - uint16_t FinalScan( String& rString, String& rComment ); // Final analysis with default - // of the type - int FinalScanGetCalendar( uint16_t& nPos, sal_uInt16& i, sal_uInt16& nAnzResStrings ); - - bool InsertSymbol( sal_uInt16 & nPos, NfSymbolType eType, const String& rStr ); - - static inline bool StringEqualsChar( const String& rStr, sal_Unicode ch ) - { return rStr.at(0) == ch && rStr.size() == 1; } - - static uint16_t RemoveQuotes( String& rStr ); -}; - -#define NF_COMMENT_IN_FORMATSTRING 0 - -namespace utl { - class DigitGroupingIterator; -} - -class SvStream; -class Color; - -class ImpSvNumberformatScan; // format code string scanner -class ImpSvNumberInputScan; // input string scanner -class ImpSvNumMultipleWriteHeader; // compatible file format -class ImpSvNumMultipleReadHeader; // compatible file format - -enum SvNumberformatLimitOps -{ - NUMBERFORMAT_OP_NO = 0, // Undefined, no OP - NUMBERFORMAT_OP_EQ = 1, // Operator = - NUMBERFORMAT_OP_NE = 2, // Operator <> - NUMBERFORMAT_OP_LT = 3, // Operator < - NUMBERFORMAT_OP_LE = 4, // Operator <= - NUMBERFORMAT_OP_GT = 5, // Operator > - NUMBERFORMAT_OP_GE = 6 // Operator >= -}; - -// SYSTEM-german to SYSTEM-xxx and vice versa conversion hack onLoad -enum NfHackConversion -{ - NF_CONVERT_NONE, - NF_CONVERT_GERMAN_ENGLISH, - NF_CONVERT_ENGLISH_GERMAN -}; - -struct ImpSvNumberformatInfo // Struct for FormatInfo -{ - String* sStrArray; // Array of symbols - short* nTypeArray; // Array of infos - sal_uInt16 nThousand; // Count of group separator sequences - sal_uInt16 nCntPre; // Count of digits before decimal point - sal_uInt16 nCntPost; // Count of digits after decimal point - sal_uInt16 nCntExp; // Count of exponent digits, or AM/PM - sal_uInt32 nExpVal; // - short eScannedType; // Type determined by scan - bool bThousand; // Has group (AKA thousand) separator - - void Copy( const ImpSvNumberformatInfo& rNumFor, sal_uInt16 nAnz ); -}; - -class SvNumberNatNum -{ - LocaleIndentifier eLang; - sal_uInt8 nNum; - bool bDBNum :1; // DBNum, to be converted to NatNum - bool bDate :1; // Used in date? (needed for DBNum/NatNum mapping) - bool bSet :1; // If set, since NatNum0 is possible - -public: - - SvNumberNatNum() : eLang( LocaleId_en_US ), nNum(0), - bDBNum(0), bDate(0), bSet(0) {} - bool IsComplete() const { return bSet && eLang != LocaleId_en_US; } - sal_uInt8 GetRawNum() const { return nNum; } - sal_uInt8 GetNatNum() const { return 0; } - LanguageType GetLang() const { return eLang; } - void SetLang( LanguageType e ) { eLang = e; } - void SetNum( sal_uInt8 nNumber, bool bDBNumber ) - { - nNum = nNumber; - bDBNum = bDBNumber; - bSet = true; - } - bool IsSet() const { return bSet; } - void SetDate( bool bDateP ) { bDate = (bDateP != 0); } -}; - -class CharClass; - -class ImpSvNumFor // One of four subformats of the format code string -{ -public: - ImpSvNumFor(); // Ctor without filling the Info - ~ImpSvNumFor(); - - void Enlarge(sal_uInt16 nAnz); // Init of arrays to the right size - - void Copy( const ImpSvNumFor& rNumFor, ImpSvNumberformatScan* pSc ); - - ImpSvNumberformatInfo& Info() { return aI;} - const ImpSvNumberformatInfo& Info() const { return aI; } - - // Get count of substrings (symbols) - sal_uInt16 GetnAnz() const { return nAnzStrings;} - - Color* GetColor() const { return pColor; } - void SetColor( Color* pCol, String& rName ) - { pColor = pCol; sColorName = rName; } - const String& GetColorName() const { return sColorName; } - - // new SYMBOLTYPE_CURRENCY in subformat? - bool HasNewCurrency() const; - bool GetNewCurrencySymbol( String& rSymbol, String& rExtension ) const; - - void SetNatNumNum( sal_uInt8 nNum, bool bDBNum ) { aNatNum.SetNum( nNum, bDBNum ); } - void SetNatNumLang( LanguageType eLang ) { aNatNum.SetLang( eLang ); } - void SetNatNumDate( bool bDate ) { aNatNum.SetDate( bDate ); } - const SvNumberNatNum& GetNatNum() const { return aNatNum; } - - // check, if the format code contains a subformat for text - bool HasTextFormatCode() const; - -private: - ImpSvNumberformatInfo aI; - String sColorName; - Color* pColor; - sal_uInt16 nAnzStrings; - SvNumberNatNum aNatNum; - -}; - -class LocaleData; - -class SvNumberformat -{ -public: - // Normal ctor - SvNumberformat( String& rString, - LocaleData* pFormatter, - ImpSvNumberInputScan* pISc, - uint16_t& nCheckPos, - LanguageType eLan = LocaleIndentifier::LocaleId_en_US, - bool bStand = false ); - - // Ascii version of constructor - SvNumberformat(std::string& rString, - LocaleData* pFormatter, - ImpSvNumberInputScan* pISc, - uint16_t& nCheckPos, - LanguageType eLan = LocaleIndentifier::LocaleId_en_US, - bool bStand = false); - - void InitFormat(String& rString, - LocaleData* pFormatter, - ImpSvNumberInputScan* pISc, - uint16_t& nCheckPos, - LanguageType eLan, - bool bStand); - - ~SvNumberformat(); - - /// Get type of format, may include NUMBERFORMAT_DEFINED bit - short GetType() const - { return (nNewStandardDefined && - (nNewStandardDefined <= SV_NUMBERFORMATTER_VERSION)) ? - (eType & ~NUMBERFORMAT_DEFINED) : eType; } - - void SetType(const short eSetType) { eType = eSetType; } - // Standard means the I18N defined standard format of this type - void SetStandard() { bStandard = true; } - bool IsStandard() const { return bStandard; } - - // For versions before version nVer it is UserDefined, for newer versions - // it is builtin. nVer of SV_NUMBERFORMATTER_VERSION_... - void SetNewStandardDefined( sal_uInt16 nVer ) - { nNewStandardDefined = nVer; eType |= NUMBERFORMAT_DEFINED; } - - sal_uInt16 GetNewStandardDefined() const { return nNewStandardDefined; } - bool IsAdditionalStandardDefined() const - { return nNewStandardDefined == SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS; } - - LanguageType GetLanguage() const { return eLnge;} - - const String& GetFormatstring() const { return sFormatstring; } - - void SetUsed(const bool b) { bIsUsed = b; } - bool GetUsed() const { return bIsUsed; } - bool IsStarFormatSupported() const { return bStarFlag; } - void SetStarFormatSupport( bool b ) { bStarFlag = b; } - - bool GetOutputString( double fNumber, sal_uInt16 nCharCount, String& rOutString ) const; - - bool GetOutputString( double fNumber, String& OutString, Color** ppColor ); - bool GetOutputString( double fNumber, std::string& OutString ); - bool GetOutputString( String& sString, String& OutString, Color** ppColor ); - - // True if type text - bool IsTextFormat() const { return (eType & NUMBERFORMAT_TEXT) != 0; } - // True if 4th subformat present - bool HasTextFormat() const - { - return (NumFor[3].GetnAnz() > 0) || - (NumFor[3].Info().eScannedType == NUMBERFORMAT_TEXT); - } - - void GetFormatSpecialInfo(bool& bThousand, - bool& IsRed, - sal_uInt16& nPrecision, - sal_uInt16& nAnzLeading) const; - - /// Count of decimal precision - sal_uInt16 GetFormatPrecision() const { return NumFor[0].Info().nCntPost; } - - //! Read/write access on a special sal_uInt16 component, may only be used on the - //! standard format 0, 5000, ... and only by the number formatter! - sal_uInt16 GetLastInsertKey() const - { return NumFor[0].Info().nThousand; } - void SetLastInsertKey(sal_uInt16 nKey) - { NumFor[0].Info().nThousand = nKey; } - - //! Only onLoad: convert from stored to current system language/country - void ConvertLanguage( LocaleData& rConverter, - LanguageType eConvertFrom, LanguageType eConvertTo, bool bSystem = false ); - - // Substring of a subformat code nNumFor (0..3) - // nPos == 0xFFFF => last substring - // bString==true: first/last SYMBOLTYPE_STRING or SYMBOLTYPE_CURRENCY - const String* GetNumForString( sal_uInt16 nNumFor, sal_uInt16 nPos, - bool bString = false ) const; - - // Subtype of a subformat code nNumFor (0..3) - // nPos == 0xFFFF => last substring - // bString==true: first/last SYMBOLTYPE_STRING or SYMBOLTYPE_CURRENCY - short GetNumForType( sal_uInt16 nNumFor, sal_uInt16 nPos, bool bString = false ) const; - - /** If the count of string elements (substrings, ignoring [modifiers] and - so on) in a subformat code nNumFor (0..3) is equal to the given number. - Used by ImpSvNumberInputScan::IsNumberFormatMain() to detect a matched - format. */ - bool IsNumForStringElementCountEqual( sal_uInt16 nNumFor, sal_uInt16 nAllCount, - sal_uInt16 nNumCount ) const - { - if ( nNumFor < 4 ) - { - // First try a simple approach. Note that this is called only - // if all MidStrings did match so far, to verify that all - // strings of the format were matched and not just the starting - // sequence, so we don't have to check if GetnAnz() includes - // [modifiers] or anything else if both counts are equal. - sal_uInt16 nCnt = NumFor[nNumFor].GetnAnz(); - if ( nAllCount == nCnt ) - return true; - if ( nAllCount < nCnt ) // check ignoring [modifiers] and so on - return ImpGetNumForStringElementCount( nNumFor ) == - (nAllCount - nNumCount); - } - return false; - } - - // Whether the second subformat code is really for negative numbers - // or another limit set. - bool IsNegativeRealNegative() const - { - return fLimit1 == 0.0 && fLimit2 == 0.0 && - ( (eOp1 == NUMBERFORMAT_OP_GE && eOp2 == NUMBERFORMAT_OP_NO) || - (eOp1 == NUMBERFORMAT_OP_GT && eOp2 == NUMBERFORMAT_OP_LT) || - (eOp1 == NUMBERFORMAT_OP_NO && eOp2 == NUMBERFORMAT_OP_NO) ); - } - // Whether the first subformat code is really for negative numbers - // or another limit set. - bool IsNegativeRealNegative2() const - { - return fLimit1 == 0.0 && fLimit2 == 0.0 && - ( (eOp2 == NUMBERFORMAT_OP_GT && eOp1 == NUMBERFORMAT_OP_LT) || - (eOp2 == NUMBERFORMAT_OP_EQ && eOp1 == NUMBERFORMAT_OP_LT) || - (eOp2 == NUMBERFORMAT_OP_GE && eOp1 == NUMBERFORMAT_OP_LT) || - (eOp2 == NUMBERFORMAT_OP_NO && eOp1 == NUMBERFORMAT_OP_LT) || - (eOp2 == NUMBERFORMAT_OP_NO && eOp1 == NUMBERFORMAT_OP_LE) || - (eOp2 == NUMBERFORMAT_OP_GT && eOp1 == NUMBERFORMAT_OP_LE)); - } - - // Whether the negative format is without a sign or not - bool IsNegativeWithoutSign() const; - - // Whether a new SYMBOLTYPE_CURRENCY is contained in the format - bool HasNewCurrency() const; - - // check, if the format code contains a subformat for text - bool HasTextFormatCode() const; - - // Build string from NewCurrency for saving it SO50 compatible - void Build50Formatstring( String& rStr ) const; - - // strip [$-yyy] from all [$xxx-yyy] leaving only xxx's, - // if bQuoteSymbol==true the xxx will become "xxx" - static String StripNewCurrencyDelimiters( const String& rStr, - bool bQuoteSymbol ); - - // If a new SYMBOLTYPE_CURRENCY is contained if the format is of type - // NUMBERFORMAT_CURRENCY, and if so the symbol xxx and the extension nnn - // of [$xxx-nnn] are returned - bool GetNewCurrencySymbol( String& rSymbol, String& rExtension ) const; - - static bool HasStringNegativeSign( const String& rStr ); - - /** - Whether a character at position nPos is somewhere between two matching - cQuote or not. - If nPos points to a cQuote, a true is returned on an opening cQuote, - a false is returned on a closing cQuote. - A cQuote between quotes may be escaped by a cEscIn, a cQuote outside of - quotes may be escaped by a cEscOut. - The default '\0' results in no escapement possible. - Defaults are set right according to the "unlogic" of the Numberformatter - */ - static bool IsInQuote( const String& rString, uint16_t nPos, - sal_Unicode cQuote = '"', - sal_Unicode cEscIn = '\0', sal_Unicode cEscOut = '\\' ); - - /** - Return the position of a matching closing cQuote if the character at - position nPos is between two matching cQuote, otherwise return - STRING_NOTFOUND. - If nPos points to an opening cQuote the position of the matching - closing cQuote is returned. - If nPos points to a closing cQuote nPos is returned. - If nPos points into a part which starts with an opening cQuote but has - no closing cQuote, rString.size() is returned. - Uses IsInQuote internally, so you don't have to call - that prior to a call of this method. - */ - static uint16_t GetQuoteEnd( const String& rString, uint16_t nPos, - sal_Unicode cQuote = '"', - sal_Unicode cEscIn = '\0', sal_Unicode cEscOut = '\\' ); - - void SetComment( const String& rStr ) { sComment = rStr; } - const String& GetComment() const { return sComment; } - - // Erase "{ "..." }" from format subcode string to get the pure comment (old version) - static void EraseCommentBraces( String& rStr ); - // Set comment rStr in format string rFormat and in rComment (old version) - static void SetComment( const String& rStr, String& rFormat, String& rComment ); - // Erase comment at end of rStr to get pure format code string (old version) - static void EraseComment( String& rStr ); - - /** Insert the number of blanks into the string that is needed to simulate - the width of character c for underscore formats */ - static uint16_t InsertBlanks( String& r, uint16_t nPos, sal_Unicode c ); - - /// One of YMD,DMY,MDY if date format - DateFormat GetDateOrder() const; - - /** A coded value of the exact YMD combination used, if date format. - For example: YYYY-MM-DD => ('Y' << 16) | ('M' << 8) | 'D' - or: MM/YY => ('M' << 8) | 'Y' */ - sal_uInt32 GetExactDateOrder() const; - - ImpSvNumberformatScan* ImpGetScan() const { return rScanPtr; } - - // used in XML export - void GetConditions( SvNumberformatLimitOps& rOper1, double& rVal1, - SvNumberformatLimitOps& rOper2, double& rVal2 ) const; - Color* GetColor( sal_uInt16 nNumFor ) const; - void GetNumForInfo( sal_uInt16 nNumFor, short& rScannedType, - bool& bThousand, sal_uInt16& nPrecision, sal_uInt16& nAnzLeading ) const; - - // rAttr.Number not empty if NatNum attributes are to be stored - //void GetNatNumXml( - // ::com::sun::star::i18n::NativeNumberXmlAttributes& rAttr, - // sal_uInt16 nNumFor ) const; - - /** @returns if E,EE,R,RR,AAA,AAAA in format code of subformat - nNumFor (0..3) and no preceding calendar was specified and the - currently loaded calendar is "gregorian". */ - bool IsOtherCalendar( sal_uInt16 nNumFor ) const - { - if ( nNumFor < 4 ) - return ImpIsOtherCalendar( NumFor[nNumFor] ); - return false; - } - - /** Switches to the first non-"gregorian" calendar, but only if the current - calendar is "gregorian"; original calendar name and date/time returned, - but only if calendar switched and rOrgCalendar was empty. */ - void SwitchToOtherCalendar( String& rOrgCalendar, double& fOrgDateTime ) const; - - /** Switches to the "gregorian" calendar, but only if the current calendar - is non-"gregorian" and rOrgCalendar is not empty. Thus a preceding - ImpSwitchToOtherCalendar() call should have been placed prior to - calling this method. */ - void SwitchToGregorianCalendar( const String& rOrgCalendar, double fOrgDateTime ) const; - - /** Switches to the first specified calendar, if any, in subformat nNumFor - (0..3). Original calendar name and date/time returned, but only if - calendar switched and rOrgCalendar was empty. - - @return - if a calendar was specified and switched to, - else. - */ - bool SwitchToSpecifiedCalendar( String& rOrgCalendar, double& fOrgDateTime, - sal_uInt16 nNumFor ) const - { - if ( nNumFor < 4 ) - return ImpSwitchToSpecifiedCalendar( rOrgCalendar, - fOrgDateTime, NumFor[nNumFor] ); - return false; - } - -private: - ImpSvNumFor NumFor[4]; // Array for the 4 subformats - String sFormatstring; // The format code string - String sComment; // Comment, since number formatter version 6 - double fLimit1; // Value for first condition - double fLimit2; // Value for second condition - LocaleData* pFormatter; - ImpSvNumberformatScan* rScanPtr; - LanguageType eLnge; // Language/country of the format - SvNumberformatLimitOps eOp1; // Operator for first condition - SvNumberformatLimitOps eOp2; // Operator for second condition - sal_uInt16 nNewStandardDefined; // new builtin formats as of version 6 - short eType; // Type of format - bool bStarFlag; // Take *n format as ESC n - bool bStandard; // If this is a default standard format - bool bIsUsed; // Flag as used for storing - - sal_uInt16 ImpGetNumForStringElementCount( sal_uInt16 nNumFor ) const; - - bool ImpIsOtherCalendar( const ImpSvNumFor& rNumFor ) const; - - bool ImpSwitchToSpecifiedCalendar( String& rOrgCalendar, - double& fOrgDateTime, const ImpSvNumFor& rNumFor ) const; - - //const LocaleDataWrapper& rLoc() const { return rScan.GetLoc(); } - //CalendarWrapper& GetCal() const { return rScan.GetCal(); } - - // divide in substrings and color conditions - short ImpNextSymbol( String& rString, - uint16_t& nPos, - String& sSymbol ); - - // read string until ']' and strip blanks (after condition) - static uint16_t ImpGetNumber( String& rString, - uint16_t& nPos, - String& sSymbol ); - - // get xxx of "[$-xxx]" as LanguageType, starting at and advancing position nPos - static LanguageType ImpGetLanguageType( const String& rString, uint16_t& nPos ); - - // standard number output - void ImpGetOutputStandard( double& fNumber, String& OutString ); - void ImpGetOutputStdToPrecision( double& rNumber, String& rOutString, sal_uInt16 nPrecision ) const; - // numbers in input line - void ImpGetOutputInputLine( double fNumber, String& OutString ); - - // check subcondition - // OP undefined => -1 - // else 0 or 1 - short ImpCheckCondition(double& fNumber, - double& fLimit, - SvNumberformatLimitOps eOp); - - sal_uLong ImpGGT(sal_uLong x, sal_uLong y); - sal_uLong ImpGGTRound(sal_uLong x, sal_uLong y); - - // Helper function for number strings - // append string symbols, insert leading 0 or ' ', or ... - bool ImpNumberFill( String& sStr, - double& rNumber, - uint16_t& k, - sal_uInt16& j, - sal_uInt16 nIx, - short eSymbolType ); - - // Helper function to fill in the integer part and the group (AKA thousand) separators - bool ImpNumberFillWithThousands( String& sStr, - double& rNumber, - uint16_t k, - sal_uInt16 j, - sal_uInt16 nIx, - sal_uInt16 nDigCnt ); - // Hilfsfunktion zum Auffuellen der Vor- - // kommazahl auch mit Tausenderpunkt - - // Helper function to fill in the group (AKA thousand) separators - // or to skip additional digits - void ImpDigitFill( String& sStr, - uint16_t nStart, - uint16_t& k, - sal_uInt16 nIx, - uint16_t & nDigitCount, - DigitGroupingIterator & rGrouping ); - - bool ImpGetDateOutput( double fNumber, - sal_uInt16 nIx, - String& OutString ); - bool ImpGetTimeOutput( double fNumber, - sal_uInt16 nIx, - String& OutString ); - bool ImpGetDateTimeOutput( double fNumber, - sal_uInt16 nIx, - String& OutString ); - - // Switches to the "gregorian" calendar if the current calendar is - // non-"gregorian" and the era is a "Dummy" era of a calendar which doesn't - // know a "before" era (like zh_TW ROC or ja_JP Gengou). If switched and - // rOrgCalendar was "gregorian" the string is emptied. If rOrgCalendar was - // empty the previous calendar name and date/time are returned. - bool ImpFallBackToGregorianCalendar( String& rOrgCalendar, double& fOrgDateTime ); - - // Append a "G" short era string of the given calendar. In the case of a - // Gengou calendar this is a one character abbreviation, for other - // calendars the XExtendedCalendar::getDisplayString() method is called. - void ImpAppendEraG( String& OutString, sal_Int16 nNatNum ); - - bool ImpGetNumberOutput( double fNumber, - sal_uInt16 nIx, - String& OutString ); - - //void ImpCopyNumberformat( const SvNumberformat& rFormat ); - - // normal digits or other digits, depending on ImpSvNumFor.aNatNum, - // [NatNum1], [NatNum2], ... - String ImpGetNatNumString( const SvNumberNatNum& rNum, sal_Int32 nVal, - sal_uInt16 nMinDigits = 0 ) const; - - String ImpIntToString( sal_uInt16 nIx, sal_Int32 nVal, sal_uInt16 nMinDigits = 0 ) const - { - const SvNumberNatNum& rNum = NumFor[nIx].GetNatNum(); - if ( nMinDigits || rNum.IsComplete() ) - return ImpGetNatNumString( rNum, nVal, nMinDigits ); - return std::to_wstring(nVal); - } - - // transliterate according to NativeNumber - //void ImpTransliterateImpl( String& rStr, const SvNumberNatNum& rNum ) const; - - void ImpTransliterate( String& rStr, const SvNumberNatNum& rNum ) const - { - //if ( rNum.IsComplete() ) - // ImpTransliterateImpl( rStr, rNum ); - } -}; - -} // namespace duckdb_excel - -#endif // _NF_ZFORMAT_H diff --git a/extension/excel/numformat/nf_calendar.cpp b/extension/excel/numformat/nf_calendar.cpp deleted file mode 100644 index c33c795c2b3..00000000000 --- a/extension/excel/numformat/nf_calendar.cpp +++ /dev/null @@ -1,1326 +0,0 @@ -/************************************************************** - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - *************************************************************/ - -#include -#include -#include -#ifdef _WIN32 -#include -#else -#include -#endif -#include -#include "nf_calendar.h" -#include "nf_localedata.h" - - -namespace duckdb_excel { - -//------------- calendar.cxx ------------------------------------ - -#define erDUMP_ICU_CALENDAR 0 -#define erDUMP_I18N_CALENDAR 0 -#define DUMP_ICU_CAL_MSG(x) -#define DUMP_I18N_CAL_MSG(x) - -namespace CalendarDisplayIndex { -/// name of an AM/PM value -const short CDI_AM_PM = 0; -/// name of a day of week -const short CDI_DAY = 1; -/// name of a month -const short CDI_MONTH = 2; -/// name of a year (if used for a specific calendar) -const short CDI_YEAR = 3; -/// name of an era, like BC/AD -const short CDI_ERA = 4; -} // namespace CalendarDisplayIndex - -const double MILLISECONDS_PER_DAY = 1000.0 * 60.0 * 60.0 * 24.0; - -Calendar::Calendar(LocaleData *pFormatterP) { - pFormatter = pFormatterP; - init(NULL); - pNullDate = new Date(30, 12, 1899); - memset(fieldValue, 0, sizeof(fieldValue)); -} -Calendar::Calendar(Era *_eraArray) { - init(_eraArray); - pNullDate = new Date(30, 12, 1899); - memset(fieldValue, 0, sizeof(fieldValue)); -} -void Calendar::init(Era *_eraArray) { - eraArray = _eraArray; - aEpochStart = DateTime(Date(1, 1, 1970)); - timeInDays = 0.0; -} - -Calendar::~Calendar() { - delete pNullDate; -} - -void Calendar::setValue(sal_Int16 fieldIndex, sal_Int16 value) { - if (fieldIndex < 0 || FIELD_INDEX_COUNT <= fieldIndex) { - return; - } - fieldSet |= (1 << fieldIndex); - fieldValue[fieldIndex] = value; -} - -bool Calendar::getCombinedOffset(sal_Int32 &o_nOffset, sal_Int16 nParentFieldIndex, sal_Int16 nChildFieldIndex) const { - o_nOffset = 0; - bool bFieldsSet = false; - if (fieldSet & (1 << nParentFieldIndex)) { - bFieldsSet = true; - o_nOffset = static_cast(fieldValue[nParentFieldIndex]) * 60000; - } - if (fieldSet & (1 << nChildFieldIndex)) { - bFieldsSet = true; - if (o_nOffset < 0) - o_nOffset -= static_cast(fieldValue[nChildFieldIndex]); - else - o_nOffset += static_cast(fieldValue[nChildFieldIndex]); - } - return bFieldsSet; -} - -bool Calendar::getZoneOffset(sal_Int32 &o_nOffset) const { - return getCombinedOffset(o_nOffset, CalendarFieldIndex::ZONE_OFFSET, CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS); -} - -bool Calendar::getDSTOffset(sal_Int32 &o_nOffset) const { - return getCombinedOffset(o_nOffset, CalendarFieldIndex::DST_OFFSET, CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS); -} - -void Calendar::submitFields() { - sal_Int32 nZoneOffset, nDSTOffset; - getZoneOffset(nZoneOffset); - getDSTOffset(nDSTOffset); -} - -void Calendar::submitValues(sal_Int32 nYear, sal_Int32 nMonth, sal_Int32 nDay, sal_Int32 nHour, sal_Int32 nMinute, - sal_Int32 nSecond, sal_Int32 nMilliSecond, sal_Int32 nZone, sal_Int32 nDST) { - submitFields(); -} - -#if (0) -static void lcl_setCombinedOffsetFieldValues(sal_Int32 nValue, sal_Int16 rFieldSetValue[], sal_Int16 rFieldValue[], - sal_Int16 nParentFieldIndex, sal_Int16 nChildFieldIndex) { - sal_Int32 nTrunc = nValue / 60000; - rFieldSetValue[nParentFieldIndex] = rFieldValue[nParentFieldIndex] = static_cast(nTrunc); - sal_uInt16 nMillis = static_cast(abs(nValue - nTrunc * 60000)); - rFieldSetValue[nChildFieldIndex] = rFieldValue[nChildFieldIndex] = static_cast(nMillis); -} -#endif - -sal_Int16 Calendar::getValue(sal_Int16 fieldIndex) { - if (fieldIndex < 0 || FIELD_INDEX_COUNT <= fieldIndex) { - return -1; - } - - return fieldValue[fieldIndex]; -} - -bool Calendar::isValid() { - return true; -} - -static sal_Int32 DisplayCode2FieldIndex(sal_Int32 nCalendarDisplayCode) { - switch (nCalendarDisplayCode) { - case CalendarDisplayCode::SHORT_DAY: - case CalendarDisplayCode::LONG_DAY: - return CalendarFieldIndex::DAY_OF_MONTH; - case CalendarDisplayCode::SHORT_DAY_NAME: - case CalendarDisplayCode::LONG_DAY_NAME: - return CalendarFieldIndex::DAY_OF_WEEK; - case CalendarDisplayCode::SHORT_QUARTER: - case CalendarDisplayCode::LONG_QUARTER: - case CalendarDisplayCode::SHORT_MONTH: - case CalendarDisplayCode::LONG_MONTH: - case CalendarDisplayCode::SHORT_MONTH_NAME: - case CalendarDisplayCode::LONG_MONTH_NAME: - return CalendarFieldIndex::CFI_MONTH; - case CalendarDisplayCode::SHORT_YEAR: - case CalendarDisplayCode::LONG_YEAR: - return CalendarFieldIndex::CFI_YEAR; - case CalendarDisplayCode::SHORT_ERA: - case CalendarDisplayCode::LONG_ERA: - return CalendarFieldIndex::ERA; - case CalendarDisplayCode::SHORT_YEAR_AND_ERA: - case CalendarDisplayCode::LONG_YEAR_AND_ERA: - return CalendarFieldIndex::CFI_YEAR; - default: - return 0; - } -} - -std::wstring Calendar::getDisplayName(sal_Int16 displayIndex, sal_Int16 idx, sal_Int16 nameType) { - std::wstring aStr; - - switch (displayIndex) { - case CalendarDisplayIndex::CDI_AM_PM: /* ==0 */ - if (idx == 0) - aStr = pFormatter->getTimeAM(); - else if (idx == 1) - aStr = pFormatter->getTimePM(); - else - return L""; - break; - case CalendarDisplayIndex::CDI_DAY: - idx %= pFormatter->getDayOfWeekSize(); - if (nameType == 0) - aStr = pFormatter->getDayOfWeekAbbrvName(idx); - else if (nameType == 1) - aStr = pFormatter->getDayOfWeekFullName(idx); - else - return L""; - break; - case CalendarDisplayIndex::CDI_MONTH: - if (idx >= pFormatter->getMonthsOfYearSize()) - return L""; - if (nameType == 0) - aStr = pFormatter->getMonthsOfYearAbbrvName(idx); - else if (nameType == 1) - aStr = pFormatter->getMonthsOfYearFullName(idx); - else - return L""; - break; - case CalendarDisplayIndex::CDI_ERA: - if (idx >= pFormatter->getEraSize()) - return L""; - if (nameType == 0) - aStr = pFormatter->getEraAbbrvName(idx); - else if (nameType == 1) - aStr = pFormatter->getEraFullName(idx); - else - return L""; - break; - case CalendarDisplayIndex::CDI_YEAR: - break; - default: - return L""; - } - return aStr; -} - -// Methods in XExtendedCalendar -std::wstring Calendar::getDisplayString(sal_Int32 nCalendarDisplayCode, sal_Int16 nNativeNumberMode) { - sal_Int16 value = getValue((sal_Int16)(DisplayCode2FieldIndex(nCalendarDisplayCode))); - std::wstring aOUStr; - - if (nCalendarDisplayCode == CalendarDisplayCode::SHORT_QUARTER || - nCalendarDisplayCode == CalendarDisplayCode::LONG_QUARTER) { - sal_Int16 quarter = value / 3; - // Since this base class method may be called by derived calendar - // classes where a year consists of more than 12 months we need a check - // to not run out of bounds of reserved quarter words. Perhaps a more - // clean way (instead of dividing by 3) would be to first get the - // number of months, divide by 4 and then use that result to divide the - // actual month value. - if (quarter > 3) - quarter = 3; - quarter = (sal_Int16)(quarter + ((nCalendarDisplayCode == CalendarDisplayCode::SHORT_QUARTER) - ? reservedWords::QUARTER1_ABBREVIATION - : reservedWords::QUARTER1_WORD)); - aOUStr = pFormatter->getReservedWord(quarter); - } else { - // The "#100211# - checked" comments serve for detection of "use of - // sprintf is safe here" conditions. An sprintf encountered without - // having that comment triggers alarm ;-) - wchar_t aStr[10]; - switch (nCalendarDisplayCode) { - case CalendarDisplayCode::SHORT_MONTH: - value += 1; // month is zero based - // fall thru - case CalendarDisplayCode::SHORT_DAY: - swprintf(aStr, sizeof(aStr) / sizeof(wchar_t), L"%d", value); // #100211# - checked - break; - case CalendarDisplayCode::LONG_YEAR: - // if (aCalendar.Name.equalsAscii("gengou")) - // swprintf(aStr, L"%02d", value); // #100211# - checked - // else - swprintf(aStr, sizeof(aStr) / sizeof(wchar_t), L"%d", value); // #100211# - checked - break; - case CalendarDisplayCode::LONG_MONTH: - value += 1; // month is zero based - swprintf(aStr, sizeof(aStr) / sizeof(wchar_t), L"%02d", value); // #100211# - checked - break; - case CalendarDisplayCode::SHORT_YEAR: - // Take last 2 digits, or only one if value<10, for example, - // in case of the Gengou calendar. - // #i116701# For values in non-Gregorian era years use all - // digits. - if (value < 100 || eraArray) - swprintf(aStr, sizeof(aStr) / sizeof(wchar_t), L"%d", value); // #100211# - checked - else - swprintf(aStr, sizeof(aStr) / sizeof(wchar_t), L"%02d", value % 100); // #100211# - checked - break; - case CalendarDisplayCode::LONG_DAY: - swprintf(aStr, sizeof(aStr) / sizeof(wchar_t), L"%02d", value); // #100211# - checked - break; - - case CalendarDisplayCode::SHORT_DAY_NAME: - return getDisplayName(CalendarDisplayIndex::CDI_DAY, value, 0); - case CalendarDisplayCode::LONG_DAY_NAME: - return getDisplayName(CalendarDisplayIndex::CDI_DAY, value, 1); - case CalendarDisplayCode::SHORT_MONTH_NAME: - return getDisplayName(CalendarDisplayIndex::CDI_MONTH, value, 0); - case CalendarDisplayCode::LONG_MONTH_NAME: - return getDisplayName(CalendarDisplayIndex::CDI_MONTH, value, 1); - case CalendarDisplayCode::SHORT_ERA: - return getDisplayName(CalendarDisplayIndex::CDI_ERA, value, 0); - case CalendarDisplayCode::LONG_ERA: - return getDisplayName(CalendarDisplayIndex::CDI_ERA, value, 1); - - case CalendarDisplayCode::SHORT_YEAR_AND_ERA: - return getDisplayString(CalendarDisplayCode::SHORT_ERA, nNativeNumberMode) + - getDisplayString(CalendarDisplayCode::SHORT_YEAR, nNativeNumberMode); - - case CalendarDisplayCode::LONG_YEAR_AND_ERA: - return getDisplayString(CalendarDisplayCode::LONG_ERA, nNativeNumberMode) + - getDisplayString(CalendarDisplayCode::LONG_YEAR, nNativeNumberMode); - - default: - return L""; - } - aOUStr = aStr; - } - return aOUStr; -} - -void Calendar::setDateTime(double timeInDays_val) { - double fDiff = DateTime(*(GetNullDate())) - getEpochStart(); - timeInDays = timeInDays_val - fDiff; - DateTime dt; - dt += timeInDays; - setValue(CalendarFieldIndex::AM_PM, dt.GetHour() < 12 ? 0 : 1); - setValue(CalendarFieldIndex::DAY_OF_MONTH, dt.GetDay()); - setValue(CalendarFieldIndex::DAY_OF_WEEK, dt.GetDayOfWeek() + 1); - setValue(CalendarFieldIndex::DAY_OF_YEAR, dt.GetDayOfYear()); - setValue(CalendarFieldIndex::CFI_HOUR, dt.GetHour()); - setValue(CalendarFieldIndex::CFI_MINUTE, dt.GetMin()); - setValue(CalendarFieldIndex::CFI_SECOND, dt.GetSec()); - setValue(CalendarFieldIndex::CFI_MILLISECOND, dt.Get100Sec() * 10); - setValue(CalendarFieldIndex::WEEK_OF_YEAR, dt.GetWeekOfYear()); - setValue(CalendarFieldIndex::CFI_YEAR, dt.GetYear()); - setValue(CalendarFieldIndex::CFI_MONTH, dt.GetMonth() - 1); -} - -double Calendar::getDateTime() { - return timeInDays; -} - -sal_Int32 Calendar::getCombinedOffsetInMillis(sal_Int16 nParentFieldIndex, sal_Int16 nChildFieldIndex) { - sal_Int32 nOffset = 0; - nOffset = (sal_Int32)(getValue(nParentFieldIndex)) * 60000; - sal_Int16 nSecondMillis = getValue(nChildFieldIndex); - if (nOffset < 0) - nOffset -= static_cast(nSecondMillis); - else - nOffset += static_cast(nSecondMillis); - return nOffset; -} - -sal_Int32 Calendar::getZoneOffsetInMillis() { - return getCombinedOffsetInMillis(CalendarFieldIndex::ZONE_OFFSET, CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS); -} - -sal_Int32 Calendar::getDSTOffsetInMillis() { - return getCombinedOffsetInMillis(CalendarFieldIndex::DST_OFFSET, CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS); -} - -void Calendar::setLocalDateTime(double nTimeInDays) { - setDateTime(nTimeInDays); - sal_Int32 nZone1 = getZoneOffsetInMillis(); - sal_Int32 nDST1 = getDSTOffsetInMillis(); - double nLoc = nTimeInDays - (double)(nZone1 + nDST1) / MILLISECONDS_PER_DAY; - setDateTime(nLoc); - sal_Int32 nZone2 = getZoneOffsetInMillis(); - sal_Int32 nDST2 = getDSTOffsetInMillis(); - if (nDST1 != nDST2) { - nLoc = nTimeInDays - (double)(nZone2 + nDST2) / MILLISECONDS_PER_DAY; - setDateTime(nLoc); - sal_Int32 nDST3 = getDSTOffsetInMillis(); - if (nDST2 != nDST3 && !nDST3) { - nLoc = nTimeInDays - (double)(nZone2 + nDST3) / MILLISECONDS_PER_DAY; - setDateTime(nLoc); - } - } -} - -double Calendar::getLocalDateTime() { - double nTimeInDays = getDateTime(); - sal_Int32 nZone = getZoneOffsetInMillis(); - sal_Int32 nDST = getDSTOffsetInMillis(); - nTimeInDays += (double)(nZone + nDST) / MILLISECONDS_PER_DAY; - return nTimeInDays; -} - -void Calendar::ChangeNullDate(const sal_uInt16 Day, const sal_uInt16 Month, const sal_uInt16 Year) { - if (pNullDate) - *pNullDate = Date(Day, Month, Year); - else - pNullDate = new Date(Day, Month, Year); -} - - -//------------- datetime.cxx ------------------------------------ - -bool DateTime::IsBetween( const DateTime& rFrom, - const DateTime& rTo ) const -{ - if ( (*this >= rFrom) && (*this <= rTo) ) - return true; - else - return false; -} - -bool DateTime::operator >( const DateTime& rDateTime ) const -{ - if ( (Date::operator>( rDateTime )) || - (Date::operator==( rDateTime ) && Time::operator>( rDateTime )) ) - return true; - else - return false; -} - -bool DateTime::operator <( const DateTime& rDateTime ) const -{ - if ( (Date::operator<( rDateTime )) || - (Date::operator==( rDateTime ) && Time::operator<( rDateTime )) ) - return true; - else - return false; -} - -bool DateTime::operator >=( const DateTime& rDateTime ) const -{ - if ( (Date::operator>( rDateTime )) || - (Date::operator==( rDateTime ) && Time::operator>=( rDateTime )) ) - return true; - else - return false; -} - -bool DateTime::operator <=( const DateTime& rDateTime ) const -{ - if ( (Date::operator<( rDateTime )) || - (Date::operator==( rDateTime ) && Time::operator<=( rDateTime )) ) - return true; - else - return false; -} - -long DateTime::GetSecFromDateTime( const Date& rDate ) const -{ - if ( Date::operator<( rDate ) ) - return 0; - else - { - long nSec = Date( *this ) - rDate; - nSec *= 24UL*60*60; - long nHour = GetHour(); - long nMin = GetMin(); - nSec += (nHour*3600)+(nMin*60)+GetSec(); - return nSec; - } -} - -void DateTime::MakeDateTimeFromSec( const Date& rDate, sal_uIntPtr nSec ) -{ - long nDays = nSec / (24UL*60*60); - ((Date*)this)->operator=( rDate ); - nSec -= nDays * (24UL*60*60); - sal_uInt16 nMin = (sal_uInt16)(nSec / 60); - nSec -= nMin * 60; - ((Time*)this)->operator=( Time( 0, nMin, (sal_uInt16)nSec ) ); - operator+=( nDays ); -} - -DateTime& DateTime::operator +=( const Time& rTime ) -{ - Time aTime = *this; - aTime += rTime; - sal_uInt16 nHours = aTime.GetHour(); - if ( aTime.GetTime() > 0 ) - { - while ( nHours >= 24 ) - { - Date::operator++(); - nHours -= 24; - } - aTime.SetHour( nHours ); - } - else if ( aTime.GetTime() != 0 ) - { - while ( nHours >= 24 ) - { - Date::operator--(); - nHours -= 24; - } - Date::operator--(); - aTime = Time( 24, 0, 0 )+aTime; - } - Time::operator=( aTime ); - - return *this; -} - -DateTime& DateTime::operator -=( const Time& rTime ) -{ - Time aTime = *this; - aTime -= rTime; - sal_uInt16 nHours = aTime.GetHour(); - if ( aTime.GetTime() > 0 ) - { - while ( nHours >= 24 ) - { - Date::operator++(); - nHours -= 24; - } - aTime.SetHour( nHours ); - } - else if ( aTime.GetTime() != 0 ) - { - while ( nHours >= 24 ) - { - Date::operator--(); - nHours -= 24; - } - Date::operator--(); - aTime = Time( 24, 0, 0 )+aTime; - } - Time::operator=( aTime ); - - return *this; -} - -DateTime operator +( const DateTime& rDateTime, long nDays ) -{ - DateTime aDateTime( rDateTime ); - aDateTime += nDays; - return aDateTime; -} - -DateTime operator -( const DateTime& rDateTime, long nDays ) -{ - DateTime aDateTime( rDateTime ); - aDateTime -= nDays; - return aDateTime; -} - -DateTime operator +( const DateTime& rDateTime, const Time& rTime ) -{ - DateTime aDateTime( rDateTime ); - aDateTime += rTime; - return aDateTime; -} - -DateTime operator -( const DateTime& rDateTime, const Time& rTime ) -{ - DateTime aDateTime( rDateTime ); - aDateTime -= rTime; - return aDateTime; -} - -DateTime& DateTime::operator +=( double fTimeInDays ) -{ - double fInt, fFrac; - if ( fTimeInDays < 0.0 ) - { - fInt = ceil( fTimeInDays ); - fFrac = fInt <= fTimeInDays ? 0.0 : fTimeInDays - fInt; - } - else - { - fInt = floor( fTimeInDays ); - fFrac = fInt >= fTimeInDays ? 0.0 : fTimeInDays - fInt; - } - Date::operator+=( long(fInt) ); // full days - if ( fFrac ) - { - Time aTime(0); // default ctor calls system time, we don't need that - fFrac *= 24UL * 60 * 60 * 1000; // time expressed in milliseconds - aTime.MakeTimeFromMS( long(fFrac) ); // method handles negative ms - operator+=( aTime ); - } - return *this; -} - -DateTime operator +( const DateTime& rDateTime, double fTimeInDays ) -{ - DateTime aDateTime( rDateTime ); - aDateTime += fTimeInDays; - return aDateTime; -} - -double operator -( const DateTime& rDateTime1, const DateTime& rDateTime2 ) -{ - long nDays = (const Date&) rDateTime1 - (const Date&) rDateTime2; - long nTime = rDateTime1.GetMSFromTime() - rDateTime2.GetMSFromTime(); - if ( nTime ) - { - double fTime = double(nTime); - fTime /= 24UL * 60 * 60 * 1000; // convert from milliseconds to fraction - if ( nDays < 0 && fTime > 0.0 ) - fTime = 1.0 - fTime; - return double(nDays) + fTime; - } - return double(nDays); -} - -void DateTime::GetWin32FileDateTime( sal_uInt32 & rLower, sal_uInt32 & rUpper ) -{ - const sal_Int64 a100nPerSecond = SAL_CONST_INT64( 10000000 ); - const sal_Int64 a100nPerDay = a100nPerSecond * sal_Int64( 60 * 60 * 24 ); - - sal_Int64 nYears = GetYear() - 1601; - sal_Int64 nDays = - nYears * 365 + - nYears / 4 - nYears / 100 + nYears / 400 + - GetDayOfYear() - 1; - - sal_Int64 aTime = - a100nPerDay * nDays + - a100nPerSecond * ( - sal_Int64( GetSec() ) + - 60 * sal_Int64( GetMin() ) + - 60 * 60 * sal_Int64( GetHour() ) ); - - rLower = sal_uInt32( aTime % SAL_CONST_UINT64( 0x100000000 ) ); - rUpper = sal_uInt32( aTime / SAL_CONST_UINT64( 0x100000000 ) ); -} - -DateTime DateTime::CreateFromWin32FileDateTime( const sal_uInt32 & rLower, const sal_uInt32 & rUpper ) -{ - const sal_Int64 a100nPerSecond = SAL_CONST_INT64( 10000000 ); - const sal_Int64 a100nPerDay = a100nPerSecond * sal_Int64( 60 * 60 * 24 ); - - sal_Int64 aTime = sal_Int64( - sal_uInt64( rUpper ) * SAL_CONST_UINT64( 0x100000000 ) + - sal_uInt64( rLower ) ); - - sal_Int64 nDays = aTime / a100nPerDay; - sal_Int64 nYears = - ( nDays - - ( nDays / ( 4 * 365 ) ) + - ( nDays / ( 100 * 365 ) ) - - ( nDays / ( 400 * 365 ) ) ) / 365; - nDays -= nYears * 365 + nYears / 4 - nYears / 100 + nYears / 400; - - sal_uInt16 nMonths = 0; - for( sal_Int64 nDaysCount = nDays; nDaysCount >= 0; ) - { - nDays = nDaysCount; - nMonths ++; - nDaysCount -= Date( - 1, nMonths, (sal_uInt16)(1601 + nYears) ). - GetDaysInMonth(); - } - - Date _aDate( - (sal_uInt16)( nDays + 1 ), nMonths, - (sal_uInt16)(nYears + 1601) ); - Time _aTime( sal_uIntPtr( ( aTime / ( a100nPerSecond * 60 * 60 ) ) % sal_Int64( 24 ) ), - sal_uIntPtr( ( aTime / ( a100nPerSecond * 60 ) ) % sal_Int64( 60 ) ), - sal_uIntPtr( ( aTime / ( a100nPerSecond ) ) % sal_Int64( 60 ) ) ); - - return DateTime( _aDate, _aTime ); -} - - -// ----------------------- tdate.cxx ------------------------------------- - -static sal_uInt16 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -#define MAX_DAYS 3636532 - -inline bool ImpIsLeapYear( sal_uInt16 nYear ) -{ - return ( - ( ((nYear % 4) == 0) && ((nYear % 100) != 0) ) || - ( (nYear % 400) == 0 ) - ); -} - -inline sal_uInt16 DaysInMonth( sal_uInt16 nMonth, sal_uInt16 nYear ) -{ - if ( nMonth != 2 ) - return aDaysInMonth[nMonth-1]; - else - { - if (ImpIsLeapYear(nYear)) - return aDaysInMonth[nMonth-1] + 1; - else - return aDaysInMonth[nMonth-1]; - } -} - -long Date::DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear ) -{ - long nDays; - - nDays = ((sal_uIntPtr)nYear-1) * 365; - nDays += ((nYear-1) / 4) - ((nYear-1) / 100) + ((nYear-1) / 400); - for( sal_uInt16 i = 1; i < nMonth; i++ ) - nDays += DaysInMonth(i,nYear); - nDays += nDay; - return nDays; -} - -static void DaysToDate( long nDays, - sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear ) -{ - long nTempDays; - long i = 0; - bool bCalc; - - do - { - nTempDays = (long)nDays; - rYear = (sal_uInt16)((nTempDays / 365) - i); - nTempDays -= ((sal_uIntPtr)rYear-1) * 365; - nTempDays -= ((rYear-1) / 4) - ((rYear-1) / 100) + ((rYear-1) / 400); - bCalc = false; - if ( nTempDays < 1 ) - { - i++; - bCalc = true; - } - else - { - if ( nTempDays > 365 ) - { - if ( (nTempDays != 366) || !ImpIsLeapYear( rYear ) ) - { - i--; - bCalc = true; - } - } - } - } - while ( bCalc ); - - rMonth = 1; - while ( (sal_uIntPtr)nTempDays > DaysInMonth( rMonth, rYear ) ) - { - nTempDays -= DaysInMonth( rMonth, rYear ); - rMonth++; - } - rDay = (sal_uInt16)nTempDays; -} - -Date::Date() -{ - time_t nTmpTime; - struct tm aTime; - - nTmpTime = time( 0 ); - nDate = 30 + 1200 + (((sal_uIntPtr)1899)*10000); -} - -void Date::SetDay( sal_uInt16 nNewDay ) -{ - sal_uIntPtr nMonth = GetMonth(); - sal_uIntPtr nYear = GetYear(); - - nDate = ((sal_uIntPtr)(nNewDay%100)) + (nMonth*100) + (nYear*10000); -} - -void Date::SetMonth( sal_uInt16 nNewMonth ) -{ - sal_uIntPtr nDay = GetDay(); - sal_uIntPtr nYear = GetYear(); - - nDate = nDay + (((sal_uIntPtr)(nNewMonth%100))*100) + (nYear*10000); -} - -void Date::SetYear( sal_uInt16 nNewYear ) -{ - sal_uIntPtr nDay = GetDay(); - sal_uIntPtr nMonth = GetMonth(); - - nDate = nDay + (nMonth*100) + (((sal_uIntPtr)(nNewYear%10000))*10000); -} - -DayOfWeek Date::GetDayOfWeek() const -{ - return (DayOfWeek)((sal_uIntPtr)(DateToDays( GetDay(), GetMonth(), GetYear() )-1) % 7); -} - -sal_uInt16 Date::GetDayOfYear() const -{ - sal_uInt16 nDay = GetDay(); - for( sal_uInt16 i = 1; i < GetMonth(); i++ ) - nDay = nDay + DaysInMonth( i, GetYear() ); // += yields a warning on MSVC, so don't use it - return nDay; -} - -sal_uInt16 Date::GetWeekOfYear( DayOfWeek eStartDay, - sal_Int16 nMinimumNumberOfDaysInWeek ) const -{ - short nWeek; - short n1WDay = (short)Date( 1, 1, GetYear() ).GetDayOfWeek(); - short nDayOfYear = (short)GetDayOfYear(); - - // Days of the week start at 0, so subtract one - nDayOfYear--; - // StartDay consider - n1WDay = (n1WDay+(7-(short)eStartDay)) % 7; - - if (nMinimumNumberOfDaysInWeek < 1 || 7 < nMinimumNumberOfDaysInWeek) - { - //DBG_ERRORFILE("Date::GetWeekOfYear: invalid nMinimumNumberOfDaysInWeek"); - nMinimumNumberOfDaysInWeek = 4; - } - - if ( nMinimumNumberOfDaysInWeek == 1 ) - { - nWeek = ((n1WDay+nDayOfYear)/7) + 1; - // 53rd week only if we are not already in the first - // week of the new year lie - if ( nWeek == 54 ) - nWeek = 1; - else if ( nWeek == 53 ) - { - short nDaysInYear = (short)GetDaysInYear(); - short nDaysNextYear = (short)Date( 1, 1, GetYear()+1 ).GetDayOfWeek(); - nDaysNextYear = (nDaysNextYear+(7-(short)eStartDay)) % 7; - if ( nDayOfYear > (nDaysInYear-nDaysNextYear-1) ) - nWeek = 1; - } - } - else if ( nMinimumNumberOfDaysInWeek == 7 ) - { - nWeek = ((n1WDay+nDayOfYear)/7); - // First week of a year corresponds to the last week of previous year - if ( nWeek == 0 ) - { - Date aLastDatePrevYear( 31, 12, GetYear()-1 ); - nWeek = aLastDatePrevYear.GetWeekOfYear( eStartDay, nMinimumNumberOfDaysInWeek ); - } - } - else // ( nMinimumNumberOfDaysInWeek == somehing_else, commentary examples for 4 ) - { - // x_monday - thursday - if ( n1WDay < nMinimumNumberOfDaysInWeek ) - nWeek = 1; - // friday - else if ( n1WDay == nMinimumNumberOfDaysInWeek ) - nWeek = 53; - // saturday - else if ( n1WDay == nMinimumNumberOfDaysInWeek + 1 ) - { - // year after leap year - if ( Date( 1, 1, GetYear()-1 ).IsLeapYear() ) - nWeek = 53; - else - nWeek = 52; - } - // sunday - else - nWeek = 52; - - if ( (nWeek == 1) || (nDayOfYear + n1WDay > 6) ) - { - if ( nWeek == 1 ) - nWeek += (nDayOfYear + n1WDay) / 7; - else - nWeek = (nDayOfYear + n1WDay) / 7; - if ( nWeek == 53 ) - { - // next x_Sunday == first x_Sunday in the new year - // == same week - long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() ); - nTempDays += 6 - (GetDayOfWeek()+(7-(short)eStartDay)) % 7; - sal_uInt16 nDay; - sal_uInt16 nMonth; - sal_uInt16 nYear; - DaysToDate( nTempDays, nDay, nMonth, nYear ); - nWeek = Date( nDay, nMonth, nYear ).GetWeekOfYear( eStartDay, nMinimumNumberOfDaysInWeek ); - } - } - } - - return (sal_uInt16)nWeek; -} - -sal_uInt16 Date::GetDaysInMonth() const -{ - return DaysInMonth( GetMonth(), GetYear() ); -} - -bool Date::IsLeapYear() const -{ - sal_uInt16 nYear = GetYear(); - return ImpIsLeapYear( nYear ); -} - -bool Date::IsValid() const -{ - sal_uInt16 nDay = GetDay(); - sal_uInt16 nMonth = GetMonth(); - sal_uInt16 nYear = GetYear(); - - if ( !nMonth || (nMonth > 12) ) - return false; - if ( !nDay || (nDay > DaysInMonth( nMonth, nYear )) ) - return false; - else if ( nYear <= 1582 ) - { - if ( nYear < 1582 ) - return false; - else if ( nMonth < 10 ) - return false; - else if ( (nMonth == 10) && (nDay < 15) ) - return false; - } - - return true; -} - -Date& Date::operator +=( long nDays ) -{ - sal_uInt16 nDay; - sal_uInt16 nMonth; - sal_uInt16 nYear; - long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() ); - - nTempDays += nDays; - if ( nTempDays > MAX_DAYS ) - nDate = 31 + (12*100) + (((sal_uIntPtr)9999)*10000); - else if ( nTempDays <= 0 ) - nDate = 1 + 100; - else - { - DaysToDate( nTempDays, nDay, nMonth, nYear ); - nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000); - } - - return *this; -} - -Date& Date::operator -=( long nDays ) -{ - sal_uInt16 nDay; - sal_uInt16 nMonth; - sal_uInt16 nYear; - long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() ); - - nTempDays -= nDays; - if ( nTempDays > MAX_DAYS ) - nDate = 31 + (12*100) + (((sal_uIntPtr)9999)*10000); - else if ( nTempDays <= 0 ) - nDate = 1 + 100; - else - { - DaysToDate( nTempDays, nDay, nMonth, nYear ); - nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000); - } - - return *this; -} - -Date& Date::operator ++() -{ - sal_uInt16 nDay; - sal_uInt16 nMonth; - sal_uInt16 nYear; - long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() ); - - if ( nTempDays < MAX_DAYS ) - { - nTempDays++; - DaysToDate( nTempDays, nDay, nMonth, nYear ); - nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000); - } - - return *this; -} - -Date& Date::operator --() -{ - sal_uInt16 nDay; - sal_uInt16 nMonth; - sal_uInt16 nYear; - long nTempDays = DateToDays( GetDay(), GetMonth(), GetYear() ); - - if ( nTempDays > 1 ) - { - nTempDays--; - DaysToDate( nTempDays, nDay, nMonth, nYear ); - nDate = ((sal_uIntPtr)nDay) + (((sal_uIntPtr)nMonth)*100) + (((sal_uIntPtr)nYear)*10000); - } - return *this; -} - -#ifndef MPW33 - -Date Date::operator ++( int ) -{ - Date aOldDate = *this; - Date::operator++(); - return aOldDate; -} - -Date Date::operator --( int ) -{ - Date aOldDate = *this; - Date::operator--(); - return aOldDate; -} - -#endif - -Date operator +( const Date& rDate, long nDays ) -{ - Date aDate( rDate ); - aDate += nDays; - return aDate; -} - -Date operator -( const Date& rDate, long nDays ) -{ - Date aDate( rDate ); - aDate -= nDays; - return aDate; -} - -long operator -( const Date& rDate1, const Date& rDate2 ) -{ - sal_uIntPtr nTempDays1 = Date::DateToDays( rDate1.GetDay(), rDate1.GetMonth(), - rDate1.GetYear() ); - sal_uIntPtr nTempDays2 = Date::DateToDays( rDate2.GetDay(), rDate2.GetMonth(), - rDate2.GetYear() ); - return nTempDays1 - nTempDays2; -} - - -// -------------------------- ttime.cxx ---------------------------------------- - -static sal_Int32 TimeToSec100( const Time& rTime ) -{ - short nSign = (rTime.GetTime() >= 0) ? +1 : -1; - sal_Int32 nHour = rTime.GetHour(); - sal_Int32 nMin = rTime.GetMin(); - sal_Int32 nSec = rTime.GetSec(); - sal_Int32 n100Sec = rTime.Get100Sec(); - -// Wegen Interal Compiler Error bei MSC, etwas komplizierter -// return (n100Sec + (nSec*100) + (nMin*60*100) + (nHour*60*60*100) * nSign); - - sal_Int32 nRet = n100Sec; - nRet += nSec*100; - nRet += nMin*60*100; - nRet += nHour*60*60*100; - - return (nRet * nSign); -} - -static Time Sec100ToTime( sal_Int32 nSec100 ) -{ - short nSign; - if ( nSec100 < 0 ) - { - nSec100 *= -1; - nSign = -1; - } - else - nSign = 1; - - Time aTime( 0, 0, 0, nSec100 ); - aTime.SetTime( aTime.GetTime() * nSign ); - return aTime; -} - -Time::Time() -{ - nTime = 0; -} - -Time::Time( const Time& rTime ) -{ - nTime = rTime.nTime; -} - -Time::Time( sal_uIntPtr nHour, sal_uIntPtr nMin, sal_uIntPtr nSec, sal_uIntPtr n100Sec ) -{ - nSec += n100Sec / 100; - n100Sec = n100Sec % 100; - nMin += nSec / 60; - nSec = nSec % 60; - nHour += nMin / 60; - nMin = nMin % 60; - - nTime = (sal_Int32)(n100Sec + (nSec*100) + (nMin*10000) + (nHour*1000000)); -} - -void Time::SetHour( sal_uInt16 nNewHour ) -{ - short nSign = (nTime >= 0) ? +1 : -1; - sal_Int32 nMin = GetMin(); - sal_Int32 nSec = GetSec(); - sal_Int32 n100Sec = Get100Sec(); - - nTime = (n100Sec + (nSec*100) + (nMin*10000) + - (((sal_Int32)nNewHour)*1000000)) * nSign; -} - -void Time::SetMin( sal_uInt16 nNewMin ) -{ - short nSign = (nTime >= 0) ? +1 : -1; - sal_Int32 nHour = GetHour(); - sal_Int32 nSec = GetSec(); - sal_Int32 n100Sec = Get100Sec(); - - nNewMin = nNewMin % 60; - - nTime = (n100Sec + (nSec*100) + (((sal_Int32)nNewMin)*10000) + - (nHour*1000000)) * nSign; -} - -void Time::SetSec( sal_uInt16 nNewSec ) -{ - short nSign = (nTime >= 0) ? +1 : -1; - sal_Int32 nHour = GetHour(); - sal_Int32 nMin = GetMin(); - sal_Int32 n100Sec = Get100Sec(); - - nNewSec = nNewSec % 60; - - nTime = (n100Sec + (((sal_Int32)nNewSec)*100) + (nMin*10000) + - (nHour*1000000)) * nSign; -} - -void Time::Set100Sec( sal_uInt16 nNew100Sec ) -{ - short nSign = (nTime >= 0) ? +1 : -1; - sal_Int32 nHour = GetHour(); - sal_Int32 nMin = GetMin(); - sal_Int32 nSec = GetSec(); - - nNew100Sec = nNew100Sec % 100; - - nTime = (((sal_Int32)nNew100Sec) + (nSec*100) + (nMin*10000) + - (nHour*1000000)) * nSign; -} - -sal_Int32 Time::GetMSFromTime() const -{ - short nSign = (nTime >= 0) ? +1 : -1; - sal_Int32 nHour = GetHour(); - sal_Int32 nMin = GetMin(); - sal_Int32 nSec = GetSec(); - sal_Int32 n100Sec = Get100Sec(); - - return (((nHour*3600000)+(nMin*60000)+(nSec*1000)+(n100Sec*10))*nSign); -} - -void Time::MakeTimeFromMS( sal_Int32 nMS ) -{ - short nSign; - if ( nMS < 0 ) - { - nMS *= -1; - nSign = -1; - } - else - nSign = 1; - - Time aTime( 0, 0, 0, nMS/10 ); - SetTime( aTime.GetTime() * nSign ); -} - -double Time::GetTimeInDays() const -{ - short nSign = (nTime >= 0) ? +1 : -1; - double nHour = GetHour(); - double nMin = GetMin(); - double nSec = GetSec(); - double n100Sec = Get100Sec(); - - return (nHour+(nMin/60)+(nSec/(60*60))+(n100Sec/(60*60*100))) / 24 * nSign; -} - -Time& Time::operator =( const Time& rTime ) -{ - nTime = rTime.nTime; - return *this; -} - -Time& Time::operator +=( const Time& rTime ) -{ - nTime = Sec100ToTime( TimeToSec100( *this ) + - TimeToSec100( rTime ) ).GetTime(); - return *this; -} - -Time& Time::operator -=( const Time& rTime ) -{ - nTime = Sec100ToTime( TimeToSec100( *this ) - - TimeToSec100( rTime ) ).GetTime(); - return *this; -} - -Time operator +( const Time& rTime1, const Time& rTime2 ) -{ - return Sec100ToTime( TimeToSec100( rTime1 ) + - TimeToSec100( rTime2 ) ); -} - -Time operator -( const Time& rTime1, const Time& rTime2 ) -{ - return Sec100ToTime( TimeToSec100( rTime1 ) - - TimeToSec100( rTime2 ) ); -} - -bool Time::IsEqualIgnore100Sec( const Time& rTime ) const -{ - sal_Int32 n1 = (nTime < 0 ? -Get100Sec() : Get100Sec() ); - sal_Int32 n2 = (rTime.nTime < 0 ? -rTime.Get100Sec() : rTime.Get100Sec() ); - return (nTime - n1) == (rTime.nTime - n2); -} - -Time Time::GetUTCOffset() -{ -#if defined( OS2 ) -#undef timezone - PM_DATETIME aDateTime; - DosGetDateTime( &aDateTime ); - - // Zeit zusammenbauen - if ( aDateTime.timezone != -1 ) - { - short nTempTime = (short)Abs( aDateTime.timezone ); - Time aTime( 0, (sal_uInt16)nTempTime ); - if ( aDateTime.timezone > 0 ) - aTime = -aTime; - return aTime; - } - else - return Time( 0 ); -#elif defined( _WIN32 ) - TIME_ZONE_INFORMATION aTimeZone; - aTimeZone.Bias = 0; - DWORD nTimeZoneRet = GetTimeZoneInformation( &aTimeZone ); - sal_Int32 nTempTime = aTimeZone.Bias; - if ( nTimeZoneRet == TIME_ZONE_ID_STANDARD ) - nTempTime += aTimeZone.StandardBias; - else if ( nTimeZoneRet == TIME_ZONE_ID_DAYLIGHT ) - nTempTime += aTimeZone.DaylightBias; - Time aTime( 0, (sal_uInt16)abs( nTempTime ) ); - if ( nTempTime > 0 ) - aTime = -aTime; - return aTime; -#else - static sal_uIntPtr nCacheTicks = 0; - static sal_Int32 nCacheSecOffset = -1; - sal_uIntPtr nTicks = Time::GetSystemTicks(); - time_t nTime; - tm aTM; - sal_Int32 nLocalTime; - sal_Int32 nUTC; - short nTempTime; - - // Evt. Wert neu ermitteln - if ( (nCacheSecOffset == -1) || - ((nTicks - nCacheTicks) > 360000) || - ( nTicks < nCacheTicks ) // handle overflow - ) - { - nTime = time( 0 ); - localtime_r( &nTime, &aTM ); - nLocalTime = mktime( &aTM ); -#if defined( SOLARIS ) - // Solaris gmtime_r() seems not to handle daylight saving time - // flags correctly - nUTC = nLocalTime + ( aTM.tm_isdst == 0 ? timezone : altzone ); -#elif defined( LINUX ) - // Linux mktime() seems not to handle tm_isdst correctly - nUTC = nLocalTime - aTM.tm_gmtoff; -#else - gmtime_r( &nTime, &aTM ); - nUTC = mktime( &aTM ); -#endif - nCacheTicks = nTicks; - nCacheSecOffset = (nLocalTime-nUTC) / 60; - } - - nTempTime = (short)abs( nCacheSecOffset ); - Time aTime( 0, (sal_uInt16)nTempTime ); - if ( nCacheSecOffset < 0 ) - aTime = -aTime; - return aTime; -#endif -} - - -sal_uIntPtr Time::GetSystemTicks() -{ -#if defined _WIN32 - return (sal_uIntPtr)GetTickCount(); -#elif defined( OS2 ) - sal_uIntPtr nClock; - DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) ); - return (sal_uIntPtr)nClock; -#else - timeval tv; - gettimeofday(&tv, 0); - - double fTicks = tv.tv_sec; - fTicks *= 1000; - fTicks += ((tv.tv_usec + 500) / 1000); - - fTicks = fmod(fTicks, double(ULONG_MAX)); - return sal_uIntPtr(fTicks); -#endif -} - -sal_uIntPtr Time::GetProcessTicks() -{ -#if defined _WIN32 - return (sal_uIntPtr)GetTickCount(); -#elif defined( OS2 ) - sal_uIntPtr nClock; - DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &nClock, sizeof( nClock ) ); - return (sal_uIntPtr)nClock; -#else - static sal_uIntPtr nImplTicksPerSecond = 0; - static double dImplTicksPerSecond; - static double dImplTicksULONGMAX; - sal_uIntPtr nTicks = (sal_uIntPtr)clock(); - - if ( !nImplTicksPerSecond ) - { - nImplTicksPerSecond = CLOCKS_PER_SEC; - dImplTicksPerSecond = nImplTicksPerSecond; - dImplTicksULONGMAX = (double)(sal_uIntPtr)ULONG_MAX; - } - - double fTicks = nTicks; - fTicks *= 1000; - fTicks /= dImplTicksPerSecond; - fTicks = fmod (fTicks, dImplTicksULONGMAX); - return (sal_uIntPtr)fTicks; -#endif -} - -} // namespace duckdb_excel \ No newline at end of file diff --git a/extension/excel/numformat/nf_localedata.cpp b/extension/excel/numformat/nf_localedata.cpp deleted file mode 100644 index 571a74eefad..00000000000 --- a/extension/excel/numformat/nf_localedata.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include "nf_calendar.h" -#include "nf_localedata.h" - - -namespace duckdb_excel { - -LocaleData::LocaleData() { - LoadLocaleData(); - - m_cur_locale_id = LocaleId_en_US; - m_eval_date_format = NF_EVALDATEFORMAT_INTL; - - m_calendar_ptr = new Calendar(this); - m_num_format_scan_ptr = new ImpSvNumberformatScan(this); -} - -LocaleData::~LocaleData() { - if (m_calendar_ptr) { - delete m_calendar_ptr; - } - if (m_num_format_scan_ptr) { - delete m_num_format_scan_ptr; - } -} - -void LocaleData::LoadLocaleData() { - // en-US - // -------------------------------------------------------------------------------------------------------------------------------- - m_locale_list[LocaleId_en_US].seperators.date = L"/"; - m_locale_list[LocaleId_en_US].seperators.thousand = L","; - m_locale_list[LocaleId_en_US].seperators.decimal = L"."; - m_locale_list[LocaleId_en_US].seperators.time = L":"; - m_locale_list[LocaleId_en_US].seperators.time100sec = L"."; - m_locale_list[LocaleId_en_US].seperators.list = L";"; - m_locale_list[LocaleId_en_US].seperators.longdatedayofweek = L", "; - m_locale_list[LocaleId_en_US].seperators.longdateday = L", "; - m_locale_list[LocaleId_en_US].seperators.longdatemonth = L" "; - m_locale_list[LocaleId_en_US].seperators.longdateyear = L" "; - - m_locale_list[LocaleId_en_US].digit_grouping.clear(); - m_locale_list[LocaleId_en_US].digit_grouping.push_back(3); - m_locale_list[LocaleId_en_US].digit_grouping.push_back(0); - - std::wstring str = L"USD"; - m_locale_list[LocaleId_en_US].setCurrentCurrencyId(str); - m_locale_list[LocaleId_en_US].currency[L"USD"].currency_symbol = L"$"; - m_locale_list[LocaleId_en_US].currency[L"USD"].bank_symbol = L"USD"; - m_locale_list[LocaleId_en_US].currency[L"USD"].currency_name = L"US Dollar"; - m_locale_list[LocaleId_en_US].currency[L"USD"].decimal_places = 2; - - m_locale_list[LocaleId_en_US].time_am = L"AM"; - m_locale_list[LocaleId_en_US].time_pm = L"PM"; - - m_locale_list[LocaleId_en_US].date_format = MDY; - - m_locale_list[LocaleId_en_US].months_of_year.clear(); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"jan", L"Jan", L"January"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"feb", L"Feb", L"February"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"mar", L"Mar", L"March"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"apr", L"Apr", L"April"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"may", L"May", L"May"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"jun", L"Jun", L"June"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"jul", L"Jul", L"July"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"aug", L"Aug", L"August"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"sep", L"Sep", L"September"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"oct", L"Oct", L"October"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"nov", L"Nov", L"November"}); - m_locale_list[LocaleId_en_US].months_of_year.push_back({L"dec", L"Dec", L"December"}); - - m_locale_list[LocaleId_en_US].days_of_week.clear(); - m_locale_list[LocaleId_en_US].days_of_week.push_back({L"sun", L"Sun", L"Sunday"}); - m_locale_list[LocaleId_en_US].days_of_week.push_back({L"mon", L"Mon", L"Monday"}); - m_locale_list[LocaleId_en_US].days_of_week.push_back({L"tue", L"Tue", L"Tuesday"}); - m_locale_list[LocaleId_en_US].days_of_week.push_back({L"wed", L"Wed", L"Wednesday"}); - m_locale_list[LocaleId_en_US].days_of_week.push_back({L"thu", L"Thu", L"Thursday"}); - m_locale_list[LocaleId_en_US].days_of_week.push_back({L"fri", L"Fri", L"Friday"}); - m_locale_list[LocaleId_en_US].days_of_week.push_back({L"sat", L"Sat", L"Saturday"}); - - m_locale_list[LocaleId_en_US].reserved_words[0] = L"true"; - m_locale_list[LocaleId_en_US].reserved_words[1] = L"false"; - m_locale_list[LocaleId_en_US].reserved_words[2] = L"1st quarter"; - m_locale_list[LocaleId_en_US].reserved_words[3] = L"2nd quarter"; - m_locale_list[LocaleId_en_US].reserved_words[4] = L"3rd quarter"; - m_locale_list[LocaleId_en_US].reserved_words[5] = L"4th quarter"; - m_locale_list[LocaleId_en_US].reserved_words[6] = L"above"; - m_locale_list[LocaleId_en_US].reserved_words[7] = L"below"; - m_locale_list[LocaleId_en_US].reserved_words[8] = L"Q1"; - m_locale_list[LocaleId_en_US].reserved_words[9] = L"Q2"; - m_locale_list[LocaleId_en_US].reserved_words[10] = L"Q3"; - m_locale_list[LocaleId_en_US].reserved_words[11] = L"Q4"; - - m_locale_list[LocaleId_en_US].format_codes.fixed_format_key1 = L"General"; - m_locale_list[LocaleId_en_US].format_codes.scientific_format_key1 = L"0.00E+000"; - m_locale_list[LocaleId_en_US].format_codes.percent_format_key1 = L"0%"; - m_locale_list[LocaleId_en_US].format_codes.currency_format_key1 = L"[CURRENCY]#,##0;-[CURRENCY]#,##0"; - m_locale_list[LocaleId_en_US].format_codes.date_format_key1 = L"M/D/YY"; - m_locale_list[LocaleId_en_US].format_codes.date_format_key9 = L"NNNNMMMM DD, YYYY"; - m_locale_list[LocaleId_en_US].format_codes.datetime_format_key1 = L"MM/DD/YY HH:MM AM/PM"; - - m_locale_list[LocaleId_en_US].eras.clear(); - m_locale_list[LocaleId_en_US].eras.push_back({L"BC", L"BC"}); - m_locale_list[LocaleId_en_US].eras.push_back({L"AD", L"AD"}); - - // fr-FR - // -------------------------------------------------------------------------------------------------------------------------------- - m_locale_list[LocaleId_fr_FR].seperators.date = L"/"; - m_locale_list[LocaleId_fr_FR].seperators.thousand = L" "; - m_locale_list[LocaleId_fr_FR].seperators.decimal = L","; - m_locale_list[LocaleId_fr_FR].seperators.time = L":"; - m_locale_list[LocaleId_fr_FR].seperators.time100sec = L","; - m_locale_list[LocaleId_fr_FR].seperators.list = L";"; - m_locale_list[LocaleId_fr_FR].seperators.longdatedayofweek = L" "; - m_locale_list[LocaleId_fr_FR].seperators.longdateday = L" "; - m_locale_list[LocaleId_fr_FR].seperators.longdatemonth = L" "; - m_locale_list[LocaleId_fr_FR].seperators.longdateyear = L" "; - - m_locale_list[LocaleId_fr_FR].digit_grouping.clear(); - m_locale_list[LocaleId_fr_FR].digit_grouping.push_back(3); - m_locale_list[LocaleId_fr_FR].digit_grouping.push_back(0); - - str = L"EUR"; - m_locale_list[LocaleId_fr_FR].setCurrentCurrencyId(str); - m_locale_list[LocaleId_fr_FR].currency[L"EUR"].currency_symbol = L"€"; - m_locale_list[LocaleId_fr_FR].currency[L"EUR"].bank_symbol = L"EUR"; - m_locale_list[LocaleId_fr_FR].currency[L"EUR"].currency_name = L"euro"; - m_locale_list[LocaleId_fr_FR].currency[L"EUR"].decimal_places = 2; - m_locale_list[LocaleId_fr_FR].currency[L"FRF"].currency_symbol = L"F"; - m_locale_list[LocaleId_fr_FR].currency[L"FRF"].bank_symbol = L"FRF"; - m_locale_list[LocaleId_fr_FR].currency[L"FRF"].currency_name = L"franc français"; - m_locale_list[LocaleId_fr_FR].currency[L"FRF"].decimal_places = 2; - - m_locale_list[LocaleId_fr_FR].time_am = L"AM"; - m_locale_list[LocaleId_fr_FR].time_pm = L"PM"; - - m_locale_list[LocaleId_fr_FR].date_format = DMY; - - m_locale_list[LocaleId_fr_FR].months_of_year.clear(); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"jan", L"janv.", L"janvier"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"feb", L"févr.", L"février"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"mar", L"mars", L"mars"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"apr", L"avr.", L"avril"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"may", L"mai", L"mai"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"jun", L"juin", L"juin"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"jul", L"juil.", L"juillet"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"aug", L"août", L"août"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"sep", L"sept.", L"septembre"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"oct", L"oct.", L"octobre"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"nov", L"nov.", L"novembre"}); - m_locale_list[LocaleId_fr_FR].months_of_year.push_back({L"dec", L"déc.", L"décembre"}); - - m_locale_list[LocaleId_fr_FR].days_of_week.clear(); - m_locale_list[LocaleId_fr_FR].days_of_week.push_back({L"sun", L"dim.", L"dimanche"}); - m_locale_list[LocaleId_fr_FR].days_of_week.push_back({L"mon", L"lun.", L"lundi"}); - m_locale_list[LocaleId_fr_FR].days_of_week.push_back({L"tue", L"mar.", L"mardi"}); - m_locale_list[LocaleId_fr_FR].days_of_week.push_back({L"wed", L"mer.", L"mercredi"}); - m_locale_list[LocaleId_fr_FR].days_of_week.push_back({L"thu", L"jeu.", L"jeudi"}); - m_locale_list[LocaleId_fr_FR].days_of_week.push_back({L"fri", L"ven.", L"vendredi"}); - m_locale_list[LocaleId_fr_FR].days_of_week.push_back({L"sat", L"sam.", L"samedi"}); - - m_locale_list[LocaleId_fr_FR].reserved_words[0] = L"vrai"; - m_locale_list[LocaleId_fr_FR].reserved_words[1] = L"faux"; - m_locale_list[LocaleId_fr_FR].reserved_words[2] = L"1er trimestre"; - m_locale_list[LocaleId_fr_FR].reserved_words[3] = L"2e trimestre"; - m_locale_list[LocaleId_fr_FR].reserved_words[4] = L"3e trimestre"; - m_locale_list[LocaleId_fr_FR].reserved_words[5] = L"4e trimestre"; - m_locale_list[LocaleId_fr_FR].reserved_words[6] = L"supra"; - m_locale_list[LocaleId_fr_FR].reserved_words[7] = L"infra"; - m_locale_list[LocaleId_fr_FR].reserved_words[8] = L"T1"; - m_locale_list[LocaleId_fr_FR].reserved_words[9] = L"T2"; - m_locale_list[LocaleId_fr_FR].reserved_words[10] = L"T3"; - m_locale_list[LocaleId_fr_FR].reserved_words[11] = L"T4"; - - m_locale_list[LocaleId_fr_FR].format_codes.fixed_format_key1 = L"Standard"; - m_locale_list[LocaleId_fr_FR].format_codes.scientific_format_key1 = L"0,00E+000"; - m_locale_list[LocaleId_fr_FR].format_codes.percent_format_key1 = L"0%"; - m_locale_list[LocaleId_fr_FR].format_codes.currency_format_key1 = L"# ##0 [CURRENCY];-# ##0 [CURRENCY]"; - m_locale_list[LocaleId_fr_FR].format_codes.date_format_key1 = L"JJ/MM/AAAA"; - m_locale_list[LocaleId_fr_FR].format_codes.date_format_key9 = L"NNNNJ MMMM AAAA"; - m_locale_list[LocaleId_fr_FR].format_codes.datetime_format_key1 = L"JJ/MM/AA HH:MM"; - - m_locale_list[LocaleId_fr_FR].eras.clear(); - m_locale_list[LocaleId_fr_FR].eras.push_back({L"av. J.-C.", L"av. J.-C."}); - m_locale_list[LocaleId_fr_FR].eras.push_back({L"apr. J.-C.", L"ap. J.-C."}); -} - -} // namespace duckdb_excel \ No newline at end of file diff --git a/extension/excel/numformat/nf_zformat.cpp b/extension/excel/numformat/nf_zformat.cpp deleted file mode 100644 index eba5b85fa42..00000000000 --- a/extension/excel/numformat/nf_zformat.cpp +++ /dev/null @@ -1,8712 +0,0 @@ -/************************************************************** - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - *************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "nf_calendar.h" -#include "nf_zformat.h" - - -namespace duckdb_excel { - -// --------------------------- zforfind.cxx --------------------------------------------- - -#ifndef DBG_UTIL -#define NF_TEST_CALENDAR 0 -#else -#define NF_TEST_CALENDAR 0 -#endif - -const sal_uInt8 ImpSvNumberInputScan::nMatchedEndString = 0x01; -const sal_uInt8 ImpSvNumberInputScan::nMatchedMidString = 0x02; -const sal_uInt8 ImpSvNumberInputScan::nMatchedStartString = 0x04; -const sal_uInt8 ImpSvNumberInputScan::nMatchedVirgin = 0x08; -const sal_uInt8 ImpSvNumberInputScan::nMatchedUsedAsReturn = 0x10; - -#define NF_RECOGNIZE_ISO8601_TIMEZONES 0 - - -enum ScanState -{ - SsStop, - SsStart, - SsGetCon, // condition - SsGetString, // format string - SsGetPrefix, // color or NatNumN - SsGetTime, // [HH] for time - SsGetBracketed, // any [...] not decided yet - SsGetValue, - SsGetChar, - SsGetWord, - SsGetStar, - SsGetBlank -}; - -ImpSvNumberInputScan::ImpSvNumberInputScan(LocaleData* pFormatterP ) - : - pUpperMonthText( NULL ), - pUpperAbbrevMonthText( NULL ), - pUpperDayText( NULL ), - pUpperAbbrevDayText( NULL ) -{ - pFormatter = pFormatterP; - nYear2000 = 1970; - time_t nTmpTime; - struct tm aTime; - nTmpTime = time(0); - if (localtime_r(&nTmpTime, &aTime)) - { - nYear2000 = aTime.tm_year + 2000; - } - Reset(); - ChangeIntl(); -} - - -ImpSvNumberInputScan::~ImpSvNumberInputScan() -{ - Reset(); - delete [] pUpperMonthText; - delete [] pUpperAbbrevMonthText; - delete [] pUpperDayText; - delete [] pUpperAbbrevDayText; -} - - -void ImpSvNumberInputScan::Reset() -{ - for (sal_uInt16 i = 0; i < SV_MAX_ANZ_INPUT_STRINGS; i++) - { - sStrArray[i].erase(); - nNums[i] = SV_MAX_ANZ_INPUT_STRINGS-1; - IsNum[i] = false; - } - - nMonth = 0; - nMonthPos = 0; - nTimePos = 0; - nSign = 0; - nESign = 0; - nDecPos = 0; - nNegCheck = 0; - nAnzStrings = 0; - nAnzNums = 0; - nThousand = 0; - eScannedType = NUMBERFORMAT_UNDEFINED; - nAmPm = 0; - nPosThousandString = 0; - nLogical = 0; - nStringScanNumFor = 0; - nStringScanSign = 0; - nMatchedAllStrings = nMatchedVirgin; - nMayBeIso8601 = 0; - nTimezonePos = 0; -} - - -inline bool ImpSvNumberInputScan::MyIsdigit( sal_Unicode c ) -{ - return c < 128 && isdigit( (unsigned char) c ); -} - - -double ImpSvNumberInputScan::StringToDouble( const String& rStr, bool bForceFraction ) -{ - double fNum = 0.0; - double fFrac = 0.0; - int nExp = 0; - uint16_t nPos = 0; - uint16_t nLen = rStr.size(); - bool bPreSep = !bForceFraction; - - while (nPos < nLen) - { - if (rStr.at(nPos) == L'.') - bPreSep = false; - else if (bPreSep) - fNum = fNum * 10.0 + (double) (rStr.at(nPos) - L'0'); - else - { - fFrac = fFrac * 10.0 + (double) (rStr.at(nPos) - L'0'); - --nExp; - } - nPos++; - } - if (fFrac) - return fNum + fFrac * pow(10.0, nExp); - return fNum; -} - - -bool ImpSvNumberInputScan::NextNumberStringSymbol( - const sal_Unicode*& pStr, - String& rSymbol ) -{ - bool isNumber = false; - sal_Unicode cToken; - ScanState eState = SsStart; - const sal_Unicode* pHere = pStr; - uint16_t nChars = 0; - - while ( ((cToken = *pHere) != 0) && eState != SsStop) - { - pHere++; - switch (eState) - { - case SsStart: - if ( MyIsdigit( cToken ) ) - { - eState = SsGetValue; - isNumber = true; - } - else - eState = SsGetString; - nChars++; - break; - case SsGetValue: - if ( MyIsdigit( cToken ) ) - nChars++; - else - { - eState = SsStop; - pHere--; - } - break; - case SsGetString: - if ( !MyIsdigit( cToken ) ) - nChars++; - else - { - eState = SsStop; - pHere--; - } - break; - default: - break; - } // switch - } // while - - if ( nChars ) - rSymbol.assign( pStr, nChars ); - else - rSymbol.erase(); - - pStr = pHere; - - return isNumber; -} - - -bool ImpSvNumberInputScan::SkipThousands( - const sal_Unicode*& pStr, - String& rSymbol ) -{ - bool res = false; - sal_Unicode cToken; - const String& rThSep = pFormatter->GetNumThousandSep(); - const sal_Unicode* pHere = pStr; - ScanState eState = SsStart; - uint16_t nCounter = 0; // counts 3 digits - - while ( ((cToken = *pHere) != 0) && eState != SsStop) - { - pHere++; - switch (eState) - { - case SsStart: - if ( StringPtrContains( rThSep, pHere-1, 0 ) ) - { - nCounter = 0; - eState = SsGetValue; - pHere += rThSep.size()-1; - } - else - { - eState = SsStop; - pHere--; - } - break; - case SsGetValue: - if ( MyIsdigit( cToken ) ) - { - rSymbol += cToken; - nCounter++; - if (nCounter == 3) - { - eState = SsStart; - res = true; // .000 combination found - } - } - else - { - eState = SsStop; - pHere--; - } - break; - default: - break; - } // switch - } // while - - if (eState == SsGetValue) // break witth less than 3 digits - { - if ( nCounter ) - rSymbol.erase( rSymbol.size() - nCounter, nCounter ); - pHere -= nCounter + rThSep.size(); // put back ThSep also - } - pStr = pHere; - - return res; -} - - -void ImpSvNumberInputScan::NumberStringDivision( const String& rString ) -{ - const sal_Unicode* pStr = rString.data(); - const sal_Unicode* const pEnd = pStr + rString.size(); - while ( pStr < pEnd && nAnzStrings < SV_MAX_ANZ_INPUT_STRINGS ) - { - if ( NextNumberStringSymbol( pStr, sStrArray[nAnzStrings] ) ) - { // Zahl - IsNum[nAnzStrings] = true; - nNums[nAnzNums] = nAnzStrings; - nAnzNums++; - if (nAnzStrings >= SV_MAX_ANZ_INPUT_STRINGS - 7 && - nPosThousandString == 0) // nur einmal - if ( SkipThousands( pStr, sStrArray[nAnzStrings] ) ) - nPosThousandString = nAnzStrings; - } - else - { - IsNum[nAnzStrings] = false; - } - nAnzStrings++; - } -} - - -bool ImpSvNumberInputScan::StringContainsImpl( const String& rWhat, - const String& rString, uint16_t nPos ) -{ - if ( nPos + rWhat.size() <= rString.size() ) - return StringPtrContainsImpl( rWhat, rString.data(), nPos ); - return false; -} - - -bool ImpSvNumberInputScan::StringPtrContainsImpl( const String& rWhat, - const sal_Unicode* pString, uint16_t nPos ) -{ - if ( rWhat.size() == 0 ) - return false; - const sal_Unicode* pWhat = rWhat.data(); - const sal_Unicode* const pEnd = pWhat + rWhat.size(); - const sal_Unicode* pStr = pString + nPos; - while ( pWhat < pEnd ) - { - if ( *pWhat != *pStr ) - return false; - pWhat++; - pStr++; - } - return true; -} - - -inline bool ImpSvNumberInputScan::SkipChar( sal_Unicode c, const String& rString, - uint16_t& nPos ) -{ - if ((nPos < rString.size()) && (rString.at(nPos) == c)) - { - nPos++; - return true; - } - return false; -} - - -inline void ImpSvNumberInputScan::SkipBlanks( const String& rString, - uint16_t& nPos ) -{ - if ( nPos < rString.size() ) - { - const sal_Unicode* p = rString.data() + nPos; - while ( *p == L' ' ) - { - nPos++; - p++; - } - } -} - - -inline bool ImpSvNumberInputScan::SkipString( const String& rWhat, - const String& rString, uint16_t& nPos ) -{ - if ( StringContains( rWhat, rString, nPos ) ) - { - nPos = nPos + rWhat.size(); - return true; - } - return false; -} - - -inline bool ImpSvNumberInputScan::GetThousandSep( - const String& rString, - uint16_t& nPos, - sal_uInt16 nStringPos ) -{ - const String& rSep = pFormatter->GetNumThousandSep(); - // Is it an ordinary space instead of a non-breaking space? - bool bSpaceBreak = rSep.at(0) == 0xa0 && rString.at(0) == 0x20 && - rSep.size() == 1 && rString.size() == 1; - if (!( (rString == rSep || bSpaceBreak) // nothing else - && nStringPos < nAnzStrings - 1 // safety first! - && IsNum[nStringPos+1] )) // number follows - return false; // no? => out - - DigitGroupingIterator aGrouping(pFormatter->getDigitGrouping()); - // Match ,### in {3} or ,## in {3,2} - /* FIXME: this could be refined to match ,## in {3,2} only if ,##,## or - * ,##,### and to match ,### in {3,2} only if it's the last. However, - * currently there is no track kept where group separators occur. In {3,2} - * #,###,### and #,##,## would be valid input, which maybe isn't even bad - * for #,###,###. Other combinations such as #,###,## maybe not. */ - uint16_t nLen = sStrArray[nStringPos + 1].size(); - if (nLen == aGrouping.get() // with 3 (or so) digits - || nLen == aGrouping.advance().get() // or with 2 (or 3 or so) digits - || nPosThousandString == nStringPos + 1 // or concatenated - ) - { - nPos = nPos + rSep.size(); - return true; - } - return false; -} - - -short ImpSvNumberInputScan::GetLogical( const String& rString ) -{ - short res; - - const ImpSvNumberformatScan* pFS = pFormatter->GetFormatScanner(); - if ( rString == pFS->GetTrueString() ) - res = 1; - else if ( rString == pFS->GetFalseString() ) - res = -1; - else - res = 0; - - return res; -} - - -short ImpSvNumberInputScan::GetMonth( const String& rString, uint16_t& nPos ) -{ - // #102136# The correct English form of month September abbreviated is - // SEPT, but almost every data contains SEP instead. - static const String aSeptCorrect = L"SEPT"; - static const String aSepShortened = L"SEP"; - - short res = 0; // no month found - - if (rString.size() > nPos) // only if needed - { - if ( !bTextInitialized ) - InitText(); - sal_Int16 nMonths = pFormatter->getMonthsOfYearSize(); - for ( sal_Int16 i = 0; i < nMonths; i++ ) - { - if ( StringContains( pUpperMonthText[i], rString, nPos ) ) - { // full names first - nPos = nPos + pUpperMonthText[i].size(); - res = i+1; - break; // for - } - else if ( StringContains( pUpperAbbrevMonthText[i], rString, nPos ) ) - { // abbreviated - nPos = nPos + pUpperAbbrevMonthText[i].size(); - res = (short)(-(i+1)); // negative - break; // for - } - else if ( i == 8 && pUpperAbbrevMonthText[i] == aSeptCorrect && - StringContains( aSepShortened, rString, nPos ) ) - { // #102136# SEPT/SEP - nPos = nPos + aSepShortened.size(); - res = (short)(-(i+1)); // negative - break; // for - } - } - } - - return res; -} - - -// Converts a string containing a DayOfWeek name (Mon, Monday) at nPos into the -// DayOfWeek number + 1 (negative if abbreviated), returns 0 if nothing found -int ImpSvNumberInputScan::GetDayOfWeek( const String& rString, uint16_t& nPos ) -{ - int res = 0; // no day found - - if (rString.size() > nPos) // only if needed - { - if ( !bTextInitialized ) - InitText(); - sal_Int16 nDays = pFormatter->getDayOfWeekSize(); - for ( sal_Int16 i = 0; i < nDays; i++ ) - { - if ( StringContains( pUpperDayText[i], rString, nPos ) ) - { // full names first - nPos = nPos + pUpperDayText[i].size(); - res = i + 1; - break; // for - } - if ( StringContains( pUpperAbbrevDayText[i], rString, nPos ) ) - { // abbreviated - nPos = nPos + pUpperAbbrevDayText[i].size(); - res = -(i + 1); // negative - break; // for - } - } - } - - return res; -} - - -bool ImpSvNumberInputScan::GetCurrency( const String& rString, uint16_t& nPos, - const SvNumberformat* pFormat ) -{ - if ( rString.size() > nPos ) - { - if ( !aUpperCurrSymbol.size() ) - { // if no format specified the currency of the initialized formatter - aUpperCurrSymbol = pFormatter->getCurrSymbol(); - ConvertToUpper(aUpperCurrSymbol); - } - if ( StringContains( aUpperCurrSymbol, rString, nPos ) ) - { - nPos = nPos + aUpperCurrSymbol.size(); - return true; - } - if ( pFormat ) - { - String aSymbol, aExtension; - if ( pFormat->GetNewCurrencySymbol( aSymbol, aExtension ) ) - { - if ( aSymbol.size() <= rString.size() - nPos ) - { - ConvertToUpper(aSymbol); - if ( StringContains( aSymbol, rString, nPos ) ) - { - nPos = nPos + aSymbol.size(); - return true; - } - } - } - } - } - - return false; -} - - -bool ImpSvNumberInputScan::GetTimeAmPm( const String& rString, uint16_t& nPos ) -{ - - if ( rString.size() > nPos ) - { - String am_str = pFormatter->getTimeAM(); - ConvertToUpper(am_str); - String pm_str = pFormatter->getTimePM(); - ConvertToUpper(pm_str); - if (StringContains(am_str, rString, nPos)) - { - nAmPm = 1; - nPos = nPos + pFormatter->getTimeAM().size(); - return true; - } - else if ( StringContains( pm_str, rString, nPos ) ) - { - nAmPm = -1; - nPos = nPos + pFormatter->getTimePM().size(); - return true; - } - } - - return false; -} - - -inline bool ImpSvNumberInputScan::GetDecSep( const String& rString, uint16_t& nPos ) -{ - if ( rString.size() > nPos ) - { - const String& rSep = pFormatter->GetNumDecimalSep(); - if ( rString.substr(nPos) == rSep ) - { - nPos = nPos + rSep.size(); - return true; - } - } - return false; -} - - -// read a hundredth seconds separator - -inline bool ImpSvNumberInputScan::GetTime100SecSep( const String& rString, uint16_t& nPos ) -{ - if ( rString.size() > nPos ) - { - const String& rSep = pFormatter->getTime100SecSep(); - if ( rString.substr(nPos) == rSep ) - { - nPos = nPos + rSep.size(); - return true; - } - } - return false; -} - - -int ImpSvNumberInputScan::GetSign( const String& rString, uint16_t& nPos ) -{ - if (rString.size() > nPos) - switch (rString.at(nPos)) - { - case L'+': - nPos++; - return 1; - case L'(': // '(' aehnlich wie '-' ?!? - nNegCheck = 1; - //! fallthru - case L'-': - nPos++; - return -1; - default: - break; - } - - return 0; -} - - -short ImpSvNumberInputScan::GetESign( const String& rString, uint16_t& nPos ) -{ - if (rString.size() > nPos) - switch (rString.at(nPos)) - { - case L'+': - nPos++; - return 1; - case L'-': - nPos++; - return -1; - default: - break; - } - - return 0; -} - - -// i counts string portions, j counts numbers thereof. -// It should had been called SkipNumber instead. - -inline bool ImpSvNumberInputScan::GetNextNumber( sal_uInt16& i, sal_uInt16& j ) -{ - if ( i < nAnzStrings && IsNum[i] ) - { - j++; - i++; - return true; - } - return false; -} - - -void ImpSvNumberInputScan::GetTimeRef( - double& fOutNumber, - sal_uInt16 nIndex, // j-value of the first numeric time part of input, default 0 - sal_uInt16 nAnz ) // count of numeric time parts -{ - sal_uInt16 nHour; - sal_uInt16 nMinute = 0; - sal_uInt16 nSecond = 0; - double fSecond100 = 0.0; - sal_uInt16 nStartIndex = nIndex; - - if (nTimezonePos) - { - // find first timezone number index and adjust count - for (sal_uInt16 j=0; jgetMonthsOfYearSize(); - - if (sStrArray[nNums[nIndex]].size() <= 2) - { - sal_uInt16 nNum = (sal_uInt16)std::stoi(sStrArray[nNums[nIndex]]); - if ( 0 < nNum && nNum <= nRes ) - nRes = nNum - 1; // zero based for CalendarFieldIndex::CFI_MONTH - } - - return nRes; -} - - -// 30 -> 1930, 29 -> 2029, oder 56 -> 1756, 55 -> 1855, ... - -sal_uInt16 ImpSvNumberInputScan::ImplGetYear( sal_uInt16 nIndex ) -{ - sal_uInt16 nYear = 0; - - if (sStrArray[nNums[nIndex]].size() <= 4) - { - nYear = (sal_uInt16)std::stoi(sStrArray[nNums[nIndex]]); - if (nYear < 100) - { - if (nYear < (nYear2000 % 100)) - return nYear + (((nYear2000 / 100) + 1) * 100); - else - return nYear + ((nYear2000 / 100) * 100); - } - } - - return nYear; -} - -bool ImpSvNumberInputScan::MayBeIso8601() -{ - if (nMayBeIso8601 == 0) - { - if (nAnzNums >= 3 && nNums[0] < nAnzStrings && - stoi(sStrArray[nNums[0]]) > 31) - nMayBeIso8601 = 1; - else - nMayBeIso8601 = 2; - } - return nMayBeIso8601 == 1; -} - -bool ImpSvNumberInputScan::GetDateRef( double& fDays, sal_uInt16& nCounter, - const SvNumberformat* pFormat ) -{ - //using namespace ::com::sun::star::i18n; - NfEvalDateFormat eEDF; - int nFormatOrder; - if ( pFormat && ((pFormat->GetType() & NUMBERFORMAT_DATE) == NUMBERFORMAT_DATE) ) - { - eEDF = pFormatter->GetEvalDateFormat(); - switch ( eEDF ) - { - case NF_EVALDATEFORMAT_INTL : - case NF_EVALDATEFORMAT_FORMAT : - nFormatOrder = 1; // only one loop - break; - default: - nFormatOrder = 2; - if ( nMatchedAllStrings ) - eEDF = NF_EVALDATEFORMAT_FORMAT_INTL; - // we have a complete match, use it - } - } - else - { - eEDF = NF_EVALDATEFORMAT_INTL; - nFormatOrder = 1; - } - bool res = true; - - Calendar* pCal = pFormatter->GetCalendar(); - for ( int nTryOrder = 1; nTryOrder <= nFormatOrder; nTryOrder++ ) - { - pCal->setGregorianDateTime( Date() ); // today - String aOrgCalendar; // empty => not changed yet - DateFormat DateFmt; - bool bFormatTurn; - switch ( eEDF ) - { - case NF_EVALDATEFORMAT_INTL : - bFormatTurn = false; - DateFmt = pFormatter->getDateFormat(); - break; - default: - DateFmt = DateFormat::YMD; - bFormatTurn = false; - } - - res = true; - nCounter = 0; - // For incomplete dates, always assume first day of month if not specified. - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 ); - - switch (nAnzNums) // count of numbers in string - { - case 0: // none - if (nMonthPos) // only month (Jan) - pCal->setValue( CalendarFieldIndex::CFI_MONTH, abs(nMonth)-1 ); - else - res = false; - break; - - case 1: // only one number - nCounter = 1; - switch (nMonthPos) // where is the month - { - case 0: // not found => only day entered - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) ); - break; - case 1: // month at the beginning (Jan 01) - pCal->setValue( CalendarFieldIndex::CFI_MONTH, abs(nMonth)-1 ); - switch (DateFmt) - { - case MDY: - case YMD: - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) ); - break; - case DMY: - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(0) ); - break; - default: - res = false; - break; - } - break; - case 3: // month at the end (10 Jan) - pCal->setValue( CalendarFieldIndex::CFI_MONTH, abs(nMonth)-1 ); - switch (DateFmt) - { - case DMY: - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) ); - break; - case YMD: - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(0) ); - break; - default: - res = false; - break; - } - break; - default: - res = false; - break; - } // switch (nMonthPos) - break; - - case 2: // 2 numbers - nCounter = 2; - switch (nMonthPos) // where is the month - { - case 0: // not found - { - bool bHadExact; - sal_uInt32 nExactDateOrder = (bFormatTurn ? pFormat->GetExactDateOrder() : 0); - if ( 0xff < nExactDateOrder && nExactDateOrder <= 0xffff ) - { // formatted as date and exactly 2 parts - bHadExact = true; - switch ( (nExactDateOrder >> 8) & 0xff ) - { - case L'Y': - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(0) ); - break; - case L'M': - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(0) ); - break; - case L'D': - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) ); - break; - default: - bHadExact = false; - } - switch ( nExactDateOrder & 0xff ) - { - case L'Y': - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(1) ); - break; - case L'M': - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(1) ); - break; - case L'D': - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) ); - break; - default: - bHadExact = false; - } - } - else - bHadExact = false; - if ( !bHadExact || !pCal->isValid() ) - { - if ( !bHadExact && nExactDateOrder ) - pCal->setGregorianDateTime( Date() ); // reset today - switch (DateFmt) - { - case MDY: - // M D - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) ); - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(0) ); - if ( !pCal->isValid() ) // 2nd try - { // M Y - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 ); - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(0) ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(1) ); - } - break; - case DMY: - // D M - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) ); - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(1) ); - if ( !pCal->isValid() ) // 2nd try - { // M Y - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 ); - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(0) ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(1) ); - } - break; - case YMD: - // M D - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) ); - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(0) ); - if ( !pCal->isValid() ) // 2nd try - { // Y M - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 ); - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(1) ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(0) ); - } - break; - default: - res = false; - break; - } - } - } - break; - case 1: // month at the beginning (Jan 01 01) - { - // The input is valid as MDY in almost any - // constellation, there is no date order (M)YD except if - // set in a format applied. - pCal->setValue( CalendarFieldIndex::CFI_MONTH, abs(nMonth)-1 ); - sal_uInt32 nExactDateOrder = (bFormatTurn ? pFormat->GetExactDateOrder() : 0); - if ((((nExactDateOrder >> 8) & 0xff) == L'Y') && ((nExactDateOrder & 0xff) == L'D')) - { - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(0) ); - } - else - { - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(1) ); - } - } - break; - case 2: // month in the middle (10 Jan 94) - pCal->setValue( CalendarFieldIndex::CFI_MONTH, abs(nMonth)-1 ); - switch (DateFmt) - { - case MDY: // yes, "10-Jan-94" is valid - case DMY: - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(1) ); - break; - case YMD: - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(0) ); - break; - default: - res = false; - break; - } - break; - default: // else, e.g. month at the end (94 10 Jan) - res = false; - break; - } // switch (nMonthPos) - break; - - default: // more than two numbers (31.12.94 8:23) (31.12. 8:23) - switch (nMonthPos) // where is the month - { - case 0: // not found - { - nCounter = 3; - if ( nTimePos > 1 ) - { // find first time number index (should only be 3 or 2 anyway) - for ( sal_uInt16 j = 0; j < nAnzNums; j++ ) - { - if ( nNums[j] == nTimePos - 2 ) - { - nCounter = j; - break; // for - } - } - } - // ISO 8601 yyyy-mm-dd forced recognition - DateFormat eDF = (MayBeIso8601() ? YMD : DateFmt); - switch (eDF) - { - case MDY: - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) ); - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(0) ); - if ( nCounter > 2 ) - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(2) ); - break; - case DMY: - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) ); - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(1) ); - if ( nCounter > 2 ) - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(2) ); - break; - case YMD: - if ( nCounter > 2 ) - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(2) ); - pCal->setValue( CalendarFieldIndex::CFI_MONTH, ImplGetMonth(1) ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(0) ); - break; - default: - res = false; - break; - } - } - break; - case 1: // month at the beginning (Jan 01 01 8:23) - nCounter = 2; - switch (DateFmt) - { - case MDY: - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) ); - pCal->setValue( CalendarFieldIndex::CFI_MONTH, abs(nMonth)-1 ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(1) ); - break; - default: - res = false; - break; - } - break; - case 2: // month in the middle (10 Jan 94 8:23) - nCounter = 2; - pCal->setValue( CalendarFieldIndex::CFI_MONTH, abs(nMonth)-1 ); - switch (DateFmt) - { - case DMY: - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(1) ); - break; - case YMD: - pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) ); - pCal->setValue( CalendarFieldIndex::CFI_YEAR, ImplGetYear(0) ); - break; - default: - res = false; - break; - } - break; - default: // else, e.g. month at the end (94 10 Jan 8:23) - nCounter = 2; - res = false; - break; - } // switch (nMonthPos) - break; - } // switch (nAnzNums) - - if ( res && pCal->isValid() ) - { - fDays = floor( pCal->getLocalDateTime() ); - nTryOrder = nFormatOrder; // break for - } - else - res = false; - } - - return res; -} - - -bool ImpSvNumberInputScan::ScanStartString( const String& rString, - const SvNumberformat* pFormat ) -{ - uint16_t nPos = 0; - int nDayOfWeek; - - // First of all, eat leading blanks - SkipBlanks(rString, nPos); - - // Yes, nMatchedAllStrings should know about the sign position - nSign = GetSign(rString, nPos); - if ( nSign ) // sign? - SkipBlanks(rString, nPos); - - // #102371# match against format string only if start string is not a sign character - if ( nMatchedAllStrings && !(nSign && rString.size() == 1) ) - { // Match against format in any case, so later on for a "x1-2-3" input - // we may distinguish between a xy-m-d (or similar) date and a x0-0-0 - // format. No sign detection here! - if ( ScanStringNumFor( rString, nPos, pFormat, 0, true ) ) - nMatchedAllStrings |= nMatchedStartString; - else - nMatchedAllStrings = 0; - } - - if ( GetDecSep(rString, nPos) ) // decimal separator in start string - { - nDecPos = 1; - SkipBlanks(rString, nPos); - } - else if ( GetCurrency(rString, nPos, pFormat) ) // currency (DM 1)? - { - eScannedType = NUMBERFORMAT_CURRENCY; // !!! it IS currency !!! - SkipBlanks(rString, nPos); - if (nSign == 0) // no sign yet - { - nSign = GetSign(rString, nPos); - if ( nSign ) // DM -1 - SkipBlanks(rString, nPos); - } - } - else - { - nMonth = GetMonth(rString, nPos); - if ( nMonth ) // month (Jan 1)? - { - eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date !!! - nMonthPos = 1; // month at the beginning - if ( nMonth < 0 ) - SkipChar( L'.', rString, nPos ); // abbreviated - SkipBlanks(rString, nPos); - } - else - { - nDayOfWeek = GetDayOfWeek( rString, nPos ); - if ( nDayOfWeek ) - { // day of week is just parsed away - eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date !!! - if ( nPos < rString.size() ) - { - if ( nDayOfWeek < 0 ) - { // abbreviated - if ( rString.at( nPos ) == L'.' ) - ++nPos; - } - else - { // full long name - SkipBlanks(rString, nPos); - SkipString( pFormatter->getLongDateDayOfWeekSep(), rString, nPos ); - } - SkipBlanks(rString, nPos); - nMonth = GetMonth(rString, nPos); - if ( nMonth ) // month (Jan 1)? - { - nMonthPos = 1; // month a the beginning - if ( nMonth < 0 ) - SkipChar( L'.', rString, nPos ); // abbreviated - SkipBlanks(rString, nPos); - } - } - } - } - } - - if (nPos < rString.size()) // not everything consumed - { - // Does input StartString equal StartString of format? - // This time with sign detection! - if ( !ScanStringNumFor( rString, nPos, pFormat, 0 ) ) - return MatchedReturn(); - } - - return true; -} - - -bool ImpSvNumberInputScan::ScanMidString( const String& rString, - sal_uInt16 nStringPos, const SvNumberformat* pFormat ) -{ - uint16_t nPos = 0; - short eOldScannedType = eScannedType; - - if ( nMatchedAllStrings ) - { // Match against format in any case, so later on for a "1-2-3-4" input - // we may distinguish between a y-m-d (or similar) date and a 0-0-0-0 - // format. - if ( ScanStringNumFor( rString, 0, pFormat, nStringPos ) ) - nMatchedAllStrings |= nMatchedMidString; - else - nMatchedAllStrings = 0; - } - - SkipBlanks(rString, nPos); - if (GetDecSep(rString, nPos)) // decimal separator? - { - if (nDecPos == 1 || nDecPos == 3) // .12.4 or 1.E2.1 - return MatchedReturn(); - else if (nDecPos == 2) // . dup: 12.4. - { - if (bDecSepInDateSeps) // . also date separator - { - if ( eScannedType != NUMBERFORMAT_UNDEFINED && - eScannedType != NUMBERFORMAT_DATE && - eScannedType != NUMBERFORMAT_DATETIME) // already another type - return MatchedReturn(); - if (eScannedType == NUMBERFORMAT_UNDEFINED) - eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date - SkipBlanks(rString, nPos); - } - else - return MatchedReturn(); - } - else - { - nDecPos = 2; // . in mid string - SkipBlanks(rString, nPos); - } - } - else if ( ((eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME) - && GetTime100SecSep( rString, nPos ) ) - { // hundredth seconds separator - if ( nDecPos ) - return MatchedReturn(); - nDecPos = 2; // . in mid string - SkipBlanks(rString, nPos); - } - - if (SkipChar(L'/', rString, nPos)) // fraction? - { - if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type - && eScannedType != NUMBERFORMAT_DATE) // except date - return MatchedReturn(); // => jan/31/1994 - else if ( eScannedType != NUMBERFORMAT_DATE // analyzed date until now - && ( eSetType == NUMBERFORMAT_FRACTION // and preset was fraction - || (nAnzNums == 3 // or 3 numbers - && nStringPos > 2) ) ) // and what ??? - { - SkipBlanks(rString, nPos); - eScannedType = NUMBERFORMAT_FRACTION; // !!! it IS a fraction - } - else - nPos--; // put '/' back - } - - if (GetThousandSep(rString, nPos, nStringPos)) // 1,000 - { - if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type - && eScannedType != NUMBERFORMAT_CURRENCY) // except currency - return MatchedReturn(); - nThousand++; - } - - const String& rDate = pFormatter->GetDateSep(); - const String& rTime = pFormatter->getTimeSep(); - sal_Unicode cTime = rTime.at(0); - SkipBlanks(rString, nPos); - if ( SkipString(rDate, rString, nPos) // 10., 10-, 10/ - || ((cTime != L'.') && SkipChar(L'.', rString, nPos)) // TRICKY: - || ((cTime != L'/') && SkipChar(L'/', rString, nPos)) // short boolean - || ((cTime != L'-') && SkipChar(L'-', rString, nPos)) ) // evaluation! - { - if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type - && eScannedType != NUMBERFORMAT_DATE) // except date - return MatchedReturn(); - SkipBlanks(rString, nPos); - eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date - short nTmpMonth = GetMonth(rString, nPos); // 10. Jan 94 - if (nMonth && nTmpMonth) // month dup - return MatchedReturn(); - if (nTmpMonth) - { - nMonth = nTmpMonth; - nMonthPos = 2; // month in the middle - if ( nMonth < 0 && SkipChar( L'.', rString, nPos ) ) - ; // short month may be abbreviated Jan. - else if ( SkipChar( L'-', rString, nPos ) ) - ; // #79632# recognize 17-Jan-2001 to be a date - // #99065# short and long month name - else - SkipString(pFormatter->getLongDateMonthSep(), rString, nPos ); - SkipBlanks(rString, nPos); - } - } - - short nTempMonth = GetMonth(rString, nPos); // month in the middle (10 Jan 94) - if (nTempMonth) - { - if (nMonth != 0) // month dup - return MatchedReturn(); - if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type - && eScannedType != NUMBERFORMAT_DATE) // except date - return MatchedReturn(); - eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date - nMonth = nTempMonth; - nMonthPos = 2; // month in the middle - if ( nMonth < 0 ) - SkipChar( L'.', rString, nPos ); // abbreviated - SkipString(pFormatter->getLongDateMonthSep(), rString, nPos ); - SkipBlanks(rString, nPos); - } - - if ( SkipChar(L'E', rString, nPos) // 10E, 10e, 10,Ee - || SkipChar(L'e', rString, nPos) ) - { - if (eScannedType != NUMBERFORMAT_UNDEFINED) // already another type - return MatchedReturn(); - else - { - SkipBlanks(rString, nPos); - eScannedType = NUMBERFORMAT_SCIENTIFIC; // !!! it IS scientific - if ( nThousand+2 == nAnzNums // special case 1.E2 - && nDecPos == 2 ) - nDecPos = 3; // 1,100.E2 1,100,100.E3 - } - nESign = GetESign(rString, nPos); // signed exponent? - SkipBlanks(rString, nPos); - } - - if ( SkipString(rTime, rString, nPos) ) // time separator? - { - if (nDecPos) // already . => maybe error - { - if (bDecSepInDateSeps) // . also date sep - { - if ( eScannedType != NUMBERFORMAT_DATE && // already another type than date - eScannedType != NUMBERFORMAT_DATETIME) // or date time - return MatchedReturn(); - if (eScannedType == NUMBERFORMAT_DATE) - nDecPos = 0; // reset for time transition - } - else - return MatchedReturn(); - } - if ( ( eScannedType == NUMBERFORMAT_DATE // already date type - || eScannedType == NUMBERFORMAT_DATETIME) // or date time - && nAnzNums > 3) // and more than 3 numbers? (31.Dez.94 8:23) - { - SkipBlanks(rString, nPos); - eScannedType = NUMBERFORMAT_DATETIME; // !!! it IS date with time - } - else if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type - && eScannedType != NUMBERFORMAT_TIME) // except time - return MatchedReturn(); - else - { - SkipBlanks(rString, nPos); - eScannedType = NUMBERFORMAT_TIME; // !!! it IS a time - } - if ( !nTimePos ) - nTimePos = nStringPos + 1; - } - - if (nPos < rString.size()) - { - switch (eScannedType) - { - case NUMBERFORMAT_DATE: - if (nMonthPos == 1 && pFormatter->getLongDateFormat() == MDY) - { - // #68232# recognize long date separators like ", " in "September 5, 1999" - if (SkipString(pFormatter->getLongDateDaySep(), rString, nPos )) - SkipBlanks( rString, nPos ); - } - else if (nStringPos == 5 && nPos == 0 && rString.size() == 1 && - rString.at(0) == L'T' && MayBeIso8601()) - { - // ISO 8601 combined date and time, yyyy-mm-ddThh:mm - ++nPos; - } - break; - } - } - - if (nPos < rString.size()) // not everything consumed? - { - if ( nMatchedAllStrings & ~nMatchedVirgin ) - eScannedType = eOldScannedType; - else - return false; - } - - return true; -} - - -bool ImpSvNumberInputScan::ScanEndString( const String& rString, - const SvNumberformat* pFormat ) -{ - uint16_t nPos = 0; - - if ( nMatchedAllStrings ) - { // Match against format in any case, so later on for a "1-2-3-4" input - // we may distinguish between a y-m-d (or similar) date and a 0-0-0-0 - // format. - if ( ScanStringNumFor( rString, 0, pFormat, 0xFFFF ) ) - nMatchedAllStrings |= nMatchedEndString; - else - nMatchedAllStrings = 0; - } - - SkipBlanks(rString, nPos); - if (GetDecSep(rString, nPos)) // decimal separator? - { - if (nDecPos == 1 || nDecPos == 3) // .12.4 or 12.E4. - return MatchedReturn(); - else if (nDecPos == 2) // . dup: 12.4. - { - if (bDecSepInDateSeps) // . also date sep - { - if ( eScannedType != NUMBERFORMAT_UNDEFINED && - eScannedType != NUMBERFORMAT_DATE && - eScannedType != NUMBERFORMAT_DATETIME) // already another type - return MatchedReturn(); - if (eScannedType == NUMBERFORMAT_UNDEFINED) - eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date - SkipBlanks(rString, nPos); - } - else - return MatchedReturn(); - } - else - { - nDecPos = 3; // . in end string - SkipBlanks(rString, nPos); - } - } - - if ( nSign == 0 // conflict - not signed - && eScannedType != NUMBERFORMAT_DATE) // and not date -//!? catch time too? - { // not signed yet - nSign = GetSign(rString, nPos); // 1- DM - if (nNegCheck) // '(' as sign - return MatchedReturn(); - } - - SkipBlanks(rString, nPos); - if (nNegCheck && SkipChar(L')', rString, nPos)) // skip ')' if appropriate - { - nNegCheck = 0; - SkipBlanks(rString, nPos); - } - - if ( GetCurrency(rString, nPos, pFormat) ) // currency symbol? - { - if (eScannedType != NUMBERFORMAT_UNDEFINED) // currency dup - return MatchedReturn(); - else - { - SkipBlanks(rString, nPos); - eScannedType = NUMBERFORMAT_CURRENCY; - } // behind currency a '-' is allowed - if (nSign == 0) // not signed yet - { - nSign = GetSign(rString, nPos); // DM - - SkipBlanks(rString, nPos); - if (nNegCheck) // 3 DM ( - return MatchedReturn(); - } - if ( nNegCheck && eScannedType == NUMBERFORMAT_CURRENCY - && SkipChar(L')', rString, nPos) ) - { - nNegCheck = 0; // ')' skipped - SkipBlanks(rString, nPos); // only if currency - } - } - - if ( SkipChar(L'%', rString, nPos) ) // 1 % - { - if (eScannedType != NUMBERFORMAT_UNDEFINED) // already another type - return MatchedReturn(); - SkipBlanks(rString, nPos); - eScannedType = NUMBERFORMAT_PERCENT; - } - - const String& rDate = pFormatter->GetDateSep(); - const String& rTime = pFormatter->getTimeSep(); - if ( SkipString(rTime, rString, nPos) ) // 10: - { - if (nDecPos) // already , => error - return MatchedReturn(); - if (eScannedType == NUMBERFORMAT_DATE && nAnzNums > 2) // 31.Dez.94 8: - { - SkipBlanks(rString, nPos); - eScannedType = NUMBERFORMAT_DATETIME; - } - else if (eScannedType != NUMBERFORMAT_UNDEFINED && - eScannedType != NUMBERFORMAT_TIME) // already another type - return MatchedReturn(); - else - { - SkipBlanks(rString, nPos); - eScannedType = NUMBERFORMAT_TIME; - } - if ( !nTimePos ) - nTimePos = nAnzStrings; - } - - sal_Unicode cTime = rTime.at(0); - if ( SkipString(rDate, rString, nPos) // 10., 10-, 10/ - || ((cTime != L'.') && SkipChar(L'.', rString, nPos)) // TRICKY: - || ((cTime != L'/') && SkipChar(L'/', rString, nPos)) // short boolean - || ((cTime != L'-') && SkipChar(L'-', rString, nPos)) ) // evaluation! - { - if (eScannedType != NUMBERFORMAT_UNDEFINED && - eScannedType != NUMBERFORMAT_DATE) // already another type - return MatchedReturn(); - else - { - SkipBlanks(rString, nPos); - eScannedType = NUMBERFORMAT_DATE; - } - short nTmpMonth = GetMonth(rString, nPos); // 10. Jan - if (nMonth && nTmpMonth) // month dup - return MatchedReturn(); - if (nTmpMonth) - { - nMonth = nTmpMonth; - nMonthPos = 3; // month at end - if ( nMonth < 0 ) - SkipChar( L'.', rString, nPos ); // abbreviated - SkipBlanks(rString, nPos); - } - } - - short nTempMonth = GetMonth(rString, nPos); // 10 Jan - if (nTempMonth) - { - if (nMonth) // month dup - return MatchedReturn(); - if (eScannedType != NUMBERFORMAT_UNDEFINED && - eScannedType != NUMBERFORMAT_DATE) // already another type - return MatchedReturn(); - eScannedType = NUMBERFORMAT_DATE; - nMonth = nTempMonth; - nMonthPos = 3; // month at end - if ( nMonth < 0 ) - SkipChar( L'.', rString, nPos ); // abbreviated - SkipBlanks(rString, nPos); - } - - uint16_t nOrigPos = nPos; - if (GetTimeAmPm(rString, nPos)) - { - if (eScannedType != NUMBERFORMAT_UNDEFINED && - eScannedType != NUMBERFORMAT_TIME && - eScannedType != NUMBERFORMAT_DATETIME) // already another type - return MatchedReturn(); - else - { - // If not already scanned as time, 6.78am does not result in 6 - // seconds and 78 hundredths in the morning. Keep as suffix. - if (eScannedType != NUMBERFORMAT_TIME && nDecPos == 2 && nAnzNums == 2) - nPos = nOrigPos; // rewind am/pm - else - { - SkipBlanks(rString, nPos); - if ( eScannedType != NUMBERFORMAT_DATETIME ) - eScannedType = NUMBERFORMAT_TIME; - } - } - } - - if ( nNegCheck && SkipChar(L')', rString, nPos) ) - { - if (eScannedType == NUMBERFORMAT_CURRENCY) // only if currency - { - nNegCheck = 0; // skip ')' - SkipBlanks(rString, nPos); - } - else - return MatchedReturn(); - } - - if ( nPos < rString.size() && - (eScannedType == NUMBERFORMAT_DATE - || eScannedType == NUMBERFORMAT_DATETIME) ) - { // day of week is just parsed away - uint16_t nOldPos = nPos; - const String& rSep = pFormatter->getLongDateDayOfWeekSep(); - if ( StringContains( rSep, rString, nPos ) ) - { - nPos = nPos + rSep.size(); - SkipBlanks(rString, nPos); - } - int nDayOfWeek = GetDayOfWeek( rString, nPos ); - if ( nDayOfWeek ) - { - if ( nPos < rString.size() ) - { - if ( nDayOfWeek < 0 ) - { // short - if ( rString.at( nPos ) == L'.' ) - ++nPos; - } - SkipBlanks(rString, nPos); - } - } - else - nPos = nOldPos; - } - - if (nPos < rString.size()) // everything consumed? - { - // does input EndString equal EndString in Format? - if ( !ScanStringNumFor( rString, nPos, pFormat, 0xFFFF ) ) - return false; - } - - return true; -} - - -bool ImpSvNumberInputScan::ScanStringNumFor( - const String& rString, // String to scan - uint16_t nPos, // Position until which was consumed - const SvNumberformat* pFormat, // The format to match - sal_uInt16 nString, // Substring of format, 0xFFFF => last - bool bDontDetectNegation // Suppress sign detection - ) -{ - if ( !pFormat ) - return false; - const String* pStr; - String aString( rString ); - bool bFound = false; - bool bFirst = true; - bool bContinue = true; - sal_uInt16 nSub; - do - { - // Don't try "lower" subformats ff the very first match was the second - // or third subformat. - nSub = nStringScanNumFor; - do - { // Step through subformats, first positive, then negative, then - // other, but not the last (text) subformat. - pStr = pFormat->GetNumForString( nSub, nString, true ); - if ( pStr && aString == *pStr ) - { - bFound = true; - bContinue = false; - } - else if ( nSub < 2 ) - ++nSub; - else - bContinue = false; - } while ( bContinue ); - if ( !bFound && bFirst && nPos ) - { // try remaining substring - bFirst = false; - aString.erase( 0, nPos ); - bContinue = true; - } - } while ( bContinue ); - - if ( !bFound ) - { - if ( !bDontDetectNegation && (nString == 0) && !bFirst && (nSign < 0) - && pFormat->IsNegativeRealNegative() ) - { // simply negated twice? --1 - EraseAllChars(aString, L' ' ); - if ( (aString.size() == 1) && (aString.at(0) == L'-') ) - { - bFound = true; - nStringScanSign = -1; - nSub = 0; //! not 1 - } - } - if ( !bFound ) - return false; - } - else if ( !bDontDetectNegation && (nSub == 1) && - pFormat->IsNegativeRealNegative() ) - { // negative - if ( nStringScanSign < 0 ) - { - if ( (nSign < 0) && (nStringScanNumFor != 1) ) - nStringScanSign = 1; // triple negated --1 yyy - } - else if ( nStringScanSign == 0 ) - { - if ( nSign < 0 ) - { // nSign and nStringScanSign will be combined later, - // flip sign if doubly negated - if ( (nString == 0) && !bFirst - && SvNumberformat::HasStringNegativeSign( aString ) ) - nStringScanSign = -1; // direct double negation - else if ( pFormat->IsNegativeWithoutSign() ) - nStringScanSign = -1; // indirect double negation - } - else - nStringScanSign = -1; - } - else // > 0 - nStringScanSign = -1; - } - nStringScanNumFor = nSub; - return true; -} - - -bool ImpSvNumberInputScan::IsNumberFormatMain( - const String& rString, // string to be analyzed - double& , // OUT: result as number, if possible - const SvNumberformat* pFormat ) // maybe number format set to match against -{ - Reset(); - NumberStringDivision( rString ); // breakdown into strings and numbers - if (nAnzStrings >= SV_MAX_ANZ_INPUT_STRINGS) // too many elements - return false; // Njet, Nope, ... - - if (nAnzNums == 0) // no number in input - { - if ( nAnzStrings > 0 ) - { - // Here we may change the original, we don't need it anymore. - // This saves copies and ToUpper() in GetLogical() and is faster. - String& rStrArray = sStrArray[0]; - EraseTrailingChars(rStrArray, L' '); - EraseLeadingChars(rStrArray, L' '); - nLogical = GetLogical( rStrArray ); - if ( nLogical ) - { - eScannedType = NUMBERFORMAT_LOGICAL; // !!! it's a BOOLEAN - nMatchedAllStrings &= ~nMatchedVirgin; - return true; - } - else - return false; // simple text - } - else - return false; // simple text - } - - sal_uInt16 i = 0; // mark any symbol - sal_uInt16 j = 0; // mark only numbers - - switch ( nAnzNums ) - { - case 1 : // Exactly 1 number in input - { // nAnzStrings >= 1 - if (GetNextNumber(i,j)) // i=1,0 - { // Number at start - if (eSetType == NUMBERFORMAT_FRACTION) // Fraction 1 = 1/1 - { - if (i >= nAnzStrings || // no end string nor decimal separator - sStrArray[i] == pFormatter->GetNumDecimalSep()) - { - eScannedType = NUMBERFORMAT_FRACTION; - nMatchedAllStrings &= ~nMatchedVirgin; - return true; - } - } - } - else - { // Analyze start string - if (!ScanStartString( sStrArray[i], pFormat )) // i=0 - return false; // already an error - i++; // next symbol, i=1 - } - GetNextNumber(i,j); // i=1,2 - if (eSetType == NUMBERFORMAT_FRACTION) // Fraction -1 = -1/1 - { - if (nSign && !nNegCheck && // Sign +, - - eScannedType == NUMBERFORMAT_UNDEFINED && // not date or currency - nDecPos == 0 && // no previous decimal separator - (i >= nAnzStrings || // no end string nor decimal separator - sStrArray[i] == pFormatter->GetNumDecimalSep()) - ) - { - eScannedType = NUMBERFORMAT_FRACTION; - nMatchedAllStrings &= ~nMatchedVirgin; - return true; - } - } - if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat )) - return false; - } - break; - case 2 : // Exactly 2 numbers in input - { // nAnzStrings >= 3 - if (!GetNextNumber(i,j)) // i=1,0 - { // Analyze start string - if (!ScanStartString( sStrArray[i], pFormat )) - return false; // already an error - i++; // i=1 - } - GetNextNumber(i,j); // i=1,2 - if ( !ScanMidString( sStrArray[i], i, pFormat ) ) - return false; - i++; // next symbol, i=2,3 - GetNextNumber(i,j); // i=3,4 - if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat )) - return false; - if (eSetType == NUMBERFORMAT_FRACTION) // -1,200. as fraction - { - if (!nNegCheck && // no sign '(' - eScannedType == NUMBERFORMAT_UNDEFINED && - (nDecPos == 0 || nDecPos == 3) // no decimal separator or at end - ) - { - eScannedType = NUMBERFORMAT_FRACTION; - nMatchedAllStrings &= ~nMatchedVirgin; - return true; - } - } - } - break; - case 3 : // Exactly 3 numbers in input - { // nAnzStrings >= 5 - if (!GetNextNumber(i,j)) // i=1,0 - { // Analyze start string - if (!ScanStartString( sStrArray[i], pFormat )) - return false; // already an error - i++; // i=1 - if (nDecPos == 1) // decimal separator at start => error - return false; - } - GetNextNumber(i,j); // i=1,2 - if ( !ScanMidString( sStrArray[i], i, pFormat ) ) - return false; - i++; // i=2,3 - if (eScannedType == NUMBERFORMAT_SCIENTIFIC) // E only at end - return false; - GetNextNumber(i,j); // i=3,4 - if ( !ScanMidString( sStrArray[i], i, pFormat ) ) - return false; - i++; // i=4,5 - GetNextNumber(i,j); // i=5,6 - if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat )) - return false; - if (eSetType == NUMBERFORMAT_FRACTION) // -1,200,100. as fraction - { - if (!nNegCheck && // no sign '(' - eScannedType == NUMBERFORMAT_UNDEFINED && - (nDecPos == 0 || nDecPos == 3) // no decimal separator or at end - ) - { - eScannedType = NUMBERFORMAT_FRACTION; - nMatchedAllStrings &= ~nMatchedVirgin; - return true; - } - } - if ( eScannedType == NUMBERFORMAT_FRACTION && nDecPos ) - return false; // #36857# not a real fraction - } - break; - default: // More than 3 numbers in input - { // nAnzStrings >= 7 - if (!GetNextNumber(i,j)) // i=1,0 - { // Analyze startstring - if (!ScanStartString( sStrArray[i], pFormat )) - return false; // already an error - i++; // i=1 - if (nDecPos == 1) // decimal separator at start => error - return false; - } - GetNextNumber(i,j); // i=1,2 - if ( !ScanMidString( sStrArray[i], i, pFormat ) ) - return false; - i++; // i=2,3 - sal_uInt16 nThOld = 10; // just not 0 or 1 - while (nThOld != nThousand && j < nAnzNums-1) - // Execute at least one time - // but leave one number. - { // Loop over group separators - nThOld = nThousand; - if (eScannedType == NUMBERFORMAT_SCIENTIFIC) // E only at end - return false; - GetNextNumber(i,j); - if ( i < nAnzStrings && !ScanMidString( sStrArray[i], i, pFormat ) ) - return false; - i++; - } - if (eScannedType == NUMBERFORMAT_DATE || // long date or - eScannedType == NUMBERFORMAT_TIME || // long time or - eScannedType == NUMBERFORMAT_UNDEFINED) // long number - { - for (sal_uInt16 k = j; k < nAnzNums-1; k++) - { - if (eScannedType == NUMBERFORMAT_SCIENTIFIC) // E only at endd - return false; - GetNextNumber(i,j); - if ( i < nAnzStrings && !ScanMidString( sStrArray[i], i, pFormat ) ) - return false; - i++; - } - } - GetNextNumber(i,j); - if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat )) - return false; - if (eSetType == NUMBERFORMAT_FRACTION) // -1,200,100. as fraction - { - if (!nNegCheck && // no sign '(' - eScannedType == NUMBERFORMAT_UNDEFINED && - (nDecPos == 0 || nDecPos == 3) // no decimal separator or at end - ) - { - eScannedType = NUMBERFORMAT_FRACTION; - nMatchedAllStrings &= ~nMatchedVirgin; - return true; - } - } - if ( eScannedType == NUMBERFORMAT_FRACTION && nDecPos ) - return false; // #36857# not a real fraction - } - } - - if (eScannedType == NUMBERFORMAT_UNDEFINED) - { - nMatchedAllStrings &= ~nMatchedVirgin; - // did match including nMatchedUsedAsReturn - bool bDidMatch = (nMatchedAllStrings != 0); - if ( nMatchedAllStrings ) - { - bool bMatch = (pFormat ? pFormat->IsNumForStringElementCountEqual( - nStringScanNumFor, nAnzStrings, nAnzNums ) : false); - if ( !bMatch ) - nMatchedAllStrings = 0; - } - if ( nMatchedAllStrings ) - eScannedType = eSetType; - else if ( bDidMatch ) - return false; - else - eScannedType = NUMBERFORMAT_NUMBER; - // everything else should have been recognized by now - } - else if ( eScannedType == NUMBERFORMAT_DATE ) - { // the very relaxed date input checks may interfere with a preset format - nMatchedAllStrings &= ~nMatchedVirgin; - bool bWasReturn = ((nMatchedAllStrings & nMatchedUsedAsReturn) != 0); - if ( nMatchedAllStrings ) - { - bool bMatch = (pFormat ? pFormat->IsNumForStringElementCountEqual( - nStringScanNumFor, nAnzStrings, nAnzNums ) : false); - if ( !bMatch ) - nMatchedAllStrings = 0; - } - if ( nMatchedAllStrings ) - eScannedType = eSetType; - else if ( bWasReturn ) - return false; - } - else - nMatchedAllStrings = 0; // reset flag to no substrings matched - - return true; -} - - -// return true or false depending on the nMatched... state and remember usage -bool ImpSvNumberInputScan::MatchedReturn() -{ - if ( nMatchedAllStrings & ~nMatchedVirgin ) - { - nMatchedAllStrings |= nMatchedUsedAsReturn; - return true; - } - return false; -} - - -// Initialize uppercase months and weekdays - -void ImpSvNumberInputScan::InitText() -{ - sal_Int32 j, nElems; - delete [] pUpperMonthText; - delete [] pUpperAbbrevMonthText; - nElems = pFormatter->getMonthsOfYearSize(); - pUpperMonthText = new String[nElems]; - pUpperAbbrevMonthText = new String[nElems]; - for (j = 0; j < nElems; j++) - { - pUpperMonthText[j] = pFormatter->getMonthsOfYearFullName(j); - ConvertToUpper(pUpperMonthText[j]); - pUpperAbbrevMonthText[j] = pFormatter->getMonthsOfYearAbbrvName(j); - ConvertToUpper(pUpperAbbrevMonthText[j]); - } - delete [] pUpperDayText; - delete [] pUpperAbbrevDayText; - nElems = pFormatter->getDayOfWeekSize(); - pUpperDayText = new String[nElems]; - pUpperAbbrevDayText = new String[nElems]; - for (j = 0; j < nElems; j++) - { - pUpperDayText[j] = pFormatter->getDayOfWeekFullName(j); - ConvertToUpper(pUpperDayText[j]); - pUpperAbbrevDayText[j] = pFormatter->getDayOfWeekAbbrvName(j); - ConvertToUpper(pUpperAbbrevDayText[j]); - } - bTextInitialized = true; -} - - -// MUST be called if International/Locale is changed - -void ImpSvNumberInputScan::ChangeIntl() -{ - sal_Unicode cDecSep = pFormatter->GetNumDecimalSep().at(0); - bDecSepInDateSeps = ( cDecSep == L'-' || - cDecSep == L'/' || - cDecSep == L'.' || - cDecSep == pFormatter->GetDateSep().at(0) ); - bTextInitialized = false; - aUpperCurrSymbol.erase(); -} - - -// => does rString represent a number (also date, time et al) - -bool ImpSvNumberInputScan::IsNumberFormat( - const String& rString, // string to be analyzed - short& F_Type, // IN: old type, OUT: new type - double& fOutNumber, // OUT: number if convertable - const SvNumberformat* pFormat ) // maybe a number format to match against -{ - String sResString; - String aString; - bool res; // return value - eSetType = F_Type; // old type set - - if ( !rString.size() ) - res = false; - else if (rString.size() > 308) // arbitrary - res = false; - else - { - // NoMoreUpperNeeded, all comparisons on UpperCase - aString = rString; - ConvertToUpper(aString); - // convert native number to ASCII if necessary - res = IsNumberFormatMain( aString, fOutNumber, pFormat ); - } - - if (res) - { - if ( nNegCheck // ')' not found for '(' - || (nSign && (eScannedType == NUMBERFORMAT_DATE - || eScannedType == NUMBERFORMAT_DATETIME)) - ) // signed date/datetime - res = false; - else - { // check count of partial number strings - switch (eScannedType) - { - case NUMBERFORMAT_PERCENT: - case NUMBERFORMAT_CURRENCY: - case NUMBERFORMAT_NUMBER: - if (nDecPos == 1) // .05 - { - // matched MidStrings function like group separators - if ( nMatchedAllStrings ) - nThousand = nAnzNums - 1; - else if ( nAnzNums != 1 ) - res = false; - } - else if (nDecPos == 2) // 1.05 - { - // matched MidStrings function like group separators - if ( nMatchedAllStrings ) - nThousand = nAnzNums - 1; - else if ( nAnzNums != nThousand+2 ) - res = false; - } - else // 1,100 or 1,100. - { - // matched MidStrings function like group separators - if ( nMatchedAllStrings ) - nThousand = nAnzNums - 1; - else if ( nAnzNums != nThousand+1 ) - res = false; - } - break; - - case NUMBERFORMAT_SCIENTIFIC: // 1.0e-2 - if (nDecPos == 1) // .05 - { - if (nAnzNums != 2) - res = false; - } - else if (nDecPos == 2) // 1.05 - { - if (nAnzNums != nThousand+3) - res = false; - } - else // 1,100 or 1,100. - { - if (nAnzNums != nThousand+2) - res = false; - } - break; - - case NUMBERFORMAT_DATE: - if (nMonth) - { // month name and numbers - if (nAnzNums > 2) - res = false; - } - else - { - if (nAnzNums > 3) - res = false; - } - break; - - case NUMBERFORMAT_TIME: - if (nDecPos) - { // hundredth seconds included - if (nAnzNums > 4) - res = false; - } - else - { - if (nAnzNums > 3) - res = false; - } - break; - - case NUMBERFORMAT_DATETIME: - if (nMonth) - { // month name and numbers - if (nDecPos) - { // hundredth seconds included - if (nAnzNums > 6) - res = false; - } - else - { - if (nAnzNums > 5) - res = false; - } - } - else - { - if (nDecPos) - { // hundredth seconds included - if (nAnzNums > 7) - res = false; - } - else - { - if (nAnzNums > 6) - res = false; - } - } - break; - - default: - break; - } // switch - } // else - } // if (res) - - if (res) - { // we finally have a number - switch (eScannedType) - { - case NUMBERFORMAT_LOGICAL: - if (nLogical == 1) - fOutNumber = 1.0; // True - else if (nLogical == -1) - fOutNumber = 0.0; // False - else - res = false; // Oops - break; - - case NUMBERFORMAT_PERCENT: - case NUMBERFORMAT_CURRENCY: - case NUMBERFORMAT_NUMBER: - case NUMBERFORMAT_SCIENTIFIC: - case NUMBERFORMAT_DEFINED: // if no category detected handle as number - { - if ( nDecPos == 1 ) // . at start - sResString = L"0."; - else - sResString.erase(); - sal_uInt16 k; - for ( k = 0; k <= nThousand; k++) - sResString += sStrArray[nNums[k]]; // integer part - if ( nDecPos == 2 && k < nAnzNums ) // . somewhere - { - sResString += L'.'; - sal_uInt16 nStop = (eScannedType == NUMBERFORMAT_SCIENTIFIC ? - nAnzNums-1 : nAnzNums); - for ( ; k < nStop; k++) - sResString += sStrArray[nNums[k]]; // fractional part - } - - if (eScannedType != NUMBERFORMAT_SCIENTIFIC) - fOutNumber = StringToDouble(sResString); - else - { // append exponent - sResString += L'E'; - if ( nESign == -1 ) - sResString += L'-'; - sResString += sStrArray[nNums[nAnzNums-1]]; - try { - fOutNumber = std::stod(sResString); - } - catch(std::exception e) - { - F_Type = NUMBERFORMAT_TEXT; // overflow/underflow -> Text - if (nESign == -1) - fOutNumber = 0.0; - else - fOutNumber = DBL_MAX; -/*!*/ return true; - } - } - - if ( nStringScanSign ) - { - if ( nSign ) - nSign *= nStringScanSign; - else - nSign = nStringScanSign; - } - if ( nSign < 0 ) - fOutNumber = -fOutNumber; - - if (eScannedType == NUMBERFORMAT_PERCENT) - fOutNumber/= 100.0; - } - break; - - case NUMBERFORMAT_FRACTION: - if (nAnzNums == 1) - fOutNumber = StringToDouble(sStrArray[nNums[0]]); - else if (nAnzNums == 2) - { - if (nThousand == 1) - { - sResString = sStrArray[nNums[0]]; - sResString += sStrArray[nNums[1]]; // integer part - fOutNumber = StringToDouble(sResString); - } - else - { - double fZaehler = StringToDouble(sStrArray[nNums[0]]); - double fNenner = StringToDouble(sStrArray[nNums[1]]); - if (fNenner != 0.0) - fOutNumber = fZaehler/fNenner; - else - res = false; - } - } - else // nAnzNums > 2 - { - sal_uInt16 k = 1; - sResString = sStrArray[nNums[0]]; - if (nThousand > 0) - for (k = 1; k <= nThousand; k++) - sResString += sStrArray[nNums[k]]; - fOutNumber = StringToDouble(sResString); - - if (k == nAnzNums-2) - { - double fZaehler = StringToDouble(sStrArray[nNums[k]]); - double fNenner = StringToDouble(sStrArray[nNums[k+1]]); - if (fNenner != 0.0) - fOutNumber += fZaehler/fNenner; - else - res = false; - } - } - - if ( nStringScanSign ) - { - if ( nSign ) - nSign *= nStringScanSign; - else - nSign = nStringScanSign; - } - if ( nSign < 0 ) - fOutNumber = -fOutNumber; - break; - - case NUMBERFORMAT_TIME: - GetTimeRef(fOutNumber, 0, nAnzNums); - if ( nSign < 0 ) - fOutNumber = -fOutNumber; - break; - - case NUMBERFORMAT_DATE: - { - sal_uInt16 nCounter = 0; // dummy here - res = GetDateRef( fOutNumber, nCounter, pFormat ); - } - break; - - case NUMBERFORMAT_DATETIME: - { - sal_uInt16 nCounter = 0; // needed here - res = GetDateRef( fOutNumber, nCounter, pFormat ); - if ( res ) - { - double fTime; - GetTimeRef( fTime, nCounter, nAnzNums - nCounter ); - fOutNumber += fTime; - } - } - break; - - default: - //DBG_ERRORFILE( "Some number recognized but what's it?" ); - fOutNumber = 0.0; - break; - } - } - - if (res) // overflow/underflow -> Text - { - if (fOutNumber < -DBL_MAX) // -1.7E308 - { - F_Type = NUMBERFORMAT_TEXT; - fOutNumber = -DBL_MAX; - return true; - } - else if (fOutNumber > DBL_MAX) // 1.7E308 - { - F_Type = NUMBERFORMAT_TEXT; - fOutNumber = DBL_MAX; - return true; - } - } - - if (res == false) - { - eScannedType = NUMBERFORMAT_TEXT; - fOutNumber = 0.0; - } - - F_Type = eScannedType; - return res; -} - - -// ------------------------------------- zforscan.cxx ----------------------------------------------- - -const sal_Unicode cNonBreakingSpace = 0xA0; - -bool isLetter(const String& rStr, uint16_t nPos) -{ - if (nPos < 0 || nPos >= rStr.size()) { - return false; - } - sal_Unicode c = rStr.at(nPos); - if (c >= L'A' && c <= L'Z' || c >= L'a' && c <= L'z') { - return true; - } - return false; -} - - -ImpSvNumberformatScan::ImpSvNumberformatScan( LocaleData* pFormatterP ) -{ - pFormatter = pFormatterP; - bConvertMode = false; - //! All keywords MUST be UPPERCASE! - sKeyword[NF_KEY_E] = L"E"; // Exponent - sKeyword[NF_KEY_AMPM] = L"AM/PM"; // AM/PM - sKeyword[NF_KEY_AP] = L"A/P"; // AM/PM short - sKeyword[NF_KEY_MI] = L"M"; // Minute - sKeyword[NF_KEY_MMI] = L"MM"; // Minute 02 - sKeyword[NF_KEY_S] = L"S"; // Second - sKeyword[NF_KEY_SS] = L"SS"; // Second 02 - sKeyword[NF_KEY_Q] = L"Q"; // Quarter short 'Q' - sKeyword[NF_KEY_QQ] = L"QQ"; // Quarter long - sKeyword[NF_KEY_NN] = L"NN"; // Day of week short - sKeyword[NF_KEY_NNN] = L"NNN"; // Day of week long - sKeyword[NF_KEY_NNNN] = L"NNNN"; // Day of week long incl. separator - sKeyword[NF_KEY_WW] = L"WW"; // Week of year - sKeyword[NF_KEY_CCC] = L"CCC"; // Currency abbreviation - bKeywordsNeedInit = true; // locale dependent keywords - bCompatCurNeedInit = true; // locale dependent compatibility currency strings - - nStandardPrec = 2; - - sErrStr = L"###"; - Reset(); -} - -ImpSvNumberformatScan::~ImpSvNumberformatScan() -{ - Reset(); -} - - -void ImpSvNumberformatScan::ChangeIntl() -{ - bKeywordsNeedInit = true; - bCompatCurNeedInit = true; - // may be initialized by InitSpecialKeyword() - sKeyword[NF_KEY_TRUE].erase(); - sKeyword[NF_KEY_FALSE].erase(); -} - - -void ImpSvNumberformatScan::InitSpecialKeyword( NfKeywordIndex eIdx ) const -{ - String str; - switch ( eIdx ) - { - case NF_KEY_TRUE : - str = pFormatter->getReservedWord(reservedWords::TRUE_WORD); - ConvertToUpper(str); - ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE] = str; - if ( !sKeyword[NF_KEY_TRUE].size() ) - { - ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE] = L"true"; - } - break; - case NF_KEY_FALSE : - str = pFormatter->getReservedWord(reservedWords::FALSE_WORD); - ConvertToUpper(str); - ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE] = str; - if ( !sKeyword[NF_KEY_FALSE].size() ) - { - ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE] = L"false"; - } - break; - default: - break; - } -} - - -void ImpSvNumberformatScan::InitCompatCur() const -{ - ImpSvNumberformatScan* pThis = (ImpSvNumberformatScan*)this; - // currency symbol for old style ("automatic") compatibility format codes - //pFormatter->GetCompatibilityCurrency( pThis->sCurSymbol, pThis->sCurAbbrev ); - pThis->sCurAbbrev = pFormatter->getCurrBankSymbol(); - pThis->sCurSymbol = pFormatter->getCurrSymbol(); - - // currency symbol upper case - String str = sCurSymbol; - ConvertToUpper(str); - pThis->sCurString = str; - - bCompatCurNeedInit = false; -} - - -void ImpSvNumberformatScan::InitKeywords() const -{ - if ( !bKeywordsNeedInit ) - return ; - ((ImpSvNumberformatScan*)this)->SetDependentKeywords(); - bKeywordsNeedInit = false; -} - - -/** Extract the name of General, Standard, Whatever, ignoring leading modifiers - such as [NatNum1]. */ -static String lcl_extractStandardGeneralName( const String& rCode ) -{ - String aStr; - const sal_Unicode* p = rCode.data(); - const sal_Unicode* const pStop = p + rCode.size(); - const sal_Unicode* pBeg = p; // name begins here - bool bMod = false; - bool bDone = false; - while (p < pStop && !bDone) - { - switch (*p) - { - case L'[': - bMod = true; - break; - case L']': - if (bMod) - { - bMod = false; - pBeg = p+1; - } - // else: would be a locale data error, easily to be spotted in - // UI dialog - break; - case L';': - if (!bMod) - { - bDone = true; - --p; // put back, increment by one follows - } - break; - } - ++p; - if (bMod) - pBeg = p; - } - if (pBeg < p) - aStr = rCode.substr(pBeg - rCode.data(), p - pBeg); - return aStr; -} - - -void ImpSvNumberformatScan::SetDependentKeywords() -{ - // #80023# be sure to generate keywords for the loaded Locale, not for the - // requested Locale, otherwise number format codes might not match - LocaleIndentifier eLang = pFormatter->GetLocaleId(); - - String aFormat = pFormatter->getFormatCodeNumberStandard(); - sNameStandardFormat = lcl_extractStandardGeneralName( aFormat); - ConvertToUpper(sNameStandardFormat); - sKeyword[NF_KEY_GENERAL] = sNameStandardFormat; - - // preset new calendar keywords - sKeyword[NF_KEY_AAA] = L"AAA"; - sKeyword[NF_KEY_AAAA] = L"AAAA"; - sKeyword[NF_KEY_EC] = L"E"; - sKeyword[NF_KEY_EEC] = L"EE"; - sKeyword[NF_KEY_G] = L"G"; - sKeyword[NF_KEY_GG] = L"GG"; - sKeyword[NF_KEY_GGG] = L"GGG"; - sKeyword[NF_KEY_R] = L"R"; - sKeyword[NF_KEY_RR] = L"RR"; - - // Thai T NatNum special. Other locale's small letter 't' results in upper - // case comparison not matching but length does in conversion mode. Ugly. - //if (eLang == LANGUAGE_THAI) - // sKeyword[NF_KEY_THAI_T] = L"T"; - //else - sKeyword[NF_KEY_THAI_T] = L"t"; - - switch ( eLang ) - { - default: - { - // day - switch ( eLang ) - { - case LocaleId_fr_FR : - sKeyword[NF_KEY_D] = L"J"; - sKeyword[NF_KEY_DD] = L"JJ"; - sKeyword[NF_KEY_DDD] = L"JJJ"; - sKeyword[NF_KEY_DDDD] = L"JJJJ"; - break; - default: - sKeyword[NF_KEY_D] = L"D"; - sKeyword[NF_KEY_DD] = L"DD"; - sKeyword[NF_KEY_DDD] = L"DDD"; - sKeyword[NF_KEY_DDDD] = L"DDDD"; - } - // month - switch ( eLang ) - { - default: - sKeyword[NF_KEY_M] = L"M"; - sKeyword[NF_KEY_MM] = L"MM"; - sKeyword[NF_KEY_MMM] = L"MMM"; - sKeyword[NF_KEY_MMMM] = L"MMMM"; - sKeyword[NF_KEY_MMMMM] = L"MMMMM"; - } - // year - switch ( eLang ) - { - case LocaleId_fr_FR: - sKeyword[NF_KEY_YY] = L"AA"; - sKeyword[NF_KEY_YYYY] = L"AAAA"; - // must exchange the day of week name code, same as Xcl - sKeyword[NF_KEY_AAA] = L"OOO"; - sKeyword[NF_KEY_AAAA] = L"OOOO"; - break; - default: - sKeyword[NF_KEY_YY] = L"YY"; - sKeyword[NF_KEY_YYYY] = L"YYYY"; - } - // hour - switch ( eLang ) - { - default: - sKeyword[NF_KEY_H] = L"H"; - sKeyword[NF_KEY_HH] = L"HH"; - } - // boolean - sKeyword[NF_KEY_BOOLEAN] = L"BOOLEAN"; - // colours - sKeyword[NF_KEY_COLOR] = L"COLOR"; - sKeyword[NF_KEY_BLACK] = L"BLACK"; - sKeyword[NF_KEY_BLUE] = L"BLUE"; - sKeyword[NF_KEY_GREEN] = L"GREEN"; - sKeyword[NF_KEY_CYAN] = L"CYAN"; - sKeyword[NF_KEY_RED] = L"RED"; - sKeyword[NF_KEY_MAGENTA] = L"MAGENTA"; - sKeyword[NF_KEY_BROWN] = L"BROWN"; - sKeyword[NF_KEY_GREY] = L"GREY"; - sKeyword[NF_KEY_YELLOW] = L"YELLOW"; - sKeyword[NF_KEY_WHITE] = L"WHITE"; - } - break; - } - - // boolean keyords - InitSpecialKeyword( NF_KEY_TRUE ); - InitSpecialKeyword( NF_KEY_FALSE ); - - // compatibility currency strings - InitCompatCur(); -} - - -void ImpSvNumberformatScan::ChangeStandardPrec(sal_uInt16 nPrec) -{ - nStandardPrec = nPrec; -} - -short ImpSvNumberformatScan::GetKeyWord( const String& sSymbol, uint16_t nPos ) -{ - String sString = sSymbol.substr(nPos); - ConvertToUpper(sString); - const NfKeywordTable & rKeyword = GetKeywords(); - // #77026# for the Xcl perverts: the GENERAL keyword is recognized anywhere - if ( sString.find( rKeyword[NF_KEY_GENERAL] ) == 0 ) - return NF_KEY_GENERAL; - //! MUST be a reverse search to find longer strings first - short i = NF_KEYWORD_ENTRIES_COUNT-1; - bool bFound = false; - for ( ; i > NF_KEY_LASTKEYWORD_SO5; --i ) - { - bFound = sString.find(rKeyword[i]) == 0; - if ( bFound ) - { - break; - } - } - // new keywords take precedence over old keywords - if ( !bFound ) - { // skip the gap of colors et al between new and old keywords and search on - i = NF_KEY_LASTKEYWORD; - while ( i > 0 && sString.find(rKeyword[i]) != 0) - i--; - if ( i > NF_KEY_LASTOLDKEYWORD && sString != rKeyword[i] ) - { // found something, but maybe it's something else? - // e.g. new NNN is found in NNNN, for NNNN we must search on - short j = i - 1; - while ( j > 0 && sString.find(rKeyword[j]) != 0) - j--; - if ( j && rKeyword[j].size() > rKeyword[i].size() ) - return j; - } - } - return i; // 0 => not found -} - -short ImpSvNumberformatScan::Next_Symbol( const String& rStr, - uint16_t& nPos, String& sSymbol ) -{ - if ( bKeywordsNeedInit ) - InitKeywords(); - const uint16_t nStart = nPos; - short eType = 0; - ScanState eState = SsStart; - sSymbol.erase(); - while ( nPos < rStr.size() && eState != SsStop ) - { - sal_Unicode cToken = rStr.at( nPos++ ); - switch (eState) - { - case SsStart: - { - // Fetch any currency longer than one character and don't get - // confused later on by "E/" or other combinations of letters - // and meaningful symbols. Necessary for old automatic currency. - // #96158# But don't do it if we're starting a "[...]" section, - // for example a "[$...]" new currency symbol to not parse away - // "$U" (symbol) of "[$UYU]" (abbreviation). - if ( nCurrPos != STRING_NOTFOUND && sCurString.size() > 1 && - nPos-1 + sCurString.size() <= rStr.size() && - !(nPos > 1 && rStr.at( nPos-2 ) == L'[') ) - { - String aTest( rStr.substr( nPos-1, sCurString.size() ) ); - ConvertToUpper(aTest); - if ( aTest == sCurString ) - { - sSymbol = rStr.substr( --nPos, sCurString.size() ); - nPos = nPos + sSymbol.size(); - eState = SsStop; - eType = NF_SYMBOLTYPE_STRING; - return eType; - } - } - switch (cToken) - { - case L'#': - case L'0': - case L'?': - case L'%': - case L'@': - case L'[': - case L']': - case L',': - case L'.': - case L'/': - case L'\'': - case L' ': - case L':': - case L'-': - { - eType = NF_SYMBOLTYPE_DEL; - sSymbol += cToken; - eState = SsStop; - } - break; - case L'*': - { - eType = NF_SYMBOLTYPE_STAR; - sSymbol += cToken; - eState = SsGetStar; - } - break; - case L'_': - { - eType = NF_SYMBOLTYPE_BLANK; - sSymbol += cToken; - eState = SsGetBlank; - } - break; - case L'"': - eType = NF_SYMBOLTYPE_STRING; - eState = SsGetString; - sSymbol += cToken; - break; - case L'\\': - eType = NF_SYMBOLTYPE_STRING; - eState = SsGetChar; - sSymbol += cToken; - break; - case L'$': - case L'+': - case L'(': - case L')': - eType = NF_SYMBOLTYPE_STRING; - eState = SsStop; - sSymbol += cToken; - break; - default : - { - if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cToken) || - StringEqualsChar( pFormatter->GetNumThousandSep(), cToken) || - StringEqualsChar( pFormatter->GetDateSep(), cToken) || - StringEqualsChar(pFormatter->getTimeSep(), cToken) || - StringEqualsChar(pFormatter->getTime100SecSep(), cToken)) - { - // Another separator than pre-known ASCII - eType = NF_SYMBOLTYPE_DEL; - sSymbol += cToken; - eState = SsStop; - } - else if ( isLetter( rStr, nPos-1 ) ) - { - short nTmpType = GetKeyWord( rStr, nPos-1 ); - if ( nTmpType ) - { - bool bCurrency = false; - // "Automatic" currency may start with keyword, - // like "R" (Rand) and 'R' (era) - if ( nCurrPos != STRING_NOTFOUND && - nPos-1 + sCurString.size() <= rStr.size() && - sCurString.find( sKeyword[nTmpType] ) == 0 ) - { - String aTest( rStr.substr( nPos-1, sCurString.size() ) ); - ConvertToUpper(aTest); - if ( aTest == sCurString ) - bCurrency = true; - } - if ( bCurrency ) - { - eState = SsGetWord; - sSymbol += cToken; - } - else - { - eType = nTmpType; - uint16_t nLen = sKeyword[eType].size(); - sSymbol = rStr.substr( nPos-1, nLen ); - if ( eType == NF_KEY_E || IsAmbiguousE( eType ) ) - { - sal_Unicode cNext = rStr.at(nPos); - switch ( cNext ) - { - case L'+' : - case L'-' : // E+ E- combine to one symbol - sSymbol += cNext; - eType = NF_KEY_E; - nPos++; - break; - case L'0' : - case L'#' : // scientific E without sign - eType = NF_KEY_E; - break; - } - } - nPos--; - nPos = nPos + nLen; - eState = SsStop; - } - } - else - { - eState = SsGetWord; - sSymbol += cToken; - } - } - else if (std::iswdigit(rStr.at(nPos-1))) - { - eType = NF_SYMBOLTYPE_DIGIT; - eState = SsStop; - sSymbol += cToken; - } - else - { - eType = NF_SYMBOLTYPE_STRING; - eState = SsStop; - sSymbol += cToken; - } - } - break; - } - } - break; - case SsGetChar: - { - sSymbol += cToken; - eState = SsStop; - } - break; - case SsGetString: - { - if (cToken == L'"') - eState = SsStop; - sSymbol += cToken; - } - break; - case SsGetWord: - { - if ( isLetter( rStr, nPos-1 ) ) - { - short nTmpType = GetKeyWord( rStr, nPos-1 ); - if ( nTmpType ) - { // beginning of keyword, stop scan and put back - eType = NF_SYMBOLTYPE_STRING; - eState = SsStop; - nPos--; - } - else - sSymbol += cToken; - } - else - { - bool bDontStop = false; - switch (cToken) - { - case L'/': // AM/PM, A/P - { - sal_Unicode cNext = rStr.at(nPos); - if ( cNext == L'P' || cNext == L'p' ) - { - uint16_t nLen = sSymbol.size(); - if ( 1 <= nLen - && (sSymbol.at(0) == L'A' || sSymbol.at(0) == L'a') - && (nLen == 1 || (nLen == 2 - && (sSymbol.at(1) == L'M' || sSymbol.at(1) == L'm') - && (rStr.at(nPos+1) == L'M' || rStr.at(nPos+1) == L'm'))) ) - { - sSymbol += cToken; - bDontStop = true; - } - } - } - break; - } - // anything not recognized will stop the scan - if ( eState != SsStop && !bDontStop ) - { - eState = SsStop; - nPos--; - eType = NF_SYMBOLTYPE_STRING; - } - } - } - break; - case SsGetStar: - { - eState = SsStop; - sSymbol += cToken; - nRepPos = (nPos - nStart) - 1; // every time > 0!! - } - break; - case SsGetBlank: - { - eState = SsStop; - sSymbol += cToken; - } - break; - default: - break; - } // of switch - } // of while - if (eState == SsGetWord) - eType = NF_SYMBOLTYPE_STRING; - return eType; -} - -uint16_t ImpSvNumberformatScan::Symbol_Division(const String& rString) -{ - nCurrPos = STRING_NOTFOUND; - // Is currency involved? - String sString = rString; - ConvertToUpper(sString); - uint16_t nCPos = 0; - while (nCPos != STRING_NOTFOUND) - { - nCPos = sString.find(GetCurString(), nCPos); - if (nCPos != STRING_NOTFOUND) - { - // in Quotes? - uint16_t nQ = SvNumberformat::GetQuoteEnd( sString, nCPos ); - if ( nQ == STRING_NOTFOUND ) - { - sal_Unicode c; - if ( nCPos == 0 || - ((c = sString.at(uint16_t(nCPos-1))) != '"' - && c != L'\\') ) // dm can be replaced by "dm - { // \d to be protected - nCurrPos = nCPos; - nCPos = STRING_NOTFOUND; // cancellation - } - else - nCPos++; // keep searching - } - else - nCPos = nQ + 1; // keep searching - } - } - nAnzStrings = 0; - bool bStar = false; // is set with '*'detection - Reset(); - - uint16_t nPos = 0; - const uint16_t nLen = rString.size(); - while (nPos < nLen && nAnzStrings < NF_MAX_FORMAT_SYMBOLS) - { - nTypeArray[nAnzStrings] = Next_Symbol(rString, nPos, sStrArray[nAnzStrings]); - if (nTypeArray[nAnzStrings] == NF_SYMBOLTYPE_STAR) - { // monitoring of '*' - if (bStar) - return nPos; // error: double '*' - else - bStar = true; - } - nAnzStrings++; - } - - return 0; // 0 => ok -} - -void ImpSvNumberformatScan::SkipStrings(sal_uInt16& i, uint16_t& nPos) -{ - while (i < nAnzStrings && ( nTypeArray[i] == NF_SYMBOLTYPE_STRING - || nTypeArray[i] == NF_SYMBOLTYPE_BLANK - || nTypeArray[i] == NF_SYMBOLTYPE_STAR) ) - { - nPos = nPos + sStrArray[i].size(); - i++; - } -} - - -sal_uInt16 ImpSvNumberformatScan::PreviousKeyword(sal_uInt16 i) -{ - short res = 0; - if (i > 0 && i < nAnzStrings) - { - i--; - while (i > 0 && nTypeArray[i] <= 0) - i--; - if (nTypeArray[i] > 0) - res = nTypeArray[i]; - } - return res; -} - -sal_uInt16 ImpSvNumberformatScan::NextKeyword(sal_uInt16 i) -{ - short res = 0; - if (i < nAnzStrings-1) - { - i++; - while (i < nAnzStrings-1 && nTypeArray[i] <= 0) - i++; - if (nTypeArray[i] > 0) - res = nTypeArray[i]; - } - return res; -} - -short ImpSvNumberformatScan::PreviousType( sal_uInt16 i ) -{ - if ( i > 0 && i < nAnzStrings ) - { - do - { - i--; - } while ( i > 0 && nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ); - return nTypeArray[i]; - } - return 0; -} - -sal_Unicode ImpSvNumberformatScan::PreviousChar(sal_uInt16 i) -{ - sal_Unicode res = L' '; - if (i > 0 && i < nAnzStrings) - { - i--; - while (i > 0 && ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY - || nTypeArray[i] == NF_SYMBOLTYPE_STRING - || nTypeArray[i] == NF_SYMBOLTYPE_STAR - || nTypeArray[i] == NF_SYMBOLTYPE_BLANK ) ) - i--; - if (sStrArray[i].size() > 0) - res = sStrArray[i].at(uint16_t(sStrArray[i].size()-1)); - } - return res; -} - -sal_Unicode ImpSvNumberformatScan::NextChar(sal_uInt16 i) -{ - sal_Unicode res = L' '; - if (i < nAnzStrings-1) - { - i++; - while (i < nAnzStrings-1 && - ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY - || nTypeArray[i] == NF_SYMBOLTYPE_STRING - || nTypeArray[i] == NF_SYMBOLTYPE_STAR - || nTypeArray[i] == NF_SYMBOLTYPE_BLANK)) - i++; - if (sStrArray[i].size() > 0) - res = sStrArray[i].at(0); - } - return res; -} - -bool ImpSvNumberformatScan::IsLastBlankBeforeFrac(sal_uInt16 i) -{ - bool res = true; - if (i < nAnzStrings-1) - { - bool bStop = false; - i++; - while (i < nAnzStrings-1 && !bStop) - { - i++; - if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL && - sStrArray[i].at(0) == L'/') - bStop = true; - else if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL && - sStrArray[i].at(0) == L' ') - res = false; - } - if (!bStop) // kein '/' - res = false; - } - else - res = false; // kein '/' mehr - - return res; -} - -void ImpSvNumberformatScan::Reset() -{ - nAnzStrings = 0; - nAnzResStrings = 0; - - for (size_t i = 0; i < NF_MAX_FORMAT_SYMBOLS; i++) - { - sStrArray[i].erase(); - nTypeArray[i] = 0; - } - - eScannedType = NUMBERFORMAT_UNDEFINED; - nRepPos = 0; - bExp = false; - bThousand = false; - nThousand = 0; - bDecSep = false; - nDecPos = -1; - nExpPos = (sal_uInt16) -1; - nBlankPos = (sal_uInt16) -1; - nCntPre = 0; - nCntPost = 0; - nCntExp = 0; - nExpVal = 0; - bFrac = false; - bBlank = false; - nNatNumModifier = 0; -} - - -bool ImpSvNumberformatScan::Is100SecZero( sal_uInt16 i, bool bHadDecSep ) -{ - sal_uInt16 nIndexPre = PreviousKeyword( i ); - return (nIndexPre == NF_KEY_S || nIndexPre == NF_KEY_SS) - && (bHadDecSep // S, SS ',' - || (i>0 && nTypeArray[i-1] == NF_SYMBOLTYPE_STRING)); - // SS"any"00 take "any" as a valid decimal separator -} - - -uint16_t ImpSvNumberformatScan::ScanType(const String&) -{ - uint16_t nPos = 0; - sal_uInt16 i = 0; - short eNewType; - bool bMatchBracket = false; - bool bHaveGeneral = false; // if General/Standard encountered - - SkipStrings(i, nPos); - while (i < nAnzStrings) - { - if (nTypeArray[i] > 0) - { // keyword - switch (nTypeArray[i]) - { - case NF_KEY_E: // E - eNewType = NUMBERFORMAT_SCIENTIFIC; - break; - case NF_KEY_AMPM: // AM,A,PM,P - case NF_KEY_AP: - case NF_KEY_H: // H - case NF_KEY_HH: // HH - case NF_KEY_S: // S - case NF_KEY_SS: // SS - eNewType = NUMBERFORMAT_TIME; - break; - case NF_KEY_M: // M - case NF_KEY_MM: // MM - { // minute or month - sal_uInt16 nIndexPre = PreviousKeyword(i); - sal_uInt16 nIndexNex = NextKeyword(i); - sal_Unicode cChar = PreviousChar(i); - if (nIndexPre == NF_KEY_H || // H - nIndexPre == NF_KEY_HH || // HH - nIndexNex == NF_KEY_S || // S - nIndexNex == NF_KEY_SS || // SS - cChar == L'[' ) // [M - { - eNewType = NUMBERFORMAT_TIME; - nTypeArray[i] -= 2; // 6 -> 4, 7 -> 5 - } - else - eNewType = NUMBERFORMAT_DATE; - } - break; - case NF_KEY_MMM: // MMM - case NF_KEY_MMMM: // MMMM - case NF_KEY_MMMMM: // MMMMM - case NF_KEY_Q: // Q - case NF_KEY_QQ: // QQ - case NF_KEY_D: // D - case NF_KEY_DD: // DD - case NF_KEY_DDD: // DDD - case NF_KEY_DDDD: // DDDD - case NF_KEY_YY: // YY - case NF_KEY_YYYY: // YYYY - case NF_KEY_NN: // NN - case NF_KEY_NNN: // NNN - case NF_KEY_NNNN: // NNNN - case NF_KEY_WW : // WW - case NF_KEY_AAA : // AAA - case NF_KEY_AAAA : // AAAA - case NF_KEY_EC : // E - case NF_KEY_EEC : // EE - case NF_KEY_G : // G - case NF_KEY_GG : // GG - case NF_KEY_GGG : // GGG - case NF_KEY_R : // R - case NF_KEY_RR : // RR - eNewType = NUMBERFORMAT_DATE; - break; - case NF_KEY_CCC: // CCC - eNewType = NUMBERFORMAT_CURRENCY; - break; - case NF_KEY_GENERAL: // Standard - eNewType = NUMBERFORMAT_NUMBER; - bHaveGeneral = true; - break; - default: - eNewType = NUMBERFORMAT_UNDEFINED; - break; - } - } - else - { // control character - switch ( sStrArray[i].at(0) ) - { - case L'#': - case L'?': - eNewType = NUMBERFORMAT_NUMBER; - break; - case L'0': - { - if ( (eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME ) - { - if ( Is100SecZero( i, bDecSep ) ) - { - bDecSep = true; // subsequent 0's - eNewType = NUMBERFORMAT_TIME; - } - else - return nPos; // Error - } - else - eNewType = NUMBERFORMAT_NUMBER; - } - break; - case L'%': - eNewType = NUMBERFORMAT_PERCENT; - break; - case L'/': - eNewType = NUMBERFORMAT_FRACTION; - break; - case L'[': - { - if ( i < nAnzStrings-1 && - nTypeArray[i+1] == NF_SYMBOLTYPE_STRING && - sStrArray[i+1].at(0) == L'$' ) - { // as of SV_NUMBERFORMATTER_VERSION_NEW_CURR - eNewType = NUMBERFORMAT_CURRENCY; - bMatchBracket = true; - } - else if ( i < nAnzStrings-1 && - nTypeArray[i+1] == NF_SYMBOLTYPE_STRING && - sStrArray[i+1].at(0) == L'~' ) - { // as of SV_NUMBERFORMATTER_VERSION_CALENDAR - eNewType = NUMBERFORMAT_DATE; - bMatchBracket = true; - } - else - { - sal_uInt16 nIndexNex = NextKeyword(i); - if (nIndexNex == NF_KEY_H || // H - nIndexNex == NF_KEY_HH || // HH - nIndexNex == NF_KEY_M || // M - nIndexNex == NF_KEY_MM || // MM - nIndexNex == NF_KEY_S || // S - nIndexNex == NF_KEY_SS ) // SS - eNewType = NUMBERFORMAT_TIME; - else - return nPos; // Error - } - } - break; - case L'@': - eNewType = NUMBERFORMAT_TEXT; - break; - default: - if ( sStrArray[i] == pFormatter->getTime100SecSep() ) - bDecSep = true; // for SS,0 - eNewType = NUMBERFORMAT_UNDEFINED; - break; - } - } - if (eScannedType == NUMBERFORMAT_UNDEFINED) - eScannedType = eNewType; - else if (eScannedType == NUMBERFORMAT_TEXT || eNewType == NUMBERFORMAT_TEXT) - eScannedType = NUMBERFORMAT_TEXT; // Text is always text - else if (eNewType == NUMBERFORMAT_UNDEFINED) - { // remains as before - } - else if (eScannedType != eNewType) - { - switch (eScannedType) - { - case NUMBERFORMAT_DATE: - { - switch (eNewType) - { - case NUMBERFORMAT_TIME: - eScannedType = NUMBERFORMAT_DATETIME; - break; - case NUMBERFORMAT_FRACTION: // DD/MM - break; - default: - { - if (nCurrPos != STRING_NOTFOUND) - eScannedType = NUMBERFORMAT_UNDEFINED; - else if ( sStrArray[i] != pFormatter->GetDateSep() ) - return nPos; - } - } - } - break; - case NUMBERFORMAT_TIME: - { - switch (eNewType) - { - case NUMBERFORMAT_DATE: - eScannedType = NUMBERFORMAT_DATETIME; - break; - case NUMBERFORMAT_FRACTION: // MM/SS - break; - default: - { - if (nCurrPos != STRING_NOTFOUND) - eScannedType = NUMBERFORMAT_UNDEFINED; - else if ( sStrArray[i] != pFormatter->getTimeSep() ) - return nPos; - } - } - } - break; - case NUMBERFORMAT_DATETIME: - { - switch (eNewType) - { - case NUMBERFORMAT_TIME: - case NUMBERFORMAT_DATE: - break; - case NUMBERFORMAT_FRACTION: // DD/MM - break; - default: - { - if (nCurrPos != STRING_NOTFOUND) - eScannedType = NUMBERFORMAT_UNDEFINED; - else if ( sStrArray[i] != pFormatter->GetDateSep() - && sStrArray[i] != pFormatter->getTimeSep() ) - return nPos; - } - } - } - break; - case NUMBERFORMAT_PERCENT: - { - switch (eNewType) - { - case NUMBERFORMAT_NUMBER: // only number by percent - break; - default: - return nPos; - } - } - break; - case NUMBERFORMAT_SCIENTIFIC: - { - switch (eNewType) - { - case NUMBERFORMAT_NUMBER: // only number after E - break; - default: - return nPos; - } - } - break; - case NUMBERFORMAT_NUMBER: - { - switch (eNewType) - { - case NUMBERFORMAT_SCIENTIFIC: - case NUMBERFORMAT_PERCENT: - case NUMBERFORMAT_FRACTION: - case NUMBERFORMAT_CURRENCY: - eScannedType = eNewType; - break; - default: - if (nCurrPos != STRING_NOTFOUND) - eScannedType = NUMBERFORMAT_UNDEFINED; - else - return nPos; - } - } - break; - case NUMBERFORMAT_FRACTION: - { - switch (eNewType) - { - case NUMBERFORMAT_NUMBER: // only number after fraction - break; - default: - return nPos; - } - } - break; - default: - break; - } - } - nPos = nPos + sStrArray[i].size(); // Proofreading position - i++; - if ( bMatchBracket ) - { // no type detection inside of matching brackets if [$...], [~...] - while ( bMatchBracket && i < nAnzStrings ) - { - if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL - && sStrArray[i].at(0) == L']' ) - bMatchBracket = false; - else - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - i++; - } - if ( bMatchBracket ) - return nPos; // missing closing bracket at end of code - } - SkipStrings(i, nPos); - } - - if ((eScannedType == NUMBERFORMAT_NUMBER || eScannedType == NUMBERFORMAT_UNDEFINED) - && nCurrPos != STRING_NOTFOUND && !bHaveGeneral) - eScannedType = NUMBERFORMAT_CURRENCY; // old "automatic" currency - if (eScannedType == NUMBERFORMAT_UNDEFINED) - eScannedType = NUMBERFORMAT_DEFINED; - return 0; // Alles ok -} - - -bool ImpSvNumberformatScan::InsertSymbol( sal_uInt16 & nPos, NfSymbolType eType, const String& rStr ) -{ - if (nAnzStrings >= NF_MAX_FORMAT_SYMBOLS || nPos > nAnzStrings) - return false; - ++nAnzResStrings; - if (nPos > 0 && nTypeArray[nPos-1] == NF_SYMBOLTYPE_EMPTY) - --nPos; // reuse position - else - { - ++nAnzStrings; - for (size_t i = nAnzStrings; i > nPos; --i) - { - nTypeArray[i] = nTypeArray[i-1]; - sStrArray[i] = sStrArray[i-1]; - } - } - nTypeArray[nPos] = static_cast(eType); - sStrArray[nPos] = rStr; - return true; -} - - -int ImpSvNumberformatScan::FinalScanGetCalendar( uint16_t& nPos, sal_uInt16& i, - sal_uInt16& rAnzResStrings ) -{ - return 0; -} - -uint16_t ImpSvNumberformatScan::FinalScan( String& rString, String& rComment ) -{ - // save values for convert mode - String sOldDecSep = pFormatter->GetNumDecimalSep(); - String sOldThousandSep = pFormatter->GetNumThousandSep(); - String sOldDateSep = pFormatter->GetDateSep(); - String sOldTimeSep = pFormatter->getTimeSep(); - String sOldTime100SecSep= pFormatter->getTime100SecSep(); - String sOldCurSymbol = GetCurSymbol(); - String sOldCurString = GetCurString(); - sal_Unicode cOldKeyH = sKeyword[NF_KEY_H].at(0); - sal_Unicode cOldKeyMI = sKeyword[NF_KEY_MI].at(0); - sal_Unicode cOldKeyS = sKeyword[NF_KEY_S].at(0); - - // If the group separator is a Non-Breaking Space (French) continue with a - // normal space instead so queries on space work correctly. - // The format string is adjusted to allow both. - // For output of the format code string the LocaleData characters are used. - if ( sOldThousandSep.at(0) == cNonBreakingSpace && sOldThousandSep.size() == 1 ) - sOldThousandSep = L' '; - - // change locale data et al - if (bConvertMode) - { - pFormatter->SetLocaleId(eNewLnge); - //! init new keywords - InitKeywords(); - } - - uint16_t nPos = 0; // error correction position - sal_uInt16 i = 0; // symbol loop counter - sal_uInt16 nCounter = 0; // counts digits - nAnzResStrings = nAnzStrings; // counts remaining symbols - bDecSep = false; // reset in case already used in TypeCheck - bool bThaiT = false; // Thai T NatNum modifier present - - switch (eScannedType) - { - case NUMBERFORMAT_TEXT: - case NUMBERFORMAT_DEFINED: - { - while (i < nAnzStrings) - { - switch (nTypeArray[i]) - { - case NF_SYMBOLTYPE_BLANK: - case NF_SYMBOLTYPE_STAR: - break; - case NF_SYMBOLTYPE_COMMENT: - { - String& rStr = sStrArray[i]; - nPos = nPos + rStr.size(); - SvNumberformat::EraseCommentBraces( rStr ); - rComment += rStr; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - } - break; - case NF_KEY_GENERAL : // #77026# "General" is the same as "@" - break; - default: - { - if ( nTypeArray[i] != NF_SYMBOLTYPE_DEL || - sStrArray[i].at(0) != L'@' ) - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - } - break; - } - nPos = nPos + sStrArray[i].size(); - i++; - } // of while - } - break; - case NUMBERFORMAT_NUMBER: - case NUMBERFORMAT_PERCENT: - case NUMBERFORMAT_CURRENCY: - case NUMBERFORMAT_SCIENTIFIC: - case NUMBERFORMAT_FRACTION: - { - sal_Unicode cThousandFill = L' '; - while (i < nAnzStrings) - { - if (eScannedType == NUMBERFORMAT_FRACTION && // special case - nTypeArray[i] == NF_SYMBOLTYPE_DEL && // # ### #/# - StringEqualsChar( sOldThousandSep, L' ' ) && // e.g. France or Sweden - StringEqualsChar( sStrArray[i], L' ' ) && - !bFrac && - IsLastBlankBeforeFrac(i) ) - { - nTypeArray[i] = NF_SYMBOLTYPE_STRING; // del->string - } // no dew.p. - - - if (nTypeArray[i] == NF_SYMBOLTYPE_BLANK || - nTypeArray[i] == NF_SYMBOLTYPE_STAR || - nTypeArray[i] == NF_KEY_CCC || // CCC - nTypeArray[i] == NF_KEY_GENERAL ) // Standard - { - if (nTypeArray[i] == NF_KEY_GENERAL) - { - nThousand = FLAG_STANDARD_IN_FORMAT; - if ( bConvertMode ) - sStrArray[i] = sNameStandardFormat; - } - nPos = nPos + sStrArray[i].size(); - i++; - } - else if (nTypeArray[i] == NF_SYMBOLTYPE_STRING || // Strings oder - nTypeArray[i] > 0) // Keywords - { - if (eScannedType == NUMBERFORMAT_SCIENTIFIC && - nTypeArray[i] == NF_KEY_E) // E+ - { - if (bExp) // doppelt - return nPos; - bExp = true; - nExpPos = i; - if (bDecSep) - nCntPost = nCounter; - else - nCntPre = nCounter; - nCounter = 0; - nTypeArray[i] = NF_SYMBOLTYPE_EXP; - } - else if (eScannedType == NUMBERFORMAT_FRACTION && - sStrArray[i].at(0) == L' ') - { - if (!bBlank && !bFrac) // not double or behind / - { - if (bDecSep && nCounter > 0) // decimal places - return nPos; // error - bBlank = true; - nBlankPos = i; - nCntPre = nCounter; - nCounter = 0; - } - nTypeArray[i] = NF_SYMBOLTYPE_FRACBLANK; - } - else if (nTypeArray[i] == NF_KEY_THAI_T) - { - bThaiT = true; - sStrArray[i] = sKeyword[nTypeArray[i]]; - } - else - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - i++; - } - else if (nTypeArray[i] == NF_SYMBOLTYPE_DEL) - { - sal_Unicode cHere = sStrArray[i].at(0); - // Handle not pre-known separators in switch. - sal_Unicode cSimplified; - if (StringEqualsChar( pFormatter->GetNumThousandSep(), cHere)) - cSimplified = L','; - else if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cHere)) - cSimplified = L'.'; - else - cSimplified = cHere; - switch ( cSimplified ) - { - case L'#': - case L'0': - case L'?': - { - if (nThousand > 0) // #... # - return nPos; // error - //else if (bFrac && cHere == L'0') // modified for "0 0/0" - // return nPos; // 0 in the denominator - nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; - String& rStr = sStrArray[i]; - nPos = nPos + rStr.size(); - i++; - nCounter++; - while (i < nAnzStrings && - (sStrArray[i].at(0) == L'#' || - sStrArray[i].at(0) == L'0' || - sStrArray[i].at(0) == L'?') - ) - { - nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; - nPos = nPos + sStrArray[i].size(); - nCounter++; - i++; - } - } - break; - case L'-': - { - if ( bDecSep && nDecPos+1 == i && - nTypeArray[nDecPos] == NF_SYMBOLTYPE_DECSEP ) - { // "0.--" - nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; - String& rStr = sStrArray[i]; - nPos = nPos + rStr.size(); - i++; - nCounter++; - while (i < nAnzStrings && - (sStrArray[i].at(0) == L'-') ) - { - // If more than two dashes are present in - // currency formats the last dash will be - // interpreted literally as a minus sign. - // Has to be this ugly. Period. - if ( eScannedType == NUMBERFORMAT_CURRENCY - && rStr.size() >= 2 && - (i == nAnzStrings-1 || - sStrArray[i+1].at(0) != L'-') ) - break; - rStr += sStrArray[i]; - nPos = nPos + sStrArray[i].size(); - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - nCounter++; - i++; - } - } - else - { - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - i++; - } - } - break; - case L'.': - case L',': - case L'\'': - case L' ': - { - sal_Unicode cSep = cHere; // remember - if ( StringEqualsChar( sOldThousandSep, cSep ) ) - { - // previous char with skip empty - sal_Unicode cPre = PreviousChar(i); - sal_Unicode cNext; - if (bExp || bBlank || bFrac) - { // after E, / or ' ' - if ( !StringEqualsChar( sOldThousandSep, L' ' ) ) - { - nPos = nPos + sStrArray[i].size(); - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - i++; // eat it - } - else - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - } - else if (i > 0 && i < nAnzStrings-1 && - (cPre == L'#' || cPre == L'0') && - ((cNext = NextChar(i)) == L'#' || cNext == L'0') - ) // #,# - { - nPos = nPos + sStrArray[i].size(); - if (!bThousand) // only once - { - bThousand = true; - cThousandFill = sStrArray[i+1].at(0); - } - // Eat it, will be reinserted at proper - // grouping positions further down. - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - i++; - } - else if (i > 0 && (cPre == L'#' || cPre == L'0') - && PreviousType(i) == NF_SYMBOLTYPE_DIGIT - && nThousand < FLAG_STANDARD_IN_FORMAT ) - { // #,,,, - if ( StringEqualsChar( sOldThousandSep, L' ' ) ) - { // strange, those French.. - bool bFirst = true; - String& rStr = sStrArray[i]; - // set a hard Non-Breaking Space or ConvertMode - const String& rSepF = pFormatter->GetNumThousandSep(); - while ( i < nAnzStrings - && sStrArray[i] == sOldThousandSep - && StringEqualsChar( sOldThousandSep, NextChar(i) ) ) - { // last was a space or another space - // is following => separator - nPos = nPos + sStrArray[i].size(); - if ( bFirst ) - { - bFirst = false; - rStr = rSepF; - nTypeArray[i] = NF_SYMBOLTYPE_THSEP; - } - else - { - rStr += rSepF; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - } - nThousand++; - i++; - } - if ( i < nAnzStrings-1 - && sStrArray[i] == sOldThousandSep ) - { // something following last space - // => space if currency contained, - // else separator - nPos = nPos + sStrArray[i].size(); - if ( (nPos <= nCurrPos && - nCurrPos < nPos + sStrArray[i+1].size()) - || nTypeArray[i+1] == NF_KEY_CCC - || (i < nAnzStrings-2 && - sStrArray[i+1].at(0) == L'[' && - sStrArray[i+2].at(0) == L'$') ) - { - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - } - else - { - if ( bFirst ) - { - bFirst = false; - rStr = rSepF; - nTypeArray[i] = NF_SYMBOLTYPE_THSEP; - } - else - { - rStr += rSepF; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - } - nThousand++; - } - i++; - } - } - else - { - do - { - nThousand++; - nTypeArray[i] = NF_SYMBOLTYPE_THSEP; - nPos = nPos + sStrArray[i].size(); - sStrArray[i] = pFormatter->GetNumThousandSep(); - i++; - } while (i < nAnzStrings && - sStrArray[i] == sOldThousandSep); - } - } - else // any grsep - { - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - String& rStr = sStrArray[i]; - nPos = nPos + rStr.size(); - i++; - while ( i < nAnzStrings && - sStrArray[i] == sOldThousandSep ) - { - rStr += sStrArray[i]; - nPos = nPos + sStrArray[i].size(); - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - i++; - } - } - } - else if ( StringEqualsChar( sOldDecSep, cSep ) ) - { - if (bBlank || bFrac) // . behind / or ' ' - return nPos; // error - else if (bExp) // behind E - { - nPos = nPos + sStrArray[i].size(); - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - i++; // eat it - } - else if (bDecSep) // any . - { - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - String& rStr = sStrArray[i]; - nPos = nPos + rStr.size(); - i++; - while ( i < nAnzStrings && - sStrArray[i] == sOldDecSep ) - { - rStr += sStrArray[i]; - nPos = nPos + sStrArray[i].size(); - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - i++; - } - } - else - { - nPos = nPos + sStrArray[i].size(); - nTypeArray[i] = NF_SYMBOLTYPE_DECSEP; - sStrArray[i] = pFormatter->GetNumDecimalSep(); - bDecSep = true; - nDecPos = i; - nCntPre = nCounter; - nCounter = 0; - - i++; - } - } // of else = DecSep - else // . without meaning - { - if (cSep == L' ' && - eScannedType == NUMBERFORMAT_FRACTION && - StringEqualsChar( sStrArray[i], L' ' ) ) - { - if (!bBlank && !bFrac) // no dups - { // or behind / - if (bDecSep && nCounter > 0)// dec. - return nPos; // error - bBlank = true; - nBlankPos = i; - nCntPre = nCounter; - nCounter = 0; - } - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - } - else - { - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - String& rStr = sStrArray[i]; - nPos = nPos + rStr.size(); - i++; - while (i < nAnzStrings && - StringEqualsChar( sStrArray[i], cSep ) ) - { - rStr += sStrArray[i]; - nPos = nPos + sStrArray[i].size(); - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - i++; - } - } - } - } - break; - case L'/': - { - if (eScannedType == NUMBERFORMAT_FRACTION) - { - if ( i == 0 || - (nTypeArray[i-1] != NF_SYMBOLTYPE_DIGIT && - nTypeArray[i-1] != NF_SYMBOLTYPE_EMPTY) ) - return nPos ? nPos : 1; // /? not allowed - else if (!bFrac || (bDecSep && nCounter > 0)) - { - bFrac = true; - nCntPost = nCounter; - nCounter = 0; - nTypeArray[i] = NF_SYMBOLTYPE_FRAC; - nPos = nPos + sStrArray[i].size(); - i++; - } - else // / double or , in count - return nPos; // error - } - else - { - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - i++; - } - } - break; - case L'[' : - { - if ( eScannedType == NUMBERFORMAT_CURRENCY && - i < nAnzStrings-1 && - nTypeArray[i+1] == NF_SYMBOLTYPE_STRING && - sStrArray[i+1].at(0) == L'$' ) - { // [$DM-xxx] - // ab SV_NUMBERFORMATTER_VERSION_NEW_CURR - nPos = nPos + sStrArray[i].size(); // [ - nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL; - nPos = nPos + sStrArray[++i].size(); // $ - sStrArray[i-1] += sStrArray[i]; // [$ - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - if ( ++i >= nAnzStrings ) - return nPos; // error - nPos = nPos + sStrArray[i].size(); // DM - String& rStr = sStrArray[i]; - String* pStr = &sStrArray[i]; - nTypeArray[i] = NF_SYMBOLTYPE_CURRENCY; // wandeln - bool bHadDash = false; - i++; - while ( i < nAnzStrings && - sStrArray[i].at(0) != L']' ) - { - nPos = nPos + sStrArray[i].size(); - if ( bHadDash ) - { - *pStr += sStrArray[i]; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - } - else - { - if ( sStrArray[i].at(0) == L'-' ) - { - bHadDash = true; - pStr = &sStrArray[i]; - nTypeArray[i] = NF_SYMBOLTYPE_CURREXT; - } - else - { - *pStr += sStrArray[i]; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - } - } - i++; - } - if ( rStr.size() && i < nAnzStrings && - sStrArray[i].at(0) == L']' ) - { - nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL; - nPos = nPos + sStrArray[i].size(); - i++; - } - else - return nPos; // error - } - else - { - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - i++; - } - } - break; - default: // Others Dels - { - if (eScannedType == NUMBERFORMAT_PERCENT && - cHere == L'%') - nTypeArray[i] = NF_SYMBOLTYPE_PERCENT; - else - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - i++; - } - break; - } // of switch (Del) - } // of else Del - else if ( nTypeArray[i] == NF_SYMBOLTYPE_COMMENT ) - { - String& rStr = sStrArray[i]; - nPos = nPos + rStr.size(); - SvNumberformat::EraseCommentBraces( rStr ); - rComment += rStr; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - i++; - } - else if (eScannedType == NUMBERFORMAT_FRACTION && nTypeArray[i] == NF_SYMBOLTYPE_DIGIT) // added part - { - String& rStr = sStrArray[i]; - String digit_str = rStr; - nPos = nPos + rStr.size(); - i++; - nCounter++; - while (i < nAnzStrings && (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT || - sStrArray[i].at(0) == L'0')) - { - nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; - digit_str += sStrArray[i]; - nPos = nPos + sStrArray[i].size(); - nCounter++; - i++; - } - if (digit_str.size() > 0) nExpVal = std::stoi(digit_str); - } - else - { - //DBG_ERRORFILE( "unknown NF_SYMBOLTYPE_..." ); - nPos = nPos + sStrArray[i].size(); - i++; - } - } // of while - if (eScannedType == NUMBERFORMAT_FRACTION) - { - if (bFrac) - nCntExp = nCounter; - else if (bBlank) - nCntPost = nCounter; - else - nCntPre = nCounter; - } - else - { - if (bExp) - nCntExp = nCounter; - else if (bDecSep) - nCntPost = nCounter; - else - nCntPre = nCounter; - } - if (bThousand) // Expansion of grouping separators - { - sal_uInt16 nMaxPos; - if (bFrac) - { - if (bBlank) - nMaxPos = nBlankPos; - else - nMaxPos = 0; // no grouping - } - else if (bDecSep) // decimal separator present - nMaxPos = nDecPos; - else if (bExp) // 'E' exponent present - nMaxPos = nExpPos; - else // up to end - nMaxPos = i; - // Insert separators at proper positions. - uint16_t nCount = 0; - DigitGroupingIterator aGrouping(pFormatter->getDigitGrouping()); - size_t nFirstDigitSymbol = nMaxPos; - size_t nFirstGroupingSymbol = nMaxPos; - i = nMaxPos; - while (i-- > 0) - { - if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT) - { - nFirstDigitSymbol = i; - nCount = nCount + sStrArray[i].size(); // MSC converts += to int and then warns, so ... - // Insert separator only if not leftmost symbol. - if (i > 0 && nCount >= aGrouping.getPos()) - { - if (!InsertSymbol( i, NF_SYMBOLTYPE_THSEP, pFormatter->GetNumThousandSep())) - // nPos isn't correct here, but signals error - return nPos; - // i may have been decremented by 1 - nFirstDigitSymbol = i + 1; - nFirstGroupingSymbol = i; - aGrouping.advance(); - } - } - } - // Generated something like "string",000; remove separator again. - if (nFirstGroupingSymbol < nFirstDigitSymbol) - { - nTypeArray[nFirstGroupingSymbol] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - } - } - // Combine digits into groups to save memory (Info will be copied - // later, taking only non-empty symbols). - for (i = 0; i < nAnzStrings; ++i) - { - if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT) - { - String& rStr = sStrArray[i]; - while (++i < nAnzStrings && - nTypeArray[i] == NF_SYMBOLTYPE_DIGIT) - { - rStr += sStrArray[i]; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - } - } - } - } - break; // of NUMBERFORMAT_NUMBER - case NUMBERFORMAT_DATE: - { - while (i < nAnzStrings) - { - switch (nTypeArray[i]) - { - case NF_SYMBOLTYPE_BLANK: - case NF_SYMBOLTYPE_STAR: - case NF_SYMBOLTYPE_STRING: - nPos = nPos + sStrArray[i].size(); - i++; - break; - case NF_SYMBOLTYPE_COMMENT: - { - String& rStr = sStrArray[i]; - nPos = nPos + rStr.size(); - SvNumberformat::EraseCommentBraces( rStr ); - rComment += rStr; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - i++; - } - break; - case NF_SYMBOLTYPE_DEL: - { - int nCalRet; - if (sStrArray[i] == sOldDateSep) - { - nTypeArray[i] = NF_SYMBOLTYPE_DATESEP; - nPos = nPos + sStrArray[i].size(); - if (bConvertMode) - sStrArray[i] = pFormatter->GetDateSep(); - i++; - } - else if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 ) - { - if ( nCalRet < 0 ) - return nPos; // error - } - else - { - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - i++; - } - } - break; - case NF_KEY_THAI_T : - bThaiT = true; - // fall thru - case NF_KEY_M: // M - case NF_KEY_MM: // MM - case NF_KEY_MMM: // MMM - case NF_KEY_MMMM: // MMMM - case NF_KEY_MMMMM: // MMMMM - case NF_KEY_Q: // Q - case NF_KEY_QQ: // QQ - case NF_KEY_D: // D - case NF_KEY_DD: // DD - case NF_KEY_DDD: // DDD - case NF_KEY_DDDD: // DDDD - case NF_KEY_YY: // YY - case NF_KEY_YYYY: // YYYY - case NF_KEY_NN: // NN - case NF_KEY_NNN: // NNN - case NF_KEY_NNNN: // NNNN - case NF_KEY_WW : // WW - case NF_KEY_AAA : // AAA - case NF_KEY_AAAA : // AAAA - case NF_KEY_EC : // E - case NF_KEY_EEC : // EE - case NF_KEY_G : // G - case NF_KEY_GG : // GG - case NF_KEY_GGG : // GGG - case NF_KEY_R : // R - case NF_KEY_RR : // RR - sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT - nPos = nPos + sStrArray[i].size(); - i++; - break; - default: // andere Keywords - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - i++; - break; - } - } // of while - } - break; // of NUMBERFORMAT_DATE - case NUMBERFORMAT_TIME: - { - while (i < nAnzStrings) - { - switch (nTypeArray[i]) - { - case NF_SYMBOLTYPE_BLANK: - case NF_SYMBOLTYPE_STAR: - { - nPos = nPos + sStrArray[i].size(); - i++; - } - break; - case NF_SYMBOLTYPE_DEL: - { - switch( sStrArray[i].at(0) ) - { - case L'0': - { - if ( Is100SecZero( i, bDecSep ) ) - { - bDecSep = true; - nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; - String& rStr = sStrArray[i]; - i++; - nPos = nPos + sStrArray[i].size(); - nCounter++; - while (i < nAnzStrings && - sStrArray[i].at(0) == L'0') - { - rStr += sStrArray[i]; - nPos = nPos + sStrArray[i].size(); - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - nCounter++; - i++; - } - } - else - return nPos; - } - break; - case L'#': - case L'?': - return nPos; - case L'[': - { - if (bThousand) // double - return nPos; - bThousand = true; // at time free - sal_Unicode cChar = std::towupper(NextChar(i)); - if ( cChar == cOldKeyH ) - nThousand = 1; // H - else if ( cChar == cOldKeyMI ) - nThousand = 2; // M - else if ( cChar == cOldKeyS ) - nThousand = 3; // S - else - return nPos; - nPos = nPos + sStrArray[i].size(); - i++; - } - break; - case L']': - { - if (!bThousand) // no [ before - return nPos; - nPos = nPos + sStrArray[i].size(); - i++; - } - break; - default: - { - nPos = nPos + sStrArray[i].size(); - if ( sStrArray[i] == sOldTimeSep ) - { - nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP; - if ( bConvertMode ) - sStrArray[i] = pFormatter->getTimeSep(); - } - else if ( sStrArray[i] == sOldTime100SecSep ) - { - bDecSep = true; - nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP; - if ( bConvertMode ) - sStrArray[i] = pFormatter->getTime100SecSep(); - } - else - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - i++; - } - break; - } - } - break; - case NF_SYMBOLTYPE_STRING: - { - nPos = nPos + sStrArray[i].size(); - i++; - } - break; - case NF_SYMBOLTYPE_COMMENT: - { - String& rStr = sStrArray[i]; - nPos = nPos + rStr.size(); - SvNumberformat::EraseCommentBraces( rStr ); - rComment += rStr; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - i++; - } - break; - case NF_KEY_AMPM: // AM/PM - case NF_KEY_AP: // A/P - { - bExp = true; // abused for A/P - sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT - nPos = nPos + sStrArray[i].size(); - i++; - } - break; - case NF_KEY_THAI_T : - bThaiT = true; - // fall thru - case NF_KEY_MI: // M - case NF_KEY_MMI: // MM - case NF_KEY_H: // H - case NF_KEY_HH: // HH - case NF_KEY_S: // S - case NF_KEY_SS: // SS - { - sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT - nPos = nPos + sStrArray[i].size(); - i++; - } - break; - default: // andere Keywords - { - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - i++; - } - break; - } - } // of while - nCntPost = nCounter; // counter of zeros - if (bExp) - nCntExp = 1; // notes AM/PM - } - break; // of NUMBERFORMAT_TIME - case NUMBERFORMAT_DATETIME: - { - bool bTimePart = false; - while (i < nAnzStrings) - { - switch (nTypeArray[i]) - { - case NF_SYMBOLTYPE_BLANK: - case NF_SYMBOLTYPE_STAR: - case NF_SYMBOLTYPE_STRING: - nPos = nPos + sStrArray[i].size(); - i++; - break; - case NF_SYMBOLTYPE_COMMENT: - { - String& rStr = sStrArray[i]; - nPos = nPos + rStr.size(); - SvNumberformat::EraseCommentBraces( rStr ); - rComment += rStr; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - i++; - } - break; - case NF_SYMBOLTYPE_DEL: - { - int nCalRet; - if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 ) - { - if ( nCalRet < 0 ) - return nPos; // error - } - else - { - switch( sStrArray[i].at(0) ) - { - case L'0': - { - if ( bTimePart && Is100SecZero( i, bDecSep ) ) - { - bDecSep = true; - nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; - String& rStr = sStrArray[i]; - i++; - nPos = nPos + sStrArray[i].size(); - nCounter++; - while (i < nAnzStrings && - sStrArray[i].at(0) == L'0') - { - rStr += sStrArray[i]; - nPos = nPos + sStrArray[i].size(); - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - nCounter++; - i++; - } - } - else - return nPos; - } - break; - case L'#': - case L'?': - return nPos; - default: - { - nPos = nPos + sStrArray[i].size(); - if (bTimePart) - { - if ( sStrArray[i] == sOldTimeSep ) - { - nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP; - if ( bConvertMode ) - sStrArray[i] = pFormatter->getTimeSep(); - } - else if ( sStrArray[i] == sOldTime100SecSep ) - { - bDecSep = true; - nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP; - if ( bConvertMode ) - sStrArray[i] = pFormatter->getTime100SecSep(); - } - else - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - } - else - { - if ( sStrArray[i] == sOldDateSep ) - { - nTypeArray[i] = NF_SYMBOLTYPE_DATESEP; - if (bConvertMode) - sStrArray[i] = pFormatter->GetDateSep(); - } - else - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - } - i++; - } - } - } - } - break; - case NF_KEY_AMPM: // AM/PM - case NF_KEY_AP: // A/P - { - bTimePart = true; - bExp = true; // abused for A/P - sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT - nPos = nPos + sStrArray[i].size(); - i++; - } - break; - case NF_KEY_MI: // M - case NF_KEY_MMI: // MM - case NF_KEY_H: // H - case NF_KEY_HH: // HH - case NF_KEY_S: // S - case NF_KEY_SS: // SS - bTimePart = true; - sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT - nPos = nPos + sStrArray[i].size(); - i++; - break; - case NF_KEY_M: // M - case NF_KEY_MM: // MM - case NF_KEY_MMM: // MMM - case NF_KEY_MMMM: // MMMM - case NF_KEY_MMMMM: // MMMMM - case NF_KEY_Q: // Q - case NF_KEY_QQ: // QQ - case NF_KEY_D: // D - case NF_KEY_DD: // DD - case NF_KEY_DDD: // DDD - case NF_KEY_DDDD: // DDDD - case NF_KEY_YY: // YY - case NF_KEY_YYYY: // YYYY - case NF_KEY_NN: // NN - case NF_KEY_NNN: // NNN - case NF_KEY_NNNN: // NNNN - case NF_KEY_WW : // WW - case NF_KEY_AAA : // AAA - case NF_KEY_AAAA : // AAAA - case NF_KEY_EC : // E - case NF_KEY_EEC : // EE - case NF_KEY_G : // G - case NF_KEY_GG : // GG - case NF_KEY_GGG : // GGG - case NF_KEY_R : // R - case NF_KEY_RR : // RR - bTimePart = false; - sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT - nPos = nPos + sStrArray[i].size(); - i++; - break; - case NF_KEY_THAI_T : - bThaiT = true; - sStrArray[i] = sKeyword[nTypeArray[i]]; - nPos = nPos + sStrArray[i].size(); - i++; - break; - default: // andere Keywords - nTypeArray[i] = NF_SYMBOLTYPE_STRING; - nPos = nPos + sStrArray[i].size(); - i++; - break; - } - } // of while - nCntPost = nCounter; // decimals (100th seconds) - if (bExp) - nCntExp = 1; // notes AM/PM - } - break; // of NUMBERFORMAT_DATETIME - default: - break; - } - if (eScannedType == NUMBERFORMAT_SCIENTIFIC && - (nCntPre + nCntPost == 0 || nCntExp == 0)) - return nPos; - else if (eScannedType == NUMBERFORMAT_FRACTION && (nCntExp > 8 || nCntExp == 0)) - return nPos; - - if (bThaiT && !GetNatNumModifier()) - SetNatNumModifier(1); - - if ( bConvertMode ) - { // strings containing keywords of the target locale must be quoted, so - // the user sees the difference and is able to edit the format string - for ( i=0; i < nAnzStrings; i++ ) - { - if ( nTypeArray[i] == NF_SYMBOLTYPE_STRING && - sStrArray[i].at(0) != L'\"' ) - { - if ( bConvertSystemToSystem && eScannedType == NUMBERFORMAT_CURRENCY ) - { // don't stringize automatic currency, will be converted - if ( sStrArray[i] == sOldCurSymbol ) - continue; // for - // DM might be splitted into D and M - if ( sStrArray[i].size() < sOldCurSymbol.size() && - std::towupper(sStrArray[i].at(0)) == sOldCurString.at(0) ) - { - String aTmp( sStrArray[i] ); - sal_uInt16 j = i + 1; - while ( aTmp.size() < sOldCurSymbol.size() && - j < nAnzStrings && - nTypeArray[j] == NF_SYMBOLTYPE_STRING ) - { - aTmp += sStrArray[j++]; - } - String str = aTmp; ConvertToUpper(str); - if (str == sOldCurString ) - { - sStrArray[i++] = aTmp; - for ( ; iGetNumThousandSep(), - c) || StringEqualsChar( - pFormatter->GetNumDecimalSep(), - c) || (c == L' ' && - StringEqualsChar( - pFormatter->GetNumThousandSep(), - cNonBreakingSpace)))) - rString += sStrArray[i]; - else if ((eScannedType & NUMBERFORMAT_DATE) && - StringEqualsChar( - pFormatter->GetDateSep(), c)) - rString += sStrArray[i]; - else if ((eScannedType & NUMBERFORMAT_TIME) && - (StringEqualsChar(pFormatter->getTimeSep(), - c) || - StringEqualsChar( - pFormatter->getTime100SecSep(), c))) - rString += sStrArray[i]; - else if (eScannedType & NUMBERFORMAT_FRACTION) - rString += sStrArray[i]; - else - rString += c; - break; - default: - rString += sStrArray[i]; - } - } - else - rString += sStrArray[i]; - if ( RemoveQuotes( sStrArray[i] ) > 0 ) - { // update currency up to quoted string - if ( eScannedType == NUMBERFORMAT_CURRENCY ) - { // dM -> DM or DM -> $ in old automatic - // currency formats, oh my ..., why did we ever - // introduce them? - String aTmp = sStrArray[iPos].substr(nArrPos); - ConvertToUpper(aTmp); - uint16_t nCPos = aTmp.find( sOldCurString ); - if ( nCPos != STRING_NOTFOUND ) - { - const String& rCur = - bConvertMode && bConvertSystemToSystem ? - GetCurSymbol() : sOldCurSymbol; - sStrArray[iPos].replace( nArrPos+nCPos, sOldCurString.size(), rCur ); - rString.replace( nStringPos+nCPos, sOldCurString.size(), rCur ); - } - nStringPos = rString.size(); - if ( iPos == i ) - nArrPos = sStrArray[iPos].size(); - else - nArrPos = sStrArray[iPos].size() + sStrArray[i].size(); - } - } - if ( iPos != i ) - { - sStrArray[iPos] += sStrArray[i]; - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - } - i++; - } while ( i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_STRING ); - if ( i < nAnzStrings ) - i--; // enter switch on next symbol again - if ( eScannedType == NUMBERFORMAT_CURRENCY && nStringPos < rString.size() ) - { // same as above, since last RemoveQuotes - String aTmp = sStrArray[iPos].substr(nArrPos); - ConvertToUpper(aTmp); - uint16_t nCPos = aTmp.find( sOldCurString ); - if ( nCPos != STRING_NOTFOUND ) - { - const String& rCur = - bConvertMode && bConvertSystemToSystem ? - GetCurSymbol() : sOldCurSymbol; - sStrArray[iPos].replace( nArrPos+nCPos, sOldCurString.size(), rCur ); - rString.replace( nStringPos+nCPos, sOldCurString.size(), rCur ); - } - } - } - break; - case NF_SYMBOLTYPE_CURRENCY : - { - rString += sStrArray[i]; - RemoveQuotes( sStrArray[i] ); - } - break; - case NF_KEY_THAI_T: - if (bThaiT && GetNatNumModifier() == 1) - { // Remove T from format code, will be replaced with a [NatNum1] prefix. - nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; - nAnzResStrings--; - } - else - rString += sStrArray[i]; - break; - case NF_SYMBOLTYPE_EMPTY : - // nothing - break; - default: - rString += sStrArray[i]; - } - i++; - } - return 0; -} - - -uint16_t ImpSvNumberformatScan::RemoveQuotes( String& rStr ) -{ - if ( rStr.size() > 1 ) - { - sal_Unicode c = rStr.at(0); - uint16_t n; - if ( c == L'"' && rStr.at( (n = uint16_t(rStr.size()-1)) ) == L'"' ) - { - rStr.erase(n,1); - rStr.erase(0,1); - return 2; - } - else if ( c == L'\\' ) - { - rStr.erase(0,1); - return 1; - } - } - return 0; -} - - -uint16_t ImpSvNumberformatScan::ScanFormat( String& rString, String& rComment ) -{ - uint16_t res = Symbol_Division(rString); //lexical analysis - if (!res) - res = ScanType(rString); // Format type detection - if (!res) - res = FinalScan( rString, rComment ); // Type-dependent End Analysis - return res; // res = Control position - // res = 0 => Format ok -} - -void ImpSvNumberformatScan::CopyInfo(ImpSvNumberformatInfo* pInfo, sal_uInt16 nAnz) -{ - size_t i,j; - j = 0; - i = 0; - while (i < nAnz && j < NF_MAX_FORMAT_SYMBOLS) - { - if (nTypeArray[j] != NF_SYMBOLTYPE_EMPTY) - { - pInfo->sStrArray[i] = sStrArray[j]; - pInfo->nTypeArray[i] = nTypeArray[j]; - i++; - } - j++; - } - pInfo->eScannedType = eScannedType; - pInfo->bThousand = bThousand; - pInfo->nThousand = nThousand; - pInfo->nCntPre = nCntPre; - pInfo->nCntPost = nCntPost; - pInfo->nCntExp = nCntExp; - pInfo->nExpVal = nExpVal; -} - - -// ----------------------------------------------- zformat.cxx ---------------------------------------------------------- - -const sal_uInt16 UPPER_PRECISION = 300; // entirely arbitrary... -const double EXP_LOWER_BOUND = 1.0E-4; // prefer scientific notation below this value. - -const double _D_MAX_U_LONG_ = (double) 0xffffffff; // 4294967295.0 -const double _D_MAX_LONG_ = (double) 0x7fffffff; // 2147483647.0 -const sal_uInt16 _MAX_FRACTION_PREC = 3; -const double D_EPS = 1.0E-2; - -const double _D_MAX_D_BY_100 = 1.7E306; -const double _D_MIN_M_BY_1000 = 2.3E-305; - -const sal_uInt16 UNLIMITED_PRECISION = (sal_uInt16)0xffff; -const sal_uInt16 INPUTSTRING_PRECISION = (sal_uInt16)0xfffe; - -static sal_uInt8 cCharWidths[ 128-32 ] = { - 1,1,1,2,2,3,2,1,1,1,1,2,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,2, - 3,2,2,2,2,2,2,3,2,1,2,2,2,3,3,3, - 2,3,2,2,2,2,2,3,2,2,2,1,1,1,2,2, - 1,2,2,2,2,2,1,2,2,1,1,2,1,3,2,2, - 2,2,1,2,1,2,2,2,2,2,2,1,1,1,2,1 -}; - -static int const n10Count = 16; -static double const n10s[2][n10Count] = { - { 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, - 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16 }, - { 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, - 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16 } -}; -double const nKorrVal[] = { - 0, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8, - 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14, 9e-15 -}; - -// return pow(10.0,nExp) optimized for exponents in the interval [-16,16] -static double getN10Exp(int nExp) -{ - if (nExp < 0) - { - if (-nExp <= n10Count) - return n10s[1][-nExp - 1]; - else - return pow(10.0, static_cast(nExp)); - } - else if (nExp > 0) - { - if (nExp <= n10Count) - return n10s[0][nExp - 1]; - else - return pow(10.0, static_cast(nExp)); - } - else // ( nExp == 0 ) - return 1.0; -} - -// Solaris C++ 5.2 compiler has problems when "StringT ** pResult" is -// "typename T::String ** pResult" instead: -void doubleToString(String& pResult, - sal_Int32 * pResultCapacity, sal_Int32 nResultOffset, - double fValue, rtl_math_StringFormat eFormat, - sal_Int32 nDecPlaces, sal_Unicode cDecSeparator, - sal_Int32 const * pGroups, - sal_Unicode cGroupSeparator, - bool bEraseTrailingDecZeros) -{ - static double const nRoundVal[] = { - 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6, - 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14 - }; - - // sign adjustment, instead of testing for fValue<0.0 this will also fetch - // -0.0 - bool bSign = fabs(fValue) < 0.0; - if (bSign) - fValue = -fValue; - - if (std::isnan(fValue)) - { - pResult = L"NaN"; - return; - } - - if (std::isinf(fValue)) - { - if (bSign) - pResult = L"-INF"; - else - pResult = L"INF"; - return; - } - - // find the exponent - int nExp = 0; - if (fValue > 0.0) - { - nExp = static_cast(floor(log10(fValue))); - fValue /= getN10Exp(nExp); - } - - switch (eFormat) - { - case rtl_math_StringFormat_Automatic: - { // E or F depending on exponent magnitude - int nPrec; - if (nExp <= -15 || nExp >= 15) // #58531# was <-16, >16 - { - nPrec = 14; - eFormat = rtl_math_StringFormat_E; - } - else - { - if (nExp < 14) - { - nPrec = 15 - nExp - 1; - eFormat = rtl_math_StringFormat_F; - } - else - { - nPrec = 15; - eFormat = rtl_math_StringFormat_F; - } - } - if (nDecPlaces == rtl_math_DecimalPlaces_Max) - nDecPlaces = nPrec; - } - break; - case rtl_math_StringFormat_G: - { // G-Point, similar to sprintf %G - if (nDecPlaces == rtl_math_DecimalPlaces_DefaultSignificance) - nDecPlaces = 6; - if (nExp < -4 || nExp >= nDecPlaces) - { - nDecPlaces = std::max< sal_Int32 >(1, nDecPlaces - 1); - eFormat = rtl_math_StringFormat_E; - } - else - { - nDecPlaces = std::max< sal_Int32 >(0, nDecPlaces - nExp - 1); - eFormat = rtl_math_StringFormat_F; - } - } - break; - default: - break; - } - - sal_Int32 nDigits = nDecPlaces + 1; - - if (eFormat == rtl_math_StringFormat_F) - nDigits += nExp; - - // Round the number - if (nDigits >= 0) - { - if ((fValue += nRoundVal[nDigits > 15 ? 15 : nDigits]) >= 10) - { - fValue = 1.0; - nExp++; - if (eFormat == rtl_math_StringFormat_F) - nDigits++; - } - } - - static sal_Int32 const nBufMax = 256; - sal_Unicode aBuf[nBufMax]; - sal_Unicode * pBuf = aBuf; - sal_Unicode * p = pBuf; - if (bSign) - *p++ = static_cast(L'-'); - - bool bHasDec = false; - - int nDecPos; - // Check for F format and number < 1 - if (eFormat == rtl_math_StringFormat_F) - { - if (nExp < 0) - { - *p++ = static_cast(L'0'); - if (nDecPlaces > 0) - { - *p++ = cDecSeparator; - bHasDec = true; - } - sal_Int32 i = (nDigits <= 0 ? nDecPlaces : -nExp - 1); - while ((i--) > 0) - *p++ = static_cast(L'0'); - nDecPos = 0; - } - else - nDecPos = nExp + 1; - } - else - nDecPos = 1; - - int nGrouping = 0, nGroupSelector = 0, nGroupExceed = 0; - if (nDecPos > 1 && pGroups && pGroups[0] && cGroupSeparator) - { - while (nGrouping + pGroups[nGroupSelector] < nDecPos) - { - nGrouping += pGroups[nGroupSelector]; - if (pGroups[nGroupSelector + 1]) - { - if (nGrouping + pGroups[nGroupSelector + 1] >= nDecPos) - break; // while - ++nGroupSelector; - } - else if (!nGroupExceed) - nGroupExceed = nGrouping; - } - } - - // print the number - if (nDigits > 0) - { - for (int i = 0; ; i++) - { - if (i < 15) - { - int nDigit; - if (nDigits - 1 == 0 && i > 0 && i < 14) - nDigit = static_cast(floor(fValue - + nKorrVal[15 - i])); - else - nDigit = static_cast(fValue + 1E-15); - if (nDigit >= 10) - { // after-treatment of up-rounding to the next decade - sal_Int32 sLen = static_cast(p - pBuf) - 1; - if (sLen == -1) - { - p = pBuf; - if (eFormat == rtl_math_StringFormat_F) - { - *p++ = static_cast(L'1'); - *p++ = static_cast(L'0'); - } - else - { - *p++ = static_cast(L'1'); - *p++ = cDecSeparator; - *p++ = static_cast(L'0'); - nExp++; - bHasDec = true; - } - } - else - { - for (sal_Int32 j = sLen; j >= 0; j--) - { - sal_Unicode cS = pBuf[j]; - if (cS != cDecSeparator) - { - if (cS != static_cast(L'9')) - { - pBuf[j] = ++cS; - j = -1; // break loop - } - else - { - pBuf[j] - = static_cast('0'); - if (j == 0) - { - if (eFormat == rtl_math_StringFormat_F) - { // insert '1' - sal_Unicode * px = p++; - while (pBuf < px) - { - *px = *(px - 1); - px--; - } - pBuf[0] = static_cast< - sal_Unicode>(L'1'); - } - else - { - pBuf[j] = static_cast< - sal_Unicode>(L'1'); - nExp++; - } - } - } - } - } - *p++ = static_cast(L'0'); - } - fValue = 0.0; - } - else - { - *p++ = static_cast( - nDigit + static_cast(L'0')); - fValue = (fValue - nDigit) * 10.0; - } - } - else - *p++ = static_cast(L'0'); - if (!--nDigits) - break; // for - if (nDecPos) - { - if (!--nDecPos) - { - *p++ = cDecSeparator; - bHasDec = true; - } - else if (nDecPos == nGrouping) - { - *p++ = cGroupSeparator; - nGrouping -= pGroups[nGroupSelector]; - if (nGroupSelector && nGrouping < nGroupExceed) - --nGroupSelector; - } - } - } - } - - if (!bHasDec && eFormat == rtl_math_StringFormat_F) - { // nDecPlaces < 0 did round the value - while (--nDecPos > 0) - { // fill before decimal point - if (nDecPos == nGrouping) - { - *p++ = cGroupSeparator; - nGrouping -= pGroups[nGroupSelector]; - if (nGroupSelector && nGrouping < nGroupExceed) - --nGroupSelector; - } - *p++ = static_cast(L'0'); - } - } - - if (bEraseTrailingDecZeros && bHasDec && p > pBuf) - { - while (*(p - 1) == static_cast(L'0')) - p--; - if (*(p - 1) == cDecSeparator) - p--; - } - - // Print the exponent ('E', followed by '+' or '-', followed by exactly - // three digits). The code in rtl_[u]str_valueOf{Float|Double} relies on - // this format. - if (eFormat == rtl_math_StringFormat_E) - { - if (p == pBuf) - *p++ = static_cast(L'1'); - // maybe no nDigits if nDecPlaces < 0 - *p++ = static_cast(L'E'); - if (nExp < 0) - { - nExp = -nExp; - *p++ = static_cast(L'-'); - } - else - *p++ = static_cast(L'+'); - // if (nExp >= 100 ) - *p++ = static_cast( - nExp / 100 + static_cast(L'0')); - nExp %= 100; - *p++ = static_cast( - nExp / 10 + static_cast(L'0')); - *p++ = static_cast( - nExp % 10 + static_cast(L'0')); - } - - if (pResultCapacity == NULL) { - pBuf[p - pBuf] = L'\0'; - pResult = pBuf; - } - else if (*pResultCapacity >= 0) { - int32_t cnt = p - pBuf; - if (cnt > *pResultCapacity) cnt = *pResultCapacity; - pBuf[cnt] = L'\0'; - pResult = pBuf; - } - else { - pResult = L""; - } -} - -void rtl_math_doubleToUString(String& pResult, - sal_Int32 * pResultCapacity, - sal_Int32 nResultOffset, double fValue, - rtl_math_StringFormat eFormat, - sal_Int32 nDecPlaces, - sal_Unicode cDecSeparator, - sal_Int32 const * pGroups, - sal_Unicode cGroupSeparator, - bool bEraseTrailingDecZeros) -{ - doubleToString( - pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces, - cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros); -} - -/** A wrapper around rtl_math_doubleToUString, with no grouping. - */ -inline String doubleToUString(double fValue, - rtl_math_StringFormat eFormat, - sal_Int32 nDecPlaces, - sal_Unicode cDecSeparator, - bool bEraseTrailingDecZeros = false) -{ - String aResult; - rtl_math_doubleToUString(aResult, 0, 0, fValue, eFormat, nDecPlaces, - cDecSeparator, 0, 0, bEraseTrailingDecZeros); - return aResult; -} - -double rtl_math_round(double fValue, int nDecPlaces, - enum rtl_math_RoundingMode eMode) -{ - //OSL_ASSERT(nDecPlaces >= -20 && nDecPlaces <= 20); - - if (fValue == 0.0) - return fValue; - - // sign adjustment - bool bSign = fabs(fValue) < 0.0; - if (bSign) - fValue = -fValue; - - double fFac = 0; - if (nDecPlaces != 0) - { - // max 20 decimals, we don't have unlimited precision - // #38810# and no overflow on fValue*=fFac - if (nDecPlaces < -20 || 20 < nDecPlaces || fValue > (DBL_MAX / 1e20)) - return bSign ? -fValue : fValue; - - fFac = getN10Exp(nDecPlaces); - fValue *= fFac; - } - //else //! uninitialized fFac, not needed - - switch (eMode) - { - case rtl_math_RoundingMode_Corrected: - { - int nExp; // exponent for correction - if (fValue > 0.0) - nExp = static_cast(floor(log10(fValue))); - else - nExp = 0; - int nIndex = 15 - nExp; - if (nIndex > 15) - nIndex = 15; - else if (nIndex <= 1) - nIndex = 0; - fValue = floor(fValue + 0.5 + nKorrVal[nIndex]); - } - break; - case rtl_math_RoundingMode_Down: - fValue = floor(fValue); - break; - case rtl_math_RoundingMode_Up: - fValue = ceil(fValue); - break; - case rtl_math_RoundingMode_Floor: - fValue = bSign ? ceil(fValue) - : floor(fValue); - break; - case rtl_math_RoundingMode_Ceiling: - fValue = bSign ? floor(fValue) - : ceil(fValue); - break; - case rtl_math_RoundingMode_HalfDown: - { - double f = floor(fValue); - fValue = ((fValue - f) <= 0.5) ? f : ceil(fValue); - } - break; - case rtl_math_RoundingMode_HalfUp: - { - double f = floor(fValue); - fValue = ((fValue - f) < 0.5) ? f : ceil(fValue); - } - break; - case rtl_math_RoundingMode_HalfEven: -#if defined FLT_ROUNDS - /* - Use fast version. FLT_ROUNDS may be defined to a function by some compilers! - - DBL_EPSILON is the smallest fractional number which can be represented, - its reciprocal is therefore the smallest number that cannot have a - fractional part. Once you add this reciprocal to `x', its fractional part - is stripped off. Simply subtracting the reciprocal back out returns `x' - without its fractional component. - Simple, clever, and elegant - thanks to Ross Cottrell, the original author, - who placed it into public domain. - - volatile: prevent compiler from being too smart - */ - if (FLT_ROUNDS == 1) - { - volatile double x = fValue + 1.0 / DBL_EPSILON; - fValue = x - 1.0 / DBL_EPSILON; - } - else -#endif // FLT_ROUNDS - { - double f = floor(fValue); - if ((fValue - f) != 0.5) - fValue = floor(fValue + 0.5); - else - { - double g = f / 2.0; - fValue = (g == floor(g)) ? f : (f + 1.0); - } - } - break; - default: - //OSL_ASSERT(false); - break; - } - - if (nDecPlaces != 0) - fValue /= fFac; - - return bSign ? -fValue : fValue; -} - -inline double math_round( - double fValue, int nDecPlaces = 0, - rtl_math_RoundingMode eMode = rtl_math_RoundingMode_Corrected) -{ - return rtl_math_round(fValue, nDecPlaces, eMode); -} - -// static -uint16_t SvNumberformat::InsertBlanks( String& r, uint16_t nPos, sal_Unicode c ) -{ - if( c >= 32 ) - { - sal_uInt16 n = 2; // Default for characters > 128 (HACK!) - if (c <= 127) - n = 1;// cCharWidths[c - 32]; - while( n-- ) - r.insert( nPos++, L" " ); - } - return nPos; -} - -static long GetPrecExp( double fAbsVal ) -{ - if ( fAbsVal < 1e-7 || fAbsVal > 1e7 ) - { // the gap, whether it's faster or not, is between 1e6 and 1e7 - return (long) floor( log10( fAbsVal ) ) + 1; - } - else - { - long nPrecExp = 1; - while( fAbsVal < 1 ) - { - fAbsVal *= 10; - nPrecExp--; - } - while( fAbsVal >= 10 ) - { - fAbsVal /= 10; - nPrecExp++; - } - return nPrecExp; - } -} - -const sal_uInt16 nNewCurrencyVersionId = 0x434E; // "NC" -const sal_Unicode cNewCurrencyMagic = 0x01; // Magic for format code in comment -const sal_uInt16 nNewStandardFlagVersionId = 0x4653; // "SF" - -void ImpSvNumberformatInfo::Copy( const ImpSvNumberformatInfo& rNumFor, sal_uInt16 nAnz ) -{ - for (sal_uInt16 i = 0; i < nAnz; i++) - { - sStrArray[i] = rNumFor.sStrArray[i]; - nTypeArray[i] = rNumFor.nTypeArray[i]; - } - eScannedType = rNumFor.eScannedType; - bThousand = rNumFor.bThousand; - nThousand = rNumFor.nThousand; - nCntPre = rNumFor.nCntPre; - nCntPost = rNumFor.nCntPost; - nCntExp = rNumFor.nCntExp; - nExpVal = rNumFor.nExpVal; -} - -ImpSvNumFor::ImpSvNumFor() -{ - nAnzStrings = 0; - aI.nTypeArray = NULL; - aI.sStrArray = NULL; - aI.eScannedType = NUMBERFORMAT_UNDEFINED; - aI.bThousand = false; - aI.nThousand = 0; - aI.nCntPre = 0; - aI.nCntPost = 0; - aI.nCntExp = 0; - pColor = NULL; -} - -ImpSvNumFor::~ImpSvNumFor() -{ - for (sal_uInt16 i = 0; i < nAnzStrings; i++) - aI.sStrArray[i].erase(); - delete [] aI.sStrArray; - delete [] aI.nTypeArray; -} - -void ImpSvNumFor::Enlarge(sal_uInt16 nAnz) -{ - if ( nAnzStrings != nAnz ) - { - if ( aI.nTypeArray ) - delete [] aI.nTypeArray; - if ( aI.sStrArray ) - delete [] aI.sStrArray; - nAnzStrings = nAnz; - if ( nAnz ) - { - aI.nTypeArray = new short[nAnz]; - aI.sStrArray = new String[nAnz]; - } - else - { - aI.nTypeArray = NULL; - aI.sStrArray = NULL; - } - } -} - -void ImpSvNumFor::Copy( const ImpSvNumFor& rNumFor, ImpSvNumberformatScan* pSc ) -{ - Enlarge( rNumFor.nAnzStrings ); - aI.Copy( rNumFor.aI, nAnzStrings ); - sColorName = rNumFor.sColorName; - aNatNum = rNumFor.aNatNum; -} - -bool ImpSvNumFor::HasNewCurrency() const -{ - for ( sal_uInt16 j=0; j 0 ) - return true; // conditions - switch ( nSymbolType ) - { - case BRACKET_SYMBOLTYPE_COLOR : - case BRACKET_SYMBOLTYPE_DBNUM1 : - case BRACKET_SYMBOLTYPE_DBNUM2 : - case BRACKET_SYMBOLTYPE_DBNUM3 : - case BRACKET_SYMBOLTYPE_DBNUM4 : - case BRACKET_SYMBOLTYPE_DBNUM5 : - case BRACKET_SYMBOLTYPE_DBNUM6 : - case BRACKET_SYMBOLTYPE_DBNUM7 : - case BRACKET_SYMBOLTYPE_DBNUM8 : - case BRACKET_SYMBOLTYPE_DBNUM9 : - case BRACKET_SYMBOLTYPE_LOCALE : - case BRACKET_SYMBOLTYPE_NATNUM0 : - case BRACKET_SYMBOLTYPE_NATNUM1 : - case BRACKET_SYMBOLTYPE_NATNUM2 : - case BRACKET_SYMBOLTYPE_NATNUM3 : - case BRACKET_SYMBOLTYPE_NATNUM4 : - case BRACKET_SYMBOLTYPE_NATNUM5 : - case BRACKET_SYMBOLTYPE_NATNUM6 : - case BRACKET_SYMBOLTYPE_NATNUM7 : - case BRACKET_SYMBOLTYPE_NATNUM8 : - case BRACKET_SYMBOLTYPE_NATNUM9 : - case BRACKET_SYMBOLTYPE_NATNUM10 : - case BRACKET_SYMBOLTYPE_NATNUM11 : - case BRACKET_SYMBOLTYPE_NATNUM12 : - case BRACKET_SYMBOLTYPE_NATNUM13 : - case BRACKET_SYMBOLTYPE_NATNUM14 : - case BRACKET_SYMBOLTYPE_NATNUM15 : - case BRACKET_SYMBOLTYPE_NATNUM16 : - case BRACKET_SYMBOLTYPE_NATNUM17 : - case BRACKET_SYMBOLTYPE_NATNUM18 : - case BRACKET_SYMBOLTYPE_NATNUM19 : - return true; - } - return false; -} - - -SvNumberformat::SvNumberformat(String& rString, - LocaleData* pFormatterP, - ImpSvNumberInputScan* pISc, - uint16_t& nCheckPos, - LanguageType eLan, - bool bStan) -{ - InitFormat(rString, pFormatterP, pISc, nCheckPos, eLan, bStan); -} - -SvNumberformat::SvNumberformat(std::string& rString, - LocaleData* pFormatterP, - ImpSvNumberInputScan* pISc, - uint16_t& nCheckPos, - LanguageType eLan, - bool bStan) -{ - std::wstring in_str(rString.length(), L' '); - std::copy(rString.begin(), rString.end(), in_str.begin()); - - InitFormat(in_str, pFormatterP, pISc, nCheckPos, eLan, bStan); -} - -void SvNumberformat::InitFormat(String& rString, - LocaleData* pFormatterP, - ImpSvNumberInputScan* pISc, - uint16_t& nCheckPos, - LanguageType eLan, - bool bStan) -{ - pFormatter = pFormatterP; - nNewStandardDefined = 0; - bStarFlag = false; - - if (!pFormatter || !pISc) - { - return; - } - rScanPtr = pFormatter->GetFormatScanner(); - bStandard = bStan; - bIsUsed = false; - fLimit1 = 0.0; - fLimit2 = 0.0; - eOp1 = NUMBERFORMAT_OP_NO; - eOp2 = NUMBERFORMAT_OP_NO; - eType = NUMBERFORMAT_DEFINED; - - bool bCancel = false; - bool bCondition = false; - short eSymbolType; - uint16_t nPos = 0; - uint16_t nPosOld; - nCheckPos = 0; - String aComment; - - // Split into 4 sub formats - sal_uInt16 nIndex; - for (nIndex = 0; nIndex < 4 && !bCancel; nIndex++) - { - // Original language/country may have to be reestablished - - String sStr; - nPosOld = nPos; // Start position of substring - // first get bracketed prefixes; e.g. conditions, color - do - { - eSymbolType = ImpNextSymbol(rString, nPos, sStr); - if (eSymbolType > 0) // condition - { - if (nIndex == 0 && !bCondition) - { - bCondition = true; - eOp1 = (SvNumberformatLimitOps)eSymbolType; - } - else if (nIndex == 1 && bCondition) - eOp2 = (SvNumberformatLimitOps)eSymbolType; - else // error - { - bCancel = true; // break for - nCheckPos = nPosOld; - } - if (!bCancel) - { - double fNumber; - uint16_t nAnzChars = ImpGetNumber(rString, nPos, sStr); - if (nAnzChars > 0) - { - short F_Type = NUMBERFORMAT_UNDEFINED; - if (!pISc->IsNumberFormat(sStr, F_Type, fNumber) || - (F_Type != NUMBERFORMAT_NUMBER && - F_Type != NUMBERFORMAT_SCIENTIFIC)) - { - fNumber = 0.0; - nPos = nPos - nAnzChars; - rString.erase(nPos, nAnzChars); - rString.insert(nPos, L"0"); - nPos++; - } - } - else - { - fNumber = 0.0; - rString.insert(nPos++, L"0"); - } - if (nIndex == 0) - fLimit1 = fNumber; - else - fLimit2 = fNumber; - if (rString.at(nPos) == L']') - nPos++; - else - { - bCancel = true; // break for - nCheckPos = nPos; - } - } - nPosOld = nPos; // position before string - } - else if (lcl_SvNumberformat_IsBracketedPrefix(eSymbolType)) - { - if (!bCancel) - { - rString.erase(nPosOld, nPos - nPosOld); - rString.insert(nPosOld, sStr); - nPos = nPosOld + sStr.size(); - rString.insert(nPos, L"]"); - rString.insert(nPosOld, L"["); - nPos += 2; - nPosOld = nPos; // position before string - } - } - } while (!bCancel && lcl_SvNumberformat_IsBracketedPrefix(eSymbolType)); - - // The remaining format code string - if (!bCancel) - { - if (eSymbolType == BRACKET_SYMBOLTYPE_FORMAT) - { - if (nIndex == 1 && eOp1 == NUMBERFORMAT_OP_NO) - eOp1 = NUMBERFORMAT_OP_GT; // undefined condition, default: > 0 - else if (nIndex == 2 && eOp2 == NUMBERFORMAT_OP_NO) - eOp2 = NUMBERFORMAT_OP_LT; // undefined condition, default: < 0 - if (sStr.size() == 0) - { // empty sub format - } - else - { - uint16_t nStrPos = rScanPtr->ScanFormat(sStr, aComment); - sal_uInt16 nAnz = rScanPtr->GetAnzResStrings(); - if (nAnz == 0) // error - nStrPos = 1; - if (nStrPos == 0) // ok - { - rString.erase(nPosOld, nPos - nPosOld); - rString.insert(nPosOld, sStr); - nPos = nPosOld + sStr.size(); - if (nPos < rString.size()) - { - rString.insert(nPos, L";"); - nPos++; - } - NumFor[nIndex].Enlarge(nAnz); - rScanPtr->CopyInfo(&(NumFor[nIndex].Info()), nAnz); - // type check - if (nIndex == 0) - eType = (short)NumFor[nIndex].Info().eScannedType; - else if (nIndex == 3) - { - NumFor[nIndex].Info().eScannedType = NUMBERFORMAT_TEXT; - } - else if ((short)NumFor[nIndex].Info().eScannedType != eType) - eType = NUMBERFORMAT_DEFINED; - } - else - { - nCheckPos = nPosOld + nStrPos; // error in string - bCancel = true; // break for - } - } - } - else if (eSymbolType == BRACKET_SYMBOLTYPE_ERROR) // error - { - nCheckPos = nPosOld; - bCancel = true; - } - else if (lcl_SvNumberformat_IsBracketedPrefix(eSymbolType)) - { - nCheckPos = nPosOld + 1; // error, prefix in string - bCancel = true; // break for - } - } - if (bCancel && !nCheckPos) - nCheckPos = 1; // nCheckPos is used as an error condition - if (!bCancel) - { - if (NumFor[nIndex].GetNatNum().IsSet() && - NumFor[nIndex].GetNatNum().GetLang() == LocaleId_en_US) - NumFor[nIndex].SetNatNumLang(eLan); - } - if (rString.size() == nPos) - { - if (nIndex == 2 && eSymbolType == BRACKET_SYMBOLTYPE_FORMAT && - rString.at(nPos - 1) == L';') - { // #83510# A 4th subformat explicitly specified to be empty - // hides any text. Need the type here for HasTextFormat() - NumFor[3].Info().eScannedType = NUMBERFORMAT_TEXT; - } - bCancel = true; - } - if (NumFor[nIndex].GetNatNum().IsSet()) - NumFor[nIndex].SetNatNumDate( - (NumFor[nIndex].Info().eScannedType & NUMBERFORMAT_DATE) != 0); - } - - if (bCondition && !nCheckPos) - { - if (nIndex == 1 && NumFor[0].GetnAnz() == 0 && - rString.at(rString.size() - 1) != L';') - { // No format code => GENERAL but not if specified empty - String aAdd(rScanPtr->GetStandardName()); - String aTmp; - if (!rScanPtr->ScanFormat(aAdd, aTmp)) - { - sal_uInt16 nAnz = rScanPtr->GetAnzResStrings(); - if (nAnz) - { - NumFor[0].Enlarge(nAnz); - rScanPtr->CopyInfo(&(NumFor[0].Info()), nAnz); - rString += aAdd; - } - } - } - else if (nIndex == 1 && NumFor[nIndex].GetnAnz() == 0 && - rString.at(rString.size() - 1) != L';' && - (NumFor[0].GetnAnz() > 1 || (NumFor[0].GetnAnz() == 1 && - NumFor[0].Info().nTypeArray[0] != NF_KEY_GENERAL))) - { // No trailing second subformat => GENERAL but not if specified empty - // and not if first subformat is GENERAL - String aAdd(rScanPtr->GetStandardName()); - String aTmp; - if (!rScanPtr->ScanFormat(aAdd, aTmp)) - { - sal_uInt16 nAnz = rScanPtr->GetAnzResStrings(); - if (nAnz) - { - NumFor[nIndex].Enlarge(nAnz); - rScanPtr->CopyInfo(&(NumFor[nIndex].Info()), nAnz); - rString += L';'; - rString += aAdd; - } - } - } - else if (nIndex == 2 && NumFor[nIndex].GetnAnz() == 0 && - rString.at(rString.size() - 1) != L';' && - eOp2 != NUMBERFORMAT_OP_NO) - { // No trailing third subformat => GENERAL but not if specified empty - String aAdd(rScanPtr->GetStandardName()); - String aTmp; - if (!rScanPtr->ScanFormat(aAdd, aTmp)) - { - sal_uInt16 nAnz = rScanPtr->GetAnzResStrings(); - if (nAnz) - { - NumFor[nIndex].Enlarge(nAnz); - rScanPtr->CopyInfo(&(NumFor[nIndex].Info()), nAnz); - rString += L';'; - rString += aAdd; - } - } - } - } - sFormatstring = rString; - if (aComment.size()) - { - SetComment(aComment); // sets sComment and sFormatstring - rString = sFormatstring; // - } - if (NumFor[2].GetnAnz() == 0 && // no 3rd substring - eOp1 == NUMBERFORMAT_OP_GT && eOp2 == NUMBERFORMAT_OP_NO && - fLimit1 == 0.0 && fLimit2 == 0.0) - eOp1 = NUMBERFORMAT_OP_GE; // 0 to the first format -} - -SvNumberformat::~SvNumberformat() -{ -} - -uint16_t SvNumberformat::ImpGetNumber(String& rString, - uint16_t& nPos, - String& sSymbol) -{ - uint16_t nStartPos = nPos; - sal_Unicode cToken; - uint16_t nLen = rString.size(); - sSymbol.erase(); - while ( nPos < nLen && ((cToken = rString.at(nPos)) != ']') ) - { - if (cToken == L' ') - { // delete spaces - rString.erase(nPos,1); - nLen--; - } - else - { - nPos++; - sSymbol += cToken; - } - } - return nPos - nStartPos; -} - - -// static -LanguageType SvNumberformat::ImpGetLanguageType( const String& rString, - uint16_t& nPos ) -{ - sal_Int32 nNum = 0; - sal_Unicode cToken = 0; - uint16_t nLen = rString.size(); - while ( nPos < nLen && ((cToken = rString.at(nPos)) != L']') ) - { - if (L'0' <= cToken && cToken <= L'9' ) - { - nNum *= 16; - nNum += cToken - L'0'; - } - else if ( L'a' <= cToken && cToken <= L'f' ) - { - nNum *= 16; - nNum += cToken - L'a' + 10; - } - else if ( L'A' <= cToken && cToken <= L'F' ) - { - nNum *= 16; - nNum += cToken - L'A' + 10; - } - else - return LocaleId_en_US; - ++nPos; - } - return (nNum && (cToken == ']' || nPos == nLen)) ? (LanguageType)nNum : - LocaleId_en_US; -} - -bool IsSingleSymbol(String& rString, uint16_t nPos){ - bool ret = false; - while(nPos > 0){ - if(rString.at(nPos) == '*' || rString.at(nPos) == '\\' || rString.at(nPos) == L'_'){ - ret = !ret; - nPos--; - } - else - return ret; - } - return ret; -} - -short SvNumberformat::ImpNextSymbol(String& rString, - uint16_t& nPos, - String& sSymbol) -{ - short eSymbolType = BRACKET_SYMBOLTYPE_FORMAT; - sal_Unicode cToken; - sal_Unicode cLetter = L' '; // intermediate result - uint16_t nLen = rString.size(); - ScanState eState = SsStart; - sSymbol.erase(); - const NfKeywordTable & rKeywords = rScanPtr->GetKeywords(); - while (nPos < nLen && eState != SsStop) - { - cToken = rString.at(nPos); - nPos++; - switch (eState) - { - case SsStart: - { - if (cToken == L'[') - { - eState = SsGetBracketed; - sSymbol += cToken; - } - else if (cToken == L';') - { - eState = SsGetString; - nPos--; - eSymbolType = BRACKET_SYMBOLTYPE_FORMAT; - } - else if (cToken == L']') - { - eState = SsStop; - eSymbolType = BRACKET_SYMBOLTYPE_ERROR; - } - else if (cToken == L' ') // Skip Blanks - { - rString.erase(nPos-1,1); - nPos--; - nLen--; - } - else - { - sSymbol += cToken; - eState = SsGetString; - eSymbolType = BRACKET_SYMBOLTYPE_FORMAT; - } - } - break; - case SsGetBracketed: - { - switch (cToken) - { - case L'<': - case L'>': - case L'=': - { - EraseAllChars(sSymbol, L'['); - sSymbol += cToken; - cLetter = cToken; - eState = SsGetCon; - switch (cToken) - { - case L'<': eSymbolType = NUMBERFORMAT_OP_LT; break; - case L'>': eSymbolType = NUMBERFORMAT_OP_GT; break; - case L'=': eSymbolType = NUMBERFORMAT_OP_EQ; break; - default: break; - } - } - break; - case L' ': - { - rString.erase(nPos-1,1); - nPos--; - nLen--; - } - break; - case L'$' : - { - if ( rString.at(nPos) == L'-' ) - { // [$-xxx] locale - EraseAllChars(sSymbol, L'['); - eSymbolType = BRACKET_SYMBOLTYPE_LOCALE; - eState = SsGetPrefix; - } - else - { // currency as of SV_NUMBERFORMATTER_VERSION_NEW_CURR - eSymbolType = BRACKET_SYMBOLTYPE_FORMAT; - eState = SsGetString; - } - sSymbol += cToken; - } - break; - case L'~' : - { // calendarID as of SV_NUMBERFORMATTER_VERSION_CALENDAR - eSymbolType = BRACKET_SYMBOLTYPE_FORMAT; - sSymbol += cToken; - eState = SsGetString; - } - break; - default: - { - static const String aNatNum = L"NATNUM"; - static const String aDBNum = L"DBNUM"; - String aUpperNatNum = rString.substr(nPos-1, aNatNum.size()); - ConvertToUpper(aUpperNatNum); - String aUpperDBNum = rString.substr(nPos-1, aDBNum.size()); - ConvertToUpper(aUpperDBNum); - sal_Unicode cUpper = aUpperNatNum.at(0); - if (cUpper == rKeywords[NF_KEY_H].at(0) || // H - cUpper == rKeywords[NF_KEY_MI].at(0) || // M - cUpper == rKeywords[NF_KEY_S].at(0) ) // S - { - sSymbol += cToken; - eState = SsGetTime; - cLetter = cToken; - } - else - { - EraseAllChars(sSymbol, L'['); - sSymbol += cToken; - eSymbolType = BRACKET_SYMBOLTYPE_COLOR; - eState = SsGetPrefix; - } - } - break; - } - } - break; - case SsGetString: - { - if (cToken == L';' && (nPos>=2) &&!IsSingleSymbol(rString, nPos-2)) - { - eState = SsStop; - } - else - sSymbol += cToken; - } - break; - case SsGetTime: - { - if (cToken == L']') - { - sSymbol += cToken; - eState = SsGetString; - eSymbolType = BRACKET_SYMBOLTYPE_FORMAT; - } - else - { - sal_Unicode cUpper = std::towupper(rString.at(nPos-1)); - if (cUpper == rKeywords[NF_KEY_H].at(0) || // H - cUpper == rKeywords[NF_KEY_MI].at(0) || // M - cUpper == rKeywords[NF_KEY_S].at(0) ) // S - { - if (cLetter == cToken) - { - sSymbol += cToken; - cLetter = L' '; - } - else - { - EraseAllChars(sSymbol, L'['); - sSymbol += cToken; - eState = SsGetPrefix; - } - } - else - { - EraseAllChars(sSymbol, L'['); - sSymbol += cToken; - eSymbolType = BRACKET_SYMBOLTYPE_COLOR; - eState = SsGetPrefix; - } - } - } - break; - case SsGetCon: - { - switch (cToken) - { - case L'<': - { - eState = SsStop; - eSymbolType = BRACKET_SYMBOLTYPE_ERROR; - } - break; - case L'>': - { - if (cLetter == L'<') - { - sSymbol += cToken; - cLetter = L' '; - eState = SsStop; - eSymbolType = NUMBERFORMAT_OP_NE; - } - else - { - eState = SsStop; - eSymbolType = BRACKET_SYMBOLTYPE_ERROR; - } - } - break; - case L'=': - { - if (cLetter == L'<') - { - sSymbol += cToken; - cLetter = L' '; - eSymbolType = NUMBERFORMAT_OP_LE; - } - else if (cLetter == L'>') - { - sSymbol += cToken; - cLetter = L' '; - eSymbolType = NUMBERFORMAT_OP_GE; - } - else - { - eState = SsStop; - eSymbolType = BRACKET_SYMBOLTYPE_ERROR; - } - } - break; - case L' ': - { - rString.erase(nPos-1,1); - nPos--; - nLen--; - } - break; - default: - { - eState = SsStop; - nPos--; - } - break; - } - } - break; - case SsGetPrefix: - { - if (cToken == L']') - eState = SsStop; - else - sSymbol += cToken; - } - break; - default: - break; - } // of switch - } // of while - - return eSymbolType; -} - -bool SvNumberformat::HasNewCurrency() const -{ - for ( sal_uInt16 j=0; j<4; j++ ) - { - if ( NumFor[j].HasNewCurrency() ) - return true; - } - return false; -} - -bool SvNumberformat::HasTextFormatCode() const -{ - for ( sal_uInt16 j=0; j<4; j++ ) - { - if ( NumFor[j].HasTextFormatCode() ) - return true; - } - return false; -} - -bool SvNumberformat::GetNewCurrencySymbol( String& rSymbol, - String& rExtension ) const -{ - for ( sal_uInt16 j=0; j<4; j++ ) - { - if ( NumFor[j].GetNewCurrencySymbol( rSymbol, rExtension ) ) - return true; - } - rSymbol.erase(); - rExtension.erase(); - return false; -} - - -// static -String SvNumberformat::StripNewCurrencyDelimiters( const String& rStr, - bool bQuoteSymbol ) -{ - String aTmp; - size_t find_pos; - uint16_t nStartPos, nPos, nLen; - nLen = rStr.size(); - nStartPos = 0; - while ( (find_pos = rStr.find( L"[$", nStartPos )) != std::string::npos ) - { - nPos = (uint16_t)find_pos; - uint16_t nEnd; - if ( (nEnd = GetQuoteEnd( rStr, nPos )) < nLen ) - { - aTmp += rStr.substr( nStartPos, ++nEnd - nStartPos ); - nStartPos = nEnd; - } - else - { - aTmp += rStr.substr( nStartPos, nPos - nStartPos ); - nStartPos = nPos + 2; - uint16_t nDash; - nEnd = nStartPos - 1; - do - { - nDash = rStr.find( L"-", ++nEnd ); - } while ( (nEnd = GetQuoteEnd( rStr, nDash )) < nLen ); - uint16_t nClose; - nEnd = nStartPos - 1; - do - { - nClose = rStr.find( L"]", ++nEnd ); - } while ( (nEnd = GetQuoteEnd( rStr, nClose )) < nLen ); - nPos = ( nDash < nClose ? nDash : nClose ); - if ( !bQuoteSymbol || rStr.at( nStartPos ) == L'"' ) - aTmp += rStr.substr( nStartPos, nPos - nStartPos ); - else - { - aTmp += L'"'; - aTmp += rStr.substr( nStartPos, nPos - nStartPos ); - aTmp += L'"'; - } - nStartPos = nClose + 1; - } - } - if ( nLen > nStartPos ) - aTmp += rStr.substr( nStartPos, nLen - nStartPos ); - return aTmp; -} - - -void SvNumberformat::Build50Formatstring( String& rStr ) const -{ - rStr = StripNewCurrencyDelimiters( sFormatstring, true ); -} - - -void SvNumberformat::ImpGetOutputStandard(double& fNumber, String& OutString) -{ - sal_uInt16 nStandardPrec = rScanPtr->GetStandardPrec(); - - if ( fabs(fNumber) > 1.0E15 ) // #58531# war E16 - { - nStandardPrec = ::std::min(nStandardPrec, static_cast(14)); // limits to 14 decimals - OutString = doubleToUString( fNumber, - rtl_math_StringFormat_E, nStandardPrec /*2*/, - pFormatter->GetNumDecimalSep().at(0)); - } - else - ImpGetOutputStdToPrecision(fNumber, OutString, nStandardPrec); -} - -void SvNumberformat::ImpGetOutputStdToPrecision(double& rNumber, String& rOutString, sal_uInt16 nPrecision) const -{ - nPrecision = ::std::min(UPPER_PRECISION, nPrecision); - - rOutString = doubleToUString( rNumber, - rtl_math_StringFormat_F, nPrecision /*2*/, - pFormatter->GetNumDecimalSep().at(0), true ); - if (rOutString.at(0) == L'-' && - std::count(rOutString.begin(), rOutString.end(), L'0') == rOutString.size()) - EraseLeadingChars(rOutString, L'-'); // nicht -0 - - ImpTransliterate( rOutString, NumFor[0].GetNatNum() ); -} - -void SvNumberformat::ImpGetOutputInputLine(double fNumber, String& OutString) -{ - bool bModified = false; - if ( (eType & NUMBERFORMAT_PERCENT) && (fabs(fNumber) < _D_MAX_D_BY_100)) - { - if (fNumber == 0.0) - { - OutString = L"0%"; - return; - } - fNumber *= 100; - bModified = true; - } - - if (fNumber == 0.0) - { - OutString = L'0'; - return; - } - - OutString = doubleToUString( fNumber, - rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, - pFormatter->GetNumDecimalSep().at(0), true ); - - if ( eType & NUMBERFORMAT_PERCENT && bModified) - OutString += L'%'; - return; -} - -short SvNumberformat::ImpCheckCondition(double& fNumber, - double& fLimit, - SvNumberformatLimitOps eOp) -{ - switch(eOp) - { - case NUMBERFORMAT_OP_NO: return -1; - case NUMBERFORMAT_OP_EQ: return (short) (fNumber == fLimit); - case NUMBERFORMAT_OP_NE: return (short) (fNumber != fLimit); - case NUMBERFORMAT_OP_LT: return (short) (fNumber < fLimit); - case NUMBERFORMAT_OP_LE: return (short) (fNumber <= fLimit); - case NUMBERFORMAT_OP_GT: return (short) (fNumber > fLimit); - case NUMBERFORMAT_OP_GE: return (short) (fNumber >= fLimit); - default: return -1; - } -} - -bool SvNumberformat::GetOutputString(String& sString, - String& OutString, - Color** ppColor) -{ - OutString.erase(); - sal_uInt16 nIx; - if (eType & NUMBERFORMAT_TEXT) - nIx = 0; - else if (NumFor[3].GetnAnz() > 0) - nIx = 3; - else - { - *ppColor = NULL; // no change of color - return false; - } - *ppColor = NULL; // NumFor[nIx].GetColor(); - const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info(); - if (rInfo.eScannedType == NUMBERFORMAT_TEXT) - { - bool bRes = false; - const sal_uInt16 nAnz = NumFor[nIx].GetnAnz(); - for (sal_uInt16 i = 0; i < nAnz; i++) - { - switch (rInfo.nTypeArray[i]) - { - case NF_SYMBOLTYPE_STAR: - if( bStarFlag ) - { - OutString += (sal_Unicode) 0x1B; - OutString += rInfo.sStrArray[i].at(1); - bRes = true; - } - break; - case NF_SYMBOLTYPE_BLANK: - InsertBlanks( OutString, OutString.size(), - rInfo.sStrArray[i].at(0) ); - break; - case NF_KEY_GENERAL : // #77026# "General" is the same as "@" - case NF_SYMBOLTYPE_DEL : - OutString += sString; - break; - default: - OutString += rInfo.sStrArray[i]; - } - } - return bRes; - } - return false; -} - -sal_uLong SvNumberformat::ImpGGT(sal_uLong x, sal_uLong y) -{ - if (y == 0) - return x; - else - { - sal_uLong z = x%y; - while (z) - { - x = y; - y = z; - z = x%y; - } - return y; - } -} - -sal_uLong SvNumberformat::ImpGGTRound(sal_uLong x, sal_uLong y) -{ - if (y == 0) - return x; - else - { - sal_uLong z = x%y; - while ((double)z/(double)y > D_EPS) - { - x = y; - y = z; - z = x%y; - } - return y; - } -} - -namespace { - -void lcl_GetOutputStringScientific( - double fNumber, sal_uInt16 nCharCount, LocaleData* pFormatter, String& rOutString) -{ - bool bSign = fabs(fNumber) < 0.0; - - // 1.000E+015 (one digit and the decimal point, and the five chars for the exponential part, totalling 7). - sal_uInt16 nPrec = nCharCount > 7 ? nCharCount - 7 : 0; - if (nPrec && bSign) - // Make room for the negative sign. - --nPrec; - - nPrec = ::std::min(nPrec, static_cast(14)); // limit to 14 decimals. - - rOutString = doubleToUString( - fNumber, rtl_math_StringFormat_E, nPrec, pFormatter->GetNumDecimalSep().at(0)); -} - -} - -bool SvNumberformat::GetOutputString(double fNumber, sal_uInt16 nCharCount, String& rOutString) const -{ - using namespace std; - - if (eType != NUMBERFORMAT_NUMBER) - return false; - - double fTestNum = fabs(fNumber); - - if (fTestNum < EXP_LOWER_BOUND) - { - lcl_GetOutputStringScientific(fNumber, nCharCount, pFormatter, rOutString); - return true; - } - - double fExp = log10(fTestNum); - // Values < 1.0 always have one digit before the decimal point. - sal_uInt16 nDigitPre = fExp >= 0.0 ? static_cast(ceil(fExp)) : 1; - - if (nDigitPre > 15) - { - lcl_GetOutputStringScientific(fNumber, nCharCount, pFormatter, rOutString); - return true; - } - - sal_uInt16 nPrec = nCharCount >= nDigitPre ? nCharCount - nDigitPre : 0; - if (nPrec && fNumber < 0.0) - // Subtract the negative sign. - --nPrec; - if (nPrec) - // Subtract the decimal point. - --nPrec; - - ImpGetOutputStdToPrecision(fNumber, rOutString, nPrec); - if (rOutString.size() > nCharCount) - // String still wider than desired. Switch to scientific notation. - lcl_GetOutputStringScientific(fNumber, nCharCount, pFormatter, rOutString); - - return true; -} - -bool SvNumberformat::GetOutputString(double fNumber, - String& OutString, - Color** ppColor) -{ - bool bRes = false; - OutString.erase(); // delete everything - *ppColor = NULL; // no color change - if (eType & NUMBERFORMAT_LOGICAL) - { - if (fNumber) - OutString = rScanPtr->GetTrueString(); - else - OutString = rScanPtr->GetFalseString(); - return false; - } - if (eType & NUMBERFORMAT_TEXT) - { - ImpGetOutputStandard(fNumber, OutString); - return false; - } - bool bHadStandard = false; - if (bStandard) // individual standard formats - { - if (rScanPtr->GetStandardPrec() == INPUTSTRING_PRECISION) // all number formats InputLine - { - ImpGetOutputInputLine(fNumber, OutString); - return false; - } - switch (eType) - { - case NUMBERFORMAT_NUMBER: // - { - if (rScanPtr->GetStandardPrec() == UNLIMITED_PRECISION) - { - bool bSign = fNumber < 0.0; - if (bSign) - fNumber = -fNumber; - ImpGetOutputStdToPrecision(fNumber, OutString, 10); // Use 10 decimals for general 'unlimited' format. - if (fNumber < EXP_LOWER_BOUND) - { - uint16_t nLen = OutString.size(); - if (!nLen) - return false; - - if (nLen > 11 || (OutString == L"0" && fNumber != 0.0)) - { - sal_uInt16 nStandardPrec = rScanPtr->GetStandardPrec(); - nStandardPrec = ::std::min(nStandardPrec, static_cast(14)); // limits to 14 decimals - OutString = doubleToUString( fNumber, - rtl_math_StringFormat_E, nStandardPrec /*2*/, - pFormatter->GetNumDecimalSep().at(0), true); - } - } - if (bSign) - OutString.insert(0, L"-"); - return false; - } - ImpGetOutputStandard(fNumber, OutString); - bHadStandard = true; - } - break; - case NUMBERFORMAT_DATE: - bRes |= ImpGetDateOutput(fNumber, 0, OutString); - bHadStandard = true; - break; - case NUMBERFORMAT_TIME: - bRes |= ImpGetTimeOutput(fNumber, 0, OutString); - bHadStandard = true; - break; - case NUMBERFORMAT_DATETIME: - bRes |= ImpGetDateTimeOutput(fNumber, 0, OutString); - bHadStandard = true; - break; - } - } - if ( !bHadStandard ) - { - sal_uInt16 nIx; // Index des Teilformats - short nCheck = ImpCheckCondition(fNumber, fLimit1, eOp1); - if (nCheck == -1 || nCheck == 1) // nur 1 String oder True - nIx = 0; - else - { - nCheck = ImpCheckCondition(fNumber, fLimit2, eOp2); - if (nCheck == -1 || nCheck == 1) - nIx = 1; - else - nIx = 2; - } - if (nIx == 1 && // negatives Format - IsNegativeRealNegative() && fNumber < 0.0) // unsigned - fNumber = -fNumber; // Eliminate signs - if (nIx == 0 && IsNegativeRealNegative2() && fNumber < 0.0) - fNumber = -fNumber; - *ppColor = NULL; // NumFor[nIx].GetColor(); - const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info(); - const sal_uInt16 nAnz = NumFor[nIx].GetnAnz(); - if (nAnz == 0 && rInfo.eScannedType == NUMBERFORMAT_UNDEFINED) - return false; // leer => nichts - else if (nAnz == 0) // sonst Standard-Format - { - ImpGetOutputStandard(fNumber, OutString); - return false; - } - switch (rInfo.eScannedType) - { - case NUMBERFORMAT_TEXT: - case NUMBERFORMAT_DEFINED: - { - for (sal_uInt16 i = 0; i < nAnz; i++) - { - switch (rInfo.nTypeArray[i]) - { - case NF_SYMBOLTYPE_STAR: - if( bStarFlag ) - { - OutString += (sal_Unicode) 0x1B; - OutString += rInfo.sStrArray[i].at(1); - bRes = true; - } - break; - case NF_SYMBOLTYPE_BLANK: - InsertBlanks( OutString, OutString.size(), - rInfo.sStrArray[i].at(0) ); - break; - case NF_SYMBOLTYPE_STRING: - case NF_SYMBOLTYPE_CURRENCY: - OutString += rInfo.sStrArray[i]; - break; - case NF_SYMBOLTYPE_THSEP: - if (rInfo.nThousand == 0) - OutString += rInfo.sStrArray[i]; - break; - default: - break; - } - } - } - break; - case NUMBERFORMAT_DATE: - bRes |= ImpGetDateOutput(fNumber, nIx, OutString); - break; - case NUMBERFORMAT_TIME: - bRes |= ImpGetTimeOutput(fNumber, nIx, OutString); - break; - case NUMBERFORMAT_DATETIME: - bRes |= ImpGetDateTimeOutput(fNumber, nIx, OutString); - break; - case NUMBERFORMAT_NUMBER: - case NUMBERFORMAT_PERCENT: - case NUMBERFORMAT_CURRENCY: - bRes |= ImpGetNumberOutput(fNumber, nIx, OutString); - break; - case NUMBERFORMAT_FRACTION: - { - String sStr, sFrac, sDiv; // Strings, value for - sal_uLong nFrac, nDiv; // pre-decimal point - // numerator and denominator - bool bSign = false; - if (fNumber < 0) - { - if (nIx == 0) // not in rear - bSign = true; // Formats - fNumber = -fNumber; - } - double fNum = floor(fNumber); // integer part - fNumber -= fNum; // decimal part - if (fNum > _D_MAX_U_LONG_ || rInfo.nCntExp > 9) - // too large - { - OutString = rScanPtr->GetErrorString(); - return false; - } - if (rInfo.nCntExp == 0) - { - return false; - } - sal_uLong nBasis = ((sal_uLong)floor( // 9, 99, 999 ,... - pow(10.0,rInfo.nCntExp))) - 1; - sal_uLong x0, y0, x1, y1; - - if (rInfo.nExpVal <= 0) - { - if (rInfo.nCntExp <= _MAX_FRACTION_PREC) - { - bool bUpperHalf; - if (fNumber > 0.5) - { - bUpperHalf = true; - fNumber -= (fNumber - 0.5) * 2.0; - } - else - bUpperHalf = false; - // Entry into Farey series - // Find: - x0 = (sal_uLong)floor(fNumber*nBasis); // z.B. 2/9 <= x < 3/9 - if (x0 == 0) // => x0 = 2 - { - y0 = 1; - x1 = 1; - y1 = nBasis; - } - else if (x0 == (nBasis - 1) / 2) // (b-1)/2, 1/2 - { // goes (nbase odd) - y0 = nBasis; - x1 = 1; - y1 = 2; - } - else if (x0 == 1) - { - y0 = nBasis; // 1/n; 1/(n-1) - x1 = 1; - y1 = nBasis - 1; - } - else - { - y0 = nBasis; // z.B. 2/9 2/8 - x1 = x0; - y1 = nBasis - 1; - double fUg = (double)x0 / (double)y0; - double fOg = (double)x1 / (double)y1; - sal_uLong nGgt = ImpGGT(y0, x0); // x0/y0 short - x0 /= nGgt; - y0 /= nGgt; // boxing: - sal_uLong x2 = 0; - sal_uLong y2 = 0; - bool bStop = false; - while (!bStop) - { - double fTest = (double)x1 / (double)y1; - while (!bStop) - { - while (fTest > fOg) - { - x1--; - fTest = (double)x1 / (double)y1; - } - while (fTest < fUg && y1 > 1) - { - y1--; - fTest = (double)x1 / (double)y1; - } - if (fTest <= fOg) - { - fOg = fTest; - bStop = true; - } - else if (y1 == 1) - bStop = true; - } // of while - nGgt = ImpGGT(y1, x1); // x1/y1 short - x2 = x1 / nGgt; - y2 = y1 / nGgt; - if (x2*y0 - x0 * y2 == 1 || y1 <= 1) // Test, ob x2/y2 - bStop = true; // next Farey number - else - { - y1--; - bStop = false; - } - } // of while - x1 = x2; - y1 = y2; - } // of else - double fup, flow; - flow = (double)x0 / (double)y0; - fup = (double)x1 / (double)y1; - while (fNumber > fup) - { - sal_uLong x2 = ((y0 + nBasis) / y1)*x1 - x0; // next Farey number - sal_uLong y2 = ((y0 + nBasis) / y1)*y1 - y0; - // GetNextFareyNumber(nBasis, x0, x1, y0, y1, x2, y2); - x0 = x1; - y0 = y1; - x1 = x2; - y1 = y2; - flow = fup; - fup = (double)x1 / (double)y1; - } - if (fNumber - flow < fup - fNumber) - { - nFrac = x0; - nDiv = y0; - } - else - { - nFrac = x1; - nDiv = y1; - } - if (bUpperHalf) // Original restaur. - { - if (nFrac == 0 && nDiv == 1) // 1/1 - fNum += 1.0; - else - nFrac = nDiv - nFrac; - } - } - else // big denominators - { // 0,1234->123/1000 - sal_uLong nGgt; - nDiv = 10000000; - nFrac = ((sal_uLong)floor(0.5 + fNumber * 10000000.0)); - nGgt = ImpGGT(nDiv, nFrac); - if (nGgt > 1) - { - nDiv /= nGgt; - nFrac /= nGgt; - } - if (nDiv > nBasis) - { - nGgt = ImpGGTRound(nDiv, nFrac); - if (nGgt > 1) - { - nDiv /= nGgt; - nFrac /= nGgt; - } - } - if (nDiv > nBasis) - { - nDiv = nBasis; - nFrac = ((sal_uLong)floor(0.5 + fNumber * - pow(10.0, rInfo.nCntExp))); - nGgt = ImpGGTRound(nDiv, nFrac); - if (nGgt > 1) - { - nDiv /= nGgt; - nFrac /= nGgt; - } - } - } - } - else - { - nDiv = rInfo.nExpVal; - double temp_val = fNumber * nDiv; - nFrac = floor(temp_val); - if (temp_val - nFrac >= 0.5) - nFrac++; - if (nFrac == nDiv) - { - fNum += 1.0; - nDiv = 1; - nFrac = 0; - } - } - - if (rInfo.nCntPre == 0) // spurious break - { - double fNum1 = fNum * (double)nDiv + (double)nFrac; - if (fNum1 > _D_MAX_U_LONG_) - { - OutString = rScanPtr->GetErrorString(); - return false; - } - nFrac = (sal_uLong) floor(fNum1); - sStr.erase(); - } - else if (fNum == 0.0 && nFrac != 0) - sStr.erase(); - else - { - wchar_t aBuf[100]; - swprintf( aBuf, sizeof(aBuf) / sizeof(wchar_t), L"%.f", fNum ); // simple rounded integer (#100211# - checked) - sStr = aBuf; - ImpTransliterate( sStr, NumFor[nIx].GetNatNum() ); - } - if (rInfo.nCntPre > 0 && nFrac == 0) - { - sFrac.erase(); - sDiv.erase(); - } - else - { - sFrac = ImpIntToString( nIx, nFrac ); - sDiv = ImpIntToString( nIx, nDiv ); - } - - sal_uInt16 j = nAnz-1; // last symbol->backward. - uint16_t k; // denominator: - bRes |= ImpNumberFill(sDiv, fNumber, k, j, nIx, NF_SYMBOLTYPE_FRAC); - bool bCont = true; - if (rInfo.nTypeArray[j] == NF_SYMBOLTYPE_FRAC) - { - if (rInfo.nCntPre > 0 && nFrac == 0) - sDiv.insert(0, 1, L' '); - else - sDiv.insert( 0, 1, rInfo.sStrArray[j].at(0) ); - if ( j ) - j--; - else - bCont = false; - } - // next counter: - if ( !bCont ) - sFrac.erase(); - else - { - bRes |= ImpNumberFill(sFrac, fNumber, k, j, nIx, NF_SYMBOLTYPE_FRACBLANK); - if (rInfo.nTypeArray[j] == NF_SYMBOLTYPE_FRACBLANK) - { - sFrac.insert(0, rInfo.sStrArray[j]); - if ( j ) - j--; - else - bCont = false; - } - } - // further main number - if ( !bCont ) - sStr.erase(); - else - { - k = sStr.size(); // after last digit - if (k > 0) - { - bRes |= ImpNumberFillWithThousands(sStr, fNumber, k, j, nIx, - rInfo.nCntPre); - } - } - if (bSign && !(nFrac == 0 && fNum == 0.0)) - OutString.insert(0, 1, L'-'); // not -0 - OutString += sStr; - OutString += sFrac; - OutString += sDiv; - } - break; - case NUMBERFORMAT_SCIENTIFIC: - { - bool bSign = false; - if (fNumber < 0) - { - if (nIx == 0) // not in rear - bSign = true; // Formaten - fNumber = -fNumber; - } - String sStr( doubleToUString( fNumber, - rtl_math_StringFormat_E, - rInfo.nCntPre + rInfo.nCntPost - 1, L'.' )); - - String ExpStr; - short nExpSign = 1; - uint16_t nExPos = sStr.find('E'); - if ( nExPos != STRING_NOTFOUND ) - { - // split into mantisse and exponent and get rid of "E+" or "E-" - uint16_t nExpStart = nExPos + 1; - switch ( sStr.at( nExpStart ) ) - { - case L'-' : - nExpSign = -1; - // fallthru - case L'+' : - ++nExpStart; - break; - } - ExpStr = sStr.substr( nExpStart ); // part following the "E+" - sStr.erase( nExPos ); - EraseAllChars(sStr, L'.'); // cut any decimal delimiter - if ( rInfo.nCntPre != 1 ) // rescale Exp - { - sal_Int32 nExp = std::stoi(ExpStr) * nExpSign; - nExp -= sal_Int32(rInfo.nCntPre)-1; - if ( nExp < 0 ) - { - nExpSign = -1; - nExp = -nExp; - } - else - nExpSign = 1; - ExpStr = std::to_wstring( nExp ); - } - } - sal_uInt16 j = nAnz-1; // last symbol - uint16_t k; // position in ExpStr - bRes |= ImpNumberFill(ExpStr, fNumber, k, j, nIx, NF_SYMBOLTYPE_EXP); - - uint16_t nZeros = 0; // erase leading zeros - while (nZeros < k && ExpStr.at(nZeros) == L'0') - ++nZeros; - if (nZeros) - ExpStr.erase( 0, nZeros); - - bool bCont = true; - if (rInfo.nTypeArray[j] == NF_SYMBOLTYPE_EXP) - { - const String& rStr = rInfo.sStrArray[j]; - if (nExpSign == -1) - ExpStr.insert(0, 1, L'-'); - else if (rStr.size() > 1 && rStr.at(1) == L'+') - ExpStr.insert(0, 1, L'+'); - ExpStr.insert(0, 1, rStr.at(0)); - if ( j ) - j--; - else - bCont = false; - } - // further main number: - if ( !bCont ) - sStr.erase(); - else - { - k = sStr.size(); // after last digit - bRes |= ImpNumberFillWithThousands(sStr,fNumber, k,j,nIx, - rInfo.nCntPre + - rInfo.nCntPost); - } - if (bSign) - sStr.insert(0, 1, L'-'); - OutString = sStr; - OutString += ExpStr; - } - break; - } - } - return bRes; -} - -bool SvNumberformat::GetOutputString(double fNumber, std::string& OutString) -{ - String out_str; - duckdb_excel::Color *pColor = nullptr; - bool result = GetOutputString(fNumber, out_str, &pColor); - - std::string temp(out_str.length(), ' '); - std::copy(out_str.begin(), out_str.end(), temp.begin()); - OutString = temp; - - return result; -} - -bool SvNumberformat::ImpGetTimeOutput(double fNumber, - sal_uInt16 nIx, - String& OutString) -{ - //bool bCalendarSet = false; - double fNumberOrig = fNumber; - bool bRes = false; - bool bSign = false; - if (fNumber < 0.0) - { - fNumber = -fNumber; - if (nIx == 0) - bSign = true; - } - const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info(); - if (rInfo.bThousand) // []-Format - { - if (fNumber > 1.0E10) // too large - { - OutString = rScanPtr->GetErrorString(); - return false; - } - } - else - fNumber -= floor(fNumber); // otherwise cut off date - bool bInputLine; - uint16_t nCntPost; - if ( rScanPtr->GetStandardPrec() == 300 && - 0 < rInfo.nCntPost && rInfo.nCntPost < 7 ) - { // round at 7 decimals (+5 of 86400 == 12 significant digits) - bInputLine = true; - nCntPost = 7; - } - else - { - bInputLine = false; - nCntPost = uint16_t(rInfo.nCntPost); - } - if (bSign && !rInfo.bThousand) // no []-Format - fNumber = 1.0 - fNumber; // "reciprocal" - double fTime = fNumber * 86400.0; - fTime = math_round( fTime, int(nCntPost) ); - if (bSign && fTime == 0.0) - bSign = false; // not -00:00:00 - - if( floor( fTime ) > _D_MAX_U_LONG_ ) - { - OutString = rScanPtr->GetErrorString(); - return false; - } - sal_uLong nSeconds = (sal_uLong)floor( fTime ); - - String sSecStr( doubleToUString( fTime-nSeconds, - rtl_math_StringFormat_F, int(nCntPost), L'.')); - EraseLeadingChars(sSecStr, L'0'); - EraseLeadingChars(sSecStr, L'.'); - if ( bInputLine ) - { - EraseTrailingChars(sSecStr, L'0'); - if ( sSecStr.size() < uint16_t(rInfo.nCntPost) ) - sSecStr.insert( sSecStr.size(), rInfo.nCntPost - sSecStr.size(), L'0' ); - ImpTransliterate( sSecStr, NumFor[nIx].GetNatNum() ); - nCntPost = sSecStr.size(); - } - else - ImpTransliterate( sSecStr, NumFor[nIx].GetNatNum() ); - - uint16_t nSecPos = 0; // For digits - // process - sal_uLong nHour, nMin, nSec; - if (!rInfo.bThousand) // no [] Format - { - nHour = (nSeconds/3600) % 24; - nMin = (nSeconds%3600) / 60; - nSec = nSeconds%60; - } - else if (rInfo.nThousand == 3) // [ss] - { - nHour = 0; - nMin = 0; - nSec = nSeconds; - } - else if (rInfo.nThousand == 2) // [mm]:ss - { - nHour = 0; - nMin = nSeconds / 60; - nSec = nSeconds % 60; - } - else if (rInfo.nThousand == 1) // [hh]:mm:ss - { - nHour = nSeconds / 3600; - nMin = (nSeconds%3600) / 60; - nSec = nSeconds%60; - } - else { - // TODO What should these be set to? - nHour = 0; - nMin = 0; - nSec = 0; - } - - sal_Unicode cAmPm = L' '; // a or p - if (rInfo.nCntExp) // AM/PM - { - if (nHour == 0) - { - nHour = 12; - cAmPm = L'a'; - } - else if (nHour < 12) - cAmPm = L'a'; - else - { - cAmPm = L'p'; - if (nHour > 12) - nHour -= 12; - } - } - const sal_uInt16 nAnz = NumFor[nIx].GetnAnz(); - for (sal_uInt16 i = 0; i < nAnz; i++) - { - switch (rInfo.nTypeArray[i]) - { - case NF_SYMBOLTYPE_STAR: - if( bStarFlag ) - { - OutString += (sal_Unicode) 0x1B; - OutString += rInfo.sStrArray[i].at(1); - bRes = true; - } - break; - case NF_SYMBOLTYPE_BLANK: - InsertBlanks( OutString, OutString.size(), - rInfo.sStrArray[i].at(0) ); - break; - case NF_SYMBOLTYPE_STRING: - case NF_SYMBOLTYPE_CURRENCY: - case NF_SYMBOLTYPE_DATESEP: - case NF_SYMBOLTYPE_TIMESEP: - case NF_SYMBOLTYPE_TIME100SECSEP: - OutString += rInfo.sStrArray[i]; - break; - case NF_SYMBOLTYPE_DIGIT: - { - uint16_t nLen = ( bInputLine && i > 0 && - (rInfo.nTypeArray[i-1] == NF_SYMBOLTYPE_STRING || - rInfo.nTypeArray[i-1] == NF_SYMBOLTYPE_TIME100SECSEP) ? - nCntPost : rInfo.sStrArray[i].size() ); - for (uint16_t j = 0; j < nLen && nSecPos < nCntPost; j++) - { - OutString += sSecStr.at(nSecPos); - nSecPos++; - } - } - break; - case NF_KEY_AMPM: // AM/PM - { - if (cAmPm == L'a') - OutString += pFormatter->getTimeAM(); - else - OutString += pFormatter->getTimePM(); - } - break; - case NF_KEY_AP: // A/P - { - if (cAmPm == L'a') - OutString += L'a'; - else - OutString += L'p'; - } - break; - case NF_KEY_MI: // M - OutString += ImpIntToString( nIx, nMin ); - break; - case NF_KEY_MMI: // MM - OutString += ImpIntToString( nIx, nMin, 2 ); - break; - case NF_KEY_H: // H - OutString += ImpIntToString( nIx, nHour ); - break; - case NF_KEY_HH: // HH - OutString += ImpIntToString( nIx, nHour, 2 ); - break; - case NF_KEY_S: // S - OutString += ImpIntToString( nIx, nSec ); - break; - case NF_KEY_SS: // SS - OutString += ImpIntToString( nIx, nSec, 2 ); - break; - default: - break; - } - } - if (bSign && rInfo.bThousand) - OutString.insert(0, L"-"); - return bRes; -} - - -bool SvNumberformat::ImpIsOtherCalendar( const ImpSvNumFor& rNumFor ) const -{ - return false; -} - - -void SvNumberformat::SwitchToOtherCalendar( String& rOrgCalendar, - double& fOrgDateTime ) const -{ -} - - -void SvNumberformat::SwitchToGregorianCalendar( const String& rOrgCalendar, - double fOrgDateTime ) const -{ -} - - -bool SvNumberformat::ImpFallBackToGregorianCalendar( String& rOrgCalendar, double& fOrgDateTime ) -{ - return false; -} - - -bool SvNumberformat::ImpSwitchToSpecifiedCalendar( String& rOrgCalendar, - double& fOrgDateTime, const ImpSvNumFor& rNumFor ) const -{ - return false; -} - - -// static -void SvNumberformat::ImpAppendEraG( String& OutString, sal_Int16 nNatNum ) -{ - OutString += pFormatter->GetCalendar()->getDisplayString(CalendarDisplayCode::SHORT_ERA, nNatNum); -} - - -bool SvNumberformat::ImpGetDateOutput(double fNumber, - sal_uInt16 nIx, - String& OutString) -{ - bool bRes = false; - Calendar* rCal = pFormatter->GetCalendar(); - double fDiff = DateTime(*(rCal->GetNullDate())) - rCal->getEpochStart(); - fNumber += fDiff; - rCal->setLocalDateTime( fNumber ); - String aOrgCalendar; // empty => not changed yet - double fOrgDateTime; - bool bOtherCalendar = ImpIsOtherCalendar( NumFor[nIx] ); - if ( bOtherCalendar ) - SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime ); - if ( ImpFallBackToGregorianCalendar( aOrgCalendar, fOrgDateTime ) ) - bOtherCalendar = false; - const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info(); - const sal_uInt16 nAnz = NumFor[nIx].GetnAnz(); - sal_Int16 nNatNum = NumFor[nIx].GetNatNum().GetNatNum(); - for (sal_uInt16 i = 0; i < nAnz; i++) - { - switch (rInfo.nTypeArray[i]) - { - case NF_SYMBOLTYPE_CALENDAR : - break; - case NF_SYMBOLTYPE_STAR: - if( bStarFlag ) - { - OutString += (sal_Unicode) 0x1B; - OutString += rInfo.sStrArray[i].at(1); - bRes = true; - } - break; - case NF_SYMBOLTYPE_BLANK: - InsertBlanks( OutString, OutString.size(), - rInfo.sStrArray[i].at(0) ); - break; - case NF_SYMBOLTYPE_STRING: - case NF_SYMBOLTYPE_CURRENCY: - case NF_SYMBOLTYPE_DATESEP: - case NF_SYMBOLTYPE_TIMESEP: - case NF_SYMBOLTYPE_TIME100SECSEP: - OutString += rInfo.sStrArray[i]; - break; - case NF_KEY_M: // M - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_MONTH, nNatNum ); - break; - case NF_KEY_MM: // MM - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_MONTH, nNatNum ); - break; - case NF_KEY_MMM: // MMM - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_MONTH_NAME, nNatNum ); - break; - case NF_KEY_MMMM: // MMMM - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_MONTH_NAME, nNatNum ); - break; - case NF_KEY_MMMMM: // MMMMM - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_MONTH_NAME, nNatNum ).at(0); - break; - case NF_KEY_Q: // Q - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_QUARTER, nNatNum ); - break; - case NF_KEY_QQ: // QQ - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_QUARTER, nNatNum ); - break; - case NF_KEY_D: // D - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_DAY, nNatNum ); - break; - case NF_KEY_DD: // DD - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_DAY, nNatNum ); - break; - case NF_KEY_DDD: // DDD - { - if ( bOtherCalendar ) - SwitchToGregorianCalendar( aOrgCalendar, fOrgDateTime ); - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_DAY_NAME, nNatNum ); - if ( bOtherCalendar ) - SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime ); - } - break; - case NF_KEY_DDDD: // DDDD - { - if ( bOtherCalendar ) - SwitchToGregorianCalendar( aOrgCalendar, fOrgDateTime ); - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_DAY_NAME, nNatNum ); - if ( bOtherCalendar ) - SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime ); - } - break; - case NF_KEY_YY: // YY - { - if ( bOtherCalendar ) - SwitchToGregorianCalendar( aOrgCalendar, fOrgDateTime ); - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_YEAR, nNatNum ); - if ( bOtherCalendar ) - SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime ); - } - break; - case NF_KEY_YYYY: // YYYY - { - if ( bOtherCalendar ) - SwitchToGregorianCalendar( aOrgCalendar, fOrgDateTime ); - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_YEAR, nNatNum ); - if ( bOtherCalendar ) - SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime ); - } - break; - case NF_KEY_EC: // E - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_YEAR, nNatNum ); - break; - case NF_KEY_EEC: // EE - case NF_KEY_R: // R - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_YEAR, nNatNum ); - break; - case NF_KEY_NN: // NN - case NF_KEY_AAA: // AAA - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_DAY_NAME, nNatNum ); - break; - case NF_KEY_NNN: // NNN - case NF_KEY_AAAA: // AAAA - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_DAY_NAME, nNatNum ); - break; - case NF_KEY_NNNN: // NNNN - { - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_DAY_NAME, nNatNum ); - OutString += pFormatter->getLongDateDayOfWeekSep(); - } - break; - case NF_KEY_WW : // WW - { - sal_Int16 nVal = rCal->getValue( CalendarFieldIndex::WEEK_OF_YEAR ); - OutString += ImpIntToString( nIx, nVal ); - } - break; - case NF_KEY_G: // G - ImpAppendEraG( OutString, nNatNum ); - break; - case NF_KEY_GG: // GG - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_ERA, nNatNum ); - break; - case NF_KEY_GGG: // GGG - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_ERA, nNatNum ); - break; - case NF_KEY_RR: // RR => GGGEE - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_YEAR_AND_ERA, nNatNum ); - break; - } - } - return bRes; -} - -bool SvNumberformat::ImpGetDateTimeOutput(double fNumber, - sal_uInt16 nIx, - String& OutString) -{ - bool bRes = false; - - Calendar* rCal = pFormatter->GetCalendar(); - double fDiff = DateTime(*(rCal->GetNullDate())) - rCal->getEpochStart(); - fNumber += fDiff; - - const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info(); - bool bInputLine; - uint16_t nCntPost; - if ( rScanPtr->GetStandardPrec() == 300 && - 0 < rInfo.nCntPost && rInfo.nCntPost < 7 ) - { // round at 7 decimals (+5 of 86400 == 12 significant digits) - bInputLine = true; - nCntPost = 7; - } - else - { - bInputLine = false; - nCntPost = uint16_t(rInfo.nCntPost); - } - double fTime = (fNumber - floor( fNumber )) * 86400.0; - fTime = math_round( fTime, int(nCntPost) ); - if (fTime >= 86400.0) - { - // result of fNumber==x.999999999... rounded up, use correct date/time - fTime -= 86400.0; - fNumber = floor( fNumber + 0.5) + fTime; - } - rCal->setLocalDateTime( fNumber ); - - String aOrgCalendar; // empty => not changed yet - double fOrgDateTime; - bool bOtherCalendar = ImpIsOtherCalendar( NumFor[nIx] ); - if ( bOtherCalendar ) - SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime ); - if ( ImpFallBackToGregorianCalendar( aOrgCalendar, fOrgDateTime ) ) - bOtherCalendar = false; - sal_Int16 nNatNum = NumFor[nIx].GetNatNum().GetNatNum(); - - sal_uLong nSeconds = (sal_uLong)floor( fTime ); - String sSecStr( doubleToUString( fTime-nSeconds, - rtl_math_StringFormat_F, int(nCntPost), L'.')); - EraseLeadingChars(sSecStr, L'0'); - EraseLeadingChars(sSecStr, L'.'); - if ( bInputLine ) - { - EraseTrailingChars(sSecStr, '0'); - if ( sSecStr.size() < uint16_t(rInfo.nCntPost) ) - sSecStr.insert(sSecStr.size(), uint16_t(rInfo.nCntPost) - sSecStr.size(), L'0' ); - ImpTransliterate( sSecStr, NumFor[nIx].GetNatNum() ); - nCntPost = sSecStr.size(); - } - else - ImpTransliterate( sSecStr, NumFor[nIx].GetNatNum() ); - - uint16_t nSecPos = 0; // Zum Ziffernweisen - // abarbeiten - sal_uLong nHour, nMin, nSec; - if (!rInfo.bThousand) // [] Format - { - nHour = (nSeconds/3600) % 24; - nMin = (nSeconds%3600) / 60; - nSec = nSeconds%60; - } - else if (rInfo.nThousand == 3) // [ss] - { - nHour = 0; - nMin = 0; - nSec = nSeconds; - } - else if (rInfo.nThousand == 2) // [mm]:ss - { - nHour = 0; - nMin = nSeconds / 60; - nSec = nSeconds % 60; - } - else if (rInfo.nThousand == 1) // [hh]:mm:ss - { - nHour = nSeconds / 3600; - nMin = (nSeconds%3600) / 60; - nSec = nSeconds%60; - } - else { - nHour = 0; // TODO What should these values be? - nMin = 0; - nSec = 0; - } - sal_Unicode cAmPm = L' '; // a oder p - if (rInfo.nCntExp) // AM/PM - { - if (nHour == 0) - { - nHour = 12; - cAmPm = L'a'; - } - else if (nHour < 12) - cAmPm = L'a'; - else - { - cAmPm = L'p'; - if (nHour > 12) - nHour -= 12; - } - } - const sal_uInt16 nAnz = NumFor[nIx].GetnAnz(); - for (sal_uInt16 i = 0; i < nAnz; i++) - { - switch (rInfo.nTypeArray[i]) - { - case NF_SYMBOLTYPE_CALENDAR : - break; - case NF_SYMBOLTYPE_STAR: - if( bStarFlag ) - { - OutString += (sal_Unicode) 0x1B; - OutString += rInfo.sStrArray[i].at(1); - bRes = true; - } - break; - case NF_SYMBOLTYPE_BLANK: - InsertBlanks( OutString, OutString.size(), - rInfo.sStrArray[i].at(0) ); - break; - case NF_SYMBOLTYPE_STRING: - case NF_SYMBOLTYPE_CURRENCY: - case NF_SYMBOLTYPE_DATESEP: - case NF_SYMBOLTYPE_TIMESEP: - case NF_SYMBOLTYPE_TIME100SECSEP: - OutString += rInfo.sStrArray[i]; - break; - case NF_SYMBOLTYPE_DIGIT: - { - uint16_t nLen = ( bInputLine && i > 0 && - (rInfo.nTypeArray[i-1] == NF_SYMBOLTYPE_STRING || - rInfo.nTypeArray[i-1] == NF_SYMBOLTYPE_TIME100SECSEP) ? - nCntPost : rInfo.sStrArray[i].size() ); - for (uint16_t j = 0; j < nLen && nSecPos < nCntPost; j++) - { - OutString += sSecStr.at(nSecPos); - nSecPos++; - } - } - break; - case NF_KEY_AMPM: // AM/PM - { - if (cAmPm == L'a') - OutString += pFormatter->getTimeAM(); - else - OutString += pFormatter->getTimePM(); - } - break; - case NF_KEY_AP: // A/P - { - if (cAmPm == L'a') - OutString += L'a'; - else - OutString += L'p'; - } - break; - case NF_KEY_MI: // M - OutString += ImpIntToString( nIx, nMin ); - break; - case NF_KEY_MMI: // MM - OutString += ImpIntToString( nIx, nMin, 2 ); - break; - case NF_KEY_H: // H - OutString += ImpIntToString( nIx, nHour ); - break; - case NF_KEY_HH: // HH - OutString += ImpIntToString( nIx, nHour, 2 ); - break; - case NF_KEY_S: // S - OutString += ImpIntToString( nIx, nSec ); - break; - case NF_KEY_SS: // SS - OutString += ImpIntToString( nIx, nSec, 2 ); - break; - case NF_KEY_M: // M - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_MONTH, nNatNum ); - break; - case NF_KEY_MM: // MM - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_MONTH, nNatNum ); - break; - case NF_KEY_MMM: // MMM - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_MONTH_NAME, nNatNum ); - break; - case NF_KEY_MMMM: // MMMM - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_MONTH_NAME, nNatNum ); - break; - case NF_KEY_MMMMM: // MMMMM - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_MONTH_NAME, nNatNum ).at(0); - break; - case NF_KEY_Q: // Q - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_QUARTER, nNatNum ); - break; - case NF_KEY_QQ: // QQ - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_QUARTER, nNatNum ); - break; - case NF_KEY_D: // D - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_DAY, nNatNum ); - break; - case NF_KEY_DD: // DD - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_DAY, nNatNum ); - break; - case NF_KEY_DDD: // DDD - { - if ( bOtherCalendar ) - SwitchToGregorianCalendar( aOrgCalendar, fOrgDateTime ); - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_DAY_NAME, nNatNum ); - if ( bOtherCalendar ) - SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime ); - } - break; - case NF_KEY_DDDD: // DDDD - { - if ( bOtherCalendar ) - SwitchToGregorianCalendar( aOrgCalendar, fOrgDateTime ); - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_DAY_NAME, nNatNum ); - if ( bOtherCalendar ) - SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime ); - } - break; - case NF_KEY_YY: // YY - { - if ( bOtherCalendar ) - SwitchToGregorianCalendar( aOrgCalendar, fOrgDateTime ); - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_YEAR, nNatNum ); - if ( bOtherCalendar ) - SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime ); - } - break; - case NF_KEY_YYYY: // YYYY - { - if ( bOtherCalendar ) - SwitchToGregorianCalendar( aOrgCalendar, fOrgDateTime ); - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_YEAR, nNatNum ); - if ( bOtherCalendar ) - SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime ); - } - break; - case NF_KEY_EC: // E - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_YEAR, nNatNum ); - break; - case NF_KEY_EEC: // EE - case NF_KEY_R: // R - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_YEAR, nNatNum ); - break; - case NF_KEY_NN: // NN - case NF_KEY_AAA: // AAA - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_DAY_NAME, nNatNum ); - break; - case NF_KEY_NNN: // NNN - case NF_KEY_AAAA: // AAAA - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_DAY_NAME, nNatNum ); - break; - case NF_KEY_NNNN: // NNNN - { - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_DAY_NAME, nNatNum ); - OutString += pFormatter->getLongDateDayOfWeekSep(); - } - break; - case NF_KEY_WW : // WW - { - sal_Int16 nVal = rCal->getValue( CalendarFieldIndex::WEEK_OF_YEAR ); - OutString += ImpIntToString( nIx, nVal ); - } - break; - case NF_KEY_G: // G - ImpAppendEraG( OutString, nNatNum ); - break; - case NF_KEY_GG: // GG - OutString += rCal->getDisplayString( - CalendarDisplayCode::SHORT_ERA, nNatNum ); - break; - case NF_KEY_GGG: // GGG - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_ERA, nNatNum ); - break; - case NF_KEY_RR: // RR => GGGEE - OutString += rCal->getDisplayString( - CalendarDisplayCode::LONG_YEAR_AND_ERA, nNatNum ); - break; - } - } - return bRes; -} - -bool SvNumberformat::ImpGetNumberOutput(double fNumber, - sal_uInt16 nIx, - String& OutString) -{ - bool bRes = false; - bool bSign; - if (fNumber < 0.0) - { - if (nIx == 0) // nicht in hinteren - bSign = true; // Formaten - else - bSign = false; - fNumber = -fNumber; - } - else - { - bSign = false; - if ( fabs( fNumber ) < 0.0 ) - fNumber = -fNumber; // yes, -0.0 is possible, eliminate '-' - } - const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info(); - if (rInfo.eScannedType == NUMBERFORMAT_PERCENT) - { - if (fNumber < _D_MAX_D_BY_100) - fNumber *= 100.0; - else - { - OutString = rScanPtr->GetErrorString(); - return false; - } - } - sal_uInt16 i, j; - uint16_t k; - String sStr; - long nPrecExp; - bool bInteger = false; - if ( rInfo.nThousand != FLAG_STANDARD_IN_FORMAT ) - { // special formatting only if no GENERAL keyword in format code - const sal_uInt16 nThousand = rInfo.nThousand; - for (i = 0; i < nThousand; i++) - { - if (fNumber > _D_MIN_M_BY_1000) - fNumber /= 1000.0; - else - fNumber = 0.0; - } - if (fNumber > 0.0) - nPrecExp = GetPrecExp( fNumber ); - else - nPrecExp = 0; - if (rInfo.nCntPost) // decimal places - { - if (rInfo.nCntPost + nPrecExp > 15 && nPrecExp < 15) - { - sStr = doubleToUString( fNumber, - rtl_math_StringFormat_F, 15-nPrecExp, L'.'); - for (long l = 15-nPrecExp; l < (long) rInfo.nCntPost; l++) - sStr += L'0'; - } - else - sStr = doubleToUString( fNumber, - rtl_math_StringFormat_F, rInfo.nCntPost, L'.' ); - EraseLeadingChars(sStr, L'0'); // leading zeros removed - } - else if (fNumber == 0.0) // Null - { - } - else // Integer - { - sStr = doubleToUString( fNumber, - rtl_math_StringFormat_F, 0, L'.'); - EraseLeadingChars(sStr, L'0'); // leading zeros removed - } - uint16_t nPoint = sStr.find( L'.' ); - if ( nPoint != STRING_NOTFOUND ) - { - const sal_Unicode* p = sStr.data() + nPoint; - while ( *++p == L'0' ) - ; - if ( !*p ) - bInteger = true; - sStr.erase( nPoint, 1 ); // . remove - } - if (bSign && - (sStr.size() == 0 || std::count(sStr.begin(), sStr.end(), L'0') == sStr.size()+1)) // nur 00000 - bSign = false; // not -0.00 - } // End of != FLAG_STANDARD_IN_FORMAT - - // from back to front - // edit: - k = sStr.size(); // after last digit - j = NumFor[nIx].GetnAnz()-1; // last Symbol - // decimal places: - if (rInfo.nCntPost > 0) - { - bool bTrailing = true; // whether end zeros? - bool bFilled = false; // if refilled ? - short nType; - while (j > 0 && // - (nType = rInfo.nTypeArray[j]) != NF_SYMBOLTYPE_DECSEP) - { - switch ( nType ) - { - case NF_SYMBOLTYPE_STAR: - if( bStarFlag ) - { - sStr.insert( k /*++*/, 1, (sal_Unicode) 0x1B ); - sStr.insert(k, 1, rInfo.sStrArray[j].at(1)); - bRes = true; - } - break; - case NF_SYMBOLTYPE_BLANK: - /*k = */ InsertBlanks( sStr,k,rInfo.sStrArray[j].at(0) ); - break; - case NF_SYMBOLTYPE_STRING: - case NF_SYMBOLTYPE_CURRENCY: - case NF_SYMBOLTYPE_PERCENT: - sStr.insert(k, rInfo.sStrArray[j]); - break; - case NF_SYMBOLTYPE_THSEP: - if (rInfo.nThousand == 0) - sStr.insert(k, rInfo.sStrArray[j]); - break; - case NF_SYMBOLTYPE_DIGIT: - { - const String& rStr = rInfo.sStrArray[j]; - const sal_Unicode* p1 = rStr.data(); - const sal_Unicode* p = p1 + rStr.size(); - while ( p1 < p-- ) - { - const sal_Unicode c = *p; - k--; - if ( sStr.at(k) != L'0' ) - bTrailing = false; - if (bTrailing) - { - if ( c == L'0' ) - bFilled = true; - else if ( c == L'-' ) - { - if ( bInteger ) - sStr[k] = L'-'; - bFilled = true; - } - else if ( c == L'?' ) - { - sStr[k] = L' '; - bFilled = true; - } - else if ( !bFilled ) // # - sStr.erase(k,1); - } - } // of for - } // of case digi - break; - case NF_KEY_CCC: // CCC-Currency - sStr.insert(k, rScanPtr->GetCurAbbrev()); - break; - case NF_KEY_GENERAL: // Standard im String - { - String sNum; - ImpGetOutputStandard(fNumber, sNum); - EraseLeadingChars(sNum, L'-'); - sStr.insert(k, sNum); - } - break; - default: - break; - } // of switch - j--; - } // of while - } // of decimal point - - bRes |= ImpNumberFillWithThousands(sStr, fNumber, k, j, nIx, // fill up with if necessary . - rInfo.nCntPre); - if ( rInfo.nCntPost > 0 ) - { - const String& rDecSep = pFormatter->GetNumDecimalSep(); - uint16_t nLen = rDecSep.size(); - if ( sStr.size() > nLen && sStr.substr( sStr.size() - nLen, nLen ) == rDecSep ) - sStr.erase( sStr.size() - nLen ); // no decimals => strip DecSep - } - if (bSign) - sStr.insert(0, 1, L'-'); - ImpTransliterate( sStr, NumFor[nIx].GetNatNum() ); - OutString = sStr; - return bRes; -} - -bool SvNumberformat::ImpNumberFillWithThousands( - String& sStr, // number string - double& rNumber, // number - uint16_t k, // position within string - sal_uInt16 j, // symbol index within format code - sal_uInt16 nIx, // subformat index - sal_uInt16 nDigCnt) // count of integer digits in format -{ - bool bRes = false; - uint16_t nLeadingStringChars = 0; // inserted StringChars before number - uint16_t nDigitCount = 0; // count of integer digits from the right - bool bStop = false; - const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info(); - // no normal thousands separators if number divided by thousands - bool bDoThousands = (rInfo.nThousand == 0); - DigitGroupingIterator aGrouping(pFormatter->getDigitGrouping()); - while (!bStop) // backwards - { - if (j == 0) - bStop = true; - switch (rInfo.nTypeArray[j]) - { - case NF_SYMBOLTYPE_DECSEP: - aGrouping.reset(); - // fall thru - case NF_SYMBOLTYPE_STRING: - case NF_SYMBOLTYPE_CURRENCY: - case NF_SYMBOLTYPE_PERCENT: - sStr.insert(k, rInfo.sStrArray[j]); - if ( k == 0 ) - nLeadingStringChars = - nLeadingStringChars + rInfo.sStrArray[j].size(); - break; - case NF_SYMBOLTYPE_STAR: - if( bStarFlag ) - { - sStr.insert( k/*++*/, 1, (sal_Unicode) 0x1B ); - sStr.insert(k, 1, rInfo.sStrArray[j].at(1)); - bRes = true; - } - break; - case NF_SYMBOLTYPE_BLANK: - /*k = */ InsertBlanks( sStr,k,rInfo.sStrArray[j].at(0) ); - break; - case NF_SYMBOLTYPE_THSEP: - { - // #i7284# #102685# Insert separator also if number is divided - // by thousands and the separator is specified somewhere in - // between and not only at the end. - // #i12596# But do not insert if it's a parenthesized negative - // format like (#,) - // In fact, do not insert if divided and regex [0#,],[^0#] and - // no other digit symbol follows (which was already detected - // during scan of format code, otherwise there would be no - // division), else do insert. Same in ImpNumberFill() below. - if ( !bDoThousands && j < NumFor[nIx].GetnAnz()-1 ) - bDoThousands = ((j == 0) || - (rInfo.nTypeArray[j-1] != NF_SYMBOLTYPE_DIGIT && - rInfo.nTypeArray[j-1] != NF_SYMBOLTYPE_THSEP) || - (rInfo.nTypeArray[j+1] == NF_SYMBOLTYPE_DIGIT)); - if ( bDoThousands ) - { - if (k > 0) - sStr.insert(k, rInfo.sStrArray[j]); - else if (nDigitCount < nDigCnt) - { - // Leading '#' displays nothing (e.g. no leading - // separator for numbers <1000 with #,##0 format). - // Leading '?' displays blank. - // Everything else, including nothing, displays the - // separator. - sal_Unicode cLeader = 0; - if (j > 0 && rInfo.nTypeArray[j-1] == NF_SYMBOLTYPE_DIGIT) - { - const String& rStr = rInfo.sStrArray[j-1]; - uint16_t nLen = rStr.size(); - if (nLen) - cLeader = rStr.at(nLen-1); - } - switch (cLeader) - { - case L'#': - ; // nothing - break; - case L'?': - // erAck: 2008-04-03T16:24+0200 - // Actually this currently isn't executed - // because the format scanner in the context of - // "?," doesn't generate a group separator but - // a literal ',' character instead that is - // inserted unconditionally. Should be changed - // on some occasion. - sStr.insert(k, 1, L' '); - break; - default: - sStr.insert(k, rInfo.sStrArray[j]); - } - } - aGrouping.advance(); - } - } - break; - case NF_SYMBOLTYPE_DIGIT: - { - const String& rStr = rInfo.sStrArray[j]; - const sal_Unicode* p1 = rStr.data(); - const sal_Unicode* p = p1 + rStr.size(); - while ( p1 < p-- ) - { - nDigitCount++; - if (k > 0) - k--; - else - { - switch (*p) - { - case L'0': - sStr.insert(0, 1, L'0'); - break; - case L'?': - sStr.insert(0, 1, L' '); - break; - } - } - if (nDigitCount == nDigCnt && k > 0) - { // more digits than specified - ImpDigitFill(sStr, 0, k, nIx, nDigitCount, aGrouping); - } - } - } - break; - case NF_KEY_CCC: // CCC currency - sStr.insert(k, rScanPtr->GetCurAbbrev()); - break; - case NF_KEY_GENERAL: // "General" in string - { - String sNum; - ImpGetOutputStandard(rNumber, sNum); - EraseLeadingChars(sNum, L'-'); - sStr.insert(k, sNum); - } - break; - - default: - break; - } // switch - j--; // next format code string - } // while - k = k + nLeadingStringChars; // MSC converts += to int and then warns, so ... - if (k > nLeadingStringChars) - ImpDigitFill(sStr, nLeadingStringChars, k, nIx, nDigitCount, aGrouping); - return bRes; -} - -void SvNumberformat::ImpDigitFill( - String& sStr, // number string - uint16_t nStart, // start of digits - uint16_t& k, // position within string - sal_uInt16 nIx, // subformat index - uint16_t & nDigitCount, // count of integer digits from the right so far - DigitGroupingIterator & rGrouping ) // current grouping -{ - if (NumFor[nIx].Info().bThousand) // only if grouping - { // fill in separators - const String& rThousandSep = pFormatter->GetNumThousandSep(); - while (k > nStart) - { - if (nDigitCount == rGrouping.getPos()) - { - sStr.insert(k, rThousandSep); - rGrouping.advance(); - } - nDigitCount++; - k--; - } - } - else // simply skip - k = nStart; -} - -bool SvNumberformat::ImpNumberFill( String& sStr, // number string - double& rNumber, // number for "General" format - uint16_t& k, // position within string - sal_uInt16& j, // symbol index within format code - sal_uInt16 nIx, // subformat index - short eSymbolType ) // type of stop condition -{ - bool bRes = false; - k = sStr.size(); // behind last digit - const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info(); - // no normal thousands separators if number divided by thousands - bool bDoThousands = (rInfo.nThousand == 0); - short nType; - while (j > 0 && (nType = rInfo.nTypeArray[j]) != eSymbolType ) - { // rueckwaerts: - switch ( nType ) - { - case NF_SYMBOLTYPE_STAR: - if( bStarFlag ) - { - sStr.insert( k++, 1, sal_Unicode(0x1B) ); - sStr.insert(k, 1, rInfo.sStrArray[j].at(1)); - bRes = true; - } - break; - case NF_SYMBOLTYPE_BLANK: - k = InsertBlanks( sStr,k,rInfo.sStrArray[j].at(0) ); - break; - case NF_SYMBOLTYPE_THSEP: - { - // Same as in ImpNumberFillWithThousands() above, do not insert - // if divided and regex [0#,],[^0#] and no other digit symbol - // follows (which was already detected during scan of format - // code, otherwise there would be no division), else do insert. - if ( !bDoThousands && j < NumFor[nIx].GetnAnz()-1 ) - bDoThousands = ((j == 0) || - (rInfo.nTypeArray[j-1] != NF_SYMBOLTYPE_DIGIT && - rInfo.nTypeArray[j-1] != NF_SYMBOLTYPE_THSEP) || - (rInfo.nTypeArray[j+1] == NF_SYMBOLTYPE_DIGIT)); - if ( bDoThousands && k > 0 ) - { - sStr.insert(k, rInfo.sStrArray[j]); - } - } - break; - case NF_SYMBOLTYPE_DIGIT: - { - const String& rStr = rInfo.sStrArray[j]; - const sal_Unicode* p1 = rStr.data(); - const sal_Unicode* p = p1 + rStr.size(); - while ( p1 < p-- ) - { - if (k > 0) - k--; - else - { - switch (*p) - { - case L'0': - sStr.insert(0, 1, L'0'); - break; - case L'?': - sStr.insert(0, 1, L' '); - break; - } - } - } - } - break; - case NF_KEY_CCC: // CCC-Waehrung - sStr.insert(k, rScanPtr->GetCurAbbrev()); - break; - case NF_KEY_GENERAL: // Standard im String - { - String sNum; - ImpGetOutputStandard(rNumber, sNum); - EraseLeadingChars(sNum, L'-'); // Vorzeichen weg!! - sStr.insert(k, sNum); - } - break; - - default: - sStr.insert(k, rInfo.sStrArray[j]); - break; - } // of switch - j--; // naechster String - } // of while - return bRes; -} - -void SvNumberformat::GetFormatSpecialInfo(bool& bThousand, - bool& IsRed, - sal_uInt16& nPrecision, - sal_uInt16& nAnzLeading) const -{ - // as before: take info from nNumFor=0 for whole format (for dialog etc.) - - short nDummyType; - GetNumForInfo( 0, nDummyType, bThousand, nPrecision, nAnzLeading ); - - IsRed = false; -} - -void SvNumberformat::GetNumForInfo( sal_uInt16 nNumFor, short& rScannedType, - bool& bThousand, sal_uInt16& nPrecision, sal_uInt16& nAnzLeading ) const -{ - // take info from a specified sub-format (for XML export) - - if ( nNumFor > 3 ) - return; // invalid - - const ImpSvNumberformatInfo& rInfo = NumFor[nNumFor].Info(); - rScannedType = rInfo.eScannedType; - bThousand = rInfo.bThousand; - nPrecision = rInfo.nCntPost; - if (bStandard && rInfo.eScannedType == NUMBERFORMAT_NUMBER) - // StandardFormat - nAnzLeading = 1; - else - { - nAnzLeading = 0; - bool bStop = false; - sal_uInt16 i = 0; - const sal_uInt16 nAnz = NumFor[nNumFor].GetnAnz(); - while (!bStop && i < nAnz) - { - short nType = rInfo.nTypeArray[i]; - if ( nType == NF_SYMBOLTYPE_DIGIT) - { - const sal_Unicode* p = rInfo.sStrArray[i].data(); - while ( *p == L'#' ) - p++; - while ( *p++ == L'0' ) - nAnzLeading++; - } - else if (nType == NF_SYMBOLTYPE_DECSEP || nType == NF_SYMBOLTYPE_EXP) - bStop = true; - i++; - } - } -} - -const String* SvNumberformat::GetNumForString( sal_uInt16 nNumFor, sal_uInt16 nPos, - bool bString /* = false */ ) const -{ - if ( nNumFor > 3 ) - return NULL; - sal_uInt16 nAnz = NumFor[nNumFor].GetnAnz(); - if ( !nAnz ) - return NULL; - if ( nPos == 0xFFFF ) - { - nPos = nAnz - 1; - if ( bString ) - { // rueckwaerts - short* pType = NumFor[nNumFor].Info().nTypeArray + nPos; - while ( nPos > 0 && (*pType != NF_SYMBOLTYPE_STRING) && - (*pType != NF_SYMBOLTYPE_CURRENCY) ) - { - pType--; - nPos--; - } - if ( (*pType != NF_SYMBOLTYPE_STRING) && (*pType != NF_SYMBOLTYPE_CURRENCY) ) - return NULL; - } - } - else if ( nPos > nAnz - 1 ) - return NULL; - else if ( bString ) - { // vorwaerts - short* pType = NumFor[nNumFor].Info().nTypeArray + nPos; - while ( nPos < nAnz && (*pType != NF_SYMBOLTYPE_STRING) && - (*pType != NF_SYMBOLTYPE_CURRENCY) ) - { - pType++; - nPos++; - } - if ( nPos >= nAnz || ((*pType != NF_SYMBOLTYPE_STRING) && - (*pType != NF_SYMBOLTYPE_CURRENCY)) ) - return NULL; - } - return &NumFor[nNumFor].Info().sStrArray[nPos]; -} - - -short SvNumberformat::GetNumForType( sal_uInt16 nNumFor, sal_uInt16 nPos, - bool bString /* = false */ ) const -{ - if ( nNumFor > 3 ) - return 0; - sal_uInt16 nAnz = NumFor[nNumFor].GetnAnz(); - if ( !nAnz ) - return 0; - if ( nPos == 0xFFFF ) - { - nPos = nAnz - 1; - if ( bString ) - { // rueckwaerts - short* pType = NumFor[nNumFor].Info().nTypeArray + nPos; - while ( nPos > 0 && (*pType != NF_SYMBOLTYPE_STRING) && - (*pType != NF_SYMBOLTYPE_CURRENCY) ) - { - pType--; - nPos--; - } - if ( (*pType != NF_SYMBOLTYPE_STRING) && (*pType != NF_SYMBOLTYPE_CURRENCY) ) - return 0; - } - } - else if ( nPos > nAnz - 1 ) - return 0; - else if ( bString ) - { // vorwaerts - short* pType = NumFor[nNumFor].Info().nTypeArray + nPos; - while ( nPos < nAnz && (*pType != NF_SYMBOLTYPE_STRING) && - (*pType != NF_SYMBOLTYPE_CURRENCY) ) - { - pType++; - nPos++; - } - if ( (*pType != NF_SYMBOLTYPE_STRING) && (*pType != NF_SYMBOLTYPE_CURRENCY) ) - return 0; - } - return NumFor[nNumFor].Info().nTypeArray[nPos]; -} - - -bool SvNumberformat::IsNegativeWithoutSign() const -{ - if ( IsNegativeRealNegative() ) - { - const String* pStr = GetNumForString( 1, 0, true ); - if ( pStr ) - return !HasStringNegativeSign( *pStr ); - } - return false; -} - - -DateFormat SvNumberformat::GetDateOrder() const -{ - if ( (eType & NUMBERFORMAT_DATE) == NUMBERFORMAT_DATE ) - { - short const * const pType = NumFor[0].Info().nTypeArray; - sal_uInt16 nAnz = NumFor[0].GetnAnz(); - for ( sal_uInt16 j=0; jgetDateFormat(); -} - - -sal_uInt32 SvNumberformat::GetExactDateOrder() const -{ - sal_uInt32 nRet = 0; - if ( (eType & NUMBERFORMAT_DATE) != NUMBERFORMAT_DATE ) - { - return nRet; - } - short const * const pType = NumFor[0].Info().nTypeArray; - sal_uInt16 nAnz = NumFor[0].GetnAnz(); - int nShift = 0; - for ( sal_uInt16 j=0; j"; - break; - case NUMBERFORMAT_OP_LT : - rStr = L"[<"; - break; - case NUMBERFORMAT_OP_LE : - rStr = L"[<="; - break; - case NUMBERFORMAT_OP_GT : - rStr = L"[>"; - break; - case NUMBERFORMAT_OP_GE : - rStr = L"[>="; - break; - default: - break; - } - rStr += String( doubleToUString( fLimit, - rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, - rDecSep.at(0), true)); - rStr += L']'; - } -} - - -String SvNumberformat::ImpGetNatNumString( const SvNumberNatNum& rNum, - sal_Int32 nVal, sal_uInt16 nMinDigits ) const -{ - String aStr; - if ( nMinDigits ) - { - if ( nMinDigits == 2 ) - { // speed up the most common case - if ( 0 <= nVal && nVal < 10 ) - { - wchar_t str[3]; - swprintf(str, sizeof(str) / sizeof(wchar_t), L"0%d", nVal); - aStr = str; - } - else - aStr = std::to_wstring( nVal ); - } - else - { - String aValStr( std::to_wstring( nVal ) ); - if ( aValStr.size() >= nMinDigits ) - aStr = aValStr; - else - { - aStr = L""; - aStr.insert(0, nMinDigits - aValStr.size(), L'0'); - aStr += aValStr; - } - } - } - else - aStr = std::to_wstring( nVal ); - ImpTransliterate( aStr, rNum ); - return aStr; -} - - -bool SvNumberformat::HasStringNegativeSign( const String& rStr ) -{ - // for Sign must be '-' at the beginning or at the end of the substring (blanks ignored) - uint16_t nLen = rStr.size(); - if ( !nLen ) - return false; - const sal_Unicode* const pBeg = rStr.data(); - const sal_Unicode* const pEnd = pBeg + nLen; - const sal_Unicode* p = pBeg; - do - { // beginning - if ( *p == L'-' ) - return true; - } while ( *p == L' ' && ++p < pEnd ); - p = pEnd - 1; - do - { // end - if ( *p == L'-' ) - return true; - } while ( *p == L' ' && pBeg < --p ); - return false; -} - - -// static -void SvNumberformat::SetComment( const String& rStr, String& rFormat, - String& rComment ) -{ - if ( rComment.size() ) - { // Delete old comment from format string - //! not via EraseComment, the comment must match - String aTmp( L"{" ); - aTmp += L' '; - aTmp += rComment; - aTmp += L' '; - aTmp += L'}'; - uint16_t nCom = 0; - do - { - nCom = rFormat.find( aTmp, nCom ); - } while ( (nCom != STRING_NOTFOUND) && (nCom + aTmp.size() != rFormat.size()) ); - if ( nCom != STRING_NOTFOUND ) - rFormat.erase( nCom ); - } - if ( rStr.size() ) - { // put new comment - rFormat += L'{'; - rFormat += L' '; - rFormat += rStr; - rFormat += L' '; - rFormat += L'}'; - rComment = rStr; - } -} - - -// static -void SvNumberformat::EraseCommentBraces( String& rStr ) -{ - uint16_t nLen = rStr.size(); - if ( nLen && rStr.at(0) == L'{' ) - { - rStr.erase( 0, 1 ); - --nLen; - } - if ( nLen && rStr.at(0) == L' ' ) - { - rStr.erase( 0, 1 ); - --nLen; - } - if ( nLen && rStr.at( nLen-1 ) == L'}' ) - rStr.erase( --nLen, 1 ); - if ( nLen && rStr.at( nLen-1 ) == L' ' ) - rStr.erase( --nLen, 1 ); -} - - -// static -void SvNumberformat::EraseComment( String& rStr ) -{ - const sal_Unicode* p = rStr.data(); - bool bInString = false; - bool bEscaped = false; - bool bFound = false; - uint16_t nPos = 0; - while ( !bFound && *p ) - { - switch ( *p ) - { - case L'\\' : - bEscaped = !bEscaped; - break; - case L'\"' : - if ( !bEscaped ) - bInString = !bInString; - break; - case L'{' : - if ( !bEscaped && !bInString ) - { - bFound = true; - nPos = (uint16_t)(p - rStr.data()); - } - break; - } - if ( bEscaped && *p != L'\\' ) - bEscaped = false; - ++p; - } - if ( bFound ) - rStr.erase( nPos ); -} - - -// static -bool SvNumberformat::IsInQuote( const String& rStr, uint16_t nPos, - sal_Unicode cQuote, sal_Unicode cEscIn, sal_Unicode cEscOut ) -{ - uint16_t nLen = rStr.size(); - if ( nPos >= nLen ) - return false; - const sal_Unicode* p0 = rStr.data(); - const sal_Unicode* p = p0; - const sal_Unicode* p1 = p0 + nPos; - bool bQuoted = false; - while ( p <= p1 ) - { - if ( *p == cQuote ) - { - if ( p == p0 ) - bQuoted = true; - else if ( bQuoted ) - { - if ( *(p-1) != cEscIn ) - bQuoted = false; - } - else - { - if ( *(p-1) != cEscOut ) - bQuoted = true; - } - } - p++; - } - return bQuoted; -} - - -// static -uint16_t SvNumberformat::GetQuoteEnd( const String& rStr, uint16_t nPos, - sal_Unicode cQuote, sal_Unicode cEscIn, sal_Unicode cEscOut ) -{ - uint16_t nLen = rStr.size(); - if ( nPos >= nLen ) - return STRING_NOTFOUND; - if ( !IsInQuote( rStr, nPos, cQuote, cEscIn, cEscOut ) ) - { - if ( rStr.at( nPos ) == cQuote ) - return nPos; // closing quote - return STRING_NOTFOUND; - } - const sal_Unicode* p0 = rStr.data(); - const sal_Unicode* p = p0 + nPos; - const sal_Unicode* p1 = p0 + nLen; - while ( p < p1 ) - { - if ( *p == cQuote && p > p0 && *(p-1) != cEscIn ) - return (uint16_t)(p - p0); - p++; - } - return nLen; // String end -} - - -sal_uInt16 SvNumberformat::ImpGetNumForStringElementCount( sal_uInt16 nNumFor ) const -{ - sal_uInt16 nCnt = 0; - sal_uInt16 nAnz = NumFor[nNumFor].GetnAnz(); - short const * const pType = NumFor[nNumFor].Info().nTypeArray; - for ( sal_uInt16 j=0; j; + secret_type.default_provider = "config"; + ExtensionUtil::RegisterSecretType(instance, secret_type); + + // Generic Bearer config provider + CreateSecretFunction config_fun = {GENERIC_BEARER_TYPE, "config", CreateBearerSecretFromConfig}; + config_fun.named_parameters["token"] = LogicalType::VARCHAR; + ExtensionUtil::RegisterFunction(instance, config_fun); + + // HuggingFace secret + SecretType secret_type_hf; + secret_type_hf.name = HUGGINGFACE_TYPE; + secret_type_hf.deserializer = KeyValueSecret::Deserialize; + secret_type_hf.default_provider = "config"; + ExtensionUtil::RegisterSecretType(instance, secret_type_hf); + + // Huggingface config provider + CreateSecretFunction hf_config_fun = {HUGGINGFACE_TYPE, "config", CreateBearerSecretFromConfig}; + hf_config_fun.named_parameters["token"] = LogicalType::VARCHAR; + ExtensionUtil::RegisterFunction(instance, hf_config_fun); + + // Huggingface credential_chain provider + CreateSecretFunction hf_cred_fun = {HUGGINGFACE_TYPE, "credential_chain", + CreateHuggingFaceSecretFromCredentialChain}; + ExtensionUtil::RegisterFunction(instance, hf_cred_fun); +} + +unique_ptr CreateBearerTokenFunctions::CreateSecretFunctionInternal(ClientContext &context, + CreateSecretInput &input, + const string &token) { + // Set scope to user provided scope or the default + auto scope = input.scope; + if (scope.empty()) { + if (input.type == GENERIC_BEARER_TYPE) { + scope.push_back(""); + } else if (input.type == HUGGINGFACE_TYPE) { + scope.push_back("hf://"); + } else { + throw InternalException("Unknown secret type found in httpfs extension: '%s'", input.type); + } + } + auto return_value = make_uniq(scope, input.type, input.provider, input.name); + + //! Set key value map + return_value->secret_map["token"] = token; + + //! Set redact keys + return_value->redact_keys = {"token"}; + + return std::move(return_value); +} + +unique_ptr CreateBearerTokenFunctions::CreateBearerSecretFromConfig(ClientContext &context, + CreateSecretInput &input) { + string token; + + auto token_input = input.options.find("token"); + for (const auto &named_param : input.options) { + auto lower_name = StringUtil::Lower(named_param.first); + if (lower_name == "token") { + token = named_param.second.ToString(); + } + } + + return CreateSecretFunctionInternal(context, input, token); +} + +static string TryReadTokenFile(const string &token_path, const string error_source_message, + bool fail_on_exception = true) { + try { + LocalFileSystem fs; + auto handle = fs.OpenFile(token_path, {FileOpenFlags::FILE_FLAGS_READ}); + return handle->ReadLine(); + } catch (std::exception &ex) { + if (!fail_on_exception) { + return ""; + } + ErrorData error(ex); + throw IOException("Failed to read token path '%s'%s. (error: %s)", token_path, error_source_message, + error.RawMessage()); + } +} + +unique_ptr +CreateBearerTokenFunctions::CreateHuggingFaceSecretFromCredentialChain(ClientContext &context, + CreateSecretInput &input) { + // Step 1: Try the ENV variable HF_TOKEN + const char *hf_token_env = std::getenv("HF_TOKEN"); + if (hf_token_env) { + return CreateSecretFunctionInternal(context, input, hf_token_env); + } + // Step 2: Try the ENV variable HF_TOKEN_PATH + const char *hf_token_path_env = std::getenv("HF_TOKEN_PATH"); + if (hf_token_path_env) { + auto token = TryReadTokenFile(hf_token_path_env, " fetched from HF_TOKEN_PATH env variable"); + return CreateSecretFunctionInternal(context, input, token); + } + + // Step 3: Try the path $HF_HOME/token + const char *hf_home_env = std::getenv("HF_HOME"); + if (hf_home_env) { + auto token_path = LocalFileSystem().JoinPath(hf_home_env, "token"); + auto token = TryReadTokenFile(token_path, " constructed using the HF_HOME variable: '$HF_HOME/token'"); + return CreateSecretFunctionInternal(context, input, token); + } + + // Step 4: Check the default path + auto token = TryReadTokenFile("~/.cache/huggingface/token", "", false); + return CreateSecretFunctionInternal(context, input, token); +} } // namespace duckdb diff --git a/extension/httpfs/hffs.cpp b/extension/httpfs/hffs.cpp new file mode 100644 index 00000000000..ebc01335642 --- /dev/null +++ b/extension/httpfs/hffs.cpp @@ -0,0 +1,418 @@ +#include "hffs.hpp" + +#include "duckdb/common/atomic.hpp" +#include "duckdb/common/exception/http_exception.hpp" +#include "duckdb/common/file_opener.hpp" +#include "duckdb/common/http_state.hpp" +#include "duckdb/common/types/hash.hpp" +#include "duckdb/main/database.hpp" +#include "duckdb/main/secret/secret_manager.hpp" +#include "duckdb/function/scalar/string_functions.hpp" + +#include +#include + +#define CPPHTTPLIB_OPENSSL_SUPPORT +#include "httplib.hpp" + +#include + +namespace duckdb { + +static duckdb::unique_ptr initialize_http_headers(HeaderMap &header_map) { + auto headers = make_uniq(); + for (auto &entry : header_map) { + headers->insert(entry); + } + return headers; +} + +HuggingFaceFileSystem::~HuggingFaceFileSystem() { +} + +static string ParseNextUrlFromLinkHeader(const string &link_header_content) { + auto split_outer = StringUtil::Split(link_header_content, ','); + for (auto &split : split_outer) { + auto split_inner = StringUtil::Split(split, ';'); + if (split_inner.size() != 2) { + throw IOException("Unexpected link header for huggingface pagination: %s", link_header_content); + } + + StringUtil::Trim(split_inner[1]); + if (split_inner[1] == "rel=\"next\"") { + StringUtil::Trim(split_inner[0]); + + if (!StringUtil::StartsWith(split_inner[0], "<") || !StringUtil::EndsWith(split_inner[0], ">")) { + throw IOException("Unexpected link header for huggingface pagination: %s", link_header_content); + } + + return split_inner[0].substr(1, split_inner[0].size() - 2); + } + } + + throw IOException("Failed to parse Link header for paginated response, pagination support"); +} + +HFFileHandle::~HFFileHandle() {}; + +void HFFileHandle::InitializeClient(optional_ptr client_context) { + http_client = HTTPFileSystem::GetClient(this->http_params, parsed_url.endpoint.c_str(), this); +} + +string HuggingFaceFileSystem::ListHFRequest(ParsedHFUrl &url, HTTPParams &http_params, string &next_page_url, + optional_ptr state) { + HeaderMap header_map; + auto headers = initialize_http_headers(header_map); + string link_header_result; + + auto client = HTTPFileSystem::GetClient(http_params, url.endpoint.c_str(), nullptr); + std::stringstream response; + + std::function request([&]() { + if (state) { + state->get_count++; + } + + return client->Get( + next_page_url.c_str(), *headers, + [&](const duckdb_httplib_openssl::Response &response) { + if (response.status >= 400) { + throw HTTPException(response, "HTTP GET error on '%s' (HTTP %d)", next_page_url, response.status); + } + auto link_res = response.headers.find("Link"); + if (link_res != response.headers.end()) { + link_header_result = link_res->second; + } + return true; + }, + [&](const char *data, size_t data_length) { + if (state) { + state->total_bytes_received += data_length; + } + response << string(data, data_length); + return true; + }); + }); + + auto res = RunRequestWithRetry(request, next_page_url, "GET", http_params, nullptr); + + if (res->code != 200) { + throw IOException(res->error + " error for HTTP GET to '" + next_page_url + "'"); + } + + if (!link_header_result.empty()) { + next_page_url = ParseNextUrlFromLinkHeader(link_header_result); + } else { + next_page_url = ""; + } + + return response.str(); +} + +static bool Match(vector::const_iterator key, vector::const_iterator key_end, + vector::const_iterator pattern, vector::const_iterator pattern_end) { + + while (key != key_end && pattern != pattern_end) { + if (*pattern == "**") { + if (std::next(pattern) == pattern_end) { + return true; + } + while (key != key_end) { + if (Match(key, key_end, std::next(pattern), pattern_end)) { + return true; + } + key++; + } + return false; + } + if (!LikeFun::Glob(key->data(), key->length(), pattern->data(), pattern->length())) { + return false; + } + key++; + pattern++; + } + return key == key_end && pattern == pattern_end; +} + +void ParseListResult(string &input, vector &files, vector &directories) { + enum parse_entry { FILE, DIR, UNKNOWN }; + idx_t idx = 0; + idx_t nested = 0; + bool found_path; + parse_entry type; + string current_string; +base: + found_path = false; + type = parse_entry::UNKNOWN; + for (; idx < input.size(); idx++) { + if (input[idx] == '{') { + idx++; + goto entry; + } + } + goto end; +entry: + while (idx < input.size()) { + if (input[idx] == '}') { + if (nested) { + idx++; + nested--; + continue; + } else if (!found_path || type == parse_entry::UNKNOWN) { + throw IOException("Failed to parse list result"); + } else if (type == parse_entry::FILE) { + files.push_back("/" + current_string); + } else { + directories.push_back("/" + current_string); + } + current_string = ""; + idx++; + goto base; + } else if (input[idx] == '{') { + nested++; + idx++; + } else if (strncmp(input.c_str() + idx, "\"type\":\"directory\"", 18) == 0) { + type = parse_entry::DIR; + idx += 18; + } else if (strncmp(input.c_str() + idx, "\"type\":\"file\"", 13) == 0) { + type = parse_entry::FILE; + idx += 13; + } else if (strncmp(input.c_str() + idx, "\"path\":\"", 8) == 0) { + idx += 8; + found_path = true; + goto pathname; + } else { + idx++; + } + } + goto end; +pathname: + while (idx < input.size()) { + // Handle escaped quote in url + if (input[idx] == '\\' && idx + 1 < input.size() && input[idx] == '\"') { + current_string += '\"'; + idx += 2; + } else if (input[idx] == '\"') { + idx++; + goto entry; + } else { + current_string += input[idx]; + idx++; + } + } +end: + return; +} + +// Some valid example Urls: +// - hf://datasets/lhoestq/demo1/default/train/0000.parquet +// - hf://datasets/lhoestq/demo1/default/train/*.parquet +// - hf://datasets/lhoestq/demo1/*/train/file_[abc].parquet +// - hf://datasets/lhoestq/demo1/**/train/*.parquet +vector HuggingFaceFileSystem::Glob(const string &path, FileOpener *opener) { + // Ensure the glob pattern is a valid HF url + auto parsed_glob_url = HFUrlParse(path); + auto first_wildcard_pos = parsed_glob_url.path.find_first_of("*[\\"); + + if (first_wildcard_pos == string::npos) { + return {path}; + } + + string shared_path = parsed_glob_url.path.substr(0, first_wildcard_pos); + auto last_path_slash = shared_path.find_last_of('/', first_wildcard_pos); + + // trim the final + if (last_path_slash == string::npos) { + // Root path + shared_path = ""; + } else { + shared_path = shared_path.substr(0, last_path_slash); + } + + auto http_params = HTTPParams::ReadFrom(opener); + SetParams(http_params, path, opener); + auto http_state = HTTPState::TryGetState(opener).get(); + + ParsedHFUrl curr_hf_path = parsed_glob_url; + curr_hf_path.path = shared_path; + + vector files; + vector dirs = {shared_path}; + string next_page_url = ""; + + // Loop over the paths and paginated responses for each path + while (true) { + if (next_page_url.empty() && !dirs.empty()) { + // Done with previous dir, load the next one + curr_hf_path.path = dirs.back(); + dirs.pop_back(); + next_page_url = HuggingFaceFileSystem::GetTreeUrl(curr_hf_path, http_params.hf_max_per_page); + } else if (next_page_url.empty()) { + // No more pages to read, also no more dirs + break; + } + + auto response_str = ListHFRequest(curr_hf_path, http_params, next_page_url, http_state); + ParseListResult(response_str, files, dirs); + } + + vector pattern_splits = StringUtil::Split(parsed_glob_url.path, "/"); + vector result; + for (const auto &file : files) { + + vector file_splits = StringUtil::Split(file, "/"); + bool is_match = Match(file_splits.begin(), file_splits.end(), pattern_splits.begin(), pattern_splits.end()); + + if (is_match) { + curr_hf_path.path = file; + result.push_back(GetHFUrl(curr_hf_path)); + } + } + + // Prune files using match + return result; +} + +unique_ptr HuggingFaceFileSystem::HeadRequest(FileHandle &handle, string hf_url, + HeaderMap header_map) { + auto &hf_handle = handle.Cast(); + auto http_url = HuggingFaceFileSystem::GetFileUrl(hf_handle.parsed_url); + return HTTPFileSystem::HeadRequest(handle, http_url, header_map); +} + +unique_ptr HuggingFaceFileSystem::GetRequest(FileHandle &handle, string s3_url, HeaderMap header_map) { + auto &hf_handle = handle.Cast(); + auto http_url = HuggingFaceFileSystem::GetFileUrl(hf_handle.parsed_url); + return HTTPFileSystem::GetRequest(handle, http_url, header_map); +} + +unique_ptr HuggingFaceFileSystem::GetRangeRequest(FileHandle &handle, string s3_url, + HeaderMap header_map, idx_t file_offset, + char *buffer_out, idx_t buffer_out_len) { + auto &hf_handle = handle.Cast(); + auto http_url = HuggingFaceFileSystem::GetFileUrl(hf_handle.parsed_url); + return HTTPFileSystem::GetRangeRequest(handle, http_url, header_map, file_offset, buffer_out, buffer_out_len); +} + +unique_ptr HuggingFaceFileSystem::CreateHandle(const string &path, FileOpenFlags flags, + optional_ptr opener) { + D_ASSERT(flags.Compression() == FileCompressionType::UNCOMPRESSED); + + auto parsed_url = HFUrlParse(path); + + auto params = HTTPParams::ReadFrom(opener); + SetParams(params, path, opener); + + return duckdb::make_uniq(*this, std::move(parsed_url), path, flags, params); +} + +void HuggingFaceFileSystem::SetParams(HTTPParams ¶ms, const string &path, optional_ptr opener) { + auto secret_manager = FileOpener::TryGetSecretManager(opener); + auto transaction = FileOpener::TryGetCatalogTransaction(opener); + if (secret_manager && transaction) { + auto secret_match = secret_manager->LookupSecret(*transaction, path, "huggingface"); + + if (secret_match.HasMatch()) { + const auto &kv_secret = dynamic_cast(*secret_match.secret_entry->secret); + params.bearer_token = kv_secret.TryGetValue("token", true).ToString(); + } + } +} + +static void ThrowParseError(const string &url) { + throw IOException( + "Failed to parse '%s'. Please format url like: 'hf://datasets/my-username/my-dataset/path/to/file.parquet'", + url); +} + +ParsedHFUrl HuggingFaceFileSystem::HFUrlParse(const string &url) { + ParsedHFUrl result; + + if (!StringUtil::StartsWith(url, "hf://")) { + throw InternalException("Not an hf url"); + } + + size_t last_delim = 5; + size_t curr_delim; + + // Parse Repository type + curr_delim = url.find('/', last_delim); + if (curr_delim == string::npos) { + ThrowParseError(url); + } + result.repo_type = url.substr(last_delim, curr_delim - last_delim); + if (result.repo_type != "datasets" && result.repo_type != "spaces") { + throw IOException( + "Failed to parse: '%s'. Currently DuckDB only supports querying datasets or spaces, so the url should " + "start with 'hf://datasets' or 'hf://spaces'", + url); + } + + last_delim = curr_delim; + + // Parse repository and revision + auto repo_delim = url.find('/', last_delim + 1); + if (repo_delim == string::npos) { + ThrowParseError(url); + } + + auto next_at = url.find('@', repo_delim + 1); + auto next_slash = url.find('/', repo_delim + 1); + + if (next_slash == string::npos) { + ThrowParseError(url); + } + + if (next_at != string::npos && next_at < next_slash) { + result.repository = url.substr(last_delim + 1, next_at - last_delim - 1); + result.revision = url.substr(next_at + 1, next_slash - next_at - 1); + } else { + result.repository = url.substr(last_delim + 1, next_slash - last_delim - 1); + } + last_delim = next_slash; + + // The remainder is the path + result.path = url.substr(last_delim); + + return result; +} + +string HuggingFaceFileSystem::GetHFUrl(const ParsedHFUrl &url) { + if (url.revision == "main") { + return "hf://" + url.repo_type + "/" + url.repository + url.path; + } else { + return "hf://" + url.repo_type + "/" + url.repository + "@" + url.revision + url.path; + } +} + +string HuggingFaceFileSystem::GetTreeUrl(const ParsedHFUrl &url, idx_t limit) { + //! Url format {endpoint}/api/{repo_type}/{repository}/tree/{revision}{encoded_path_in_repo} + string http_url = url.endpoint; + + http_url = JoinPath(http_url, "api"); + http_url = JoinPath(http_url, url.repo_type); + http_url = JoinPath(http_url, url.repository); + http_url = JoinPath(http_url, "tree"); + http_url = JoinPath(http_url, url.revision); + http_url += url.path; + + if (limit > 0) { + http_url += "?limit=" + to_string(limit); + } + + return http_url; +} + +string HuggingFaceFileSystem::GetFileUrl(const ParsedHFUrl &url) { + //! Url format {endpoint}/{repo_type}[/{repository}/{revision}{encoded_path_in_repo} + string http_url = url.endpoint; + http_url = JoinPath(http_url, url.repo_type); + http_url = JoinPath(http_url, url.repository); + http_url = JoinPath(http_url, "resolve"); + http_url = JoinPath(http_url, url.revision); + http_url += url.path; + + return http_url; +} + +} // namespace duckdb diff --git a/extension/httpfs/httpfs.cpp b/extension/httpfs/httpfs.cpp index 8c0bd34262b..659f93dc9cd 100644 --- a/extension/httpfs/httpfs.cpp +++ b/extension/httpfs/httpfs.cpp @@ -7,9 +7,11 @@ #include "duckdb/common/thread.hpp" #include "duckdb/common/types/hash.hpp" #include "duckdb/function/scalar/strftime_format.hpp" +#include "duckdb/logging/http_logger.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/main/database.hpp" #include "duckdb/common/helper.hpp" +#include "duckdb/main/secret/secret_manager.hpp" #include #include @@ -39,6 +41,7 @@ HTTPParams HTTPParams::ReadFrom(optional_ptr opener) { bool keep_alive = DEFAULT_KEEP_ALIVE; bool enable_server_cert_verification = DEFAULT_ENABLE_SERVER_CERT_VERIFICATION; std::string ca_cert_file; + uint64_t hf_max_per_page = DEFAULT_HF_MAX_PER_PAGE; Value value; if (FileOpener::TryGetCurrentSetting(opener, "http_timeout", value)) { @@ -65,10 +68,20 @@ HTTPParams HTTPParams::ReadFrom(optional_ptr opener) { if (FileOpener::TryGetCurrentSetting(opener, "ca_cert_file", value)) { ca_cert_file = value.ToString(); } + if (FileOpener::TryGetCurrentSetting(opener, "hf_max_per_page", value)) { + hf_max_per_page = value.GetValue(); + } - return { - timeout, retries, retry_wait_ms, retry_backoff, force_download, keep_alive, enable_server_cert_verification, - ca_cert_file}; + return {timeout, + retries, + retry_wait_ms, + retry_backoff, + force_download, + keep_alive, + enable_server_cert_verification, + ca_cert_file, + "", + hf_max_per_page}; } void HTTPFileSystem::ParseUrl(string &url, string &path_out, string &proto_host_port_out) { @@ -90,9 +103,10 @@ void HTTPFileSystem::ParseUrl(string &url, string &path_out, string &proto_host_ // Retry the request performed by fun using the exponential backoff strategy defined in params. Before retry, the // retry callback is called -static duckdb::unique_ptr -RunRequestWithRetry(const std::function &request, string &url, string method, - const HTTPParams ¶ms, const std::function &retry_cb = {}) { +duckdb::unique_ptr +HTTPFileSystem::RunRequestWithRetry(const std::function &request, string &url, + string method, const HTTPParams ¶ms, + const std::function &retry_cb) { idx_t tries = 0; while (true) { std::exception_ptr caught_e = nullptr; @@ -158,7 +172,7 @@ unique_ptr HTTPFileSystem::PostRequest(FileHandle &handle, stri idx_t out_offset = 0; std::function request([&]() { - auto client = GetClient(hfs.http_params, proto_host_port.c_str()); + auto client = GetClient(hfs.http_params, proto_host_port.c_str(), &hfs); if (hfs.state) { hfs.state->post_count++; @@ -196,7 +210,8 @@ unique_ptr HTTPFileSystem::PostRequest(FileHandle &handle, stri } unique_ptr HTTPFileSystem::GetClient(const HTTPParams &http_params, - const char *proto_host_port) { + const char *proto_host_port, + optional_ptr hfs) { auto client = make_uniq(proto_host_port); client->set_follow_location(true); client->set_keep_alive(http_params.keep_alive); @@ -208,6 +223,13 @@ unique_ptr HTTPFileSystem::GetClient(const HTTPP client->set_read_timeout(http_params.timeout); client->set_connection_timeout(http_params.timeout); client->set_decompress(false); + if (hfs && hfs->http_logger) { + client->set_logger( + hfs->http_logger->GetLogger()); + } + if (!http_params.bearer_token.empty()) { + client->set_bearer_token_auth(http_params.bearer_token.c_str()); + } return client; } @@ -219,7 +241,7 @@ unique_ptr HTTPFileSystem::PutRequest(FileHandle &handle, strin auto headers = initialize_http_headers(header_map); std::function request([&]() { - auto client = GetClient(hfs.http_params, proto_host_port.c_str()); + auto client = GetClient(hfs.http_params, proto_host_port.c_str(), &hfs); if (hfs.state) { hfs.state->put_count++; hfs.state->total_bytes_sent += buffer_in_len; @@ -244,7 +266,7 @@ unique_ptr HTTPFileSystem::HeadRequest(FileHandle &handle, stri }); std::function on_retry( - [&]() { hfs.http_client = GetClient(hfs.http_params, proto_host_port.c_str()); }); + [&]() { hfs.http_client = GetClient(hfs.http_params, proto_host_port.c_str(), &hfs); }); return RunRequestWithRetry(request, url, "HEAD", hfs.http_params, on_retry); } @@ -300,7 +322,7 @@ unique_ptr HTTPFileSystem::GetRequest(FileHandle &handle, strin }); std::function on_retry( - [&]() { hfh.http_client = GetClient(hfh.http_params, proto_host_port.c_str()); }); + [&]() { hfh.http_client = GetClient(hfh.http_params, proto_host_port.c_str(), &hfh); }); return RunRequestWithRetry(request, url, "GET", hfh.http_params, on_retry); } @@ -367,7 +389,7 @@ unique_ptr HTTPFileSystem::GetRangeRequest(FileHandle &handle, }); std::function on_retry( - [&]() { hfs.http_client = GetClient(hfs.http_params, proto_host_port.c_str()); }); + [&]() { hfs.http_client = GetClient(hfs.http_params, proto_host_port.c_str(), &hfs); }); return RunRequestWithRetry(request, url, "GET Range", hfs.http_params, on_retry); } @@ -380,7 +402,21 @@ HTTPFileHandle::HTTPFileHandle(FileSystem &fs, const string &path, FileOpenFlags unique_ptr HTTPFileSystem::CreateHandle(const string &path, FileOpenFlags flags, optional_ptr opener) { D_ASSERT(flags.Compression() == FileCompressionType::UNCOMPRESSED); - return duckdb::make_uniq(*this, path, flags, HTTPParams::ReadFrom(opener)); + + auto params = HTTPParams::ReadFrom(opener); + + auto secret_manager = FileOpener::TryGetSecretManager(opener); + auto transaction = FileOpener::TryGetCatalogTransaction(opener); + if (secret_manager && transaction) { + auto secret_match = secret_manager->LookupSecret(*transaction, path, "bearer"); + + if (secret_match.HasMatch()) { + const auto &kv_secret = dynamic_cast(*secret_match.secret_entry->secret); + params.bearer_token = kv_secret.TryGetValue("token", true).ToString(); + } + } + + return duckdb::make_uniq(*this, path, flags, params); } unique_ptr HTTPFileSystem::OpenFile(const string &path, FileOpenFlags flags, @@ -568,7 +604,7 @@ static optional_ptr TryGetMetadataCache(optional_ptr opener) { - InitializeClient(); + InitializeClient(FileOpener::TryGetClientContext(opener)); auto &hfs = file_system.Cast(); state = HTTPState::TryGetState(opener); if (!state) { @@ -701,10 +737,15 @@ void HTTPFileHandle::Initialize(optional_ptr opener) { } } -void HTTPFileHandle::InitializeClient() { +void HTTPFileHandle::InitializeClient(optional_ptr context) { string path_out, proto_host_port; HTTPFileSystem::ParseUrl(path, path_out, proto_host_port); - http_client = HTTPFileSystem::GetClient(this->http_params, proto_host_port.c_str()); + http_client = HTTPFileSystem::GetClient(this->http_params, proto_host_port.c_str(), this); + if (context && ClientConfig::GetConfig(*context).enable_http_logging) { + http_logger = context->client_data->http_logger.get(); + http_client->set_logger( + http_logger->GetLogger()); + } } ResponseWrapper::ResponseWrapper(duckdb_httplib_openssl::Response &res, string &original_url) { diff --git a/extension/httpfs/httpfs_config.py b/extension/httpfs/httpfs_config.py index 4c63f13d995..791dcb1c2fd 100644 --- a/extension/httpfs/httpfs_config.py +++ b/extension/httpfs/httpfs_config.py @@ -10,6 +10,13 @@ os.path.sep.join(x.split('/')) for x in [ 'extension/httpfs/' + s - for s in ['create_secret_functions.cpp', 'httpfs_extension.cpp', 'httpfs.cpp', 's3fs.cpp', 'crypto.cpp'] + for s in [ + 'create_secret_functions.cpp', + 'crypto.cpp', + 'hffs.cpp', + 'httpfs.cpp', + 'httpfs_extension.cpp', + 's3fs.cpp', + ] ] ] diff --git a/extension/httpfs/httpfs_extension.cpp b/extension/httpfs/httpfs_extension.cpp index 685062c7c7a..8f1966c9cd6 100644 --- a/extension/httpfs/httpfs_extension.cpp +++ b/extension/httpfs/httpfs_extension.cpp @@ -5,6 +5,7 @@ #include "create_secret_functions.hpp" #include "duckdb.hpp" #include "s3fs.hpp" +#include "hffs.hpp" namespace duckdb { @@ -13,6 +14,7 @@ static void LoadInternal(DatabaseInstance &instance) { auto &fs = instance.GetFileSystem(); fs.RegisterSubSystem(make_uniq()); + fs.RegisterSubSystem(make_uniq()); fs.RegisterSubSystem(make_uniq(BufferManager::GetBufferManager(instance))); auto &config = DBConfig::GetConfig(instance); @@ -55,10 +57,15 @@ static void LoadInternal(DatabaseInstance &instance) { config.AddExtensionOption("s3_uploader_thread_limit", "S3 Uploader global thread limit", LogicalType::UBIGINT, Value(50)); + // HuggingFace options + config.AddExtensionOption("hf_max_per_page", "Debug option to limit number of items returned in list requests", + LogicalType::UBIGINT, Value::UBIGINT(0)); + auto provider = make_uniq(config); provider->SetAll(); CreateS3SecretFunctions::Register(instance); + CreateBearerTokenFunctions::Register(instance); } void HttpfsExtension::Load(DuckDB &db) { @@ -68,6 +75,14 @@ std::string HttpfsExtension::Name() { return "httpfs"; } +std::string HttpfsExtension::Version() const { +#ifdef EXT_VERSION_HTTPFS + return EXT_VERSION_HTTPFS; +#else + return ""; +#endif +} + } // namespace duckdb extern "C" { diff --git a/extension/httpfs/include/create_secret_functions.hpp b/extension/httpfs/include/create_secret_functions.hpp index bfb0a1451c3..91d4d8d073f 100644 --- a/extension/httpfs/include/create_secret_functions.hpp +++ b/extension/httpfs/include/create_secret_functions.hpp @@ -29,4 +29,23 @@ struct CreateS3SecretFunctions { static void RegisterCreateSecretFunction(DatabaseInstance &instance, string type); }; +struct CreateBearerTokenFunctions { +public: + static constexpr const char *GENERIC_BEARER_TYPE = "bearer"; + static constexpr const char *HUGGINGFACE_TYPE = "huggingface"; + + //! Register all CreateSecretFunctions + static void Register(DatabaseInstance &instance); + +protected: + //! Internal function to create bearer token + static unique_ptr CreateSecretFunctionInternal(ClientContext &context, CreateSecretInput &input, + const string &token); + //! Function for the "config" provider: creates secret from parameters passed by user + static unique_ptr CreateBearerSecretFromConfig(ClientContext &context, CreateSecretInput &input); + //! Function for the "config" provider: creates secret from parameters passed by user + static unique_ptr CreateHuggingFaceSecretFromCredentialChain(ClientContext &context, + CreateSecretInput &input); +}; + } // namespace duckdb diff --git a/extension/httpfs/include/hffs.hpp b/extension/httpfs/include/hffs.hpp new file mode 100644 index 00000000000..e577382e3ae --- /dev/null +++ b/extension/httpfs/include/hffs.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include "httpfs.hpp" + +namespace duckdb { + +struct ParsedHFUrl { + //! Path within the + string path; + //! Name of the repo (i presume) + string repository; + + //! Endpoint, defaults to HF + string endpoint = "https://huggingface.co"; + //! Which revision/branch/tag to use + string revision = "main"; + //! For DuckDB this may be a sensible default? + string repo_type = "datasets"; +}; + +class HuggingFaceFileSystem : public HTTPFileSystem { +public: + ~HuggingFaceFileSystem() override; + + vector Glob(const string &path, FileOpener *opener = nullptr) override; + + duckdb::unique_ptr HeadRequest(FileHandle &handle, string hf_url, HeaderMap header_map) override; + duckdb::unique_ptr GetRequest(FileHandle &handle, string hf_url, HeaderMap header_map) override; + duckdb::unique_ptr GetRangeRequest(FileHandle &handle, string hf_url, HeaderMap header_map, + idx_t file_offset, char *buffer_out, + idx_t buffer_out_len) override; + + bool CanHandleFile(const string &fpath) override { + return fpath.rfind("hf://", 0) == 0; + }; + + string GetName() const override { + return "HuggingFaceFileSystem"; + } + static ParsedHFUrl HFUrlParse(const string &url); + string GetHFUrl(const ParsedHFUrl &url); + string GetTreeUrl(const ParsedHFUrl &url, idx_t limit); + string GetFileUrl(const ParsedHFUrl &url); + + static void SetParams(HTTPParams ¶ms, const string &path, optional_ptr opener); + +protected: + duckdb::unique_ptr CreateHandle(const string &path, FileOpenFlags flags, + optional_ptr opener) override; + + string ListHFRequest(ParsedHFUrl &url, HTTPParams &http_params, string &next_page_url, + optional_ptr state); +}; + +class HFFileHandle : public HTTPFileHandle { + friend class HuggingFaceFileSystem; + +public: + HFFileHandle(FileSystem &fs, ParsedHFUrl hf_url, string http_url, FileOpenFlags flags, + const HTTPParams &http_params) + : HTTPFileHandle(fs, std::move(http_url), flags, http_params), parsed_url(std::move(hf_url)) { + } + ~HFFileHandle() override; + + void InitializeClient(optional_ptr client_context) override; + +protected: + ParsedHFUrl parsed_url; +}; + +} // namespace duckdb diff --git a/extension/httpfs/include/httpfs.hpp b/extension/httpfs/include/httpfs.hpp index a3a237d0c77..1ef1c11278a 100644 --- a/extension/httpfs/include/httpfs.hpp +++ b/extension/httpfs/include/httpfs.hpp @@ -10,11 +10,14 @@ namespace duckdb_httplib_openssl { struct Response; +class Result; class Client; } // namespace duckdb_httplib_openssl namespace duckdb { +class HTTPLogger; + using HeaderMap = case_insensitive_map_t; // avoid including httplib in header @@ -37,6 +40,7 @@ struct HTTPParams { static constexpr bool DEFAULT_FORCE_DOWNLOAD = false; static constexpr bool DEFAULT_KEEP_ALIVE = true; static constexpr bool DEFAULT_ENABLE_SERVER_CERT_VERIFICATION = false; + static constexpr uint64_t DEFAULT_HF_MAX_PER_PAGE = 0; uint64_t timeout; uint64_t retries; @@ -47,6 +51,10 @@ struct HTTPParams { bool enable_server_cert_verification; std::string ca_cert_file; + string bearer_token; + + idx_t hf_max_per_page; + static HTTPParams ReadFrom(optional_ptr opener); }; @@ -59,6 +67,7 @@ class HTTPFileHandle : public FileHandle { // We keep an http client stored for connection reuse with keep-alive headers duckdb::unique_ptr http_client; + optional_ptr http_logger; const HTTPParams http_params; @@ -83,18 +92,20 @@ class HTTPFileHandle : public FileHandle { shared_ptr state; + void AddHeaders(HeaderMap &map); + public: void Close() override { } protected: - virtual void InitializeClient(); + virtual void InitializeClient(optional_ptr client_context); }; class HTTPFileSystem : public FileSystem { public: - static duckdb::unique_ptr GetClient(const HTTPParams &http_params, - const char *proto_host_port); + static duckdb::unique_ptr + GetClient(const HTTPParams &http_params, const char *proto_host_port, optional_ptr hfs); static void ParseUrl(string &url, string &path_out, string &proto_host_port_out); duckdb::unique_ptr OpenFile(const string &path, FileOpenFlags flags, optional_ptr opener = nullptr) final; @@ -154,6 +165,10 @@ class HTTPFileSystem : public FileSystem { virtual duckdb::unique_ptr CreateHandle(const string &path, FileOpenFlags flags, optional_ptr opener); + static duckdb::unique_ptr + RunRequestWithRetry(const std::function &request, string &url, string method, + const HTTPParams ¶ms, const std::function &retry_cb = {}); + private: // Global cache mutex global_cache_lock; diff --git a/extension/httpfs/include/httpfs_extension.hpp b/extension/httpfs/include/httpfs_extension.hpp index b6412389223..3c4f3a11068 100644 --- a/extension/httpfs/include/httpfs_extension.hpp +++ b/extension/httpfs/include/httpfs_extension.hpp @@ -8,6 +8,7 @@ class HttpfsExtension : public Extension { public: void Load(DuckDB &db) override; std::string Name() override; + std::string Version() const override; }; } // namespace duckdb diff --git a/extension/httpfs/include/s3fs.hpp b/extension/httpfs/include/s3fs.hpp index 781b2b73bc6..501c49c0377 100644 --- a/extension/httpfs/include/s3fs.hpp +++ b/extension/httpfs/include/s3fs.hpp @@ -165,7 +165,7 @@ class S3FileHandle : public HTTPFileHandle { atomic uploader_has_error {false}; std::exception_ptr upload_exception; - void InitializeClient() override; + void InitializeClient(optional_ptr client_context) override; //! Rethrow IO Exception originating from an upload thread void RethrowIOError() { diff --git a/extension/httpfs/s3fs.cpp b/extension/httpfs/s3fs.cpp index b06120896c0..4a481d68558 100644 --- a/extension/httpfs/s3fs.cpp +++ b/extension/httpfs/s3fs.cpp @@ -3,17 +3,17 @@ #include "crypto.hpp" #include "duckdb.hpp" #ifndef DUCKDB_AMALGAMATION +#include "duckdb/common/exception/http_exception.hpp" +#include "duckdb/common/helper.hpp" #include "duckdb/common/http_state.hpp" #include "duckdb/common/thread.hpp" #include "duckdb/common/types/timestamp.hpp" #include "duckdb/function/scalar/strftime_format.hpp" -#include "duckdb/common/exception/http_exception.hpp" -#include "duckdb/common/helper.hpp" #endif #include -#include #include +#include #include #include @@ -321,7 +321,15 @@ S3AuthParams S3SecretHelper::GetParams(const KeyValueSecret &secret) { } S3FileHandle::~S3FileHandle() { - Close(); + if (Exception::UncaughtException()) { + // We are in an exception, don't do anything + return; + } + + try { + Close(); + } catch (...) { // NOLINT + } } S3ConfigParams S3ConfigParams::ReadFrom(optional_ptr opener) { @@ -361,11 +369,11 @@ void S3FileHandle::Close() { } } -void S3FileHandle::InitializeClient() { +void S3FileHandle::InitializeClient(optional_ptr client_context) { auto parsed_url = S3FileSystem::S3UrlParse(path, this->auth_params); string proto_host_port = parsed_url.http_proto + parsed_url.host; - http_client = HTTPFileSystem::GetClient(this->http_params, proto_host_port.c_str()); + http_client = HTTPFileSystem::GetClient(this->http_params, proto_host_port.c_str(), this); } // Opens the multipart upload and returns the ID @@ -1119,8 +1127,8 @@ string AWSListObjectV2::Request(string &path, HTTPParams &http_params, S3AuthPar create_s3_header(req_path, req_params, parsed_url.host, "s3", "GET", s3_auth_params, "", "", "", ""); auto headers = initialize_http_headers(header_map); - auto client = S3FileSystem::GetClient( - http_params, (parsed_url.http_proto + parsed_url.host).c_str()); // Get requests use fresh connection + auto client = S3FileSystem::GetClient(http_params, (parsed_url.http_proto + parsed_url.host).c_str(), + nullptr); // Get requests use fresh connection std::stringstream response; auto res = client->Get( listobjectv2_url.c_str(), *headers, diff --git a/extension/icu/CMakeLists.txt b/extension/icu/CMakeLists.txt index 7042ddc982b..dd5ea8c8253 100644 --- a/extension/icu/CMakeLists.txt +++ b/extension/icu/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(ICUExtension) diff --git a/extension/icu/icu-strptime.cpp b/extension/icu/icu-strptime.cpp index d54d15a3700..c7a5351f428 100644 --- a/extension/icu/icu-strptime.cpp +++ b/extension/icu/icu-strptime.cpp @@ -68,15 +68,15 @@ struct ICUStrptime : public ICUDateFunc { } // Now get the parts in the given time zone - uint64_t micros = 0; + uint64_t micros = parsed.GetMicros(); calendar->set(UCAL_EXTENDED_YEAR, parsed.data[0]); // strptime doesn't understand eras calendar->set(UCAL_MONTH, parsed.data[1] - 1); calendar->set(UCAL_DATE, parsed.data[2]); calendar->set(UCAL_HOUR_OF_DAY, parsed.data[3]); calendar->set(UCAL_MINUTE, parsed.data[4]); calendar->set(UCAL_SECOND, parsed.data[5]); - calendar->set(UCAL_MILLISECOND, parsed.data[6] / Interval::MICROS_PER_MSEC); - micros = parsed.data[6] % Interval::MICROS_PER_MSEC; + calendar->set(UCAL_MILLISECOND, micros / Interval::MICROS_PER_MSEC); + micros %= Interval::MICROS_PER_MSEC; // This overrides the TZ setting, so only use it if an offset was parsed. // Note that we don't bother/worry about the DST setting because the two just combine. @@ -158,7 +158,7 @@ struct ICUStrptime : public ICUDateFunc { } } - static bind_scalar_function_t bind_strptime; + static bind_scalar_function_t bind_strptime; // NOLINT static duckdb::unique_ptr StrpTimeBindFunction(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { @@ -194,7 +194,7 @@ struct ICUStrptime : public ICUDateFunc { throw InvalidInputException("strptime format list must not be empty"); } vector formats; - bool has_tz = true; + bool has_tz = false; for (const auto &child : children) { format_string = child.ToString(); format.format_specifier = format_string; @@ -341,7 +341,7 @@ struct ICUStrptime : public ICUDateFunc { } }; -bind_scalar_function_t ICUStrptime::bind_strptime = nullptr; +bind_scalar_function_t ICUStrptime::bind_strptime = nullptr; // NOLINT struct ICUStrftime : public ICUDateFunc { static void ParseFormatSpecifier(string_t &format_str, StrfTimeFormat &format) { diff --git a/extension/icu/icu-table-range.cpp b/extension/icu/icu-table-range.cpp index 9f466a7d656..f7efd856ad9 100644 --- a/extension/icu/icu-table-range.cpp +++ b/extension/icu/icu-table-range.cpp @@ -13,14 +13,13 @@ namespace duckdb { struct ICUTableRange { using CalendarPtr = unique_ptr; - struct BindData : public TableFunctionData { - BindData(const BindData &other) + struct ICURangeBindData : public TableFunctionData { + ICURangeBindData(const ICURangeBindData &other) : TableFunctionData(other), tz_setting(other.tz_setting), cal_setting(other.cal_setting), - calendar(other.calendar->clone()), start(other.start), end(other.end), increment(other.increment), - inclusive_bound(other.inclusive_bound), greater_than_check(other.greater_than_check) { + calendar(other.calendar->clone()) { } - explicit BindData(ClientContext &context) { + explicit ICURangeBindData(ClientContext &context) { Value tz_value; if (context.TryGetCurrentSetting("TimeZone", tz_value)) { tz_setting = tz_value.ToString(); @@ -48,6 +47,15 @@ struct ICUTableRange { string tz_setting; string cal_setting; CalendarPtr calendar; + }; + + struct ICURangeLocalState : public LocalTableFunctionState { + ICURangeLocalState() { + } + + bool initialized_row = false; + idx_t current_input_row = 0; + timestamp_t current_state; timestamp_t start; timestamp_t end; @@ -55,17 +63,6 @@ struct ICUTableRange { bool inclusive_bound; bool greater_than_check; - bool Equals(const FunctionData &other_p) const override { - auto &other = other_p.Cast(); - return other.start == start && other.end == end && other.increment == increment && - other.inclusive_bound == inclusive_bound && other.greater_than_check == greater_than_check && - *calendar == *other.calendar; - } - - unique_ptr Copy() const override { - return make_uniq(*this); - } - bool Finished(timestamp_t current_value) const { if (greater_than_check) { if (inclusive_bound) { @@ -84,107 +81,129 @@ struct ICUTableRange { }; template - static unique_ptr Bind(ClientContext &context, TableFunctionBindInput &input, - vector &return_types, vector &names) { - auto result = make_uniq(context); - - auto &inputs = input.inputs; - D_ASSERT(inputs.size() == 3); - for (const auto &value : inputs) { - if (value.IsNull()) { - throw BinderException("RANGE with NULL bounds is not supported"); + static void GenerateRangeDateTimeParameters(DataChunk &input, idx_t row_id, ICURangeLocalState &result) { + input.Flatten(); + for (idx_t c = 0; c < input.ColumnCount(); c++) { + if (FlatVector::IsNull(input.data[c], row_id)) { + result.start = timestamp_t(0); + result.end = timestamp_t(0); + result.increment = interval_t(); + result.greater_than_check = true; + result.inclusive_bound = false; + return; } } - result->start = inputs[0].GetValue(); - result->end = inputs[1].GetValue(); - result->increment = inputs[2].GetValue(); + + result.start = FlatVector::GetValue(input.data[0], row_id); + result.end = FlatVector::GetValue(input.data[1], row_id); + result.increment = FlatVector::GetValue(input.data[2], row_id); // Infinities either cause errors or infinite loops, so just ban them - if (!Timestamp::IsFinite(result->start) || !Timestamp::IsFinite(result->end)) { + if (!Timestamp::IsFinite(result.start) || !Timestamp::IsFinite(result.end)) { throw BinderException("RANGE with infinite bounds is not supported"); } - if (result->increment.months == 0 && result->increment.days == 0 && result->increment.micros == 0) { + if (result.increment.months == 0 && result.increment.days == 0 && result.increment.micros == 0) { throw BinderException("interval cannot be 0!"); } // all elements should point in the same direction - if (result->increment.months > 0 || result->increment.days > 0 || result->increment.micros > 0) { - if (result->increment.months < 0 || result->increment.days < 0 || result->increment.micros < 0) { + if (result.increment.months > 0 || result.increment.days > 0 || result.increment.micros > 0) { + if (result.increment.months < 0 || result.increment.days < 0 || result.increment.micros < 0) { throw BinderException("RANGE with composite interval that has mixed signs is not supported"); } - result->greater_than_check = true; - if (result->start > result->end) { + result.greater_than_check = true; + if (result.start > result.end) { throw BinderException( "start is bigger than end, but increment is positive: cannot generate infinite series"); } } else { - result->greater_than_check = false; - if (result->start < result->end) { + result.greater_than_check = false; + if (result.start < result.end) { throw BinderException( "start is smaller than end, but increment is negative: cannot generate infinite series"); } } - return_types.push_back(inputs[0].type()); + result.inclusive_bound = GENERATE_SERIES; + } + + template + static unique_ptr Bind(ClientContext &context, TableFunctionBindInput &input, + vector &return_types, vector &names) { + auto result = make_uniq(context); + + return_types.push_back(LogicalType::TIMESTAMP_TZ); if (GENERATE_SERIES) { - // generate_series has inclusive bounds on the RHS - result->inclusive_bound = true; names.emplace_back("generate_series"); } else { - result->inclusive_bound = false; names.emplace_back("range"); } return std::move(result); } - struct State : public GlobalTableFunctionState { - explicit State(timestamp_t start_p) : current_state(start_p) { - } - - timestamp_t current_state; - bool finished = false; - }; - - static unique_ptr Init(ClientContext &context, TableFunctionInitInput &input) { - auto &bind_data = input.bind_data->Cast(); - return make_uniq(bind_data.start); + static unique_ptr RangeDateTimeLocalInit(ExecutionContext &context, + TableFunctionInitInput &input, + GlobalTableFunctionState *global_state) { + return make_uniq(); } - static void ICUTableRangeFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { - auto &bind_data = data_p.bind_data->Cast(); + template + static OperatorResultType ICUTableRangeFunction(ExecutionContext &context, TableFunctionInput &data_p, + DataChunk &input, DataChunk &output) { + auto &bind_data = data_p.bind_data->Cast(); + auto &state = data_p.local_state->Cast(); CalendarPtr calendar_ptr(bind_data.calendar->clone()); auto calendar = calendar_ptr.get(); - auto &state = data_p.global_state->Cast(); - if (state.finished) { - return; - } - - idx_t size = 0; - auto data = FlatVector::GetData(output.data[0]); while (true) { - data[size++] = state.current_state; - state.current_state = ICUDateFunc::Add(calendar, state.current_state, bind_data.increment); - if (bind_data.Finished(state.current_state)) { - state.finished = true; - break; + if (!state.initialized_row) { + // initialize for the current input row + if (state.current_input_row >= input.size()) { + // ran out of rows + state.current_input_row = 0; + state.initialized_row = false; + return OperatorResultType::NEED_MORE_INPUT; + } + GenerateRangeDateTimeParameters(input, state.current_input_row, state); + state.initialized_row = true; + state.current_state = state.start; + } + idx_t size = 0; + auto data = FlatVector::GetData(output.data[0]); + while (true) { + if (state.Finished(state.current_state)) { + break; + } + data[size++] = state.current_state; + state.current_state = ICUDateFunc::Add(calendar, state.current_state, state.increment); + if (size >= STANDARD_VECTOR_SIZE) { + break; + } } - if (size >= STANDARD_VECTOR_SIZE) { - break; + if (size == 0) { + // move to next row + state.current_input_row++; + state.initialized_row = false; + continue; } + output.SetCardinality(size); + return OperatorResultType::HAVE_MORE_OUTPUT; } - output.SetCardinality(size); } static void AddICUTableRangeFunction(DatabaseInstance &db) { TableFunctionSet range("range"); - range.AddFunction(TableFunction({LogicalType::TIMESTAMP_TZ, LogicalType::TIMESTAMP_TZ, LogicalType::INTERVAL}, - ICUTableRangeFunction, Bind, Init)); + TableFunction range_function({LogicalType::TIMESTAMP_TZ, LogicalType::TIMESTAMP_TZ, LogicalType::INTERVAL}, + nullptr, Bind, nullptr, RangeDateTimeLocalInit); + range_function.in_out_function = ICUTableRangeFunction; + range.AddFunction(range_function); ExtensionUtil::AddFunctionOverload(db, range); // generate_series: similar to range, but inclusive instead of exclusive bounds on the RHS TableFunctionSet generate_series("generate_series"); - generate_series.AddFunction( - TableFunction({LogicalType::TIMESTAMP_TZ, LogicalType::TIMESTAMP_TZ, LogicalType::INTERVAL}, - ICUTableRangeFunction, Bind, Init)); + TableFunction generate_series_function( + {LogicalType::TIMESTAMP_TZ, LogicalType::TIMESTAMP_TZ, LogicalType::INTERVAL}, nullptr, Bind, nullptr, + RangeDateTimeLocalInit); + generate_series_function.in_out_function = ICUTableRangeFunction; + generate_series.AddFunction(generate_series_function); ExtensionUtil::AddFunctionOverload(db, generate_series); } }; diff --git a/extension/icu/icu_extension.cpp b/extension/icu/icu_extension.cpp index bf09f4e1970..707bd35a3b1 100644 --- a/extension/icu/icu_extension.cpp +++ b/extension/icu/icu_extension.cpp @@ -26,6 +26,7 @@ #include "include/icu_extension.hpp" #include "unicode/calendar.h" #include "unicode/coll.h" +#include "unicode/errorcode.h" #include "unicode/sortkey.h" #include "unicode/stringpiece.h" #include "unicode/timezone.h" @@ -39,6 +40,10 @@ struct IcuBindData : public FunctionData { duckdb::unique_ptr collator; string language; string country; + string tag; + + IcuBindData(duckdb::unique_ptr collator_p) : collator(std::move(collator_p)) { + } IcuBindData(string language_p, string country_p) : language(std::move(language_p)), country(std::move(country_p)) { UErrorCode status = U_ZERO_ERROR; @@ -54,16 +59,64 @@ struct IcuBindData : public FunctionData { } } + IcuBindData(string tag_p) : tag(std::move(tag_p)) { + UErrorCode status = U_ZERO_ERROR; + UCollator *ucollator = ucol_open(tag.c_str(), &status); + if (U_FAILURE(status)) { + auto error_name = u_errorName(status); + throw InvalidInputException("Failed to create ICU collator with tag %s: %s", tag, error_name); + } + collator = unique_ptr(icu::Collator::fromUCollator(ucollator)); + } + + static duckdb::unique_ptr CreateInstance(string language, string country, string tag) { + //! give priority to tagged collation + if (!tag.empty()) { + return make_uniq(tag); + } else { + return make_uniq(language, country); + } + } + duckdb::unique_ptr Copy() const override { - return make_uniq(language, country); + return CreateInstance(language, country, tag); } bool Equals(const FunctionData &other_p) const override { auto &other = other_p.Cast(); - return language == other.language && country == other.country; + return language == other.language && country == other.country && tag == other.tag; + } + + static void Serialize(Serializer &serializer, const optional_ptr bind_data_p, + const ScalarFunction &function) { + auto &bind_data = bind_data_p->Cast(); + serializer.WriteProperty(100, "language", bind_data.language); + serializer.WriteProperty(101, "country", bind_data.country); + serializer.WritePropertyWithDefault(102, "tag", bind_data.tag); + } + + static unique_ptr Deserialize(Deserializer &deserializer, ScalarFunction &function) { + string language; + string country; + string tag; + deserializer.ReadProperty(100, "language", language); + deserializer.ReadProperty(101, "country", country); + deserializer.ReadPropertyWithDefault(102, "tag", tag); + return CreateInstance(language, country, tag); + } + + static const string FUNCTION_PREFIX; + + static string EncodeFunctionName(const string &collation) { + return FUNCTION_PREFIX + collation; + } + static string DecodeFunctionName(const string &fname) { + return fname.substr(FUNCTION_PREFIX.size()); } }; +const string IcuBindData::FUNCTION_PREFIX = "icu_collate_"; + static int32_t ICUGetSortKey(icu::Collator &collator, string_t input, duckdb::unique_ptr &buffer, int32_t &buffer_size) { icu::UnicodeString unicode_string = @@ -108,7 +161,13 @@ static void ICUCollateFunction(DataChunk &args, ExpressionState &state, Vector & static duckdb::unique_ptr ICUCollateBind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { - auto splits = StringUtil::Split(bound_function.name, "_"); + //! Return a tagged collator + if (!bound_function.extra_info.empty()) { + return make_uniq(bound_function.extra_info); + } + + const auto collation = IcuBindData::DecodeFunctionName(bound_function.name); + auto splits = StringUtil::Split(collation, "_"); if (splits.size() == 1) { return make_uniq(splits[0], ""); } else if (splits.size() == 2) { @@ -127,6 +186,10 @@ static duckdb::unique_ptr ICUSortKeyBind(ClientContext &context, S if (val.IsNull()) { throw NotImplementedException("ICU_SORT_KEY(VARCHAR, VARCHAR) expected a non-null collation"); } + //! Verify tagged collation + if (!bound_function.extra_info.empty()) { + return make_uniq(bound_function.extra_info); + } auto splits = StringUtil::Split(StringValue::Get(val), "_"); if (splits.size() == 1) { return make_uniq(splits[0], ""); @@ -137,19 +200,13 @@ static duckdb::unique_ptr ICUSortKeyBind(ClientContext &context, S } } -static void ICUCollateSerialize(Serializer &serializer, const optional_ptr bind_data, - const ScalarFunction &function) { - throw NotImplementedException("FIXME: serialize icu-collate"); -} - -static duckdb::unique_ptr ICUCollateDeserialize(Deserializer &deserializer, ScalarFunction &function) { - throw NotImplementedException("FIXME: serialize icu-collate"); -} - -static ScalarFunction GetICUFunction(const string &collation) { - ScalarFunction result(collation, {LogicalType::VARCHAR}, LogicalType::VARCHAR, ICUCollateFunction, ICUCollateBind); - result.serialize = ICUCollateSerialize; - result.deserialize = ICUCollateDeserialize; +static ScalarFunction GetICUCollateFunction(const string &collation, const string &tag) { + string fname = IcuBindData::EncodeFunctionName(collation); + ScalarFunction result(fname, {LogicalType::VARCHAR}, LogicalType::VARCHAR, ICUCollateFunction, ICUCollateBind); + //! collation tag is added into the Function extra info + result.extra_info = std::move(tag); + result.serialize = IcuBindData::Serialize; + result.deserialize = IcuBindData::Deserialize; return result; } @@ -238,9 +295,24 @@ static void LoadInternal(DuckDB &ddb) { } collation = StringUtil::Lower(collation); - CreateCollationInfo info(collation, GetICUFunction(collation), false, false); + CreateCollationInfo info(collation, GetICUCollateFunction(collation, ""), false, false); ExtensionUtil::RegisterCollation(db, info); } + + /** + * This collation function is inpired on the Postgres "ignore_accents": + * See: https://www.postgresql.org/docs/current/collation.html + * CREATE COLLATION ignore_accents (provider = icu, locale = 'und-u-ks-level1-kc-true', deterministic = false); + * + * Also, according with the source file: postgres/src/backend/utils/adt/pg_locale.c. + * "und-u-kc-ks-level1" is converted to the equivalent ICU format locale ID, + * e.g. "und@colcaselevel=yes;colstrength=primary" + * + */ + CreateCollationInfo info("icu_noaccent", GetICUCollateFunction("noaccent", "und-u-ks-level1-kc-true"), false, + false); + ExtensionUtil::RegisterCollation(db, info); + ScalarFunction sort_key("icu_sort_key", {LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::VARCHAR, ICUCollateFunction, ICUSortKeyBind); ExtensionUtil::RegisterFunction(db, sort_key); @@ -283,6 +355,14 @@ std::string IcuExtension::Name() { return "icu"; } +std::string IcuExtension::Version() const { +#ifdef EXT_VERSION_ICU + return EXT_VERSION_ICU; +#else + return ""; +#endif +} + } // namespace duckdb extern "C" { diff --git a/extension/icu/include/icu_extension.hpp b/extension/icu/include/icu_extension.hpp index e1127e93c85..9577a4709d2 100644 --- a/extension/icu/include/icu_extension.hpp +++ b/extension/icu/include/icu_extension.hpp @@ -16,6 +16,7 @@ class IcuExtension : public Extension { public: void Load(DuckDB &db) override; std::string Name() override; + std::string Version() const override; }; } // namespace duckdb diff --git a/extension/icu/third_party/icu/i18n/basictz.cpp b/extension/icu/third_party/icu/i18n/basictz.cpp index 54ee5a1a2bf..4ad55f47b49 100644 --- a/extension/icu/third_party/icu/i18n/basictz.cpp +++ b/extension/icu/third_party/icu/i18n/basictz.cpp @@ -63,7 +63,7 @@ BasicTimeZone::hasEquivalentTransitions(const BasicTimeZone& tz, UDate start, UD } else { if (raw1 != raw2 || dst1 != dst2) { return FALSE; - } + } } // Check transitions in the range UDate time = start; @@ -159,7 +159,7 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, if (((tr.getFrom()->getDSTSavings() == 0 && tr.getTo()->getDSTSavings() != 0) || (tr.getFrom()->getDSTSavings() != 0 && tr.getTo()->getDSTSavings() == 0)) && (date + MILLIS_PER_YEAR > nextTransitionTime)) { - + int32_t year, month, dom, dow, doy, mid; UDate d; @@ -375,13 +375,13 @@ BasicTimeZone::getTimeZoneRulesAfter(UDate start, InitialTimeZoneRule*& initial, UDate updatedTime = tzt.getTime(); if (updatedTime == time) { // Can get here if rules for start & end of daylight time have exactly - // the same time. + // the same time. // TODO: fix getNextTransition() to prevent it? status = U_INVALID_STATE_ERROR; goto error; } time = updatedTime; - + const TimeZoneRule *toRule = tzt.getTo(); for (i = 0; i < ruleCount; i++) { r = (TimeZoneRule*)orgRules->elementAt(i); @@ -408,7 +408,7 @@ BasicTimeZone::getTimeZoneRulesAfter(UDate start, InitialTimeZoneRule*& initial, if (!avail) { break; } - if (*(tzt0.getTo()) == *tar) { + if (*tar == *(tzt0.getTo())) { break; } t = tzt0.getTime(); diff --git a/extension/inet/CMakeLists.txt b/extension/inet/CMakeLists.txt index 7ba451acebf..7fb2e2a9fd9 100644 --- a/extension/inet/CMakeLists.txt +++ b/extension/inet/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(INETExtension) diff --git a/extension/inet/include/inet_extension.hpp b/extension/inet/include/inet_extension.hpp index 2c66589a8ac..ac7df5b2261 100644 --- a/extension/inet/include/inet_extension.hpp +++ b/extension/inet/include/inet_extension.hpp @@ -17,6 +17,7 @@ class InetExtension : public Extension { public: void Load(DuckDB &db) override; std::string Name() override; + std::string Version() const override; }; } // namespace duckdb diff --git a/extension/inet/inet_extension.cpp b/extension/inet/inet_extension.cpp index 86d0bf921ce..d767524eed9 100644 --- a/extension/inet/inet_extension.cpp +++ b/extension/inet/inet_extension.cpp @@ -53,6 +53,14 @@ std::string InetExtension::Name() { return "inet"; } +std::string InetExtension::Version() const { +#ifdef EXT_VERSION_INET + return EXT_VERSION_INET; +#else + return ""; +#endif +} + } // namespace duckdb extern "C" { diff --git a/extension/jemalloc/CMakeLists.txt b/extension/jemalloc/CMakeLists.txt index 48795458949..38be497f55f 100644 --- a/extension/jemalloc/CMakeLists.txt +++ b/extension/jemalloc/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(JemallocExtension) diff --git a/extension/jemalloc/include/jemalloc_extension.hpp b/extension/jemalloc/include/jemalloc_extension.hpp index 180b7043095..a5ef49671a2 100644 --- a/extension/jemalloc/include/jemalloc_extension.hpp +++ b/extension/jemalloc/include/jemalloc_extension.hpp @@ -16,13 +16,17 @@ class JemallocExtension : public Extension { public: void Load(DuckDB &db) override; std::string Name() override; + std::string Version() const override; static data_ptr_t Allocate(PrivateAllocatorData *private_data, idx_t size); static void Free(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t size); static data_ptr_t Reallocate(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t old_size, idx_t size); + static int64_t DecayDelay(); static void ThreadFlush(idx_t threshold); + static void ThreadIdle(); static void FlushAll(); + static void SetBackgroundThreads(bool enable); }; } // namespace duckdb diff --git a/extension/jemalloc/jemalloc/CMakeLists.txt b/extension/jemalloc/jemalloc/CMakeLists.txt index ee8918cf03a..0398e0fbfa3 100644 --- a/extension/jemalloc/jemalloc/CMakeLists.txt +++ b/extension/jemalloc/jemalloc/CMakeLists.txt @@ -1,79 +1,76 @@ include_directories(include) -add_library( - jemalloc OBJECT - src/arena.cpp - src/background_thread.cpp - src/base.cpp - src/bin.cpp - src/bin_info.cpp - src/bitmap.cpp - src/buf_writer.cpp - src/cache_bin.cpp - src/ckh.cpp - src/counter.cpp - src/ctl.cpp - src/decay.cpp - src/div.cpp - src/ecache.cpp - src/edata.cpp - src/edata_cache.cpp - src/ehooks.cpp - src/emap.cpp - src/eset.cpp - src/exp_grow.cpp - src/extent.cpp - src/extent_dss.cpp - src/extent_mmap.cpp - src/fxp.cpp - src/hook.cpp - src/hpa.cpp - src/hpa_hooks.cpp - src/hpdata.cpp - src/inspect.cpp - src/jemalloc.cpp - src/large.cpp - src/log.cpp - src/malloc_io.cpp - src/mutex.cpp - src/nstime.cpp - src/pa.cpp - src/pa_extra.cpp - src/pac.cpp - src/pages.cpp - src/pai.cpp - src/peak_event.cpp - src/prof.cpp - src/prof_data.cpp - src/prof_log.cpp - src/prof_recent.cpp - src/prof_stats.cpp - src/prof_sys.cpp - src/psset.cpp - src/rtree.cpp - src/safety_check.cpp - src/san.cpp - src/san_bump.cpp - src/sc.cpp - src/sec.cpp - src/stats.cpp - src/sz.cpp - src/tcache.cpp - src/test_hooks.cpp - src/thread_event.cpp - src/ticker.cpp - src/tsd.cpp - src/witness.cpp) +set(JEMALLOC_C_FILES + src/jemalloc.c + src/arena.c + src/background_thread.c + src/base.c + src/bin.c + src/bin_info.c + src/bitmap.c + src/buf_writer.c + src/cache_bin.c + src/ckh.c + src/counter.c + src/ctl.c + src/decay.c + src/div.c + src/ecache.c + src/edata.c + src/edata_cache.c + src/ehooks.c + src/emap.c + src/eset.c + src/exp_grow.c + src/extent.c + src/extent_dss.c + src/extent_mmap.c + src/fxp.c + src/san.c + src/san_bump.c + src/hook.c + src/hpa.c + src/hpa_hooks.c + src/hpdata.c + src/inspect.c + src/large.c + src/log.c + src/malloc_io.c + src/mutex.c + src/nstime.c + src/pa.c + src/pa_extra.c + src/pai.c + src/pac.c + src/pages.c + src/peak_event.c + src/prof.c + src/prof_data.c + src/prof_log.c + src/prof_recent.c + src/prof_stats.c + src/prof_sys.c + src/psset.c + src/rtree.c + src/safety_check.c + src/sc.c + src/sec.c + src/stats.c + src/sz.c + src/tcache.c + src/test_hooks.c + src/thread_event.c + src/ticker.c + src/tsd.c + src/util.c + src/witness.c) -# we don't want this -target_compile_definitions(jemalloc PRIVATE -DJEMALLOC_NO_PRIVATE_NAMESPACE) -target_compile_definitions(jemalloc PRIVATE -DJEMALLOC_NO_RENAME) +# if we add this jemalloc overrides new/delete +# would be great but causes trouble in our Python client +# should be resolvable, with some effort +# src/jemalloc_cpp.cpp -# some extra debug defs -if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - target_compile_definitions(jemalloc PRIVATE -DJEMALLOC_DEBUG) - target_compile_definitions(jemalloc PRIVATE -DJEMALLOC_LOG) -endif() +add_library(jemalloc OBJECT ${JEMALLOC_C_FILES}) set(JEMALLOC_OBJECT_FILES ${JEMALLOC_OBJECT_FILES} $ diff --git a/extension/jemalloc/jemalloc/README.md b/extension/jemalloc/jemalloc/README.md new file mode 100644 index 00000000000..6b3454f59cc --- /dev/null +++ b/extension/jemalloc/jemalloc/README.md @@ -0,0 +1,133 @@ +# Updating jemalloc + +Clone [this](https://github.com/jemalloc/jemalloc), and check out the branch you need. + +For convenience: +```sh +export DUCKDB_DIR= +``` + +Copy jemalloc source files: +```sh +cd +./configure --with-jemalloc-prefix="duckdb_je_" --with-private-namespace="duckdb_" --without-export +cp -r src/* $DUCKDB_DIR/extension/jemalloc/jemalloc/src/ +cp -r include/* $DUCKDB_DIR/extension/jemalloc/jemalloc/include/ +cp COPYING $DUCKDB_DIR/extension/jemalloc/jemalloc/LICENSE +``` + +Remove junk: +```sh +cd $DUCKDB_DIR/extension/jemalloc/jemalloc +find . -name "*.in" -type f -delete +find . -name "*.sh" -type f -delete +find . -name "*.awk" -type f -delete +find . -name "*.txt" -type f -delete +find . -name "*.py" -type f -delete +``` + +Restore these files: +```sh +git checkout -- \ + include/jemalloc/internal/jemalloc_internal_defs.h \ + include/jemalloc/jemalloc.h \ + CMakeLists.txt +``` + +The logarithm of the size of a pointer is defined in `jemalloc.h` and `jemalloc_defs.h`, around line 50. +This is not portable, but we can make it portable if we replace all of it with this: +```c++ +#ifdef _MSC_VER +# ifdef _WIN64 +# define LG_SIZEOF_PTR_WIN 3 +# else +# define LG_SIZEOF_PTR_WIN 2 +# endif +#endif + +/* sizeof(void *) == 2^LG_SIZEOF_PTR. */ +#include +#ifdef _MSC_VER +# define LG_SIZEOF_PTR LG_SIZEOF_PTR_WIN +#elif INTPTR_MAX == INT64_MAX +# define LG_SIZEOF_PTR 3 +#else +# define LG_SIZEOF_PTR 2 +#endif +``` + +Add this to `jemalloc.h`: +```c++ +// DuckDB uses a 10s decay +#define DUCKDB_JEMALLOC_DECAY 10 +``` + +We also supply our own config string in `jemalloc.c`. +Define this just after the `#include`s. +```c++ +#define JE_MALLOC_CONF_BUFFER_SIZE 200; +char JE_MALLOC_CONF_BUFFER[JE_MALLOC_CONF_BUFFER_SIZE]; +``` +This is what `jemalloc_constructor` in `jemalloc.c` should look like: +```c++ +JEMALLOC_ATTR(constructor) +static void +jemalloc_constructor(void) { + unsigned long long cpu_count = malloc_ncpus(); + unsigned long long bgt_count = cpu_count / 32; + if (bgt_count == 0) { + bgt_count = 1; + } + // decay is in ms + unsigned long long decay = DUCKDB_DECAY_DELAY * 1000; +#ifdef DEBUG + snprintf(JE_MALLOC_CONF_BUFFER, JE_MALLOC_CONF_BUFFER_SIZE, "junk:true,oversize_threshold:268435456,dirty_decay_ms:%llu,muzzy_decay_ms:%llu,narenas:%llu,max_background_threads:%llu", decay, decay, cpu_count, bgt_count); +#else + snprintf(JE_MALLOC_CONF_BUFFER, JE_MALLOC_CONF_BUFFER_SIZE, "oversize_threshold:268435456,dirty_decay_ms:%llu,muzzy_decay_ms:%llu,narenas:%llu,max_background_threads:%llu", decay, decay, cpu_count, bgt_count); +#endif + je_malloc_conf = JE_MALLOC_CONF_BUFFER; + malloc_init(); +} +``` + +Almost no symbols are leaked due to `private_namespace.h`. +The `exported_symbols_check.py` script still found a few, so these lines need to be added to `private_namespace.h`: +```c++ +// DuckDB: added these so we can pass "exported_symbols_check.py" +#define JE_MALLOC_CONF_BUFFER JEMALLOC_N(JE_MALLOC_CONF_BUFFER) +#define arena_name_get JEMALLOC_N(arena_name_get) +#define arena_name_set JEMALLOC_N(arena_name_set) +#define b0_alloc_tcache_stack JEMALLOC_N(b0_alloc_tcache_stack) +#define b0_dalloc_tcache_stack JEMALLOC_N(b0_dalloc_tcache_stack) +#define base_alloc_rtree JEMALLOC_N(base_alloc_rtree) +#define cache_bin_stack_use_thp JEMALLOC_N(cache_bin_stack_use_thp) +#define disabled_bin JEMALLOC_N(disabled_bin) +#define global_do_not_change_tcache_maxclass JEMALLOC_N(global_do_not_change_tcache_maxclass) +#define global_do_not_change_tcache_nbins JEMALLOC_N(global_do_not_change_tcache_nbins) +#define invalid_conf_abort JEMALLOC_N(invalid_conf_abort) +#define je_free_aligned_sized JEMALLOC_N(je_free_aligned_sized) +#define je_free_sized JEMALLOC_N(je_free_sized) +#define _malloc_thread_cleanup JEMALLOC_N(_malloc_thread_cleanup) +#define _malloc_tsd_cleanup_register JEMALLOC_N(_malloc_tsd_cleanup_register) +#define multi_setting_parse_next JEMALLOC_N(multi_setting_parse_next) +#define opt_calloc_madvise_threshold JEMALLOC_N(opt_calloc_madvise_threshold) +#define opt_debug_double_free_max_scan JEMALLOC_N(opt_debug_double_free_max_scan) +#define opt_malloc_conf_env_var JEMALLOC_N(opt_malloc_conf_env_var) +#define opt_malloc_conf_symlink JEMALLOC_N(opt_malloc_conf_symlink) +#define opt_prof_bt_max JEMALLOC_N(opt_prof_bt_max) +#define opt_prof_pid_namespace JEMALLOC_N(opt_prof_pid_namespace) +#define os_page JEMALLOC_N(os_page) +#define pa_shard_nactive JEMALLOC_N(pa_shard_nactive) +#define pa_shard_ndirty JEMALLOC_N(pa_shard_ndirty) +#define pa_shard_nmuzzy JEMALLOC_N(pa_shard_nmuzzy) +#define prof_sample_free_hook_get JEMALLOC_N(prof_sample_free_hook_get) +#define prof_sample_free_hook_set JEMALLOC_N(prof_sample_free_hook_set) +#define prof_sample_hook_get JEMALLOC_N(prof_sample_hook_get) +#define prof_sample_hook_set JEMALLOC_N(prof_sample_hook_set) +#define pthread_create_wrapper JEMALLOC_N(pthread_create_wrapper) +#define tcache_bin_ncached_max_read JEMALLOC_N(tcache_bin_ncached_max_read) +#define tcache_bins_ncached_max_write JEMALLOC_N(tcache_bins_ncached_max_write) +#define tcache_enabled_set JEMALLOC_N(tcache_enabled_set) +#define thread_tcache_max_set JEMALLOC_N(thread_tcache_max_set) +#define tsd_tls JEMALLOC_N(tsd_tls) +``` diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/activity_callback.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/activity_callback.h index 93c7be4bc78..0f4f396228f 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/activity_callback.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/activity_callback.h @@ -1,7 +1,7 @@ #ifndef JEMALLOC_INTERNAL_ACTIVITY_CALLBACK_H #define JEMALLOC_INTERNAL_ACTIVITY_CALLBACK_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" /* * The callback to be executed "periodically", in response to some amount of @@ -22,6 +22,4 @@ struct activity_callback_thunk_s { void *uctx; }; -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ACTIVITY_CALLBACK_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_externs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_externs.h index 93b651c4848..f91bd888f97 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_externs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_externs.h @@ -1,15 +1,16 @@ #ifndef JEMALLOC_INTERNAL_ARENA_EXTERNS_H #define JEMALLOC_INTERNAL_ARENA_EXTERNS_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_stats.h" #include "jemalloc/internal/bin.h" #include "jemalloc/internal/div.h" +#include "jemalloc/internal/emap.h" #include "jemalloc/internal/extent_dss.h" #include "jemalloc/internal/hook.h" #include "jemalloc/internal/pages.h" #include "jemalloc/internal/stats.h" -namespace duckdb_jemalloc { - /* * When the amount of pages to be purged exceeds this amount, deferred purge * should happen. @@ -20,11 +21,10 @@ extern ssize_t opt_dirty_decay_ms; extern ssize_t opt_muzzy_decay_ms; extern percpu_arena_mode_t opt_percpu_arena; -extern const char *percpu_arena_mode_names[]; +extern const char *const percpu_arena_mode_names[]; extern div_info_t arena_binind_div_info[SC_NBINS]; -extern malloc_mutex_t arenas_lock; extern emap_t arena_emap_global; extern size_t opt_oversize_threshold; @@ -50,9 +50,9 @@ edata_t *arena_extent_alloc_large(tsdn_t *tsdn, arena_t *arena, void arena_extent_dalloc_large_prep(tsdn_t *tsdn, arena_t *arena, edata_t *edata); void arena_extent_ralloc_large_shrink(tsdn_t *tsdn, arena_t *arena, - edata_t *edata, size_t oldsize); + edata_t *edata, size_t oldusize); void arena_extent_ralloc_large_expand(tsdn_t *tsdn, arena_t *arena, - edata_t *edata, size_t oldsize); + edata_t *edata, size_t oldusize); bool arena_decay_ms_set(tsdn_t *tsdn, arena_t *arena, extent_state_t state, ssize_t decay_ms); ssize_t arena_decay_ms_get(arena_t *arena, extent_state_t state); @@ -63,14 +63,14 @@ void arena_do_deferred_work(tsdn_t *tsdn, arena_t *arena); void arena_reset(tsd_t *tsd, arena_t *arena); void arena_destroy(tsd_t *tsd, arena_t *arena); void arena_cache_bin_fill_small(tsdn_t *tsdn, arena_t *arena, - cache_bin_t *cache_bin, cache_bin_info_t *cache_bin_info, szind_t binind, - const unsigned nfill); + cache_bin_t *cache_bin, szind_t binind, const cache_bin_sz_t nfill); void *arena_malloc_hard(tsdn_t *tsdn, arena_t *arena, size_t size, - szind_t ind, bool zero); + szind_t ind, bool zero, bool slab); void *arena_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, - size_t alignment, bool zero, tcache_t *tcache); -void arena_prof_promote(tsdn_t *tsdn, void *ptr, size_t usize); + size_t alignment, bool zero, bool slab, tcache_t *tcache); +void arena_prof_promote(tsdn_t *tsdn, void *ptr, size_t usize, + size_t bumped_usize); void arena_dalloc_promoted(tsdn_t *tsdn, void *ptr, tcache_t *tcache, bool slow_path); void arena_slab_dalloc(tsdn_t *tsdn, arena_t *arena, edata_t *slab); @@ -83,13 +83,15 @@ void arena_dalloc_small(tsdn_t *tsdn, void *ptr); bool arena_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t extra, bool zero, size_t *newsize); void *arena_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t oldsize, - size_t size, size_t alignment, bool zero, tcache_t *tcache, + size_t size, size_t alignment, bool zero, bool slab, tcache_t *tcache, hook_ralloc_args_t *hook_args); dss_prec_t arena_dss_prec_get(arena_t *arena); ehooks_t *arena_get_ehooks(arena_t *arena); extent_hooks_t *arena_set_extent_hooks(tsd_t *tsd, arena_t *arena, extent_hooks_t *extent_hooks); bool arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec); +void arena_name_get(arena_t *arena, char *name); +void arena_name_set(arena_t *arena, const char *name); ssize_t arena_dirty_decay_ms_default_get(void); bool arena_dirty_decay_ms_default_set(ssize_t decay_ms); ssize_t arena_muzzy_decay_ms_default_get(void); @@ -100,7 +102,7 @@ unsigned arena_nthreads_get(arena_t *arena, bool internal); void arena_nthreads_inc(arena_t *arena, bool internal); void arena_nthreads_dec(arena_t *arena, bool internal); arena_t *arena_new(tsdn_t *tsdn, unsigned ind, const arena_config_t *config); -bool arena_init_huge(void); +bool arena_init_huge(arena_t *a0); bool arena_is_huge(unsigned arena_ind); arena_t *arena_choose_huge(tsd_t *tsd); bin_t *arena_bin_choose(tsdn_t *tsdn, arena_t *arena, szind_t binind, @@ -120,6 +122,4 @@ void arena_prefork8(tsdn_t *tsdn, arena_t *arena); void arena_postfork_parent(tsdn_t *tsdn, arena_t *arena); void arena_postfork_child(tsdn_t *tsdn, arena_t *arena); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ARENA_EXTERNS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_inlines_a.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_inlines_a.h index 65e2c2d103c..214ce80b238 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_inlines_a.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_inlines_a.h @@ -1,7 +1,8 @@ #ifndef JEMALLOC_INTERNAL_ARENA_INLINES_A_H #define JEMALLOC_INTERNAL_ARENA_INLINES_A_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_structs.h" static inline unsigned arena_ind_get(const arena_t *arena) { @@ -23,6 +24,4 @@ arena_internal_get(arena_t *arena) { return atomic_load_zu(&arena->stats.internal, ATOMIC_RELAXED); } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ARENA_INLINES_A_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_inlines_b.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_inlines_b.h index c28d896fa8d..a891b35cd40 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_inlines_b.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_inlines_b.h @@ -1,18 +1,24 @@ #ifndef JEMALLOC_INTERNAL_ARENA_INLINES_B_H #define JEMALLOC_INTERNAL_ARENA_INLINES_B_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_externs.h" +#include "jemalloc/internal/arena_structs.h" #include "jemalloc/internal/div.h" #include "jemalloc/internal/emap.h" +#include "jemalloc/internal/jemalloc_internal_inlines_b.h" #include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/large_externs.h" #include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/prof_externs.h" +#include "jemalloc/internal/prof_structs.h" #include "jemalloc/internal/rtree.h" #include "jemalloc/internal/safety_check.h" #include "jemalloc/internal/sc.h" #include "jemalloc/internal/sz.h" +#include "jemalloc/internal/tcache_inlines.h" #include "jemalloc/internal/ticker.h" -namespace duckdb_jemalloc { - static inline arena_t * arena_get_from_edata(edata_t *edata) { return (arena_t *)atomic_load_p(&arenas[edata_arena_ind_get(edata)], @@ -30,14 +36,46 @@ arena_choose_maybe_huge(tsd_t *tsd, arena_t *arena, size_t size) { * 1) is using auto arena selection (i.e. arena == NULL), and 2) the * thread is not assigned to a manual arena. */ - if (unlikely(size >= oversize_threshold)) { - arena_t *tsd_arena = tsd_arena_get(tsd); - if (tsd_arena == NULL || arena_is_auto(tsd_arena)) { - return arena_choose_huge(tsd); - } + arena_t *tsd_arena = tsd_arena_get(tsd); + if (tsd_arena == NULL) { + tsd_arena = arena_choose(tsd, NULL); + } + + size_t threshold = atomic_load_zu( + &tsd_arena->pa_shard.pac.oversize_threshold, ATOMIC_RELAXED); + if (unlikely(size >= threshold) && arena_is_auto(tsd_arena)) { + return arena_choose_huge(tsd); } - return arena_choose(tsd, NULL); + return tsd_arena; +} + +JEMALLOC_ALWAYS_INLINE bool +large_dalloc_safety_checks(edata_t *edata, const void *ptr, szind_t szind) { + if (!config_opt_safety_checks) { + return false; + } + + /* + * Eagerly detect double free and sized dealloc bugs for large sizes. + * The cost is low enough (as edata will be accessed anyway) to be + * enabled all the time. + */ + if (unlikely(edata == NULL || + edata_state_get(edata) != extent_state_active)) { + safety_check_fail("Invalid deallocation detected: " + "pages being freed (%p) not currently active, " + "possibly caused by double free bugs.", ptr); + return true; + } + size_t input_size = sz_index2size(szind); + if (unlikely(input_size != edata_usize_get(edata))) { + safety_check_fail_sized_dealloc(/* current_dealloc */ true, ptr, + /* true_size */ edata_usize_get(edata), input_size); + return true; + } + + return false; } JEMALLOC_ALWAYS_INLINE void @@ -63,12 +101,18 @@ arena_prof_info_get(tsd_t *tsd, const void *ptr, emap_alloc_ctx_t *alloc_ctx, if (unlikely(!is_slab)) { /* edata must have been initialized at this point. */ assert(edata != NULL); + if (reset_recent && + large_dalloc_safety_checks(edata, ptr, + edata_szind_get(edata))) { + prof_info->alloc_tctx = PROF_TCTX_SENTINEL; + return; + } large_prof_info_get(tsd, edata, prof_info, reset_recent); } else { - prof_info->alloc_tctx = (prof_tctx_t *)(uintptr_t)1U; + prof_info->alloc_tctx = PROF_TCTX_SENTINEL; /* * No need to set other fields in prof_info; they will never be - * accessed if (uintptr_t)alloc_tctx == (uintptr_t)1U. + * accessed if alloc_tctx == PROF_TCTX_SENTINEL. */ } } @@ -133,7 +177,8 @@ arena_decay_ticks(tsdn_t *tsdn, arena_t *arena, unsigned nticks) { */ ticker_geom_t *decay_ticker = tsd_arena_decay_tickerp_get(tsd); uint64_t *prng_state = tsd_prng_statep_get(tsd); - if (unlikely(ticker_geom_ticks(decay_ticker, prng_state, nticks))) { + if (unlikely(ticker_geom_ticks(decay_ticker, prng_state, nticks, + tsd_reentrancy_level_get(tsd) > 0))) { arena_decay(tsdn, arena, false, false); } } @@ -145,23 +190,25 @@ arena_decay_tick(tsdn_t *tsdn, arena_t *arena) { JEMALLOC_ALWAYS_INLINE void * arena_malloc(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind, bool zero, - tcache_t *tcache, bool slow_path) { + bool slab, tcache_t *tcache, bool slow_path) { assert(!tsdn_null(tsdn) || tcache == NULL); if (likely(tcache != NULL)) { - if (likely(size <= SC_SMALL_MAXCLASS)) { + if (likely(slab)) { + assert(sz_can_use_slab(size)); return tcache_alloc_small(tsdn_tsd(tsdn), arena, tcache, size, ind, zero, slow_path); - } - if (likely(size <= tcache_maxclass)) { + } else if (likely( + ind < tcache_nbins_get(tcache->tcache_slow) && + !tcache_bin_disabled(ind, &tcache->bins[ind], + tcache->tcache_slow))) { return tcache_alloc_large(tsdn_tsd(tsdn), arena, tcache, size, ind, zero, slow_path); } - /* (size > tcache_maxclass) case falls through. */ - assert(size > tcache_maxclass); + /* (size > tcache_max) case falls through. */ } - return arena_malloc_hard(tsdn, arena, size, ind, zero); + return arena_malloc_hard(tsdn, arena, size, ind, zero, slab); } JEMALLOC_ALWAYS_INLINE arena_t * @@ -212,35 +259,6 @@ arena_vsalloc(tsdn_t *tsdn, const void *ptr) { return sz_index2size(full_alloc_ctx.szind); } -JEMALLOC_ALWAYS_INLINE bool -large_dalloc_safety_checks(edata_t *edata, void *ptr, szind_t szind) { - if (!config_opt_safety_checks) { - return false; - } - - /* - * Eagerly detect double free and sized dealloc bugs for large sizes. - * The cost is low enough (as edata will be accessed anyway) to be - * enabled all the time. - */ - if (unlikely(edata == NULL || - edata_state_get(edata) != extent_state_active)) { - safety_check_fail("Invalid deallocation detected: " - "pages being freed (%p) not currently active, " - "possibly caused by double free bugs.", - (uintptr_t)edata_addr_get(edata)); - return true; - } - size_t input_size = sz_index2size(szind); - if (unlikely(input_size != edata_usize_get(edata))) { - safety_check_fail_sized_dealloc(/* current_dealloc */ true, ptr, - /* true_size */ edata_usize_get(edata), input_size); - return true; - } - - return false; -} - static inline void arena_dalloc_large_no_tcache(tsdn_t *tsdn, void *ptr, szind_t szind) { if (config_prof && unlikely(szind < SC_NBINS)) { @@ -282,24 +300,76 @@ arena_dalloc_no_tcache(tsdn_t *tsdn, void *ptr) { JEMALLOC_ALWAYS_INLINE void arena_dalloc_large(tsdn_t *tsdn, void *ptr, tcache_t *tcache, szind_t szind, bool slow_path) { - if (szind < nhbins) { - if (config_prof && unlikely(szind < SC_NBINS)) { - arena_dalloc_promoted(tsdn, ptr, tcache, slow_path); - } else { + assert (!tsdn_null(tsdn) && tcache != NULL); + bool is_sample_promoted = config_prof && szind < SC_NBINS; + if (unlikely(is_sample_promoted)) { + arena_dalloc_promoted(tsdn, ptr, tcache, slow_path); + } else { + if (szind < tcache_nbins_get(tcache->tcache_slow) && + !tcache_bin_disabled(szind, &tcache->bins[szind], + tcache->tcache_slow)) { tcache_dalloc_large(tsdn_tsd(tsdn), tcache, ptr, szind, slow_path); + } else { + edata_t *edata = emap_edata_lookup(tsdn, + &arena_emap_global, ptr); + if (large_dalloc_safety_checks(edata, ptr, szind)) { + /* See the comment in isfree. */ + return; + } + large_dalloc(tsdn, edata); } - } else { - edata_t *edata = emap_edata_lookup(tsdn, &arena_emap_global, - ptr); - if (large_dalloc_safety_checks(edata, ptr, szind)) { - /* See the comment in isfree. */ - return; - } - large_dalloc(tsdn, edata); } } +/* Find the region index of a pointer. */ +JEMALLOC_ALWAYS_INLINE size_t +arena_slab_regind_impl(div_info_t* div_info, szind_t binind, + edata_t *slab, const void *ptr) { + size_t diff, regind; + + /* Freeing a pointer outside the slab can cause assertion failure. */ + assert((uintptr_t)ptr >= (uintptr_t)edata_addr_get(slab)); + assert((uintptr_t)ptr < (uintptr_t)edata_past_get(slab)); + /* Freeing an interior pointer can cause assertion failure. */ + assert(((uintptr_t)ptr - (uintptr_t)edata_addr_get(slab)) % + (uintptr_t)bin_infos[binind].reg_size == 0); + + diff = (size_t)((uintptr_t)ptr - (uintptr_t)edata_addr_get(slab)); + + /* Avoid doing division with a variable divisor. */ + regind = div_compute(div_info, diff); + assert(regind < bin_infos[binind].nregs); + return regind; +} + +/* Checks whether ptr is currently active in the arena. */ +JEMALLOC_ALWAYS_INLINE bool +arena_tcache_dalloc_small_safety_check(tsdn_t *tsdn, void *ptr) { + if (!config_debug) { + return false; + } + edata_t *edata = emap_edata_lookup(tsdn, &arena_emap_global, ptr); + szind_t binind = edata_szind_get(edata); + div_info_t div_info = arena_binind_div_info[binind]; + /* + * Calls the internal function arena_slab_regind_impl because the + * safety check does not require a lock. + */ + size_t regind = arena_slab_regind_impl(&div_info, binind, edata, ptr); + slab_data_t *slab_data = edata_slab_data_get(edata); + const bin_info_t *bin_info = &bin_infos[binind]; + assert(edata_nfree_get(edata) < bin_info->nregs); + if (unlikely(!bitmap_get(slab_data->bitmap, &bin_info->bitmap_info, + regind))) { + safety_check_fail( + "Invalid deallocation detected: the pointer being freed (%p) not " + "currently active, possibly caused by double free bugs.\n", ptr); + return true; + } + return false; +} + JEMALLOC_ALWAYS_INLINE void arena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache, emap_alloc_ctx_t *caller_alloc_ctx, bool slow_path) { @@ -315,7 +385,7 @@ arena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache, if (caller_alloc_ctx != NULL) { alloc_ctx = *caller_alloc_ctx; } else { - util_assume(!tsdn_null(tsdn)); + util_assume(tsdn != NULL); emap_alloc_ctx_lookup(tsdn, &arena_emap_global, ptr, &alloc_ctx); } @@ -330,6 +400,9 @@ arena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache, if (likely(alloc_ctx.slab)) { /* Small allocation. */ + if (arena_tcache_dalloc_small_safety_check(tsdn, ptr)) { + return; + } tcache_dalloc_small(tsdn_tsd(tsdn), tcache, ptr, alloc_ctx.szind, slow_path); } else { @@ -417,6 +490,9 @@ arena_sdalloc(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache, if (likely(alloc_ctx.slab)) { /* Small allocation. */ + if (arena_tcache_dalloc_small_safety_check(tsdn, ptr)) { + return; + } tcache_dalloc_small(tsdn_tsd(tsdn), tcache, ptr, alloc_ctx.szind, slow_path); } else { @@ -444,7 +520,7 @@ arena_cache_oblivious_randomize(tsdn_t *tsdn, arena_t *arena, edata_t *edata, } uintptr_t random_offset = ((uintptr_t)r) << (LG_PAGE - lg_range); - edata->e_addr = (void *)((uintptr_t)edata->e_addr + + edata->e_addr = (void *)((byte_t *)edata->e_addr + random_offset); assert(ALIGNMENT_ADDR2BASE(edata->e_addr, alignment) == edata->e_addr); @@ -467,22 +543,7 @@ struct arena_dalloc_bin_locked_info_s { JEMALLOC_ALWAYS_INLINE size_t arena_slab_regind(arena_dalloc_bin_locked_info_t *info, szind_t binind, edata_t *slab, const void *ptr) { - size_t diff, regind; - - /* Freeing a pointer outside the slab can cause assertion failure. */ - assert((uintptr_t)ptr >= (uintptr_t)edata_addr_get(slab)); - assert((uintptr_t)ptr < (uintptr_t)edata_past_get(slab)); - /* Freeing an interior pointer can cause assertion failure. */ - assert(((uintptr_t)ptr - (uintptr_t)edata_addr_get(slab)) % - (uintptr_t)bin_infos[binind].reg_size == 0); - - diff = (size_t)((uintptr_t)ptr - (uintptr_t)edata_addr_get(slab)); - - /* Avoid doing division with a variable divisor. */ - regind = div_compute(&info->div_info, diff); - - assert(regind < bin_infos[binind].nregs); - + size_t regind = arena_slab_regind_impl(&info->div_info, binind, slab, ptr); return regind; } @@ -545,10 +606,8 @@ arena_dalloc_bin_locked_finish(tsdn_t *tsdn, arena_t *arena, bin_t *bin, static inline bin_t * arena_get_bin(arena_t *arena, szind_t binind, unsigned binshard) { - bin_t *shard0 = (bin_t *)((uintptr_t)arena + arena_bin_offsets[binind]); + bin_t *shard0 = (bin_t *)((byte_t *)arena + arena_bin_offsets[binind]); return shard0 + binshard; } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ARENA_INLINES_B_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_stats.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_stats.h index 3d37da186b6..3d512630c33 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_stats.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_stats.h @@ -1,6 +1,7 @@ #ifndef JEMALLOC_INTERNAL_ARENA_STATS_H #define JEMALLOC_INTERNAL_ARENA_STATS_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/lockedint.h" #include "jemalloc/internal/mutex.h" @@ -8,8 +9,6 @@ #include "jemalloc/internal/pa.h" #include "jemalloc/internal/sc.h" -namespace duckdb_jemalloc { - JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS typedef struct arena_stats_large_s arena_stats_large_t; @@ -53,6 +52,8 @@ struct arena_stats_s { * in pa_shard_stats_t. */ size_t base; /* Derived. */ + size_t metadata_edata; /* Derived. */ + size_t metadata_rtree; /* Derived. */ size_t resident; /* Derived. */ size_t metadata_thp; /* Derived. */ size_t mapped; /* Derived. */ @@ -113,6 +114,4 @@ arena_stats_large_flush_nrequests_add(tsdn_t *tsdn, arena_stats_t *arena_stats, LOCKEDINT_MTX_UNLOCK(tsdn, arena_stats->mtx); } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ARENA_STATS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_structs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_structs.h index a6a26c690a9..803ed25c81c 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_structs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_structs.h @@ -1,6 +1,7 @@ #ifndef JEMALLOC_INTERNAL_ARENA_STRUCTS_H #define JEMALLOC_INTERNAL_ARENA_STRUCTS_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/arena_stats.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/bin.h" @@ -17,8 +18,6 @@ #include "jemalloc/internal/sc.h" #include "jemalloc/internal/ticker.h" -namespace duckdb_jemalloc { - struct arena_s { /* * Number of threads currently assigned to this arena. Each thread has @@ -93,13 +92,19 @@ struct arena_s { /* Used to determine uptime. Read-only after initialization. */ nstime_t create_time; + /* The name of the arena. */ + char name[ARENA_NAME_LEN]; + /* * The arena is allocated alongside its bins; really this is a * dynamically sized array determined by the binshard settings. + * Enforcing cacheline-alignment to minimize the number of cachelines + * touched on the hot paths. */ - bin_t bins[0]; + JEMALLOC_WARN_ON_USAGE("Do not use this field directly. " + "Use `arena_get_bin` instead.") + JEMALLOC_ALIGNED(CACHELINE) + bin_t all_bins[0]; }; -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ARENA_STRUCTS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_types.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_types.h index 8463928d978..a1fc8926e41 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_types.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/arena_types.h @@ -1,16 +1,16 @@ #ifndef JEMALLOC_INTERNAL_ARENA_TYPES_H #define JEMALLOC_INTERNAL_ARENA_TYPES_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/sc.h" -#include "jemalloc/jemalloc_typedefs.h" /* Default decay times in milliseconds. */ #define DIRTY_DECAY_MS_DEFAULT ZD(10 * 1000) #define MUZZY_DECAY_MS_DEFAULT (0) /* Number of event ticks between time checks. */ #define ARENA_DECAY_NTICKS_PER_UPDATE 1000 - -namespace duckdb_jemalloc { +/* Maximum length of the arena name. */ +#define ARENA_NAME_LEN 32 typedef struct arena_decay_s arena_decay_t; typedef struct arena_s arena_t; @@ -58,6 +58,4 @@ typedef struct arena_config_s arena_config_t; extern const arena_config_t arena_config_default; -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ARENA_TYPES_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/assert.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/assert.h index 78e1b9572ef..38eb2a2c0b2 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/assert.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/assert.h @@ -1,11 +1,7 @@ -#ifndef JEMALLOC_INTERNAL_ASSERT_H -#define JEMALLOC_INTERNAL_ASSERT_H - +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/util.h" -namespace duckdb_jemalloc { - /* * Define a custom assert() in order to reduce the chances of deadlock during * assertion failure. @@ -16,7 +12,7 @@ namespace duckdb_jemalloc { malloc_printf( \ ": %s:%d: Failed assertion: \"%s\"\n", \ __FILE__, __LINE__, #e); \ - jemalloc_abort(); \ + abort(); \ } \ } while (0) #endif @@ -27,7 +23,7 @@ namespace duckdb_jemalloc { malloc_printf( \ ": %s:%d: Unreachable code reached\n", \ __FILE__, __LINE__); \ - jemalloc_abort(); \ + abort(); \ } \ unreachable(); \ } while (0) @@ -38,7 +34,7 @@ namespace duckdb_jemalloc { if (config_debug) { \ malloc_printf(": %s:%d: Not implemented\n", \ __FILE__, __LINE__); \ - jemalloc_abort(); \ + abort(); \ } \ } while (0) #endif @@ -59,7 +55,3 @@ namespace duckdb_jemalloc { } \ } while (0) #endif - -} // namespace duckdb_jemalloc - -#endif /* JEMALLOC_INTERNAL_ASSERT_H */ \ No newline at end of file diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic.h index 32e72b28a62..6dd2a7c60ae 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic.h @@ -1,7 +1,7 @@ #ifndef JEMALLOC_INTERNAL_ATOMIC_H #define JEMALLOC_INTERNAL_ATOMIC_H -#define ATOMIC_INLINE JEMALLOC_ALWAYS_INLINE +#include "jemalloc/internal/jemalloc_preamble.h" #define JEMALLOC_U8_ATOMICS #if defined(JEMALLOC_GCC_ATOMIC_ATOMICS) @@ -22,6 +22,8 @@ # error "Don't have atomics implemented on this platform." #endif +#define ATOMIC_INLINE JEMALLOC_ALWAYS_INLINE + /* * This header gives more or less a backport of C11 atomics. The user can write * JEMALLOC_GENERATE_ATOMICS(type, short_type, lg_sizeof_type); to generate @@ -51,8 +53,6 @@ #define ATOMIC_ACQ_REL atomic_memory_order_acq_rel #define ATOMIC_SEQ_CST atomic_memory_order_seq_cst -namespace duckdb_jemalloc { - /* * Another convenience -- simple atomic helper functions. */ @@ -106,6 +106,4 @@ JEMALLOC_GENERATE_EXPANDED_INT_ATOMICS(uint64_t, u64, 3) #undef ATOMIC_INLINE -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ATOMIC_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_c11.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_c11.h index 3c07b207228..74173b0313e 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_c11.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_c11.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_ATOMIC_C11_H #define JEMALLOC_INTERNAL_ATOMIC_C11_H +#include "jemalloc/internal/jemalloc_preamble.h" #include -namespace duckdb_jemalloc { - #define ATOMIC_INIT(...) ATOMIC_VAR_INIT(__VA_ARGS__) #define atomic_memory_order_t memory_order @@ -96,6 +95,4 @@ atomic_fetch_xor_##short_type(atomic_##short_type##_t *a, \ return atomic_fetch_xor_explicit(a, val, mo); \ } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ATOMIC_C11_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_gcc_atomic.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_gcc_atomic.h index 4a5c288b688..0819fde1716 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_gcc_atomic.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_gcc_atomic.h @@ -1,9 +1,12 @@ #ifndef JEMALLOC_INTERNAL_ATOMIC_GCC_ATOMIC_H #define JEMALLOC_INTERNAL_ATOMIC_GCC_ATOMIC_H -#define ATOMIC_INIT(...) {__VA_ARGS__} +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/assert.h" + +#define ATOMIC_INLINE JEMALLOC_ALWAYS_INLINE -namespace duckdb_jemalloc { +#define ATOMIC_INIT(...) {__VA_ARGS__} typedef enum { atomic_memory_order_relaxed, @@ -126,6 +129,6 @@ atomic_fetch_xor_##short_type(atomic_##short_type##_t *a, type val, \ atomic_enum_to_builtin(mo)); \ } -} // namespace duckdb_jemalloc +#undef ATOMIC_INLINE #endif /* JEMALLOC_INTERNAL_ATOMIC_GCC_ATOMIC_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h index 451f8994561..21136bd0de6 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h @@ -1,7 +1,9 @@ #ifndef JEMALLOC_INTERNAL_ATOMIC_GCC_SYNC_H #define JEMALLOC_INTERNAL_ATOMIC_GCC_SYNC_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" + +#define ATOMIC_INLINE JEMALLOC_ALWAYS_INLINE #define ATOMIC_INIT(...) {__VA_ARGS__} @@ -194,6 +196,6 @@ atomic_fetch_xor_##short_type(atomic_##short_type##_t *a, type val, \ return __sync_fetch_and_xor(&a->repr, val); \ } -} // namespace duckdb_jemalloc +#undef ATOMIC_INLINE #endif /* JEMALLOC_INTERNAL_ATOMIC_GCC_SYNC_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_msvc.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_msvc.h index 65d0d41a182..a429f1abdb0 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_msvc.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/atomic_msvc.h @@ -1,7 +1,9 @@ #ifndef JEMALLOC_INTERNAL_ATOMIC_MSVC_H #define JEMALLOC_INTERNAL_ATOMIC_MSVC_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" + +#define ATOMIC_INLINE JEMALLOC_ALWAYS_INLINE #define ATOMIC_INIT(...) {__VA_ARGS__} @@ -157,6 +159,6 @@ atomic_fetch_xor_##short_type(atomic_##short_type##_t *a, \ &a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val); \ } -} // namespace duckdb_jemalloc +#undef ATOMIC_INLINE #endif /* JEMALLOC_INTERNAL_ATOMIC_MSVC_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_externs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_externs.h index 8ac174782a5..0d34ee550f9 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_externs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_externs.h @@ -1,7 +1,10 @@ #ifndef JEMALLOC_INTERNAL_BACKGROUND_THREAD_EXTERNS_H #define JEMALLOC_INTERNAL_BACKGROUND_THREAD_EXTERNS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/background_thread_structs.h" +#include "jemalloc/internal/base.h" +#include "jemalloc/internal/mutex.h" extern bool opt_background_thread; extern size_t opt_max_background_threads; @@ -32,6 +35,4 @@ extern int pthread_create_wrapper(pthread_t *__restrict, const pthread_attr_t *, bool background_thread_boot0(void); bool background_thread_boot1(tsdn_t *tsdn, base_t *base); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BACKGROUND_THREAD_EXTERNS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_inlines.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_inlines.h index 5509570d542..4ed05d1b9ba 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_inlines.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_inlines.h @@ -1,7 +1,10 @@ #ifndef JEMALLOC_INTERNAL_BACKGROUND_THREAD_INLINES_H #define JEMALLOC_INTERNAL_BACKGROUND_THREAD_INLINES_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_inlines_a.h" +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/background_thread_externs.h" JEMALLOC_ALWAYS_INLINE bool background_thread_enabled(void) { @@ -47,6 +50,4 @@ background_thread_indefinite_sleep(background_thread_info_t *info) { return atomic_load_b(&info->indefinite_sleep, ATOMIC_ACQUIRE); } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BACKGROUND_THREAD_INLINES_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_structs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_structs.h index 220b3f8e2e7..67b6879745d 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_structs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/background_thread_structs.h @@ -1,7 +1,8 @@ #ifndef JEMALLOC_INTERNAL_BACKGROUND_THREAD_STRUCTS_H #define JEMALLOC_INTERNAL_BACKGROUND_THREAD_STRUCTS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/mutex.h" /* This file really combines "structs" and "types", but only transitionally. */ @@ -65,6 +66,4 @@ struct background_thread_stats_s { }; typedef struct background_thread_stats_s background_thread_stats_t; -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BACKGROUND_THREAD_STRUCTS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/base.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/base.h index e05152d02f6..86b0cf4a6fb 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/base.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/base.h @@ -1,12 +1,11 @@ #ifndef JEMALLOC_INTERNAL_BASE_H #define JEMALLOC_INTERNAL_BASE_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/edata.h" #include "jemalloc/internal/ehooks.h" #include "jemalloc/internal/mutex.h" -namespace duckdb_jemalloc { - enum metadata_thp_mode_e { metadata_thp_disabled = 0, /* @@ -25,7 +24,7 @@ typedef enum metadata_thp_mode_e metadata_thp_mode_t; #define METADATA_THP_DEFAULT metadata_thp_disabled extern metadata_thp_mode_t opt_metadata_thp; -extern const char *metadata_thp_mode_names[]; +extern const char *const metadata_thp_mode_names[]; /* Embedded at the beginning of every block of base-managed virtual memory. */ @@ -74,8 +73,13 @@ struct base_s { /* Heap of extents that track unused trailing space within blocks. */ edata_heap_t avail[SC_NSIZES]; + /* Contains reusable base edata (used by tcache_stacks currently). */ + edata_avail_t edata_avail; + /* Stats, only maintained if config_stats. */ size_t allocated; + size_t edata_allocated; + size_t rtree_allocated; size_t resident; size_t mapped; /* Number of THP regions touched. */ @@ -102,13 +106,15 @@ extent_hooks_t *base_extent_hooks_set(base_t *base, extent_hooks_t *extent_hooks); void *base_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment); edata_t *base_alloc_edata(tsdn_t *tsdn, base_t *base); +void *base_alloc_rtree(tsdn_t *tsdn, base_t *base, size_t size); +void *b0_alloc_tcache_stack(tsdn_t *tsdn, size_t size); +void b0_dalloc_tcache_stack(tsdn_t *tsdn, void *tcache_stack); void base_stats_get(tsdn_t *tsdn, base_t *base, size_t *allocated, - size_t *resident, size_t *mapped, size_t *n_thp); + size_t *edata_allocated, size_t *rtree_allocated, size_t *resident, + size_t *mapped, size_t *n_thp); void base_prefork(tsdn_t *tsdn, base_t *base); void base_postfork_parent(tsdn_t *tsdn, base_t *base); void base_postfork_child(tsdn_t *tsdn, base_t *base); bool base_boot(tsdn_t *tsdn); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BASE_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/bin.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/bin.h index 1d35260c31c..ed27c18f1ee 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/bin.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/bin.h @@ -1,14 +1,13 @@ #ifndef JEMALLOC_INTERNAL_BIN_H #define JEMALLOC_INTERNAL_BIN_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/bin_stats.h" #include "jemalloc/internal/bin_types.h" #include "jemalloc/internal/edata.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/sc.h" -namespace duckdb_jemalloc { - /* * A bin contains a set of extents that are currently being used for slab * allocations. @@ -50,7 +49,7 @@ struct bins_s { bin_t *bin_shards; }; -void bin_shard_sizes_boot(unsigned bin_shards[SC_NBINS]); +void bin_shard_sizes_boot(unsigned bin_shard_sizes[SC_NBINS]); bool bin_update_shard_size(unsigned bin_shards[SC_NBINS], size_t start_size, size_t end_size, size_t nshards); @@ -81,6 +80,4 @@ bin_stats_merge(tsdn_t *tsdn, bin_stats_data_t *dst_bin_stats, bin_t *bin) { malloc_mutex_unlock(tsdn, &bin->lock); } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BIN_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_info.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_info.h index 6e00f0d718e..b6175550e1c 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_info.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_info.h @@ -1,11 +1,9 @@ #ifndef JEMALLOC_INTERNAL_BIN_INFO_H #define JEMALLOC_INTERNAL_BIN_INFO_H -#include "jemalloc/internal/jemalloc_internal_decls.h" +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/bitmap.h" -namespace duckdb_jemalloc { - /* * Read-only information associated with each element of arena_t's bins array * is stored separately, partly to reduce memory usage (only one copy, rather @@ -50,6 +48,4 @@ extern bin_info_t bin_infos[SC_NBINS]; void bin_info_boot(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BIN_INFO_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_stats.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_stats.h index 5f5d0eae5cd..f95b9e9c445 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_stats.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_stats.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_BIN_STATS_H #define JEMALLOC_INTERNAL_BIN_STATS_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/mutex_prof.h" -namespace duckdb_jemalloc { - typedef struct bin_stats_s bin_stats_t; struct bin_stats_s { /* @@ -56,7 +55,4 @@ struct bin_stats_data_s { bin_stats_t stats_data; mutex_prof_data_t mutex_data; }; - -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BIN_STATS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_types.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_types.h index acb8b9fe230..5ec22dfdc8e 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_types.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/bin_types.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_BIN_TYPES_H #define JEMALLOC_INTERNAL_BIN_TYPES_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/sc.h" -namespace duckdb_jemalloc { - #define BIN_SHARDS_MAX (1 << EDATA_BITS_BINSHARD_WIDTH) #define N_BIN_SHARDS_DEFAULT 1 @@ -16,6 +15,4 @@ struct tsd_binshards_s { uint8_t binshard[SC_NBINS]; }; -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BIN_TYPES_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/bit_util.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/bit_util.h index 94c2ff75f57..c413a75d0ec 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/bit_util.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/bit_util.h @@ -1,8 +1,8 @@ #ifndef JEMALLOC_INTERNAL_BIT_UTIL_H #define JEMALLOC_INTERNAL_BIT_UTIL_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/assert.h" -#include "jemalloc/internal/util.h" /* Sanity check. */ #if !defined(JEMALLOC_INTERNAL_FFSLL) || !defined(JEMALLOC_INTERNAL_FFSL) \ @@ -10,8 +10,6 @@ # error JEMALLOC_INTERNAL_FFS{,L,LL} should have been defined by configure #endif -namespace duckdb_jemalloc { - /* * Unlike the builtins and posix ffs functions, our ffs requires a non-zero * input, and returns the position of the lowest bit set (as opposed to the @@ -343,7 +341,6 @@ ffs_u32(uint32_t x) { #else #error No implementation for 32-bit ffs() #endif - return ffs_u(x); } static inline unsigned @@ -353,7 +350,6 @@ fls_u32(uint32_t x) { #else #error No implementation for 32-bit fls() #endif - return fls_u(x); } static inline uint64_t @@ -422,6 +418,4 @@ lg_ceil(size_t x) { #define LG_CEIL(x) (LG_FLOOR(x) + (((x) & ((x) - 1)) == 0 ? 0 : 1)) -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BIT_UTIL_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/bitmap.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/bitmap.h index a7e6c258d86..e501da47526 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/bitmap.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/bitmap.h @@ -1,11 +1,10 @@ #ifndef JEMALLOC_INTERNAL_BITMAP_H #define JEMALLOC_INTERNAL_BITMAP_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/bit_util.h" #include "jemalloc/internal/sc.h" -namespace duckdb_jemalloc { - typedef unsigned long bitmap_t; #define LG_SIZEOF_BITMAP LG_SIZEOF_LONG @@ -112,7 +111,7 @@ typedef unsigned long bitmap_t; /* nbits. */ \ nbits, \ /* nlevels. */ \ - (uint32_t)(BITMAP_GROUPS_L0(nbits) > BITMAP_GROUPS_L1(nbits)) + \ + (BITMAP_GROUPS_L0(nbits) > BITMAP_GROUPS_L1(nbits)) + \ (BITMAP_GROUPS_L1(nbits) > BITMAP_GROUPS_L2(nbits)) + \ (BITMAP_GROUPS_L2(nbits) > BITMAP_GROUPS_L3(nbits)) + \ (BITMAP_GROUPS_L3(nbits) > BITMAP_GROUPS_L4(nbits)) + 1, \ @@ -367,6 +366,4 @@ bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) { #endif /* BITMAP_USE_TREE */ } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BITMAP_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/buf_writer.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/buf_writer.h index d5f1bfcbd9a..fa0ac99cfd6 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/buf_writer.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/buf_writer.h @@ -1,7 +1,9 @@ #ifndef JEMALLOC_INTERNAL_BUF_WRITER_H #define JEMALLOC_INTERNAL_BUF_WRITER_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/tsd_types.h" /* * Note: when using the buffered writer, cbopaque is passed to write_cb only @@ -31,6 +33,4 @@ typedef ssize_t (read_cb_t)(void *read_cbopaque, void *buf, size_t limit); void buf_writer_pipe(buf_writer_t *buf_writer, read_cb_t *read_cb, void *read_cbopaque); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_BUF_WRITER_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/cache_bin.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/cache_bin.h index 482fbd975bf..a26c3671d0a 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/cache_bin.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/cache_bin.h @@ -1,12 +1,12 @@ #ifndef JEMALLOC_INTERNAL_CACHE_BIN_H #define JEMALLOC_INTERNAL_CACHE_BIN_H -#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_externs.h" #include "jemalloc/internal/ql.h" +#include "jemalloc/internal/safety_check.h" #include "jemalloc/internal/sz.h" -namespace duckdb_jemalloc { - /* * The cache_bins are the mechanism that the tcache and the arena use to * communicate. The tcache fills from and flushes to the arena by passing a @@ -23,16 +23,20 @@ namespace duckdb_jemalloc { */ typedef uint16_t cache_bin_sz_t; +#define JUNK_ADDR ((uintptr_t)0x7a7a7a7a7a7a7a7aULL) /* * Leave a noticeable mark pattern on the cache bin stack boundaries, in case a * bug starts leaking those. Make it look like the junk pattern but be distinct * from it. */ -static const uintptr_t cache_bin_preceding_junk = - (uintptr_t)0x7a7a7a7a7a7a7a7aULL; -/* Note: a7 vs. 7a above -- this tells you which pointer leaked. */ -static const uintptr_t cache_bin_trailing_junk = - (uintptr_t)0xa7a7a7a7a7a7a7a7ULL; +static const uintptr_t cache_bin_preceding_junk = JUNK_ADDR; +/* Note: JUNK_ADDR vs. JUNK_ADDR + 1 -- this tells you which pointer leaked. */ +static const uintptr_t cache_bin_trailing_junk = JUNK_ADDR + 1; +/* + * A pointer used to initialize a fake stack_head for disabled small bins + * so that the enabled/disabled assessment does not rely on ncached_max. + */ +extern const uintptr_t disabled_bin; /* * That implies the following value, for the maximum number of items in any @@ -125,6 +129,9 @@ struct cache_bin_s { * array. Immutable after initialization. */ uint16_t low_bits_empty; + + /* The maximum number of cached items in the bin. */ + cache_bin_info_t bin_info; }; /* @@ -171,10 +178,41 @@ cache_bin_nonfast_aligned(const void *ptr) { return ((uintptr_t)ptr & san_cache_bin_nonfast_mask) == 0; } +static inline const void * +cache_bin_disabled_bin_stack(void) { + return &disabled_bin; +} + +/* + * If a cache bin was zero initialized (either because it lives in static or + * thread-local storage, or was memset to 0), this function indicates whether or + * not cache_bin_init was called on it. + */ +static inline bool +cache_bin_still_zero_initialized(cache_bin_t *bin) { + return bin->stack_head == NULL; +} + +static inline bool +cache_bin_disabled(cache_bin_t *bin) { + bool disabled = (bin->stack_head == cache_bin_disabled_bin_stack()); + if (disabled) { + assert((uintptr_t)(*bin->stack_head) == JUNK_ADDR); + } + return disabled; +} + +/* Gets ncached_max without asserting that the bin is enabled. */ +static inline cache_bin_sz_t +cache_bin_ncached_max_get_unsafe(cache_bin_t *bin) { + return bin->bin_info.ncached_max; +} + /* Returns ncached_max: Upper limit on ncached. */ static inline cache_bin_sz_t -cache_bin_info_ncached_max(cache_bin_info_t *info) { - return info->ncached_max; +cache_bin_ncached_max_get(cache_bin_t *bin) { + assert(!cache_bin_disabled(bin)); + return cache_bin_ncached_max_get_unsafe(bin); } /* @@ -196,28 +234,19 @@ cache_bin_assert_earlier(cache_bin_t *bin, uint16_t earlier, uint16_t later) { * Does difference calculations that handle wraparound correctly. Earlier must * be associated with the position earlier in memory. */ -static inline uint16_t -cache_bin_diff(cache_bin_t *bin, uint16_t earlier, uint16_t later, bool racy) { - /* - * When it's racy, bin->low_bits_full can be modified concurrently. It - * can cross the uint16_t max value and become less than - * bin->low_bits_empty at the time of the check. - */ - if (!racy) { - cache_bin_assert_earlier(bin, earlier, later); - } +static inline cache_bin_sz_t +cache_bin_diff(cache_bin_t *bin, uint16_t earlier, uint16_t later) { + cache_bin_assert_earlier(bin, earlier, later); return later - earlier; } /* * Number of items currently cached in the bin, without checking ncached_max. - * We require specifying whether or not the request is racy or not (i.e. whether - * or not concurrent modifications are possible). */ static inline cache_bin_sz_t -cache_bin_ncached_get_internal(cache_bin_t *bin, bool racy) { +cache_bin_ncached_get_internal(cache_bin_t *bin) { cache_bin_sz_t diff = cache_bin_diff(bin, - (uint16_t)(uintptr_t)bin->stack_head, bin->low_bits_empty, racy); + (uint16_t)(uintptr_t)bin->stack_head, bin->low_bits_empty); cache_bin_sz_t n = diff / sizeof(void *); /* * We have undefined behavior here; if this function is called from the @@ -228,7 +257,7 @@ cache_bin_ncached_get_internal(cache_bin_t *bin, bool racy) { * fast paths. This should still be "safe" in the sense of generating * the correct assembly for the foreseeable future, though. */ - assert(n == 0 || *(bin->stack_head) != NULL || racy); + assert(n == 0 || *(bin->stack_head) != NULL); return n; } @@ -238,10 +267,9 @@ cache_bin_ncached_get_internal(cache_bin_t *bin, bool racy) { * possible. */ static inline cache_bin_sz_t -cache_bin_ncached_get_local(cache_bin_t *bin, cache_bin_info_t *info) { - cache_bin_sz_t n = cache_bin_ncached_get_internal(bin, - /* racy */ false); - assert(n <= cache_bin_info_ncached_max(info)); +cache_bin_ncached_get_local(cache_bin_t *bin) { + cache_bin_sz_t n = cache_bin_ncached_get_internal(bin); + assert(n <= cache_bin_ncached_max_get(bin)); return n; } @@ -256,9 +284,8 @@ cache_bin_ncached_get_local(cache_bin_t *bin, cache_bin_info_t *info) { static inline void ** cache_bin_empty_position_get(cache_bin_t *bin) { cache_bin_sz_t diff = cache_bin_diff(bin, - (uint16_t)(uintptr_t)bin->stack_head, bin->low_bits_empty, - /* racy */ false); - uintptr_t empty_bits = (uintptr_t)bin->stack_head + diff; + (uint16_t)(uintptr_t)bin->stack_head, bin->low_bits_empty); + byte_t *empty_bits = (byte_t *)bin->stack_head + diff; void **ret = (void **)empty_bits; assert(ret >= bin->stack_head); @@ -277,9 +304,9 @@ cache_bin_empty_position_get(cache_bin_t *bin) { * arena statistics collection. */ static inline uint16_t -cache_bin_low_bits_low_bound_get(cache_bin_t *bin, cache_bin_info_t *info) { +cache_bin_low_bits_low_bound_get(cache_bin_t *bin) { return (uint16_t)bin->low_bits_empty - - info->ncached_max * sizeof(void *); + cache_bin_ncached_max_get(bin) * sizeof(void *); } /* @@ -288,8 +315,8 @@ cache_bin_low_bits_low_bound_get(cache_bin_t *bin, cache_bin_info_t *info) { * A pointer to the position with the lowest address of the backing array. */ static inline void ** -cache_bin_low_bound_get(cache_bin_t *bin, cache_bin_info_t *info) { - cache_bin_sz_t ncached_max = cache_bin_info_ncached_max(info); +cache_bin_low_bound_get(cache_bin_t *bin) { + cache_bin_sz_t ncached_max = cache_bin_ncached_max_get(bin); void **ret = cache_bin_empty_position_get(bin) - ncached_max; assert(ret <= bin->stack_head); @@ -301,8 +328,8 @@ cache_bin_low_bound_get(cache_bin_t *bin, cache_bin_info_t *info) { * batch fill a nonempty cache bin. */ static inline void -cache_bin_assert_empty(cache_bin_t *bin, cache_bin_info_t *info) { - assert(cache_bin_ncached_get_local(bin, info) == 0); +cache_bin_assert_empty(cache_bin_t *bin) { + assert(cache_bin_ncached_get_local(bin) == 0); assert(cache_bin_empty_position_get(bin) == bin->stack_head); } @@ -314,15 +341,15 @@ cache_bin_assert_empty(cache_bin_t *bin, cache_bin_info_t *info) { static inline cache_bin_sz_t cache_bin_low_water_get_internal(cache_bin_t *bin) { return cache_bin_diff(bin, bin->low_bits_low_water, - bin->low_bits_empty, /* racy */ false) / sizeof(void *); + bin->low_bits_empty) / sizeof(void *); } /* Returns the numeric value of low water in [0, ncached]. */ static inline cache_bin_sz_t -cache_bin_low_water_get(cache_bin_t *bin, cache_bin_info_t *info) { +cache_bin_low_water_get(cache_bin_t *bin) { cache_bin_sz_t low_water = cache_bin_low_water_get_internal(bin); - assert(low_water <= cache_bin_info_ncached_max(info)); - assert(low_water <= cache_bin_ncached_get_local(bin, info)); + assert(low_water <= cache_bin_ncached_max_get(bin)); + assert(low_water <= cache_bin_ncached_get_local(bin)); cache_bin_assert_earlier(bin, (uint16_t)(uintptr_t)bin->stack_head, bin->low_bits_low_water); @@ -336,12 +363,14 @@ cache_bin_low_water_get(cache_bin_t *bin, cache_bin_info_t *info) { */ static inline void cache_bin_low_water_set(cache_bin_t *bin) { + assert(!cache_bin_disabled(bin)); bin->low_bits_low_water = (uint16_t)(uintptr_t)bin->stack_head; } static inline void cache_bin_low_water_adjust(cache_bin_t *bin) { - if (cache_bin_ncached_get_internal(bin, /* racy */ false) + assert(!cache_bin_disabled(bin)); + if (cache_bin_ncached_get_internal(bin) < cache_bin_low_water_get_internal(bin)) { cache_bin_low_water_set(bin); } @@ -413,8 +442,7 @@ cache_bin_alloc(cache_bin_t *bin, bool *success) { JEMALLOC_ALWAYS_INLINE cache_bin_sz_t cache_bin_alloc_batch(cache_bin_t *bin, size_t num, void **out) { - cache_bin_sz_t n = cache_bin_ncached_get_internal(bin, - /* racy */ false); + cache_bin_sz_t n = cache_bin_ncached_get_internal(bin); if (n > num) { n = (cache_bin_sz_t)num; } @@ -430,6 +458,35 @@ cache_bin_full(cache_bin_t *bin) { return ((uint16_t)(uintptr_t)bin->stack_head == bin->low_bits_full); } +/* + * Scans the allocated area of the cache_bin for the given pointer up to limit. + * Fires safety_check_fail if the ptr is found and returns true. + */ +JEMALLOC_ALWAYS_INLINE bool +cache_bin_dalloc_safety_checks(cache_bin_t *bin, void *ptr) { + if (!config_debug || opt_debug_double_free_max_scan == 0) { + return false; + } + + cache_bin_sz_t ncached = cache_bin_ncached_get_internal(bin); + unsigned max_scan = opt_debug_double_free_max_scan < ncached + ? opt_debug_double_free_max_scan + : ncached; + + void **cur = bin->stack_head; + void **limit = cur + max_scan; + for (; cur < limit; cur++) { + if (*cur == ptr) { + safety_check_fail( + "Invalid deallocation detected: double free of " + "pointer %p\n", + ptr); + return true; + } + } + return false; +} + /* * Free an object into the given bin. Fails only if the bin is full. */ @@ -439,6 +496,10 @@ cache_bin_dalloc_easy(cache_bin_t *bin, void *ptr) { return false; } + if (unlikely(cache_bin_dalloc_safety_checks(bin, ptr))) { + return true; + } + bin->stack_head--; *bin->stack_head = ptr; cache_bin_assert_earlier(bin, bin->low_bits_full, @@ -457,9 +518,8 @@ cache_bin_stash(cache_bin_t *bin, void *ptr) { /* Stash at the full position, in the [full, head) range. */ uint16_t low_bits_head = (uint16_t)(uintptr_t)bin->stack_head; /* Wraparound handled as well. */ - uint16_t diff = cache_bin_diff(bin, bin->low_bits_full, low_bits_head, - /* racy */ false); - *(void **)((uintptr_t)bin->stack_head - diff) = ptr; + uint16_t diff = cache_bin_diff(bin, bin->low_bits_full, low_bits_head); + *(void **)((byte_t *)bin->stack_head - diff) = ptr; assert(!cache_bin_full(bin)); bin->low_bits_full += sizeof(void *); @@ -468,28 +528,18 @@ cache_bin_stash(cache_bin_t *bin, void *ptr) { return true; } -/* - * Get the number of stashed pointers. - * - * When called from a thread not owning the TLS (i.e. racy = true), it's - * important to keep in mind that 'bin->stack_head' and 'bin->low_bits_full' can - * be modified concurrently and almost none assertions about their values can be - * made. - */ +/* Get the number of stashed pointers. */ JEMALLOC_ALWAYS_INLINE cache_bin_sz_t -cache_bin_nstashed_get_internal(cache_bin_t *bin, cache_bin_info_t *info, - bool racy) { - cache_bin_sz_t ncached_max = cache_bin_info_ncached_max(info); - uint16_t low_bits_low_bound = cache_bin_low_bits_low_bound_get(bin, - info); +cache_bin_nstashed_get_internal(cache_bin_t *bin) { + cache_bin_sz_t ncached_max = cache_bin_ncached_max_get(bin); + uint16_t low_bits_low_bound = cache_bin_low_bits_low_bound_get(bin); cache_bin_sz_t n = cache_bin_diff(bin, low_bits_low_bound, - bin->low_bits_full, racy) / sizeof(void *); + bin->low_bits_full) / sizeof(void *); assert(n <= ncached_max); - - if (!racy) { + if (config_debug && n != 0) { /* Below are for assertions only. */ - void **low_bound = cache_bin_low_bound_get(bin, info); + void **low_bound = cache_bin_low_bound_get(bin); assert((uint16_t)(uintptr_t)low_bound == low_bits_low_bound); void *stashed = *(low_bound + n - 1); @@ -498,35 +548,56 @@ cache_bin_nstashed_get_internal(cache_bin_t *bin, cache_bin_info_t *info, /* Allow arbitrary pointers to be stashed in tests. */ aligned = true; #endif - assert(n == 0 || (stashed != NULL && aligned)); + assert(stashed != NULL && aligned); } return n; } JEMALLOC_ALWAYS_INLINE cache_bin_sz_t -cache_bin_nstashed_get_local(cache_bin_t *bin, cache_bin_info_t *info) { - cache_bin_sz_t n = cache_bin_nstashed_get_internal(bin, info, - /* racy */ false); - assert(n <= cache_bin_info_ncached_max(info)); +cache_bin_nstashed_get_local(cache_bin_t *bin) { + cache_bin_sz_t n = cache_bin_nstashed_get_internal(bin); + assert(n <= cache_bin_ncached_max_get(bin)); return n; } /* * Obtain a racy view of the number of items currently in the cache bin, in the * presence of possible concurrent modifications. + * + * Note that this is the only racy function in this header. Any other functions + * are assumed to be non-racy. The "racy" term here means accessed from another + * thread (that is not the owner of the specific cache bin). This only happens + * when gathering stats (read-only). The only change because of the racy + * condition is that assertions based on mutable fields are omitted. + * + * It's important to keep in mind that 'bin->stack_head' and + * 'bin->low_bits_full' can be modified concurrently and almost no assertions + * about their values can be made. + * + * This function should not call other utility functions because the racy + * condition may cause unexpected / undefined behaviors in unverified utility + * functions. Currently, this function calls two utility functions + * cache_bin_ncached_max_get and cache_bin_low_bits_low_bound_get because + * they help access values that will not be concurrently modified. */ static inline void -cache_bin_nitems_get_remote(cache_bin_t *bin, cache_bin_info_t *info, - cache_bin_sz_t *ncached, cache_bin_sz_t *nstashed) { - cache_bin_sz_t n = cache_bin_ncached_get_internal(bin, /* racy */ true); - assert(n <= cache_bin_info_ncached_max(info)); +cache_bin_nitems_get_remote(cache_bin_t *bin, cache_bin_sz_t *ncached, + cache_bin_sz_t *nstashed) { + /* Racy version of cache_bin_ncached_get_internal. */ + cache_bin_sz_t diff = bin->low_bits_empty - + (uint16_t)(uintptr_t)bin->stack_head; + cache_bin_sz_t n = diff / sizeof(void *); *ncached = n; - n = cache_bin_nstashed_get_internal(bin, info, /* racy */ true); - assert(n <= cache_bin_info_ncached_max(info)); + /* Racy version of cache_bin_nstashed_get_internal. */ + uint16_t low_bits_low_bound = cache_bin_low_bits_low_bound_get(bin); + n = (bin->low_bits_full - low_bits_low_bound) / sizeof(void *); *nstashed = n; - /* Note that cannot assert ncached + nstashed <= ncached_max (racy). */ + /* + * Note that cannot assert anything regarding ncached_max because + * it can be configured on the fly and is thus racy. + */ } /* @@ -570,9 +641,9 @@ struct cache_bin_ptr_array_s { * finish_fill call before doing any alloc/dalloc operations on the bin. */ static inline void -cache_bin_init_ptr_array_for_fill(cache_bin_t *bin, cache_bin_info_t *info, - cache_bin_ptr_array_t *arr, cache_bin_sz_t nfill) { - cache_bin_assert_empty(bin, info); +cache_bin_init_ptr_array_for_fill(cache_bin_t *bin, cache_bin_ptr_array_t *arr, + cache_bin_sz_t nfill) { + cache_bin_assert_empty(bin); arr->ptr = cache_bin_empty_position_get(bin) - nfill; } @@ -582,9 +653,9 @@ cache_bin_init_ptr_array_for_fill(cache_bin_t *bin, cache_bin_info_t *info, * case of OOM. */ static inline void -cache_bin_finish_fill(cache_bin_t *bin, cache_bin_info_t *info, - cache_bin_ptr_array_t *arr, cache_bin_sz_t nfilled) { - cache_bin_assert_empty(bin, info); +cache_bin_finish_fill(cache_bin_t *bin, cache_bin_ptr_array_t *arr, + cache_bin_sz_t nfilled) { + cache_bin_assert_empty(bin); void **empty_position = cache_bin_empty_position_get(bin); if (nfilled < arr->n) { memmove(empty_position - nfilled, empty_position - arr->n, @@ -598,42 +669,41 @@ cache_bin_finish_fill(cache_bin_t *bin, cache_bin_info_t *info, * everything we give them. */ static inline void -cache_bin_init_ptr_array_for_flush(cache_bin_t *bin, cache_bin_info_t *info, +cache_bin_init_ptr_array_for_flush(cache_bin_t *bin, cache_bin_ptr_array_t *arr, cache_bin_sz_t nflush) { arr->ptr = cache_bin_empty_position_get(bin) - nflush; - assert(cache_bin_ncached_get_local(bin, info) == 0 + assert(cache_bin_ncached_get_local(bin) == 0 || *arr->ptr != NULL); } static inline void -cache_bin_finish_flush(cache_bin_t *bin, cache_bin_info_t *info, - cache_bin_ptr_array_t *arr, cache_bin_sz_t nflushed) { - unsigned rem = cache_bin_ncached_get_local(bin, info) - nflushed; +cache_bin_finish_flush(cache_bin_t *bin, cache_bin_ptr_array_t *arr, + cache_bin_sz_t nflushed) { + unsigned rem = cache_bin_ncached_get_local(bin) - nflushed; memmove(bin->stack_head + nflushed, bin->stack_head, rem * sizeof(void *)); - bin->stack_head = bin->stack_head + nflushed; + bin->stack_head += nflushed; cache_bin_low_water_adjust(bin); } static inline void cache_bin_init_ptr_array_for_stashed(cache_bin_t *bin, szind_t binind, - cache_bin_info_t *info, cache_bin_ptr_array_t *arr, - cache_bin_sz_t nstashed) { + cache_bin_ptr_array_t *arr, cache_bin_sz_t nstashed) { assert(nstashed > 0); - assert(cache_bin_nstashed_get_local(bin, info) == nstashed); + assert(cache_bin_nstashed_get_local(bin) == nstashed); - void **low_bound = cache_bin_low_bound_get(bin, info); + void **low_bound = cache_bin_low_bound_get(bin); arr->ptr = low_bound; assert(*arr->ptr != NULL); } static inline void -cache_bin_finish_flush_stashed(cache_bin_t *bin, cache_bin_info_t *info) { - void **low_bound = cache_bin_low_bound_get(bin, info); +cache_bin_finish_flush_stashed(cache_bin_t *bin) { + void **low_bound = cache_bin_low_bound_get(bin); /* Reset the bin local full position. */ bin->low_bits_full = (uint16_t)(uintptr_t)low_bound; - assert(cache_bin_nstashed_get_local(bin, info) == 0); + assert(cache_bin_nstashed_get_local(bin) == 0); } /* @@ -646,8 +716,8 @@ void cache_bin_info_init(cache_bin_info_t *bin_info, * Given an array of initialized cache_bin_info_ts, determine how big an * allocation is required to initialize a full set of cache_bin_ts. */ -void cache_bin_info_compute_alloc(cache_bin_info_t *infos, szind_t ninfos, - size_t *size, size_t *alignment); +void cache_bin_info_compute_alloc(const cache_bin_info_t *infos, + szind_t ninfos, size_t *size, size_t *alignment); /* * Actually initialize some cache bins. Callers should allocate the backing @@ -656,20 +726,13 @@ void cache_bin_info_compute_alloc(cache_bin_info_t *infos, szind_t ninfos, * cache_bin_postincrement. *alloc_cur will then point immediately past the end * of the allocation. */ -void cache_bin_preincrement(cache_bin_info_t *infos, szind_t ninfos, +void cache_bin_preincrement(const cache_bin_info_t *infos, szind_t ninfos, void *alloc, size_t *cur_offset); -void cache_bin_postincrement(cache_bin_info_t *infos, szind_t ninfos, +void cache_bin_postincrement(void *alloc, size_t *cur_offset); +void cache_bin_init(cache_bin_t *bin, const cache_bin_info_t *info, void *alloc, size_t *cur_offset); -void cache_bin_init(cache_bin_t *bin, cache_bin_info_t *info, void *alloc, - size_t *cur_offset); - -/* - * If a cache bin was zero initialized (either because it lives in static or - * thread-local storage, or was memset to 0), this function indicates whether or - * not cache_bin_init was called on it. - */ -bool cache_bin_still_zero_initialized(cache_bin_t *bin); +void cache_bin_init_disabled(cache_bin_t *bin, cache_bin_sz_t ncached_max); -} // namespace duckdb_jemalloc +bool cache_bin_stack_use_thp(void); #endif /* JEMALLOC_INTERNAL_CACHE_BIN_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/ckh.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/ckh.h index e6d2203a4d2..8e9d7fedd5d 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/ckh.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/ckh.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_CKH_H #define JEMALLOC_INTERNAL_CKH_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/tsd.h" -namespace duckdb_jemalloc { - /* Cuckoo hashing implementation. Skip to the end for the interface. */ /******************************************************************************/ @@ -100,6 +99,4 @@ bool ckh_string_keycomp(const void *k1, const void *k2); void ckh_pointer_hash(const void *key, size_t r_hash[2]); bool ckh_pointer_keycomp(const void *k1, const void *k2); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_CKH_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/counter.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/counter.h index b4009976c07..74e307013ee 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/counter.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/counter.h @@ -1,8 +1,8 @@ #ifndef JEMALLOC_INTERNAL_COUNTER_H #define JEMALLOC_INTERNAL_COUNTER_H -namespace duckdb_jemalloc { - +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/lockedint.h" #include "jemalloc/internal/mutex.h" typedef struct counter_accum_s { @@ -33,6 +33,4 @@ void counter_prefork(tsdn_t *tsdn, counter_accum_t *counter); void counter_postfork_parent(tsdn_t *tsdn, counter_accum_t *counter); void counter_postfork_child(tsdn_t *tsdn, counter_accum_t *counter); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_COUNTER_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/ctl.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/ctl.h index 6d09f842b63..1f124bfcf08 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/ctl.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/ctl.h @@ -1,6 +1,10 @@ #ifndef JEMALLOC_INTERNAL_CTL_H #define JEMALLOC_INTERNAL_CTL_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_stats.h" +#include "jemalloc/internal/background_thread_structs.h" +#include "jemalloc/internal/bin_stats.h" #include "jemalloc/internal/jemalloc_internal_types.h" #include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/mutex_prof.h" @@ -8,10 +12,9 @@ #include "jemalloc/internal/sc.h" #include "jemalloc/internal/stats.h" -namespace duckdb_jemalloc { - /* Maximum ctl tree depth. */ #define CTL_MAX_DEPTH 7 +#define CTL_MULTI_SETTING_MAX_LEN 1000 typedef struct ctl_node_s { bool named; @@ -55,6 +58,8 @@ typedef struct ctl_stats_s { size_t allocated; size_t active; size_t metadata; + size_t metadata_edata; + size_t metadata_rtree; size_t metadata_thp; size_t resident; size_t mapped; @@ -118,7 +123,7 @@ void ctl_mtx_assert_held(tsdn_t *tsdn); malloc_printf( \ ": Failure in xmallctl(\"%s\", ...)\n", \ name); \ - jemalloc_abort(); \ + abort(); \ } \ } while (0) @@ -126,7 +131,7 @@ void ctl_mtx_assert_held(tsdn_t *tsdn); if (je_mallctlnametomib(name, mibp, miblenp) != 0) { \ malloc_printf(": Failure in " \ "xmallctlnametomib(\"%s\", ...)\n", name); \ - jemalloc_abort(); \ + abort(); \ } \ } while (0) @@ -135,7 +140,7 @@ void ctl_mtx_assert_held(tsdn_t *tsdn); newlen) != 0) { \ malloc_write( \ ": Failure in xmallctlbymib()\n"); \ - jemalloc_abort(); \ + abort(); \ } \ } while (0) @@ -144,7 +149,7 @@ void ctl_mtx_assert_held(tsdn_t *tsdn); != 0) { \ malloc_write( \ ": Failure in ctl_mibnametomib()\n"); \ - jemalloc_abort(); \ + abort(); \ } \ } while (0) @@ -154,10 +159,8 @@ void ctl_mtx_assert_held(tsdn_t *tsdn); oldp, oldlenp, newp, newlen) != 0) { \ malloc_write( \ ": Failure in ctl_bymibname()\n"); \ - jemalloc_abort(); \ + abort(); \ } \ } while (0) -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_CTL_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/decay.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/decay.h index 8cf53411837..74be55daeaf 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/decay.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/decay.h @@ -1,10 +1,10 @@ #ifndef JEMALLOC_INTERNAL_DECAY_H #define JEMALLOC_INTERNAL_DECAY_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/mutex.h" #include "jemalloc/internal/smoothstep.h" -namespace duckdb_jemalloc { - #define DECAY_UNBOUNDED_TIME_TO_PURGE ((uint64_t)-1) /* @@ -185,6 +185,4 @@ bool decay_maybe_advance_epoch(decay_t *decay, nstime_t *new_time, uint64_t decay_ns_until_purge(decay_t *decay, size_t npages_current, uint64_t npages_threshold); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_DECAY_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/div.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/div.h index 45c74bd18ed..56d5f463fa4 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/div.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/div.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_DIV_H #define JEMALLOC_INTERNAL_DIV_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/assert.h" -namespace duckdb_jemalloc { - /* * This module does the division that computes the index of a region in a slab, * given its offset relative to the base. @@ -40,6 +39,4 @@ div_compute(div_info_t *div_info, size_t n) { return i; } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_DIV_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/ecache.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/ecache.h index 95f48171687..2bd74fdef70 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/ecache.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/ecache.h @@ -1,11 +1,10 @@ #ifndef JEMALLOC_INTERNAL_ECACHE_H #define JEMALLOC_INTERNAL_ECACHE_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/eset.h" -#include "jemalloc/internal/san.h" #include "jemalloc/internal/mutex.h" - -namespace duckdb_jemalloc { +#include "jemalloc/internal/san.h" typedef struct ecache_s ecache_t; struct ecache_s { @@ -54,6 +53,4 @@ void ecache_prefork(tsdn_t *tsdn, ecache_t *ecache); void ecache_postfork_parent(tsdn_t *tsdn, ecache_t *ecache); void ecache_postfork_child(tsdn_t *tsdn, ecache_t *ecache); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ECACHE_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/edata.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/edata.h index cf3d389a47c..17befd92c4e 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/edata.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/edata.h @@ -1,20 +1,20 @@ #ifndef JEMALLOC_INTERNAL_EDATA_H #define JEMALLOC_INTERNAL_EDATA_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/bin_info.h" #include "jemalloc/internal/bit_util.h" #include "jemalloc/internal/hpdata.h" #include "jemalloc/internal/nstime.h" #include "jemalloc/internal/ph.h" +#include "jemalloc/internal/prof_types.h" #include "jemalloc/internal/ql.h" #include "jemalloc/internal/sc.h" #include "jemalloc/internal/slab_data.h" #include "jemalloc/internal/sz.h" #include "jemalloc/internal/typed_list.h" -namespace duckdb_jemalloc { - /* * sizeof(edata_t) is 128 bytes on 64-bit architectures. Ensure the alignment * to free up the low bits in the rtree leaf. @@ -377,18 +377,18 @@ edata_ps_get(const edata_t *edata) { static inline void * edata_before_get(const edata_t *edata) { - return (void *)((uintptr_t)edata_base_get(edata) - PAGE); + return (void *)((byte_t *)edata_base_get(edata) - PAGE); } static inline void * edata_last_get(const edata_t *edata) { - return (void *)((uintptr_t)edata_base_get(edata) + + return (void *)((byte_t *)edata_base_get(edata) + edata_size_get(edata) - PAGE); } static inline void * edata_past_get(const edata_t *edata) { - return (void *)((uintptr_t)edata_base_get(edata) + + return (void *)((byte_t *)edata_base_get(edata) + edata_size_get(edata)); } @@ -621,7 +621,8 @@ edata_init(edata_t *edata, unsigned arena_ind, void *addr, size_t size, } static inline void -edata_binit(edata_t *edata, void *addr, size_t bsize, uint64_t sn) { +edata_binit(edata_t *edata, void *addr, size_t bsize, uint64_t sn, + bool reused) { edata_arena_ind_set(edata, (1U << MALLOCX_ARENA_BITS) - 1); edata_addr_set(edata, addr); edata_bsize_set(edata, bsize); @@ -629,7 +630,8 @@ edata_binit(edata_t *edata, void *addr, size_t bsize, uint64_t sn) { edata_szind_set(edata, SC_NSIZES); edata_sn_set(edata, sn); edata_state_set(edata, extent_state_active); - edata_guarded_set(edata, false); + /* See comments in base_edata_is_reused. */ + edata_guarded_set(edata, reused); edata_zeroed_set(edata, true); edata_committed_set(edata, true); /* @@ -658,19 +660,28 @@ edata_ead_comp(const edata_t *a, const edata_t *b) { static inline edata_cmp_summary_t edata_cmp_summary_get(const edata_t *edata) { - return edata_cmp_summary_t{edata_sn_get(edata), - (uintptr_t)edata_addr_get(edata)}; + edata_cmp_summary_t result; + result.sn = edata_sn_get(edata); + result.addr = (uintptr_t)edata_addr_get(edata); + return result; } static inline int edata_cmp_summary_comp(edata_cmp_summary_t a, edata_cmp_summary_t b) { - int ret; - ret = (a.sn > b.sn) - (a.sn < b.sn); - if (ret != 0) { - return ret; - } - ret = (a.addr > b.addr) - (a.addr < b.addr); - return ret; + /* + * Logically, what we're doing here is comparing based on `.sn`, and + * falling back to comparing on `.addr` in the case that `a.sn == b.sn`. + * We accomplish this by multiplying the result of the `.sn` comparison + * by 2, so that so long as it is not 0, it will dominate the `.addr` + * comparison in determining the sign of the returned result value. + * The justification for doing things this way is that this is + * branchless - all of the branches that would be present in a + * straightforward implementation are common cases, and thus the branch + * prediction accuracy is not great. As a result, this implementation + * is measurably faster (by around 30%). + */ + return (2 * ((a.sn > b.sn) - (a.sn < b.sn))) + + ((a.addr > b.addr) - (a.addr < b.addr)); } static inline int @@ -683,20 +694,14 @@ edata_snad_comp(const edata_t *a, const edata_t *b) { static inline int edata_esnead_comp(const edata_t *a, const edata_t *b) { - int ret; - - ret = edata_esn_comp(a, b); - if (ret != 0) { - return ret; - } - - ret = edata_ead_comp(a, b); - return ret; + /* + * Similar to `edata_cmp_summary_comp`, we've opted for a + * branchless implementation for the sake of performance. + */ + return (2 * edata_esn_comp(a, b)) + edata_ead_comp(a, b); } ph_proto(, edata_avail, edata_t) ph_proto(, edata_heap, edata_t) -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_EDATA_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/edata_cache.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/edata_cache.h index 6dde19d9dd6..b2c7b4f1d29 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/edata_cache.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/edata_cache.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_EDATA_CACHE_H #define JEMALLOC_INTERNAL_EDATA_CACHE_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/base.h" -namespace duckdb_jemalloc { - /* For tests only. */ #define EDATA_CACHE_FAST_FILL 4 @@ -48,6 +47,4 @@ void edata_cache_fast_put(tsdn_t *tsdn, edata_cache_fast_t *ecs, edata_t *edata); void edata_cache_fast_disable(tsdn_t *tsdn, edata_cache_fast_t *ecs); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_EDATA_CACHE_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/ehooks.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/ehooks.h index 02cceedf65d..947e056c45e 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/ehooks.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/ehooks.h @@ -1,10 +1,11 @@ #ifndef JEMALLOC_INTERNAL_EHOOKS_H #define JEMALLOC_INTERNAL_EHOOKS_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/extent_mmap.h" - -namespace duckdb_jemalloc { +#include "jemalloc/internal/tsd.h" +#include "jemalloc/internal/tsd_types.h" /* * This module is the internal interface to the extent hooks (both @@ -55,7 +56,7 @@ bool ehooks_default_purge_lazy_impl(void *addr, size_t offset, size_t length); #ifdef PAGES_CAN_PURGE_FORCED bool ehooks_default_purge_forced_impl(void *addr, size_t offset, size_t length); #endif -bool ehooks_default_split_impl(); +bool ehooks_default_split_impl(void); /* * Merge is the only default extent hook we declare -- see the comment in * ehooks_merge. @@ -411,6 +412,4 @@ ehooks_unguard(tsdn_t *tsdn, ehooks_t *ehooks, void *guard1, void *guard2) { return err; } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_EHOOKS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/emap.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/emap.h index 6c501e4772c..08262f1f1e7 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/emap.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/emap.h @@ -1,11 +1,10 @@ #ifndef JEMALLOC_INTERNAL_EMAP_H #define JEMALLOC_INTERNAL_EMAP_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/base.h" #include "jemalloc/internal/rtree.h" -namespace duckdb_jemalloc { - /* * Note: Ends without at semicolon, so that * EMAP_DECLARE_RTREE_CTX; @@ -356,6 +355,4 @@ emap_edata_lookup_batch(tsd_t *tsd, emap_t *emap, size_t nptrs, } } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_EMAP_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/emitter.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/emitter.h index b6f9c9cc377..bc12fe92041 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/emitter.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/emitter.h @@ -1,27 +1,28 @@ #ifndef JEMALLOC_INTERNAL_EMITTER_H #define JEMALLOC_INTERNAL_EMITTER_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/ql.h" -#include - -namespace duckdb_jemalloc { - +typedef enum emitter_output_e emitter_output_t; enum emitter_output_e { emitter_output_json, emitter_output_json_compact, emitter_output_table }; -typedef enum emitter_output_e emitter_output_t; +typedef enum emitter_justify_e emitter_justify_t; enum emitter_justify_e { emitter_justify_left, emitter_justify_right, /* Not for users; just to pass to internal functions. */ emitter_justify_none }; -typedef enum emitter_justify_e emitter_justify_t; +typedef enum emitter_type_e emitter_type_t; enum emitter_type_e { emitter_type_bool, emitter_type_int, @@ -38,7 +39,6 @@ enum emitter_type_e { */ emitter_type_title, }; -typedef enum emitter_type_e emitter_type_t; typedef struct emitter_col_s emitter_col_t; struct emitter_col_s { @@ -511,6 +511,4 @@ emitter_end(emitter_t *emitter) { } } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_EMITTER_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/eset.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/eset.h index b23fd4cd9fc..9b7c4a89e14 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/eset.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/eset.h @@ -1,13 +1,12 @@ #ifndef JEMALLOC_INTERNAL_ESET_H #define JEMALLOC_INTERNAL_ESET_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/atomic.h" -#include "jemalloc/internal/fb.h" #include "jemalloc/internal/edata.h" +#include "jemalloc/internal/fb.h" #include "jemalloc/internal/mutex.h" -namespace duckdb_jemalloc { - /* * An eset ("extent set") is a quantized collection of extents, with built-in * LRU queue. @@ -76,6 +75,4 @@ void eset_remove(eset_t *eset, edata_t *edata); edata_t *eset_fit(eset_t *eset, size_t esize, size_t alignment, bool exact_only, unsigned lg_max_fit); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_ESET_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/exp_grow.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/exp_grow.h index 620e1b71a77..40a1add0375 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/exp_grow.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/exp_grow.h @@ -1,8 +1,8 @@ #ifndef JEMALLOC_INTERNAL_EXP_GROW_H #define JEMALLOC_INTERNAL_EXP_GROW_H -namespace duckdb_jemalloc { - +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/sz.h" typedef struct exp_grow_s exp_grow_t; struct exp_grow_s { /* @@ -49,6 +49,4 @@ exp_grow_size_commit(exp_grow_t *exp_grow, pszind_t skip) { void exp_grow_init(exp_grow_t *exp_grow); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_EXP_GROW_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/extent.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/extent.h index 78cb816e92c..17feb703ecb 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/extent.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/extent.h @@ -1,13 +1,13 @@ #ifndef JEMALLOC_INTERNAL_EXTENT_H #define JEMALLOC_INTERNAL_EXTENT_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/ecache.h" #include "jemalloc/internal/ehooks.h" +#include "jemalloc/internal/pac.h" #include "jemalloc/internal/ph.h" #include "jemalloc/internal/rtree.h" -namespace duckdb_jemalloc { - /* * This module contains the page-level allocator. It chooses the addresses that * allocations requested by other modules will inhabit, and updates the global @@ -46,8 +46,6 @@ void extent_destroy_wrapper(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, edata_t *edata); bool extent_commit_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, size_t offset, size_t length); -bool extent_decommit_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, - size_t offset, size_t length); bool extent_purge_lazy_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, size_t offset, size_t length); bool extent_purge_forced_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, @@ -136,6 +134,4 @@ extent_can_acquire_neighbor(edata_t *edata, rtree_contents_t contents, return true; } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_EXTENT_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/extent_dss.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/extent_dss.h index 90285f28afe..c8e71e82b28 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/extent_dss.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/extent_dss.h @@ -1,7 +1,9 @@ #ifndef JEMALLOC_INTERNAL_EXTENT_DSS_H #define JEMALLOC_INTERNAL_EXTENT_DSS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_types.h" +#include "jemalloc/internal/tsd_types.h" typedef enum { dss_prec_disabled = 0, @@ -13,7 +15,7 @@ typedef enum { #define DSS_PREC_DEFAULT dss_prec_secondary #define DSS_DEFAULT "secondary" -extern const char *dss_prec_names[]; +extern const char *const dss_prec_names[]; extern const char *opt_dss; @@ -25,6 +27,4 @@ bool extent_in_dss(void *addr); bool extent_dss_mergeable(void *addr_a, void *addr_b); void extent_dss_boot(void); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_EXTENT_DSS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/extent_mmap.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/extent_mmap.h index 027a988fcb8..e6a4649e709 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/extent_mmap.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/extent_mmap.h @@ -1,7 +1,7 @@ #ifndef JEMALLOC_INTERNAL_EXTENT_MMAP_EXTERNS_H #define JEMALLOC_INTERNAL_EXTENT_MMAP_EXTERNS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" extern bool opt_retain; @@ -9,6 +9,4 @@ void *extent_alloc_mmap(void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit); bool extent_dalloc_mmap(void *addr, size_t size); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_EXTENT_MMAP_EXTERNS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/fb.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/fb.h index 207bf3a7b46..e38095aff48 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/fb.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/fb.h @@ -1,7 +1,9 @@ #ifndef JEMALLOC_INTERNAL_FB_H #define JEMALLOC_INTERNAL_FB_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/bit_util.h" /* * The flat bitmap module. This has a larger API relative to the bitmap module @@ -372,6 +374,4 @@ fb_bit_not(fb_group_t *dst, fb_group_t *src, size_t nbits) { } } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_FB_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/fxp.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/fxp.h index 36071d61c79..e42425f9199 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/fxp.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/fxp.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_FXP_H #define JEMALLOC_INTERNAL_FXP_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/assert.h" -namespace duckdb_jemalloc { - /* * A simple fixed-point math implementation, supporting only unsigned values * (with overflow being an error). @@ -127,6 +126,4 @@ fxp_mul_frac(size_t x_orig, fxp_t frac) { bool fxp_parse(fxp_t *a, const char *ptr, char **end); void fxp_print(fxp_t a, char buf[FXP_BUF_SIZE]); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_FXP_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/hash.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/hash.h index 781803a31ff..15162b947ab 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/hash.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/hash.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_HASH_H #define JEMALLOC_INTERNAL_HASH_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/assert.h" -namespace duckdb_jemalloc { - /* * The following hash function is based on MurmurHash3, placed into the public * domain by Austin Appleby. See https://github.com/aappleby/smhasher for @@ -319,6 +318,4 @@ hash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2]) { #endif } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_HASH_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/hook.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/hook.h index 3819e0946fa..76b9130d236 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/hook.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/hook.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_HOOK_H #define JEMALLOC_INTERNAL_HOOK_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/tsd.h" -namespace duckdb_jemalloc { - /* * This API is *extremely* experimental, and may get ripped out, changed in API- * and ABI-incompatible ways, be insufficiently or incorrectly documented, etc. @@ -57,6 +56,7 @@ enum hook_alloc_e { hook_alloc_calloc, hook_alloc_memalign, hook_alloc_valloc, + hook_alloc_pvalloc, hook_alloc_mallocx, /* The reallocating functions have both alloc and dalloc variants */ @@ -145,9 +145,9 @@ struct hook_ralloc_args_s { * Returns an opaque handle to be used when removing the hook. NULL means that * we couldn't install the hook. */ -bool hook_boot(); +bool hook_boot(void); -void *hook_install(tsdn_t *tsdn, hooks_t *hooks); +void *hook_install(tsdn_t *tsdn, hooks_t *to_install); /* Uninstalls the hook with the handle previously returned from hook_install. */ void hook_remove(tsdn_t *tsdn, void *opaque); @@ -162,6 +162,4 @@ void hook_invoke_dalloc(hook_dalloc_t type, void *address, void hook_invoke_expand(hook_expand_t type, void *address, size_t old_usize, size_t new_usize, uintptr_t result_raw, uintptr_t args_raw[4]); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_HOOK_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa.h index 71c2a536578..4805efaf8c0 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa.h @@ -1,21 +1,19 @@ #ifndef JEMALLOC_INTERNAL_HPA_H #define JEMALLOC_INTERNAL_HPA_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/base.h" +#include "jemalloc/internal/edata_cache.h" +#include "jemalloc/internal/emap.h" #include "jemalloc/internal/exp_grow.h" #include "jemalloc/internal/hpa_hooks.h" #include "jemalloc/internal/hpa_opts.h" +#include "jemalloc/internal/mutex.h" #include "jemalloc/internal/pai.h" #include "jemalloc/internal/psset.h" -namespace duckdb_jemalloc { - typedef struct hpa_central_s hpa_central_t; struct hpa_central_s { - /* - * The mutex guarding most of the operations on the central data - * structure. - */ - malloc_mutex_t mtx; /* * Guards expansion of eden. We separate this from the regular mutex so * that cheaper operations can still continue while we're doing the OS @@ -150,7 +148,7 @@ struct hpa_shard_s { * is not necessarily a guarantee that it backs its allocations by hugepages, * just that it can function properly given the system it's running on. */ -bool hpa_supported(); +bool hpa_supported(void); bool hpa_central_init(hpa_central_t *central, base_t *base, const hpa_hooks_t *hooks); bool hpa_shard_init(hpa_shard_t *shard, hpa_central_t *central, emap_t *emap, base_t *base, edata_cache_t *edata_cache, unsigned ind, @@ -181,6 +179,4 @@ void hpa_shard_prefork4(tsdn_t *tsdn, hpa_shard_t *shard); void hpa_shard_postfork_parent(tsdn_t *tsdn, hpa_shard_t *shard); void hpa_shard_postfork_child(tsdn_t *tsdn, hpa_shard_t *shard); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_HPA_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa_hooks.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa_hooks.h index a717b267745..72f3a43c21c 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa_hooks.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa_hooks.h @@ -1,7 +1,8 @@ #ifndef JEMALLOC_INTERNAL_HPA_HOOKS_H #define JEMALLOC_INTERNAL_HPA_HOOKS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/nstime.h" typedef struct hpa_hooks_s hpa_hooks_t; struct hpa_hooks_s { @@ -14,8 +15,6 @@ struct hpa_hooks_s { uint64_t (*ms_since)(nstime_t *r_time); }; -extern hpa_hooks_t hpa_hooks_default; - -} // namespace duckdb_jemalloc +extern const hpa_hooks_t hpa_hooks_default; #endif /* JEMALLOC_INTERNAL_HPA_HOOKS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa_opts.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa_opts.h index c8b664c3d31..6e58c86b056 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa_opts.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/hpa_opts.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_HPA_OPTS_H #define JEMALLOC_INTERNAL_HPA_OPTS_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/fxp.h" -namespace duckdb_jemalloc { - /* * This file is morally part of hpa.h, but is split out for header-ordering * reasons. @@ -73,6 +72,4 @@ struct hpa_shard_opts_s { 5 * 1000 \ } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_HPA_OPTS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/hpdata.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/hpdata.h index 9e6f378e7cb..7ba92112f9e 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/hpdata.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/hpdata.h @@ -1,13 +1,14 @@ #ifndef JEMALLOC_INTERNAL_HPDATA_H #define JEMALLOC_INTERNAL_HPDATA_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/fb.h" +#include "jemalloc/internal/nstime.h" +#include "jemalloc/internal/pages.h" #include "jemalloc/internal/ph.h" #include "jemalloc/internal/ql.h" #include "jemalloc/internal/typed_list.h" -namespace duckdb_jemalloc { - /* * The metadata representation we use for extents in hugepages. While the PAC * uses the edata_t to represent both active and inactive extents, the HP only @@ -345,12 +346,12 @@ hpdata_assert_consistent(hpdata_t *hpdata) { } static inline bool -hpdata_empty(hpdata_t *hpdata) { +hpdata_empty(const hpdata_t *hpdata) { return hpdata->h_nactive == 0; } static inline bool -hpdata_full(hpdata_t *hpdata) { +hpdata_full(const hpdata_t *hpdata) { return hpdata->h_nactive == HUGEPAGE_PAGES; } @@ -361,7 +362,7 @@ void hpdata_init(hpdata_t *hpdata, void *addr, uint64_t age); * offset within that allocation. */ void *hpdata_reserve_alloc(hpdata_t *hpdata, size_t sz); -void hpdata_unreserve(hpdata_t *hpdata, void *begin, size_t sz); +void hpdata_unreserve(hpdata_t *hpdata, void *addr, size_t sz); /* * The hpdata_purge_prepare_t allows grabbing the metadata required to purge @@ -412,6 +413,4 @@ void hpdata_purge_end(hpdata_t *hpdata, hpdata_purge_state_t *purge_state); void hpdata_hugify(hpdata_t *hpdata); void hpdata_dehugify(hpdata_t *hpdata); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_HPDATA_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/inspect.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/inspect.h index 7fbb11a158d..0da920ca111 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/inspect.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/inspect.h @@ -1,7 +1,8 @@ #ifndef JEMALLOC_INTERNAL_INSPECT_H #define JEMALLOC_INTERNAL_INSPECT_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/tsd_types.h" /* * This module contains the heap introspection capabilities. For now they are @@ -39,6 +40,4 @@ void inspect_extent_util_stats_verbose_get(tsdn_t *tsdn, const void *ptr, size_t *nfree, size_t *nregs, size_t *size, size_t *bin_nfree, size_t *bin_nregs, void **slabcur_addr); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_INSPECT_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h index cee805e7809..0bca9133136 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h @@ -1,8 +1,6 @@ #ifndef JEMALLOC_INTERNAL_DECLS_H #define JEMALLOC_INTERNAL_DECLS_H -#include "jemalloc/internal/jemalloc_internal_defs.h" - #include #ifdef _WIN32 # include @@ -34,7 +32,7 @@ # include # endif # include -# if defined(__FreeBSD__) || defined(__DragonFly__) +# if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) # include # include # if defined(__FreeBSD__) @@ -57,25 +55,24 @@ #endif #include -#include +#include #ifndef SIZE_T_MAX # define SIZE_T_MAX SIZE_MAX #endif #ifndef SSIZE_MAX # define SSIZE_MAX ((ssize_t)(SIZE_T_MAX >> 1)) #endif - +#include +#include +#include +#include +#include +#include #ifndef offsetof # define offsetof(type, member) ((size_t)&(((type *)NULL)->member)) #endif -#include - -#ifdef _MSC_VER -#include "msvc_compat/strings.h" -#else +#include #include -#endif - #include #ifdef _MSC_VER # include @@ -108,4 +105,21 @@ isblank(int c) { # undef small #endif +/* + * Oftentimes we'd like to perform some kind of arithmetic to obtain + * a pointer from another pointer but with some offset or mask applied. + * Naively you would accomplish this by casting the source pointer to + * `uintptr_t`, performing all of the relevant arithmetic, and then casting + * the result to the desired pointer type. However, this has the unfortunate + * side-effect of concealing pointer provenance, hiding useful information for + * optimization from the compiler (see here for details: + * https://clang.llvm.org/extra/clang-tidy/checks/performance/no-int-to-ptr.html + * ) + * Instead what one should do is cast the source pointer to `char *` and perform + * the equivalent arithmetic (since `char` of course represents one byte). But + * because `char *` has the semantic meaning of "string", we define this typedef + * simply to make it clearer where we are performing such pointer arithmetic. + */ +typedef char byte_t; + #endif /* JEMALLOC_INTERNAL_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h index c44696e3f0a..e20bff79423 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h @@ -2,27 +2,29 @@ #ifndef JEMALLOC_INTERNAL_DEFS_H_ #define JEMALLOC_INTERNAL_DEFS_H_ -#include +#if defined(__GNUC__) +#define _GNU_SOURCE +#endif -namespace duckdb_jemalloc { +#include /* * If JEMALLOC_PREFIX is defined via --with-jemalloc-prefix, it will cause all * public APIs to be prefixed. This makes it possible, with some care, to use * multiple allocators simultaneously. */ -// #define JEMALLOC_PREFIX "je_" -// #define JEMALLOC_CPREFIX "JE_" +#define JEMALLOC_PREFIX "duckdb_je_" +#define JEMALLOC_CPREFIX "DUCKDB_JE_" /* * Define overrides for non-standard allocator-related functions if they are * present on the system. */ /* #undef JEMALLOC_OVERRIDE___LIBC_CALLOC */ -// #define JEMALLOC_OVERRIDE___LIBC_FREE -//#define JEMALLOC_OVERRIDE___LIBC_MALLOC +/* #undef JEMALLOC_OVERRIDE___LIBC_FREE */ +/* #undef JEMALLOC_OVERRIDE___LIBC_MALLOC /* #undef JEMALLOC_OVERRIDE___LIBC_MEMALIGN */ -//#define JEMALLOC_OVERRIDE___LIBC_REALLOC +/* #undef JEMALLOC_OVERRIDE___LIBC_REALLOC */ /* #undef JEMALLOC_OVERRIDE___LIBC_VALLOC */ /* #undef JEMALLOC_OVERRIDE___POSIX_MEMALIGN */ @@ -32,15 +34,15 @@ namespace duckdb_jemalloc { * from being exported, but for static libraries, naming collisions are a real * possibility. */ -#define JEMALLOC_PRIVATE_NAMESPACE je_ +#define JEMALLOC_PRIVATE_NAMESPACE duckdb_je_ /* * Hyper-threaded CPUs may need a special instruction inside spin loops in * order to yield to another virtual CPU. */ -//#define CPU_SPINWAIT __asm__ volatile("isb") +// #define CPU_SPINWAIT __asm__ volatile("isb") /* 1 if CPU_SPINWAIT is defined, 0 otherwise. */ -//#define HAVE_CPU_SPINWAIT 1 +// #define HAVE_CPU_SPINWAIT 1 /* * Number of significant bits in virtual addresses. This may be less than the @@ -48,13 +50,13 @@ namespace duckdb_jemalloc { * bits are the same as bit 47. */ #if INTPTR_MAX == INT64_MAX - #define LG_VADDR 48 +#define LG_VADDR 48 #else - #define LG_VADDR 32 +#define LG_VADDR 32 #endif /* Defined if C11 atomics are available. */ -#define JEMALLOC_C11_ATOMICS +#define JEMALLOC_C11_ATOMICS /* Defined if GCC __atomic atomics are available. */ #ifndef _MSC_VER @@ -80,7 +82,9 @@ namespace duckdb_jemalloc { /* * Defined if os_unfair_lock_*() functions are available, as provided by Darwin. */ +// #if defined(__APPLE__) // #define JEMALLOC_OS_UNFAIR_LOCK +// #endif /* Defined if syscall(2) is usable. */ /* #undef JEMALLOC_USE_SYSCALL */ @@ -96,13 +100,13 @@ namespace duckdb_jemalloc { // #define JEMALLOC_HAVE_ISSETUGID /* Defined if pthread_atfork(3) is available. */ -//#define JEMALLOC_HAVE_PTHREAD_ATFORK +// #define JEMALLOC_HAVE_PTHREAD_ATFORK /* Defined if pthread_setname_np(3) is available. */ /* #undef JEMALLOC_HAVE_PTHREAD_SETNAME_NP */ /* Defined if pthread_getname_np(3) is available. */ -#define JEMALLOC_HAVE_PTHREAD_GETNAME_NP +// #define JEMALLOC_HAVE_PTHREAD_GETNAME_NP /* Defined if pthread_get_name_np(3) is available. */ /* #undef JEMALLOC_HAVE_PTHREAD_GET_NAME_NP */ @@ -125,7 +129,7 @@ namespace duckdb_jemalloc { /* * Defined if clock_gettime(CLOCK_REALTIME, ...) is available. */ -#define JEMALLOC_HAVE_CLOCK_REALTIME +#define JEMALLOC_HAVE_CLOCK_REALTIME /* * Defined if _malloc_thread_cleanup() exists. At least in the case of @@ -134,7 +138,9 @@ namespace duckdb_jemalloc { * _malloc_thread_cleanup() exists, use it as the basis for thread cleanup in * malloc_tsd. */ -/* #undef JEMALLOC_MALLOC_THREAD_CLEANUP */ +#if defined(__APPLE__) || defined(__FreeBSD__) +#define JEMALLOC_MALLOC_THREAD_CLEANUP +#endif /* * Defined if threaded initialization is known to be safe on this platform. @@ -151,7 +157,7 @@ namespace duckdb_jemalloc { /* #undef JEMALLOC_MUTEX_INIT_CB */ /* Non-empty if the tls_model attribute is supported. */ -#define JEMALLOC_TLS_MODEL __attribute__((tls_model("initial-exec"))) +#define JEMALLOC_TLS_MODEL __attribute__((tls_model("global-dynamic"))) /* * JEMALLOC_DEBUG enables assertions and other sanity checks, and disables @@ -160,7 +166,7 @@ namespace duckdb_jemalloc { /* #undef JEMALLOC_DEBUG */ /* JEMALLOC_STATS enables statistics calculation. */ -#define JEMALLOC_STATS +#define JEMALLOC_STATS /* JEMALLOC_EXPERIMENTAL_SMALLOCX_API enables experimental smallocx API. */ /* #undef JEMALLOC_EXPERIMENTAL_SMALLOCX_API */ @@ -184,7 +190,7 @@ namespace duckdb_jemalloc { /* #undef JEMALLOC_DSS */ /* Support memory filling (junk/zero). */ -#define JEMALLOC_FILL +#define JEMALLOC_FILL /* Support utrace(2)-based tracing. */ /* #undef JEMALLOC_UTRACE */ @@ -196,7 +202,7 @@ namespace duckdb_jemalloc { /* #undef JEMALLOC_XMALLOC */ /* Support lazy locking (avoid locking unless a second thread is launched). */ -/* #undef JEMALLOC_LAZY_LOCK */ +// #define JEMALLOC_LAZY_LOCK /* * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size @@ -205,11 +211,12 @@ namespace duckdb_jemalloc { /* #undef LG_QUANTUM */ /* One page is 2^LG_PAGE bytes. */ -// NOTE: This is an attempt at setting a correct page size for multiple architectures without running getconf -// This is compiled into DuckDB, which means that our distributions have a fixed page size -// We only enable jemalloc for non-ARM Linux builds, virtually all of which have a page size of 4KB -// The other definitions are just here for people who want to build DuckDB with jemalloc themselves -#if defined(__i386__) || defined(__x86_64__) || defined(__amd64__) || defined(COMPILER_MSVC) && (defined(_M_IX86) || defined(_M_X64)) +// ----- DuckDB comment ----- +// The page size for jemalloc can always be bigger than the actual system page size +#if INTPTR_MAX != INT64_MAX +#define LG_PAGE 12 // 32-bit systems typically have a 4KB page size +#elif defined(__i386__) || defined(__x86_64__) || defined(__amd64__) || \ + defined(COMPILER_MSVC) && (defined(_M_IX86) || defined(_M_X64)) #define LG_PAGE 12 // x86 and x86_64 typically have a 4KB page size #elif defined(__powerpc__) || defined(__ppc__) #define LG_PAGE 16 // PowerPC architectures often use 64KB page size @@ -217,19 +224,11 @@ namespace duckdb_jemalloc { #define LG_PAGE 13 // SPARC architectures usually have an 8KB page size #elif defined(__aarch64__) || defined(__ARM_ARCH) -// ARM architectures can have a wide range of page sizes +// ARM architectures are less well-defined #if defined(__APPLE__) #define LG_PAGE 14 // Apple Silicon uses a 16KB page size - -// Best effort for other ARM versions -#elif defined(__ARM_ARCH) && __ARM_ARCH >= 8 -#define LG_PAGE 16 // ARM architectures >= ARMv8 typically use a 64KB page size -#elif defined(__ARM_ARCH) && __ARM_ARCH >= 7 -#define LG_PAGE 14 // ARM architectures >= ARMv7 typically use a 16KB page size -#elif defined(__ARM_ARCH) && __ARM_ARCH >= 6 -#define LG_PAGE 12 // ARM architectures >= ARMv6 typically use a 4KB page size #else -#define LG_PAGE 12 // Default to a 4KB page size for unknown ARM architectures +#define LG_PAGE 16 // Use max known page size for ARM #endif #else @@ -253,7 +252,9 @@ namespace duckdb_jemalloc { * VirtualAlloc()/VirtualFree() operations must be precisely matched, i.e. * mappings do *not* coalesce/fragment. */ -#define JEMALLOC_MAPS_COALESCE +#ifndef _MSC_VER +#define JEMALLOC_MAPS_COALESCE +#endif /* * If defined, retain memory for later reuse by default rather than using e.g. @@ -261,10 +262,15 @@ namespace duckdb_jemalloc { * common sequences of mmap()/munmap() calls will cause virtual memory map * holes. */ -/* #undef JEMALLOC_RETAIN */ +// ----- DuckDB comment ----- +// This makes it feasible to run the larger page size (https://github.com/duckdb/duckdb/discussions/11455), +// but it causes DuckDB to retain RSS even after closing the connection, so we have to disable it +// #if INTPTR_MAX == INT64_MAX +// #define JEMALLOC_RETAIN +// #endif /* TLS is used to map arenas and magazine caches to threads. */ -/* #undef JEMALLOC_TLS */ +#define JEMALLOC_TLS /* * Used to mark unreachable code to quiet "end of non-void" compiler warnings. @@ -284,9 +290,7 @@ namespace duckdb_jemalloc { * use ffs_*() from util.h. */ #ifdef _MSC_VER -} // namespace duckdb_jemalloc #include "msvc_compat/strings.h" -namespace duckdb_jemalloc { #define JEMALLOC_INTERNAL_FFSLL ffsll #define JEMALLOC_INTERNAL_FFSL ffsl #define JEMALLOC_INTERNAL_FFS ffs @@ -299,14 +303,14 @@ namespace duckdb_jemalloc { /* * popcount*() functions to use for bitmapping. */ -//#define JEMALLOC_INTERNAL_POPCOUNTL __builtin_popcountl -//#define JEMALLOC_INTERNAL_POPCOUNT __builtin_popcount +// #define JEMALLOC_INTERNAL_POPCOUNTL __builtin_popcountl +// #define JEMALLOC_INTERNAL_POPCOUNT __builtin_popcount /* * If defined, explicitly attempt to more uniformly distribute large allocation * pointer alignments across all cache indices. */ -#define JEMALLOC_CACHE_OBLIVIOUS +// #define JEMALLOC_CACHE_OBLIVIOUS /* * If defined, enable logging facilities. We make this a configure option to @@ -323,7 +327,9 @@ namespace duckdb_jemalloc { /* * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings. */ -//#define JEMALLOC_ZONE +// #if defined(__APPLE__) +// #define JEMALLOC_ZONE +// #endif /* * Methods for determining whether the OS overcommits. @@ -331,8 +337,11 @@ namespace duckdb_jemalloc { * /proc/sys/vm.overcommit_memory file. * JEMALLOC_SYSCTL_VM_OVERCOMMIT: FreeBSD's vm.overcommit sysctl. */ -/* #undef JEMALLOC_SYSCTL_VM_OVERCOMMIT */ -/* #undef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY */ +#ifdef __FreeBSD__ +#define JEMALLOC_SYSCTL_VM_OVERCOMMIT +#else +#define JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY +#endif /* Defined if madvise(2) is available. */ #define JEMALLOC_HAVE_MADVISE @@ -356,12 +365,12 @@ namespace duckdb_jemalloc { * MADV_FREE, though typically with higher * system overhead. */ -//#define JEMALLOC_PURGE_MADVISE_FREE -#define JEMALLOC_PURGE_MADVISE_DONTNEED +#define JEMALLOC_PURGE_MADVISE_FREE +// #define JEMALLOC_PURGE_MADVISE_DONTNEED /* #undef JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS */ /* Defined if madvise(2) is available but MADV_FREE is not (x86 Linux only). */ -#undef JEMALLOC_DEFINE_MADVISE_FREE +#define JEMALLOC_DEFINE_MADVISE_FREE /* * Defined if MADV_DO[NT]DUMP is supported as an argument to madvise. @@ -401,7 +410,7 @@ namespace duckdb_jemalloc { /* * Defined if malloc_size is supported */ -//#define JEMALLOC_HAVE_MALLOC_SIZE +// #define JEMALLOC_HAVE_MALLOC_SIZE /* Define if operating system has alloca.h header. */ /* #undef JEMALLOC_HAS_ALLOCA_H */ @@ -435,30 +444,34 @@ namespace duckdb_jemalloc { /* #undef JEMALLOC_GLIBC_MEMALIGN_HOOK */ /* pthread support */ -#define JEMALLOC_HAVE_PTHREAD +#define JEMALLOC_HAVE_PTHREAD /* dlsym() support */ -#define JEMALLOC_HAVE_DLSYM +#define JEMALLOC_HAVE_DLSYM /* Adaptive mutex support in pthreads. */ /* #undef JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */ /* GNU specific sched_getcpu support */ -/* #undef JEMALLOC_HAVE_SCHED_GETCPU */ +#if defined(__GNUC__) +#define JEMALLOC_HAVE_SCHED_GETCPU +#endif /* GNU specific sched_setaffinity support */ -/* #undef JEMALLOC_HAVE_SCHED_SETAFFINITY */ +#if defined(__GNUC__) +#define JEMALLOC_HAVE_SCHED_SETAFFINITY +#endif /* * If defined, all the features necessary for background threads are present. */ -/* #undef JEMALLOC_BACKGROUND_THREAD */ +#define JEMALLOC_BACKGROUND_THREAD /* * If defined, jemalloc symbols are not exported (doesn't work when * JEMALLOC_PREFIX is not defined). */ -/* #undef JEMALLOC_EXPORT */ +#define JEMALLOC_EXPORT /* config.malloc_conf options string. */ #define JEMALLOC_CONFIG_MALLOC_CONF "" @@ -469,13 +482,13 @@ namespace duckdb_jemalloc { /* * Defined if strerror_r returns char * if _GNU_SOURCE is defined. */ -//#define JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE +// #define JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE /* Performs additional safety checks when defined. */ /* #undef JEMALLOC_OPT_SAFETY_CHECKS */ /* Is C++ support being built? */ -#define JEMALLOC_ENABLE_CXX +#define JEMALLOC_ENABLE_CXX /* Performs additional size checks when defined. */ /* #undef JEMALLOC_OPT_SIZE_CHECKS */ @@ -484,11 +497,11 @@ namespace duckdb_jemalloc { /* #undef JEMALLOC_UAF_DETECTION */ /* Darwin VM_MAKE_TAG support */ -//#define JEMALLOC_HAVE_VM_MAKE_TAG +// #if defined(__APPLE__) +// #define JEMALLOC_HAVE_VM_MAKE_TAG +// #endif /* If defined, realloc(ptr, 0) defaults to "free" instead of "alloc". */ /* #undef JEMALLOC_ZERO_REALLOC_DEFAULT_FREE */ -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_DEFS_H_ */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h index 278b943251a..41c0f366f47 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h @@ -1,13 +1,12 @@ #ifndef JEMALLOC_INTERNAL_EXTERNS_H #define JEMALLOC_INTERNAL_EXTERNS_H +#include "jemalloc/internal/arena_types.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/hpa_opts.h" +#include "jemalloc/internal/nstime.h" #include "jemalloc/internal/sec_opts.h" #include "jemalloc/internal/tsd_types.h" -#include "jemalloc/internal/nstime.h" - -namespace duckdb_jemalloc { /* TSD checks this to set thread local slow state accordingly. */ extern bool malloc_slow; @@ -24,8 +23,9 @@ extern sec_opts_t opt_hpa_sec_opts; extern const char *opt_junk; extern bool opt_junk_alloc; extern bool opt_junk_free; -extern void (*junk_free_callback)(void *ptr, size_t size); -extern void (*junk_alloc_callback)(void *ptr, size_t size); +extern void (*JET_MUTABLE junk_free_callback)(void *ptr, size_t size); +extern void (*JET_MUTABLE junk_alloc_callback)(void *ptr, size_t size); +extern void (*JET_MUTABLE invalid_conf_abort)(void); extern bool opt_utrace; extern bool opt_xmalloc; extern bool opt_experimental_infallible_new; @@ -33,9 +33,14 @@ extern bool opt_zero; extern unsigned opt_narenas; extern zero_realloc_action_t opt_zero_realloc_action; extern malloc_init_t malloc_init_state; -extern const char *zero_realloc_mode_names[]; +extern const char *const zero_realloc_mode_names[]; extern atomic_zu_t zero_realloc_count; extern bool opt_cache_oblivious; +extern unsigned opt_debug_double_free_max_scan; +extern size_t opt_calloc_madvise_threshold; + +extern const char *opt_malloc_conf_symlink; +extern const char *opt_malloc_conf_env_var; /* Escape free-fastpath when ptr & mask == 0 (for sanitization purpose). */ extern uintptr_t san_cache_bin_nonfast_mask; @@ -71,9 +76,8 @@ size_t batch_alloc(void **ptrs, size_t num, size_t size, int flags); void jemalloc_prefork(void); void jemalloc_postfork_parent(void); void jemalloc_postfork_child(void); -void JEMALLOC_NOTHROW je_sdallocx_noflags(void *ptr, size_t size); +void sdallocx_default(void *ptr, size_t size, int flags); +void free_default(void *ptr); void *malloc_default(size_t size); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_EXTERNS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_includes.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_includes.h index 32676a6fcd6..751c112ff4c 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_includes.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_includes.h @@ -36,9 +36,6 @@ * global jemalloc definitions, however. */ -// For ptrdiff_t -#include - /******************************************************************************/ /* TYPES */ /******************************************************************************/ @@ -71,16 +68,16 @@ /* INLINES */ /******************************************************************************/ -#include "jemalloc/internal/jemalloc_int_inl_a.h" +#include "jemalloc/internal/jemalloc_internal_inlines_a.h" /* * Include portions of arena code interleaved with tcache code in order to * resolve circular dependencies. */ #include "jemalloc/internal/arena_inlines_a.h" -#include "jemalloc/internal/jemalloc_int_inl_b.h" +#include "jemalloc/internal/jemalloc_internal_inlines_b.h" #include "jemalloc/internal/tcache_inlines.h" #include "jemalloc/internal/arena_inlines_b.h" -#include "jemalloc/internal/jemalloc_int_inl_c.h" +#include "jemalloc/internal/jemalloc_internal_inlines_c.h" #include "jemalloc/internal/prof_inlines.h" #include "jemalloc/internal/background_thread_inlines.h" diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_int_inl_a.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_a.h similarity index 84% rename from extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_int_inl_a.h rename to extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_a.h index acf539efa0c..111cda42991 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_int_inl_a.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_a.h @@ -1,14 +1,16 @@ #ifndef JEMALLOC_INTERNAL_INLINES_A_H #define JEMALLOC_INTERNAL_INLINES_A_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_externs.h" +#include "jemalloc/internal/arena_types.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/bit_util.h" #include "jemalloc/internal/jemalloc_internal_types.h" #include "jemalloc/internal/sc.h" +#include "jemalloc/internal/tcache_externs.h" #include "jemalloc/internal/ticker.h" -namespace duckdb_jemalloc { - JEMALLOC_ALWAYS_INLINE malloc_cpuid_t malloc_getcpu(void) { assert(have_percpu_arena); @@ -16,6 +18,15 @@ malloc_getcpu(void) { return GetCurrentProcessorNumber(); #elif defined(JEMALLOC_HAVE_SCHED_GETCPU) return (malloc_cpuid_t)sched_getcpu(); +#elif defined(JEMALLOC_HAVE_RDTSCP) + unsigned int ecx; + asm volatile("rdtscp" : "=c" (ecx) :: "eax", "edx"); + return (malloc_cpuid_t)(ecx & 0xfff); +#elif defined(__aarch64__) && defined(__APPLE__) + /* Other oses most likely use tpidr_el0 instead */ + uintptr_t c; + asm volatile("mrs %x0, tpidrro_el0" : "=r"(c) :: "memory"); + return (malloc_cpuid_t)(c & (1 << 3) - 1); #else not_reached(); return -1; @@ -121,6 +132,4 @@ post_reentrancy(tsd_t *tsd) { tsd_post_reentrancy_raw(tsd); } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_INLINES_A_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_int_inl_b.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_b.h similarity index 93% rename from extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_int_inl_b.h rename to extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_b.h index d4c3b71c409..2ddb4a894b3 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_int_inl_b.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_b.h @@ -1,9 +1,10 @@ #ifndef JEMALLOC_INTERNAL_INLINES_B_H #define JEMALLOC_INTERNAL_INLINES_B_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_inlines_a.h" #include "jemalloc/internal/extent.h" - -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_internal_inlines_a.h" static inline void percpu_arena_update(tsd_t *tsd, unsigned cpu) { @@ -22,6 +23,7 @@ percpu_arena_update(tsd_t *tsd, unsigned cpu) { tcache_t *tcache = tcache_get(tsd); if (tcache != NULL) { tcache_slow_t *tcache_slow = tsd_tcache_slowp_get(tsd); + assert(tcache_slow->arena != NULL); tcache_arena_reassociate(tsd_tsdn(tsd), tcache_slow, tcache, newarena); } @@ -102,6 +104,4 @@ arena_is_auto(arena_t *arena) { return (arena_ind_get(arena) < manual_arena_base); } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_INLINES_B_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_int_inl_c.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h similarity index 50% rename from extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_int_inl_c.h rename to extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h index 1551bf8c231..6dcffac9573 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_int_inl_c.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h @@ -1,6 +1,10 @@ #ifndef JEMALLOC_INTERNAL_INLINES_C_H #define JEMALLOC_INTERNAL_INLINES_C_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_externs.h" +#include "jemalloc/internal/arena_inlines_b.h" +#include "jemalloc/internal/emap.h" #include "jemalloc/internal/hook.h" #include "jemalloc/internal/jemalloc_internal_types.h" #include "jemalloc/internal/log.h" @@ -8,7 +12,14 @@ #include "jemalloc/internal/thread_event.h" #include "jemalloc/internal/witness.h" -namespace duckdb_jemalloc { +/* + * These correspond to the macros in jemalloc/jemalloc_macros.h. Broadly, we + * should have one constant here per magic value there. Note however that the + * representations need not be related. + */ +#define TCACHE_IND_NONE ((unsigned)-1) +#define TCACHE_IND_AUTOMATIC ((unsigned)-2) +#define ARENA_IND_AUTOMATIC ((unsigned)-1) /* * Translating the names of the 'i' functions: @@ -43,10 +54,12 @@ isalloc(tsdn_t *tsdn, const void *ptr) { } JEMALLOC_ALWAYS_INLINE void * -iallocztm(tsdn_t *tsdn, size_t size, szind_t ind, bool zero, tcache_t *tcache, - bool is_internal, arena_t *arena, bool slow_path) { +iallocztm_explicit_slab(tsdn_t *tsdn, size_t size, szind_t ind, bool zero, + bool slab, tcache_t *tcache, bool is_internal, arena_t *arena, + bool slow_path) { void *ret; + assert(!slab || sz_can_use_slab(size)); /* slab && large is illegal */ assert(!is_internal || tcache == NULL); assert(!is_internal || arena == NULL || arena_is_auto(arena)); if (!tsdn_null(tsdn) && tsd_reentrancy_level_get(tsdn_tsd(tsdn)) == 0) { @@ -54,13 +67,21 @@ iallocztm(tsdn_t *tsdn, size_t size, szind_t ind, bool zero, tcache_t *tcache, WITNESS_RANK_CORE, 0); } - ret = arena_malloc(tsdn, arena, size, ind, zero, tcache, slow_path); + ret = arena_malloc(tsdn, arena, size, ind, zero, slab, tcache, slow_path); if (config_stats && is_internal && likely(ret != NULL)) { arena_internal_add(iaalloc(tsdn, ret), isalloc(tsdn, ret)); } return ret; } +JEMALLOC_ALWAYS_INLINE void * +iallocztm(tsdn_t *tsdn, size_t size, szind_t ind, bool zero, tcache_t *tcache, + bool is_internal, arena_t *arena, bool slow_path) { + bool slab = sz_can_use_slab(size); + return iallocztm_explicit_slab(tsdn, size, ind, zero, slab, tcache, + is_internal, arena, slow_path); +} + JEMALLOC_ALWAYS_INLINE void * ialloc(tsd_t *tsd, size_t size, szind_t ind, bool zero, bool slow_path) { return iallocztm(tsd_tsdn(tsd), size, ind, zero, tcache_get(tsd), false, @@ -68,10 +89,11 @@ ialloc(tsd_t *tsd, size_t size, szind_t ind, bool zero, bool slow_path) { } JEMALLOC_ALWAYS_INLINE void * -ipallocztm(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero, - tcache_t *tcache, bool is_internal, arena_t *arena) { +ipallocztm_explicit_slab(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero, + bool slab, tcache_t *tcache, bool is_internal, arena_t *arena) { void *ret; + assert(!slab || sz_can_use_slab(usize)); /* slab && large is illegal */ assert(usize != 0); assert(usize == sz_sa2u(usize, alignment)); assert(!is_internal || tcache == NULL); @@ -79,7 +101,7 @@ ipallocztm(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero, witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, 0); - ret = arena_palloc(tsdn, arena, usize, alignment, zero, tcache); + ret = arena_palloc(tsdn, arena, usize, alignment, zero, slab, tcache); assert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret); if (config_stats && is_internal && likely(ret != NULL)) { arena_internal_add(iaalloc(tsdn, ret), isalloc(tsdn, ret)); @@ -87,12 +109,26 @@ ipallocztm(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero, return ret; } +JEMALLOC_ALWAYS_INLINE void * +ipallocztm(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero, + tcache_t *tcache, bool is_internal, arena_t *arena) { + return ipallocztm_explicit_slab(tsdn, usize, alignment, zero, + sz_can_use_slab(usize), tcache, is_internal, arena); +} + JEMALLOC_ALWAYS_INLINE void * ipalloct(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero, tcache_t *tcache, arena_t *arena) { return ipallocztm(tsdn, usize, alignment, zero, tcache, false, arena); } +JEMALLOC_ALWAYS_INLINE void * +ipalloct_explicit_slab(tsdn_t *tsdn, size_t usize, size_t alignment, + bool zero, bool slab, tcache_t *tcache, arena_t *arena) { + return ipallocztm_explicit_slab(tsdn, usize, alignment, zero, slab, + tcache, false, arena); +} + JEMALLOC_ALWAYS_INLINE void * ipalloc(tsd_t *tsd, size_t usize, size_t alignment, bool zero) { return ipallocztm(tsd_tsdn(tsd), usize, alignment, zero, @@ -137,7 +173,7 @@ isdalloct(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache, JEMALLOC_ALWAYS_INLINE void * iralloct_realign(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, - size_t alignment, bool zero, tcache_t *tcache, arena_t *arena, + size_t alignment, bool zero, bool slab, tcache_t *tcache, arena_t *arena, hook_ralloc_args_t *hook_args) { witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, 0); @@ -148,7 +184,8 @@ iralloct_realign(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, if (unlikely(usize == 0 || usize > SC_LARGE_MAXCLASS)) { return NULL; } - p = ipalloct(tsdn, usize, alignment, zero, tcache, arena); + p = ipalloct_explicit_slab(tsdn, usize, alignment, zero, slab, + tcache, arena); if (p == NULL) { return NULL; } @@ -175,8 +212,9 @@ iralloct_realign(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, * passed-around anywhere. */ JEMALLOC_ALWAYS_INLINE void * -iralloct(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t alignment, - bool zero, tcache_t *tcache, arena_t *arena, hook_ralloc_args_t *hook_args) +iralloct_explicit_slab(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, + size_t alignment, bool zero, bool slab, tcache_t *tcache, arena_t *arena, + hook_ralloc_args_t *hook_args) { assert(ptr != NULL); assert(size != 0); @@ -190,18 +228,28 @@ iralloct(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t alignment, * and copy. */ return iralloct_realign(tsdn, ptr, oldsize, size, alignment, - zero, tcache, arena, hook_args); + zero, slab, tcache, arena, hook_args); } return arena_ralloc(tsdn, arena, ptr, oldsize, size, alignment, zero, - tcache, hook_args); + slab, tcache, hook_args); +} + +JEMALLOC_ALWAYS_INLINE void * +iralloct(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t alignment, + size_t usize, bool zero, tcache_t *tcache, arena_t *arena, + hook_ralloc_args_t *hook_args) +{ + bool slab = sz_can_use_slab(usize); + return iralloct_explicit_slab(tsdn, ptr, oldsize, size, alignment, zero, + slab, tcache, arena, hook_args); } JEMALLOC_ALWAYS_INLINE void * iralloc(tsd_t *tsd, void *ptr, size_t oldsize, size_t size, size_t alignment, - bool zero, hook_ralloc_args_t *hook_args) { - return iralloct(tsd_tsdn(tsd), ptr, oldsize, size, alignment, zero, - tcache_get(tsd), NULL, hook_args); + size_t usize, bool zero, hook_ralloc_args_t *hook_args) { + return iralloct(tsd_tsdn(tsd), ptr, oldsize, size, alignment, usize, + zero, tcache_get(tsd), NULL, hook_args); } JEMALLOC_ALWAYS_INLINE bool @@ -230,8 +278,6 @@ fastpath_success_finish(tsd_t *tsd, uint64_t allocated_after, if (config_stats) { bin->tstats.nrequests++; } - - LOG("core.malloc.exit", "result: %p", ret); } JEMALLOC_ALWAYS_INLINE bool @@ -258,7 +304,6 @@ malloc_initialized(void) { */ JEMALLOC_ALWAYS_INLINE void * imalloc_fastpath(size_t size, void *(fallback_alloc)(size_t)) { - LOG("core.malloc.entry", "size: %zu", size); if (tsd_get_allocates() && unlikely(!malloc_initialized())) { return fallback_alloc(size); } @@ -316,6 +361,8 @@ imalloc_fastpath(size_t size, void *(fallback_alloc)(size_t)) { tcache_t *tcache = tsd_tcachep_get(tsd); assert(tcache == tcache_get(tsd)); cache_bin_t *bin = &tcache->bins[ind]; + /* Suppress spurious warning from static analysis */ + assert(bin != NULL); bool tcache_success; void *ret; @@ -339,6 +386,212 @@ imalloc_fastpath(size_t size, void *(fallback_alloc)(size_t)) { return fallback_alloc(size); } -} // namespace duckdb_jemalloc +JEMALLOC_ALWAYS_INLINE tcache_t * +tcache_get_from_ind(tsd_t *tsd, unsigned tcache_ind, bool slow, bool is_alloc) { + tcache_t *tcache; + if (tcache_ind == TCACHE_IND_AUTOMATIC) { + if (likely(!slow)) { + /* Getting tcache ptr unconditionally. */ + tcache = tsd_tcachep_get(tsd); + assert(tcache == tcache_get(tsd)); + } else if (is_alloc || + likely(tsd_reentrancy_level_get(tsd) == 0)) { + tcache = tcache_get(tsd); + } else { + tcache = NULL; + } + } else { + /* + * Should not specify tcache on deallocation path when being + * reentrant. + */ + assert(is_alloc || tsd_reentrancy_level_get(tsd) == 0 || + tsd_state_nocleanup(tsd)); + if (tcache_ind == TCACHE_IND_NONE) { + tcache = NULL; + } else { + tcache = tcaches_get(tsd, tcache_ind); + } + } + return tcache; +} + +JEMALLOC_ALWAYS_INLINE bool +maybe_check_alloc_ctx(tsd_t *tsd, void *ptr, emap_alloc_ctx_t *alloc_ctx) { + if (config_opt_size_checks) { + emap_alloc_ctx_t dbg_ctx; + emap_alloc_ctx_lookup(tsd_tsdn(tsd), &arena_emap_global, ptr, + &dbg_ctx); + if (alloc_ctx->szind != dbg_ctx.szind) { + safety_check_fail_sized_dealloc( + /* current_dealloc */ true, ptr, + /* true_size */ sz_size2index(dbg_ctx.szind), + /* input_size */ sz_size2index(alloc_ctx->szind)); + return true; + } + if (alloc_ctx->slab != dbg_ctx.slab) { + safety_check_fail( + "Internal heap corruption detected: " + "mismatch in slab bit"); + return true; + } + } + return false; +} + +JEMALLOC_ALWAYS_INLINE bool +prof_sample_aligned(const void *ptr) { + return ((uintptr_t)ptr & PROF_SAMPLE_ALIGNMENT_MASK) == 0; +} + +JEMALLOC_ALWAYS_INLINE bool +free_fastpath_nonfast_aligned(void *ptr, bool check_prof) { + /* + * free_fastpath do not handle two uncommon cases: 1) sampled profiled + * objects and 2) sampled junk & stash for use-after-free detection. + * Both have special alignments which are used to escape the fastpath. + * + * prof_sample is page-aligned, which covers the UAF check when both + * are enabled (the assertion below). Avoiding redundant checks since + * this is on the fastpath -- at most one runtime branch from this. + */ + if (config_debug && cache_bin_nonfast_aligned(ptr)) { + assert(prof_sample_aligned(ptr)); + } + + if (config_prof && check_prof) { + /* When prof is enabled, the prof_sample alignment is enough. */ + if (prof_sample_aligned(ptr)) { + return true; + } else { + return false; + } + } + + if (config_uaf_detection) { + if (cache_bin_nonfast_aligned(ptr)) { + return true; + } else { + return false; + } + } + + return false; +} + +/* Returns whether or not the free attempt was successful. */ +JEMALLOC_ALWAYS_INLINE +bool free_fastpath(void *ptr, size_t size, bool size_hint) { + tsd_t *tsd = tsd_get(false); + /* The branch gets optimized away unless tsd_get_allocates(). */ + if (unlikely(tsd == NULL)) { + return false; + } + /* + * The tsd_fast() / initialized checks are folded into the branch + * testing (deallocated_after >= threshold) later in this function. + * The threshold will be set to 0 when !tsd_fast. + */ + assert(tsd_fast(tsd) || + *tsd_thread_deallocated_next_event_fastp_get_unsafe(tsd) == 0); + + emap_alloc_ctx_t alloc_ctx; + if (!size_hint) { + bool err = emap_alloc_ctx_try_lookup_fast(tsd, + &arena_emap_global, ptr, &alloc_ctx); + + /* Note: profiled objects will have alloc_ctx.slab set */ + if (unlikely(err || !alloc_ctx.slab || + free_fastpath_nonfast_aligned(ptr, + /* check_prof */ false))) { + return false; + } + assert(alloc_ctx.szind != SC_NSIZES); + } else { + /* + * Check for both sizes that are too large, and for sampled / + * special aligned objects. The alignment check will also check + * for null ptr. + */ + if (unlikely(size > SC_LOOKUP_MAXCLASS || + free_fastpath_nonfast_aligned(ptr, + /* check_prof */ true))) { + return false; + } + alloc_ctx.szind = sz_size2index_lookup(size); + /* Max lookup class must be small. */ + assert(alloc_ctx.szind < SC_NBINS); + /* This is a dead store, except when opt size checking is on. */ + alloc_ctx.slab = true; + } + /* + * Currently the fastpath only handles small sizes. The branch on + * SC_LOOKUP_MAXCLASS makes sure of it. This lets us avoid checking + * tcache szind upper limit (i.e. tcache_max) as well. + */ + assert(alloc_ctx.slab); + + uint64_t deallocated, threshold; + te_free_fastpath_ctx(tsd, &deallocated, &threshold); + + size_t usize = sz_index2size(alloc_ctx.szind); + uint64_t deallocated_after = deallocated + usize; + /* + * Check for events and tsd non-nominal (fast_threshold will be set to + * 0) in a single branch. Note that this handles the uninitialized case + * as well (TSD init will be triggered on the non-fastpath). Therefore + * anything depends on a functional TSD (e.g. the alloc_ctx sanity check + * below) needs to be after this branch. + */ + if (unlikely(deallocated_after >= threshold)) { + return false; + } + assert(tsd_fast(tsd)); + bool fail = maybe_check_alloc_ctx(tsd, ptr, &alloc_ctx); + if (fail) { + /* See the comment in isfree. */ + return true; + } + + tcache_t *tcache = tcache_get_from_ind(tsd, TCACHE_IND_AUTOMATIC, + /* slow */ false, /* is_alloc */ false); + cache_bin_t *bin = &tcache->bins[alloc_ctx.szind]; + + /* + * If junking were enabled, this is where we would do it. It's not + * though, since we ensured above that we're on the fast path. Assert + * that to double-check. + */ + assert(!opt_junk_free); + + if (!cache_bin_dalloc_easy(bin, ptr)) { + return false; + } + + *tsd_thread_deallocatedp_get(tsd) = deallocated_after; + + return true; +} + +JEMALLOC_ALWAYS_INLINE void JEMALLOC_NOTHROW +je_sdallocx_noflags(void *ptr, size_t size) { + if (!free_fastpath(ptr, size, true)) { + sdallocx_default(ptr, size, 0); + } +} + +JEMALLOC_ALWAYS_INLINE void JEMALLOC_NOTHROW +je_sdallocx_impl(void *ptr, size_t size, int flags) { + if (flags != 0 || !free_fastpath(ptr, size, true)) { + sdallocx_default(ptr, size, flags); + } +} + +JEMALLOC_ALWAYS_INLINE void JEMALLOC_NOTHROW +je_free_impl(void *ptr) { + if (!free_fastpath(ptr, 0, false)) { + free_default(ptr); + } +} #endif /* JEMALLOC_INTERNAL_INLINES_C_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h index ddcf9eb1be3..40df5febcdf 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h @@ -1,8 +1,6 @@ #ifndef JEMALLOC_INTERNAL_MACROS_H #define JEMALLOC_INTERNAL_MACROS_H -#include "jemalloc/jemalloc_macros.h" - #ifdef JEMALLOC_DEBUG # define JEMALLOC_ALWAYS_INLINE static inline #else @@ -39,8 +37,10 @@ /* Various function pointers are static and immutable except during testing. */ #ifdef JEMALLOC_JET # define JET_MUTABLE +# define JET_EXTERN extern #else # define JET_MUTABLE const +# define JET_EXTERN static #endif #define JEMALLOC_VA_ARGS_HEAD(head, ...) head @@ -52,8 +52,10 @@ # define JEMALLOC_DIAGNOSTIC_POP __pragma(warning(pop)) # define JEMALLOC_DIAGNOSTIC_IGNORE(W) __pragma(warning(disable:W)) # define JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS +# define JEMALLOC_DIAGNOSTIC_IGNORE_FRAME_ADDRESS # define JEMALLOC_DIAGNOSTIC_IGNORE_TYPE_LIMITS # define JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN +# define JEMALLOC_DIAGNOSTIC_IGNORE_DEPRECATED # define JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS /* #pragma GCC diagnostic first appeared in gcc 4.6. */ #elif (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && \ @@ -81,6 +83,8 @@ # define JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS # endif +# define JEMALLOC_DIAGNOSTIC_IGNORE_FRAME_ADDRESS \ + JEMALLOC_DIAGNOSTIC_IGNORE("-Wframe-address") # define JEMALLOC_DIAGNOSTIC_IGNORE_TYPE_LIMITS \ JEMALLOC_DIAGNOSTIC_IGNORE("-Wtype-limits") # define JEMALLOC_DIAGNOSTIC_IGNORE_UNUSED_PARAMETER \ @@ -91,6 +95,12 @@ # else # define JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN # endif +# ifdef JEMALLOC_HAVE_ATTR_DEPRECATED +# define JEMALLOC_DIAGNOSTIC_IGNORE_DEPRECATED \ + JEMALLOC_DIAGNOSTIC_IGNORE("-Wdeprecated-declarations") +# else +# define JEMALLOC_DIAGNOSTIC_IGNORE_DEPRECATED +# endif # define JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS \ JEMALLOC_DIAGNOSTIC_PUSH \ JEMALLOC_DIAGNOSTIC_IGNORE_UNUSED_PARAMETER @@ -99,11 +109,19 @@ # define JEMALLOC_DIAGNOSTIC_POP # define JEMALLOC_DIAGNOSTIC_IGNORE(W) # define JEMALLOC_DIAGNOSTIC_IGNORE_MISSING_STRUCT_FIELD_INITIALIZERS +# define JEMALLOC_DIAGNOSTIC_IGNORE_FRAME_ADDRESS # define JEMALLOC_DIAGNOSTIC_IGNORE_TYPE_LIMITS # define JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN +# define JEMALLOC_DIAGNOSTIC_IGNORE_DEPRECATED # define JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS #endif +#define JEMALLOC_SUPPRESS_WARN_ON_USAGE(...) \ + JEMALLOC_DIAGNOSTIC_PUSH \ + JEMALLOC_DIAGNOSTIC_IGNORE_DEPRECATED \ + __VA_ARGS__ \ + JEMALLOC_DIAGNOSTIC_POP + /* * Disables spurious diagnostics for all headers. Since these headers are not * included by users directly, it does not affect their diagnostic settings. diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_overrides.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_overrides.h new file mode 100644 index 00000000000..5fbbe249552 --- /dev/null +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_overrides.h @@ -0,0 +1,21 @@ +#ifndef JEMALLOC_INTERNAL_OVERRIDES_H +#define JEMALLOC_INTERNAL_OVERRIDES_H + +/* + * Under normal circumstances this header serves no purpose, as these settings + * can be customized via the corresponding autoconf options at configure-time. + * Overriding in this fashion is useful when the header files generated by + * autoconf are used as input for another build system. + */ + +#ifdef JEMALLOC_OVERRIDE_LG_PAGE + #undef LG_PAGE + #define LG_PAGE JEMALLOC_OVERRIDE_LG_PAGE +#endif + +#ifdef JEMALLOC_OVERRIDE_JEMALLOC_CONFIG_MALLOC_CONF + #undef JEMALLOC_CONFIG_MALLOC_CONF + #define JEMALLOC_CONFIG_MALLOC_CONF JEMALLOC_OVERRIDE_JEMALLOC_CONFIG_MALLOC_CONF +#endif + +#endif /* JEMALLOC_INTERNAL_OVERRIDES_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h index aa44c7b0491..4ab5a0cff81 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h @@ -3,8 +3,6 @@ #include "jemalloc/internal/quantum.h" -namespace duckdb_jemalloc { - /* Processor / core id type. */ typedef int malloc_cpuid_t; @@ -47,12 +45,12 @@ typedef enum malloc_init_e malloc_init_t; #define MALLOCX_ARENA_SHIFT 20 #define MALLOCX_TCACHE_SHIFT 8 #define MALLOCX_ARENA_MASK \ - (((1 << MALLOCX_ARENA_BITS) - 1) << MALLOCX_ARENA_SHIFT) + ((unsigned)(((1U << MALLOCX_ARENA_BITS) - 1) << MALLOCX_ARENA_SHIFT)) /* NB: Arena index bias decreases the maximum number of arenas by 1. */ -#define MALLOCX_ARENA_LIMIT ((1 << MALLOCX_ARENA_BITS) - 1) +#define MALLOCX_ARENA_LIMIT ((unsigned)((1U << MALLOCX_ARENA_BITS) - 1)) #define MALLOCX_TCACHE_MASK \ - (((1 << MALLOCX_TCACHE_BITS) - 1) << MALLOCX_TCACHE_SHIFT) -#define MALLOCX_TCACHE_MAX ((1 << MALLOCX_TCACHE_BITS) - 3) + ((unsigned)(((1U << MALLOCX_TCACHE_BITS) - 1) << MALLOCX_TCACHE_SHIFT)) +#define MALLOCX_TCACHE_MAX ((unsigned)((1U << MALLOCX_TCACHE_BITS) - 3)) #define MALLOCX_LG_ALIGN_MASK ((1 << MALLOCX_LG_ALIGN_BITS) - 1) /* Use MALLOCX_ALIGN_GET() if alignment may not be specified in flags. */ #define MALLOCX_ALIGN_GET_SPECIFIED(flags) \ @@ -101,7 +99,8 @@ typedef enum malloc_init_e malloc_init_t; /* Return the nearest aligned address at or below a. */ #define ALIGNMENT_ADDR2BASE(a, alignment) \ - ((void *)((uintptr_t)(a) & ((~(alignment)) + 1))) + ((void *)(((byte_t *)(a)) - (((uintptr_t)(a)) - \ + ((uintptr_t)(a) & ((~(alignment)) + 1))))) /* Return the offset between a and the nearest aligned address at or below a. */ #define ALIGNMENT_ADDR2OFFSET(a, alignment) \ @@ -111,28 +110,35 @@ typedef enum malloc_init_e malloc_init_t; #define ALIGNMENT_CEILING(s, alignment) \ (((s) + (alignment - 1)) & ((~(alignment)) + 1)) +/* + * Return the nearest aligned address at or above a. + * + * While at first glance this would appear to be merely a more complicated + * way to perform the same computation as `ALIGNMENT_CEILING`, + * this has the important additional property of not concealing pointer + * provenance from the compiler. See the block-comment on the + * definition of `byte_t` for more details. + */ +#define ALIGNMENT_ADDR2CEILING(a, alignment) \ + ((void *)(((byte_t *)(a)) + (((((uintptr_t)(a)) + \ + (alignment - 1)) & ((~(alignment)) + 1)) - ((uintptr_t)(a))))) + /* Declare a variable-length array. */ -#if __STDC_VERSION__ < 199901L +#if __STDC_VERSION__ < 199901L || defined(__STDC_NO_VLA__) # ifdef _MSC_VER # include # define alloca _alloca # else # ifdef JEMALLOC_HAS_ALLOCA_H -} // namespace duckdb_jemalloc # include -namespace duckdb_jemalloc { # else -} // namespace duckdb_jemalloc -# include -namespace duckdb_jemalloc { +# include # endif # endif # define VARIABLE_ARRAY(type, name, count) \ - type *name = (type *)alloca(sizeof(type) * (count)) + type *name = alloca(sizeof(type) * (count)) #else # define VARIABLE_ARRAY(type, name, count) type name[(count)] #endif -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_TYPES_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h index cfd73bc93da..3f93c014d51 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h @@ -1,11 +1,6 @@ #ifndef JEMALLOC_PREAMBLE_H #define JEMALLOC_PREAMBLE_H -#include -#include -#include -#include - #include "jemalloc/internal/jemalloc_internal_defs.h" #include "jemalloc/internal/jemalloc_internal_decls.h" @@ -25,11 +20,11 @@ # define JEMALLOC_N(n) jet_##n # include "jemalloc/internal/public_namespace.h" # define JEMALLOC_NO_RENAME -# include "jemalloc/jemalloc.h" +# include "../jemalloc.h" # undef JEMALLOC_NO_RENAME #else -# define JEMALLOC_N(n) je_##n -# include "jemalloc/jemalloc.h" +# define JEMALLOC_N(n) duckdb_je_##n +# include "../jemalloc.h" #endif #if defined(JEMALLOC_OSATOMIC) @@ -49,24 +44,19 @@ * want the inclusion of hooks to happen early, so that we hook as much as * possible. */ -/* #ifndef JEMALLOC_NO_PRIVATE_NAMESPACE # ifndef JEMALLOC_JET # include "jemalloc/internal/private_namespace.h" # else # include "jemalloc/internal/private_namespace_jet.h" -#include "jemalloc/internal/priva" # endif #endif - */ #include "jemalloc/internal/test_hooks.h" #ifdef JEMALLOC_DEFINE_MADVISE_FREE # define JEMALLOC_MADV_FREE 8 #endif -namespace duckdb_jemalloc { - static const bool config_debug = #ifdef JEMALLOC_DEBUG true @@ -225,7 +215,7 @@ static const bool config_enable_cxx = #endif ; -#if defined(_WIN32) || defined(JEMALLOC_HAVE_SCHED_GETCPU) +#if defined(_WIN32) || defined(__APPLE__) || defined(JEMALLOC_HAVE_SCHED_GETCPU) /* Currently percpu_arena depends on sched_getcpu. */ #define JEMALLOC_PERCPU_ARENA #endif @@ -270,13 +260,4 @@ static const bool have_memcntl = #endif ; -// calls to abort() must be within DEBUG block to satisfy duckdb R builds -static void jemalloc_abort() { -#ifdef DEBUG - abort(); -#endif -} - -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_PREAMBLE_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/large_externs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/large_externs.h index 6df798d58d4..ce9c8689400 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/large_externs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/large_externs.h @@ -1,10 +1,10 @@ #ifndef JEMALLOC_INTERNAL_LARGE_EXTERNS_H #define JEMALLOC_INTERNAL_LARGE_EXTERNS_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/edata.h" #include "jemalloc/internal/hook.h" -namespace duckdb_jemalloc { - void *large_malloc(tsdn_t *tsdn, arena_t *arena, size_t usize, bool zero); void *large_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, bool zero); @@ -23,6 +23,4 @@ void large_prof_info_get(tsd_t *tsd, edata_t *edata, prof_info_t *prof_info, void large_prof_tctx_reset(edata_t *edata); void large_prof_info_set(edata_t *edata, prof_tctx_t *tctx, size_t size); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_LARGE_EXTERNS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/lockedint.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/lockedint.h index c646924b053..062dedbfdb3 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/lockedint.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/lockedint.h @@ -1,7 +1,10 @@ #ifndef JEMALLOC_INTERNAL_LOCKEDINT_H #define JEMALLOC_INTERNAL_LOCKEDINT_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/tsd_types.h" /* * In those architectures that support 64-bit atomics, we use atomic updates for @@ -203,6 +206,4 @@ locked_read_atomic_zu(locked_zu_t *p) { return atomic_load_zu(&p->val, ATOMIC_RELAXED); } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_LOCKEDINT_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/log.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/log.h index 147a6c72922..7b074abde5b 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/log.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/log.h @@ -1,12 +1,11 @@ #ifndef JEMALLOC_INTERNAL_LOG_H #define JEMALLOC_INTERNAL_LOG_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/mutex.h" -namespace duckdb_jemalloc { - #ifdef JEMALLOC_LOG # define JEMALLOC_LOG_VAR_BUFSIZE 1000 #else @@ -28,9 +27,9 @@ namespace duckdb_jemalloc { * log("extent.a", "log msg for extent.a"); // 5 * log("extent.b", "log msg for extent.b"); // 6 * - * And your malloc_conf option is "log=arena.a|extent", then lines 2, 4, 5, and + * And your malloc_conf option is "log:arena.a|extent", then lines 2, 4, 5, and * 6 will print at runtime. You can enable logging from all log vars by - * writing "log=.". + * writing "log:.". * * None of this should be regarded as a stable API for right now. It's intended * as a debugging interface, to let us keep around some of our printf-debugging @@ -98,8 +97,7 @@ log_impl_varargs(const char *name, ...) { dst_offset += malloc_snprintf(buf, JEMALLOC_LOG_BUFSIZE, "%s: ", name); dst_offset += malloc_vsnprintf(buf + dst_offset, JEMALLOC_LOG_BUFSIZE - dst_offset, format, ap); - dst_offset += malloc_snprintf(buf + dst_offset, - JEMALLOC_LOG_BUFSIZE - dst_offset, "\n"); + malloc_snprintf(buf + dst_offset, JEMALLOC_LOG_BUFSIZE - dst_offset, "\n"); va_end(ap); malloc_write(buf); @@ -114,6 +112,4 @@ do { \ log_do_end(log_var) \ } while (0) -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_LOG_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/malloc_io.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/malloc_io.h index ef59998b16e..91e7b2ba758 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/malloc_io.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/malloc_io.h @@ -2,9 +2,6 @@ #define JEMALLOC_INTERNAL_MALLOC_IO_H #include "jemalloc/internal/jemalloc_preamble.h" - -#include "jemalloc/internal/jemalloc_internal_macros.h" -#include "jemalloc/internal/jemalloc_internal_decls.h" #include "jemalloc/internal/jemalloc_internal_types.h" #ifdef _WIN32 @@ -25,7 +22,7 @@ # define FMTuPTR FMTPTR_PREFIX "u" # define FMTxPTR FMTPTR_PREFIX "x" #else -# include +# include # define FMTd32 PRId32 # define FMTu32 PRIu32 # define FMTx32 PRIx32 @@ -37,8 +34,6 @@ # define FMTxPTR PRIxPTR #endif -namespace duckdb_jemalloc { - /* Size of stack-allocated buffer passed to buferror(). */ #define BUFERROR_BUF 64 @@ -72,44 +67,71 @@ void malloc_cprintf(write_cb_t *write_cb, void *cbopaque, const char *format, ...) JEMALLOC_FORMAT_PRINTF(3, 4); void malloc_printf(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2); +static inline ssize_t +malloc_write_fd_syscall(int fd, const void *buf, size_t count) { +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_write) + /* + * Use syscall(2) rather than write(2) when possible in order to avoid + * the possibility of memory allocation within libc. This is necessary + * on FreeBSD; most operating systems do not have this problem though. + * + * syscall() returns long or int, depending on platform, so capture the + * result in the widest plausible type to avoid compiler warnings. + */ + long result = syscall(SYS_write, fd, buf, count); +#else + ssize_t result = (ssize_t)write(fd, buf, +#ifdef _WIN32 + (unsigned int) +#endif + count); +#endif + return (ssize_t)result; +} + static inline ssize_t malloc_write_fd(int fd, const void *buf, size_t count) { -//#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_write) -// /* -// * Use syscall(2) rather than write(2) when possible in order to avoid -// * the possibility of memory allocation within libc. This is necessary -// * on FreeBSD; most operating systems do not have this problem though. -// * -// * syscall() returns long or int, depending on platform, so capture the -// * result in the widest plausible type to avoid compiler warnings. -// */ -// long result = syscall(SYS_write, fd, buf, count); -//#else -// ssize_t result = (ssize_t)write(fd, buf, -//#ifdef _WIN32 -// (unsigned int) -//#endif -// count); -//#endif -// return (ssize_t)result; - return (ssize_t)0; + size_t bytes_written = 0; + do { + ssize_t result = malloc_write_fd_syscall(fd, + &((const byte_t *)buf)[bytes_written], + count - bytes_written); + if (result < 0) { + return result; + } + bytes_written += result; + } while (bytes_written < count); + return bytes_written; } static inline ssize_t -malloc_read_fd(int fd, void *buf, size_t count) { -//#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read) -// long result = syscall(SYS_read, fd, buf, count); -//#else -// ssize_t result = read(fd, buf, -//#ifdef _WIN32 -// (unsigned int) -//#endif -// count); -//#endif -// return (ssize_t)result; - return (ssize_t)0; +malloc_read_fd_syscall(int fd, void *buf, size_t count) { +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read) + long result = syscall(SYS_read, fd, buf, count); +#else + ssize_t result = read(fd, buf, +#ifdef _WIN32 + (unsigned int) +#endif + count); +#endif + return (ssize_t)result; } -} // namespace duckdb_jemalloc +static inline ssize_t +malloc_read_fd(int fd, void *buf, size_t count) { + size_t bytes_read = 0; + do { + ssize_t result = malloc_read_fd_syscall(fd, + &((byte_t *)buf)[bytes_read], count - bytes_read); + if (result < 0) { + return result; + } else if (result == 0) { + break; + } + bytes_read += result; + } while (bytes_read < count); + return bytes_read; +} #endif /* JEMALLOC_INTERNAL_MALLOC_IO_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/mpsc_queue.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/mpsc_queue.h index 2844a5b3eb4..d8aa624bba6 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/mpsc_queue.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/mpsc_queue.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_MPSC_QUEUE_H #define JEMALLOC_INTERNAL_MPSC_QUEUE_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/atomic.h" -namespace duckdb_jemalloc { - /* * A concurrent implementation of a multi-producer, single-consumer queue. It * supports three concurrent operations: @@ -133,6 +132,4 @@ a_prefix##pop_batch(a_queue_type *queue, a_list_type *dst) { \ ql_concat(dst, &reversed, a_link); \ } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_MPSC_QUEUE_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/mutex.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/mutex.h index 76358d3daa3..75abf298bf3 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/mutex.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/mutex.h @@ -1,13 +1,12 @@ #ifndef JEMALLOC_INTERNAL_MUTEX_H #define JEMALLOC_INTERNAL_MUTEX_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/mutex_prof.h" #include "jemalloc/internal/tsd.h" #include "jemalloc/internal/witness.h" -namespace duckdb_jemalloc { - extern int64_t opt_mutex_max_spin; typedef enum { @@ -33,6 +32,12 @@ struct malloc_mutex_s { * unlocking thread). */ mutex_prof_data_t prof_data; + /* + * Hint flag to avoid exclusive cache line contention + * during spin waiting. Placed along with prof_data + * since it's always modified even with no contention. + */ + atomic_b_t locked; #ifdef _WIN32 # if _WIN32_WINNT >= 0x0600 SRWLOCK lock; @@ -47,11 +52,6 @@ struct malloc_mutex_s { #else pthread_mutex_t lock; #endif - /* - * Hint flag to avoid exclusive cache line contention - * during spin waiting - */ - atomic_b_t locked; }; /* * We only touch witness when configured w/ debug. However we @@ -100,21 +100,21 @@ struct malloc_mutex_s { #elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) # if defined(JEMALLOC_DEBUG) # define MALLOC_MUTEX_INITIALIZER \ - {{{LOCK_PROF_DATA_INITIALIZER, OS_UNFAIR_LOCK_INIT, ATOMIC_INIT(false)}}, \ + {{{LOCK_PROF_DATA_INITIALIZER, ATOMIC_INIT(false), OS_UNFAIR_LOCK_INIT}}, \ WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT), 0} # else # define MALLOC_MUTEX_INITIALIZER \ - {{{LOCK_PROF_DATA_INITIALIZER, OS_UNFAIR_LOCK_INIT, ATOMIC_INIT(false)}}, \ + {{{LOCK_PROF_DATA_INITIALIZER, ATOMIC_INIT(false), OS_UNFAIR_LOCK_INIT}}, \ WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} # endif #elif (defined(JEMALLOC_MUTEX_INIT_CB)) # if (defined(JEMALLOC_DEBUG)) # define MALLOC_MUTEX_INITIALIZER \ - {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, NULL, ATOMIC_INIT(false)}}, \ + {{{LOCK_PROF_DATA_INITIALIZER, ATOMIC_INIT(false), PTHREAD_MUTEX_INITIALIZER, NULL}}, \ WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT), 0} # else # define MALLOC_MUTEX_INITIALIZER \ - {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, NULL, ATOMIC_INIT(false)}}, \ + {{{LOCK_PROF_DATA_INITIALIZER, ATOMIC_INIT(false), PTHREAD_MUTEX_INITIALIZER, NULL}}, \ WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} # endif @@ -122,11 +122,11 @@ struct malloc_mutex_s { # define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT # if defined(JEMALLOC_DEBUG) # define MALLOC_MUTEX_INITIALIZER \ - {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, ATOMIC_INIT(false)}}, \ - WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT), (malloc_mutex_lock_order_t)0} + {{{LOCK_PROF_DATA_INITIALIZER, ATOMIC_INIT(false), PTHREAD_MUTEX_INITIALIZER}}, \ + WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT), 0} # else # define MALLOC_MUTEX_INITIALIZER \ - {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, ATOMIC_INIT(false)}}, \ + {{{LOCK_PROF_DATA_INITIALIZER, ATOMIC_INIT(false), PTHREAD_MUTEX_INITIALIZER}}, \ WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} # endif #endif @@ -177,7 +177,6 @@ malloc_mutex_trylock(tsdn_t *tsdn, malloc_mutex_t *mutex) { witness_assert_not_owner(tsdn_witness_tsdp_get(tsdn), &mutex->witness); if (isthreaded) { if (malloc_mutex_trylock_final(mutex)) { - atomic_store_b(&mutex->locked, true, ATOMIC_RELAXED); return true; } mutex_owner_stats_update(tsdn, mutex); @@ -318,6 +317,4 @@ malloc_mutex_prof_max_update(tsdn_t *tsdn, mutex_prof_data_t *data, /* n_wait_thds is not reported. */ } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_MUTEX_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/mutex_prof.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/mutex_prof.h index 310e2a43f5f..14e4340b787 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/mutex_prof.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/mutex_prof.h @@ -1,12 +1,11 @@ #ifndef JEMALLOC_INTERNAL_MUTEX_PROF_H #define JEMALLOC_INTERNAL_MUTEX_PROF_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/atomic.h" #include "jemalloc/internal/nstime.h" #include "jemalloc/internal/tsd_types.h" -namespace duckdb_jemalloc { - #define MUTEX_PROF_GLOBAL_MUTEXES \ OP(background_thread) \ OP(max_per_bg_thd) \ @@ -116,6 +115,4 @@ typedef struct { uint64_t n_lock_ops; } mutex_prof_data_t; -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_MUTEX_PROF_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/nstime.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/nstime.h index ad1406f861d..440a4d15e12 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/nstime.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/nstime.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_NSTIME_H #define JEMALLOC_INTERNAL_NSTIME_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/assert.h" -namespace duckdb_jemalloc { - /* Maximum supported number of seconds (~584 years). */ #define NSTIME_SEC_MAX KQU(18446744072) @@ -60,7 +59,7 @@ enum prof_time_res_e { typedef enum prof_time_res_e prof_time_res_t; extern prof_time_res_t opt_prof_time_res; -extern const char *prof_time_res_mode_names[]; +extern const char *const prof_time_res_mode_names[]; JEMALLOC_ALWAYS_INLINE void nstime_init_zero(nstime_t *time) { @@ -74,6 +73,4 @@ nstime_equals_zero(nstime_t *time) { return diff == 0; } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_NSTIME_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/pa.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/pa.h index 0b3df90b5ca..75626738784 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/pa.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/pa.h @@ -1,6 +1,7 @@ #ifndef JEMALLOC_INTERNAL_PA_H #define JEMALLOC_INTERNAL_PA_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/base.h" #include "jemalloc/internal/decay.h" #include "jemalloc/internal/ecache.h" @@ -12,8 +13,6 @@ #include "jemalloc/internal/pai.h" #include "jemalloc/internal/sec.h" -namespace duckdb_jemalloc { - /* * The page allocator; responsible for acquiring pages of memory for * allocations. It picks the implementation of the page allocator interface @@ -133,7 +132,7 @@ pa_shard_ehooks_get(pa_shard_t *shard) { /* Returns true on error. */ bool pa_central_init(pa_central_t *central, base_t *base, bool hpa, - hpa_hooks_t *hpa_hooks); + const hpa_hooks_t *hpa_hooks); /* Returns true on error. */ bool pa_shard_init(tsdn_t *tsdn, pa_shard_t *shard, pa_central_t *central, @@ -225,6 +224,10 @@ void pa_shard_prefork5(tsdn_t *tsdn, pa_shard_t *shard); void pa_shard_postfork_parent(tsdn_t *tsdn, pa_shard_t *shard); void pa_shard_postfork_child(tsdn_t *tsdn, pa_shard_t *shard); +size_t pa_shard_nactive(pa_shard_t *shard); +size_t pa_shard_ndirty(pa_shard_t *shard); +size_t pa_shard_nmuzzy(pa_shard_t *shard); + void pa_shard_basic_stats_merge(pa_shard_t *shard, size_t *nactive, size_t *ndirty, size_t *nmuzzy); @@ -242,6 +245,4 @@ void pa_shard_stats_merge(tsdn_t *tsdn, pa_shard_t *shard, void pa_shard_mtx_stats_read(tsdn_t *tsdn, pa_shard_t *shard, mutex_prof_data_t mutex_prof_data[mutex_prof_num_arena_mutexes]); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PA_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/pac.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/pac.h index 7ba795f7245..0b173a584a4 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/pac.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/pac.h @@ -1,12 +1,15 @@ #ifndef JEMALLOC_INTERNAL_PAC_H #define JEMALLOC_INTERNAL_PAC_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/decay.h" +#include "jemalloc/internal/ecache.h" +#include "jemalloc/internal/edata_cache.h" #include "jemalloc/internal/exp_grow.h" +#include "jemalloc/internal/lockedint.h" #include "jemalloc/internal/pai.h" #include "san_bump.h" -namespace duckdb_jemalloc { - /* * Page allocator classic; an implementation of the PAI interface that: * - Can be used for arenas with custom extent hooks. @@ -177,6 +180,4 @@ ssize_t pac_decay_ms_get(pac_t *pac, extent_state_t state); void pac_reset(tsdn_t *tsdn, pac_t *pac); void pac_destroy(tsdn_t *tsdn, pac_t *pac); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PAC_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/pages.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/pages.h index 45aa6993e5d..b4e9678e9dd 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/pages.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/pages.h @@ -1,9 +1,11 @@ #ifndef JEMALLOC_INTERNAL_PAGES_EXTERNS_H #define JEMALLOC_INTERNAL_PAGES_EXTERNS_H -#include "jemalloc/internal/jemalloc_internal_decls.h" +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_types.h" -namespace duckdb_jemalloc { +/* Actual operating system page size, detected during bootstrap, <= PAGE. */ +extern size_t os_page; /* Page size. LG_PAGE is determined by the configure script. */ #ifdef PAGE_MASK @@ -13,7 +15,7 @@ namespace duckdb_jemalloc { #define PAGE_MASK ((size_t)(PAGE - 1)) /* Return the page base address for the page containing address a. */ #define PAGE_ADDR2BASE(a) \ - ((void *)((uintptr_t)(a) & ~PAGE_MASK)) + ALIGNMENT_ADDR2BASE(a, PAGE) /* Return the smallest pagesize multiple that is >= s. */ #define PAGE_CEILING(s) \ (((s) + PAGE_MASK) & ~PAGE_MASK) @@ -40,7 +42,7 @@ namespace duckdb_jemalloc { /* Return the huge page base address for the huge page containing address a. */ #define HUGEPAGE_ADDR2BASE(a) \ - ((void *)((uintptr_t)(a) & ~HUGEPAGE_MASK)) + ALIGNMENT_ADDR2BASE(a, HUGEPAGE) /* Return the smallest pagesize multiple that is >= s. */ #define HUGEPAGE_CEILING(s) \ (((s) + HUGEPAGE_MASK) & ~HUGEPAGE_MASK) @@ -103,7 +105,7 @@ typedef enum { #define THP_MODE_DEFAULT thp_mode_default extern thp_mode_t opt_thp; extern thp_mode_t init_system_thp_mode; /* Initial system wide state. */ -extern const char *thp_mode_names[]; +extern const char *const thp_mode_names[]; void *pages_map(void *addr, size_t size, size_t alignment, bool *commit); void pages_unmap(void *addr, size_t size); @@ -120,6 +122,4 @@ void pages_set_thp_state (void *ptr, size_t size); void pages_mark_guards(void *head, void *tail); void pages_unmark_guards(void *head, void *tail); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PAGES_EXTERNS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/pai.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/pai.h index 988f540710e..557d30d1e4a 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/pai.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/pai.h @@ -1,9 +1,11 @@ #ifndef JEMALLOC_INTERNAL_PAI_H #define JEMALLOC_INTERNAL_PAI_H -/* An interface for page allocation. */ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/edata.h" +#include "jemalloc/internal/tsd_types.h" -namespace duckdb_jemalloc { +/* An interface for page allocation. */ typedef struct pai_s pai_t; struct pai_s { @@ -18,7 +20,7 @@ struct pai_s { * the results are not necessarily zeroed. */ size_t (*alloc_batch)(tsdn_t *tsdn, pai_t *self, size_t size, - size_t nallocs, edata_list_active_t *results, + size_t nallocs, edata_list_active_t *results, bool frequent_reuse, bool *deferred_work_generated); bool (*expand)(tsdn_t *tsdn, pai_t *self, edata_t *edata, size_t old_size, size_t new_size, bool zero, @@ -48,9 +50,10 @@ pai_alloc(tsdn_t *tsdn, pai_t *self, size_t size, size_t alignment, static inline size_t pai_alloc_batch(tsdn_t *tsdn, pai_t *self, size_t size, size_t nallocs, - edata_list_active_t *results, bool *deferred_work_generated) { + edata_list_active_t *results, bool frequent_reuse, + bool *deferred_work_generated) { return self->alloc_batch(tsdn, self, size, nallocs, results, - deferred_work_generated); + frequent_reuse, deferred_work_generated); } static inline bool @@ -89,11 +92,10 @@ pai_time_until_deferred_work(tsdn_t *tsdn, pai_t *self) { * each item in the list. */ size_t pai_alloc_batch_default(tsdn_t *tsdn, pai_t *self, size_t size, - size_t nallocs, edata_list_active_t *results, bool *deferred_work_generated); + size_t nallocs, edata_list_active_t *results, bool frequent_reuse, + bool *deferred_work_generated); /* Ditto, for dalloc. */ void pai_dalloc_batch_default(tsdn_t *tsdn, pai_t *self, edata_list_active_t *list, bool *deferred_work_generated); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PAI_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/peak.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/peak.h index 1eeaeb789f6..2a973cb8331 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/peak.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/peak.h @@ -1,7 +1,7 @@ #ifndef JEMALLOC_INTERNAL_PEAK_H #define JEMALLOC_INTERNAL_PEAK_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" typedef struct peak_s peak_t; struct peak_s { @@ -36,6 +36,4 @@ peak_set_zero(peak_t *peak, uint64_t alloc, uint64_t dalloc) { peak->adjustment = alloc - dalloc; } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PEAK_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/peak_event.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/peak_event.h index a58a899bd58..cc2a14018fa 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/peak_event.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/peak_event.h @@ -1,7 +1,8 @@ #ifndef JEMALLOC_INTERNAL_PEAK_EVENT_H #define JEMALLOC_INTERNAL_PEAK_EVENT_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/tsd_types.h" /* * While peak.h contains the simple helper struct that tracks state, this @@ -23,6 +24,4 @@ uint64_t peak_dalloc_new_event_wait(tsd_t *tsd); uint64_t peak_dalloc_postponed_event_wait(tsd_t *tsd); void peak_dalloc_event_handler(tsd_t *tsd, uint64_t elapsed); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PEAK_EVENT_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/ph.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/ph.h index cd7b3db076e..ef9634be75b 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/ph.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/ph.h @@ -1,6 +1,10 @@ #ifndef JEMALLOC_INTERNAL_PH_H #define JEMALLOC_INTERNAL_PH_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/bit_util.h" + /* * A Pairing Heap implementation. * @@ -49,8 +53,6 @@ * all took amortized complexity of an insert from O(1) to O(log(n)). */ -namespace duckdb_jemalloc { - typedef int (*ph_cmp_t)(void *, void *); /* Node structure. */ @@ -75,7 +77,7 @@ struct ph_s { JEMALLOC_ALWAYS_INLINE phn_link_t * phn_link_get(void *phn, size_t offset) { - return (phn_link_t *)(((uintptr_t)phn) + offset); + return (phn_link_t *)(((char *)phn) + offset); } JEMALLOC_ALWAYS_INLINE void @@ -129,6 +131,7 @@ phn_merge_ordered(void *phn0, void *phn1, size_t offset, phn0child = phn_lchild_get(phn0, offset); phn_next_set(phn1, phn0child, offset); if (phn0child != NULL) { + /* NOLINTNEXTLINE(readability-suspicious-call-argument) */ phn_prev_set(phn0child, phn1, offset); } phn_lchild_set(phn0, phn1, offset); @@ -145,6 +148,7 @@ phn_merge(void *phn0, void *phn1, size_t offset, ph_cmp_t cmp) { phn_merge_ordered(phn0, phn1, offset, cmp); result = phn0; } else { + /* NOLINTNEXTLINE(readability-suspicious-call-argument) */ phn_merge_ordered(phn1, phn0, offset, cmp); result = phn1; } @@ -158,6 +162,10 @@ phn_merge_siblings(void *phn, size_t offset, ph_cmp_t cmp) { void *phn0 = phn; void *phn1 = phn_next_get(phn0, offset); + if (phn1 == NULL) { + return phn0; + } + /* * Multipass merge, wherein the first two elements of a FIFO * are repeatedly merged, and each result is appended to the @@ -166,59 +174,61 @@ phn_merge_siblings(void *phn, size_t offset, ph_cmp_t cmp) { * its tail, so we do a single pass over the sibling list to * populate the FIFO. */ - if (phn1 != NULL) { - void *phnrest = phn_next_get(phn1, offset); - if (phnrest != NULL) { - phn_prev_set(phnrest, NULL, offset); - } - phn_prev_set(phn0, NULL, offset); - phn_next_set(phn0, NULL, offset); - phn_prev_set(phn1, NULL, offset); - phn_next_set(phn1, NULL, offset); - phn0 = phn_merge(phn0, phn1, offset, cmp); - head = tail = phn0; - phn0 = phnrest; - while (phn0 != NULL) { - phn1 = phn_next_get(phn0, offset); - if (phn1 != NULL) { - phnrest = phn_next_get(phn1, offset); - if (phnrest != NULL) { - phn_prev_set(phnrest, NULL, offset); - } - phn_prev_set(phn0, NULL, offset); - phn_next_set(phn0, NULL, offset); - phn_prev_set(phn1, NULL, offset); - phn_next_set(phn1, NULL, offset); - phn0 = phn_merge(phn0, phn1, offset, cmp); - phn_next_set(tail, phn0, offset); - tail = phn0; - phn0 = phnrest; - } else { - phn_next_set(tail, phn0, offset); - tail = phn0; - phn0 = NULL; - } - } - phn0 = head; + void *phnrest = phn_next_get(phn1, offset); + if (phnrest != NULL) { + phn_prev_set(phnrest, NULL, offset); + } + phn_prev_set(phn0, NULL, offset); + phn_next_set(phn0, NULL, offset); + phn_prev_set(phn1, NULL, offset); + phn_next_set(phn1, NULL, offset); + phn0 = phn_merge(phn0, phn1, offset, cmp); + head = tail = phn0; + phn0 = phnrest; + while (phn0 != NULL) { phn1 = phn_next_get(phn0, offset); if (phn1 != NULL) { - while (true) { - head = phn_next_get(phn1, offset); - assert(phn_prev_get(phn0, offset) == NULL); - phn_next_set(phn0, NULL, offset); - assert(phn_prev_get(phn1, offset) == NULL); - phn_next_set(phn1, NULL, offset); - phn0 = phn_merge(phn0, phn1, offset, cmp); - if (head == NULL) { - break; - } - phn_next_set(tail, phn0, offset); - tail = phn0; - phn0 = head; - phn1 = phn_next_get(phn0, offset); + phnrest = phn_next_get(phn1, offset); + if (phnrest != NULL) { + phn_prev_set(phnrest, NULL, offset); } + phn_prev_set(phn0, NULL, offset); + phn_next_set(phn0, NULL, offset); + phn_prev_set(phn1, NULL, offset); + phn_next_set(phn1, NULL, offset); + phn0 = phn_merge(phn0, phn1, offset, cmp); + /* NOLINTNEXTLINE(readability-suspicious-call-argument) */ + phn_next_set(tail, phn0, offset); + tail = phn0; + phn0 = phnrest; + } else { + /* NOLINTNEXTLINE(readability-suspicious-call-argument) */ + phn_next_set(tail, phn0, offset); + tail = phn0; + phn0 = NULL; } } + phn0 = head; + phn1 = phn_next_get(phn0, offset); + if (phn1 != NULL) { + while (true) { + head = phn_next_get(phn1, offset); + assert(phn_prev_get(phn0, offset) == NULL); + phn_next_set(phn0, NULL, offset); + assert(phn_prev_get(phn1, offset) == NULL); + phn_next_set(phn1, NULL, offset); + phn0 = phn_merge(phn0, phn1, offset, cmp); + if (head == NULL) { + break; + } + /* NOLINTNEXTLINE(readability-suspicious-call-argument) */ + phn_next_set(tail, phn0, offset); + tail = phn0; + phn0 = head; + phn1 = phn_next_get(phn0, offset); + } + } + return phn0; } @@ -232,7 +242,7 @@ ph_merge_aux(ph_t *ph, size_t offset, ph_cmp_t cmp) { phn_prev_set(phn, NULL, offset); phn = phn_merge_siblings(phn, offset, cmp); assert(phn_next_get(phn, offset) == NULL); - ph->root = phn_merge(ph->root, phn, offset, cmp); + phn_merge_ordered(ph->root, phn, offset, cmp); } } @@ -300,6 +310,7 @@ ph_try_aux_merge_pair(ph_t *ph, size_t offset, ph_cmp_t cmp) { phn0 = phn_merge(phn0, phn1, offset, cmp); phn_next_set(phn0, next_phn1, offset); if (next_phn1 != NULL) { + /* NOLINTNEXTLINE(readability-suspicious-call-argument) */ phn_prev_set(next_phn1, phn0, offset); } phn_next_set(ph->root, phn0, offset); @@ -320,36 +331,37 @@ ph_insert(ph_t *ph, void *phn, size_t offset, ph_cmp_t cmp) { */ if (ph->root == NULL) { ph->root = phn; - } else { - /* - * As a special case, check to see if we can replace the root. - * This is practically common in some important cases, and lets - * us defer some insertions (hopefully, until the point where - * some of the items in the aux list have been removed, savings - * us from linking them at all). - */ - if (cmp(phn, ph->root) < 0) { - phn_lchild_set(phn, ph->root, offset); - phn_prev_set(ph->root, phn, offset); - ph->root = phn; - ph->auxcount = 0; - return; - } - ph->auxcount++; - phn_next_set(phn, phn_next_get(ph->root, offset), offset); - if (phn_next_get(ph->root, offset) != NULL) { - phn_prev_set(phn_next_get(ph->root, offset), phn, - offset); - } - phn_prev_set(phn, ph->root, offset); - phn_next_set(ph->root, phn, offset); + return; } - if (ph->auxcount > 1) { - unsigned nmerges = ffs_zu(ph->auxcount - 1); - bool done = false; - for (unsigned i = 0; i < nmerges && !done; i++) { - done = ph_try_aux_merge_pair(ph, offset, cmp); - } + + /* + * As a special case, check to see if we can replace the root. + * This is practically common in some important cases, and lets + * us defer some insertions (hopefully, until the point where + * some of the items in the aux list have been removed, savings + * us from linking them at all). + */ + if (cmp(phn, ph->root) < 0) { + phn_lchild_set(phn, ph->root, offset); + phn_prev_set(ph->root, phn, offset); + ph->root = phn; + ph->auxcount = 0; + return; + } + + phn_next_set(phn, phn_next_get(ph->root, offset), offset); + if (phn_next_get(ph->root, offset) != NULL) { + phn_prev_set(phn_next_get(ph->root, offset), phn, + offset); + } + phn_prev_set(phn, ph->root, offset); + phn_next_set(ph->root, phn, offset); + + ph->auxcount++; + unsigned nmerges = ffs_zu(ph->auxcount); + bool done = false; + for (unsigned i = 0; i < nmerges && !done; i++) { + done = ph_try_aux_merge_pair(ph, offset, cmp); } } @@ -370,73 +382,35 @@ ph_remove_first(ph_t *ph, size_t offset, ph_cmp_t cmp) { JEMALLOC_ALWAYS_INLINE void ph_remove(ph_t *ph, void *phn, size_t offset, ph_cmp_t cmp) { - void *replace; - void *parent; - if (ph->root == phn) { - /* - * We can delete from aux list without merging it, but we need - * to merge if we are dealing with the root node and it has - * children. - */ - if (phn_lchild_get(phn, offset) == NULL) { - ph->root = phn_next_get(phn, offset); - if (ph->root != NULL) { - phn_prev_set(ph->root, NULL, offset); - } - return; - } ph_merge_aux(ph, offset, cmp); - if (ph->root == phn) { - ph->root = ph_merge_children(ph->root, offset, cmp); - return; - } + ph->root = ph_merge_children(phn, offset, cmp); + return; } - /* Get parent (if phn is leftmost child) before mutating. */ - if ((parent = phn_prev_get(phn, offset)) != NULL) { - if (phn_lchild_get(parent, offset) != phn) { - parent = NULL; - } - } - /* Find a possible replacement node, and link to parent. */ - replace = ph_merge_children(phn, offset, cmp); - /* Set next/prev for sibling linked list. */ + void* prev = phn_prev_get(phn, offset); + void* next = phn_next_get(phn, offset); + + /* If we have children, then we integrate them back in the heap. */ + void* replace = ph_merge_children(phn, offset, cmp); if (replace != NULL) { - if (parent != NULL) { - phn_prev_set(replace, parent, offset); - phn_lchild_set(parent, replace, offset); - } else { - phn_prev_set(replace, phn_prev_get(phn, offset), - offset); - if (phn_prev_get(phn, offset) != NULL) { - phn_next_set(phn_prev_get(phn, offset), replace, - offset); - } - } - phn_next_set(replace, phn_next_get(phn, offset), offset); - if (phn_next_get(phn, offset) != NULL) { - phn_prev_set(phn_next_get(phn, offset), replace, - offset); + phn_next_set(replace, next, offset); + if (next != NULL) { + phn_prev_set(next, replace, offset); } + + next = replace; + } + + if (next != NULL) { + phn_prev_set(next, prev, offset); + } + + assert(prev != NULL); + if (phn_lchild_get(prev, offset) == phn) { + phn_lchild_set(prev, next, offset); } else { - if (parent != NULL) { - void *next = phn_next_get(phn, offset); - phn_lchild_set(parent, next, offset); - if (next != NULL) { - phn_prev_set(next, parent, offset); - } - } else { - assert(phn_prev_get(phn, offset) != NULL); - phn_next_set( - phn_prev_get(phn, offset), - phn_next_get(phn, offset), offset); - } - if (phn_next_get(phn, offset) != NULL) { - phn_prev_set( - phn_next_get(phn, offset), - phn_prev_get(phn, offset), offset); - } + phn_next_set(prev, next, offset); } } @@ -483,13 +457,13 @@ a_prefix##_empty(a_prefix##_t *ph) { \ \ a_attr a_type * \ a_prefix##_first(a_prefix##_t *ph) { \ - return (a_type *)ph_first(&ph->ph, offsetof(a_type, a_field), \ + return ph_first(&ph->ph, offsetof(a_type, a_field), \ &a_prefix##_ph_cmp); \ } \ \ a_attr a_type * \ a_prefix##_any(a_prefix##_t *ph) { \ - return (a_type *)ph_any(&ph->ph, offsetof(a_type, a_field)); \ + return ph_any(&ph->ph, offsetof(a_type, a_field)); \ } \ \ a_attr void \ @@ -500,7 +474,7 @@ a_prefix##_insert(a_prefix##_t *ph, a_type *phn) { \ \ a_attr a_type * \ a_prefix##_remove_first(a_prefix##_t *ph) { \ - return (a_type *)ph_remove_first(&ph->ph, offsetof(a_type, a_field), \ + return ph_remove_first(&ph->ph, offsetof(a_type, a_field), \ a_prefix##_ph_cmp); \ } \ \ @@ -519,6 +493,4 @@ a_prefix##_remove_any(a_prefix##_t *ph) { \ return ret; \ } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PH_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/private_namespace.gen.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/private_namespace.gen.h new file mode 100644 index 00000000000..c68f27fd2d1 --- /dev/null +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/private_namespace.gen.h @@ -0,0 +1,726 @@ +#define a0dalloc JEMALLOC_N(a0dalloc) +#define a0malloc JEMALLOC_N(a0malloc) +#define arena_choose_hard JEMALLOC_N(arena_choose_hard) +#define arena_cleanup JEMALLOC_N(arena_cleanup) +#define arena_init JEMALLOC_N(arena_init) +#define arena_migrate JEMALLOC_N(arena_migrate) +#define arena_set JEMALLOC_N(arena_set) +#define arenas JEMALLOC_N(arenas) +#define arenas_lock JEMALLOC_N(arenas_lock) +#define batch_alloc JEMALLOC_N(batch_alloc) +#define bootstrap_calloc JEMALLOC_N(bootstrap_calloc) +#define bootstrap_free JEMALLOC_N(bootstrap_free) +#define bootstrap_malloc JEMALLOC_N(bootstrap_malloc) +#define free_default JEMALLOC_N(free_default) +#define iarena_cleanup JEMALLOC_N(iarena_cleanup) +#define je_sdallocx_noflags JEMALLOC_N(je_sdallocx_noflags) +#define jemalloc_postfork_child JEMALLOC_N(jemalloc_postfork_child) +#define jemalloc_postfork_parent JEMALLOC_N(jemalloc_postfork_parent) +#define jemalloc_prefork JEMALLOC_N(jemalloc_prefork) +#define junk_alloc_callback JEMALLOC_N(junk_alloc_callback) +#define junk_free_callback JEMALLOC_N(junk_free_callback) +#define malloc_default JEMALLOC_N(malloc_default) +#define malloc_init_state JEMALLOC_N(malloc_init_state) +#define malloc_slow JEMALLOC_N(malloc_slow) +#define manual_arena_base JEMALLOC_N(manual_arena_base) +#define narenas_auto JEMALLOC_N(narenas_auto) +#define narenas_total_get JEMALLOC_N(narenas_total_get) +#define ncpus JEMALLOC_N(ncpus) +#define opt_abort JEMALLOC_N(opt_abort) +#define opt_abort_conf JEMALLOC_N(opt_abort_conf) +#define opt_cache_oblivious JEMALLOC_N(opt_cache_oblivious) +#define opt_confirm_conf JEMALLOC_N(opt_confirm_conf) +#define opt_experimental_infallible_new JEMALLOC_N(opt_experimental_infallible_new) +#define opt_hpa JEMALLOC_N(opt_hpa) +#define opt_hpa_opts JEMALLOC_N(opt_hpa_opts) +#define opt_hpa_sec_opts JEMALLOC_N(opt_hpa_sec_opts) +#define opt_junk JEMALLOC_N(opt_junk) +#define opt_junk_alloc JEMALLOC_N(opt_junk_alloc) +#define opt_junk_free JEMALLOC_N(opt_junk_free) +#define opt_narenas JEMALLOC_N(opt_narenas) +#define opt_narenas_ratio JEMALLOC_N(opt_narenas_ratio) +#define opt_trust_madvise JEMALLOC_N(opt_trust_madvise) +#define opt_utrace JEMALLOC_N(opt_utrace) +#define opt_xmalloc JEMALLOC_N(opt_xmalloc) +#define opt_zero JEMALLOC_N(opt_zero) +#define opt_zero_realloc_action JEMALLOC_N(opt_zero_realloc_action) +#define sdallocx_default JEMALLOC_N(sdallocx_default) +#define zero_realloc_count JEMALLOC_N(zero_realloc_count) +#define zero_realloc_mode_names JEMALLOC_N(zero_realloc_mode_names) +#define arena_basic_stats_merge JEMALLOC_N(arena_basic_stats_merge) +#define arena_bin_choose JEMALLOC_N(arena_bin_choose) +#define arena_bin_offsets JEMALLOC_N(arena_bin_offsets) +#define arena_binind_div_info JEMALLOC_N(arena_binind_div_info) +#define arena_boot JEMALLOC_N(arena_boot) +#define arena_cache_bin_fill_small JEMALLOC_N(arena_cache_bin_fill_small) +#define arena_choose_huge JEMALLOC_N(arena_choose_huge) +#define arena_config_default JEMALLOC_N(arena_config_default) +#define arena_dalloc_bin_locked_handle_newly_empty JEMALLOC_N(arena_dalloc_bin_locked_handle_newly_empty) +#define arena_dalloc_bin_locked_handle_newly_nonempty JEMALLOC_N(arena_dalloc_bin_locked_handle_newly_nonempty) +#define arena_dalloc_promoted JEMALLOC_N(arena_dalloc_promoted) +#define arena_dalloc_small JEMALLOC_N(arena_dalloc_small) +#define arena_decay JEMALLOC_N(arena_decay) +#define arena_decay_ms_get JEMALLOC_N(arena_decay_ms_get) +#define arena_decay_ms_set JEMALLOC_N(arena_decay_ms_set) +#define arena_destroy JEMALLOC_N(arena_destroy) +#define arena_dirty_decay_ms_default_get JEMALLOC_N(arena_dirty_decay_ms_default_get) +#define arena_dirty_decay_ms_default_set JEMALLOC_N(arena_dirty_decay_ms_default_set) +#define arena_do_deferred_work JEMALLOC_N(arena_do_deferred_work) +#define arena_dss_prec_get JEMALLOC_N(arena_dss_prec_get) +#define arena_dss_prec_set JEMALLOC_N(arena_dss_prec_set) +#define arena_emap_global JEMALLOC_N(arena_emap_global) +#define arena_extent_alloc_large JEMALLOC_N(arena_extent_alloc_large) +#define arena_extent_dalloc_large_prep JEMALLOC_N(arena_extent_dalloc_large_prep) +#define arena_extent_ralloc_large_expand JEMALLOC_N(arena_extent_ralloc_large_expand) +#define arena_extent_ralloc_large_shrink JEMALLOC_N(arena_extent_ralloc_large_shrink) +#define arena_fill_small_fresh JEMALLOC_N(arena_fill_small_fresh) +#define arena_get_ehooks JEMALLOC_N(arena_get_ehooks) +#define arena_handle_deferred_work JEMALLOC_N(arena_handle_deferred_work) +#define arena_init_huge JEMALLOC_N(arena_init_huge) +#define arena_is_huge JEMALLOC_N(arena_is_huge) +#define arena_malloc_hard JEMALLOC_N(arena_malloc_hard) +#define arena_muzzy_decay_ms_default_get JEMALLOC_N(arena_muzzy_decay_ms_default_get) +#define arena_muzzy_decay_ms_default_set JEMALLOC_N(arena_muzzy_decay_ms_default_set) +#define arena_new JEMALLOC_N(arena_new) +#define arena_nthreads_dec JEMALLOC_N(arena_nthreads_dec) +#define arena_nthreads_get JEMALLOC_N(arena_nthreads_get) +#define arena_nthreads_inc JEMALLOC_N(arena_nthreads_inc) +#define arena_pa_central_global JEMALLOC_N(arena_pa_central_global) +#define arena_palloc JEMALLOC_N(arena_palloc) +#define arena_postfork_child JEMALLOC_N(arena_postfork_child) +#define arena_postfork_parent JEMALLOC_N(arena_postfork_parent) +#define arena_prefork0 JEMALLOC_N(arena_prefork0) +#define arena_prefork1 JEMALLOC_N(arena_prefork1) +#define arena_prefork2 JEMALLOC_N(arena_prefork2) +#define arena_prefork3 JEMALLOC_N(arena_prefork3) +#define arena_prefork4 JEMALLOC_N(arena_prefork4) +#define arena_prefork5 JEMALLOC_N(arena_prefork5) +#define arena_prefork6 JEMALLOC_N(arena_prefork6) +#define arena_prefork7 JEMALLOC_N(arena_prefork7) +#define arena_prefork8 JEMALLOC_N(arena_prefork8) +#define arena_prof_promote JEMALLOC_N(arena_prof_promote) +#define arena_ralloc JEMALLOC_N(arena_ralloc) +#define arena_ralloc_no_move JEMALLOC_N(arena_ralloc_no_move) +#define arena_reset JEMALLOC_N(arena_reset) +#define arena_retain_grow_limit_get_set JEMALLOC_N(arena_retain_grow_limit_get_set) +#define arena_set_extent_hooks JEMALLOC_N(arena_set_extent_hooks) +#define arena_slab_dalloc JEMALLOC_N(arena_slab_dalloc) +#define arena_stats_merge JEMALLOC_N(arena_stats_merge) +#define opt_dirty_decay_ms JEMALLOC_N(opt_dirty_decay_ms) +#define opt_muzzy_decay_ms JEMALLOC_N(opt_muzzy_decay_ms) +#define opt_oversize_threshold JEMALLOC_N(opt_oversize_threshold) +#define opt_percpu_arena JEMALLOC_N(opt_percpu_arena) +#define oversize_threshold JEMALLOC_N(oversize_threshold) +#define percpu_arena_mode_names JEMALLOC_N(percpu_arena_mode_names) +#define background_thread_boot0 JEMALLOC_N(background_thread_boot0) +#define background_thread_boot1 JEMALLOC_N(background_thread_boot1) +#define background_thread_create JEMALLOC_N(background_thread_create) +#define background_thread_ctl_init JEMALLOC_N(background_thread_ctl_init) +#define background_thread_enabled_state JEMALLOC_N(background_thread_enabled_state) +#define background_thread_info JEMALLOC_N(background_thread_info) +#define background_thread_is_started JEMALLOC_N(background_thread_is_started) +#define background_thread_lock JEMALLOC_N(background_thread_lock) +#define background_thread_postfork_child JEMALLOC_N(background_thread_postfork_child) +#define background_thread_postfork_parent JEMALLOC_N(background_thread_postfork_parent) +#define background_thread_prefork0 JEMALLOC_N(background_thread_prefork0) +#define background_thread_prefork1 JEMALLOC_N(background_thread_prefork1) +#define background_thread_stats_read JEMALLOC_N(background_thread_stats_read) +#define background_thread_wakeup_early JEMALLOC_N(background_thread_wakeup_early) +#define background_threads_disable JEMALLOC_N(background_threads_disable) +#define background_threads_enable JEMALLOC_N(background_threads_enable) +#define max_background_threads JEMALLOC_N(max_background_threads) +#define n_background_threads JEMALLOC_N(n_background_threads) +#define opt_background_thread JEMALLOC_N(opt_background_thread) +#define opt_max_background_threads JEMALLOC_N(opt_max_background_threads) +#define b0get JEMALLOC_N(b0get) +#define base_alloc JEMALLOC_N(base_alloc) +#define base_alloc_edata JEMALLOC_N(base_alloc_edata) +#define base_boot JEMALLOC_N(base_boot) +#define base_delete JEMALLOC_N(base_delete) +#define base_ehooks_get JEMALLOC_N(base_ehooks_get) +#define base_ehooks_get_for_metadata JEMALLOC_N(base_ehooks_get_for_metadata) +#define base_extent_hooks_set JEMALLOC_N(base_extent_hooks_set) +#define base_new JEMALLOC_N(base_new) +#define base_postfork_child JEMALLOC_N(base_postfork_child) +#define base_postfork_parent JEMALLOC_N(base_postfork_parent) +#define base_prefork JEMALLOC_N(base_prefork) +#define base_stats_get JEMALLOC_N(base_stats_get) +#define metadata_thp_mode_names JEMALLOC_N(metadata_thp_mode_names) +#define opt_metadata_thp JEMALLOC_N(opt_metadata_thp) +#define bin_init JEMALLOC_N(bin_init) +#define bin_postfork_child JEMALLOC_N(bin_postfork_child) +#define bin_postfork_parent JEMALLOC_N(bin_postfork_parent) +#define bin_prefork JEMALLOC_N(bin_prefork) +#define bin_shard_sizes_boot JEMALLOC_N(bin_shard_sizes_boot) +#define bin_update_shard_size JEMALLOC_N(bin_update_shard_size) +#define bin_info_boot JEMALLOC_N(bin_info_boot) +#define bin_infos JEMALLOC_N(bin_infos) +#define bitmap_info_init JEMALLOC_N(bitmap_info_init) +#define bitmap_init JEMALLOC_N(bitmap_init) +#define bitmap_size JEMALLOC_N(bitmap_size) +#define buf_writer_cb JEMALLOC_N(buf_writer_cb) +#define buf_writer_flush JEMALLOC_N(buf_writer_flush) +#define buf_writer_init JEMALLOC_N(buf_writer_init) +#define buf_writer_pipe JEMALLOC_N(buf_writer_pipe) +#define buf_writer_terminate JEMALLOC_N(buf_writer_terminate) +#define cache_bin_info_compute_alloc JEMALLOC_N(cache_bin_info_compute_alloc) +#define cache_bin_info_init JEMALLOC_N(cache_bin_info_init) +#define cache_bin_init JEMALLOC_N(cache_bin_init) +#define cache_bin_postincrement JEMALLOC_N(cache_bin_postincrement) +#define cache_bin_preincrement JEMALLOC_N(cache_bin_preincrement) +#define cache_bin_still_zero_initialized JEMALLOC_N(cache_bin_still_zero_initialized) +#define ckh_count JEMALLOC_N(ckh_count) +#define ckh_delete JEMALLOC_N(ckh_delete) +#define ckh_insert JEMALLOC_N(ckh_insert) +#define ckh_iter JEMALLOC_N(ckh_iter) +#define ckh_new JEMALLOC_N(ckh_new) +#define ckh_pointer_hash JEMALLOC_N(ckh_pointer_hash) +#define ckh_pointer_keycomp JEMALLOC_N(ckh_pointer_keycomp) +#define ckh_remove JEMALLOC_N(ckh_remove) +#define ckh_search JEMALLOC_N(ckh_search) +#define ckh_string_hash JEMALLOC_N(ckh_string_hash) +#define ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp) +#define counter_accum_init JEMALLOC_N(counter_accum_init) +#define counter_postfork_child JEMALLOC_N(counter_postfork_child) +#define counter_postfork_parent JEMALLOC_N(counter_postfork_parent) +#define counter_prefork JEMALLOC_N(counter_prefork) +#define ctl_boot JEMALLOC_N(ctl_boot) +#define ctl_bymib JEMALLOC_N(ctl_bymib) +#define ctl_bymibname JEMALLOC_N(ctl_bymibname) +#define ctl_byname JEMALLOC_N(ctl_byname) +#define ctl_mibnametomib JEMALLOC_N(ctl_mibnametomib) +#define ctl_mtx_assert_held JEMALLOC_N(ctl_mtx_assert_held) +#define ctl_nametomib JEMALLOC_N(ctl_nametomib) +#define ctl_postfork_child JEMALLOC_N(ctl_postfork_child) +#define ctl_postfork_parent JEMALLOC_N(ctl_postfork_parent) +#define ctl_prefork JEMALLOC_N(ctl_prefork) +#define decay_deadline_init JEMALLOC_N(decay_deadline_init) +#define decay_init JEMALLOC_N(decay_init) +#define decay_maybe_advance_epoch JEMALLOC_N(decay_maybe_advance_epoch) +#define decay_ms_valid JEMALLOC_N(decay_ms_valid) +#define decay_npages_purge_in JEMALLOC_N(decay_npages_purge_in) +#define decay_ns_until_purge JEMALLOC_N(decay_ns_until_purge) +#define decay_reinit JEMALLOC_N(decay_reinit) +#define div_init JEMALLOC_N(div_init) +#define ecache_init JEMALLOC_N(ecache_init) +#define ecache_postfork_child JEMALLOC_N(ecache_postfork_child) +#define ecache_postfork_parent JEMALLOC_N(ecache_postfork_parent) +#define ecache_prefork JEMALLOC_N(ecache_prefork) +#define edata_avail_any JEMALLOC_N(edata_avail_any) +#define edata_avail_empty JEMALLOC_N(edata_avail_empty) +#define edata_avail_first JEMALLOC_N(edata_avail_first) +#define edata_avail_insert JEMALLOC_N(edata_avail_insert) +#define edata_avail_new JEMALLOC_N(edata_avail_new) +#define edata_avail_remove JEMALLOC_N(edata_avail_remove) +#define edata_avail_remove_any JEMALLOC_N(edata_avail_remove_any) +#define edata_avail_remove_first JEMALLOC_N(edata_avail_remove_first) +#define edata_heap_any JEMALLOC_N(edata_heap_any) +#define edata_heap_empty JEMALLOC_N(edata_heap_empty) +#define edata_heap_first JEMALLOC_N(edata_heap_first) +#define edata_heap_insert JEMALLOC_N(edata_heap_insert) +#define edata_heap_new JEMALLOC_N(edata_heap_new) +#define edata_heap_remove JEMALLOC_N(edata_heap_remove) +#define edata_heap_remove_any JEMALLOC_N(edata_heap_remove_any) +#define edata_heap_remove_first JEMALLOC_N(edata_heap_remove_first) +#define edata_cache_fast_disable JEMALLOC_N(edata_cache_fast_disable) +#define edata_cache_fast_get JEMALLOC_N(edata_cache_fast_get) +#define edata_cache_fast_init JEMALLOC_N(edata_cache_fast_init) +#define edata_cache_fast_put JEMALLOC_N(edata_cache_fast_put) +#define edata_cache_get JEMALLOC_N(edata_cache_get) +#define edata_cache_init JEMALLOC_N(edata_cache_init) +#define edata_cache_postfork_child JEMALLOC_N(edata_cache_postfork_child) +#define edata_cache_postfork_parent JEMALLOC_N(edata_cache_postfork_parent) +#define edata_cache_prefork JEMALLOC_N(edata_cache_prefork) +#define edata_cache_put JEMALLOC_N(edata_cache_put) +#define ehooks_default_alloc_impl JEMALLOC_N(ehooks_default_alloc_impl) +#define ehooks_default_commit_impl JEMALLOC_N(ehooks_default_commit_impl) +#define ehooks_default_dalloc_impl JEMALLOC_N(ehooks_default_dalloc_impl) +#define ehooks_default_decommit_impl JEMALLOC_N(ehooks_default_decommit_impl) +#define ehooks_default_destroy_impl JEMALLOC_N(ehooks_default_destroy_impl) +#define ehooks_default_extent_hooks JEMALLOC_N(ehooks_default_extent_hooks) +#define ehooks_default_guard_impl JEMALLOC_N(ehooks_default_guard_impl) +#define ehooks_default_merge JEMALLOC_N(ehooks_default_merge) +#define ehooks_default_merge_impl JEMALLOC_N(ehooks_default_merge_impl) +#define ehooks_default_purge_forced_impl JEMALLOC_N(ehooks_default_purge_forced_impl) +#define ehooks_default_purge_lazy_impl JEMALLOC_N(ehooks_default_purge_lazy_impl) +#define ehooks_default_split_impl JEMALLOC_N(ehooks_default_split_impl) +#define ehooks_default_unguard_impl JEMALLOC_N(ehooks_default_unguard_impl) +#define ehooks_default_zero_impl JEMALLOC_N(ehooks_default_zero_impl) +#define ehooks_init JEMALLOC_N(ehooks_init) +#define emap_deregister_boundary JEMALLOC_N(emap_deregister_boundary) +#define emap_deregister_interior JEMALLOC_N(emap_deregister_interior) +#define emap_do_assert_mapped JEMALLOC_N(emap_do_assert_mapped) +#define emap_do_assert_not_mapped JEMALLOC_N(emap_do_assert_not_mapped) +#define emap_init JEMALLOC_N(emap_init) +#define emap_merge_commit JEMALLOC_N(emap_merge_commit) +#define emap_merge_prepare JEMALLOC_N(emap_merge_prepare) +#define emap_register_boundary JEMALLOC_N(emap_register_boundary) +#define emap_register_interior JEMALLOC_N(emap_register_interior) +#define emap_release_edata JEMALLOC_N(emap_release_edata) +#define emap_remap JEMALLOC_N(emap_remap) +#define emap_split_commit JEMALLOC_N(emap_split_commit) +#define emap_split_prepare JEMALLOC_N(emap_split_prepare) +#define emap_try_acquire_edata_neighbor JEMALLOC_N(emap_try_acquire_edata_neighbor) +#define emap_try_acquire_edata_neighbor_expand JEMALLOC_N(emap_try_acquire_edata_neighbor_expand) +#define emap_update_edata_state JEMALLOC_N(emap_update_edata_state) +#define eset_fit JEMALLOC_N(eset_fit) +#define eset_init JEMALLOC_N(eset_init) +#define eset_insert JEMALLOC_N(eset_insert) +#define eset_nbytes_get JEMALLOC_N(eset_nbytes_get) +#define eset_nextents_get JEMALLOC_N(eset_nextents_get) +#define eset_npages_get JEMALLOC_N(eset_npages_get) +#define eset_remove JEMALLOC_N(eset_remove) +#define exp_grow_init JEMALLOC_N(exp_grow_init) +#define ecache_alloc JEMALLOC_N(ecache_alloc) +#define ecache_alloc_grow JEMALLOC_N(ecache_alloc_grow) +#define ecache_dalloc JEMALLOC_N(ecache_dalloc) +#define ecache_evict JEMALLOC_N(ecache_evict) +#define extent_alloc_wrapper JEMALLOC_N(extent_alloc_wrapper) +#define extent_boot JEMALLOC_N(extent_boot) +#define extent_commit_wrapper JEMALLOC_N(extent_commit_wrapper) +#define extent_commit_zero JEMALLOC_N(extent_commit_zero) +#define extent_dalloc_gap JEMALLOC_N(extent_dalloc_gap) +#define extent_dalloc_wrapper JEMALLOC_N(extent_dalloc_wrapper) +#define extent_decommit_wrapper JEMALLOC_N(extent_decommit_wrapper) +#define extent_destroy_wrapper JEMALLOC_N(extent_destroy_wrapper) +#define extent_gdump_add JEMALLOC_N(extent_gdump_add) +#define extent_merge_wrapper JEMALLOC_N(extent_merge_wrapper) +#define extent_purge_forced_wrapper JEMALLOC_N(extent_purge_forced_wrapper) +#define extent_purge_lazy_wrapper JEMALLOC_N(extent_purge_lazy_wrapper) +#define extent_record JEMALLOC_N(extent_record) +#define extent_sn_next JEMALLOC_N(extent_sn_next) +#define extent_split_wrapper JEMALLOC_N(extent_split_wrapper) +#define opt_lg_extent_max_active_fit JEMALLOC_N(opt_lg_extent_max_active_fit) +#define dss_prec_names JEMALLOC_N(dss_prec_names) +#define extent_alloc_dss JEMALLOC_N(extent_alloc_dss) +#define extent_dss_boot JEMALLOC_N(extent_dss_boot) +#define extent_dss_mergeable JEMALLOC_N(extent_dss_mergeable) +#define extent_dss_prec_get JEMALLOC_N(extent_dss_prec_get) +#define extent_dss_prec_set JEMALLOC_N(extent_dss_prec_set) +#define extent_in_dss JEMALLOC_N(extent_in_dss) +#define opt_dss JEMALLOC_N(opt_dss) +#define extent_alloc_mmap JEMALLOC_N(extent_alloc_mmap) +#define extent_dalloc_mmap JEMALLOC_N(extent_dalloc_mmap) +#define opt_retain JEMALLOC_N(opt_retain) +#define fxp_parse JEMALLOC_N(fxp_parse) +#define fxp_print JEMALLOC_N(fxp_print) +#define opt_lg_san_uaf_align JEMALLOC_N(opt_lg_san_uaf_align) +#define opt_san_guard_large JEMALLOC_N(opt_san_guard_large) +#define opt_san_guard_small JEMALLOC_N(opt_san_guard_small) +#define san_cache_bin_nonfast_mask JEMALLOC_N(san_cache_bin_nonfast_mask) +#define san_check_stashed_ptrs JEMALLOC_N(san_check_stashed_ptrs) +#define san_guard_pages JEMALLOC_N(san_guard_pages) +#define san_init JEMALLOC_N(san_init) +#define san_unguard_pages JEMALLOC_N(san_unguard_pages) +#define san_unguard_pages_pre_destroy JEMALLOC_N(san_unguard_pages_pre_destroy) +#define tsd_san_init JEMALLOC_N(tsd_san_init) +#define san_bump_alloc JEMALLOC_N(san_bump_alloc) +#define hook_boot JEMALLOC_N(hook_boot) +#define hook_install JEMALLOC_N(hook_install) +#define hook_invoke_alloc JEMALLOC_N(hook_invoke_alloc) +#define hook_invoke_dalloc JEMALLOC_N(hook_invoke_dalloc) +#define hook_invoke_expand JEMALLOC_N(hook_invoke_expand) +#define hook_remove JEMALLOC_N(hook_remove) +#define hpa_central_extract JEMALLOC_N(hpa_central_extract) +#define hpa_central_init JEMALLOC_N(hpa_central_init) +#define hpa_shard_destroy JEMALLOC_N(hpa_shard_destroy) +#define hpa_shard_disable JEMALLOC_N(hpa_shard_disable) +#define hpa_shard_do_deferred_work JEMALLOC_N(hpa_shard_do_deferred_work) +#define hpa_shard_init JEMALLOC_N(hpa_shard_init) +#define hpa_shard_postfork_child JEMALLOC_N(hpa_shard_postfork_child) +#define hpa_shard_postfork_parent JEMALLOC_N(hpa_shard_postfork_parent) +#define hpa_shard_prefork3 JEMALLOC_N(hpa_shard_prefork3) +#define hpa_shard_prefork4 JEMALLOC_N(hpa_shard_prefork4) +#define hpa_shard_set_deferral_allowed JEMALLOC_N(hpa_shard_set_deferral_allowed) +#define hpa_shard_stats_accum JEMALLOC_N(hpa_shard_stats_accum) +#define hpa_shard_stats_merge JEMALLOC_N(hpa_shard_stats_merge) +#define hpa_supported JEMALLOC_N(hpa_supported) +#define hpa_hooks_default JEMALLOC_N(hpa_hooks_default) +#define hpdata_age_heap_any JEMALLOC_N(hpdata_age_heap_any) +#define hpdata_age_heap_empty JEMALLOC_N(hpdata_age_heap_empty) +#define hpdata_age_heap_first JEMALLOC_N(hpdata_age_heap_first) +#define hpdata_age_heap_insert JEMALLOC_N(hpdata_age_heap_insert) +#define hpdata_age_heap_new JEMALLOC_N(hpdata_age_heap_new) +#define hpdata_age_heap_remove JEMALLOC_N(hpdata_age_heap_remove) +#define hpdata_age_heap_remove_any JEMALLOC_N(hpdata_age_heap_remove_any) +#define hpdata_age_heap_remove_first JEMALLOC_N(hpdata_age_heap_remove_first) +#define hpdata_dehugify JEMALLOC_N(hpdata_dehugify) +#define hpdata_hugify JEMALLOC_N(hpdata_hugify) +#define hpdata_init JEMALLOC_N(hpdata_init) +#define hpdata_purge_begin JEMALLOC_N(hpdata_purge_begin) +#define hpdata_purge_end JEMALLOC_N(hpdata_purge_end) +#define hpdata_purge_next JEMALLOC_N(hpdata_purge_next) +#define hpdata_reserve_alloc JEMALLOC_N(hpdata_reserve_alloc) +#define hpdata_unreserve JEMALLOC_N(hpdata_unreserve) +#define inspect_extent_util_stats_get JEMALLOC_N(inspect_extent_util_stats_get) +#define inspect_extent_util_stats_verbose_get JEMALLOC_N(inspect_extent_util_stats_verbose_get) +#define large_dalloc JEMALLOC_N(large_dalloc) +#define large_dalloc_finish JEMALLOC_N(large_dalloc_finish) +#define large_dalloc_prep_locked JEMALLOC_N(large_dalloc_prep_locked) +#define large_malloc JEMALLOC_N(large_malloc) +#define large_palloc JEMALLOC_N(large_palloc) +#define large_prof_info_get JEMALLOC_N(large_prof_info_get) +#define large_prof_info_set JEMALLOC_N(large_prof_info_set) +#define large_prof_tctx_reset JEMALLOC_N(large_prof_tctx_reset) +#define large_ralloc JEMALLOC_N(large_ralloc) +#define large_ralloc_no_move JEMALLOC_N(large_ralloc_no_move) +#define large_salloc JEMALLOC_N(large_salloc) +#define log_init_done JEMALLOC_N(log_init_done) +#define log_var_names JEMALLOC_N(log_var_names) +#define log_var_update_state JEMALLOC_N(log_var_update_state) +#define buferror JEMALLOC_N(buferror) +#define malloc_cprintf JEMALLOC_N(malloc_cprintf) +#define malloc_printf JEMALLOC_N(malloc_printf) +#define malloc_snprintf JEMALLOC_N(malloc_snprintf) +#define malloc_strtoumax JEMALLOC_N(malloc_strtoumax) +#define malloc_vcprintf JEMALLOC_N(malloc_vcprintf) +#define malloc_vsnprintf JEMALLOC_N(malloc_vsnprintf) +#define malloc_write JEMALLOC_N(malloc_write) +#define wrtmessage JEMALLOC_N(wrtmessage) +#define malloc_mutex_boot JEMALLOC_N(malloc_mutex_boot) +#define malloc_mutex_init JEMALLOC_N(malloc_mutex_init) +#define malloc_mutex_lock_slow JEMALLOC_N(malloc_mutex_lock_slow) +#define malloc_mutex_postfork_child JEMALLOC_N(malloc_mutex_postfork_child) +#define malloc_mutex_postfork_parent JEMALLOC_N(malloc_mutex_postfork_parent) +#define malloc_mutex_prefork JEMALLOC_N(malloc_mutex_prefork) +#define malloc_mutex_prof_data_reset JEMALLOC_N(malloc_mutex_prof_data_reset) +#define opt_mutex_max_spin JEMALLOC_N(opt_mutex_max_spin) +#define nstime_add JEMALLOC_N(nstime_add) +#define nstime_compare JEMALLOC_N(nstime_compare) +#define nstime_copy JEMALLOC_N(nstime_copy) +#define nstime_divide JEMALLOC_N(nstime_divide) +#define nstime_iadd JEMALLOC_N(nstime_iadd) +#define nstime_idivide JEMALLOC_N(nstime_idivide) +#define nstime_imultiply JEMALLOC_N(nstime_imultiply) +#define nstime_init JEMALLOC_N(nstime_init) +#define nstime_init2 JEMALLOC_N(nstime_init2) +#define nstime_init_update JEMALLOC_N(nstime_init_update) +#define nstime_isubtract JEMALLOC_N(nstime_isubtract) +#define nstime_monotonic JEMALLOC_N(nstime_monotonic) +#define nstime_msec JEMALLOC_N(nstime_msec) +#define nstime_ns JEMALLOC_N(nstime_ns) +#define nstime_ns_since JEMALLOC_N(nstime_ns_since) +#define nstime_nsec JEMALLOC_N(nstime_nsec) +#define nstime_prof_init_update JEMALLOC_N(nstime_prof_init_update) +#define nstime_prof_update JEMALLOC_N(nstime_prof_update) +#define nstime_sec JEMALLOC_N(nstime_sec) +#define nstime_subtract JEMALLOC_N(nstime_subtract) +#define nstime_update JEMALLOC_N(nstime_update) +#define opt_prof_time_res JEMALLOC_N(opt_prof_time_res) +#define prof_time_res_mode_names JEMALLOC_N(prof_time_res_mode_names) +#define pa_alloc JEMALLOC_N(pa_alloc) +#define pa_central_init JEMALLOC_N(pa_central_init) +#define pa_dalloc JEMALLOC_N(pa_dalloc) +#define pa_decay_ms_get JEMALLOC_N(pa_decay_ms_get) +#define pa_decay_ms_set JEMALLOC_N(pa_decay_ms_set) +#define pa_expand JEMALLOC_N(pa_expand) +#define pa_shard_destroy JEMALLOC_N(pa_shard_destroy) +#define pa_shard_disable_hpa JEMALLOC_N(pa_shard_disable_hpa) +#define pa_shard_do_deferred_work JEMALLOC_N(pa_shard_do_deferred_work) +#define pa_shard_enable_hpa JEMALLOC_N(pa_shard_enable_hpa) +#define pa_shard_init JEMALLOC_N(pa_shard_init) +#define pa_shard_reset JEMALLOC_N(pa_shard_reset) +#define pa_shard_retain_grow_limit_get_set JEMALLOC_N(pa_shard_retain_grow_limit_get_set) +#define pa_shard_set_deferral_allowed JEMALLOC_N(pa_shard_set_deferral_allowed) +#define pa_shard_time_until_deferred_work JEMALLOC_N(pa_shard_time_until_deferred_work) +#define pa_shrink JEMALLOC_N(pa_shrink) +#define pa_shard_basic_stats_merge JEMALLOC_N(pa_shard_basic_stats_merge) +#define pa_shard_mtx_stats_read JEMALLOC_N(pa_shard_mtx_stats_read) +#define pa_shard_postfork_child JEMALLOC_N(pa_shard_postfork_child) +#define pa_shard_postfork_parent JEMALLOC_N(pa_shard_postfork_parent) +#define pa_shard_prefork0 JEMALLOC_N(pa_shard_prefork0) +#define pa_shard_prefork2 JEMALLOC_N(pa_shard_prefork2) +#define pa_shard_prefork3 JEMALLOC_N(pa_shard_prefork3) +#define pa_shard_prefork4 JEMALLOC_N(pa_shard_prefork4) +#define pa_shard_prefork5 JEMALLOC_N(pa_shard_prefork5) +#define pa_shard_stats_merge JEMALLOC_N(pa_shard_stats_merge) +#define pai_alloc_batch_default JEMALLOC_N(pai_alloc_batch_default) +#define pai_dalloc_batch_default JEMALLOC_N(pai_dalloc_batch_default) +#define pac_decay_all JEMALLOC_N(pac_decay_all) +#define pac_decay_ms_get JEMALLOC_N(pac_decay_ms_get) +#define pac_decay_ms_set JEMALLOC_N(pac_decay_ms_set) +#define pac_destroy JEMALLOC_N(pac_destroy) +#define pac_init JEMALLOC_N(pac_init) +#define pac_maybe_decay_purge JEMALLOC_N(pac_maybe_decay_purge) +#define pac_reset JEMALLOC_N(pac_reset) +#define pac_retain_grow_limit_get_set JEMALLOC_N(pac_retain_grow_limit_get_set) +#define init_system_thp_mode JEMALLOC_N(init_system_thp_mode) +#define opt_thp JEMALLOC_N(opt_thp) +#define pages_boot JEMALLOC_N(pages_boot) +#define pages_commit JEMALLOC_N(pages_commit) +#define pages_decommit JEMALLOC_N(pages_decommit) +#define pages_dodump JEMALLOC_N(pages_dodump) +#define pages_dontdump JEMALLOC_N(pages_dontdump) +#define pages_huge JEMALLOC_N(pages_huge) +#define pages_map JEMALLOC_N(pages_map) +#define pages_mark_guards JEMALLOC_N(pages_mark_guards) +#define pages_nohuge JEMALLOC_N(pages_nohuge) +#define pages_purge_forced JEMALLOC_N(pages_purge_forced) +#define pages_purge_lazy JEMALLOC_N(pages_purge_lazy) +#define pages_set_thp_state JEMALLOC_N(pages_set_thp_state) +#define pages_unmap JEMALLOC_N(pages_unmap) +#define pages_unmark_guards JEMALLOC_N(pages_unmark_guards) +#define thp_mode_names JEMALLOC_N(thp_mode_names) +#define peak_alloc_event_handler JEMALLOC_N(peak_alloc_event_handler) +#define peak_alloc_new_event_wait JEMALLOC_N(peak_alloc_new_event_wait) +#define peak_alloc_postponed_event_wait JEMALLOC_N(peak_alloc_postponed_event_wait) +#define peak_dalloc_event_handler JEMALLOC_N(peak_dalloc_event_handler) +#define peak_dalloc_new_event_wait JEMALLOC_N(peak_dalloc_new_event_wait) +#define peak_dalloc_postponed_event_wait JEMALLOC_N(peak_dalloc_postponed_event_wait) +#define peak_event_max JEMALLOC_N(peak_event_max) +#define peak_event_update JEMALLOC_N(peak_event_update) +#define peak_event_zero JEMALLOC_N(peak_event_zero) +#define lg_prof_sample JEMALLOC_N(lg_prof_sample) +#define opt_lg_prof_interval JEMALLOC_N(opt_lg_prof_interval) +#define opt_lg_prof_sample JEMALLOC_N(opt_lg_prof_sample) +#define opt_prof JEMALLOC_N(opt_prof) +#define opt_prof_accum JEMALLOC_N(opt_prof_accum) +#define opt_prof_active JEMALLOC_N(opt_prof_active) +#define opt_prof_final JEMALLOC_N(opt_prof_final) +#define opt_prof_gdump JEMALLOC_N(opt_prof_gdump) +#define opt_prof_leak JEMALLOC_N(opt_prof_leak) +#define opt_prof_leak_error JEMALLOC_N(opt_prof_leak_error) +#define opt_prof_prefix JEMALLOC_N(opt_prof_prefix) +#define opt_prof_sys_thread_name JEMALLOC_N(opt_prof_sys_thread_name) +#define opt_prof_thread_active_init JEMALLOC_N(opt_prof_thread_active_init) +#define opt_prof_unbias JEMALLOC_N(opt_prof_unbias) +#define prof_active_get JEMALLOC_N(prof_active_get) +#define prof_active_set JEMALLOC_N(prof_active_set) +#define prof_active_state JEMALLOC_N(prof_active_state) +#define prof_alloc_rollback JEMALLOC_N(prof_alloc_rollback) +#define prof_backtrace_hook JEMALLOC_N(prof_backtrace_hook) +#define prof_backtrace_hook_get JEMALLOC_N(prof_backtrace_hook_get) +#define prof_backtrace_hook_set JEMALLOC_N(prof_backtrace_hook_set) +#define prof_boot0 JEMALLOC_N(prof_boot0) +#define prof_boot1 JEMALLOC_N(prof_boot1) +#define prof_boot2 JEMALLOC_N(prof_boot2) +#define prof_booted JEMALLOC_N(prof_booted) +#define prof_dump_hook JEMALLOC_N(prof_dump_hook) +#define prof_dump_hook_get JEMALLOC_N(prof_dump_hook_get) +#define prof_dump_hook_set JEMALLOC_N(prof_dump_hook_set) +#define prof_free_sampled_object JEMALLOC_N(prof_free_sampled_object) +#define prof_gdump JEMALLOC_N(prof_gdump) +#define prof_gdump_get JEMALLOC_N(prof_gdump_get) +#define prof_gdump_set JEMALLOC_N(prof_gdump_set) +#define prof_gdump_val JEMALLOC_N(prof_gdump_val) +#define prof_idump JEMALLOC_N(prof_idump) +#define prof_interval JEMALLOC_N(prof_interval) +#define prof_malloc_sample_object JEMALLOC_N(prof_malloc_sample_object) +#define prof_mdump JEMALLOC_N(prof_mdump) +#define prof_postfork_child JEMALLOC_N(prof_postfork_child) +#define prof_postfork_parent JEMALLOC_N(prof_postfork_parent) +#define prof_prefork0 JEMALLOC_N(prof_prefork0) +#define prof_prefork1 JEMALLOC_N(prof_prefork1) +#define prof_sample_event_handler JEMALLOC_N(prof_sample_event_handler) +#define prof_sample_new_event_wait JEMALLOC_N(prof_sample_new_event_wait) +#define prof_sample_postponed_event_wait JEMALLOC_N(prof_sample_postponed_event_wait) +#define prof_tctx_create JEMALLOC_N(prof_tctx_create) +#define prof_tdata_cleanup JEMALLOC_N(prof_tdata_cleanup) +#define prof_tdata_init JEMALLOC_N(prof_tdata_init) +#define prof_tdata_reinit JEMALLOC_N(prof_tdata_reinit) +#define prof_thread_active_get JEMALLOC_N(prof_thread_active_get) +#define prof_thread_active_init_get JEMALLOC_N(prof_thread_active_init_get) +#define prof_thread_active_init_set JEMALLOC_N(prof_thread_active_init_set) +#define prof_thread_active_set JEMALLOC_N(prof_thread_active_set) +#define prof_thread_name_get JEMALLOC_N(prof_thread_name_get) +#define prof_thread_name_set JEMALLOC_N(prof_thread_name_set) +#define bt2gctx_mtx JEMALLOC_N(bt2gctx_mtx) +#define gctx_locks JEMALLOC_N(gctx_locks) +#define prof_bt_count JEMALLOC_N(prof_bt_count) +#define prof_bt_hash JEMALLOC_N(prof_bt_hash) +#define prof_bt_keycomp JEMALLOC_N(prof_bt_keycomp) +#define prof_cnt_all JEMALLOC_N(prof_cnt_all) +#define prof_data_init JEMALLOC_N(prof_data_init) +#define prof_dump_impl JEMALLOC_N(prof_dump_impl) +#define prof_dump_mtx JEMALLOC_N(prof_dump_mtx) +#define prof_lookup JEMALLOC_N(prof_lookup) +#define prof_reset JEMALLOC_N(prof_reset) +#define prof_shifted_unbiased_cnt JEMALLOC_N(prof_shifted_unbiased_cnt) +#define prof_tctx_try_destroy JEMALLOC_N(prof_tctx_try_destroy) +#define prof_tdata_count JEMALLOC_N(prof_tdata_count) +#define prof_tdata_detach JEMALLOC_N(prof_tdata_detach) +#define prof_tdata_init_impl JEMALLOC_N(prof_tdata_init_impl) +#define prof_thread_name_alloc JEMALLOC_N(prof_thread_name_alloc) +#define prof_thread_name_set_impl JEMALLOC_N(prof_thread_name_set_impl) +#define prof_unbias_map_init JEMALLOC_N(prof_unbias_map_init) +#define prof_unbiased_sz JEMALLOC_N(prof_unbiased_sz) +#define tdata_locks JEMALLOC_N(tdata_locks) +#define tdatas_mtx JEMALLOC_N(tdatas_mtx) +#define log_mtx JEMALLOC_N(log_mtx) +#define opt_prof_log JEMALLOC_N(opt_prof_log) +#define prof_log_alloc_count JEMALLOC_N(prof_log_alloc_count) +#define prof_log_bt_count JEMALLOC_N(prof_log_bt_count) +#define prof_log_dummy_set JEMALLOC_N(prof_log_dummy_set) +#define prof_log_init JEMALLOC_N(prof_log_init) +#define prof_log_is_logging JEMALLOC_N(prof_log_is_logging) +#define prof_log_rep_check JEMALLOC_N(prof_log_rep_check) +#define prof_log_start JEMALLOC_N(prof_log_start) +#define prof_log_stop JEMALLOC_N(prof_log_stop) +#define prof_log_thr_count JEMALLOC_N(prof_log_thr_count) +#define prof_logging_state JEMALLOC_N(prof_logging_state) +#define prof_try_log JEMALLOC_N(prof_try_log) +#define edata_prof_recent_alloc_get_no_lock_test JEMALLOC_N(edata_prof_recent_alloc_get_no_lock_test) +#define edata_prof_recent_alloc_init JEMALLOC_N(edata_prof_recent_alloc_init) +#define opt_prof_recent_alloc_max JEMALLOC_N(opt_prof_recent_alloc_max) +#define prof_recent_alloc JEMALLOC_N(prof_recent_alloc) +#define prof_recent_alloc_dump JEMALLOC_N(prof_recent_alloc_dump) +#define prof_recent_alloc_edata_get_no_lock_test JEMALLOC_N(prof_recent_alloc_edata_get_no_lock_test) +#define prof_recent_alloc_list JEMALLOC_N(prof_recent_alloc_list) +#define prof_recent_alloc_max_ctl_read JEMALLOC_N(prof_recent_alloc_max_ctl_read) +#define prof_recent_alloc_max_ctl_write JEMALLOC_N(prof_recent_alloc_max_ctl_write) +#define prof_recent_alloc_mtx JEMALLOC_N(prof_recent_alloc_mtx) +#define prof_recent_alloc_prepare JEMALLOC_N(prof_recent_alloc_prepare) +#define prof_recent_alloc_reset JEMALLOC_N(prof_recent_alloc_reset) +#define prof_recent_dump_mtx JEMALLOC_N(prof_recent_dump_mtx) +#define prof_recent_init JEMALLOC_N(prof_recent_init) +#define opt_prof_stats JEMALLOC_N(opt_prof_stats) +#define prof_stats_dec JEMALLOC_N(prof_stats_dec) +#define prof_stats_get_accum JEMALLOC_N(prof_stats_get_accum) +#define prof_stats_get_live JEMALLOC_N(prof_stats_get_live) +#define prof_stats_inc JEMALLOC_N(prof_stats_inc) +#define prof_stats_mtx JEMALLOC_N(prof_stats_mtx) +#define bt_init JEMALLOC_N(bt_init) +#define prof_backtrace JEMALLOC_N(prof_backtrace) +#define prof_base JEMALLOC_N(prof_base) +#define prof_do_mock JEMALLOC_N(prof_do_mock) +#define prof_dump_filename_mtx JEMALLOC_N(prof_dump_filename_mtx) +#define prof_dump_open_file JEMALLOC_N(prof_dump_open_file) +#define prof_dump_open_maps JEMALLOC_N(prof_dump_open_maps) +#define prof_dump_write_file JEMALLOC_N(prof_dump_write_file) +#define prof_fdump_impl JEMALLOC_N(prof_fdump_impl) +#define prof_gdump_impl JEMALLOC_N(prof_gdump_impl) +#define prof_get_default_filename JEMALLOC_N(prof_get_default_filename) +#define prof_getpid JEMALLOC_N(prof_getpid) +#define prof_hooks_init JEMALLOC_N(prof_hooks_init) +#define prof_idump_impl JEMALLOC_N(prof_idump_impl) +#define prof_mdump_impl JEMALLOC_N(prof_mdump_impl) +#define prof_prefix_set JEMALLOC_N(prof_prefix_set) +#define prof_sys_thread_name_fetch JEMALLOC_N(prof_sys_thread_name_fetch) +#define prof_sys_thread_name_read JEMALLOC_N(prof_sys_thread_name_read) +#define prof_unwind_init JEMALLOC_N(prof_unwind_init) +#define psset_init JEMALLOC_N(psset_init) +#define psset_insert JEMALLOC_N(psset_insert) +#define psset_pick_alloc JEMALLOC_N(psset_pick_alloc) +#define psset_pick_hugify JEMALLOC_N(psset_pick_hugify) +#define psset_pick_purge JEMALLOC_N(psset_pick_purge) +#define psset_remove JEMALLOC_N(psset_remove) +#define psset_stats_accum JEMALLOC_N(psset_stats_accum) +#define psset_update_begin JEMALLOC_N(psset_update_begin) +#define psset_update_end JEMALLOC_N(psset_update_end) +#define rtree_ctx_data_init JEMALLOC_N(rtree_ctx_data_init) +#define rtree_leaf_elm_lookup_hard JEMALLOC_N(rtree_leaf_elm_lookup_hard) +#define rtree_new JEMALLOC_N(rtree_new) +#define safety_check_fail JEMALLOC_N(safety_check_fail) +#define safety_check_fail_sized_dealloc JEMALLOC_N(safety_check_fail_sized_dealloc) +#define safety_check_set_abort JEMALLOC_N(safety_check_set_abort) +#define reg_size_compute JEMALLOC_N(reg_size_compute) +#define sc_boot JEMALLOC_N(sc_boot) +#define sc_data_init JEMALLOC_N(sc_data_init) +#define sc_data_update_slab_size JEMALLOC_N(sc_data_update_slab_size) +#define sec_disable JEMALLOC_N(sec_disable) +#define sec_flush JEMALLOC_N(sec_flush) +#define sec_init JEMALLOC_N(sec_init) +#define sec_mutex_stats_read JEMALLOC_N(sec_mutex_stats_read) +#define sec_postfork_child JEMALLOC_N(sec_postfork_child) +#define sec_postfork_parent JEMALLOC_N(sec_postfork_parent) +#define sec_prefork2 JEMALLOC_N(sec_prefork2) +#define sec_stats_merge JEMALLOC_N(sec_stats_merge) +#define arena_mutex_names JEMALLOC_N(arena_mutex_names) +#define global_mutex_names JEMALLOC_N(global_mutex_names) +#define opt_stats_interval JEMALLOC_N(opt_stats_interval) +#define opt_stats_interval_opts JEMALLOC_N(opt_stats_interval_opts) +#define opt_stats_print JEMALLOC_N(opt_stats_print) +#define opt_stats_print_opts JEMALLOC_N(opt_stats_print_opts) +#define stats_boot JEMALLOC_N(stats_boot) +#define stats_interval_event_handler JEMALLOC_N(stats_interval_event_handler) +#define stats_interval_new_event_wait JEMALLOC_N(stats_interval_new_event_wait) +#define stats_interval_postponed_event_wait JEMALLOC_N(stats_interval_postponed_event_wait) +#define stats_postfork_child JEMALLOC_N(stats_postfork_child) +#define stats_postfork_parent JEMALLOC_N(stats_postfork_parent) +#define stats_prefork JEMALLOC_N(stats_prefork) +#define stats_print JEMALLOC_N(stats_print) +#define sz_boot JEMALLOC_N(sz_boot) +#define sz_index2size_tab JEMALLOC_N(sz_index2size_tab) +#define sz_large_pad JEMALLOC_N(sz_large_pad) +#define sz_pind2sz_tab JEMALLOC_N(sz_pind2sz_tab) +#define sz_psz_quantize_ceil JEMALLOC_N(sz_psz_quantize_ceil) +#define sz_psz_quantize_floor JEMALLOC_N(sz_psz_quantize_floor) +#define sz_size2index_tab JEMALLOC_N(sz_size2index_tab) +#define nhbins JEMALLOC_N(nhbins) +#define opt_lg_tcache_flush_large_div JEMALLOC_N(opt_lg_tcache_flush_large_div) +#define opt_lg_tcache_flush_small_div JEMALLOC_N(opt_lg_tcache_flush_small_div) +#define opt_lg_tcache_nslots_mul JEMALLOC_N(opt_lg_tcache_nslots_mul) +#define opt_tcache JEMALLOC_N(opt_tcache) +#define opt_tcache_gc_delay_bytes JEMALLOC_N(opt_tcache_gc_delay_bytes) +#define opt_tcache_gc_incr_bytes JEMALLOC_N(opt_tcache_gc_incr_bytes) +#define opt_tcache_max JEMALLOC_N(opt_tcache_max) +#define opt_tcache_nslots_large JEMALLOC_N(opt_tcache_nslots_large) +#define opt_tcache_nslots_small_max JEMALLOC_N(opt_tcache_nslots_small_max) +#define opt_tcache_nslots_small_min JEMALLOC_N(opt_tcache_nslots_small_min) +#define tcache_alloc_small_hard JEMALLOC_N(tcache_alloc_small_hard) +#define tcache_arena_associate JEMALLOC_N(tcache_arena_associate) +#define tcache_arena_reassociate JEMALLOC_N(tcache_arena_reassociate) +#define tcache_assert_initialized JEMALLOC_N(tcache_assert_initialized) +#define tcache_bin_flush_large JEMALLOC_N(tcache_bin_flush_large) +#define tcache_bin_flush_small JEMALLOC_N(tcache_bin_flush_small) +#define tcache_bin_flush_stashed JEMALLOC_N(tcache_bin_flush_stashed) +#define tcache_bin_info JEMALLOC_N(tcache_bin_info) +#define tcache_boot JEMALLOC_N(tcache_boot) +#define tcache_cleanup JEMALLOC_N(tcache_cleanup) +#define tcache_create_explicit JEMALLOC_N(tcache_create_explicit) +#define tcache_flush JEMALLOC_N(tcache_flush) +#define tcache_gc_dalloc_event_handler JEMALLOC_N(tcache_gc_dalloc_event_handler) +#define tcache_gc_dalloc_new_event_wait JEMALLOC_N(tcache_gc_dalloc_new_event_wait) +#define tcache_gc_dalloc_postponed_event_wait JEMALLOC_N(tcache_gc_dalloc_postponed_event_wait) +#define tcache_gc_event_handler JEMALLOC_N(tcache_gc_event_handler) +#define tcache_gc_new_event_wait JEMALLOC_N(tcache_gc_new_event_wait) +#define tcache_gc_postponed_event_wait JEMALLOC_N(tcache_gc_postponed_event_wait) +#define tcache_maxclass JEMALLOC_N(tcache_maxclass) +#define tcache_postfork_child JEMALLOC_N(tcache_postfork_child) +#define tcache_postfork_parent JEMALLOC_N(tcache_postfork_parent) +#define tcache_prefork JEMALLOC_N(tcache_prefork) +#define tcache_salloc JEMALLOC_N(tcache_salloc) +#define tcache_stats_merge JEMALLOC_N(tcache_stats_merge) +#define tcaches JEMALLOC_N(tcaches) +#define tcaches_create JEMALLOC_N(tcaches_create) +#define tcaches_destroy JEMALLOC_N(tcaches_destroy) +#define tcaches_flush JEMALLOC_N(tcaches_flush) +#define tsd_tcache_data_init JEMALLOC_N(tsd_tcache_data_init) +#define tsd_tcache_enabled_data_init JEMALLOC_N(tsd_tcache_enabled_data_init) +#define test_hooks_arena_new_hook JEMALLOC_N(test_hooks_arena_new_hook) +#define test_hooks_libc_hook JEMALLOC_N(test_hooks_libc_hook) +#define te_assert_invariants_debug JEMALLOC_N(te_assert_invariants_debug) +#define te_event_trigger JEMALLOC_N(te_event_trigger) +#define te_recompute_fast_threshold JEMALLOC_N(te_recompute_fast_threshold) +#define tsd_te_init JEMALLOC_N(tsd_te_init) +#define ticker_geom_table JEMALLOC_N(ticker_geom_table) +#define malloc_tsd_boot0 JEMALLOC_N(malloc_tsd_boot0) +#define malloc_tsd_boot1 JEMALLOC_N(malloc_tsd_boot1) +#define malloc_tsd_dalloc JEMALLOC_N(malloc_tsd_dalloc) +#define malloc_tsd_malloc JEMALLOC_N(malloc_tsd_malloc) +#define tsd_boot_wrapper JEMALLOC_N(tsd_boot_wrapper) +#define tsd_booted JEMALLOC_N(tsd_booted) +#define tsd_cleanup JEMALLOC_N(tsd_cleanup) +#define tsd_fetch_slow JEMALLOC_N(tsd_fetch_slow) +#define tsd_global_slow JEMALLOC_N(tsd_global_slow) +#define tsd_global_slow_dec JEMALLOC_N(tsd_global_slow_dec) +#define tsd_global_slow_inc JEMALLOC_N(tsd_global_slow_inc) +#define tsd_init_check_recursion JEMALLOC_N(tsd_init_check_recursion) +#define tsd_init_finish JEMALLOC_N(tsd_init_finish) +#define tsd_init_head JEMALLOC_N(tsd_init_head) +#define tsd_postfork_child JEMALLOC_N(tsd_postfork_child) +#define tsd_postfork_parent JEMALLOC_N(tsd_postfork_parent) +#define tsd_prefork JEMALLOC_N(tsd_prefork) +#define tsd_slow_update JEMALLOC_N(tsd_slow_update) +#define tsd_state_set JEMALLOC_N(tsd_state_set) +#define tsd_tsd JEMALLOC_N(tsd_tsd) +#define witness_depth_error JEMALLOC_N(witness_depth_error) +#define witness_init JEMALLOC_N(witness_init) +#define witness_lock_error JEMALLOC_N(witness_lock_error) +#define witness_not_owner_error JEMALLOC_N(witness_not_owner_error) +#define witness_owner_error JEMALLOC_N(witness_owner_error) +#define witness_postfork_child JEMALLOC_N(witness_postfork_child) +#define witness_postfork_parent JEMALLOC_N(witness_postfork_parent) +#define witness_prefork JEMALLOC_N(witness_prefork) +#define witnesses_cleanup JEMALLOC_N(witnesses_cleanup) +#define zone_register JEMALLOC_N(zone_register) diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/private_namespace.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/private_namespace.h new file mode 100644 index 00000000000..4f9e2bb948f --- /dev/null +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/private_namespace.h @@ -0,0 +1,764 @@ +#define a0dalloc JEMALLOC_N(a0dalloc) +#define a0malloc JEMALLOC_N(a0malloc) +#define arena_choose_hard JEMALLOC_N(arena_choose_hard) +#define arena_cleanup JEMALLOC_N(arena_cleanup) +#define arena_init JEMALLOC_N(arena_init) +#define arena_migrate JEMALLOC_N(arena_migrate) +#define arena_set JEMALLOC_N(arena_set) +#define arenas JEMALLOC_N(arenas) +#define arenas_lock JEMALLOC_N(arenas_lock) +#define batch_alloc JEMALLOC_N(batch_alloc) +#define bootstrap_calloc JEMALLOC_N(bootstrap_calloc) +#define bootstrap_free JEMALLOC_N(bootstrap_free) +#define bootstrap_malloc JEMALLOC_N(bootstrap_malloc) +#define free_default JEMALLOC_N(free_default) +#define iarena_cleanup JEMALLOC_N(iarena_cleanup) +#define je_sdallocx_noflags JEMALLOC_N(je_sdallocx_noflags) +#define jemalloc_postfork_child JEMALLOC_N(jemalloc_postfork_child) +#define jemalloc_postfork_parent JEMALLOC_N(jemalloc_postfork_parent) +#define jemalloc_prefork JEMALLOC_N(jemalloc_prefork) +#define junk_alloc_callback JEMALLOC_N(junk_alloc_callback) +#define junk_free_callback JEMALLOC_N(junk_free_callback) +#define malloc_default JEMALLOC_N(malloc_default) +#define malloc_init_state JEMALLOC_N(malloc_init_state) +#define malloc_slow JEMALLOC_N(malloc_slow) +#define manual_arena_base JEMALLOC_N(manual_arena_base) +#define narenas_auto JEMALLOC_N(narenas_auto) +#define narenas_total_get JEMALLOC_N(narenas_total_get) +#define ncpus JEMALLOC_N(ncpus) +#define opt_abort JEMALLOC_N(opt_abort) +#define opt_abort_conf JEMALLOC_N(opt_abort_conf) +#define opt_cache_oblivious JEMALLOC_N(opt_cache_oblivious) +#define opt_confirm_conf JEMALLOC_N(opt_confirm_conf) +#define opt_experimental_infallible_new JEMALLOC_N(opt_experimental_infallible_new) +#define opt_hpa JEMALLOC_N(opt_hpa) +#define opt_hpa_opts JEMALLOC_N(opt_hpa_opts) +#define opt_hpa_sec_opts JEMALLOC_N(opt_hpa_sec_opts) +#define opt_junk JEMALLOC_N(opt_junk) +#define opt_junk_alloc JEMALLOC_N(opt_junk_alloc) +#define opt_junk_free JEMALLOC_N(opt_junk_free) +#define opt_narenas JEMALLOC_N(opt_narenas) +#define opt_narenas_ratio JEMALLOC_N(opt_narenas_ratio) +#define opt_trust_madvise JEMALLOC_N(opt_trust_madvise) +#define opt_utrace JEMALLOC_N(opt_utrace) +#define opt_xmalloc JEMALLOC_N(opt_xmalloc) +#define opt_zero JEMALLOC_N(opt_zero) +#define opt_zero_realloc_action JEMALLOC_N(opt_zero_realloc_action) +#define sdallocx_default JEMALLOC_N(sdallocx_default) +#define zero_realloc_count JEMALLOC_N(zero_realloc_count) +#define zero_realloc_mode_names JEMALLOC_N(zero_realloc_mode_names) +#define arena_basic_stats_merge JEMALLOC_N(arena_basic_stats_merge) +#define arena_bin_choose JEMALLOC_N(arena_bin_choose) +#define arena_bin_offsets JEMALLOC_N(arena_bin_offsets) +#define arena_binind_div_info JEMALLOC_N(arena_binind_div_info) +#define arena_boot JEMALLOC_N(arena_boot) +#define arena_cache_bin_fill_small JEMALLOC_N(arena_cache_bin_fill_small) +#define arena_choose_huge JEMALLOC_N(arena_choose_huge) +#define arena_config_default JEMALLOC_N(arena_config_default) +#define arena_dalloc_bin_locked_handle_newly_empty JEMALLOC_N(arena_dalloc_bin_locked_handle_newly_empty) +#define arena_dalloc_bin_locked_handle_newly_nonempty JEMALLOC_N(arena_dalloc_bin_locked_handle_newly_nonempty) +#define arena_dalloc_promoted JEMALLOC_N(arena_dalloc_promoted) +#define arena_dalloc_small JEMALLOC_N(arena_dalloc_small) +#define arena_decay JEMALLOC_N(arena_decay) +#define arena_decay_ms_get JEMALLOC_N(arena_decay_ms_get) +#define arena_decay_ms_set JEMALLOC_N(arena_decay_ms_set) +#define arena_destroy JEMALLOC_N(arena_destroy) +#define arena_dirty_decay_ms_default_get JEMALLOC_N(arena_dirty_decay_ms_default_get) +#define arena_dirty_decay_ms_default_set JEMALLOC_N(arena_dirty_decay_ms_default_set) +#define arena_do_deferred_work JEMALLOC_N(arena_do_deferred_work) +#define arena_dss_prec_get JEMALLOC_N(arena_dss_prec_get) +#define arena_dss_prec_set JEMALLOC_N(arena_dss_prec_set) +#define arena_emap_global JEMALLOC_N(arena_emap_global) +#define arena_extent_alloc_large JEMALLOC_N(arena_extent_alloc_large) +#define arena_extent_dalloc_large_prep JEMALLOC_N(arena_extent_dalloc_large_prep) +#define arena_extent_ralloc_large_expand JEMALLOC_N(arena_extent_ralloc_large_expand) +#define arena_extent_ralloc_large_shrink JEMALLOC_N(arena_extent_ralloc_large_shrink) +#define arena_fill_small_fresh JEMALLOC_N(arena_fill_small_fresh) +#define arena_get_ehooks JEMALLOC_N(arena_get_ehooks) +#define arena_handle_deferred_work JEMALLOC_N(arena_handle_deferred_work) +#define arena_init_huge JEMALLOC_N(arena_init_huge) +#define arena_is_huge JEMALLOC_N(arena_is_huge) +#define arena_malloc_hard JEMALLOC_N(arena_malloc_hard) +#define arena_muzzy_decay_ms_default_get JEMALLOC_N(arena_muzzy_decay_ms_default_get) +#define arena_muzzy_decay_ms_default_set JEMALLOC_N(arena_muzzy_decay_ms_default_set) +#define arena_new JEMALLOC_N(arena_new) +#define arena_nthreads_dec JEMALLOC_N(arena_nthreads_dec) +#define arena_nthreads_get JEMALLOC_N(arena_nthreads_get) +#define arena_nthreads_inc JEMALLOC_N(arena_nthreads_inc) +#define arena_pa_central_global JEMALLOC_N(arena_pa_central_global) +#define arena_palloc JEMALLOC_N(arena_palloc) +#define arena_postfork_child JEMALLOC_N(arena_postfork_child) +#define arena_postfork_parent JEMALLOC_N(arena_postfork_parent) +#define arena_prefork0 JEMALLOC_N(arena_prefork0) +#define arena_prefork1 JEMALLOC_N(arena_prefork1) +#define arena_prefork2 JEMALLOC_N(arena_prefork2) +#define arena_prefork3 JEMALLOC_N(arena_prefork3) +#define arena_prefork4 JEMALLOC_N(arena_prefork4) +#define arena_prefork5 JEMALLOC_N(arena_prefork5) +#define arena_prefork6 JEMALLOC_N(arena_prefork6) +#define arena_prefork7 JEMALLOC_N(arena_prefork7) +#define arena_prefork8 JEMALLOC_N(arena_prefork8) +#define arena_prof_promote JEMALLOC_N(arena_prof_promote) +#define arena_ralloc JEMALLOC_N(arena_ralloc) +#define arena_ralloc_no_move JEMALLOC_N(arena_ralloc_no_move) +#define arena_reset JEMALLOC_N(arena_reset) +#define arena_retain_grow_limit_get_set JEMALLOC_N(arena_retain_grow_limit_get_set) +#define arena_set_extent_hooks JEMALLOC_N(arena_set_extent_hooks) +#define arena_slab_dalloc JEMALLOC_N(arena_slab_dalloc) +#define arena_stats_merge JEMALLOC_N(arena_stats_merge) +#define opt_dirty_decay_ms JEMALLOC_N(opt_dirty_decay_ms) +#define opt_muzzy_decay_ms JEMALLOC_N(opt_muzzy_decay_ms) +#define opt_oversize_threshold JEMALLOC_N(opt_oversize_threshold) +#define opt_percpu_arena JEMALLOC_N(opt_percpu_arena) +#define oversize_threshold JEMALLOC_N(oversize_threshold) +#define percpu_arena_mode_names JEMALLOC_N(percpu_arena_mode_names) +#define background_thread_boot0 JEMALLOC_N(background_thread_boot0) +#define background_thread_boot1 JEMALLOC_N(background_thread_boot1) +#define background_thread_create JEMALLOC_N(background_thread_create) +#define background_thread_ctl_init JEMALLOC_N(background_thread_ctl_init) +#define background_thread_enabled_state JEMALLOC_N(background_thread_enabled_state) +#define background_thread_info JEMALLOC_N(background_thread_info) +#define background_thread_is_started JEMALLOC_N(background_thread_is_started) +#define background_thread_lock JEMALLOC_N(background_thread_lock) +#define background_thread_postfork_child JEMALLOC_N(background_thread_postfork_child) +#define background_thread_postfork_parent JEMALLOC_N(background_thread_postfork_parent) +#define background_thread_prefork0 JEMALLOC_N(background_thread_prefork0) +#define background_thread_prefork1 JEMALLOC_N(background_thread_prefork1) +#define background_thread_stats_read JEMALLOC_N(background_thread_stats_read) +#define background_thread_wakeup_early JEMALLOC_N(background_thread_wakeup_early) +#define background_threads_disable JEMALLOC_N(background_threads_disable) +#define background_threads_enable JEMALLOC_N(background_threads_enable) +#define max_background_threads JEMALLOC_N(max_background_threads) +#define n_background_threads JEMALLOC_N(n_background_threads) +#define opt_background_thread JEMALLOC_N(opt_background_thread) +#define opt_max_background_threads JEMALLOC_N(opt_max_background_threads) +#define b0get JEMALLOC_N(b0get) +#define base_alloc JEMALLOC_N(base_alloc) +#define base_alloc_edata JEMALLOC_N(base_alloc_edata) +#define base_boot JEMALLOC_N(base_boot) +#define base_delete JEMALLOC_N(base_delete) +#define base_ehooks_get JEMALLOC_N(base_ehooks_get) +#define base_ehooks_get_for_metadata JEMALLOC_N(base_ehooks_get_for_metadata) +#define base_extent_hooks_set JEMALLOC_N(base_extent_hooks_set) +#define base_new JEMALLOC_N(base_new) +#define base_postfork_child JEMALLOC_N(base_postfork_child) +#define base_postfork_parent JEMALLOC_N(base_postfork_parent) +#define base_prefork JEMALLOC_N(base_prefork) +#define base_stats_get JEMALLOC_N(base_stats_get) +#define metadata_thp_mode_names JEMALLOC_N(metadata_thp_mode_names) +#define opt_metadata_thp JEMALLOC_N(opt_metadata_thp) +#define bin_init JEMALLOC_N(bin_init) +#define bin_postfork_child JEMALLOC_N(bin_postfork_child) +#define bin_postfork_parent JEMALLOC_N(bin_postfork_parent) +#define bin_prefork JEMALLOC_N(bin_prefork) +#define bin_shard_sizes_boot JEMALLOC_N(bin_shard_sizes_boot) +#define bin_update_shard_size JEMALLOC_N(bin_update_shard_size) +#define bin_info_boot JEMALLOC_N(bin_info_boot) +#define bin_infos JEMALLOC_N(bin_infos) +#define bitmap_info_init JEMALLOC_N(bitmap_info_init) +#define bitmap_init JEMALLOC_N(bitmap_init) +#define bitmap_size JEMALLOC_N(bitmap_size) +#define buf_writer_cb JEMALLOC_N(buf_writer_cb) +#define buf_writer_flush JEMALLOC_N(buf_writer_flush) +#define buf_writer_init JEMALLOC_N(buf_writer_init) +#define buf_writer_pipe JEMALLOC_N(buf_writer_pipe) +#define buf_writer_terminate JEMALLOC_N(buf_writer_terminate) +#define cache_bin_info_compute_alloc JEMALLOC_N(cache_bin_info_compute_alloc) +#define cache_bin_info_init JEMALLOC_N(cache_bin_info_init) +#define cache_bin_init JEMALLOC_N(cache_bin_init) +#define cache_bin_postincrement JEMALLOC_N(cache_bin_postincrement) +#define cache_bin_preincrement JEMALLOC_N(cache_bin_preincrement) +#define cache_bin_still_zero_initialized JEMALLOC_N(cache_bin_still_zero_initialized) +#define ckh_count JEMALLOC_N(ckh_count) +#define ckh_delete JEMALLOC_N(ckh_delete) +#define ckh_insert JEMALLOC_N(ckh_insert) +#define ckh_iter JEMALLOC_N(ckh_iter) +#define ckh_new JEMALLOC_N(ckh_new) +#define ckh_pointer_hash JEMALLOC_N(ckh_pointer_hash) +#define ckh_pointer_keycomp JEMALLOC_N(ckh_pointer_keycomp) +#define ckh_remove JEMALLOC_N(ckh_remove) +#define ckh_search JEMALLOC_N(ckh_search) +#define ckh_string_hash JEMALLOC_N(ckh_string_hash) +#define ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp) +#define counter_accum_init JEMALLOC_N(counter_accum_init) +#define counter_postfork_child JEMALLOC_N(counter_postfork_child) +#define counter_postfork_parent JEMALLOC_N(counter_postfork_parent) +#define counter_prefork JEMALLOC_N(counter_prefork) +#define ctl_boot JEMALLOC_N(ctl_boot) +#define ctl_bymib JEMALLOC_N(ctl_bymib) +#define ctl_bymibname JEMALLOC_N(ctl_bymibname) +#define ctl_byname JEMALLOC_N(ctl_byname) +#define ctl_mibnametomib JEMALLOC_N(ctl_mibnametomib) +#define ctl_mtx_assert_held JEMALLOC_N(ctl_mtx_assert_held) +#define ctl_nametomib JEMALLOC_N(ctl_nametomib) +#define ctl_postfork_child JEMALLOC_N(ctl_postfork_child) +#define ctl_postfork_parent JEMALLOC_N(ctl_postfork_parent) +#define ctl_prefork JEMALLOC_N(ctl_prefork) +#define decay_deadline_init JEMALLOC_N(decay_deadline_init) +#define decay_init JEMALLOC_N(decay_init) +#define decay_maybe_advance_epoch JEMALLOC_N(decay_maybe_advance_epoch) +#define decay_ms_valid JEMALLOC_N(decay_ms_valid) +#define decay_npages_purge_in JEMALLOC_N(decay_npages_purge_in) +#define decay_ns_until_purge JEMALLOC_N(decay_ns_until_purge) +#define decay_reinit JEMALLOC_N(decay_reinit) +#define div_init JEMALLOC_N(div_init) +#define ecache_init JEMALLOC_N(ecache_init) +#define ecache_postfork_child JEMALLOC_N(ecache_postfork_child) +#define ecache_postfork_parent JEMALLOC_N(ecache_postfork_parent) +#define ecache_prefork JEMALLOC_N(ecache_prefork) +#define edata_avail_any JEMALLOC_N(edata_avail_any) +#define edata_avail_empty JEMALLOC_N(edata_avail_empty) +#define edata_avail_first JEMALLOC_N(edata_avail_first) +#define edata_avail_insert JEMALLOC_N(edata_avail_insert) +#define edata_avail_new JEMALLOC_N(edata_avail_new) +#define edata_avail_remove JEMALLOC_N(edata_avail_remove) +#define edata_avail_remove_any JEMALLOC_N(edata_avail_remove_any) +#define edata_avail_remove_first JEMALLOC_N(edata_avail_remove_first) +#define edata_heap_any JEMALLOC_N(edata_heap_any) +#define edata_heap_empty JEMALLOC_N(edata_heap_empty) +#define edata_heap_first JEMALLOC_N(edata_heap_first) +#define edata_heap_insert JEMALLOC_N(edata_heap_insert) +#define edata_heap_new JEMALLOC_N(edata_heap_new) +#define edata_heap_remove JEMALLOC_N(edata_heap_remove) +#define edata_heap_remove_any JEMALLOC_N(edata_heap_remove_any) +#define edata_heap_remove_first JEMALLOC_N(edata_heap_remove_first) +#define edata_cache_fast_disable JEMALLOC_N(edata_cache_fast_disable) +#define edata_cache_fast_get JEMALLOC_N(edata_cache_fast_get) +#define edata_cache_fast_init JEMALLOC_N(edata_cache_fast_init) +#define edata_cache_fast_put JEMALLOC_N(edata_cache_fast_put) +#define edata_cache_get JEMALLOC_N(edata_cache_get) +#define edata_cache_init JEMALLOC_N(edata_cache_init) +#define edata_cache_postfork_child JEMALLOC_N(edata_cache_postfork_child) +#define edata_cache_postfork_parent JEMALLOC_N(edata_cache_postfork_parent) +#define edata_cache_prefork JEMALLOC_N(edata_cache_prefork) +#define edata_cache_put JEMALLOC_N(edata_cache_put) +#define ehooks_default_alloc_impl JEMALLOC_N(ehooks_default_alloc_impl) +#define ehooks_default_commit_impl JEMALLOC_N(ehooks_default_commit_impl) +#define ehooks_default_dalloc_impl JEMALLOC_N(ehooks_default_dalloc_impl) +#define ehooks_default_decommit_impl JEMALLOC_N(ehooks_default_decommit_impl) +#define ehooks_default_destroy_impl JEMALLOC_N(ehooks_default_destroy_impl) +#define ehooks_default_extent_hooks JEMALLOC_N(ehooks_default_extent_hooks) +#define ehooks_default_guard_impl JEMALLOC_N(ehooks_default_guard_impl) +#define ehooks_default_merge JEMALLOC_N(ehooks_default_merge) +#define ehooks_default_merge_impl JEMALLOC_N(ehooks_default_merge_impl) +#define ehooks_default_purge_forced_impl JEMALLOC_N(ehooks_default_purge_forced_impl) +#define ehooks_default_purge_lazy_impl JEMALLOC_N(ehooks_default_purge_lazy_impl) +#define ehooks_default_split_impl JEMALLOC_N(ehooks_default_split_impl) +#define ehooks_default_unguard_impl JEMALLOC_N(ehooks_default_unguard_impl) +#define ehooks_default_zero_impl JEMALLOC_N(ehooks_default_zero_impl) +#define ehooks_init JEMALLOC_N(ehooks_init) +#define emap_deregister_boundary JEMALLOC_N(emap_deregister_boundary) +#define emap_deregister_interior JEMALLOC_N(emap_deregister_interior) +#define emap_do_assert_mapped JEMALLOC_N(emap_do_assert_mapped) +#define emap_do_assert_not_mapped JEMALLOC_N(emap_do_assert_not_mapped) +#define emap_init JEMALLOC_N(emap_init) +#define emap_merge_commit JEMALLOC_N(emap_merge_commit) +#define emap_merge_prepare JEMALLOC_N(emap_merge_prepare) +#define emap_register_boundary JEMALLOC_N(emap_register_boundary) +#define emap_register_interior JEMALLOC_N(emap_register_interior) +#define emap_release_edata JEMALLOC_N(emap_release_edata) +#define emap_remap JEMALLOC_N(emap_remap) +#define emap_split_commit JEMALLOC_N(emap_split_commit) +#define emap_split_prepare JEMALLOC_N(emap_split_prepare) +#define emap_try_acquire_edata_neighbor JEMALLOC_N(emap_try_acquire_edata_neighbor) +#define emap_try_acquire_edata_neighbor_expand JEMALLOC_N(emap_try_acquire_edata_neighbor_expand) +#define emap_update_edata_state JEMALLOC_N(emap_update_edata_state) +#define eset_fit JEMALLOC_N(eset_fit) +#define eset_init JEMALLOC_N(eset_init) +#define eset_insert JEMALLOC_N(eset_insert) +#define eset_nbytes_get JEMALLOC_N(eset_nbytes_get) +#define eset_nextents_get JEMALLOC_N(eset_nextents_get) +#define eset_npages_get JEMALLOC_N(eset_npages_get) +#define eset_remove JEMALLOC_N(eset_remove) +#define exp_grow_init JEMALLOC_N(exp_grow_init) +#define ecache_alloc JEMALLOC_N(ecache_alloc) +#define ecache_alloc_grow JEMALLOC_N(ecache_alloc_grow) +#define ecache_dalloc JEMALLOC_N(ecache_dalloc) +#define ecache_evict JEMALLOC_N(ecache_evict) +#define extent_alloc_wrapper JEMALLOC_N(extent_alloc_wrapper) +#define extent_boot JEMALLOC_N(extent_boot) +#define extent_commit_wrapper JEMALLOC_N(extent_commit_wrapper) +#define extent_commit_zero JEMALLOC_N(extent_commit_zero) +#define extent_dalloc_gap JEMALLOC_N(extent_dalloc_gap) +#define extent_dalloc_wrapper JEMALLOC_N(extent_dalloc_wrapper) +#define extent_decommit_wrapper JEMALLOC_N(extent_decommit_wrapper) +#define extent_destroy_wrapper JEMALLOC_N(extent_destroy_wrapper) +#define extent_gdump_add JEMALLOC_N(extent_gdump_add) +#define extent_merge_wrapper JEMALLOC_N(extent_merge_wrapper) +#define extent_purge_forced_wrapper JEMALLOC_N(extent_purge_forced_wrapper) +#define extent_purge_lazy_wrapper JEMALLOC_N(extent_purge_lazy_wrapper) +#define extent_record JEMALLOC_N(extent_record) +#define extent_sn_next JEMALLOC_N(extent_sn_next) +#define extent_split_wrapper JEMALLOC_N(extent_split_wrapper) +#define opt_lg_extent_max_active_fit JEMALLOC_N(opt_lg_extent_max_active_fit) +#define dss_prec_names JEMALLOC_N(dss_prec_names) +#define extent_alloc_dss JEMALLOC_N(extent_alloc_dss) +#define extent_dss_boot JEMALLOC_N(extent_dss_boot) +#define extent_dss_mergeable JEMALLOC_N(extent_dss_mergeable) +#define extent_dss_prec_get JEMALLOC_N(extent_dss_prec_get) +#define extent_dss_prec_set JEMALLOC_N(extent_dss_prec_set) +#define extent_in_dss JEMALLOC_N(extent_in_dss) +#define opt_dss JEMALLOC_N(opt_dss) +#define extent_alloc_mmap JEMALLOC_N(extent_alloc_mmap) +#define extent_dalloc_mmap JEMALLOC_N(extent_dalloc_mmap) +#define opt_retain JEMALLOC_N(opt_retain) +#define fxp_parse JEMALLOC_N(fxp_parse) +#define fxp_print JEMALLOC_N(fxp_print) +#define opt_lg_san_uaf_align JEMALLOC_N(opt_lg_san_uaf_align) +#define opt_san_guard_large JEMALLOC_N(opt_san_guard_large) +#define opt_san_guard_small JEMALLOC_N(opt_san_guard_small) +#define san_cache_bin_nonfast_mask JEMALLOC_N(san_cache_bin_nonfast_mask) +#define san_check_stashed_ptrs JEMALLOC_N(san_check_stashed_ptrs) +#define san_guard_pages JEMALLOC_N(san_guard_pages) +#define san_init JEMALLOC_N(san_init) +#define san_unguard_pages JEMALLOC_N(san_unguard_pages) +#define san_unguard_pages_pre_destroy JEMALLOC_N(san_unguard_pages_pre_destroy) +#define tsd_san_init JEMALLOC_N(tsd_san_init) +#define san_bump_alloc JEMALLOC_N(san_bump_alloc) +#define hook_boot JEMALLOC_N(hook_boot) +#define hook_install JEMALLOC_N(hook_install) +#define hook_invoke_alloc JEMALLOC_N(hook_invoke_alloc) +#define hook_invoke_dalloc JEMALLOC_N(hook_invoke_dalloc) +#define hook_invoke_expand JEMALLOC_N(hook_invoke_expand) +#define hook_remove JEMALLOC_N(hook_remove) +#define hpa_central_extract JEMALLOC_N(hpa_central_extract) +#define hpa_central_init JEMALLOC_N(hpa_central_init) +#define hpa_shard_destroy JEMALLOC_N(hpa_shard_destroy) +#define hpa_shard_disable JEMALLOC_N(hpa_shard_disable) +#define hpa_shard_do_deferred_work JEMALLOC_N(hpa_shard_do_deferred_work) +#define hpa_shard_init JEMALLOC_N(hpa_shard_init) +#define hpa_shard_postfork_child JEMALLOC_N(hpa_shard_postfork_child) +#define hpa_shard_postfork_parent JEMALLOC_N(hpa_shard_postfork_parent) +#define hpa_shard_prefork3 JEMALLOC_N(hpa_shard_prefork3) +#define hpa_shard_prefork4 JEMALLOC_N(hpa_shard_prefork4) +#define hpa_shard_set_deferral_allowed JEMALLOC_N(hpa_shard_set_deferral_allowed) +#define hpa_shard_stats_accum JEMALLOC_N(hpa_shard_stats_accum) +#define hpa_shard_stats_merge JEMALLOC_N(hpa_shard_stats_merge) +#define hpa_supported JEMALLOC_N(hpa_supported) +#define hpa_hooks_default JEMALLOC_N(hpa_hooks_default) +#define hpdata_age_heap_any JEMALLOC_N(hpdata_age_heap_any) +#define hpdata_age_heap_empty JEMALLOC_N(hpdata_age_heap_empty) +#define hpdata_age_heap_first JEMALLOC_N(hpdata_age_heap_first) +#define hpdata_age_heap_insert JEMALLOC_N(hpdata_age_heap_insert) +#define hpdata_age_heap_new JEMALLOC_N(hpdata_age_heap_new) +#define hpdata_age_heap_remove JEMALLOC_N(hpdata_age_heap_remove) +#define hpdata_age_heap_remove_any JEMALLOC_N(hpdata_age_heap_remove_any) +#define hpdata_age_heap_remove_first JEMALLOC_N(hpdata_age_heap_remove_first) +#define hpdata_dehugify JEMALLOC_N(hpdata_dehugify) +#define hpdata_hugify JEMALLOC_N(hpdata_hugify) +#define hpdata_init JEMALLOC_N(hpdata_init) +#define hpdata_purge_begin JEMALLOC_N(hpdata_purge_begin) +#define hpdata_purge_end JEMALLOC_N(hpdata_purge_end) +#define hpdata_purge_next JEMALLOC_N(hpdata_purge_next) +#define hpdata_reserve_alloc JEMALLOC_N(hpdata_reserve_alloc) +#define hpdata_unreserve JEMALLOC_N(hpdata_unreserve) +#define inspect_extent_util_stats_get JEMALLOC_N(inspect_extent_util_stats_get) +#define inspect_extent_util_stats_verbose_get JEMALLOC_N(inspect_extent_util_stats_verbose_get) +#define large_dalloc JEMALLOC_N(large_dalloc) +#define large_dalloc_finish JEMALLOC_N(large_dalloc_finish) +#define large_dalloc_prep_locked JEMALLOC_N(large_dalloc_prep_locked) +#define large_malloc JEMALLOC_N(large_malloc) +#define large_palloc JEMALLOC_N(large_palloc) +#define large_prof_info_get JEMALLOC_N(large_prof_info_get) +#define large_prof_info_set JEMALLOC_N(large_prof_info_set) +#define large_prof_tctx_reset JEMALLOC_N(large_prof_tctx_reset) +#define large_ralloc JEMALLOC_N(large_ralloc) +#define large_ralloc_no_move JEMALLOC_N(large_ralloc_no_move) +#define large_salloc JEMALLOC_N(large_salloc) +#define log_init_done JEMALLOC_N(log_init_done) +#define log_var_names JEMALLOC_N(log_var_names) +#define log_var_update_state JEMALLOC_N(log_var_update_state) +#define buferror JEMALLOC_N(buferror) +#define malloc_cprintf JEMALLOC_N(malloc_cprintf) +#define malloc_printf JEMALLOC_N(malloc_printf) +#define malloc_snprintf JEMALLOC_N(malloc_snprintf) +#define malloc_strtoumax JEMALLOC_N(malloc_strtoumax) +#define malloc_vcprintf JEMALLOC_N(malloc_vcprintf) +#define malloc_vsnprintf JEMALLOC_N(malloc_vsnprintf) +#define malloc_write JEMALLOC_N(malloc_write) +#define wrtmessage JEMALLOC_N(wrtmessage) +#define malloc_mutex_boot JEMALLOC_N(malloc_mutex_boot) +#define malloc_mutex_init JEMALLOC_N(malloc_mutex_init) +#define malloc_mutex_lock_slow JEMALLOC_N(malloc_mutex_lock_slow) +#define malloc_mutex_postfork_child JEMALLOC_N(malloc_mutex_postfork_child) +#define malloc_mutex_postfork_parent JEMALLOC_N(malloc_mutex_postfork_parent) +#define malloc_mutex_prefork JEMALLOC_N(malloc_mutex_prefork) +#define malloc_mutex_prof_data_reset JEMALLOC_N(malloc_mutex_prof_data_reset) +#define opt_mutex_max_spin JEMALLOC_N(opt_mutex_max_spin) +#define nstime_add JEMALLOC_N(nstime_add) +#define nstime_compare JEMALLOC_N(nstime_compare) +#define nstime_copy JEMALLOC_N(nstime_copy) +#define nstime_divide JEMALLOC_N(nstime_divide) +#define nstime_iadd JEMALLOC_N(nstime_iadd) +#define nstime_idivide JEMALLOC_N(nstime_idivide) +#define nstime_imultiply JEMALLOC_N(nstime_imultiply) +#define nstime_init JEMALLOC_N(nstime_init) +#define nstime_init2 JEMALLOC_N(nstime_init2) +#define nstime_init_update JEMALLOC_N(nstime_init_update) +#define nstime_isubtract JEMALLOC_N(nstime_isubtract) +#define nstime_monotonic JEMALLOC_N(nstime_monotonic) +#define nstime_msec JEMALLOC_N(nstime_msec) +#define nstime_ns JEMALLOC_N(nstime_ns) +#define nstime_ns_since JEMALLOC_N(nstime_ns_since) +#define nstime_nsec JEMALLOC_N(nstime_nsec) +#define nstime_prof_init_update JEMALLOC_N(nstime_prof_init_update) +#define nstime_prof_update JEMALLOC_N(nstime_prof_update) +#define nstime_sec JEMALLOC_N(nstime_sec) +#define nstime_subtract JEMALLOC_N(nstime_subtract) +#define nstime_update JEMALLOC_N(nstime_update) +#define opt_prof_time_res JEMALLOC_N(opt_prof_time_res) +#define prof_time_res_mode_names JEMALLOC_N(prof_time_res_mode_names) +#define pa_alloc JEMALLOC_N(pa_alloc) +#define pa_central_init JEMALLOC_N(pa_central_init) +#define pa_dalloc JEMALLOC_N(pa_dalloc) +#define pa_decay_ms_get JEMALLOC_N(pa_decay_ms_get) +#define pa_decay_ms_set JEMALLOC_N(pa_decay_ms_set) +#define pa_expand JEMALLOC_N(pa_expand) +#define pa_shard_destroy JEMALLOC_N(pa_shard_destroy) +#define pa_shard_disable_hpa JEMALLOC_N(pa_shard_disable_hpa) +#define pa_shard_do_deferred_work JEMALLOC_N(pa_shard_do_deferred_work) +#define pa_shard_enable_hpa JEMALLOC_N(pa_shard_enable_hpa) +#define pa_shard_init JEMALLOC_N(pa_shard_init) +#define pa_shard_reset JEMALLOC_N(pa_shard_reset) +#define pa_shard_retain_grow_limit_get_set JEMALLOC_N(pa_shard_retain_grow_limit_get_set) +#define pa_shard_set_deferral_allowed JEMALLOC_N(pa_shard_set_deferral_allowed) +#define pa_shard_time_until_deferred_work JEMALLOC_N(pa_shard_time_until_deferred_work) +#define pa_shrink JEMALLOC_N(pa_shrink) +#define pa_shard_basic_stats_merge JEMALLOC_N(pa_shard_basic_stats_merge) +#define pa_shard_mtx_stats_read JEMALLOC_N(pa_shard_mtx_stats_read) +#define pa_shard_postfork_child JEMALLOC_N(pa_shard_postfork_child) +#define pa_shard_postfork_parent JEMALLOC_N(pa_shard_postfork_parent) +#define pa_shard_prefork0 JEMALLOC_N(pa_shard_prefork0) +#define pa_shard_prefork2 JEMALLOC_N(pa_shard_prefork2) +#define pa_shard_prefork3 JEMALLOC_N(pa_shard_prefork3) +#define pa_shard_prefork4 JEMALLOC_N(pa_shard_prefork4) +#define pa_shard_prefork5 JEMALLOC_N(pa_shard_prefork5) +#define pa_shard_stats_merge JEMALLOC_N(pa_shard_stats_merge) +#define pai_alloc_batch_default JEMALLOC_N(pai_alloc_batch_default) +#define pai_dalloc_batch_default JEMALLOC_N(pai_dalloc_batch_default) +#define pac_decay_all JEMALLOC_N(pac_decay_all) +#define pac_decay_ms_get JEMALLOC_N(pac_decay_ms_get) +#define pac_decay_ms_set JEMALLOC_N(pac_decay_ms_set) +#define pac_destroy JEMALLOC_N(pac_destroy) +#define pac_init JEMALLOC_N(pac_init) +#define pac_maybe_decay_purge JEMALLOC_N(pac_maybe_decay_purge) +#define pac_reset JEMALLOC_N(pac_reset) +#define pac_retain_grow_limit_get_set JEMALLOC_N(pac_retain_grow_limit_get_set) +#define init_system_thp_mode JEMALLOC_N(init_system_thp_mode) +#define opt_thp JEMALLOC_N(opt_thp) +#define pages_boot JEMALLOC_N(pages_boot) +#define pages_commit JEMALLOC_N(pages_commit) +#define pages_decommit JEMALLOC_N(pages_decommit) +#define pages_dodump JEMALLOC_N(pages_dodump) +#define pages_dontdump JEMALLOC_N(pages_dontdump) +#define pages_huge JEMALLOC_N(pages_huge) +#define pages_map JEMALLOC_N(pages_map) +#define pages_mark_guards JEMALLOC_N(pages_mark_guards) +#define pages_nohuge JEMALLOC_N(pages_nohuge) +#define pages_purge_forced JEMALLOC_N(pages_purge_forced) +#define pages_purge_lazy JEMALLOC_N(pages_purge_lazy) +#define pages_set_thp_state JEMALLOC_N(pages_set_thp_state) +#define pages_unmap JEMALLOC_N(pages_unmap) +#define pages_unmark_guards JEMALLOC_N(pages_unmark_guards) +#define thp_mode_names JEMALLOC_N(thp_mode_names) +#define peak_alloc_event_handler JEMALLOC_N(peak_alloc_event_handler) +#define peak_alloc_new_event_wait JEMALLOC_N(peak_alloc_new_event_wait) +#define peak_alloc_postponed_event_wait JEMALLOC_N(peak_alloc_postponed_event_wait) +#define peak_dalloc_event_handler JEMALLOC_N(peak_dalloc_event_handler) +#define peak_dalloc_new_event_wait JEMALLOC_N(peak_dalloc_new_event_wait) +#define peak_dalloc_postponed_event_wait JEMALLOC_N(peak_dalloc_postponed_event_wait) +#define peak_event_max JEMALLOC_N(peak_event_max) +#define peak_event_update JEMALLOC_N(peak_event_update) +#define peak_event_zero JEMALLOC_N(peak_event_zero) +#define lg_prof_sample JEMALLOC_N(lg_prof_sample) +#define opt_lg_prof_interval JEMALLOC_N(opt_lg_prof_interval) +#define opt_lg_prof_sample JEMALLOC_N(opt_lg_prof_sample) +#define opt_prof JEMALLOC_N(opt_prof) +#define opt_prof_accum JEMALLOC_N(opt_prof_accum) +#define opt_prof_active JEMALLOC_N(opt_prof_active) +#define opt_prof_final JEMALLOC_N(opt_prof_final) +#define opt_prof_gdump JEMALLOC_N(opt_prof_gdump) +#define opt_prof_leak JEMALLOC_N(opt_prof_leak) +#define opt_prof_leak_error JEMALLOC_N(opt_prof_leak_error) +#define opt_prof_prefix JEMALLOC_N(opt_prof_prefix) +#define opt_prof_sys_thread_name JEMALLOC_N(opt_prof_sys_thread_name) +#define opt_prof_thread_active_init JEMALLOC_N(opt_prof_thread_active_init) +#define opt_prof_unbias JEMALLOC_N(opt_prof_unbias) +#define prof_active_get JEMALLOC_N(prof_active_get) +#define prof_active_set JEMALLOC_N(prof_active_set) +#define prof_active_state JEMALLOC_N(prof_active_state) +#define prof_alloc_rollback JEMALLOC_N(prof_alloc_rollback) +#define prof_backtrace_hook JEMALLOC_N(prof_backtrace_hook) +#define prof_backtrace_hook_get JEMALLOC_N(prof_backtrace_hook_get) +#define prof_backtrace_hook_set JEMALLOC_N(prof_backtrace_hook_set) +#define prof_boot0 JEMALLOC_N(prof_boot0) +#define prof_boot1 JEMALLOC_N(prof_boot1) +#define prof_boot2 JEMALLOC_N(prof_boot2) +#define prof_booted JEMALLOC_N(prof_booted) +#define prof_dump_hook JEMALLOC_N(prof_dump_hook) +#define prof_dump_hook_get JEMALLOC_N(prof_dump_hook_get) +#define prof_dump_hook_set JEMALLOC_N(prof_dump_hook_set) +#define prof_free_sampled_object JEMALLOC_N(prof_free_sampled_object) +#define prof_gdump JEMALLOC_N(prof_gdump) +#define prof_gdump_get JEMALLOC_N(prof_gdump_get) +#define prof_gdump_set JEMALLOC_N(prof_gdump_set) +#define prof_gdump_val JEMALLOC_N(prof_gdump_val) +#define prof_idump JEMALLOC_N(prof_idump) +#define prof_interval JEMALLOC_N(prof_interval) +#define prof_malloc_sample_object JEMALLOC_N(prof_malloc_sample_object) +#define prof_mdump JEMALLOC_N(prof_mdump) +#define prof_postfork_child JEMALLOC_N(prof_postfork_child) +#define prof_postfork_parent JEMALLOC_N(prof_postfork_parent) +#define prof_prefork0 JEMALLOC_N(prof_prefork0) +#define prof_prefork1 JEMALLOC_N(prof_prefork1) +#define prof_sample_event_handler JEMALLOC_N(prof_sample_event_handler) +#define prof_sample_new_event_wait JEMALLOC_N(prof_sample_new_event_wait) +#define prof_sample_postponed_event_wait JEMALLOC_N(prof_sample_postponed_event_wait) +#define prof_tctx_create JEMALLOC_N(prof_tctx_create) +#define prof_tdata_cleanup JEMALLOC_N(prof_tdata_cleanup) +#define prof_tdata_init JEMALLOC_N(prof_tdata_init) +#define prof_tdata_reinit JEMALLOC_N(prof_tdata_reinit) +#define prof_thread_active_get JEMALLOC_N(prof_thread_active_get) +#define prof_thread_active_init_get JEMALLOC_N(prof_thread_active_init_get) +#define prof_thread_active_init_set JEMALLOC_N(prof_thread_active_init_set) +#define prof_thread_active_set JEMALLOC_N(prof_thread_active_set) +#define prof_thread_name_get JEMALLOC_N(prof_thread_name_get) +#define prof_thread_name_set JEMALLOC_N(prof_thread_name_set) +#define bt2gctx_mtx JEMALLOC_N(bt2gctx_mtx) +#define gctx_locks JEMALLOC_N(gctx_locks) +#define prof_bt_count JEMALLOC_N(prof_bt_count) +#define prof_bt_hash JEMALLOC_N(prof_bt_hash) +#define prof_bt_keycomp JEMALLOC_N(prof_bt_keycomp) +#define prof_cnt_all JEMALLOC_N(prof_cnt_all) +#define prof_data_init JEMALLOC_N(prof_data_init) +#define prof_dump_impl JEMALLOC_N(prof_dump_impl) +#define prof_dump_mtx JEMALLOC_N(prof_dump_mtx) +#define prof_lookup JEMALLOC_N(prof_lookup) +#define prof_reset JEMALLOC_N(prof_reset) +#define prof_shifted_unbiased_cnt JEMALLOC_N(prof_shifted_unbiased_cnt) +#define prof_tctx_try_destroy JEMALLOC_N(prof_tctx_try_destroy) +#define prof_tdata_count JEMALLOC_N(prof_tdata_count) +#define prof_tdata_detach JEMALLOC_N(prof_tdata_detach) +#define prof_tdata_init_impl JEMALLOC_N(prof_tdata_init_impl) +#define prof_thread_name_alloc JEMALLOC_N(prof_thread_name_alloc) +#define prof_thread_name_set_impl JEMALLOC_N(prof_thread_name_set_impl) +#define prof_unbias_map_init JEMALLOC_N(prof_unbias_map_init) +#define prof_unbiased_sz JEMALLOC_N(prof_unbiased_sz) +#define tdata_locks JEMALLOC_N(tdata_locks) +#define tdatas_mtx JEMALLOC_N(tdatas_mtx) +#define log_mtx JEMALLOC_N(log_mtx) +#define opt_prof_log JEMALLOC_N(opt_prof_log) +#define prof_log_alloc_count JEMALLOC_N(prof_log_alloc_count) +#define prof_log_bt_count JEMALLOC_N(prof_log_bt_count) +#define prof_log_dummy_set JEMALLOC_N(prof_log_dummy_set) +#define prof_log_init JEMALLOC_N(prof_log_init) +#define prof_log_is_logging JEMALLOC_N(prof_log_is_logging) +#define prof_log_rep_check JEMALLOC_N(prof_log_rep_check) +#define prof_log_start JEMALLOC_N(prof_log_start) +#define prof_log_stop JEMALLOC_N(prof_log_stop) +#define prof_log_thr_count JEMALLOC_N(prof_log_thr_count) +#define prof_logging_state JEMALLOC_N(prof_logging_state) +#define prof_try_log JEMALLOC_N(prof_try_log) +#define edata_prof_recent_alloc_get_no_lock_test JEMALLOC_N(edata_prof_recent_alloc_get_no_lock_test) +#define edata_prof_recent_alloc_init JEMALLOC_N(edata_prof_recent_alloc_init) +#define opt_prof_recent_alloc_max JEMALLOC_N(opt_prof_recent_alloc_max) +#define prof_recent_alloc JEMALLOC_N(prof_recent_alloc) +#define prof_recent_alloc_dump JEMALLOC_N(prof_recent_alloc_dump) +#define prof_recent_alloc_edata_get_no_lock_test JEMALLOC_N(prof_recent_alloc_edata_get_no_lock_test) +#define prof_recent_alloc_list JEMALLOC_N(prof_recent_alloc_list) +#define prof_recent_alloc_max_ctl_read JEMALLOC_N(prof_recent_alloc_max_ctl_read) +#define prof_recent_alloc_max_ctl_write JEMALLOC_N(prof_recent_alloc_max_ctl_write) +#define prof_recent_alloc_mtx JEMALLOC_N(prof_recent_alloc_mtx) +#define prof_recent_alloc_prepare JEMALLOC_N(prof_recent_alloc_prepare) +#define prof_recent_alloc_reset JEMALLOC_N(prof_recent_alloc_reset) +#define prof_recent_dump_mtx JEMALLOC_N(prof_recent_dump_mtx) +#define prof_recent_init JEMALLOC_N(prof_recent_init) +#define opt_prof_stats JEMALLOC_N(opt_prof_stats) +#define prof_stats_dec JEMALLOC_N(prof_stats_dec) +#define prof_stats_get_accum JEMALLOC_N(prof_stats_get_accum) +#define prof_stats_get_live JEMALLOC_N(prof_stats_get_live) +#define prof_stats_inc JEMALLOC_N(prof_stats_inc) +#define prof_stats_mtx JEMALLOC_N(prof_stats_mtx) +#define bt_init JEMALLOC_N(bt_init) +#define prof_backtrace JEMALLOC_N(prof_backtrace) +#define prof_base JEMALLOC_N(prof_base) +#define prof_do_mock JEMALLOC_N(prof_do_mock) +#define prof_dump_filename_mtx JEMALLOC_N(prof_dump_filename_mtx) +#define prof_dump_open_file JEMALLOC_N(prof_dump_open_file) +#define prof_dump_open_maps JEMALLOC_N(prof_dump_open_maps) +#define prof_dump_write_file JEMALLOC_N(prof_dump_write_file) +#define prof_fdump_impl JEMALLOC_N(prof_fdump_impl) +#define prof_gdump_impl JEMALLOC_N(prof_gdump_impl) +#define prof_get_default_filename JEMALLOC_N(prof_get_default_filename) +#define prof_getpid JEMALLOC_N(prof_getpid) +#define prof_hooks_init JEMALLOC_N(prof_hooks_init) +#define prof_idump_impl JEMALLOC_N(prof_idump_impl) +#define prof_mdump_impl JEMALLOC_N(prof_mdump_impl) +#define prof_prefix_set JEMALLOC_N(prof_prefix_set) +#define prof_sys_thread_name_fetch JEMALLOC_N(prof_sys_thread_name_fetch) +#define prof_sys_thread_name_read JEMALLOC_N(prof_sys_thread_name_read) +#define prof_unwind_init JEMALLOC_N(prof_unwind_init) +#define psset_init JEMALLOC_N(psset_init) +#define psset_insert JEMALLOC_N(psset_insert) +#define psset_pick_alloc JEMALLOC_N(psset_pick_alloc) +#define psset_pick_hugify JEMALLOC_N(psset_pick_hugify) +#define psset_pick_purge JEMALLOC_N(psset_pick_purge) +#define psset_remove JEMALLOC_N(psset_remove) +#define psset_stats_accum JEMALLOC_N(psset_stats_accum) +#define psset_update_begin JEMALLOC_N(psset_update_begin) +#define psset_update_end JEMALLOC_N(psset_update_end) +#define rtree_ctx_data_init JEMALLOC_N(rtree_ctx_data_init) +#define rtree_leaf_elm_lookup_hard JEMALLOC_N(rtree_leaf_elm_lookup_hard) +#define rtree_new JEMALLOC_N(rtree_new) +#define safety_check_fail JEMALLOC_N(safety_check_fail) +#define safety_check_fail_sized_dealloc JEMALLOC_N(safety_check_fail_sized_dealloc) +#define safety_check_set_abort JEMALLOC_N(safety_check_set_abort) +#define reg_size_compute JEMALLOC_N(reg_size_compute) +#define sc_boot JEMALLOC_N(sc_boot) +#define sc_data_init JEMALLOC_N(sc_data_init) +#define sc_data_update_slab_size JEMALLOC_N(sc_data_update_slab_size) +#define sec_disable JEMALLOC_N(sec_disable) +#define sec_flush JEMALLOC_N(sec_flush) +#define sec_init JEMALLOC_N(sec_init) +#define sec_mutex_stats_read JEMALLOC_N(sec_mutex_stats_read) +#define sec_postfork_child JEMALLOC_N(sec_postfork_child) +#define sec_postfork_parent JEMALLOC_N(sec_postfork_parent) +#define sec_prefork2 JEMALLOC_N(sec_prefork2) +#define sec_stats_merge JEMALLOC_N(sec_stats_merge) +#define arena_mutex_names JEMALLOC_N(arena_mutex_names) +#define global_mutex_names JEMALLOC_N(global_mutex_names) +#define opt_stats_interval JEMALLOC_N(opt_stats_interval) +#define opt_stats_interval_opts JEMALLOC_N(opt_stats_interval_opts) +#define opt_stats_print JEMALLOC_N(opt_stats_print) +#define opt_stats_print_opts JEMALLOC_N(opt_stats_print_opts) +#define stats_boot JEMALLOC_N(stats_boot) +#define stats_interval_event_handler JEMALLOC_N(stats_interval_event_handler) +#define stats_interval_new_event_wait JEMALLOC_N(stats_interval_new_event_wait) +#define stats_interval_postponed_event_wait JEMALLOC_N(stats_interval_postponed_event_wait) +#define stats_postfork_child JEMALLOC_N(stats_postfork_child) +#define stats_postfork_parent JEMALLOC_N(stats_postfork_parent) +#define stats_prefork JEMALLOC_N(stats_prefork) +#define stats_print JEMALLOC_N(stats_print) +#define sz_boot JEMALLOC_N(sz_boot) +#define sz_index2size_tab JEMALLOC_N(sz_index2size_tab) +#define sz_large_pad JEMALLOC_N(sz_large_pad) +#define sz_pind2sz_tab JEMALLOC_N(sz_pind2sz_tab) +#define sz_psz_quantize_ceil JEMALLOC_N(sz_psz_quantize_ceil) +#define sz_psz_quantize_floor JEMALLOC_N(sz_psz_quantize_floor) +#define sz_size2index_tab JEMALLOC_N(sz_size2index_tab) +#define nhbins JEMALLOC_N(nhbins) +#define opt_lg_tcache_flush_large_div JEMALLOC_N(opt_lg_tcache_flush_large_div) +#define opt_lg_tcache_flush_small_div JEMALLOC_N(opt_lg_tcache_flush_small_div) +#define opt_lg_tcache_nslots_mul JEMALLOC_N(opt_lg_tcache_nslots_mul) +#define opt_tcache JEMALLOC_N(opt_tcache) +#define opt_tcache_gc_delay_bytes JEMALLOC_N(opt_tcache_gc_delay_bytes) +#define opt_tcache_gc_incr_bytes JEMALLOC_N(opt_tcache_gc_incr_bytes) +#define opt_tcache_max JEMALLOC_N(opt_tcache_max) +#define opt_tcache_nslots_large JEMALLOC_N(opt_tcache_nslots_large) +#define opt_tcache_nslots_small_max JEMALLOC_N(opt_tcache_nslots_small_max) +#define opt_tcache_nslots_small_min JEMALLOC_N(opt_tcache_nslots_small_min) +#define tcache_alloc_small_hard JEMALLOC_N(tcache_alloc_small_hard) +#define tcache_arena_associate JEMALLOC_N(tcache_arena_associate) +#define tcache_arena_reassociate JEMALLOC_N(tcache_arena_reassociate) +#define tcache_assert_initialized JEMALLOC_N(tcache_assert_initialized) +#define tcache_bin_flush_large JEMALLOC_N(tcache_bin_flush_large) +#define tcache_bin_flush_small JEMALLOC_N(tcache_bin_flush_small) +#define tcache_bin_flush_stashed JEMALLOC_N(tcache_bin_flush_stashed) +#define tcache_bin_info JEMALLOC_N(tcache_bin_info) +#define tcache_boot JEMALLOC_N(tcache_boot) +#define tcache_cleanup JEMALLOC_N(tcache_cleanup) +#define tcache_create_explicit JEMALLOC_N(tcache_create_explicit) +#define tcache_flush JEMALLOC_N(tcache_flush) +#define tcache_gc_dalloc_event_handler JEMALLOC_N(tcache_gc_dalloc_event_handler) +#define tcache_gc_dalloc_new_event_wait JEMALLOC_N(tcache_gc_dalloc_new_event_wait) +#define tcache_gc_dalloc_postponed_event_wait JEMALLOC_N(tcache_gc_dalloc_postponed_event_wait) +#define tcache_gc_event_handler JEMALLOC_N(tcache_gc_event_handler) +#define tcache_gc_new_event_wait JEMALLOC_N(tcache_gc_new_event_wait) +#define tcache_gc_postponed_event_wait JEMALLOC_N(tcache_gc_postponed_event_wait) +#define tcache_maxclass JEMALLOC_N(tcache_maxclass) +#define tcache_postfork_child JEMALLOC_N(tcache_postfork_child) +#define tcache_postfork_parent JEMALLOC_N(tcache_postfork_parent) +#define tcache_prefork JEMALLOC_N(tcache_prefork) +#define tcache_salloc JEMALLOC_N(tcache_salloc) +#define tcache_stats_merge JEMALLOC_N(tcache_stats_merge) +#define tcaches JEMALLOC_N(tcaches) +#define tcaches_create JEMALLOC_N(tcaches_create) +#define tcaches_destroy JEMALLOC_N(tcaches_destroy) +#define tcaches_flush JEMALLOC_N(tcaches_flush) +#define tsd_tcache_data_init JEMALLOC_N(tsd_tcache_data_init) +#define tsd_tcache_enabled_data_init JEMALLOC_N(tsd_tcache_enabled_data_init) +#define test_hooks_arena_new_hook JEMALLOC_N(test_hooks_arena_new_hook) +#define test_hooks_libc_hook JEMALLOC_N(test_hooks_libc_hook) +#define te_assert_invariants_debug JEMALLOC_N(te_assert_invariants_debug) +#define te_event_trigger JEMALLOC_N(te_event_trigger) +#define te_recompute_fast_threshold JEMALLOC_N(te_recompute_fast_threshold) +#define tsd_te_init JEMALLOC_N(tsd_te_init) +#define ticker_geom_table JEMALLOC_N(ticker_geom_table) +#define malloc_tsd_boot0 JEMALLOC_N(malloc_tsd_boot0) +#define malloc_tsd_boot1 JEMALLOC_N(malloc_tsd_boot1) +#define malloc_tsd_dalloc JEMALLOC_N(malloc_tsd_dalloc) +#define malloc_tsd_malloc JEMALLOC_N(malloc_tsd_malloc) +#define tsd_boot_wrapper JEMALLOC_N(tsd_boot_wrapper) +#define tsd_booted JEMALLOC_N(tsd_booted) +#define tsd_cleanup JEMALLOC_N(tsd_cleanup) +#define tsd_fetch_slow JEMALLOC_N(tsd_fetch_slow) +#define tsd_global_slow JEMALLOC_N(tsd_global_slow) +#define tsd_global_slow_dec JEMALLOC_N(tsd_global_slow_dec) +#define tsd_global_slow_inc JEMALLOC_N(tsd_global_slow_inc) +#define tsd_init_check_recursion JEMALLOC_N(tsd_init_check_recursion) +#define tsd_init_finish JEMALLOC_N(tsd_init_finish) +#define tsd_init_head JEMALLOC_N(tsd_init_head) +#define tsd_postfork_child JEMALLOC_N(tsd_postfork_child) +#define tsd_postfork_parent JEMALLOC_N(tsd_postfork_parent) +#define tsd_prefork JEMALLOC_N(tsd_prefork) +#define tsd_slow_update JEMALLOC_N(tsd_slow_update) +#define tsd_state_set JEMALLOC_N(tsd_state_set) +#define tsd_tsd JEMALLOC_N(tsd_tsd) +#define witness_depth_error JEMALLOC_N(witness_depth_error) +#define witness_init JEMALLOC_N(witness_init) +#define witness_lock_error JEMALLOC_N(witness_lock_error) +#define witness_not_owner_error JEMALLOC_N(witness_not_owner_error) +#define witness_owner_error JEMALLOC_N(witness_owner_error) +#define witness_postfork_child JEMALLOC_N(witness_postfork_child) +#define witness_postfork_parent JEMALLOC_N(witness_postfork_parent) +#define witness_prefork JEMALLOC_N(witness_prefork) +#define witnesses_cleanup JEMALLOC_N(witnesses_cleanup) +#define zone_register JEMALLOC_N(zone_register) + +// DuckDB: added these so we can pass "exported_symbols_check.py" +#define JE_MALLOC_CONF_BUFFER JEMALLOC_N(JE_MALLOC_CONF_BUFFER) +#define arena_name_get JEMALLOC_N(arena_name_get) +#define arena_name_set JEMALLOC_N(arena_name_set) +#define b0_alloc_tcache_stack JEMALLOC_N(b0_alloc_tcache_stack) +#define b0_dalloc_tcache_stack JEMALLOC_N(b0_dalloc_tcache_stack) +#define base_alloc_rtree JEMALLOC_N(base_alloc_rtree) +#define cache_bin_stack_use_thp JEMALLOC_N(cache_bin_stack_use_thp) +#define disabled_bin JEMALLOC_N(disabled_bin) +#define global_do_not_change_tcache_maxclass JEMALLOC_N(global_do_not_change_tcache_maxclass) +#define global_do_not_change_tcache_nbins JEMALLOC_N(global_do_not_change_tcache_nbins) +#define invalid_conf_abort JEMALLOC_N(invalid_conf_abort) +#define je_free_aligned_sized JEMALLOC_N(je_free_aligned_sized) +#define je_free_sized JEMALLOC_N(je_free_sized) +#define _malloc_thread_cleanup JEMALLOC_N(_malloc_thread_cleanup) +#define _malloc_tsd_cleanup_register JEMALLOC_N(_malloc_tsd_cleanup_register) +#define multi_setting_parse_next JEMALLOC_N(multi_setting_parse_next) +#define opt_calloc_madvise_threshold JEMALLOC_N(opt_calloc_madvise_threshold) +#define opt_debug_double_free_max_scan JEMALLOC_N(opt_debug_double_free_max_scan) +#define opt_malloc_conf_env_var JEMALLOC_N(opt_malloc_conf_env_var) +#define opt_malloc_conf_symlink JEMALLOC_N(opt_malloc_conf_symlink) +#define opt_prof_bt_max JEMALLOC_N(opt_prof_bt_max) +#define opt_prof_pid_namespace JEMALLOC_N(opt_prof_pid_namespace) +#define os_page JEMALLOC_N(os_page) +#define pa_shard_nactive JEMALLOC_N(pa_shard_nactive) +#define pa_shard_ndirty JEMALLOC_N(pa_shard_ndirty) +#define pa_shard_nmuzzy JEMALLOC_N(pa_shard_nmuzzy) +#define prof_sample_free_hook_get JEMALLOC_N(prof_sample_free_hook_get) +#define prof_sample_free_hook_set JEMALLOC_N(prof_sample_free_hook_set) +#define prof_sample_hook_get JEMALLOC_N(prof_sample_hook_get) +#define prof_sample_hook_set JEMALLOC_N(prof_sample_hook_set) +#define pthread_create_wrapper JEMALLOC_N(pthread_create_wrapper) +#define tcache_bin_ncached_max_read JEMALLOC_N(tcache_bin_ncached_max_read) +#define tcache_bins_ncached_max_write JEMALLOC_N(tcache_bins_ncached_max_write) +#define tcache_enabled_set JEMALLOC_N(tcache_enabled_set) +#define thread_tcache_max_set JEMALLOC_N(thread_tcache_max_set) +#define tsd_tls JEMALLOC_N(tsd_tls) diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prng.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prng.h index 5e71df8c058..81060d320b6 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prng.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prng.h @@ -1,6 +1,7 @@ #ifndef JEMALLOC_INTERNAL_PRNG_H #define JEMALLOC_INTERNAL_PRNG_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/bit_util.h" /* @@ -31,8 +32,6 @@ #define PRNG_A_64 UINT64_C(6364136223846793005) #define PRNG_C_64 UINT64_C(1442695040888963407) -namespace duckdb_jemalloc { - JEMALLOC_ALWAYS_INLINE uint32_t prng_state_next_u32(uint32_t state) { return (state * PRNG_A_32) + PRNG_C_32; @@ -167,6 +166,4 @@ prng_range_zu(size_t *state, size_t range) { return ret; } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PRNG_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_data.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_data.h index f0a0caf80c9..43e8d7e7058 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_data.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_data.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_PROF_DATA_H #define JEMALLOC_INTERNAL_PROF_DATA_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/mutex.h" -namespace duckdb_jemalloc { - extern malloc_mutex_t bt2gctx_mtx; extern malloc_mutex_t tdatas_mtx; extern malloc_mutex_t prof_dump_mtx; @@ -20,9 +19,8 @@ bool prof_bt_keycomp(const void *k1, const void *k2); bool prof_data_init(tsd_t *tsd); prof_tctx_t *prof_lookup(tsd_t *tsd, prof_bt_t *bt); -char *prof_thread_name_alloc(tsd_t *tsd, const char *thread_name); int prof_thread_name_set_impl(tsd_t *tsd, const char *thread_name); -void prof_unbias_map_init(); +void prof_unbias_map_init(void); void prof_dump_impl(tsd_t *tsd, write_cb_t *prof_dump_write, void *cbopaque, prof_tdata_t *tdata, bool leakcheck); prof_tdata_t * prof_tdata_init_impl(tsd_t *tsd, uint64_t thr_uid, @@ -36,6 +34,4 @@ size_t prof_tdata_count(void); size_t prof_bt_count(void); void prof_cnt_all(prof_cnt_t *cnt_all); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PROF_DATA_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_externs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_externs.h index a73ada0c507..952ace7db0f 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_externs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_externs.h @@ -1,14 +1,15 @@ #ifndef JEMALLOC_INTERNAL_PROF_EXTERNS_H #define JEMALLOC_INTERNAL_PROF_EXTERNS_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/base.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/prof_hook.h" -namespace duckdb_jemalloc { - extern bool opt_prof; extern bool opt_prof_active; extern bool opt_prof_thread_active_init; +extern unsigned opt_prof_bt_max; extern size_t opt_lg_prof_sample; /* Mean bytes between samples. */ extern ssize_t opt_lg_prof_interval; /* lg(prof_interval). */ extern bool opt_prof_gdump; /* High-water memory dumping. */ @@ -25,6 +26,9 @@ extern char opt_prof_prefix[ 1]; extern bool opt_prof_unbias; +/* Include pid namespace in profile file names. */ +extern bool opt_prof_pid_namespace; + /* For recording recent allocations */ extern ssize_t opt_prof_recent_alloc_max; @@ -52,10 +56,16 @@ extern size_t lg_prof_sample; extern bool prof_booted; void prof_backtrace_hook_set(prof_backtrace_hook_t hook); -prof_backtrace_hook_t prof_backtrace_hook_get(); +prof_backtrace_hook_t prof_backtrace_hook_get(void); void prof_dump_hook_set(prof_dump_hook_t hook); -prof_dump_hook_t prof_dump_hook_get(); +prof_dump_hook_t prof_dump_hook_get(void); + +void prof_sample_hook_set(prof_sample_hook_t hook); +prof_sample_hook_t prof_sample_hook_get(void); + +void prof_sample_free_hook_set(prof_sample_free_hook_t hook); +prof_sample_free_hook_t prof_sample_free_hook_get(void); /* Functions only accessed in prof_inlines.h */ prof_tdata_t *prof_tdata_init(tsd_t *tsd); @@ -64,7 +74,8 @@ prof_tdata_t *prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata); void prof_alloc_rollback(tsd_t *tsd, prof_tctx_t *tctx); void prof_malloc_sample_object(tsd_t *tsd, const void *ptr, size_t size, size_t usize, prof_tctx_t *tctx); -void prof_free_sampled_object(tsd_t *tsd, size_t usize, prof_info_t *prof_info); +void prof_free_sampled_object(tsd_t *tsd, const void *ptr, size_t usize, + prof_info_t *prof_info); prof_tctx_t *prof_tctx_create(tsd_t *tsd); void prof_idump(tsdn_t *tsdn); bool prof_mdump(tsd_t *tsd, const char *filename); @@ -94,6 +105,4 @@ uint64_t prof_sample_new_event_wait(tsd_t *tsd); uint64_t prof_sample_postponed_event_wait(tsd_t *tsd); void prof_sample_event_handler(tsd_t *tsd, uint64_t elapsed); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PROF_EXTERNS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_hook.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_hook.h index e39466d4dcb..3c5ff8bf62f 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_hook.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_hook.h @@ -1,7 +1,7 @@ #ifndef JEMALLOC_INTERNAL_PROF_HOOK_H #define JEMALLOC_INTERNAL_PROF_HOOK_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" /* * The hooks types of which are declared in this file are experimental and @@ -20,6 +20,10 @@ typedef void (*prof_backtrace_hook_t)(void **, unsigned *, unsigned); */ typedef void (*prof_dump_hook_t)(const char *filename); -} // namespace duckdb_jemalloc +/* ptr, size, backtrace vector, backtrace vector length */ +typedef void (*prof_sample_hook_t)(const void *, size_t, void **, unsigned); + +/* ptr, size */ +typedef void (*prof_sample_free_hook_t)(const void *, size_t); #endif /* JEMALLOC_INTERNAL_PROF_HOOK_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_inlines.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_inlines.h index 0a6b3d1f513..75300ee4058 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_inlines.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_inlines.h @@ -1,14 +1,17 @@ #ifndef JEMALLOC_INTERNAL_PROF_INLINES_H #define JEMALLOC_INTERNAL_PROF_INLINES_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_inlines_b.h" +#include "jemalloc/internal/jemalloc_internal_inlines_c.h" +#include "jemalloc/internal/prof_externs.h" +#include "jemalloc/internal/prof_structs.h" #include "jemalloc/internal/safety_check.h" #include "jemalloc/internal/sz.h" #include "jemalloc/internal/thread_event.h" -namespace duckdb_jemalloc { - JEMALLOC_ALWAYS_INLINE void -prof_active_assert() { +prof_active_assert(void) { cassert(config_prof); /* * If opt_prof is off, then prof_active must always be off, regardless @@ -39,6 +42,22 @@ prof_gdump_get_unlocked(void) { return prof_gdump_val; } +JEMALLOC_ALWAYS_INLINE void +prof_thread_name_assert(prof_tdata_t *tdata) { + if (!config_debug) { + return; + } + prof_active_assert(); + + bool terminated = false; + for (unsigned i = 0; i < PROF_THREAD_NAME_MAX_LEN; i++) { + if (tdata->thread_name[i] == '\0') { + terminated = true; + } + } + assert(terminated); +} + JEMALLOC_ALWAYS_INLINE prof_tdata_t * prof_tdata_get(tsd_t *tsd, bool create) { prof_tdata_t *tdata; @@ -60,6 +79,10 @@ prof_tdata_get(tsd_t *tsd, bool create) { assert(tdata == NULL || tdata->attached); } + if (tdata != NULL) { + prof_thread_name_assert(tdata); + } + return tdata; } @@ -83,6 +106,11 @@ prof_info_get_and_reset_recent(tsd_t *tsd, const void *ptr, arena_prof_info_get(tsd, ptr, alloc_ctx, prof_info, true); } +JEMALLOC_ALWAYS_INLINE bool +prof_tctx_is_valid(const prof_tctx_t *tctx) { + return tctx != NULL && tctx != PROF_TCTX_SENTINEL; +} + JEMALLOC_ALWAYS_INLINE void prof_tctx_reset(tsd_t *tsd, const void *ptr, emap_alloc_ctx_t *alloc_ctx) { cassert(config_prof); @@ -103,7 +131,7 @@ JEMALLOC_ALWAYS_INLINE void prof_info_set(tsd_t *tsd, edata_t *edata, prof_tctx_t *tctx, size_t size) { cassert(config_prof); assert(edata != NULL); - assert((uintptr_t)tctx > (uintptr_t)1U); + assert(prof_tctx_is_valid(tctx)); arena_prof_info_set(tsd, edata, tctx, size); } @@ -138,7 +166,7 @@ prof_alloc_prep(tsd_t *tsd, bool prof_active, bool sample_event) { if (!prof_active || likely(prof_sample_should_skip(tsd, sample_event))) { - ret = (prof_tctx_t *)(uintptr_t)1U; + ret = PROF_TCTX_SENTINEL; } else { ret = prof_tctx_create(tsd); } @@ -153,7 +181,7 @@ prof_malloc(tsd_t *tsd, const void *ptr, size_t size, size_t usize, assert(ptr != NULL); assert(usize == isalloc(tsd_tsdn(tsd), ptr)); - if (unlikely((uintptr_t)tctx > (uintptr_t)1U)) { + if (unlikely(prof_tctx_is_valid(tctx))) { prof_malloc_sample_object(tsd, ptr, size, usize, tctx); } else { prof_tctx_reset(tsd, ptr, alloc_ctx); @@ -167,7 +195,7 @@ prof_realloc(tsd_t *tsd, const void *ptr, size_t size, size_t usize, bool sampled, old_sampled, moved; cassert(config_prof); - assert(ptr != NULL || (uintptr_t)tctx <= (uintptr_t)1U); + assert(ptr != NULL || !prof_tctx_is_valid(tctx)); if (prof_active && ptr != NULL) { assert(usize == isalloc(tsd_tsdn(tsd), ptr)); @@ -180,12 +208,12 @@ prof_realloc(tsd_t *tsd, const void *ptr, size_t size, size_t usize, * sample threshold. */ prof_alloc_rollback(tsd, tctx); - tctx = (prof_tctx_t *)(uintptr_t)1U; + tctx = PROF_TCTX_SENTINEL; } } - sampled = ((uintptr_t)tctx > (uintptr_t)1U); - old_sampled = ((uintptr_t)old_prof_info->alloc_tctx > (uintptr_t)1U); + sampled = prof_tctx_is_valid(tctx); + old_sampled = prof_tctx_is_valid(old_prof_info->alloc_tctx); moved = (ptr != old_ptr); if (unlikely(sampled)) { @@ -203,7 +231,7 @@ prof_realloc(tsd_t *tsd, const void *ptr, size_t size, size_t usize, } else { prof_info_t prof_info; prof_info_get(tsd, ptr, NULL, &prof_info); - assert((uintptr_t)prof_info.alloc_tctx == (uintptr_t)1U); + assert(prof_info.alloc_tctx == PROF_TCTX_SENTINEL); } /* @@ -214,31 +242,28 @@ prof_realloc(tsd_t *tsd, const void *ptr, size_t size, size_t usize, * counters. */ if (unlikely(old_sampled)) { - prof_free_sampled_object(tsd, old_usize, old_prof_info); + prof_free_sampled_object(tsd, old_ptr, old_usize, + old_prof_info); } } JEMALLOC_ALWAYS_INLINE size_t -prof_sample_align(size_t orig_align) { +prof_sample_align(size_t usize, size_t orig_align) { /* - * Enforce page alignment, so that sampled allocations can be identified + * Enforce alignment, so that sampled allocations can be identified * w/o metadata lookup. */ assert(opt_prof); - return (opt_cache_oblivious && orig_align < PAGE) ? PAGE : - orig_align; -} - -JEMALLOC_ALWAYS_INLINE bool -prof_sample_aligned(const void *ptr) { - return ((uintptr_t)ptr & PAGE_MASK) == 0; + return (orig_align < PROF_SAMPLE_ALIGNMENT && + (sz_can_use_slab(usize) || opt_cache_oblivious)) ? + PROF_SAMPLE_ALIGNMENT : orig_align; } JEMALLOC_ALWAYS_INLINE bool prof_sampled(tsd_t *tsd, const void *ptr) { prof_info_t prof_info; prof_info_get(tsd, ptr, NULL, &prof_info); - bool sampled = (uintptr_t)prof_info.alloc_tctx > (uintptr_t)1U; + bool sampled = prof_tctx_is_valid(prof_info.alloc_tctx); if (sampled) { assert(prof_sample_aligned(ptr)); } @@ -254,12 +279,24 @@ prof_free(tsd_t *tsd, const void *ptr, size_t usize, cassert(config_prof); assert(usize == isalloc(tsd_tsdn(tsd), ptr)); - if (unlikely((uintptr_t)prof_info.alloc_tctx > (uintptr_t)1U)) { + if (unlikely(prof_tctx_is_valid(prof_info.alloc_tctx))) { assert(prof_sample_aligned(ptr)); - prof_free_sampled_object(tsd, usize, &prof_info); + prof_free_sampled_object(tsd, ptr, usize, &prof_info); } } -} // namespace duckdb_jemalloc +JEMALLOC_ALWAYS_INLINE bool +prof_thread_name_empty(prof_tdata_t *tdata) { + prof_active_assert(); + + return (tdata->thread_name[0] == '\0'); +} + +JEMALLOC_ALWAYS_INLINE void +prof_thread_name_clear(prof_tdata_t *tdata) { + prof_active_assert(); + + tdata->thread_name[0] = '\0'; +} #endif /* JEMALLOC_INTERNAL_PROF_INLINES_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_log.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_log.h index 10d182613a7..0b1271c892a 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_log.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_log.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_PROF_LOG_H #define JEMALLOC_INTERNAL_PROF_LOG_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/mutex.h" -namespace duckdb_jemalloc { - extern malloc_mutex_t log_mtx; void prof_try_log(tsd_t *tsd, size_t usize, prof_info_t *prof_info); @@ -21,6 +20,4 @@ void prof_log_dummy_set(bool new_value); bool prof_log_start(tsdn_t *tsdn, const char *filename); bool prof_log_stop(tsdn_t *tsdn); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PROF_LOG_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_recent.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_recent.h index 75432269b94..33649e6daa3 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_recent.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_recent.h @@ -1,7 +1,9 @@ #ifndef JEMALLOC_INTERNAL_PROF_RECENT_H #define JEMALLOC_INTERNAL_PROF_RECENT_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/edata.h" +#include "jemalloc/internal/mutex.h" extern malloc_mutex_t prof_recent_alloc_mtx; extern malloc_mutex_t prof_recent_dump_mtx; @@ -9,7 +11,7 @@ extern malloc_mutex_t prof_recent_dump_mtx; bool prof_recent_alloc_prepare(tsd_t *tsd, prof_tctx_t *tctx); void prof_recent_alloc(tsd_t *tsd, edata_t *edata, size_t size, size_t usize); void prof_recent_alloc_reset(tsd_t *tsd, edata_t *edata); -bool prof_recent_init(); +bool prof_recent_init(void); void edata_prof_recent_alloc_init(edata_t *edata); /* Used in unit tests. */ @@ -18,10 +20,8 @@ extern prof_recent_list_t prof_recent_alloc_list; edata_t *prof_recent_alloc_edata_get_no_lock_test(const prof_recent_t *node); prof_recent_t *edata_prof_recent_alloc_get_no_lock_test(const edata_t *edata); -ssize_t prof_recent_alloc_max_ctl_read(); +ssize_t prof_recent_alloc_max_ctl_read(void); ssize_t prof_recent_alloc_max_ctl_write(tsd_t *tsd, ssize_t max); void prof_recent_alloc_dump(tsd_t *tsd, write_cb_t *write_cb, void *cbopaque); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PROF_RECENT_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_stats.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_stats.h index b767d308235..c4d269e54d7 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_stats.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_stats.h @@ -1,7 +1,8 @@ #ifndef JEMALLOC_INTERNAL_PROF_STATS_H #define JEMALLOC_INTERNAL_PROF_STATS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/mutex.h" typedef struct prof_stats_s prof_stats_t; struct prof_stats_s { @@ -16,6 +17,4 @@ void prof_stats_dec(tsd_t *tsd, szind_t ind, size_t size); void prof_stats_get_live(tsd_t *tsd, szind_t ind, prof_stats_t *stats); void prof_stats_get_accum(tsd_t *tsd, szind_t ind, prof_stats_t *stats); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PROF_STATS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_structs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_structs.h index 6018122ca77..084a549dc45 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_structs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_structs.h @@ -1,14 +1,13 @@ #ifndef JEMALLOC_INTERNAL_PROF_STRUCTS_H #define JEMALLOC_INTERNAL_PROF_STRUCTS_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/ckh.h" #include "jemalloc/internal/edata.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/prng.h" #include "jemalloc/internal/rb.h" -namespace duckdb_jemalloc { - struct prof_bt_s { /* Backtrace, stored as len program counters. */ void **vec; @@ -158,12 +157,6 @@ struct prof_tdata_s { */ uint64_t thr_discrim; - /* Included in heap profile dumps if non-NULL. */ - char *thread_name; - - bool attached; - bool expired; - rb_node(prof_tdata_t) tdata_link; /* @@ -181,6 +174,9 @@ struct prof_tdata_s { */ ckh_t bt2tctx; + /* Included in heap profile dumps if has content. */ + char thread_name[PROF_THREAD_NAME_MAX_LEN]; + /* State used to avoid dumping while operating on prof internals. */ bool enq; bool enq_idump; @@ -200,11 +196,14 @@ struct prof_tdata_s { */ bool active; + bool attached; + bool expired; + /* Temporary storage for summation during dump. */ prof_cnt_t cnt_summed; /* Backtrace vector, used for calls to prof_backtrace(). */ - void *vec[PROF_BT_MAX]; + void **vec; }; typedef rb_tree(prof_tdata_t) prof_tdata_tree_t; @@ -220,6 +219,4 @@ struct prof_recent_s { prof_tctx_t *dalloc_tctx; }; -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PROF_STRUCTS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_sys.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_sys.h index b0c3589a2e5..e6e7f06fb27 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_sys.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_sys.h @@ -1,15 +1,17 @@ #ifndef JEMALLOC_INTERNAL_PROF_SYS_H #define JEMALLOC_INTERNAL_PROF_SYS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/base.h" +#include "jemalloc/internal/mutex.h" extern malloc_mutex_t prof_dump_filename_mtx; extern base_t *prof_base; void bt_init(prof_bt_t *bt, void **vec); void prof_backtrace(tsd_t *tsd, prof_bt_t *bt); -void prof_hooks_init(); -void prof_unwind_init(); +void prof_hooks_init(void); +void prof_unwind_init(void); void prof_sys_thread_name_fetch(tsd_t *tsd); int prof_getpid(void); void prof_get_default_filename(tsdn_t *tsdn, char *filename, uint64_t ind); @@ -26,9 +28,7 @@ typedef int (prof_dump_open_file_t)(const char *, int); extern prof_dump_open_file_t *JET_MUTABLE prof_dump_open_file; typedef ssize_t (prof_dump_write_file_t)(int, const void *, size_t); extern prof_dump_write_file_t *JET_MUTABLE prof_dump_write_file; -typedef int (prof_dump_open_maps_t)(); +typedef int (prof_dump_open_maps_t)(void); extern prof_dump_open_maps_t *JET_MUTABLE prof_dump_open_maps; -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PROF_SYS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_types.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_types.h index 5f73fe00df0..a27f7fb330a 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_types.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/prof_types.h @@ -1,8 +1,6 @@ #ifndef JEMALLOC_INTERNAL_PROF_TYPES_H #define JEMALLOC_INTERNAL_PROF_TYPES_H -namespace duckdb_jemalloc { - typedef struct prof_bt_s prof_bt_t; typedef struct prof_cnt_s prof_cnt_t; typedef struct prof_tctx_s prof_tctx_t; @@ -11,8 +9,6 @@ typedef struct prof_gctx_s prof_gctx_t; typedef struct prof_tdata_s prof_tdata_t; typedef struct prof_recent_s prof_recent_t; -} // namespace duckdb_jemalloc - /* Option defaults. */ #ifdef JEMALLOC_PROF # define PROF_PREFIX_DEFAULT "jeprof" @@ -27,7 +23,12 @@ typedef struct prof_recent_s prof_recent_t; * is based on __builtin_return_address() necessarily has a hard-coded number * of backtrace frame handlers, and should be kept in sync with this setting. */ -#define PROF_BT_MAX 128 +#ifdef JEMALLOC_PROF_GCC +# define PROF_BT_MAX_LIMIT 256 +#else +# define PROF_BT_MAX_LIMIT UINT_MAX +#endif +#define PROF_BT_MAX_DEFAULT 128 /* Initial hash table size. */ #define PROF_CKH_MINITEMS 64 @@ -76,4 +77,18 @@ typedef struct prof_recent_s prof_recent_t; /* Default number of recent allocations to record. */ #define PROF_RECENT_ALLOC_MAX_DEFAULT 0 +/* Thread name storage size limit. */ +#define PROF_THREAD_NAME_MAX_LEN 16 + +/* + * Minimum required alignment for sampled allocations. Over-aligning sampled + * allocations allows us to quickly identify them on the dalloc path without + * resorting to metadata lookup. + */ +#define PROF_SAMPLE_ALIGNMENT PAGE +#define PROF_SAMPLE_ALIGNMENT_MASK PAGE_MASK + +/* NOLINTNEXTLINE(performance-no-int-to-ptr) */ +#define PROF_TCTX_SENTINEL ((prof_tctx_t *)((uintptr_t)1U)) + #endif /* JEMALLOC_INTERNAL_PROF_TYPES_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/psset.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/psset.h index 8ca79d4f3f2..7e510b7f685 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/psset.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/psset.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_PSSET_H #define JEMALLOC_INTERNAL_PSSET_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/hpdata.h" -namespace duckdb_jemalloc { - /* * A page-slab set. What the eset is to PAC, the psset is to HPA. It maintains * a collection of page-slabs (the intent being that they are backed by @@ -130,6 +129,4 @@ psset_ndirty(psset_t *psset) { return psset->merged_stats.ndirty; } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_PSSET_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/public_namespace.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/public_namespace.h index 738e3a55073..3a9419837ff 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/public_namespace.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/public_namespace.h @@ -1,5 +1,3 @@ -namespace duckdb_jemalloc { - #define je_aligned_alloc JEMALLOC_N(aligned_alloc) #define je_calloc JEMALLOC_N(calloc) #define je_dallocx JEMALLOC_N(dallocx) @@ -14,7 +12,7 @@ namespace duckdb_jemalloc { #define je_malloc_stats_print JEMALLOC_N(malloc_stats_print) #define je_malloc_usable_size JEMALLOC_N(malloc_usable_size) #define je_mallocx JEMALLOC_N(mallocx) -#define je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c JEMALLOC_N(smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c) +#define je_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 JEMALLOC_N(smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9) #define je_nallocx JEMALLOC_N(nallocx) #define je_posix_memalign JEMALLOC_N(posix_memalign) #define je_rallocx JEMALLOC_N(rallocx) @@ -24,5 +22,3 @@ namespace duckdb_jemalloc { #define je_xallocx JEMALLOC_N(xallocx) #define je_valloc JEMALLOC_N(valloc) #define je_malloc_size JEMALLOC_N(malloc_size) - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/public_unnamespace.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/public_unnamespace.h index 558a9ef1b94..bbd77d46e80 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/public_unnamespace.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/public_unnamespace.h @@ -1,5 +1,3 @@ -namespace duckdb_jemalloc { - #undef je_aligned_alloc #undef je_calloc #undef je_dallocx @@ -14,7 +12,7 @@ namespace duckdb_jemalloc { #undef je_malloc_stats_print #undef je_malloc_usable_size #undef je_mallocx -#undef je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c +#undef je_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 #undef je_nallocx #undef je_posix_memalign #undef je_rallocx @@ -24,5 +22,3 @@ namespace duckdb_jemalloc { #undef je_xallocx #undef je_valloc #undef je_malloc_size - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/ql.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/ql.h index 22d678b459b..ebe69988a11 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/ql.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/ql.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_QL_H #define JEMALLOC_INTERNAL_QL_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/qr.h" -namespace duckdb_jemalloc { - /* * A linked-list implementation. * @@ -196,6 +195,4 @@ struct { \ #define ql_reverse_foreach(a_var, a_head, a_field) \ qr_reverse_foreach((a_var), ql_first(a_head), a_field) -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_QL_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/qr.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/qr.h index 6de777bf727..ece4f556860 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/qr.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/qr.h @@ -1,8 +1,6 @@ #ifndef JEMALLOC_INTERNAL_QR_H #define JEMALLOC_INTERNAL_QR_H -namespace duckdb_jemalloc { - /* * A ring implementation based on an embedded circular doubly-linked list. * @@ -139,6 +137,4 @@ struct { \ (var) = (((var) != (a_qr)) \ ? (var)->a_field.qre_prev : NULL)) -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_QR_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/quantum.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/quantum.h index c22d753aa79..a97f54caf62 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/quantum.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/quantum.h @@ -49,7 +49,7 @@ # ifdef __or1k__ # define LG_QUANTUM 3 # endif -# ifdef __powerpc__ +# if defined(__powerpc__) || defined(__ppc__) || defined(__powerpc64__) || defined(__ppc64__) # define LG_QUANTUM 4 # endif # if defined(__riscv) || defined(__riscv__) diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/rb.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/rb.h index 859120b86fb..5f2771a9c66 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/rb.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/rb.h @@ -1,9 +1,8 @@ #ifndef JEMALLOC_INTERNAL_RB_H #define JEMALLOC_INTERNAL_RB_H -#include "jemalloc/internal/jemalloc_internal_decls.h" - -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/safety_check.h" /*- ******************************************************************************* @@ -564,6 +563,20 @@ a_prefix##reverse_iter_filtered(a_rbt_type *rbtree, a_type *start, \ * the same as with the unfiltered version, with the added constraint that the * returned node must pass the filter. */ +JEMALLOC_ALWAYS_INLINE void +rb_remove_safety_checks(const void *nodep, const char *function_name) { + if (!config_opt_safety_checks) { + return; + } + if (unlikely(nodep == NULL)) { + safety_check_fail( + ": Invalid deallocation detected in %s: " + "attempting to remove node from tree but node was " + "not found. Possibly caused by double free bugs.", + function_name); + } +} + #define rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp) \ rb_gen_impl(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp, \ rb_empty_summarize, false) @@ -856,6 +869,8 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ } \ } \ } \ + rb_remove_safety_checks(nodep, __func__); \ + assert(nodep != NULL); \ assert(nodep->node == node); \ pathp--; \ if (pathp->node != node) { \ @@ -1857,6 +1872,4 @@ a_prefix##reverse_iter_filtered(a_rbt_type *rbtree, a_type *start, \ } \ ) /* end rb_summarized_only */ -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_RB_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/rtree.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/rtree.h index bc576d66465..f35368ae024 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/rtree.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/rtree.h @@ -1,14 +1,15 @@ #ifndef JEMALLOC_INTERNAL_RTREE_H #define JEMALLOC_INTERNAL_RTREE_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/base.h" #include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/edata.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/rtree_tsd.h" #include "jemalloc/internal/sc.h" #include "jemalloc/internal/tsd.h" -namespace duckdb_jemalloc { - /* * This radix tree implementation is tailored to the singular purpose of * associating metadata with extents that are currently owned by jemalloc. @@ -225,9 +226,11 @@ rtree_leaf_elm_bits_decode(uintptr_t bits) { uintptr_t high_bit_mask = ((uintptr_t)1 << LG_VADDR) - 1; /* Mask off metadata. */ uintptr_t mask = high_bit_mask & low_bit_mask; + /* NOLINTNEXTLINE(performance-no-int-to-ptr) */ contents.edata = (edata_t *)(bits & mask); # else /* Restore sign-extended high bits, mask metadata bits. */ + /* NOLINTNEXTLINE(performance-no-int-to-ptr) */ contents.edata = (edata_t *)((uintptr_t)((intptr_t)(bits << RTREE_NHIB) >> RTREE_NHIB) & low_bit_mask); # endif @@ -269,7 +272,12 @@ JEMALLOC_ALWAYS_INLINE void rtree_contents_encode(rtree_contents_t contents, void **bits, unsigned *additional) { #ifdef RTREE_LEAF_COMPACT + /* NOLINTNEXTLINE(performance-no-int-to-ptr) */ *bits = (void *)rtree_leaf_elm_bits_encode(contents); + /* Suppress spurious warning from static analysis */ + if (config_debug) { + *additional = 0; + } #else *additional = (unsigned)contents.metadata.slab | ((unsigned)contents.metadata.is_head << 1) @@ -301,7 +309,6 @@ rtree_leaf_elm_write(tsdn_t *tsdn, rtree_t *rtree, assert((uintptr_t)contents.edata % EDATA_ALIGNMENT == 0); void *bits; unsigned additional; - rtree_contents_encode(contents, &bits, &additional); rtree_leaf_elm_write_commit(tsdn, rtree, elm, bits, additional); } @@ -316,8 +323,10 @@ rtree_leaf_elm_state_update(tsdn_t *tsdn, rtree_t *rtree, /* dependent */ true); bits &= ~RTREE_LEAF_STATE_MASK; bits |= state << RTREE_LEAF_STATE_SHIFT; + /* NOLINTNEXTLINE(performance-no-int-to-ptr) */ atomic_store_p(&elm1->le_bits, (void *)bits, ATOMIC_RELEASE); if (elm2 != NULL) { + /* NOLINTNEXTLINE(performance-no-int-to-ptr) */ atomic_store_p(&elm2->le_bits, (void *)bits, ATOMIC_RELEASE); } #else @@ -553,6 +562,4 @@ rtree_clear_range(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, /* clearing */ true); } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_RTREE_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/rtree_tsd.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/rtree_tsd.h index 9e2ce1b90dd..59f185700d0 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/rtree_tsd.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/rtree_tsd.h @@ -1,7 +1,7 @@ #ifndef JEMALLOC_INTERNAL_RTREE_CTX_H #define JEMALLOC_INTERNAL_RTREE_CTX_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" /* * Number of leafkey/leaf pairs to cache in L1 and L2 level respectively. Each @@ -61,6 +61,4 @@ struct rtree_ctx_s { void rtree_ctx_data_init(rtree_ctx_t *ctx); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_RTREE_CTX_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/safety_check.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/safety_check.h index fbe4d4ec1a3..194b7744e1d 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/safety_check.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/safety_check.h @@ -1,7 +1,11 @@ #ifndef JEMALLOC_INTERNAL_SAFETY_CHECK_H #define JEMALLOC_INTERNAL_SAFETY_CHECK_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/pages.h" + +#define SAFETY_CHECK_DOUBLE_FREE_MAX_SCAN_DEFAULT 32 void safety_check_fail_sized_dealloc(bool current_dealloc, const void *ptr, size_t true_size, size_t input_size); @@ -12,24 +16,50 @@ typedef void (*safety_check_abort_hook_t)(const char *message); /* Can set to NULL for a default. */ void safety_check_set_abort(safety_check_abort_hook_t abort_fn); +#define REDZONE_SIZE ((size_t) 32) +#define REDZONE_FILL_VALUE 0xBC + +/* + * Normally the redzone extends `REDZONE_SIZE` bytes beyond the end of + * the allocation. However, we don't let the redzone extend onto another + * OS page because this would impose additional overhead if that page was + * not already resident in memory. + */ +JEMALLOC_ALWAYS_INLINE const unsigned char * +compute_redzone_end(const void *_ptr, size_t usize, size_t bumped_usize) { + const unsigned char *ptr = (const unsigned char *) _ptr; + const unsigned char *redzone_end = usize + REDZONE_SIZE < bumped_usize ? + &ptr[usize + REDZONE_SIZE] : &ptr[bumped_usize]; + const unsigned char *page_end = (const unsigned char *) + ALIGNMENT_ADDR2CEILING(&ptr[usize], os_page); + return redzone_end < page_end ? redzone_end : page_end; +} + JEMALLOC_ALWAYS_INLINE void safety_check_set_redzone(void *ptr, size_t usize, size_t bumped_usize) { - assert(usize < bumped_usize); - for (size_t i = usize; i < bumped_usize && i < usize + 32; ++i) { - *((unsigned char *)ptr + i) = 0xBC; + assert(usize <= bumped_usize); + const unsigned char *redzone_end = + compute_redzone_end(ptr, usize, bumped_usize); + for (unsigned char *curr = &((unsigned char *)ptr)[usize]; + curr < redzone_end; curr++) { + *curr = REDZONE_FILL_VALUE; } } JEMALLOC_ALWAYS_INLINE void safety_check_verify_redzone(const void *ptr, size_t usize, size_t bumped_usize) { - for (size_t i = usize; i < bumped_usize && i < usize + 32; ++i) { - if (unlikely(*((unsigned char *)ptr + i) != 0xBC)) { + const unsigned char *redzone_end = + compute_redzone_end(ptr, usize, bumped_usize); + for (const unsigned char *curr= &((const unsigned char *)ptr)[usize]; + curr < redzone_end; curr++) { + if (unlikely(*curr != REDZONE_FILL_VALUE)) { safety_check_fail("Use after free error\n"); } } } -} // namespace duckdb_jemalloc +#undef REDZONE_SIZE +#undef REDZONE_FILL_VALUE #endif /*JEMALLOC_INTERNAL_SAFETY_CHECK_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/san.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/san.h index 56ea3da5640..669f99dda7e 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/san.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/san.h @@ -1,11 +1,11 @@ #ifndef JEMALLOC_INTERNAL_GUARD_H #define JEMALLOC_INTERNAL_GUARD_H -#include "jemalloc/internal/jemalloc_internal_decls.h" +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/ehooks.h" #include "jemalloc/internal/emap.h" - -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_internal_externs.h" +#include "jemalloc/internal/tsd.h" #define SAN_PAGE_GUARD PAGE #define SAN_PAGE_GUARDS_SIZE (SAN_PAGE_GUARD * 2) @@ -140,7 +140,7 @@ san_junk_ptr_locations(void *ptr, size_t usize, void **first, void **mid, *first = ptr; - *mid = (void *)((uintptr_t)ptr + ((usize >> 1) & ~(ptr_sz - 1))); + *mid = (void *)((byte_t *)ptr + ((usize >> 1) & ~(ptr_sz - 1))); assert(*first != *mid || usize == ptr_sz); assert((uintptr_t)*first <= (uintptr_t)*mid); @@ -151,7 +151,7 @@ san_junk_ptr_locations(void *ptr, size_t usize, void **first, void **mid, * default the tcache only goes up to the 32K size class, and is usually * tuned lower instead of higher, which makes it less of a concern. */ - *last = (void *)((uintptr_t)ptr + usize - sizeof(uaf_detect_junk)); + *last = (void *)((byte_t *)ptr + usize - sizeof(uaf_detect_junk)); assert(*first != *last || usize == ptr_sz); assert(*mid != *last || usize <= ptr_sz * 2); assert((uintptr_t)*mid <= (uintptr_t)*last); @@ -191,6 +191,4 @@ san_uaf_detection_enabled(void) { return ret; } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_GUARD_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/san_bump.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/san_bump.h index 97a5a7b47cf..d6e9cfc5a1d 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/san_bump.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/san_bump.h @@ -1,11 +1,11 @@ #ifndef JEMALLOC_INTERNAL_SAN_BUMP_H #define JEMALLOC_INTERNAL_SAN_BUMP_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/edata.h" #include "jemalloc/internal/exp_grow.h" #include "jemalloc/internal/mutex.h" - -namespace duckdb_jemalloc { +#include "jemalloc/internal/witness.h" #define SBA_RETAINED_ALLOC_SIZE ((size_t)4 << 20) @@ -22,7 +22,7 @@ struct san_bump_alloc_s { }; static inline bool -san_bump_enabled() { +san_bump_enabled(void) { /* * We enable san_bump allocator only when it's possible to break up a * mapping and unmap a part of it (maps_coalesce). This is needed to @@ -51,6 +51,4 @@ edata_t * san_bump_alloc(tsdn_t *tsdn, san_bump_alloc_t* sba, pac_t *pac, ehooks_t *ehooks, size_t size, bool zero); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_SAN_BUMP_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/sc.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/sc.h index a44d6e5a241..770835ccd89 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/sc.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/sc.h @@ -1,8 +1,8 @@ #ifndef JEMALLOC_INTERNAL_SC_H #define JEMALLOC_INTERNAL_SC_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_types.h" -#include "jemalloc/internal/jemalloc_internal_defs.h" /* * Size class computations: @@ -169,7 +169,7 @@ /* * Size class N + (1 << SC_LG_NGROUP) twice the size of size class N. */ -#define SC_LG_NGROUP 2 +#define SC_LG_NGROUP 2 #define SC_LG_TINY_MIN 3 #if SC_LG_TINY_MIN == 0 @@ -181,11 +181,11 @@ * The definitions below are all determined by the above settings and system * characteristics. */ -#define SC_NGROUP (1ULL << SC_LG_NGROUP) -#define SC_PTR_BITS ((1ULL << LG_SIZEOF_PTR) * 8) -#define SC_NTINY (LG_QUANTUM - SC_LG_TINY_MIN) -#define SC_LG_TINY_MAXCLASS (LG_QUANTUM > SC_LG_TINY_MIN ? LG_QUANTUM - 1 : -1) -#define SC_NPSEUDO SC_NGROUP +#define SC_NGROUP (1ULL << SC_LG_NGROUP) +#define SC_PTR_BITS ((1ULL << LG_SIZEOF_PTR) * 8) +#define SC_NTINY (LG_QUANTUM - SC_LG_TINY_MIN) +#define SC_LG_TINY_MAXCLASS (LG_QUANTUM > SC_LG_TINY_MIN ? LG_QUANTUM - 1 : -1) +#define SC_NPSEUDO SC_NGROUP #define SC_LG_FIRST_REGULAR_BASE (LG_QUANTUM + SC_LG_NGROUP) /* * We cap allocations to be less than 2 ** (ptr_bits - 1), so the highest base @@ -194,14 +194,15 @@ * We could probably save some space in arenas by capping this at LG_VADDR size. */ #define SC_LG_BASE_MAX (SC_PTR_BITS - 2) -#define SC_NREGULAR (SC_NGROUP * (SC_LG_BASE_MAX - SC_LG_FIRST_REGULAR_BASE + 1) - 1) -#define SC_NSIZES (SC_NTINY + SC_NPSEUDO + SC_NREGULAR) +#define SC_NREGULAR (SC_NGROUP * \ + (SC_LG_BASE_MAX - SC_LG_FIRST_REGULAR_BASE + 1) - 1) +#define SC_NSIZES (SC_NTINY + SC_NPSEUDO + SC_NREGULAR) /* * The number of size classes that are a multiple of the page size. * * Here are the first few bases that have a page-sized SC. - *SC_NSIZES + * * lg(base) | base | highest SC | page-multiple SCs * --------------|------------------------------------------ * LG_PAGE - 1 | PAGE / 2 | PAGE | 1 @@ -221,49 +222,54 @@ * * This gives us the quantity we seek. */ -#define SC_NPSIZES (SC_NGROUP + (SC_LG_BASE_MAX - (LG_PAGE + SC_LG_NGROUP)) * SC_NGROUP + SC_NGROUP - 1) +#define SC_NPSIZES ( \ + SC_NGROUP \ + + (SC_LG_BASE_MAX - (LG_PAGE + SC_LG_NGROUP)) * SC_NGROUP \ + + SC_NGROUP - 1) /* * We declare a size class is binnable if size < page size * group. Or, in other * words, lg(size) < lg(page size) + lg(group size). */ -#define SC_NBINS \ - ( /* Sub-regular size classes. */ \ - SC_NTINY + SC_NPSEUDO /* Groups with lg_regular_min_base <= lg_base <= lg_base_max */ \ - + SC_NGROUP * (LG_PAGE + SC_LG_NGROUP - \ - SC_LG_FIRST_REGULAR_BASE) /* Last SC of the last group hits the bound exactly; exclude it. */ \ - - 1) +#define SC_NBINS ( \ + /* Sub-regular size classes. */ \ + SC_NTINY + SC_NPSEUDO \ + /* Groups with lg_regular_min_base <= lg_base <= lg_base_max */ \ + + SC_NGROUP * (LG_PAGE + SC_LG_NGROUP - SC_LG_FIRST_REGULAR_BASE) \ + /* Last SC of the last group hits the bound exactly; exclude it. */ \ + - 1) /* * The size2index_tab lookup table uses uint8_t to encode each bin index, so we * cannot support more than 256 small size classes. */ #if (SC_NBINS > 256) -#error "Too many small size classes" +# error "Too many small size classes" #endif /* The largest size class in the lookup table, and its binary log. */ -#define SC_LG_MAX_LOOKUP 12 +#define SC_LG_MAX_LOOKUP 12 #define SC_LOOKUP_MAXCLASS (1 << SC_LG_MAX_LOOKUP) /* Internal, only used for the definition of SC_SMALL_MAXCLASS. */ -#define SC_SMALL_MAX_BASE (1 << (LG_PAGE + SC_LG_NGROUP - 1)) +#define SC_SMALL_MAX_BASE (1 << (LG_PAGE + SC_LG_NGROUP - 1)) #define SC_SMALL_MAX_DELTA (1 << (LG_PAGE - 1)) /* The largest size class allocated out of a slab. */ -#define SC_SMALL_MAXCLASS (SC_SMALL_MAX_BASE + (SC_NGROUP - 1) * SC_SMALL_MAX_DELTA) +#define SC_SMALL_MAXCLASS (SC_SMALL_MAX_BASE \ + + (SC_NGROUP - 1) * SC_SMALL_MAX_DELTA) /* The fastpath assumes all lookup-able sizes are small. */ #if (SC_SMALL_MAXCLASS < SC_LOOKUP_MAXCLASS) -#error "Lookup table sizes must be small" +# error "Lookup table sizes must be small" #endif /* The smallest size class not allocated out of a slab. */ -#define SC_LARGE_MINCLASS ((size_t)1ULL << (LG_PAGE + SC_LG_NGROUP)) +#define SC_LARGE_MINCLASS ((size_t)1ULL << (LG_PAGE + SC_LG_NGROUP)) #define SC_LG_LARGE_MINCLASS (LG_PAGE + SC_LG_NGROUP) /* Internal; only used for the definition of SC_LARGE_MAXCLASS. */ -#define SC_MAX_BASE ((size_t)1 << (SC_PTR_BITS - 2)) +#define SC_MAX_BASE ((size_t)1 << (SC_PTR_BITS - 2)) #define SC_MAX_DELTA ((size_t)1 << (SC_PTR_BITS - 2 - SC_LG_NGROUP)) /* The largest size class supported. */ @@ -271,19 +277,17 @@ /* Maximum number of regions in one slab. */ #ifndef CONFIG_LG_SLAB_MAXREGS -#define SC_LG_SLAB_MAXREGS (LG_PAGE - SC_LG_TINY_MIN) -#else -#if CONFIG_LG_SLAB_MAXREGS < (LG_PAGE - SC_LG_TINY_MIN) -#error "Unsupported SC_LG_SLAB_MAXREGS" +# define SC_LG_SLAB_MAXREGS (LG_PAGE - SC_LG_TINY_MIN) #else -#define SC_LG_SLAB_MAXREGS CONFIG_LG_SLAB_MAXREGS -#endif +# if CONFIG_LG_SLAB_MAXREGS < (LG_PAGE - SC_LG_TINY_MIN) +# error "Unsupported SC_LG_SLAB_MAXREGS" +# else +# define SC_LG_SLAB_MAXREGS CONFIG_LG_SLAB_MAXREGS +# endif #endif #define SC_SLAB_MAXREGS (1U << SC_LG_SLAB_MAXREGS) -namespace duckdb_jemalloc { - typedef struct sc_s sc_t; struct sc_s { /* Size class index, or -1 if not a valid size class. */ @@ -347,9 +351,8 @@ void sc_data_init(sc_data_t *data); * Updates slab sizes in [begin, end] to be pgs pages in length, if possible. * Otherwise, does its best to accommodate the request. */ -void sc_data_update_slab_size(sc_data_t *data, size_t begin, size_t end, int pgs); +void sc_data_update_slab_size(sc_data_t *data, size_t begin, size_t end, + int pgs); void sc_boot(sc_data_t *data); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_SC_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/sec.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/sec.h index d5f5d43a2a6..8ef1e9fb668 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/sec.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/sec.h @@ -1,10 +1,12 @@ #ifndef JEMALLOC_INTERNAL_SEC_H #define JEMALLOC_INTERNAL_SEC_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/base.h" #include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/mutex.h" #include "jemalloc/internal/pai.h" - -namespace duckdb_jemalloc { +#include "jemalloc/internal/sec_opts.h" /* * Small extent cache. @@ -119,6 +121,4 @@ void sec_prefork2(tsdn_t *tsdn, sec_t *sec); void sec_postfork_parent(tsdn_t *tsdn, sec_t *sec); void sec_postfork_child(tsdn_t *tsdn, sec_t *sec); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_SEC_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/sec_opts.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/sec_opts.h index 0edfdd4e36d..19ed1492131 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/sec_opts.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/sec_opts.h @@ -1,7 +1,7 @@ #ifndef JEMALLOC_INTERNAL_SEC_OPTS_H #define JEMALLOC_INTERNAL_SEC_OPTS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" /* * The configuration settings used by an sec_t. Morally, this is part of the @@ -57,6 +57,5 @@ struct sec_opts_s { 0 \ } -} // namespace duckdb_jemalloc #endif /* JEMALLOC_INTERNAL_SEC_OPTS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/seq.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/seq.h index 39330afb232..9bb6b235d81 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/seq.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/seq.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_SEQ_H #define JEMALLOC_INTERNAL_SEQ_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/atomic.h" -namespace duckdb_jemalloc { - /* * A simple seqlock implementation. */ @@ -54,6 +53,4 @@ seq_try_load_##short_type(type *dst, seq_##short_type##_t *src) { \ return true; \ } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_SEQ_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/slab_data.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/slab_data.h index 06e4f272ca9..724c71e36da 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/slab_data.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/slab_data.h @@ -1,16 +1,13 @@ #ifndef JEMALLOC_INTERNAL_SLAB_DATA_H #define JEMALLOC_INTERNAL_SLAB_DATA_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/bitmap.h" -namespace duckdb_jemalloc { - typedef struct slab_data_s slab_data_t; struct slab_data_s { /* Per region allocated/deallocated bitmap. */ bitmap_t bitmap[BITMAP_GROUPS_MAX]; }; -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_SLAB_DATA_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/smoothstep.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/smoothstep.h index 33d9d37f1ec..2e14430f5f1 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/smoothstep.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/smoothstep.h @@ -1,8 +1,6 @@ #ifndef JEMALLOC_INTERNAL_SMOOTHSTEP_H #define JEMALLOC_INTERNAL_SMOOTHSTEP_H -namespace duckdb_jemalloc { - /* * This file was generated by the following command: * sh smoothstep.sh smoother 200 24 3 15 @@ -231,6 +229,4 @@ namespace duckdb_jemalloc { STEP( 199, UINT64_C(0x0000000000ffffeb), 0.995, 0.999998759356250) \ STEP( 200, UINT64_C(0x0000000001000000), 1.000, 1.000000000000000) \ -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_SMOOTHSTEP_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/spin.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/spin.h index a0880c6d007..87c400d5a45 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/spin.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/spin.h @@ -1,7 +1,7 @@ #ifndef JEMALLOC_INTERNAL_SPIN_H #define JEMALLOC_INTERNAL_SPIN_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" #define SPIN_INITIALIZER {0U} @@ -10,7 +10,7 @@ typedef struct { } spin_t; static inline void -spin_cpu_spinwait() { +spin_cpu_spinwait(void) { # if HAVE_CPU_SPINWAIT CPU_SPINWAIT; # else @@ -39,6 +39,4 @@ spin_adaptive(spin_t *spin) { #undef SPIN_INLINE -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_SPIN_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/stats.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/stats.h index dad08b04f85..310178eaae8 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/stats.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/stats.h @@ -1,7 +1,9 @@ #ifndef JEMALLOC_INTERNAL_STATS_H #define JEMALLOC_INTERNAL_STATS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/tsd_types.h" /* OPTION(opt, var_name, default, set_value_to) */ #define STATS_PRINT_OPTIONS \ @@ -53,6 +55,4 @@ void stats_prefork(tsdn_t *tsdn); void stats_postfork_parent(tsdn_t *tsdn); void stats_postfork_child(tsdn_t *tsdn); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_STATS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/sz.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/sz.h index de082a529b5..955d8ec0968 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/sz.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/sz.h @@ -1,13 +1,11 @@ #ifndef JEMALLOC_INTERNAL_SIZE_H #define JEMALLOC_INTERNAL_SIZE_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/bit_util.h" #include "jemalloc/internal/pages.h" #include "jemalloc/internal/sc.h" #include "jemalloc/internal/util.h" -#include "jemalloc/internal/assert.h" - -namespace duckdb_jemalloc { /* * sz module: Size computations. @@ -368,9 +366,22 @@ sz_sa2u(size_t size, size_t alignment) { return usize; } +/* + * Under normal circumstances, whether or not to use a slab + * to satisfy an allocation depends solely on the allocation's + * effective size. However, this is *not* the case when an allocation + * is sampled for profiling, in which case you *must not* use a slab + * regardless of the effective size. Thus `sz_can_use_slab` is called + * on the common path, but there exist `*_explicit_slab` variants of + * several functions for handling the aforementioned case of + * sampled allocations. + */ +JEMALLOC_ALWAYS_INLINE bool +sz_can_use_slab(size_t size) { + return size <= SC_SMALL_MAXCLASS; +} + size_t sz_psz_quantize_floor(size_t size); size_t sz_psz_quantize_ceil(size_t size); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_SIZE_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_externs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_externs.h index 11d9f02c6b4..732adacb308 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_externs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_externs.h @@ -1,7 +1,11 @@ #ifndef JEMALLOC_INTERNAL_TCACHE_EXTERNS_H #define JEMALLOC_INTERNAL_TCACHE_EXTERNS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/base.h" +#include "jemalloc/internal/cache_bin.h" +#include "jemalloc/internal/sz.h" +#include "jemalloc/internal/tcache_types.h" extern bool opt_tcache; extern size_t opt_tcache_max; @@ -17,14 +21,19 @@ extern unsigned opt_lg_tcache_flush_large_div; /* * Number of tcache bins. There are SC_NBINS small-object bins, plus 0 or more - * large-object bins. + * large-object bins. This is only used during threads initialization and + * changing it will not reflect on initialized threads as expected. Thus, + * it should not be changed on the fly. To change the number of tcache bins + * in use, refer to tcache_nbins of each tcache. */ -extern unsigned nhbins; +extern unsigned global_do_not_change_tcache_nbins; -/* Maximum cached size class. */ -extern size_t tcache_maxclass; - -extern cache_bin_info_t *tcache_bin_info; +/* + * Maximum cached size class. Same as above, this is only used during threads + * initialization and should not be changed. To change the maximum cached size + * class, refer to tcache_max of each tcache. + */ +extern size_t global_do_not_change_tcache_maxclass; /* * Explicit tcaches, managed via the tcache.{create,flush,destroy} mallctls and @@ -38,17 +47,23 @@ extern tcaches_t *tcaches; size_t tcache_salloc(tsdn_t *tsdn, const void *ptr); void *tcache_alloc_small_hard(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, - cache_bin_t *tbin, szind_t binind, bool *tcache_success); + cache_bin_t *cache_bin, szind_t binind, bool *tcache_success); -void tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, cache_bin_t *tbin, - szind_t binind, unsigned rem); -void tcache_bin_flush_large(tsd_t *tsd, tcache_t *tcache, cache_bin_t *tbin, - szind_t binind, unsigned rem); -void tcache_bin_flush_stashed(tsd_t *tsd, tcache_t *tcache, cache_bin_t *bin, - szind_t binind, bool is_small); +void tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, + cache_bin_t *cache_bin, szind_t binind, unsigned rem); +void tcache_bin_flush_large(tsd_t *tsd, tcache_t *tcache, + cache_bin_t *cache_bin, szind_t binind, unsigned rem); +void tcache_bin_flush_stashed(tsd_t *tsd, tcache_t *tcache, + cache_bin_t *cache_bin, szind_t binind, bool is_small); +bool tcache_bin_info_default_init(const char *bin_settings_segment_cur, + size_t len_left); +bool tcache_bins_ncached_max_write(tsd_t *tsd, char *settings, size_t len); +bool tcache_bin_ncached_max_read(tsd_t *tsd, size_t bin_size, + cache_bin_sz_t *ncached_max); void tcache_arena_reassociate(tsdn_t *tsdn, tcache_slow_t *tcache_slow, tcache_t *tcache, arena_t *arena); tcache_t *tcache_create_explicit(tsd_t *tsd); +void thread_tcache_max_set(tsd_t *tsd, size_t tcache_max); void tcache_cleanup(tsd_t *tsd); void tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena); bool tcaches_create(tsd_t *tsd, base_t *base, unsigned *r_ind); @@ -61,8 +76,8 @@ void tcache_prefork(tsdn_t *tsdn); void tcache_postfork_parent(tsdn_t *tsdn); void tcache_postfork_child(tsdn_t *tsdn); void tcache_flush(tsd_t *tsd); -bool tsd_tcache_data_init(tsd_t *tsd); bool tsd_tcache_enabled_data_init(tsd_t *tsd); +void tcache_enabled_set(tsd_t *tsd, bool enabled); void tcache_assert_initialized(tcache_t *tcache); @@ -74,6 +89,4 @@ uint64_t tcache_gc_dalloc_new_event_wait(tsd_t *tsd); uint64_t tcache_gc_dalloc_postponed_event_wait(tsd_t *tsd); void tcache_gc_dalloc_event_handler(tsd_t *tsd, uint64_t elapsed); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_TCACHE_EXTERNS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_inlines.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_inlines.h index f8a4b9a85e8..e8e3b41f893 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_inlines.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_inlines.h @@ -1,46 +1,90 @@ #ifndef JEMALLOC_INTERNAL_TCACHE_INLINES_H #define JEMALLOC_INTERNAL_TCACHE_INLINES_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/arena_externs.h" #include "jemalloc/internal/bin.h" +#include "jemalloc/internal/jemalloc_internal_inlines_b.h" #include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/large_externs.h" #include "jemalloc/internal/san.h" #include "jemalloc/internal/sc.h" #include "jemalloc/internal/sz.h" +#include "jemalloc/internal/tcache_externs.h" #include "jemalloc/internal/util.h" -namespace duckdb_jemalloc { - static inline bool tcache_enabled_get(tsd_t *tsd) { return tsd_tcache_enabled_get(tsd); } +static inline unsigned +tcache_nbins_get(tcache_slow_t *tcache_slow) { + assert(tcache_slow != NULL); + unsigned nbins = tcache_slow->tcache_nbins; + assert(nbins <= TCACHE_NBINS_MAX); + return nbins; +} + +static inline size_t +tcache_max_get(tcache_slow_t *tcache_slow) { + assert(tcache_slow != NULL); + size_t tcache_max = sz_index2size(tcache_nbins_get(tcache_slow) - 1); + assert(tcache_max <= TCACHE_MAXCLASS_LIMIT); + return tcache_max; +} + static inline void -tcache_enabled_set(tsd_t *tsd, bool enabled) { - bool was_enabled = tsd_tcache_enabled_get(tsd); +tcache_max_set(tcache_slow_t *tcache_slow, size_t tcache_max) { + assert(tcache_slow != NULL); + assert(tcache_max <= TCACHE_MAXCLASS_LIMIT); + tcache_slow->tcache_nbins = sz_size2index(tcache_max) + 1; +} - if (!was_enabled && enabled) { - tsd_tcache_data_init(tsd); - } else if (was_enabled && !enabled) { - tcache_cleanup(tsd); +static inline void +tcache_bin_settings_backup(tcache_t *tcache, + cache_bin_info_t tcache_bin_info[TCACHE_NBINS_MAX]) { + for (unsigned i = 0; i < TCACHE_NBINS_MAX; i++) { + cache_bin_info_init(&tcache_bin_info[i], + cache_bin_ncached_max_get_unsafe(&tcache->bins[i])); } - /* Commit the state last. Above calls check current state. */ - tsd_tcache_enabled_set(tsd, enabled); - tsd_slow_update(tsd); } JEMALLOC_ALWAYS_INLINE bool -tcache_small_bin_disabled(szind_t ind, cache_bin_t *bin) { - assert(ind < SC_NBINS); - bool ret = (cache_bin_info_ncached_max(&tcache_bin_info[ind]) == 0); - if (ret && bin != NULL) { - /* small size class but cache bin disabled. */ - assert(ind >= nhbins); - assert((uintptr_t)(*bin->stack_head) == - cache_bin_preceding_junk); +tcache_bin_disabled(szind_t ind, cache_bin_t *bin, + tcache_slow_t *tcache_slow) { + assert(bin != NULL); + assert(ind < TCACHE_NBINS_MAX); + bool disabled = cache_bin_disabled(bin); + + /* + * If a bin's ind >= nbins or ncached_max == 0, it must be disabled. + * However, when ind < nbins, it could be either enabled + * (ncached_max > 0) or disabled (ncached_max == 0). Similarly, when + * ncached_max > 0, it could be either enabled (ind < nbins) or + * disabled (ind >= nbins). Thus, if a bin is disabled, it has either + * ind >= nbins or ncached_max == 0. If a bin is enabled, it has + * ind < nbins and ncached_max > 0. + */ + unsigned nbins = tcache_nbins_get(tcache_slow); + cache_bin_sz_t ncached_max = cache_bin_ncached_max_get_unsafe(bin); + if (ind >= nbins) { + assert(disabled); + } else { + assert(!disabled || ncached_max == 0); + } + if (ncached_max == 0) { + assert(disabled); + } else { + assert(!disabled || ind >= nbins); + } + if (disabled) { + assert(ind >= nbins || ncached_max == 0); + } else { + assert(ind < nbins && ncached_max > 0); } - return ret; + return disabled; } JEMALLOC_ALWAYS_INLINE void * @@ -59,10 +103,11 @@ tcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache, if (unlikely(arena == NULL)) { return NULL; } - if (unlikely(tcache_small_bin_disabled(binind, bin))) { + if (unlikely(tcache_bin_disabled(binind, bin, + tcache->tcache_slow))) { /* stats and zero are handled directly by the arena. */ return arena_malloc_hard(tsd_tsdn(tsd), arena, size, - binind, zero); + binind, zero, /* slab */ true); } tcache_bin_flush_stashed(tsd, tcache, bin, binind, /* is_small */ true); @@ -92,8 +137,9 @@ tcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size, void *ret; bool tcache_success; - assert(binind >= SC_NBINS && binind < nhbins); cache_bin_t *bin = &tcache->bins[binind]; + assert(binind >= SC_NBINS && + !tcache_bin_disabled(binind, bin, tcache->tcache_slow)); ret = cache_bin_alloc(bin, &tcache_success); assert(tcache_success == (ret != NULL)); if (unlikely(!tcache_success)) { @@ -115,7 +161,7 @@ tcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size, } else { if (unlikely(zero)) { size_t usize = sz_index2size(binind); - assert(usize <= tcache_maxclass); + assert(usize <= tcache_max_get(tcache->tcache_slow)); memset(ret, 0, usize); } @@ -149,12 +195,12 @@ tcache_dalloc_small(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind, } if (unlikely(!cache_bin_dalloc_easy(bin, ptr))) { - if (unlikely(tcache_small_bin_disabled(binind, bin))) { + if (unlikely(tcache_bin_disabled(binind, bin, + tcache->tcache_slow))) { arena_dalloc_small(tsd_tsdn(tsd), ptr); return; } - cache_bin_sz_t max = cache_bin_info_ncached_max( - &tcache_bin_info[binind]); + cache_bin_sz_t max = cache_bin_ncached_max_get(bin); unsigned remain = max >> opt_lg_tcache_flush_small_div; tcache_bin_flush_small(tsd, tcache, bin, binind, remain); bool ret = cache_bin_dalloc_easy(bin, ptr); @@ -166,14 +212,16 @@ JEMALLOC_ALWAYS_INLINE void tcache_dalloc_large(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind, bool slow_path) { - assert(tcache_salloc(tsd_tsdn(tsd), ptr) - > SC_SMALL_MAXCLASS); - assert(tcache_salloc(tsd_tsdn(tsd), ptr) <= tcache_maxclass); + assert(tcache_salloc(tsd_tsdn(tsd), ptr) > SC_SMALL_MAXCLASS); + assert(tcache_salloc(tsd_tsdn(tsd), ptr) <= + tcache_max_get(tcache->tcache_slow)); + assert(!tcache_bin_disabled(binind, &tcache->bins[binind], + tcache->tcache_slow)); cache_bin_t *bin = &tcache->bins[binind]; if (unlikely(!cache_bin_dalloc_easy(bin, ptr))) { - unsigned remain = cache_bin_info_ncached_max( - &tcache_bin_info[binind]) >> opt_lg_tcache_flush_large_div; + unsigned remain = cache_bin_ncached_max_get(bin) >> + opt_lg_tcache_flush_large_div; tcache_bin_flush_large(tsd, tcache, bin, binind, remain); bool ret = cache_bin_dalloc_easy(bin, ptr); assert(ret); @@ -185,13 +233,11 @@ tcaches_get(tsd_t *tsd, unsigned ind) { tcaches_t *elm = &tcaches[ind]; if (unlikely(elm->tcache == NULL)) { malloc_printf(": invalid tcache id (%u).\n", ind); - jemalloc_abort(); + abort(); } else if (unlikely(elm->tcache == TCACHES_ELM_NEED_REINIT)) { elm->tcache = tcache_create_explicit(tsd); } return elm->tcache; } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_TCACHE_INLINES_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_structs.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_structs.h index 9eb16977365..d94099b00f0 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_structs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_structs.h @@ -1,13 +1,12 @@ #ifndef JEMALLOC_INTERNAL_TCACHE_STRUCTS_H #define JEMALLOC_INTERNAL_TCACHE_STRUCTS_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/cache_bin.h" #include "jemalloc/internal/ql.h" #include "jemalloc/internal/sc.h" +#include "jemalloc/internal/tcache_types.h" #include "jemalloc/internal/ticker.h" -#include "jemalloc/internal/tsd_types.h" - -namespace duckdb_jemalloc { /* * The tcache state is split into the slow and hot path data. Each has a @@ -32,6 +31,8 @@ struct tcache_slow_s { /* The arena this tcache is associated with. */ arena_t *arena; + /* The number of bins activated in the tcache. */ + unsigned tcache_nbins; /* Next bin to GC. */ szind_t next_gc_bin; /* For small bins, fill (ncached_max >> lg_fill_div). */ @@ -67,6 +68,4 @@ struct tcaches_s { }; }; -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_TCACHE_STRUCTS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_types.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_types.h index acb8a194c7a..578a199ea61 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_types.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tcache_types.h @@ -1,37 +1,25 @@ #ifndef JEMALLOC_INTERNAL_TCACHE_TYPES_H #define JEMALLOC_INTERNAL_TCACHE_TYPES_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/sc.h" -namespace duckdb_jemalloc { - typedef struct tcache_slow_s tcache_slow_t; typedef struct tcache_s tcache_t; typedef struct tcaches_s tcaches_t; -} // namespace duckdb_jemalloc - -/* - * tcache pointers close to NULL are used to encode state information that is - * used for two purposes: preventing thread caching on a per thread basis and - * cleaning up during thread shutdown. - */ -#define TCACHE_STATE_DISABLED ((tcache_t *)(uintptr_t)1) -#define TCACHE_STATE_REINCARNATED ((tcache_t *)(uintptr_t)2) -#define TCACHE_STATE_PURGATORY ((tcache_t *)(uintptr_t)3) -#define TCACHE_STATE_MAX TCACHE_STATE_PURGATORY - /* Used in TSD static initializer only. Real init in tsd_tcache_data_init(). */ #define TCACHE_ZERO_INITIALIZER {0} -#define TCACHE_SLOW_ZERO_INITIALIZER {0} +#define TCACHE_SLOW_ZERO_INITIALIZER {{0}} /* Used in TSD static initializer only. Will be initialized to opt_tcache. */ #define TCACHE_ENABLED_ZERO_INITIALIZER false /* Used for explicit tcache only. Means flushed but not destroyed. */ +/* NOLINTNEXTLINE(performance-no-int-to-ptr) */ #define TCACHES_ELM_NEED_REINIT ((tcache_t *)(uintptr_t)1) -#define TCACHE_LG_MAXCLASS_LIMIT 23 /* tcache_maxclass = 8M */ +#define TCACHE_LG_MAXCLASS_LIMIT 23 /* tcache_max = 8M */ #define TCACHE_MAXCLASS_LIMIT ((size_t)1 << TCACHE_LG_MAXCLASS_LIMIT) #define TCACHE_NBINS_MAX (SC_NBINS + SC_NGROUP * \ (TCACHE_LG_MAXCLASS_LIMIT - SC_LG_LARGE_MINCLASS) + 1) diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/test_hooks.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/test_hooks.h index 939bcf72433..af3f2755ad1 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/test_hooks.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/test_hooks.h @@ -1,10 +1,10 @@ #ifndef JEMALLOC_INTERNAL_TEST_HOOKS_H #define JEMALLOC_INTERNAL_TEST_HOOKS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" -extern JEMALLOC_EXPORT void (*test_hooks_arena_new_hook)(); -extern JEMALLOC_EXPORT void (*test_hooks_libc_hook)(); +extern JEMALLOC_EXPORT void (*test_hooks_arena_new_hook)(void); +extern JEMALLOC_EXPORT void (*test_hooks_libc_hook)(void); #if defined(JEMALLOC_JET) || defined(JEMALLOC_UNIT_TEST) # define JEMALLOC_TEST_HOOK(fn, hook) ((void)(hook != NULL && (hook(), 0)), fn) @@ -22,6 +22,5 @@ extern JEMALLOC_EXPORT void (*test_hooks_libc_hook)(); # define JEMALLOC_TEST_HOOK(fn, hook) fn #endif -} // namespace duckdb_jemalloc #endif /* JEMALLOC_INTERNAL_TEST_HOOKS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/thread_event.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/thread_event.h index f58ebf4cb23..46c57ed5644 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/thread_event.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/thread_event.h @@ -1,10 +1,9 @@ #ifndef JEMALLOC_INTERNAL_THREAD_EVENT_H #define JEMALLOC_INTERNAL_THREAD_EVENT_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/tsd.h" -namespace duckdb_jemalloc { - /* "te" is short for "thread_event" */ /* @@ -300,6 +299,4 @@ thread_alloc_event(tsd_t *tsd, size_t usize) { te_event_advance(tsd, usize, true); } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_THREAD_EVENT_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/ticker.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/ticker.h index 843d8fb9719..dca9bd10512 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/ticker.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/ticker.h @@ -1,11 +1,10 @@ #ifndef JEMALLOC_INTERNAL_TICKER_H #define JEMALLOC_INTERNAL_TICKER_H +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/prng.h" #include "jemalloc/internal/util.h" -namespace duckdb_jemalloc { - /** * A ticker makes it easy to count-down events until some limit. You * ticker_init the ticker to trigger every nticks events. You then notify it @@ -59,23 +58,27 @@ ticker_read(const ticker_t *ticker) { JEMALLOC_NOINLINE #endif static bool -ticker_fixup(ticker_t *ticker) { +ticker_fixup(ticker_t *ticker, bool delay_trigger) { + if (delay_trigger) { + ticker->tick = 0; + return false; + } ticker->tick = ticker->nticks; return true; } static inline bool -ticker_ticks(ticker_t *ticker, int32_t nticks) { +ticker_ticks(ticker_t *ticker, int32_t nticks, bool delay_trigger) { ticker->tick -= nticks; if (unlikely(ticker->tick < 0)) { - return ticker_fixup(ticker); + return ticker_fixup(ticker, delay_trigger); } return false; } static inline bool -ticker_tick(ticker_t *ticker) { - return ticker_ticks(ticker, 1); +ticker_tick(ticker_t *ticker, bool delay_trigger) { + return ticker_ticks(ticker, 1, delay_trigger); } /* @@ -152,28 +155,35 @@ ticker_geom_read(const ticker_geom_t *ticker) { JEMALLOC_NOINLINE #endif static bool -ticker_geom_fixup(ticker_geom_t *ticker, uint64_t *prng_state) { +ticker_geom_fixup(ticker_geom_t *ticker, uint64_t *prng_state, + bool delay_trigger) { + if (delay_trigger) { + ticker->tick = 0; + return false; + } + uint64_t idx = prng_lg_range_u64(prng_state, TICKER_GEOM_NBITS); ticker->tick = (uint32_t)( (uint64_t)ticker->nticks * (uint64_t)ticker_geom_table[idx] / (uint64_t)TICKER_GEOM_MUL); + return true; } static inline bool -ticker_geom_ticks(ticker_geom_t *ticker, uint64_t *prng_state, int32_t nticks) { +ticker_geom_ticks(ticker_geom_t *ticker, uint64_t *prng_state, int32_t nticks, + bool delay_trigger) { ticker->tick -= nticks; if (unlikely(ticker->tick < 0)) { - return ticker_geom_fixup(ticker, prng_state); + return ticker_geom_fixup(ticker, prng_state, delay_trigger); } return false; } static inline bool -ticker_geom_tick(ticker_geom_t *ticker, uint64_t *prng_state) { - return ticker_geom_ticks(ticker, prng_state, 1); +ticker_geom_tick(ticker_geom_t *ticker, uint64_t *prng_state, + bool delay_trigger) { + return ticker_geom_ticks(ticker, prng_state, 1, delay_trigger); } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_TICKER_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd.h index af18ef3a901..4f22dcff16e 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd.h @@ -1,312 +1,13 @@ #ifndef JEMALLOC_INTERNAL_TSD_H #define JEMALLOC_INTERNAL_TSD_H -#include "jemalloc/internal/activity_callback.h" -#include "jemalloc/internal/arena_types.h" -#include "jemalloc/internal/assert.h" -#include "jemalloc/internal/bin_types.h" -#include "jemalloc/internal/jemalloc_internal_externs.h" -#include "jemalloc/internal/peak.h" -#include "jemalloc/internal/prof_types.h" -#include "jemalloc/internal/ql.h" -#include "jemalloc/internal/rtree_tsd.h" -#include "jemalloc/internal/tcache_types.h" -#include "jemalloc/internal/tcache_structs.h" -#include "jemalloc/internal/util.h" -#include "jemalloc/internal/witness.h" -#include "jemalloc/internal/tsd_types.h" - -namespace duckdb_jemalloc { - -/* - * Thread-Specific-Data layout - * - * At least some thread-local data gets touched on the fast-path of almost all - * malloc operations. But much of it is only necessary down slow-paths, or - * testing. We want to colocate the fast-path data so that it can live on the - * same cacheline if possible. So we define three tiers of hotness: - * TSD_DATA_FAST: Touched on the alloc/dalloc fast paths. - * TSD_DATA_SLOW: Touched down slow paths. "Slow" here is sort of general; - * there are "semi-slow" paths like "not a sized deallocation, but can still - * live in the tcache". We'll want to keep these closer to the fast-path - * data. - * TSD_DATA_SLOWER: Only touched in test or debug modes, or not touched at all. - * - * An additional concern is that the larger tcache bins won't be used (we have a - * bin per size class, but by default only cache relatively small objects). So - * the earlier bins are in the TSD_DATA_FAST tier, but the later ones are in the - * TSD_DATA_SLOWER tier. - * - * As a result of all this, we put the slow data first, then the fast data, then - * the slower data, while keeping the tcache as the last element of the fast - * data (so that the fast -> slower transition happens midway through the - * tcache). While we don't yet play alignment tricks to guarantee it, this - * increases our odds of getting some cache/page locality on fast paths. - */ - -#ifdef JEMALLOC_JET -typedef void (*test_callback_t)(int *); -# define MALLOC_TSD_TEST_DATA_INIT 0x72b65c10 -# define MALLOC_TEST_TSD \ - O(test_data, int, int) \ - O(test_callback, test_callback_t, int) -# define MALLOC_TEST_TSD_INITIALIZER , MALLOC_TSD_TEST_DATA_INIT, NULL -#else -# define MALLOC_TEST_TSD -# define MALLOC_TEST_TSD_INITIALIZER -#endif - -typedef ql_elm(tsd_t) tsd_link_t; - -/* O(name, type, nullable type) */ -#define TSD_DATA_SLOW \ - O(tcache_enabled, bool, bool) \ - O(reentrancy_level, int8_t, int8_t) \ - O(thread_allocated_last_event, uint64_t, uint64_t) \ - O(thread_allocated_next_event, uint64_t, uint64_t) \ - O(thread_deallocated_last_event, uint64_t, uint64_t) \ - O(thread_deallocated_next_event, uint64_t, uint64_t) \ - O(tcache_gc_event_wait, uint64_t, uint64_t) \ - O(tcache_gc_dalloc_event_wait, uint64_t, uint64_t) \ - O(prof_sample_event_wait, uint64_t, uint64_t) \ - O(prof_sample_last_event, uint64_t, uint64_t) \ - O(stats_interval_event_wait, uint64_t, uint64_t) \ - O(stats_interval_last_event, uint64_t, uint64_t) \ - O(peak_alloc_event_wait, uint64_t, uint64_t) \ - O(peak_dalloc_event_wait, uint64_t, uint64_t) \ - O(prof_tdata, prof_tdata_t *, prof_tdata_t *) \ - O(prng_state, uint64_t, uint64_t) \ - O(san_extents_until_guard_small, uint64_t, uint64_t) \ - O(san_extents_until_guard_large, uint64_t, uint64_t) \ - O(iarena, arena_t *, arena_t *) \ - O(arena, arena_t *, arena_t *) \ - O(arena_decay_ticker, ticker_geom_t, ticker_geom_t) \ - O(sec_shard, uint8_t, uint8_t) \ - O(binshards, tsd_binshards_t, tsd_binshards_t)\ - O(tsd_link, tsd_link_t, tsd_link_t) \ - O(in_hook, bool, bool) \ - O(peak, peak_t, peak_t) \ - O(activity_callback_thunk, activity_callback_thunk_t, \ - activity_callback_thunk_t) \ - O(tcache_slow, tcache_slow_t, tcache_slow_t) \ - O(rtree_ctx, rtree_ctx_t, rtree_ctx_t) - -#define TSD_DATA_SLOW_INITIALIZER \ - /* tcache_enabled */ TCACHE_ENABLED_ZERO_INITIALIZER, \ - /* reentrancy_level */ 0, \ - /* thread_allocated_last_event */ 0, \ - /* thread_allocated_next_event */ 0, \ - /* thread_deallocated_last_event */ 0, \ - /* thread_deallocated_next_event */ 0, \ - /* tcache_gc_event_wait */ 0, \ - /* tcache_gc_dalloc_event_wait */ 0, \ - /* prof_sample_event_wait */ 0, \ - /* prof_sample_last_event */ 0, \ - /* stats_interval_event_wait */ 0, \ - /* stats_interval_last_event */ 0, \ - /* peak_alloc_event_wait */ 0, \ - /* peak_dalloc_event_wait */ 0, \ - /* prof_tdata */ NULL, \ - /* prng_state */ 0, \ - /* san_extents_until_guard_small */ 0, \ - /* san_extents_until_guard_large */ 0, \ - /* iarena */ NULL, \ - /* arena */ NULL, \ - /* arena_decay_ticker */ \ - TICKER_GEOM_INIT(ARENA_DECAY_NTICKS_PER_UPDATE), \ - /* sec_shard */ (uint8_t)-1, \ - /* binshards */ TSD_BINSHARDS_ZERO_INITIALIZER, \ - /* tsd_link */ {NULL}, \ - /* in_hook */ false, \ - /* peak */ PEAK_INITIALIZER, \ - /* activity_callback_thunk */ \ - ACTIVITY_CALLBACK_THUNK_INITIALIZER, \ - /* tcache_slow */ TCACHE_SLOW_ZERO_INITIALIZER, \ - /* rtree_ctx */ RTREE_CTX_INITIALIZER, - -/* O(name, type, nullable type) */ -#define TSD_DATA_FAST \ - O(thread_allocated, uint64_t, uint64_t) \ - O(thread_allocated_next_event_fast, uint64_t, uint64_t) \ - O(thread_deallocated, uint64_t, uint64_t) \ - O(thread_deallocated_next_event_fast, uint64_t, uint64_t) \ - O(tcache, tcache_t, tcache_t) - -#define TSD_DATA_FAST_INITIALIZER \ - /* thread_allocated */ 0, \ - /* thread_allocated_next_event_fast */ 0, \ - /* thread_deallocated */ 0, \ - /* thread_deallocated_next_event_fast */ 0, \ - /* tcache */ TCACHE_ZERO_INITIALIZER, - -/* O(name, type, nullable type) */ -#define TSD_DATA_SLOWER \ - O(witness_tsd, witness_tsd_t, witness_tsdn_t) \ - MALLOC_TEST_TSD - -#define TSD_DATA_SLOWER_INITIALIZER \ - /* witness */ WITNESS_TSD_INITIALIZER \ - /* test data */ MALLOC_TEST_TSD_INITIALIZER - - -#define TSD_INITIALIZER { \ - TSD_DATA_SLOW_INITIALIZER \ - /* state */ ATOMIC_INIT(tsd_state_uninitialized), \ - TSD_DATA_FAST_INITIALIZER \ - TSD_DATA_SLOWER_INITIALIZER \ -} - -#if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32) -void _malloc_tsd_cleanup_register(bool (*f)(void)); -#endif - -void *malloc_tsd_malloc(size_t size); -void malloc_tsd_dalloc(void *wrapper); -tsd_t *malloc_tsd_boot0(void); -void malloc_tsd_boot1(void); -void tsd_cleanup(void *arg); -tsd_t *tsd_fetch_slow(tsd_t *tsd, bool internal); -void tsd_state_set(tsd_t *tsd, uint8_t new_state); -void tsd_slow_update(tsd_t *tsd); -void tsd_prefork(tsd_t *tsd); -void tsd_postfork_parent(tsd_t *tsd); -void tsd_postfork_child(tsd_t *tsd); - -/* - * Call ..._inc when your module wants to take all threads down the slow paths, - * and ..._dec when it no longer needs to. - */ -void tsd_global_slow_inc(tsdn_t *tsdn); -void tsd_global_slow_dec(tsdn_t *tsdn); -bool tsd_global_slow(); - -enum { - /* Common case --> jnz. */ - tsd_state_nominal = 0, - /* Initialized but on slow path. */ - tsd_state_nominal_slow = 1, - /* - * Some thread has changed global state in such a way that all nominal - * threads need to recompute their fast / slow status the next time they - * get a chance. - * - * Any thread can change another thread's status *to* recompute, but - * threads are the only ones who can change their status *from* - * recompute. - */ - tsd_state_nominal_recompute = 2, - /* - * The above nominal states should be lower values. We use - * tsd_nominal_max to separate nominal states from threads in the - * process of being born / dying. - */ - tsd_state_nominal_max = 2, - - /* - * A thread might free() during its death as its only allocator action; - * in such scenarios, we need tsd, but set up in such a way that no - * cleanup is necessary. - */ - tsd_state_minimal_initialized = 3, - /* States during which we know we're in thread death. */ - tsd_state_purgatory = 4, - tsd_state_reincarnated = 5, - /* - * What it says on the tin; tsd that hasn't been initialized. Note - * that even when the tsd struct lives in TLS, when need to keep track - * of stuff like whether or not our pthread destructors have been - * scheduled, so this really truly is different than the nominal state. - */ - tsd_state_uninitialized = 6 -}; - -/* - * Some TSD accesses can only be done in a nominal state. To enforce this, we - * wrap TSD member access in a function that asserts on TSD state, and mangle - * field names to prevent touching them accidentally. - */ -#define TSD_MANGLE(n) cant_access_tsd_items_directly_use_a_getter_or_setter_##n - -#ifdef JEMALLOC_U8_ATOMICS -# define tsd_state_t atomic_u8_t -# define tsd_atomic_load atomic_load_u8 -# define tsd_atomic_store atomic_store_u8 -# define tsd_atomic_exchange atomic_exchange_u8 -#else -# define tsd_state_t atomic_u32_t -# define tsd_atomic_load atomic_load_u32 -# define tsd_atomic_store atomic_store_u32 -# define tsd_atomic_exchange atomic_exchange_u32 -#endif - -/* The actual tsd. */ -struct tsd_s { - /* - * The contents should be treated as totally opaque outside the tsd - * module. Access any thread-local state through the getters and - * setters below. - */ - -#define O(n, t, nt) \ - t TSD_MANGLE(n); - - TSD_DATA_SLOW - /* - * We manually limit the state to just a single byte. Unless the 8-bit - * atomics are unavailable (which is rare). - */ - tsd_state_t state; - TSD_DATA_FAST - TSD_DATA_SLOWER -#undef O -}; - -JEMALLOC_ALWAYS_INLINE uint8_t -tsd_state_get(tsd_t *tsd) { - /* - * This should be atomic. Unfortunately, compilers right now can't tell - * that this can be done as a memory comparison, and forces a load into - * a register that hurts fast-path performance. - */ - /* return atomic_load_u8(&tsd->state, ATOMIC_RELAXED); */ - return *(uint8_t *)&tsd->state; -} - -/* - * Wrapper around tsd_t that makes it possible to avoid implicit conversion - * between tsd_t and tsdn_t, where tsdn_t is "nullable" and has to be - * explicitly converted to tsd_t, which is non-nullable. - */ -struct tsdn_s { - tsd_t tsd; -}; -#define TSDN_NULL ((tsdn_t *)0) -JEMALLOC_ALWAYS_INLINE tsdn_t * -tsd_tsdn(tsd_t *tsd) { - return (tsdn_t *)tsd; -} - -JEMALLOC_ALWAYS_INLINE bool -tsdn_null(const tsdn_t *tsdn) { - return tsdn == NULL; -} - -JEMALLOC_ALWAYS_INLINE tsd_t * -tsdn_tsd(tsdn_t *tsdn) { - assert(!tsdn_null(tsdn)); - - return &tsdn->tsd; -} - /* * We put the platform-specific data declarations and inlines into their own * header files to avoid cluttering this file. They define tsd_boot0, * tsd_boot1, tsd_boot, tsd_booted_get, tsd_get_allocates, tsd_get, and tsd_set. */ - -} // namespace duckdb_jemalloc - #ifdef JEMALLOC_MALLOC_THREAD_CLEANUP +#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/tsd_malloc_thread_cleanup.h" #elif (defined(JEMALLOC_TLS)) #include "jemalloc/internal/tsd_tls.h" @@ -316,8 +17,6 @@ tsdn_tsd(tsdn_t *tsdn) { #include "jemalloc/internal/tsd_generic.h" #endif -namespace duckdb_jemalloc { - /* * tsd_foop_get_unsafe(tsd) returns a pointer to the thread-local instance of * foo. This omits some safety checks, and so can be used during tsd @@ -523,6 +222,4 @@ tsd_post_reentrancy_raw(tsd_t *tsd) { } } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_TSD_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_generic.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_generic.h index eb996b36a54..aa8042a4e46 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_generic.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_generic.h @@ -3,7 +3,10 @@ #endif #define JEMALLOC_INTERNAL_TSD_GENERIC_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/ql.h" +#include "jemalloc/internal/tsd_internals.h" +#include "jemalloc/internal/tsd_types.h" typedef struct tsd_init_block_s tsd_init_block_t; struct tsd_init_block_s { @@ -43,7 +46,7 @@ tsd_cleanup_wrapper(void *arg) { { malloc_write(": Error setting TSD\n"); if (opt_abort) { - jemalloc_abort(); + abort(); } } return; @@ -59,7 +62,7 @@ tsd_wrapper_set(tsd_wrapper_t *wrapper) { } if (pthread_setspecific(tsd_tsd, (void *)wrapper) != 0) { malloc_write(": Error setting TSD\n"); - jemalloc_abort(); + abort(); } } @@ -85,7 +88,7 @@ tsd_wrapper_get(bool init) { block.data = (void *)wrapper; if (wrapper == NULL) { malloc_write(": Error allocating TSD\n"); - jemalloc_abort(); + abort(); } else { wrapper->initialized = false; JEMALLOC_DIAGNOSTIC_PUSH @@ -126,7 +129,7 @@ tsd_boot1(void) { wrapper = (tsd_wrapper_t *)malloc_tsd_malloc(sizeof(tsd_wrapper_t)); if (wrapper == NULL) { malloc_write(": Error allocating TSD\n"); - jemalloc_abort(); + abort(); } tsd_boot_wrapper.initialized = false; tsd_cleanup(&tsd_boot_wrapper.val); @@ -182,5 +185,3 @@ tsd_set(tsd_t *val) { } wrapper->initialized = true; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_internals.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_internals.h new file mode 100644 index 00000000000..439f1d10c4b --- /dev/null +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_internals.h @@ -0,0 +1,304 @@ +#ifdef JEMALLOC_INTERNAL_TSD_INTERNALS_H +#error This file should be included only once, by one of tsd_malloc_thread_cleanup.h, tsd_tls.h, tsd_generic.h, or tsd_win.h +#endif +#define JEMALLOC_INTERNAL_TSD_INTERNALS_H + +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/activity_callback.h" +#include "jemalloc/internal/arena_types.h" +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/bin_types.h" +#include "jemalloc/internal/jemalloc_internal_externs.h" +#include "jemalloc/internal/peak.h" +#include "jemalloc/internal/prof_types.h" +#include "jemalloc/internal/ql.h" +#include "jemalloc/internal/rtree_tsd.h" +#include "jemalloc/internal/tcache_structs.h" +#include "jemalloc/internal/tcache_types.h" +#include "jemalloc/internal/tsd_types.h" +#include "jemalloc/internal/util.h" +#include "jemalloc/internal/witness.h" + +/* + * Thread-Specific-Data layout + * + * At least some thread-local data gets touched on the fast-path of almost all + * malloc operations. But much of it is only necessary down slow-paths, or + * testing. We want to colocate the fast-path data so that it can live on the + * same cacheline if possible. So we define three tiers of hotness: + * TSD_DATA_FAST: Touched on the alloc/dalloc fast paths. + * TSD_DATA_SLOW: Touched down slow paths. "Slow" here is sort of general; + * there are "semi-slow" paths like "not a sized deallocation, but can still + * live in the tcache". We'll want to keep these closer to the fast-path + * data. + * TSD_DATA_SLOWER: Only touched in test or debug modes, or not touched at all. + * + * An additional concern is that the larger tcache bins won't be used (we have a + * bin per size class, but by default only cache relatively small objects). So + * the earlier bins are in the TSD_DATA_FAST tier, but the later ones are in the + * TSD_DATA_SLOWER tier. + * + * As a result of all this, we put the slow data first, then the fast data, then + * the slower data, while keeping the tcache as the last element of the fast + * data (so that the fast -> slower transition happens midway through the + * tcache). While we don't yet play alignment tricks to guarantee it, this + * increases our odds of getting some cache/page locality on fast paths. + */ + +#ifdef JEMALLOC_JET +typedef void (*test_callback_t)(int *); +# define MALLOC_TSD_TEST_DATA_INIT 0x72b65c10 +# define MALLOC_TEST_TSD \ + O(test_data, int, int) \ + O(test_callback, test_callback_t, int) +# define MALLOC_TEST_TSD_INITIALIZER , MALLOC_TSD_TEST_DATA_INIT, NULL +#else +# define MALLOC_TEST_TSD +# define MALLOC_TEST_TSD_INITIALIZER +#endif + +typedef ql_elm(tsd_t) tsd_link_t; + +/* O(name, type, nullable type) */ +#define TSD_DATA_SLOW \ + O(tcache_enabled, bool, bool) \ + O(reentrancy_level, int8_t, int8_t) \ + O(min_init_state_nfetched, uint8_t, uint8_t) \ + O(thread_allocated_last_event, uint64_t, uint64_t) \ + O(thread_allocated_next_event, uint64_t, uint64_t) \ + O(thread_deallocated_last_event, uint64_t, uint64_t) \ + O(thread_deallocated_next_event, uint64_t, uint64_t) \ + O(tcache_gc_event_wait, uint64_t, uint64_t) \ + O(tcache_gc_dalloc_event_wait, uint64_t, uint64_t) \ + O(prof_sample_event_wait, uint64_t, uint64_t) \ + O(prof_sample_last_event, uint64_t, uint64_t) \ + O(stats_interval_event_wait, uint64_t, uint64_t) \ + O(stats_interval_last_event, uint64_t, uint64_t) \ + O(peak_alloc_event_wait, uint64_t, uint64_t) \ + O(peak_dalloc_event_wait, uint64_t, uint64_t) \ + O(prof_tdata, prof_tdata_t *, prof_tdata_t *) \ + O(prng_state, uint64_t, uint64_t) \ + O(san_extents_until_guard_small, uint64_t, uint64_t) \ + O(san_extents_until_guard_large, uint64_t, uint64_t) \ + O(iarena, arena_t *, arena_t *) \ + O(arena, arena_t *, arena_t *) \ + O(arena_decay_ticker, ticker_geom_t, ticker_geom_t) \ + O(sec_shard, uint8_t, uint8_t) \ + O(binshards, tsd_binshards_t, tsd_binshards_t)\ + O(tsd_link, tsd_link_t, tsd_link_t) \ + O(in_hook, bool, bool) \ + O(peak, peak_t, peak_t) \ + O(activity_callback_thunk, activity_callback_thunk_t, \ + activity_callback_thunk_t) \ + O(tcache_slow, tcache_slow_t, tcache_slow_t) \ + O(rtree_ctx, rtree_ctx_t, rtree_ctx_t) + +#define TSD_DATA_SLOW_INITIALIZER \ + /* tcache_enabled */ TCACHE_ENABLED_ZERO_INITIALIZER, \ + /* reentrancy_level */ 0, \ + /* min_init_state_nfetched */ 0, \ + /* thread_allocated_last_event */ 0, \ + /* thread_allocated_next_event */ 0, \ + /* thread_deallocated_last_event */ 0, \ + /* thread_deallocated_next_event */ 0, \ + /* tcache_gc_event_wait */ 0, \ + /* tcache_gc_dalloc_event_wait */ 0, \ + /* prof_sample_event_wait */ 0, \ + /* prof_sample_last_event */ 0, \ + /* stats_interval_event_wait */ 0, \ + /* stats_interval_last_event */ 0, \ + /* peak_alloc_event_wait */ 0, \ + /* peak_dalloc_event_wait */ 0, \ + /* prof_tdata */ NULL, \ + /* prng_state */ 0, \ + /* san_extents_until_guard_small */ 0, \ + /* san_extents_until_guard_large */ 0, \ + /* iarena */ NULL, \ + /* arena */ NULL, \ + /* arena_decay_ticker */ \ + TICKER_GEOM_INIT(ARENA_DECAY_NTICKS_PER_UPDATE), \ + /* sec_shard */ (uint8_t)-1, \ + /* binshards */ TSD_BINSHARDS_ZERO_INITIALIZER, \ + /* tsd_link */ {NULL}, \ + /* in_hook */ false, \ + /* peak */ PEAK_INITIALIZER, \ + /* activity_callback_thunk */ \ + ACTIVITY_CALLBACK_THUNK_INITIALIZER, \ + /* tcache_slow */ TCACHE_SLOW_ZERO_INITIALIZER, \ + /* rtree_ctx */ RTREE_CTX_INITIALIZER, + +/* O(name, type, nullable type) */ +#define TSD_DATA_FAST \ + O(thread_allocated, uint64_t, uint64_t) \ + O(thread_allocated_next_event_fast, uint64_t, uint64_t) \ + O(thread_deallocated, uint64_t, uint64_t) \ + O(thread_deallocated_next_event_fast, uint64_t, uint64_t) \ + O(tcache, tcache_t, tcache_t) + +#define TSD_DATA_FAST_INITIALIZER \ + /* thread_allocated */ 0, \ + /* thread_allocated_next_event_fast */ 0, \ + /* thread_deallocated */ 0, \ + /* thread_deallocated_next_event_fast */ 0, \ + /* tcache */ TCACHE_ZERO_INITIALIZER, + +/* O(name, type, nullable type) */ +#define TSD_DATA_SLOWER \ + O(witness_tsd, witness_tsd_t, witness_tsdn_t) \ + MALLOC_TEST_TSD + +#define TSD_DATA_SLOWER_INITIALIZER \ + /* witness */ WITNESS_TSD_INITIALIZER \ + /* test data */ MALLOC_TEST_TSD_INITIALIZER + + +#define TSD_INITIALIZER { \ + TSD_DATA_SLOW_INITIALIZER \ + /* state */ ATOMIC_INIT(tsd_state_uninitialized), \ + TSD_DATA_FAST_INITIALIZER \ + TSD_DATA_SLOWER_INITIALIZER \ +} + +#if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32) +void _malloc_tsd_cleanup_register(bool (*f)(void)); +#endif + +void *malloc_tsd_malloc(size_t size); +void malloc_tsd_dalloc(void *wrapper); +tsd_t *malloc_tsd_boot0(void); +void malloc_tsd_boot1(void); +void tsd_cleanup(void *arg); +tsd_t *tsd_fetch_slow(tsd_t *tsd, bool minimal); +void tsd_state_set(tsd_t *tsd, uint8_t new_state); +void tsd_slow_update(tsd_t *tsd); +void tsd_prefork(tsd_t *tsd); +void tsd_postfork_parent(tsd_t *tsd); +void tsd_postfork_child(tsd_t *tsd); + +/* + * Call ..._inc when your module wants to take all threads down the slow paths, + * and ..._dec when it no longer needs to. + */ +void tsd_global_slow_inc(tsdn_t *tsdn); +void tsd_global_slow_dec(tsdn_t *tsdn); +bool tsd_global_slow(void); + +#define TSD_MIN_INIT_STATE_MAX_FETCHED (128) + +enum { + /* Common case --> jnz. */ + tsd_state_nominal = 0, + /* Initialized but on slow path. */ + tsd_state_nominal_slow = 1, + /* + * Some thread has changed global state in such a way that all nominal + * threads need to recompute their fast / slow status the next time they + * get a chance. + * + * Any thread can change another thread's status *to* recompute, but + * threads are the only ones who can change their status *from* + * recompute. + */ + tsd_state_nominal_recompute = 2, + /* + * The above nominal states should be lower values. We use + * tsd_nominal_max to separate nominal states from threads in the + * process of being born / dying. + */ + tsd_state_nominal_max = 2, + + /* + * A thread might free() during its death as its only allocator action; + * in such scenarios, we need tsd, but set up in such a way that no + * cleanup is necessary. + */ + tsd_state_minimal_initialized = 3, + /* States during which we know we're in thread death. */ + tsd_state_purgatory = 4, + tsd_state_reincarnated = 5, + /* + * What it says on the tin; tsd that hasn't been initialized. Note + * that even when the tsd struct lives in TLS, when need to keep track + * of stuff like whether or not our pthread destructors have been + * scheduled, so this really truly is different than the nominal state. + */ + tsd_state_uninitialized = 6 +}; + +/* + * Some TSD accesses can only be done in a nominal state. To enforce this, we + * wrap TSD member access in a function that asserts on TSD state, and mangle + * field names to prevent touching them accidentally. + */ +#define TSD_MANGLE(n) cant_access_tsd_items_directly_use_a_getter_or_setter_##n + +#ifdef JEMALLOC_U8_ATOMICS +# define tsd_state_t atomic_u8_t +# define tsd_atomic_load atomic_load_u8 +# define tsd_atomic_store atomic_store_u8 +# define tsd_atomic_exchange atomic_exchange_u8 +#else +# define tsd_state_t atomic_u32_t +# define tsd_atomic_load atomic_load_u32 +# define tsd_atomic_store atomic_store_u32 +# define tsd_atomic_exchange atomic_exchange_u32 +#endif + +/* The actual tsd. */ +struct tsd_s { + /* + * The contents should be treated as totally opaque outside the tsd + * module. Access any thread-local state through the getters and + * setters below. + */ + +#define O(n, t, nt) \ + t TSD_MANGLE(n); + + TSD_DATA_SLOW + /* + * We manually limit the state to just a single byte. Unless the 8-bit + * atomics are unavailable (which is rare). + */ + tsd_state_t state; + TSD_DATA_FAST + TSD_DATA_SLOWER +#undef O +}; + +JEMALLOC_ALWAYS_INLINE uint8_t +tsd_state_get(tsd_t *tsd) { + /* + * This should be atomic. Unfortunately, compilers right now can't tell + * that this can be done as a memory comparison, and forces a load into + * a register that hurts fast-path performance. + */ + /* return atomic_load_u8(&tsd->state, ATOMIC_RELAXED); */ + return *(uint8_t *)&tsd->state; +} + +/* + * Wrapper around tsd_t that makes it possible to avoid implicit conversion + * between tsd_t and tsdn_t, where tsdn_t is "nullable" and has to be + * explicitly converted to tsd_t, which is non-nullable. + */ +struct tsdn_s { + tsd_t tsd; +}; +#define TSDN_NULL ((tsdn_t *)0) +JEMALLOC_ALWAYS_INLINE tsdn_t * +tsd_tsdn(tsd_t *tsd) { + return (tsdn_t *)tsd; +} + +JEMALLOC_ALWAYS_INLINE bool +tsdn_null(const tsdn_t *tsdn) { + return tsdn == NULL; +} + +JEMALLOC_ALWAYS_INLINE tsd_t * +tsdn_tsd(tsdn_t *tsdn) { + assert(!tsdn_null(tsdn)); + + return &tsdn->tsd; +} diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h index a4d0aae3d03..fb9ea1b452d 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h @@ -3,7 +3,9 @@ #endif #define JEMALLOC_INTERNAL_TSD_MALLOC_THREAD_CLEANUP_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/tsd_internals.h" +#include "jemalloc/internal/tsd_types.h" #define JEMALLOC_TSD_TYPE_ATTR(type) __thread type JEMALLOC_TLS_MODEL @@ -61,5 +63,3 @@ tsd_set(tsd_t *val) { } tsd_initialized = true; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_tls.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_tls.h index a6ae1838317..5e5a6e5e3c2 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_tls.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_tls.h @@ -3,7 +3,9 @@ #endif #define JEMALLOC_INTERNAL_TSD_TLS_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/tsd_internals.h" +#include "jemalloc/internal/tsd_types.h" #define JEMALLOC_TSD_TYPE_ATTR(type) __thread type JEMALLOC_TLS_MODEL @@ -56,9 +58,7 @@ tsd_set(tsd_t *val) { if (pthread_setspecific(tsd_tsd, (void *)(&tsd_tls)) != 0) { malloc_write(": Error setting tsd.\n"); if (opt_abort) { - jemalloc_abort(); + abort(); } } } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_types.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_types.h index 601e384d0de..73bbe486e27 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_types.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_types.h @@ -1,14 +1,12 @@ #ifndef JEMALLOC_INTERNAL_TSD_TYPES_H #define JEMALLOC_INTERNAL_TSD_TYPES_H -namespace duckdb_jemalloc { - #define MALLOC_TSD_CLEANUPS_MAX 4 +#include "jemalloc/internal/jemalloc_preamble.h" + typedef struct tsd_s tsd_t; typedef struct tsdn_s tsdn_t; typedef bool (*malloc_tsd_cleanup_t)(void); -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_TSD_TYPES_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_win.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_win.h index a7ab91d443b..8ec7eda729e 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_win.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/tsd_win.h @@ -3,7 +3,9 @@ #endif #define JEMALLOC_INTERNAL_TSD_WIN_H -namespace duckdb_jemalloc { +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/tsd_internals.h" +#include "jemalloc/internal/tsd_types.h" typedef struct { bool initialized; @@ -41,7 +43,7 @@ JEMALLOC_ALWAYS_INLINE void tsd_wrapper_set(tsd_wrapper_t *wrapper) { if (!TlsSetValue(tsd_tsd, (void *)wrapper)) { malloc_write(": Error setting TSD\n"); - jemalloc_abort(); + abort(); } } @@ -56,7 +58,7 @@ tsd_wrapper_get(bool init) { malloc_tsd_malloc(sizeof(tsd_wrapper_t)); if (wrapper == NULL) { malloc_write(": Error allocating TSD\n"); - jemalloc_abort(); + abort(); } else { wrapper->initialized = false; /* MSVC is finicky about aggregate initialization. */ @@ -87,7 +89,7 @@ tsd_boot1(void) { malloc_tsd_malloc(sizeof(tsd_wrapper_t)); if (wrapper == NULL) { malloc_write(": Error allocating TSD\n"); - jemalloc_abort(); + abort(); } tsd_boot_wrapper.initialized = false; tsd_cleanup(&tsd_boot_wrapper.val); @@ -139,5 +141,3 @@ tsd_set(tsd_t *val) { } wrapper->initialized = true; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/typed_list.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/typed_list.h index 5478ffcde50..6535055a1ec 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/typed_list.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/typed_list.h @@ -1,8 +1,6 @@ #ifndef JEMALLOC_INTERNAL_TYPED_LIST_H #define JEMALLOC_INTERNAL_TYPED_LIST_H -namespace duckdb_jemalloc { - /* * This wraps the ql module to implement a list class in a way that's a little * bit easier to use; it handles ql_elm_new calls and provides type safety. @@ -54,6 +52,4 @@ list_type##_concat(list_type##_t *list_a, list_type##_t *list_b) { \ ql_concat(&list_a->head, &list_b->head, linkage); \ } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_TYPED_LIST_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/util.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/util.h index 92926e37987..f40350951c9 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/util.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/util.h @@ -1,12 +1,10 @@ #ifndef JEMALLOC_INTERNAL_UTIL_H #define JEMALLOC_INTERNAL_UTIL_H -#define UTIL_INLINE static inline - -#include "jemalloc_internal_defs.h" -#include "jemalloc_internal_macros.h" +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_types.h" -namespace duckdb_jemalloc { +#define UTIL_INLINE static inline /* Junk fill patterns. */ #ifndef JEMALLOC_ALLOC_JUNK @@ -67,12 +65,19 @@ get_errno(void) { #endif } -JEMALLOC_ALWAYS_INLINE void -util_assume(bool b) { - if (!b) { - unreachable(); - } -} +#ifdef _MSC_VER +#define util_assume __assume +#elif defined(__clang__) && (__clang_major__ > 3 || \ + (__clang_major__ == 3 && __clang_minor__ >= 6)) +#define util_assume __builtin_assume +#else +#define util_assume(expr) \ + do { \ + if (!(expr)) { \ + unreachable(); \ + } \ + } while(0) +#endif /* ptr should be valid. */ JEMALLOC_ALWAYS_INLINE void @@ -112,19 +117,25 @@ util_prefetch_write(void *ptr) { JEMALLOC_ALWAYS_INLINE void util_prefetch_read_range(void *ptr, size_t sz) { for (size_t i = 0; i < sz; i += CACHELINE) { - util_prefetch_read((void *)((uintptr_t)ptr + i)); + util_prefetch_read((void *)((byte_t *)ptr + i)); } } JEMALLOC_ALWAYS_INLINE void util_prefetch_write_range(void *ptr, size_t sz) { for (size_t i = 0; i < sz; i += CACHELINE) { - util_prefetch_write((void *)((uintptr_t)ptr + i)); + util_prefetch_write((void *)((byte_t *)ptr + i)); } } #undef UTIL_INLINE -} // namespace duckdb_jemalloc - +/* + * Reads the settings in the following format: + * key1-key2:value|key3-key4:value|... + * Note it does not handle the ending '\0'. + */ +bool +multi_setting_parse_next(const char **setting_segment_cur, size_t *len_left, + size_t *key_start, size_t *key_end, size_t *value); #endif /* JEMALLOC_INTERNAL_UTIL_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/internal/witness.h b/extension/jemalloc/jemalloc/include/jemalloc/internal/witness.h index b6a1b017aa3..937ca2d5803 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/internal/witness.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/internal/witness.h @@ -1,10 +1,10 @@ #ifndef JEMALLOC_INTERNAL_WITNESS_H #define JEMALLOC_INTERNAL_WITNESS_H +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/assert.h" #include "jemalloc/internal/ql.h" -namespace duckdb_jemalloc { - /******************************************************************************/ /* LOCK RANKS */ /******************************************************************************/ @@ -343,6 +343,9 @@ witness_lock(witness_tsdn_t *witness_tsdn, witness_t *witness) { witness_lock_error(witnesses, witness); } + /* Suppress spurious warning from static analysis */ + assert(ql_empty(witnesses) || + qr_prev(ql_first(witnesses), link) != NULL); ql_elm_new(witness, link); ql_tail_insert(witnesses, witness, link); } @@ -377,6 +380,4 @@ witness_unlock(witness_tsdn_t *witness_tsdn, witness_t *witness) { } } -} // namespace duckdb_jemalloc - #endif /* JEMALLOC_INTERNAL_WITNESS_H */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc.h b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc.h index c93fefa8470..b728d5df949 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc.h @@ -1,24 +1,12 @@ #ifndef JEMALLOC_H_ #define JEMALLOC_H_ - -//#include -//#include -//#include -#include - -#define DLLEXPORT - -#ifdef _MSC_VER -#include "msvc_compat/strings.h" -#else -#include +#pragma GCC system_header +#ifdef __cplusplus +extern "C" { #endif -namespace duckdb_jemalloc { - -//#ifdef __cplusplus -//extern "C" { -//#endif +// DuckDB uses a 10s decay +#define DUCKDB_DECAY_DELAY 10 /* Defined if __attribute__((...)) syntax is supported. */ #define JEMALLOC_HAVE_ATTR @@ -36,17 +24,21 @@ namespace duckdb_jemalloc { #define JEMALLOC_HAVE_ATTR_FORMAT_PRINTF /* Defined if fallthrough attribute is supported. */ -// #define JEMALLOC_HAVE_ATTR_FALLTHROUGH +#define JEMALLOC_HAVE_ATTR_FALLTHROUGH /* Defined if cold attribute is supported. */ #define JEMALLOC_HAVE_ATTR_COLD +/* Defined if deprecated attribute is supported. */ +/* #undef JEMALLOC_HAVE_ATTR_DEPRECATED */ + /* * Define overrides for non-standard allocator-related functions if they are * present on the system. */ /* #undef JEMALLOC_OVERRIDE_MEMALIGN */ -// #define JEMALLOC_OVERRIDE_VALLOC +/* #undef JEMALLOC_OVERRIDE_VALLOC */ +/* #undef JEMALLOC_OVERRIDE_PVALLOC */ /* * At least Linux omits the "const" in: @@ -65,14 +57,15 @@ namespace duckdb_jemalloc { /* #undef JEMALLOC_USE_CXX_THROW */ #ifdef _MSC_VER -#ifdef _WIN64 -#define LG_SIZEOF_PTR_WIN 3 -#else -#define LG_SIZEOF_PTR_WIN 2 -#endif +# ifdef _WIN64 +# define LG_SIZEOF_PTR_WIN 3 +# else +# define LG_SIZEOF_PTR_WIN 2 +# endif #endif /* sizeof(void *) == 2^LG_SIZEOF_PTR. */ +#include #ifdef _MSC_VER # define LG_SIZEOF_PTR LG_SIZEOF_PTR_WIN #elif INTPTR_MAX == INT64_MAX @@ -87,58 +80,65 @@ namespace duckdb_jemalloc { * these macro definitions. */ #ifndef JEMALLOC_NO_RENAME -#define je_aligned_alloc je_aligned_alloc -#define je_calloc je_calloc -#define je_dallocx je_dallocx -#define je_free je_free -#define je_mallctl je_mallctl -#define je_mallctlbymib je_mallctlbymib -#define je_mallctlnametomib je_mallctlnametomib -#define je_malloc je_malloc -#define je_malloc_conf je_malloc_conf -#define je_malloc_conf_2_conf_harder je_malloc_conf_2_conf_harder -#define je_malloc_message je_malloc_message -#define je_malloc_stats_print je_malloc_stats_print -#define je_malloc_usable_size je_malloc_usable_size -#define je_mallocx je_mallocx -#define je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c -#define je_nallocx je_nallocx -#define je_posix_memalign je_posix_memalign -#define je_rallocx je_rallocx -#define je_realloc je_realloc -#define je_sallocx je_sallocx -#define je_sdallocx je_sdallocx -#define je_xallocx je_xallocx -#define je_valloc je_valloc -#define je_malloc_size je_malloc_size +# define je_aligned_alloc duckdb_je_aligned_alloc +# define je_calloc duckdb_je_calloc +# define je_dallocx duckdb_je_dallocx +# define je_free duckdb_je_free +# define je_mallctl duckdb_je_mallctl +# define je_mallctlbymib duckdb_je_mallctlbymib +# define je_mallctlnametomib duckdb_je_mallctlnametomib +# define je_malloc duckdb_je_malloc +# define je_malloc_conf duckdb_je_malloc_conf +# define je_malloc_conf_2_conf_harder duckdb_je_malloc_conf_2_conf_harder +# define je_malloc_message duckdb_je_malloc_message +# define je_malloc_stats_print duckdb_je_malloc_stats_print +# define je_malloc_usable_size duckdb_je_malloc_usable_size +# define je_mallocx duckdb_je_mallocx +# define je_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 duckdb_je_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 +# define je_nallocx duckdb_je_nallocx +# define je_posix_memalign duckdb_je_posix_memalign +# define je_rallocx duckdb_je_rallocx +# define je_realloc duckdb_je_realloc +# define je_sallocx duckdb_je_sallocx +# define je_sdallocx duckdb_je_sdallocx +# define je_xallocx duckdb_je_xallocx +# define je_valloc duckdb_je_valloc +# define je_malloc_size duckdb_je_malloc_size #endif -#define JEMALLOC_VERSION "5.3.0-0-g54eaed1d8b56b1aa528be3bdd1877e59c56fa90c" -#define JEMALLOC_VERSION_MAJOR 5 -#define JEMALLOC_VERSION_MINOR 3 -#define JEMALLOC_VERSION_BUGFIX 0 -#define JEMALLOC_VERSION_NREV 0 -#define JEMALLOC_VERSION_GID "54eaed1d8b56b1aa528be3bdd1877e59c56fa90c" -#define JEMALLOC_VERSION_GID_IDENT 54eaed1d8b56b1aa528be3bdd1877e59c56fa90c +#include +#include +#include +#include +#include + +#define JEMALLOC_VERSION "5.3.0-172-gfa451de17fff73cc03c31ec8cd817d62927d1ff9" +#define JEMALLOC_VERSION_MAJOR 5 +#define JEMALLOC_VERSION_MINOR 3 +#define JEMALLOC_VERSION_BUGFIX 0 +#define JEMALLOC_VERSION_NREV 172 +#define JEMALLOC_VERSION_GID "fa451de17fff73cc03c31ec8cd817d62927d1ff9" +#define JEMALLOC_VERSION_GID_IDENT fa451de17fff73cc03c31ec8cd817d62927d1ff9 -#define MALLOCX_LG_ALIGN(la) ((int)(la)) +#define MALLOCX_LG_ALIGN(la) ((int)(la)) #if LG_SIZEOF_PTR == 2 -#define MALLOCX_ALIGN(a) ((int)(ffs((int)(a)) - 1)) +# define MALLOCX_ALIGN(a) ((int)(ffs((int)(a))-1)) #else -#define MALLOCX_ALIGN(a) \ - ((int)(((size_t)(a) < (size_t)INT_MAX) ? ffs((int)(a)) - 1 : ffs((int)(((size_t)(a)) >> 32)) + 31)) +# define MALLOCX_ALIGN(a) \ + ((int)(((size_t)(a) < (size_t)INT_MAX) ? ffs((int)(a))-1 : \ + ffs((int)(((size_t)(a))>>32))+31)) #endif -#define MALLOCX_ZERO ((int)0x40) +#define MALLOCX_ZERO ((int)0x40) /* * Bias tcache index bits so that 0 encodes "automatic tcache management", and 1 * encodes MALLOCX_TCACHE_NONE. */ -#define MALLOCX_TCACHE(tc) ((int)(((tc) + 2) << 8)) -#define MALLOCX_TCACHE_NONE MALLOCX_TCACHE(-1) +#define MALLOCX_TCACHE(tc) ((int)(((tc)+2) << 8)) +#define MALLOCX_TCACHE_NONE MALLOCX_TCACHE(-1) /* * Bias arena index bits so that 0 encodes "use an automatically chosen arena". */ -//#define MALLOCX_ARENA(a) ((((int)(a)) + 1) << 20) +#define MALLOCX_ARENA(a) ((((int)(a))+1) << 20) /* * Use as arena index in "arena..{purge,decay,dss}" and @@ -152,108 +152,115 @@ namespace duckdb_jemalloc { * mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", NULL, NULL, NULL, * 0); */ -#define MALLCTL_ARENAS_ALL 4096 +#define MALLCTL_ARENAS_ALL 4096 /* * Use as arena index in "stats.arenas..*" mallctl interfaces to select * destroyed arenas. */ -#define MALLCTL_ARENAS_DESTROYED 4097 +#define MALLCTL_ARENAS_DESTROYED 4097 #if defined(__cplusplus) && defined(JEMALLOC_USE_CXX_THROW) -#define JEMALLOC_CXX_THROW throw() +# define JEMALLOC_CXX_THROW throw() #else -#define JEMALLOC_CXX_THROW +# define JEMALLOC_CXX_THROW #endif #if defined(_MSC_VER) -#define JEMALLOC_ATTR(s) -#define JEMALLOC_ALIGNED(s) __declspec(align(s)) -#define JEMALLOC_ALLOC_SIZE(s) -#define JEMALLOC_ALLOC_SIZE2(s1, s2) -#ifndef JEMALLOC_EXPORT -#ifdef DLLEXPORT -#define JEMALLOC_EXPORT __declspec(dllexport) -#else -#define JEMALLOC_EXPORT __declspec(dllimport) -#endif -#endif -#define JEMALLOC_FORMAT_ARG(i) -#define JEMALLOC_FORMAT_PRINTF(s, i) -#define JEMALLOC_FALLTHROUGH -#define JEMALLOC_NOINLINE __declspec(noinline) -#ifdef __cplusplus -#define JEMALLOC_NOTHROW __declspec(nothrow) -#else -#define JEMALLOC_NOTHROW -#endif -#define JEMALLOC_SECTION(s) __declspec(allocate(s)) -#define JEMALLOC_RESTRICT_RETURN __declspec(restrict) -#if _MSC_VER >= 1900 && !defined(__EDG__) -#define JEMALLOC_ALLOCATOR __declspec(allocator) -#else -#define JEMALLOC_ALLOCATOR -#endif -#define JEMALLOC_COLD +# define JEMALLOC_ATTR(s) +# define JEMALLOC_ALIGNED(s) __declspec(align(s)) +# define JEMALLOC_ALLOC_SIZE(s) +# define JEMALLOC_ALLOC_SIZE2(s1, s2) +# ifndef JEMALLOC_EXPORT +# ifdef DLLEXPORT +# define JEMALLOC_EXPORT __declspec(dllexport) +# else +# define JEMALLOC_EXPORT __declspec(dllimport) +# endif +# endif +# define JEMALLOC_FORMAT_ARG(i) +# define JEMALLOC_FORMAT_PRINTF(s, i) +# define JEMALLOC_FALLTHROUGH +# define JEMALLOC_NOINLINE __declspec(noinline) +# ifdef __cplusplus +# define JEMALLOC_NOTHROW __declspec(nothrow) +# else +# define JEMALLOC_NOTHROW +# endif +# define JEMALLOC_SECTION(s) __declspec(allocate(s)) +# define JEMALLOC_RESTRICT_RETURN __declspec(restrict) +# if _MSC_VER >= 1900 && !defined(__EDG__) +# define JEMALLOC_ALLOCATOR __declspec(allocator) +# else +# define JEMALLOC_ALLOCATOR +# endif +# define JEMALLOC_COLD +# define JEMALLOC_WARN_ON_USAGE(warning_message) #elif defined(JEMALLOC_HAVE_ATTR) -#define JEMALLOC_ATTR(s) __attribute__((s)) -#define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s)) -#ifdef JEMALLOC_HAVE_ATTR_ALLOC_SIZE -#define JEMALLOC_ALLOC_SIZE(s) JEMALLOC_ATTR(alloc_size(s)) -#define JEMALLOC_ALLOC_SIZE2(s1, s2) JEMALLOC_ATTR(alloc_size(s1, s2)) -#else -#define JEMALLOC_ALLOC_SIZE(s) -#define JEMALLOC_ALLOC_SIZE2(s1, s2) -#endif -#ifndef JEMALLOC_EXPORT -#define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default")) -#endif -#ifdef JEMALLOC_HAVE_ATTR_FORMAT_ARG -#define JEMALLOC_FORMAT_ARG(i) JEMALLOC_ATTR(__format_arg__(3)) -#else -#define JEMALLOC_FORMAT_ARG(i) -#endif -#ifdef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF -#define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(gnu_printf, s, i)) -#elif defined(JEMALLOC_HAVE_ATTR_FORMAT_PRINTF) -#define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(printf, s, i)) -#else -#define JEMALLOC_FORMAT_PRINTF(s, i) -#endif -#ifdef JEMALLOC_HAVE_ATTR_FALLTHROUGH -#define JEMALLOC_FALLTHROUGH JEMALLOC_ATTR(fallthrough) -#else -#define JEMALLOC_FALLTHROUGH -#endif -#define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline) -#define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow) -#define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s)) -#define JEMALLOC_RESTRICT_RETURN -#define JEMALLOC_ALLOCATOR -#ifdef JEMALLOC_HAVE_ATTR_COLD -#define JEMALLOC_COLD JEMALLOC_ATTR(__cold__) +# define JEMALLOC_ATTR(s) __attribute__((s)) +# define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s)) +# ifdef JEMALLOC_HAVE_ATTR_ALLOC_SIZE +# define JEMALLOC_ALLOC_SIZE(s) JEMALLOC_ATTR(alloc_size(s)) +# define JEMALLOC_ALLOC_SIZE2(s1, s2) JEMALLOC_ATTR(alloc_size(s1, s2)) +# else +# define JEMALLOC_ALLOC_SIZE(s) +# define JEMALLOC_ALLOC_SIZE2(s1, s2) +# endif +# ifndef JEMALLOC_EXPORT +# define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default")) +# endif +# ifdef JEMALLOC_HAVE_ATTR_FORMAT_ARG +# define JEMALLOC_FORMAT_ARG(i) JEMALLOC_ATTR(__format_arg__(3)) +# else +# define JEMALLOC_FORMAT_ARG(i) +# endif +# ifdef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF +# define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(gnu_printf, s, i)) +# elif defined(JEMALLOC_HAVE_ATTR_FORMAT_PRINTF) +# define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(printf, s, i)) +# else +# define JEMALLOC_FORMAT_PRINTF(s, i) +# endif +# ifdef JEMALLOC_HAVE_ATTR_FALLTHROUGH +# define JEMALLOC_FALLTHROUGH JEMALLOC_ATTR(fallthrough) +# else +# define JEMALLOC_FALLTHROUGH +# endif +# define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline) +# define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow) +# define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s)) +# define JEMALLOC_RESTRICT_RETURN +# define JEMALLOC_ALLOCATOR +# ifdef JEMALLOC_HAVE_ATTR_COLD +# define JEMALLOC_COLD JEMALLOC_ATTR(__cold__) +# else +# define JEMALLOC_COLD +# endif +# ifdef JEMALLOC_HAVE_ATTR_DEPRECATED +# define JEMALLOC_WARN_ON_USAGE(warning_message) JEMALLOC_ATTR(deprecated(warning_message)) +# else +# define JEMALLOC_WARN_ON_USAGE(warning_message) +# endif #else -#define JEMALLOC_COLD -#endif -#else -#define JEMALLOC_ATTR(s) -#define JEMALLOC_ALIGNED(s) -#define JEMALLOC_ALLOC_SIZE(s) -#define JEMALLOC_ALLOC_SIZE2(s1, s2) -#define JEMALLOC_EXPORT -#define JEMALLOC_FORMAT_PRINTF(s, i) -#define JEMALLOC_FALLTHROUGH -#define JEMALLOC_NOINLINE -#define JEMALLOC_NOTHROW -#define JEMALLOC_SECTION(s) -#define JEMALLOC_RESTRICT_RETURN -#define JEMALLOC_ALLOCATOR -#define JEMALLOC_COLD +# define JEMALLOC_ATTR(s) +# define JEMALLOC_ALIGNED(s) +# define JEMALLOC_ALLOC_SIZE(s) +# define JEMALLOC_ALLOC_SIZE2(s1, s2) +# define JEMALLOC_EXPORT +# define JEMALLOC_FORMAT_PRINTF(s, i) +# define JEMALLOC_FALLTHROUGH +# define JEMALLOC_NOINLINE +# define JEMALLOC_NOTHROW +# define JEMALLOC_SECTION(s) +# define JEMALLOC_RESTRICT_RETURN +# define JEMALLOC_ALLOCATOR +# define JEMALLOC_COLD +# define JEMALLOC_WARN_ON_USAGE(warning_message) #endif -#if (defined(__APPLE__) || defined(__FreeBSD__)) && !defined(JEMALLOC_NO_RENAME) -#define JEMALLOC_SYS_NOTHROW +#if (defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || (defined(__linux__) && !defined(__GLIBC__))) && !defined(JEMALLOC_NO_RENAME) +# define JEMALLOC_SYS_NOTHROW #else -#define JEMALLOC_SYS_NOTHROW JEMALLOC_NOTHROW +# define JEMALLOC_SYS_NOTHROW JEMALLOC_NOTHROW #endif /* @@ -261,51 +268,81 @@ namespace duckdb_jemalloc { * of namespace management, and should be omitted in application code unless * JEMALLOC_NO_DEMANGLE is defined (see jemalloc_mangle.h). */ -extern JEMALLOC_EXPORT const char *je_malloc_conf; -extern JEMALLOC_EXPORT void (*je_malloc_message)(void *cbopaque, const char *s); - -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) -JEMALLOC_ALLOC_SIZE(1) JEMALLOC_SYS_NOTHROW * je_malloc(size_t size); -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) -JEMALLOC_ALLOC_SIZE2(1, 2) JEMALLOC_SYS_NOTHROW * je_calloc(size_t num, size_t size); -JEMALLOC_EXPORT int JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1)) JEMALLOC_SYS_NOTHROW -je_posix_memalign(void **memptr, size_t alignment, size_t size); -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) -JEMALLOC_ALLOC_SIZE(2) JEMALLOC_SYS_NOTHROW * je_aligned_alloc(size_t alignment, size_t size); -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2) -JEMALLOC_SYS_NOTHROW * je_realloc(void *ptr, size_t size); -JEMALLOC_EXPORT void JEMALLOC_CXX_THROW JEMALLOC_SYS_NOTHROW je_free(void *ptr); - -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) -JEMALLOC_NOTHROW *je_mallocx(size_t size, int flags); -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_ALLOC_SIZE(2) JEMALLOC_NOTHROW -* je_rallocx(void *ptr, size_t size, int flags); -JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_xallocx(void *ptr, size_t size, size_t extra, int flags); -JEMALLOC_EXPORT size_t JEMALLOC_ATTR(pure) JEMALLOC_NOTHROW je_sallocx(const void *ptr, int flags); -JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_dallocx(void *ptr, int flags); -JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_sdallocx(void *ptr, size_t size, int flags); -JEMALLOC_EXPORT size_t JEMALLOC_ATTR(pure) JEMALLOC_NOTHROW je_nallocx(size_t size, int flags); - -JEMALLOC_EXPORT int JEMALLOC_NOTHROW -je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen); -JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp); -JEMALLOC_EXPORT int JEMALLOC_NOTHROW -je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen); -JEMALLOC_EXPORT void JEMALLOC_NOTHROW -je_malloc_stats_print(void (*write_cb)(void *, const char *), void *je_cbopaque, const char *opts); -JEMALLOC_EXPORT size_t JEMALLOC_CXX_THROW JEMALLOC_NOTHROW je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr); +extern JEMALLOC_EXPORT const char *je_malloc_conf; +extern JEMALLOC_EXPORT const char *je_malloc_conf_2_conf_harder; +extern JEMALLOC_EXPORT void (*je_malloc_message)(void *cbopaque, + const char *s); + +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_SYS_NOTHROW *je_malloc(size_t size) + JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_SYS_NOTHROW *je_calloc(size_t num, size_t size) + JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2); +JEMALLOC_EXPORT int JEMALLOC_SYS_NOTHROW je_posix_memalign( + void **memptr, size_t alignment, size_t size) JEMALLOC_CXX_THROW + JEMALLOC_ATTR(nonnull(1)); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_SYS_NOTHROW *je_aligned_alloc(size_t alignment, + size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) + JEMALLOC_ALLOC_SIZE(2); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_SYS_NOTHROW *je_realloc(void *ptr, size_t size) + JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2); +JEMALLOC_EXPORT void JEMALLOC_SYS_NOTHROW je_free(void *ptr) + JEMALLOC_CXX_THROW; +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_free_sized(void *ptr, size_t size); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_free_aligned_sized( + void *ptr, size_t alignment, size_t size); + +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_NOTHROW *je_mallocx(size_t size, int flags) + JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_NOTHROW *je_rallocx(void *ptr, size_t size, + int flags) JEMALLOC_ALLOC_SIZE(2); +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_xallocx(void *ptr, size_t size, + size_t extra, int flags); +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_sallocx(const void *ptr, + int flags) JEMALLOC_ATTR(pure); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_dallocx(void *ptr, int flags); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_sdallocx(void *ptr, size_t size, + int flags); +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_nallocx(size_t size, int flags) + JEMALLOC_ATTR(pure); + +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctl(const char *name, + void *oldp, size_t *oldlenp, void *newp, size_t newlen); +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctlnametomib(const char *name, + size_t *mibp, size_t *miblenp); +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctlbymib(const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_malloc_stats_print( + void (*write_cb)(void *, const char *), void *je_cbopaque, + const char *opts); +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_malloc_usable_size( + JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW; #ifdef JEMALLOC_HAVE_MALLOC_SIZE -JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_malloc_size(const void *ptr); +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_malloc_size( + const void *ptr); #endif #ifdef JEMALLOC_OVERRIDE_MEMALIGN -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_SYS_NOTHROW * -je_memalign(size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_SYS_NOTHROW *je_memalign(size_t alignment, size_t size) + JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc); #endif #ifdef JEMALLOC_OVERRIDE_VALLOC -JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) -JEMALLOC_SYS_NOTHROW * je_valloc(size_t size); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_SYS_NOTHROW *je_valloc(size_t size) JEMALLOC_CXX_THROW + JEMALLOC_ATTR(malloc); +#endif + +#ifdef JEMALLOC_OVERRIDE_PVALLOC +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_SYS_NOTHROW *je_pvalloc(size_t size) JEMALLOC_CXX_THROW + JEMALLOC_ATTR(malloc); #endif typedef struct extent_hooks_s extent_hooks_t; @@ -315,67 +352,75 @@ typedef struct extent_hooks_s extent_hooks_t; * extent_alloc(extent_hooks_t *extent_hooks, void *new_addr, size_t size, * size_t alignment, bool *zero, bool *commit, unsigned arena_ind); */ -typedef void *(extent_alloc_t)(extent_hooks_t *, void *, size_t, size_t, bool *, bool *, unsigned); +typedef void *(extent_alloc_t)(extent_hooks_t *, void *, size_t, size_t, bool *, + bool *, unsigned); /* * bool * extent_dalloc(extent_hooks_t *extent_hooks, void *addr, size_t size, * bool committed, unsigned arena_ind); */ -typedef bool(extent_dalloc_t)(extent_hooks_t *, void *, size_t, bool, unsigned); +typedef bool (extent_dalloc_t)(extent_hooks_t *, void *, size_t, bool, + unsigned); /* * void * extent_destroy(extent_hooks_t *extent_hooks, void *addr, size_t size, * bool committed, unsigned arena_ind); */ -typedef void(extent_destroy_t)(extent_hooks_t *, void *, size_t, bool, unsigned); +typedef void (extent_destroy_t)(extent_hooks_t *, void *, size_t, bool, + unsigned); /* * bool * extent_commit(extent_hooks_t *extent_hooks, void *addr, size_t size, * size_t offset, size_t length, unsigned arena_ind); */ -typedef bool(extent_commit_t)(extent_hooks_t *, void *, size_t, size_t, size_t, unsigned); +typedef bool (extent_commit_t)(extent_hooks_t *, void *, size_t, size_t, size_t, + unsigned); /* * bool * extent_decommit(extent_hooks_t *extent_hooks, void *addr, size_t size, * size_t offset, size_t length, unsigned arena_ind); */ -typedef bool(extent_decommit_t)(extent_hooks_t *, void *, size_t, size_t, size_t, unsigned); +typedef bool (extent_decommit_t)(extent_hooks_t *, void *, size_t, size_t, + size_t, unsigned); /* * bool * extent_purge(extent_hooks_t *extent_hooks, void *addr, size_t size, * size_t offset, size_t length, unsigned arena_ind); */ -typedef bool(extent_purge_t)(extent_hooks_t *, void *, size_t, size_t, size_t, unsigned); +typedef bool (extent_purge_t)(extent_hooks_t *, void *, size_t, size_t, size_t, + unsigned); /* * bool * extent_split(extent_hooks_t *extent_hooks, void *addr, size_t size, * size_t size_a, size_t size_b, bool committed, unsigned arena_ind); */ -typedef bool(extent_split_t)(extent_hooks_t *, void *, size_t, size_t, size_t, bool, unsigned); +typedef bool (extent_split_t)(extent_hooks_t *, void *, size_t, size_t, size_t, + bool, unsigned); /* * bool * extent_merge(extent_hooks_t *extent_hooks, void *addr_a, size_t size_a, * void *addr_b, size_t size_b, bool committed, unsigned arena_ind); */ -typedef bool(extent_merge_t)(extent_hooks_t *, void *, size_t, void *, size_t, bool, unsigned); +typedef bool (extent_merge_t)(extent_hooks_t *, void *, size_t, void *, size_t, + bool, unsigned); struct extent_hooks_s { - extent_alloc_t *alloc; - extent_dalloc_t *dalloc; - extent_destroy_t *destroy; - extent_commit_t *commit; - extent_decommit_t *decommit; - extent_purge_t *purge_lazy; - extent_purge_t *purge_forced; - extent_split_t *split; - extent_merge_t *merge; + extent_alloc_t *alloc; + extent_dalloc_t *dalloc; + extent_destroy_t *destroy; + extent_commit_t *commit; + extent_decommit_t *decommit; + extent_purge_t *purge_lazy; + extent_purge_t *purge_forced; + extent_split_t *split; + extent_merge_t *merge; }; /* @@ -386,33 +431,33 @@ struct extent_hooks_s { * --with-mangling and/or --with-jemalloc-prefix configuration settings. */ #ifdef JEMALLOC_MANGLE -#ifndef JEMALLOC_NO_DEMANGLE -#define JEMALLOC_NO_DEMANGLE -#endif -#define aligned_alloc je_aligned_alloc -#define calloc je_calloc -#define dallocx je_dallocx -#define free je_free -#define mallctl je_mallctl -#define mallctlbymib je_mallctlbymib -#define mallctlnametomib je_mallctlnametomib -#define malloc je_malloc -#define malloc_conf je_malloc_conf -#define malloc_conf_2_conf_harder je_malloc_conf_2_conf_harder -#define malloc_message je_malloc_message -#define malloc_stats_print je_malloc_stats_print -#define malloc_usable_size je_malloc_usable_size -#define mallocx je_mallocx -#define smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c -#define nallocx je_nallocx -#define posix_memalign je_posix_memalign -#define rallocx je_rallocx -#define realloc je_realloc -#define sallocx je_sallocx -#define sdallocx je_sdallocx -#define xallocx je_xallocx -#define valloc je_valloc -#define malloc_size je_malloc_size +# ifndef JEMALLOC_NO_DEMANGLE +# define JEMALLOC_NO_DEMANGLE +# endif +# define aligned_alloc je_aligned_alloc +# define calloc je_calloc +# define dallocx je_dallocx +# define free je_free +# define mallctl je_mallctl +# define mallctlbymib je_mallctlbymib +# define mallctlnametomib je_mallctlnametomib +# define malloc je_malloc +# define malloc_conf je_malloc_conf +# define malloc_conf_2_conf_harder je_malloc_conf_2_conf_harder +# define malloc_message je_malloc_message +# define malloc_stats_print je_malloc_stats_print +# define malloc_usable_size je_malloc_usable_size +# define mallocx je_mallocx +# define smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 je_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 +# define nallocx je_nallocx +# define posix_memalign je_posix_memalign +# define rallocx je_rallocx +# define realloc je_realloc +# define sallocx je_sallocx +# define sdallocx je_sdallocx +# define xallocx je_xallocx +# define valloc je_valloc +# define malloc_size je_malloc_size #endif /* @@ -423,36 +468,33 @@ struct extent_hooks_s { * and/or --with-jemalloc-prefix. */ #ifndef JEMALLOC_NO_DEMANGLE -#undef je_aligned_alloc -#undef je_calloc -#undef je_dallocx -#undef je_free -#undef je_mallctl -#undef je_mallctlbymib -#undef je_mallctlnametomib -#undef je_malloc -#undef je_malloc_conf -#undef je_malloc_conf_2_conf_harder -#undef je_malloc_message -#undef je_malloc_stats_print -#undef je_malloc_usable_size -#undef je_mallocx -#undef je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c -#undef je_nallocx -#undef je_posix_memalign -#undef je_rallocx -#undef je_realloc -#undef je_sallocx -#undef je_sdallocx -#undef je_xallocx -#undef je_valloc -#undef je_malloc_size +# undef je_aligned_alloc +# undef je_calloc +# undef je_dallocx +# undef je_free +# undef je_mallctl +# undef je_mallctlbymib +# undef je_mallctlnametomib +# undef je_malloc +# undef je_malloc_conf +# undef je_malloc_conf_2_conf_harder +# undef je_malloc_message +# undef je_malloc_stats_print +# undef je_malloc_usable_size +# undef je_mallocx +# undef je_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 +# undef je_nallocx +# undef je_posix_memalign +# undef je_rallocx +# undef je_realloc +# undef je_sallocx +# undef je_sdallocx +# undef je_xallocx +# undef je_valloc +# undef je_malloc_size #endif -//#ifdef __cplusplus -//} -//#endif - -} // namespace duckdb_jemalloc - +#ifdef __cplusplus +} +#endif #endif /* JEMALLOC_H_ */ diff --git a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_defs.h b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_defs.h index d6d8245aa33..1fb7f314514 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_defs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_defs.h @@ -1,8 +1,4 @@ /* include/jemalloc/jemalloc_defs.h. Generated from jemalloc_defs.h.in by configure. */ -#pragma once - -#include - /* Defined if __attribute__((...)) syntax is supported. */ #define JEMALLOC_HAVE_ATTR @@ -24,12 +20,16 @@ /* Defined if cold attribute is supported. */ #define JEMALLOC_HAVE_ATTR_COLD +/* Defined if deprecated attribute is supported. */ +/* #undef JEMALLOC_HAVE_ATTR_DEPRECATED */ + /* * Define overrides for non-standard allocator-related functions if they are * present on the system. */ /* #undef JEMALLOC_OVERRIDE_MEMALIGN */ #define JEMALLOC_OVERRIDE_VALLOC +/* #undef JEMALLOC_OVERRIDE_PVALLOC */ /* * At least Linux omits the "const" in: @@ -56,6 +56,7 @@ #endif /* sizeof(void *) == 2^LG_SIZEOF_PTR. */ +#include "limits.h" #ifdef _MSC_VER # define LG_SIZEOF_PTR LG_SIZEOF_PTR_WIN #elif INTPTR_MAX == INT64_MAX diff --git a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_macros.h b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_macros.h index bb852b748e1..bfafee98303 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_macros.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_macros.h @@ -1,29 +1,18 @@ -//#pragma once - -//#include -#include -#include - -#include - -#ifdef _MSC_VER -#include "msvc_compat/strings.h" -#else +#include +#include +#include +#include #include -#endif - -namespace duckdb_jemalloc { -#define JEMALLOC_VERSION "5.3.0-0-g54eaed1d8b56b1aa528be3bdd1877e59c56fa90c" +#define JEMALLOC_VERSION "5.3.0-172-gfa451de17fff73cc03c31ec8cd817d62927d1ff9" #define JEMALLOC_VERSION_MAJOR 5 #define JEMALLOC_VERSION_MINOR 3 #define JEMALLOC_VERSION_BUGFIX 0 -#define JEMALLOC_VERSION_NREV 0 -#define JEMALLOC_VERSION_GID "54eaed1d8b56b1aa528be3bdd1877e59c56fa90c" -#define JEMALLOC_VERSION_GID_IDENT 54eaed1d8b56b1aa528be3bdd1877e59c56fa90c +#define JEMALLOC_VERSION_NREV 172 +#define JEMALLOC_VERSION_GID "fa451de17fff73cc03c31ec8cd817d62927d1ff9" +#define JEMALLOC_VERSION_GID_IDENT fa451de17fff73cc03c31ec8cd817d62927d1ff9 #define MALLOCX_LG_ALIGN(la) ((int)(la)) -#ifndef MALLOCX_ALIGN #if LG_SIZEOF_PTR == 2 # define MALLOCX_ALIGN(a) ((int)(ffs((int)(a))-1)) #else @@ -31,15 +20,12 @@ namespace duckdb_jemalloc { ((int)(((size_t)(a) < (size_t)INT_MAX) ? ffs((int)(a))-1 : \ ffs((int)(((size_t)(a))>>32))+31)) #endif -#endif #define MALLOCX_ZERO ((int)0x40) /* * Bias tcache index bits so that 0 encodes "automatic tcache management", and 1 * encodes MALLOCX_TCACHE_NONE. */ -#ifndef MALLOCX_TCACHE #define MALLOCX_TCACHE(tc) ((int)(((tc)+2) << 8)) -#endif #define MALLOCX_TCACHE_NONE MALLOCX_TCACHE(-1) /* * Bias arena index bits so that 0 encodes "use an automatically chosen arena". @@ -71,8 +57,6 @@ namespace duckdb_jemalloc { # define JEMALLOC_CXX_THROW #endif -#define DLLEXPORT - #if defined(_MSC_VER) # define JEMALLOC_ATTR(s) # define JEMALLOC_ALIGNED(s) __declspec(align(s)) @@ -102,6 +86,7 @@ namespace duckdb_jemalloc { # define JEMALLOC_ALLOCATOR # endif # define JEMALLOC_COLD +# define JEMALLOC_WARN_ON_USAGE(warning_message) #elif defined(JEMALLOC_HAVE_ATTR) # define JEMALLOC_ATTR(s) __attribute__((s)) # define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s)) @@ -142,6 +127,11 @@ namespace duckdb_jemalloc { # else # define JEMALLOC_COLD # endif +# ifdef JEMALLOC_HAVE_ATTR_DEPRECATED +# define JEMALLOC_WARN_ON_USAGE(warning_message) JEMALLOC_ATTR(deprecated(warning_message)) +# else +# define JEMALLOC_WARN_ON_USAGE(warning_message) +# endif #else # define JEMALLOC_ATTR(s) # define JEMALLOC_ALIGNED(s) @@ -156,12 +146,11 @@ namespace duckdb_jemalloc { # define JEMALLOC_RESTRICT_RETURN # define JEMALLOC_ALLOCATOR # define JEMALLOC_COLD +# define JEMALLOC_WARN_ON_USAGE(warning_message) #endif -#if (defined(__APPLE__) || defined(__FreeBSD__)) && !defined(JEMALLOC_NO_RENAME) +#if (defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || (defined(__linux__) && !defined(__GLIBC__))) && !defined(JEMALLOC_NO_RENAME) # define JEMALLOC_SYS_NOTHROW #else # define JEMALLOC_SYS_NOTHROW JEMALLOC_NOTHROW #endif - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_mangle.h b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_mangle.h index d8cbe63c307..66cbdd56fa3 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_mangle.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_mangle.h @@ -5,9 +5,6 @@ * name mangling that matches the API prefixing that happened as a result of * --with-mangling and/or --with-jemalloc-prefix configuration settings. */ - -namespace duckdb_jemalloc { - #ifdef JEMALLOC_MANGLE # ifndef JEMALLOC_NO_DEMANGLE # define JEMALLOC_NO_DEMANGLE @@ -26,7 +23,7 @@ namespace duckdb_jemalloc { # define malloc_stats_print je_malloc_stats_print # define malloc_usable_size je_malloc_usable_size # define mallocx je_mallocx -# define smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c +# define smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 je_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 # define nallocx je_nallocx # define posix_memalign je_posix_memalign # define rallocx je_rallocx @@ -60,7 +57,7 @@ namespace duckdb_jemalloc { # undef je_malloc_stats_print # undef je_malloc_usable_size # undef je_mallocx -# undef je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c +# undef je_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 # undef je_nallocx # undef je_posix_memalign # undef je_rallocx @@ -71,5 +68,3 @@ namespace duckdb_jemalloc { # undef je_valloc # undef je_malloc_size #endif - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_mangle_jet.h b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_mangle_jet.h index 7b4e94c15aa..ca1695c2922 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_mangle_jet.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_mangle_jet.h @@ -5,9 +5,6 @@ * name mangling that matches the API prefixing that happened as a result of * --with-mangling and/or --with-jemalloc-prefix configuration settings. */ - -namespace duckdb_jemalloc { - #ifdef JEMALLOC_MANGLE # ifndef JEMALLOC_NO_DEMANGLE # define JEMALLOC_NO_DEMANGLE @@ -26,7 +23,7 @@ namespace duckdb_jemalloc { # define malloc_stats_print jet_malloc_stats_print # define malloc_usable_size jet_malloc_usable_size # define mallocx jet_mallocx -# define smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c jet_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c +# define smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 jet_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 # define nallocx jet_nallocx # define posix_memalign jet_posix_memalign # define rallocx jet_rallocx @@ -60,7 +57,7 @@ namespace duckdb_jemalloc { # undef jet_malloc_stats_print # undef jet_malloc_usable_size # undef jet_mallocx -# undef jet_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c +# undef jet_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 # undef jet_nallocx # undef jet_posix_memalign # undef jet_rallocx @@ -71,5 +68,3 @@ namespace duckdb_jemalloc { # undef jet_valloc # undef jet_malloc_size #endif - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_protos.h b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_protos.h index 9b6e6667af0..12c388e2cb9 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_protos.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_protos.h @@ -1,10 +1,10 @@ -namespace duckdb_jemalloc { /* * The je_ prefix on the following public symbol declarations is an artifact * of namespace management, and should be omitted in application code unless * JEMALLOC_NO_DEMANGLE is defined (see jemalloc_mangle.h). */ extern JEMALLOC_EXPORT const char *je_malloc_conf; +extern JEMALLOC_EXPORT const char *je_malloc_conf_2_conf_harder; extern JEMALLOC_EXPORT void (*je_malloc_message)(void *cbopaque, const char *s); @@ -26,6 +26,9 @@ JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2); JEMALLOC_EXPORT void JEMALLOC_SYS_NOTHROW je_free(void *ptr) JEMALLOC_CXX_THROW; +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_free_sized(void *ptr, size_t size); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_free_aligned_sized( + void *ptr, size_t alignment, size_t size); JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_NOTHROW *je_mallocx(size_t size, int flags) @@ -71,4 +74,8 @@ JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN JEMALLOC_ATTR(malloc); #endif -} // namespace duckdb_jemalloc +#ifdef JEMALLOC_OVERRIDE_PVALLOC +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_SYS_NOTHROW *je_pvalloc(size_t size) JEMALLOC_CXX_THROW + JEMALLOC_ATTR(malloc); +#endif diff --git a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_protos_jet.h b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_protos_jet.h index 4eaa737d35d..fb51e1b7f82 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_protos_jet.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_protos_jet.h @@ -1,10 +1,10 @@ -namespace duckdb_jemalloc { /* * The jet_ prefix on the following public symbol declarations is an artifact * of namespace management, and should be omitted in application code unless * JEMALLOC_NO_DEMANGLE is defined (see jemalloc_mangle@install_suffix@.h). */ extern JEMALLOC_EXPORT const char *jet_malloc_conf; +extern JEMALLOC_EXPORT const char *jet_malloc_conf_2_conf_harder; extern JEMALLOC_EXPORT void (*jet_malloc_message)(void *cbopaque, const char *s); @@ -26,6 +26,9 @@ JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2); JEMALLOC_EXPORT void JEMALLOC_SYS_NOTHROW jet_free(void *ptr) JEMALLOC_CXX_THROW; +JEMALLOC_EXPORT void JEMALLOC_NOTHROW jet_free_sized(void *ptr, size_t size); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW jet_free_aligned_sized( + void *ptr, size_t alignment, size_t size); JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_NOTHROW *jet_mallocx(size_t size, int flags) @@ -71,4 +74,8 @@ JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN JEMALLOC_ATTR(malloc); #endif -} // namespace duckdb_jemalloc +#ifdef JEMALLOC_OVERRIDE_PVALLOC +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_SYS_NOTHROW *jet_pvalloc(size_t size) JEMALLOC_CXX_THROW + JEMALLOC_ATTR(malloc); +#endif diff --git a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_rename.h b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_rename.h index 4670e4e3115..d7a1ae21feb 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_rename.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_rename.h @@ -1,35 +1,31 @@ -namespace duckdb_jemalloc { - /* * Name mangling for public symbols is controlled by --with-mangling and * --with-jemalloc-prefix. With default settings the je_ prefix is stripped by * these macro definitions. */ #ifndef JEMALLOC_NO_RENAME -# define je_aligned_alloc je_aligned_alloc -# define je_calloc je_calloc -# define je_dallocx je_dallocx -# define je_free je_free -# define je_mallctl je_mallctl -# define je_mallctlbymib je_mallctlbymib -# define je_mallctlnametomib je_mallctlnametomib -# define je_malloc je_malloc -# define je_malloc_conf je_malloc_conf -# define je_malloc_conf_2_conf_harder je_malloc_conf_2_conf_harder -# define je_malloc_message je_malloc_message -# define je_malloc_stats_print je_malloc_stats_print -# define je_malloc_usable_size je_malloc_usable_size -# define je_mallocx je_mallocx -# define je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c -# define je_nallocx je_nallocx -# define je_posix_memalign je_posix_memalign -# define je_rallocx je_rallocx -# define je_realloc je_realloc -# define je_sallocx je_sallocx -# define je_sdallocx je_sdallocx -# define je_xallocx je_xallocx -# define je_valloc je_valloc -# define je_malloc_size je_malloc_size +# define je_aligned_alloc duckdb_je_aligned_alloc +# define je_calloc duckdb_je_calloc +# define je_dallocx duckdb_je_dallocx +# define je_free duckdb_je_free +# define je_mallctl duckdb_je_mallctl +# define je_mallctlbymib duckdb_je_mallctlbymib +# define je_mallctlnametomib duckdb_je_mallctlnametomib +# define je_malloc duckdb_je_malloc +# define je_malloc_conf duckdb_je_malloc_conf +# define je_malloc_conf_2_conf_harder duckdb_je_malloc_conf_2_conf_harder +# define je_malloc_message duckdb_je_malloc_message +# define je_malloc_stats_print duckdb_je_malloc_stats_print +# define je_malloc_usable_size duckdb_je_malloc_usable_size +# define je_mallocx duckdb_je_mallocx +# define je_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 duckdb_je_smallocx_fa451de17fff73cc03c31ec8cd817d62927d1ff9 +# define je_nallocx duckdb_je_nallocx +# define je_posix_memalign duckdb_je_posix_memalign +# define je_rallocx duckdb_je_rallocx +# define je_realloc duckdb_je_realloc +# define je_sallocx duckdb_je_sallocx +# define je_sdallocx duckdb_je_sdallocx +# define je_xallocx duckdb_je_xallocx +# define je_valloc duckdb_je_valloc +# define je_malloc_size duckdb_je_malloc_size #endif - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_typedefs.h b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_typedefs.h index 335611d7839..1a58874306e 100644 --- a/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_typedefs.h +++ b/extension/jemalloc/jemalloc/include/jemalloc/jemalloc_typedefs.h @@ -6,7 +6,7 @@ typedef struct extent_hooks_s extent_hooks_t; * size_t alignment, bool *zero, bool *commit, unsigned arena_ind); */ typedef void *(extent_alloc_t)(extent_hooks_t *, void *, size_t, size_t, bool *, - bool *, unsigned); + bool *, unsigned); /* * bool @@ -14,7 +14,7 @@ typedef void *(extent_alloc_t)(extent_hooks_t *, void *, size_t, size_t, bool *, * bool committed, unsigned arena_ind); */ typedef bool (extent_dalloc_t)(extent_hooks_t *, void *, size_t, bool, - unsigned); + unsigned); /* * void @@ -22,7 +22,7 @@ typedef bool (extent_dalloc_t)(extent_hooks_t *, void *, size_t, bool, * bool committed, unsigned arena_ind); */ typedef void (extent_destroy_t)(extent_hooks_t *, void *, size_t, bool, - unsigned); + unsigned); /* * bool @@ -30,7 +30,7 @@ typedef void (extent_destroy_t)(extent_hooks_t *, void *, size_t, bool, * size_t offset, size_t length, unsigned arena_ind); */ typedef bool (extent_commit_t)(extent_hooks_t *, void *, size_t, size_t, size_t, - unsigned); + unsigned); /* * bool @@ -38,7 +38,7 @@ typedef bool (extent_commit_t)(extent_hooks_t *, void *, size_t, size_t, size_t, * size_t offset, size_t length, unsigned arena_ind); */ typedef bool (extent_decommit_t)(extent_hooks_t *, void *, size_t, size_t, - size_t, unsigned); + size_t, unsigned); /* * bool @@ -46,7 +46,7 @@ typedef bool (extent_decommit_t)(extent_hooks_t *, void *, size_t, size_t, * size_t offset, size_t length, unsigned arena_ind); */ typedef bool (extent_purge_t)(extent_hooks_t *, void *, size_t, size_t, size_t, - unsigned); + unsigned); /* * bool @@ -54,7 +54,7 @@ typedef bool (extent_purge_t)(extent_hooks_t *, void *, size_t, size_t, size_t, * size_t size_a, size_t size_b, bool committed, unsigned arena_ind); */ typedef bool (extent_split_t)(extent_hooks_t *, void *, size_t, size_t, size_t, - bool, unsigned); + bool, unsigned); /* * bool @@ -62,7 +62,7 @@ typedef bool (extent_split_t)(extent_hooks_t *, void *, size_t, size_t, size_t, * void *addr_b, size_t size_b, bool committed, unsigned arena_ind); */ typedef bool (extent_merge_t)(extent_hooks_t *, void *, size_t, void *, size_t, - bool, unsigned); + bool, unsigned); struct extent_hooks_s { extent_alloc_t *alloc; diff --git a/extension/jemalloc/jemalloc/include/msvc_compat/C99/stdbool.h b/extension/jemalloc/jemalloc/include/msvc_compat/C99/stdbool.h new file mode 100644 index 00000000000..d92160ebc75 --- /dev/null +++ b/extension/jemalloc/jemalloc/include/msvc_compat/C99/stdbool.h @@ -0,0 +1,20 @@ +#ifndef stdbool_h +#define stdbool_h + +#include + +/* MSVC doesn't define _Bool or bool in C, but does have BOOL */ +/* Note this doesn't pass autoconf's test because (bool) 0.5 != true */ +/* Clang-cl uses MSVC headers, so needs msvc_compat, but has _Bool as + * a built-in type. */ +#ifndef __clang__ +typedef BOOL _Bool; +#endif + +#define bool _Bool +#define true 1 +#define false 0 + +#define __bool_true_false_are_defined 1 + +#endif /* stdbool_h */ diff --git a/extension/jemalloc/jemalloc/include/msvc_compat/C99/stdint.h b/extension/jemalloc/jemalloc/include/msvc_compat/C99/stdint.h new file mode 100644 index 00000000000..c66fbb817c0 --- /dev/null +++ b/extension/jemalloc/jemalloc/include/msvc_compat/C99/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/extension/jemalloc/jemalloc/include/msvc_compat/strings.h b/extension/jemalloc/jemalloc/include/msvc_compat/strings.h index bb927c0d475..996f256ce84 100644 --- a/extension/jemalloc/jemalloc/include/msvc_compat/strings.h +++ b/extension/jemalloc/jemalloc/include/msvc_compat/strings.h @@ -1,8 +1,6 @@ #ifndef strings_h #define strings_h -namespace duckdb_jemalloc { - /* MSVC doesn't define ffs/ffsl. This dummy strings.h header is provided * for both */ #ifdef _MSC_VER @@ -57,6 +55,4 @@ static __forceinline int ffsll(unsigned __int64 x) { # define ffs(x) __builtin_ffs(x) #endif -} // namespace duckdb_jemalloc - #endif /* strings_h */ diff --git a/extension/jemalloc/jemalloc/include/msvc_compat/windows_extra.h b/extension/jemalloc/jemalloc/include/msvc_compat/windows_extra.h index 45bd1060128..a6ebb9306f2 100644 --- a/extension/jemalloc/jemalloc/include/msvc_compat/windows_extra.h +++ b/extension/jemalloc/jemalloc/include/msvc_compat/windows_extra.h @@ -1,10 +1,6 @@ #ifndef MSVC_COMPAT_WINDOWS_EXTRA_H #define MSVC_COMPAT_WINDOWS_EXTRA_H -namespace duckdb_jemalloc { - -#include - -} // namespace duckdb_jemalloc +#include #endif /* MSVC_COMPAT_WINDOWS_EXTRA_H */ diff --git a/extension/jemalloc/jemalloc/src/arena.cpp b/extension/jemalloc/jemalloc/src/arena.c similarity index 86% rename from extension/jemalloc/jemalloc/src/arena.cpp rename to extension/jemalloc/jemalloc/src/arena.c index 706140d9f32..8c87d67f6cf 100644 --- a/extension/jemalloc/jemalloc/src/arena.cpp +++ b/extension/jemalloc/jemalloc/src/arena.c @@ -12,8 +12,6 @@ #include "jemalloc/internal/safety_check.h" #include "jemalloc/internal/util.h" -namespace duckdb_jemalloc { - JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS /******************************************************************************/ @@ -23,7 +21,7 @@ JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS * Define names for both unininitialized and initialized phases, so that * options and mallctl processing are straightforward. */ -const char *percpu_arena_mode_names[] = { +const char *const percpu_arena_mode_names[] = { "percpu", "phycpu", "disabled", @@ -39,7 +37,7 @@ static atomic_zd_t dirty_decay_ms_default; static atomic_zd_t muzzy_decay_ms_default; emap_t arena_emap_global; -pa_central_t arena_pa_central_global; +static pa_central_t arena_pa_central_global; div_info_t arena_binind_div_info[SC_NBINS]; @@ -94,8 +92,10 @@ arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, arena_basic_stats_merge(tsdn, arena, nthreads, dss, dirty_decay_ms, muzzy_decay_ms, nactive, ndirty, nmuzzy); - size_t base_allocated, base_resident, base_mapped, metadata_thp; - base_stats_get(tsdn, arena->base, &base_allocated, &base_resident, + size_t base_allocated, base_edata_allocated, base_rtree_allocated, + base_resident, base_mapped, metadata_thp; + base_stats_get(tsdn, arena->base, &base_allocated, + &base_edata_allocated, &base_rtree_allocated, &base_resident, &base_mapped, &metadata_thp); size_t pac_mapped_sz = pac_mapped(&arena->pa_shard.pac); astats->mapped += base_mapped + pac_mapped_sz; @@ -104,22 +104,27 @@ arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, LOCKEDINT_MTX_LOCK(tsdn, arena->stats.mtx); astats->base += base_allocated; + astats->metadata_edata += base_edata_allocated; + astats->metadata_rtree += base_rtree_allocated; atomic_load_add_store_zu(&astats->internal, arena_internal_get(arena)); astats->metadata_thp += metadata_thp; for (szind_t i = 0; i < SC_NSIZES - SC_NBINS; i++) { - uint64_t nmalloc = locked_read_u64(tsdn, - LOCKEDINT_MTX(arena->stats.mtx), - &arena->stats.lstats[i].nmalloc); - locked_inc_u64_unsynchronized(&lstats[i].nmalloc, nmalloc); - astats->nmalloc_large += nmalloc; - + /* ndalloc should be read before nmalloc, + * since otherwise it is possible for ndalloc to be incremented, + * and the following can become true: ndalloc > nmalloc */ uint64_t ndalloc = locked_read_u64(tsdn, LOCKEDINT_MTX(arena->stats.mtx), &arena->stats.lstats[i].ndalloc); locked_inc_u64_unsynchronized(&lstats[i].ndalloc, ndalloc); astats->ndalloc_large += ndalloc; + uint64_t nmalloc = locked_read_u64(tsdn, + LOCKEDINT_MTX(arena->stats.mtx), + &arena->stats.lstats[i].nmalloc); + locked_inc_u64_unsynchronized(&lstats[i].nmalloc, nmalloc); + astats->nmalloc_large += nmalloc; + uint64_t nrequests = locked_read_u64(tsdn, LOCKEDINT_MTX(arena->stats.mtx), &arena->stats.lstats[i].nrequests); @@ -156,12 +161,14 @@ arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, malloc_mutex_lock(tsdn, &arena->tcache_ql_mtx); cache_bin_array_descriptor_t *descriptor; ql_foreach(descriptor, &arena->cache_bin_array_descriptor_ql, link) { - for (szind_t i = 0; i < nhbins; i++) { + for (szind_t i = 0; i < TCACHE_NBINS_MAX; i++) { cache_bin_t *cache_bin = &descriptor->bins[i]; - cache_bin_sz_t ncached, nstashed; - cache_bin_nitems_get_remote(cache_bin, - &tcache_bin_info[i], &ncached, &nstashed); + if (cache_bin_disabled(cache_bin)) { + continue; + } + cache_bin_sz_t ncached, nstashed; + cache_bin_nitems_get_remote(cache_bin, &ncached, &nstashed); astats->tcache_bytes += ncached * sz_index2size(i); astats->tcache_stashed_bytes += nstashed * sz_index2size(i); @@ -235,7 +242,7 @@ arena_slab_reg_alloc(edata_t *slab, const bin_info_t *bin_info) { assert(!bitmap_full(slab_data->bitmap, &bin_info->bitmap_info)); regind = bitmap_sfu(slab_data->bitmap, &bin_info->bitmap_info); - ret = (void *)((uintptr_t)edata_addr_get(slab) + + ret = (void *)((byte_t *)edata_addr_get(slab) + (uintptr_t)(bin_info->reg_size * regind)); edata_nfree_dec(slab); return ret; @@ -279,6 +286,7 @@ arena_slab_reg_alloc_batch(edata_t *slab, const bin_info_t *bin_info, while (pop--) { size_t bit = cfs_lu(&g); size_t regind = shift + bit; + /* NOLINTNEXTLINE(performance-no-int-to-ptr) */ *(ptrs + i) = (void *)(base + regsize * regind); i++; @@ -291,34 +299,48 @@ arena_slab_reg_alloc_batch(edata_t *slab, const bin_info_t *bin_info, static void arena_large_malloc_stats_update(tsdn_t *tsdn, arena_t *arena, size_t usize) { - szind_t index, hindex; - cassert(config_stats); + szind_t index = sz_size2index(usize); + /* This only occurs when we have a sampled small allocation */ if (usize < SC_LARGE_MINCLASS) { - usize = SC_LARGE_MINCLASS; + assert(index < SC_NBINS); + assert(usize >= PAGE && usize % PAGE == 0); + bin_t *bin = arena_get_bin(arena, index, /* binshard */ 0); + malloc_mutex_lock(tsdn, &bin->lock); + bin->stats.nmalloc++; + malloc_mutex_unlock(tsdn, &bin->lock); + } else { + assert(index >= SC_NBINS); + szind_t hindex = index - SC_NBINS; + LOCKEDINT_MTX_LOCK(tsdn, arena->stats.mtx); + locked_inc_u64(tsdn, LOCKEDINT_MTX(arena->stats.mtx), + &arena->stats.lstats[hindex].nmalloc, 1); + LOCKEDINT_MTX_UNLOCK(tsdn, arena->stats.mtx); } - index = sz_size2index(usize); - hindex = (index >= SC_NBINS) ? index - SC_NBINS : 0; - - locked_inc_u64(tsdn, LOCKEDINT_MTX(arena->stats.mtx), - &arena->stats.lstats[hindex].nmalloc, 1); } static void arena_large_dalloc_stats_update(tsdn_t *tsdn, arena_t *arena, size_t usize) { - szind_t index, hindex; - cassert(config_stats); + szind_t index = sz_size2index(usize); + /* This only occurs when we have a sampled small allocation */ if (usize < SC_LARGE_MINCLASS) { - usize = SC_LARGE_MINCLASS; + assert(index < SC_NBINS); + assert(usize >= PAGE && usize % PAGE == 0); + bin_t *bin = arena_get_bin(arena, index, /* binshard */ 0); + malloc_mutex_lock(tsdn, &bin->lock); + bin->stats.ndalloc++; + malloc_mutex_unlock(tsdn, &bin->lock); + } else { + assert(index >= SC_NBINS); + szind_t hindex = index - SC_NBINS; + LOCKEDINT_MTX_LOCK(tsdn, arena->stats.mtx); + locked_inc_u64(tsdn, LOCKEDINT_MTX(arena->stats.mtx), + &arena->stats.lstats[hindex].ndalloc, 1); + LOCKEDINT_MTX_UNLOCK(tsdn, arena->stats.mtx); } - index = sz_size2index(usize); - hindex = (index >= SC_NBINS) ? index - SC_NBINS : 0; - - locked_inc_u64(tsdn, LOCKEDINT_MTX(arena->stats.mtx), - &arena->stats.lstats[hindex].ndalloc, 1); } static void @@ -337,21 +359,39 @@ arena_extent_alloc_large(tsdn_t *tsdn, arena_t *arena, size_t usize, bool guarded = san_large_extent_decide_guard(tsdn, arena_get_ehooks(arena), esize, alignment); + + /* + * - if usize >= opt_calloc_madvise_threshold, + * - pa_alloc(..., zero_override = zero, ...) + * - otherwise, + * - pa_alloc(..., zero_override = false, ...) + * - use memset() to zero out memory if zero == true. + */ + bool zero_override = zero && (usize >= opt_calloc_madvise_threshold); edata_t *edata = pa_alloc(tsdn, &arena->pa_shard, esize, alignment, - /* slab */ false, szind, zero, guarded, &deferred_work_generated); - assert(deferred_work_generated == false); + /* slab */ false, szind, zero_override, guarded, + &deferred_work_generated); - if (edata != NULL) { - if (config_stats) { - LOCKEDINT_MTX_LOCK(tsdn, arena->stats.mtx); - arena_large_malloc_stats_update(tsdn, arena, usize); - LOCKEDINT_MTX_UNLOCK(tsdn, arena->stats.mtx); - } + if (edata == NULL) { + return NULL; } - if (edata != NULL && sz_large_pad != 0) { + if (config_stats) { + arena_large_malloc_stats_update(tsdn, arena, usize); + } + if (sz_large_pad != 0) { arena_cache_oblivious_randomize(tsdn, arena, edata, alignment); } + /* + * This branch should be put after the randomization so that the addr + * returned by edata_addr_get() has already be randomized, + * if cache_oblivious is enabled. + */ + if (zero && !zero_override && !edata_zeroed_get(edata)) { + void *addr = edata_addr_get(edata); + size_t usize = edata_usize_get(edata); + memset(addr, 0, usize); + } return edata; } @@ -359,10 +399,8 @@ arena_extent_alloc_large(tsdn_t *tsdn, arena_t *arena, size_t usize, void arena_extent_dalloc_large_prep(tsdn_t *tsdn, arena_t *arena, edata_t *edata) { if (config_stats) { - LOCKEDINT_MTX_LOCK(tsdn, arena->stats.mtx); arena_large_dalloc_stats_update(tsdn, arena, edata_usize_get(edata)); - LOCKEDINT_MTX_UNLOCK(tsdn, arena->stats.mtx); } } @@ -372,9 +410,7 @@ arena_extent_ralloc_large_shrink(tsdn_t *tsdn, arena_t *arena, edata_t *edata, size_t usize = edata_usize_get(edata); if (config_stats) { - LOCKEDINT_MTX_LOCK(tsdn, arena->stats.mtx); arena_large_ralloc_stats_update(tsdn, arena, oldusize, usize); - LOCKEDINT_MTX_UNLOCK(tsdn, arena->stats.mtx); } } @@ -384,9 +420,7 @@ arena_extent_ralloc_large_expand(tsdn_t *tsdn, arena_t *arena, edata_t *edata, size_t usize = edata_usize_get(edata); if (config_stats) { - LOCKEDINT_MTX_LOCK(tsdn, arena->stats.mtx); arena_large_ralloc_stats_update(tsdn, arena, oldusize, usize); - LOCKEDINT_MTX_UNLOCK(tsdn, arena->stats.mtx); } } @@ -658,6 +692,79 @@ arena_bin_reset(tsd_t *tsd, arena_t *arena, bin_t *bin) { malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); } +void +arena_prof_promote(tsdn_t *tsdn, void *ptr, size_t usize, size_t bumped_usize) { + cassert(config_prof); + assert(ptr != NULL); + assert(isalloc(tsdn, ptr) == bumped_usize); + assert(sz_can_use_slab(usize)); + + if (config_opt_safety_checks) { + safety_check_set_redzone(ptr, usize, bumped_usize); + } + + edata_t *edata = emap_edata_lookup(tsdn, &arena_emap_global, ptr); + + szind_t szind = sz_size2index(usize); + edata_szind_set(edata, szind); + emap_remap(tsdn, &arena_emap_global, edata, szind, /* slab */ false); + + assert(isalloc(tsdn, ptr) == usize); +} + +static size_t +arena_prof_demote(tsdn_t *tsdn, edata_t *edata, const void *ptr) { + cassert(config_prof); + assert(ptr != NULL); + size_t usize = isalloc(tsdn, ptr); + size_t bumped_usize = sz_sa2u(usize, PROF_SAMPLE_ALIGNMENT); + assert(bumped_usize <= SC_LARGE_MINCLASS && + PAGE_CEILING(bumped_usize) == bumped_usize); + assert(edata_size_get(edata) - bumped_usize <= sz_large_pad); + szind_t szind = sz_size2index(bumped_usize); + + edata_szind_set(edata, szind); + emap_remap(tsdn, &arena_emap_global, edata, szind, /* slab */ false); + + assert(isalloc(tsdn, ptr) == bumped_usize); + + return bumped_usize; +} + +static void +arena_dalloc_promoted_impl(tsdn_t *tsdn, void *ptr, tcache_t *tcache, + bool slow_path, edata_t *edata) { + cassert(config_prof); + assert(opt_prof); + + size_t usize = edata_usize_get(edata); + size_t bumped_usize = arena_prof_demote(tsdn, edata, ptr); + if (config_opt_safety_checks && usize < SC_LARGE_MINCLASS) { + /* + * Currently, we only do redzoning for small sampled + * allocations. + */ + safety_check_verify_redzone(ptr, usize, bumped_usize); + } + szind_t bumped_ind = sz_size2index(bumped_usize); + if (bumped_usize >= SC_LARGE_MINCLASS && + tcache != NULL && bumped_ind < TCACHE_NBINS_MAX && + !tcache_bin_disabled(bumped_ind, &tcache->bins[bumped_ind], + tcache->tcache_slow)) { + tcache_dalloc_large(tsdn_tsd(tsdn), tcache, ptr, bumped_ind, + slow_path); + } else { + large_dalloc(tsdn, edata); + } +} + +void +arena_dalloc_promoted(tsdn_t *tsdn, void *ptr, tcache_t *tcache, + bool slow_path) { + edata_t *edata = emap_edata_lookup(tsdn, &arena_emap_global, ptr); + arena_dalloc_promoted_impl(tsdn, ptr, tcache, slow_path, edata); +} + void arena_reset(tsd_t *tsd, arena_t *arena) { /* @@ -696,7 +803,12 @@ arena_reset(tsd_t *tsd, arena_t *arena) { if (config_prof && opt_prof) { prof_free(tsd, ptr, usize, &alloc_ctx); } - large_dalloc(tsd_tsdn(tsd), edata); + if (config_prof && opt_prof && alloc_ctx.szind < SC_NBINS) { + arena_dalloc_promoted_impl(tsd_tsdn(tsd), ptr, + /* tcache */ NULL, /* slow_path */ true, edata); + } else { + large_dalloc(tsd_tsdn(tsd), edata); + } malloc_mutex_lock(tsd_tsdn(tsd), &arena->large_mtx); } malloc_mutex_unlock(tsd_tsdn(tsd), &arena->large_mtx); @@ -928,15 +1040,14 @@ arena_bin_choose(tsdn_t *tsdn, arena_t *arena, szind_t binind, void arena_cache_bin_fill_small(tsdn_t *tsdn, arena_t *arena, - cache_bin_t *cache_bin, cache_bin_info_t *cache_bin_info, szind_t binind, - const unsigned nfill) { - assert(cache_bin_ncached_get_local(cache_bin, cache_bin_info) == 0); + cache_bin_t *cache_bin, szind_t binind, const cache_bin_sz_t nfill) { + assert(cache_bin_ncached_get_local(cache_bin) == 0); + assert(nfill != 0); const bin_info_t *bin_info = &bin_infos[binind]; CACHE_BIN_PTR_ARRAY_DECLARE(ptrs, nfill); - cache_bin_init_ptr_array_for_fill(cache_bin, cache_bin_info, &ptrs, - nfill); + cache_bin_init_ptr_array_for_fill(cache_bin, &ptrs, nfill); /* * Bin-local resources are used first: 1) bin->slabcur, and 2) nonfull * slabs. After both are exhausted, new slabs will be allocated through @@ -966,7 +1077,7 @@ arena_cache_bin_fill_small(tsdn_t *tsdn, arena_t *arena, bool made_progress = true; edata_t *fresh_slab = NULL; bool alloc_and_retry = false; - unsigned filled = 0; + cache_bin_sz_t filled = 0; unsigned binshard; bin_t *bin = arena_bin_choose(tsdn, arena, binind, &binshard); @@ -1050,7 +1161,7 @@ arena_cache_bin_fill_small(tsdn_t *tsdn, arena_t *arena, fresh_slab = NULL; } - cache_bin_finish_fill(cache_bin, cache_bin_info, &ptrs, filled); + cache_bin_finish_fill(cache_bin, &ptrs, filled); arena_decay_tick(tsdn, arena); } @@ -1191,7 +1302,7 @@ arena_malloc_small(tsdn_t *tsdn, arena_t *arena, szind_t binind, bool zero) { void * arena_malloc_hard(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind, - bool zero) { + bool zero, bool slab) { assert(!tsdn_null(tsdn) || arena != NULL); if (likely(!tsdn_null(tsdn))) { @@ -1201,18 +1312,19 @@ arena_malloc_hard(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind, return NULL; } - if (likely(size <= SC_SMALL_MAXCLASS)) { + if (likely(slab)) { + assert(sz_can_use_slab(size)); return arena_malloc_small(tsdn, arena, ind, zero); + } else { + return large_malloc(tsdn, arena, sz_index2size(ind), zero); } - return large_malloc(tsdn, arena, sz_index2size(ind), zero); } void * arena_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, - bool zero, tcache_t *tcache) { - void *ret; - - if (usize <= SC_SMALL_MAXCLASS) { + bool zero, bool slab, tcache_t *tcache) { + if (slab) { + assert(sz_can_use_slab(usize)); /* Small; alignment doesn't require special slab placement. */ /* usize should be a result of sz_sa2u() */ @@ -1223,74 +1335,15 @@ arena_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, */ assert(alignment <= PAGE); - ret = arena_malloc(tsdn, arena, usize, sz_size2index(usize), - zero, tcache, true); + return arena_malloc(tsdn, arena, usize, sz_size2index(usize), + zero, slab, tcache, true); } else { if (likely(alignment <= CACHELINE)) { - ret = large_malloc(tsdn, arena, usize, zero); + return large_malloc(tsdn, arena, usize, zero); } else { - ret = large_palloc(tsdn, arena, usize, alignment, zero); + return large_palloc(tsdn, arena, usize, alignment, zero); } } - return ret; -} - -void -arena_prof_promote(tsdn_t *tsdn, void *ptr, size_t usize) { - cassert(config_prof); - assert(ptr != NULL); - assert(isalloc(tsdn, ptr) == SC_LARGE_MINCLASS); - assert(usize <= SC_SMALL_MAXCLASS); - - if (config_opt_safety_checks) { - safety_check_set_redzone(ptr, usize, SC_LARGE_MINCLASS); - } - - edata_t *edata = emap_edata_lookup(tsdn, &arena_emap_global, ptr); - - szind_t szind = sz_size2index(usize); - edata_szind_set(edata, szind); - emap_remap(tsdn, &arena_emap_global, edata, szind, /* slab */ false); - - assert(isalloc(tsdn, ptr) == usize); -} - -static size_t -arena_prof_demote(tsdn_t *tsdn, edata_t *edata, const void *ptr) { - cassert(config_prof); - assert(ptr != NULL); - - edata_szind_set(edata, SC_NBINS); - emap_remap(tsdn, &arena_emap_global, edata, SC_NBINS, /* slab */ false); - - assert(isalloc(tsdn, ptr) == SC_LARGE_MINCLASS); - - return SC_LARGE_MINCLASS; -} - -void -arena_dalloc_promoted(tsdn_t *tsdn, void *ptr, tcache_t *tcache, - bool slow_path) { - cassert(config_prof); - assert(opt_prof); - - edata_t *edata = emap_edata_lookup(tsdn, &arena_emap_global, ptr); - size_t usize = edata_usize_get(edata); - size_t bumped_usize = arena_prof_demote(tsdn, edata, ptr); - if (config_opt_safety_checks && usize < SC_LARGE_MINCLASS) { - /* - * Currently, we only do redzoning for small sampled - * allocations. - */ - assert(bumped_usize == SC_LARGE_MINCLASS); - safety_check_verify_redzone(ptr, usize, bumped_usize); - } - if (bumped_usize <= tcache_maxclass && tcache != NULL) { - tcache_dalloc_large(tsdn_tsd(tsdn), tcache, ptr, - sz_size2index(bumped_usize), slow_path); - } else { - large_dalloc(tsdn, edata); - } } static void @@ -1402,16 +1455,13 @@ arena_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, assert(extra == 0 || size + extra <= SC_LARGE_MAXCLASS); edata_t *edata = emap_edata_lookup(tsdn, &arena_emap_global, ptr); - size_t usize_min; - size_t usize_max; - if (unlikely(size > SC_LARGE_MAXCLASS)) { ret = true; goto done; } - usize_min = sz_s2u(size); - usize_max = sz_s2u(size + extra); + size_t usize_min = sz_s2u(size); + size_t usize_max = sz_s2u(size + extra); if (likely(oldsize <= SC_SMALL_MAXCLASS && usize_min <= SC_SMALL_MAXCLASS)) { /* @@ -1446,28 +1496,30 @@ arena_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, static void * arena_ralloc_move_helper(tsdn_t *tsdn, arena_t *arena, size_t usize, - size_t alignment, bool zero, tcache_t *tcache) { + size_t alignment, bool zero, bool slab, tcache_t *tcache) { if (alignment == 0) { return arena_malloc(tsdn, arena, usize, sz_size2index(usize), - zero, tcache, true); + zero, slab, tcache, true); } usize = sz_sa2u(usize, alignment); if (unlikely(usize == 0 || usize > SC_LARGE_MAXCLASS)) { return NULL; } - return ipalloct(tsdn, usize, alignment, zero, tcache, arena); + return ipalloct_explicit_slab(tsdn, usize, alignment, zero, slab, + tcache, arena); } void * arena_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t oldsize, - size_t size, size_t alignment, bool zero, tcache_t *tcache, + size_t size, size_t alignment, bool zero, bool slab, tcache_t *tcache, hook_ralloc_args_t *hook_args) { size_t usize = alignment == 0 ? sz_s2u(size) : sz_sa2u(size, alignment); if (unlikely(usize == 0 || size > SC_LARGE_MAXCLASS)) { return NULL; } - if (likely(usize <= SC_SMALL_MAXCLASS)) { + if (likely(slab)) { + assert(sz_can_use_slab(usize)); /* Try to avoid moving the allocation. */ UNUSED size_t newsize; if (!arena_ralloc_no_move(tsdn, ptr, oldsize, usize, 0, zero, @@ -1491,7 +1543,7 @@ arena_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t oldsize, * object. In that case, fall back to allocating new space and copying. */ void *ret = arena_ralloc_move_helper(tsdn, arena, usize, alignment, - zero, tcache); + zero, slab, tcache); if (ret == NULL) { return NULL; } @@ -1549,6 +1601,22 @@ arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec) { return false; } +void +arena_name_get(arena_t *arena, char *name) { + char *end = (char *)memchr((void *)arena->name, '\0', ARENA_NAME_LEN); + assert(end != NULL); + size_t len = (uintptr_t)end - (uintptr_t)arena->name + 1; + assert(len > 0 && len <= ARENA_NAME_LEN); + + strncpy(name, arena->name, len); +} + +void +arena_name_set(arena_t *arena, const char *name) { + strncpy(arena->name, name, ARENA_NAME_LEN); + arena->name[ARENA_NAME_LEN - 1] = '\0'; +} + ssize_t arena_dirty_decay_ms_default_get(void) { return atomic_load_zd(&dirty_decay_ms_default, ATOMIC_RELAXED); @@ -1616,11 +1684,16 @@ arena_new(tsdn_t *tsdn, unsigned ind, const arena_config_t *config) { } } - size_t arena_size = sizeof(arena_t) + sizeof(bin_t) * nbins_total; + size_t arena_size = ALIGNMENT_CEILING(sizeof(arena_t), CACHELINE) + + sizeof(bin_t) * nbins_total; arena = (arena_t *)base_alloc(tsdn, base, arena_size, CACHELINE); if (arena == NULL) { goto label_error; } + JEMALLOC_SUPPRESS_WARN_ON_USAGE( + assert((uintptr_t)&arena->all_bins[nbins_total -1] + sizeof(bin_t) <= + (uintptr_t)arena + arena_size); + ) atomic_store_u(&arena->nthreads[0], 0, ATOMIC_RELAXED); atomic_store_u(&arena->nthreads[1], 0, ATOMIC_RELAXED); @@ -1661,7 +1734,9 @@ arena_new(tsdn_t *tsdn, unsigned ind, const arena_config_t *config) { /* Initialize bins. */ atomic_store_u(&arena->binshard_next, 0, ATOMIC_RELEASE); for (i = 0; i < nbins_total; i++) { - bool err = bin_init(arena->bins + i); + JEMALLOC_SUPPRESS_WARN_ON_USAGE( + bool err = bin_init(&arena->all_bins[i]); + ) if (err) { goto label_error; } @@ -1672,6 +1747,11 @@ arena_new(tsdn_t *tsdn, unsigned ind, const arena_config_t *config) { arena_set(ind, arena); arena->ind = ind; + /* Init the name. */ + malloc_snprintf(arena->name, sizeof(arena->name), "%s_%u", + arena_is_auto(arena) ? "auto" : "manual", arena->ind); + arena->name[ARENA_NAME_LEN - 1] = '\0'; + nstime_init_update(&arena->create_time); /* @@ -1712,6 +1792,42 @@ arena_new(tsdn_t *tsdn, unsigned ind, const arena_config_t *config) { return NULL; } +static arena_t * +arena_create_huge_arena(tsd_t *tsd, unsigned ind) { + assert(ind != 0); + + arena_t *huge_arena = arena_get(tsd_tsdn(tsd), ind, true); + if (huge_arena == NULL) { + return NULL; + } + + char *huge_arena_name = "auto_oversize"; + strncpy(huge_arena->name, huge_arena_name, ARENA_NAME_LEN); + huge_arena->name[ARENA_NAME_LEN - 1] = '\0'; + + /* + * Purge eagerly for huge allocations, because: 1) number of huge + * allocations is usually small, which means ticker based decay is not + * reliable; and 2) less immediate reuse is expected for huge + * allocations. + * + * However, with background threads enabled, keep normal purging since + * the purging delay is bounded. + */ + if (!background_thread_enabled() + && arena_dirty_decay_ms_default_get() > 0) { + arena_decay_ms_set(tsd_tsdn(tsd), huge_arena, + extent_state_dirty, 0); + } + if (!background_thread_enabled() + &&arena_muzzy_decay_ms_default_get() > 0) { + arena_decay_ms_set(tsd_tsdn(tsd), huge_arena, + extent_state_muzzy, 0); + } + + return huge_arena; +} + arena_t * arena_choose_huge(tsd_t *tsd) { /* huge_arena_ind can be 0 during init (will use a0). */ @@ -1722,32 +1838,14 @@ arena_choose_huge(tsd_t *tsd) { arena_t *huge_arena = arena_get(tsd_tsdn(tsd), huge_arena_ind, false); if (huge_arena == NULL) { /* Create the huge arena on demand. */ - assert(huge_arena_ind != 0); - huge_arena = arena_get(tsd_tsdn(tsd), huge_arena_ind, true); - if (huge_arena == NULL) { - return NULL; - } - /* - * Purge eagerly for huge allocations, because: 1) number of - * huge allocations is usually small, which means ticker based - * decay is not reliable; and 2) less immediate reuse is - * expected for huge allocations. - */ - if (arena_dirty_decay_ms_default_get() > 0) { - arena_decay_ms_set(tsd_tsdn(tsd), huge_arena, - extent_state_dirty, 0); - } - if (arena_muzzy_decay_ms_default_get() > 0) { - arena_decay_ms_set(tsd_tsdn(tsd), huge_arena, - extent_state_muzzy, 0); - } + huge_arena = arena_create_huge_arena(tsd, huge_arena_ind); } return huge_arena; } bool -arena_init_huge(void) { +arena_init_huge(arena_t *a0) { bool huge_enabled; /* The threshold should be large size class. */ @@ -1760,6 +1858,9 @@ arena_init_huge(void) { /* Reserve the index for the huge arena. */ huge_arena_ind = narenas_total_get(); oversize_threshold = opt_oversize_threshold; + /* a0 init happened before malloc_conf_init. */ + atomic_store_zu(&a0->pa_shard.pac.oversize_threshold, + oversize_threshold, ATOMIC_RELAXED); huge_enabled = true; } @@ -1784,7 +1885,9 @@ arena_boot(sc_data_t *sc_data, base_t *base, bool hpa) { (1U << sc->lg_base) + (sc->ndelta << sc->lg_delta)); } - uint32_t cur_offset = (uint32_t)offsetof(arena_t, bins); + JEMALLOC_SUPPRESS_WARN_ON_USAGE( + uint32_t cur_offset = (uint32_t)offsetof(arena_t, all_bins); + ) for (szind_t i = 0; i < SC_NBINS; i++) { arena_bin_offsets[i] = cur_offset; nbins_total += bin_infos[i].n_shards; @@ -1839,14 +1942,18 @@ arena_prefork7(tsdn_t *tsdn, arena_t *arena) { void arena_prefork8(tsdn_t *tsdn, arena_t *arena) { for (unsigned i = 0; i < nbins_total; i++) { - bin_prefork(tsdn, arena->bins + i); + JEMALLOC_SUPPRESS_WARN_ON_USAGE( + bin_prefork(tsdn, &arena->all_bins[i]); + ) } } void arena_postfork_parent(tsdn_t *tsdn, arena_t *arena) { for (unsigned i = 0; i < nbins_total; i++) { - bin_postfork_parent(tsdn, arena->bins + i); + JEMALLOC_SUPPRESS_WARN_ON_USAGE( + bin_postfork_parent(tsdn, &arena->all_bins[i]); + ) } malloc_mutex_postfork_parent(tsdn, &arena->large_mtx); @@ -1884,7 +1991,9 @@ arena_postfork_child(tsdn_t *tsdn, arena_t *arena) { } for (unsigned i = 0; i < nbins_total; i++) { - bin_postfork_child(tsdn, arena->bins + i); + JEMALLOC_SUPPRESS_WARN_ON_USAGE( + bin_postfork_child(tsdn, &arena->all_bins[i]); + ) } malloc_mutex_postfork_child(tsdn, &arena->large_mtx); @@ -1894,5 +2003,3 @@ arena_postfork_child(tsdn_t *tsdn, arena_t *arena) { malloc_mutex_postfork_child(tsdn, &arena->tcache_ql_mtx); } } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/background_thread.cpp b/extension/jemalloc/jemalloc/src/background_thread.c similarity index 94% rename from extension/jemalloc/jemalloc/src/background_thread.cpp rename to extension/jemalloc/jemalloc/src/background_thread.c index 8a895889976..eef8b73fac8 100644 --- a/extension/jemalloc/jemalloc/src/background_thread.cpp +++ b/extension/jemalloc/jemalloc/src/background_thread.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/assert.h" -namespace duckdb_jemalloc { - JEMALLOC_DIAGNOSTIC_DISABLE_SPURIOUS /******************************************************************************/ @@ -48,6 +46,42 @@ pthread_create_wrapper(pthread_t *__restrict thread, const pthread_attr_t *attr, return pthread_create_fptr(thread, attr, start_routine, arg); } + +#ifdef JEMALLOC_HAVE_DLSYM +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#endif + +static bool +pthread_create_fptr_init(void) { + if (pthread_create_fptr != NULL) { + return false; + } + /* + * Try the next symbol first, because 1) when use lazy_lock we have a + * wrapper for pthread_create; and 2) application may define its own + * wrapper as well (and can call malloc within the wrapper). + */ +#ifdef JEMALLOC_HAVE_DLSYM + pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create"); +#else + pthread_create_fptr = NULL; +#endif + if (pthread_create_fptr == NULL) { + if (config_lazy_lock) { + malloc_write(": Error in dlsym(RTLD_NEXT, " + "\"pthread_create\")\n"); + abort(); + } else { + /* Fall back to the default symbol. */ + pthread_create_fptr = pthread_create; + } + } + + return false; +} #endif /* JEMALLOC_PTHREAD_CREATE_WRAPPER */ #ifndef JEMALLOC_BACKGROUND_THREAD @@ -82,6 +116,7 @@ background_thread_info_init(tsdn_t *tsdn, background_thread_info_t *info) { static inline bool set_current_thread_affinity(int cpu) { +#if defined(JEMALLOC_HAVE_SCHED_SETAFFINITY) || defined(JEMALLOC_HAVE_PTHREAD_SETAFFINITY_NP) #if defined(JEMALLOC_HAVE_SCHED_SETAFFINITY) cpu_set_t cpuset; #else @@ -112,6 +147,9 @@ set_current_thread_affinity(int cpu) { # endif return ret != 0; #endif +#else + return false; +#endif } #define BILLION UINT64_C(1000000000) @@ -298,15 +336,16 @@ background_thread_create_signals_masked(pthread_t *thread, "failed (%d), and signal mask restoration failed " "(%d)\n", create_err, restore_err); if (opt_abort) { - jemalloc_abort(); + abort(); } } return create_err; } static bool -check_background_thread_creation(tsd_t *tsd, unsigned *n_created, - bool *created_threads) { +check_background_thread_creation(tsd_t *tsd, + const size_t const_max_background_threads, + unsigned *n_created, bool *created_threads) { bool ret = false; if (likely(*n_created == n_background_threads)) { return ret; @@ -314,7 +353,7 @@ check_background_thread_creation(tsd_t *tsd, unsigned *n_created, tsdn_t *tsdn = tsd_tsdn(tsd); malloc_mutex_unlock(tsdn, &background_thread_info[0].mtx); - for (unsigned i = 1; i < max_background_threads; i++) { + for (unsigned i = 1; i < const_max_background_threads; i++) { if (created_threads[i]) { continue; } @@ -332,6 +371,7 @@ check_background_thread_creation(tsd_t *tsd, unsigned *n_created, pre_reentrancy(tsd, NULL); int err = background_thread_create_signals_masked(&info->thread, + /* NOLINTNEXTLINE(performance-no-int-to-ptr) */ NULL, background_thread_entry, (void *)(uintptr_t)i); post_reentrancy(tsd); @@ -342,7 +382,7 @@ check_background_thread_creation(tsd_t *tsd, unsigned *n_created, malloc_printf(": background thread " "creation failed (%d)\n", err); if (opt_abort) { - jemalloc_abort(); + abort(); } } /* Return to restart the loop since we unlocked. */ @@ -356,10 +396,19 @@ check_background_thread_creation(tsd_t *tsd, unsigned *n_created, static void background_thread0_work(tsd_t *tsd) { - /* Thread0 is also responsible for launching / terminating threads. */ - VARIABLE_ARRAY(bool, created_threads, max_background_threads); + /* + * Thread0 is also responsible for launching / terminating threads. + * We are guaranteed that `max_background_threads` will not change + * underneath us. Unfortunately static analysis tools do not understand + * this, so we are extracting `max_background_threads` into a local + * variable solely for the sake of exposing this information to such + * tools. + */ + const size_t const_max_background_threads = max_background_threads; + assert(const_max_background_threads > 0); + VARIABLE_ARRAY(bool, created_threads, const_max_background_threads); unsigned i; - for (i = 1; i < max_background_threads; i++) { + for (i = 1; i < const_max_background_threads; i++) { created_threads[i] = false; } /* Start working, and create more threads when asked. */ @@ -369,8 +418,8 @@ background_thread0_work(tsd_t *tsd) { &background_thread_info[0])) { continue; } - if (check_background_thread_creation(tsd, &n_created, - (bool *)&created_threads)) { + if (check_background_thread_creation(tsd, const_max_background_threads, + &n_created, (bool *)&created_threads)) { continue; } background_work_sleep_once(tsd_tsdn(tsd), @@ -382,7 +431,7 @@ background_thread0_work(tsd_t *tsd) { * the global background_thread mutex (and is waiting) for us. */ assert(!background_thread_enabled()); - for (i = 1; i < max_background_threads; i++) { + for (i = 1; i < const_max_background_threads; i++) { background_thread_info_t *info = &background_thread_info[i]; assert(info->state != background_thread_paused); if (created_threads[i]) { @@ -432,7 +481,7 @@ background_thread_entry(void *ind_arg) { assert(thread_ind < max_background_threads); #ifdef JEMALLOC_HAVE_PTHREAD_SETNAME_NP pthread_setname_np(pthread_self(), "jemalloc_bg_thd"); -#elif defined(__FreeBSD__) || defined(__DragonFly__) +#elif defined(JEMALLOC_HAVE_PTHREAD_SET_NAME_NP) pthread_set_name_np(pthread_self(), "jemalloc_bg_thd"); #endif if (opt_percpu_arena != percpu_arena_disabled) { @@ -495,6 +544,7 @@ background_thread_create_locked(tsd_t *tsd, unsigned arena_ind) { * background threads with the underlying pthread_create. */ int err = background_thread_create_signals_masked(&info->thread, NULL, + /* NOLINTNEXTLINE(performance-no-int-to-ptr) */ background_thread_entry, (void *)thread_ind); post_reentrancy(tsd); @@ -533,7 +583,7 @@ background_threads_enable(tsd_t *tsd) { VARIABLE_ARRAY(bool, marked, max_background_threads); unsigned nmarked; - for (unsigned i = 0; i < max_background_threads; i++) { + for (size_t i = 0; i < max_background_threads; i++) { marked[i] = false; } nmarked = 0; @@ -708,43 +758,6 @@ background_thread_stats_read(tsdn_t *tsdn, background_thread_stats_t *stats) { #undef BILLION #undef BACKGROUND_THREAD_MIN_INTERVAL_NS -} // namespace duckdb_jemalloc - -#ifdef JEMALLOC_HAVE_DLSYM -#include -#endif - -namespace duckdb_jemalloc { - -static bool -pthread_create_fptr_init(void) { - if (pthread_create_fptr != NULL) { - return false; - } - /* - * Try the next symbol first, because 1) when use lazy_lock we have a - * wrapper for pthread_create; and 2) application may define its own - * wrapper as well (and can call malloc within the wrapper). - */ -#ifdef JEMALLOC_HAVE_DLSYM - pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create"); -#else - pthread_create_fptr = NULL; -#endif - if (pthread_create_fptr == NULL) { - if (config_lazy_lock) { - malloc_write(": Error in dlsym(RTLD_NEXT, " - "\"pthread_create\")\n"); - jemalloc_abort(); - } else { - /* Fall back to the default symbol. */ - pthread_create_fptr = pthread_create; - } - } - - return false; -} - /* * When lazy lock is enabled, we need to make sure setting isthreaded before * taking any background_thread locks. This is called early in ctl (instead of @@ -824,5 +837,3 @@ background_thread_boot1(tsdn_t *tsdn, base_t *base) { return false; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/base.cpp b/extension/jemalloc/jemalloc/src/base.c similarity index 72% rename from extension/jemalloc/jemalloc/src/base.cpp rename to extension/jemalloc/jemalloc/src/base.c index 676ab2d9372..1d5e8fcda3c 100644 --- a/extension/jemalloc/jemalloc/src/base.cpp +++ b/extension/jemalloc/jemalloc/src/base.c @@ -6,8 +6,6 @@ #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/sz.h" -namespace duckdb_jemalloc { - /* * In auto mode, arenas switch to huge pages for the base allocator on the * second base block. a0 switches to thp on the 5th block (after 20 megabytes @@ -24,7 +22,7 @@ static base_t *b0; metadata_thp_mode_t opt_metadata_thp = METADATA_THP_DEFAULT; -const char *metadata_thp_mode_names[] = { +const char *const metadata_thp_mode_names[] = { "disabled", "auto", "always" @@ -112,6 +110,16 @@ base_unmap(tsdn_t *tsdn, ehooks_t *ehooks, unsigned ind, void *addr, } } +static inline bool +base_edata_is_reused(edata_t *edata) { + /* + * Borrow the guarded bit to indicate if the extent is a recycled one, + * i.e. the ones returned to base for reuse; currently only tcache bin + * stacks. Skips stats updating if so (needed for this purpose only). + */ + return edata_guarded_get(edata); +} + static void base_edata_init(size_t *extent_sn_next, edata_t *edata, void *addr, size_t size) { @@ -120,7 +128,7 @@ base_edata_init(size_t *extent_sn_next, edata_t *edata, void *addr, sn = *extent_sn_next; (*extent_sn_next)++; - edata_binit(edata, addr, size, sn); + edata_binit(edata, addr, size, sn, false /* is_reused */); } static size_t @@ -183,28 +191,61 @@ base_extent_bump_alloc_helper(edata_t *edata, size_t *gap_size, size_t size, *gap_size = ALIGNMENT_CEILING((uintptr_t)edata_addr_get(edata), alignment) - (uintptr_t)edata_addr_get(edata); - ret = (void *)((uintptr_t)edata_addr_get(edata) + *gap_size); + ret = (void *)((byte_t *)edata_addr_get(edata) + *gap_size); assert(edata_bsize_get(edata) >= *gap_size + size); - edata_binit(edata, (void *)((uintptr_t)edata_addr_get(edata) + + edata_binit(edata, (void *)((byte_t *)edata_addr_get(edata) + *gap_size + size), edata_bsize_get(edata) - *gap_size - size, - edata_sn_get(edata)); + edata_sn_get(edata), base_edata_is_reused(edata)); return ret; } static void -base_extent_bump_alloc_post(base_t *base, edata_t *edata, size_t gap_size, - void *addr, size_t size) { +base_edata_heap_insert(tsdn_t *tsdn, base_t *base, edata_t *edata) { + malloc_mutex_assert_owner(tsdn, &base->mtx); + + size_t bsize = edata_bsize_get(edata); + assert(bsize > 0); + /* + * Compute the index for the largest size class that does not exceed + * extent's size. + */ + szind_t index_floor = sz_size2index(bsize + 1) - 1; + edata_heap_insert(&base->avail[index_floor], edata); +} + +/* + * Only can be called by top-level functions, since it may call base_alloc + * internally when cache is empty. + */ +static edata_t * +base_alloc_base_edata(tsdn_t *tsdn, base_t *base) { + edata_t *edata; + + malloc_mutex_lock(tsdn, &base->mtx); + edata = edata_avail_first(&base->edata_avail); + if (edata != NULL) { + edata_avail_remove(&base->edata_avail, edata); + } + malloc_mutex_unlock(tsdn, &base->mtx); + + if (edata == NULL) { + edata = base_alloc_edata(tsdn, base); + } + + return edata; +} + +static void +base_extent_bump_alloc_post(tsdn_t *tsdn, base_t *base, edata_t *edata, + size_t gap_size, void *addr, size_t size) { if (edata_bsize_get(edata) > 0) { - /* - * Compute the index for the largest size class that does not - * exceed extent's size. - */ - szind_t index_floor = - sz_size2index(edata_bsize_get(edata) + 1) - 1; - edata_heap_insert(&base->avail[index_floor], edata); + base_edata_heap_insert(tsdn, base, edata); + } else { + /* Freed base edata_t stored in edata_avail. */ + edata_avail_insert(&base->edata_avail, edata); } - if (config_stats) { + if (config_stats && !base_edata_is_reused(edata)) { base->allocated += size; /* * Add one PAGE to base_resident for every page boundary that is @@ -226,13 +267,13 @@ base_extent_bump_alloc_post(base_t *base, edata_t *edata, size_t gap_size, } static void * -base_extent_bump_alloc(base_t *base, edata_t *edata, size_t size, +base_extent_bump_alloc(tsdn_t *tsdn, base_t *base, edata_t *edata, size_t size, size_t alignment) { void *ret; size_t gap_size; ret = base_extent_bump_alloc_helper(edata, &gap_size, size, alignment); - base_extent_bump_alloc_post(base, edata, gap_size, ret, size); + base_extent_bump_alloc_post(tsdn, base, edata, gap_size, ret, size); return ret; } @@ -293,7 +334,7 @@ base_block_alloc(tsdn_t *tsdn, base_t *base, ehooks_t *ehooks, unsigned ind, block->next = NULL; assert(block_size >= header_size); base_edata_init(extent_sn_next, &block->edata, - (void *)((uintptr_t)block + header_size), block_size - header_size); + (void *)((byte_t *)block + header_size), block_size - header_size); return block; } @@ -386,7 +427,11 @@ base_new(tsdn_t *tsdn, unsigned ind, const extent_hooks_t *extent_hooks, for (szind_t i = 0; i < SC_NSIZES; i++) { edata_heap_new(&base->avail[i]); } + edata_avail_new(&base->edata_avail); + if (config_stats) { + base->edata_allocated = 0; + base->rtree_allocated = 0; base->allocated = sizeof(base_block_t); base->resident = PAGE_CEILING(sizeof(base_block_t)); base->mapped = block->size; @@ -397,8 +442,12 @@ base_new(tsdn_t *tsdn, unsigned ind, const extent_hooks_t *extent_hooks, assert(base->resident <= base->mapped); assert(base->n_thp << LG_HUGEPAGE <= base->mapped); } - base_extent_bump_alloc_post(base, &block->edata, gap_size, base, + + /* Locking here is only necessary because of assertions. */ + malloc_mutex_lock(tsdn, &base->mtx); + base_extent_bump_alloc_post(tsdn, base, &block->edata, gap_size, base, base_size); + malloc_mutex_unlock(tsdn, &base->mtx); return base; } @@ -435,7 +484,7 @@ base_extent_hooks_set(base_t *base, extent_hooks_t *extent_hooks) { static void * base_alloc_impl(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment, - size_t *esn) { + size_t *esn, size_t *ret_usize) { alignment = QUANTUM_CEILING(alignment); size_t usize = ALIGNMENT_CEILING(size, alignment); size_t asize = usize + alignment - QUANTUM; @@ -459,10 +508,13 @@ base_alloc_impl(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment, goto label_return; } - ret = base_extent_bump_alloc(base, edata, usize, alignment); + ret = base_extent_bump_alloc(tsdn, base, edata, usize, alignment); if (esn != NULL) { *esn = (size_t)edata_sn_get(edata); } + if (ret_usize != NULL) { + *ret_usize = usize; + } label_return: malloc_mutex_unlock(tsdn, &base->mtx); return ret; @@ -478,30 +530,120 @@ base_alloc_impl(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment, */ void * base_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment) { - return base_alloc_impl(tsdn, base, size, alignment, NULL); + return base_alloc_impl(tsdn, base, size, alignment, NULL, NULL); } edata_t * base_alloc_edata(tsdn_t *tsdn, base_t *base) { - size_t esn; - edata_t *edata = (edata_t *)base_alloc_impl(tsdn, base, sizeof(edata_t), - EDATA_ALIGNMENT, &esn); + size_t esn, usize; + edata_t *edata = base_alloc_impl(tsdn, base, sizeof(edata_t), + EDATA_ALIGNMENT, &esn, &usize); if (edata == NULL) { return NULL; } + if (config_stats) { + base->edata_allocated += usize; + } edata_esn_set(edata, esn); return edata; } +void * +base_alloc_rtree(tsdn_t *tsdn, base_t *base, size_t size) { + size_t usize; + void *rtree = base_alloc_impl(tsdn, base, size, CACHELINE, NULL, + &usize); + if (rtree == NULL) { + return NULL; + } + if (config_stats) { + base->rtree_allocated += usize; + } + return rtree; +} + +static inline void +b0_alloc_header_size(size_t *header_size, size_t *alignment) { + *alignment = QUANTUM; + *header_size = QUANTUM > sizeof(edata_t *) ? QUANTUM : + sizeof(edata_t *); +} + +/* + * Each piece allocated here is managed by a separate edata, because it was bump + * allocated and cannot be merged back into the original base_block. This means + * it's not for general purpose: 1) they are not page aligned, nor page sized, + * and 2) the requested size should not be too small (as each piece comes with + * an edata_t). Only used for tcache bin stack allocation now. + */ +void * +b0_alloc_tcache_stack(tsdn_t *tsdn, size_t stack_size) { + base_t *base = b0get(); + edata_t *edata = base_alloc_base_edata(tsdn, base); + if (edata == NULL) { + return NULL; + } + + /* + * Reserve room for the header, which stores a pointer to the managing + * edata_t. The header itself is located right before the return + * address, so that edata can be retrieved on dalloc. Bump up to usize + * to improve reusability -- otherwise the freed stacks will be put back + * into the previous size class. + */ + size_t esn, alignment, header_size; + b0_alloc_header_size(&header_size, &alignment); + + size_t alloc_size = sz_s2u(stack_size + header_size); + void *addr = base_alloc_impl(tsdn, base, alloc_size, alignment, &esn, + NULL); + if (addr == NULL) { + edata_avail_insert(&base->edata_avail, edata); + return NULL; + } + + /* Set is_reused: see comments in base_edata_is_reused. */ + edata_binit(edata, addr, alloc_size, esn, true /* is_reused */); + *(edata_t **)addr = edata; + + return (byte_t *)addr + header_size; +} + +void +b0_dalloc_tcache_stack(tsdn_t *tsdn, void *tcache_stack) { + /* edata_t pointer stored in header. */ + size_t alignment, header_size; + b0_alloc_header_size(&header_size, &alignment); + + edata_t *edata = *(edata_t **)((byte_t *)tcache_stack - header_size); + void *addr = edata_addr_get(edata); + size_t bsize = edata_bsize_get(edata); + /* Marked as "reused" to avoid double counting stats. */ + assert(base_edata_is_reused(edata)); + assert(addr != NULL && bsize > 0); + + /* Zero out since base_alloc returns zeroed memory. */ + memset(addr, 0, bsize); + + base_t *base = b0get(); + malloc_mutex_lock(tsdn, &base->mtx); + base_edata_heap_insert(tsdn, base, edata); + malloc_mutex_unlock(tsdn, &base->mtx); +} + void -base_stats_get(tsdn_t *tsdn, base_t *base, size_t *allocated, size_t *resident, +base_stats_get(tsdn_t *tsdn, base_t *base, size_t *allocated, + size_t *edata_allocated, size_t *rtree_allocated, size_t *resident, size_t *mapped, size_t *n_thp) { cassert(config_stats); malloc_mutex_lock(tsdn, &base->mtx); assert(base->allocated <= base->resident); assert(base->resident <= base->mapped); + assert(base->edata_allocated + base->rtree_allocated <= base->allocated); *allocated = base->allocated; + *edata_allocated = base->edata_allocated; + *rtree_allocated = base->rtree_allocated; *resident = base->resident; *mapped = base->mapped; *n_thp = base->n_thp; @@ -529,5 +671,3 @@ base_boot(tsdn_t *tsdn) { /* metadata_use_hooks */ true); return (b0 == NULL); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/bin.cpp b/extension/jemalloc/jemalloc/src/bin.c similarity index 96% rename from extension/jemalloc/jemalloc/src/bin.cpp rename to extension/jemalloc/jemalloc/src/bin.c index 513b2960233..fa20458705a 100644 --- a/extension/jemalloc/jemalloc/src/bin.cpp +++ b/extension/jemalloc/jemalloc/src/bin.c @@ -6,8 +6,6 @@ #include "jemalloc/internal/sc.h" #include "jemalloc/internal/witness.h" -namespace duckdb_jemalloc { - bool bin_update_shard_size(unsigned bin_shard_sizes[SC_NBINS], size_t start_size, size_t end_size, size_t nshards) { @@ -69,5 +67,3 @@ void bin_postfork_child(tsdn_t *tsdn, bin_t *bin) { malloc_mutex_postfork_child(tsdn, &bin->lock); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/bin_info.cpp b/extension/jemalloc/jemalloc/src/bin_info.c similarity index 94% rename from extension/jemalloc/jemalloc/src/bin_info.cpp rename to extension/jemalloc/jemalloc/src/bin_info.c index e750b03d642..8629ef8817d 100644 --- a/extension/jemalloc/jemalloc/src/bin_info.cpp +++ b/extension/jemalloc/jemalloc/src/bin_info.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/bin_info.h" -namespace duckdb_jemalloc { - bin_info_t bin_infos[SC_NBINS]; static void @@ -30,5 +28,3 @@ bin_info_boot(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) { assert(sc_data->initialized); bin_infos_init(sc_data, bin_shard_sizes, bin_infos); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/bitmap.cpp b/extension/jemalloc/jemalloc/src/bitmap.c similarity index 98% rename from extension/jemalloc/jemalloc/src/bitmap.cpp rename to extension/jemalloc/jemalloc/src/bitmap.c index d33d88fb9aa..0ccedc5db5b 100644 --- a/extension/jemalloc/jemalloc/src/bitmap.cpp +++ b/extension/jemalloc/jemalloc/src/bitmap.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/assert.h" -namespace duckdb_jemalloc { - /******************************************************************************/ #ifdef BITMAP_USE_TREE @@ -120,5 +118,3 @@ size_t bitmap_size(const bitmap_info_t *binfo) { return (bitmap_info_ngroups(binfo) << LG_SIZEOF_BITMAP); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/buf_writer.cpp b/extension/jemalloc/jemalloc/src/buf_writer.c similarity index 96% rename from extension/jemalloc/jemalloc/src/buf_writer.cpp rename to extension/jemalloc/jemalloc/src/buf_writer.c index a810fea2efb..7c6f79403c0 100644 --- a/extension/jemalloc/jemalloc/src/buf_writer.cpp +++ b/extension/jemalloc/jemalloc/src/buf_writer.c @@ -4,8 +4,6 @@ #include "jemalloc/internal/buf_writer.h" #include "jemalloc/internal/malloc_io.h" -namespace duckdb_jemalloc { - static void * buf_writer_allocate_internal_buf(tsdn_t *tsdn, size_t buf_len) { #ifdef JEMALLOC_JET @@ -54,7 +52,7 @@ buf_writer_init(tsdn_t *tsdn, buf_writer_t *buf_writer, write_cb_t *write_cb, buf_writer->buf = buf; buf_writer->internal_buf = false; } else { - buf_writer->buf = (char *)buf_writer_allocate_internal_buf(tsdn, + buf_writer->buf = buf_writer_allocate_internal_buf(tsdn, buf_len); buf_writer->internal_buf = true; } @@ -144,5 +142,3 @@ buf_writer_pipe(buf_writer_t *buf_writer, read_cb_t *read_cb, } while (nread > 0); buf_writer_flush(buf_writer); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/cache_bin.cpp b/extension/jemalloc/jemalloc/src/cache_bin.c similarity index 57% rename from extension/jemalloc/jemalloc/src/cache_bin.cpp rename to extension/jemalloc/jemalloc/src/cache_bin.c index 1e4939208d7..6438705f0e9 100644 --- a/extension/jemalloc/jemalloc/src/cache_bin.cpp +++ b/extension/jemalloc/jemalloc/src/cache_bin.c @@ -5,7 +5,7 @@ #include "jemalloc/internal/cache_bin.h" #include "jemalloc/internal/safety_check.h" -namespace duckdb_jemalloc { +const uintptr_t disabled_bin = JUNK_ADDR; void cache_bin_info_init(cache_bin_info_t *info, @@ -16,8 +16,19 @@ cache_bin_info_init(cache_bin_info_t *info, info->ncached_max = (cache_bin_sz_t)ncached_max; } +bool +cache_bin_stack_use_thp(void) { + /* + * If metadata_thp is enabled, allocating tcache stack from the base + * allocator for efficiency gains. The downside, however, is that base + * allocator never purges freed memory, and may cache a fair amount of + * memory after many threads are terminated and not reused. + */ + return metadata_thp_enabled(); +} + void -cache_bin_info_compute_alloc(cache_bin_info_t *infos, szind_t ninfos, +cache_bin_info_compute_alloc(const cache_bin_info_t *infos, szind_t ninfos, size_t *size, size_t *alignment) { /* For the total bin stack region (per tcache), reserve 2 more slots so * that @@ -28,19 +39,19 @@ cache_bin_info_compute_alloc(cache_bin_info_t *infos, szind_t ninfos, */ *size = sizeof(void *) * 2; for (szind_t i = 0; i < ninfos; i++) { - assert(infos[i].ncached_max > 0); *size += infos[i].ncached_max * sizeof(void *); } /* - * Align to at least PAGE, to minimize the # of TLBs needed by the - * smaller sizes; also helps if the larger sizes don't get used at all. + * When not using THP, align to at least PAGE, to minimize the # of TLBs + * needed by the smaller sizes; also helps if the larger sizes don't get + * used at all. */ - *alignment = PAGE; + *alignment = cache_bin_stack_use_thp() ? QUANTUM : PAGE; } void -cache_bin_preincrement(cache_bin_info_t *infos, szind_t ninfos, void *alloc, +cache_bin_preincrement(const cache_bin_info_t *infos, szind_t ninfos, void *alloc, size_t *cur_offset) { if (config_debug) { size_t computed_size; @@ -52,52 +63,57 @@ cache_bin_preincrement(cache_bin_info_t *infos, szind_t ninfos, void *alloc, assert(((uintptr_t)alloc & (computed_alignment - 1)) == 0); } - *(uintptr_t *)((uintptr_t)alloc + *cur_offset) = + *(uintptr_t *)((byte_t *)alloc + *cur_offset) = cache_bin_preceding_junk; *cur_offset += sizeof(void *); } void -cache_bin_postincrement(cache_bin_info_t *infos, szind_t ninfos, void *alloc, - size_t *cur_offset) { - *(uintptr_t *)((uintptr_t)alloc + *cur_offset) = +cache_bin_postincrement(void *alloc, size_t *cur_offset) { + *(uintptr_t *)((byte_t *)alloc + *cur_offset) = cache_bin_trailing_junk; *cur_offset += sizeof(void *); } void -cache_bin_init(cache_bin_t *bin, cache_bin_info_t *info, void *alloc, +cache_bin_init(cache_bin_t *bin, const cache_bin_info_t *info, void *alloc, size_t *cur_offset) { /* * The full_position points to the lowest available space. Allocations * will access the slots toward higher addresses (for the benefit of * adjacent prefetch). */ - void *stack_cur = (void *)((uintptr_t)alloc + *cur_offset); + void *stack_cur = (void *)((byte_t *)alloc + *cur_offset); void *full_position = stack_cur; uint16_t bin_stack_size = info->ncached_max * sizeof(void *); *cur_offset += bin_stack_size; - void *empty_position = (void *)((uintptr_t)alloc + *cur_offset); + void *empty_position = (void *)((byte_t *)alloc + *cur_offset); /* Init to the empty position. */ bin->stack_head = (void **)empty_position; bin->low_bits_low_water = (uint16_t)(uintptr_t)bin->stack_head; bin->low_bits_full = (uint16_t)(uintptr_t)full_position; bin->low_bits_empty = (uint16_t)(uintptr_t)empty_position; + cache_bin_info_init(&bin->bin_info, info->ncached_max); cache_bin_sz_t free_spots = cache_bin_diff(bin, - bin->low_bits_full, (uint16_t)(uintptr_t)bin->stack_head, - /* racy */ false); + bin->low_bits_full, (uint16_t)(uintptr_t)bin->stack_head); assert(free_spots == bin_stack_size); - assert(cache_bin_ncached_get_local(bin, info) == 0); + if (!cache_bin_disabled(bin)) { + assert(cache_bin_ncached_get_local(bin) == 0); + } assert(cache_bin_empty_position_get(bin) == empty_position); assert(bin_stack_size > 0 || empty_position == full_position); } -bool -cache_bin_still_zero_initialized(cache_bin_t *bin) { - return bin->stack_head == NULL; +void +cache_bin_init_disabled(cache_bin_t *bin, cache_bin_sz_t ncached_max) { + const void *fake_stack = cache_bin_disabled_bin_stack(); + size_t fake_offset = 0; + cache_bin_info_t fake_info; + cache_bin_info_init(&fake_info, 0); + cache_bin_init(bin, &fake_info, (void *)fake_stack, &fake_offset); + cache_bin_info_init(&bin->bin_info, ncached_max); + assert(fake_offset == 0); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/ckh.cpp b/extension/jemalloc/jemalloc/src/ckh.c similarity index 99% rename from extension/jemalloc/jemalloc/src/ckh.cpp rename to extension/jemalloc/jemalloc/src/ckh.c index 9b3343081b7..8db4319c51d 100644 --- a/extension/jemalloc/jemalloc/src/ckh.cpp +++ b/extension/jemalloc/jemalloc/src/ckh.c @@ -35,18 +35,17 @@ * ******************************************************************************/ #include "jemalloc/internal/jemalloc_preamble.h" -#include "jemalloc/internal/jemalloc_internal_includes.h" #include "jemalloc/internal/ckh.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + #include "jemalloc/internal/assert.h" #include "jemalloc/internal/hash.h" #include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/prng.h" #include "jemalloc/internal/util.h" -namespace duckdb_jemalloc { - /******************************************************************************/ /* Function prototypes for non-inline static functions. */ @@ -568,5 +567,3 @@ bool ckh_pointer_keycomp(const void *k1, const void *k2) { return (k1 == k2); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/counter.cpp b/extension/jemalloc/jemalloc/src/counter.c similarity index 93% rename from extension/jemalloc/jemalloc/src/counter.cpp rename to extension/jemalloc/jemalloc/src/counter.c index 987b91a1afa..8f1ae3af45e 100644 --- a/extension/jemalloc/jemalloc/src/counter.cpp +++ b/extension/jemalloc/jemalloc/src/counter.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/counter.h" -namespace duckdb_jemalloc { - bool counter_accum_init(counter_accum_t *counter, uint64_t interval) { if (LOCKEDINT_MTX_INIT(counter->mtx, "counter_accum", @@ -30,5 +28,3 @@ void counter_postfork_child(tsdn_t *tsdn, counter_accum_t *counter) { LOCKEDINT_MTX_POSTFORK_CHILD(tsdn, counter->mtx); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/ctl.cpp b/extension/jemalloc/jemalloc/src/ctl.c similarity index 92% rename from extension/jemalloc/jemalloc/src/ctl.cpp rename to extension/jemalloc/jemalloc/src/ctl.c index 7b2eed5ee09..37b69576d48 100644 --- a/extension/jemalloc/jemalloc/src/ctl.cpp +++ b/extension/jemalloc/jemalloc/src/ctl.c @@ -18,8 +18,6 @@ #include "jemalloc/internal/sc.h" #include "jemalloc/internal/util.h" -namespace duckdb_jemalloc { - /******************************************************************************/ /* Data. */ @@ -68,7 +66,10 @@ CTL_PROTO(epoch) CTL_PROTO(background_thread) CTL_PROTO(max_background_threads) CTL_PROTO(thread_tcache_enabled) +CTL_PROTO(thread_tcache_max) CTL_PROTO(thread_tcache_flush) +CTL_PROTO(thread_tcache_ncached_max_write) +CTL_PROTO(thread_tcache_ncached_max_read_sizeclass) CTL_PROTO(thread_peak_read) CTL_PROTO(thread_peak_reset) CTL_PROTO(thread_prof_name) @@ -94,6 +95,7 @@ CTL_PROTO(config_xmalloc) CTL_PROTO(opt_abort) CTL_PROTO(opt_abort_conf) CTL_PROTO(opt_cache_oblivious) +CTL_PROTO(opt_debug_double_free_max_scan) CTL_PROTO(opt_trust_madvise) CTL_PROTO(opt_confirm_conf) CTL_PROTO(opt_hpa) @@ -143,6 +145,7 @@ CTL_PROTO(opt_prof) CTL_PROTO(opt_prof_prefix) CTL_PROTO(opt_prof_active) CTL_PROTO(opt_prof_thread_active_init) +CTL_PROTO(opt_prof_bt_max) CTL_PROTO(opt_lg_prof_sample) CTL_PROTO(opt_lg_prof_interval) CTL_PROTO(opt_prof_gdump) @@ -150,12 +153,17 @@ CTL_PROTO(opt_prof_final) CTL_PROTO(opt_prof_leak) CTL_PROTO(opt_prof_leak_error) CTL_PROTO(opt_prof_accum) +CTL_PROTO(opt_prof_pid_namespace) CTL_PROTO(opt_prof_recent_alloc_max) CTL_PROTO(opt_prof_stats) CTL_PROTO(opt_prof_sys_thread_name) CTL_PROTO(opt_prof_time_res) CTL_PROTO(opt_lg_san_uaf_align) CTL_PROTO(opt_zero_realloc) +CTL_PROTO(opt_malloc_conf_symlink) +CTL_PROTO(opt_malloc_conf_env_var) +CTL_PROTO(opt_malloc_conf_global_var) +CTL_PROTO(opt_malloc_conf_global_var_2_conf_harder) CTL_PROTO(tcache_create) CTL_PROTO(tcache_flush) CTL_PROTO(tcache_destroy) @@ -170,6 +178,7 @@ CTL_PROTO(arena_i_dirty_decay_ms) CTL_PROTO(arena_i_muzzy_decay_ms) CTL_PROTO(arena_i_extent_hooks) CTL_PROTO(arena_i_retain_grow_limit) +CTL_PROTO(arena_i_name) INDEX_PROTO(arena_i) CTL_PROTO(arenas_bin_i_size) CTL_PROTO(arenas_bin_i_nregs) @@ -292,6 +301,8 @@ CTL_PROTO(stats_arenas_i_muzzy_nmadvise) CTL_PROTO(stats_arenas_i_muzzy_purged) CTL_PROTO(stats_arenas_i_base) CTL_PROTO(stats_arenas_i_internal) +CTL_PROTO(stats_arenas_i_metadata_edata) +CTL_PROTO(stats_arenas_i_metadata_rtree) CTL_PROTO(stats_arenas_i_metadata_thp) CTL_PROTO(stats_arenas_i_tcache_bytes) CTL_PROTO(stats_arenas_i_tcache_stashed_bytes) @@ -305,6 +316,8 @@ CTL_PROTO(stats_background_thread_num_threads) CTL_PROTO(stats_background_thread_num_runs) CTL_PROTO(stats_background_thread_run_interval) CTL_PROTO(stats_metadata) +CTL_PROTO(stats_metadata_edata) +CTL_PROTO(stats_metadata_rtree) CTL_PROTO(stats_metadata_thp) CTL_PROTO(stats_resident) CTL_PROTO(stats_mapped) @@ -314,6 +327,8 @@ CTL_PROTO(experimental_hooks_install) CTL_PROTO(experimental_hooks_remove) CTL_PROTO(experimental_hooks_prof_backtrace) CTL_PROTO(experimental_hooks_prof_dump) +CTL_PROTO(experimental_hooks_prof_sample) +CTL_PROTO(experimental_hooks_prof_sample_free) CTL_PROTO(experimental_hooks_safety_check_abort) CTL_PROTO(experimental_thread_activity_callback) CTL_PROTO(experimental_utilization_query) @@ -366,9 +381,17 @@ CTL_PROTO(stats_mutexes_reset) */ #define INDEX(i) {false}, i##_index +static const ctl_named_node_t thread_tcache_ncached_max_node[] = { + {NAME("read_sizeclass"), + CTL(thread_tcache_ncached_max_read_sizeclass)}, + {NAME("write"), CTL(thread_tcache_ncached_max_write)} +}; + static const ctl_named_node_t thread_tcache_node[] = { {NAME("enabled"), CTL(thread_tcache_enabled)}, - {NAME("flush"), CTL(thread_tcache_flush)} + {NAME("max"), CTL(thread_tcache_max)}, + {NAME("flush"), CTL(thread_tcache_flush)}, + {NAME("ncached_max"), CHILD(named, thread_tcache_ncached_max)} }; static const ctl_named_node_t thread_peak_node[] = { @@ -408,6 +431,14 @@ static const ctl_named_node_t config_node[] = { {NAME("xmalloc"), CTL(config_xmalloc)} }; +static const ctl_named_node_t opt_malloc_conf_node[] = { + {NAME("symlink"), CTL(opt_malloc_conf_symlink)}, + {NAME("env_var"), CTL(opt_malloc_conf_env_var)}, + {NAME("global_var"), CTL(opt_malloc_conf_global_var)}, + {NAME("global_var_2_conf_harder"), + CTL(opt_malloc_conf_global_var_2_conf_harder)} +}; + static const ctl_named_node_t opt_node[] = { {NAME("abort"), CTL(opt_abort)}, {NAME("abort_conf"), CTL(opt_abort_conf)}, @@ -469,6 +500,7 @@ static const ctl_named_node_t opt_node[] = { {NAME("prof_prefix"), CTL(opt_prof_prefix)}, {NAME("prof_active"), CTL(opt_prof_active)}, {NAME("prof_thread_active_init"), CTL(opt_prof_thread_active_init)}, + {NAME("prof_bt_max"), CTL(opt_prof_bt_max)}, {NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)}, {NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)}, {NAME("prof_gdump"), CTL(opt_prof_gdump)}, @@ -476,12 +508,16 @@ static const ctl_named_node_t opt_node[] = { {NAME("prof_leak"), CTL(opt_prof_leak)}, {NAME("prof_leak_error"), CTL(opt_prof_leak_error)}, {NAME("prof_accum"), CTL(opt_prof_accum)}, + {NAME("prof_pid_namespace"), CTL(opt_prof_pid_namespace)}, {NAME("prof_recent_alloc_max"), CTL(opt_prof_recent_alloc_max)}, {NAME("prof_stats"), CTL(opt_prof_stats)}, {NAME("prof_sys_thread_name"), CTL(opt_prof_sys_thread_name)}, {NAME("prof_time_resolution"), CTL(opt_prof_time_res)}, {NAME("lg_san_uaf_align"), CTL(opt_lg_san_uaf_align)}, - {NAME("zero_realloc"), CTL(opt_zero_realloc)} + {NAME("zero_realloc"), CTL(opt_zero_realloc)}, + {NAME("debug_double_free_max_scan"), + CTL(opt_debug_double_free_max_scan)}, + {NAME("malloc_conf"), CHILD(named, opt_malloc_conf)} }; static const ctl_named_node_t tcache_node[] = { @@ -501,11 +537,12 @@ static const ctl_named_node_t arena_i_node[] = { * Undocumented for now, since we anticipate an arena API in flux after * we cut the last 5-series release. */ - {NAME("oversize_threshold"), CTL(arena_i_oversize_threshold)}, - {NAME("dirty_decay_ms"), CTL(arena_i_dirty_decay_ms)}, - {NAME("muzzy_decay_ms"), CTL(arena_i_muzzy_decay_ms)}, - {NAME("extent_hooks"), CTL(arena_i_extent_hooks)}, - {NAME("retain_grow_limit"), CTL(arena_i_retain_grow_limit)} + {NAME("oversize_threshold"), CTL(arena_i_oversize_threshold)}, + {NAME("dirty_decay_ms"), CTL(arena_i_dirty_decay_ms)}, + {NAME("muzzy_decay_ms"), CTL(arena_i_muzzy_decay_ms)}, + {NAME("extent_hooks"), CTL(arena_i_extent_hooks)}, + {NAME("retain_grow_limit"), CTL(arena_i_retain_grow_limit)}, + {NAME("name"), CTL(arena_i_name)} }; static const ctl_named_node_t super_arena_i_node[] = { {NAME(""), CHILD(named, arena_i)} @@ -792,6 +829,8 @@ static const ctl_named_node_t stats_arenas_i_node[] = { {NAME("muzzy_purged"), CTL(stats_arenas_i_muzzy_purged)}, {NAME("base"), CTL(stats_arenas_i_base)}, {NAME("internal"), CTL(stats_arenas_i_internal)}, + {NAME("metadata_edata"), CTL(stats_arenas_i_metadata_edata)}, + {NAME("metadata_rtree"), CTL(stats_arenas_i_metadata_rtree)}, {NAME("metadata_thp"), CTL(stats_arenas_i_metadata_thp)}, {NAME("tcache_bytes"), CTL(stats_arenas_i_tcache_bytes)}, {NAME("tcache_stashed_bytes"), @@ -837,6 +876,8 @@ static const ctl_named_node_t stats_node[] = { {NAME("allocated"), CTL(stats_allocated)}, {NAME("active"), CTL(stats_active)}, {NAME("metadata"), CTL(stats_metadata)}, + {NAME("metadata_edata"), CTL(stats_metadata_edata)}, + {NAME("metadata_rtree"), CTL(stats_metadata_rtree)}, {NAME("metadata_thp"), CTL(stats_metadata_thp)}, {NAME("resident"), CTL(stats_resident)}, {NAME("mapped"), CTL(stats_mapped)}, @@ -853,6 +894,8 @@ static const ctl_named_node_t experimental_hooks_node[] = { {NAME("remove"), CTL(experimental_hooks_remove)}, {NAME("prof_backtrace"), CTL(experimental_hooks_prof_backtrace)}, {NAME("prof_dump"), CTL(experimental_hooks_prof_dump)}, + {NAME("prof_sample"), CTL(experimental_hooks_prof_sample)}, + {NAME("prof_sample_free"), CTL(experimental_hooks_prof_sample_free)}, {NAME("safety_check_abort"), CTL(experimental_hooks_safety_check_abort)}, }; @@ -1033,23 +1076,7 @@ ctl_arena_clear(ctl_arena_t *ctl_arena) { ctl_arena->pdirty = 0; ctl_arena->pmuzzy = 0; if (config_stats) { - memset(&ctl_arena->astats->astats, 0, sizeof(arena_stats_t)); - ctl_arena->astats->allocated_small = 0; - ctl_arena->astats->nmalloc_small = 0; - ctl_arena->astats->ndalloc_small = 0; - ctl_arena->astats->nrequests_small = 0; - ctl_arena->astats->nfills_small = 0; - ctl_arena->astats->nflushes_small = 0; - memset(ctl_arena->astats->bstats, 0, SC_NBINS * - sizeof(bin_stats_data_t)); - memset(ctl_arena->astats->lstats, 0, (SC_NSIZES - SC_NBINS) * - sizeof(arena_stats_large_t)); - memset(ctl_arena->astats->estats, 0, SC_NPSIZES * - sizeof(pac_estats_t)); - memset(&ctl_arena->astats->hpastats, 0, - sizeof(hpa_shard_stats_t)); - memset(&ctl_arena->astats->secstats, 0, - sizeof(sec_stats_t)); + memset(ctl_arena->astats, 0, sizeof(*(ctl_arena->astats))); } } @@ -1143,6 +1170,10 @@ MUTEX_PROF_ARENA_MUTEXES #undef OP if (!destroyed) { sdstats->astats.base += astats->astats.base; + sdstats->astats.metadata_edata += astats->astats + .metadata_edata; + sdstats->astats.metadata_rtree += astats->astats + .metadata_rtree; sdstats->astats.resident += astats->astats.resident; sdstats->astats.metadata_thp += astats->astats.metadata_thp; ctl_accum_atomic_zu(&sdstats->astats.internal, @@ -1305,9 +1336,18 @@ ctl_background_thread_stats_read(tsdn_t *tsdn) { static void ctl_refresh(tsdn_t *tsdn) { - unsigned i; + malloc_mutex_assert_owner(tsdn, &ctl_mtx); + /* + * We are guaranteed that `ctl_arenas->narenas` will not change + * underneath us since we hold `ctl_mtx` for the duration of this + * function. Unfortunately static analysis tools do not understand this, + * so we are extracting `narenas` into a local variable solely for the + * sake of exposing this information to such tools. + */ + const unsigned narenas = ctl_arenas->narenas; + assert(narenas > 0); ctl_arena_t *ctl_sarena = arenas_i(MALLCTL_ARENAS_ALL); - VARIABLE_ARRAY(arena_t *, tarenas, ctl_arenas->narenas); + VARIABLE_ARRAY(arena_t *, tarenas, narenas); /* * Clear sum stats, since they will be merged into by @@ -1315,11 +1355,11 @@ ctl_refresh(tsdn_t *tsdn) { */ ctl_arena_clear(ctl_sarena); - for (i = 0; i < ctl_arenas->narenas; i++) { + for (unsigned i = 0; i < narenas; i++) { tarenas[i] = arena_get(tsdn, i, false); } - for (i = 0; i < ctl_arenas->narenas; i++) { + for (unsigned i = 0; i < narenas; i++) { ctl_arena_t *ctl_arena = arenas_i(i); bool initialized = (tarenas[i] != NULL); @@ -1337,6 +1377,10 @@ ctl_refresh(tsdn_t *tsdn) { ctl_stats->metadata = ctl_sarena->astats->astats.base + atomic_load_zu(&ctl_sarena->astats->astats.internal, ATOMIC_RELAXED); + ctl_stats->metadata_edata = ctl_sarena->astats->astats + .metadata_edata; + ctl_stats->metadata_rtree = ctl_sarena->astats->astats + .metadata_rtree; ctl_stats->resident = ctl_sarena->astats->astats.resident; ctl_stats->metadata_thp = ctl_sarena->astats->astats.metadata_thp; @@ -1807,7 +1851,9 @@ ctl_mtx_assert_held(tsdn_t *tsdn) { /* Verify that the space provided is enough. */ #define VERIFY_READ(t) do { \ if (oldp == NULL || oldlenp == NULL || *oldlenp != sizeof(t)) { \ - *oldlenp = 0; \ + if (oldlenp != NULL) { \ + *oldlenp = 0; \ + } \ ret = EINVAL; \ goto label_return; \ } \ @@ -1857,31 +1903,6 @@ ctl_mtx_assert_held(tsdn_t *tsdn) { * There's a lot of code duplication in the following macros due to limitations * in how nested cpp macros are expanded. */ -#define CTL_RO_CLGEN(c, l, n, v, t) \ -static int \ -n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ - size_t *oldlenp, void *newp, size_t newlen) { \ - int ret; \ - t oldval; \ - \ - if (!(c)) { \ - return ENOENT; \ - } \ - if (l) { \ - malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); \ - } \ - READONLY(); \ - oldval = (v); \ - READ(oldval, t); \ - \ - ret = 0; \ -label_return: \ - if (l) { \ - malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); \ - } \ - return ret; \ -} - #define CTL_RO_CGEN(c, n, v, t) \ static int \ n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \ @@ -2130,6 +2151,8 @@ CTL_RO_CONFIG_GEN(config_xmalloc, bool) CTL_RO_NL_GEN(opt_abort, opt_abort, bool) CTL_RO_NL_GEN(opt_abort_conf, opt_abort_conf, bool) CTL_RO_NL_GEN(opt_cache_oblivious, opt_cache_oblivious, bool) +CTL_RO_NL_GEN(opt_debug_double_free_max_scan, + opt_debug_double_free_max_scan, unsigned) CTL_RO_NL_GEN(opt_trust_madvise, opt_trust_madvise, bool) CTL_RO_NL_GEN(opt_confirm_conf, opt_confirm_conf, bool) @@ -2202,8 +2225,11 @@ CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *) CTL_RO_NL_CGEN(config_prof, opt_prof_active, opt_prof_active, bool) CTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init, opt_prof_thread_active_init, bool) +CTL_RO_NL_CGEN(config_prof, opt_prof_bt_max, opt_prof_bt_max, unsigned) CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t) CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool) +CTL_RO_NL_CGEN(config_prof, opt_prof_pid_namespace, opt_prof_pid_namespace, + bool) CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t) CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool) CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool) @@ -2221,6 +2247,17 @@ CTL_RO_NL_CGEN(config_uaf_detection, opt_lg_san_uaf_align, CTL_RO_NL_GEN(opt_zero_realloc, zero_realloc_mode_names[opt_zero_realloc_action], const char *) +/* malloc_conf options */ +CTL_RO_NL_CGEN(opt_malloc_conf_symlink, opt_malloc_conf_symlink, + opt_malloc_conf_symlink, const char *) +CTL_RO_NL_CGEN(opt_malloc_conf_env_var, opt_malloc_conf_env_var, + opt_malloc_conf_env_var, const char *) +CTL_RO_NL_CGEN(je_malloc_conf, opt_malloc_conf_global_var, je_malloc_conf, + const char *) +CTL_RO_NL_CGEN(je_malloc_conf_2_conf_harder, + opt_malloc_conf_global_var_2_conf_harder, je_malloc_conf_2_conf_harder, + const char *) + /******************************************************************************/ static int @@ -2282,6 +2319,78 @@ thread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, CTL_RO_NL_GEN(thread_allocated, tsd_thread_allocated_get(tsd), uint64_t) CTL_RO_NL_GEN(thread_allocatedp, tsd_thread_allocatedp_get(tsd), uint64_t *) + +static int +thread_tcache_ncached_max_read_sizeclass_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { + int ret; + size_t bin_size = 0; + + /* Read the bin size from newp. */ + if (newp == NULL) { + ret = EINVAL; + goto label_return; + } + WRITE(bin_size, size_t); + + cache_bin_sz_t ncached_max = 0; + if (tcache_bin_ncached_max_read(tsd, bin_size, &ncached_max)) { + ret = EINVAL; + goto label_return; + } + size_t result = (size_t)ncached_max; + READ(result, size_t); + ret = 0; +label_return: + return ret; +} + +static int +thread_tcache_ncached_max_write_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { + int ret; + WRITEONLY(); + if (newp != NULL) { + if (!tcache_available(tsd)) { + ret = ENOENT; + goto label_return; + } + char *settings = NULL; + WRITE(settings, char *); + if (settings == NULL) { + ret = EINVAL; + goto label_return; + } + /* Get the length of the setting string safely. */ + char *end = (char *)memchr(settings, '\0', + CTL_MULTI_SETTING_MAX_LEN); + if (end == NULL) { + ret = EINVAL; + goto label_return; + } + /* + * Exclude the last '\0' for len since it is not handled by + * multi_setting_parse_next. + */ + size_t len = (uintptr_t)end - (uintptr_t)settings; + if (len == 0) { + ret = 0; + goto label_return; + } + + if (tcache_bins_ncached_max_write(tsd, settings, len)) { + ret = EINVAL; + goto label_return; + } + } + + ret = 0; +label_return: + return ret; +} + CTL_RO_NL_GEN(thread_deallocated, tsd_thread_deallocated_get(tsd), uint64_t) CTL_RO_NL_GEN(thread_deallocatedp, tsd_thread_deallocatedp_get(tsd), uint64_t *) @@ -2307,6 +2416,40 @@ thread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, return ret; } +static int +thread_tcache_max_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) { + int ret; + size_t oldval; + + /* pointer to tcache_t always exists even with tcache disabled. */ + tcache_t *tcache = tsd_tcachep_get(tsd); + assert(tcache != NULL); + oldval = tcache_max_get(tcache->tcache_slow); + READ(oldval, size_t); + + if (newp != NULL) { + if (newlen != sizeof(size_t)) { + ret = EINVAL; + goto label_return; + } + size_t new_tcache_max = oldval; + WRITE(new_tcache_max, size_t); + if (new_tcache_max > TCACHE_MAXCLASS_LIMIT) { + new_tcache_max = TCACHE_MAXCLASS_LIMIT; + } + new_tcache_max = sz_s2u(new_tcache_max); + if(new_tcache_max != oldval) { + thread_tcache_max_set(tsd, new_tcache_max); + } + } + + ret = 0; +label_return: + return ret; +} + static int thread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, @@ -2335,10 +2478,9 @@ thread_peak_read_ctl(tsd_t *tsd, const size_t *mib, if (!config_stats) { return ENOENT; } - uint64_t result; READONLY(); peak_event_update(tsd); - result = peak_event_max(tsd); + uint64_t result = peak_event_max(tsd); READ(result, uint64_t); ret = 0; label_return: @@ -2373,13 +2515,13 @@ thread_prof_name_ctl(tsd_t *tsd, const size_t *mib, READ_XOR_WRITE(); if (newp != NULL) { - if (newlen != sizeof(const char *)) { + const char *newval = *(const char **)newp; + if (newlen != sizeof(const char *) || newval == NULL) { ret = EINVAL; goto label_return; } - if ((ret = prof_thread_name_set(tsd, *(const char **)newp)) != - 0) { + if ((ret = prof_thread_name_set(tsd, newval)) != 0) { goto label_return; } } else { @@ -2732,7 +2874,6 @@ arena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, int ret; const char *dss = NULL; unsigned arena_ind; - dss_prec_t dss_prec_old = dss_prec_limit; dss_prec_t dss_prec = dss_prec_limit; malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); @@ -2744,7 +2885,7 @@ arena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, for (i = 0; i < dss_prec_limit; i++) { if (strcmp(dss_prec_names[i], dss) == 0) { - dss_prec = (dss_prec_t)i; + dss_prec = i; match = true; break; } @@ -2760,6 +2901,7 @@ arena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, * Access via index narenas is deprecated, and scheduled for removal in * 6.0.0. */ + dss_prec_t dss_prec_old; if (arena_ind == MALLCTL_ARENAS_ALL || arena_ind == ctl_arenas->narenas) { if (dss_prec != dss_prec_limit && @@ -2793,10 +2935,9 @@ arena_i_oversize_threshold_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, int ret; unsigned arena_ind; - arena_t *arena; MIB_UNSIGNED(arena_ind, 1); - arena = arena_get(tsd_tsdn(tsd), arena_ind, false); + arena_t *arena = arena_get(tsd_tsdn(tsd), arena_ind, false); if (arena == NULL) { ret = EFAULT; goto label_return; @@ -2827,14 +2968,13 @@ arena_i_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen, unsigned arena_ind; arena_t *arena; - extent_state_t state; MIB_UNSIGNED(arena_ind, 1); arena = arena_get(tsd_tsdn(tsd), arena_ind, false); if (arena == NULL) { ret = EFAULT; goto label_return; } - state = dirty ? extent_state_dirty : extent_state_muzzy; + extent_state_t state = dirty ? extent_state_dirty : extent_state_muzzy; if (oldp != NULL && oldlenp != NULL) { size_t oldval = arena_decay_ms_get(arena, state); @@ -2980,6 +3120,61 @@ arena_i_retain_grow_limit_ctl(tsd_t *tsd, const size_t *mib, return ret; } +/* + * When writing, newp should point to a char array storing the name to be set. + * A name longer than ARENA_NAME_LEN will be arbitrarily cut. When reading, + * oldp should point to a char array whose length is no shorter than + * ARENA_NAME_LEN or the length of the name when it was set. + */ +static int +arena_i_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned arena_ind; + char *name; + + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); + MIB_UNSIGNED(arena_ind, 1); + if (arena_ind == MALLCTL_ARENAS_ALL || arena_ind >= + ctl_arenas->narenas) { + ret = EINVAL; + goto label_return; + } + arena_t *arena = arena_get(tsd_tsdn(tsd), arena_ind, false); + if (arena == NULL) { + ret = EFAULT; + goto label_return; + } + + if (oldp != NULL && oldlenp != NULL) { + /* + * Read the arena name. When reading, the input oldp should + * point to an array with a length no shorter than + * ARENA_NAME_LEN or the length when it was set. + */ + if (*oldlenp != sizeof(char *)) { + ret = EINVAL; + goto label_return; + } + name = *(char **)oldp; + arena_name_get(arena, name); + } + + if (newp != NULL) { + /* Write the arena name. */ + WRITE(name, char *); + if (name == NULL) { + ret = EINVAL; + goto label_return; + } + arena_name_set(arena, name); + } + ret = 0; +label_return: + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); + return ret; +} + static const ctl_named_node_t * arena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i) { @@ -3067,9 +3262,9 @@ arenas_muzzy_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t) CTL_RO_NL_GEN(arenas_page, PAGE, size_t) -CTL_RO_NL_GEN(arenas_tcache_max, tcache_maxclass, size_t) +CTL_RO_NL_GEN(arenas_tcache_max, global_do_not_change_tcache_maxclass, size_t) CTL_RO_NL_GEN(arenas_nbins, SC_NBINS, unsigned) -CTL_RO_NL_GEN(arenas_nhbins, nhbins, unsigned) +CTL_RO_NL_GEN(arenas_nhbins, global_do_not_change_tcache_nbins, unsigned) CTL_RO_NL_GEN(arenas_bin_i_size, bin_infos[mib[2]].reg_size, size_t) CTL_RO_NL_GEN(arenas_bin_i_nregs, bin_infos[mib[2]].nregs, uint32_t) CTL_RO_NL_GEN(arenas_bin_i_slab_size, bin_infos[mib[2]].slab_size, size_t) @@ -3103,9 +3298,8 @@ arenas_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); - arena_config_t config; VERIFY_READ(unsigned); - config = arena_config_default; + arena_config_t config = arena_config_default; WRITE(config.extent_hooks, extent_hooks_t *); if ((arena_ind = ctl_arena_init(tsd, &config)) == UINT_MAX) { ret = EAGAIN; @@ -3150,19 +3344,21 @@ arenas_lookup_ctl(tsd_t *tsd, const size_t *mib, int ret; unsigned arena_ind; void *ptr; - edata_t *edata; + emap_full_alloc_ctx_t alloc_ctx; + bool ptr_not_present; arena_t *arena; ptr = NULL; ret = EINVAL; malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); WRITE(ptr, void *); - edata = emap_edata_lookup(tsd_tsdn(tsd), &arena_emap_global, ptr); - if (edata == NULL) { + ptr_not_present = emap_full_alloc_ctx_try_lookup(tsd_tsdn(tsd), &arena_emap_global, ptr, + &alloc_ctx); + if (ptr_not_present || alloc_ctx.edata == NULL) { goto label_return; } - arena = arena_get_from_edata(edata); + arena = arena_get_from_edata(alloc_ctx.edata); if (arena == NULL) { goto label_return; } @@ -3446,6 +3642,62 @@ experimental_hooks_prof_dump_ctl(tsd_t *tsd, const size_t *mib, return ret; } +static int +experimental_hooks_prof_sample_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + + if (oldp == NULL && newp == NULL) { + ret = EINVAL; + goto label_return; + } + if (oldp != NULL) { + prof_sample_hook_t old_hook = + prof_sample_hook_get(); + READ(old_hook, prof_sample_hook_t); + } + if (newp != NULL) { + if (!opt_prof) { + ret = ENOENT; + goto label_return; + } + prof_sample_hook_t new_hook JEMALLOC_CC_SILENCE_INIT(NULL); + WRITE(new_hook, prof_sample_hook_t); + prof_sample_hook_set(new_hook); + } + ret = 0; +label_return: + return ret; +} + +static int +experimental_hooks_prof_sample_free_ctl(tsd_t *tsd, const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + + if (oldp == NULL && newp == NULL) { + ret = EINVAL; + goto label_return; + } + if (oldp != NULL) { + prof_sample_free_hook_t old_hook = + prof_sample_free_hook_get(); + READ(old_hook, prof_sample_free_hook_t); + } + if (newp != NULL) { + if (!opt_prof) { + ret = ENOENT; + goto label_return; + } + prof_sample_free_hook_t new_hook JEMALLOC_CC_SILENCE_INIT(NULL); + WRITE(new_hook, prof_sample_free_hook_t); + prof_sample_free_hook_set(new_hook); + } + ret = 0; +label_return: + return ret; +} + /* For integration test purpose only. No plan to move out of experimental. */ static int experimental_hooks_safety_check_abort_ctl(tsd_t *tsd, const size_t *mib, @@ -3472,6 +3724,10 @@ experimental_hooks_safety_check_abort_ctl(tsd_t *tsd, const size_t *mib, CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats->allocated, size_t) CTL_RO_CGEN(config_stats, stats_active, ctl_stats->active, size_t) CTL_RO_CGEN(config_stats, stats_metadata, ctl_stats->metadata, size_t) +CTL_RO_CGEN(config_stats, stats_metadata_edata, ctl_stats->metadata_edata, + size_t) +CTL_RO_CGEN(config_stats, stats_metadata_rtree, ctl_stats->metadata_rtree, + size_t) CTL_RO_CGEN(config_stats, stats_metadata_thp, ctl_stats->metadata_thp, size_t) CTL_RO_CGEN(config_stats, stats_resident, ctl_stats->resident, size_t) CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats->mapped, size_t) @@ -3537,6 +3793,10 @@ CTL_RO_CGEN(config_stats, stats_arenas_i_base, CTL_RO_CGEN(config_stats, stats_arenas_i_internal, atomic_load_zu(&arenas_i(mib[2])->astats->astats.internal, ATOMIC_RELAXED), size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_metadata_edata, + arenas_i(mib[2])->astats->astats.metadata_edata, size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_metadata_rtree, + arenas_i(mib[2])->astats->astats.metadata_rtree, size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_metadata_thp, arenas_i(mib[2])->astats->astats.metadata_thp, size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_tcache_bytes, @@ -3868,9 +4128,8 @@ experimental_hooks_install_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, * this API, which can change at a moment's notice. */ hooks_t hooks; - void *handle; WRITE(hooks, hooks_t); - handle = hook_install(tsd_tsdn(tsd), &hooks); + void *handle = hook_install(tsd_tsdn(tsd), &hooks); if (handle == NULL) { ret = EAGAIN; goto label_return; @@ -3886,9 +4145,8 @@ static int experimental_hooks_remove_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; - void *handle; WRITEONLY(); - handle = NULL; + void *handle = NULL; WRITE(handle, void *); if (handle == NULL) { ret = EINVAL; @@ -4001,7 +4259,6 @@ experimental_utilization_query_ctl(tsd_t *tsd, const size_t *mib, assert(sizeof(inspect_extent_util_stats_verbose_t) == sizeof(void *) + sizeof(size_t) * 5); - void *ptr = NULL; if (oldp == NULL || oldlenp == NULL || *oldlenp != sizeof(inspect_extent_util_stats_verbose_t) || newp == NULL) { @@ -4009,9 +4266,9 @@ experimental_utilization_query_ctl(tsd_t *tsd, const size_t *mib, goto label_return; } - inspect_extent_util_stats_verbose_t *util_stats; + void *ptr = NULL; WRITE(ptr, void *); - util_stats + inspect_extent_util_stats_verbose_t *util_stats = (inspect_extent_util_stats_verbose_t *)oldp; inspect_extent_util_stats_verbose_get(tsd_tsdn(tsd), ptr, &util_stats->nfree, &util_stats->nregs, &util_stats->size, @@ -4126,10 +4383,6 @@ experimental_utilization_batch_query_ctl(tsd_t *tsd, const size_t *mib, assert(sizeof(inspect_extent_util_stats_t) == sizeof(size_t) * 3); - - void **ptrs = (void **)newp; - inspect_extent_util_stats_t *util_stats; - const size_t len = newlen / sizeof(const void *); if (oldp == NULL || oldlenp == NULL || newp == NULL || newlen == 0 || newlen != len * sizeof(const void *) @@ -4138,7 +4391,8 @@ experimental_utilization_batch_query_ctl(tsd_t *tsd, const size_t *mib, goto label_return; } - util_stats = + void **ptrs = (void **)newp; + inspect_extent_util_stats_t *util_stats = (inspect_extent_util_stats_t *)oldp; size_t i; for (i = 0; i < len; ++i) { @@ -4282,12 +4536,11 @@ experimental_batch_alloc_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; - size_t filled; VERIFY_READ(size_t); batch_alloc_packet_t batch_alloc_packet; ASSURED_WRITE(batch_alloc_packet, batch_alloc_packet_t); - filled = batch_alloc(batch_alloc_packet.ptrs, + size_t filled = batch_alloc(batch_alloc_packet.ptrs, batch_alloc_packet.num, batch_alloc_packet.size, batch_alloc_packet.flags); READ(filled, size_t); @@ -4425,5 +4678,3 @@ prof_stats_lextents_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, } return super_prof_stats_lextents_i_node; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/decay.cpp b/extension/jemalloc/jemalloc/src/decay.c similarity index 99% rename from extension/jemalloc/jemalloc/src/decay.cpp rename to extension/jemalloc/jemalloc/src/decay.c index b77ef80f101..f75696ddb09 100644 --- a/extension/jemalloc/jemalloc/src/decay.cpp +++ b/extension/jemalloc/jemalloc/src/decay.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/decay.h" -namespace duckdb_jemalloc { - static const uint64_t h_steps[SMOOTHSTEP_NSTEPS] = { #define STEP(step, h, x, y) \ h, @@ -16,7 +14,7 @@ static const uint64_t h_steps[SMOOTHSTEP_NSTEPS] = { * Generate a new deadline that is uniformly random within the next epoch after * the current one. */ -void +static void decay_deadline_init(decay_t *decay) { nstime_copy(&decay->deadline, &decay->epoch); nstime_add(&decay->deadline, &decay->interval); @@ -159,6 +157,7 @@ decay_deadline_reached(const decay_t *decay, const nstime_t *time) { uint64_t decay_npages_purge_in(decay_t *decay, nstime_t *time, size_t npages_new) { uint64_t decay_interval_ns = decay_epoch_duration_ns(decay); + assert(decay_interval_ns != 0); size_t n_epoch = (size_t)(nstime_ns(time) / decay_interval_ns); uint64_t npages_purge; @@ -295,5 +294,3 @@ uint64_t decay_ns_until_purge(decay_t *decay, size_t npages_current, } return decay_interval_ns * (ub + lb) / 2; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/div.cpp b/extension/jemalloc/jemalloc/src/div.c similarity index 92% rename from extension/jemalloc/jemalloc/src/div.cpp rename to extension/jemalloc/jemalloc/src/div.c index 6a96ae1aec6..808892a133f 100644 --- a/extension/jemalloc/jemalloc/src/div.cpp +++ b/extension/jemalloc/jemalloc/src/div.c @@ -1,12 +1,9 @@ #include "jemalloc/internal/jemalloc_preamble.h" -#include "jemalloc/internal/jemalloc_internal_includes.h" #include "jemalloc/internal/div.h" #include "jemalloc/internal/assert.h" -namespace duckdb_jemalloc { - /* * Suppose we have n = q * d, all integers. We know n and d, and want q = n / d. * @@ -56,5 +53,3 @@ div_init(div_info_t *div_info, size_t d) { div_info->d = d; #endif } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/ecache.cpp b/extension/jemalloc/jemalloc/src/ecache.c similarity index 93% rename from extension/jemalloc/jemalloc/src/ecache.cpp rename to extension/jemalloc/jemalloc/src/ecache.c index 58f15802979..a242227d32d 100644 --- a/extension/jemalloc/jemalloc/src/ecache.cpp +++ b/extension/jemalloc/jemalloc/src/ecache.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/san.h" -namespace duckdb_jemalloc { - bool ecache_init(tsdn_t *tsdn, ecache_t *ecache, extent_state_t state, unsigned ind, bool delay_coalesce) { @@ -35,5 +33,3 @@ void ecache_postfork_child(tsdn_t *tsdn, ecache_t *ecache) { malloc_mutex_postfork_child(tsdn, &ecache->mtx); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/edata.cpp b/extension/jemalloc/jemalloc/src/edata.c similarity index 79% rename from extension/jemalloc/jemalloc/src/edata.cpp rename to extension/jemalloc/jemalloc/src/edata.c index fd44e6fc3ec..82b6f5654b5 100644 --- a/extension/jemalloc/jemalloc/src/edata.cpp +++ b/extension/jemalloc/jemalloc/src/edata.c @@ -1,10 +1,6 @@ #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" -namespace duckdb_jemalloc { - ph_gen(, edata_avail, edata_t, avail_link, edata_esnead_comp) ph_gen(, edata_heap, edata_t, heap_link, edata_snad_comp) - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/edata_cache.cpp b/extension/jemalloc/jemalloc/src/edata_cache.c similarity index 98% rename from extension/jemalloc/jemalloc/src/edata_cache.cpp rename to extension/jemalloc/jemalloc/src/edata_cache.c index 7bace89ca05..6bc1848cbcb 100644 --- a/extension/jemalloc/jemalloc/src/edata_cache.cpp +++ b/extension/jemalloc/jemalloc/src/edata_cache.c @@ -1,8 +1,6 @@ #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" -namespace duckdb_jemalloc { - bool edata_cache_init(edata_cache_t *edata_cache, base_t *base) { edata_avail_new(&edata_cache->avail); @@ -154,5 +152,3 @@ edata_cache_fast_disable(tsdn_t *tsdn, edata_cache_fast_t *ecs) { edata_cache_fast_flush_all(tsdn, ecs); ecs->disabled = true; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/ehooks.cpp b/extension/jemalloc/jemalloc/src/ehooks.c similarity index 95% rename from extension/jemalloc/jemalloc/src/ehooks.cpp rename to extension/jemalloc/jemalloc/src/ehooks.c index 1606d3043bb..fc2355e608e 100644 --- a/extension/jemalloc/jemalloc/src/ehooks.cpp +++ b/extension/jemalloc/jemalloc/src/ehooks.c @@ -4,8 +4,6 @@ #include "jemalloc/internal/ehooks.h" #include "jemalloc/internal/extent_mmap.h" -namespace duckdb_jemalloc { - void ehooks_init(ehooks_t *ehooks, extent_hooks_t *extent_hooks, unsigned ind) { /* All other hooks are optional; this one is not. */ @@ -102,7 +100,7 @@ ehooks_default_destroy(extent_hooks_t *extent_hooks, void *addr, size_t size, bool ehooks_default_commit_impl(void *addr, size_t offset, size_t length) { - return pages_commit((void *)((uintptr_t)addr + (uintptr_t)offset), + return pages_commit((void *)((byte_t *)addr + (uintptr_t)offset), length); } @@ -114,7 +112,7 @@ ehooks_default_commit(extent_hooks_t *extent_hooks, void *addr, size_t size, bool ehooks_default_decommit_impl(void *addr, size_t offset, size_t length) { - return pages_decommit((void *)((uintptr_t)addr + (uintptr_t)offset), + return pages_decommit((void *)((byte_t *)addr + (uintptr_t)offset), length); } @@ -127,7 +125,7 @@ ehooks_default_decommit(extent_hooks_t *extent_hooks, void *addr, size_t size, #ifdef PAGES_CAN_PURGE_LAZY bool ehooks_default_purge_lazy_impl(void *addr, size_t offset, size_t length) { - return pages_purge_lazy((void *)((uintptr_t)addr + (uintptr_t)offset), + return pages_purge_lazy((void *)((byte_t *)addr + (uintptr_t)offset), length); } @@ -145,7 +143,7 @@ ehooks_default_purge_lazy(extent_hooks_t *extent_hooks, void *addr, size_t size, #ifdef PAGES_CAN_PURGE_FORCED bool ehooks_default_purge_forced_impl(void *addr, size_t offset, size_t length) { - return pages_purge_forced((void *)((uintptr_t)addr + + return pages_purge_forced((void *)((byte_t *)addr + (uintptr_t)offset), length); } @@ -161,7 +159,7 @@ ehooks_default_purge_forced(extent_hooks_t *extent_hooks, void *addr, #endif bool -ehooks_default_split_impl() { +ehooks_default_split_impl(void) { if (!maps_coalesce) { /* * Without retain, only whole regions can be purged (required by @@ -275,5 +273,3 @@ const extent_hooks_t ehooks_default_extent_hooks = { ehooks_default_split, ehooks_default_merge }; - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/emap.cpp b/extension/jemalloc/jemalloc/src/emap.c similarity index 98% rename from extension/jemalloc/jemalloc/src/emap.cpp rename to extension/jemalloc/jemalloc/src/emap.c index bd045057933..9cc95a724a9 100644 --- a/extension/jemalloc/jemalloc/src/emap.cpp +++ b/extension/jemalloc/jemalloc/src/emap.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/emap.h" -namespace duckdb_jemalloc { - enum emap_lock_result_e { emap_lock_result_success, emap_lock_result_failure, @@ -149,7 +147,7 @@ emap_rtree_write_acquired(tsdn_t *tsdn, emap_t *emap, rtree_leaf_elm_t *elm_a, contents.metadata.slab = slab; contents.metadata.is_head = (edata == NULL) ? false : edata_is_head_get(edata); - contents.metadata.state = (extent_state_t)((edata == NULL) ? 0 : edata_state_get(edata)); + contents.metadata.state = (edata == NULL) ? 0 : edata_state_get(edata); rtree_leaf_elm_write(tsdn, &emap->rtree, elm_a, contents); if (elm_b != NULL) { rtree_leaf_elm_write(tsdn, &emap->rtree, elm_b, contents); @@ -386,5 +384,3 @@ emap_do_assert_not_mapped(tsdn_t *tsdn, emap_t *emap, edata_t *edata) { &context2); assert(context2.edata == NULL); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/eset.cpp b/extension/jemalloc/jemalloc/src/eset.c similarity index 99% rename from extension/jemalloc/jemalloc/src/eset.cpp rename to extension/jemalloc/jemalloc/src/eset.c index 68f17772645..6f8f335e198 100644 --- a/extension/jemalloc/jemalloc/src/eset.cpp +++ b/extension/jemalloc/jemalloc/src/eset.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/eset.h" -namespace duckdb_jemalloc { - #define ESET_NPSIZES (SC_NPSIZES + 1) static void @@ -282,5 +280,3 @@ eset_fit(eset_t *eset, size_t esize, size_t alignment, bool exact_only, return edata; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/exp_grow.cpp b/extension/jemalloc/jemalloc/src/exp_grow.c similarity index 79% rename from extension/jemalloc/jemalloc/src/exp_grow.cpp rename to extension/jemalloc/jemalloc/src/exp_grow.c index 74a2666b495..386471f49fd 100644 --- a/extension/jemalloc/jemalloc/src/exp_grow.cpp +++ b/extension/jemalloc/jemalloc/src/exp_grow.c @@ -1,12 +1,8 @@ #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" -namespace duckdb_jemalloc { - void exp_grow_init(exp_grow_t *exp_grow) { exp_grow->next = sz_psz2ind(HUGEPAGE); exp_grow->limit = sz_psz2ind(SC_LARGE_MAXCLASS); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/extent.cpp b/extension/jemalloc/jemalloc/src/extent.c similarity index 97% rename from extension/jemalloc/jemalloc/src/extent.cpp rename to extension/jemalloc/jemalloc/src/extent.c index af2bf108bd3..2efc7938bab 100644 --- a/extension/jemalloc/jemalloc/src/extent.cpp +++ b/extension/jemalloc/jemalloc/src/extent.c @@ -8,8 +8,6 @@ #include "jemalloc/internal/ph.h" #include "jemalloc/internal/mutex.h" -namespace duckdb_jemalloc { - /******************************************************************************/ /* Data. */ @@ -45,6 +43,8 @@ static edata_t *extent_try_coalesce(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, static edata_t *extent_alloc_retained(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, edata_t *expand_edata, size_t size, size_t alignment, bool zero, bool *commit, bool guarded); +static bool extent_decommit_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, + edata_t *edata, size_t offset, size_t length); /******************************************************************************/ @@ -201,8 +201,6 @@ ecache_evict(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, * concurrent operations. */ switch (ecache->state) { - case extent_state_active: - not_reached(); case extent_state_dirty: case extent_state_muzzy: emap_update_edata_state(tsdn, pac->emap, edata, @@ -211,6 +209,9 @@ ecache_evict(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, case extent_state_retained: extent_deregister(tsdn, pac, edata); break; + case extent_state_active: + case extent_state_transition: + case extent_state_merging: default: not_reached(); } @@ -407,6 +408,7 @@ extent_recycle_extract(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, edata = emap_try_acquire_edata_neighbor_expand(tsdn, pac->emap, expand_edata, EXTENT_PAI_PAC, ecache->state); if (edata != NULL) { + /* NOLINTNEXTLINE(readability-suspicious-call-argument) */ extent_assert_can_expand(expand_edata, edata); if (edata_size_get(edata) < size) { emap_release_edata(tsdn, pac->emap, edata, @@ -647,15 +649,6 @@ extent_grow_retained(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, size_t size, size_t alignment, bool zero, bool *commit) { malloc_mutex_assert_owner(tsdn, &pac->grow_mtx); - extent_split_interior_result_t result; - edata_t *edata; - bool err; - bool zeroed; - bool committed; - void *ptr; - edata_t *to_leak; - edata_t *to_salvage; - size_t alloc_size_min = size + PAGE_CEILING(alignment) - PAGE; /* Beware size_t wrap-around. */ if (alloc_size_min < size) { @@ -667,20 +660,20 @@ extent_grow_retained(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, */ size_t alloc_size; pszind_t exp_grow_skip; - err = exp_grow_size_prepare(&pac->exp_grow, alloc_size_min, + bool err = exp_grow_size_prepare(&pac->exp_grow, alloc_size_min, &alloc_size, &exp_grow_skip); if (err) { goto label_err; } - edata = edata_cache_get(tsdn, pac->edata_cache); + edata_t *edata = edata_cache_get(tsdn, pac->edata_cache); if (edata == NULL) { goto label_err; } - zeroed = false; - committed = false; + bool zeroed = false; + bool committed = false; - ptr = ehooks_alloc(tsdn, ehooks, NULL, alloc_size, PAGE, &zeroed, + void *ptr = ehooks_alloc(tsdn, ehooks, NULL, alloc_size, PAGE, &zeroed, &committed); if (ptr == NULL) { @@ -704,10 +697,10 @@ extent_grow_retained(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, edata_t *lead; edata_t *trail; - to_leak JEMALLOC_CC_SILENCE_INIT(NULL); - to_salvage JEMALLOC_CC_SILENCE_INIT(NULL); + edata_t *to_leak JEMALLOC_CC_SILENCE_INIT(NULL); + edata_t *to_salvage JEMALLOC_CC_SILENCE_INIT(NULL); - result = extent_split_interior(tsdn, + extent_split_interior_result_t result = extent_split_interior(tsdn, pac, ehooks, &edata, &lead, &trail, &to_leak, &to_salvage, NULL, size, alignment); @@ -751,7 +744,7 @@ extent_grow_retained(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, /* A successful commit should return zeroed memory. */ if (config_debug) { void *addr = edata_addr_get(edata); - size_t *p = (size_t *)(uintptr_t)addr; + size_t *p = (size_t *)addr; /* Check the first page only. */ for (size_t i = 0; i < PAGE / sizeof(size_t); i++) { assert(p[i] == 0); @@ -831,6 +824,7 @@ static edata_t * extent_try_coalesce_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, ecache_t *ecache, edata_t *edata, bool *coalesced) { assert(!edata_guarded_get(edata)); + assert(coalesced != NULL); /* * We avoid checking / locking inactive neighbors for large size * classes, since they are eagerly coalesced on deallocation which can @@ -937,8 +931,9 @@ extent_record(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, ecache_t *ecache, goto label_skip_coalesce; } if (!ecache->delay_coalesce) { + bool coalesced_unused; edata = extent_try_coalesce(tsdn, pac, ehooks, ecache, edata, - NULL); + &coalesced_unused); } else if (edata_size_get(edata) >= SC_LARGE_MINCLASS) { assert(ecache == &pac->ecache_dirty); /* Always coalesce large extents eagerly. */ @@ -950,6 +945,7 @@ extent_record(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, ecache_t *ecache, } while (coalesced); if (edata_size_get(edata) >= atomic_load_zu(&pac->oversize_threshold, ATOMIC_RELAXED) + && !background_thread_enabled() && extent_may_force_decay(pac)) { /* Shortcut to purge the oversize extent eagerly. */ malloc_mutex_unlock(tsdn, &ecache->mtx); @@ -1129,7 +1125,7 @@ extent_commit_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, /* growing_retained */ false); } -bool +static bool extent_decommit_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, size_t offset, size_t length) { witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), @@ -1198,20 +1194,18 @@ extent_split_impl(tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, return NULL; } - bool err; - edata_t *trail = edata_cache_get(tsdn, pac->edata_cache); if (trail == NULL) { goto label_error_a; } edata_init(trail, edata_arena_ind_get(edata), - (void *)((uintptr_t)edata_base_get(edata) + size_a), size_b, + (void *)((byte_t *)edata_base_get(edata) + size_a), size_b, /* slab */ false, SC_NSIZES, edata_sn_get(edata), edata_state_get(edata), edata_zeroed_get(edata), edata_committed_get(edata), EXTENT_PAI_PAC, EXTENT_NOT_HEAD); emap_prepare_t prepare; - err = emap_split_prepare(tsdn, pac->emap, &prepare, edata, + bool err = emap_split_prepare(tsdn, pac->emap, &prepare, edata, size_a, trail, size_b); if (err) { goto label_error_b; @@ -1337,5 +1331,3 @@ extent_boot(void) { return false; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/extent_dss.cpp b/extension/jemalloc/jemalloc/src/extent_dss.c similarity index 92% rename from extension/jemalloc/jemalloc/src/extent_dss.cpp rename to extension/jemalloc/jemalloc/src/extent_dss.c index ac8bb256289..32fb4112245 100644 --- a/extension/jemalloc/jemalloc/src/extent_dss.cpp +++ b/extension/jemalloc/jemalloc/src/extent_dss.c @@ -5,14 +5,15 @@ #include "jemalloc/internal/extent_dss.h" #include "jemalloc/internal/spin.h" -namespace duckdb_jemalloc { - /******************************************************************************/ /* Data. */ +/* NOLINTNEXTLINE(performance-no-int-to-ptr) */ +#define SBRK_INVALID ((void *)-1) + const char *opt_dss = DSS_DEFAULT; -const char *dss_prec_names[] = { +const char *const dss_prec_names[] = { "disabled", "primary", "secondary", @@ -96,7 +97,7 @@ extent_dss_max_update(void *new_addr) { * up to date. */ void *max_cur = extent_dss_sbrk(0); - if (max_cur == (void *)-1) { + if (max_cur == SBRK_INVALID) { return NULL; } atomic_store_p(&dss_max, max_cur, ATOMIC_RELEASE); @@ -142,17 +143,17 @@ extent_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size, goto label_oom; } - auto head_state = opt_retain ? EXTENT_IS_HEAD : + bool head_state = opt_retain ? EXTENT_IS_HEAD : EXTENT_NOT_HEAD; /* * Compute how much page-aligned gap space (if any) is * necessary to satisfy alignment. This space can be * recycled for later use. */ - void *gap_addr_page = (void *)(PAGE_CEILING( - (uintptr_t)max_cur)); - void *ret = (void *)ALIGNMENT_CEILING( - (uintptr_t)gap_addr_page, alignment); + void *gap_addr_page = ALIGNMENT_ADDR2CEILING(max_cur, + PAGE); + void *ret = ALIGNMENT_ADDR2CEILING( + gap_addr_page, alignment); size_t gap_size_page = (uintptr_t)ret - (uintptr_t)gap_addr_page; if (gap_size_page != 0) { @@ -167,7 +168,7 @@ extent_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size, * Compute the address just past the end of the desired * allocation space. */ - void *dss_next = (void *)((uintptr_t)ret + size); + void *dss_next = (void *)((byte_t *)ret + size); if ((uintptr_t)ret < (uintptr_t)max_cur || (uintptr_t)dss_next < (uintptr_t)max_cur) { goto label_oom; /* Wrap-around. */ @@ -222,7 +223,7 @@ extent_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size, * Failure, whether due to OOM or a race with a raw * sbrk() call from outside the allocator. */ - if (dss_prev == (void *)-1) { + if (dss_prev == SBRK_INVALID) { /* OOM. */ atomic_store_b(&dss_exhausted, true, ATOMIC_RELEASE); @@ -272,10 +273,8 @@ extent_dss_boot(void) { dss_base = extent_dss_sbrk(0); atomic_store_b(&dss_extending, false, ATOMIC_RELAXED); - atomic_store_b(&dss_exhausted, dss_base == (void *)-1, ATOMIC_RELAXED); + atomic_store_b(&dss_exhausted, dss_base == SBRK_INVALID, ATOMIC_RELAXED); atomic_store_p(&dss_max, dss_base, ATOMIC_RELAXED); } /******************************************************************************/ - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/extent_mmap.cpp b/extension/jemalloc/jemalloc/src/extent_mmap.c similarity index 93% rename from extension/jemalloc/jemalloc/src/extent_mmap.cpp rename to extension/jemalloc/jemalloc/src/extent_mmap.c index 75b1ab2bc8e..5f0ee2d24b1 100644 --- a/extension/jemalloc/jemalloc/src/extent_mmap.cpp +++ b/extension/jemalloc/jemalloc/src/extent_mmap.c @@ -4,8 +4,6 @@ #include "jemalloc/internal/assert.h" #include "jemalloc/internal/extent_mmap.h" -namespace duckdb_jemalloc { - /******************************************************************************/ /* Data. */ @@ -41,5 +39,3 @@ extent_dalloc_mmap(void *addr, size_t size) { } return opt_retain; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/fxp.cpp b/extension/jemalloc/jemalloc/src/fxp.c similarity index 94% rename from extension/jemalloc/jemalloc/src/fxp.cpp rename to extension/jemalloc/jemalloc/src/fxp.c index 5dc233943d4..96585f0a65a 100644 --- a/extension/jemalloc/jemalloc/src/fxp.cpp +++ b/extension/jemalloc/jemalloc/src/fxp.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/fxp.h" -namespace duckdb_jemalloc { - static bool fxp_isdigit(char c) { return '0' <= c && c <= '9'; @@ -115,14 +113,12 @@ fxp_print(fxp_t a, char buf[FXP_BUF_SIZE]) { fraction_digits /= 10; } - size_t printed = malloc_snprintf(buf, FXP_BUF_SIZE, "%" FMTu32".", + size_t printed = malloc_snprintf(buf, FXP_BUF_SIZE, "%"FMTu32".", integer_part); for (int i = 0; i < leading_fraction_zeros; i++) { buf[printed] = '0'; printed++; } - malloc_snprintf(&buf[printed], FXP_BUF_SIZE - printed, "%" FMTu64, + malloc_snprintf(&buf[printed], FXP_BUF_SIZE - printed, "%"FMTu64, fraction_digits); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/hook.cpp b/extension/jemalloc/jemalloc/src/hook.c similarity index 97% rename from extension/jemalloc/jemalloc/src/hook.cpp rename to extension/jemalloc/jemalloc/src/hook.c index e6c57747e5a..77a988d722c 100644 --- a/extension/jemalloc/jemalloc/src/hook.cpp +++ b/extension/jemalloc/jemalloc/src/hook.c @@ -1,5 +1,4 @@ #include "jemalloc/internal/jemalloc_preamble.h" -#include "jemalloc/internal/jemalloc_internal_includes.h" #include "jemalloc/internal/hook.h" @@ -7,8 +6,6 @@ #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/seq.h" -namespace duckdb_jemalloc { - typedef struct hooks_internal_s hooks_internal_t; struct hooks_internal_s { hooks_t hooks; @@ -22,7 +19,7 @@ static seq_hooks_t hooks[HOOK_MAX]; static malloc_mutex_t hooks_mu; bool -hook_boot() { +hook_boot(void) { return malloc_mutex_init(&hooks_mu, "hooks", WITNESS_RANK_HOOK, malloc_mutex_rank_exclusive); } @@ -103,7 +100,7 @@ for (int for_each_hook_counter = 0; \ } static bool * -hook_reentrantp() { +hook_reentrantp(void) { /* * We prevent user reentrancy within hooks. This is basically just a * thread-local bool that triggers an early-exit. @@ -196,5 +193,3 @@ hook_invoke_expand(hook_expand_t type, void *address, size_t old_usize, FOR_EACH_HOOK_END HOOK_EPILOGUE } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/hpa.cpp b/extension/jemalloc/jemalloc/src/hpa.c similarity index 96% rename from extension/jemalloc/jemalloc/src/hpa.cpp rename to extension/jemalloc/jemalloc/src/hpa.c index 8f8e2431c69..99d1f03341b 100644 --- a/extension/jemalloc/jemalloc/src/hpa.cpp +++ b/extension/jemalloc/jemalloc/src/hpa.c @@ -6,15 +6,14 @@ #include "jemalloc/internal/fb.h" #include "jemalloc/internal/witness.h" -namespace duckdb_jemalloc { - #define HPA_EDEN_SIZE (128 * HUGEPAGE) static edata_t *hpa_alloc(tsdn_t *tsdn, pai_t *self, size_t size, size_t alignment, bool zero, bool guarded, bool frequent_reuse, bool *deferred_work_generated); static size_t hpa_alloc_batch(tsdn_t *tsdn, pai_t *self, size_t size, - size_t nallocs, edata_list_active_t *results, bool *deferred_work_generated); + size_t nallocs, edata_list_active_t *results, bool frequent_reuse, + bool *deferred_work_generated); static bool hpa_expand(tsdn_t *tsdn, pai_t *self, edata_t *edata, size_t old_size, size_t new_size, bool zero, bool *deferred_work_generated); static bool hpa_shrink(tsdn_t *tsdn, pai_t *self, edata_t *edata, @@ -26,7 +25,7 @@ static void hpa_dalloc_batch(tsdn_t *tsdn, pai_t *self, static uint64_t hpa_time_until_deferred_work(tsdn_t *tsdn, pai_t *self); bool -hpa_supported() { +hpa_supported(void) { #ifdef _WIN32 /* * At least until the API and implementation is somewhat settled, we @@ -70,11 +69,7 @@ hpa_central_init(hpa_central_t *central, base_t *base, const hpa_hooks_t *hooks) if (err) { return true; } - err = malloc_mutex_init(¢ral->mtx, "hpa_central", - WITNESS_RANK_HPA_CENTRAL, malloc_mutex_rank_exclusive); - if (err) { - return true; - } + central->base = base; central->eden = NULL; central->eden_len = 0; @@ -89,7 +84,7 @@ hpa_alloc_ps(tsdn_t *tsdn, hpa_central_t *central) { CACHELINE); } -hpdata_t * +static hpdata_t * hpa_central_extract(tsdn_t *tsdn, hpa_central_t *central, size_t size, bool *oom) { /* Don't yet support big allocations; these should get filtered out. */ @@ -649,7 +644,9 @@ static size_t hpa_alloc_batch_psset(tsdn_t *tsdn, hpa_shard_t *shard, size_t size, size_t nallocs, edata_list_active_t *results, bool *deferred_work_generated) { - assert(size <= shard->opts.slab_max_alloc); + assert(size <= HUGEPAGE); + assert(size <= shard->opts.slab_max_alloc || + size == sz_index2size(sz_size2index(size))); bool oom = false; size_t nsuccess = hpa_try_alloc_batch_no_grow(tsdn, shard, size, &oom, @@ -709,23 +706,35 @@ hpa_alloc_batch_psset(tsdn_t *tsdn, hpa_shard_t *shard, size_t size, static hpa_shard_t * hpa_from_pai(pai_t *self) { - assert(self->alloc = &hpa_alloc); - assert(self->expand = &hpa_expand); - assert(self->shrink = &hpa_shrink); - assert(self->dalloc = &hpa_dalloc); + assert(self->alloc == &hpa_alloc); + assert(self->expand == &hpa_expand); + assert(self->shrink == &hpa_shrink); + assert(self->dalloc == &hpa_dalloc); return (hpa_shard_t *)self; } static size_t hpa_alloc_batch(tsdn_t *tsdn, pai_t *self, size_t size, size_t nallocs, - edata_list_active_t *results, bool *deferred_work_generated) { + edata_list_active_t *results, bool frequent_reuse, + bool *deferred_work_generated) { assert(nallocs > 0); assert((size & PAGE_MASK) == 0); witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), WITNESS_RANK_CORE, 0); hpa_shard_t *shard = hpa_from_pai(self); - if (size > shard->opts.slab_max_alloc) { + /* + * frequent_use here indicates this request comes from the arena bins, + * in which case it will be split into slabs, and therefore there is no + * intrinsic slack in the allocation (the entire range of allocated size + * will be accessed). + * + * In this case bypass the slab_max_alloc limit (if still within the + * huge page size). These requests do not concern internal + * fragmentation with huge pages (again, the full size will be used). + */ + if (!(frequent_reuse && size <= HUGEPAGE) && + (size > shard->opts.slab_max_alloc)) { return 0; } @@ -777,7 +786,7 @@ hpa_alloc(tsdn_t *tsdn, pai_t *self, size_t size, size_t alignment, bool zero, edata_list_active_t results; edata_list_active_init(&results); size_t nallocs = hpa_alloc_batch(tsdn, self, size, /* nallocs */ 1, - &results, deferred_work_generated); + &results, frequent_reuse, deferred_work_generated); assert(nallocs == 0 || nallocs == 1); edata_t *edata = edata_list_active_first(&results); return edata; @@ -1044,5 +1053,3 @@ hpa_shard_postfork_child(tsdn_t *tsdn, hpa_shard_t *shard) { malloc_mutex_postfork_child(tsdn, &shard->grow_mtx); malloc_mutex_postfork_child(tsdn, &shard->mtx); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/hpa_hooks.cpp b/extension/jemalloc/jemalloc/src/hpa_hooks.c similarity index 93% rename from extension/jemalloc/jemalloc/src/hpa_hooks.cpp rename to extension/jemalloc/jemalloc/src/hpa_hooks.c index 9ac6cb24978..6048f3821ba 100644 --- a/extension/jemalloc/jemalloc/src/hpa_hooks.cpp +++ b/extension/jemalloc/jemalloc/src/hpa_hooks.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/hpa_hooks.h" -namespace duckdb_jemalloc { - static void *hpa_hooks_map(size_t size); static void hpa_hooks_unmap(void *ptr, size_t size); static void hpa_hooks_purge(void *ptr, size_t size); @@ -13,7 +11,7 @@ static void hpa_hooks_dehugify(void *ptr, size_t size); static void hpa_hooks_curtime(nstime_t *r_nstime, bool first_reading); static uint64_t hpa_hooks_ms_since(nstime_t *past_nstime); -hpa_hooks_t hpa_hooks_default = { +const hpa_hooks_t hpa_hooks_default = { &hpa_hooks_map, &hpa_hooks_unmap, &hpa_hooks_purge, @@ -63,5 +61,3 @@ static uint64_t hpa_hooks_ms_since(nstime_t *past_nstime) { return nstime_ns_since(past_nstime) / 1000 / 1000; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/hpdata.cpp b/extension/jemalloc/jemalloc/src/hpdata.c similarity index 98% rename from extension/jemalloc/jemalloc/src/hpdata.cpp rename to extension/jemalloc/jemalloc/src/hpdata.c index cfe8755f9db..3058eafe85b 100644 --- a/extension/jemalloc/jemalloc/src/hpdata.cpp +++ b/extension/jemalloc/jemalloc/src/hpdata.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/hpdata.h" -namespace duckdb_jemalloc { - static int hpdata_age_comp(const hpdata_t *a, const hpdata_t *b) { uint64_t a_age = hpdata_age_get(a); @@ -132,7 +130,7 @@ hpdata_reserve_alloc(hpdata_t *hpdata, size_t sz) { hpdata_assert_consistent(hpdata); return (void *)( - (uintptr_t)hpdata_addr_get(hpdata) + (result << LG_PAGE)); + (byte_t *)hpdata_addr_get(hpdata) + (result << LG_PAGE)); } void @@ -279,7 +277,7 @@ hpdata_purge_next(hpdata_t *hpdata, hpdata_purge_state_t *purge_state, } *r_purge_addr = (void *)( - (uintptr_t)hpdata_addr_get(hpdata) + purge_begin * PAGE); + (byte_t *)hpdata_addr_get(hpdata) + purge_begin * PAGE); *r_purge_size = purge_len * PAGE; purge_state->next_purge_search_begin = purge_begin + purge_len; @@ -325,5 +323,3 @@ hpdata_dehugify(hpdata_t *hpdata) { hpdata->h_huge = false; hpdata_assert_consistent(hpdata); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/inspect.cpp b/extension/jemalloc/jemalloc/src/inspect.c similarity index 97% rename from extension/jemalloc/jemalloc/src/inspect.cpp rename to extension/jemalloc/jemalloc/src/inspect.c index ce546961882..2575b5c1f13 100644 --- a/extension/jemalloc/jemalloc/src/inspect.cpp +++ b/extension/jemalloc/jemalloc/src/inspect.c @@ -1,7 +1,6 @@ #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" - -namespace duckdb_jemalloc { +#include "jemalloc/internal/inspect.h" void inspect_extent_util_stats_get(tsdn_t *tsdn, const void *ptr, size_t *nfree, @@ -77,5 +76,3 @@ inspect_extent_util_stats_verbose_get(tsdn_t *tsdn, const void *ptr, *slabcur_addr = slab != NULL ? edata_addr_get(slab) : NULL; malloc_mutex_unlock(tsdn, &bin->lock); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/jemalloc.cpp b/extension/jemalloc/jemalloc/src/jemalloc.c similarity index 88% rename from extension/jemalloc/jemalloc/src/jemalloc.cpp rename to extension/jemalloc/jemalloc/src/jemalloc.c index ae74794952d..5f2e5b35b74 100644 --- a/extension/jemalloc/jemalloc/src/jemalloc.cpp +++ b/extension/jemalloc/jemalloc/src/jemalloc.c @@ -1,4 +1,3 @@ -#define JEMALLOC_C_ #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" @@ -26,14 +25,13 @@ #include "jemalloc/internal/thread_event.h" #include "jemalloc/internal/util.h" -#include "duckdb/common/string_util.hpp" - -namespace duckdb_jemalloc { - /******************************************************************************/ /* Data. */ /* Runtime configuration options. */ +#define JE_MALLOC_CONF_BUFFER_SIZE 200 +char JE_MALLOC_CONF_BUFFER[JE_MALLOC_CONF_BUFFER_SIZE]; + const char *je_malloc_conf #ifndef _WIN32 JEMALLOC_ATTR(weak) @@ -62,6 +60,9 @@ const char *je_malloc_conf_2_conf_harder #endif ; +const char *opt_malloc_conf_symlink = NULL; +const char *opt_malloc_conf_env_var = NULL; + bool opt_abort = #ifdef JEMALLOC_DEBUG true @@ -125,7 +126,7 @@ zero_realloc_action_t opt_zero_realloc_action = atomic_zu_t zero_realloc_count = ATOMIC_INIT(0); -const char *zero_realloc_mode_names[] = { +const char *const zero_realloc_mode_names[] = { "alloc", "free", "abort", @@ -146,20 +147,26 @@ static void default_junk_free(void *ptr, size_t usize) { memset(ptr, junk_free_byte, usize); } -void (*junk_alloc_callback)(void *ptr, size_t size) = &default_junk_alloc; -void (*junk_free_callback)(void *ptr, size_t size) = &default_junk_free; +void (*JET_MUTABLE junk_alloc_callback)(void *ptr, size_t size) = &default_junk_alloc; +void (*JET_MUTABLE junk_free_callback)(void *ptr, size_t size) = &default_junk_free; +void (*JET_MUTABLE invalid_conf_abort)(void) = &abort; bool opt_utrace = false; bool opt_xmalloc = false; bool opt_experimental_infallible_new = false; bool opt_zero = false; unsigned opt_narenas = 0; -fxp_t opt_narenas_ratio = FXP_INIT_INT(4); +static fxp_t opt_narenas_ratio = FXP_INIT_INT(4); unsigned ncpus; +unsigned opt_debug_double_free_max_scan = + SAFETY_CHECK_DOUBLE_FREE_MAX_SCAN_DEFAULT; + +size_t opt_calloc_madvise_threshold = 0; + /* Protects arenas initialization. */ -malloc_mutex_t arenas_lock; +static malloc_mutex_t arenas_lock; /* The global hpa, and whether it's on. */ bool opt_hpa = false; @@ -434,7 +441,7 @@ arena_new_create_background_thread(tsdn_t *tsdn, unsigned ind) { if (background_thread_create(tsdn_tsd(tsdn), ind)) { malloc_printf(": error in background thread " "creation for arena %u. Abort.\n", ind); - jemalloc_abort(); + abort(); } } } @@ -461,8 +468,12 @@ arena_bind(tsd_t *tsd, unsigned ind, bool internal) { tsd_iarena_set(tsd, arena); } else { tsd_arena_set(tsd, arena); - unsigned shard = atomic_fetch_add_u(&arena->binshard_next, 1, - ATOMIC_RELAXED); + /* + * While shard acts as a random seed, the cast below should + * not make much difference. + */ + uint8_t shard = (uint8_t)atomic_fetch_add_u( + &arena->binshard_next, 1, ATOMIC_RELAXED); tsd_binshards_t *bins = tsd_binshardsp_get(tsd); for (unsigned i = 0; i < SC_NBINS; i++) { assert(bin_infos[i].n_shards > 0 && @@ -704,16 +715,20 @@ check_entry_exit_locking(tsdn_t *tsdn) { */ static char * -jemalloc_secure_getenv(const char *name) { -#ifdef JEMALLOC_HAVE_SECURE_GETENV - return secure_getenv(name); +jemalloc_getenv(const char *name) { +#ifdef JEMALLOC_FORCE_GETENV + return getenv(name); #else -# ifdef JEMALLOC_HAVE_ISSETUGID +# ifdef JEMALLOC_HAVE_SECURE_GETENV + return secure_getenv(name); +# else +# ifdef JEMALLOC_HAVE_ISSETUGID if (issetugid() != 0) { return NULL; } -# endif +# endif return getenv(name); +# endif #endif } @@ -763,7 +778,7 @@ malloc_ncpus(void) { * Since otherwise tricky things is possible with percpu arenas in use. */ static bool -malloc_cpu_count_is_deterministic() +malloc_cpu_count_is_deterministic(void) { #ifdef _WIN32 return true; @@ -818,48 +833,12 @@ init_opt_stats_opts(const char *v, size_t vlen, char *dest) { assert(opts_len == strlen(dest)); } -/* Reads the next size pair in a multi-sized option. */ -static bool -malloc_conf_multi_sizes_next(const char **slab_size_segment_cur, - size_t *vlen_left, size_t *slab_start, size_t *slab_end, size_t *new_size) { - const char *cur = *slab_size_segment_cur; - char *end; - uintmax_t um; - - set_errno(0); - - /* First number, then '-' */ - um = malloc_strtoumax(cur, &end, 0); - if (get_errno() != 0 || *end != '-') { - return true; - } - *slab_start = (size_t)um; - cur = end + 1; - - /* Second number, then ':' */ - um = malloc_strtoumax(cur, &end, 0); - if (get_errno() != 0 || *end != ':') { - return true; - } - *slab_end = (size_t)um; - cur = end + 1; - - /* Last number */ - um = malloc_strtoumax(cur, &end, 0); - if (get_errno() != 0) { - return true; - } - *new_size = (size_t)um; - - /* Consume the separator if there is one. */ - if (*end == '|') { - end++; - } - - *vlen_left -= end - *slab_size_segment_cur; - *slab_size_segment_cur = end; +static void +malloc_conf_format_error(const char *msg, const char *begin, const char *end) { + size_t len = end - begin + 1; + len = len > BUFERROR_BUF ? BUFERROR_BUF : len; - return false; + malloc_printf(": %s -- %.*s\n", msg, (int)len, begin); } static bool @@ -895,13 +874,15 @@ malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p, break; case '\0': if (opts != *opts_p) { - malloc_write(": Conf string ends " - "with key\n"); + malloc_conf_format_error( + "Conf string ends with key", + *opts_p, opts - 1); had_conf_error = true; } return true; default: - malloc_write(": Malformed conf string\n"); + malloc_conf_format_error( + "Malformed conf string", *opts_p, opts); had_conf_error = true; return true; } @@ -919,8 +900,9 @@ malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p, * comma if one exists. */ if (*opts == '\0') { - malloc_write(": Conf string ends " - "with comma\n"); + malloc_conf_format_error( + "Conf string ends with comma", + *opts_p, opts - 1); had_conf_error = true; } *vlen_p = (uintptr_t)opts - 1 - (uintptr_t)*v_p; @@ -945,7 +927,7 @@ malloc_abort_invalid_conf(void) { assert(opt_abort_conf); malloc_printf(": Abort (abort_conf:true) on invalid conf " "value (see above).\n"); - jemalloc_abort(); + invalid_conf_abort(); } static void @@ -981,14 +963,15 @@ malloc_slow_flag_init(void) { #define MALLOC_CONF_NSOURCES 5 static const char * -obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) { +obtain_malloc_conf(unsigned which_source, char readlink_buf[PATH_MAX + 1]) { if (config_debug) { static unsigned read_source = 0; /* * Each source should only be read once, to minimize # of * syscalls on init. */ - assert(read_source++ == which_source); + assert(read_source == which_source); + read_source++; } assert(which_source < MALLOC_CONF_NSOURCES); @@ -1023,9 +1006,9 @@ obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) { * link's name. */ #ifndef JEMALLOC_READLINKAT - linklen = readlink(linkname, buf, PATH_MAX); + linklen = readlink(linkname, readlink_buf, PATH_MAX); #else - linklen = readlinkat(AT_FDCWD, linkname, buf, PATH_MAX); + linklen = readlinkat(AT_FDCWD, linkname, readlink_buf, PATH_MAX); #endif if (linklen == -1) { /* No configuration specified. */ @@ -1034,8 +1017,8 @@ obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) { set_errno(saved_errno); } #endif - buf[linklen] = '\0'; - ret = buf; + readlink_buf[linklen] = '\0'; + ret = readlink_buf; break; } case 3: { const char *envname = @@ -1046,11 +1029,8 @@ obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) { #endif ; - if ((ret = jemalloc_secure_getenv(envname)) != NULL) { - /* - * Do nothing; opts is already initialized to the value - * of the MALLOC_CONF environment variable. - */ + if ((ret = jemalloc_getenv(envname)) != NULL) { + opt_malloc_conf_env_var = ret; } else { /* No configuration specified. */ ret = NULL; @@ -1066,10 +1046,50 @@ obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) { return ret; } +static void +validate_hpa_settings(void) { + if (!hpa_supported() || !opt_hpa || opt_hpa_opts.dirty_mult == (fxp_t)-1) { + return; + } + size_t hpa_threshold = fxp_mul_frac(HUGEPAGE, opt_hpa_opts.dirty_mult) + + opt_hpa_opts.hugification_threshold; + if (hpa_threshold > HUGEPAGE) { + return; + } + + had_conf_error = true; + char hpa_dirty_mult[FXP_BUF_SIZE]; + char hugification_threshold[FXP_BUF_SIZE]; + char normalization_message[256] = {0}; + fxp_print(opt_hpa_opts.dirty_mult, hpa_dirty_mult); + fxp_print(fxp_div(FXP_INIT_INT((unsigned) + (opt_hpa_opts.hugification_threshold >> LG_PAGE)), + FXP_INIT_INT(HUGEPAGE_PAGES)), hugification_threshold); + if (!opt_abort_conf) { + char normalized_hugification_threshold[FXP_BUF_SIZE]; + opt_hpa_opts.hugification_threshold += + HUGEPAGE - hpa_threshold; + fxp_print(fxp_div(FXP_INIT_INT((unsigned) + (opt_hpa_opts.hugification_threshold >> LG_PAGE)), + FXP_INIT_INT(HUGEPAGE_PAGES)), + normalized_hugification_threshold); + malloc_snprintf(normalization_message, + sizeof(normalization_message), ": Normalizing " + "HPA settings to avoid pathological behavior, setting " + "hpa_hugification_threshold_ratio: to %s.\n", + normalized_hugification_threshold); + } + malloc_printf( + ": Invalid combination of options " + "hpa_hugification_threshold_ratio: %s and hpa_dirty_mult: %s. " + "These values should sum to > 1.0.\n%s", hugification_threshold, + hpa_dirty_mult, normalization_message); +} + static void malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], bool initial_call, const char *opts_cache[MALLOC_CONF_NSOURCES], - char buf[PATH_MAX + 1]) { + char readlink_buf[PATH_MAX + 1]) { static const char *opts_explain[MALLOC_CONF_NSOURCES] = { "string specified via --with-malloc-conf", "string pointed to by the global variable malloc_conf", @@ -1086,7 +1106,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], for (i = 0; i < MALLOC_CONF_NSOURCES; i++) { /* Get runtime configuration. */ if (initial_call) { - opts_cache[i] = obtain_malloc_conf(i, buf); + opts_cache[i] = obtain_malloc_conf(i, readlink_buf); } opts = opts_cache[i]; if (!initial_call && opt_confirm_conf) { @@ -1224,6 +1244,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], CONF_HANDLE_BOOL(opt_abort, "abort") CONF_HANDLE_BOOL(opt_abort_conf, "abort_conf") + CONF_HANDLE_BOOL(opt_cache_oblivious, "cache_oblivious") CONF_HANDLE_BOOL(opt_trust_madvise, "trust_madvise") if (strncmp("metadata_thp", k, klen) == 0) { int m; @@ -1231,7 +1252,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], for (m = 0; m < metadata_thp_mode_limit; m++) { if (strncmp(metadata_thp_mode_names[m], v, vlen) == 0) { - opt_metadata_thp = (metadata_thp_mode_t)m; + opt_metadata_thp = m; match = true; break; } @@ -1249,7 +1270,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], for (m = 0; m < dss_prec_limit; m++) { if (strncmp(dss_prec_names[m], v, vlen) == 0) { - if (extent_dss_prec_set((dss_prec_t)m)) { + if (extent_dss_prec_set(m)) { CONF_ERROR( "Error setting dss", k, klen, v, vlen); @@ -1295,7 +1316,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], size_t size_start; size_t size_end; size_t nshards; - bool err = malloc_conf_multi_sizes_next( + bool err = multi_setting_parse_next( &bin_shards_segment_cur, &vlen_left, &size_start, &size_end, &nshards); if (err || bin_update_shard_size( @@ -1310,6 +1331,16 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], } while (vlen_left > 0); CONF_CONTINUE; } + if (CONF_MATCH("tcache_ncached_max")) { + bool err = tcache_bin_info_default_init( + v, vlen); + if (err) { + CONF_ERROR("Invalid settings for " + "tcache_ncached_max", k, klen, v, + vlen); + } + CONF_CONTINUE; + } CONF_HANDLE_INT64_T(opt_mutex_max_spin, "mutex_max_spin", -1, INT64_MAX, CONF_CHECK_MIN, CONF_DONT_CHECK_MAX, false); @@ -1423,6 +1454,13 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], CONF_HANDLE_UNSIGNED(opt_lg_tcache_flush_large_div, "lg_tcache_flush_large_div", 1, 16, CONF_CHECK_MIN, CONF_CHECK_MAX, /* clip */ true) + CONF_HANDLE_UNSIGNED(opt_debug_double_free_max_scan, + "debug_double_free_max_scan", 0, UINT_MAX, + CONF_DONT_CHECK_MIN, CONF_DONT_CHECK_MAX, + /* clip */ false) + CONF_HANDLE_SIZE_T(opt_calloc_madvise_threshold, + "calloc_madvise_threshold", 0, SC_LARGE_MAXCLASS, + CONF_DONT_CHECK_MIN, CONF_CHECK_MAX, /* clip */ false) /* * The runtime option of oversize_threshold remains @@ -1451,7 +1489,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], "No getcpu support", k, klen, v, vlen); } - opt_percpu_arena = (percpu_arena_mode_t)m; + opt_percpu_arena = m; match = true; break; } @@ -1553,7 +1591,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], size_t slab_start; size_t slab_end; size_t pgs; - err = malloc_conf_multi_sizes_next( + err = multi_setting_parse_next( &slab_size_segment_cur, &vlen_left, &slab_start, &slab_end, &pgs); @@ -1581,6 +1619,9 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], - 1, CONF_DONT_CHECK_MIN, CONF_CHECK_MAX, true) CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum") + CONF_HANDLE_UNSIGNED(opt_prof_bt_max, "prof_bt_max", + 1, PROF_BT_MAX_LIMIT, CONF_CHECK_MIN, CONF_CHECK_MAX, + /* clip */ true) CONF_HANDLE_SSIZE_T(opt_lg_prof_interval, "lg_prof_interval", -1, (sizeof(uint64_t) << 3) - 1) @@ -1590,6 +1631,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], CONF_HANDLE_BOOL(opt_prof_leak_error, "prof_leak_error") CONF_HANDLE_BOOL(opt_prof_log, "prof_log") + CONF_HANDLE_BOOL(opt_prof_pid_namespace, "prof_pid_namespace") CONF_HANDLE_SSIZE_T(opt_prof_recent_alloc_max, "prof_recent_alloc_max", -1, SSIZE_MAX) CONF_HANDLE_BOOL(opt_prof_stats, "prof_stats") @@ -1646,7 +1688,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], "No THP support", k, klen, v, vlen); } - opt_thp = (thp_mode_t)m; + opt_thp = m; match = true; break; } @@ -1726,6 +1768,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], /* Re-enable diagnostic "-Wtype-limits" */ JEMALLOC_DIAGNOSTIC_POP } + validate_hpa_settings(); if (opt_abort_conf && had_conf_error) { malloc_abort_invalid_conf(); } @@ -1740,18 +1783,22 @@ malloc_conf_init_check_deps(void) { "prof_final.\n"); return true; } + /* To emphasize in the stats output that opt is disabled when !debug. */ + if (!config_debug) { + opt_debug_double_free_max_scan = 0; + } return false; } static void -malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) { +malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], + char readlink_buf[PATH_MAX + 1]) { const char *opts_cache[MALLOC_CONF_NSOURCES] = {NULL, NULL, NULL, NULL, NULL}; - char buf[PATH_MAX + 1]; /* The first call only set the confirm_conf option and opts_cache */ - malloc_conf_init_helper(NULL, NULL, true, opts_cache, buf); + malloc_conf_init_helper(NULL, NULL, true, opts_cache, readlink_buf); malloc_conf_init_helper(sc_data, bin_shard_sizes, false, opts_cache, NULL); if (malloc_conf_init_check_deps()) { @@ -1791,7 +1838,7 @@ malloc_init_hard_needed(void) { } static bool -malloc_init_hard_a0_locked() { +malloc_init_hard_a0_locked(void) { malloc_initializer = INITIALIZER; JEMALLOC_DIAGNOSTIC_PUSH @@ -1817,7 +1864,9 @@ malloc_init_hard_a0_locked() { if (config_prof) { prof_boot0(); } - malloc_conf_init(&sc_data, bin_shard_sizes); + char readlink_buf[PATH_MAX + 1]; + readlink_buf[0] = '\0'; + malloc_conf_init(&sc_data, bin_shard_sizes, readlink_buf); san_init(opt_lg_san_uaf_align); sz_boot(&sc_data, opt_cache_oblivious); bin_info_boot(&sc_data, bin_shard_sizes); @@ -1827,7 +1876,7 @@ malloc_init_hard_a0_locked() { if (atexit(stats_print_atexit) != 0) { malloc_write(": Error in atexit()\n"); if (opt_abort) { - jemalloc_abort(); + abort(); } } } @@ -1911,6 +1960,15 @@ malloc_init_hard_a0_locked() { malloc_init_state = malloc_init_a0_initialized; + size_t buf_len = strlen(readlink_buf); + if (buf_len > 0) { + void *readlink_allocated = a0ialloc(buf_len + 1, false, true); + if (readlink_allocated != NULL) { + memcpy(readlink_allocated, readlink_buf, buf_len + 1); + opt_malloc_conf_symlink = readlink_allocated; + } + } + return false; } @@ -1948,7 +2006,7 @@ malloc_init_hard_recursible(void) { malloc_abort_invalid_conf(); } if (opt_abort) { - jemalloc_abort(); + abort(); } } } @@ -1962,7 +2020,7 @@ malloc_init_hard_recursible(void) { jemalloc_postfork_child) != 0) { malloc_write(": Error in pthread_atfork()\n"); if (opt_abort) { - jemalloc_abort(); + abort(); } return true; } @@ -2001,9 +2059,7 @@ percpu_arena_as_initialized(percpu_arena_mode_t mode) { assert(mode <= percpu_arena_disabled); if (mode != percpu_arena_disabled) { - // DuckDB: have to change to this to silence cpp compiler errors -// mode += percpu_arena_mode_enabled_base; - mode = (percpu_arena_mode_t)((int)mode + (int)percpu_arena_mode_enabled_base); + mode += percpu_arena_mode_enabled_base; } return mode; @@ -2020,14 +2076,14 @@ malloc_init_narenas(void) { "available. Setting narenas to %u.\n", opt_narenas ? opt_narenas : malloc_narenas_default()); if (opt_abort) { - jemalloc_abort(); + abort(); } } else { if (ncpus >= MALLOCX_ARENA_LIMIT) { malloc_printf(": narenas w/ percpu" "arena beyond limit (%d)\n", ncpus); if (opt_abort) { - jemalloc_abort(); + abort(); } return true; } @@ -2039,7 +2095,7 @@ malloc_init_narenas(void) { "with odd number (%u) of CPUs (no hyper " "threading?).\n", ncpus); if (opt_abort) - jemalloc_abort(); + abort(); } unsigned n = percpu_arena_ind_limit( percpu_arena_as_initialized(opt_percpu_arena)); @@ -2077,7 +2133,7 @@ malloc_init_narenas(void) { narenas_auto); } narenas_total_set(narenas_auto); - if (arena_init_huge()) { + if (arena_init_huge(a0)) { narenas_total_inc(); } manual_arena_base = narenas_total_get(); @@ -2260,15 +2316,6 @@ static_opts_init(static_opts_t *static_opts) { static_opts->usize = false; } -/* - * These correspond to the macros in jemalloc/jemalloc_macros.h. Broadly, we - * should have one constant here per magic value there. Note however that the - * representations need not be related. - */ -#define TCACHE_IND_NONE ((unsigned)-1) -#define TCACHE_IND_AUTOMATIC ((unsigned)-2) -#define ARENA_IND_AUTOMATIC ((unsigned)-1) - typedef struct dynamic_opts_s dynamic_opts_t; struct dynamic_opts_s { void **result; @@ -2333,36 +2380,6 @@ zero_get(bool guarantee, bool slow) { } } -JEMALLOC_ALWAYS_INLINE tcache_t * -tcache_get_from_ind(tsd_t *tsd, unsigned tcache_ind, bool slow, bool is_alloc) { - tcache_t *tcache; - if (tcache_ind == TCACHE_IND_AUTOMATIC) { - if (likely(!slow)) { - /* Getting tcache ptr unconditionally. */ - tcache = tsd_tcachep_get(tsd); - assert(tcache == tcache_get(tsd)); - } else if (is_alloc || - likely(tsd_reentrancy_level_get(tsd) == 0)) { - tcache = tcache_get(tsd); - } else { - tcache = NULL; - } - } else { - /* - * Should not specify tcache on deallocation path when being - * reentrant. - */ - assert(is_alloc || tsd_reentrancy_level_get(tsd) == 0 || - tsd_state_nocleanup(tsd)); - if (tcache_ind == TCACHE_IND_NONE) { - tcache = NULL; - } else { - tcache = tcaches_get(tsd, tcache_ind); - } - } - return tcache; -} - /* Return true if a manual arena is specified and arena_get() OOMs. */ JEMALLOC_ALWAYS_INLINE bool arena_get_from_ind(tsd_t *tsd, unsigned arena_ind, arena_t **arena_p) { @@ -2385,7 +2402,7 @@ arena_get_from_ind(tsd_t *tsd, unsigned arena_ind, arena_t **arena_p) { /* ind is ignored if dopts->alignment > 0. */ JEMALLOC_ALWAYS_INLINE void * imalloc_no_sample(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd, - size_t size, size_t usize, szind_t ind) { + size_t size, size_t usize, szind_t ind, bool slab) { /* Fill in the tcache. */ tcache_t *tcache = tcache_get_from_ind(tsd, dopts->tcache_ind, sopts->slow, /* is_alloc */ true); @@ -2397,12 +2414,12 @@ imalloc_no_sample(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd, } if (unlikely(dopts->alignment != 0)) { - return ipalloct(tsd_tsdn(tsd), usize, dopts->alignment, - dopts->zero, tcache, arena); + return ipalloct_explicit_slab(tsd_tsdn(tsd), usize, + dopts->alignment, dopts->zero, slab, tcache, arena); } - return iallocztm(tsd_tsdn(tsd), size, ind, dopts->zero, tcache, false, - arena, sopts->slow); + return iallocztm_explicit_slab(tsd_tsdn(tsd), size, ind, dopts->zero, + slab, tcache, false, arena, sopts->slow); } JEMALLOC_ALWAYS_INLINE void * @@ -2410,29 +2427,26 @@ imalloc_sample(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd, size_t usize, szind_t ind) { void *ret; + dopts->alignment = prof_sample_align(usize, dopts->alignment); /* - * For small allocations, sampling bumps the usize. If so, we allocate - * from the ind_large bucket. + * If the allocation is small enough that it would normally be allocated + * on a slab, we need to take additional steps to ensure that it gets + * its own extent instead. */ - szind_t ind_large; - size_t bumped_usize = usize; - - dopts->alignment = prof_sample_align(dopts->alignment); - if (usize <= SC_SMALL_MAXCLASS) { - assert(((dopts->alignment == 0) ? - sz_s2u(SC_LARGE_MINCLASS) : - sz_sa2u(SC_LARGE_MINCLASS, dopts->alignment)) - == SC_LARGE_MINCLASS); - ind_large = sz_size2index(SC_LARGE_MINCLASS); - bumped_usize = sz_s2u(SC_LARGE_MINCLASS); + if (sz_can_use_slab(usize)) { + assert((dopts->alignment & PROF_SAMPLE_ALIGNMENT_MASK) == 0); + size_t bumped_usize = sz_sa2u(usize, dopts->alignment); + szind_t bumped_ind = sz_size2index(bumped_usize); + dopts->tcache_ind = TCACHE_IND_NONE; ret = imalloc_no_sample(sopts, dopts, tsd, bumped_usize, - bumped_usize, ind_large); + bumped_usize, bumped_ind, /* slab */ false); if (unlikely(ret == NULL)) { return NULL; } - arena_prof_promote(tsd_tsdn(tsd), ret, usize); + arena_prof_promote(tsd_tsdn(tsd), ret, usize, bumped_usize); } else { - ret = imalloc_no_sample(sopts, dopts, tsd, usize, usize, ind); + ret = imalloc_no_sample(sopts, dopts, tsd, usize, usize, ind, + /* slab */ false); } assert(prof_sample_aligned(ret)); @@ -2557,11 +2571,12 @@ imalloc_body(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd) { sample_event); emap_alloc_ctx_t alloc_ctx; - if (likely((uintptr_t)tctx == (uintptr_t)1U)) { - alloc_ctx.slab = (usize <= SC_SMALL_MAXCLASS); + if (likely(tctx == PROF_TCTX_SENTINEL)) { + alloc_ctx.slab = sz_can_use_slab(usize); allocation = imalloc_no_sample( - sopts, dopts, tsd, usize, usize, ind); - } else if ((uintptr_t)tctx > (uintptr_t)1U) { + sopts, dopts, tsd, usize, usize, ind, + alloc_ctx.slab); + } else if (tctx != NULL) { allocation = imalloc_sample( sopts, dopts, tsd, usize, ind); alloc_ctx.slab = false; @@ -2577,7 +2592,7 @@ imalloc_body(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd) { } else { assert(!opt_prof); allocation = imalloc_no_sample(sopts, dopts, tsd, size, usize, - ind); + ind, sz_can_use_slab(usize)); if (unlikely(allocation == NULL)) { goto label_oom; } @@ -2612,7 +2627,7 @@ imalloc_body(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd) { label_oom: if (unlikely(sopts->slow) && config_xmalloc && unlikely(opt_xmalloc)) { malloc_write(sopts->oom_string); - jemalloc_abort(); + abort(); } if (sopts->slow) { @@ -2639,7 +2654,7 @@ imalloc_body(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd) { label_invalid_alignment: if (config_xmalloc && unlikely(opt_xmalloc)) { malloc_write(sopts->invalid_alignment_string); - jemalloc_abort(); + abort(); } if (sopts->set_errno_on_error) { @@ -2664,7 +2679,7 @@ imalloc_init_check(static_opts_t *sopts, dynamic_opts_t *dopts) { if (unlikely(!malloc_initialized()) && unlikely(malloc_init())) { if (config_xmalloc && unlikely(opt_xmalloc)) { malloc_write(sopts->oom_string); - jemalloc_abort(); + abort(); } UTRACE(NULL, dopts->num_items * dopts->item_size, NULL); set_errno(ENOMEM); @@ -2735,8 +2750,6 @@ malloc_default(size_t size) { hook_invoke_alloc(hook_alloc_malloc, ret, (uintptr_t)ret, args); } - LOG("core.malloc.exit", "result: %p", ret); - return ret; } @@ -2744,12 +2757,21 @@ malloc_default(size_t size) { /* * Begin malloc(3)-compatible functions. */ -JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) -JEMALLOC_ALLOC_SIZE(1) JEMALLOC_SYS_NOTHROW * je_malloc(size_t size) { - return imalloc_fastpath(size, &malloc_default); + +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) +je_malloc(size_t size) { + LOG("core.malloc.entry", "size: %zu", size); + + void * ret = imalloc_fastpath(size, &malloc_default); + + LOG("core.malloc.exit", "result: %p", ret); + return ret; } -int JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1)) JEMALLOC_SYS_NOTHROW +JEMALLOC_EXPORT int JEMALLOC_NOTHROW +JEMALLOC_ATTR(nonnull(1)) je_posix_memalign(void **memptr, size_t alignment, size_t size) { int ret; static_opts_t sopts; @@ -2787,8 +2809,10 @@ je_posix_memalign(void **memptr, size_t alignment, size_t size) { return ret; } -JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) -JEMALLOC_ALLOC_SIZE(2) JEMALLOC_SYS_NOTHROW * je_aligned_alloc(size_t alignment, size_t size) { +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(2) +je_aligned_alloc(size_t alignment, size_t size) { void *ret; static_opts_t sopts; @@ -2826,13 +2850,15 @@ JEMALLOC_ALLOC_SIZE(2) JEMALLOC_SYS_NOTHROW * je_aligned_alloc(size_t alignment, return ret; } -JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) -JEMALLOC_ALLOC_SIZE2(1, 2) JEMALLOC_SYS_NOTHROW * je_calloc(size_t num, size_t size) { +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2) +je_calloc(size_t num, size_t size) { void *ret; static_opts_t sopts; dynamic_opts_t dopts; - LOG("core.calloc.entry", "num: %zu, size: %zu\n", num, size); + LOG("core.calloc.entry", "num: %zu, size: %zu", num, size); static_opts_init(&sopts); dynamic_opts_init(&dopts); @@ -2894,29 +2920,6 @@ ifree(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path) { thread_dalloc_event(tsd, usize); } -JEMALLOC_ALWAYS_INLINE bool -maybe_check_alloc_ctx(tsd_t *tsd, void *ptr, emap_alloc_ctx_t *alloc_ctx) { - if (config_opt_size_checks) { - emap_alloc_ctx_t dbg_ctx; - emap_alloc_ctx_lookup(tsd_tsdn(tsd), &arena_emap_global, ptr, - &dbg_ctx); - if (alloc_ctx->szind != dbg_ctx.szind) { - safety_check_fail_sized_dealloc( - /* current_dealloc */ true, ptr, - /* true_size */ sz_size2index(dbg_ctx.szind), - /* input_size */ sz_size2index(alloc_ctx->szind)); - return true; - } - if (alloc_ctx->slab != dbg_ctx.slab) { - safety_check_fail( - "Internal heap corruption detected: " - "mismatch in slab bit"); - return true; - } - } - return false; -} - JEMALLOC_ALWAYS_INLINE void isfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache, bool slow_path) { if (!slow_path) { @@ -3023,143 +3026,27 @@ free_default(void *ptr) { } } -JEMALLOC_ALWAYS_INLINE bool -free_fastpath_nonfast_aligned(void *ptr, bool check_prof) { - /* - * free_fastpath do not handle two uncommon cases: 1) sampled profiled - * objects and 2) sampled junk & stash for use-after-free detection. - * Both have special alignments which are used to escape the fastpath. - * - * prof_sample is page-aligned, which covers the UAF check when both - * are enabled (the assertion below). Avoiding redundant checks since - * this is on the fastpath -- at most one runtime branch from this. - */ - if (config_debug && cache_bin_nonfast_aligned(ptr)) { - assert(prof_sample_aligned(ptr)); - } +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_free(void *ptr) { + LOG("core.free.entry", "ptr: %p", ptr); - if (config_prof && check_prof) { - /* When prof is enabled, the prof_sample alignment is enough. */ - if (prof_sample_aligned(ptr)) { - return true; - } else { - return false; - } - } + je_free_impl(ptr); - if (config_uaf_detection) { - if (cache_bin_nonfast_aligned(ptr)) { - return true; - } else { - return false; - } - } - - return false; + LOG("core.free.exit", ""); } -/* Returns whether or not the free attempt was successful. */ -JEMALLOC_ALWAYS_INLINE -bool free_fastpath(void *ptr, size_t size, bool size_hint) { - tsd_t *tsd = tsd_get(false); - /* The branch gets optimized away unless tsd_get_allocates(). */ - if (unlikely(tsd == NULL)) { - return false; - } - /* - * The tsd_fast() / initialized checks are folded into the branch - * testing (deallocated_after >= threshold) later in this function. - * The threshold will be set to 0 when !tsd_fast. - */ - assert(tsd_fast(tsd) || - *tsd_thread_deallocated_next_event_fastp_get_unsafe(tsd) == 0); - - emap_alloc_ctx_t alloc_ctx; - if (!size_hint) { - bool err = emap_alloc_ctx_try_lookup_fast(tsd, - &arena_emap_global, ptr, &alloc_ctx); - - /* Note: profiled objects will have alloc_ctx.slab set */ - if (unlikely(err || !alloc_ctx.slab || - free_fastpath_nonfast_aligned(ptr, - /* check_prof */ false))) { - return false; - } - assert(alloc_ctx.szind != SC_NSIZES); - } else { - /* - * Check for both sizes that are too large, and for sampled / - * special aligned objects. The alignment check will also check - * for null ptr. - */ - if (unlikely(size > SC_LOOKUP_MAXCLASS || - free_fastpath_nonfast_aligned(ptr, - /* check_prof */ true))) { - return false; - } - alloc_ctx.szind = sz_size2index_lookup(size); - /* Max lookup class must be small. */ - assert(alloc_ctx.szind < SC_NBINS); - /* This is a dead store, except when opt size checking is on. */ - alloc_ctx.slab = true; - } - /* - * Currently the fastpath only handles small sizes. The branch on - * SC_LOOKUP_MAXCLASS makes sure of it. This lets us avoid checking - * tcache szind upper limit (i.e. tcache_maxclass) as well. - */ - assert(alloc_ctx.slab); - - uint64_t deallocated, threshold; - te_free_fastpath_ctx(tsd, &deallocated, &threshold); - - size_t usize = sz_index2size(alloc_ctx.szind); - uint64_t deallocated_after = deallocated + usize; - /* - * Check for events and tsd non-nominal (fast_threshold will be set to - * 0) in a single branch. Note that this handles the uninitialized case - * as well (TSD init will be triggered on the non-fastpath). Therefore - * anything depends on a functional TSD (e.g. the alloc_ctx sanity check - * below) needs to be after this branch. - */ - if (unlikely(deallocated_after >= threshold)) { - return false; - } - assert(tsd_fast(tsd)); - bool fail = maybe_check_alloc_ctx(tsd, ptr, &alloc_ctx); - if (fail) { - /* See the comment in isfree. */ - return true; - } - - tcache_t *tcache = tcache_get_from_ind(tsd, TCACHE_IND_AUTOMATIC, - /* slow */ false, /* is_alloc */ false); - cache_bin_t *bin = &tcache->bins[alloc_ctx.szind]; +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_free_sized(void *ptr, size_t size) { + LOG("core.free_sized.entry", "ptr: %p, size: %zu", ptr, size); - /* - * If junking were enabled, this is where we would do it. It's not - * though, since we ensured above that we're on the fast path. Assert - * that to double-check. - */ - assert(!opt_junk_free); + je_sdallocx_noflags(ptr, size); - if (!cache_bin_dalloc_easy(bin, ptr)) { - return false; - } - - *tsd_thread_deallocatedp_get(tsd) = deallocated_after; - - return true; + LOG("core.free_sized.exit", ""); } -void JEMALLOC_CXX_THROW JEMALLOC_SYS_NOTHROW je_free(void *ptr) { - LOG("core.free.entry", "ptr: %p", ptr); - - if (!free_fastpath(ptr, 0, false)) { - free_default(ptr); - } - - LOG("core.free.exit", ""); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_free_aligned_sized(void *ptr, size_t alignment, size_t size) { + return je_sdallocx(ptr, size, /* flags */ MALLOCX_ALIGN(alignment)); } /* @@ -3171,7 +3058,7 @@ void JEMALLOC_CXX_THROW JEMALLOC_SYS_NOTHROW je_free(void *ptr) { */ #ifdef JEMALLOC_OVERRIDE_MEMALIGN -JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_NOTHROW * JEMALLOC_ATTR(malloc) je_memalign(size_t alignment, size_t size) { @@ -3185,6 +3072,7 @@ je_memalign(size_t alignment, size_t size) { static_opts_init(&sopts); dynamic_opts_init(&dopts); + sopts.bump_empty_aligned_alloc = true; sopts.min_alignment = 1; sopts.oom_string = ": Error allocating aligned memory: out of memory\n"; @@ -3210,8 +3098,10 @@ je_memalign(size_t alignment, size_t size) { #endif #ifdef JEMALLOC_OVERRIDE_VALLOC -JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) -JEMALLOC_SYS_NOTHROW * je_valloc(size_t size) { +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) +je_valloc(size_t size) { void *ret; static_opts_t sopts; @@ -3245,6 +3135,49 @@ JEMALLOC_SYS_NOTHROW * je_valloc(size_t size) { } #endif +#ifdef JEMALLOC_OVERRIDE_PVALLOC +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) +je_pvalloc(size_t size) { + void *ret; + + static_opts_t sopts; + dynamic_opts_t dopts; + + LOG("core.pvalloc.entry", "size: %zu\n", size); + + static_opts_init(&sopts); + dynamic_opts_init(&dopts); + + sopts.null_out_result_on_error = true; + sopts.min_alignment = PAGE; + sopts.oom_string = + ": Error allocating aligned memory: out of memory\n"; + sopts.invalid_alignment_string = + ": Error allocating aligned memory: invalid alignment\n"; + + dopts.result = &ret; + dopts.num_items = 1; + /* + * This is the only difference from je_valloc - size is rounded up to + * a PAGE multiple. + */ + dopts.item_size = PAGE_CEILING(size); + dopts.alignment = PAGE; + + imalloc(&sopts, &dopts); + if (sopts.slow) { + uintptr_t args[3] = {size}; + hook_invoke_alloc(hook_alloc_pvalloc, ret, (uintptr_t)ret, + args); + } + + LOG("core.pvalloc.exit", "result: %p\n", ret); + return ret; +} +#endif + #if defined(JEMALLOC_IS_MALLOC) && defined(JEMALLOC_GLIBC_MALLOC_HOOK) /* * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible @@ -3257,11 +3190,11 @@ JEMALLOC_SYS_NOTHROW * je_valloc(size_t size) { */ #include // defines __GLIBC__ if we are compiling against glibc -void (*__free_hook)(void *ptr) = je_free; -void *(*__malloc_hook)(size_t size) = je_malloc; -void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc; +JEMALLOC_EXPORT void (*__free_hook)(void *ptr) = je_free; +JEMALLOC_EXPORT void *(*__malloc_hook)(size_t size) = je_malloc; +JEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc; # ifdef JEMALLOC_GLIBC_MEMALIGN_HOOK -void *(*__memalign_hook)(size_t alignment, size_t size) = +JEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) = je_memalign; # endif @@ -3280,6 +3213,13 @@ void *__libc_calloc(size_t n, size_t size) PREALIAS(je_calloc); # ifdef JEMALLOC_OVERRIDE___LIBC_FREE void __libc_free(void* ptr) PREALIAS(je_free); # endif +# ifdef JEMALLOC_OVERRIDE___LIBC_FREE_SIZED +void __libc_free_sized(void* ptr, size_t size) PREALIAS(je_free_sized); +# endif +# ifdef JEMALLOC_OVERRIDE___LIBC_FREE_ALIGNED_SIZED +void __libc_free_aligned_sized( + void* ptr, size_t alignment, size_t size) PREALIAS(je_free_aligned_sized); +# endif # ifdef JEMALLOC_OVERRIDE___LIBC_MALLOC void *__libc_malloc(size_t size) PREALIAS(je_malloc); # endif @@ -3292,6 +3232,9 @@ void *__libc_realloc(void* ptr, size_t size) PREALIAS(je_realloc); # ifdef JEMALLOC_OVERRIDE___LIBC_VALLOC void *__libc_valloc(size_t size) PREALIAS(je_valloc); # endif +# ifdef JEMALLOC_OVERRIDE___LIBC_PVALLOC +void *__libc_pvalloc(size_t size) PREALIAS(je_pvalloc); +# endif # ifdef JEMALLOC_OVERRIDE___POSIX_MEMALIGN int __posix_memalign(void** r, size_t a, size_t s) PREALIAS(je_posix_memalign); # endif @@ -3339,7 +3282,7 @@ typedef struct { size_t size; } smallocx_return_t; -JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN smallocx_return_t JEMALLOC_NOTHROW /* * The attribute JEMALLOC_ATTR(malloc) cannot be used due to: @@ -3389,8 +3332,10 @@ JEMALLOC_SMALLOCX_CONCAT_HELPER2(je_smallocx_, JEMALLOC_VERSION_GID_IDENT) #undef JEMALLOC_SMALLOCX_CONCAT_HELPER2 #endif -JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) -JEMALLOC_NOTHROW *je_mallocx(size_t size, int flags) { +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) +je_mallocx(size_t size, int flags) { void *ret; static_opts_t sopts; dynamic_opts_t dopts; @@ -3416,7 +3361,7 @@ JEMALLOC_NOTHROW *je_mallocx(size_t size, int flags) { imalloc(&sopts, &dopts); if (sopts.slow) { - uintptr_t args[3] = {size, (uintptr_t)flags}; + uintptr_t args[3] = {size, flags}; hook_invoke_alloc(hook_alloc_mallocx, ret, (uintptr_t)ret, args); } @@ -3435,18 +3380,25 @@ irallocx_prof_sample(tsdn_t *tsdn, void *old_ptr, size_t old_usize, return NULL; } - alignment = prof_sample_align(alignment); - if (usize <= SC_SMALL_MAXCLASS) { - p = iralloct(tsdn, old_ptr, old_usize, - SC_LARGE_MINCLASS, alignment, zero, tcache, - arena, hook_args); + alignment = prof_sample_align(usize, alignment); + /* + * If the allocation is small enough that it would normally be allocated + * on a slab, we need to take additional steps to ensure that it gets + * its own extent instead. + */ + if (sz_can_use_slab(usize)) { + size_t bumped_usize = sz_sa2u(usize, alignment); + p = iralloct_explicit_slab(tsdn, old_ptr, old_usize, + bumped_usize, alignment, zero, /* slab */ false, + tcache, arena, hook_args); if (p == NULL) { return NULL; } - arena_prof_promote(tsdn, p, usize); + arena_prof_promote(tsdn, p, usize, bumped_usize); } else { - p = iralloct(tsdn, old_ptr, old_usize, usize, alignment, zero, - tcache, arena, hook_args); + p = iralloct_explicit_slab(tsdn, old_ptr, old_usize, usize, + alignment, zero, /* slab */ false, tcache, arena, + hook_args); } assert(prof_sample_aligned(p)); @@ -3464,12 +3416,12 @@ irallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size, bool sample_event = te_prof_sample_event_lookahead(tsd, usize); prof_tctx_t *tctx = prof_alloc_prep(tsd, prof_active, sample_event); void *p; - if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) { + if (unlikely(tctx != PROF_TCTX_SENTINEL)) { p = irallocx_prof_sample(tsd_tsdn(tsd), old_ptr, old_usize, usize, alignment, zero, tcache, arena, tctx, hook_args); } else { p = iralloct(tsd_tsdn(tsd), old_ptr, old_usize, size, alignment, - zero, tcache, arena, hook_args); + usize, zero, tcache, arena, hook_args); } if (unlikely(p == NULL)) { prof_alloc_rollback(tsd, tctx); @@ -3500,14 +3452,12 @@ do_rallocx(void *ptr, size_t size, int flags, bool is_realloc) { bool zero = zero_get(MALLOCX_ZERO_GET(flags), /* slow */ true); unsigned arena_ind = mallocx_arena_get(flags); - unsigned tcache_ind; - tcache_t *tcache; if (arena_get_from_ind(tsd, arena_ind, &arena)) { goto label_oom; } - tcache_ind = mallocx_tcache_get(flags); - tcache = tcache_get_from_ind(tsd, tcache_ind, + unsigned tcache_ind = mallocx_tcache_get(flags); + tcache_t *tcache = tcache_get_from_ind(tsd, tcache_ind, /* slow */ true, /* is_alloc */ true); emap_alloc_ctx_t alloc_ctx; @@ -3516,13 +3466,12 @@ do_rallocx(void *ptr, size_t size, int flags, bool is_realloc) { assert(alloc_ctx.szind != SC_NSIZES); old_usize = sz_index2size(alloc_ctx.szind); assert(old_usize == isalloc(tsd_tsdn(tsd), ptr)); - hook_ralloc_args_t hook_args; if (aligned_usize_get(size, alignment, &usize, NULL, false)) { goto label_oom; } - hook_args = {is_realloc, {(uintptr_t)ptr, size, - (uintptr_t)flags, 0}}; + hook_ralloc_args_t hook_args = {is_realloc, {(uintptr_t)ptr, size, + flags, 0}}; if (config_prof && opt_prof) { p = irallocx_prof(tsd, ptr, old_usize, size, alignment, usize, zero, tcache, arena, &alloc_ctx, &hook_args); @@ -3531,7 +3480,7 @@ do_rallocx(void *ptr, size_t size, int flags, bool is_realloc) { } } else { p = iralloct(tsd_tsdn(tsd), ptr, old_usize, size, alignment, - zero, tcache, arena, &hook_args); + usize, zero, tcache, arena, &hook_args); if (unlikely(p == NULL)) { goto label_oom; } @@ -3547,15 +3496,18 @@ do_rallocx(void *ptr, size_t size, int flags, bool is_realloc) { if (config_fill && unlikely(opt_junk_alloc) && usize > old_usize && !zero) { size_t excess_len = usize - old_usize; - void *excess_start = (void *)((uintptr_t)p + old_usize); + void *excess_start = (void *)((byte_t *)p + old_usize); junk_alloc_callback(excess_start, excess_len); } return p; label_oom: + if (is_realloc) { + set_errno(ENOMEM); + } if (config_xmalloc && unlikely(opt_xmalloc)) { malloc_write(": Error in rallocx(): out of memory\n"); - jemalloc_abort(); + abort(); } UTRACE(ptr, size, 0); check_entry_exit_locking(tsd_tsdn(tsd)); @@ -3563,8 +3515,10 @@ do_rallocx(void *ptr, size_t size, int flags, bool is_realloc) { return NULL; } -JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_ALLOC_SIZE(2) JEMALLOC_NOTHROW -* je_rallocx(void *ptr, size_t size, int flags) { +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ALLOC_SIZE(2) +je_rallocx(void *ptr, size_t size, int flags) { LOG("core.rallocx.entry", "ptr: %p, size: %zu, flags: %d", ptr, size, flags); void *ret = do_rallocx(ptr, size, flags, false); @@ -3611,8 +3565,10 @@ do_realloc_nonnull_zero(void *ptr) { } } -JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2) -JEMALLOC_SYS_NOTHROW * je_realloc(void *ptr, size_t size) { +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ALLOC_SIZE(2) +je_realloc(void *ptr, size_t size) { LOG("core.realloc.entry", "ptr: %p, size: %zu\n", ptr, size); if (likely(ptr != NULL && size != 0)) { @@ -3709,7 +3665,7 @@ ixallocx_prof(tsd_t *tsd, void *ptr, size_t old_usize, size_t size, prof_tctx_t *tctx = prof_alloc_prep(tsd, prof_active, sample_event); size_t usize; - if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) { + if (unlikely(tctx != PROF_TCTX_SENTINEL)) { usize = ixallocx_prof_sample(tsd_tsdn(tsd), ptr, old_usize, size, extra, alignment, zero, tctx); } else { @@ -3741,7 +3697,8 @@ ixallocx_prof(tsd_t *tsd, void *ptr, size_t old_usize, size_t size, return usize; } -size_t JEMALLOC_NOTHROW je_xallocx(void *ptr, size_t size, size_t extra, int flags) { +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW +je_xallocx(void *ptr, size_t size, size_t extra, int flags) { tsd_t *tsd; size_t usize, old_usize; size_t alignment = MALLOCX_ALIGN_GET(flags); @@ -3812,12 +3769,12 @@ size_t JEMALLOC_NOTHROW je_xallocx(void *ptr, size_t size, size_t extra, int fla if (config_fill && unlikely(opt_junk_alloc) && usize > old_usize && !zero) { size_t excess_len = usize - old_usize; - void *excess_start = (void *)((uintptr_t)ptr + old_usize); + void *excess_start = (void *)((byte_t *)ptr + old_usize); junk_alloc_callback(excess_start, excess_len); } label_not_resized: if (unlikely(!tsd_fast(tsd))) { - uintptr_t args[4] = {(uintptr_t)ptr, size, extra, (uintptr_t)flags}; + uintptr_t args[4] = {(uintptr_t)ptr, size, extra, flags}; hook_invoke_expand(hook_expand_xallocx, ptr, old_usize, usize, (uintptr_t)usize, args); } @@ -3829,7 +3786,9 @@ size_t JEMALLOC_NOTHROW je_xallocx(void *ptr, size_t size, size_t extra, int fla return usize; } -size_t JEMALLOC_ATTR(pure) JEMALLOC_NOTHROW je_sallocx(const void *ptr, int flags) { +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW +JEMALLOC_ATTR(pure) +je_sallocx(const void *ptr, int flags) { size_t usize; tsdn_t *tsdn; @@ -3854,7 +3813,8 @@ size_t JEMALLOC_ATTR(pure) JEMALLOC_NOTHROW je_sallocx(const void *ptr, int flag return usize; } -void JEMALLOC_NOTHROW je_dallocx(void *ptr, int flags) { +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_dallocx(void *ptr, int flags) { LOG("core.dallocx.entry", "ptr: %p, flags: %d", ptr, flags); assert(ptr != NULL); @@ -3873,7 +3833,7 @@ void JEMALLOC_NOTHROW je_dallocx(void *ptr, int flags) { tsd_assert_fast(tsd); ifree(tsd, ptr, tcache, false); } else { - uintptr_t args_raw[3] = {(uintptr_t)ptr, (uintptr_t)flags}; + uintptr_t args_raw[3] = {(uintptr_t)ptr, flags}; hook_invoke_dalloc(hook_dalloc_dallocx, ptr, args_raw); ifree(tsd, ptr, tcache, true); } @@ -3911,37 +3871,26 @@ sdallocx_default(void *ptr, size_t size, int flags) { tsd_assert_fast(tsd); isfree(tsd, ptr, usize, tcache, false); } else { - uintptr_t args_raw[3] = {(uintptr_t)ptr, size, (uintptr_t)flags}; + uintptr_t args_raw[3] = {(uintptr_t)ptr, size, flags}; hook_invoke_dalloc(hook_dalloc_sdallocx, ptr, args_raw); isfree(tsd, ptr, usize, tcache, true); } check_entry_exit_locking(tsd_tsdn(tsd)); } -void JEMALLOC_NOTHROW je_sdallocx(void *ptr, size_t size, int flags) { +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_sdallocx(void *ptr, size_t size, int flags) { LOG("core.sdallocx.entry", "ptr: %p, size: %zu, flags: %d", ptr, size, flags); - if (flags != 0 || !free_fastpath(ptr, size, true)) { - sdallocx_default(ptr, size, flags); - } - - LOG("core.sdallocx.exit", ""); -} - -void JEMALLOC_NOTHROW -je_sdallocx_noflags(void *ptr, size_t size) { - LOG("core.sdallocx.entry", "ptr: %p, size: %zu, flags: 0", ptr, - size); - - if (!free_fastpath(ptr, size, true)) { - sdallocx_default(ptr, size, 0); - } + je_sdallocx_impl(ptr, size, flags); LOG("core.sdallocx.exit", ""); } -size_t JEMALLOC_ATTR(pure) JEMALLOC_NOTHROW je_nallocx(size_t size, int flags) { +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW +JEMALLOC_ATTR(pure) +je_nallocx(size_t size, int flags) { size_t usize; tsdn_t *tsdn; @@ -3966,7 +3915,7 @@ size_t JEMALLOC_ATTR(pure) JEMALLOC_NOTHROW je_nallocx(size_t size, int flags) { return usize; } -int JEMALLOC_NOTHROW +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; @@ -3988,7 +3937,7 @@ je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, return ret; } -int JEMALLOC_NOTHROW +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp) { int ret; @@ -4008,7 +3957,7 @@ je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp) { return ret; } -int JEMALLOC_NOTHROW +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; @@ -4030,7 +3979,7 @@ je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, } #define STATS_PRINT_BUFSIZE 65536 -void JEMALLOC_NOTHROW +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque, const char *opts) { tsdn_t *tsdn; @@ -4078,7 +4027,7 @@ je_malloc_usable_size_impl(JEMALLOC_USABLE_SIZE_CONST void *ptr) { return ret; } -size_t JEMALLOC_NOTHROW +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) { LOG("core.malloc_usable_size.entry", "ptr: %p", ptr); @@ -4089,7 +4038,7 @@ je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) { } #ifdef JEMALLOC_HAVE_MALLOC_SIZE -size_t JEMALLOC_NOTHROW +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_malloc_size(const void *ptr) { LOG("core.malloc_size.entry", "ptr: %p", ptr); @@ -4123,30 +4072,26 @@ batch_alloc(void **ptrs, size_t num, size_t size, int flags) { size_t filled = 0; - size_t nregs = 0; - cache_bin_t *bin = NULL; - arena_t *arena = NULL; - - bool zero; - szind_t ind; - size_t alignment; - if (unlikely(tsd == NULL || tsd_reentrancy_level_get(tsd) > 0)) { goto label_done; } - alignment = MALLOCX_ALIGN_GET(flags); + size_t alignment = MALLOCX_ALIGN_GET(flags); size_t usize; if (aligned_usize_get(size, alignment, &usize, NULL, false)) { goto label_done; } - ind = sz_size2index(usize); - zero = zero_get(MALLOCX_ZERO_GET(flags), /* slow */ true); + szind_t ind = sz_size2index(usize); + bool zero = zero_get(MALLOCX_ZERO_GET(flags), /* slow */ true); /* * The cache bin and arena will be lazily initialized; it's hard to * know in advance whether each of them needs to be initialized. */ + cache_bin_t *bin = NULL; + arena_t *arena = NULL; + + size_t nregs = 0; if (likely(ind < SC_NBINS)) { nregs = bin_infos[ind].nregs; assert(nregs > 0); @@ -4192,15 +4137,15 @@ batch_alloc(void **ptrs, size_t num, size_t size, int flags) { filled += n; } - if (likely(ind < nhbins) && progress < batch) { + unsigned tcache_ind = mallocx_tcache_get(flags); + tcache_t *tcache = tcache_get_from_ind(tsd, tcache_ind, + /* slow */ true, /* is_alloc */ true); + if (likely(tcache != NULL && + ind < tcache_nbins_get(tcache->tcache_slow) && + !tcache_bin_disabled(ind, &tcache->bins[ind], + tcache->tcache_slow)) && progress < batch) { if (bin == NULL) { - unsigned tcache_ind = mallocx_tcache_get(flags); - tcache_t *tcache = tcache_get_from_ind(tsd, - tcache_ind, /* slow */ true, - /* is_alloc */ true); - if (tcache != NULL) { - bin = &tcache->bins[ind]; - } + bin = &tcache->bins[ind]; } /* * If we don't have a tcache bin, we don't want to @@ -4308,8 +4253,19 @@ batch_alloc(void **ptrs, size_t num, size_t size, int flags) { JEMALLOC_ATTR(constructor) static void jemalloc_constructor(void) { - static const std::string CONFIG_STRING = duckdb::StringUtil::Format("narenas:%llu,dirty_decay_ms:1000,muzzy_decay_ms:1000", duckdb::idx_t(malloc_ncpus())); - je_malloc_conf = CONFIG_STRING.c_str(); + unsigned long long cpu_count = malloc_ncpus(); + unsigned long long bgt_count = cpu_count / 32; + if (bgt_count == 0) { + bgt_count = 1; + } + // decay is in ms + unsigned long long decay = DUCKDB_DECAY_DELAY * 1000; +#ifdef DEBUG + snprintf(JE_MALLOC_CONF_BUFFER, JE_MALLOC_CONF_BUFFER_SIZE, "junk:true,oversize_threshold:268435456,dirty_decay_ms:%llu,muzzy_decay_ms:%llu,narenas:%llu,max_background_threads:%llu", decay, decay, cpu_count, bgt_count); +#else + snprintf(JE_MALLOC_CONF_BUFFER, JE_MALLOC_CONF_BUFFER_SIZE, "oversize_threshold:268435456,dirty_decay_ms:%llu,muzzy_decay_ms:%llu,narenas:%llu,max_background_threads:%llu", decay, decay, cpu_count, bgt_count); +#endif + je_malloc_conf = JE_MALLOC_CONF_BUFFER; malloc_init(); } #endif @@ -4318,7 +4274,7 @@ jemalloc_constructor(void) { void jemalloc_prefork(void) #else -void +JEMALLOC_EXPORT void _malloc_prefork(void) #endif { @@ -4326,7 +4282,6 @@ _malloc_prefork(void) unsigned i, j, narenas; arena_t *arena; - #ifdef JEMALLOC_MUTEX_INIT_CB if (!malloc_initialized()) { return; @@ -4398,7 +4353,7 @@ _malloc_prefork(void) void jemalloc_postfork_parent(void) #else -void +JEMALLOC_EXPORT void _malloc_postfork(void) #endif { @@ -4466,5 +4421,3 @@ jemalloc_postfork_child(void) { } /******************************************************************************/ - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/jemalloc_cpp.cpp b/extension/jemalloc/jemalloc/src/jemalloc_cpp.cpp new file mode 100644 index 00000000000..fffd6aee5b4 --- /dev/null +++ b/extension/jemalloc/jemalloc/src/jemalloc_cpp.cpp @@ -0,0 +1,308 @@ +#include +#include +// NOLINTBEGIN(misc-use-anonymous-namespace) + +#ifdef __cplusplus +extern "C" { +#endif + +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#ifdef __cplusplus +} +#endif + +// All operators in this file are exported. + +// Possibly alias hidden versions of malloc and sdallocx to avoid an extra plt +// thunk? +// +// extern __typeof (sdallocx) sdallocx_int +// __attribute ((alias ("sdallocx"), +// visibility ("hidden"))); +// +// ... but it needs to work with jemalloc namespaces. + +void *operator new(std::size_t size); +void *operator new[](std::size_t size); +void *operator new(std::size_t size, const std::nothrow_t &) noexcept; +void *operator new[](std::size_t size, const std::nothrow_t &) noexcept; +void operator delete(void *ptr) noexcept; +void operator delete[](void *ptr) noexcept; +void operator delete(void *ptr, const std::nothrow_t &) noexcept; +void operator delete[](void *ptr, const std::nothrow_t &) noexcept; + +#if __cpp_sized_deallocation >= 201309 +/* C++14's sized-delete operators. */ +void operator delete(void *ptr, std::size_t size) noexcept; +void operator delete[](void *ptr, std::size_t size) noexcept; +#endif + +#if __cpp_aligned_new >= 201606 +/* C++17's over-aligned operators. */ +void *operator new(std::size_t size, std::align_val_t); +void *operator new(std::size_t size, std::align_val_t, const std::nothrow_t &) noexcept; +void *operator new[](std::size_t size, std::align_val_t); +void *operator new[](std::size_t size, std::align_val_t, const std::nothrow_t &) noexcept; +void operator delete(void* ptr, std::align_val_t) noexcept; +void operator delete(void* ptr, std::align_val_t, const std::nothrow_t &) noexcept; +void operator delete(void* ptr, std::size_t size, std::align_val_t al) noexcept; +void operator delete[](void* ptr, std::align_val_t) noexcept; +void operator delete[](void* ptr, std::align_val_t, const std::nothrow_t &) noexcept; +void operator delete[](void* ptr, std::size_t size, std::align_val_t al) noexcept; +#endif + +JEMALLOC_NOINLINE +static void * +handleOOM(std::size_t size, bool nothrow) { + if (opt_experimental_infallible_new) { + const char *huge_warning = (size >= ((std::size_t)1 << 30)) ? + "This may be caused by heap corruption, if the large size " + "is unexpected (suggest building with sanitizers for " + "debugging)." : ""; + + safety_check_fail(": Allocation of size %zu failed. " + "%s opt.experimental_infallible_new is true. Aborting.\n", + size, huge_warning); + return nullptr; + } + + void *ptr = nullptr; + + while (ptr == nullptr) { + std::new_handler handler; + // GCC-4.8 and clang 4.0 do not have std::get_new_handler. + { + static std::mutex mtx; + std::lock_guard lock(mtx); + + handler = std::set_new_handler(nullptr); + std::set_new_handler(handler); + } + if (handler == nullptr) + break; + + try { + handler(); + } catch (const std::bad_alloc &) { + break; + } + + ptr = je_malloc(size); + } + + if (ptr == nullptr && !nothrow) + std::__throw_bad_alloc(); + return ptr; +} + +template +JEMALLOC_NOINLINE +static void * +fallbackNewImpl(std::size_t size) noexcept(IsNoExcept) { + void *ptr = malloc_default(size); + if (likely(ptr != nullptr)) { + return ptr; + } + return handleOOM(size, IsNoExcept); +} + +template +JEMALLOC_ALWAYS_INLINE +void * +newImpl(std::size_t size) noexcept(IsNoExcept) { + LOG("core.operator_new.entry", "size: %zu", size); + + void * ret = imalloc_fastpath(size, &fallbackNewImpl); + + LOG("core.operator_new.exit", "result: %p", ret); + return ret; +} + +void * +operator new(std::size_t size) { + return newImpl(size); +} + +void * +operator new[](std::size_t size) { + return newImpl(size); +} + +void * +operator new(std::size_t size, const std::nothrow_t &) noexcept { + return newImpl(size); +} + +void * +operator new[](std::size_t size, const std::nothrow_t &) noexcept { + return newImpl(size); +} + +#if __cpp_aligned_new >= 201606 + +template +JEMALLOC_ALWAYS_INLINE +void * +alignedNewImpl(std::size_t size, std::align_val_t alignment) noexcept(IsNoExcept) { + void *ptr = je_aligned_alloc(static_cast(alignment), size); + if (likely(ptr != nullptr)) { + return ptr; + } + + return handleOOM(size, IsNoExcept); +} + +void * +operator new(std::size_t size, std::align_val_t alignment) { + return alignedNewImpl(size, alignment); +} + +void * +operator new[](std::size_t size, std::align_val_t alignment) { + return alignedNewImpl(size, alignment); +} + +void * +operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t &) noexcept { + return alignedNewImpl(size, alignment); +} + +void * +operator new[](std::size_t size, std::align_val_t alignment, const std::nothrow_t &) noexcept { + return alignedNewImpl(size, alignment); +} + +#endif // __cpp_aligned_new + +void +operator delete(void *ptr) noexcept { + LOG("core.operator_delete.entry", "ptr: %p", ptr); + + je_free_impl(ptr); + + LOG("core.operator_delete.exit", ""); +} + +void +operator delete[](void *ptr) noexcept { + LOG("core.operator_delete.entry", "ptr: %p", ptr); + + je_free_impl(ptr); + + LOG("core.operator_delete.exit", ""); +} + +void +operator delete(void *ptr, const std::nothrow_t &) noexcept { + LOG("core.operator_delete.entry", "ptr: %p", ptr); + + je_free_impl(ptr); + + LOG("core.operator_delete.exit", ""); +} + +void operator delete[](void *ptr, const std::nothrow_t &) noexcept { + LOG("core.operator_delete.entry", "ptr: %p", ptr); + + je_free_impl(ptr); + + LOG("core.operator_delete.exit", ""); +} + +#if __cpp_sized_deallocation >= 201309 + +JEMALLOC_ALWAYS_INLINE +void +sizedDeleteImpl(void* ptr, std::size_t size) noexcept { + if (unlikely(ptr == nullptr)) { + return; + } + LOG("core.operator_delete.entry", "ptr: %p, size: %zu", ptr, size); + + je_sdallocx_noflags(ptr, size); + + LOG("core.operator_delete.exit", ""); +} + +void +operator delete(void *ptr, std::size_t size) noexcept { + sizedDeleteImpl(ptr, size); +} + +void +operator delete[](void *ptr, std::size_t size) noexcept { + sizedDeleteImpl(ptr, size); +} + +#endif // __cpp_sized_deallocation + +#if __cpp_aligned_new >= 201606 + +JEMALLOC_ALWAYS_INLINE +void +alignedSizedDeleteImpl(void* ptr, std::size_t size, std::align_val_t alignment) + noexcept { + if (config_debug) { + assert(((size_t)alignment & ((size_t)alignment - 1)) == 0); + } + if (unlikely(ptr == nullptr)) { + return; + } + LOG("core.operator_delete.entry", "ptr: %p, size: %zu, alignment: %zu", + ptr, size, alignment); + + je_sdallocx_impl(ptr, size, MALLOCX_ALIGN(alignment)); + + LOG("core.operator_delete.exit", ""); +} + +void +operator delete(void* ptr, std::align_val_t) noexcept { + LOG("core.operator_delete.entry", "ptr: %p", ptr); + + je_free_impl(ptr); + + LOG("core.operator_delete.exit", ""); +} + +void +operator delete[](void* ptr, std::align_val_t) noexcept { + LOG("core.operator_delete.entry", "ptr: %p", ptr); + + je_free_impl(ptr); + + LOG("core.operator_delete.exit", ""); +} + +void +operator delete(void* ptr, std::align_val_t, const std::nothrow_t&) noexcept { + LOG("core.operator_delete.entry", "ptr: %p", ptr); + + je_free_impl(ptr); + + LOG("core.operator_delete.exit", ""); +} + +void +operator delete[](void* ptr, std::align_val_t, const std::nothrow_t&) noexcept { + LOG("core.operator_delete.entry", "ptr: %p", ptr); + + je_free_impl(ptr); + + LOG("core.operator_delete.exit", ""); +} + +void +operator delete(void* ptr, std::size_t size, std::align_val_t alignment) noexcept { + alignedSizedDeleteImpl(ptr, size, alignment); +} + +void +operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexcept { + alignedSizedDeleteImpl(ptr, size, alignment); +} + +#endif // __cpp_aligned_new +// NOLINTEND(misc-use-anonymous-namespace) diff --git a/extension/jemalloc/jemalloc/src/large.cpp b/extension/jemalloc/jemalloc/src/large.c similarity index 96% rename from extension/jemalloc/jemalloc/src/large.cpp rename to extension/jemalloc/jemalloc/src/large.c index adccf561d4e..d78085f03c0 100644 --- a/extension/jemalloc/jemalloc/src/large.cpp +++ b/extension/jemalloc/jemalloc/src/large.c @@ -8,8 +8,6 @@ #include "jemalloc/internal/prof_recent.h" #include "jemalloc/internal/util.h" -namespace duckdb_jemalloc { - /******************************************************************************/ void * @@ -115,10 +113,10 @@ large_ralloc_no_move_expand(tsdn_t *tsdn, edata_t *edata, size_t usize, * of CACHELINE in [0 .. PAGE). */ void *zbase = (void *) - ((uintptr_t)edata_addr_get(edata) + old_usize); - void *zpast = PAGE_ADDR2BASE((void *)((uintptr_t)zbase + + ((byte_t *)edata_addr_get(edata) + old_usize); + void *zpast = PAGE_ADDR2BASE((void *)((byte_t *)zbase + PAGE)); - size_t nzero = (uintptr_t)zpast - (uintptr_t)zbase; + size_t nzero = (byte_t *)zpast - (byte_t *)zbase; assert(nzero > 0); memset(zbase, 0, nzero); } @@ -289,7 +287,7 @@ large_prof_info_get(tsd_t *tsd, edata_t *edata, prof_info_t *prof_info, prof_tctx_t *alloc_tctx = edata_prof_tctx_get(edata); prof_info->alloc_tctx = alloc_tctx; - if ((uintptr_t)alloc_tctx > (uintptr_t)1U) { + if (prof_tctx_is_valid(alloc_tctx)) { nstime_copy(&prof_info->alloc_time, edata_prof_alloc_time_get(edata)); prof_info->alloc_size = edata_prof_alloc_size_get(edata); @@ -310,7 +308,7 @@ large_prof_tctx_set(edata_t *edata, prof_tctx_t *tctx) { void large_prof_tctx_reset(edata_t *edata) { - large_prof_tctx_set(edata, (prof_tctx_t *)(uintptr_t)1U); + large_prof_tctx_set(edata, PROF_TCTX_SENTINEL); } void @@ -322,5 +320,3 @@ large_prof_info_set(edata_t *edata, prof_tctx_t *tctx, size_t size) { edata_prof_recent_alloc_init(edata); large_prof_tctx_set(edata, tctx); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/log.cpp b/extension/jemalloc/jemalloc/src/log.c similarity index 97% rename from extension/jemalloc/jemalloc/src/log.cpp rename to extension/jemalloc/jemalloc/src/log.c index d2e1fa8529e..778902fb9b8 100644 --- a/extension/jemalloc/jemalloc/src/log.cpp +++ b/extension/jemalloc/jemalloc/src/log.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/log.h" -namespace duckdb_jemalloc { - char log_var_names[JEMALLOC_LOG_VAR_BUFSIZE]; atomic_b_t log_init_done = ATOMIC_INIT(false); @@ -78,5 +76,3 @@ log_var_update_state(log_var_t *log_var) { segment_begin = segment_end + 1; } } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/malloc_io.cpp b/extension/jemalloc/jemalloc/src/malloc_io.c similarity index 96% rename from extension/jemalloc/jemalloc/src/malloc_io.cpp rename to extension/jemalloc/jemalloc/src/malloc_io.c index 59cceeba36f..192d82081cc 100644 --- a/extension/jemalloc/jemalloc/src/malloc_io.cpp +++ b/extension/jemalloc/jemalloc/src/malloc_io.c @@ -1,12 +1,9 @@ -#include "jemalloc/internal/malloc_io.h" - #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" +#include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/util.h" -namespace duckdb_jemalloc { - #ifdef assert # undef assert #endif @@ -27,14 +24,14 @@ namespace duckdb_jemalloc { #define assert(e) do { \ if (config_debug && !(e)) { \ malloc_write(": Failed assertion\n"); \ - jemalloc_abort(); \ + abort(); \ } \ } while (0) #define not_reached() do { \ if (config_debug) { \ malloc_write(": Unreachable code reached\n"); \ - jemalloc_abort(); \ + abort(); \ } \ unreachable(); \ } while (0) @@ -42,7 +39,7 @@ namespace duckdb_jemalloc { #define not_implemented() do { \ if (config_debug) { \ malloc_write(": Not implemented\n"); \ - jemalloc_abort(); \ + abort(); \ } \ } while (0) @@ -95,8 +92,20 @@ malloc_write(const char *s) { */ int buferror(int err, char *buf, size_t buflen) { - // duckdb: this function was not portable +#ifdef _WIN32 + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, + (LPSTR)buf, (DWORD)buflen, NULL); return 0; +#elif defined(JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE) && defined(_GNU_SOURCE) + char *b = strerror_r(err, buf, buflen); + if (b != buf) { + strncpy(buf, b, buflen); + buf[buflen-1] = '\0'; + } + return 0; +#else + return strerror_r(err, buf, buflen); +#endif } uintmax_t @@ -307,7 +316,8 @@ x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p) { if (alt_form) { s -= 2; (*slen_p) += 2; - memcpy(s, uppercase ? "0X" : "0x", 2); + s[0] = '0'; + s[1] = uppercase ? 'X' : 'x'; } return s; } @@ -414,7 +424,6 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) { unsigned char len = '?'; char *s; size_t slen; - bool first_width_digit = true; bool pad_zero = false; f++; @@ -453,9 +462,7 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) { } break; case '0': - if (first_width_digit) { - pad_zero = true; - } + pad_zero = true; JEMALLOC_FALLTHROUGH; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { @@ -465,7 +472,6 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) { assert(uwidth != UINTMAX_MAX || get_errno() != ERANGE); width = (int)uwidth; - first_width_digit = false; break; } default: break; @@ -686,5 +692,3 @@ malloc_printf(const char *format, ...) { #undef not_implemented #undef assert_not_implemented #include "jemalloc/internal/assert.h" - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/mutex.cpp b/extension/jemalloc/jemalloc/src/mutex.c similarity index 97% rename from extension/jemalloc/jemalloc/src/mutex.cpp rename to extension/jemalloc/jemalloc/src/mutex.c index e3566af0766..5655100de72 100644 --- a/extension/jemalloc/jemalloc/src/mutex.cpp +++ b/extension/jemalloc/jemalloc/src/mutex.c @@ -5,9 +5,7 @@ #include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/spin.h" -namespace duckdb_jemalloc { - -#ifndef _CRT_SPINCOUNT +#if defined(_WIN32) && !defined(_CRT_SPINCOUNT) #define _CRT_SPINCOUNT 4000 #endif @@ -55,12 +53,11 @@ malloc_mutex_lock_slow(malloc_mutex_t *mutex) { mutex_prof_data_t *data = &mutex->prof_data; nstime_t before; - int cnt; if (ncpus == 1) { goto label_spin_done; } - cnt = 0; + int cnt = 0; do { spin_cpu_spinwait(); if (!atomic_load_b(&mutex->locked, ATOMIC_RELAXED) @@ -209,7 +206,7 @@ malloc_mutex_postfork_child(tsdn_t *tsdn, malloc_mutex_t *mutex) { malloc_printf(": Error re-initializing mutex in " "child\n"); if (opt_abort) { - jemalloc_abort(); + abort(); } } #endif @@ -229,5 +226,3 @@ malloc_mutex_boot(void) { #endif return false; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/nstime.cpp b/extension/jemalloc/jemalloc/src/nstime.c similarity index 98% rename from extension/jemalloc/jemalloc/src/nstime.cpp rename to extension/jemalloc/jemalloc/src/nstime.c index a470309a0b4..7fb9100eee1 100644 --- a/extension/jemalloc/jemalloc/src/nstime.cpp +++ b/extension/jemalloc/jemalloc/src/nstime.c @@ -5,8 +5,6 @@ #include "jemalloc/internal/assert.h" -namespace duckdb_jemalloc { - #define BILLION UINT64_C(1000000000) #define MILLION UINT64_C(1000000) @@ -230,7 +228,7 @@ nstime_monotonic_t *JET_MUTABLE nstime_monotonic = nstime_monotonic_impl; prof_time_res_t opt_prof_time_res = prof_time_res_default; -const char *prof_time_res_mode_names[] = { +const char *const prof_time_res_mode_names[] = { "default", "high", }; @@ -288,4 +286,4 @@ nstime_prof_init_update(nstime_t *time) { nstime_prof_update(time); } -} // namespace duckdb_jemalloc + diff --git a/extension/jemalloc/jemalloc/src/pa.cpp b/extension/jemalloc/jemalloc/src/pa.c similarity index 94% rename from extension/jemalloc/jemalloc/src/pa.cpp rename to extension/jemalloc/jemalloc/src/pa.c index b39c4afd405..7a24ae65be0 100644 --- a/extension/jemalloc/jemalloc/src/pa.cpp +++ b/extension/jemalloc/jemalloc/src/pa.c @@ -4,8 +4,6 @@ #include "jemalloc/internal/san.h" #include "jemalloc/internal/hpa.h" -namespace duckdb_jemalloc { - static void pa_nactive_add(pa_shard_t *shard, size_t add_pages) { atomic_fetch_add_zu(&shard->nactive, add_pages, ATOMIC_RELAXED); @@ -13,13 +11,13 @@ pa_nactive_add(pa_shard_t *shard, size_t add_pages) { static void pa_nactive_sub(pa_shard_t *shard, size_t sub_pages) { - assert(atomic_load_zu(&shard->nactive, ATOMIC_RELAXED) >= sub_pages); + assert(pa_shard_nactive(shard) >= sub_pages); atomic_fetch_sub_zu(&shard->nactive, sub_pages, ATOMIC_RELAXED); } bool pa_central_init(pa_central_t *central, base_t *base, bool hpa, - hpa_hooks_t *hpa_hooks) { + const hpa_hooks_t *hpa_hooks) { bool err; if (hpa) { err = hpa_central_init(¢ral->hpa, base, hpa_hooks); @@ -110,7 +108,7 @@ pa_shard_destroy(tsdn_t *tsdn, pa_shard_t *shard) { pac_destroy(tsdn, &shard->pac); if (shard->ever_used_hpa) { sec_flush(tsdn, &shard->hpa_sec); - hpa_shard_disable(tsdn, &shard->hpa_shard); + hpa_shard_destroy(tsdn, &shard->hpa_shard); } } @@ -222,13 +220,6 @@ pa_dalloc(tsdn_t *tsdn, pa_shard_t *shard, edata_t *edata, pai_dalloc(tsdn, pai, edata, deferred_work_generated); } -bool -pa_shard_retain_grow_limit_get_set(tsdn_t *tsdn, pa_shard_t *shard, - size_t *old_limit, size_t *new_limit) { - return pac_retain_grow_limit_get_set(tsdn, &shard->pac, old_limit, - new_limit); -} - bool pa_decay_ms_set(tsdn_t *tsdn, pa_shard_t *shard, extent_state_t state, ssize_t decay_ms, pac_purge_eagerness_t eagerness) { @@ -277,5 +268,3 @@ pa_shard_time_until_deferred_work(tsdn_t *tsdn, pa_shard_t *shard) { } return time; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/pa_extra.cpp b/extension/jemalloc/jemalloc/src/pa_extra.c similarity index 91% rename from extension/jemalloc/jemalloc/src/pa_extra.cpp rename to extension/jemalloc/jemalloc/src/pa_extra.c index 8932f60ad1e..7650703970c 100644 --- a/extension/jemalloc/jemalloc/src/pa_extra.cpp +++ b/extension/jemalloc/jemalloc/src/pa_extra.c @@ -1,8 +1,6 @@ #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" -namespace duckdb_jemalloc { - /* * This file is logically part of the PA module. While pa.c contains the core * allocator functionality, this file contains boring integration functionality; @@ -76,12 +74,31 @@ pa_shard_postfork_child(tsdn_t *tsdn, pa_shard_t *shard) { } } +size_t +pa_shard_nactive(pa_shard_t *shard) { + return atomic_load_zu(&shard->nactive, ATOMIC_RELAXED); +} + +size_t +pa_shard_ndirty(pa_shard_t *shard) { + size_t ndirty = ecache_npages_get(&shard->pac.ecache_dirty); + if (shard->ever_used_hpa) { + ndirty += psset_ndirty(&shard->hpa_shard.psset); + } + return ndirty; +} + +size_t +pa_shard_nmuzzy(pa_shard_t *shard) { + return ecache_npages_get(&shard->pac.ecache_muzzy); +} + void pa_shard_basic_stats_merge(pa_shard_t *shard, size_t *nactive, size_t *ndirty, size_t *nmuzzy) { - *nactive += atomic_load_zu(&shard->nactive, ATOMIC_RELAXED); - *ndirty += ecache_npages_get(&shard->pac.ecache_dirty); - *nmuzzy += ecache_npages_get(&shard->pac.ecache_muzzy); + *nactive += pa_shard_nactive(shard); + *ndirty += pa_shard_ndirty(shard); + *nmuzzy += pa_shard_nmuzzy(shard); } void @@ -97,8 +114,8 @@ pa_shard_stats_merge(tsdn_t *tsdn, pa_shard_t *shard, &shard->edata_cache.count, ATOMIC_RELAXED); size_t resident_pgs = 0; - resident_pgs += atomic_load_zu(&shard->nactive, ATOMIC_RELAXED); - resident_pgs += ecache_npages_get(&shard->pac.ecache_dirty); + resident_pgs += pa_shard_nactive(shard); + resident_pgs += pa_shard_ndirty(shard); *resident += (resident_pgs << LG_PAGE); /* Dirty decay stats */ @@ -191,5 +208,3 @@ pa_shard_mtx_stats_read(tsdn_t *tsdn, pa_shard_t *shard, &mutex_prof_data[arena_prof_mutex_hpa_sec]); } } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/pac.cpp b/extension/jemalloc/jemalloc/src/pac.c similarity index 99% rename from extension/jemalloc/jemalloc/src/pac.cpp rename to extension/jemalloc/jemalloc/src/pac.c index 0246bd61dfa..57a0c953d11 100644 --- a/extension/jemalloc/jemalloc/src/pac.cpp +++ b/extension/jemalloc/jemalloc/src/pac.c @@ -4,8 +4,6 @@ #include "jemalloc/internal/pac.h" #include "jemalloc/internal/san.h" -namespace duckdb_jemalloc { - static edata_t *pac_alloc_impl(tsdn_t *tsdn, pai_t *self, size_t size, size_t alignment, bool zero, bool guarded, bool frequent_reuse, bool *deferred_work_generated); @@ -31,6 +29,10 @@ pac_decay_data_get(pac_t *pac, extent_state_t state, *r_decay_stats = &pac->stats->decay_muzzy; *r_ecache = &pac->ecache_muzzy; return; + case extent_state_active: + case extent_state_retained: + case extent_state_transition: + case extent_state_merging: default: unreachable(); } @@ -387,8 +389,6 @@ pac_decay_stashed(tsdn_t *tsdn, pac_t *pac, decay_t *decay, npurged += npages; switch (ecache->state) { - case extent_state_active: - not_reached(); case extent_state_dirty: if (try_muzzy) { err = extent_purge_lazy_wrapper(tsdn, ehooks, @@ -404,7 +404,10 @@ pac_decay_stashed(tsdn_t *tsdn, pac_t *pac, decay_t *decay, extent_dalloc_wrapper(tsdn, pac, ehooks, edata); nunmapped += npages; break; + case extent_state_active: case extent_state_retained: + case extent_state_transition: + case extent_state_merging: default: not_reached(); } @@ -587,5 +590,3 @@ pac_destroy(tsdn_t *tsdn, pac_t *pac) { extent_destroy_wrapper(tsdn, pac, ehooks, edata); } } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/pages.cpp b/extension/jemalloc/jemalloc/src/pages.c similarity index 94% rename from extension/jemalloc/jemalloc/src/pages.cpp rename to extension/jemalloc/jemalloc/src/pages.c index e80c00f11f0..8cf2fd9f876 100644 --- a/extension/jemalloc/jemalloc/src/pages.cpp +++ b/extension/jemalloc/jemalloc/src/pages.c @@ -7,8 +7,6 @@ #include "jemalloc/internal/assert.h" #include "jemalloc/internal/malloc_io.h" -namespace duckdb_jemalloc { - #ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT #include #ifdef __FreeBSD__ @@ -23,12 +21,19 @@ namespace duckdb_jemalloc { #else #define PAGES_FD_TAG -1 #endif +#if defined(JEMALLOC_HAVE_PRCTL) && defined(JEMALLOC_PAGEID) +#include +#ifndef PR_SET_VMA +#define PR_SET_VMA 0x53564d41 +#define PR_SET_VMA_ANON_NAME 0 +#endif +#endif /******************************************************************************/ /* Data. */ /* Actual operating system page size, detected during bootstrap, <= PAGE. */ -static size_t os_page; +size_t os_page; #ifndef _WIN32 # define PAGES_PROT_COMMIT (PROT_READ | PROT_WRITE) @@ -37,7 +42,7 @@ static int mmap_flags; #endif static bool os_overcommits; -const char *thp_mode_names[] = { +const char *const thp_mode_names[] = { "default", "always", "never", @@ -61,9 +66,8 @@ static int madvise_dont_need_zeros_is_faulty = -1; * * [1]: https://patchwork.kernel.org/patch/10576637/ */ -static int madvise_MADV_DONTNEED_zeroes_pages() +static int madvise_MADV_DONTNEED_zeroes_pages(void) { - int works = -1; size_t size = PAGE; void * addr = mmap(NULL, size, PROT_READ|PROT_WRITE, @@ -73,11 +77,12 @@ static int madvise_MADV_DONTNEED_zeroes_pages() malloc_write(": Cannot allocate memory for " "MADV_DONTNEED check\n"); if (opt_abort) { - jemalloc_abort(); + abort(); } } memset(addr, 'A', size); + int works; if (madvise(addr, size, MADV_DONTNEED) == 0) { works = memchr(addr, 'A', size) == NULL; } else { @@ -92,7 +97,7 @@ static int madvise_MADV_DONTNEED_zeroes_pages() malloc_write(": Cannot deallocate memory for " "MADV_DONTNEED check\n"); if (opt_abort) { - jemalloc_abort(); + abort(); } } @@ -100,6 +105,22 @@ static int madvise_MADV_DONTNEED_zeroes_pages() } #endif +#ifdef JEMALLOC_PAGEID +static int os_page_id(void *addr, size_t size, const char *name) +{ +#ifdef JEMALLOC_HAVE_PRCTL + /* + * While parsing `/proc//maps` file, the block could appear as + * 7f4836000000-7f4836800000 rw-p 00000000 00:00 0 [anon:jemalloc_pg_overcommit]` + */ + return prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (uintptr_t)addr, size, + (uintptr_t)name); +#else + return 0; +#endif +} +#endif + /******************************************************************************/ /* * Function prototypes for static functions that are referenced prior to @@ -134,6 +155,7 @@ os_pages_map(void *addr, size_t size, size_t alignment, bool *commit) { * of existing mappings, and we only want to create new mappings. */ { + int flags = mmap_flags; #ifdef __NetBSD__ /* * On NetBSD PAGE for a platform is defined to the @@ -143,12 +165,12 @@ os_pages_map(void *addr, size_t size, size_t alignment, bool *commit) { */ if (alignment > os_page || PAGE > os_page) { unsigned int a = ilog2(MAX(alignment, PAGE)); - mmap_flags |= MAP_ALIGNED(a); + flags |= MAP_ALIGNED(a); } #endif int prot = *commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT; - ret = mmap(addr, size, prot, mmap_flags, PAGES_FD_TAG, 0); + ret = mmap(addr, size, prot, flags, PAGES_FD_TAG, 0); } assert(ret != NULL); @@ -164,13 +186,18 @@ os_pages_map(void *addr, size_t size, size_t alignment, bool *commit) { #endif assert(ret == NULL || (addr == NULL && ret != addr) || (addr != NULL && ret == addr)); +#ifdef JEMALLOC_PAGEID + int n = os_page_id(ret, size, + os_overcommits ? "jemalloc_pg_overcommit" : "jemalloc_pg"); + assert(n == 0 || (n == -1 && get_errno() == EINVAL)); +#endif return ret; } static void * os_pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size, bool *commit) { - void *ret = (void *)((uintptr_t)addr + leadsize); + void *ret = (void *)((byte_t *)addr + leadsize); assert(alloc_size >= leadsize + size); #ifdef _WIN32 @@ -190,7 +217,7 @@ os_pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size, os_pages_unmap(addr, leadsize); } if (trailsize != 0) { - os_pages_unmap((void *)((uintptr_t)ret + size), trailsize); + os_pages_unmap((void *)((byte_t *)ret + size), trailsize); } return ret; #endif @@ -218,7 +245,7 @@ os_pages_unmap(void *addr, size_t size) { #endif "(): %s\n", buf); if (opt_abort) { - jemalloc_abort(); + abort(); } } } @@ -704,7 +731,7 @@ init_thp_state(void) { if (!have_madvise_huge && !have_memcntl) { if (metadata_thp_enabled() && opt_abort) { malloc_write(": no MADV_HUGEPAGE support\n"); - jemalloc_abort(); + abort(); } goto label_error; } @@ -762,7 +789,7 @@ pages_boot(void) { if (os_page > PAGE) { malloc_write(": Unsupported system page size\n"); if (opt_abort) { - jemalloc_abort(); + abort(); } return true; } @@ -824,5 +851,3 @@ pages_boot(void) { return false; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/pai.cpp b/extension/jemalloc/jemalloc/src/pai.c similarity index 79% rename from extension/jemalloc/jemalloc/src/pai.cpp rename to extension/jemalloc/jemalloc/src/pai.c index c762f4d7ba1..e8cddfc3b51 100644 --- a/extension/jemalloc/jemalloc/src/pai.cpp +++ b/extension/jemalloc/jemalloc/src/pai.c @@ -1,16 +1,15 @@ #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" -namespace duckdb_jemalloc { - size_t pai_alloc_batch_default(tsdn_t *tsdn, pai_t *self, size_t size, size_t nallocs, - edata_list_active_t *results, bool *deferred_work_generated) { + edata_list_active_t *results, bool frequent_reuse, + bool *deferred_work_generated) { for (size_t i = 0; i < nallocs; i++) { bool deferred_by_alloc = false; edata_t *edata = pai_alloc(tsdn, self, size, PAGE, - /* zero */ false, /* guarded */ false, - /* frequent_reuse */ false, &deferred_by_alloc); + /* zero */ false, /* guarded */ false, frequent_reuse, + &deferred_by_alloc); *deferred_work_generated |= deferred_by_alloc; if (edata == NULL) { return i; @@ -31,5 +30,3 @@ pai_dalloc_batch_default(tsdn_t *tsdn, pai_t *self, *deferred_work_generated |= deferred_by_dalloc; } } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/peak_event.cpp b/extension/jemalloc/jemalloc/src/peak_event.c similarity index 97% rename from extension/jemalloc/jemalloc/src/peak_event.cpp rename to extension/jemalloc/jemalloc/src/peak_event.c index 8d7cbc8cf20..4093fbcc691 100644 --- a/extension/jemalloc/jemalloc/src/peak_event.cpp +++ b/extension/jemalloc/jemalloc/src/peak_event.c @@ -6,8 +6,6 @@ #include "jemalloc/internal/activity_callback.h" #include "jemalloc/internal/peak.h" -namespace duckdb_jemalloc { - /* * Update every 64K by default. We're not exposing this as a configuration * option for now; we don't want to bind ourselves too tightly to any particular @@ -82,5 +80,3 @@ peak_dalloc_event_handler(tsd_t *tsd, uint64_t elapsed) { peak_event_update(tsd); peak_event_activity_callback(tsd); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/prof.cpp b/extension/jemalloc/jemalloc/src/prof.c similarity index 89% rename from extension/jemalloc/jemalloc/src/prof.cpp rename to extension/jemalloc/jemalloc/src/prof.c index 52307f85486..6ae7f76885a 100644 --- a/extension/jemalloc/jemalloc/src/prof.cpp +++ b/extension/jemalloc/jemalloc/src/prof.c @@ -13,8 +13,6 @@ #include "jemalloc/internal/prof_hook.h" #include "jemalloc/internal/thread_event.h" -namespace duckdb_jemalloc { - /* * This file implements the profiling "APIs" needed by other parts of jemalloc, * and also manages the relevant "operational" data, mainly options and mutexes; @@ -28,6 +26,7 @@ namespace duckdb_jemalloc { bool opt_prof = false; bool opt_prof_active = true; bool opt_prof_thread_active_init = true; +unsigned opt_prof_bt_max = PROF_BT_MAX_DEFAULT; size_t opt_lg_prof_sample = LG_PROF_SAMPLE_DEFAULT; ssize_t opt_lg_prof_interval = LG_PROF_INTERVAL_DEFAULT; bool opt_prof_gdump = false; @@ -35,6 +34,7 @@ bool opt_prof_final = false; bool opt_prof_leak = false; bool opt_prof_leak_error = false; bool opt_prof_accum = false; +bool opt_prof_pid_namespace = false; char opt_prof_prefix[PROF_DUMP_FILENAME_LEN]; bool opt_prof_sys_thread_name = false; bool opt_prof_unbias = true; @@ -74,10 +74,16 @@ static malloc_mutex_t next_thr_uid_mtx; bool prof_booted = false; /* Logically a prof_backtrace_hook_t. */ -atomic_p_t prof_backtrace_hook; +static atomic_p_t prof_backtrace_hook; /* Logically a prof_dump_hook_t. */ -atomic_p_t prof_dump_hook; +static atomic_p_t prof_dump_hook; + +/* Logically a prof_sample_hook_t. */ +static atomic_p_t prof_sample_hook; + +/* Logically a prof_sample_free_hook_t. */ +static atomic_p_t prof_sample_free_hook; /******************************************************************************/ @@ -86,11 +92,19 @@ prof_alloc_rollback(tsd_t *tsd, prof_tctx_t *tctx) { cassert(config_prof); if (tsd_reentrancy_level_get(tsd) > 0) { - assert((uintptr_t)tctx == (uintptr_t)1U); + assert(tctx == PROF_TCTX_SENTINEL); return; } - if ((uintptr_t)tctx > (uintptr_t)1U) { + if (prof_tctx_is_valid(tctx)) { + /* + * This `assert` really shouldn't be necessary. It's here + * because there's a bug in the clang static analyzer; it + * somehow does not realize that by `prof_tctx_is_valid(tctx)` + * being true that we've already ensured that `tctx` is not + * `NULL`. + */ + assert(tctx != NULL); malloc_mutex_lock(tsd_tsdn(tsd), tctx->tdata->lock); tctx->prepared = false; prof_tctx_try_destroy(tsd, tctx); @@ -146,17 +160,37 @@ prof_malloc_sample_object(tsd_t *tsd, const void *ptr, size_t size, if (opt_prof_stats) { prof_stats_inc(tsd, szind, size); } + + /* Sample hook. */ + prof_sample_hook_t prof_sample_hook = prof_sample_hook_get(); + if (prof_sample_hook != NULL) { + prof_bt_t *bt = &tctx->gctx->bt; + pre_reentrancy(tsd, NULL); + prof_sample_hook(ptr, size, bt->vec, bt->len); + post_reentrancy(tsd); + } } void -prof_free_sampled_object(tsd_t *tsd, size_t usize, prof_info_t *prof_info) { +prof_free_sampled_object(tsd_t *tsd, const void *ptr, size_t usize, + prof_info_t *prof_info) { cassert(config_prof); assert(prof_info != NULL); prof_tctx_t *tctx = prof_info->alloc_tctx; - assert((uintptr_t)tctx > (uintptr_t)1U); + assert(prof_tctx_is_valid(tctx)); szind_t szind = sz_size2index(usize); + + /* Unsample hook. */ + prof_sample_free_hook_t prof_sample_free_hook = + prof_sample_free_hook_get(); + if (prof_sample_free_hook != NULL) { + pre_reentrancy(tsd, NULL); + prof_sample_free_hook(ptr, usize); + post_reentrancy(tsd); + } + malloc_mutex_lock(tsd_tsdn(tsd), tctx->tdata->lock); assert(tctx->cnts.curobjs > 0); @@ -244,7 +278,8 @@ prof_sample_new_event_wait(tsd_t *tsd) { * otherwise bytes_until_sample would be 0 if u is exactly 1.0. */ uint64_t r = prng_lg_range_u64(tsd_prng_statep_get(tsd), 53); - double u = (r == 0U) ? 1.0 : (double)r * (1.0/9007199254740992.0L); + double u = (r == 0U) ? 1.0 : (double)((long double)r * + (1.0L/9007199254740992.0L)); return (uint64_t)(log(u) / log(1.0 - (1.0 / (double)((uint64_t)1U << lg_prof_sample)))) + (uint64_t)1U; @@ -390,11 +425,14 @@ prof_tdata_t * prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata) { uint64_t thr_uid = tdata->thr_uid; uint64_t thr_discrim = tdata->thr_discrim + 1; - char *thread_name = (tdata->thread_name != NULL) ? - prof_thread_name_alloc(tsd, tdata->thread_name) : NULL; bool active = tdata->active; + /* Keep a local copy of the thread name, before detaching. */ + prof_thread_name_assert(tdata); + char thread_name[PROF_THREAD_NAME_MAX_LEN]; + strncpy(thread_name, tdata->thread_name, PROF_THREAD_NAME_MAX_LEN); prof_tdata_detach(tsd, tdata); + return prof_tdata_init_impl(tsd, thr_uid, thr_discrim, thread_name, active); } @@ -439,15 +477,15 @@ prof_active_set(tsdn_t *tsdn, bool active) { const char * prof_thread_name_get(tsd_t *tsd) { - assert(tsd_reentrancy_level_get(tsd) == 0); + static const char *prof_thread_name_dummy = ""; - prof_tdata_t *tdata; - - tdata = prof_tdata_get(tsd, true); + assert(tsd_reentrancy_level_get(tsd) == 0); + prof_tdata_t *tdata = prof_tdata_get(tsd, true); if (tdata == NULL) { - return ""; + return prof_thread_name_dummy; } - return (tdata->thread_name != NULL ? tdata->thread_name : ""); + + return tdata->thread_name; } int @@ -530,26 +568,48 @@ prof_gdump_set(tsdn_t *tsdn, bool gdump) { void prof_backtrace_hook_set(prof_backtrace_hook_t hook) { - atomic_store_p(&prof_backtrace_hook, &hook, ATOMIC_RELEASE); + atomic_store_p(&prof_backtrace_hook, hook, ATOMIC_RELEASE); } prof_backtrace_hook_t -prof_backtrace_hook_get() { +prof_backtrace_hook_get(void) { return (prof_backtrace_hook_t)atomic_load_p(&prof_backtrace_hook, ATOMIC_ACQUIRE); } void prof_dump_hook_set(prof_dump_hook_t hook) { - atomic_store_p(&prof_dump_hook, &hook, ATOMIC_RELEASE); + atomic_store_p(&prof_dump_hook, hook, ATOMIC_RELEASE); } prof_dump_hook_t -prof_dump_hook_get() { +prof_dump_hook_get(void) { return (prof_dump_hook_t)atomic_load_p(&prof_dump_hook, ATOMIC_ACQUIRE); } +void +prof_sample_hook_set(prof_sample_hook_t hook) { + atomic_store_p(&prof_sample_hook, hook, ATOMIC_RELEASE); +} + +prof_sample_hook_t +prof_sample_hook_get(void) { + return (prof_sample_hook_t)atomic_load_p(&prof_sample_hook, + ATOMIC_ACQUIRE); +} + +void +prof_sample_free_hook_set(prof_sample_free_hook_t hook) { + atomic_store_p(&prof_sample_free_hook, hook, ATOMIC_RELEASE); +} + +prof_sample_free_hook_t +prof_sample_free_hook_get(void) { + return (prof_sample_free_hook_t)atomic_load_p(&prof_sample_free_hook, + ATOMIC_ACQUIRE); +} + void prof_boot0(void) { cassert(config_prof); @@ -652,7 +712,7 @@ prof_boot2(tsd_t *tsd, base_t *base) { atexit(prof_fdump) != 0) { malloc_write(": Error in atexit()\n"); if (opt_abort) { - jemalloc_abort(); + abort(); } } @@ -789,5 +849,3 @@ prof_postfork_child(tsdn_t *tsdn) { } /******************************************************************************/ - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/prof_data.cpp b/extension/jemalloc/jemalloc/src/prof_data.c similarity index 95% rename from extension/jemalloc/jemalloc/src/prof_data.cpp rename to extension/jemalloc/jemalloc/src/prof_data.c index ea1b38faf9c..39af0c90a5b 100644 --- a/extension/jemalloc/jemalloc/src/prof_data.cpp +++ b/extension/jemalloc/jemalloc/src/prof_data.c @@ -7,8 +7,6 @@ #include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/prof_data.h" -namespace duckdb_jemalloc { - /* * This file defines and manages the core profiling data structures. * @@ -87,8 +85,10 @@ prof_tctx_comp(const prof_tctx_t *a, const prof_tctx_t *b) { return ret; } +/* NOLINTBEGIN(performance-no-int-to-ptr) */ rb_gen(static UNUSED, tctx_tree_, prof_tctx_tree_t, prof_tctx_t, tctx_link, prof_tctx_comp) +/* NOLINTEND(performance-no-int-to-ptr) */ static int prof_gctx_comp(const prof_gctx_t *a, const prof_gctx_t *b) { @@ -102,8 +102,10 @@ prof_gctx_comp(const prof_gctx_t *a, const prof_gctx_t *b) { return ret; } +/* NOLINTBEGIN(performance-no-int-to-ptr) */ rb_gen(static UNUSED, gctx_tree_, prof_gctx_tree_t, prof_gctx_t, dump_link, prof_gctx_comp) +/* NOLINTEND(performance-no-int-to-ptr) */ static int prof_tdata_comp(const prof_tdata_t *a, const prof_tdata_t *b) { @@ -121,8 +123,10 @@ prof_tdata_comp(const prof_tdata_t *a, const prof_tdata_t *b) { return ret; } +/* NOLINTBEGIN(performance-no-int-to-ptr) */ rb_gen(static UNUSED, tdata_tree_, prof_tdata_tree_t, prof_tdata_t, tdata_link, prof_tdata_comp) +/* NOLINTEND(performance-no-int-to-ptr) */ /******************************************************************************/ @@ -443,66 +447,31 @@ prof_bt_count(void) { return bt_count; } -char * -prof_thread_name_alloc(tsd_t *tsd, const char *thread_name) { - char *ret; - size_t size; - - if (thread_name == NULL) { - return NULL; - } - - size = strlen(thread_name) + 1; - if (size == 1) { - return strdup(""); - } - - ret = (char *)iallocztm(tsd_tsdn(tsd), size, sz_size2index(size), false, NULL, - true, arena_get(TSDN_NULL, 0, true), true); - if (ret == NULL) { - return NULL; - } - memcpy(ret, thread_name, size); - return ret; +static void +prof_thread_name_write_tdata(prof_tdata_t *tdata, const char *thread_name) { + strncpy(tdata->thread_name, thread_name, PROF_THREAD_NAME_MAX_LEN); + tdata->thread_name[PROF_THREAD_NAME_MAX_LEN - 1] = '\0'; } int prof_thread_name_set_impl(tsd_t *tsd, const char *thread_name) { assert(tsd_reentrancy_level_get(tsd) == 0); + assert(thread_name != NULL); - prof_tdata_t *tdata; - unsigned i; - char *s; - - tdata = prof_tdata_get(tsd, true); - if (tdata == NULL) { - return EAGAIN; - } - - /* Validate input. */ - if (thread_name == NULL) { - return EFAULT; - } - for (i = 0; thread_name[i] != '\0'; i++) { + for (unsigned i = 0; thread_name[i] != '\0'; i++) { char c = thread_name[i]; if (!isgraph(c) && !isblank(c)) { - return EFAULT; + return EINVAL; } } - s = prof_thread_name_alloc(tsd, thread_name); - if (s == NULL) { - return EAGAIN; + prof_tdata_t *tdata = prof_tdata_get(tsd, true); + if (tdata == NULL) { + return ENOMEM; } - if (tdata->thread_name != NULL) { - idalloctm(tsd_tsdn(tsd), tdata->thread_name, NULL, NULL, true, - true); - tdata->thread_name = NULL; - } - if (strlen(s) > 0) { - tdata->thread_name = s; - } + prof_thread_name_write_tdata(tdata, thread_name); + return 0; } @@ -540,7 +509,7 @@ prof_double_uint64_cast(double d) { } #endif -void prof_unbias_map_init() { +void prof_unbias_map_init(void) { /* See the comment in prof_sample_new_event_wait */ #ifdef JEMALLOC_PROF for (szind_t i = 0; i < SC_NSIZES; i++) { @@ -664,7 +633,7 @@ prof_dump_print_cnts(write_cb_t *prof_dump_write, void *cbopaque, accumbytes = cnts->accumbytes; } prof_dump_printf(prof_dump_write, cbopaque, - "%" FMTu64": %" FMTu64" [%" FMTu64": %" FMTu64"]", + "%"FMTu64": %"FMTu64" [%"FMTu64": %"FMTu64"]", curobjs, curbytes, accumobjs, accumbytes); } @@ -740,6 +709,7 @@ prof_tctx_merge_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg) { case prof_tctx_state_purgatory: prof_tctx_merge_gctx(tsdn, tctx, tctx->gctx); break; + case prof_tctx_state_initializing: default: not_reached(); } @@ -767,7 +737,7 @@ prof_tctx_dump_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *opaque) { case prof_tctx_state_dumping: case prof_tctx_state_purgatory: prof_dump_printf(arg->prof_dump_write, arg->cbopaque, - " t%" FMTu64": ", tctx->thr_uid); + " t%"FMTu64": ", tctx->thr_uid); prof_dump_print_cnts(arg->prof_dump_write, arg->cbopaque, &tctx->dump_cnts); arg->prof_dump_write(arg->cbopaque, "\n"); @@ -795,6 +765,7 @@ prof_tctx_finish_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg) { case prof_tctx_state_purgatory: ret = tctx; goto label_return; + case prof_tctx_state_initializing: default: not_reached(); } @@ -948,11 +919,11 @@ prof_tdata_dump_iter(prof_tdata_tree_t *tdatas_ptr, prof_tdata_t *tdata, } prof_dump_iter_arg_t *arg = (prof_dump_iter_arg_t *)opaque; - prof_dump_printf(arg->prof_dump_write, arg->cbopaque, " t%" FMTu64": ", + prof_dump_printf(arg->prof_dump_write, arg->cbopaque, " t%"FMTu64": ", tdata->thr_uid); prof_dump_print_cnts(arg->prof_dump_write, arg->cbopaque, &tdata->cnt_summed); - if (tdata->thread_name != NULL) { + if (!prof_thread_name_empty(tdata)) { arg->prof_dump_write(arg->cbopaque, " "); arg->prof_dump_write(arg->cbopaque, tdata->thread_name); } @@ -963,7 +934,7 @@ prof_tdata_dump_iter(prof_tdata_tree_t *tdatas_ptr, prof_tdata_t *tdata, static void prof_dump_header(prof_dump_iter_arg_t *arg, const prof_cnt_t *cnt_all) { prof_dump_printf(arg->prof_dump_write, arg->cbopaque, - "heap_v2/%" FMTu64"\n t*: ", ((uint64_t)1U << lg_prof_sample)); + "heap_v2/%"FMTu64"\n t*: ", ((uint64_t)1U << lg_prof_sample)); prof_dump_print_cnts(arg->prof_dump_write, arg->cbopaque, cnt_all); arg->prof_dump_write(arg->cbopaque, "\n"); @@ -999,7 +970,7 @@ prof_dump_gctx(prof_dump_iter_arg_t *arg, prof_gctx_t *gctx, arg->prof_dump_write(arg->cbopaque, "@"); for (unsigned i = 0; i < bt->len; i++) { prof_dump_printf(arg->prof_dump_write, arg->cbopaque, - " %#" FMTxPTR, (uintptr_t)bt->vec[i]); + " %#"FMTxPTR, (uintptr_t)bt->vec[i]); } arg->prof_dump_write(arg->cbopaque, "\n t*: "); @@ -1033,8 +1004,8 @@ prof_leakcheck(const prof_cnt_t *cnt_all, size_t leak_ngctx) { uint64_t curobjs = (uint64_t)round(((double)cnt_all->curobjs) * scale_factor); - malloc_printf(": Leak approximation summary: ~%" FMTu64 - " byte%s, ~%" FMTu64 " object%s, >= %zu context%s\n", + malloc_printf(": Leak approximation summary: ~%"FMTu64 + " byte%s, ~%"FMTu64" object%s, >= %zu context%s\n", curbytes, (curbytes != 1) ? "s" : "", curobjs, (curobjs != 1) ? "s" : "", leak_ngctx, (leak_ngctx != 1) ? "s" : ""); malloc_printf( @@ -1169,20 +1140,28 @@ prof_tdata_init_impl(tsd_t *tsd, uint64_t thr_uid, uint64_t thr_discrim, cassert(config_prof); /* Initialize an empty cache for this thread. */ - tdata = (prof_tdata_t *)iallocztm(tsd_tsdn(tsd), sizeof(prof_tdata_t), - sz_size2index(sizeof(prof_tdata_t)), false, NULL, true, + size_t tdata_sz = ALIGNMENT_CEILING(sizeof(prof_tdata_t), QUANTUM); + size_t total_sz = tdata_sz + sizeof(void *) * opt_prof_bt_max; + tdata = (prof_tdata_t *)iallocztm(tsd_tsdn(tsd), + total_sz, sz_size2index(total_sz), false, NULL, true, arena_get(TSDN_NULL, 0, true), true); if (tdata == NULL) { return NULL; } + tdata->vec = (void **)((byte_t *)tdata + tdata_sz); tdata->lock = prof_tdata_mutex_choose(thr_uid); tdata->thr_uid = thr_uid; tdata->thr_discrim = thr_discrim; - tdata->thread_name = thread_name; tdata->attached = true; tdata->expired = false; tdata->tctx_uid_next = 0; + if (thread_name == NULL) { + prof_thread_name_clear(tdata); + } else { + prof_thread_name_write_tdata(tdata, thread_name); + } + prof_thread_name_assert(tdata); if (ckh_new(tsd, &tdata->bt2tctx, PROF_CKH_MINITEMS, prof_bt_hash, prof_bt_keycomp)) { @@ -1230,13 +1209,8 @@ prof_tdata_destroy_locked(tsd_t *tsd, prof_tdata_t *tdata, malloc_mutex_assert_not_owner(tsd_tsdn(tsd), tdata->lock); tdata_tree_remove(&tdatas, tdata); - assert(prof_tdata_should_destroy_unlocked(tdata, even_if_attached)); - if (tdata->thread_name != NULL) { - idalloctm(tsd_tsdn(tsd), tdata->thread_name, NULL, NULL, true, - true); - } ckh_delete(tsd, &tdata->bt2tctx); idalloctm(tsd_tsdn(tsd), tdata, NULL, NULL, true, true); } @@ -1421,6 +1395,8 @@ prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx) { destroy_tctx = false; destroy_gctx = false; break; + case prof_tctx_state_initializing: + case prof_tctx_state_purgatory: default: not_reached(); destroy_tctx = false; @@ -1447,5 +1423,3 @@ prof_tctx_try_destroy(tsd_t *tsd, prof_tctx_t *tctx) { } /******************************************************************************/ - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/prof_log.cpp b/extension/jemalloc/jemalloc/src/prof_log.c similarity index 96% rename from extension/jemalloc/jemalloc/src/prof_log.cpp rename to extension/jemalloc/jemalloc/src/prof_log.c index 5bcb9d72519..f4000aecf41 100644 --- a/extension/jemalloc/jemalloc/src/prof_log.cpp +++ b/extension/jemalloc/jemalloc/src/prof_log.c @@ -12,22 +12,20 @@ #include "jemalloc/internal/prof_log.h" #include "jemalloc/internal/prof_sys.h" -namespace duckdb_jemalloc { - bool opt_prof_log = false; +typedef enum prof_logging_state_e prof_logging_state_t; enum prof_logging_state_e { prof_logging_state_stopped, prof_logging_state_started, prof_logging_state_dumping }; -typedef enum prof_logging_state_e prof_logging_state_t; /* * - stopped: log_start never called, or previous log_stop has completed. * - started: log_start called, log_stop not called yet. Allocations are logged. * - dumping: log_stop called but not finished; samples are not logged anymore. */ -prof_logging_state_t prof_logging_state = prof_logging_state_stopped; +static prof_logging_state_t prof_logging_state = prof_logging_state_stopped; /* Used in unit tests. */ static bool prof_log_dummy = false; @@ -221,18 +219,6 @@ prof_try_log(tsd_t *tsd, size_t usize, prof_info_t *prof_info) { malloc_mutex_lock(tsd_tsdn(tsd), &log_mtx); - nstime_t alloc_time; - nstime_t free_time; - - size_t sz; - prof_alloc_node_t *new_node; - - const char *prod_thr_name; - const char *cons_thr_name; - - prof_bt_t *cons_bt; - prof_bt_t *prod_bt; - if (prof_logging_state != prof_logging_state_started) { goto label_done; } @@ -248,26 +234,26 @@ prof_try_log(tsd_t *tsd, size_t usize, prof_info_t *prof_info) { log_tables_initialized = true; } - alloc_time = prof_info->alloc_time; + nstime_t alloc_time = prof_info->alloc_time; + nstime_t free_time; nstime_prof_init_update(&free_time); - sz = sizeof(prof_alloc_node_t); - new_node = (prof_alloc_node_t *) + size_t sz = sizeof(prof_alloc_node_t); + prof_alloc_node_t *new_node = (prof_alloc_node_t *) iallocztm(tsd_tsdn(tsd), sz, sz_size2index(sz), false, NULL, true, arena_get(TSDN_NULL, 0, true), true); - prod_thr_name = (tctx->tdata->thread_name == NULL)? - "" : tctx->tdata->thread_name; - cons_thr_name = prof_thread_name_get(tsd); + const char *prod_thr_name = tctx->tdata->thread_name; + const char *cons_thr_name = prof_thread_name_get(tsd); prof_bt_t bt; /* Initialize the backtrace, using the buffer in tdata to store it. */ bt_init(&bt, cons_tdata->vec); prof_backtrace(tsd, &bt); - cons_bt = &bt; + prof_bt_t *cons_bt = &bt; /* We haven't destroyed tctx yet, so gctx should be good to read. */ - prod_bt = &tctx->gctx->bt; + prof_bt_t *prod_bt = &tctx->gctx->bt; new_node->next = NULL; new_node->alloc_thr_ind = prof_log_thr_index(tsd, tctx->tdata->thr_uid, @@ -452,7 +438,7 @@ prof_log_start(tsdn_t *tsdn, const char *filename) { malloc_write(": Error in atexit() " "for logging\n"); if (opt_abort) { - jemalloc_abort(); + abort(); } ret = true; goto label_done; @@ -604,7 +590,7 @@ prof_log_emit_metadata(emitter_t *emitter) { uint64_t ns = nstime_ns(&now) - nstime_ns(&log_start_timestamp); emitter_json_kv(emitter, "duration", emitter_type_uint64, &ns); - const char *vers = JEMALLOC_VERSION; + char *vers = JEMALLOC_VERSION; emitter_json_kv(emitter, "version", emitter_type_string, &vers); @@ -662,7 +648,7 @@ prof_log_stop(tsdn_t *tsdn) { malloc_printf(": creat() for log file \"%s\" " " failed with %d\n", log_filename, errno); if (opt_abort) { - jemalloc_abort(); + abort(); } return true; } @@ -728,5 +714,3 @@ prof_log_init(tsd_t *tsd) { } /******************************************************************************/ - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/prof_recent.cpp b/extension/jemalloc/jemalloc/src/prof_recent.c similarity index 97% rename from extension/jemalloc/jemalloc/src/prof_recent.cpp rename to extension/jemalloc/jemalloc/src/prof_recent.c index 68e0fabaa35..b5639b4cb90 100644 --- a/extension/jemalloc/jemalloc/src/prof_recent.cpp +++ b/extension/jemalloc/jemalloc/src/prof_recent.c @@ -7,8 +7,6 @@ #include "jemalloc/internal/prof_data.h" #include "jemalloc/internal/prof_recent.h" -namespace duckdb_jemalloc { - ssize_t opt_prof_recent_alloc_max = PROF_RECENT_ALLOC_MAX_DEFAULT; malloc_mutex_t prof_recent_alloc_mtx; /* Protects the fields below */ static atomic_zd_t prof_recent_alloc_max; @@ -18,13 +16,13 @@ prof_recent_list_t prof_recent_alloc_list; malloc_mutex_t prof_recent_dump_mtx; /* Protects dumping. */ static void -prof_recent_alloc_max_init() { +prof_recent_alloc_max_init(void) { atomic_store_zd(&prof_recent_alloc_max, opt_prof_recent_alloc_max, ATOMIC_RELAXED); } static inline ssize_t -prof_recent_alloc_max_get_no_lock() { +prof_recent_alloc_max_get_no_lock(void) { return atomic_load_zd(&prof_recent_alloc_max, ATOMIC_RELAXED); } @@ -330,8 +328,6 @@ prof_recent_alloc(tsd_t *tsd, edata_t *edata, size_t size, size_t usize) { prof_recent_alloc_assert_count(tsd); } - prof_recent_t *tail; - if (prof_recent_alloc_max_get(tsd) == 0) { assert(prof_recent_alloc_is_empty(tsd)); goto label_rollback; @@ -364,7 +360,7 @@ prof_recent_alloc(tsd_t *tsd, edata_t *edata, size_t size, size_t usize) { } /* Fill content into the tail node. */ - tail = ql_last(&prof_recent_alloc_list, link); + prof_recent_t *tail = ql_last(&prof_recent_alloc_list, link); assert(tail != NULL); tail->size = size; tail->usize = usize; @@ -407,7 +403,7 @@ prof_recent_alloc(tsd_t *tsd, edata_t *edata, size_t size, size_t usize) { } ssize_t -prof_recent_alloc_max_ctl_read() { +prof_recent_alloc_max_ctl_read(void) { cassert(config_prof); /* Don't bother to acquire the lock. */ return prof_recent_alloc_max_get_no_lock(); @@ -499,9 +495,10 @@ prof_recent_alloc_dump_node(emitter_t *emitter, prof_recent_t *node) { &node->alloc_tctx->thr_uid); prof_tdata_t *alloc_tdata = node->alloc_tctx->tdata; assert(alloc_tdata != NULL); - if (alloc_tdata->thread_name != NULL) { + if (!prof_thread_name_empty(alloc_tdata)) { + const char *thread_name = alloc_tdata->thread_name; emitter_json_kv(emitter, "alloc_thread_name", - emitter_type_string, &alloc_tdata->thread_name); + emitter_type_string, &thread_name); } uint64_t alloc_time_ns = nstime_ns(&node->alloc_time); emitter_json_kv(emitter, "alloc_time", emitter_type_uint64, @@ -515,9 +512,10 @@ prof_recent_alloc_dump_node(emitter_t *emitter, prof_recent_t *node) { emitter_type_uint64, &node->dalloc_tctx->thr_uid); prof_tdata_t *dalloc_tdata = node->dalloc_tctx->tdata; assert(dalloc_tdata != NULL); - if (dalloc_tdata->thread_name != NULL) { + if (!prof_thread_name_empty(dalloc_tdata)) { + const char *thread_name = dalloc_tdata->thread_name; emitter_json_kv(emitter, "dalloc_thread_name", - emitter_type_string, &dalloc_tdata->thread_name); + emitter_type_string, &thread_name); } assert(!nstime_equals_zero(&node->dalloc_time)); uint64_t dalloc_time_ns = nstime_ns(&node->dalloc_time); @@ -584,7 +582,7 @@ prof_recent_alloc_dump(tsd_t *tsd, write_cb_t *write_cb, void *cbopaque) { #undef PROF_RECENT_PRINT_BUFSIZE bool -prof_recent_init() { +prof_recent_init(void) { cassert(config_prof); prof_recent_alloc_max_init(); @@ -602,5 +600,3 @@ prof_recent_init() { return false; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/prof_stats.cpp b/extension/jemalloc/jemalloc/src/prof_stats.c similarity index 96% rename from extension/jemalloc/jemalloc/src/prof_stats.cpp rename to extension/jemalloc/jemalloc/src/prof_stats.c index 166b65ae39d..5d1a506bb72 100644 --- a/extension/jemalloc/jemalloc/src/prof_stats.cpp +++ b/extension/jemalloc/jemalloc/src/prof_stats.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/prof_stats.h" -namespace duckdb_jemalloc { - bool opt_prof_stats = false; malloc_mutex_t prof_stats_mtx; static prof_stats_t prof_stats_live[PROF_SC_NSIZES]; @@ -57,5 +55,3 @@ prof_stats_get_accum(tsd_t *tsd, szind_t ind, prof_stats_t *stats) { memcpy(stats, &prof_stats_accum[ind], sizeof(prof_stats_t)); prof_stats_leave(tsd); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/prof_sys.cpp b/extension/jemalloc/jemalloc/src/prof_sys.c similarity index 68% rename from extension/jemalloc/jemalloc/src/prof_sys.cpp rename to extension/jemalloc/jemalloc/src/prof_sys.c index d44cd91e743..8a904040e59 100644 --- a/extension/jemalloc/jemalloc/src/prof_sys.cpp +++ b/extension/jemalloc/jemalloc/src/prof_sys.c @@ -1,4 +1,3 @@ -#define JEMALLOC_PROF_SYS_C_ #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" @@ -7,8 +6,6 @@ #include "jemalloc/internal/prof_data.h" #include "jemalloc/internal/prof_sys.h" -namespace duckdb_jemalloc { - #ifdef JEMALLOC_PROF_LIBUNWIND #define UNW_LOCAL_ONLY #include @@ -29,8 +26,6 @@ namespace duckdb_jemalloc { malloc_mutex_t prof_dump_filename_mtx; -bool prof_do_mock = false; - static uint64_t prof_dump_seq; static uint64_t prof_dump_iseq; static uint64_t prof_dump_mseq; @@ -57,9 +52,9 @@ prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) { cassert(config_prof); assert(*len == 0); assert(vec != NULL); - assert(max_len == PROF_BT_MAX); + assert(max_len <= PROF_BT_MAX_LIMIT); - nframes = unw_backtrace(vec, PROF_BT_MAX); + nframes = unw_backtrace(vec, max_len); if (nframes <= 0) { return; } @@ -99,13 +94,16 @@ prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) { cassert(config_prof); assert(vec != NULL); - assert(max_len == PROF_BT_MAX); + assert(max_len <= PROF_BT_MAX_LIMIT); _Unwind_Backtrace(prof_unwind_callback, &data); } #elif (defined(JEMALLOC_PROF_GCC)) +JEMALLOC_DIAGNOSTIC_PUSH +JEMALLOC_DIAGNOSTIC_IGNORE_FRAME_ADDRESS static void prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) { +/* The input arg must be a constant for __builtin_return_address. */ #define BT_FRAME(i) \ if ((i) < max_len) { \ void *p; \ @@ -124,7 +122,7 @@ prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) { cassert(config_prof); assert(vec != NULL); - assert(max_len == PROF_BT_MAX); + assert(max_len <= PROF_BT_MAX_LIMIT); BT_FRAME(0) BT_FRAME(1) @@ -266,7 +264,149 @@ prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) { BT_FRAME(125) BT_FRAME(126) BT_FRAME(127) + BT_FRAME(128) + BT_FRAME(129) + + BT_FRAME(130) + BT_FRAME(131) + BT_FRAME(132) + BT_FRAME(133) + BT_FRAME(134) + BT_FRAME(135) + BT_FRAME(136) + BT_FRAME(137) + BT_FRAME(138) + BT_FRAME(139) + + BT_FRAME(140) + BT_FRAME(141) + BT_FRAME(142) + BT_FRAME(143) + BT_FRAME(144) + BT_FRAME(145) + BT_FRAME(146) + BT_FRAME(147) + BT_FRAME(148) + BT_FRAME(149) + + BT_FRAME(150) + BT_FRAME(151) + BT_FRAME(152) + BT_FRAME(153) + BT_FRAME(154) + BT_FRAME(155) + BT_FRAME(156) + BT_FRAME(157) + BT_FRAME(158) + BT_FRAME(159) + + BT_FRAME(160) + BT_FRAME(161) + BT_FRAME(162) + BT_FRAME(163) + BT_FRAME(164) + BT_FRAME(165) + BT_FRAME(166) + BT_FRAME(167) + BT_FRAME(168) + BT_FRAME(169) + + BT_FRAME(170) + BT_FRAME(171) + BT_FRAME(172) + BT_FRAME(173) + BT_FRAME(174) + BT_FRAME(175) + BT_FRAME(176) + BT_FRAME(177) + BT_FRAME(178) + BT_FRAME(179) + + BT_FRAME(180) + BT_FRAME(181) + BT_FRAME(182) + BT_FRAME(183) + BT_FRAME(184) + BT_FRAME(185) + BT_FRAME(186) + BT_FRAME(187) + BT_FRAME(188) + BT_FRAME(189) + + BT_FRAME(190) + BT_FRAME(191) + BT_FRAME(192) + BT_FRAME(193) + BT_FRAME(194) + BT_FRAME(195) + BT_FRAME(196) + BT_FRAME(197) + BT_FRAME(198) + BT_FRAME(199) + + BT_FRAME(200) + BT_FRAME(201) + BT_FRAME(202) + BT_FRAME(203) + BT_FRAME(204) + BT_FRAME(205) + BT_FRAME(206) + BT_FRAME(207) + BT_FRAME(208) + BT_FRAME(209) + + BT_FRAME(210) + BT_FRAME(211) + BT_FRAME(212) + BT_FRAME(213) + BT_FRAME(214) + BT_FRAME(215) + BT_FRAME(216) + BT_FRAME(217) + BT_FRAME(218) + BT_FRAME(219) + + BT_FRAME(220) + BT_FRAME(221) + BT_FRAME(222) + BT_FRAME(223) + BT_FRAME(224) + BT_FRAME(225) + BT_FRAME(226) + BT_FRAME(227) + BT_FRAME(228) + BT_FRAME(229) + + BT_FRAME(230) + BT_FRAME(231) + BT_FRAME(232) + BT_FRAME(233) + BT_FRAME(234) + BT_FRAME(235) + BT_FRAME(236) + BT_FRAME(237) + BT_FRAME(238) + BT_FRAME(239) + + BT_FRAME(240) + BT_FRAME(241) + BT_FRAME(242) + BT_FRAME(243) + BT_FRAME(244) + BT_FRAME(245) + BT_FRAME(246) + BT_FRAME(247) + BT_FRAME(248) + BT_FRAME(249) + + BT_FRAME(250) + BT_FRAME(251) + BT_FRAME(252) + BT_FRAME(253) + BT_FRAME(254) + BT_FRAME(255) #undef BT_FRAME +JEMALLOC_DIAGNOSTIC_POP } #else static void @@ -283,18 +423,20 @@ prof_backtrace(tsd_t *tsd, prof_bt_t *bt) { assert(prof_backtrace_hook != NULL); pre_reentrancy(tsd, NULL); - prof_backtrace_hook(bt->vec, &bt->len, PROF_BT_MAX); + prof_backtrace_hook(bt->vec, &bt->len, opt_prof_bt_max); post_reentrancy(tsd); } void -prof_hooks_init() { +prof_hooks_init(void) { prof_backtrace_hook_set(&prof_backtrace_impl); prof_dump_hook_set(NULL); + prof_sample_hook_set(NULL); + prof_sample_free_hook_set(NULL); } void -prof_unwind_init() { +prof_unwind_init(void) { #ifdef JEMALLOC_PROF_LIBGCC /* * Cause the backtracing machinery to allocate its internal @@ -306,7 +448,6 @@ prof_unwind_init() { static int prof_sys_thread_name_read_impl(char *buf, size_t limit) { -#ifdef JEMALLOC_PROF #if defined(JEMALLOC_HAVE_PTHREAD_GETNAME_NP) return pthread_getname_np(pthread_self(), buf, limit); #elif defined(JEMALLOC_HAVE_PTHREAD_GET_NAME_NP) @@ -315,21 +456,23 @@ prof_sys_thread_name_read_impl(char *buf, size_t limit) { #else return ENOSYS; #endif -#else - return 0; -#endif } prof_sys_thread_name_read_t *JET_MUTABLE prof_sys_thread_name_read = prof_sys_thread_name_read_impl; void prof_sys_thread_name_fetch(tsd_t *tsd) { -#define THREAD_NAME_MAX_LEN 16 - char buf[THREAD_NAME_MAX_LEN]; - if (!prof_sys_thread_name_read(buf, THREAD_NAME_MAX_LEN)) { - prof_thread_name_set_impl(tsd, buf); + prof_tdata_t *tdata = prof_tdata_get(tsd, true); + if (tdata == NULL) { + return; + } + + if (prof_sys_thread_name_read(tdata->thread_name, + PROF_THREAD_NAME_MAX_LEN) != 0) { + prof_thread_name_clear(tdata); } -#undef THREAD_NAME_MAX_LEN + + tdata->thread_name[PROF_THREAD_NAME_MAX_LEN - 1] = '\0'; } int @@ -341,6 +484,41 @@ prof_getpid(void) { #endif } +long +prof_get_pid_namespace() { + long ret = 0; + +#if defined(_WIN32) || defined(__APPLE__) + // Not supported, do nothing. +#else + char buf[PATH_MAX]; + const char* linkname = +# if defined(__FreeBSD__) || defined(__DragonFly__) + "/proc/curproc/ns/pid" +# else + "/proc/self/ns/pid" +# endif + ; + ssize_t linklen = +# ifndef JEMALLOC_READLINKAT + readlink(linkname, buf, PATH_MAX) +# else + readlinkat(AT_FDCWD, linkname, buf, PATH_MAX) +# endif + ; + + // namespace string is expected to be like pid:[4026531836] + if (linklen > 0) { + // Trim the trailing "]" + buf[linklen-1] = '\0'; + char* index = strtok(buf, "pid:["); + ret = atol(index); + } +#endif + + return ret; +} + /* * This buffer is rather large for stack allocation, so use a single buffer for * all profile dumps; protected by prof_dump_mtx. @@ -388,7 +566,7 @@ prof_dump_check_possible_error(prof_dump_arg_t *arg, bool err_cond, malloc_write(buf); if (opt_abort) { - jemalloc_abort(); + abort(); } } @@ -427,6 +605,72 @@ prof_dump_close(prof_dump_arg_t *arg) { } } +#ifdef __APPLE__ +#include + +#ifdef __LP64__ +typedef struct mach_header_64 mach_header_t; +typedef struct segment_command_64 segment_command_t; +#define MH_MAGIC_VALUE MH_MAGIC_64 +#define MH_CIGAM_VALUE MH_CIGAM_64 +#define LC_SEGMENT_VALUE LC_SEGMENT_64 +#else +typedef struct mach_header mach_header_t; +typedef struct segment_command segment_command_t; +#define MH_MAGIC_VALUE MH_MAGIC +#define MH_CIGAM_VALUE MH_CIGAM +#define LC_SEGMENT_VALUE LC_SEGMENT +#endif + +static void +prof_dump_dyld_image_vmaddr(buf_writer_t *buf_writer, uint32_t image_index) { + const mach_header_t *header = (const mach_header_t *) + _dyld_get_image_header(image_index); + if (header == NULL || (header->magic != MH_MAGIC_VALUE && + header->magic != MH_CIGAM_VALUE)) { + // Invalid header + return; + } + + intptr_t slide = _dyld_get_image_vmaddr_slide(image_index); + const char *name = _dyld_get_image_name(image_index); + struct load_command *load_cmd = (struct load_command *) + ((char *)header + sizeof(mach_header_t)); + for (uint32_t i = 0; load_cmd && (i < header->ncmds); i++) { + if (load_cmd->cmd == LC_SEGMENT_VALUE) { + const segment_command_t *segment_cmd = + (const segment_command_t *)load_cmd; + if (!strcmp(segment_cmd->segname, "__TEXT")) { + char buffer[PATH_MAX + 1]; + malloc_snprintf(buffer, sizeof(buffer), + "%016llx-%016llx: %s\n", segment_cmd->vmaddr + slide, + segment_cmd->vmaddr + slide + segment_cmd->vmsize, name); + buf_writer_cb(buf_writer, buffer); + return; + } + } + load_cmd = + (struct load_command *)((char *)load_cmd + load_cmd->cmdsize); + } +} + +static void +prof_dump_dyld_maps(buf_writer_t *buf_writer) { + uint32_t image_count = _dyld_image_count(); + for (uint32_t i = 0; i < image_count; i++) { + prof_dump_dyld_image_vmaddr(buf_writer, i); + } +} + +prof_dump_open_maps_t *JET_MUTABLE prof_dump_open_maps = NULL; + +static void +prof_dump_maps(buf_writer_t *buf_writer) { + buf_writer_cb(buf_writer, "\nMAPPED_LIBRARIES:\n"); + /* No proc map file to read on MacOS, dump dyld maps for backtrace. */ + prof_dump_dyld_maps(buf_writer); +} +#else /* !__APPLE__ */ #ifndef _WIN32 JEMALLOC_FORMAT_PRINTF(1, 2) static int @@ -453,7 +697,7 @@ prof_open_maps_internal(const char *format, ...) { #endif static int -prof_dump_open_maps_impl() { +prof_dump_open_maps_impl(void) { int mfd; cassert(config_prof); @@ -492,6 +736,7 @@ prof_dump_maps(buf_writer_t *buf_writer) { buf_writer_pipe(buf_writer, prof_dump_read_maps_cb, &mfd); close(mfd); } +#endif /* __APPLE__ */ static bool prof_dump(tsd_t *tsd, bool propagate_err, const char *filename, @@ -570,15 +815,30 @@ prof_dump_filename(tsd_t *tsd, char *filename, char v, uint64_t vseq) { const char *prefix = prof_prefix_get(tsd_tsdn(tsd)); if (vseq != VSEQ_INVALID) { - /* "...v.heap" */ - malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, - "%s.%d.%" FMTu64".%c%" FMTu64".heap", prefix, prof_getpid(), - prof_dump_seq, v, vseq); + if (opt_prof_pid_namespace) { + /* "....v.heap" */ + malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, + "%s.%ld.%d.%"FMTu64".%c%"FMTu64".heap", prefix, + prof_get_pid_namespace(), prof_getpid(), prof_dump_seq, v, + vseq); + } else { + /* "...v.heap" */ + malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, + "%s.%d.%"FMTu64".%c%"FMTu64".heap", prefix, prof_getpid(), + prof_dump_seq, v, vseq); + } } else { - /* "....heap" */ - malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, - "%s.%d.%" FMTu64".%c.heap", prefix, prof_getpid(), - prof_dump_seq, v); + if (opt_prof_pid_namespace) { + /* ".....heap" */ + malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, + "%s.%ld.%d.%"FMTu64".%c.heap", prefix, + prof_get_pid_namespace(), prof_getpid(), prof_dump_seq, v); + } else { + /* "....heap" */ + malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, + "%s.%d.%"FMTu64".%c.heap", prefix, prof_getpid(), + prof_dump_seq, v); + } } prof_dump_seq++; } @@ -586,8 +846,14 @@ prof_dump_filename(tsd_t *tsd, char *filename, char v, uint64_t vseq) { void prof_get_default_filename(tsdn_t *tsdn, char *filename, uint64_t ind) { malloc_mutex_lock(tsdn, &prof_dump_filename_mtx); - malloc_snprintf(filename, PROF_DUMP_FILENAME_LEN, - "%s.%d.%" FMTu64".json", prof_prefix_get(tsdn), prof_getpid(), ind); + if (opt_prof_pid_namespace) { + malloc_snprintf(filename, PROF_DUMP_FILENAME_LEN, + "%s.%ld.%d.%"FMTu64".json", prof_prefix_get(tsdn), + prof_get_pid_namespace(), prof_getpid(), ind); + } else { + malloc_snprintf(filename, PROF_DUMP_FILENAME_LEN, + "%s.%d.%"FMTu64".json", prof_prefix_get(tsdn), prof_getpid(), ind); + } malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx); } @@ -606,11 +872,14 @@ bool prof_prefix_set(tsdn_t *tsdn, const char *prefix) { cassert(config_prof); ctl_mtx_assert_held(tsdn); + if (prefix == NULL) { + return true; + } malloc_mutex_lock(tsdn, &prof_dump_filename_mtx); if (prof_prefix == NULL) { malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx); /* Everything is still guarded by ctl_mtx. */ - char *buffer = (char *)base_alloc(tsdn, prof_base, + char *buffer = base_alloc(tsdn, prof_base, PROF_DUMP_FILENAME_LEN, QUANTUM); if (buffer == NULL) { return true; @@ -673,5 +942,3 @@ prof_gdump_impl(tsd_t *tsd) { malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx); prof_dump(tsd, false, filename, false); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/psset.cpp b/extension/jemalloc/jemalloc/src/psset.c similarity index 91% rename from extension/jemalloc/jemalloc/src/psset.cpp rename to extension/jemalloc/jemalloc/src/psset.c index e0c7a3b9934..55966816542 100644 --- a/extension/jemalloc/jemalloc/src/psset.cpp +++ b/extension/jemalloc/jemalloc/src/psset.c @@ -5,8 +5,6 @@ #include "jemalloc/internal/fb.h" -namespace duckdb_jemalloc { - void psset_init(psset_t *psset) { for (unsigned i = 0; i < PSSET_NPSIZES; i++) { @@ -94,8 +92,20 @@ psset_bin_stats_remove(psset_t *psset, psset_bin_stats_t *binstats, psset_bin_stats_insert_remove(psset, binstats, ps, false); } +static pszind_t +psset_hpdata_heap_index(const hpdata_t *ps) { + assert(!hpdata_full(ps)); + assert(!hpdata_empty(ps)); + size_t longest_free_range = hpdata_longest_free_range_get(ps); + pszind_t pind = sz_psz2ind(sz_psz_quantize_floor( + longest_free_range << LG_PAGE)); + assert(pind < PSSET_NPSIZES); + return pind; +} + static void -psset_hpdata_heap_remove(psset_t *psset, pszind_t pind, hpdata_t *ps) { +psset_hpdata_heap_remove(psset_t *psset, hpdata_t *ps) { + pszind_t pind = psset_hpdata_heap_index(ps); hpdata_age_heap_remove(&psset->pageslabs[pind], ps); if (hpdata_age_heap_empty(&psset->pageslabs[pind])) { fb_unset(psset->pageslab_bitmap, PSSET_NPSIZES, (size_t)pind); @@ -103,7 +113,8 @@ psset_hpdata_heap_remove(psset_t *psset, pszind_t pind, hpdata_t *ps) { } static void -psset_hpdata_heap_insert(psset_t *psset, pszind_t pind, hpdata_t *ps) { +psset_hpdata_heap_insert(psset_t *psset, hpdata_t *ps) { + pszind_t pind = psset_hpdata_heap_index(ps); if (hpdata_age_heap_empty(&psset->pageslabs[pind])) { fb_set(psset->pageslab_bitmap, PSSET_NPSIZES, (size_t)pind); } @@ -117,12 +128,7 @@ psset_stats_insert(psset_t* psset, hpdata_t *ps) { } else if (hpdata_full(ps)) { psset_bin_stats_insert(psset, psset->stats.full_slabs, ps); } else { - size_t longest_free_range = hpdata_longest_free_range_get(ps); - - pszind_t pind = sz_psz2ind(sz_psz_quantize_floor( - longest_free_range << LG_PAGE)); - assert(pind < PSSET_NPSIZES); - + pszind_t pind = psset_hpdata_heap_index(ps); psset_bin_stats_insert(psset, psset->stats.nonfull_slabs[pind], ps); } @@ -135,12 +141,7 @@ psset_stats_remove(psset_t *psset, hpdata_t *ps) { } else if (hpdata_full(ps)) { psset_bin_stats_remove(psset, psset->stats.full_slabs, ps); } else { - size_t longest_free_range = hpdata_longest_free_range_get(ps); - - pszind_t pind = sz_psz2ind(sz_psz_quantize_floor( - longest_free_range << LG_PAGE)); - assert(pind < PSSET_NPSIZES); - + pszind_t pind = psset_hpdata_heap_index(ps); psset_bin_stats_remove(psset, psset->stats.nonfull_slabs[pind], ps); } @@ -167,13 +168,7 @@ psset_alloc_container_insert(psset_t *psset, hpdata_t *ps) { * going to return them from a psset_pick_alloc call. */ } else { - size_t longest_free_range = hpdata_longest_free_range_get(ps); - - pszind_t pind = sz_psz2ind(sz_psz_quantize_floor( - longest_free_range << LG_PAGE)); - assert(pind < PSSET_NPSIZES); - - psset_hpdata_heap_insert(psset, pind, ps); + psset_hpdata_heap_insert(psset, ps); } } @@ -188,13 +183,7 @@ psset_alloc_container_remove(psset_t *psset, hpdata_t *ps) { } else if (hpdata_full(ps)) { /* Same as above -- do nothing in this case. */ } else { - size_t longest_free_range = hpdata_longest_free_range_get(ps); - - pszind_t pind = sz_psz2ind(sz_psz_quantize_floor( - longest_free_range << LG_PAGE)); - assert(pind < PSSET_NPSIZES); - - psset_hpdata_heap_remove(psset, pind, ps); + psset_hpdata_heap_remove(psset, ps); } } @@ -385,5 +374,3 @@ psset_remove(psset_t *psset, hpdata_t *ps) { hpdata_hugify_list_remove(&psset->to_hugify, ps); } } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/rtree.cpp b/extension/jemalloc/jemalloc/src/rtree.c similarity index 93% rename from extension/jemalloc/jemalloc/src/rtree.cpp rename to extension/jemalloc/jemalloc/src/rtree.c index 134cfb32998..b6ac04b7586 100644 --- a/extension/jemalloc/jemalloc/src/rtree.cpp +++ b/extension/jemalloc/jemalloc/src/rtree.c @@ -4,8 +4,6 @@ #include "jemalloc/internal/assert.h" #include "jemalloc/internal/mutex.h" -namespace duckdb_jemalloc { - /* * Only the most significant bits of keys passed to rtree_{read,write}() are * used. @@ -31,14 +29,14 @@ rtree_new(rtree_t *rtree, base_t *base, bool zeroed) { static rtree_node_elm_t * rtree_node_alloc(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) { - return (rtree_node_elm_t *)base_alloc(tsdn, rtree->base, - nelms * sizeof(rtree_node_elm_t), CACHELINE); + return (rtree_node_elm_t *)base_alloc_rtree(tsdn, rtree->base, + nelms * sizeof(rtree_node_elm_t)); } static rtree_leaf_elm_t * rtree_leaf_alloc(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) { - return (rtree_leaf_elm_t *)base_alloc(tsdn, rtree->base, - nelms * sizeof(rtree_leaf_elm_t), CACHELINE); + return (rtree_leaf_elm_t *)base_alloc_rtree(tsdn, rtree->base, + nelms * sizeof(rtree_leaf_elm_t)); } static rtree_node_elm_t * @@ -49,7 +47,7 @@ rtree_node_init(tsdn_t *tsdn, rtree_t *rtree, unsigned level, * If *elmp is non-null, then it was initialized with the init lock * held, so we can get by with 'relaxed' here. */ - rtree_node_elm_t *node = (rtree_node_elm_t *)atomic_load_p(elmp, ATOMIC_RELAXED); + rtree_node_elm_t *node = atomic_load_p(elmp, ATOMIC_RELAXED); if (node == NULL) { node = rtree_node_alloc(tsdn, rtree, ZU(1) << rtree_levels[level].bits); @@ -75,7 +73,7 @@ rtree_leaf_init(tsdn_t *tsdn, rtree_t *rtree, atomic_p_t *elmp) { * If *elmp is non-null, then it was initialized with the init lock * held, so we can get by with 'relaxed' here. */ - rtree_leaf_elm_t *leaf = (rtree_leaf_elm_t *)atomic_load_p(elmp, ATOMIC_RELAXED); + rtree_leaf_elm_t *leaf = atomic_load_p(elmp, ATOMIC_RELAXED); if (leaf == NULL) { leaf = rtree_leaf_alloc(tsdn, rtree, ZU(1) << rtree_levels[RTREE_HEIGHT-1].bits); @@ -261,5 +259,3 @@ rtree_ctx_data_init(rtree_ctx_t *ctx) { cache->leaf = NULL; } } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/safety_check.cpp b/extension/jemalloc/jemalloc/src/safety_check.c similarity index 56% rename from extension/jemalloc/jemalloc/src/safety_check.cpp rename to extension/jemalloc/jemalloc/src/safety_check.c index f29993dbb83..d3f68fbc114 100644 --- a/extension/jemalloc/jemalloc/src/safety_check.cpp +++ b/extension/jemalloc/jemalloc/src/safety_check.c @@ -1,28 +1,39 @@ #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" -#include - -namespace duckdb_jemalloc { - static safety_check_abort_hook_t safety_check_abort; void safety_check_fail_sized_dealloc(bool current_dealloc, const void *ptr, size_t true_size, size_t input_size) { - char *src = (char *)(current_dealloc ? "the current pointer being freed" : - "in thread cache, possibly from previous deallocations"); + char *src = current_dealloc ? "the current pointer being freed" : + "in thread cache, possibly from previous deallocations"; + char *suggest_debug_build = config_debug ? "" : " --enable-debug or"; safety_check_fail(": size mismatch detected (true size %zu " "vs input size %zu), likely caused by application sized " - "deallocation bugs (source address: %p, %s). Suggest building with " - "--enable-debug or address sanitizer for debugging. Abort.\n", - true_size, input_size, ptr, src); + "deallocation bugs (source address: %p, %s). Suggest building with" + "%s address sanitizer for debugging. Abort.\n", + true_size, input_size, ptr, src, suggest_debug_build); } void safety_check_set_abort(safety_check_abort_hook_t abort_fn) { safety_check_abort = abort_fn; } +/* + * In addition to malloc_write, also embed hint msg in the abort function name + * because there are cases only logging crash stack traces. + */ +static void +safety_check_detected_heap_corruption___run_address_sanitizer_build_to_debug(const char *buf) { + if (safety_check_abort == NULL) { + malloc_write(buf); + abort(); + } else { + safety_check_abort(buf); + } +} + void safety_check_fail(const char *format, ...) { char buf[MALLOC_PRINTF_BUFSIZE]; @@ -31,12 +42,5 @@ void safety_check_fail(const char *format, ...) { malloc_vsnprintf(buf, MALLOC_PRINTF_BUFSIZE, format, ap); va_end(ap); - if (safety_check_abort == NULL) { - malloc_write(buf); - jemalloc_abort(); - } else { - safety_check_abort(buf); - } + safety_check_detected_heap_corruption___run_address_sanitizer_build_to_debug(buf); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/san.cpp b/extension/jemalloc/jemalloc/src/san.c similarity index 86% rename from extension/jemalloc/jemalloc/src/san.cpp rename to extension/jemalloc/jemalloc/src/san.c index dbc09684c69..28ea3d7cb6f 100644 --- a/extension/jemalloc/jemalloc/src/san.cpp +++ b/extension/jemalloc/jemalloc/src/san.c @@ -6,8 +6,6 @@ #include "jemalloc/internal/san.h" #include "jemalloc/internal/tsd.h" -namespace duckdb_jemalloc { - /* The sanitizer options. */ size_t opt_san_guard_large = SAN_GUARD_LARGE_EVERY_N_EXTENTS_DEFAULT; size_t opt_san_guard_small = SAN_GUARD_SMALL_EVERY_N_EXTENTS_DEFAULT; @@ -22,43 +20,43 @@ ssize_t opt_lg_san_uaf_align = SAN_LG_UAF_ALIGN_DEFAULT; uintptr_t san_cache_bin_nonfast_mask = SAN_CACHE_BIN_NONFAST_MASK_DEFAULT; static inline void -san_find_guarded_addr(edata_t *edata, uintptr_t *guard1, uintptr_t *guard2, - uintptr_t *addr, size_t size, bool left, bool right) { +san_find_guarded_addr(edata_t *edata, void **guard1, void **guard2, + void **addr, size_t size, bool left, bool right) { assert(!edata_guarded_get(edata)); assert(size % PAGE == 0); - *addr = (uintptr_t)edata_base_get(edata); + *addr = edata_base_get(edata); if (left) { *guard1 = *addr; - *addr += SAN_PAGE_GUARD; + *addr = ((byte_t *)*addr) + SAN_PAGE_GUARD; } else { - *guard1 = 0; + *guard1 = NULL; } if (right) { - *guard2 = *addr + size; + *guard2 = ((byte_t *)*addr) + size; } else { - *guard2 = 0; + *guard2 = NULL; } } static inline void -san_find_unguarded_addr(edata_t *edata, uintptr_t *guard1, uintptr_t *guard2, - uintptr_t *addr, size_t size, bool left, bool right) { +san_find_unguarded_addr(edata_t *edata, void **guard1, void **guard2, + void **addr, size_t size, bool left, bool right) { assert(edata_guarded_get(edata)); assert(size % PAGE == 0); - *addr = (uintptr_t)edata_base_get(edata); + *addr = edata_base_get(edata); if (right) { - *guard2 = *addr + size; + *guard2 = ((byte_t *)*addr) + size; } else { - *guard2 = 0; + *guard2 = NULL; } if (left) { - *guard1 = *addr - SAN_PAGE_GUARD; - assert(*guard1 != 0); + *guard1 = ((byte_t *)*addr) - SAN_PAGE_GUARD; + assert(*guard1 != NULL); *addr = *guard1; } else { - *guard1 = 0; + *guard1 = NULL; } } @@ -75,16 +73,16 @@ san_guard_pages(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, emap_t *emap, ? san_two_side_unguarded_sz(size_with_guards) : san_one_side_unguarded_sz(size_with_guards); - uintptr_t guard1, guard2, addr; + void *guard1, *guard2, *addr; san_find_guarded_addr(edata, &guard1, &guard2, &addr, usize, left, right); assert(edata_state_get(edata) == extent_state_active); - ehooks_guard(tsdn, ehooks, (void *)guard1, (void *)guard2); + ehooks_guard(tsdn, ehooks, guard1, guard2); /* Update the guarded addr and usable size of the edata. */ edata_size_set(edata, usize); - edata_addr_set(edata, (void *)addr); + edata_addr_set(edata, addr); edata_guarded_set(edata, true); if (remap) { @@ -110,7 +108,7 @@ san_unguard_pages_impl(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata, ? san_two_side_guarded_sz(size) : san_one_side_guarded_sz(size); - uintptr_t guard1, guard2, addr; + void *guard1, *guard2, *addr; san_find_unguarded_addr(edata, &guard1, &guard2, &addr, size, left, right); @@ -208,5 +206,3 @@ san_init(ssize_t lg_san_uaf_align) { san_cache_bin_nonfast_mask = ((uintptr_t)1 << lg_san_uaf_align) - 1; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/san_bump.cpp b/extension/jemalloc/jemalloc/src/san_bump.c similarity index 95% rename from extension/jemalloc/jemalloc/src/san_bump.cpp rename to extension/jemalloc/jemalloc/src/san_bump.c index 109c9f09c0d..888974555f2 100644 --- a/extension/jemalloc/jemalloc/src/san_bump.cpp +++ b/extension/jemalloc/jemalloc/src/san_bump.c @@ -7,8 +7,6 @@ #include "jemalloc/internal/ehooks.h" #include "jemalloc/internal/edata_cache.h" -namespace duckdb_jemalloc { - static bool san_bump_grow_locked(tsdn_t *tsdn, san_bump_alloc_t *sba, pac_t *pac, ehooks_t *ehooks, size_t size); @@ -22,7 +20,6 @@ san_bump_alloc(tsdn_t *tsdn, san_bump_alloc_t* sba, pac_t *pac, size_t guarded_size = san_one_side_guarded_sz(size); malloc_mutex_lock(tsdn, &sba->mtx); - size_t trail_size; if (sba->curr_reg == NULL || edata_size_get(sba->curr_reg) < guarded_size) { @@ -41,7 +38,7 @@ san_bump_alloc(tsdn_t *tsdn, san_bump_alloc_t* sba, pac_t *pac, to_destroy = NULL; } assert(guarded_size <= edata_size_get(sba->curr_reg)); - trail_size = edata_size_get(sba->curr_reg) - guarded_size; + size_t trail_size = edata_size_get(sba->curr_reg) - guarded_size; edata_t* edata; if (trail_size != 0) { @@ -105,5 +102,3 @@ san_bump_grow_locked(tsdn_t *tsdn, san_bump_alloc_t *sba, pac_t *pac, } return false; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/sc.cpp b/extension/jemalloc/jemalloc/src/sc.c similarity index 99% rename from extension/jemalloc/jemalloc/src/sc.cpp rename to extension/jemalloc/jemalloc/src/sc.c index d02d3020251..e4a94d89f24 100644 --- a/extension/jemalloc/jemalloc/src/sc.cpp +++ b/extension/jemalloc/jemalloc/src/sc.c @@ -6,8 +6,6 @@ #include "jemalloc/internal/pages.h" #include "jemalloc/internal/sc.h" -namespace duckdb_jemalloc { - /* * This module computes the size classes used to satisfy allocations. The logic * here was ported more or less line-by-line from a shell script, and because of @@ -306,5 +304,3 @@ void sc_boot(sc_data_t *data) { sc_data_init(data); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/sec.cpp b/extension/jemalloc/jemalloc/src/sec.c similarity index 98% rename from extension/jemalloc/jemalloc/src/sec.cpp rename to extension/jemalloc/jemalloc/src/sec.c index 374196c7d28..19d69ff4569 100644 --- a/extension/jemalloc/jemalloc/src/sec.cpp +++ b/extension/jemalloc/jemalloc/src/sec.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/sec.h" -namespace duckdb_jemalloc { - static edata_t *sec_alloc(tsdn_t *tsdn, pai_t *self, size_t size, size_t alignment, bool zero, bool guarded, bool frequent_reuse, bool *deferred_work_generated); @@ -176,14 +174,15 @@ sec_shard_alloc_locked(tsdn_t *tsdn, sec_t *sec, sec_shard_t *shard, static edata_t * sec_batch_fill_and_alloc(tsdn_t *tsdn, sec_t *sec, sec_shard_t *shard, - sec_bin_t *bin, size_t size) { + sec_bin_t *bin, size_t size, bool frequent_reuse) { malloc_mutex_assert_not_owner(tsdn, &shard->mtx); edata_list_active_t result; edata_list_active_init(&result); bool deferred_work_generated = false; size_t nalloc = pai_alloc_batch(tsdn, sec->fallback, size, - 1 + sec->opts.batch_fill_extra, &result, &deferred_work_generated); + 1 + sec->opts.batch_fill_extra, &result, frequent_reuse, + &deferred_work_generated); edata_t *ret = edata_list_active_first(&result); if (ret != NULL) { @@ -253,7 +252,7 @@ sec_alloc(tsdn_t *tsdn, pai_t *self, size_t size, size_t alignment, bool zero, if (edata == NULL) { if (do_batch_fill) { edata = sec_batch_fill_and_alloc(tsdn, sec, shard, bin, - size); + size, frequent_reuse); } else { edata = pai_alloc(tsdn, sec->fallback, size, alignment, zero, /* guarded */ false, frequent_reuse, @@ -422,5 +421,3 @@ sec_postfork_child(tsdn_t *tsdn, sec_t *sec) { malloc_mutex_postfork_child(tsdn, &sec->shards[i].mtx); } } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/stats.cpp b/extension/jemalloc/jemalloc/src/stats.c similarity index 94% rename from extension/jemalloc/jemalloc/src/stats.cpp rename to extension/jemalloc/jemalloc/src/stats.c index 2fbdbacb414..026a4f547dd 100644 --- a/extension/jemalloc/jemalloc/src/stats.cpp +++ b/extension/jemalloc/jemalloc/src/stats.c @@ -9,15 +9,13 @@ #include "jemalloc/internal/mutex_prof.h" #include "jemalloc/internal/prof_stats.h" -namespace duckdb_jemalloc { - -const char *global_mutex_names[mutex_prof_num_global_mutexes] = { +static const char *const global_mutex_names[mutex_prof_num_global_mutexes] = { #define OP(mtx) #mtx, MUTEX_PROF_GLOBAL_MUTEXES #undef OP }; -const char *arena_mutex_names[mutex_prof_num_arena_mutexes] = { +static const char *const arena_mutex_names[mutex_prof_num_arena_mutexes] = { #define OP(mtx) #mtx, MUTEX_PROF_ARENA_MUTEXES #undef OP @@ -44,15 +42,18 @@ const char *arena_mutex_names[mutex_prof_num_arena_mutexes] = { assert(miblen_new == miblen + 1); \ } while (0) -#define CTL_M2_GET(n, i, v, t) do { \ +#define CTL_MIB_GET(n, i, v, t, ind) do { \ size_t mib[CTL_MAX_DEPTH]; \ size_t miblen = sizeof(mib) / sizeof(size_t); \ size_t sz = sizeof(t); \ xmallctlnametomib(n, mib, &miblen); \ - mib[2] = (i); \ + mib[(ind)] = (i); \ xmallctlbymib(mib, miblen, (void *)v, &sz, NULL, 0); \ } while (0) +#define CTL_M1_GET(n, i, v, t) CTL_MIB_GET(n, i, v, t, 1) +#define CTL_M2_GET(n, i, v, t) CTL_MIB_GET(n, i, v, t, 2) + /******************************************************************************/ /* Data. */ @@ -112,8 +113,8 @@ mutex_stats_init_cols(emitter_row_t *row, const char *table_name, emitter_col_t *name, emitter_col_t col_uint64_t[mutex_prof_num_uint64_t_counters], emitter_col_t col_uint32_t[mutex_prof_num_uint32_t_counters]) { - mutex_prof_uint64_t_counter_ind_t k_uint64_t = (mutex_prof_uint64_t_counter_ind_t)0; - mutex_prof_uint32_t_counter_ind_t k_uint32_t = (mutex_prof_uint32_t_counter_ind_t)0; + mutex_prof_uint64_t_counter_ind_t k_uint64_t = 0; + mutex_prof_uint32_t_counter_ind_t k_uint32_t = 0; emitter_col_t *col; @@ -129,7 +130,7 @@ mutex_stats_init_cols(emitter_row_t *row, const char *table_name, #define WIDTH_uint64_t 16 #define OP(counter, counter_type, human, derived, base_counter) \ col = &col_##counter_type[k_##counter_type]; \ - k_##counter_type = (mutex_prof_##counter_type##_counter_ind_t)((counter_type)k_##counter_type + 1); \ + ++k_##counter_type; \ emitter_col_init(col, row); \ col->justify = emitter_justify_right; \ col->width = derived ? 8 : WIDTH_##counter_type; \ @@ -248,8 +249,8 @@ mutex_stats_emit(emitter_t *emitter, emitter_row_t *row, emitter_table_row(emitter, row); } - mutex_prof_uint64_t_counter_ind_t k_uint64_t = (mutex_prof_uint64_t_counter_ind_t)0; - mutex_prof_uint32_t_counter_ind_t k_uint32_t = (mutex_prof_uint32_t_counter_ind_t)0; + mutex_prof_uint64_t_counter_ind_t k_uint64_t = 0; + mutex_prof_uint32_t_counter_ind_t k_uint32_t = 0; emitter_col_t *col; @@ -258,7 +259,7 @@ mutex_stats_emit(emitter_t *emitter, emitter_row_t *row, #define OP(counter, type, human, derived, base_counter) \ if (!derived) { \ col = &col_##type[k_##type]; \ - k_##type = (mutex_prof_##type##_counter_ind_t)((type)k_##type + 1);; \ + ++k_##type; \ emitter_json_kv(emitter, #counter, EMITTER_TYPE_##type, \ (const void *)&col->bool_val); \ } @@ -323,7 +324,7 @@ stats_arena_bins_print(emitter_t *emitter, bool mutex, unsigned i, COL_HDR(row, size, NULL, right, 20, size) COL_HDR(row, ind, NULL, right, 4, unsigned) - COL_HDR(row, allocated, NULL, right, 13, uint64) + COL_HDR(row, allocated, NULL, right, 13, size) COL_HDR(row, nmalloc, NULL, right, 13, uint64) COL_HDR(row, nmalloc_ps, "(#/sec)", right, 8, uint64) COL_HDR(row, ndalloc, NULL, right, 13, uint64) @@ -909,8 +910,7 @@ stats_arena_hpa_shard_print(emitter_t *emitter, unsigned i, uint64_t uptime) { " npageslabs: %zu huge, %zu nonhuge\n" " nactive: %zu huge, %zu nonhuge \n" " ndirty: %zu huge, %zu nonhuge \n" - " nretained: 0 huge, %zu nonhuge \n" - "\n", + " nretained: 0 huge, %zu nonhuge \n", npageslabs_huge, npageslabs_nonhuge, nactive_huge, nactive_nonhuge, ndirty_huge, ndirty_nonhuge, @@ -931,6 +931,7 @@ stats_arena_hpa_shard_print(emitter_t *emitter, unsigned i, uint64_t uptime) { &ndirty_nonhuge); emitter_json_object_end(emitter); /* End "empty_slabs" */ + /* Last, nonfull slab stats. */ COL_HDR(row, size, NULL, right, 20, size) COL_HDR(row, ind, NULL, right, 4, unsigned) COL_HDR(row, npageslabs_huge, NULL, right, 16, size) @@ -946,6 +947,7 @@ stats_arena_hpa_shard_print(emitter_t *emitter, unsigned i, uint64_t uptime) { stats_arenas_mib[2] = i; CTL_LEAF_PREPARE(stats_arenas_mib, 3, "hpa_shard.nonfull_slabs"); + emitter_table_printf(emitter, " In nonfull slabs:\n"); emitter_table_row(emitter, &header_row); emitter_json_array_kv_begin(emitter, "nonfull_slabs"); bool in_gap = false; @@ -1028,7 +1030,7 @@ stats_arena_mutexes_print(emitter_t *emitter, unsigned arena_ind, uint64_t uptim stats_arenas_mib[2] = arena_ind; CTL_LEAF_PREPARE(stats_arenas_mib, 3, "mutexes"); - for (int i = 0; i < mutex_prof_num_arena_mutexes; + for (mutex_prof_arena_ind_t i = 0; i < mutex_prof_num_arena_mutexes; i++) { const char *name = arena_mutex_names[i]; emitter_json_object_kv_begin(emitter, name); @@ -1044,11 +1046,14 @@ JEMALLOC_COLD static void stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large, bool mutex, bool extents, bool hpa) { + char name[ARENA_NAME_LEN]; + char *namep = name; unsigned nthreads; const char *dss; ssize_t dirty_decay_ms, muzzy_decay_ms; size_t page, pactive, pdirty, pmuzzy, mapped, retained; - size_t base, internal, resident, metadata_thp, extent_avail; + size_t base, internal, resident, metadata_edata, metadata_rtree, + metadata_thp, extent_avail; uint64_t dirty_npurge, dirty_nmadvise, dirty_purged; uint64_t muzzy_npurge, muzzy_nmadvise, muzzy_purged; size_t small_allocated; @@ -1061,6 +1066,10 @@ stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large, uint64_t uptime; CTL_GET("arenas.page", &page, size_t); + if (i != MALLCTL_ARENAS_ALL && i != MALLCTL_ARENAS_DESTROYED) { + CTL_M1_GET("arena.0.name", i, (void *)&namep, const char *); + emitter_kv(emitter, "name", "name", emitter_type_string, &namep); + } CTL_M2_GET("stats.arenas.0.nthreads", i, &nthreads, unsigned); emitter_kv(emitter, "nthreads", "assigned threads", @@ -1344,6 +1353,8 @@ stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large, GET_AND_EMIT_MEM_STAT(retained) GET_AND_EMIT_MEM_STAT(base) GET_AND_EMIT_MEM_STAT(internal) + GET_AND_EMIT_MEM_STAT(metadata_edata) + GET_AND_EMIT_MEM_STAT(metadata_rtree) GET_AND_EMIT_MEM_STAT(metadata_thp) GET_AND_EMIT_MEM_STAT(tcache_bytes) GET_AND_EMIT_MEM_STAT(tcache_stashed_bytes) @@ -1421,18 +1432,18 @@ stats_general_print(emitter_t *emitter) { /* opt. */ #define OPT_WRITE(name, var, size, emitter_type) \ - if (je_mallctl("opt." name, (void *)&var, &size, NULL, 0) == \ + if (je_mallctl("opt."name, (void *)&var, &size, NULL, 0) == \ 0) { \ - emitter_kv(emitter, name, "opt." name, emitter_type, \ + emitter_kv(emitter, name, "opt."name, emitter_type, \ &var); \ } #define OPT_WRITE_MUTABLE(name, var1, var2, size, emitter_type, \ altname) \ - if (je_mallctl("opt." name, (void *)&var1, &size, NULL, 0) == \ + if (je_mallctl("opt."name, (void *)&var1, &size, NULL, 0) == \ 0 && je_mallctl(altname, (void *)&var2, &size, NULL, 0) \ == 0) { \ - emitter_kv_note(emitter, name, "opt." name, \ + emitter_kv_note(emitter, name, "opt."name, \ emitter_type, &var1, altname, emitter_type, \ &var2); \ } @@ -1462,6 +1473,40 @@ stats_general_print(emitter_t *emitter) { emitter_dict_begin(emitter, "opt", "Run-time option settings"); + /* + * opt.malloc_conf. + * + * Sources are documented in https://jemalloc.net/jemalloc.3.html#tuning + * - (Not Included Here) The string specified via --with-malloc-conf, + * which is already printed out above as config.malloc_conf + * - (Included) The string pointed to by the global variable malloc_conf + * - (Included) The “name” of the file referenced by the symbolic link + * named /etc/malloc.conf + * - (Included) The value of the environment variable MALLOC_CONF + * - (Optional, Unofficial) The string pointed to by the global variable + * malloc_conf_2_conf_harder, which is hidden from the public. + * + * Note: The outputs are strictly ordered by priorities (low -> high). + * + */ +#define MALLOC_CONF_WRITE(name, message) \ + if (je_mallctl("opt.malloc_conf."name, (void *)&cpv, &cpsz, NULL, 0) != \ + 0) { \ + cpv = ""; \ + } \ + emitter_kv(emitter, name, message, emitter_type_string, &cpv); + + MALLOC_CONF_WRITE("global_var", "Global variable malloc_conf"); + MALLOC_CONF_WRITE("symlink", "Symbolic link malloc.conf"); + MALLOC_CONF_WRITE("env_var", "Environment variable MALLOC_CONF"); + /* As this config is unofficial, skip the output if it's NULL */ + if (je_mallctl("opt.malloc_conf.global_var_2_conf_harder", + (void *)&cpv, &cpsz, NULL, 0) == 0) { + emitter_kv(emitter, "global_var_2_conf_harder", "Global " + "variable malloc_conf_2_conf_harder", emitter_type_string, &cpv); + } +#undef MALLOC_CONF_WRITE + OPT_WRITE_BOOL("abort") OPT_WRITE_BOOL("abort_conf") OPT_WRITE_BOOL("cache_oblivious") @@ -1520,8 +1565,10 @@ stats_general_print(emitter_t *emitter) { OPT_WRITE_SIZE_T("tcache_gc_delay_bytes") OPT_WRITE_UNSIGNED("lg_tcache_flush_small_div") OPT_WRITE_UNSIGNED("lg_tcache_flush_large_div") + OPT_WRITE_UNSIGNED("debug_double_free_max_scan") OPT_WRITE_CHAR_P("thp") OPT_WRITE_BOOL("prof") + OPT_WRITE_UNSIGNED("prof_bt_max") OPT_WRITE_CHAR_P("prof_prefix") OPT_WRITE_BOOL_MUTABLE("prof_active", "prof.active") OPT_WRITE_BOOL_MUTABLE("prof_thread_active_init", @@ -1541,7 +1588,7 @@ stats_general_print(emitter_t *emitter) { OPT_WRITE_CHAR_P("stats_interval_opts") OPT_WRITE_CHAR_P("zero_realloc") - emitter_dict_end(emitter); + emitter_dict_end(emitter); /* Close "opt". */ #undef OPT_WRITE #undef OPT_WRITE_MUTABLE @@ -1686,8 +1733,8 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed, * These should be deleted. We keep them around for a while, to aid in * the transition to the emitter code. */ - size_t allocated, active, metadata, metadata_thp, resident, mapped, - retained; + size_t allocated, active, metadata, metadata_edata, metadata_rtree, + metadata_thp, resident, mapped, retained; size_t num_background_threads; size_t zero_reallocs; uint64_t background_thread_num_runs, background_thread_run_interval; @@ -1695,6 +1742,8 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed, CTL_GET("stats.allocated", &allocated, size_t); CTL_GET("stats.active", &active, size_t); CTL_GET("stats.metadata", &metadata, size_t); + CTL_GET("stats.metadata_edata", &metadata_edata, size_t); + CTL_GET("stats.metadata_rtree", &metadata_rtree, size_t); CTL_GET("stats.metadata_thp", &metadata_thp, size_t); CTL_GET("stats.resident", &resident, size_t); CTL_GET("stats.mapped", &mapped, size_t); @@ -1720,6 +1769,10 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed, emitter_json_kv(emitter, "allocated", emitter_type_size, &allocated); emitter_json_kv(emitter, "active", emitter_type_size, &active); emitter_json_kv(emitter, "metadata", emitter_type_size, &metadata); + emitter_json_kv(emitter, "metadata_edata", emitter_type_size, + &metadata_edata); + emitter_json_kv(emitter, "metadata_rtree", emitter_type_size, + &metadata_rtree); emitter_json_kv(emitter, "metadata_thp", emitter_type_size, &metadata_thp); emitter_json_kv(emitter, "resident", emitter_type_size, &resident); @@ -1729,9 +1782,10 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed, &zero_reallocs); emitter_table_printf(emitter, "Allocated: %zu, active: %zu, " - "metadata: %zu (n_thp %zu), resident: %zu, mapped: %zu, " - "retained: %zu\n", allocated, active, metadata, metadata_thp, - resident, mapped, retained); + "metadata: %zu (n_thp %zu, edata %zu, rtree %zu), resident: %zu, " + "mapped: %zu, retained: %zu\n", allocated, active, metadata, + metadata_thp, metadata_edata, metadata_rtree, resident, mapped, + retained); /* Strange behaviors */ emitter_table_printf(emitter, @@ -1748,7 +1802,7 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed, emitter_json_object_end(emitter); /* Close "background_thread". */ emitter_table_printf(emitter, "Background threads: %zu, " - "num_runs: %" FMTu64", run_interval: %" FMTu64" ns\n", + "num_runs: %"FMTu64", run_interval: %"FMTu64" ns\n", num_background_threads, background_thread_num_runs, background_thread_run_interval); @@ -1793,7 +1847,7 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed, size_t sz; VARIABLE_ARRAY(bool, initialized, narenas); bool destroyed_initialized; - unsigned i, j, ninitialized; + unsigned i, ninitialized; xmallctlnametomib("arena.0.initialized", mib, &miblen); for (i = ninitialized = 0; i < narenas; i++) { @@ -1833,7 +1887,7 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed, /* Unmerged stats. */ if (unmerged) { - for (i = j = 0; i < narenas; i++) { + for (i = 0; i < narenas; i++) { if (initialized[i]) { char arena_ind_str[20]; malloc_snprintf(arena_ind_str, @@ -1881,7 +1935,7 @@ stats_print(write_cb_t *write_cb, void *cbopaque, const char *opts) { } malloc_write(": Failure in mallctl(\"epoch\", " "...)\n"); - jemalloc_abort(); + abort(); } if (opts != NULL) { @@ -1973,5 +2027,3 @@ void stats_postfork_child(tsdn_t *tsdn) { counter_postfork_child(tsdn, &stats_interval_accumulated); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/sz.cpp b/extension/jemalloc/jemalloc/src/sz.c similarity index 96% rename from extension/jemalloc/jemalloc/src/sz.cpp rename to extension/jemalloc/jemalloc/src/sz.c index f31f815f842..89def9d509a 100644 --- a/extension/jemalloc/jemalloc/src/sz.cpp +++ b/extension/jemalloc/jemalloc/src/sz.c @@ -2,8 +2,6 @@ #include "jemalloc/internal/jemalloc_internal_includes.h" #include "jemalloc/internal/sz.h" -namespace duckdb_jemalloc { - JEMALLOC_ALIGNED(CACHELINE) size_t sz_pind2sz_tab[SC_NPSIZES+1]; size_t sz_large_pad; @@ -102,7 +100,8 @@ sz_boot_size2index_tab(const sc_data_t *sc_data) { size_t max_ind = ((sz + (ZU(1) << SC_LG_TINY_MIN) - 1) >> SC_LG_TINY_MIN); for (; dst_ind <= max_ind && dst_ind < dst_max; dst_ind++) { - sz_size2index_tab[dst_ind] = sc_ind; + assert(sc_ind < 1 << (sizeof(uint8_t) * 8)); + sz_size2index_tab[dst_ind] = (uint8_t)sc_ind; } } } @@ -114,5 +113,3 @@ sz_boot(const sc_data_t *sc_data, bool cache_oblivious) { sz_boot_index2size_tab(sc_data); sz_boot_size2index_tab(sc_data); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/tcache.cpp b/extension/jemalloc/jemalloc/src/tcache.c similarity index 68% rename from extension/jemalloc/jemalloc/src/tcache.cpp rename to extension/jemalloc/jemalloc/src/tcache.c index 98f53608b94..f923554166c 100644 --- a/extension/jemalloc/jemalloc/src/tcache.cpp +++ b/extension/jemalloc/jemalloc/src/tcache.c @@ -2,19 +2,18 @@ #include "jemalloc/internal/jemalloc_internal_includes.h" #include "jemalloc/internal/assert.h" +#include "jemalloc/internal/base.h" #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/safety_check.h" #include "jemalloc/internal/san.h" #include "jemalloc/internal/sc.h" -namespace duckdb_jemalloc { - /******************************************************************************/ /* Data. */ bool opt_tcache = true; -/* tcache_maxclass is set to 32KB by default. */ +/* global_do_not_change_tcache_maxclass is set to 32KB by default. */ size_t opt_tcache_max = ((size_t)1) << 15; /* Reasonable defaults for min and max values. */ @@ -59,16 +58,30 @@ size_t opt_tcache_gc_delay_bytes = 0; unsigned opt_lg_tcache_flush_small_div = 1; unsigned opt_lg_tcache_flush_large_div = 1; -cache_bin_info_t *tcache_bin_info; - -/* Total stack size required (per tcache). Include the padding above. */ -static size_t tcache_bin_alloc_size; -static size_t tcache_bin_alloc_alignment; +/* + * Number of cache bins enabled, including both large and small. This value + * is only used to initialize tcache_nbins in the per-thread tcache. + * Directly modifying it will not affect threads already launched. + */ +unsigned global_do_not_change_tcache_nbins; +/* + * Max size class to be cached (can be small or large). This value is only used + * to initialize tcache_max in the per-thread tcache. Directly modifying it + * will not affect threads already launched. + */ +size_t global_do_not_change_tcache_maxclass; -/* Number of cache bins enabled, including both large and small. */ -unsigned nhbins; -/* Max size class to be cached (can be small or large). */ -size_t tcache_maxclass; +/* + * Default bin info for each bin. Will be initialized in malloc_conf_init + * and tcache_boot and should not be modified after that. + */ +static cache_bin_info_t opt_tcache_ncached_max[TCACHE_NBINS_MAX] = {{0}}; +/* + * Marks whether a bin's info is set already. This is used in + * tcache_bin_info_compute to avoid overwriting ncached_max specified by + * malloc_conf. It should be set only when parsing malloc_conf. + */ +static bool opt_tcache_ncached_max_set[TCACHE_NBINS_MAX] = {0}; tcaches_t *tcaches; @@ -128,10 +141,9 @@ tcache_gc_small(tsd_t *tsd, tcache_slow_t *tcache_slow, tcache_t *tcache, assert(szind < SC_NBINS); cache_bin_t *cache_bin = &tcache->bins[szind]; - cache_bin_sz_t ncached = cache_bin_ncached_get_local(cache_bin, - &tcache_bin_info[szind]); - cache_bin_sz_t low_water = cache_bin_low_water_get(cache_bin, - &tcache_bin_info[szind]); + assert(!tcache_bin_disabled(szind, cache_bin, tcache->tcache_slow)); + cache_bin_sz_t ncached = cache_bin_ncached_get_local(cache_bin); + cache_bin_sz_t low_water = cache_bin_low_water_get(cache_bin); assert(!tcache_slow->bin_refilled[szind]); size_t nflush = low_water - (low_water >> 2); @@ -154,8 +166,8 @@ tcache_gc_small(tsd_t *tsd, tcache_slow_t *tcache_slow, tcache_t *tcache, * Reduce fill count by 2X. Limit lg_fill_div such that * the fill count is always at least 1. */ - if ((cache_bin_info_ncached_max(&tcache_bin_info[szind]) - >> (tcache_slow->lg_fill_div[szind] + 1)) >= 1) { + if ((cache_bin_ncached_max_get(cache_bin) >> + (tcache_slow->lg_fill_div[szind] + 1)) >= 1) { tcache_slow->lg_fill_div[szind]++; } } @@ -166,10 +178,9 @@ tcache_gc_large(tsd_t *tsd, tcache_slow_t *tcache_slow, tcache_t *tcache, /* Like the small GC; flush 3/4 of untouched items. */ assert(szind >= SC_NBINS); cache_bin_t *cache_bin = &tcache->bins[szind]; - cache_bin_sz_t ncached = cache_bin_ncached_get_local(cache_bin, - &tcache_bin_info[szind]); - cache_bin_sz_t low_water = cache_bin_low_water_get(cache_bin, - &tcache_bin_info[szind]); + assert(!tcache_bin_disabled(szind, cache_bin, tcache->tcache_slow)); + cache_bin_sz_t ncached = cache_bin_ncached_get_local(cache_bin); + cache_bin_sz_t low_water = cache_bin_low_water_get(cache_bin); tcache_bin_flush_large(tsd, tcache, cache_bin, szind, (unsigned)(ncached - low_water + (low_water >> 2))); } @@ -186,10 +197,12 @@ tcache_event(tsd_t *tsd) { bool is_small = (szind < SC_NBINS); cache_bin_t *cache_bin = &tcache->bins[szind]; - tcache_bin_flush_stashed(tsd, tcache, cache_bin, szind, is_small); + if (tcache_bin_disabled(szind, cache_bin, tcache_slow)) { + goto label_done; + } - cache_bin_sz_t low_water = cache_bin_low_water_get(cache_bin, - &tcache_bin_info[szind]); + tcache_bin_flush_stashed(tsd, tcache, cache_bin, szind, is_small); + cache_bin_sz_t low_water = cache_bin_low_water_get(cache_bin); if (low_water > 0) { if (is_small) { tcache_gc_small(tsd, tcache_slow, tcache, szind); @@ -209,8 +222,9 @@ tcache_event(tsd_t *tsd) { } cache_bin_low_water_set(cache_bin); +label_done: tcache_slow->next_gc_bin++; - if (tcache_slow->next_gc_bin == nhbins) { + if (tcache_slow->next_gc_bin == tcache_nbins_get(tcache_slow)) { tcache_slow->next_gc_bin = 0; } } @@ -235,10 +249,13 @@ tcache_alloc_small_hard(tsdn_t *tsdn, arena_t *arena, void *ret; assert(tcache_slow->arena != NULL); - unsigned nfill = cache_bin_info_ncached_max(&tcache_bin_info[binind]) + assert(!tcache_bin_disabled(binind, cache_bin, tcache_slow)); + cache_bin_sz_t nfill = cache_bin_ncached_max_get(cache_bin) >> tcache_slow->lg_fill_div[binind]; - arena_cache_bin_fill_small(tsdn, arena, cache_bin, - &tcache_bin_info[binind], binind, nfill); + if (nfill == 0) { + nfill = 1; + } + arena_cache_bin_fill_small(tsdn, arena, cache_bin, binind, nfill); tcache_slow->bin_refilled[binind] = true; ret = cache_bin_alloc(cache_bin, tcache_success); @@ -320,7 +337,7 @@ tcache_bin_flush_impl(tsd_t *tsd, tcache_t *tcache, cache_bin_t *cache_bin, if (small) { assert(binind < SC_NBINS); } else { - assert(binind < nhbins); + assert(binind < tcache_nbins_get(tcache_slow)); } arena_t *tcache_arena = tcache_slow->arena; assert(tcache_arena != NULL); @@ -507,22 +524,34 @@ tcache_bin_flush_impl(tsd_t *tsd, tcache_t *tcache, cache_bin_t *cache_bin, JEMALLOC_ALWAYS_INLINE void tcache_bin_flush_bottom(tsd_t *tsd, tcache_t *tcache, cache_bin_t *cache_bin, szind_t binind, unsigned rem, bool small) { + assert(rem <= cache_bin_ncached_max_get(cache_bin)); + assert(!tcache_bin_disabled(binind, cache_bin, tcache->tcache_slow)); + cache_bin_sz_t orig_nstashed = cache_bin_nstashed_get_local(cache_bin); tcache_bin_flush_stashed(tsd, tcache, cache_bin, binind, small); - cache_bin_sz_t ncached = cache_bin_ncached_get_local(cache_bin, - &tcache_bin_info[binind]); - assert((cache_bin_sz_t)rem <= ncached); - unsigned nflush = ncached - rem; + cache_bin_sz_t ncached = cache_bin_ncached_get_local(cache_bin); + assert((cache_bin_sz_t)rem <= ncached + orig_nstashed); + if ((cache_bin_sz_t)rem > ncached) { + /* + * The flush_stashed above could have done enough flushing, if + * there were many items stashed. Validate that: 1) non zero + * stashed, and 2) bin stack has available space now. + */ + assert(orig_nstashed > 0); + assert(ncached + cache_bin_nstashed_get_local(cache_bin) + < cache_bin_ncached_max_get(cache_bin)); + /* Still go through the flush logic for stats purpose only. */ + rem = ncached; + } + cache_bin_sz_t nflush = ncached - (cache_bin_sz_t)rem; CACHE_BIN_PTR_ARRAY_DECLARE(ptrs, nflush); - cache_bin_init_ptr_array_for_flush(cache_bin, &tcache_bin_info[binind], - &ptrs, nflush); + cache_bin_init_ptr_array_for_flush(cache_bin, &ptrs, nflush); tcache_bin_flush_impl(tsd, tcache, cache_bin, binind, &ptrs, nflush, small); - cache_bin_finish_flush(cache_bin, &tcache_bin_info[binind], &ptrs, - ncached - rem); + cache_bin_finish_flush(cache_bin, &ptrs, nflush); } void @@ -550,35 +579,66 @@ tcache_bin_flush_large(tsd_t *tsd, tcache_t *tcache, cache_bin_t *cache_bin, void tcache_bin_flush_stashed(tsd_t *tsd, tcache_t *tcache, cache_bin_t *cache_bin, szind_t binind, bool is_small) { - cache_bin_info_t *info = &tcache_bin_info[binind]; + assert(!tcache_bin_disabled(binind, cache_bin, tcache->tcache_slow)); /* * The two below are for assertion only. The content of original cached * items remain unchanged -- the stashed items reside on the other end * of the stack. Checking the stack head and ncached to verify. */ void *head_content = *cache_bin->stack_head; - cache_bin_sz_t orig_cached = cache_bin_ncached_get_local(cache_bin, - info); + cache_bin_sz_t orig_cached = cache_bin_ncached_get_local(cache_bin); - cache_bin_sz_t nstashed = cache_bin_nstashed_get_local(cache_bin, info); - assert(orig_cached + nstashed <= cache_bin_info_ncached_max(info)); + cache_bin_sz_t nstashed = cache_bin_nstashed_get_local(cache_bin); + assert(orig_cached + nstashed <= cache_bin_ncached_max_get(cache_bin)); if (nstashed == 0) { return; } CACHE_BIN_PTR_ARRAY_DECLARE(ptrs, nstashed); - cache_bin_init_ptr_array_for_stashed(cache_bin, binind, info, &ptrs, + cache_bin_init_ptr_array_for_stashed(cache_bin, binind, &ptrs, nstashed); san_check_stashed_ptrs(ptrs.ptr, nstashed, sz_index2size(binind)); tcache_bin_flush_impl(tsd, tcache, cache_bin, binind, &ptrs, nstashed, is_small); - cache_bin_finish_flush_stashed(cache_bin, info); + cache_bin_finish_flush_stashed(cache_bin); - assert(cache_bin_nstashed_get_local(cache_bin, info) == 0); - assert(cache_bin_ncached_get_local(cache_bin, info) == orig_cached); + assert(cache_bin_nstashed_get_local(cache_bin) == 0); + assert(cache_bin_ncached_get_local(cache_bin) == orig_cached); assert(head_content == *cache_bin->stack_head); } +JET_EXTERN bool +tcache_get_default_ncached_max_set(szind_t ind) { + return opt_tcache_ncached_max_set[ind]; +} + +JET_EXTERN const cache_bin_info_t * +tcache_get_default_ncached_max(void) { + return opt_tcache_ncached_max; +} + +bool +tcache_bin_ncached_max_read(tsd_t *tsd, size_t bin_size, + cache_bin_sz_t *ncached_max) { + if (bin_size > TCACHE_MAXCLASS_LIMIT) { + return true; + } + + if (!tcache_available(tsd)) { + *ncached_max = 0; + return false; + } + + tcache_t *tcache = tsd_tcachep_get(tsd); + assert(tcache != NULL); + szind_t bin_ind = sz_size2index(bin_size); + + cache_bin_t *bin = &tcache->bins[bin_ind]; + *ncached_max = tcache_bin_disabled(bin_ind, bin, tcache->tcache_slow) ? + 0: cache_bin_ncached_max_get(bin); + return false; +} + void tcache_arena_associate(tsdn_t *tsdn, tcache_slow_t *tcache_slow, tcache_t *tcache, arena_t *arena) { @@ -635,48 +695,36 @@ tcache_arena_reassociate(tsdn_t *tsdn, tcache_slow_t *tcache_slow, tcache_arena_associate(tsdn, tcache_slow, tcache, arena); } -bool -tsd_tcache_enabled_data_init(tsd_t *tsd) { - /* Called upon tsd initialization. */ - tsd_tcache_enabled_set(tsd, opt_tcache); - tsd_slow_update(tsd); - - if (opt_tcache) { - /* Trigger tcache init. */ - tsd_tcache_data_init(tsd); - } - - return false; +static void +tcache_default_settings_init(tcache_slow_t *tcache_slow) { + assert(tcache_slow != NULL); + assert(global_do_not_change_tcache_maxclass != 0); + assert(global_do_not_change_tcache_nbins != 0); + tcache_slow->tcache_nbins = global_do_not_change_tcache_nbins; } static void tcache_init(tsd_t *tsd, tcache_slow_t *tcache_slow, tcache_t *tcache, - void *mem) { + void *mem, const cache_bin_info_t *tcache_bin_info) { tcache->tcache_slow = tcache_slow; tcache_slow->tcache = tcache; - // DuckDB C++: We can't do "sizeof(ql_elm(tcache_t))" because the struct is unnamed - // We statically initialize one here so we can do the sizeof - static constexpr const ql_elm(tcache_t) ql_elm_tcache_t{}; - - memset(&tcache_slow->link, 0, sizeof(ql_elm_tcache_t)); + memset(&tcache_slow->link, 0, sizeof(ql_elm(tcache_t))); tcache_slow->next_gc_bin = 0; tcache_slow->arena = NULL; tcache_slow->dyn_alloc = mem; /* * We reserve cache bins for all small size classes, even if some may - * not get used (i.e. bins higher than nhbins). This allows the fast - * and common paths to access cache bin metadata safely w/o worrying - * about which ones are disabled. + * not get used (i.e. bins higher than tcache_nbins). This allows + * the fast and common paths to access cache bin metadata safely w/o + * worrying about which ones are disabled. */ - unsigned n_reserved_bins = nhbins < SC_NBINS ? SC_NBINS : nhbins; - memset(tcache->bins, 0, sizeof(cache_bin_t) * n_reserved_bins); - + unsigned tcache_nbins = tcache_nbins_get(tcache_slow); size_t cur_offset = 0; - cache_bin_preincrement(tcache_bin_info, nhbins, mem, + cache_bin_preincrement(tcache_bin_info, tcache_nbins, mem, &cur_offset); - for (unsigned i = 0; i < nhbins; i++) { + for (unsigned i = 0; i < tcache_nbins; i++) { if (i < SC_NBINS) { tcache_slow->lg_fill_div[i] = 1; tcache_slow->bin_refilled[i] = false; @@ -684,49 +732,137 @@ tcache_init(tsd_t *tsd, tcache_slow_t *tcache_slow, tcache_t *tcache, = tcache_gc_item_delay_compute(i); } cache_bin_t *cache_bin = &tcache->bins[i]; - cache_bin_init(cache_bin, &tcache_bin_info[i], mem, - &cur_offset); + if (tcache_bin_info[i].ncached_max > 0) { + cache_bin_init(cache_bin, &tcache_bin_info[i], mem, + &cur_offset); + } else { + cache_bin_init_disabled(cache_bin, + tcache_bin_info[i].ncached_max); + } } /* - * For small size classes beyond tcache_maxclass (i.e. nhbins < NBINS), - * their cache bins are initialized to a state to safely and efficiently - * fail all fastpath alloc / free, so that no additional check around - * nhbins is needed on fastpath. + * Initialize all disabled bins to a state that can safely and + * efficiently fail all fastpath alloc / free, so that no additional + * check around tcache_nbins is needed on fastpath. Yet we still + * store the ncached_max in the bin_info for future usage. */ - for (unsigned i = nhbins; i < SC_NBINS; i++) { - /* Disabled small bins. */ + for (unsigned i = tcache_nbins; i < TCACHE_NBINS_MAX; i++) { cache_bin_t *cache_bin = &tcache->bins[i]; - void *fake_stack = mem; - size_t fake_offset = 0; + cache_bin_init_disabled(cache_bin, + tcache_bin_info[i].ncached_max); + assert(tcache_bin_disabled(i, cache_bin, tcache->tcache_slow)); + } - cache_bin_init(cache_bin, &tcache_bin_info[i], fake_stack, - &fake_offset); - assert(tcache_small_bin_disabled(i, cache_bin)); + cache_bin_postincrement(mem, &cur_offset); + if (config_debug) { + /* Sanity check that the whole stack is used. */ + size_t size, alignment; + cache_bin_info_compute_alloc(tcache_bin_info, tcache_nbins, + &size, &alignment); + assert(cur_offset == size); } +} - cache_bin_postincrement(tcache_bin_info, nhbins, mem, - &cur_offset); - /* Sanity check that the whole stack is used. */ - assert(cur_offset == tcache_bin_alloc_size); +static inline unsigned +tcache_ncached_max_compute(szind_t szind) { + if (szind >= SC_NBINS) { + return opt_tcache_nslots_large; + } + unsigned slab_nregs = bin_infos[szind].nregs; + + /* We may modify these values; start with the opt versions. */ + unsigned nslots_small_min = opt_tcache_nslots_small_min; + unsigned nslots_small_max = opt_tcache_nslots_small_max; + + /* + * Clamp values to meet our constraints -- even, nonzero, min < max, and + * suitable for a cache bin size. + */ + if (opt_tcache_nslots_small_max > CACHE_BIN_NCACHED_MAX) { + nslots_small_max = CACHE_BIN_NCACHED_MAX; + } + if (nslots_small_min % 2 != 0) { + nslots_small_min++; + } + if (nslots_small_max % 2 != 0) { + nslots_small_max--; + } + if (nslots_small_min < 2) { + nslots_small_min = 2; + } + if (nslots_small_max < 2) { + nslots_small_max = 2; + } + if (nslots_small_min > nslots_small_max) { + nslots_small_min = nslots_small_max; + } + + unsigned candidate; + if (opt_lg_tcache_nslots_mul < 0) { + candidate = slab_nregs >> (-opt_lg_tcache_nslots_mul); + } else { + candidate = slab_nregs << opt_lg_tcache_nslots_mul; + } + if (candidate % 2 != 0) { + /* + * We need the candidate size to be even -- we assume that we + * can divide by two and get a positive number (e.g. when + * flushing). + */ + ++candidate; + } + if (candidate <= nslots_small_min) { + return nslots_small_min; + } else if (candidate <= nslots_small_max) { + return candidate; + } else { + return nslots_small_max; + } } -/* Initialize auto tcache (embedded in TSD). */ -bool -tsd_tcache_data_init(tsd_t *tsd) { +JET_EXTERN void +tcache_bin_info_compute(cache_bin_info_t tcache_bin_info[TCACHE_NBINS_MAX]) { + /* + * Compute the values for each bin, but for bins with indices larger + * than tcache_nbins, no items will be cached. + */ + for (szind_t i = 0; i < TCACHE_NBINS_MAX; i++) { + unsigned ncached_max = tcache_get_default_ncached_max_set(i) ? + (unsigned)tcache_get_default_ncached_max()[i].ncached_max: + tcache_ncached_max_compute(i); + assert(ncached_max <= CACHE_BIN_NCACHED_MAX); + cache_bin_info_init(&tcache_bin_info[i], + (cache_bin_sz_t)ncached_max); + } +} + +static bool +tsd_tcache_data_init_impl(tsd_t *tsd, arena_t *arena, + const cache_bin_info_t *tcache_bin_info) { tcache_slow_t *tcache_slow = tsd_tcache_slowp_get_unsafe(tsd); tcache_t *tcache = tsd_tcachep_get_unsafe(tsd); assert(cache_bin_still_zero_initialized(&tcache->bins[0])); - size_t alignment = tcache_bin_alloc_alignment; - size_t size = sz_sa2u(tcache_bin_alloc_size, alignment); - - void *mem = ipallocztm(tsd_tsdn(tsd), size, alignment, true, NULL, - true, arena_get(TSDN_NULL, 0, true)); + unsigned tcache_nbins = tcache_nbins_get(tcache_slow); + size_t size, alignment; + cache_bin_info_compute_alloc(tcache_bin_info, tcache_nbins, + &size, &alignment); + + void *mem; + if (cache_bin_stack_use_thp()) { + /* Alignment is ignored since it comes from THP. */ + assert(alignment == QUANTUM); + mem = b0_alloc_tcache_stack(tsd_tsdn(tsd), size); + } else { + size = sz_sa2u(size, alignment); + mem = ipallocztm(tsd_tsdn(tsd), size, alignment, true, NULL, + true, arena_get(TSDN_NULL, 0, true)); + } if (mem == NULL) { return true; } - tcache_init(tsd, tcache_slow, tcache, mem); + tcache_init(tsd, tcache_slow, tcache, mem, tcache_bin_info); /* * Initialization is a bit tricky here. After malloc init is done, all * threads can rely on arena_choose and associate tcache accordingly. @@ -736,14 +872,15 @@ tsd_tcache_data_init(tsd_t *tsd) { * arena_choose_hard() will re-associate properly. */ tcache_slow->arena = NULL; - arena_t *arena; if (!malloc_initialized()) { /* If in initialization, assign to a0. */ arena = arena_get(tsd_tsdn(tsd), 0, false); tcache_arena_associate(tsd_tsdn(tsd), tcache_slow, tcache, arena); } else { - arena = arena_choose(tsd, NULL); + if (arena == NULL) { + arena = arena_choose(tsd, NULL); + } /* This may happen if thread.tcache.enabled is used. */ if (tcache_slow->arena == NULL) { tcache_arena_associate(tsd_tsdn(tsd), tcache_slow, @@ -755,6 +892,14 @@ tsd_tcache_data_init(tsd_t *tsd) { return false; } +/* Initialize auto tcache (embedded in TSD). */ +static bool +tsd_tcache_data_init(tsd_t *tsd, arena_t *arena, + const cache_bin_info_t tcache_bin_info[TCACHE_NBINS_MAX]) { + assert(tcache_bin_info != NULL); + return tsd_tcache_data_init_impl(tsd, arena, tcache_bin_info); +} + /* Created manual tcache for tcache.create mallctl. */ tcache_t * tcache_create_explicit(tsd_t *tsd) { @@ -763,21 +908,28 @@ tcache_create_explicit(tsd_t *tsd) { * the beginning of the whole allocation (for freeing). The makes sure * the cache bins have the requested alignment. */ - size_t size = tcache_bin_alloc_size + sizeof(tcache_t) + unsigned tcache_nbins = global_do_not_change_tcache_nbins; + size_t tcache_size, alignment; + cache_bin_info_compute_alloc(tcache_get_default_ncached_max(), + tcache_nbins, &tcache_size, &alignment); + + size_t size = tcache_size + sizeof(tcache_t) + sizeof(tcache_slow_t); /* Naturally align the pointer stacks. */ size = PTR_CEILING(size); - size = sz_sa2u(size, tcache_bin_alloc_alignment); + size = sz_sa2u(size, alignment); - void *mem = ipallocztm(tsd_tsdn(tsd), size, tcache_bin_alloc_alignment, + void *mem = ipallocztm(tsd_tsdn(tsd), size, alignment, true, NULL, true, arena_get(TSDN_NULL, 0, true)); if (mem == NULL) { return NULL; } - tcache_t *tcache = (tcache_t *)((uintptr_t)mem + tcache_bin_alloc_size); + tcache_t *tcache = (void *)((byte_t *)mem + tcache_size); tcache_slow_t *tcache_slow = - (tcache_slow_t *)((uintptr_t)mem + tcache_bin_alloc_size + sizeof(tcache_t)); - tcache_init(tsd, tcache_slow, tcache, mem); + (void *)((byte_t *)mem + tcache_size + sizeof(tcache_t)); + tcache_default_settings_init(tcache_slow); + tcache_init(tsd, tcache_slow, tcache, mem, + tcache_get_default_ncached_max()); tcache_arena_associate(tsd_tsdn(tsd), tcache_slow, tcache, arena_ichoose(tsd, NULL)); @@ -785,13 +937,151 @@ tcache_create_explicit(tsd_t *tsd) { return tcache; } +bool +tsd_tcache_enabled_data_init(tsd_t *tsd) { + /* Called upon tsd initialization. */ + tsd_tcache_enabled_set(tsd, opt_tcache); + /* + * tcache is not available yet, but we need to set up its tcache_nbins + * in advance. + */ + tcache_default_settings_init(tsd_tcache_slowp_get(tsd)); + tsd_slow_update(tsd); + + if (opt_tcache) { + /* Trigger tcache init. */ + tsd_tcache_data_init(tsd, NULL, + tcache_get_default_ncached_max()); + } + + return false; +} + +void +tcache_enabled_set(tsd_t *tsd, bool enabled) { + bool was_enabled = tsd_tcache_enabled_get(tsd); + + if (!was_enabled && enabled) { + tsd_tcache_data_init(tsd, NULL, + tcache_get_default_ncached_max()); + } else if (was_enabled && !enabled) { + tcache_cleanup(tsd); + } + /* Commit the state last. Above calls check current state. */ + tsd_tcache_enabled_set(tsd, enabled); + tsd_slow_update(tsd); +} + +void +thread_tcache_max_set(tsd_t *tsd, size_t tcache_max) { + assert(tcache_max <= TCACHE_MAXCLASS_LIMIT); + assert(tcache_max == sz_s2u(tcache_max)); + tcache_t *tcache = tsd_tcachep_get(tsd); + tcache_slow_t *tcache_slow = tcache->tcache_slow; + cache_bin_info_t tcache_bin_info[TCACHE_NBINS_MAX] = {{0}}; + assert(tcache != NULL && tcache_slow != NULL); + + bool enabled = tcache_available(tsd); + arena_t *assigned_arena; + if (enabled) { + assigned_arena = tcache_slow->arena; + /* Carry over the bin settings during the reboot. */ + tcache_bin_settings_backup(tcache, tcache_bin_info); + /* Shutdown and reboot the tcache for a clean slate. */ + tcache_cleanup(tsd); + } + + /* + * Still set tcache_nbins of the tcache even if the tcache is not + * available yet because the values are stored in tsd_t and are + * always available for changing. + */ + tcache_max_set(tcache_slow, tcache_max); + + if (enabled) { + tsd_tcache_data_init(tsd, assigned_arena, tcache_bin_info); + } + + assert(tcache_nbins_get(tcache_slow) == sz_size2index(tcache_max) + 1); +} + +static bool +tcache_bin_info_settings_parse(const char *bin_settings_segment_cur, + size_t len_left, cache_bin_info_t tcache_bin_info[TCACHE_NBINS_MAX], + bool bin_info_is_set[TCACHE_NBINS_MAX]) { + do { + size_t size_start, size_end; + size_t ncached_max; + bool err = multi_setting_parse_next(&bin_settings_segment_cur, + &len_left, &size_start, &size_end, &ncached_max); + if (err) { + return true; + } + if (size_end > TCACHE_MAXCLASS_LIMIT) { + size_end = TCACHE_MAXCLASS_LIMIT; + } + if (size_start > TCACHE_MAXCLASS_LIMIT || + size_start > size_end) { + continue; + } + /* May get called before sz_init (during malloc_conf_init). */ + szind_t bin_start = sz_size2index_compute(size_start); + szind_t bin_end = sz_size2index_compute(size_end); + if (ncached_max > CACHE_BIN_NCACHED_MAX) { + ncached_max = (size_t)CACHE_BIN_NCACHED_MAX; + } + for (szind_t i = bin_start; i <= bin_end; i++) { + cache_bin_info_init(&tcache_bin_info[i], + (cache_bin_sz_t)ncached_max); + if (bin_info_is_set != NULL) { + bin_info_is_set[i] = true; + } + } + } while (len_left > 0); + + return false; +} + +bool +tcache_bin_info_default_init(const char *bin_settings_segment_cur, + size_t len_left) { + return tcache_bin_info_settings_parse(bin_settings_segment_cur, + len_left, opt_tcache_ncached_max, opt_tcache_ncached_max_set); +} + + +bool +tcache_bins_ncached_max_write(tsd_t *tsd, char *settings, size_t len) { + assert(tcache_available(tsd)); + assert(len != 0); + tcache_t *tcache = tsd_tcachep_get(tsd); + assert(tcache != NULL); + cache_bin_info_t tcache_bin_info[TCACHE_NBINS_MAX]; + tcache_bin_settings_backup(tcache, tcache_bin_info); + + if(tcache_bin_info_settings_parse(settings, len, tcache_bin_info, + NULL)) { + return true; + } + + arena_t *assigned_arena = tcache->tcache_slow->arena; + tcache_cleanup(tsd); + tsd_tcache_data_init(tsd, assigned_arena, + tcache_bin_info); + + return false; +} + static void tcache_flush_cache(tsd_t *tsd, tcache_t *tcache) { tcache_slow_t *tcache_slow = tcache->tcache_slow; assert(tcache_slow->arena != NULL); - for (unsigned i = 0; i < nhbins; i++) { + for (unsigned i = 0; i < tcache_nbins_get(tcache_slow); i++) { cache_bin_t *cache_bin = &tcache->bins[i]; + if (tcache_bin_disabled(i, cache_bin, tcache_slow)) { + continue; + } if (i < SC_NBINS) { tcache_bin_flush_small(tsd, tcache, cache_bin, i, 0); } else { @@ -818,10 +1108,14 @@ tcache_destroy(tsd_t *tsd, tcache_t *tcache, bool tsd_tcache) { if (tsd_tcache) { cache_bin_t *cache_bin = &tcache->bins[0]; - cache_bin_assert_empty(cache_bin, &tcache_bin_info[0]); + cache_bin_assert_empty(cache_bin); + } + if (tsd_tcache && cache_bin_stack_use_thp()) { + b0_dalloc_tcache_stack(tsd_tsdn(tsd), tcache_slow->dyn_alloc); + } else { + idalloctm(tsd_tsdn(tsd), tcache_slow->dyn_alloc, NULL, NULL, + true, true); } - idalloctm(tsd_tsdn(tsd), tcache_slow->dyn_alloc, NULL, NULL, true, - true); /* * The deallocation and tcache flush above may not trigger decay since @@ -856,13 +1150,8 @@ tcache_cleanup(tsd_t *tsd) { assert(!cache_bin_still_zero_initialized(&tcache->bins[0])); tcache_destroy(tsd, tcache, true); - if (config_debug) { - /* - * For debug testing only, we want to pretend we're still in the - * zero-initialized state. - */ - memset(tcache->bins, 0, sizeof(cache_bin_t) * nhbins); - } + /* Make sure all bins used are reinitialized to the clean state. */ + memset(tcache->bins, 0, sizeof(cache_bin_t) * TCACHE_NBINS_MAX); } void @@ -870,8 +1159,11 @@ tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena) { cassert(config_stats); /* Merge and reset tcache stats. */ - for (unsigned i = 0; i < nhbins; i++) { + for (unsigned i = 0; i < tcache_nbins_get(tcache->tcache_slow); i++) { cache_bin_t *cache_bin = &tcache->bins[i]; + if (tcache_bin_disabled(i, cache_bin, tcache->tcache_slow)) { + continue; + } if (i < SC_NBINS) { bin_t *bin = arena_bin_choose(tsdn, arena, i, NULL); malloc_mutex_lock(tsdn, &bin->lock); @@ -892,7 +1184,7 @@ tcaches_create_prep(tsd_t *tsd, base_t *base) { malloc_mutex_assert_owner(tsd_tsdn(tsd), &tcaches_mtx); if (tcaches == NULL) { - tcaches = (tcaches_t *)base_alloc(tsd_tsdn(tsd), base, + tcaches = base_alloc(tsd_tsdn(tsd), base, sizeof(tcache_t *) * (MALLOCX_TCACHE_MAX+1), CACHELINE); if (tcaches == NULL) { err = true; @@ -918,13 +1210,12 @@ tcaches_create(tsd_t *tsd, base_t *base, unsigned *r_ind) { malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); - tcache_t *tcache; if (tcaches_create_prep(tsd, base)) { err = true; goto label_return; } - tcache = tcache_create_explicit(tsd); + tcache_t *tcache = tcache_create_explicit(tsd); if (tcache == NULL) { err = true; goto label_return; @@ -994,97 +1285,25 @@ tcaches_destroy(tsd_t *tsd, unsigned ind) { } } -static unsigned -tcache_ncached_max_compute(szind_t szind) { - if (szind >= SC_NBINS) { - assert(szind < nhbins); - return opt_tcache_nslots_large; - } - unsigned slab_nregs = bin_infos[szind].nregs; - - /* We may modify these values; start with the opt versions. */ - unsigned nslots_small_min = opt_tcache_nslots_small_min; - unsigned nslots_small_max = opt_tcache_nslots_small_max; - - /* - * Clamp values to meet our constraints -- even, nonzero, min < max, and - * suitable for a cache bin size. - */ - if (opt_tcache_nslots_small_max > CACHE_BIN_NCACHED_MAX) { - nslots_small_max = CACHE_BIN_NCACHED_MAX; - } - if (nslots_small_min % 2 != 0) { - nslots_small_min++; - } - if (nslots_small_max % 2 != 0) { - nslots_small_max--; - } - if (nslots_small_min < 2) { - nslots_small_min = 2; - } - if (nslots_small_max < 2) { - nslots_small_max = 2; - } - if (nslots_small_min > nslots_small_max) { - nslots_small_min = nslots_small_max; - } - - unsigned candidate; - if (opt_lg_tcache_nslots_mul < 0) { - candidate = slab_nregs >> (-opt_lg_tcache_nslots_mul); - } else { - candidate = slab_nregs << opt_lg_tcache_nslots_mul; - } - if (candidate % 2 != 0) { - /* - * We need the candidate size to be even -- we assume that we - * can divide by two and get a positive number (e.g. when - * flushing). - */ - ++candidate; - } - if (candidate <= nslots_small_min) { - return nslots_small_min; - } else if (candidate <= nslots_small_max) { - return candidate; - } else { - return nslots_small_max; - } -} - bool tcache_boot(tsdn_t *tsdn, base_t *base) { - tcache_maxclass = sz_s2u(opt_tcache_max); - assert(tcache_maxclass <= TCACHE_MAXCLASS_LIMIT); - nhbins = sz_size2index(tcache_maxclass) + 1; + global_do_not_change_tcache_maxclass = sz_s2u(opt_tcache_max); + assert(global_do_not_change_tcache_maxclass <= TCACHE_MAXCLASS_LIMIT); + global_do_not_change_tcache_nbins = + sz_size2index(global_do_not_change_tcache_maxclass) + 1; + /* + * Pre-compute default bin info and store the results in + * opt_tcache_ncached_max. After the changes here, + * opt_tcache_ncached_max should not be modified and should always be + * accessed using tcache_get_default_ncached_max. + */ + tcache_bin_info_compute(opt_tcache_ncached_max); if (malloc_mutex_init(&tcaches_mtx, "tcaches", WITNESS_RANK_TCACHES, malloc_mutex_rank_exclusive)) { return true; } - /* Initialize tcache_bin_info. See comments in tcache_init(). */ - unsigned n_reserved_bins = nhbins < SC_NBINS ? SC_NBINS : nhbins; - size_t size = n_reserved_bins * sizeof(cache_bin_info_t); - tcache_bin_info = (cache_bin_info_t *)base_alloc(tsdn, base, size, - CACHELINE); - if (tcache_bin_info == NULL) { - return true; - } - - for (szind_t i = 0; i < nhbins; i++) { - unsigned ncached_max = tcache_ncached_max_compute(i); - cache_bin_info_init(&tcache_bin_info[i], ncached_max); - } - for (szind_t i = nhbins; i < SC_NBINS; i++) { - /* Disabled small bins. */ - cache_bin_info_init(&tcache_bin_info[i], 0); - assert(tcache_small_bin_disabled(i, NULL)); - } - - cache_bin_info_compute_alloc(tcache_bin_info, nhbins, - &tcache_bin_alloc_size, &tcache_bin_alloc_alignment); - return false; } @@ -1106,5 +1325,3 @@ tcache_postfork_child(tsdn_t *tsdn) { void tcache_assert_initialized(tcache_t *tcache) { assert(!cache_bin_still_zero_initialized(&tcache->bins[0])); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/test_hooks.cpp b/extension/jemalloc/jemalloc/src/test_hooks.c similarity index 60% rename from extension/jemalloc/jemalloc/src/test_hooks.cpp rename to extension/jemalloc/jemalloc/src/test_hooks.c index 0dfb247b666..40621199d86 100644 --- a/extension/jemalloc/jemalloc/src/test_hooks.cpp +++ b/extension/jemalloc/jemalloc/src/test_hooks.c @@ -1,16 +1,12 @@ #include "jemalloc/internal/jemalloc_preamble.h" -#include "jemalloc/internal/test_hooks.h" - -namespace duckdb_jemalloc { - /* * The hooks are a little bit screwy -- they're not genuinely exported in the * sense that we want them available to end-users, but we do want them visible * from outside the generated library, so that we can use them in test code. */ -void (*test_hooks_arena_new_hook)() = NULL; - -void (*test_hooks_libc_hook)() = NULL; +JEMALLOC_EXPORT +void (*test_hooks_arena_new_hook)(void) = NULL; -} // namespace duckdb_jemalloc +JEMALLOC_EXPORT +void (*test_hooks_libc_hook)(void) = NULL; diff --git a/extension/jemalloc/jemalloc/src/thread_event.cpp b/extension/jemalloc/jemalloc/src/thread_event.c similarity index 99% rename from extension/jemalloc/jemalloc/src/thread_event.cpp rename to extension/jemalloc/jemalloc/src/thread_event.c index 948033c1273..37eb5827d3c 100644 --- a/extension/jemalloc/jemalloc/src/thread_event.cpp +++ b/extension/jemalloc/jemalloc/src/thread_event.c @@ -3,8 +3,6 @@ #include "jemalloc/internal/thread_event.h" -namespace duckdb_jemalloc { - /* * Signatures for event specific functions. These functions should be defined * by the modules owning each event. The signatures here verify that the @@ -343,5 +341,3 @@ tsd_te_init(tsd_t *tsd) { te_init(tsd, false); te_assert_invariants(tsd); } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/ticker.cpp b/extension/jemalloc/jemalloc/src/ticker.c similarity index 95% rename from extension/jemalloc/jemalloc/src/ticker.cpp rename to extension/jemalloc/jemalloc/src/ticker.c index 64de567edce..790b5c20079 100644 --- a/extension/jemalloc/jemalloc/src/ticker.cpp +++ b/extension/jemalloc/jemalloc/src/ticker.c @@ -1,8 +1,6 @@ #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_includes.h" -namespace duckdb_jemalloc { - /* * To avoid using floating point math down core paths (still necessary because * versions of the glibc dynamic loader that did not preserve xmm registers are @@ -32,5 +30,3 @@ const uint8_t ticker_geom_table[1 << TICKER_GEOM_NBITS] = { 16, 15, 14, 13, 12, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/tsd.cpp b/extension/jemalloc/jemalloc/src/tsd.c similarity index 93% rename from extension/jemalloc/jemalloc/src/tsd.cpp rename to extension/jemalloc/jemalloc/src/tsd.c index edcbd61104c..a4db8e36019 100644 --- a/extension/jemalloc/jemalloc/src/tsd.cpp +++ b/extension/jemalloc/jemalloc/src/tsd.c @@ -6,8 +6,6 @@ #include "jemalloc/internal/mutex.h" #include "jemalloc/internal/rtree.h" -namespace duckdb_jemalloc { - /******************************************************************************/ /* Data. */ @@ -150,7 +148,7 @@ tsd_local_slow(tsd_t *tsd) { } bool -tsd_global_slow() { +tsd_global_slow(void) { return atomic_load_u32(&tsd_global_slow_count, ATOMIC_RELAXED) > 0; } @@ -302,9 +300,25 @@ tsd_fetch_slow(tsd_t *tsd, bool minimal) { tsd_state_set(tsd, tsd_state_minimal_initialized); tsd_set(tsd); tsd_data_init_nocleanup(tsd); + *tsd_min_init_state_nfetchedp_get(tsd) = 1; } } else if (tsd_state_get(tsd) == tsd_state_minimal_initialized) { - if (!minimal) { + /* + * If a thread only ever deallocates (e.g. dedicated reclamation + * threads), we want to help it to eventually escape the slow + * path (caused by the minimal initialized state). The nfetched + * counter tracks the number of times the tsd has been accessed + * under the min init state, and triggers the switch to nominal + * once reached the max allowed count. + * + * This means at most 128 deallocations stay on the slow path. + * + * Also see comments in free_default(). + */ + uint8_t *nfetched = tsd_min_init_state_nfetchedp_get(tsd); + assert(*nfetched >= 1); + (*nfetched)++; + if (!minimal || *nfetched == TSD_MIN_INIT_STATE_MAX_FETCHED) { /* Switch to fully initialized. */ tsd_state_set(tsd, tsd_state_nominal); assert(*tsd_reentrancy_levelp_get(tsd) >= 1); @@ -490,14 +504,13 @@ _tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { # pragma comment(linker, "/INCLUDE:_tls_callback") # else # pragma comment(linker, "/INCLUDE:_tls_used") -# pragma comment(linker, "/INCLUDE:" STRINGIFY(tls_callback)) -#endif -#pragma section(".CRT$XLY", long, read) +# pragma comment(linker, "/INCLUDE:" STRINGIFY(tls_callback) ) +# endif +# pragma section(".CRT$XLY",long,read) #endif -extern "C" -JEMALLOC_SECTION(".CRT$XLY") -JEMALLOC_ATTR(used) - BOOL(WINAPI *const tls_callback)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) = _tls_callback; +JEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used) +BOOL (WINAPI *const tls_callback)(HINSTANCE hinstDLL, + DWORD fdwReason, LPVOID lpvReserved) = _tls_callback; #endif #if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \ @@ -550,5 +563,3 @@ tsd_postfork_child(tsd_t *tsd) { tsd_add_nominal(tsd); } } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/util.c b/extension/jemalloc/jemalloc/src/util.c new file mode 100644 index 00000000000..b73848fb5fa --- /dev/null +++ b/extension/jemalloc/jemalloc/src/util.c @@ -0,0 +1,49 @@ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/util.h" + +/* Reads the next size pair in a multi-sized option. */ +bool +multi_setting_parse_next(const char **setting_segment_cur, size_t *len_left, + size_t *key_start, size_t *key_end, size_t *value) { + const char *cur = *setting_segment_cur; + char *end; + uintmax_t um; + + set_errno(0); + + /* First number, then '-' */ + um = malloc_strtoumax(cur, &end, 0); + if (get_errno() != 0 || *end != '-') { + return true; + } + *key_start = (size_t)um; + cur = end + 1; + + /* Second number, then ':' */ + um = malloc_strtoumax(cur, &end, 0); + if (get_errno() != 0 || *end != ':') { + return true; + } + *key_end = (size_t)um; + cur = end + 1; + + /* Last number */ + um = malloc_strtoumax(cur, &end, 0); + if (get_errno() != 0) { + return true; + } + *value = (size_t)um; + + /* Consume the separator if there is one. */ + if (*end == '|') { + end++; + } + + *len_left -= end - *setting_segment_cur; + *setting_segment_cur = end; + + return false; +} + diff --git a/extension/jemalloc/jemalloc/src/witness.cpp b/extension/jemalloc/jemalloc/src/witness.c similarity index 95% rename from extension/jemalloc/jemalloc/src/witness.cpp rename to extension/jemalloc/jemalloc/src/witness.c index c524f3927c6..4474af04c8d 100644 --- a/extension/jemalloc/jemalloc/src/witness.cpp +++ b/extension/jemalloc/jemalloc/src/witness.c @@ -4,8 +4,6 @@ #include "jemalloc/internal/assert.h" #include "jemalloc/internal/malloc_io.h" -namespace duckdb_jemalloc { - void witness_init(witness_t *witness, const char *name, witness_rank_t rank, witness_comp_t *comp, void *opaque) { @@ -52,7 +50,7 @@ witness_lock_error_impl(const witness_list_t *witnesses, malloc_printf(": Lock rank order reversal:"); witness_print_witnesses(witnesses); malloc_printf(" %s(%u)\n", witness->name, witness->rank); - jemalloc_abort(); + abort(); } witness_lock_error_t *JET_MUTABLE witness_lock_error = witness_lock_error_impl; @@ -60,7 +58,7 @@ static void witness_owner_error_impl(const witness_t *witness) { malloc_printf(": Should own %s(%u)\n", witness->name, witness->rank); - jemalloc_abort(); + abort(); } witness_owner_error_t *JET_MUTABLE witness_owner_error = witness_owner_error_impl; @@ -69,7 +67,7 @@ static void witness_not_owner_error_impl(const witness_t *witness) { malloc_printf(": Should not own %s(%u)\n", witness->name, witness->rank); - jemalloc_abort(); + abort(); } witness_not_owner_error_t *JET_MUTABLE witness_not_owner_error = witness_not_owner_error_impl; @@ -81,7 +79,7 @@ witness_depth_error_impl(const witness_list_t *witnesses, (depth != 1) ? "s" : "", rank_inclusive); witness_print_witnesses(witnesses); malloc_printf("\n"); - jemalloc_abort(); + abort(); } witness_depth_error_t *JET_MUTABLE witness_depth_error = witness_depth_error_impl; @@ -122,5 +120,3 @@ witness_postfork_child(witness_tsd_t *witness_tsd) { #endif witness_tsd->forking = false; } - -} // namespace duckdb_jemalloc diff --git a/extension/jemalloc/jemalloc/src/zone.c b/extension/jemalloc/jemalloc/src/zone.c new file mode 100644 index 00000000000..23dfdd04a91 --- /dev/null +++ b/extension/jemalloc/jemalloc/src/zone.c @@ -0,0 +1,469 @@ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" + +#ifndef JEMALLOC_ZONE +# error "This source file is for zones on Darwin (OS X)." +#endif + +/* Definitions of the following structs in malloc/malloc.h might be too old + * for the built binary to run on newer versions of OSX. So use the newest + * possible version of those structs. + */ +typedef struct _malloc_zone_t { + void *reserved1; + void *reserved2; + size_t (*size)(struct _malloc_zone_t *, const void *); + void *(*malloc)(struct _malloc_zone_t *, size_t); + void *(*calloc)(struct _malloc_zone_t *, size_t, size_t); + void *(*valloc)(struct _malloc_zone_t *, size_t); + void (*free)(struct _malloc_zone_t *, void *); + void *(*realloc)(struct _malloc_zone_t *, void *, size_t); + void (*destroy)(struct _malloc_zone_t *); + const char *zone_name; + unsigned (*batch_malloc)(struct _malloc_zone_t *, size_t, void **, unsigned); + void (*batch_free)(struct _malloc_zone_t *, void **, unsigned); + struct malloc_introspection_t *introspect; + unsigned version; + void *(*memalign)(struct _malloc_zone_t *, size_t, size_t); + void (*free_definite_size)(struct _malloc_zone_t *, void *, size_t); + size_t (*pressure_relief)(struct _malloc_zone_t *, size_t); +} malloc_zone_t; + +typedef struct { + vm_address_t address; + vm_size_t size; +} vm_range_t; + +typedef struct malloc_statistics_t { + unsigned blocks_in_use; + size_t size_in_use; + size_t max_size_in_use; + size_t size_allocated; +} malloc_statistics_t; + +typedef kern_return_t memory_reader_t(task_t, vm_address_t, vm_size_t, void **); + +typedef void vm_range_recorder_t(task_t, void *, unsigned type, vm_range_t *, unsigned); + +typedef struct malloc_introspection_t { + kern_return_t (*enumerator)(task_t, void *, unsigned, vm_address_t, memory_reader_t, vm_range_recorder_t); + size_t (*good_size)(malloc_zone_t *, size_t); + boolean_t (*check)(malloc_zone_t *); + void (*print)(malloc_zone_t *, boolean_t); + void (*log)(malloc_zone_t *, void *); + void (*force_lock)(malloc_zone_t *); + void (*force_unlock)(malloc_zone_t *); + void (*statistics)(malloc_zone_t *, malloc_statistics_t *); + boolean_t (*zone_locked)(malloc_zone_t *); + boolean_t (*enable_discharge_checking)(malloc_zone_t *); + boolean_t (*disable_discharge_checking)(malloc_zone_t *); + void (*discharge)(malloc_zone_t *, void *); +#ifdef __BLOCKS__ + void (*enumerate_discharged_pointers)(malloc_zone_t *, void (^)(void *, void *)); +#else + void *enumerate_unavailable_without_blocks; +#endif + void (*reinit_lock)(malloc_zone_t *); +} malloc_introspection_t; + +extern kern_return_t malloc_get_all_zones(task_t, memory_reader_t, vm_address_t **, unsigned *); + +extern malloc_zone_t *malloc_default_zone(void); + +extern void malloc_zone_register(malloc_zone_t *zone); + +extern void malloc_zone_unregister(malloc_zone_t *zone); + +/* + * The malloc_default_purgeable_zone() function is only available on >= 10.6. + * We need to check whether it is present at runtime, thus the weak_import. + */ +extern malloc_zone_t *malloc_default_purgeable_zone(void) +JEMALLOC_ATTR(weak_import); + +/******************************************************************************/ +/* Data. */ + +static malloc_zone_t *default_zone, *purgeable_zone; +static malloc_zone_t jemalloc_zone; +static struct malloc_introspection_t jemalloc_zone_introspect; +static pid_t zone_force_lock_pid = -1; + +/******************************************************************************/ +/* Function prototypes for non-inline static functions. */ + +static size_t zone_size(malloc_zone_t *zone, const void *ptr); +static void *zone_malloc(malloc_zone_t *zone, size_t size); +static void *zone_calloc(malloc_zone_t *zone, size_t num, size_t size); +static void *zone_valloc(malloc_zone_t *zone, size_t size); +static void zone_free(malloc_zone_t *zone, void *ptr); +static void *zone_realloc(malloc_zone_t *zone, void *ptr, size_t size); +static void *zone_memalign(malloc_zone_t *zone, size_t alignment, + size_t size); +static void zone_free_definite_size(malloc_zone_t *zone, void *ptr, + size_t size); +static void zone_destroy(malloc_zone_t *zone); +static unsigned zone_batch_malloc(struct _malloc_zone_t *zone, size_t size, + void **results, unsigned num_requested); +static void zone_batch_free(struct _malloc_zone_t *zone, + void **to_be_freed, unsigned num_to_be_freed); +static size_t zone_pressure_relief(struct _malloc_zone_t *zone, size_t goal); +static size_t zone_good_size(malloc_zone_t *zone, size_t size); +static kern_return_t zone_enumerator(task_t task, void *data, unsigned type_mask, + vm_address_t zone_address, memory_reader_t reader, + vm_range_recorder_t recorder); +static boolean_t zone_check(malloc_zone_t *zone); +static void zone_print(malloc_zone_t *zone, boolean_t verbose); +static void zone_log(malloc_zone_t *zone, void *address); +static void zone_force_lock(malloc_zone_t *zone); +static void zone_force_unlock(malloc_zone_t *zone); +static void zone_statistics(malloc_zone_t *zone, + malloc_statistics_t *stats); +static boolean_t zone_locked(malloc_zone_t *zone); +static void zone_reinit_lock(malloc_zone_t *zone); + +/******************************************************************************/ +/* + * Functions. + */ + +static size_t +zone_size(malloc_zone_t *zone, const void *ptr) { + /* + * There appear to be places within Darwin (such as setenv(3)) that + * cause calls to this function with pointers that *no* zone owns. If + * we knew that all pointers were owned by *some* zone, we could split + * our zone into two parts, and use one as the default allocator and + * the other as the default deallocator/reallocator. Since that will + * not work in practice, we must check all pointers to assure that they + * reside within a mapped extent before determining size. + */ + return ivsalloc(tsdn_fetch(), ptr); +} + +static void * +zone_malloc(malloc_zone_t *zone, size_t size) { + return je_malloc(size); +} + +static void * +zone_calloc(malloc_zone_t *zone, size_t num, size_t size) { + return je_calloc(num, size); +} + +static void * +zone_valloc(malloc_zone_t *zone, size_t size) { + void *ret = NULL; /* Assignment avoids useless compiler warning. */ + + je_posix_memalign(&ret, PAGE, size); + + return ret; +} + +static void +zone_free(malloc_zone_t *zone, void *ptr) { + if (ivsalloc(tsdn_fetch(), ptr) != 0) { + je_free(ptr); + return; + } + + free(ptr); +} + +static void * +zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) { + if (ivsalloc(tsdn_fetch(), ptr) != 0) { + return je_realloc(ptr, size); + } + + return realloc(ptr, size); +} + +static void * +zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size) { + void *ret = NULL; /* Assignment avoids useless compiler warning. */ + + je_posix_memalign(&ret, alignment, size); + + return ret; +} + +static void +zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size) { + size_t alloc_size; + + alloc_size = ivsalloc(tsdn_fetch(), ptr); + if (alloc_size != 0) { + assert(alloc_size == size); + je_free(ptr); + return; + } + + free(ptr); +} + +static void +zone_destroy(malloc_zone_t *zone) { + /* This function should never be called. */ + not_reached(); +} + +static unsigned +zone_batch_malloc(struct _malloc_zone_t *zone, size_t size, void **results, + unsigned num_requested) { + unsigned i; + + for (i = 0; i < num_requested; i++) { + results[i] = je_malloc(size); + if (!results[i]) + break; + } + + return i; +} + +static void +zone_batch_free(struct _malloc_zone_t *zone, void **to_be_freed, + unsigned num_to_be_freed) { + unsigned i; + + for (i = 0; i < num_to_be_freed; i++) { + zone_free(zone, to_be_freed[i]); + to_be_freed[i] = NULL; + } +} + +static size_t +zone_pressure_relief(struct _malloc_zone_t *zone, size_t goal) { + return 0; +} + +static size_t +zone_good_size(malloc_zone_t *zone, size_t size) { + if (size == 0) { + size = 1; + } + return sz_s2u(size); +} + +static kern_return_t +zone_enumerator(task_t task, void *data, unsigned type_mask, + vm_address_t zone_address, memory_reader_t reader, + vm_range_recorder_t recorder) { + return KERN_SUCCESS; +} + +static boolean_t +zone_check(malloc_zone_t *zone) { + return true; +} + +static void +zone_print(malloc_zone_t *zone, boolean_t verbose) { +} + +static void +zone_log(malloc_zone_t *zone, void *address) { +} + +static void +zone_force_lock(malloc_zone_t *zone) { + if (isthreaded) { + /* + * See the note in zone_force_unlock, below, to see why we need + * this. + */ + assert(zone_force_lock_pid == -1); + zone_force_lock_pid = getpid(); + jemalloc_prefork(); + } +} + +static void +zone_force_unlock(malloc_zone_t *zone) { + /* + * zone_force_lock and zone_force_unlock are the entry points to the + * forking machinery on OS X. The tricky thing is, the child is not + * allowed to unlock mutexes locked in the parent, even if owned by the + * forking thread (and the mutex type we use in OS X will fail an assert + * if we try). In the child, we can get away with reinitializing all + * the mutexes, which has the effect of unlocking them. In the parent, + * doing this would mean we wouldn't wake any waiters blocked on the + * mutexes we unlock. So, we record the pid of the current thread in + * zone_force_lock, and use that to detect if we're in the parent or + * child here, to decide which unlock logic we need. + */ + if (isthreaded) { + assert(zone_force_lock_pid != -1); + if (getpid() == zone_force_lock_pid) { + jemalloc_postfork_parent(); + } else { + jemalloc_postfork_child(); + } + zone_force_lock_pid = -1; + } +} + +static void +zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { + /* We make no effort to actually fill the values */ + stats->blocks_in_use = 0; + stats->size_in_use = 0; + stats->max_size_in_use = 0; + stats->size_allocated = 0; +} + +static boolean_t +zone_locked(malloc_zone_t *zone) { + /* Pretend no lock is being held */ + return false; +} + +static void +zone_reinit_lock(malloc_zone_t *zone) { + /* As of OSX 10.12, this function is only used when force_unlock would + * be used if the zone version were < 9. So just use force_unlock. */ + zone_force_unlock(zone); +} + +static void +zone_init(void) { + jemalloc_zone.size = zone_size; + jemalloc_zone.malloc = zone_malloc; + jemalloc_zone.calloc = zone_calloc; + jemalloc_zone.valloc = zone_valloc; + jemalloc_zone.free = zone_free; + jemalloc_zone.realloc = zone_realloc; + jemalloc_zone.destroy = zone_destroy; + jemalloc_zone.zone_name = "jemalloc_zone"; + jemalloc_zone.batch_malloc = zone_batch_malloc; + jemalloc_zone.batch_free = zone_batch_free; + jemalloc_zone.introspect = &jemalloc_zone_introspect; + jemalloc_zone.version = 9; + jemalloc_zone.memalign = zone_memalign; + jemalloc_zone.free_definite_size = zone_free_definite_size; + jemalloc_zone.pressure_relief = zone_pressure_relief; + + jemalloc_zone_introspect.enumerator = zone_enumerator; + jemalloc_zone_introspect.good_size = zone_good_size; + jemalloc_zone_introspect.check = zone_check; + jemalloc_zone_introspect.print = zone_print; + jemalloc_zone_introspect.log = zone_log; + jemalloc_zone_introspect.force_lock = zone_force_lock; + jemalloc_zone_introspect.force_unlock = zone_force_unlock; + jemalloc_zone_introspect.statistics = zone_statistics; + jemalloc_zone_introspect.zone_locked = zone_locked; + jemalloc_zone_introspect.enable_discharge_checking = NULL; + jemalloc_zone_introspect.disable_discharge_checking = NULL; + jemalloc_zone_introspect.discharge = NULL; +#ifdef __BLOCKS__ + jemalloc_zone_introspect.enumerate_discharged_pointers = NULL; +#else + jemalloc_zone_introspect.enumerate_unavailable_without_blocks = NULL; +#endif + jemalloc_zone_introspect.reinit_lock = zone_reinit_lock; +} + +static malloc_zone_t * +zone_default_get(void) { + malloc_zone_t **zones = NULL; + unsigned int num_zones = 0; + + /* + * On OSX 10.12, malloc_default_zone returns a special zone that is not + * present in the list of registered zones. That zone uses a "lite zone" + * if one is present (apparently enabled when malloc stack logging is + * enabled), or the first registered zone otherwise. In practice this + * means unless malloc stack logging is enabled, the first registered + * zone is the default. So get the list of zones to get the first one, + * instead of relying on malloc_default_zone. + */ + if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, + (vm_address_t**)&zones, &num_zones)) { + /* + * Reset the value in case the failure happened after it was + * set. + */ + num_zones = 0; + } + + if (num_zones) { + return zones[0]; + } + + return malloc_default_zone(); +} + +/* As written, this function can only promote jemalloc_zone. */ +static void +zone_promote(void) { + malloc_zone_t *zone; + + do { + /* + * Unregister and reregister the default zone. On OSX >= 10.6, + * unregistering takes the last registered zone and places it + * at the location of the specified zone. Unregistering the + * default zone thus makes the last registered one the default. + * On OSX < 10.6, unregistering shifts all registered zones. + * The first registered zone then becomes the default. + */ + malloc_zone_unregister(default_zone); + malloc_zone_register(default_zone); + + /* + * On OSX 10.6, having the default purgeable zone appear before + * the default zone makes some things crash because it thinks it + * owns the default zone allocated pointers. We thus + * unregister/re-register it in order to ensure it's always + * after the default zone. On OSX < 10.6, there is no purgeable + * zone, so this does nothing. On OSX >= 10.6, unregistering + * replaces the purgeable zone with the last registered zone + * above, i.e. the default zone. Registering it again then puts + * it at the end, obviously after the default zone. + */ + if (purgeable_zone != NULL) { + malloc_zone_unregister(purgeable_zone); + malloc_zone_register(purgeable_zone); + } + + zone = zone_default_get(); + } while (zone != &jemalloc_zone); +} + +JEMALLOC_ATTR(constructor) +void +zone_register(void) { + /* + * If something else replaced the system default zone allocator, don't + * register jemalloc's. + */ + default_zone = zone_default_get(); + if (!default_zone->zone_name || strcmp(default_zone->zone_name, + "DefaultMallocZone") != 0) { + return; + } + + /* + * The default purgeable zone is created lazily by OSX's libc. It uses + * the default zone when it is created for "small" allocations + * (< 15 KiB), but assumes the default zone is a scalable_zone. This + * obviously fails when the default zone is the jemalloc zone, so + * malloc_default_purgeable_zone() is called beforehand so that the + * default purgeable zone is created when the default zone is still + * a scalable_zone. As purgeable zones only exist on >= 10.6, we need + * to check for the existence of malloc_default_purgeable_zone() at + * run time. + */ + purgeable_zone = (malloc_default_purgeable_zone == NULL) ? NULL : + malloc_default_purgeable_zone(); + + /* Register the custom zone. At this point it won't be the default. */ + zone_init(); + malloc_zone_register(&jemalloc_zone); + + /* Promote the custom zone to be default. */ + zone_promote(); +} diff --git a/extension/jemalloc/jemalloc_config.py b/extension/jemalloc/jemalloc_config.py index 873b8bb4300..6dedff00ecc 100644 --- a/extension/jemalloc/jemalloc_config.py +++ b/extension/jemalloc/jemalloc_config.py @@ -1,4 +1,5 @@ import os +import platform # list all include directories include_directories = [ @@ -9,67 +10,68 @@ os.path.sep.join(x.split('/')) for x in [ 'extension/jemalloc/jemalloc_extension.cpp', - 'extension/jemalloc/jemalloc/src/arena.cpp', - 'extension/jemalloc/jemalloc/src/background_thread.cpp', - 'extension/jemalloc/jemalloc/src/base.cpp', - 'extension/jemalloc/jemalloc/src/bin.cpp', - 'extension/jemalloc/jemalloc/src/bin_info.cpp', - 'extension/jemalloc/jemalloc/src/bitmap.cpp', - 'extension/jemalloc/jemalloc/src/buf_writer.cpp', - 'extension/jemalloc/jemalloc/src/cache_bin.cpp', - 'extension/jemalloc/jemalloc/src/ckh.cpp', - 'extension/jemalloc/jemalloc/src/counter.cpp', - 'extension/jemalloc/jemalloc/src/ctl.cpp', - 'extension/jemalloc/jemalloc/src/decay.cpp', - 'extension/jemalloc/jemalloc/src/div.cpp', - 'extension/jemalloc/jemalloc/src/ecache.cpp', - 'extension/jemalloc/jemalloc/src/edata.cpp', - 'extension/jemalloc/jemalloc/src/edata_cache.cpp', - 'extension/jemalloc/jemalloc/src/ehooks.cpp', - 'extension/jemalloc/jemalloc/src/emap.cpp', - 'extension/jemalloc/jemalloc/src/eset.cpp', - 'extension/jemalloc/jemalloc/src/exp_grow.cpp', - 'extension/jemalloc/jemalloc/src/extent.cpp', - 'extension/jemalloc/jemalloc/src/extent_dss.cpp', - 'extension/jemalloc/jemalloc/src/extent_mmap.cpp', - 'extension/jemalloc/jemalloc/src/fxp.cpp', - 'extension/jemalloc/jemalloc/src/hook.cpp', - 'extension/jemalloc/jemalloc/src/hpa.cpp', - 'extension/jemalloc/jemalloc/src/hpa_hooks.cpp', - 'extension/jemalloc/jemalloc/src/hpdata.cpp', - 'extension/jemalloc/jemalloc/src/inspect.cpp', - 'extension/jemalloc/jemalloc/src/jemalloc.cpp', - 'extension/jemalloc/jemalloc/src/large.cpp', - 'extension/jemalloc/jemalloc/src/log.cpp', - 'extension/jemalloc/jemalloc/src/malloc_io.cpp', - 'extension/jemalloc/jemalloc/src/mutex.cpp', - 'extension/jemalloc/jemalloc/src/nstime.cpp', - 'extension/jemalloc/jemalloc/src/pa.cpp', - 'extension/jemalloc/jemalloc/src/pa_extra.cpp', - 'extension/jemalloc/jemalloc/src/pac.cpp', - 'extension/jemalloc/jemalloc/src/pages.cpp', - 'extension/jemalloc/jemalloc/src/pai.cpp', - 'extension/jemalloc/jemalloc/src/peak_event.cpp', - 'extension/jemalloc/jemalloc/src/prof.cpp', - 'extension/jemalloc/jemalloc/src/prof_data.cpp', - 'extension/jemalloc/jemalloc/src/prof_log.cpp', - 'extension/jemalloc/jemalloc/src/prof_recent.cpp', - 'extension/jemalloc/jemalloc/src/prof_stats.cpp', - 'extension/jemalloc/jemalloc/src/prof_sys.cpp', - 'extension/jemalloc/jemalloc/src/psset.cpp', - 'extension/jemalloc/jemalloc/src/rtree.cpp', - 'extension/jemalloc/jemalloc/src/safety_check.cpp', - 'extension/jemalloc/jemalloc/src/san.cpp', - 'extension/jemalloc/jemalloc/src/san_bump.cpp', - 'extension/jemalloc/jemalloc/src/sc.cpp', - 'extension/jemalloc/jemalloc/src/sec.cpp', - 'extension/jemalloc/jemalloc/src/stats.cpp', - 'extension/jemalloc/jemalloc/src/sz.cpp', - 'extension/jemalloc/jemalloc/src/tcache.cpp', - 'extension/jemalloc/jemalloc/src/test_hooks.cpp', - 'extension/jemalloc/jemalloc/src/thread_event.cpp', - 'extension/jemalloc/jemalloc/src/ticker.cpp', - 'extension/jemalloc/jemalloc/src/tsd.cpp', - 'extension/jemalloc/jemalloc/src/witness.cpp', + 'extension/jemalloc/jemalloc/src/jemalloc.c', + 'extension/jemalloc/jemalloc/src/arena.c', + 'extension/jemalloc/jemalloc/src/background_thread.c', + 'extension/jemalloc/jemalloc/src/base.c', + 'extension/jemalloc/jemalloc/src/bin.c', + 'extension/jemalloc/jemalloc/src/bin_info.c', + 'extension/jemalloc/jemalloc/src/bitmap.c', + 'extension/jemalloc/jemalloc/src/buf_writer.c', + 'extension/jemalloc/jemalloc/src/cache_bin.c', + 'extension/jemalloc/jemalloc/src/ckh.c', + 'extension/jemalloc/jemalloc/src/counter.c', + 'extension/jemalloc/jemalloc/src/ctl.c', + 'extension/jemalloc/jemalloc/src/decay.c', + 'extension/jemalloc/jemalloc/src/div.c', + 'extension/jemalloc/jemalloc/src/ecache.c', + 'extension/jemalloc/jemalloc/src/edata.c', + 'extension/jemalloc/jemalloc/src/edata_cache.c', + 'extension/jemalloc/jemalloc/src/ehooks.c', + 'extension/jemalloc/jemalloc/src/emap.c', + 'extension/jemalloc/jemalloc/src/eset.c', + 'extension/jemalloc/jemalloc/src/exp_grow.c', + 'extension/jemalloc/jemalloc/src/extent.c', + 'extension/jemalloc/jemalloc/src/extent_dss.c', + 'extension/jemalloc/jemalloc/src/extent_mmap.c', + 'extension/jemalloc/jemalloc/src/fxp.c', + 'extension/jemalloc/jemalloc/src/san.c', + 'extension/jemalloc/jemalloc/src/san_bump.c', + 'extension/jemalloc/jemalloc/src/hook.c', + 'extension/jemalloc/jemalloc/src/hpa.c', + 'extension/jemalloc/jemalloc/src/hpa_hooks.c', + 'extension/jemalloc/jemalloc/src/hpdata.c', + 'extension/jemalloc/jemalloc/src/inspect.c', + 'extension/jemalloc/jemalloc/src/large.c', + 'extension/jemalloc/jemalloc/src/log.c', + 'extension/jemalloc/jemalloc/src/malloc_io.c', + 'extension/jemalloc/jemalloc/src/mutex.c', + 'extension/jemalloc/jemalloc/src/nstime.c', + 'extension/jemalloc/jemalloc/src/pa.c', + 'extension/jemalloc/jemalloc/src/pa_extra.c', + 'extension/jemalloc/jemalloc/src/pai.c', + 'extension/jemalloc/jemalloc/src/pac.c', + 'extension/jemalloc/jemalloc/src/pages.c', + 'extension/jemalloc/jemalloc/src/peak_event.c', + 'extension/jemalloc/jemalloc/src/prof.c', + 'extension/jemalloc/jemalloc/src/prof_data.c', + 'extension/jemalloc/jemalloc/src/prof_log.c', + 'extension/jemalloc/jemalloc/src/prof_recent.c', + 'extension/jemalloc/jemalloc/src/prof_stats.c', + 'extension/jemalloc/jemalloc/src/prof_sys.c', + 'extension/jemalloc/jemalloc/src/psset.c', + 'extension/jemalloc/jemalloc/src/rtree.c', + 'extension/jemalloc/jemalloc/src/safety_check.c', + 'extension/jemalloc/jemalloc/src/sc.c', + 'extension/jemalloc/jemalloc/src/sec.c', + 'extension/jemalloc/jemalloc/src/stats.c', + 'extension/jemalloc/jemalloc/src/sz.c', + 'extension/jemalloc/jemalloc/src/tcache.c', + 'extension/jemalloc/jemalloc/src/test_hooks.c', + 'extension/jemalloc/jemalloc/src/thread_event.c', + 'extension/jemalloc/jemalloc/src/ticker.c', + 'extension/jemalloc/jemalloc/src/tsd.c', + 'extension/jemalloc/jemalloc/src/util.c', + 'extension/jemalloc/jemalloc/src/witness.c', ] ] diff --git a/extension/jemalloc/jemalloc_extension.cpp b/extension/jemalloc/jemalloc_extension.cpp index 596f58157fa..a51d7c371bb 100644 --- a/extension/jemalloc/jemalloc_extension.cpp +++ b/extension/jemalloc/jemalloc_extension.cpp @@ -4,10 +4,6 @@ #include "duckdb/common/allocator.hpp" #include "jemalloc/jemalloc.h" -#ifndef DUCKDB_NO_THREADS -#include "duckdb/common/thread.hpp" -#endif - namespace duckdb { void JemallocExtension::Load(DuckDB &db) { @@ -19,20 +15,20 @@ std::string JemallocExtension::Name() { } data_ptr_t JemallocExtension::Allocate(PrivateAllocatorData *private_data, idx_t size) { - return data_ptr_cast(duckdb_jemalloc::je_malloc(size)); + return data_ptr_cast(duckdb_je_malloc(size)); } void JemallocExtension::Free(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t size) { - duckdb_jemalloc::je_free(pointer); + duckdb_je_free(pointer); } data_ptr_t JemallocExtension::Reallocate(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t old_size, idx_t size) { - return data_ptr_cast(duckdb_jemalloc::je_realloc(pointer, size)); + return data_ptr_cast(duckdb_je_realloc(pointer, size)); } static void JemallocCTL(const char *name, void *old_ptr, size_t *old_len, void *new_ptr, size_t new_len) { - if (duckdb_jemalloc::je_mallctl(name, old_ptr, old_len, new_ptr, new_len) != 0) { + if (duckdb_je_mallctl(name, old_ptr, old_len, new_ptr, new_len) != 0) { #ifdef DEBUG // We only want to throw an exception here when debugging throw InternalException("je_mallctl failed for setting \"%s\"", name); @@ -42,7 +38,7 @@ static void JemallocCTL(const char *name, void *old_ptr, size_t *old_len, void * template static void SetJemallocCTL(const char *name, T &val) { - JemallocCTL(name, &val, sizeof(T)); + JemallocCTL(name, nullptr, nullptr, &val, sizeof(T)); } static void SetJemallocCTL(const char *name) { @@ -57,9 +53,17 @@ static T GetJemallocCTL(const char *name) { return result; } +static inline string PurgeArenaString(idx_t arena_idx) { + return StringUtil::Format("arena.%llu.purge", arena_idx); +} + +int64_t JemallocExtension::DecayDelay() { + return DUCKDB_DECAY_DELAY; +} + void JemallocExtension::ThreadFlush(idx_t threshold) { // We flush after exceeding the threshold - if (GetJemallocCTL("thread.peak.read") < threshold) { + if (GetJemallocCTL("thread.peak.read") > threshold) { return; } @@ -67,25 +71,45 @@ void JemallocExtension::ThreadFlush(idx_t threshold) { SetJemallocCTL("thread.tcache.flush"); // Flush this thread's arena - const auto purge_arena = StringUtil::Format("arena.%llu.purge", idx_t(GetJemallocCTL("thread.arena"))); + const auto purge_arena = PurgeArenaString(idx_t(GetJemallocCTL("thread.arena"))); SetJemallocCTL(purge_arena.c_str()); // Reset the peak after resetting SetJemallocCTL("thread.peak.reset"); } +void JemallocExtension::ThreadIdle() { + // Indicate that this thread is idle + SetJemallocCTL("thread.idle"); + + // Reset the peak after resetting + SetJemallocCTL("thread.peak.reset"); +} + void JemallocExtension::FlushAll() { // Flush thread-local cache SetJemallocCTL("thread.tcache.flush"); // Flush all arenas - const auto purge_arena = StringUtil::Format("arena.%llu.purge", MALLCTL_ARENAS_ALL); + const auto purge_arena = PurgeArenaString(MALLCTL_ARENAS_ALL); SetJemallocCTL(purge_arena.c_str()); // Reset the peak after resetting SetJemallocCTL("thread.peak.reset"); } +void JemallocExtension::SetBackgroundThreads(bool enable) { + SetJemallocCTL("background_thread", enable); +} + +std::string JemallocExtension::Version() const { +#ifdef EXT_VERSION_JEMALLOC + return EXT_VERSION_JEMALLOC; +#else + return ""; +#endif +} + } // namespace duckdb extern "C" { diff --git a/extension/json/CMakeLists.txt b/extension/json/CMakeLists.txt index 0068703cc62..4101111df8c 100644 --- a/extension/json/CMakeLists.txt +++ b/extension/json/CMakeLists.txt @@ -1,10 +1,8 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(JSONExtension) -include_directories(yyjson/include) include_directories(include) -add_subdirectory(yyjson) add_subdirectory(json_functions) set(JSON_EXTENSION_FILES @@ -31,8 +29,7 @@ set(JSON_EXTENSION_FILES json_functions/json_serialize_sql.cpp json_functions/json_serialize_plan.cpp json_functions/read_json.cpp - json_functions/read_json_objects.cpp - ${YYJSON_OBJECT_FILES}) + json_functions/read_json_objects.cpp) build_static_extension(json ${JSON_EXTENSION_FILES}) set(PARAMETERS "-warnings") diff --git a/extension/json/include/json.json b/extension/json/include/json.json index 8b182dec927..4bababcb069 100644 --- a/extension/json/include/json.json +++ b/extension/json/include/json.json @@ -153,6 +153,12 @@ "name": "convert_strings_to_integers", "type": "bool", "default": false + }, + { + "id": 116, + "name": "map_inference_threshold", + "type": "idx_t", + "default": 25 } ], "constructor": ["$ClientContext", "files", "date_format", "timestamp_format"] diff --git a/extension/json/include/json_common.hpp b/extension/json/include/json_common.hpp index 1e7da02f0c8..bcc8d7c23db 100644 --- a/extension/json/include/json_common.hpp +++ b/extension/json/include/json_common.hpp @@ -14,6 +14,8 @@ #include "duckdb/planner/expression/bound_function_expression.hpp" #include "yyjson.hpp" +using namespace duckdb_yyjson; // NOLINT + namespace duckdb { //! JSON allocator is a custom allocator for yyjson that prevents many tiny allocations @@ -108,6 +110,7 @@ struct JSONCommon { switch (yyjson_get_tag(val)) { case YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE: return JSONCommon::TYPE_STRING_NULL; + case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC: case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: return JSONCommon::TYPE_STRING_VARCHAR; case YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE: @@ -136,6 +139,7 @@ struct JSONCommon { switch (yyjson_get_tag(val)) { case YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE: return LogicalTypeId::SQLNULL; + case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC: case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: return LogicalTypeId::VARCHAR; case YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE: @@ -286,7 +290,8 @@ struct JSONCommon { private: //! Get JSON pointer (/field/index/... syntax) static inline yyjson_val *GetPointer(yyjson_val *val, const char *ptr, const idx_t &len) { - return len == 1 ? val : unsafe_yyjson_get_pointer(val, ptr, len); + yyjson_ptr_err err; + return len == 1 ? val : unsafe_yyjson_ptr_getx(val, ptr, len, &err); } //! Get JSON path ($.field[index]... syntax) static yyjson_val *GetPath(yyjson_val *val, const char *ptr, const idx_t &len); diff --git a/extension/json/include/json_executors.hpp b/extension/json/include/json_executors.hpp index 334170ee73b..78da4526842 100644 --- a/extension/json/include/json_executors.hpp +++ b/extension/json/include/json_executors.hpp @@ -30,7 +30,7 @@ struct JSONExecutors { } //! Two-argument JSON read function (with path query), i.e. json_type('[1, 2, 3]', '$[0]') - template + template static void BinaryExecute(DataChunk &args, ExpressionState &state, Vector &result, std::function fun) { auto &func_expr = state.expr.Cast(); @@ -48,7 +48,7 @@ struct JSONExecutors { auto doc = JSONCommon::ReadDocument(input, JSONCommon::READ_FLAG, lstate.json_allocator.GetYYAlc()); auto val = JSONCommon::GetUnsafe(doc->root, ptr, len); - if (!val || unsafe_yyjson_is_null(val)) { + if (!val || (NULL_IF_NULL && unsafe_yyjson_is_null(val))) { mask.SetInvalid(idx); return T {}; } else { @@ -76,7 +76,7 @@ struct JSONExecutors { for (idx_t i = 0; i < vals.size(); i++) { auto &val = vals[i]; D_ASSERT(val != nullptr); // Wildcard extract shouldn't give back nullptrs - if (unsafe_yyjson_is_null(val)) { + if (NULL_IF_NULL && unsafe_yyjson_is_null(val)) { child_validity.SetInvalid(current_size + i); } else { child_vals[current_size + i] = fun(val, alc, result); @@ -109,7 +109,7 @@ struct JSONExecutors { } //! JSON read function with list of path queries, i.e. json_type('[1, 2, 3]', ['$[0]', '$[1]']) - template + template static void ExecuteMany(DataChunk &args, ExpressionState &state, Vector &result, std::function fun) { auto &func_expr = state.expr.Cast(); @@ -148,7 +148,7 @@ struct JSONExecutors { for (idx_t path_i = 0; path_i < num_paths; path_i++) { auto child_idx = offset + path_i; val = JSONCommon::GetUnsafe(doc->root, info.ptrs[path_i], info.lens[path_i]); - if (!val || unsafe_yyjson_is_null(val)) { + if (!val || (NULL_IF_NULL && unsafe_yyjson_is_null(val))) { child_validity.SetInvalid(child_idx); } else { child_data[child_idx] = fun(val, alc, child); diff --git a/extension/json/include/json_extension.hpp b/extension/json/include/json_extension.hpp index f5b9a2e429e..421fb6f608d 100644 --- a/extension/json/include/json_extension.hpp +++ b/extension/json/include/json_extension.hpp @@ -16,6 +16,7 @@ class JsonExtension : public Extension { public: void Load(DuckDB &db) override; std::string Name() override; + std::string Version() const override; }; } // namespace duckdb diff --git a/extension/json/include/json_functions.hpp b/extension/json/include/json_functions.hpp index 4f7f26b272c..51fae296b58 100644 --- a/extension/json/include/json_functions.hpp +++ b/extension/json/include/json_functions.hpp @@ -70,8 +70,8 @@ class JSONFunctions { static vector GetScalarFunctions(); static vector GetPragmaFunctions(); static vector GetTableFunctions(); - static unique_ptr ReadJSONReplacement(ClientContext &context, const string &table_name, - ReplacementScanData *data); + static unique_ptr ReadJSONReplacement(ClientContext &context, ReplacementScanInput &input, + optional_ptr data); static TableFunction GetReadJSONTableFunction(shared_ptr function_info); static CopyFunction GetJSONCopyFunction(); static void RegisterSimpleCastFunctions(CastFunctionSet &casts); diff --git a/extension/json/include/json_scan.hpp b/extension/json/include/json_scan.hpp index 1e0b9dc2d9b..9dc96ed438f 100644 --- a/extension/json/include/json_scan.hpp +++ b/extension/json/include/json_scan.hpp @@ -124,12 +124,15 @@ struct JSONScanData : public TableFunctionData { idx_t max_depth = NumericLimits::Maximum(); //! We divide the number of appearances of each JSON field by the auto-detection sample size //! If the average over the fields of an object is less than this threshold, - //! we default to the JSON type for this object rather than the shredded type + //! we default to the MAP type with value type of merged field types double field_appearance_threshold = 0.1; //! The maximum number of files we sample to sample sample_size rows idx_t maximum_sample_files = 32; //! Whether we auto-detect and convert JSON strings to integers bool convert_strings_to_integers = false; + //! If a struct contains more fields than this threshold with at least 80% similar types, + //! we infer it as MAP type + idx_t map_inference_threshold = 25; //! All column names (in order) vector names; diff --git a/extension/json/include/json_serializer.hpp b/extension/json/include/json_serializer.hpp index d8f80a50554..aa17f3ffd16 100644 --- a/extension/json/include/json_serializer.hpp +++ b/extension/json/include/json_serializer.hpp @@ -27,8 +27,8 @@ struct JsonSerializer : Serializer { public: explicit JsonSerializer(yyjson_mut_doc *doc, bool skip_if_null, bool skip_if_empty, bool skip_if_default) : doc(doc), stack({yyjson_mut_obj(doc)}), skip_if_null(skip_if_null), skip_if_empty(skip_if_empty) { - serialize_enum_as_string = true; - serialize_default_values = !skip_if_default; + options.serialize_enum_as_string = true; + options.serialize_default_values = !skip_if_default; } template diff --git a/extension/json/include/json_structure.hpp b/extension/json/include/json_structure.hpp index 1f0087778d7..216c05112d1 100644 --- a/extension/json/include/json_structure.hpp +++ b/extension/json/include/json_structure.hpp @@ -82,8 +82,9 @@ struct JSONStructure { public: static void ExtractStructure(yyjson_val *val, JSONStructureNode &node, const bool ignore_errors); static LogicalType StructureToType(ClientContext &context, const JSONStructureNode &node, const idx_t max_depth, - const double field_appearance_threshold, idx_t depth = 0, - idx_t sample_count = DConstants::INVALID_INDEX); + const double field_appearance_threshold, idx_t map_inference_threshold, + idx_t depth = 0, idx_t sample_count = DConstants::INVALID_INDEX, + const LogicalType &null_type = LogicalType::JSON()); }; } // namespace duckdb diff --git a/extension/json/json_common.cpp b/extension/json/json_common.cpp index 65e5ba721ed..edb961e26b0 100644 --- a/extension/json/json_common.cpp +++ b/extension/json/json_common.cpp @@ -1,4 +1,5 @@ #include "json_common.hpp" + #include "duckdb/common/exception/binder_exception.hpp" namespace duckdb { @@ -31,16 +32,58 @@ string ThrowPathError(const char *ptr, const char *end, const bool binder) { } } -static inline idx_t ReadString(const char *ptr, const char *const end, const bool escaped) { +struct JSONKeyReadResult { +public: + static inline JSONKeyReadResult Empty() { + return {idx_t(0), string()}; + } + + static inline JSONKeyReadResult WildCard() { + return {1, "*"}; + } + + inline bool IsValid() { + return chars_read != 0; + } + + inline bool IsWildCard() { + return key == "*"; + } + +public: + idx_t chars_read; + string key; +}; + +static inline JSONKeyReadResult ReadString(const char *ptr, const char *const end, const bool escaped) { const char *const before = ptr; if (escaped) { + auto key = make_unsafe_uniq_array(end - ptr); + idx_t key_len = 0; + + bool backslash = false; while (ptr != end) { - if (*ptr == '"') { - break; + if (backslash) { + if (*ptr != '"' && *ptr != '\\') { + key[key_len++] = '\\'; + } + backslash = false; + } else { + if (*ptr == '"') { + break; + } else if (*ptr == '\\') { + backslash = true; + ptr++; + continue; + } } - ptr++; + key[key_len++] = *ptr++; + } + if (ptr == end || backslash) { + return JSONKeyReadResult::Empty(); + } else { + return {idx_t(ptr - before), string(key.get(), key_len)}; } - return ptr == end ? 0 : ptr - before; } else { while (ptr != end) { if (*ptr == '.' || *ptr == '[') { @@ -48,7 +91,7 @@ static inline idx_t ReadString(const char *ptr, const char *const end, const boo } ptr++; } - return ptr - before; + return {idx_t(ptr - before), string(before, ptr - before)}; } } @@ -79,28 +122,24 @@ static inline idx_t ReadInteger(const char *ptr, const char *const end, idx_t &i return idx >= (idx_t)IDX_T_MAX ? 0 : ptr - before; } -static inline bool ReadKey(const char *&ptr, const char *const end, const char *&key_ptr, idx_t &key_len) { +static inline JSONKeyReadResult ReadKey(const char *ptr, const char *const end) { D_ASSERT(ptr != end); if (*ptr == '*') { // Wildcard - ptr++; - key_len = DConstants::INVALID_INDEX; - return true; + return JSONKeyReadResult::WildCard(); } bool escaped = false; if (*ptr == '"') { ptr++; // Skip past opening '"' escaped = true; } - key_ptr = ptr; - key_len = ReadString(ptr, end, escaped); - if (key_len == 0) { - return false; + auto result = ReadString(ptr, end, escaped); + if (!result.IsValid()) { + return result; } - ptr += key_len; if (escaped) { - ptr++; // Skip past closing '"' + result.chars_read += 2; // Account for surrounding quotes } - return true; + return result; } static inline bool ReadArrayIndex(const char *&ptr, const char *const end, idx_t &array_index, bool &from_back) { @@ -155,14 +194,13 @@ JSONPathType JSONCommon::ValidatePath(const char *ptr, const idx_t &len, const b } switch (c) { case '.': { // Object field - const char *key_ptr; - idx_t key_len; - if (!ReadKey(ptr, end, key_ptr, key_len)) { + auto key = ReadKey(ptr, end); + if (!key.IsValid()) { ThrowPathError(ptr, end, binder); - } - if (key_len == DConstants::INVALID_INDEX) { + } else if (key.IsWildCard()) { path_type = JSONPathType::WILDCARD; } + ptr += key.chars_read; break; } case '[': { // Array index @@ -195,16 +233,10 @@ yyjson_val *JSONCommon::GetPath(yyjson_val *val, const char *ptr, const idx_t &l if (!unsafe_yyjson_is_obj(val)) { return nullptr; } - const char *key_ptr; - idx_t key_len; -#ifdef DEBUG - bool success = -#endif - ReadKey(ptr, end, key_ptr, key_len); -#ifdef DEBUG - D_ASSERT(success); -#endif - val = yyjson_obj_getn(val, key_ptr, key_len); + auto key_result = ReadKey(ptr, end); + D_ASSERT(key_result.IsValid()); + ptr += key_result.chars_read; + val = yyjson_obj_getn(val, key_result.key.c_str(), key_result.key.size()); break; } case '[': { // Array index @@ -243,16 +275,10 @@ void GetWildcardPathInternal(yyjson_val *val, const char *ptr, const char *const if (!unsafe_yyjson_is_obj(val)) { return; } - const char *key_ptr; - idx_t key_len; -#ifdef DEBUG - bool success = -#endif - ReadKey(ptr, end, key_ptr, key_len); -#ifdef DEBUG - D_ASSERT(success); -#endif - if (key_len == DConstants::INVALID_INDEX) { // Wildcard + auto key_result = ReadKey(ptr, end); + D_ASSERT(key_result.IsValid()); + ptr += key_result.chars_read; + if (key_result.IsWildCard()) { // Wildcard size_t idx, max; yyjson_val *key, *obj_val; yyjson_obj_foreach(val, idx, max, key, obj_val) { @@ -260,7 +286,7 @@ void GetWildcardPathInternal(yyjson_val *val, const char *ptr, const char *const } return; } - val = yyjson_obj_getn(val, key_ptr, key_len); + val = yyjson_obj_getn(val, key_result.key.c_str(), key_result.key.size()); break; } case '[': { // Array index diff --git a/extension/json/json_config.py b/extension/json/json_config.py index 9ac16e272ef..16a1195a79a 100644 --- a/extension/json/json_config.py +++ b/extension/json/json_config.py @@ -1,9 +1,7 @@ import os # list all include directories -include_directories = [ - os.path.sep.join(x.split('/')) for x in ['extension/json/include', 'extension/json/yyjson/include'] -] +include_directories = [os.path.sep.join(x.split('/')) for x in ['extension/json/include']] # source files source_files = [ os.path.sep.join(x.split('/')) @@ -27,7 +25,6 @@ 'extension/json/json_functions/json_valid.cpp', 'extension/json/json_functions/read_json_objects.cpp', 'extension/json/json_functions/read_json.cpp', - 'extension/json/yyjson/yyjson.cpp', 'extension/json/json_functions/json_serialize_plan.cpp', 'extension/json/json_functions/json_serialize_sql.cpp', 'extension/json/json_serializer.cpp', diff --git a/extension/json/json_extension.cpp b/extension/json/json_extension.cpp index 88671d30e36..07bba320611 100644 --- a/extension/json/json_extension.cpp +++ b/extension/json/json_extension.cpp @@ -68,6 +68,14 @@ std::string JsonExtension::Name() { return "json"; } +std::string JsonExtension::Version() const { +#ifdef EXT_VERSION_JSON + return EXT_VERSION_JSON; +#else + return ""; +#endif +} + } // namespace duckdb extern "C" { diff --git a/extension/json/json_functions.cpp b/extension/json/json_functions.cpp index e8241d6e35f..a4c818bcecf 100644 --- a/extension/json/json_functions.cpp +++ b/extension/json/json_functions.cpp @@ -16,7 +16,7 @@ using JSONPathType = JSONCommon::JSONPathType; static JSONPathType CheckPath(const Value &path_val, string &path, size_t &len) { if (path_val.IsNull()) { - throw InternalException("JSON path cannot be NULL"); + throw BinderException("JSON path cannot be NULL"); } const auto path_str_val = path_val.DefaultCastAs(LogicalType::VARCHAR); auto path_str = path_str_val.GetValueUnsafe(); @@ -194,8 +194,9 @@ vector JSONFunctions::GetTableFunctions() { return functions; } -unique_ptr JSONFunctions::ReadJSONReplacement(ClientContext &context, const string &table_name, - ReplacementScanData *data) { +unique_ptr JSONFunctions::ReadJSONReplacement(ClientContext &context, ReplacementScanInput &input, + optional_ptr data) { + auto &table_name = input.table_name; if (!ReplacementScan::CanReplace(table_name, {"json", "jsonl", "ndjson"})) { return nullptr; } diff --git a/extension/json/json_functions/copy_json.cpp b/extension/json/json_functions/copy_json.cpp index 4744e5a78c8..d6cdb84706c 100644 --- a/extension/json/json_functions/copy_json.cpp +++ b/extension/json/json_functions/copy_json.cpp @@ -19,14 +19,14 @@ static void ThrowJSONCopyParameterException(const string &loption) { static BoundStatement CopyToJSONPlan(Binder &binder, CopyStatement &stmt) { auto stmt_copy = stmt.Copy(); auto © = stmt_copy->Cast(); - auto &info = *copy.info; + auto &copied_info = *copy.info; // Parse the options, creating options for the CSV writer while doing so string date_format; string timestamp_format; // We insert the JSON file extension here so it works properly with PER_THREAD_OUTPUT/FILE_SIZE_BYTES etc. case_insensitive_map_t> csv_copy_options {{"file_extension", {"json"}}}; - for (const auto &kv : info.options) { + for (const auto &kv : copied_info.options) { const auto &loption = StringUtil::Lower(kv.first); if (loption == "dateformat" || loption == "date_format") { if (kv.second.size() != 1) { @@ -58,16 +58,17 @@ static BoundStatement CopyToJSONPlan(Binder &binder, CopyStatement &stmt) { } // Bind the select statement of the original to resolve the types - auto dummy_binder = Binder::CreateBinder(binder.context, &binder, true); - auto bound_original = dummy_binder->Bind(*stmt.select_statement); + auto dummy_binder = Binder::CreateBinder(binder.context, &binder); + auto bound_original = dummy_binder->Bind(*stmt.info->select_statement); // Create new SelectNode with the original SelectNode as a subquery in the FROM clause auto select_stmt = make_uniq(); - select_stmt->node = std::move(copy.select_statement); + select_stmt->node = std::move(copied_info.select_statement); auto subquery_ref = make_uniq(std::move(select_stmt)); - copy.select_statement = make_uniq_base(); - auto &new_select_node = copy.select_statement->Cast(); - new_select_node.from_table = std::move(subquery_ref); + + copied_info.select_statement = make_uniq_base(); + auto &select_node = copied_info.select_statement->Cast(); + select_node.from_table = std::move(subquery_ref); // Create new select list vector> select_list; @@ -95,18 +96,17 @@ static BoundStatement CopyToJSONPlan(Binder &binder, CopyStatement &stmt) { } // Now create the struct_pack/to_json to create a JSON object per row - auto &select_node = copy.select_statement->Cast(); vector> struct_pack_child; struct_pack_child.emplace_back(make_uniq("struct_pack", std::move(select_list))); select_node.select_list.emplace_back(make_uniq("to_json", std::move(struct_pack_child))); // Now we can just use the CSV writer - info.format = "csv"; - info.options = std::move(csv_copy_options); - info.options["quote"] = {""}; - info.options["escape"] = {""}; - info.options["delimiter"] = {"\n"}; - info.options["header"] = {{0}}; + copied_info.format = "csv"; + copied_info.options = std::move(csv_copy_options); + copied_info.options["quote"] = {""}; + copied_info.options["escape"] = {""}; + copied_info.options["delimiter"] = {"\n"}; + copied_info.options["header"] = {{0}}; return binder.Bind(*stmt_copy); } diff --git a/extension/json/json_functions/json_create.cpp b/extension/json/json_functions/json_create.cpp index 2167ae902e5..ca58033b97b 100644 --- a/extension/json/json_functions/json_create.cpp +++ b/extension/json/json_functions/json_create.cpp @@ -313,8 +313,10 @@ static void CreateValuesMap(const StructNames &names, yyjson_mut_doc *doc, yyjso // Create nested keys auto &map_key_v = MapVector::GetKeys(value_v); auto map_key_count = ListVector::GetListSize(value_v); + Vector map_keys_string(LogicalType::VARCHAR, map_key_count); + VectorOperations::DefaultCast(map_key_v, map_keys_string, map_key_count); auto nested_keys = JSONCommon::AllocateArray(doc, map_key_count); - TemplatedCreateValues(doc, nested_keys, map_key_v, map_key_count); + TemplatedCreateValues(doc, nested_keys, map_keys_string, map_key_count); // Create nested values auto &map_val_v = MapVector::GetValues(value_v); auto map_val_count = ListVector::GetListSize(value_v); @@ -747,7 +749,7 @@ void JSONFunctions::RegisterJSONCreateCastFunctions(CastFunctionSet &casts) { source_type = LogicalType::UNION({{"any", LogicalType::ANY}}); break; case LogicalTypeId::ARRAY: - source_type = LogicalType::ARRAY(LogicalType::ANY); + source_type = LogicalType::ARRAY(LogicalType::ANY, optional_idx()); break; case LogicalTypeId::VARCHAR: // We skip this one here as it's handled in json_functions.cpp diff --git a/extension/json/json_functions/json_structure.cpp b/extension/json/json_functions/json_structure.cpp index 0fd574f898e..36e93780f88 100644 --- a/extension/json/json_functions/json_structure.cpp +++ b/extension/json/json_functions/json_structure.cpp @@ -5,6 +5,8 @@ #include "json_scan.hpp" #include "json_transform.hpp" +#include + namespace duckdb { static inline bool IsNumeric(LogicalTypeId type) { @@ -388,27 +390,37 @@ static inline void ExtractStructureObject(yyjson_val *obj, JSONStructureNode &no auto &description = node.GetOrCreateDescription(LogicalTypeId::STRUCT); // Keep track of keys so we can detect duplicates - case_insensitive_set_t obj_keys; + unordered_set obj_keys; + case_insensitive_set_t ci_obj_keys; size_t idx, max; yyjson_val *key, *val; yyjson_obj_foreach(obj, idx, max, key, val) { - auto key_ptr = unsafe_yyjson_get_str(key); - auto key_len = unsafe_yyjson_get_len(key); - auto insert_result = obj_keys.insert(string(key_ptr, key_len)); - if (!ignore_errors && !insert_result.second) { - JSONCommon::ThrowValFormatError("Duplicate key \"" + string(key_ptr, key_len) + "\" in object %s", obj); + const string obj_key(unsafe_yyjson_get_str(key), unsafe_yyjson_get_len(key)); + auto insert_result = obj_keys.insert(obj_key); + if (!ignore_errors && !insert_result.second) { // Exact match + JSONCommon::ThrowValFormatError("Duplicate key \"" + obj_key + "\" in object %s", obj); + } + insert_result = ci_obj_keys.insert(obj_key); + if (!ignore_errors && !insert_result.second) { // Case-insensitive match + JSONCommon::ThrowValFormatError("Duplicate key (different case) \"" + obj_key + "\" and \"" + + *insert_result.first + "\" in object %s", + obj); } description.GetOrCreateChild(key, val, ignore_errors); } } -static inline void ExtractStructureVal(yyjson_val *val, JSONStructureNode &node, const bool ignore_errors) { +static inline void ExtractStructureVal(yyjson_val *val, JSONStructureNode &node) { D_ASSERT(!yyjson_is_arr(val) && !yyjson_is_obj(val)); node.GetOrCreateDescription(JSONCommon::ValTypeToLogicalTypeId(val)); } void JSONStructure::ExtractStructure(yyjson_val *val, JSONStructureNode &node, const bool ignore_errors) { + if (!val) { + return; + } + node.count++; switch (yyjson_get_tag(val)) { case YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE: @@ -416,7 +428,7 @@ void JSONStructure::ExtractStructure(yyjson_val *val, JSONStructureNode &node, c case YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE: return ExtractStructureObject(val, node, ignore_errors); default: - return ExtractStructureVal(val, node, ignore_errors); + return ExtractStructureVal(val, node); } } @@ -475,9 +487,9 @@ static inline yyjson_mut_val *ConvertStructure(const JSONStructureNode &node, yy } } -static inline string_t JSONStructureFunction(yyjson_val *val, yyjson_alc *alc, Vector &result) { +static inline string_t JSONStructureFunction(yyjson_val *val, yyjson_alc *alc, Vector &) { return JSONCommon::WriteVal( - ConvertStructure(ExtractStructureInternal(val, false), yyjson_mut_doc_new(alc)), alc); + ConvertStructure(ExtractStructureInternal(val, true), yyjson_mut_doc_new(alc)), alc); } static void StructureFunction(DataChunk &args, ExpressionState &state, Vector &result) { @@ -497,46 +509,235 @@ ScalarFunctionSet JSONFunctions::GetStructureFunction() { } static LogicalType StructureToTypeArray(ClientContext &context, const JSONStructureNode &node, const idx_t max_depth, - const double field_appearance_threshold, idx_t depth, - const idx_t sample_count) { + const double field_appearance_threshold, const idx_t map_inference_threshold, + idx_t depth, const idx_t sample_count, const LogicalType &null_type) { D_ASSERT(node.descriptions.size() == 1 && node.descriptions[0].type == LogicalTypeId::LIST); const auto &desc = node.descriptions[0]; D_ASSERT(desc.children.size() == 1); - return LogicalType::LIST(JSONStructure::StructureToType( - context, desc.children[0], max_depth, field_appearance_threshold, depth + 1, desc.children[0].count)); + return LogicalType::LIST(JSONStructure::StructureToType(context, desc.children[0], max_depth, + field_appearance_threshold, map_inference_threshold, + depth + 1, desc.children[0].count, null_type)); +} + +static void MergeNodes(JSONStructureNode &merged, const JSONStructureNode &node, const idx_t max_depth, + const idx_t depth) { + if (depth >= max_depth) { + merged.GetOrCreateDescription(LogicalTypeId::SQLNULL); + return; + } + + merged.count += node.count; + for (const auto &desc : node.descriptions) { + D_ASSERT(desc.type != LogicalTypeId::INVALID); + switch (desc.type) { + case LogicalTypeId::LIST: { + auto &merged_description = merged.GetOrCreateDescription(LogicalTypeId::LIST); + auto &merged_child = merged_description.GetOrCreateChild(); + for (const auto &child_desc : desc.children) { + MergeNodes(merged_child, child_desc, max_depth, depth + 1); + } + break; + } + case LogicalTypeId::STRUCT: { + auto &merged_description = merged.GetOrCreateDescription(LogicalTypeId::STRUCT); + for (const auto &child_desc : desc.children) { + yyjson_val key {}; + yyjson_set_strn(&key, child_desc.key->c_str(), child_desc.key->length()); + auto &merged_child = merged_description.GetOrCreateChild(&key, nullptr, false); + MergeNodes(merged_child, child_desc, max_depth, depth + 1); + } + break; + } + default: { + const auto &prev_size = merged.descriptions.size(); + const bool prev_was_null = prev_size == 1 && merged.descriptions[0].type == LogicalTypeId::SQLNULL; + auto &merged_desc = merged.GetOrCreateDescription(desc.type); + if (desc.type == LogicalTypeId::SQLNULL) { + break; + } + + if (prev_was_null || prev_size != merged.descriptions.size()) { + // New non-null description, copy the last candidate type + if (!desc.candidate_types.empty()) { + merged_desc.candidate_types = {desc.candidate_types.back()}; + } + } else if (!merged_desc.candidate_types.empty() && + (desc.candidate_types.empty() || + merged_desc.candidate_types.back() != desc.candidate_types.back())) { + // Remove candidate type since it is not equal to the last candidate type of desc + merged_desc.candidate_types.clear(); + } + } + } + } +} + +static const LogicalType &GetMapValueType(const LogicalType &map) { + D_ASSERT(map.id() == LogicalTypeId::MAP); + return map.AuxInfo()->Cast().child_type.AuxInfo()->Cast().child_types[1].second; +} + +static double CalculateTypeSimilarity(const LogicalType &merged, const LogicalType &type, idx_t max_depth, idx_t depth); + +static double CalculateMapAndStructSimilarity(const LogicalType &map_type, const LogicalType &struct_type, + const bool swapped, const idx_t max_depth, const idx_t depth) { + const auto &map_value_type = GetMapValueType(map_type); + const auto &struct_child_types = struct_type.AuxInfo()->Cast().child_types; + double total_similarity = 0; + for (const auto &struct_child_type : struct_child_types) { + const auto similarity = + swapped ? CalculateTypeSimilarity(struct_child_type.second, map_value_type, max_depth, depth + 1) + : CalculateTypeSimilarity(map_value_type, struct_child_type.second, max_depth, depth + 1); + if (similarity < 0) { + return similarity; + } + total_similarity += similarity; + } + return total_similarity / static_cast(struct_child_types.size()); +} + +static double CalculateTypeSimilarity(const LogicalType &merged, const LogicalType &type, const idx_t max_depth, + const idx_t depth) { + if (depth >= max_depth || merged == LogicalTypeId::SQLNULL) { + return 1; + } + if (merged.IsJSONType()) { + // Incompatible types + return -1; + } + if (type.IsJSONType() || merged == type) { + return 1; + } + + switch (merged.id()) { + case LogicalTypeId::STRUCT: { + if (type.id() == LogicalTypeId::MAP) { + // This can happen for empty structs/maps ("{}"), or in rare cases where an inconsistent struct becomes + // consistent when merged, but does not have enough children to be considered a map. + return CalculateMapAndStructSimilarity(type, merged, true, max_depth, depth); + } + + // Only structs can be merged into a struct + D_ASSERT(type.id() == LogicalTypeId::STRUCT); + const auto &merged_child_types = merged.AuxInfo()->Cast().child_types; + const auto &type_child_types = type.AuxInfo()->Cast().child_types; + + unordered_map merged_child_types_map; + for (const auto &merged_child : merged_child_types) { + merged_child_types_map.emplace(merged_child.first, merged_child.second); + } + + double total_similarity = 0; + for (const auto &type_child_type : type_child_types) { + const auto it = merged_child_types_map.find(type_child_type.first); + // All struct keys should be present in the merged struct + D_ASSERT(it != merged_child_types_map.end()); + const auto similarity = CalculateTypeSimilarity(it->second, type_child_type.second, max_depth, depth + 1); + if (similarity < 0) { + return similarity; + } + total_similarity += similarity; + } + return total_similarity / static_cast(merged_child_types.size()); + } + case LogicalTypeId::MAP: { + if (type.id() == LogicalTypeId::MAP) { + return CalculateTypeSimilarity(GetMapValueType(merged), GetMapValueType(type), max_depth, depth + 1); + } + + // Only maps and structs can be merged into a map + D_ASSERT(type.id() == LogicalTypeId::STRUCT); + return CalculateMapAndStructSimilarity(merged, type, false, max_depth, depth); + } + case LogicalTypeId::LIST: { + // Only lists can be merged into a list + D_ASSERT(type.id() == LogicalTypeId::LIST); + const auto &merged_child_type = merged.AuxInfo()->Cast().child_type; + const auto &type_child_type = type.AuxInfo()->Cast().child_type; + return CalculateTypeSimilarity(merged_child_type, type_child_type, max_depth, depth + 1); + } + default: + // This is only reachable if type has been inferred using candidate_types, but candidate_types were not + // consistent among all map values + return 1; + } +} + +static bool IsStructureInconsistent(const JSONStructureDescription &desc, const idx_t sample_count, + const double field_appearance_threshold) { + double total_child_counts = 0; + for (const auto &child : desc.children) { + total_child_counts += static_cast(child.count) / static_cast(sample_count); + } + const auto avg_occurrence = total_child_counts / static_cast(desc.children.size()); + return avg_occurrence < field_appearance_threshold; +} + +static LogicalType GetMergedType(ClientContext &context, const JSONStructureDescription &desc, const idx_t max_depth, + const double field_appearance_threshold, const idx_t map_inference_threshold, + const idx_t depth, const LogicalType &null_type) { + JSONStructureNode merged; + for (const auto &child : desc.children) { + MergeNodes(merged, child, max_depth, depth + 1); + } + return JSONStructure::StructureToType(context, merged, max_depth, field_appearance_threshold, + map_inference_threshold, depth + 1, merged.count, null_type); } static LogicalType StructureToTypeObject(ClientContext &context, const JSONStructureNode &node, const idx_t max_depth, - const double field_appearance_threshold, idx_t depth, - const idx_t sample_count) { + const double field_appearance_threshold, const idx_t map_inference_threshold, + idx_t depth, const idx_t sample_count, const LogicalType &null_type) { D_ASSERT(node.descriptions.size() == 1 && node.descriptions[0].type == LogicalTypeId::STRUCT); auto &desc = node.descriptions[0]; - // If it's an empty struct we do JSON instead + // If it's an empty struct we do MAP of JSON instead if (desc.children.empty()) { - // Empty struct - let's do JSON instead - return LogicalType::JSON(); + // Empty struct - let's do MAP of JSON instead + return LogicalType::MAP(LogicalType::VARCHAR, null_type); } - // If it's an inconsistent object we also just do JSON - double total_child_counts = 0; - for (const auto &child : desc.children) { - total_child_counts += double(child.count) / sample_count; - } - const auto avg_occurrence = total_child_counts / desc.children.size(); - if (avg_occurrence < field_appearance_threshold) { - return LogicalType::JSON(); + // If it's an inconsistent object we also just do MAP with the best-possible, recursively-merged value type + if (IsStructureInconsistent(desc, sample_count, field_appearance_threshold)) { + return LogicalType::MAP(LogicalType::VARCHAR, + GetMergedType(context, desc, max_depth, field_appearance_threshold, + map_inference_threshold, depth + 1, null_type)); } + // We have a consistent object child_list_t child_types; child_types.reserve(desc.children.size()); for (auto &child : desc.children) { D_ASSERT(child.key); - child_types.emplace_back(*child.key, - JSONStructure::StructureToType(context, child, max_depth, field_appearance_threshold, - depth + 1, sample_count)); + child_types.emplace_back( + *child.key, JSONStructure::StructureToType(context, child, max_depth, field_appearance_threshold, + map_inference_threshold, depth + 1, sample_count, null_type)); + } + + // If we have many children and all children have similar-enough types we infer map + if (desc.children.size() >= map_inference_threshold) { + LogicalType map_value_type = GetMergedType(context, desc, max_depth, field_appearance_threshold, + map_inference_threshold, depth + 1, LogicalTypeId::SQLNULL); + + double total_similarity = 0; + for (const auto &child_type : child_types) { + const auto similarity = CalculateTypeSimilarity(map_value_type, child_type.second, max_depth, depth + 1); + if (similarity < 0) { + total_similarity = similarity; + break; + } + total_similarity += similarity; + } + const auto avg_similarity = total_similarity / static_cast(child_types.size()); + if (avg_similarity >= 0.8) { + if (null_type != LogicalTypeId::SQLNULL) { + map_value_type = GetMergedType(context, desc, max_depth, field_appearance_threshold, + map_inference_threshold, depth + 1, null_type); + } + return LogicalType::MAP(LogicalType::VARCHAR, map_value_type); + } } + return LogicalType::STRUCT(child_types); } @@ -550,12 +751,13 @@ static LogicalType StructureToTypeString(const JSONStructureNode &node) { } LogicalType JSONStructure::StructureToType(ClientContext &context, const JSONStructureNode &node, const idx_t max_depth, - const double field_appearance_threshold, idx_t depth, idx_t sample_count) { + const double field_appearance_threshold, const idx_t map_inference_threshold, + idx_t depth, idx_t sample_count, const LogicalType &null_type) { if (depth >= max_depth) { return LogicalType::JSON(); } if (node.descriptions.empty()) { - return LogicalType::JSON(); + return null_type; } if (node.descriptions.size() != 1) { // Inconsistent types, so we resort to JSON return LogicalType::JSON(); @@ -565,15 +767,17 @@ LogicalType JSONStructure::StructureToType(ClientContext &context, const JSONStr D_ASSERT(desc.type != LogicalTypeId::INVALID); switch (desc.type) { case LogicalTypeId::LIST: - return StructureToTypeArray(context, node, max_depth, field_appearance_threshold, depth, sample_count); + return StructureToTypeArray(context, node, max_depth, field_appearance_threshold, map_inference_threshold, + depth, sample_count, null_type); case LogicalTypeId::STRUCT: - return StructureToTypeObject(context, node, max_depth, field_appearance_threshold, depth, sample_count); + return StructureToTypeObject(context, node, max_depth, field_appearance_threshold, map_inference_threshold, + depth, sample_count, null_type); case LogicalTypeId::VARCHAR: return StructureToTypeString(node); - case LogicalTypeId::SQLNULL: - return LogicalType::JSON(); case LogicalTypeId::UBIGINT: return LogicalTypeId::BIGINT; // We prefer not to return UBIGINT in our type auto-detection + case LogicalTypeId::SQLNULL: + return null_type; default: return desc.type; } diff --git a/extension/json/json_functions/json_transform.cpp b/extension/json/json_functions/json_transform.cpp index 7aa0345b7d4..d1f1caa1116 100644 --- a/extension/json/json_functions/json_transform.cpp +++ b/extension/json/json_functions/json_transform.cpp @@ -59,6 +59,7 @@ static LogicalType StructureStringToType(yyjson_val *val, ClientContext &context return StructureStringToTypeArray(val, context); case YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE: return StructureToTypeObject(val, context); + case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC: case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: return TransformStringToLogicalType(unsafe_yyjson_get_str(val), context); default: @@ -99,6 +100,7 @@ static inline bool GetValueNumerical(yyjson_val *val, T &result, JSONTransformOp D_ASSERT(unsafe_yyjson_get_tag(val) != (YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE)); bool success; switch (unsafe_yyjson_get_tag(val)) { + case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC: case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: success = OP::template Operation(GetString(val), result, options.strict_cast); break; @@ -134,6 +136,7 @@ static inline bool GetValueDecimal(yyjson_val *val, T &result, uint8_t w, uint8_ D_ASSERT(unsafe_yyjson_get_tag(val) != (YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE)); bool success; switch (unsafe_yyjson_get_tag(val)) { + case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC: case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: success = OP::template Operation(GetString(val), result, options.parameters, w, s); break; @@ -167,6 +170,7 @@ static inline bool GetValueDecimal(yyjson_val *val, T &result, uint8_t w, uint8_ static inline bool GetValueString(yyjson_val *val, yyjson_alc *alc, string_t &result, Vector &vector) { D_ASSERT(unsafe_yyjson_get_tag(val) != (YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE)); switch (unsafe_yyjson_get_tag(val)) { + case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC: case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: result = string_t(unsafe_yyjson_get_str(val), unsafe_yyjson_get_len(val)); return true; @@ -1008,7 +1012,7 @@ void JSONFunctions::RegisterJSONTransformCastFunctions(CastFunctionSet &casts) { target_type = LogicalType::UNION({{"any", LogicalType::ANY}}); break; case LogicalTypeId::ARRAY: - target_type = LogicalType::ARRAY(LogicalType::ANY); + target_type = LogicalType::ARRAY(LogicalType::ANY, optional_idx()); break; case LogicalTypeId::VARCHAR: // We skip this one here as it's handled in json_functions.cpp diff --git a/extension/json/json_functions/json_type.cpp b/extension/json/json_functions/json_type.cpp index b1e9dbcc2d4..8f3fb3ad972 100644 --- a/extension/json/json_functions/json_type.cpp +++ b/extension/json/json_functions/json_type.cpp @@ -11,11 +11,11 @@ static void UnaryTypeFunction(DataChunk &args, ExpressionState &state, Vector &r } static void BinaryTypeFunction(DataChunk &args, ExpressionState &state, Vector &result) { - JSONExecutors::BinaryExecute(args, state, result, GetType); + JSONExecutors::BinaryExecute(args, state, result, GetType); } static void ManyTypeFunction(DataChunk &args, ExpressionState &state, Vector &result) { - JSONExecutors::ExecuteMany(args, state, result, GetType); + JSONExecutors::ExecuteMany(args, state, result, GetType); } static void GetTypeFunctionsInternal(ScalarFunctionSet &set, const LogicalType &input_type) { diff --git a/extension/json/json_functions/read_json.cpp b/extension/json/json_functions/read_json.cpp index e207060a448..9976eef8814 100644 --- a/extension/json/json_functions/read_json.cpp +++ b/extension/json/json_functions/read_json.cpp @@ -99,8 +99,8 @@ void JSONScan::AutoDetect(ClientContext &context, JSONScanData &bind_data, vecto bind_data.type = JSONScanType::READ_JSON; // Convert structure to logical type - auto type = - JSONStructure::StructureToType(context, node, bind_data.max_depth, bind_data.field_appearance_threshold); + auto type = JSONStructure::StructureToType(context, node, bind_data.max_depth, bind_data.field_appearance_threshold, + bind_data.map_inference_threshold); // Auto-detect record type if (bind_data.options.record_type == JSONRecordType::AUTO_DETECT) { @@ -196,6 +196,16 @@ unique_ptr ReadJSONBind(ClientContext &context, TableFunctionBindI "read_json_auto \"field_appearance_threshold\" parameter must be between 0 and 1"); } bind_data->field_appearance_threshold = arg; + } else if (loption == "map_inference_threshold") { + auto arg = BigIntValue::Get(kv.second); + if (arg == -1) { + bind_data->map_inference_threshold = NumericLimits::Maximum(); + } else if (arg >= 0) { + bind_data->map_inference_threshold = arg; + } else { + throw BinderException("read_json_auto \"map_inference_threshold\" parameter must be 0 or positive, " + "or -1 to disable map inference for consistent objects."); + } } else if (loption == "dateformat" || loption == "date_format") { auto format_string = StringValue::Get(kv.second); if (StringUtil::Lower(format_string) == "iso") { @@ -277,8 +287,10 @@ unique_ptr ReadJSONBind(ClientContext &context, TableFunctionBindI D_ASSERT(return_types.size() == names.size()); } - bind_data->reader_bind = - MultiFileReader::BindOptions(bind_data->options.file_options, bind_data->files, return_types, names); + SimpleMultiFileList file_list(std::move(bind_data->files)); + MultiFileReader().BindOptions(bind_data->options.file_options, file_list, return_types, names, + bind_data->reader_bind); + bind_data->files = file_list.GetAllFiles(); auto &transform_options = bind_data->transform_options; transform_options.strict_cast = !bind_data->ignore_errors; @@ -345,7 +357,7 @@ static void ReadJSONFunction(ClientContext &context, TableFunctionInput &data_p, } if (output.size() != 0) { - MultiFileReader::FinalizeChunk(gstate.bind_data.reader_bind, lstate.GetReaderData(), output); + MultiFileReader().FinalizeChunk(context, gstate.bind_data.reader_bind, lstate.GetReaderData(), output, nullptr); } } @@ -378,6 +390,7 @@ TableFunctionSet CreateJSONFunctionInfo(string name, shared_ptr in table_function.named_parameters["maximum_depth"] = LogicalType::BIGINT; table_function.named_parameters["field_appearance_threshold"] = LogicalType::DOUBLE; table_function.named_parameters["convert_strings_to_integers"] = LogicalType::BOOLEAN; + table_function.named_parameters["map_inference_threshold"] = LogicalType::BIGINT; return MultiFileReader::CreateFunctionSet(table_function); } diff --git a/extension/json/json_functions/read_json_objects.cpp b/extension/json/json_functions/read_json_objects.cpp index 630c2e69468..46d4e7982f8 100644 --- a/extension/json/json_functions/read_json_objects.cpp +++ b/extension/json/json_functions/read_json_objects.cpp @@ -14,8 +14,10 @@ unique_ptr ReadJSONObjectsBind(ClientContext &context, TableFuncti return_types.push_back(LogicalType::JSON()); names.emplace_back("json"); - bind_data->reader_bind = - MultiFileReader::BindOptions(bind_data->options.file_options, bind_data->files, return_types, names); + SimpleMultiFileList file_list(std::move(bind_data->files)); + MultiFileReader().BindOptions(bind_data->options.file_options, file_list, return_types, names, + bind_data->reader_bind); + bind_data->files = file_list.GetAllFiles(); return std::move(bind_data); } @@ -45,7 +47,7 @@ static void ReadJSONObjectsFunction(ClientContext &context, TableFunctionInput & output.SetCardinality(count); if (output.size() != 0) { - MultiFileReader::FinalizeChunk(gstate.bind_data.reader_bind, lstate.GetReaderData(), output); + MultiFileReader().FinalizeChunk(context, gstate.bind_data.reader_bind, lstate.GetReaderData(), output, nullptr); } } diff --git a/extension/json/json_scan.cpp b/extension/json/json_scan.cpp index b6989b6b3f0..f406e162b90 100644 --- a/extension/json/json_scan.cpp +++ b/extension/json/json_scan.cpp @@ -29,7 +29,7 @@ void JSONScanData::Bind(ClientContext &context, TableFunctionBindInput &input) { auto_detect = info.auto_detect; for (auto &kv : input.named_parameters) { - if (MultiFileReader::ParseOption(kv.first, kv.second, options.file_options, context)) { + if (MultiFileReader().ParseOption(kv.first, kv.second, options.file_options, context)) { continue; } auto loption = StringUtil::Lower(kv.first); @@ -60,8 +60,12 @@ void JSONScanData::Bind(ClientContext &context, TableFunctionBindInput &input) { } } - files = MultiFileReader::GetFileList(context, input.inputs[0], "JSON"); - options.file_options.AutoDetectHivePartitioning(files, context); + auto multi_file_reader = MultiFileReader::Create(input.table_function); + auto file_list = multi_file_reader->CreateFileList(context, input.inputs[0]); + options.file_options.AutoDetectHivePartitioning(*file_list, context); + + // TODO: store the MultiFilelist instead + files = file_list->GetAllFiles(); InitializeReaders(context); } @@ -201,9 +205,9 @@ unique_ptr JSONGlobalTableFunctionState::Init(ClientCo vector dummy_types(input.column_ids.size(), LogicalType::ANY); for (auto &reader : gstate.json_readers) { - MultiFileReader::FinalizeBind(reader->GetOptions().file_options, gstate.bind_data.reader_bind, - reader->GetFileName(), gstate.names, dummy_types, bind_data.names, - input.column_ids, reader->reader_data, context); + MultiFileReader().FinalizeBind(reader->GetOptions().file_options, gstate.bind_data.reader_bind, + reader->GetFileName(), gstate.names, dummy_types, bind_data.names, + input.column_ids, reader->reader_data, context, nullptr); } return std::move(result); @@ -973,10 +977,16 @@ unique_ptr JSONScan::Cardinality(ClientContext &, const Function void JSONScan::ComplexFilterPushdown(ClientContext &context, LogicalGet &get, FunctionData *bind_data_p, vector> &filters) { auto &data = bind_data_p->Cast(); - auto reset_reader = - MultiFileReader::ComplexFilterPushdown(context, data.files, data.options.file_options, get, filters); - if (reset_reader) { - MultiFileReader::PruneReaders(data); + + SimpleMultiFileList file_list(std::move(data.files)); + + auto filtered_list = + MultiFileReader().ComplexFilterPushdown(context, file_list, data.options.file_options, get, filters); + if (filtered_list) { + MultiFileReader().PruneReaders(data, *filtered_list); + data.files = filtered_list->GetAllFiles(); + } else { + data.files = file_list.GetAllFiles(); } } @@ -995,7 +1005,7 @@ unique_ptr JSONScan::Deserialize(Deserializer &deserializer, Table } void JSONScan::TableFunctionDefaults(TableFunction &table_function) { - MultiFileReader::AddParameters(table_function); + MultiFileReader().AddParameters(table_function); table_function.named_parameters["maximum_object_size"] = LogicalType::UINTEGER; table_function.named_parameters["ignore_errors"] = LogicalType::BOOLEAN; diff --git a/extension/json/serialize_json.cpp b/extension/json/serialize_json.cpp index c45ffc2f51a..a9263fa5957 100644 --- a/extension/json/serialize_json.cpp +++ b/extension/json/serialize_json.cpp @@ -44,6 +44,7 @@ void JSONScanData::Serialize(Serializer &serializer) const { serializer.WritePropertyWithDefault(113, "field_appearance_threshold", field_appearance_threshold, 0.1); serializer.WritePropertyWithDefault(114, "maximum_sample_files", maximum_sample_files, 32); serializer.WritePropertyWithDefault(115, "convert_strings_to_integers", convert_strings_to_integers, false); + serializer.WritePropertyWithDefault(116, "map_inference_threshold", map_inference_threshold, 25); } unique_ptr JSONScanData::Deserialize(Deserializer &deserializer) { @@ -74,6 +75,7 @@ unique_ptr JSONScanData::Deserialize(Deserializer &deserializer) { deserializer.ReadPropertyWithDefault(113, "field_appearance_threshold", result->field_appearance_threshold, 0.1); deserializer.ReadPropertyWithDefault(114, "maximum_sample_files", result->maximum_sample_files, 32); deserializer.ReadPropertyWithDefault(115, "convert_strings_to_integers", result->convert_strings_to_integers, false); + deserializer.ReadPropertyWithDefault(116, "map_inference_threshold", result->map_inference_threshold, 25); return result; } diff --git a/extension/json/yyjson/CMakeLists.txt b/extension/json/yyjson/CMakeLists.txt deleted file mode 100644 index 35533b952e9..00000000000 --- a/extension/json/yyjson/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -include_directories(include) - -add_library(yyjson OBJECT yyjson.cpp) -set(YYJSON_OBJECT_FILES - ${YYJSON_OBJECT_FILES} $ - PARENT_SCOPE) - -disable_target_warnings(yyjson) diff --git a/extension/parquet/CMakeLists.txt b/extension/parquet/CMakeLists.txt index f4d415dbeeb..89af368aa85 100644 --- a/extension/parquet/CMakeLists.txt +++ b/extension/parquet/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.5...3.29) project(ParquetExtension) @@ -10,7 +10,8 @@ include_directories( ../../third_party/snappy ../../third_party/zstd/include ../../third_party/mbedtls - ../../third_party/mbedtls/include) + ../../third_party/mbedtls/include + ../../third_party/brotli/include) set(PARQUET_EXTENSION_FILES column_reader.cpp @@ -23,7 +24,8 @@ set(PARQUET_EXTENSION_FILES parquet_timestamp.cpp parquet_writer.cpp serialize_parquet.cpp - zstd_file_system.cpp) + zstd_file_system.cpp + geo_parquet.cpp) if(NOT CLANG_TIDY) # parquet/thrift/snappy @@ -60,7 +62,38 @@ if(NOT CLANG_TIDY) ../../third_party/zstd/compress/zstd_fast.cpp ../../third_party/zstd/compress/zstd_lazy.cpp ../../third_party/zstd/compress/zstd_ldm.cpp - ../../third_party/zstd/compress/zstd_opt.cpp) + ../../third_party/zstd/compress/zstd_opt.cpp + ../../third_party/brotli/enc/dictionary_hash.cpp + ../../third_party/brotli/enc/backward_references_hq.cpp + ../../third_party/brotli/enc/histogram.cpp + ../../third_party/brotli/enc/memory.cpp + ../../third_party/brotli/enc/entropy_encode.cpp + ../../third_party/brotli/enc/compound_dictionary.cpp + ../../third_party/brotli/enc/compress_fragment_two_pass.cpp + ../../third_party/brotli/enc/block_splitter.cpp + ../../third_party/brotli/enc/command.cpp + ../../third_party/brotli/enc/encode.cpp + ../../third_party/brotli/enc/encoder_dict.cpp + ../../third_party/brotli/enc/cluster.cpp + ../../third_party/brotli/enc/backward_references.cpp + ../../third_party/brotli/enc/utf8_util.cpp + ../../third_party/brotli/enc/compress_fragment.cpp + ../../third_party/brotli/enc/fast_log.cpp + ../../third_party/brotli/enc/brotli_bit_stream.cpp + ../../third_party/brotli/enc/bit_cost.cpp + ../../third_party/brotli/enc/static_dict.cpp + ../../third_party/brotli/enc/literal_cost.cpp + ../../third_party/brotli/enc/metablock.cpp + ../../third_party/brotli/common/dictionary.cpp + ../../third_party/brotli/common/constants.cpp + ../../third_party/brotli/common/transform.cpp + ../../third_party/brotli/common/platform.cpp + ../../third_party/brotli/common/shared_dictionary.cpp + ../../third_party/brotli/common/context.cpp + ../../third_party/brotli/dec/state.cpp + ../../third_party/brotli/dec/decode.cpp + ../../third_party/brotli/dec/huffman.cpp + ../../third_party/brotli/dec/bit_reader.cpp) endif() build_static_extension(parquet ${PARQUET_EXTENSION_FILES}) diff --git a/extension/parquet/column_reader.cpp b/extension/parquet/column_reader.cpp index 08471fdf3fe..65d5e01c0d4 100644 --- a/extension/parquet/column_reader.cpp +++ b/extension/parquet/column_reader.cpp @@ -1,23 +1,25 @@ #include "column_reader.hpp" #include "boolean_column_reader.hpp" +#include "brotli/decode.h" #include "callback_column_reader.hpp" #include "cast_column_reader.hpp" #include "duckdb.hpp" +#include "expression_column_reader.hpp" #include "list_column_reader.hpp" +#include "lz4.hpp" #include "miniz_wrapper.hpp" +#include "null_column_reader.hpp" #include "parquet_decimal_utils.hpp" #include "parquet_reader.hpp" #include "parquet_timestamp.hpp" #include "row_number_column_reader.hpp" #include "snappy.h" #include "string_column_reader.hpp" -#include "null_column_reader.hpp" #include "struct_column_reader.hpp" #include "templated_column_reader.hpp" #include "utf8proc_wrapper.hpp" #include "zstd.h" -#include "lz4.hpp" #ifndef DUCKDB_AMALGAMATION #include "duckdb/common/helper.hpp" @@ -373,12 +375,26 @@ void ColumnReader::DecompressInternal(CompressionCodec::type codec, const_data_p } break; } + case CompressionCodec::BROTLI: { + auto state = duckdb_brotli::BrotliDecoderCreateInstance(nullptr, nullptr, nullptr); + size_t total_out = 0; + auto src_size_size_t = NumericCast(src_size); + auto dst_size_size_t = NumericCast(dst_size); + + auto res = duckdb_brotli::BrotliDecoderDecompressStream(state, &src_size_size_t, &src, &dst_size_size_t, &dst, + &total_out); + if (res != duckdb_brotli::BROTLI_DECODER_RESULT_SUCCESS) { + throw std::runtime_error("Brotli Decompression failure"); + } + duckdb_brotli::BrotliDecoderDestroyInstance(state); + break; + } default: { std::stringstream codec_name; codec_name << codec; throw std::runtime_error("Unsupported compression codec \"" + codec_name.str() + - "\". Supported options are uncompressed, gzip, lz4_raw, snappy or zstd"); + "\". Supported options are uncompressed, brotli, gzip, lz4_raw, snappy or zstd"); } } } @@ -641,7 +657,7 @@ uint32_t StringColumnReader::VerifyString(const char *str_data, uint32_t str_len void StringColumnReader::Dictionary(shared_ptr data, idx_t num_entries) { dict = std::move(data); - dict_strings = unique_ptr(new string_t[num_entries]); + dict_strings = unsafe_unique_ptr(new string_t[num_entries]); for (idx_t dict_idx = 0; dict_idx < num_entries; dict_idx++) { uint32_t str_len; if (fixed_width_string_length == 0) { @@ -741,7 +757,7 @@ void StringColumnReader::DeltaByteArray(uint8_t *defines, idx_t num_values, parq result_mask.SetInvalid(row_idx + result_offset); continue; } - if (filter[row_idx + result_offset]) { + if (filter.test(row_idx + result_offset)) { if (delta_offset >= byte_array_count) { throw IOException("DELTA_BYTE_ARRAY - length mismatch between values and byte array lengths (attempted " "read of %d from %d entries) - corrupt file?", @@ -773,8 +789,7 @@ void StringColumnReader::PlainReference(shared_ptr plain_data, Vecto } string_t StringParquetValueConversion::DictRead(ByteBuffer &dict, uint32_t &offset, ColumnReader &reader) { - auto &dict_strings = reader.Cast().dict_strings; - return dict_strings[offset]; + return reader.Cast().dict_strings[offset]; } string_t StringParquetValueConversion::PlainRead(ByteBuffer &plain_data, ColumnReader &reader) { @@ -794,6 +809,18 @@ void StringParquetValueConversion::PlainSkip(ByteBuffer &plain_data, ColumnReade plain_data.inc(str_len); } +bool StringParquetValueConversion::PlainAvailable(const ByteBuffer &plain_data, const idx_t count) { + return true; +} + +string_t StringParquetValueConversion::UnsafePlainRead(ByteBuffer &plain_data, ColumnReader &reader) { + return PlainRead(plain_data, reader); +} + +void StringParquetValueConversion::UnsafePlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { + PlainSkip(plain_data, reader); +} + //===--------------------------------------------------------------------===// // List Column Reader //===--------------------------------------------------------------------===// @@ -1010,7 +1037,7 @@ idx_t CastColumnReader::Read(uint64_t num_values, parquet_filter_t &filter, data intermediate_vector.Flatten(amount); auto &validity = FlatVector::Validity(intermediate_vector); for (idx_t i = 0; i < amount; i++) { - if (!filter[i]) { + if (!filter.test(i)) { validity.SetInvalid(i); } } @@ -1043,6 +1070,59 @@ idx_t CastColumnReader::GroupRowsAvailable() { return child_reader->GroupRowsAvailable(); } +//===--------------------------------------------------------------------===// +// Expression Column Reader +//===--------------------------------------------------------------------===// +ExpressionColumnReader::ExpressionColumnReader(ClientContext &context, unique_ptr child_reader_p, + unique_ptr expr_p) + : ColumnReader(child_reader_p->Reader(), expr_p->return_type, child_reader_p->Schema(), child_reader_p->FileIdx(), + child_reader_p->MaxDefine(), child_reader_p->MaxRepeat()), + child_reader(std::move(child_reader_p)), expr(std::move(expr_p)), executor(context, expr.get()) { + vector intermediate_types {child_reader->Type()}; + intermediate_chunk.Initialize(reader.allocator, intermediate_types); +} + +unique_ptr ExpressionColumnReader::Stats(idx_t row_group_idx_p, const vector &columns) { + // expression stats is not supported (yet) + return nullptr; +} + +void ExpressionColumnReader::InitializeRead(idx_t row_group_idx_p, const vector &columns, + TProtocol &protocol_p) { + child_reader->InitializeRead(row_group_idx_p, columns, protocol_p); +} + +idx_t ExpressionColumnReader::Read(uint64_t num_values, parquet_filter_t &filter, data_ptr_t define_out, + data_ptr_t repeat_out, Vector &result) { + intermediate_chunk.Reset(); + auto &intermediate_vector = intermediate_chunk.data[0]; + + auto amount = child_reader->Read(num_values, filter, define_out, repeat_out, intermediate_vector); + if (!filter.all()) { + // work-around for filters: set all values that are filtered to NULL to prevent the cast from failing on + // uninitialized data + intermediate_vector.Flatten(amount); + auto &validity = FlatVector::Validity(intermediate_vector); + for (idx_t i = 0; i < amount; i++) { + if (!filter[i]) { + validity.SetInvalid(i); + } + } + } + // Execute the expression + intermediate_chunk.SetCardinality(amount); + executor.ExecuteExpression(intermediate_chunk, result); + return amount; +} + +void ExpressionColumnReader::Skip(idx_t num_values) { + child_reader->Skip(num_values); +} + +idx_t ExpressionColumnReader::GroupRowsAvailable() { + return child_reader->GroupRowsAvailable(); +} + //===--------------------------------------------------------------------===// // Struct Column Reader //===--------------------------------------------------------------------===// @@ -1147,8 +1227,7 @@ idx_t StructColumnReader::GroupRowsAvailable() { template struct DecimalParquetValueConversion { static DUCKDB_PHYSICAL_TYPE DictRead(ByteBuffer &dict, uint32_t &offset, ColumnReader &reader) { - auto dict_ptr = reinterpret_cast(dict.ptr); - return dict_ptr[offset]; + return reinterpret_cast(dict.ptr)[offset]; } static DUCKDB_PHYSICAL_TYPE PlainRead(ByteBuffer &plain_data, ColumnReader &reader) { @@ -1170,6 +1249,18 @@ struct DecimalParquetValueConversion { uint32_t decimal_len = FIXED_LENGTH ? reader.Schema().type_length : plain_data.read(); plain_data.inc(decimal_len); } + + static bool PlainAvailable(const ByteBuffer &plain_data, const idx_t count) { + return true; + } + + static DUCKDB_PHYSICAL_TYPE UnsafePlainRead(ByteBuffer &plain_data, ColumnReader &reader) { + return PlainRead(plain_data, reader); + } + + static void UnsafePlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { + PlainSkip(plain_data, reader); + } }; template @@ -1262,8 +1353,7 @@ unique_ptr ParquetDecimalUtils::CreateReader(ParquetReader &reader //===--------------------------------------------------------------------===// struct UUIDValueConversion { static hugeint_t DictRead(ByteBuffer &dict, uint32_t &offset, ColumnReader &reader) { - auto dict_ptr = reinterpret_cast(dict.ptr); - return dict_ptr[offset]; + return reinterpret_cast(dict.ptr)[offset]; } static hugeint_t ReadParquetUUID(const_data_ptr_t input) { @@ -1284,17 +1374,27 @@ struct UUIDValueConversion { } static hugeint_t PlainRead(ByteBuffer &plain_data, ColumnReader &reader) { - idx_t byte_len = sizeof(hugeint_t); - plain_data.available(byte_len); - auto res = ReadParquetUUID(const_data_ptr_cast(plain_data.ptr)); - - plain_data.inc(byte_len); - return res; + plain_data.available(sizeof(hugeint_t)); + return UnsafePlainRead(plain_data, reader); } static void PlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { plain_data.inc(sizeof(hugeint_t)); } + + static bool PlainAvailable(const ByteBuffer &plain_data, const idx_t count) { + return plain_data.check_available(count * sizeof(hugeint_t)); + } + + static hugeint_t UnsafePlainRead(ByteBuffer &plain_data, ColumnReader &reader) { + auto res = ReadParquetUUID(const_data_ptr_cast(plain_data.ptr)); + plain_data.unsafe_inc(sizeof(hugeint_t)); + return res; + } + + static void UnsafePlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { + plain_data.unsafe_inc(sizeof(hugeint_t)); + } }; class UUIDColumnReader : public TemplatedColumnReader { @@ -1322,8 +1422,7 @@ struct IntervalValueConversion { static constexpr const idx_t PARQUET_INTERVAL_SIZE = 12; static interval_t DictRead(ByteBuffer &dict, uint32_t &offset, ColumnReader &reader) { - auto dict_ptr = reinterpret_cast(dict.ptr); - return dict_ptr[offset]; + return reinterpret_cast(dict.ptr)[offset]; } static interval_t ReadParquetInterval(const_data_ptr_t input) { @@ -1335,17 +1434,27 @@ struct IntervalValueConversion { } static interval_t PlainRead(ByteBuffer &plain_data, ColumnReader &reader) { - idx_t byte_len = PARQUET_INTERVAL_SIZE; - plain_data.available(byte_len); - auto res = ReadParquetInterval(const_data_ptr_cast(plain_data.ptr)); - - plain_data.inc(byte_len); - return res; + plain_data.available(PARQUET_INTERVAL_SIZE); + return UnsafePlainRead(plain_data, reader); } static void PlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { plain_data.inc(PARQUET_INTERVAL_SIZE); } + + static bool PlainAvailable(const ByteBuffer &plain_data, const idx_t count) { + return plain_data.check_available(count * PARQUET_INTERVAL_SIZE); + } + + static interval_t UnsafePlainRead(ByteBuffer &plain_data, ColumnReader &reader) { + auto res = ReadParquetInterval(const_data_ptr_cast(plain_data.ptr)); + plain_data.unsafe_inc(PARQUET_INTERVAL_SIZE); + return res; + } + + static void UnsafePlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { + plain_data.unsafe_inc(PARQUET_INTERVAL_SIZE); + } }; class IntervalColumnReader : public TemplatedColumnReader { @@ -1464,6 +1573,39 @@ unique_ptr ColumnReader::CreateReader(ParquetReader &reader, const break; } break; + case LogicalTypeId::TIMESTAMP_NS: + switch (schema_p.type) { + case Type::INT96: + return make_uniq>( + reader, type_p, schema_p, file_idx_p, max_define, max_repeat); + case Type::INT64: + if (schema_p.__isset.logicalType && schema_p.logicalType.__isset.TIMESTAMP) { + if (schema_p.logicalType.TIMESTAMP.unit.__isset.MILLIS) { + return make_uniq>( + reader, type_p, schema_p, file_idx_p, max_define, max_repeat); + } else if (schema_p.logicalType.TIMESTAMP.unit.__isset.MICROS) { + return make_uniq>( + reader, type_p, schema_p, file_idx_p, max_define, max_repeat); + } else if (schema_p.logicalType.TIMESTAMP.unit.__isset.NANOS) { + return make_uniq>( + reader, type_p, schema_p, file_idx_p, max_define, max_repeat); + } + } else if (schema_p.__isset.converted_type) { + switch (schema_p.converted_type) { + case ConvertedType::TIMESTAMP_MICROS: + return make_uniq>( + reader, type_p, schema_p, file_idx_p, max_define, max_repeat); + case ConvertedType::TIMESTAMP_MILLIS: + return make_uniq>( + reader, type_p, schema_p, file_idx_p, max_define, max_repeat); + default: + break; + } + } + default: + break; + } + break; case LogicalTypeId::DATE: return make_uniq>(reader, type_p, schema_p, file_idx_p, max_define, max_repeat); diff --git a/extension/parquet/column_writer.cpp b/extension/parquet/column_writer.cpp index 99889fd03cf..4f26631d6a7 100644 --- a/extension/parquet/column_writer.cpp +++ b/extension/parquet/column_writer.cpp @@ -4,27 +4,26 @@ #include "parquet_rle_bp_decoder.hpp" #include "parquet_rle_bp_encoder.hpp" #include "parquet_writer.hpp" +#include "geo_parquet.hpp" #ifndef DUCKDB_AMALGAMATION -#include "duckdb/common/common.hpp" #include "duckdb/common/exception.hpp" -#include "duckdb/common/mutex.hpp" #include "duckdb/common/operator/comparison_operators.hpp" #include "duckdb/common/serializer/buffered_file_writer.hpp" #include "duckdb/common/serializer/memory_stream.hpp" #include "duckdb/common/serializer/write_stream.hpp" #include "duckdb/common/string_map_set.hpp" -#include "duckdb/common/types/date.hpp" #include "duckdb/common/types/hugeint.hpp" -#include "duckdb/common/types/string_heap.hpp" #include "duckdb/common/types/time.hpp" #include "duckdb/common/types/timestamp.hpp" #include "duckdb/common/types/uhugeint.hpp" +#include "duckdb/execution/expression_executor.hpp" #endif #include "lz4.hpp" #include "miniz_wrapper.hpp" #include "snappy.h" #include "zstd.h" +#include "brotli/encode.h" namespace duckdb { @@ -69,6 +68,10 @@ static uint8_t GetVarintSize(uint32_t val) { ColumnWriterStatistics::~ColumnWriterStatistics() { } +bool ColumnWriterStatistics::HasStats() { + return false; +} + string ColumnWriterStatistics::GetMin() { return string(); } @@ -234,6 +237,18 @@ void ColumnWriter::CompressPage(MemoryStream &temp_writer, size_t &compressed_si compressed_data = compressed_buf.get(); break; } + case CompressionCodec::BROTLI: { + + compressed_size = duckdb_brotli::BrotliEncoderMaxCompressedSize(temp_writer.GetPosition()); + compressed_buf = unique_ptr(new data_t[compressed_size]); + + duckdb_brotli::BrotliEncoderCompress(BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, + temp_writer.GetPosition(), temp_writer.GetData(), &compressed_size, + compressed_buf.get()); + compressed_data = compressed_buf.get(); + + break; + } default: throw InternalException("Unsupported codec for Parquet Writer"); } @@ -245,7 +260,7 @@ void ColumnWriter::CompressPage(MemoryStream &temp_writer, size_t &compressed_si } void ColumnWriter::HandleRepeatLevels(ColumnWriterState &state, ColumnWriterState *parent, idx_t count, - idx_t max_repeat) { + idx_t max_repeat) const { if (!parent) { // no repeat levels without a parent node return; @@ -255,8 +270,8 @@ void ColumnWriter::HandleRepeatLevels(ColumnWriterState &state, ColumnWriterStat } } -void ColumnWriter::HandleDefineLevels(ColumnWriterState &state, ColumnWriterState *parent, ValidityMask &validity, - idx_t count, uint16_t define_value, uint16_t null_value) { +void ColumnWriter::HandleDefineLevels(ColumnWriterState &state, ColumnWriterState *parent, const ValidityMask &validity, + const idx_t count, const uint16_t define_value, const uint16_t null_value) const { if (parent) { // parent node: inherit definition level from the parent idx_t vector_index = 0; @@ -280,15 +295,12 @@ void ColumnWriter::HandleDefineLevels(ColumnWriterState &state, ColumnWriterStat } else { // no parent: set definition levels only from this validity mask for (idx_t i = 0; i < count; i++) { - if (validity.RowIsValid(i)) { - state.definition_levels.push_back(define_value); - } else { - if (!can_have_nulls) { - throw IOException("Parquet writer: map key column is not allowed to contain NULL values"); - } - state.null_count++; - state.definition_levels.push_back(null_value); - } + const auto is_null = !validity.RowIsValid(i); + state.definition_levels.emplace_back(is_null ? null_value : define_value); + state.null_count += is_null; + } + if (!can_have_nulls && state.null_count != 0) { + throw IOException("Parquet writer: map key column is not allowed to contain NULL values"); } } } @@ -382,8 +394,8 @@ class BasicColumnWriter : public ColumnWriter { void FinalizeWrite(ColumnWriterState &state) override; protected: - void WriteLevels(WriteStream &temp_writer, const vector &levels, idx_t max_value, idx_t start_offset, - idx_t count); + static void WriteLevels(WriteStream &temp_writer, const unsafe_vector &levels, idx_t max_value, + idx_t start_offset, idx_t count); virtual duckdb_parquet::format::Encoding::type GetEncoding(BasicColumnWriterState &state); @@ -400,7 +412,7 @@ class BasicColumnWriter : public ColumnWriter { virtual void FlushPageState(WriteStream &temp_writer, ColumnWriterPageState *state); //! Retrieves the row size of a vector at the specified location. Only used for scalar types. - virtual idx_t GetRowSize(Vector &vector, idx_t index, BasicColumnWriterState &state); + virtual idx_t GetRowSize(const Vector &vector, const idx_t index, const BasicColumnWriterState &state) const; //! Writes a (subset of a) vector to the specified serializer. Only used for scalar types. virtual void WriteVector(WriteStream &temp_writer, ColumnWriterStatistics *stats, ColumnWriterPageState *page_state, Vector &vector, idx_t chunk_start, idx_t chunk_end) = 0; @@ -452,8 +464,9 @@ void BasicColumnWriter::Prepare(ColumnWriterState &state_p, ColumnWriterState *p HandleDefineLevels(state, parent, validity, count, max_define, max_define - 1); idx_t vector_index = 0; + reference page_info_ref = state.page_info.back(); for (idx_t i = start; i < vcount; i++) { - auto &page_info = state.page_info.back(); + auto &page_info = page_info_ref.get(); page_info.row_count++; col_chunk.meta_data.num_values++; if (parent && !parent->is_empty.empty() && parent->is_empty[parent_index + i]) { @@ -466,6 +479,7 @@ void BasicColumnWriter::Prepare(ColumnWriterState &state_p, ColumnWriterState *p PageInformation new_info; new_info.offset = page_info.offset + page_info.row_count; state.page_info.push_back(new_info); + page_info_ref = state.page_info.back(); } } vector_index++; @@ -501,7 +515,8 @@ void BasicColumnWriter::BeginWrite(ColumnWriterState &state_p) { hdr.data_page_header.definition_level_encoding = Encoding::RLE; hdr.data_page_header.repetition_level_encoding = Encoding::RLE; - write_info.temp_writer = make_uniq(); + write_info.temp_writer = make_uniq( + MaxValue(NextPowerOfTwo(page_info.estimated_page_size), MemoryStream::DEFAULT_INITIAL_CAPACITY)); write_info.write_count = page_info.empty_count; write_info.max_write_count = page_info.row_count; write_info.page_state = InitializePageState(state); @@ -516,7 +531,7 @@ void BasicColumnWriter::BeginWrite(ColumnWriterState &state_p) { NextPage(state); } -void BasicColumnWriter::WriteLevels(WriteStream &temp_writer, const vector &levels, idx_t max_value, +void BasicColumnWriter::WriteLevels(WriteStream &temp_writer, const unsafe_vector &levels, idx_t max_value, idx_t offset, idx_t count) { if (levels.empty() || count == 0) { return; @@ -590,7 +605,7 @@ void BasicColumnWriter::FlushPage(BasicColumnWriterState &state) { D_ASSERT(hdr.compressed_page_size > 0); if (write_info.compressed_buf) { - // if the data has been compressed, we no longer need the compressed data + // if the data has been compressed, we no longer need the uncompressed data D_ASSERT(write_info.compressed_buf.get() == write_info.compressed_data); write_info.temp_writer.reset(); } @@ -600,7 +615,8 @@ unique_ptr BasicColumnWriter::InitializeStatsState() { return make_uniq(); } -idx_t BasicColumnWriter::GetRowSize(Vector &vector, idx_t index, BasicColumnWriterState &state) { +idx_t BasicColumnWriter::GetRowSize(const Vector &vector, const idx_t index, + const BasicColumnWriterState &state) const { throw InternalException("GetRowSize unsupported for struct/list column writers"); } @@ -651,15 +667,12 @@ void BasicColumnWriter::SetParquetStatistics(BasicColumnWriterState &state, column_chunk.meta_data.statistics.__isset.max = true; column_chunk.meta_data.__isset.statistics = true; } - auto min_value = state.stats_state->GetMinValue(); - if (!min_value.empty()) { - column_chunk.meta_data.statistics.min_value = std::move(min_value); + if (state.stats_state->HasStats()) { + column_chunk.meta_data.statistics.min_value = state.stats_state->GetMinValue(); column_chunk.meta_data.statistics.__isset.min_value = true; column_chunk.meta_data.__isset.statistics = true; - } - auto max_value = state.stats_state->GetMaxValue(); - if (!max_value.empty()) { - column_chunk.meta_data.statistics.max_value = std::move(max_value); + + column_chunk.meta_data.statistics.max_value = state.stats_state->GetMaxValue(); column_chunk.meta_data.statistics.__isset.max_value = true; column_chunk.meta_data.__isset.statistics = true; } @@ -686,18 +699,24 @@ void BasicColumnWriter::FinalizeWrite(ColumnWriterState &state_p) { if (HasDictionary(state)) { column_chunk.meta_data.statistics.distinct_count = DictionarySize(state); column_chunk.meta_data.statistics.__isset.distinct_count = true; - column_chunk.meta_data.dictionary_page_offset = start_offset; + column_chunk.meta_data.dictionary_page_offset = column_writer.GetTotalWritten(); column_chunk.meta_data.__isset.dictionary_page_offset = true; FlushDictionary(state, state.stats_state.get()); } // record the start position of the pages for this column - column_chunk.meta_data.data_page_offset = column_writer.GetTotalWritten(); + column_chunk.meta_data.data_page_offset = 0; SetParquetStatistics(state, column_chunk); // write the individual pages to disk idx_t total_uncompressed_size = 0; for (auto &write_info : state.write_info) { + // set the data page offset whenever we see the *first* data page + if (column_chunk.meta_data.data_page_offset == 0 && (write_info.page_header.type == PageType::DATA_PAGE || + write_info.page_header.type == PageType::DATA_PAGE_V2)) { + column_chunk.meta_data.data_page_offset = column_writer.GetTotalWritten(); + ; + } D_ASSERT(write_info.page_header.uncompressed_page_size > 0); auto header_start_offset = column_writer.GetTotalWritten(); writer.Write(write_info.page_header); @@ -761,7 +780,7 @@ class NumericStatisticsState : public ColumnWriterStatistics { T max; public: - bool HasStats() { + bool HasStats() override { return min <= max; } @@ -807,7 +826,7 @@ struct ParquetCastOperator : public BaseParquetOperator { struct ParquetTimestampNSOperator : public BaseParquetOperator { template static TGT Operation(SRC input) { - return Timestamp::FromEpochNanoSecondsPossiblyInfinite(input).value; + return TGT(input); } }; @@ -858,16 +877,26 @@ struct ParquetUhugeintOperator { }; template -static void TemplatedWritePlain(Vector &col, ColumnWriterStatistics *stats, idx_t chunk_start, idx_t chunk_end, - ValidityMask &mask, WriteStream &ser) { - auto *ptr = FlatVector::GetData(col); +static void TemplatedWritePlain(Vector &col, ColumnWriterStatistics *stats, const idx_t chunk_start, + const idx_t chunk_end, ValidityMask &mask, WriteStream &ser) { + static constexpr idx_t WRITE_COMBINER_CAPACITY = 8; + TGT write_combiner[WRITE_COMBINER_CAPACITY]; + idx_t write_combiner_count = 0; + + const auto *ptr = FlatVector::GetData(col); for (idx_t r = chunk_start; r < chunk_end; r++) { - if (mask.RowIsValid(r)) { - TGT target_value = OP::template Operation(ptr[r]); - OP::template HandleStats(stats, ptr[r], target_value); - ser.Write(target_value); + if (!mask.RowIsValid(r)) { + continue; + } + TGT target_value = OP::template Operation(ptr[r]); + OP::template HandleStats(stats, ptr[r], target_value); + write_combiner[write_combiner_count++] = target_value; + if (write_combiner_count == WRITE_COMBINER_CAPACITY) { + ser.WriteData(const_data_ptr_cast(write_combiner), WRITE_COMBINER_CAPACITY * sizeof(TGT)); + write_combiner_count = 0; } } + ser.WriteData(const_data_ptr_cast(write_combiner), write_combiner_count * sizeof(TGT)); } template @@ -890,7 +919,7 @@ class StandardColumnWriter : public BasicColumnWriter { TemplatedWritePlain(input_column, stats, chunk_start, chunk_end, mask, temp_writer); } - idx_t GetRowSize(Vector &vector, idx_t index, BasicColumnWriterState &state) override { + idx_t GetRowSize(const Vector &vector, const idx_t index, const BasicColumnWriterState &state) const override { return sizeof(TGT); } }; @@ -907,7 +936,7 @@ class BooleanStatisticsState : public ColumnWriterStatistics { bool max; public: - bool HasStats() { + bool HasStats() override { return !(min && !max); } @@ -984,7 +1013,7 @@ class BooleanColumnWriter : public BasicColumnWriter { } } - idx_t GetRowSize(Vector &vector, idx_t index, BasicColumnWriterState &state) override { + idx_t GetRowSize(const Vector &vector, const idx_t index, const BasicColumnWriterState &state) const override { return sizeof(bool); } }; @@ -1029,7 +1058,7 @@ class FixedDecimalStatistics : public ColumnWriterStatistics { return string(const_char_ptr_cast(buffer), 16); } - bool HasStats() { + bool HasStats() override { return min <= max; } @@ -1085,7 +1114,7 @@ class FixedDecimalColumnWriter : public BasicColumnWriter { } } - idx_t GetRowSize(Vector &vector, idx_t index, BasicColumnWriterState &state) override { + idx_t GetRowSize(const Vector &vector, const idx_t index, const BasicColumnWriterState &state) const override { return sizeof(hugeint_t); } }; @@ -1132,7 +1161,7 @@ class UUIDColumnWriter : public BasicColumnWriter { } } - idx_t GetRowSize(Vector &vector, idx_t index, BasicColumnWriterState &state) override { + idx_t GetRowSize(const Vector &vector, const idx_t index, const BasicColumnWriterState &state) const override { return PARQUET_UUID_SIZE; } }; @@ -1174,11 +1203,52 @@ class IntervalColumnWriter : public BasicColumnWriter { } } - idx_t GetRowSize(Vector &vector, idx_t index, BasicColumnWriterState &state) override { + idx_t GetRowSize(const Vector &vector, const idx_t index, const BasicColumnWriterState &state) const override { return PARQUET_INTERVAL_SIZE; } }; +//===--------------------------------------------------------------------===// +// Geometry Column Writer +//===--------------------------------------------------------------------===// +// This class just wraps another column writer, but also calculates the extent +// of the geometry column by updating the geodata object with every written +// vector. +template +class GeometryColumnWriter : public WRITER_IMPL { + GeoParquetColumnMetadata geo_data; + GeoParquetColumnMetadataWriter geo_data_writer; + string column_name; + +public: + void Write(ColumnWriterState &state, Vector &vector, idx_t count) override { + // Just write normally + WRITER_IMPL::Write(state, vector, count); + + // And update the geodata object + geo_data_writer.Update(geo_data, vector, count); + } + void FinalizeWrite(ColumnWriterState &state) override { + WRITER_IMPL::FinalizeWrite(state); + + // Add the geodata object to the writer + this->writer.GetGeoParquetData().geometry_columns[column_name] = geo_data; + } + +public: + GeometryColumnWriter(ClientContext &context, ParquetWriter &writer, idx_t schema_idx, vector schema_path_p, + idx_t max_repeat, idx_t max_define, bool can_have_nulls, string name) + : WRITER_IMPL(writer, schema_idx, std::move(schema_path_p), max_repeat, max_define, can_have_nulls), + geo_data_writer(context), column_name(std::move(name)) { + + auto &geo_data = writer.GetGeoParquetData(); + if (geo_data.primary_geometry_column.empty()) { + // Set the first column to the primary column + geo_data.primary_geometry_column = column_name; + } + } +}; + //===--------------------------------------------------------------------===// // String Column Writer //===--------------------------------------------------------------------===// @@ -1195,7 +1265,7 @@ class StringStatisticsState : public ColumnWriterStatistics { string max; public: - bool HasStats() { + bool HasStats() override { return has_stats; } @@ -1210,6 +1280,7 @@ class StringStatisticsState : public ColumnWriterStatistics { // ideally we avoid placing several mega or giga-byte long strings there // we put a threshold of 10KB, if we see strings that exceed this threshold we avoid gathering stats values_too_big = true; + has_stats = false; min = string(); max = string(); return; @@ -1254,7 +1325,7 @@ class StringColumnWriterState : public BasicColumnWriterState { // key_bit_width== 0 signifies the chunk is written in plain encoding uint32_t key_bit_width; - bool IsDictionaryEncoded() { + bool IsDictionaryEncoded() const { return key_bit_width != 0; } }; @@ -1449,7 +1520,8 @@ class StringColumnWriter : public BasicColumnWriter { values[entry.second] = entry.first; } // first write the contents of the dictionary page to a temporary buffer - auto temp_writer = make_uniq(); + auto temp_writer = make_uniq( + MaxValue(NextPowerOfTwo(state.estimated_dict_page_size), MemoryStream::DEFAULT_INITIAL_CAPACITY)); for (idx_t r = 0; r < values.size(); r++) { auto &value = values[r]; // update the statistics @@ -1462,7 +1534,7 @@ class StringColumnWriter : public BasicColumnWriter { WriteDictionary(state, std::move(temp_writer), values.size()); } - idx_t GetRowSize(Vector &vector, idx_t index, BasicColumnWriterState &state_p) override { + idx_t GetRowSize(const Vector &vector, const idx_t index, const BasicColumnWriterState &state_p) const override { auto &state = state_p.Cast(); if (state.IsDictionaryEncoded()) { return (state.key_bit_width + 7) / 8; @@ -1606,7 +1678,7 @@ class EnumColumnWriter : public BasicColumnWriter { WriteDictionary(state, std::move(temp_writer), enum_count); } - idx_t GetRowSize(Vector &vector, idx_t index, BasicColumnWriterState &state) override { + idx_t GetRowSize(const Vector &vector, const idx_t index, const BasicColumnWriterState &state) const override { return (bit_width + 7) / 8; } }; @@ -1998,7 +2070,8 @@ void ArrayColumnWriter::Write(ColumnWriterState &state_p, Vector &vector, idx_t // Create Column Writer //===--------------------------------------------------------------------===// -unique_ptr ColumnWriter::CreateWriterRecursive(vector &schemas, +unique_ptr ColumnWriter::CreateWriterRecursive(ClientContext &context, + vector &schemas, ParquetWriter &writer, const LogicalType &type, const string &name, vector schema_path, optional_ptr field_ids, @@ -2040,7 +2113,7 @@ unique_ptr ColumnWriter::CreateWriterRecursive(vector> child_writers; child_writers.reserve(child_types.size()); for (auto &child_type : child_types) { - child_writers.push_back(CreateWriterRecursive(schemas, writer, child_type.second, child_type.first, + child_writers.push_back(CreateWriterRecursive(context, schemas, writer, child_type.second, child_type.first, schema_path, child_field_ids, max_repeat, max_define + 1)); } return make_uniq(writer, schema_idx, std::move(schema_path), max_repeat, max_define, @@ -2079,8 +2152,8 @@ unique_ptr ColumnWriter::CreateWriterRecursive(vector(writer, schema_idx, std::move(schema_path), max_repeat, max_define, std::move(child_writer), can_have_nulls); @@ -2134,7 +2207,7 @@ unique_ptr ColumnWriter::CreateWriterRecursive(vector ColumnWriter::CreateWriterRecursive(vector>(context, writer, schema_idx, std::move(schema_path), + max_repeat, max_define, can_have_nulls, name); + } + switch (type.id()) { case LogicalTypeId::BOOLEAN: return make_uniq(writer, schema_idx, std::move(schema_path), max_repeat, max_define, diff --git a/extension/parquet/geo_parquet.cpp b/extension/parquet/geo_parquet.cpp new file mode 100644 index 00000000000..0719013edeb --- /dev/null +++ b/extension/parquet/geo_parquet.cpp @@ -0,0 +1,384 @@ + +#include "geo_parquet.hpp" + +#include "column_reader.hpp" +#include "duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/function/scalar_function.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/planner/expression/bound_reference_expression.hpp" +#include "duckdb/main/extension_helper.hpp" +#include "expression_column_reader.hpp" +#include "parquet_reader.hpp" +#include "yyjson.hpp" + +namespace duckdb { + +using namespace duckdb_yyjson; // NOLINT + +const char *WKBGeometryTypes::ToString(WKBGeometryType type) { + switch (type) { + case WKBGeometryType::POINT: + return "Point"; + case WKBGeometryType::LINESTRING: + return "LineString"; + case WKBGeometryType::POLYGON: + return "Polygon"; + case WKBGeometryType::MULTIPOINT: + return "MultiPoint"; + case WKBGeometryType::MULTILINESTRING: + return "MultiLineString"; + case WKBGeometryType::MULTIPOLYGON: + return "MultiPolygon"; + case WKBGeometryType::GEOMETRYCOLLECTION: + return "GeometryCollection"; + case WKBGeometryType::POINT_Z: + return "Point Z"; + case WKBGeometryType::LINESTRING_Z: + return "LineString Z"; + case WKBGeometryType::POLYGON_Z: + return "Polygon Z"; + case WKBGeometryType::MULTIPOINT_Z: + return "MultiPoint Z"; + case WKBGeometryType::MULTILINESTRING_Z: + return "MultiLineString Z"; + case WKBGeometryType::MULTIPOLYGON_Z: + return "MultiPolygon Z"; + case WKBGeometryType::GEOMETRYCOLLECTION_Z: + return "GeometryCollection Z"; + default: + throw NotImplementedException("Unsupported geometry type"); + } +} + +//------------------------------------------------------------------------------ +// GeoParquetColumnMetadataWriter +//------------------------------------------------------------------------------ +GeoParquetColumnMetadataWriter::GeoParquetColumnMetadataWriter(ClientContext &context) { + executor = make_uniq(context); + + auto &catalog = Catalog::GetSystemCatalog(context); + + // These functions are required to extract the geometry type, ZM flag and bounding box from a WKB blob + auto &type_func_set = + catalog.GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, DEFAULT_SCHEMA, "st_geometrytype") + .Cast(); + auto &flag_func_set = catalog.GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, DEFAULT_SCHEMA, "st_zmflag") + .Cast(); + auto &bbox_func_set = catalog.GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, DEFAULT_SCHEMA, "st_extent") + .Cast(); + + auto wkb_type = LogicalType(LogicalTypeId::BLOB); + wkb_type.SetAlias("WKB_BLOB"); + + auto type_func = type_func_set.functions.GetFunctionByArguments(context, {wkb_type}); + auto flag_func = flag_func_set.functions.GetFunctionByArguments(context, {wkb_type}); + auto bbox_func = bbox_func_set.functions.GetFunctionByArguments(context, {wkb_type}); + + auto type_type = LogicalType::UTINYINT; + auto flag_type = flag_func.return_type; + auto bbox_type = bbox_func.return_type; + + vector> type_args; + type_args.push_back(make_uniq(wkb_type, 0)); + + vector> flag_args; + flag_args.push_back(make_uniq(wkb_type, 0)); + + vector> bbox_args; + bbox_args.push_back(make_uniq(wkb_type, 0)); + + type_expr = make_uniq(type_type, type_func, std::move(type_args), nullptr); + flag_expr = make_uniq(flag_type, flag_func, std::move(flag_args), nullptr); + bbox_expr = make_uniq(bbox_type, bbox_func, std::move(bbox_args), nullptr); + + // Add the expressions to the executor + executor->AddExpression(*type_expr); + executor->AddExpression(*flag_expr); + executor->AddExpression(*bbox_expr); + + // Initialize the input and result chunks + // The input chunk should be empty, as we always reference the input vector + input_chunk.InitializeEmpty({wkb_type}); + result_chunk.Initialize(context, {type_type, flag_type, bbox_type}); +} + +void GeoParquetColumnMetadataWriter::Update(GeoParquetColumnMetadata &meta, Vector &vector, idx_t count) { + input_chunk.Reset(); + result_chunk.Reset(); + + // Reference the vector + input_chunk.data[0].Reference(vector); + input_chunk.SetCardinality(count); + + // Execute the expression + executor->Execute(input_chunk, result_chunk); + + // The first column is the geometry type + // The second column is the zm flag + // The third column is the bounding box + + UnifiedVectorFormat type_format; + UnifiedVectorFormat flag_format; + UnifiedVectorFormat bbox_format; + + result_chunk.data[0].ToUnifiedFormat(count, type_format); + result_chunk.data[1].ToUnifiedFormat(count, flag_format); + result_chunk.data[2].ToUnifiedFormat(count, bbox_format); + + const auto &bbox_components = StructVector::GetEntries(result_chunk.data[2]); + D_ASSERT(bbox_components.size() == 4); + + UnifiedVectorFormat xmin_format; + UnifiedVectorFormat ymin_format; + UnifiedVectorFormat xmax_format; + UnifiedVectorFormat ymax_format; + + bbox_components[0]->ToUnifiedFormat(count, xmin_format); + bbox_components[1]->ToUnifiedFormat(count, ymin_format); + bbox_components[2]->ToUnifiedFormat(count, xmax_format); + bbox_components[3]->ToUnifiedFormat(count, ymax_format); + + for (idx_t in_idx = 0; in_idx < count; in_idx++) { + const auto type_idx = type_format.sel->get_index(in_idx); + const auto flag_idx = flag_format.sel->get_index(in_idx); + const auto bbox_idx = bbox_format.sel->get_index(in_idx); + + const auto type_valid = type_format.validity.RowIsValid(type_idx); + const auto flag_valid = flag_format.validity.RowIsValid(flag_idx); + const auto bbox_valid = bbox_format.validity.RowIsValid(bbox_idx); + + if (!type_valid || !flag_valid || !bbox_valid) { + continue; + } + + // Update the geometry type + const auto flag = UnifiedVectorFormat::GetData(flag_format)[flag_idx]; + const auto type = UnifiedVectorFormat::GetData(type_format)[type_idx]; + if (flag == 1 || flag == 3) { + // M or ZM + throw InvalidInputException("Geoparquet does not support geometries with M coordinates"); + } + const auto has_z = flag == 2; + auto wkb_type = static_cast((type + 1) + (has_z ? 1000 : 0)); + meta.geometry_types.insert(wkb_type); + + // Update the bounding box + const auto min_x = UnifiedVectorFormat::GetData(xmin_format)[bbox_idx]; + const auto min_y = UnifiedVectorFormat::GetData(ymin_format)[bbox_idx]; + const auto max_x = UnifiedVectorFormat::GetData(xmax_format)[bbox_idx]; + const auto max_y = UnifiedVectorFormat::GetData(ymax_format)[bbox_idx]; + meta.bbox.Combine(min_x, max_x, min_y, max_y); + } +} + +//------------------------------------------------------------------------------ +// GeoParquetFileMetadata +//------------------------------------------------------------------------------ + +unique_ptr +GeoParquetFileMetadata::Read(const duckdb_parquet::format::FileMetaData &file_meta_data) { + for (auto &kv : file_meta_data.key_value_metadata) { + if (kv.key == "geo") { + const auto geo_metadata = yyjson_read(kv.value.c_str(), kv.value.size(), 0); + if (!geo_metadata) { + throw InvalidInputException("Failed to parse geoparquet metadata"); + } + try { + // Check the root object + const auto root = yyjson_doc_get_root(geo_metadata); + if (!yyjson_is_obj(root)) { + throw InvalidInputException("Geoparquet metadata is not an object"); + } + + auto result = make_uniq(); + + // Check and parse the version + const auto version_val = yyjson_obj_get(root, "version"); + if (!yyjson_is_str(version_val)) { + throw InvalidInputException("Geoparquet metadata does not have a version"); + } + result->version = yyjson_get_str(version_val); + if (StringUtil::StartsWith(result->version, "2")) { + // Guard against a breaking future 2.0 version + throw InvalidInputException("Geoparquet version %s is not supported", result->version); + } + + // Check and parse the primary geometry column + const auto primary_geometry_column_val = yyjson_obj_get(root, "primary_column"); + if (!yyjson_is_str(primary_geometry_column_val)) { + throw InvalidInputException("Geoparquet metadata does not have a primary column"); + } + result->primary_geometry_column = yyjson_get_str(primary_geometry_column_val); + + // Check and parse the geometry columns + const auto columns_val = yyjson_obj_get(root, "columns"); + if (!yyjson_is_obj(columns_val)) { + throw InvalidInputException("Geoparquet metadata does not have a columns object"); + } + + // Iterate over all geometry columns + yyjson_obj_iter iter = yyjson_obj_iter_with(columns_val); + yyjson_val *column_key; + + while ((column_key = yyjson_obj_iter_next(&iter))) { + const auto column_val = yyjson_obj_iter_get_val(column_key); + const auto column_name = yyjson_get_str(column_key); + + auto &column = result->geometry_columns[column_name]; + + if (!yyjson_is_obj(column_val)) { + throw InvalidInputException("Geoparquet column '%s' is not an object", column_name); + } + + // Parse the encoding + const auto encoding_val = yyjson_obj_get(column_val, "encoding"); + if (!yyjson_is_str(encoding_val)) { + throw InvalidInputException("Geoparquet column '%s' does not have an encoding", column_name); + } + const auto encoding_str = yyjson_get_str(encoding_val); + if (strcmp(encoding_str, "WKB") == 0) { + column.geometry_encoding = GeoParquetColumnEncoding::WKB; + } else { + throw InvalidInputException("Geoparquet column '%s' has an unsupported encoding", column_name); + } + + // Parse the geometry types + const auto geometry_types_val = yyjson_obj_get(column_val, "geometry_types"); + if (!yyjson_is_arr(geometry_types_val)) { + throw InvalidInputException("Geoparquet column '%s' does not have geometry types", column_name); + } + // We dont care about the geometry types for now. + + // TODO: Parse the bounding box, other metadata that might be useful. + // (Only encoding and geometry types are required to be present) + } + + // Return the result + return result; + + } catch (...) { + // Make sure to free the JSON document in case of an exception + yyjson_doc_free(geo_metadata); + throw; + } + } + } + return nullptr; +} + +void GeoParquetFileMetadata::Write(duckdb_parquet::format::FileMetaData &file_meta_data) const { + + yyjson_mut_doc *doc = yyjson_mut_doc_new(nullptr); + yyjson_mut_val *root = yyjson_mut_obj(doc); + yyjson_mut_doc_set_root(doc, root); + + // Add the version + yyjson_mut_obj_add_strncpy(doc, root, "version", version.c_str(), version.size()); + + // Add the primary column + yyjson_mut_obj_add_strncpy(doc, root, "primary_column", primary_geometry_column.c_str(), + primary_geometry_column.size()); + + // Add the columns + const auto json_columns = yyjson_mut_obj_add_obj(doc, root, "columns"); + + for (auto &column : geometry_columns) { + const auto column_json = yyjson_mut_obj_add_obj(doc, json_columns, column.first.c_str()); + yyjson_mut_obj_add_str(doc, column_json, "encoding", "WKB"); + const auto geometry_types = yyjson_mut_obj_add_arr(doc, column_json, "geometry_types"); + for (auto &geometry_type : column.second.geometry_types) { + const auto type_name = WKBGeometryTypes::ToString(geometry_type); + yyjson_mut_arr_add_str(doc, geometry_types, type_name); + } + const auto bbox = yyjson_mut_obj_add_arr(doc, column_json, "bbox"); + yyjson_mut_arr_add_real(doc, bbox, column.second.bbox.min_x); + yyjson_mut_arr_add_real(doc, bbox, column.second.bbox.min_y); + yyjson_mut_arr_add_real(doc, bbox, column.second.bbox.max_x); + yyjson_mut_arr_add_real(doc, bbox, column.second.bbox.max_y); + + // If the CRS is present, add it + if (!column.second.projjson.empty()) { + const auto crs_doc = yyjson_read(column.second.projjson.c_str(), column.second.projjson.size(), 0); + if (!crs_doc) { + yyjson_mut_doc_free(doc); + throw InvalidInputException("Failed to parse CRS JSON"); + } + const auto crs_root = yyjson_doc_get_root(crs_doc); + const auto crs_val = yyjson_val_mut_copy(doc, crs_root); + const auto crs_key = yyjson_mut_strcpy(doc, "projjson"); + yyjson_mut_obj_add(column_json, crs_key, crs_val); + yyjson_doc_free(crs_doc); + } + } + + yyjson_write_err err; + size_t len; + char *json = yyjson_mut_write_opts(doc, 0, nullptr, &len, &err); + if (!json) { + yyjson_mut_doc_free(doc); + throw SerializationException("Failed to write JSON string: %s", err.msg); + } + + // Create a string from the JSON + duckdb_parquet::format::KeyValue kv; + kv.__set_key("geo"); + kv.__set_value(string(json, len)); + + // Free the JSON and the document + free(json); + yyjson_mut_doc_free(doc); + + file_meta_data.key_value_metadata.push_back(kv); + file_meta_data.__isset.key_value_metadata = true; +} + +bool GeoParquetFileMetadata::IsGeometryColumn(const string &column_name) const { + return geometry_columns.find(column_name) != geometry_columns.end(); +} + +unique_ptr GeoParquetFileMetadata::CreateColumnReader(ParquetReader &reader, + const LogicalType &logical_type, + const SchemaElement &s_ele, idx_t schema_idx_p, + idx_t max_define_p, idx_t max_repeat_p, + ClientContext &context) { + + D_ASSERT(IsGeometryColumn(s_ele.name)); + + const auto &column = geometry_columns[s_ele.name]; + + // Get the catalog + auto &catalog = Catalog::GetSystemCatalog(context); + + // WKB encoding + if (logical_type.id() == LogicalTypeId::BLOB && column.geometry_encoding == GeoParquetColumnEncoding::WKB) { + // Look for a conversion function in the catalog + auto &conversion_func_set = + catalog.GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, DEFAULT_SCHEMA, "st_geomfromwkb") + .Cast(); + auto conversion_func = conversion_func_set.functions.GetFunctionByArguments(context, {LogicalType::BLOB}); + + // Create a bound function call expression + auto args = vector>(); + args.push_back(std::move(make_uniq(LogicalType::BLOB, 0))); + auto expr = + make_uniq(conversion_func.return_type, conversion_func, std::move(args), nullptr); + + // Create a child reader + auto child_reader = + ColumnReader::CreateReader(reader, logical_type, s_ele, schema_idx_p, max_define_p, max_repeat_p); + + // Create an expression reader that applies the conversion function to the child reader + return make_uniq(context, std::move(child_reader), std::move(expr)); + } + + // Otherwise, unrecognized encoding + throw NotImplementedException("Unsupported geometry encoding"); +} + +bool GeoParquetFileMetadata::IsSpatialExtensionInstalled(ClientContext &context) { + // Try to load the spatial extension + return ExtensionHelper::TryAutoLoadExtension(context, "spatial"); +} + +} // namespace duckdb diff --git a/extension/parquet/include/boolean_column_reader.hpp b/extension/parquet/include/boolean_column_reader.hpp index 9410ee30112..125c548dcc8 100644 --- a/extension/parquet/include/boolean_column_reader.hpp +++ b/extension/parquet/include/boolean_column_reader.hpp @@ -46,18 +46,29 @@ struct BooleanParquetValueConversion { static bool PlainRead(ByteBuffer &plain_data, ColumnReader &reader) { plain_data.available(1); + return UnsafePlainRead(plain_data, reader); + } + + static void PlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { + PlainRead(plain_data, reader); + } + + static bool PlainAvailable(const ByteBuffer &plain_data, const idx_t count) { + return plain_data.check_available((count + 7) / 8); + } + + static bool UnsafePlainRead(ByteBuffer &plain_data, ColumnReader &reader) { auto &byte_pos = reader.Cast().byte_pos; bool ret = (*plain_data.ptr >> byte_pos) & 1; - byte_pos++; - if (byte_pos == 8) { + if (++byte_pos == 8) { byte_pos = 0; - plain_data.inc(1); + plain_data.unsafe_inc(1); } return ret; } - static void PlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { - PlainRead(plain_data, reader); + static void UnsafePlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { + UnsafePlainRead(plain_data, reader); } }; diff --git a/extension/parquet/include/column_reader.hpp b/extension/parquet/include/column_reader.hpp index f4e32f39102..0a7a17ea08d 100644 --- a/extension/parquet/include/column_reader.hpp +++ b/extension/parquet/include/column_reader.hpp @@ -73,18 +73,43 @@ class ColumnReader { template void PlainTemplated(shared_ptr plain_data, uint8_t *defines, uint64_t num_values, parquet_filter_t &filter, idx_t result_offset, Vector &result) { - auto result_ptr = FlatVector::GetData(result); - auto &result_mask = FlatVector::Validity(result); - for (idx_t row_idx = 0; row_idx < num_values; row_idx++) { - if (HasDefines() && defines[row_idx + result_offset] != max_define) { - result_mask.SetInvalid(row_idx + result_offset); - continue; + if (HasDefines()) { + if (CONVERSION::PlainAvailable(*plain_data, num_values)) { + PlainTemplatedInternal(*plain_data, defines, num_values, filter, + result_offset, result); + } else { + PlainTemplatedInternal(*plain_data, defines, num_values, filter, + result_offset, result); + } + } else { + if (CONVERSION::PlainAvailable(*plain_data, num_values)) { + PlainTemplatedInternal(*plain_data, defines, num_values, filter, + result_offset, result); + } else { + PlainTemplatedInternal(*plain_data, defines, num_values, filter, + result_offset, result); } - if (filter[row_idx + result_offset]) { - VALUE_TYPE val = CONVERSION::PlainRead(*plain_data, *this); - result_ptr[row_idx + result_offset] = val; + } + } + +private: + template + void PlainTemplatedInternal(ByteBuffer &plain_data, const uint8_t *__restrict defines, const uint64_t num_values, + const parquet_filter_t &filter, const idx_t result_offset, Vector &result) { + const auto result_ptr = FlatVector::GetData(result); + auto &result_mask = FlatVector::Validity(result); + for (idx_t row_idx = result_offset; row_idx < result_offset + num_values; row_idx++) { + if (HAS_DEFINES && defines[row_idx] != max_define) { + result_mask.SetInvalid(row_idx); + } else if (filter.test(row_idx)) { + result_ptr[row_idx] = + UNSAFE ? CONVERSION::UnsafePlainRead(plain_data, *this) : CONVERSION::PlainRead(plain_data, *this); } else { // there is still some data there that we have to skip over - CONVERSION::PlainSkip(*plain_data, *this); + if (UNSAFE) { + CONVERSION::UnsafePlainSkip(plain_data, *this); + } else { + CONVERSION::PlainSkip(plain_data, *this); + } } } } @@ -110,11 +135,11 @@ class ColumnReader { // applies any skips that were registered using Skip() virtual void ApplyPendingSkips(idx_t num_values); - bool HasDefines() { + bool HasDefines() const { return max_define > 0; } - bool HasRepeats() { + bool HasRepeats() const { return max_repeat > 0; } diff --git a/extension/parquet/include/column_writer.hpp b/extension/parquet/include/column_writer.hpp index edd67bced78..65f89e596fa 100644 --- a/extension/parquet/include/column_writer.hpp +++ b/extension/parquet/include/column_writer.hpp @@ -22,8 +22,8 @@ class ColumnWriterState { public: virtual ~ColumnWriterState(); - vector definition_levels; - vector repetition_levels; + unsafe_vector definition_levels; + unsafe_vector repetition_levels; vector is_empty; idx_t null_count = 0; @@ -44,6 +44,7 @@ class ColumnWriterStatistics { public: virtual ~ColumnWriterStatistics(); + virtual bool HasStats(); virtual string GetMin(); virtual string GetMax(); virtual string GetMinValue(); @@ -78,12 +79,11 @@ class ColumnWriter { public: //! Create the column writer for a specific type recursively - static unique_ptr CreateWriterRecursive(vector &schemas, - ParquetWriter &writer, const LogicalType &type, - const string &name, vector schema_path, - optional_ptr field_ids, - idx_t max_repeat = 0, idx_t max_define = 1, - bool can_have_nulls = true); + static unique_ptr + CreateWriterRecursive(ClientContext &context, vector &schemas, + ParquetWriter &writer, const LogicalType &type, const string &name, + vector schema_path, optional_ptr field_ids, idx_t max_repeat = 0, + idx_t max_define = 1, bool can_have_nulls = true); virtual unique_ptr InitializeWriteState(duckdb_parquet::format::RowGroup &row_group) = 0; @@ -108,9 +108,9 @@ class ColumnWriter { virtual void FinalizeWrite(ColumnWriterState &state) = 0; protected: - void HandleDefineLevels(ColumnWriterState &state, ColumnWriterState *parent, ValidityMask &validity, idx_t count, - uint16_t define_value, uint16_t null_value); - void HandleRepeatLevels(ColumnWriterState &state_p, ColumnWriterState *parent, idx_t count, idx_t max_repeat); + void HandleDefineLevels(ColumnWriterState &state, ColumnWriterState *parent, const ValidityMask &validity, + const idx_t count, const uint16_t define_value, const uint16_t null_value) const; + void HandleRepeatLevels(ColumnWriterState &state_p, ColumnWriterState *parent, idx_t count, idx_t max_repeat) const; void CompressPage(MemoryStream &temp_writer, size_t &compressed_size, data_ptr_t &compressed_data, unique_ptr &compressed_buf); diff --git a/extension/parquet/include/expression_column_reader.hpp b/extension/parquet/include/expression_column_reader.hpp new file mode 100644 index 00000000000..c94a816d3a8 --- /dev/null +++ b/extension/parquet/include/expression_column_reader.hpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// expression_column_reader.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "column_reader.hpp" +#include "templated_column_reader.hpp" + +namespace duckdb { + +//! A column reader that executes an expression over a child reader +class ExpressionColumnReader : public ColumnReader { +public: + static constexpr const PhysicalType TYPE = PhysicalType::INVALID; + +public: + ExpressionColumnReader(ClientContext &context, unique_ptr child_reader, unique_ptr expr); + + unique_ptr child_reader; + DataChunk intermediate_chunk; + unique_ptr expr; + ExpressionExecutor executor; + +public: + unique_ptr Stats(idx_t row_group_idx_p, const vector &columns) override; + void InitializeRead(idx_t row_group_idx_p, const vector &columns, TProtocol &protocol_p) override; + + idx_t Read(uint64_t num_values, parquet_filter_t &filter, data_ptr_t define_out, data_ptr_t repeat_out, + Vector &result) override; + + void Skip(idx_t num_values) override; + idx_t GroupRowsAvailable() override; + + uint64_t TotalCompressedSize() override { + return child_reader->TotalCompressedSize(); + } + + idx_t FileOffset() const override { + return child_reader->FileOffset(); + } + + void RegisterPrefetch(ThriftFileTransport &transport, bool allow_merge) override { + child_reader->RegisterPrefetch(transport, allow_merge); + } +}; + +} // namespace duckdb diff --git a/extension/parquet/include/geo_parquet.hpp b/extension/parquet/include/geo_parquet.hpp new file mode 100644 index 00000000000..e1e3825d435 --- /dev/null +++ b/extension/parquet/include/geo_parquet.hpp @@ -0,0 +1,138 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// geo_parquet.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "column_writer.hpp" +#include "duckdb/common/string.hpp" +#include "duckdb/common/types/data_chunk.hpp" +#include "duckdb/common/unordered_map.hpp" +#include "duckdb/common/unordered_set.hpp" +#include "parquet_types.h" + +namespace duckdb { + +enum class WKBGeometryType : uint16_t { + POINT = 1, + LINESTRING = 2, + POLYGON = 3, + MULTIPOINT = 4, + MULTILINESTRING = 5, + MULTIPOLYGON = 6, + GEOMETRYCOLLECTION = 7, + + POINT_Z = 1001, + LINESTRING_Z = 1002, + POLYGON_Z = 1003, + MULTIPOINT_Z = 1004, + MULTILINESTRING_Z = 1005, + MULTIPOLYGON_Z = 1006, + GEOMETRYCOLLECTION_Z = 1007, +}; + +struct WKBGeometryTypes { + static const char *ToString(WKBGeometryType type); +}; + +struct GeometryBounds { + double min_x = NumericLimits::Maximum(); + double max_x = NumericLimits::Minimum(); + double min_y = NumericLimits::Maximum(); + double max_y = NumericLimits::Minimum(); + + GeometryBounds() = default; + + void Combine(const GeometryBounds &other) { + min_x = std::min(min_x, other.min_x); + max_x = std::max(max_x, other.max_x); + min_y = std::min(min_y, other.min_y); + max_y = std::max(max_y, other.max_y); + } + + void Combine(const double &x, const double &y) { + min_x = std::min(min_x, x); + max_x = std::max(max_x, x); + min_y = std::min(min_y, y); + max_y = std::max(max_y, y); + } + + void Combine(const double &min_x, const double &max_x, const double &min_y, const double &max_y) { + this->min_x = std::min(this->min_x, min_x); + this->max_x = std::max(this->max_x, max_x); + this->min_y = std::min(this->min_y, min_y); + this->max_y = std::max(this->max_y, max_y); + } +}; + +//------------------------------------------------------------------------------ +// GeoParquetMetadata +//------------------------------------------------------------------------------ +class ParquetReader; +class ColumnReader; +class ClientContext; +class ExpressionExecutor; + +enum class GeoParquetColumnEncoding : uint8_t { + WKB = 1, + POINT, + LINESTRING, + POLYGON, + MULTIPOINT, + MULTILINESTRING, + MULTIPOLYGON, +}; + +struct GeoParquetColumnMetadata { + // The encoding of the geometry column + GeoParquetColumnEncoding geometry_encoding; + + // The geometry types that are present in the column + set geometry_types; + + // The bounds of the geometry column + GeometryBounds bbox; + + // The crs of the geometry column (if any) in PROJJSON format + string projjson; +}; + +class GeoParquetColumnMetadataWriter { + unique_ptr executor; + DataChunk input_chunk; + DataChunk result_chunk; + + unique_ptr type_expr; + unique_ptr flag_expr; + unique_ptr bbox_expr; + +public: + explicit GeoParquetColumnMetadataWriter(ClientContext &context); + void Update(GeoParquetColumnMetadata &meta, Vector &vector, idx_t count); +}; + +struct GeoParquetFileMetadata { +public: + static unique_ptr Read(const duckdb_parquet::format::FileMetaData &file_meta_data); + void Write(duckdb_parquet::format::FileMetaData &file_meta_data) const; + +public: + // Default to 1.1.0 for now + string version = "1.1.0"; + string primary_geometry_column; + unordered_map geometry_columns; + + unique_ptr CreateColumnReader(ParquetReader &reader, const LogicalType &logical_type, + const duckdb_parquet::format::SchemaElement &s_ele, idx_t schema_idx_p, + idx_t max_define_p, idx_t max_repeat_p, ClientContext &context); + + bool IsGeometryColumn(const string &column_name) const; + + static bool IsSpatialExtensionInstalled(ClientContext &context); +}; + +} // namespace duckdb diff --git a/extension/parquet/include/parquet.json b/extension/parquet/include/parquet.json index e73d919b12b..3d9e7710fde 100644 --- a/extension/parquet/include/parquet.json +++ b/extension/parquet/include/parquet.json @@ -116,7 +116,9 @@ { "id": 100, "name": "ids", - "type": "unique_ptr>" + "type": "case_insensitive_map_t", + "serialize_property": "ids.operator*()", + "deserialize_property": "ids.operator*()" } ], "pointer_type": "none" diff --git a/extension/parquet/include/parquet_extension.hpp b/extension/parquet/include/parquet_extension.hpp index d24eeb6a870..702adb382e2 100644 --- a/extension/parquet/include/parquet_extension.hpp +++ b/extension/parquet/include/parquet_extension.hpp @@ -8,6 +8,7 @@ class ParquetExtension : public Extension { public: void Load(DuckDB &db) override; std::string Name() override; + std::string Version() const override; }; } // namespace duckdb diff --git a/extension/parquet/include/parquet_file_metadata_cache.hpp b/extension/parquet/include/parquet_file_metadata_cache.hpp index 01d316dc0f3..48b6448ded5 100644 --- a/extension/parquet/include/parquet_file_metadata_cache.hpp +++ b/extension/parquet/include/parquet_file_metadata_cache.hpp @@ -10,9 +10,9 @@ #include "duckdb.hpp" #ifndef DUCKDB_AMALGAMATION #include "duckdb/storage/object_cache.hpp" +#include "geo_parquet.hpp" #endif #include "parquet_types.h" - namespace duckdb { //! ParquetFileMetadataCache @@ -20,8 +20,9 @@ class ParquetFileMetadataCache : public ObjectCacheEntry { public: ParquetFileMetadataCache() : metadata(nullptr) { } - ParquetFileMetadataCache(unique_ptr file_metadata, time_t r_time) - : metadata(std::move(file_metadata)), read_time(r_time) { + ParquetFileMetadataCache(unique_ptr file_metadata, time_t r_time, + unique_ptr geo_metadata) + : metadata(std::move(file_metadata)), read_time(r_time), geo_metadata(std::move(geo_metadata)) { } ~ParquetFileMetadataCache() override = default; @@ -32,6 +33,9 @@ class ParquetFileMetadataCache : public ObjectCacheEntry { //! read time time_t read_time; + //! GeoParquet metadata + unique_ptr geo_metadata; + public: static string ObjectType() { return "parquet_metadata"; diff --git a/extension/parquet/include/parquet_reader.hpp b/extension/parquet/include/parquet_reader.hpp index 6e65d46d837..fda0b08de6c 100644 --- a/extension/parquet/include/parquet_reader.hpp +++ b/extension/parquet/include/parquet_reader.hpp @@ -120,7 +120,7 @@ class ParquetReader { vector generated_column_schema; public: - void InitializeScan(ParquetReaderScanState &state, vector groups_to_read); + void InitializeScan(ClientContext &context, ParquetReaderScanState &state, vector groups_to_read); void Scan(ParquetReaderScanState &state, DataChunk &output); idx_t NumRows(); @@ -150,12 +150,12 @@ class ParquetReader { } private: - void InitializeSchema(); + void InitializeSchema(ClientContext &context); bool ScanInternal(ParquetReaderScanState &state, DataChunk &output); - unique_ptr CreateReader(); + unique_ptr CreateReader(ClientContext &context); - unique_ptr CreateReaderRecursive(idx_t depth, idx_t max_define, idx_t max_repeat, - idx_t &next_schema_idx, idx_t &next_file_idx); + unique_ptr CreateReaderRecursive(ClientContext &context, idx_t depth, idx_t max_define, + idx_t max_repeat, idx_t &next_schema_idx, idx_t &next_file_idx); const duckdb_parquet::format::RowGroup &GetGroup(ParquetReaderScanState &state); uint64_t GetGroupCompressedSize(ParquetReaderScanState &state); idx_t GetGroupOffset(ParquetReaderScanState &state); diff --git a/extension/parquet/include/parquet_rle_bp_decoder.hpp b/extension/parquet/include/parquet_rle_bp_decoder.hpp index 125edf1dd29..2709338818e 100644 --- a/extension/parquet/include/parquet_rle_bp_decoder.hpp +++ b/extension/parquet/include/parquet_rle_bp_decoder.hpp @@ -7,10 +7,10 @@ //===----------------------------------------------------------------------===// #pragma once +#include "decode_utils.hpp" #include "parquet_types.h" -#include "thrift_tools.hpp" #include "resizable_buffer.hpp" -#include "decode_utils.hpp" +#include "thrift_tools.hpp" namespace duckdb { @@ -35,7 +35,7 @@ class RleBpDecoder { while (values_read < batch_size) { if (repeat_count_ > 0) { int repeat_batch = MinValue(batch_size - values_read, static_cast(repeat_count_)); - std::fill(values + values_read, values + values_read + repeat_batch, static_cast(current_value_)); + std::fill_n(values + values_read, repeat_batch, static_cast(current_value_)); repeat_count_ -= repeat_batch; values_read += repeat_batch; } else if (literal_count_ > 0) { diff --git a/extension/parquet/include/parquet_rle_bp_encoder.hpp b/extension/parquet/include/parquet_rle_bp_encoder.hpp index e9115a8280d..029dd06eb0a 100644 --- a/extension/parquet/include/parquet_rle_bp_encoder.hpp +++ b/extension/parquet/include/parquet_rle_bp_encoder.hpp @@ -16,7 +16,7 @@ namespace duckdb { class RleBpEncoder { public: - RleBpEncoder(uint32_t bit_width); + explicit RleBpEncoder(uint32_t bit_width); public: //! NOTE: Prepare is only required if a byte count is required BEFORE writing diff --git a/extension/parquet/include/parquet_timestamp.hpp b/extension/parquet/include/parquet_timestamp.hpp index d9c33b4d75a..8631af9979e 100644 --- a/extension/parquet/include/parquet_timestamp.hpp +++ b/extension/parquet/include/parquet_timestamp.hpp @@ -17,14 +17,22 @@ struct Int96 { }; timestamp_t ImpalaTimestampToTimestamp(const Int96 &raw_ts); +timestamp_ns_t ImpalaTimestampToTimestampNS(const Int96 &raw_ts); Int96 TimestampToImpalaTimestamp(timestamp_t &ts); + timestamp_t ParquetTimestampMicrosToTimestamp(const int64_t &raw_ts); timestamp_t ParquetTimestampMsToTimestamp(const int64_t &raw_ts); timestamp_t ParquetTimestampNsToTimestamp(const int64_t &raw_ts); + +timestamp_ns_t ParquetTimestampMsToTimestampNs(const int64_t &raw_ms); +timestamp_ns_t ParquetTimestampUsToTimestampNs(const int64_t &raw_us); +timestamp_ns_t ParquetTimestampNsToTimestampNs(const int64_t &raw_ns); + date_t ParquetIntToDate(const int32_t &raw_date); dtime_t ParquetIntToTimeMs(const int32_t &raw_time); dtime_t ParquetIntToTime(const int64_t &raw_time); dtime_t ParquetIntToTimeNs(const int64_t &raw_time); + dtime_tz_t ParquetIntToTimeMsTZ(const int32_t &raw_time); dtime_tz_t ParquetIntToTimeTZ(const int64_t &raw_time); dtime_tz_t ParquetIntToTimeNsTZ(const int64_t &raw_time); diff --git a/extension/parquet/include/parquet_writer.hpp b/extension/parquet/include/parquet_writer.hpp index 137a946c4f8..5b3a472e26d 100644 --- a/extension/parquet/include/parquet_writer.hpp +++ b/extension/parquet/include/parquet_writer.hpp @@ -20,6 +20,7 @@ #include "column_writer.hpp" #include "parquet_types.h" +#include "geo_parquet.hpp" #include "thrift/protocol/TCompactProtocol.h" namespace duckdb { @@ -61,8 +62,8 @@ struct FieldID { class ParquetWriter { public: - ParquetWriter(FileSystem &fs, string file_name, vector types, vector names, - duckdb_parquet::format::CompressionCodec::type codec, ChildFieldIDs field_ids, + ParquetWriter(ClientContext &context, FileSystem &fs, string file_name, vector types, + vector names, duckdb_parquet::format::CompressionCodec::type codec, ChildFieldIDs field_ids, const vector> &kv_metadata, shared_ptr encryption_config, double dictionary_compression_ratio_threshold, optional_idx compression_level); @@ -85,6 +86,9 @@ class ParquetWriter { duckdb_parquet::format::Type::type GetType(idx_t schema_idx) { return file_meta_data.schema[schema_idx].type; } + LogicalType GetSQLType(idx_t schema_idx) const { + return sql_types[schema_idx]; + } BufferedFileWriter &GetWriter() { return *writer; } @@ -98,15 +102,20 @@ class ParquetWriter { optional_idx CompressionLevel() const { return compression_level; } - - static CopyTypeSupport TypeIsSupported(const LogicalType &type); + idx_t NumberOfRowGroups() { + lock_guard glock(lock); + return file_meta_data.row_groups.size(); + } uint32_t Write(const duckdb_apache::thrift::TBase &object); uint32_t WriteData(const const_data_ptr_t buffer, const uint32_t buffer_size); + GeoParquetFileMetadata &GetGeoParquetData(); + + static bool TryGetParquetType(const LogicalType &duckdb_type, + optional_ptr type = nullptr); + private: - static CopyTypeSupport DuckDBTypeToParquetTypeInternal(const LogicalType &duckdb_type, - duckdb_parquet::format::Type::type &type); string file_name; vector sql_types; vector column_names; @@ -122,6 +131,8 @@ class ParquetWriter { std::mutex lock; vector> column_writers; + + unique_ptr geoparquet_data; }; } // namespace duckdb diff --git a/extension/parquet/include/resizable_buffer.hpp b/extension/parquet/include/resizable_buffer.hpp index 39ee933883f..65b639bab7e 100644 --- a/extension/parquet/include/resizable_buffer.hpp +++ b/extension/parquet/include/resizable_buffer.hpp @@ -25,50 +25,72 @@ class ByteBuffer { // on to the 10 thousandth impl uint64_t len = 0; public: - void inc(uint64_t increment) { + void inc(const uint64_t increment) { available(increment); + unsafe_inc(increment); + } + + void unsafe_inc(const uint64_t increment) { len -= increment; ptr += increment; } template T read() { - T val = get(); - inc(sizeof(T)); + available(sizeof(T)); + return unsafe_read(); + } + + template + T unsafe_read() { + T val = unsafe_get(); + unsafe_inc(sizeof(T)); return val; } template T get() { available(sizeof(T)); - T val = Load(ptr); - return val; + return unsafe_get(); } - void copy_to(char *dest, uint64_t len) { + template + T unsafe_get() { + return Load(ptr); + } + + void copy_to(char *dest, const uint64_t len) const { available(len); + unsafe_copy_to(dest, len); + } + + void unsafe_copy_to(char *dest, const uint64_t len) const { std::memcpy(dest, ptr, len); } - void zero() { + void zero() const { std::memset(ptr, 0, len); } - void available(uint64_t req_len) { - if (req_len > len) { + void available(const uint64_t req_len) const { + if (!check_available(req_len)) { throw std::runtime_error("Out of buffer"); } } + + bool check_available(const uint64_t req_len) const { + return req_len <= len; + } }; class ResizeableBuffer : public ByteBuffer { public: ResizeableBuffer() { } - ResizeableBuffer(Allocator &allocator, uint64_t new_size) { + ResizeableBuffer(Allocator &allocator, const uint64_t new_size) { resize(allocator, new_size); } - void resize(Allocator &allocator, uint64_t new_size) { + void resize(Allocator &allocator, const uint64_t new_size) { len = new_size; if (new_size == 0) { return; diff --git a/extension/parquet/include/string_column_reader.hpp b/extension/parquet/include/string_column_reader.hpp index df266015599..f67bbd9da72 100644 --- a/extension/parquet/include/string_column_reader.hpp +++ b/extension/parquet/include/string_column_reader.hpp @@ -16,8 +16,11 @@ struct StringParquetValueConversion { static string_t DictRead(ByteBuffer &dict, uint32_t &offset, ColumnReader &reader); static string_t PlainRead(ByteBuffer &plain_data, ColumnReader &reader); - static void PlainSkip(ByteBuffer &plain_data, ColumnReader &reader); + + static bool PlainAvailable(const ByteBuffer &plain_data, const idx_t count); + static string_t UnsafePlainRead(ByteBuffer &plain_data, ColumnReader &reader); + static void UnsafePlainSkip(ByteBuffer &plain_data, ColumnReader &reader); }; class StringColumnReader : public TemplatedColumnReader { @@ -28,7 +31,7 @@ class StringColumnReader : public TemplatedColumnReader dict_strings; + unsafe_unique_ptr dict_strings; idx_t fixed_width_string_length; idx_t delta_offset = 0; diff --git a/extension/parquet/include/templated_column_reader.hpp b/extension/parquet/include/templated_column_reader.hpp index 009cd6aeeb8..e29d2a98a0f 100644 --- a/extension/parquet/include/templated_column_reader.hpp +++ b/extension/parquet/include/templated_column_reader.hpp @@ -27,6 +27,18 @@ struct TemplatedParquetValueConversion { static void PlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { plain_data.inc(sizeof(VALUE_TYPE)); } + + static bool PlainAvailable(const ByteBuffer &plain_data, const idx_t count) { + return plain_data.check_available(count * sizeof(VALUE_TYPE)); + } + + static VALUE_TYPE UnsafePlainRead(ByteBuffer &plain_data, ColumnReader &reader) { + return plain_data.unsafe_read(); + } + + static void UnsafePlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { + plain_data.unsafe_inc(sizeof(VALUE_TYPE)); + } }; template @@ -56,29 +68,43 @@ class TemplatedColumnReader : public ColumnReader { void Offsets(uint32_t *offsets, uint8_t *defines, uint64_t num_values, parquet_filter_t &filter, idx_t result_offset, Vector &result) override { - auto result_ptr = FlatVector::GetData(result); - auto &result_mask = FlatVector::Validity(result); + if (!dict) { + throw IOException( + "Parquet file is likely corrupted, cannot have dictionary offsets without seeing a dictionary first."); + } + if (HasDefines()) { + OffsetsInternal(*dict, offsets, defines, num_values, filter, result_offset, result); + } else { + OffsetsInternal(*dict, offsets, defines, num_values, filter, result_offset, result); + } + } + void Plain(shared_ptr plain_data, uint8_t *defines, uint64_t num_values, parquet_filter_t &filter, + idx_t result_offset, Vector &result) override { + PlainTemplated(std::move(plain_data), defines, num_values, filter, result_offset, + result); + } + +private: + template + void OffsetsInternal(ResizeableBuffer &dict_ref, uint32_t *__restrict offsets, const uint8_t *__restrict defines, + const uint64_t num_values, const parquet_filter_t &filter, const idx_t result_offset, + Vector &result) { + const auto result_ptr = FlatVector::GetData(result); + auto &result_mask = FlatVector::Validity(result); idx_t offset_idx = 0; - for (idx_t row_idx = 0; row_idx < num_values; row_idx++) { - if (HasDefines() && defines[row_idx + result_offset] != max_define) { - result_mask.SetInvalid(row_idx + result_offset); + for (idx_t row_idx = result_offset; row_idx < result_offset + num_values; row_idx++) { + if (HAS_DEFINES && defines[row_idx] != max_define) { + result_mask.SetInvalid(row_idx); continue; } - if (filter[row_idx + result_offset]) { - VALUE_TYPE val = VALUE_CONVERSION::DictRead(*dict, offsets[offset_idx++], *this); - result_ptr[row_idx + result_offset] = val; + if (filter.test(row_idx)) { + result_ptr[row_idx] = VALUE_CONVERSION::DictRead(dict_ref, offsets[offset_idx++], *this); } else { offset_idx++; } } } - - void Plain(shared_ptr plain_data, uint8_t *defines, uint64_t num_values, parquet_filter_t &filter, - idx_t result_offset, Vector &result) override { - PlainTemplated(std::move(plain_data), defines, num_values, filter, result_offset, - result); - } }; template ()); + } + + static void UnsafePlainSkip(ByteBuffer &plain_data, ColumnReader &reader) { + plain_data.unsafe_inc(sizeof(PARQUET_PHYSICAL_TYPE)); + } }; } // namespace duckdb diff --git a/extension/parquet/parquet_config.py b/extension/parquet/parquet_config.py index 344fe52c190..7b8ba00a07a 100644 --- a/extension/parquet/parquet_config.py +++ b/extension/parquet/parquet_config.py @@ -8,6 +8,10 @@ 'third_party/parquet', 'third_party/thrift', 'third_party/lz4', + 'third_party/brotli/include', + 'third_party/brotli/common', + 'third_party/brotli/dec', + 'third_party/brotli/enc', 'third_party/snappy', 'third_party/zstd/include', 'third_party/mbedtls', @@ -29,6 +33,7 @@ 'extension/parquet/parquet_writer.cpp', 'extension/parquet/serialize_parquet.cpp', 'extension/parquet/zstd_file_system.cpp', + 'extension/parquet/geo_parquet.cpp', ] ] # parquet/thrift/snappy @@ -73,3 +78,41 @@ ] # lz4 source_files += [os.path.sep.join(x.split('/')) for x in ['third_party/lz4/lz4.cpp']] + +# brotli +source_files += [ + os.path.sep.join(x.split('/')) + for x in [ + 'third_party/brotli/common/constants.cpp', + 'third_party/brotli/common/context.cpp', + 'third_party/brotli/common/dictionary.cpp', + 'third_party/brotli/common/platform.cpp', + 'third_party/brotli/common/shared_dictionary.cpp', + 'third_party/brotli/common/transform.cpp', + 'third_party/brotli/dec/bit_reader.cpp', + 'third_party/brotli/dec/decode.cpp', + 'third_party/brotli/dec/huffman.cpp', + 'third_party/brotli/dec/state.cpp', + 'third_party/brotli/enc/backward_references.cpp', + 'third_party/brotli/enc/backward_references_hq.cpp', + 'third_party/brotli/enc/bit_cost.cpp', + 'third_party/brotli/enc/block_splitter.cpp', + 'third_party/brotli/enc/brotli_bit_stream.cpp', + 'third_party/brotli/enc/cluster.cpp', + 'third_party/brotli/enc/command.cpp', + 'third_party/brotli/enc/compound_dictionary.cpp', + 'third_party/brotli/enc/compress_fragment.cpp', + 'third_party/brotli/enc/compress_fragment_two_pass.cpp', + 'third_party/brotli/enc/dictionary_hash.cpp', + 'third_party/brotli/enc/encode.cpp', + 'third_party/brotli/enc/encoder_dict.cpp', + 'third_party/brotli/enc/entropy_encode.cpp', + 'third_party/brotli/enc/fast_log.cpp', + 'third_party/brotli/enc/histogram.cpp', + 'third_party/brotli/enc/literal_cost.cpp', + 'third_party/brotli/enc/memory.cpp', + 'third_party/brotli/enc/metablock.cpp', + 'third_party/brotli/enc/static_dict.cpp', + 'third_party/brotli/enc/utf8_util.cpp', + ] +] diff --git a/extension/parquet/parquet_crypto.cpp b/extension/parquet/parquet_crypto.cpp index d6bb7f1b220..71cf79b8939 100644 --- a/extension/parquet/parquet_crypto.cpp +++ b/extension/parquet/parquet_crypto.cpp @@ -4,8 +4,9 @@ #include "thrift_tools.hpp" #ifndef DUCKDB_AMALGAMATION +#include "duckdb/common/exception/conversion_exception.hpp" #include "duckdb/common/helper.hpp" -#include "duckdb/common/common.hpp" +#include "duckdb/common/types/blob.hpp" #include "duckdb/storage/arena_allocator.hpp" #endif @@ -358,15 +359,34 @@ uint32_t ParquetCrypto::WriteData(TProtocol &oprot, const const_data_ptr_t buffe return etrans.Finalize(); } +string Base64Decode(const string &key) { + auto result_size = Blob::FromBase64Size(key); + auto output = duckdb::unique_ptr(new unsigned char[result_size]); + Blob::FromBase64(key, output.get(), result_size); + string decoded_key(reinterpret_cast(output.get()), result_size); + return decoded_key; +} + void ParquetCrypto::AddKey(ClientContext &context, const FunctionParameters ¶meters) { const auto &key_name = StringValue::Get(parameters.values[0]); const auto &key = StringValue::Get(parameters.values[1]); - if (!AESGCMState::ValidKey(key)) { - throw InvalidInputException( - "Invalid AES key. Must have a length of 128, 192, or 256 bits (16, 24, or 32 bytes)"); - } + auto &keys = ParquetKeys::Get(context); - keys.AddKey(key_name, key); + if (AESGCMState::ValidKey(key)) { + keys.AddKey(key_name, key); + } else { + string decoded_key; + try { + decoded_key = Base64Decode(key); + } catch (const ConversionException &e) { + throw InvalidInputException("Invalid AES key. Not a plain AES key NOR a base64 encoded string"); + } + if (!AESGCMState::ValidKey(decoded_key)) { + throw InvalidInputException( + "Invalid AES key. Must have a length of 128, 192, or 256 bits (16, 24, or 32 bytes)"); + } + keys.AddKey(key_name, decoded_key); + } } } // namespace duckdb diff --git a/extension/parquet/parquet_extension.cpp b/extension/parquet/parquet_extension.cpp index 69e329bd31e..4fc12001b52 100644 --- a/extension/parquet/parquet_extension.cpp +++ b/extension/parquet/parquet_extension.cpp @@ -8,6 +8,12 @@ #include "parquet_metadata.hpp" #include "parquet_reader.hpp" #include "parquet_writer.hpp" +#include "geo_parquet.hpp" +#include "duckdb/parser/query_node/select_node.hpp" +#include "duckdb/planner/query_node/bound_select_node.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" +#include "duckdb/parser/expression/positional_reference_expression.hpp" +#include "duckdb/parser/tableref/subqueryref.hpp" #include "struct_column_reader.hpp" #include "zstd_file_system.hpp" @@ -17,15 +23,16 @@ #include #include #ifndef DUCKDB_AMALGAMATION -#include "duckdb/common/helper.hpp" #include "duckdb/catalog/catalog.hpp" #include "duckdb/catalog/catalog_entry/table_function_catalog_entry.hpp" #include "duckdb/common/constants.hpp" #include "duckdb/common/enums/file_compression_type.hpp" #include "duckdb/common/file_system.hpp" +#include "duckdb/common/helper.hpp" #include "duckdb/common/multi_file_reader.hpp" #include "duckdb/common/serializer/deserializer.hpp" #include "duckdb/common/serializer/serializer.hpp" +#include "duckdb/common/type_visitor.hpp" #include "duckdb/function/copy_function.hpp" #include "duckdb/function/pragma_function.hpp" #include "duckdb/function/table_function.hpp" @@ -40,13 +47,16 @@ #include "duckdb/planner/operator/logical_get.hpp" #include "duckdb/storage/statistics/base_statistics.hpp" #include "duckdb/storage/table/row_group.hpp" +#include "duckdb/planner/expression/bound_cast_expression.hpp" #endif namespace duckdb { struct ParquetReadBindData : public TableFunctionData { + shared_ptr file_list; + unique_ptr multi_file_reader; + shared_ptr initial_reader; - vector files; atomic chunk_count; vector names; vector types; @@ -59,6 +69,7 @@ struct ParquetReadBindData : public TableFunctionData { idx_t initial_file_cardinality; idx_t initial_file_row_groups; ParquetOptions parquet_options; + MultiFileReaderBindData reader_bind; void Initialize(shared_ptr reader) { @@ -75,23 +86,45 @@ struct ParquetReadLocalState : public LocalTableFunctionState { bool is_parallel; idx_t batch_index; idx_t file_index; - //! The DataChunk containing all read columns (even filter columns that are immediately removed) + //! The DataChunk containing all read columns (even columns that are immediately removed) DataChunk all_columns; }; enum class ParquetFileState : uint8_t { UNOPENED, OPENING, OPEN, CLOSED }; +struct ParquetFileReaderData { + // Create data for an unopened file + explicit ParquetFileReaderData(const string &file_to_be_opened) + : reader(nullptr), file_state(ParquetFileState::UNOPENED), file_mutex(make_uniq()), + file_to_be_opened(file_to_be_opened) { + } + // Create data for an existing reader + explicit ParquetFileReaderData(shared_ptr reader_p) + : reader(std::move(reader_p)), file_state(ParquetFileState::OPEN), file_mutex(make_uniq()) { + } + + //! Currently opened reader for the file + shared_ptr reader; + //! Flag to indicate the file is being opened + ParquetFileState file_state; + //! Mutexes to wait for the file when it is being opened + unique_ptr file_mutex; + + //! (only set when file_state is UNOPENED) the file to be opened + string file_to_be_opened; +}; + struct ParquetReadGlobalState : public GlobalTableFunctionState { + //! The scan over the file_list + MultiFileListScanData file_list_scan; + + unique_ptr multi_file_reader_state; + mutex lock; - //! The initial reader from the bind phase - shared_ptr initial_reader; - //! Currently opened readers - vector> readers; - //! Flag to indicate a file is being opened - vector file_states; - //! Mutexes to wait for a file that is currently being opened - unique_ptr file_mutexes; + //! The current set of parquet readers + vector readers; + //! Signal to other threads that a file failed to open, letting every thread abort. bool error_opening_file = false; @@ -112,7 +145,7 @@ struct ParquetReadGlobalState : public GlobalTableFunctionState { return max_threads; } - bool CanRemoveFilterColumns() const { + bool CanRemoveColumns() const { return !projection_ids.empty(); } }; @@ -134,6 +167,9 @@ struct ParquetWriteBindData : public TableFunctionData { //! Dictionary compression is applied only if the compression ratio exceeds this threshold double dictionary_compression_ratio_threshold = 1.0; + //! After how many row groups to rotate to a new file + optional_idx row_groups_per_file; + ChildFieldIDs field_ids; //! The compression level, higher value is more optional_idx compression_level; @@ -156,10 +192,12 @@ struct ParquetWriteLocalState : public LocalFunctionData { BindInfo ParquetGetBindInfo(const optional_ptr bind_data) { auto bind_info = BindInfo(ScanType::PARQUET); auto &parquet_bind = bind_data->Cast(); + vector file_path; - for (auto &path : parquet_bind.files) { - file_path.emplace_back(path); + for (const auto &file : parquet_bind.file_list->Files()) { + file_path.emplace_back(file); } + // LCOV_EXCL_START bind_info.InsertOption("file_path", Value::LIST(LogicalType::VARCHAR, file_path)); bind_info.InsertOption("binary_as_string", Value::BOOLEAN(parquet_bind.parquet_options.binary_as_string)); @@ -169,9 +207,26 @@ BindInfo ParquetGetBindInfo(const optional_ptr bind_data) { return bind_info; } +static void ParseFileRowNumberOption(MultiFileReaderBindData &bind_data, ParquetOptions &options, + vector &return_types, vector &names) { + if (options.file_row_number) { + if (StringUtil::CIFind(names, "file_row_number") != DConstants::INVALID_INDEX) { + throw BinderException( + "Using file_row_number option on file with column named file_row_number is not supported"); + } + + bind_data.file_row_number_idx = names.size(); + return_types.emplace_back(LogicalType::BIGINT); + names.emplace_back("file_row_number"); + } +} + static MultiFileReaderBindData BindSchema(ClientContext &context, vector &return_types, vector &names, ParquetReadBindData &result, ParquetOptions &options) { D_ASSERT(!options.schema.empty()); + + options.file_options.AutoDetectHivePartitioning(*result.file_list, context); + auto &file_options = options.file_options; if (file_options.union_by_name || file_options.hive_partitioning) { throw BinderException("Parquet schema cannot be combined with union_by_name=true or hive_partitioning=true"); @@ -187,45 +242,42 @@ static MultiFileReaderBindData BindSchema(ClientContext &context, vectorBindOptions(options.file_options, *result.file_list, schema_col_types, schema_col_names, + bind_data); names = schema_col_names; return_types = schema_col_types; D_ASSERT(names.size() == return_types.size()); - if (options.file_row_number) { - if (std::find(names.begin(), names.end(), "file_row_number") != names.end()) { - throw BinderException( - "Using file_row_number option on file with column named file_row_number is not supported"); - } - - bind_data.file_row_number_idx = names.size(); - return_types.emplace_back(LogicalType::BIGINT); - names.emplace_back("file_row_number"); - } + ParseFileRowNumberOption(bind_data, options, return_types, names); return bind_data; } static void InitializeParquetReader(ParquetReader &reader, const ParquetReadBindData &bind_data, const vector &global_column_ids, - optional_ptr table_filters, ClientContext &context) { + optional_ptr table_filters, ClientContext &context, + optional_idx file_idx, optional_ptr reader_state) { auto &parquet_options = bind_data.parquet_options; auto &reader_data = reader.reader_data; + + // Mark the file in the file list we are scanning here + reader_data.file_list_idx = file_idx; + if (bind_data.parquet_options.schema.empty()) { - MultiFileReader::InitializeReader(reader, parquet_options.file_options, bind_data.reader_bind, bind_data.types, - bind_data.names, global_column_ids, table_filters, bind_data.files[0], - context); + bind_data.multi_file_reader->InitializeReader( + reader, parquet_options.file_options, bind_data.reader_bind, bind_data.types, bind_data.names, + global_column_ids, table_filters, bind_data.file_list->GetFirstFile(), context, reader_state); return; } // a fixed schema was supplied, initialize the MultiFileReader settings here so we can read using the schema // this deals with hive partitioning and filename=true - MultiFileReader::FinalizeBind(parquet_options.file_options, bind_data.reader_bind, reader.GetFileName(), - reader.GetNames(), bind_data.types, bind_data.names, global_column_ids, reader_data, - context); + bind_data.multi_file_reader->FinalizeBind(parquet_options.file_options, bind_data.reader_bind, reader.GetFileName(), + reader.GetNames(), bind_data.types, bind_data.names, global_column_ids, + reader_data, context, reader_state); // create a mapping from field id to column index in file unordered_map field_id_to_column_index; @@ -284,7 +336,7 @@ static void InitializeParquetReader(ParquetReader &reader, const ParquetReadBind reader_data.empty_columns = reader_data.column_ids.empty(); // Finally, initialize the filters - MultiFileReader::CreateFilterMap(bind_data.types, table_filters, reader_data); + bind_data.multi_file_reader->CreateFilterMap(bind_data.types, table_filters, reader_data, reader_state); reader_data.filters = table_filters; } @@ -317,7 +369,6 @@ class ParquetScanFunction { {"type", LogicalType::VARCHAR}, {"default_value", LogicalType::VARCHAR}}})); table_function.named_parameters["encryption_config"] = LogicalTypeId::ANY; - MultiFileReader::AddParameters(table_function); table_function.get_batch_index = ParquetScanGetBatchIndex; table_function.serialize = ParquetScanSerialize; table_function.deserialize = ParquetScanDeserialize; @@ -326,6 +377,9 @@ class ParquetScanFunction { table_function.filter_pushdown = true; table_function.filter_prune = true; table_function.pushdown_complex_filter = ParquetComplexFilterPushdown; + + MultiFileReader::AddParameters(table_function); + return MultiFileReader::CreateFunctionSet(table_function); } @@ -355,8 +409,13 @@ class ParquetScanFunction { } } - auto files = MultiFileReader::GetFileList(context, Value(info.file_path), "Parquet"); - return ParquetScanBindInternal(context, std::move(files), expected_types, expected_names, parquet_options); + // TODO: Allow overriding the MultiFileReader for COPY FROM? + auto multi_file_reader = MultiFileReader::CreateDefault("ParquetCopy"); + vector paths = {info.file_path}; + auto file_list = multi_file_reader->CreateFileList(context, paths); + + return ParquetScanBindInternal(context, std::move(multi_file_reader), std::move(file_list), expected_types, + expected_names, parquet_options); } static unique_ptr ParquetScanStats(ClientContext &context, const FunctionData *bind_data_p, @@ -370,7 +429,8 @@ class ParquetScanFunction { // NOTE: we do not want to parse the Parquet metadata for the sole purpose of getting column statistics auto &config = DBConfig::GetConfig(context); - if (bind_data.files.size() < 2) { + + if (bind_data.file_list->GetExpandResult() != FileExpandResult::MULTIPLE_FILES) { if (bind_data.initial_reader) { // most common path, scanning single parquet file return bind_data.initial_reader->ReadStatistics(bind_data.names[column_index]); @@ -387,8 +447,7 @@ class ParquetScanFunction { // enabled at all) FileSystem &fs = FileSystem::GetFileSystem(context); - for (idx_t file_idx = 0; file_idx < bind_data.files.size(); file_idx++) { - auto &file_name = bind_data.files[file_idx]; + for (const auto &file_name : bind_data.file_list->Files()) { auto metadata = cache.Get(file_name); if (!metadata) { // missing metadata entry in cache, no usable stats @@ -425,17 +484,33 @@ class ParquetScanFunction { return nullptr; } - static unique_ptr ParquetScanBindInternal(ClientContext &context, vector files, + static unique_ptr ParquetScanBindInternal(ClientContext &context, + unique_ptr multi_file_reader, + unique_ptr file_list, vector &return_types, vector &names, ParquetOptions parquet_options) { auto result = make_uniq(); - result->files = std::move(files); - if (parquet_options.schema.empty()) { - result->reader_bind = MultiFileReader::BindReader(context, result->types, result->names, - *result, parquet_options); - } else { - // a schema was supplied + result->multi_file_reader = std::move(multi_file_reader); + result->file_list = std::move(file_list); + + bool bound_on_first_file = true; + if (result->multi_file_reader->Bind(parquet_options.file_options, *result->file_list, result->types, + result->names, result->reader_bind)) { + result->multi_file_reader->BindOptions(parquet_options.file_options, *result->file_list, result->types, + result->names, result->reader_bind); + // Enable the parquet file_row_number on the parquet options if the file_row_number_idx was set + if (result->reader_bind.file_row_number_idx != DConstants::INVALID_INDEX) { + parquet_options.file_row_number = true; + } + bound_on_first_file = false; + } else if (!parquet_options.schema.empty()) { + // A schema was supplied: use the schema for binding result->reader_bind = BindSchema(context, result->types, result->names, *result, parquet_options); + } else { + parquet_options.file_options.AutoDetectHivePartitioning(*result->file_list, context); + // Default bind + result->reader_bind = result->multi_file_reader->BindReader( + context, result->types, result->names, *result->file_list, *result, parquet_options); } if (return_types.empty()) { @@ -444,9 +519,11 @@ class ParquetScanFunction { names = result->names; } else { if (return_types.size() != result->types.size()) { + auto file_string = bound_on_first_file ? result->file_list->GetFirstFile() + : StringUtil::Join(result->file_list->GetPaths(), ","); throw std::runtime_error(StringUtil::Format( - "Failed to read file \"%s\" - column count mismatch: expected %d columns but found %d", - result->files[0], return_types.size(), result->types.size())); + "Failed to read file(s) \"%s\" - column count mismatch: expected %d columns but found %d", + file_string, return_types.size(), result->types.size())); } // expected types - overwrite the types we want to read instead result->types = return_types; @@ -457,11 +534,12 @@ class ParquetScanFunction { static unique_ptr ParquetScanBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { - auto files = MultiFileReader::GetFileList(context, input.inputs[0], "Parquet"); + auto multi_file_reader = MultiFileReader::Create(input.table_function); + ParquetOptions parquet_options(context); for (auto &kv : input.named_parameters) { auto loption = StringUtil::Lower(kv.first); - if (MultiFileReader::ParseOption(kv.first, kv.second, parquet_options.file_options, context)) { + if (multi_file_reader->ParseOption(kv.first, kv.second, parquet_options.file_options, context)) { continue; } if (loption == "binary_as_string") { @@ -487,23 +565,27 @@ class ParquetScanFunction { parquet_options.encryption_config = ParquetEncryptionConfig::Create(context, kv.second); } } - parquet_options.file_options.AutoDetectHivePartitioning(files, context); - return ParquetScanBindInternal(context, std::move(files), return_types, names, parquet_options); + + auto file_list = multi_file_reader->CreateFileList(context, input.inputs[0]); + return ParquetScanBindInternal(context, std::move(multi_file_reader), std::move(file_list), return_types, names, + parquet_options); } static double ParquetProgress(ClientContext &context, const FunctionData *bind_data_p, const GlobalTableFunctionState *global_state) { auto &bind_data = bind_data_p->Cast(); auto &gstate = global_state->Cast(); - if (bind_data.files.empty()) { + + auto total_count = bind_data.file_list->GetTotalFileCount(); + if (total_count == 0) { return 100.0; } if (bind_data.initial_file_cardinality == 0) { - return (100.0 * (gstate.file_index + 1)) / bind_data.files.size(); + return (100.0 * (gstate.file_index + 1)) / total_count; } auto percentage = MinValue( 100.0, (bind_data.chunk_count * STANDARD_VECTOR_SIZE * 100.0 / bind_data.initial_file_cardinality)); - return (percentage + 100.0 * gstate.file_index) / bind_data.files.size(); + return (percentage + 100.0 * gstate.file_index) / total_count; } static unique_ptr @@ -514,7 +596,8 @@ class ParquetScanFunction { auto result = make_uniq(); result->is_parallel = true; result->batch_index = 0; - if (input.CanRemoveFilterColumns()) { + + if (gstate.CanRemoveColumns()) { result->all_columns.Initialize(context.client, gstate.scanned_types); } if (!ParquetParallelStateNext(context.client, bind_data, *result, gstate)) { @@ -527,35 +610,46 @@ class ParquetScanFunction { TableFunctionInitInput &input) { auto &bind_data = input.bind_data->CastNoConst(); auto result = make_uniq(); - - result->file_states = vector(bind_data.files.size(), ParquetFileState::UNOPENED); - result->file_mutexes = unique_ptr(new mutex[bind_data.files.size()]); - if (bind_data.files.empty()) { - result->initial_reader = nullptr; - } else { - result->readers = std::move(bind_data.union_readers); - if (result->readers.size() != bind_data.files.size()) { - result->readers = vector>(bind_data.files.size(), nullptr); - } else { - std::fill(result->file_states.begin(), result->file_states.end(), ParquetFileState::OPEN); + bind_data.file_list->InitializeScan(result->file_list_scan); + + result->multi_file_reader_state = bind_data.multi_file_reader->InitializeGlobalState( + context, bind_data.parquet_options.file_options, bind_data.reader_bind, *bind_data.file_list, + bind_data.types, bind_data.names, input.column_ids); + if (bind_data.file_list->IsEmpty()) { + result->readers = {}; + } else if (!bind_data.union_readers.empty()) { + // TODO: confirm we are not changing behaviour by modifying the order here? + for (auto &reader : bind_data.union_readers) { + if (!reader) { + break; + } + result->readers.push_back(ParquetFileReaderData(std::move(reader))); } - if (bind_data.initial_reader) { - result->initial_reader = std::move(bind_data.initial_reader); - result->readers[0] = result->initial_reader; - } else if (result->readers[0]) { - result->initial_reader = result->readers[0]; - } else { - result->initial_reader = - make_shared_ptr(context, bind_data.files[0], bind_data.parquet_options); - result->readers[0] = result->initial_reader; + if (result->readers.size() != bind_data.file_list->GetTotalFileCount()) { + // This case happens with recursive CTEs: the first execution the readers have already + // been moved out of the bind data. + // FIXME: clean up this process and make it more explicit + result->readers = {}; } - result->file_states[0] = ParquetFileState::OPEN; + } else if (bind_data.initial_reader) { + // Ensure the initial reader was actually constructed from the first file + if (bind_data.initial_reader->file_name != bind_data.file_list->GetFirstFile()) { + throw InternalException("First file from list ('%s') does not match first reader ('%s')", + bind_data.initial_reader->file_name, bind_data.file_list->GetFirstFile()); + } + result->readers.emplace_back(std::move(bind_data.initial_reader)); } - for (auto &reader : result->readers) { - if (!reader) { - continue; + + // Ensure all readers are initialized and FileListScan is sync with readers list + for (auto &reader_data : result->readers) { + string file_name; + idx_t file_idx = result->file_list_scan.current_file_idx; + bind_data.file_list->Scan(result->file_list_scan, file_name); + if (file_name != reader_data.reader->file_name) { + throw InternalException("Mismatch in filename order and reader order in parquet scan"); } - InitializeParquetReader(*reader, bind_data, input.column_ids, input.filters, context); + InitializeParquetReader(*reader_data.reader, bind_data, input.column_ids, input.filters, context, file_idx, + result->multi_file_reader_state); } result->column_ids = input.column_ids; @@ -564,8 +658,17 @@ class ParquetScanFunction { result->file_index = 0; result->batch_index = 0; result->max_threads = ParquetScanMaxThreads(context, input.bind_data.get()); - if (input.CanRemoveFilterColumns()) { - result->projection_ids = input.projection_ids; + + bool require_extra_columns = + result->multi_file_reader_state && result->multi_file_reader_state->RequiresExtraColumns(); + if (input.CanRemoveFilterColumns() || require_extra_columns) { + if (!input.projection_ids.empty()) { + result->projection_ids = input.projection_ids; + } else { + result->projection_ids.resize(input.column_ids.size()); + iota(begin(result->projection_ids), end(result->projection_ids), 0); + } + const auto table_types = bind_data.types; for (const auto &col_idx : input.column_ids) { if (IsRowIdColumnId(col_idx)) { @@ -575,6 +678,13 @@ class ParquetScanFunction { } } } + + if (require_extra_columns) { + for (const auto &column_type : result->multi_file_reader_state->extra_columns) { + result->scanned_types.push_back(column_type); + } + } + return std::move(result); } @@ -588,7 +698,8 @@ class ParquetScanFunction { static void ParquetScanSerialize(Serializer &serializer, const optional_ptr bind_data_p, const TableFunction &function) { auto &bind_data = bind_data_p->Cast(); - serializer.WriteProperty(100, "files", bind_data.files); + + serializer.WriteProperty(100, "files", bind_data.file_list->GetAllFiles()); serializer.WriteProperty(101, "types", bind_data.types); serializer.WriteProperty(102, "names", bind_data.names); serializer.WriteProperty(103, "parquet_options", bind_data.parquet_options); @@ -600,7 +711,17 @@ class ParquetScanFunction { auto types = deserializer.ReadProperty>(101, "types"); auto names = deserializer.ReadProperty>(102, "names"); auto parquet_options = deserializer.ReadProperty(103, "parquet_options"); - return ParquetScanBindInternal(context, files, types, names, parquet_options); + + vector file_path; + for (auto &path : files) { + file_path.emplace_back(path); + } + + auto multi_file_reader = MultiFileReader::Create(function); + auto file_list = multi_file_reader->CreateFileList(context, Value::LIST(LogicalType::VARCHAR, file_path), + FileGlobOptions::DISALLOW_EMPTY); + return ParquetScanBindInternal(context, std::move(multi_file_reader), std::move(file_list), types, names, + parquet_options); } static void ParquetScanImplementation(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { @@ -612,14 +733,16 @@ class ParquetScanFunction { auto &bind_data = data_p.bind_data->CastNoConst(); do { - if (gstate.CanRemoveFilterColumns()) { + if (gstate.CanRemoveColumns()) { data.all_columns.Reset(); data.reader->Scan(data.scan_state, data.all_columns); - MultiFileReader::FinalizeChunk(bind_data.reader_bind, data.reader->reader_data, data.all_columns); + bind_data.multi_file_reader->FinalizeChunk(context, bind_data.reader_bind, data.reader->reader_data, + data.all_columns, gstate.multi_file_reader_state); output.ReferenceColumns(data.all_columns, gstate.projection_ids); } else { data.reader->Scan(data.scan_state, output); - MultiFileReader::FinalizeChunk(bind_data.reader_bind, data.reader->reader_data, output); + bind_data.multi_file_reader->FinalizeChunk(context, bind_data.reader_bind, data.reader->reader_data, + output, gstate.multi_file_reader_state); } bind_data.chunk_count++; @@ -634,17 +757,33 @@ class ParquetScanFunction { static unique_ptr ParquetCardinality(ClientContext &context, const FunctionData *bind_data) { auto &data = bind_data->Cast(); - return make_uniq(data.initial_file_cardinality * data.files.size()); + return make_uniq(data.initial_file_cardinality * data.file_list->GetTotalFileCount()); } static idx_t ParquetScanMaxThreads(ClientContext &context, const FunctionData *bind_data) { auto &data = bind_data->Cast(); - if (data.files.size() > 1) { + + if (data.file_list->GetExpandResult() == FileExpandResult::MULTIPLE_FILES) { return TaskScheduler::GetScheduler(context).NumberOfThreads(); } + return MaxValue(data.initial_file_row_groups, (idx_t)1); } + // Queries the metadataprovider for another file to scan, updating the files/reader lists in the process. + // Returns true if resized + static bool ResizeFiles(const ParquetReadBindData &bind_data, ParquetReadGlobalState ¶llel_state) { + string scanned_file; + if (!bind_data.file_list->Scan(parallel_state.file_list_scan, scanned_file)) { + return false; + } + + // Push the file in the reader data, to be opened later + parallel_state.readers.emplace_back(scanned_file); + + return true; + } + // This function looks for the next available row group. If not available, it will open files from bind_data.files // until there is a row group available for scanning or the files runs out static bool ParquetParallelStateNext(ClientContext &context, const ParquetReadBindData &bind_data, @@ -656,35 +795,30 @@ class ParquetScanFunction { return false; } - if (parallel_state.file_index >= parallel_state.readers.size()) { + if (parallel_state.file_index >= parallel_state.readers.size() && !ResizeFiles(bind_data, parallel_state)) { return false; } - D_ASSERT(parallel_state.initial_reader); - - if (parallel_state.file_states[parallel_state.file_index] == ParquetFileState::OPEN) { - if (parallel_state.row_group_index < - parallel_state.readers[parallel_state.file_index]->NumRowGroups()) { + auto ¤t_reader_data = parallel_state.readers[parallel_state.file_index]; + if (current_reader_data.file_state == ParquetFileState::OPEN) { + if (parallel_state.row_group_index < current_reader_data.reader->NumRowGroups()) { // The current reader has rowgroups left to be scanned - scan_data.reader = parallel_state.readers[parallel_state.file_index]; + scan_data.reader = current_reader_data.reader; vector group_indexes {parallel_state.row_group_index}; - scan_data.reader->InitializeScan(scan_data.scan_state, group_indexes); + scan_data.reader->InitializeScan(context, scan_data.scan_state, group_indexes); scan_data.batch_index = parallel_state.batch_index++; scan_data.file_index = parallel_state.file_index; parallel_state.row_group_index++; return true; } else { // Close current file - parallel_state.file_states[parallel_state.file_index] = ParquetFileState::CLOSED; - parallel_state.readers[parallel_state.file_index] = nullptr; + current_reader_data.file_state = ParquetFileState::CLOSED; + current_reader_data.reader = nullptr; // Set state to the next file parallel_state.file_index++; parallel_state.row_group_index = 0; - if (parallel_state.file_index >= bind_data.files.size()) { - return false; - } continue; } } @@ -694,7 +828,7 @@ class ParquetScanFunction { } // Check if the current file is being opened, in that case we need to wait for it. - if (parallel_state.file_states[parallel_state.file_index] == ParquetFileState::OPENING) { + if (parallel_state.readers[parallel_state.file_index].file_state == ParquetFileState::OPENING) { WaitForFile(parallel_state.file_index, parallel_state, parallel_lock); } } @@ -704,10 +838,12 @@ class ParquetScanFunction { vector> &filters) { auto &data = bind_data_p->Cast(); - auto reset_reader = MultiFileReader::ComplexFilterPushdown(context, data.files, - data.parquet_options.file_options, get, filters); - if (reset_reader) { - MultiFileReader::PruneReaders(data); + auto new_list = data.multi_file_reader->ComplexFilterPushdown(context, *data.file_list, + data.parquet_options.file_options, get, filters); + + if (new_list) { + data.file_list = std::move(new_list); + MultiFileReader::PruneReaders(data, *data.file_list); } } @@ -715,9 +851,14 @@ class ParquetScanFunction { static void WaitForFile(idx_t file_index, ParquetReadGlobalState ¶llel_state, unique_lock ¶llel_lock) { while (true) { - // To get the file lock, we first need to release the parallel_lock to prevent deadlocking + + // Get pointer to file mutex before unlocking + auto &file_mutex = *parallel_state.readers[file_index].file_mutex; + + // To get the file lock, we first need to release the parallel_lock to prevent deadlocking. Note that this + // requires getting the ref to the file mutex pointer with the lock stil held: readers get be resized parallel_lock.unlock(); - unique_lock current_file_lock(parallel_state.file_mutexes[file_index]); + unique_lock current_file_lock(file_mutex); parallel_lock.lock(); // Here we have both locks which means we can stop waiting if: @@ -725,7 +866,7 @@ class ParquetScanFunction { // - the thread opening the file has failed // - the file was somehow scanned till the end while we were waiting if (parallel_state.file_index >= parallel_state.readers.size() || - parallel_state.file_states[parallel_state.file_index] != ParquetFileState::OPENING || + parallel_state.readers[parallel_state.file_index].file_state != ParquetFileState::OPENING || parallel_state.error_opening_file) { return; } @@ -737,24 +878,29 @@ class ParquetScanFunction { ParquetReadLocalState &scan_data, ParquetReadGlobalState ¶llel_state, unique_lock ¶llel_lock) { const auto num_threads = TaskScheduler::GetScheduler(context).NumberOfThreads(); - const auto file_index_limit = MinValue(parallel_state.file_index + num_threads, bind_data.files.size()); + + const auto file_index_limit = + MinValue(parallel_state.file_index + num_threads, parallel_state.readers.size()); + for (idx_t i = parallel_state.file_index; i < file_index_limit; i++) { - if (parallel_state.file_states[i] == ParquetFileState::UNOPENED) { - string file = bind_data.files[i]; - parallel_state.file_states[i] = ParquetFileState::OPENING; - auto pq_options = parallel_state.initial_reader->parquet_options; + if (parallel_state.readers[i].file_state == ParquetFileState::UNOPENED) { + auto ¤t_reader_data = parallel_state.readers[i]; + current_reader_data.file_state = ParquetFileState::OPENING; + auto pq_options = bind_data.parquet_options; + + // Get pointer to file mutex before unlocking + auto ¤t_file_lock = *current_reader_data.file_mutex; // Now we switch which lock we are holding, instead of locking the global state, we grab the lock on // the file we are opening. This file lock allows threads to wait for a file to be opened. parallel_lock.unlock(); - - unique_lock file_lock(parallel_state.file_mutexes[i]); + unique_lock file_lock(current_file_lock); shared_ptr reader; try { - reader = make_shared_ptr(context, file, pq_options); + reader = make_shared_ptr(context, current_reader_data.file_to_be_opened, pq_options); InitializeParquetReader(*reader, bind_data, parallel_state.column_ids, parallel_state.filters, - context); + context, i, parallel_state.multi_file_reader_state); } catch (...) { parallel_lock.lock(); parallel_state.error_opening_file = true; @@ -763,8 +909,8 @@ class ParquetScanFunction { // Now re-lock the state and add the reader parallel_lock.lock(); - parallel_state.readers[i] = reader; - parallel_state.file_states[i] = ParquetFileState::OPEN; + current_reader_data.reader = reader; + current_reader_data.file_state = ParquetFileState::OPEN; return true; } @@ -943,6 +1089,8 @@ unique_ptr ParquetWriteBind(ClientContext &context, CopyFunctionBi bind_data->row_group_size_bytes = option.second[0].GetValue(); } row_group_size_bytes_set = true; + } else if (loption == "row_groups_per_file") { + bind_data->row_groups_per_file = option.second[0].GetValue(); } else if (loption == "compression" || loption == "codec") { const auto roption = StringUtil::Lower(option.second[0].ToString()); if (roption == "uncompressed") { @@ -953,12 +1101,14 @@ unique_ptr ParquetWriteBind(ClientContext &context, CopyFunctionBi bind_data->codec = duckdb_parquet::format::CompressionCodec::GZIP; } else if (roption == "zstd") { bind_data->codec = duckdb_parquet::format::CompressionCodec::ZSTD; + } else if (roption == "brotli") { + bind_data->codec = duckdb_parquet::format::CompressionCodec::BROTLI; } else if (roption == "lz4" || roption == "lz4_raw") { /* LZ4 is technically another compression scheme, but deprecated and arrow also uses them * interchangeably */ bind_data->codec = duckdb_parquet::format::CompressionCodec::LZ4_RAW; } else { - throw BinderException("Expected %s argument to be either [uncompressed, snappy, gzip or zstd]", + throw BinderException("Expected %s argument to be either [uncompressed, brotli, gzip, snappy, or zstd]", loption); } } else if (loption == "field_ids") { @@ -1035,7 +1185,7 @@ unique_ptr ParquetWriteInitializeGlobal(ClientContext &conte auto &fs = FileSystem::GetFileSystem(context); global_state->writer = make_uniq( - fs, file_path, parquet_bind.sql_types, parquet_bind.column_names, parquet_bind.codec, + context, fs, file_path, parquet_bind.sql_types, parquet_bind.column_names, parquet_bind.codec, parquet_bind.field_ids.Copy(), parquet_bind.kv_metadata, parquet_bind.encryption_config, parquet_bind.dictionary_compression_ratio_threshold, parquet_bind.compression_level); return std::move(global_state); @@ -1050,8 +1200,8 @@ void ParquetWriteSink(ExecutionContext &context, FunctionData &bind_data_p, Glob // append data to the local (buffered) chunk collection local_state.buffer.Append(local_state.append_state, input); - if (local_state.buffer.Count() > bind_data.row_group_size || - local_state.buffer.SizeInBytes() > bind_data.row_group_size_bytes) { + if (local_state.buffer.Count() >= bind_data.row_group_size || + local_state.buffer.SizeInBytes() >= bind_data.row_group_size_bytes) { // if the chunk collection exceeds a certain size (rows/bytes) we flush it to the parquet file local_state.append_state.current_chunk_state.handles.clear(); global_state.writer->Flush(local_state.buffer); @@ -1159,6 +1309,7 @@ static void ParquetCopySerialize(Serializer &serializer, const FunctionData &bin serializer.WriteProperty(108, "dictionary_compression_ratio_threshold", bind_data.dictionary_compression_ratio_threshold); serializer.WritePropertyWithDefault(109, "compression_level", bind_data.compression_level); + serializer.WriteProperty(110, "row_groups_per_file", bind_data.row_groups_per_file); } static unique_ptr ParquetCopyDeserialize(Deserializer &deserializer, CopyFunction &function) { @@ -1175,6 +1326,8 @@ static unique_ptr ParquetCopyDeserialize(Deserializer &deserialize deserializer.ReadPropertyWithDefault(108, "dictionary_compression_ratio_threshold", data->dictionary_compression_ratio_threshold, 1.0); deserializer.ReadPropertyWithDefault(109, "compression_level", data->compression_level); + data->row_groups_per_file = + deserializer.ReadPropertyWithDefault(110, "row_groups_per_file", optional_idx::Invalid()); return std::move(data); } // LCOV_EXCL_STOP @@ -1226,18 +1379,33 @@ idx_t ParquetWriteDesiredBatchSize(ClientContext &context, FunctionData &bind_da } //===--------------------------------------------------------------------===// -// Current File Size +// File rotation //===--------------------------------------------------------------------===// -idx_t ParquetWriteFileSize(GlobalFunctionData &gstate) { +bool ParquetWriteRotateFiles(FunctionData &bind_data_p, const optional_idx &file_size_bytes) { + auto &bind_data = bind_data_p.Cast(); + return file_size_bytes.IsValid() || bind_data.row_groups_per_file.IsValid(); +} + +bool ParquetWriteRotateNextFile(GlobalFunctionData &gstate, FunctionData &bind_data_p, + const optional_idx &file_size_bytes) { auto &global_state = gstate.Cast(); - return global_state.writer->FileSize(); + auto &bind_data = bind_data_p.Cast(); + if (file_size_bytes.IsValid() && global_state.writer->FileSize() > file_size_bytes.GetIndex()) { + return true; + } + if (bind_data.row_groups_per_file.IsValid() && + global_state.writer->NumberOfRowGroups() >= bind_data.row_groups_per_file.GetIndex()) { + return true; + } + return false; } //===--------------------------------------------------------------------===// // Scan Replacement //===--------------------------------------------------------------------===// -unique_ptr ParquetScanReplacement(ClientContext &context, const string &table_name, - ReplacementScanData *data) { +unique_ptr ParquetScanReplacement(ClientContext &context, ReplacementScanInput &input, + optional_ptr data) { + auto &table_name = input.table_name; if (!ReplacementScan::CanReplace(table_name, {"parquet"})) { return nullptr; } @@ -1254,6 +1422,86 @@ unique_ptr ParquetScanReplacement(ClientContext &context, const string return std::move(table_function); } +//===--------------------------------------------------------------------===// +// Select +//===--------------------------------------------------------------------===// +// Helper predicates for ParquetWriteSelect +static bool IsTypeNotSupported(const LogicalType &type) { + if (type.IsNested()) { + return false; + } + return !ParquetWriter::TryGetParquetType(type); +} + +static bool IsTypeLossy(const LogicalType &type) { + return type.id() == LogicalTypeId::HUGEINT || type.id() == LogicalTypeId::UHUGEINT; +} + +static vector> ParquetWriteSelect(CopyToSelectInput &input) { + + auto &context = input.context; + + vector> result; + + bool any_change = false; + + for (auto &expr : input.select_list) { + + const auto &type = expr->return_type; + const auto &name = expr->alias; + + // Spatial types need to be encoded into WKB when writing GeoParquet. + // But dont perform this conversion if this is a EXPORT DATABASE statement + if (input.copy_to_type == CopyToType::COPY_TO_FILE && type.id() == LogicalTypeId::BLOB && type.HasAlias() && + type.GetAlias() == "GEOMETRY") { + + LogicalType wkb_blob_type(LogicalTypeId::BLOB); + wkb_blob_type.SetAlias("WKB_BLOB"); + + auto cast_expr = BoundCastExpression::AddCastToType(context, std::move(expr), wkb_blob_type, false); + cast_expr->alias = name; + result.push_back(std::move(cast_expr)); + any_change = true; + } + // If this is an EXPORT DATABASE statement, we dont want to write "lossy" types, instead cast them to VARCHAR + else if (input.copy_to_type == CopyToType::EXPORT_DATABASE && TypeVisitor::Contains(type, IsTypeLossy)) { + // Replace all lossy types with VARCHAR + auto new_type = TypeVisitor::VisitReplace( + type, [](const LogicalType &ty) -> LogicalType { return IsTypeLossy(ty) ? LogicalType::VARCHAR : ty; }); + + // Cast the column to the new type + auto cast_expr = BoundCastExpression::AddCastToType(context, std::move(expr), new_type, false); + cast_expr->alias = name; + result.push_back(std::move(cast_expr)); + any_change = true; + } + // Else look if there is any unsupported type + else if (TypeVisitor::Contains(type, IsTypeNotSupported)) { + // If there is at least one unsupported type, replace all unsupported types with varchar + // and perform a CAST + auto new_type = TypeVisitor::VisitReplace(type, [](const LogicalType &ty) -> LogicalType { + return IsTypeNotSupported(ty) ? LogicalType::VARCHAR : ty; + }); + + auto cast_expr = BoundCastExpression::AddCastToType(context, std::move(expr), new_type, false); + cast_expr->alias = name; + result.push_back(std::move(cast_expr)); + any_change = true; + } + // Otherwise, just reference the input column + else { + result.push_back(std::move(expr)); + } + } + + // If any change was made, return the new expressions + // otherwise, return an empty vector to indicate no change and avoid pushing another projection on to the plan + if (any_change) { + return result; + } + return {}; +} + void ParquetExtension::Load(DuckDB &db) { auto &db_instance = *db.instance; auto &fs = db.GetFileSystem(); @@ -1282,6 +1530,7 @@ void ParquetExtension::Load(DuckDB &db) { ExtensionUtil::RegisterFunction(db_instance, MultiFileReader::CreateFunctionSet(file_meta_fun)); CopyFunction function("parquet"); + function.copy_to_select = ParquetWriteSelect; function.copy_to_bind = ParquetWriteBind; function.copy_to_initialize_global = ParquetWriteInitializeGlobal; function.copy_to_initialize_local = ParquetWriteInitializeLocal; @@ -1294,10 +1543,10 @@ void ParquetExtension::Load(DuckDB &db) { function.prepare_batch = ParquetWritePrepareBatch; function.flush_batch = ParquetWriteFlushBatch; function.desired_batch_size = ParquetWriteDesiredBatchSize; - function.file_size_bytes = ParquetWriteFileSize; + function.rotate_files = ParquetWriteRotateFiles; + function.rotate_next_file = ParquetWriteRotateNextFile; function.serialize = ParquetCopySerialize; function.deserialize = ParquetCopyDeserialize; - function.supports_type = ParquetWriter::TypeIsSupported; function.extension = "parquet"; ExtensionUtil::RegisterFunction(db_instance, function); @@ -1317,6 +1566,14 @@ std::string ParquetExtension::Name() { return "parquet"; } +std::string ParquetExtension::Version() const { +#ifdef EXT_VERSION_PARQUET + return EXT_VERSION_PARQUET; +#else + return ""; +#endif +} + } // namespace duckdb #ifdef DUCKDB_BUILD_LOADABLE_EXTENSION diff --git a/extension/parquet/parquet_metadata.cpp b/extension/parquet/parquet_metadata.cpp index 811b31aa39a..72b16faeae4 100644 --- a/extension/parquet/parquet_metadata.cpp +++ b/extension/parquet/parquet_metadata.cpp @@ -15,13 +15,8 @@ namespace duckdb { struct ParquetMetaDataBindData : public TableFunctionData { vector return_types; - vector files; - -public: - bool Equals(const FunctionData &other_p) const override { - auto &other = other_p.Cast(); - return other.return_types == return_types && files == other.files; - } + unique_ptr file_list; + unique_ptr multi_file_reader; }; enum class ParquetMetadataOperatorType : uint8_t { META_DATA, SCHEMA, KEY_VALUE_META_DATA, FILE_META_DATA }; @@ -31,10 +26,12 @@ struct ParquetMetaDataOperatorData : public GlobalTableFunctionState { : collection(context, types) { } - idx_t file_index; ColumnDataCollection collection; ColumnDataScanState scan_state; + MultiFileListScanData file_list_scan; + string current_file; + public: static void BindMetaData(vector &return_types, vector &names); static void BindSchema(vector &return_types, vector &names); @@ -588,33 +585,39 @@ unique_ptr ParquetMetaDataBind(ClientContext &context, TableFuncti auto result = make_uniq(); result->return_types = return_types; - result->files = MultiFileReader::GetFileList(context, input.inputs[0], "Parquet"); + result->multi_file_reader = MultiFileReader::Create(input.table_function); + result->file_list = result->multi_file_reader->CreateFileList(context, input.inputs[0]); return std::move(result); } template unique_ptr ParquetMetaDataInit(ClientContext &context, TableFunctionInitInput &input) { auto &bind_data = input.bind_data->Cast(); - D_ASSERT(!bind_data.files.empty()); auto result = make_uniq(context, bind_data.return_types); + + bind_data.file_list->InitializeScan(result->file_list_scan); + bind_data.file_list->Scan(result->file_list_scan, result->current_file); + + D_ASSERT(!bind_data.file_list->IsEmpty()); + switch (TYPE) { case ParquetMetadataOperatorType::SCHEMA: - result->LoadSchemaData(context, bind_data.return_types, bind_data.files[0]); + result->LoadSchemaData(context, bind_data.return_types, bind_data.file_list->GetFirstFile()); break; case ParquetMetadataOperatorType::META_DATA: - result->LoadRowGroupMetadata(context, bind_data.return_types, bind_data.files[0]); + result->LoadRowGroupMetadata(context, bind_data.return_types, bind_data.file_list->GetFirstFile()); break; case ParquetMetadataOperatorType::KEY_VALUE_META_DATA: - result->LoadKeyValueMetaData(context, bind_data.return_types, bind_data.files[0]); + result->LoadKeyValueMetaData(context, bind_data.return_types, bind_data.file_list->GetFirstFile()); break; case ParquetMetadataOperatorType::FILE_META_DATA: - result->LoadFileMetaData(context, bind_data.return_types, bind_data.files[0]); + result->LoadFileMetaData(context, bind_data.return_types, bind_data.file_list->GetFirstFile()); break; default: throw InternalException("Unsupported ParquetMetadataOperatorType"); } - result->file_index = 0; + return std::move(result); } @@ -625,30 +628,29 @@ void ParquetMetaDataImplementation(ClientContext &context, TableFunctionInput &d while (true) { if (!data.collection.Scan(data.scan_state, output)) { - if (data.file_index + 1 < bind_data.files.size()) { - // load the metadata for the next file - data.file_index++; - switch (TYPE) { - case ParquetMetadataOperatorType::SCHEMA: - data.LoadSchemaData(context, bind_data.return_types, bind_data.files[data.file_index]); - break; - case ParquetMetadataOperatorType::META_DATA: - data.LoadRowGroupMetadata(context, bind_data.return_types, bind_data.files[data.file_index]); - break; - case ParquetMetadataOperatorType::KEY_VALUE_META_DATA: - data.LoadKeyValueMetaData(context, bind_data.return_types, bind_data.files[data.file_index]); - break; - case ParquetMetadataOperatorType::FILE_META_DATA: - data.LoadFileMetaData(context, bind_data.return_types, bind_data.files[data.file_index]); - break; - default: - throw InternalException("Unsupported ParquetMetadataOperatorType"); - } - continue; - } else { - // no files remaining: done + + // Try get next file + if (!bind_data.file_list->Scan(data.file_list_scan, data.current_file)) { return; } + + switch (TYPE) { + case ParquetMetadataOperatorType::SCHEMA: + data.LoadSchemaData(context, bind_data.return_types, data.current_file); + break; + case ParquetMetadataOperatorType::META_DATA: + data.LoadRowGroupMetadata(context, bind_data.return_types, data.current_file); + break; + case ParquetMetadataOperatorType::KEY_VALUE_META_DATA: + data.LoadKeyValueMetaData(context, bind_data.return_types, data.current_file); + break; + case ParquetMetadataOperatorType::FILE_META_DATA: + data.LoadFileMetaData(context, bind_data.return_types, data.current_file); + break; + default: + throw InternalException("Unsupported ParquetMetadataOperatorType"); + } + continue; } if (output.size() != 0) { return; diff --git a/extension/parquet/parquet_reader.cpp b/extension/parquet/parquet_reader.cpp index 7ff71fe9edc..e71e26af74f 100644 --- a/extension/parquet/parquet_reader.cpp +++ b/extension/parquet/parquet_reader.cpp @@ -5,6 +5,7 @@ #include "cast_column_reader.hpp" #include "column_reader.hpp" #include "duckdb.hpp" +#include "expression_column_reader.hpp" #include "list_column_reader.hpp" #include "parquet_crypto.hpp" #include "parquet_file_metadata_cache.hpp" @@ -14,18 +15,15 @@ #include "string_column_reader.hpp" #include "struct_column_reader.hpp" #include "templated_column_reader.hpp" +#include "geo_parquet.hpp" #include "thrift_tools.hpp" #ifndef DUCKDB_AMALGAMATION #include "duckdb/common/file_system.hpp" -#include "duckdb/common/hive_partitioning.hpp" -#include "duckdb/common/pair.hpp" #include "duckdb/common/helper.hpp" +#include "duckdb/common/hive_partitioning.hpp" #include "duckdb/common/string_util.hpp" -#include "duckdb/common/types/date.hpp" -#include "duckdb/common/vector_operations/vector_operations.hpp" #include "duckdb/planner/filter/conjunction_filter.hpp" #include "duckdb/planner/filter/constant_filter.hpp" -#include "duckdb/planner/filter/null_filter.hpp" #include "duckdb/planner/filter/struct_filter.hpp" #include "duckdb/planner/table_filter.hpp" #include "duckdb/storage/object_cache.hpp" @@ -55,7 +53,7 @@ CreateThriftFileProtocol(Allocator &allocator, FileHandle &file_handle, bool pre } static shared_ptr -LoadMetadata(Allocator &allocator, FileHandle &file_handle, +LoadMetadata(ClientContext &context, Allocator &allocator, FileHandle &file_handle, const shared_ptr &encryption_config) { auto current_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); @@ -113,7 +111,14 @@ LoadMetadata(Allocator &allocator, FileHandle &file_handle, metadata->read(file_proto.get()); } - return make_shared_ptr(std::move(metadata), current_time); + unique_ptr geo_meta = nullptr; + + // Only read the GeoParquet metadata if the spatial extension is installed + if (GeoParquetFileMetadata::IsSpatialExtensionInstalled(context)) { + geo_meta = GeoParquetFileMetadata::Read(*metadata); + } + + return make_shared_ptr(std::move(metadata), current_time, std::move(geo_meta)); } LogicalType ParquetReader::DeriveLogicalType(const SchemaElement &s_ele, bool binary_as_string) { @@ -129,6 +134,8 @@ LogicalType ParquetReader::DeriveLogicalType(const SchemaElement &s_ele, bool bi } else if (s_ele.logicalType.__isset.TIMESTAMP) { if (s_ele.logicalType.TIMESTAMP.isAdjustedToUTC) { return LogicalType::TIMESTAMP_TZ; + } else if (s_ele.logicalType.TIMESTAMP.unit.__isset.NANOS) { + return LogicalType::TIMESTAMP_NS; } return LogicalType::TIMESTAMP; } else if (s_ele.logicalType.__isset.TIME) { @@ -242,7 +249,7 @@ LogicalType ParquetReader::DeriveLogicalType(const SchemaElement &s_ele, bool bi case ConvertedType::INTERVAL: return LogicalType::INTERVAL; case ConvertedType::JSON: - return LogicalType::VARCHAR; + return LogicalType::JSON(); case ConvertedType::NULL_TYPE: return LogicalTypeId::SQLNULL; case ConvertedType::MAP: @@ -284,8 +291,9 @@ LogicalType ParquetReader::DeriveLogicalType(const SchemaElement &s_ele) { return DeriveLogicalType(s_ele, parquet_options.binary_as_string); } -unique_ptr ParquetReader::CreateReaderRecursive(idx_t depth, idx_t max_define, idx_t max_repeat, - idx_t &next_schema_idx, idx_t &next_file_idx) { +unique_ptr ParquetReader::CreateReaderRecursive(ClientContext &context, idx_t depth, idx_t max_define, + idx_t max_repeat, idx_t &next_schema_idx, + idx_t &next_file_idx) { auto file_meta_data = GetFileMetadata(); D_ASSERT(file_meta_data); D_ASSERT(next_schema_idx < file_meta_data->schema.size()); @@ -302,6 +310,16 @@ unique_ptr ParquetReader::CreateReaderRecursive(idx_t depth, idx_t if (repetition_type == FieldRepetitionType::REPEATED) { max_repeat++; } + + // Check for geoparquet spatial types + if (depth == 1) { + // geoparquet types have to be at the root of the schema, and have to be present in the kv metadata + if (metadata->geo_metadata && metadata->geo_metadata->IsGeometryColumn(s_ele.name)) { + return metadata->geo_metadata->CreateColumnReader(*this, DeriveLogicalType(s_ele), s_ele, next_file_idx++, + max_define, max_repeat, context); + } + } + if (s_ele.__isset.num_children && s_ele.num_children > 0) { // inner node child_list_t child_types; vector> child_readers; @@ -313,7 +331,7 @@ unique_ptr ParquetReader::CreateReaderRecursive(idx_t depth, idx_t auto &child_ele = file_meta_data->schema[next_schema_idx]; auto child_reader = - CreateReaderRecursive(depth + 1, max_define, max_repeat, next_schema_idx, next_file_idx); + CreateReaderRecursive(context, depth + 1, max_define, max_repeat, next_schema_idx, next_file_idx); child_types.push_back(make_pair(child_ele.name, child_reader->Type())); child_readers.push_back(std::move(child_reader)); @@ -387,7 +405,7 @@ unique_ptr ParquetReader::CreateReaderRecursive(idx_t depth, idx_t } // TODO we don't need readers for columns we are not going to read ay -unique_ptr ParquetReader::CreateReader() { +unique_ptr ParquetReader::CreateReader(ClientContext &context) { auto file_meta_data = GetFileMetadata(); idx_t next_schema_idx = 0; idx_t next_file_idx = 0; @@ -398,7 +416,7 @@ unique_ptr ParquetReader::CreateReader() { if (file_meta_data->schema[0].num_children == 0) { throw IOException("Parquet reader: root schema element has no children"); } - auto ret = CreateReaderRecursive(0, 0, 0, next_schema_idx, next_file_idx); + auto ret = CreateReaderRecursive(context, 0, 0, 0, next_schema_idx, next_file_idx); if (ret->Type().id() != LogicalTypeId::STRUCT) { throw InvalidInputException("Root element of Parquet file must be a struct"); } @@ -425,7 +443,7 @@ unique_ptr ParquetReader::CreateReader() { return ret; } -void ParquetReader::InitializeSchema() { +void ParquetReader::InitializeSchema(ClientContext &context) { auto file_meta_data = GetFileMetadata(); if (file_meta_data->__isset.encryption_algorithm) { @@ -438,7 +456,7 @@ void ParquetReader::InitializeSchema() { if (file_meta_data->schema.size() < 2) { throw FormatException("Need at least one non-root column in the file"); } - root_reader = CreateReader(); + root_reader = CreateReader(context); auto &root_type = root_reader->Type(); auto &child_types = StructType::GetChildTypes(root_type); D_ASSERT(root_type.id() == LogicalTypeId::STRUCT); @@ -449,7 +467,7 @@ void ParquetReader::InitializeSchema() { // Add generated constant column for row number if (parquet_options.file_row_number) { - if (std::find(names.begin(), names.end(), "file_row_number") != names.end()) { + if (StringUtil::CIFind(names, "file_row_number") != DConstants::INVALID_INDEX) { throw BinderException( "Using file_row_number option on file with column named file_row_number is not supported"); } @@ -498,23 +516,23 @@ ParquetReader::ParquetReader(ClientContext &context_p, string file_name_p, Parqu // or if this file has cached metadata // or if the cached version already expired if (!ObjectCache::ObjectCacheEnabled(context_p)) { - metadata = LoadMetadata(allocator, *file_handle, parquet_options.encryption_config); + metadata = LoadMetadata(context_p, allocator, *file_handle, parquet_options.encryption_config); } else { auto last_modify_time = fs.GetLastModifiedTime(*file_handle); metadata = ObjectCache::GetObjectCache(context_p).Get(file_name); if (!metadata || (last_modify_time + 10 >= metadata->read_time)) { - metadata = LoadMetadata(allocator, *file_handle, parquet_options.encryption_config); + metadata = LoadMetadata(context_p, allocator, *file_handle, parquet_options.encryption_config); ObjectCache::GetObjectCache(context_p).Put(file_name, metadata); } } - InitializeSchema(); + InitializeSchema(context_p); } ParquetReader::ParquetReader(ClientContext &context_p, ParquetOptions parquet_options_p, shared_ptr metadata_p) : fs(FileSystem::GetFileSystem(context_p)), allocator(BufferAllocator::Get(context_p)), metadata(std::move(metadata_p)), parquet_options(std::move(parquet_options_p)) { - InitializeSchema(); + InitializeSchema(context_p); } ParquetReader::~ParquetReader() { @@ -680,7 +698,8 @@ idx_t ParquetReader::NumRowGroups() { return GetFileMetadata()->row_groups.size(); } -void ParquetReader::InitializeScan(ParquetReaderScanState &state, vector groups_to_read) { +void ParquetReader::InitializeScan(ClientContext &context, ParquetReaderScanState &state, + vector groups_to_read) { state.current_group = -1; state.finished = false; state.group_offset = 0; @@ -700,7 +719,7 @@ void ParquetReader::InitializeScan(ParquetReaderScanState &state, vector } state.thrift_file_proto = CreateThriftFileProtocol(allocator, *state.file_handle, state.prefetch_mode); - state.root_reader = CreateReader(); + state.root_reader = CreateReader(context); state.define_buf.resize(allocator, STANDARD_VECTOR_SIZE); state.repeat_buf.resize(allocator, STANDARD_VECTOR_SIZE); } @@ -720,7 +739,9 @@ void FilterIsNull(Vector &v, parquet_filter_t &filter_mask, idx_t count) { filter_mask.reset(); } else { for (idx_t i = 0; i < count; i++) { - filter_mask[i] = filter_mask[i] && !mask.RowIsValid(i); + if (filter_mask.test(i)) { + filter_mask.set(i, !mask.RowIsValid(i)); + } } } } @@ -738,7 +759,9 @@ void FilterIsNotNull(Vector &v, parquet_filter_t &filter_mask, idx_t count) { auto &mask = FlatVector::Validity(v); if (!mask.AllValid()) { for (idx_t i = 0; i < count; i++) { - filter_mask[i] = filter_mask[i] && mask.RowIsValid(i); + if (filter_mask.test(i)) { + filter_mask.set(i, mask.RowIsValid(i)); + } } } } @@ -763,13 +786,15 @@ void TemplatedFilterOperation(Vector &v, T constant, parquet_filter_t &filter_ma if (!mask.AllValid()) { for (idx_t i = 0; i < count; i++) { - if (mask.RowIsValid(i)) { - filter_mask[i] = filter_mask[i] && OP::Operation(v_ptr[i], constant); + if (filter_mask.test(i) && mask.RowIsValid(i)) { + filter_mask.set(i, OP::Operation(v_ptr[i], constant)); } } } else { for (idx_t i = 0; i < count; i++) { - filter_mask[i] = filter_mask[i] && OP::Operation(v_ptr[i], constant); + if (filter_mask.test(i)) { + filter_mask.set(i, OP::Operation(v_ptr[i], constant)); + } } } } @@ -1049,7 +1074,7 @@ bool ParquetReader::ScanInternal(ParquetReaderScanState &state, DataChunk &resul idx_t sel_size = 0; for (idx_t i = 0; i < this_output_chunk_rows; i++) { - if (filter_mask[i]) { + if (filter_mask.test(i)) { state.sel.set_index(sel_size++, i); } } diff --git a/extension/parquet/parquet_statistics.cpp b/extension/parquet/parquet_statistics.cpp index 351b5938ad2..bd0a7edb530 100644 --- a/extension/parquet/parquet_statistics.cpp +++ b/extension/parquet/parquet_statistics.cpp @@ -48,9 +48,6 @@ static unique_ptr CreateNumericStats(const LogicalType &type, Value ParquetStatisticsUtils::ConvertValue(const LogicalType &type, const duckdb_parquet::format::SchemaElement &schema_ele, const std::string &stats) { - if (stats.empty()) { - return Value(); - } auto stats_data = const_data_ptr_cast(stats.c_str()); switch (type.id()) { case LogicalTypeId::BOOLEAN: { @@ -198,8 +195,12 @@ Value ParquetStatisticsUtils::ConvertValue(const LogicalType &type, } if (schema_ele.__isset.logicalType && schema_ele.logicalType.__isset.TIME) { // logical type - if (schema_ele.logicalType.TIME.unit.__isset.MICROS) { + if (schema_ele.logicalType.TIME.unit.__isset.MILLIS) { + return Value::TIMETZ(ParquetIntToTimeMsTZ(val)); + } else if (schema_ele.logicalType.TIME.unit.__isset.MICROS) { return Value::TIMETZ(ParquetIntToTimeTZ(val)); + } else if (schema_ele.logicalType.TIME.unit.__isset.NANOS) { + return Value::TIMETZ(ParquetIntToTimeNsTZ(val)); } else { throw InternalException("Time With Time Zone logicalType is set but unit is not defined"); } @@ -243,6 +244,38 @@ Value ParquetStatisticsUtils::ConvertValue(const LogicalType &type, return Value::TIMESTAMP(timestamp_value); } } + case LogicalTypeId::TIMESTAMP_NS: { + timestamp_ns_t timestamp_value; + if (schema_ele.type == Type::INT96) { + if (stats.size() != sizeof(Int96)) { + throw InternalException("Incorrect stats size for type TIMESTAMP_NS"); + } + timestamp_value = ImpalaTimestampToTimestampNS(Load(stats_data)); + } else { + D_ASSERT(schema_ele.type == Type::INT64); + if (stats.size() != sizeof(int64_t)) { + throw InternalException("Incorrect stats size for type TIMESTAMP_NS"); + } + auto val = Load(stats_data); + if (schema_ele.__isset.logicalType && schema_ele.logicalType.__isset.TIMESTAMP) { + // logical type + if (schema_ele.logicalType.TIMESTAMP.unit.__isset.MILLIS) { + timestamp_value = ParquetTimestampMsToTimestampNs(val); + } else if (schema_ele.logicalType.TIMESTAMP.unit.__isset.NANOS) { + timestamp_value = ParquetTimestampNsToTimestampNs(val); + } else if (schema_ele.logicalType.TIMESTAMP.unit.__isset.MICROS) { + timestamp_value = ParquetTimestampUsToTimestampNs(val); + } else { + throw InternalException("Timestamp (NS) logicalType is set but unit is unknown"); + } + } else if (schema_ele.converted_type == duckdb_parquet::format::ConvertedType::TIMESTAMP_MILLIS) { + timestamp_value = ParquetTimestampMsToTimestampNs(val); + } else { + timestamp_value = ParquetTimestampUsToTimestampNs(val); + } + } + return Value::TIMESTAMPNS(timestamp_value); + } default: throw InternalException("Unsupported type for stats %s", type.ToString()); } diff --git a/extension/parquet/parquet_timestamp.cpp b/extension/parquet/parquet_timestamp.cpp index 3451e26686a..a0ada7d14e7 100644 --- a/extension/parquet/parquet_timestamp.cpp +++ b/extension/parquet/parquet_timestamp.cpp @@ -14,14 +14,31 @@ static constexpr int64_t JULIAN_TO_UNIX_EPOCH_DAYS = 2440588LL; static constexpr int64_t MILLISECONDS_PER_DAY = 86400000LL; static constexpr int64_t MICROSECONDS_PER_DAY = MILLISECONDS_PER_DAY * 1000LL; static constexpr int64_t NANOSECONDS_PER_MICRO = 1000LL; +static constexpr int64_t NANOSECONDS_PER_DAY = MICROSECONDS_PER_DAY * 1000LL; + +static inline int64_t ImpalaTimestampToDays(const Int96 &impala_timestamp) { + return impala_timestamp.value[2] - JULIAN_TO_UNIX_EPOCH_DAYS; +} static int64_t ImpalaTimestampToMicroseconds(const Int96 &impala_timestamp) { - int64_t days_since_epoch = impala_timestamp.value[2] - JULIAN_TO_UNIX_EPOCH_DAYS; + int64_t days_since_epoch = ImpalaTimestampToDays(impala_timestamp); auto nanoseconds = Load(const_data_ptr_cast(impala_timestamp.value)); auto microseconds = nanoseconds / NANOSECONDS_PER_MICRO; return days_since_epoch * MICROSECONDS_PER_DAY + microseconds; } +static int64_t ImpalaTimestampToNanoseconds(const Int96 &impala_timestamp) { + int64_t days_since_epoch = ImpalaTimestampToDays(impala_timestamp); + auto nanoseconds = Load(const_data_ptr_cast(impala_timestamp.value)); + return days_since_epoch * NANOSECONDS_PER_DAY + nanoseconds; +} + +timestamp_ns_t ImpalaTimestampToTimestampNS(const Int96 &raw_ts) { + timestamp_ns_t result; + result.value = ImpalaTimestampToNanoseconds(raw_ts); + return result; +} + timestamp_t ImpalaTimestampToTimestamp(const Int96 &raw_ts) { auto impala_us = ImpalaTimestampToMicroseconds(raw_ts); return Timestamp::FromEpochMicroSeconds(impala_us); @@ -52,6 +69,30 @@ timestamp_t ParquetTimestampMsToTimestamp(const int64_t &raw_ts) { return Timestamp::FromEpochMs(raw_ts); } +timestamp_ns_t ParquetTimestampMsToTimestampNs(const int64_t &raw_ms) { + timestamp_ns_t input; + input.value = raw_ms; + if (!Timestamp::IsFinite(input)) { + return input; + } + return Timestamp::TimestampNsFromEpochMillis(raw_ms); +} + +timestamp_ns_t ParquetTimestampUsToTimestampNs(const int64_t &raw_us) { + timestamp_ns_t input; + input.value = raw_us; + if (!Timestamp::IsFinite(input)) { + return input; + } + return Timestamp::TimestampNsFromEpochMicros(raw_us); +} + +timestamp_ns_t ParquetTimestampNsToTimestampNs(const int64_t &raw_ns) { + timestamp_ns_t result; + result.value = raw_ns; + return result; +} + timestamp_t ParquetTimestampNsToTimestamp(const int64_t &raw_ts) { timestamp_t input(raw_ts); if (!Timestamp::IsFinite(input)) { diff --git a/extension/parquet/parquet_writer.cpp b/extension/parquet/parquet_writer.cpp index fcc17f4de84..97c9f47323a 100644 --- a/extension/parquet/parquet_writer.cpp +++ b/extension/parquet/parquet_writer.cpp @@ -8,6 +8,8 @@ #ifndef DUCKDB_AMALGAMATION #include "duckdb/common/file_system.hpp" #include "duckdb/common/serializer/buffered_file_writer.hpp" +#include "duckdb/common/serializer/deserializer.hpp" +#include "duckdb/common/serializer/serializer.hpp" #include "duckdb/common/serializer/write_stream.hpp" #include "duckdb/common/string_util.hpp" #include "duckdb/function/table_function.hpp" @@ -80,8 +82,8 @@ class MyTransport : public TTransport { WriteStream &serializer; }; -CopyTypeSupport ParquetWriter::DuckDBTypeToParquetTypeInternal(const LogicalType &duckdb_type, - Type::type &parquet_type) { +bool ParquetWriter::TryGetParquetType(const LogicalType &duckdb_type, optional_ptr parquet_type_ptr) { + Type::type parquet_type; switch (duckdb_type.id()) { case LogicalTypeId::BOOLEAN: parquet_type = Type::BOOLEAN; @@ -104,7 +106,7 @@ CopyTypeSupport ParquetWriter::DuckDBTypeToParquetTypeInternal(const LogicalType case LogicalTypeId::UHUGEINT: case LogicalTypeId::HUGEINT: parquet_type = Type::DOUBLE; - return CopyTypeSupport::LOSSY; + break; case LogicalTypeId::ENUM: case LogicalTypeId::BLOB: case LogicalTypeId::VARCHAR: @@ -149,71 +151,29 @@ CopyTypeSupport ParquetWriter::DuckDBTypeToParquetTypeInternal(const LogicalType break; default: // Anything that is not supported - return CopyTypeSupport::UNSUPPORTED; + return false; + } + if (parquet_type_ptr) { + *parquet_type_ptr = parquet_type; } - return CopyTypeSupport::SUPPORTED; + return true; } Type::type ParquetWriter::DuckDBTypeToParquetType(const LogicalType &duckdb_type) { Type::type result; - auto type_supports = DuckDBTypeToParquetTypeInternal(duckdb_type, result); - if (type_supports == CopyTypeSupport::UNSUPPORTED) { - throw NotImplementedException("Unimplemented type for Parquet \"%s\"", duckdb_type.ToString()); - } - return result; -} - -CopyTypeSupport ParquetWriter::TypeIsSupported(const LogicalType &type) { - Type::type unused; - auto id = type.id(); - if (id == LogicalTypeId::LIST) { - auto &child_type = ListType::GetChildType(type); - return TypeIsSupported(child_type); - } - if (id == LogicalTypeId::ARRAY) { - auto &child_type = ArrayType::GetChildType(type); - return TypeIsSupported(child_type); - } - if (id == LogicalTypeId::UNION) { - auto count = UnionType::GetMemberCount(type); - for (idx_t i = 0; i < count; i++) { - auto &member_type = UnionType::GetMemberType(type, i); - auto type_support = TypeIsSupported(member_type); - if (type_support != CopyTypeSupport::SUPPORTED) { - return type_support; - } - } - return CopyTypeSupport::SUPPORTED; - } - if (id == LogicalTypeId::STRUCT) { - auto &children = StructType::GetChildTypes(type); - for (auto &child : children) { - auto &child_type = child.second; - auto type_support = TypeIsSupported(child_type); - if (type_support != CopyTypeSupport::SUPPORTED) { - return type_support; - } - } - return CopyTypeSupport::SUPPORTED; - } - if (id == LogicalTypeId::MAP) { - auto &key_type = MapType::KeyType(type); - auto &value_type = MapType::ValueType(type); - auto key_type_support = TypeIsSupported(key_type); - if (key_type_support != CopyTypeSupport::SUPPORTED) { - return key_type_support; - } - auto value_type_support = TypeIsSupported(value_type); - if (value_type_support != CopyTypeSupport::SUPPORTED) { - return value_type_support; - } - return CopyTypeSupport::SUPPORTED; + if (TryGetParquetType(duckdb_type, &result)) { + return result; } - return DuckDBTypeToParquetTypeInternal(type, unused); + throw NotImplementedException("Unimplemented type for Parquet \"%s\"", duckdb_type.ToString()); } void ParquetWriter::SetSchemaProperties(const LogicalType &duckdb_type, duckdb_parquet::format::SchemaElement &schema_ele) { + if (duckdb_type.IsJSONType()) { + schema_ele.converted_type = ConvertedType::JSON; + schema_ele.__isset.converted_type = true; + return; + } switch (duckdb_type.id()) { case LogicalTypeId::TINYINT: schema_ele.converted_type = ConvertedType::INT_8; @@ -262,7 +222,6 @@ void ParquetWriter::SetSchemaProperties(const LogicalType &duckdb_type, break; case LogicalTypeId::TIMESTAMP_TZ: case LogicalTypeId::TIMESTAMP: - case LogicalTypeId::TIMESTAMP_NS: case LogicalTypeId::TIMESTAMP_SEC: schema_ele.converted_type = ConvertedType::TIMESTAMP_MICROS; schema_ele.__isset.converted_type = true; @@ -271,6 +230,13 @@ void ParquetWriter::SetSchemaProperties(const LogicalType &duckdb_type, schema_ele.logicalType.TIMESTAMP.isAdjustedToUTC = (duckdb_type.id() == LogicalTypeId::TIMESTAMP_TZ); schema_ele.logicalType.TIMESTAMP.unit.__isset.MICROS = true; break; + case LogicalTypeId::TIMESTAMP_NS: + schema_ele.__isset.converted_type = false; + schema_ele.__isset.logicalType = true; + schema_ele.logicalType.__isset.TIMESTAMP = true; + schema_ele.logicalType.TIMESTAMP.isAdjustedToUTC = false; + schema_ele.logicalType.TIMESTAMP.unit.__isset.NANOS = true; + break; case LogicalTypeId::TIMESTAMP_MS: schema_ele.converted_type = ConvertedType::TIMESTAMP_MILLIS; schema_ele.__isset.converted_type = true; @@ -347,8 +313,8 @@ void VerifyUniqueNames(const vector &names) { #endif } -ParquetWriter::ParquetWriter(FileSystem &fs, string file_name_p, vector types_p, vector names_p, - CompressionCodec::type codec, ChildFieldIDs field_ids_p, +ParquetWriter::ParquetWriter(ClientContext &context, FileSystem &fs, string file_name_p, vector types_p, + vector names_p, CompressionCodec::type codec, ChildFieldIDs field_ids_p, const vector> &kv_metadata, shared_ptr encryption_config_p, double dictionary_compression_ratio_threshold_p, optional_idx compression_level_p) @@ -411,8 +377,8 @@ ParquetWriter::ParquetWriter(FileSystem &fs, string file_name_p, vector schema_path; for (idx_t i = 0; i < sql_types.size(); i++) { - column_writers.push_back(ColumnWriter::CreateWriterRecursive(file_meta_data.schema, *this, sql_types[i], - unique_names[i], schema_path, &field_ids)); + column_writers.push_back(ColumnWriter::CreateWriterRecursive( + context, file_meta_data.schema, *this, sql_types[i], unique_names[i], schema_path, &field_ids)); } } @@ -458,6 +424,11 @@ void ParquetWriter::PrepareRowGroup(ColumnDataCollection &buffer, PreparedRowGro } } + // Reserving these once at the start really pays off + for (auto &write_state : write_states) { + write_state->definition_levels.reserve(buffer.Count()); + } + for (auto &chunk : buffer.Chunks({column_ids})) { for (idx_t i = 0; i < next; i++) { col_writers[i].get().Prepare(*write_states[i], nullptr, chunk.data[i], chunk.size()); @@ -481,6 +452,42 @@ void ParquetWriter::PrepareRowGroup(ColumnDataCollection &buffer, PreparedRowGro result.heaps = buffer.GetHeapReferences(); } +// Validation code adapted from Impala +static void ValidateOffsetInFile(const string &filename, idx_t col_idx, idx_t file_length, idx_t offset, + const string &offset_name) { + if (offset < 0 || offset >= file_length) { + throw IOException("File '%s': metadata is corrupt. Column %d has invalid " + "%s (offset=%llu file_size=%llu).", + filename, col_idx, offset_name, offset, file_length); + } +} + +static void ValidateColumnOffsets(const string &filename, idx_t file_length, const ParquetRowGroup &row_group) { + for (idx_t i = 0; i < row_group.columns.size(); ++i) { + const auto &col_chunk = row_group.columns[i]; + ValidateOffsetInFile(filename, i, file_length, col_chunk.meta_data.data_page_offset, "data page offset"); + auto col_start = NumericCast(col_chunk.meta_data.data_page_offset); + // The file format requires that if a dictionary page exists, it be before data pages. + if (col_chunk.meta_data.__isset.dictionary_page_offset) { + ValidateOffsetInFile(filename, i, file_length, col_chunk.meta_data.dictionary_page_offset, + "dictionary page offset"); + if (NumericCast(col_chunk.meta_data.dictionary_page_offset) >= col_start) { + throw IOException("Parquet file '%s': metadata is corrupt. Dictionary " + "page (offset=%llu) must come before any data pages (offset=%llu).", + filename, col_chunk.meta_data.dictionary_page_offset, col_start); + } + col_start = col_chunk.meta_data.dictionary_page_offset; + } + auto col_len = NumericCast(col_chunk.meta_data.total_compressed_size); + auto col_end = col_start + col_len; + if (col_end <= 0 || col_end > file_length) { + throw IOException("Parquet file '%s': metadata is corrupt. Column %llu has " + "invalid column offsets (offset=%llu, size=%llu, file_size=%llu).", + filename, i, col_start, col_len, file_length); + } + } +} + void ParquetWriter::FlushRowGroup(PreparedRowGroup &prepared) { lock_guard glock(lock); auto &row_group = prepared.row_group; @@ -494,6 +501,8 @@ void ParquetWriter::FlushRowGroup(PreparedRowGroup &prepared) { auto write_state = std::move(states[col_idx]); col_writer->FinalizeWrite(*write_state); } + // let's make sure all offsets are ay-okay + ValidateColumnOffsets(file_name, writer->GetTotalWritten(), row_group); // append the row group to the file meta data file_meta_data.row_groups.push_back(row_group); @@ -515,7 +524,7 @@ void ParquetWriter::Flush(ColumnDataCollection &buffer) { } void ParquetWriter::Finalize() { - auto start_offset = writer->GetTotalWritten(); + const auto start_offset = writer->GetTotalWritten(); if (encryption_config) { // Crypto metadata is written unencrypted FileCryptoMetaData crypto_metadata; @@ -525,6 +534,12 @@ void ParquetWriter::Finalize() { crypto_metadata.__set_encryption_algorithm(alg); crypto_metadata.write(protocol.get()); } + + // Add geoparquet metadata to the file metadata + if (geoparquet_data) { + geoparquet_data->Write(file_meta_data); + } + Write(file_meta_data); writer->Write(writer->GetTotalWritten() - start_offset); @@ -538,8 +553,15 @@ void ParquetWriter::Finalize() { } // flush to disk - writer->Sync(); + writer->Close(); writer.reset(); } +GeoParquetFileMetadata &ParquetWriter::GetGeoParquetData() { + if (!geoparquet_data) { + geoparquet_data = make_uniq(); + } + return *geoparquet_data; +} + } // namespace duckdb diff --git a/extension/parquet/serialize_parquet.cpp b/extension/parquet/serialize_parquet.cpp index b28ff0211f3..cc5d1445284 100644 --- a/extension/parquet/serialize_parquet.cpp +++ b/extension/parquet/serialize_parquet.cpp @@ -14,12 +14,12 @@ namespace duckdb { void ChildFieldIDs::Serialize(Serializer &serializer) const { - serializer.WritePropertyWithDefault>>(100, "ids", ids); + serializer.WritePropertyWithDefault>(100, "ids", ids.operator*()); } ChildFieldIDs ChildFieldIDs::Deserialize(Deserializer &deserializer) { ChildFieldIDs result; - deserializer.ReadPropertyWithDefault>>(100, "ids", result.ids); + deserializer.ReadPropertyWithDefault>(100, "ids", result.ids.operator*()); return result; } diff --git a/extension/sqlsmith/CMakeLists.txt b/extension/sqlsmith/CMakeLists.txt deleted file mode 100644 index 6117be8f3e7..00000000000 --- a/extension/sqlsmith/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12) - -project(SQLSmithExtension) - -include_directories(include) -include_directories(third_party/sqlsmith/include) -add_subdirectory(third_party) - -set(SQLSMITH_SOURCES - sqlsmith_extension.cpp statement_generator.cpp statement_simplifier.cpp - fuzzyduck.cpp ${SQLSMITH_OBJECT_FILES}) - -build_static_extension(sqlsmith ${SQLSMITH_SOURCES}) -set(PARAMETERS "-warnings") -build_loadable_extension(sqlsmith ${PARAMETERS} ${SQLSMITH_SOURCES}) - -install( - TARGETS sqlsmith_extension - EXPORT "${DUCKDB_EXPORT_SET}" - LIBRARY DESTINATION "${INSTALL_LIB_DIR}" - ARCHIVE DESTINATION "${INSTALL_LIB_DIR}") diff --git a/extension/sqlsmith/fuzzyduck.cpp b/extension/sqlsmith/fuzzyduck.cpp deleted file mode 100644 index 7d4f0b932e6..00000000000 --- a/extension/sqlsmith/fuzzyduck.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "fuzzyduck.hpp" -#include "duckdb/common/random_engine.hpp" -#include "statement_generator.hpp" -#include -#include -#include - -namespace duckdb { - -FuzzyDuck::FuzzyDuck(ClientContext &context) : context(context) { -} - -FuzzyDuck::~FuzzyDuck() { -} - -void FuzzyDuck::BeginFuzzing() { - auto &random_engine = RandomEngine::Get(context); - if (seed == 0) { - seed = random_engine.NextRandomInteger(); - } - if (max_queries == 0) { - throw BinderException("Provide a max_queries argument greater than 0"); - } - if (!complete_log.empty()) { - auto &fs = FileSystem::GetFileSystem(context); - TryRemoveFile(complete_log); - complete_log_handle = - fs.OpenFile(complete_log, FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE_NEW); - } -} - -void FuzzyDuck::EndFuzzing() { - if (complete_log_handle) { - complete_log_handle->Close(); - } -} - -void FuzzyDuck::Fuzz() { - BeginFuzzing(); - for (idx_t i = 0; i < max_queries; i++) { - LogMessage("Query " + to_string(i) + "\n"); - auto query = GenerateQuery(); - RunQuery(std::move(query)); - } - EndFuzzing(); -} - -void FuzzyDuck::FuzzAllFunctions() { - StatementGenerator generator(context); - auto queries = generator.GenerateAllFunctionCalls(); - - if (max_queries == 0) { - max_queries = queries.size(); - } - - std::default_random_engine e(seed); - std::shuffle(std::begin(queries), std::end(queries), e); - BeginFuzzing(); - for (auto &query : queries) { - RunQuery(std::move(query)); - } - EndFuzzing(); -} - -string FuzzyDuck::GenerateQuery() { - LogTask("Generating query with seed " + to_string(seed)); - auto &engine = RandomEngine::Get(context); - // set the seed - engine.SetSeed(seed); - // get the next seed - seed = engine.NextRandomInteger(); - - // generate the statement - StatementGenerator generator(context); - auto statement = generator.GenerateStatement(); - return statement->ToString(); -} - -void sleep_thread(Connection *con, atomic *is_active, atomic *timed_out, idx_t timeout_duration) { - // timeout is given in seconds - // we wait 10ms per iteration, so timeout * 100 gives us the amount of - // iterations - for (size_t i = 0; i < (size_t)(timeout_duration * 100) && *is_active; i++) { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - if (*is_active) { - *timed_out = true; - con->Interrupt(); - } -} - -void FuzzyDuck::RunQuery(string query) { - LogQuery(query + ";"); - - Connection con(*context.db); - atomic is_active(true); - atomic timed_out(false); - std::thread interrupt_thread(sleep_thread, &con, &is_active, &timed_out, timeout); - - auto result = con.Query(query); - is_active = false; - interrupt_thread.join(); - if (timed_out) { - LogMessage("TIMEOUT"); - } else if (result->HasError()) { - LogMessage("EXECUTION ERROR: " + result->GetError()); - } else { - LogMessage("EXECUTION SUCCESS!"); - } -} - -void FuzzyDuck::TryRemoveFile(const string &path) { - auto &fs = FileSystem::GetFileSystem(context); - if (fs.FileExists(path)) { - fs.RemoveFile(path); - } -} - -void FuzzyDuck::LogMessage(const string &message) { - if (!verbose_output) { - return; - } - Printer::Print(message); -} - -void FuzzyDuck::LogTask(const string &message) { - if (verbose_output) { - LogMessage(message + "\n"); - } - LogToCurrent(message); -} - -void FuzzyDuck::LogQuery(const string &message) { - if (verbose_output) { - LogMessage(message + "\n"); - } - LogToCurrent(message); - LogToComplete(message); -} - -void FuzzyDuck::LogToCurrent(const string &message) { - if (log.empty()) { - return; - } - auto &fs = FileSystem::GetFileSystem(context); - TryRemoveFile(log); - auto file = fs.OpenFile(log, FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE_NEW); - file->Write((void *)message.c_str(), message.size()); - file->Sync(); - file->Close(); -} -void FuzzyDuck::LogToComplete(const string &message) { - if (!complete_log_handle) { - return; - } - complete_log_handle->Write((void *)message.c_str(), message.size()); - complete_log_handle->Write((void *)"\n", 1); - complete_log_handle->Sync(); -} - -} // namespace duckdb diff --git a/extension/sqlsmith/include/fuzzyduck.hpp b/extension/sqlsmith/include/fuzzyduck.hpp deleted file mode 100644 index 4393e87bc35..00000000000 --- a/extension/sqlsmith/include/fuzzyduck.hpp +++ /dev/null @@ -1,54 +0,0 @@ -//===----------------------------------------------------------------------===// -// DuckDB -// -// fuzzyduck.hpp -// -// -//===----------------------------------------------------------------------===// - -#pragma once - -#include "duckdb.hpp" -#include "duckdb/parser/query_node.hpp" - -namespace duckdb { -struct FileHandle; - -class FuzzyDuck { -public: - FuzzyDuck(ClientContext &context); - ~FuzzyDuck(); - - ClientContext &context; - uint32_t seed = 0; - idx_t max_queries = 0; - string complete_log; - string log; - bool verbose_output = false; - idx_t timeout = 30; - -public: - void Fuzz(); - void FuzzAllFunctions(); - -private: - void BeginFuzzing(); - void EndFuzzing(); - - string GenerateQuery(); - void RunQuery(string query); - - void LogMessage(const string &message); - void LogTask(const string &message); - void LogQuery(const string &message); - - void LogToCurrent(const string &message); - void LogToComplete(const string &message); - - void TryRemoveFile(const string &path); - -private: - unique_ptr complete_log_handle; -}; - -} // namespace duckdb diff --git a/extension/sqlsmith/include/statement_generator.hpp b/extension/sqlsmith/include/statement_generator.hpp deleted file mode 100644 index bc96b609727..00000000000 --- a/extension/sqlsmith/include/statement_generator.hpp +++ /dev/null @@ -1,148 +0,0 @@ -//===----------------------------------------------------------------------===// -// DuckDB -// -// statement_generator.hpp -// -// -//===----------------------------------------------------------------------===// - -#pragma once - -#include "duckdb.hpp" -#include "duckdb/parser/query_node.hpp" - -namespace duckdb { -class SQLStatement; -class SelectStatement; -class InsertStatement; -class UpdateStatement; -class DeleteStatement; -class TableRef; -class SelectNode; -class SetOperationNode; -class QueryNode; -class ParsedExpression; -class ResultModifier; -class OrderModifier; -class UpdateSetInfo; - -struct GeneratorContext; - -class StatementGenerator { -public: - constexpr static idx_t MAX_DEPTH = 10; - constexpr static idx_t MAX_EXPRESSION_DEPTH = 50; - - friend class ExpressionDepthChecker; - friend class AggregateChecker; - friend class WindowChecker; - -public: - StatementGenerator(ClientContext &context); - StatementGenerator(StatementGenerator &parent); - ~StatementGenerator(); - -public: - unique_ptr GenerateStatement(); - - vector GenerateAllFunctionCalls(); - -private: - unique_ptr GenerateStatement(StatementType type); - - unique_ptr GenerateSelect(); - unique_ptr GenerateCreate(); - unique_ptr GenerateQueryNode(); - - unique_ptr GenerateCreateInfo(); - - void GenerateCTEs(QueryNode &node); - unique_ptr GenerateTableRef(); - unique_ptr GenerateExpression(); - - unique_ptr GenerateBaseTableRef(); - unique_ptr GenerateExpressionListRef(); - unique_ptr GenerateJoinRef(); - unique_ptr GenerateSubqueryRef(); - unique_ptr GenerateTableFunctionRef(); - unique_ptr GeneratePivotRef(); - - unique_ptr GenerateConstant(); - unique_ptr GenerateColumnRef(); - unique_ptr GenerateFunction(); - unique_ptr GenerateOperator(); - unique_ptr GenerateWindowFunction(optional_ptr function = nullptr); - unique_ptr GenerateConjunction(); - unique_ptr GenerateStar(); - unique_ptr GenerateLambda(); - unique_ptr GenerateSubquery(); - unique_ptr GenerateCast(); - unique_ptr GenerateBetween(); - unique_ptr GenerateComparison(); - unique_ptr GeneratePositionalReference(); - unique_ptr GenerateCase(); - - unique_ptr GenerateOrderBy(); - - LogicalType GenerateLogicalType(); - - void GenerateAllScalar(ScalarFunctionCatalogEntry &scalar_function, vector &result); - void GenerateAllAggregate(AggregateFunctionCatalogEntry &aggregate_function, vector &result); - string GenerateTestAllTypes(BaseScalarFunction &base_function); - string GenerateTestVectorTypes(BaseScalarFunction &base_function); - string GenerateCast(const LogicalType &target, const string &source_name, bool add_varchar); - bool FunctionArgumentsAlwaysNull(const string &name); - - idx_t RandomValue(idx_t max); - bool RandomBoolean(); - //! Returns true with a percentage change (0-100) - bool RandomPercentage(idx_t percentage); - string RandomString(idx_t length); - unique_ptr RandomExpression(idx_t percentage); - - //! Generate identifier for a column or parent using "t" or "c" prefixes. ie. t0, or c0 - string GenerateIdentifier(); - string GenerateTableIdentifier(); - string GenerateSchemaIdentifier(); - string GenerateViewIdentifier(); - - //! using the parent generate a relation name. ie. t0 - string GenerateRelationName(); - //! using the parent, generate a valid column name. ie. c0 - string GenerateColumnName(); - idx_t GetIndex(); - - Value GenerateConstantValue(); - - ExpressionType GenerateComparisonType(); - - //! used to create columns when creating new tables; - -private: - ClientContext &context; - optional_ptr parent; - unique_ptr current_statement; - vector current_relation_names; - vector current_column_names; - - std::shared_ptr generator_context; - idx_t index = 0; - idx_t depth = 0; - idx_t expression_depth = 0; - - bool in_window = false; - bool in_aggregate = false; - - std::shared_ptr GetDatabaseState(ClientContext &context); - vector> GenerateChildren(idx_t min, idx_t max); - - template - const T &Choose(const vector &entries) { - if (entries.empty()) { - throw InternalException("Attempting to choose from an empty vector"); - } - return entries[RandomValue(entries.size())]; - } -}; - -} // namespace duckdb diff --git a/extension/sqlsmith/include/statement_simplifier.hpp b/extension/sqlsmith/include/statement_simplifier.hpp deleted file mode 100644 index 0f238437fe8..00000000000 --- a/extension/sqlsmith/include/statement_simplifier.hpp +++ /dev/null @@ -1,89 +0,0 @@ -//===----------------------------------------------------------------------===// -// DuckDB -// -// statement_simplifier.hpp -// -// -//===----------------------------------------------------------------------===// - -#pragma once - -#include "duckdb.hpp" -#include "duckdb/parser/query_node.hpp" - -namespace duckdb { -class SQLStatement; -class SelectStatement; -class InsertStatement; -class UpdateStatement; -class DeleteStatement; -class TableRef; -class SelectNode; -class SetOperationNode; -class QueryNode; -class ParsedExpression; -class ResultModifier; -class OrderModifier; -class UpdateSetInfo; -class GroupByNode; - -class StatementSimplifier { -public: - StatementSimplifier(SQLStatement &statement_p, vector &result_p); - - SQLStatement &statement; - vector &result; - -public: - void Simplify(SQLStatement &stmt); - -private: - void Simplify(SelectStatement &stmt); - void Simplify(InsertStatement &stmt); - void Simplify(UpdateStatement &stmt); - void Simplify(DeleteStatement &stmt); - - void Simplification(); - - template - void SimplifyList(vector &list, bool is_optional = true); - template - void SimplifyMap(T &map); - template - void SimplifySet(T &set); - - template - void SimplifyReplace(T &element, T &other); - - template - void SimplifyOptional(duckdb::unique_ptr &opt); - template - void SimplifyAlias(T &input); - template - void SimplifyEnum(T &enum_ref, T default_value); - - void Simplify(unique_ptr &ref); - - void Simplify(SelectNode &node); - void Simplify(SetOperationNode &node); - void Simplify(unique_ptr &node); - - void Simplify(ResultModifier &modifier); - void Simplify(OrderModifier &modifier); - - void SimplifyExpression(duckdb::unique_ptr &expr); - void SimplifyOptionalExpression(duckdb::unique_ptr &expr); - void SimplifyChildExpression(duckdb::unique_ptr &expr, unique_ptr &child); - void SimplifyExpressionList(duckdb::unique_ptr &expr, - vector> &expression_list); - void SimplifyExpressionList(vector> &expression_list, bool is_optional = true); - void Simplify(CommonTableExpressionMap &cte_map); - void Simplify(GroupByNode &groups); - - void Simplify(UpdateSetInfo &info); - -private: - vector>> query_nodes; -}; - -} // namespace duckdb diff --git a/extension/sqlsmith/sqlsmith_extension.cpp b/extension/sqlsmith/sqlsmith_extension.cpp deleted file mode 100644 index 0ee11118cf5..00000000000 --- a/extension/sqlsmith/sqlsmith_extension.cpp +++ /dev/null @@ -1,223 +0,0 @@ -#define DUCKDB_EXTENSION_MAIN - -#include "sqlsmith_extension.hpp" -#include "sqlsmith.hh" -#include "statement_simplifier.hpp" -#include "fuzzyduck.hpp" - -#ifndef DUCKDB_AMALGAMATION -#include "duckdb/function/table_function.hpp" -#include "duckdb/parser/parser.hpp" -#include "duckdb/main/extension_util.hpp" -#endif - -namespace duckdb { - -struct SQLSmithFunctionData : public TableFunctionData { - SQLSmithFunctionData() { - } - - int32_t seed = -1; - idx_t max_queries = 0; - bool exclude_catalog = false; - bool dump_all_queries = false; - bool dump_all_graphs = false; - bool verbose_output = false; - string complete_log; - string log; - bool finished = false; -}; - -static duckdb::unique_ptr SQLSmithBind(ClientContext &context, TableFunctionBindInput &input, - vector &return_types, vector &names) { - auto result = make_uniq(); - for (auto &kv : input.named_parameters) { - if (kv.first == "seed") { - result->seed = IntegerValue::Get(kv.second); - } else if (kv.first == "max_queries") { - result->max_queries = UBigIntValue::Get(kv.second); - } else if (kv.first == "exclude_catalog") { - result->exclude_catalog = BooleanValue::Get(kv.second); - } else if (kv.first == "dump_all_queries") { - result->dump_all_queries = BooleanValue::Get(kv.second); - } else if (kv.first == "dump_all_graphs") { - result->dump_all_graphs = BooleanValue::Get(kv.second); - } else if (kv.first == "verbose_output") { - result->verbose_output = BooleanValue::Get(kv.second); - } else if (kv.first == "complete_log") { - result->complete_log = StringValue::Get(kv.second); - } else if (kv.first == "log") { - result->log = StringValue::Get(kv.second); - } - } - return_types.emplace_back(LogicalType::BOOLEAN); - names.emplace_back("Success"); - return std::move(result); -} - -static void SQLSmithFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { - auto &data = data_p.bind_data->CastNoConst(); - if (data.finished) { - return; - } - - duckdb_sqlsmith::SQLSmithOptions options; - options.seed = data.seed; - options.max_queries = data.max_queries; - options.exclude_catalog = data.exclude_catalog; - options.dump_all_queries = data.dump_all_queries; - options.dump_all_graphs = data.dump_all_graphs; - options.verbose_output = data.verbose_output; - options.complete_log = data.complete_log; - options.log = data.log; - duckdb_sqlsmith::run_sqlsmith(DatabaseInstance::GetDatabase(context), options); - - data.finished = true; -} - -struct ReduceSQLFunctionData : public TableFunctionData { - ReduceSQLFunctionData() { - } - - vector statements; - idx_t offset = 0; -}; - -static duckdb::unique_ptr ReduceSQLBind(ClientContext &context, TableFunctionBindInput &input, - vector &return_types, vector &names) { - return_types.emplace_back(LogicalType::VARCHAR); - names.emplace_back("sql"); - - auto result = make_uniq(); - auto sql = input.inputs[0].ToString(); - Parser parser; - parser.ParseQuery(sql); - if (parser.statements.size() != 1) { - throw InvalidInputException("reduce_sql_statement requires a single statement as parameter"); - } - auto &statement = *parser.statements[0]; - StatementSimplifier simplifier(statement, result->statements); - simplifier.Simplify(statement); - return std::move(result); -} - -static void ReduceSQLFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { - auto &data = data_p.bind_data->CastNoConst(); - if (data.offset >= data.statements.size()) { - // finished returning values - return; - } - // start returning values - // either fill up the chunk or return all the remaining columns - idx_t count = 0; - while (data.offset < data.statements.size() && count < STANDARD_VECTOR_SIZE) { - auto &entry = data.statements[data.offset++]; - output.data[0].SetValue(count, Value(entry)); - count++; - } - output.SetCardinality(count); -} - -struct FuzzyDuckFunctionData : public TableFunctionData { - FuzzyDuckFunctionData(ClientContext &context) : fuzzer(context) { - } - - FuzzyDuck fuzzer; - bool finished = false; -}; - -static duckdb::unique_ptr FuzzyDuckBind(ClientContext &context, TableFunctionBindInput &input, - vector &return_types, vector &names) { - auto result = make_uniq(context); - for (auto &kv : input.named_parameters) { - if (kv.first == "seed") { - result->fuzzer.seed = IntegerValue::Get(kv.second); - } else if (kv.first == "max_queries") { - result->fuzzer.max_queries = UBigIntValue::Get(kv.second); - } else if (kv.first == "complete_log") { - result->fuzzer.complete_log = StringValue::Get(kv.second); - } else if (kv.first == "log") { - result->fuzzer.log = StringValue::Get(kv.second); - } else if (kv.first == "verbose_output") { - result->fuzzer.verbose_output = BooleanValue::Get(kv.second); - } - } - return_types.emplace_back(LogicalType::BOOLEAN); - names.emplace_back("Success"); - return std::move(result); -} - -static void FuzzyDuckFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { - auto &data = data_p.bind_data->CastNoConst(); - if (data.finished) { - return; - } - - data.fuzzer.Fuzz(); - data.finished = true; -} - -static void FuzzAllFunctions(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { - auto &data = data_p.bind_data->CastNoConst(); - if (data.finished) { - return; - } - - data.fuzzer.FuzzAllFunctions(); - data.finished = true; -} - -void SqlsmithExtension::Load(DuckDB &db) { - auto &db_instance = *db.instance; - - TableFunction sqlsmith_func("sqlsmith", {}, SQLSmithFunction, SQLSmithBind); - sqlsmith_func.named_parameters["seed"] = LogicalType::INTEGER; - sqlsmith_func.named_parameters["max_queries"] = LogicalType::UBIGINT; - sqlsmith_func.named_parameters["exclude_catalog"] = LogicalType::BOOLEAN; - sqlsmith_func.named_parameters["dump_all_queries"] = LogicalType::BOOLEAN; - sqlsmith_func.named_parameters["dump_all_graphs"] = LogicalType::BOOLEAN; - sqlsmith_func.named_parameters["verbose_output"] = LogicalType::BOOLEAN; - sqlsmith_func.named_parameters["complete_log"] = LogicalType::VARCHAR; - sqlsmith_func.named_parameters["log"] = LogicalType::VARCHAR; - ExtensionUtil::RegisterFunction(db_instance, sqlsmith_func); - - TableFunction fuzzy_duck_fun("fuzzyduck", {}, FuzzyDuckFunction, FuzzyDuckBind); - fuzzy_duck_fun.named_parameters["seed"] = LogicalType::INTEGER; - fuzzy_duck_fun.named_parameters["max_queries"] = LogicalType::UBIGINT; - fuzzy_duck_fun.named_parameters["log"] = LogicalType::VARCHAR; - fuzzy_duck_fun.named_parameters["complete_log"] = LogicalType::VARCHAR; - fuzzy_duck_fun.named_parameters["verbose_output"] = LogicalType::BOOLEAN; - ExtensionUtil::RegisterFunction(db_instance, fuzzy_duck_fun); - - TableFunction fuzz_all_functions("fuzz_all_functions", {}, FuzzAllFunctions, FuzzyDuckBind); - fuzz_all_functions.named_parameters["seed"] = LogicalType::INTEGER; - fuzz_all_functions.named_parameters["log"] = LogicalType::VARCHAR; - fuzz_all_functions.named_parameters["complete_log"] = LogicalType::VARCHAR; - fuzz_all_functions.named_parameters["verbose_output"] = LogicalType::BOOLEAN; - ExtensionUtil::RegisterFunction(db_instance, fuzz_all_functions); - - TableFunction reduce_sql_function("reduce_sql_statement", {LogicalType::VARCHAR}, ReduceSQLFunction, ReduceSQLBind); - ExtensionUtil::RegisterFunction(db_instance, reduce_sql_function); -} - -std::string SqlsmithExtension::Name() { - return "sqlsmith"; -} - -} // namespace duckdb - -extern "C" { - -DUCKDB_EXTENSION_API void sqlsmith_init(duckdb::DatabaseInstance &db) { - duckdb::DuckDB db_wrapper(db); - db_wrapper.LoadExtension(); -} - -DUCKDB_EXTENSION_API const char *sqlsmith_version() { - return duckdb::DuckDB::LibraryVersion(); -} -} - -#ifndef DUCKDB_EXTENSION_MAIN -#error DUCKDB_EXTENSION_MAIN not defined -#endif diff --git a/extension/sqlsmith/statement_generator.cpp b/extension/sqlsmith/statement_generator.cpp deleted file mode 100644 index 9727ad317a6..00000000000 --- a/extension/sqlsmith/statement_generator.cpp +++ /dev/null @@ -1,1261 +0,0 @@ -#include "statement_generator.hpp" - -#include "duckdb/catalog/catalog_entry/list.hpp" -#include "duckdb/common/random_engine.hpp" -#include "duckdb/common/types/uuid.hpp" -#include "duckdb/function/table/system_functions.hpp" -#include "duckdb/parser/expression/list.hpp" -#include "duckdb/parser/parsed_data/create_schema_info.hpp" -#include "duckdb/parser/parsed_data/create_table_info.hpp" -#include "duckdb/parser/parsed_data/create_view_info.hpp" -#include "duckdb/parser/parsed_data/create_function_info.hpp" -#include "duckdb/parser/parsed_data/create_type_info.hpp" -#include "duckdb/parser/parsed_expression_iterator.hpp" -#include "duckdb/parser/query_node/select_node.hpp" -#include "duckdb/parser/query_node/set_operation_node.hpp" -#include "duckdb/parser/statement/create_statement.hpp" -#include "duckdb/parser/statement/delete_statement.hpp" -#include "duckdb/parser/statement/insert_statement.hpp" -#include "duckdb/parser/statement/select_statement.hpp" -#include "duckdb/parser/statement/update_statement.hpp" -#include "duckdb/parser/tableref/list.hpp" - -namespace duckdb { - -struct GeneratorContext { - vector test_types; - vector> scalar_functions; - vector> table_functions; - vector> pragma_functions; - vector> tables_and_views; -}; - -StatementGenerator::StatementGenerator(ClientContext &context) : context(context), parent(nullptr), depth(0) { - generator_context = GetDatabaseState(context); -} - -StatementGenerator::StatementGenerator(StatementGenerator &parent_p) - : context(parent_p.context), parent(&parent_p), generator_context(parent_p.generator_context), - depth(parent_p.depth + 1) { - if (depth > MAX_DEPTH) { - throw InternalException("depth too high"); - } -} - -StatementGenerator::~StatementGenerator() { -} - -std::shared_ptr StatementGenerator::GetDatabaseState(ClientContext &context) { - auto result = std::make_shared(); - result->test_types = TestAllTypesFun::GetTestTypes(); - - auto schemas = Catalog::GetAllSchemas(context); - // extract the functions - for (auto &schema_ref : schemas) { - auto &schema = schema_ref.get(); - schema.Scan(context, CatalogType::SCALAR_FUNCTION_ENTRY, - [&](CatalogEntry &entry) { result->scalar_functions.push_back(entry); }); - schema.Scan(context, CatalogType::TABLE_FUNCTION_ENTRY, [&](CatalogEntry &entry) { - // don't include fuzz functions - if (entry.name.find("fuzzyduck") == std::string::npos && - entry.name.find("fuzz_all_functions") == std::string::npos && - entry.name.find("reduce_sql_statement") == std::string::npos && - entry.name.find("sqlsmith") == std::string::npos) { - result->table_functions.push_back(entry); - } - }); - schema.Scan(context, CatalogType::PRAGMA_FUNCTION_ENTRY, - [&](CatalogEntry &entry) { result->pragma_functions.push_back(entry); }); - schema.Scan(context, CatalogType::TABLE_ENTRY, [&](CatalogEntry &entry) { - if (entry.internal) { - return; - } - result->tables_and_views.push_back(entry); - }); - } - return result; -} - -unique_ptr StatementGenerator::GenerateStatement() { - if (RandomPercentage(80)) { - return GenerateStatement(StatementType::SELECT_STATEMENT); - } - return GenerateStatement(StatementType::CREATE_STATEMENT); -} - -unique_ptr StatementGenerator::GenerateStatement(StatementType type) { - switch (type) { - case StatementType::SELECT_STATEMENT: - return GenerateSelect(); - case StatementType::CREATE_STATEMENT: - return GenerateCreate(); - default: - throw InternalException("Unsupported type"); - } -} - -//===--------------------------------------------------------------------===// -// Statements -//===--------------------------------------------------------------------===// -unique_ptr StatementGenerator::GenerateSelect() { - auto select = make_uniq(); - select->node = GenerateQueryNode(); - return select; -} - -unique_ptr StatementGenerator::GenerateCreate() { - auto create = make_uniq(); - create->info = GenerateCreateInfo(); - return create; -} - -//===--------------------------------------------------------------------===// -// Create Info Node -//===--------------------------------------------------------------------===// - -unique_ptr StatementGenerator::GenerateCreateInfo() { - switch (RandomValue(4)) { - case 0: { - auto info = make_uniq(); - info->name = RandomString(5); - idx_t num_enums = RandomValue(10); - auto Enum_Vector = Vector(LogicalType::VARCHAR, num_enums); - for (idx_t i = 0; i < num_enums; i++) { - Enum_Vector.SetValue(i, Value(RandomString(10))); - } - info->type = LogicalType::ENUM("My_enum", Enum_Vector, num_enums); - return std::move(info); - } - case 1: { - auto info = make_uniq(); - info->catalog = INVALID_CATALOG; - info->schema = DEFAULT_SCHEMA; - info->table = GenerateTableIdentifier(); - if (RandomPercentage(50)) { - info->query = GenerateSelect(); - } else { - idx_t num_cols = RandomValue(1000); - for (idx_t i = 0; i < num_cols; i++) { - info->columns.AddColumn(ColumnDefinition(GenerateIdentifier(), GenerateLogicalType())); - } - } - // TODO: add constraints to the columns (primary keys etc.); - return std::move(info); - } - case 2: { - auto info = make_uniq(); - info->catalog = INVALID_CATALOG; - info->on_conflict = OnCreateConflict::REPLACE_ON_CONFLICT; - info->schema = GenerateSchemaIdentifier(); - return std::move(info); - } - case 3: { - auto info = make_uniq(); - info->view_name = GenerateViewIdentifier(); - info->query = GenerateSelect(); - // TODO: add support for aliases in the view. - return std::move(info); - } - default: - break; - } - throw InternalException("Unsupported Create Info Type"); -} - -//===--------------------------------------------------------------------===// -// Query Node -//===--------------------------------------------------------------------===// -void StatementGenerator::GenerateCTEs(QueryNode &node) { - if (depth > 0) { - return; - } - while (RandomPercentage(20)) { - auto cte = make_uniq(); - cte->query = unique_ptr_cast(GenerateSelect()); - for (idx_t i = 0; i < 1 + RandomValue(10); i++) { - cte->aliases.push_back(GenerateIdentifier()); - } - node.cte_map.map.insert(make_pair(GenerateTableIdentifier(), std::move(cte))); - } -} -unique_ptr StatementGenerator::GenerateQueryNode() { - unique_ptr result; - bool is_distinct = false; - if (RandomPercentage(70)) { - // select node - auto select_node = make_uniq(); - // generate CTEs - GenerateCTEs(*select_node); - - is_distinct = RandomPercentage(30); - if (RandomPercentage(95)) { - select_node->from_table = GenerateTableRef(); - } - select_node->select_list = GenerateChildren(1, 10); - select_node->where_clause = RandomExpression(60); - select_node->having = RandomExpression(25); - if (RandomPercentage(30)) { - select_node->groups.group_expressions = GenerateChildren(1, 5); - auto group_count = select_node->groups.group_expressions.size(); - if (RandomPercentage(70)) { - // single GROUP BY - GroupingSet set; - for (idx_t i = 0; i < group_count; i++) { - set.insert(i); - } - select_node->groups.grouping_sets.push_back(std::move(set)); - } else { - // multiple grouping sets - while (true) { - GroupingSet set; - while (true) { - set.insert(RandomValue(group_count)); - if (RandomPercentage(50)) { - break; - } - } - select_node->groups.grouping_sets.push_back(std::move(set)); - if (RandomPercentage(70)) { - break; - } - } - } - } - select_node->qualify = RandomExpression(10); - select_node->aggregate_handling = - RandomPercentage(10) ? AggregateHandling::FORCE_AGGREGATES : AggregateHandling::STANDARD_HANDLING; - if (RandomPercentage(10)) { - auto sample = make_uniq(); - sample->is_percentage = RandomPercentage(50); - if (sample->is_percentage) { - sample->sample_size = Value::BIGINT(RandomValue(100)); - } else { - sample->sample_size = Value::BIGINT(RandomValue(99999)); - } - sample->method = Choose( - {SampleMethod::BERNOULLI_SAMPLE, SampleMethod::RESERVOIR_SAMPLE, SampleMethod::SYSTEM_SAMPLE}); - select_node->sample = std::move(sample); - } - result = std::move(select_node); - } else { - auto setop = make_uniq(); - GenerateCTEs(*setop); - setop->setop_type = Choose({SetOperationType::EXCEPT, SetOperationType::INTERSECT, - SetOperationType::UNION, SetOperationType::UNION_BY_NAME}); - setop->left = GenerateQueryNode(); - setop->right = GenerateQueryNode(); - switch (setop->setop_type) { - case SetOperationType::EXCEPT: - case SetOperationType::INTERSECT: - is_distinct = true; - break; - case SetOperationType::UNION: - case SetOperationType::UNION_BY_NAME: - is_distinct = RandomBoolean(); - break; - default: - throw InternalException("Unsupported set operation type"); - } - result = std::move(setop); - } - - if (is_distinct) { - result->modifiers.push_back(make_uniq()); - } - if (RandomPercentage(20)) { - result->modifiers.push_back(GenerateOrderBy()); - } - if (RandomPercentage(20)) { - if (RandomPercentage(50)) { - auto limit_percent_modifier = make_uniq(); - if (RandomPercentage(30)) { - limit_percent_modifier->limit = GenerateExpression(); - } else if (RandomPercentage(30)) { - limit_percent_modifier->offset = GenerateExpression(); - } else { - limit_percent_modifier->limit = GenerateExpression(); - limit_percent_modifier->offset = GenerateExpression(); - } - result->modifiers.push_back(std::move(limit_percent_modifier)); - } else { - auto limit_modifier = make_uniq(); - if (RandomPercentage(30)) { - limit_modifier->limit = GenerateExpression(); - } else if (RandomPercentage(30)) { - limit_modifier->offset = GenerateExpression(); - } else { - limit_modifier->limit = GenerateExpression(); - limit_modifier->offset = GenerateExpression(); - } - result->modifiers.push_back(std::move(limit_modifier)); - } - } - return result; -} - -//===--------------------------------------------------------------------===// -// Table Ref -//===--------------------------------------------------------------------===// -unique_ptr StatementGenerator::GenerateTableRef() { - if (RandomPercentage(60)) { - return GenerateBaseTableRef(); - } - if (RandomPercentage(20)) { - return GenerateExpressionListRef(); - } - if (RandomPercentage(40)) { - return GenerateJoinRef(); - } - switch (RandomValue(3)) { - case 0: - return GenerateSubqueryRef(); - case 1: - return GenerateTableFunctionRef(); - case 2: - return GeneratePivotRef(); - default: - throw InternalException("StatementGenerator::GenerateTableRef"); - } -} - -unique_ptr StatementGenerator::GenerateBaseTableRef() { - if (generator_context->tables_and_views.empty()) { - return GenerateExpressionListRef(); - } - auto &entry_ref = Choose(generator_context->tables_and_views); - auto &entry = entry_ref.get(); - auto result = make_uniq(); - idx_t column_count; - switch (entry.type) { - case CatalogType::TABLE_ENTRY: { - auto &table = entry.Cast(); - column_count = table.GetColumns().LogicalColumnCount(); - break; - } - case CatalogType::VIEW_ENTRY: { - auto &view = entry.Cast(); - column_count = view.types.size(); - break; - } - default: - throw InternalException("StatementGenerator::GenerateBaseTableRef"); - } - for (idx_t i = 0; i < column_count; i++) { - result->column_name_alias.push_back(GenerateIdentifier()); - } - result->alias = GenerateTableIdentifier(); - result->table_name = entry.name; - return std::move(result); -} - -unique_ptr StatementGenerator::GenerateExpressionListRef() { - auto result = make_uniq(); - auto column_count = 1 + RandomValue(10); - for (idx_t r = 0; r < 1 + RandomValue(10); r++) { - vector> values; - for (idx_t c = 0; c < column_count; c++) { - values.push_back(GenerateConstant()); - } - result->values.push_back(std::move(values)); - } - return std::move(result); -} - -unique_ptr StatementGenerator::GenerateJoinRef() { - JoinRefType join_ref; - if (RandomPercentage(10)) { - join_ref = JoinRefType::CROSS; - } else if (RandomPercentage(10)) { - join_ref = JoinRefType::ASOF; - } else if (RandomPercentage(10)) { - join_ref = JoinRefType::NATURAL; - } else if (RandomPercentage(10)) { - join_ref = JoinRefType::POSITIONAL; - } else { - join_ref = JoinRefType::REGULAR; - } - auto join = make_uniq(join_ref); - join->left = GenerateTableRef(); - join->right = GenerateTableRef(); - if (join_ref != JoinRefType::CROSS && join_ref != JoinRefType::NATURAL) { - if (RandomPercentage(70)) { - join->condition = GenerateExpression(); - } else { - while (true) { - join->using_columns.push_back(GenerateColumnName()); - if (RandomPercentage(50)) { - break; - } - } - } - } - join->type = Choose( - {JoinType::LEFT, JoinType::RIGHT, JoinType::INNER, JoinType::OUTER, JoinType::SEMI, JoinType::ANTI}); - return std::move(join); -} - -unique_ptr StatementGenerator::GenerateSubqueryRef() { - if (depth >= MAX_DEPTH) { - return GenerateBaseTableRef(); - } - unique_ptr subquery; - { - StatementGenerator child_generator(*this); - subquery = unique_ptr_cast(child_generator.GenerateSelect()); - for (auto &col : child_generator.current_column_names) { - current_column_names.push_back(std::move(col)); - } - } - auto result = make_uniq(std::move(subquery), GenerateTableIdentifier()); - return std::move(result); -} - -unique_ptr StatementGenerator::GenerateTableFunctionRef() { - auto function = make_uniq(); - auto &table_function_ref = Choose(generator_context->table_functions); - auto &entry = table_function_ref.get().Cast(); - auto table_function = entry.functions.GetFunctionByOffset(RandomValue(entry.functions.Size())); - - auto result = make_uniq(); - vector> children; - for (idx_t i = 0; i < table_function.arguments.size(); i++) { - children.push_back(GenerateConstant()); - } - vector names; - for (auto &e : table_function.named_parameters) { - names.push_back(e.first); - } - while (!names.empty() && RandomPercentage(50)) { - auto name = Choose(names); - names.erase(std::find(names.begin(), names.end(), name)); - auto expr = GenerateConstant(); - expr->alias = name; - children.push_back(std::move(expr)); - } - result->function = make_uniq(entry.name, std::move(children)); - for (idx_t i = 0; i < 1 + RandomValue(9); i++) { - result->column_name_alias.push_back(GenerateIdentifier()); - } - result->alias = GenerateTableIdentifier(); - return std::move(result); -} - -unique_ptr StatementGenerator::GeneratePivotRef() { - auto pivot = make_uniq(); - pivot->source = GenerateTableRef(); - bool is_pivot = RandomPercentage(50); - if (is_pivot) { - // pivot - // aggregates - while (true) { - pivot->aggregates.push_back(GenerateFunction()); - if (RandomPercentage(50)) { - break; - } - } - while (RandomPercentage(50)) { - pivot->groups.push_back(GenerateColumnName()); - } - } else { - // unpivot - while (true) { - pivot->unpivot_names.push_back(GenerateColumnName()); - if (RandomPercentage(50)) { - break; - } - } - pivot->include_nulls = RandomBoolean(); - } - while (true) { - PivotColumn col; - idx_t number_of_columns = 1 + RandomValue(2); - for (idx_t i = 0; i < number_of_columns; i++) { - if (is_pivot) { - col.pivot_expressions.push_back(GenerateExpression()); - } else { - col.unpivot_names.push_back(GenerateColumnName()); - } - } - while (true) { - PivotColumnEntry entry; - for (idx_t i = 0; i < number_of_columns; i++) { - entry.values.push_back(GenerateConstantValue()); - } - col.entries.push_back(std::move(entry)); - if (RandomPercentage(50)) { - break; - } - } - pivot->pivots.push_back(std::move(col)); - if (RandomPercentage(70)) { - break; - } - } - return std::move(pivot); -} - -//===--------------------------------------------------------------------===// -// Expressions -//===--------------------------------------------------------------------===// -class ExpressionDepthChecker { -public: - explicit ExpressionDepthChecker(StatementGenerator &generator) : generator(generator) { - generator.expression_depth++; - } - ~ExpressionDepthChecker() { - generator.expression_depth--; - } - - StatementGenerator &generator; -}; - -unique_ptr StatementGenerator::GenerateExpression() { - ExpressionDepthChecker checker(*this); - if (RandomPercentage(50) || RandomPercentage(expression_depth + depth * 5)) { - return GenerateColumnRef(); - } - if (RandomPercentage(30)) { - return GenerateConstant(); - } - if (RandomPercentage(3)) { - return GenerateSubquery(); - } - switch (RandomValue(9)) { - case 0: - return GenerateOperator(); - case 1: - return GenerateFunction(); - case 2: - return GenerateWindowFunction(); - case 3: - return GenerateConjunction(); - case 4: - return GenerateStar(); - case 5: - return GenerateCast(); - case 6: - return GenerateBetween(); - case 7: - return GenerateComparison(); - case 8: - return GeneratePositionalReference(); - default: - throw InternalException("StatementGenerator::GenerateExpression"); - } -} - -Value StatementGenerator::GenerateConstantValue() { - if (RandomPercentage(50)) { - return Value::BIGINT(RandomValue(9999)); - } - if (RandomPercentage(30)) { - return Value(UUID::ToString(UUID::GenerateRandomUUID(RandomEngine::Get(context)))); - } - auto &val = Choose(generator_context->test_types); - Value constant_val; - switch (RandomValue(3)) { - case 0: - constant_val = val.min_value; - break; - case 1: - constant_val = val.max_value; - break; - case 2: - constant_val = Value(val.type); - break; - default: - throw InternalException("StatementGenerator::GenerateConstant"); - } - return constant_val; -} - -unique_ptr StatementGenerator::GenerateConstant() { - return make_uniq(GenerateConstantValue()); -} - -LogicalType StatementGenerator::GenerateLogicalType() { - return Choose(generator_context->test_types).type; -} - -unique_ptr StatementGenerator::GenerateColumnRef() { - auto column_name = GenerateColumnName(); - if (column_name.empty()) { - return GenerateConstant(); - } - return make_uniq(std::move(column_name)); -} - -class AggregateChecker { -public: - explicit AggregateChecker(StatementGenerator &generator) : generator(generator) { - generator.in_aggregate = true; - } - ~AggregateChecker() { - generator.in_aggregate = false; - } - - StatementGenerator &generator; -}; - -unique_ptr StatementGenerator::GenerateFunction() { - // get a random function - auto &function_ref = Choose(generator_context->scalar_functions); - auto &function = function_ref.get(); - string name; - idx_t min_parameters; - idx_t max_parameters; - unique_ptr filter; - unique_ptr order_bys; - bool distinct = false; - unique_ptr checker; - vector arguments; - switch (function.type) { - case CatalogType::SCALAR_FUNCTION_ENTRY: { - auto &scalar_entry = function.Cast(); - auto actual_function = scalar_entry.functions.GetFunctionByOffset(RandomValue(scalar_entry.functions.Size())); - - name = scalar_entry.name; - arguments = actual_function.arguments; - min_parameters = actual_function.arguments.size(); - max_parameters = min_parameters; - if (actual_function.varargs.id() != LogicalTypeId::INVALID) { - max_parameters += 5; - } - break; - } - case CatalogType::AGGREGATE_FUNCTION_ENTRY: { - auto &aggregate_entry = function.Cast(); - auto actual_function = - aggregate_entry.functions.GetFunctionByOffset(RandomValue(aggregate_entry.functions.Size())); - - name = aggregate_entry.name; - min_parameters = actual_function.arguments.size(); - max_parameters = min_parameters; - if (actual_function.varargs.id() != LogicalTypeId::INVALID) { - max_parameters += 5; - } - if (RandomPercentage(10) && !in_window) { - return GenerateWindowFunction(&actual_function); - } - if (in_aggregate) { - // we cannot nest aggregates - return GenerateColumnRef(); - } - checker = make_uniq(*this); - filter = RandomExpression(10); - if (RandomPercentage(10)) { - // generate order by - order_bys = GenerateOrderBy(); - } - if (RandomPercentage(10)) { - distinct = true; - } - break; - } - case CatalogType::MACRO_ENTRY: { - auto ¯o_entry = function.Cast(); - name = macro_entry.name; - min_parameters = macro_entry.function->parameters.size(); - max_parameters = min_parameters; - break; - } - default: - throw InternalException("StatementGenerator::GenerateFunction"); - } - auto children = GenerateChildren(min_parameters, max_parameters); - // push lambda expressions - for (idx_t i = 0; i < arguments.size(); i++) { - if (arguments[i].id() == LogicalTypeId::LAMBDA) { - children[i] = GenerateLambda(); - } - } - // FIXME: add export_state - return make_uniq(std::move(name), std::move(children), std::move(filter), std::move(order_bys), - distinct); -} - -unique_ptr StatementGenerator::GenerateOrderBy() { - auto result = make_uniq(); - while (true) { - auto order_type = Choose({OrderType::ASCENDING, OrderType::DESCENDING, OrderType::ORDER_DEFAULT}); - auto null_type = Choose( - {OrderByNullType::NULLS_FIRST, OrderByNullType::NULLS_LAST, OrderByNullType::ORDER_DEFAULT}); - result->orders.emplace_back(order_type, null_type, GenerateExpression()); - // continue with a random chance - if (RandomPercentage(50)) { - break; - } - } - return result; -} - -unique_ptr StatementGenerator::GenerateOperator() { - ExpressionType type; - idx_t min_parameters; - idx_t max_parameters; - switch (RandomValue(9)) { - case 0: - type = ExpressionType::COMPARE_IN; - min_parameters = 2; - max_parameters = 10; - break; - case 1: - type = ExpressionType::COMPARE_NOT_IN; - min_parameters = 2; - max_parameters = 10; - break; - case 2: - type = ExpressionType::OPERATOR_NOT; - min_parameters = 1; - max_parameters = 1; - break; - case 3: - type = ExpressionType::OPERATOR_COALESCE; - min_parameters = 2; - max_parameters = 10; - break; - case 4: - type = ExpressionType::OPERATOR_IS_NULL; - min_parameters = 1; - max_parameters = 1; - break; - case 5: - type = ExpressionType::OPERATOR_IS_NOT_NULL; - min_parameters = 1; - max_parameters = 1; - break; - case 6: - type = ExpressionType::ARRAY_EXTRACT; - min_parameters = 2; - max_parameters = 2; - break; - case 7: - type = ExpressionType::ARRAY_SLICE; - min_parameters = 3; - max_parameters = 3; - break; - case 8: - type = ExpressionType::ARRAY_CONSTRUCTOR; - min_parameters = 0; - max_parameters = 10; - break; - default: - throw InternalException("StatementGenerator::GenerateOperator"); - } - auto children = GenerateChildren(min_parameters, max_parameters); - return make_uniq(type, std::move(children)); -} - -vector> StatementGenerator::GenerateChildren(idx_t min, idx_t max) { - if (min > max) { - throw InternalException("StatementGenerator::GenerateChildren min > max"); - } - vector> children; - if (min == 0 && max == 0) { - return children; - } - idx_t upper_bound = min == max ? min : min + RandomValue(max - min); - for (idx_t i = 0; i < upper_bound; i++) { - children.push_back(GenerateExpression()); - } - return children; -} - -class WindowChecker { -public: - explicit WindowChecker(StatementGenerator &generator) : generator(generator) { - generator.in_window = true; - } - ~WindowChecker() { - generator.in_window = false; - } - - StatementGenerator &generator; -}; - -unique_ptr StatementGenerator::GenerateWindowFunction(optional_ptr function) { - if (in_window) { - // we cannot nest window functions - return GenerateColumnRef(); - } - ExpressionType type; - string name; - idx_t min_parameters; - idx_t max_parameters; - if (function) { - type = ExpressionType::WINDOW_AGGREGATE; - name = function->name; - min_parameters = function->arguments.size(); - max_parameters = min_parameters; - } else { - name = Choose({"rank", "rank_dense", "percent_rank", "row_number", "first_value", "last_value", - "nth_value", "cume_dist", "lead", "lag", "ntile"}); - type = WindowExpression::WindowToExpressionType(name); - switch (type) { - case ExpressionType::WINDOW_RANK: - case ExpressionType::WINDOW_RANK_DENSE: - case ExpressionType::WINDOW_ROW_NUMBER: - case ExpressionType::WINDOW_PERCENT_RANK: - case ExpressionType::WINDOW_CUME_DIST: - min_parameters = 0; - break; - case ExpressionType::WINDOW_NTILE: - case ExpressionType::WINDOW_FIRST_VALUE: - case ExpressionType::WINDOW_LAST_VALUE: - case ExpressionType::WINDOW_LEAD: - case ExpressionType::WINDOW_LAG: - min_parameters = 1; - break; - case ExpressionType::WINDOW_NTH_VALUE: - min_parameters = 2; - break; - default: - throw InternalException("StatementGenerator::GenerateWindow"); - } - max_parameters = min_parameters; - } - WindowChecker checker(*this); - auto result = make_uniq(type, INVALID_CATALOG, INVALID_SCHEMA, std::move(name)); - result->children = GenerateChildren(min_parameters, max_parameters); - while (RandomPercentage(50)) { - result->partitions.push_back(GenerateExpression()); - } - if (RandomPercentage(30)) { - result->orders = std::move(GenerateOrderBy()->orders); - } - if (function) { - result->filter_expr = RandomExpression(30); - if (RandomPercentage(30)) { - result->ignore_nulls = true; - } - } - vector window_boundaries { - WindowBoundary::UNBOUNDED_PRECEDING, WindowBoundary::UNBOUNDED_FOLLOWING, WindowBoundary::CURRENT_ROW_RANGE, - WindowBoundary::CURRENT_ROW_ROWS, WindowBoundary::EXPR_PRECEDING_ROWS, WindowBoundary::EXPR_FOLLOWING_ROWS, - WindowBoundary::EXPR_PRECEDING_RANGE, WindowBoundary::EXPR_FOLLOWING_RANGE}; - do { - result->start = Choose(window_boundaries); - } while (result->start == WindowBoundary::UNBOUNDED_FOLLOWING); - do { - result->end = Choose(window_boundaries); - } while (result->end == WindowBoundary::UNBOUNDED_PRECEDING); - switch (result->start) { - case WindowBoundary::EXPR_PRECEDING_ROWS: - case WindowBoundary::EXPR_PRECEDING_RANGE: - case WindowBoundary::EXPR_FOLLOWING_ROWS: - case WindowBoundary::EXPR_FOLLOWING_RANGE: - result->start_expr = GenerateExpression(); - break; - default: - break; - } - switch (result->end) { - case WindowBoundary::EXPR_PRECEDING_ROWS: - case WindowBoundary::EXPR_PRECEDING_RANGE: - case WindowBoundary::EXPR_FOLLOWING_ROWS: - case WindowBoundary::EXPR_FOLLOWING_RANGE: - result->end_expr = GenerateExpression(); - break; - default: - break; - } - switch (type) { - case ExpressionType::WINDOW_LEAD: - case ExpressionType::WINDOW_LAG: - result->offset_expr = RandomExpression(30); - result->default_expr = RandomExpression(30); - break; - default: - break; - } - return std::move(result); -} - -unique_ptr StatementGenerator::RandomExpression(idx_t percentage) { - if (RandomPercentage(percentage)) { - return GenerateExpression(); - } - return nullptr; -} - -unique_ptr StatementGenerator::GenerateConjunction() { - auto left = GenerateExpression(); - auto right = GenerateExpression(); - ExpressionType conjunction_type; - switch (RandomValue(2)) { - case 0: - conjunction_type = ExpressionType::CONJUNCTION_AND; - break; - case 1: - conjunction_type = ExpressionType::CONJUNCTION_OR; - break; - default: - throw InternalException("StatementGenerator::GenerateConjunction"); - } - return make_uniq(conjunction_type, std::move(left), std::move(right)); -} - -unique_ptr StatementGenerator::GenerateStar() { - auto result = make_uniq(); - if (!current_relation_names.empty()) { - if (RandomPercentage(10)) { - result->relation_name = GenerateRelationName(); - } - } - - while (RandomPercentage(20)) { - auto column_name = GenerateColumnName(); - if (column_name.empty()) { - break; - } - result->exclude_list.insert(column_name); - } - while (RandomPercentage(20)) { - auto column_name = GenerateColumnName(); - if (column_name.empty()) { - break; - } - result->replace_list.insert(make_pair(column_name, GenerateExpression())); - } - if (RandomPercentage(50) || expression_depth > 0) { - result->columns = true; - if (RandomPercentage(50)) { - result->expr = GenerateLambda(); - } - } - return std::move(result); -} - -unique_ptr StatementGenerator::GenerateLambda() { - // generate the lambda name and add the lambda column names to the set of possibly-generated column names - auto lambda_parameter = GenerateIdentifier(); - // generate the lhs - auto lhs = make_uniq(lambda_parameter); - auto rhs = GenerateExpression(); - current_column_names.erase(std::find(current_column_names.begin(), current_column_names.end(), lambda_parameter)); - - return make_uniq(std::move(lhs), std::move(rhs)); -} - -string StatementGenerator::GenerateTableIdentifier() { - auto identifier = "t" + to_string(GetIndex()); - current_relation_names.push_back(identifier); - return identifier; -} - -string StatementGenerator::GenerateIdentifier() { - auto identifier = "c" + to_string(GetIndex()); - current_column_names.push_back(identifier); - return identifier; -} - -string StatementGenerator::GenerateSchemaIdentifier() { - auto identifier = "s" + to_string(GetIndex()); - // TODO: add support for current_schema_names - return identifier; -} - -string StatementGenerator::GenerateViewIdentifier() { - auto identifier = "v" + to_string(GetIndex()); - current_relation_names.push_back(identifier); - return identifier; -} - -idx_t StatementGenerator::GetIndex() { - if (parent) { - return parent->GetIndex(); - } - return ++index; -} - -unique_ptr StatementGenerator::GenerateSubquery() { - if (depth >= MAX_DEPTH || in_window) { - return GenerateConstant(); - } - auto subquery = make_uniq(); - - { - StatementGenerator child_generator(*this); - subquery->subquery = unique_ptr_cast(child_generator.GenerateSelect()); - } - subquery->subquery_type = - Choose({SubqueryType::ANY, SubqueryType::EXISTS, SubqueryType::SCALAR, SubqueryType::NOT_EXISTS}); - if (subquery->subquery_type == SubqueryType::ANY || subquery->subquery_type == SubqueryType::SCALAR) { - subquery->child = GenerateExpression(); - } - if (subquery->subquery_type == SubqueryType::ANY) { - subquery->comparison_type = GenerateComparisonType(); - } - return std::move(subquery); -} - -unique_ptr StatementGenerator::GenerateCast() { - auto child = GenerateExpression(); - auto type = GenerateLogicalType(); - return make_uniq(std::move(type), std::move(child), RandomBoolean()); -} - -unique_ptr StatementGenerator::GenerateBetween() { - auto input = GenerateExpression(); - auto lower = GenerateExpression(); - auto upper = GenerateExpression(); - return make_uniq(std::move(input), std::move(lower), std::move(upper)); -} - -ExpressionType StatementGenerator::GenerateComparisonType() { - static vector comparisons {ExpressionType::COMPARE_EQUAL, - ExpressionType::COMPARE_NOTEQUAL, - ExpressionType::COMPARE_LESSTHAN, - ExpressionType::COMPARE_GREATERTHAN, - ExpressionType::COMPARE_LESSTHANOREQUALTO, - ExpressionType::COMPARE_GREATERTHANOREQUALTO, - ExpressionType::COMPARE_DISTINCT_FROM, - ExpressionType::COMPARE_NOT_DISTINCT_FROM}; - return Choose(comparisons); -} - -unique_ptr StatementGenerator::GenerateComparison() { - auto lhs = GenerateExpression(); - auto rhs = GenerateExpression(); - return make_uniq(GenerateComparisonType(), std::move(lhs), std::move(rhs)); -} - -unique_ptr StatementGenerator::GeneratePositionalReference() { - return make_uniq(1 + RandomValue(10)); -} - -unique_ptr StatementGenerator::GenerateCase() { - auto case_stmt = make_uniq(); - case_stmt->else_expr = GenerateExpression(); - while (true) { - CaseCheck check; - check.then_expr = GenerateExpression(); - check.when_expr = GenerateExpression(); - case_stmt->case_checks.push_back(std::move(check)); - if (RandomPercentage(50)) { - break; - } - } - return std::move(case_stmt); -} - -//===--------------------------------------------------------------------===// -// Helpers -//===--------------------------------------------------------------------===// -string StatementGenerator::GenerateRelationName() { - if (parent) { - auto parent_relation = parent->GenerateRelationName(); - if (current_relation_names.empty()) { - return parent_relation; - } - if (parent_relation.empty() || RandomPercentage(80)) { - return Choose(current_relation_names); - } - return parent_relation; - } else { - if (current_relation_names.empty()) { - return string(); - } - return Choose(current_relation_names); - } -} - -string StatementGenerator::GenerateColumnName() { - if (parent) { - auto parent_column = parent->GenerateColumnName(); - if (current_column_names.empty()) { - return parent_column; - } - if (parent_column.empty() || RandomPercentage(80)) { - return Choose(current_column_names); - } - return parent_column; - } else { - if (current_column_names.empty()) { - return string(); - } - return Choose(current_column_names); - } -} - -idx_t StatementGenerator::RandomValue(idx_t max) { - if (max == 0) { - return 0; - } - return RandomEngine::Get(context).NextRandomInteger() % max; -} - -string StatementGenerator::RandomString(idx_t length) { - - const string charset = "$_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - string result = ""; - for (int i = 0; i < length; ++i) { - int randomIndex = RandomValue(charset.length()); - result += charset[randomIndex]; - } - - return result; -} - -bool StatementGenerator::RandomBoolean() { - return RandomValue(2) == 0; -} - -bool StatementGenerator::RandomPercentage(idx_t percentage) { - if (percentage > 100) { - return true; - } - return RandomValue(100) <= percentage; -} - -//===--------------------------------------------------------------------===// -// Exhaustive Function Generation -//===--------------------------------------------------------------------===// -bool StatementGenerator::FunctionArgumentsAlwaysNull(const string &name) { - // some functions run for a very long time with extreme parameters because they e.g. generate giant strings - // for that reason we skip testing those functions with extreme parameters - static case_insensitive_set_t always_null_functions {"rpad", "pad", "lpad", "repeat"}; - - return always_null_functions.find(name) != always_null_functions.end(); -} -string StatementGenerator::GenerateTestAllTypes(BaseScalarFunction &base_function) { - auto select = make_uniq(); - auto node = make_uniq(); - - bool always_null = FunctionArgumentsAlwaysNull(base_function.name); - - vector> children; - for (auto &arg : base_function.arguments) { - // look up the type - unique_ptr argument; - if (!always_null) { - for (auto &test_type : generator_context->test_types) { - if (test_type.type.id() == arg.id()) { - argument = make_uniq(test_type.name); - } - } - } - if (!argument) { - argument = make_uniq(Value(arg)); - } - children.push_back(std::move(argument)); - } - auto from_clause = make_uniq(); - from_clause->table_name = "all_types"; - node->from_table = std::move(from_clause); - - auto function_expr = make_uniq(base_function.name, std::move(children)); - node->select_list.push_back(std::move(function_expr)); - - select->node = std::move(node); - return select->ToString(); -} - -string StatementGenerator::GenerateTestVectorTypes(BaseScalarFunction &base_function) { - auto select = make_uniq(); - auto node = make_uniq(); - - bool always_null = FunctionArgumentsAlwaysNull(base_function.name); - - vector> children; - vector> test_vector_types; - vector column_aliases; - for (auto &arg : base_function.arguments) { - unique_ptr argument; - if (!always_null) { - string argument_name = "c" + to_string(column_aliases.size() + 1); - column_aliases.push_back(argument_name); - argument = make_uniq(std::move(argument_name)); - auto constant_expr = make_uniq(Value()); - auto cast = make_uniq(arg, std::move(constant_expr)); - test_vector_types.push_back(std::move(cast)); - } else { - argument = make_uniq(Value(arg)); - } - children.push_back(std::move(argument)); - } - auto from_clause = make_uniq(); - auto vector_types_fun = make_uniq("test_vector_types", std::move(test_vector_types)); - from_clause->function = std::move(vector_types_fun); - from_clause->alias = "test_vector_types"; - from_clause->column_name_alias = std::move(column_aliases); - node->from_table = std::move(from_clause); - - auto function_expr = make_uniq(base_function.name, std::move(children)); - node->select_list.push_back(std::move(function_expr)); - - select->node = std::move(node); - return select->ToString(); -} - -string StatementGenerator::GenerateCast(const LogicalType &target, const string &source_name, bool add_varchar) { - auto select = make_uniq(); - auto node = make_uniq(); - - auto from_clause = make_uniq(); - from_clause->table_name = "all_types"; - node->from_table = std::move(from_clause); - - unique_ptr source; - source = make_uniq(source_name); - if (add_varchar) { - source = make_uniq(LogicalType::VARCHAR, std::move(source)); - } - auto cast = make_uniq(target, std::move(source)); - node->select_list.push_back(std::move(cast)); - - select->node = std::move(node); - return select->ToString(); -} - -void StatementGenerator::GenerateAllScalar(ScalarFunctionCatalogEntry &scalar_function, vector &result) { - for (idx_t offset = 0; offset < scalar_function.functions.Size(); offset++) { - auto function = scalar_function.functions.GetFunctionByOffset(offset); - - result.push_back(GenerateTestAllTypes(function)); - result.push_back(GenerateTestVectorTypes(function)); - } -} - -void StatementGenerator::GenerateAllAggregate(AggregateFunctionCatalogEntry &aggregate_function, - vector &result) { - for (idx_t offset = 0; offset < aggregate_function.functions.Size(); offset++) { - auto function = aggregate_function.functions.GetFunctionByOffset(offset); - - result.push_back(GenerateTestAllTypes(function)); - result.push_back(GenerateTestVectorTypes(function)); - } -} - -vector StatementGenerator::GenerateAllFunctionCalls() { - // all scalar functions - vector result; - for (auto &function_ref : generator_context->scalar_functions) { - auto &function = function_ref.get(); - switch (function.type) { - case CatalogType::SCALAR_FUNCTION_ENTRY: { - auto &scalar_entry = function.Cast(); - GenerateAllScalar(scalar_entry, result); - break; - } - case CatalogType::AGGREGATE_FUNCTION_ENTRY: { - auto &aggregate_entry = function.Cast(); - GenerateAllAggregate(aggregate_entry, result); - break; - } - case CatalogType::MACRO_ENTRY: - default: - break; - } - } - // generate all casts - for (auto &source_type : generator_context->test_types) { - for (auto &target_type : generator_context->test_types) { - result.push_back(GenerateCast(target_type.type, source_type.name, false)); - result.push_back(GenerateCast(target_type.type, source_type.name, true)); - } - } - return result; -} - -} // namespace duckdb diff --git a/extension/sqlsmith/statement_simplifier.cpp b/extension/sqlsmith/statement_simplifier.cpp deleted file mode 100644 index 66662f4cc02..00000000000 --- a/extension/sqlsmith/statement_simplifier.cpp +++ /dev/null @@ -1,453 +0,0 @@ -#include "statement_simplifier.hpp" - -#ifndef DUCKDB_AMALGAMATION -#include "duckdb/parser/query_node/select_node.hpp" -#include "duckdb/parser/query_node/set_operation_node.hpp" -#include "duckdb/parser/tableref/list.hpp" -#include "duckdb/parser/parsed_expression_iterator.hpp" -#include "duckdb/parser/expression/list.hpp" -#include "duckdb/parser/statement/delete_statement.hpp" -#include "duckdb/parser/statement/insert_statement.hpp" -#include "duckdb/parser/statement/update_statement.hpp" -#include "duckdb/parser/statement/select_statement.hpp" -#endif - -namespace duckdb { - -StatementSimplifier::StatementSimplifier(SQLStatement &statement_p, vector &result_p) - : statement(statement_p), result(result_p) { -} - -void StatementSimplifier::Simplification() { - result.push_back(statement.ToString()); -} - -template -void StatementSimplifier::SimplifyReplace(T &element, T &other) { - auto n = std::move(element); - element = std::move(other); - Simplification(); - other = std::move(element); - element = std::move(n); -} - -template -void StatementSimplifier::SimplifyList(vector &list, bool is_optional) { - if (list.size() <= (is_optional ? 0 : 1)) { - return; - } - for (idx_t i = 0; i < list.size(); i++) { - auto n = std::move(list[i]); - list.erase(list.begin() + i); - Simplification(); - list.insert(list.begin() + i, std::move(n)); - } -} - -template -void StatementSimplifier::SimplifyMap(T &map) { - if (map.empty()) { - return; - } - // copy the keys - vector keys; - for (auto &entry : map) { - keys.push_back(entry.first); - } - // try to remove all of the keys - for (idx_t i = 0; i < keys.size(); i++) { - auto entry = map.find(keys[i]); - auto n = std::move(entry->second); - map.erase(entry); - Simplification(); - map.insert(make_pair(std::move(keys[i]), std::move(n))); - } -} - -template -void StatementSimplifier::SimplifySet(T &set) { - if (set.empty()) { - return; - } - // copy the keys - vector keys; - for (auto &entry : set) { - keys.push_back(entry); - } - // try to remove all of the keys - for (idx_t i = 0; i < keys.size(); i++) { - auto entry = set.find(keys[i]); - set.erase(entry); - Simplification(); - set.insert(std::move(keys[i])); - } -} - -template -void StatementSimplifier::SimplifyOptional(duckdb::unique_ptr &opt) { - if (!opt) { - return; - } - auto n = std::move(opt); - Simplification(); - opt = std::move(n); -} - -template -void StatementSimplifier::SimplifyEnum(T &enum_ref, T default_value) { - if (enum_ref == default_value) { - return; - } - auto current = enum_ref; - enum_ref = default_value; - Simplification(); - enum_ref = current; -} - -template -void StatementSimplifier::SimplifyAlias(T &input) { - auto alias = std::move(input.alias); - auto column_name_alias = std::move(input.column_name_alias); - Simplification(); - input.alias = std::move(alias); - input.column_name_alias = std::move(column_name_alias); -} - -void StatementSimplifier::Simplify(unique_ptr &ref) { - switch (ref->type) { - case TableReferenceType::SUBQUERY: { - auto &subquery = ref->Cast(); - SimplifyAlias(subquery); - if (subquery.subquery->node->type == QueryNodeType::SELECT_NODE) { - auto &select_node = subquery.subquery->node->Cast(); - SimplifyReplace(ref, select_node.from_table); - } - Simplify(subquery.subquery->node); - break; - } - case TableReferenceType::JOIN: { - auto &cp = ref->Cast(); - Simplify(cp.left); - Simplify(cp.right); - SimplifyOptionalExpression(cp.condition); - SimplifyReplace(ref, cp.left); - SimplifyReplace(ref, cp.right); - SimplifyEnum(cp.type, JoinType::INNER); - SimplifyEnum(cp.ref_type, JoinRefType::REGULAR); - break; - } - case TableReferenceType::EXPRESSION_LIST: { - auto &expr_list = ref->Cast(); - if (expr_list.values.size() == 1) { - SimplifyList(expr_list.values[0]); - } else if (expr_list.values.size() > 1) { - SimplifyList(expr_list.values, false); - } - break; - } - case TableReferenceType::TABLE_FUNCTION: { - auto &table_function = ref->Cast(); - // try to remove aliases - SimplifyAlias(table_function); - break; - } - case TableReferenceType::BASE_TABLE: { - auto &table_ref = ref->Cast(); - SimplifyAlias(table_ref); - break; - } - default: - break; - } -} - -void StatementSimplifier::Simplify(GroupByNode &groups) { - // try to remove all groups - auto group_expr = std::move(groups.group_expressions); - auto group_sets = std::move(groups.grouping_sets); - Simplification(); - groups.group_expressions = std::move(group_expr); - groups.grouping_sets = std::move(group_sets); - - // try to remove grouping sets - SimplifyList(groups.grouping_sets, false); - // simplify expressions - for (auto &group : groups.group_expressions) { - SimplifyExpression(group); - } -} - -void StatementSimplifier::Simplify(SelectNode &node) { - // simplify projection list - SimplifyExpressionList(node.select_list, false); - // from clause - SimplifyOptional(node.from_table); - // simplify groups - Simplify(node.groups); - // simplify filters - SimplifyOptionalExpression(node.where_clause); - SimplifyOptionalExpression(node.having); - SimplifyOptionalExpression(node.qualify); - SimplifyOptional(node.sample); - SimplifyEnum(node.aggregate_handling, AggregateHandling::STANDARD_HANDLING); - - Simplify(node.from_table); -} - -void StatementSimplifier::Simplify(SetOperationNode &node) { - Simplify(node.left); - Simplify(node.right); -} - -void StatementSimplifier::Simplify(CommonTableExpressionMap &cte) { - // remove individual CTEs - SimplifyMap(cte.map); - for (auto &cte_child : cte.map) { - // simplify individual ctes - Simplify(cte_child.second->query->node); - } -} - -void StatementSimplifier::Simplify(unique_ptr &node) { - query_nodes.push_back(node); - Simplify(node->cte_map); - switch (node->type) { - case QueryNodeType::SELECT_NODE: - Simplify(node->Cast()); - break; - case QueryNodeType::SET_OPERATION_NODE: { - auto &setop = node->Cast(); - SimplifyReplace(node, setop.left); - SimplifyReplace(node, setop.right); - Simplify(setop); - break; - } - case QueryNodeType::RECURSIVE_CTE_NODE: - case QueryNodeType::CTE_NODE: - default: - break; - } - for (auto &modifier : node->modifiers) { - Simplify(*modifier); - } - SimplifyList(node->modifiers); - query_nodes.pop_back(); -} - -void StatementSimplifier::SimplifyExpressionList(duckdb::unique_ptr &expr, - vector> &expression_list) { - for (auto &child : expression_list) { - SimplifyChildExpression(expr, child); - } -} - -void StatementSimplifier::SimplifyExpressionList(vector> &expression_list, - bool is_optional) { - SimplifyList(expression_list, is_optional); - for (auto &child : expression_list) { - SimplifyExpression(child); - } -} - -void StatementSimplifier::SimplifyChildExpression(duckdb::unique_ptr &expr, - unique_ptr &child) { - if (!child) { - return; - } - SimplifyReplace(expr, child); - SimplifyExpression(child); -} - -void StatementSimplifier::SimplifyOptionalExpression(duckdb::unique_ptr &expr) { - if (!expr) { - return; - } - SimplifyOptional(expr); - SimplifyExpression(expr); -} - -void StatementSimplifier::SimplifyExpression(duckdb::unique_ptr &expr) { - if (!expr) { - return; - } - auto expr_class = expr->GetExpressionClass(); - switch (expr_class) { - case ExpressionClass::CONSTANT: - return; - default: - break; - } - duckdb::unique_ptr constant = make_uniq(Value()); - SimplifyReplace(expr, constant); - switch (expr_class) { - case ExpressionClass::CONJUNCTION: { - auto &conj = expr->Cast(); - SimplifyExpressionList(expr, conj.children); - break; - } - case ExpressionClass::FUNCTION: { - auto &func = expr->Cast(); - SimplifyExpressionList(expr, func.children); - SimplifyEnum(func.distinct, false); - SimplifyOptionalExpression(func.filter); - SimplifyOptional(func.order_bys); - if (func.order_bys) { - Simplify(*func.order_bys); - } - break; - } - case ExpressionClass::OPERATOR: { - auto &op = expr->Cast(); - SimplifyExpressionList(expr, op.children); - break; - } - case ExpressionClass::CASE: { - auto &op = expr->Cast(); - SimplifyChildExpression(expr, op.else_expr); - for (auto &case_check : op.case_checks) { - SimplifyChildExpression(expr, case_check.then_expr); - SimplifyChildExpression(expr, case_check.when_expr); - } - break; - } - case ExpressionClass::CAST: { - auto &cast = expr->Cast(); - SimplifyChildExpression(expr, cast.child); - break; - } - case ExpressionClass::COLLATE: { - auto &collate = expr->Cast(); - SimplifyChildExpression(expr, collate.child); - break; - } - case ExpressionClass::SUBQUERY: { - auto &subq = expr->Cast(); - // try to move this subquery fully into the outer query - if (!query_nodes.empty()) { - SimplifyReplace(query_nodes.back().get(), subq.subquery->node); - } - SimplifyChildExpression(expr, subq.child); - Simplify(subq.subquery->node); - break; - } - case ExpressionClass::COMPARISON: { - auto &comp = expr->Cast(); - SimplifyChildExpression(expr, comp.left); - SimplifyChildExpression(expr, comp.right); - break; - } - case ExpressionClass::STAR: { - auto &star = expr->Cast(); - SimplifyMap(star.replace_list); - SimplifySet(star.exclude_list); - for (auto &entry : star.replace_list) { - SimplifyChildExpression(expr, entry.second); - } - break; - } - case ExpressionClass::WINDOW: { - auto &window = expr->Cast(); - SimplifyExpressionList(expr, window.children); - SimplifyExpressionList(expr, window.partitions); - SimplifyList(window.orders); - SimplifyChildExpression(expr, window.filter_expr); - SimplifyChildExpression(expr, window.start_expr); - SimplifyChildExpression(expr, window.end_expr); - SimplifyChildExpression(expr, window.offset_expr); - SimplifyChildExpression(expr, window.default_expr); - SimplifyEnum(window.ignore_nulls, false); - SimplifyEnum(window.distinct, false); - SimplifyEnum(window.start, WindowBoundary::UNBOUNDED_PRECEDING); - SimplifyEnum(window.end, WindowBoundary::CURRENT_ROW_RANGE); - SimplifyEnum(window.exclude_clause, WindowExcludeMode::NO_OTHER); - break; - } - default: - break; - } -} - -void StatementSimplifier::Simplify(ResultModifier &modifier) { - switch (modifier.type) { - case ResultModifierType::ORDER_MODIFIER: - Simplify(modifier.Cast()); - break; - default: - break; - } -} - -void StatementSimplifier::Simplify(OrderModifier &modifier) { - for (auto &order : modifier.orders) { - SimplifyExpression(order.expression); - } - SimplifyList(modifier.orders); -} - -void StatementSimplifier::Simplify(SelectStatement &stmt) { - Simplify(stmt.node); - ParsedExpressionIterator::EnumerateQueryNodeChildren( - *stmt.node, [&](duckdb::unique_ptr &child) { SimplifyExpression(child); }); -} - -void StatementSimplifier::Simplify(InsertStatement &stmt) { - Simplify(stmt.cte_map); - Simplify(*stmt.select_statement); - SimplifyList(stmt.returning_list); -} - -void StatementSimplifier::Simplify(DeleteStatement &stmt) { - Simplify(stmt.cte_map); - SimplifyOptional(stmt.condition); - SimplifyExpression(stmt.condition); - SimplifyList(stmt.using_clauses); - SimplifyList(stmt.returning_list); -} - -void StatementSimplifier::Simplify(UpdateSetInfo &info) { - SimplifyOptional(info.condition); - SimplifyExpression(info.condition); - if (info.columns.size() > 1) { - for (idx_t i = 0; i < info.columns.size(); i++) { - auto col = std::move(info.columns[i]); - auto expr = std::move(info.expressions[i]); - info.columns.erase(info.columns.begin() + i); - info.expressions.erase(info.expressions.begin() + i); - Simplification(); - info.columns.insert(info.columns.begin() + i, std::move(col)); - info.expressions.insert(info.expressions.begin() + i, std::move(expr)); - } - } - for (auto &expr : info.expressions) { - SimplifyExpression(expr); - } -} - -void StatementSimplifier::Simplify(UpdateStatement &stmt) { - Simplify(stmt.cte_map); - SimplifyOptional(stmt.from_table); - D_ASSERT(stmt.set_info); - Simplify(*stmt.set_info); - SimplifyList(stmt.returning_list); -} - -void StatementSimplifier::Simplify(SQLStatement &stmt) { - switch (stmt.type) { - case StatementType::SELECT_STATEMENT: - Simplify(stmt.Cast()); - break; - case StatementType::INSERT_STATEMENT: - Simplify(stmt.Cast()); - break; - case StatementType::UPDATE_STATEMENT: - Simplify(stmt.Cast()); - break; - case StatementType::DELETE_STATEMENT: - Simplify(stmt.Cast()); - break; - default: - throw InvalidInputException("Expected a single SELECT, INSERT or UPDATE statement"); - } -} - -} // namespace duckdb diff --git a/extension/sqlsmith/third_party/CMakeLists.txt b/extension/sqlsmith/third_party/CMakeLists.txt deleted file mode 100644 index 2dcdc609415..00000000000 --- a/extension/sqlsmith/third_party/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_subdirectory(sqlsmith) - -set(SQLSMITH_OBJECT_FILES - ${SQLSMITH_OBJECT_FILES} - PARENT_SCOPE) diff --git a/extension/sqlsmith/third_party/sqlsmith/CMakeLists.txt b/extension/sqlsmith/third_party/sqlsmith/CMakeLists.txt deleted file mode 100644 index 4970d898b39..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -include_directories(include) - -add_library( - sqlsmith OBJECT - duckdb.cc - dump.cc - expr.cc - grammar.cc - impedance.cc - log.cc - prod.cc - random.cc - relmodel.cc - schema.cc - sqlsmith.cc) -set(SQLSMITH_OBJECT_FILES - ${SQLSMITH_OBJECT_FILES} $ - PARENT_SCOPE) - -disable_target_warnings(sqlsmith) diff --git a/extension/sqlsmith/third_party/sqlsmith/duckdb.cc b/extension/sqlsmith/third_party/sqlsmith/duckdb.cc deleted file mode 100644 index 03687d9c7ef..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/duckdb.cc +++ /dev/null @@ -1,177 +0,0 @@ -#include "duckdb.hh" - -#include -#include -#include -#include -#include -#include - -#include - -using namespace duckdb; -using namespace std; - -static regex e_syntax(".*syntax error at or near .*"); -static regex e_internal(".*INTERNAL.*"); - -sqlsmith_duckdb_connection::sqlsmith_duckdb_connection(duckdb::DatabaseInstance &database) { - // in-memory database - connection = make_uniq(database); -} - -void sqlsmith_duckdb_connection::q(const char *query) { - auto result = connection->Query(query); - if (result->HasError()) { - result->ThrowError(); - } -} - -schema_duckdb::schema_duckdb(duckdb::DatabaseInstance &database, bool no_catalog, bool verbose_output) - : sqlsmith_duckdb_connection(database) { - // generate empty TPC-H schema - if (verbose_output) - cerr << "Loading tables..."; - auto result = connection->Query("SELECT * FROM sqlite_master WHERE type IN ('table', 'view')"); - if (result->HasError()) { - result->ThrowError(); - } - for (size_t i = 0; i < result->RowCount(); i++) { - auto type = StringValue::Get(result->GetValue(0, i)); - auto name = StringValue::Get(result->GetValue(2, i)); - bool view = type == "view"; - table tab(name, "main", !view, !view); - tables.push_back(tab); - } - if (verbose_output) - cerr << "done." << endl; - - if (tables.size() == 0) { - throw std::runtime_error("No tables available in catalog!"); - } - if (verbose_output) - cerr << "Loading columns and constraints..."; - - for (auto t = tables.begin(); t != tables.end(); ++t) { - result = connection->Query("PRAGMA table_info('" + t->name + "')"); - if (result->HasError()) { - result->ThrowError(); - } - for (size_t i = 0; i < result->RowCount(); i++) { - auto name = StringValue::Get(result->GetValue(1, i)); - auto type = StringValue::Get(result->GetValue(2, i)); - column c(name, sqltype::get(type)); - t->columns().push_back(c); - } - } - - if (verbose_output) - cerr << "done." << endl; - - Connection con(database); - auto query_result = con.Query(R"( -SELECT function_name, parameter_types, return_type, function_type -FROM duckdb_functions() -WHERE NOT(has_side_effects) - AND (function_type='aggregate' or function_type='scalar'); - )"); - - for (auto &row : *query_result) { - auto function_name = row.GetValue(0); - auto parameter_types = row.GetValue(1); - auto return_type = row.GetValue(2); - auto function_type = row.GetValue(3); - auto ¶ms = ListValue::GetChildren(parameter_types); - if (function_type == "scalar") { - // check if this is an operator or a function - bool is_operator = false; - for (auto ch : function_name) { - if (!StringUtil::CharacterIsAlpha(ch) && !StringUtil::CharacterIsDigit(ch) && ch != '_') { - is_operator = true; - break; - } - } - if (is_operator) { - // operator - if (params.size() == 2) { - auto lparam = StringValue::Get(params[0]); - auto rparam = StringValue::Get(params[1]); - op o(function_name, sqltype::get(lparam), sqltype::get(rparam), sqltype::get(return_type)); - register_operator(o); - } - } else { - // function - routine proc("", "", sqltype::get(return_type), function_name); - for (auto ¶m : params) { - auto param_name = StringValue::Get(params[0]); - proc.argtypes.push_back(sqltype::get(param_name)); - } - register_routine(proc); - } - } else if (function_type == "aggregate") { - routine proc("", "", sqltype::get(return_type), function_name); - for (auto ¶m : params) { - auto param_name = StringValue::Get(params[0]); - proc.argtypes.push_back(sqltype::get(param_name)); - } - register_aggregate(proc); - } else { - throw std::runtime_error("unrecognized function type in sqlsmith"); - } - } - - booltype = sqltype::get("BOOLEAN"); - inttype = sqltype::get("INTEGER"); - - internaltype = sqltype::get("internal"); - arraytype = sqltype::get("ARRAY"); - - true_literal = "1"; - false_literal = "0"; - - auto &type_list = sqltype::get_types(); - for (auto &kv : type_list) { - types.push_back(kv.second); - } - - generate_indexes(verbose_output); -} - -dut_duckdb::dut_duckdb(duckdb::DatabaseInstance &database) : sqlsmith_duckdb_connection(database) { -} - -volatile bool is_active = false; -// timeout is 10ms * TIMEOUT_TICKS -#define TIMEOUT_TICKS 50 - -void sleep_thread(Connection *connection) { - for (size_t i = 0; i < TIMEOUT_TICKS && is_active; i++) { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - if (is_active) { - connection->Interrupt(); - } -} - -void dut_duckdb::test(const std::string &stmt) { - is_active = true; - thread interrupt_thread(sleep_thread, connection.get()); - auto result = connection->Query(stmt); - is_active = false; - interrupt_thread.join(); - - if (result->HasError()) { - auto error = result->GetError().c_str(); - if (regex_match(error, e_internal)) { - throw dut::broken(error); - } - try { - if (regex_match(error, e_syntax)) - throw dut::syntax(error); - else - throw dut::failure(error); - } catch (dut::failure &e) { - throw; - } - } -} diff --git a/extension/sqlsmith/third_party/sqlsmith/dump.cc b/extension/sqlsmith/third_party/sqlsmith/dump.cc deleted file mode 100644 index 0c43bd1e613..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/dump.cc +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include - -#include "dump.hh" -#include "util.hh" - -using namespace std; - -std::string graphml_dumper::id(struct prod *p) { - ostringstream os; - os << pretty_type(p) << "_" << p; - return os.str(); -} - -graphml_dumper::graphml_dumper(ostream &out) : o(out) { - o << "" << endl - << "" << endl; - - o << "" - << endl; - o << "" - << endl; - o << "" - << endl; - - o << "" << endl; -} - -void graphml_dumper::visit(struct prod *p) { - o << ""; - o << "" << p->retries << ""; - o << "" << pretty_type(p) << ""; - o << "" << p->scope << ""; - o << "" << endl; - if (p->pprod) { - o << "pprod) << "\"/>"; - } - o << endl; -} - -graphml_dumper::~graphml_dumper() { - o << "" << endl; -} - -void ast_logger::generated(prod &query) { - string filename(""); - filename += "sqlsmith-"; - filename += to_string(queries); - filename += ".xml"; - ofstream os(filename); - graphml_dumper visitor(os); - query.accept(&visitor); - queries++; -} diff --git a/extension/sqlsmith/third_party/sqlsmith/expr.cc b/extension/sqlsmith/third_party/sqlsmith/expr.cc deleted file mode 100644 index dc181ee20a8..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/expr.cc +++ /dev/null @@ -1,352 +0,0 @@ -#include -#include -#include -#include -#include - -#include "random.hh" -#include "relmodel.hh" -#include "grammar.hh" -#include "schema.hh" -#include "impedance.hh" -#include "expr.hh" - -using namespace std; -using impedance::matched; - -shared_ptr value_expr::factory(prod *p, sqltype *type_constraint) { - try { - if (1 == d20() && p->level < d6() && window_function::allowed(p)) - return std::make_shared(p, type_constraint); - else if (1 == d42() && p->level < d6()) - return std::make_shared(p, type_constraint); - else if (1 == d42() && p->level < d6()) - return std::make_shared(p, type_constraint); - else if (p->level < d6() && d6() == 1) - return std::make_shared(p, type_constraint); - else if (d12() == 1) - return std::make_shared(p, type_constraint); - else if (p->level < d6() && d9() == 1) - return std::make_shared(p, type_constraint); - else if (p->scope->refs.size() && d20() > 1) - return std::make_shared(p, type_constraint); - else - return std::make_shared(p, type_constraint); - } catch (runtime_error &e) { - } - p->retry(); - return factory(p, type_constraint); -} - -case_expr::case_expr(prod *p, sqltype *type_constraint) : value_expr(p) { - condition = bool_expr::factory(this); - true_expr = value_expr::factory(this, type_constraint); - false_expr = value_expr::factory(this, true_expr->type); - - if (false_expr->type != true_expr->type) { - /* Types are consistent but not identical. Try to find a more - concrete one for a better match. */ - if (true_expr->type->consistent(false_expr->type)) - true_expr = value_expr::factory(this, false_expr->type); - else - false_expr = value_expr::factory(this, true_expr->type); - } - type = true_expr->type; -} - -void case_expr::out(std::ostream &out) { - out << "case when " << *condition; - out << " then " << *true_expr; - out << " else " << *true_expr; - out << " end"; - indent(out); -} - -void case_expr::accept(prod_visitor *v) { - v->visit(this); - condition->accept(v); - true_expr->accept(v); - false_expr->accept(v); -} - -column_reference::column_reference(prod *p, sqltype *type_constraint) : value_expr(p) { - if (type_constraint) { - auto pairs = scope->refs_of_type(type_constraint); - auto picked = random_pick(pairs); - reference += picked.first->ident() + "." + picked.second.name; - type = picked.second.type; - assert(type_constraint->consistent(type)); - } else { - named_relation *r = random_pick(scope->refs); - - reference += r->ident() + "."; - column &c = random_pick(r->columns()); - type = c.type; - reference += c.name; - } -} - -shared_ptr bool_expr::factory(prod *p) { - try { - if (p->level > d100()) - return std::make_shared(p); - if (d6() < 4) - return std::make_shared(p); - else if (d6() < 4) - return std::make_shared(p); - else if (d6() < 4) - return std::make_shared(p); - else if (d6() < 4) - return std::make_shared(p); - else - return std::make_shared(p); - // return std::make_shared(q); - } catch (runtime_error &e) { - } - p->retry(); - return factory(p); -} - -exists_predicate::exists_predicate(prod *p) : bool_expr(p) { - subquery = std::make_shared(this, scope); -} - -void exists_predicate::accept(prod_visitor *v) { - v->visit(this); - subquery->accept(v); -} - -void exists_predicate::out(std::ostream &out) { - out << "EXISTS ("; - indent(out); - out << *subquery << ")"; -} - -distinct_pred::distinct_pred(prod *p) : bool_binop(p) { - lhs = std::make_shared(this); - rhs = std::make_shared(this, lhs->type); -} - -comparison_op::comparison_op(prod *p) : bool_binop(p) { - auto &idx = p->scope->schema->operators_returning_type; - - auto iters = idx.equal_range(scope->schema->booltype); - oper = random_pick<>(iters)->second; - - lhs = value_expr::factory(this, oper->left); - rhs = value_expr::factory(this, oper->right); - - if (oper->left == oper->right && lhs->type != rhs->type) { - - if (lhs->type->consistent(rhs->type)) - lhs = value_expr::factory(this, rhs->type); - else - rhs = value_expr::factory(this, lhs->type); - } -} - -coalesce::coalesce(prod *p, sqltype *type_constraint, const char *abbrev) : value_expr(p), abbrev_(abbrev) { - auto first_expr = value_expr::factory(this, type_constraint); - auto second_expr = value_expr::factory(this, first_expr->type); - - retry_limit = 20; - while (first_expr->type != second_expr->type) { - retry(); - if (first_expr->type->consistent(second_expr->type)) - first_expr = value_expr::factory(this, second_expr->type); - else - second_expr = value_expr::factory(this, first_expr->type); - } - type = second_expr->type; - - value_exprs.push_back(first_expr); - value_exprs.push_back(second_expr); -} - -void coalesce::out(std::ostream &out) { - out << "cast(" << abbrev_ << "("; - for (auto expr = value_exprs.begin(); expr != value_exprs.end(); expr++) { - out << **expr; - if (expr + 1 != value_exprs.end()) - out << ",", indent(out); - } - out << ")"; - out << " as " << type->name << ")"; -} - -const_expr::const_expr(prod *p, sqltype *type_constraint) : value_expr(p), expr("") { - type = type_constraint ? type_constraint : scope->schema->inttype; - - if (type == scope->schema->inttype) - expr = to_string(d100()); - else if (type == scope->schema->booltype) - expr += (d6() > 3) ? scope->schema->true_literal : scope->schema->false_literal; - else if (dynamic_cast(p) && (d6() > 3)) - expr += "default"; - else - expr += "cast(null as " + type->name + ")"; -} - -funcall::funcall(prod *p, sqltype *type_constraint, bool agg) : value_expr(p), is_aggregate(agg) { - if (type_constraint == scope->schema->internaltype) - fail("cannot call functions involving internal type"); - - auto &idx = agg ? p->scope->schema->aggregates_returning_type - : (4 < d6()) ? p->scope->schema->routines_returning_type - : p->scope->schema->parameterless_routines_returning_type; - -retry: - - if (!type_constraint) { - proc = random_pick(idx.begin(), idx.end())->second; - } else { - auto iters = idx.equal_range(type_constraint); - proc = random_pick<>(iters)->second; - if (proc && !type_constraint->consistent(proc->restype)) { - retry(); - goto retry; - } - } - - if (!proc) { - retry(); - goto retry; - } - - if (type_constraint) - type = type_constraint; - else - type = proc->restype; - - if (type == scope->schema->internaltype) { - retry(); - goto retry; - } - - for (auto type : proc->argtypes) - if (type == scope->schema->internaltype || type == scope->schema->arraytype) { - retry(); - goto retry; - } - - for (auto argtype : proc->argtypes) { - assert(argtype); - auto expr = value_expr::factory(this, argtype); - parms.push_back(expr); - } -} - -void funcall::out(std::ostream &out) { - out << proc->ident() << "("; - for (auto expr = parms.begin(); expr != parms.end(); expr++) { - indent(out); - out << "cast(" << **expr << " as " << (*expr)->type->name << ")"; - if (expr + 1 != parms.end()) - out << ","; - } - - if (is_aggregate && (parms.begin() == parms.end())) - out << "*"; - out << ")"; -} - -atomic_subselect::atomic_subselect(prod *p, sqltype *type_constraint) - : value_expr(p), offset((d6() == 6) ? d100() : d6()) { - match(); - if (d6() < 3) { - if (type_constraint) { - auto idx = scope->schema->aggregates_returning_type; - auto iters = idx.equal_range(type_constraint); - agg = random_pick<>(iters)->second; - } else { - agg = &random_pick<>(scope->schema->aggregates); - } - if (agg->argtypes.size() != 1) - agg = 0; - else - type_constraint = agg->argtypes[0]; - } else { - agg = 0; - } - - if (type_constraint) { - auto idx = scope->schema->tables_with_columns_of_type; - col = 0; - auto iters = idx.equal_range(type_constraint); - tab = random_pick<>(iters)->second; - - for (auto &cand : tab->columns()) { - if (type_constraint->consistent(cand.type)) { - col = &cand; - break; - } - } - assert(col); - } else { - tab = &random_pick<>(scope->schema->tables); - col = &random_pick<>(tab->columns()); - } - - type = agg ? agg->restype : col->type; -} - -void atomic_subselect::out(std::ostream &out) { - out << "(select "; - - if (agg) - out << agg->ident() << "(" << col->name << ")"; - else - out << col->name; - - out << " from " << tab->ident(); - - if (!agg) - out << " limit 1 offset " << offset; - - out << ")"; - indent(out); -} - -void window_function::out(std::ostream &out) { - indent(out); - out << *aggregate << " over (partition by "; - - for (auto ref = partition_by.begin(); ref != partition_by.end(); ref++) { - out << **ref; - if (ref + 1 != partition_by.end()) - out << ","; - } - - out << " order by "; - - for (auto ref = order_by.begin(); ref != order_by.end(); ref++) { - out << **ref; - if (ref + 1 != order_by.end()) - out << ","; - } - - out << ")"; -} - -window_function::window_function(prod *p, sqltype *type_constraint) : value_expr(p) { - match(); - aggregate = std::make_shared(this, type_constraint, true); - type = aggregate->type; - partition_by.push_back(std::make_shared(this)); - while (d6() > 4) - partition_by.push_back(std::make_shared(this)); - - order_by.push_back(std::make_shared(this)); - while (d6() > 4) - order_by.push_back(std::make_shared(this)); -} - -bool window_function::allowed(prod *p) { - if (dynamic_cast(p)) - return dynamic_cast(p->pprod) ? true : false; - if (dynamic_cast(p)) - return false; - if (dynamic_cast(p)) - return allowed(p->pprod); - return false; -} diff --git a/extension/sqlsmith/third_party/sqlsmith/grammar.cc b/extension/sqlsmith/third_party/sqlsmith/grammar.cc deleted file mode 100644 index 61f0ade6e21..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/grammar.cc +++ /dev/null @@ -1,618 +0,0 @@ -#include -#include -#include -#include -#include - -#include "random.hh" -#include "relmodel.hh" -#include "grammar.hh" -#include "schema.hh" -#include "impedance.hh" - -using namespace std; - -shared_ptr table_ref::factory(prod *p) { - try { - if (p->level < 3 + d6()) { - if (d6() > 3 && p->level < d6()) - return std::make_shared(p); - if (d6() > 3) - return std::make_shared(p); - } - if (d6() > 3) - return std::make_shared(p); - else - return std::make_shared(p); - } catch (runtime_error &e) { - p->retry(); - } - return factory(p); -} - -table_or_query_name::table_or_query_name(prod *p) : table_ref(p) { - t = random_pick(scope->tables); - refs.push_back(std::make_shared(scope->stmt_uid("ref"), t)); -} - -void table_or_query_name::out(std::ostream &out) { - out << t->ident() << " as " << refs[0]->ident(); -} - -target_table::target_table(prod *p, table *victim) : table_ref(p) { - while (!victim || victim->schema == "pg_catalog" || !victim->is_base_table || !victim->columns().size()) { - struct named_relation *pick = random_pick(scope->tables); - victim = dynamic_cast(pick); - retry(); - } - victim_ = victim; - refs.push_back(std::make_shared(scope->stmt_uid("target"), victim)); -} - -void target_table::out(std::ostream &out) { - out << victim_->ident() << " as " << refs[0]->ident(); -} - -table_sample::table_sample(prod *p) : table_ref(p) { - match(); - retry_limit = 1000; /* retries are cheap here */ - do { - auto pick = random_pick(scope->schema->base_tables); - t = dynamic_cast(pick); - retry(); - } while (!t || !t->is_base_table); - - refs.push_back(std::make_shared(scope->stmt_uid("sample"), t)); - percent = 0.1 * d100(); - method = (d6() > 2) ? "system" : "bernoulli"; -} - -void table_sample::out(std::ostream &out) { - out << t->ident() << " as " << refs[0]->ident() << " tablesample " << method << " (" << percent << ") "; -} - -table_subquery::table_subquery(prod *p, bool lateral) : table_ref(p), is_lateral(lateral) { - query = std::make_shared(this, scope, lateral); - string alias = scope->stmt_uid("subq"); - relation *aliased_rel = &query->select_list->derived_table; - refs.push_back(std::make_shared(alias, aliased_rel)); -} - -table_subquery::~table_subquery() { -} - -void table_subquery::accept(prod_visitor *v) { - query->accept(v); - v->visit(this); -} - -shared_ptr join_cond::factory(prod *p, table_ref &lhs, table_ref &rhs) { - try { - if (d6() < 6) - return std::make_shared(p, lhs, rhs); - else - return std::make_shared(p, lhs, rhs); - } catch (runtime_error &e) { - p->retry(); - } - return factory(p, lhs, rhs); -} - -simple_join_cond::simple_join_cond(prod *p, table_ref &lhs, table_ref &rhs) : join_cond(p, lhs, rhs) { -retry: - named_relation *left_rel = &*random_pick(lhs.refs); - - if (!left_rel->columns().size()) { - retry(); - goto retry; - } - - named_relation *right_rel = &*random_pick(rhs.refs); - - column &c1 = random_pick(left_rel->columns()); - - for (auto c2 : right_rel->columns()) { - if (c1.type == c2.type) { - condition += left_rel->ident() + "." + c1.name + " = " + right_rel->ident() + "." + c2.name + " "; - break; - } - } - if (condition == "") { - retry(); - goto retry; - } -} - -void simple_join_cond::out(std::ostream &out) { - out << condition; -} - -expr_join_cond::expr_join_cond(prod *p, table_ref &lhs, table_ref &rhs) : join_cond(p, lhs, rhs), joinscope(p->scope) { - scope = &joinscope; - for (auto ref : lhs.refs) - joinscope.refs.push_back(&*ref); - for (auto ref : rhs.refs) - joinscope.refs.push_back(&*ref); - search = bool_expr::factory(this); -} - -void expr_join_cond::out(std::ostream &out) { - out << *search; -} - -joined_table::joined_table(prod *p) : table_ref(p) { - lhs = table_ref::factory(this); - rhs = table_ref::factory(this); - - condition = join_cond::factory(this, *lhs, *rhs); - - if (d6() < 4) { - type = "inner"; - } else if (d6() < 4) { - type = "left"; - } else { - type = "right"; - } - - for (auto ref : lhs->refs) - refs.push_back(ref); - for (auto ref : rhs->refs) - refs.push_back(ref); -} - -void joined_table::out(std::ostream &out) { - out << *lhs; - indent(out); - out << type << " join " << *rhs; - indent(out); - out << "on (" << *condition << ")"; -} - -void table_subquery::out(std::ostream &out) { - if (is_lateral) - out << "lateral "; - out << "(" << *query << ") as " << refs[0]->ident(); -} - -void from_clause::out(std::ostream &out) { - if (!reflist.size()) - return; - out << "from "; - - for (auto r = reflist.begin(); r < reflist.end(); r++) { - indent(out); - out << **r; - if (r + 1 != reflist.end()) - out << ","; - } -} - -from_clause::from_clause(prod *p) : prod(p) { - reflist.push_back(table_ref::factory(this)); - for (auto r : reflist.back()->refs) - scope->refs.push_back(&*r); - - while (d6() > 5) { - // add a lateral subquery - if (!impedance::matched(typeid(lateral_subquery))) - break; - reflist.push_back(std::make_shared(this)); - for (auto r : reflist.back()->refs) - scope->refs.push_back(&*r); - } -} - -select_list::select_list(prod *p) : prod(p) { - do { - shared_ptr e = value_expr::factory(this); - value_exprs.push_back(e); - ostringstream name; - name << "c" << columns++; - sqltype *t = e->type; - assert(t); - derived_table.columns().push_back(column(name.str(), t)); - } while (d6() > 1); -} - -void select_list::out(std::ostream &out) { - int i = 0; - for (auto expr = value_exprs.begin(); expr != value_exprs.end(); expr++) { - indent(out); - out << **expr << " as " << derived_table.columns()[i].name; - i++; - if (expr + 1 != value_exprs.end()) - out << ", "; - } -} - -void query_spec::out(std::ostream &out) { - out << "select " << set_quantifier << " " << *select_list; - indent(out); - out << *from_clause; - indent(out); - out << "where "; - out << *search; - if (limit_clause.length()) { - indent(out); - out << limit_clause; - } -} - -struct for_update_verify : prod_visitor { - virtual void visit(prod *p) { - if (dynamic_cast(p)) - throw("window function"); - joined_table *join = dynamic_cast(p); - if (join && join->type != "inner") - throw("outer join"); - query_spec *subquery = dynamic_cast(p); - if (subquery) - subquery->set_quantifier = ""; - table_or_query_name *tab = dynamic_cast(p); - if (tab) { - table *actual_table = dynamic_cast
(tab->t); - if (actual_table && !actual_table->is_insertable) - throw("read only"); - if (actual_table->name.find("pg_")) - throw("catalog"); - } - table_sample *sample = dynamic_cast(p); - if (sample) { - table *actual_table = dynamic_cast
(sample->t); - if (actual_table && !actual_table->is_insertable) - throw("read only"); - if (actual_table->name.find("pg_")) - throw("catalog"); - } - }; -}; - -select_for_update::select_for_update(prod *p, struct scope *s, bool lateral) : query_spec(p, s, lateral) { - static const char *modes[] = { - "update", - "share", - "no key update", - "key share", - }; - - try { - for_update_verify v1; - this->accept(&v1); - - } catch (const char *reason) { - lockmode = 0; - return; - } - lockmode = modes[d6() % (sizeof(modes) / sizeof(*modes))]; - set_quantifier = ""; // disallow distinct -} - -void select_for_update::out(std::ostream &out) { - query_spec::out(out); - if (lockmode) { - indent(out); - out << " for " << lockmode; - } -} - -query_spec::query_spec(prod *p, struct scope *s, bool lateral) : prod(p), myscope(s) { - scope = &myscope; - scope->tables = s->tables; - - if (lateral) - scope->refs = s->refs; - - from_clause = std::make_shared(this); - select_list = std::make_shared(this); - - set_quantifier = (d100() == 1) ? "distinct" : ""; - - search = bool_expr::factory(this); - - if (d6() > 2) { - ostringstream cons; - cons << "limit " << d100() + d100(); - limit_clause = cons.str(); - } -} - -long prepare_stmt::seq; - -void modifying_stmt::pick_victim() { - do { - struct named_relation *pick = random_pick(scope->tables); - victim = dynamic_cast(pick); - retry(); - } while (!victim || victim->schema == "pg_catalog" || !victim->is_base_table || !victim->columns().size()); -} - -modifying_stmt::modifying_stmt(prod *p, struct scope *s, table *victim) : prod(p), myscope(s) { - scope = &myscope; - scope->tables = s->tables; - - if (!victim) - pick_victim(); -} - -delete_stmt::delete_stmt(prod *p, struct scope *s, table *v) : modifying_stmt(p, s, v) { - scope->refs.push_back(victim); - search = bool_expr::factory(this); -} - -delete_returning::delete_returning(prod *p, struct scope *s, table *victim) : delete_stmt(p, s, victim) { - match(); - select_list = std::make_shared(this); -} - -insert_stmt::insert_stmt(prod *p, struct scope *s, table *v) : modifying_stmt(p, s, v) { - match(); - - for (auto col : victim->columns()) { - auto expr = value_expr::factory(this, col.type); - assert(expr->type == col.type); - value_exprs.push_back(expr); - } -} - -void insert_stmt::out(std::ostream &out) { - out << "insert into " << victim->ident() << " "; - - if (!value_exprs.size()) { - out << "default values"; - return; - } - - out << "values ("; - - for (auto expr = value_exprs.begin(); expr != value_exprs.end(); expr++) { - indent(out); - out << **expr; - if (expr + 1 != value_exprs.end()) - out << ", "; - } - out << ")"; -} - -set_list::set_list(prod *p, table *target) : prod(p) { - do { - for (auto col : target->columns()) { - if (d6() < 4) - continue; - auto expr = value_expr::factory(this, col.type); - value_exprs.push_back(expr); - names.push_back(col.name); - } - } while (!names.size()); -} - -void set_list::out(std::ostream &out) { - assert(names.size()); - out << " set "; - for (size_t i = 0; i < names.size(); i++) { - indent(out); - out << names[i] << " = " << *value_exprs[i]; - if (i + 1 != names.size()) - out << ", "; - } -} - -update_stmt::update_stmt(prod *p, struct scope *s, table *v) : modifying_stmt(p, s, v) { - scope->refs.push_back(victim); - search = bool_expr::factory(this); - set_list = std::make_shared(this, victim); -} - -void update_stmt::out(std::ostream &out) { - out << "update " << victim->ident() << *set_list; -} - -update_returning::update_returning(prod *p, struct scope *s, table *v) : update_stmt(p, s, v) { - match(); - - select_list = std::make_shared(this); -} - -upsert_stmt::upsert_stmt(prod *p, struct scope *s, table *v) : insert_stmt(p, s, v) { - match(); - - if (!victim->constraints.size()) - fail("need table w/ constraint for upsert"); - - set_list = std::make_shared(this, victim); - search = bool_expr::factory(this); - constraint = random_pick(victim->constraints); -} - -shared_ptr statement_factory(struct scope *s) { - try { - s->new_stmt(); - if (d42() == 1) - return std::make_shared((struct prod *)0, s); - if (d42() == 1) - return std::make_shared((struct prod *)0, s); - else if (d42() == 1) - return std::make_shared((struct prod *)0, s); - else if (d42() == 1) { - return std::make_shared((struct prod *)0, s); - } else if (d42() == 1) - return std::make_shared((struct prod *)0, s); - else if (d6() > 4) - return std::make_shared((struct prod *)0, s); - else if (d6() > 5) - return std::make_shared((struct prod *)0, s); - return std::make_shared((struct prod *)0, s); - } catch (runtime_error &e) { - return statement_factory(s); - } -} - -void common_table_expression::accept(prod_visitor *v) { - v->visit(this); - for (auto q : with_queries) - q->accept(v); - query->accept(v); -} - -common_table_expression::common_table_expression(prod *parent, struct scope *s) : prod(parent), myscope(s) { - scope = &myscope; - do { - shared_ptr query = std::make_shared(this, s); - with_queries.push_back(query); - string alias = scope->stmt_uid("jennifer"); - relation *relation = &query->select_list->derived_table; - auto aliased_rel = std::make_shared(alias, relation); - refs.push_back(aliased_rel); - scope->tables.push_back(&*aliased_rel); - - } while (d6() > 2); - -retry: - do { - auto pick = random_pick(s->tables); - scope->tables.push_back(pick); - } while (d6() > 3); - try { - query = std::make_shared(this, scope); - } catch (runtime_error &e) { - retry(); - goto retry; - } -} - -void common_table_expression::out(std::ostream &out) { - out << "WITH "; - for (size_t i = 0; i < with_queries.size(); i++) { - indent(out); - out << refs[i]->ident() << " AS " - << "(" << *with_queries[i] << ")"; - if (i + 1 != with_queries.size()) - out << ", "; - indent(out); - } - out << *query; - indent(out); -} - -merge_stmt::merge_stmt(prod *p, struct scope *s, table *v) : modifying_stmt(p, s, v) { - match(); - target_table_ = std::make_shared(this, victim); - data_source = table_ref::factory(this); - // join_condition = join_cond::factory(this, *target_table_, - // *data_source); - join_condition = std::make_shared(this, *target_table_, *data_source); - - /* Put data_source into scope but not target_table. Visibility of - the latter varies depending on kind of when clause. */ - // for (auto r : data_source->refs) - // scope->refs.push_back(&*r); - - clauselist.push_back(when_clause::factory(this)); - while (d6() > 4) - clauselist.push_back(when_clause::factory(this)); -} - -void merge_stmt::out(std::ostream &out) { - out << "MERGE INTO " << *target_table_; - indent(out); - out << "USING " << *data_source; - indent(out); - out << "ON " << *join_condition; - indent(out); - for (auto p : clauselist) { - out << *p; - indent(out); - } -} - -void merge_stmt::accept(prod_visitor *v) { - v->visit(this); - target_table_->accept(v); - data_source->accept(v); - join_condition->accept(v); - for (auto p : clauselist) - p->accept(v); -} - -when_clause::when_clause(merge_stmt *p) : prod(p) { - condition = bool_expr::factory(this); - matched = d6() > 3; -} - -void when_clause::out(std::ostream &out) { - out << (matched ? "WHEN MATCHED " : "WHEN NOT MATCHED"); - indent(out); - out << "AND " << *condition; - indent(out); - out << " THEN "; - out << (matched ? "DELETE" : "DO NOTHING"); -} - -void when_clause::accept(prod_visitor *v) { - v->visit(this); - condition->accept(v); -} - -when_clause_update::when_clause_update(merge_stmt *p) : when_clause(p), myscope(p->scope) { - myscope.tables = scope->tables; - myscope.refs = scope->refs; - scope = &myscope; - scope->refs.push_back(&*(p->target_table_->refs[0])); - - set_list = std::make_shared(this, p->victim); -} - -void when_clause_update::out(std::ostream &out) { - out << "WHEN MATCHED AND " << *condition; - indent(out); - out << " THEN UPDATE " << *set_list; -} - -void when_clause_update::accept(prod_visitor *v) { - v->visit(this); - set_list->accept(v); -} - -when_clause_insert::when_clause_insert(struct merge_stmt *p) : when_clause(p) { - for (auto col : p->victim->columns()) { - auto expr = value_expr::factory(this, col.type); - assert(expr->type == col.type); - exprs.push_back(expr); - } -} - -void when_clause_insert::out(std::ostream &out) { - out << "WHEN NOT MATCHED AND " << *condition; - indent(out); - out << " THEN INSERT VALUES ( "; - - for (auto expr = exprs.begin(); expr != exprs.end(); expr++) { - out << **expr; - if (expr + 1 != exprs.end()) - out << ", "; - } - out << ")"; -} - -void when_clause_insert::accept(prod_visitor *v) { - v->visit(this); - for (auto p : exprs) - p->accept(v); -} - -shared_ptr when_clause::factory(struct merge_stmt *p) { - try { - switch (d6()) { - case 1: - case 2: - return std::make_shared(p); - case 3: - case 4: - return std::make_shared(p); - default: - return std::make_shared(p); - } - } catch (runtime_error &e) { - p->retry(); - } - return factory(p); -} diff --git a/extension/sqlsmith/third_party/sqlsmith/impedance.cc b/extension/sqlsmith/third_party/sqlsmith/impedance.cc deleted file mode 100644 index d8f121a729c..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/impedance.cc +++ /dev/null @@ -1,88 +0,0 @@ -#include "impedance.hh" -#include "log.hh" -#include - -using namespace std; - -static map occurances_in_failed_query; -static map occurances_in_ok_query; -static map retries; -static map limited; -static map failed; - -impedance_visitor::impedance_visitor(map &occured) : _occured(occured) { -} - -void impedance_visitor::visit(struct prod *p) { - found[typeid(*p).name()] = true; -} - -impedance_visitor::~impedance_visitor() { - for (auto pair : found) - _occured[pair.first]++; -} - -void impedance_feedback::executed(prod &query) { - impedance_visitor v(occurances_in_ok_query); - query.accept(&v); -} - -void impedance_feedback::error(prod &query, const dut::failure &e) { - (void)e; - impedance_visitor v(occurances_in_failed_query); - query.accept(&v); -} - -namespace impedance { - -bool matched(const char *name) { - if (100 > occurances_in_failed_query[name]) - return true; - double error_rate = - (double)occurances_in_failed_query[name] / (occurances_in_failed_query[name] + occurances_in_ok_query[name]); - if (error_rate > 0.99) - return false; - return true; -} - -void report() { - cerr << "impedance report: " << endl; - for (auto pair : occurances_in_failed_query) { - cerr << " " << pretty_type(pair.first) << ": " << pair.second << "/" << occurances_in_ok_query[pair.first] - << " (bad/ok)"; - if (!matched(pair.first)) - cerr << " -> BLACKLISTED"; - cerr << endl; - } -} - -void report(std::ostream &out) { - out << "{\"impedance\": [ " << endl; - - for (auto pair = occurances_in_failed_query.begin(); pair != occurances_in_failed_query.end(); ++pair) { - out << "{\"prod\": \"" << pretty_type(pair->first) << "\"," - << "\"bad\": " << pair->second << ", " - << "\"ok\": " << occurances_in_ok_query[pair->first] << ", " - << "\"limited\": " << limited[pair->first] << ", " - << "\"failed\": " << failed[pair->first] << ", " - << "\"retries\": " << retries[pair->first] << "} "; - - if (next(pair) != occurances_in_failed_query.end()) - out << "," << endl; - } - out << "]}" << endl; -} - -void retry(const char *p) { - retries[p]++; -} - -void limit(const char *p) { - limited[p]++; -} - -void fail(const char *p) { - failed[p]++; -} - -} // namespace impedance diff --git a/extension/sqlsmith/third_party/sqlsmith/include/duckdb.hh b/extension/sqlsmith/third_party/sqlsmith/include/duckdb.hh deleted file mode 100644 index b61b4e14f83..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/duckdb.hh +++ /dev/null @@ -1,33 +0,0 @@ -/// @file -/// @brief schema and dut classes for DuckDB - -#ifndef DUCKDB_HH -#define DUCKDB_HH - -#include "duckdb.hpp" - -#include "dut.hh" -#include "relmodel.hh" -#include "schema.hh" - -struct sqlsmith_duckdb_connection { - duckdb::unique_ptr database; - duckdb::unique_ptr connection; - char *zErrMsg = 0; - int rc; - void q(const char *query); - sqlsmith_duckdb_connection(duckdb::DatabaseInstance &database); -}; - -struct schema_duckdb : schema, sqlsmith_duckdb_connection { - schema_duckdb(duckdb::DatabaseInstance &database, bool no_catalog, bool verbose_output); - virtual std::string quote_name(const std::string &id) { - return id; - } -}; - -struct dut_duckdb : dut_base, sqlsmith_duckdb_connection { - virtual void test(const std::string &stmt); - dut_duckdb(duckdb::DatabaseInstance &database); -}; -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/dump.hh b/extension/sqlsmith/third_party/sqlsmith/include/dump.hh deleted file mode 100644 index c3d296ca3c1..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/dump.hh +++ /dev/null @@ -1,27 +0,0 @@ -/// @file -/// @brief Dump syntax trees as GraphML -#ifndef DUMP_HH -#define DUMP_HH - -#include -#include -#include - -#include "log.hh" -#include "prod.hh" - -struct graphml_dumper : prod_visitor { - std::ostream &o; - virtual void visit(struct prod *p); - graphml_dumper(std::ostream &out); - std::string id(prod *p); - std::string type(struct prod *p); - virtual ~graphml_dumper(); -}; - -struct ast_logger : logger { - int queries = 0; - virtual void generated(prod &query); -}; - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/dut.hh b/extension/sqlsmith/third_party/sqlsmith/include/dut.hh deleted file mode 100644 index fb49fb4e3bc..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/dut.hh +++ /dev/null @@ -1,47 +0,0 @@ -/// @file -/// @brief Base class for device under test - -#ifndef DUT_HH -#define DUT_HH -#include -#include - -#include "prod.hh" - -namespace dut { - -struct failure : public std::exception { - std::string errstr; - std::string sqlstate; - const char *what() const throw() { - return errstr.c_str(); - } - failure(const char *s, const char *sqlstate_ = "") throw() : errstr(), sqlstate() { - errstr = s; - sqlstate = sqlstate_; - }; -}; - -struct broken : failure { - broken(const char *s, const char *sqlstate_ = "") throw() : failure(s, sqlstate_) { - } -}; - -struct timeout : failure { - timeout(const char *s, const char *sqlstate_ = "") throw() : failure(s, sqlstate_) { - } -}; - -struct syntax : failure { - syntax(const char *s, const char *sqlstate_ = "") throw() : failure(s, sqlstate_) { - } -}; - -} // namespace dut - -struct dut_base { - std::string version; - virtual void test(const std::string &stmt) = 0; -}; - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/expr.hh b/extension/sqlsmith/third_party/sqlsmith/include/expr.hh deleted file mode 100644 index 5b72669231f..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/expr.hh +++ /dev/null @@ -1,208 +0,0 @@ -/// @file -/// @brief grammar: Value expression productions - -#ifndef EXPR_HH -#define EXPR_HH - -#include "prod.hh" -#include -#include "duckdb/common/vector.hpp" - -using duckdb::vector; -using std::shared_ptr; -using std::string; - -struct value_expr : prod { - sqltype *type; - virtual void out(std::ostream &out) = 0; - virtual ~value_expr() { - } - value_expr(prod *p) : prod(p) { - } - static shared_ptr factory(prod *p, sqltype *type_constraint = 0); -}; - -struct case_expr : value_expr { - shared_ptr condition; - shared_ptr true_expr; - shared_ptr false_expr; - case_expr(prod *p, sqltype *type_constraint = 0); - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v); -}; - -struct funcall : value_expr { - routine *proc; - bool is_aggregate; - vector> parms; - virtual void out(std::ostream &out); - virtual ~funcall() { - } - funcall(prod *p, sqltype *type_constraint = 0, bool agg = 0); - virtual void accept(prod_visitor *v) { - v->visit(this); - for (auto p : parms) - p->accept(v); - } -}; - -struct atomic_subselect : value_expr { - table *tab; - column *col; - int offset; - routine *agg; - atomic_subselect(prod *p, sqltype *type_constraint = 0); - virtual void out(std::ostream &out); -}; - -struct const_expr : value_expr { - std::string expr; - const_expr(prod *p, sqltype *type_constraint = 0); - virtual void out(std::ostream &out) { - out << expr; - } - virtual ~const_expr() { - } -}; - -struct column_reference : value_expr { - column_reference(prod *p, sqltype *type_constraint = 0); - virtual void out(std::ostream &out) { - out << reference; - } - std::string reference; - virtual ~column_reference() { - } -}; - -struct coalesce : value_expr { - const char *abbrev_; - vector> value_exprs; - virtual ~coalesce() {}; - coalesce(prod *p, sqltype *type_constraint = 0, const char *abbrev = "coalesce"); - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v) { - v->visit(this); - for (auto p : value_exprs) - p->accept(v); - } -}; - -struct nullif : coalesce { - virtual ~nullif() {}; - nullif(prod *p, sqltype *type_constraint = 0) : coalesce(p, type_constraint, "nullif") {}; -}; - -struct bool_expr : value_expr { - virtual ~bool_expr() { - } - bool_expr(prod *p) : value_expr(p) { - type = scope->schema->booltype; - } - static shared_ptr factory(prod *p); -}; - -struct truth_value : bool_expr { - virtual ~truth_value() { - } - const char *op; - virtual void out(std::ostream &out) { - out << op; - } - truth_value(prod *p) : bool_expr(p) { - op = ((d6() < 4) ? scope->schema->true_literal : scope->schema->false_literal); - } -}; - -struct null_predicate : bool_expr { - virtual ~null_predicate() { - } - const char *negate; - shared_ptr expr; - null_predicate(prod *p) : bool_expr(p) { - negate = ((d6() < 4) ? "not " : ""); - expr = value_expr::factory(this); - } - virtual void out(std::ostream &out) { - out << *expr << " is " << negate << "NULL"; - } - virtual void accept(prod_visitor *v) { - v->visit(this); - expr->accept(v); - } -}; - -struct exists_predicate : bool_expr { - shared_ptr subquery; - virtual ~exists_predicate() { - } - exists_predicate(prod *p); - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v); -}; - -struct bool_binop : bool_expr { - shared_ptr lhs, rhs; - bool_binop(prod *p) : bool_expr(p) { - } - virtual void out(std::ostream &out) = 0; - virtual void accept(prod_visitor *v) { - v->visit(this); - lhs->accept(v); - rhs->accept(v); - } -}; - -struct bool_term : bool_binop { - virtual ~bool_term() { - } - const char *op; - virtual void out(std::ostream &out) { - out << "(" << *lhs << ") "; - indent(out); - out << op << " (" << *rhs << ")"; - } - bool_term(prod *p) : bool_binop(p) { - op = ((d6() < 4) ? "or" : "and"); - lhs = bool_expr::factory(this); - rhs = bool_expr::factory(this); - } -}; - -struct distinct_pred : bool_binop { - distinct_pred(prod *p); - virtual ~distinct_pred() {}; - virtual void out(std::ostream &o) { - o << *lhs << " is distinct from " << *rhs; - } -}; - -struct comparison_op : bool_binop { - op *oper; - comparison_op(prod *p); - virtual ~comparison_op() {}; - virtual void out(std::ostream &o) { - o << *lhs << " " << oper->name << " " << *rhs; - } -}; - -struct window_function : value_expr { - virtual void out(std::ostream &out); - virtual ~window_function() { - } - window_function(prod *p, sqltype *type_constraint); - vector> partition_by; - vector> order_by; - shared_ptr aggregate; - static bool allowed(prod *pprod); - virtual void accept(prod_visitor *v) { - v->visit(this); - aggregate->accept(v); - for (auto p : partition_by) - p->accept(v); - for (auto p : order_by) - p->accept(v); - } -}; - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/grammar.hh b/extension/sqlsmith/third_party/sqlsmith/include/grammar.hh deleted file mode 100644 index 1eba224e149..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/grammar.hh +++ /dev/null @@ -1,367 +0,0 @@ -/// @file -/// @brief grammar: Top-level and unsorted grammar productions - -#ifndef GRAMMAR_HH -#define GRAMMAR_HH - -#include "relmodel.hh" -#include "schema.hh" -#include -#include - -#include "expr.hh" -#include "prod.hh" - -using std::shared_ptr; - -struct table_ref : prod { - vector> refs; - static shared_ptr factory(prod *p); - table_ref(prod *p) : prod(p) { - } - virtual ~table_ref() { - } -}; - -struct table_or_query_name : table_ref { - virtual void out(std::ostream &out); - table_or_query_name(prod *p); - virtual ~table_or_query_name() { - } - named_relation *t; -}; - -struct target_table : table_ref { - virtual void out(std::ostream &out); - target_table(prod *p, table *victim = 0); - virtual ~target_table() { - } - table *victim_; -}; - -struct table_sample : table_ref { - virtual void out(std::ostream &out); - table_sample(prod *p); - virtual ~table_sample() { - } - struct table *t; - -private: - string method; - double percent; -}; - -struct table_subquery : table_ref { - bool is_lateral; - virtual void out(std::ostream &out); - shared_ptr query; - table_subquery(prod *p, bool lateral = false); - virtual ~table_subquery(); - virtual void accept(prod_visitor *v); -}; - -struct lateral_subquery : table_subquery { - lateral_subquery(prod *p) : table_subquery(p, true) { - } -}; - -struct join_cond : prod { - static shared_ptr factory(prod *p, table_ref &lhs, table_ref &rhs); - join_cond(prod *p, table_ref &lhs, table_ref &rhs) : prod(p) { - (void)lhs; - (void)rhs; - } - virtual ~join_cond() { - } -}; - -struct simple_join_cond : join_cond { - std::string condition; - simple_join_cond(prod *p, table_ref &lhs, table_ref &rhs); - virtual ~simple_join_cond() { - } - virtual void out(std::ostream &out); -}; - -struct expr_join_cond : join_cond { - struct scope joinscope; - shared_ptr search; - expr_join_cond(prod *p, table_ref &lhs, table_ref &rhs); - virtual ~expr_join_cond() { - } - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v) { - search->accept(v); - v->visit(this); - } -}; - -struct joined_table : table_ref { - virtual void out(std::ostream &out); - joined_table(prod *p); - std::string type; - std::string alias; - virtual std::string ident() { - return alias; - } - shared_ptr lhs; - shared_ptr rhs; - shared_ptr condition; - virtual ~joined_table() { - } - virtual void accept(prod_visitor *v) { - lhs->accept(v); - rhs->accept(v); - condition->accept(v); - v->visit(this); - } -}; - -struct from_clause : prod { - vector> reflist; - virtual void out(std::ostream &out); - from_clause(prod *p); - virtual ~from_clause() { - } - virtual void accept(prod_visitor *v) { - v->visit(this); - for (auto p : reflist) - p->accept(v); - } -}; - -struct select_list : prod { - vector> value_exprs; - relation derived_table; - int columns = 0; - select_list(prod *p); - virtual void out(std::ostream &out); - virtual ~select_list() { - } - virtual void accept(prod_visitor *v) { - v->visit(this); - for (auto p : value_exprs) - p->accept(v); - } -}; - -struct query_spec : prod { - std::string set_quantifier; - shared_ptr from_clause; - shared_ptr select_list; - shared_ptr search; - std::string limit_clause; - struct scope myscope; - virtual void out(std::ostream &out); - query_spec(prod *p, struct scope *s, bool lateral = 0); - virtual ~query_spec() { - } - virtual void accept(prod_visitor *v) { - v->visit(this); - select_list->accept(v); - from_clause->accept(v); - search->accept(v); - } -}; - -struct select_for_update : query_spec { - const char *lockmode; - virtual void out(std::ostream &out); - select_for_update(prod *p, struct scope *s, bool lateral = 0); - virtual ~select_for_update() { - } -}; - -struct prepare_stmt : prod { - query_spec q; - static long seq; - long id; - virtual void out(std::ostream &out) { - out << "prepare prep" << id << " as " << q; - } - prepare_stmt(prod *p) : prod(p), q(p, scope) { - id = seq++; - } - virtual ~prepare_stmt() { - } - virtual void accept(prod_visitor *v) { - v->visit(this); - q.accept(v); - } -}; - -struct modifying_stmt : prod { - table *victim; - struct scope myscope; - modifying_stmt(prod *p, struct scope *s, struct table *victim = 0); - virtual ~modifying_stmt() { - } - // shared_ptr modifying_stmt::factory(prod *p, struct - // scope *s); - virtual void pick_victim(); -}; - -struct delete_stmt : modifying_stmt { - shared_ptr search; - delete_stmt(prod *p, struct scope *s, table *v); - virtual ~delete_stmt() { - } - virtual void out(std::ostream &out) { - out << "delete from " << victim->ident(); - indent(out); - out << "where " << std::endl << *search; - } - virtual void accept(prod_visitor *v) { - v->visit(this); - search->accept(v); - } -}; - -struct delete_returning : delete_stmt { - shared_ptr select_list; - delete_returning(prod *p, struct scope *s, table *victim = 0); - virtual void out(std::ostream &out) { - delete_stmt::out(out); - out << std::endl << "returning " << *select_list; - } - virtual void accept(prod_visitor *v) { - v->visit(this); - search->accept(v); - select_list->accept(v); - } -}; - -struct insert_stmt : modifying_stmt { - vector> value_exprs; - insert_stmt(prod *p, struct scope *s, table *victim = 0); - virtual ~insert_stmt() { - } - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v) { - v->visit(this); - for (auto p : value_exprs) - p->accept(v); - } -}; - -struct set_list : prod { - vector> value_exprs; - vector names; - set_list(prod *p, table *target); - virtual ~set_list() { - } - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v) { - v->visit(this); - for (auto p : value_exprs) - p->accept(v); - } -}; - -struct upsert_stmt : insert_stmt { - shared_ptr set_list; - string constraint; - shared_ptr search; - upsert_stmt(prod *p, struct scope *s, table *v = 0); - virtual void out(std::ostream &out) { - insert_stmt::out(out); - out << " on conflict on constraint " << constraint << " do update "; - out << *set_list << " where " << *search; - } - virtual void accept(prod_visitor *v) { - insert_stmt::accept(v); - set_list->accept(v); - search->accept(v); - } - virtual ~upsert_stmt() { - } -}; - -struct update_stmt : modifying_stmt { - shared_ptr search; - shared_ptr set_list; - update_stmt(prod *p, struct scope *s, table *victim = 0); - virtual ~update_stmt() { - } - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v) { - v->visit(this); - search->accept(v); - } -}; - -struct when_clause : prod { - bool matched; - shared_ptr condition; - // shared_ptr merge_action; - when_clause(struct merge_stmt *p); - virtual ~when_clause() { - } - static shared_ptr factory(struct merge_stmt *p); - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v); -}; - -struct when_clause_update : when_clause { - shared_ptr set_list; - struct scope myscope; - when_clause_update(struct merge_stmt *p); - virtual ~when_clause_update() { - } - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v); -}; - -struct when_clause_insert : when_clause { - vector> exprs; - when_clause_insert(struct merge_stmt *p); - virtual ~when_clause_insert() { - } - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v); -}; - -struct merge_stmt : modifying_stmt { - merge_stmt(prod *p, struct scope *s, table *victim = 0); - shared_ptr target_table_; - shared_ptr data_source; - shared_ptr join_condition; - vector> clauselist; - virtual ~merge_stmt() { - } - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v); -}; - -struct update_returning : update_stmt { - shared_ptr select_list; - update_returning(prod *p, struct scope *s, table *victim = 0); - virtual ~update_returning() { - } - virtual void out(std::ostream &out) { - update_stmt::out(out); - out << std::endl << "returning " << *select_list; - } - virtual void accept(prod_visitor *v) { - v->visit(this); - search->accept(v); - set_list->accept(v); - select_list->accept(v); - } -}; - -shared_ptr statement_factory(struct scope *s); - -struct common_table_expression : prod { - vector> with_queries; - shared_ptr query; - vector> refs; - struct scope myscope; - virtual void out(std::ostream &out); - virtual void accept(prod_visitor *v); - common_table_expression(prod *parent, struct scope *s); - virtual ~common_table_expression() { - } -}; - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/impedance.hh b/extension/sqlsmith/third_party/sqlsmith/include/impedance.hh deleted file mode 100644 index 8fc73b52b60..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/impedance.hh +++ /dev/null @@ -1,62 +0,0 @@ -/// @file -/// @brief feedback to the grammar about failed productions - -#ifndef IMPEDANCE_HH -#define IMPEDANCE_HH - -#include "dut.hh" -#include "log.hh" -#include "prod.hh" -#include "util.hh" -#include -#include - -struct impedance_visitor : prod_visitor { - std::map &_occured; - std::map found; - virtual void visit(struct prod *p); - impedance_visitor(std::map &occured); - virtual ~impedance_visitor(); -}; - -struct impedance_feedback : logger { - virtual void executed(prod &query); - virtual void error(prod &query, const dut::failure &e); - impedance_feedback() { - } -}; - -namespace impedance { -bool matched(const char *p); -inline bool matched(const std::type_info &id) { - return matched(id.name()); -} -inline bool matched(prod *p) { - return matched(typeid(*p)); -} -void retry(const char *p); -inline void retry(const std::type_info &id) { - return retry(id.name()); -} -inline void retry(prod *p) { - return retry(typeid(*p)); -} -void limit(const char *p); -inline void limit(const std::type_info &id) { - return limit(id.name()); -} -inline void limit(prod *p) { - return limit(typeid(*p)); -} -void fail(const char *p); -inline void fail(const std::type_info &id) { - return fail(id.name()); -} -inline void fail(prod *p) { - return fail(typeid(*p)); -} -void report(); -void report(std::ostream &out); -} // namespace impedance - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/log.hh b/extension/sqlsmith/third_party/sqlsmith/include/log.hh deleted file mode 100644 index 5412b690cab..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/log.hh +++ /dev/null @@ -1,55 +0,0 @@ -/// @file -/// @brief logging - -#ifndef LOG_HH -#define LOG_HH - -#include -#include -#include - -#include "dut.hh" -#include "prod.hh" - -/// logger base class -struct logger { - virtual void generated(prod &query) { - (void)query; - } - virtual void executed(prod &query) { - (void)query; - } - virtual void error(prod &query, const dut::failure &e) { - (void)query, (void)e; - } -}; - -/// logger to dump all generated queries -struct query_dumper : logger { - virtual void generated(prod &query) { - query.out(std::cout); - std::cout << ";" << std::endl; - } -}; - -/// logger for statistics collection -struct stats_collecting_logger : logger { - long queries = 0; - float sum_nodes = 0; - float sum_height = 0; - float sum_retries = 0; - virtual void generated(prod &query); -}; - -/// stderr logger -struct cerr_logger : stats_collecting_logger { - const int columns = 80; - std::map errors; - virtual void report(); - virtual void generated(prod &query); - virtual void executed(prod &query); - virtual void error(prod &query, const dut::failure &e); - void report(prod &p); -}; - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/prod.hh b/extension/sqlsmith/third_party/sqlsmith/include/prod.hh deleted file mode 100644 index 409d836d235..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/prod.hh +++ /dev/null @@ -1,59 +0,0 @@ -/// @file -/// @brief Base class for grammar productions - -#include -#include - -#ifndef PROD_HH -#define PROD_HH - -/// Base class for walking the AST -struct prod_visitor { - virtual void visit(struct prod *p) = 0; - virtual ~prod_visitor() { - } -}; - -/// Base class for AST nodes -struct prod { - /// Parent production that instanciated this one. May be NULL for - /// top-level productions. - struct prod *pprod; - /// Scope object to model column/table reference visibility. - struct scope *scope; - /// Level of this production in the AST. 0 for root node. - int level; - /// Number of retries in this production. Child productions are - /// generated speculatively and may fail. - long retries = 0; - /// Maximum number of retries allowed before reporting a failure to - /// the Parent prod. - long retry_limit = 100; - prod(prod *parent); - virtual ~prod() { - } - /// Newline and indent according to tree level. - virtual void indent(std::ostream &out); - /// Emit SQL for this production. - virtual void out(std::ostream &out) = 0; - /// Check with the impedance matching code whether this production - /// has been blacklisted and throw an exception. - virtual void match(); - /// Visitor pattern for walking the AST. Make sure you visit all - /// child production when deriving classes. - virtual void accept(prod_visitor *v) { - v->visit(this); - } - /// Report a "failed to generate" error. - virtual void fail(const char *reason); - /// Increase the retry count and throw an exception when retry_limit - /// is exceeded. - void retry(); -}; - -inline std::ostream &operator<<(std::ostream &s, prod &p) { - p.out(s); - return s; -} - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/random.hh b/extension/sqlsmith/third_party/sqlsmith/include/random.hh deleted file mode 100644 index e38a3543a91..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/random.hh +++ /dev/null @@ -1,45 +0,0 @@ -/// @file -/// @brief randomness - -#ifndef RANDOM_HH -#define RANDOM_HH - -#include -#include -#include -#include -#include "duckdb/common/vector.hpp" - -namespace smith { -extern std::mt19937_64 rng; -} - -using duckdb::vector; - -template -T &random_pick(vector &container) { - if (!container.size()) - throw std::runtime_error("No candidates available"); - - std::uniform_int_distribution pick(0, container.size() - 1); - return container[pick(smith::rng)]; -} - -template -I random_pick(I beg, I end) { - if (beg == end) - throw std::runtime_error("No candidates available"); - - std::uniform_int_distribution<> pick(0, std::distance(beg, end) - 1); - std::advance(beg, pick(smith::rng)); - return beg; -} - -template -I random_pick(std::pair iters) { - return random_pick(iters.first, iters.second); -} - -int d6(), d9(), d12(), d20(), d42(), d100(); - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/relmodel.hh b/extension/sqlsmith/third_party/sqlsmith/include/relmodel.hh deleted file mode 100644 index 5019ee881fa..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/relmodel.hh +++ /dev/null @@ -1,163 +0,0 @@ -/// @file -/// @brief supporting classes for the grammar - -#ifndef RELMODEL_HH -#define RELMODEL_HH -#include -#include -#include -#include -#include -#include "duckdb/common/vector.hpp" - -using duckdb::vector; -using std::make_pair; -using std::map; -using std::pair; -using std::shared_ptr; -using std::string; - -struct sqltype { - string name; - static map typemap; - static struct sqltype *get(string s); - static const map &get_types(); - sqltype(string n) : name(n) { - } - - /** This function is used to model postgres-style pseudotypes. - A generic type is consistent with a more concrete type. - E.G., anyarray->consistent(intarray) is true - while int4array->consistent(anyarray) is false - - There must not be cycles in the consistency graph, since the - grammar will use fixpoint iteration to resolve type conformance - situations in the direction of more concrete types */ - virtual bool consistent(struct sqltype *rvalue); -}; - -struct column { - string name; - sqltype *type; - column(string name) : name(name) { - } - column(string name, sqltype *t) : name(name), type(t) { - assert(t); - } -}; - -struct relation { - vector cols; - virtual ~relation() { - } - virtual vector &columns() { - return cols; - } -}; - -struct named_relation : relation { - string name; - virtual string ident() { - return name; - } - virtual ~named_relation() { - } - named_relation(string n) : name(n) { - } -}; - -struct aliased_relation : named_relation { - relation *rel; - virtual ~aliased_relation() { - } - aliased_relation(string n, relation *r) : named_relation(n), rel(r) { - } - virtual vector &columns() { - return rel->columns(); - } -}; - -struct table : named_relation { - string schema; - bool is_insertable; - bool is_base_table; - vector constraints; - table(string name, string schema, bool insertable, bool base_table) - : named_relation(name), schema(schema), is_insertable(insertable), is_base_table(base_table) { - } - virtual string ident() { - return schema + "." + name; - } - virtual ~table() {}; -}; - -struct scope { - struct scope *parent; - /// available to table_ref productions - vector tables; - /// available to column_ref productions - vector refs; - struct schema *schema; - /// Counters for prefixed stmt-unique identifiers - shared_ptr> stmt_seq; - scope(struct scope *parent = 0) : parent(parent) { - if (parent) { - schema = parent->schema; - tables = parent->tables; - refs = parent->refs; - stmt_seq = parent->stmt_seq; - } - } - vector> refs_of_type(sqltype *t) { - vector> result; - for (auto r : refs) - for (auto c : r->columns()) - if (t->consistent(c.type)) - result.push_back(make_pair(r, c)); - return result; - } - /** Generate unique identifier with prefix. */ - string stmt_uid(const char *prefix) { - string result(prefix); - result += "_"; - result += std::to_string((*stmt_seq)[result]++); - return result; - } - /** Reset unique identifier counters. */ - void new_stmt() { - stmt_seq = std::make_shared>(); - } -}; - -struct op { - string name; - sqltype *left; - sqltype *right; - sqltype *result; - op(string n, sqltype *l, sqltype *r, sqltype *res) : name(n), left(l), right(r), result(res) { - } - op() { - } -}; - -struct routine { - string specific_name; - string schema; - vector argtypes; - sqltype *restype; - string name; - routine(string schema, string specific_name, sqltype *data_type, string name) - : specific_name(specific_name), schema(schema), restype(data_type), name(name) { - assert(data_type); - } - virtual ~routine() { - } - virtual string ident() { - if (schema.size()) - return schema + "." + name; - else - return name; - } -}; - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/schema.hh b/extension/sqlsmith/third_party/sqlsmith/include/schema.hh deleted file mode 100644 index 3363d863e11..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/schema.hh +++ /dev/null @@ -1,84 +0,0 @@ -/// @file -/// @brief Base class providing schema information to grammar - -#ifndef SCHEMA_HH -#define SCHEMA_HH - -#include -#include -#include -#include - -#include "random.hh" -#include "relmodel.hh" - -using duckdb::vector; - -struct schema { - sqltype *booltype; - sqltype *inttype; - sqltype *internaltype; - sqltype *arraytype; - - vector types; - - vector
tables; - vector operators; - vector routines; - vector aggregates; - - typedef std::tuple typekey; - std::multimap index; - typedef std::multimap::iterator op_iterator; - - std::multimap routines_returning_type; - std::multimap aggregates_returning_type; - std::multimap parameterless_routines_returning_type; - std::multimap tables_with_columns_of_type; - std::multimap operators_returning_type; - std::multimap concrete_type; - vector
base_tables; - - string version; - int version_num; // comparable version number - - const char *true_literal = "true"; - const char *false_literal = "false"; - - virtual std::string quote_name(const std::string &id) = 0; - - void summary() { - std::cout << "Found " << tables.size() << " user table(s) in information schema." << std::endl; - } - void fill_scope(struct scope &s) { - for (auto &t : tables) - s.tables.push_back(&t); - s.schema = this; - } - virtual void register_operator(op &o) { - operators.push_back(o); - typekey t(o.left, o.right, o.result); - index.insert(std::pair(t, o)); - } - virtual void register_routine(routine &r) { - routines.push_back(r); - } - virtual void register_aggregate(routine &r) { - aggregates.push_back(r); - } - virtual op_iterator find_operator(sqltype *left, sqltype *right, sqltype *res) { - typekey t(left, right, res); - auto cons = index.equal_range(t); - if (cons.first == cons.second) - return index.end(); - else - return random_pick<>(cons.first, cons.second); - } - schema() { - } - virtual ~schema() { - } - void generate_indexes(bool verbose_output); -}; - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/sqlsmith.hh b/extension/sqlsmith/third_party/sqlsmith/include/sqlsmith.hh deleted file mode 100644 index 4bcf23bc16e..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/sqlsmith.hh +++ /dev/null @@ -1,27 +0,0 @@ -/// @file -/// @brief Base class providing schema information to grammar - -#ifndef SQLSMITH_HH -#define SQLSMITH_HH - -#include -#include "duckdb.hh" - -namespace duckdb_sqlsmith { - -struct SQLSmithOptions { - int32_t seed = -1; - uint64_t max_queries = 0; - bool exclude_catalog = false; - bool dump_all_queries = false; - bool dump_all_graphs = false; - bool verbose_output = false; - std::string complete_log; - std::string log; -}; - -int32_t run_sqlsmith(duckdb::DatabaseInstance &database, SQLSmithOptions options); - -} // namespace duckdb_sqlsmith - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/include/util.hh b/extension/sqlsmith/third_party/sqlsmith/include/util.hh deleted file mode 100644 index c237e9d4ce0..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/include/util.hh +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef UTIL_HH -#define UTIL_HH -#include -#include -#include - -using namespace std; - -/* TODO: The strings are implementation-defined. How do they look in - clang? */ - -inline std::string pretty_type(const char *raw) { - ostringstream os; - os << raw; - string s = os.str(); - while (s[0] <= '9') - s.erase(s.begin()); - return s; -} - -inline std::string pretty_type(struct prod *p) { - return pretty_type(typeid(*p).name()); -} - -#endif diff --git a/extension/sqlsmith/third_party/sqlsmith/log.cc b/extension/sqlsmith/third_party/sqlsmith/log.cc deleted file mode 100644 index 287e9d381fe..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/log.cc +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include - -#include - -#include - -#include "log.hh" -#include "schema.hh" -#include "impedance.hh" -#include "random.hh" - -#include "duckdb/common/vector.hpp" - -using namespace std; - -struct stats_visitor : prod_visitor { - int nodes = 0; - int maxlevel = 0; - long retries = 0; - map production_stats; - virtual void visit(struct prod *p) { - nodes++; - if (p->level > maxlevel) - maxlevel = p->level; - production_stats[typeid(*p).name()]++; - retries += p->retries; - } - void report() { - cerr << "production statistics" << endl; - duckdb::vector> report; - for (auto p : production_stats) - report.push_back(p); - stable_sort( - report.begin(), report.end(), - [](const pair &a, const pair &b) { return a.second > b.second; }); - for (auto p : report) { - cerr << p.second << "\t" << p.first << endl; - } - } -}; - -void stats_collecting_logger::generated(prod &query) { - queries++; - - stats_visitor v; - query.accept(&v); - - sum_nodes += v.nodes; - sum_height += v.maxlevel; - sum_retries += v.retries; -} - -void cerr_logger::report() { - cerr << endl << "queries: " << queries << endl; - // << " (" << 1000.0*query_count/gen_time.count() << " gen/s, " - // << 1000.0*query_count/query_time.count() << " exec/s)" << endl; - cerr << "AST stats (avg): height = " << sum_height / queries << " nodes = " << sum_nodes / queries << endl; - - duckdb::vector> report; - for (auto e : errors) { - report.push_back(e); - } - stable_sort(report.begin(), report.end(), - [](const pair &a, const pair &b) { return a.second > b.second; }); - long err_count = 0; - for (auto e : report) { - err_count += e.second; - cerr << e.second << "\t" << e.first.substr(0, 80) << endl; - } - cerr << "error rate: " << (float)err_count / (queries) << endl; - impedance::report(); -} - -void cerr_logger::generated(prod &p) { - stats_collecting_logger::generated(p); - if ((10 * columns - 1) == queries % (10 * columns)) - report(); -} - -void cerr_logger::executed(prod &query) { - (void)query; - if (columns - 1 == (queries % columns)) { - cerr << endl; - } - cerr << "."; -} - -void cerr_logger::error(prod &query, const dut::failure &e) { - (void)query; - istringstream err(e.what()); - string line; - - if (columns - 1 == (queries % columns)) { - cerr << endl; - } - getline(err, line); - errors[line]++; - if (dynamic_cast(&e)) - cerr << "t"; - else if (dynamic_cast(&e)) - cerr << "S"; - else if (dynamic_cast(&e)) - cerr << "C"; - else - cerr << "e"; -} diff --git a/extension/sqlsmith/third_party/sqlsmith/prod.cc b/extension/sqlsmith/third_party/sqlsmith/prod.cc deleted file mode 100644 index bd90c3af4aa..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/prod.cc +++ /dev/null @@ -1,41 +0,0 @@ -/// @file -/// @brief Base class for grammar productions -#include -#include -#include "prod.hh" -#include "impedance.hh" - -prod::prod(struct prod *parent) : pprod(parent) { - if (parent) { - level = parent->level + 1; - scope = parent->scope; - } else { - scope = 0; - level = 0; - } -} - -void prod::indent(std::ostream &out) { - out << std::endl; - for (int i = 0; i < level; i++) - out << " "; -} - -void prod::retry() { - impedance::retry(this); - if (retries++ <= retry_limit) - return; - - impedance::limit(this); - throw std::runtime_error(std::string("excessive retries in ") + typeid(*this).name()); -} - -void prod::match() { - if (!impedance::matched(this)) - throw std::runtime_error("impedance mismatch"); -} - -void prod::fail(const char *reason) { - impedance::fail(this); - throw std::runtime_error(reason); -} diff --git a/extension/sqlsmith/third_party/sqlsmith/random.cc b/extension/sqlsmith/third_party/sqlsmith/random.cc deleted file mode 100644 index 8952e36e1ab..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/random.cc +++ /dev/null @@ -1,35 +0,0 @@ -#include "random.hh" - -namespace smith { -std::mt19937_64 rng; -} - -int d6() { - static std::uniform_int_distribution<> pick(1, 6); - return pick(smith::rng); -} - -int d9() { - static std::uniform_int_distribution<> pick(1, 9); - return pick(smith::rng); -} - -int d12() { - static std::uniform_int_distribution<> pick(1, 12); - return pick(smith::rng); -} - -int d20() { - static std::uniform_int_distribution<> pick(1, 20); - return pick(smith::rng); -} - -int d42() { - static std::uniform_int_distribution<> pick(1, 42); - return pick(smith::rng); -} - -int d100() { - static std::uniform_int_distribution<> pick(1, 100); - return pick(smith::rng); -} diff --git a/extension/sqlsmith/third_party/sqlsmith/relmodel.cc b/extension/sqlsmith/third_party/sqlsmith/relmodel.cc deleted file mode 100644 index 3bb313f298e..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/relmodel.cc +++ /dev/null @@ -1,23 +0,0 @@ -#include "relmodel.hh" -#include -#include -#include - -map sqltype::typemap; - -sqltype *sqltype::get(string n) { - std::transform(n.begin(), n.end(), n.begin(), [](unsigned char c) { return std::tolower(c); }); - - if (typemap.count(n)) - return typemap[n]; - else - return typemap[n] = new sqltype(n); -} - -const map &sqltype::get_types() { - return typemap; -} - -bool sqltype::consistent(struct sqltype *rvalue) { - return this == rvalue; -} diff --git a/extension/sqlsmith/third_party/sqlsmith/schema.cc b/extension/sqlsmith/third_party/sqlsmith/schema.cc deleted file mode 100644 index 3164bb2ca64..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/schema.cc +++ /dev/null @@ -1,59 +0,0 @@ -#include "schema.hh" -#include "relmodel.hh" -#include - -using namespace std; - -void schema::generate_indexes(bool verbose_output) { - - if (verbose_output) - cerr << "Generating indexes..."; - - for (auto &type : types) { - assert(type); - for (auto &r : aggregates) { - if (type->consistent(r.restype)) - aggregates_returning_type.insert(pair(type, &r)); - } - - for (auto &r : routines) { - if (!type->consistent(r.restype)) - continue; - routines_returning_type.insert(pair(type, &r)); - if (!r.argtypes.size()) - parameterless_routines_returning_type.insert(pair(type, &r)); - } - - for (auto &t : tables) { - for (auto &c : t.columns()) { - if (type->consistent(c.type)) { - tables_with_columns_of_type.insert(pair(type, &t)); - break; - } - } - } - - for (auto &concrete : types) { - if (type->consistent(concrete)) - concrete_type.insert(pair(type, concrete)); - } - - for (auto &o : operators) { - if (type->consistent(o.result)) - operators_returning_type.insert(pair(type, &o)); - } - } - - for (auto &t : tables) { - if (t.is_base_table) - base_tables.push_back(&t); - } - - if (verbose_output) - cerr << "done." << endl; - - assert(booltype); - assert(inttype); - assert(internaltype); - assert(arraytype); -} diff --git a/extension/sqlsmith/third_party/sqlsmith/sqlsmith.cc b/extension/sqlsmith/third_party/sqlsmith/sqlsmith.cc deleted file mode 100644 index 90483ae0d5c..00000000000 --- a/extension/sqlsmith/third_party/sqlsmith/sqlsmith.cc +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include - -#include - -#include -#include - -#include -#include - -#include "grammar.hh" -#include "random.hh" -#include "relmodel.hh" -#include "schema.hh" - -#include "dump.hh" -#include "dut.hh" -#include "impedance.hh" -#include "log.hh" - -#include "duckdb.hh" -#include "sqlsmith.hh" - -#include "duckdb/common/vector.hpp" - -using namespace std; - -using namespace std::chrono; - -extern "C" { -#include -#include -#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__) -#include -#define GETPID ::getpid -#else -#include -#define GETPID (int)GetCurrentProcessId -#endif -} - -/* make the cerr logger globally accessible so we can emit one last - report on SIGINT */ -cerr_logger *global_cerr_logger; - -extern "C" void cerr_log_handler(int) { - if (global_cerr_logger) - global_cerr_logger->report(); - exit(1); -} - -namespace duckdb_sqlsmith { - -int32_t run_sqlsmith(duckdb::DatabaseInstance &database, SQLSmithOptions opt) { - // - // if (options.count("help")) { - // cerr << " --duckdb=URI SQLite database to send queries to" << endl - // << " --seed=int seed RNG with specified int instead " - // "of PID" - // << endl - // << " --dump-all-queries print queries as they are generated" << endl - // << " --dump-all-graphs dump generated ASTs" << endl - // << " --dry-run print queries instead of executing " - // "them" - // << endl - // << " --exclude-catalog don't generate queries using catalog " - // "relations" - // << endl - // << " --max-queries=long terminate after generating this many " - // "queries" - // << endl - // << " --rng-state=string deserialize dumped rng state" << endl - // << " --verbose emit progress output" << endl - // << " --version print version information and exit" << endl - // << " --help print available command line options " - // "and exit" - // << endl; - // return 0; - // } else if (options.count("version")) { - // return 0; - // } - - try { - shared_ptr schema; - schema = std::make_shared(database, opt.exclude_catalog, opt.verbose_output); - - scope scope; - long queries_generated = 0; - schema->fill_scope(scope); - - // if (options.count("rng-state")) { - // istringstream(options["rng-state"]) >> smith::rng; - // } else { - smith::rng.seed(opt.seed >= 0 ? opt.seed : GETPID()); - // } - - duckdb::vector> loggers; - - loggers.push_back(std::make_shared()); - - if (opt.verbose_output) { - auto l = std::make_shared(); - global_cerr_logger = &*l; - loggers.push_back(l); - signal(SIGINT, cerr_log_handler); - } - - if (opt.dump_all_graphs) - loggers.push_back(std::make_shared()); - - if (opt.dump_all_queries) - loggers.push_back(std::make_shared()); - - // if (options.count("dry-run")) { - // while (1) { - // shared_ptr gen = statement_factory(&scope); - // gen->out(cout); - // for (auto l : loggers) - // l->generated(*gen); - // cout << ";" << endl; - // queries_generated++; - // - // if (opt.max_queries >= 0 && (queries_generated >= opt.max_queries)) - // return 0; - // } - // } - - shared_ptr dut; - - dut = std::make_shared(database); - - if (opt.verbose_output) - cerr << "Running queries..." << endl; - - bool has_complete_log = !opt.complete_log.empty(); - bool has_log = !opt.log.empty(); - ofstream complete_log; - if (has_complete_log) { - complete_log.open(opt.complete_log); - } - while (1) /* Loop to recover connection loss */ - { - while (1) { /* Main loop */ - - if (opt.max_queries >= 0 && (++queries_generated > opt.max_queries)) { - if (global_cerr_logger) - global_cerr_logger->report(); - return 0; - } - - /* Invoke top-level production to generate AST */ - shared_ptr gen = statement_factory(&scope); - - for (auto l : loggers) - l->generated(*gen); - - /* Generate SQL from AST */ - ostringstream s; - gen->out(s); - - // write the query to the complete log that has all the - // queries - if (has_complete_log) { - complete_log << s.str() << ";" << endl; - complete_log.flush(); - } - - // write the last-executed query to a separate log file - if (has_log) { - ofstream out_file; - out_file.open(opt.log); - out_file << s.str() << ";" << endl; - out_file.close(); - } - - /* Try to execute it */ - try { - dut->test(s.str()); - for (auto l : loggers) - l->executed(*gen); - } catch (const dut::failure &e) { - for (auto l : loggers) - try { - l->error(*gen, e); - } catch (runtime_error &e) { - cerr << endl << "log failed: " << typeid(*l).name() << ": " << e.what() << endl; - } - if ((dynamic_cast(&e))) { - /* re-throw to outer loop */ - throw; - } - } - } - } - } catch (const exception &e) { - cerr << e.what() << endl; - exit(1); - } -} - -} // namespace duckdb_sqlsmith diff --git a/extension/tpcds/CMakeLists.txt b/extension/tpcds/CMakeLists.txt index 9e1925f8e70..6ec4cb8bd78 100644 --- a/extension/tpcds/CMakeLists.txt +++ b/extension/tpcds/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(TpcdsExtension) diff --git a/extension/tpcds/include/tpcds_extension.hpp b/extension/tpcds/include/tpcds_extension.hpp index 41d79adf128..7021050f4a7 100644 --- a/extension/tpcds/include/tpcds_extension.hpp +++ b/extension/tpcds/include/tpcds_extension.hpp @@ -17,6 +17,7 @@ class TpcdsExtension : public Extension { public: void Load(DuckDB &db) override; std::string Name() override; + std::string Version() const override; //! Gets the specified TPC-DS Query number as a string static std::string GetQuery(int query); diff --git a/extension/tpcds/tpcds_extension.cpp b/extension/tpcds/tpcds_extension.cpp index ab2df7a5164..c48fd968e71 100644 --- a/extension/tpcds/tpcds_extension.cpp +++ b/extension/tpcds/tpcds_extension.cpp @@ -45,7 +45,8 @@ static duckdb::unique_ptr DsdgenBind(ClientContext &context, Table } if (input.binder) { auto &catalog = Catalog::GetCatalog(context, result->catalog); - input.binder->properties.modified_databases.insert(catalog.GetName()); + auto &properties = input.binder->GetStatementProperties(); + properties.modified_databases.insert(catalog.GetName()); } return_types.emplace_back(LogicalType::BOOLEAN); names.emplace_back("Success"); @@ -192,6 +193,14 @@ std::string TpcdsExtension::Name() { return "tpcds"; } +std::string TpcdsExtension::Version() const { +#ifdef EXT_VERSION_TPCDS + return EXT_VERSION_TPCDS; +#else + return ""; +#endif +} + } // namespace duckdb extern "C" { diff --git a/extension/tpch/CMakeLists.txt b/extension/tpch/CMakeLists.txt index 65eddd2c289..46dcb12ec84 100644 --- a/extension/tpch/CMakeLists.txt +++ b/extension/tpch/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(TpchExtension) diff --git a/extension/tpch/dbgen/bm_utils.cpp b/extension/tpch/dbgen/bm_utils.cpp index 80c1575a3df..b6fbf205cef 100644 --- a/extension/tpch/dbgen/bm_utils.cpp +++ b/extension/tpch/dbgen/bm_utils.cpp @@ -89,7 +89,7 @@ static char alpha_num[65] = "0123456789abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMN char *getenv PROTO((const char *name)); #endif void usage(); -void permute_dist(distribution *d, seed_t *seed); +void permute_dist(distribution *d, seed_t *seed, DBGenContext *ctx); /* * tpch_env_config: look for a environmental variable setting and return its @@ -302,7 +302,6 @@ void read_dist(const char *path, const char *name, distribution *target) { fprintf(stderr, "Read error on dist '%s'\n", name); exit(1); } - target->permute = (long *)NULL; return; } @@ -310,16 +309,16 @@ void read_dist(const char *path, const char *name, distribution *target) { * agg_str(set, count) build an aggregated string from count unique * selections taken from set */ -void agg_str(distribution *set, long count, seed_t *seed, char *dest) { +void agg_str(distribution *set, long count, seed_t *seed, char *dest, DBGenContext *ctx) { distribution *d; int i; d = set; *dest = '\0'; - permute_dist(d, seed); + permute_dist(d, seed, ctx); for (i = 0; i < count; i++) { - strcat(dest, DIST_MEMBER(set, DIST_PERMUTE(d, i))); + strcat(dest, DIST_MEMBER(set, ctx->permute[i])); strcat(dest, " "); } *(dest + (int)strlen(dest) - 1) = '\0'; diff --git a/extension/tpch/dbgen/build.cpp b/extension/tpch/dbgen/build.cpp index 8d03b0f362a..808f6c8e3d1 100644 --- a/extension/tpch/dbgen/build.cpp +++ b/extension/tpch/dbgen/build.cpp @@ -10,6 +10,7 @@ */ #include #include +#include #ifndef VMS #include #endif @@ -20,6 +21,7 @@ #include "dbgen/dsstypes.h" #include + #include "dbgen/rng64.h" #define LEAP_ADJ(yr, mnth) ((LEAP(yr) && (mnth) >= 2) ? 1 : 0) @@ -64,13 +66,12 @@ static void gen_phone(DSS_HUGE ind, char *target, seed_t *seed) { long mk_cust(DSS_HUGE n_cust, customer_t *c, DBGenContext *ctx) { DSS_HUGE i; - static int bInit = 0; + static std::once_flag bInit; static char szFormat[100]; - if (!bInit) { + std::call_once (bInit, [&](){ snprintf(szFormat, sizeof(szFormat), C_NAME_FMT, 9, &HUGE_FORMAT[1]); - bInit = 1; - } + }); c->custkey = n_cust; snprintf(c->name, sizeof(c->name), szFormat, C_NAME_TAG, n_cust); V_STR(C_ADDR_LEN, &ctx->Seed[C_ADDR_SD], c->address); @@ -117,15 +118,13 @@ long mk_order(DSS_HUGE index, order_t *o, DBGenContext *ctx, long upd_num) { char tmp_str[2]; char **mk_ascdate PROTO((void)); int delta = 1; - static int bInit = 0; + static std::once_flag bInit; static char szFormat[100]; - if (!bInit) { + std::call_once (bInit, [&](){ snprintf(szFormat, sizeof(szFormat), O_CLRK_FMT, 9, &HUGE_FORMAT[1]); - bInit = 1; - } - if (asc_date == NULL) asc_date = mk_ascdate(); + }); mk_sparse(index, &o->okey, (upd_num == 0) ? 0 : 1 + upd_num / (10000 / UPD_PCT)); if (ctx->scale_factor >= 30000) RANDOM64(o->custkey, O_CKEY_MIN, O_CKEY_MAX, &ctx->Seed[O_CKEY_SD]); @@ -216,17 +215,17 @@ long mk_part(DSS_HUGE index, part_t *p, DBGenContext *ctx) { DSS_HUGE temp; long snum; DSS_HUGE brnd; - static int bInit = 0; + static std::once_flag bInit; static char szFormat[100]; static char szBrandFormat[100]; - if (!bInit) { + + std::call_once (bInit, [&](){ snprintf(szFormat, sizeof(szFormat), P_MFG_FMT, 1, &HUGE_FORMAT[1]); snprintf(szBrandFormat, sizeof(szBrandFormat), P_BRND_FMT, 2, &HUGE_FORMAT[1]); - bInit = 1; - } + }); p->partkey = index; - agg_str(&colors, (long)P_NAME_SCL, &ctx->Seed[P_NAME_SD], p->name); + agg_str(&colors, (long)P_NAME_SCL, &ctx->Seed[P_NAME_SD], p->name, ctx); RANDOM(temp, P_MFG_MIN, P_MFG_MAX, &ctx->Seed[P_MFG_SD]); snprintf(p->mfgr, sizeof(p->mfgr), szFormat, P_MFG_TAG, temp); RANDOM(brnd, P_BRND_MIN, P_BRND_MAX, &ctx->Seed[P_BRND_SD]); @@ -252,13 +251,12 @@ long mk_part(DSS_HUGE index, part_t *p, DBGenContext *ctx) { long mk_supp(DSS_HUGE index, supplier_t *s, DBGenContext *ctx) { DSS_HUGE i, bad_press, noise, offset, type; - static int bInit = 0; + static std::once_flag bInit; static char szFormat[100]; - if (!bInit) { + std::call_once (bInit, [&](){ snprintf(szFormat, sizeof(szFormat), S_NAME_FMT, 9, &HUGE_FORMAT[1]); - bInit = 1; - } + }); s->suppkey = index; snprintf(s->name, sizeof(s->name), szFormat, S_NAME_TAG, index); V_STR(S_ADDR_LEN, &ctx->Seed[S_ADDR_SD], s->address); diff --git a/extension/tpch/dbgen/dbgen.cpp b/extension/tpch/dbgen/dbgen.cpp index c6e938068db..09a1aaac71e 100644 --- a/extension/tpch/dbgen/dbgen.cpp +++ b/extension/tpch/dbgen/dbgen.cpp @@ -11,6 +11,9 @@ #include "duckdb/catalog/catalog.hpp" #include "duckdb/main/appender.hpp" #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" +#ifndef DUCKDB_NO_THREADS +#include "duckdb/common/thread.hpp" +#endif #endif #define DECLARER /* EXTERN references get defined here */ @@ -473,16 +476,97 @@ void skip(int table, int children, DSS_HUGE step, DBGenContext &dbgen_ctx) { } } +struct TPCHDBgenParameters { + TPCHDBgenParameters(ClientContext &context, Catalog &catalog, const string &schema, const string &suffix) { + tables.resize(REGION + 1); + for (size_t i = PART; i <= REGION; i++) { + auto tname = get_table_name(i); + if (!tname.empty()) { + string full_tname = string(tname) + string(suffix); + auto &tbl_catalog = catalog.GetEntry(context, schema, full_tname); + tables[i] = &tbl_catalog; + } + } + + } + + vector> tables; +}; + +class TPCHDataAppender { +public: + TPCHDataAppender(ClientContext &context, TPCHDBgenParameters ¶meters, DBGenContext base_context, idx_t flush_count) : + context(context), parameters(parameters) { + dbgen_ctx = base_context; + append_info = duckdb::unique_ptr(new tpch_append_information[REGION + 1]); + memset(append_info.get(), 0, sizeof(tpch_append_information) * REGION + 1); + for (size_t i = PART; i <= REGION; i++) { + if (parameters.tables[i]) { + auto &tbl_catalog = *parameters.tables[i]; + append_info[i].appender = make_uniq(context, tbl_catalog, flush_count); + } + } + } + + void GenerateTableData(int table_index, idx_t row_count, idx_t offset) { + gen_tbl(context, table_index, static_cast(row_count), append_info.get(), &dbgen_ctx, offset); + } + + void AppendData(int children, int current_step) { + DSS_HUGE i; + DSS_HUGE rowcnt = 0; + for (i = PART; i <= REGION; i++) { + if (table & (1 << i)) { + if (i < NATION) { + rowcnt = dbgen_ctx.tdefs[i].base * dbgen_ctx.scale_factor; + } else { + rowcnt = dbgen_ctx.tdefs[i].base; + } + if (children > 1 && current_step != -1) { + size_t part_size = std::ceil((double)rowcnt / (double)children); + auto part_offset = part_size * current_step; + auto part_end = part_offset + part_size; + rowcnt = part_end > rowcnt ? rowcnt - part_offset : part_size; + skip(i, children, part_offset, dbgen_ctx); + if (rowcnt > 0) { + // generate part of the table + GenerateTableData((int) i, rowcnt, part_offset); + } + } else { + // generate full table + GenerateTableData((int) i, rowcnt, 0); + } + } + } + } + + void Flush() { + // flush any incomplete chunks + for (idx_t i = PART; i <= REGION; i++) { + if (append_info[i].appender) { + append_info[i].appender->Flush(); + append_info[i].appender.reset(); + } + } + } + +private: + ClientContext &context; + TPCHDBgenParameters ¶meters; + unique_ptr append_info; + DBGenContext dbgen_ctx; +}; + +static void ParallelTPCHAppend(TPCHDataAppender *appender, int children, int current_step) { + appender->AppendData(children, current_step); +} + void DBGenWrapper::LoadTPCHData(ClientContext &context, double flt_scale, string catalog_name, string schema, - string suffix, int children_p, int current_step) { + string suffix, int children, int current_step) { if (flt_scale == 0) { return; } - // generate the actual data - DSS_HUGE rowcnt = 0; - DSS_HUGE extra; - DSS_HUGE i; // all tables table = (1 << CUST) | (1 << SUPP) | (1 << NATION) | (1 << REGION) | (1 << PART_PSUPP) | (1 << ORDER_LINE); force = 0; @@ -495,9 +579,10 @@ void DBGenWrapper::LoadTPCHData(ClientContext &context, double flt_scale, string set_seeds = 0; updates = 0; - DBGenContext dbgen_ctx; + d_path = NULL; - tdef *tdefs = dbgen_ctx.tdefs; + DBGenContext base_context; + tdef *tdefs = base_context.tdefs; tdefs[PART].base = 200000; tdefs[PSUPP].base = 200000; tdefs[SUPP].base = 10000; @@ -509,18 +594,11 @@ void DBGenWrapper::LoadTPCHData(ClientContext &context, double flt_scale, string tdefs[NATION].base = NATIONS_MAX; tdefs[REGION].base = NATIONS_MAX; - children = children_p; - d_path = NULL; - - if (current_step >= children) { - return; - } - if (flt_scale < MIN_SCALE) { int i; int int_scale; - dbgen_ctx.scale_factor = 1; + base_context.scale_factor = 1; int_scale = (int)(1000 * flt_scale); for (i = PART; i < REGION; i++) { tdefs[i].base = (DSS_HUGE)(int_scale * tdefs[i].base) / 1000; @@ -529,58 +607,76 @@ void DBGenWrapper::LoadTPCHData(ClientContext &context, double flt_scale, string } } } else { - dbgen_ctx.scale_factor = (long)flt_scale; + base_context.scale_factor = (long)flt_scale; } - load_dists(10 * 1024 * 1024, &dbgen_ctx); // 10MiB + if (current_step >= children) { + return; + } + + load_dists(10 * 1024 * 1024, &base_context); // 10MiB /* have to do this after init */ tdefs[NATION].base = nations.count; tdefs[REGION].base = regions.count; auto &catalog = Catalog::GetCatalog(context, catalog_name); - auto append_info = duckdb::unique_ptr(new tpch_append_information[REGION + 1]); - memset(append_info.get(), 0, sizeof(tpch_append_information) * REGION + 1); - for (size_t i = PART; i <= REGION; i++) { - auto tname = get_table_name(i); - if (!tname.empty()) { - string full_tname = string(tname) + string(suffix); - auto &tbl_catalog = catalog.GetEntry(context, schema, full_tname); - append_info[i].appender = make_uniq(context, tbl_catalog); + TPCHDBgenParameters parameters(context, catalog, schema, suffix); +#ifndef DUCKDB_NO_THREADS + bool explicit_partial_generation = children > 1 && current_step != -1; + auto thread_count = TaskScheduler::GetScheduler(context).NumberOfThreads(); + if (explicit_partial_generation || thread_count <= 1) { +#endif + // if we are doing explicit partial generation the parallelism is managed outside of dbgen + // only generate the chunk we are interested in + TPCHDataAppender appender(context, parameters, base_context, BaseAppender::DEFAULT_FLUSH_COUNT); + appender.AppendData(children, current_step); + appender.Flush(); +#ifndef DUCKDB_NO_THREADS + } else { + // we split into 20 children per scale factor by default + static constexpr idx_t CHILDREN_PER_SCALE_FACTOR = 20; + idx_t child_count; + if (flt_scale < 1) { + child_count = 1; + } else { + child_count = MinValue(static_cast(CHILDREN_PER_SCALE_FACTOR * flt_scale), MAX_CHILDREN); } - } - - for (i = PART; i <= REGION; i++) { - if (table & (1 << i)) { - if (i < NATION) { - rowcnt = tdefs[i].base * dbgen_ctx.scale_factor; - } else { - rowcnt = tdefs[i].base; + idx_t step = 0; + vector finished_appenders; + while(step < child_count) { + // launch N threads + vector new_appenders; + vector threads; + idx_t launched_step = step; + // initialize the appenders for each thread + // note we prevent the threads themselves from flushing the appenders by specifying a very high flush count here + for(idx_t thr_idx = 0; thr_idx < thread_count && launched_step < child_count; thr_idx++, launched_step++) { + new_appenders.emplace_back(context, parameters, base_context, NumericLimits::Maximum()); } - if (children > 1 && current_step != -1) { - size_t part_size = std::ceil((double)rowcnt / (double)children); - auto part_offset = part_size * current_step; - auto part_end = part_offset + part_size; - rowcnt = part_end > rowcnt ? rowcnt - part_offset : part_size; - skip(i, children, part_offset, dbgen_ctx); - if (rowcnt > 0) { - // generate part of the table - gen_tbl(context, (int)i, rowcnt, append_info.get(), &dbgen_ctx, part_offset); - } - } else { - // generate full table - gen_tbl(context, (int)i, rowcnt, append_info.get(), &dbgen_ctx); + // launch the threads + for(idx_t thr_idx = 0; thr_idx < new_appenders.size(); thr_idx++) { + threads.emplace_back(ParallelTPCHAppend, &new_appenders[thr_idx], child_count, step); + step++; + } + // flush the previous batch of appenders while waiting (if any are there) + // now flush the appenders in-order + for(auto &appender : finished_appenders) { + appender.Flush(); + } + finished_appenders.clear(); + // wait for all threads to finish + for(auto &thread : threads) { + thread.join(); } + finished_appenders = std::move(new_appenders); } - } - // flush any incomplete chunks - for (size_t i = PART; i <= REGION; i++) { - if (append_info[i].appender) { - append_info[i].appender->Flush(); - append_info[i].appender.reset(); + // flush the final batch of appenders + for(auto &appender : finished_appenders) { + appender.Flush(); } } - +#endif cleanup_dists(); } diff --git a/extension/tpch/dbgen/include/dbgen/dss.h b/extension/tpch/dbgen/include/dbgen/dss.h index 34d7025f944..e26b6361be6 100644 --- a/extension/tpch/dbgen/include/dbgen/dss.h +++ b/extension/tpch/dbgen/include/dbgen/dss.h @@ -109,14 +109,12 @@ typedef struct { int count; int max; set_member *list; - long *permute; } distribution; /* * some handy access functions */ #define DIST_SIZE(d) d->count #define DIST_MEMBER(d, i) ((set_member *)((d)->list + i))->text -#define DIST_PERMUTE(d, i) (d->permute[i]) typedef struct { const char *name; @@ -152,7 +150,7 @@ long unjulian PROTO((long date)); long dssncasecmp PROTO((const char *s1, const char *s2, int n)); long dsscasecmp PROTO((const char *s1, const char *s2)); int pick_str PROTO((distribution * s, seed_t *seed, char *target)); -void agg_str PROTO((distribution * set, long count, seed_t *seed, char *dest)); +void agg_str PROTO((distribution * set, long count, seed_t *seed, char *dest, DBGenContext *ctx)); void read_dist PROTO((const char *path, const char *name, distribution *target)); void embed_str PROTO((distribution * d, int min, int max, int stream, char *dest)); #ifndef STDLIB_HAS_GETOPT @@ -216,8 +214,6 @@ EXTERN long verbose; EXTERN long force; EXTERN long updates; EXTERN long table; -EXTERN long children; -EXTERN int step; EXTERN int set_seeds; EXTERN char *d_path; @@ -483,6 +479,13 @@ int dbg_print(int dt, FILE *tgt, void *data, int len, int eol); #define BBB_OFFSET_SD 47 struct DBGenContext { + ~DBGenContext() { + if (permute) { + free(permute); + permute = NULL; + } + } + seed_t Seed[MAX_STREAM + 1] = { {PART, 1, 0, 1}, /* P_MFG_SD 0 */ {PART, 46831694, 0, 1}, /* P_BRND_SD 1 */ @@ -550,6 +553,7 @@ struct DBGenContext { }; long scale_factor = 1; + long *permute = NULL; }; #endif /* DSS_H */ diff --git a/extension/tpch/dbgen/permute.cpp b/extension/tpch/dbgen/permute.cpp index 6ef80d1afd6..396247bdb52 100644 --- a/extension/tpch/dbgen/permute.cpp +++ b/extension/tpch/dbgen/permute.cpp @@ -14,10 +14,11 @@ #include "dbgen/config.h" #include "dbgen/dss.h" +#include DSS_HUGE NextRand(DSS_HUGE seed); void permute(long *set, int cnt, seed_t *seed); -void permute_dist(distribution *d, seed_t *seed); +void permute_dist(distribution *d, seed_t *seed, DBGenContext *ctx); long seed; char *eol[2] = {" ", "},"}; @@ -27,8 +28,8 @@ char *eol[2] = {" ", "},"}; void permute(long *a, int c, seed_t *seed) { int i; - static DSS_HUGE source; - static long temp; + DSS_HUGE source; + long temp; if (a != (long *)NULL) { for (i = 0; i < c; i++) { @@ -42,17 +43,17 @@ void permute(long *a, int c, seed_t *seed) { return; } -void permute_dist(distribution *d, seed_t *seed) { +void permute_dist(distribution *d, seed_t *seed, DBGenContext *ctx) { int i; if (d != NULL) { - if (d->permute == (long *)NULL) { - d->permute = (long *)malloc(sizeof(long) * DIST_SIZE(d)); - MALLOC_CHECK(d->permute); + if (ctx->permute == (long *)NULL) { + ctx->permute = (long *)malloc(sizeof(long) * DIST_SIZE(d)); + MALLOC_CHECK(ctx->permute); } for (i = 0; i < DIST_SIZE(d); i++) - *(d->permute + i) = i; - permute(d->permute, DIST_SIZE(d), seed); + *(ctx->permute + i) = i; + permute(ctx->permute, DIST_SIZE(d), seed); } else INTERNAL_ERROR("Bad call to permute_dist"); diff --git a/extension/tpch/include/tpch_extension.hpp b/extension/tpch/include/tpch_extension.hpp index 8f063b2df0d..a6af5082471 100644 --- a/extension/tpch/include/tpch_extension.hpp +++ b/extension/tpch/include/tpch_extension.hpp @@ -16,6 +16,7 @@ class TpchExtension : public Extension { public: void Load(DuckDB &db) override; std::string Name() override; + std::string Version() const override; //! Gets the specified TPC-H Query number as a string static std::string GetQuery(int query); diff --git a/extension/tpch/tpch_extension.cpp b/extension/tpch/tpch_extension.cpp index b5cde706fd6..3cda60f7652 100644 --- a/extension/tpch/tpch_extension.cpp +++ b/extension/tpch/tpch_extension.cpp @@ -54,7 +54,8 @@ static duckdb::unique_ptr DbgenBind(ClientContext &context, TableF } if (input.binder) { auto &catalog = Catalog::GetCatalog(context, result->catalog); - input.binder->properties.modified_databases.insert(catalog.GetName()); + auto &properties = input.binder->GetStatementProperties(); + properties.modified_databases.insert(catalog.GetName()); } return_types.emplace_back(LogicalType::BOOLEAN); names.emplace_back("Success"); @@ -202,6 +203,14 @@ std::string TpchExtension::Name() { return "tpch"; } +std::string TpchExtension::Version() const { +#ifdef EXT_VERSION_TPCH + return EXT_VERSION_TPCH; +#else + return ""; +#endif +} + } // namespace duckdb extern "C" { diff --git a/scripts/append_metadata.cmake b/scripts/append_metadata.cmake index 557db545d90..46caab131f8 100644 --- a/scripts/append_metadata.cmake +++ b/scripts/append_metadata.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.5...3.29) # Usage: cmake -DEXTENSION=path/to/extension.duckdb_extension -DPLATFORM_FILE=README.md -DDUCKDB_VERSION=tag1 -DEXTENSION_VERSION=tag2 -P scripts/append_metadata.cmake # Currently hardcoded to host up to 8 fields diff --git a/scripts/apply_extension_patches.py b/scripts/apply_extension_patches.py index e51870ae3e1..4cb618f4528 100644 --- a/scripts/apply_extension_patches.py +++ b/scripts/apply_extension_patches.py @@ -17,7 +17,7 @@ def raise_error(error_msg): sys.exit(1) -patches = os.listdir(directory) +patches = sorted(os.listdir(directory)) for patch in patches: if not patch.endswith('.patch'): raise_error( diff --git a/scripts/coverage_check.sh b/scripts/coverage_check.sh index 0ca7afa85ad..8293930bfc5 100755 --- a/scripts/coverage_check.sh +++ b/scripts/coverage_check.sh @@ -13,8 +13,6 @@ mkdir -p build/coverage # run tests build/coverage/test/unittest build/coverage/test/unittest "[coverage]" -build/coverage/test/unittest "[intraquery]" -build/coverage/test/unittest "[interquery]" build/coverage/test/unittest "[detailed_profiler]" build/coverage/test/unittest test/sql/tpch/tpch_sf01.test_slow python3 -m pytest --shell-binary build/coverage/duckdb tools/shell/tests/ @@ -27,4 +25,4 @@ lcov --config-file .github/workflows/lcovrc --remove coverage.info $(< .github/w genhtml -o coverage_html lcov.info # check that coverage passes threshold -python3 scripts/check_coverage.py +# python3 scripts/check_coverage.py diff --git a/scripts/exported_symbols_check.py b/scripts/exported_symbols_check.py index 547956a740c..67f7457cf63 100644 --- a/scripts/exported_symbols_check.py +++ b/scripts/exported_symbols_check.py @@ -23,6 +23,7 @@ 'duckdb_fmt::', 'duckdb_hll::', 'duckdb_moodycamel::', + 'duckdb_yyjson::', 'duckdb_', 'RefCounter', 'registerTMCloneTable', diff --git a/scripts/format.py b/scripts/format.py index e053a021f0e..d89f1aeacf9 100644 --- a/scripts/format.py +++ b/scripts/format.py @@ -107,20 +107,18 @@ os.path.join('tools', 'rpkg', 'inst', 'include', 'cpp11'), os.path.join('extension', 'tpcds', 'dsdgen'), os.path.join('extension', 'jemalloc', 'jemalloc'), - os.path.join('extension', 'json', 'yyjson'), os.path.join('extension', 'icu', 'third_party'), - os.path.join('src', 'include', 'duckdb', 'core_functions', 'aggregate'), - os.path.join('src', 'include', 'duckdb', 'core_functions', 'scalar'), os.path.join('tools', 'nodejs', 'src', 'duckdb'), ] format_all = False check_only = True confirm = True silent = False +force = False def print_usage(): - print("Usage: python scripts/format.py [revision|--all] [--check|--fix]") + print("Usage: python scripts/format.py [revision|--all] [--check|--fix] [--force]") print( " [revision] is an optional revision number, all files that changed since that revision will be formatted (default=HEAD)" ) @@ -148,6 +146,8 @@ def print_usage(): confirm = True elif arg == '--silent': silent = True + elif arg == '--force': + force = True else: print_usage() @@ -170,9 +170,6 @@ def can_format_file(full_path): if not os.path.isfile(full_path): return False fname = full_path.split(os.path.sep)[-1] - # check ignored files - if file_is_ignored(full_path): - return False found = False # check file extension for ext in extensions: @@ -181,6 +178,9 @@ def can_format_file(full_path): break if not found: return False + # check ignored files + if file_is_ignored(full_path): + return False # now check file directory for dname in formatted_directories: if full_path.startswith(dname): @@ -263,8 +263,13 @@ def get_changed_files(revision): def get_formatted_text(f, full_path, directory, ext): if not can_format_file(full_path): - print("Eek, cannot format file " + full_path + " but attempted to format anyway") - exit(1) + if not force: + print( + "File " + + full_path + + " is not normally formatted - but attempted to format anyway. Use --force if formatting is desirable" + ) + exit(1) if f == 'list.hpp': # fill in list file file_list = [ diff --git a/scripts/generate_extensions_function.py b/scripts/generate_extensions_function.py index be00d406eda..d5c5ead9328 100644 --- a/scripts/generate_extensions_function.py +++ b/scripts/generate_extensions_function.py @@ -26,7 +26,7 @@ args = parser.parse_args() -EXTENSIONS_PATH = os.path.join("..", "build", "extension_configuration", "extensions.txt") +EXTENSIONS_PATH = os.path.join("..", "build", "extension_configuration", "extensions.csv") DUCKDB_PATH = os.path.join("..", 'build', 'release', 'duckdb') HEADER_PATH = os.path.join("..", "src", "include", "duckdb", "main", "extension_entries.hpp") @@ -194,8 +194,10 @@ def check_prerequisites(): def get_extension_names() -> List[str]: extension_names = [] with open(EXTENSIONS_PATH) as f: + # Skip the csv header + next(f) for line in f: - extension_name = line.rstrip() + extension_name = line.split(',')[0].rstrip() if "jemalloc" in extension_name: # We skip jemalloc as it doesn't produce a loadable extension but is in the config continue @@ -474,7 +476,7 @@ def write_header(data: ExtensionData): static constexpr ExtensionEntry EXTENSION_FILE_PREFIXES[] = { {"http://", "httpfs"}, {"https://", "httpfs"}, {"s3://", "httpfs"}, {"s3a://", "httpfs"}, {"s3n://", "httpfs"}, {"gcs://", "httpfs"}, {"gs://", "httpfs"}, {"r2://", "httpfs"}, {"azure://", "azure"}, {"az://", "azure"}, - {"abfss://", "azure"} + {"abfss://", "azure"}, {"hf://", "httpfs"} }; // END_OF_EXTENSION_FILE_PREFIXES // Note: these are currently hardcoded in scripts/generate_extensions_function.py @@ -503,7 +505,10 @@ def write_header(data: ExtensionData): static constexpr ExtensionEntry EXTENSION_SECRET_TYPES[] = {{"s3", "httpfs"}, {"r2", "httpfs"}, {"gcs", "httpfs"}, - {"azure", "azure"}}; // EXTENSION_SECRET_TYPES + {"azure", "azure"}, + {"huggingface", "httpfs"}, + {"bearer", "httpfs"} + }; // EXTENSION_SECRET_TYPES // Note: these are currently hardcoded in scripts/generate_extensions_function.py @@ -515,12 +520,17 @@ def write_header(data: ExtensionData): {"gcs/credential_chain", "aws"}, {"r2/credential_chain", "aws"}, {"azure/config", "azure"}, - {"azure/credential_chain", "azure"}}; // EXTENSION_SECRET_PROVIDERS + {"azure/credential_chain", "azure"}, + {"huggingface/config", "httfps"}, + {"huggingface/credential_chain", "httpfs"}, + {"bearer/config", "httpfs"} +}; // EXTENSION_SECRET_PROVIDERS static constexpr const char *AUTOLOADABLE_EXTENSIONS[] = { "aws", "azure", "autocomplete", + "delta", "excel", "fts", "httpfs", @@ -551,6 +561,14 @@ def write_header(data: ExtensionData): file.close() +# Extensions that can be autoloaded, but are not buildable by DuckDB CI +HARDCODED_EXTENSION_FUNCTIONS = ExtensionFunction.create_map( + [ + ("delta_scan", "delta", "CatalogType::TABLE_FUNCTION_ENTRY"), + ] +) + + def main(): check_prerequisites() @@ -572,6 +590,10 @@ def main(): # Add the entries we initially parsed from the HEADER_PATH extension_data.add_entries(parsed_entries) + # Add hardcoded extension entries ( + for key, value in HARDCODED_EXTENSION_FUNCTIONS.items(): + extension_data.function_map[key] = value + if args.validate: extension_data.validate() return diff --git a/scripts/generate_serialization.py b/scripts/generate_serialization.py index b876182a0d9..2aea754a7c0 100644 --- a/scripts/generate_serialization.py +++ b/scripts/generate_serialization.py @@ -6,6 +6,7 @@ parser = argparse.ArgumentParser(description='Generate serialization code') parser.add_argument('--source', type=str, help='Source directory') parser.add_argument('--target', type=str, help='Target directory') + args = parser.parse_args() if args.source is None: @@ -36,6 +37,58 @@ } ) +scripts_dir = os.path.dirname(os.path.abspath(__file__)) +version_map_path = scripts_dir + '/../src/storage/version_map.json' +version_map_file = file = open(version_map_path) +version_map = json.load(version_map_file) + + +def verify_serialization_versions(version_map): + serialization = version_map['serialization'] + if list(serialization.keys())[-1] != 'latest': + print(f"The version map ({version_map_path}) for serialization versions must end in 'latest'!") + exit(1) + + +verify_serialization_versions(version_map) + + +def lookup_serialization_version(version: str): + if version.lower() == "latest": + print( + f"'latest' is not an allowed 'version' to use in serialization JSON files, please provide a duckdb version" + ) + + versions = version_map['serialization'] + if version not in versions: + from packaging.version import Version + + current_version = Version(version) + + # This version does not exist in the version map + # Which is allowed for unreleased versions, they will get mapped to 'latest' instead + + last_registered_version = Version(list(versions.keys())[-2]) + if current_version < last_registered_version: + # The version was lower than the last defined version, which is not allowed + print( + f"Specified version ({current_version}) could not be found in the version_map.json, and it is lower than the last defined version ({last_registered_version})!" + ) + exit(1) + + if hasattr(lookup_serialization_version, 'latest_version'): + # We have already mapped a version to 'latest', check that the versions match + latest_version = getattr(lookup_serialization_version, 'latest_version') + if current_version != latest_version: + print( + f"Found more than one version that is not present in the version_map.json!: {current_version}, {latest_version}" + ) + exit(1) + else: + setattr(lookup_serialization_version, 'latest_version', current_version) + return versions['latest'] + return versions[version] + include_base = '#include "${FILENAME}"\n' @@ -147,7 +200,15 @@ def get_default_argument(default_value): def get_serialize_element( - property_name, property_id, property_key, property_type, has_default, default_value, is_deleted, pointer_type + property_name, + property_id, + property_key, + property_type, + has_default, + default_value, + is_deleted, + pointer_type, + version, ): assignment = '.' if pointer_type == 'none' else '->' default_argument = '' if default_value is None else f', {get_default_argument(default_value)}' @@ -156,7 +217,7 @@ def get_serialize_element( template = "\t/* [Deleted] (${PROPERTY_TYPE}) \"${PROPERTY_NAME}\" */\n" elif has_default: template = template.replace('WriteProperty', 'WritePropertyWithDefault') - return ( + serialization_code = ( template.replace('${PROPERTY_NAME}', property_name) .replace('${PROPERTY_TYPE}', property_type) .replace('${PROPERTY_ID}', str(property_id)) @@ -165,6 +226,16 @@ def get_serialize_element( .replace('${ASSIGNMENT}', assignment) ) + storage_version = lookup_serialization_version(version) + if storage_version != 1: + code = [] + code.append(f'\tif (serializer.ShouldSerialize({storage_version})) {{') + code.append('\t' + serialization_code) + + result = '\n'.join(code) + '\t}\n' + return result + return serialization_code + def get_deserialize_element_template( template, @@ -244,6 +315,8 @@ def generate_return(class_entry): return '\treturn std::move(result);' +# FIXME: python has __slots__ for this, so it's enforced by Python itself +# see: https://wiki.python.org/moin/UsingSlots supported_member_entries = [ 'id', 'name', @@ -254,6 +327,7 @@ def generate_return(class_entry): 'base', 'default', 'deleted', + 'version', ] @@ -282,12 +356,15 @@ def __init__(self, entry): self.has_default = False self.default = None self.deleted = False + self.version: str = 'v0.10.2' if 'property' in entry: self.serialize_property = entry['property'] self.deserialize_property = entry['property'] else: self.serialize_property = self.name self.deserialize_property = self.name + if 'version' in entry: + self.version = entry['version'] if 'serialize_property' in entry: self.serialize_property = entry['serialize_property'] if 'deserialize_property' in entry: @@ -406,6 +483,7 @@ def generate_base_class_code(base_class): default, entry.deleted, base_class.pointer_type, + entry.version, ) base_class_deserialize += get_deserialize_element( entry.deserialize_property, @@ -587,6 +665,7 @@ def generate_class_code(class_entry): '${BASE_PROPERTY}', entry.base.replace('*', '') ).replace('${DERIVED_PROPERTY}', entry.type.replace('*', '')) type_name = replace_pointer(entry.type) + class_serialize += get_serialize_element( write_property_name, property_id, @@ -596,6 +675,7 @@ def generate_class_code(class_entry): default_value, entry.deleted, class_entry.pointer_type, + entry.version, ) if entry_idx > last_constructor_index: class_deserialize += get_deserialize_element_template( diff --git a/scripts/generate_storage_info.py b/scripts/generate_storage_info.py new file mode 100644 index 00000000000..a2941b3faf4 --- /dev/null +++ b/scripts/generate_storage_info.py @@ -0,0 +1,64 @@ +import json +import os + +scripts_dir = os.path.dirname(os.path.abspath(__file__)) +VERSION_MAP_PATH = scripts_dir + "/../src/storage/version_map.json" +STORAGE_INFO_PATH = scripts_dir + "/../src/storage/storage_info.cpp" +START_MARKER = "// START OF {type} VERSION INFO" +END_MARKER = "// END OF {type} VERSION INFO" + + +def generate_version_info_array(storage_versions, type_and_name): + + result = [] + result.append(f"static const {type_and_name}[] = {{") + + for version_name, storage_version in storage_versions.items(): + result.append(f'\t{{"{version_name}", {storage_version}}},') + + result.append("\t{nullptr, 0}") + result.append("};\n") + + return "\n".join(result) + + +def main(): + + with open(VERSION_MAP_PATH, 'r') as json_file: + version_map = json.load(json_file) + storage_version_info = generate_version_info_array( + version_map['storage'], 'StorageVersionInfo storage_version_info' + ) + serialization_version_info = generate_version_info_array( + version_map['serialization'], 'SerializationVersionInfo serialization_version_info' + ) + + with open(STORAGE_INFO_PATH, "r") as cpp_file: + content = cpp_file.read() + + for type in version_map: + capitalized_type = type.capitalize() + upper_type = type.upper() + array_code = generate_version_info_array( + version_map[type], f'{capitalized_type}VersionInfo {type}_version_info' + ) + + start_marker = START_MARKER.format(type=upper_type) + start_index = content.find(start_marker) + if start_index == -1: + print(f"storage_info.cpp is corrupted, could not find the START_MARKER for {type}") + exit(1) + + end_marker = END_MARKER.format(type=upper_type) + end_index = content.find(end_marker) + if end_index == -1: + print(f"storage_info.cpp is corrupted, could not find the END_MARKER for {type}") + exit(1) + content = content[: start_index + len(start_marker)] + "\n" + array_code + content[end_index:] + + with open(STORAGE_INFO_PATH, "w") as cpp_file: + cpp_file.write(content) + + +if __name__ == "__main__": + main() diff --git a/scripts/jdbc_maven_deploy.py b/scripts/jdbc_maven_deploy.py deleted file mode 100644 index 2f5e4e3b064..00000000000 --- a/scripts/jdbc_maven_deploy.py +++ /dev/null @@ -1,201 +0,0 @@ -# https://central.sonatype.org/pages/manual-staging-bundle-creation-and-deployment.html -# https://issues.sonatype.org/browse/OSSRH-58179 - -# this is the pgp key we use to sign releases -# if this key should be lost, generate a new one with `gpg --full-generate-key` -# AND upload to keyserver: `gpg --keyserver hkp://keys.openpgp.org --send-keys [...]` -# export the keys for GitHub Actions like so: `gpg --export-secret-keys | base64` -# -------------------------------- -# pub ed25519 2022-02-07 [SC] -# 65F91213E069629F406F7CF27F610913E3A6F526 -# uid [ultimate] DuckDB -# sub cv25519 2022-02-07 [E] - -import os -import pathlib -import shutil -import subprocess -import sys -import tempfile -import zipfile -import re - - -def exec(cmd): - print(cmd) - res = subprocess.run(cmd.split(' '), capture_output=True) - if res.returncode == 0: - return res.stdout - raise ValueError(res.stdout + res.stderr) - - -if len(sys.argv) < 4 or not os.path.isdir(sys.argv[2]) or not os.path.isdir(sys.argv[3]): - print("Usage: [release_tag, format: v1.2.3] [artifact_dir] [jdbc_root_path]") - exit(1) - -version_regex = re.compile(r'^v((\d+)\.(\d+)\.\d+)$') -release_tag = sys.argv[1] -deploy_url = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' -is_release = True - -if release_tag == 'main': - # for SNAPSHOT builds we increment the minor version and set patch level to zero. - # seemed the most sensible - last_tag = exec('git tag --sort=-committerdate').decode('utf8').split('\n')[0] - re_result = version_regex.search(last_tag) - if re_result is None: - raise ValueError("Could not parse last tag %s" % last_tag) - release_version = "%d.%d.0-SNAPSHOT" % (int(re_result.group(2)), int(re_result.group(3)) + 1) - # orssh uses a different deploy url for snapshots yay - deploy_url = 'https://oss.sonatype.org/content/repositories/snapshots/' - is_release = False -elif version_regex.match(release_tag): - release_version = version_regex.search(release_tag).group(1) -else: - print("Not running on %s" % release_tag) - exit(0) - -jdbc_artifact_dir = sys.argv[2] -jdbc_root_path = sys.argv[3] - -combine_builds = ['linux-amd64', 'osx-universal', 'windows-amd64', 'linux-aarch64'] - -staging_dir = tempfile.mkdtemp() - -binary_jar = '%s/duckdb_jdbc-%s.jar' % (staging_dir, release_version) -pom = '%s/duckdb_jdbc-%s.pom' % (staging_dir, release_version) -sources_jar = '%s/duckdb_jdbc-%s-sources.jar' % (staging_dir, release_version) -javadoc_jar = '%s/duckdb_jdbc-%s-javadoc.jar' % (staging_dir, release_version) - -pom_template = """ - - 4.0.0 - org.duckdb - duckdb_jdbc - ${VERSION} - jar - DuckDB JDBC Driver - A JDBC-Compliant driver for the DuckDB data management system - https://www.duckdb.org - - - - MIT License - https://raw.githubusercontent.com/duckdb/duckdb/main/LICENSE - repo - - - - - - Mark Raasveldt - mark@duckdblabs.com - DuckDB Labs - https://www.duckdblabs.com - - - Hannes Muehleisen - hannes@duckdblabs.com - DuckDB Labs - https://www.duckdblabs.com - - - - - scm:git:git://github.com/duckdb/duckdb.git - scm:git:ssh://github.com:duckdb/duckdb.git - http://github.com/duckdb/duckdb/tree/main - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 - true - - ossrh - https://oss.sonatype.org/ - - - - - - - -""" - -# create a matching POM with this version -pom_path = pathlib.Path(pom) -pom_path.write_text(pom_template.replace("${VERSION}", release_version)) - -# fatten up jar to add other binaries, start with first one -shutil.copyfile(os.path.join(jdbc_artifact_dir, "java-" + combine_builds[0], "duckdb_jdbc.jar"), binary_jar) -for build in combine_builds[1:]: - old_jar = zipfile.ZipFile(os.path.join(jdbc_artifact_dir, "java-" + build, "duckdb_jdbc.jar"), 'r') - for zip_entry in old_jar.namelist(): - if zip_entry.startswith('libduckdb_java.so'): - old_jar.extract(zip_entry, staging_dir) - exec("jar -uf %s -C %s %s" % (binary_jar, staging_dir, zip_entry)) - -javadoc_stage_dir = tempfile.mkdtemp() - -exec("javadoc -Xdoclint:-reference -d %s -sourcepath %s/src/main/java org.duckdb" % (javadoc_stage_dir, jdbc_root_path)) -exec("jar -cvf %s -C %s ." % (javadoc_jar, javadoc_stage_dir)) -exec("jar -cvf %s -C %s/src/main/java org" % (sources_jar, jdbc_root_path)) - -# make sure all files exist before continuing -if ( - not os.path.exists(javadoc_jar) - or not os.path.exists(sources_jar) - or not os.path.exists(pom) - or not os.path.exists(binary_jar) -): - raise ValueError('could not create all required files') - -# now sign and upload everything -# for this to work, you must have entry in ~/.m2/settings.xml: - -# -# -# -# ossrh -# hfmuehleisen -# [...] -# -# -# - -results_dir = os.path.join(jdbc_artifact_dir, "results") -if not os.path.exists(results_dir): - os.mkdir(results_dir) - - -for jar in [binary_jar, sources_jar, javadoc_jar]: - shutil.copyfile(jar, os.path.join(results_dir, os.path.basename(jar))) - -print("JARs created, uploading (this can take a while!)") -deploy_cmd_prefix = 'mvn gpg:sign-and-deploy-file -Durl=%s -DrepositoryId=ossrh' % deploy_url -exec("%s -DpomFile=%s -Dfile=%s" % (deploy_cmd_prefix, pom, binary_jar)) -exec("%s -Dclassifier=sources -DpomFile=%s -Dfile=%s" % (deploy_cmd_prefix, pom, sources_jar)) -exec("%s -Dclassifier=javadoc -DpomFile=%s -Dfile=%s" % (deploy_cmd_prefix, pom, javadoc_jar)) - - -if not is_release: - print("Not a release, not closing repo") - exit(0) - -print("Close/Release steps") -# # beautiful -os.environ["MAVEN_OPTS"] = '--add-opens=java.base/java.util=ALL-UNNAMED' - -# this list has horrid output, lets try to parse. What we want starts with orgduckdb- and then a number -repo_id = re.search(r'(orgduckdb-\d+)', exec("mvn -f %s nexus-staging:rc-list" % (pom)).decode('utf8')).groups()[0] -exec("mvn -f %s nexus-staging:rc-close -DstagingRepositoryId=%s" % (pom, repo_id)) -exec("mvn -f %s nexus-staging:rc-release -DstagingRepositoryId=%s" % (pom, repo_id)) - -print("Done?") diff --git a/scripts/package_build.py b/scripts/package_build.py index ac737e88c14..de6ecdfb846 100644 --- a/scripts/package_build.py +++ b/scripts/package_build.py @@ -22,6 +22,10 @@ def third_party_includes(): includes += [os.path.join('third_party', 'libpg_query')] includes += [os.path.join('third_party', 'libpg_query', 'include')] includes += [os.path.join('third_party', 'lz4')] + includes += [os.path.join('third_party', 'brotli', 'include')] + includes += [os.path.join('third_party', 'brotli', 'common')] + includes += [os.path.join('third_party', 'brotli', 'dec')] + includes += [os.path.join('third_party', 'brotli', 'enc')] includes += [os.path.join('third_party', 'mbedtls')] includes += [os.path.join('third_party', 'mbedtls', 'include')] includes += [os.path.join('third_party', 'mbedtls', 'library')] @@ -32,6 +36,7 @@ def third_party_includes(): includes += [os.path.join('third_party', 'tdigest')] includes += [os.path.join('third_party', 'utf8proc')] includes += [os.path.join('third_party', 'utf8proc', 'include')] + includes += [os.path.join('third_party', 'yyjson', 'include')] return includes @@ -47,6 +52,7 @@ def third_party_sources(): sources += [os.path.join('third_party', 'utf8proc')] sources += [os.path.join('third_party', 'libpg_query')] sources += [os.path.join('third_party', 'mbedtls')] + sources += [os.path.join('third_party', 'yyjson')] return sources diff --git a/scripts/plan_cost_runner.py b/scripts/plan_cost_runner.py index 416d6884002..43b4dcb6a09 100644 --- a/scripts/plan_cost_runner.py +++ b/scripts/plan_cost_runner.py @@ -89,14 +89,14 @@ def __eq__(self, other): def op_inspect(op) -> PlanCost: cost = PlanCost() - if op['name'] == "Query": - cost.time = op['timing'] - if op['name'] == 'HASH_JOIN' and not op['extra_info'].startswith('MARK'): - cost.total = op['cardinality'] - if 'cardinality' in op['children'][0]: - cost.probe_side += op['children'][0]['cardinality'] - if 'cardinality' in op['children'][1]: - cost.build_side += op['children'][1]['cardinality'] + if 'Query' in op: + cost.time = op['operator_timing'] + if 'name' in op and op['name'] == 'HASH_JOIN' and not op['extra_info'].startswith('MARK'): + cost.total = op['operator_cardinality'] + if 'operator_cardinality' in op['children'][0]: + cost.probe_side += op['children'][0]['operator_cardinality'] + if 'operator_cardinality' in op['children'][1]: + cost.build_side += op['children'][1]['operator_cardinality'] left_cost = op_inspect(op['children'][0]) right_cost = op_inspect(op['children'][1]) cost.probe_side += left_cost.probe_side + right_cost.probe_side diff --git a/scripts/reduce_sql.py b/scripts/reduce_sql.py index ab2cd70e96c..245a89b7b10 100644 --- a/scripts/reduce_sql.py +++ b/scripts/reduce_sql.py @@ -19,6 +19,28 @@ ''' +class MultiStatementManager: + delimiter = ';' + + def __init__(self, multi_statement): + # strip whitespace, then the final ';', and split on all ';' inbetween. + statements = list( + map(lambda x: x.strip(), multi_statement.strip().strip(';').split(MultiStatementManager.delimiter)) + ) + self.statements = [] + for stmt in statements: + if len(stmt) > 0: + self.statements.append(stmt.strip() + ";") + + def is_multi_statement(sql_statement): + if len(sql_statement.split(';')) > 1: + return True + return False + + def get_last_statement(self): + return self.statements[-1] + + def sanitize_error(err): err = re.sub(r'Error: near line \d+: ', '', err) err = err.replace(os.getcwd() + '/', '') @@ -192,7 +214,20 @@ def reduce_query_log_query(start, shell, queries, query_index, max_time_seconds) return sql_query -def reduce_query_log(queries, shell, max_time_seconds=300): +def reduce_multi_statement(sql_queries, local_shell, local_data_load): + reducer = MultiStatementManager(sql_queries) + last_statement = reducer.get_last_statement() + print(f"testing if just last statement of multi statement creates the error") + (stdout, stderr, returncode) = run_shell_command(local_shell, local_data_load + last_statement) + expected_error = sanitize_error(stderr).strip() + if len(expected_error) > 0: + # reduce just the last statement + return reduce(last_statement, local_data_load, local_shell, expected_error, int(args.max_time)) + queries = reduce_query_log(reducer.statements, local_shell, [local_data_load]) + return "\n".join(queries) + + +def reduce_query_log(queries, shell, data_load=[], max_time_seconds=300): start = time.time() current_index = 0 # first try to remove as many queries as possible @@ -203,8 +238,9 @@ def reduce_query_log(queries, shell, max_time_seconds=300): break # remove the query at "current_index" new_queries = queries[:current_index] + queries[current_index + 1 :] + new_queries_with_data = data_load + new_queries # try to run the queries and check if we still get the same error - (new_queries_x, current_error) = run_queries_until_crash(new_queries) + (new_queries_x, current_error) = run_queries_until_crash(new_queries_with_data) if current_error is None: # cannot remove this query without invalidating the test case current_index += 1 @@ -258,7 +294,11 @@ def reduce_query_log(queries, shell, max_time_seconds=300): print(expected_error) print("===================================================") - final_query = reduce(sql_query, data_load, shell, expected_error, int(args.max_time)) + if MultiStatementManager.is_multi_statement(sql_query): + final_query = reduce_multi_statement(sql_query, shell, data_load) + else: + final_query = reduce(sql_query, data_load, shell, expected_error, int(args.max_time)) + print("Found final reduced query") print("===================================================") print(final_query) diff --git a/scripts/regression_test_python.py b/scripts/regression_test_python.py index 3b88e5c99ce..f4b8c0420f3 100644 --- a/scripts/regression_test_python.py +++ b/scripts/regression_test_python.py @@ -6,6 +6,7 @@ import time import argparse from typing import Dict, List, Any +import numpy as np TPCH_QUERIES = [] res = duckdb.execute( @@ -58,9 +59,16 @@ def close_result(): class BenchmarkResult: - def __init__(self, duration, run_number): - self.duration = duration - self.run_number = run_number + def __init__(self, name): + self.name = name + self.runs: List[float] = [] + + def add(self, duration: float): + self.runs.append(duration) + + def write(self): + for i, run in enumerate(self.runs): + write_result(self.name, i, run) class TPCHData: @@ -76,10 +84,10 @@ def get_tables(self, convertor) -> Dict[str, Any]: res[table] = convertor(self.conn, table) return res - def load_lineitem(self, collector) -> List[BenchmarkResult]: + def load_lineitem(self, collector, benchmark_name) -> BenchmarkResult: query = 'SELECT * FROM lineitem' - results = [] - for nrun in range(nruns): + result = BenchmarkResult(benchmark_name) + for _ in range(nruns): duration = 0.0 start = time.time() rel = self.conn.sql(query) @@ -89,8 +97,8 @@ def load_lineitem(self, collector) -> List[BenchmarkResult]: del res padding = " " * len(str(nruns)) print_msg(f"T{padding}: {duration}s") - results.append(BenchmarkResult(duration, nrun)) - return results + result.add(duration) + return result class TPCHBenchmarker: @@ -109,11 +117,11 @@ def register_tables(self, tables: Dict[str, Any]): for name, table in tables.items(): self.con.register(name, table) - def run_tpch(self, collector) -> List[BenchmarkResult]: + def run_tpch(self, collector, benchmark_name) -> BenchmarkResult: print_msg("") print_msg(TPCH_QUERIES) - results = [] - for nrun in range(nruns): + result = BenchmarkResult(benchmark_name) + for _ in range(nruns): duration = 0.0 # Execute all queries for i, query in enumerate(TPCH_QUERIES): @@ -130,8 +138,8 @@ def run_tpch(self, collector) -> List[BenchmarkResult]: duration += float(end - start) padding = " " * len(str(nruns)) print_msg(f"T{padding}: {duration}s") - results.append(BenchmarkResult(duration, nrun)) - return results + result.add(duration) + return result def test_tpch(): @@ -152,14 +160,10 @@ def fetch_arrow(rel: duckdb.DuckDBPyRelation): COLLECTORS = {'native': fetch_native, 'pandas': fetch_pandas, 'arrow': fetch_arrow} # For every collector, load lineitem 'nrun' times for collector in COLLECTORS: - results: List[BenchmarkResult] = tpch.load_lineitem(COLLECTORS[collector]) - benchmark_name = collector + "_load_lineitem" - print_msg(benchmark_name) + result: BenchmarkResult = tpch.load_lineitem(COLLECTORS[collector], collector + "_load_lineitem") + print_msg(result.name) print_msg(collector) - for res in results: - run_number = res.run_number - duration = res.duration - write_result(benchmark_name, run_number, duration) + result.write() ## ------- Benchmark running TPCH queries on top of different formats -------- @@ -177,12 +181,8 @@ def convert_arrow(conn: duckdb.DuckDBPyConnection, table_name: str): tester = TPCHBenchmarker(convertor) tester.register_tables(tables) collector = COLLECTORS[convertor] - results: List[BenchmarkResult] = tester.run_tpch(collector) - benchmark_name = f"{convertor}tpch" - for res in results: - run_number = res.run_number - duration = res.duration - write_result(benchmark_name, run_number, duration) + result: BenchmarkResult = tester.run_tpch(collector, f"{convertor}tpch") + result.write() def generate_string(seed: int): @@ -226,10 +226,10 @@ def generate(self, unique_values, values, arrow_dict: ArrowDictionary): ) self.table = pa.table([array], names=["x"]) - def benchmark(self) -> List[BenchmarkResult]: + def benchmark(self, benchmark_name) -> BenchmarkResult: self.con.register('arrow_table', self.table) - results = [] - for nrun in range(nruns): + result = BenchmarkResult(benchmark_name) + for _ in range(nruns): duration = 0.0 start = time.time() res = self.con.execute( @@ -243,7 +243,45 @@ def benchmark(self) -> List[BenchmarkResult]: del res padding = " " * len(str(nruns)) print_msg(f"T{padding}: {duration}s") - results.append(BenchmarkResult(duration, nrun)) + result.add(duration) + return result + + +class SelectAndCallBenchmark: + def __init__(self): + """ + SELECT statements become QueryRelations, any other statement type becomes a MaterializedRelation. + We use SELECT and CALL here because their execution plans are identical + """ + self.initialize_connection() + + def initialize_connection(self): + self.con = duckdb.connect() + if not threads: + return + print_msg(f'Limiting threads to {threads}') + self.con.execute(f"SET threads={threads}") + + def benchmark(self, name, query) -> List[BenchmarkResult]: + results: List[BenchmarkResult] = [] + methods = {'select': 'select * from ', 'call': 'call '} + for key, value in methods.items(): + for rowcount in [2048, 50000, 2500000]: + result = BenchmarkResult(f'{key}_{name}_{rowcount}') + query_string = query.format(rows=rowcount) + query_string = value + query_string + rel = self.con.sql(query_string) + print_msg(rel.type) + for _ in range(nruns): + duration = 0.0 + start = time.time() + rel.fetchall() + end = time.time() + duration = float(end - start) + padding = " " * len(str(nruns)) + print_msg(f"T{padding}: {duration}s") + result.add(duration) + results.append(result) return results @@ -265,19 +303,52 @@ def generate(self): self.con.execute(f"create table wide as select {new_table} from lineitem limit 500") self.con.execute(f"copy wide to 'wide_table.csv' (FORMAT CSV)") - def benchmark(self) -> List[BenchmarkResult]: - results = [] - for nrun in range(nruns): + def benchmark(self, benchmark_name) -> BenchmarkResult: + result = BenchmarkResult(benchmark_name) + for _ in range(nruns): duration = 0.0 pandas_df = pd.read_csv('wide_table.csv') start = time.time() - for amplification in range(30): + for _ in range(30): res = self.con.execute("""select * from pandas_df""").df() end = time.time() duration = float(end - start) del res - results.append(BenchmarkResult(duration, nrun)) - return results + result.add(duration) + return result + + +class PandasAnalyzerBenchmark: + def __init__(self): + self.initialize_connection() + self.generate() + + def initialize_connection(self): + self.con = duckdb.connect() + if not threads: + return + print_msg(f'Limiting threads to {threads}') + self.con.execute(f"SET threads={threads}") + + def generate(self): + return + + def benchmark(self, benchmark_name) -> BenchmarkResult: + result = BenchmarkResult(benchmark_name) + data = [None] * 9999999 + [1] # Last element is 1, others are None + + # Create the DataFrame with the specified data and column type as object + pandas_df = pd.DataFrame(data, columns=['Column'], dtype=object) + for _ in range(nruns): + duration = 0.0 + start = time.time() + for _ in range(30): + res = self.con.execute("""select * from pandas_df""").df() + end = time.time() + duration = float(end - start) + del res + result.add(duration) + return result def test_arrow_dictionaries_scan(): @@ -287,28 +358,42 @@ def test_arrow_dictionaries_scan(): DATASET_SIZE = 10000000 for unique_values in [2, 1000, DICT_SIZE]: test = ArrowDictionaryBenchmark(unique_values, DATASET_SIZE, arrow_dict) - results = test.benchmark() benchmark_name = f"arrow_dict_unique_{unique_values}_total_{DATASET_SIZE}" - for res in results: - run_number = res.run_number - duration = res.duration - write_result(benchmark_name, run_number, duration) + result = test.benchmark(benchmark_name) + result.write() def test_loading_pandas_df_many_times(): test = PandasDFLoadBenchmark() - results = test.benchmark() benchmark_name = f"load_pandas_df_many_times" - for res in results: - run_number = res.run_number - duration = res.duration - write_result(benchmark_name, run_number, duration) + result = test.benchmark(benchmark_name) + result.write() + + +def test_pandas_analyze(): + test = PandasAnalyzerBenchmark() + benchmark_name = f"pandas_analyze" + result = test.benchmark(benchmark_name) + result.write() + + +def test_call_and_select_statements(): + test = SelectAndCallBenchmark() + queries = { + 'repeat_row': "repeat_row(42, 'test', True, 'this is a long string', num_rows={rows})", + } + for key, value in queries.items(): + results = test.benchmark(key, value) + for res in results: + res.write() def main(): test_tpch() test_arrow_dictionaries_scan() test_loading_pandas_df_many_times() + test_pandas_analyze() + test_call_and_select_statements() close_result() diff --git a/scripts/run_extension_medata_tests.sh b/scripts/run_extension_medata_tests.sh new file mode 100755 index 00000000000..bac4653ea79 --- /dev/null +++ b/scripts/run_extension_medata_tests.sh @@ -0,0 +1,177 @@ +#!/bin/bash + +# Generates a bunch of directories to be used for testing extension updating related behaviour used in `test/extension/update_extensions_ci.test` + +# Please consider your energy footprint by only running this script with ccache. +# note that subsequent runs used cached artifacts, use `make clean` or rm -rf build/debug to clean + +set -x +set -e + +DUCKDB_BUILD_DIR="./build/debug" + +TEST_DIR="./build/extension_metadata_test_data" +TEST_DIR_COPY="./build/extension_metadata_test_data_copy" + +### Directories to use +# Used as the extension installation directory for DuckDB +export LOCAL_EXTENSION_DIR="$TEST_DIR/extension_dir" +# Repository for testing successfully updating extensions +export LOCAL_EXTENSION_REPO_UPDATED="$TEST_DIR/repository" +# Repository for testing incorrect platform +export LOCAL_EXTENSION_REPO_INCORRECT_PLATFORM="$TEST_DIR/repository_incorrect_platform" +# Repository for testing incorrect version +export LOCAL_EXTENSION_REPO_INCORRECT_DUCKDB_VERSION="$TEST_DIR/repository_incorrect_version" +# Repository where both platform and version mismatch +export LOCAL_EXTENSION_REPO_VERSION_AND_PLATFORM_INCORRECT="$TEST_DIR/repository_incorrect_version_and_platform" +# Directory containing the extensions for direct installing +export DIRECT_INSTALL_DIR="$TEST_DIR/direct_install" + +# Extension dir with a malformed info file for an extension +export LOCAL_EXTENSION_DIR_MALFORMED_INFO="$TEST_DIR/extension_dir_malformed_info" +# Extension dir with a metadata install version that mismatches the files metadata +export LOCAL_EXTENSION_DIR_INFO_INCORRECT_VERSION="$TEST_DIR/extension_dir_malformed_info_incorrect_version" + +if [ -d "$TEST_DIR_COPY" ]; then + # REUSE PREVIOUSLY GENERATED DATA + rm -r $TEST_DIR + cp -R $TEST_DIR_COPY $TEST_DIR +else + # GENERATE FRESH DATA + mkdir -p $TEST_DIR + mkdir -p $DIRECT_INSTALL_DIR + mkdir -p $LOCAL_EXTENSION_DIR + mkdir -p $LOCAL_EXTENSION_REPO_UPDATED + mkdir -p $LOCAL_EXTENSION_REPO_INCORRECT_PLATFORM + mkdir -p $LOCAL_EXTENSION_REPO_INCORRECT_DUCKDB_VERSION + + ################################################# + ### First repo: successfully updating extensions. + ################################################# + # Set extension config + cat > $TEST_DIR/extension_config_before.cmake < $TEST_DIR/extension_config_after.cmake < $TEST_DIR/extension_config_incorrect_platform.cmake < $TEST_DIR/extension_config_incorrect_version.cmake < $TEST_DIR/extension_config_incorrect_version.cmake < $LOCAL_EXTENSION_DIR_MALFORMED_INFO/$DUCKDB_VERSION/$DUCKDB_PLATFORM/tpcds.duckdb_extension.info + + # Create dir with malformed info file: we install a new version from LOCAL_EXTENSION_REPO_UPDATED but preserve the old info file + $DUCKDB_BUILD_DIR/duckdb -unsigned -c "set extension_directory='$LOCAL_EXTENSION_DIR_INFO_INCORRECT_VERSION'; install 'tpch' from '$LOCAL_EXTENSION_REPO_UPDATED'" + cp $LOCAL_EXTENSION_DIR/$DUCKDB_VERSION/$DUCKDB_PLATFORM/tpch.duckdb_extension.info $LOCAL_EXTENSION_DIR_INFO_INCORRECT_VERSION/$DUCKDB_VERSION/$DUCKDB_PLATFORM/tpch.duckdb_extension.info + + ################################################################### + ### Allow using copy instead of regenerating test data on every run + ################################################################### + cp -R $TEST_DIR $TEST_DIR_COPY +fi + +########################### +### Set version and platform +########################### +DUCKDB_VERSION=`$DUCKDB_BUILD_DIR/duckdb -csv -noheader -c 'select source_id from pragma_version()'` +DUCKDB_PLATFORM=`cat $DUCKDB_BUILD_DIR/duckdb_platform_out` + +########################### +### Populate the minio repositories +########################### +AWS_DEFAULT_REGION=eu-west-1 AWS_ACCESS_KEY_ID=minio_duckdb_user AWS_SECRET_ACCESS_KEY=minio_duckdb_user_password aws --endpoint-url http://duckdb-minio.com:9000 s3 sync $LOCAL_EXTENSION_REPO_UPDATED s3://test-bucket-public/ci-test-repo +export REMOTE_EXTENSION_REPO_UPDATED=http://duckdb-minio.com:9000/test-bucket-public/ci-test-repo +export REMOTE_EXTENSION_REPO_DIRECT_PATH=http://duckdb-minio.com:9000/test-bucket-public/ci-test-repo/$DUCKDB_VERSION/$DUCKDB_PLATFORM + +################ +### Run test +################ +RUN_EXTENSION_UPDATE_TEST=1 $DUCKDB_BUILD_DIR/test/unittest test/extension/update_extensions_ci.test diff --git a/scripts/run_fuzzer.py b/scripts/run_fuzzer.py index c7d096f11ed..f2bb8f326bf 100644 --- a/scripts/run_fuzzer.py +++ b/scripts/run_fuzzer.py @@ -13,6 +13,7 @@ db = None shell = None perform_checks = True +dry = False for param in sys.argv: if param == '--sqlsmith': fuzzer = 'sqlsmith' @@ -32,6 +33,8 @@ shell = param.replace('--shell=', '') elif param.startswith('--seed='): seed = int(param.replace('--seed=', '')) + elif param.startswith('--dry'): + dry = True if fuzzer is None: print("Unrecognized fuzzer to run, expected e.g. --sqlsmith or --duckfuzz") @@ -94,7 +97,11 @@ def run_shell_command(cmd): # first get a list of all github issues, and check if we can still reproduce them -current_errors = fuzzer_helper.extract_github_issues(shell, perform_checks) + +if dry: + current_errors = [] +else: + current_errors = fuzzer_helper.extract_github_issues(shell, perform_checks) max_queries = 2000 last_query_log_file = 'sqlsmith.log' @@ -148,11 +155,12 @@ def run_shell_command(cmd): with open(last_query_log_file, 'r') as f: last_query = f.read() -cmd = load_script + '\n' + last_query +with open(complete_log_file, 'r') as f: + all_queries = f.read() -(stdout, stderr, returncode) = run_shell_command(cmd) +(stdout, stderr, returncode) = run_shell_command(load_script + all_queries) if returncode == 0: - print("Failed to reproduce the issue with a single command...") + print("Failed to reproduce the issue...") exit(0) print("============== STDOUT ================") @@ -161,12 +169,11 @@ def run_shell_command(cmd): print(stderr) print("==========================================") if not fuzzer_helper.is_internal_error(stderr): - print("Failed to reproduce the internal error with a single command") + print("Failed to reproduce the internal error") exit(0) error_msg = reduce_sql.sanitize_error(stderr) - print("=========================================") print(" Reproduced successfully ") print("=========================================") @@ -180,14 +187,13 @@ def run_shell_command(cmd): ) exit(0) -print(last_query) - print("=========================================") print(" Attempting to reduce query ") print("=========================================") - # try to reduce the query as much as possible -last_query = reduce_sql.reduce(last_query, load_script, shell, error_msg) +# reduce_multi_statement checks just the last statement first as a heuristic to see if +# only the last statement causes the error. +required_queries = reduce_sql.reduce_multi_statement(all_queries, shell, load_script) cmd = load_script + '\n' + last_query + "\n" fuzzer_helper.file_issue(cmd, error_msg, fuzzer_name, seed, git_hash) diff --git a/scripts/run_sqlancer.py b/scripts/run_sqlancer.py index 61d4a13052d..2646de41fc9 100644 --- a/scripts/run_sqlancer.py +++ b/scripts/run_sqlancer.py @@ -120,7 +120,7 @@ print('----------------------------------------------') # clean up queries from the query log by trying to remove queries one by one -queries = reduce_sql.reduce_query_log(queries, shell) +queries = reduce_sql.reduce_query_log(queries, shell, []) reduced_test_case = ';\n'.join(queries) print('----------------------------------------------') diff --git a/scripts/run_tests_one_by_one.py b/scripts/run_tests_one_by_one.py index ec5f5eb88a6..863251f3a52 100644 --- a/scripts/run_tests_one_by_one.py +++ b/scripts/run_tests_one_by_one.py @@ -1,6 +1,7 @@ import sys import subprocess import time +import threading import argparse @@ -22,6 +23,9 @@ def valid_timeout(value): parser.add_argument('--no-assertions', action='store_false', help='Disable assertions') parser.add_argument('--time_execution', action='store_true', help='Measure and print the execution time of each test') parser.add_argument('--list', action='store_true', help='Print the list of tests to run') +parser.add_argument( + '--print-interval', action='store', help='Prints "Still running..." every N seconds', default=300.0, type=float +) parser.add_argument( '--timeout', action='store', @@ -29,6 +33,7 @@ def valid_timeout(value): default=3600, type=valid_timeout, ) +parser.add_argument('--valgrind', action='store_true', help='Run the tests with valgrind', default=False) args, extra_args = parser.parse_known_args() @@ -44,12 +49,12 @@ def valid_timeout(value): timeout = args.timeout # Use the '-l' parameter to output the list of tests to run -proc = subprocess.Popen([unittest_program, '-l'] + extra_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) -stdout = proc.stdout.read().decode('utf8') -stderr = proc.stderr.read().decode('utf8') -if proc.returncode is not None and proc.returncode != 0: +proc = subprocess.run([unittest_program, '-l'] + extra_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) +stdout = proc.stdout.decode('utf8').strip() +stderr = proc.stderr.decode('utf8').strip() +if len(stderr) > 0: print("Failed to run program " + unittest_program) - print(proc.returncode) + print("Returncode:", proc.returncode) print(stdout) print(stderr) exit(1) @@ -98,14 +103,35 @@ def parse_assertions(stdout): return "ERROR" +is_active = False + + +def print_interval_background(interval): + global is_active + current_ticker = 0.0 + while is_active: + time.sleep(0.1) + current_ticker += 0.1 + if current_ticker >= interval: + print("Still running...") + current_ticker = 0 + + for test_number, test_case in enumerate(test_cases): if not profile: print(f"[{test_number}/{test_count}]: {test_case}", end="", flush=True) + + # start the background thread + is_active = True + background_print_thread = threading.Thread(target=print_interval_background, args=[args.print_interval]) + background_print_thread.start() + start = time.time() try: - res = subprocess.run( - [unittest_program, test_case], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=timeout - ) + test_cmd = [unittest_program, test_case] + if args.valgrind: + test_cmd = ['valgrind'] + test_cmd + res = subprocess.run(test_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=timeout) except subprocess.TimeoutExpired as e: print(" (TIMED OUT)", flush=True) fail() @@ -115,6 +141,10 @@ def parse_assertions(stdout): stderr = res.stderr.decode('utf8') end = time.time() + # joint he background print thread + is_active = False + background_print_thread.join() + additional_data = "" if assertions: additional_data += " (" + parse_assertions(stdout) + ")" diff --git a/scripts/sqllogictest/result.py b/scripts/sqllogictest/result.py index f95f4021364..e71fc3fc653 100644 --- a/scripts/sqllogictest/result.py +++ b/scripts/sqllogictest/result.py @@ -432,24 +432,31 @@ def connect(self) -> SQLLogicConnectionPool: return SQLLogicConnectionPool(self.database.cursor()) +def is_regex(input: str) -> bool: + return input.startswith(":") or input.startswith(":") + + +def matches_regex(input: str, actual_str: str) -> bool: + if input.startswith(":"): + should_match = True + regex_str = input.replace(":", "") + else: + should_match = False + regex_str = input.replace(":", "") + re_options = re.DOTALL + re_pattern = re.compile(regex_str, re_options) + regex_matches = bool(re_pattern.fullmatch(actual_str)) + return regex_matches == should_match + + def compare_values(result: QueryResult, actual_str, expected_str, current_column): error = False if actual_str == expected_str: return True - if expected_str.startswith(":") or expected_str.startswith(":"): - if expected_str.startswith(":"): - should_match = True - regex_str = expected_str.replace(":", "") - else: - should_match = False - regex_str = expected_str.replace(":", "") - re_options = re.DOTALL - re_pattern = re.compile(regex_str, re_options) - regex_matches = bool(re_pattern.fullmatch(actual_str)) - if regex_matches == should_match: - return True + if is_regex(expected_str): + return matches_regex(expected_str, actual_str) sql_type = result.types[current_column] @@ -779,6 +786,7 @@ def execute_load(self, load: Load): self.runner.delete_database(dbpath) else: dbpath = "" + self.runner.loaded_databases.add(dbpath) # set up the config file additional_config = {} @@ -969,13 +977,19 @@ def execute_statement(self, statement: Statement): if expected_result.lines == None: return expected = '\n'.join(expected_result.lines) - # Sanitize the expected error - if expected.startswith('Dependency Error: '): - expected = expected.split('Dependency Error: ')[1] - if expected not in str(e): - self.fail( - f"Query failed, but did not produce the right error: {expected}\nInstead it produced: {str(e)}" - ) + if is_regex(expected): + if not matches_regex(expected, str(e)): + self.fail( + f"Query failed, but did not produce the right error: {expected}\nInstead it produced: {str(e)}" + ) + else: + # Sanitize the expected error + if expected.startswith('Dependency Error: '): + expected = expected.split('Dependency Error: ')[1] + if expected not in str(e): + self.fail( + f"Query failed, but did not produce the right error: {expected}\nInstead it produced: {str(e)}" + ) def check_require(self, statement: Require) -> RequireResult: not_an_extension = [ @@ -1115,7 +1129,10 @@ def update_value(context: SQLLogicContext) -> Generator[Any, Any, Any]: context.remove_keyword(key) loop_context = SQLLogicContext(self.pool, self.runner, statements, self.keywords.copy(), update_value) - loop_context.execute() + try: + loop_context.execute() + except TestException: + self.error = loop_context.error else: contexts: Dict[Tuple[str, int], Any] = {} for val in range(loop.start, loop.end): @@ -1247,6 +1264,8 @@ def execute(self): if self.runner.skip_active() and statement.__class__ != Unskip: # Keep skipping until Unskip is found continue + if statement.get_decorators() != []: + self.skiptest("Decorators are not supported yet") method = self.STATEMENTS.get(statement.__class__) if not method: self.skiptest("Not supported by the runner") diff --git a/scripts/test_block_sizes.py b/scripts/test_block_sizes.py index 6f4dbc2fcc4..41db6646355 100644 --- a/scripts/test_block_sizes.py +++ b/scripts/test_block_sizes.py @@ -1,6 +1,4 @@ import os -import re -from python_helpers import open_utf8 def execute_system_command(cmd): @@ -11,14 +9,6 @@ def execute_system_command(cmd): raise Exception -def replace_in_file(fname, regex, replace): - with open_utf8(fname, 'r') as f: - contents = f.read() - contents = re.sub(regex, replace, contents) - with open_utf8(fname, 'w+') as f: - f.write(contents) - - current_dir = os.getcwd() build_dir = os.path.join(os.getcwd(), 'build', 'release') @@ -28,14 +18,8 @@ def replace_in_file(fname, regex, replace): print("TESTING BLOCK_ALLOC_SIZE=%d" % (block_size,)) print("TESTING STANDARD_VECTOR_SIZE") -replace_in_file( - 'src/include/duckdb/storage/storage_info.hpp', - r'constexpr static idx_t BLOCK_ALLOC_SIZE = \w+', - 'constexpr static idx_t BLOCK_ALLOC_SIZE = %d' % (block_size,), -) - execute_system_command('rm -rf build') -execute_system_command('make relassert') +execute_system_command(f'BLOCK_ALLOC_SIZE={block_size} make relassert') execute_system_command('build/relassert/test/unittest') execute_system_command('build/relassert/test/unittest "test/sql/storage/*"') @@ -45,12 +29,6 @@ def replace_in_file(fname, regex, replace): print("TESTING BLOCK_ALLOC_SIZE=%d" % (block_size,)) print("TESTING STANDARD_VECTOR_SIZE=%d" % (vector_size,)) -replace_in_file( - 'src/include/duckdb/common/vector_size.hpp', - r'#define STANDARD_VECTOR_SIZE \w+', - '#define STANDARD_VECTOR_SIZE %d' % (vector_size,), -) - execute_system_command('rm -rf build') -execute_system_command('make release') +execute_system_command(f'BLOCK_ALLOC_SIZE={block_size} STANDARD_VECTOR_SIZE={vector_size} make release') execute_system_command('build/release/test/unittest') diff --git a/scripts/test_docker_images.sh b/scripts/test_docker_images.sh index 3b180e96378..ef8e993dae2 100755 --- a/scripts/test_docker_images.sh +++ b/scripts/test_docker_images.sh @@ -1,11 +1,21 @@ #!/usr/bin/env bash + +TEST="./build/release/duckdb -c 'PRAGMA platform;' && make clean && echo 'DOCKER TEST RESULT: SUCCESS' || (echo 'DOCKER TEST RESULT: FAILURE' && make clean)" + make clean -docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb amazonlinux:2 <<< "yum install g++ git make cmake ninja-build -y && GEN=ninja make && make clean" 2>&1 -docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb amazonlinux:latest <<< "yum install clang git make cmake ninja-build -y && GEN=ninja make && make clean" 2>&1 -docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb alpine:latest <<< "apk add g++ git make cmake ninja && GEN=ninja make && make clean" 2>&1 -docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb alpine:latest <<< "apk add g++ git make cmake ninja python3 && GEN=ninja make && make clean" 2>&1 -docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb alpine:latest <<< "apk add g++ git make cmake ninja && CXX_STANDARD=23 GEN=ninja make && make clean" 2>&1 -docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb ubuntu:20.04 <<< "apt-get update && export DEBIAN_FRONTEND=noninteractive && apt-get install g++ git make cmake ninja-build -y && GEN=ninja make && make clean" 2>&1 -docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb ubuntu:devel <<< "apt-get update && export DEBIAN_FRONTEND=noninteractive && apt-get install g++ git make cmake ninja-build -y && GEN=ninja make && make clean" 2>&1 -docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb centos <<< "sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* && yum install git make cmake clang -y && make && make clean" 2>&1 + +# Currently not working due to cmake version being too low +# docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb amazonlinux:2 <<< "yum install gcc gcc-c++ git make cmake ninja-build -y && GEN=ninja make && $TEST" 2>&1 + +docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb alpine:latest <<< "apk add g++ git make cmake ninja python3 && cmake -Bbuild . && cmake --build build && cmake --install build && g++ -std=c++11 examples/embedded-c++/main.cpp" +docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb amazonlinux:latest <<< "yum install clang git make cmake ninja-build -y && GEN=ninja make && $TEST" 2>&1 +docker run -i --platform linux/arm64 --rm -v $(pwd):/duckdb --workdir /duckdb alpine:latest <<< "apk add g++ git make cmake ninja && GEN=ninja make && $TEST" 2>&1 +docker run -i --platform linux/amd64 --rm -v $(pwd):/duckdb --workdir /duckdb alpine:latest <<< "apk add g++ git make cmake ninja && GEN=ninja make && $TEST" 2>&1 +docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb alpine:latest <<< "apk add g++ git make cmake ninja && GEN=ninja make && $TEST" 2>&1 +docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb alpine:latest <<< "apk add g++ git make cmake ninja python3 && GEN=ninja make && $TEST" 2>&1 +docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb alpine:latest <<< "apk add g++ git make cmake ninja && CXX_STANDARD=23 GEN=ninja make && $TEST" 2>&1 +docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb ubuntu:20.04 <<< "apt-get update && export DEBIAN_FRONTEND=noninteractive && apt-get install g++ git make cmake ninja-build -y && GEN=ninja make && $TEST" 2>&1 +docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb ubuntu:devel <<< "apt-get update && export DEBIAN_FRONTEND=noninteractive && apt-get install g++ git make cmake ninja-build -y && GEN=ninja make && $TEST" 2>&1 +docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb centos <<< "sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* && yum install git make cmake clang -y && make && $TEST" 2>&1 +docker run -i --rm -v $(pwd):/duckdb --workdir /duckdb fedora <<< "dnf install make cmake ninja-build gcc g++ -y && make && $TEST" 2>&1 diff --git a/scripts/test_vector_sizes.py b/scripts/test_vector_sizes.py index 49e044298aa..77ee50c27da 100644 --- a/scripts/test_vector_sizes.py +++ b/scripts/test_vector_sizes.py @@ -1,5 +1,4 @@ -import os, sys, re -from python_helpers import open_utf8 +import os vector_sizes = [2] @@ -12,24 +11,11 @@ def execute_system_command(cmd): retcode = os.system(cmd) print(retcode) if retcode != 0: - raise Exception - - -def replace_in_file(fname, regex, replace): - with open_utf8(fname, 'r') as f: - contents = f.read() - contents = re.sub(regex, replace, contents) - with open_utf8(fname, 'w+') as f: - f.write(contents) + raise Exception(f"Failed to run command {cmd} - exit code {retcode}") for vector_size in vector_sizes: print("TESTING STANDARD_VECTOR_SIZE=%d" % (vector_size,)) - replace_in_file( - 'src/include/duckdb/common/vector_size.hpp', - r'#define STANDARD_VECTOR_SIZE \w+', - '#define STANDARD_VECTOR_SIZE %d' % (vector_size,), - ) execute_system_command('rm -rf build') - execute_system_command('make relassert') + execute_system_command(f'STANDARD_VECTOR_SIZE={vector_size} make relassert') execute_system_command('python3 scripts/run_tests_one_by_one.py build/relassert/test/unittest --no-exit') diff --git a/scripts/verify_enum_integrity.py b/scripts/verify_enum_integrity.py index 89e5283d772..cdfb2570072 100644 --- a/scripts/verify_enum_integrity.py +++ b/scripts/verify_enum_integrity.py @@ -1,49 +1,50 @@ -import clang.cindex +from cxxheaderparser.parser import CxxParser, ParserOptions +from cxxheaderparser.visitor import CxxVisitor +from cxxheaderparser.preprocessor import make_pcpp_preprocessor +from cxxheaderparser.parserstate import NamespaceBlockState +from cxxheaderparser.types import EnumDecl import textwrap import os -from typing import Optional -def visit_enum(cursor): - enum_name = cursor.spelling +class Visitor: + def on_enum(self, state: NamespaceBlockState, cursor: EnumDecl) -> None: + enum_name = cursor.typename.segments[0].format() + if '<' in enum_name: + raise Exception( + "Enum '{}' is an anonymous enum, please name it\n".format(cursor.doxygen[3:] if cursor.doxygen else '') + ) - enum_constants = dict() - for enum_const in cursor.get_children(): - if enum_const.kind == clang.cindex.CursorKind.ENUM_CONSTANT_DECL: - name = enum_const.spelling - tokens = enum_const.get_tokens() - if len(list(tokens)) == 1: + enum_constants = dict() + for enum_const in cursor.values: + name = enum_const.name.format() + if enum_const.value is None: raise Exception(f"Enum constant '{name}' in '{enum_name}' does not have an explicit value assignment.") - value = enum_const.enum_value + value = enum_const.value.format() if value in enum_constants: other_constant = enum_constants[value] error = f""" - Enum '{enum_name}' contains a duplicate value: - Value {value} is defined for both '{other_constant}' and '{name}' - """ + Enum '{enum_name}' contains a duplicate value: + Value {value} is defined for both '{other_constant}' and '{name}' + """ error = textwrap.dedent(error) raise Exception(error) enum_constants[value] = name - print(f"Succesfully verified the integrity of enum {enum_name} ({len(enum_constants)} entries)") + print(f"Succesfully verified the integrity of enum {enum_name} ({len(enum_constants)} entries)") + + def __getattr__(self, name): + return lambda *args, **kwargs: True def parse_enum(file_path): # Create index - index = clang.cindex.Index.create() - - # Parse the file - tu = index.parse(file_path) - - # Traverse the AST - for cursor in tu.cursor.walk_preorder(): - try: - kind = cursor.kind - is_enum = kind == clang.cindex.CursorKind.ENUM_DECL - except: - is_enum = False - if not is_enum: - continue - visit_enum(cursor) + parser = CxxParser( + file_path, + None, + visitor=Visitor(), + options=ParserOptions(preprocessor=make_pcpp_preprocessor()), + ) + parser.parse() if __name__ == "__main__": diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 21f47240848..06c0c9a0961 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -91,7 +91,8 @@ else() duckdb_hyperloglog duckdb_fastpforlib duckdb_skiplistlib - duckdb_mbedtls) + duckdb_mbedtls + duckdb_yyjson) add_library(duckdb SHARED ${ALL_OBJECT_FILES}) target_link_libraries(duckdb ${DUCKDB_LINK_LIBS}) @@ -115,7 +116,8 @@ else() DIRECTORY "${PROJECT_SOURCE_DIR}/src/include/duckdb" DESTINATION "${INSTALL_INCLUDE_DIR}" FILES_MATCHING - PATTERN "*.hpp") + PATTERN "*.hpp" + PATTERN "*.ipp") install(FILES "${PROJECT_SOURCE_DIR}/src/include/duckdb.hpp" "${PROJECT_SOURCE_DIR}/src/include/duckdb.h" DESTINATION "${INSTALL_INCLUDE_DIR}") diff --git a/src/catalog/CMakeLists.txt b/src/catalog/CMakeLists.txt index 0536fae3bdd..4a8a8e3e1a6 100644 --- a/src/catalog/CMakeLists.txt +++ b/src/catalog/CMakeLists.txt @@ -10,6 +10,7 @@ add_library_unity( duckdb_catalog OBJECT catalog_entry.cpp + catalog_entry_retriever.cpp catalog.cpp catalog_search_path.cpp catalog_set.cpp diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 775af179588..4d334a4d19e 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -280,14 +280,13 @@ optional_ptr Catalog::CreateCollation(CatalogTransaction transacti // Index //===--------------------------------------------------------------------===// optional_ptr Catalog::CreateIndex(CatalogTransaction transaction, CreateIndexInfo &info) { - auto &context = transaction.GetContext(); - return CreateIndex(context, info); + auto &schema = GetSchema(transaction, info.schema); + auto &table = schema.GetEntry(transaction, CatalogType::TABLE_ENTRY, info.table)->Cast(); + return schema.CreateIndex(transaction, info, table); } optional_ptr Catalog::CreateIndex(ClientContext &context, CreateIndexInfo &info) { - auto &schema = GetSchema(context, info.schema); - auto &table = GetEntry(context, schema.name, info.table); - return schema.CreateIndex(context, info, table); + return CreateIndex(GetCatalogTransaction(context), info); } //===--------------------------------------------------------------------===// @@ -760,19 +759,6 @@ CatalogEntryLookup Catalog::TryLookupEntry(ClientContext &context, CatalogType t return Catalog::TryLookupEntry(context, lookups, type, name, if_not_found, error_context); } -CatalogEntry &Catalog::GetEntry(ClientContext &context, const string &schema, const string &name) { - vector entry_types {CatalogType::TABLE_ENTRY, CatalogType::SEQUENCE_ENTRY}; - - for (auto entry_type : entry_types) { - auto result = GetEntry(context, entry_type, schema, name, OnEntryNotFound::RETURN_NULL); - if (result) { - return *result; - } - } - - throw CatalogException("CatalogElement \"%s.%s\" does not exist!", schema, name); -} - optional_ptr Catalog::GetEntry(ClientContext &context, CatalogType type, const string &schema_name, const string &name, OnEntryNotFound if_not_found, QueryErrorContext error_context) { @@ -840,21 +826,6 @@ optional_ptr Catalog::GetSchema(ClientContext &context, cons return nullptr; } -LogicalType Catalog::GetType(ClientContext &context, const string &schema, const string &name, - OnEntryNotFound if_not_found) { - auto type_entry = GetEntry(context, schema, name, if_not_found); - if (!type_entry) { - return LogicalType::INVALID; - } - return type_entry->user_type; -} - -LogicalType Catalog::GetType(ClientContext &context, const string &catalog_name, const string &schema, - const string &name) { - auto &type_entry = Catalog::GetEntry(context, catalog_name, schema, name); - return type_entry.user_type; -} - vector> Catalog::GetSchemas(ClientContext &context) { vector> schemas; ScanSchemas(context, [&](SchemaCatalogEntry &entry) { schemas.push_back(entry); }); @@ -912,15 +883,24 @@ vector> Catalog::GetAllSchemas(ClientContext &cont return result; } -void Catalog::Alter(ClientContext &context, AlterInfo &info) { +void Catalog::Alter(CatalogTransaction transaction, AlterInfo &info) { ModifyCatalog(); - auto lookup = LookupEntry(context, info.GetCatalogType(), info.schema, info.name, info.if_not_found); - - if (!lookup.Found()) { - return; + if (transaction.HasContext()) { + auto lookup = + LookupEntry(transaction.GetContext(), info.GetCatalogType(), info.schema, info.name, info.if_not_found); + if (!lookup.Found()) { + return; + } + return lookup.schema->Alter(transaction, info); } - return lookup.schema->Alter(context, info); + D_ASSERT(info.if_not_found == OnEntryNotFound::THROW_EXCEPTION); + auto &schema = GetSchema(transaction, info.schema); + return schema.Alter(transaction, info); +} + +void Catalog::Alter(ClientContext &context, AlterInfo &info) { + Alter(GetCatalogTransaction(context), info); } vector Catalog::GetMetadataInfo(ClientContext &context) { diff --git a/src/catalog/catalog_entry.cpp b/src/catalog/catalog_entry.cpp index a7ca7265303..aa05a866670 100644 --- a/src/catalog/catalog_entry.cpp +++ b/src/catalog/catalog_entry.cpp @@ -26,6 +26,13 @@ unique_ptr CatalogEntry::AlterEntry(ClientContext &context, AlterI throw InternalException("Unsupported alter type for catalog entry!"); } +unique_ptr CatalogEntry::AlterEntry(CatalogTransaction transaction, AlterInfo &info) { + if (!transaction.context) { + throw InternalException("Cannot AlterEntry without client context"); + } + return AlterEntry(*transaction.context, info); +} + void CatalogEntry::UndoAlter(ClientContext &context, AlterInfo &info) { } diff --git a/src/catalog/catalog_entry/duck_index_entry.cpp b/src/catalog/catalog_entry/duck_index_entry.cpp index 7230179ba2f..b6da4918f6e 100644 --- a/src/catalog/catalog_entry/duck_index_entry.cpp +++ b/src/catalog/catalog_entry/duck_index_entry.cpp @@ -4,15 +4,15 @@ namespace duckdb { -IndexDataTableInfo::IndexDataTableInfo(shared_ptr &info_p, const string &index_name_p) - : info(info_p), index_name(index_name_p) { +IndexDataTableInfo::IndexDataTableInfo(shared_ptr info_p, const string &index_name_p) + : info(std::move(info_p)), index_name(index_name_p) { } IndexDataTableInfo::~IndexDataTableInfo() { if (!info) { return; } - info->indexes.RemoveIndex(index_name); + info->GetIndexes().RemoveIndex(index_name); } DuckIndexEntry::DuckIndexEntry(Catalog &catalog, SchemaCatalogEntry &schema, CreateIndexInfo &info) @@ -38,11 +38,11 @@ unique_ptr DuckIndexEntry::Copy(ClientContext &context) const { } string DuckIndexEntry::GetSchemaName() const { - return GetDataTableInfo().schema; + return GetDataTableInfo().GetSchemaName(); } string DuckIndexEntry::GetTableName() const { - return GetDataTableInfo().table; + return GetDataTableInfo().GetTableName(); } DataTableInfo &DuckIndexEntry::GetDataTableInfo() const { @@ -51,7 +51,7 @@ DataTableInfo &DuckIndexEntry::GetDataTableInfo() const { void DuckIndexEntry::CommitDrop() { D_ASSERT(info); - GetDataTableInfo().indexes.CommitDrop(name); + GetDataTableInfo().GetIndexes().CommitDrop(name); } } // namespace duckdb diff --git a/src/catalog/catalog_entry/duck_schema_entry.cpp b/src/catalog/catalog_entry/duck_schema_entry.cpp index ccdba5acbd0..06d7857ba0b 100644 --- a/src/catalog/catalog_entry/duck_schema_entry.cpp +++ b/src/catalog/catalog_entry/duck_schema_entry.cpp @@ -1,5 +1,6 @@ #include "duckdb/catalog/catalog_entry/duck_schema_entry.hpp" #include "duckdb/catalog/default/default_functions.hpp" +#include "duckdb/catalog/default/default_table_functions.hpp" #include "duckdb/catalog/default/default_types.hpp" #include "duckdb/catalog/default/default_views.hpp" #include "duckdb/catalog/catalog_entry/collate_catalog_entry.hpp" @@ -33,16 +34,17 @@ #include "duckdb/parser/parsed_data/create_type_info.hpp" #include "duckdb/parser/parsed_data/create_view_info.hpp" #include "duckdb/parser/parsed_data/drop_info.hpp" +#include "duckdb/transaction/meta_transaction.hpp" +#include "duckdb/main/attached_database.hpp" +#include "duckdb/transaction/duck_transaction.hpp" namespace duckdb { -static void FindForeignKeyInformation(CatalogEntry &entry, AlterForeignKeyType alter_fk_type, +static void FindForeignKeyInformation(TableCatalogEntry &table, AlterForeignKeyType alter_fk_type, vector> &fk_arrays) { - if (entry.type != CatalogType::TABLE_ENTRY) { - return; - } - auto &table_entry = entry.Cast(); - auto &constraints = table_entry.GetConstraints(); + auto &constraints = table.GetConstraints(); + auto &catalog = table.ParentCatalog(); + auto &name = table.name; for (idx_t i = 0; i < constraints.size(); i++) { auto &cond = constraints[i]; if (cond->type != ConstraintType::FOREIGN_KEY) { @@ -50,9 +52,9 @@ static void FindForeignKeyInformation(CatalogEntry &entry, AlterForeignKeyType a } auto &fk = cond->Cast(); if (fk.info.type == ForeignKeyType::FK_TYPE_FOREIGN_KEY_TABLE) { - AlterEntryData alter_data(entry.ParentCatalog().GetName(), fk.info.schema, fk.info.table, + AlterEntryData alter_data(catalog.GetName(), fk.info.schema, fk.info.table, OnEntryNotFound::THROW_EXCEPTION); - fk_arrays.push_back(make_uniq(std::move(alter_data), entry.name, fk.pk_columns, + fk_arrays.push_back(make_uniq(std::move(alter_data), name, fk.pk_columns, fk.fk_columns, fk.info.pk_keys, fk.info.fk_keys, alter_fk_type)); } else if (fk.info.type == ForeignKeyType::FK_TYPE_PRIMARY_KEY_TABLE && @@ -66,19 +68,20 @@ static void FindForeignKeyInformation(CatalogEntry &entry, AlterForeignKeyType a static void LazyLoadIndexes(ClientContext &context, CatalogEntry &entry) { if (entry.type == CatalogType::TABLE_ENTRY) { auto &table_entry = entry.Cast(); - table_entry.GetStorage().info->InitializeIndexes(context); + table_entry.GetStorage().InitializeIndexes(context); } else if (entry.type == CatalogType::INDEX_ENTRY) { auto &index_entry = entry.Cast(); auto &table_entry = Catalog::GetEntry(context, CatalogType::TABLE_ENTRY, index_entry.catalog.GetName(), index_entry.GetSchemaName(), index_entry.GetTableName()) .Cast(); - table_entry.GetStorage().info->InitializeIndexes(context); + table_entry.GetStorage().InitializeIndexes(context); } } DuckSchemaEntry::DuckSchemaEntry(Catalog &catalog, CreateSchemaInfo &info) : SchemaCatalogEntry(catalog, info), tables(catalog, make_uniq(catalog, *this)), - indexes(catalog), table_functions(catalog), copy_functions(catalog), pragma_functions(catalog), + indexes(catalog), table_functions(catalog, make_uniq(catalog, *this)), + copy_functions(catalog), pragma_functions(catalog), functions(catalog, make_uniq(catalog, *this)), sequences(catalog), collations(catalog), types(catalog, make_uniq(catalog, *this)) { } @@ -100,6 +103,17 @@ optional_ptr DuckSchemaEntry::AddEntryInternal(CatalogTransaction auto entry_type = entry->type; auto result = entry.get(); + if (transaction.context) { + auto &meta = MetaTransaction::Get(transaction.GetContext()); + auto modified_database = meta.ModifiedDatabase(); + auto &db = ParentCatalog().GetAttached(); + if (!db.IsTemporary() && !db.IsSystem()) { + if (!modified_database || !RefersToSameObject(*modified_database, ParentCatalog().GetAttached())) { + throw InternalException( + "DuckSchemaEntry::AddEntryInternal called but this database is not marked as modified"); + } + } + } // first find the set for this entry auto &set = GetCatalogSet(entry_type); dependencies.AddDependency(*this); @@ -107,10 +121,14 @@ optional_ptr DuckSchemaEntry::AddEntryInternal(CatalogTransaction // CREATE OR REPLACE: first try to drop the entry auto old_entry = set.GetEntry(transaction, entry_name); if (old_entry) { + if (dependencies.Contains(*old_entry)) { + throw CatalogException("CREATE OR REPLACE is not allowed to depend on itself"); + } if (old_entry->type != entry_type) { throw CatalogException("Existing object %s is of type %s, trying to replace with type %s", entry_name, CatalogTypeToString(old_entry->type), CatalogTypeToString(entry_type)); } + OnDropEntry(transaction, *old_entry); (void)set.DropEntry(transaction, entry_name, false, entry->internal); } } @@ -128,26 +146,25 @@ optional_ptr DuckSchemaEntry::AddEntryInternal(CatalogTransaction optional_ptr DuckSchemaEntry::CreateTable(CatalogTransaction transaction, BoundCreateTableInfo &info) { auto table = make_uniq(catalog, *this, info); - auto &storage = table->GetStorage(); - storage.info->cardinality = storage.GetTotalRows(); - - auto entry = AddEntryInternal(transaction, std::move(table), info.Base().on_conflict, info.dependencies); - if (!entry) { - return nullptr; - } // add a foreign key constraint in main key table if there is a foreign key constraint vector> fk_arrays; - FindForeignKeyInformation(*entry, AlterForeignKeyType::AFT_ADD, fk_arrays); + FindForeignKeyInformation(*table, AlterForeignKeyType::AFT_ADD, fk_arrays); for (idx_t i = 0; i < fk_arrays.size(); i++) { // alter primary key table auto &fk_info = *fk_arrays[i]; - catalog.Alter(transaction.GetContext(), fk_info); + Alter(transaction, fk_info); // make a dependency between this table and referenced table auto &set = GetCatalogSet(CatalogType::TABLE_ENTRY); info.dependencies.AddDependency(*set.GetEntry(transaction, fk_info.name)); } + + auto entry = AddEntryInternal(transaction, std::move(table), info.Base().on_conflict, info.dependencies); + if (!entry) { + return nullptr; + } + return entry; } @@ -159,7 +176,7 @@ optional_ptr DuckSchemaEntry::CreateFunction(CatalogTransaction tr if (current_entry) { // the current entry exists - alter it instead auto alter_info = info.GetAlterInfo(); - Alter(transaction.GetContext(), *alter_info); + Alter(transaction, *alter_info); return nullptr; } } @@ -197,7 +214,7 @@ optional_ptr DuckSchemaEntry::CreateFunction(CatalogTransaction tr optional_ptr DuckSchemaEntry::AddEntry(CatalogTransaction transaction, unique_ptr entry, OnCreateConflict on_conflict) { - LogicalDependencyList dependencies; + LogicalDependencyList dependencies = entry->dependencies; return AddEntryInternal(transaction, std::move(entry), on_conflict, dependencies); } @@ -216,19 +233,20 @@ optional_ptr DuckSchemaEntry::CreateView(CatalogTransaction transa return AddEntry(transaction, std::move(view), info.on_conflict); } -optional_ptr DuckSchemaEntry::CreateIndex(ClientContext &context, CreateIndexInfo &info, +optional_ptr DuckSchemaEntry::CreateIndex(CatalogTransaction transaction, CreateIndexInfo &info, TableCatalogEntry &table) { - LogicalDependencyList dependencies; - dependencies.AddDependency(table); + info.dependencies.AddDependency(table); // currently, we can not alter PK/FK/UNIQUE constraints // concurrency-safe name checks against other INDEX catalog entries happens in the catalog - if (!table.GetStorage().IndexNameIsUnique(info.index_name)) { + if (info.on_conflict != OnCreateConflict::IGNORE_ON_CONFLICT && + !table.GetStorage().IndexNameIsUnique(info.index_name)) { throw CatalogException("An index with the name " + info.index_name + " already exists!"); } auto index = make_uniq(catalog, *this, info); - return AddEntryInternal(GetCatalogTransaction(context), std::move(index), info.on_conflict, dependencies); + auto dependencies = index->dependencies; + return AddEntryInternal(transaction, std::move(index), info.on_conflict, dependencies); } optional_ptr DuckSchemaEntry::CreateCollation(CatalogTransaction transaction, CreateCollationInfo &info) { @@ -258,11 +276,10 @@ optional_ptr DuckSchemaEntry::CreatePragmaFunction(CatalogTransact return AddEntry(transaction, std::move(pragma_function), info.on_conflict); } -void DuckSchemaEntry::Alter(ClientContext &context, AlterInfo &info) { +void DuckSchemaEntry::Alter(CatalogTransaction transaction, AlterInfo &info) { CatalogType type = info.GetCatalogType(); auto &set = GetCatalogSet(type); - auto transaction = GetCatalogTransaction(context); if (info.type == AlterType::CHANGE_OWNERSHIP) { if (!set.AlterOwnership(transaction, info.Cast())) { throw CatalogException("Couldn't change ownership!"); @@ -303,10 +320,14 @@ void DuckSchemaEntry::DropEntry(ClientContext &context, DropInfo &info) { // if this is a index or table with indexes, initialize any unknown index instances LazyLoadIndexes(context, *existing_entry); - // if there is a foreign key constraint, get that information vector> fk_arrays; - FindForeignKeyInformation(*existing_entry, AlterForeignKeyType::AFT_DELETE, fk_arrays); + if (existing_entry->type == CatalogType::TABLE_ENTRY) { + // if there is a foreign key constraint, get that information + auto &table_entry = existing_entry->Cast(); + FindForeignKeyInformation(table_entry, AlterForeignKeyType::AFT_DELETE, fk_arrays); + } + OnDropEntry(transaction, *existing_entry); if (!set.DropEntry(transaction, info.name, info.cascade, info.allow_drop_internal)) { throw InternalException("Could not drop element because of an internal error"); } @@ -314,8 +335,21 @@ void DuckSchemaEntry::DropEntry(ClientContext &context, DropInfo &info) { // remove the foreign key constraint in main key table if main key table's name is valid for (idx_t i = 0; i < fk_arrays.size(); i++) { // alter primary key table - catalog.Alter(context, *fk_arrays[i]); + Alter(transaction, *fk_arrays[i]); + } +} + +void DuckSchemaEntry::OnDropEntry(CatalogTransaction transaction, CatalogEntry &entry) { + if (!transaction.transaction) { + return; } + if (entry.type != CatalogType::TABLE_ENTRY) { + return; + } + // if we have transaction local insertions for this table - clear them + auto &table_entry = entry.Cast(); + auto &local_storage = LocalStorage::Get(transaction.transaction->Cast()); + local_storage.DropTable(table_entry.GetStorage()); } optional_ptr DuckSchemaEntry::GetEntry(CatalogTransaction transaction, CatalogType type, diff --git a/src/catalog/catalog_entry/duck_table_entry.cpp b/src/catalog/catalog_entry/duck_table_entry.cpp index 5476b80e49a..144fe314dae 100644 --- a/src/catalog/catalog_entry/duck_table_entry.cpp +++ b/src/catalog/catalog_entry/duck_table_entry.cpp @@ -50,7 +50,7 @@ void AddDataTableIndex(DataTable &storage, const ColumnList &columns, const vect if (!info.IsValid() && !info.name.empty() && !storage.IsRoot()) { throw TransactionException("Transaction conflict: cannot add an index to a table that has been altered!"); } - storage.info->indexes.AddIndex(std::move(art)); + storage.AddIndex(std::move(art)); } void AddDataTableIndex(DataTable &storage, const ColumnList &columns, vector &keys, @@ -153,7 +153,7 @@ DuckTableEntry::DuckTableEntry(Catalog &catalog, SchemaCatalogEntry &schema, Bou } if (!info.indexes.empty()) { - storage->info->index_storage_infos = info.indexes; + storage->SetIndexStorageInfo(std::move(info.indexes)); } } @@ -168,6 +168,23 @@ unique_ptr DuckTableEntry::GetStatistics(ClientContext &context, return storage->GetStatistics(context, column.StorageOid()); } +unique_ptr DuckTableEntry::AlterEntry(CatalogTransaction transaction, AlterInfo &info) { + if (transaction.context) { + return AlterEntry(*transaction.context, info); + } + if (info.type == AlterType::ALTER_TABLE) { + auto &table_info = info.Cast(); + if (table_info.alter_table_type == AlterTableType::FOREIGN_KEY_CONSTRAINT) { + auto &foreign_key_constraint_info = table_info.Cast(); + if (foreign_key_constraint_info.type == AlterForeignKeyType::AFT_ADD) { + // for checkpoint loading we support adding foreign key constraints without a client context + return AddForeignKeyConstraint(nullptr, foreign_key_constraint_info); + } + } + } + return CatalogEntry::AlterEntry(transaction, info); +} + unique_ptr DuckTableEntry::AlterEntry(ClientContext &context, AlterInfo &info) { D_ASSERT(!internal); @@ -190,7 +207,7 @@ unique_ptr DuckTableEntry::AlterEntry(ClientContext &context, Alte auto &rename_info = table_info.Cast(); auto copied_table = Copy(context); copied_table->name = rename_info.new_table_name; - storage->info->table = rename_info.new_table_name; + storage->SetTableName(rename_info.new_table_name); return copied_table; } case AlterTableType::ADD_COLUMN: { @@ -236,7 +253,7 @@ void DuckTableEntry::UndoAlter(ClientContext &context, AlterInfo &info) { auto &table_info = info.Cast(); switch (table_info.alter_table_type) { case AlterTableType::RENAME_TABLE: { - storage->info->table = this->name; + storage->SetTableName(this->name); break; default: break; @@ -263,6 +280,7 @@ unique_ptr DuckTableEntry::RenameColumn(ClientContext &context, Re auto create_info = make_uniq(schema, name); create_info->temporary = temporary; create_info->comment = comment; + create_info->tags = tags; for (auto &col : columns.Logical()) { auto copy = col.Copy(); if (rename_idx == col.Logical()) { @@ -336,6 +354,7 @@ unique_ptr DuckTableEntry::AddColumn(ClientContext &context, AddCo auto create_info = make_uniq(schema, name); create_info->temporary = temporary; create_info->comment = comment; + create_info->tags = tags; for (auto &col : columns.Logical()) { create_info->columns.AddColumn(col.Copy()); @@ -343,14 +362,14 @@ unique_ptr DuckTableEntry::AddColumn(ClientContext &context, AddCo for (auto &constraint : constraints) { create_info->constraints.push_back(constraint->Copy()); } - Binder::BindLogicalType(context, info.new_column.TypeMutable(), &catalog, schema.name); + auto binder = Binder::CreateBinder(context); + binder->BindLogicalType(info.new_column.TypeMutable(), &catalog, schema.name); info.new_column.SetOid(columns.LogicalColumnCount()); info.new_column.SetStorageOid(columns.PhysicalColumnCount()); auto col = info.new_column.Copy(); create_info->columns.AddColumn(std::move(col)); - auto binder = Binder::CreateBinder(context); vector> bound_defaults; auto bound_create_info = binder->BindCreateTableInfo(std::move(create_info), schema, bound_defaults); auto new_storage = make_shared_ptr(context, *storage, info.new_column, *bound_defaults.back()); @@ -458,6 +477,7 @@ unique_ptr DuckTableEntry::RemoveColumn(ClientContext &context, Re auto create_info = make_uniq(schema, name); create_info->temporary = temporary; create_info->comment = comment; + create_info->tags = tags; logical_index_set_t removed_columns; if (column_dependency_manager.HasDependents(removed_index)) { @@ -499,6 +519,7 @@ unique_ptr DuckTableEntry::RemoveColumn(ClientContext &context, Re unique_ptr DuckTableEntry::SetDefault(ClientContext &context, SetDefaultInfo &info) { auto create_info = make_uniq(schema, name); create_info->comment = comment; + create_info->tags = tags; auto default_idx = GetColumnIndex(info.column_name); if (default_idx.index == COLUMN_IDENTIFIER_ROW_ID) { throw CatalogException("Cannot SET DEFAULT for rowid column"); @@ -531,6 +552,7 @@ unique_ptr DuckTableEntry::SetNotNull(ClientContext &context, SetN auto create_info = make_uniq(schema, name); create_info->comment = comment; + create_info->tags = tags; create_info->columns = columns.Copy(); auto not_null_idx = GetColumnIndex(info.column_name); @@ -568,6 +590,7 @@ unique_ptr DuckTableEntry::SetNotNull(ClientContext &context, SetN unique_ptr DuckTableEntry::DropNotNull(ClientContext &context, DropNotNullInfo &info) { auto create_info = make_uniq(schema, name); create_info->comment = comment; + create_info->tags = tags; create_info->columns = columns.Copy(); auto not_null_idx = GetColumnIndex(info.column_name); @@ -589,13 +612,14 @@ unique_ptr DuckTableEntry::DropNotNull(ClientContext &context, Dro } unique_ptr DuckTableEntry::ChangeColumnType(ClientContext &context, ChangeColumnTypeInfo &info) { - Binder::BindLogicalType(context, info.target_type, &catalog, schema.name); + auto binder = Binder::CreateBinder(context); + binder->BindLogicalType(info.target_type, &catalog, schema.name); auto change_idx = GetColumnIndex(info.column_name); auto create_info = make_uniq(schema, name); create_info->temporary = temporary; create_info->comment = comment; + create_info->tags = tags; - auto binder = Binder::CreateBinder(context); auto bound_constraints = binder->BindConstraints(constraints, name, columns); for (auto &col : columns.Logical()) { auto copy = col.Copy(); @@ -681,6 +705,7 @@ unique_ptr DuckTableEntry::ChangeColumnType(ClientContext &context unique_ptr DuckTableEntry::SetColumnComment(ClientContext &context, SetColumnCommentInfo &info) { auto create_info = make_uniq(schema, name); create_info->comment = comment; + create_info->tags = tags; auto default_idx = GetColumnIndex(info.column_name); if (default_idx.index == COLUMN_IDENTIFIER_ROW_ID) { throw CatalogException("Cannot SET DEFAULT for rowid column"); @@ -705,11 +730,13 @@ unique_ptr DuckTableEntry::SetColumnComment(ClientContext &context return make_uniq(catalog, schema, *bound_create_info, storage); } -unique_ptr DuckTableEntry::AddForeignKeyConstraint(ClientContext &context, AlterForeignKeyInfo &info) { +unique_ptr DuckTableEntry::AddForeignKeyConstraint(optional_ptr context, + AlterForeignKeyInfo &info) { D_ASSERT(info.type == AlterForeignKeyType::AFT_ADD); auto create_info = make_uniq(schema, name); create_info->temporary = temporary; create_info->comment = comment; + create_info->tags = tags; create_info->columns = columns.Copy(); for (idx_t i = 0; i < constraints.size(); i++) { @@ -724,8 +751,13 @@ unique_ptr DuckTableEntry::AddForeignKeyConstraint(ClientContext & create_info->constraints.push_back( make_uniq(info.pk_columns, info.fk_columns, std::move(fk_info))); - auto binder = Binder::CreateBinder(context); - auto bound_create_info = binder->BindCreateTableInfo(std::move(create_info), schema); + unique_ptr bound_create_info; + if (context) { + auto binder = Binder::CreateBinder(*context); + bound_create_info = binder->BindCreateTableInfo(std::move(create_info), schema); + } else { + bound_create_info = Binder::BindCreateTableCheckpoint(std::move(create_info), schema); + } return make_uniq(catalog, schema, *bound_create_info, storage); } @@ -735,6 +767,7 @@ unique_ptr DuckTableEntry::DropForeignKeyConstraint(ClientContext auto create_info = make_uniq(schema, name); create_info->temporary = temporary; create_info->comment = comment; + create_info->tags = tags; create_info->columns = columns.Copy(); for (idx_t i = 0; i < constraints.size(); i++) { @@ -757,6 +790,7 @@ unique_ptr DuckTableEntry::DropForeignKeyConstraint(ClientContext unique_ptr DuckTableEntry::Copy(ClientContext &context) const { auto create_info = make_uniq(schema, name); create_info->comment = comment; + create_info->tags = tags; create_info->columns = columns.Copy(); for (idx_t i = 0; i < constraints.size(); i++) { @@ -771,7 +805,7 @@ unique_ptr DuckTableEntry::Copy(ClientContext &context) const { void DuckTableEntry::SetAsRoot() { storage->SetAsRoot(); - storage->info->table = name; + storage->SetTableName(name); } void DuckTableEntry::CommitAlter(string &column_name) { @@ -808,18 +842,7 @@ vector DuckTableEntry::GetColumnSegmentInfo() { } TableStorageInfo DuckTableEntry::GetStorageInfo(ClientContext &context) { - TableStorageInfo result; - result.cardinality = storage->info->cardinality.load(); - storage->info->indexes.Scan([&](Index &index) { - IndexInfo info; - info.is_primary = index.IsPrimary(); - info.is_unique = index.IsUnique() || info.is_primary; - info.is_foreign = index.IsForeign(); - info.column_set = index.column_id_set; - result.index_info.push_back(std::move(info)); - return false; - }); - return result; + return storage->GetStorageInfo(); } } // namespace duckdb diff --git a/src/catalog/catalog_entry/index_catalog_entry.cpp b/src/catalog/catalog_entry/index_catalog_entry.cpp index 63ae552e17a..9e704dcdb7a 100644 --- a/src/catalog/catalog_entry/index_catalog_entry.cpp +++ b/src/catalog/catalog_entry/index_catalog_entry.cpp @@ -7,6 +7,7 @@ IndexCatalogEntry::IndexCatalogEntry(Catalog &catalog, SchemaCatalogEntry &schem index_type(info.index_type), index_constraint_type(info.constraint_type), column_ids(info.column_ids) { this->temporary = info.temporary; + this->dependencies = info.dependencies; this->comment = info.comment; } @@ -21,6 +22,7 @@ unique_ptr IndexCatalogEntry::GetInfo() const { result->index_type = index_type; result->constraint_type = index_constraint_type; result->column_ids = column_ids; + result->dependencies = dependencies; for (auto &expr : expressions) { result->expressions.push_back(expr->Copy()); @@ -30,6 +32,7 @@ unique_ptr IndexCatalogEntry::GetInfo() const { } result->comment = comment; + result->tags = tags; return std::move(result); } diff --git a/src/catalog/catalog_entry/macro_catalog_entry.cpp b/src/catalog/catalog_entry/macro_catalog_entry.cpp index 3ac57460b62..473b07f449a 100644 --- a/src/catalog/catalog_entry/macro_catalog_entry.cpp +++ b/src/catalog/catalog_entry/macro_catalog_entry.cpp @@ -11,7 +11,9 @@ MacroCatalogEntry::MacroCatalogEntry(Catalog &catalog, SchemaCatalogEntry &schem function(std::move(info.function)) { this->temporary = info.temporary; this->internal = info.internal; + this->dependencies = info.dependencies; this->comment = info.comment; + this->tags = info.tags; } ScalarMacroCatalogEntry::ScalarMacroCatalogEntry(Catalog &catalog, SchemaCatalogEntry &schema, CreateMacroInfo &info) @@ -42,7 +44,9 @@ unique_ptr MacroCatalogEntry::GetInfo() const { info->schema = schema.name; info->name = name; info->function = function->Copy(); + info->dependencies = dependencies; info->comment = comment; + info->tags = tags; return std::move(info); } diff --git a/src/catalog/catalog_entry/schema_catalog_entry.cpp b/src/catalog/catalog_entry/schema_catalog_entry.cpp index 0f7e1dfc82c..5789cff8dbe 100644 --- a/src/catalog/catalog_entry/schema_catalog_entry.cpp +++ b/src/catalog/catalog_entry/schema_catalog_entry.cpp @@ -14,12 +14,18 @@ SchemaCatalogEntry::SchemaCatalogEntry(Catalog &catalog, CreateSchemaInfo &info) : InCatalogEntry(CatalogType::SCHEMA_ENTRY, catalog, info.schema) { this->internal = info.internal; this->comment = info.comment; + this->tags = info.tags; } CatalogTransaction SchemaCatalogEntry::GetCatalogTransaction(ClientContext &context) { return CatalogTransaction(catalog, context); } +optional_ptr SchemaCatalogEntry::CreateIndex(ClientContext &context, CreateIndexInfo &info, + TableCatalogEntry &table) { + return CreateIndex(GetCatalogTransaction(context), info, table); +} + SimilarCatalogEntry SchemaCatalogEntry::GetSimilarEntry(CatalogTransaction transaction, CatalogType type, const string &name) { SimilarCatalogEntry result; @@ -37,6 +43,7 @@ unique_ptr SchemaCatalogEntry::GetInfo() const { auto result = make_uniq(); result->schema = name; result->comment = comment; + result->tags = tags; return std::move(result); } diff --git a/src/catalog/catalog_entry/sequence_catalog_entry.cpp b/src/catalog/catalog_entry/sequence_catalog_entry.cpp index 5606ddc8ba8..085048b0aec 100644 --- a/src/catalog/catalog_entry/sequence_catalog_entry.cpp +++ b/src/catalog/catalog_entry/sequence_catalog_entry.cpp @@ -22,6 +22,7 @@ SequenceCatalogEntry::SequenceCatalogEntry(Catalog &catalog, SchemaCatalogEntry : StandardEntry(CatalogType::SEQUENCE_ENTRY, schema, catalog, info.name), data(info) { this->temporary = info.temporary; this->comment = info.comment; + this->tags = info.tags; } unique_ptr SequenceCatalogEntry::Copy(ClientContext &context) const { @@ -73,7 +74,7 @@ int64_t SequenceCatalogEntry::NextValue(DuckTransaction &transaction) { data.last_value = result; data.usage_count++; if (!temporary) { - transaction.sequence_usage[this] = SequenceValue(data.usage_count, data.counter); + transaction.PushSequenceUsage(*this, data); } return result; } @@ -98,7 +99,9 @@ unique_ptr SequenceCatalogEntry::GetInfo() const { result->max_value = seq_data.max_value; result->start_value = seq_data.counter; result->cycle = seq_data.cycle; + result->dependencies = dependencies; result->comment = comment; + result->tags = tags; return std::move(result); } diff --git a/src/catalog/catalog_entry/table_catalog_entry.cpp b/src/catalog/catalog_entry/table_catalog_entry.cpp index 5a72cc801a2..33f6c1e4f15 100644 --- a/src/catalog/catalog_entry/table_catalog_entry.cpp +++ b/src/catalog/catalog_entry/table_catalog_entry.cpp @@ -23,7 +23,9 @@ TableCatalogEntry::TableCatalogEntry(Catalog &catalog, SchemaCatalogEntry &schem : StandardEntry(CatalogType::TABLE_ENTRY, schema, catalog, info.table), columns(std::move(info.columns)), constraints(std::move(info.constraints)) { this->temporary = info.temporary; + this->dependencies = info.dependencies; this->comment = info.comment; + this->tags = info.tags; } bool TableCatalogEntry::HasGeneratedColumns() const { @@ -64,9 +66,11 @@ unique_ptr TableCatalogEntry::GetInfo() const { result->table = name; result->columns = columns.Copy(); result->constraints.reserve(constraints.size()); + result->dependencies = dependencies; std::for_each(constraints.begin(), constraints.end(), [&result](const unique_ptr &c) { result->constraints.emplace_back(c->Copy()); }); result->comment = comment; + result->tags = tags; return std::move(result); } diff --git a/src/catalog/catalog_entry/type_catalog_entry.cpp b/src/catalog/catalog_entry/type_catalog_entry.cpp index 4e04ee26b1b..c60c7167da4 100644 --- a/src/catalog/catalog_entry/type_catalog_entry.cpp +++ b/src/catalog/catalog_entry/type_catalog_entry.cpp @@ -10,10 +10,13 @@ namespace duckdb { TypeCatalogEntry::TypeCatalogEntry(Catalog &catalog, SchemaCatalogEntry &schema, CreateTypeInfo &info) - : StandardEntry(CatalogType::TYPE_ENTRY, schema, catalog, info.name), user_type(info.type) { + : StandardEntry(CatalogType::TYPE_ENTRY, schema, catalog, info.name), user_type(info.type), + bind_modifiers(info.bind_modifiers) { this->temporary = info.temporary; this->internal = info.internal; + this->dependencies = info.dependencies; this->comment = info.comment; + this->tags = info.tags; } unique_ptr TypeCatalogEntry::Copy(ClientContext &context) const { @@ -29,7 +32,10 @@ unique_ptr TypeCatalogEntry::GetInfo() const { result->schema = schema.name; result->name = name; result->type = user_type; + result->dependencies = dependencies; result->comment = comment; + result->tags = tags; + result->bind_modifiers = bind_modifiers; return std::move(result); } diff --git a/src/catalog/catalog_entry/view_catalog_entry.cpp b/src/catalog/catalog_entry/view_catalog_entry.cpp index 2452dc0de9e..9f029f21443 100644 --- a/src/catalog/catalog_entry/view_catalog_entry.cpp +++ b/src/catalog/catalog_entry/view_catalog_entry.cpp @@ -20,7 +20,9 @@ void ViewCatalogEntry::Initialize(CreateViewInfo &info) { this->temporary = info.temporary; this->sql = info.sql; this->internal = info.internal; + this->dependencies = info.dependencies; this->comment = info.comment; + this->tags = info.tags; this->column_comments = info.column_comments; } @@ -39,7 +41,9 @@ unique_ptr ViewCatalogEntry::GetInfo() const { result->names = names; result->types = types; result->temporary = temporary; + result->dependencies = dependencies; result->comment = comment; + result->tags = tags; result->column_comments = column_comments; return std::move(result); } diff --git a/src/catalog/catalog_entry_retriever.cpp b/src/catalog/catalog_entry_retriever.cpp new file mode 100644 index 00000000000..db0d0d42398 --- /dev/null +++ b/src/catalog/catalog_entry_retriever.cpp @@ -0,0 +1,64 @@ +#include "duckdb/catalog/catalog_entry_retriever.hpp" +#include "duckdb/catalog/catalog.hpp" +#include "duckdb/catalog/catalog_entry.hpp" +#include "duckdb/parser/query_error_context.hpp" +#include "duckdb/main/client_context.hpp" +#include "duckdb/common/enums/on_entry_not_found.hpp" +#include "duckdb/common/enums/catalog_type.hpp" +#include "duckdb/common/optional_ptr.hpp" +#include "duckdb/catalog/catalog_entry/type_catalog_entry.hpp" + +namespace duckdb { + +LogicalType CatalogEntryRetriever::GetType(Catalog &catalog, const string &schema, const string &name, + OnEntryNotFound on_entry_not_found) { + QueryErrorContext error_context; + auto result = GetEntry(CatalogType::TYPE_ENTRY, catalog, schema, name, on_entry_not_found, error_context); + if (!result) { + return LogicalType::INVALID; + } + auto &type_entry = result->Cast(); + return type_entry.user_type; +} + +LogicalType CatalogEntryRetriever::GetType(const string &catalog, const string &schema, const string &name, + OnEntryNotFound on_entry_not_found) { + QueryErrorContext error_context; + auto result = GetEntry(CatalogType::TYPE_ENTRY, catalog, schema, name, on_entry_not_found, error_context); + if (!result) { + return LogicalType::INVALID; + } + auto &type_entry = result->Cast(); + return type_entry.user_type; +} + +optional_ptr CatalogEntryRetriever::GetEntry(CatalogType type, const string &catalog, + const string &schema, const string &name, + OnEntryNotFound on_entry_not_found, + QueryErrorContext error_context) { + return GetEntryInternal( + [&]() { return Catalog::GetEntry(context, type, catalog, schema, name, on_entry_not_found, error_context); }); +} + +optional_ptr CatalogEntryRetriever::GetSchema(const string &catalog, const string &name, + OnEntryNotFound on_entry_not_found, + QueryErrorContext error_context) { + auto result = Catalog::GetSchema(context, catalog, name, on_entry_not_found, error_context); + if (!result) { + return result; + } + if (callback) { + // Call the callback if it's set + callback(*result); + } + return result; +} + +optional_ptr CatalogEntryRetriever::GetEntry(CatalogType type, Catalog &catalog, const string &schema, + const string &name, OnEntryNotFound on_entry_not_found, + QueryErrorContext error_context) { + return GetEntryInternal( + [&]() { return catalog.GetEntry(context, type, schema, name, on_entry_not_found, error_context); }); +} + +} // namespace duckdb diff --git a/src/catalog/catalog_set.cpp b/src/catalog/catalog_set.cpp index d167fd90d31..17badcc34d6 100644 --- a/src/catalog/catalog_set.cpp +++ b/src/catalog/catalog_set.cpp @@ -14,6 +14,7 @@ #include "duckdb/transaction/transaction_manager.hpp" #include "duckdb/catalog/dependency_list.hpp" #include "duckdb/common/exception/transaction_exception.hpp" +#include "duckdb/catalog/catalog_entry/schema_catalog_entry.hpp" namespace duckdb { @@ -245,10 +246,22 @@ bool CatalogSet::AlterOwnership(CatalogTransaction transaction, ChangeOwnershipI if (!entry) { return false; } - - auto &owner_entry = catalog.GetEntry(transaction.GetContext(), info.owner_schema, info.owner_name); + optional_ptr owner_entry; + auto schema = catalog.GetSchema(transaction, info.owner_schema, OnEntryNotFound::RETURN_NULL); + if (schema) { + vector entry_types {CatalogType::TABLE_ENTRY, CatalogType::SEQUENCE_ENTRY}; + for (auto entry_type : entry_types) { + owner_entry = schema->GetEntry(transaction, entry_type, info.owner_name); + if (owner_entry) { + break; + } + } + } + if (!owner_entry) { + throw CatalogException("CatalogElement \"%s.%s\" does not exist!", info.owner_schema, info.owner_name); + } write_lock.unlock(); - catalog.GetDependencyManager().AddOwnership(transaction, owner_entry, *entry); + catalog.GetDependencyManager().AddOwnership(transaction, *owner_entry, *entry); return true; } @@ -292,39 +305,41 @@ bool CatalogSet::RenameEntryInternal(CatalogTransaction transaction, CatalogEntr } bool CatalogSet::AlterEntry(CatalogTransaction transaction, const string &name, AlterInfo &alter_info) { - // lock the catalog for writing - unique_lock write_lock(catalog.GetWriteLock()); - // lock this catalog set to disallow reading - unique_lock read_lock(catalog_lock); - // If the entry does not exist, we error - auto entry = GetEntryInternal(transaction, name); + auto entry = GetEntry(transaction, name); if (!entry) { return false; } if (!alter_info.allow_internal && entry->internal) { throw CatalogException("Cannot alter entry \"%s\" because it is an internal system entry", entry->name); } - if (!transaction.context) { - throw InternalException("Cannot AlterEntry without client context"); - } - - auto &context = *transaction.context; unique_ptr value; if (alter_info.type == AlterType::SET_COMMENT) { // Copy the existing entry; we are only changing metadata here - value = entry->Copy(context); + if (!transaction.context) { + throw InternalException("Cannot AlterEntry::SET_COMMENT without client context"); + } + value = entry->Copy(*transaction.context); value->comment = alter_info.Cast().comment_value; } else { // Use the existing entry to create the altered entry - value = entry->AlterEntry(context, alter_info); + value = entry->AlterEntry(transaction, alter_info); if (!value) { // alter failed, but did not result in an error return true; } } + // lock the catalog for writing + unique_lock write_lock(catalog.GetWriteLock()); + // lock this catalog set to disallow reading + unique_lock read_lock(catalog_lock); + + // fetch the entry again before doing the modification + // this will catch any write-write conflicts between transactions + entry = GetEntryInternal(transaction, name); + // Mark this entry as being created by this transaction value->timestamp = transaction.transaction_id; value->set = this; @@ -355,7 +370,7 @@ bool CatalogSet::AlterEntry(CatalogTransaction transaction, const string &name, write_lock.unlock(); // Check the dependency manager to verify that there are no conflicting dependencies with this alter - catalog.GetDependencyManager().AlterObject(transaction, *entry, *new_entry); + catalog.GetDependencyManager().AlterObject(transaction, *entry, *new_entry, alter_info); return true; } @@ -508,14 +523,10 @@ optional_ptr CatalogSet::CreateDefaultEntry(CatalogTransaction tra // no defaults either: return null return nullptr; } + read_lock.unlock(); // this catalog set has a default map defined // check if there is a default entry that we can create with this name - if (!transaction.context) { - // no context - cannot create default entry - return nullptr; - } - read_lock.unlock(); - auto entry = defaults->CreateDefaultEntry(*transaction.context, name); + auto entry = defaults->CreateDefaultEntry(transaction, name); read_lock.lock(); if (!entry) { @@ -594,7 +605,7 @@ void CatalogSet::Undo(CatalogEntry &entry) { } void CatalogSet::CreateDefaultEntries(CatalogTransaction transaction, unique_lock &read_lock) { - if (!defaults || defaults->created_all_entries || !transaction.context) { + if (!defaults || defaults->created_all_entries) { return; } // this catalog set has a default set defined: @@ -605,7 +616,7 @@ void CatalogSet::CreateDefaultEntries(CatalogTransaction transaction, unique_loc // we unlock during the CreateEntry, since it might reference other catalog sets... // specifically for views this can happen since the view will be bound read_lock.unlock(); - auto entry = defaults->CreateDefaultEntry(*transaction.context, default_entry); + auto entry = defaults->CreateDefaultEntry(transaction, default_entry); if (!entry) { throw InternalException("Failed to create default entry for %s", default_entry); } diff --git a/src/catalog/default/CMakeLists.txt b/src/catalog/default/CMakeLists.txt index 5f73d0d000b..669e0e49b57 100644 --- a/src/catalog/default/CMakeLists.txt +++ b/src/catalog/default/CMakeLists.txt @@ -1,5 +1,12 @@ -add_library_unity(duckdb_catalog_default_entries OBJECT default_functions.cpp - default_schemas.cpp default_types.cpp default_views.cpp) +add_library_unity( + duckdb_catalog_default_entries + OBJECT + default_functions.cpp + default_generator.cpp + default_schemas.cpp + default_table_functions.cpp + default_types.cpp + default_views.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/catalog/default/default_functions.cpp b/src/catalog/default/default_functions.cpp index ee8ba09bb32..dca2af36155 100644 --- a/src/catalog/default/default_functions.cpp +++ b/src/catalog/default/default_functions.cpp @@ -60,8 +60,9 @@ static const DefaultMacro internal_macros[] = { {"pg_catalog", "pg_get_viewdef", {"oid", nullptr}, "(select sql from duckdb_views() v where v.view_oid=oid)"}, {"pg_catalog", "pg_get_constraintdef", {"constraint_oid", "pretty_bool", nullptr}, "(select constraint_text from duckdb_constraints() d_constraint where d_constraint.table_oid=constraint_oid//1000000 and d_constraint.constraint_index=constraint_oid%1000000)"}, {"pg_catalog", "pg_get_expr", {"pg_node_tree", "relation_oid", nullptr}, "pg_node_tree"}, - {"pg_catalog", "format_pg_type", {"logical_type", "type_name", nullptr}, "case when logical_type='FLOAT' then 'real' when logical_type='DOUBLE' then 'double precision' when logical_type='DECIMAL' then 'numeric' when logical_type='ENUM' then lower(type_name) when logical_type='VARCHAR' then 'character varying' when logical_type='BLOB' then 'bytea' when logical_type='TIMESTAMP' then 'timestamp without time zone' when logical_type='TIME' then 'time without time zone' else lower(logical_type) end"}, + {"pg_catalog", "format_pg_type", {"logical_type", "type_name", nullptr}, "case upper(logical_type) when 'FLOAT' then 'float4' when 'DOUBLE' then 'float8' when 'DECIMAL' then 'numeric' when 'ENUM' then lower(type_name) when 'VARCHAR' then 'varchar' when 'BLOB' then 'bytea' when 'TIMESTAMP' then 'timestamp' when 'TIME' then 'time' when 'TIMESTAMP WITH TIME ZONE' then 'timestamptz' when 'TIME WITH TIME ZONE' then 'timetz' when 'SMALLINT' then 'int2' when 'INTEGER' then 'int4' when 'BIGINT' then 'int8' when 'BOOLEAN' then 'bool' else lower(logical_type) end"}, {"pg_catalog", "format_type", {"type_oid", "typemod", nullptr}, "(select format_pg_type(logical_type, type_name) from duckdb_types() t where t.type_oid=type_oid) || case when typemod>0 then concat('(', typemod//1000, ',', typemod%1000, ')') else '' end"}, + {"pg_catalog", "map_to_pg_oid", {"type_name", nullptr}, "case type_name when 'bool' then 16 when 'int16' then 21 when 'int' then 23 when 'bigint' then 20 when 'date' then 1082 when 'time' then 1083 when 'datetime' then 1114 when 'dec' then 1700 when 'float' then 700 when 'double' then 701 when 'bpchar' then 1043 when 'binary' then 17 when 'interval' then 1186 when 'timestamptz' then 1184 when 'timetz' then 1266 when 'bit' then 1560 when 'guid' then 2950 else null end"}, // map duckdb_oid to pg_oid. If no corresponding type, return null {"pg_catalog", "pg_has_role", {"user", "role", "privilege", nullptr}, "true"}, //boolean //does user have privilege for role {"pg_catalog", "pg_has_role", {"role", "privilege", nullptr}, "true"}, //boolean //does current user have privilege for role @@ -171,13 +172,13 @@ static const DefaultMacro internal_macros[] = { {nullptr, nullptr, {nullptr}, nullptr} }; -unique_ptr DefaultFunctionGenerator::CreateInternalTableMacroInfo(const DefaultMacro &default_macro, unique_ptr function) { +unique_ptr DefaultFunctionGenerator::CreateInternalMacroInfo(const DefaultMacro &default_macro, unique_ptr function) { for (idx_t param_idx = 0; default_macro.parameters[param_idx] != nullptr; param_idx++) { function->parameters.push_back( make_uniq(default_macro.parameters[param_idx])); } - - auto type = function->type == MacroType::TABLE_MACRO ? CatalogType::TABLE_MACRO_ENTRY : CatalogType::MACRO_ENTRY; + D_ASSERT(function->type == MacroType::SCALAR_MACRO); + auto type = CatalogType::MACRO_ENTRY; auto bind_info = make_uniq(type); bind_info->schema = default_macro.schema; bind_info->name = default_macro.name; @@ -194,18 +195,7 @@ unique_ptr DefaultFunctionGenerator::CreateInternalMacroInfo(co D_ASSERT(expressions.size() == 1); auto result = make_uniq(std::move(expressions[0])); - return CreateInternalTableMacroInfo(default_macro, std::move(result)); -} - -unique_ptr DefaultFunctionGenerator::CreateInternalTableMacroInfo(const DefaultMacro &default_macro) { - Parser parser; - parser.ParseQuery(default_macro.macro); - D_ASSERT(parser.statements.size() == 1); - D_ASSERT(parser.statements[0]->type == StatementType::SELECT_STATEMENT); - - auto &select = parser.statements[0]->Cast(); - auto result = make_uniq(std::move(select.node)); - return CreateInternalTableMacroInfo(default_macro, std::move(result)); + return CreateInternalMacroInfo(default_macro, std::move(result)); } static unique_ptr GetDefaultFunction(const string &input_schema, const string &input_name) { diff --git a/src/catalog/default/default_generator.cpp b/src/catalog/default/default_generator.cpp new file mode 100644 index 00000000000..2fbb2b646ee --- /dev/null +++ b/src/catalog/default/default_generator.cpp @@ -0,0 +1,24 @@ +#include "duckdb/catalog/default/default_generator.hpp" +#include "duckdb/catalog/catalog_transaction.hpp" + +namespace duckdb { + +DefaultGenerator::DefaultGenerator(Catalog &catalog) : catalog(catalog), created_all_entries(false) { +} +DefaultGenerator::~DefaultGenerator() { +} + +unique_ptr DefaultGenerator::CreateDefaultEntry(ClientContext &context, const string &entry_name) { + throw InternalException("CreateDefaultEntry with ClientContext called but not supported in this generator"); +} + +unique_ptr DefaultGenerator::CreateDefaultEntry(CatalogTransaction transaction, + const string &entry_name) { + if (!transaction.context) { + // no context - cannot create default entry + return nullptr; + } + return CreateDefaultEntry(*transaction.context, entry_name); +} + +} // namespace duckdb diff --git a/src/catalog/default/default_schemas.cpp b/src/catalog/default/default_schemas.cpp index 72a95da7b5e..64aaf56d26b 100644 --- a/src/catalog/default/default_schemas.cpp +++ b/src/catalog/default/default_schemas.cpp @@ -11,7 +11,7 @@ struct DefaultSchema { static const DefaultSchema internal_schemas[] = {{"information_schema"}, {"pg_catalog"}, {nullptr}}; -static bool GetDefaultSchema(const string &input_schema) { +bool DefaultSchemaGenerator::IsDefaultSchema(const string &input_schema) { auto schema = StringUtil::Lower(input_schema); for (idx_t index = 0; internal_schemas[index].name != nullptr; index++) { if (internal_schemas[index].name == schema) { @@ -24,8 +24,9 @@ static bool GetDefaultSchema(const string &input_schema) { DefaultSchemaGenerator::DefaultSchemaGenerator(Catalog &catalog) : DefaultGenerator(catalog) { } -unique_ptr DefaultSchemaGenerator::CreateDefaultEntry(ClientContext &context, const string &entry_name) { - if (GetDefaultSchema(entry_name)) { +unique_ptr DefaultSchemaGenerator::CreateDefaultEntry(CatalogTransaction transaction, + const string &entry_name) { + if (IsDefaultSchema(entry_name)) { CreateSchemaInfo info; info.schema = StringUtil::Lower(entry_name); info.internal = true; diff --git a/src/catalog/default/default_table_functions.cpp b/src/catalog/default/default_table_functions.cpp new file mode 100644 index 00000000000..cc4a3167f51 --- /dev/null +++ b/src/catalog/default/default_table_functions.cpp @@ -0,0 +1,137 @@ +#include "duckdb/catalog/default/default_table_functions.hpp" +#include "duckdb/catalog/catalog_entry/table_macro_catalog_entry.hpp" +#include "duckdb/parser/parser.hpp" +#include "duckdb/parser/parsed_data/create_macro_info.hpp" +#include "duckdb/parser/statement/select_statement.hpp" +#include "duckdb/function/table_macro_function.hpp" + +namespace duckdb { + +// clang-format off +static const DefaultTableMacro internal_table_macros[] = { + {DEFAULT_SCHEMA, "histogram_values", {"source", "col_name", nullptr}, {{"bin_count", "10"}, {"technique", "'auto'"}, {nullptr, nullptr}}, R"( +WITH bins AS ( + SELECT + CASE + WHEN (NOT (can_cast_implicitly(MIN(col_name), NULL::BIGINT) OR + can_cast_implicitly(MIN(col_name), NULL::DOUBLE) OR + can_cast_implicitly(MIN(col_name), NULL::TIMESTAMP)) AND technique='auto') + OR technique='sample' + THEN + list(distinct col_name)[:bin_count] + WHEN technique='equi-height' + THEN + quantile(col_name, [x / bin_count::DOUBLE for x in generate_series(1, bin_count)]) + WHEN technique='equi-width' + THEN + equi_width_bins(MIN(col_name), MAX(col_name), bin_count, false) + WHEN technique='equi-width-nice' OR technique='auto' + THEN + equi_width_bins(MIN(col_name), MAX(col_name), bin_count, true) + ELSE + error(concat('Unrecognized technique ', technique)) + END AS bins + FROM query_table(source::VARCHAR) + ) +SELECT UNNEST(bins) AS bin, UNNEST([histogram[bin] for bin in bins])[1] AS count +FROM ( + SELECT list_sort(list_distinct(FIRST(bins))) AS bins, histogram(col_name, bins) AS histogram + FROM query_table(source::VARCHAR), bins +); +)"}, + {DEFAULT_SCHEMA, "histogram", {"source", "col_name", nullptr}, {{"bin_count", "10"}, {"technique", "'auto'"}, {nullptr, nullptr}}, R"( +SELECT + CASE + WHEN (NOT (can_cast_implicitly(bin, NULL::BIGINT) OR + can_cast_implicitly(bin, NULL::DOUBLE) OR + can_cast_implicitly(bin, NULL::TIMESTAMP)) AND technique='auto') + OR technique='sample' + THEN bin::VARCHAR + WHEN row_number() over () = 1 + THEN concat('x <= ', bin::VARCHAR) + ELSE concat(lag(bin::VARCHAR) over (), ' < x <= ', bin::VARCHAR) + END AS bin, + count, + bar(count, 0, max(count) over ()) AS bar +FROM histogram_values(source, col_name, bin_count := bin_count, technique := technique); +)"}, + {nullptr, nullptr, {nullptr}, {{nullptr, nullptr}}, nullptr} + }; +// clang-format on + +DefaultTableFunctionGenerator::DefaultTableFunctionGenerator(Catalog &catalog, SchemaCatalogEntry &schema) + : DefaultGenerator(catalog), schema(schema) { +} + +unique_ptr +DefaultTableFunctionGenerator::CreateInternalTableMacroInfo(const DefaultTableMacro &default_macro, + unique_ptr function) { + for (idx_t param_idx = 0; default_macro.parameters[param_idx] != nullptr; param_idx++) { + function->parameters.push_back(make_uniq(default_macro.parameters[param_idx])); + } + for (idx_t named_idx = 0; default_macro.named_parameters[named_idx].name != nullptr; named_idx++) { + auto expr_list = Parser::ParseExpressionList(default_macro.named_parameters[named_idx].default_value); + if (expr_list.size() != 1) { + throw InternalException("Expected a single expression"); + } + function->default_parameters.insert( + make_pair(default_macro.named_parameters[named_idx].name, std::move(expr_list[0]))); + } + + auto type = CatalogType::TABLE_MACRO_ENTRY; + auto bind_info = make_uniq(type); + bind_info->schema = default_macro.schema; + bind_info->name = default_macro.name; + bind_info->temporary = true; + bind_info->internal = true; + bind_info->function = std::move(function); + return bind_info; +} + +unique_ptr +DefaultTableFunctionGenerator::CreateTableMacroInfo(const DefaultTableMacro &default_macro) { + Parser parser; + parser.ParseQuery(default_macro.macro); + if (parser.statements.size() != 1 || parser.statements[0]->type != StatementType::SELECT_STATEMENT) { + throw InternalException("Expected a single select statement in CreateTableMacroInfo internal"); + } + auto node = std::move(parser.statements[0]->Cast().node); + + auto result = make_uniq(std::move(node)); + return CreateInternalTableMacroInfo(default_macro, std::move(result)); +} + +static unique_ptr GetDefaultTableFunction(const string &input_schema, const string &input_name) { + auto schema = StringUtil::Lower(input_schema); + auto name = StringUtil::Lower(input_name); + for (idx_t index = 0; internal_table_macros[index].name != nullptr; index++) { + if (internal_table_macros[index].schema == schema && internal_table_macros[index].name == name) { + return DefaultTableFunctionGenerator::CreateTableMacroInfo(internal_table_macros[index]); + } + } + return nullptr; +} + +unique_ptr DefaultTableFunctionGenerator::CreateDefaultEntry(ClientContext &context, + const string &entry_name) { + auto info = GetDefaultTableFunction(schema.name, entry_name); + if (info) { + return make_uniq_base(catalog, schema, info->Cast()); + } + return nullptr; +} + +vector DefaultTableFunctionGenerator::GetDefaultEntries() { + vector result; + for (idx_t index = 0; internal_table_macros[index].name != nullptr; index++) { + if (StringUtil::Lower(internal_table_macros[index].name) != internal_table_macros[index].name) { + throw InternalException("Default macro name %s should be lowercase", internal_table_macros[index].name); + } + if (internal_table_macros[index].schema == schema.name) { + result.emplace_back(internal_table_macros[index].name); + } + } + return result; +} + +} // namespace duckdb diff --git a/src/catalog/default/default_views.cpp b/src/catalog/default/default_views.cpp index 967d1d576eb..aeec58653d7 100644 --- a/src/catalog/default/default_views.cpp +++ b/src/catalog/default/default_views.cpp @@ -44,7 +44,7 @@ static const DefaultView internal_views[] = { {"pg_catalog", "pg_settings", "SELECT name, value setting, description short_desc, CASE WHEN input_type = 'VARCHAR' THEN 'string' WHEN input_type = 'BOOLEAN' THEN 'bool' WHEN input_type IN ('BIGINT', 'UBIGINT') THEN 'integer' ELSE input_type END vartype FROM duckdb_settings()"}, {"pg_catalog", "pg_tables", "SELECT schema_name schemaname, table_name tablename, 'duckdb' tableowner, NULL \"tablespace\", index_count > 0 hasindexes, false hasrules, false hastriggers FROM duckdb_tables()"}, {"pg_catalog", "pg_tablespace", "SELECT 0 oid, 'pg_default' spcname, 0 spcowner, NULL spcacl, NULL spcoptions"}, - {"pg_catalog", "pg_type", "SELECT type_oid oid, format_pg_type(logical_type, type_name) typname, schema_oid typnamespace, 0 typowner, type_size typlen, false typbyval, CASE WHEN logical_type='ENUM' THEN 'e' else 'b' end typtype, CASE WHEN type_category='NUMERIC' THEN 'N' WHEN type_category='STRING' THEN 'S' WHEN type_category='DATETIME' THEN 'D' WHEN type_category='BOOLEAN' THEN 'B' WHEN type_category='COMPOSITE' THEN 'C' WHEN type_category='USER' THEN 'U' ELSE 'X' END typcategory, false typispreferred, true typisdefined, NULL typdelim, NULL typrelid, NULL typsubscript, NULL typelem, NULL typarray, NULL typinput, NULL typoutput, NULL typreceive, NULL typsend, NULL typmodin, NULL typmodout, NULL typanalyze, 'd' typalign, 'p' typstorage, NULL typnotnull, NULL typbasetype, NULL typtypmod, NULL typndims, NULL typcollation, NULL typdefaultbin, NULL typdefault, NULL typacl FROM duckdb_types() WHERE type_size IS NOT NULL;"}, + {"pg_catalog", "pg_type", "SELECT CASE WHEN type_oid IS NULL THEN NULL WHEN logical_type = 'ENUM' AND type_name <> 'enum' THEN type_oid ELSE map_to_pg_oid(type_name) END oid, format_pg_type(logical_type, type_name) typname, schema_oid typnamespace, 0 typowner, type_size typlen, false typbyval, CASE WHEN logical_type='ENUM' THEN 'e' else 'b' end typtype, CASE WHEN type_category='NUMERIC' THEN 'N' WHEN type_category='STRING' THEN 'S' WHEN type_category='DATETIME' THEN 'D' WHEN type_category='BOOLEAN' THEN 'B' WHEN type_category='COMPOSITE' THEN 'C' WHEN type_category='USER' THEN 'U' ELSE 'X' END typcategory, false typispreferred, true typisdefined, NULL typdelim, NULL typrelid, NULL typsubscript, NULL typelem, NULL typarray, NULL typinput, NULL typoutput, NULL typreceive, NULL typsend, NULL typmodin, NULL typmodout, NULL typanalyze, 'd' typalign, 'p' typstorage, NULL typnotnull, NULL typbasetype, NULL typtypmod, NULL typndims, NULL typcollation, NULL typdefaultbin, NULL typdefault, NULL typacl FROM duckdb_types() WHERE type_oid IS NOT NULL;"}, {"pg_catalog", "pg_views", "SELECT schema_name schemaname, view_name viewname, 'duckdb' viewowner, sql definition FROM duckdb_views()"}, {"information_schema", "columns", "SELECT database_name table_catalog, schema_name table_schema, table_name, column_name, column_index ordinal_position, column_default, CASE WHEN is_nullable THEN 'YES' ELSE 'NO' END is_nullable, data_type, character_maximum_length, NULL::INT character_octet_length, numeric_precision, numeric_precision_radix, numeric_scale, NULL::INT datetime_precision, NULL::VARCHAR interval_type, NULL::INT interval_precision, NULL::VARCHAR character_set_catalog, NULL::VARCHAR character_set_schema, NULL::VARCHAR character_set_name, NULL::VARCHAR collation_catalog, NULL::VARCHAR collation_schema, NULL::VARCHAR collation_name, NULL::VARCHAR domain_catalog, NULL::VARCHAR domain_schema, NULL::VARCHAR domain_name, NULL::VARCHAR udt_catalog, NULL::VARCHAR udt_schema, NULL::VARCHAR udt_name, NULL::VARCHAR scope_catalog, NULL::VARCHAR scope_schema, NULL::VARCHAR scope_name, NULL::BIGINT maximum_cardinality, NULL::VARCHAR dtd_identifier, NULL::BOOL is_self_referencing, NULL::BOOL is_identity, NULL::VARCHAR identity_generation, NULL::VARCHAR identity_start, NULL::VARCHAR identity_increment, NULL::VARCHAR identity_maximum, NULL::VARCHAR identity_minimum, NULL::BOOL identity_cycle, NULL::VARCHAR is_generated, NULL::VARCHAR generation_expression, NULL::BOOL is_updatable, comment AS COLUMN_COMMENT FROM duckdb_columns;"}, {"information_schema", "schemata", "SELECT database_name catalog_name, schema_name, 'duckdb' schema_owner, NULL::VARCHAR default_character_set_catalog, NULL::VARCHAR default_character_set_schema, NULL::VARCHAR default_character_set_name, sql sql_path FROM duckdb_schemas()"}, diff --git a/src/catalog/dependency_manager.cpp b/src/catalog/dependency_manager.cpp index 86b1fb251b1..51c60d3ad83 100644 --- a/src/catalog/dependency_manager.cpp +++ b/src/catalog/dependency_manager.cpp @@ -349,6 +349,90 @@ void DependencyManager::CleanupDependencies(CatalogTransaction transaction, Cata } } +static string EntryToString(CatalogEntryInfo &info) { + auto type = info.type; + switch (type) { + case CatalogType::TABLE_ENTRY: { + return StringUtil::Format("table \"%s\"", info.name); + } + case CatalogType::SCHEMA_ENTRY: { + return StringUtil::Format("schema \"%s\"", info.name); + } + case CatalogType::VIEW_ENTRY: { + return StringUtil::Format("view \"%s\"", info.name); + } + case CatalogType::INDEX_ENTRY: { + return StringUtil::Format("index \"%s\"", info.name); + } + case CatalogType::SEQUENCE_ENTRY: { + return StringUtil::Format("index \"%s\"", info.name); + } + case CatalogType::COLLATION_ENTRY: { + return StringUtil::Format("collation \"%s\"", info.name); + } + case CatalogType::TYPE_ENTRY: { + return StringUtil::Format("type \"%s\"", info.name); + } + case CatalogType::TABLE_FUNCTION_ENTRY: { + return StringUtil::Format("table function \"%s\"", info.name); + } + case CatalogType::SCALAR_FUNCTION_ENTRY: { + return StringUtil::Format("scalar function \"%s\"", info.name); + } + case CatalogType::AGGREGATE_FUNCTION_ENTRY: { + return StringUtil::Format("aggregate function \"%s\"", info.name); + } + case CatalogType::PRAGMA_FUNCTION_ENTRY: { + return StringUtil::Format("pragma function \"%s\"", info.name); + } + case CatalogType::COPY_FUNCTION_ENTRY: { + return StringUtil::Format("copy function \"%s\"", info.name); + } + case CatalogType::MACRO_ENTRY: { + return StringUtil::Format("macro function \"%s\"", info.name); + } + case CatalogType::TABLE_MACRO_ENTRY: { + return StringUtil::Format("table macro function \"%s\"", info.name); + } + case CatalogType::SECRET_ENTRY: { + return StringUtil::Format("secret \"%s\"", info.name); + } + case CatalogType::SECRET_TYPE_ENTRY: { + return StringUtil::Format("secret type \"%s\"", info.name); + } + case CatalogType::SECRET_FUNCTION_ENTRY: { + return StringUtil::Format("secret function \"%s\"", info.name); + } + default: + throw InternalException("CatalogType not handled in EntryToString (DependencyManager) for %s", + CatalogTypeToString(type)); + }; +} + +string DependencyManager::CollectDependents(CatalogTransaction transaction, catalog_entry_set_t &entries, + CatalogEntryInfo &info) { + string result; + for (auto &entry : entries) { + D_ASSERT(!IsSystemEntry(entry.get())); + auto other_info = GetLookupProperties(entry); + result += StringUtil::Format("%s depends on %s.\n", EntryToString(other_info), EntryToString(info)); + catalog_entry_set_t entry_dependents; + ScanDependents(transaction, other_info, [&](DependencyEntry &dep) { + auto child = LookupEntry(transaction, dep); + if (!child) { + return; + } + if (!CascadeDrop(false, dep.Dependent().flags)) { + entry_dependents.insert(*child); + } + }); + if (!entry_dependents.empty()) { + result += CollectDependents(transaction, entry_dependents, other_info); + } + } + return result; +} + void DependencyManager::DropObject(CatalogTransaction transaction, CatalogEntry &object, bool cascade) { if (IsSystemEntry(object)) { // Don't do anything for this @@ -358,6 +442,8 @@ void DependencyManager::DropObject(CatalogTransaction transaction, CatalogEntry auto info = GetLookupProperties(object); // Check if there are any entries that block the DROP because they still depend on the object catalog_entry_set_t to_drop; + + catalog_entry_set_t blocking_dependents; ScanDependents(transaction, info, [&](DependencyEntry &dep) { // It makes no sense to have a schema depend on anything D_ASSERT(dep.EntryInfo().type != CatalogType::SCHEMA_ENTRY); @@ -368,12 +454,19 @@ void DependencyManager::DropObject(CatalogTransaction transaction, CatalogEntry if (!CascadeDrop(cascade, dep.Dependent().flags)) { // no cascade and there are objects that depend on this object: throw error - throw DependencyException("Cannot drop entry \"%s\" because there are entries that " - "depend on it. Use DROP...CASCADE to drop all dependents.", - object.name); + blocking_dependents.insert(*entry); + } else { + to_drop.insert(*entry); } - to_drop.insert(*entry); }); + if (!blocking_dependents.empty()) { + string error_string = + StringUtil::Format("Cannot drop entry \"%s\" because there are entries that depend on it.\n", object.name); + error_string += CollectDependents(transaction, blocking_dependents, info); + error_string += "Use DROP...CASCADE to drop all dependents."; + throw DependencyException(error_string); + } + ScanSubjects(transaction, info, [&](DependencyEntry &dep) { auto flags = dep.Subject().flags; if (flags.IsOwnership()) { @@ -392,7 +485,8 @@ void DependencyManager::DropObject(CatalogTransaction transaction, CatalogEntry } } -void DependencyManager::AlterObject(CatalogTransaction transaction, CatalogEntry &old_obj, CatalogEntry &new_obj) { +void DependencyManager::AlterObject(CatalogTransaction transaction, CatalogEntry &old_obj, CatalogEntry &new_obj, + AlterInfo &alter_info) { if (IsSystemEntry(new_obj)) { D_ASSERT(IsSystemEntry(old_obj)); // Don't do anything for this @@ -408,9 +502,39 @@ void DependencyManager::AlterObject(CatalogTransaction transaction, CatalogEntry // It makes no sense to have a schema depend on anything D_ASSERT(dep.EntryInfo().type != CatalogType::SCHEMA_ENTRY); - throw DependencyException("Cannot alter entry \"%s\" because there are entries that " - "depend on it.", - old_obj.name); + bool disallow_alter = true; + switch (alter_info.type) { + case AlterType::ALTER_TABLE: { + auto &alter_table = alter_info.Cast(); + switch (alter_table.alter_table_type) { + case AlterTableType::FOREIGN_KEY_CONSTRAINT: { + // These alters are made as part of a CREATE or DROP table statement when a foreign key column is + // present either adding or removing a reference to the referenced primary key table + disallow_alter = false; + break; + } + case AlterTableType::ADD_COLUMN: { + disallow_alter = false; + break; + } + default: + break; + } + break; + } + case AlterType::SET_COLUMN_COMMENT: + case AlterType::SET_COMMENT: { + disallow_alter = false; + break; + } + default: + break; + } + if (disallow_alter) { + throw DependencyException("Cannot alter entry \"%s\" because there are entries that " + "depend on it.", + old_obj.name); + } auto dep_info = DependencyInfo::FromDependent(dep); dep_info.subject.entry = new_info; @@ -447,8 +571,8 @@ void DependencyManager::AlterObject(CatalogTransaction transaction, CatalogEntry void DependencyManager::Scan( ClientContext &context, const std::function &callback) { - lock_guard write_lock(catalog.GetWriteLock()); auto transaction = catalog.GetCatalogTransaction(context); + lock_guard write_lock(catalog.GetWriteLock()); // All the objects registered in the dependency manager catalog_entry_set_t entries; diff --git a/src/catalog/duck_catalog.cpp b/src/catalog/duck_catalog.cpp index ebf1bb53b72..1adebff72bb 100644 --- a/src/catalog/duck_catalog.cpp +++ b/src/catalog/duck_catalog.cpp @@ -7,6 +7,7 @@ #include "duckdb/catalog/default/default_schemas.hpp" #include "duckdb/function/built_in_functions.hpp" #include "duckdb/main/attached_database.hpp" +#include "duckdb/transaction/duck_transaction_manager.hpp" #ifndef DISABLE_CORE_FUNCTIONS_EXTENSION #include "duckdb/core_functions/core_functions.hpp" #endif @@ -129,10 +130,14 @@ optional_ptr DuckCatalog::GetSchema(CatalogTransaction trans } DatabaseSize DuckCatalog::GetDatabaseSize(ClientContext &context) { + auto &transaction = DuckTransactionManager::Get(db); + auto lock = transaction.SharedCheckpointLock(); return db.GetStorageManager().GetDatabaseSize(); } vector DuckCatalog::GetMetadataInfo(ClientContext &context) { + auto &transaction = DuckTransactionManager::Get(db); + auto lock = transaction.SharedCheckpointLock(); return db.GetStorageManager().GetMetadataInfo(); } diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index c25a4a78de5..cb3f17d11e1 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -46,6 +46,7 @@ add_library_unity( http_state.cpp pipe_file_system.cpp local_file_system.cpp + multi_file_list.cpp multi_file_reader.cpp error_data.cpp printer.cpp diff --git a/src/common/allocator.cpp b/src/common/allocator.cpp index c587aaf3344..169343306b4 100644 --- a/src/common/allocator.cpp +++ b/src/common/allocator.cpp @@ -4,6 +4,7 @@ #include "duckdb/common/atomic.hpp" #include "duckdb/common/exception.hpp" #include "duckdb/common/helper.hpp" +#include "duckdb/common/numeric_utils.hpp" #include @@ -128,7 +129,9 @@ data_ptr_t Allocator::AllocateData(idx_t size) { auto result = allocate_function(private_data.get(), size); #ifdef DEBUG D_ASSERT(private_data); - private_data->debug_info->AllocateData(result, size); + if (private_data->free_type != AllocatorFreeType::DOES_NOT_REQUIRE_FREE) { + private_data->debug_info->AllocateData(result, size); + } #endif if (!result) { throw OutOfMemoryException("Failed to allocate block of %llu bytes (bad allocation)", size); @@ -143,7 +146,9 @@ void Allocator::FreeData(data_ptr_t pointer, idx_t size) { D_ASSERT(size > 0); #ifdef DEBUG D_ASSERT(private_data); - private_data->debug_info->FreeData(pointer, size); + if (private_data->free_type != AllocatorFreeType::DOES_NOT_REQUIRE_FREE) { + private_data->debug_info->FreeData(pointer, size); + } #endif free_function(private_data.get(), pointer, size); } @@ -161,7 +166,9 @@ data_ptr_t Allocator::ReallocateData(data_ptr_t pointer, idx_t old_size, idx_t s auto new_pointer = reallocate_function(private_data.get(), pointer, old_size, size); #ifdef DEBUG D_ASSERT(private_data); - private_data->debug_info->ReallocateData(pointer, new_pointer, old_size, size); + if (private_data->free_type != AllocatorFreeType::DOES_NOT_REQUIRE_FREE) { + private_data->debug_info->ReallocateData(pointer, new_pointer, old_size, size); + } #endif if (!new_pointer) { throw OutOfMemoryException("Failed to re-allocate block of %llu bytes (bad allocation)", size); @@ -173,7 +180,11 @@ data_ptr_t Allocator::DefaultAllocate(PrivateAllocatorData *private_data, idx_t #ifdef USE_JEMALLOC return JemallocExtension::Allocate(private_data, size); #else - return data_ptr_cast(malloc(size)); + auto default_allocate_result = malloc(size); + if (!default_allocate_result) { + throw std::bad_alloc(); + } + return data_ptr_cast(default_allocate_result); #endif } @@ -203,18 +214,46 @@ Allocator &Allocator::DefaultAllocator() { return *DefaultAllocatorReference(); } +int64_t Allocator::DecayDelay() { +#ifdef USE_JEMALLOC + return JemallocExtension::DecayDelay(); +#else + return NumericLimits::Maximum(); +#endif +} + +bool Allocator::SupportsFlush() { +#ifdef USE_JEMALLOC + return true; +#else + return false; +#endif +} + void Allocator::ThreadFlush(idx_t threshold) { #ifdef USE_JEMALLOC JemallocExtension::ThreadFlush(threshold); #endif } +void Allocator::ThreadIdle() { +#ifdef USE_JEMALLOC + JemallocExtension::ThreadIdle(); +#endif +} + void Allocator::FlushAll() { #ifdef USE_JEMALLOC JemallocExtension::FlushAll(); #endif } +void Allocator::SetBackgroundThreads(bool enable) { +#ifdef USE_JEMALLOC + JemallocExtension::SetBackgroundThreads(enable); +#endif +} + //===--------------------------------------------------------------------===// // Debug Info (extended) //===--------------------------------------------------------------------===// diff --git a/src/common/arrow/appender/bool_data.cpp b/src/common/arrow/appender/bool_data.cpp index d30b3933907..78befb603af 100644 --- a/src/common/arrow/appender/bool_data.cpp +++ b/src/common/arrow/appender/bool_data.cpp @@ -5,7 +5,7 @@ namespace duckdb { void ArrowBoolData::Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { auto byte_count = (capacity + 7) / 8; - result.main_buffer.reserve(byte_count); + result.GetMainBuffer().reserve(byte_count); (void)AppendValidity; // silence a compiler warning about unused static function } @@ -13,14 +13,15 @@ void ArrowBoolData::Append(ArrowAppendData &append_data, Vector &input, idx_t fr idx_t size = to - from; UnifiedVectorFormat format; input.ToUnifiedFormat(input_size, format); - + auto &main_buffer = append_data.GetMainBuffer(); + auto &validity_buffer = append_data.GetValidityBuffer(); // we initialize both the validity and the bit set to 1's - ResizeValidity(append_data.validity, append_data.row_count + size); - ResizeValidity(append_data.main_buffer, append_data.row_count + size); + ResizeValidity(validity_buffer, append_data.row_count + size); + ResizeValidity(main_buffer, append_data.row_count + size); auto data = UnifiedVectorFormat::GetData(format); - auto result_data = append_data.main_buffer.GetData(); - auto validity_data = append_data.validity.GetData(); + auto result_data = main_buffer.GetData(); + auto validity_data = validity_buffer.GetData(); uint8_t current_bit; idx_t current_byte; GetBitPosition(append_data.row_count, current_byte, current_bit); @@ -39,7 +40,7 @@ void ArrowBoolData::Append(ArrowAppendData &append_data, Vector &input, idx_t fr void ArrowBoolData::Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { result->n_buffers = 2; - result->buffers[1] = append_data.main_buffer.data(); + result->buffers[1] = append_data.GetMainBuffer().data(); } } // namespace duckdb diff --git a/src/common/arrow/appender/union_data.cpp b/src/common/arrow/appender/union_data.cpp index 02acffe03d3..d39ddfd54d7 100644 --- a/src/common/arrow/appender/union_data.cpp +++ b/src/common/arrow/appender/union_data.cpp @@ -8,7 +8,7 @@ namespace duckdb { // Unions //===--------------------------------------------------------------------===// void ArrowUnionData::Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { - result.main_buffer.reserve(capacity * sizeof(int8_t)); + result.GetMainBuffer().reserve(capacity * sizeof(int8_t)); for (auto &child : UnionType::CopyMemberTypes(type)) { auto child_buffer = ArrowAppender::InitializeChild(child.second, capacity, result.options); @@ -22,7 +22,7 @@ void ArrowUnionData::Append(ArrowAppendData &append_data, Vector &input, idx_t f input.ToUnifiedFormat(input_size, format); idx_t size = to - from; - auto &types_buffer = append_data.main_buffer; + auto &types_buffer = append_data.GetMainBuffer(); duckdb::vector child_vectors; for (const auto &child : UnionType::CopyMemberTypes(input.GetType())) { @@ -57,7 +57,7 @@ void ArrowUnionData::Append(ArrowAppendData &append_data, Vector &input, idx_t f void ArrowUnionData::Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { result->n_buffers = 1; - result->buffers[0] = append_data.main_buffer.data(); + result->buffers[0] = append_data.GetMainBuffer().data(); auto &child_types = UnionType::CopyMemberTypes(type); ArrowAppender::AddChildren(append_data, child_types.size()); diff --git a/src/common/arrow/arrow_appender.cpp b/src/common/arrow/arrow_appender.cpp index e5ed4343c32..43d7cb5371f 100644 --- a/src/common/arrow/arrow_appender.cpp +++ b/src/common/arrow/arrow_appender.cpp @@ -72,7 +72,7 @@ ArrowArray *ArrowAppender::FinalizeChild(const LogicalType &type, unique_ptrbuffers = append_data.buffers.data(); result->null_count = NumericCast(append_data.null_count); result->length = NumericCast(append_data.row_count); - result->buffers[0] = append_data.validity.data(); + result->buffers[0] = append_data.GetValidityBuffer().data(); if (append_data.finalize) { append_data.finalize(append_data, type, result.get()); @@ -138,13 +138,15 @@ static void InitializeFunctionPointers(ArrowAppendData &append_data, const Logic case LogicalTypeId::INTEGER: InitializeAppenderForType>(append_data); break; + case LogicalTypeId::TIME_TZ: + InitializeAppenderForType>(append_data); + break; case LogicalTypeId::TIME: case LogicalTypeId::TIMESTAMP_SEC: case LogicalTypeId::TIMESTAMP_MS: case LogicalTypeId::TIMESTAMP: case LogicalTypeId::TIMESTAMP_NS: case LogicalTypeId::TIMESTAMP_TZ: - case LogicalTypeId::TIME_TZ: case LogicalTypeId::BIGINT: InitializeAppenderForType>(append_data); break; @@ -188,6 +190,16 @@ static void InitializeFunctionPointers(ArrowAppendData &append_data, const Logic } break; case LogicalTypeId::VARCHAR: + if (append_data.options.produce_arrow_string_view) { + InitializeAppenderForType(append_data); + } else { + if (append_data.options.arrow_offset_size == ArrowOffsetSize::LARGE) { + InitializeAppenderForType>(append_data); + } else { + InitializeAppenderForType>(append_data); + } + } + break; case LogicalTypeId::BLOB: case LogicalTypeId::BIT: if (append_data.options.arrow_offset_size == ArrowOffsetSize::LARGE) { @@ -231,10 +243,18 @@ static void InitializeFunctionPointers(ArrowAppendData &append_data, const Logic InitializeAppenderForType(append_data); break; case LogicalTypeId::LIST: { - if (append_data.options.arrow_offset_size == ArrowOffsetSize::LARGE) { - InitializeAppenderForType>(append_data); + if (append_data.options.arrow_use_list_view) { + if (append_data.options.arrow_offset_size == ArrowOffsetSize::LARGE) { + InitializeAppenderForType>(append_data); + } else { + InitializeAppenderForType>(append_data); + } } else { - InitializeAppenderForType>(append_data); + if (append_data.options.arrow_offset_size == ArrowOffsetSize::LARGE) { + InitializeAppenderForType>(append_data); + } else { + InitializeAppenderForType>(append_data); + } } break; } @@ -253,7 +273,7 @@ unique_ptr ArrowAppender::InitializeChild(const LogicalType &ty InitializeFunctionPointers(*result, type); auto byte_count = (capacity + 7) / 8; - result->validity.reserve(byte_count); + result->GetValidityBuffer().reserve(byte_count); result->initialize(*result, type, capacity); return result; } diff --git a/src/common/arrow/arrow_converter.cpp b/src/common/arrow/arrow_converter.cpp index b9f9ef836ed..4c775bcd324 100644 --- a/src/common/arrow/arrow_converter.cpp +++ b/src/common/arrow/arrow_converter.cpp @@ -129,18 +129,20 @@ void SetArrowFormat(DuckDBArrowSchemaHolder &root_holder, ArrowSchema &child, co break; case LogicalTypeId::UUID: case LogicalTypeId::VARCHAR: - if (options.arrow_offset_size == ArrowOffsetSize::LARGE) { - child.format = "U"; + if (options.produce_arrow_string_view) { + child.format = "vu"; } else { - child.format = "u"; + if (options.arrow_offset_size == ArrowOffsetSize::LARGE) { + child.format = "U"; + } else { + child.format = "u"; + } } break; case LogicalTypeId::DATE: child.format = "tdD"; break; -#ifdef DUCKDB_WASM case LogicalTypeId::TIME_TZ: -#endif case LogicalTypeId::TIME: child.format = "ttu"; break; @@ -187,10 +189,18 @@ void SetArrowFormat(DuckDBArrowSchemaHolder &root_holder, ArrowSchema &child, co break; } case LogicalTypeId::LIST: { - if (options.arrow_offset_size == ArrowOffsetSize::LARGE) { - child.format = "+L"; + if (options.arrow_use_list_view) { + if (options.arrow_offset_size == ArrowOffsetSize::LARGE) { + child.format = "+vL"; + } else { + child.format = "+vl"; + } } else { - child.format = "+l"; + if (options.arrow_offset_size == ArrowOffsetSize::LARGE) { + child.format = "+L"; + } else { + child.format = "+l"; + } } child.n_children = 1; root_holder.nested_children.emplace_back(); diff --git a/src/common/box_renderer.cpp b/src/common/box_renderer.cpp index 684e47ce3ad..404bb32fde9 100644 --- a/src/common/box_renderer.cpp +++ b/src/common/box_renderer.cpp @@ -77,6 +77,9 @@ void BoxRenderer::RenderValue(std::ostream &ss, const string &value, idx_t colum } string BoxRenderer::RenderType(const LogicalType &type) { + if (type.HasAlias()) { + return StringUtil::Lower(type.ToString()); + } switch (type.id()) { case LogicalTypeId::TINYINT: return "int8"; @@ -477,8 +480,8 @@ void BoxRenderer::RenderHeader(const vector &names, const vector(const char *value) { throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } +template<> +const char* EnumUtil::ToChars(ArrowTypeInfoType value) { + switch(value) { + case ArrowTypeInfoType::LIST: + return "LIST"; + case ArrowTypeInfoType::STRUCT: + return "STRUCT"; + case ArrowTypeInfoType::DATE_TIME: + return "DATE_TIME"; + case ArrowTypeInfoType::STRING: + return "STRING"; + case ArrowTypeInfoType::ARRAY: + return "ARRAY"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +ArrowTypeInfoType EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "LIST")) { + return ArrowTypeInfoType::LIST; + } + if (StringUtil::Equals(value, "STRUCT")) { + return ArrowTypeInfoType::STRUCT; + } + if (StringUtil::Equals(value, "DATE_TIME")) { + return ArrowTypeInfoType::DATE_TIME; + } + if (StringUtil::Equals(value, "STRING")) { + return ArrowTypeInfoType::STRING; + } + if (StringUtil::Equals(value, "ARRAY")) { + return ArrowTypeInfoType::ARRAY; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + template<> const char* EnumUtil::ToChars(ArrowVariableSizeType value) { switch(value) { - case ArrowVariableSizeType::FIXED_SIZE: - return "FIXED_SIZE"; case ArrowVariableSizeType::NORMAL: return "NORMAL"; + case ArrowVariableSizeType::FIXED_SIZE: + return "FIXED_SIZE"; case ArrowVariableSizeType::SUPER_SIZE: return "SUPER_SIZE"; + case ArrowVariableSizeType::VIEW: + return "VIEW"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } @@ -587,15 +636,41 @@ const char* EnumUtil::ToChars(ArrowVariableSizeType value template<> ArrowVariableSizeType EnumUtil::FromString(const char *value) { - if (StringUtil::Equals(value, "FIXED_SIZE")) { - return ArrowVariableSizeType::FIXED_SIZE; - } if (StringUtil::Equals(value, "NORMAL")) { return ArrowVariableSizeType::NORMAL; } + if (StringUtil::Equals(value, "FIXED_SIZE")) { + return ArrowVariableSizeType::FIXED_SIZE; + } if (StringUtil::Equals(value, "SUPER_SIZE")) { return ArrowVariableSizeType::SUPER_SIZE; } + if (StringUtil::Equals(value, "VIEW")) { + return ArrowVariableSizeType::VIEW; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + +template<> +const char* EnumUtil::ToChars(BinderType value) { + switch(value) { + case BinderType::REGULAR_BINDER: + return "REGULAR_BINDER"; + case BinderType::VIEW_BINDER: + return "VIEW_BINDER"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +BinderType EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "REGULAR_BINDER")) { + return BinderType::REGULAR_BINDER; + } + if (StringUtil::Equals(value, "VIEW_BINDER")) { + return BinderType::VIEW_BINDER; + } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } @@ -606,6 +681,8 @@ const char* EnumUtil::ToChars(BindingMode value) { return "STANDARD_BINDING"; case BindingMode::EXTRACT_NAMES: return "EXTRACT_NAMES"; + case BindingMode::EXTRACT_REPLACEMENT_SCANS: + return "EXTRACT_REPLACEMENT_SCANS"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } @@ -619,6 +696,9 @@ BindingMode EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "EXTRACT_NAMES")) { return BindingMode::EXTRACT_NAMES; } + if (StringUtil::Equals(value, "EXTRACT_REPLACEMENT_SCANS")) { + return BindingMode::EXTRACT_REPLACEMENT_SCANS; + } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } @@ -1280,6 +1360,85 @@ ConstraintType EnumUtil::FromString(const char *value) { throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } +template<> +const char* EnumUtil::ToChars(CopyFunctionReturnType value) { + switch(value) { + case CopyFunctionReturnType::CHANGED_ROWS: + return "CHANGED_ROWS"; + case CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST: + return "CHANGED_ROWS_AND_FILE_LIST"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +CopyFunctionReturnType EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "CHANGED_ROWS")) { + return CopyFunctionReturnType::CHANGED_ROWS; + } + if (StringUtil::Equals(value, "CHANGED_ROWS_AND_FILE_LIST")) { + return CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + +template<> +const char* EnumUtil::ToChars(CopyOverwriteMode value) { + switch(value) { + case CopyOverwriteMode::COPY_ERROR_ON_CONFLICT: + return "COPY_ERROR_ON_CONFLICT"; + case CopyOverwriteMode::COPY_OVERWRITE: + return "COPY_OVERWRITE"; + case CopyOverwriteMode::COPY_OVERWRITE_OR_IGNORE: + return "COPY_OVERWRITE_OR_IGNORE"; + case CopyOverwriteMode::COPY_APPEND: + return "COPY_APPEND"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +CopyOverwriteMode EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "COPY_ERROR_ON_CONFLICT")) { + return CopyOverwriteMode::COPY_ERROR_ON_CONFLICT; + } + if (StringUtil::Equals(value, "COPY_OVERWRITE")) { + return CopyOverwriteMode::COPY_OVERWRITE; + } + if (StringUtil::Equals(value, "COPY_OVERWRITE_OR_IGNORE")) { + return CopyOverwriteMode::COPY_OVERWRITE_OR_IGNORE; + } + if (StringUtil::Equals(value, "COPY_APPEND")) { + return CopyOverwriteMode::COPY_APPEND; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + +template<> +const char* EnumUtil::ToChars(CopyToType value) { + switch(value) { + case CopyToType::COPY_TO_FILE: + return "COPY_TO_FILE"; + case CopyToType::EXPORT_DATABASE: + return "EXPORT_DATABASE"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +CopyToType EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "COPY_TO_FILE")) { + return CopyToType::COPY_TO_FILE; + } + if (StringUtil::Equals(value, "EXPORT_DATABASE")) { + return CopyToType::EXPORT_DATABASE; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + template<> const char* EnumUtil::ToChars(DataFileType value) { switch(value) { @@ -1931,6 +2090,34 @@ ExplainType EnumUtil::FromString(const char *value) { throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } +template<> +const char* EnumUtil::ToChars(ExponentType value) { + switch(value) { + case ExponentType::NONE: + return "NONE"; + case ExponentType::POSITIVE: + return "POSITIVE"; + case ExponentType::NEGATIVE: + return "NEGATIVE"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +ExponentType EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "NONE")) { + return ExponentType::NONE; + } + if (StringUtil::Equals(value, "POSITIVE")) { + return ExponentType::POSITIVE; + } + if (StringUtil::Equals(value, "NEGATIVE")) { + return ExponentType::NEGATIVE; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + template<> const char* EnumUtil::ToChars(ExpressionClass value) { switch(value) { @@ -2502,6 +2689,44 @@ ExpressionType EnumUtil::FromString(const char *value) { throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } +template<> +const char* EnumUtil::ToChars(ExtensionInstallMode value) { + switch(value) { + case ExtensionInstallMode::UNKNOWN: + return "UNKNOWN"; + case ExtensionInstallMode::REPOSITORY: + return "REPOSITORY"; + case ExtensionInstallMode::CUSTOM_PATH: + return "CUSTOM_PATH"; + case ExtensionInstallMode::STATICALLY_LINKED: + return "STATICALLY_LINKED"; + case ExtensionInstallMode::NOT_INSTALLED: + return "NOT_INSTALLED"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +ExtensionInstallMode EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "UNKNOWN")) { + return ExtensionInstallMode::UNKNOWN; + } + if (StringUtil::Equals(value, "REPOSITORY")) { + return ExtensionInstallMode::REPOSITORY; + } + if (StringUtil::Equals(value, "CUSTOM_PATH")) { + return ExtensionInstallMode::CUSTOM_PATH; + } + if (StringUtil::Equals(value, "STATICALLY_LINKED")) { + return ExtensionInstallMode::STATICALLY_LINKED; + } + if (StringUtil::Equals(value, "NOT_INSTALLED")) { + return ExtensionInstallMode::NOT_INSTALLED; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + template<> const char* EnumUtil::ToChars(ExtensionLoadResult value) { switch(value) { @@ -2531,19 +2756,54 @@ ExtensionLoadResult EnumUtil::FromString(const char *value) } template<> -const char* EnumUtil::ToChars(ExternalDependenciesType value) { +const char* EnumUtil::ToChars(ExtensionUpdateResultTag value) { switch(value) { - case ExternalDependenciesType::PYTHON_DEPENDENCY: - return "PYTHON_DEPENDENCY"; + case ExtensionUpdateResultTag::UNKNOWN: + return "UNKNOWN"; + case ExtensionUpdateResultTag::NO_UPDATE_AVAILABLE: + return "NO_UPDATE_AVAILABLE"; + case ExtensionUpdateResultTag::NOT_A_REPOSITORY: + return "NOT_A_REPOSITORY"; + case ExtensionUpdateResultTag::NOT_INSTALLED: + return "NOT_INSTALLED"; + case ExtensionUpdateResultTag::STATICALLY_LOADED: + return "STATICALLY_LOADED"; + case ExtensionUpdateResultTag::MISSING_INSTALL_INFO: + return "MISSING_INSTALL_INFO"; + case ExtensionUpdateResultTag::REDOWNLOADED: + return "REDOWNLOADED"; + case ExtensionUpdateResultTag::UPDATED: + return "UPDATED"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } } template<> -ExternalDependenciesType EnumUtil::FromString(const char *value) { - if (StringUtil::Equals(value, "PYTHON_DEPENDENCY")) { - return ExternalDependenciesType::PYTHON_DEPENDENCY; +ExtensionUpdateResultTag EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "UNKNOWN")) { + return ExtensionUpdateResultTag::UNKNOWN; + } + if (StringUtil::Equals(value, "NO_UPDATE_AVAILABLE")) { + return ExtensionUpdateResultTag::NO_UPDATE_AVAILABLE; + } + if (StringUtil::Equals(value, "NOT_A_REPOSITORY")) { + return ExtensionUpdateResultTag::NOT_A_REPOSITORY; + } + if (StringUtil::Equals(value, "NOT_INSTALLED")) { + return ExtensionUpdateResultTag::NOT_INSTALLED; + } + if (StringUtil::Equals(value, "STATICALLY_LOADED")) { + return ExtensionUpdateResultTag::STATICALLY_LOADED; + } + if (StringUtil::Equals(value, "MISSING_INSTALL_INFO")) { + return ExtensionUpdateResultTag::MISSING_INSTALL_INFO; + } + if (StringUtil::Equals(value, "REDOWNLOADED")) { + return ExtensionUpdateResultTag::REDOWNLOADED; + } + if (StringUtil::Equals(value, "UPDATED")) { + return ExtensionUpdateResultTag::UPDATED; } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } @@ -2705,6 +2965,34 @@ FileCompressionType EnumUtil::FromString(const char *value) throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } +template<> +const char* EnumUtil::ToChars(FileExpandResult value) { + switch(value) { + case FileExpandResult::NO_FILES: + return "NO_FILES"; + case FileExpandResult::SINGLE_FILE: + return "SINGLE_FILE"; + case FileExpandResult::MULTIPLE_FILES: + return "MULTIPLE_FILES"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +FileExpandResult EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "NO_FILES")) { + return FileExpandResult::NO_FILES; + } + if (StringUtil::Equals(value, "SINGLE_FILE")) { + return FileExpandResult::SINGLE_FILE; + } + if (StringUtil::Equals(value, "MULTIPLE_FILES")) { + return FileExpandResult::MULTIPLE_FILES; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + template<> const char* EnumUtil::ToChars(FileGlobOptions value) { switch(value) { @@ -3304,6 +3592,8 @@ const char* EnumUtil::ToChars(LogicalOperatorType value) { return "LOGICAL_LOAD"; case LogicalOperatorType::LOGICAL_RESET: return "LOGICAL_RESET"; + case LogicalOperatorType::LOGICAL_UPDATE_EXTENSIONS: + return "LOGICAL_UPDATE_EXTENSIONS"; case LogicalOperatorType::LOGICAL_CREATE_SECRET: return "LOGICAL_CREATE_SECRET"; case LogicalOperatorType::LOGICAL_EXTENSION_OPERATOR: @@ -3489,6 +3779,9 @@ LogicalOperatorType EnumUtil::FromString(const char *value) if (StringUtil::Equals(value, "LOGICAL_RESET")) { return LogicalOperatorType::LOGICAL_RESET; } + if (StringUtil::Equals(value, "LOGICAL_UPDATE_EXTENSIONS")) { + return LogicalOperatorType::LOGICAL_UPDATE_EXTENSIONS; + } if (StringUtil::Equals(value, "LOGICAL_CREATE_SECRET")) { return LogicalOperatorType::LOGICAL_CREATE_SECRET; } @@ -3908,6 +4201,39 @@ MemoryTag EnumUtil::FromString(const char *value) { throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } +template<> +const char* EnumUtil::ToChars(MetricsType value) { + switch(value) { + case MetricsType::CPU_TIME: + return "CPU_TIME"; + case MetricsType::EXTRA_INFO: + return "EXTRA_INFO"; + case MetricsType::OPERATOR_CARDINALITY: + return "OPERATOR_CARDINALITY"; + case MetricsType::OPERATOR_TIMING: + return "OPERATOR_TIMING"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +MetricsType EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "CPU_TIME")) { + return MetricsType::CPU_TIME; + } + if (StringUtil::Equals(value, "EXTRA_INFO")) { + return MetricsType::EXTRA_INFO; + } + if (StringUtil::Equals(value, "OPERATOR_CARDINALITY")) { + return MetricsType::OPERATOR_CARDINALITY; + } + if (StringUtil::Equals(value, "OPERATOR_TIMING")) { + return MetricsType::OPERATOR_TIMING; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + template<> const char* EnumUtil::ToChars(NType value) { switch(value) { @@ -4160,6 +4486,10 @@ const char* EnumUtil::ToChars(OptimizerType value) { return "COMMON_AGGREGATE"; case OptimizerType::COLUMN_LIFETIME: return "COLUMN_LIFETIME"; + case OptimizerType::BUILD_SIDE_PROBE_SIDE: + return "BUILD_SIDE_PROBE_SIDE"; + case OptimizerType::LIMIT_PUSHDOWN: + return "LIMIT_PUSHDOWN"; case OptimizerType::TOP_N: return "TOP_N"; case OptimizerType::COMPRESSED_MATERIALIZATION: @@ -4219,6 +4549,12 @@ OptimizerType EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "COLUMN_LIFETIME")) { return OptimizerType::COLUMN_LIFETIME; } + if (StringUtil::Equals(value, "BUILD_SIDE_PROBE_SIDE")) { + return OptimizerType::BUILD_SIDE_PROBE_SIDE; + } + if (StringUtil::Equals(value, "LIMIT_PUSHDOWN")) { + return OptimizerType::LIMIT_PUSHDOWN; + } if (StringUtil::Equals(value, "TOP_N")) { return OptimizerType::TOP_N; } @@ -4389,6 +4725,8 @@ const char* EnumUtil::ToChars(ParseInfoType value) { return "COMMENT_ON_COLUMN_INFO"; case ParseInfoType::COPY_DATABASE_INFO: return "COPY_DATABASE_INFO"; + case ParseInfoType::UPDATE_EXTENSIONS_INFO: + return "UPDATE_EXTENSIONS_INFO"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } @@ -4444,6 +4782,9 @@ ParseInfoType EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "COPY_DATABASE_INFO")) { return ParseInfoType::COPY_DATABASE_INFO; } + if (StringUtil::Equals(value, "UPDATE_EXTENSIONS_INFO")) { + return ParseInfoType::UPDATE_EXTENSIONS_INFO; + } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } @@ -4488,6 +4829,8 @@ const char* EnumUtil::ToChars(PartitionSortStage value) { return "MERGE"; case PartitionSortStage::SORTED: return "SORTED"; + case PartitionSortStage::FINISHED: + return "FINISHED"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } @@ -4510,6 +4853,9 @@ PartitionSortStage EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "SORTED")) { return PartitionSortStage::SORTED; } + if (StringUtil::Equals(value, "FINISHED")) { + return PartitionSortStage::FINISHED; + } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } @@ -4755,6 +5101,8 @@ const char* EnumUtil::ToChars(PhysicalOperatorType value) return "EXTENSION"; case PhysicalOperatorType::VERIFY_VECTOR: return "VERIFY_VECTOR"; + case PhysicalOperatorType::UPDATE_EXTENSIONS: + return "UPDATE_EXTENSIONS"; case PhysicalOperatorType::CREATE_SECRET: return "CREATE_SECRET"; default: @@ -4989,6 +5337,9 @@ PhysicalOperatorType EnumUtil::FromString(const char *valu if (StringUtil::Equals(value, "VERIFY_VECTOR")) { return PhysicalOperatorType::VERIFY_VECTOR; } + if (StringUtil::Equals(value, "UPDATE_EXTENSIONS")) { + return PhysicalOperatorType::UPDATE_EXTENSIONS; + } if (StringUtil::Equals(value, "CREATE_SECRET")) { return PhysicalOperatorType::CREATE_SECRET; } @@ -5387,6 +5738,8 @@ const char* EnumUtil::ToChars(RelationType value) { return "INSERT_RELATION"; case RelationType::VALUE_LIST_RELATION: return "VALUE_LIST_RELATION"; + case RelationType::MATERIALIZED_RELATION: + return "MATERIALIZED_RELATION"; case RelationType::DELETE_RELATION: return "DELETE_RELATION"; case RelationType::UPDATE_RELATION: @@ -5460,6 +5813,9 @@ RelationType EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "VALUE_LIST_RELATION")) { return RelationType::VALUE_LIST_RELATION; } + if (StringUtil::Equals(value, "MATERIALIZED_RELATION")) { + return RelationType::MATERIALIZED_RELATION; + } if (StringUtil::Equals(value, "DELETE_RELATION")) { return RelationType::DELETE_RELATION; } @@ -5579,6 +5935,34 @@ SampleMethod EnumUtil::FromString(const char *value) { throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } +template<> +const char* EnumUtil::ToChars(SampleType value) { + switch(value) { + case SampleType::BLOCKING_SAMPLE: + return "BLOCKING_SAMPLE"; + case SampleType::RESERVOIR_SAMPLE: + return "RESERVOIR_SAMPLE"; + case SampleType::RESERVOIR_PERCENTAGE_SAMPLE: + return "RESERVOIR_PERCENTAGE_SAMPLE"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +SampleType EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "BLOCKING_SAMPLE")) { + return SampleType::BLOCKING_SAMPLE; + } + if (StringUtil::Equals(value, "RESERVOIR_SAMPLE")) { + return SampleType::RESERVOIR_SAMPLE; + } + if (StringUtil::Equals(value, "RESERVOIR_PERCENTAGE_SAMPLE")) { + return SampleType::RESERVOIR_PERCENTAGE_SAMPLE; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + template<> const char* EnumUtil::ToChars(ScanType value) { switch(value) { @@ -6103,6 +6487,8 @@ const char* EnumUtil::ToChars(StatementType value) { return "MULTI_STATEMENT"; case StatementType::COPY_DATABASE_STATEMENT: return "COPY_DATABASE_STATEMENT"; + case StatementType::UPDATE_EXTENSIONS_STATEMENT: + return "UPDATE_EXTENSIONS_STATEMENT"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } @@ -6197,6 +6583,9 @@ StatementType EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "COPY_DATABASE_STATEMENT")) { return StatementType::COPY_DATABASE_STATEMENT; } + if (StringUtil::Equals(value, "UPDATE_EXTENSIONS_STATEMENT")) { + return StatementType::UPDATE_EXTENSIONS_STATEMENT; + } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } @@ -6601,6 +6990,8 @@ const char* EnumUtil::ToChars(TableReferenceType value) { return "PIVOT"; case TableReferenceType::SHOW_REF: return "SHOW_REF"; + case TableReferenceType::COLUMN_DATA: + return "COLUMN_DATA"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } @@ -6638,6 +7029,9 @@ TableReferenceType EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "SHOW_REF")) { return TableReferenceType::SHOW_REF; } + if (StringUtil::Equals(value, "COLUMN_DATA")) { + return TableReferenceType::COLUMN_DATA; + } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } @@ -6652,6 +7046,8 @@ const char* EnumUtil::ToChars(TableScanType value) { return "TABLE_SCAN_COMMITTED_ROWS_DISALLOW_UPDATES"; case TableScanType::TABLE_SCAN_COMMITTED_ROWS_OMIT_PERMANENTLY_DELETED: return "TABLE_SCAN_COMMITTED_ROWS_OMIT_PERMANENTLY_DELETED"; + case TableScanType::TABLE_SCAN_LATEST_COMMITTED_ROWS: + return "TABLE_SCAN_LATEST_COMMITTED_ROWS"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } @@ -6671,6 +7067,9 @@ TableScanType EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "TABLE_SCAN_COMMITTED_ROWS_OMIT_PERMANENTLY_DELETED")) { return TableScanType::TABLE_SCAN_COMMITTED_ROWS_OMIT_PERMANENTLY_DELETED; } + if (StringUtil::Equals(value, "TABLE_SCAN_LATEST_COMMITTED_ROWS")) { + return TableScanType::TABLE_SCAN_LATEST_COMMITTED_ROWS; + } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } @@ -6758,6 +7157,34 @@ TimestampCastResult EnumUtil::FromString(const char *value) throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } +template<> +const char* EnumUtil::ToChars(TransactionModifierType value) { + switch(value) { + case TransactionModifierType::TRANSACTION_DEFAULT_MODIFIER: + return "TRANSACTION_DEFAULT_MODIFIER"; + case TransactionModifierType::TRANSACTION_READ_ONLY: + return "TRANSACTION_READ_ONLY"; + case TransactionModifierType::TRANSACTION_READ_WRITE: + return "TRANSACTION_READ_WRITE"; + default: + throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); + } +} + +template<> +TransactionModifierType EnumUtil::FromString(const char *value) { + if (StringUtil::Equals(value, "TRANSACTION_DEFAULT_MODIFIER")) { + return TransactionModifierType::TRANSACTION_DEFAULT_MODIFIER; + } + if (StringUtil::Equals(value, "TRANSACTION_READ_ONLY")) { + return TransactionModifierType::TRANSACTION_READ_ONLY; + } + if (StringUtil::Equals(value, "TRANSACTION_READ_WRITE")) { + return TransactionModifierType::TRANSACTION_READ_WRITE; + } + throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); +} + template<> const char* EnumUtil::ToChars(TransactionType value) { switch(value) { @@ -6842,6 +7269,8 @@ const char* EnumUtil::ToChars(UndoFlags value) { return "DELETE_TUPLE"; case UndoFlags::UPDATE_TUPLE: return "UPDATE_TUPLE"; + case UndoFlags::SEQUENCE_VALUE: + return "SEQUENCE_VALUE"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } @@ -6864,6 +7293,9 @@ UndoFlags EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "UPDATE_TUPLE")) { return UndoFlags::UPDATE_TUPLE; } + if (StringUtil::Equals(value, "SEQUENCE_VALUE")) { + return UndoFlags::SEQUENCE_VALUE; + } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } diff --git a/src/common/enums/logical_operator_type.cpp b/src/common/enums/logical_operator_type.cpp index c2beaae9640..550bea5beac 100644 --- a/src/common/enums/logical_operator_type.cpp +++ b/src/common/enums/logical_operator_type.cpp @@ -128,6 +128,8 @@ string LogicalOperatorToString(LogicalOperatorType type) { return "CUSTOM_OP"; case LogicalOperatorType::LOGICAL_PIVOT: return "PIVOT"; + case LogicalOperatorType::LOGICAL_UPDATE_EXTENSIONS: + return "UPDATE_EXTENSIONS"; } return "INVALID"; } diff --git a/src/common/enums/optimizer_type.cpp b/src/common/enums/optimizer_type.cpp index d3f13108e41..3a109f646c4 100644 --- a/src/common/enums/optimizer_type.cpp +++ b/src/common/enums/optimizer_type.cpp @@ -24,7 +24,9 @@ static const DefaultOptimizerType internal_optimizer_types[] = { {"common_subexpressions", OptimizerType::COMMON_SUBEXPRESSIONS}, {"common_aggregate", OptimizerType::COMMON_AGGREGATE}, {"column_lifetime", OptimizerType::COLUMN_LIFETIME}, + {"limit_pushdown", OptimizerType::LIMIT_PUSHDOWN}, {"top_n", OptimizerType::TOP_N}, + {"build_side_probe_side", OptimizerType::BUILD_SIDE_PROBE_SIDE}, {"compressed_materialization", OptimizerType::COMPRESSED_MATERIALIZATION}, {"duplicate_groups", OptimizerType::DUPLICATE_GROUPS}, {"reorder_filter", OptimizerType::REORDER_FILTER}, diff --git a/src/common/enums/physical_operator_type.cpp b/src/common/enums/physical_operator_type.cpp index 1d1a3b39c9d..4cb851c989d 100644 --- a/src/common/enums/physical_operator_type.cpp +++ b/src/common/enums/physical_operator_type.cpp @@ -155,6 +155,8 @@ string PhysicalOperatorToString(PhysicalOperatorType type) { return "COPY_DATABASE"; case PhysicalOperatorType::VERIFY_VECTOR: return "VERIFY_VECTOR"; + case PhysicalOperatorType::UPDATE_EXTENSIONS: + return "UPDATE_EXTENSIONS"; case PhysicalOperatorType::INVALID: break; } diff --git a/src/common/enums/relation_type.cpp b/src/common/enums/relation_type.cpp index 3c55f95aeeb..caac469a8e8 100644 --- a/src/common/enums/relation_type.cpp +++ b/src/common/enums/relation_type.cpp @@ -37,6 +37,8 @@ string RelationTypeToString(RelationType type) { return "INSERT_RELATION"; case RelationType::VALUE_LIST_RELATION: return "VALUE_LIST_RELATION"; + case RelationType::MATERIALIZED_RELATION: + return "MATERIALIZED_RELATION"; case RelationType::DELETE_RELATION: return "DELETE_RELATION"; case RelationType::UPDATE_RELATION: diff --git a/src/common/enums/statement_type.cpp b/src/common/enums/statement_type.cpp index eddee179e55..0250ff2cb00 100644 --- a/src/common/enums/statement_type.cpp +++ b/src/common/enums/statement_type.cpp @@ -61,6 +61,8 @@ string StatementTypeToString(StatementType type) { return "DETACH"; case StatementType::MULTI_STATEMENT: return "MULTI"; + case StatementType::UPDATE_EXTENSIONS_STATEMENT: + return "UPDATE_EXTENSIONS"; case StatementType::INVALID_STATEMENT: break; } diff --git a/src/common/error_data.cpp b/src/common/error_data.cpp index add9a273dab..c7262cab73e 100644 --- a/src/common/error_data.cpp +++ b/src/common/error_data.cpp @@ -1,6 +1,6 @@ #include "duckdb/common/error_data.hpp" -#include "duckdb/common/exception.hpp" +#include "duckdb/common/exception.hpp" #include "duckdb/common/string_util.hpp" #include "duckdb/common/to_string.hpp" #include "duckdb/common/types.hpp" @@ -25,6 +25,13 @@ ErrorData::ErrorData(const string &message) : initialized(true), type(ExceptionT // parse the constructed JSON if (message.empty() || message[0] != '{') { // not JSON! Use the message as a raw Exception message and leave type as uninitialized + + if (message == std::bad_alloc().what()) { + type = ExceptionType::OUT_OF_MEMORY; + raw_message = "Allocation failure"; + return; + } + raw_message = message; return; } else { @@ -43,7 +50,15 @@ ErrorData::ErrorData(const string &message) : initialized(true), type(ExceptionT const string &ErrorData::Message() { if (final_message.empty()) { - final_message = Exception::ExceptionTypeToString(type) + " Error: " + raw_message; + if (type != ExceptionType::UNKNOWN_TYPE) { + final_message = Exception::ExceptionTypeToString(type) + " "; + } + final_message += "Error: " + raw_message; + if (type == ExceptionType::INTERNAL) { + final_message += "\nThis error signals an assertion failure within DuckDB. This usually occurs due to " + "unexpected conditions or errors in the program's logic.\nFor more information, see " + "https://duckdb.org/docs/dev/internal_errors"; + } } return final_message; } diff --git a/src/common/extra_type_info.cpp b/src/common/extra_type_info.cpp index d6a63216491..88dacaf37ce 100644 --- a/src/common/extra_type_info.cpp +++ b/src/common/extra_type_info.cpp @@ -17,6 +17,28 @@ ExtraTypeInfo::ExtraTypeInfo(ExtraTypeInfoType type, string alias) : type(type), } ExtraTypeInfo::~ExtraTypeInfo() { } +shared_ptr ExtraTypeInfo::Copy() const { + return make_shared_ptr(*this); +} + +static bool CompareModifiers(const vector &left, const vector &right) { + // Check if the common prefix of the properties is the same for both types + auto common_props = MinValue(left.size(), right.size()); + for (idx_t i = 0; i < common_props; i++) { + if (left[i].type() != right[i].type()) { + return false; + } + // Special case for nulls: + // For type modifiers, NULL is equivalent to ANY + if (left[i].IsNull() || right[i].IsNull()) { + continue; + } + if (left[i] != right[i]) { + return false; + } + } + return true; +} bool ExtraTypeInfo::Equals(ExtraTypeInfo *other_p) const { if (type == ExtraTypeInfoType::INVALID_TYPE_INFO || type == ExtraTypeInfoType::STRING_TYPE_INFO || @@ -31,6 +53,9 @@ bool ExtraTypeInfo::Equals(ExtraTypeInfo *other_p) const { if (alias != other_p->alias) { return false; } + if (!CompareModifiers(modifiers, other_p->modifiers)) { + return false; + } return true; } if (!other_p) { @@ -39,7 +64,13 @@ bool ExtraTypeInfo::Equals(ExtraTypeInfo *other_p) const { if (type != other_p->type) { return false; } - return alias == other_p->alias && EqualsInternal(other_p); + if (alias != other_p->alias) { + return false; + } + if (!CompareModifiers(modifiers, other_p->modifiers)) { + return false; + } + return EqualsInternal(other_p); } bool ExtraTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { @@ -63,6 +94,10 @@ bool DecimalTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { return width == other.width && scale == other.scale; } +shared_ptr DecimalTypeInfo::Copy() const { + return make_shared_ptr(*this); +} + //===--------------------------------------------------------------------===// // String Type Info //===--------------------------------------------------------------------===// @@ -78,6 +113,10 @@ bool StringTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { return true; } +shared_ptr StringTypeInfo::Copy() const { + return make_shared_ptr(*this); +} + //===--------------------------------------------------------------------===// // List Type Info //===--------------------------------------------------------------------===// @@ -93,6 +132,10 @@ bool ListTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { return child_type == other.child_type; } +shared_ptr ListTypeInfo::Copy() const { + return make_shared_ptr(*this); +} + //===--------------------------------------------------------------------===// // Struct Type Info //===--------------------------------------------------------------------===// @@ -108,6 +151,10 @@ bool StructTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { return child_types == other.child_types; } +shared_ptr StructTypeInfo::Copy() const { + return make_shared_ptr(*this); +} + //===--------------------------------------------------------------------===// // Aggregate State Type Info //===--------------------------------------------------------------------===// @@ -125,6 +172,10 @@ bool AggregateStateTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { state_type.bound_argument_types == other.state_type.bound_argument_types; } +shared_ptr AggregateStateTypeInfo::Copy() const { + return make_shared_ptr(*this); +} + //===--------------------------------------------------------------------===// // User Type Info //===--------------------------------------------------------------------===// @@ -135,9 +186,14 @@ UserTypeInfo::UserTypeInfo(string name_p) : ExtraTypeInfo(ExtraTypeInfoType::USER_TYPE_INFO), user_type_name(std::move(name_p)) { } -UserTypeInfo::UserTypeInfo(string catalog_p, string schema_p, string name_p) +UserTypeInfo::UserTypeInfo(string name_p, vector modifiers_p) + : ExtraTypeInfo(ExtraTypeInfoType::USER_TYPE_INFO), user_type_name(std::move(name_p)), + user_type_modifiers(std::move(modifiers_p)) { +} + +UserTypeInfo::UserTypeInfo(string catalog_p, string schema_p, string name_p, vector modifiers_p) : ExtraTypeInfo(ExtraTypeInfoType::USER_TYPE_INFO), catalog(std::move(catalog_p)), schema(std::move(schema_p)), - user_type_name(std::move(name_p)) { + user_type_name(std::move(name_p)), user_type_modifiers(std::move(modifiers_p)) { } bool UserTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { @@ -145,6 +201,10 @@ bool UserTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { return other.user_type_name == user_type_name; } +shared_ptr UserTypeInfo::Copy() const { + return make_shared_ptr(*this); +} + //===--------------------------------------------------------------------===// // Enum Type Info //===--------------------------------------------------------------------===// @@ -318,6 +378,12 @@ void EnumTypeInfo::Serialize(Serializer &serializer) const { [&](Serializer::List &list, idx_t i) { list.WriteElement(strings[i]); }); } +shared_ptr EnumTypeInfo::Copy() const { + Vector values_insert_order_copy(LogicalType::VARCHAR, false, false, 0); + values_insert_order_copy.Reference(values_insert_order); + return make_shared_ptr(values_insert_order_copy, dict_size); +} + //===--------------------------------------------------------------------===// // ArrayTypeInfo //===--------------------------------------------------------------------===// @@ -331,6 +397,10 @@ bool ArrayTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { return child_type == other.child_type && size == other.size; } +shared_ptr ArrayTypeInfo::Copy() const { + return make_shared_ptr(*this); +} + //===--------------------------------------------------------------------===// // Any Type Info //===--------------------------------------------------------------------===// @@ -346,8 +416,12 @@ bool AnyTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { return target_type == other.target_type && cast_score == other.cast_score; } +shared_ptr AnyTypeInfo::Copy() const { + return make_shared_ptr(*this); +} + //===--------------------------------------------------------------------===// -// Any Type Info +// Integer Literal Type Info //===--------------------------------------------------------------------===// IntegerLiteralTypeInfo::IntegerLiteralTypeInfo() : ExtraTypeInfo(ExtraTypeInfoType::INTEGER_LITERAL_TYPE_INFO) { } @@ -361,4 +435,8 @@ bool IntegerLiteralTypeInfo::EqualsInternal(ExtraTypeInfo *other_p) const { return constant_value == other.constant_value; } +shared_ptr IntegerLiteralTypeInfo::Copy() const { + return make_shared_ptr(*this); +} + } // namespace duckdb diff --git a/src/common/file_system.cpp b/src/common/file_system.cpp index f00bbadc068..166b2051797 100644 --- a/src/common/file_system.cpp +++ b/src/common/file_system.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -623,9 +624,14 @@ FileType FileHandle::GetType() { } bool FileSystem::IsRemoteFile(const string &path) { - const string prefixes[] = {"http://", "https://", "s3://", "s3a://", "s3n://", "gcs://", "gs://", "r2://"}; - for (auto &prefix : prefixes) { - if (StringUtil::StartsWith(path, prefix)) { + string extension = ""; + return IsRemoteFile(path, extension); +} + +bool FileSystem::IsRemoteFile(const string &path, string &extension) { + for (const auto &entry : EXTENSION_FILE_PREFIXES) { + if (StringUtil::StartsWith(path, entry.name)) { + extension = entry.extension; return true; } } diff --git a/src/common/filename_pattern.cpp b/src/common/filename_pattern.cpp index 89cc6c63a75..04851ad3fba 100644 --- a/src/common/filename_pattern.cpp +++ b/src/common/filename_pattern.cpp @@ -10,6 +10,7 @@ void FilenamePattern::SetFilenamePattern(const string &pattern) { base = pattern; pos = base.find(id_format); + uuid = false; if (pos != string::npos) { base = StringUtil::Replace(base, id_format, ""); uuid = false; diff --git a/src/common/gzip_file_system.cpp b/src/common/gzip_file_system.cpp index a4e39b90d39..100721a3a6a 100644 --- a/src/common/gzip_file_system.cpp +++ b/src/common/gzip_file_system.cpp @@ -320,9 +320,30 @@ void GZipFileSystem::VerifyGZIPHeader(uint8_t gzip_hdr[], idx_t read_count) { } } +bool GZipFileSystem::CheckIsZip(const char *data, duckdb::idx_t size) { + if (size < GZIP_HEADER_MINSIZE) { + return false; + } + + auto data_ptr = reinterpret_cast(data); + if (data_ptr[0] != 0x1F || data_ptr[1] != 0x8B) { + return false; + } + + if (data_ptr[2] != GZIP_COMPRESSION_DEFLATE) { + return false; + } + + return true; +} + string GZipFileSystem::UncompressGZIPString(const string &in) { + return UncompressGZIPString(in.data(), in.size()); +} + +string GZipFileSystem::UncompressGZIPString(const char *data, idx_t size) { // decompress file - auto body_ptr = in.data(); + auto body_ptr = data; auto mz_stream_ptr = make_uniq(); memset(mz_stream_ptr.get(), 0, sizeof(duckdb_miniz::mz_stream)); @@ -332,7 +353,7 @@ string GZipFileSystem::UncompressGZIPString(const string &in) { // check for incorrectly formatted files // TODO this is mostly the same as gzip_file_system.cpp - if (in.size() < GZIP_HEADER_MINSIZE) { + if (size < GZIP_HEADER_MINSIZE) { throw IOException("Input is not a GZIP stream"); } memcpy(gzip_hdr, body_ptr, GZIP_HEADER_MINSIZE); @@ -348,7 +369,7 @@ string GZipFileSystem::UncompressGZIPString(const string &in) { do { c = *body_ptr; body_ptr++; - } while (c != '\0' && (idx_t)(body_ptr - in.data()) < in.size()); + } while (c != '\0' && (idx_t)(body_ptr - data) < size); } // stream is now set to beginning of payload data @@ -357,7 +378,7 @@ string GZipFileSystem::UncompressGZIPString(const string &in) { throw InternalException("Failed to initialize miniz"); } - auto bytes_remaining = in.size() - NumericCast(body_ptr - in.data()); + auto bytes_remaining = size - NumericCast(body_ptr - data); mz_stream_ptr->next_in = const_uchar_ptr_cast(body_ptr); mz_stream_ptr->avail_in = NumericCast(bytes_remaining); diff --git a/src/common/hive_partitioning.cpp b/src/common/hive_partitioning.cpp index 3ae1f7f3241..92649cef327 100644 --- a/src/common/hive_partitioning.cpp +++ b/src/common/hive_partitioning.cpp @@ -144,6 +144,9 @@ void HivePartitioning::ApplyFiltersToFileList(ClientContext &context, vector= pruned_filters.size()); + get.extra_info.total_files = files.size(); + get.extra_info.filtered_files = pruned_files.size(); + filters = std::move(pruned_filters); files = std::move(pruned_files); } diff --git a/src/common/local_file_system.cpp b/src/common/local_file_system.cpp index 937b018fb86..99420fffbdf 100644 --- a/src/common/local_file_system.cpp +++ b/src/common/local_file_system.cpp @@ -29,6 +29,7 @@ #ifdef __MINGW32__ // need to manually define this for mingw extern "C" WINBASEAPI BOOL WINAPI GetPhysicallyInstalledSystemMemory(PULONGLONG); +extern "C" WINBASEAPI BOOL QueryFullProcessImageNameW(HANDLE, DWORD, LPWSTR, PDWORD); #endif #undef FILE_CREATE // woo mingw @@ -485,9 +486,14 @@ int64_t LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_byte bool LocalFileSystem::Trim(FileHandle &handle, idx_t offset_bytes, idx_t length_bytes) { #if defined(__linux__) + // FALLOC_FL_PUNCH_HOLE requires glibc 2.18 or up +#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 18) + return false; +#else int fd = handle.Cast().fd; int res = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset_bytes, length_bytes); return res == 0; +#endif #else return false; #endif @@ -609,10 +615,15 @@ bool LocalFileSystem::ListFiles(const string &directory, const std::function> dir_unique_ptr(dir, [](DIR *d) { closedir(d); }); + struct dirent *ent; // loop over all files in the directory while ((ent = readdir(dir)) != nullptr) { @@ -635,7 +646,7 @@ bool LocalFileSystem::ListFiles(const string &directory, const std::function + +namespace duckdb { + +// Helper method to do Filter Pushdown into a MultiFileList +bool PushdownInternal(ClientContext &context, const MultiFileReaderOptions &options, LogicalGet &get, + vector> &filters, vector &expanded_files) { + unordered_map column_map; + for (idx_t i = 0; i < get.column_ids.size(); i++) { + if (!IsRowIdColumnId(get.column_ids[i])) { + column_map.insert({get.names[get.column_ids[i]], i}); + } + } + + auto start_files = expanded_files.size(); + HivePartitioning::ApplyFiltersToFileList(context, expanded_files, filters, column_map, get, + options.hive_partitioning, options.filename); + + if (expanded_files.size() != start_files) { + return true; + } + + return false; +} + +//===--------------------------------------------------------------------===// +// MultiFileListIterator +//===--------------------------------------------------------------------===// +MultiFileListIterationHelper MultiFileList::Files() { + return MultiFileListIterationHelper(*this); +} + +MultiFileListIterationHelper::MultiFileListIterationHelper(MultiFileList &file_list_p) : file_list(file_list_p) { +} + +MultiFileListIterationHelper::MultiFileListIterator::MultiFileListIterator(MultiFileList *file_list_p) + : file_list(file_list_p) { + if (!file_list) { + return; + } + + file_list->InitializeScan(file_scan_data); + if (!file_list->Scan(file_scan_data, current_file)) { + // There is no first file: move iterator to nop state + file_list = nullptr; + file_scan_data.current_file_idx = DConstants::INVALID_INDEX; + } +} + +void MultiFileListIterationHelper::MultiFileListIterator::Next() { + if (!file_list) { + return; + } + + if (!file_list->Scan(file_scan_data, current_file)) { + // exhausted collection: move iterator to nop state + file_list = nullptr; + file_scan_data.current_file_idx = DConstants::INVALID_INDEX; + } +} + +MultiFileListIterationHelper::MultiFileListIterator MultiFileListIterationHelper::begin() { // NOLINT: match stl API + return MultiFileListIterationHelper::MultiFileListIterator( + file_list.GetExpandResult() == FileExpandResult::NO_FILES ? nullptr : &file_list); +} +MultiFileListIterationHelper::MultiFileListIterator MultiFileListIterationHelper::end() { // NOLINT: match stl API + return MultiFileListIterationHelper::MultiFileListIterator(nullptr); +} + +MultiFileListIterationHelper::MultiFileListIterator &MultiFileListIterationHelper::MultiFileListIterator::operator++() { + Next(); + return *this; +} + +bool MultiFileListIterationHelper::MultiFileListIterator::operator!=(const MultiFileListIterator &other) const { + return file_list != other.file_list || file_scan_data.current_file_idx != other.file_scan_data.current_file_idx; +} + +const string &MultiFileListIterationHelper::MultiFileListIterator::operator*() const { + return current_file; +} + +//===--------------------------------------------------------------------===// +// MultiFileList +//===--------------------------------------------------------------------===// +MultiFileList::MultiFileList(vector paths, FileGlobOptions options) + : paths(std::move(paths)), glob_options(options) { +} + +MultiFileList::~MultiFileList() { +} + +const vector MultiFileList::GetPaths() const { + return paths; +} + +void MultiFileList::InitializeScan(MultiFileListScanData &iterator) { + iterator.current_file_idx = 0; +} + +bool MultiFileList::Scan(MultiFileListScanData &iterator, string &result_file) { + D_ASSERT(iterator.current_file_idx != DConstants::INVALID_INDEX); + auto maybe_file = GetFile(iterator.current_file_idx); + + if (maybe_file.empty()) { + D_ASSERT(iterator.current_file_idx >= GetTotalFileCount()); + return false; + } + + result_file = maybe_file; + iterator.current_file_idx++; + return true; +} + +unique_ptr MultiFileList::ComplexFilterPushdown(ClientContext &context, + const MultiFileReaderOptions &options, LogicalGet &get, + vector> &filters) { + // By default the filter pushdown into a multifilelist does nothing + return nullptr; +} + +string MultiFileList::GetFirstFile() { + return GetFile(0); +} + +bool MultiFileList::IsEmpty() { + return GetExpandResult() == FileExpandResult::NO_FILES; +} + +//===--------------------------------------------------------------------===// +// SimpleMultiFileList +//===--------------------------------------------------------------------===// +SimpleMultiFileList::SimpleMultiFileList(vector paths_p) + : MultiFileList(std::move(paths_p), FileGlobOptions::ALLOW_EMPTY) { +} + +unique_ptr SimpleMultiFileList::ComplexFilterPushdown(ClientContext &context_p, + const MultiFileReaderOptions &options, + LogicalGet &get, + vector> &filters) { + if (!options.hive_partitioning && !options.filename) { + return nullptr; + } + + // FIXME: don't copy list until first file is filtered + auto file_copy = paths; + auto res = PushdownInternal(context_p, options, get, filters, file_copy); + + if (res) { + return make_uniq(file_copy); + } + + return nullptr; +} + +vector SimpleMultiFileList::GetAllFiles() { + return paths; +} + +FileExpandResult SimpleMultiFileList::GetExpandResult() { + if (paths.size() > 1) { + return FileExpandResult::MULTIPLE_FILES; + } else if (paths.size() == 1) { + return FileExpandResult::SINGLE_FILE; + } + + return FileExpandResult::NO_FILES; +} + +string SimpleMultiFileList::GetFile(idx_t i) { + if (paths.empty() || i >= paths.size()) { + return ""; + } + + return paths[i]; +} + +idx_t SimpleMultiFileList::GetTotalFileCount() { + return paths.size(); +} + +//===--------------------------------------------------------------------===// +// GlobMultiFileList +//===--------------------------------------------------------------------===// +GlobMultiFileList::GlobMultiFileList(ClientContext &context_p, vector paths_p, FileGlobOptions options) + : MultiFileList(std::move(paths_p), options), context(context_p), current_path(0) { +} + +unique_ptr GlobMultiFileList::ComplexFilterPushdown(ClientContext &context_p, + const MultiFileReaderOptions &options, + LogicalGet &get, + vector> &filters) { + lock_guard lck(lock); + + // Expand all + // FIXME: lazy expansion + // FIXME: push down filters into glob + while (ExpandPathInternal()) { + } + + if (!options.hive_partitioning && !options.filename) { + return nullptr; + } + auto res = PushdownInternal(context, options, get, filters, expanded_files); + + if (res) { + return make_uniq(expanded_files); + } + + return nullptr; +} + +vector GlobMultiFileList::GetAllFiles() { + lock_guard lck(lock); + while (ExpandPathInternal()) { + } + return expanded_files; +} + +idx_t GlobMultiFileList::GetTotalFileCount() { + lock_guard lck(lock); + while (ExpandPathInternal()) { + } + return expanded_files.size(); +} + +FileExpandResult GlobMultiFileList::GetExpandResult() { + // GetFile(1) will ensure at least the first 2 files are expanded if they are available + GetFile(1); + + if (expanded_files.size() > 1) { + return FileExpandResult::MULTIPLE_FILES; + } else if (expanded_files.size() == 1) { + return FileExpandResult::SINGLE_FILE; + } + + return FileExpandResult::NO_FILES; +} + +string GlobMultiFileList::GetFile(idx_t i) { + lock_guard lck(lock); + return GetFileInternal(i); +} + +string GlobMultiFileList::GetFileInternal(idx_t i) { + while (expanded_files.size() <= i) { + if (!ExpandPathInternal()) { + return ""; + } + } + D_ASSERT(expanded_files.size() > i); + return expanded_files[i]; +} + +bool GlobMultiFileList::ExpandPathInternal() { + if (IsFullyExpanded()) { + return false; + } + + auto &fs = FileSystem::GetFileSystem(context); + auto glob_files = fs.GlobFiles(paths[current_path], context, glob_options); + std::sort(glob_files.begin(), glob_files.end()); + expanded_files.insert(expanded_files.end(), glob_files.begin(), glob_files.end()); + + current_path++; + + return true; +} + +bool GlobMultiFileList::IsFullyExpanded() { + return current_path == paths.size(); +} + +} // namespace duckdb diff --git a/src/common/multi_file_reader.cpp b/src/common/multi_file_reader.cpp index 97babb7a2f3..5f428b28eab 100644 --- a/src/common/multi_file_reader.cpp +++ b/src/common/multi_file_reader.cpp @@ -8,64 +8,105 @@ #include "duckdb/function/table_function.hpp" #include "duckdb/main/config.hpp" #include "duckdb/planner/operator/logical_get.hpp" +#include "duckdb/common/string_util.hpp" #include namespace duckdb { +MultiFileReaderGlobalState::~MultiFileReaderGlobalState() { +} + +MultiFileReader::~MultiFileReader() { +} + +unique_ptr MultiFileReader::Create(const TableFunction &table_function) { + unique_ptr res; + if (table_function.get_multi_file_reader) { + res = table_function.get_multi_file_reader(); + res->function_name = table_function.name; + } else { + res = make_uniq(); + res->function_name = table_function.name; + } + return res; +} + +unique_ptr MultiFileReader::CreateDefault(const string &function_name) { + auto res = make_uniq(); + res->function_name = function_name; + return res; +} + void MultiFileReader::AddParameters(TableFunction &table_function) { - table_function.named_parameters["filename"] = LogicalType::BOOLEAN; + table_function.named_parameters["filename"] = LogicalType::ANY; table_function.named_parameters["hive_partitioning"] = LogicalType::BOOLEAN; table_function.named_parameters["union_by_name"] = LogicalType::BOOLEAN; table_function.named_parameters["hive_types"] = LogicalType::ANY; table_function.named_parameters["hive_types_autocast"] = LogicalType::BOOLEAN; } -vector MultiFileReader::GetFileList(ClientContext &context, const Value &input, const string &name, - FileGlobOptions options) { - auto &config = DBConfig::GetConfig(context); - if (!config.options.enable_external_access) { - throw PermissionException("Scanning %s files is disabled through configuration", name); - } +vector MultiFileReader::ParsePaths(const Value &input) { if (input.IsNull()) { - throw ParserException("%s reader cannot take NULL list as parameter", name); + throw ParserException("%s cannot take NULL list as parameter", function_name); } - FileSystem &fs = FileSystem::GetFileSystem(context); - vector files; - if (input.type().id() == LogicalTypeId::VARCHAR) { - auto file_name = StringValue::Get(input); - files = fs.GlobFiles(file_name, context, options); - - // Sort the files to ensure that the order is deterministic - std::sort(files.begin(), files.end()); + if (input.type().id() == LogicalTypeId::VARCHAR) { + return {StringValue::Get(input)}; } else if (input.type().id() == LogicalTypeId::LIST) { + vector paths; for (auto &val : ListValue::GetChildren(input)) { if (val.IsNull()) { - throw ParserException("%s reader cannot take NULL input as parameter", name); + throw ParserException("%s reader cannot take NULL input as parameter", function_name); } if (val.type().id() != LogicalTypeId::VARCHAR) { - throw ParserException("%s reader can only take a list of strings as a parameter", name); + throw ParserException("%s reader can only take a list of strings as a parameter", function_name); } - auto glob_files = fs.GlobFiles(StringValue::Get(val), context, options); - std::sort(glob_files.begin(), glob_files.end()); - files.insert(files.end(), glob_files.begin(), glob_files.end()); + paths.push_back(StringValue::Get(val)); } + return paths; } else { - throw InternalException("Unsupported type for MultiFileReader::GetFileList"); + throw InternalException("Unsupported type for MultiFileReader::ParsePaths called with: '%s'"); + } +} + +unique_ptr MultiFileReader::CreateFileList(ClientContext &context, const vector &paths, + FileGlobOptions options) { + auto &config = DBConfig::GetConfig(context); + if (!config.options.enable_external_access) { + throw PermissionException("Scanning %s files is disabled through configuration", function_name); } - if (files.empty() && options == FileGlobOptions::DISALLOW_EMPTY) { - throw IOException("%s reader needs at least one file to read", name); + vector result_files; + + auto res = make_uniq(context, paths, options); + if (res->GetExpandResult() == FileExpandResult::NO_FILES && options == FileGlobOptions::DISALLOW_EMPTY) { + throw IOException("%s needs at least one file to read", function_name); } + return std::move(res); +} - return files; +unique_ptr MultiFileReader::CreateFileList(ClientContext &context, const Value &input, + FileGlobOptions options) { + auto paths = ParsePaths(input); + return CreateFileList(context, paths, options); } bool MultiFileReader::ParseOption(const string &key, const Value &val, MultiFileReaderOptions &options, ClientContext &context) { auto loption = StringUtil::Lower(key); if (loption == "filename") { - options.filename = BooleanValue::Get(val); + if (val.type() == LogicalType::VARCHAR) { + // If not, we interpret it as the name of the column containing the filename + options.filename = true; + options.filename_column = StringValue::Get(val); + } else { + Value boolean_value; + string error_message; + if (val.DefaultTryCastAs(LogicalType::BOOLEAN, boolean_value, &error_message)) { + // If the argument can be cast to boolean, we just interpret it as a boolean + options.filename = BooleanValue::Get(boolean_value); + } + } } else if (loption == "hive_partitioning") { options.hive_partitioning = BooleanValue::Get(val); options.auto_detect_hive_partitioning = false; @@ -99,70 +140,57 @@ bool MultiFileReader::ParseOption(const string &key, const Value &val, MultiFile return true; } -bool MultiFileReader::ComplexFilterPushdown(ClientContext &context, vector &files, - const MultiFileReaderOptions &options, LogicalGet &get, - vector> &filters) { - if (files.empty()) { - return false; - } - if (!options.hive_partitioning && !options.filename) { - return false; - } - - unordered_map column_map; - for (idx_t i = 0; i < get.column_ids.size(); i++) { - if (!IsRowIdColumnId(get.column_ids[i])) { - column_map.insert({get.names[get.column_ids[i]], i}); - } - } - - auto start_files = files.size(); - HivePartitioning::ApplyFiltersToFileList(context, files, filters, column_map, get, options.hive_partitioning, - options.filename); +unique_ptr MultiFileReader::ComplexFilterPushdown(ClientContext &context, MultiFileList &files, + const MultiFileReaderOptions &options, LogicalGet &get, + vector> &filters) { + return files.ComplexFilterPushdown(context, options, get, filters); +} - if (files.size() != start_files) { - // we have pruned files - return true; - } +bool MultiFileReader::Bind(MultiFileReaderOptions &options, MultiFileList &files, vector &return_types, + vector &names, MultiFileReaderBindData &bind_data) { + // The Default MultiFileReader can not perform any binding as it uses MultiFileLists with no schema information. return false; } -MultiFileReaderBindData MultiFileReader::BindOptions(MultiFileReaderOptions &options, const vector &files, - vector &return_types, vector &names) { - MultiFileReaderBindData bind_data; +void MultiFileReader::BindOptions(MultiFileReaderOptions &options, MultiFileList &files, + vector &return_types, vector &names, + MultiFileReaderBindData &bind_data) { // Add generated constant column for filename if (options.filename) { - if (std::find(names.begin(), names.end(), "filename") != names.end()) { - throw BinderException("Using filename option on file with column named filename is not supported"); + if (std::find(names.begin(), names.end(), options.filename_column) != names.end()) { + throw BinderException("Option filename adds column \"%s\", but a column with this name is also in the " + "file. Try setting a different name: filename=''", + options.filename_column); } bind_data.filename_idx = names.size(); return_types.emplace_back(LogicalType::VARCHAR); - names.emplace_back("filename"); + names.emplace_back(options.filename_column); } // Add generated constant columns from hive partitioning scheme if (options.hive_partitioning) { - D_ASSERT(!files.empty()); - auto partitions = HivePartitioning::Parse(files[0]); + D_ASSERT(files.GetExpandResult() != FileExpandResult::NO_FILES); + auto partitions = HivePartitioning::Parse(files.GetFirstFile()); // verify that all files have the same hive partitioning scheme - for (auto &f : files) { - auto file_partitions = HivePartitioning::Parse(f); + for (const auto &file : files.Files()) { + auto file_partitions = HivePartitioning::Parse(file); for (auto &part_info : partitions) { if (file_partitions.find(part_info.first) == file_partitions.end()) { string error = "Hive partition mismatch between file \"%s\" and \"%s\": key \"%s\" not found"; if (options.auto_detect_hive_partitioning == true) { - throw InternalException(error + "(hive partitioning was autodetected)", files[0], f, - part_info.first); + throw InternalException(error + "(hive partitioning was autodetected)", files.GetFirstFile(), + file, part_info.first); } - throw BinderException(error.c_str(), files[0], f, part_info.first); + throw BinderException(error.c_str(), files.GetFirstFile(), file, part_info.first); } } if (partitions.size() != file_partitions.size()) { string error_msg = "Hive partition mismatch between file \"%s\" and \"%s\""; if (options.auto_detect_hive_partitioning == true) { - throw InternalException(error_msg + "(hive partitioning was autodetected)", files[0], f); + throw InternalException(error_msg + "(hive partitioning was autodetected)", files.GetFirstFile(), + file); } - throw BinderException(error_msg.c_str(), files[0], f); + throw BinderException(error_msg.c_str(), files.GetFirstFile(), file); } } @@ -188,14 +216,13 @@ MultiFileReaderBindData MultiFileReader::BindOptions(MultiFileReaderOptions &opt bind_data.hive_partitioning_indexes.emplace_back(part.first, hive_partitioning_index); } } - return bind_data; } void MultiFileReader::FinalizeBind(const MultiFileReaderOptions &file_options, const MultiFileReaderBindData &options, const string &filename, const vector &local_names, const vector &global_types, const vector &global_names, const vector &global_column_ids, MultiFileReaderData &reader_data, - ClientContext &context) { + ClientContext &context, optional_ptr global_state) { // create a map of name -> column index case_insensitive_map_t name_map; @@ -247,10 +274,20 @@ void MultiFileReader::FinalizeBind(const MultiFileReaderOptions &file_options, c } } +unique_ptr +MultiFileReader::InitializeGlobalState(ClientContext &context, const MultiFileReaderOptions &file_options, + const MultiFileReaderBindData &bind_data, const MultiFileList &file_list, + const vector &global_types, const vector &global_names, + const vector &global_column_ids) { + // By default, the multifilereader does not require any global state + return nullptr; +} + void MultiFileReader::CreateNameMapping(const string &file_name, const vector &local_types, const vector &local_names, const vector &global_types, const vector &global_names, const vector &global_column_ids, - MultiFileReaderData &reader_data, const string &initial_file) { + MultiFileReaderData &reader_data, const string &initial_file, + optional_ptr global_state) { D_ASSERT(global_types.size() == global_names.size()); D_ASSERT(local_types.size() == local_names.size()); // we have expected types: create a map of name -> column index @@ -307,6 +344,7 @@ void MultiFileReader::CreateNameMapping(const string &file_name, const vector &local_names, const vector &global_types, const vector &global_names, const vector &global_column_ids, optional_ptr filters, MultiFileReaderData &reader_data, - const string &initial_file) { + const string &initial_file, const MultiFileReaderBindData &options, + optional_ptr global_state) { CreateNameMapping(file_name, local_types, local_names, global_types, global_names, global_column_ids, reader_data, - initial_file); - CreateFilterMap(global_types, filters, reader_data); + initial_file, global_state); + CreateFilterMap(global_types, filters, reader_data, global_state); } void MultiFileReader::CreateFilterMap(const vector &global_types, optional_ptr filters, - MultiFileReaderData &reader_data) { + MultiFileReaderData &reader_data, + optional_ptr global_state) { if (filters) { - reader_data.filter_map.resize(global_types.size()); + auto filter_map_size = global_types.size(); + if (global_state) { + filter_map_size += global_state->extra_columns.size(); + } + reader_data.filter_map.resize(filter_map_size); + for (idx_t c = 0; c < reader_data.column_mapping.size(); c++) { auto map_index = reader_data.column_mapping[c]; reader_data.filter_map[map_index].index = c; @@ -337,8 +382,9 @@ void MultiFileReader::CreateFilterMap(const vector &global_types, o } } -void MultiFileReader::FinalizeChunk(const MultiFileReaderBindData &bind_data, const MultiFileReaderData &reader_data, - DataChunk &chunk) { +void MultiFileReader::FinalizeChunk(ClientContext &context, const MultiFileReaderBindData &bind_data, + const MultiFileReaderData &reader_data, DataChunk &chunk, + optional_ptr global_state) { // reference all the constants set up in MultiFileReader::FinalizeBind for (auto &entry : reader_data.constant_map) { chunk.data[entry.column_id].Reference(entry.value); @@ -359,7 +405,7 @@ HivePartitioningIndex::HivePartitioningIndex(string value_p, idx_t index) : valu } void MultiFileReaderOptions::AddBatchInfo(BindInfo &bind_info) const { - bind_info.InsertOption("filename", Value::BOOLEAN(filename)); + bind_info.InsertOption("filename", Value(filename_column)); bind_info.InsertOption("hive_partitioning", Value::BOOLEAN(hive_partitioning)); bind_info.InsertOption("auto_detect_hive_partitioning", Value::BOOLEAN(auto_detect_hive_partitioning)); bind_info.InsertOption("union_by_name", Value::BOOLEAN(union_by_name)); @@ -387,16 +433,17 @@ void UnionByName::CombineUnionTypes(const vector &col_names, const vecto } } -bool MultiFileReaderOptions::AutoDetectHivePartitioningInternal(const vector &files, ClientContext &context) { +bool MultiFileReaderOptions::AutoDetectHivePartitioningInternal(MultiFileList &files, ClientContext &context) { std::unordered_set partitions; auto &fs = FileSystem::GetFileSystem(context); - auto splits_first_file = StringUtil::Split(files.front(), fs.PathSeparator(files.front())); + auto first_file = files.GetFirstFile(); + auto splits_first_file = StringUtil::Split(first_file, fs.PathSeparator(first_file)); if (splits_first_file.size() < 2) { return false; } - for (auto it = splits_first_file.begin(); it != splits_first_file.end(); it++) { - auto partition = StringUtil::Split(*it, "="); + for (auto &split : splits_first_file) { + auto partition = StringUtil::Split(split, "="); if (partition.size() == 2) { partitions.insert(partition.front()); } @@ -404,7 +451,8 @@ bool MultiFileReaderOptions::AutoDetectHivePartitioningInternal(const vector &files, ClientContext &context) { +void MultiFileReaderOptions::AutoDetectHiveTypesInternal(MultiFileList &files, ClientContext &context) { const LogicalType candidates[] = {LogicalType::DATE, LogicalType::TIMESTAMP, LogicalType::BIGINT}; auto &fs = FileSystem::GetFileSystem(context); unordered_map detected_types; - for (auto &file : files) { + for (const auto &file : files.Files()) { unordered_map partitions; auto splits = StringUtil::Split(file, fs.PathSeparator(file)); if (splits.size() < 2) { @@ -475,8 +523,8 @@ void MultiFileReaderOptions::AutoDetectHiveTypesInternal(const vector &f hive_types_schema.insert(make_pair(entry.first, std::move(entry.second))); } } -void MultiFileReaderOptions::AutoDetectHivePartitioning(const vector &files, ClientContext &context) { - D_ASSERT(!files.empty()); +void MultiFileReaderOptions::AutoDetectHivePartitioning(MultiFileList &files, ClientContext &context) { + D_ASSERT(files.GetExpandResult() != FileExpandResult::NO_FILES); const bool hp_explicitly_disabled = !auto_detect_hive_partitioning && !hive_partitioning; const bool ht_enabled = !hive_types_schema.empty(); if (hp_explicitly_disabled && ht_enabled) { diff --git a/src/common/operator/cast_operators.cpp b/src/common/operator/cast_operators.cpp index 02e30431969..ceb2b7eb99d 100644 --- a/src/common/operator/cast_operators.cpp +++ b/src/common/operator/cast_operators.cpp @@ -922,26 +922,45 @@ bool TryCast::Operation(double input, double &result, bool strict) { //===--------------------------------------------------------------------===// template <> bool TryCast::Operation(string_t input, bool &result, bool strict) { - auto input_data = input.GetData(); + auto input_data = reinterpret_cast(input.GetData()); auto input_size = input.GetSize(); switch (input_size) { case 1: { - char c = UnsafeNumericCast(std::tolower(*input_data)); - if (c == 't' || (!strict && c == '1')) { + unsigned char c = UnsafeNumericCast(std::tolower(*input_data)); + if (c == 't' || (!strict && c == 'y') || (!strict && c == '1')) { result = true; return true; - } else if (c == 'f' || (!strict && c == '0')) { + } else if (c == 'f' || (!strict && c == 'n') || (!strict && c == '0')) { result = false; return true; } return false; } + case 2: { + unsigned char n = UnsafeNumericCast(std::tolower(input_data[0])); + unsigned char o = UnsafeNumericCast(std::tolower(input_data[1])); + if (n == 'n' && o == 'o') { + result = false; + return true; + } + return false; + } + case 3: { + unsigned char y = UnsafeNumericCast(std::tolower(input_data[0])); + unsigned char e = UnsafeNumericCast(std::tolower(input_data[1])); + unsigned char s = UnsafeNumericCast(std::tolower(input_data[2])); + if (y == 'y' && e == 'e' && s == 's') { + result = true; + return true; + } + return false; + } case 4: { - char t = UnsafeNumericCast(std::tolower(input_data[0])); - char r = UnsafeNumericCast(std::tolower(input_data[1])); - char u = UnsafeNumericCast(std::tolower(input_data[2])); - char e = UnsafeNumericCast(std::tolower(input_data[3])); + unsigned char t = UnsafeNumericCast(std::tolower(input_data[0])); + unsigned char r = UnsafeNumericCast(std::tolower(input_data[1])); + unsigned char u = UnsafeNumericCast(std::tolower(input_data[2])); + unsigned char e = UnsafeNumericCast(std::tolower(input_data[3])); if (t == 't' && r == 'r' && u == 'u' && e == 'e') { result = true; return true; @@ -949,11 +968,11 @@ bool TryCast::Operation(string_t input, bool &result, bool strict) { return false; } case 5: { - char f = UnsafeNumericCast(std::tolower(input_data[0])); - char a = UnsafeNumericCast(std::tolower(input_data[1])); - char l = UnsafeNumericCast(std::tolower(input_data[2])); - char s = UnsafeNumericCast(std::tolower(input_data[3])); - char e = UnsafeNumericCast(std::tolower(input_data[4])); + unsigned char f = UnsafeNumericCast(std::tolower(input_data[0])); + unsigned char a = UnsafeNumericCast(std::tolower(input_data[1])); + unsigned char l = UnsafeNumericCast(std::tolower(input_data[2])); + unsigned char s = UnsafeNumericCast(std::tolower(input_data[3])); + unsigned char e = UnsafeNumericCast(std::tolower(input_data[4])); if (f == 'f' && a == 'a' && l == 'l' && s == 's' && e == 'e') { result = false; return true; @@ -1125,8 +1144,8 @@ bool TryCast::Operation(interval_t input, interval_t &result, bool strict) { // Non-Standard Timestamps //===--------------------------------------------------------------------===// template <> -duckdb::string_t CastFromTimestampNS::Operation(duckdb::timestamp_t input, Vector &result) { - return StringCast::Operation(CastTimestampNsToUs::Operation(input), result); +duckdb::string_t CastFromTimestampNS::Operation(duckdb::timestamp_ns_t input, Vector &result) { + return StringCast::Operation(input, result); } template <> duckdb::string_t CastFromTimestampMS::Operation(duckdb::timestamp_t input, Vector &result) { @@ -1142,7 +1161,7 @@ timestamp_t CastTimestampUsToMs::Operation(timestamp_t input) { if (!Timestamp::IsFinite(input)) { return input; } - timestamp_t cast_timestamp(Timestamp::GetEpochMs(input)); + timestamp_t cast_timestamp(Timestamp::GetEpochRounded(input, Interval::MICROS_PER_MSEC)); return cast_timestamp; } @@ -1160,7 +1179,7 @@ timestamp_t CastTimestampUsToSec::Operation(timestamp_t input) { if (!Timestamp::IsFinite(input)) { return input; } - timestamp_t cast_timestamp(Timestamp::GetEpochSeconds(input)); + timestamp_t cast_timestamp(Timestamp::GetEpochRounded(input, Interval::MICROS_PER_SEC)); return cast_timestamp; } @@ -1258,20 +1277,8 @@ dtime_t CastTimestampSecToTime::Operation(timestamp_t input) { // Cast To Timestamp //===--------------------------------------------------------------------===// template <> -bool TryCastToTimestampNS::Operation(string_t input, timestamp_t &result, bool strict) { - if (!TryCast::Operation(input, result, strict)) { - return false; - } - if (!Timestamp::IsFinite(result)) { - return true; - } - - int64_t nanoseconds; - if (!Timestamp::TryGetEpochNanoSeconds(result, nanoseconds)) { - throw ConversionException("Could not convert VARCHAR value '%s' to Timestamp(NS)", input.GetString()); - } - result = nanoseconds; - return true; +bool TryCastToTimestampNS::Operation(string_t input, timestamp_ns_t &result, bool strict) { + return TryCast::Operation(input, result, strict); } template <> @@ -1279,10 +1286,7 @@ bool TryCastToTimestampMS::Operation(string_t input, timestamp_t &result, bool s if (!TryCast::Operation(input, result, strict)) { return false; } - if (!Timestamp::IsFinite(result)) { - return true; - } - result = Timestamp::GetEpochMs(result); + result = CastTimestampUsToMs::Operation(result); return true; } @@ -1291,15 +1295,12 @@ bool TryCastToTimestampSec::Operation(string_t input, timestamp_t &result, bool if (!TryCast::Operation(input, result, strict)) { return false; } - if (!Timestamp::IsFinite(result)) { - return true; - } - result = Timestamp::GetEpochSeconds(result); + result = CastTimestampUsToSec::Operation(result); return true; } template <> -bool TryCastToTimestampNS::Operation(date_t input, timestamp_t &result, bool strict) { +bool TryCastToTimestampNS::Operation(date_t input, timestamp_ns_t &result, bool strict) { if (!TryCast::Operation(input, result, strict)) { return false; } @@ -1564,11 +1565,27 @@ bool TryCast::Operation(string_t input, timestamp_t &result, bool strict) { return Timestamp::TryConvertTimestamp(input.GetData(), input.GetSize(), result) == TimestampCastResult::SUCCESS; } +template <> +bool TryCast::Operation(string_t input, timestamp_ns_t &result, bool strict) { + return Timestamp::TryConvertTimestamp(input.GetData(), input.GetSize(), result) == TimestampCastResult::SUCCESS; +} + template <> timestamp_t Cast::Operation(string_t input) { return Timestamp::FromCString(input.GetData(), input.GetSize()); } +template <> +timestamp_ns_t Cast::Operation(string_t input) { + int32_t nanos; + const auto ts = Timestamp::FromCString(input.GetData(), input.GetSize(), &nanos); + timestamp_ns_t result; + if (!Timestamp::TryFromTimestampNanos(ts, nanos, result)) { + throw ConversionException(Timestamp::ConversionError(input)); + } + return result; +} + //===--------------------------------------------------------------------===// // Cast From Interval //===--------------------------------------------------------------------===// @@ -1588,12 +1605,13 @@ bool TryCastErrorMessage::Operation(string_t input, interval_t &result, CastPara // when that value is full, we perform a HUGEINT multiplication to flush it into the hugeint // this takes the number of HUGEINT multiplications down from [0-38] to [0-2] -template +template struct HugeIntCastData { using ResultType = T; + using IntermediateType = INTERMEDIATE_T; using Operation = OP; ResultType result; - ResultType intermediate; + IntermediateType intermediate; uint8_t digits; ResultType decimal; @@ -1647,8 +1665,8 @@ struct HugeIntegerCastOperation { template static bool HandleDigit(T &state, uint8_t digit) { if (NEGATIVE) { - if (DUCKDB_UNLIKELY(static_cast(state.intermediate) < - (NumericLimits::Minimum() + digit) / 10)) { + if (DUCKDB_UNLIKELY(state.intermediate < + (NumericLimits::Minimum() + digit) / 10)) { // intermediate is full: need to flush it if (!state.Flush()) { return false; @@ -1656,7 +1674,8 @@ struct HugeIntegerCastOperation { } state.intermediate = state.intermediate * 10 - digit; } else { - if (DUCKDB_UNLIKELY(state.intermediate > (NumericLimits::Maximum() - digit) / 10)) { + if (DUCKDB_UNLIKELY(state.intermediate > + (NumericLimits::Maximum() - digit) / 10)) { if (!state.Flush()) { return false; } @@ -1790,8 +1809,8 @@ struct HugeIntegerCastOperation { template <> bool TryCast::Operation(string_t input, hugeint_t &result, bool strict) { - HugeIntCastData state {}; - if (!TryIntegerCast, true, true, HugeIntegerCastOperation>( + HugeIntCastData state {}; + if (!TryIntegerCast, true, true, HugeIntegerCastOperation>( input.GetData(), input.GetSize(), state, strict)) { return false; } @@ -1801,8 +1820,8 @@ bool TryCast::Operation(string_t input, hugeint_t &result, bool strict) { template <> bool TryCast::Operation(string_t input, uhugeint_t &result, bool strict) { - HugeIntCastData state {}; - if (!TryIntegerCast, false, true, HugeIntegerCastOperation>( + HugeIntCastData state {}; + if (!TryIntegerCast, false, true, HugeIntegerCastOperation>( input.GetData(), input.GetSize(), state, strict)) { return false; } @@ -1814,205 +1833,6 @@ bool TryCast::Operation(string_t input, uhugeint_t &result, bool strict) { // Decimal String Cast //===--------------------------------------------------------------------===// -template -struct DecimalCastData { - using StoreType = T; - StoreType result; - uint8_t width; - uint8_t scale; - uint8_t digit_count; - uint8_t decimal_count; - //! Whether we have determined if the result should be rounded - bool round_set; - //! If the result should be rounded - bool should_round; - //! Only set when ALLOW_EXPONENT is enabled - enum class ExponentType : uint8_t { NONE, POSITIVE, NEGATIVE }; - uint8_t excessive_decimals; - ExponentType exponent_type; -}; - -struct DecimalCastOperation { - template - static bool HandleDigit(T &state, uint8_t digit) { - if (state.result == 0 && digit == 0) { - // leading zero's don't count towards the digit count - return true; - } - if (state.digit_count == state.width - state.scale) { - // width of decimal type is exceeded! - return false; - } - state.digit_count++; - if (NEGATIVE) { - if (state.result < (NumericLimits::Minimum() / 10)) { - return false; - } - state.result = state.result * 10 - digit; - } else { - if (state.result > (NumericLimits::Maximum() / 10)) { - return false; - } - state.result = state.result * 10 + digit; - } - return true; - } - - template - static bool HandleHexDigit(T &state, uint8_t digit) { - return false; - } - - template - static bool HandleBinaryDigit(T &state, uint8_t digit) { - return false; - } - - template - static void RoundUpResult(T &state) { - if (NEGATIVE) { - state.result -= 1; - } else { - state.result += 1; - } - } - - template - static bool HandleExponent(T &state, int32_t exponent) { - auto decimal_excess = (state.decimal_count > state.scale) ? state.decimal_count - state.scale : 0; - if (exponent > 0) { - state.exponent_type = T::ExponentType::POSITIVE; - // Positive exponents need up to 'exponent' amount of digits - // Everything beyond that amount needs to be truncated - if (decimal_excess > exponent) { - // We've allowed too many decimals - state.excessive_decimals = UnsafeNumericCast(decimal_excess - exponent); - exponent = 0; - } else { - exponent -= decimal_excess; - } - D_ASSERT(exponent >= 0); - } else if (exponent < 0) { - state.exponent_type = T::ExponentType::NEGATIVE; - } - if (!Finalize(state)) { - return false; - } - if (exponent < 0) { - bool round_up = false; - for (idx_t i = 0; i < idx_t(-int64_t(exponent)); i++) { - auto mod = state.result % 10; - round_up = NEGATIVE ? mod <= -5 : mod >= 5; - state.result /= 10; - if (state.result == 0) { - break; - } - } - if (round_up) { - RoundUpResult(state); - } - return true; - } else { - // positive exponent: append 0's - for (idx_t i = 0; i < idx_t(exponent); i++) { - if (!HandleDigit(state, 0)) { - return false; - } - } - return true; - } - } - - template - static bool HandleDecimal(T &state, uint8_t digit) { - if (state.decimal_count == state.scale && !state.round_set) { - // Determine whether the last registered decimal should be rounded or not - state.round_set = true; - state.should_round = digit >= 5; - } - if (!ALLOW_EXPONENT && state.decimal_count == state.scale) { - // we exceeded the amount of supported decimals - // however, we don't throw an error here - // we just truncate the decimal - return true; - } - //! If we expect an exponent, we need to preserve the decimals - //! But we don't want to overflow, so we prevent overflowing the result with this check - if (state.digit_count + state.decimal_count >= DecimalWidth::max) { - return true; - } - state.decimal_count++; - if (NEGATIVE) { - state.result = state.result * 10 - digit; - } else { - state.result = state.result * 10 + digit; - } - return true; - } - - template - static bool TruncateExcessiveDecimals(T &state) { - D_ASSERT(state.excessive_decimals); - bool round_up = false; - for (idx_t i = 0; i < state.excessive_decimals; i++) { - auto mod = state.result % 10; - round_up = NEGATIVE ? mod <= -5 : mod >= 5; - state.result /= static_cast(10.0); - } - //! Only round up when exponents are involved - if (state.exponent_type == T::ExponentType::POSITIVE && round_up) { - RoundUpResult(state); - } - D_ASSERT(state.decimal_count > state.scale); - state.decimal_count = state.scale; - return true; - } - - template - static bool Finalize(T &state) { - if (state.exponent_type != T::ExponentType::POSITIVE && state.decimal_count > state.scale) { - //! Did not encounter an exponent, but ALLOW_EXPONENT was on - state.excessive_decimals = state.decimal_count - state.scale; - } - if (state.excessive_decimals && !TruncateExcessiveDecimals(state)) { - return false; - } - if (state.exponent_type == T::ExponentType::NONE && state.round_set && state.should_round) { - RoundUpResult(state); - } - // if we have not gotten exactly "scale" decimals, we need to multiply the result - // e.g. if we have a string "1.0" that is cast to a DECIMAL(9,3), the value needs to be 1000 - // but we have only gotten the value "10" so far, so we multiply by 1000 - for (uint8_t i = state.decimal_count; i < state.scale; i++) { - state.result *= 10; - } - return true; - } -}; - -template -bool TryDecimalStringCast(string_t input, T &result, CastParameters ¶meters, uint8_t width, uint8_t scale) { - DecimalCastData state; - state.result = 0; - state.width = width; - state.scale = scale; - state.digit_count = 0; - state.decimal_count = 0; - state.excessive_decimals = 0; - state.exponent_type = DecimalCastData::ExponentType::NONE; - state.round_set = false; - state.should_round = false; - if (!TryIntegerCast, true, true, DecimalCastOperation, false, decimal_separator>( - input.GetData(), input.GetSize(), state, false)) { - string error = StringUtil::Format("Could not convert string \"%s\" to DECIMAL(%d,%d)", input.GetString(), - (int)width, (int)scale); - HandleCastError::AssignError(error, parameters); - return false; - } - result = state.result; - return true; -} - template <> bool TryCastToDecimal::Operation(string_t input, int16_t &result, CastParameters ¶meters, uint8_t width, uint8_t scale) { @@ -2063,22 +1883,22 @@ bool TryCastToDecimalCommaSeparated::Operation(string_t input, hugeint_t &result template <> string_t StringCastFromDecimal::Operation(int16_t input, uint8_t width, uint8_t scale, Vector &result) { - return DecimalToString::Format(input, width, scale, result); + return DecimalToString::Format(input, width, scale, result); } template <> string_t StringCastFromDecimal::Operation(int32_t input, uint8_t width, uint8_t scale, Vector &result) { - return DecimalToString::Format(input, width, scale, result); + return DecimalToString::Format(input, width, scale, result); } template <> string_t StringCastFromDecimal::Operation(int64_t input, uint8_t width, uint8_t scale, Vector &result) { - return DecimalToString::Format(input, width, scale, result); + return DecimalToString::Format(input, width, scale, result); } template <> string_t StringCastFromDecimal::Operation(hugeint_t input, uint8_t width, uint8_t scale, Vector &result) { - return HugeintToStringCast::FormatDecimal(input, width, scale, result); + return DecimalToString::Format(input, width, scale, result); } //===--------------------------------------------------------------------===// diff --git a/src/common/operator/string_cast.cpp b/src/common/operator/string_cast.cpp index be3d604910b..df4ba7ac89e 100644 --- a/src/common/operator/string_cast.cpp +++ b/src/common/operator/string_cast.cpp @@ -56,6 +56,10 @@ template <> duckdb::string_t StringCast::Operation(uint64_t input, Vector &vector) { return NumericHelper::FormatSigned(input, vector); } +template <> +duckdb::string_t StringCast::Operation(hugeint_t input, Vector &vector) { + return NumericHelper::FormatSigned(input, vector); +} template <> string_t StringCast::Operation(float input, Vector &vector) { @@ -76,11 +80,6 @@ string_t StringCast::Operation(interval_t input, Vector &vector) { return StringVector::AddString(vector, buffer, length); } -template <> -duckdb::string_t StringCast::Operation(hugeint_t input, Vector &vector) { - return HugeintToStringCast::FormatSigned(input, vector); -} - template <> duckdb::string_t StringCast::Operation(uhugeint_t input, Vector &vector) { return UhugeintToStringCast::Format(input, vector); @@ -126,8 +125,8 @@ duckdb::string_t StringCast::Operation(dtime_t input, Vector &vector) { return result; } -template <> -duckdb::string_t StringCast::Operation(timestamp_t input, Vector &vector) { +template +duckdb::string_t StringFromTimestamp(timestamp_t input, Vector &vector) { if (input == timestamp_t::infinity()) { return StringVector::AddString(vector, Date::PINF); } else if (input == timestamp_t::ninfinity()) { @@ -135,7 +134,16 @@ duckdb::string_t StringCast::Operation(timestamp_t input, Vector &vector) { } date_t date_entry; dtime_t time_entry; - Timestamp::Convert(input, date_entry, time_entry); + int32_t picos = 0; + if (HAS_NANOS) { + timestamp_ns_t ns; + ns.value = input.value; + Timestamp::Convert(ns, date_entry, time_entry, picos); + // Use picoseconds so we have 6 digits + picos *= 1000; + } else { + Timestamp::Convert(input, date_entry, time_entry); + } int32_t date[3], time[4]; Date::Convert(date_entry, date[0], date[1], date[2]); @@ -145,21 +153,43 @@ duckdb::string_t StringCast::Operation(timestamp_t input, Vector &vector) { idx_t year_length; bool add_bc; char micro_buffer[6]; + char nano_buffer[6]; idx_t date_length = DateToStringCast::Length(date, year_length, add_bc); idx_t time_length = TimeToStringCast::Length(time, micro_buffer); - idx_t length = date_length + time_length + 1; + idx_t nano_length = 0; + if (picos) { + // If there are ps, we need all the µs + time_length = 15; + nano_length = 6; + nano_length -= NumericCast(TimeToStringCast::FormatMicros(picos, nano_buffer)); + } + const idx_t length = date_length + 1 + time_length + nano_length; string_t result = StringVector::EmptyString(vector, length); auto data = result.GetDataWriteable(); DateToStringCast::Format(data, date, year_length, add_bc); - data[date_length] = ' '; - TimeToStringCast::Format(data + date_length + 1, time_length, time, micro_buffer); + data += date_length; + *data++ = ' '; + TimeToStringCast::Format(data, time_length, time, micro_buffer); + data += time_length; + memcpy(data, nano_buffer, nano_length); + D_ASSERT(data + nano_length <= result.GetDataWriteable() + length); result.Finalize(); return result; } +template <> +duckdb::string_t StringCast::Operation(timestamp_t input, Vector &vector) { + return StringFromTimestamp(input, vector); +} + +template <> +duckdb::string_t StringCast::Operation(timestamp_ns_t input, Vector &vector) { + return StringFromTimestamp(input, vector); +} + template <> duckdb::string_t StringCast::Operation(duckdb::string_t input, Vector &result) { return StringVector::AddStringOrBlob(result, input); diff --git a/src/common/printer.cpp b/src/common/printer.cpp index 2c24069c14f..0c704b74d99 100644 --- a/src/common/printer.cpp +++ b/src/common/printer.cpp @@ -62,7 +62,7 @@ idx_t Printer::TerminalWidth() { #ifndef DUCKDB_DISABLE_PRINT #ifdef DUCKDB_WINDOWS CONSOLE_SCREEN_BUFFER_INFO csbi; - int columns, rows; + int rows; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); rows = csbi.srWindow.Right - csbi.srWindow.Left + 1; diff --git a/src/common/row_operations/row_heap_gather.cpp b/src/common/row_operations/row_heap_gather.cpp index dbcfea6c186..fa433c64e12 100644 --- a/src/common/row_operations/row_heap_gather.cpp +++ b/src/common/row_operations/row_heap_gather.cpp @@ -153,6 +153,8 @@ static void HeapGatherArrayVector(Vector &v, const idx_t vcount, const Selection data_ptr_t array_validitymask_location = key_locations[i]; key_locations[i] += array_validitymask_size; + NestedValidity parent_validity(array_validitymask_location); + // The size of each variable size entry is stored after the validity mask // (if the child type is variable size) data_ptr_t var_entry_size_ptr = nullptr; @@ -164,8 +166,8 @@ static void HeapGatherArrayVector(Vector &v, const idx_t vcount, const Selection // row idx const auto row_idx = sel.get_index(i); - auto array_start = row_idx * array_size; - auto elem_remaining = array_size; + idx_t array_start = row_idx * array_size; + idx_t elem_remaining = array_size; while (elem_remaining > 0) { auto chunk_size = MinValue(static_cast(STANDARD_VECTOR_SIZE), elem_remaining); @@ -190,11 +192,11 @@ static void HeapGatherArrayVector(Vector &v, const idx_t vcount, const Selection } // Pass on this array's validity mask to the child vector - NestedValidity parent_validity(array_validitymask_location); RowOperations::HeapGather(child_vector, chunk_size, array_sel, array_entry_locations, &parent_validity); elem_remaining -= chunk_size; array_start += chunk_size; + parent_validity.OffsetListBy(chunk_size); } } } diff --git a/src/common/row_operations/row_heap_scatter.cpp b/src/common/row_operations/row_heap_scatter.cpp index 3c7f9d41e92..01cf7b5897e 100644 --- a/src/common/row_operations/row_heap_scatter.cpp +++ b/src/common/row_operations/row_heap_scatter.cpp @@ -8,18 +8,22 @@ namespace duckdb { using ValidityBytes = TemplatedValidityMask; NestedValidity::NestedValidity(data_ptr_t validitymask_location) - : list_validity_location(validitymask_location), struct_validity_locations(nullptr), entry_idx(0), idx_in_entry(0) { + : list_validity_location(validitymask_location), struct_validity_locations(nullptr), entry_idx(0), idx_in_entry(0), + list_validity_offset(0) { } NestedValidity::NestedValidity(data_ptr_t *validitymask_locations, idx_t child_vector_index) - : list_validity_location(nullptr), struct_validity_locations(validitymask_locations), entry_idx(0), - idx_in_entry(0) { + : list_validity_location(nullptr), struct_validity_locations(validitymask_locations), entry_idx(0), idx_in_entry(0), + list_validity_offset(0) { ValidityBytes::GetEntryIndex(child_vector_index, entry_idx, idx_in_entry); } void NestedValidity::SetInvalid(idx_t idx) { if (list_validity_location) { // Is List + + idx = idx + list_validity_offset; + idx_t list_entry_idx; idx_t list_idx_in_entry; ValidityBytes::GetEntryIndex(idx, list_entry_idx, list_idx_in_entry); @@ -32,9 +36,16 @@ void NestedValidity::SetInvalid(idx_t idx) { } } +void NestedValidity::OffsetListBy(idx_t offset) { + list_validity_offset += offset; +} + bool NestedValidity::IsValid(idx_t idx) { if (list_validity_location) { // Is List + + idx = idx + list_validity_offset; + idx_t list_entry_idx; idx_t list_idx_in_entry; ValidityBytes::GetEntryIndex(idx, list_entry_idx, list_idx_in_entry); @@ -437,6 +448,8 @@ static void HeapScatterArrayVector(Vector &v, idx_t vcount, const SelectionVecto memset(array_validitymask_location, -1, array_validitymask_size); key_locations[i] += array_validitymask_size; + NestedValidity array_parent_validity(array_validitymask_location); + // If the array contains variable size entries, we reserve spaces for them here data_ptr_t var_entry_size_ptr = nullptr; if (child_type_is_var_size) { @@ -474,7 +487,6 @@ static void HeapScatterArrayVector(Vector &v, idx_t vcount, const SelectionVecto } } - NestedValidity array_parent_validity(array_validitymask_location); RowOperations::HeapScatter(child_vector, ArrayVector::GetTotalSize(v), *FlatVector::IncrementalSelectionVector(), chunk_size, array_entry_locations, &array_parent_validity, array_start); @@ -482,6 +494,7 @@ static void HeapScatterArrayVector(Vector &v, idx_t vcount, const SelectionVecto // update for next iteration elem_remaining -= chunk_size; array_start += chunk_size; + array_parent_validity.OffsetListBy(chunk_size); } } } diff --git a/src/common/row_operations/row_matcher.cpp b/src/common/row_operations/row_matcher.cpp index 23b16946644..fe45a65d782 100644 --- a/src/common/row_operations/row_matcher.cpp +++ b/src/common/row_operations/row_matcher.cpp @@ -198,6 +198,22 @@ void RowMatcher::Initialize(const bool no_match_sel, const TupleDataLayout &layo } } +void RowMatcher::Initialize(const bool no_match_sel, const TupleDataLayout &layout, const Predicates &predicates, + vector &columns) { + + // The columns must have the same size as the predicates vector + D_ASSERT(columns.size() == predicates.size()); + + // The largest column_id must be smaller than the number of types to not cause an out-of-bounds error + D_ASSERT(*max_element(columns.begin(), columns.end()) < layout.GetTypes().size()); + + match_functions.reserve(predicates.size()); + for (idx_t idx = 0; idx < predicates.size(); idx++) { + column_t col_idx = columns[idx]; + match_functions.push_back(GetMatchFunction(no_match_sel, layout.GetTypes()[col_idx], predicates[idx])); + } +} + idx_t RowMatcher::Match(DataChunk &lhs, const vector &lhs_formats, SelectionVector &sel, idx_t count, const TupleDataLayout &rhs_layout, Vector &rhs_row_locations, SelectionVector *no_match_sel, idx_t &no_match_count) { @@ -211,6 +227,30 @@ idx_t RowMatcher::Match(DataChunk &lhs, const vector &lhs return count; } +idx_t RowMatcher::Match(DataChunk &lhs, const vector &lhs_formats, SelectionVector &sel, + idx_t count, const TupleDataLayout &rhs_layout, Vector &rhs_row_locations, + SelectionVector *no_match_sel, idx_t &no_match_count, const vector &columns) { + D_ASSERT(!match_functions.empty()); + + // The column_ids must have the same size as the match_functions vector + D_ASSERT(columns.size() == match_functions.size()); + + // The largest column_id must be smaller than the number columns to not cause an out-of-bounds error + D_ASSERT(*max_element(columns.begin(), columns.end()) < lhs.ColumnCount()); + + for (idx_t fun_idx = 0; fun_idx < match_functions.size(); fun_idx++) { + // if we only care about specific columns, we need to use the column_ids to get the correct column index + // otherwise, we just use the fun_idx + const auto col_idx = columns[fun_idx]; + + const auto &match_function = match_functions[fun_idx]; + count = + match_function.function(lhs.data[col_idx], lhs_formats[col_idx], sel, count, rhs_layout, rhs_row_locations, + col_idx, match_function.child_functions, no_match_sel, no_match_count); + } + return count; +} + MatchFunction RowMatcher::GetMatchFunction(const bool no_match_sel, const LogicalType &type, const ExpressionType predicate) { return no_match_sel ? GetMatchFunction(type, predicate) : GetMatchFunction(type, predicate); diff --git a/src/common/row_operations/row_radix_scatter.cpp b/src/common/row_operations/row_radix_scatter.cpp index 01557ca455c..73242d13c82 100644 --- a/src/common/row_operations/row_radix_scatter.cpp +++ b/src/common/row_operations/row_radix_scatter.cpp @@ -125,7 +125,7 @@ void RadixScatterListVector(Vector &v, UnifiedVectorFormat &vdata, const Selecti key_locations[i][0] = 1; key_locations[i]++; RowOperations::RadixScatter(child_vector, list_size, *FlatVector::IncrementalSelectionVector(), 1, - key_locations + i, false, true, false, prefix_len, width - 1, + key_locations + i, false, true, false, prefix_len, width - 2, list_entry.offset); } else { // denote that the list is empty with a 0 diff --git a/src/common/serializer/buffered_file_writer.cpp b/src/common/serializer/buffered_file_writer.cpp index be4f51fc3c7..ce0113f1d4a 100644 --- a/src/common/serializer/buffered_file_writer.cpp +++ b/src/common/serializer/buffered_file_writer.cpp @@ -14,8 +14,8 @@ BufferedFileWriter::BufferedFileWriter(FileSystem &fs, const string &path_p, Fil handle = fs.OpenFile(path, open_flags | FileLockType::WRITE_LOCK); } -int64_t BufferedFileWriter::GetFileSize() { - return fs.GetFileSize(*handle) + NumericCast(offset); +idx_t BufferedFileWriter::GetFileSize() { + return NumericCast(fs.GetFileSize(*handle)) + offset; } idx_t BufferedFileWriter::GetTotalWritten() { @@ -65,20 +65,26 @@ void BufferedFileWriter::Flush() { offset = 0; } +void BufferedFileWriter::Close() { + Flush(); + handle->Close(); + handle.reset(); +} + void BufferedFileWriter::Sync() { Flush(); handle->Sync(); } -void BufferedFileWriter::Truncate(int64_t size) { - auto persistent = fs.GetFileSize(*handle); - D_ASSERT(size <= persistent + NumericCast(offset)); +void BufferedFileWriter::Truncate(idx_t size) { + auto persistent = NumericCast(fs.GetFileSize(*handle)); + D_ASSERT(size <= persistent + offset); if (persistent <= size) { // truncating into the pending write buffer. - offset = NumericCast(size - persistent); + offset = size - persistent; } else { // truncate the physical file on disk - handle->Truncate(size); + handle->Truncate(NumericCast(size)); // reset anything written in the buffer offset = 0; } diff --git a/src/common/serializer/memory_stream.cpp b/src/common/serializer/memory_stream.cpp index 6064ebe1a84..a4869696316 100644 --- a/src/common/serializer/memory_stream.cpp +++ b/src/common/serializer/memory_stream.cpp @@ -2,8 +2,13 @@ namespace duckdb { -MemoryStream::MemoryStream(idx_t capacity) - : position(0), capacity(capacity), owns_data(true), data(static_cast(malloc(capacity))) { +MemoryStream::MemoryStream(idx_t capacity) : position(0), capacity(capacity), owns_data(true) { + D_ASSERT(capacity != 0 && IsPowerOfTwo(capacity)); + auto data_malloc_result = malloc(capacity); + if (!data_malloc_result) { + throw std::bad_alloc(); + } + data = static_cast(data_malloc_result); } MemoryStream::MemoryStream(data_ptr_t buffer, idx_t capacity) @@ -25,7 +30,6 @@ void MemoryStream::WriteData(const_data_ptr_t source, idx_t write_size) { throw SerializationException("Failed to serialize: not enough space in buffer to fulfill write request"); } } - memcpy(data + position, source, write_size); position += write_size; } diff --git a/src/common/serializer/serializer.cpp b/src/common/serializer/serializer.cpp index e74461203ca..91a7f4772c0 100644 --- a/src/common/serializer/serializer.cpp +++ b/src/common/serializer/serializer.cpp @@ -17,7 +17,7 @@ template <> void Serializer::WritePropertyWithDefault(const field_id_t field_id, const char *tag, const Value &value, const Value &&default_value) { // If current value is default, don't write it - if (!serialize_default_values && ValueOperations::NotDistinctFrom(value, default_value)) { + if (!options.serialize_default_values && ValueOperations::NotDistinctFrom(value, default_value)) { OnOptionalPropertyBegin(field_id, tag, false); OnOptionalPropertyEnd(false); return; diff --git a/src/common/sort/partition_state.cpp b/src/common/sort/partition_state.cpp index 5346d057a38..b92a04a8163 100644 --- a/src/common/sort/partition_state.cpp +++ b/src/common/sort/partition_state.cpp @@ -11,7 +11,7 @@ namespace duckdb { PartitionGlobalHashGroup::PartitionGlobalHashGroup(BufferManager &buffer_manager, const Orders &partitions, const Orders &orders, const Types &payload_types, bool external) - : count(0), batch_base(0) { + : count(0) { RowLayout payload_layout; payload_layout.Initialize(payload_types); @@ -401,11 +401,11 @@ void PartitionLocalSinkState::Combine() { PartitionGlobalMergeState::PartitionGlobalMergeState(PartitionGlobalSinkState &sink, GroupDataPtr group_data_p, hash_t hash_bin) - : sink(sink), group_data(std::move(group_data_p)), memory_per_thread(sink.memory_per_thread), + : sink(sink), group_data(std::move(group_data_p)), group_idx(sink.hash_groups.size()), + memory_per_thread(sink.memory_per_thread), num_threads(NumericCast(TaskScheduler::GetScheduler(sink.context).NumberOfThreads())), stage(PartitionSortStage::INIT), total_tasks(0), tasks_assigned(0), tasks_completed(0) { - const auto group_idx = sink.hash_groups.size(); auto new_group = make_uniq(sink.buffer_manager, sink.partitions, sink.orders, sink.payload_types, sink.external); sink.hash_groups.emplace_back(std::move(new_group)); @@ -423,12 +423,11 @@ PartitionGlobalMergeState::PartitionGlobalMergeState(PartitionGlobalSinkState &s } PartitionGlobalMergeState::PartitionGlobalMergeState(PartitionGlobalSinkState &sink) - : sink(sink), memory_per_thread(sink.memory_per_thread), + : sink(sink), group_idx(0), memory_per_thread(sink.memory_per_thread), num_threads(NumericCast(TaskScheduler::GetScheduler(sink.context).NumberOfThreads())), stage(PartitionSortStage::INIT), total_tasks(0), tasks_assigned(0), tasks_completed(0) { const hash_t hash_bin = 0; - const size_t group_idx = 0; hash_group = sink.hash_groups[group_idx].get(); global_sort = sink.hash_groups[group_idx]->global_sort.get(); @@ -448,6 +447,10 @@ void PartitionLocalMergeState::Merge() { merge_sorter.PerformInMergeRound(); } +void PartitionLocalMergeState::Sorted() { + merge_state->sink.OnSortedPartition(merge_state->group_idx); +} + void PartitionLocalMergeState::ExecuteTask() { switch (stage) { case PartitionSortStage::SCAN: @@ -459,6 +462,9 @@ void PartitionLocalMergeState::ExecuteTask() { case PartitionSortStage::MERGE: Merge(); break; + case PartitionSortStage::SORTED: + Sorted(); + break; default: throw InternalException("Unexpected PartitionSortStage in ExecuteTask!"); } @@ -531,12 +537,18 @@ bool PartitionGlobalMergeState::TryPrepareNextStage() { return true; case PartitionSortStage::SORTED: - break; + stage = PartitionSortStage::FINISHED; + total_tasks = 0; + return false; + + case PartitionSortStage::FINISHED: + return false; } stage = PartitionSortStage::SORTED; + total_tasks = 1; - return false; + return true; } PartitionGlobalMergeStates::PartitionGlobalMergeStates(PartitionGlobalSinkState &sink) { @@ -559,6 +571,8 @@ PartitionGlobalMergeStates::PartitionGlobalMergeStates(PartitionGlobalSinkState auto state = make_uniq(sink); states.emplace_back(std::move(state)); } + + sink.OnBeginMerge(); } class PartitionMergeTask : public ExecutorTask { @@ -602,7 +616,7 @@ bool PartitionGlobalMergeStates::ExecuteTask(PartitionLocalMergeState &local_sta // Thread is done with its assigned task, try to fetch new work for (auto group = sorted; group < states.size(); ++group) { auto &global_state = states[group]; - if (global_state->IsSorted()) { + if (global_state->IsFinished()) { // This hash group is done // Update the high water mark of densely completed groups if (sorted == group) { diff --git a/src/common/sort/radix_sort.cpp b/src/common/sort/radix_sort.cpp index 9d40f90d7ef..a917631acfc 100644 --- a/src/common/sort/radix_sort.cpp +++ b/src/common/sort/radix_sort.cpp @@ -244,7 +244,7 @@ void RadixSort(BufferManager &buffer_manager, const data_ptr_t &dataptr, const i duckdb_pdqsort::PDQConstants constants(sort_layout.entry_size, col_offset, sorting_size, *end); duckdb_pdqsort::pdqsort_branchless(begin, begin + count, constants); } else if (count <= SortConstants::INSERTION_SORT_THRESHOLD) { - InsertionSort(dataptr, nullptr, count, 0, sort_layout.entry_size, sort_layout.comparison_size, 0, false); + InsertionSort(dataptr, nullptr, count, col_offset, sort_layout.entry_size, sorting_size, 0, false); } else if (sorting_size <= SortConstants::MSD_RADIX_SORT_SIZE_THRESHOLD) { RadixSortLSD(buffer_manager, dataptr, count, col_offset, sort_layout.entry_size, sorting_size); } else { diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 2e9eb676e52..81e8dc9bf96 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -15,6 +15,10 @@ #include #include +#include "yyjson.hpp" + +using namespace duckdb_yyjson; // NOLINT + namespace duckdb { string StringUtil::GenerateRandomName(idx_t length) { @@ -242,7 +246,7 @@ bool StringUtil::CIEquals(const string &l1, const string &l2) { bool StringUtil::CILessThan(const string &s1, const string &s2) { const auto charmap = UpperFun::ASCII_TO_UPPER_MAP; - unsigned char u1, u2; + unsigned char u1 {}, u2 {}; idx_t length = MinValue(s1.length(), s2.length()); length += s1.length() != s2.length(); @@ -256,6 +260,16 @@ bool StringUtil::CILessThan(const string &s1, const string &s2) { return (charmap[u1] - charmap[u2]) < 0; } +idx_t StringUtil::CIFind(vector &vector, const string &search_string) { + for (idx_t i = 0; i < vector.size(); i++) { + const auto &string = vector[i]; + if (CIEquals(string, search_string)) { + return i; + } + } + return DConstants::INVALID_INDEX; +} + vector StringUtil::Split(const string &input, const string &split) { vector splits; @@ -405,181 +419,73 @@ string StringUtil::CandidatesErrorMessage(const vector &strings, const s return StringUtil::CandidatesMessage(closest_strings, message_prefix); } -static void SkipSpaces(const string &message, idx_t &pos) { - for (; pos < message.size() && StringUtil::CharacterIsSpace(message[pos]); pos++) { - } -} - -static bool MatchCharacter(const string &message, idx_t &pos, char c) { - if (pos >= message.size()) { - return false; - } - return message[pos] == c; -} - -static string ParseJSONValue(const string &message, idx_t &pos) { - string result; - if (!MatchCharacter(message, pos, '"')) { - // values need to start with a quote - D_ASSERT(0); - return result; - } - pos++; - for (; pos < message.size(); pos++) { - if (message[pos] == '\\') { - // escape - pos++; - if (pos >= message.size()) { - // escape at end of string!? - D_ASSERT(0); - return result; - } - switch (message[pos]) { - case 'r': - result += '\r'; - break; - case 'n': - result += '\n'; - break; - case 't': - result += '\t'; - break; - case 'b': - result += '\b'; - break; - case 'f': - result += '\f'; - break; - case '0': - result += '\0'; - break; - case '\\': - case '"': - case '/': - result += message[pos]; - break; - default: - // unsupported escape character - // NOTE: we do not support unicode escape sequences here - D_ASSERT(0); - result += message[pos]; - break; - } - } else if (message[pos] == '"') { - // end of message - pos++; - return result; - } else { - result += message[pos]; - } - } - // no end-of-value found - D_ASSERT(0); - return result; -} - unordered_map StringUtil::ParseJSONMap(const string &json) { unordered_map result; if (json.empty()) { return result; } - idx_t pos = 0; - SkipSpaces(json, pos); - if (!MatchCharacter(json, pos, '{')) { - D_ASSERT(0); - return result; - } - pos++; - while (true) { - SkipSpaces(json, pos); - if (MatchCharacter(json, pos, '}')) { - // end of object - break; + yyjson_read_flag flags = YYJSON_READ_ALLOW_INVALID_UNICODE; + yyjson_doc *doc = yyjson_read(json.c_str(), json.size(), flags); + if (!doc) { + throw SerializationException("Failed to parse JSON string: %s", json); + } + yyjson_val *root = yyjson_doc_get_root(doc); + if (!root || yyjson_get_type(root) != YYJSON_TYPE_OBJ) { + yyjson_doc_free(doc); + throw SerializationException("Failed to parse JSON string: %s", json); + } + yyjson_obj_iter iter; + yyjson_obj_iter_init(root, &iter); + yyjson_val *key, *value; + while ((key = yyjson_obj_iter_next(&iter))) { + value = yyjson_obj_iter_get_val(key); + if (yyjson_get_type(value) != YYJSON_TYPE_STR) { + yyjson_doc_free(doc); + throw SerializationException("Failed to parse JSON string: %s", json); } - if (!result.empty()) { - // objects are comma separated - if (!MatchCharacter(json, pos, ',')) { - D_ASSERT(0); - return result; - } - pos++; - } - string key = ParseJSONValue(json, pos); - SkipSpaces(json, pos); - if (!MatchCharacter(json, pos, ':')) { - D_ASSERT(0); - return result; - } - pos++; - string value = ParseJSONValue(json, pos); - auto entry = result.find(key); - if (entry != result.end()) { - // entry already exists - D_ASSERT(0); - continue; - } - result.insert(make_pair(std::move(key), std::move(value))); + auto key_val = yyjson_get_str(key); + auto key_len = yyjson_get_len(key); + auto value_val = yyjson_get_str(value); + auto value_len = yyjson_get_len(value); + result.emplace(string(key_val, key_len), string(value_val, value_len)); } + yyjson_doc_free(doc); return result; } -static void WriteJSONValue(const string &value, string &result) { - result += '"'; - for (auto c : value) { - // check for characters we need to escape - switch (c) { - case '\0': - result += "\\0"; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\t': - result += "\\t"; - break; - case '\r': - result += "\\r"; - break; - case '\n': - result += "\\n"; - break; - case '"': - result += "\\\""; - break; - default: - result += c; - break; - } - } - result += '"'; -} - -static void WriteJSONPair(const string &key, const string &value, string &result) { - WriteJSONValue(key, result); - result += ":"; - WriteJSONValue(value, result); -} - string StringUtil::ToJSONMap(ExceptionType type, const string &message, const unordered_map &map) { D_ASSERT(map.find("exception_type") == map.end()); D_ASSERT(map.find("exception_message") == map.end()); - string result; - result += "{"; - // we always write exception type/message - WriteJSONPair("exception_type", Exception::ExceptionTypeToString(type), result); - result += ","; - WriteJSONPair("exception_message", message, result); + + yyjson_mut_doc *doc = yyjson_mut_doc_new(nullptr); + yyjson_mut_val *root = yyjson_mut_obj(doc); + yyjson_mut_doc_set_root(doc, root); + + auto except_str = Exception::ExceptionTypeToString(type); + yyjson_mut_obj_add_strncpy(doc, root, "exception_type", except_str.c_str(), except_str.size()); + yyjson_mut_obj_add_strncpy(doc, root, "exception_message", message.c_str(), message.size()); for (auto &entry : map) { - result += ","; - WriteJSONPair(entry.first, entry.second, result); + auto key = yyjson_mut_strncpy(doc, entry.first.c_str(), entry.first.size()); + auto value = yyjson_mut_strncpy(doc, entry.second.c_str(), entry.second.size()); + yyjson_mut_obj_add(root, key, value); + } + + yyjson_write_err err; + size_t len; + constexpr yyjson_write_flag flags = YYJSON_WRITE_ALLOW_INVALID_UNICODE; + char *json = yyjson_mut_write_opts(doc, flags, nullptr, &len, &err); + if (!json) { + yyjson_mut_doc_free(doc); + throw SerializationException("Failed to write JSON string: %s", err.msg); } - result += "}"; + // Create a string from the JSON + string result(json, len); + + // Free the JSON and the document + free(json); + yyjson_mut_doc_free(doc); + + // Return the result return result; } diff --git a/src/common/symbols.cpp b/src/common/symbols.cpp index ee16effeac4..47f0f1b7e54 100644 --- a/src/common/symbols.cpp +++ b/src/common/symbols.cpp @@ -140,7 +140,6 @@ template class unique_ptr; template class unique_ptr; template class unique_ptr; template class unique_ptr; -template class unique_ptr; template class unique_ptr; template class unique_ptr; template class unique_ptr; @@ -180,7 +179,6 @@ INSTANTIATE_VECTOR(vector>) INSTANTIATE_VECTOR(vector>) INSTANTIATE_VECTOR(vector>) INSTANTIATE_VECTOR(vector>) -INSTANTIATE_VECTOR(vector>) INSTANTIATE_VECTOR(vector>) INSTANTIATE_VECTOR(vector>) INSTANTIATE_VECTOR(vector>) diff --git a/src/common/tree_renderer.cpp b/src/common/tree_renderer.cpp index aa295364022..d19ee539000 100644 --- a/src/common/tree_renderer.cpp +++ b/src/common/tree_renderer.cpp @@ -484,10 +484,14 @@ unique_ptr TreeRenderer::CreateNode(const PipelineRenderNode &op } unique_ptr TreeRenderer::CreateNode(const QueryProfiler::TreeNode &op) { - auto result = TreeRenderer::CreateRenderNode(op.name, op.extra_info); + string extra_info; + if (op.profiling_info.Enabled(MetricsType::EXTRA_INFO)) { + extra_info = op.profiling_info.metrics.extra_info; + } + auto result = TreeRenderer::CreateRenderNode(op.name, extra_info); result->extra_text += "\n[INFOSEPARATOR]"; - result->extra_text += "\n" + to_string(op.info.elements); - string timing = StringUtil::Format("%.2f", op.info.time); + result->extra_text += "\n" + to_string(op.profiling_info.metrics.operator_cardinality); + string timing = StringUtil::Format("%.2f", op.profiling_info.metrics.operator_timing); result->extra_text += "\n(" + timing + "s)"; return result; } diff --git a/src/common/types.cpp b/src/common/types.cpp index c8ed13960b0..d9d260a42bd 100644 --- a/src/common/types.cpp +++ b/src/common/types.cpp @@ -364,6 +364,18 @@ string LogicalType::ToString() const { if (id_ != LogicalTypeId::USER) { auto alias = GetAlias(); if (!alias.empty()) { + auto mods_ptr = GetModifiers(); + if (mods_ptr && !mods_ptr->empty()) { + auto &mods = *mods_ptr; + alias += "("; + for (idx_t i = 0; i < mods.size(); i++) { + alias += mods[i].ToString(); + if (i < mods.size() - 1) { + alias += ", "; + } + } + alias += ")"; + } return alias; } } @@ -457,6 +469,7 @@ string LogicalType::ToString() const { auto &catalog = UserType::GetCatalog(*this); auto &schema = UserType::GetSchema(*this); auto &type = UserType::GetTypeName(*this); + auto &mods = UserType::GetTypeModifiers(*this); if (!catalog.empty()) { result = KeywordHelper::WriteOptionallyQuoted(catalog); @@ -471,6 +484,18 @@ string LogicalType::ToString() const { result += "."; } result += KeywordHelper::WriteOptionallyQuoted(type); + + if (!mods.empty()) { + result += "("; + for (idx_t i = 0; i < mods.size(); i++) { + result += mods[i].ToString(); + if (i < mods.size() - 1) { + result += ", "; + } + } + result += ")"; + } + return result; } case LogicalTypeId::AGGREGATE_STATE: { @@ -504,7 +529,9 @@ LogicalType TransformStringToLogicalType(const string &str) { LogicalType GetUserTypeRecursive(const LogicalType &type, ClientContext &context) { if (type.id() == LogicalTypeId::USER && type.HasAlias()) { - return Catalog::GetType(context, INVALID_CATALOG, INVALID_SCHEMA, type.GetAlias()); + auto &type_entry = + Catalog::GetEntry(context, INVALID_CATALOG, INVALID_SCHEMA, type.GetAlias()); + return type_entry.user_type; } // Look for LogicalTypeId::USER in nested types if (type.id() == LogicalTypeId::STRUCT) { @@ -569,12 +596,24 @@ bool LogicalType::IsNumeric() const { } } -bool LogicalType::IsValid() const { - return id() != LogicalTypeId::INVALID && id() != LogicalTypeId::UNKNOWN; +bool LogicalType::IsTemporal() const { + switch (id_) { + case LogicalTypeId::DATE: + case LogicalTypeId::TIME: + case LogicalTypeId::TIMESTAMP: + case LogicalTypeId::TIME_TZ: + case LogicalTypeId::TIMESTAMP_TZ: + case LogicalTypeId::TIMESTAMP_SEC: + case LogicalTypeId::TIMESTAMP_MS: + case LogicalTypeId::TIMESTAMP_NS: + return true; + default: + return false; + } } -bool LogicalType::Contains(LogicalTypeId type_id) const { - return Contains([&](const LogicalType &type) { return type.id() == type_id; }); +bool LogicalType::IsValid() const { + return id() != LogicalTypeId::INVALID && id() != LogicalTypeId::UNKNOWN; } bool LogicalType::GetDecimalProperties(uint8_t &width, uint8_t &scale) const { @@ -1131,6 +1170,15 @@ bool ApproxEqual(double ldecimal, double rdecimal) { //===--------------------------------------------------------------------===// // Extra Type Info //===--------------------------------------------------------------------===// + +LogicalType LogicalType::DeepCopy() const { + LogicalType copy = *this; + if (type_info_) { + copy.type_info_ = type_info_->Copy(); + } + return copy; +} + void LogicalType::SetAlias(string alias) { if (!type_info_) { type_info_ = make_shared_ptr(ExtraTypeInfoType::GENERIC_TYPE_INFO, std::move(alias)); @@ -1159,6 +1207,53 @@ bool LogicalType::HasAlias() const { return false; } +void LogicalType::SetModifiers(vector modifiers) { + if (!type_info_ && !modifiers.empty()) { + type_info_ = make_shared_ptr(ExtraTypeInfoType::GENERIC_TYPE_INFO); + } + type_info_->modifiers = std::move(modifiers); +} + +bool LogicalType::HasModifiers() const { + if (id() == LogicalTypeId::USER) { + return !UserType::GetTypeModifiers(*this).empty(); + } + if (type_info_) { + return !type_info_->modifiers.empty(); + } + return false; +} + +vector LogicalType::GetModifiersCopy() const { + if (id() == LogicalTypeId::USER) { + return UserType::GetTypeModifiers(*this); + } + if (type_info_) { + return type_info_->modifiers; + } + return {}; +} + +optional_ptr> LogicalType::GetModifiers() { + if (id() == LogicalTypeId::USER) { + return UserType::GetTypeModifiers(*this); + } + if (type_info_) { + return type_info_->modifiers; + } + return nullptr; +} + +optional_ptr> LogicalType::GetModifiers() const { + if (id() == LogicalTypeId::USER) { + return UserType::GetTypeModifiers(*this); + } + if (type_info_) { + return type_info_->modifiers; + } + return nullptr; +} + //===--------------------------------------------------------------------===// // Decimal Type //===--------------------------------------------------------------------===// @@ -1287,7 +1382,7 @@ bool StructType::IsUnnamed(const LogicalType &type) { if (child_types.empty()) { return false; } - return child_types[0].first.empty(); + return child_types[0].first.empty(); // NOLINT } LogicalType LogicalType::STRUCT(child_list_t children) { @@ -1402,13 +1497,33 @@ const string &UserType::GetTypeName(const LogicalType &type) { return info->Cast().user_type_name; } +const vector &UserType::GetTypeModifiers(const LogicalType &type) { + D_ASSERT(type.id() == LogicalTypeId::USER); + auto info = type.AuxInfo(); + D_ASSERT(info); + return info->Cast().user_type_modifiers; +} + +vector &UserType::GetTypeModifiers(LogicalType &type) { + D_ASSERT(type.id() == LogicalTypeId::USER); + auto info = type.GetAuxInfoShrPtr(); + D_ASSERT(info); + return info->Cast().user_type_modifiers; +} + LogicalType LogicalType::USER(const string &user_type_name) { auto info = make_shared_ptr(user_type_name); return LogicalType(LogicalTypeId::USER, std::move(info)); } -LogicalType LogicalType::USER(string catalog, string schema, string name) { - auto info = make_shared_ptr(std::move(catalog), std::move(schema), std::move(name)); +LogicalType LogicalType::USER(const string &user_type_name, const vector &user_type_mods) { + auto info = make_shared_ptr(user_type_name, user_type_mods); + return LogicalType(LogicalTypeId::USER, std::move(info)); +} + +LogicalType LogicalType::USER(string catalog, string schema, string name, vector user_type_mods) { + auto info = make_shared_ptr(std::move(catalog), std::move(schema), std::move(name), + std::move(user_type_mods)); return LogicalType(LogicalTypeId::USER, std::move(info)); } @@ -1521,16 +1636,18 @@ LogicalType ArrayType::ConvertToList(const LogicalType &type) { } } -LogicalType LogicalType::ARRAY(const LogicalType &child, idx_t size) { - D_ASSERT(size > 0); - D_ASSERT(size < ArrayType::MAX_ARRAY_SIZE); - auto info = make_shared_ptr(child, size); - return LogicalType(LogicalTypeId::ARRAY, std::move(info)); -} - -LogicalType LogicalType::ARRAY(const LogicalType &child) { - auto info = make_shared_ptr(child, 0); - return LogicalType(LogicalTypeId::ARRAY, std::move(info)); +LogicalType LogicalType::ARRAY(const LogicalType &child, optional_idx size) { + if (!size.IsValid()) { + // Create an incomplete ARRAY type, used for binding + auto info = make_shared_ptr(child, 0); + return LogicalType(LogicalTypeId::ARRAY, std::move(info)); + } else { + auto array_size = size.GetIndex(); + D_ASSERT(array_size > 0); + D_ASSERT(array_size <= ArrayType::MAX_ARRAY_SIZE); + auto info = make_shared_ptr(child, array_size); + return LogicalType(LogicalTypeId::ARRAY, std::move(info)); + } } //===--------------------------------------------------------------------===// diff --git a/src/common/types/blob.cpp b/src/common/types/blob.cpp index 6f472c0e3b9..11df1341804 100644 --- a/src/common/types/blob.cpp +++ b/src/common/types/blob.cpp @@ -77,15 +77,16 @@ bool Blob::TryGetBlobSize(string_t str, idx_t &str_len, CastParameters ¶mete for (idx_t i = 0; i < len; i++) { if (data[i] == '\\') { if (i + 3 >= len) { - string error = "Invalid hex escape code encountered in string -> blob conversion: " - "unterminated escape code at end of blob"; + string error = StringUtil::Format("Invalid hex escape code encountered in string -> blob conversion of " + "string \"%s\": unterminated escape code at end of blob", + str.GetString()); HandleCastError::AssignError(error, parameters); return false; } if (data[i + 1] != 'x' || Blob::HEX_MAP[data[i + 2]] < 0 || Blob::HEX_MAP[data[i + 3]] < 0) { - string error = - StringUtil::Format("Invalid hex escape code encountered in string -> blob conversion: %s", - string(const_char_ptr_cast(data) + i, 4)); + string error = StringUtil::Format( + "Invalid hex escape code encountered in string -> blob conversion of string \"%s\": %s", + str.GetString(), string(const_char_ptr_cast(data) + i, 4)); HandleCastError::AssignError(error, parameters); return false; } @@ -94,8 +95,10 @@ bool Blob::TryGetBlobSize(string_t str, idx_t &str_len, CastParameters ¶mete } else if (data[i] <= 127) { str_len++; } else { - string error = "Invalid byte encountered in STRING -> BLOB conversion. All non-ascii characters " - "must be escaped with hex codes (e.g. \\xAA)"; + string error = StringUtil::Format( + "Invalid byte encountered in STRING -> BLOB conversion of string \"%s\". All non-ascii characters " + "must be escaped with hex codes (e.g. \\xAA)", + str.GetString()); HandleCastError::AssignError(error, parameters); return false; } diff --git a/src/common/types/cast_helpers.cpp b/src/common/types/cast_helpers.cpp index f37fbaa971e..5a5f11210bc 100644 --- a/src/common/types/cast_helpers.cpp +++ b/src/common/types/cast_helpers.cpp @@ -103,6 +103,101 @@ int NumericHelper::UnsignedLength(uint64_t value) { } } +template <> +int NumericHelper::UnsignedLength(hugeint_t value) { + D_ASSERT(value.upper >= 0); + if (value.upper == 0) { + return UnsignedLength(value.lower); + } + // search the length using the POWERS_OF_TEN array + // the length has to be between [17] and [38], because the hugeint is bigger than 2^63 + // we use the same approach as above, but split a bit more because comparisons for hugeints are more expensive + if (value >= Hugeint::POWERS_OF_TEN[27]) { + // [27..38] + if (value >= Hugeint::POWERS_OF_TEN[32]) { + if (value >= Hugeint::POWERS_OF_TEN[36]) { + int length = 37; + length += value >= Hugeint::POWERS_OF_TEN[37]; + length += value >= Hugeint::POWERS_OF_TEN[38]; + return length; + } else { + int length = 33; + length += value >= Hugeint::POWERS_OF_TEN[33]; + length += value >= Hugeint::POWERS_OF_TEN[34]; + length += value >= Hugeint::POWERS_OF_TEN[35]; + return length; + } + } else { + if (value >= Hugeint::POWERS_OF_TEN[30]) { + int length = 31; + length += value >= Hugeint::POWERS_OF_TEN[31]; + length += value >= Hugeint::POWERS_OF_TEN[32]; + return length; + } else { + int length = 28; + length += value >= Hugeint::POWERS_OF_TEN[28]; + length += value >= Hugeint::POWERS_OF_TEN[29]; + return length; + } + } + } else { + // [17..27] + if (value >= Hugeint::POWERS_OF_TEN[22]) { + // [22..27] + if (value >= Hugeint::POWERS_OF_TEN[25]) { + int length = 26; + length += value >= Hugeint::POWERS_OF_TEN[26]; + return length; + } else { + int length = 23; + length += value >= Hugeint::POWERS_OF_TEN[23]; + length += value >= Hugeint::POWERS_OF_TEN[24]; + return length; + } + } else { + // [17..22] + if (value >= Hugeint::POWERS_OF_TEN[20]) { + int length = 21; + length += value >= Hugeint::POWERS_OF_TEN[21]; + return length; + } else { + int length = 18; + length += value >= Hugeint::POWERS_OF_TEN[18]; + length += value >= Hugeint::POWERS_OF_TEN[19]; + return length; + } + } + } +} + +template <> +string_t NumericHelper::FormatSigned(hugeint_t value, Vector &vector) { + int negative = value.upper < 0; + if (negative) { + if (value == NumericLimits::Minimum()) { + string_t result = StringVector::AddString(vector, Hugeint::HUGEINT_MINIMUM_STRING); + return result; + } + Hugeint::NegateInPlace(value); + } + int length = UnsignedLength(value) + negative; + string_t result = StringVector::EmptyString(vector, NumericCast(length)); + auto dataptr = result.GetDataWriteable(); + auto endptr = dataptr + length; + if (value.upper == 0) { + // small value: format as uint64_t + endptr = NumericHelper::FormatUnsigned(value.lower, endptr); + } else { + endptr = FormatUnsigned(value, endptr); + } + if (negative) { + *--endptr = '-'; + } + D_ASSERT(endptr == dataptr); + result.Finalize(); + return result; +} + template <> std::string NumericHelper::ToString(hugeint_t value) { return Hugeint::ToString(value); @@ -113,4 +208,106 @@ std::string NumericHelper::ToString(uhugeint_t value) { return Uhugeint::ToString(value); } +template <> +int DecimalToString::DecimalLength(hugeint_t value, uint8_t width, uint8_t scale) { + D_ASSERT(value > NumericLimits::Minimum()); + int negative; + + if (value.upper < 0) { + Hugeint::NegateInPlace(value); + negative = 1; + } else { + negative = 0; + } + if (scale == 0) { + // scale is 0: regular number + return NumericHelper::UnsignedLength(value) + negative; + } + // length is max of either: + // scale + 2 OR + // integer length + 1 + // scale + 2 happens when the number is in the range of (-1, 1) + // in that case we print "0.XXX", which is the scale, plus "0." (2 chars) + // integer length + 1 happens when the number is outside of that range + // in that case we print the integer number, but with one extra character ('.') + auto extra_numbers = width > scale ? 2 : 1; + return MaxValue(scale + extra_numbers, NumericHelper::UnsignedLength(value) + 1) + negative; +} + +template <> +string_t DecimalToString::Format(hugeint_t value, uint8_t width, uint8_t scale, Vector &vector) { + int length = DecimalLength(value, width, scale); + string_t result = StringVector::EmptyString(vector, NumericCast(length)); + + auto dst = result.GetDataWriteable(); + + FormatDecimal(value, width, scale, dst, NumericCast(length)); + + result.Finalize(); + return result; +} + +template <> +char *NumericHelper::FormatUnsigned(hugeint_t value, char *ptr) { + while (value.upper > 0) { + // while integer division is slow, hugeint division is MEGA slow + // we want to avoid doing as many divisions as possible + // for that reason we start off doing a division by a large power of ten that uint64_t can hold + // (100000000000000000) - this is the third largest + // the reason we don't use the largest is because that can result in an overflow inside the division + // function + uint64_t remainder; + value = Hugeint::DivModPositive(value, 100000000000000000ULL, remainder); + + auto startptr = ptr; + // now we format the remainder: note that we need to pad with zero's in case + // the remainder is small (i.e. less than 10000000000000000) + ptr = NumericHelper::FormatUnsigned(remainder, ptr); + + int format_length = UnsafeNumericCast(startptr - ptr); + // pad with zero + for (int i = format_length; i < 17; i++) { + *--ptr = '0'; + } + } + // once the value falls in the range of a uint64_t, fallback to formatting as uint64_t to avoid hugeint division + return NumericHelper::FormatUnsigned(value.lower, ptr); +} + +template <> +void DecimalToString::FormatDecimal(hugeint_t value, uint8_t width, uint8_t scale, char *dst, idx_t len) { + auto endptr = dst + len; + + int negative = value.upper < 0; + if (negative) { + Hugeint::NegateInPlace(value); + *dst = '-'; + dst++; + } + if (scale == 0) { + // with scale=0 we format the number as a regular number + NumericHelper::FormatUnsigned(value, endptr); + return; + } + + // we write two numbers: + // the numbers BEFORE the decimal (major) + // and the numbers AFTER the decimal (minor) + hugeint_t minor; + hugeint_t major = Hugeint::DivMod(value, Hugeint::POWERS_OF_TEN[scale], minor); + + // write the number after the decimal + dst = NumericHelper::FormatUnsigned(minor, endptr); + // (optionally) pad with zeros and add the decimal point + while (dst > (endptr - scale)) { + *--dst = '0'; + } + *--dst = '.'; + // now write the part before the decimal + D_ASSERT(width > scale || major == 0); + if (width > scale) { + dst = NumericHelper::FormatUnsigned(major, dst); + } +} + } // namespace duckdb diff --git a/src/common/types/column/column_data_collection.cpp b/src/common/types/column/column_data_collection.cpp index 46aed955ad8..c3752a98253 100644 --- a/src/common/types/column/column_data_collection.cpp +++ b/src/common/types/column/column_data_collection.cpp @@ -690,8 +690,16 @@ void ColumnDataCopyArray(ColumnDataMetaData &meta_data, const UnifiedVectorForma } } - child_function.function(child_meta_data, child_vector_data, child_vector, offset * array_size, - array_size * copy_count); + auto is_constant = source.GetVectorType() == VectorType::CONSTANT_VECTOR; + // If the array is constant, we need to copy the child vector n times + if (is_constant) { + for (idx_t i = 0; i < copy_count; i++) { + child_function.function(child_meta_data, child_vector_data, child_vector, 0, array_size); + } + } else { + child_function.function(child_meta_data, child_vector_data, child_vector, offset * array_size, + copy_count * array_size); + } } ColumnDataCopyFunction ColumnDataCollection::GetCopyFunction(const LogicalType &type) { diff --git a/src/common/types/conflict_info.cpp b/src/common/types/conflict_info.cpp index e832bf8967b..44f8aa7f1fb 100644 --- a/src/common/types/conflict_info.cpp +++ b/src/common/types/conflict_info.cpp @@ -12,7 +12,7 @@ bool ConflictInfo::ConflictTargetMatches(Index &index) const { return true; } // Check whether the column ids match - return column_ids == index.column_id_set; + return column_ids == index.GetColumnIdSet(); } } // namespace duckdb diff --git a/src/common/types/data_chunk.cpp b/src/common/types/data_chunk.cpp index 114beb1f49e..50166877c0e 100644 --- a/src/common/types/data_chunk.cpp +++ b/src/common/types/data_chunk.cpp @@ -37,6 +37,15 @@ void DataChunk::Initialize(ClientContext &context, const vector &ty Initialize(Allocator::Get(context), types, capacity_p); } +idx_t DataChunk::GetAllocationSize() const { + idx_t total_size = 0; + auto cardinality = size(); + for (auto &vec : data) { + total_size += vec.GetAllocationSize(cardinality); + } + return total_size; +} + void DataChunk::Initialize(Allocator &allocator, vector::const_iterator begin, vector::const_iterator end, idx_t capacity_p) { D_ASSERT(data.empty()); // can only be initialized once @@ -273,7 +282,7 @@ void DataChunk::Deserialize(Deserializer &deserializer) { // initialize the data chunk D_ASSERT(!types.empty()); - Initialize(Allocator::DefaultAllocator(), types); + Initialize(Allocator::DefaultAllocator(), types, MaxValue(row_count, STANDARD_VECTOR_SIZE)); SetCardinality(row_count); // read the data diff --git a/src/common/types/date.cpp b/src/common/types/date.cpp index be334903519..d498f6e58e8 100644 --- a/src/common/types/date.cpp +++ b/src/common/types/date.cpp @@ -450,22 +450,6 @@ int64_t Date::EpochMilliseconds(date_t date) { return result; } -int32_t Date::ExtractYear(date_t d, int32_t *last_year) { - auto n = d.days; - // cached look up: check if year of this date is the same as the last one we looked up - // note that this only works for years in the range [1970, 2370] - if (n >= Date::CUMULATIVE_YEAR_DAYS[*last_year] && n < Date::CUMULATIVE_YEAR_DAYS[*last_year + 1]) { - return Date::EPOCH_YEAR + *last_year; - } - int32_t year; - Date::ExtractYearOffset(n, year, *last_year); - return year; -} - -int32_t Date::ExtractYear(timestamp_t ts, int32_t *last_year) { - return Date::ExtractYear(Timestamp::GetDate(ts), last_year); -} - int32_t Date::ExtractYear(date_t d) { int32_t year, year_offset; Date::ExtractYearOffset(d.days, year, year_offset); diff --git a/src/common/types/decimal.cpp b/src/common/types/decimal.cpp index 2f38d76ea78..d05e4a000dc 100644 --- a/src/common/types/decimal.cpp +++ b/src/common/types/decimal.cpp @@ -3,30 +3,30 @@ namespace duckdb { -template +template string TemplatedDecimalToString(SIGNED value, uint8_t width, uint8_t scale) { - auto len = DecimalToString::DecimalLength(value, width, scale); + auto len = DecimalToString::DecimalLength(value, width, scale); auto data = make_unsafe_uniq_array(UnsafeNumericCast(len + 1)); - DecimalToString::FormatDecimal(value, width, scale, data.get(), UnsafeNumericCast(len)); + DecimalToString::FormatDecimal(value, width, scale, data.get(), UnsafeNumericCast(len)); return string(data.get(), UnsafeNumericCast(len)); } string Decimal::ToString(int16_t value, uint8_t width, uint8_t scale) { - return TemplatedDecimalToString(value, width, scale); + return TemplatedDecimalToString(value, width, scale); } string Decimal::ToString(int32_t value, uint8_t width, uint8_t scale) { - return TemplatedDecimalToString(value, width, scale); + return TemplatedDecimalToString(value, width, scale); } string Decimal::ToString(int64_t value, uint8_t width, uint8_t scale) { - return TemplatedDecimalToString(value, width, scale); + return TemplatedDecimalToString(value, width, scale); } string Decimal::ToString(hugeint_t value, uint8_t width, uint8_t scale) { - auto len = HugeintToStringCast::DecimalLength(value, width, scale); + auto len = DecimalToString::DecimalLength(value, width, scale); auto data = make_unsafe_uniq_array(UnsafeNumericCast(len + 1)); - HugeintToStringCast::FormatDecimal(value, width, scale, data.get(), UnsafeNumericCast(len)); + DecimalToString::FormatDecimal(value, width, scale, data.get(), UnsafeNumericCast(len)); return string(data.get(), UnsafeNumericCast(len)); } diff --git a/src/common/types/hugeint.cpp b/src/common/types/hugeint.cpp index d83d81caa13..a920781a81a 100644 --- a/src/common/types/hugeint.cpp +++ b/src/common/types/hugeint.cpp @@ -77,6 +77,14 @@ bool Hugeint::TryNegate(hugeint_t input, hugeint_t &result) { return true; } +hugeint_t Hugeint::Abs(hugeint_t n) { + if (n < 0) { + return Hugeint::Negate(n); + } else { + return n; + } +} + //===--------------------------------------------------------------------===// // Divide //===--------------------------------------------------------------------===// diff --git a/src/common/types/row/tuple_data_allocator.cpp b/src/common/types/row/tuple_data_allocator.cpp index ee3d93ee5e6..02283b12a60 100644 --- a/src/common/types/row/tuple_data_allocator.cpp +++ b/src/common/types/row/tuple_data_allocator.cpp @@ -1,9 +1,9 @@ #include "duckdb/common/types/row/tuple_data_allocator.hpp" +#include "duckdb/common/fast_mem.hpp" #include "duckdb/common/types/row/tuple_data_segment.hpp" #include "duckdb/common/types/row/tuple_data_states.hpp" #include "duckdb/storage/buffer_manager.hpp" -#include "duckdb/common/fast_mem.hpp" namespace duckdb { @@ -13,7 +13,7 @@ TupleDataBlock::TupleDataBlock(BufferManager &buffer_manager, idx_t capacity_p) buffer_manager.Allocate(MemoryTag::HASH_TABLE, capacity, false, &handle); } -TupleDataBlock::TupleDataBlock(TupleDataBlock &&other) noexcept { +TupleDataBlock::TupleDataBlock(TupleDataBlock &&other) noexcept : capacity(0), size(0) { std::swap(handle, other.handle); std::swap(capacity, other.capacity); std::swap(size, other.size); @@ -140,22 +140,12 @@ TupleDataChunkPart TupleDataAllocator::BuildChunkPart(TupleDataPinState &pin_sta } if (total_heap_size == 0) { - // We don't need a heap at all - result.heap_block_index = TupleDataChunkPart::INVALID_INDEX; - result.heap_block_offset = TupleDataChunkPart::INVALID_INDEX; - result.total_heap_size = 0; - result.base_heap_ptr = nullptr; + result.SetHeapEmpty(); } else { - // Allocate heap block (if needed) - if (heap_blocks.empty() || heap_blocks.back().RemainingCapacity() < heap_sizes[append_offset]) { - const auto size = MaxValue((idx_t)Storage::BLOCK_SIZE, heap_sizes[append_offset]); - heap_blocks.emplace_back(buffer_manager, size); - } - result.heap_block_index = NumericCast(heap_blocks.size() - 1); - auto &heap_block = heap_blocks[result.heap_block_index]; - result.heap_block_offset = NumericCast(heap_block.size); + const auto heap_remaining = MaxValue(heap_blocks.empty() ? (idx_t)Storage::BLOCK_SIZE + : heap_blocks.back().RemainingCapacity(), + heap_sizes[append_offset]); - const auto heap_remaining = heap_block.RemainingCapacity(); if (total_heap_size <= heap_remaining) { // Everything fits result.total_heap_size = NumericCast(total_heap_size); @@ -172,9 +162,22 @@ TupleDataChunkPart TupleDataAllocator::BuildChunkPart(TupleDataPinState &pin_sta } } - // Mark this portion of the heap block as filled and set the pointer - heap_block.size += result.total_heap_size; - result.base_heap_ptr = GetBaseHeapPointer(pin_state, result); + if (result.total_heap_size == 0) { + result.SetHeapEmpty(); + } else { + // Allocate heap block (if needed) + if (heap_blocks.empty() || heap_blocks.back().RemainingCapacity() < heap_sizes[append_offset]) { + const auto size = MaxValue((idx_t)Storage::BLOCK_SIZE, heap_sizes[append_offset]); + heap_blocks.emplace_back(buffer_manager, size); + } + result.heap_block_index = NumericCast(heap_blocks.size() - 1); + auto &heap_block = heap_blocks[result.heap_block_index]; + result.heap_block_offset = NumericCast(heap_block.size); + + // Mark this portion of the heap block as filled and set the pointer + heap_block.size += result.total_heap_size; + result.base_heap_ptr = GetBaseHeapPointer(pin_state, result); + } } } D_ASSERT(result.count != 0 && result.count <= STANDARD_VECTOR_SIZE); diff --git a/src/common/types/row/tuple_data_collection.cpp b/src/common/types/row/tuple_data_collection.cpp index 86cbb144c80..1c35bd6f164 100644 --- a/src/common/types/row/tuple_data_collection.cpp +++ b/src/common/types/row/tuple_data_collection.cpp @@ -4,6 +4,7 @@ #include "duckdb/common/printer.hpp" #include "duckdb/common/row_operations/row_operations.hpp" #include "duckdb/common/types/row/tuple_data_allocator.hpp" +#include "duckdb/common/type_visitor.hpp" #include @@ -163,7 +164,7 @@ void TupleDataCollection::InitializeChunkState(TupleDataChunkState &chunk_state, for (auto &col : column_ids) { auto &type = types[col]; - if (type.Contains(LogicalTypeId::ARRAY)) { + if (TypeVisitor::Contains(type, LogicalTypeId::ARRAY)) { auto cast_type = ArrayType::ConvertToList(type); chunk_state.cached_cast_vector_cache.push_back( make_uniq(Allocator::DefaultAllocator(), cast_type)); @@ -384,6 +385,17 @@ void TupleDataCollection::InitializeChunk(DataChunk &chunk) const { chunk.Initialize(allocator->GetAllocator(), layout.GetTypes()); } +void TupleDataCollection::InitializeChunk(DataChunk &chunk, const vector &columns) const { + vector chunk_types(columns.size()); + // keep the order of the columns + for (idx_t i = 0; i < columns.size(); i++) { + auto column_idx = columns[i]; + D_ASSERT(column_idx < layout.ColumnCount()); + chunk_types[i] = layout.GetTypes()[column_idx]; + } + chunk.Initialize(allocator->GetAllocator(), chunk_types); +} + void TupleDataCollection::InitializeScanChunk(TupleDataScanState &state, DataChunk &chunk) const { auto &column_ids = state.chunk_state.column_ids; D_ASSERT(!column_ids.empty()); @@ -419,7 +431,7 @@ void TupleDataCollection::InitializeScan(TupleDataScanState &state, vector(Allocator::DefaultAllocator(), cast_type)); diff --git a/src/common/types/row/tuple_data_scatter_gather.cpp b/src/common/types/row/tuple_data_scatter_gather.cpp index 341f239ffde..3af3315507f 100644 --- a/src/common/types/row/tuple_data_scatter_gather.cpp +++ b/src/common/types/row/tuple_data_scatter_gather.cpp @@ -3,6 +3,7 @@ #include "duckdb/common/types/null_value.hpp" #include "duckdb/common/types/row/tuple_data_collection.hpp" #include "duckdb/common/uhugeint.hpp" +#include "duckdb/common/type_visitor.hpp" namespace duckdb { @@ -1508,7 +1509,7 @@ TupleDataGatherFunction TupleDataCollection::GetGatherFunction(const LogicalType return TupleDataGetGatherFunctionInternal(type, false); } - if (type.Contains(LogicalTypeId::ARRAY)) { + if (TypeVisitor::Contains(type, LogicalTypeId::ARRAY)) { // Special case: we cant handle arrays yet, so we need to replace them with lists when gathering auto new_type = ArrayType::ConvertToList(type); TupleDataGatherFunction result; diff --git a/src/common/types/row/tuple_data_segment.cpp b/src/common/types/row/tuple_data_segment.cpp index d84da30fd42..eb38913b7d5 100644 --- a/src/common/types/row/tuple_data_segment.cpp +++ b/src/common/types/row/tuple_data_segment.cpp @@ -7,6 +7,13 @@ namespace duckdb { TupleDataChunkPart::TupleDataChunkPart(mutex &lock_p) : lock(lock_p) { } +void TupleDataChunkPart::SetHeapEmpty() { + heap_block_index = INVALID_INDEX; + heap_block_offset = INVALID_INDEX; + total_heap_size = 0; + base_heap_ptr = nullptr; +} + void SwapTupleDataChunkPart(TupleDataChunkPart &a, TupleDataChunkPart &b) { std::swap(a.row_block_index, b.row_block_index); std::swap(a.row_block_offset, b.row_block_offset); diff --git a/src/common/types/selection_vector.cpp b/src/common/types/selection_vector.cpp index 8458d4c651b..b743c61fa1e 100644 --- a/src/common/types/selection_vector.cpp +++ b/src/common/types/selection_vector.cpp @@ -43,4 +43,19 @@ buffer_ptr SelectionVector::Slice(const SelectionVector &sel, idx return data; } +void SelectionVector::Verify(idx_t count, idx_t vector_size) const { +#ifdef DEBUG + D_ASSERT(vector_size >= 1); + for (idx_t i = 0; i < count; i++) { + auto index = get_index(i); + if (index >= vector_size) { + throw InternalException( + "Provided SelectionVector is invalid, index %d points to %d, which is out of range. " + "the valid range (0-%d)", + i, index, vector_size - 1); + } + } +#endif +} + } // namespace duckdb diff --git a/src/common/types/string_heap.cpp b/src/common/types/string_heap.cpp index eac0f59e7f5..be23433dd46 100644 --- a/src/common/types/string_heap.cpp +++ b/src/common/types/string_heap.cpp @@ -51,6 +51,10 @@ string_t StringHeap::AddBlob(const string_t &data) { string_t StringHeap::EmptyString(idx_t len) { D_ASSERT(len > string_t::INLINE_LENGTH); + if (len > string_t::MAX_STRING_SIZE) { + throw OutOfRangeException("Cannot create a string of size: '%d', the maximum supported string size is: '%d'", + len, string_t::MAX_STRING_SIZE); + } auto insert_pos = const_char_ptr_cast(allocator.Allocate(len)); return string_t(insert_pos, UnsafeNumericCast(len)); } diff --git a/src/common/types/time.cpp b/src/common/types/time.cpp index 8d2ba7fc3f7..61132f82700 100644 --- a/src/common/types/time.cpp +++ b/src/common/types/time.cpp @@ -21,7 +21,8 @@ static_assert(sizeof(dtime_t) == sizeof(int64_t), "dtime_t was padded"); // microseconds and Z are optional // ISO 8601 -bool Time::TryConvertInternal(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict) { +bool Time::TryConvertInternal(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict, + optional_ptr nanos) { int32_t hour = -1, min = -1, sec = -1, micros = -1; pos = 0; @@ -92,11 +93,19 @@ bool Time::TryConvertInternal(const char *buf, idx_t len, idx_t &pos, dtime_t &r pos++; // we expect some microseconds int32_t mult = 100000; + if (nanos) { + // do we expect nanoseconds? + mult *= Interval::NANOS_PER_MICRO; + } for (; pos < len && StringUtil::CharacterIsDigit(buf[pos]); pos++, mult /= 10) { if (mult > 0) { micros += (buf[pos] - '0') * mult; } } + if (nanos) { + *nanos = micros % Interval::NANOS_PER_MICRO; + micros /= Interval::NANOS_PER_MICRO; + } } // in strict mode, check remaining string for non-space characters @@ -115,16 +124,18 @@ bool Time::TryConvertInternal(const char *buf, idx_t len, idx_t &pos, dtime_t &r return true; } -bool Time::TryConvertInterval(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict) { - return Time::TryConvertInternal(buf, len, pos, result, strict); +bool Time::TryConvertInterval(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict, + optional_ptr nanos) { + return Time::TryConvertInternal(buf, len, pos, result, strict, nanos); } -bool Time::TryConvertTime(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict) { - if (!Time::TryConvertInternal(buf, len, pos, result, strict)) { +bool Time::TryConvertTime(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict, + optional_ptr nanos) { + if (!Time::TryConvertInternal(buf, len, pos, result, strict, nanos)) { if (!strict) { // last chance, check if we can parse as timestamp timestamp_t timestamp; - if (Timestamp::TryConvertTimestamp(buf, len, timestamp) == TimestampCastResult::SUCCESS) { + if (Timestamp::TryConvertTimestamp(buf, len, timestamp, nanos) == TimestampCastResult::SUCCESS) { if (!Timestamp::IsFinite(timestamp)) { return false; } @@ -137,14 +148,15 @@ bool Time::TryConvertTime(const char *buf, idx_t len, idx_t &pos, dtime_t &resul return result.micros <= Interval::MICROS_PER_DAY; } -bool Time::TryConvertTimeTZ(const char *buf, idx_t len, idx_t &pos, dtime_tz_t &result, bool &has_offset, bool strict) { +bool Time::TryConvertTimeTZ(const char *buf, idx_t len, idx_t &pos, dtime_tz_t &result, bool &has_offset, bool strict, + optional_ptr nanos) { dtime_t time_part; has_offset = false; - if (!Time::TryConvertInternal(buf, len, pos, time_part, false)) { + if (!Time::TryConvertInternal(buf, len, pos, time_part, false, nanos)) { if (!strict) { // last chance, check if we can parse as timestamp timestamp_t timestamp; - if (Timestamp::TryConvertTimestamp(buf, len, timestamp) == TimestampCastResult::SUCCESS) { + if (Timestamp::TryConvertTimestamp(buf, len, timestamp, nanos) == TimestampCastResult::SUCCESS) { if (!Timestamp::IsFinite(timestamp)) { return false; } @@ -218,17 +230,17 @@ string Time::ConversionError(string_t str) { return Time::ConversionError(str.GetString()); } -dtime_t Time::FromCString(const char *buf, idx_t len, bool strict) { +dtime_t Time::FromCString(const char *buf, idx_t len, bool strict, optional_ptr nanos) { dtime_t result; idx_t pos; - if (!Time::TryConvertTime(buf, len, pos, result, strict)) { + if (!Time::TryConvertTime(buf, len, pos, result, strict, nanos)) { throw ConversionException(ConversionError(string(buf, len))); } return result; } -dtime_t Time::FromString(const string &str, bool strict) { - return Time::FromCString(str.c_str(), str.size(), strict); +dtime_t Time::FromString(const string &str, bool strict, optional_ptr nanos) { + return Time::FromCString(str.c_str(), str.size(), strict, nanos); } string Time::ToString(dtime_t time) { @@ -273,6 +285,15 @@ dtime_t Time::FromTime(int32_t hour, int32_t minute, int32_t second, int32_t mic return dtime_t(result); } +int64_t Time::ToNanoTime(int32_t hour, int32_t minute, int32_t second, int32_t nanoseconds) { + int64_t result; + result = hour; // hours + result = result * Interval::MINS_PER_HOUR + minute; // hours -> minutes + result = result * Interval::SECS_PER_MINUTE + second; // minutes -> seconds + result = result * Interval::NANOS_PER_SEC + nanoseconds; // seconds -> nanoseconds + return result; +} + bool Time::IsValidTime(int32_t hour, int32_t minute, int32_t second, int32_t microseconds) { if (hour < 0 || hour >= 24) { return (hour == 24) && (minute == 0) && (second == 0) && (microseconds == 0); diff --git a/src/common/types/timestamp.cpp b/src/common/types/timestamp.cpp index 3ae9e46237c..a50d676340f 100644 --- a/src/common/types/timestamp.cpp +++ b/src/common/types/timestamp.cpp @@ -55,7 +55,8 @@ timestamp_t ×tamp_t::operator-=(const int64_t &delta) { return *this; } -bool Timestamp::TryConvertTimestampTZ(const char *str, idx_t len, timestamp_t &result, bool &has_offset, string_t &tz) { +bool Timestamp::TryConvertTimestampTZ(const char *str, idx_t len, timestamp_t &result, bool &has_offset, string_t &tz, + optional_ptr nanos) { idx_t pos; date_t date; dtime_t time; @@ -79,7 +80,14 @@ bool Timestamp::TryConvertTimestampTZ(const char *str, idx_t len, timestamp_t &r pos++; } idx_t time_pos = 0; - if (!Time::TryConvertTime(str + pos, len - pos, time_pos, time)) { + // TryConvertTime may recursively call us, so we opt for a stricter + // operation. Note that we can't pass strict== true here because we + // want to process any suffix. + if (!Time::TryConvertInterval(str + pos, len - pos, time_pos, time, false, nanos)) { + return false; + } + // We parsed an interval, so make sure it is in range. + if (time.micros > Interval::MICROS_PER_DAY) { return false; } pos += time_pos; @@ -125,11 +133,12 @@ bool Timestamp::TryConvertTimestampTZ(const char *str, idx_t len, timestamp_t &r return true; } -TimestampCastResult Timestamp::TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result) { +TimestampCastResult Timestamp::TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result, + optional_ptr nanos) { string_t tz(nullptr, 0); bool has_offset = false; // We don't understand TZ without an extension, so fail if one was provided. - auto success = TryConvertTimestampTZ(str, len, result, has_offset, tz); + auto success = TryConvertTimestampTZ(str, len, result, has_offset, tz, nanos); if (!success) { return TimestampCastResult::ERROR_INCORRECT_FORMAT; } @@ -148,6 +157,31 @@ TimestampCastResult Timestamp::TryConvertTimestamp(const char *str, idx_t len, t return TimestampCastResult::ERROR_NON_UTC_TIMEZONE; } +bool Timestamp::TryFromTimestampNanos(timestamp_t input, int32_t nanos, timestamp_ns_t &result) { + if (!IsFinite(input)) { + result.value = input.value; + return true; + } + // Scale to ns + if (!TryMultiplyOperator::Operation(input.value, Interval::NANOS_PER_MICRO, result.value)) { + return false; + } + + return TryAddOperator::Operation(result.value, int64_t(nanos), result.value); +} + +TimestampCastResult Timestamp::TryConvertTimestamp(const char *str, idx_t len, timestamp_ns_t &result) { + int32_t nanos = 0; + auto success = TryConvertTimestamp(str, len, result, &nanos); + if (success != TimestampCastResult::SUCCESS) { + return success; + } + if (!TryFromTimestampNanos(result, nanos, result)) { + return TimestampCastResult::ERROR_INCORRECT_FORMAT; + } + return TimestampCastResult::SUCCESS; +} + string Timestamp::ConversionError(const string &str) { return StringUtil::Format("timestamp field value out of range: \"%s\", " "expected format is (YYYY-MM-DD HH:MM:SS[.US][±HH:MM| ZONE])", @@ -168,9 +202,9 @@ string Timestamp::UnsupportedTimezoneError(string_t str) { return Timestamp::UnsupportedTimezoneError(str.GetString()); } -timestamp_t Timestamp::FromCString(const char *str, idx_t len) { +timestamp_t Timestamp::FromCString(const char *str, idx_t len, optional_ptr nanos) { timestamp_t result; - auto cast_result = Timestamp::TryConvertTimestamp(str, len, result); + auto cast_result = Timestamp::TryConvertTimestamp(str, len, result, nanos); if (cast_result == TimestampCastResult::SUCCESS) { return result; } @@ -246,9 +280,9 @@ string Timestamp::ToString(timestamp_t timestamp) { } date_t Timestamp::GetDate(timestamp_t timestamp) { - if (timestamp == timestamp_t::infinity()) { + if (DUCKDB_UNLIKELY(timestamp == timestamp_t::infinity())) { return date_t::infinity(); - } else if (timestamp == timestamp_t::ninfinity()) { + } else if (DUCKDB_UNLIKELY(timestamp == timestamp_t::ninfinity())) { return date_t::ninfinity(); } return date_t((timestamp.value + (timestamp.value < 0)) / Interval::MICROS_PER_DAY - (timestamp.value < 0)); @@ -303,6 +337,19 @@ void Timestamp::Convert(timestamp_t timestamp, date_t &out_date, dtime_t &out_ti D_ASSERT(timestamp == Timestamp::FromDatetime(out_date, out_time)); } +void Timestamp::Convert(timestamp_ns_t input, date_t &out_date, dtime_t &out_time, int32_t &out_nanos) { + timestamp_t ms(input.value / Interval::NANOS_PER_MICRO); + out_date = Timestamp::GetDate(ms); + int64_t days_nanos; + if (!TryMultiplyOperator::Operation(out_date.days, Interval::NANOS_PER_DAY, + days_nanos)) { + throw ConversionException("Date out of range in timestamp_ns conversion"); + } + + out_time = dtime_t((input.value - days_nanos) / Interval::NANOS_PER_MICRO); + out_nanos = (input.value - days_nanos) % Interval::NANOS_PER_MICRO; +} + timestamp_t Timestamp::GetCurrentTimestamp() { auto now = system_clock::now(); auto epoch_ms = duration_cast(now.time_since_epoch()).count(); @@ -340,7 +387,7 @@ timestamp_t Timestamp::FromEpochMicroSeconds(int64_t micros) { } timestamp_t Timestamp::FromEpochNanoSecondsPossiblyInfinite(int64_t ns) { - return timestamp_t(ns / 1000); + return timestamp_t(ns / Interval::NANOS_PER_MICRO); } timestamp_t Timestamp::FromEpochNanoSeconds(int64_t ns) { @@ -348,6 +395,24 @@ timestamp_t Timestamp::FromEpochNanoSeconds(int64_t ns) { return FromEpochNanoSecondsPossiblyInfinite(ns); } +timestamp_ns_t Timestamp::TimestampNsFromEpochMillis(int64_t millis) { + D_ASSERT(Timestamp::IsFinite(timestamp_t(millis))); + timestamp_ns_t result; + if (!TryMultiplyOperator::Operation(millis, Interval::NANOS_PER_MICRO, result.value)) { + throw ConversionException("Could not convert Timestamp(US) to Timestamp(NS)"); + } + return result; +} + +timestamp_ns_t Timestamp::TimestampNsFromEpochMicros(int64_t micros) { + D_ASSERT(Timestamp::IsFinite(timestamp_t(micros))); + timestamp_ns_t result; + if (!TryMultiplyOperator::Operation(micros, Interval::NANOS_PER_MSEC, result.value)) { + throw ConversionException("Could not convert Timestamp(MS) to Timestamp(NS)"); + } + return result; +} + int64_t Timestamp::GetEpochSeconds(timestamp_t timestamp) { D_ASSERT(Timestamp::IsFinite(timestamp)); return timestamp.value / Interval::MICROS_PER_SEC; @@ -363,9 +428,8 @@ int64_t Timestamp::GetEpochMicroSeconds(timestamp_t timestamp) { } bool Timestamp::TryGetEpochNanoSeconds(timestamp_t timestamp, int64_t &result) { - constexpr static const int64_t NANOSECONDS_IN_MICROSECOND = 1000; D_ASSERT(Timestamp::IsFinite(timestamp)); - if (!TryMultiplyOperator::Operation(timestamp.value, NANOSECONDS_IN_MICROSECOND, result)) { + if (!TryMultiplyOperator::Operation(timestamp.value, Interval::NANOS_PER_MICRO, result)) { return false; } return true; @@ -380,6 +444,21 @@ int64_t Timestamp::GetEpochNanoSeconds(timestamp_t timestamp) { return result; } +int64_t Timestamp::GetEpochRounded(timestamp_t input, int64_t power_of_ten) { + D_ASSERT(Timestamp::IsFinite(input)); + // Round away from the epoch. + // Scale first so we don't overflow. + const auto scaling = power_of_ten / 2; + input.value /= scaling; + if (input.value < 0) { + --input.value; + } else { + ++input.value; + } + input.value /= 2; + return input.value; +} + double Timestamp::GetJulianDay(timestamp_t timestamp) { double result = double(Timestamp::GetTime(timestamp).micros); result /= Interval::MICROS_PER_DAY; diff --git a/src/common/types/validity_mask.cpp b/src/common/types/validity_mask.cpp index d91c7a7373e..6af8a172b99 100644 --- a/src/common/types/validity_mask.cpp +++ b/src/common/types/validity_mask.cpp @@ -3,6 +3,7 @@ #include "duckdb/common/numeric_utils.hpp" #include "duckdb/common/serializer/write_stream.hpp" #include "duckdb/common/serializer/read_stream.hpp" +#include "duckdb/common/types/selection_vector.hpp" namespace duckdb { @@ -94,6 +95,24 @@ bool ValidityMask::IsAligned(idx_t count) { return count % BITS_PER_VALUE == 0; } +void ValidityMask::CopySel(const ValidityMask &other, const SelectionVector &sel, idx_t source_offset, + idx_t target_offset, idx_t copy_count) { + if (!other.IsMaskSet() && !IsMaskSet()) { + // no need to copy anything if neither has any null values + return; + } + + if (!sel.IsSet() && IsAligned(source_offset) && IsAligned(target_offset)) { + // common case where we are shifting into an aligned mask using a flat vector + SliceInPlace(other, target_offset, source_offset, copy_count); + return; + } + for (idx_t i = 0; i < copy_count; i++) { + auto source_idx = sel.get_index(source_offset + i); + Set(target_offset + i, other.RowIsValid(source_idx)); + } +} + void ValidityMask::SliceInPlace(const ValidityMask &other, idx_t target_offset, idx_t source_offset, idx_t count) { EnsureWritable(); if (IsAligned(source_offset) && IsAligned(target_offset)) { @@ -101,8 +120,13 @@ void ValidityMask::SliceInPlace(const ValidityMask &other, idx_t target_offset, auto source_validity = other.GetData(); auto source_offset_entries = EntryCount(source_offset); auto target_offset_entries = EntryCount(target_offset); - memcpy(target_validity + target_offset_entries, source_validity + source_offset_entries, - sizeof(validity_t) * EntryCount(count)); + if (!source_validity) { + // if source has no validity mask - set all bytes to 1 + memset(target_validity + target_offset_entries, 0xFF, sizeof(validity_t) * EntryCount(count)); + } else { + memcpy(target_validity + target_offset_entries, source_validity + source_offset_entries, + sizeof(validity_t) * EntryCount(count)); + } return; } else if (IsAligned(target_offset)) { // Simple common case where we are shifting into an aligned mask (e.g., 0 in Slice above) diff --git a/src/common/types/value.cpp b/src/common/types/value.cpp index fe7d9e5de6b..0224a33e870 100644 --- a/src/common/types/value.cpp +++ b/src/common/types/value.cpp @@ -230,12 +230,23 @@ Value Value::MinimumValue(const LogicalType &type) { case LogicalTypeId::TIMESTAMP: return Value::TIMESTAMP(Date::FromDate(Timestamp::MIN_YEAR, Timestamp::MIN_MONTH, Timestamp::MIN_DAY), dtime_t(0)); - case LogicalTypeId::TIMESTAMP_SEC: - return MinimumValue(LogicalType::TIMESTAMP).DefaultCastAs(LogicalType::TIMESTAMP_S); - case LogicalTypeId::TIMESTAMP_MS: - return MinimumValue(LogicalType::TIMESTAMP).DefaultCastAs(LogicalType::TIMESTAMP_MS); - case LogicalTypeId::TIMESTAMP_NS: - return Value::TIMESTAMPNS(timestamp_t(NumericLimits::Minimum())); + case LogicalTypeId::TIMESTAMP_SEC: { + // Casting rounds up, which will overflow + const auto min_us = MinimumValue(LogicalType::TIMESTAMP).GetValue(); + return Value::TIMESTAMPSEC(timestamp_t(Timestamp::GetEpochSeconds(min_us))); + } + case LogicalTypeId::TIMESTAMP_MS: { + // Casting rounds up, which will overflow + const auto min_us = MinimumValue(LogicalType::TIMESTAMP).GetValue(); + return Value::TIMESTAMPMS(timestamp_t(Timestamp::GetEpochMs(min_us))); + } + case LogicalTypeId::TIMESTAMP_NS: { + // Clear the fractional day. + auto min_ns = NumericLimits::Minimum(); + min_ns /= Interval::NANOS_PER_DAY; + min_ns *= Interval::NANOS_PER_DAY; + return Value::TIMESTAMPNS(timestamp_t(min_ns)); + } case LogicalTypeId::TIME_TZ: // "00:00:00+1559" from the PG docs, but actually 00:00:00+15:59:59 return Value::TIMETZ(dtime_tz_t(dtime_t(0), dtime_tz_t::MAX_OFFSET)); @@ -303,12 +314,18 @@ Value Value::MaximumValue(const LogicalType &type) { return Value::TIME(dtime_t(Interval::MICROS_PER_DAY)); case LogicalTypeId::TIMESTAMP: return Value::TIMESTAMP(timestamp_t(NumericLimits::Maximum() - 1)); - case LogicalTypeId::TIMESTAMP_MS: - return MaximumValue(LogicalType::TIMESTAMP).DefaultCastAs(LogicalType::TIMESTAMP_MS); + case LogicalTypeId::TIMESTAMP_MS: { + // Casting rounds up, which will overflow + const auto max_us = MaximumValue(LogicalType::TIMESTAMP).GetValue(); + return Value::TIMESTAMPMS(timestamp_t(Timestamp::GetEpochMs(max_us))); + } case LogicalTypeId::TIMESTAMP_NS: return Value::TIMESTAMPNS(timestamp_t(NumericLimits::Maximum() - 1)); - case LogicalTypeId::TIMESTAMP_SEC: - return MaximumValue(LogicalType::TIMESTAMP).DefaultCastAs(LogicalType::TIMESTAMP_S); + case LogicalTypeId::TIMESTAMP_SEC: { + // Casting rounds up, which will overflow + const auto max_us = MaximumValue(LogicalType::TIMESTAMP).GetValue(); + return Value::TIMESTAMPSEC(timestamp_t(Timestamp::GetEpochSeconds(max_us))); + } case LogicalTypeId::TIME_TZ: // "24:00:00-1559" from the PG docs but actually "24:00:00-15:59:59" return Value::TIMETZ(dtime_tz_t(dtime_t(Interval::MICROS_PER_DAY), dtime_tz_t::MIN_OFFSET)); @@ -334,8 +351,10 @@ Value Value::MaximumValue(const LogicalType &type) { throw InternalException("Unknown decimal type"); } } - case LogicalTypeId::ENUM: - return Value::ENUM(EnumType::GetSize(type) - 1, type); + case LogicalTypeId::ENUM: { + auto enum_size = EnumType::GetSize(type); + return Value::ENUM(enum_size - (enum_size ? 1 : 0), type); + } default: throw InvalidTypeException(type, "MaximumValue requires numeric type"); } @@ -715,6 +734,18 @@ Value Value::MAP(const LogicalType &key_type, const LogicalType &value_type, vec return result; } +Value Value::MAP(const unordered_map &kv_pairs) { + Value result; + result.type_ = LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR); + result.is_null = false; + vector pairs; + for (auto &kv : kv_pairs) { + pairs.push_back(Value::STRUCT({{"key", Value(kv.first)}, {"value", Value(kv.second)}})); + } + result.value_info_ = make_shared_ptr(std::move(pairs)); + return result; +} + Value Value::UNION(child_list_t members, uint8_t tag, Value value) { D_ASSERT(!members.empty()); D_ASSERT(members.size() <= UnionType::MAX_UNION_MEMBERS); diff --git a/src/common/types/vector.cpp b/src/common/types/vector.cpp index 112dc0de96a..ed9df746c1b 100644 --- a/src/common/types/vector.cpp +++ b/src/common/types/vector.cpp @@ -30,7 +30,7 @@ namespace duckdb { UnifiedVectorFormat::UnifiedVectorFormat() : sel(nullptr), data(nullptr) { } -UnifiedVectorFormat::UnifiedVectorFormat(UnifiedVectorFormat &&other) noexcept { +UnifiedVectorFormat::UnifiedVectorFormat(UnifiedVectorFormat &&other) noexcept : sel(nullptr), data(nullptr) { bool refers_to_self = other.sel == &other.owned_sel; std::swap(sel, other.sel); std::swap(data, other.data); @@ -306,103 +306,82 @@ void Vector::Initialize(bool zero_data, idx_t capacity) { } } -struct DataArrays { - Vector &vec; - data_ptr_t data; - optional_ptr buffer; - idx_t type_size; - bool is_nested; - idx_t nested_multiplier; - DataArrays(Vector &vec, data_ptr_t data, optional_ptr buffer, idx_t type_size, bool is_nested, - idx_t nested_multiplier = 1) - : vec(vec), data(data), buffer(buffer), type_size(type_size), is_nested(is_nested), - nested_multiplier(nested_multiplier) { - } -}; - -void FindChildren(vector &to_resize, VectorBuffer &auxiliary, idx_t current_multiplier) { - if (auxiliary.GetBufferType() == VectorBufferType::LIST_BUFFER) { - auto &buffer = auxiliary.Cast(); - auto &child = buffer.GetChild(); - auto data = child.GetData(); - if (!data) { - //! Nested type - DataArrays arrays(child, data, child.GetBuffer().get(), GetTypeIdSize(child.GetType().InternalType()), - true); - to_resize.emplace_back(arrays); - FindChildren(to_resize, *child.GetAuxiliary(), current_multiplier); - } else { - DataArrays arrays(child, data, child.GetBuffer().get(), GetTypeIdSize(child.GetType().InternalType()), - false); - to_resize.emplace_back(arrays); - } - } else if (auxiliary.GetBufferType() == VectorBufferType::STRUCT_BUFFER) { - auto &buffer = auxiliary.Cast(); - auto &children = buffer.GetChildren(); +void Vector::FindResizeInfos(vector &resize_infos, const idx_t multiplier) { + + ResizeInfo resize_info(*this, data, buffer.get(), multiplier); + resize_infos.emplace_back(resize_info); + + // Base case. + if (data) { + return; + } + + D_ASSERT(auxiliary); + switch (GetAuxiliary()->GetBufferType()) { + case VectorBufferType::LIST_BUFFER: { + auto &vector_list_buffer = auxiliary->Cast(); + auto &child = vector_list_buffer.GetChild(); + child.FindResizeInfos(resize_infos, multiplier); + break; + } + case VectorBufferType::STRUCT_BUFFER: { + auto &vector_struct_buffer = auxiliary->Cast(); + auto &children = vector_struct_buffer.GetChildren(); for (auto &child : children) { - auto data = child->GetData(); - if (!data) { - //! Nested type - DataArrays arrays(*child, data, child->GetBuffer().get(), - GetTypeIdSize(child->GetType().InternalType()), true); - to_resize.emplace_back(arrays); - FindChildren(to_resize, *child->GetAuxiliary(), current_multiplier); - } else { - DataArrays arrays(*child, data, child->GetBuffer().get(), - GetTypeIdSize(child->GetType().InternalType()), false); - to_resize.emplace_back(arrays); - } - } - } else if (auxiliary.GetBufferType() == VectorBufferType::ARRAY_BUFFER) { - auto &buffer = auxiliary.Cast(); - auto array_size = buffer.GetArraySize(); - auto &child = buffer.GetChild(); - auto data = child.GetData(); - if (!data) { - //! Nested type - DataArrays arrays(child, data, child.GetBuffer().get(), GetTypeIdSize(child.GetType().InternalType()), true, - current_multiplier); - to_resize.emplace_back(arrays); - - // The child vectors of ArrayTypes always have to be (size * array_size), so we need to multiply the - // multiplier by the array size - auto new_multiplier = current_multiplier * array_size; - FindChildren(to_resize, *child.GetAuxiliary(), new_multiplier); - } else { - DataArrays arrays(child, data, child.GetBuffer().get(), GetTypeIdSize(child.GetType().InternalType()), - false, current_multiplier); - to_resize.emplace_back(arrays); + child->FindResizeInfos(resize_infos, multiplier); } + break; + } + case VectorBufferType::ARRAY_BUFFER: { + // We need to multiply the multiplier by the array size because + // the child vectors of ARRAY types are always child_count * array_size. + auto &vector_array_buffer = auxiliary->Cast(); + auto new_multiplier = vector_array_buffer.GetArraySize() * multiplier; + auto &child = vector_array_buffer.GetChild(); + child.FindResizeInfos(resize_infos, new_multiplier); + break; + } + default: + break; } } -void Vector::Resize(idx_t cur_size, idx_t new_size) { - vector to_resize; + +void Vector::Resize(idx_t current_size, idx_t new_size) { + // The vector does not contain any data. if (!buffer) { buffer = make_buffer(0); } - if (!data) { - //! this is a nested structure - DataArrays arrays(*this, data, buffer.get(), GetTypeIdSize(GetType().InternalType()), true); - to_resize.emplace_back(arrays); - // The child vectors of ArrayTypes always have to be (size * array_size), so we need to multiply the - // resize amount by the array size recursively for every nested array. - auto start_multiplier = GetType().id() == LogicalTypeId::ARRAY ? ArrayType::GetSize(GetType()) : 1; - FindChildren(to_resize, *auxiliary, start_multiplier); - } else { - DataArrays arrays(*this, data, buffer.get(), GetTypeIdSize(GetType().InternalType()), false); - to_resize.emplace_back(arrays); - } - for (auto &data_to_resize : to_resize) { - if (!data_to_resize.is_nested) { - auto new_data = - make_unsafe_uniq_array(new_size * data_to_resize.type_size * data_to_resize.nested_multiplier); - memcpy(new_data.get(), data_to_resize.data, - cur_size * data_to_resize.type_size * data_to_resize.nested_multiplier * sizeof(data_t)); - data_to_resize.buffer->SetData(std::move(new_data)); - data_to_resize.vec.data = data_to_resize.buffer->GetData(); + // Obtain the resize information for each (nested) vector. + vector resize_infos; + FindResizeInfos(resize_infos, 1); + + for (auto &resize_info_entry : resize_infos) { + // Resize the validity mask. + auto new_validity_size = new_size * resize_info_entry.multiplier; + resize_info_entry.vec.validity.Resize(current_size, new_validity_size); + + // For nested data types, we only need to resize the validity mask. + if (!resize_info_entry.data) { + continue; } - data_to_resize.vec.validity.Resize(cur_size, new_size * data_to_resize.nested_multiplier); + + auto type_size = GetTypeIdSize(resize_info_entry.vec.GetType().InternalType()); + auto old_size = current_size * type_size * resize_info_entry.multiplier * sizeof(data_t); + auto target_size = new_size * type_size * resize_info_entry.multiplier * sizeof(data_t); + + // We have an upper limit of 128GB for a single vector. + if (target_size > DConstants::MAX_VECTOR_SIZE) { + throw OutOfRangeException("Cannot resize vector to %s: maximum allowed vector size is %s", + StringUtil::BytesToHumanReadableString(target_size), + StringUtil::BytesToHumanReadableString(DConstants::MAX_VECTOR_SIZE)); + } + + // Copy the data buffer to a resized buffer. + auto new_data = make_unsafe_uniq_array(target_size); + memcpy(new_data.get(), resize_info_entry.data, old_size); + resize_info_entry.buffer->SetData(std::move(new_data)); + resize_info_entry.vec.data = resize_info_entry.buffer->GetData(); } } @@ -804,6 +783,44 @@ void Vector::Print(idx_t count) const { Printer::Print(ToString(count)); } +// TODO: add the size of validity masks to this +idx_t Vector::GetAllocationSize(idx_t cardinality) const { + if (!type.IsNested()) { + auto physical_size = GetTypeIdSize(type.InternalType()); + return cardinality * physical_size; + } + auto internal_type = type.InternalType(); + switch (internal_type) { + case PhysicalType::LIST: { + auto physical_size = GetTypeIdSize(type.InternalType()); + auto total_size = physical_size * cardinality; + + auto child_cardinality = ListVector::GetListCapacity(*this); + auto &child_entry = ListVector::GetEntry(*this); + total_size += (child_entry.GetAllocationSize(child_cardinality)); + return total_size; + } + case PhysicalType::ARRAY: { + auto child_cardinality = ArrayVector::GetTotalSize(*this); + + auto &child_entry = ArrayVector::GetEntry(*this); + auto total_size = (child_entry.GetAllocationSize(child_cardinality)); + return total_size; + } + case PhysicalType::STRUCT: { + idx_t total_size = 0; + auto &children = StructVector::GetEntries(*this); + for (auto &child : children) { + total_size += child->GetAllocationSize(cardinality); + } + return total_size; + } + default: + throw NotImplementedException("Vector::GetAllocationSize not implemented for type: %s", type.ToString()); + break; + } +} + string Vector::ToString() const { string retval = VectorTypeToString(GetVectorType()) + " " + GetType().ToString() + ": (UNKNOWN COUNT) [ "; switch (GetVectorType()) { @@ -881,7 +898,10 @@ void Vector::Flatten(idx_t count) { // constant NULL, set nullmask validity.EnsureWritable(); validity.SetAllInvalid(count); - return; + if (GetType().InternalType() != PhysicalType::STRUCT) { + // for structs we still need to flatten the child vectors as well + return; + } } // non-null constant: have to repeat the constant switch (GetType().InternalType()) { @@ -1176,8 +1196,13 @@ void Vector::Serialize(Serializer &serializer, idx_t count) { for (idx_t i = 0; i < count; i++) { auto idx = vdata.sel->get_index(i); auto source = source_array[idx]; - entries[i].offset = source.offset; - entries[i].length = source.length; + if (vdata.validity.RowIsValid(idx)) { + entries[i].offset = source.offset; + entries[i].length = source.length; + } else { + entries[i].offset = 0; + entries[i].length = 0; + } } serializer.WriteProperty(104, "list_size", list_size); serializer.WriteList(105, "entries", count, [&](Serializer::List &list, idx_t i) { @@ -1213,7 +1238,7 @@ void Vector::Deserialize(Deserializer &deserializer, idx_t count) { validity.Reset(); const auto has_validity = deserializer.ReadProperty(100, "all_valid"); if (has_validity) { - validity.Initialize(count); + validity.Initialize(MaxValue(count, STANDARD_VECTOR_SIZE)); deserializer.ReadProperty(101, "validity", data_ptr_cast(validity.GetData()), validity.ValidityMaskSize(count)); } diff --git a/src/common/types/vector_buffer.cpp b/src/common/types/vector_buffer.cpp index 7a7db5faeaf..59bc6f9cadf 100644 --- a/src/common/types/vector_buffer.cpp +++ b/src/common/types/vector_buffer.cpp @@ -68,6 +68,10 @@ VectorListBuffer::VectorListBuffer(const LogicalType &list_type, idx_t initial_c void VectorListBuffer::Reserve(idx_t to_reserve) { if (to_reserve > capacity) { idx_t new_capacity = NextPowerOfTwo(to_reserve); + if (new_capacity == 0) { + // Overflow: set to_reserve to the maximum value + new_capacity = to_reserve; + } D_ASSERT(new_capacity >= to_reserve); child->Resize(capacity, new_capacity); capacity = new_capacity; diff --git a/src/common/vector_operations/generators.cpp b/src/common/vector_operations/generators.cpp index a5faba93747..2fc5b67c6d7 100644 --- a/src/common/vector_operations/generators.cpp +++ b/src/common/vector_operations/generators.cpp @@ -18,7 +18,7 @@ void TemplatedGenerateSequence(Vector &result, idx_t count, int64_t start, int64 } result.SetVectorType(VectorType::FLAT_VECTOR); auto result_data = FlatVector::GetData(result); - auto value = (T)start; + auto value = T(start); for (idx_t i = 0; i < count; i++) { if (i > 0) { value += increment; @@ -44,12 +44,6 @@ void VectorOperations::GenerateSequence(Vector &result, idx_t count, int64_t sta case PhysicalType::INT64: TemplatedGenerateSequence(result, count, start, increment); break; - case PhysicalType::FLOAT: - TemplatedGenerateSequence(result, count, start, increment); - break; - case PhysicalType::DOUBLE: - TemplatedGenerateSequence(result, count, start, increment); - break; default: throw NotImplementedException("Unimplemented type for generate sequence"); } @@ -64,10 +58,10 @@ void TemplatedGenerateSequence(Vector &result, idx_t count, const SelectionVecto } result.SetVectorType(VectorType::FLAT_VECTOR); auto result_data = FlatVector::GetData(result); - auto value = (T)start; + auto value = static_cast(start); for (idx_t i = 0; i < count; i++) { - auto idx = UnsafeNumericCast(sel.get_index(i)); - result_data[idx] = UnsafeNumericCast(value + increment * idx); + auto idx = sel.get_index(i); + result_data[idx] = static_cast(value + static_cast(increment) * idx); } } @@ -89,12 +83,6 @@ void VectorOperations::GenerateSequence(Vector &result, idx_t count, const Selec case PhysicalType::INT64: TemplatedGenerateSequence(result, count, sel, start, increment); break; - case PhysicalType::FLOAT: - TemplatedGenerateSequence(result, count, sel, start, increment); - break; - case PhysicalType::DOUBLE: - TemplatedGenerateSequence(result, count, sel, start, increment); - break; default: throw NotImplementedException("Unimplemented type for generate sequence"); } diff --git a/src/common/vector_operations/is_distinct_from.cpp b/src/common/vector_operations/is_distinct_from.cpp index 82ef31663a0..e9a31ee0e66 100644 --- a/src/common/vector_operations/is_distinct_from.cpp +++ b/src/common/vector_operations/is_distinct_from.cpp @@ -476,6 +476,16 @@ idx_t PositionComparator::Final(Vector &left, Vector & return VectorOperations::DistinctGreaterThan(right, left, &sel, count, true_sel, false_sel, null_mask); } +template <> +idx_t PositionComparator::Final(Vector &left, Vector &right, + const SelectionVector &sel, idx_t count, + optional_ptr true_sel, + optional_ptr false_sel, + optional_ptr null_mask) { + // DistinctGreaterThan has NULLs last + return VectorOperations::DistinctGreaterThan(right, left, &sel, count, true_sel, false_sel, null_mask); +} + template <> idx_t PositionComparator::Final(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, optional_ptr true_sel, @@ -484,6 +494,16 @@ idx_t PositionComparator::Final(Vector &left, Vecto return VectorOperations::DistinctGreaterThan(left, right, &sel, count, true_sel, false_sel, null_mask); } +template <> +idx_t PositionComparator::Final(Vector &left, Vector &right, + const SelectionVector &sel, idx_t count, + optional_ptr true_sel, + optional_ptr false_sel, + optional_ptr null_mask) { + // DistinctLessThan has NULLs last + return VectorOperations::DistinctLessThan(right, left, &sel, count, true_sel, false_sel, null_mask); +} + using StructEntries = vector>; static void ExtractNestedSelection(const SelectionVector &slice_sel, const idx_t count, const SelectionVector &sel, diff --git a/src/common/vector_operations/vector_copy.cpp b/src/common/vector_operations/vector_copy.cpp index 3823cd39e30..7315a4e591d 100644 --- a/src/common/vector_operations/vector_copy.cpp +++ b/src/common/vector_operations/vector_copy.cpp @@ -23,7 +23,7 @@ static void TemplatedCopy(const Vector &source, const SelectionVector &sel, Vect } } -static const ValidityMask &CopyValidityMask(const Vector &v) { +static const ValidityMask &ExtractValidityMask(const Vector &v) { switch (v.GetVectorType()) { case VectorType::FLAT_VECTOR: return FlatVector::Validity(v); @@ -101,25 +101,8 @@ void VectorOperations::Copy(const Vector &source_p, Vector &target, const Select tmask.Set(target_offset + i, valid); } } else { - auto &smask = CopyValidityMask(*source); - if (smask.IsMaskSet() || tmask.IsMaskSet()) { - for (idx_t i = 0; i < copy_count; i++) { - auto idx = sel->get_index(source_offset + i); - - if (smask.RowIsValid(idx)) { - // set valid - if (!tmask.AllValid()) { - tmask.SetValidUnsafe(target_offset + i); - } - } else { - // set invalid - if (tmask.AllValid()) { - tmask.Initialize(); - } - tmask.SetInvalidUnsafe(target_offset + i); - } - } - } + auto &smask = ExtractValidityMask(*source); + tmask.CopySel(smask, *sel, source_offset, target_offset, copy_count); } D_ASSERT(sel); diff --git a/src/core_functions/aggregate/distributive/approx_count.cpp b/src/core_functions/aggregate/distributive/approx_count.cpp index 6b8dd0d7c66..f9479f179c3 100644 --- a/src/core_functions/aggregate/distributive/approx_count.cpp +++ b/src/core_functions/aggregate/distributive/approx_count.cpp @@ -5,109 +5,165 @@ #include "duckdb/function/function_set.hpp" #include "duckdb/planner/expression/bound_aggregate_expression.hpp" +#include "hyperloglog.hpp" + +#include + namespace duckdb { +// Algorithms from +// "New cardinality estimation algorithms for HyperLogLog sketches" +// Otmar Ertl, arXiv:1702.01284 struct ApproxDistinctCountState { - ApproxDistinctCountState() : log(nullptr) { + static constexpr idx_t P = 6; + static constexpr idx_t Q = 64 - P; + static constexpr idx_t M = 1 << P; + static constexpr double ALPHA = 0.721347520444481703680; // 1 / (2 log(2)) + + ApproxDistinctCountState() { + ::memset(k, 0, sizeof(k)); + } + + //! Taken from https://stackoverflow.com/a/72088344 + static inline uint8_t CountTrailingZeros(const uint64_t &x) { + static constexpr const uint64_t DEBRUIJN = 0x03f79d71b4cb0a89; + static constexpr const uint8_t LOOKUP[] = {0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61, + 54, 58, 35, 52, 50, 42, 21, 44, 38, 32, 29, 23, 17, 11, 4, 62, + 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43, 31, 22, 10, 45, + 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63}; + return LOOKUP[(DEBRUIJN * (x ^ (x - 1))) >> 58]; + } + + inline void Update(const idx_t &i, const uint8_t &z) { + k[i] = MaxValue(k[i], z); + } + + //! Algorithm 1 + inline void InsertElement(hash_t h) { + const auto i = h & ((1 << P) - 1); + h >>= P; + h |= hash_t(1) << Q; + const uint8_t z = CountTrailingZeros(h) + 1; + Update(i, z); } - ~ApproxDistinctCountState() { - if (log) { - delete log; + + //! Algorithm 2 + inline void Merge(const ApproxDistinctCountState &other) { + for (idx_t i = 0; i < M; ++i) { + Update(i, other.k[i]); } } - HyperLogLog *log; + //! Algorithm 4 + void ExtractCounts(uint32_t *c) const { + for (idx_t i = 0; i < M; ++i) { + c[k[i]]++; + } + } + + //! Algorithm 6 + static int64_t EstimateCardinality(uint32_t *c) { + auto z = M * duckdb_hll::hllTau((M - c[Q]) / double(M)); + + for (idx_t k = Q; k >= 1; --k) { + z += c[k]; + z *= 0.5; + } + + z += M * duckdb_hll::hllSigma(c[0] / double(M)); + + return llroundl(ALPHA * M * M / z); + } + + idx_t Count() const { + uint32_t c[Q + 2] = {0}; + ExtractCounts(c); + return idx_t(EstimateCardinality(c)); + } + + uint8_t k[M]; }; struct ApproxCountDistinctFunction { template static void Initialize(STATE &state) { - state.log = nullptr; + new (&state) STATE(); } template static void Combine(const STATE &source, STATE &target, AggregateInputData &) { - if (!source.log) { - return; - } - if (!target.log) { - target.log = new HyperLogLog(); - } - D_ASSERT(target.log); - D_ASSERT(source.log); - auto new_log = target.log->MergePointer(*source.log); - delete target.log; - target.log = new_log; + target.Merge(source); } template static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { - if (state.log) { - target = UnsafeNumericCast(state.log->Count()); - } else { - target = 0; - } + target = UnsafeNumericCast(state.Count()); } static bool IgnoreNull() { return true; } - - template - static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { - if (state.log) { - delete state.log; - state.log = nullptr; - } - } }; static void ApproxCountDistinctSimpleUpdateFunction(Vector inputs[], AggregateInputData &, idx_t input_count, data_ptr_t state, idx_t count) { D_ASSERT(input_count == 1); + auto &input = inputs[0]; + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); - auto agg_state = reinterpret_cast(state); - if (!agg_state->log) { - agg_state->log = new HyperLogLog(); + if (count > STANDARD_VECTOR_SIZE) { + throw InternalException("ApproxCountDistinct - count must be at most vector size"); } + Vector hash_vec(LogicalType::HASH, count); + VectorOperations::Hash(input, hash_vec, count); - UnifiedVectorFormat vdata; - inputs[0].ToUnifiedFormat(count, vdata); + UnifiedVectorFormat hdata; + hash_vec.ToUnifiedFormat(count, hdata); + const auto *hashes = UnifiedVectorFormat::GetData(hdata); + auto agg_state = reinterpret_cast(state); - if (count > STANDARD_VECTOR_SIZE) { - throw InternalException("ApproxCountDistinct - count must be at most vector size"); + if (hash_vec.GetVectorType() == VectorType::CONSTANT_VECTOR) { + if (idata.validity.RowIsValid(0)) { + agg_state->InsertElement(hashes[0]); + } + } else { + for (idx_t i = 0; i < count; ++i) { + if (idata.validity.RowIsValid(idata.sel->get_index(i))) { + const auto hash = hashes[hdata.sel->get_index(i)]; + agg_state->InsertElement(hash); + } + } } - uint64_t indices[STANDARD_VECTOR_SIZE]; - uint8_t counts[STANDARD_VECTOR_SIZE]; - HyperLogLog::ProcessEntries(vdata, inputs[0].GetType(), indices, counts, count); - agg_state->log->AddToLog(vdata, count, indices, counts); } static void ApproxCountDistinctUpdateFunction(Vector inputs[], AggregateInputData &, idx_t input_count, Vector &state_vector, idx_t count) { D_ASSERT(input_count == 1); + auto &input = inputs[0]; + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); + + if (count > STANDARD_VECTOR_SIZE) { + throw InternalException("ApproxCountDistinct - count must be at most vector size"); + } + Vector hash_vec(LogicalType::HASH, count); + VectorOperations::Hash(input, hash_vec, count); UnifiedVectorFormat sdata; state_vector.ToUnifiedFormat(count, sdata); - auto states = UnifiedVectorFormat::GetDataNoConst(sdata); + const auto states = UnifiedVectorFormat::GetDataNoConst(sdata); + UnifiedVectorFormat hdata; + hash_vec.ToUnifiedFormat(count, hdata); + const auto *hashes = UnifiedVectorFormat::GetData(hdata); for (idx_t i = 0; i < count; i++) { - auto agg_state = states[sdata.sel->get_index(i)]; - if (!agg_state->log) { - agg_state->log = new HyperLogLog(); + if (idata.validity.RowIsValid(idata.sel->get_index(i))) { + auto agg_state = states[sdata.sel->get_index(i)]; + const auto hash = hashes[hdata.sel->get_index(i)]; + agg_state->InsertElement(hash); } } - - UnifiedVectorFormat vdata; - inputs[0].ToUnifiedFormat(count, vdata); - - if (count > STANDARD_VECTOR_SIZE) { - throw InternalException("ApproxCountDistinct - count must be at most vector size"); - } - uint64_t indices[STANDARD_VECTOR_SIZE]; - uint8_t counts[STANDARD_VECTOR_SIZE]; - HyperLogLog::ProcessEntries(vdata, inputs[0].GetType(), indices, counts, count); - HyperLogLog::AddToLogs(vdata, count, indices, counts, reinterpret_cast(states), sdata.sel); } AggregateFunction GetApproxCountDistinctFunction(const LogicalType &input_type) { @@ -117,30 +173,13 @@ AggregateFunction GetApproxCountDistinctFunction(const LogicalType &input_type) ApproxCountDistinctUpdateFunction, AggregateFunction::StateCombine, AggregateFunction::StateFinalize, - ApproxCountDistinctSimpleUpdateFunction, nullptr, - AggregateFunction::StateDestroy); + ApproxCountDistinctSimpleUpdateFunction); fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; return fun; } -AggregateFunctionSet ApproxCountDistinctFun::GetFunctions() { - AggregateFunctionSet approx_count("approx_count_distinct"); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::UTINYINT)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::USMALLINT)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::UINTEGER)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::UBIGINT)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::UHUGEINT)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::TINYINT)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::SMALLINT)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::BIGINT)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::HUGEINT)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::FLOAT)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::DOUBLE)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::TIMESTAMP)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::TIMESTAMP_TZ)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::BLOB)); - approx_count.AddFunction(GetApproxCountDistinctFunction(LogicalType::ANY_PARAMS(LogicalType::VARCHAR, 150))); - return approx_count; +AggregateFunction ApproxCountDistinctFun::GetFunction() { + return GetApproxCountDistinctFunction(LogicalType::ANY); } } // namespace duckdb diff --git a/src/core_functions/aggregate/distributive/arg_min_max.cpp b/src/core_functions/aggregate/distributive/arg_min_max.cpp index 01f677e9bfa..99ec376d056 100644 --- a/src/core_functions/aggregate/distributive/arg_min_max.cpp +++ b/src/core_functions/aggregate/distributive/arg_min_max.cpp @@ -1,12 +1,13 @@ -#include "duckdb/core_functions/aggregate/distributive_functions.hpp" #include "duckdb/common/exception.hpp" +#include "duckdb/common/operator/comparison_operators.hpp" #include "duckdb/common/vector_operations/vector_operations.hpp" +#include "duckdb/core_functions/aggregate/distributive_functions.hpp" #include "duckdb/function/cast/cast_function_set.hpp" #include "duckdb/function/function_set.hpp" #include "duckdb/planner/expression/bound_aggregate_expression.hpp" #include "duckdb/planner/expression/bound_comparison_expression.hpp" #include "duckdb/planner/expression_binder.hpp" -#include "duckdb/common/operator/comparison_operators.hpp" +#include "duckdb/core_functions/create_sort_key.hpp" namespace duckdb { @@ -42,11 +43,6 @@ void ArgMinMaxStateBase::CreateValue(string_t &value) { value = string_t(uint32_t(0)); } -template <> -void ArgMinMaxStateBase::CreateValue(Vector *&value) { - value = nullptr; -} - template <> void ArgMinMaxStateBase::DestroyValue(string_t &value) { if (!value.IsInlined()) { @@ -54,12 +50,6 @@ void ArgMinMaxStateBase::DestroyValue(string_t &value) { } } -template <> -void ArgMinMaxStateBase::DestroyValue(Vector *&value) { - delete value; - value = nullptr; -} - template <> void ArgMinMaxStateBase::AssignValue(string_t &target, string_t new_value) { DestroyValue(target); @@ -104,7 +94,6 @@ struct ArgMinMaxState : public ArgMinMaxStateBase { template struct ArgMinMaxBase { - template static void Initialize(STATE &state) { new (&state) STATE; @@ -164,7 +153,7 @@ struct ArgMinMaxBase { if (!state.is_initialized || state.arg_null) { finalize_data.ReturnNull(); } else { - STATE::template ReadValue(finalize_data.result, state.arg, target); + STATE::template ReadValue(finalize_data.result, state.arg, target); } } @@ -174,45 +163,64 @@ struct ArgMinMaxBase { static unique_ptr Bind(ClientContext &context, AggregateFunction &function, vector> &arguments) { - ExpressionBinder::PushCollation(context, arguments[1], arguments[1]->return_type, false); + if (arguments[1]->return_type.InternalType() == PhysicalType::VARCHAR) { + ExpressionBinder::PushCollation(context, arguments[1], arguments[1]->return_type); + } function.arguments[0] = arguments[0]->return_type; function.return_type = arguments[0]->return_type; return nullptr; } }; -template -struct VectorArgMinMaxBase : ArgMinMaxBase { - template - static void AssignVector(STATE &state, Vector &arg, bool arg_null, const idx_t idx) { - if (!state.arg) { - state.arg = new Vector(arg.GetType(), 1); - state.arg->SetVectorType(VectorType::CONSTANT_VECTOR); - } - state.arg_null = arg_null; - if (!arg_null) { - sel_t selv = UnsafeNumericCast(idx); - SelectionVector sel(&selv); - VectorOperations::Copy(arg, *state.arg, sel, 1, 0, 0); - } +struct SpecializedGenericArgMinMaxState { + static bool CreateExtraState() { + // nop extra state + return false; + } + + static void PrepareData(Vector &by, idx_t count, bool &, UnifiedVectorFormat &result) { + by.ToUnifiedFormat(count, result); + } +}; + +template +struct GenericArgMinMaxState { + static Vector CreateExtraState() { + return Vector(LogicalType::BLOB); } + static void PrepareData(Vector &by, idx_t count, Vector &extra_state, UnifiedVectorFormat &result) { + OrderModifiers modifiers(ORDER_TYPE, OrderByNullType::NULLS_LAST); + CreateSortKeyHelpers::CreateSortKey(by, count, modifiers, extra_state); + extra_state.ToUnifiedFormat(count, result); + } +}; + +template +struct VectorArgMinMaxBase : ArgMinMaxBase { template static void Update(Vector inputs[], AggregateInputData &, idx_t input_count, Vector &state_vector, idx_t count) { auto &arg = inputs[0]; UnifiedVectorFormat adata; arg.ToUnifiedFormat(count, adata); + using ARG_TYPE = typename STATE::ARG_TYPE; using BY_TYPE = typename STATE::BY_TYPE; auto &by = inputs[1]; UnifiedVectorFormat bdata; - by.ToUnifiedFormat(count, bdata); + auto extra_state = UPDATE_TYPE::CreateExtraState(); + UPDATE_TYPE::PrepareData(by, count, extra_state, bdata); const auto bys = UnifiedVectorFormat::GetData(bdata); UnifiedVectorFormat sdata; state_vector.ToUnifiedFormat(count, sdata); - auto states = (STATE **)sdata.data; + STATE *last_state = nullptr; + sel_t assign_sel[STANDARD_VECTOR_SIZE]; + idx_t assign_count = 0; + + auto states = UnifiedVectorFormat::GetData(sdata); for (idx_t i = 0; i < count; i++) { const auto bidx = bdata.sel->get_index(i); if (!bdata.validity.RowIsValid(bidx)) { @@ -228,16 +236,42 @@ struct VectorArgMinMaxBase : ArgMinMaxBase { const auto sidx = sdata.sel->get_index(i); auto &state = *states[sidx]; - if (!state.is_initialized) { + if (!state.is_initialized || COMPARATOR::template Operation(bval, state.value)) { STATE::template AssignValue(state.value, bval); - AssignVector(state, arg, arg_null, i); + state.arg_null = arg_null; + // micro-adaptivity: it is common we overwrite the same state repeatedly + // e.g. when running arg_max(val, ts) and ts is sorted in ascending order + // this check essentially says: + // "if we are overriding the same state as the last row, the last write was pointless" + // hence we skip the last write altogether + if (!arg_null) { + if (&state == last_state) { + assign_count--; + } + assign_sel[assign_count++] = UnsafeNumericCast(i); + last_state = &state; + } state.is_initialized = true; - - } else if (COMPARATOR::template Operation(bval, state.value)) { - STATE::template AssignValue(state.value, bval); - AssignVector(state, arg, arg_null, i); } } + if (assign_count == 0) { + // no need to assign anything: nothing left to do + return; + } + Vector sort_key(LogicalType::BLOB); + auto modifiers = OrderModifiers(ORDER_TYPE, OrderByNullType::NULLS_LAST); + // slice with a selection vector and generate sort keys + SelectionVector sel(assign_sel); + Vector sliced_input(arg, sel, assign_count); + CreateSortKeyHelpers::CreateSortKey(sliced_input, assign_count, modifiers, sort_key); + auto sort_key_data = FlatVector::GetData(sort_key); + + // now assign sort keys + for (idx_t i = 0; i < assign_count; i++) { + const auto sidx = sdata.sel->get_index(sel.get_index(i)); + auto &state = *states[sidx]; + STATE::template AssignValue(state.arg, sort_key_data[i]); + } } template @@ -246,8 +280,12 @@ struct VectorArgMinMaxBase : ArgMinMaxBase { return; } if (!target.is_initialized || COMPARATOR::Operation(source.value, target.value)) { - STATE::template AssignValue(target.value, source.value); - AssignVector(target, *source.arg, source.arg_null, 0); + STATE::template AssignValue(target.value, source.value); + target.arg_null = source.arg_null; + if (!target.arg_null) { + STATE::template AssignValue(target.arg, source.arg); + ; + } target.is_initialized = true; } } @@ -257,7 +295,8 @@ struct VectorArgMinMaxBase : ArgMinMaxBase { if (!state.is_initialized || state.arg_null) { finalize_data.ReturnNull(); } else { - VectorOperations::Copy(*state.arg, finalize_data.result, 1, 0, finalize_data.result_idx); + CreateSortKeyHelpers::DecodeSortKey(state.arg, finalize_data.result, finalize_data.result_idx, + OrderModifiers(ORDER_TYPE, OrderByNullType::NULLS_LAST)); } } @@ -318,9 +357,7 @@ AggregateFunction GetArgMinMaxFunctionInternal(const LogicalType &by_type, const if (type.InternalType() == PhysicalType::VARCHAR || by_type.InternalType() == PhysicalType::VARCHAR) { function.destructor = AggregateFunction::StateDestroy; } - if (by_type.InternalType() == PhysicalType::VARCHAR) { - function.bind = OP::Bind; - } + function.bind = OP::Bind; return function; } @@ -376,6 +413,13 @@ static unique_ptr BindDecimalArgMinMax(ClientContext &context, Agg idx_t best_target = DConstants::INVALID_INDEX; int64_t lowest_cost = NumericLimits::Maximum(); for (idx_t i = 0; i < by_types.size(); ++i) { + // Before falling back to casting, check for a physical type match for the by_type + if (by_types[i].InternalType() == by_type.InternalType()) { + lowest_cost = 0; + best_target = DConstants::INVALID_INDEX; + break; + } + auto cast_cost = CastFunctionSet::Get(context).ImplicitCastCost(by_type, by_types[i]); if (cast_cost < 0) { continue; @@ -402,7 +446,17 @@ void AddDecimalArgMinMaxFunctionBy(AggregateFunctionSet &fun, const LogicalType nullptr, nullptr, nullptr, nullptr, BindDecimalArgMinMax)); } -template +template +void AddGenericArgMinMaxFunction(AggregateFunctionSet &fun) { + using STATE = ArgMinMaxState; + fun.AddFunction( + AggregateFunction({LogicalType::ANY, LogicalType::ANY}, LogicalType::ANY, AggregateFunction::StateSize, + AggregateFunction::StateInitialize, OP::template Update, + AggregateFunction::StateCombine, AggregateFunction::StateVoidFinalize, + nullptr, OP::Bind, AggregateFunction::StateDestroy)); +} + +template static void AddArgMinMaxFunctions(AggregateFunctionSet &fun) { using OP = ArgMinMaxBase; AddArgMinMaxFunctionBy(fun, LogicalType::INTEGER); @@ -419,31 +473,35 @@ static void AddArgMinMaxFunctions(AggregateFunctionSet &fun) { AddDecimalArgMinMaxFunctionBy(fun, by_type); } - using VECTOR_OP = VectorArgMinMaxBase; - AddVectorArgMinMaxFunctionBy(fun, LogicalType::ANY); + using VECTOR_OP = VectorArgMinMaxBase; + AddVectorArgMinMaxFunctionBy(fun, LogicalType::ANY); + + // we always use LessThan when using sort keys because the ORDER_TYPE takes care of selecting the lowest or highest + using GENERIC_VECTOR_OP = VectorArgMinMaxBase>; + AddGenericArgMinMaxFunction(fun); } AggregateFunctionSet ArgMinFun::GetFunctions() { AggregateFunctionSet fun; - AddArgMinMaxFunctions(fun); + AddArgMinMaxFunctions(fun); return fun; } AggregateFunctionSet ArgMaxFun::GetFunctions() { AggregateFunctionSet fun; - AddArgMinMaxFunctions(fun); + AddArgMinMaxFunctions(fun); return fun; } AggregateFunctionSet ArgMinNullFun::GetFunctions() { AggregateFunctionSet fun; - AddArgMinMaxFunctions(fun); + AddArgMinMaxFunctions(fun); return fun; } AggregateFunctionSet ArgMaxNullFun::GetFunctions() { AggregateFunctionSet fun; - AddArgMinMaxFunctions(fun); + AddArgMinMaxFunctions(fun); return fun; } diff --git a/src/core_functions/aggregate/distributive/bitagg.cpp b/src/core_functions/aggregate/distributive/bitagg.cpp index 2d57a4f548c..af3056359ac 100644 --- a/src/core_functions/aggregate/distributive/bitagg.cpp +++ b/src/core_functions/aggregate/distributive/bitagg.cpp @@ -53,10 +53,10 @@ struct BitwiseOperation { template static void Operation(STATE &state, const INPUT_TYPE &input, AggregateUnaryInput &) { if (!state.is_set) { - OP::template Assign(state, input); + OP::template Assign(state, input); state.is_set = true; } else { - OP::template Execute(state, input); + OP::template Execute(state, input); } } @@ -79,10 +79,10 @@ struct BitwiseOperation { } if (!target.is_set) { // target is NULL, use source value directly. - OP::template Assign(target, source.value); + OP::template Assign(target, source.value); target.is_set = true; } else { - OP::template Execute(target, source.value); + OP::template Execute(target, source.value); } } diff --git a/src/core_functions/aggregate/distributive/entropy.cpp b/src/core_functions/aggregate/distributive/entropy.cpp index e66f3078346..426d4498c7c 100644 --- a/src/core_functions/aggregate/distributive/entropy.cpp +++ b/src/core_functions/aggregate/distributive/entropy.cpp @@ -50,11 +50,12 @@ struct EntropyFunctionBase { template static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { - double count = state.count; + double count = static_cast(state.count); if (state.distinct) { double entropy = 0; for (auto &val : *state.distinct) { - entropy += (val.second / count) * log2(count / val.second); + double val_sec = static_cast(val.second); + entropy += (val_sec / count) * log2(count / val_sec); } target = entropy; } else { diff --git a/src/core_functions/aggregate/distributive/functions.json b/src/core_functions/aggregate/distributive/functions.json index 3bdfe3446fb..f128069b25b 100644 --- a/src/core_functions/aggregate/distributive/functions.json +++ b/src/core_functions/aggregate/distributive/functions.json @@ -1,10 +1,10 @@ [ { "name": "approx_count_distinct", - "parameters": "x", + "parameters": "any", "description": "Computes the approximate count of distinct elements using HyperLogLog.", "example": "approx_count_distinct(A)", - "type": "aggregate_function_set" + "type": "aggregate_function" }, { "name": "arg_min", diff --git a/src/core_functions/aggregate/distributive/minmax.cpp b/src/core_functions/aggregate/distributive/minmax.cpp index d3a5dd49c68..14ad523cfac 100644 --- a/src/core_functions/aggregate/distributive/minmax.cpp +++ b/src/core_functions/aggregate/distributive/minmax.cpp @@ -8,6 +8,7 @@ #include "duckdb/planner/expression/bound_comparison_expression.hpp" #include "duckdb/planner/expression_binder.hpp" #include "duckdb/function/function_binder.hpp" +#include "duckdb/core_functions/aggregate/sort_key_helpers.hpp" namespace duckdb { @@ -147,28 +148,47 @@ struct MaxOperation : public NumericMinMaxBase { } }; -struct StringMinMaxBase : public MinMaxBase { - template - static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { - if (state.isset && !state.value.IsInlined()) { - delete[] state.value.GetData(); +struct MinMaxStringState : MinMaxState { + void Destroy() { + if (isset && !value.IsInlined()) { + delete[] value.GetData(); } } - template - static void Assign(STATE &state, INPUT_TYPE input, AggregateInputData &input_data) { - Destroy(state, input_data); + void Assign(string_t input) { if (input.IsInlined()) { - state.value = input; + // inlined string - we can directly store it into the string_t without having to allocate anything + Destroy(); + value = input; } else { - // non-inlined string, need to allocate space for it + // non-inlined string, need to allocate space for it somehow auto len = input.GetSize(); - auto ptr = new char[len]; + char *ptr; + if (!isset || value.GetSize() < len) { + // we cannot fit this into the current slot - destroy it and re-allocate + Destroy(); + ptr = new char[len]; + } else { + // this fits into the current slot - take over the pointer + ptr = value.GetDataWriteable(); + } memcpy(ptr, input.GetData(), len); - state.value = string_t(ptr, UnsafeNumericCast(len)); + value = string_t(ptr, UnsafeNumericCast(len)); } } +}; + +struct StringMinMaxBase : public MinMaxBase { + template + static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { + state.Destroy(); + } + + template + static void Assign(STATE &state, INPUT_TYPE input, AggregateInputData &input_data) { + state.Assign(input); + } template static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { @@ -213,302 +233,57 @@ struct MaxOperationString : public StringMinMaxBase { } }; -template -static bool TemplatedOptimumType(Vector &left, idx_t lidx, idx_t lcount, Vector &right, idx_t ridx, idx_t rcount) { - UnifiedVectorFormat lvdata, rvdata; - left.ToUnifiedFormat(lcount, lvdata); - right.ToUnifiedFormat(rcount, rvdata); - - lidx = lvdata.sel->get_index(lidx); - ridx = rvdata.sel->get_index(ridx); - - auto ldata = UnifiedVectorFormat::GetData(lvdata); - auto rdata = UnifiedVectorFormat::GetData(rvdata); - - auto &lval = ldata[lidx]; - auto &rval = rdata[ridx]; - - auto lnull = !lvdata.validity.RowIsValid(lidx); - auto rnull = !rvdata.validity.RowIsValid(ridx); - - return OP::Operation(lval, rval, lnull, rnull); -} - -template -static bool TemplatedOptimumList(Vector &left, idx_t lidx, idx_t lcount, Vector &right, idx_t ridx, idx_t rcount); - -template -static bool TemplatedOptimumStruct(Vector &left, idx_t lidx, idx_t lcount, Vector &right, idx_t ridx, idx_t rcount); - -template -static bool TemplatedOptimumArray(Vector &left, idx_t lidx, idx_t lcount, Vector &right, idx_t ridx, idx_t rcount); - -template -static bool TemplatedOptimumValue(Vector &left, idx_t lidx, idx_t lcount, Vector &right, idx_t ridx, idx_t rcount) { - D_ASSERT(left.GetType() == right.GetType()); - switch (left.GetType().InternalType()) { - case PhysicalType::BOOL: - case PhysicalType::INT8: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::INT16: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::INT32: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::INT64: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::UINT8: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::UINT16: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::UINT32: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::UINT64: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::INT128: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::UINT128: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::FLOAT: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::DOUBLE: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::INTERVAL: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::VARCHAR: - return TemplatedOptimumType(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::LIST: - return TemplatedOptimumList(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::STRUCT: - return TemplatedOptimumStruct(left, lidx, lcount, right, ridx, rcount); - case PhysicalType::ARRAY: - return TemplatedOptimumArray(left, lidx, lcount, right, ridx, rcount); - default: - throw InternalException("Invalid type for distinct comparison"); - } -} - -template -static bool TemplatedOptimumStruct(Vector &left, idx_t lidx_p, idx_t lcount, Vector &right, idx_t ridx_p, - idx_t rcount) { - // STRUCT dictionaries apply to all the children - // so map the indexes first - UnifiedVectorFormat lvdata, rvdata; - left.ToUnifiedFormat(lcount, lvdata); - right.ToUnifiedFormat(rcount, rvdata); - - idx_t lidx = lvdata.sel->get_index(lidx_p); - idx_t ridx = rvdata.sel->get_index(ridx_p); - - // DISTINCT semantics are in effect for nested types - auto lnull = !lvdata.validity.RowIsValid(lidx); - auto rnull = !rvdata.validity.RowIsValid(ridx); - if (lnull || rnull) { - return OP::Operation(0, 0, lnull, rnull); - } - - auto &lchildren = StructVector::GetEntries(left); - auto &rchildren = StructVector::GetEntries(right); - - D_ASSERT(lchildren.size() == rchildren.size()); - for (idx_t col_no = 0; col_no < lchildren.size(); ++col_no) { - auto &lchild = *lchildren[col_no]; - auto &rchild = *rchildren[col_no]; - - // Strict comparisons use the OP for definite - if (TemplatedOptimumValue(lchild, lidx_p, lcount, rchild, ridx_p, rcount)) { - return true; - } - - if (col_no == lchildren.size() - 1) { - break; - } - - // Strict comparisons use IS NOT DISTINCT for possible - if (!TemplatedOptimumValue(lchild, lidx_p, lcount, rchild, ridx_p, rcount)) { - return false; - } - } - - return false; -} - -template -static bool TemplatedOptimumList(Vector &left, idx_t lidx, idx_t lcount, Vector &right, idx_t ridx, idx_t rcount) { - UnifiedVectorFormat lvdata, rvdata; - left.ToUnifiedFormat(lcount, lvdata); - right.ToUnifiedFormat(rcount, rvdata); - - // Update the indexes and vector sizes for recursion. - lidx = lvdata.sel->get_index(lidx); - ridx = rvdata.sel->get_index(ridx); - - lcount = ListVector::GetListSize(left); - rcount = ListVector::GetListSize(right); - - // DISTINCT semantics are in effect for nested types - auto lnull = !lvdata.validity.RowIsValid(lidx); - auto rnull = !rvdata.validity.RowIsValid(ridx); - if (lnull || rnull) { - return OP::Operation(0, 0, lnull, rnull); - } - - auto &lchild = ListVector::GetEntry(left); - auto &rchild = ListVector::GetEntry(right); - - auto ldata = UnifiedVectorFormat::GetData(lvdata); - auto rdata = UnifiedVectorFormat::GetData(rvdata); - - auto &lval = ldata[lidx]; - auto &rval = rdata[ridx]; - - for (idx_t pos = 0;; ++pos) { - // Tie-breaking uses the OP - if (pos == lval.length || pos == rval.length) { - return OP::Operation(lval.length, rval.length, false, false); - } - - // Strict comparisons use the OP for definite - lidx = lval.offset + pos; - ridx = rval.offset + pos; - if (TemplatedOptimumValue(lchild, lidx, lcount, rchild, ridx, rcount)) { - return true; - } - - // Strict comparisons use IS NOT DISTINCT for possible - if (!TemplatedOptimumValue(lchild, lidx, lcount, rchild, ridx, rcount)) { - return false; - } - } - - return false; -} - -// FIXME: We should try to unify this with TemplatedOptimumList -template -static bool TemplatedOptimumArray(Vector &left, idx_t lidx_p, idx_t lcount, Vector &right, idx_t ridx_p, idx_t rcount) { - // so map the indexes first - UnifiedVectorFormat lvdata, rvdata; - left.ToUnifiedFormat(lcount, lvdata); - right.ToUnifiedFormat(rcount, rvdata); - - idx_t lidx = lvdata.sel->get_index(lidx_p); - idx_t ridx = rvdata.sel->get_index(ridx_p); - - // DISTINCT semantics are in effect for nested types - auto lnull = !lvdata.validity.RowIsValid(lidx); - auto rnull = !rvdata.validity.RowIsValid(ridx); - if (lnull || rnull) { - return OP::Operation(0, 0, lnull, rnull); - } - - auto &lchild = ArrayVector::GetEntry(left); - auto &rchild = ArrayVector::GetEntry(right); - auto left_array_size = ArrayType::GetSize(left.GetType()); - auto right_array_size = ArrayType::GetSize(right.GetType()); - - D_ASSERT(left_array_size == right_array_size); - - auto lchild_count = lcount * left_array_size; - auto rchild_count = rcount * right_array_size; - - for (idx_t elem_idx = 0; elem_idx < left_array_size; elem_idx++) { - auto left_elem_idx = lidx * left_array_size + elem_idx; - auto right_elem_idx = ridx * right_array_size + elem_idx; - - // Strict comparisons use the OP for definite - if (TemplatedOptimumValue(lchild, left_elem_idx, lchild_count, rchild, right_elem_idx, rchild_count)) { - return true; - } - - // Strict comparisons use IS NOT DISTINCT for possible - if (!TemplatedOptimumValue(lchild, left_elem_idx, lchild_count, rchild, right_elem_idx, - rchild_count)) { - return false; - } - } - return false; -} - -struct VectorMinMaxState { - Vector *value; -}; - +template struct VectorMinMaxBase { + static constexpr OrderType ORDER_TYPE = ORDER_TYPE_TEMPLATED; + static bool IgnoreNull() { return true; } template static void Initialize(STATE &state) { - state.value = nullptr; + state.isset = false; } template static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { - if (state.value) { - delete state.value; - } - state.value = nullptr; - } - - template - static void Assign(STATE &state, Vector &input, const idx_t idx) { - if (!state.value) { - state.value = new Vector(input.GetType()); - state.value->SetVectorType(VectorType::CONSTANT_VECTOR); - } - sel_t selv = UnsafeNumericCast(idx); - SelectionVector sel(&selv); - VectorOperations::Copy(input, *state.value, sel, 1, 0, 0); + state.Destroy(); } - template - static void Execute(STATE &state, Vector &input, const idx_t idx, const idx_t count) { - Assign(state, input, idx); + template + static void Assign(STATE &state, INPUT_TYPE input, AggregateInputData &input_data) { + state.Assign(input); } - template - static void Update(Vector inputs[], AggregateInputData &, idx_t input_count, Vector &state_vector, idx_t count) { - auto &input = inputs[0]; - UnifiedVectorFormat idata; - input.ToUnifiedFormat(count, idata); - - UnifiedVectorFormat sdata; - state_vector.ToUnifiedFormat(count, sdata); - - auto states = (STATE **)sdata.data; - for (idx_t i = 0; i < count; i++) { - const auto idx = idata.sel->get_index(i); - if (!idata.validity.RowIsValid(idx)) { - continue; - } - const auto sidx = sdata.sel->get_index(i); - auto &state = *states[sidx]; - if (!state.value) { - Assign(state, input, i); - } else { - OP::template Execute(state, input, i, count); - } + template + static void Execute(STATE &state, INPUT_TYPE input, AggregateInputData &input_data) { + if (!state.isset) { + Assign(state, input, input_data); + state.isset = true; + return; + } + if (LessThan::Operation(input, state.value)) { + Assign(state, input, input_data); } } template - static void Combine(const STATE &source, STATE &target, AggregateInputData &) { - if (!source.value) { + static void Combine(const STATE &source, STATE &target, AggregateInputData &input_data) { + if (!source.isset) { + // source is NULL, nothing to do return; - } else if (!target.value) { - Assign(target, *source.value, 0); - } else { - OP::template Execute(target, *source.value, 0, 1); } + OP::template Execute(target, source.value, input_data); } template static void Finalize(STATE &state, AggregateFinalizeData &finalize_data) { - if (!state.value) { + if (!state.isset) { finalize_data.ReturnNull(); } else { - VectorOperations::Copy(*state.value, finalize_data.result, 1, 0, finalize_data.result_idx); + CreateSortKeyHelpers::DecodeSortKey(state.value, finalize_data.result, finalize_data.result_idx, + OrderModifiers(ORDER_TYPE, OrderByNullType::NULLS_LAST)); } } @@ -520,56 +295,17 @@ struct VectorMinMaxBase { } }; -struct MinOperationVector : public VectorMinMaxBase { - template - static void Execute(STATE &state, Vector &input, const idx_t idx, const idx_t count) { - if (TemplatedOptimumValue(input, idx, count, *state.value, 0, 1)) { - Assign(state, input, idx); - } - } -}; - -struct MaxOperationVector : public VectorMinMaxBase { - template - static void Execute(STATE &state, Vector &input, const idx_t idx, const idx_t count) { - if (TemplatedOptimumValue(input, idx, count, *state.value, 0, 1)) { - Assign(state, input, idx); - } - } -}; +struct MinOperationVector : VectorMinMaxBase {}; -template -unique_ptr BindDecimalMinMax(ClientContext &context, AggregateFunction &function, - vector> &arguments) { - auto decimal_type = arguments[0]->return_type; - auto name = function.name; - switch (decimal_type.InternalType()) { - case PhysicalType::INT16: - function = GetUnaryAggregate(LogicalType::SMALLINT); - break; - case PhysicalType::INT32: - function = GetUnaryAggregate(LogicalType::INTEGER); - break; - case PhysicalType::INT64: - function = GetUnaryAggregate(LogicalType::BIGINT); - break; - default: - function = GetUnaryAggregate(LogicalType::HUGEINT); - break; - } - function.name = std::move(name); - function.arguments[0] = decimal_type; - function.return_type = decimal_type; - function.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - return nullptr; -} +struct MaxOperationVector : VectorMinMaxBase {}; template static AggregateFunction GetMinMaxFunction(const LogicalType &type) { return AggregateFunction( - {type}, type, AggregateFunction::StateSize, AggregateFunction::StateInitialize, - OP::template Update, AggregateFunction::StateCombine, - AggregateFunction::StateVoidFinalize, nullptr, OP::Bind, AggregateFunction::StateDestroy); + {type}, LogicalType::BLOB, AggregateFunction::StateSize, AggregateFunction::StateInitialize, + AggregateSortKeyHelpers::UnaryUpdate, + AggregateFunction::StateCombine, AggregateFunction::StateVoidFinalize, nullptr, OP::Bind, + AggregateFunction::StateDestroy); } template @@ -577,12 +313,12 @@ static AggregateFunction GetMinMaxOperator(const LogicalType &type) { auto internal_type = type.InternalType(); switch (internal_type) { case PhysicalType::VARCHAR: - return AggregateFunction::UnaryAggregateDestructor, string_t, string_t, OP_STRING>( - type.id(), type.id()); + return AggregateFunction::UnaryAggregateDestructor(type.id(), + type.id()); case PhysicalType::LIST: case PhysicalType::STRUCT: case PhysicalType::ARRAY: - return GetMinMaxFunction(type); + return GetMinMaxFunction(type); default: return GetUnaryAggregate(type); } @@ -591,7 +327,6 @@ static AggregateFunction GetMinMaxOperator(const LogicalType &type) { template unique_ptr BindMinMax(ClientContext &context, AggregateFunction &function, vector> &arguments) { - if (arguments[0]->return_type.id() == LogicalTypeId::VARCHAR) { auto str_collation = StringType::GetCollation(arguments[0]->return_type); if (!str_collation.empty()) { @@ -616,7 +351,7 @@ unique_ptr BindMinMax(ClientContext &context, AggregateFunction &f // Create a copied child and PushCollation for it. arguments.push_back(arguments[0]->Copy()); - ExpressionBinder::PushCollation(context, arguments[1], arguments[0]->return_type, false); + ExpressionBinder::PushCollation(context, arguments[1], arguments[0]->return_type); // Bind function like arg_min/arg_max. function.arguments[0] = arguments[0]->return_type; @@ -626,6 +361,9 @@ unique_ptr BindMinMax(ClientContext &context, AggregateFunction &f } auto input_type = arguments[0]->return_type; + if (input_type.id() == LogicalTypeId::UNKNOWN) { + throw ParameterNotResolvedException(); + } auto name = std::move(function.name); function = GetMinMaxOperator(input_type); function.name = std::move(name); @@ -639,8 +377,6 @@ unique_ptr BindMinMax(ClientContext &context, AggregateFunction &f template static void AddMinMaxOperator(AggregateFunctionSet &set) { - set.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, BindDecimalMinMax)); set.AddFunction(AggregateFunction({LogicalType::ANY}, LogicalType::ANY, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, BindMinMax)); } diff --git a/src/core_functions/aggregate/holistic/CMakeLists.txt b/src/core_functions/aggregate/holistic/CMakeLists.txt index ee932373072..943789ab5bc 100644 --- a/src/core_functions/aggregate/holistic/CMakeLists.txt +++ b/src/core_functions/aggregate/holistic/CMakeLists.txt @@ -1,5 +1,11 @@ -add_library_unity(duckdb_aggr_holistic OBJECT quantile.cpp mode.cpp - approximate_quantile.cpp reservoir_quantile.cpp) +add_library_unity( + duckdb_aggr_holistic + OBJECT + quantile.cpp + mad.cpp + mode.cpp + approximate_quantile.cpp + reservoir_quantile.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/core_functions/aggregate/holistic/approximate_quantile.cpp b/src/core_functions/aggregate/holistic/approximate_quantile.cpp index 338a0647d0f..5b6abcd203c 100644 --- a/src/core_functions/aggregate/holistic/approximate_quantile.cpp +++ b/src/core_functions/aggregate/holistic/approximate_quantile.cpp @@ -133,33 +133,56 @@ struct ApproxQuantileScalarOperation : public ApproxQuantileOperation { } }; -AggregateFunction GetApproximateQuantileAggregateFunction(PhysicalType type) { - switch (type) { +static AggregateFunction GetApproximateQuantileAggregateFunction(const LogicalType &type) { + // Not binary comparable + if (type == LogicalType::TIME_TZ) { + return AggregateFunction::UnaryAggregateDestructor(type, type); + } + switch (type.InternalType()) { + case PhysicalType::INT8: + return AggregateFunction::UnaryAggregateDestructor(type, type); case PhysicalType::INT16: return AggregateFunction::UnaryAggregateDestructor(LogicalType::SMALLINT, - LogicalType::SMALLINT); + ApproxQuantileScalarOperation>(type, type); case PhysicalType::INT32: return AggregateFunction::UnaryAggregateDestructor(LogicalType::INTEGER, - LogicalType::INTEGER); + ApproxQuantileScalarOperation>(type, type); case PhysicalType::INT64: return AggregateFunction::UnaryAggregateDestructor(LogicalType::BIGINT, - LogicalType::BIGINT); + ApproxQuantileScalarOperation>(type, type); case PhysicalType::INT128: return AggregateFunction::UnaryAggregateDestructor(LogicalType::HUGEINT, - LogicalType::HUGEINT); + ApproxQuantileScalarOperation>(type, type); + case PhysicalType::FLOAT: + return AggregateFunction::UnaryAggregateDestructor(type, type); case PhysicalType::DOUBLE: return AggregateFunction::UnaryAggregateDestructor(LogicalType::DOUBLE, - LogicalType::DOUBLE); + ApproxQuantileScalarOperation>(type, type); default: throw InternalException("Unimplemented quantile aggregate"); } } +static AggregateFunction GetApproximateQuantileDecimalAggregateFunction(const LogicalType &type) { + switch (type.InternalType()) { + case PhysicalType::INT8: + return GetApproximateQuantileAggregateFunction(LogicalType::TINYINT); + case PhysicalType::INT16: + return GetApproximateQuantileAggregateFunction(LogicalType::SMALLINT); + case PhysicalType::INT32: + return GetApproximateQuantileAggregateFunction(LogicalType::INTEGER); + case PhysicalType::INT64: + return GetApproximateQuantileAggregateFunction(LogicalType::BIGINT); + case PhysicalType::INT128: + return GetApproximateQuantileAggregateFunction(LogicalType::HUGEINT); + default: + throw InternalException("Unimplemented quantile decimal aggregate"); + } +} + static float CheckApproxQuantile(const Value &quantile_val) { if (quantile_val.IsNull()) { throw BinderException("APPROXIMATE QUANTILE parameter cannot be NULL"); @@ -181,14 +204,25 @@ unique_ptr BindApproxQuantile(ClientContext &context, AggregateFun throw BinderException("APPROXIMATE QUANTILE can only take constant quantile parameters"); } Value quantile_val = ExpressionExecutor::EvaluateScalar(context, *arguments[1]); + if (quantile_val.IsNull()) { + throw BinderException("APPROXIMATE QUANTILE parameter list cannot be NULL"); + } vector quantiles; - if (quantile_val.type().id() != LogicalTypeId::LIST) { - quantiles.push_back(CheckApproxQuantile(quantile_val)); - } else { + switch (quantile_val.type().id()) { + case LogicalTypeId::LIST: for (const auto &element_val : ListValue::GetChildren(quantile_val)) { quantiles.push_back(CheckApproxQuantile(element_val)); } + break; + case LogicalTypeId::ARRAY: + for (const auto &element_val : ArrayValue::GetChildren(quantile_val)) { + quantiles.push_back(CheckApproxQuantile(element_val)); + } + break; + default: + quantiles.push_back(CheckApproxQuantile(quantile_val)); + break; } // remove the quantile argument so we can use the unary aggregate @@ -199,14 +233,14 @@ unique_ptr BindApproxQuantile(ClientContext &context, AggregateFun unique_ptr BindApproxQuantileDecimal(ClientContext &context, AggregateFunction &function, vector> &arguments) { auto bind_data = BindApproxQuantile(context, function, arguments); - function = GetApproximateQuantileAggregateFunction(arguments[0]->return_type.InternalType()); + function = GetApproximateQuantileDecimalAggregateFunction(arguments[0]->return_type); function.name = "approx_quantile"; function.serialize = ApproximateQuantileBindData::Serialize; function.deserialize = ApproximateQuantileBindData::Deserialize; return bind_data; } -AggregateFunction GetApproximateQuantileAggregate(PhysicalType type) { +AggregateFunction GetApproximateQuantileAggregate(const LogicalType &type) { auto fun = GetApproximateQuantileAggregateFunction(type); fun.bind = BindApproxQuantile; fun.serialize = ApproximateQuantileBindData::Serialize; @@ -276,9 +310,16 @@ AggregateFunction GetApproxQuantileListAggregateFunction(const LogicalType &type case LogicalTypeId::SMALLINT: return GetTypedApproxQuantileListAggregateFunction(type); case LogicalTypeId::INTEGER: + case LogicalTypeId::DATE: + case LogicalTypeId::TIME: return GetTypedApproxQuantileListAggregateFunction(type); case LogicalTypeId::BIGINT: + case LogicalTypeId::TIMESTAMP: + case LogicalTypeId::TIMESTAMP_TZ: return GetTypedApproxQuantileListAggregateFunction(type); + case LogicalTypeId::TIME_TZ: + // Not binary comparable + return GetTypedApproxQuantileListAggregateFunction(type); case LogicalTypeId::HUGEINT: return GetTypedApproxQuantileListAggregateFunction(type); case LogicalTypeId::FLOAT: @@ -296,10 +337,9 @@ AggregateFunction GetApproxQuantileListAggregateFunction(const LogicalType &type case PhysicalType::INT128: return GetTypedApproxQuantileListAggregateFunction(type); default: - throw NotImplementedException("Unimplemented approximate quantile list aggregate"); + throw NotImplementedException("Unimplemented approximate quantile list decimal aggregate"); } default: - // TODO: Add quantitative temporal types throw NotImplementedException("Unimplemented approximate quantile list aggregate"); } } @@ -331,11 +371,17 @@ AggregateFunctionSet ApproxQuantileFun::GetFunctions() { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, BindApproxQuantileDecimal)); - approx_quantile.AddFunction(GetApproximateQuantileAggregate(PhysicalType::INT16)); - approx_quantile.AddFunction(GetApproximateQuantileAggregate(PhysicalType::INT32)); - approx_quantile.AddFunction(GetApproximateQuantileAggregate(PhysicalType::INT64)); - approx_quantile.AddFunction(GetApproximateQuantileAggregate(PhysicalType::INT128)); - approx_quantile.AddFunction(GetApproximateQuantileAggregate(PhysicalType::DOUBLE)); + approx_quantile.AddFunction(GetApproximateQuantileAggregate(LogicalType::SMALLINT)); + approx_quantile.AddFunction(GetApproximateQuantileAggregate(LogicalType::INTEGER)); + approx_quantile.AddFunction(GetApproximateQuantileAggregate(LogicalType::BIGINT)); + approx_quantile.AddFunction(GetApproximateQuantileAggregate(LogicalType::HUGEINT)); + approx_quantile.AddFunction(GetApproximateQuantileAggregate(LogicalType::DOUBLE)); + + approx_quantile.AddFunction(GetApproximateQuantileAggregate(LogicalType::DATE)); + approx_quantile.AddFunction(GetApproximateQuantileAggregate(LogicalType::TIME)); + approx_quantile.AddFunction(GetApproximateQuantileAggregate(LogicalType::TIME_TZ)); + approx_quantile.AddFunction(GetApproximateQuantileAggregate(LogicalType::TIMESTAMP)); + approx_quantile.AddFunction(GetApproximateQuantileAggregate(LogicalType::TIMESTAMP_TZ)); // List variants approx_quantile.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::FLOAT)}, @@ -349,6 +395,13 @@ AggregateFunctionSet ApproxQuantileFun::GetFunctions() { approx_quantile.AddFunction(GetApproxQuantileListAggregate(LogicalTypeId::HUGEINT)); approx_quantile.AddFunction(GetApproxQuantileListAggregate(LogicalTypeId::FLOAT)); approx_quantile.AddFunction(GetApproxQuantileListAggregate(LogicalTypeId::DOUBLE)); + + approx_quantile.AddFunction(GetApproxQuantileListAggregate(LogicalType::DATE)); + approx_quantile.AddFunction(GetApproxQuantileListAggregate(LogicalType::TIME)); + approx_quantile.AddFunction(GetApproxQuantileListAggregate(LogicalType::TIME_TZ)); + approx_quantile.AddFunction(GetApproxQuantileListAggregate(LogicalType::TIMESTAMP)); + approx_quantile.AddFunction(GetApproxQuantileListAggregate(LogicalType::TIMESTAMP_TZ)); + return approx_quantile; } diff --git a/src/core_functions/aggregate/holistic/mad.cpp b/src/core_functions/aggregate/holistic/mad.cpp new file mode 100644 index 00000000000..8be7415fff0 --- /dev/null +++ b/src/core_functions/aggregate/holistic/mad.cpp @@ -0,0 +1,330 @@ +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/core_functions/aggregate/holistic_functions.hpp" +#include "duckdb/planner/expression.hpp" +#include "duckdb/common/operator/cast_operators.hpp" +#include "duckdb/common/operator/abs.hpp" +#include "duckdb/core_functions/aggregate/quantile_state.hpp" + +namespace duckdb { + +struct FrameSet { + inline explicit FrameSet(const SubFrames &frames_p) : frames(frames_p) { + } + + inline idx_t Size() const { + idx_t result = 0; + for (const auto &frame : frames) { + result += frame.end - frame.start; + } + + return result; + } + + inline bool Contains(idx_t i) const { + for (idx_t f = 0; f < frames.size(); ++f) { + const auto &frame = frames[f]; + if (frame.start <= i && i < frame.end) { + return true; + } + } + return false; + } + const SubFrames &frames; +}; + +struct QuantileReuseUpdater { + idx_t *index; + idx_t j; + + inline QuantileReuseUpdater(idx_t *index, idx_t j) : index(index), j(j) { + } + + inline void Neither(idx_t begin, idx_t end) { + } + + inline void Left(idx_t begin, idx_t end) { + } + + inline void Right(idx_t begin, idx_t end) { + for (; begin < end; ++begin) { + index[j++] = begin; + } + } + + inline void Both(idx_t begin, idx_t end) { + } +}; + +void ReuseIndexes(idx_t *index, const SubFrames &currs, const SubFrames &prevs) { + + // Copy overlapping indices by scanning the previous set and copying down into holes. + // We copy instead of leaving gaps in case there are fewer values in the current frame. + FrameSet prev_set(prevs); + FrameSet curr_set(currs); + const auto prev_count = prev_set.Size(); + idx_t j = 0; + for (idx_t p = 0; p < prev_count; ++p) { + auto idx = index[p]; + + // Shift down into any hole + if (j != p) { + index[j] = idx; + } + + // Skip overlapping values + if (curr_set.Contains(idx)) { + ++j; + } + } + + // Insert new indices + if (j > 0) { + QuantileReuseUpdater updater(index, j); + AggregateExecutor::IntersectFrames(prevs, currs, updater); + } else { + // No overlap: overwrite with new values + for (const auto &curr : currs) { + for (auto idx = curr.start; idx < curr.end; ++idx) { + index[j++] = idx; + } + } + } +} + +//===--------------------------------------------------------------------===// +// Median Absolute Deviation +//===--------------------------------------------------------------------===// +template +struct MadAccessor { + using INPUT_TYPE = T; + using RESULT_TYPE = R; + const MEDIAN_TYPE &median; + explicit MadAccessor(const MEDIAN_TYPE &median_p) : median(median_p) { + } + + inline RESULT_TYPE operator()(const INPUT_TYPE &input) const { + const RESULT_TYPE delta = input - UnsafeNumericCast(median); + return TryAbsOperator::Operation(delta); + } +}; + +// hugeint_t - double => undefined +template <> +struct MadAccessor { + using INPUT_TYPE = hugeint_t; + using RESULT_TYPE = double; + using MEDIAN_TYPE = double; + const MEDIAN_TYPE &median; + explicit MadAccessor(const MEDIAN_TYPE &median_p) : median(median_p) { + } + inline RESULT_TYPE operator()(const INPUT_TYPE &input) const { + const auto delta = Hugeint::Cast(input) - median; + return TryAbsOperator::Operation(delta); + } +}; + +// date_t - timestamp_t => interval_t +template <> +struct MadAccessor { + using INPUT_TYPE = date_t; + using RESULT_TYPE = interval_t; + using MEDIAN_TYPE = timestamp_t; + const MEDIAN_TYPE &median; + explicit MadAccessor(const MEDIAN_TYPE &median_p) : median(median_p) { + } + inline RESULT_TYPE operator()(const INPUT_TYPE &input) const { + const auto dt = Cast::Operation(input); + const auto delta = dt - median; + return Interval::FromMicro(TryAbsOperator::Operation(delta)); + } +}; + +// timestamp_t - timestamp_t => int64_t +template <> +struct MadAccessor { + using INPUT_TYPE = timestamp_t; + using RESULT_TYPE = interval_t; + using MEDIAN_TYPE = timestamp_t; + const MEDIAN_TYPE &median; + explicit MadAccessor(const MEDIAN_TYPE &median_p) : median(median_p) { + } + inline RESULT_TYPE operator()(const INPUT_TYPE &input) const { + const auto delta = input - median; + return Interval::FromMicro(TryAbsOperator::Operation(delta)); + } +}; + +// dtime_t - dtime_t => int64_t +template <> +struct MadAccessor { + using INPUT_TYPE = dtime_t; + using RESULT_TYPE = interval_t; + using MEDIAN_TYPE = dtime_t; + const MEDIAN_TYPE &median; + explicit MadAccessor(const MEDIAN_TYPE &median_p) : median(median_p) { + } + inline RESULT_TYPE operator()(const INPUT_TYPE &input) const { + const auto delta = input - median; + return Interval::FromMicro(TryAbsOperator::Operation(delta)); + } +}; + +template +struct MedianAbsoluteDeviationOperation : QuantileOperation { + template + static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { + if (state.v.empty()) { + finalize_data.ReturnNull(); + return; + } + using INPUT_TYPE = typename STATE::InputType; + D_ASSERT(finalize_data.input.bind_data); + auto &bind_data = finalize_data.input.bind_data->Cast(); + D_ASSERT(bind_data.quantiles.size() == 1); + const auto &q = bind_data.quantiles[0]; + Interpolator interp(q, state.v.size(), false); + const auto med = interp.template Operation(state.v.data(), finalize_data.result); + + MadAccessor accessor(med); + target = interp.template Operation(state.v.data(), finalize_data.result, accessor); + } + + template + static void Window(const INPUT_TYPE *data, const ValidityMask &fmask, const ValidityMask &dmask, + AggregateInputData &aggr_input_data, STATE &state, const SubFrames &frames, Vector &result, + idx_t ridx, const STATE *gstate) { + auto rdata = FlatVector::GetData(result); + + QuantileIncluded included(fmask, dmask); + const auto n = FrameSize(included, frames); + + if (!n) { + auto &rmask = FlatVector::Validity(result); + rmask.Set(ridx, false); + return; + } + + // Compute the median + D_ASSERT(aggr_input_data.bind_data); + auto &bind_data = aggr_input_data.bind_data->Cast(); + + D_ASSERT(bind_data.quantiles.size() == 1); + const auto &quantile = bind_data.quantiles[0]; + auto &window_state = state.GetOrCreateWindowState(); + MEDIAN_TYPE med; + if (gstate && gstate->HasTrees()) { + med = gstate->GetWindowState().template WindowScalar(data, frames, n, result, quantile); + } else { + window_state.UpdateSkip(data, frames, included); + med = window_state.template WindowScalar(data, frames, n, result, quantile); + } + + // Lazily initialise frame state + window_state.SetCount(frames.back().end - frames.front().start); + auto index2 = window_state.m.data(); + D_ASSERT(index2); + + // The replacement trick does not work on the second index because if + // the median has changed, the previous order is not correct. + // It is probably close, however, and so reuse is helpful. + auto &prevs = window_state.prevs; + ReuseIndexes(index2, frames, prevs); + std::partition(index2, index2 + window_state.count, included); + + Interpolator interp(quantile, n, false); + + // Compute mad from the second index + using ID = QuantileIndirect; + ID indirect(data); + + using MAD = MadAccessor; + MAD mad(med); + + using MadIndirect = QuantileComposed; + MadIndirect mad_indirect(mad, indirect); + rdata[ridx] = interp.template Operation(index2, result, mad_indirect); + + // Prev is used by both skip lists and increments + prevs = frames; + } +}; + +unique_ptr BindMAD(ClientContext &context, AggregateFunction &function, + vector> &arguments) { + return make_uniq(Value::DECIMAL(int16_t(5), 2, 1)); +} + +template +AggregateFunction GetTypedMedianAbsoluteDeviationAggregateFunction(const LogicalType &input_type, + const LogicalType &target_type) { + using STATE = QuantileState; + using OP = MedianAbsoluteDeviationOperation; + auto fun = AggregateFunction::UnaryAggregateDestructor(input_type, target_type); + fun.bind = BindMAD; + fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; + fun.window = AggregateFunction::UnaryWindow; + fun.window_init = OP::template WindowInit; + return fun; +} + +AggregateFunction GetMedianAbsoluteDeviationAggregateFunction(const LogicalType &type) { + switch (type.id()) { + case LogicalTypeId::FLOAT: + return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + case LogicalTypeId::DOUBLE: + return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + case LogicalTypeId::DECIMAL: + switch (type.InternalType()) { + case PhysicalType::INT16: + return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + case PhysicalType::INT32: + return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + case PhysicalType::INT64: + return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + case PhysicalType::INT128: + return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + default: + throw NotImplementedException("Unimplemented Median Absolute Deviation DECIMAL aggregate"); + } + break; + + case LogicalTypeId::DATE: + return GetTypedMedianAbsoluteDeviationAggregateFunction(type, + LogicalType::INTERVAL); + case LogicalTypeId::TIMESTAMP: + case LogicalTypeId::TIMESTAMP_TZ: + return GetTypedMedianAbsoluteDeviationAggregateFunction( + type, LogicalType::INTERVAL); + case LogicalTypeId::TIME: + case LogicalTypeId::TIME_TZ: + return GetTypedMedianAbsoluteDeviationAggregateFunction(type, + LogicalType::INTERVAL); + + default: + throw NotImplementedException("Unimplemented Median Absolute Deviation aggregate"); + } +} + +unique_ptr BindMedianAbsoluteDeviationDecimal(ClientContext &context, AggregateFunction &function, + vector> &arguments) { + function = GetMedianAbsoluteDeviationAggregateFunction(arguments[0]->return_type); + function.name = "mad"; + function.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; + return BindMAD(context, function, arguments); +} + +AggregateFunctionSet MadFun::GetFunctions() { + AggregateFunctionSet mad("mad"); + mad.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, BindMedianAbsoluteDeviationDecimal)); + + const vector MAD_TYPES = {LogicalType::FLOAT, LogicalType::DOUBLE, LogicalType::DATE, + LogicalType::TIMESTAMP, LogicalType::TIME, LogicalType::TIMESTAMP_TZ, + LogicalType::TIME_TZ}; + for (const auto &type : MAD_TYPES) { + mad.AddFunction(GetMedianAbsoluteDeviationAggregateFunction(type)); + } + return mad; +} + +} // namespace duckdb diff --git a/src/core_functions/aggregate/holistic/mode.cpp b/src/core_functions/aggregate/holistic/mode.cpp index f33ccc415e9..a8d0dbf1eac 100644 --- a/src/core_functions/aggregate/holistic/mode.cpp +++ b/src/core_functions/aggregate/holistic/mode.cpp @@ -1,7 +1,3 @@ -// MODE( ) -// Returns the most frequent value for the values within expr1. -// NULL values are ignored. If all the values are NULL, or there are 0 rows, then the function returns NULL. - #include "duckdb/common/exception.hpp" #include "duckdb/common/uhugeint.hpp" #include "duckdb/common/vector_operations/vector_operations.hpp" @@ -9,9 +5,15 @@ #include "duckdb/core_functions/aggregate/holistic_functions.hpp" #include "duckdb/planner/expression/bound_aggregate_expression.hpp" #include "duckdb/common/unordered_map.hpp" - +#include "duckdb/common/owning_string_map.hpp" +#include "duckdb/core_functions/create_sort_key.hpp" +#include "duckdb/core_functions/aggregate/sort_key_helpers.hpp" #include +// MODE( ) +// Returns the most frequent value for the values within expr1. +// NULL values are ignored. If all the values are NULL, or there are 0 rows, then the function returns NULL. + namespace std { template <> @@ -42,15 +44,49 @@ struct hash { namespace duckdb { -template +struct ModeAttr { + ModeAttr() : count(0), first_row(std::numeric_limits::max()) { + } + size_t count; + idx_t first_row; +}; + +template +struct ModeStandard { + using MAP_TYPE = unordered_map; + + static MAP_TYPE *CreateEmpty(ArenaAllocator &) { + return new MAP_TYPE(); + } + static MAP_TYPE *CreateEmpty(Allocator &) { + return new MAP_TYPE(); + } + + template + static RESULT_TYPE Assign(Vector &result, INPUT_TYPE input) { + return RESULT_TYPE(input); + } +}; + +struct ModeString { + using MAP_TYPE = OwningStringMap; + + static MAP_TYPE *CreateEmpty(ArenaAllocator &allocator) { + return new MAP_TYPE(allocator); + } + static MAP_TYPE *CreateEmpty(Allocator &allocator) { + return new MAP_TYPE(allocator); + } + + template + static RESULT_TYPE Assign(Vector &result, INPUT_TYPE input) { + return StringVector::AddStringOrBlob(result, input); + } +}; + +template struct ModeState { - struct ModeAttr { - ModeAttr() : count(0), first_row(std::numeric_limits::max()) { - } - size_t count; - idx_t first_row; - }; - using Counts = unordered_map; + using Counts = typename TYPE_OP::MAP_TYPE; ModeState() { } @@ -72,8 +108,9 @@ struct ModeState { } void Reset() { - Counts empty; - frequency_map->swap(empty); + if (frequency_map) { + frequency_map->clear(); + } nonzero = 0; count = 0; valid = false; @@ -137,37 +174,27 @@ struct ModeIncluded { const ValidityMask &dmask; }; -struct ModeAssignmentStandard { - template - static RESULT_TYPE Assign(Vector &result, INPUT_TYPE input) { - return RESULT_TYPE(input); - } -}; - -struct ModeAssignmentString { - template - static RESULT_TYPE Assign(Vector &result, INPUT_TYPE input) { - return StringVector::AddString(result, input); - } -}; - -template -struct ModeFunction { +template +struct BaseModeFunction { template static void Initialize(STATE &state) { new (&state) STATE(); } template - static void Operation(STATE &state, const INPUT_TYPE &input, AggregateUnaryInput &) { + static void Execute(STATE &state, const INPUT_TYPE &key, AggregateInputData &input_data) { if (!state.frequency_map) { - state.frequency_map = new typename STATE::Counts(); + state.frequency_map = TYPE_OP::CreateEmpty(input_data.allocator); } - auto key = KEY_TYPE(input); auto &i = (*state.frequency_map)[key]; - i.count++; + ++i.count; i.first_row = MinValue(i.first_row, state.count); - state.count++; + ++state.count; + } + + template + static void Operation(STATE &state, const INPUT_TYPE &key, AggregateUnaryInput &aggr_input) { + Execute(state, key, aggr_input.input); } template @@ -188,6 +215,18 @@ struct ModeFunction { target.count += source.count; } + static bool IgnoreNull() { + return true; + } + + template + static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { + state.~STATE(); + } +}; + +template +struct ModeFunction : BaseModeFunction { template static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { if (!state.frequency_map) { @@ -196,17 +235,17 @@ struct ModeFunction { } auto highest_frequency = state.Scan(); if (highest_frequency != state.frequency_map->end()) { - target = ASSIGN_OP::template Assign(finalize_data.result, highest_frequency->first); + target = TYPE_OP::template Assign(finalize_data.result, highest_frequency->first); } else { finalize_data.ReturnNull(); } } + template - static void ConstantOperation(STATE &state, const INPUT_TYPE &input, AggregateUnaryInput &, idx_t count) { + static void ConstantOperation(STATE &state, const INPUT_TYPE &key, AggregateUnaryInput &aggr_input, idx_t count) { if (!state.frequency_map) { - state.frequency_map = new typename STATE::Counts(); + state.frequency_map = TYPE_OP::CreateEmpty(aggr_input.input.allocator); } - auto key = KEY_TYPE(input); auto &i = (*state.frequency_map)[key]; i.count += count; i.first_row = MinValue(i.first_row, state.count); @@ -229,7 +268,7 @@ struct ModeFunction { inline void Left(idx_t begin, idx_t end) { for (; begin < end; ++begin) { if (included(begin)) { - state.ModeRm(KEY_TYPE(data[begin]), begin); + state.ModeRm(data[begin], begin); } } } @@ -237,7 +276,7 @@ struct ModeFunction { inline void Right(idx_t begin, idx_t end) { for (; begin < end; ++begin) { if (included(begin)) { - state.ModeAdd(KEY_TYPE(data[begin]), begin); + state.ModeAdd(data[begin], begin); } } } @@ -260,17 +299,17 @@ struct ModeFunction { ModeIncluded included(fmask, dmask); if (!state.frequency_map) { - state.frequency_map = new typename STATE::Counts; + state.frequency_map = TYPE_OP::CreateEmpty(Allocator::DefaultAllocator()); } - const double tau = .25; - if (state.nonzero <= tau * state.frequency_map->size() || prevs.back().end <= frames.front().start || + const size_t tau_inverse = 4; // tau==0.25 + if (state.nonzero <= (state.frequency_map->size() / tau_inverse) || prevs.back().end <= frames.front().start || frames.back().end <= prevs.front().start) { state.Reset(); // for f ∈ F do for (const auto &frame : frames) { for (auto i = frame.start; i < frame.end; ++i) { if (included(i)) { - state.ModeAdd(KEY_TYPE(data[i]), i); + state.ModeAdd(data[i], i); } } } @@ -291,100 +330,100 @@ struct ModeFunction { } if (state.valid) { - rdata[rid] = ASSIGN_OP::template Assign(result, *state.mode); + rdata[rid] = TYPE_OP::template Assign(result, *state.mode); } else { rmask.Set(rid, false); } prevs = frames; } +}; - static bool IgnoreNull() { - return true; - } - +template +struct ModeFallbackFunction : BaseModeFunction { template - static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { - state.~STATE(); + static void Finalize(STATE &state, AggregateFinalizeData &finalize_data) { + if (!state.frequency_map) { + finalize_data.ReturnNull(); + return; + } + auto highest_frequency = state.Scan(); + if (highest_frequency != state.frequency_map->end()) { + CreateSortKeyHelpers::DecodeSortKey(highest_frequency->first, finalize_data.result, + finalize_data.result_idx, + OrderModifiers(OrderType::ASCENDING, OrderByNullType::NULLS_LAST)); + } else { + finalize_data.ReturnNull(); + } } }; -template +template > AggregateFunction GetTypedModeFunction(const LogicalType &type) { - using STATE = ModeState; - using OP = ModeFunction; - auto return_type = type.id() == LogicalTypeId::ANY ? LogicalType::VARCHAR : type; - auto func = AggregateFunction::UnaryAggregateDestructor(type, return_type); + using STATE = ModeState; + using OP = ModeFunction; + auto func = AggregateFunction::UnaryAggregateDestructor(type, type); func.window = AggregateFunction::UnaryWindow; return func; } +AggregateFunction GetFallbackModeFunction(const LogicalType &type) { + using STATE = ModeState; + using OP = ModeFallbackFunction; + AggregateFunction aggr({type}, type, AggregateFunction::StateSize, + AggregateFunction::StateInitialize, + AggregateSortKeyHelpers::UnaryUpdate, AggregateFunction::StateCombine, + AggregateFunction::StateVoidFinalize, nullptr); + aggr.destructor = AggregateFunction::StateDestroy; + return aggr; +} + AggregateFunction GetModeAggregate(const LogicalType &type) { switch (type.InternalType()) { case PhysicalType::INT8: - return GetTypedModeFunction(type); + return GetTypedModeFunction(type); case PhysicalType::UINT8: - return GetTypedModeFunction(type); + return GetTypedModeFunction(type); case PhysicalType::INT16: - return GetTypedModeFunction(type); + return GetTypedModeFunction(type); case PhysicalType::UINT16: - return GetTypedModeFunction(type); + return GetTypedModeFunction(type); case PhysicalType::INT32: - return GetTypedModeFunction(type); + return GetTypedModeFunction(type); case PhysicalType::UINT32: - return GetTypedModeFunction(type); + return GetTypedModeFunction(type); case PhysicalType::INT64: - return GetTypedModeFunction(type); + return GetTypedModeFunction(type); case PhysicalType::UINT64: - return GetTypedModeFunction(type); + return GetTypedModeFunction(type); case PhysicalType::INT128: - return GetTypedModeFunction(type); + return GetTypedModeFunction(type); case PhysicalType::UINT128: - return GetTypedModeFunction(type); - + return GetTypedModeFunction(type); case PhysicalType::FLOAT: - return GetTypedModeFunction(type); + return GetTypedModeFunction(type); case PhysicalType::DOUBLE: - return GetTypedModeFunction(type); - + return GetTypedModeFunction(type); case PhysicalType::INTERVAL: - return GetTypedModeFunction(type); - + return GetTypedModeFunction(type); case PhysicalType::VARCHAR: - return GetTypedModeFunction( - LogicalType::ANY_PARAMS(LogicalType::VARCHAR, 150)); - + return GetTypedModeFunction(type); default: - throw NotImplementedException("Unimplemented mode aggregate"); + return GetFallbackModeFunction(type); } } -unique_ptr BindModeDecimal(ClientContext &context, AggregateFunction &function, - vector> &arguments) { +unique_ptr BindModeAggregate(ClientContext &context, AggregateFunction &function, + vector> &arguments) { function = GetModeAggregate(arguments[0]->return_type); function.name = "mode"; return nullptr; } AggregateFunctionSet ModeFun::GetFunctions() { - const vector TEMPORAL = {LogicalType::DATE, LogicalType::TIMESTAMP, LogicalType::TIME, - LogicalType::TIMESTAMP_TZ, LogicalType::TIME_TZ, LogicalType::INTERVAL}; - AggregateFunctionSet mode; - mode.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, BindModeDecimal)); - - for (const auto &type : LogicalType::Numeric()) { - if (type.id() != LogicalTypeId::DECIMAL) { - mode.AddFunction(GetModeAggregate(type)); - } - } - - for (const auto &type : TEMPORAL) { - mode.AddFunction(GetModeAggregate(type)); - } - - mode.AddFunction(GetModeAggregate(LogicalType::VARCHAR)); + mode.AddFunction(AggregateFunction({LogicalTypeId::ANY}, LogicalTypeId::ANY, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, BindModeAggregate)); return mode; } } // namespace duckdb diff --git a/src/core_functions/aggregate/holistic/quantile.cpp b/src/core_functions/aggregate/holistic/quantile.cpp index 84446a6cee4..d25b9189715 100644 --- a/src/core_functions/aggregate/holistic/quantile.cpp +++ b/src/core_functions/aggregate/holistic/quantile.cpp @@ -1,141 +1,18 @@ #include "duckdb/execution/expression_executor.hpp" #include "duckdb/core_functions/aggregate/holistic_functions.hpp" -#include "duckdb/execution/merge_sort_tree.hpp" #include "duckdb/core_functions/aggregate/quantile_enum.hpp" #include "duckdb/planner/expression.hpp" #include "duckdb/common/operator/cast_operators.hpp" #include "duckdb/common/operator/abs.hpp" -#include "duckdb/common/operator/multiply.hpp" - +#include "duckdb/core_functions/aggregate/quantile_state.hpp" #include "duckdb/common/types/timestamp.hpp" #include "duckdb/common/queue.hpp" #include "duckdb/common/serializer/serializer.hpp" #include "duckdb/common/serializer/deserializer.hpp" - -#include "SkipList.h" - -#include -#include -#include -#include +#include "duckdb/core_functions/aggregate/sort_key_helpers.hpp" namespace duckdb { -// Interval arithmetic -static interval_t MultiplyByDouble(const interval_t &i, const double &d) { // NOLINT - D_ASSERT(d >= 0 && d <= 1); - return Interval::FromMicro(std::llround(Interval::GetMicro(i) * d)); -} - -inline interval_t operator+(const interval_t &lhs, const interval_t &rhs) { - return Interval::FromMicro(Interval::GetMicro(lhs) + Interval::GetMicro(rhs)); -} - -inline interval_t operator-(const interval_t &lhs, const interval_t &rhs) { - return Interval::FromMicro(Interval::GetMicro(lhs) - Interval::GetMicro(rhs)); -} - -struct FrameSet { - inline explicit FrameSet(const SubFrames &frames_p) : frames(frames_p) { - } - - inline idx_t Size() const { - idx_t result = 0; - for (const auto &frame : frames) { - result += frame.end - frame.start; - } - - return result; - } - - inline bool Contains(idx_t i) const { - for (idx_t f = 0; f < frames.size(); ++f) { - const auto &frame = frames[f]; - if (frame.start <= i && i < frame.end) { - return true; - } - } - return false; - } - const SubFrames &frames; -}; - -struct QuantileIncluded { - inline explicit QuantileIncluded(const ValidityMask &fmask_p, const ValidityMask &dmask_p) - : fmask(fmask_p), dmask(dmask_p) { - } - - inline bool operator()(const idx_t &idx) const { - return fmask.RowIsValid(idx) && dmask.RowIsValid(idx); - } - - inline bool AllValid() const { - return fmask.AllValid() && dmask.AllValid(); - } - - const ValidityMask &fmask; - const ValidityMask &dmask; -}; - -struct QuantileReuseUpdater { - idx_t *index; - idx_t j; - - inline QuantileReuseUpdater(idx_t *index, idx_t j) : index(index), j(j) { - } - - inline void Neither(idx_t begin, idx_t end) { - } - - inline void Left(idx_t begin, idx_t end) { - } - - inline void Right(idx_t begin, idx_t end) { - for (; begin < end; ++begin) { - index[j++] = begin; - } - } - - inline void Both(idx_t begin, idx_t end) { - } -}; - -void ReuseIndexes(idx_t *index, const SubFrames &currs, const SubFrames &prevs) { - - // Copy overlapping indices by scanning the previous set and copying down into holes. - // We copy instead of leaving gaps in case there are fewer values in the current frame. - FrameSet prev_set(prevs); - FrameSet curr_set(currs); - const auto prev_count = prev_set.Size(); - idx_t j = 0; - for (idx_t p = 0; p < prev_count; ++p) { - auto idx = index[p]; - - // Shift down into any hole - if (j != p) { - index[j] = idx; - } - - // Skip overlapping values - if (curr_set.Contains(idx)) { - ++j; - } - } - - // Insert new indices - if (j > 0) { - QuantileReuseUpdater updater(index, j); - AggregateExecutor::IntersectFrames(prevs, currs, updater); - } else { - // No overlap: overwrite with new values - for (const auto &curr : currs) { - for (auto idx = curr.start; idx < curr.end; ++idx) { - index[j++] = idx; - } - } - } -} - template struct IndirectLess { inline explicit IndirectLess(const INPUT_TYPE *inputs_p) : inputs(inputs_p) { @@ -148,262 +25,6 @@ struct IndirectLess { const INPUT_TYPE *inputs; }; -struct CastInterpolation { - - template - static inline TARGET_TYPE Cast(const INPUT_TYPE &src, Vector &result) { - return Cast::Operation(src); - } - template - static inline TARGET_TYPE Interpolate(const TARGET_TYPE &lo, const double d, const TARGET_TYPE &hi) { - const auto delta = hi - lo; - return UnsafeNumericCast(lo + delta * d); - } -}; - -template <> -interval_t CastInterpolation::Cast(const dtime_t &src, Vector &result) { - return {0, 0, src.micros}; -} - -template <> -double CastInterpolation::Interpolate(const double &lo, const double d, const double &hi) { - return lo * (1.0 - d) + hi * d; -} - -template <> -dtime_t CastInterpolation::Interpolate(const dtime_t &lo, const double d, const dtime_t &hi) { - return dtime_t(std::llround(lo.micros * (1.0 - d) + hi.micros * d)); -} - -template <> -timestamp_t CastInterpolation::Interpolate(const timestamp_t &lo, const double d, const timestamp_t &hi) { - return timestamp_t(std::llround(lo.value * (1.0 - d) + hi.value * d)); -} - -template <> -hugeint_t CastInterpolation::Interpolate(const hugeint_t &lo, const double d, const hugeint_t &hi) { - return Hugeint::Convert(Interpolate(Hugeint::Cast(lo), d, Hugeint::Cast(hi))); -} - -template <> -interval_t CastInterpolation::Interpolate(const interval_t &lo, const double d, const interval_t &hi) { - const interval_t delta = hi - lo; - return lo + MultiplyByDouble(delta, d); -} - -template <> -string_t CastInterpolation::Cast(const std::string &src, Vector &result) { - return StringVector::AddString(result, src); -} - -template <> -string_t CastInterpolation::Cast(const string_t &src, Vector &result) { - return StringVector::AddString(result, src); -} - -// Direct access -template -struct QuantileDirect { - using INPUT_TYPE = T; - using RESULT_TYPE = T; - - inline const INPUT_TYPE &operator()(const INPUT_TYPE &x) const { - return x; - } -}; - -// Indirect access -template -struct QuantileIndirect { - using INPUT_TYPE = idx_t; - using RESULT_TYPE = T; - const RESULT_TYPE *data; - - explicit QuantileIndirect(const RESULT_TYPE *data_p) : data(data_p) { - } - - inline RESULT_TYPE operator()(const idx_t &input) const { - return data[input]; - } -}; - -// Composed access -template -struct QuantileComposed { - using INPUT_TYPE = typename INNER::INPUT_TYPE; - using RESULT_TYPE = typename OUTER::RESULT_TYPE; - - const OUTER &outer; - const INNER &inner; - - explicit QuantileComposed(const OUTER &outer_p, const INNER &inner_p) : outer(outer_p), inner(inner_p) { - } - - inline RESULT_TYPE operator()(const idx_t &input) const { - return outer(inner(input)); - } -}; - -// Accessed comparison -template -struct QuantileCompare { - using INPUT_TYPE = typename ACCESSOR::INPUT_TYPE; - const ACCESSOR &accessor; - const bool desc; - explicit QuantileCompare(const ACCESSOR &accessor_p, bool desc_p) : accessor(accessor_p), desc(desc_p) { - } - - inline bool operator()(const INPUT_TYPE &lhs, const INPUT_TYPE &rhs) const { - const auto lval = accessor(lhs); - const auto rval = accessor(rhs); - - return desc ? (rval < lval) : (lval < rval); - } -}; - -// Avoid using naked Values in inner loops... -struct QuantileValue { - explicit QuantileValue(const Value &v) : val(v), dbl(v.GetValue()) { - const auto &type = val.type(); - switch (type.id()) { - case LogicalTypeId::DECIMAL: { - integral = IntegralValue::Get(v); - scaling = Hugeint::POWERS_OF_TEN[DecimalType::GetScale(type)]; - break; - } - default: - break; - } - } - - Value val; - - // DOUBLE - double dbl; - - // DECIMAL - hugeint_t integral; - hugeint_t scaling; -}; - -bool operator==(const QuantileValue &x, const QuantileValue &y) { - return x.val == y.val; -} - -// Continuous interpolation -template -struct Interpolator { - Interpolator(const QuantileValue &q, const idx_t n_p, const bool desc_p) - : desc(desc_p), RN((double)(n_p - 1) * q.dbl), FRN(UnsafeNumericCast(floor(RN))), - CRN(UnsafeNumericCast(ceil(RN))), begin(0), end(n_p) { - } - - template > - TARGET_TYPE Interpolate(INPUT_TYPE lidx, INPUT_TYPE hidx, Vector &result, const ACCESSOR &accessor) const { - using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE; - if (lidx == hidx) { - return CastInterpolation::Cast(accessor(lidx), result); - } else { - auto lo = CastInterpolation::Cast(accessor(lidx), result); - auto hi = CastInterpolation::Cast(accessor(hidx), result); - return CastInterpolation::Interpolate(lo, RN - FRN, hi); - } - } - - template > - TARGET_TYPE Operation(INPUT_TYPE *v_t, Vector &result, const ACCESSOR &accessor = ACCESSOR()) const { - using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE; - QuantileCompare comp(accessor, desc); - if (CRN == FRN) { - std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp); - return CastInterpolation::Cast(accessor(v_t[FRN]), result); - } else { - std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp); - std::nth_element(v_t + FRN, v_t + CRN, v_t + end, comp); - auto lo = CastInterpolation::Cast(accessor(v_t[FRN]), result); - auto hi = CastInterpolation::Cast(accessor(v_t[CRN]), result); - return CastInterpolation::Interpolate(lo, RN - FRN, hi); - } - } - - template - inline TARGET_TYPE Extract(const INPUT_TYPE **dest, Vector &result) const { - if (CRN == FRN) { - return CastInterpolation::Cast(*dest[0], result); - } else { - auto lo = CastInterpolation::Cast(*dest[0], result); - auto hi = CastInterpolation::Cast(*dest[1], result); - return CastInterpolation::Interpolate(lo, RN - FRN, hi); - } - } - - const bool desc; - const double RN; - const idx_t FRN; - const idx_t CRN; - - idx_t begin; - idx_t end; -}; - -// Discrete "interpolation" -template <> -struct Interpolator { - static inline idx_t Index(const QuantileValue &q, const idx_t n) { - idx_t floored; - switch (q.val.type().id()) { - case LogicalTypeId::DECIMAL: { - // Integer arithmetic for accuracy - const auto integral = q.integral; - const auto scaling = q.scaling; - const auto scaled_q = - DecimalMultiplyOverflowCheck::Operation(Hugeint::Convert(n), integral); - const auto scaled_n = - DecimalMultiplyOverflowCheck::Operation(Hugeint::Convert(n), scaling); - floored = Cast::Operation((scaled_n - scaled_q) / scaling); - break; - } - default: - const auto scaled_q = (double)(n * q.dbl); - floored = UnsafeNumericCast(floor(n - scaled_q)); - break; - } - - return MaxValue(1, n - floored) - 1; - } - - Interpolator(const QuantileValue &q, const idx_t n_p, bool desc_p) - : desc(desc_p), FRN(Index(q, n_p)), CRN(FRN), begin(0), end(n_p) { - } - - template > - TARGET_TYPE Interpolate(INPUT_TYPE lidx, INPUT_TYPE hidx, Vector &result, const ACCESSOR &accessor) const { - using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE; - return CastInterpolation::Cast(accessor(lidx), result); - } - - template > - TARGET_TYPE Operation(INPUT_TYPE *v_t, Vector &result, const ACCESSOR &accessor = ACCESSOR()) const { - using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE; - QuantileCompare comp(accessor, desc); - std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp); - return CastInterpolation::Cast(accessor(v_t[FRN]), result); - } - - template - TARGET_TYPE Extract(const INPUT_TYPE **dest, Vector &result) const { - return CastInterpolation::Cast(*dest[0], result); - } - - const bool desc; - const idx_t FRN; - const idx_t CRN; - - idx_t begin; - idx_t end; -}; - template static inline T QuantileAbs(const T &t) { return AbsOperator::Operation(t); @@ -435,497 +56,155 @@ inline Value QuantileAbs(const Value &v) { } } -void BindQuantileInner(AggregateFunction &function, const LogicalType &type, QuantileSerializationType quantile_type); +//===--------------------------------------------------------------------===// +// Quantile Bind Data +//===--------------------------------------------------------------------===// +QuantileBindData::QuantileBindData() { +} -struct QuantileBindData : public FunctionData { - QuantileBindData() { - } +QuantileBindData::QuantileBindData(const Value &quantile_p) + : quantiles(1, QuantileValue(QuantileAbs(quantile_p))), order(1, 0), desc(quantile_p < 0) { +} - explicit QuantileBindData(const Value &quantile_p) - : quantiles(1, QuantileValue(QuantileAbs(quantile_p))), order(1, 0), desc(quantile_p < 0) { +QuantileBindData::QuantileBindData(const vector &quantiles_p) { + vector normalised; + size_t pos = 0; + size_t neg = 0; + for (idx_t i = 0; i < quantiles_p.size(); ++i) { + const auto &q = quantiles_p[i]; + pos += (q > 0); + neg += (q < 0); + normalised.emplace_back(QuantileAbs(q)); + order.push_back(i); } - - explicit QuantileBindData(const vector &quantiles_p) { - vector normalised; - size_t pos = 0; - size_t neg = 0; - for (idx_t i = 0; i < quantiles_p.size(); ++i) { - const auto &q = quantiles_p[i]; - pos += (q > 0); - neg += (q < 0); - normalised.emplace_back(QuantileAbs(q)); - order.push_back(i); - } - if (pos && neg) { - throw BinderException("QUANTILE parameters must have consistent signs"); - } - desc = (neg > 0); - - IndirectLess lt(normalised.data()); - std::sort(order.begin(), order.end(), lt); - - for (const auto &q : normalised) { - quantiles.emplace_back(QuantileValue(q)); - } + if (pos && neg) { + throw BinderException("QUANTILE parameters must have consistent signs"); } + desc = (neg > 0); - QuantileBindData(const QuantileBindData &other) : order(other.order), desc(other.desc) { - for (const auto &q : other.quantiles) { - quantiles.emplace_back(q); - } - } + IndirectLess lt(normalised.data()); + std::sort(order.begin(), order.end(), lt); - unique_ptr Copy() const override { - return make_uniq(*this); + for (const auto &q : normalised) { + quantiles.emplace_back(QuantileValue(q)); } +} - bool Equals(const FunctionData &other_p) const override { - auto &other = other_p.Cast(); - return desc == other.desc && quantiles == other.quantiles && order == other.order; +QuantileBindData::QuantileBindData(const QuantileBindData &other) : order(other.order), desc(other.desc) { + for (const auto &q : other.quantiles) { + quantiles.emplace_back(q); } +} - static void Serialize(Serializer &serializer, const optional_ptr bind_data_p, - const AggregateFunction &function) { - auto &bind_data = bind_data_p->Cast(); - vector raw; - for (const auto &q : bind_data.quantiles) { - raw.emplace_back(q.val); - } - serializer.WriteProperty(100, "quantiles", raw); - serializer.WriteProperty(101, "order", bind_data.order); - serializer.WriteProperty(102, "desc", bind_data.desc); - } +unique_ptr QuantileBindData::Copy() const { + return make_uniq(*this); +} - static unique_ptr Deserialize(Deserializer &deserializer, AggregateFunction &function) { - auto result = make_uniq(); - vector raw; - deserializer.ReadProperty(100, "quantiles", raw); - deserializer.ReadProperty(101, "order", result->order); - deserializer.ReadProperty(102, "desc", result->desc); - QuantileSerializationType deserialization_type; - deserializer.ReadPropertyWithDefault(103, "quantile_type", deserialization_type, - QuantileSerializationType::NON_DECIMAL); - - if (deserialization_type != QuantileSerializationType::NON_DECIMAL) { - LogicalType arg_type; - deserializer.ReadProperty(104, "logical_type", arg_type); - - BindQuantileInner(function, arg_type, deserialization_type); - } +bool QuantileBindData::Equals(const FunctionData &other_p) const { + auto &other = other_p.Cast(); + return desc == other.desc && quantiles == other.quantiles && order == other.order; +} - for (const auto &r : raw) { - result->quantiles.emplace_back(QuantileValue(r)); - } - return std::move(result); +void QuantileBindData::Serialize(Serializer &serializer, const optional_ptr bind_data_p, + const AggregateFunction &function) { + auto &bind_data = bind_data_p->Cast(); + vector raw; + for (const auto &q : bind_data.quantiles) { + raw.emplace_back(q.val); } + serializer.WriteProperty(100, "quantiles", raw); + serializer.WriteProperty(101, "order", bind_data.order); + serializer.WriteProperty(102, "desc", bind_data.desc); +} - static void SerializeDecimalDiscrete(Serializer &serializer, const optional_ptr bind_data_p, - const AggregateFunction &function) { - Serialize(serializer, bind_data_p, function); +unique_ptr QuantileBindData::Deserialize(Deserializer &deserializer, AggregateFunction &function) { + auto result = make_uniq(); + vector raw; + deserializer.ReadProperty(100, "quantiles", raw); + deserializer.ReadProperty(101, "order", result->order); + deserializer.ReadProperty(102, "desc", result->desc); + QuantileSerializationType deserialization_type; + deserializer.ReadPropertyWithDefault(103, "quantile_type", deserialization_type, + QuantileSerializationType::NON_DECIMAL); - serializer.WritePropertyWithDefault( - 103, "quantile_type", QuantileSerializationType::DECIMAL_DISCRETE, QuantileSerializationType::NON_DECIMAL); - serializer.WriteProperty(104, "logical_type", function.arguments[0]); + if (deserialization_type != QuantileSerializationType::NON_DECIMAL) { + deserializer.ReadDeletedProperty(104, "logical_type"); } - static void SerializeDecimalDiscreteList(Serializer &serializer, const optional_ptr bind_data_p, - const AggregateFunction &function) { - Serialize(serializer, bind_data_p, function); - - serializer.WritePropertyWithDefault(103, "quantile_type", - QuantileSerializationType::DECIMAL_DISCRETE_LIST, - QuantileSerializationType::NON_DECIMAL); - serializer.WriteProperty(104, "logical_type", function.arguments[0]); - } - static void SerializeDecimalContinuous(Serializer &serializer, const optional_ptr bind_data_p, - const AggregateFunction &function) { - Serialize(serializer, bind_data_p, function); - - serializer.WritePropertyWithDefault(103, "quantile_type", - QuantileSerializationType::DECIMAL_CONTINUOUS, - QuantileSerializationType::NON_DECIMAL); - serializer.WriteProperty(104, "logical_type", function.arguments[0]); + for (const auto &r : raw) { + result->quantiles.emplace_back(QuantileValue(r)); } - static void SerializeDecimalContinuousList(Serializer &serializer, const optional_ptr bind_data_p, - const AggregateFunction &function) { + return std::move(result); +} - Serialize(serializer, bind_data_p, function); +//===--------------------------------------------------------------------===// +// Cast Interpolation +//===--------------------------------------------------------------------===// +template <> +interval_t CastInterpolation::Cast(const dtime_t &src, Vector &result) { + return {0, 0, src.micros}; +} - serializer.WritePropertyWithDefault( - 103, "quantile_type", QuantileSerializationType::DECIMAL_CONTINUOUS_LIST, - QuantileSerializationType::NON_DECIMAL); - serializer.WriteProperty(104, "logical_type", function.arguments[0]); - } +template <> +double CastInterpolation::Interpolate(const double &lo, const double d, const double &hi) { + return lo * (1.0 - d) + hi * d; +} - vector quantiles; - vector order; - bool desc; -}; +template <> +dtime_t CastInterpolation::Interpolate(const dtime_t &lo, const double d, const dtime_t &hi) { + return dtime_t(std::llround(lo.micros * (1.0 - d) + hi.micros * d)); +} -template -struct QuantileSortTree : public MergeSortTree { +template <> +timestamp_t CastInterpolation::Interpolate(const timestamp_t &lo, const double d, const timestamp_t &hi) { + return timestamp_t(std::llround(lo.value * (1.0 - d) + hi.value * d)); +} - using BaseTree = MergeSortTree; - using Elements = typename BaseTree::Elements; +template <> +hugeint_t CastInterpolation::Interpolate(const hugeint_t &lo, const double d, const hugeint_t &hi) { + return Hugeint::Convert(Interpolate(Hugeint::Cast(lo), d, Hugeint::Cast(hi))); +} - explicit QuantileSortTree(Elements &&lowest_level) : BaseTree(std::move(lowest_level)) { - } +static interval_t MultiplyByDouble(const interval_t &i, const double &d) { // NOLINT + D_ASSERT(d >= 0 && d <= 1); + return Interval::FromMicro(std::llround(Interval::GetMicro(i) * d)); +} - template - static unique_ptr WindowInit(const INPUT_TYPE *data, AggregateInputData &aggr_input_data, - const ValidityMask &data_mask, const ValidityMask &filter_mask, - idx_t count) { - // Build the indirection array - using ElementType = typename QuantileSortTree::ElementType; - vector sorted(count); - if (filter_mask.AllValid() && data_mask.AllValid()) { - std::iota(sorted.begin(), sorted.end(), 0); - } else { - size_t valid = 0; - QuantileIncluded included(filter_mask, data_mask); - for (ElementType i = 0; i < count; ++i) { - if (included(i)) { - sorted[valid++] = i; - } - } - sorted.resize(valid); - } +inline interval_t operator+(const interval_t &lhs, const interval_t &rhs) { + return Interval::FromMicro(Interval::GetMicro(lhs) + Interval::GetMicro(rhs)); +} - // Sort it - auto &bind_data = aggr_input_data.bind_data->Cast(); - using Accessor = QuantileIndirect; - Accessor indirect(data); - QuantileCompare cmp(indirect, bind_data.desc); - std::sort(sorted.begin(), sorted.end(), cmp); +inline interval_t operator-(const interval_t &lhs, const interval_t &rhs) { + return Interval::FromMicro(Interval::GetMicro(lhs) - Interval::GetMicro(rhs)); +} - return make_uniq(std::move(sorted)); - } +template <> +interval_t CastInterpolation::Interpolate(const interval_t &lo, const double d, const interval_t &hi) { + const interval_t delta = hi - lo; + return lo + MultiplyByDouble(delta, d); +} - inline IDX SelectNth(const SubFrames &frames, size_t n) const { - return BaseTree::NthElement(BaseTree::SelectNth(frames, n)); - } +template <> +string_t CastInterpolation::Cast(const string_t &src, Vector &result) { + return StringVector::AddStringOrBlob(result, src); +} - template - RESULT_TYPE WindowScalar(const INPUT_TYPE *data, const SubFrames &frames, const idx_t n, Vector &result, - const QuantileValue &q) const { - D_ASSERT(n > 0); - - // Find the interpolated indicies within the frame - Interpolator interp(q, n, false); - const auto lo_data = SelectNth(frames, interp.FRN); - auto hi_data = lo_data; - if (interp.CRN != interp.FRN) { - hi_data = SelectNth(frames, interp.CRN); +//===--------------------------------------------------------------------===// +// Scalar Quantile +//===--------------------------------------------------------------------===// +template +struct QuantileScalarOperation : public QuantileOperation { + template + static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { + if (state.v.empty()) { + finalize_data.ReturnNull(); + return; } - - // Interpolate indirectly - using ID = QuantileIndirect; - ID indirect(data); - return interp.template Interpolate(lo_data, hi_data, result, indirect); - } - - template - void WindowList(const INPUT_TYPE *data, const SubFrames &frames, const idx_t n, Vector &list, const idx_t lidx, - const QuantileBindData &bind_data) const { - D_ASSERT(n > 0); - - // Result is a constant LIST with a fixed length - auto ldata = FlatVector::GetData(list); - auto &lentry = ldata[lidx]; - lentry.offset = ListVector::GetListSize(list); - lentry.length = bind_data.quantiles.size(); - - ListVector::Reserve(list, lentry.offset + lentry.length); - ListVector::SetListSize(list, lentry.offset + lentry.length); - auto &result = ListVector::GetEntry(list); - auto rdata = FlatVector::GetData(result); - - using ID = QuantileIndirect; - ID indirect(data); - for (const auto &q : bind_data.order) { - const auto &quantile = bind_data.quantiles[q]; - Interpolator interp(quantile, n, false); - - const auto lo_data = SelectNth(frames, interp.FRN); - auto hi_data = lo_data; - if (interp.CRN != interp.FRN) { - hi_data = SelectNth(frames, interp.CRN); - } - - // Interpolate indirectly - rdata[lentry.offset + q] = - interp.template Interpolate(lo_data, hi_data, result, indirect); - } - } -}; - -template -struct PointerLess { - inline bool operator()(const T &lhi, const T &rhi) const { - return *lhi < *rhi; - } -}; - -template -struct QuantileState { - using SaveType = SAVE_TYPE; - using InputType = INPUT_TYPE; - - // Regular aggregation - vector v; - - // Windowed Quantile merge sort trees - using QuantileSortTree32 = QuantileSortTree; - using QuantileSortTree64 = QuantileSortTree; - unique_ptr qst32; - unique_ptr qst64; - - // Windowed Quantile skip lists - using PointerType = const InputType *; - using SkipListType = duckdb_skiplistlib::skip_list::HeadNode>; - SubFrames prevs; - unique_ptr s; - mutable vector dest; - - // Windowed MAD indirection - idx_t count; - vector m; - - QuantileState() : count(0) { - } - - ~QuantileState() { - } - - inline void SetCount(size_t count_p) { - count = count_p; - if (count >= m.size()) { - m.resize(count); - } - } - - inline SkipListType &GetSkipList(bool reset = false) { - if (reset || !s) { - s.reset(); - s = make_uniq(); - } - return *s; - } - - struct SkipListUpdater { - SkipListType &skip; - const INPUT_TYPE *data; - const QuantileIncluded &included; - - inline SkipListUpdater(SkipListType &skip, const INPUT_TYPE *data, const QuantileIncluded &included) - : skip(skip), data(data), included(included) { - } - - inline void Neither(idx_t begin, idx_t end) { - } - - inline void Left(idx_t begin, idx_t end) { - for (; begin < end; ++begin) { - if (included(begin)) { - skip.remove(data + begin); - } - } - } - - inline void Right(idx_t begin, idx_t end) { - for (; begin < end; ++begin) { - if (included(begin)) { - skip.insert(data + begin); - } - } - } - - inline void Both(idx_t begin, idx_t end) { - } - }; - - void UpdateSkip(const INPUT_TYPE *data, const SubFrames &frames, const QuantileIncluded &included) { - // No overlap, or no data - if (!s || prevs.back().end <= frames.front().start || frames.back().end <= prevs.front().start) { - auto &skip = GetSkipList(true); - for (const auto &frame : frames) { - for (auto i = frame.start; i < frame.end; ++i) { - if (included(i)) { - skip.insert(data + i); - } - } - } - } else { - auto &skip = GetSkipList(); - SkipListUpdater updater(skip, data, included); - AggregateExecutor::IntersectFrames(prevs, frames, updater); - } - } - - bool HasTrees() const { - return qst32 || qst64; - } - - template - RESULT_TYPE WindowScalar(const INPUT_TYPE *data, const SubFrames &frames, const idx_t n, Vector &result, - const QuantileValue &q) const { - D_ASSERT(n > 0); - if (qst32) { - return qst32->WindowScalar(data, frames, n, result, q); - } else if (qst64) { - return qst64->WindowScalar(data, frames, n, result, q); - } else if (s) { - // Find the position(s) needed - try { - Interpolator interp(q, s->size(), false); - s->at(interp.FRN, interp.CRN - interp.FRN + 1, dest); - return interp.template Extract(dest.data(), result); - } catch (const duckdb_skiplistlib::skip_list::IndexError &idx_err) { - throw InternalException(idx_err.message()); - } - } else { - throw InternalException("No accelerator for scalar QUANTILE"); - } - } - - template - void WindowList(const INPUT_TYPE *data, const SubFrames &frames, const idx_t n, Vector &list, const idx_t lidx, - const QuantileBindData &bind_data) const { - D_ASSERT(n > 0); - // Result is a constant LIST with a fixed length - auto ldata = FlatVector::GetData(list); - auto &lentry = ldata[lidx]; - lentry.offset = ListVector::GetListSize(list); - lentry.length = bind_data.quantiles.size(); - - ListVector::Reserve(list, lentry.offset + lentry.length); - ListVector::SetListSize(list, lentry.offset + lentry.length); - auto &result = ListVector::GetEntry(list); - auto rdata = FlatVector::GetData(result); - - for (const auto &q : bind_data.order) { - const auto &quantile = bind_data.quantiles[q]; - rdata[lentry.offset + q] = WindowScalar(data, frames, n, result, quantile); - } - } -}; - -struct QuantileOperation { - template - static void Initialize(STATE &state) { - new (&state) STATE(); - } - - template - static void ConstantOperation(STATE &state, const INPUT_TYPE &input, AggregateUnaryInput &unary_input, - idx_t count) { - for (idx_t i = 0; i < count; i++) { - Operation(state, input, unary_input); - } - } - - template - static void Operation(STATE &state, const INPUT_TYPE &input, AggregateUnaryInput &) { - state.v.emplace_back(input); - } - - template - static void Combine(const STATE &source, STATE &target, AggregateInputData &) { - if (source.v.empty()) { - return; - } - target.v.insert(target.v.end(), source.v.begin(), source.v.end()); - } - - template - static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { - state.~STATE(); - } - - static bool IgnoreNull() { - return true; - } - - template - static void WindowInit(AggregateInputData &aggr_input_data, const WindowPartitionInput &partition, - data_ptr_t g_state) { - D_ASSERT(partition.input_count == 1); - - auto inputs = partition.inputs; - const auto count = partition.count; - const auto &filter_mask = partition.filter_mask; - const auto &stats = partition.stats; - - // If frames overlap significantly, then use local skip lists. - if (stats[0].end <= stats[1].begin) { - // Frames can overlap - const auto overlap = double(stats[1].begin - stats[0].end); - const auto cover = double(stats[1].end - stats[0].begin); - const auto ratio = overlap / cover; - if (ratio > .75) { - return; - } - } - - const auto data = FlatVector::GetData(inputs[0]); - const auto &data_mask = FlatVector::Validity(inputs[0]); - - // Build the tree - auto &state = *reinterpret_cast(g_state); - if (count < std::numeric_limits::max()) { - state.qst32 = QuantileSortTree::WindowInit(data, aggr_input_data, data_mask, - filter_mask, count); - } else { - state.qst64 = QuantileSortTree::WindowInit(data, aggr_input_data, data_mask, - filter_mask, count); - } - } - - static idx_t FrameSize(const QuantileIncluded &included, const SubFrames &frames) { - // Count the number of valid values - idx_t n = 0; - if (included.AllValid()) { - for (const auto &frame : frames) { - n += frame.end - frame.start; - } - } else { - // NULLs or FILTERed values, - for (const auto &frame : frames) { - for (auto i = frame.start; i < frame.end; ++i) { - n += included(i); - } - } - } - - return n; - } -}; - -template -static AggregateFunction QuantileListAggregate(const LogicalType &input_type, const LogicalType &child_type) { // NOLINT - LogicalType result_type = - LogicalType::LIST(child_type.id() == LogicalTypeId::ANY ? LogicalType::VARCHAR : child_type); - return AggregateFunction( - {input_type}, result_type, AggregateFunction::StateSize, AggregateFunction::StateInitialize, - AggregateFunction::UnaryScatterUpdate, AggregateFunction::StateCombine, - AggregateFunction::StateFinalize, AggregateFunction::UnaryUpdate, - nullptr, AggregateFunction::StateDestroy); -} - -template -struct QuantileScalarOperation : public QuantileOperation { - - template - static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { - if (state.v.empty()) { - finalize_data.ReturnNull(); - return; - } - D_ASSERT(finalize_data.input.bind_data); - auto &bind_data = finalize_data.input.bind_data->Cast(); - D_ASSERT(bind_data.quantiles.size() == 1); - Interpolator interp(bind_data.quantiles[0], state.v.size(), bind_data.desc); - target = interp.template Operation(state.v.data(), finalize_data.result); + D_ASSERT(finalize_data.input.bind_data); + auto &bind_data = finalize_data.input.bind_data->Cast(); + D_ASSERT(bind_data.quantiles.size() == 1); + Interpolator interp(bind_data.quantiles[0], state.v.size(), bind_data.desc); + target = interp.template Operation(state.v.data(), finalize_data.result); } template @@ -943,544 +222,340 @@ struct QuantileScalarOperation : public QuantileOperation { if (!n) { rmask.Set(ridx, false); - return; - } - - const auto &quantile = bind_data.quantiles[0]; - if (gstate && gstate->HasTrees()) { - rdata[ridx] = gstate->template WindowScalar(data, frames, n, result, quantile); - } else { - // Update the skip list - state.UpdateSkip(data, frames, included); - - // Find the position(s) needed - rdata[ridx] = state.template WindowScalar(data, frames, n, result, quantile); - - // Save the previous state for next time - state.prevs = frames; - } - } -}; - -template -AggregateFunction GetTypedDiscreteQuantileAggregateFunction(const LogicalType &type) { - using STATE = QuantileState; - using OP = QuantileScalarOperation; - auto return_type = type.id() == LogicalTypeId::ANY ? LogicalType::VARCHAR : type; - auto fun = AggregateFunction::UnaryAggregateDestructor(type, return_type); - fun.window = AggregateFunction::UnaryWindow; - fun.window_init = OP::WindowInit; - return fun; -} - -AggregateFunction GetDiscreteQuantileAggregateFunction(const LogicalType &type) { - switch (type.id()) { - case LogicalTypeId::TINYINT: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::SMALLINT: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::INTEGER: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::BIGINT: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::HUGEINT: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::FLOAT: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::DOUBLE: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::DECIMAL: - switch (type.InternalType()) { - case PhysicalType::INT16: - return GetTypedDiscreteQuantileAggregateFunction(type); - case PhysicalType::INT32: - return GetTypedDiscreteQuantileAggregateFunction(type); - case PhysicalType::INT64: - return GetTypedDiscreteQuantileAggregateFunction(type); - case PhysicalType::INT128: - return GetTypedDiscreteQuantileAggregateFunction(type); - default: - throw NotImplementedException("Unimplemented discrete quantile aggregate"); - } - case LogicalTypeId::DATE: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::TIMESTAMP: - case LogicalTypeId::TIMESTAMP_TZ: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::TIME: - case LogicalTypeId::TIME_TZ: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::INTERVAL: - return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::ANY: - return GetTypedDiscreteQuantileAggregateFunction(type); - - default: - throw NotImplementedException("Unimplemented discrete quantile aggregate"); - } -} - -template -struct QuantileListOperation : public QuantileOperation { - - template - static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { - if (state.v.empty()) { - finalize_data.ReturnNull(); - return; - } - - D_ASSERT(finalize_data.input.bind_data); - auto &bind_data = finalize_data.input.bind_data->Cast(); - - auto &result = ListVector::GetEntry(finalize_data.result); - auto ridx = ListVector::GetListSize(finalize_data.result); - ListVector::Reserve(finalize_data.result, ridx + bind_data.quantiles.size()); - auto rdata = FlatVector::GetData(result); - - auto v_t = state.v.data(); - D_ASSERT(v_t); - - auto &entry = target; - entry.offset = ridx; - idx_t lower = 0; - for (const auto &q : bind_data.order) { - const auto &quantile = bind_data.quantiles[q]; - Interpolator interp(quantile, state.v.size(), bind_data.desc); - interp.begin = lower; - rdata[ridx + q] = interp.template Operation(v_t, result); - lower = interp.FRN; - } - entry.length = bind_data.quantiles.size(); - - ListVector::SetListSize(finalize_data.result, entry.offset + entry.length); - } - - template - static void Window(const INPUT_TYPE *data, const ValidityMask &fmask, const ValidityMask &dmask, - AggregateInputData &aggr_input_data, STATE &state, const SubFrames &frames, Vector &list, - idx_t lidx, const STATE *gstate) { - D_ASSERT(aggr_input_data.bind_data); - auto &bind_data = aggr_input_data.bind_data->Cast(); - - QuantileIncluded included(fmask, dmask); - const auto n = FrameSize(included, frames); - - // Result is a constant LIST with a fixed length - if (!n) { - auto &lmask = FlatVector::Validity(list); - lmask.Set(lidx, false); - return; - } - - if (gstate && gstate->HasTrees()) { - gstate->template WindowList(data, frames, n, list, lidx, bind_data); - } else { - // - state.UpdateSkip(data, frames, included); - state.template WindowList(data, frames, n, list, lidx, bind_data); - state.prevs = frames; - } - } -}; - -template -AggregateFunction GetTypedDiscreteQuantileListAggregateFunction(const LogicalType &type) { - using STATE = QuantileState; - using OP = QuantileListOperation; - auto fun = QuantileListAggregate(type, type); - fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - fun.window = AggregateFunction::UnaryWindow; - fun.window_init = OP::template WindowInit; - return fun; -} - -AggregateFunction GetDiscreteQuantileListAggregateFunction(const LogicalType &type) { - switch (type.id()) { - case LogicalTypeId::TINYINT: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::SMALLINT: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::INTEGER: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::BIGINT: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::HUGEINT: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::FLOAT: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::DOUBLE: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::DECIMAL: - switch (type.InternalType()) { - case PhysicalType::INT16: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case PhysicalType::INT32: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case PhysicalType::INT64: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case PhysicalType::INT128: - return GetTypedDiscreteQuantileListAggregateFunction(type); - default: - throw NotImplementedException("Unimplemented discrete quantile list aggregate"); - } - case LogicalTypeId::DATE: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::TIMESTAMP: - case LogicalTypeId::TIMESTAMP_TZ: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::TIME: - case LogicalTypeId::TIME_TZ: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::INTERVAL: - return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::ANY: - return GetTypedDiscreteQuantileListAggregateFunction(type); - default: - throw NotImplementedException("Unimplemented discrete quantile list aggregate"); - } -} - -template -AggregateFunction GetTypedContinuousQuantileAggregateFunction(const LogicalType &input_type, - const LogicalType &target_type) { - using STATE = QuantileState; - using OP = QuantileScalarOperation; - auto fun = AggregateFunction::UnaryAggregateDestructor(input_type, target_type); - fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - fun.window = AggregateFunction::UnaryWindow; - fun.window_init = OP::template WindowInit; - return fun; -} - -AggregateFunction GetContinuousQuantileAggregateFunction(const LogicalType &type) { - switch (type.id()) { - case LogicalTypeId::TINYINT: - return GetTypedContinuousQuantileAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::SMALLINT: - return GetTypedContinuousQuantileAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::INTEGER: - return GetTypedContinuousQuantileAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::BIGINT: - return GetTypedContinuousQuantileAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::HUGEINT: - return GetTypedContinuousQuantileAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::FLOAT: - return GetTypedContinuousQuantileAggregateFunction(type, type); - case LogicalTypeId::DOUBLE: - return GetTypedContinuousQuantileAggregateFunction(type, type); - case LogicalTypeId::DECIMAL: - switch (type.InternalType()) { - case PhysicalType::INT16: - return GetTypedContinuousQuantileAggregateFunction(type, type); - case PhysicalType::INT32: - return GetTypedContinuousQuantileAggregateFunction(type, type); - case PhysicalType::INT64: - return GetTypedContinuousQuantileAggregateFunction(type, type); - case PhysicalType::INT128: - return GetTypedContinuousQuantileAggregateFunction(type, type); - default: - throw NotImplementedException("Unimplemented continuous quantile DECIMAL aggregate"); - } - case LogicalTypeId::DATE: - return GetTypedContinuousQuantileAggregateFunction(type, LogicalType::TIMESTAMP); - case LogicalTypeId::TIMESTAMP: - case LogicalTypeId::TIMESTAMP_TZ: - return GetTypedContinuousQuantileAggregateFunction(type, type); - case LogicalTypeId::TIME: - case LogicalTypeId::TIME_TZ: - return GetTypedContinuousQuantileAggregateFunction(type, type); - - default: - throw NotImplementedException("Unimplemented continuous quantile aggregate"); - } -} - -template -AggregateFunction GetTypedContinuousQuantileListAggregateFunction(const LogicalType &input_type, - const LogicalType &result_type) { - using STATE = QuantileState; - using OP = QuantileListOperation; - auto fun = QuantileListAggregate(input_type, result_type); - fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - fun.window = AggregateFunction::UnaryWindow; - fun.window_init = OP::template WindowInit; - return fun; -} - -AggregateFunction GetContinuousQuantileListAggregateFunction(const LogicalType &type) { - switch (type.id()) { - case LogicalTypeId::TINYINT: - return GetTypedContinuousQuantileListAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::SMALLINT: - return GetTypedContinuousQuantileListAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::INTEGER: - return GetTypedContinuousQuantileListAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::BIGINT: - return GetTypedContinuousQuantileListAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::HUGEINT: - return GetTypedContinuousQuantileListAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::FLOAT: - return GetTypedContinuousQuantileListAggregateFunction(type, type); - case LogicalTypeId::DOUBLE: - return GetTypedContinuousQuantileListAggregateFunction(type, type); - case LogicalTypeId::DECIMAL: - switch (type.InternalType()) { - case PhysicalType::INT16: - return GetTypedContinuousQuantileListAggregateFunction(type, type); - case PhysicalType::INT32: - return GetTypedContinuousQuantileListAggregateFunction(type, type); - case PhysicalType::INT64: - return GetTypedContinuousQuantileListAggregateFunction(type, type); - case PhysicalType::INT128: - return GetTypedContinuousQuantileListAggregateFunction(type, type); - default: - throw NotImplementedException("Unimplemented discrete quantile DECIMAL list aggregate"); + return; } - case LogicalTypeId::DATE: - return GetTypedContinuousQuantileListAggregateFunction(type, LogicalType::TIMESTAMP); - case LogicalTypeId::TIMESTAMP: - case LogicalTypeId::TIMESTAMP_TZ: - return GetTypedContinuousQuantileListAggregateFunction(type, type); - case LogicalTypeId::TIME: - case LogicalTypeId::TIME_TZ: - return GetTypedContinuousQuantileListAggregateFunction(type, type); - default: - throw NotImplementedException("Unimplemented discrete quantile list aggregate"); - } -} -template -struct MadAccessor { - using INPUT_TYPE = T; - using RESULT_TYPE = R; - const MEDIAN_TYPE &median; - explicit MadAccessor(const MEDIAN_TYPE &median_p) : median(median_p) { - } + const auto &quantile = bind_data.quantiles[0]; + if (gstate && gstate->HasTrees()) { + rdata[ridx] = gstate->GetWindowState().template WindowScalar(data, frames, n, result, + quantile); + } else { + auto &window_state = state.GetOrCreateWindowState(); - inline RESULT_TYPE operator()(const INPUT_TYPE &input) const { - const RESULT_TYPE delta = input - UnsafeNumericCast(median); - return TryAbsOperator::Operation(delta); - } -}; + // Update the skip list + window_state.UpdateSkip(data, frames, included); -// hugeint_t - double => undefined -template <> -struct MadAccessor { - using INPUT_TYPE = hugeint_t; - using RESULT_TYPE = double; - using MEDIAN_TYPE = double; - const MEDIAN_TYPE &median; - explicit MadAccessor(const MEDIAN_TYPE &median_p) : median(median_p) { - } - inline RESULT_TYPE operator()(const INPUT_TYPE &input) const { - const auto delta = Hugeint::Cast(input) - median; - return TryAbsOperator::Operation(delta); - } -}; + // Find the position(s) needed + rdata[ridx] = window_state.template WindowScalar(data, frames, n, result, quantile); -// date_t - timestamp_t => interval_t -template <> -struct MadAccessor { - using INPUT_TYPE = date_t; - using RESULT_TYPE = interval_t; - using MEDIAN_TYPE = timestamp_t; - const MEDIAN_TYPE &median; - explicit MadAccessor(const MEDIAN_TYPE &median_p) : median(median_p) { - } - inline RESULT_TYPE operator()(const INPUT_TYPE &input) const { - const auto dt = Cast::Operation(input); - const auto delta = dt - median; - return Interval::FromMicro(TryAbsOperator::Operation(delta)); + // Save the previous state for next time + window_state.prevs = frames; + } } }; -// timestamp_t - timestamp_t => int64_t -template <> -struct MadAccessor { - using INPUT_TYPE = timestamp_t; - using RESULT_TYPE = interval_t; - using MEDIAN_TYPE = timestamp_t; - const MEDIAN_TYPE &median; - explicit MadAccessor(const MEDIAN_TYPE &median_p) : median(median_p) { - } - inline RESULT_TYPE operator()(const INPUT_TYPE &input) const { - const auto delta = input - median; - return Interval::FromMicro(TryAbsOperator::Operation(delta)); +struct QuantileScalarFallback : QuantileOperation { + template + static void Execute(STATE &state, const INPUT_TYPE &key, AggregateInputData &input_data) { + state.AddElement(key, input_data); } -}; -// dtime_t - dtime_t => int64_t -template <> -struct MadAccessor { - using INPUT_TYPE = dtime_t; - using RESULT_TYPE = interval_t; - using MEDIAN_TYPE = dtime_t; - const MEDIAN_TYPE &median; - explicit MadAccessor(const MEDIAN_TYPE &median_p) : median(median_p) { - } - inline RESULT_TYPE operator()(const INPUT_TYPE &input) const { - const auto delta = input - median; - return Interval::FromMicro(TryAbsOperator::Operation(delta)); + template + static void Finalize(STATE &state, AggregateFinalizeData &finalize_data) { + if (state.v.empty()) { + finalize_data.ReturnNull(); + return; + } + D_ASSERT(finalize_data.input.bind_data); + auto &bind_data = finalize_data.input.bind_data->Cast(); + D_ASSERT(bind_data.quantiles.size() == 1); + Interpolator interp(bind_data.quantiles[0], state.v.size(), bind_data.desc); + auto interpolation_result = interp.InterpolateInternal(state.v.data()); + CreateSortKeyHelpers::DecodeSortKey(interpolation_result, finalize_data.result, finalize_data.result_idx, + OrderModifiers(OrderType::ASCENDING, OrderByNullType::NULLS_LAST)); } }; -template -struct MedianAbsoluteDeviationOperation : public QuantileOperation { - +//===--------------------------------------------------------------------===// +// Quantile List +//===--------------------------------------------------------------------===// +template +struct QuantileListOperation : QuantileOperation { template static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { if (state.v.empty()) { finalize_data.ReturnNull(); return; } - using SAVE_TYPE = typename STATE::SaveType; + D_ASSERT(finalize_data.input.bind_data); auto &bind_data = finalize_data.input.bind_data->Cast(); - D_ASSERT(bind_data.quantiles.size() == 1); - const auto &q = bind_data.quantiles[0]; - Interpolator interp(q, state.v.size(), false); - const auto med = interp.template Operation(state.v.data(), finalize_data.result); - MadAccessor accessor(med); - target = interp.template Operation(state.v.data(), finalize_data.result, accessor); + auto &result = ListVector::GetEntry(finalize_data.result); + auto ridx = ListVector::GetListSize(finalize_data.result); + ListVector::Reserve(finalize_data.result, ridx + bind_data.quantiles.size()); + auto rdata = FlatVector::GetData(result); + + auto v_t = state.v.data(); + D_ASSERT(v_t); + + auto &entry = target; + entry.offset = ridx; + idx_t lower = 0; + for (const auto &q : bind_data.order) { + const auto &quantile = bind_data.quantiles[q]; + Interpolator interp(quantile, state.v.size(), bind_data.desc); + interp.begin = lower; + rdata[ridx + q] = interp.template Operation(v_t, result); + lower = interp.FRN; + } + entry.length = bind_data.quantiles.size(); + + ListVector::SetListSize(finalize_data.result, entry.offset + entry.length); } template static void Window(const INPUT_TYPE *data, const ValidityMask &fmask, const ValidityMask &dmask, - AggregateInputData &aggr_input_data, STATE &state, const SubFrames &frames, Vector &result, - idx_t ridx, const STATE *gstate) { - auto rdata = FlatVector::GetData(result); + AggregateInputData &aggr_input_data, STATE &state, const SubFrames &frames, Vector &list, + idx_t lidx, const STATE *gstate) { + D_ASSERT(aggr_input_data.bind_data); + auto &bind_data = aggr_input_data.bind_data->Cast(); QuantileIncluded included(fmask, dmask); const auto n = FrameSize(included, frames); + // Result is a constant LIST with a fixed length if (!n) { - auto &rmask = FlatVector::Validity(result); - rmask.Set(ridx, false); + auto &lmask = FlatVector::Validity(list); + lmask.Set(lidx, false); return; } - // Compute the median - D_ASSERT(aggr_input_data.bind_data); - auto &bind_data = aggr_input_data.bind_data->Cast(); - - D_ASSERT(bind_data.quantiles.size() == 1); - const auto &quantile = bind_data.quantiles[0]; - MEDIAN_TYPE med; if (gstate && gstate->HasTrees()) { - med = gstate->template WindowScalar(data, frames, n, result, quantile); + gstate->GetWindowState().template WindowList(data, frames, n, list, lidx, bind_data); } else { - state.UpdateSkip(data, frames, included); - med = state.template WindowScalar(data, frames, n, result, quantile); + auto &window_state = state.GetOrCreateWindowState(); + window_state.UpdateSkip(data, frames, included); + window_state.template WindowList(data, frames, n, list, lidx, bind_data); + window_state.prevs = frames; + } + } +}; + +struct QuantileListFallback : QuantileOperation { + template + static void Execute(STATE &state, const INPUT_TYPE &key, AggregateInputData &input_data) { + state.AddElement(key, input_data); + } + + template + static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { + if (state.v.empty()) { + finalize_data.ReturnNull(); + return; } - // Lazily initialise frame state - state.SetCount(frames.back().end - frames.front().start); - auto index2 = state.m.data(); - D_ASSERT(index2); + D_ASSERT(finalize_data.input.bind_data); + auto &bind_data = finalize_data.input.bind_data->Cast(); + + auto &result = ListVector::GetEntry(finalize_data.result); + auto ridx = ListVector::GetListSize(finalize_data.result); + ListVector::Reserve(finalize_data.result, ridx + bind_data.quantiles.size()); + + auto v_t = state.v.data(); + D_ASSERT(v_t); - // The replacement trick does not work on the second index because if - // the median has changed, the previous order is not correct. - // It is probably close, however, and so reuse is helpful. - auto &prevs = state.prevs; - ReuseIndexes(index2, frames, prevs); - std::partition(index2, index2 + state.count, included); + auto &entry = target; + entry.offset = ridx; + idx_t lower = 0; + for (const auto &q : bind_data.order) { + const auto &quantile = bind_data.quantiles[q]; + Interpolator interp(quantile, state.v.size(), bind_data.desc); + interp.begin = lower; + auto interpolation_result = interp.InterpolateInternal(state.v.data()); + CreateSortKeyHelpers::DecodeSortKey(interpolation_result, result, ridx + q, + OrderModifiers(OrderType::ASCENDING, OrderByNullType::NULLS_LAST)); + lower = interp.FRN; + } + entry.length = bind_data.quantiles.size(); - Interpolator interp(quantile, n, false); + ListVector::SetListSize(finalize_data.result, entry.offset + entry.length); + } +}; - // Compute mad from the second index - using ID = QuantileIndirect; - ID indirect(data); +//===--------------------------------------------------------------------===// +// Discrete Quantiles +//===--------------------------------------------------------------------===// +template +AggregateFunction GetDiscreteQuantileTemplated(const LogicalType &type) { + switch (type.InternalType()) { + case PhysicalType::INT8: + return OP::template GetFunction(type); + case PhysicalType::INT16: + return OP::template GetFunction(type); + case PhysicalType::INT32: + return OP::template GetFunction(type); + case PhysicalType::INT64: + return OP::template GetFunction(type); + case PhysicalType::INT128: + return OP::template GetFunction(type); + case PhysicalType::FLOAT: + return OP::template GetFunction(type); + case PhysicalType::DOUBLE: + return OP::template GetFunction(type); + case PhysicalType::INTERVAL: + return OP::template GetFunction(type); + case PhysicalType::VARCHAR: + return OP::template GetFunction(type); + default: + return OP::GetFallback(type); + } +} - using MAD = MadAccessor; - MAD mad(med); +struct ScalarDiscreteQuantile { + template + static AggregateFunction GetFunction(const LogicalType &type) { + using STATE = QuantileState; + using OP = QuantileScalarOperation; + auto fun = AggregateFunction::UnaryAggregateDestructor(type, type); + fun.window = AggregateFunction::UnaryWindow; + fun.window_init = OP::WindowInit; + return fun; + } - using MadIndirect = QuantileComposed; - MadIndirect mad_indirect(mad, indirect); - rdata[ridx] = interp.template Operation(index2, result, mad_indirect); + static AggregateFunction GetFallback(const LogicalType &type) { + using STATE = QuantileState; + using OP = QuantileScalarFallback; - // Prev is used by both skip lists and increments - prevs = frames; + AggregateFunction fun( + {type}, type, AggregateFunction::StateSize, AggregateFunction::StateInitialize, + AggregateSortKeyHelpers::UnaryUpdate, AggregateFunction::StateCombine, + AggregateFunction::StateVoidFinalize, nullptr, nullptr, + AggregateFunction::StateDestroy); + return fun; } }; -unique_ptr BindMedian(ClientContext &context, AggregateFunction &function, - vector> &arguments) { - return make_uniq(Value::DECIMAL(int16_t(5), 2, 1)); +template +static AggregateFunction QuantileListAggregate(const LogicalType &input_type, const LogicalType &child_type) { // NOLINT + LogicalType result_type = LogicalType::LIST(child_type); + return AggregateFunction( + {input_type}, result_type, AggregateFunction::StateSize, AggregateFunction::StateInitialize, + AggregateFunction::UnaryScatterUpdate, AggregateFunction::StateCombine, + AggregateFunction::StateFinalize, AggregateFunction::UnaryUpdate, + nullptr, AggregateFunction::StateDestroy); } -template -AggregateFunction GetTypedMedianAbsoluteDeviationAggregateFunction(const LogicalType &input_type, - const LogicalType &target_type) { - using STATE = QuantileState; - using OP = MedianAbsoluteDeviationOperation; - auto fun = AggregateFunction::UnaryAggregateDestructor(input_type, target_type); - fun.bind = BindMedian; - fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - fun.window = AggregateFunction::UnaryWindow; - fun.window_init = OP::template WindowInit; - return fun; +struct ListDiscreteQuantile { + template + static AggregateFunction GetFunction(const LogicalType &type) { + using STATE = QuantileState; + using OP = QuantileListOperation; + auto fun = QuantileListAggregate(type, type); + fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; + fun.window = AggregateFunction::UnaryWindow; + fun.window_init = OP::template WindowInit; + return fun; + } + + static AggregateFunction GetFallback(const LogicalType &type) { + using STATE = QuantileState; + using OP = QuantileListFallback; + + AggregateFunction fun( + {type}, LogicalType::LIST(type), AggregateFunction::StateSize, + AggregateFunction::StateInitialize, AggregateSortKeyHelpers::UnaryUpdate, + AggregateFunction::StateCombine, AggregateFunction::StateFinalize, + nullptr, nullptr, AggregateFunction::StateDestroy); + return fun; + } +}; + +AggregateFunction GetDiscreteQuantile(const LogicalType &type) { + return GetDiscreteQuantileTemplated(type); +} + +AggregateFunction GetDiscreteQuantileList(const LogicalType &type) { + return GetDiscreteQuantileTemplated(type); } -AggregateFunction GetMedianAbsoluteDeviationAggregateFunction(const LogicalType &type) { +//===--------------------------------------------------------------------===// +// Continuous Quantiles +//===--------------------------------------------------------------------===// +template +AggregateFunction GetContinuousQuantileTemplated(const LogicalType &type) { switch (type.id()) { + case LogicalTypeId::SQLNULL: + case LogicalTypeId::TINYINT: + case LogicalTypeId::SMALLINT: + case LogicalTypeId::INTEGER: + case LogicalTypeId::UTINYINT: + case LogicalTypeId::USMALLINT: + case LogicalTypeId::UINTEGER: + case LogicalTypeId::UBIGINT: + case LogicalTypeId::BIGINT: + case LogicalTypeId::UHUGEINT: + case LogicalTypeId::HUGEINT: case LogicalTypeId::FLOAT: - return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); case LogicalTypeId::DOUBLE: - return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + return OP::template GetFunction(LogicalType::DOUBLE, LogicalType::DOUBLE); case LogicalTypeId::DECIMAL: switch (type.InternalType()) { case PhysicalType::INT16: - return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + return OP::template GetFunction(type, type); case PhysicalType::INT32: - return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + return OP::template GetFunction(type, type); case PhysicalType::INT64: - return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + return OP::template GetFunction(type, type); case PhysicalType::INT128: - return GetTypedMedianAbsoluteDeviationAggregateFunction(type, type); + return OP::template GetFunction(type, type); default: - throw NotImplementedException("Unimplemented Median Absolute Deviation DECIMAL aggregate"); + throw NotImplementedException("Unimplemented continuous quantile DECIMAL aggregate"); } - break; - case LogicalTypeId::DATE: - return GetTypedMedianAbsoluteDeviationAggregateFunction(type, - LogicalType::INTERVAL); + return OP::template GetFunction(type, LogicalType::TIMESTAMP); case LogicalTypeId::TIMESTAMP: case LogicalTypeId::TIMESTAMP_TZ: - return GetTypedMedianAbsoluteDeviationAggregateFunction( - type, LogicalType::INTERVAL); + case LogicalTypeId::TIMESTAMP_SEC: + case LogicalTypeId::TIMESTAMP_MS: + case LogicalTypeId::TIMESTAMP_NS: + return OP::template GetFunction(type, type); case LogicalTypeId::TIME: case LogicalTypeId::TIME_TZ: - return GetTypedMedianAbsoluteDeviationAggregateFunction(type, - LogicalType::INTERVAL); - + return OP::template GetFunction(type, type); default: - throw NotImplementedException("Unimplemented Median Absolute Deviation aggregate"); + throw NotImplementedException("Unimplemented continuous quantile aggregate"); } } -unique_ptr BindMedianDecimal(ClientContext &context, AggregateFunction &function, - vector> &arguments) { - auto bind_data = BindMedian(context, function, arguments); +struct ScalarContinuousQuantile { + template + static AggregateFunction GetFunction(const LogicalType &input_type, const LogicalType &target_type) { + using STATE = QuantileState; + using OP = QuantileScalarOperation; + auto fun = + AggregateFunction::UnaryAggregateDestructor(input_type, target_type); + fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; + fun.window = AggregateFunction::UnaryWindow; + fun.window_init = OP::template WindowInit; + return fun; + } +}; + +struct ListContinuousQuantile { + template + static AggregateFunction GetFunction(const LogicalType &input_type, const LogicalType &target_type) { + using STATE = QuantileState; + using OP = QuantileListOperation; + auto fun = QuantileListAggregate(input_type, target_type); + fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; + fun.window = AggregateFunction::UnaryWindow; + fun.window_init = OP::template WindowInit; + return fun; + } +}; - function = GetDiscreteQuantileAggregateFunction(arguments[0]->return_type); - function.name = "median"; - function.serialize = QuantileBindData::SerializeDecimalDiscrete; - function.deserialize = QuantileBindData::Deserialize; - function.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - return bind_data; +AggregateFunction GetContinuousQuantile(const LogicalType &type) { + return GetContinuousQuantileTemplated(type); } -unique_ptr BindMedianAbsoluteDeviationDecimal(ClientContext &context, AggregateFunction &function, - vector> &arguments) { - function = GetMedianAbsoluteDeviationAggregateFunction(arguments[0]->return_type); - function.name = "mad"; - function.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - return BindMedian(context, function, arguments); +AggregateFunction GetContinuousQuantileList(const LogicalType &type) { + return GetContinuousQuantileTemplated(type); } +//===--------------------------------------------------------------------===// +// Quantile binding +//===--------------------------------------------------------------------===// static const Value &CheckQuantile(const Value &quantile_val) { if (quantile_val.IsNull()) { throw BinderException("QUANTILE parameter cannot be NULL"); @@ -1509,214 +584,246 @@ unique_ptr BindQuantile(ClientContext &context, AggregateFunction throw BinderException("QUANTILE argument must not be NULL"); } vector quantiles; - if (quantile_val.type().id() != LogicalTypeId::LIST) { - quantiles.push_back(CheckQuantile(quantile_val)); - } else { + switch (quantile_val.type().id()) { + case LogicalTypeId::LIST: for (const auto &element_val : ListValue::GetChildren(quantile_val)) { quantiles.push_back(CheckQuantile(element_val)); } + break; + case LogicalTypeId::ARRAY: + for (const auto &element_val : ArrayValue::GetChildren(quantile_val)) { + quantiles.push_back(CheckQuantile(element_val)); + } + break; + default: + quantiles.push_back(CheckQuantile(quantile_val)); + break; } Function::EraseArgument(function, arguments, arguments.size() - 1); return make_uniq(quantiles); } -void BindQuantileInner(AggregateFunction &function, const LogicalType &type, QuantileSerializationType quantile_type) { - switch (quantile_type) { - case QuantileSerializationType::DECIMAL_DISCRETE: - function = GetDiscreteQuantileAggregateFunction(type); - function.serialize = QuantileBindData::SerializeDecimalDiscrete; - function.name = "quantile_disc"; - break; - case QuantileSerializationType::DECIMAL_DISCRETE_LIST: - function = GetDiscreteQuantileListAggregateFunction(type); - function.serialize = QuantileBindData::SerializeDecimalDiscreteList; - function.name = "quantile_disc"; - break; - case QuantileSerializationType::DECIMAL_CONTINUOUS: - function = GetContinuousQuantileAggregateFunction(type); - function.serialize = QuantileBindData::SerializeDecimalContinuous; - function.name = "quantile_cont"; - break; - case QuantileSerializationType::DECIMAL_CONTINUOUS_LIST: - function = GetContinuousQuantileListAggregateFunction(type); - function.serialize = QuantileBindData::SerializeDecimalContinuousList; - function.name = "quantile_cont"; - break; - case QuantileSerializationType::NON_DECIMAL: - throw SerializationException("NON_DECIMAL is not a valid quantile_type for BindQuantileInner"); +//===--------------------------------------------------------------------===// +// Function definitions +//===--------------------------------------------------------------------===// +static bool CanInterpolate(const LogicalType &type) { + if (type.HasAlias()) { + return false; + } + switch (type.id()) { + case LogicalTypeId::DECIMAL: + case LogicalTypeId::SQLNULL: + case LogicalTypeId::TINYINT: + case LogicalTypeId::SMALLINT: + case LogicalTypeId::INTEGER: + case LogicalTypeId::UTINYINT: + case LogicalTypeId::USMALLINT: + case LogicalTypeId::UINTEGER: + case LogicalTypeId::UBIGINT: + case LogicalTypeId::BIGINT: + case LogicalTypeId::UHUGEINT: + case LogicalTypeId::HUGEINT: + case LogicalTypeId::FLOAT: + case LogicalTypeId::DOUBLE: + case LogicalTypeId::DATE: + case LogicalTypeId::TIMESTAMP: + case LogicalTypeId::TIMESTAMP_TZ: + case LogicalTypeId::TIMESTAMP_SEC: + case LogicalTypeId::TIMESTAMP_MS: + case LogicalTypeId::TIMESTAMP_NS: + case LogicalTypeId::TIME: + case LogicalTypeId::TIME_TZ: + return true; + default: + return false; } - function.deserialize = QuantileBindData::Deserialize; - function.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; } -unique_ptr BindDiscreteQuantileDecimal(ClientContext &context, AggregateFunction &function, - vector> &arguments) { - auto bind_data = BindQuantile(context, function, arguments); - BindQuantileInner(function, arguments[0]->return_type, QuantileSerializationType::DECIMAL_DISCRETE); - return bind_data; -} +struct MedianFunction { + static AggregateFunction GetAggregate(const LogicalType &type) { + auto fun = CanInterpolate(type) ? GetContinuousQuantile(type) : GetDiscreteQuantile(type); + fun.name = "median"; + fun.serialize = QuantileBindData::Serialize; + fun.deserialize = Deserialize; + return fun; + } -unique_ptr BindDiscreteQuantileDecimalList(ClientContext &context, AggregateFunction &function, - vector> &arguments) { - auto bind_data = BindQuantile(context, function, arguments); - BindQuantileInner(function, arguments[0]->return_type, QuantileSerializationType::DECIMAL_DISCRETE_LIST); - return bind_data; -} + static unique_ptr Deserialize(Deserializer &deserializer, AggregateFunction &function) { + auto bind_data = QuantileBindData::Deserialize(deserializer, function); -unique_ptr BindContinuousQuantileDecimal(ClientContext &context, AggregateFunction &function, - vector> &arguments) { - auto bind_data = BindQuantile(context, function, arguments); - BindQuantileInner(function, arguments[0]->return_type, QuantileSerializationType::DECIMAL_CONTINUOUS); - return bind_data; -} + auto &input_type = function.arguments[0]; + function = GetAggregate(input_type); + return bind_data; + } -unique_ptr BindContinuousQuantileDecimalList(ClientContext &context, AggregateFunction &function, - vector> &arguments) { - auto bind_data = BindQuantile(context, function, arguments); - BindQuantileInner(function, arguments[0]->return_type, QuantileSerializationType::DECIMAL_CONTINUOUS_LIST); - return bind_data; -} -static bool CanInterpolate(const LogicalType &type) { - switch (type.id()) { - case LogicalTypeId::INTERVAL: - case LogicalTypeId::VARCHAR: - case LogicalTypeId::ANY: - return false; - default: - return true; + static unique_ptr Bind(ClientContext &context, AggregateFunction &function, + vector> &arguments) { + function = GetAggregate(arguments[0]->return_type); + return make_uniq(Value::DECIMAL(int16_t(5), 2, 1)); } -} +}; -AggregateFunction GetMedianAggregate(const LogicalType &type) { - auto fun = CanInterpolate(type) ? GetContinuousQuantileAggregateFunction(type) - : GetDiscreteQuantileAggregateFunction(type); - fun.bind = BindMedian; - fun.serialize = QuantileBindData::Serialize; - fun.deserialize = QuantileBindData::Deserialize; - return fun; -} +struct DiscreteQuantileFunction { + static AggregateFunction GetAggregate(const LogicalType &type) { + auto fun = GetDiscreteQuantile(type); + fun.name = "quantile_disc"; + fun.bind = Bind; + fun.serialize = QuantileBindData::Serialize; + fun.deserialize = Deserialize; + // temporarily push an argument so we can bind the actual quantile + fun.arguments.emplace_back(LogicalType::DOUBLE); + fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; + return fun; + } -AggregateFunction GetDiscreteQuantileAggregate(const LogicalType &type) { - auto fun = GetDiscreteQuantileAggregateFunction(type); - fun.bind = BindQuantile; - fun.serialize = QuantileBindData::Serialize; - fun.deserialize = QuantileBindData::Deserialize; - // temporarily push an argument so we can bind the actual quantile - fun.arguments.emplace_back(LogicalType::DOUBLE); - fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - return fun; -} + static unique_ptr Deserialize(Deserializer &deserializer, AggregateFunction &function) { + auto bind_data = QuantileBindData::Deserialize(deserializer, function); -AggregateFunction GetDiscreteQuantileListAggregate(const LogicalType &type) { - auto fun = GetDiscreteQuantileListAggregateFunction(type); - fun.bind = BindQuantile; - fun.serialize = QuantileBindData::Serialize; - fun.deserialize = QuantileBindData::Deserialize; - // temporarily push an argument so we can bind the actual quantile - auto list_of_double = LogicalType::LIST(LogicalType::DOUBLE); - fun.arguments.push_back(list_of_double); - fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - return fun; -} + auto &input_type = function.arguments[0]; + function = GetAggregate(input_type); + return bind_data; + } -AggregateFunction GetContinuousQuantileAggregate(const LogicalType &type) { - auto fun = GetContinuousQuantileAggregateFunction(type); - fun.bind = BindQuantile; - fun.serialize = QuantileBindData::Serialize; - fun.deserialize = QuantileBindData::Deserialize; - // temporarily push an argument so we can bind the actual quantile - fun.arguments.emplace_back(LogicalType::DOUBLE); - fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - return fun; -} + static unique_ptr Bind(ClientContext &context, AggregateFunction &function, + vector> &arguments) { + function = GetAggregate(arguments[0]->return_type); + return BindQuantile(context, function, arguments); + } +}; -AggregateFunction GetContinuousQuantileListAggregate(const LogicalType &type) { - auto fun = GetContinuousQuantileListAggregateFunction(type); - fun.bind = BindQuantile; - fun.serialize = QuantileBindData::Serialize; - fun.deserialize = QuantileBindData::Deserialize; - // temporarily push an argument so we can bind the actual quantile - auto list_of_double = LogicalType::LIST(LogicalType::DOUBLE); - fun.arguments.push_back(list_of_double); - fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; - return fun; -} +struct DiscreteQuantileListFunction { + static AggregateFunction GetAggregate(const LogicalType &type) { + auto fun = GetDiscreteQuantileList(type); + fun.name = "quantile_disc"; + fun.bind = Bind; + fun.serialize = QuantileBindData::Serialize; + fun.deserialize = Deserialize; + // temporarily push an argument so we can bind the actual quantile + fun.arguments.emplace_back(LogicalType::LIST(LogicalType::DOUBLE)); + fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; + return fun; + } + + static unique_ptr Deserialize(Deserializer &deserializer, AggregateFunction &function) { + auto bind_data = QuantileBindData::Deserialize(deserializer, function); + + auto &input_type = function.arguments[0]; + function = GetAggregate(input_type); + return bind_data; + } + + static unique_ptr Bind(ClientContext &context, AggregateFunction &function, + vector> &arguments) { + function = GetAggregate(arguments[0]->return_type); + return BindQuantile(context, function, arguments); + } +}; + +struct ContinuousQuantileFunction { + static AggregateFunction GetAggregate(const LogicalType &type) { + auto fun = GetContinuousQuantile(type); + fun.name = "quantile_cont"; + fun.bind = Bind; + fun.serialize = QuantileBindData::Serialize; + fun.deserialize = Deserialize; + // temporarily push an argument so we can bind the actual quantile + fun.arguments.emplace_back(LogicalType::DOUBLE); + fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; + return fun; + } + + static unique_ptr Deserialize(Deserializer &deserializer, AggregateFunction &function) { + auto bind_data = QuantileBindData::Deserialize(deserializer, function); + + auto &input_type = function.arguments[0]; + function = GetAggregate(input_type); + return bind_data; + } + + static unique_ptr Bind(ClientContext &context, AggregateFunction &function, + vector> &arguments) { + function = GetAggregate(function.arguments[0].id() == LogicalTypeId::DECIMAL ? arguments[0]->return_type + : function.arguments[0]); + return BindQuantile(context, function, arguments); + } +}; + +struct ContinuousQuantileListFunction { + static AggregateFunction GetAggregate(const LogicalType &type) { + auto fun = GetContinuousQuantileList(type); + fun.name = "quantile_cont"; + fun.bind = Bind; + fun.serialize = QuantileBindData::Serialize; + fun.deserialize = Deserialize; + // temporarily push an argument so we can bind the actual quantile + auto list_of_double = LogicalType::LIST(LogicalType::DOUBLE); + fun.arguments.push_back(list_of_double); + fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; + return fun; + } + + static unique_ptr Deserialize(Deserializer &deserializer, AggregateFunction &function) { + auto bind_data = QuantileBindData::Deserialize(deserializer, function); + + auto &input_type = function.arguments[0]; + function = GetAggregate(input_type); + return bind_data; + } + + static unique_ptr Bind(ClientContext &context, AggregateFunction &function, + vector> &arguments) { + function = GetAggregate(function.arguments[0].id() == LogicalTypeId::DECIMAL ? arguments[0]->return_type + : function.arguments[0]); + return BindQuantile(context, function, arguments); + } +}; -AggregateFunction GetQuantileDecimalAggregate(const vector &arguments, const LogicalType &return_type, - bind_aggregate_function_t bind) { - AggregateFunction fun(arguments, return_type, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, bind); - fun.bind = bind; +template +AggregateFunction EmptyQuantileFunction(LogicalType input, LogicalType result, LogicalType extra_arg) { + AggregateFunction fun({std::move(input)}, std::move(result), nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + OP::Bind); + if (extra_arg.id() != LogicalTypeId::INVALID) { + fun.arguments.push_back(std::move(extra_arg)); + } fun.serialize = QuantileBindData::Serialize; - fun.deserialize = QuantileBindData::Deserialize; + fun.deserialize = OP::Deserialize; fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT; return fun; } -vector GetQuantileTypes() { - return {LogicalType::TINYINT, LogicalType::SMALLINT, - LogicalType::INTEGER, LogicalType::BIGINT, - LogicalType::HUGEINT, LogicalType::FLOAT, - LogicalType::DOUBLE, LogicalType::DATE, - LogicalType::TIMESTAMP, LogicalType::TIME, - LogicalType::TIMESTAMP_TZ, LogicalType::TIME_TZ, - LogicalType::INTERVAL, LogicalType::ANY_PARAMS(LogicalType::VARCHAR, 150)}; -} - AggregateFunctionSet MedianFun::GetFunctions() { - AggregateFunctionSet median("median"); - median.AddFunction( - GetQuantileDecimalAggregate({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, BindMedianDecimal)); - for (const auto &type : GetQuantileTypes()) { - median.AddFunction(GetMedianAggregate(type)); - } - return median; + AggregateFunctionSet set("median"); + set.AddFunction(EmptyQuantileFunction(LogicalType::ANY, LogicalType::ANY, LogicalTypeId::INVALID)); + return set; } AggregateFunctionSet QuantileDiscFun::GetFunctions() { - AggregateFunctionSet quantile_disc("quantile_disc"); - quantile_disc.AddFunction(GetQuantileDecimalAggregate({LogicalTypeId::DECIMAL, LogicalType::DOUBLE}, - LogicalTypeId::DECIMAL, BindDiscreteQuantileDecimal)); - quantile_disc.AddFunction( - GetQuantileDecimalAggregate({LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::DOUBLE)}, - LogicalType::LIST(LogicalTypeId::DECIMAL), BindDiscreteQuantileDecimalList)); - for (const auto &type : GetQuantileTypes()) { - quantile_disc.AddFunction(GetDiscreteQuantileAggregate(type)); - quantile_disc.AddFunction(GetDiscreteQuantileListAggregate(type)); - } - return quantile_disc; - // quantile + AggregateFunctionSet set("quantile_disc"); + set.AddFunction( + EmptyQuantileFunction(LogicalType::ANY, LogicalType::ANY, LogicalType::DOUBLE)); + set.AddFunction(EmptyQuantileFunction(LogicalType::ANY, LogicalType::ANY, + LogicalType::LIST(LogicalType::DOUBLE))); + return set; +} + +vector GetContinuousQuantileTypes() { + return {LogicalType::DOUBLE, LogicalType::DATE, LogicalType::TIMESTAMP, + LogicalType::TIME, LogicalType::TIMESTAMP_TZ, LogicalType::TIME_TZ}; } AggregateFunctionSet QuantileContFun::GetFunctions() { AggregateFunctionSet quantile_cont("quantile_cont"); - quantile_cont.AddFunction(GetQuantileDecimalAggregate({LogicalTypeId::DECIMAL, LogicalType::DOUBLE}, - LogicalTypeId::DECIMAL, BindContinuousQuantileDecimal)); - quantile_cont.AddFunction( - GetQuantileDecimalAggregate({LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::DOUBLE)}, - LogicalType::LIST(LogicalTypeId::DECIMAL), BindContinuousQuantileDecimalList)); - - for (const auto &type : GetQuantileTypes()) { - if (CanInterpolate(type)) { - quantile_cont.AddFunction(GetContinuousQuantileAggregate(type)); - quantile_cont.AddFunction(GetContinuousQuantileListAggregate(type)); - } + quantile_cont.AddFunction(EmptyQuantileFunction( + LogicalTypeId::DECIMAL, LogicalTypeId::DECIMAL, LogicalType::DOUBLE)); + quantile_cont.AddFunction(EmptyQuantileFunction( + LogicalTypeId::DECIMAL, LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::DOUBLE))); + for (const auto &type : GetContinuousQuantileTypes()) { + quantile_cont.AddFunction(EmptyQuantileFunction(type, type, LogicalType::DOUBLE)); + quantile_cont.AddFunction( + EmptyQuantileFunction(type, type, LogicalType::LIST(LogicalType::DOUBLE))); } return quantile_cont; } -AggregateFunctionSet MadFun::GetFunctions() { - AggregateFunctionSet mad("mad"); - mad.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, BindMedianAbsoluteDeviationDecimal)); - - const vector MAD_TYPES = {LogicalType::FLOAT, LogicalType::DOUBLE, LogicalType::DATE, - LogicalType::TIMESTAMP, LogicalType::TIME, LogicalType::TIMESTAMP_TZ, - LogicalType::TIME_TZ}; - for (const auto &type : MAD_TYPES) { - mad.AddFunction(GetMedianAbsoluteDeviationAggregateFunction(type)); - } - return mad; -} - } // namespace duckdb diff --git a/src/core_functions/aggregate/holistic/reservoir_quantile.cpp b/src/core_functions/aggregate/holistic/reservoir_quantile.cpp index 9e7c24c5952..b96100ded2f 100644 --- a/src/core_functions/aggregate/holistic/reservoir_quantile.cpp +++ b/src/core_functions/aggregate/holistic/reservoir_quantile.cpp @@ -325,6 +325,7 @@ unique_ptr BindReservoirQuantile(ClientContext &context, Aggregate } if (arguments.size() == 2) { + // remove the quantile argument so we can use the unary aggregate if (function.arguments.size() == 2) { Function::EraseArgument(function, arguments, arguments.size() - 1); } else { @@ -345,9 +346,14 @@ unique_ptr BindReservoirQuantile(ClientContext &context, Aggregate throw BinderException("Size of the RESERVOIR_QUANTILE sample must be bigger than 0"); } - // remove the quantile argument so we can use the unary aggregate - Function::EraseArgument(function, arguments, arguments.size() - 1); - Function::EraseArgument(function, arguments, arguments.size() - 1); + // remove the quantile arguments so we can use the unary aggregate + if (function.arguments.size() == arguments.size()) { + Function::EraseArgument(function, arguments, arguments.size() - 1); + Function::EraseArgument(function, arguments, arguments.size() - 1); + } else { + arguments.pop_back(); + arguments.pop_back(); + } return make_uniq(quantiles, NumericCast(sample_size)); } diff --git a/src/core_functions/aggregate/nested/CMakeLists.txt b/src/core_functions/aggregate/nested/CMakeLists.txt index a55e1e75d9c..14bfc8436bf 100644 --- a/src/core_functions/aggregate/nested/CMakeLists.txt +++ b/src/core_functions/aggregate/nested/CMakeLists.txt @@ -1,4 +1,5 @@ -add_library_unity(duckdb_aggr_nested OBJECT list.cpp histogram.cpp) +add_library_unity(duckdb_aggr_nested OBJECT binned_histogram.cpp list.cpp + histogram.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/core_functions/aggregate/nested/binned_histogram.cpp b/src/core_functions/aggregate/nested/binned_histogram.cpp new file mode 100644 index 00000000000..ee656fa48fd --- /dev/null +++ b/src/core_functions/aggregate/nested/binned_histogram.cpp @@ -0,0 +1,260 @@ +#include "duckdb/function/scalar/nested_functions.hpp" +#include "duckdb/core_functions/aggregate/nested_functions.hpp" +#include "duckdb/planner/expression/bound_aggregate_expression.hpp" +#include "duckdb/common/types/vector.hpp" +#include "duckdb/core_functions/aggregate/histogram_helpers.hpp" +#include "duckdb/common/algorithm.hpp" + +namespace duckdb { + +template +struct HistogramBinState { + using TYPE = T; + + unsafe_vector *bin_boundaries; + unsafe_vector *counts; + + void Initialize() { + bin_boundaries = nullptr; + counts = nullptr; + } + + void Destroy() { + if (bin_boundaries) { + delete bin_boundaries; + bin_boundaries = nullptr; + } + if (counts) { + delete counts; + counts = nullptr; + } + } + + bool IsSet() { + return bin_boundaries; + } + + template + void InitializeBins(Vector &bin_vector, idx_t count, idx_t pos, AggregateInputData &aggr_input) { + bin_boundaries = new unsafe_vector(); + counts = new unsafe_vector(); + UnifiedVectorFormat bin_data; + bin_vector.ToUnifiedFormat(count, bin_data); + auto bin_counts = UnifiedVectorFormat::GetData(bin_data); + auto bin_index = bin_data.sel->get_index(pos); + auto bin_list = bin_counts[bin_index]; + if (!bin_data.validity.RowIsValid(bin_index)) { + throw BinderException("Histogram bin list cannot be NULL"); + } + + auto &bin_child = ListVector::GetEntry(bin_vector); + UnifiedVectorFormat bin_child_data; + auto extra_state = OP::CreateExtraState(); + OP::PrepareData(bin_child, ListVector::GetListSize(bin_vector), extra_state, bin_child_data); + + bin_boundaries->reserve(bin_list.length); + for (idx_t i = 0; i < bin_list.length; i++) { + auto bin_child_idx = bin_child_data.sel->get_index(bin_list.offset + i); + if (!bin_child_data.validity.RowIsValid(bin_child_idx)) { + throw BinderException("Histogram bin entry cannot be NULL"); + } + bin_boundaries->push_back(OP::template ExtractValue(bin_child_data, bin_list.offset + i, aggr_input)); + } + // sort the bin boundaries + std::sort(bin_boundaries->begin(), bin_boundaries->end()); + // ensure there are no duplicate bin boundaries + for (idx_t i = 1; i < bin_boundaries->size(); i++) { + if (Equals::Operation((*bin_boundaries)[i - 1], (*bin_boundaries)[i])) { + bin_boundaries->erase_at(i); + i--; + } + } + + counts->resize(bin_list.length + 1); + } +}; + +struct HistogramBinFunction { + template + static void Initialize(STATE &state) { + state.Initialize(); + } + + template + static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { + state.Destroy(); + } + + static bool IgnoreNull() { + return true; + } + + template + static void Combine(const STATE &source, STATE &target, AggregateInputData &input_data) { + if (!source.bin_boundaries) { + // nothing to combine + return; + } + if (!target.bin_boundaries) { + // target does not have bin boundaries - copy everything over + target.bin_boundaries = new unsafe_vector(); + target.counts = new unsafe_vector(); + *target.bin_boundaries = *source.bin_boundaries; + *target.counts = *source.counts; + } else { + // both source and target have bin boundaries + if (*target.bin_boundaries != *source.bin_boundaries) { + throw NotImplementedException( + "Histogram - cannot combine histograms with different bin boundaries. " + "Bin boundaries must be the same for all histograms within the same group"); + } + if (target.counts->size() != source.counts->size()) { + throw InternalException("Histogram combine - bin boundaries are the same but counts are different"); + } + D_ASSERT(target.counts->size() == source.counts->size()); + for (idx_t bin_idx = 0; bin_idx < target.counts->size(); bin_idx++) { + (*target.counts)[bin_idx] += (*source.counts)[bin_idx]; + } + } + } +}; + +template +static void HistogramBinUpdateFunction(Vector inputs[], AggregateInputData &aggr_input, idx_t input_count, + Vector &state_vector, idx_t count) { + auto &input = inputs[0]; + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); + + auto &bin_vector = inputs[1]; + + auto extra_state = OP::CreateExtraState(); + UnifiedVectorFormat input_data; + OP::PrepareData(input, count, extra_state, input_data); + + auto states = UnifiedVectorFormat::GetData *>(sdata); + auto data = UnifiedVectorFormat::GetData(input_data); + for (idx_t i = 0; i < count; i++) { + auto idx = input_data.sel->get_index(i); + if (!input_data.validity.RowIsValid(idx)) { + continue; + } + auto &state = *states[sdata.sel->get_index(i)]; + if (!state.IsSet()) { + state.template InitializeBins(bin_vector, count, i, aggr_input); + } + auto entry = std::lower_bound(state.bin_boundaries->begin(), state.bin_boundaries->end(), data[idx]); + auto bin_entry = UnsafeNumericCast(entry - state.bin_boundaries->begin()); + ++(*state.counts)[bin_entry]; + } +} + +template +static void HistogramBinFinalizeFunction(Vector &state_vector, AggregateInputData &, Vector &result, idx_t count, + idx_t offset) { + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); + auto states = UnifiedVectorFormat::GetData *>(sdata); + + auto &mask = FlatVector::Validity(result); + auto old_len = ListVector::GetListSize(result); + idx_t new_entries = 0; + // figure out how much space we need + for (idx_t i = 0; i < count; i++) { + auto &state = *states[sdata.sel->get_index(i)]; + if (!state.bin_boundaries) { + continue; + } + new_entries += state.bin_boundaries->size(); + } + // reserve space in the list vector + ListVector::Reserve(result, old_len + new_entries); + auto &keys = MapVector::GetKeys(result); + auto &values = MapVector::GetValues(result); + auto list_entries = FlatVector::GetData(result); + auto count_entries = FlatVector::GetData(values); + + idx_t current_offset = old_len; + for (idx_t i = 0; i < count; i++) { + const auto rid = i + offset; + auto &state = *states[sdata.sel->get_index(i)]; + if (!state.bin_boundaries) { + mask.SetInvalid(rid); + continue; + } + + auto &list_entry = list_entries[rid]; + list_entry.offset = current_offset; + for (idx_t bin_idx = 0; bin_idx < state.bin_boundaries->size(); bin_idx++) { + OP::template HistogramFinalize((*state.bin_boundaries)[bin_idx], keys, current_offset); + count_entries[current_offset] = (*state.counts)[bin_idx]; + current_offset++; + } + list_entry.length = current_offset - list_entry.offset; + } + D_ASSERT(current_offset == old_len + new_entries); + ListVector::SetListSize(result, current_offset); + result.Verify(count); +} + +template +static AggregateFunction GetHistogramBinFunction(const LogicalType &type) { + using STATE_TYPE = HistogramBinState; + + auto struct_type = LogicalType::MAP(type, LogicalType::UBIGINT); + return AggregateFunction( + "histogram", {type, LogicalType::LIST(type)}, struct_type, AggregateFunction::StateSize, + AggregateFunction::StateInitialize, HistogramBinUpdateFunction, + AggregateFunction::StateCombine, HistogramBinFinalizeFunction, nullptr, + nullptr, AggregateFunction::StateDestroy); +} + +AggregateFunction GetHistogramBinFunction(const LogicalType &type) { + switch (type.InternalType()) { + case PhysicalType::BOOL: + return GetHistogramBinFunction(type); + case PhysicalType::UINT8: + return GetHistogramBinFunction(type); + case PhysicalType::UINT16: + return GetHistogramBinFunction(type); + case PhysicalType::UINT32: + return GetHistogramBinFunction(type); + case PhysicalType::UINT64: + return GetHistogramBinFunction(type); + case PhysicalType::INT8: + return GetHistogramBinFunction(type); + case PhysicalType::INT16: + return GetHistogramBinFunction(type); + case PhysicalType::INT32: + return GetHistogramBinFunction(type); + case PhysicalType::INT64: + return GetHistogramBinFunction(type); + case PhysicalType::FLOAT: + return GetHistogramBinFunction(type); + case PhysicalType::DOUBLE: + return GetHistogramBinFunction(type); + case PhysicalType::VARCHAR: + return GetHistogramBinFunction(type); + default: + return GetHistogramBinFunction(type); + } +} + +unique_ptr HistogramBinBindFunction(ClientContext &context, AggregateFunction &function, + vector> &arguments) { + for (auto &arg : arguments) { + if (arg->return_type.id() == LogicalTypeId::UNKNOWN) { + throw ParameterNotResolvedException(); + } + } + + function = GetHistogramBinFunction(arguments[0]->return_type); + return nullptr; +} + +AggregateFunction HistogramFun::BinnedHistogramFunction() { + return AggregateFunction("histogram", {LogicalType::ANY, LogicalType::LIST(LogicalType::ANY)}, LogicalTypeId::MAP, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, HistogramBinBindFunction, nullptr); +} + +} // namespace duckdb diff --git a/src/core_functions/aggregate/nested/functions.json b/src/core_functions/aggregate/nested/functions.json index 085daa8926f..56567b58ca3 100644 --- a/src/core_functions/aggregate/nested/functions.json +++ b/src/core_functions/aggregate/nested/functions.json @@ -5,7 +5,7 @@ "description": "Returns a LIST of STRUCTs with the fields bucket and count.", "example": "histogram(A)", "type": "aggregate_function_set", - "extra_functions": ["static AggregateFunction GetHistogramUnorderedMap(LogicalType &type);"] + "extra_functions": ["static AggregateFunction GetHistogramUnorderedMap(LogicalType &type);", "static AggregateFunction BinnedHistogramFunction();"] }, { "name": "list", diff --git a/src/core_functions/aggregate/nested/histogram.cpp b/src/core_functions/aggregate/nested/histogram.cpp index 2f7414340e9..f1c72f93ed2 100644 --- a/src/core_functions/aggregate/nested/histogram.cpp +++ b/src/core_functions/aggregate/nested/histogram.cpp @@ -1,57 +1,13 @@ #include "duckdb/function/scalar/nested_functions.hpp" #include "duckdb/core_functions/aggregate/nested_functions.hpp" -#include "duckdb/planner/expression/bound_aggregate_expression.hpp" -#include "duckdb/common/pair.hpp" -#include "duckdb/planner/expression/bound_function_expression.hpp" #include "duckdb/common/types/vector.hpp" +#include "duckdb/common/string_map_set.hpp" +#include "duckdb/core_functions/aggregate/histogram_helpers.hpp" +#include "duckdb/common/owning_string_map.hpp" namespace duckdb { -struct HistogramFunctor { - template > - static void HistogramUpdate(UnifiedVectorFormat &sdata, UnifiedVectorFormat &input_data, idx_t count) { - auto states = (HistogramAggState **)sdata.data; - for (idx_t i = 0; i < count; i++) { - if (input_data.validity.RowIsValid(input_data.sel->get_index(i))) { - auto &state = *states[sdata.sel->get_index(i)]; - if (!state.hist) { - state.hist = new MAP_TYPE(); - } - auto value = UnifiedVectorFormat::GetData(input_data); - (*state.hist)[value[input_data.sel->get_index(i)]]++; - } - } - } - - template - static Value HistogramFinalize(T first) { - return Value::CreateValue(first); - } -}; - -struct HistogramStringFunctor { - template > - static void HistogramUpdate(UnifiedVectorFormat &sdata, UnifiedVectorFormat &input_data, idx_t count) { - auto states = (HistogramAggState **)sdata.data; - auto input_strings = UnifiedVectorFormat::GetData(input_data); - for (idx_t i = 0; i < count; i++) { - if (input_data.validity.RowIsValid(input_data.sel->get_index(i))) { - auto &state = *states[sdata.sel->get_index(i)]; - if (!state.hist) { - state.hist = new MAP_TYPE(); - } - (*state.hist)[input_strings[input_data.sel->get_index(i)].GetString()]++; - } - } - } - - template - static Value HistogramFinalize(T first) { - string_t value = first; - return Value::CreateValue(value); - } -}; - +template struct HistogramFunction { template static void Initialize(STATE &state) { @@ -59,7 +15,7 @@ struct HistogramFunction { } template - static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { + static void Destroy(STATE &state, AggregateInputData &) { if (state.hist) { delete state.hist; } @@ -68,59 +24,97 @@ struct HistogramFunction { static bool IgnoreNull() { return true; } + + template + static void Combine(const STATE &source, STATE &target, AggregateInputData &input_data) { + if (!source.hist) { + return; + } + if (!target.hist) { + target.hist = MAP_TYPE::CreateEmpty(input_data.allocator); + } + for (auto &entry : *source.hist) { + (*target.hist)[entry.first] += entry.second; + } + } }; -template -static void HistogramUpdateFunction(Vector inputs[], AggregateInputData &, idx_t input_count, Vector &state_vector, - idx_t count) { +template +struct DefaultMapType { + using MAP_TYPE = TYPE; - D_ASSERT(input_count == 1); + static TYPE *CreateEmpty(ArenaAllocator &) { + return new TYPE(); + } +}; - auto &input = inputs[0]; - UnifiedVectorFormat sdata; - state_vector.ToUnifiedFormat(count, sdata); - UnifiedVectorFormat input_data; - input.ToUnifiedFormat(count, input_data); +template +struct StringMapType { + using MAP_TYPE = TYPE; - OP::template HistogramUpdate(sdata, input_data, count); -} + static TYPE *CreateEmpty(ArenaAllocator &allocator) { + return new TYPE(allocator); + } +}; -template -static void HistogramCombineFunction(Vector &state_vector, Vector &combined, AggregateInputData &, idx_t count) { +template +static void HistogramUpdateFunction(Vector inputs[], AggregateInputData &aggr_input, idx_t input_count, + Vector &state_vector, idx_t count) { + + D_ASSERT(input_count == 1); + auto &input = inputs[0]; UnifiedVectorFormat sdata; state_vector.ToUnifiedFormat(count, sdata); - auto states_ptr = (HistogramAggState **)sdata.data; - auto combined_ptr = FlatVector::GetData *>(combined); + auto extra_state = OP::CreateExtraState(); + UnifiedVectorFormat input_data; + OP::PrepareData(input, count, extra_state, input_data); + auto states = UnifiedVectorFormat::GetData *>(sdata); + auto input_values = UnifiedVectorFormat::GetData(input_data); for (idx_t i = 0; i < count; i++) { - auto &state = *states_ptr[sdata.sel->get_index(i)]; - if (!state.hist) { + auto idx = input_data.sel->get_index(i); + if (!input_data.validity.RowIsValid(idx)) { continue; } - if (!combined_ptr[i]->hist) { - combined_ptr[i]->hist = new MAP_TYPE(); - } - D_ASSERT(combined_ptr[i]->hist); - D_ASSERT(state.hist); - for (auto &entry : *state.hist) { - (*combined_ptr[i]->hist)[entry.first] += entry.second; + auto &state = *states[sdata.sel->get_index(i)]; + if (!state.hist) { + state.hist = MAP_TYPE::CreateEmpty(aggr_input.allocator); } + auto &input_value = input_values[idx]; + ++(*state.hist)[input_value]; } } template static void HistogramFinalizeFunction(Vector &state_vector, AggregateInputData &, Vector &result, idx_t count, idx_t offset) { + using HIST_STATE = HistogramAggState; UnifiedVectorFormat sdata; state_vector.ToUnifiedFormat(count, sdata); - auto states = (HistogramAggState **)sdata.data; + auto states = UnifiedVectorFormat::GetData(sdata); auto &mask = FlatVector::Validity(result); auto old_len = ListVector::GetListSize(result); - + idx_t new_entries = 0; + // figure out how much space we need + for (idx_t i = 0; i < count; i++) { + auto &state = *states[sdata.sel->get_index(i)]; + if (!state.hist) { + continue; + } + new_entries += state.hist->size(); + } + // reserve space in the list vector + ListVector::Reserve(result, old_len + new_entries); + auto &keys = MapVector::GetKeys(result); + auto &values = MapVector::GetValues(result); + auto list_entries = FlatVector::GetData(result); + auto count_entries = FlatVector::GetData(values); + + idx_t current_offset = old_len; for (idx_t i = 0; i < count; i++) { const auto rid = i + offset; auto &state = *states[sdata.sel->get_index(i)]; @@ -129,135 +123,112 @@ static void HistogramFinalizeFunction(Vector &state_vector, AggregateInputData & continue; } + auto &list_entry = list_entries[rid]; + list_entry.offset = current_offset; for (auto &entry : *state.hist) { - Value bucket_value = OP::template HistogramFinalize(entry.first); - auto count_value = Value::CreateValue(entry.second); - auto struct_value = - Value::STRUCT({std::make_pair("key", bucket_value), std::make_pair("value", count_value)}); - ListVector::PushBack(result, struct_value); + OP::template HistogramFinalize(entry.first, keys, current_offset); + count_entries[current_offset] = entry.second; + current_offset++; } - - auto list_struct_data = ListVector::GetData(result); - list_struct_data[rid].length = ListVector::GetListSize(result) - old_len; - list_struct_data[rid].offset = old_len; - old_len += list_struct_data[rid].length; + list_entry.length = current_offset - list_entry.offset; } + D_ASSERT(current_offset == old_len + new_entries); + ListVector::SetListSize(result, current_offset); result.Verify(count); } -unique_ptr HistogramBindFunction(ClientContext &context, AggregateFunction &function, - vector> &arguments) { - - D_ASSERT(arguments.size() == 1); - - if (arguments[0]->return_type.id() == LogicalTypeId::LIST || - arguments[0]->return_type.id() == LogicalTypeId::STRUCT || - arguments[0]->return_type.id() == LogicalTypeId::MAP) { - throw NotImplementedException("Unimplemented type for histogram %s", arguments[0]->return_type.ToString()); - } - auto child_type = function.arguments[0].id() == LogicalTypeId::ANY ? LogicalType::VARCHAR : function.arguments[0]; - auto struct_type = LogicalType::MAP(child_type, LogicalType::UBIGINT); - - function.return_type = struct_type; - return make_uniq(function.return_type); -} - -template > +template static AggregateFunction GetHistogramFunction(const LogicalType &type) { + using STATE_TYPE = HistogramAggState; + using HIST_FUNC = HistogramFunction; + + auto struct_type = LogicalType::MAP(type, LogicalType::UBIGINT); + return AggregateFunction( + "histogram", {type}, struct_type, AggregateFunction::StateSize, + AggregateFunction::StateInitialize, HistogramUpdateFunction, + AggregateFunction::StateCombine, HistogramFinalizeFunction, nullptr, + nullptr, AggregateFunction::StateDestroy); +} - using STATE_TYPE = HistogramAggState; - - return AggregateFunction("histogram", {type}, LogicalTypeId::MAP, AggregateFunction::StateSize, - AggregateFunction::StateInitialize, - HistogramUpdateFunction, HistogramCombineFunction, - HistogramFinalizeFunction, nullptr, HistogramBindFunction, - AggregateFunction::StateDestroy); +template +AggregateFunction GetMapTypeInternal(const LogicalType &type) { + return GetHistogramFunction(type); } template AggregateFunction GetMapType(const LogicalType &type) { if (IS_ORDERED) { - return GetHistogramFunction(type); + return GetMapTypeInternal>>(type); + } + return GetMapTypeInternal>>(type); +} + +template +AggregateFunction GetStringMapType(const LogicalType &type) { + if (IS_ORDERED) { + return GetMapTypeInternal>>(type); + } else { + return GetMapTypeInternal>>(type); } - return GetHistogramFunction>(type); } template AggregateFunction GetHistogramFunction(const LogicalType &type) { - switch (type.id()) { - case LogicalTypeId::BOOLEAN: + switch (type.InternalType()) { + case PhysicalType::BOOL: return GetMapType(type); - case LogicalTypeId::UTINYINT: + case PhysicalType::UINT8: return GetMapType(type); - case LogicalTypeId::USMALLINT: + case PhysicalType::UINT16: return GetMapType(type); - case LogicalTypeId::UINTEGER: + case PhysicalType::UINT32: return GetMapType(type); - case LogicalTypeId::UBIGINT: + case PhysicalType::UINT64: return GetMapType(type); - case LogicalTypeId::TINYINT: + case PhysicalType::INT8: return GetMapType(type); - case LogicalTypeId::SMALLINT: + case PhysicalType::INT16: return GetMapType(type); - case LogicalTypeId::INTEGER: + case PhysicalType::INT32: return GetMapType(type); - case LogicalTypeId::BIGINT: + case PhysicalType::INT64: return GetMapType(type); - case LogicalTypeId::FLOAT: + case PhysicalType::FLOAT: return GetMapType(type); - case LogicalTypeId::DOUBLE: + case PhysicalType::DOUBLE: return GetMapType(type); - case LogicalTypeId::TIMESTAMP: - return GetMapType(type); - case LogicalTypeId::TIMESTAMP_TZ: - return GetMapType(type); - case LogicalTypeId::TIMESTAMP_SEC: - return GetMapType(type); - case LogicalTypeId::TIMESTAMP_MS: - return GetMapType(type); - case LogicalTypeId::TIMESTAMP_NS: - return GetMapType(type); - case LogicalTypeId::TIME: - return GetMapType(type); - case LogicalTypeId::TIME_TZ: - return GetMapType(type); - case LogicalTypeId::DATE: - return GetMapType(type); - case LogicalTypeId::ANY: - return GetMapType(type); + case PhysicalType::VARCHAR: + return GetStringMapType(type); default: - throw InternalException("Unimplemented histogram aggregate"); + return GetStringMapType(type); + } +} + +template +unique_ptr HistogramBindFunction(ClientContext &context, AggregateFunction &function, + vector> &arguments) { + + D_ASSERT(arguments.size() == 1); + + if (arguments[0]->return_type.id() == LogicalTypeId::UNKNOWN) { + throw ParameterNotResolvedException(); } + function = GetHistogramFunction(arguments[0]->return_type); + return make_uniq(function.return_type); } AggregateFunctionSet HistogramFun::GetFunctions() { AggregateFunctionSet fun; - fun.AddFunction(GetHistogramFunction<>(LogicalType::BOOLEAN)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::UTINYINT)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::USMALLINT)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::UINTEGER)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::UBIGINT)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::TINYINT)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::SMALLINT)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::INTEGER)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::BIGINT)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::FLOAT)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::DOUBLE)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::TIMESTAMP)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::TIMESTAMP_TZ)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::TIMESTAMP_S)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::TIMESTAMP_MS)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::TIMESTAMP_NS)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::TIME)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::TIME_TZ)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::DATE)); - fun.AddFunction(GetHistogramFunction<>(LogicalType::ANY_PARAMS(LogicalType::VARCHAR))); + AggregateFunction histogram_function("histogram", {LogicalType::ANY}, LogicalTypeId::MAP, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, HistogramBindFunction, nullptr); + fun.AddFunction(HistogramFun::BinnedHistogramFunction()); + fun.AddFunction(histogram_function); return fun; } AggregateFunction HistogramFun::GetHistogramUnorderedMap(LogicalType &type) { - const auto &const_type = type; - return GetHistogramFunction(const_type); + return AggregateFunction("histogram", {LogicalType::ANY}, LogicalTypeId::MAP, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, HistogramBindFunction, nullptr); } } // namespace duckdb diff --git a/src/core_functions/function_list.cpp b/src/core_functions/function_list.cpp index 23bf8224256..433968917cc 100644 --- a/src/core_functions/function_list.cpp +++ b/src/core_functions/function_list.cpp @@ -65,7 +65,7 @@ static const StaticFunctionDefinition internal_functions[] = { DUCKDB_SCALAR_FUNCTION_ALIAS(AggregateFun), DUCKDB_SCALAR_FUNCTION(AliasFun), DUCKDB_SCALAR_FUNCTION_ALIAS(ApplyFun), - DUCKDB_AGGREGATE_FUNCTION_SET(ApproxCountDistinctFun), + DUCKDB_AGGREGATE_FUNCTION(ApproxCountDistinctFun), DUCKDB_AGGREGATE_FUNCTION_SET(ApproxQuantileFun), DUCKDB_AGGREGATE_FUNCTION_SET(ArgMaxFun), DUCKDB_AGGREGATE_FUNCTION_SET(ArgMaxNullFun), @@ -109,6 +109,7 @@ static const StaticFunctionDefinition internal_functions[] = { DUCKDB_AGGREGATE_FUNCTION_SET(BitstringAggFun), DUCKDB_AGGREGATE_FUNCTION(BoolAndFun), DUCKDB_AGGREGATE_FUNCTION(BoolOrFun), + DUCKDB_SCALAR_FUNCTION(CanCastImplicitlyFun), DUCKDB_SCALAR_FUNCTION(CardinalityFun), DUCKDB_SCALAR_FUNCTION(CbrtFun), DUCKDB_SCALAR_FUNCTION_SET(CeilFun), @@ -157,6 +158,7 @@ static const StaticFunctionDefinition internal_functions[] = { DUCKDB_SCALAR_FUNCTION_SET(EpochMsFun), DUCKDB_SCALAR_FUNCTION_SET(EpochNsFun), DUCKDB_SCALAR_FUNCTION_SET(EpochUsFun), + DUCKDB_SCALAR_FUNCTION_SET(EquiWidthBinsFun), DUCKDB_SCALAR_FUNCTION_SET(EraFun), DUCKDB_SCALAR_FUNCTION(ErrorFun), DUCKDB_SCALAR_FUNCTION(EvenFun), @@ -267,6 +269,7 @@ static const StaticFunctionDefinition internal_functions[] = { DUCKDB_AGGREGATE_FUNCTION_SET(ModeFun), DUCKDB_SCALAR_FUNCTION_SET(MonthFun), DUCKDB_SCALAR_FUNCTION_SET(MonthNameFun), + DUCKDB_SCALAR_FUNCTION_SET(NanosecondsFun), DUCKDB_SCALAR_FUNCTION_SET(NextAfterFun), DUCKDB_SCALAR_FUNCTION_ALIAS(NowFun), DUCKDB_SCALAR_FUNCTION_ALIAS(OrdFun), @@ -341,6 +344,7 @@ static const StaticFunctionDefinition internal_functions[] = { DUCKDB_AGGREGATE_FUNCTION_ALIAS(SumkahanFun), DUCKDB_SCALAR_FUNCTION(TanFun), DUCKDB_SCALAR_FUNCTION_SET(TimeBucketFun), + DUCKDB_SCALAR_FUNCTION(TimeTZSortKeyFun), DUCKDB_SCALAR_FUNCTION_SET(TimezoneFun), DUCKDB_SCALAR_FUNCTION_SET(TimezoneHourFun), DUCKDB_SCALAR_FUNCTION_SET(TimezoneMinuteFun), @@ -357,6 +361,7 @@ static const StaticFunctionDefinition internal_functions[] = { DUCKDB_SCALAR_FUNCTION(ToMillisecondsFun), DUCKDB_SCALAR_FUNCTION(ToMinutesFun), DUCKDB_SCALAR_FUNCTION(ToMonthsFun), + DUCKDB_SCALAR_FUNCTION(ToQuartersFun), DUCKDB_SCALAR_FUNCTION(ToSecondsFun), DUCKDB_SCALAR_FUNCTION(ToTimestampFun), DUCKDB_SCALAR_FUNCTION(ToWeeksFun), diff --git a/src/core_functions/scalar/array/array_functions.cpp b/src/core_functions/scalar/array/array_functions.cpp index 9840ba1cc72..324de46a4b0 100644 --- a/src/core_functions/scalar/array/array_functions.cpp +++ b/src/core_functions/scalar/array/array_functions.cpp @@ -208,6 +208,11 @@ static unique_ptr ArrayGenericBinaryBind(ClientContext &context, S auto &left_type = arguments[0]->return_type; auto &right_type = arguments[1]->return_type; + // mystery to me how anything non-array could ever end up here but it happened + if (left_type.id() != LogicalTypeId::ARRAY || right_type.id() != LogicalTypeId::ARRAY) { + throw InvalidInputException(StringUtil::Format("%s: Arguments must be arrays of FLOAT or DOUBLE", OP::NAME)); + } + auto left_size = ArrayType::GetSize(left_type); auto right_size = ArrayType::GetSize(right_type); if (left_size != right_size) { @@ -249,9 +254,9 @@ ScalarFunctionSet ArrayInnerProductFun::GetFunctions() { ScalarFunctionSet set("array_inner_product"); // Generic array inner product function for (auto &type : LogicalType::Real()) { - set.AddFunction(ScalarFunction({LogicalType::ARRAY(type), LogicalType::ARRAY(type)}, type, - ArrayGenericBinaryFunction, - ArrayGenericBinaryBind)); + set.AddFunction( + ScalarFunction({LogicalType::ARRAY(type, optional_idx()), LogicalType::ARRAY(type, optional_idx())}, type, + ArrayGenericBinaryFunction, ArrayGenericBinaryBind)); } return set; } @@ -260,8 +265,9 @@ ScalarFunctionSet ArrayDistanceFun::GetFunctions() { ScalarFunctionSet set("array_distance"); // Generic array distance function for (auto &type : LogicalType::Real()) { - set.AddFunction(ScalarFunction({LogicalType::ARRAY(type), LogicalType::ARRAY(type)}, type, - ArrayGenericBinaryFunction, ArrayGenericBinaryBind)); + set.AddFunction( + ScalarFunction({LogicalType::ARRAY(type, optional_idx()), LogicalType::ARRAY(type, optional_idx())}, type, + ArrayGenericBinaryFunction, ArrayGenericBinaryBind)); } return set; } @@ -270,9 +276,9 @@ ScalarFunctionSet ArrayCosineSimilarityFun::GetFunctions() { ScalarFunctionSet set("array_cosine_similarity"); // Generic array cosine similarity function for (auto &type : LogicalType::Real()) { - set.AddFunction(ScalarFunction({LogicalType::ARRAY(type), LogicalType::ARRAY(type)}, type, - ArrayGenericBinaryFunction, - ArrayGenericBinaryBind)); + set.AddFunction( + ScalarFunction({LogicalType::ARRAY(type, optional_idx()), LogicalType::ARRAY(type, optional_idx())}, type, + ArrayGenericBinaryFunction, ArrayGenericBinaryBind)); } return set; } diff --git a/src/core_functions/scalar/blob/create_sort_key.cpp b/src/core_functions/scalar/blob/create_sort_key.cpp index e4798667427..bcebe192fab 100644 --- a/src/core_functions/scalar/blob/create_sort_key.cpp +++ b/src/core_functions/scalar/blob/create_sort_key.cpp @@ -4,42 +4,10 @@ #include "duckdb/common/radix.hpp" #include "duckdb/planner/expression/bound_function_expression.hpp" #include "duckdb/planner/expression_binder.hpp" +#include "duckdb/core_functions/create_sort_key.hpp" namespace duckdb { -struct OrderModifiers { - OrderModifiers(OrderType order_type, OrderByNullType null_type) : order_type(order_type), null_type(null_type) { - } - - OrderType order_type; - OrderByNullType null_type; - - bool operator==(const OrderModifiers &other) const { - return order_type == other.order_type && null_type == other.null_type; - } - - static OrderModifiers Parse(const string &val) { - auto lcase = StringUtil::Replace(StringUtil::Lower(val), "_", " "); - OrderType order_type; - if (StringUtil::StartsWith(lcase, "asc")) { - order_type = OrderType::ASCENDING; - } else if (StringUtil::StartsWith(lcase, "desc")) { - order_type = OrderType::DESCENDING; - } else { - throw BinderException("create_sort_key modifier must start with either ASC or DESC"); - } - OrderByNullType null_type; - if (StringUtil::EndsWith(lcase, "nulls first")) { - null_type = OrderByNullType::NULLS_FIRST; - } else if (StringUtil::EndsWith(lcase, "nulls last")) { - null_type = OrderByNullType::NULLS_LAST; - } else { - throw BinderException("create_sort_key modifier must end with either NULLS FIRST or NULLS LAST"); - } - return OrderModifiers(order_type, null_type); - } -}; - struct CreateSortKeyBindData : public FunctionData { vector modifiers; @@ -76,7 +44,7 @@ unique_ptr CreateSortKeyBind(ClientContext &context, ScalarFunctio } // push collations for (idx_t i = 0; i < arguments.size(); i += 2) { - ExpressionBinder::PushCollation(context, arguments[i], arguments[i]->return_type, false); + ExpressionBinder::PushCollation(context, arguments[i], arguments[i]->return_type); } // check if all types are constant bool all_constant = true; @@ -109,7 +77,9 @@ struct SortKeyVectorData { static constexpr data_t BLOB_ESCAPE_CHARACTER = 1; SortKeyVectorData(Vector &input, idx_t size, OrderModifiers modifiers) : vec(input) { - input.ToUnifiedFormat(size, format); + if (size != 0) { + input.ToUnifiedFormat(size, format); + } this->size = size; null_byte = NULL_FIRST_BYTE; @@ -140,7 +110,7 @@ struct SortKeyVectorData { } case PhysicalType::LIST: { auto &child_entry = ListVector::GetEntry(input); - auto child_size = ListVector::GetListSize(input); + auto child_size = size == 0 ? 0 : ListVector::GetListSize(input); child_data.push_back(make_uniq(child_entry, child_size, child_modifiers)); break; } @@ -152,6 +122,9 @@ struct SortKeyVectorData { SortKeyVectorData(const SortKeyVectorData &other) = delete; SortKeyVectorData &operator=(const SortKeyVectorData &) = delete; + void Initialize() { + } + PhysicalType GetPhysicalType() { return vec.GetType().InternalType(); } @@ -176,6 +149,21 @@ struct SortKeyConstantOperator { Radix::EncodeData(result, input); return sizeof(T); } + + static idx_t Decode(const_data_ptr_t input, Vector &result, idx_t result_idx, bool flip_bytes) { + auto result_data = FlatVector::GetData(result); + if (flip_bytes) { + // descending order - so flip bytes + data_t flipped_bytes[sizeof(T)]; + for (idx_t b = 0; b < sizeof(T); b++) { + flipped_bytes[b] = ~input[b]; + } + result_data[result_idx] = Radix::DecodeData(flipped_bytes); + } else { + result_data[result_idx] = Radix::DecodeData(input); + } + return sizeof(T); + } }; struct SortKeyVarcharOperator { @@ -186,14 +174,39 @@ struct SortKeyVarcharOperator { } static idx_t Encode(data_ptr_t result, TYPE input) { - auto input_data = input.GetDataUnsafe(); + auto input_data = const_data_ptr_cast(input.GetDataUnsafe()); auto input_size = input.GetSize(); for (idx_t r = 0; r < input_size; r++) { - result[r] = UnsafeNumericCast(input_data[r] + 1); + result[r] = input_data[r] + 1; } result[input_size] = SortKeyVectorData::STRING_DELIMITER; // null-byte delimiter return input_size + 1; } + + static idx_t Decode(const_data_ptr_t input, Vector &result, idx_t result_idx, bool flip_bytes) { + auto result_data = FlatVector::GetData(result); + // iterate until we encounter the string delimiter to figure out the string length + data_t string_delimiter = SortKeyVectorData::STRING_DELIMITER; + if (flip_bytes) { + string_delimiter = ~string_delimiter; + } + idx_t pos; + for (pos = 0; input[pos] != string_delimiter; pos++) { + } + idx_t str_len = pos; + // now allocate the string data and fill it with the decoded data + result_data[result_idx] = StringVector::EmptyString(result, str_len); + auto str_data = data_ptr_cast(result_data[result_idx].GetDataWriteable()); + for (pos = 0; pos < str_len; pos++) { + if (flip_bytes) { + str_data[pos] = (~input[pos]) - 1; + } else { + str_data[pos] = input[pos] - 1; + } + } + result_data[result_idx].Finalize(); + return pos + 1; + } }; struct SortKeyBlobOperator { @@ -228,6 +241,42 @@ struct SortKeyBlobOperator { result[result_offset++] = SortKeyVectorData::STRING_DELIMITER; // null-byte delimiter return result_offset; } + + static idx_t Decode(const_data_ptr_t input, Vector &result, idx_t result_idx, bool flip_bytes) { + auto result_data = FlatVector::GetData(result); + // scan until we find the delimiter, keeping in mind escapes + data_t string_delimiter = SortKeyVectorData::STRING_DELIMITER; + data_t escape_character = SortKeyVectorData::BLOB_ESCAPE_CHARACTER; + if (flip_bytes) { + string_delimiter = ~string_delimiter; + escape_character = ~escape_character; + } + idx_t blob_len = 0; + idx_t pos; + for (pos = 0; input[pos] != string_delimiter; pos++) { + blob_len++; + if (input[pos] == escape_character) { + // escape character - skip the next byte + pos++; + } + } + // now allocate the blob data and fill it with the decoded data + result_data[result_idx] = StringVector::EmptyString(result, blob_len); + auto str_data = data_ptr_cast(result_data[result_idx].GetDataWriteable()); + for (idx_t input_pos = 0, result_pos = 0; input_pos < pos; input_pos++) { + if (input[input_pos] == escape_character) { + // if we encounter an escape character - copy the NEXT byte + input_pos++; + } + if (flip_bytes) { + str_data[result_pos++] = ~input[input_pos]; + } else { + str_data[result_pos++] = input[input_pos]; + } + } + result_data[result_idx].Finalize(); + return pos + 1; + } }; struct SortKeyListEntry { @@ -402,7 +451,7 @@ static void GetSortKeyLengthRecursive(SortKeyVectorData &vector_data, SortKeyChu } } -static void GetSortKeyLength(SortKeyVectorData &vector_data, SortKeyLengthInfo &result) { +static void GetSortKeyLength(SortKeyVectorData &vector_data, SortKeyLengthInfo &result, SortKeyChunk chunk) { // top-level method auto physical_type = vector_data.GetPhysicalType(); if (TypeIsConstantSize(physical_type)) { @@ -411,7 +460,11 @@ static void GetSortKeyLength(SortKeyVectorData &vector_data, SortKeyLengthInfo & result.constant_length += GetTypeIdSize(physical_type); return; } - GetSortKeyLengthRecursive(vector_data, SortKeyChunk(0, vector_data.size), result); + GetSortKeyLengthRecursive(vector_data, chunk, result); +} + +static void GetSortKeyLength(SortKeyVectorData &vector_data, SortKeyLengthInfo &result) { + GetSortKeyLength(vector_data, result, SortKeyChunk(0, vector_data.size)); } //===--------------------------------------------------------------------===// @@ -633,7 +686,7 @@ static void FinalizeSortData(Vector &result, idx_t size) { case LogicalTypeId::BIGINT: { auto result_data = FlatVector::GetData(result); for (idx_t r = 0; r < size; r++) { - result_data[r] = BSwap(result_data[r]); + result_data[r] = BSwap(result_data[r]); } break; } @@ -642,40 +695,259 @@ static void FinalizeSortData(Vector &result, idx_t size) { } } -static void CreateSortKeyFunction(DataChunk &args, ExpressionState &state, Vector &result) { - auto &bind_data = state.expr.Cast().bind_info->Cast(); - - // prepare the sort key data - vector> sort_key_data; - for (idx_t c = 0; c < args.ColumnCount(); c += 2) { - sort_key_data.push_back(make_uniq(args.data[c], args.size(), bind_data.modifiers[c / 2])); - } - +static void CreateSortKeyInternal(vector> &sort_key_data, + const vector &modifiers, Vector &result, idx_t row_count) { // two phases // a) get the length of the final sorted key // b) allocate the sorted key and construct // we do all of this in a vectorized manner - SortKeyLengthInfo key_lengths(args.size()); + SortKeyLengthInfo key_lengths(row_count); for (auto &vector_data : sort_key_data) { GetSortKeyLength(*vector_data, key_lengths); } // allocate the empty sort keys - auto data_pointers = unique_ptr(new data_ptr_t[args.size()]); - PrepareSortData(result, args.size(), key_lengths, data_pointers.get()); + auto data_pointers = unique_ptr(new data_ptr_t[row_count]); + PrepareSortData(result, row_count, key_lengths, data_pointers.get()); unsafe_vector offsets; - offsets.resize(args.size(), 0); + offsets.resize(row_count, 0); // now construct the sort keys for (idx_t c = 0; c < sort_key_data.size(); c++) { - SortKeyConstructInfo info(bind_data.modifiers[c], offsets, data_pointers.get()); + SortKeyConstructInfo info(modifiers[c], offsets, data_pointers.get()); ConstructSortKey(*sort_key_data[c], info); } - FinalizeSortData(result, args.size()); + FinalizeSortData(result, row_count); +} + +void CreateSortKeyHelpers::CreateSortKey(Vector &input, idx_t input_count, OrderModifiers order_modifier, + Vector &result) { + // prepare the sort key data + vector modifiers {order_modifier}; + vector> sort_key_data; + sort_key_data.push_back(make_uniq(input, input_count, order_modifier)); + + CreateSortKeyInternal(sort_key_data, modifiers, result, input_count); +} + +static void CreateSortKeyFunction(DataChunk &args, ExpressionState &state, Vector &result) { + auto &bind_data = state.expr.Cast().bind_info->Cast(); + + // prepare the sort key data + vector> sort_key_data; + for (idx_t c = 0; c < args.ColumnCount(); c += 2) { + sort_key_data.push_back(make_uniq(args.data[c], args.size(), bind_data.modifiers[c / 2])); + } + CreateSortKeyInternal(sort_key_data, bind_data.modifiers, result, args.size()); + if (args.AllConstant()) { result.SetVectorType(VectorType::CONSTANT_VECTOR); } } +//===--------------------------------------------------------------------===// +// Decode Sort Key +//===--------------------------------------------------------------------===// +struct DecodeSortKeyData { + explicit DecodeSortKeyData(OrderModifiers modifiers, string_t &sort_key) + : data(const_data_ptr_cast(sort_key.GetData())), size(sort_key.GetSize()), position(0), + flip_bytes(modifiers.order_type == OrderType::DESCENDING) { + } + + const_data_ptr_t data; + idx_t size; + idx_t position; + bool flip_bytes; +}; + +void DecodeSortKeyRecursive(DecodeSortKeyData &decode_data, SortKeyVectorData &vector_data, Vector &result, + idx_t result_idx); + +template +void TemplatedDecodeSortKey(DecodeSortKeyData &decode_data, SortKeyVectorData &vector_data, Vector &result, + idx_t result_idx) { + auto validity_byte = decode_data.data[decode_data.position]; + decode_data.position++; + if (validity_byte == vector_data.null_byte) { + // NULL value + FlatVector::Validity(result).SetInvalid(result_idx); + return; + } + idx_t increment = OP::Decode(decode_data.data + decode_data.position, result, result_idx, decode_data.flip_bytes); + decode_data.position += increment; +} + +void DecodeSortKeyStruct(DecodeSortKeyData &decode_data, SortKeyVectorData &vector_data, Vector &result, + idx_t result_idx) { + // check if the top-level is valid or not + auto validity_byte = decode_data.data[decode_data.position]; + decode_data.position++; + if (validity_byte == vector_data.null_byte) { + // entire struct is NULL + // note that we still deserialize the children + FlatVector::Validity(result).SetInvalid(result_idx); + } + // recurse into children + auto &child_entries = StructVector::GetEntries(result); + for (idx_t c = 0; c < child_entries.size(); c++) { + auto &child_entry = child_entries[c]; + DecodeSortKeyRecursive(decode_data, *vector_data.child_data[c], *child_entry, result_idx); + } +} + +void DecodeSortKeyList(DecodeSortKeyData &decode_data, SortKeyVectorData &vector_data, Vector &result, + idx_t result_idx) { + // check if the top-level is valid or not + auto validity_byte = decode_data.data[decode_data.position]; + decode_data.position++; + if (validity_byte == vector_data.null_byte) { + // entire list is NULL + FlatVector::Validity(result).SetInvalid(result_idx); + return; + } + // list is valid - decode child elements + // we don't know how many there will be + // decode child elements until we encounter the list delimiter + auto list_delimiter = SortKeyVectorData::LIST_DELIMITER; + if (decode_data.flip_bytes) { + list_delimiter = ~list_delimiter; + } + auto list_data = FlatVector::GetData(result); + auto &child_vector = ListVector::GetEntry(result); + // get the current list size + auto start_list_size = ListVector::GetListSize(result); + auto new_list_size = start_list_size; + // loop until we find the list delimiter + while (decode_data.data[decode_data.position] != list_delimiter) { + // found a valid entry here - decode it + // first reserve space for it + new_list_size++; + ListVector::Reserve(result, new_list_size); + + // now decode the entry + DecodeSortKeyRecursive(decode_data, *vector_data.child_data[0], child_vector, new_list_size - 1); + } + // skip the list delimiter + decode_data.position++; + // set the list_entry_t information and update the list size + list_data[result_idx].length = new_list_size - start_list_size; + list_data[result_idx].offset = start_list_size; + ListVector::SetListSize(result, new_list_size); +} + +void DecodeSortKeyArray(DecodeSortKeyData &decode_data, SortKeyVectorData &vector_data, Vector &result, + idx_t result_idx) { + // check if the top-level is valid or not + auto validity_byte = decode_data.data[decode_data.position]; + decode_data.position++; + if (validity_byte == vector_data.null_byte) { + // entire array is NULL + // note that we still read the child elements + FlatVector::Validity(result).SetInvalid(result_idx); + } + // array is valid - decode child elements + // arrays need to encode exactly array_size child elements + // however the decoded data still contains a list delimiter + // we use this delimiter to verify we successfully decoded the entire array + auto list_delimiter = SortKeyVectorData::LIST_DELIMITER; + if (decode_data.flip_bytes) { + list_delimiter = ~list_delimiter; + } + auto &child_vector = ArrayVector::GetEntry(result); + auto array_size = ArrayType::GetSize(result.GetType()); + + idx_t found_elements = 0; + auto child_start = array_size * result_idx; + // loop until we find the list delimiter + while (decode_data.data[decode_data.position] != list_delimiter) { + found_elements++; + if (found_elements > array_size) { + // error - found too many elements + break; + } + // now decode the entry + DecodeSortKeyRecursive(decode_data, *vector_data.child_data[0], child_vector, child_start + found_elements - 1); + } + // skip the list delimiter + decode_data.position++; + if (found_elements != array_size) { + throw InvalidInputException("Failed to decode array - found %d elements but expected %d", found_elements, + array_size); + } +} + +void DecodeSortKeyRecursive(DecodeSortKeyData &decode_data, SortKeyVectorData &vector_data, Vector &result, + idx_t result_idx) { + switch (result.GetType().InternalType()) { + case PhysicalType::BOOL: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::UINT8: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::INT8: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::UINT16: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::INT16: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::UINT32: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::INT32: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::UINT64: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::INT64: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::FLOAT: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::DOUBLE: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::INTERVAL: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::UINT128: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::INT128: + TemplatedDecodeSortKey>(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::VARCHAR: + if (vector_data.vec.GetType().id() == LogicalTypeId::VARCHAR) { + TemplatedDecodeSortKey(decode_data, vector_data, result, result_idx); + } else { + TemplatedDecodeSortKey(decode_data, vector_data, result, result_idx); + } + break; + case PhysicalType::STRUCT: + DecodeSortKeyStruct(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::LIST: + DecodeSortKeyList(decode_data, vector_data, result, result_idx); + break; + case PhysicalType::ARRAY: + DecodeSortKeyArray(decode_data, vector_data, result, result_idx); + break; + default: + throw NotImplementedException("Unsupported type %s in DecodeSortKey", vector_data.vec.GetType()); + } +} + +void CreateSortKeyHelpers::DecodeSortKey(string_t sort_key, Vector &result, idx_t result_idx, + OrderModifiers modifiers) { + SortKeyVectorData sort_key_data(result, 0, modifiers); + DecodeSortKeyData decode_data(modifiers, sort_key); + DecodeSortKeyRecursive(decode_data, sort_key_data, result, result_idx); +} + ScalarFunction CreateSortKeyFun::GetFunction() { ScalarFunction sort_key_function("create_sort_key", {LogicalType::ANY}, LogicalType::BLOB, CreateSortKeyFunction, CreateSortKeyBind); diff --git a/src/core_functions/scalar/date/date_part.cpp b/src/core_functions/scalar/date/date_part.cpp index 3d0b75775ce..c234e1e310e 100644 --- a/src/core_functions/scalar/date/date_part.cpp +++ b/src/core_functions/scalar/date/date_part.cpp @@ -2,6 +2,7 @@ #include "duckdb/common/case_insensitive_map.hpp" #include "duckdb/common/enums/date_part_specifier.hpp" #include "duckdb/common/exception.hpp" +#include "duckdb/common/exception/conversion_exception.hpp" #include "duckdb/common/string_util.hpp" #include "duckdb/common/enum_util.hpp" #include "duckdb/common/types/date.hpp" @@ -11,6 +12,7 @@ #include "duckdb/execution/expression_executor.hpp" #include "duckdb/function/scalar/nested_functions.hpp" #include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/common/types/date_lookup_cache.hpp" namespace duckdb { @@ -98,6 +100,20 @@ static unique_ptr PropagateSimpleDatePartStatistics(vector +struct DateCacheLocalState : public FunctionLocalState { + explicit DateCacheLocalState() { + } + + DateLookupCache cache; +}; + +template +unique_ptr InitDateCacheLocalState(ExpressionState &state, const BoundFunctionExpression &expr, + FunctionData *bind_data) { + return make_uniq>(); +} + struct DatePart { template static unique_ptr PropagateDatePartStatistics(vector &child_stats, @@ -403,6 +419,18 @@ struct DatePart { } }; + struct NanosecondsOperator { + template + static inline TR Operation(TA input) { + return MicrosecondsOperator::Operation(input) * Interval::NANOS_PER_MICRO; + } + + template + static unique_ptr PropagateStatistics(ClientContext &context, FunctionStatisticsInput &input) { + return PropagateSimpleDatePartStatistics<0, 60000000000>(input.child_stats); + } + }; + struct MicrosecondsOperator { template static inline TR Operation(TA input) { @@ -466,7 +494,7 @@ struct DatePart { struct EpochOperator { template static inline TR Operation(TA input) { - return Date::Epoch(input); + return TR(Date::Epoch(input)); } template @@ -720,7 +748,7 @@ struct DatePart { if (mask & EPOCH) { auto double_data = HasPartValue(double_values, DatePartSpecifier::EPOCH); if (double_data) { - double_data[idx] = Date::Epoch(input); + double_data[idx] = double(Date::Epoch(input)); } } if (mask & DOY) { @@ -732,25 +760,19 @@ struct DatePart { if (mask & JD) { auto double_data = HasPartValue(double_values, DatePartSpecifier::JULIAN_DAY); if (double_data) { - double_data[idx] = Date::ExtractJulianDay(input); + double_data[idx] = double(Date::ExtractJulianDay(input)); } } } }; }; -template -static void LastYearFunction(DataChunk &args, ExpressionState &state, Vector &result) { - int32_t last_year = 0; - UnaryExecutor::ExecuteWithNulls(args.data[0], result, args.size(), - [&](T input, ValidityMask &mask, idx_t idx) { - if (Value::IsFinite(input)) { - return Date::ExtractYear(input, &last_year); - } else { - mask.SetInvalid(idx); - return 0; - } - }); +template +static void DatePartCachedFunction(DataChunk &args, ExpressionState &state, Vector &result) { + auto &lstate = ExecuteFunctionState::GetFunctionState(state)->Cast>(); + UnaryExecutor::ExecuteWithNulls( + args.data[0], result, args.size(), + [&](T input, ValidityMask &mask, idx_t idx) { return lstate.cache.ExtractElement(input, mask, idx); }); } template <> @@ -1073,6 +1095,19 @@ int64_t DatePart::EpochMillisOperator::Operation(dtime_tz_t input) { return DatePart::EpochMillisOperator::Operation(input.time()); } +template <> +int64_t DatePart::NanosecondsOperator::Operation(timestamp_ns_t input) { + if (!Timestamp::IsFinite(input)) { + throw ConversionException("Can't get nanoseconds of infinite TIMESTAMP"); + } + date_t date; + dtime_t time; + int32_t nanos; + Timestamp::Convert(input, date, time, nanos); + // remove everything but the second & nanosecond part + return (time.micros % Interval::MICROS_PER_MINUTE) * Interval::NANOS_PER_MICRO + nanos; +} + template <> int64_t DatePart::MicrosecondsOperator::Operation(timestamp_t input) { D_ASSERT(Timestamp::IsFinite(input)); @@ -1189,7 +1224,7 @@ int64_t DatePart::HoursOperator::Operation(dtime_tz_t input) { template <> double DatePart::EpochOperator::Operation(timestamp_t input) { D_ASSERT(Timestamp::IsFinite(input)); - return Timestamp::GetEpochMicroSeconds(input) / double(Interval::MICROS_PER_SEC); + return double(Timestamp::GetEpochMicroSeconds(input)) / double(Interval::MICROS_PER_SEC); } template <> @@ -1203,7 +1238,7 @@ double DatePart::EpochOperator::Operation(interval_t input) { interval_epoch = interval_days * Interval::SECS_PER_DAY; // we add 0.25 days per year to sort of account for leap days interval_epoch += interval_years * (Interval::SECS_PER_DAY / 4); - return interval_epoch + input.micros / double(Interval::MICROS_PER_SEC); + return double(interval_epoch) + double(input.micros) / double(Interval::MICROS_PER_SEC); } // TODO: We can't propagate interval statistics because we can't easily compare interval_t for order. @@ -1215,7 +1250,7 @@ unique_ptr DatePart::EpochOperator::PropagateStatistics double DatePart::EpochOperator::Operation(dtime_t input) { - return input.micros / double(Interval::MICROS_PER_SEC); + return double(input.micros) / double(Interval::MICROS_PER_SEC); } template <> @@ -1301,7 +1336,7 @@ int64_t DatePart::TimezoneMinuteOperator::Operation(dtime_tz_t input) { template <> double DatePart::JulianDayOperator::Operation(date_t input) { - return Date::ExtractJulianDay(input); + return double(Date::ExtractJulianDay(input)); } template <> @@ -1659,14 +1694,15 @@ static unique_ptr DatePartBind(ClientContext &context, ScalarFunct return nullptr; } +template ScalarFunctionSet GetGenericDatePartFunction(scalar_function_t date_func, scalar_function_t ts_func, scalar_function_t interval_func, function_statistics_t date_stats, function_statistics_t ts_stats) { ScalarFunctionSet operator_set; - operator_set.AddFunction( - ScalarFunction({LogicalType::DATE}, LogicalType::BIGINT, std::move(date_func), nullptr, nullptr, date_stats)); - operator_set.AddFunction( - ScalarFunction({LogicalType::TIMESTAMP}, LogicalType::BIGINT, std::move(ts_func), nullptr, nullptr, ts_stats)); + operator_set.AddFunction(ScalarFunction({LogicalType::DATE}, LogicalType::BIGINT, std::move(date_func), nullptr, + nullptr, date_stats, DATE_CACHE)); + operator_set.AddFunction(ScalarFunction({LogicalType::TIMESTAMP}, LogicalType::BIGINT, std::move(ts_func), nullptr, + nullptr, ts_stats, DATE_CACHE)); operator_set.AddFunction(ScalarFunction({LogicalType::INTERVAL}, LogicalType::BIGINT, std::move(interval_func))); return operator_set; } @@ -1945,20 +1981,24 @@ struct StructDatePart { return result; } }; +template +ScalarFunctionSet GetCachedDatepartFunction() { + return GetGenericDatePartFunction>( + DatePartCachedFunction, DatePartCachedFunction, + ScalarFunction::UnaryFunction, OP::template PropagateStatistics, + OP::template PropagateStatistics); +} ScalarFunctionSet YearFun::GetFunctions() { - return GetGenericDatePartFunction(LastYearFunction, LastYearFunction, - ScalarFunction::UnaryFunction, - DatePart::YearOperator::PropagateStatistics, - DatePart::YearOperator::PropagateStatistics); + return GetCachedDatepartFunction(); } ScalarFunctionSet MonthFun::GetFunctions() { - return GetDatePartFunction(); + return GetCachedDatepartFunction(); } ScalarFunctionSet DayFun::GetFunctions() { - return GetDatePartFunction(); + return GetCachedDatepartFunction(); } ScalarFunctionSet DecadeFun::GetFunctions() { @@ -2065,6 +2105,26 @@ ScalarFunctionSet EpochMsFun::GetFunctions() { return operator_set; } +ScalarFunctionSet NanosecondsFun::GetFunctions() { + using OP = DatePart::NanosecondsOperator; + using TR = int64_t; + const LogicalType &result_type = LogicalType::BIGINT; + auto operator_set = GetTimePartFunction(); + + auto ns_func = DatePart::UnaryFunction; + auto ns_stats = OP::template PropagateStatistics; + operator_set.AddFunction( + ScalarFunction({LogicalType::TIMESTAMP_NS}, result_type, ns_func, nullptr, nullptr, ns_stats)); + + // TIMESTAMP WITH TIME ZONE has the same representation as TIMESTAMP so no need to defer to ICU + auto tstz_func = DatePart::UnaryFunction; + auto tstz_stats = OP::template PropagateStatistics; + operator_set.AddFunction( + ScalarFunction({LogicalType::TIMESTAMP_TZ}, LogicalType::BIGINT, tstz_func, nullptr, nullptr, tstz_stats)); + + return operator_set; +} + ScalarFunctionSet MicrosecondsFun::GetFunctions() { return GetTimePartFunction(); } diff --git a/src/core_functions/scalar/date/epoch.cpp b/src/core_functions/scalar/date/epoch.cpp index 3de2d50ac02..0944335deb9 100644 --- a/src/core_functions/scalar/date/epoch.cpp +++ b/src/core_functions/scalar/date/epoch.cpp @@ -28,4 +28,21 @@ ScalarFunction ToTimestampFun::GetFunction() { return ScalarFunction({LogicalType::DOUBLE}, LogicalType::TIMESTAMP_TZ, EpochSecFunction); } +struct TimeTZSortKeyOperator { + template + static RESULT_TYPE Operation(INPUT_TYPE input) { + return input.sort_key(); + } +}; + +static void TimeTZSortKeyFunction(DataChunk &input, ExpressionState &state, Vector &result) { + D_ASSERT(input.ColumnCount() == 1); + + UnaryExecutor::Execute(input.data[0], result, input.size()); +} + +ScalarFunction TimeTZSortKeyFun::GetFunction() { + return ScalarFunction({LogicalType::TIME_TZ}, LogicalType::UBIGINT, TimeTZSortKeyFunction); +} + } // namespace duckdb diff --git a/src/core_functions/scalar/date/functions.json b/src/core_functions/scalar/date/functions.json index 58f35b85e94..d84d2782d60 100644 --- a/src/core_functions/scalar/date/functions.json +++ b/src/core_functions/scalar/date/functions.json @@ -253,6 +253,14 @@ "example": "monthname(TIMESTAMP '1992-09-20')", "type": "scalar_function_set" }, + { + "struct": "NanosecondsFun", + "name": "nanosecond", + "parameters": "tsns", + "description": "Extract the nanosecond component from a date or timestamp", + "example": "nanosecond(timestamp_ns '2021-08-03 11:59:44.123456789') => 44123456789", + "type": "scalar_function_set" + }, { "name": "quarter", "parameters": "ts", @@ -312,6 +320,14 @@ "example": "timezone_minute(timestamp '2021-08-03 11:59:44.123456')", "type": "scalar_function_set" }, + { + "struct": "TimeTZSortKeyFun", + "name": "timetz_byte_comparable", + "parameters": "time_tz", + "description": "Converts a TIME WITH TIME ZONE to an integer sort key", + "example": "timetz_byte_comparable('18:18:16.21-07:00'::TIME_TZ)", + "type": "scalar_function" + }, { "name": "to_centuries", "parameters": "integer", @@ -375,6 +391,13 @@ "example": "to_months(5)", "type": "scalar_function" }, + { + "name": "to_quarters", + "parameters": "integer", + "description": "Construct a quarter interval", + "example": "to_quarters(5)", + "type": "scalar_function" + }, { "name": "to_seconds", "parameters": "double", diff --git a/src/core_functions/scalar/date/strftime.cpp b/src/core_functions/scalar/date/strftime.cpp index 01c907a5d89..8aa34d325c0 100644 --- a/src/core_functions/scalar/date/strftime.cpp +++ b/src/core_functions/scalar/date/strftime.cpp @@ -80,6 +80,19 @@ static void StrfTimeFunctionTimestamp(DataChunk &args, ExpressionState &state, V info.format.ConvertTimestampVector(args.data[REVERSED ? 1 : 0], result, args.size()); } +template +static void StrfTimeFunctionTimestampNS(DataChunk &args, ExpressionState &state, Vector &result) { + auto &func_expr = state.expr.Cast(); + auto &info = func_expr.bind_info->Cast(); + + if (info.is_null) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + ConstantVector::SetNull(result, true); + return; + } + info.format.ConvertTimestampNSVector(args.data[REVERSED ? 1 : 0], result, args.size()); +} + ScalarFunctionSet StrfTimeFun::GetFunctions() { ScalarFunctionSet strftime; @@ -87,10 +100,14 @@ ScalarFunctionSet StrfTimeFun::GetFunctions() { StrfTimeFunctionDate, StrfTimeBindFunction)); strftime.AddFunction(ScalarFunction({LogicalType::TIMESTAMP, LogicalType::VARCHAR}, LogicalType::VARCHAR, StrfTimeFunctionTimestamp, StrfTimeBindFunction)); + strftime.AddFunction(ScalarFunction({LogicalType::TIMESTAMP_NS, LogicalType::VARCHAR}, LogicalType::VARCHAR, + StrfTimeFunctionTimestampNS, StrfTimeBindFunction)); strftime.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::DATE}, LogicalType::VARCHAR, StrfTimeFunctionDate, StrfTimeBindFunction)); strftime.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::TIMESTAMP}, LogicalType::VARCHAR, StrfTimeFunctionTimestamp, StrfTimeBindFunction)); + strftime.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::TIMESTAMP_NS}, LogicalType::VARCHAR, + StrfTimeFunctionTimestampNS, StrfTimeBindFunction)); return strftime; } @@ -126,60 +143,29 @@ struct StrpTimeBindData : public FunctionData { } }; -static unique_ptr StrpTimeBindFunction(ClientContext &context, ScalarFunction &bound_function, - vector> &arguments) { - if (arguments[1]->HasParameter()) { - throw ParameterNotResolvedException(); - } - if (!arguments[1]->IsFoldable()) { - throw InvalidInputException(*arguments[0], "strptime format must be a constant"); - } - Value format_value = ExpressionExecutor::EvaluateScalar(context, *arguments[1]); - string format_string; - StrpTimeFormat format; - if (format_value.IsNull()) { - return make_uniq(format, format_string); - } else if (format_value.type().id() == LogicalTypeId::VARCHAR) { - format_string = format_value.ToString(); - format.format_specifier = format_string; - string error = StrTimeFormat::ParseFormatSpecifier(format_string, format); - if (!error.empty()) { - throw InvalidInputException(*arguments[0], "Failed to parse format specifier %s: %s", format_string, error); - } - if (format.HasFormatSpecifier(StrTimeSpecifier::UTC_OFFSET)) { - bound_function.return_type = LogicalType::TIMESTAMP_TZ; - } - return make_uniq(format, format_string); - } else if (format_value.type() == LogicalType::LIST(LogicalType::VARCHAR)) { - const auto &children = ListValue::GetChildren(format_value); - if (children.empty()) { - throw InvalidInputException(*arguments[0], "strptime format list must not be empty"); - } - vector format_strings; - vector formats; - for (const auto &child : children) { - format_string = child.ToString(); - format.format_specifier = format_string; - string error = StrTimeFormat::ParseFormatSpecifier(format_string, format); - if (!error.empty()) { - throw InvalidInputException(*arguments[0], "Failed to parse format specifier %s: %s", format_string, - error); - } - // If any format has UTC offsets, then we have to produce TSTZ - if (format.HasFormatSpecifier(StrTimeSpecifier::UTC_OFFSET)) { - bound_function.return_type = LogicalType::TIMESTAMP_TZ; - } - format_strings.emplace_back(format_string); - formats.emplace_back(format); - } - return make_uniq(formats, format_strings); - } else { - throw InvalidInputException(*arguments[0], "strptime format must be a string"); - } +template +inline T StrpTimeResult(StrpTimeFormat::ParseResult &parsed) { + return parsed.ToTimestamp(); +} + +template <> +inline timestamp_ns_t StrpTimeResult(StrpTimeFormat::ParseResult &parsed) { + return parsed.ToTimestampNS(); +} + +template +inline bool StrpTimeTryResult(StrpTimeFormat &format, string_t &input, T &result, string &error) { + return format.TryParseTimestamp(input, result, error); +} + +template <> +inline bool StrpTimeTryResult(StrpTimeFormat &format, string_t &input, timestamp_ns_t &result, string &error) { + return format.TryParseTimestampNS(input, result, error); } struct StrpTimeFunction { + template static void Parse(DataChunk &args, ExpressionState &state, Vector &result) { auto &func_expr = state.expr.Cast(); auto &info = func_expr.bind_info->Cast(); @@ -196,17 +182,18 @@ struct StrpTimeFunction { ConstantVector::SetNull(result, true); return; } - UnaryExecutor::Execute(args.data[0], result, args.size(), [&](string_t input) { + UnaryExecutor::Execute(args.data[0], result, args.size(), [&](string_t input) { StrpTimeFormat::ParseResult result; for (auto &format : info.formats) { if (format.Parse(input, result)) { - return result.ToTimestamp(); + return StrpTimeResult(result); } } throw InvalidInputException(result.FormatError(input, info.formats[0].format_specifier)); }); } + template static void TryParse(DataChunk &args, ExpressionState &state, Vector &result) { auto &func_expr = state.expr.Cast(); auto &info = func_expr.bind_info->Cast(); @@ -217,19 +204,94 @@ struct StrpTimeFunction { return; } - UnaryExecutor::ExecuteWithNulls( - args.data[0], result, args.size(), [&](string_t input, ValidityMask &mask, idx_t idx) { - timestamp_t result; - string error; - for (auto &format : info.formats) { - if (format.TryParseTimestamp(input, result, error)) { - return result; - } - } - - mask.SetInvalid(idx); - return timestamp_t(); - }); + UnaryExecutor::ExecuteWithNulls(args.data[0], result, args.size(), + [&](string_t input, ValidityMask &mask, idx_t idx) { + T result; + string error; + for (auto &format : info.formats) { + if (StrpTimeTryResult(format, input, result, error)) { + return result; + } + } + + mask.SetInvalid(idx); + return T(); + }); + } + + static unique_ptr Bind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + if (arguments[1]->HasParameter()) { + throw ParameterNotResolvedException(); + } + if (!arguments[1]->IsFoldable()) { + throw InvalidInputException(*arguments[0], "strptime format must be a constant"); + } + Value format_value = ExpressionExecutor::EvaluateScalar(context, *arguments[1]); + string format_string; + StrpTimeFormat format; + if (format_value.IsNull()) { + return make_uniq(format, format_string); + } else if (format_value.type().id() == LogicalTypeId::VARCHAR) { + format_string = format_value.ToString(); + format.format_specifier = format_string; + string error = StrTimeFormat::ParseFormatSpecifier(format_string, format); + if (!error.empty()) { + throw InvalidInputException(*arguments[0], "Failed to parse format specifier %s: %s", format_string, + error); + } + if (format.HasFormatSpecifier(StrTimeSpecifier::UTC_OFFSET)) { + bound_function.return_type = LogicalType::TIMESTAMP_TZ; + } else if (format.HasFormatSpecifier(StrTimeSpecifier::NANOSECOND_PADDED)) { + bound_function.return_type = LogicalType::TIMESTAMP_NS; + if (bound_function.name == "strptime") { + bound_function.function = Parse; + } else { + bound_function.function = TryParse; + } + } + return make_uniq(format, format_string); + } else if (format_value.type() == LogicalType::LIST(LogicalType::VARCHAR)) { + const auto &children = ListValue::GetChildren(format_value); + if (children.empty()) { + throw InvalidInputException(*arguments[0], "strptime format list must not be empty"); + } + vector format_strings; + vector formats; + bool has_offset = false; + bool has_nanos = false; + + for (const auto &child : children) { + format_string = child.ToString(); + format.format_specifier = format_string; + string error = StrTimeFormat::ParseFormatSpecifier(format_string, format); + if (!error.empty()) { + throw InvalidInputException(*arguments[0], "Failed to parse format specifier %s: %s", format_string, + error); + } + has_offset = has_offset || format.HasFormatSpecifier(StrTimeSpecifier::UTC_OFFSET); + has_nanos = has_nanos || format.HasFormatSpecifier(StrTimeSpecifier::NANOSECOND_PADDED); + format_strings.emplace_back(format_string); + formats.emplace_back(format); + } + + if (has_offset) { + // If any format has UTC offsets, then we have to produce TSTZ + bound_function.return_type = LogicalType::TIMESTAMP_TZ; + } else if (has_nanos) { + // If any format has nanoseconds, then we have to produce TSNS + // unless there is an offset, in which case we produce + bound_function.return_type = LogicalType::TIMESTAMP_NS; + if (bound_function.name == "strptime") { + bound_function.function = Parse; + } else { + bound_function.function = TryParse; + } + } + return make_uniq(formats, format_strings); + } else { + throw InvalidInputException(*arguments[0], "strptime format must be a string"); + } } }; @@ -238,12 +300,12 @@ ScalarFunctionSet StrpTimeFun::GetFunctions() { const auto list_type = LogicalType::LIST(LogicalType::VARCHAR); auto fun = ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::TIMESTAMP, - StrpTimeFunction::Parse, StrpTimeBindFunction); + StrpTimeFunction::Parse, StrpTimeFunction::Bind); fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; strptime.AddFunction(fun); - fun = ScalarFunction({LogicalType::VARCHAR, list_type}, LogicalType::TIMESTAMP, StrpTimeFunction::Parse, - StrpTimeBindFunction); + fun = ScalarFunction({LogicalType::VARCHAR, list_type}, LogicalType::TIMESTAMP, + StrpTimeFunction::Parse, StrpTimeFunction::Bind); fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; strptime.AddFunction(fun); return strptime; @@ -254,12 +316,12 @@ ScalarFunctionSet TryStrpTimeFun::GetFunctions() { const auto list_type = LogicalType::LIST(LogicalType::VARCHAR); auto fun = ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::TIMESTAMP, - StrpTimeFunction::TryParse, StrpTimeBindFunction); + StrpTimeFunction::TryParse, StrpTimeFunction::Bind); fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; try_strptime.AddFunction(fun); - fun = ScalarFunction({LogicalType::VARCHAR, list_type}, LogicalType::TIMESTAMP, StrpTimeFunction::TryParse, - StrpTimeBindFunction); + fun = ScalarFunction({LogicalType::VARCHAR, list_type}, LogicalType::TIMESTAMP, + StrpTimeFunction::TryParse, StrpTimeFunction::Bind); fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; try_strptime.AddFunction(fun); diff --git a/src/core_functions/scalar/date/to_interval.cpp b/src/core_functions/scalar/date/to_interval.cpp index 6f283b15fe5..d5ff5de6ff2 100644 --- a/src/core_functions/scalar/date/to_interval.cpp +++ b/src/core_functions/scalar/date/to_interval.cpp @@ -65,6 +65,20 @@ struct ToYearsOperator { } }; +struct ToQuartersOperator { + template + static inline TR Operation(TA input) { + interval_t result; + if (!TryMultiplyOperator::Operation(input, Interval::MONTHS_PER_QUARTER, + result.months)) { + throw OutOfRangeException("Interval value %d quarters out of range", input); + } + result.days = 0; + result.micros = 0; + return result; + } +}; + struct ToMonthsOperator { template static inline TR Operation(TA input) { @@ -170,6 +184,11 @@ ScalarFunction ToYearsFun::GetFunction() { ScalarFunction::UnaryFunction); } +ScalarFunction ToQuartersFun::GetFunction() { + return ScalarFunction({LogicalType::INTEGER}, LogicalType::INTERVAL, + ScalarFunction::UnaryFunction); +} + ScalarFunction ToMonthsFun::GetFunction() { return ScalarFunction({LogicalType::INTEGER}, LogicalType::INTERVAL, ScalarFunction::UnaryFunction); diff --git a/src/core_functions/scalar/debug/vector_type.cpp b/src/core_functions/scalar/debug/vector_type.cpp index 0f2dc5e2ed3..625273cde44 100644 --- a/src/core_functions/scalar/debug/vector_type.cpp +++ b/src/core_functions/scalar/debug/vector_type.cpp @@ -1,6 +1,5 @@ #include "duckdb/core_functions/scalar/debug_functions.hpp" -#include "duckdb/common/exception.hpp" #include "duckdb/common/vector_operations/vector_operations.hpp" #include "duckdb/planner/expression/bound_function_expression.hpp" #include "duckdb/common/enum_util.hpp" @@ -14,10 +13,12 @@ static void VectorTypeFunction(DataChunk &input, ExpressionState &state, Vector } ScalarFunction VectorTypeFun::GetFunction() { - return ScalarFunction("vector_type", // name of the function - {LogicalType::ANY}, // argument list - LogicalType::VARCHAR, // return type - VectorTypeFunction); + auto vector_type_fun = ScalarFunction("vector_type", // name of the function + {LogicalType::ANY}, // argument list + LogicalType::VARCHAR, // return type + VectorTypeFunction); + vector_type_fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + return vector_type_fun; } } // namespace duckdb diff --git a/src/core_functions/scalar/generic/CMakeLists.txt b/src/core_functions/scalar/generic/CMakeLists.txt index 642cb1e98eb..7b32ce5302c 100644 --- a/src/core_functions/scalar/generic/CMakeLists.txt +++ b/src/core_functions/scalar/generic/CMakeLists.txt @@ -2,6 +2,7 @@ add_library_unity( duckdb_func_generic OBJECT alias.cpp + can_implicitly_cast.cpp current_setting.cpp error.cpp hash.cpp diff --git a/src/core_functions/scalar/generic/can_implicitly_cast.cpp b/src/core_functions/scalar/generic/can_implicitly_cast.cpp new file mode 100644 index 00000000000..37b25d489b7 --- /dev/null +++ b/src/core_functions/scalar/generic/can_implicitly_cast.cpp @@ -0,0 +1,40 @@ +#include "duckdb/core_functions/scalar/generic_functions.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/function/cast/cast_function_set.hpp" +#include "duckdb/function/cast_rules.hpp" + +namespace duckdb { + +bool CanCastImplicitly(ClientContext &context, const LogicalType &source, const LogicalType &target) { + return CastFunctionSet::Get(context).ImplicitCastCost(source, target) >= 0; +} + +static void CanCastImplicitlyFunction(DataChunk &args, ExpressionState &state, Vector &result) { + auto &context = state.GetContext(); + bool can_cast_implicitly = CanCastImplicitly(context, args.data[0].GetType(), args.data[1].GetType()); + auto v = Value::BOOLEAN(can_cast_implicitly); + result.Reference(v); +} + +unique_ptr BindCanCastImplicitlyExpression(FunctionBindExpressionInput &input) { + auto &source_type = input.function.children[0]->return_type; + auto &target_type = input.function.children[1]->return_type; + if (source_type.id() == LogicalTypeId::UNKNOWN || source_type.id() == LogicalTypeId::SQLNULL || + target_type.id() == LogicalTypeId::UNKNOWN || target_type.id() == LogicalTypeId::SQLNULL) { + // parameter - unknown return type + return nullptr; + } + // emit a constant expression + return make_uniq( + Value::BOOLEAN(CanCastImplicitly(input.context, source_type, target_type))); +} + +ScalarFunction CanCastImplicitlyFun::GetFunction() { + auto fun = ScalarFunction({LogicalType::ANY, LogicalType::ANY}, LogicalType::BOOLEAN, CanCastImplicitlyFunction); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + fun.bind_expression = BindCanCastImplicitlyExpression; + return fun; +} + +} // namespace duckdb diff --git a/src/core_functions/scalar/generic/current_setting.cpp b/src/core_functions/scalar/generic/current_setting.cpp index 5eb5c91a545..43bbdcfbe0e 100644 --- a/src/core_functions/scalar/generic/current_setting.cpp +++ b/src/core_functions/scalar/generic/current_setting.cpp @@ -43,12 +43,11 @@ unique_ptr CurrentSettingBind(ClientContext &context, ScalarFuncti } Value key_val = ExpressionExecutor::EvaluateScalar(context, *key_child); D_ASSERT(key_val.type().id() == LogicalTypeId::VARCHAR); - auto &key_str = StringValue::Get(key_val); - if (key_val.IsNull() || key_str.empty()) { + if (key_val.IsNull() || StringValue::Get(key_val).empty()) { throw ParserException("Key name for current_setting needs to be neither NULL nor empty"); } - auto key = StringUtil::Lower(key_str); + auto key = StringUtil::Lower(StringValue::Get(key_val)); Value val; if (!context.TryGetCurrentSetting(key, val)) { Catalog::AutoloadExtensionByConfigName(context, key); diff --git a/src/core_functions/scalar/generic/functions.json b/src/core_functions/scalar/generic/functions.json index a04735f3a82..cc9b156c10e 100644 --- a/src/core_functions/scalar/generic/functions.json +++ b/src/core_functions/scalar/generic/functions.json @@ -56,6 +56,13 @@ "struct": "TypeOfFun", "type": "scalar_function" }, + { + "name": "can_cast_implicitly", + "parameters": "source_type,target_type", + "description": "Whether or not we can implicitly cast from the source type to the other type", + "example": "can_implicitly_cast(NULL::INTEGER, NULL::BIGINT)", + "type": "scalar_function" + }, { "name": "current_query", "parameters": "", @@ -105,5 +112,12 @@ "description": "Returns the currently active version of DuckDB in this format: v0.3.2\t", "example": "version()", "type": "scalar_function" + }, + { + "name": "equi_width_bins", + "parameters": "min,max,bin_count,nice_rounding", + "description": "Generates bin_count equi-width bins between the min and max. If enabled nice_rounding makes the numbers more readable/less jagged", + "example": "equi_width_bins(0, 10, 2, true)", + "type": "scalar_function_set" } ] diff --git a/src/core_functions/scalar/generic/typeof.cpp b/src/core_functions/scalar/generic/typeof.cpp index a1b01f8c0ca..b74a0cef520 100644 --- a/src/core_functions/scalar/generic/typeof.cpp +++ b/src/core_functions/scalar/generic/typeof.cpp @@ -1,4 +1,6 @@ #include "duckdb/core_functions/scalar/generic_functions.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" namespace duckdb { @@ -7,9 +9,20 @@ static void TypeOfFunction(DataChunk &args, ExpressionState &state, Vector &resu result.Reference(v); } +unique_ptr BindTypeOfFunctionExpression(FunctionBindExpressionInput &input) { + auto &return_type = input.function.children[0]->return_type; + if (return_type.id() == LogicalTypeId::UNKNOWN || return_type.id() == LogicalTypeId::SQLNULL) { + // parameter - unknown return type + return nullptr; + } + // emit a constant expression + return make_uniq(Value(return_type.ToString())); +} + ScalarFunction TypeOfFun::GetFunction() { auto fun = ScalarFunction({LogicalType::ANY}, LogicalType::VARCHAR, TypeOfFunction); fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + fun.bind_expression = BindTypeOfFunctionExpression; return fun; } diff --git a/src/core_functions/scalar/list/array_slice.cpp b/src/core_functions/scalar/list/array_slice.cpp index c04e037b4a7..3cc0960d96a 100644 --- a/src/core_functions/scalar/list/array_slice.cpp +++ b/src/core_functions/scalar/list/array_slice.cpp @@ -42,7 +42,7 @@ unique_ptr ListSliceBindData::Copy() const { template static idx_t CalculateSliceLength(idx_t begin, idx_t end, INDEX_TYPE step, bool svalid) { if (step < 0) { - step = abs(step); + step = AbsValue(step); } if (step == 0 && svalid) { throw InvalidInputException("Slice step cannot be zero"); @@ -163,6 +163,18 @@ static void ExecuteConstantSlice(Vector &result, Vector &str_vector, Vector &beg optional_ptr step_vector, const idx_t count, SelectionVector &sel, idx_t &sel_idx, optional_ptr result_child_vector, bool begin_is_empty, bool end_is_empty) { + + // check all this nullness early + auto str_valid = !ConstantVector::IsNull(str_vector); + auto begin_valid = !ConstantVector::IsNull(begin_vector); + auto end_valid = !ConstantVector::IsNull(end_vector); + auto step_valid = step_vector && !ConstantVector::IsNull(*step_vector); + + if (!str_valid || !begin_valid || !end_valid || (step_vector && !step_valid)) { + ConstantVector::SetNull(result, true); + return; + } + auto result_data = ConstantVector::GetData(result); auto str_data = ConstantVector::GetData(str_vector); auto begin_data = ConstantVector::GetData(begin_vector); @@ -180,20 +192,15 @@ static void ExecuteConstantSlice(Vector &result, Vector &str_vector, Vector &beg end = begin_is_empty ? ValueLength(str) : end; } - auto str_valid = !ConstantVector::IsNull(str_vector); - auto begin_valid = !ConstantVector::IsNull(begin_vector); - auto end_valid = !ConstantVector::IsNull(end_vector); - auto step_valid = step_vector && !ConstantVector::IsNull(*step_vector); - // Clamp offsets bool clamp_result = false; - if (str_valid && begin_valid && end_valid && (step_valid || step == 1)) { + if (step_valid || step == 1) { clamp_result = ClampSlice(str, begin, end); } idx_t sel_length = 0; bool sel_valid = false; - if (step_vector && step_valid && str_valid && begin_valid && end_valid && step != 1 && end - begin > 0) { + if (step_valid && step != 1 && end - begin > 0) { sel_length = CalculateSliceLength(UnsafeNumericCast(begin), UnsafeNumericCast(end), step, step_valid); sel.Initialize(sel_length); @@ -201,7 +208,7 @@ static void ExecuteConstantSlice(Vector &result, Vector &str_vector, Vector &beg } // Try to slice - if (!str_valid || !begin_valid || !end_valid || (step_vector && !step_valid) || !clamp_result) { + if (!clamp_result) { ConstantVector::SetNull(result, true); } else if (step == 1) { result_data[0] = SliceValue(result, str, begin, end); diff --git a/src/core_functions/scalar/list/list_aggregates.cpp b/src/core_functions/scalar/list/list_aggregates.cpp index fe7a95fcb11..61686175a4b 100644 --- a/src/core_functions/scalar/list/list_aggregates.cpp +++ b/src/core_functions/scalar/list/list_aggregates.cpp @@ -10,6 +10,8 @@ #include "duckdb/planner/expression/bound_cast_expression.hpp" #include "duckdb/planner/expression_binder.hpp" #include "duckdb/function/function_binder.hpp" +#include "duckdb/core_functions/create_sort_key.hpp" +#include "duckdb/common/owning_string_map.hpp" namespace duckdb { @@ -93,16 +95,23 @@ struct StateVector { struct FinalizeValueFunctor { template - static Value FinalizeValue(T first) { - return Value::CreateValue(first); + static void HistogramFinalize(T value, Vector &result, idx_t offset) { + FlatVector::GetData(result)[offset] = value; } }; struct FinalizeStringValueFunctor { template - static Value FinalizeValue(T first) { - string_t value = first; - return Value::CreateValue(value); + static void HistogramFinalize(T value, Vector &result, idx_t offset) { + FlatVector::GetData(result)[offset] = StringVector::AddStringOrBlob(result, value); + } +}; + +struct FinalizeGenericValueFunctor { + template + static void HistogramFinalize(T value, Vector &result, idx_t offset) { + CreateSortKeyHelpers::DecodeSortKey(value, result, offset, + OrderModifiers(OrderType::ASCENDING, OrderByNullType::NULLS_LAST)); } }; @@ -115,32 +124,44 @@ struct AggregateFunctor { struct DistinctFunctor { template > static void ListExecuteFunction(Vector &result, Vector &state_vector, idx_t count) { - UnifiedVectorFormat sdata; state_vector.ToUnifiedFormat(count, sdata); - auto states = (HistogramAggState **)sdata.data; - - auto result_data = FlatVector::GetData(result); + auto states = UnifiedVectorFormat::GetData *>(sdata); - idx_t offset = 0; + auto old_len = ListVector::GetListSize(result); + idx_t new_entries = 0; + // figure out how much space we need for (idx_t i = 0; i < count; i++) { - - auto state = states[sdata.sel->get_index(i)]; - result_data[i].offset = offset; - - if (!state->hist) { - result_data[i].length = 0; + auto &state = *states[sdata.sel->get_index(i)]; + if (!state.hist) { continue; } + new_entries += state.hist->size(); + } + // reserve space in the list vector + ListVector::Reserve(result, old_len + new_entries); + auto &child_elements = ListVector::GetEntry(result); + auto list_entries = FlatVector::GetData(result); - result_data[i].length = state->hist->size(); - offset += state->hist->size(); + idx_t current_offset = old_len; + for (idx_t i = 0; i < count; i++) { + const auto rid = i; + auto &state = *states[sdata.sel->get_index(i)]; + auto &list_entry = list_entries[rid]; + list_entry.offset = current_offset; + if (!state.hist) { + list_entry.length = 0; + continue; + } - for (auto &entry : *state->hist) { - Value bucket_value = OP::template FinalizeValue(entry.first); - ListVector::PushBack(result, bucket_value); + for (auto &entry : *state.hist) { + OP::template HistogramFinalize(entry.first, child_elements, current_offset); + current_offset++; } + list_entry.length = current_offset - list_entry.offset; } + D_ASSERT(current_offset == old_len + new_entries); + ListVector::SetListSize(result, current_offset); result.Verify(count); } }; @@ -148,13 +169,11 @@ struct DistinctFunctor { struct UniqueFunctor { template > static void ListExecuteFunction(Vector &result, Vector &state_vector, idx_t count) { - UnifiedVectorFormat sdata; state_vector.ToUnifiedFormat(count, sdata); - auto states = (HistogramAggState **)sdata.data; + auto states = UnifiedVectorFormat::GetData *>(sdata); auto result_data = FlatVector::GetData(result); - for (idx_t i = 0; i < count; i++) { auto state = states[sdata.sel->get_index(i)]; @@ -163,7 +182,6 @@ struct UniqueFunctor { result_data[i] = 0; continue; } - result_data[i] = state->hist->size(); } result.Verify(count); @@ -305,49 +323,12 @@ static void ListAggregatesFunction(DataChunk &args, ExpressionState &state, Vect result, state_vector.state_vector, count); break; case PhysicalType::INT32: - if (key_type.id() == LogicalTypeId::DATE) { - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - } else { - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - } + FUNCTION_FUNCTOR::template ListExecuteFunction( + result, state_vector.state_vector, count); break; case PhysicalType::INT64: - switch (key_type.id()) { - case LogicalTypeId::TIME: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case LogicalTypeId::TIME_TZ: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case LogicalTypeId::TIMESTAMP: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case LogicalTypeId::TIMESTAMP_MS: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case LogicalTypeId::TIMESTAMP_NS: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case LogicalTypeId::TIMESTAMP_SEC: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case LogicalTypeId::TIMESTAMP_TZ: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - default: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - } + FUNCTION_FUNCTOR::template ListExecuteFunction( + result, state_vector.state_vector, count); break; case PhysicalType::FLOAT: FUNCTION_FUNCTOR::template ListExecuteFunction( @@ -358,11 +339,15 @@ static void ListAggregatesFunction(DataChunk &args, ExpressionState &state, Vect result, state_vector.state_vector, count); break; case PhysicalType::VARCHAR: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); + FUNCTION_FUNCTOR::template ListExecuteFunction>(result, state_vector.state_vector, + count); break; default: - throw InternalException("Unimplemented histogram aggregate"); + FUNCTION_FUNCTOR::template ListExecuteFunction>(result, state_vector.state_vector, + count); + break; } } @@ -486,8 +471,7 @@ static unique_ptr ListAggregatesBind(ClientContext &context, Scala // create the unordered map histogram function D_ASSERT(best_function.arguments.size() == 1); - auto key_type = best_function.arguments[0]; - auto aggr_function = HistogramFun::GetHistogramUnorderedMap(key_type); + auto aggr_function = HistogramFun::GetHistogramUnorderedMap(child_type); return ListAggregatesBindFunction(context, bound_function, child_type, aggr_function, arguments); } diff --git a/src/core_functions/scalar/list/list_sort.cpp b/src/core_functions/scalar/list/list_sort.cpp index f206c509323..0fbe54ba999 100644 --- a/src/core_functions/scalar/list/list_sort.cpp +++ b/src/core_functions/scalar/list/list_sort.cpp @@ -130,8 +130,6 @@ static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &re // get the child vector auto lists_size = ListVector::GetListSize(sort_result_vec); auto &child_vector = ListVector::GetEntry(sort_result_vec); - UnifiedVectorFormat child_data; - child_vector.ToUnifiedFormat(lists_size, child_data); // get the lists data UnifiedVectorFormat lists_data; diff --git a/src/core_functions/scalar/list/list_value.cpp b/src/core_functions/scalar/list/list_value.cpp index e2ae537fb72..38e50f1dda0 100644 --- a/src/core_functions/scalar/list/list_value.cpp +++ b/src/core_functions/scalar/list/list_value.cpp @@ -11,17 +11,49 @@ namespace duckdb { -static void ListValueFunction(DataChunk &args, ExpressionState &state, Vector &result) { - D_ASSERT(result.GetType().id() == LogicalTypeId::LIST); - auto &child_type = ListType::GetChildType(result.GetType()); +struct ListValueAssign { + template + static T Assign(const T &input, Vector &result) { + return input; + } +}; - result.SetVectorType(VectorType::CONSTANT_VECTOR); - for (idx_t i = 0; i < args.ColumnCount(); i++) { - if (args.data[i].GetVectorType() != VectorType::CONSTANT_VECTOR) { - result.SetVectorType(VectorType::FLAT_VECTOR); +struct ListValueStringAssign { + template + static T Assign(const T &input, Vector &result) { + return StringVector::AddStringOrBlob(result, input); + } +}; + +template +static void TemplatedListValueFunction(DataChunk &args, Vector &result) { + idx_t list_size = args.ColumnCount(); + ListVector::Reserve(result, args.size() * list_size); + auto result_data = FlatVector::GetData(result); + auto &list_child = ListVector::GetEntry(result); + auto child_data = FlatVector::GetData(list_child); + auto &child_validity = FlatVector::Validity(list_child); + + auto unified_format = args.ToUnifiedFormat(); + for (idx_t r = 0; r < args.size(); r++) { + for (idx_t c = 0; c < list_size; c++) { + auto input_idx = unified_format[c].sel->get_index(r); + auto result_idx = r * list_size + c; + auto input_data = UnifiedVectorFormat::GetData(unified_format[c]); + if (unified_format[c].validity.RowIsValid(input_idx)) { + child_data[result_idx] = OP::template Assign(input_data[input_idx], list_child); + } else { + child_validity.SetInvalid(result_idx); + } } + result_data[r].offset = r * list_size; + result_data[r].length = list_size; } + ListVector::SetListSize(result, args.size() * list_size); +} +static void TemplatedListValueFunctionFallback(DataChunk &args, Vector &result) { + auto &child_type = ListType::GetChildType(result.GetType()); auto result_data = FlatVector::GetData(result); for (idx_t i = 0; i < args.size(); i++) { result_data[i].offset = ListVector::GetListSize(result); @@ -31,7 +63,74 @@ static void ListValueFunction(DataChunk &args, ExpressionState &state, Vector &r } result_data[i].length = args.ColumnCount(); } - result.Verify(args.size()); +} + +static void ListValueFunction(DataChunk &args, ExpressionState &state, Vector &result) { + D_ASSERT(result.GetType().id() == LogicalTypeId::LIST); + result.SetVectorType(VectorType::CONSTANT_VECTOR); + for (idx_t i = 0; i < args.ColumnCount(); i++) { + if (args.data[i].GetVectorType() != VectorType::CONSTANT_VECTOR) { + result.SetVectorType(VectorType::FLAT_VECTOR); + } + } + if (args.ColumnCount() == 0) { + // no columns - early out - result is a constant empty list + auto result_data = FlatVector::GetData(result); + result_data[0].length = 0; + result_data[0].offset = 0; + result.SetVectorType(VectorType::CONSTANT_VECTOR); + return; + } + auto &result_type = ListVector::GetEntry(result).GetType(); + switch (result_type.InternalType()) { + case PhysicalType::BOOL: + case PhysicalType::INT8: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::INT16: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::INT32: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::INT64: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::UINT8: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::UINT16: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::UINT32: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::UINT64: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::INT128: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::UINT128: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::FLOAT: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::DOUBLE: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::INTERVAL: + TemplatedListValueFunction(args, result); + break; + case PhysicalType::VARCHAR: + TemplatedListValueFunction(args, result); + break; + default: { + TemplatedListValueFunctionFallback(args, result); + break; + } + } } template diff --git a/src/core_functions/scalar/map/map_concat.cpp b/src/core_functions/scalar/map/map_concat.cpp index 1a6a270269a..b3ffc17400d 100644 --- a/src/core_functions/scalar/map/map_concat.cpp +++ b/src/core_functions/scalar/map/map_concat.cpp @@ -61,14 +61,20 @@ static void MapConcatFunction(DataChunk &args, ExpressionState &state, Vector &r auto &result_entry = result_data[i]; vector index_to_map; vector keys_list; + bool all_null = true; for (idx_t map_idx = 0; map_idx < map_count; map_idx++) { if (args.data[map_idx].GetType().id() == LogicalTypeId::SQLNULL) { continue; } - auto &map_format = map_formats[map_idx]; - auto &keys = MapVector::GetKeys(args.data[map_idx]); + auto &map_format = map_formats[map_idx]; auto index = map_format.sel->get_index(i); + if (!map_format.validity.RowIsValid(index)) { + continue; + } + + all_null = false; + auto &keys = MapVector::GetKeys(args.data[map_idx]); auto entry = UnifiedVectorFormat::GetData(map_format)[index]; // Update the list for this row @@ -89,6 +95,15 @@ static void MapConcatFunction(DataChunk &args, ExpressionState &state, Vector &r } } } + + result_entry.offset = ListVector::GetListSize(result); + result_entry.length = keys_list.size(); + if (all_null) { + D_ASSERT(keys_list.empty() && index_to_map.empty()); + FlatVector::SetNull(result, i, true); + continue; + } + vector values_list; D_ASSERT(keys_list.size() == index_to_map.size()); // Get the values from the mapping @@ -98,8 +113,6 @@ static void MapConcatFunction(DataChunk &args, ExpressionState &state, Vector &r values_list.push_back(values.GetValue(mapping.key_index)); } D_ASSERT(values_list.size() == keys_list.size()); - result_entry.offset = ListVector::GetListSize(result); - result_entry.length = values_list.size(); auto list_entries = GetListEntries(std::move(keys_list), std::move(values_list)); for (auto &list_entry : list_entries) { ListVector::PushBack(result, list_entry); diff --git a/src/core_functions/scalar/map/map_entries.cpp b/src/core_functions/scalar/map/map_entries.cpp index 7629c789622..47e6539938e 100644 --- a/src/core_functions/scalar/map/map_entries.cpp +++ b/src/core_functions/scalar/map/map_entries.cpp @@ -12,7 +12,15 @@ namespace duckdb { static void MapEntriesFunction(DataChunk &args, ExpressionState &state, Vector &result) { auto count = args.size(); - MapUtil::ReinterpretMap(result, args.data[0], count); + auto &map = args.data[0]; + if (map.GetType().id() == LogicalTypeId::SQLNULL) { + // Input is a constant NULL + result.SetVectorType(VectorType::CONSTANT_VECTOR); + ConstantVector::SetNull(result, true); + return; + } + + MapUtil::ReinterpretMap(result, map, count); if (args.AllConstant()) { result.SetVectorType(VectorType::CONSTANT_VECTOR); @@ -20,10 +28,20 @@ static void MapEntriesFunction(DataChunk &args, ExpressionState &state, Vector & result.Verify(count); } -static unique_ptr MapEntriesBind(ClientContext &context, ScalarFunction &bound_function, - vector> &arguments) { +static LogicalType CreateReturnType(const LogicalType &map) { + auto &key_type = MapType::KeyType(map); + auto &value_type = MapType::ValueType(map); + child_list_t child_types; + child_types.push_back(make_pair("key", key_type)); + child_types.push_back(make_pair("value", value_type)); + + auto row_type = LogicalType::STRUCT(child_types); + return LogicalType::LIST(row_type); +} +static unique_ptr MapEntriesBind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { if (arguments.size() != 1) { throw InvalidInputException("Too many arguments provided, only expecting a single map"); } @@ -36,25 +54,24 @@ static unique_ptr MapEntriesBind(ClientContext &context, ScalarFun return nullptr; } + if (map.id() == LogicalTypeId::SQLNULL) { + // Input is NULL, output is STRUCT(NULL, NULL)[] + auto map_type = LogicalType::MAP(LogicalTypeId::SQLNULL, LogicalTypeId::SQLNULL); + bound_function.return_type = CreateReturnType(map_type); + return make_uniq(bound_function.return_type); + } + if (map.id() != LogicalTypeId::MAP) { throw InvalidInputException("The provided argument is not a map"); } - auto &key_type = MapType::KeyType(map); - auto &value_type = MapType::ValueType(map); - - child_types.push_back(make_pair("key", key_type)); - child_types.push_back(make_pair("value", value_type)); - - auto row_type = LogicalType::STRUCT(child_types); - - bound_function.return_type = LogicalType::LIST(row_type); + bound_function.return_type = CreateReturnType(map); return make_uniq(bound_function.return_type); } ScalarFunction MapEntriesFun::GetFunction() { //! the arguments and return types are actually set in the binder function ScalarFunction fun({}, LogicalTypeId::LIST, MapEntriesFunction, MapEntriesBind); - fun.null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; fun.varargs = LogicalType::ANY; return fun; } diff --git a/src/core_functions/scalar/map/map_extract.cpp b/src/core_functions/scalar/map/map_extract.cpp index 8f6c4a8b03f..9cf1ca1053e 100644 --- a/src/core_functions/scalar/map/map_extract.cpp +++ b/src/core_functions/scalar/map/map_extract.cpp @@ -70,14 +70,20 @@ void FillResult(Vector &map, Vector &offsets, Vector &result, idx_t count) { } } +static bool ArgumentIsConstantNull(Vector &argument) { + return argument.GetType().id() == LogicalTypeId::SQLNULL; +} + static void MapExtractFunction(DataChunk &args, ExpressionState &state, Vector &result) { D_ASSERT(args.data.size() == 2); - D_ASSERT(args.data[0].GetType().id() == LogicalTypeId::MAP); result.SetVectorType(VectorType::FLAT_VECTOR); + auto &map = args.data[0]; + auto &key = args.data[1]; + idx_t tuple_count = args.size(); // Optimization: because keys are not allowed to be NULL, we can early-out - if (args.data[1].GetType().id() == LogicalTypeId::SQLNULL) { + if (ArgumentIsConstantNull(map) || ArgumentIsConstantNull(key)) { //! We don't need to look through the map if the 'key' to look for is NULL ListVector::SetListSize(result, 0); result.SetVectorType(VectorType::CONSTANT_VECTOR); @@ -87,9 +93,7 @@ static void MapExtractFunction(DataChunk &args, ExpressionState &state, Vector & result.Verify(tuple_count); return; } - - auto &map = args.data[0]; - auto &key = args.data[1]; + D_ASSERT(map.GetType().id() == LogicalTypeId::MAP); UnifiedVectorFormat map_data; @@ -124,18 +128,27 @@ static unique_ptr MapExtractBind(ClientContext &context, ScalarFun if (arguments.size() != 2) { throw BinderException("MAP_EXTRACT must have exactly two arguments"); } - if (arguments[0]->return_type.id() != LogicalTypeId::MAP) { + + auto &map_type = arguments[0]->return_type; + auto &input_type = arguments[1]->return_type; + + if (map_type.id() == LogicalTypeId::SQLNULL) { + bound_function.return_type = LogicalType::LIST(LogicalTypeId::SQLNULL); + return make_uniq(bound_function.return_type); + } + + if (map_type.id() != LogicalTypeId::MAP) { throw BinderException("MAP_EXTRACT can only operate on MAPs"); } - auto &value_type = MapType::ValueType(arguments[0]->return_type); + auto &value_type = MapType::ValueType(map_type); //! Here we have to construct the List Type that will be returned bound_function.return_type = LogicalType::LIST(value_type); - auto key_type = MapType::KeyType(arguments[0]->return_type); - if (key_type.id() != LogicalTypeId::SQLNULL && arguments[1]->return_type.id() != LogicalTypeId::SQLNULL) { - bound_function.arguments[1] = MapType::KeyType(arguments[0]->return_type); + auto key_type = MapType::KeyType(map_type); + if (key_type.id() != LogicalTypeId::SQLNULL && input_type.id() != LogicalTypeId::SQLNULL) { + bound_function.arguments[1] = MapType::KeyType(map_type); } - return make_uniq(value_type); + return make_uniq(bound_function.return_type); } ScalarFunction MapExtractFun::GetFunction() { diff --git a/src/core_functions/scalar/map/map_keys_values.cpp b/src/core_functions/scalar/map/map_keys_values.cpp index 6c1e8efb8c5..c5578895da5 100644 --- a/src/core_functions/scalar/map/map_keys_values.cpp +++ b/src/core_functions/scalar/map/map_keys_values.cpp @@ -10,10 +10,16 @@ namespace duckdb { static void MapKeyValueFunction(DataChunk &args, ExpressionState &state, Vector &result, Vector &(*get_child_vector)(Vector &)) { + auto &map = args.data[0]; + D_ASSERT(result.GetType().id() == LogicalTypeId::LIST); - auto count = args.size(); + if (map.GetType().id() == LogicalTypeId::SQLNULL) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + ConstantVector::SetNull(result, true); + return; + } - auto &map = args.data[0]; + auto count = args.size(); D_ASSERT(map.GetType().id() == LogicalTypeId::MAP); auto child = get_child_vector(map); @@ -60,6 +66,12 @@ static unique_ptr MapKeyValueBind(ClientContext &context, ScalarFu return nullptr; } + if (map.id() == LogicalTypeId::SQLNULL) { + // Input is NULL, output is NULL[] + bound_function.return_type = LogicalType::LIST(LogicalTypeId::SQLNULL); + return make_uniq(bound_function.return_type); + } + if (map.id() != LogicalTypeId::MAP) { throw InvalidInputException("The provided argument is not a map"); } @@ -83,14 +95,14 @@ static unique_ptr MapValuesBind(ClientContext &context, ScalarFunc ScalarFunction MapKeysFun::GetFunction() { //! the arguments and return types are actually set in the binder function ScalarFunction fun({}, LogicalTypeId::LIST, MapKeysFunction, MapKeysBind); - fun.null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; fun.varargs = LogicalType::ANY; return fun; } ScalarFunction MapValuesFun::GetFunction() { ScalarFunction fun({}, LogicalTypeId::LIST, MapValuesFunction, MapValuesBind); - fun.null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; fun.varargs = LogicalType::ANY; return fun; } diff --git a/src/core_functions/scalar/string/chr.cpp b/src/core_functions/scalar/string/chr.cpp index 20947cd2f81..34f897eb66e 100644 --- a/src/core_functions/scalar/string/chr.cpp +++ b/src/core_functions/scalar/string/chr.cpp @@ -30,7 +30,7 @@ static void ChrFunction(DataChunk &args, ExpressionState &state, Vector &result) int utf8_bytes; UnaryExecutor::Execute(code_vec, result, args.size(), [&](int32_t input) { ChrOperator::GetCodepoint(input, c, utf8_bytes); - return StringVector::AddString(result, &c[0], utf8_bytes); + return StringVector::AddString(result, &c[0], UnsafeNumericCast(utf8_bytes)); }); } #endif diff --git a/src/core_functions/scalar/string/repeat.cpp b/src/core_functions/scalar/string/repeat.cpp index afe3269f94b..b124c65bd34 100644 --- a/src/core_functions/scalar/string/repeat.cpp +++ b/src/core_functions/scalar/string/repeat.cpp @@ -1,5 +1,6 @@ #include "duckdb/common/vector_operations/binary_executor.hpp" #include "duckdb/core_functions/scalar/string_functions.hpp" +#include "duckdb/common/operator/multiply.hpp" namespace duckdb { @@ -11,15 +12,22 @@ static void RepeatFunction(DataChunk &args, ExpressionState &, Vector &result) { str_vector, cnt_vector, result, args.size(), [&](string_t str, int64_t cnt) { auto input_str = str.GetData(); auto size_str = str.GetSize(); + idx_t copy_count = cnt <= 0 || size_str == 0 ? 0 : UnsafeNumericCast(cnt); - idx_t copy_count = cnt <= 0 || size_str == 0 ? 0 : idx_t(cnt); - auto result_str = StringVector::EmptyString(result, size_str * copy_count); - auto result_data = result_str.GetDataWriteable(); - for (idx_t i = 0; i < copy_count; i++) { - memcpy(result_data + i * size_str, input_str, size_str); + idx_t copy_size; + if (TryMultiplyOperator::Operation(size_str, copy_count, copy_size)) { + auto result_str = StringVector::EmptyString(result, copy_size); + auto result_data = result_str.GetDataWriteable(); + for (idx_t i = 0; i < copy_count; i++) { + memcpy(result_data + i * size_str, input_str, size_str); + } + result_str.Finalize(); + return result_str; + } else { + throw OutOfRangeException( + "Cannot create a string of size: '%d' * '%d', the maximum supported string size is: '%d'", size_str, + copy_count, string_t::MAX_STRING_SIZE); } - result_str.Finalize(); - return result_str; }); } diff --git a/src/core_functions/scalar/string/reverse.cpp b/src/core_functions/scalar/string/reverse.cpp index 95c3cf1a0cc..cef1441fa00 100644 --- a/src/core_functions/scalar/string/reverse.cpp +++ b/src/core_functions/scalar/string/reverse.cpp @@ -3,7 +3,7 @@ #include "duckdb/common/exception.hpp" #include "duckdb/common/vector_operations/vector_operations.hpp" #include "duckdb/common/vector_operations/unary_executor.hpp" -#include "utf8proc.hpp" +#include "utf8proc_wrapper.hpp" #include @@ -23,10 +23,9 @@ static bool StrReverseASCII(const char *input, idx_t n, char *output) { //! Unicode string reverse using grapheme breakers static void StrReverseUnicode(const char *input, idx_t n, char *output) { - utf8proc_grapheme_callback(input, n, [&](size_t start, size_t end) { - memcpy(output + n - end, input + start, end - start); - return true; - }); + for (auto cluster : Utf8Proc::GraphemeClusters(input, n)) { + memcpy(output + n - cluster.end, input + cluster.start, cluster.end - cluster.start); + } } struct ReverseOperator { diff --git a/src/execution/aggregate_hashtable.cpp b/src/execution/aggregate_hashtable.cpp index 27e3111130e..4e141644685 100644 --- a/src/execution/aggregate_hashtable.cpp +++ b/src/execution/aggregate_hashtable.cpp @@ -9,6 +9,7 @@ #include "duckdb/common/types/row/tuple_data_iterator.hpp" #include "duckdb/common/vector_operations/vector_operations.hpp" #include "duckdb/execution/expression_executor.hpp" +#include "duckdb/execution/ht_entry.hpp" #include "duckdb/planner/expression/bound_aggregate_expression.hpp" namespace duckdb { @@ -146,7 +147,7 @@ void GroupedAggregateHashTable::Verify() { continue; } auto hash = Load(entry.GetPointer() + hash_offset); - D_ASSERT(entry.GetSalt() == aggr_ht_entry_t::ExtractSalt(hash)); + D_ASSERT(entry.GetSalt() == ht_entry_t::ExtractSalt(hash)); total_count++; } D_ASSERT(total_count == Count()); @@ -154,7 +155,7 @@ void GroupedAggregateHashTable::Verify() { } void GroupedAggregateHashTable::ClearPointerTable() { - std::fill_n(entries, capacity, aggr_ht_entry_t(0)); + std::fill_n(entries, capacity, ht_entry_t::GetEmptyEntry()); } void GroupedAggregateHashTable::ResetCount() { @@ -173,8 +174,8 @@ void GroupedAggregateHashTable::Resize(idx_t size) { } capacity = size; - hash_map = buffer_manager.GetBufferAllocator().Allocate(capacity * sizeof(aggr_ht_entry_t)); - entries = reinterpret_cast(hash_map.get()); + hash_map = buffer_manager.GetBufferAllocator().Allocate(capacity * sizeof(ht_entry_t)); + entries = reinterpret_cast(hash_map.get()); ClearPointerTable(); bitmask = capacity - 1; @@ -201,7 +202,7 @@ void GroupedAggregateHashTable::Resize(idx_t size) { } auto &entry = entries[entry_idx]; D_ASSERT(!entry.IsOccupied()); - entry.SetSalt(aggr_ht_entry_t::ExtractSalt(hash)); + entry.SetSalt(ht_entry_t::ExtractSalt(hash)); entry.SetPointer(row_location); D_ASSERT(entry.IsOccupied()); } @@ -333,7 +334,7 @@ idx_t GroupedAggregateHashTable::FindOrCreateGroupsInternal(DataChunk &groups, V const auto &hash = hashes[r]; ht_offsets[r] = ApplyBitMask(hash); D_ASSERT(ht_offsets[r] == hash % capacity); - hash_salts[r] = aggr_ht_entry_t::ExtractSalt(hash); + hash_salts[r] = ht_entry_t::ExtractSalt(hash); } // we start out with all entries [0, 1, 2, ..., groups.size()] @@ -360,7 +361,8 @@ idx_t GroupedAggregateHashTable::FindOrCreateGroupsInternal(DataChunk &groups, V idx_t new_group_count = 0; idx_t remaining_entries = groups.size(); - while (remaining_entries > 0) { + idx_t iteration_count; + for (iteration_count = 0; remaining_entries > 0 && iteration_count < capacity; iteration_count++) { idx_t new_entry_count = 0; idx_t need_compare_count = 0; idx_t no_match_count = 0; @@ -370,7 +372,9 @@ idx_t GroupedAggregateHashTable::FindOrCreateGroupsInternal(DataChunk &groups, V const auto index = sel_vector->get_index(i); const auto &salt = hash_salts[index]; auto &ht_offset = ht_offsets[index]; - while (true) { + + idx_t inner_iteration_count; + for (inner_iteration_count = 0; inner_iteration_count < capacity; inner_iteration_count++) { auto &entry = entries[ht_offset]; if (entry.IsOccupied()) { // Cell is occupied: Compare salts if (entry.GetSalt() == salt) { @@ -393,6 +397,9 @@ idx_t GroupedAggregateHashTable::FindOrCreateGroupsInternal(DataChunk &groups, V break; } } + if (inner_iteration_count == capacity) { + throw InternalException("Maximum inner iteration count reached in GroupedAggregateHashTable"); + } } if (new_entry_count != 0) { @@ -440,6 +447,9 @@ idx_t GroupedAggregateHashTable::FindOrCreateGroupsInternal(DataChunk &groups, V sel_vector = &state.no_match_vector; remaining_entries = no_match_count; } + if (iteration_count == capacity) { + throw InternalException("Maximum outer iteration count reached in GroupedAggregateHashTable"); + } count += new_group_count; return new_group_count; diff --git a/src/execution/index/CMakeLists.txt b/src/execution/index/CMakeLists.txt index b300678c690..741dbec67b0 100644 --- a/src/execution/index/CMakeLists.txt +++ b/src/execution/index/CMakeLists.txt @@ -1,6 +1,12 @@ add_subdirectory(art) -add_library_unity(duckdb_execution_index OBJECT fixed_size_allocator.cpp - fixed_size_buffer.cpp unknown_index.cpp index_type_set.cpp) +add_library_unity( + duckdb_execution_index + OBJECT + fixed_size_allocator.cpp + fixed_size_buffer.cpp + unbound_index.cpp + index_type_set.cpp + bound_index.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/execution/index/art/art.cpp b/src/execution/index/art/art.cpp index b150f7f4398..974a7ec1167 100644 --- a/src/execution/index/art/art.cpp +++ b/src/execution/index/art/art.cpp @@ -39,7 +39,7 @@ ART::ART(const string &name, const IndexConstraintType index_constraint_type, co TableIOManager &table_io_manager, const vector> &unbound_expressions, AttachedDatabase &db, const shared_ptr, ALLOCATOR_COUNT>> &allocators_ptr, const IndexStorageInfo &info) - : Index(name, ART::TYPE_NAME, index_constraint_type, column_ids, table_io_manager, unbound_expressions, db), + : BoundIndex(name, ART::TYPE_NAME, index_constraint_type, column_ids, table_io_manager, unbound_expressions, db), allocators(allocators_ptr), owns_data(false) { // initialize all allocators @@ -213,139 +213,153 @@ unique_ptr ART::TryInitializeScan(const Transaction &transaction // Keys //===--------------------------------------------------------------------===// -template +template static void TemplatedGenerateKeys(ArenaAllocator &allocator, Vector &input, idx_t count, vector &keys) { - UnifiedVectorFormat idata; - input.ToUnifiedFormat(count, idata); D_ASSERT(keys.size() >= count); + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); auto input_data = UnifiedVectorFormat::GetData(idata); + for (idx_t i = 0; i < count; i++) { auto idx = idata.sel->get_index(i); - if (idata.validity.RowIsValid(idx)) { + + if (IS_NOT_NULL || idata.validity.RowIsValid(idx)) { ARTKey::CreateARTKey(allocator, input.GetType(), keys[i], input_data[idx]); - } else { - // we need to possibly reset the former key value in the keys vector - keys[i] = ARTKey(); + continue; } + + // We need to reset the key value in the reusable keys vector. + keys[i] = ARTKey(); } } -template +template static void ConcatenateKeys(ArenaAllocator &allocator, Vector &input, idx_t count, vector &keys) { + UnifiedVectorFormat idata; input.ToUnifiedFormat(count, idata); - auto input_data = UnifiedVectorFormat::GetData(idata); + for (idx_t i = 0; i < count; i++) { auto idx = idata.sel->get_index(i); - // key is not NULL (no previous column entry was NULL) - if (!keys[i].Empty()) { - if (!idata.validity.RowIsValid(idx)) { - // this column entry is NULL, set whole key to NULL - keys[i] = ARTKey(); - } else { - auto other_key = ARTKey::CreateARTKey(allocator, input.GetType(), input_data[idx]); - keys[i].ConcatenateARTKey(allocator, other_key); - } + if (IS_NOT_NULL) { + auto other_key = ARTKey::CreateARTKey(allocator, input.GetType(), input_data[idx]); + keys[i].ConcatenateARTKey(allocator, other_key); + continue; + } + + // A previous column entry was NULL. + if (keys[i].Empty()) { + continue; } + + // This column entry is NULL, so we set the whole key to NULL. + if (!idata.validity.RowIsValid(idx)) { + keys[i] = ARTKey(); + continue; + } + + // Concatenate the keys. + auto other_key = ARTKey::CreateARTKey(allocator, input.GetType(), input_data[idx]); + keys[i].ConcatenateARTKey(allocator, other_key); } } -void ART::GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector &keys) { - // generate keys for the first input column +template +void GenerateKeysInternal(ArenaAllocator &allocator, DataChunk &input, vector &keys) { switch (input.data[0].GetType().InternalType()) { case PhysicalType::BOOL: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::INT8: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::INT16: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::INT32: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::INT64: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::INT128: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::UINT8: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::UINT16: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::UINT32: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::UINT64: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::UINT128: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::FLOAT: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::DOUBLE: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; case PhysicalType::VARCHAR: - TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); + TemplatedGenerateKeys(allocator, input.data[0], input.size(), keys); break; default: throw InternalException("Invalid type for index"); } + // We concatenate the keys for each remaining column of a compound key. for (idx_t i = 1; i < input.ColumnCount(); i++) { - // for each of the remaining columns, concatenate switch (input.data[i].GetType().InternalType()) { case PhysicalType::BOOL: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::INT8: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::INT16: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::INT32: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::INT64: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::INT128: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::UINT8: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::UINT16: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::UINT32: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::UINT64: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::UINT128: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::FLOAT: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::DOUBLE: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; case PhysicalType::VARCHAR: - ConcatenateKeys(allocator, input.data[i], input.size(), keys); + ConcatenateKeys(allocator, input.data[i], input.size(), keys); break; default: throw InternalException("Invalid type for index"); @@ -353,6 +367,16 @@ void ART::GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector +void ART::GenerateKeys<>(ArenaAllocator &allocator, DataChunk &input, vector &keys) { + GenerateKeysInternal(allocator, input, keys); +} + +template <> +void ART::GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector &keys) { + GenerateKeysInternal(allocator, input, keys); +} + //===--------------------------------------------------------------------===// // Construct from sorted data (only during CREATE (UNIQUE) INDEX statements) //===--------------------------------------------------------------------===// @@ -380,8 +404,8 @@ void GetChildSections(vector &child_sections, vector &keys, child_sections.emplace_back(child_start_idx, key_section.end, keys, key_section); } -bool Construct(ART &art, vector &keys, row_t *row_ids, Node &node, KeySection &key_section, - bool &has_constraint) { +bool ConstructInternal(ART &art, vector &keys, const row_t *row_ids, Node &node, KeySection &key_section, + bool &has_constraint) { D_ASSERT(key_section.start < keys.size()); D_ASSERT(key_section.end < keys.size()); @@ -438,7 +462,7 @@ bool Construct(ART &art, vector &keys, row_t *row_ids, Node &node, KeySe // recurse on each child section for (auto &child_section : child_sections) { Node new_child; - auto no_violation = Construct(art, keys, row_ids, new_child, child_section, has_constraint); + auto no_violation = ConstructInternal(art, keys, row_ids, new_child, child_section, has_constraint); Node::InsertChild(art, ref_node, child_section.key_byte, new_child); if (!no_violation) { return false; @@ -449,13 +473,13 @@ bool Construct(ART &art, vector &keys, row_t *row_ids, Node &node, KeySe bool ART::ConstructFromSorted(idx_t count, vector &keys, Vector &row_identifiers) { - // prepare the row_identifiers - row_identifiers.Flatten(count); - auto row_ids = FlatVector::GetData(row_identifiers); + UnifiedVectorFormat row_id_data; + row_identifiers.ToUnifiedFormat(count, row_id_data); + auto row_ids = UnifiedVectorFormat::GetData(row_id_data); auto key_section = KeySection(0, count - 1, 0, 0); auto has_constraint = IsUnique(); - if (!Construct(*this, keys, row_ids, tree, key_section, has_constraint)) { + if (!ConstructInternal(*this, keys, row_ids, tree, key_section, has_constraint)) { return false; } @@ -474,19 +498,18 @@ bool ART::ConstructFromSorted(idx_t count, vector &keys, Vector &row_ide //===--------------------------------------------------------------------===// // Insert / Verification / Constraint Checking //===--------------------------------------------------------------------===// -ErrorData ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) { +ErrorData ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_identifiers) { - D_ASSERT(row_ids.GetType().InternalType() == ROW_TYPE); + D_ASSERT(row_identifiers.GetType().InternalType() == ROW_TYPE); D_ASSERT(logical_types[0] == input.data[0].GetType()); - // generate the keys for the given input ArenaAllocator arena_allocator(BufferAllocator::Get(db)); vector keys(input.size()); - GenerateKeys(arena_allocator, input, keys); + GenerateKeys<>(arena_allocator, input, keys); - // get the corresponding row IDs - row_ids.Flatten(input.size()); - auto row_identifiers = FlatVector::GetData(row_ids); + UnifiedVectorFormat row_id_data; + row_identifiers.ToUnifiedFormat(input.size(), row_id_data); + auto row_ids = UnifiedVectorFormat::GetData(row_id_data); // now insert the elements into the index idx_t failed_index = DConstants::INVALID_INDEX; @@ -495,7 +518,7 @@ ErrorData ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) { continue; } - row_t row_id = row_identifiers[i]; + auto row_id = row_ids[i]; if (!Insert(tree, keys[i], 0, row_id)) { // failed to insert because of constraint violation failed_index = i; @@ -509,7 +532,7 @@ ErrorData ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) { if (keys[i].Empty()) { continue; } - row_t row_id = row_identifiers[i]; + row_t row_id = row_ids[i]; Erase(tree, keys[i], 0, row_id); } } @@ -526,7 +549,7 @@ ErrorData ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) { } auto leaf = Lookup(tree, keys[i], 0); - D_ASSERT(Leaf::ContainsRowId(*this, *leaf, row_identifiers[i])); + D_ASSERT(Leaf::ContainsRowId(*this, *leaf, row_ids[i])); } #endif @@ -648,28 +671,25 @@ void ART::CommitDrop(IndexLock &index_lock) { tree.Clear(); } -void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) { +void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_identifiers) { DataChunk expression; expression.Initialize(Allocator::DefaultAllocator(), logical_types); - - // first resolve the expressions ExecuteExpressions(input, expression); - // then generate the keys for the given input ArenaAllocator arena_allocator(BufferAllocator::Get(db)); vector keys(expression.size()); - GenerateKeys(arena_allocator, expression, keys); + GenerateKeys<>(arena_allocator, expression, keys); - // now erase the elements from the database - row_ids.Flatten(input.size()); - auto row_identifiers = FlatVector::GetData(row_ids); + UnifiedVectorFormat row_id_data; + row_identifiers.ToUnifiedFormat(input.size(), row_id_data); + auto row_ids = UnifiedVectorFormat::GetData(row_id_data); for (idx_t i = 0; i < input.size(); i++) { if (keys[i].Empty()) { continue; } - Erase(tree, keys[i], 0, row_identifiers[i]); + Erase(tree, keys[i], 0, row_ids[i]); } #ifdef DEBUG @@ -681,7 +701,7 @@ void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) { auto leaf = Lookup(tree, keys[i], 0); if (leaf) { - D_ASSERT(!Leaf::ContainsRowId(*this, *leaf, row_identifiers[i])); + D_ASSERT(!Leaf::ContainsRowId(*this, *leaf, row_ids[i])); } } #endif @@ -787,21 +807,6 @@ bool ART::SearchEqual(ARTKey &key, idx_t max_count, vector &result_ids) { return Leaf::GetRowIds(*this, *leaf, result_ids, max_count); } -void ART::SearchEqualJoinNoFetch(ARTKey &key, idx_t &result_size) { - - // we need to look for a leaf - auto leaf_node = Lookup(tree, key, 0); - if (!leaf_node) { - result_size = 0; - return; - } - - // we only perform index joins on PK/FK columns - D_ASSERT(leaf_node->GetType() == NType::LEAF_INLINED); - result_size = 1; - return; -} - //===--------------------------------------------------------------------===// // Lookup //===--------------------------------------------------------------------===// @@ -1040,10 +1045,9 @@ void ART::CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_m expression_chunk.Initialize(Allocator::DefaultAllocator(), logical_types); ExecuteExpressions(input, expression_chunk); - // generate the keys for the given input ArenaAllocator arena_allocator(BufferAllocator::Get(db)); vector keys(expression_chunk.size()); - GenerateKeys(arena_allocator, expression_chunk, keys); + GenerateKeys<>(arena_allocator, expression_chunk, keys); idx_t found_conflict = DConstants::INVALID_INDEX; for (idx_t i = 0; found_conflict == DConstants::INVALID_INDEX && i < input.size(); i++) { @@ -1115,7 +1119,7 @@ void ART::WritePartialBlocks() { // use the partial block manager to serialize all allocator data auto &block_manager = table_io_manager.GetIndexBlockManager(); - PartialBlockManager partial_block_manager(block_manager, CheckpointType::FULL_CHECKPOINT); + PartialBlockManager partial_block_manager(block_manager, PartialBlockType::FULL_CHECKPOINT); for (auto &allocator : *allocators) { allocator->SerializeBuffers(partial_block_manager); @@ -1152,8 +1156,7 @@ void ART::Deserialize(const BlockPointer &pointer) { //===--------------------------------------------------------------------===// void ART::InitializeVacuum(ARTFlags &flags) { - - flags.vacuum_flags.reserve(allocators->size()); + flags.vacuum_flags.reserve(flags.vacuum_flags.size() + allocators->size()); for (auto &allocator : *allocators) { flags.vacuum_flags.push_back(allocator->InitializeVacuum()); } @@ -1231,7 +1234,7 @@ void ART::InitializeMerge(ARTFlags &flags) { } } -bool ART::MergeIndexes(IndexLock &state, Index &other_index) { +bool ART::MergeIndexes(IndexLock &state, BoundIndex &other_index) { auto &other_art = other_index.Cast(); if (!other_art.tree.HasMetadata()) { diff --git a/src/execution/index/bound_index.cpp b/src/execution/index/bound_index.cpp new file mode 100644 index 00000000000..49a02a05eec --- /dev/null +++ b/src/execution/index/bound_index.cpp @@ -0,0 +1,115 @@ +#include "duckdb/execution/index/bound_index.hpp" + +#include "duckdb/common/radix.hpp" +#include "duckdb/common/serializer/serializer.hpp" +#include "duckdb/planner/expression/bound_columnref_expression.hpp" +#include "duckdb/planner/expression/bound_reference_expression.hpp" +#include "duckdb/planner/expression_iterator.hpp" +#include "duckdb/storage/table/append_state.hpp" + +namespace duckdb { + +//------------------------------------------------------------------------------- +// Bound index +//------------------------------------------------------------------------------- + +BoundIndex::BoundIndex(const string &name, const string &index_type, IndexConstraintType index_constraint_type, + const vector &column_ids, TableIOManager &table_io_manager, + const vector> &unbound_expressions_p, AttachedDatabase &db) + : Index(column_ids, table_io_manager, db), name(name), index_type(index_type), + index_constraint_type(index_constraint_type) { + + for (auto &expr : unbound_expressions_p) { + types.push_back(expr->return_type.InternalType()); + logical_types.push_back(expr->return_type); + unbound_expressions.emplace_back(expr->Copy()); + bound_expressions.push_back(BindExpression(expr->Copy())); + executor.AddExpression(*bound_expressions.back()); + } +} + +void BoundIndex::InitializeLock(IndexLock &state) { + state.index_lock = unique_lock(lock); +} + +ErrorData BoundIndex::Append(DataChunk &entries, Vector &row_identifiers) { + IndexLock state; + InitializeLock(state); + return Append(state, entries, row_identifiers); +} + +void BoundIndex::CommitDrop() { + IndexLock index_lock; + InitializeLock(index_lock); + CommitDrop(index_lock); +} + +void BoundIndex::Delete(DataChunk &entries, Vector &row_identifiers) { + IndexLock state; + InitializeLock(state); + Delete(state, entries, row_identifiers); +} + +bool BoundIndex::MergeIndexes(BoundIndex &other_index) { + IndexLock state; + InitializeLock(state); + return MergeIndexes(state, other_index); +} + +string BoundIndex::VerifyAndToString(const bool only_verify) { + IndexLock state; + InitializeLock(state); + return VerifyAndToString(state, only_verify); +} + +void BoundIndex::Vacuum() { + IndexLock state; + InitializeLock(state); + Vacuum(state); +} + +idx_t BoundIndex::GetInMemorySize() { + IndexLock state; + InitializeLock(state); + return GetInMemorySize(state); +} + +void BoundIndex::ExecuteExpressions(DataChunk &input, DataChunk &result) { + executor.Execute(input, result); +} + +unique_ptr BoundIndex::BindExpression(unique_ptr expr) { + if (expr->type == ExpressionType::BOUND_COLUMN_REF) { + auto &bound_colref = expr->Cast(); + return make_uniq(expr->return_type, column_ids[bound_colref.binding.column_index]); + } + ExpressionIterator::EnumerateChildren( + *expr, [this](unique_ptr &expr) { expr = BindExpression(std::move(expr)); }); + return expr; +} + +bool BoundIndex::IndexIsUpdated(const vector &column_ids_p) const { + for (auto &column : column_ids_p) { + if (column_id_set.find(column.index) != column_id_set.end()) { + return true; + } + } + return false; +} + +IndexStorageInfo BoundIndex::GetStorageInfo(const bool get_buffers) { + throw NotImplementedException("The implementation of this index serialization does not exist."); +} + +string BoundIndex::AppendRowError(DataChunk &input, idx_t index) { + string error; + for (idx_t c = 0; c < input.ColumnCount(); c++) { + if (c > 0) { + error += ", "; + } + error += input.GetValue(c, index).ToString(); + } + return error; +} + +} // namespace duckdb diff --git a/src/execution/index/fixed_size_allocator.cpp b/src/execution/index/fixed_size_allocator.cpp index 32018b3e304..f40234e3f70 100644 --- a/src/execution/index/fixed_size_allocator.cpp +++ b/src/execution/index/fixed_size_allocator.cpp @@ -8,9 +8,9 @@ FixedSizeAllocator::FixedSizeAllocator(const idx_t segment_size, BlockManager &b : block_manager(block_manager), buffer_manager(block_manager.buffer_manager), segment_size(segment_size), total_segment_count(0) { - if (segment_size > Storage::BLOCK_SIZE - sizeof(validity_t)) { + if (segment_size > block_manager.GetBlockSize() - sizeof(validity_t)) { throw InternalException("The maximum segment size of fixed-size allocators is " + - to_string(Storage::BLOCK_SIZE - sizeof(validity_t))); + to_string(block_manager.GetBlockSize() - sizeof(validity_t))); } // calculate how many segments fit into one buffer (available_segments_per_buffer) @@ -21,7 +21,7 @@ FixedSizeAllocator::FixedSizeAllocator(const idx_t segment_size, BlockManager &b bitmask_count = 0; available_segments_per_buffer = 0; - while (byte_count < Storage::BLOCK_SIZE) { + while (byte_count < block_manager.GetBlockSize()) { if (!bitmask_count || (bitmask_count * bits_per_value) % available_segments_per_buffer == 0) { // we need to add another validity_t value to the bitmask, to allow storing another // bits_per_value segments on a buffer @@ -29,7 +29,7 @@ FixedSizeAllocator::FixedSizeAllocator(const idx_t segment_size, BlockManager &b byte_count += sizeof(validity_t); } - auto remaining_bytes = Storage::BLOCK_SIZE - byte_count; + auto remaining_bytes = block_manager.GetBlockSize() - byte_count; auto remaining_segments = MinValue(remaining_bytes / segment_size, bits_per_value); if (remaining_segments == 0) { @@ -126,7 +126,7 @@ idx_t FixedSizeAllocator::GetInMemorySize() const { idx_t memory_usage = 0; for (auto &buffer : buffers) { if (buffer.second.InMemory()) { - memory_usage += Storage::BLOCK_SIZE; + memory_usage += block_manager.GetBlockSize(); } } return memory_usage; @@ -209,7 +209,7 @@ bool FixedSizeAllocator::InitializeVacuum() { // calculate the vacuum threshold adaptively D_ASSERT(excess_buffer_count < temporary_vacuum_buffers.size()); idx_t memory_usage = GetInMemorySize(); - idx_t excess_memory_usage = excess_buffer_count * Storage::BLOCK_SIZE; + idx_t excess_memory_usage = excess_buffer_count * block_manager.GetBlockSize(); auto excess_percentage = double(excess_memory_usage) / double(memory_usage); auto threshold = double(VACUUM_THRESHOLD) / 100.0; if (excess_percentage < threshold) { diff --git a/src/execution/index/fixed_size_buffer.cpp b/src/execution/index/fixed_size_buffer.cpp index ab5f4f1d43b..aa95d2ac8e4 100644 --- a/src/execution/index/fixed_size_buffer.cpp +++ b/src/execution/index/fixed_size_buffer.cpp @@ -40,7 +40,7 @@ FixedSizeBuffer::FixedSizeBuffer(BlockManager &block_manager) block_handle(nullptr) { auto &buffer_manager = block_manager.buffer_manager; - buffer_handle = buffer_manager.Allocate(MemoryTag::ART_INDEX, Storage::BLOCK_SIZE, false, &block_handle); + buffer_handle = buffer_manager.Allocate(MemoryTag::ART_INDEX, block_manager.GetBlockSize(), false, &block_handle); } FixedSizeBuffer::FixedSizeBuffer(BlockManager &block_manager, const idx_t segment_count, const idx_t allocation_size, @@ -134,7 +134,7 @@ void FixedSizeBuffer::Pin() { // we need to copy the (partial) data into a new (not yet disk-backed) buffer handle shared_ptr new_block_handle; auto new_buffer_handle = - buffer_manager.Allocate(MemoryTag::ART_INDEX, Storage::BLOCK_SIZE, false, &new_block_handle); + buffer_manager.Allocate(MemoryTag::ART_INDEX, block_manager.GetBlockSize(), false, &new_block_handle); memcpy(new_buffer_handle.Ptr(), buffer_handle.Ptr() + block_pointer.offset, allocation_size); diff --git a/src/execution/index/unbound_index.cpp b/src/execution/index/unbound_index.cpp new file mode 100644 index 00000000000..b8173d75124 --- /dev/null +++ b/src/execution/index/unbound_index.cpp @@ -0,0 +1,30 @@ +#include "duckdb/execution/index/unbound_index.hpp" +#include "duckdb/parser/parsed_data/create_index_info.hpp" +#include "duckdb/storage/table_io_manager.hpp" +#include "duckdb/storage/block_manager.hpp" +#include "duckdb/storage/index_storage_info.hpp" + +namespace duckdb { + +//------------------------------------------------------------------------------- +// Unbound index +//------------------------------------------------------------------------------- + +UnboundIndex::UnboundIndex(unique_ptr create_info, IndexStorageInfo storage_info_p, + TableIOManager &table_io_manager, AttachedDatabase &db) + : Index(create_info->Cast().column_ids, table_io_manager, db), create_info(std::move(create_info)), + storage_info(std::move(storage_info_p)) { +} + +void UnboundIndex::CommitDrop() { + auto &block_manager = table_io_manager.GetIndexBlockManager(); + for (auto &info : storage_info.allocator_infos) { + for (auto &block : info.block_pointers) { + if (block.IsValid()) { + block_manager.MarkBlockAsModified(block.block_id); + } + } + } +} + +} // namespace duckdb diff --git a/src/execution/index/unknown_index.cpp b/src/execution/index/unknown_index.cpp deleted file mode 100644 index e2b6a0cbd3c..00000000000 --- a/src/execution/index/unknown_index.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "duckdb/execution/index/unknown_index.hpp" -#include "duckdb/parser/parsed_data/create_index_info.hpp" - -namespace duckdb { - -//------------------------------------------------------------------------------- -// Unknown index -//------------------------------------------------------------------------------- - -UnknownIndex::UnknownIndex(const string &name, const string &index_type, IndexConstraintType index_constraint_type, - const vector &column_ids, TableIOManager &table_io_manager, - const vector> &unbound_expressions, AttachedDatabase &db, - const CreateIndexInfo &create_info_p, IndexStorageInfo storage_info_p) - : Index(name, index_type, index_constraint_type, column_ids, table_io_manager, unbound_expressions, db), - create_info(create_info_p), storage_info(std::move(storage_info_p)) { -} - -string UnknownIndex::GenerateErrorMessage() const { - return StringUtil::Format( - R"(Unknown index type "%s" for index "%s". You probably need to load an extension containing this index type)", - index_type.c_str(), name.c_str()); -} - -ErrorData UnknownIndex::Append(IndexLock &, DataChunk &, Vector &) { - throw MissingExtensionException(GenerateErrorMessage()); -} -void UnknownIndex::VerifyAppend(DataChunk &) { - throw MissingExtensionException(GenerateErrorMessage()); -} -void UnknownIndex::VerifyAppend(DataChunk &, ConflictManager &) { - throw MissingExtensionException(GenerateErrorMessage()); -} -void UnknownIndex::CommitDrop(IndexLock &) { - throw MissingExtensionException(GenerateErrorMessage()); -} -void UnknownIndex::Delete(IndexLock &, DataChunk &, Vector &) { - throw MissingExtensionException(GenerateErrorMessage()); -} -ErrorData UnknownIndex::Insert(IndexLock &, DataChunk &, Vector &) { - throw MissingExtensionException(GenerateErrorMessage()); -} -IndexStorageInfo UnknownIndex::GetStorageInfo(bool) { - throw MissingExtensionException(GenerateErrorMessage()); -} -bool UnknownIndex::MergeIndexes(IndexLock &, Index &) { - throw MissingExtensionException(GenerateErrorMessage()); -} -void UnknownIndex::Vacuum(IndexLock &) { - throw MissingExtensionException(GenerateErrorMessage()); -} -idx_t UnknownIndex::GetInMemorySize(IndexLock &) { - throw MissingExtensionException(GenerateErrorMessage()); -} -void UnknownIndex::CheckConstraintsForChunk(DataChunk &, ConflictManager &) { - throw MissingExtensionException(GenerateErrorMessage()); -} -string UnknownIndex::VerifyAndToString(IndexLock &, bool) { - throw MissingExtensionException(GenerateErrorMessage()); -} - -string UnknownIndex::GetConstraintViolationMessage(VerifyExistenceType, idx_t, DataChunk &) { - throw MissingExtensionException(GenerateErrorMessage()); -} - -} // namespace duckdb diff --git a/src/execution/join_hashtable.cpp b/src/execution/join_hashtable.cpp index c1f273915e6..d43792bb779 100644 --- a/src/execution/join_hashtable.cpp +++ b/src/execution/join_hashtable.cpp @@ -4,23 +4,40 @@ #include "duckdb/common/row_operations/row_operations.hpp" #include "duckdb/common/types/column/column_data_collection_segment.hpp" #include "duckdb/common/vector_operations/vector_operations.hpp" +#include "duckdb/execution/ht_entry.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/storage/buffer_manager.hpp" namespace duckdb { - using ValidityBytes = JoinHashTable::ValidityBytes; using ScanStructure = JoinHashTable::ScanStructure; using ProbeSpill = JoinHashTable::ProbeSpill; using ProbeSpillLocalState = JoinHashTable::ProbeSpillLocalAppendState; +JoinHashTable::SharedState::SharedState() + : rhs_row_locations(LogicalType::POINTER), salt_match_sel(STANDARD_VECTOR_SIZE), + key_no_match_sel(STANDARD_VECTOR_SIZE) { +} + +JoinHashTable::ProbeState::ProbeState() + : SharedState(), salt_v(LogicalType::UBIGINT), ht_offsets_v(LogicalType::UBIGINT), + ht_offsets_dense_v(LogicalType::UBIGINT), non_empty_sel(STANDARD_VECTOR_SIZE) { +} + +JoinHashTable::InsertState::InsertState(const unique_ptr &data_collection, + const vector &equality_predicate_columns) + : SharedState(), remaining_sel(STANDARD_VECTOR_SIZE), key_match_sel(STANDARD_VECTOR_SIZE) { + data_collection->InitializeChunkState(chunk_state, equality_predicate_columns); +} + JoinHashTable::JoinHashTable(BufferManager &buffer_manager_p, const vector &conditions_p, vector btypes, JoinType type_p, const vector &output_columns_p) : buffer_manager(buffer_manager_p), conditions(conditions_p), build_types(std::move(btypes)), output_columns(output_columns_p), entry_size(0), tuple_size(0), vfound(Value::BOOLEAN(false)), join_type(type_p), finalized(false), has_null(false), radix_bits(INITIAL_RADIX_BITS), partition_start(0), partition_end(0) { - for (auto &condition : conditions) { + for (idx_t i = 0; i < conditions.size(); ++i) { + auto &condition = conditions[i]; D_ASSERT(condition.left->return_type == condition.right->return_type); auto type = condition.left->return_type; if (condition.comparison == ExpressionType::COMPARE_EQUAL || @@ -30,9 +47,15 @@ JoinHashTable::JoinHashTable(BufferManager &buffer_manager_p, const vector(new RowMatcher()); + row_matcher_probe_no_match_sel = unique_ptr(new RowMatcher()); + + row_matcher_probe->Initialize(false, layout, non_equality_predicates, non_equality_predicate_columns); + row_matcher_probe_no_match_sel->Initialize(true, layout, non_equality_predicates, + non_equality_predicate_columns); + + needs_chain_matcher = true; + } else { + needs_chain_matcher = false; + } + + chains_longer_than_one = false; + row_matcher_build.Initialize(true, layout, equality_predicates); const auto &offsets = layout.GetOffsets(); tuple_size = offsets[condition_types.size() + build_types.size()]; @@ -62,6 +101,9 @@ JoinHashTable::JoinHashTable(BufferManager &buffer_manager_p, const vector(buffer_manager, layout); sink_collection = make_uniq(buffer_manager, layout, radix_bits, layout.ColumnCount() - 1); + + dead_end = make_unsafe_uniq_array(layout.GetRowWidth()); + memset(dead_end.get(), 0, layout.GetRowWidth()); } JoinHashTable::~JoinHashTable() { @@ -86,32 +128,190 @@ void JoinHashTable::Merge(JoinHashTable &other) { sink_collection->Combine(*other.sink_collection); } -void JoinHashTable::ApplyBitmask(Vector &hashes, idx_t count) { - if (hashes.GetVectorType() == VectorType::CONSTANT_VECTOR) { - D_ASSERT(!ConstantVector::IsNull(hashes)); - auto indices = ConstantVector::GetData(hashes); - *indices = *indices & bitmask; +static void ApplyBitmaskAndGetSaltBuild(Vector &hashes_v, const idx_t &count, const idx_t &bitmask) { + + if (hashes_v.GetVectorType() == VectorType::CONSTANT_VECTOR) { + + D_ASSERT(!ConstantVector::IsNull(hashes_v)); + + auto indices = ConstantVector::GetData(hashes_v); + hash_t salt = ht_entry_t::ExtractSaltWithNulls(*indices); + idx_t offset = *indices & bitmask; + *indices = offset | salt; + hashes_v.Flatten(count); + } else { - hashes.Flatten(count); - auto indices = FlatVector::GetData(hashes); + hashes_v.Flatten(count); + auto hashes = FlatVector::GetData(hashes_v); + for (idx_t i = 0; i < count; i++) { - indices[i] &= bitmask; + idx_t salt = ht_entry_t::ExtractSaltWithNulls(hashes[i]); + idx_t offset = hashes[i] & bitmask; + hashes[i] = offset | salt; } } } -void JoinHashTable::ApplyBitmask(Vector &hashes, const SelectionVector &sel, idx_t count, Vector &pointers) { - UnifiedVectorFormat hdata; - hashes.ToUnifiedFormat(count, hdata); +// uses an AND operation to apply the modulo operation instead of an if condition that could be branch mispredicted +inline void IncrementAndWrap(idx_t &value, const uint64_t &capacity_mask) { + value += 1; + // leave the salt bits unchanged + value &= capacity_mask; +} + +//! Gets a pointer to the entry in the HT for each of the hashes_v using linear probing. Will update the key_match_sel +//! vector and the count argument to the number and position of the matches +template +static inline void GetRowPointersInternal(DataChunk &keys, TupleDataChunkState &key_state, + JoinHashTable::ProbeState &state, Vector &hashes_v, + const SelectionVector &sel, idx_t &count, JoinHashTable *ht, + ht_entry_t *entries, Vector &pointers_result_v, SelectionVector &match_sel) { + + UnifiedVectorFormat hashes_v_unified; + hashes_v.ToUnifiedFormat(count, hashes_v_unified); + + auto hashes = UnifiedVectorFormat::GetData(hashes_v_unified); + auto salts = FlatVector::GetData(state.salt_v); + + auto ht_offsets = FlatVector::GetData(state.ht_offsets_v); + auto ht_offsets_dense = FlatVector::GetData(state.ht_offsets_dense_v); - auto hash_data = UnifiedVectorFormat::GetData(hdata); - auto result_data = FlatVector::GetData(pointers); - auto main_ht = reinterpret_cast(hash_map.get()); + idx_t non_empty_count = 0; + + // first, filter out the empty rows and calculate the offset for (idx_t i = 0; i < count; i++) { - auto rindex = sel.get_index(i); - auto hindex = hdata.sel->get_index(rindex); - auto hash = hash_data[hindex]; - result_data[rindex] = main_ht + (hash & bitmask); + const auto row_index = sel.get_index(i); + auto uvf_index = hashes_v_unified.sel->get_index(row_index); + auto ht_offset = hashes[uvf_index] & ht->bitmask; + ht_offsets_dense[i] = ht_offset; + ht_offsets[row_index] = ht_offset; + } + + // have a dense loop to have as few instructions as possible while producing cache misses as this is the + // first location where we access the big entries array + for (idx_t i = 0; i < count; i++) { + idx_t ht_offset = ht_offsets_dense[i]; + auto &entry = entries[ht_offset]; + bool occupied = entry.IsOccupied(); + state.non_empty_sel.set_index(non_empty_count, i); + non_empty_count += occupied; + } + + for (idx_t i = 0; i < non_empty_count; i++) { + // transform the dense index to the actual index in the sel vector + idx_t dense_index = state.non_empty_sel.get_index(i); + const auto row_index = sel.get_index(dense_index); + state.non_empty_sel.set_index(i, row_index); + + if (USE_SALTS) { + auto uvf_index = hashes_v_unified.sel->get_index(row_index); + auto hash = hashes[uvf_index]; + hash_t row_salt = ht_entry_t::ExtractSalt(hash); + salts[row_index] = row_salt; + } + } + + auto pointers_result = FlatVector::GetData(pointers_result_v); + auto row_ptr_insert_to = FlatVector::GetData(state.rhs_row_locations); + + const SelectionVector *remaining_sel = &state.non_empty_sel; + idx_t remaining_count = non_empty_count; + + idx_t &match_count = count; + match_count = 0; + + while (remaining_count > 0) { + idx_t salt_match_count = 0; + idx_t key_no_match_count = 0; + + // for each entry, linear probing until + // a) an empty entry is found -> return nullptr (do nothing, as vector is zeroed) + // b) an entry is found where the salt matches -> need to compare the keys + for (idx_t i = 0; i < remaining_count; i++) { + const auto row_index = remaining_sel->get_index(i); + + idx_t &ht_offset = ht_offsets[row_index]; + bool occupied; + ht_entry_t entry; + + if (USE_SALTS) { + hash_t row_salt = salts[row_index]; + // increment the ht_offset of the entry as long as next entry is occupied and salt does not match + while (true) { + entry = entries[ht_offset]; + occupied = entry.IsOccupied(); + bool salt_match = entry.GetSalt() == row_salt; + + // condition for incrementing the ht_offset: occupied and row_salt does not match -> move to next + // entry + if (!occupied || salt_match) { + break; + } + + IncrementAndWrap(ht_offset, ht->bitmask); + } + } else { + entry = entries[ht_offset]; + occupied = entry.IsOccupied(); + } + + // the entries we need to process in the next iteration are the ones that are occupied and the row_salt + // does not match, the ones that are empty need no further processing + state.salt_match_sel.set_index(salt_match_count, row_index); + salt_match_count += occupied; + + // entry might be empty, so the pointer in the entry is nullptr, but this does not matter as the row + // will not be compared anyway as with an empty entry we are already done + row_ptr_insert_to[row_index] = entry.GetPointerOrNull(); + } + + if (salt_match_count != 0) { + // Perform row comparisons, after function call salt_match_sel will point to the keys that match + idx_t key_match_count = ht->row_matcher_build.Match(keys, key_state.vector_data, state.salt_match_sel, + salt_match_count, ht->layout, state.rhs_row_locations, + &state.key_no_match_sel, key_no_match_count); + + D_ASSERT(key_match_count + key_no_match_count == salt_match_count); + + // Set a pointer to the matching row + for (idx_t i = 0; i < key_match_count; i++) { + const auto row_index = state.salt_match_sel.get_index(i); + pointers_result[row_index] = row_ptr_insert_to[row_index]; + + match_sel.set_index(match_count, row_index); + match_count++; + } + + // Linear probing: each of the entries that do not match move to the next entry in the HT + for (idx_t i = 0; i < key_no_match_count; i++) { + const auto row_index = state.key_no_match_sel.get_index(i); + auto &ht_offset = ht_offsets[row_index]; + + IncrementAndWrap(ht_offset, ht->bitmask); + } + } + + remaining_sel = &state.key_no_match_sel; + remaining_count = key_no_match_count; + } +} + +inline bool JoinHashTable::UseSalt() const { + // only use salt for large hash tables and if there is only one equality condition as otherwise + // we potentially need to compare multiple keys + return this->capacity > USE_SALT_THRESHOLD && this->equality_predicate_columns.size() == 1; +} + +void JoinHashTable::GetRowPointers(DataChunk &keys, TupleDataChunkState &key_state, ProbeState &state, Vector &hashes_v, + const SelectionVector &sel, idx_t &count, Vector &pointers_result_v, + SelectionVector &match_sel) { + + if (UseSalt()) { + GetRowPointersInternal(keys, key_state, state, hashes_v, sel, count, this, entries, pointers_result_v, + match_sel); + } else { + GetRowPointersInternal(keys, key_state, state, hashes_v, sel, count, this, entries, pointers_result_v, + match_sel); } } @@ -243,65 +443,254 @@ idx_t JoinHashTable::PrepareKeys(DataChunk &keys, vector return added_count; } -template -static inline void InsertHashesLoop(atomic pointers[], const hash_t indices[], const idx_t count, - const data_ptr_t key_locations[], const idx_t pointer_offset) { - for (idx_t i = 0; i < count; i++) { - const auto index = indices[i]; - if (PARALLEL) { - data_ptr_t head; +//! If we consider to insert into an entry we expct to be empty, if it was filled in the meantime the insert will not +//! happen and we need to return the pointer to the to row with which the new entry would have collided. In any other +//! case we return a nullptr +template +static inline data_ptr_t InsertRowToEntry(atomic &entry, data_ptr_t row_ptr_to_insert, const hash_t salt, + const idx_t pointer_offset) { + + if (PARALLEL) { + // if we expect the entry to be empty, if the operation fails we need to cancel the whole operation as another + // key might have been inserted in the meantime that does not match the current key + if (EXPECT_EMPTY) { + + // add nullptr to the end of the list to mark the end + Store(nullptr, row_ptr_to_insert + pointer_offset); + + ht_entry_t new_empty_entry = ht_entry_t::GetDesiredEntry(row_ptr_to_insert, salt); + ht_entry_t expected_empty_entry = ht_entry_t::GetEmptyEntry(); + std::atomic_compare_exchange_weak(&entry, &expected_empty_entry, new_empty_entry); + + // if the expected empty entry actually was null, we can just return the pointer, and it will be a nullptr + // if the expected entry was filled in the meantime, we need to cancel the operation and will return the + // pointer to the next entry + return expected_empty_entry.GetPointerOrNull(); + } + + // if we expect the entry to be full, we know that even if the insert fails the keys still match so we can + // just keep trying until we succeed + else { + ht_entry_t expected_current_entry = entry.load(std::memory_order_relaxed); + ht_entry_t desired_new_entry = ht_entry_t::GetDesiredEntry(row_ptr_to_insert, salt); + D_ASSERT(expected_current_entry.IsOccupied()); + do { - head = pointers[index]; - Store(head, key_locations[i] + pointer_offset); - } while (!std::atomic_compare_exchange_weak(&pointers[index], &head, key_locations[i])); - } else { - // set prev in current key to the value (NOTE: this will be nullptr if there is none) - Store(pointers[index], key_locations[i] + pointer_offset); + data_ptr_t current_row_pointer = expected_current_entry.GetPointer(); + Store(current_row_pointer, row_ptr_to_insert + pointer_offset); + } while (!std::atomic_compare_exchange_weak(&entry, &expected_current_entry, desired_new_entry)); - // set pointer to current tuple - pointers[index] = key_locations[i]; + return nullptr; } } + // if we are not in parallel mode, we can just do the operation without any checks + else { + ht_entry_t current_entry = entry.load(std::memory_order_relaxed); + data_ptr_t current_row_pointer = current_entry.GetPointerOrNull(); + Store(current_row_pointer, row_ptr_to_insert + pointer_offset); + entry = ht_entry_t::GetDesiredEntry(row_ptr_to_insert, salt); + return nullptr; + } } +static inline void PerformKeyComparison(atomic entries[], JoinHashTable::InsertState &state, + JoinHashTable *ht, const unique_ptr &data_collection, + Vector &row_locations, const idx_t count, idx_t &key_match_count, + idx_t &key_no_match_count) { + // Get the data for the rows that need to be compared + DataChunk lhs_data; + data_collection->InitializeChunk(lhs_data, + ht->equality_predicate_columns); // makes sure DataChunk has the right format + lhs_data.SetCardinality(count); // and the right size + + // The target selection vector says where to write the results into the lhs_data, we just want to write + // sequentially as otherwise we trigger a bug in the Gather function + data_collection->Gather(row_locations, state.salt_match_sel, count, ht->equality_predicate_columns, lhs_data, + *FlatVector::IncrementalSelectionVector(), state.chunk_state.cached_cast_vectors); + + TupleDataCollection::ToUnifiedFormat(state.chunk_state, lhs_data); -void JoinHashTable::InsertHashes(Vector &hashes, idx_t count, data_ptr_t key_locations[], bool parallel) { - D_ASSERT(hashes.GetType().id() == LogicalType::HASH); + for (idx_t i = 0; i < count; i++) { + state.key_match_sel.set_index(i, i); + } + + // Perform row comparisons + key_match_count = + ht->row_matcher_build.Match(lhs_data, state.chunk_state.vector_data, state.key_match_sel, count, ht->layout, + state.rhs_row_locations, &state.key_no_match_sel, key_no_match_count); + + D_ASSERT(key_match_count + key_no_match_count == count); +} - // use bitmask to get position in array - ApplyBitmask(hashes, count); +template +static inline void InsertMatchesAndIncrementMisses(atomic entries[], JoinHashTable::InsertState &state, + JoinHashTable *ht, data_ptr_t *lhs_row_locations, + idx_t *ht_offsets_and_salts, const idx_t capacity_mask, + const idx_t key_match_count, const idx_t key_no_match_count) { + // Insert the rows that match + for (idx_t i = 0; i < key_match_count; i++) { + const auto need_compare_idx = state.key_match_sel.get_index(i); + const auto entry_index = state.salt_match_sel.get_index(need_compare_idx); + + idx_t ht_offset = ht_offsets_and_salts[entry_index] & ht_entry_t::POINTER_MASK; + auto &entry = entries[ht_offset]; + data_ptr_t row_ptr_to_insert = lhs_row_locations[entry_index]; + + auto salt = ht_offsets_and_salts[entry_index]; + InsertRowToEntry(entry, row_ptr_to_insert, salt, ht->pointer_offset); + + ht->chains_longer_than_one = true; + } - hashes.Flatten(count); - D_ASSERT(hashes.GetVectorType() == VectorType::FLAT_VECTOR); + // Linear probing: each of the entries that do not match move to the next entry in the HT + for (idx_t i = 0; i < key_no_match_count; i++) { - auto pointers = reinterpret_cast *>(hash_map.get()); - auto indices = FlatVector::GetData(hashes); + const auto need_compare_idx = state.key_no_match_sel.get_index(i); + const auto entry_index = state.salt_match_sel.get_index(need_compare_idx); + + idx_t &ht_offset_and_salt = ht_offsets_and_salts[entry_index]; + + IncrementAndWrap(ht_offset_and_salt, capacity_mask); + + state.remaining_sel.set_index(i, entry_index); + } +} + +template +static void InsertHashesLoop(atomic entries[], Vector row_locations, Vector &hashes_v, const idx_t &count, + JoinHashTable::InsertState &state, unique_ptr &data_collection, + JoinHashTable *ht) { + D_ASSERT(hashes_v.GetType().id() == LogicalType::HASH); + ApplyBitmaskAndGetSaltBuild(hashes_v, count, ht->bitmask); + + // the offset for each row to insert + idx_t *ht_offsets_and_salts = FlatVector::GetData(hashes_v); + // the row locations of the rows that are already in the hash table + data_ptr_t *rhs_row_locations = FlatVector::GetData(state.rhs_row_locations); + // the row locations of the rows that are to be inserted + data_ptr_t *lhs_row_locations = FlatVector::GetData(row_locations); + + const SelectionVector *remaining_sel = FlatVector::IncrementalSelectionVector(); + idx_t remaining_count = count; + + // use the ht bitmask to make the modulo operation faster but keep the salt bits intact + idx_t capacity_mask = ht->bitmask | ht_entry_t::SALT_MASK; + while (remaining_count > 0) { + idx_t salt_match_count = 0; + + // iterate over each entry to find out whether it belongs to an existing list or will start + // a new list + for (idx_t i = 0; i < remaining_count; i++) { + + const idx_t row_index = remaining_sel->get_index(i); + + idx_t &ht_offset_and_salt = ht_offsets_and_salts[row_index]; + const hash_t salt = ht_entry_t::ExtractSalt(ht_offset_and_salt); + + idx_t ht_offset; + ht_entry_t entry; + bool occupied, salt_match; + + // increment the ht_offset_and_salt of the entry as long as next entry is occupied and salt does not match + while (true) { + ht_offset = ht_offset_and_salt & ht_entry_t::POINTER_MASK; + atomic &atomic_entry = entries[ht_offset]; + entry = atomic_entry.load(std::memory_order_relaxed); + occupied = entry.IsOccupied(); + salt_match = entry.GetSalt() == salt; + + // condition for incrementing the ht_offset: occupied and row_salt does not match -> move to next entry + if (!occupied || salt_match) { + break; + } + + IncrementAndWrap(ht_offset_and_salt, capacity_mask); + } + + if (!occupied) { // insert into free + atomic &atomic_entry = entries[ht_offset]; + data_ptr_t row_ptr_to_insert = lhs_row_locations[row_index]; + data_ptr_t potential_collided_ptr = + InsertRowToEntry(atomic_entry, row_ptr_to_insert, salt, ht->pointer_offset); + + if (PARALLEL) { + // if the insertion was not successful, the entry was occupied in the meantime, so we have to + // compare the keys and insert the row to the next entry + if (potential_collided_ptr) { + // if the entry was occupied, we need to compare the keys and insert the row to the next entry + // we need to compare the keys and insert the row to the next entry + state.salt_match_sel.set_index(salt_match_count, row_index); + rhs_row_locations[salt_match_count] = potential_collided_ptr; + salt_match_count += 1; + } + } + + } else { // compare with full entry + state.salt_match_sel.set_index(salt_match_count, row_index); + rhs_row_locations[salt_match_count] = entry.GetPointer(); + salt_match_count += 1; + } + } + + // at this step, for all the rows to insert we stepped either until we found an empty entry or an entry with + // a matching salt, we now need to compare the keys for the ones that have a matching salt + + idx_t key_match_count = 0; + idx_t key_no_match_count = 0; + + if (salt_match_count != 0) { + + PerformKeyComparison(entries, state, ht, data_collection, row_locations, salt_match_count, key_match_count, + key_no_match_count); + + InsertMatchesAndIncrementMisses(entries, state, ht, lhs_row_locations, ht_offsets_and_salts, + capacity_mask, key_match_count, key_no_match_count); + } + + // update the overall selection vector to only point the entries that still need to be inserted + // as there was no match found for them yet + remaining_sel = &state.remaining_sel; + remaining_count = key_no_match_count; + } +} + +void JoinHashTable::InsertHashes(Vector &hashes_v, idx_t count, TupleDataChunkState &chunk_state, + InsertState &insert_state, bool parallel) { + auto atomic_entries = reinterpret_cast *>(this->entries); + auto row_locations = chunk_state.row_locations; if (parallel) { - InsertHashesLoop(pointers, indices, count, key_locations, pointer_offset); + InsertHashesLoop(atomic_entries, row_locations, hashes_v, count, insert_state, this->data_collection, + this); } else { - InsertHashesLoop(pointers, indices, count, key_locations, pointer_offset); + InsertHashesLoop(atomic_entries, row_locations, hashes_v, count, insert_state, this->data_collection, + this); } } void JoinHashTable::InitializePointerTable() { - idx_t capacity = PointerTableCapacity(Count()); + capacity = PointerTableCapacity(Count()); D_ASSERT(IsPowerOfTwo(capacity)); if (hash_map.get()) { // There is already a hash map - auto current_capacity = hash_map.GetSize() / sizeof(data_ptr_t); - if (capacity != current_capacity) { - // Different size, re-allocate + auto current_capacity = hash_map.GetSize() / sizeof(ht_entry_t); + if (capacity > current_capacity) { + // Need more space hash_map = buffer_manager.GetBufferAllocator().Allocate(capacity * sizeof(data_ptr_t)); + entries = reinterpret_cast(hash_map.get()); + } else { + // Just use the current hash map + capacity = current_capacity; } } else { // Allocate a hash map - hash_map = buffer_manager.GetBufferAllocator().Allocate(capacity * sizeof(data_ptr_t)); + hash_map = buffer_manager.GetBufferAllocator().Allocate(capacity * sizeof(ht_entry_t)); + entries = reinterpret_cast(hash_map.get()); } - D_ASSERT(hash_map.GetSize() == capacity * sizeof(data_ptr_t)); + D_ASSERT(hash_map.GetSize() == capacity * sizeof(ht_entry_t)); // initialize HT with all-zero entries - std::fill_n(reinterpret_cast(hash_map.get()), capacity, nullptr); + std::fill_n(entries, capacity, ht_entry_t::GetEmptyEntry()); bitmask = capacity - 1; } @@ -316,12 +705,16 @@ void JoinHashTable::Finalize(idx_t chunk_idx_from, idx_t chunk_idx_to, bool para TupleDataChunkIterator iterator(*data_collection, TupleDataPinProperties::KEEP_EVERYTHING_PINNED, chunk_idx_from, chunk_idx_to, false); const auto row_locations = iterator.GetRowLocations(); + + InsertState insert_state(this->data_collection, this->equality_predicate_columns); do { const auto count = iterator.GetCurrentChunkCount(); for (idx_t i = 0; i < count; i++) { hash_data[i] = Load(row_locations[i] + pointer_offset); } - InsertHashes(hashes, count, row_locations, parallel); + TupleDataChunkState &chunk_state = iterator.GetChunkState(); + + InsertHashes(hashes, count, chunk_state, insert_state, parallel); } while (iterator.Next()); } @@ -332,7 +725,6 @@ unique_ptr JoinHashTable::InitializeScanStructure(DataChunk &keys // set up the scan structure auto ss = make_uniq(*this, key_state); - if (join_type != JoinType::INNER) { ss->found_match = make_unsafe_uniq_array(STANDARD_VECTOR_SIZE); memset(ss->found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE); @@ -344,8 +736,8 @@ unique_ptr JoinHashTable::InitializeScanStructure(DataChunk &keys return ss; } -unique_ptr JoinHashTable::Probe(DataChunk &keys, TupleDataChunkState &key_state, - Vector *precomputed_hashes) { +unique_ptr JoinHashTable::Probe(DataChunk &keys, TupleDataChunkState &key_state, ProbeState &probe_state, + optional_ptr precomputed_hashes) { const SelectionVector *current_sel; auto ss = InitializeScanStructure(keys, key_state, current_sel); if (ss->count == 0) { @@ -353,24 +745,23 @@ unique_ptr JoinHashTable::Probe(DataChunk &keys, TupleDataChunkSt } if (precomputed_hashes) { - ApplyBitmask(*precomputed_hashes, *current_sel, ss->count, ss->pointers); + GetRowPointers(keys, key_state, probe_state, *precomputed_hashes, *current_sel, ss->count, ss->pointers, + ss->sel_vector); } else { - // hash all the keys Vector hashes(LogicalType::HASH); + // hash all the keys Hash(keys, *current_sel, ss->count, hashes); // now initialize the pointers of the scan structure based on the hashes - ApplyBitmask(hashes, *current_sel, ss->count, ss->pointers); + GetRowPointers(keys, key_state, probe_state, hashes, *current_sel, ss->count, ss->pointers, ss->sel_vector); } - // create the selection vector linking to only non-empty entries - ss->InitializeSelectionVector(current_sel); - return ss; } ScanStructure::ScanStructure(JoinHashTable &ht_p, TupleDataChunkState &key_state_p) - : key_state(key_state_p), pointers(LogicalType::POINTER), sel_vector(STANDARD_VECTOR_SIZE), ht(ht_p), + : key_state(key_state_p), pointers(LogicalType::POINTER), sel_vector(STANDARD_VECTOR_SIZE), + chain_match_sel_vector(STANDARD_VECTOR_SIZE), chain_no_match_sel_vector(STANDARD_VECTOR_SIZE), ht(ht_p), finished(false) { } @@ -381,8 +772,6 @@ void ScanStructure::Next(DataChunk &keys, DataChunk &left, DataChunk &result) { switch (ht.join_type) { case JoinType::INNER: case JoinType::RIGHT: - case JoinType::RIGHT_ANTI: - case JoinType::RIGHT_SEMI: NextInnerJoin(keys, left, result); break; case JoinType::SEMI: @@ -394,6 +783,10 @@ void ScanStructure::Next(DataChunk &keys, DataChunk &left, DataChunk &result) { case JoinType::ANTI: NextAntiJoin(keys, left, result); break; + case JoinType::RIGHT_ANTI: + case JoinType::RIGHT_SEMI: + NextRightSemiOrAntiJoin(keys, left, result); + break; case JoinType::OUTER: case JoinType::LEFT: NextLeftJoin(keys, left, result); @@ -406,7 +799,7 @@ void ScanStructure::Next(DataChunk &keys, DataChunk &left, DataChunk &result) { } } -bool ScanStructure::PointersExhausted() { +bool ScanStructure::PointersExhausted() const { // AdvancePointers creates a "new_count" for every pointer advanced during the // previous advance pointers call. If no pointers are advanced, new_count = 0. // count is then set ot new_count. @@ -414,20 +807,36 @@ bool ScanStructure::PointersExhausted() { } idx_t ScanStructure::ResolvePredicates(DataChunk &keys, SelectionVector &match_sel, SelectionVector *no_match_sel) { - // Start with the scan selection + + // Initialize the found_match array to the current sel_vector for (idx_t i = 0; i < this->count; ++i) { match_sel.set_index(i, this->sel_vector.get_index(i)); } - idx_t no_match_count = 0; - auto &matcher = no_match_sel ? ht.row_matcher_no_match_sel : ht.row_matcher; - return matcher.Match(keys, key_state.vector_data, match_sel, this->count, ht.layout, pointers, no_match_sel, - no_match_count); + // If there is a matcher for the probing side because of non-equality predicates, use it + if (ht.needs_chain_matcher) { + + idx_t no_match_count = 0; + + auto &matcher = no_match_sel ? ht.row_matcher_probe_no_match_sel : ht.row_matcher_probe; + + D_ASSERT(matcher); + + // we need to only use the vectors with the indices of the columns that are used in the probe phase, namely + // the non-equality columns + + return matcher->Match(keys, key_state.vector_data, match_sel, this->count, ht.layout, pointers, no_match_sel, + no_match_count, ht.non_equality_predicate_columns); + } else { + // no match sel is the opposite of match sel + return this->count; + } } idx_t ScanStructure::ScanInnerJoin(DataChunk &keys, SelectionVector &result_vector) { while (true) { - // resolve the predicates for this set of keys + + // resolve the equality_predicates for this set of keys idx_t result_count = ResolvePredicates(keys, result_vector, nullptr); // after doing all the comparisons set the found_match vector @@ -449,6 +858,12 @@ idx_t ScanStructure::ScanInnerJoin(DataChunk &keys, SelectionVector &result_vect } void ScanStructure::AdvancePointers(const SelectionVector &sel, idx_t sel_count) { + + if (!ht.chains_longer_than_one) { + this->count = 0; + return; + } + // now for all the pointers, we move on to the next set of pointers idx_t new_count = 0; auto ptrs = FlatVector::GetData(this->pointers); @@ -462,20 +877,6 @@ void ScanStructure::AdvancePointers(const SelectionVector &sel, idx_t sel_count) this->count = new_count; } -void ScanStructure::InitializeSelectionVector(const SelectionVector *¤t_sel) { - idx_t non_empty_count = 0; - auto ptrs = FlatVector::GetData(pointers); - auto cnt = count; - for (idx_t i = 0; i < cnt; i++) { - const auto idx = current_sel->get_index(i); - ptrs[idx] = Load(ptrs[idx]); - if (ptrs[idx]) { - sel_vector.set_index(non_empty_count++, idx); - } - } - count = non_empty_count; -} - void ScanStructure::AdvancePointers() { AdvancePointers(this->sel_vector, this->count); } @@ -499,17 +900,17 @@ void ScanStructure::NextInnerJoin(DataChunk &keys, DataChunk &left, DataChunk &r return; } - SelectionVector result_vector(STANDARD_VECTOR_SIZE); + idx_t result_count = ScanInnerJoin(keys, chain_match_sel_vector); - idx_t result_count = ScanInnerJoin(keys, result_vector); if (result_count > 0) { if (PropagatesBuildSide(ht.join_type)) { // full/right outer join: mark join matches as FOUND in the HT auto ptrs = FlatVector::GetData(pointers); for (idx_t i = 0; i < result_count; i++) { - auto idx = result_vector.get_index(i); - // NOTE: threadsan reports this as a data race because this can be set concurrently by separate threads - // Technically it is, but it does not matter, since the only value that can be written is "true" + auto idx = chain_match_sel_vector.get_index(i); + // NOTE: threadsan reports this as a data race because this can be set concurrently by separate + // threads Technically it is, but it does not matter, since the only value that can be written is + // "true" Store(true, ptrs[idx] + ht.tuple_size); } } @@ -518,14 +919,14 @@ void ScanStructure::NextInnerJoin(DataChunk &keys, DataChunk &left, DataChunk &r // matches were found // construct the result // on the LHS, we create a slice using the result vector - result.Slice(left, result_vector, result_count); + result.Slice(left, chain_match_sel_vector, result_count); // on the RHS, we need to fetch the data from the hash table for (idx_t i = 0; i < ht.output_columns.size(); i++) { auto &vector = result.data[left.ColumnCount() + i]; const auto output_col_idx = ht.output_columns[i]; D_ASSERT(vector.GetType() == ht.layout.GetTypes()[output_col_idx]); - GatherResult(vector, result_vector, result_count, output_col_idx); + GatherResult(vector, chain_match_sel_vector, result_count, output_col_idx); } } AdvancePointers(); @@ -538,18 +939,20 @@ void ScanStructure::ScanKeyMatches(DataChunk &keys) { // we handle the entire chunk in one call to Next(). // for every pointer, we keep chasing pointers and doing comparisons. // this results in a boolean array indicating whether or not the tuple has a match - SelectionVector match_sel(STANDARD_VECTOR_SIZE), no_match_sel(STANDARD_VECTOR_SIZE); + // Start with the scan selection + while (this->count > 0) { - // resolve the predicates for the current set of pointers - idx_t match_count = ResolvePredicates(keys, match_sel, &no_match_sel); + + // resolve the equality_predicates for the current set of pointers + idx_t match_count = ResolvePredicates(keys, chain_match_sel_vector, &chain_no_match_sel_vector); idx_t no_match_count = this->count - match_count; // mark each of the matches as found for (idx_t i = 0; i < match_count; i++) { - found_match[match_sel.get_index(i)] = true; + found_match[chain_match_sel_vector.get_index(i)] = true; } // continue searching for the ones where we did not find a match yet - AdvancePointers(no_match_sel, no_match_count); + AdvancePointers(chain_no_match_sel_vector, no_match_count); } } @@ -594,6 +997,41 @@ void ScanStructure::NextAntiJoin(DataChunk &keys, DataChunk &left, DataChunk &re finished = true; } +void ScanStructure::NextRightSemiOrAntiJoin(DataChunk &keys, DataChunk &left, DataChunk &result) { + const auto ptrs = FlatVector::GetData(pointers); + while (!PointersExhausted()) { + // resolve the equality_predicates for this set of keys + idx_t result_count = ResolvePredicates(keys, chain_match_sel_vector, nullptr); + + // for each match, fully follow the chain + for (idx_t i = 0; i < result_count; i++) { + const auto idx = chain_match_sel_vector.get_index(i); + auto &ptr = ptrs[idx]; + if (Load(ptr + ht.tuple_size)) { // Early out: chain has been fully marked as found before + ptr = ht.dead_end.get(); + continue; + } + + // Fully mark chain as found + while (true) { + // NOTE: threadsan reports this as a data race because this can be set concurrently by separate threads + // Technically it is, but it does not matter, since the only value that can be written is "true" + Store(true, ptr + ht.tuple_size); + auto next_ptr = Load(ptr + ht.pointer_offset); + if (!next_ptr) { + break; + } + ptr = next_ptr; + } + } + + // check the next set of pointers + AdvancePointers(); + } + + finished = true; +} + void ScanStructure::ConstructMarkJoinResult(DataChunk &join_keys, DataChunk &child, DataChunk &result) { // for the initial set of columns we just reference the left side result.SetCardinality(child); @@ -749,21 +1187,21 @@ void ScanStructure::NextSingleJoin(DataChunk &keys, DataChunk &input, DataChunk // (2) we return NULL for that data if there is no match idx_t result_count = 0; SelectionVector result_sel(STANDARD_VECTOR_SIZE); - SelectionVector match_sel(STANDARD_VECTOR_SIZE), no_match_sel(STANDARD_VECTOR_SIZE); + while (this->count > 0) { - // resolve the predicates for the current set of pointers - idx_t match_count = ResolvePredicates(keys, match_sel, &no_match_sel); + // resolve the equality_predicates for the current set of pointers + idx_t match_count = ResolvePredicates(keys, chain_match_sel_vector, &chain_no_match_sel_vector); idx_t no_match_count = this->count - match_count; // mark each of the matches as found for (idx_t i = 0; i < match_count; i++) { // found a match for this index - auto index = match_sel.get_index(i); + auto index = chain_match_sel_vector.get_index(i); found_match[index] = true; result_sel.set_index(result_count++, index); } // continue searching for the ones where we did not find a match yet - AdvancePointers(no_match_sel, no_match_count); + AdvancePointers(chain_no_match_sel_vector, no_match_count); } // reference the columns of the left side from the result D_ASSERT(input.ColumnCount() > 0); @@ -1020,8 +1458,8 @@ static void CreateSpillChunk(DataChunk &spill_chunk, DataChunk &keys, DataChunk } unique_ptr JoinHashTable::ProbeAndSpill(DataChunk &keys, TupleDataChunkState &key_state, - DataChunk &payload, ProbeSpill &probe_spill, - ProbeSpillLocalAppendState &spill_state, + ProbeState &probe_state, DataChunk &payload, + ProbeSpill &probe_spill, ProbeSpillLocalAppendState &spill_state, DataChunk &spill_chunk) { // hash all the keys Vector hashes(LogicalType::HASH); @@ -1055,10 +1493,7 @@ unique_ptr JoinHashTable::ProbeAndSpill(DataChunk &keys, TupleDat } // now initialize the pointers of the scan structure based on the hashes - ApplyBitmask(hashes, *current_sel, ss->count, ss->pointers); - - // create the selection vector linking to only non-empty entries - ss->InitializeSelectionVector(current_sel); + GetRowPointers(keys, key_state, probe_state, hashes, *current_sel, ss->count, ss->pointers, ss->sel_vector); return ss; } diff --git a/src/execution/operator/aggregate/aggregate_object.cpp b/src/execution/operator/aggregate/aggregate_object.cpp index af61fa17fb4..7068f6c9536 100644 --- a/src/execution/operator/aggregate/aggregate_object.cpp +++ b/src/execution/operator/aggregate/aggregate_object.cpp @@ -20,7 +20,7 @@ AggregateObject::AggregateObject(BoundAggregateExpression *aggr) aggr->filter.get()) { } -AggregateObject::AggregateObject(BoundWindowExpression &window) +AggregateObject::AggregateObject(const BoundWindowExpression &window) : AggregateObject(*window.aggregate, window.bind_info.get(), window.children.size(), AlignValue(window.aggregate->state_size()), window.distinct ? AggregateType::DISTINCT : AggregateType::NON_DISTINCT, diff --git a/src/execution/operator/aggregate/physical_streaming_window.cpp b/src/execution/operator/aggregate/physical_streaming_window.cpp index f1310350e62..850cdac4ef7 100644 --- a/src/execution/operator/aggregate/physical_streaming_window.cpp +++ b/src/execution/operator/aggregate/physical_streaming_window.cpp @@ -1,5 +1,6 @@ #include "duckdb/execution/operator/aggregate/physical_streaming_window.hpp" +#include "duckdb/execution/aggregate_hashtable.hpp" #include "duckdb/execution/expression_executor.hpp" #include "duckdb/function/aggregate_function.hpp" #include "duckdb/parallel/thread_context.hpp" @@ -24,43 +25,206 @@ class StreamingWindowGlobalState : public GlobalOperatorState { class StreamingWindowState : public OperatorState { public: - using StateBuffer = vector; - - StreamingWindowState() - : initialized(false), allocator(Allocator::DefaultAllocator()), - statev(LogicalType::POINTER, data_ptr_cast(&state_ptr)) { - } + struct AggregateState { + AggregateState(ClientContext &client, BoundWindowExpression &wexpr, Allocator &allocator) + : wexpr(wexpr), arena_allocator(Allocator::DefaultAllocator()), executor(client), filter_executor(client), + statev(LogicalType::POINTER, data_ptr_cast(&state_ptr)), hashes(LogicalType::HASH), + addresses(LogicalType::POINTER) { + D_ASSERT(wexpr.GetExpressionType() == ExpressionType::WINDOW_AGGREGATE); + auto &aggregate = *wexpr.aggregate; + bind_data = wexpr.bind_info.get(); + dtor = aggregate.destructor; + state.resize(aggregate.state_size()); + state_ptr = state.data(); + aggregate.initialize(state.data()); + for (auto &child : wexpr.children) { + arg_types.push_back(child->return_type); + executor.AddExpression(*child); + } + if (!arg_types.empty()) { + arg_chunk.Initialize(allocator, arg_types); + arg_cursor.Initialize(allocator, arg_types); + } + if (wexpr.filter_expr) { + filter_executor.AddExpression(*wexpr.filter_expr); + filter_sel.Initialize(); + } + if (wexpr.distinct) { + distinct = make_uniq(client, allocator, arg_types); + distinct_args.Initialize(allocator, arg_types); + distinct_sel.Initialize(); + } + } - ~StreamingWindowState() override { - for (size_t i = 0; i < aggregate_dtors.size(); ++i) { - auto dtor = aggregate_dtors[i]; + ~AggregateState() { if (dtor) { - AggregateInputData aggr_input_data(aggregate_bind_data[i], allocator); - state_ptr = aggregate_states[i].data(); + AggregateInputData aggr_input_data(bind_data, arena_allocator); + state_ptr = state.data(); dtor(statev, aggr_input_data, 1); } } + + void Execute(ExecutionContext &context, DataChunk &input, Vector &result); + + //! The aggregate expression + BoundWindowExpression &wexpr; + //! The allocator to use for aggregate data structures + ArenaAllocator arena_allocator; + //! Reusable executor for the children + ExpressionExecutor executor; + //! Shared executor for FILTER clauses + ExpressionExecutor filter_executor; + //! The single aggregate state we update row-by-row + vector state; + //! The pointer to the state stored in the state vector + data_ptr_t state_ptr = nullptr; + //! The state vector for the single state + Vector statev; + //! The aggregate binding data (if any) + FunctionData *bind_data = nullptr; + //! The aggregate state destructor (if any) + aggregate_destructor_t dtor = nullptr; + //! The inputs rows that pass the FILTER + SelectionVector filter_sel; + //! The number of unfiltered rows so far for COUNT(*) + int64_t unfiltered = 0; + //! Argument types + vector arg_types; + //! Argument value buffer + DataChunk arg_chunk; + //! Argument cursor (a one element slice of arg_chunk) + DataChunk arg_cursor; + + //! Hash table for accumulating the distinct values + unique_ptr distinct; + //! Filtered arguments for checking distinctness + DataChunk distinct_args; + //! Reusable hash vector + Vector hashes; + //! Rows that produced new distinct values + SelectionVector distinct_sel; + //! Pointers to groups in the hash table. + Vector addresses; + }; + + struct LeadLagState { + static constexpr idx_t MAX_BUFFER = STANDARD_VECTOR_SIZE; + + static bool ComputeOffset(ClientContext &context, BoundWindowExpression &wexpr, int64_t &offset) { + offset = 1; + if (wexpr.offset_expr) { + if (wexpr.offset_expr->HasParameter() || !wexpr.offset_expr->IsFoldable()) { + return false; + } + auto offset_value = ExpressionExecutor::EvaluateScalar(context, *wexpr.offset_expr); + if (offset_value.IsNull()) { + return false; + } + Value bigint_value; + if (!offset_value.DefaultTryCastAs(LogicalType::BIGINT, bigint_value, nullptr, false)) { + return false; + } + offset = bigint_value.GetValue(); + } + + // We can only support negative LEAD values and positive LAG values + if (wexpr.type == ExpressionType::WINDOW_LEAD) { + offset = -offset; + } + return 0 <= offset && idx_t(offset) < MAX_BUFFER; + } + + static bool ComputeDefault(ClientContext &context, BoundWindowExpression &wexpr, Value &result) { + if (!wexpr.default_expr) { + result = Value(wexpr.return_type); + return true; + } + + if (wexpr.default_expr && (wexpr.default_expr->HasParameter() || !wexpr.default_expr->IsFoldable())) { + return false; + } + auto dflt_value = ExpressionExecutor::EvaluateScalar(context, *wexpr.default_expr); + return dflt_value.DefaultTryCastAs(wexpr.return_type, result, nullptr, false); + } + + LeadLagState(ClientContext &context, BoundWindowExpression &wexpr) + : wexpr(wexpr), executor(context, *wexpr.children[0]), curr(wexpr.return_type), prev(wexpr.return_type), + temp(wexpr.return_type) { + ComputeOffset(context, wexpr, offset); + ComputeDefault(context, wexpr, dflt); + + buffered = idx_t(offset); + prev.Reference(dflt); + prev.Flatten(buffered); + temp.Initialize(false, buffered); + } + + void Execute(ExecutionContext &context, DataChunk &input, Vector &result) { + executor.ExecuteExpression(input, curr); + const idx_t count = input.size(); + // Copy prev[0, buffered] => result[0, buffered] + idx_t source_count = MinValue(buffered, count); + VectorOperations::Copy(prev, result, source_count, 0, 0); + // Special case when we have buffered enough values for the output + if (count < buffered) { + // Shift down incomplete buffers + // Copy prev[buffered-count, buffered] => temp[0, count] + source_count = buffered - count; + FlatVector::Validity(temp).Reset(); + VectorOperations::Copy(prev, temp, buffered, source_count, 0); + + // Copy temp[0, count] => prev[0, count] + FlatVector::Validity(prev).Reset(); + VectorOperations::Copy(temp, prev, count, 0, 0); + // Copy curr[0, buffered-count] => prev[count, buffered] + VectorOperations::Copy(curr, prev, source_count, 0, count); + } else { + // Copy input values beyond what we have buffered + source_count = count - buffered; + // Copy curr[0, count-buffered] => result[buffered, count] + VectorOperations::Copy(curr, result, source_count, 0, buffered); + // Copy curr[count-buffered, count] => prev[0, buffered] + FlatVector::Validity(prev).Reset(); + VectorOperations::Copy(curr, prev, count, source_count, 0); + } + } + + //! The aggregate expression + BoundWindowExpression &wexpr; + //! Cache the executor to cut down on memory allocation + ExpressionExecutor executor; + //! The constant offset + int64_t offset; + //! The number of rows we have buffered + idx_t buffered; + //! The constant default value + Value dflt; + //! The current set of values + Vector curr; + //! The previous set of values + Vector prev; + //! The copy buffer + Vector temp; + }; + + explicit StreamingWindowState(ClientContext &client) : initialized(false), allocator(Allocator::Get(client)) { + } + + ~StreamingWindowState() override { } void Initialize(ClientContext &context, DataChunk &input, const vector> &expressions) { const_vectors.resize(expressions.size()); aggregate_states.resize(expressions.size()); - aggregate_bind_data.resize(expressions.size(), nullptr); - aggregate_dtors.resize(expressions.size(), nullptr); + lead_lag_states.resize(expressions.size()); for (idx_t expr_idx = 0; expr_idx < expressions.size(); expr_idx++) { auto &expr = *expressions[expr_idx]; auto &wexpr = expr.Cast(); switch (expr.GetExpressionType()) { - case ExpressionType::WINDOW_AGGREGATE: { - auto &aggregate = *wexpr.aggregate; - auto &state = aggregate_states[expr_idx]; - aggregate_bind_data[expr_idx] = wexpr.bind_info.get(); - aggregate_dtors[expr_idx] = aggregate.destructor; - state.resize(aggregate.state_size()); - aggregate.initialize(state.data()); + case ExpressionType::WINDOW_AGGREGATE: + aggregate_states[expr_idx] = make_uniq(context, wexpr, allocator); break; - } case ExpressionType::WINDOW_FIRST_VALUE: { // Just execute the expression once ExpressionExecutor executor(context); @@ -81,6 +245,10 @@ class StreamingWindowState : public OperatorState { const_vectors[expr_idx] = make_uniq(Value((int64_t)1)); break; } + case ExpressionType::WINDOW_LAG: + case ExpressionType::WINDOW_LEAD: + lead_lag_states[expr_idx] = make_uniq(context, wexpr); + break; default: break; } @@ -91,22 +259,153 @@ class StreamingWindowState : public OperatorState { public: bool initialized; vector> const_vectors; - ArenaAllocator allocator; // Aggregation - vector aggregate_states; - vector aggregate_bind_data; - vector aggregate_dtors; - data_ptr_t state_ptr; - Vector statev; + vector> aggregate_states; + Allocator &allocator; + + // Lead/Lag + vector> lead_lag_states; }; +bool PhysicalStreamingWindow::IsStreamingFunction(ClientContext &context, unique_ptr &expr) { + auto &wexpr = expr->Cast(); + if (!wexpr.partitions.empty() || !wexpr.orders.empty() || wexpr.ignore_nulls || + wexpr.exclude_clause != WindowExcludeMode::NO_OTHER) { + return false; + } + switch (wexpr.type) { + // TODO: add more expression types here? + case ExpressionType::WINDOW_AGGREGATE: + // We can stream aggregates if they are "running totals" + return wexpr.start == WindowBoundary::UNBOUNDED_PRECEDING && wexpr.end == WindowBoundary::CURRENT_ROW_ROWS; + case ExpressionType::WINDOW_FIRST_VALUE: + case ExpressionType::WINDOW_PERCENT_RANK: + case ExpressionType::WINDOW_RANK: + case ExpressionType::WINDOW_RANK_DENSE: + case ExpressionType::WINDOW_ROW_NUMBER: + return true; + case ExpressionType::WINDOW_LAG: + case ExpressionType::WINDOW_LEAD: { + // We can stream LEAD/LAG if the arguments are constant and the delta is less than a block behind + Value dflt; + int64_t offset; + return StreamingWindowState::LeadLagState::ComputeDefault(context, wexpr, dflt) && + StreamingWindowState::LeadLagState::ComputeOffset(context, wexpr, offset); + } + default: + return false; + } +} + unique_ptr PhysicalStreamingWindow::GetGlobalOperatorState(ClientContext &context) const { return make_uniq(); } unique_ptr PhysicalStreamingWindow::GetOperatorState(ExecutionContext &context) const { - return make_uniq(); + return make_uniq(context.client); +} + +void StreamingWindowState::AggregateState::Execute(ExecutionContext &context, DataChunk &input, Vector &result) { + // Establish the aggregation environment + const idx_t count = input.size(); + auto &aggregate = *wexpr.aggregate; + auto &aggr_state = *this; + auto &statev = aggr_state.statev; + + // Compute the FILTER mask (if any) + ValidityMask filter_mask; + auto filtered = count; + auto &filter_sel = aggr_state.filter_sel; + if (wexpr.filter_expr) { + filtered = filter_executor.SelectExpression(input, filter_sel); + if (filtered < count) { + filter_mask.Initialize(count); + filter_mask.SetAllInvalid(count); + for (idx_t f = 0; f < filtered; ++f) { + filter_mask.SetValid(filter_sel.get_index(f)); + } + } + } + + // Check for COUNT(*) + if (wexpr.children.empty()) { + D_ASSERT(GetTypeIdSize(result.GetType().InternalType()) == sizeof(int64_t)); + auto data = FlatVector::GetData(result); + auto &unfiltered = aggr_state.unfiltered; + for (idx_t i = 0; i < count; ++i) { + unfiltered += int64_t(filter_mask.RowIsValid(i)); + data[i] = unfiltered; + } + return; + } + + // Compute the arguments + auto &arg_chunk = aggr_state.arg_chunk; + executor.Execute(input, arg_chunk); + arg_chunk.Flatten(); + + // Update the distinct hash table + ValidityMask distinct_mask; + if (aggr_state.distinct) { + auto &distinct_args = aggr_state.distinct_args; + distinct_args.Reference(arg_chunk); + if (wexpr.filter_expr) { + distinct_args.Slice(filter_sel, filtered); + } + idx_t distinct = 0; + auto &distinct_sel = aggr_state.distinct_sel; + if (filtered) { + // FindOrCreateGroups assumes non-empty input + auto &hashes = aggr_state.hashes; + distinct_args.Hash(hashes); + + auto &addresses = aggr_state.addresses; + distinct = aggr_state.distinct->FindOrCreateGroups(distinct_args, hashes, addresses, distinct_sel); + } + + // Translate the distinct selection from filtered row numbers + // back to input row numbers. We need to produce output for all input rows, + // so we filter out + if (distinct < filtered) { + distinct_mask.Initialize(count); + distinct_mask.SetAllInvalid(count); + for (idx_t d = 0; d < distinct; ++d) { + const auto f = distinct_sel.get_index(d); + distinct_mask.SetValid(filter_sel.get_index(f)); + } + } + } + + // Iterate through them using a single SV + sel_t s = 0; + SelectionVector sel(&s); + auto &arg_cursor = aggr_state.arg_cursor; + arg_cursor.Reset(); + arg_cursor.Slice(sel, 1); + // This doesn't work for STRUCTs because the SV + // is not copied to the children when you slice + vector structs; + for (column_t col_idx = 0; col_idx < arg_chunk.ColumnCount(); ++col_idx) { + auto &col_vec = arg_cursor.data[col_idx]; + DictionaryVector::Child(col_vec).Reference(arg_chunk.data[col_idx]); + if (col_vec.GetType().InternalType() == PhysicalType::STRUCT) { + structs.emplace_back(col_idx); + } + } + + // Update the state and finalize it one row at a time. + AggregateInputData aggr_input_data(wexpr.bind_info.get(), aggr_state.arena_allocator); + for (idx_t i = 0; i < count; ++i) { + sel.set_index(0, i); + for (const auto struct_idx : structs) { + arg_cursor.data[struct_idx].Slice(arg_chunk.data[struct_idx], sel, 1); + } + if (filter_mask.RowIsValid(i) && distinct_mask.RowIsValid(i)) { + aggregate.update(arg_cursor.data.data(), aggr_input_data, arg_cursor.ColumnCount(), statev, 1); + } + aggregate.finalize(statev, aggr_input_data, result, 1, i); + } } OperatorResultType PhysicalStreamingWindow::Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, @@ -128,57 +427,9 @@ OperatorResultType PhysicalStreamingWindow::Execute(ExecutionContext &context, D auto &expr = *select_list[expr_idx]; auto &result = chunk.data[col_idx]; switch (expr.GetExpressionType()) { - case ExpressionType::WINDOW_AGGREGATE: { - // Establish the aggregation environment - auto &wexpr = expr.Cast(); - auto &aggregate = *wexpr.aggregate; - auto &statev = state.statev; - state.state_ptr = state.aggregate_states[expr_idx].data(); - AggregateInputData aggr_input_data(wexpr.bind_info.get(), state.allocator); - - // Check for COUNT(*) - if (wexpr.children.empty()) { - D_ASSERT(GetTypeIdSize(result.GetType().InternalType()) == sizeof(int64_t)); - auto data = FlatVector::GetData(result); - int64_t start_row = gstate.row_number; - for (idx_t i = 0; i < input.size(); ++i) { - data[i] = NumericCast(start_row + NumericCast(i)); - } - break; - } - - // Compute the arguments - auto &allocator = Allocator::Get(context.client); - ExpressionExecutor executor(context.client); - vector payload_types; - for (auto &child : wexpr.children) { - payload_types.push_back(child->return_type); - executor.AddExpression(*child); - } - - DataChunk payload; - payload.Initialize(allocator, payload_types); - executor.Execute(input, payload); - - // Iterate through them using a single SV - payload.Flatten(); - DataChunk row; - row.Initialize(allocator, payload_types); - sel_t s = 0; - SelectionVector sel(&s); - row.Slice(sel, 1); - for (size_t col_idx = 0; col_idx < payload.ColumnCount(); ++col_idx) { - DictionaryVector::Child(row.data[col_idx]).Reference(payload.data[col_idx]); - } - - // Update the state and finalize it one row at a time. - for (idx_t i = 0; i < input.size(); ++i) { - sel.set_index(0, i); - aggregate.update(row.data.data(), aggr_input_data, row.ColumnCount(), statev, 1); - aggregate.finalize(statev, aggr_input_data, result, 1, i); - } + case ExpressionType::WINDOW_AGGREGATE: + state.aggregate_states[expr_idx]->Execute(context, input, result); break; - } case ExpressionType::WINDOW_FIRST_VALUE: case ExpressionType::WINDOW_PERCENT_RANK: case ExpressionType::WINDOW_RANK: @@ -196,6 +447,10 @@ OperatorResultType PhysicalStreamingWindow::Execute(ExecutionContext &context, D } break; } + case ExpressionType::WINDOW_LAG: + case ExpressionType::WINDOW_LEAD: + state.lead_lag_states[expr_idx]->Execute(context, input, result); + break; default: throw NotImplementedException("%s for StreamingWindow", ExpressionTypeToString(expr.GetExpressionType())); } diff --git a/src/execution/operator/aggregate/physical_window.cpp b/src/execution/operator/aggregate/physical_window.cpp index 7790eb67de3..79a5aa01ca2 100644 --- a/src/execution/operator/aggregate/physical_window.cpp +++ b/src/execution/operator/aggregate/physical_window.cpp @@ -30,22 +30,99 @@ namespace duckdb { // Global sink state -class WindowGlobalSinkState : public GlobalSinkState { +class WindowGlobalSinkState; + +class WindowHashGroup { public: - WindowGlobalSinkState(const PhysicalWindow &op, ClientContext &context) - : op(op), mode(DBConfig::GetConfig(context).options.window_mode) { + using HashGroupPtr = unique_ptr; + using OrderMasks = PartitionGlobalHashGroup::OrderMasks; + using ExecutorGlobalStatePtr = unique_ptr; + using ExecutorGlobalStates = vector; - D_ASSERT(op.select_list[op.order_idx]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); - auto &wexpr = op.select_list[op.order_idx]->Cast(); + WindowHashGroup(WindowGlobalSinkState &gstate, const idx_t hash_bin_p); + + // Scan all of the blocks during the build phase + unique_ptr GetBuildScanner() const { + if (!rows) { + return nullptr; + } + return make_uniq(*rows, *heap, layout, external, false); + } - global_partition = - make_uniq(context, wexpr.partitions, wexpr.orders, op.children[0]->types, - wexpr.partitions_stats, op.estimated_cardinality); + // Scan a single block during the evaluate phase + unique_ptr GetEvaluateScanner(idx_t block_idx) const { + // Second pass can flush + D_ASSERT(rows); + return make_uniq(*rows, *heap, layout, external, block_idx, true); } + HashGroupPtr hash_group; + //! The generated input chunks + unique_ptr rows; + unique_ptr heap; + RowLayout layout; + //! The partition boundary mask + ValidityMask partition_mask; + //! The order boundary mask + OrderMasks order_masks; + //! External paging + bool external; + //! The function global states for this hash group + ExecutorGlobalStates gestates; + + //! The bin number + idx_t hash_bin; + //! The output ordering batch index this hash group starts at + idx_t batch_base; + +private: + void MaterializeSortedData(); +}; + +class WindowPartitionGlobalSinkState; + +class WindowGlobalSinkState : public GlobalSinkState { +public: + using ExecutorPtr = unique_ptr; + using Executors = vector; + + WindowGlobalSinkState(const PhysicalWindow &op, ClientContext &context); + + //! Parent operator const PhysicalWindow &op; - unique_ptr global_partition; - WindowAggregationMode mode; + //! Execution context + ClientContext &context; + //! The partitioned sunk data + unique_ptr global_partition; + //! The execution functions + Executors executors; +}; + +class WindowPartitionGlobalSinkState : public PartitionGlobalSinkState { +public: + using WindowHashGroupPtr = unique_ptr; + + WindowPartitionGlobalSinkState(WindowGlobalSinkState &gsink, const BoundWindowExpression &wexpr) + : PartitionGlobalSinkState(gsink.context, wexpr.partitions, wexpr.orders, gsink.op.children[0]->types, + wexpr.partitions_stats, gsink.op.estimated_cardinality), + gsink(gsink) { + } + ~WindowPartitionGlobalSinkState() override = default; + + void OnBeginMerge() override { + PartitionGlobalSinkState::OnBeginMerge(); + window_hash_groups.resize(hash_groups.size()); + } + + void OnSortedPartition(const idx_t group_idx) override { + PartitionGlobalSinkState::OnSortedPartition(group_idx); + window_hash_groups[group_idx] = make_uniq(gsink, group_idx); + } + + //! Operator global sink state + WindowGlobalSinkState &gsink; + //! The sorted hash groups + vector window_hash_groups; }; // Per-thread sink state @@ -89,39 +166,54 @@ PhysicalWindow::PhysicalWindow(vector types, vector WindowExecutorFactory(BoundWindowExpression &wexpr, ClientContext &context, - const ValidityMask &partition_mask, - const ValidityMask &order_mask, const idx_t payload_count, WindowAggregationMode mode) { switch (wexpr.type) { case ExpressionType::WINDOW_AGGREGATE: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask, mode); + return make_uniq(wexpr, context, mode); case ExpressionType::WINDOW_ROW_NUMBER: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(wexpr, context); case ExpressionType::WINDOW_RANK_DENSE: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(wexpr, context); case ExpressionType::WINDOW_RANK: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(wexpr, context); case ExpressionType::WINDOW_PERCENT_RANK: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(wexpr, context); case ExpressionType::WINDOW_CUME_DIST: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(wexpr, context); case ExpressionType::WINDOW_NTILE: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(wexpr, context); case ExpressionType::WINDOW_LEAD: case ExpressionType::WINDOW_LAG: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(wexpr, context); case ExpressionType::WINDOW_FIRST_VALUE: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(wexpr, context); case ExpressionType::WINDOW_LAST_VALUE: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(wexpr, context); case ExpressionType::WINDOW_NTH_VALUE: - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(wexpr, context); break; default: throw InternalException("Window aggregate type %s", ExpressionTypeToString(wexpr.type)); } } +WindowGlobalSinkState::WindowGlobalSinkState(const PhysicalWindow &op, ClientContext &context) + : op(op), context(context) { + + D_ASSERT(op.select_list[op.order_idx]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); + auto &wexpr = op.select_list[op.order_idx]->Cast(); + + const auto mode = DBConfig::GetConfig(context).options.window_mode; + for (idx_t expr_idx = 0; expr_idx < op.select_list.size(); ++expr_idx) { + D_ASSERT(op.select_list[expr_idx]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); + auto &wexpr = op.select_list[expr_idx]->Cast(); + auto wexec = WindowExecutorFactory(wexpr, context, mode); + executors.emplace_back(std::move(wexec)); + } + + global_partition = make_uniq(*this, wexpr); +} + //===--------------------------------------------------------------------===// // Sink //===--------------------------------------------------------------------===// @@ -220,34 +312,36 @@ class WindowGlobalSourceState : public GlobalSourceState { WindowGlobalSourceState::WindowGlobalSourceState(ClientContext &context_p, WindowGlobalSinkState &gsink_p) : context(context_p), gsink(gsink_p), next_build(0), tasks_remaining(0), returned(0) { - auto &hash_groups = gsink.global_partition->hash_groups; - auto &gpart = gsink.global_partition; - if (hash_groups.empty()) { + auto &window_hash_groups = gsink.global_partition->window_hash_groups; + + if (window_hash_groups.empty()) { // OVER() - built.resize(1); if (gpart->rows) { tasks_remaining += gpart->rows->blocks.size(); } + if (tasks_remaining) { + // We need to construct the single WindowHashGroup here because the sort tasks will not be run. + built.resize(1); + window_hash_groups.emplace_back(make_uniq(gsink, idx_t(0))); + } } else { - built.resize(hash_groups.size()); + built.resize(window_hash_groups.size()); idx_t batch_base = 0; - for (auto &hash_group : hash_groups) { - if (!hash_group) { + for (auto &window_hash_group : window_hash_groups) { + if (!window_hash_group) { continue; } - auto &global_sort_state = *hash_group->global_sort; - if (global_sort_state.sorted_blocks.empty()) { + auto &rows = window_hash_group->rows; + if (!rows) { continue; } - D_ASSERT(global_sort_state.sorted_blocks.size() == 1); - auto &sb = *global_sort_state.sorted_blocks[0]; - auto &sd = *sb.payload_data; - tasks_remaining += sd.data_blocks.size(); + const auto block_count = window_hash_group->rows->blocks.size(); + tasks_remaining += block_count; - hash_group->batch_base = batch_base; - batch_base += sd.data_blocks.size(); + window_hash_group->batch_base = batch_base; + batch_base += block_count; } } } @@ -255,40 +349,21 @@ WindowGlobalSourceState::WindowGlobalSourceState(ClientContext &context_p, Windo // Per-bin evaluation state (build and evaluate) class WindowPartitionSourceState { public: - using HashGroupPtr = unique_ptr; - using ExecutorPtr = unique_ptr; - using Executors = vector; - using OrderMasks = PartitionGlobalHashGroup::OrderMasks; + using WindowHashGroupPtr = unique_ptr; WindowPartitionSourceState(ClientContext &context, WindowGlobalSourceState &gsource) : context(context), op(gsource.gsink.op), gsource(gsource), read_block_idx(0), unscanned(0) { - layout.Initialize(gsource.gsink.global_partition->payload_types); } unique_ptr GetScanner() const; - void MaterializeSortedData(); void BuildPartition(WindowGlobalSinkState &gstate, const idx_t hash_bin); ClientContext &context; const PhysicalWindow &op; WindowGlobalSourceState &gsource; - HashGroupPtr hash_group; - //! The generated input chunks - unique_ptr rows; - unique_ptr heap; - RowLayout layout; - //! The partition boundary mask - ValidityMask partition_mask; - //! The order boundary mask - OrderMasks order_masks; - //! External paging - bool external; - //! The current execution functions - Executors executors; - //! The bin number - idx_t hash_bin; + WindowHashGroupPtr window_hash_group; //! The next block to read. mutable atomic read_block_idx; @@ -296,7 +371,7 @@ class WindowPartitionSourceState { atomic unscanned; }; -void WindowPartitionSourceState::MaterializeSortedData() { +void WindowHashGroup::MaterializeSortedData() { auto &global_sort_state = *hash_group->global_sort; if (global_sort_state.sorted_blocks.empty()) { return; @@ -337,29 +412,29 @@ void WindowPartitionSourceState::MaterializeSortedData() { unique_ptr WindowPartitionSourceState::GetScanner() const { auto &gsink = *gsource.gsink.global_partition; + const auto hash_bin = window_hash_group->hash_bin; + auto &rows = window_hash_group->rows; if ((gsink.rows && !hash_bin) || hash_bin < gsink.hash_groups.size()) { const auto block_idx = read_block_idx++; if (block_idx >= rows->blocks.size()) { return nullptr; } - // Second pass can flush --gsource.tasks_remaining; - return make_uniq(*rows, *heap, layout, external, block_idx, true); + return window_hash_group->GetEvaluateScanner(block_idx); } return nullptr; } -void WindowPartitionSourceState::BuildPartition(WindowGlobalSinkState &gstate, const idx_t hash_bin_p) { - // Get rid of any stale data - hash_bin = hash_bin_p; - +WindowHashGroup::WindowHashGroup(WindowGlobalSinkState &gstate, const idx_t hash_bin_p) + : hash_bin(hash_bin_p), batch_base(0) { // There are three types of partitions: // 1. No partition (no sorting) // 2. One partition (sorting, but no hashing) // 3. Multiple partitions (sorting and hashing) // How big is the partition? - auto &gpart = *gsource.gsink.global_partition; + auto &gpart = *gstate.global_partition; + layout.Initialize(gpart.payload_types); idx_t count = 0; if (hash_bin < gpart.hash_groups.size() && gpart.hash_groups[hash_bin]) { count = gpart.hash_groups[hash_bin]->count; @@ -373,9 +448,9 @@ void WindowPartitionSourceState::BuildPartition(WindowGlobalSinkState &gstate, c partition_mask.Initialize(count); partition_mask.SetAllInvalid(count); - for (idx_t expr_idx = 0; expr_idx < op.select_list.size(); ++expr_idx) { - D_ASSERT(op.select_list[expr_idx]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); - auto &wexpr = op.select_list[expr_idx]->Cast(); + const auto &executors = gstate.executors; + for (auto &wexec : executors) { + auto &wexpr = wexec->wexpr; auto &order_mask = order_masks[wexpr.partitions.size() + wexpr.orders.size()]; if (order_mask.IsMaskSet()) { continue; @@ -408,20 +483,27 @@ void WindowPartitionSourceState::BuildPartition(WindowGlobalSinkState &gstate, c return; } - // Create the executors for each function - executors.clear(); - for (idx_t expr_idx = 0; expr_idx < op.select_list.size(); ++expr_idx) { - D_ASSERT(op.select_list[expr_idx]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); - auto &wexpr = op.select_list[expr_idx]->Cast(); + // Create the executor state for each function + for (auto &wexec : executors) { + auto &wexpr = wexec->wexpr; auto &order_mask = order_masks[wexpr.partitions.size() + wexpr.orders.size()]; - auto wexec = WindowExecutorFactory(wexpr, context, partition_mask, order_mask, count, gstate.mode); - executors.emplace_back(std::move(wexec)); + gestates.emplace_back(wexec->GetGlobalState(count, partition_mask, order_mask)); } +} + +void WindowPartitionSourceState::BuildPartition(WindowGlobalSinkState &gsink, const idx_t hash_bin_p) { + auto &gpart = *gsink.global_partition; + window_hash_group = std::move(gpart.window_hash_groups[hash_bin_p]); + const auto &executors = gsink.executors; + auto &gestates = window_hash_group->gestates; // First pass over the input without flushing DataChunk input_chunk; input_chunk.Initialize(gpart.allocator, gpart.payload_types); - auto scanner = make_uniq(*rows, *heap, layout, external, false); + auto scanner = window_hash_group->GetBuildScanner(); + if (!scanner) { + return; + } idx_t input_idx = 0; while (true) { input_chunk.Reset(); @@ -431,28 +513,28 @@ void WindowPartitionSourceState::BuildPartition(WindowGlobalSinkState &gstate, c } // TODO: Parallelization opportunity - for (auto &wexec : executors) { - wexec->Sink(input_chunk, input_idx, scanner->Count()); + for (idx_t w = 0; w < executors.size(); ++w) { + executors[w]->Sink(input_chunk, input_idx, scanner->Count(), *gestates[w]); } input_idx += input_chunk.size(); } // TODO: Parallelization opportunity - for (auto &wexec : executors) { - wexec->Finalize(); + for (idx_t w = 0; w < executors.size(); ++w) { + executors[w]->Finalize(*gestates[w]); } // External scanning assumes all blocks are swizzled. scanner->ReSwizzle(); // Start the block countdown - unscanned = rows->blocks.size(); + unscanned = window_hash_group->rows->blocks.size(); } // Per-thread scan state class WindowLocalSourceState : public LocalSourceState { public: - using ReadStatePtr = unique_ptr; + using ReadStatePtr = unique_ptr; using ReadStates = vector; explicit WindowLocalSourceState(WindowGlobalSourceState &gsource); @@ -480,15 +562,14 @@ class WindowLocalSourceState : public LocalSourceState { WindowLocalSourceState::WindowLocalSourceState(WindowGlobalSourceState &gsource) : gsource(gsource), hash_bin(gsource.built.size()), batch_index(0) { - auto &gsink = *gsource.gsink.global_partition; - auto &op = gsource.gsink.op; + auto &gsink = gsource.gsink; + auto &global_partition = *gsink.global_partition; - input_chunk.Initialize(gsink.allocator, gsink.payload_types); + input_chunk.Initialize(global_partition.allocator, global_partition.payload_types); vector output_types; - for (idx_t expr_idx = 0; expr_idx < op.select_list.size(); ++expr_idx) { - D_ASSERT(op.select_list[expr_idx]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); - auto &wexpr = op.select_list[expr_idx]->Cast(); + for (auto &wexec : gsink.executors) { + auto &wexpr = wexec->wexpr; output_types.emplace_back(wexpr.return_type); } output_chunk.Initialize(Allocator::Get(gsource.context), output_types); @@ -532,7 +613,7 @@ WindowGlobalSourceState::Task WindowGlobalSourceState::StealWork() { } WindowGlobalSourceState::Task WindowGlobalSourceState::NextTask(idx_t hash_bin) { - auto &hash_groups = gsink.global_partition->hash_groups; + auto &window_hash_groups = gsink.global_partition->window_hash_groups; const auto bin_count = built.size(); // Flush unneeded data @@ -554,8 +635,13 @@ WindowGlobalSourceState::Task WindowGlobalSourceState::NextTask(idx_t hash_bin) hash_bin = next_build++; if (hash_bin < bin_count) { // Find a non-empty hash group. - for (; hash_bin < hash_groups.size(); hash_bin = next_build++) { - if (hash_groups[hash_bin] && hash_groups[hash_bin]->count) { + for (; hash_bin < built.size(); hash_bin = next_build++) { + auto &window_hash_group = window_hash_groups[hash_bin]; + if (!window_hash_group) { + continue; + } + auto &rows = window_hash_group->rows; + if (rows && rows->count) { auto result = CreateTask(hash_bin); if (result.second) { return result; @@ -564,7 +650,7 @@ WindowGlobalSourceState::Task WindowGlobalSourceState::NextTask(idx_t hash_bin) } // OVER() doesn't have a hash_group - if (hash_groups.empty()) { + if (window_hash_groups.empty()) { auto result = CreateTask(hash_bin); if (result.second) { return result; @@ -591,7 +677,8 @@ void WindowLocalSourceState::UpdateBatchIndex() { D_ASSERT(partition_source); D_ASSERT(scanner.get()); - batch_index = partition_source->hash_group ? partition_source->hash_group->batch_base : 0; + const auto &window_hash_group = partition_source->window_hash_group; + batch_index = window_hash_group->batch_base; batch_index += scanner->BlockIndex(); } @@ -608,12 +695,14 @@ bool WindowLocalSourceState::NextPartition() { } partition_source = task.first; scanner = std::move(task.second); - hash_bin = partition_source->hash_bin; + hash_bin = partition_source->window_hash_group->hash_bin; UpdateBatchIndex(); } - for (auto &wexec : partition_source->executors) { - read_states.emplace_back(wexec->GetExecutorState()); + const auto &executors = gsource.gsink.executors; + auto &gestates = partition_source->window_hash_group->gestates; + for (idx_t w = 0; w < executors.size(); ++w) { + read_states.emplace_back(executors[w]->GetLocalState(*gestates[w])); } return true; @@ -639,13 +728,15 @@ void WindowLocalSourceState::Scan(DataChunk &result) { input_chunk.Reset(); scanner->Scan(input_chunk); - auto &executors = partition_source->executors; + const auto &executors = gsource.gsink.executors; + auto &gestates = partition_source->window_hash_group->gestates; output_chunk.Reset(); for (idx_t expr_idx = 0; expr_idx < executors.size(); ++expr_idx) { auto &executor = *executors[expr_idx]; + auto &gstate = *gestates[expr_idx]; auto &lstate = *read_states[expr_idx]; auto &result = output_chunk.data[expr_idx]; - executor.Evaluate(position, input_chunk, result, lstate); + executor.Evaluate(position, input_chunk, result, lstate, gstate); } output_chunk.SetCardinality(input_chunk); output_chunk.Verify(); @@ -689,7 +780,7 @@ double PhysicalWindow::GetProgress(ClientContext &context, GlobalSourceState &gs auto &gsink = gsource.gsink; const auto count = gsink.global_partition->count.load(); - return count ? (returned / double(count)) : -1; + return count ? (double(returned) / double(count)) : -1; } idx_t PhysicalWindow::GetBatchIndex(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, diff --git a/src/execution/operator/csv_scanner/buffer_manager/csv_buffer_manager.cpp b/src/execution/operator/csv_scanner/buffer_manager/csv_buffer_manager.cpp index 8f7b88c566c..c8a7d167678 100644 --- a/src/execution/operator/csv_scanner/buffer_manager/csv_buffer_manager.cpp +++ b/src/execution/operator/csv_scanner/buffer_manager/csv_buffer_manager.cpp @@ -4,8 +4,9 @@ namespace duckdb { CSVBufferManager::CSVBufferManager(ClientContext &context_p, const CSVReaderOptions &options, const string &file_path_p, - const idx_t file_idx_p) - : context(context_p), file_idx(file_idx_p), file_path(file_path_p), buffer_size(CSVBuffer::CSV_BUFFER_SIZE) { + const idx_t file_idx_p, bool per_file_single_threaded_p) + : context(context_p), per_file_single_threaded(per_file_single_threaded_p), file_idx(file_idx_p), + file_path(file_path_p), buffer_size(CSVBuffer::CSV_BUFFER_SIZE) { D_ASSERT(!file_path.empty()); file_handle = ReadCSV::OpenCSV(file_path, options.compression, context); is_pipe = file_handle->IsPipe(); @@ -38,17 +39,7 @@ bool CSVBufferManager::ReadNextAndCacheIt() { D_ASSERT(last_buffer); for (idx_t i = 0; i < 2; i++) { if (!last_buffer->IsCSVFileLastBuffer()) { - auto cur_buffer_size = buffer_size; - if (file_handle->uncompressed) { - if (file_handle->FileSize() - bytes_read) { - cur_buffer_size = file_handle->FileSize() - bytes_read; - } - } - if (cur_buffer_size == 0) { - last_buffer->last_buffer = true; - return false; - } - auto maybe_last_buffer = last_buffer->Next(*file_handle, cur_buffer_size, file_idx, has_seeked); + auto maybe_last_buffer = last_buffer->Next(*file_handle, buffer_size, file_idx, has_seeked); if (!maybe_last_buffer) { last_buffer->last_buffer = true; return false; @@ -81,7 +72,7 @@ shared_ptr CSVBufferManager::GetBuffer(const idx_t pos) { done = true; } } - if (pos != 0 && (sniffing || file_handle->CanSeek())) { + if (pos != 0 && (sniffing || file_handle->CanSeek() || per_file_single_threaded)) { // We don't need to unpin the buffers here if we are not sniffing since we // control it per-thread on the scan if (cached_buffers[pos - 1]) { diff --git a/src/execution/operator/csv_scanner/scanner/base_scanner.cpp b/src/execution/operator/csv_scanner/scanner/base_scanner.cpp index 23212e99e79..0a6205484a8 100644 --- a/src/execution/operator/csv_scanner/scanner/base_scanner.cpp +++ b/src/execution/operator/csv_scanner/scanner/base_scanner.cpp @@ -1,17 +1,19 @@ -#include "duckdb/execution/operator/csv_scanner/csv_sniffer.hpp" #include "duckdb/execution/operator/csv_scanner/base_scanner.hpp" +#include "duckdb/execution/operator/csv_scanner/csv_sniffer.hpp" +#include "duckdb/execution/operator/csv_scanner/skip_scanner.hpp" + namespace duckdb { ScannerResult::ScannerResult(CSVStates &states_p, CSVStateMachine &state_machine_p) - : states(states_p), state_machine(state_machine_p) { + : state_machine(state_machine_p), states(states_p) { } BaseScanner::BaseScanner(shared_ptr buffer_manager_p, shared_ptr state_machine_p, shared_ptr error_handler_p, bool sniffing_p, shared_ptr csv_file_scan_p, CSVIterator iterator_p) : csv_file_scan(std::move(csv_file_scan_p)), sniffing(sniffing_p), error_handler(std::move(error_handler_p)), - state_machine(std::move(state_machine_p)), iterator(iterator_p), buffer_manager(std::move(buffer_manager_p)) { + state_machine(std::move(state_machine_p)), buffer_manager(std::move(buffer_manager_p)), iterator(iterator_p) { D_ASSERT(buffer_manager); D_ASSERT(state_machine); // Initialize current buffer handle @@ -39,29 +41,39 @@ bool BaseScanner::FinishedFile() { return iterator.pos.buffer_pos + 1 == cur_buffer_handle->actual_size; } -void BaseScanner::Reset() { - iterator.SetCurrentPositionToBoundary(); - lines_read = 0; +CSVIterator BaseScanner::SkipCSVRows(shared_ptr buffer_manager, + const shared_ptr &state_machine, idx_t rows_to_skip) { + if (rows_to_skip == 0) { + return {}; + } + auto error_handler = make_shared_ptr(); + SkipScanner row_skipper(std::move(buffer_manager), state_machine, error_handler, rows_to_skip); + row_skipper.ParseChunk(); + return row_skipper.GetIterator(); } CSVIterator &BaseScanner::GetIterator() { return iterator; } +void BaseScanner::SetIterator(const CSVIterator &it) { + iterator = it; +} + ScannerResult &BaseScanner::ParseChunk() { - throw InternalException("ParseChunk() from CSV Base Scanner is mot implemented"); + throw InternalException("ParseChunk() from CSV Base Scanner is not implemented"); } ScannerResult &BaseScanner::GetResult() { - throw InternalException("GetResult() from CSV Base Scanner is mot implemented"); + throw InternalException("GetResult() from CSV Base Scanner is not implemented"); } void BaseScanner::Initialize() { - throw InternalException("Initialize() from CSV Base Scanner is mot implemented"); + throw InternalException("Initialize() from CSV Base Scanner is not implemented"); } void BaseScanner::FinalizeChunkProcess() { - throw InternalException("FinalizeChunkProcess() from CSV Base Scanner is mot implemented"); + throw InternalException("FinalizeChunkProcess() from CSV Base Scanner is not implemented"); } CSVStateMachine &BaseScanner::GetStateMachine() { diff --git a/src/execution/operator/csv_scanner/scanner/column_count_scanner.cpp b/src/execution/operator/csv_scanner/scanner/column_count_scanner.cpp index 70542ef4b47..48898cecbac 100644 --- a/src/execution/operator/csv_scanner/scanner/column_count_scanner.cpp +++ b/src/execution/operator/csv_scanner/scanner/column_count_scanner.cpp @@ -41,17 +41,19 @@ void ColumnCountResult::QuotedNewLine(ColumnCountResult &result) { // nop } -ColumnCountScanner::ColumnCountScanner(shared_ptr buffer_manager, +ColumnCountScanner::ColumnCountScanner(shared_ptr buffer_manager_p, const shared_ptr &state_machine, - shared_ptr error_handler) - : BaseScanner(std::move(buffer_manager), state_machine, std::move(error_handler)), result(states, *state_machine), - column_count(1) { - sniffing = true; + shared_ptr error_handler, CSVIterator iterator) + : BaseScanner(std::move(buffer_manager_p), state_machine, std::move(error_handler), true, nullptr, iterator), + result(states, *state_machine), column_count(1) { } unique_ptr ColumnCountScanner::UpgradeToStringValueScanner() { - auto scanner = make_uniq(0U, buffer_manager, state_machine, error_handler, nullptr, true); - return scanner; + auto iterator = SkipCSVRows(buffer_manager, state_machine, state_machine->dialect_options.skip_rows.GetValue()); + if (iterator.done) { + return make_uniq(0U, buffer_manager, state_machine, error_handler, nullptr, true); + } + return make_uniq(0U, buffer_manager, state_machine, error_handler, nullptr, true, iterator); } ColumnCountResult &ColumnCountScanner::ParseChunk() { diff --git a/src/execution/operator/csv_scanner/scanner/scanner_boundary.cpp b/src/execution/operator/csv_scanner/scanner/scanner_boundary.cpp index aa2c3aea5be..4ddd938bbb7 100644 --- a/src/execution/operator/csv_scanner/scanner/scanner_boundary.cpp +++ b/src/execution/operator/csv_scanner/scanner/scanner_boundary.cpp @@ -2,28 +2,15 @@ namespace duckdb { -CSVPosition::CSVPosition(idx_t file_idx_p, idx_t buffer_idx_p, idx_t buffer_pos_p) - : file_idx(file_idx_p), buffer_idx(buffer_idx_p), buffer_pos(buffer_pos_p) { +CSVPosition::CSVPosition(idx_t buffer_idx_p, idx_t buffer_pos_p) : buffer_idx(buffer_idx_p), buffer_pos(buffer_pos_p) { } CSVPosition::CSVPosition() { } -CSVBoundary::CSVBoundary(idx_t file_idx_p, idx_t buffer_idx_p, idx_t buffer_pos_p, idx_t boundary_idx_p, - idx_t end_pos_p) - : file_idx(file_idx_p), buffer_idx(buffer_idx_p), buffer_pos(buffer_pos_p), boundary_idx(boundary_idx_p), - end_pos(end_pos_p) { +CSVBoundary::CSVBoundary(idx_t buffer_idx_p, idx_t buffer_pos_p, idx_t boundary_idx_p, idx_t end_pos_p) + : buffer_idx(buffer_idx_p), buffer_pos(buffer_pos_p), boundary_idx(boundary_idx_p), end_pos(end_pos_p) { } -CSVBoundary::CSVBoundary() - : file_idx(0), buffer_idx(0), buffer_pos(0), boundary_idx(0), end_pos(NumericLimits::Maximum()) { -} -CSVIterator::CSVIterator(idx_t file_idx, idx_t buffer_idx, idx_t buffer_pos, idx_t boundary_idx, idx_t buffer_size) - : pos(file_idx, buffer_idx, buffer_pos), is_set(true) { - // The end of our boundary will be the buffer size itself it that's smaller than where we want to go - if (buffer_size < buffer_pos + BYTES_PER_THREAD) { - boundary = {file_idx, buffer_idx, buffer_pos, boundary_idx, buffer_size}; - } else { - boundary = {file_idx, buffer_idx, buffer_pos, boundary_idx, buffer_pos + BYTES_PER_THREAD}; - } +CSVBoundary::CSVBoundary() : buffer_idx(0), buffer_pos(0), boundary_idx(0), end_pos(NumericLimits::Maximum()) { } CSVIterator::CSVIterator() : is_set(false) { @@ -32,7 +19,6 @@ CSVIterator::CSVIterator() : is_set(false) { void CSVBoundary::Print() { #ifndef DUCKDB_DISABLE_PRINT std::cout << "---Boundary: " << boundary_idx << " ---" << '\n'; - std::cout << "File Index:: " << file_idx << '\n'; std::cout << "Buffer Index: " << buffer_idx << '\n'; std::cout << "Buffer Pos: " << buffer_pos << '\n'; std::cout << "End Pos: " << end_pos << '\n'; @@ -51,6 +37,8 @@ bool CSVIterator::Next(CSVBufferManager &buffer_manager) { if (!is_set) { return false; } + // If we are calling next this is not the first one anymore + first_one = false; boundary.boundary_idx++; // This is our start buffer auto buffer = buffer_manager.GetBuffer(boundary.buffer_idx); @@ -84,12 +72,8 @@ idx_t CSVIterator::GetEndPos() const { return boundary.end_pos; } -idx_t CSVIterator::GetFileIdx() const { - return pos.file_idx; -} - idx_t CSVIterator::GetBufferIdx() const { - return boundary.buffer_idx; + return pos.buffer_idx; } idx_t CSVIterator::GetBoundaryIdx() const { @@ -97,11 +81,27 @@ idx_t CSVIterator::GetBoundaryIdx() const { } void CSVIterator::SetCurrentPositionToBoundary() { - pos.file_idx = boundary.file_idx; pos.buffer_idx = boundary.buffer_idx; pos.buffer_pos = boundary.buffer_pos; } +void CSVIterator::SetCurrentBoundaryToPosition(bool single_threaded) { + if (single_threaded) { + is_set = false; + return; + } + boundary.buffer_idx = pos.buffer_idx; + if (pos.buffer_pos == 0) { + boundary.end_pos = CSVIterator::BYTES_PER_THREAD; + } else { + boundary.end_pos = ((pos.buffer_pos + CSVIterator::BYTES_PER_THREAD - 1) / CSVIterator::BYTES_PER_THREAD) * + CSVIterator::BYTES_PER_THREAD; + } + + boundary.buffer_pos = boundary.end_pos - CSVIterator::BYTES_PER_THREAD; + is_set = true; +} + void CSVIterator::SetStart(idx_t start) { boundary.buffer_pos = start; } diff --git a/src/execution/operator/csv_scanner/scanner/skip_scanner.cpp b/src/execution/operator/csv_scanner/scanner/skip_scanner.cpp index 486c26b9f32..a1c78768128 100644 --- a/src/execution/operator/csv_scanner/scanner/skip_scanner.cpp +++ b/src/execution/operator/csv_scanner/scanner/skip_scanner.cpp @@ -38,6 +38,7 @@ bool SkipResult::EmptyLine(SkipResult &result, const idx_t buffer_pos) { } return false; } + SkipScanner::SkipScanner(shared_ptr buffer_manager, const shared_ptr &state_machine, shared_ptr error_handler, idx_t rows_to_skip) : BaseScanner(std::move(buffer_manager), state_machine, std::move(error_handler)), @@ -58,6 +59,20 @@ void SkipScanner::Initialize() { } void SkipScanner::FinalizeChunkProcess() { - // nop + // We continue skipping until we skipped enough rows, or we have nothing else to read. + while (!FinishedFile() && result.row_count < result.rows_to_skip) { + cur_buffer_handle = buffer_manager->GetBuffer(++iterator.pos.buffer_idx); + if (cur_buffer_handle) { + iterator.pos.buffer_pos = 0; + buffer_handle_ptr = cur_buffer_handle->Ptr(); + Process(result); + } + } + // Skip Carriage Return + if (state_machine->options.dialect_options.state_machine_options.new_line == NewLineIdentifier::CARRY_ON && + states.states[1] == CSVState::CARRIAGE_RETURN) { + iterator.pos.buffer_pos++; + } + iterator.done = FinishedFile(); } } // namespace duckdb diff --git a/src/execution/operator/csv_scanner/scanner/string_value_scanner.cpp b/src/execution/operator/csv_scanner/scanner/string_value_scanner.cpp index de2cdabf6bd..f7453f796f9 100644 --- a/src/execution/operator/csv_scanner/scanner/string_value_scanner.cpp +++ b/src/execution/operator/csv_scanner/scanner/string_value_scanner.cpp @@ -1,26 +1,31 @@ #include "duckdb/execution/operator/csv_scanner/string_value_scanner.hpp" + +#include "duckdb/common/operator/decimal_cast_operators.hpp" +#include "duckdb/common/operator/double_cast_operator.hpp" +#include "duckdb/common/operator/integer_cast_operator.hpp" +#include "duckdb/common/types/time.hpp" #include "duckdb/execution/operator/csv_scanner/csv_casting.hpp" -#include "duckdb/execution/operator/csv_scanner/skip_scanner.hpp" #include "duckdb/execution/operator/csv_scanner/csv_file_scanner.hpp" +#include "duckdb/execution/operator/csv_scanner/skip_scanner.hpp" +#include "duckdb/function/cast/cast_function_set.hpp" #include "duckdb/main/client_data.hpp" -#include "duckdb/common/operator/integer_cast_operator.hpp" -#include "duckdb/common/operator/double_cast_operator.hpp" -#include #include "utf8proc_wrapper.hpp" +#include + namespace duckdb { StringValueResult::StringValueResult(CSVStates &states, CSVStateMachine &state_machine, const shared_ptr &buffer_handle, Allocator &buffer_allocator, - idx_t result_size_p, idx_t buffer_position, CSVErrorHandler &error_hander_p, + bool figure_out_new_line_p, idx_t buffer_position, CSVErrorHandler &error_hander_p, CSVIterator &iterator_p, bool store_line_size_p, shared_ptr csv_file_scan_p, idx_t &lines_read_p, bool sniffing_p) : ScannerResult(states, state_machine), number_of_columns(NumericCast(state_machine.dialect_options.num_cols)), null_padding(state_machine.options.null_padding), ignore_errors(state_machine.options.ignore_errors.GetValue()), - result_size(result_size_p), error_handler(error_hander_p), iterator(iterator_p), + figure_out_new_line(figure_out_new_line_p), error_handler(error_hander_p), iterator(iterator_p), store_line_size(store_line_size_p), csv_file_scan(std::move(csv_file_scan_p)), lines_read(lines_read_p), - sniffing(sniffing_p) { + current_errors(state_machine.options.IgnoreErrors()), sniffing(sniffing_p) { // Vector information D_ASSERT(number_of_columns > 0); buffer_handles[buffer_handle->buffer_idx] = buffer_handle; @@ -29,16 +34,18 @@ StringValueResult::StringValueResult(CSVStates &states, CSVStateMachine &state_m buffer_size = buffer_handle->actual_size; last_position = {buffer_handle->buffer_idx, buffer_position, buffer_size}; requested_size = buffer_handle->requested_size; + result_size = figure_out_new_line ? 1 : STANDARD_VECTOR_SIZE; // Current Result information current_line_position.begin = {iterator.pos.buffer_idx, iterator.pos.buffer_pos, buffer_handle->actual_size}; current_line_position.end = current_line_position.begin; // Fill out Parse Types vector logical_types; - parse_types = make_unsafe_uniq_array>(number_of_columns); + parse_types = make_unsafe_uniq_array(number_of_columns); + LogicalType varchar_type = LogicalType::VARCHAR; if (!csv_file_scan) { for (idx_t i = 0; i < number_of_columns; i++) { - parse_types[i] = {LogicalTypeId::VARCHAR, true}; + parse_types[i] = ParseTypeInfo(varchar_type, true); logical_types.emplace_back(LogicalType::VARCHAR); string name = "Column_" + to_string(i); names.emplace_back(name); @@ -51,11 +58,11 @@ StringValueResult::StringValueResult(CSVStates &states, CSVStateMachine &state_m } for (idx_t i = 0; i < csv_file_scan->file_types.size(); i++) { auto &type = csv_file_scan->file_types[i]; - if (StringValueScanner::CanDirectlyCast(type, state_machine.options.dialect_options.date_format)) { - parse_types[i] = {type.id(), true}; + if (StringValueScanner::CanDirectlyCast(type)) { + parse_types[i] = ParseTypeInfo(type, true); logical_types.emplace_back(type); } else { - parse_types[i] = {LogicalTypeId::VARCHAR, type.id() == LogicalTypeId::VARCHAR || type.IsNested()}; + parse_types[i] = ParseTypeInfo(varchar_type, type.id() == LogicalTypeId::VARCHAR || type.IsNested()); logical_types.emplace_back(LogicalType::VARCHAR); } } @@ -76,7 +83,7 @@ StringValueResult::StringValueResult(CSVStates &states, CSVStateMachine &state_m if (!projecting_columns) { for (idx_t j = logical_types.size(); j < number_of_columns; j++) { // This can happen if we have sneaky null columns at the end that we wish to ignore - parse_types[j] = {LogicalTypeId::VARCHAR, true}; + parse_types[j] = ParseTypeInfo(varchar_type, true); logical_types.emplace_back(LogicalType::VARCHAR); } } @@ -99,6 +106,15 @@ StringValueResult::StringValueResult(CSVStates &states, CSVStateMachine &state_m } date_format = state_machine.options.dialect_options.date_format.at(LogicalTypeId::DATE).GetValue(); timestamp_format = state_machine.options.dialect_options.date_format.at(LogicalTypeId::TIMESTAMP).GetValue(); + decimal_separator = state_machine.options.decimal_separator[0]; + + if (iterator.first_one) { + lines_read += + state_machine.dialect_options.skip_rows.GetValue() + state_machine.dialect_options.header.GetValue(); + if (lines_read == 0) { + SkipBOM(); + } + } } StringValueResult::~StringValueResult() { @@ -120,7 +136,31 @@ inline bool IsValueNull(const char *null_str_ptr, const char *value_ptr, const i return true; } +bool StringValueResult::HandleTooManyColumnsError(const char *value_ptr, const idx_t size) { + if (cur_col_id >= number_of_columns) { + bool error = true; + if (cur_col_id == number_of_columns && ((quoted && state_machine.options.allow_quoted_nulls) || !quoted)) { + // we make an exception if the first over-value is null + bool is_value_null = false; + for (idx_t i = 0; i < null_str_count; i++) { + is_value_null = is_value_null || IsValueNull(null_str_ptr[i], value_ptr, size); + } + error = !is_value_null; + } + if (error) { + // We error pointing to the current value error. + current_errors.Insert(CSVErrorType::TOO_MANY_COLUMNS, cur_col_id, chunk_col_id, last_position); + cur_col_id++; + } + // We had an error + return true; + } + return false; +} void StringValueResult::AddValueToVector(const char *value_ptr, const idx_t size, bool allocate) { + if (HandleTooManyColumnsError(value_ptr, size)) { + return; + } if (cur_col_id >= number_of_columns) { bool error = true; if (cur_col_id == number_of_columns && ((quoted && state_machine.options.allow_quoted_nulls) || !quoted)) { @@ -133,7 +173,7 @@ void StringValueResult::AddValueToVector(const char *value_ptr, const idx_t size } if (error) { // We error pointing to the current value error. - current_errors.push_back({CSVErrorType::TOO_MANY_COLUMNS, cur_col_id, last_position}); + current_errors.Insert(CSVErrorType::TOO_MANY_COLUMNS, cur_col_id, chunk_col_id, last_position); cur_col_id++; } return; @@ -154,9 +194,9 @@ void StringValueResult::AddValueToVector(const char *value_ptr, const idx_t size empty = state_machine.options.force_not_null[chunk_col_id]; } if (empty) { - if (parse_types[chunk_col_id].first != LogicalTypeId::VARCHAR) { + if (parse_types[chunk_col_id].type_id != LogicalTypeId::VARCHAR) { // If it is not a varchar, empty values are not accepted, we must error. - current_errors.push_back({CSVErrorType::CAST_ERROR, cur_col_id, last_position}); + current_errors.Insert(CSVErrorType::CAST_ERROR, cur_col_id, chunk_col_id, last_position); } static_cast(vector_ptr[chunk_col_id])[number_of_rows] = string_t(); } else { @@ -174,7 +214,7 @@ void StringValueResult::AddValueToVector(const char *value_ptr, const idx_t size } } bool success = true; - switch (parse_types[chunk_col_id].first) { + switch (parse_types[chunk_col_id].type_id) { case LogicalTypeId::TINYINT: success = TrySimpleIntegerCast(value_ptr, size, static_cast(vector_ptr[chunk_col_id])[number_of_rows], false); @@ -228,6 +268,12 @@ void StringValueResult::AddValueToVector(const char *value_ptr, const idx_t size } break; } + case LogicalTypeId::TIME: { + idx_t pos; + success = Time::TryConvertTime(value_ptr, size, pos, + static_cast(vector_ptr[chunk_col_id])[number_of_rows], false); + break; + } case LogicalTypeId::TIMESTAMP: { if (!timestamp_format.Empty()) { success = timestamp_format.TryParseTimestamp( @@ -239,17 +285,77 @@ void StringValueResult::AddValueToVector(const char *value_ptr, const idx_t size } break; } + case LogicalTypeId::DECIMAL: { + if (decimal_separator == ',') { + switch (parse_types[chunk_col_id].internal_type) { + case PhysicalType::INT16: + success = TryDecimalStringCast( + value_ptr, size, static_cast(vector_ptr[chunk_col_id])[number_of_rows], + parse_types[chunk_col_id].width, parse_types[chunk_col_id].scale); + break; + case PhysicalType::INT32: + success = TryDecimalStringCast( + value_ptr, size, static_cast(vector_ptr[chunk_col_id])[number_of_rows], + parse_types[chunk_col_id].width, parse_types[chunk_col_id].scale); + break; + case PhysicalType::INT64: + success = TryDecimalStringCast( + value_ptr, size, static_cast(vector_ptr[chunk_col_id])[number_of_rows], + parse_types[chunk_col_id].width, parse_types[chunk_col_id].scale); + break; + case PhysicalType::INT128: + success = TryDecimalStringCast( + value_ptr, size, static_cast(vector_ptr[chunk_col_id])[number_of_rows], + parse_types[chunk_col_id].width, parse_types[chunk_col_id].scale); + break; + default: + throw InternalException("Invalid Physical Type for Decimal Value. Physical Type: " + + TypeIdToString(parse_types[chunk_col_id].internal_type)); + } + + } else if (decimal_separator == '.') { + switch (parse_types[chunk_col_id].internal_type) { + case PhysicalType::INT16: + success = TryDecimalStringCast(value_ptr, size, + static_cast(vector_ptr[chunk_col_id])[number_of_rows], + parse_types[chunk_col_id].width, parse_types[chunk_col_id].scale); + break; + case PhysicalType::INT32: + success = TryDecimalStringCast(value_ptr, size, + static_cast(vector_ptr[chunk_col_id])[number_of_rows], + parse_types[chunk_col_id].width, parse_types[chunk_col_id].scale); + break; + case PhysicalType::INT64: + success = TryDecimalStringCast(value_ptr, size, + static_cast(vector_ptr[chunk_col_id])[number_of_rows], + parse_types[chunk_col_id].width, parse_types[chunk_col_id].scale); + break; + case PhysicalType::INT128: + success = TryDecimalStringCast(value_ptr, size, + static_cast(vector_ptr[chunk_col_id])[number_of_rows], + parse_types[chunk_col_id].width, parse_types[chunk_col_id].scale); + break; + default: + throw InternalException("Invalid Physical Type for Decimal Value. Physical Type: " + + TypeIdToString(parse_types[chunk_col_id].internal_type)); + } + } else { + throw InvalidInputException("Decimals can only have ',' and '.' as decimal separators"); + } + break; + } default: { // By default, we add a string // We only evaluate if a string is utf8 valid, if it's actually a varchar - if (parse_types[chunk_col_id].second && !Utf8Proc::IsValid(value_ptr, UnsafeNumericCast(size))) { + if (parse_types[chunk_col_id].validate_utf8 && + !Utf8Proc::IsValid(value_ptr, UnsafeNumericCast(size))) { bool force_error = !state_machine.options.ignore_errors.GetValue() && sniffing; // Invalid unicode, we must error if (force_error) { HandleUnicodeError(cur_col_id, last_position); } // If we got here, we are ingoring errors, hence we must ignore this line. - current_errors.push_back({CSVErrorType::INVALID_UNICODE, cur_col_id, last_position}); + current_errors.Insert(CSVErrorType::INVALID_UNICODE, cur_col_id, chunk_col_id, last_position); break; } if (allocate) { @@ -264,13 +370,15 @@ void StringValueResult::AddValueToVector(const char *value_ptr, const idx_t size } } if (!success) { - // We had a casting error, we push it here because we can only error when finishing the line read. - std::ostringstream error; - // Casting Error Message - error << "Could not convert string \"" << std::string(value_ptr, size) << "\" to \'" - << LogicalTypeIdToString(parse_types[cur_col_id].first) << "\'"; - current_errors.push_back({CSVErrorType::CAST_ERROR, cur_col_id, last_position}); - current_errors.back().error_message = error.str(); + current_errors.Insert(CSVErrorType::CAST_ERROR, cur_col_id, chunk_col_id, last_position); + if (!state_machine.options.IgnoreErrors()) { + // We have to write the cast error message. + std::ostringstream error; + // Casting Error Message + error << "Could not convert string \"" << std::string(value_ptr, size) << "\" to \'" + << LogicalTypeIdToString(parse_types[chunk_col_id].type_id) << "\'"; + current_errors.ModifyErrorMessageOfLastError(error.str()); + } } cur_col_id++; chunk_col_id++; @@ -300,7 +408,8 @@ void StringValueResult::Reset() { if (cur_buffer) { buffer_handles[cur_buffer->buffer_idx] = cur_buffer; } - current_errors.clear(); + current_errors.Reset(); + borked_rows.clear(); } void StringValueResult::AddQuotedValue(StringValueResult &result, const idx_t buffer_pos) { @@ -313,12 +422,15 @@ void StringValueResult::AddQuotedValue(StringValueResult &result, const idx_t bu return; } } - // If it's an escaped value we have to remove all the escapes, this is not really great - auto value = StringValueScanner::RemoveEscape( - result.buffer_ptr + result.quoted_position + 1, buffer_pos - result.quoted_position - 2, - result.state_machine.dialect_options.state_machine_options.escape.GetValue(), - result.parse_chunk.data[result.chunk_col_id]); - result.AddValueToVector(value.GetData(), value.GetSize()); + if (!result.HandleTooManyColumnsError(result.buffer_ptr + result.quoted_position + 1, + buffer_pos - result.quoted_position - 2)) { + // If it's an escaped value we have to remove all the escapes, this is not really great + auto value = StringValueScanner::RemoveEscape( + result.buffer_ptr + result.quoted_position + 1, buffer_pos - result.quoted_position - 2, + result.state_machine.dialect_options.state_machine_options.escape.GetValue(), + result.parse_chunk.data[result.chunk_col_id]); + result.AddValueToVector(value.GetData(), value.GetSize()); + } } else { if (buffer_pos < result.last_position.buffer_pos + 2) { // empty value @@ -347,38 +459,36 @@ void StringValueResult::AddValue(StringValueResult &result, const idx_t buffer_p } void StringValueResult::HandleUnicodeError(idx_t col_idx, LinePosition &error_position) { - if (!state_machine.options.IgnoreErrors()) { - bool first_nl; - auto borked_line = current_line_position.ReconstructCurrentLine(first_nl, buffer_handles); - LinesPerBoundary lines_per_batch(iterator.GetBoundaryIdx(), lines_read); - if (current_line_position.begin == error_position) { - auto csv_error = - CSVError::InvalidUTF8(state_machine.options, col_idx, lines_per_batch, borked_line, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl), - error_position.GetGlobalPosition(requested_size, first_nl)); - error_handler.Error(csv_error, true); - } else { - auto csv_error = - CSVError::InvalidUTF8(state_machine.options, col_idx, lines_per_batch, borked_line, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl), - error_position.GetGlobalPosition(requested_size)); - error_handler.Error(csv_error, true); - } + + bool first_nl; + auto borked_line = current_line_position.ReconstructCurrentLine(first_nl, buffer_handles); + LinesPerBoundary lines_per_batch(iterator.GetBoundaryIdx(), lines_read); + if (current_line_position.begin == error_position) { + auto csv_error = CSVError::InvalidUTF8(state_machine.options, col_idx, lines_per_batch, borked_line, + current_line_position.begin.GetGlobalPosition(requested_size, first_nl), + error_position.GetGlobalPosition(requested_size, first_nl)); + error_handler.Error(csv_error, true); + } else { + auto csv_error = CSVError::InvalidUTF8(state_machine.options, col_idx, lines_per_batch, borked_line, + current_line_position.begin.GetGlobalPosition(requested_size, first_nl), + error_position.GetGlobalPosition(requested_size)); + error_handler.Error(csv_error, true); } } -bool StringValueResult::HandleError() { - if (state_machine.options.IgnoreErrors() && !current_errors.empty()) { - current_errors.clear(); - cur_col_id = 0; - chunk_col_id = 0; +bool LineError::HandleErrors(StringValueResult &result) { + if (ignore_errors && is_error_in_line && !result.figure_out_new_line) { + result.cur_col_id = 0; + result.chunk_col_id = 0; + result.number_of_rows--; + Reset(); return true; } // Reconstruct CSV Line for (auto &cur_error : current_errors) { - LinesPerBoundary lines_per_batch(iterator.GetBoundaryIdx(), lines_read); + LinesPerBoundary lines_per_batch(result.iterator.GetBoundaryIdx(), result.lines_read); bool first_nl; - auto borked_line = current_line_position.ReconstructCurrentLine(first_nl, buffer_handles); + auto borked_line = result.current_line_position.ReconstructCurrentLine(first_nl, result.buffer_handles); CSVError csv_error; auto col_idx = cur_error.col_idx; auto &line_pos = cur_error.error_position; @@ -386,74 +496,76 @@ bool StringValueResult::HandleError() { switch (cur_error.type) { case CSVErrorType::TOO_MANY_COLUMNS: case CSVErrorType::TOO_FEW_COLUMNS: - if (current_line_position.begin == line_pos) { + if (result.current_line_position.begin == line_pos) { csv_error = CSVError::IncorrectColumnAmountError( - state_machine.options, col_idx, lines_per_batch, borked_line, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl), - line_pos.GetGlobalPosition(requested_size, first_nl)); + result.state_machine.options, col_idx, lines_per_batch, borked_line, + result.current_line_position.begin.GetGlobalPosition(result.requested_size, first_nl), + line_pos.GetGlobalPosition(result.requested_size, first_nl)); } else { csv_error = CSVError::IncorrectColumnAmountError( - state_machine.options, col_idx, lines_per_batch, borked_line, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl), - line_pos.GetGlobalPosition(requested_size)); + result.state_machine.options, col_idx, lines_per_batch, borked_line, + result.current_line_position.begin.GetGlobalPosition(result.requested_size, first_nl), + line_pos.GetGlobalPosition(result.requested_size)); } break; case CSVErrorType::INVALID_UNICODE: { - if (current_line_position.begin == line_pos) { - csv_error = - CSVError::InvalidUTF8(state_machine.options, col_idx, lines_per_batch, borked_line, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl), - line_pos.GetGlobalPosition(requested_size, first_nl)); + if (result.current_line_position.begin == line_pos) { + csv_error = CSVError::InvalidUTF8( + result.state_machine.options, col_idx, lines_per_batch, borked_line, + result.current_line_position.begin.GetGlobalPosition(result.requested_size, first_nl), + line_pos.GetGlobalPosition(result.requested_size, first_nl)); } else { - csv_error = - CSVError::InvalidUTF8(state_machine.options, col_idx, lines_per_batch, borked_line, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl), - line_pos.GetGlobalPosition(requested_size)); + csv_error = CSVError::InvalidUTF8( + result.state_machine.options, col_idx, lines_per_batch, borked_line, + result.current_line_position.begin.GetGlobalPosition(result.requested_size, first_nl), + line_pos.GetGlobalPosition(result.requested_size)); } break; } case CSVErrorType::UNTERMINATED_QUOTES: - if (current_line_position.begin == line_pos) { + if (result.current_line_position.begin == line_pos) { csv_error = CSVError::UnterminatedQuotesError( - state_machine.options, col_idx, lines_per_batch, borked_line, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl), - line_pos.GetGlobalPosition(requested_size, first_nl)); + result.state_machine.options, col_idx, lines_per_batch, borked_line, + result.current_line_position.begin.GetGlobalPosition(result.requested_size, first_nl), + line_pos.GetGlobalPosition(result.requested_size, first_nl)); } else { csv_error = CSVError::UnterminatedQuotesError( - state_machine.options, col_idx, lines_per_batch, borked_line, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl), - line_pos.GetGlobalPosition(requested_size)); + result.state_machine.options, col_idx, lines_per_batch, borked_line, + result.current_line_position.begin.GetGlobalPosition(result.requested_size, first_nl), + line_pos.GetGlobalPosition(result.requested_size)); } break; case CSVErrorType::CAST_ERROR: - if (current_line_position.begin == line_pos) { + if (result.current_line_position.begin == line_pos) { csv_error = CSVError::CastError( - state_machine.options, names[cur_error.col_idx], cur_error.error_message, cur_error.col_idx, - borked_line, lines_per_batch, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl), - line_pos.GetGlobalPosition(requested_size, first_nl), parse_types[cur_error.col_idx].first); + result.state_machine.options, result.names[cur_error.col_idx], cur_error.error_message, + cur_error.col_idx, borked_line, lines_per_batch, + result.current_line_position.begin.GetGlobalPosition(result.requested_size, first_nl), + line_pos.GetGlobalPosition(result.requested_size, first_nl), + result.parse_types[cur_error.chunk_idx].type_id); } else { csv_error = CSVError::CastError( - state_machine.options, names[cur_error.col_idx], cur_error.error_message, cur_error.col_idx, - borked_line, lines_per_batch, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl), - line_pos.GetGlobalPosition(requested_size), parse_types[cur_error.col_idx].first); + result.state_machine.options, result.names[cur_error.col_idx], cur_error.error_message, + cur_error.col_idx, borked_line, lines_per_batch, + result.current_line_position.begin.GetGlobalPosition(result.requested_size, first_nl), + line_pos.GetGlobalPosition(result.requested_size), result.parse_types[cur_error.chunk_idx].type_id); } break; case CSVErrorType::MAXIMUM_LINE_SIZE: csv_error = CSVError::LineSizeError( - state_machine.options, cur_error.current_line_size, lines_per_batch, borked_line, - current_line_position.begin.GetGlobalPosition(requested_size, first_nl)); + result.state_machine.options, cur_error.current_line_size, lines_per_batch, borked_line, + result.current_line_position.begin.GetGlobalPosition(result.requested_size, first_nl)); break; default: throw InvalidInputException("CSV Error not allowed when inserting row"); } - error_handler.Error(csv_error); + result.error_handler.Error(csv_error); } - if (!current_errors.empty()) { - current_errors.clear(); - cur_col_id = 0; - chunk_col_id = 0; + if (is_error_in_line) { + result.borked_rows.insert(result.number_of_rows); + result.cur_col_id = 0; + result.chunk_col_id = 0; + Reset(); return true; } return false; @@ -465,8 +577,7 @@ void StringValueResult::QuotedNewLine(StringValueResult &result) { void StringValueResult::NullPaddingQuotedNewlineCheck() { // We do some checks for null_padding correctness - if (state_machine.options.null_padding && iterator.IsBoundarySet() && quoted_new_line && - !state_machine.options.IgnoreErrors()) { + if (state_machine.options.null_padding && iterator.IsBoundarySet() && quoted_new_line) { // If we have null_padding set, we found a quoted new line, we are scanning the file in parallel; We error. LinesPerBoundary lines_per_batch(iterator.GetBoundaryIdx(), lines_read); auto csv_error = CSVError::NullPaddingFail(state_machine.options, lines_per_batch); @@ -521,17 +632,22 @@ bool StringValueResult::AddRowInternal() { } current_line_position.begin = current_line_position.end; current_line_position.end = current_line_start; - if (current_line_size > state_machine.options.maximum_line_size && !state_machine.options.IgnoreErrors()) { - current_errors.push_back({CSVErrorType::MAXIMUM_LINE_SIZE, 1, last_position}); - current_errors.back().current_line_size = current_line_size; + if (current_line_size > state_machine.options.maximum_line_size) { + current_errors.Insert(CSVErrorType::MAXIMUM_LINE_SIZE, 1, chunk_col_id, last_position, current_line_size); } - if (!current_errors.empty() && !state_machine.options.IgnoreErrors()) { - // We need to add a few columns error + if (!state_machine.options.null_padding) { for (idx_t col_idx = cur_col_id; col_idx < number_of_columns; col_idx++) { - current_errors.push_back({CSVErrorType::TOO_FEW_COLUMNS, col_idx - 1, last_position}); + current_errors.Insert(CSVErrorType::TOO_FEW_COLUMNS, col_idx - 1, chunk_col_id, last_position); } } - if (HandleError()) { + + if (current_errors.HandleErrors(*this)) { + line_positions_per_row[number_of_rows] = current_line_position; + number_of_rows++; + if (number_of_rows >= result_size) { + // We have a full chunk + return true; + } return false; } NullPaddingQuotedNewlineCheck(); @@ -621,14 +737,13 @@ bool StringValueResult::AddRow(StringValueResult &result, const idx_t buffer_pos } void StringValueResult::InvalidState(StringValueResult &result) { - if (!result.state_machine.options.IgnoreErrors()) { - bool force_error = !result.state_machine.options.ignore_errors.GetValue() && result.sniffing; - // Invalid unicode, we must error - if (force_error) { - result.HandleUnicodeError(result.cur_col_id, result.last_position); - } - result.current_errors.push_back({CSVErrorType::UNTERMINATED_QUOTES, result.cur_col_id, result.last_position}); + bool force_error = !result.state_machine.options.ignore_errors.GetValue() && result.sniffing; + // Invalid unicode, we must error + if (force_error) { + result.HandleUnicodeError(result.cur_col_id, result.last_position); } + result.current_errors.Insert(CSVErrorType::UNTERMINATED_QUOTES, result.cur_col_id, result.chunk_col_id, + result.last_position); } bool StringValueResult::EmptyLine(StringValueResult &result, const idx_t buffer_pos) { @@ -665,31 +780,34 @@ StringValueScanner::StringValueScanner(idx_t scanner_idx_p, const shared_ptr &state_machine, const shared_ptr &error_handler, const shared_ptr &csv_file_scan, bool sniffing, - CSVIterator boundary, idx_t result_size) + CSVIterator boundary, bool figure_out_nl) : BaseScanner(buffer_manager, state_machine, error_handler, sniffing, csv_file_scan, boundary), scanner_idx(scanner_idx_p), - result(states, *state_machine, cur_buffer_handle, BufferAllocator::Get(buffer_manager->context), result_size, + result(states, *state_machine, cur_buffer_handle, BufferAllocator::Get(buffer_manager->context), figure_out_nl, iterator.pos.buffer_pos, *error_handler, iterator, buffer_manager->context.client_data->debug_set_max_line_length, csv_file_scan, lines_read, sniffing) { } StringValueScanner::StringValueScanner(const shared_ptr &buffer_manager, const shared_ptr &state_machine, - const shared_ptr &error_handler) - : BaseScanner(buffer_manager, state_machine, error_handler, false, nullptr, {}), scanner_idx(0), - result(states, *state_machine, cur_buffer_handle, Allocator::DefaultAllocator(), STANDARD_VECTOR_SIZE, - iterator.pos.buffer_pos, *error_handler, iterator, - buffer_manager->context.client_data->debug_set_max_line_length, csv_file_scan, lines_read, sniffing) { + const shared_ptr &error_handler, CSVIterator boundary) + : BaseScanner(buffer_manager, state_machine, error_handler, false, nullptr, boundary), scanner_idx(0), + result(states, *state_machine, cur_buffer_handle, Allocator::DefaultAllocator(), false, iterator.pos.buffer_pos, + *error_handler, iterator, buffer_manager->context.client_data->debug_set_max_line_length, csv_file_scan, + lines_read, sniffing) { } unique_ptr StringValueScanner::GetCSVScanner(ClientContext &context, CSVReaderOptions &options) { + // Its possible we might have to do some skipping first auto state_machine = make_shared_ptr(options, options.dialect_options.state_machine_options, CSVStateMachineCache::Get(context)); state_machine->dialect_options.num_cols = options.dialect_options.num_cols; state_machine->dialect_options.header = options.dialect_options.header; auto buffer_manager = make_shared_ptr(context, options, options.file_path, 0); - auto scanner = make_uniq(buffer_manager, state_machine, make_shared_ptr()); + idx_t rows_to_skip = state_machine->options.GetSkipRows() + state_machine->options.GetHeader(); + auto it = BaseScanner::SkipCSVRows(buffer_manager, state_machine, rows_to_skip); + auto scanner = make_uniq(buffer_manager, state_machine, make_shared_ptr(), it); scanner->csv_file_scan = make_shared_ptr(context, options.file_path, options); scanner->csv_file_scan->InitializeProjection(); return scanner; @@ -711,7 +829,6 @@ void StringValueScanner::Flush(DataChunk &insert_chunk) { auto &parse_chunk = process_result.ToChunk(); // We have to check if we got to error error_handler->ErrorIfNeeded(); - if (parse_chunk.size() == 0) { return; } @@ -719,7 +836,6 @@ void StringValueScanner::Flush(DataChunk &insert_chunk) { insert_chunk.SetCardinality(parse_chunk); // We keep track of the borked lines, in case we are ignoring errors - unordered_set borked_lines; D_ASSERT(csv_file_scan); auto &reader_data = csv_file_scan->reader_data; @@ -742,22 +858,9 @@ void StringValueScanner::Flush(DataChunk &insert_chunk) { result_vector.Reinterpret(parse_vector); } else { string error_message; - CastParameters parameters(false, &error_message); - bool success; idx_t line_error = 0; - bool line_error_set = true; - if (state_machine->options.decimal_separator != "." && type.id() == LogicalTypeId::DECIMAL) { - success = - CSVCast::TryCastDecimalVectorCommaSeparated(state_machine->options, parse_vector, result_vector, - parse_chunk.size(), parameters, type, line_error); - - } else { - // target type is not varchar: perform a cast - success = VectorOperations::TryCast(buffer_manager->context, parse_vector, result_vector, - parse_chunk.size(), &error_message, false, true); - line_error_set = false; - } - if (success) { + if (VectorOperations::TryCast(buffer_manager->context, parse_vector, result_vector, parse_chunk.size(), + &error_message, false, true)) { continue; } // An error happened, to propagate it we need to figure out the exact line where the casting failed. @@ -765,12 +868,11 @@ void StringValueScanner::Flush(DataChunk &insert_chunk) { result_vector.ToUnifiedFormat(parse_chunk.size(), inserted_column_data); UnifiedVectorFormat parse_column_data; parse_vector.ToUnifiedFormat(parse_chunk.size(), parse_column_data); - if (!line_error_set) { - for (; line_error < parse_chunk.size(); line_error++) { - if (!inserted_column_data.validity.RowIsValid(line_error) && - parse_column_data.validity.RowIsValid(line_error)) { - break; - } + + for (; line_error < parse_chunk.size(); line_error++) { + if (!inserted_column_data.validity.RowIsValid(line_error) && + parse_column_data.validity.RowIsValid(line_error)) { + break; } } { @@ -799,13 +901,13 @@ void StringValueScanner::Flush(DataChunk &insert_chunk) { error_handler->Error(csv_error); } } - borked_lines.insert(line_error++); + result.borked_rows.insert(line_error++); D_ASSERT(state_machine->options.ignore_errors.GetValue()); // We are ignoring errors. We must continue but ignoring borked rows for (; line_error < parse_chunk.size(); line_error++) { if (!inserted_column_data.validity.RowIsValid(line_error) && parse_column_data.validity.RowIsValid(line_error)) { - borked_lines.insert(line_error); + result.borked_rows.insert(line_error); vector row; for (idx_t col = 0; col < parse_chunk.ColumnCount(); col++) { row.push_back(parse_chunk.GetValue(col, line_error)); @@ -833,12 +935,12 @@ void StringValueScanner::Flush(DataChunk &insert_chunk) { } } } - if (!borked_lines.empty()) { + if (!result.borked_rows.empty()) { // We must remove the borked lines from our chunk - SelectionVector succesful_rows(parse_chunk.size() - borked_lines.size()); + SelectionVector succesful_rows(parse_chunk.size()); idx_t sel_idx = 0; for (idx_t row_idx = 0; row_idx < parse_chunk.size(); row_idx++) { - if (borked_lines.find(row_idx) == borked_lines.end()) { + if (result.borked_rows.find(row_idx) == result.borked_rows.end()) { succesful_rows.set_index(sel_idx++, row_idx); } } @@ -849,7 +951,6 @@ void StringValueScanner::Flush(DataChunk &insert_chunk) { void StringValueScanner::Initialize() { states.Initialize(); - if (result.result_size != 1 && !(sniffing && state_machine->options.null_padding && !state_machine->options.dialect_options.skip_rows.IsSetByUser())) { SetStart(); @@ -1133,33 +1234,13 @@ bool StringValueScanner::MoveToNextBuffer() { return false; } -void StringValueScanner::SkipBOM() { - if (cur_buffer_handle->actual_size >= 3 && result.buffer_ptr[0] == '\xEF' && result.buffer_ptr[1] == '\xBB' && - result.buffer_ptr[2] == '\xBF') { +void StringValueResult::SkipBOM() { + if (buffer_size >= 3 && buffer_ptr[0] == '\xEF' && buffer_ptr[1] == '\xBB' && buffer_ptr[2] == '\xBF' && + iterator.pos.buffer_pos == 0) { iterator.pos.buffer_pos = 3; } } -void StringValueScanner::SkipCSVRows() { - idx_t rows_to_skip = - state_machine->dialect_options.skip_rows.GetValue() + state_machine->dialect_options.header.GetValue(); - if (rows_to_skip == 0) { - return; - } - SkipScanner row_skipper(buffer_manager, state_machine, error_handler, rows_to_skip); - row_skipper.ParseChunk(); - iterator.pos.buffer_pos = row_skipper.GetIteratorPosition(); - if (row_skipper.state_machine->options.dialect_options.state_machine_options.new_line == - NewLineIdentifier::CARRY_ON && - row_skipper.states.states[1] == CSVState::CARRIAGE_RETURN) { - iterator.pos.buffer_pos++; - } - if (result.store_line_size) { - result.error_handler.NewMaxLineSize(iterator.pos.buffer_pos); - } - lines_read += row_skipper.GetLinesRead(); -} - void StringValueScanner::SkipUntilNewLine() { // Now skip until next newline if (state_machine->options.dialect_options.state_machine_options.new_line.GetValue() == @@ -1190,8 +1271,7 @@ void StringValueScanner::SkipUntilNewLine() { } } -bool StringValueScanner::CanDirectlyCast(const LogicalType &type, - const map> &format_options) { +bool StringValueScanner::CanDirectlyCast(const LogicalType &type) { switch (type.id()) { case LogicalTypeId::TINYINT: @@ -1206,6 +1286,8 @@ bool StringValueScanner::CanDirectlyCast(const LogicalType &type, case LogicalTypeId::FLOAT: case LogicalTypeId::DATE: case LogicalTypeId::TIMESTAMP: + case LogicalTypeId::TIME: + case LogicalTypeId::DECIMAL: case LogicalType::VARCHAR: return true; default: @@ -1214,12 +1296,10 @@ bool StringValueScanner::CanDirectlyCast(const LogicalType &type, } void StringValueScanner::SetStart() { - if (iterator.pos.buffer_idx == 0 && iterator.pos.buffer_pos == 0) { - // This means this is the very first buffer - // This CSV is not from auto-detect, so we don't know where exactly it starts - // Hence we potentially have to skip empty lines and headers. - SkipBOM(); - SkipCSVRows(); + if (iterator.first_one) { + if (result.store_line_size) { + result.error_handler.NewMaxLineSize(iterator.pos.buffer_pos); + } return; } // We have to look for a new line that fits our schema @@ -1232,13 +1312,13 @@ void StringValueScanner::SetStart() { // When Null Padding, we assume we start from the correct new-line return; } - scan_finder = make_uniq(0U, buffer_manager, state_machine, make_shared_ptr(true), - csv_file_scan, false, iterator, 1U); + csv_file_scan, false, iterator, true); auto &tuples = scan_finder->ParseChunk(); line_found = true; - if (tuples.number_of_rows != 1) { + if (tuples.number_of_rows != 1 || + (!tuples.borked_rows.empty() && !state_machine->options.ignore_errors.GetValue())) { line_found = false; // If no tuples were parsed, this is not the correct start, we need to skip until the next new line // Or if columns don't match, this is not the correct start, we need to skip until the next new line @@ -1253,16 +1333,7 @@ void StringValueScanner::SetStart() { } } if (iterator.pos.buffer_pos == cur_buffer_handle->actual_size || - scan_finder->iterator.GetBufferIdx() >= iterator.GetBufferIdx()) { - // Propagate any errors - if (!scan_finder->error_handler->errors.empty() && state_machine->options.ignore_errors.GetValue()) { - for (auto &error_vector : scan_finder->error_handler->errors) { - for (auto &error : error_vector.second) { - error_handler->Error(error); - } - } - result.lines_read++; - } + scan_finder->iterator.GetBufferIdx() > iterator.GetBufferIdx()) { // If things go terribly wrong, we never loop indefinetly. iterator.pos.buffer_idx = scan_finder->iterator.pos.buffer_idx; iterator.pos.buffer_pos = scan_finder->iterator.pos.buffer_pos; @@ -1272,15 +1343,6 @@ void StringValueScanner::SetStart() { } } } while (!line_found); - // Propagate any errors - if (!scan_finder->error_handler->errors.empty() && state_machine->options.ignore_errors.GetValue()) { - for (auto &error_vector : scan_finder->error_handler->errors) { - for (auto &error : error_vector.second) { - error_handler->Error(error); - } - } - result.lines_read++; - } iterator.pos.buffer_idx = scan_finder->result.current_line_position.begin.buffer_idx; iterator.pos.buffer_pos = scan_finder->result.current_line_position.begin.buffer_pos; result.last_position = {iterator.pos.buffer_idx, iterator.pos.buffer_pos, result.buffer_size}; @@ -1300,12 +1362,9 @@ void StringValueScanner::FinalizeChunkProcess() { // If we are not done we have two options. // 1) If a boundary is set. if (iterator.IsBoundarySet()) { - for (auto &cur_error : result.current_errors) { - if (!(cur_error == CSVErrorType::UNTERMINATED_QUOTES)) { - iterator.done = true; - } + if (!result.current_errors.HasErrorType(CSVErrorType::UNTERMINATED_QUOTES)) { + iterator.done = true; } - // We read until the next line or until we have nothing else to read. // Move to next buffer if (!cur_buffer_handle) { @@ -1322,7 +1381,7 @@ void StringValueScanner::FinalizeChunkProcess() { MoveToNextBuffer(); } } else { - result.HandleError(); + result.current_errors.HandleErrors(result); } if (!iterator.done) { if (iterator.pos.buffer_pos >= iterator.GetEndPos() || iterator.pos.buffer_idx > iterator.GetBufferIdx() || diff --git a/src/execution/operator/csv_scanner/sniffer/dialect_detection.cpp b/src/execution/operator/csv_scanner/sniffer/dialect_detection.cpp index 0d8d2fe45ed..48682a798df 100644 --- a/src/execution/operator/csv_scanner/sniffer/dialect_detection.cpp +++ b/src/execution/operator/csv_scanner/sniffer/dialect_detection.cpp @@ -68,6 +68,8 @@ void CSVSniffer::GenerateStateMachineSearchSpace(vector(options, state_machine_options, state_machine_cache); + make_shared_ptr(options, state_machine_options, state_machine_cache); + if (options.dialect_options.skip_rows.IsSetByUser()) { + if (!iterator_set) { + first_iterator = BaseScanner::SkipCSVRows(buffer_manager, sniffing_state_machine, + options.dialect_options.skip_rows.GetValue()); + iterator_set = true; + } + column_count_scanners.emplace_back( + make_uniq(buffer_manager, std::move(sniffing_state_machine), + detection_error_handler, first_iterator)); + continue; + } column_count_scanners.emplace_back(make_uniq( buffer_manager, std::move(sniffing_state_machine), detection_error_handler)); } @@ -90,13 +103,13 @@ void CSVSniffer::AnalyzeDialectCandidate(unique_ptr scanner, idx_t &best_consistent_rows, idx_t &prev_padding_count) { // The sniffed_column_counts variable keeps track of the number of columns found for each row auto &sniffed_column_counts = scanner->ParseChunk(); + idx_t dirty_notes = 0; if (sniffed_column_counts.error) { // This candidate has an error (i.e., over maximum line size or never unquoting quoted values) return; } - idx_t start_row = options.dialect_options.skip_rows.GetValue(); idx_t consistent_rows = 0; - idx_t num_cols = sniffed_column_counts.result_position == 0 ? 1 : sniffed_column_counts[start_row]; + idx_t num_cols = sniffed_column_counts.result_position == 0 ? 1 : sniffed_column_counts[0]; idx_t padding_count = 0; bool allow_padding = options.null_padding; if (sniffed_column_counts.result_position > rows_read) { @@ -107,7 +120,7 @@ void CSVSniffer::AnalyzeDialectCandidate(unique_ptr scanner, // Not acceptable return; } - for (idx_t row = start_row; row < sniffed_column_counts.result_position; row++) { + for (idx_t row = 0; row < sniffed_column_counts.result_position; row++) { if (set_columns.IsCandidateUnacceptable(sniffed_column_counts[row], options.null_padding, options.ignore_errors.GetValue(), sniffed_column_counts.last_value_always_empty)) { @@ -122,7 +135,7 @@ void CSVSniffer::AnalyzeDialectCandidate(unique_ptr scanner, padding_count = 0; // we use the maximum amount of num_cols that we find num_cols = sniffed_column_counts[row]; - start_row = row; + dirty_notes = row; consistent_rows = 1; } else if (num_cols >= sniffed_column_counts[row]) { @@ -148,7 +161,7 @@ void CSVSniffer::AnalyzeDialectCandidate(unique_ptr scanner, // If the number of rows is consistent with the calculated value after accounting for skipped rows and the // start row. - bool rows_consistent = consistent_rows + (start_row - options.dialect_options.skip_rows.GetValue()) == + bool rows_consistent = consistent_rows + (dirty_notes - options.dialect_options.skip_rows.GetValue()) == sniffed_column_counts.result_position - options.dialect_options.skip_rows.GetValue(); // If there are more than one consistent row. bool more_than_one_row = (consistent_rows > 1); @@ -158,7 +171,7 @@ void CSVSniffer::AnalyzeDialectCandidate(unique_ptr scanner, // If the start position is valid. bool start_good = !candidates.empty() && - (start_row <= candidates.front()->GetStateMachine().dialect_options.skip_rows.GetValue()); + (dirty_notes <= candidates.front()->GetStateMachine().dialect_options.skip_rows.GetValue()); // If padding happened but it is not allowed. bool invalid_padding = !allow_padding && padding_count > 0; @@ -186,11 +199,17 @@ void CSVSniffer::AnalyzeDialectCandidate(unique_ptr scanner, best_consistent_rows = consistent_rows; max_columns_found = num_cols; prev_padding_count = padding_count; - if (!options.null_padding && !options.ignore_errors.GetValue()) { - sniffing_state_machine.dialect_options.skip_rows = start_row; - } else { + if (options.dialect_options.skip_rows.IsSetByUser()) { + // If skip rows is set by user, and we found dirty notes, we only accept it if either null_padding or + // ignore_errors is set + if (dirty_notes != 0 && !options.null_padding && !options.ignore_errors.GetValue()) { + return; + } sniffing_state_machine.dialect_options.skip_rows = options.dialect_options.skip_rows.GetValue(); + } else if (!options.null_padding && !options.ignore_errors.GetValue()) { + sniffing_state_machine.dialect_options.skip_rows = dirty_notes; } + candidates.clear(); sniffing_state_machine.dialect_options.num_cols = num_cols; candidates.emplace_back(std::move(scanner)); @@ -211,11 +230,17 @@ void CSVSniffer::AnalyzeDialectCandidate(unique_ptr scanner, } } if (!same_quote_is_candidate) { - if (!options.null_padding && !options.ignore_errors.GetValue()) { - sniffing_state_machine.dialect_options.skip_rows = start_row; - } else { + if (options.dialect_options.skip_rows.IsSetByUser()) { + // If skip rows is set by user, and we found dirty notes, we only accept it if either null_padding or + // ignore_errors is set + if (dirty_notes != 0 && !options.null_padding && !options.ignore_errors.GetValue()) { + return; + } sniffing_state_machine.dialect_options.skip_rows = options.dialect_options.skip_rows.GetValue(); + } else if (!options.null_padding && !options.ignore_errors.GetValue()) { + sniffing_state_machine.dialect_options.skip_rows = dirty_notes; } + sniffing_state_machine.dialect_options.num_cols = num_cols; candidates.emplace_back(std::move(scanner)); } @@ -278,9 +303,7 @@ void CSVSniffer::RefineCandidates() { candidates.push_back(std::move(cc_best_candidate)); return; } - if (cc_best_candidate->state_machine->state_machine_options.quote == '\0') { - candidates.push_back(std::move(cc_best_candidate)); - } + candidates.push_back(std::move(cc_best_candidate)); } return; } @@ -344,7 +367,6 @@ void CSVSniffer::DetectDialect() { escape_candidates_map); // Step 3: Analyze all candidates on the first chunk for (auto &state_machine : csv_state_machines) { - state_machine->Reset(); AnalyzeDialectCandidate(std::move(state_machine), rows_read, best_consistent_rows, prev_padding_count); } // Step 4: Loop over candidates and find if they can still produce good results for the remaining chunks diff --git a/src/execution/operator/csv_scanner/sniffer/header_detection.cpp b/src/execution/operator/csv_scanner/sniffer/header_detection.cpp index d6ddff70dd9..e5498a57ffa 100644 --- a/src/execution/operator/csv_scanner/sniffer/header_detection.cpp +++ b/src/execution/operator/csv_scanner/sniffer/header_detection.cpp @@ -126,7 +126,7 @@ bool CSVSniffer::DetectHeaderWithSetColumn() { if (sql_type != LogicalType::VARCHAR) { all_varchar = false; if (!CanYouCastIt(best_header_row[col].value, sql_type, options.dialect_options, - best_header_row[col].IsNull())) { + best_header_row[col].IsNull(), options.decimal_separator[0])) { first_row_consistent = false; } } @@ -178,7 +178,7 @@ void CSVSniffer::DetectHeader() { if (sql_type != LogicalType::VARCHAR) { all_varchar = false; if (!CanYouCastIt(best_header_row[col].value, sql_type, sniffer_state_machine.dialect_options, - best_header_row[col].IsNull())) { + best_header_row[col].IsNull(), options.decimal_separator[0])) { first_row_consistent = false; } } diff --git a/src/execution/operator/csv_scanner/sniffer/type_detection.cpp b/src/execution/operator/csv_scanner/sniffer/type_detection.cpp index 7e7898baf8f..8cb87dcbdd1 100644 --- a/src/execution/operator/csv_scanner/sniffer/type_detection.cpp +++ b/src/execution/operator/csv_scanner/sniffer/type_detection.cpp @@ -1,9 +1,10 @@ -#include "duckdb/common/operator/decimal_cast_operators.hpp" -#include "duckdb/execution/operator/csv_scanner/csv_sniffer.hpp" #include "duckdb/common/algorithm.hpp" -#include "duckdb/common/string.hpp" -#include "duckdb/common/operator/integer_cast_operator.hpp" +#include "duckdb/common/operator/decimal_cast_operators.hpp" #include "duckdb/common/operator/double_cast_operator.hpp" +#include "duckdb/common/operator/integer_cast_operator.hpp" +#include "duckdb/common/string.hpp" +#include "duckdb/common/types/time.hpp" +#include "duckdb/execution/operator/csv_scanner/csv_sniffer.hpp" namespace duckdb { struct TryCastFloatingOperator { @@ -95,7 +96,7 @@ void CSVSniffer::SetDateFormat(CSVStateMachine &candidate, const string &format_ } bool CSVSniffer::CanYouCastIt(const string_t value, const LogicalType &type, const DialectOptions &dialect_options, - const bool is_null) { + const bool is_null, const char decimal_separator) { if (is_null) { return true; } @@ -157,17 +158,81 @@ bool CSVSniffer::CanYouCastIt(const string_t value, const LogicalType &type, con } } case LogicalTypeId::TIMESTAMP: { + timestamp_t dummy_value; if (!dialect_options.date_format.find(LogicalTypeId::TIMESTAMP)->second.GetValue().Empty()) { - timestamp_t result; string error_message; return dialect_options.date_format.find(LogicalTypeId::TIMESTAMP) ->second.GetValue() - .TryParseTimestamp(value, result, error_message); + .TryParseTimestamp(value, dummy_value, error_message); } else { - timestamp_t dummy_value; return Timestamp::TryConvertTimestamp(value_ptr, value_size, dummy_value) == TimestampCastResult::SUCCESS; } } + case LogicalTypeId::TIME: { + idx_t pos; + dtime_t dummy_value; + return Time::TryConvertTime(value_ptr, value_size, pos, dummy_value, true); + } + case LogicalTypeId::DECIMAL: { + uint8_t width, scale; + type.GetDecimalProperties(width, scale); + if (decimal_separator == ',') { + switch (type.InternalType()) { + case PhysicalType::INT16: { + int16_t dummy_value; + return TryDecimalStringCast(value_ptr, value_size, dummy_value, width, scale); + } + + case PhysicalType::INT32: { + int32_t dummy_value; + return TryDecimalStringCast(value_ptr, value_size, dummy_value, width, scale); + } + + case PhysicalType::INT64: { + int64_t dummy_value; + return TryDecimalStringCast(value_ptr, value_size, dummy_value, width, scale); + } + + case PhysicalType::INT128: { + hugeint_t dummy_value; + return TryDecimalStringCast(value_ptr, value_size, dummy_value, width, scale); + } + + default: + throw InternalException("Invalid Physical Type for Decimal Value. Physical Type: " + + TypeIdToString(type.InternalType())); + } + + } else if (decimal_separator == '.') { + switch (type.InternalType()) { + case PhysicalType::INT16: { + int16_t dummy_value; + return TryDecimalStringCast(value_ptr, value_size, dummy_value, width, scale); + } + + case PhysicalType::INT32: { + int32_t dummy_value; + return TryDecimalStringCast(value_ptr, value_size, dummy_value, width, scale); + } + + case PhysicalType::INT64: { + int64_t dummy_value; + return TryDecimalStringCast(value_ptr, value_size, dummy_value, width, scale); + } + + case PhysicalType::INT128: { + hugeint_t dummy_value; + return TryDecimalStringCast(value_ptr, value_size, dummy_value, width, scale); + } + + default: + throw InternalException("Invalid Physical Type for Decimal Value. Physical Type: " + + TypeIdToString(type.InternalType())); + } + } else { + throw InvalidInputException("Decimals can only have ',' and '.' as decimal separators"); + } + } case LogicalTypeId::VARCHAR: return true; default: { @@ -271,7 +336,6 @@ void CSVSniffer::DetectTypes() { // Reset candidate for parsing auto candidate = candidate_cc->UpgradeToStringValueScanner(); - // Parse chunk and read csv with info candidate auto &data_chunk = candidate->ParseChunk().ToChunk(); idx_t row_idx = 0; @@ -300,7 +364,7 @@ void CSVSniffer::DetectTypes() { // try cast from string to sql_type while (col_type_candidates.size() > 1) { const auto &sql_type = col_type_candidates.back(); - // try formatting for date types if the user did not specify one and it starts with numeric + // try formatting for date types if the user did not specify one, and it starts with numeric // values. string separator; // If Value is not Null, Has a numeric date format, and the current investigated candidate is @@ -317,7 +381,8 @@ void CSVSniffer::DetectTypes() { continue; } if (CanYouCastIt(vector_data[row_idx], sql_type, sniffing_state_machine.dialect_options, - !null_mask.RowIsValid(row_idx))) { + !null_mask.RowIsValid(row_idx), + sniffing_state_machine.options.decimal_separator[0])) { break; } else { if (row_idx != start_idx_detection && cur_top_candidate == LogicalType::BOOLEAN) { @@ -347,7 +412,8 @@ void CSVSniffer::DetectTypes() { // it's good if the dialect creates more non-varchar columns, but only if we sacrifice < 30% of // best_num_cols. - if (varchar_cols < min_varchar_cols && info_sql_types_candidates.size() > (max_columns_found * 0.7) && + if (varchar_cols(info_sql_types_candidates.size())>( + static_cast(max_columns_found) * 0.7) && (!options.ignore_errors.GetValue() || candidate->error_handler->errors.size() < min_errors)) { min_errors = candidate->error_handler->errors.size(); best_header_row.clear(); diff --git a/src/execution/operator/csv_scanner/table_function/csv_file_scanner.cpp b/src/execution/operator/csv_scanner/table_function/csv_file_scanner.cpp index eeb563cf771..3bdb8e925e9 100644 --- a/src/execution/operator/csv_scanner/table_function/csv_file_scanner.cpp +++ b/src/execution/operator/csv_scanner/table_function/csv_file_scanner.cpp @@ -1,6 +1,8 @@ #include "duckdb/execution/operator/csv_scanner/csv_file_scanner.hpp" -#include "duckdb/function/table/read_csv.hpp" + #include "duckdb/execution/operator/csv_scanner/csv_sniffer.hpp" +#include "duckdb/execution/operator/csv_scanner/skip_scanner.hpp" +#include "duckdb/function/table/read_csv.hpp" namespace duckdb { @@ -12,38 +14,53 @@ CSVFileScan::CSVFileScan(ClientContext &context, shared_ptr bu state_machine(std::move(state_machine_p)), file_size(buffer_manager->file_handle->FileSize()), error_handler(make_shared_ptr(options_p.ignore_errors.GetValue())), on_disk_file(buffer_manager->file_handle->OnDiskFile()), options(options_p) { + + auto multi_file_reader = MultiFileReader::CreateDefault("CSV Scan"); if (bind_data.initial_reader.get()) { auto &union_reader = *bind_data.initial_reader; names = union_reader.GetNames(); options = union_reader.options; types = union_reader.GetTypes(); - MultiFileReader::InitializeReader(*this, options.file_options, bind_data.reader_bind, bind_data.return_types, - bind_data.return_names, column_ids, nullptr, file_path, context); + multi_file_reader->InitializeReader(*this, options.file_options, bind_data.reader_bind, bind_data.return_types, + bind_data.return_names, column_ids, nullptr, file_path, context, nullptr); InitializeFileNamesTypes(); return; } else if (!bind_data.column_info.empty()) { // Serialized Union By name names = bind_data.column_info[0].names; types = bind_data.column_info[0].types; - MultiFileReader::InitializeReader(*this, options.file_options, bind_data.reader_bind, bind_data.return_types, - bind_data.return_names, column_ids, nullptr, file_path, context); + multi_file_reader->InitializeReader(*this, options.file_options, bind_data.reader_bind, bind_data.return_types, + bind_data.return_names, column_ids, nullptr, file_path, context, nullptr); InitializeFileNamesTypes(); return; } names = bind_data.return_names; types = bind_data.return_types; file_schema = bind_data.return_types; - MultiFileReader::InitializeReader(*this, options.file_options, bind_data.reader_bind, bind_data.return_types, - bind_data.return_names, column_ids, nullptr, file_path, context); + multi_file_reader->InitializeReader(*this, options.file_options, bind_data.reader_bind, bind_data.return_types, + bind_data.return_names, column_ids, nullptr, file_path, context, nullptr); InitializeFileNamesTypes(); + SetStart(); +} + +void CSVFileScan::SetStart() { + idx_t rows_to_skip = options.GetSkipRows() + state_machine->dialect_options.header.GetValue(); + if (rows_to_skip == 0) { + start_iterator.first_one = true; + return; + } + SkipScanner skip_scanner(buffer_manager, state_machine, error_handler, rows_to_skip); + skip_scanner.ParseChunk(); + start_iterator = skip_scanner.GetIterator(); } CSVFileScan::CSVFileScan(ClientContext &context, const string &file_path_p, const CSVReaderOptions &options_p, const idx_t file_idx_p, const ReadCSVData &bind_data, const vector &column_ids, - const vector &file_schema) + const vector &file_schema, bool per_file_single_threaded) : file_path(file_path_p), file_idx(file_idx_p), error_handler(make_shared_ptr(options_p.ignore_errors.GetValue())), options(options_p) { + auto multi_file_reader = MultiFileReader::CreateDefault("CSV Scan"); if (file_idx < bind_data.union_readers.size()) { // we are doing UNION BY NAME - fetch the options from the union reader for this file optional_ptr union_reader_ptr; @@ -63,17 +80,18 @@ CSVFileScan::CSVFileScan(ClientContext &context, const string &file_path_p, cons options = union_reader.options; types = union_reader.GetTypes(); state_machine = union_reader.state_machine; - MultiFileReader::InitializeReader(*this, options.file_options, bind_data.reader_bind, - bind_data.return_types, bind_data.return_names, column_ids, nullptr, - file_path, context); + multi_file_reader->InitializeReader(*this, options.file_options, bind_data.reader_bind, + bind_data.return_types, bind_data.return_names, column_ids, nullptr, + file_path, context, nullptr); InitializeFileNamesTypes(); + SetStart(); return; } } // Initialize Buffer Manager - buffer_manager = make_shared_ptr(context, options, file_path, file_idx); + buffer_manager = make_shared_ptr(context, options, file_path, file_idx, per_file_single_threaded); // Initialize On Disk and Size of file on_disk_file = buffer_manager->file_handle->OnDiskFile(); file_size = buffer_manager->file_handle->FileSize(); @@ -92,9 +110,10 @@ CSVFileScan::CSVFileScan(ClientContext &context, const string &file_path_p, cons state_machine = make_shared_ptr( state_machine_cache.Get(options.dialect_options.state_machine_options), options); - MultiFileReader::InitializeReader(*this, options.file_options, bind_data.reader_bind, bind_data.return_types, - bind_data.return_names, column_ids, nullptr, file_path, context); + multi_file_reader->InitializeReader(*this, options.file_options, bind_data.reader_bind, bind_data.return_types, + bind_data.return_names, column_ids, nullptr, file_path, context, nullptr); InitializeFileNamesTypes(); + SetStart(); return; } // Sniff it (We only really care about dialect detection, if types or number of columns are different this will @@ -123,9 +142,10 @@ CSVFileScan::CSVFileScan(ClientContext &context, const string &file_path_p, cons state_machine = make_shared_ptr( state_machine_cache.Get(options.dialect_options.state_machine_options), options); - MultiFileReader::InitializeReader(*this, options.file_options, bind_data.reader_bind, bind_data.return_types, - bind_data.return_names, column_ids, nullptr, file_path, context); + multi_file_reader->InitializeReader(*this, options.file_options, bind_data.reader_bind, bind_data.return_types, + bind_data.return_names, column_ids, nullptr, file_path, context, nullptr); InitializeFileNamesTypes(); + SetStart(); } CSVFileScan::CSVFileScan(ClientContext &context, const string &file_name, CSVReaderOptions &options_p) @@ -153,6 +173,7 @@ CSVFileScan::CSVFileScan(ClientContext &context, const string &file_name, CSVRea // Initialize State Machine state_machine = make_shared_ptr( state_machine_cache.Get(options.dialect_options.state_machine_options), options); + SetStart(); } void CSVFileScan::InitializeFileNamesTypes() { diff --git a/src/execution/operator/csv_scanner/table_function/global_csv_state.cpp b/src/execution/operator/csv_scanner/table_function/global_csv_state.cpp index acf19effc24..16895bc40c3 100644 --- a/src/execution/operator/csv_scanner/table_function/global_csv_state.cpp +++ b/src/execution/operator/csv_scanner/table_function/global_csv_state.cpp @@ -1,9 +1,11 @@ #include "duckdb/execution/operator/csv_scanner/global_csv_state.hpp" -#include "duckdb/main/client_data.hpp" -#include "duckdb/execution/operator/csv_scanner/scanner_boundary.hpp" + #include "duckdb/execution/operator/csv_scanner/csv_sniffer.hpp" +#include "duckdb/execution/operator/csv_scanner/scanner_boundary.hpp" +#include "duckdb/execution/operator/csv_scanner/skip_scanner.hpp" #include "duckdb/execution/operator/persistent/csv_rejects_table.hpp" #include "duckdb/main/appender.hpp" +#include "duckdb/main/client_data.hpp" namespace duckdb { @@ -22,7 +24,7 @@ CSVGlobalState::CSVGlobalState(ClientContext &context_p, const shared_ptr(context, files[0], options, 0U, bind_data, column_ids, file_schema)); + make_uniq(context, files[0], options, 0U, bind_data, column_ids, file_schema, false)); }; // There are situations where we only support single threaded scanning bool many_csv_files = files.size() > 1 && files.size() > system_threads * 2; @@ -30,13 +32,13 @@ CSVGlobalState::CSVGlobalState(ClientContext &context_p, const shared_ptrbuffer_manager->GetBuffer(0)->actual_size; - current_boundary = CSVIterator(0, 0, 0, 0, buffer_size); + current_boundary = file_scans.back()->start_iterator; + current_boundary.SetCurrentBoundaryToPosition(single_threaded); + if (current_boundary.done && context.client_data->debug_set_max_line_length) { + context.client_data->debug_max_line_length = current_boundary.pos.buffer_pos; } - current_buffer_in_use = make_shared_ptr(*file_scans.back()->buffer_manager, 0); + current_buffer_in_use = + make_shared_ptr(*file_scans.back()->buffer_manager, current_boundary.GetBufferIdx()); } double CSVGlobalState::GetProgress(const ReadCSVData &bind_data_p) const { @@ -68,8 +70,12 @@ unique_ptr CSVGlobalState::Next(optional_ptr parallel_lock(main_mutex); file_scans.emplace_back(make_shared_ptr(context, bind_data.files[cur_idx], bind_data.options, - cur_idx, bind_data, column_ids, file_schema)); + cur_idx, bind_data, column_ids, file_schema, true)); current_file = file_scans.back(); + current_boundary = current_file->start_iterator; + current_boundary.SetCurrentBoundaryToPosition(single_threaded); + current_buffer_in_use = + make_shared_ptr(*file_scans.back()->buffer_manager, current_boundary.GetBufferIdx()); } if (previous_scanner) { lock_guard parallel_lock(main_mutex); @@ -113,11 +119,12 @@ unique_ptr CSVGlobalState::Next(optional_ptr(context, bind_data.files[current_file_idx], bind_data.options, current_file_idx, bind_data, - column_ids, file_schema)); + column_ids, file_schema, false)); // And re-start the boundary-iterator - auto buffer_size = file_scans.back()->buffer_manager->GetBuffer(0)->actual_size; - current_boundary = CSVIterator(current_file_idx, 0, 0, 0, buffer_size); - current_buffer_in_use = make_shared_ptr(*file_scans.back()->buffer_manager, 0); + current_boundary = file_scans.back()->start_iterator; + current_boundary.SetCurrentBoundaryToPosition(single_threaded); + current_buffer_in_use = + make_shared_ptr(*file_scans.back()->buffer_manager, current_boundary.GetBufferIdx()); } else { // If not we are done with this CSV Scanning finished = true; diff --git a/src/execution/operator/csv_scanner/util/csv_reader_options.cpp b/src/execution/operator/csv_scanner/util/csv_reader_options.cpp index 953d2cc78ad..5e077a027e7 100644 --- a/src/execution/operator/csv_scanner/util/csv_reader_options.cpp +++ b/src/execution/operator/csv_scanner/util/csv_reader_options.cpp @@ -89,11 +89,14 @@ void CSVReaderOptions::SetEscape(const string &input) { this->dialect_options.state_machine_options.escape.Set(escape_str[0]); } -int64_t CSVReaderOptions::GetSkipRows() const { - return NumericCast(this->dialect_options.skip_rows.GetValue()); +idx_t CSVReaderOptions::GetSkipRows() const { + return NumericCast(this->dialect_options.skip_rows.GetValue()); } void CSVReaderOptions::SetSkipRows(int64_t skip_rows) { + if (skip_rows < 0) { + throw InvalidInputException("skip_rows option from read_csv scanner, must be equal or higher than 0"); + } dialect_options.skip_rows.Set(NumericCast(skip_rows)); } @@ -416,12 +419,12 @@ static Value StringVectorToValue(const vector &vec) { static uint8_t GetCandidateSpecificity(const LogicalType &candidate_type) { //! Const ht with accepted auto_types and their weights in specificity const duckdb::unordered_map auto_type_candidates_specificity { - {(uint8_t)LogicalTypeId::VARCHAR, 0}, {(uint8_t)LogicalTypeId::TIMESTAMP, 1}, - {(uint8_t)LogicalTypeId::DATE, 2}, {(uint8_t)LogicalTypeId::TIME, 3}, - {(uint8_t)LogicalTypeId::DOUBLE, 4}, {(uint8_t)LogicalTypeId::FLOAT, 5}, - {(uint8_t)LogicalTypeId::DECIMAL, 6}, {(uint8_t)LogicalTypeId::BIGINT, 7}, - {(uint8_t)LogicalTypeId::INTEGER, 8}, {(uint8_t)LogicalTypeId::SMALLINT, 9}, - {(uint8_t)LogicalTypeId::TINYINT, 10}, {(uint8_t)LogicalTypeId::BOOLEAN, 11}, + {(uint8_t)LogicalTypeId::VARCHAR, 0}, {(uint8_t)LogicalTypeId::DOUBLE, 1}, + {(uint8_t)LogicalTypeId::FLOAT, 2}, {(uint8_t)LogicalTypeId::DECIMAL, 3}, + {(uint8_t)LogicalTypeId::BIGINT, 4}, {(uint8_t)LogicalTypeId::INTEGER, 5}, + {(uint8_t)LogicalTypeId::SMALLINT, 6}, {(uint8_t)LogicalTypeId::TINYINT, 7}, + {(uint8_t)LogicalTypeId::TIMESTAMP, 8}, {(uint8_t)LogicalTypeId::DATE, 9}, + {(uint8_t)LogicalTypeId::TIME, 10}, {(uint8_t)LogicalTypeId::BOOLEAN, 11}, {(uint8_t)LogicalTypeId::SQLNULL, 12}}; auto id = (uint8_t)candidate_type.id(); @@ -445,7 +448,7 @@ void CSVReaderOptions::FromNamedParameters(named_parameter_map_t &in, ClientCont vector &return_types, vector &names) { map ordered_user_defined_parameters; for (auto &kv : in) { - if (MultiFileReader::ParseOption(kv.first, kv.second, file_options, context)) { + if (MultiFileReader().ParseOption(kv.first, kv.second, file_options, context)) { continue; } auto loption = StringUtil::Lower(kv.first); @@ -588,15 +591,17 @@ void CSVReaderOptions::ToNamedParameters(named_parameter_map_t &named_params) { } named_params["max_line_size"] = Value::BIGINT(NumericCast(maximum_line_size)); if (dialect_options.skip_rows.IsSetByUser()) { - named_params["skip"] = Value::BIGINT(GetSkipRows()); + named_params["skip"] = Value::UBIGINT(GetSkipRows()); } named_params["null_padding"] = Value::BOOLEAN(null_padding); named_params["parallel"] = Value::BOOLEAN(parallel); - if (!date_format.at(LogicalType::DATE).format_specifier.empty()) { - named_params["dateformat"] = Value(date_format.at(LogicalType::DATE).format_specifier); + if (!dialect_options.date_format.at(LogicalType::DATE).GetValue().format_specifier.empty()) { + named_params["dateformat"] = + Value(dialect_options.date_format.at(LogicalType::DATE).GetValue().format_specifier); } - if (!date_format.at(LogicalType::TIMESTAMP).format_specifier.empty()) { - named_params["timestampformat"] = Value(date_format.at(LogicalType::TIMESTAMP).format_specifier); + if (!dialect_options.date_format.at(LogicalType::TIMESTAMP).GetValue().format_specifier.empty()) { + named_params["timestampformat"] = + Value(dialect_options.date_format.at(LogicalType::TIMESTAMP).GetValue().format_specifier); } named_params["normalize_names"] = Value::BOOLEAN(normalize_names); diff --git a/src/execution/operator/helper/CMakeLists.txt b/src/execution/operator/helper/CMakeLists.txt index 68b6ed97c91..1032e71de77 100644 --- a/src/execution/operator/helper/CMakeLists.txt +++ b/src/execution/operator/helper/CMakeLists.txt @@ -3,6 +3,7 @@ add_library_unity( OBJECT physical_batch_collector.cpp physical_buffered_collector.cpp + physical_buffered_batch_collector.cpp physical_create_secret.cpp physical_execute.cpp physical_explain_analyze.cpp @@ -19,6 +20,7 @@ add_library_unity( physical_streaming_limit.cpp physical_streaming_sample.cpp physical_transaction.cpp + physical_update_extensions.cpp physical_vacuum.cpp physical_verify_vector.cpp) set(ALL_OBJECT_FILES diff --git a/src/execution/operator/helper/physical_buffered_batch_collector.cpp b/src/execution/operator/helper/physical_buffered_batch_collector.cpp new file mode 100644 index 00000000000..f881da2a97d --- /dev/null +++ b/src/execution/operator/helper/physical_buffered_batch_collector.cpp @@ -0,0 +1,109 @@ +#include "duckdb/execution/operator/helper/physical_buffered_batch_collector.hpp" + +#include "duckdb/common/types/batched_data_collection.hpp" +#include "duckdb/main/client_context.hpp" +#include "duckdb/main/materialized_query_result.hpp" +#include "duckdb/main/buffered_data/buffered_data.hpp" +#include "duckdb/main/buffered_data/batched_buffered_data.hpp" +#include "duckdb/main/stream_query_result.hpp" + +namespace duckdb { + +PhysicalBufferedBatchCollector::PhysicalBufferedBatchCollector(PreparedStatementData &data) + : PhysicalResultCollector(data) { +} + +//===--------------------------------------------------------------------===// +// Sink +//===--------------------------------------------------------------------===// +class BufferedBatchCollectorGlobalState : public GlobalSinkState { +public: + weak_ptr context; + shared_ptr buffered_data; +}; + +BufferedBatchCollectorLocalState::BufferedBatchCollectorLocalState() { +} + +SinkResultType PhysicalBufferedBatchCollector::Sink(ExecutionContext &context, DataChunk &chunk, + OperatorSinkInput &input) const { + auto &gstate = input.global_state.Cast(); + auto &lstate = input.local_state.Cast(); + + lstate.current_batch = lstate.partition_info.batch_index.GetIndex(); + auto batch = lstate.partition_info.batch_index.GetIndex(); + auto min_batch_index = lstate.partition_info.min_batch_index.GetIndex(); + + auto &buffered_data = gstate.buffered_data->Cast(); + buffered_data.UpdateMinBatchIndex(min_batch_index); + + if (buffered_data.ShouldBlockBatch(batch)) { + auto callback_state = input.interrupt_state; + buffered_data.BlockSink(callback_state, batch); + return SinkResultType::BLOCKED; + } + + // FIXME: if we want to make this more accurate, we should grab a reservation on the buffer space + // while we're unlocked some other thread could also append, causing us to potentially cross our buffer size + + buffered_data.Append(chunk, batch); + + return SinkResultType::NEED_MORE_INPUT; +} + +SinkNextBatchType PhysicalBufferedBatchCollector::NextBatch(ExecutionContext &context, + OperatorSinkNextBatchInput &input) const { + + auto &gstate = input.global_state.Cast(); + auto &lstate = input.local_state.Cast(); + + auto batch = lstate.current_batch; + auto min_batch_index = lstate.partition_info.min_batch_index.GetIndex(); + auto new_index = lstate.partition_info.batch_index.GetIndex(); + + auto &buffered_data = gstate.buffered_data->Cast(); + buffered_data.CompleteBatch(batch); + lstate.current_batch = new_index; + // FIXME: this can move from the buffer to the read queue, increasing the 'read_queue_byte_count' + // We might want to block here if 'read_queue_byte_count' has already reached the ReadQueueCapacity() + // So we don't completely disregard the 'streaming_buffer_size' that was set + buffered_data.UpdateMinBatchIndex(min_batch_index); + return SinkNextBatchType::READY; +} + +SinkCombineResultType PhysicalBufferedBatchCollector::Combine(ExecutionContext &context, + OperatorSinkCombineInput &input) const { + auto &gstate = input.global_state.Cast(); + auto &lstate = input.local_state.Cast(); + + auto min_batch_index = lstate.partition_info.min_batch_index.GetIndex(); + auto &buffered_data = gstate.buffered_data->Cast(); + + // FIXME: this can move from the buffer to the read queue, increasing the 'read_queue_byte_count' + // We might want to block here if 'read_queue_byte_count' has already reached the ReadQueueCapacity() + // So we don't completely disregard the 'streaming_buffer_size' that was set + buffered_data.UpdateMinBatchIndex(min_batch_index); + return SinkCombineResultType::FINISHED; +} + +unique_ptr PhysicalBufferedBatchCollector::GetLocalSinkState(ExecutionContext &context) const { + auto state = make_uniq(); + return std::move(state); +} + +unique_ptr PhysicalBufferedBatchCollector::GetGlobalSinkState(ClientContext &context) const { + auto state = make_uniq(); + state->context = context.shared_from_this(); + state->buffered_data = make_shared_ptr(state->context); + return std::move(state); +} + +unique_ptr PhysicalBufferedBatchCollector::GetResult(GlobalSinkState &state) { + auto &gstate = state.Cast(); + auto cc = gstate.context.lock(); + auto result = make_uniq(statement_type, properties, types, names, cc->GetClientProperties(), + gstate.buffered_data); + return std::move(result); +} + +} // namespace duckdb diff --git a/src/execution/operator/helper/physical_buffered_collector.cpp b/src/execution/operator/helper/physical_buffered_collector.cpp index 9f2ac70db09..6a036109245 100644 --- a/src/execution/operator/helper/physical_buffered_collector.cpp +++ b/src/execution/operator/helper/physical_buffered_collector.cpp @@ -19,31 +19,23 @@ class BufferedCollectorGlobalState : public GlobalSinkState { shared_ptr buffered_data; }; -class BufferedCollectorLocalState : public LocalSinkState { -public: - bool blocked = false; -}; +class BufferedCollectorLocalState : public LocalSinkState {}; SinkResultType PhysicalBufferedCollector::Sink(ExecutionContext &context, DataChunk &chunk, OperatorSinkInput &input) const { auto &gstate = input.global_state.Cast(); auto &lstate = input.local_state.Cast(); + (void)lstate; lock_guard l(gstate.glock); auto &buffered_data = gstate.buffered_data->Cast(); - if (!lstate.blocked || buffered_data.BufferIsFull()) { - lstate.blocked = true; + if (buffered_data.BufferIsFull()) { auto callback_state = input.interrupt_state; - auto blocked_sink = BlockedSink(callback_state, chunk.size()); - buffered_data.BlockSink(blocked_sink); + buffered_data.BlockSink(callback_state); return SinkResultType::BLOCKED; } - - auto to_append = make_uniq(); - to_append->Initialize(Allocator::DefaultAllocator(), chunk.GetTypes()); - chunk.Copy(*to_append, 0); - buffered_data.Append(std::move(to_append)); + buffered_data.Append(chunk); return SinkResultType::NEED_MORE_INPUT; } diff --git a/src/execution/operator/helper/physical_load.cpp b/src/execution/operator/helper/physical_load.cpp index 62054206680..e20b5af0d73 100644 --- a/src/execution/operator/helper/physical_load.cpp +++ b/src/execution/operator/helper/physical_load.cpp @@ -3,10 +3,32 @@ namespace duckdb { +static void InstallFromRepository(ClientContext &context, const LoadInfo &info) { + ExtensionRepository repository; + if (!info.repository.empty() && info.repo_is_alias) { + auto repository_url = ExtensionRepository::TryGetRepositoryUrl(info.repository); + // This has been checked during bind, so it should not fail here + if (repository_url.empty()) { + throw InternalException("The repository alias failed to resolve"); + } + repository = ExtensionRepository(info.repository, repository_url); + } else if (!info.repository.empty()) { + repository = ExtensionRepository::GetRepositoryByUrl(info.repository); + } + + ExtensionHelper::InstallExtension(context, info.filename, info.load_type == LoadType::FORCE_INSTALL, repository, + true, info.version); +} + SourceResultType PhysicalLoad::GetData(ExecutionContext &context, DataChunk &chunk, OperatorSourceInput &input) const { if (info->load_type == LoadType::INSTALL || info->load_type == LoadType::FORCE_INSTALL) { - ExtensionHelper::InstallExtension(context.client, info->filename, info->load_type == LoadType::FORCE_INSTALL, - info->repository); + if (info->repository.empty()) { + ExtensionHelper::InstallExtension(context.client, info->filename, + info->load_type == LoadType::FORCE_INSTALL, nullptr, true, info->version); + } else { + InstallFromRepository(context.client, *info); + } + } else { ExtensionHelper::LoadExternalExtension(context.client, info->filename); } diff --git a/src/execution/operator/helper/physical_result_collector.cpp b/src/execution/operator/helper/physical_result_collector.cpp index 8b2bbdf8e11..d1424ce807e 100644 --- a/src/execution/operator/helper/physical_result_collector.cpp +++ b/src/execution/operator/helper/physical_result_collector.cpp @@ -1,6 +1,7 @@ #include "duckdb/execution/operator/helper/physical_result_collector.hpp" #include "duckdb/execution/operator/helper/physical_batch_collector.hpp" +#include "duckdb/execution/operator/helper/physical_buffered_batch_collector.hpp" #include "duckdb/execution/operator/helper/physical_materialized_collector.hpp" #include "duckdb/execution/operator/helper/physical_buffered_collector.hpp" #include "duckdb/execution/physical_plan_generator.hpp" @@ -35,7 +36,7 @@ unique_ptr PhysicalResultCollector::GetResultCollector( // we care about maintaining insertion order and the sources all support batch indexes // use a batch collector if (data.is_streaming) { - return make_uniq_base(data, false); + return make_uniq_base(data); } return make_uniq_base(data); } diff --git a/src/execution/operator/helper/physical_transaction.cpp b/src/execution/operator/helper/physical_transaction.cpp index 9361cbd5428..8846cfffc34 100644 --- a/src/execution/operator/helper/physical_transaction.cpp +++ b/src/execution/operator/helper/physical_transaction.cpp @@ -28,6 +28,9 @@ SourceResultType PhysicalTransaction::GetData(ExecutionContext &context, DataChu // preserving the transaction context for the next query client.transaction.SetAutoCommit(false); auto &config = DBConfig::GetConfig(context.client); + if (info->modifier == TransactionModifierType::TRANSACTION_READ_ONLY) { + client.transaction.SetReadOnly(); + } if (config.options.immediate_transaction_mode) { // if immediate transaction mode is enabled then start all transactions immediately auto databases = DatabaseManager::Get(client).GetDatabases(client); diff --git a/src/execution/operator/helper/physical_update_extensions.cpp b/src/execution/operator/helper/physical_update_extensions.cpp new file mode 100644 index 00000000000..d29632d122d --- /dev/null +++ b/src/execution/operator/helper/physical_update_extensions.cpp @@ -0,0 +1,57 @@ +#include "duckdb/execution/operator/helper/physical_update_extensions.hpp" +#include "duckdb/main/extension_helper.hpp" + +namespace duckdb { + +SourceResultType PhysicalUpdateExtensions::GetData(ExecutionContext &context, DataChunk &chunk, + OperatorSourceInput &input) const { + auto &data = input.global_state.Cast(); + + if (data.offset >= data.update_result_entries.size()) { + // finished returning values + return SourceResultType::FINISHED; + } + + idx_t count = 0; + while (data.offset < data.update_result_entries.size() && count < STANDARD_VECTOR_SIZE) { + auto &entry = data.update_result_entries[data.offset]; + + // return values: + idx_t col = 0; + // extension_name LogicalType::VARCHAR + chunk.SetValue(col++, count, Value(entry.extension_name)); + // repository LogicalType::VARCHAR + chunk.SetValue(col++, count, Value(entry.repository)); + // update_result + chunk.SetValue(col++, count, Value(EnumUtil::ToString(entry.tag))); + // previous_version LogicalType::VARCHAR + chunk.SetValue(col++, count, Value(entry.prev_version)); + // current_version LogicalType::VARCHAR + chunk.SetValue(col++, count, Value(entry.installed_version)); + + data.offset++; + count++; + } + chunk.SetCardinality(count); + + return data.offset >= data.update_result_entries.size() ? SourceResultType::FINISHED + : SourceResultType::HAVE_MORE_OUTPUT; +} + +unique_ptr PhysicalUpdateExtensions::GetGlobalSourceState(ClientContext &context) const { + auto res = make_uniq(); + + if (info->extensions_to_update.empty()) { + // Update all + res->update_result_entries = ExtensionHelper::UpdateExtensions(context); + } else { + // Update extensions in extensions_to_update + for (const auto &ext : info->extensions_to_update) { + res->update_result_entries.emplace_back(ExtensionHelper::UpdateExtension(context, ext)); + } + } + + return std::move(res); +} + +} // namespace duckdb diff --git a/src/execution/operator/helper/physical_verify_vector.cpp b/src/execution/operator/helper/physical_verify_vector.cpp index 080ab1e3f27..5fc627c9250 100644 --- a/src/execution/operator/helper/physical_verify_vector.cpp +++ b/src/execution/operator/helper/physical_verify_vector.cpp @@ -18,25 +18,30 @@ class VerifyVectorState : public OperatorState { idx_t const_idx; }; -OperatorResultType VerifyEmitConstantVectors(DataChunk &input, DataChunk &chunk, OperatorState &state_p) { +OperatorResultType VerifyEmitConstantVectors(const DataChunk &input, DataChunk &chunk, OperatorState &state_p) { auto &state = state_p.Cast(); D_ASSERT(state.const_idx < input.size()); + // Ensure that we don't alter the input data while another thread is still using it. + DataChunk copied_input; + copied_input.Initialize(Allocator::DefaultAllocator(), input.GetTypes()); + input.Copy(copied_input); + // emit constant vectors at the current index for (idx_t c = 0; c < chunk.ColumnCount(); c++) { - ConstantVector::Reference(chunk.data[c], input.data[c], state.const_idx, 1); + ConstantVector::Reference(chunk.data[c], copied_input.data[c], state.const_idx, 1); } chunk.SetCardinality(1); state.const_idx++; - if (state.const_idx >= input.size()) { + if (state.const_idx >= copied_input.size()) { state.const_idx = 0; return OperatorResultType::NEED_MORE_INPUT; } return OperatorResultType::HAVE_MORE_OUTPUT; } -OperatorResultType VerifyEmitDictionaryVectors(DataChunk &input, DataChunk &chunk, OperatorState &state) { - chunk.Reference(input); +OperatorResultType VerifyEmitDictionaryVectors(const DataChunk &input, DataChunk &chunk, OperatorState &state) { + input.Copy(chunk); for (idx_t c = 0; c < chunk.ColumnCount(); c++) { Vector::DebugTransformToDictionary(chunk.data[c], chunk.size()); } @@ -48,7 +53,7 @@ struct ConstantOrSequenceInfo { bool is_constant = true; }; -OperatorResultType VerifyEmitSequenceVector(DataChunk &input, DataChunk &chunk, OperatorState &state_p) { +OperatorResultType VerifyEmitSequenceVector(const DataChunk &input, DataChunk &chunk, OperatorState &state_p) { auto &state = state_p.Cast(); D_ASSERT(state.const_idx < input.size()); @@ -189,8 +194,8 @@ OperatorResultType VerifyEmitSequenceVector(DataChunk &input, DataChunk &chunk, return OperatorResultType::HAVE_MORE_OUTPUT; } -OperatorResultType VerifyEmitNestedShuffleVector(DataChunk &input, DataChunk &chunk, OperatorState &state) { - chunk.Reference(input); +OperatorResultType VerifyEmitNestedShuffleVector(const DataChunk &input, DataChunk &chunk, OperatorState &state) { + input.Copy(chunk); for (idx_t c = 0; c < chunk.ColumnCount(); c++) { Vector::DebugShuffleNestedVector(chunk.data[c], chunk.size()); } diff --git a/src/execution/operator/join/physical_hash_join.cpp b/src/execution/operator/join/physical_hash_join.cpp index e9d880ec56f..f2980944dbb 100644 --- a/src/execution/operator/join/physical_hash_join.cpp +++ b/src/execution/operator/join/physical_hash_join.cpp @@ -533,6 +533,7 @@ class HashJoinOperatorState : public CachingOperatorState { bool initialized; JoinHashTable::ProbeSpillLocalAppendState spill_state; + JoinHashTable::ProbeState probe_state; //! Chunk to sink data into for external join DataChunk spill_chunk; @@ -610,10 +611,11 @@ OperatorResultType PhysicalHashJoin::ExecuteInternal(ExecutionContext &context, // perform the actual probe if (sink.external) { - state.scan_structure = sink.hash_table->ProbeAndSpill(state.join_keys, state.join_key_state, input, - *sink.probe_spill, state.spill_state, state.spill_chunk); + state.scan_structure = + sink.hash_table->ProbeAndSpill(state.join_keys, state.join_key_state, state.probe_state, input, + *sink.probe_spill, state.spill_state, state.spill_chunk); } else { - state.scan_structure = sink.hash_table->Probe(state.join_keys, state.join_key_state); + state.scan_structure = sink.hash_table->Probe(state.join_keys, state.join_key_state, state.probe_state); } state.scan_structure->Next(state.join_keys, input, chunk); return OperatorResultType::HAVE_MORE_OUTPUT; @@ -716,11 +718,13 @@ class HashJoinLocalSourceState : public LocalSourceState { DataChunk join_keys; DataChunk payload; TupleDataChunkState join_key_state; + //! Column indices to easily reference the join keys/payload columns in probe_chunk vector join_key_indices; vector payload_indices; //! Scan structure for the external probe unique_ptr scan_structure; + JoinHashTable::ProbeState probe_state; bool empty_ht_probe_in_progress; //! Chunks assigned to this thread for a full/outer scan @@ -991,7 +995,7 @@ void HashJoinLocalSourceState::ExternalProbe(HashJoinGlobalSinkState &sink, Hash } // Perform the probe - scan_structure = sink.hash_table->Probe(join_keys, join_key_state, precomputed_hashes); + scan_structure = sink.hash_table->Probe(join_keys, join_key_state, probe_state, precomputed_hashes); scan_structure->Next(join_keys, payload, chunk); } diff --git a/src/execution/operator/join/physical_left_delim_join.cpp b/src/execution/operator/join/physical_left_delim_join.cpp index 04a6ce80d1a..1d6972e0da8 100644 --- a/src/execution/operator/join/physical_left_delim_join.cpp +++ b/src/execution/operator/join/physical_left_delim_join.cpp @@ -23,7 +23,7 @@ PhysicalLeftDelimJoin::PhysicalLeftDelimJoin(vector types, unique_p // we replace it with a PhysicalColumnDataScan, that scans the ColumnDataCollection that we keep cached // the actual chunk collection to scan will be created in the LeftDelimJoinGlobalState auto cached_chunk_scan = make_uniq( - children[0]->GetTypes(), PhysicalOperatorType::COLUMN_DATA_SCAN, estimated_cardinality); + children[0]->GetTypes(), PhysicalOperatorType::COLUMN_DATA_SCAN, estimated_cardinality, nullptr); join->children[0] = std::move(cached_chunk_scan); } diff --git a/src/execution/operator/persistent/physical_batch_copy_to_file.cpp b/src/execution/operator/persistent/physical_batch_copy_to_file.cpp index 17f4e0e4026..e18e6e70d8d 100644 --- a/src/execution/operator/persistent/physical_batch_copy_to_file.cpp +++ b/src/execution/operator/persistent/physical_batch_copy_to_file.cpp @@ -1,14 +1,16 @@ #include "duckdb/execution/operator/persistent/physical_batch_copy_to_file.hpp" -#include "duckdb/execution/operator/persistent/physical_copy_to_file.hpp" -#include "duckdb/parallel/base_pipeline_event.hpp" -#include "duckdb/common/vector_operations/vector_operations.hpp" -#include "duckdb/common/types/batched_data_collection.hpp" + #include "duckdb/common/allocator.hpp" #include "duckdb/common/queue.hpp" -#include "duckdb/storage/buffer_manager.hpp" +#include "duckdb/common/types/batched_data_collection.hpp" +#include "duckdb/common/vector_operations/vector_operations.hpp" #include "duckdb/execution/operator/persistent/batch_memory_manager.hpp" #include "duckdb/execution/operator/persistent/batch_task_manager.hpp" +#include "duckdb/execution/operator/persistent/physical_copy_to_file.hpp" +#include "duckdb/parallel/base_pipeline_event.hpp" #include "duckdb/parallel/executor_task.hpp" +#include "duckdb/storage/buffer_manager.hpp" + #include namespace duckdb { @@ -158,7 +160,7 @@ SinkResultType PhysicalBatchCopyToFile::Sink(ExecutionContext &context, DataChun auto batch_index = state.partition_info.batch_index.GetIndex(); if (state.current_task == FixedBatchCopyState::PROCESSING_TASKS) { ExecuteTasks(context.client, gstate); - FlushBatchData(context.client, gstate, memory_manager.GetMinimumBatchIndex()); + FlushBatchData(context.client, gstate); if (!memory_manager.IsMinimumBatchIndex(batch_index) && memory_manager.OutOfMemory(batch_index)) { lock_guard l(memory_manager.GetBlockedTaskLock()); @@ -232,7 +234,7 @@ class ProcessRemainingBatchesTask : public ExecutorTask { TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override { while (op.ExecuteTask(context, gstate)) { - op.FlushBatchData(context, gstate, 0); + op.FlushBatchData(context, gstate); } event->FinishTask(); return TaskExecutionResult::TASK_FINISHED; @@ -279,8 +281,8 @@ SinkFinalizeType PhysicalBatchCopyToFile::FinalFlush(ClientContext &context, Glo if (gstate.task_manager.TaskCount() != 0) { throw InternalException("Unexecuted tasks are remaining in PhysicalFixedBatchCopy::FinalFlush!?"); } - auto min_batch_index = idx_t(NumericLimits::Maximum()); - FlushBatchData(context, gstate_p, min_batch_index); + + FlushBatchData(context, gstate_p); if (gstate.scheduled_batch_index != gstate.flushed_batch_index) { throw InternalException("Not all batches were flushed to disk - incomplete file?"); } @@ -323,7 +325,7 @@ class RepartitionedFlushTask : public BatchCopyTask { } void Execute(const PhysicalBatchCopyToFile &op, ClientContext &context, GlobalSinkState &gstate_p) override { - op.FlushBatchData(context, gstate_p, 0); + op.FlushBatchData(context, gstate_p); } }; @@ -475,7 +477,7 @@ void PhysicalBatchCopyToFile::RepartitionBatches(ClientContext &context, GlobalS } } -void PhysicalBatchCopyToFile::FlushBatchData(ClientContext &context, GlobalSinkState &gstate_p, idx_t min_index) const { +void PhysicalBatchCopyToFile::FlushBatchData(ClientContext &context, GlobalSinkState &gstate_p) const { auto &gstate = gstate_p.Cast(); auto &memory_manager = gstate.memory_manager; @@ -561,7 +563,7 @@ void PhysicalBatchCopyToFile::AddLocalBatch(ClientContext &context, GlobalSinkSt //! Execute a single repartition task ExecuteTask(context, gstate); //! Flush batch data to disk (if any is ready) - FlushBatchData(context, gstate, memory_manager.GetMinimumBatchIndex()); + FlushBatchData(context, gstate); } } @@ -605,7 +607,20 @@ SourceResultType PhysicalBatchCopyToFile::GetData(ExecutionContext &context, Dat auto &g = sink_state->Cast(); chunk.SetCardinality(1); - chunk.SetValue(0, 0, Value::BIGINT(NumericCast(g.rows_copied.load()))); + switch (return_type) { + case CopyFunctionReturnType::CHANGED_ROWS: + chunk.SetValue(0, 0, Value::BIGINT(NumericCast(g.rows_copied.load()))); + break; + case CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST: { + chunk.SetValue(0, 0, Value::BIGINT(NumericCast(g.rows_copied.load()))); + auto fp = use_tmp_file ? PhysicalCopyToFile::GetNonTmpFile(context.client, file_path) : file_path; + chunk.SetValue(1, 0, Value::LIST(LogicalType::VARCHAR, {fp})); + break; + } + default: + throw NotImplementedException("Unknown CopyFunctionReturnType"); + } + return SourceResultType::FINISHED; } diff --git a/src/execution/operator/persistent/physical_batch_insert.cpp b/src/execution/operator/persistent/physical_batch_insert.cpp index 12eda91c7e8..a65d1cca71a 100644 --- a/src/execution/operator/persistent/physical_batch_insert.cpp +++ b/src/execution/operator/persistent/physical_batch_insert.cpp @@ -176,10 +176,10 @@ class BatchInsertLocalState : public LocalSinkState { unique_ptr constraint_state; void CreateNewCollection(DuckTableEntry &table, const vector &insert_types) { - auto &table_info = table.GetStorage().info; + auto table_info = table.GetStorage().GetDataTableInfo(); auto &block_manager = TableIOManager::Get(table.GetStorage()).GetBlockManagerForRowData(); - current_collection = - make_uniq(table_info, block_manager, insert_types, NumericCast(MAX_ROW_ID)); + current_collection = make_uniq(std::move(table_info), block_manager, insert_types, + NumericCast(MAX_ROW_ID)); current_collection->InitializeEmpty(); current_collection->InitializeAppend(current_append_state); } diff --git a/src/execution/operator/persistent/physical_copy_database.cpp b/src/execution/operator/persistent/physical_copy_database.cpp index d0d831303b5..e66881beb31 100644 --- a/src/execution/operator/persistent/physical_copy_database.cpp +++ b/src/execution/operator/persistent/physical_copy_database.cpp @@ -49,8 +49,10 @@ SourceResultType PhysicalCopyDatabase::GetData(ExecutionContext &context, DataCh catalog.CreateTable(context.client, *bound_info); break; } + case CatalogType::INDEX_ENTRY: default: - throw InternalException("Entry type not supported in PhysicalCopyDatabase"); + throw NotImplementedException("Entry type %s not supported in PhysicalCopyDatabase", + CatalogTypeToString(create_info->type)); } } return SourceResultType::FINISHED; diff --git a/src/execution/operator/persistent/physical_copy_to_file.cpp b/src/execution/operator/persistent/physical_copy_to_file.cpp index 9205067b3c1..fd6416cb95a 100644 --- a/src/execution/operator/persistent/physical_copy_to_file.cpp +++ b/src/execution/operator/persistent/physical_copy_to_file.cpp @@ -5,9 +5,9 @@ #include "duckdb/common/hive_partitioning.hpp" #include "duckdb/common/string_util.hpp" #include "duckdb/common/types/uuid.hpp" -#include "duckdb/common/vector_operations/vector_operations.hpp" -#include "duckdb/storage/storage_lock.hpp" #include "duckdb/common/value_operations/value_operations.hpp" +#include "duckdb/common/vector_operations/vector_operations.hpp" + #include namespace duckdb { @@ -56,6 +56,8 @@ class CopyToFunctionGlobalState : public GlobalSinkState { unordered_set created_directories; //! shared state for HivePartitionedColumnData shared_ptr partition_state; + //! File names + vector file_names; void CreateDir(const string &dir_path, FileSystem &fs) { if (created_directories.find(dir_path) != created_directories.end()) { @@ -81,6 +83,11 @@ class CopyToFunctionGlobalState : public GlobalSinkState { return path; } + void AddFileName(const StorageLockKey &l, const string &file_name) { + D_ASSERT(l.GetType() == StorageLockType::EXCLUSIVE); + file_names.emplace_back(file_name); + } + void FinalizePartition(ClientContext &context, const PhysicalCopyToFile &op, PartitionWriteInfo &info) { if (!info.global_state) { // already finalized @@ -100,7 +107,7 @@ class CopyToFunctionGlobalState : public GlobalSinkState { PartitionWriteInfo &GetPartitionWriteInfo(ExecutionContext &context, const PhysicalCopyToFile &op, const vector &values) { - auto l = lock.GetExclusiveLock(); + auto global_lock = lock.GetExclusiveLock(); // check if we have already started writing this partition auto entry = active_partitioned_writes.find(values); if (entry != active_partitioned_writes.end()) { @@ -112,6 +119,19 @@ class CopyToFunctionGlobalState : public GlobalSinkState { auto trimmed_path = op.GetTrimmedPath(context.client); string hive_path = GetOrCreateDirectory(op.partition_columns, op.names, values, trimmed_path, fs); string full_path(op.filename_pattern.CreateFilename(fs, hive_path, op.file_extension, 0)); + if (op.overwrite_mode == CopyOverwriteMode::COPY_APPEND) { + // when appending, we first check if the file exists + while (fs.FileExists(full_path)) { + // file already exists - re-generate name + if (!op.filename_pattern.HasUUID()) { + throw InternalException("CopyOverwriteMode::COPY_APPEND without {uuid} - and file exists"); + } + full_path = op.filename_pattern.CreateFilename(fs, hive_path, op.file_extension, 0); + } + } + if (op.return_type == CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST) { + AddFileName(*global_lock, full_path); + } // initialize writes auto info = make_uniq(); info->global_state = op.function.copy_to_initialize_global(context.client, *op.bind_data, full_path); @@ -204,12 +224,15 @@ class CopyToFunctionLocalState : public LocalSinkState { } }; -unique_ptr PhysicalCopyToFile::CreateFileState(ClientContext &context, - GlobalSinkState &sink) const { +unique_ptr PhysicalCopyToFile::CreateFileState(ClientContext &context, GlobalSinkState &sink, + StorageLockKey &global_lock) const { auto &g = sink.Cast(); idx_t this_file_offset = g.last_file_offset++; auto &fs = FileSystem::GetFileSystem(context); string output_path(filename_pattern.CreateFilename(fs, file_path, file_extension, this_file_offset)); + if (return_type == CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST) { + g.AddFileName(global_lock, output_path); + } return function.copy_to_initialize_global(context, *bind_data, output_path); } @@ -222,18 +245,20 @@ unique_ptr PhysicalCopyToFile::GetLocalSinkState(ExecutionContex return std::move(state); } auto res = make_uniq(function.copy_to_initialize_local(context, *bind_data)); - if (per_thread_output) { - res->global_state = CreateFileState(context.client, *sink_state); - } return std::move(res); } -void CheckDirectory(FileSystem &fs, const string &file_path, bool overwrite) { - if (fs.IsRemoteFile(file_path) && overwrite) { - // we only remove files for local file systems - // as remote file systems (e.g. S3) do not support RemoveFile +void CheckDirectory(FileSystem &fs, const string &file_path, CopyOverwriteMode overwrite_mode) { + if (overwrite_mode == CopyOverwriteMode::COPY_OVERWRITE_OR_IGNORE || + overwrite_mode == CopyOverwriteMode::COPY_APPEND) { + // with overwrite or ignore we fully ignore the presence of any files instead of erasing them return; } + if (fs.IsRemoteFile(file_path) && overwrite_mode == CopyOverwriteMode::COPY_OVERWRITE) { + // we can only remove files for local file systems currently + // as remote file systems (e.g. S3) do not support RemoveFile + throw NotImplementedException("OVERWRITE is not supported for remote file systems"); + } vector file_list; vector directory_list; directory_list.push_back(file_path); @@ -251,19 +276,17 @@ void CheckDirectory(FileSystem &fs, const string &file_path, bool overwrite) { if (file_list.empty()) { return; } - if (overwrite) { + if (overwrite_mode == CopyOverwriteMode::COPY_OVERWRITE) { for (auto &file : file_list) { fs.RemoveFile(file); } } else { - throw IOException("Directory \"%s\" is not empty! Enable OVERWRITE_OR_IGNORE option to force writing", - file_path); + throw IOException("Directory \"%s\" is not empty! Enable OVERWRITE option to overwrite files", file_path); } } unique_ptr PhysicalCopyToFile::GetGlobalSinkState(ClientContext &context) const { - - if (partition_output || per_thread_output || file_size_bytes.IsValid()) { + if (partition_output || per_thread_output || rotate) { auto &fs = FileSystem::GetFileSystem(context); if (fs.FileExists(file_path)) { // the target file exists AND is a file (not a directory) @@ -272,11 +295,11 @@ unique_ptr PhysicalCopyToFile::GetGlobalSinkState(ClientContext throw IOException("Cannot write to \"%s\" - it exists and is a file, not a directory!", file_path); } else { // for local files we can remove the file if OVERWRITE_OR_IGNORE is enabled - if (overwrite_or_ignore) { + if (overwrite_mode == CopyOverwriteMode::COPY_OVERWRITE) { fs.RemoveFile(file_path); } else { throw IOException("Cannot write to \"%s\" - it exists and is a file, not a directory! Enable " - "OVERWRITE_OR_IGNORE option to force writing", + "OVERWRITE option to overwrite the file", file_path); } } @@ -285,12 +308,13 @@ unique_ptr PhysicalCopyToFile::GetGlobalSinkState(ClientContext if (!fs.DirectoryExists(file_path)) { fs.CreateDirectory(file_path); } else { - CheckDirectory(fs, file_path, overwrite_or_ignore); + CheckDirectory(fs, file_path, overwrite_mode); } auto state = make_uniq(nullptr); - if (!per_thread_output && file_size_bytes.IsValid()) { - state->global_state = CreateFileState(context, *state); + if (!per_thread_output && rotate) { + auto global_lock = state->lock.GetExclusiveLock(); + state->global_state = CreateFileState(context, *state, *global_lock); } if (partition_output) { @@ -300,7 +324,15 @@ unique_ptr PhysicalCopyToFile::GetGlobalSinkState(ClientContext return std::move(state); } - return make_uniq(function.copy_to_initialize_global(context, *bind_data, file_path)); + auto state = + make_uniq(function.copy_to_initialize_global(context, *bind_data, file_path)); + if (use_tmp_file) { + auto global_lock = state->lock.GetExclusiveLock(); + state->AddFileName(*global_lock, file_path); + } else { + state->file_names.emplace_back(file_path); + } + return std::move(state); } //===--------------------------------------------------------------------===// @@ -308,6 +340,15 @@ unique_ptr PhysicalCopyToFile::GetGlobalSinkState(ClientContext //===--------------------------------------------------------------------===// void PhysicalCopyToFile::MoveTmpFile(ClientContext &context, const string &tmp_file_path) { auto &fs = FileSystem::GetFileSystem(context); + auto file_path = GetNonTmpFile(context, tmp_file_path); + if (fs.FileExists(file_path)) { + fs.RemoveFile(file_path); + } + fs.MoveFile(tmp_file_path, file_path); +} + +string PhysicalCopyToFile::GetNonTmpFile(ClientContext &context, const string &tmp_file_path) { + auto &fs = FileSystem::GetFileSystem(context); auto path = StringUtil::GetFilePath(tmp_file_path); auto base = StringUtil::GetFileName(tmp_file_path); @@ -317,11 +358,7 @@ void PhysicalCopyToFile::MoveTmpFile(ClientContext &context, const string &tmp_f base = base.substr(4); } - auto file_path = fs.JoinPath(path, base); - if (fs.FileExists(file_path)) { - fs.RemoveFile(file_path); - } - fs.MoveFile(tmp_file_path, file_path); + return fs.JoinPath(path, base); } PhysicalCopyToFile::PhysicalCopyToFile(vector types, CopyFunction function_p, @@ -334,42 +371,46 @@ SinkResultType PhysicalCopyToFile::Sink(ExecutionContext &context, DataChunk &ch auto &g = input.global_state.Cast(); auto &l = input.local_state.Cast(); + g.rows_copied += chunk.size(); + if (partition_output) { l.AppendToPartition(context, *this, g, chunk); return SinkResultType::NEED_MORE_INPUT; } - g.rows_copied += chunk.size(); - if (per_thread_output) { auto &gstate = l.global_state; - function.copy_to_sink(context, *bind_data, *gstate, *l.local_state, chunk); - - if (file_size_bytes.IsValid() && function.file_size_bytes(*gstate) > file_size_bytes.GetIndex()) { + if (!gstate) { + // Lazily create file state here to prevent creating empty files + auto global_lock = g.lock.GetExclusiveLock(); + gstate = CreateFileState(context.client, *sink_state, *global_lock); + } else if (rotate && function.rotate_next_file(*gstate, *bind_data, file_size_bytes)) { function.copy_to_finalize(context.client, *bind_data, *gstate); - gstate = CreateFileState(context.client, *sink_state); + auto global_lock = g.lock.GetExclusiveLock(); + gstate = CreateFileState(context.client, *sink_state, *global_lock); } + function.copy_to_sink(context, *bind_data, *gstate, *l.local_state, chunk); return SinkResultType::NEED_MORE_INPUT; } - if (!file_size_bytes.IsValid()) { + if (!file_size_bytes.IsValid() && !rotate) { function.copy_to_sink(context, *bind_data, *g.global_state, *l.local_state, chunk); return SinkResultType::NEED_MORE_INPUT; } - // FILE_SIZE_BYTES is set, but threads write to the same file, synchronize using lock + // FILE_SIZE_BYTES/rotate is set, but threads write to the same file, synchronize using lock auto &gstate = g.global_state; - auto lock = g.lock.GetExclusiveLock(); - if (function.file_size_bytes(*gstate) > file_size_bytes.GetIndex()) { + auto global_lock = g.lock.GetExclusiveLock(); + if (rotate && function.rotate_next_file(*gstate, *bind_data, file_size_bytes)) { auto owned_gstate = std::move(gstate); - gstate = CreateFileState(context.client, *sink_state); - lock.reset(); + gstate = CreateFileState(context.client, *sink_state, *global_lock); + global_lock.reset(); function.copy_to_finalize(context.client, *bind_data, *owned_gstate); } else { - lock.reset(); + global_lock.reset(); } - lock = g.lock.GetSharedLock(); + global_lock = g.lock.GetSharedLock(); function.copy_to_sink(context, *bind_data, *gstate, *l.local_state, chunk); return SinkResultType::NEED_MORE_INPUT; @@ -384,11 +425,13 @@ SinkCombineResultType PhysicalCopyToFile::Combine(ExecutionContext &context, Ope l.FlushPartitions(context, *this, g); } else if (function.copy_to_combine) { if (per_thread_output) { - // For PER_THREAD_OUTPUT, we can combine/finalize immediately - function.copy_to_combine(context, *bind_data, *l.global_state, *l.local_state); - function.copy_to_finalize(context.client, *bind_data, *l.global_state); - } else if (file_size_bytes.IsValid()) { - // File in global state may change with FILE_SIZE_BYTES, need to grab lock + // For PER_THREAD_OUTPUT, we can combine/finalize immediately (if there is a gstate) + if (l.global_state) { + function.copy_to_combine(context, *bind_data, *l.global_state, *l.local_state); + function.copy_to_finalize(context.client, *bind_data, *l.global_state); + } + } else if (rotate) { + // File in global state may change with FILE_SIZE_BYTES/rotate, need to grab lock auto lock = g.lock.GetSharedLock(); function.copy_to_combine(context, *bind_data, *g.global_state, *l.local_state); } else { @@ -418,6 +461,7 @@ SinkFinalizeType PhysicalCopyToFile::Finalize(Pipeline &pipeline, Event &event, D_ASSERT(!per_thread_output); D_ASSERT(!partition_output); D_ASSERT(!file_size_bytes.IsValid()); + D_ASSERT(!rotate); MoveTmpFile(context, file_path); } } @@ -433,7 +477,17 @@ SourceResultType PhysicalCopyToFile::GetData(ExecutionContext &context, DataChun auto &g = sink_state->Cast(); chunk.SetCardinality(1); - chunk.SetValue(0, 0, Value::BIGINT(NumericCast(g.rows_copied.load()))); + switch (return_type) { + case CopyFunctionReturnType::CHANGED_ROWS: + chunk.SetValue(0, 0, Value::BIGINT(NumericCast(g.rows_copied.load()))); + break; + case CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST: + chunk.SetValue(0, 0, Value::BIGINT(NumericCast(g.rows_copied.load()))); + chunk.SetValue(1, 0, Value::LIST(LogicalType::VARCHAR, g.file_names)); + break; + default: + throw NotImplementedException("Unknown CopyFunctionReturnType"); + } return SourceResultType::FINISHED; } diff --git a/src/execution/operator/persistent/physical_delete.cpp b/src/execution/operator/persistent/physical_delete.cpp index 83c92b67f65..ec832aa299a 100644 --- a/src/execution/operator/persistent/physical_delete.cpp +++ b/src/execution/operator/persistent/physical_delete.cpp @@ -52,7 +52,7 @@ SinkResultType PhysicalDelete::Sink(ExecutionContext &context, DataChunk &chunk, auto &row_identifiers = chunk.data[row_id_index]; vector column_ids; - for (idx_t i = 0; i < table.column_definitions.size(); i++) { + for (idx_t i = 0; i < table.ColumnCount(); i++) { column_ids.emplace_back(i); }; auto cfs = ColumnFetchState(); diff --git a/src/execution/operator/persistent/physical_export.cpp b/src/execution/operator/persistent/physical_export.cpp index a127a95dc77..ccb9cd31261 100644 --- a/src/execution/operator/persistent/physical_export.cpp +++ b/src/execution/operator/persistent/physical_export.cpp @@ -17,7 +17,9 @@ namespace duckdb { using std::stringstream; -static void WriteCatalogEntries(stringstream &ss, vector> &entries) { +void ReorderTableEntries(catalog_entry_vector_t &tables); + +static void WriteCatalogEntries(stringstream &ss, catalog_entry_vector_t &entries) { for (auto &entry : entries) { if (entry.get().internal) { continue; @@ -133,11 +135,24 @@ void PhysicalExport::ExtractEntries(ClientContext &context, vector &lhs, const reference &rhs) { + return lhs.get().oid < rhs.get().oid; + }); + + catalog_entry_vector_t catalog_entries; + idx_t size = 0; + size += entries.schemas.size(); + size += entries.custom_types.size(); + size += entries.sequences.size(); + size += entries.tables.size(); + size += entries.views.size(); + size += entries.indexes.size(); + size += entries.macros.size(); + catalog_entries.reserve(size); + AddEntries(catalog_entries, entries.schemas); + AddEntries(catalog_entries, entries.sequences); + AddEntries(catalog_entries, entries.custom_types); + AddEntries(catalog_entries, entries.tables); + AddEntries(catalog_entries, entries.macros); + AddEntries(catalog_entries, entries.views); + AddEntries(catalog_entries, entries.indexes); + return catalog_entries; +} + SourceResultType PhysicalExport::GetData(ExecutionContext &context, DataChunk &chunk, OperatorSourceInput &input) const { auto &state = input.global_state.Cast(); diff --git a/src/execution/operator/persistent/physical_insert.cpp b/src/execution/operator/persistent/physical_insert.cpp index a2d3e9c6111..64c706b83eb 100644 --- a/src/execution/operator/persistent/physical_insert.cpp +++ b/src/execution/operator/persistent/physical_insert.cpp @@ -446,22 +446,37 @@ SinkResultType PhysicalInsert::Sink(ExecutionContext &context, DataChunk &chunk, gstate.initialized = true; } - if (return_chunk) { + if (action_type != OnConflictAction::NOTHING && return_chunk) { + // If the action is UPDATE or REPLACE, we will always create either an APPEND or an INSERT + // for NOTHING we don't create either an APPEND or an INSERT for the tuple + // so it should not be added to the RETURNING chunk gstate.return_collection.Append(lstate.insert_chunk); } idx_t updated_tuples = OnConflictHandling(table, context, lstate); + if (action_type == OnConflictAction::NOTHING && return_chunk) { + // Because we didn't add to the RETURNING chunk yet + // we add the tuples that did not get filtered out now + gstate.return_collection.Append(lstate.insert_chunk); + } gstate.insert_count += lstate.insert_chunk.size(); gstate.insert_count += updated_tuples; storage.LocalAppend(gstate.append_state, table, context.client, lstate.insert_chunk, true); + + // We finalize the local append to write the segment node count. + if (action_type != OnConflictAction::THROW) { + storage.FinalizeLocalAppend(gstate.append_state); + gstate.initialized = false; + } + } else { D_ASSERT(!return_chunk); // parallel append if (!lstate.local_collection) { lock_guard l(gstate.lock); - auto &table_info = storage.info; + auto table_info = storage.GetDataTableInfo(); auto &block_manager = TableIOManager::Get(storage).GetBlockManagerForRowData(); - lstate.local_collection = - make_uniq(table_info, block_manager, insert_types, NumericCast(MAX_ROW_ID)); + lstate.local_collection = make_uniq(std::move(table_info), block_manager, insert_types, + NumericCast(MAX_ROW_ID)); lstate.local_collection->InitializeEmpty(); lstate.local_collection->InitializeAppend(lstate.local_append_state); lstate.writer = &gstate.table.GetStorage().CreateOptimisticWriter(context.client); diff --git a/src/execution/operator/projection/physical_tableinout_function.cpp b/src/execution/operator/projection/physical_tableinout_function.cpp index d32094f7e2e..f8d585bf58b 100644 --- a/src/execution/operator/projection/physical_tableinout_function.cpp +++ b/src/execution/operator/projection/physical_tableinout_function.cpp @@ -38,7 +38,16 @@ unique_ptr PhysicalTableInOutFunction::GetOperatorState(Execution result->local_state = function.init_local(context, input, gstate.global_state.get()); } if (!projected_input.empty()) { - result->input_chunk.Initialize(context.client, children[0]->types); + vector input_types; + auto &child_types = children[0]->types; + idx_t input_length = child_types.size() - projected_input.size(); + for (idx_t k = 0; k < input_length; k++) { + input_types.push_back(child_types[k]); + } + for (idx_t k = 0; k < projected_input.size(); k++) { + D_ASSERT(projected_input[k] >= input_length); + } + result->input_chunk.Initialize(context.client, input_types); } return std::move(result); } @@ -71,9 +80,8 @@ OperatorResultType PhysicalTableInOutFunction::Execute(ExecutionContext &context } // we are processing a new row: fetch the data for the current row state.input_chunk.Reset(); - D_ASSERT(input.ColumnCount() == state.input_chunk.ColumnCount()); // set up the input data to the table in-out function - for (idx_t col_idx = 0; col_idx < input.ColumnCount(); col_idx++) { + for (idx_t col_idx = 0; col_idx < state.input_chunk.ColumnCount(); col_idx++) { ConstantVector::Reference(state.input_chunk.data[col_idx], input.data[col_idx], state.row_index, 1); } state.input_chunk.SetCardinality(1); @@ -100,6 +108,18 @@ OperatorResultType PhysicalTableInOutFunction::Execute(ExecutionContext &context return OperatorResultType::HAVE_MORE_OUTPUT; } +string PhysicalTableInOutFunction::ParamsToString() const { + string result; + if (function.to_string) { + result = function.to_string(bind_data.get()); + } else { + result += function.name; + } + result += "\n[INFOSEPARATOR]\n"; + result += StringUtil::Format("EC: %llu", estimated_cardinality); + return result; +} + OperatorFinalizeResultType PhysicalTableInOutFunction::FinalExecute(ExecutionContext &context, DataChunk &chunk, GlobalOperatorState &gstate_p, OperatorState &state_p) const { diff --git a/src/execution/operator/projection/physical_unnest.cpp b/src/execution/operator/projection/physical_unnest.cpp index 356b2272421..2d5421a723c 100644 --- a/src/execution/operator/projection/physical_unnest.cpp +++ b/src/execution/operator/projection/physical_unnest.cpp @@ -204,6 +204,9 @@ static void UnnestVector(UnifiedVectorFormat &child_vector_data, Vector &child_v } break; } + case PhysicalType::ARRAY: { + throw NotImplementedException("ARRAY type not supported for UNNEST."); + } default: throw InternalException("Unimplemented type for UNNEST."); } diff --git a/src/execution/operator/scan/physical_column_data_scan.cpp b/src/execution/operator/scan/physical_column_data_scan.cpp index ca6899406a7..1db1d5f3621 100644 --- a/src/execution/operator/scan/physical_column_data_scan.cpp +++ b/src/execution/operator/scan/physical_column_data_scan.cpp @@ -10,9 +10,8 @@ namespace duckdb { PhysicalColumnDataScan::PhysicalColumnDataScan(vector types, PhysicalOperatorType op_type, idx_t estimated_cardinality, - unique_ptr owned_collection_p) - : PhysicalOperator(op_type, std::move(types), estimated_cardinality), collection(owned_collection_p.get()), - owned_collection(std::move(owned_collection_p)) { + optionally_owned_ptr collection_p) + : PhysicalOperator(op_type, std::move(types), estimated_cardinality), collection(std::move(collection_p)) { } PhysicalColumnDataScan::PhysicalColumnDataScan(vector types, PhysicalOperatorType op_type, diff --git a/src/execution/operator/scan/physical_expression_scan.cpp b/src/execution/operator/scan/physical_expression_scan.cpp index 5e08bc9471f..c0e91ae2be4 100644 --- a/src/execution/operator/scan/physical_expression_scan.cpp +++ b/src/execution/operator/scan/physical_expression_scan.cpp @@ -1,6 +1,7 @@ #include "duckdb/execution/operator/scan/physical_expression_scan.hpp" -#include "duckdb/parallel/thread_context.hpp" + #include "duckdb/execution/expression_executor.hpp" +#include "duckdb/parallel/thread_context.hpp" namespace duckdb { @@ -27,8 +28,7 @@ OperatorResultType PhysicalExpressionScan::Execute(ExecutionContext &context, Da for (; chunk.size() + input.size() <= STANDARD_VECTOR_SIZE && state.expression_index < expressions.size(); state.expression_index++) { state.temp_chunk.Reset(); - EvaluateExpression(context.client, state.expression_index, &input, state.temp_chunk); - chunk.Append(state.temp_chunk); + EvaluateExpression(context.client, state.expression_index, &input, chunk, &state.temp_chunk); } if (state.expression_index < expressions.size()) { return OperatorResultType::HAVE_MORE_OUTPUT; @@ -38,15 +38,30 @@ OperatorResultType PhysicalExpressionScan::Execute(ExecutionContext &context, Da } } -void PhysicalExpressionScan::EvaluateExpression(ClientContext &context, idx_t expression_idx, DataChunk *child_chunk, - DataChunk &result) const { +void PhysicalExpressionScan::EvaluateExpression(ClientContext &context, idx_t expression_idx, + optional_ptr child_chunk, DataChunk &result, + optional_ptr temp_chunk_ptr) const { + if (temp_chunk_ptr) { + EvaluateExpressionInternal(context, expression_idx, child_chunk, result, *temp_chunk_ptr); + } else { + DataChunk temp_chunk; + temp_chunk.Initialize(Allocator::Get(context), GetTypes()); + EvaluateExpressionInternal(context, expression_idx, child_chunk, result, temp_chunk); + } +} + +void PhysicalExpressionScan::EvaluateExpressionInternal(ClientContext &context, idx_t expression_idx, + optional_ptr child_chunk, DataChunk &result, + DataChunk &temp_chunk) const { ExpressionExecutor executor(context, expressions[expression_idx]); if (child_chunk) { child_chunk->Verify(); - executor.Execute(*child_chunk, result); + executor.Execute(*child_chunk, temp_chunk); } else { - executor.Execute(result); + executor.Execute(temp_chunk); } + // Need to append because "executor" might be holding state (e.g., strings), which go out of scope here + result.Append(temp_chunk); } bool PhysicalExpressionScan::IsFoldable() const { diff --git a/src/execution/operator/scan/physical_table_scan.cpp b/src/execution/operator/scan/physical_table_scan.cpp index ba64b293bae..518cae0ccd4 100644 --- a/src/execution/operator/scan/physical_table_scan.cpp +++ b/src/execution/operator/scan/physical_table_scan.cpp @@ -13,11 +13,12 @@ PhysicalTableScan::PhysicalTableScan(vector types, TableFunction fu unique_ptr bind_data_p, vector returned_types_p, vector column_ids_p, vector projection_ids_p, vector names_p, unique_ptr table_filters_p, - idx_t estimated_cardinality, ExtraOperatorInfo extra_info) + idx_t estimated_cardinality, ExtraOperatorInfo extra_info, + vector parameters_p) : PhysicalOperator(PhysicalOperatorType::TABLE_SCAN, std::move(types), estimated_cardinality), function(std::move(function_p)), bind_data(std::move(bind_data_p)), returned_types(std::move(returned_types_p)), column_ids(std::move(column_ids_p)), projection_ids(std::move(projection_ids_p)), names(std::move(names_p)), - table_filters(std::move(table_filters_p)), extra_info(extra_info) { + table_filters(std::move(table_filters_p)), extra_info(extra_info), parameters(std::move(parameters_p)) { } class TableScanGlobalSourceState : public GlobalSourceState { @@ -32,10 +33,24 @@ class TableScanGlobalSourceState : public GlobalSourceState { } else { max_threads = 1; } + if (op.function.in_out_function) { + // this is an in-out function, we need to setup the input chunk + vector input_types; + for (auto ¶m : op.parameters) { + input_types.push_back(param.type()); + } + input_chunk.Initialize(context, input_types); + for (idx_t c = 0; c < op.parameters.size(); c++) { + input_chunk.data[c].SetValue(0, op.parameters[c]); + } + input_chunk.SetCardinality(1); + } } idx_t max_threads = 0; unique_ptr global_state; + bool in_out_final = false; + DataChunk input_chunk; idx_t MaxThreads() override { return max_threads; @@ -71,7 +86,18 @@ SourceResultType PhysicalTableScan::GetData(ExecutionContext &context, DataChunk auto &state = input.local_state.Cast(); TableFunctionInput data(bind_data.get(), state.local_state.get(), gstate.global_state.get()); - function.function(context.client, data, chunk); + if (function.function) { + function.function(context.client, data, chunk); + } else { + if (gstate.in_out_final) { + function.in_out_function_final(context, data, chunk); + } + function.in_out_function(context, data, gstate.input_chunk, chunk); + if (chunk.size() == 0 && function.in_out_function_final) { + function.in_out_function_final(context, data, chunk); + gstate.in_out_final = true; + } + } return chunk.size() == 0 ? SourceResultType::FINISHED : SourceResultType::HAVE_MORE_OUTPUT; } @@ -143,7 +169,12 @@ string PhysicalTableScan::ParamsToString() const { if (!extra_info.file_filters.empty()) { result += "\n[INFOSEPARATOR]\n"; result += "File Filters: " + extra_info.file_filters; + if (extra_info.filtered_files.IsValid() && extra_info.total_files.IsValid()) { + result += StringUtil::Format("\nScanning: %llu/%llu files", extra_info.filtered_files.GetIndex(), + extra_info.total_files.GetIndex()); + } } + result += "\n[INFOSEPARATOR]\n"; result += StringUtil::Format("EC: %llu", estimated_cardinality); return result; diff --git a/src/execution/operator/schema/physical_attach.cpp b/src/execution/operator/schema/physical_attach.cpp index c60e9b756d1..69af179f37c 100644 --- a/src/execution/operator/schema/physical_attach.cpp +++ b/src/execution/operator/schema/physical_attach.cpp @@ -10,48 +10,6 @@ namespace duckdb { -//===--------------------------------------------------------------------===// -// Helper -//===--------------------------------------------------------------------===// - -void ParseOptions(const unique_ptr &info, AccessMode &access_mode, string &db_type, - string &unrecognized_option) { - - for (auto &entry : info->options) { - - if (entry.first == "readonly" || entry.first == "read_only") { - auto read_only = BooleanValue::Get(entry.second.DefaultCastAs(LogicalType::BOOLEAN)); - if (read_only) { - access_mode = AccessMode::READ_ONLY; - } else { - access_mode = AccessMode::READ_WRITE; - } - continue; - } - - if (entry.first == "readwrite" || entry.first == "read_write") { - auto read_only = !BooleanValue::Get(entry.second.DefaultCastAs(LogicalType::BOOLEAN)); - if (read_only) { - access_mode = AccessMode::READ_ONLY; - } else { - access_mode = AccessMode::READ_WRITE; - } - continue; - } - - if (entry.first == "type") { - // extract the database type - db_type = StringValue::Get(entry.second.DefaultCastAs(LogicalType::VARCHAR)); - continue; - } - - // we allow unrecognized options - if (unrecognized_option.empty()) { - unrecognized_option = entry.first; - } - } -} - //===--------------------------------------------------------------------===// // Source //===--------------------------------------------------------------------===// @@ -59,16 +17,13 @@ SourceResultType PhysicalAttach::GetData(ExecutionContext &context, DataChunk &c OperatorSourceInput &input) const { // parse the options auto &config = DBConfig::GetConfig(context.client); - AccessMode access_mode = config.options.access_mode; - string db_type; - string unrecognized_option; - ParseOptions(info, access_mode, db_type, unrecognized_option); + AttachOptions options(info, config.options.access_mode); // get the name and path of the database auto &name = info->name; auto &path = info->path; - if (db_type.empty()) { - DBPathAndType::ExtractExtensionPrefix(path, db_type); + if (options.db_type.empty()) { + DBPathAndType::ExtractExtensionPrefix(path, options.db_type); } if (name.empty()) { auto &fs = FileSystem::GetFileSystem(context.client); @@ -82,12 +37,12 @@ SourceResultType PhysicalAttach::GetData(ExecutionContext &context, DataChunk &c auto existing_db = db_manager.GetDatabase(context.client, name); if (existing_db) { - if ((existing_db->IsReadOnly() && access_mode == AccessMode::READ_WRITE) || - (!existing_db->IsReadOnly() && access_mode == AccessMode::READ_ONLY)) { + if ((existing_db->IsReadOnly() && options.access_mode == AccessMode::READ_WRITE) || + (!existing_db->IsReadOnly() && options.access_mode == AccessMode::READ_ONLY)) { auto existing_mode = existing_db->IsReadOnly() ? AccessMode::READ_ONLY : AccessMode::READ_WRITE; auto existing_mode_str = EnumUtil::ToString(existing_mode); - auto attached_mode = EnumUtil::ToString(access_mode); + auto attached_mode = EnumUtil::ToString(options.access_mode); throw BinderException("Database \"%s\" is already attached in %s mode, cannot re-attach in %s mode", name, existing_mode_str, attached_mode); } @@ -96,10 +51,27 @@ SourceResultType PhysicalAttach::GetData(ExecutionContext &context, DataChunk &c } } - // get the database type and attach the database - db_manager.GetDatabaseType(context.client, db_type, *info, config, unrecognized_option); - auto attached_db = db_manager.AttachDatabase(context.client, *info, db_type, access_mode); - attached_db->Initialize(&context.client); + string extension = ""; + if (FileSystem::IsRemoteFile(path, extension)) { + if (!ExtensionHelper::TryAutoLoadExtension(context.client, extension)) { + throw MissingExtensionException("Attaching path '%s' requires extension '%s' to be loaded", path, + extension); + } + if (options.access_mode == AccessMode::AUTOMATIC) { + // Attaching of remote files gets bumped to READ_ONLY + // This is due to the fact that on most (all?) remote files writes to DB are not available + // and having this raised later is not super helpful + options.access_mode = AccessMode::READ_ONLY; + } + } + + // Get the database type and attach the database. + db_manager.GetDatabaseType(context.client, *info, config, options); + auto attached_db = db_manager.AttachDatabase(context.client, *info, options); + + //! Initialize the database. + const auto block_alloc_size = info->GetBlockAllocSize(); + attached_db->Initialize(block_alloc_size); return SourceResultType::FINISHED; } diff --git a/src/execution/operator/schema/physical_create_art_index.cpp b/src/execution/operator/schema/physical_create_art_index.cpp index 94aa2b74b9e..48731644a37 100644 --- a/src/execution/operator/schema/physical_create_art_index.cpp +++ b/src/execution/operator/schema/physical_create_art_index.cpp @@ -4,9 +4,9 @@ #include "duckdb/catalog/catalog_entry/duck_table_entry.hpp" #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" #include "duckdb/execution/index/art/art_key.hpp" +#include "duckdb/execution/index/bound_index.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/main/database_manager.hpp" -#include "duckdb/storage/index.hpp" #include "duckdb/storage/storage_manager.hpp" #include "duckdb/storage/table/append_state.hpp" #include "duckdb/common/exception/transaction_exception.hpp" @@ -34,14 +34,14 @@ PhysicalCreateARTIndex::PhysicalCreateARTIndex(LogicalOperator &op, TableCatalog class CreateARTIndexGlobalSinkState : public GlobalSinkState { public: //! Global index to be added to the table - unique_ptr global_index; + unique_ptr global_index; }; class CreateARTIndexLocalSinkState : public LocalSinkState { public: explicit CreateARTIndexLocalSinkState(ClientContext &context) : arena_allocator(Allocator::Get(context)) {}; - unique_ptr local_index; + unique_ptr local_index; ArenaAllocator arena_allocator; vector keys; DataChunk key_chunk; @@ -82,9 +82,9 @@ SinkResultType PhysicalCreateARTIndex::SinkUnsorted(Vector &row_identifiers, Ope auto &l_state = input.local_state.Cast(); auto count = l_state.key_chunk.size(); - // get the corresponding row IDs - row_identifiers.Flatten(count); - auto row_ids = FlatVector::GetData(row_identifiers); + UnifiedVectorFormat row_id_data; + row_identifiers.ToUnifiedFormat(count, row_id_data); + auto row_ids = UnifiedVectorFormat::GetData(row_id_data); // insert the row IDs auto &art = l_state.local_index->Cast(); @@ -104,9 +104,9 @@ SinkResultType PhysicalCreateARTIndex::SinkSorted(Vector &row_identifiers, Opera auto &l_index = l_state.local_index; // create an ART from the chunk - auto art = - make_uniq(info->index_name, l_index->index_constraint_type, l_index->column_ids, l_index->table_io_manager, - l_index->unbound_expressions, storage.db, l_index->Cast().allocators); + auto art = make_uniq(info->index_name, l_index->GetConstraintType(), l_index->GetColumnIds(), + l_index->table_io_manager, l_index->unbound_expressions, storage.db, + l_index->Cast().allocators); if (!art->ConstructFromSorted(l_state.key_chunk.size(), l_state.keys, row_identifiers)) { throw ConstraintException("Data contains duplicates on indexed column(s)"); } @@ -123,29 +123,29 @@ SinkResultType PhysicalCreateARTIndex::Sink(ExecutionContext &context, DataChunk OperatorSinkInput &input) const { D_ASSERT(chunk.ColumnCount() >= 2); - - // generate the keys for the given input auto &l_state = input.local_state.Cast(); l_state.key_chunk.ReferenceColumns(chunk, l_state.key_column_ids); l_state.arena_allocator.Reset(); - ART::GenerateKeys(l_state.arena_allocator, l_state.key_chunk, l_state.keys); - // insert the keys and their corresponding row IDs + // Insert the keys and their corresponding row identifiers. auto &row_identifiers = chunk.data[chunk.ColumnCount() - 1]; if (sorted) { + ART::GenerateKeys(l_state.arena_allocator, l_state.key_chunk, l_state.keys); return SinkSorted(row_identifiers, input); } + + ART::GenerateKeys(l_state.arena_allocator, l_state.key_chunk, l_state.keys); return SinkUnsorted(row_identifiers, input); } SinkCombineResultType PhysicalCreateARTIndex::Combine(ExecutionContext &context, OperatorSinkCombineInput &input) const { - auto &gstate = input.global_state.Cast(); - auto &lstate = input.local_state.Cast(); + auto &g_state = input.global_state.Cast(); + auto &l_state = input.local_state.Cast(); // merge the local index into the global index - if (!gstate.global_index->MergeIndexes(*lstate.local_index)) { + if (!g_state.global_index->MergeIndexes(*l_state.local_index)) { throw ConstraintException("Data contains duplicates on indexed column(s)"); } @@ -169,7 +169,7 @@ SinkFinalizeType PhysicalCreateARTIndex::Finalize(Pipeline &pipeline, Event &eve auto &schema = table.schema; info->column_ids = storage_ids; - auto index_entry = schema.CreateIndex(context, *info, table).get(); + auto index_entry = schema.CreateIndex(schema.GetCatalogTransaction(context), *info, table).get(); if (!index_entry) { D_ASSERT(info->on_conflict == OnCreateConflict::IGNORE_ON_CONFLICT); // index already exists, but error ignored because of IF NOT EXISTS @@ -178,13 +178,13 @@ SinkFinalizeType PhysicalCreateARTIndex::Finalize(Pipeline &pipeline, Event &eve auto &index = index_entry->Cast(); index.initial_index_size = state.global_index->GetInMemorySize(); - index.info = make_shared_ptr(storage.info, index.name); + index.info = make_shared_ptr(storage.GetDataTableInfo(), index.name); for (auto &parsed_expr : info->parsed_expressions) { index.parsed_expressions.push_back(parsed_expr->Copy()); } // add index to storage - storage.info->indexes.AddIndex(std::move(state.global_index)); + storage.AddIndex(std::move(state.global_index)); return SinkFinalizeType::READY; } diff --git a/src/execution/physical_plan/plan_column_data_get.cpp b/src/execution/physical_plan/plan_column_data_get.cpp index 49e23c6f7f4..46305675bc0 100644 --- a/src/execution/physical_plan/plan_column_data_get.cpp +++ b/src/execution/physical_plan/plan_column_data_get.cpp @@ -8,10 +8,8 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalColumnData D_ASSERT(op.children.size() == 0); D_ASSERT(op.collection); - // create a PhysicalChunkScan pointing towards the owned collection - auto chunk_scan = make_uniq(op.types, PhysicalOperatorType::COLUMN_DATA_SCAN, - op.estimated_cardinality, std::move(op.collection)); - return std::move(chunk_scan); + return make_uniq(op.types, PhysicalOperatorType::COLUMN_DATA_SCAN, op.estimated_cardinality, + std::move(op.collection)); } } // namespace duckdb diff --git a/src/execution/physical_plan/plan_copy_to_file.cpp b/src/execution/physical_plan/plan_copy_to_file.cpp index cd7f19cdbca..8c26a0ea0eb 100644 --- a/src/execution/physical_plan/plan_copy_to_file.cpp +++ b/src/execution/physical_plan/plan_copy_to_file.cpp @@ -1,5 +1,5 @@ -#include "duckdb/execution/operator/persistent/physical_copy_to_file.hpp" #include "duckdb/execution/operator/persistent/physical_batch_copy_to_file.hpp" +#include "duckdb/execution/operator/persistent/physical_copy_to_file.hpp" #include "duckdb/execution/physical_plan_generator.hpp" #include "duckdb/planner/operator/logical_copy_to_file.hpp" @@ -16,8 +16,8 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalCopyToFile auto base = StringUtil::GetFileName(op.file_path); op.file_path = fs.JoinPath(path, "tmp_" + base); } - if (op.per_thread_output || op.file_size_bytes.IsValid() || op.partition_output || !op.partition_columns.empty() || - op.overwrite_or_ignore) { + if (op.per_thread_output || op.file_size_bytes.IsValid() || op.rotate || op.partition_output || + !op.partition_columns.empty() || op.overwrite_mode != CopyOverwriteMode::COPY_ERROR_ON_CONFLICT) { // hive-partitioning/per-thread output does not care about insertion order, and does not support batch indexes preserve_insertion_order = false; supports_batch_index = false; @@ -36,19 +36,22 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalCopyToFile copy->file_path = op.file_path; copy->use_tmp_file = op.use_tmp_file; copy->children.push_back(std::move(plan)); + copy->return_type = op.return_type; return std::move(copy); } // COPY from select statement to file auto copy = make_uniq(op.types, op.function, std::move(op.bind_data), op.estimated_cardinality); copy->file_path = op.file_path; copy->use_tmp_file = op.use_tmp_file; - copy->overwrite_or_ignore = op.overwrite_or_ignore; + copy->overwrite_mode = op.overwrite_mode; copy->filename_pattern = op.filename_pattern; copy->file_extension = op.file_extension; copy->per_thread_output = op.per_thread_output; if (op.file_size_bytes.IsValid()) { copy->file_size_bytes = op.file_size_bytes; } + copy->rotate = op.rotate; + copy->return_type = op.return_type; copy->partition_output = op.partition_output; copy->partition_columns = op.partition_columns; copy->names = op.names; diff --git a/src/execution/physical_plan/plan_delim_get.cpp b/src/execution/physical_plan/plan_delim_get.cpp index 32ddeb2f0e3..1b45efe21b4 100644 --- a/src/execution/physical_plan/plan_delim_get.cpp +++ b/src/execution/physical_plan/plan_delim_get.cpp @@ -8,8 +8,8 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalDelimGet & D_ASSERT(op.children.empty()); // create a PhysicalChunkScan without an owned_collection, the collection will be added later - auto chunk_scan = - make_uniq(op.types, PhysicalOperatorType::DELIM_SCAN, op.estimated_cardinality); + auto chunk_scan = make_uniq(op.types, PhysicalOperatorType::DELIM_SCAN, + op.estimated_cardinality, nullptr); return std::move(chunk_scan); } diff --git a/src/execution/physical_plan/plan_distinct.cpp b/src/execution/physical_plan/plan_distinct.cpp index e0bb12d688c..355169c33aa 100644 --- a/src/execution/physical_plan/plan_distinct.cpp +++ b/src/execution/physical_plan/plan_distinct.cpp @@ -67,6 +67,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalDistinct & bool changes_made = false; auto new_expr = OrderedAggregateOptimizer::Apply(context, *first_aggregate, groups, changes_made); if (new_expr) { + D_ASSERT(new_expr->return_type == first_aggregate->return_type); D_ASSERT(new_expr->type == ExpressionType::BOUND_AGGREGATE); first_aggregate = unique_ptr_cast(std::move(new_expr)); } diff --git a/src/execution/physical_plan/plan_expression_get.cpp b/src/execution/physical_plan/plan_expression_get.cpp index b0db627e76f..b637267426d 100644 --- a/src/execution/physical_plan/plan_expression_get.cpp +++ b/src/execution/physical_plan/plan_expression_get.cpp @@ -19,19 +19,18 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalExpression // simple expression scan (i.e. no subqueries to evaluate and no prepared statement parameters) // we can evaluate all the expressions right now and turn this into a chunk collection scan auto chunk_scan = make_uniq(op.types, PhysicalOperatorType::COLUMN_DATA_SCAN, - expr_scan->expressions.size()); - chunk_scan->owned_collection = make_uniq(context, op.types); - chunk_scan->collection = chunk_scan->owned_collection.get(); + expr_scan->expressions.size(), + make_uniq(context, op.types)); DataChunk chunk; chunk.Initialize(allocator, op.types); ColumnDataAppendState append_state; - chunk_scan->owned_collection->InitializeAppend(append_state); + chunk_scan->collection->InitializeAppend(append_state); for (idx_t expression_idx = 0; expression_idx < expr_scan->expressions.size(); expression_idx++) { chunk.Reset(); expr_scan->EvaluateExpression(context, expression_idx, nullptr, chunk); - chunk_scan->owned_collection->Append(append_state, chunk); + chunk_scan->collection->Append(append_state, chunk); } return std::move(chunk_scan); } diff --git a/src/execution/physical_plan/plan_get.cpp b/src/execution/physical_plan/plan_get.cpp index e7ec54376a2..639f49affb3 100644 --- a/src/execution/physical_plan/plan_get.cpp +++ b/src/execution/physical_plan/plan_get.cpp @@ -1,8 +1,11 @@ +#include "duckdb/execution/operator/scan/physical_expression_scan.hpp" +#include "duckdb/execution/operator/scan/physical_dummy_scan.hpp" #include "duckdb/execution/operator/projection/physical_projection.hpp" #include "duckdb/execution/operator/projection/physical_tableinout_function.hpp" #include "duckdb/execution/operator/scan/physical_table_scan.hpp" #include "duckdb/execution/physical_plan_generator.hpp" #include "duckdb/function/table/table_scan.hpp" +#include "duckdb/planner/expression/bound_cast_expression.hpp" #include "duckdb/planner/expression/bound_constant_expression.hpp" #include "duckdb/planner/expression/bound_reference_expression.hpp" #include "duckdb/planner/operator/logical_get.hpp" @@ -31,11 +34,41 @@ unique_ptr CreateTableFilterSet(TableFilterSet &table_filters, v unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalGet &op) { if (!op.children.empty()) { + auto child_node = CreatePlan(std::move(op.children[0])); // this is for table producing functions that consume subquery results - D_ASSERT(op.children.size() == 1); + // push a projection node with casts if required + if (child_node->types.size() < op.input_table_types.size()) { + throw InternalException( + "Mismatch between input table types and child node types - expected %llu but got %llu", + op.input_table_types.size(), child_node->types.size()); + } + vector return_types; + vector> expressions; + bool any_cast_required = false; + for (idx_t proj_idx = 0; proj_idx < child_node->types.size(); proj_idx++) { + auto ref = make_uniq(child_node->types[proj_idx], proj_idx); + auto &target_type = + proj_idx < op.input_table_types.size() ? op.input_table_types[proj_idx] : child_node->types[proj_idx]; + if (child_node->types[proj_idx] != target_type) { + // cast is required - push a cast + any_cast_required = true; + auto cast = BoundCastExpression::AddCastToType(context, std::move(ref), target_type); + expressions.push_back(std::move(cast)); + } else { + expressions.push_back(std::move(ref)); + } + return_types.push_back(target_type); + } + if (any_cast_required) { + auto proj = make_uniq(std::move(return_types), std::move(expressions), + child_node->estimated_cardinality); + proj->children.push_back(std::move(child_node)); + child_node = std::move(proj); + } + auto node = make_uniq(op.types, op.function, std::move(op.bind_data), op.column_ids, op.estimated_cardinality, std::move(op.projected_input)); - node->children.push_back(CreatePlan(std::move(op.children[0]))); + node->children.push_back(std::move(child_node)); return std::move(node); } if (!op.projected_input.empty()) { @@ -53,9 +86,10 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalGet &op) { // create the table scan node if (!op.function.projection_pushdown) { // function does not support projection pushdown - auto node = make_uniq(op.returned_types, op.function, std::move(op.bind_data), - op.returned_types, op.column_ids, vector(), op.names, - std::move(table_filters), op.estimated_cardinality, op.extra_info); + auto node = + make_uniq(op.returned_types, op.function, std::move(op.bind_data), op.returned_types, + op.column_ids, vector(), op.names, std::move(table_filters), + op.estimated_cardinality, op.extra_info, std::move(op.parameters)); // first check if an additional projection is necessary if (op.column_ids.size() == op.returned_types.size()) { bool projection_necessary = false; @@ -93,7 +127,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalGet &op) { } else { return make_uniq(op.types, op.function, std::move(op.bind_data), op.returned_types, op.column_ids, op.projection_ids, op.names, std::move(table_filters), - op.estimated_cardinality, op.extra_info); + op.estimated_cardinality, op.extra_info, std::move(op.parameters)); } } diff --git a/src/execution/physical_plan/plan_limit.cpp b/src/execution/physical_plan/plan_limit.cpp index e10764cc336..508f1c889c8 100644 --- a/src/execution/physical_plan/plan_limit.cpp +++ b/src/execution/physical_plan/plan_limit.cpp @@ -7,10 +7,27 @@ namespace duckdb { -bool UseBatchLimit(BoundLimitNode &limit_val, BoundLimitNode &offset_val) { +bool UseBatchLimit(PhysicalOperator &child_node, BoundLimitNode &limit_val, BoundLimitNode &offset_val) { #ifdef DUCKDB_ALTERNATIVE_VERIFY return true; #else + // we only want to use the batch limit when we are executing a complex query (e.g. involving a filter or join) + // if we are doing a limit over a table scan we are otherwise scanning a lot of rows just to throw them away + reference current_ref(child_node); + bool finished = false; + while (!finished) { + auto ¤t_op = current_ref.get(); + switch (current_op.type) { + case PhysicalOperatorType::TABLE_SCAN: + return false; + case PhysicalOperatorType::PROJECTION: + current_ref = *current_op.children[0]; + break; + default: + finished = true; + break; + } + } // we only use batch limit when we are computing a small amount of values // as the batch limit materializes this many rows PER thread static constexpr const idx_t BATCH_LIMIT_THRESHOLD = 10000; @@ -48,7 +65,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalLimit &op) op.estimated_cardinality, true); } else { // maintaining insertion order is important - if (UseBatchIndex(*plan) && UseBatchLimit(op.limit_val, op.offset_val)) { + if (UseBatchIndex(*plan) && UseBatchLimit(*plan, op.limit_val, op.offset_val)) { // source supports batch index: use parallel batch limit limit = make_uniq(op.types, std::move(op.limit_val), std::move(op.offset_val), op.estimated_cardinality); diff --git a/src/execution/physical_plan/plan_simple.cpp b/src/execution/physical_plan/plan_simple.cpp index 3a7c2f9691c..a13b607c4b1 100644 --- a/src/execution/physical_plan/plan_simple.cpp +++ b/src/execution/physical_plan/plan_simple.cpp @@ -1,6 +1,7 @@ #include "duckdb/execution/operator/helper/physical_load.hpp" #include "duckdb/execution/operator/helper/physical_transaction.hpp" #include "duckdb/execution/operator/helper/physical_vacuum.hpp" +#include "duckdb/execution/operator/helper/physical_update_extensions.hpp" #include "duckdb/execution/operator/schema/physical_alter.hpp" #include "duckdb/execution/operator/schema/physical_attach.hpp" #include "duckdb/execution/operator/schema/physical_create_schema.hpp" @@ -34,6 +35,9 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalSimple &op case LogicalOperatorType::LOGICAL_DETACH: return make_uniq(unique_ptr_cast(std::move(op.info)), op.estimated_cardinality); + case LogicalOperatorType::LOGICAL_UPDATE_EXTENSIONS: + return make_uniq(unique_ptr_cast(std::move(op.info)), + op.estimated_cardinality); default: throw NotImplementedException("Unimplemented type for logical simple operator"); } diff --git a/src/execution/physical_plan/plan_window.cpp b/src/execution/physical_plan/plan_window.cpp index 69f505eca30..f294d9324fb 100644 --- a/src/execution/physical_plan/plan_window.cpp +++ b/src/execution/physical_plan/plan_window.cpp @@ -2,6 +2,7 @@ #include "duckdb/execution/operator/aggregate/physical_window.hpp" #include "duckdb/execution/operator/projection/physical_projection.hpp" #include "duckdb/execution/physical_plan_generator.hpp" +#include "duckdb/main/client_context.hpp" #include "duckdb/planner/expression/bound_reference_expression.hpp" #include "duckdb/planner/expression/bound_window_expression.hpp" #include "duckdb/planner/operator/logical_window.hpp" @@ -10,29 +11,6 @@ namespace duckdb { -static bool IsStreamingWindow(unique_ptr &expr) { - auto &wexpr = expr->Cast(); - if (!wexpr.partitions.empty() || !wexpr.orders.empty() || wexpr.ignore_nulls || - wexpr.exclude_clause != WindowExcludeMode::NO_OTHER) { - return false; - } - switch (wexpr.type) { - // TODO: add more expression types here? - case ExpressionType::WINDOW_AGGREGATE: - // We can stream aggregates if they are "running totals" and don't use filters - return wexpr.start == WindowBoundary::UNBOUNDED_PRECEDING && wexpr.end == WindowBoundary::CURRENT_ROW_ROWS && - !wexpr.filter_expr; - case ExpressionType::WINDOW_FIRST_VALUE: - case ExpressionType::WINDOW_PERCENT_RANK: - case ExpressionType::WINDOW_RANK: - case ExpressionType::WINDOW_RANK_DENSE: - case ExpressionType::WINDOW_ROW_NUMBER: - return true; - default: - return false; - } -} - unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalWindow &op) { D_ASSERT(op.children.size() == 1); @@ -51,10 +29,11 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalWindow &op types.resize(input_width); // Identify streaming windows + const bool enable_optimizer = ClientConfig::GetConfig(context).enable_optimizer; vector blocking_windows; vector streaming_windows; for (idx_t expr_idx = 0; expr_idx < op.expressions.size(); expr_idx++) { - if (IsStreamingWindow(op.expressions[expr_idx])) { + if (enable_optimizer && PhysicalStreamingWindow::IsStreamingFunction(context, op.expressions[expr_idx])) { streaming_windows.push_back(expr_idx); } else { blocking_windows.push_back(expr_idx); diff --git a/src/execution/physical_plan_generator.cpp b/src/execution/physical_plan_generator.cpp index 4f88c00cf79..6b223f72dc9 100644 --- a/src/execution/physical_plan_generator.cpp +++ b/src/execution/physical_plan_generator.cpp @@ -211,6 +211,9 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalOperator & case LogicalOperatorType::LOGICAL_COPY_DATABASE: plan = CreatePlan(op.Cast()); break; + case LogicalOperatorType::LOGICAL_UPDATE_EXTENSIONS: + plan = CreatePlan(op.Cast()); + break; case LogicalOperatorType::LOGICAL_EXTENSION_OPERATOR: plan = op.Cast().CreatePlan(context, *this); diff --git a/src/execution/radix_partitioned_hashtable.cpp b/src/execution/radix_partitioned_hashtable.cpp index 595c1c4c2c8..27e4190e66b 100644 --- a/src/execution/radix_partitioned_hashtable.cpp +++ b/src/execution/radix_partitioned_hashtable.cpp @@ -6,6 +6,7 @@ #include "duckdb/common/types/row/tuple_data_iterator.hpp" #include "duckdb/execution/aggregate_hashtable.hpp" #include "duckdb/execution/executor.hpp" +#include "duckdb/execution/ht_entry.hpp" #include "duckdb/execution/operator/aggregate/physical_hash_aggregate.hpp" #include "duckdb/main/config.hpp" #include "duckdb/parallel/event.hpp" @@ -167,6 +168,8 @@ class RadixHTGlobalSinkState : public GlobalSinkState { atomic external; //! Threads that have called Sink atomic active_threads; + //! Number of threads (from TaskScheduler) + const idx_t number_of_threads; //! If any thread has called combine atomic any_combined; @@ -193,6 +196,7 @@ class RadixHTGlobalSinkState : public GlobalSinkState { RadixHTGlobalSinkState::RadixHTGlobalSinkState(ClientContext &context_p, const RadixPartitionedHashTable &radix_ht_p) : context(context_p), temporary_memory_state(TemporaryMemoryManager::Get(context).Register(context)), radix_ht(radix_ht_p), config(context, *this), finalized(false), external(false), active_threads(0), + number_of_threads(NumericCast(TaskScheduler::GetScheduler(context).NumberOfThreads())), any_combined(false), finalize_done(0), scan_pin_properties(TupleDataPinProperties::DESTROY_AFTER_DONE), count_before_combining(0), max_partition_size(0) { @@ -202,7 +206,7 @@ RadixHTGlobalSinkState::RadixHTGlobalSinkState(ClientContext &context_p, const R auto num_partitions = RadixPartitioning::NumberOfPartitions(config.GetRadixBits()); auto count_per_partition = ht_count / num_partitions; auto blocks_per_partition = (count_per_partition + tuples_per_block) / tuples_per_block + 1; - auto ht_size = blocks_per_partition * Storage::BLOCK_ALLOC_SIZE + config.sink_capacity * sizeof(aggr_ht_entry_t); + auto ht_size = blocks_per_partition * Storage::BLOCK_ALLOC_SIZE + config.sink_capacity * sizeof(ht_entry_t); // This really is the minimum reservation that we can do auto num_threads = NumericCast(TaskScheduler::GetScheduler(context).NumberOfThreads()); @@ -230,6 +234,7 @@ void RadixHTGlobalSinkState::Destroy() { } // There are aggregates with destructors: Call the destructor for each of the aggregates + lock_guard guard(lock); RowOperationsState row_state(*stored_allocators.back()); for (auto &partition : partitions) { auto &data_collection = *partition->data; @@ -305,7 +310,7 @@ idx_t RadixHTConfig::SinkCapacity(ClientContext &context) { const auto cache_per_active_thread = L1_CACHE_SIZE + L2_CACHE_SIZE + total_shared_cache_size / active_threads; // Divide cache per active thread by entry size, round up to next power of two, to get capacity - const auto size_per_entry = sizeof(aggr_ht_entry_t) * GroupedAggregateHashTable::LOAD_FACTOR; + const auto size_per_entry = sizeof(ht_entry_t) * GroupedAggregateHashTable::LOAD_FACTOR; const auto capacity = NextPowerOfTwo(NumericCast(static_cast(cache_per_active_thread) / size_per_entry)); @@ -358,28 +363,27 @@ void RadixPartitionedHashTable::PopulateGroupChunk(DataChunk &group_chunk, DataC group_chunk.Verify(); } -bool MaybeRepartition(ClientContext &context, RadixHTGlobalSinkState &gstate, RadixHTLocalSinkState &lstate, - const idx_t &active_threads) { +bool MaybeRepartition(ClientContext &context, RadixHTGlobalSinkState &gstate, RadixHTLocalSinkState &lstate) { auto &config = gstate.config; auto &ht = *lstate.ht; auto &partitioned_data = ht.GetPartitionedData(); // Check if we're approaching the memory limit auto &temporary_memory_state = *gstate.temporary_memory_state; - const auto total_size = partitioned_data->SizeInBytes() + ht.Capacity() * sizeof(aggr_ht_entry_t); - idx_t thread_limit = temporary_memory_state.GetReservation() / active_threads; + const auto total_size = partitioned_data->SizeInBytes() + ht.Capacity() * sizeof(ht_entry_t); + idx_t thread_limit = temporary_memory_state.GetReservation() / gstate.number_of_threads; if (total_size > thread_limit) { // We're over the thread memory limit if (!gstate.external) { // We haven't yet triggered out-of-core behavior, but maybe we don't have to, grab the lock and check again lock_guard guard(gstate.lock); - thread_limit = temporary_memory_state.GetReservation() / active_threads; + thread_limit = temporary_memory_state.GetReservation() / gstate.number_of_threads; if (total_size > thread_limit) { // Out-of-core would be triggered below, try to increase the reservation auto remaining_size = - MaxValue(active_threads * total_size, temporary_memory_state.GetRemainingSize()); + MaxValue(gstate.number_of_threads * total_size, temporary_memory_state.GetRemainingSize()); temporary_memory_state.SetRemainingSize(context, 2 * remaining_size); - thread_limit = temporary_memory_state.GetReservation() / active_threads; + thread_limit = temporary_memory_state.GetReservation() / gstate.number_of_threads; } } } @@ -402,7 +406,7 @@ bool MaybeRepartition(ClientContext &context, RadixHTGlobalSinkState &gstate, Ra } // We can go external when there is only one active thread, but we shouldn't repartition here - if (active_threads < 2) { + if (gstate.number_of_threads < 2) { return false; } @@ -412,7 +416,7 @@ bool MaybeRepartition(ClientContext &context, RadixHTGlobalSinkState &gstate, Ra const auto row_size_per_partition = partitioned_data->Count() * partitioned_data->GetLayout().GetRowWidth() / partition_count; - if (row_size_per_partition > config.BLOCK_FILL_FACTOR * Storage::BLOCK_SIZE) { + if (row_size_per_partition > NumericCast(config.BLOCK_FILL_FACTOR * Storage::BLOCK_SIZE)) { // We crossed our block filling threshold, try to increment radix bits config.SetRadixBits(current_radix_bits + config.REPARTITION_RADIX_BITS); } @@ -450,8 +454,7 @@ void RadixPartitionedHashTable::Sink(ExecutionContext &context, DataChunk &chunk return; // We can fit another chunk } - const idx_t active_threads = gstate.active_threads; - if (active_threads > 2) { + if (gstate.number_of_threads > 2) { // 'Reset' the HT without taking its data, we can just keep appending to the same collection // This only works because we never resize the HT ht.ClearPointerTable(); @@ -460,7 +463,7 @@ void RadixPartitionedHashTable::Sink(ExecutionContext &context, DataChunk &chunk } // Check if we need to repartition - auto repartitioned = MaybeRepartition(context.client, gstate, lstate, active_threads); + auto repartitioned = MaybeRepartition(context.client, gstate, lstate); if (repartitioned && ht.Count() != 0) { // We repartitioned, but we didn't clear the pointer table / reset the count because we're on 1 or 2 threads @@ -481,7 +484,7 @@ void RadixPartitionedHashTable::Combine(ExecutionContext &context, GlobalSinkSta // Set any_combined, then check one last time whether we need to repartition gstate.any_combined = true; - MaybeRepartition(context.client, gstate, lstate, gstate.active_threads); + MaybeRepartition(context.client, gstate, lstate); auto &ht = *lstate.ht; ht.UnpinData(); @@ -513,7 +516,7 @@ void RadixPartitionedHashTable::Finalize(ClientContext &context, GlobalSinkState gstate.count_before_combining = uncombined_data.Count(); // If true there is no need to combine, it was all done by a single thread in a single HT - const auto single_ht = !gstate.external && gstate.active_threads == 1; + const auto single_ht = !gstate.external && gstate.active_threads == 1 && gstate.number_of_threads == 1; auto &uncombined_partition_data = uncombined_data.GetPartitions(); const auto n_partitions = uncombined_partition_data.size(); @@ -522,7 +525,7 @@ void RadixPartitionedHashTable::Finalize(ClientContext &context, GlobalSinkState auto &partition = uncombined_partition_data[i]; auto partition_size = partition->SizeInBytes() + - GroupedAggregateHashTable::GetCapacityForCount(partition->Count()) * sizeof(aggr_ht_entry_t); + GroupedAggregateHashTable::GetCapacityForCount(partition->Count()) * sizeof(ht_entry_t); gstate.max_partition_size = MaxValue(gstate.max_partition_size, partition_size); gstate.partitions.emplace_back(make_uniq(std::move(partition))); @@ -591,7 +594,6 @@ class RadixHTGlobalSourceState : public GlobalSourceState { vector column_ids; //! For synchronizing tasks - mutex lock; idx_t task_idx; atomic task_done; }; @@ -651,7 +653,7 @@ RadixHTGlobalSourceState::RadixHTGlobalSourceState(ClientContext &context_p, con SourceResultType RadixHTGlobalSourceState::AssignTask(RadixHTGlobalSinkState &sink, RadixHTLocalSourceState &lstate, InterruptState &interrupt_state) { // First, try to get a partition index - lock_guard gstate_guard(lock); + lock_guard gstate_guard(sink.lock); if (finished) { return SourceResultType::FINISHED; } @@ -720,11 +722,13 @@ void RadixHTLocalSourceState::Finalize(RadixHTGlobalSinkState &sink, RadixHTGlob // However, we will limit the initial capacity so we don't do a huge over-allocation const auto n_threads = NumericCast(TaskScheduler::GetScheduler(gstate.context).NumberOfThreads()); const auto memory_limit = BufferManager::GetBufferManager(gstate.context).GetMaxMemory(); - const idx_t thread_limit = NumericCast(0.6 * memory_limit / n_threads); + const idx_t thread_limit = NumericCast(0.6 * double(memory_limit) / double(n_threads)); const idx_t size_per_entry = partition.data->SizeInBytes() / MaxValue(partition.data->Count(), 1) + - idx_t(GroupedAggregateHashTable::LOAD_FACTOR * sizeof(aggr_ht_entry_t)); - const auto capacity_limit = NextPowerOfTwo(thread_limit / size_per_entry); + idx_t(GroupedAggregateHashTable::LOAD_FACTOR * sizeof(ht_entry_t)); + // but not lower than the initial capacity + const auto capacity_limit = + MaxValue(NextPowerOfTwo(thread_limit / size_per_entry), GroupedAggregateHashTable::InitialCapacity()); ht = sink.radix_ht.CreateHT(gstate.context, MinValue(capacity, capacity_limit), 0); } else { @@ -745,7 +749,7 @@ void RadixHTLocalSourceState::Finalize(RadixHTGlobalSinkState &sink, RadixHTGlob partition.data->Combine(*ht->GetPartitionedData()->GetPartitions()[0]); // Update thread-global state - lock_guard global_guard(gstate.lock); + lock_guard global_guard(sink.lock); sink.stored_allocators.emplace_back(ht->GetAggregateAllocator()); const auto finalizes_done = ++sink.finalize_done; D_ASSERT(finalizes_done <= sink.partitions.size()); @@ -785,7 +789,7 @@ void RadixHTLocalSourceState::Scan(RadixHTGlobalSinkState &sink, RadixHTGlobalSo data_collection.Reset(); } scan_status = RadixHTScanStatus::DONE; - lock_guard gstate_guard(gstate.lock); + lock_guard gstate_guard(sink.lock); if (++gstate.task_done == sink.partitions.size()) { gstate.finished = true; } @@ -912,10 +916,10 @@ double RadixPartitionedHashTable::GetProgress(ClientContext &, GlobalSinkState & } // Get scan progress, weigh it 1x - total_progress += 1.0 * gstate.task_done; + total_progress += 1.0 * double(gstate.task_done); // Divide by 3x for the weights, and the number of partitions to get a value between 0 and 1 again - total_progress /= 3.0 * sink.partitions.size(); + total_progress /= 3.0 * double(sink.partitions.size()); // Multiply by 100 to get a percentage return 100.0 * total_progress; diff --git a/src/execution/reservoir_sample.cpp b/src/execution/reservoir_sample.cpp index 0aba8bf7fb5..fc711d91c19 100644 --- a/src/execution/reservoir_sample.cpp +++ b/src/execution/reservoir_sample.cpp @@ -4,48 +4,55 @@ namespace duckdb { -void BlockingSample::Serialize(Serializer &serializer) const { +void ReservoirChunk::Serialize(Serializer &serializer) const { + chunk.Serialize(serializer); } -unique_ptr BlockingSample::Deserialize(Deserializer &deserializer) { - return nullptr; +unique_ptr ReservoirChunk::Deserialize(Deserializer &deserializer) { + auto result = make_uniq(); + result->chunk.Deserialize(deserializer); + return result; } ReservoirSample::ReservoirSample(Allocator &allocator, idx_t sample_count, int64_t seed) : BlockingSample(seed), allocator(allocator), sample_count(sample_count), reservoir_initialized(false) { } +ReservoirSample::ReservoirSample(idx_t sample_count, int64_t seed) + : ReservoirSample(Allocator::DefaultAllocator(), sample_count, seed) { +} + void ReservoirSample::AddToReservoir(DataChunk &input) { if (sample_count == 0) { // sample count is 0, means no samples were requested return; } - base_reservoir_sample.num_entries_seen_total += input.size(); + old_base_reservoir_sample.num_entries_seen_total += input.size(); // Input: A population V of n weighted items // Output: A reservoir R with a size m // 1: The first m items of V are inserted into R // first we need to check if the reservoir already has "m" elements - if (!reservoir_chunk || reservoir_chunk->size() < sample_count) { + if (!reservoir_data_chunk || reservoir_data_chunk->size() < sample_count) { if (FillReservoir(input) == 0) { // entire chunk was consumed by reservoir return; } } - D_ASSERT(reservoir_chunk); - D_ASSERT(reservoir_chunk->size() == sample_count); + D_ASSERT(reservoir_data_chunk); + D_ASSERT(reservoir_data_chunk->size() == sample_count); // Initialize the weights if they have not been already - if (base_reservoir_sample.reservoir_weights.empty()) { - base_reservoir_sample.InitializeReservoir(reservoir_chunk->size(), sample_count); + if (old_base_reservoir_sample.reservoir_weights.empty()) { + old_base_reservoir_sample.InitializeReservoir(reservoir_data_chunk->size(), sample_count); } // find the position of next_index_to_sample relative to number of seen entries (num_entries_to_skip_b4_next_sample) idx_t remaining = input.size(); idx_t base_offset = 0; while (true) { - idx_t offset = - base_reservoir_sample.next_index_to_sample - base_reservoir_sample.num_entries_to_skip_b4_next_sample; + idx_t offset = old_base_reservoir_sample.next_index_to_sample - + old_base_reservoir_sample.num_entries_to_skip_b4_next_sample; if (offset >= remaining) { // not in this chunk! increment current count and go to the next chunk - base_reservoir_sample.num_entries_to_skip_b4_next_sample += remaining; + old_base_reservoir_sample.num_entries_to_skip_b4_next_sample += remaining; return; } // in this chunk! replace the element @@ -57,47 +64,47 @@ void ReservoirSample::AddToReservoir(DataChunk &input) { } unique_ptr ReservoirSample::GetChunk() { - if (!reservoir_chunk || reservoir_chunk->size() == 0) { + if (!reservoir_data_chunk || reservoir_data_chunk->size() == 0) { return nullptr; } - auto collected_sample_count = reservoir_chunk->size(); + auto collected_sample_count = reservoir_data_chunk->size(); if (collected_sample_count > STANDARD_VECTOR_SIZE) { // get from the back to avoid creating two selection vectors // one to return the first STANDARD_VECTOR_SIZE - // another to replace the reservoir_chunk with the first STANDARD VECTOR SIZE missing + // another to replace the reservoir_data_chunk with the first STANDARD VECTOR SIZE missing auto ret = make_uniq(); auto samples_remaining = collected_sample_count - STANDARD_VECTOR_SIZE; - auto reservoir_types = reservoir_chunk->GetTypes(); + auto reservoir_types = reservoir_data_chunk->GetTypes(); SelectionVector sel(STANDARD_VECTOR_SIZE); for (idx_t i = samples_remaining; i < collected_sample_count; i++) { sel.set_index(i - samples_remaining, i); } ret->Initialize(allocator, reservoir_types.begin(), reservoir_types.end(), STANDARD_VECTOR_SIZE); - ret->Slice(*reservoir_chunk, sel, STANDARD_VECTOR_SIZE); + ret->Slice(*reservoir_data_chunk, sel, STANDARD_VECTOR_SIZE); ret->SetCardinality(STANDARD_VECTOR_SIZE); // reduce capacity and cardinality of the sample data chunk - reservoir_chunk->SetCardinality(samples_remaining); + reservoir_data_chunk->SetCardinality(samples_remaining); return ret; } - return std::move(reservoir_chunk); + return std::move(reservoir_data_chunk); } void ReservoirSample::ReplaceElement(DataChunk &input, idx_t index_in_chunk, double with_weight) { // replace the entry in the reservoir // 8. The item in R with the minimum key is replaced by item vi - D_ASSERT(input.ColumnCount() == reservoir_chunk->ColumnCount()); + D_ASSERT(input.ColumnCount() == reservoir_data_chunk->ColumnCount()); for (idx_t col_idx = 0; col_idx < input.ColumnCount(); col_idx++) { - reservoir_chunk->SetValue(col_idx, base_reservoir_sample.min_weighted_entry_index, - input.GetValue(col_idx, index_in_chunk)); + reservoir_data_chunk->SetValue(col_idx, old_base_reservoir_sample.min_weighted_entry_index, + input.GetValue(col_idx, index_in_chunk)); } - base_reservoir_sample.ReplaceElement(with_weight); + old_base_reservoir_sample.ReplaceElement(with_weight); } void ReservoirSample::InitializeReservoir(DataChunk &input) { - reservoir_chunk = make_uniq(); - reservoir_chunk->Initialize(allocator, input.GetTypes(), sample_count); - for (idx_t col_idx = 0; col_idx < reservoir_chunk->ColumnCount(); col_idx++) { - FlatVector::Validity(reservoir_chunk->data[col_idx]).Initialize(sample_count); + reservoir_data_chunk = make_uniq(); + reservoir_data_chunk->Initialize(allocator, input.GetTypes(), sample_count); + for (idx_t col_idx = 0; col_idx < reservoir_data_chunk->ColumnCount(); col_idx++) { + FlatVector::Validity(reservoir_data_chunk->data[col_idx]).Initialize(sample_count); } reservoir_initialized = true; } @@ -105,7 +112,7 @@ void ReservoirSample::InitializeReservoir(DataChunk &input) { idx_t ReservoirSample::FillReservoir(DataChunk &input) { idx_t chunk_count = input.size(); input.Flatten(); - auto num_added_samples = reservoir_chunk ? reservoir_chunk->size() : 0; + auto num_added_samples = reservoir_data_chunk ? reservoir_data_chunk->size() : 0; D_ASSERT(num_added_samples <= sample_count); // required count is what we still need to add to the reservoir @@ -123,8 +130,8 @@ idx_t ReservoirSample::FillReservoir(DataChunk &input) { if (!reservoir_initialized) { InitializeReservoir(input); } - reservoir_chunk->Append(input, false, nullptr, required_count); - base_reservoir_sample.InitializeReservoir(required_count, sample_count); + reservoir_data_chunk->Append(input, false, nullptr, required_count); + old_base_reservoir_sample.InitializeReservoir(required_count, sample_count); // check if there are still elements remaining in the Input data chunk that should be // randomly sampled and potentially added. This happens if we are on a boundary @@ -155,8 +162,12 @@ ReservoirSamplePercentage::ReservoirSamplePercentage(Allocator &allocator, doubl current_sample = make_uniq(allocator, reservoir_sample_size, random.NextRandomInteger()); } +ReservoirSamplePercentage::ReservoirSamplePercentage(double percentage, int64_t seed) + : ReservoirSamplePercentage(Allocator::DefaultAllocator(), percentage, seed) { +} + void ReservoirSamplePercentage::AddToReservoir(DataChunk &input) { - base_reservoir_sample.num_entries_seen_total += input.size(); + old_base_reservoir_sample.num_entries_seen_total += input.size(); if (current_count + input.size() > RESERVOIR_THRESHOLD) { // we don't have enough space in our current reservoir // first check what we still need to append to the current sample diff --git a/src/execution/window_executor.cpp b/src/execution/window_executor.cpp index 4d6b9b099c3..eff799037e4 100644 --- a/src/execution/window_executor.cpp +++ b/src/execution/window_executor.cpp @@ -193,7 +193,7 @@ struct WindowColumnIterator { template struct OperationCompare : public std::function { inline bool operator()(const T &lhs, const T &val) const { - return OP::template Operation(lhs, val); + return OP::template Operation(lhs, val); } }; @@ -335,7 +335,7 @@ struct WindowBoundariesState { } } - WindowBoundariesState(BoundWindowExpression &wexpr, const idx_t input_size); + WindowBoundariesState(const BoundWindowExpression &wexpr, const idx_t input_size); void Update(const idx_t row_idx, const WindowInputColumn &range_collection, const idx_t chunk_idx, WindowInputExpression &boundary_start, WindowInputExpression &boundary_end, @@ -364,8 +364,8 @@ struct WindowBoundariesState { idx_t peer_end = 0; idx_t valid_start = 0; idx_t valid_end = 0; - int64_t window_start = -1; - int64_t window_end = -1; + idx_t window_start = NumericLimits::Maximum(); + idx_t window_end = NumericLimits::Maximum(); FrameBounds prev; }; @@ -447,49 +447,51 @@ void WindowBoundariesState::Update(const idx_t row_idx, const WindowInputColumn next_pos = row_idx + 1; // determine window boundaries depending on the type of expression - window_start = -1; - window_end = -1; - switch (start_boundary) { case WindowBoundary::UNBOUNDED_PRECEDING: - window_start = NumericCast(partition_start); + window_start = partition_start; break; case WindowBoundary::CURRENT_ROW_ROWS: - window_start = NumericCast(row_idx); + window_start = row_idx; break; case WindowBoundary::CURRENT_ROW_RANGE: - window_start = NumericCast(peer_start); + window_start = peer_start; break; case WindowBoundary::EXPR_PRECEDING_ROWS: { - if (!TrySubtractOperator::Operation(int64_t(row_idx), boundary_start.GetCell(chunk_idx), - window_start)) { + int64_t computed_start; + if (!TrySubtractOperator::Operation(static_cast(row_idx), boundary_start.GetCell(chunk_idx), + computed_start)) { throw OutOfRangeException("Overflow computing ROWS PRECEDING start"); } + window_start = UnsafeNumericCast(MaxValue(computed_start, 0)); break; } case WindowBoundary::EXPR_FOLLOWING_ROWS: { - if (!TryAddOperator::Operation(int64_t(row_idx), boundary_start.GetCell(chunk_idx), window_start)) { + int64_t computed_start; + if (!TryAddOperator::Operation(static_cast(row_idx), boundary_start.GetCell(chunk_idx), + computed_start)) { throw OutOfRangeException("Overflow computing ROWS FOLLOWING start"); } + window_start = UnsafeNumericCast(MaxValue(computed_start, 0)); break; } case WindowBoundary::EXPR_PRECEDING_RANGE: { if (boundary_start.CellIsNull(chunk_idx)) { - window_start = NumericCast(peer_start); + window_start = peer_start; } else { prev.start = FindOrderedRangeBound(range_collection, range_sense, valid_start, row_idx, start_boundary, boundary_start, chunk_idx, prev); - window_start = NumericCast(prev.start); + window_start = prev.start; } break; } case WindowBoundary::EXPR_FOLLOWING_RANGE: { if (boundary_start.CellIsNull(chunk_idx)) { - window_start = NumericCast(peer_start); + window_start = peer_start; } else { prev.start = FindOrderedRangeBound(range_collection, range_sense, row_idx, valid_end, start_boundary, boundary_start, chunk_idx, prev); - window_start = NumericCast(prev.start); + window_start = prev.start; } break; } @@ -499,42 +501,49 @@ void WindowBoundariesState::Update(const idx_t row_idx, const WindowInputColumn switch (end_boundary) { case WindowBoundary::CURRENT_ROW_ROWS: - window_end = NumericCast(row_idx + 1); + window_end = row_idx + 1; break; case WindowBoundary::CURRENT_ROW_RANGE: - window_end = NumericCast(peer_end); + window_end = peer_end; break; case WindowBoundary::UNBOUNDED_FOLLOWING: - window_end = NumericCast(partition_end); + window_end = partition_end; break; - case WindowBoundary::EXPR_PRECEDING_ROWS: + case WindowBoundary::EXPR_PRECEDING_ROWS: { + int64_t computed_start; if (!TrySubtractOperator::Operation(int64_t(row_idx + 1), boundary_end.GetCell(chunk_idx), - window_end)) { + computed_start)) { throw OutOfRangeException("Overflow computing ROWS PRECEDING end"); } + window_end = UnsafeNumericCast(MaxValue(computed_start, 0)); break; - case WindowBoundary::EXPR_FOLLOWING_ROWS: - if (!TryAddOperator::Operation(int64_t(row_idx + 1), boundary_end.GetCell(chunk_idx), window_end)) { + } + case WindowBoundary::EXPR_FOLLOWING_ROWS: { + int64_t computed_start; + if (!TryAddOperator::Operation(int64_t(row_idx + 1), boundary_end.GetCell(chunk_idx), + computed_start)) { throw OutOfRangeException("Overflow computing ROWS FOLLOWING end"); } + window_end = UnsafeNumericCast(MaxValue(computed_start, 0)); break; + } case WindowBoundary::EXPR_PRECEDING_RANGE: { if (boundary_end.CellIsNull(chunk_idx)) { - window_end = NumericCast(peer_end); + window_end = peer_end; } else { prev.end = FindOrderedRangeBound(range_collection, range_sense, valid_start, row_idx, end_boundary, boundary_end, chunk_idx, prev); - window_end = NumericCast(prev.end); + window_end = prev.end; } break; } case WindowBoundary::EXPR_FOLLOWING_RANGE: { if (boundary_end.CellIsNull(chunk_idx)) { - window_end = NumericCast(peer_end); + window_end = peer_end; } else { prev.end = FindOrderedRangeBound(range_collection, range_sense, row_idx, valid_end, end_boundary, boundary_end, chunk_idx, prev); - window_end = NumericCast(prev.end); + window_end = prev.end; } break; } @@ -543,33 +552,29 @@ void WindowBoundariesState::Update(const idx_t row_idx, const WindowInputColumn } // clamp windows to partitions if they should exceed - if (window_start < NumericCast(partition_start)) { - window_start = NumericCast(partition_start); - } - if (window_start > NumericCast(partition_end)) { - window_start = NumericCast(partition_end); + if (window_start < partition_start) { + window_start = partition_start; } - if (window_end < NumericCast(partition_start)) { - window_end = NumericCast(partition_start); + if (window_start > partition_end) { + window_start = partition_end; } - if (window_end > NumericCast(partition_end)) { - window_end = NumericCast(partition_end); + if (window_end < partition_start) { + window_end = partition_start; } - - if (window_start < 0 || window_end < 0) { - throw InternalException("Failed to compute window boundaries"); + if (window_end > partition_end) { + window_end = partition_end; } } -static bool HasPrecedingRange(BoundWindowExpression &wexpr) { +static bool HasPrecedingRange(const BoundWindowExpression &wexpr) { return (wexpr.start == WindowBoundary::EXPR_PRECEDING_RANGE || wexpr.end == WindowBoundary::EXPR_PRECEDING_RANGE); } -static bool HasFollowingRange(BoundWindowExpression &wexpr) { +static bool HasFollowingRange(const BoundWindowExpression &wexpr) { return (wexpr.start == WindowBoundary::EXPR_FOLLOWING_RANGE || wexpr.end == WindowBoundary::EXPR_FOLLOWING_RANGE); } -WindowBoundariesState::WindowBoundariesState(BoundWindowExpression &wexpr, const idx_t input_size) +WindowBoundariesState::WindowBoundariesState(const BoundWindowExpression &wexpr, const idx_t input_size) : type(wexpr.type), input_size(input_size), start_boundary(wexpr.start), end_boundary(wexpr.end), partition_count(wexpr.partitions.size()), order_count(wexpr.orders.size()), range_sense(wexpr.orders.empty() ? OrderType::INVALID : wexpr.orders[0].type), @@ -598,8 +603,8 @@ void WindowBoundariesState::Bounds(DataChunk &bounds, idx_t row_idx, const Windo *peer_begin_data++ = peer_start; *peer_end_data++ = peer_end; } - *window_begin_data++ = window_start; - *window_end_data++ = window_end; + *window_begin_data++ = UnsafeNumericCast(window_start); + *window_end_data++ = UnsafeNumericCast(window_end); } bounds.SetCardinality(count); } @@ -607,10 +612,9 @@ void WindowBoundariesState::Bounds(DataChunk &bounds, idx_t row_idx, const Windo //===--------------------------------------------------------------------===// // WindowExecutorBoundsState //===--------------------------------------------------------------------===// -class WindowExecutorBoundsState : public WindowExecutorState { +class WindowExecutorBoundsState : public WindowExecutorLocalState { public: - WindowExecutorBoundsState(BoundWindowExpression &wexpr, ClientContext &context, const idx_t count, - const ValidityMask &partition_mask_p, const ValidityMask &order_mask_p); + explicit WindowExecutorBoundsState(const WindowExecutorGlobalState &gstate); ~WindowExecutorBoundsState() override { } @@ -627,13 +631,13 @@ class WindowExecutorBoundsState : public WindowExecutorState { WindowInputExpression boundary_end; }; -WindowExecutorBoundsState::WindowExecutorBoundsState(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask_p, - const ValidityMask &order_mask_p) - : partition_mask(partition_mask_p), order_mask(order_mask_p), state(wexpr, payload_count), - boundary_start(wexpr.start_expr.get(), context), boundary_end(wexpr.end_expr.get(), context) { +WindowExecutorBoundsState::WindowExecutorBoundsState(const WindowExecutorGlobalState &gstate) + : WindowExecutorLocalState(gstate), partition_mask(gstate.partition_mask), order_mask(gstate.order_mask), + state(gstate.executor.wexpr, gstate.payload_count), + boundary_start(gstate.executor.wexpr.start_expr.get(), gstate.executor.context), + boundary_end(gstate.executor.wexpr.end_expr.get(), gstate.executor.context) { vector bounds_types(6, LogicalType(LogicalTypeId::UBIGINT)); - bounds.Initialize(Allocator::Get(context), bounds_types); + bounds.Initialize(Allocator::Get(gstate.executor.context), bounds_types); } void WindowExecutorBoundsState::UpdateBounds(idx_t row_idx, DataChunk &input_chunk, const WindowInputColumn &range) { @@ -746,24 +750,23 @@ void ExclusionFilter::ResetMask(idx_t row_idx, idx_t offset) { } //===--------------------------------------------------------------------===// -// WindowValueState +// WindowValueLocalState //===--------------------------------------------------------------------===// //! A class representing the state of the first_value, last_value and nth_value functions -class WindowValueState : public WindowExecutorBoundsState { +class WindowValueLocalState : public WindowExecutorBoundsState { public: - WindowValueState(BoundWindowExpression &wexpr, ClientContext &context, const idx_t count, - const ValidityMask &partition_mask_p, const ValidityMask &order_mask_p, - const ValidityMask &ignore_nulls) - : WindowExecutorBoundsState(wexpr, context, count, partition_mask_p, order_mask_p) + WindowValueLocalState(const WindowExecutorGlobalState &gstate, const ValidityMask &ignore_nulls) + : WindowExecutorBoundsState(gstate) { - if (wexpr.exclude_clause == WindowExcludeMode::NO_OTHER) { + if (gstate.executor.wexpr.exclude_clause == WindowExcludeMode::NO_OTHER) { exclusion_filter = nullptr; ignore_nulls_exclude = &ignore_nulls; } else { // create the exclusion filter based on ignore_nulls - exclusion_filter = make_uniq(wexpr.exclude_clause, count, ignore_nulls); + exclusion_filter = + make_uniq(gstate.executor.wexpr.exclude_clause, gstate.payload_count, ignore_nulls); ignore_nulls_exclude = &exclusion_filter->mask; } } @@ -777,7 +780,7 @@ class WindowValueState : public WindowExecutorBoundsState { //===--------------------------------------------------------------------===// // WindowExecutor //===--------------------------------------------------------------------===// -static void PrepareInputExpressions(vector> &exprs, ExpressionExecutor &executor, +static void PrepareInputExpressions(const vector> &exprs, ExpressionExecutor &executor, DataChunk &chunk) { if (exprs.empty()) { return; @@ -795,31 +798,57 @@ static void PrepareInputExpressions(vector> &exprs, Expre } } -WindowExecutor::WindowExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask) - : wexpr(wexpr), context(context), payload_count(payload_count), partition_mask(partition_mask), - order_mask(order_mask), payload_collection(), payload_executor(context), - range((HasPrecedingRange(wexpr) || HasFollowingRange(wexpr)) ? wexpr.orders[0].expression.get() : nullptr, - context, payload_count) { +WindowExecutor::WindowExecutor(BoundWindowExpression &wexpr, ClientContext &context) : wexpr(wexpr), context(context) { +} + +WindowExecutorGlobalState::WindowExecutorGlobalState(const WindowExecutor &executor, const idx_t payload_count, + const ValidityMask &partition_mask, const ValidityMask &order_mask) + : executor(executor), payload_count(payload_count), partition_mask(partition_mask), order_mask(order_mask), + payload_executor(executor.context), range((HasPrecedingRange(executor.wexpr) || HasFollowingRange(executor.wexpr)) + ? executor.wexpr.orders[0].expression.get() + : nullptr, + executor.context, payload_count) { + // TODO: child may be a scalar, don't need to materialize the whole collection then // evaluate inner expressions of window functions, could be more complex - PrepareInputExpressions(wexpr.children, payload_executor, payload_chunk); + PrepareInputExpressions(executor.wexpr.children, payload_executor, payload_chunk); +} - auto types = payload_chunk.GetTypes(); - if (!types.empty()) { - payload_collection.Initialize(Allocator::Get(context), types); - } +unique_ptr WindowExecutor::GetGlobalState(const idx_t payload_count, + const ValidityMask &partition_mask, + const ValidityMask &order_mask) const { + return make_uniq(*this, payload_count, partition_mask, order_mask); } -unique_ptr WindowExecutor::GetExecutorState() const { - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); +unique_ptr WindowExecutor::GetLocalState(const WindowExecutorGlobalState &gstate) const { + return make_uniq(gstate); } //===--------------------------------------------------------------------===// // WindowAggregateExecutor //===--------------------------------------------------------------------===// -bool WindowAggregateExecutor::IsConstantAggregate() { +class WindowAggregateExecutorGlobalState : public WindowExecutorGlobalState { +public: + bool IsConstantAggregate(); + bool IsCustomAggregate(); + bool IsDistinctAggregate(); + + WindowAggregateExecutorGlobalState(const WindowAggregateExecutor &executor, const idx_t payload_count, + const ValidityMask &partition_mask, const ValidityMask &order_mask); + + ExpressionExecutor filter_executor; + SelectionVector filter_sel; + + // aggregate computation algorithm + unique_ptr aggregator; + // aggregate global state + unique_ptr gsink; +}; + +bool WindowAggregateExecutorGlobalState::IsConstantAggregate() { + const auto &wexpr = executor.wexpr; + if (!wexpr.aggregate) { return false; } @@ -877,7 +906,9 @@ bool WindowAggregateExecutor::IsConstantAggregate() { return true; } -bool WindowAggregateExecutor::IsDistinctAggregate() { +bool WindowAggregateExecutorGlobalState::IsDistinctAggregate() { + const auto &wexpr = executor.wexpr; + if (!wexpr.aggregate) { return false; } @@ -885,7 +916,10 @@ bool WindowAggregateExecutor::IsDistinctAggregate() { return wexpr.distinct; } -bool WindowAggregateExecutor::IsCustomAggregate() { +bool WindowAggregateExecutorGlobalState::IsCustomAggregate() { + const auto &wexpr = executor.wexpr; + const auto &mode = reinterpret_cast(executor).mode; + if (!wexpr.aggregate) { return false; } @@ -897,43 +931,55 @@ bool WindowAggregateExecutor::IsCustomAggregate() { return (mode < WindowAggregationMode::COMBINE); } -void WindowExecutor::Evaluate(idx_t row_idx, DataChunk &input_chunk, Vector &result, - WindowExecutorState &lstate) const { +void WindowExecutor::Evaluate(idx_t row_idx, DataChunk &input_chunk, Vector &result, WindowExecutorLocalState &lstate, + WindowExecutorGlobalState &gstate) const { auto &lbstate = lstate.Cast(); - lbstate.UpdateBounds(row_idx, input_chunk, range); + lbstate.UpdateBounds(row_idx, input_chunk, gstate.range); const auto count = input_chunk.size(); - EvaluateInternal(lstate, result, count, row_idx); + EvaluateInternal(gstate, lstate, result, count, row_idx); result.Verify(count); } WindowAggregateExecutor::WindowAggregateExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t count, const ValidityMask &partition_mask, - const ValidityMask &order_mask, WindowAggregationMode mode) - : WindowExecutor(wexpr, context, count, partition_mask, order_mask), mode(mode), filter_executor(context) { + WindowAggregationMode mode) + : WindowExecutor(wexpr, context), mode(mode) { +} + +WindowAggregateExecutorGlobalState::WindowAggregateExecutorGlobalState(const WindowAggregateExecutor &executor, + const idx_t group_count, + const ValidityMask &partition_mask, + const ValidityMask &order_mask) + : WindowExecutorGlobalState(executor, group_count, partition_mask, order_mask), filter_executor(executor.context) { + auto &wexpr = executor.wexpr; + auto &context = executor.context; + auto return_type = wexpr.return_type; + auto arg_types = payload_chunk.GetTypes(); + const auto &mode = reinterpret_cast(executor).mode; // Force naive for SEPARATE mode or for (currently!) unsupported functionality const auto force_naive = !ClientConfig::GetConfig(context).enable_optimizer || mode == WindowAggregationMode::SEPARATE; AggregateObject aggr(wexpr); if (force_naive || (wexpr.distinct && wexpr.exclude_clause != WindowExcludeMode::NO_OTHER)) { - aggregator = make_uniq(aggr, wexpr.return_type, wexpr.exclude_clause, count); + aggregator = make_uniq(aggr, arg_types, return_type, wexpr.exclude_clause); } else if (IsDistinctAggregate()) { // build a merge sort tree // see https://dl.acm.org/doi/pdf/10.1145/3514221.3526184 - aggregator = make_uniq(aggr, wexpr.return_type, wexpr.exclude_clause, count, context); + aggregator = make_uniq(aggr, arg_types, return_type, wexpr.exclude_clause, context); } else if (IsConstantAggregate()) { - aggregator = - make_uniq(aggr, wexpr.return_type, partition_mask, wexpr.exclude_clause, count); + aggregator = make_uniq(aggr, arg_types, return_type, wexpr.exclude_clause); } else if (IsCustomAggregate()) { - aggregator = make_uniq(aggr, wexpr.return_type, wexpr.exclude_clause, count); + aggregator = make_uniq(aggr, arg_types, return_type, wexpr.exclude_clause); } else { // build a segment tree for frame-adhering aggregates // see http://www.vldb.org/pvldb/vol8/p1058-leis.pdf - aggregator = make_uniq(aggr, wexpr.return_type, mode, wexpr.exclude_clause, count); + aggregator = make_uniq(aggr, arg_types, return_type, mode, wexpr.exclude_clause); } + gsink = aggregator->GetGlobalState(group_count, partition_mask); + // evaluate the FILTER clause and stuff it into a large mask for compactness and reuse if (wexpr.filter_expr) { filter_executor.AddExpression(*wexpr.filter_expr); @@ -941,7 +987,22 @@ WindowAggregateExecutor::WindowAggregateExecutor(BoundWindowExpression &wexpr, C } } -void WindowAggregateExecutor::Sink(DataChunk &input_chunk, const idx_t input_idx, const idx_t total_count) { +unique_ptr WindowAggregateExecutor::GetGlobalState(const idx_t payload_count, + const ValidityMask &partition_mask, + const ValidityMask &order_mask) const { + return make_uniq(*this, payload_count, partition_mask, order_mask); +} + +void WindowAggregateExecutor::Sink(DataChunk &input_chunk, const idx_t input_idx, const idx_t total_count, + WindowExecutorGlobalState &gstate) const { + auto &gastate = gstate.Cast(); + auto &filter_sel = gastate.filter_sel; + auto &filter_executor = gastate.filter_executor; + auto &payload_executor = gastate.payload_executor; + auto &payload_chunk = gastate.payload_chunk; + auto &aggregator = gastate.aggregator; + auto &gsink = gastate.gsink; + // TODO we could evaluate those expressions in parallel idx_t filtered = 0; SelectionVector *filtering = nullptr; @@ -960,9 +1021,9 @@ void WindowAggregateExecutor::Sink(DataChunk &input_chunk, const idx_t input_idx } D_ASSERT(aggregator); - aggregator->Sink(payload_chunk, filtering, filtered); + aggregator->Sink(*gsink, payload_chunk, filtering, filtered); - WindowExecutor::Sink(input_chunk, input_idx, total_count); + WindowExecutor::Sink(input_chunk, input_idx, total_count, gstate); } static void ApplyWindowStats(const WindowBoundary &boundary, FrameDelta &delta, BaseStatistics *base, bool is_start) { @@ -1023,13 +1084,16 @@ static void ApplyWindowStats(const WindowBoundary &boundary, FrameDelta &delta, } } -void WindowAggregateExecutor::Finalize() { +void WindowAggregateExecutor::Finalize(WindowExecutorGlobalState &gstate) const { + auto &gastate = gstate.Cast(); + auto &aggregator = gastate.aggregator; + auto &gsink = gastate.gsink; D_ASSERT(aggregator); // Estimate the frame statistics // Default to the entire partition if we don't know anything FrameStats stats; - const auto count = NumericCast(aggregator->GetInputs().size()); + const auto count = NumericCast(gastate.payload_count); // First entry is the frame start stats[0] = FrameDelta(-count, count); @@ -1041,16 +1105,13 @@ void WindowAggregateExecutor::Finalize() { base = wexpr.expr_stats.empty() ? nullptr : wexpr.expr_stats[1].get(); ApplyWindowStats(wexpr.end, stats[1], base, false); - aggregator->Finalize(stats); + aggregator->Finalize(*gsink, stats); } -class WindowAggregateState : public WindowExecutorBoundsState { +class WindowAggregateExecutorLocalState : public WindowExecutorBoundsState { public: - WindowAggregateState(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask, - const WindowAggregator &aggregator) - : WindowExecutorBoundsState(wexpr, context, payload_count, partition_mask, order_mask), - aggregator_state(aggregator.GetLocalState()) { + WindowAggregateExecutorLocalState(const WindowExecutorGlobalState &gstate, const WindowAggregator &aggregator) + : WindowExecutorBoundsState(gstate), aggregator_state(aggregator.GetLocalState()) { } public: @@ -1060,32 +1121,35 @@ class WindowAggregateState : public WindowExecutorBoundsState { void NextRank(idx_t partition_begin, idx_t peer_begin, idx_t row_idx); }; -unique_ptr WindowAggregateExecutor::GetExecutorState() const { - auto res = make_uniq(wexpr, context, payload_count, partition_mask, order_mask, *aggregator); +unique_ptr +WindowAggregateExecutor::GetLocalState(const WindowExecutorGlobalState &gstate) const { + auto &gastate = gstate.Cast(); + auto res = make_uniq(gstate, *gastate.aggregator); return std::move(res); } -void WindowAggregateExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { - auto &lastate = lstate.Cast(); +void WindowAggregateExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { + auto &gastate = gstate.Cast(); + auto &lastate = lstate.Cast(); + auto &aggregator = gastate.aggregator; + auto &gsink = gastate.gsink; D_ASSERT(aggregator); auto &agg_state = *lastate.aggregator_state; - aggregator->Evaluate(agg_state, lastate.bounds, result, count, row_idx); + aggregator->Evaluate(*gsink, agg_state, lastate.bounds, result, count, row_idx); } //===--------------------------------------------------------------------===// // WindowRowNumberExecutor //===--------------------------------------------------------------------===// -WindowRowNumberExecutor::WindowRowNumberExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask, - const ValidityMask &order_mask) - : WindowExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowRowNumberExecutor::WindowRowNumberExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowExecutor(wexpr, context) { } -void WindowRowNumberExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { +void WindowRowNumberExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { auto &lbstate = lstate.Cast(); auto partition_begin = FlatVector::GetData(lbstate.bounds.data[PARTITION_BEGIN]); auto rdata = FlatVector::GetData(result); @@ -1099,9 +1163,7 @@ void WindowRowNumberExecutor::EvaluateInternal(WindowExecutorState &lstate, Vect //===--------------------------------------------------------------------===// class WindowPeerState : public WindowExecutorBoundsState { public: - WindowPeerState(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask) - : WindowExecutorBoundsState(wexpr, context, payload_count, partition_mask, order_mask) { + explicit WindowPeerState(const WindowExecutorGlobalState &gstate) : WindowExecutorBoundsState(gstate) { } public: @@ -1125,17 +1187,16 @@ void WindowPeerState::NextRank(idx_t partition_begin, idx_t peer_begin, idx_t ro rank_equal++; } -WindowRankExecutor::WindowRankExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask) - : WindowExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowRankExecutor::WindowRankExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowExecutor(wexpr, context) { } -unique_ptr WindowRankExecutor::GetExecutorState() const { - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); +unique_ptr WindowRankExecutor::GetLocalState(const WindowExecutorGlobalState &gstate) const { + return make_uniq(gstate); } -void WindowRankExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { +void WindowRankExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { auto &lpeer = lstate.Cast(); auto partition_begin = FlatVector::GetData(lpeer.bounds.data[PARTITION_BEGIN]); auto peer_begin = FlatVector::GetData(lpeer.bounds.data[PEER_BEGIN]); @@ -1151,19 +1212,20 @@ void WindowRankExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &r } } -WindowDenseRankExecutor::WindowDenseRankExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask, - const ValidityMask &order_mask) - : WindowExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowDenseRankExecutor::WindowDenseRankExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowExecutor(wexpr, context) { } -unique_ptr WindowDenseRankExecutor::GetExecutorState() const { - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); +unique_ptr +WindowDenseRankExecutor::GetLocalState(const WindowExecutorGlobalState &gstate) const { + return make_uniq(gstate); } -void WindowDenseRankExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { +void WindowDenseRankExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { auto &lpeer = lstate.Cast(); + + auto &order_mask = gstate.order_mask; auto partition_begin = FlatVector::GetData(lpeer.bounds.data[PARTITION_BEGIN]); auto peer_begin = FlatVector::GetData(lpeer.bounds.data[PEER_BEGIN]); auto rdata = FlatVector::GetData(result); @@ -1213,18 +1275,17 @@ void WindowDenseRankExecutor::EvaluateInternal(WindowExecutorState &lstate, Vect } } -WindowPercentRankExecutor::WindowPercentRankExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask, - const ValidityMask &order_mask) - : WindowExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowPercentRankExecutor::WindowPercentRankExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowExecutor(wexpr, context) { } -unique_ptr WindowPercentRankExecutor::GetExecutorState() const { - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); +unique_ptr +WindowPercentRankExecutor::GetLocalState(const WindowExecutorGlobalState &gstate) const { + return make_uniq(gstate); } -void WindowPercentRankExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { +void WindowPercentRankExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { auto &lpeer = lstate.Cast(); auto partition_begin = FlatVector::GetData(lpeer.bounds.data[PARTITION_BEGIN]); auto partition_end = FlatVector::GetData(lpeer.bounds.data[PARTITION_END]); @@ -1246,14 +1307,12 @@ void WindowPercentRankExecutor::EvaluateInternal(WindowExecutorState &lstate, Ve //===--------------------------------------------------------------------===// // WindowCumeDistExecutor //===--------------------------------------------------------------------===// -WindowCumeDistExecutor::WindowCumeDistExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask, - const ValidityMask &order_mask) - : WindowExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowCumeDistExecutor::WindowCumeDistExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowExecutor(wexpr, context) { } -void WindowCumeDistExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { +void WindowCumeDistExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { auto &lbstate = lstate.Cast(); auto partition_begin = FlatVector::GetData(lbstate.bounds.data[PARTITION_BEGIN]); auto partition_end = FlatVector::GetData(lbstate.bounds.data[PARTITION_END]); @@ -1266,22 +1325,54 @@ void WindowCumeDistExecutor::EvaluateInternal(WindowExecutorState &lstate, Vecto } } +//===--------------------------------------------------------------------===// +// WindowValueGlobalState +//===--------------------------------------------------------------------===// + +class WindowValueGlobalState : public WindowExecutorGlobalState { +public: + WindowValueGlobalState(const WindowExecutor &executor, const idx_t payload_count, + const ValidityMask &partition_mask, const ValidityMask &order_mask) + : WindowExecutorGlobalState(executor, payload_count, partition_mask, order_mask) + + { + auto types = payload_chunk.GetTypes(); + if (!types.empty()) { + payload_collection.Initialize(Allocator::Get(executor.context), types, payload_count); + } + } + + // The partition values + DataChunk payload_collection; + // IGNORE NULLS + ValidityMask ignore_nulls; +}; + //===--------------------------------------------------------------------===// // WindowValueExecutor //===--------------------------------------------------------------------===// -WindowValueExecutor::WindowValueExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask, - const ValidityMask &order_mask) - : WindowExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowValueExecutor::WindowValueExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowExecutor(wexpr, context) { } -WindowNtileExecutor::WindowNtileExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask, - const ValidityMask &order_mask) - : WindowValueExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowNtileExecutor::WindowNtileExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowValueExecutor(wexpr, context) { } -void WindowValueExecutor::Sink(DataChunk &input_chunk, const idx_t input_idx, const idx_t total_count) { +unique_ptr WindowValueExecutor::GetGlobalState(const idx_t payload_count, + const ValidityMask &partition_mask, + const ValidityMask &order_mask) const { + return make_uniq(*this, payload_count, partition_mask, order_mask); +} + +void WindowValueExecutor::Sink(DataChunk &input_chunk, const idx_t input_idx, const idx_t total_count, + WindowExecutorGlobalState &gstate) const { + auto &gvstate = gstate.Cast(); + auto &payload_chunk = gvstate.payload_chunk; + auto &payload_executor = gvstate.payload_executor; + auto &payload_collection = gvstate.payload_collection; + auto &ignore_nulls = gvstate.ignore_nulls; + // Single pass over the input to produce the global data. // Vectorisation for the win... @@ -1337,20 +1428,23 @@ void WindowValueExecutor::Sink(DataChunk &input_chunk, const idx_t input_idx, co } } - WindowExecutor::Sink(input_chunk, input_idx, total_count); + WindowExecutor::Sink(input_chunk, input_idx, total_count, gstate); } -unique_ptr WindowValueExecutor::GetExecutorState() const { +unique_ptr WindowValueExecutor::GetLocalState(const WindowExecutorGlobalState &gstate) const { if (wexpr.type == ExpressionType::WINDOW_FIRST_VALUE || wexpr.type == ExpressionType::WINDOW_LAST_VALUE || wexpr.type == ExpressionType::WINDOW_NTH_VALUE) { - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask, ignore_nulls); + auto &ignore_nulls = gstate.Cast().ignore_nulls; + return make_uniq(gstate, ignore_nulls); } else { - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); + return make_uniq(gstate); } } -void WindowNtileExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { +void WindowNtileExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { + auto &gvstate = gstate.Cast(); + auto &payload_collection = gvstate.payload_collection; D_ASSERT(payload_collection.ColumnCount() == 1); auto &lbstate = lstate.Cast(); auto partition_begin = FlatVector::GetData(lbstate.bounds.data[PARTITION_BEGIN]); @@ -1395,14 +1489,14 @@ void WindowNtileExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector & } //===--------------------------------------------------------------------===// -// WindowLeadLagState +// WindowLeadLagLocalState //===--------------------------------------------------------------------===// -class WindowLeadLagState : public WindowExecutorBoundsState { +class WindowLeadLagLocalState : public WindowExecutorBoundsState { public: - WindowLeadLagState(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask) - : WindowExecutorBoundsState(wexpr, context, payload_count, partition_mask, order_mask), - leadlag_offset(wexpr.offset_expr.get(), context), leadlag_default(wexpr.default_expr.get(), context) { + explicit WindowLeadLagLocalState(const WindowExecutorGlobalState &gstate) + : WindowExecutorBoundsState(gstate), + leadlag_offset(gstate.executor.wexpr.offset_expr.get(), gstate.executor.context), + leadlag_default(gstate.executor.wexpr.default_expr.get(), gstate.executor.context) { } void UpdateBounds(idx_t row_idx, DataChunk &input_chunk, const WindowInputColumn &range) override; @@ -1413,7 +1507,7 @@ class WindowLeadLagState : public WindowExecutorBoundsState { WindowInputExpression leadlag_default; }; -void WindowLeadLagState::UpdateBounds(idx_t row_idx, DataChunk &input_chunk, const WindowInputColumn &range) { +void WindowLeadLagLocalState::UpdateBounds(idx_t row_idx, DataChunk &input_chunk, const WindowInputColumn &range) { // Evaluate the row-level arguments leadlag_offset.Execute(input_chunk); leadlag_default.Execute(input_chunk); @@ -1421,19 +1515,21 @@ void WindowLeadLagState::UpdateBounds(idx_t row_idx, DataChunk &input_chunk, con WindowExecutorBoundsState::UpdateBounds(row_idx, input_chunk, range); } -WindowLeadLagExecutor::WindowLeadLagExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask, - const ValidityMask &order_mask) - : WindowValueExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowLeadLagExecutor::WindowLeadLagExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowValueExecutor(wexpr, context) { } -unique_ptr WindowLeadLagExecutor::GetExecutorState() const { - return make_uniq(wexpr, context, payload_count, partition_mask, order_mask); +unique_ptr +WindowLeadLagExecutor::GetLocalState(const WindowExecutorGlobalState &gstate) const { + return make_uniq(gstate); } -void WindowLeadLagExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { - auto &llstate = lstate.Cast(); +void WindowLeadLagExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { + auto &gvstate = gstate.Cast(); + auto &payload_collection = gvstate.payload_collection; + auto &ignore_nulls = gvstate.ignore_nulls; + auto &llstate = lstate.Cast(); auto partition_begin = FlatVector::GetData(llstate.bounds.data[PARTITION_BEGIN]); auto partition_end = FlatVector::GetData(llstate.bounds.data[PARTITION_END]); @@ -1470,15 +1566,15 @@ void WindowLeadLagExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector } } -WindowFirstValueExecutor::WindowFirstValueExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask, - const ValidityMask &order_mask) - : WindowValueExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowFirstValueExecutor::WindowFirstValueExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowValueExecutor(wexpr, context) { } -void WindowFirstValueExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { - auto &lvstate = lstate.Cast(); +void WindowFirstValueExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { + auto &gvstate = gstate.Cast(); + auto &payload_collection = gvstate.payload_collection; + auto &lvstate = lstate.Cast(); auto window_begin = FlatVector::GetData(lvstate.bounds.data[WINDOW_BEGIN]); auto window_end = FlatVector::GetData(lvstate.bounds.data[WINDOW_END]); for (idx_t i = 0; i < count; ++i, ++row_idx) { @@ -1506,15 +1602,15 @@ void WindowFirstValueExecutor::EvaluateInternal(WindowExecutorState &lstate, Vec } } -WindowLastValueExecutor::WindowLastValueExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask, - const ValidityMask &order_mask) - : WindowValueExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowLastValueExecutor::WindowLastValueExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowValueExecutor(wexpr, context) { } -void WindowLastValueExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { - auto &lvstate = lstate.Cast(); +void WindowLastValueExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { + auto &gvstate = gstate.Cast(); + auto &payload_collection = gvstate.payload_collection; + auto &lvstate = lstate.Cast(); auto window_begin = FlatVector::GetData(lvstate.bounds.data[WINDOW_BEGIN]); auto window_end = FlatVector::GetData(lvstate.bounds.data[WINDOW_END]); for (idx_t i = 0; i < count; ++i, ++row_idx) { @@ -1541,17 +1637,17 @@ void WindowLastValueExecutor::EvaluateInternal(WindowExecutorState &lstate, Vect } } -WindowNthValueExecutor::WindowNthValueExecutor(BoundWindowExpression &wexpr, ClientContext &context, - const idx_t payload_count, const ValidityMask &partition_mask, - const ValidityMask &order_mask) - : WindowValueExecutor(wexpr, context, payload_count, partition_mask, order_mask) { +WindowNthValueExecutor::WindowNthValueExecutor(BoundWindowExpression &wexpr, ClientContext &context) + : WindowValueExecutor(wexpr, context) { } -void WindowNthValueExecutor::EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, - idx_t row_idx) const { +void WindowNthValueExecutor::EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, + Vector &result, idx_t count, idx_t row_idx) const { + auto &gvstate = gstate.Cast(); + auto &payload_collection = gvstate.payload_collection; D_ASSERT(payload_collection.ColumnCount() == 2); - auto &lvstate = lstate.Cast(); + auto &lvstate = lstate.Cast(); auto window_begin = FlatVector::GetData(lvstate.bounds.data[WINDOW_BEGIN]); auto window_end = FlatVector::GetData(lvstate.bounds.data[WINDOW_END]); for (idx_t i = 0; i < count; ++i, ++row_idx) { diff --git a/src/execution/window_segment_tree.cpp b/src/execution/window_segment_tree.cpp index 5ea8429a299..d68992e6655 100644 --- a/src/execution/window_segment_tree.cpp +++ b/src/execution/window_segment_tree.cpp @@ -18,29 +18,56 @@ namespace duckdb { WindowAggregatorState::WindowAggregatorState() : allocator(Allocator::DefaultAllocator()) { } -WindowAggregator::WindowAggregator(AggregateObject aggr_p, const LogicalType &result_type_p, - const WindowExcludeMode exclude_mode_p, idx_t partition_count_p) - : aggr(std::move(aggr_p)), result_type(result_type_p), partition_count(partition_count_p), - state_size(aggr.function.state_size()), filter_pos(0), exclude_mode(exclude_mode_p) { +class WindowAggregatorGlobalState : public WindowAggregatorState { +public: + WindowAggregatorGlobalState(const WindowAggregator &aggregator_p, idx_t group_count) + : aggregator(aggregator_p), filter_pos(0) { + + if (!aggregator.arg_types.empty()) { + inputs.Initialize(Allocator::DefaultAllocator(), aggregator.arg_types); + } + if (aggregator.aggr.filter) { + // Start with all invalid and set the ones that pass + filter_bits.resize(ValidityMask::ValidityMaskSize(group_count), 0); + filter_mask.Initialize(filter_bits.data()); + } + } + + //! The aggregator data + const WindowAggregator &aggregator; + + //! Partition data chunk + DataChunk inputs; + + //! The filtered rows in inputs. + vector filter_bits; + ValidityMask filter_mask; + idx_t filter_pos; +}; + +WindowAggregator::WindowAggregator(AggregateObject aggr_p, const vector &arg_types_p, + const LogicalType &result_type_p, const WindowExcludeMode exclude_mode_p) + : aggr(std::move(aggr_p)), arg_types(arg_types_p), result_type(result_type_p), + state_size(aggr.function.state_size()), exclude_mode(exclude_mode_p) { } WindowAggregator::~WindowAggregator() { } -void WindowAggregator::Sink(DataChunk &payload_chunk, SelectionVector *filter_sel, idx_t filtered) { - if (!inputs.ColumnCount() && payload_chunk.ColumnCount()) { - inputs.Initialize(Allocator::DefaultAllocator(), payload_chunk.GetTypes()); - } +unique_ptr WindowAggregator::GetGlobalState(idx_t group_count, const ValidityMask &) const { + return make_uniq(*this, group_count); +} + +void WindowAggregator::Sink(WindowAggregatorState &gsink, DataChunk &payload_chunk, SelectionVector *filter_sel, + idx_t filtered) { + auto &gasink = gsink.Cast(); + auto &inputs = gasink.inputs; + auto &filter_mask = gasink.filter_mask; + auto &filter_pos = gasink.filter_pos; if (inputs.ColumnCount()) { inputs.Append(payload_chunk, true); } if (filter_sel) { - // Lazy instantiation - if (!filter_mask.IsMaskSet()) { - // Start with all invalid and set the ones that pass - filter_bits.resize(ValidityMask::ValidityMaskSize(partition_count), 0); - filter_mask.Initialize(filter_bits.data()); - } for (idx_t f = 0; f < filtered; ++f) { filter_mask.SetValid(filter_pos + filter_sel->get_index(f)); } @@ -48,16 +75,43 @@ void WindowAggregator::Sink(DataChunk &payload_chunk, SelectionVector *filter_se } } -void WindowAggregator::Finalize(const FrameStats &stats) { +void WindowAggregator::Finalize(WindowAggregatorState &gstate, const FrameStats &stats) { } //===--------------------------------------------------------------------===// -// WindowConstantAggregate +// WindowConstantAggregator //===--------------------------------------------------------------------===// -WindowConstantAggregator::WindowConstantAggregator(AggregateObject aggr, const LogicalType &result_type, - const ValidityMask &partition_mask, - const WindowExcludeMode exclude_mode_p, const idx_t count) - : WindowAggregator(std::move(aggr), result_type, exclude_mode_p, count), partition(0), row(0), state(state_size), +class WindowConstantAggregatorGlobalState : public WindowAggregatorGlobalState { +public: + WindowConstantAggregatorGlobalState(const WindowConstantAggregator &aggregator, idx_t count, + const ValidityMask &partition_mask); + + void Sink(DataChunk &payload_chunk, SelectionVector *filter_sel, idx_t filtered); + void Finalize(const FrameStats &stats); + + void AggregateInit(); + void AggegateFinal(Vector &result, idx_t rid); + + //! Partition starts + vector partition_offsets; + //! Aggregate results + unique_ptr results; + //! The current result partition being built/read + idx_t partition; + //! The current input row being built/read + idx_t row; + //! Data pointer that contains a single state, used for intermediate window segment aggregation + vector state; + //! A vector of pointers to "state", used for intermediate window segment aggregation + Vector statep; + //! Reused result state container for the window functions + Vector statef; +}; + +WindowConstantAggregatorGlobalState::WindowConstantAggregatorGlobalState(const WindowConstantAggregator &aggregator, + idx_t group_count, + const ValidityMask &partition_mask) + : WindowAggregatorGlobalState(aggregator, 0), partition(0), row(0), state(aggregator.state_size), statep(Value::POINTER(CastPointerToValue(state.data()))), statef(Value::POINTER(CastPointerToValue(state.data()))) { @@ -69,7 +123,7 @@ WindowConstantAggregator::WindowConstantAggregator(AggregateObject aggr, const L } else { idx_t entry_idx; idx_t shift; - for (idx_t start = 0; start < count;) { + for (idx_t start = 0; start < group_count;) { partition_mask.GetEntryIndex(start, entry_idx, shift); // If start is aligned with the start of a block, @@ -81,7 +135,7 @@ WindowConstantAggregator::WindowConstantAggregator(AggregateObject aggr, const L } // Loop over the block - for (; shift < ValidityMask::BITS_PER_VALUE && start < count; ++shift, ++start) { + for (; shift < ValidityMask::BITS_PER_VALUE && start < group_count; ++shift, ++start) { if (partition_mask.RowIsValid(block, shift)) { partition_offsets.emplace_back(start); } @@ -90,22 +144,27 @@ WindowConstantAggregator::WindowConstantAggregator(AggregateObject aggr, const L } // Initialise the vector for caching the results - results = make_uniq(result_type, partition_offsets.size()); - partition_offsets.emplace_back(count); - - // Create an aggregate state for intermediate aggregates - gstate = make_uniq(); + results = make_uniq(aggregator.result_type, partition_offsets.size()); + partition_offsets.emplace_back(group_count); // Start the first aggregate AggregateInit(); } -void WindowConstantAggregator::AggregateInit() { +WindowConstantAggregator::WindowConstantAggregator(AggregateObject aggr, const vector &arg_types, + const LogicalType &result_type, + const WindowExcludeMode exclude_mode_p) + : WindowAggregator(std::move(aggr), arg_types, result_type, exclude_mode_p) { +} + +void WindowConstantAggregatorGlobalState::AggregateInit() { + const auto &aggr = aggregator.aggr; aggr.function.initialize(state.data()); } -void WindowConstantAggregator::AggegateFinal(Vector &result, idx_t rid) { - AggregateInputData aggr_input_data(aggr.GetFunctionData(), gstate->allocator); +void WindowConstantAggregatorGlobalState::AggegateFinal(Vector &result, idx_t rid) { + const auto &aggr = aggregator.aggr; + AggregateInputData aggr_input_data(aggr.GetFunctionData(), allocator); aggr.function.finalize(statef, aggr_input_data, result, 1, rid); if (aggr.function.destructor) { @@ -113,15 +172,24 @@ void WindowConstantAggregator::AggegateFinal(Vector &result, idx_t rid) { } } -void WindowConstantAggregator::Sink(DataChunk &payload_chunk, SelectionVector *filter_sel, idx_t filtered) { +unique_ptr WindowConstantAggregator::GetGlobalState(idx_t group_count, + const ValidityMask &partition_mask) const { + return make_uniq(*this, group_count, partition_mask); +} + +void WindowConstantAggregator::Sink(WindowAggregatorState &gsink, DataChunk &payload_chunk, SelectionVector *filter_sel, + idx_t filtered) { + auto &gasink = gsink.Cast(); + + gasink.Sink(payload_chunk, filter_sel, filtered); +} + +void WindowConstantAggregatorGlobalState::Sink(DataChunk &payload_chunk, SelectionVector *filter_sel, idx_t filtered) { + const auto &aggr = aggregator.aggr; const auto chunk_begin = row; const auto chunk_end = chunk_begin + payload_chunk.size(); - if (!inputs.ColumnCount() && payload_chunk.ColumnCount()) { - inputs.Initialize(Allocator::DefaultAllocator(), payload_chunk.GetTypes()); - } - - AggregateInputData aggr_input_data(aggr.GetFunctionData(), gstate->allocator); + AggregateInputData aggr_input_data(aggr.GetFunctionData(), allocator); idx_t begin = 0; idx_t filter_idx = 0; auto partition_end = partition_offsets[partition + 1]; @@ -186,10 +254,16 @@ void WindowConstantAggregator::Sink(DataChunk &payload_chunk, SelectionVector *f } } -void WindowConstantAggregator::Finalize(const FrameStats &stats) { +void WindowConstantAggregatorGlobalState::Finalize(const FrameStats &stats) { AggegateFinal(*results, partition++); } +void WindowConstantAggregator::Finalize(WindowAggregatorState &gsink, const FrameStats &stats) { + auto &gasink = gsink.Cast(); + + gasink.Finalize(stats); +} + class WindowConstantAggregatorState : public WindowAggregatorState { public: WindowConstantAggregatorState() : partition(0) { @@ -209,8 +283,12 @@ unique_ptr WindowConstantAggregator::GetLocalState() cons return make_uniq(); } -void WindowConstantAggregator::Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &target, - idx_t count, idx_t row_idx) const { +void WindowConstantAggregator::Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, + const DataChunk &bounds, Vector &result, idx_t count, idx_t row_idx) const { + auto &gasink = gsink.Cast(); + const auto &partition_offsets = gasink.partition_offsets; + const auto &results = *gasink.results; + auto begins = FlatVector::GetData(bounds.data[WINDOW_BEGIN]); // Chunk up the constants and copy them one at a time auto &lcstate = lstate.Cast(); @@ -222,7 +300,7 @@ void WindowConstantAggregator::Evaluate(WindowAggregatorState &lstate, const Dat while (partition_offsets[lcstate.partition + 1] <= begin) { // Flush the previous partition's data if (matched) { - VectorOperations::Copy(*results, target, lcstate.matches, matched, 0, target_offset); + VectorOperations::Copy(results, result, lcstate.matches, matched, 0, target_offset); target_offset += matched; matched = 0; } @@ -234,16 +312,16 @@ void WindowConstantAggregator::Evaluate(WindowAggregatorState &lstate, const Dat // Flush the last partition if (matched) { - VectorOperations::Copy(*results, target, lcstate.matches, matched, 0, target_offset); + VectorOperations::Copy(results, result, lcstate.matches, matched, 0, target_offset); } } //===--------------------------------------------------------------------===// // WindowCustomAggregator //===--------------------------------------------------------------------===// -WindowCustomAggregator::WindowCustomAggregator(AggregateObject aggr, const LogicalType &result_type, - const WindowExcludeMode exclude_mode_p, idx_t count) - : WindowAggregator(std::move(aggr), result_type, exclude_mode_p, count) { +WindowCustomAggregator::WindowCustomAggregator(AggregateObject aggr, const vector &arg_types, + const LogicalType &result_type, const WindowExcludeMode exclude_mode) + : WindowAggregator(std::move(aggr), arg_types, result_type, exclude_mode) { } WindowCustomAggregator::~WindowCustomAggregator() { @@ -282,6 +360,20 @@ static void InitSubFrames(SubFrames &frames, const WindowExcludeMode exclude_mod frames.resize(nframes, {0, 0}); } +class WindowCustomAggregatorGlobalState : public WindowAggregatorGlobalState { +public: + explicit WindowCustomAggregatorGlobalState(const WindowCustomAggregator &aggregator, idx_t group_count) + : WindowAggregatorGlobalState(aggregator, group_count) { + + gcstate = make_uniq(aggregator.aggr, aggregator.exclude_mode); + } + + //! Data pointer that contains a single local state, used for global custom window execution state + unique_ptr gcstate; + //! Partition description for custom window APIs + unique_ptr partition_input; +}; + WindowCustomAggregatorState::WindowCustomAggregatorState(const AggregateObject &aggr, const WindowExcludeMode exclude_mode) : aggr(aggr), state(aggr.function.state_size()), statef(Value::POINTER(CastPointerToValue(state.data()))), @@ -299,17 +391,25 @@ WindowCustomAggregatorState::~WindowCustomAggregatorState() { } } -void WindowCustomAggregator::Finalize(const FrameStats &stats) { - WindowAggregator::Finalize(stats); - partition_input = +unique_ptr WindowCustomAggregator::GetGlobalState(idx_t group_count, + const ValidityMask &) const { + return make_uniq(*this, group_count); +} + +void WindowCustomAggregator::Finalize(WindowAggregatorState &gsink, const FrameStats &stats) { + WindowAggregator::Finalize(gsink, stats); + + auto &gcsink = gsink.Cast(); + auto &inputs = gcsink.inputs; + auto &filter_mask = gcsink.filter_mask; + gcsink.partition_input = make_uniq(inputs.data.data(), inputs.ColumnCount(), inputs.size(), filter_mask, stats); if (aggr.function.window_init) { - gstate = GetLocalState(); - auto &gcstate = gstate->Cast(); + auto &gcstate = *gcsink.gcstate; AggregateInputData aggr_input_data(aggr.GetFunctionData(), gcstate.allocator); - aggr.function.window_init(aggr_input_data, *partition_input, gcstate.state.data()); + aggr.function.window_init(aggr_input_data, *gcsink.partition_input, gcstate.state.data()); } } @@ -374,29 +474,30 @@ static void EvaluateSubFrames(const DataChunk &bounds, const WindowExcludeMode e } } -void WindowCustomAggregator::Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &result, - idx_t count, idx_t row_idx) const { +void WindowCustomAggregator::Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, + const DataChunk &bounds, Vector &result, idx_t count, idx_t row_idx) const { auto &lcstate = lstate.Cast(); auto &frames = lcstate.frames; const_data_ptr_t gstate_p = nullptr; - if (gstate) { - auto &gcstate = gstate->Cast(); - gstate_p = gcstate.state.data(); + auto &gcsink = gsink.Cast(); + if (gcsink.gcstate) { + gstate_p = gcsink.gcstate->state.data(); } EvaluateSubFrames(bounds, exclude_mode, count, row_idx, frames, [&](idx_t i) { // Extract the range AggregateInputData aggr_input_data(aggr.GetFunctionData(), lstate.allocator); - aggr.function.window(aggr_input_data, *partition_input, gstate_p, lcstate.state.data(), frames, result, i); + aggr.function.window(aggr_input_data, *gcsink.partition_input, gstate_p, lcstate.state.data(), frames, result, + i); }); } //===--------------------------------------------------------------------===// // WindowNaiveAggregator //===--------------------------------------------------------------------===// -WindowNaiveAggregator::WindowNaiveAggregator(AggregateObject aggr, const LogicalType &result_type, - const WindowExcludeMode exclude_mode_p, idx_t partition_count) - : WindowAggregator(std::move(aggr), result_type, exclude_mode_p, partition_count) { +WindowNaiveAggregator::WindowNaiveAggregator(AggregateObject aggr, const vector &arg_types, + const LogicalType &result_type, const WindowExcludeMode exclude_mode) + : WindowAggregator(std::move(aggr), arg_types, result_type, exclude_mode) { } WindowNaiveAggregator::~WindowNaiveAggregator() { @@ -405,44 +506,47 @@ WindowNaiveAggregator::~WindowNaiveAggregator() { class WindowNaiveState : public WindowAggregatorState { public: struct HashRow { - explicit HashRow(WindowNaiveState &state) : state(state) { + HashRow(WindowNaiveState &state, const DataChunk &inputs) : state(state), inputs(inputs) { } size_t operator()(const idx_t &i) const { - return state.Hash(i); + return state.Hash(inputs, i); } WindowNaiveState &state; + const DataChunk &inputs; }; struct EqualRow { - explicit EqualRow(WindowNaiveState &state) : state(state) { + EqualRow(WindowNaiveState &state, const DataChunk &inputs) : state(state), inputs(inputs) { } bool operator()(const idx_t &lhs, const idx_t &rhs) const { - return state.KeyEqual(lhs, rhs); + return state.KeyEqual(inputs, lhs, rhs); } WindowNaiveState &state; + const DataChunk &inputs; }; using RowSet = std::unordered_set; - explicit WindowNaiveState(const WindowNaiveAggregator &gstate); + explicit WindowNaiveState(const WindowNaiveAggregator &gsink); - void Evaluate(const DataChunk &bounds, Vector &result, idx_t count, idx_t row_idx); + void Evaluate(const WindowAggregatorGlobalState &gsink, const DataChunk &bounds, Vector &result, idx_t count, + idx_t row_idx); protected: //! Flush the accumulated intermediate states into the result states - void FlushStates(); + void FlushStates(const WindowAggregatorGlobalState &gsink); //! Hashes a value for the hash table - size_t Hash(idx_t rid); + size_t Hash(const DataChunk &inputs, idx_t rid); //! Compares two values for the hash table - bool KeyEqual(const idx_t &lhs, const idx_t &rhs); + bool KeyEqual(const DataChunk &inputs, const idx_t &lhs, const idx_t &rhs); //! The global state - const WindowNaiveAggregator &gstate; + const WindowNaiveAggregator &aggregator; //! Data pointer that contains a vector of states, used for row aggregation vector state; //! Reused result state container for the aggregate @@ -459,21 +563,12 @@ class WindowNaiveState : public WindowAggregatorState { SubFrames frames; //! The optional hash table used for DISTINCT Vector hashes; - HashRow hash_row; - EqualRow equal_row; - RowSet row_set; }; -WindowNaiveState::WindowNaiveState(const WindowNaiveAggregator &gstate) - : gstate(gstate), state(gstate.state_size * STANDARD_VECTOR_SIZE), statef(LogicalType::POINTER), - statep((LogicalType::POINTER)), flush_count(0), hashes(LogicalType::HASH), hash_row(*this), equal_row(*this), - row_set(STANDARD_VECTOR_SIZE, hash_row, equal_row) { - InitSubFrames(frames, gstate.exclude_mode); - - auto &inputs = gstate.GetInputs(); - if (inputs.ColumnCount() > 0) { - leaves.Initialize(Allocator::DefaultAllocator(), inputs.GetTypes()); - } +WindowNaiveState::WindowNaiveState(const WindowNaiveAggregator &aggregator_p) + : aggregator(aggregator_p), state(aggregator.state_size * STANDARD_VECTOR_SIZE), statef(LogicalType::POINTER), + statep((LogicalType::POINTER)), flush_count(0), hashes(LogicalType::HASH) { + InitSubFrames(frames, aggregator.exclude_mode); update_sel.Initialize(); @@ -485,28 +580,26 @@ WindowNaiveState::WindowNaiveState(const WindowNaiveAggregator &gstate) auto fdata = FlatVector::GetData(statef); for (idx_t i = 0; i < STANDARD_VECTOR_SIZE; ++i) { fdata[i] = state_ptr; - state_ptr += gstate.state_size; + state_ptr += aggregator.state_size; } } -void WindowNaiveState::FlushStates() { +void WindowNaiveState::FlushStates(const WindowAggregatorGlobalState &gsink) { if (!flush_count) { return; } - auto &inputs = gstate.GetInputs(); + auto &inputs = gsink.inputs; leaves.Slice(inputs, update_sel, flush_count); - auto &aggr = gstate.aggr; + auto &aggr = aggregator.aggr; AggregateInputData aggr_input_data(aggr.GetFunctionData(), allocator); aggr.function.update(leaves.data.data(), aggr_input_data, leaves.ColumnCount(), statep, flush_count); flush_count = 0; } -size_t WindowNaiveState::Hash(idx_t rid) { - auto &inputs = gstate.GetInputs(); - +size_t WindowNaiveState::Hash(const DataChunk &inputs, idx_t rid) { auto s = UnsafeNumericCast(rid); SelectionVector sel(&s); leaves.Slice(inputs, sel, 1); @@ -515,9 +608,7 @@ size_t WindowNaiveState::Hash(idx_t rid) { return *FlatVector::GetData(hashes); } -bool WindowNaiveState::KeyEqual(const idx_t &lhs, const idx_t &rhs) { - auto &inputs = gstate.GetInputs(); - +bool WindowNaiveState::KeyEqual(const DataChunk &inputs, const idx_t &lhs, const idx_t &rhs) { auto l = UnsafeNumericCast(lhs); SelectionVector lsel(&l); @@ -538,14 +629,24 @@ bool WindowNaiveState::KeyEqual(const idx_t &lhs, const idx_t &rhs) { return true; } -void WindowNaiveState::Evaluate(const DataChunk &bounds, Vector &result, idx_t count, idx_t row_idx) { - auto &aggr = gstate.aggr; - auto &filter_mask = gstate.GetFilterMask(); +void WindowNaiveState::Evaluate(const WindowAggregatorGlobalState &gsink, const DataChunk &bounds, Vector &result, + idx_t count, idx_t row_idx) { + auto &aggr = aggregator.aggr; + auto &filter_mask = gsink.filter_mask; + auto &inputs = gsink.inputs; + + if (leaves.ColumnCount() == 0 && inputs.ColumnCount() > 0) { + leaves.Initialize(Allocator::DefaultAllocator(), inputs.GetTypes()); + } auto fdata = FlatVector::GetData(statef); auto pdata = FlatVector::GetData(statep); - EvaluateSubFrames(bounds, gstate.exclude_mode, count, row_idx, frames, [&](idx_t rid) { + HashRow hash_row(*this, inputs); + EqualRow equal_row(*this, inputs); + RowSet row_set(STANDARD_VECTOR_SIZE, hash_row, equal_row); + + EvaluateSubFrames(bounds, aggregator.exclude_mode, count, row_idx, frames, [&](idx_t rid) { auto agg_state = fdata[rid]; aggr.function.initialize(agg_state); @@ -565,14 +666,14 @@ void WindowNaiveState::Evaluate(const DataChunk &bounds, Vector &result, idx_t c pdata[flush_count] = agg_state; update_sel[flush_count++] = UnsafeNumericCast(f); if (flush_count >= STANDARD_VECTOR_SIZE) { - FlushStates(); + FlushStates(gsink); } } } }); // Flush the final states - FlushStates(); + FlushStates(gsink); // Finalise the result aggregates and write to the result AggregateInputData aggr_input_data(aggr.GetFunctionData(), allocator); @@ -588,50 +689,76 @@ unique_ptr WindowNaiveAggregator::GetLocalState() const { return make_uniq(*this); } -void WindowNaiveAggregator::Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &result, - idx_t count, idx_t row_idx) const { - auto &ldstate = lstate.Cast(); - ldstate.Evaluate(bounds, result, count, row_idx); +void WindowNaiveAggregator::Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, + const DataChunk &bounds, Vector &result, idx_t count, idx_t row_idx) const { + const auto &gnstate = gsink.Cast(); + auto &lnstate = lstate.Cast(); + lnstate.Evaluate(gnstate, bounds, result, count, row_idx); } //===--------------------------------------------------------------------===// // WindowSegmentTree //===--------------------------------------------------------------------===// -WindowSegmentTree::WindowSegmentTree(AggregateObject aggr, const LogicalType &result_type, WindowAggregationMode mode_p, - const WindowExcludeMode exclude_mode_p, idx_t count) - : WindowAggregator(std::move(aggr), result_type, exclude_mode_p, count), internal_nodes(0), mode(mode_p) { +class WindowSegmentTreeGlobalState : public WindowAggregatorGlobalState { +public: + WindowSegmentTreeGlobalState(const WindowSegmentTree &aggregator, idx_t group_count) + : WindowAggregatorGlobalState(aggregator, group_count), tree(aggregator), internal_nodes(0) { + } + ~WindowSegmentTreeGlobalState() override; + + void ConstructTree(); + + //! The owning aggregator + const WindowSegmentTree &tree; + //! The actual window segment tree: an array of aggregate states that represent all the intermediate nodes + unsafe_unique_array levels_flat_native; + //! For each level, the starting location in the levels_flat_native array + vector levels_flat_start; + //! The total number of internal nodes of the tree, stored in levels_flat_native + idx_t internal_nodes; + + // TREE_FANOUT needs to cleanly divide STANDARD_VECTOR_SIZE + static constexpr idx_t TREE_FANOUT = 16; +}; + +WindowSegmentTree::WindowSegmentTree(AggregateObject aggr, const vector &arg_types, + const LogicalType &result_type, WindowAggregationMode mode_p, + const WindowExcludeMode exclude_mode_p) + : WindowAggregator(std::move(aggr), arg_types, result_type, exclude_mode_p), mode(mode_p) { } -void WindowSegmentTree::Finalize(const FrameStats &stats) { - WindowAggregator::Finalize(stats); +void WindowSegmentTree::Finalize(WindowAggregatorState &gsink, const FrameStats &stats) { + WindowAggregator::Finalize(gsink, stats); + + auto &gasink = gsink.Cast(); + auto &inputs = gasink.inputs; - gstate = GetLocalState(); if (inputs.ColumnCount() > 0) { if (aggr.function.combine && UseCombineAPI()) { - ConstructTree(); + gasink.ConstructTree(); } } } -WindowSegmentTree::~WindowSegmentTree() { - if (!aggr.function.destructor || !gstate) { +WindowSegmentTreeGlobalState::~WindowSegmentTreeGlobalState() { + if (!tree.aggr.function.destructor) { // nothing to destroy return; } - AggregateInputData aggr_input_data(aggr.GetFunctionData(), gstate->allocator); + AggregateInputData aggr_input_data(tree.aggr.GetFunctionData(), allocator); // call the destructor for all the intermediate states data_ptr_t address_data[STANDARD_VECTOR_SIZE]; Vector addresses(LogicalType::POINTER, data_ptr_cast(address_data)); idx_t count = 0; for (idx_t i = 0; i < internal_nodes; i++) { - address_data[count++] = data_ptr_t(levels_flat_native.get() + i * state_size); + address_data[count++] = data_ptr_t(levels_flat_native.get() + i * tree.state_size); if (count == STANDARD_VECTOR_SIZE) { - aggr.function.destructor(addresses, aggr_input_data, count); + tree.aggr.function.destructor(addresses, aggr_input_data, count); count = 0; } } if (count > 0) { - aggr.function.destructor(addresses, aggr_input_data, count); + tree.aggr.function.destructor(addresses, aggr_input_data, count); } } @@ -652,23 +779,23 @@ class WindowSegmentTreePart { void FlushStates(bool combining); void ExtractFrame(idx_t begin, idx_t end, data_ptr_t current_state); - void WindowSegmentValue(const WindowSegmentTree &tree, idx_t l_idx, idx_t begin, idx_t end, + void WindowSegmentValue(const WindowSegmentTreeGlobalState &tree, idx_t l_idx, idx_t begin, idx_t end, data_ptr_t current_state); //! Writes result and calls destructors void Finalize(Vector &result, idx_t count); void Combine(WindowSegmentTreePart &other, idx_t count); - void Evaluate(const WindowSegmentTree &tree, const idx_t *begins, const idx_t *ends, Vector &result, idx_t count, - idx_t row_idx, FramePart frame_part); + void Evaluate(const WindowSegmentTreeGlobalState &tree, const idx_t *begins, const idx_t *ends, Vector &result, + idx_t count, idx_t row_idx, FramePart frame_part); protected: //! Initialises the accumulation state vector (statef) void Initialize(idx_t count); //! Accumulate upper tree levels - void EvaluateUpperLevels(const WindowSegmentTree &tree, const idx_t *begins, const idx_t *ends, idx_t count, - idx_t row_idx, FramePart frame_part); - void EvaluateLeaves(const WindowSegmentTree &tree, const idx_t *begins, const idx_t *ends, idx_t count, + void EvaluateUpperLevels(const WindowSegmentTreeGlobalState &tree, const idx_t *begins, const idx_t *ends, + idx_t count, idx_t row_idx, FramePart frame_part); + void EvaluateLeaves(const WindowSegmentTreeGlobalState &tree, const idx_t *begins, const idx_t *ends, idx_t count, idx_t row_idx, FramePart frame_part, FramePart leaf_part); public: @@ -704,18 +831,13 @@ class WindowSegmentTreePart { class WindowSegmentTreeState : public WindowAggregatorState { public: - WindowSegmentTreeState(const AggregateObject &aggr, const DataChunk &inputs, const ValidityMask &filter_mask) - : aggr(aggr), inputs(inputs), filter_mask(filter_mask), part(allocator, aggr, inputs, filter_mask) { + WindowSegmentTreeState() { } - //! The aggregate function - const AggregateObject &aggr; - //! The aggregate function - const DataChunk &inputs; - //! The filtered rows in inputs - const ValidityMask &filter_mask; + void Evaluate(const WindowSegmentTreeGlobalState &gsink, const DataChunk &bounds, Vector &result, idx_t count, + idx_t row_idx); //! The left (default) segment tree part - WindowSegmentTreePart part; + unique_ptr part; //! The right segment tree part (for EXCLUDE) unique_ptr right_part; }; @@ -746,8 +868,13 @@ WindowSegmentTreePart::WindowSegmentTreePart(ArenaAllocator &allocator, const Ag WindowSegmentTreePart::~WindowSegmentTreePart() { } +unique_ptr WindowSegmentTree::GetGlobalState(idx_t group_count, + const ValidityMask &partition_mask) const { + return make_uniq(*this, group_count); +} + unique_ptr WindowSegmentTree::GetLocalState() const { - return make_uniq(aggr, inputs, filter_mask); + return make_uniq(); } void WindowSegmentTreePart::FlushStates(bool combining) { @@ -800,8 +927,8 @@ void WindowSegmentTreePart::ExtractFrame(idx_t begin, idx_t end, data_ptr_t stat } } -void WindowSegmentTreePart::WindowSegmentValue(const WindowSegmentTree &tree, idx_t l_idx, idx_t begin, idx_t end, - data_ptr_t state_ptr) { +void WindowSegmentTreePart::WindowSegmentValue(const WindowSegmentTreeGlobalState &tree, idx_t l_idx, idx_t begin, + idx_t end, data_ptr_t state_ptr) { D_ASSERT(begin <= end); if (begin == end || inputs.ColumnCount() == 0) { return; @@ -837,11 +964,11 @@ void WindowSegmentTreePart::Finalize(Vector &result, idx_t count) { } } -void WindowSegmentTree::ConstructTree() { +void WindowSegmentTreeGlobalState::ConstructTree() { D_ASSERT(inputs.ColumnCount() > 0); - // Use a temporary scan state to build the tree - auto >state = gstate->Cast().part; + // Single part for constructing the tree + WindowSegmentTreePart gtstate(allocator, tree.aggr, inputs, filter_mask); // compute space required to store internal nodes of segment tree internal_nodes = 0; @@ -850,7 +977,7 @@ void WindowSegmentTree::ConstructTree() { level_nodes = (level_nodes + (TREE_FANOUT - 1)) / TREE_FANOUT; internal_nodes += level_nodes; } while (level_nodes > 1); - levels_flat_native = make_unsafe_uniq_array(internal_nodes * state_size); + levels_flat_native = make_unsafe_uniq_array(internal_nodes * tree.state_size); levels_flat_start.push_back(0); idx_t levels_flat_offset = 0; @@ -862,8 +989,8 @@ void WindowSegmentTree::ConstructTree() { (level_current == 0 ? inputs.size() : levels_flat_offset - levels_flat_start[level_current - 1])) > 1) { for (idx_t pos = 0; pos < level_size; pos += TREE_FANOUT) { // compute the aggregate for this entry in the segment tree - data_ptr_t state_ptr = levels_flat_native.get() + (levels_flat_offset * state_size); - aggr.function.initialize(state_ptr); + data_ptr_t state_ptr = levels_flat_native.get() + (levels_flat_offset * tree.state_size); + gtstate.aggr.function.initialize(state_ptr); gtstate.WindowSegmentValue(*this, level_current, pos, MinValue(level_size, pos + TREE_FANOUT), state_ptr); gtstate.FlushStates(level_current > 0); @@ -876,46 +1003,52 @@ void WindowSegmentTree::ConstructTree() { // Corner case: single element in the window if (levels_flat_offset == 0) { - aggr.function.initialize(levels_flat_native.get()); + gtstate.aggr.function.initialize(levels_flat_native.get()); } } -void WindowSegmentTree::Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &result, idx_t count, - idx_t row_idx) const { - +void WindowSegmentTree::Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, + const DataChunk &bounds, Vector &result, idx_t count, idx_t row_idx) const { + const auto >state = gsink.Cast(); auto <state = lstate.Cast(); + ltstate.Evaluate(gtstate, bounds, result, count, row_idx); +} + +void WindowSegmentTreeState::Evaluate(const WindowSegmentTreeGlobalState >state, const DataChunk &bounds, + Vector &result, idx_t count, idx_t row_idx) { auto window_begin = FlatVector::GetData(bounds.data[WINDOW_BEGIN]); auto window_end = FlatVector::GetData(bounds.data[WINDOW_END]); auto peer_begin = FlatVector::GetData(bounds.data[PEER_BEGIN]); auto peer_end = FlatVector::GetData(bounds.data[PEER_END]); - auto &part = ltstate.part; - if (exclude_mode != WindowExcludeMode::NO_OTHER) { + if (!part) { + part = + make_uniq(allocator, gtstate.aggregator.aggr, gtstate.inputs, gtstate.filter_mask); + } + + if (gtstate.aggregator.exclude_mode != WindowExcludeMode::NO_OTHER) { // 1. evaluate the tree left of the excluded part - part.Evaluate(*this, window_begin, peer_begin, result, count, row_idx, WindowSegmentTreePart::LEFT); + part->Evaluate(gtstate, window_begin, peer_begin, result, count, row_idx, WindowSegmentTreePart::LEFT); // 2. set up a second state for the right of the excluded part - if (!ltstate.right_part) { - ltstate.right_part = part.Copy(); + if (!right_part) { + right_part = part->Copy(); } - auto &right_part = *ltstate.right_part; // 3. evaluate the tree right of the excluded part - right_part.Evaluate(*this, peer_end, window_end, result, count, row_idx, WindowSegmentTreePart::RIGHT); + right_part->Evaluate(gtstate, peer_end, window_end, result, count, row_idx, WindowSegmentTreePart::RIGHT); // 4. combine the buffer state into the Segment Tree State - part.Combine(right_part, count); + part->Combine(*right_part, count); } else { - part.Evaluate(*this, window_begin, window_end, result, count, row_idx, WindowSegmentTreePart::FULL); + part->Evaluate(gtstate, window_begin, window_end, result, count, row_idx, WindowSegmentTreePart::FULL); } - part.Finalize(result, count); + part->Finalize(result, count); } -void WindowSegmentTreePart::Evaluate(const WindowSegmentTree &tree, const idx_t *begins, const idx_t *ends, +void WindowSegmentTreePart::Evaluate(const WindowSegmentTreeGlobalState &tree, const idx_t *begins, const idx_t *ends, Vector &result, idx_t count, idx_t row_idx, FramePart frame_part) { - D_ASSERT(aggr.function.combine && tree.UseCombineAPI()); - Initialize(count); if (order_insensitive) { @@ -940,11 +1073,11 @@ void WindowSegmentTreePart::Initialize(idx_t count) { } } -void WindowSegmentTreePart::EvaluateUpperLevels(const WindowSegmentTree &tree, const idx_t *begins, const idx_t *ends, - idx_t count, idx_t row_idx, FramePart frame_part) { +void WindowSegmentTreePart::EvaluateUpperLevels(const WindowSegmentTreeGlobalState &tree, const idx_t *begins, + const idx_t *ends, idx_t count, idx_t row_idx, FramePart frame_part) { auto fdata = FlatVector::GetData(statef); - const auto exclude_mode = tree.exclude_mode; + const auto exclude_mode = tree.tree.exclude_mode; const bool begin_on_curr_row = frame_part == FramePart::RIGHT && exclude_mode == WindowExcludeMode::CURRENT_ROW; const bool end_on_curr_row = frame_part == FramePart::LEFT && exclude_mode == WindowExcludeMode::CURRENT_ROW; @@ -1034,8 +1167,9 @@ void WindowSegmentTreePart::EvaluateUpperLevels(const WindowSegmentTree &tree, c FlushStates(true); } -void WindowSegmentTreePart::EvaluateLeaves(const WindowSegmentTree &tree, const idx_t *begins, const idx_t *ends, - idx_t count, idx_t row_idx, FramePart frame_part, FramePart leaf_part) { +void WindowSegmentTreePart::EvaluateLeaves(const WindowSegmentTreeGlobalState &tree, const idx_t *begins, + const idx_t *ends, idx_t count, idx_t row_idx, FramePart frame_part, + FramePart leaf_part) { auto fdata = FlatVector::GetData(statef); @@ -1044,7 +1178,7 @@ void WindowSegmentTreePart::EvaluateLeaves(const WindowSegmentTree &tree, const // The current row is the leftmost value of the right hand side. const bool compute_left = leaf_part != FramePart::RIGHT; const bool compute_right = leaf_part != FramePart::LEFT; - const auto exclude_mode = tree.exclude_mode; + const auto exclude_mode = tree.tree.exclude_mode; const bool begin_on_curr_row = frame_part == FramePart::RIGHT && exclude_mode == WindowExcludeMode::CURRENT_ROW; const bool end_on_curr_row = frame_part == FramePart::LEFT && exclude_mode == WindowExcludeMode::CURRENT_ROW; // with EXCLUDE TIES, in addition to the frame part right of the peer group's end, we also need to consider the @@ -1087,17 +1221,55 @@ void WindowSegmentTreePart::EvaluateLeaves(const WindowSegmentTree &tree, const //===--------------------------------------------------------------------===// // WindowDistinctAggregator //===--------------------------------------------------------------------===// -WindowDistinctAggregator::WindowDistinctAggregator(AggregateObject aggr, const LogicalType &result_type, - const WindowExcludeMode exclude_mode_p, idx_t count, - ClientContext &context) - : WindowAggregator(std::move(aggr), result_type, exclude_mode_p, count), context(context), - allocator(Allocator::DefaultAllocator()) { +WindowDistinctAggregator::WindowDistinctAggregator(AggregateObject aggr, const vector &arg_types, + const LogicalType &result_type, + const WindowExcludeMode exclude_mode_p, ClientContext &context) + : WindowAggregator(std::move(aggr), arg_types, result_type, exclude_mode_p), context(context) { +} + +class WindowDistinctAggregatorGlobalState : public WindowAggregatorGlobalState { +public: + using GlobalSortStatePtr = unique_ptr; + class DistinctSortTree; + + WindowDistinctAggregatorGlobalState(const WindowDistinctAggregator &aggregator, idx_t group_count); + ~WindowDistinctAggregatorGlobalState() override; + + void Sink(DataChunk &arg_chunk, SelectionVector *filter_sel, idx_t filtered); + void Finalize(const FrameStats &stats); + + // Single threaded sorting for now + ClientContext &context; + GlobalSortStatePtr global_sort; + LocalSortState local_sort; + idx_t payload_pos; + idx_t memory_per_thread; + + vector payload_types; + DataChunk sort_chunk; + DataChunk payload_chunk; + + //! The merge sort tree for the aggregate. + unique_ptr merge_sort_tree; + //! The actual window segment tree: an array of aggregate states that represent all the intermediate nodes + unsafe_unique_array levels_flat_native; + //! For each level, the starting location in the levels_flat_native array + vector levels_flat_start; + + //! The total number of internal nodes of the tree, stored in levels_flat_native + idx_t internal_nodes; +}; + +WindowDistinctAggregatorGlobalState::WindowDistinctAggregatorGlobalState(const WindowDistinctAggregator &aggregator_p, + idx_t group_count) + : WindowAggregatorGlobalState(aggregator_p, group_count), context(aggregator_p.context) { payload_types.emplace_back(LogicalType::UBIGINT); payload_chunk.Initialize(Allocator::DefaultAllocator(), payload_types); } -WindowDistinctAggregator::~WindowDistinctAggregator() { +WindowDistinctAggregatorGlobalState::~WindowDistinctAggregatorGlobalState() { + const auto &aggr = aggregator.aggr; if (!aggr.function.destructor) { // nothing to destroy return; @@ -1108,7 +1280,7 @@ WindowDistinctAggregator::~WindowDistinctAggregator() { Vector addresses(LogicalType::POINTER, data_ptr_cast(address_data)); idx_t count = 0; for (idx_t i = 0; i < internal_nodes; i++) { - address_data[count++] = data_ptr_t(levels_flat_native.get() + i * state_size); + address_data[count++] = data_ptr_t(levels_flat_native.get() + i * aggregator.state_size); if (count == STANDARD_VECTOR_SIZE) { aggr.function.destructor(addresses, aggr_input_data, count); count = 0; @@ -1119,9 +1291,20 @@ WindowDistinctAggregator::~WindowDistinctAggregator() { } } -void WindowDistinctAggregator::Sink(DataChunk &arg_chunk, SelectionVector *filter_sel, idx_t filtered) { - WindowAggregator::Sink(arg_chunk, filter_sel, filtered); +unique_ptr WindowDistinctAggregator::GetGlobalState(idx_t group_count, + const ValidityMask &partition_mask) const { + return make_uniq(*this, group_count); +} + +void WindowDistinctAggregator::Sink(WindowAggregatorState &gsink, DataChunk &arg_chunk, SelectionVector *filter_sel, + idx_t filtered) { + WindowAggregator::Sink(gsink, arg_chunk, filter_sel, filtered); + + auto &gdstate = gsink.Cast(); + gdstate.Sink(arg_chunk, filter_sel, filtered); +} +void WindowDistinctAggregatorGlobalState::Sink(DataChunk &arg_chunk, SelectionVector *filter_sel, idx_t filtered) { // We sort the arguments and use the partition index as a tie-breaker. // TODO: Use a hash table? if (!global_sort) { @@ -1157,13 +1340,16 @@ void WindowDistinctAggregator::Sink(DataChunk &arg_chunk, SelectionVector *filte // 3: for i ← 0 to in.size do // 4: sorted[i] ← (in[i], i) const auto count = arg_chunk.size(); - auto payload_data = FlatVector::GetData(payload_chunk.data[0]); - std::iota(payload_data, payload_data + count, payload_pos); + payload_chunk.Reset(); + auto &sorted_vec = payload_chunk.data[0]; + auto sorted = FlatVector::GetData(sorted_vec); + std::iota(sorted, sorted + count, payload_pos); payload_pos += count; for (column_t c = 0; c < arg_chunk.ColumnCount(); ++c) { sort_chunk.data[c].Reference(arg_chunk.data[c]); } + sort_chunk.data.back().Reference(sorted_vec); sort_chunk.SetCardinality(arg_chunk); payload_chunk.SetCardinality(sort_chunk); @@ -1180,16 +1366,21 @@ void WindowDistinctAggregator::Sink(DataChunk &arg_chunk, SelectionVector *filte } } -class WindowDistinctAggregator::DistinctSortTree : public MergeSortTree { +void WindowDistinctAggregator::Finalize(WindowAggregatorState &gsink, const FrameStats &stats) { + auto &gdsink = gsink.Cast(); + gdsink.Finalize(stats); +} + +class WindowDistinctAggregatorGlobalState::DistinctSortTree : public MergeSortTree { public: // prev_idx, input_idx using ZippedTuple = std::tuple; using ZippedElements = vector; - DistinctSortTree(ZippedElements &&prev_idcs, WindowDistinctAggregator &wda); + DistinctSortTree(ZippedElements &&prev_idcs, WindowDistinctAggregatorGlobalState &gdsink); }; -void WindowDistinctAggregator::Finalize(const FrameStats &stats) { +void WindowDistinctAggregatorGlobalState::Finalize(const FrameStats &stats) { // 5: Sort sorted lexicographically increasing global_sort->AddLocalState(local_sort); global_sort->PrepareMergePhase(); @@ -1267,19 +1458,19 @@ void WindowDistinctAggregator::Finalize(const FrameStats &stats) { merge_sort_tree = make_uniq(std::move(prev_idcs), *this); } -WindowDistinctAggregator::DistinctSortTree::DistinctSortTree(ZippedElements &&prev_idcs, - WindowDistinctAggregator &wda) { - auto &inputs = wda.inputs; - auto &aggr = wda.aggr; - auto &allocator = wda.allocator; - const auto state_size = wda.state_size; - auto &internal_nodes = wda.internal_nodes; - auto &levels_flat_native = wda.levels_flat_native; - auto &levels_flat_start = wda.levels_flat_start; +WindowDistinctAggregatorGlobalState::DistinctSortTree::DistinctSortTree(ZippedElements &&prev_idcs, + WindowDistinctAggregatorGlobalState &gdsink) { + auto &aggr = gdsink.aggregator.aggr; + auto &allocator = gdsink.allocator; + auto &inputs = gdsink.inputs; + const auto state_size = gdsink.aggregator.state_size; + auto &internal_nodes = gdsink.internal_nodes; + auto &levels_flat_native = gdsink.levels_flat_native; + auto &levels_flat_start = gdsink.levels_flat_start; //! Input data chunk, used for leaf segment aggregation DataChunk leaves; - leaves.Initialize(Allocator::DefaultAllocator(), inputs.GetTypes()); + leaves.Initialize(Allocator::DefaultAllocator(), gdsink.inputs.GetTypes()); SelectionVector sel; sel.Initialize(); @@ -1379,20 +1570,17 @@ WindowDistinctAggregator::DistinctSortTree::DistinctSortTree(ZippedElements &&pr class WindowDistinctState : public WindowAggregatorState { public: - WindowDistinctState(const AggregateObject &aggr, const DataChunk &inputs, const WindowDistinctAggregator &tree); + explicit WindowDistinctState(const WindowDistinctAggregator &aggregator); - void Evaluate(const DataChunk &bounds, Vector &result, idx_t count, idx_t row_idx); + void Evaluate(const WindowDistinctAggregatorGlobalState &gdstate, const DataChunk &bounds, Vector &result, + idx_t count, idx_t row_idx); protected: //! Flush the accumulated intermediate states into the result states void FlushStates(); - //! The aggregate function - const AggregateObject &aggr; - //! The aggregate function - const DataChunk &inputs; - //! The merge sort tree data - const WindowDistinctAggregator &tree; + //! The aggregator we are working with + const WindowDistinctAggregator &aggregator; //! The size of a single aggregate state const idx_t state_size; //! Data pointer that contains a vector of states, used for row aggregation @@ -1409,12 +1597,10 @@ class WindowDistinctState : public WindowAggregatorState { SubFrames frames; }; -WindowDistinctState::WindowDistinctState(const AggregateObject &aggr, const DataChunk &inputs, - const WindowDistinctAggregator &tree) - : aggr(aggr), inputs(inputs), tree(tree), state_size(aggr.function.state_size()), - state((state_size * STANDARD_VECTOR_SIZE)), statef(LogicalType::POINTER), statep(LogicalType::POINTER), - statel(LogicalType::POINTER), flush_count(0) { - InitSubFrames(frames, tree.exclude_mode); +WindowDistinctState::WindowDistinctState(const WindowDistinctAggregator &aggregator) + : aggregator(aggregator), state_size(aggregator.state_size), state((aggregator.state_size * STANDARD_VECTOR_SIZE)), + statef(LogicalType::POINTER), statep(LogicalType::POINTER), statel(LogicalType::POINTER), flush_count(0) { + InitSubFrames(frames, aggregator.exclude_mode); // Build the finalise vector that just points to the result states data_ptr_t state_ptr = state.data(); @@ -1433,6 +1619,7 @@ void WindowDistinctState::FlushStates() { return; } + const auto &aggr = aggregator.aggr; AggregateInputData aggr_input_data(aggr.GetFunctionData(), allocator); statel.Verify(flush_count); aggr.function.combine(statel, statep, aggr_input_data, flush_count); @@ -1440,15 +1627,18 @@ void WindowDistinctState::FlushStates() { flush_count = 0; } -void WindowDistinctState::Evaluate(const DataChunk &bounds, Vector &result, idx_t count, idx_t row_idx) { +void WindowDistinctState::Evaluate(const WindowDistinctAggregatorGlobalState &gdstate, const DataChunk &bounds, + Vector &result, idx_t count, idx_t row_idx) { auto fdata = FlatVector::GetData(statef); auto ldata = FlatVector::GetData(statel); auto pdata = FlatVector::GetData(statep); - const auto &merge_sort_tree = *tree.merge_sort_tree; - const auto running_aggs = tree.levels_flat_native.get(); + const auto &merge_sort_tree = *gdstate.merge_sort_tree; + const auto running_aggs = gdstate.levels_flat_native.get(); + const auto exclude_mode = gdstate.aggregator.exclude_mode; + const auto &aggr = gdstate.aggregator.aggr; - EvaluateSubFrames(bounds, tree.exclude_mode, count, row_idx, frames, [&](idx_t rid) { + EvaluateSubFrames(bounds, exclude_mode, count, row_idx, frames, [&](idx_t rid) { auto agg_state = fdata[rid]; aggr.function.initialize(agg_state); @@ -1460,7 +1650,7 @@ void WindowDistinctState::Evaluate(const DataChunk &bounds, Vector &result, idx_ if (run_pos != run_begin) { // Find the source aggregate // Buffer a merge of the indicated state into the current state - const auto agg_idx = tree.levels_flat_start[level] + run_pos - 1; + const auto agg_idx = gdstate.levels_flat_start[level] + run_pos - 1; const auto running_agg = running_aggs + agg_idx * state_size; pdata[flush_count] = agg_state; ldata[flush_count++] = running_agg; @@ -1485,13 +1675,15 @@ void WindowDistinctState::Evaluate(const DataChunk &bounds, Vector &result, idx_ } unique_ptr WindowDistinctAggregator::GetLocalState() const { - return make_uniq(aggr, inputs, *this); + return make_uniq(*this); } -void WindowDistinctAggregator::Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &result, - idx_t count, idx_t row_idx) const { +void WindowDistinctAggregator::Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, + const DataChunk &bounds, Vector &result, idx_t count, idx_t row_idx) const { + + const auto &gdstate = gsink.Cast(); auto &ldstate = lstate.Cast(); - ldstate.Evaluate(bounds, result, count, row_idx); + ldstate.Evaluate(gdstate, bounds, result, count, row_idx); } } // namespace duckdb diff --git a/src/function/CMakeLists.txt b/src/function/CMakeLists.txt index 15188f77572..b2529c8d8ca 100644 --- a/src/function/CMakeLists.txt +++ b/src/function/CMakeLists.txt @@ -10,6 +10,7 @@ add_library_unity( built_in_functions.cpp cast_rules.cpp compression_config.cpp + copy_function.cpp function.cpp function_binder.cpp function_set.cpp diff --git a/src/function/aggregate/distributive/first.cpp b/src/function/aggregate/distributive/first.cpp index 143cf431757..6c4e62d4bb3 100644 --- a/src/function/aggregate/distributive/first.cpp +++ b/src/function/aggregate/distributive/first.cpp @@ -1,5 +1,6 @@ #include "duckdb/common/exception.hpp" #include "duckdb/common/vector_operations/vector_operations.hpp" +#include "duckdb/core_functions/create_sort_key.hpp" #include "duckdb/function/aggregate/distributive_functions.hpp" #include "duckdb/planner/expression.hpp" @@ -66,7 +67,7 @@ struct FirstFunction : public FirstFunctionBase { }; template -struct FirstFunctionString : public FirstFunctionBase { +struct FirstFunctionStringBase : public FirstFunctionBase { template static void SetValue(STATE &state, AggregateInputData &input_data, string_t value, bool is_null) { if (LAST && state.is_set) { @@ -93,10 +94,28 @@ struct FirstFunctionString : public FirstFunctionBase { } } + template + static void Combine(const STATE &source, STATE &target, AggregateInputData &input_data) { + if (source.is_set && (LAST || !target.is_set)) { + SetValue(target, input_data, source.value, source.is_null); + } + } + + template + static void Destroy(STATE &state, AggregateInputData &) { + if (state.is_set && !state.is_null && !state.value.IsInlined()) { + delete[] state.value.GetData(); + } + } +}; + +template +struct FirstFunctionString : FirstFunctionStringBase { template static void Operation(STATE &state, const INPUT_TYPE &input, AggregateUnaryInput &unary_input) { if (LAST || !state.is_set) { - SetValue(state, unary_input.input, input, !unary_input.RowIsValid()); + FirstFunctionStringBase::template SetValue(state, unary_input.input, input, + !unary_input.RowIsValid()); } } @@ -106,13 +125,6 @@ struct FirstFunctionString : public FirstFunctionBase { Operation(state, input, unary_input); } - template - static void Combine(const STATE &source, STATE &target, AggregateInputData &input_data) { - if (source.is_set && (LAST || !target.is_set)) { - SetValue(target, input_data, source.value, source.is_null); - } - } - template static void Finalize(STATE &state, T &target, AggregateFinalizeData &finalize_data) { if (!state.is_set || state.is_null) { @@ -121,48 +133,14 @@ struct FirstFunctionString : public FirstFunctionBase { target = StringVector::AddStringOrBlob(finalize_data.result, state.value); } } - - template - static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { - if (state.is_set && !state.is_null && !state.value.IsInlined()) { - delete[] state.value.GetData(); - } - } -}; - -struct FirstStateVector { - Vector *value; }; template -struct FirstVectorFunction { - template - static void Initialize(STATE &state) { - state.value = nullptr; - } +struct FirstVectorFunction : FirstFunctionStringBase { + using STATE = FirstState; - template - static void Destroy(STATE &state, AggregateInputData &aggr_input_data) { - if (state.value) { - delete state.value; - } - } - static bool IgnoreNull() { - return SKIP_NULLS; - } - - template - static void SetValue(STATE &state, Vector &input, const idx_t idx) { - if (!state.value) { - state.value = new Vector(input.GetType()); - state.value->SetVectorType(VectorType::CONSTANT_VECTOR); - } - sel_t selv = UnsafeNumericCast(idx); - SelectionVector sel(&selv); - VectorOperations::Copy(input, *state.value, sel, 1, 0, 0); - } - - static void Update(Vector inputs[], AggregateInputData &, idx_t input_count, Vector &state_vector, idx_t count) { + static void Update(Vector inputs[], AggregateInputData &input_data, idx_t input_count, Vector &state_vector, + idx_t count) { auto &input = inputs[0]; UnifiedVectorFormat idata; input.ToUnifiedFormat(count, idata); @@ -170,32 +148,59 @@ struct FirstVectorFunction { UnifiedVectorFormat sdata; state_vector.ToUnifiedFormat(count, sdata); - auto states = UnifiedVectorFormat::GetData(sdata); + sel_t assign_sel[STANDARD_VECTOR_SIZE]; + idx_t assign_count = 0; + + auto states = UnifiedVectorFormat::GetData(sdata); for (idx_t i = 0; i < count; i++) { const auto idx = idata.sel->get_index(i); - if (SKIP_NULLS && !idata.validity.RowIsValid(idx)) { + bool is_null = !idata.validity.RowIsValid(idx); + if (SKIP_NULLS && is_null) { continue; } auto &state = *states[sdata.sel->get_index(i)]; - if (LAST || !state.value) { - SetValue(state, input, i); + if (!LAST && state.is_set) { + continue; } + assign_sel[assign_count++] = NumericCast(i); + } + if (assign_count == 0) { + // fast path - nothing to set + return; } - } - template - static void Combine(const STATE &source, STATE &target, AggregateInputData &) { - if (source.value && (LAST || !target.value)) { - SetValue(target, *source.value, 0); + Vector sort_key(LogicalType::BLOB); + OrderModifiers modifiers(OrderType::ASCENDING, OrderByNullType::NULLS_LAST); + // slice with a selection vector and generate sort keys + if (assign_count == input_count) { + CreateSortKeyHelpers::CreateSortKey(input, input_count, modifiers, sort_key); + } else { + SelectionVector sel(assign_sel); + Vector sliced_input(input, sel, assign_count); + CreateSortKeyHelpers::CreateSortKey(sliced_input, assign_count, modifiers, sort_key); + } + auto sort_key_data = FlatVector::GetData(sort_key); + + // now assign sort keys + for (idx_t i = 0; i < assign_count; i++) { + const auto sidx = sdata.sel->get_index(assign_sel[i]); + bool is_null = !idata.validity.RowIsValid(assign_sel[i]); + auto &state = *states[sidx]; + if (!LAST && state.is_set) { + continue; + } + FirstFunctionStringBase::template SetValue(state, input_data, sort_key_data[i], + is_null); } } template static void Finalize(STATE &state, AggregateFinalizeData &finalize_data) { - if (!state.value) { + if (!state.is_set || state.is_null) { finalize_data.ReturnNull(); } else { - VectorOperations::Copy(*state.value, finalize_data.result, 1, 0, finalize_data.result_idx); + CreateSortKeyHelpers::DecodeSortKey(state.value, finalize_data.result, finalize_data.result_idx, + OrderModifiers(OrderType::ASCENDING, OrderByNullType::NULLS_LAST)); } } @@ -229,45 +234,44 @@ AggregateFunction GetDecimalFirstFunction(const LogicalType &type) { return GetFirstFunction(LogicalType::HUGEINT); } } - template static AggregateFunction GetFirstFunction(const LogicalType &type) { - switch (type.id()) { - case LogicalTypeId::BOOLEAN: - return GetFirstAggregateTemplated(type); - case LogicalTypeId::TINYINT: + if (type.id() == LogicalTypeId::DECIMAL) { + type.Verify(); + AggregateFunction function = GetDecimalFirstFunction(type); + function.arguments[0] = type; + function.return_type = type; + return function; + } + switch (type.InternalType()) { + case PhysicalType::BOOL: + case PhysicalType::INT8: return GetFirstAggregateTemplated(type); - case LogicalTypeId::SMALLINT: + case PhysicalType::INT16: return GetFirstAggregateTemplated(type); - case LogicalTypeId::INTEGER: - case LogicalTypeId::DATE: + case PhysicalType::INT32: return GetFirstAggregateTemplated(type); - case LogicalTypeId::BIGINT: - case LogicalTypeId::TIME: - case LogicalTypeId::TIMESTAMP: - case LogicalTypeId::TIME_TZ: - case LogicalTypeId::TIMESTAMP_TZ: + case PhysicalType::INT64: return GetFirstAggregateTemplated(type); - case LogicalTypeId::UTINYINT: + case PhysicalType::UINT8: return GetFirstAggregateTemplated(type); - case LogicalTypeId::USMALLINT: + case PhysicalType::UINT16: return GetFirstAggregateTemplated(type); - case LogicalTypeId::UINTEGER: + case PhysicalType::UINT32: return GetFirstAggregateTemplated(type); - case LogicalTypeId::UBIGINT: + case PhysicalType::UINT64: return GetFirstAggregateTemplated(type); - case LogicalTypeId::HUGEINT: + case PhysicalType::INT128: return GetFirstAggregateTemplated(type); - case LogicalTypeId::UHUGEINT: + case PhysicalType::UINT128: return GetFirstAggregateTemplated(type); - case LogicalTypeId::FLOAT: + case PhysicalType::FLOAT: return GetFirstAggregateTemplated(type); - case LogicalTypeId::DOUBLE: + case PhysicalType::DOUBLE: return GetFirstAggregateTemplated(type); - case LogicalTypeId::INTERVAL: + case PhysicalType::INTERVAL: return GetFirstAggregateTemplated(type); - case LogicalTypeId::VARCHAR: - case LogicalTypeId::BLOB: + case PhysicalType::VARCHAR: if (LAST) { return AggregateFunction::UnaryAggregateDestructor, string_t, string_t, FirstFunctionString>(type, type); @@ -275,21 +279,13 @@ static AggregateFunction GetFirstFunction(const LogicalType &type) { return AggregateFunction::UnaryAggregate, string_t, string_t, FirstFunctionString>(type, type); } - case LogicalTypeId::DECIMAL: { - type.Verify(); - AggregateFunction function = GetDecimalFirstFunction(type); - function.arguments[0] = type; - function.return_type = type; - // TODO set_key here? - return function; - } default: { using OP = FirstVectorFunction; - return AggregateFunction({type}, type, AggregateFunction::StateSize, - AggregateFunction::StateInitialize, OP::Update, - AggregateFunction::StateCombine, - AggregateFunction::StateVoidFinalize, nullptr, OP::Bind, - AggregateFunction::StateDestroy, nullptr, nullptr); + using STATE = FirstState; + return AggregateFunction( + {type}, type, AggregateFunction::StateSize, AggregateFunction::StateInitialize, + OP::Update, AggregateFunction::StateCombine, AggregateFunction::StateVoidFinalize, + nullptr, OP::Bind, LAST ? AggregateFunction::StateDestroy : nullptr, nullptr, nullptr); } } } diff --git a/src/function/cast/cast_function_set.cpp b/src/function/cast/cast_function_set.cpp index 5e30e4c3ba1..48b8bef77ab 100644 --- a/src/function/cast/cast_function_set.cpp +++ b/src/function/cast/cast_function_set.cpp @@ -3,6 +3,7 @@ #include "duckdb/common/pair.hpp" #include "duckdb/common/types/type_map.hpp" #include "duckdb/function/cast_rules.hpp" +#include "duckdb/planner/collation_binding.hpp" #include "duckdb/main/config.hpp" namespace duckdb { @@ -34,10 +35,18 @@ CastFunctionSet &CastFunctionSet::Get(ClientContext &context) { return DBConfig::GetConfig(context).GetCastFunctions(); } +CollationBinding &CollationBinding::Get(ClientContext &context) { + return DBConfig::GetConfig(context).GetCollationBinding(); +} + CastFunctionSet &CastFunctionSet::Get(DatabaseInstance &db) { return DBConfig::GetConfig(db).GetCastFunctions(); } +CollationBinding &CollationBinding::Get(DatabaseInstance &db) { + return DBConfig::GetConfig(db).GetCollationBinding(); +} + BoundCastInfo CastFunctionSet::GetCastFunction(const LogicalType &source, const LogicalType &target, GetCastFunctionInput &get_input) { if (source == target) { @@ -97,7 +106,7 @@ static auto RelaxedTypeMatch(type_map_t &map, const LogicalType case LogicalTypeId::UNION: return map.find(LogicalType::UNION({{"any", LogicalType::ANY}})); case LogicalTypeId::ARRAY: - return map.find(LogicalType::ARRAY(LogicalType::ANY)); + return map.find(LogicalType::ARRAY(LogicalType::ANY, optional_idx())); default: return map.find(LogicalType::ANY); } diff --git a/src/function/cast/decimal_cast.cpp b/src/function/cast/decimal_cast.cpp index 3af81e0f0b1..d1bc6e771a9 100644 --- a/src/function/cast/decimal_cast.cpp +++ b/src/function/cast/decimal_cast.cpp @@ -100,8 +100,17 @@ bool TemplatedDecimalScaleUp(Vector &source, Vector &result, idx_t count, CastPa struct DecimalScaleDownOperator { template static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) { + // We need to round here, not truncate. auto data = (DecimalScaleInput *)dataptr; - return Cast::Operation(input / data->factor); + // Scale first so we don't overflow when rounding. + const auto scaling = data->factor / 2; + input /= scaling; + if (input < 0) { + input -= 1; + } else { + input += 1; + } + return Cast::Operation(input / 2); } }; diff --git a/src/function/cast/string_cast.cpp b/src/function/cast/string_cast.cpp index d18c6ce1907..5c0e5d6ed74 100644 --- a/src/function/cast/string_cast.cpp +++ b/src/function/cast/string_cast.cpp @@ -161,7 +161,7 @@ bool VectorStringToList::StringToNestedTypeCastLoop(const string_t *source_data, if (!VectorStringToList::SplitStringList(source_data[idx], child_data, total, varchar_vector)) { string text = "Type VARCHAR with value '" + source_data[idx].GetString() + "' can't be cast to the destination type LIST"; - HandleVectorCastError::Operation(text, result_mask, idx, vector_cast_data); + HandleVectorCastError::Operation(text, result_mask, i, vector_cast_data); } list_data[i].length = total - list_data[i].offset; // length is the amount of parts coming from this string } @@ -412,7 +412,7 @@ bool VectorStringToArray::StringToNestedTypeCastLoop(const string_t *source_data // Null the entire array for (idx_t j = 0; j < array_size; j++) { - FlatVector::SetNull(varchar_vector, idx * array_size + j, true); + FlatVector::SetNull(varchar_vector, i * array_size + j, true); } total += array_size; @@ -422,7 +422,7 @@ bool VectorStringToArray::StringToNestedTypeCastLoop(const string_t *source_data if (!VectorStringToList::SplitStringList(source_data[idx], child_data, total, varchar_vector)) { auto text = StringUtil::Format("Type VARCHAR with value '%s' can't be cast to the destination type ARRAY", source_data[idx].GetString()); - HandleVectorCastError::Operation(text, result_mask, idx, vector_cast_data); + HandleVectorCastError::Operation(text, result_mask, i, vector_cast_data); } } D_ASSERT(total == child_count); @@ -477,7 +477,7 @@ BoundCastInfo DefaultCasts::StringCastSwitch(BindCastInput &input, const Logical return BoundCastInfo(&VectorCastHelpers::TryCastErrorLoop); case LogicalTypeId::TIMESTAMP_NS: return BoundCastInfo( - &VectorCastHelpers::TryCastStrictLoop); + &VectorCastHelpers::TryCastStrictLoop); case LogicalTypeId::TIMESTAMP_SEC: return BoundCastInfo( &VectorCastHelpers::TryCastStrictLoop); @@ -502,10 +502,10 @@ BoundCastInfo DefaultCasts::StringCastSwitch(BindCastInput &input, const Logical ListBoundCastData::InitListLocalState); case LogicalTypeId::ARRAY: // the second argument allows for a secondary casting function to be passed in the CastParameters - return BoundCastInfo( - &StringToNestedTypeCast, - ArrayBoundCastData::BindArrayToArrayCast(input, LogicalType::ARRAY(LogicalType::VARCHAR), target), - ArrayBoundCastData::InitArrayLocalState); + return BoundCastInfo(&StringToNestedTypeCast, + ArrayBoundCastData::BindArrayToArrayCast( + input, LogicalType::ARRAY(LogicalType::VARCHAR, optional_idx()), target), + ArrayBoundCastData::InitArrayLocalState); case LogicalTypeId::STRUCT: return BoundCastInfo(&StringToNestedTypeCast, StructBoundCastData::BindStructToStructCast(input, InitVarcharStructType(target), target), diff --git a/src/function/cast/time_casts.cpp b/src/function/cast/time_casts.cpp index 4ac38d121d7..b9587ad1ce3 100644 --- a/src/function/cast/time_casts.cpp +++ b/src/function/cast/time_casts.cpp @@ -14,7 +14,7 @@ BoundCastInfo DefaultCasts::DateCastSwitch(BindCastInput &input, const LogicalTy // date to timestamp return BoundCastInfo(&VectorCastHelpers::TryCastLoop); case LogicalTypeId::TIMESTAMP_NS: - return BoundCastInfo(&VectorCastHelpers::TryCastLoop); + return BoundCastInfo(&VectorCastHelpers::TryCastLoop); case LogicalTypeId::TIMESTAMP_SEC: return BoundCastInfo(&VectorCastHelpers::TryCastLoop); case LogicalTypeId::TIMESTAMP_MS: @@ -113,7 +113,7 @@ BoundCastInfo DefaultCasts::TimestampNsCastSwitch(BindCastInput &input, const Lo switch (target.id()) { case LogicalTypeId::VARCHAR: // timestamp (ns) to varchar - return BoundCastInfo(&VectorCastHelpers::StringCast); + return BoundCastInfo(&VectorCastHelpers::StringCast); case LogicalTypeId::DATE: // timestamp (ns) to date return BoundCastInfo(&VectorCastHelpers::TemplatedCastLoop); diff --git a/src/function/cast_rules.cpp b/src/function/cast_rules.cpp index 98ca78b8665..f6537e235e1 100644 --- a/src/function/cast_rules.cpp +++ b/src/function/cast_rules.cpp @@ -211,6 +211,10 @@ static int64_t ImplicitCastUhugeint(const LogicalType &to) { static int64_t ImplicitCastDate(const LogicalType &to) { switch (to.id()) { case LogicalTypeId::TIMESTAMP: + case LogicalTypeId::TIMESTAMP_TZ: + case LogicalTypeId::TIMESTAMP_MS: + case LogicalTypeId::TIMESTAMP_NS: + case LogicalTypeId::TIMESTAMP_SEC: return TargetTypeCost(to); default: return -1; diff --git a/src/function/compression_config.cpp b/src/function/compression_config.cpp index 62ba1ce6ada..5388f842f4b 100644 --- a/src/function/compression_config.cpp +++ b/src/function/compression_config.cpp @@ -1,12 +1,12 @@ -#include "duckdb/main/config.hpp" -#include "duckdb/function/compression_function.hpp" -#include "duckdb/function/compression/compression.hpp" #include "duckdb/common/pair.hpp" +#include "duckdb/function/compression/compression.hpp" +#include "duckdb/function/compression_function.hpp" +#include "duckdb/main/config.hpp" namespace duckdb { typedef CompressionFunction (*get_compression_function_t)(PhysicalType type); -typedef bool (*compression_supports_type_t)(PhysicalType type); +typedef bool (*compression_supports_type_t)(const CompressionInfo &info); struct DefaultCompressionMethod { CompressionType type; @@ -29,12 +29,12 @@ static const DefaultCompressionMethod internal_compression_methods[] = { {CompressionType::COMPRESSION_AUTO, nullptr, nullptr}}; static optional_ptr FindCompressionFunction(CompressionFunctionSet &set, CompressionType type, - PhysicalType data_type) { + const CompressionInfo &info) { auto &functions = set.functions; auto comp_entry = functions.find(type); if (comp_entry != functions.end()) { auto &type_functions = comp_entry->second; - auto type_entry = type_functions.find(data_type); + auto type_entry = type_functions.find(info.GetPhysicalType()); if (type_entry != type_functions.end()) { return &type_entry->second; } @@ -43,56 +43,56 @@ static optional_ptr FindCompressionFunction(CompressionFunc } static optional_ptr LoadCompressionFunction(CompressionFunctionSet &set, CompressionType type, - PhysicalType data_type) { + const CompressionInfo &info) { for (idx_t index = 0; internal_compression_methods[index].get_function; index++) { const auto &method = internal_compression_methods[index]; if (method.type == type) { // found the correct compression type - if (!method.supports_type(data_type)) { + if (!method.supports_type(info)) { // but it does not support this data type: bail out return nullptr; } // the type is supported: create the function and insert it into the set - auto function = method.get_function(data_type); - set.functions[type].insert(make_pair(data_type, function)); - return FindCompressionFunction(set, type, data_type); + auto function = method.get_function(info.GetPhysicalType()); + set.functions[type].insert(make_pair(info.GetPhysicalType(), function)); + return FindCompressionFunction(set, type, info); } } throw InternalException("Unsupported compression function type"); } static void TryLoadCompression(DBConfig &config, vector> &result, CompressionType type, - PhysicalType data_type) { - auto function = config.GetCompressionFunction(type, data_type); + const CompressionInfo &info) { + auto function = config.GetCompressionFunction(type, info); if (!function) { return; } result.push_back(*function); } -vector> DBConfig::GetCompressionFunctions(PhysicalType data_type) { +vector> DBConfig::GetCompressionFunctions(const CompressionInfo &info) { vector> result; - TryLoadCompression(*this, result, CompressionType::COMPRESSION_UNCOMPRESSED, data_type); - TryLoadCompression(*this, result, CompressionType::COMPRESSION_RLE, data_type); - TryLoadCompression(*this, result, CompressionType::COMPRESSION_BITPACKING, data_type); - TryLoadCompression(*this, result, CompressionType::COMPRESSION_DICTIONARY, data_type); - TryLoadCompression(*this, result, CompressionType::COMPRESSION_CHIMP, data_type); - TryLoadCompression(*this, result, CompressionType::COMPRESSION_PATAS, data_type); - TryLoadCompression(*this, result, CompressionType::COMPRESSION_ALP, data_type); - TryLoadCompression(*this, result, CompressionType::COMPRESSION_ALPRD, data_type); - TryLoadCompression(*this, result, CompressionType::COMPRESSION_FSST, data_type); + TryLoadCompression(*this, result, CompressionType::COMPRESSION_UNCOMPRESSED, info); + TryLoadCompression(*this, result, CompressionType::COMPRESSION_RLE, info); + TryLoadCompression(*this, result, CompressionType::COMPRESSION_BITPACKING, info); + TryLoadCompression(*this, result, CompressionType::COMPRESSION_DICTIONARY, info); + TryLoadCompression(*this, result, CompressionType::COMPRESSION_CHIMP, info); + TryLoadCompression(*this, result, CompressionType::COMPRESSION_PATAS, info); + TryLoadCompression(*this, result, CompressionType::COMPRESSION_ALP, info); + TryLoadCompression(*this, result, CompressionType::COMPRESSION_ALPRD, info); + TryLoadCompression(*this, result, CompressionType::COMPRESSION_FSST, info); return result; } -optional_ptr DBConfig::GetCompressionFunction(CompressionType type, PhysicalType data_type) { +optional_ptr DBConfig::GetCompressionFunction(CompressionType type, const CompressionInfo &info) { lock_guard l(compression_functions->lock); // check if the function is already loaded - auto function = FindCompressionFunction(*compression_functions, type, data_type); + auto function = FindCompressionFunction(*compression_functions, type, info); if (function) { return function; } // else load the function - return LoadCompressionFunction(*compression_functions, type, data_type); + return LoadCompressionFunction(*compression_functions, type, info); } } // namespace duckdb diff --git a/src/function/copy_function.cpp b/src/function/copy_function.cpp new file mode 100644 index 00000000000..ac2bc754533 --- /dev/null +++ b/src/function/copy_function.cpp @@ -0,0 +1,27 @@ +#include "duckdb/function/copy_function.hpp" + +namespace duckdb { + +vector GetCopyFunctionReturnNames(CopyFunctionReturnType return_type) { + switch (return_type) { + case CopyFunctionReturnType::CHANGED_ROWS: + return {"Count"}; + case CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST: + return {"Count", "Files"}; + default: + throw NotImplementedException("Unknown CopyFunctionReturnType"); + } +} + +vector GetCopyFunctionReturnLogicalTypes(CopyFunctionReturnType return_type) { + switch (return_type) { + case CopyFunctionReturnType::CHANGED_ROWS: + return {LogicalType::BIGINT}; + case CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST: + return {LogicalType::BIGINT, LogicalType::LIST(LogicalType::VARCHAR)}; + default: + throw NotImplementedException("Unknown CopyFunctionReturnType"); + } +} + +} // namespace duckdb diff --git a/src/function/function_binder.cpp b/src/function/function_binder.cpp index 267f589d8ff..e3b8f94e019 100644 --- a/src/function/function_binder.cpp +++ b/src/function/function_binder.cpp @@ -12,6 +12,7 @@ #include "duckdb/planner/expression/bound_constant_expression.hpp" #include "duckdb/planner/expression/bound_function_expression.hpp" #include "duckdb/planner/expression_binder.hpp" +#include "duckdb/function/scalar/generic_functions.hpp" namespace duckdb { @@ -238,21 +239,38 @@ LogicalTypeComparisonResult RequiresCast(const LogicalType &source_type, const L return LogicalTypeComparisonResult::DIFFERENT_TYPES; } -LogicalType PrepareTypeForCast(const LogicalType &type) { +bool TypeRequiresPrepare(const LogicalType &type) { + if (type.id() == LogicalTypeId::ANY) { + return true; + } + if (type.id() == LogicalTypeId::LIST) { + return TypeRequiresPrepare(ListType::GetChildType(type)); + } + return false; +} + +LogicalType PrepareTypeForCastRecursive(const LogicalType &type) { if (type.id() == LogicalTypeId::ANY) { return AnyType::GetTargetType(type); } if (type.id() == LogicalTypeId::LIST) { - return LogicalType::LIST(PrepareTypeForCast(ListType::GetChildType(type))); + return LogicalType::LIST(PrepareTypeForCastRecursive(ListType::GetChildType(type))); } return type; } +void PrepareTypeForCast(LogicalType &type) { + if (!TypeRequiresPrepare(type)) { + return; + } + type = PrepareTypeForCastRecursive(type); +} + void FunctionBinder::CastToFunctionArguments(SimpleFunction &function, vector> &children) { for (auto &arg : function.arguments) { - arg = PrepareTypeForCast(arg); + PrepareTypeForCast(arg); } - function.varargs = PrepareTypeForCast(function.varargs); + PrepareTypeForCast(function.varargs); for (idx_t i = 0; i < children.size(); i++) { auto target_type = i < function.arguments.size() ? function.arguments[i] : function.varargs; @@ -279,7 +297,7 @@ void FunctionBinder::CastToFunctionArguments(SimpleFunction &function, vector FunctionBinder::BindScalarFunction(const string &schema, const string &name, vector> children, ErrorData &error, - bool is_operator, Binder *binder) { + bool is_operator, optional_ptr binder) { // bind the function auto &function = Catalog::GetSystemCatalog(context).GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, schema, name); @@ -290,7 +308,7 @@ unique_ptr FunctionBinder::BindScalarFunction(const string &schema, unique_ptr FunctionBinder::BindScalarFunction(ScalarFunctionCatalogEntry &func, vector> children, ErrorData &error, - bool is_operator, Binder *binder) { + bool is_operator, optional_ptr binder) { // bind the function auto best_function = BindFunction(func.name, func.functions, children, error); if (!best_function.IsValid()) { @@ -335,23 +353,38 @@ unique_ptr FunctionBinder::BindScalarFunction(ScalarFunctionCatalogE } } } - return BindScalarFunction(bound_function, std::move(children), is_operator); + return BindScalarFunction(bound_function, std::move(children), is_operator, binder); } -unique_ptr FunctionBinder::BindScalarFunction(ScalarFunction bound_function, - vector> children, - bool is_operator) { +unique_ptr FunctionBinder::BindScalarFunction(ScalarFunction bound_function, + vector> children, bool is_operator, + optional_ptr binder) { unique_ptr bind_info; if (bound_function.bind) { bind_info = bound_function.bind(context, bound_function, children); } + if (bound_function.get_modified_databases && binder) { + auto &properties = binder->GetStatementProperties(); + FunctionModifiedDatabasesInput input(bind_info, properties.modified_databases); + bound_function.get_modified_databases(input); + } // check if we need to add casts to the children CastToFunctionArguments(bound_function, children); // now create the function auto return_type = bound_function.return_type; - return make_uniq(std::move(return_type), std::move(bound_function), std::move(children), - std::move(bind_info), is_operator); + unique_ptr result; + auto result_func = make_uniq(std::move(return_type), std::move(bound_function), + std::move(children), std::move(bind_info), is_operator); + if (result_func->function.bind_expression) { + // if a bind_expression callback is registered - call it and emit the resulting expression + FunctionBindExpressionInput input(context, result_func->bind_info.get(), *result_func); + result = result_func->function.bind_expression(input); + } + if (!result) { + result = std::move(result_func); + } + return result; } unique_ptr FunctionBinder::BindAggregateFunction(AggregateFunction bound_function, diff --git a/src/function/pragma/pragma_functions.cpp b/src/function/pragma/pragma_functions.cpp index d44ec629d26..3e82bfb7c5e 100644 --- a/src/function/pragma/pragma_functions.cpp +++ b/src/function/pragma/pragma_functions.cpp @@ -2,6 +2,8 @@ #include "duckdb/common/enums/output_type.hpp" #include "duckdb/common/operator/cast_operators.hpp" +#include "duckdb/function/function_set.hpp" +#include "duckdb/logging/http_logger.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/main/database.hpp" #include "duckdb/main/query_profiler.hpp" @@ -10,7 +12,6 @@ #include "duckdb/planner/expression_binder.hpp" #include "duckdb/storage/buffer_manager.hpp" #include "duckdb/storage/storage_manager.hpp" -#include "duckdb/function/function_set.hpp" #include diff --git a/src/function/pragma/pragma_queries.cpp b/src/function/pragma/pragma_queries.cpp index d1033bbc55d..fdb47ae3510 100644 --- a/src/function/pragma/pragma_queries.cpp +++ b/src/function/pragma/pragma_queries.cpp @@ -3,9 +3,10 @@ #include "duckdb/common/file_system.hpp" #include "duckdb/common/string_util.hpp" #include "duckdb/function/pragma/pragma_functions.hpp" +#include "duckdb/main/client_data.hpp" #include "duckdb/main/config.hpp" #include "duckdb/main/database_manager.hpp" -#include "duckdb/main/client_data.hpp" +#include "duckdb/main/extension_helper.hpp" #include "duckdb/parser/parser.hpp" #include "duckdb/parser/qualified_name.hpp" #include "duckdb/parser/statement/copy_statement.hpp" diff --git a/src/function/scalar/generic/CMakeLists.txt b/src/function/scalar/generic/CMakeLists.txt index 0211ed135d1..a19367f1b01 100644 --- a/src/function/scalar/generic/CMakeLists.txt +++ b/src/function/scalar/generic/CMakeLists.txt @@ -1,4 +1,5 @@ -add_library_unity(duckdb_func_generic_main OBJECT constant_or_null.cpp) +add_library_unity(duckdb_func_generic_main OBJECT binning.cpp + constant_or_null.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/function/scalar/generic/binning.cpp b/src/function/scalar/generic/binning.cpp new file mode 100644 index 00000000000..44f9a15f930 --- /dev/null +++ b/src/function/scalar/generic/binning.cpp @@ -0,0 +1,451 @@ +#include "duckdb/common/exception.hpp" +#include "duckdb/common/hugeint.hpp" +#include "duckdb/common/types/date.hpp" +#include "duckdb/common/types/time.hpp" +#include "duckdb/common/types/timestamp.hpp" +#include "duckdb/common/vector_operations/generic_executor.hpp" +#include "duckdb/core_functions/scalar/generic_functions.hpp" +#include "duckdb/common/operator/subtract.hpp" + +namespace duckdb { + +static hugeint_t GetPreviousPowerOfTen(hugeint_t input) { + hugeint_t power_of_ten = 1; + while (power_of_ten < input) { + power_of_ten *= 10; + } + return power_of_ten / 10; +} + +enum class NiceRounding { CEILING, ROUND }; + +hugeint_t MakeNumberNice(hugeint_t input, hugeint_t power_of_ten, NiceRounding rounding) { + // we consider numbers nice if they are divisible by 2 or 5 times the power-of-ten one lower than the current + // e.g. 120 is a nice number because it is divisible by 20 + // 122 is not a nice number -> we make it nice by turning it into 120 [/20] + // 153 is not a nice number -> we make it nice by turning it into 150 [/50] + // 1220 is not a nice number -> we turn it into 1200 [/200] + // first figure out the previous power of 10 (i.e. for 67 we return 10) + // now the power of ten is the power BELOW the current number + // i.e. for 67, it is not 10 + // now we can get the 2 or 5 divisors + hugeint_t two = power_of_ten / 5; + hugeint_t five = power_of_ten / 2; + + // compute the closest round number by adding the divisor / 2 and truncating + // do this for both divisors + hugeint_t round_to_two, round_to_five; + if (rounding == NiceRounding::ROUND) { + // round + round_to_two = (input + (two / 2)) / two * two; + round_to_five = (input + (five / 2)) / five * five; + } else { + // ceil + round_to_two = (input + (two - 1)) / two * two; + round_to_five = (input + (five - 1)) / five * five; + } + // now pick the closest number of the two (i.e. for 147 we pick 150, not 140) + if (AbsValue(input - round_to_two) < AbsValue(input - round_to_five)) { + return round_to_two; + } else { + return round_to_five; + } +} + +static double GetPreviousPowerOfTen(double input) { + double power_of_ten = 1; + if (input < 1) { + while (power_of_ten > input) { + power_of_ten /= 10; + } + return power_of_ten; + } + while (power_of_ten < input) { + power_of_ten *= 10; + } + return power_of_ten / 10; +} + +double MakeNumberNice(double input, const double power_of_ten, NiceRounding rounding) { + if (input == 0) { + return 0; + } + // now the power of ten is the power BELOW the current number + // i.e. for 67, it is not 10 + // now we can get the 2 or 5 divisors + const double two = power_of_ten / 5; + const double five = power_of_ten / 2; + + double round_to_two, round_to_five; + if (rounding == NiceRounding::ROUND) { + round_to_two = std::round(input / two) * two; + round_to_five = std::round(input / five) * five; + } else { + round_to_two = std::ceil(input / two) * two; + round_to_five = std::ceil(input / five) * five; + } + if (!Value::IsFinite(round_to_two) || !Value::IsFinite(round_to_five)) { + return input; + } + // now pick the closest number of the two (i.e. for 147 we pick 150, not 140) + if (AbsValue(input - round_to_two) < AbsValue(input - round_to_five)) { + return round_to_two; + } else { + return round_to_five; + } +} + +struct EquiWidthBinsInteger { + static constexpr LogicalTypeId LOGICAL_TYPE = LogicalTypeId::BIGINT; + + static vector> Operation(const Expression &expr, int64_t input_min, int64_t input_max, + idx_t bin_count, bool nice_rounding) { + vector> result; + // to prevent integer truncation from affecting the bin boundaries we calculate them with numbers multiplied by + // 1000 we then divide to get the actual boundaries + const auto FACTOR = hugeint_t(1000); + auto min = hugeint_t(input_min) * FACTOR; + auto max = hugeint_t(input_max) * FACTOR; + + const hugeint_t span = max - min; + hugeint_t step = span / Hugeint::Convert(bin_count); + hugeint_t power_of_ten = GetPreviousPowerOfTen(step); + if (nice_rounding) { + // when doing nice rounding we try to make the max/step values nicer + step = MakeNumberNice(step, power_of_ten, NiceRounding::ROUND); + max = MakeNumberNice(max, power_of_ten, NiceRounding::CEILING); + } + + for (hugeint_t bin_boundary = max; bin_boundary > min; bin_boundary -= step) { + const hugeint_t target_boundary = bin_boundary / FACTOR; + int64_t real_boundary = Hugeint::Cast(target_boundary); + if (!result.empty()) { + if (real_boundary < input_min || result.size() >= bin_count) { + // we can never generate input_min + break; + } + if (real_boundary == result.back().val) { + // we cannot generate the same value multiple times in a row - skip this step + continue; + } + } + result.push_back(real_boundary); + } + return result; + } +}; + +struct EquiWidthBinsDouble { + static constexpr LogicalTypeId LOGICAL_TYPE = LogicalTypeId::DOUBLE; + + static vector> Operation(const Expression &expr, double min, double input_max, + idx_t bin_count, bool nice_rounding) { + double max = input_max; + if (!Value::IsFinite(min) || !Value::IsFinite(max)) { + throw InvalidInputException("equi_width_bucket does not support infinite or nan as min/max value"); + } + vector> result; + const double span = max - min; + double step; + if (!Value::IsFinite(span)) { + // max - min does not fit + step = max / bin_count - min / bin_count; + } else { + step = span / static_cast(bin_count); + } + const double step_power_of_ten = GetPreviousPowerOfTen(step); + if (nice_rounding) { + // when doing nice rounding we try to make the max/step values nicer + step = MakeNumberNice(step, step_power_of_ten, NiceRounding::ROUND); + max = MakeNumberNice(input_max, step_power_of_ten, NiceRounding::CEILING); + } + + const double round_multiplication = 10 / step_power_of_ten; + for (double bin_boundary = max; bin_boundary > min; bin_boundary -= step) { + // because floating point addition adds inaccuracies, we add rounding at every step + if (nice_rounding) { + bin_boundary = std::round(bin_boundary * round_multiplication) / round_multiplication; + } + if (bin_boundary < min || result.size() >= bin_count) { + // we can never generate below input_min + break; + } + result.push_back(bin_boundary); + } + return result; + } +}; + +void NextMonth(int32_t &year, int32_t &month) { + month++; + if (month == 13) { + year++; + month = 1; + } +} + +void NextDay(int32_t &year, int32_t &month, int32_t &day) { + day++; + if (!Date::IsValid(year, month, day)) { + // day is out of range for month, move to next month + NextMonth(year, month); + day = 1; + } +} + +void NextHour(int32_t &year, int32_t &month, int32_t &day, int32_t &hour) { + hour++; + if (hour >= 24) { + NextDay(year, month, day); + hour = 0; + } +} + +void NextMinute(int32_t &year, int32_t &month, int32_t &day, int32_t &hour, int32_t &minute) { + minute++; + if (minute >= 60) { + NextHour(year, month, day, hour); + minute = 0; + } +} + +void NextSecond(int32_t &year, int32_t &month, int32_t &day, int32_t &hour, int32_t &minute, int32_t &sec) { + sec++; + if (sec >= 60) { + NextMinute(year, month, day, hour, minute); + sec = 0; + } +} + +timestamp_t MakeTimestampNice(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t minute, int32_t sec, + int32_t micros, interval_t step) { + // how to make a timestamp nice depends on the step + if (step.months >= 12) { + // if the step involves one year or more, ceil to months + // set time component to 00:00:00.00 + if (day > 1 || hour > 0 || minute > 0 || sec > 0 || micros > 0) { + // move to next month + NextMonth(year, month); + hour = minute = sec = micros = 0; + day = 1; + } + } else if (step.months > 0 || step.days >= 1) { + // if the step involves more than one day, ceil to days + if (hour > 0 || minute > 0 || sec > 0 || micros > 0) { + NextDay(year, month, day); + hour = minute = sec = micros = 0; + } + } else if (step.days > 0 || step.micros >= Interval::MICROS_PER_HOUR) { + // if the step involves more than one hour, ceil to hours + if (minute > 0 || sec > 0 || micros > 0) { + NextHour(year, month, day, hour); + minute = sec = micros = 0; + } + } else if (step.micros >= Interval::MICROS_PER_MINUTE) { + // if the step involves more than one minute, ceil to minutes + if (sec > 0 || micros > 0) { + NextMinute(year, month, day, hour, minute); + sec = micros = 0; + } + } else if (step.micros >= Interval::MICROS_PER_SEC) { + // if the step involves more than one second, ceil to seconds + if (micros > 0) { + NextSecond(year, month, day, hour, minute, sec); + micros = 0; + } + } + return Timestamp::FromDatetime(Date::FromDate(year, month, day), Time::FromTime(hour, minute, sec, micros)); +} + +int64_t RoundNumberToDivisor(int64_t number, int64_t divisor) { + return (number + (divisor / 2)) / divisor * divisor; +} + +interval_t MakeIntervalNice(interval_t interval) { + if (interval.months >= 6) { + // if we have more than 6 months, we don't care about days + interval.days = interval.micros = 0; + } else if (interval.months > 0 || interval.days >= 5) { + // if we have any months or more than 5 days, we don't care about micros + interval.micros = 0; + } else if (interval.days > 0 || interval.micros >= 6 * Interval::MICROS_PER_HOUR) { + // if we any days or more than 6 hours, we want micros to be roundable by hours at least + interval.micros = RoundNumberToDivisor(interval.micros, Interval::MICROS_PER_HOUR); + } else if (interval.micros >= Interval::MICROS_PER_HOUR) { + // if we have more than an hour, we want micros to be divisible by quarter hours + interval.micros = RoundNumberToDivisor(interval.micros, Interval::MICROS_PER_MINUTE * 15); + } else if (interval.micros >= Interval::MICROS_PER_MINUTE * 10) { + // if we have more than 10 minutes, we want micros to be divisible by minutes + interval.micros = RoundNumberToDivisor(interval.micros, Interval::MICROS_PER_MINUTE); + } else if (interval.micros >= Interval::MICROS_PER_MINUTE) { + // if we have more than a minute, we want micros to be divisible by quarter minutes + interval.micros = RoundNumberToDivisor(interval.micros, Interval::MICROS_PER_SEC * 15); + } else if (interval.micros >= Interval::MICROS_PER_SEC * 10) { + // if we have more than 10 seconds, we want micros to be divisible by seconds + interval.micros = RoundNumberToDivisor(interval.micros, Interval::MICROS_PER_SEC); + } + return interval; +} + +void GetTimestampComponents(timestamp_t input, int32_t &year, int32_t &month, int32_t &day, int32_t &hour, + int32_t &minute, int32_t &sec, int32_t µs) { + date_t date; + dtime_t time; + + Timestamp::Convert(input, date, time); + Date::Convert(date, year, month, day); + Time::Convert(time, hour, minute, sec, micros); +} + +struct EquiWidthBinsTimestamp { + static constexpr LogicalTypeId LOGICAL_TYPE = LogicalTypeId::TIMESTAMP; + + static vector> Operation(const Expression &expr, timestamp_t input_min, + timestamp_t input_max, idx_t bin_count, bool nice_rounding) { + if (!Value::IsFinite(input_min) || !Value::IsFinite(input_max)) { + throw InvalidInputException(expr, "equi_width_bucket does not support infinite or nan as min/max value"); + } + + if (!nice_rounding) { + // if we are not doing nice rounding it is pretty simple - just interpolate between the timestamp values + auto interpolated_values = + EquiWidthBinsInteger::Operation(expr, input_min.value, input_max.value, bin_count, false); + + vector> result; + for (auto &val : interpolated_values) { + result.push_back(timestamp_t(val.val)); + } + return result; + } + // fetch the components of the timestamps + int32_t min_year, min_month, min_day, min_hour, min_minute, min_sec, min_micros; + int32_t max_year, max_month, max_day, max_hour, max_minute, max_sec, max_micros; + GetTimestampComponents(input_min, min_year, min_month, min_day, min_hour, min_minute, min_sec, min_micros); + GetTimestampComponents(input_max, max_year, max_month, max_day, max_hour, max_minute, max_sec, max_micros); + + // get the interval differences per component + // note: these can be negative (except for the largest non-zero difference) + interval_t interval_diff; + interval_diff.months = (max_year - min_year) * Interval::MONTHS_PER_YEAR + (max_month - min_month); + interval_diff.days = max_day - min_day; + interval_diff.micros = (max_hour - min_hour) * Interval::MICROS_PER_HOUR + + (max_minute - min_minute) * Interval::MICROS_PER_MINUTE + + (max_sec - min_sec) * Interval::MICROS_PER_SEC + (max_micros - min_micros); + + double step_months = static_cast(interval_diff.months) / static_cast(bin_count); + double step_days = static_cast(interval_diff.days) / static_cast(bin_count); + double step_micros = static_cast(interval_diff.micros) / static_cast(bin_count); + // since we truncate the months/days, propagate any fractional component to the unit below (i.e. 0.2 months + // becomes 6 days) + if (step_months > 0) { + double overflow_months = step_months - std::floor(step_months); + step_days += overflow_months * Interval::DAYS_PER_MONTH; + } + if (step_days > 0) { + double overflow_days = step_days - std::floor(step_days); + step_micros += overflow_days * Interval::MICROS_PER_DAY; + } + interval_t step; + step.months = static_cast(step_months); + step.days = static_cast(step_days); + step.micros = static_cast(step_micros); + + // now we make the max, and the step nice + step = MakeIntervalNice(step); + timestamp_t timestamp_val = + MakeTimestampNice(max_year, max_month, max_day, max_hour, max_minute, max_sec, max_micros, step); + if (step.months <= 0 && step.days <= 0 && step.micros <= 0) { + // interval must be at least one microsecond + step.months = step.days = 0; + step.micros = 1; + } + + vector> result; + while (timestamp_val.value >= input_min.value && result.size() < bin_count) { + result.push_back(timestamp_val); + timestamp_val = SubtractOperator::Operation(timestamp_val, step); + } + return result; + } +}; + +unique_ptr BindEquiWidthFunction(ClientContext &, ScalarFunction &bound_function, + vector> &arguments) { + // while internally the bins are computed over a unified type + // the equi_width_bins function returns the same type as the input MAX + if (arguments[1]->return_type.id() != LogicalTypeId::UNKNOWN && + arguments[1]->return_type.id() != LogicalTypeId::SQLNULL) { + bound_function.return_type = LogicalType::LIST(arguments[1]->return_type); + } + return nullptr; +} + +template +static void EquiWidthBinFunction(DataChunk &args, ExpressionState &state, Vector &result) { + static constexpr int64_t MAX_BIN_COUNT = 1000000; + auto &min_arg = args.data[0]; + auto &max_arg = args.data[1]; + auto &bin_count = args.data[2]; + auto &nice_rounding = args.data[3]; + + Vector intermediate_result(LogicalType::LIST(OP::LOGICAL_TYPE)); + GenericExecutor::ExecuteQuaternary, PrimitiveType, PrimitiveType, PrimitiveType, + GenericListType>>( + min_arg, max_arg, bin_count, nice_rounding, intermediate_result, args.size(), + [&](PrimitiveType min_p, PrimitiveType max_p, PrimitiveType bins_p, + PrimitiveType nice_rounding_p) { + if (max_p.val < min_p.val) { + throw InvalidInputException(state.expr, + "Invalid input for bin function - max value is smaller than min value"); + } + if (bins_p.val <= 0) { + throw InvalidInputException(state.expr, "Invalid input for bin function - there must be > 0 bins"); + } + if (bins_p.val > MAX_BIN_COUNT) { + throw InvalidInputException(state.expr, "Invalid input for bin function - max bin count of %d exceeded", + MAX_BIN_COUNT); + } + GenericListType> result_bins; + if (max_p.val == min_p.val) { + // if max = min return a single bucket + result_bins.values.push_back(max_p.val); + } else { + result_bins.values = OP::Operation(state.expr, min_p.val, max_p.val, static_cast(bins_p.val), + nice_rounding_p.val); + // last bin should always be the input max + if (result_bins.values[0].val < max_p.val) { + result_bins.values[0].val = max_p.val; + } + std::reverse(result_bins.values.begin(), result_bins.values.end()); + } + return result_bins; + }); + VectorOperations::DefaultCast(intermediate_result, result, args.size()); +} + +static void UnsupportedEquiWidth(DataChunk &args, ExpressionState &state, Vector &) { + throw BinderException(state.expr, "Unsupported type \"%s\" for equi_width_bins", args.data[0].GetType()); +} + +ScalarFunctionSet EquiWidthBinsFun::GetFunctions() { + ScalarFunctionSet functions("equi_width_bins"); + functions.AddFunction( + ScalarFunction({LogicalType::BIGINT, LogicalType::BIGINT, LogicalType::BIGINT, LogicalType::BOOLEAN}, + LogicalType::LIST(LogicalType::BIGINT), EquiWidthBinFunction, + BindEquiWidthFunction)); + functions.AddFunction( + ScalarFunction({LogicalType::DOUBLE, LogicalType::DOUBLE, LogicalType::BIGINT, LogicalType::BOOLEAN}, + LogicalType::LIST(LogicalType::DOUBLE), EquiWidthBinFunction, + BindEquiWidthFunction)); + functions.AddFunction( + ScalarFunction({LogicalType::TIMESTAMP, LogicalType::TIMESTAMP, LogicalType::BIGINT, LogicalType::BOOLEAN}, + LogicalType::LIST(LogicalType::DATE), EquiWidthBinFunction, + BindEquiWidthFunction)); + functions.AddFunction( + ScalarFunction({LogicalType::ANY_PARAMS(LogicalType::ANY, 150), LogicalType::ANY_PARAMS(LogicalType::ANY, 150), + LogicalType::BIGINT, LogicalType::BOOLEAN}, + LogicalType::LIST(LogicalType::ANY), UnsupportedEquiWidth, BindEquiWidthFunction)); + return functions; +} + +} // namespace duckdb diff --git a/src/function/scalar/list/CMakeLists.txt b/src/function/scalar/list/CMakeLists.txt index cd4412440b1..1ec4ac330f0 100644 --- a/src/function/scalar/list/CMakeLists.txt +++ b/src/function/scalar/list/CMakeLists.txt @@ -1,7 +1,6 @@ add_library_unity( duckdb_func_list_nested OBJECT - list_concat.cpp contains_or_position.cpp list_extract.cpp list_resize.cpp diff --git a/src/function/scalar/list/list_concat.cpp b/src/function/scalar/list/list_concat.cpp deleted file mode 100644 index 880d752640a..00000000000 --- a/src/function/scalar/list/list_concat.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "duckdb/common/types/data_chunk.hpp" -#include "duckdb/function/scalar/nested_functions.hpp" -#include "duckdb/planner/expression/bound_function_expression.hpp" -#include "duckdb/planner/expression/bound_parameter_expression.hpp" -#include "duckdb/planner/expression_binder.hpp" -#include "duckdb/planner/expression/bound_cast_expression.hpp" - -namespace duckdb { - -static void ListConcatFunction(DataChunk &args, ExpressionState &state, Vector &result) { - D_ASSERT(args.ColumnCount() == 2); - auto count = args.size(); - - Vector &lhs = args.data[0]; - Vector &rhs = args.data[1]; - if (lhs.GetType().id() == LogicalTypeId::SQLNULL) { - result.Reference(rhs); - return; - } - if (rhs.GetType().id() == LogicalTypeId::SQLNULL) { - result.Reference(lhs); - return; - } - - UnifiedVectorFormat lhs_data; - UnifiedVectorFormat rhs_data; - lhs.ToUnifiedFormat(count, lhs_data); - rhs.ToUnifiedFormat(count, rhs_data); - auto lhs_entries = UnifiedVectorFormat::GetData(lhs_data); - auto rhs_entries = UnifiedVectorFormat::GetData(rhs_data); - - auto lhs_list_size = ListVector::GetListSize(lhs); - auto rhs_list_size = ListVector::GetListSize(rhs); - auto &lhs_child = ListVector::GetEntry(lhs); - auto &rhs_child = ListVector::GetEntry(rhs); - UnifiedVectorFormat lhs_child_data; - UnifiedVectorFormat rhs_child_data; - lhs_child.ToUnifiedFormat(lhs_list_size, lhs_child_data); - rhs_child.ToUnifiedFormat(rhs_list_size, rhs_child_data); - - result.SetVectorType(VectorType::FLAT_VECTOR); - auto result_entries = FlatVector::GetData(result); - auto &result_validity = FlatVector::Validity(result); - - idx_t offset = 0; - for (idx_t i = 0; i < count; i++) { - auto lhs_list_index = lhs_data.sel->get_index(i); - auto rhs_list_index = rhs_data.sel->get_index(i); - if (!lhs_data.validity.RowIsValid(lhs_list_index) && !rhs_data.validity.RowIsValid(rhs_list_index)) { - result_validity.SetInvalid(i); - continue; - } - result_entries[i].offset = offset; - result_entries[i].length = 0; - if (lhs_data.validity.RowIsValid(lhs_list_index)) { - const auto &lhs_entry = lhs_entries[lhs_list_index]; - result_entries[i].length += lhs_entry.length; - ListVector::Append(result, lhs_child, *lhs_child_data.sel, lhs_entry.offset + lhs_entry.length, - lhs_entry.offset); - } - if (rhs_data.validity.RowIsValid(rhs_list_index)) { - const auto &rhs_entry = rhs_entries[rhs_list_index]; - result_entries[i].length += rhs_entry.length; - ListVector::Append(result, rhs_child, *rhs_child_data.sel, rhs_entry.offset + rhs_entry.length, - rhs_entry.offset); - } - offset += result_entries[i].length; - } - D_ASSERT(ListVector::GetListSize(result) == offset); - - if (lhs.GetVectorType() == VectorType::CONSTANT_VECTOR && rhs.GetVectorType() == VectorType::CONSTANT_VECTOR) { - result.SetVectorType(VectorType::CONSTANT_VECTOR); - } -} - -static unique_ptr ListConcatBind(ClientContext &context, ScalarFunction &bound_function, - vector> &arguments) { - D_ASSERT(bound_function.arguments.size() == 2); - - // if either argument is an array, we cast it to a list - arguments[0] = BoundCastExpression::AddArrayCastToList(context, std::move(arguments[0])); - arguments[1] = BoundCastExpression::AddArrayCastToList(context, std::move(arguments[1])); - - auto &lhs = arguments[0]->return_type; - auto &rhs = arguments[1]->return_type; - - if (lhs.id() == LogicalTypeId::UNKNOWN || rhs.id() == LogicalTypeId::UNKNOWN) { - throw ParameterNotResolvedException(); - } else if (lhs.id() == LogicalTypeId::SQLNULL || rhs.id() == LogicalTypeId::SQLNULL) { - // we mimic postgres behaviour: list_concat(NULL, my_list) = my_list - auto return_type = rhs.id() == LogicalTypeId::SQLNULL ? lhs : rhs; - bound_function.arguments[0] = return_type; - bound_function.arguments[1] = return_type; - bound_function.return_type = return_type; - } else { - D_ASSERT(lhs.id() == LogicalTypeId::LIST); - D_ASSERT(rhs.id() == LogicalTypeId::LIST); - - // Resolve list type - LogicalType child_type = LogicalType::SQLNULL; - for (const auto &argument : arguments) { - auto &next_type = ListType::GetChildType(argument->return_type); - if (!LogicalType::TryGetMaxLogicalType(context, child_type, next_type, child_type)) { - throw BinderException("Cannot concatenate lists of types %s[] and %s[] - an explicit cast is required", - child_type.ToString(), next_type.ToString()); - } - } - auto list_type = LogicalType::LIST(child_type); - - bound_function.arguments[0] = list_type; - bound_function.arguments[1] = list_type; - bound_function.return_type = list_type; - } - return make_uniq(bound_function.return_type); -} - -static unique_ptr ListConcatStats(ClientContext &context, FunctionStatisticsInput &input) { - auto &child_stats = input.child_stats; - D_ASSERT(child_stats.size() == 2); - - auto &left_stats = child_stats[0]; - auto &right_stats = child_stats[1]; - - auto stats = left_stats.ToUnique(); - stats->Merge(right_stats); - - return stats; -} - -ScalarFunction ListConcatFun::GetFunction() { - // the arguments and return types are actually set in the binder function - auto fun = ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::LIST(LogicalType::ANY)}, - LogicalType::LIST(LogicalType::ANY), ListConcatFunction, ListConcatBind, nullptr, - ListConcatStats); - fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; - return fun; -} - -void ListConcatFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction({"list_concat", "list_cat", "array_concat", "array_cat"}, GetFunction()); -} - -} // namespace duckdb diff --git a/src/function/scalar/list/list_resize.cpp b/src/function/scalar/list/list_resize.cpp index 04f494139cd..792e0f6bce9 100644 --- a/src/function/scalar/list/list_resize.cpp +++ b/src/function/scalar/list/list_resize.cpp @@ -28,7 +28,7 @@ void ListResizeFunction(DataChunk &args, ExpressionState &state, Vector &result) UnifiedVectorFormat new_size_data; new_sizes.ToUnifiedFormat(count, new_size_data); - auto new_size_entries = UnifiedVectorFormat::GetData(new_size_data); + auto new_size_entries = UnifiedVectorFormat::GetData(new_size_data); UnifiedVectorFormat child_data; child.ToUnifiedFormat(count, child_data); @@ -38,7 +38,7 @@ void ListResizeFunction(DataChunk &args, ExpressionState &state, Vector &result) for (idx_t i = 0; i < count; i++) { auto index = new_size_data.sel->get_index(i); if (new_size_data.validity.RowIsValid(index)) { - new_child_size += UnsafeNumericCast(new_size_entries[index]); + new_child_size += new_size_entries[index]; } } @@ -72,7 +72,7 @@ void ListResizeFunction(DataChunk &args, ExpressionState &state, Vector &result) idx_t new_size_entry = 0; if (new_size_data.validity.RowIsValid(new_index)) { - new_size_entry = UnsafeNumericCast(new_size_entries[new_index]); + new_size_entry = new_size_entries[new_index]; } // find the smallest size between lists and new_sizes diff --git a/src/function/scalar/list/list_select.cpp b/src/function/scalar/list/list_select.cpp index d31e7573a9b..07413977bfd 100644 --- a/src/function/scalar/list/list_select.cpp +++ b/src/function/scalar/list/list_select.cpp @@ -45,6 +45,12 @@ struct SetSelectionVectorWhere { if (!input_validity.RowIsValid(input_offset + child_idx)) { validity_mask.SetInvalid(target_offset); } + + if (child_idx >= target_length) { + selection_vector.set_index(target_offset, 0); + validity_mask.SetInvalid(target_offset); + } + target_offset++; } diff --git a/src/function/scalar/list/list_zip.cpp b/src/function/scalar/list/list_zip.cpp index 6069fab5c67..7e05038280d 100644 --- a/src/function/scalar/list/list_zip.cpp +++ b/src/function/scalar/list/list_zip.cpp @@ -143,8 +143,10 @@ static unique_ptr ListZipBind(ClientContext &context, ScalarFuncti case LogicalTypeId::SQLNULL: struct_children.push_back(make_pair(string(), LogicalTypeId::SQLNULL)); break; - default: + case LogicalTypeId::UNKNOWN: throw ParameterNotResolvedException(); + default: + throw BinderException("Parameter type needs to be List"); } } bound_function.return_type = LogicalType::LIST(LogicalType::STRUCT(struct_children)); diff --git a/src/function/scalar/operators/add.cpp b/src/function/scalar/operators/add.cpp index f0670120fe0..f3b86d5276a 100644 --- a/src/function/scalar/operators/add.cpp +++ b/src/function/scalar/operators/add.cpp @@ -36,15 +36,8 @@ interval_t AddOperator::Operation(interval_t left, interval_t right) { template <> date_t AddOperator::Operation(date_t left, int32_t right) { - if (!Value::IsFinite(left)) { - return left; - } - int32_t days; - if (!TryAddOperator::Operation(left.days, right, days)) { - throw OutOfRangeException("Date out of range"); - } - date_t result(days); - if (!Value::IsFinite(result)) { + date_t result; + if (!TryAddOperator::Operation(left, right, result)) { throw OutOfRangeException("Date out of range"); } return result; @@ -154,6 +147,23 @@ bool TryAddOperator::Operation(uint64_t left, uint64_t right, uint64_t &result) return OverflowCheckedAddition::Operation(left, right, result); } +template <> +bool TryAddOperator::Operation(date_t left, int32_t right, date_t &result) { + if (left == date_t::infinity() || left == date_t::ninfinity()) { + result = date_t(left); + return true; + } + int32_t days; + if (!TryAddOperator::Operation(left.days, right, days)) { + return false; + } + result.days = days; + if (!Value::IsFinite(result)) { + return false; + } + return true; +} + template <> bool TryAddOperator::Operation(int8_t left, int8_t right, int8_t &result) { return OverflowCheckedAddition::Operation(left, right, result); diff --git a/src/function/scalar/operators/arithmetic.cpp b/src/function/scalar/operators/arithmetic.cpp index 828395ff529..17cda072388 100644 --- a/src/function/scalar/operators/arithmetic.cpp +++ b/src/function/scalar/operators/arithmetic.cpp @@ -1,3 +1,4 @@ +#include "duckdb/common/enum_util.hpp" #include "duckdb/common/operator/add.hpp" #include "duckdb/common/operator/multiply.hpp" #include "duckdb/common/operator/numeric_binary_operators.hpp" @@ -9,10 +10,10 @@ #include "duckdb/common/types/time.hpp" #include "duckdb/common/types/timestamp.hpp" #include "duckdb/common/vector_operations/vector_operations.hpp" -#include "duckdb/common/enum_util.hpp" +#include "duckdb/function/scalar/nested_functions.hpp" #include "duckdb/function/scalar/operators.hpp" +#include "duckdb/function/scalar/string_functions.hpp" #include "duckdb/planner/expression/bound_function_expression.hpp" -#include "duckdb/function/scalar/nested_functions.hpp" #include diff --git a/src/function/scalar/sequence/nextval.cpp b/src/function/scalar/sequence/nextval.cpp index 2167e8e4a49..4e80ed43df0 100644 --- a/src/function/scalar/sequence/nextval.cpp +++ b/src/function/scalar/sequence/nextval.cpp @@ -11,12 +11,13 @@ #include "duckdb/common/serializer/deserializer.hpp" #include "duckdb/common/serializer/serializer.hpp" #include "duckdb/common/vector_operations/unary_executor.hpp" +#include "duckdb/transaction/meta_transaction.hpp" #include "duckdb/planner/binder.hpp" namespace duckdb { struct CurrentSequenceValueOperator { - static int64_t Operation(DuckTransaction &transaction, SequenceCatalogEntry &seq) { + static int64_t Operation(DuckTransaction &, SequenceCatalogEntry &seq) { return seq.CurrentValue(); } }; @@ -27,62 +28,80 @@ struct NextSequenceValueOperator { } }; +SequenceCatalogEntry &BindSequence(ClientContext &context, string &catalog, string &schema, const string &name) { + // fetch the sequence from the catalog + Binder::BindSchemaOrCatalog(context, catalog, schema); + return Catalog::GetEntry(context, catalog, schema, name); +} + SequenceCatalogEntry &BindSequence(ClientContext &context, const string &name) { auto qname = QualifiedName::Parse(name); - // fetch the sequence from the catalog - Binder::BindSchemaOrCatalog(context, qname.catalog, qname.schema); - return Catalog::GetEntry(context, qname.catalog, qname.schema, qname.name); + return BindSequence(context, qname.catalog, qname.schema, qname.name); +} + +struct NextValLocalState : public FunctionLocalState { + explicit NextValLocalState(DuckTransaction &transaction, SequenceCatalogEntry &sequence) + : transaction(transaction), sequence(sequence) { + } + + DuckTransaction &transaction; + SequenceCatalogEntry &sequence; +}; + +unique_ptr NextValLocalFunction(ExpressionState &state, const BoundFunctionExpression &expr, + FunctionData *bind_data) { + if (!bind_data) { + return nullptr; + } + auto &context = state.GetContext(); + auto &info = bind_data->Cast(); + auto &sequence = info.sequence; + auto &transaction = DuckTransaction::Get(context, sequence.catalog); + return make_uniq(transaction, sequence); } template static void NextValFunction(DataChunk &args, ExpressionState &state, Vector &result) { auto &func_expr = state.expr.Cast(); - auto &info = func_expr.bind_info->Cast(); - auto &input = args.data[0]; - - auto &context = state.GetContext(); - if (info.sequence) { - auto &sequence = *info.sequence; - auto &transaction = DuckTransaction::Get(context, sequence.catalog); - // sequence to use is hard coded - // increment the sequence - result.SetVectorType(VectorType::FLAT_VECTOR); - auto result_data = FlatVector::GetData(result); - for (idx_t i = 0; i < args.size(); i++) { - // get the next value from the sequence - result_data[i] = OP::Operation(transaction, sequence); - } - } else { - // sequence to use comes from the input - UnaryExecutor::Execute(input, result, args.size(), [&](string_t value) { - // fetch the sequence from the catalog - auto &sequence = BindSequence(context, value.GetString()); - // finally get the next value from the sequence - auto &transaction = DuckTransaction::Get(context, sequence.catalog); - return OP::Operation(transaction, sequence); - }); + if (!func_expr.bind_info) { + // no bind info - return null + result.SetVectorType(VectorType::CONSTANT_VECTOR); + ConstantVector::SetNull(result, true); + return; + } + auto &lstate = ExecuteFunctionState::GetFunctionState(state)->Cast(); + // sequence to use is hard coded + // increment the sequence + result.SetVectorType(VectorType::FLAT_VECTOR); + auto result_data = FlatVector::GetData(result); + for (idx_t i = 0; i < args.size(); i++) { + // get the next value from the sequence + result_data[i] = OP::Operation(lstate.transaction, lstate.sequence); } } -static unique_ptr NextValBind(ClientContext &context, ScalarFunction &bound_function, +static unique_ptr NextValBind(ClientContext &context, ScalarFunction &, vector> &arguments) { - optional_ptr sequence; - if (arguments[0]->IsFoldable()) { - // parameter to nextval function is a foldable constant - // evaluate the constant and perform the catalog lookup already - auto seqname = ExpressionExecutor::EvaluateScalar(context, *arguments[0]); - if (!seqname.IsNull()) { - sequence = &BindSequence(context, seqname.ToString()); - } + if (!arguments[0]->IsFoldable()) { + throw NotImplementedException( + "currval/nextval requires a constant sequence - non-constant sequences are no longer supported"); } - return make_uniq(sequence); + // parameter to nextval function is a foldable constant + // evaluate the constant and perform the catalog lookup already + auto seqname = ExpressionExecutor::EvaluateScalar(context, *arguments[0]); + if (seqname.IsNull()) { + return nullptr; + } + auto &seq = BindSequence(context, seqname.ToString()); + return make_uniq(seq); } static void NextValDependency(BoundFunctionExpression &expr, LogicalDependencyList &dependencies) { - auto &info = expr.bind_info->Cast(); - if (info.sequence) { - dependencies.AddDependency(*info.sequence); + if (!expr.bind_info) { + return; } + auto &info = expr.bind_info->Cast(); + dependencies.AddDependency(info.sequence); } void Serialize(Serializer &serializer, const optional_ptr bind_data, const ScalarFunction &) { @@ -93,14 +112,21 @@ void Serialize(Serializer &serializer, const optional_ptr bind_dat unique_ptr Deserialize(Deserializer &deserializer, ScalarFunction &) { auto create_info = deserializer.ReadPropertyWithDefault>(100, "sequence_create_info", unique_ptr()); - optional_ptr catalog_entry_ptr; - if (create_info) { - auto &seq_info = create_info->Cast(); - auto &context = deserializer.Get(); - catalog_entry_ptr = - &Catalog::GetEntry(context, seq_info.catalog, seq_info.schema, seq_info.name); + if (!create_info) { + return nullptr; + } + auto &seq_info = create_info->Cast(); + auto &context = deserializer.Get(); + auto &sequence = BindSequence(context, seq_info.catalog, seq_info.schema, seq_info.name); + return make_uniq(sequence); +} + +void NextValModifiedDatabases(FunctionModifiedDatabasesInput &input) { + if (!input.bind_data) { + return; } - return make_uniq(catalog_entry_ptr); + auto &seq = input.bind_data->Cast(); + input.modified_databases.insert(seq.sequence.ParentCatalog().GetName()); } void NextvalFun::RegisterFunction(BuiltinFunctions &set) { @@ -109,6 +135,8 @@ void NextvalFun::RegisterFunction(BuiltinFunctions &set) { next_val.stability = FunctionStability::VOLATILE; next_val.serialize = Serialize; next_val.deserialize = Deserialize; + next_val.get_modified_databases = NextValModifiedDatabases; + next_val.init_local_state = NextValLocalFunction; set.AddFunction(next_val); } @@ -118,6 +146,7 @@ void CurrvalFun::RegisterFunction(BuiltinFunctions &set) { curr_val.stability = FunctionStability::VOLATILE; curr_val.serialize = Serialize; curr_val.deserialize = Deserialize; + curr_val.init_local_state = NextValLocalFunction; set.AddFunction(curr_val); } diff --git a/src/function/scalar/strftime_format.cpp b/src/function/scalar/strftime_format.cpp index d4cf4067047..1077b562582 100644 --- a/src/function/scalar/strftime_format.cpp +++ b/src/function/scalar/strftime_format.cpp @@ -1,10 +1,14 @@ #include "duckdb/function/scalar/strftime_format.hpp" +#include "duckdb/common/exception/conversion_exception.hpp" #include "duckdb/common/string_util.hpp" #include "duckdb/common/to_string.hpp" #include "duckdb/common/types/cast_helpers.hpp" #include "duckdb/common/types/date.hpp" #include "duckdb/common/types/time.hpp" #include "duckdb/common/types/timestamp.hpp" +#include "duckdb/common/operator/add.hpp" +#include "duckdb/common/operator/multiply.hpp" + #include namespace duckdb { @@ -67,15 +71,15 @@ void StrfTimeFormat::AddFormatSpecifier(string preceding_literal, StrTimeSpecifi StrTimeFormat::AddFormatSpecifier(std::move(preceding_literal), specifier); } -idx_t StrfTimeFormat::GetSpecifierLength(StrTimeSpecifier specifier, date_t date, dtime_t time, int32_t utc_offset, +idx_t StrfTimeFormat::GetSpecifierLength(StrTimeSpecifier specifier, date_t date, int32_t data[8], const char *tz_name) { switch (specifier) { case StrTimeSpecifier::FULL_WEEKDAY_NAME: return Date::DAY_NAMES[Date::ExtractISODayOfTheWeek(date) % 7].GetSize(); case StrTimeSpecifier::FULL_MONTH_NAME: - return Date::MONTH_NAMES[Date::ExtractMonth(date) - 1].GetSize(); + return Date::MONTH_NAMES[data[1] - 1].GetSize(); case StrTimeSpecifier::YEAR_DECIMAL: { - auto year = Date::ExtractYear(date); + auto year = data[0]; // Be consistent with WriteStandardSpecifier if (0 <= year && year <= 9999) { return 4; @@ -85,13 +89,13 @@ idx_t StrfTimeFormat::GetSpecifierLength(StrTimeSpecifier specifier, date_t date } case StrTimeSpecifier::MONTH_DECIMAL: { idx_t len = 1; - auto month = Date::ExtractMonth(date); + auto month = data[1]; len += month >= 10; return len; } case StrTimeSpecifier::UTC_OFFSET: // ±HH or ±HH:MM - return (utc_offset % 60) ? 6 : 3; + return (data[7] % 60) ? 6 : 3; case StrTimeSpecifier::TZ_NAME: if (tz_name) { return strlen(tz_name); @@ -104,8 +108,7 @@ idx_t StrfTimeFormat::GetSpecifierLength(StrTimeSpecifier specifier, date_t date case StrTimeSpecifier::SECOND_DECIMAL: { // time specifiers idx_t len = 1; - int32_t hour, min, sec, msec; - Time::Convert(time, hour, min, sec, msec); + int32_t hour = data[3], min = data[4], sec = data[5]; switch (specifier) { case StrTimeSpecifier::HOUR_24_DECIMAL: len += hour >= 10; @@ -129,38 +132,49 @@ idx_t StrfTimeFormat::GetSpecifierLength(StrTimeSpecifier specifier, date_t date return len; } case StrTimeSpecifier::DAY_OF_MONTH: - return UnsafeNumericCast( - NumericHelper::UnsignedLength(UnsafeNumericCast(Date::ExtractDay(date)))); + return UnsafeNumericCast(NumericHelper::UnsignedLength(UnsafeNumericCast(data[2]))); case StrTimeSpecifier::DAY_OF_YEAR_DECIMAL: return UnsafeNumericCast( NumericHelper::UnsignedLength(UnsafeNumericCast(Date::ExtractDayOfTheYear(date)))); case StrTimeSpecifier::YEAR_WITHOUT_CENTURY: - return UnsafeNumericCast(NumericHelper::UnsignedLength( - UnsafeNumericCast(AbsValue(Date::ExtractYear(date)) % 100))); + return UnsafeNumericCast( + NumericHelper::UnsignedLength(UnsafeNumericCast(AbsValue(data[0]) % 100))); default: throw InternalException("Unimplemented specifier for GetSpecifierLength"); } } //! Returns the total length of the date formatted by this format specifier -idx_t StrfTimeFormat::GetLength(date_t date, dtime_t time, int32_t utc_offset, const char *tz_name) { +idx_t StrfTimeFormat::GetLength(date_t date, int32_t data[8], const char *tz_name) const { idx_t size = constant_size; if (!var_length_specifiers.empty()) { for (auto &specifier : var_length_specifiers) { - size += GetSpecifierLength(specifier, date, time, utc_offset, tz_name); + size += GetSpecifierLength(specifier, date, data, tz_name); } } return size; } -char *StrfTimeFormat::WriteString(char *target, const string_t &str) { +idx_t StrfTimeFormat::GetLength(date_t date, dtime_t time, int32_t utc_offset, const char *tz_name) { + if (!var_length_specifiers.empty()) { + int32_t data[8]; + Date::Convert(date, data[0], data[1], data[2]); + Time::Convert(time, data[3], data[4], data[5], data[6]); + data[6] *= Interval::NANOS_PER_MICRO; + data[7] = utc_offset; + return GetLength(date, data, tz_name); + } + return constant_size; +} + +char *StrfTimeFormat::WriteString(char *target, const string_t &str) const { idx_t size = str.GetSize(); memcpy(target, str.GetData(), size); return target + size; } // write a value in the range of 0..99 unpadded (e.g. "1", "2", ... "98", "99") -char *StrfTimeFormat::Write2(char *target, uint8_t value) { +char *StrfTimeFormat::Write2(char *target, uint8_t value) const { D_ASSERT(value < 100); if (value >= 10) { return WritePadded2(target, value); @@ -171,7 +185,7 @@ char *StrfTimeFormat::Write2(char *target, uint8_t value) { } // write a value in the range of 0..99 padded to 2 digits -char *StrfTimeFormat::WritePadded2(char *target, uint32_t value) { +char *StrfTimeFormat::WritePadded2(char *target, uint32_t value) const { D_ASSERT(value < 100); auto index = static_cast(value * 2); *target++ = duckdb_fmt::internal::data::digits[index]; @@ -180,7 +194,7 @@ char *StrfTimeFormat::WritePadded2(char *target, uint32_t value) { } // write a value in the range of 0..999 padded -char *StrfTimeFormat::WritePadded3(char *target, uint32_t value) { +char *StrfTimeFormat::WritePadded3(char *target, uint32_t value) const { D_ASSERT(value < 1000); if (value >= 100) { WritePadded2(target + 1, value % 100); @@ -194,7 +208,7 @@ char *StrfTimeFormat::WritePadded3(char *target, uint32_t value) { } // write a value in the range of 0..999999... padded to the given number of digits -char *StrfTimeFormat::WritePadded(char *target, uint32_t value, size_t padding) { +char *StrfTimeFormat::WritePadded(char *target, uint32_t value, size_t padding) const { D_ASSERT(padding > 1); if (padding % 2) { int decimals = value % 1000; @@ -228,7 +242,7 @@ bool StrfTimeFormat::IsDateSpecifier(StrTimeSpecifier specifier) { } } -char *StrfTimeFormat::WriteDateSpecifier(StrTimeSpecifier specifier, date_t date, char *target) { +char *StrfTimeFormat::WriteDateSpecifier(StrTimeSpecifier specifier, date_t date, char *target) const { switch (specifier) { case StrTimeSpecifier::ABBREVIATED_WEEKDAY_NAME: { auto dow = Date::ExtractISODayOfTheWeek(date); @@ -280,8 +294,8 @@ char *StrfTimeFormat::WriteDateSpecifier(StrTimeSpecifier specifier, date_t date } char *StrfTimeFormat::WriteStandardSpecifier(StrTimeSpecifier specifier, int32_t data[], const char *tz_name, - size_t tz_len, char *target) { - // data contains [0] year, [1] month, [2] day, [3] hour, [4] minute, [5] second, [6] msec, [7] utc + size_t tz_len, char *target) const { + // data contains [0] year, [1] month, [2] day, [3] hour, [4] minute, [5] second, [6] ns, [7] utc switch (specifier) { case StrTimeSpecifier::DAY_OF_MONTH_PADDED: target = WritePadded2(target, UnsafeNumericCast(data[2])); @@ -339,13 +353,13 @@ char *StrfTimeFormat::WriteStandardSpecifier(StrTimeSpecifier specifier, int32_t target = WritePadded2(target, UnsafeNumericCast(data[5])); break; case StrTimeSpecifier::NANOSECOND_PADDED: - target = WritePadded(target, UnsafeNumericCast(data[6] * Interval::NANOS_PER_MICRO), 9); + target = WritePadded(target, UnsafeNumericCast(data[6]), 9); break; case StrTimeSpecifier::MICROSECOND_PADDED: - target = WritePadded(target, UnsafeNumericCast(data[6]), 6); + target = WritePadded(target, UnsafeNumericCast(data[6] / Interval::NANOS_PER_MICRO), 6); break; case StrTimeSpecifier::MILLISECOND_PADDED: - target = WritePadded3(target, UnsafeNumericCast(data[6] / Interval::MICROS_PER_MSEC)); + target = WritePadded3(target, UnsafeNumericCast(data[6] / Interval::NANOS_PER_MSEC)); break; case StrTimeSpecifier::UTC_OFFSET: { *target++ = (data[7] < 0) ? '-' : '+'; @@ -404,7 +418,7 @@ char *StrfTimeFormat::WriteStandardSpecifier(StrTimeSpecifier specifier, int32_t return target; } -void StrfTimeFormat::FormatString(date_t date, int32_t data[8], const char *tz_name, char *target) { +void StrfTimeFormat::FormatStringNS(date_t date, int32_t data[8], const char *tz_name, char *target) const { D_ASSERT(specifiers.size() + 1 == literals.size()); idx_t i; for (i = 0; i < specifiers.size(); i++) { @@ -423,6 +437,12 @@ void StrfTimeFormat::FormatString(date_t date, int32_t data[8], const char *tz_n memcpy(target, literals[i].c_str(), literals[i].size()); } +void StrfTimeFormat::FormatString(date_t date, int32_t data[8], const char *tz_name, char *target) { + data[6] *= Interval::NANOS_PER_MICRO; + FormatStringNS(date, data, tz_name, target); + data[6] /= Interval::NANOS_PER_MICRO; +} + void StrfTimeFormat::FormatString(date_t date, dtime_t time, char *target) { int32_t data[8]; // year, month, day, hour, min, sec, µs, offset Date::Convert(date, data[0], data[1], data[2]); @@ -650,24 +670,68 @@ void StrfTimeFormat::ConvertDateVector(Vector &input, Vector &result, idx_t coun }); } +string_t StrfTimeFormat::ConvertTimestampValue(const timestamp_t &input, Vector &result) const { + if (Timestamp::IsFinite(input)) { + date_t date; + dtime_t time; + Timestamp::Convert(input, date, time); + + int32_t data[8]; // year, month, day, hour, min, sec, ns, offset + Date::Convert(date, data[0], data[1], data[2]); + Time::Convert(time, data[3], data[4], data[5], data[6]); + data[6] *= Interval::NANOS_PER_MICRO; + data[7] = 0; + const char *tz_name = nullptr; + + idx_t len = GetLength(date, data, tz_name); + string_t target = StringVector::EmptyString(result, len); + FormatStringNS(date, data, tz_name, target.GetDataWriteable()); + target.Finalize(); + return target; + } else { + return StringVector::AddString(result, Timestamp::ToString(input)); + } +} + +string_t StrfTimeFormat::ConvertTimestampValue(const timestamp_ns_t &input, Vector &result) const { + if (Timestamp::IsFinite(input)) { + date_t date; + dtime_t time; + int32_t nanos; + Timestamp::Convert(input, date, time, nanos); + + int32_t data[8]; // year, month, day, hour, min, sec, ns, offset + Date::Convert(date, data[0], data[1], data[2]); + Time::Convert(time, data[3], data[4], data[5], data[6]); + data[6] *= Interval::NANOS_PER_MICRO; + data[6] += nanos; + data[7] = 0; + const char *tz_name = nullptr; + + idx_t len = GetLength(date, data, tz_name); + string_t target = StringVector::EmptyString(result, len); + FormatStringNS(date, data, tz_name, target.GetDataWriteable()); + target.Finalize(); + return target; + } else { + return StringVector::AddString(result, Timestamp::ToString(input)); + } +} + void StrfTimeFormat::ConvertTimestampVector(Vector &input, Vector &result, idx_t count) { D_ASSERT(input.GetType().id() == LogicalTypeId::TIMESTAMP || input.GetType().id() == LogicalTypeId::TIMESTAMP_TZ); D_ASSERT(result.GetType().id() == LogicalTypeId::VARCHAR); UnaryExecutor::ExecuteWithNulls( - input, result, count, [&](timestamp_t input, ValidityMask &mask, idx_t idx) { - if (Timestamp::IsFinite(input)) { - date_t date; - dtime_t time; - Timestamp::Convert(input, date, time); - idx_t len = GetLength(date, time, 0, nullptr); - string_t target = StringVector::EmptyString(result, len); - FormatString(date, time, target.GetDataWriteable()); - target.Finalize(); - return target; - } else { - return StringVector::AddString(result, Timestamp::ToString(input)); - } - }); + input, result, count, + [&](timestamp_t input, ValidityMask &mask, idx_t idx) { return ConvertTimestampValue(input, result); }); +} + +void StrfTimeFormat::ConvertTimestampNSVector(Vector &input, Vector &result, idx_t count) { + D_ASSERT(input.GetType().id() == LogicalTypeId::TIMESTAMP_NS); + D_ASSERT(result.GetType().id() == LogicalTypeId::VARCHAR); + UnaryExecutor::ExecuteWithNulls( + input, result, count, + [&](timestamp_ns_t input, ValidityMask &mask, idx_t idx) { return ConvertTimestampValue(input, result); }); } void StrpTimeFormat::AddFormatSpecifier(string preceding_literal, StrTimeSpecifier specifier) { @@ -1000,19 +1064,18 @@ bool StrpTimeFormat::Parse(const char *data, size_t size, ParseResult &result) c break; case StrTimeSpecifier::NANOSECOND_PADDED: D_ASSERT(number < Interval::NANOS_PER_SEC); // enforced by the length of the number - // microseconds (rounded) - result_data[6] = - UnsafeNumericCast((number + Interval::NANOS_PER_MICRO / 2) / Interval::NANOS_PER_MICRO); + // nanoseconds + result_data[6] = UnsafeNumericCast(number); break; case StrTimeSpecifier::MICROSECOND_PADDED: D_ASSERT(number < Interval::MICROS_PER_SEC); // enforced by the length of the number - // microseconds - result_data[6] = UnsafeNumericCast(number); + // nanoseconds + result_data[6] = UnsafeNumericCast(number * Interval::NANOS_PER_MICRO); break; case StrTimeSpecifier::MILLISECOND_PADDED: D_ASSERT(number < Interval::MSECS_PER_SEC); // enforced by the length of the number - // microseconds - result_data[6] = UnsafeNumericCast(number * Interval::MICROS_PER_MSEC); + // nanoseconds + result_data[6] = UnsafeNumericCast(number * Interval::NANOS_PER_MSEC); break; case StrTimeSpecifier::WEEK_NUMBER_PADDED_SUN_FIRST: case StrTimeSpecifier::WEEK_NUMBER_PADDED_MON_FIRST: @@ -1366,17 +1429,27 @@ bool StrpTimeFormat::ParseResult::TryToDate(date_t &result) { return Date::TryFromDate(data[0], data[1], data[2], result); } +int32_t StrpTimeFormat::ParseResult::GetMicros() const { + return (data[6] + Interval::NANOS_PER_MICRO / 2) / Interval::NANOS_PER_MICRO; +} + dtime_t StrpTimeFormat::ParseResult::ToTime() { const auto hour_offset = data[7] / Interval::MINS_PER_HOUR; const auto mins_offset = data[7] % Interval::MINS_PER_HOUR; - return Time::FromTime(data[3] - hour_offset, data[4] - mins_offset, data[5], data[6]); + return Time::FromTime(data[3] - hour_offset, data[4] - mins_offset, data[5], GetMicros()); +} + +int64_t StrpTimeFormat::ParseResult::ToTimeNS() { + const int32_t hour_offset = data[7] / Interval::MINS_PER_HOUR; + const int32_t mins_offset = data[7] % Interval::MINS_PER_HOUR; + return Time::ToNanoTime(data[3] - hour_offset, data[4] - mins_offset, data[5], data[6]); } bool StrpTimeFormat::ParseResult::TryToTime(dtime_t &result) { if (data[7]) { return false; } - result = Time::FromTime(data[3], data[4], data[5], data[6]); + result = Time::FromTime(data[3], data[4], data[5], GetMicros()); return true; } @@ -1390,7 +1463,7 @@ timestamp_t StrpTimeFormat::ParseResult::ToTimestamp() { return Timestamp::FromDatetime(special, dtime_t(0)); } - date_t date = Date::FromDate(data[0], data[1], data[2]); + date_t date = ToDate(); dtime_t time = ToTime(); return Timestamp::FromDatetime(date, time); } @@ -1404,6 +1477,49 @@ bool StrpTimeFormat::ParseResult::TryToTimestamp(timestamp_t &result) { return Timestamp::TryFromDatetime(date, time, result); } +timestamp_ns_t StrpTimeFormat::ParseResult::ToTimestampNS() { + timestamp_ns_t result; + if (is_special) { + if (special == date_t::infinity()) { + result.value = timestamp_t::infinity().value; + } else if (special == date_t::ninfinity()) { + result.value = timestamp_t::ninfinity().value; + } else { + result.value = special.days * Interval::NANOS_PER_DAY; + } + } else { + // Don't use rounded µs + const auto date = ToDate(); + const auto time = ToTimeNS(); + if (!TryMultiplyOperator::Operation(date.days, Interval::NANOS_PER_DAY, + result.value)) { + throw ConversionException("Date out of nanosecond range: %d-%d-%d", data[0], data[1], data[2]); + } + if (!TryAddOperator::Operation(result.value, time, result.value)) { + throw ConversionException("Overflow exception in date/time -> timestamp_ns conversion"); + } + } + + return result; +} + +bool StrpTimeFormat::ParseResult::TryToTimestampNS(timestamp_ns_t &result) { + date_t date; + if (!TryToDate(date)) { + return false; + } + + // Don't use rounded µs + const auto time = ToTimeNS(); + if (!TryMultiplyOperator::Operation(date.days, Interval::NANOS_PER_DAY, result.value)) { + return false; + } + if (!TryAddOperator::Operation(result.value, time, result.value)) { + return false; + } + return Timestamp::IsFinite(result); +} + string StrpTimeFormat::ParseResult::FormatError(string_t input, const string &format_specifier) { return StringUtil::Format("Could not parse string \"%s\" according to format specifier \"%s\"\n%s\nError: %s", input.GetString(), format_specifier, @@ -1453,4 +1569,21 @@ bool StrpTimeFormat::TryParseTimestamp(const char *data, size_t size, timestamp_ return parse_result.TryToTimestamp(result); } +bool StrpTimeFormat::TryParseTimestampNS(string_t input, timestamp_ns_t &result, string &error_message) const { + ParseResult parse_result; + if (!Parse(input, parse_result)) { + error_message = parse_result.FormatError(input, format_specifier); + return false; + } + return parse_result.TryToTimestampNS(result); +} + +bool StrpTimeFormat::TryParseTimestampNS(const char *data, size_t size, timestamp_ns_t &result) const { + ParseResult parse_result; + if (!Parse(data, size, parse_result)) { + return false; + } + return parse_result.TryToTimestampNS(result); +} + } // namespace duckdb diff --git a/src/function/scalar/string/CMakeLists.txt b/src/function/scalar/string/CMakeLists.txt index 360f7b38458..1de617f5c4d 100644 --- a/src/function/scalar/string/CMakeLists.txt +++ b/src/function/scalar/string/CMakeLists.txt @@ -4,6 +4,7 @@ add_library_unity( OBJECT caseconvert.cpp concat.cpp + concat_ws.cpp length.cpp like.cpp nfc_normalize.cpp diff --git a/src/function/scalar/string/caseconvert.cpp b/src/function/scalar/string/caseconvert.cpp index fa5b612f186..b6240d0624d 100644 --- a/src/function/scalar/string/caseconvert.cpp +++ b/src/function/scalar/string/caseconvert.cpp @@ -5,7 +5,7 @@ #include "duckdb/common/vector_operations/unary_executor.hpp" #include "duckdb/planner/expression/bound_function_expression.hpp" -#include "utf8proc.hpp" +#include "utf8proc_wrapper.hpp" #include @@ -58,9 +58,10 @@ static idx_t GetResultLength(const char *input_data, idx_t input_length) { if (input_data[i] & 0x80) { // unicode int sz = 0; - auto codepoint = utf8proc_codepoint(input_data + i, sz); - auto converted_codepoint = IS_UPPER ? utf8proc_toupper(codepoint) : utf8proc_tolower(codepoint); - auto new_sz = utf8proc_codepoint_length(converted_codepoint); + auto codepoint = Utf8Proc::UTF8ToCodepoint(input_data + i, sz); + auto converted_codepoint = + IS_UPPER ? Utf8Proc::CodepointToUpper(codepoint) : Utf8Proc::CodepointToLower(codepoint); + auto new_sz = Utf8Proc::CodepointLength(converted_codepoint); D_ASSERT(new_sz >= 0); output_length += UnsafeNumericCast(new_sz); i += UnsafeNumericCast(sz); @@ -79,9 +80,10 @@ static void CaseConvert(const char *input_data, idx_t input_length, char *result if (input_data[i] & 0x80) { // non-ascii character int sz = 0, new_sz = 0; - auto codepoint = utf8proc_codepoint(input_data + i, sz); - auto converted_codepoint = IS_UPPER ? utf8proc_toupper(codepoint) : utf8proc_tolower(codepoint); - auto success = utf8proc_codepoint_to_utf8(converted_codepoint, new_sz, result_data); + auto codepoint = Utf8Proc::UTF8ToCodepoint(input_data + i, sz); + auto converted_codepoint = + IS_UPPER ? Utf8Proc::CodepointToUpper(codepoint) : Utf8Proc::CodepointToLower(codepoint); + auto success = Utf8Proc::CodepointToUtf8(converted_codepoint, new_sz, result_data); D_ASSERT(success); (void)success; result_data += new_sz; diff --git a/src/function/scalar/string/concat.cpp b/src/function/scalar/string/concat.cpp index 5ad0c9a3ede..9f78af9a23e 100644 --- a/src/function/scalar/string/concat.cpp +++ b/src/function/scalar/string/concat.cpp @@ -4,12 +4,41 @@ #include "duckdb/common/vector_operations/vector_operations.hpp" #include "duckdb/function/scalar/nested_functions.hpp" #include "duckdb/function/scalar/string_functions.hpp" +#include "duckdb/planner/expression/bound_cast_expression.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" #include namespace duckdb { -static void ConcatFunction(DataChunk &args, ExpressionState &state, Vector &result) { +struct ConcatFunctionData : public FunctionData { + ConcatFunctionData(const LogicalType &return_type_p, bool is_operator_p) + : return_type(return_type_p), is_operator(is_operator_p) { + } + ~ConcatFunctionData() override; + + LogicalType return_type; + + bool is_operator = false; + +public: + bool Equals(const FunctionData &other_p) const override; + unique_ptr Copy() const override; +}; + +ConcatFunctionData::~ConcatFunctionData() { +} + +bool ConcatFunctionData::Equals(const FunctionData &other_p) const { + auto &other = other_p.Cast(); + return return_type == other.return_type && is_operator == other.is_operator; +} + +unique_ptr ConcatFunctionData::Copy() const { + return make_uniq(return_type, is_operator); +} + +static void StringConcatFunction(DataChunk &args, ExpressionState &state, Vector &result) { result.SetVectorType(VectorType::CONSTANT_VECTOR); // iterate over the vectors to count how large the final string will be idx_t constant_lengths = 0; @@ -114,130 +143,224 @@ static void ConcatOperator(DataChunk &args, ExpressionState &state, Vector &resu }); } -static void TemplatedConcatWS(DataChunk &args, const string_t *sep_data, const SelectionVector &sep_sel, - const SelectionVector &rsel, idx_t count, Vector &result) { - vector result_lengths(args.size(), 0); - vector has_results(args.size(), false); - - // we overallocate here, but this is important for static analysis - auto orrified_data = make_unsafe_uniq_array(args.ColumnCount()); +static void ListConcatFunction(DataChunk &args, ExpressionState &state, Vector &result) { + D_ASSERT(args.ColumnCount() == 2); + auto count = args.size(); - for (idx_t col_idx = 1; col_idx < args.ColumnCount(); col_idx++) { - args.data[col_idx].ToUnifiedFormat(args.size(), orrified_data[col_idx - 1]); + Vector &lhs = args.data[0]; + Vector &rhs = args.data[1]; + if (lhs.GetType().id() == LogicalTypeId::SQLNULL) { + result.Reference(rhs); + return; + } + if (rhs.GetType().id() == LogicalTypeId::SQLNULL) { + result.Reference(lhs); + return; } - // first figure out the lengths - for (idx_t col_idx = 1; col_idx < args.ColumnCount(); col_idx++) { - auto &idata = orrified_data[col_idx - 1]; + UnifiedVectorFormat lhs_data; + UnifiedVectorFormat rhs_data; + lhs.ToUnifiedFormat(count, lhs_data); + rhs.ToUnifiedFormat(count, rhs_data); + auto lhs_entries = UnifiedVectorFormat::GetData(lhs_data); + auto rhs_entries = UnifiedVectorFormat::GetData(rhs_data); - auto input_data = UnifiedVectorFormat::GetData(idata); - for (idx_t i = 0; i < count; i++) { - auto ridx = rsel.get_index(i); - auto sep_idx = sep_sel.get_index(ridx); - auto idx = idata.sel->get_index(ridx); - if (!idata.validity.RowIsValid(idx)) { - continue; - } - if (has_results[ridx]) { - result_lengths[ridx] += sep_data[sep_idx].GetSize(); - } - result_lengths[ridx] += input_data[idx].GetSize(); - has_results[ridx] = true; + auto lhs_list_size = ListVector::GetListSize(lhs); + auto rhs_list_size = ListVector::GetListSize(rhs); + auto &lhs_child = ListVector::GetEntry(lhs); + auto &rhs_child = ListVector::GetEntry(rhs); + UnifiedVectorFormat lhs_child_data; + UnifiedVectorFormat rhs_child_data; + lhs_child.ToUnifiedFormat(lhs_list_size, lhs_child_data); + rhs_child.ToUnifiedFormat(rhs_list_size, rhs_child_data); + + result.SetVectorType(VectorType::FLAT_VECTOR); + auto result_entries = FlatVector::GetData(result); + auto &result_validity = FlatVector::Validity(result); + + idx_t offset = 0; + for (idx_t i = 0; i < count; i++) { + auto lhs_list_index = lhs_data.sel->get_index(i); + auto rhs_list_index = rhs_data.sel->get_index(i); + if (!lhs_data.validity.RowIsValid(lhs_list_index) && !rhs_data.validity.RowIsValid(rhs_list_index)) { + result_validity.SetInvalid(i); + continue; } + result_entries[i].offset = offset; + result_entries[i].length = 0; + if (lhs_data.validity.RowIsValid(lhs_list_index)) { + const auto &lhs_entry = lhs_entries[lhs_list_index]; + result_entries[i].length += lhs_entry.length; + ListVector::Append(result, lhs_child, *lhs_child_data.sel, lhs_entry.offset + lhs_entry.length, + lhs_entry.offset); + } + if (rhs_data.validity.RowIsValid(rhs_list_index)) { + const auto &rhs_entry = rhs_entries[rhs_list_index]; + result_entries[i].length += rhs_entry.length; + ListVector::Append(result, rhs_child, *rhs_child_data.sel, rhs_entry.offset + rhs_entry.length, + rhs_entry.offset); + } + offset += result_entries[i].length; } + D_ASSERT(ListVector::GetListSize(result) == offset); - // first we allocate the empty strings for each of the values - auto result_data = FlatVector::GetData(result); - for (idx_t i = 0; i < count; i++) { - auto ridx = rsel.get_index(i); - // allocate an empty string of the required size - result_data[ridx] = StringVector::EmptyString(result, result_lengths[ridx]); - // we reuse the result_lengths vector to store the currently appended size - result_lengths[ridx] = 0; - has_results[ridx] = false; + if (lhs.GetVectorType() == VectorType::CONSTANT_VECTOR && rhs.GetVectorType() == VectorType::CONSTANT_VECTOR) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); } +} - // now that the empty space for the strings has been allocated, perform the concatenation - for (idx_t col_idx = 1; col_idx < args.ColumnCount(); col_idx++) { - auto &idata = orrified_data[col_idx - 1]; - auto input_data = UnifiedVectorFormat::GetData(idata); - for (idx_t i = 0; i < count; i++) { - auto ridx = rsel.get_index(i); - auto sep_idx = sep_sel.get_index(ridx); - auto idx = idata.sel->get_index(ridx); - if (!idata.validity.RowIsValid(idx)) { - continue; - } - if (has_results[ridx]) { - auto sep_size = sep_data[sep_idx].GetSize(); - auto sep_ptr = sep_data[sep_idx].GetData(); - memcpy(result_data[ridx].GetDataWriteable() + result_lengths[ridx], sep_ptr, sep_size); - result_lengths[ridx] += sep_size; - } - auto input_ptr = input_data[idx].GetData(); - auto input_len = input_data[idx].GetSize(); - memcpy(result_data[ridx].GetDataWriteable() + result_lengths[ridx], input_ptr, input_len); - result_lengths[ridx] += input_len; - has_results[ridx] = true; - } +static void ConcatFunction(DataChunk &args, ExpressionState &state, Vector &result) { + auto &func_expr = state.expr.Cast(); + auto &info = func_expr.bind_info->Cast(); + if (info.return_type.id() == LogicalTypeId::LIST) { + return ListConcatFunction(args, state, result); + } else if (info.is_operator) { + return ConcatOperator(args, state, result); } - for (idx_t i = 0; i < count; i++) { - auto ridx = rsel.get_index(i); - result_data[ridx].Finalize(); + return StringConcatFunction(args, state, result); +} + +static void SetArgumentType(ScalarFunction &bound_function, const LogicalType &type, bool is_operator) { + if (is_operator) { + bound_function.arguments[0] = type; + bound_function.arguments[1] = type; + bound_function.return_type = type; + return; + } + + for (auto &arg : bound_function.arguments) { + arg = type; + } + bound_function.varargs = type; + bound_function.return_type = type; +} + +static void HandleArrayBinding(ClientContext &context, vector> &arguments) { + if (arguments[1]->return_type.id() != LogicalTypeId::ARRAY && + arguments[1]->return_type.id() != LogicalTypeId::SQLNULL) { + throw BinderException("Cannot concatenate types %s and %s", arguments[0]->return_type.ToString(), + arguments[1]->return_type.ToString()); } + + // if either argument is an array, we cast it to a list + arguments[0] = BoundCastExpression::AddArrayCastToList(context, std::move(arguments[0])); + arguments[1] = BoundCastExpression::AddArrayCastToList(context, std::move(arguments[1])); } -static void ConcatWSFunction(DataChunk &args, ExpressionState &state, Vector &result) { - auto &separator = args.data[0]; - UnifiedVectorFormat vdata; - separator.ToUnifiedFormat(args.size(), vdata); +static unique_ptr HandleListBinding(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments, bool is_operator) { + // list_concat only accepts two arguments + D_ASSERT(arguments.size() == 2); - result.SetVectorType(VectorType::CONSTANT_VECTOR); - for (idx_t col_idx = 0; col_idx < args.ColumnCount(); col_idx++) { - if (args.data[col_idx].GetVectorType() != VectorType::CONSTANT_VECTOR) { - result.SetVectorType(VectorType::FLAT_VECTOR); - break; - } + auto &lhs = arguments[0]->return_type; + auto &rhs = arguments[1]->return_type; + + if (lhs.id() == LogicalTypeId::UNKNOWN || rhs.id() == LogicalTypeId::UNKNOWN) { + throw ParameterNotResolvedException(); + } else if (lhs.id() == LogicalTypeId::SQLNULL || rhs.id() == LogicalTypeId::SQLNULL) { + // we mimic postgres behaviour: list_concat(NULL, my_list) = my_list + auto return_type = rhs.id() == LogicalTypeId::SQLNULL ? lhs : rhs; + SetArgumentType(bound_function, return_type, is_operator); + return make_uniq(bound_function.return_type, is_operator); } - switch (separator.GetVectorType()) { - case VectorType::CONSTANT_VECTOR: { - if (ConstantVector::IsNull(separator)) { - // constant NULL as separator: return constant NULL vector - result.SetVectorType(VectorType::CONSTANT_VECTOR); - ConstantVector::SetNull(result, true); - return; - } - // no null values - auto sel = FlatVector::IncrementalSelectionVector(); - TemplatedConcatWS(args, UnifiedVectorFormat::GetData(vdata), *vdata.sel, *sel, args.size(), result); - return; + if (lhs.id() != LogicalTypeId::LIST || rhs.id() != LogicalTypeId::LIST) { + throw BinderException("Cannot concatenate types %s and %s", lhs.ToString(), rhs.ToString()); } - default: { - // default case: loop over nullmask and create a non-null selection vector - idx_t not_null_count = 0; - SelectionVector not_null_vector(STANDARD_VECTOR_SIZE); - auto &result_mask = FlatVector::Validity(result); - for (idx_t i = 0; i < args.size(); i++) { - if (!vdata.validity.RowIsValid(vdata.sel->get_index(i))) { - result_mask.SetInvalid(i); - } else { - not_null_vector.set_index(not_null_count++, i); - } + + // Resolve list type + LogicalType child_type = LogicalType::SQLNULL; + for (const auto &argument : arguments) { + auto &next_type = ListType::GetChildType(argument->return_type); + if (!LogicalType::TryGetMaxLogicalType(context, child_type, next_type, child_type)) { + throw BinderException("Cannot concatenate lists of types %s[] and %s[] - an explicit cast is required", + child_type.ToString(), next_type.ToString()); } - TemplatedConcatWS(args, UnifiedVectorFormat::GetData(vdata), *vdata.sel, not_null_vector, - not_null_count, result); - return; } + auto list_type = LogicalType::LIST(child_type); + + SetArgumentType(bound_function, list_type, is_operator); + return make_uniq(bound_function.return_type, is_operator); +} + +static void FindFirstTwoArguments(vector> &arguments, LogicalTypeId &first_arg, + LogicalTypeId &second_arg) { + first_arg = arguments[0]->return_type.id(); + second_arg = first_arg; + if (arguments.size() > 1) { + second_arg = arguments[1]->return_type.id(); } } static unique_ptr BindConcatFunction(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { - for (auto &arg : bound_function.arguments) { - arg = LogicalType::VARCHAR; + LogicalTypeId first_arg; + LogicalTypeId second_arg; + FindFirstTwoArguments(arguments, first_arg, second_arg); + + if (arguments.size() > 2 && (first_arg == LogicalTypeId::ARRAY || first_arg == LogicalTypeId::LIST)) { + throw BinderException("list_concat only accepts two arguments"); } - bound_function.varargs = LogicalType::VARCHAR; - return nullptr; + + if (first_arg == LogicalTypeId::ARRAY || second_arg == LogicalTypeId::ARRAY) { + HandleArrayBinding(context, arguments); + FindFirstTwoArguments(arguments, first_arg, second_arg); + } + + if (first_arg == LogicalTypeId::LIST || second_arg == LogicalTypeId::LIST) { + return HandleListBinding(context, bound_function, arguments, false); + } + + // we can now assume that the input is a string or castable to a string + SetArgumentType(bound_function, LogicalType::VARCHAR, false); + return make_uniq(bound_function.return_type, false); +} + +static unique_ptr BindConcatOperator(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + D_ASSERT(arguments.size() == 2); + + LogicalTypeId lhs; + LogicalTypeId rhs; + FindFirstTwoArguments(arguments, lhs, rhs); + + if (lhs == LogicalTypeId::ARRAY || rhs == LogicalTypeId::ARRAY) { + HandleArrayBinding(context, arguments); + FindFirstTwoArguments(arguments, lhs, rhs); + } + + if (lhs == LogicalTypeId::LIST || rhs == LogicalTypeId::LIST) { + return HandleListBinding(context, bound_function, arguments, true); + } + + // we can now assume that the input is a string or castable to a string + SetArgumentType(bound_function, LogicalType::VARCHAR, true); + return make_uniq(bound_function.return_type, true); +} + +static unique_ptr ListConcatStats(ClientContext &context, FunctionStatisticsInput &input) { + auto &child_stats = input.child_stats; + D_ASSERT(child_stats.size() == 2); + + auto &left_stats = child_stats[0]; + auto &right_stats = child_stats[1]; + + auto stats = left_stats.ToUnique(); + stats->Merge(right_stats); + + return stats; +} + +ScalarFunction ListConcatFun::GetFunction() { + // The arguments and return types are set in the binder function. + auto fun = ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::LIST(LogicalType::ANY)}, + LogicalType::LIST(LogicalType::ANY), ConcatFunction, BindConcatFunction, nullptr, + ListConcatStats); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + return fun; +} + +void ListConcatFun::RegisterFunction(BuiltinFunctions &set) { + set.AddFunction({"list_concat", "list_cat", "array_concat", "array_cat"}, GetFunction()); } void ConcatFun::RegisterFunction(BuiltinFunctions &set) { @@ -249,34 +372,17 @@ void ConcatFun::RegisterFunction(BuiltinFunctions &set) { // i.e. NULL || 'hello' = NULL // the concat function, however, treats NULL values as an empty string // i.e. concat(NULL, 'hello') = 'hello' - // concat_ws functions similarly to the concat function, except the result is NULL if the separator is NULL - // if the separator is not NULL, however, NULL values are counted as empty string - // there is one separate rule: there are no separators added between NULL values - // so the NULL value and empty string are different! - // e.g.: - // concat_ws(',', NULL, NULL) = "" - // concat_ws(',', '', '') = "," + ScalarFunction concat = - ScalarFunction("concat", {LogicalType::ANY}, LogicalType::VARCHAR, ConcatFunction, BindConcatFunction); + ScalarFunction("concat", {LogicalType::ANY}, LogicalType::ANY, ConcatFunction, BindConcatFunction); concat.varargs = LogicalType::ANY; concat.null_handling = FunctionNullHandling::SPECIAL_HANDLING; set.AddFunction(concat); - ScalarFunctionSet concat_op("||"); - concat_op.AddFunction( - ScalarFunction({LogicalType::ANY, LogicalType::ANY}, LogicalType::VARCHAR, ConcatOperator, BindConcatFunction)); - concat_op.AddFunction(ScalarFunction({LogicalType::BLOB, LogicalType::BLOB}, LogicalType::BLOB, ConcatOperator)); - concat_op.AddFunction(ListConcatFun::GetFunction()); - for (auto &fun : concat_op.functions) { - fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; - } + ScalarFunction concat_op = ScalarFunction("||", {LogicalType::ANY, LogicalType::ANY}, LogicalType::ANY, + ConcatFunction, BindConcatOperator); + concat.null_handling = FunctionNullHandling::SPECIAL_HANDLING; set.AddFunction(concat_op); - - ScalarFunction concat_ws = ScalarFunction("concat_ws", {LogicalType::VARCHAR, LogicalType::ANY}, - LogicalType::VARCHAR, ConcatWSFunction, BindConcatFunction); - concat_ws.varargs = LogicalType::ANY; - concat_ws.null_handling = FunctionNullHandling::SPECIAL_HANDLING; - set.AddFunction(concat_ws); } } // namespace duckdb diff --git a/src/function/scalar/string/concat_ws.cpp b/src/function/scalar/string/concat_ws.cpp new file mode 100644 index 00000000000..873eb56d0d7 --- /dev/null +++ b/src/function/scalar/string/concat_ws.cpp @@ -0,0 +1,149 @@ +#include "duckdb/function/scalar/string_functions.hpp" + +#include + +namespace duckdb { + +static void TemplatedConcatWS(DataChunk &args, const string_t *sep_data, const SelectionVector &sep_sel, + const SelectionVector &rsel, idx_t count, Vector &result) { + vector result_lengths(args.size(), 0); + vector has_results(args.size(), false); + + // we overallocate here, but this is important for static analysis + auto orrified_data = make_unsafe_uniq_array(args.ColumnCount()); + + for (idx_t col_idx = 1; col_idx < args.ColumnCount(); col_idx++) { + args.data[col_idx].ToUnifiedFormat(args.size(), orrified_data[col_idx - 1]); + } + + // first figure out the lengths + for (idx_t col_idx = 1; col_idx < args.ColumnCount(); col_idx++) { + auto &idata = orrified_data[col_idx - 1]; + + auto input_data = UnifiedVectorFormat::GetData(idata); + for (idx_t i = 0; i < count; i++) { + auto ridx = rsel.get_index(i); + auto sep_idx = sep_sel.get_index(ridx); + auto idx = idata.sel->get_index(ridx); + if (!idata.validity.RowIsValid(idx)) { + continue; + } + if (has_results[ridx]) { + result_lengths[ridx] += sep_data[sep_idx].GetSize(); + } + result_lengths[ridx] += input_data[idx].GetSize(); + has_results[ridx] = true; + } + } + + // first we allocate the empty strings for each of the values + auto result_data = FlatVector::GetData(result); + for (idx_t i = 0; i < count; i++) { + auto ridx = rsel.get_index(i); + // allocate an empty string of the required size + result_data[ridx] = StringVector::EmptyString(result, result_lengths[ridx]); + // we reuse the result_lengths vector to store the currently appended size + result_lengths[ridx] = 0; + has_results[ridx] = false; + } + + // now that the empty space for the strings has been allocated, perform the concatenation + for (idx_t col_idx = 1; col_idx < args.ColumnCount(); col_idx++) { + auto &idata = orrified_data[col_idx - 1]; + auto input_data = UnifiedVectorFormat::GetData(idata); + for (idx_t i = 0; i < count; i++) { + auto ridx = rsel.get_index(i); + auto sep_idx = sep_sel.get_index(ridx); + auto idx = idata.sel->get_index(ridx); + if (!idata.validity.RowIsValid(idx)) { + continue; + } + if (has_results[ridx]) { + auto sep_size = sep_data[sep_idx].GetSize(); + auto sep_ptr = sep_data[sep_idx].GetData(); + memcpy(result_data[ridx].GetDataWriteable() + result_lengths[ridx], sep_ptr, sep_size); + result_lengths[ridx] += sep_size; + } + auto input_ptr = input_data[idx].GetData(); + auto input_len = input_data[idx].GetSize(); + memcpy(result_data[ridx].GetDataWriteable() + result_lengths[ridx], input_ptr, input_len); + result_lengths[ridx] += input_len; + has_results[ridx] = true; + } + } + for (idx_t i = 0; i < count; i++) { + auto ridx = rsel.get_index(i); + result_data[ridx].Finalize(); + } +} + +static void ConcatWSFunction(DataChunk &args, ExpressionState &state, Vector &result) { + auto &separator = args.data[0]; + UnifiedVectorFormat vdata; + separator.ToUnifiedFormat(args.size(), vdata); + + result.SetVectorType(VectorType::CONSTANT_VECTOR); + for (idx_t col_idx = 0; col_idx < args.ColumnCount(); col_idx++) { + if (args.data[col_idx].GetVectorType() != VectorType::CONSTANT_VECTOR) { + result.SetVectorType(VectorType::FLAT_VECTOR); + break; + } + } + switch (separator.GetVectorType()) { + case VectorType::CONSTANT_VECTOR: { + if (ConstantVector::IsNull(separator)) { + // constant NULL as separator: return constant NULL vector + result.SetVectorType(VectorType::CONSTANT_VECTOR); + ConstantVector::SetNull(result, true); + return; + } + // no null values + auto sel = FlatVector::IncrementalSelectionVector(); + TemplatedConcatWS(args, UnifiedVectorFormat::GetData(vdata), *vdata.sel, *sel, args.size(), result); + return; + } + default: { + // default case: loop over nullmask and create a non-null selection vector + idx_t not_null_count = 0; + SelectionVector not_null_vector(STANDARD_VECTOR_SIZE); + auto &result_mask = FlatVector::Validity(result); + for (idx_t i = 0; i < args.size(); i++) { + if (!vdata.validity.RowIsValid(vdata.sel->get_index(i))) { + result_mask.SetInvalid(i); + } else { + not_null_vector.set_index(not_null_count++, i); + } + } + TemplatedConcatWS(args, UnifiedVectorFormat::GetData(vdata), *vdata.sel, not_null_vector, + not_null_count, result); + return; + } + } +} + +static unique_ptr BindConcatWSFunction(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + for (auto &arg : bound_function.arguments) { + arg = LogicalType::VARCHAR; + } + bound_function.varargs = LogicalType::VARCHAR; + return nullptr; +} + +void ConcatWSFun::RegisterFunction(BuiltinFunctions &set) { + // concat_ws functions similarly to the concat function, except the result is NULL if the separator is NULL + // if the separator is not NULL, however, NULL values are counted as empty string + // there is one separate rule: there are no separators added between NULL values, + // so the NULL value and empty string are different! + // e.g.: + // concat_ws(',', NULL, NULL) = "" + // concat_ws(',', '', '') = "," + + ScalarFunction concat_ws = ScalarFunction("concat_ws", {LogicalType::VARCHAR, LogicalType::ANY}, + LogicalType::VARCHAR, ConcatWSFunction, BindConcatWSFunction); + concat_ws.varargs = LogicalType::ANY; + concat_ws.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + set.AddFunction(concat_ws); +} + +} // namespace duckdb diff --git a/src/function/scalar/string/substring.cpp b/src/function/scalar/string/substring.cpp index 76f4859f273..f7ff13f3499 100644 --- a/src/function/scalar/string/substring.cpp +++ b/src/function/scalar/string/substring.cpp @@ -224,11 +224,7 @@ string_t SubstringFun::SubstringGrapheme(Vector &result, string_t input, int64_t if (offset < 0) { // negative offset, this case is more difficult // we first need to count the number of characters in the string - idx_t num_characters = 0; - utf8proc_grapheme_callback(input_data, input_size, [&](size_t start, size_t end) { - num_characters++; - return true; - }); + idx_t num_characters = Utf8Proc::GraphemeCount(input_data, input_size); // now call substring start and end again, but with the number of unicode characters this time SubstringStartEnd(UnsafeNumericCast(num_characters), offset, length, start, end); } @@ -236,16 +232,15 @@ string_t SubstringFun::SubstringGrapheme(Vector &result, string_t input, int64_t // now scan the graphemes of the string to find the positions of the start and end characters int64_t current_character = 0; idx_t start_pos = DConstants::INVALID_INDEX, end_pos = input_size; - utf8proc_grapheme_callback(input_data, input_size, [&](size_t gstart, size_t gend) { + for (auto cluster : Utf8Proc::GraphemeClusters(input_data, input_size)) { if (current_character == start) { - start_pos = gstart; + start_pos = cluster.start; } else if (current_character == end) { - end_pos = gstart; - return false; + end_pos = cluster.start; + break; } current_character++; - return true; - }); + } if (start_pos == DConstants::INVALID_INDEX) { return SubstringEmptyString(result); } diff --git a/src/function/scalar/string_functions.cpp b/src/function/scalar/string_functions.cpp index 88d7b7169e3..e3ccbe0af9b 100644 --- a/src/function/scalar/string_functions.cpp +++ b/src/function/scalar/string_functions.cpp @@ -7,6 +7,7 @@ void BuiltinFunctions::RegisterStringFunctions() { Register(); Register(); Register(); + Register(); Register(); Register(); Register(); diff --git a/src/function/scalar_function.cpp b/src/function/scalar_function.cpp index ceebf3d5252..75d74cf5097 100644 --- a/src/function/scalar_function.cpp +++ b/src/function/scalar_function.cpp @@ -5,6 +5,9 @@ namespace duckdb { FunctionLocalState::~FunctionLocalState() { } +ScalarFunctionInfo::~ScalarFunctionInfo() { +} + ScalarFunction::ScalarFunction(string name, vector arguments, LogicalType return_type, scalar_function_t function, bind_scalar_function_t bind, dependency_function_t dependency, function_statistics_t statistics, @@ -13,7 +16,8 @@ ScalarFunction::ScalarFunction(string name, vector arguments, Logic : BaseScalarFunction(std::move(name), std::move(arguments), std::move(return_type), side_effects, std::move(varargs), null_handling), function(std::move(function)), bind(bind), init_local_state(init_local_state), dependency(dependency), - statistics(statistics), bind_lambda(bind_lambda), serialize(nullptr), deserialize(nullptr) { + statistics(statistics), bind_lambda(bind_lambda), bind_expression(nullptr), get_modified_databases(nullptr), + serialize(nullptr), deserialize(nullptr) { } ScalarFunction::ScalarFunction(vector arguments, LogicalType return_type, scalar_function_t function, diff --git a/src/function/table/CMakeLists.txt b/src/function/table/CMakeLists.txt index f9c9beabad0..0399da4d1f1 100644 --- a/src/function/table/CMakeLists.txt +++ b/src/function/table/CMakeLists.txt @@ -8,6 +8,7 @@ add_library_unity( arrow_conversion.cpp checkpoint.cpp glob.cpp + query_function.cpp range.cpp repeat.cpp repeat_row.cpp diff --git a/src/function/table/arrow.cpp b/src/function/table/arrow.cpp index f7fe3c48144..220a9d54e73 100644 --- a/src/function/table/arrow.cpp +++ b/src/function/table/arrow.cpp @@ -10,10 +10,25 @@ #include "duckdb/function/table_function.hpp" #include "duckdb/parser/parsed_data/create_table_function_info.hpp" #include "duckdb/function/table/arrow/arrow_duck_schema.hpp" +#include "duckdb/function/table/arrow/arrow_type_info.hpp" +#include "duckdb/parser/tableref/table_function_ref.hpp" #include "utf8proc_wrapper.hpp" namespace duckdb { +static unique_ptr CreateListType(ArrowSchema &child, ArrowVariableSizeType size_type, bool view) { + auto child_type = ArrowTableFunction::GetArrowLogicalType(child); + + unique_ptr type_info; + auto type = LogicalType::LIST(child_type->GetDuckType()); + if (view) { + type_info = ArrowListInfo::ListView(std::move(child_type), size_type); + } else { + type_info = ArrowListInfo::List(std::move(child_type), size_type); + } + return make_uniq(type, std::move(type_info)); +} + static unique_ptr GetArrowLogicalTypeNoDictionary(ArrowSchema &schema) { auto format = string(schema.format); if (format == "n") { @@ -66,9 +81,12 @@ static unique_ptr GetArrowLogicalTypeNoDictionary(ArrowSchema &schema } return make_uniq(LogicalType::DECIMAL(NumericCast(width), NumericCast(scale))); } else if (format == "u") { - return make_uniq(LogicalType::VARCHAR, ArrowVariableSizeType::NORMAL); + return make_uniq(LogicalType::VARCHAR, make_uniq(ArrowVariableSizeType::NORMAL)); } else if (format == "U") { - return make_uniq(LogicalType::VARCHAR, ArrowVariableSizeType::SUPER_SIZE); + return make_uniq(LogicalType::VARCHAR, + make_uniq(ArrowVariableSizeType::SUPER_SIZE)); + } else if (format == "vu") { + return make_uniq(LogicalType::VARCHAR, make_uniq(ArrowVariableSizeType::VIEW)); } else if (format == "tsn:") { return make_uniq(LogicalTypeId::TIMESTAMP_NS); } else if (format == "tsu:") { @@ -78,50 +96,51 @@ static unique_ptr GetArrowLogicalTypeNoDictionary(ArrowSchema &schema } else if (format == "tss:") { return make_uniq(LogicalTypeId::TIMESTAMP_SEC); } else if (format == "tdD") { - return make_uniq(LogicalType::DATE, ArrowDateTimeType::DAYS); + return make_uniq(LogicalType::DATE, make_uniq(ArrowDateTimeType::DAYS)); } else if (format == "tdm") { - return make_uniq(LogicalType::DATE, ArrowDateTimeType::MILLISECONDS); + return make_uniq(LogicalType::DATE, make_uniq(ArrowDateTimeType::MILLISECONDS)); } else if (format == "tts") { - return make_uniq(LogicalType::TIME, ArrowDateTimeType::SECONDS); + return make_uniq(LogicalType::TIME, make_uniq(ArrowDateTimeType::SECONDS)); } else if (format == "ttm") { - return make_uniq(LogicalType::TIME, ArrowDateTimeType::MILLISECONDS); + return make_uniq(LogicalType::TIME, make_uniq(ArrowDateTimeType::MILLISECONDS)); } else if (format == "ttu") { - return make_uniq(LogicalType::TIME, ArrowDateTimeType::MICROSECONDS); + return make_uniq(LogicalType::TIME, make_uniq(ArrowDateTimeType::MICROSECONDS)); } else if (format == "ttn") { - return make_uniq(LogicalType::TIME, ArrowDateTimeType::NANOSECONDS); + return make_uniq(LogicalType::TIME, make_uniq(ArrowDateTimeType::NANOSECONDS)); } else if (format == "tDs") { - return make_uniq(LogicalType::INTERVAL, ArrowDateTimeType::SECONDS); + return make_uniq(LogicalType::INTERVAL, make_uniq(ArrowDateTimeType::SECONDS)); } else if (format == "tDm") { - return make_uniq(LogicalType::INTERVAL, ArrowDateTimeType::MILLISECONDS); + return make_uniq(LogicalType::INTERVAL, + make_uniq(ArrowDateTimeType::MILLISECONDS)); } else if (format == "tDu") { - return make_uniq(LogicalType::INTERVAL, ArrowDateTimeType::MICROSECONDS); + return make_uniq(LogicalType::INTERVAL, + make_uniq(ArrowDateTimeType::MICROSECONDS)); } else if (format == "tDn") { - return make_uniq(LogicalType::INTERVAL, ArrowDateTimeType::NANOSECONDS); + return make_uniq(LogicalType::INTERVAL, + make_uniq(ArrowDateTimeType::NANOSECONDS)); } else if (format == "tiD") { - return make_uniq(LogicalType::INTERVAL, ArrowDateTimeType::DAYS); + return make_uniq(LogicalType::INTERVAL, make_uniq(ArrowDateTimeType::DAYS)); } else if (format == "tiM") { - return make_uniq(LogicalType::INTERVAL, ArrowDateTimeType::MONTHS); + return make_uniq(LogicalType::INTERVAL, make_uniq(ArrowDateTimeType::MONTHS)); } else if (format == "tin") { - return make_uniq(LogicalType::INTERVAL, ArrowDateTimeType::MONTH_DAY_NANO); + return make_uniq(LogicalType::INTERVAL, + make_uniq(ArrowDateTimeType::MONTH_DAY_NANO)); } else if (format == "+l") { - auto child_type = ArrowTableFunction::GetArrowLogicalType(*schema.children[0]); - auto list_type = - make_uniq(LogicalType::LIST(child_type->GetDuckType()), ArrowVariableSizeType::NORMAL); - list_type->AddChild(std::move(child_type)); - return list_type; + return CreateListType(*schema.children[0], ArrowVariableSizeType::NORMAL, false); } else if (format == "+L") { - auto child_type = ArrowTableFunction::GetArrowLogicalType(*schema.children[0]); - auto list_type = - make_uniq(LogicalType::LIST(child_type->GetDuckType()), ArrowVariableSizeType::SUPER_SIZE); - list_type->AddChild(std::move(child_type)); - return list_type; + return CreateListType(*schema.children[0], ArrowVariableSizeType::SUPER_SIZE, false); + } else if (format == "+vl") { + return CreateListType(*schema.children[0], ArrowVariableSizeType::NORMAL, true); + } else if (format == "+vL") { + return CreateListType(*schema.children[0], ArrowVariableSizeType::SUPER_SIZE, true); } else if (format[0] == '+' && format[1] == 'w') { std::string parameters = format.substr(format.find(':') + 1); auto fixed_size = NumericCast(std::stoi(parameters)); auto child_type = ArrowTableFunction::GetArrowLogicalType(*schema.children[0]); - auto list_type = make_uniq(LogicalType::ARRAY(child_type->GetDuckType(), fixed_size), fixed_size); - list_type->AddChild(std::move(child_type)); - return list_type; + + auto array_type = LogicalType::ARRAY(child_type->GetDuckType(), fixed_size); + auto type_info = make_uniq(std::move(child_type), fixed_size); + return make_uniq(array_type, std::move(type_info)); } else if (format == "+s") { child_list_t child_types; vector> children; @@ -133,8 +152,8 @@ static unique_ptr GetArrowLogicalTypeNoDictionary(ArrowSchema &schema children.emplace_back(ArrowTableFunction::GetArrowLogicalType(*schema.children[type_idx])); child_types.emplace_back(schema.children[type_idx]->name, children.back()->GetDuckType()); } - auto struct_type = make_uniq(LogicalType::STRUCT(std::move(child_types))); - struct_type->AssignChildren(std::move(children)); + auto type_info = make_uniq(std::move(children)); + auto struct_type = make_uniq(LogicalType::STRUCT(std::move(child_types)), std::move(type_info)); return struct_type; } else if (format[0] == '+' && format[1] == 'u') { if (format[2] != 's') { @@ -158,8 +177,8 @@ static unique_ptr GetArrowLogicalTypeNoDictionary(ArrowSchema &schema members.emplace_back(type->name, children.back()->GetDuckType()); } - auto union_type = make_uniq(LogicalType::UNION(members)); - union_type->AssignChildren(std::move(children)); + auto type_info = make_uniq(std::move(children)); + auto union_type = make_uniq(LogicalType::UNION(members), std::move(type_info)); return union_type; } else if (format == "+r") { child_list_t members; @@ -174,8 +193,8 @@ static unique_ptr GetArrowLogicalTypeNoDictionary(ArrowSchema &schema members.emplace_back(type->name, children.back()->GetDuckType()); } - auto struct_type = make_uniq(LogicalType::STRUCT(members)); - struct_type->AssignChildren(std::move(children)); + auto type_info = make_uniq(std::move(children)); + auto struct_type = make_uniq(LogicalType::STRUCT(members), std::move(type_info)); struct_type->SetRunEndEncoded(); return struct_type; } else if (format == "+m") { @@ -183,43 +202,46 @@ static unique_ptr GetArrowLogicalTypeNoDictionary(ArrowSchema &schema D_ASSERT(arrow_struct_type.n_children == 2); auto key_type = ArrowTableFunction::GetArrowLogicalType(*arrow_struct_type.children[0]); auto value_type = ArrowTableFunction::GetArrowLogicalType(*arrow_struct_type.children[1]); - auto map_type = make_uniq(LogicalType::MAP(key_type->GetDuckType(), value_type->GetDuckType()), - ArrowVariableSizeType::NORMAL); child_list_t key_value; key_value.emplace_back(std::make_pair("key", key_type->GetDuckType())); key_value.emplace_back(std::make_pair("value", value_type->GetDuckType())); - auto inner_struct = - make_uniq(LogicalType::STRUCT(std::move(key_value)), ArrowVariableSizeType::NORMAL); + auto map_type = LogicalType::MAP(key_type->GetDuckType(), value_type->GetDuckType()); vector> children; children.reserve(2); children.push_back(std::move(key_type)); children.push_back(std::move(value_type)); - inner_struct->AssignChildren(std::move(children)); - map_type->AddChild(std::move(inner_struct)); - return map_type; + auto inner_struct = make_uniq(LogicalType::STRUCT(std::move(key_value)), + make_uniq(std::move(children))); + auto map_type_info = ArrowListInfo::List(std::move(inner_struct), ArrowVariableSizeType::NORMAL); + return make_uniq(map_type, std::move(map_type_info)); } else if (format == "z") { - return make_uniq(LogicalType::BLOB, ArrowVariableSizeType::NORMAL); + auto type_info = make_uniq(ArrowVariableSizeType::NORMAL); + return make_uniq(LogicalType::BLOB, std::move(type_info)); } else if (format == "Z") { - return make_uniq(LogicalType::BLOB, ArrowVariableSizeType::SUPER_SIZE); + auto type_info = make_uniq(ArrowVariableSizeType::SUPER_SIZE); + return make_uniq(LogicalType::BLOB, std::move(type_info)); } else if (format[0] == 'w') { - std::string parameters = format.substr(format.find(':') + 1); + string parameters = format.substr(format.find(':') + 1); auto fixed_size = NumericCast(std::stoi(parameters)); - return make_uniq(LogicalType::BLOB, fixed_size); + auto type_info = make_uniq(fixed_size); + return make_uniq(LogicalType::BLOB, std::move(type_info)); } else if (format[0] == 't' && format[1] == 's') { // Timestamp with Timezone // TODO right now we just get the UTC value. We probably want to support this properly in the future + unique_ptr type_info; if (format[2] == 'n') { - return make_uniq(LogicalType::TIMESTAMP_TZ, ArrowDateTimeType::NANOSECONDS); + type_info = make_uniq(ArrowDateTimeType::NANOSECONDS); } else if (format[2] == 'u') { - return make_uniq(LogicalType::TIMESTAMP_TZ, ArrowDateTimeType::MICROSECONDS); + type_info = make_uniq(ArrowDateTimeType::MICROSECONDS); } else if (format[2] == 'm') { - return make_uniq(LogicalType::TIMESTAMP_TZ, ArrowDateTimeType::MILLISECONDS); + type_info = make_uniq(ArrowDateTimeType::MILLISECONDS); } else if (format[2] == 's') { - return make_uniq(LogicalType::TIMESTAMP_TZ, ArrowDateTimeType::SECONDS); + type_info = make_uniq(ArrowDateTimeType::SECONDS); } else { throw NotImplementedException(" Timestamptz precision of not accepted"); } + return make_uniq(LogicalType::TIMESTAMP_TZ, std::move(type_info)); } else { throw NotImplementedException("Unsupported Internal Arrow Type %s", format); } @@ -257,18 +279,30 @@ unique_ptr ArrowTableFunction::ArrowScanBind(ClientContext &contex if (input.inputs[0].IsNull() || input.inputs[1].IsNull() || input.inputs[2].IsNull()) { throw BinderException("arrow_scan: pointers cannot be null"); } + auto &ref = input.ref; + + shared_ptr dependency; + if (ref.external_dependency) { + // This was created during the replacement scan for Python (see python_replacement_scan.cpp) + // this object is the owning reference to 'stream_factory_ptr' and has to be kept alive. + dependency = ref.external_dependency->GetDependency("replacement_cache"); + D_ASSERT(dependency); + } auto stream_factory_ptr = input.inputs[0].GetPointer(); auto stream_factory_produce = (stream_factory_produce_t)input.inputs[1].GetPointer(); // NOLINT auto stream_factory_get_schema = (stream_factory_get_schema_t)input.inputs[2].GetPointer(); // NOLINT - auto res = make_uniq(stream_factory_produce, stream_factory_ptr); + auto res = make_uniq(stream_factory_produce, stream_factory_ptr, std::move(dependency)); auto &data = *res; stream_factory_get_schema(reinterpret_cast(stream_factory_ptr), data.schema_root.arrow_schema); PopulateArrowTableType(res->arrow_table, data.schema_root, names, return_types); QueryResult::DeduplicateColumns(names); res->all_types = return_types; + if (return_types.empty()) { + throw InvalidInputException("Provided table/dataframe must have at least one column"); + } return std::move(res); } diff --git a/src/function/table/arrow/CMakeLists.txt b/src/function/table/arrow/CMakeLists.txt index badf731a842..7b329157e1f 100644 --- a/src/function/table/arrow/CMakeLists.txt +++ b/src/function/table/arrow/CMakeLists.txt @@ -1,5 +1,5 @@ add_library_unity(duckdb_arrow_conversion OBJECT arrow_duck_schema.cpp - arrow_array_scan_state.cpp) + arrow_array_scan_state.cpp arrow_type_info.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/function/table/arrow/arrow_duck_schema.cpp b/src/function/table/arrow/arrow_duck_schema.cpp index ae841179cbb..b434b99c512 100644 --- a/src/function/table/arrow/arrow_duck_schema.cpp +++ b/src/function/table/arrow/arrow_duck_schema.cpp @@ -13,15 +13,6 @@ const arrow_column_map_t &ArrowTableType::GetColumns() const { return arrow_convert_data; } -void ArrowType::AddChild(unique_ptr child) { - children.emplace_back(std::move(child)); -} - -void ArrowType::AssignChildren(vector> children) { - D_ASSERT(this->children.empty()); - this->children = std::move(children); -} - void ArrowType::SetDictionary(unique_ptr dictionary) { D_ASSERT(!this->dictionary_type); dictionary_type = std::move(dictionary); @@ -37,8 +28,12 @@ const ArrowType &ArrowType::GetDictionary() const { } void ArrowType::SetRunEndEncoded() { - D_ASSERT(children.size() == 2); - auto actual_type = children[1]->GetDuckType(); + D_ASSERT(type_info); + D_ASSERT(type_info->type == ArrowTypeInfoType::STRUCT); + auto &struct_info = type_info->Cast(); + D_ASSERT(struct_info.ChildCount() == 2); + + auto actual_type = struct_info.GetChild(1).GetDuckType(); // Override the duckdb type to the actual type type = actual_type; run_end_encoded = true; @@ -60,29 +55,33 @@ LogicalType ArrowType::GetDuckType(bool use_dictionary) const { auto id = type.id(); switch (id) { case LogicalTypeId::STRUCT: { + auto &struct_info = type_info->Cast(); child_list_t new_children; - for (idx_t i = 0; i < children.size(); i++) { - auto &child = children[i]; + for (idx_t i = 0; i < struct_info.ChildCount(); i++) { + auto &child = struct_info.GetChild(i); auto &child_name = StructType::GetChildName(type, i); - new_children.emplace_back(std::make_pair(child_name, child->GetDuckType(true))); + new_children.emplace_back(std::make_pair(child_name, child.GetDuckType(true))); } return LogicalType::STRUCT(std::move(new_children)); } case LogicalTypeId::LIST: { - auto &child = children[0]; - return LogicalType::LIST(child->GetDuckType(true)); + auto &list_info = type_info->Cast(); + auto &child = list_info.GetChild(); + return LogicalType::LIST(child.GetDuckType(true)); } case LogicalTypeId::MAP: { - auto &struct_child = children[0]; - auto struct_type = struct_child->GetDuckType(true); + auto &list_info = type_info->Cast(); + auto &struct_child = list_info.GetChild(); + auto struct_type = struct_child.GetDuckType(true); return LogicalType::MAP(StructType::GetChildType(struct_type, 0), StructType::GetChildType(struct_type, 1)); } case LogicalTypeId::UNION: { + auto &union_info = type_info->Cast(); child_list_t new_children; - for (idx_t i = 0; i < children.size(); i++) { - auto &child = children[i]; + for (idx_t i = 0; i < union_info.ChildCount(); i++) { + auto &child = union_info.GetChild(i); auto &child_name = UnionType::GetMemberName(type, i); - new_children.emplace_back(std::make_pair(child_name, child->GetDuckType(true))); + new_children.emplace_back(std::make_pair(child_name, child.GetDuckType(true))); } return LogicalType::UNION(std::move(new_children)); } @@ -92,22 +91,4 @@ LogicalType ArrowType::GetDuckType(bool use_dictionary) const { } } -ArrowVariableSizeType ArrowType::GetSizeType() const { - return size_type; -} - -ArrowDateTimeType ArrowType::GetDateTimeType() const { - return date_time_precision; -} - -const ArrowType &ArrowType::operator[](idx_t index) const { - D_ASSERT(index < children.size()); - return *children[index]; -} - -idx_t ArrowType::FixedSize() const { - D_ASSERT(size_type == ArrowVariableSizeType::FIXED_SIZE); - return fixed_size; -} - } // namespace duckdb diff --git a/src/function/table/arrow/arrow_type_info.cpp b/src/function/table/arrow/arrow_type_info.cpp new file mode 100644 index 00000000000..e012f1b5cfc --- /dev/null +++ b/src/function/table/arrow/arrow_type_info.cpp @@ -0,0 +1,135 @@ +#include "duckdb/function/table/arrow/arrow_type_info.hpp" +#include "duckdb/function/table/arrow/arrow_duck_schema.hpp" + +namespace duckdb { + +//===--------------------------------------------------------------------===// +// ArrowTypeInfo +//===--------------------------------------------------------------------===// + +ArrowTypeInfo::ArrowTypeInfo(ArrowTypeInfoType type) : type(type) { +} + +ArrowTypeInfo::~ArrowTypeInfo() { +} + +//===--------------------------------------------------------------------===// +// ArrowStructInfo +//===--------------------------------------------------------------------===// + +ArrowStructInfo::ArrowStructInfo(vector> children) + : ArrowTypeInfo(ArrowTypeInfoType::STRUCT), children(std::move(children)) { +} + +idx_t ArrowStructInfo::ChildCount() const { + return children.size(); +} + +ArrowStructInfo::~ArrowStructInfo() { +} + +const ArrowType &ArrowStructInfo::GetChild(idx_t index) const { + D_ASSERT(index < children.size()); + return *children[index]; +} + +const vector> &ArrowStructInfo::GetChildren() const { + return children; +} + +//===--------------------------------------------------------------------===// +// ArrowDateTimeInfo +//===--------------------------------------------------------------------===// + +ArrowDateTimeInfo::ArrowDateTimeInfo(ArrowDateTimeType size) + : ArrowTypeInfo(ArrowTypeInfoType::DATE_TIME), size_type(size) { +} + +ArrowDateTimeInfo::~ArrowDateTimeInfo() { +} + +ArrowDateTimeType ArrowDateTimeInfo::GetDateTimeType() const { + return size_type; +} + +//===--------------------------------------------------------------------===// +// ArrowStringInfo +//===--------------------------------------------------------------------===// + +ArrowStringInfo::ArrowStringInfo(ArrowVariableSizeType size) + : ArrowTypeInfo(ArrowTypeInfoType::STRING), size_type(size), fixed_size(0) { + D_ASSERT(size != ArrowVariableSizeType::FIXED_SIZE); +} + +ArrowStringInfo::~ArrowStringInfo() { +} + +ArrowStringInfo::ArrowStringInfo(idx_t fixed_size) + : ArrowTypeInfo(ArrowTypeInfoType::STRING), size_type(ArrowVariableSizeType::FIXED_SIZE), fixed_size(fixed_size) { +} + +ArrowVariableSizeType ArrowStringInfo::GetSizeType() const { + return size_type; +} + +idx_t ArrowStringInfo::FixedSize() const { + D_ASSERT(size_type == ArrowVariableSizeType::FIXED_SIZE); + return fixed_size; +} + +//===--------------------------------------------------------------------===// +// ArrowListInfo +//===--------------------------------------------------------------------===// + +ArrowListInfo::ArrowListInfo(unique_ptr child, ArrowVariableSizeType size) + : ArrowTypeInfo(ArrowTypeInfoType::LIST), size_type(size), child(std::move(child)) { +} + +ArrowListInfo::~ArrowListInfo() { +} + +unique_ptr ArrowListInfo::ListView(unique_ptr child, ArrowVariableSizeType size) { + D_ASSERT(size == ArrowVariableSizeType::SUPER_SIZE || size == ArrowVariableSizeType::NORMAL); + auto list_info = unique_ptr(new ArrowListInfo(std::move(child), size)); + list_info->is_view = true; + return list_info; +} + +unique_ptr ArrowListInfo::List(unique_ptr child, ArrowVariableSizeType size) { + D_ASSERT(size == ArrowVariableSizeType::SUPER_SIZE || size == ArrowVariableSizeType::NORMAL); + return unique_ptr(new ArrowListInfo(std::move(child), size)); +} + +ArrowVariableSizeType ArrowListInfo::GetSizeType() const { + return size_type; +} + +bool ArrowListInfo::IsView() const { + return is_view; +} + +ArrowType &ArrowListInfo::GetChild() const { + return *child; +} + +//===--------------------------------------------------------------------===// +// ArrowArrayInfo +//===--------------------------------------------------------------------===// + +ArrowArrayInfo::ArrowArrayInfo(unique_ptr child, idx_t fixed_size) + : ArrowTypeInfo(ArrowTypeInfoType::ARRAY), child(std::move(child)), fixed_size(fixed_size) { + D_ASSERT(fixed_size > 0); +} + +ArrowArrayInfo::~ArrowArrayInfo() { +} + +idx_t ArrowArrayInfo::FixedSize() const { + return fixed_size; +} + +ArrowType &ArrowArrayInfo::GetChild() const { + return *child; +} + +} // namespace duckdb diff --git a/src/function/table/arrow_conversion.cpp b/src/function/table/arrow_conversion.cpp index c1759ef8484..43ffc3a755d 100644 --- a/src/function/table/arrow_conversion.cpp +++ b/src/function/table/arrow_conversion.cpp @@ -5,6 +5,7 @@ #include "duckdb/common/types/arrow_aux_data.hpp" #include "duckdb/function/scalar/nested_functions.hpp" #include "duckdb/common/exception/conversion_exception.hpp" +#include "duckdb/common/types/arrow_string_view_type.hpp" namespace duckdb { @@ -119,42 +120,109 @@ static void ColumnArrowToDuckDBDictionary(Vector &vector, ArrowArray &array, Arr idx_t size, const ArrowType &arrow_type, int64_t nested_offset = -1, ValidityMask *parent_mask = nullptr, uint64_t parent_offset = 0); -static void ArrowToDuckDBList(Vector &vector, ArrowArray &array, ArrowArrayScanState &array_state, idx_t size, - const ArrowType &arrow_type, int64_t nested_offset, ValidityMask *parent_mask, - int64_t parent_offset) { - auto size_type = arrow_type.GetSizeType(); - idx_t list_size = 0; - auto &scan_state = array_state.state; +namespace { - SetValidityMask(vector, array, scan_state, size, parent_offset, nested_offset); +struct ArrowListOffsetData { + idx_t list_size = 0; idx_t start_offset = 0; +}; + +} // namespace + +template +static ArrowListOffsetData ConvertArrowListOffsetsTemplated(Vector &vector, ArrowArray &array, idx_t size, + idx_t effective_offset) { + ArrowListOffsetData result; + auto &start_offset = result.start_offset; + auto &list_size = result.list_size; + idx_t cur_offset = 0; - if (size_type == ArrowVariableSizeType::NORMAL) { - auto offsets = - ArrowBufferData(array, 1) + GetEffectiveOffset(array, parent_offset, scan_state, nested_offset); - start_offset = offsets[0]; - auto list_data = FlatVector::GetData(vector); + auto offsets = ArrowBufferData(array, 1) + effective_offset; + start_offset = offsets[0]; + auto list_data = FlatVector::GetData(vector); + for (idx_t i = 0; i < size; i++) { + auto &le = list_data[i]; + le.offset = cur_offset; + le.length = offsets[i + 1] - offsets[i]; + cur_offset += le.length; + } + list_size = offsets[size]; + list_size -= start_offset; + return result; +} + +template +static ArrowListOffsetData ConvertArrowListViewOffsetsTemplated(Vector &vector, ArrowArray &array, idx_t size, + idx_t effective_offset) { + ArrowListOffsetData result; + auto &start_offset = result.start_offset; + auto &list_size = result.list_size; + + list_size = 0; + auto offsets = ArrowBufferData(array, 1) + effective_offset; + auto sizes = ArrowBufferData(array, 2) + effective_offset; + + // In ListArrays the offsets have to be sequential + // ListViewArrays do not have this same constraint + // for that reason we need to keep track of the lowest offset, so we can skip all the data that comes before it + // when we scan the child data + + auto lowest_offset = size ? offsets[0] : 0; + auto list_data = FlatVector::GetData(vector); + for (idx_t i = 0; i < size; i++) { + auto &le = list_data[i]; + le.offset = offsets[i]; + le.length = sizes[i]; + list_size += le.length; + if (sizes[i] != 0) { + lowest_offset = MinValue(lowest_offset, offsets[i]); + } + } + start_offset = lowest_offset; + if (start_offset) { + // We start scanning the child data at the 'start_offset' so we need to fix up the created list entries for (idx_t i = 0; i < size; i++) { auto &le = list_data[i]; - le.offset = cur_offset; - le.length = offsets[i + 1] - offsets[i]; - cur_offset += le.length; + le.offset = le.offset <= start_offset ? 0 : le.offset - start_offset; + } + } + return result; +} + +static ArrowListOffsetData ConvertArrowListOffsets(Vector &vector, ArrowArray &array, idx_t size, + const ArrowType &arrow_type, idx_t effective_offset) { + auto &list_info = arrow_type.GetTypeInfo(); + auto size_type = list_info.GetSizeType(); + if (list_info.IsView()) { + if (size_type == ArrowVariableSizeType::NORMAL) { + return ConvertArrowListViewOffsetsTemplated(vector, array, size, effective_offset); + } else { + D_ASSERT(size_type == ArrowVariableSizeType::SUPER_SIZE); + return ConvertArrowListViewOffsetsTemplated(vector, array, size, effective_offset); } - list_size = offsets[size]; } else { - auto offsets = - ArrowBufferData(array, 1) + GetEffectiveOffset(array, parent_offset, scan_state, nested_offset); - start_offset = offsets[0]; - auto list_data = FlatVector::GetData(vector); - for (idx_t i = 0; i < size; i++) { - auto &le = list_data[i]; - le.offset = cur_offset; - le.length = offsets[i + 1] - offsets[i]; - cur_offset += le.length; + if (size_type == ArrowVariableSizeType::NORMAL) { + return ConvertArrowListOffsetsTemplated(vector, array, size, effective_offset); + } else { + D_ASSERT(size_type == ArrowVariableSizeType::SUPER_SIZE); + return ConvertArrowListOffsetsTemplated(vector, array, size, effective_offset); } - list_size = offsets[size]; } - list_size -= start_offset; +} + +static void ArrowToDuckDBList(Vector &vector, ArrowArray &array, ArrowArrayScanState &array_state, idx_t size, + const ArrowType &arrow_type, int64_t nested_offset, ValidityMask *parent_mask, + int64_t parent_offset) { + auto &scan_state = array_state.state; + + auto &list_info = arrow_type.GetTypeInfo(); + SetValidityMask(vector, array, scan_state, size, parent_offset, nested_offset); + + auto effective_offset = GetEffectiveOffset(array, parent_offset, scan_state, nested_offset); + auto list_data = ConvertArrowListOffsets(vector, array, size, arrow_type, effective_offset); + auto &start_offset = list_data.start_offset; + auto &list_size = list_data.list_size; + ListVector::Reserve(vector, list_size); ListVector::SetListSize(vector, list_size); auto &child_vector = ListVector::GetEntry(vector); @@ -173,7 +241,8 @@ static void ArrowToDuckDBList(Vector &vector, ArrowArray &array, ArrowArrayScanS } auto &child_state = array_state.GetChild(0); auto &child_array = *array.children[0]; - auto &child_type = arrow_type[0]; + auto &child_type = list_info.GetChild(); + if (list_size == 0 && start_offset == 0) { D_ASSERT(!child_array.dictionary); ColumnArrowToDuckDB(child_vector, child_array, child_state, list_size, child_type, -1); @@ -204,9 +273,9 @@ static void ArrowToDuckDBArray(Vector &vector, ArrowArray &array, ArrowArrayScan const ArrowType &arrow_type, int64_t nested_offset, ValidityMask *parent_mask, int64_t parent_offset) { - D_ASSERT(arrow_type.GetSizeType() == ArrowVariableSizeType::FIXED_SIZE); + auto &array_info = arrow_type.GetTypeInfo(); auto &scan_state = array_state.state; - auto array_size = arrow_type.FixedSize(); + auto array_size = array_info.FixedSize(); auto child_count = array_size * size; auto child_offset = GetEffectiveOffset(array, parent_offset, scan_state, nested_offset) * array_size; @@ -242,7 +311,7 @@ static void ArrowToDuckDBArray(Vector &vector, ArrowArray &array, ArrowArrayScan auto &child_state = array_state.GetChild(0); auto &child_array = *array.children[0]; - auto &child_type = arrow_type[0]; + auto &child_type = array_info.GetChild(); if (child_count == 0 && child_offset == 0) { D_ASSERT(!child_array.dictionary); ColumnArrowToDuckDB(child_vector, child_array, child_state, child_count, child_type, -1); @@ -259,10 +328,11 @@ static void ArrowToDuckDBArray(Vector &vector, ArrowArray &array, ArrowArrayScan static void ArrowToDuckDBBlob(Vector &vector, ArrowArray &array, const ArrowScanLocalState &scan_state, idx_t size, const ArrowType &arrow_type, int64_t nested_offset, int64_t parent_offset) { - auto size_type = arrow_type.GetSizeType(); SetValidityMask(vector, array, scan_state, size, parent_offset, nested_offset); + auto &string_info = arrow_type.GetTypeInfo(); + auto size_type = string_info.GetSizeType(); if (size_type == ArrowVariableSizeType::FIXED_SIZE) { - auto fixed_size = arrow_type.FixedSize(); + auto fixed_size = string_info.FixedSize(); //! Have to check validity mask before setting this up idx_t offset = GetEffectiveOffset(array, parent_offset, scan_state, nested_offset) * fixed_size; auto cdata = ArrowBufferData(array, 1); @@ -339,6 +409,35 @@ static void SetVectorString(Vector &vector, idx_t size, char *cdata, T *offsets) } } +static void SetVectorStringView(Vector &vector, idx_t size, ArrowArray &array, idx_t current_pos) { + auto strings = FlatVector::GetData(vector); + auto arrow_string = ArrowBufferData(array, 1) + current_pos; + + for (idx_t row_idx = 0; row_idx < size; row_idx++) { + if (FlatVector::IsNull(vector, row_idx)) { + continue; + } + auto length = UnsafeNumericCast(arrow_string[row_idx].Length()); + if (arrow_string[row_idx].IsInline()) { + // This string is inlined + // | Bytes 0-3 | Bytes 4-15 | + // |------------|---------------------------------------| + // | length | data (padded with 0) | + strings[row_idx] = string_t(arrow_string[row_idx].GetInlineData(), length); + } else { + // This string is not inlined, we have to check a different buffer and offsets + // | Bytes 0-3 | Bytes 4-7 | Bytes 8-11 | Bytes 12-15 | + // |------------|------------|------------|-------------| + // | length | prefix | buf. index | offset | + auto buffer_index = UnsafeNumericCast(arrow_string[row_idx].GetBufferIndex()); + int32_t offset = arrow_string[row_idx].GetOffset(); + D_ASSERT(array.n_buffers > 2 + buffer_index); + auto c_data = ArrowBufferData(array, 2 + buffer_index); + strings[row_idx] = string_t(&c_data[offset], length); + } + } +} + static void DirectConversion(Vector &vector, ArrowArray &array, const ArrowScanLocalState &scan_state, int64_t nested_offset, uint64_t parent_offset) { auto internal_type = GetTypeIdSize(vector.GetType().InternalType()); @@ -592,8 +691,9 @@ static void ColumnArrowToDuckDBRunEndEncoded(Vector &vector, ArrowArray &array, auto &run_ends_array = *array.children[0]; auto &values_array = *array.children[1]; - auto &run_ends_type = arrow_type[0]; - auto &values_type = arrow_type[1]; + auto &struct_info = arrow_type.GetTypeInfo(); + auto &run_ends_type = struct_info.GetChild(0); + auto &values_type = struct_info.GetChild(1); D_ASSERT(vector.GetType() == values_type.GetDuckType()); auto &scan_state = array_state.state; @@ -687,22 +787,36 @@ static void ColumnArrowToDuckDB(Vector &vector, ArrowArray &array, ArrowArraySca break; } case LogicalTypeId::VARCHAR: { - auto size_type = arrow_type.GetSizeType(); - auto cdata = ArrowBufferData(array, 2); - if (size_type == ArrowVariableSizeType::SUPER_SIZE) { + auto &string_info = arrow_type.GetTypeInfo(); + auto size_type = string_info.GetSizeType(); + switch (size_type) { + case ArrowVariableSizeType::SUPER_SIZE: { + auto cdata = ArrowBufferData(array, 2); auto offsets = ArrowBufferData(array, 1) + GetEffectiveOffset(array, NumericCast(parent_offset), scan_state, nested_offset); SetVectorString(vector, size, cdata, offsets); - } else { + break; + } + case ArrowVariableSizeType::NORMAL: + case ArrowVariableSizeType::FIXED_SIZE: { + auto cdata = ArrowBufferData(array, 2); auto offsets = ArrowBufferData(array, 1) + GetEffectiveOffset(array, NumericCast(parent_offset), scan_state, nested_offset); SetVectorString(vector, size, cdata, offsets); + break; + } + case ArrowVariableSizeType::VIEW: { + SetVectorStringView( + vector, size, array, + GetEffectiveOffset(array, NumericCast(parent_offset), scan_state, nested_offset)); + break; + } } break; } case LogicalTypeId::DATE: { - - auto precision = arrow_type.GetDateTimeType(); + auto &datetime_info = arrow_type.GetTypeInfo(); + auto precision = datetime_info.GetDateTimeType(); switch (precision) { case ArrowDateTimeType::DAYS: { DirectConversion(vector, array, scan_state, nested_offset, parent_offset); @@ -725,7 +839,8 @@ static void ColumnArrowToDuckDB(Vector &vector, ArrowArray &array, ArrowArraySca break; } case LogicalTypeId::TIME: { - auto precision = arrow_type.GetDateTimeType(); + auto &datetime_info = arrow_type.GetTypeInfo(); + auto precision = datetime_info.GetDateTimeType(); switch (precision) { case ArrowDateTimeType::SECONDS: { TimeConversion(vector, array, scan_state, nested_offset, NumericCast(parent_offset), size, @@ -757,7 +872,8 @@ static void ColumnArrowToDuckDB(Vector &vector, ArrowArray &array, ArrowArraySca break; } case LogicalTypeId::TIMESTAMP_TZ: { - auto precision = arrow_type.GetDateTimeType(); + auto &datetime_info = arrow_type.GetTypeInfo(); + auto precision = datetime_info.GetDateTimeType(); switch (precision) { case ArrowDateTimeType::SECONDS: { TimestampTZConversion(vector, array, scan_state, nested_offset, NumericCast(parent_offset), size, @@ -788,7 +904,8 @@ static void ColumnArrowToDuckDB(Vector &vector, ArrowArray &array, ArrowArraySca break; } case LogicalTypeId::INTERVAL: { - auto precision = arrow_type.GetDateTimeType(); + auto &datetime_info = arrow_type.GetTypeInfo(); + auto precision = datetime_info.GetDateTimeType(); switch (precision) { case ArrowDateTimeType::SECONDS: { IntervalConversionUs(vector, array, scan_state, nested_offset, NumericCast(parent_offset), size, @@ -907,12 +1024,13 @@ static void ColumnArrowToDuckDB(Vector &vector, ArrowArray &array, ArrowArraySca } case LogicalTypeId::STRUCT: { //! Fill the children + auto &struct_info = arrow_type.GetTypeInfo(); auto &child_entries = StructVector::GetEntries(vector); auto &struct_validity_mask = FlatVector::Validity(vector); for (idx_t child_idx = 0; child_idx < NumericCast(array.n_children); child_idx++) { auto &child_entry = *child_entries[child_idx]; auto &child_array = *array.children[child_idx]; - auto &child_type = arrow_type[child_idx]; + auto &child_type = struct_info.GetChild(child_idx); auto &child_state = array_state.GetChild(child_idx); SetValidityMask(child_entry, child_array, scan_state, size, array.offset, nested_offset); @@ -951,13 +1069,13 @@ static void ColumnArrowToDuckDB(Vector &vector, ArrowArray &array, ArrowArraySca auto members = UnionType::CopyMemberTypes(vector.GetType()); auto &validity_mask = FlatVector::Validity(vector); - + auto &union_info = arrow_type.GetTypeInfo(); duckdb::vector children; for (idx_t child_idx = 0; child_idx < NumericCast(array.n_children); child_idx++) { Vector child(members[child_idx].second, size); auto &child_array = *array.children[child_idx]; auto &child_state = array_state.GetChild(child_idx); - auto &child_type = arrow_type[child_idx]; + auto &child_type = union_info.GetChild(child_idx); SetValidityMask(child, child_array, scan_state, size, NumericCast(parent_offset), nested_offset); auto array_physical_type = GetArrowArrayPhysicalType(child_type); diff --git a/src/function/table/copy_csv.cpp b/src/function/table/copy_csv.cpp index 9d0cf359892..06ab8f7a315 100644 --- a/src/function/table/copy_csv.cpp +++ b/src/function/table/copy_csv.cpp @@ -11,15 +11,13 @@ #include "duckdb/function/copy_function.hpp" #include "duckdb/function/scalar/string_functions.hpp" #include "duckdb/function/table/read_csv.hpp" -#include "duckdb/parser/parsed_data/copy_info.hpp" +#include "duckdb/parser/expression/bound_expression.hpp" #include "duckdb/parser/expression/cast_expression.hpp" -#include "duckdb/parser/expression/function_expression.hpp" -#include "duckdb/parser/expression/columnref_expression.hpp" #include "duckdb/parser/expression/constant_expression.hpp" -#include "duckdb/parser/expression/bound_expression.hpp" +#include "duckdb/parser/expression/function_expression.hpp" +#include "duckdb/parser/parsed_data/copy_info.hpp" #include "duckdb/planner/expression/bound_reference_expression.hpp" -#include "duckdb/execution/column_binding_resolver.hpp" -#include "duckdb/planner/operator/logical_dummy_scan.hpp" + #include namespace duckdb { @@ -199,7 +197,9 @@ static unique_ptr ReadCSVBind(ClientContext &context, CopyInfo &in bind_data->csv_names = expected_names; bind_data->return_types = expected_types; bind_data->return_names = expected_names; - bind_data->files = MultiFileReader::GetFileList(context, Value(info.file_path), "CSV"); + + auto multi_file_reader = MultiFileReader::CreateDefault("CSVCopy"); + bind_data->files = multi_file_reader->CreateFileList(context, Value(info.file_path))->GetAllFiles(); auto &options = bind_data->options; @@ -430,11 +430,6 @@ static unique_ptr WriteCSVInitializeGlobal(ClientContext &co return std::move(global_data); } -idx_t WriteCSVFileSize(GlobalFunctionData &gstate) { - auto &global_state = gstate.Cast(); - return global_state.FileSize(); -} - static void WriteCSVChunkInternal(ClientContext &context, FunctionData &bind_data, DataChunk &cast_chunk, MemoryStream &writer, DataChunk &input, bool &written_anything, ExpressionExecutor &executor) { @@ -590,6 +585,18 @@ void WriteCSVFlushBatch(ClientContext &context, FunctionData &bind_data, GlobalF writer.Rewind(); } +//===--------------------------------------------------------------------===// +// File rotation +//===--------------------------------------------------------------------===// +bool WriteCSVRotateFiles(FunctionData &, const optional_idx &file_size_bytes) { + return file_size_bytes.IsValid(); +} + +bool WriteCSVRotateNextFile(GlobalFunctionData &gstate, FunctionData &, const optional_idx &file_size_bytes) { + auto &global_state = gstate.Cast(); + return global_state.FileSize() > file_size_bytes.GetIndex(); +} + void CSVCopyFunction::RegisterFunction(BuiltinFunctions &set) { CopyFunction info("csv"); info.copy_to_bind = WriteCSVBind; @@ -601,7 +608,8 @@ void CSVCopyFunction::RegisterFunction(BuiltinFunctions &set) { info.execution_mode = WriteCSVExecutionMode; info.prepare_batch = WriteCSVPrepareBatch; info.flush_batch = WriteCSVFlushBatch; - info.file_size_bytes = WriteCSVFileSize; + info.rotate_files = WriteCSVRotateFiles; + info.rotate_next_file = WriteCSVRotateNextFile; info.copy_from_bind = ReadCSVBind; info.copy_from_function = ReadCSVTableFunction::GetFunction(); diff --git a/src/function/table/glob.cpp b/src/function/table/glob.cpp index 84dbc688ce1..d31462450ac 100644 --- a/src/function/table/glob.cpp +++ b/src/function/table/glob.cpp @@ -8,27 +8,33 @@ namespace duckdb { struct GlobFunctionBindData : public TableFunctionData { - vector files; + unique_ptr file_list; }; static unique_ptr GlobFunctionBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { auto result = make_uniq(); - result->files = MultiFileReader::GetFileList(context, input.inputs[0], "Globbing", FileGlobOptions::ALLOW_EMPTY); + auto multi_file_reader = MultiFileReader::Create(input.table_function); + result->file_list = multi_file_reader->CreateFileList(context, input.inputs[0], FileGlobOptions::ALLOW_EMPTY); return_types.emplace_back(LogicalType::VARCHAR); names.emplace_back("file"); return std::move(result); } struct GlobFunctionState : public GlobalTableFunctionState { - GlobFunctionState() : current_idx(0) { + GlobFunctionState() { } - idx_t current_idx; + MultiFileListScanData file_list_scan; }; static unique_ptr GlobFunctionInit(ClientContext &context, TableFunctionInitInput &input) { - return make_uniq(); + auto &bind_data = input.bind_data->Cast(); + auto res = make_uniq(); + + bind_data.file_list->InitializeScan(res->file_list_scan); + + return std::move(res); } static void GlobFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { @@ -36,10 +42,12 @@ static void GlobFunction(ClientContext &context, TableFunctionInput &data_p, Dat auto &state = data_p.global_state->Cast(); idx_t count = 0; - idx_t next_idx = MinValue(state.current_idx + STANDARD_VECTOR_SIZE, bind_data.files.size()); - for (; state.current_idx < next_idx; state.current_idx++) { - output.data[0].SetValue(count, bind_data.files[state.current_idx]); - count++; + while (count < STANDARD_VECTOR_SIZE) { + string file; + if (!bind_data.file_list->Scan(state.file_list_scan, file)) { + break; + } + output.data[0].SetValue(count++, file); } output.SetCardinality(count); } diff --git a/src/function/table/query_function.cpp b/src/function/table/query_function.cpp new file mode 100644 index 00000000000..8a18b1cb3c1 --- /dev/null +++ b/src/function/table/query_function.cpp @@ -0,0 +1,75 @@ +#include "duckdb/parser/parser.hpp" +#include "duckdb/main/client_context.hpp" +#include "duckdb/function/table/range.hpp" +#include "duckdb/function/function_set.hpp" +#include "duckdb/parser/tableref/subqueryref.hpp" + +namespace duckdb { + +static unique_ptr ParseSubquery(const string &query, const ParserOptions &options, const string &err_msg) { + Parser parser(options); + parser.ParseQuery(query); + if (parser.statements.size() != 1 || parser.statements[0]->type != StatementType::SELECT_STATEMENT) { + throw ParserException(err_msg); + } + auto select_stmt = unique_ptr_cast(std::move(parser.statements[0])); + return duckdb::make_uniq(std::move(select_stmt)); +} + +static void UnionTablesQuery(TableFunctionBindInput &input, string &query) { + string by_name = (input.inputs.size() == 2 && + (input.inputs[1].type().id() == LogicalTypeId::BOOLEAN && input.inputs[1].GetValue())) + ? "BY NAME " + : ""; // 'by_name' variable defaults to false + if (input.inputs[0].type().id() == LogicalTypeId::VARCHAR) { + query += "FROM " + KeywordHelper::WriteOptionallyQuoted(input.inputs[0].ToString()); + } else if (input.inputs[0].type() == LogicalType::LIST(LogicalType::VARCHAR)) { + string union_all_clause = " UNION ALL " + by_name + "FROM "; + const auto &children = ListValue::GetChildren(input.inputs[0]); + if (children.empty()) { + throw InvalidInputException("Input list is empty"); + } + + query += "FROM " + KeywordHelper::WriteOptionallyQuoted(children[0].ToString()); + for (size_t i = 1; i < children.size(); ++i) { + auto child = children[i].ToString(); + query += union_all_clause + KeywordHelper::WriteOptionallyQuoted(child); + } + } else { + throw InvalidInputException("Expected a table or a list with tables as input"); + } +} + +static unique_ptr QueryBindReplace(ClientContext &context, TableFunctionBindInput &input) { + auto query = input.inputs[0].ToString(); + auto subquery_ref = ParseSubquery(query, context.GetParserOptions(), "Expected a single SELECT statement"); + return std::move(subquery_ref); +} + +static unique_ptr TableBindReplace(ClientContext &context, TableFunctionBindInput &input) { + string query; + UnionTablesQuery(input, query); + auto subquery_ref = + ParseSubquery(query, context.GetParserOptions(), "Expected a table or a list with tables as input"); + return std::move(subquery_ref); +} + +void QueryTableFunction::RegisterFunction(BuiltinFunctions &set) { + TableFunction query("query", {LogicalType::VARCHAR}, nullptr, nullptr); + query.bind_replace = QueryBindReplace; + set.AddFunction(query); + + TableFunctionSet query_table("query_table"); + TableFunction query_table_function({LogicalType::VARCHAR}, nullptr, nullptr); + query_table_function.bind_replace = TableBindReplace; + query_table.AddFunction(query_table_function); + + query_table_function.arguments = {LogicalType::LIST(LogicalType::VARCHAR)}; + query_table.AddFunction(query_table_function); + // add by_name option + query_table_function.arguments.emplace_back(LogicalType::BOOLEAN); + query_table.AddFunction(query_table_function); + set.AddFunction(query_table); +} + +} // namespace duckdb diff --git a/src/function/table/range.cpp b/src/function/table/range.cpp index 884a51b754e..17bcda81d3d 100644 --- a/src/function/table/range.cpp +++ b/src/function/table/range.cpp @@ -11,129 +11,196 @@ namespace duckdb { //===--------------------------------------------------------------------===// // Range (integers) //===--------------------------------------------------------------------===// +static void GetParameters(int64_t values[], idx_t value_count, hugeint_t &start, hugeint_t &end, hugeint_t &increment) { + if (value_count < 2) { + // single argument: only the end is specified + start = 0; + end = values[0]; + } else { + // two arguments: first two arguments are start and end + start = values[0]; + end = values[1]; + } + if (value_count < 3) { + increment = 1; + } else { + increment = values[2]; + } +} + struct RangeFunctionBindData : public TableFunctionData { + explicit RangeFunctionBindData(const vector &inputs) : cardinality(0) { + int64_t values[3]; + for (idx_t i = 0; i < inputs.size(); i++) { + if (inputs[i].IsNull()) { + return; + } + values[i] = inputs[i].GetValue(); + } + hugeint_t start; + hugeint_t end; + hugeint_t increment; + GetParameters(values, inputs.size(), start, end, increment); + cardinality = Hugeint::Cast((end - start) / increment); + } + + idx_t cardinality; +}; + +template +static unique_ptr RangeFunctionBind(ClientContext &context, TableFunctionBindInput &input, + vector &return_types, vector &names) { + return_types.emplace_back(LogicalType::BIGINT); + if (GENERATE_SERIES) { + names.emplace_back("generate_series"); + } else { + names.emplace_back("range"); + } + if (input.inputs.empty() || input.inputs.size() > 3) { + return nullptr; + } + return make_uniq(input.inputs); +} + +struct RangeFunctionLocalState : public LocalTableFunctionState { + RangeFunctionLocalState() { + } + + bool initialized_row = false; + idx_t current_input_row = 0; + idx_t current_idx = 0; + hugeint_t start; hugeint_t end; hugeint_t increment; - -public: - bool Equals(const FunctionData &other_p) const override { - auto &other = other_p.Cast(); - return other.start == start && other.end == end && other.increment == increment; - } }; +static unique_ptr RangeFunctionLocalInit(ExecutionContext &context, + TableFunctionInitInput &input, + GlobalTableFunctionState *global_state) { + return make_uniq(); +} + template -static void GenerateRangeParameters(const vector &inputs, RangeFunctionBindData &result) { - for (auto &input : inputs) { - if (input.IsNull()) { +static void GenerateRangeParameters(DataChunk &input, idx_t row_id, RangeFunctionLocalState &result) { + input.Flatten(); + for (idx_t c = 0; c < input.ColumnCount(); c++) { + if (FlatVector::IsNull(input.data[c], row_id)) { result.start = GENERATE_SERIES ? 1 : 0; result.end = 0; result.increment = 1; return; } } - if (inputs.size() < 2) { - // single argument: only the end is specified - result.start = 0; - result.end = inputs[0].GetValue(); - } else { - // two arguments: first two arguments are start and end - result.start = inputs[0].GetValue(); - result.end = inputs[1].GetValue(); - } - if (inputs.size() < 3) { - result.increment = 1; - } else { - result.increment = inputs[2].GetValue(); + int64_t values[3]; + for (idx_t c = 0; c < input.ColumnCount(); c++) { + if (c >= 3) { + throw InternalException("Unsupported parameter count for range function"); + } + values[c] = FlatVector::GetValue(input.data[c], row_id); } + GetParameters(values, input.ColumnCount(), result.start, result.end, result.increment); if (result.increment == 0) { throw BinderException("interval cannot be 0!"); } if (result.start > result.end && result.increment > 0) { throw BinderException("start is bigger than end, but increment is positive: cannot generate infinite series"); - } else if (result.start < result.end && result.increment < 0) { + } + if (result.start < result.end && result.increment < 0) { throw BinderException("start is smaller than end, but increment is negative: cannot generate infinite series"); } -} - -template -static unique_ptr RangeFunctionBind(ClientContext &context, TableFunctionBindInput &input, - vector &return_types, vector &names) { - auto result = make_uniq(); - auto &inputs = input.inputs; - GenerateRangeParameters(inputs, *result); - - return_types.emplace_back(LogicalType::BIGINT); if (GENERATE_SERIES) { // generate_series has inclusive bounds on the RHS - if (result->increment < 0) { - result->end = result->end - 1; + if (result.increment < 0) { + result.end = result.end - 1; } else { - result->end = result->end + 1; + result.end = result.end + 1; } - names.emplace_back("generate_series"); - } else { - names.emplace_back("range"); } - return std::move(result); } -struct RangeFunctionState : public GlobalTableFunctionState { - RangeFunctionState() : current_idx(0) { - } - - int64_t current_idx; -}; - -static unique_ptr RangeFunctionInit(ClientContext &context, TableFunctionInitInput &input) { - return make_uniq(); -} - -static void RangeFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { - auto &bind_data = data_p.bind_data->Cast(); - auto &state = data_p.global_state->Cast(); - - auto increment = bind_data.increment; - auto end = bind_data.end; - hugeint_t current_value = bind_data.start + increment * state.current_idx; - int64_t current_value_i64; - if (!Hugeint::TryCast(current_value, current_value_i64)) { - return; +template +static OperatorResultType RangeFunction(ExecutionContext &context, TableFunctionInput &data_p, DataChunk &input, + DataChunk &output) { + auto &state = data_p.local_state->Cast(); + while (true) { + if (!state.initialized_row) { + // initialize for the current input row + if (state.current_input_row >= input.size()) { + // ran out of rows + state.current_input_row = 0; + state.initialized_row = false; + return OperatorResultType::NEED_MORE_INPUT; + } + GenerateRangeParameters(input, state.current_input_row, state); + state.initialized_row = true; + state.current_idx = 0; + } + auto increment = state.increment; + auto end = state.end; + hugeint_t current_value = state.start + increment * UnsafeNumericCast(state.current_idx); + int64_t current_value_i64; + if (!Hugeint::TryCast(current_value, current_value_i64)) { + // move to next row + state.current_input_row++; + state.initialized_row = false; + continue; + } + int64_t offset = increment < 0 ? 1 : -1; + idx_t remaining = MinValue( + Hugeint::Cast((end - current_value + (increment + offset)) / increment), STANDARD_VECTOR_SIZE); + // set the result vector as a sequence vector + output.data[0].Sequence(current_value_i64, Hugeint::Cast(increment), remaining); + // increment the index pointer by the remaining count + state.current_idx += remaining; + output.SetCardinality(remaining); + if (remaining == 0) { + // move to next row + state.current_input_row++; + state.initialized_row = false; + continue; + } + return OperatorResultType::HAVE_MORE_OUTPUT; } - int64_t offset = increment < 0 ? 1 : -1; - idx_t remaining = MinValue(Hugeint::Cast((end - current_value + (increment + offset)) / increment), - STANDARD_VECTOR_SIZE); - // set the result vector as a sequence vector - output.data[0].Sequence(current_value_i64, Hugeint::Cast(increment), remaining); - // increment the index pointer by the remaining count - state.current_idx += remaining; - output.SetCardinality(remaining); } unique_ptr RangeCardinality(ClientContext &context, const FunctionData *bind_data_p) { + if (!bind_data_p) { + return nullptr; + } auto &bind_data = bind_data_p->Cast(); - idx_t cardinality = Hugeint::Cast((bind_data.end - bind_data.start) / bind_data.increment); - return make_uniq(cardinality, cardinality); + return make_uniq(bind_data.cardinality, bind_data.cardinality); } //===--------------------------------------------------------------------===// // Range (timestamp) //===--------------------------------------------------------------------===// -struct RangeDateTimeBindData : public TableFunctionData { +template +static unique_ptr RangeDateTimeBind(ClientContext &context, TableFunctionBindInput &input, + vector &return_types, vector &names) { + return_types.push_back(LogicalType::TIMESTAMP); + if (GENERATE_SERIES) { + names.emplace_back("generate_series"); + } else { + names.emplace_back("range"); + } + return nullptr; +} + +struct RangeDateTimeLocalState : public LocalTableFunctionState { + RangeDateTimeLocalState() { + } + + bool initialized_row = false; + idx_t current_input_row = 0; + timestamp_t current_state; + timestamp_t start; timestamp_t end; interval_t increment; bool inclusive_bound; bool greater_than_check; -public: - bool Equals(const FunctionData &other_p) const override { - auto &other = other_p.Cast(); - return other.start == start && other.end == end && other.increment == increment && - other.inclusive_bound == inclusive_bound && other.greater_than_check == greater_than_check; - } - bool Finished(timestamp_t current_value) const { if (greater_than_check) { if (inclusive_bound) { @@ -152,98 +219,105 @@ struct RangeDateTimeBindData : public TableFunctionData { }; template -static unique_ptr RangeDateTimeBind(ClientContext &context, TableFunctionBindInput &input, - vector &return_types, vector &names) { - auto result = make_uniq(); - auto &inputs = input.inputs; - D_ASSERT(inputs.size() == 3); - for (idx_t i = 0; i < inputs.size(); ++i) { - if (inputs[i].IsNull()) { - throw BinderException("RANGE with NULL argument is not supported"); +static void GenerateRangeDateTimeParameters(DataChunk &input, idx_t row_id, RangeDateTimeLocalState &result) { + input.Flatten(); + + for (idx_t c = 0; c < input.ColumnCount(); c++) { + if (FlatVector::IsNull(input.data[c], row_id)) { + result.start = timestamp_t(0); + result.end = timestamp_t(0); + result.increment = interval_t(); + result.greater_than_check = true; + result.inclusive_bound = false; + return; } } - result->start = inputs[0].GetValue(); - result->end = inputs[1].GetValue(); - result->increment = inputs[2].GetValue(); + + result.start = FlatVector::GetValue(input.data[0], row_id); + result.end = FlatVector::GetValue(input.data[1], row_id); + result.increment = FlatVector::GetValue(input.data[2], row_id); // Infinities either cause errors or infinite loops, so just ban them - if (!Timestamp::IsFinite(result->start) || !Timestamp::IsFinite(result->end)) { + if (!Timestamp::IsFinite(result.start) || !Timestamp::IsFinite(result.end)) { throw BinderException("RANGE with infinite bounds is not supported"); } - if (result->increment.months == 0 && result->increment.days == 0 && result->increment.micros == 0) { + if (result.increment.months == 0 && result.increment.days == 0 && result.increment.micros == 0) { throw BinderException("interval cannot be 0!"); } // all elements should point in the same direction - if (result->increment.months > 0 || result->increment.days > 0 || result->increment.micros > 0) { - if (result->increment.months < 0 || result->increment.days < 0 || result->increment.micros < 0) { + if (result.increment.months > 0 || result.increment.days > 0 || result.increment.micros > 0) { + if (result.increment.months < 0 || result.increment.days < 0 || result.increment.micros < 0) { throw BinderException("RANGE with composite interval that has mixed signs is not supported"); } - result->greater_than_check = true; - if (result->start > result->end) { + result.greater_than_check = true; + if (result.start > result.end) { throw BinderException( "start is bigger than end, but increment is positive: cannot generate infinite series"); } } else { - result->greater_than_check = false; - if (result->start < result->end) { + result.greater_than_check = false; + if (result.start < result.end) { throw BinderException( "start is smaller than end, but increment is negative: cannot generate infinite series"); } } - return_types.push_back(inputs[0].type()); - if (GENERATE_SERIES) { - // generate_series has inclusive bounds on the RHS - result->inclusive_bound = true; - names.emplace_back("generate_series"); - } else { - result->inclusive_bound = false; - names.emplace_back("range"); - } - return std::move(result); + result.inclusive_bound = GENERATE_SERIES; } -struct RangeDateTimeState : public GlobalTableFunctionState { - explicit RangeDateTimeState(timestamp_t start_p) : current_state(start_p) { - } - - timestamp_t current_state; - bool finished = false; -}; - -static unique_ptr RangeDateTimeInit(ClientContext &context, TableFunctionInitInput &input) { - auto &bind_data = input.bind_data->Cast(); - return make_uniq(bind_data.start); +static unique_ptr RangeDateTimeLocalInit(ExecutionContext &context, + TableFunctionInitInput &input, + GlobalTableFunctionState *global_state) { + return make_uniq(); } -static void RangeDateTimeFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { - auto &bind_data = data_p.bind_data->Cast(); - auto &state = data_p.global_state->Cast(); - if (state.finished) { - return; - } - - idx_t size = 0; - auto data = FlatVector::GetData(output.data[0]); +template +static OperatorResultType RangeDateTimeFunction(ExecutionContext &context, TableFunctionInput &data_p, DataChunk &input, + DataChunk &output) { + auto &state = data_p.local_state->Cast(); while (true) { - if (bind_data.Finished(state.current_state)) { - state.finished = true; - break; + if (!state.initialized_row) { + // initialize for the current input row + if (state.current_input_row >= input.size()) { + // ran out of rows + state.current_input_row = 0; + state.initialized_row = false; + return OperatorResultType::NEED_MORE_INPUT; + } + GenerateRangeDateTimeParameters(input, state.current_input_row, state); + state.initialized_row = true; + state.current_state = state.start; + } + idx_t size = 0; + auto data = FlatVector::GetData(output.data[0]); + while (true) { + if (state.Finished(state.current_state)) { + break; + } + if (size >= STANDARD_VECTOR_SIZE) { + break; + } + data[size++] = state.current_state; + state.current_state = + AddOperator::Operation(state.current_state, state.increment); } - if (size >= STANDARD_VECTOR_SIZE) { - break; + if (size == 0) { + // move to next row + state.current_input_row++; + state.initialized_row = false; + continue; } - data[size++] = state.current_state; - state.current_state = - AddOperator::Operation(state.current_state, bind_data.increment); + output.SetCardinality(size); + return OperatorResultType::HAVE_MORE_OUTPUT; } - output.SetCardinality(size); } void RangeTableFunction::RegisterFunction(BuiltinFunctions &set) { TableFunctionSet range("range"); - TableFunction range_function({LogicalType::BIGINT}, RangeFunction, RangeFunctionBind, RangeFunctionInit); + TableFunction range_function({LogicalType::BIGINT}, nullptr, RangeFunctionBind, nullptr, + RangeFunctionLocalInit); + range_function.in_out_function = RangeFunction; range_function.cardinality = RangeCardinality; // single argument range: (end) - implicit start = 0 and increment = 1 @@ -254,20 +328,25 @@ void RangeTableFunction::RegisterFunction(BuiltinFunctions &set) { // three arguments range: (start, end, increment) range_function.arguments = {LogicalType::BIGINT, LogicalType::BIGINT, LogicalType::BIGINT}; range.AddFunction(range_function); - range.AddFunction(TableFunction({LogicalType::TIMESTAMP, LogicalType::TIMESTAMP, LogicalType::INTERVAL}, - RangeDateTimeFunction, RangeDateTimeBind, RangeDateTimeInit)); + TableFunction range_in_out({LogicalType::TIMESTAMP, LogicalType::TIMESTAMP, LogicalType::INTERVAL}, nullptr, + RangeDateTimeBind, nullptr, RangeDateTimeLocalInit); + range_in_out.in_out_function = RangeDateTimeFunction; + range.AddFunction(range_in_out); set.AddFunction(range); // generate_series: similar to range, but inclusive instead of exclusive bounds on the RHS TableFunctionSet generate_series("generate_series"); range_function.bind = RangeFunctionBind; + range_function.in_out_function = RangeFunction; range_function.arguments = {LogicalType::BIGINT}; generate_series.AddFunction(range_function); range_function.arguments = {LogicalType::BIGINT, LogicalType::BIGINT}; generate_series.AddFunction(range_function); range_function.arguments = {LogicalType::BIGINT, LogicalType::BIGINT, LogicalType::BIGINT}; generate_series.AddFunction(range_function); - generate_series.AddFunction(TableFunction({LogicalType::TIMESTAMP, LogicalType::TIMESTAMP, LogicalType::INTERVAL}, - RangeDateTimeFunction, RangeDateTimeBind, RangeDateTimeInit)); + TableFunction generate_series_in_out({LogicalType::TIMESTAMP, LogicalType::TIMESTAMP, LogicalType::INTERVAL}, + nullptr, RangeDateTimeBind, nullptr, RangeDateTimeLocalInit); + generate_series_in_out.in_out_function = RangeDateTimeFunction; + generate_series.AddFunction(generate_series_in_out); set.AddFunction(generate_series); } @@ -282,6 +361,7 @@ void BuiltinFunctions::RegisterTableFunctions() { CSVSnifferFunction::RegisterFunction(*this); ReadBlobFunction::RegisterFunction(*this); ReadTextFunction::RegisterFunction(*this); + QueryTableFunction::RegisterFunction(*this); } } // namespace duckdb diff --git a/src/function/table/read_csv.cpp b/src/function/table/read_csv.cpp index 181c6f13b46..59091c0c581 100644 --- a/src/function/table/read_csv.cpp +++ b/src/function/table/read_csv.cpp @@ -48,7 +48,8 @@ static unique_ptr ReadCSVBind(ClientContext &context, TableFunctio auto result = make_uniq(); auto &options = result->options; - result->files = MultiFileReader::GetFileList(context, input.inputs[0], "CSV"); + auto multi_file_reader = MultiFileReader::Create(input.table_function); + auto multi_file_list = multi_file_reader->CreateFileList(context, input.inputs[0]); options.FromNamedParameters(input.named_parameters, context, return_types, names); if (options.rejects_table_name.IsSetByUser() && !options.store_rejects.GetValue() && @@ -79,7 +80,7 @@ static unique_ptr ReadCSVBind(ClientContext &context, TableFunctio throw BinderException("REJECTS_LIMIT option is only supported when REJECTS_TABLE is set to a table name"); } - options.file_options.AutoDetectHivePartitioning(result->files, context); + options.file_options.AutoDetectHivePartitioning(*multi_file_list, context); if (!options.auto_detect && return_types.empty()) { throw BinderException("read_csv requires columns to be specified through the 'columns' option. Use " @@ -87,8 +88,8 @@ static unique_ptr ReadCSVBind(ClientContext &context, TableFunctio "AUTO_DETECT=TRUE) to automatically guess columns."); } if (options.auto_detect && !options.file_options.union_by_name) { - options.file_path = result->files[0]; - result->buffer_manager = make_shared_ptr(context, options, result->files[0], 0); + options.file_path = multi_file_list->GetFirstFile(); + result->buffer_manager = make_shared_ptr(context, options, options.file_path, 0); CSVSniffer sniffer(options, result->buffer_manager, CSVStateMachineCache::Get(context), {&return_types, &names}); auto sniffer_result = sniffer.SniffCSV(); @@ -103,8 +104,8 @@ static unique_ptr ReadCSVBind(ClientContext &context, TableFunctio D_ASSERT(return_types.size() == names.size()); result->options.dialect_options.num_cols = names.size(); if (options.file_options.union_by_name) { - result->reader_bind = - MultiFileReader::BindUnionReader(context, return_types, names, *result, options); + result->reader_bind = multi_file_reader->BindUnionReader(context, return_types, names, + *multi_file_list, *result, options); if (result->union_readers.size() > 1) { result->column_info.emplace_back(result->initial_reader->names, result->initial_reader->types); for (idx_t i = 1; i < result->union_readers.size(); i++) { @@ -128,7 +129,8 @@ static unique_ptr ReadCSVBind(ClientContext &context, TableFunctio } else { result->csv_types = return_types; result->csv_names = names; - result->reader_bind = MultiFileReader::BindOptions(options.file_options, result->files, return_types, names); + multi_file_reader->BindOptions(options.file_options, *multi_file_list, return_types, names, + result->reader_bind); } result->return_types = return_types; result->return_names = names; @@ -153,6 +155,10 @@ static unique_ptr ReadCSVBind(ClientContext &context, TableFunctio } } } + + // TODO: make the CSV reader use MultiFileList throughout, instead of converting to vector + result->files = multi_file_list->GetAllFiles(); + result->Finalize(); return std::move(result); } @@ -196,6 +202,10 @@ unique_ptr ReadCSVInitLocal(ExecutionContext &context, return nullptr; } auto &global_state = global_state_p->Cast(); + if (global_state.current_boundary.done) { + // nothing to do + return nullptr; + } auto csv_scanner = global_state.Next(nullptr); if (!csv_scanner) { global_state.DecrementThread(); @@ -209,6 +219,9 @@ static void ReadCSVFunction(ClientContext &context, TableFunctionInput &data_p, return; } auto &csv_global_state = data_p.global_state->Cast(); + if (!data_p.local_state) { + return; + } auto &csv_local_state = data_p.local_state->Cast(); if (!csv_local_state.csv_reader) { @@ -217,8 +230,8 @@ static void ReadCSVFunction(ClientContext &context, TableFunctionInput &data_p, } do { if (output.size() != 0) { - MultiFileReader::FinalizeChunk(bind_data.reader_bind, - csv_local_state.csv_reader->csv_file_scan->reader_data, output); + MultiFileReader().FinalizeChunk(context, bind_data.reader_bind, + csv_local_state.csv_reader->csv_file_scan->reader_data, output, nullptr); break; } if (csv_local_state.csv_reader->FinishedIterator()) { @@ -276,6 +289,7 @@ void ReadCSVTableFunction::ReadCSVAddNamedParameters(TableFunction &table_functi table_function.named_parameters["names"] = LogicalType::LIST(LogicalType::VARCHAR); table_function.named_parameters["column_names"] = LogicalType::LIST(LogicalType::VARCHAR); table_function.named_parameters["parallel"] = LogicalType::BOOLEAN; + MultiFileReader::AddParameters(table_function); } @@ -292,10 +306,14 @@ double CSVReaderProgress(ClientContext &context, const FunctionData *bind_data_p void CSVComplexFilterPushdown(ClientContext &context, LogicalGet &get, FunctionData *bind_data_p, vector> &filters) { auto &data = bind_data_p->Cast(); - auto reset_reader = - MultiFileReader::ComplexFilterPushdown(context, data.files, data.options.file_options, get, filters); - if (reset_reader) { - MultiFileReader::PruneReaders(data); + SimpleMultiFileList file_list(data.files); + auto filtered_list = + MultiFileReader().ComplexFilterPushdown(context, file_list, data.options.file_options, get, filters); + if (filtered_list) { + data.files = filtered_list->GetAllFiles(); + MultiFileReader::PruneReaders(data, file_list); + } else { + data.files = file_list.GetAllFiles(); } } @@ -326,6 +344,15 @@ static unique_ptr CSVReaderDeserialize(Deserializer &deserializer, return std::move(result); } +void PushdownTypeToCSVScanner(ClientContext &context, optional_ptr bind_data, + const unordered_map &new_column_types) { + auto &csv_bind = bind_data->Cast(); + for (auto &type : new_column_types) { + csv_bind.csv_types[type.first] = type.second; + csv_bind.return_types[type.first] = type.second; + } +} + TableFunction ReadCSVTableFunction::GetFunction() { TableFunction read_csv("read_csv", {LogicalType::VARCHAR}, ReadCSVFunction, ReadCSVBind, ReadCSVInitGlobal, ReadCSVInitLocal); @@ -336,6 +363,7 @@ TableFunction ReadCSVTableFunction::GetFunction() { read_csv.get_batch_index = CSVReaderGetBatchIndex; read_csv.cardinality = CSVReaderCardinality; read_csv.projection_pushdown = true; + read_csv.type_pushdown = PushdownTypeToCSVScanner; ReadCSVAddNamedParameters(read_csv); return read_csv; } @@ -352,7 +380,9 @@ void ReadCSVTableFunction::RegisterFunction(BuiltinFunctions &set) { set.AddFunction(MultiFileReader::CreateFunctionSet(ReadCSVTableFunction::GetAutoFunction())); } -unique_ptr ReadCSVReplacement(ClientContext &context, const string &table_name, ReplacementScanData *data) { +unique_ptr ReadCSVReplacement(ClientContext &context, ReplacementScanInput &input, + optional_ptr data) { + auto &table_name = input.table_name; auto lower_name = StringUtil::Lower(table_name); // remove any compression if (StringUtil::EndsWith(lower_name, ".gz")) { diff --git a/src/function/table/read_file.cpp b/src/function/table/read_file.cpp index c6aa707d026..e9039b0bfe4 100644 --- a/src/function/table/read_file.cpp +++ b/src/function/table/read_file.cpp @@ -53,7 +53,10 @@ template static unique_ptr ReadFileBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { auto result = make_uniq(); - result->files = MultiFileReader::GetFileList(context, input.inputs[0], OP::FILE_TYPE, FileGlobOptions::ALLOW_EMPTY); + + auto multi_file_reader = MultiFileReader::Create(input.table_function); + result->files = + multi_file_reader->CreateFileList(context, input.inputs[0], FileGlobOptions::ALLOW_EMPTY)->GetAllFiles(); return_types.push_back(LogicalType::VARCHAR); names.push_back("filename"); diff --git a/src/function/table/repeat.cpp b/src/function/table/repeat.cpp index 25fa43dc067..08fdc0086f5 100644 --- a/src/function/table/repeat.cpp +++ b/src/function/table/repeat.cpp @@ -26,7 +26,11 @@ static unique_ptr RepeatBind(ClientContext &context, TableFunction if (inputs[1].IsNull()) { throw BinderException("Repeat second parameter cannot be NULL"); } - return make_uniq(inputs[0], NumericCast(inputs[1].GetValue())); + auto repeat_count = inputs[1].GetValue(); + if (repeat_count < 0) { + throw BinderException("Repeat second parameter cannot be be less than 0"); + } + return make_uniq(inputs[0], NumericCast(repeat_count)); } static unique_ptr RepeatInit(ClientContext &context, TableFunctionInitInput &input) { diff --git a/src/function/table/sniff_csv.cpp b/src/function/table/sniff_csv.cpp index 11dfb779757..d395e9dd296 100644 --- a/src/function/table/sniff_csv.cpp +++ b/src/function/table/sniff_csv.cpp @@ -66,7 +66,9 @@ static unique_ptr CSVSniffBind(ClientContext &context, TableFuncti return_types.emplace_back(LogicalType::BOOLEAN); names.emplace_back("HasHeader"); // 7. List> - return_types.emplace_back(LogicalType::VARCHAR); + child_list_t struct_children {{"name", LogicalType::VARCHAR}, {"type", LogicalType::VARCHAR}}; + auto list_child = LogicalType::STRUCT(struct_children); + return_types.emplace_back(LogicalType::LIST(list_child)); names.emplace_back("Columns"); // 8. Date Format return_types.emplace_back(LogicalType::VARCHAR); @@ -141,16 +143,20 @@ static void CSVSniffFunction(ClientContext &context, TableFunctionInput &data_p, auto has_header = Value::BOOLEAN(sniffer_options.dialect_options.header.GetValue()).ToString(); output.SetValue(5, 0, has_header); // 7. List> {'col1': 'INTEGER', 'col2': 'VARCHAR'} + vector values; std::ostringstream columns; columns << "{"; for (idx_t i = 0; i < sniffer_result.return_types.size(); i++) { + child_list_t struct_children {{"name", sniffer_result.names[i]}, + {"type", {sniffer_result.return_types[i].ToString()}}}; + values.emplace_back(Value::STRUCT(struct_children)); columns << "'" << sniffer_result.names[i] << "': '" << sniffer_result.return_types[i].ToString() << "'"; if (i != sniffer_result.return_types.size() - 1) { columns << separator; } } columns << "}"; - output.SetValue(6, 0, columns.str()); + output.SetValue(6, 0, Value::LIST(values)); // 8. Date Format auto date_format = sniffer_options.dialect_options.date_format[LogicalType::DATE].GetValue(); if (!date_format.Empty()) { diff --git a/src/function/table/system/duckdb_databases.cpp b/src/function/table/system/duckdb_databases.cpp index 0aee93897a0..2c7c9c91331 100644 --- a/src/function/table/system/duckdb_databases.cpp +++ b/src/function/table/system/duckdb_databases.cpp @@ -26,6 +26,9 @@ static unique_ptr DuckDBDatabasesBind(ClientContext &context, Tabl names.emplace_back("comment"); return_types.emplace_back(LogicalType::VARCHAR); + names.emplace_back("tags"); + return_types.emplace_back(LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR)); + names.emplace_back("internal"); return_types.emplace_back(LogicalType::BOOLEAN); @@ -80,6 +83,8 @@ void DuckDBDatabasesFunction(ClientContext &context, TableFunctionInput &data_p, output.SetValue(col++, count, db_path); // comment, VARCHAR output.SetValue(col++, count, Value(attached.comment)); + // tags, MAP + output.SetValue(col++, count, Value::MAP(attached.tags)); // internal, BOOLEAN output.SetValue(col++, count, Value::BOOLEAN(is_internal)); // type, VARCHAR diff --git a/src/function/table/system/duckdb_extensions.cpp b/src/function/table/system/duckdb_extensions.cpp index 7a2f4510887..3c7f2396b0a 100644 --- a/src/function/table/system/duckdb_extensions.cpp +++ b/src/function/table/system/duckdb_extensions.cpp @@ -8,6 +8,10 @@ #include "duckdb/main/database.hpp" #include "duckdb/main/extension_helper.hpp" +#include "duckdb/common/serializer/buffered_file_reader.hpp" +#include "duckdb/common/serializer/binary_deserializer.hpp" +#include "duckdb/main/extension_install_info.hpp" + namespace duckdb { struct ExtensionInformation { @@ -15,6 +19,8 @@ struct ExtensionInformation { bool loaded = false; bool installed = false; string file_path; + ExtensionInstallMode install_mode; + string installed_from; string description; vector aliases; string extension_version; @@ -51,6 +57,12 @@ static unique_ptr DuckDBExtensionsBind(ClientContext &context, Tab names.emplace_back("extension_version"); return_types.emplace_back(LogicalType::VARCHAR); + names.emplace_back("install_mode"); + return_types.emplace_back(LogicalType::VARCHAR); + + names.emplace_back("installed_from"); + return_types.emplace_back(LogicalType::VARCHAR); + return nullptr; } @@ -60,6 +72,7 @@ unique_ptr DuckDBExtensionsInit(ClientContext &context auto &fs = FileSystem::GetFileSystem(context); auto &db = DatabaseInstance::GetDatabase(context); + // Firstly, we go over all Default Extensions: duckdb_extensions always prints those, installed/loaded or not map installed_extensions; auto extension_count = ExtensionHelper::DefaultExtensionCount(); auto alias_count = ExtensionHelper::ExtensionAliasCount(); @@ -70,6 +83,8 @@ unique_ptr DuckDBExtensionsInit(ClientContext &context info.installed = extension.statically_loaded; info.loaded = false; info.file_path = extension.statically_loaded ? "(BUILT-IN)" : string(); + info.install_mode = + extension.statically_loaded ? ExtensionInstallMode::STATICALLY_LINKED : ExtensionInstallMode::UNKNOWN; info.description = extension.description; for (idx_t k = 0; k < alias_count; k++) { auto alias = ExtensionHelper::GetExtensionAlias(k); @@ -79,8 +94,9 @@ unique_ptr DuckDBExtensionsInit(ClientContext &context } installed_extensions[info.name] = std::move(info); } + + // Secondly we scan all installed extensions and their install info #ifndef WASM_LOADABLE_EXTENSIONS - // scan the install directory for installed extensions auto ext_directory = ExtensionHelper::ExtensionDirectory(context); fs.ListFiles(ext_directory, [&](const string &path, bool is_directory) { if (!StringUtil::EndsWith(path, ".duckdb_extension")) { @@ -88,34 +104,55 @@ unique_ptr DuckDBExtensionsInit(ClientContext &context } ExtensionInformation info; info.name = fs.ExtractBaseName(path); + info.installed = true; info.loaded = false; info.file_path = fs.JoinPath(ext_directory, path); + + // Check the info file for its installation source + auto info_file_path = fs.JoinPath(ext_directory, path + ".info"); + + // Read the info file + auto extension_install_info = ExtensionInstallInfo::TryReadInfoFile(fs, info_file_path, info.name); + info.install_mode = extension_install_info->mode; + info.extension_version = extension_install_info->version; + if (extension_install_info->mode == ExtensionInstallMode::REPOSITORY) { + info.installed_from = ExtensionRepository::GetRepository(extension_install_info->repository_url); + } else { + info.installed_from = extension_install_info->full_path; + } + auto entry = installed_extensions.find(info.name); if (entry == installed_extensions.end()) { installed_extensions[info.name] = std::move(info); } else { - if (!entry->second.loaded) { + if (entry->second.install_mode != ExtensionInstallMode::STATICALLY_LINKED) { entry->second.file_path = info.file_path; + entry->second.install_mode = info.install_mode; + entry->second.installed_from = info.installed_from; + entry->second.install_mode = info.install_mode; + entry->second.extension_version = info.extension_version; } entry->second.installed = true; } }); #endif - // now check the list of currently loaded extensions + + // Finally, we check the list of currently loaded extensions auto &loaded_extensions = db.LoadedExtensionsData(); for (auto &e : loaded_extensions) { auto &ext_name = e.first; auto &ext_info = e.second; auto entry = installed_extensions.find(ext_name); - if (entry == installed_extensions.end()) { - ExtensionInformation info; + if (entry == installed_extensions.end() || !entry->second.installed) { + ExtensionInformation &info = installed_extensions[ext_name]; info.name = ext_name; info.loaded = true; - info.extension_version = ext_info.extension_version; - installed_extensions[ext_name] = std::move(info); + info.extension_version = ext_info.version; + info.installed = ext_info.mode == ExtensionInstallMode::STATICALLY_LINKED; + info.install_mode = ext_info.mode; } else { entry->second.loaded = true; - entry->second.extension_version = ext_info.extension_version; + entry->second.extension_version = ext_info.version; } } @@ -144,7 +181,7 @@ void DuckDBExtensionsFunction(ClientContext &context, TableFunctionInput &data_p // loaded LogicalType::BOOLEAN output.SetValue(1, count, Value::BOOLEAN(entry.loaded)); // installed LogicalType::BOOLEAN - output.SetValue(2, count, !entry.installed && entry.loaded ? Value() : Value::BOOLEAN(entry.installed)); + output.SetValue(2, count, Value::BOOLEAN(entry.installed)); // install_path LogicalType::VARCHAR output.SetValue(3, count, Value(entry.file_path)); // description LogicalType::VARCHAR @@ -153,6 +190,10 @@ void DuckDBExtensionsFunction(ClientContext &context, TableFunctionInput &data_p output.SetValue(5, count, Value::LIST(LogicalType::VARCHAR, entry.aliases)); // extension version LogicalType::LIST(LogicalType::VARCHAR) output.SetValue(6, count, Value(entry.extension_version)); + // installed_mode LogicalType::VARCHAR + output.SetValue(7, count, entry.installed ? Value(EnumUtil::ToString(entry.install_mode)) : Value()); + // installed_source LogicalType::VARCHAR + output.SetValue(8, count, Value(entry.installed_from)); data.offset++; count++; diff --git a/src/function/table/system/duckdb_functions.cpp b/src/function/table/system/duckdb_functions.cpp index 4dd287fd3ff..1ee4b85143b 100644 --- a/src/function/table/system/duckdb_functions.cpp +++ b/src/function/table/system/duckdb_functions.cpp @@ -49,6 +49,9 @@ static unique_ptr DuckDBFunctionsBind(ClientContext &context, Tabl names.emplace_back("comment"); return_types.emplace_back(LogicalType::VARCHAR); + names.emplace_back("tags"); + return_types.emplace_back(LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR)); + names.emplace_back("return_type"); return_types.emplace_back(LogicalType::VARCHAR); @@ -470,6 +473,9 @@ bool ExtractFunctionData(FunctionEntry &entry, idx_t function_idx, DataChunk &ou // comment, LogicalType::VARCHAR output.SetValue(col++, output_offset, entry.comment); + // tags, LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR) + output.SetValue(col++, output_offset, Value::MAP(entry.tags)); + // return_type, LogicalType::VARCHAR output.SetValue(col++, output_offset, OP::GetReturnType(function, function_idx)); diff --git a/src/function/table/system/duckdb_indexes.cpp b/src/function/table/system/duckdb_indexes.cpp index 0b8e78853b4..80938f605c1 100644 --- a/src/function/table/system/duckdb_indexes.cpp +++ b/src/function/table/system/duckdb_indexes.cpp @@ -45,6 +45,9 @@ static unique_ptr DuckDBIndexesBind(ClientContext &context, TableF names.emplace_back("comment"); return_types.emplace_back(LogicalType::VARCHAR); + names.emplace_back("tags"); + return_types.emplace_back(LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR)); + names.emplace_back("is_unique"); return_types.emplace_back(LogicalType::BOOLEAN); @@ -109,6 +112,8 @@ void DuckDBIndexesFunction(ClientContext &context, TableFunctionInput &data_p, D output.SetValue(col++, count, Value::BIGINT(NumericCast(table_entry.oid))); // comment, VARCHAR output.SetValue(col++, count, Value(index.comment)); + // tags, MAP + output.SetValue(col++, count, Value::MAP(index.tags)); // is_unique, BOOLEAN output.SetValue(col++, count, Value::BOOLEAN(index.IsUnique())); // is_primary, BOOLEAN diff --git a/src/function/table/system/duckdb_schemas.cpp b/src/function/table/system/duckdb_schemas.cpp index c8d9828e360..295d440b6eb 100644 --- a/src/function/table/system/duckdb_schemas.cpp +++ b/src/function/table/system/duckdb_schemas.cpp @@ -33,6 +33,9 @@ static unique_ptr DuckDBSchemasBind(ClientContext &context, TableF names.emplace_back("comment"); return_types.emplace_back(LogicalType::VARCHAR); + names.emplace_back("tags"); + return_types.emplace_back(LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR)); + names.emplace_back("internal"); return_types.emplace_back(LogicalType::BOOLEAN); @@ -75,6 +78,8 @@ void DuckDBSchemasFunction(ClientContext &context, TableFunctionInput &data_p, D output.SetValue(col++, count, Value(entry.name)); // "comment", PhysicalType::VARCHAR output.SetValue(col++, count, Value(entry.comment)); + // "tags", MAP(VARCHAR, VARCHAR) + output.SetValue(col++, count, Value::MAP(entry.tags)); // "internal", PhysicalType::BOOLEAN output.SetValue(col++, count, Value::BOOLEAN(entry.internal)); // "sql", PhysicalType::VARCHAR diff --git a/src/function/table/system/duckdb_sequences.cpp b/src/function/table/system/duckdb_sequences.cpp index 979ef65f005..b95d23c2e48 100644 --- a/src/function/table/system/duckdb_sequences.cpp +++ b/src/function/table/system/duckdb_sequences.cpp @@ -41,6 +41,9 @@ static unique_ptr DuckDBSequencesBind(ClientContext &context, Tabl names.emplace_back("comment"); return_types.emplace_back(LogicalType::VARCHAR); + names.emplace_back("tags"); + return_types.emplace_back(LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR)); + names.emplace_back("temporary"); return_types.emplace_back(LogicalType::BOOLEAN); @@ -109,6 +112,8 @@ void DuckDBSequencesFunction(ClientContext &context, TableFunctionInput &data_p, output.SetValue(col++, count, Value::BIGINT(NumericCast(seq.oid))); // comment, VARCHAR output.SetValue(col++, count, Value(seq.comment)); + // tags, MAP(VARCHAR, VARCHAR) + output.SetValue(col++, count, Value::MAP(seq.tags)); // temporary, BOOLEAN output.SetValue(col++, count, Value::BOOLEAN(seq.temporary)); // start_value, BIGINT diff --git a/src/function/table/system/duckdb_tables.cpp b/src/function/table/system/duckdb_tables.cpp index b605ca5f031..7f1386ab339 100644 --- a/src/function/table/system/duckdb_tables.cpp +++ b/src/function/table/system/duckdb_tables.cpp @@ -44,6 +44,9 @@ static unique_ptr DuckDBTablesBind(ClientContext &context, TableFu names.emplace_back("comment"); return_types.emplace_back(LogicalType::VARCHAR); + names.emplace_back("tags"); + return_types.emplace_back(LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR)); + names.emplace_back("internal"); return_types.emplace_back(LogicalType::BOOLEAN); @@ -138,6 +141,8 @@ void DuckDBTablesFunction(ClientContext &context, TableFunctionInput &data_p, Da output.SetValue(col++, count, Value::BIGINT(NumericCast(table.oid))); // comment, LogicalType::VARCHAR output.SetValue(col++, count, Value(table.comment)); + // tags, LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR) + output.SetValue(col++, count, Value::MAP(table.tags)); // internal, LogicalType::BOOLEAN output.SetValue(col++, count, Value::BOOLEAN(table.internal)); // temporary, LogicalType::BOOLEAN diff --git a/src/function/table/system/duckdb_types.cpp b/src/function/table/system/duckdb_types.cpp index 1b7ca0c9748..3872852d01d 100644 --- a/src/function/table/system/duckdb_types.cpp +++ b/src/function/table/system/duckdb_types.cpp @@ -52,6 +52,9 @@ static unique_ptr DuckDBTypesBind(ClientContext &context, TableFun names.emplace_back("comment"); return_types.emplace_back(LogicalType::VARCHAR); + names.emplace_back("tags"); + return_types.emplace_back(LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR)); + names.emplace_back("internal"); return_types.emplace_back(LogicalType::BOOLEAN); @@ -167,6 +170,8 @@ void DuckDBTypesFunction(ClientContext &context, TableFunctionInput &data_p, Dat output.SetValue(col++, count, category.empty() ? Value() : Value(category)); // comment, VARCHAR output.SetValue(col++, count, Value(type_entry.comment)); + // tags, MAP + output.SetValue(col++, count, Value::MAP(type_entry.tags)); // internal, BOOLEAN output.SetValue(col++, count, Value::BOOLEAN(type_entry.internal)); // labels, VARCHAR[] diff --git a/src/function/table/system/duckdb_views.cpp b/src/function/table/system/duckdb_views.cpp index e2eb2660346..1ae6fcce723 100644 --- a/src/function/table/system/duckdb_views.cpp +++ b/src/function/table/system/duckdb_views.cpp @@ -40,6 +40,9 @@ static unique_ptr DuckDBViewsBind(ClientContext &context, TableFun names.emplace_back("comment"); return_types.emplace_back(LogicalType::VARCHAR); + names.emplace_back("tags"); + return_types.emplace_back(LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR)); + names.emplace_back("internal"); return_types.emplace_back(LogicalType::BOOLEAN); @@ -100,6 +103,8 @@ void DuckDBViewsFunction(ClientContext &context, TableFunctionInput &data_p, Dat output.SetValue(col++, count, Value::BIGINT(NumericCast(view.oid))); // comment, LogicalType::VARCHARs output.SetValue(col++, count, Value(view.comment)); + // tags, LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR) + output.SetValue(col++, count, Value::MAP(view.tags)); // internal, LogicalType::BOOLEAN output.SetValue(col++, count, Value::BOOLEAN(view.internal)); // temporary, LogicalType::BOOLEAN diff --git a/src/function/table/table_scan.cpp b/src/function/table/table_scan.cpp index 26a9843775e..d6c7bdde4bd 100644 --- a/src/function/table/table_scan.cpp +++ b/src/function/table/table_scan.cpp @@ -202,8 +202,9 @@ unique_ptr TableScanCardinality(ClientContext &context, const Fu auto &bind_data = bind_data_p->Cast(); auto &local_storage = LocalStorage::Get(context, bind_data.table.catalog); auto &storage = bind_data.table.GetStorage(); - idx_t estimated_cardinality = storage.info->cardinality + local_storage.AddedRows(bind_data.table.GetStorage()); - return make_uniq(storage.info->cardinality, estimated_cardinality); + idx_t table_rows = storage.GetTotalRows(); + idx_t estimated_cardinality = table_rows + local_storage.AddedRows(bind_data.table.GetStorage()); + return make_uniq(table_rows, estimated_cardinality); } //===--------------------------------------------------------------------===// @@ -263,7 +264,8 @@ static void RewriteIndexExpression(Index &index, LogicalGet &get, Expression &ex auto &bound_colref = expr.Cast(); // bound column ref: rewrite to fit in the current set of bound column ids bound_colref.binding.table_index = get.table_index; - column_t referenced_column = index.column_ids[bound_colref.binding.column_index]; + auto &column_ids = index.GetColumnIds(); + column_t referenced_column = column_ids[bound_colref.binding.column_index]; // search for the referenced column in the set of column_ids for (idx_t i = 0; i < get.column_ids.size(); i++) { if (get.column_ids[i] == referenced_column) { @@ -306,22 +308,13 @@ void TableScanPushdownComplexFilter(ClientContext &context, LogicalGet &get, Fun return; } - // behold - storage.info->indexes.Scan([&](Index &index) { - // first rewrite the index expression so the ColumnBindings align with the column bindings of the current table - - if (index.IsUnknown()) { - // unknown index: skip - return false; - } - - if (index.index_type != ART::TYPE_NAME) { - // only ART indexes are supported for now - return false; - } - - auto &art_index = index.Cast(); + auto checkpoint_lock = storage.GetSharedCheckpointLock(); + auto &info = storage.GetDataTableInfo(); + auto &transaction = Transaction::Get(context, bind_data.table.catalog); + // bind and scan any ART indexes + info->GetIndexes().BindAndScan(context, *info, [&](ART &art_index) { + // first rewrite the index expression so the ColumnBindings align with the column bindings of the current table if (art_index.unbound_expressions.size() > 1) { // NOTE: index scans are not (yet) supported for compound index keys return false; @@ -336,8 +329,6 @@ void TableScanPushdownComplexFilter(ClientContext &context, LogicalGet &get, Fun } // try to find a matching index for any of the filter expressions - auto &transaction = Transaction::Get(context, bind_data.table.catalog); - for (auto &filter : filters) { auto index_state = art_index.TryInitializeScan(transaction, *index_expression, *filter); if (index_state != nullptr) { diff --git a/src/function/table/unnest.cpp b/src/function/table/unnest.cpp index b6485bc3d2a..b7599270f1c 100644 --- a/src/function/table/unnest.cpp +++ b/src/function/table/unnest.cpp @@ -47,7 +47,7 @@ static unique_ptr UnnestBind(ClientContext &context, TableFunction throw BinderException("UNNEST requires a single list as input"); } return_types.push_back(ListType::GetChildType(input.input_table_types[0])); - names.push_back(input.input_table_names[0]); + names.push_back("unnest"); return make_uniq(input.input_table_types[0]); } @@ -78,7 +78,8 @@ static OperatorResultType UnnestFunction(ExecutionContext &context, TableFunctio } void UnnestTableFunction::RegisterFunction(BuiltinFunctions &set) { - TableFunction unnest_function("unnest", {LogicalTypeId::TABLE}, nullptr, UnnestBind, UnnestInit, UnnestLocalInit); + TableFunction unnest_function("unnest", {LogicalType::LIST(LogicalType::ANY)}, nullptr, UnnestBind, UnnestInit, + UnnestLocalInit); unnest_function.in_out_function = UnnestFunction; set.AddFunction(unnest_function); } diff --git a/src/function/table_function.cpp b/src/function/table_function.cpp index 9d0ec2b2810..802f89fb6ee 100644 --- a/src/function/table_function.cpp +++ b/src/function/table_function.cpp @@ -18,8 +18,8 @@ TableFunction::TableFunction(string name, vector arguments, table_f init_global(init_global), init_local(init_local), function(function), in_out_function(nullptr), in_out_function_final(nullptr), statistics(nullptr), dependency(nullptr), cardinality(nullptr), pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), get_batch_index(nullptr), - get_bind_info(nullptr), serialize(nullptr), deserialize(nullptr), projection_pushdown(false), - filter_pushdown(false), filter_prune(false) { + get_bind_info(nullptr), type_pushdown(nullptr), get_multi_file_reader(nullptr), serialize(nullptr), + deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), filter_prune(false) { } TableFunction::TableFunction(const vector &arguments, table_function_t function, @@ -31,8 +31,9 @@ TableFunction::TableFunction() : SimpleNamedParameterFunction("", {}), bind(nullptr), bind_replace(nullptr), init_global(nullptr), init_local(nullptr), function(nullptr), in_out_function(nullptr), statistics(nullptr), dependency(nullptr), cardinality(nullptr), pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), - get_batch_index(nullptr), get_bind_info(nullptr), serialize(nullptr), deserialize(nullptr), - projection_pushdown(false), filter_pushdown(false), filter_prune(false) { + get_batch_index(nullptr), get_bind_info(nullptr), type_pushdown(nullptr), get_multi_file_reader(nullptr), + serialize(nullptr), deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), + filter_prune(false) { } bool TableFunction::Equal(const TableFunction &rhs) const { diff --git a/src/include/duckdb.h b/src/include/duckdb.h index 45606c8a31a..2277bd84a08 100644 --- a/src/include/duckdb.h +++ b/src/include/duckdb.h @@ -35,6 +35,13 @@ #endif #endif +//! In the future, we are planning to move extension functions to a separate header. For now you can set the define +//! below to remove the functions that are planned to be moved out of this header. +// #define DUCKDB_NO_EXTENSION_FUNCTIONS + +//! Set the define below to remove all functions that are deprecated or planned to be deprecated +// #define DUCKDB_API_NO_DEPRECATED + //! API versions //! If no explicit API version is defined, the latest API version is used. //! Note that using older API versions (i.e. not using DUCKDB_API_LATEST) is deprecated. @@ -137,23 +144,23 @@ typedef enum DUCKDB_TYPE { DUCKDB_TYPE_TIMESTAMP_TZ = 31, } duckdb_type; //! An enum over the returned state of different functions. -typedef enum { DuckDBSuccess = 0, DuckDBError = 1 } duckdb_state; +typedef enum duckdb_state { DuckDBSuccess = 0, DuckDBError = 1 } duckdb_state; //! An enum over the pending state of a pending query result. -typedef enum { +typedef enum duckdb_pending_state { DUCKDB_PENDING_RESULT_READY = 0, DUCKDB_PENDING_RESULT_NOT_READY = 1, DUCKDB_PENDING_ERROR = 2, DUCKDB_PENDING_NO_TASKS_AVAILABLE = 3 } duckdb_pending_state; //! An enum over DuckDB's different result types. -typedef enum { +typedef enum duckdb_result_type { DUCKDB_RESULT_TYPE_INVALID = 0, DUCKDB_RESULT_TYPE_CHANGED_ROWS = 1, DUCKDB_RESULT_TYPE_NOTHING = 2, DUCKDB_RESULT_TYPE_QUERY_RESULT = 3, } duckdb_result_type; //! An enum over DuckDB's different statement types. -typedef enum { +typedef enum duckdb_statement_type { DUCKDB_STATEMENT_TYPE_INVALID = 0, DUCKDB_STATEMENT_TYPE_SELECT = 1, DUCKDB_STATEMENT_TYPE_INSERT = 2, @@ -405,6 +412,12 @@ typedef struct _duckdb_appender { void *__appn; } * duckdb_appender; +//! The table description allows querying info about the table. +//! Must be destroyed with `duckdb_table_description_destroy`. +typedef struct _duckdb_table_description { + void *__tabledesc; +} * duckdb_table_description; + //! Can be used to provide start-up options for the DuckDB instance. //! Must be destroyed with `duckdb_destroy_config`. typedef struct _duckdb_config { @@ -429,21 +442,44 @@ typedef struct _duckdb_value { void *__val; } * duckdb_value; +//===--------------------------------------------------------------------===// +// Function types +//===--------------------------------------------------------------------===// +//! Additional function info. When setting this info, it is necessary to pass a destroy-callback function. +typedef struct _duckdb_function_info { + void *__val; +} * duckdb_function_info; + +//===--------------------------------------------------------------------===// +// Scalar function types +//===--------------------------------------------------------------------===// +//! A scalar function. Must be destroyed with `duckdb_destroy_scalar_function`. +typedef struct _duckdb_scalar_function { + void *__val; +} * duckdb_scalar_function; + +//! The main function of the scalar function. +typedef void (*duckdb_scalar_function_t)(duckdb_function_info info, duckdb_data_chunk input, duckdb_vector output); + //===--------------------------------------------------------------------===// // Table function types //===--------------------------------------------------------------------===// +#ifndef DUCKDB_NO_EXTENSION_FUNCTIONS //! A table function. Must be destroyed with `duckdb_destroy_table_function`. -typedef void *duckdb_table_function; +typedef struct _duckdb_table_function { + void *__val; +} * duckdb_table_function; //! The bind info of the function. When setting this info, it is necessary to pass a destroy-callback function. -typedef void *duckdb_bind_info; +typedef struct _duckdb_bind_info { + void *__val; +} * duckdb_bind_info; //! Additional function init info. When setting this info, it is necessary to pass a destroy-callback function. -typedef void *duckdb_init_info; - -//! Additional function info. When setting this info, it is necessary to pass a destroy-callback function. -typedef void *duckdb_function_info; +typedef struct _duckdb_init_info { + void *__val; +} * duckdb_init_info; //! The bind function of the table function. typedef void (*duckdb_table_function_bind_t)(duckdb_bind_info info); @@ -459,10 +495,13 @@ typedef void (*duckdb_table_function_t)(duckdb_function_info info, duckdb_data_c //===--------------------------------------------------------------------===// //! Additional replacement scan info. When setting this info, it is necessary to pass a destroy-callback function. -typedef void *duckdb_replacement_scan_info; +typedef struct _duckdb_replacement_scan_info { + void *__val; +} * duckdb_replacement_scan_info; //! A replacement scan function that can be added to a database. typedef void (*duckdb_replacement_callback_t)(duckdb_replacement_scan_info info, const char *table_name, void *data); +#endif //===--------------------------------------------------------------------===// // Arrow-related types @@ -582,6 +621,9 @@ The duckdb_config must be destroyed using 'duckdb_destroy_config' This will always succeed unless there is a malloc failure. +Note that `duckdb_destroy_config` should always be called on the resulting config, even if the function returns +`DuckDBError`. + * out_config: The result configuration object. * returns: `DuckDBSuccess` on success or `DuckDBError` on failure. */ @@ -709,13 +751,17 @@ Returns the number of columns present in a the result object. */ DUCKDB_API idx_t duckdb_column_count(duckdb_result *result); +#ifndef DUCKDB_API_NO_DEPRECATED /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Returns the number of rows present in the result object. * result: The result object. * returns: The number of rows present in the result object. */ DUCKDB_API idx_t duckdb_row_count(duckdb_result *result); +#endif /*! Returns the number of rows changed by the query stored in the result. This is relevant only for INSERT/UPDATE/DELETE @@ -726,6 +772,7 @@ queries. For other queries the rows_changed will be 0. */ DUCKDB_API idx_t duckdb_rows_changed(duckdb_result *result); +#ifndef DUCKDB_API_NO_DEPRECATED /*! **DEPRECATED**: Prefer using `duckdb_result_get_chunk` instead. @@ -769,6 +816,7 @@ if (nullmask[row]) { * returns: The nullmask of the specified column. */ DUCKDB_API bool *duckdb_nullmask_data(duckdb_result *result, idx_t col); +#endif /*! Returns the error message contained within the result. The error is only set if `duckdb_query` returns `DuckDBError`. @@ -783,8 +831,10 @@ DUCKDB_API const char *duckdb_result_error(duckdb_result *result); //===--------------------------------------------------------------------===// // Result Functions //===--------------------------------------------------------------------===// - +#ifndef DUCKDB_API_NO_DEPRECATED /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Fetches a data chunk from the duckdb_result. This function should be called repeatedly until the result is exhausted. The result must be destroyed with `duckdb_destroy_data_chunk`. @@ -804,6 +854,8 @@ Use `duckdb_result_chunk_count` to figure out how many chunks there are in the r DUCKDB_API duckdb_data_chunk duckdb_result_get_chunk(duckdb_result result, idx_t chunk_index); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Checks if the type of the internal result is StreamQueryResult. * result: The result object to check. @@ -812,12 +864,15 @@ Checks if the type of the internal result is StreamQueryResult. DUCKDB_API bool duckdb_result_is_streaming(duckdb_result result); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Returns the number of data chunks present in the result. * result: The result object * returns: Number of data chunks present in the result. */ DUCKDB_API idx_t duckdb_result_chunk_count(duckdb_result result); +#endif /*! Returns the return_type of the given result, or DUCKDB_RETURN_TYPE_INVALID on error @@ -827,6 +882,7 @@ Returns the return_type of the given result, or DUCKDB_RETURN_TYPE_INVALID on er */ DUCKDB_API duckdb_result_type duckdb_result_return_type(duckdb_result result); +#ifndef DUCKDB_API_NO_DEPRECATED //===--------------------------------------------------------------------===// // Safe fetch functions //===--------------------------------------------------------------------===// @@ -837,91 +893,127 @@ DUCKDB_API duckdb_result_type duckdb_result_return_type(duckdb_result result); // For fast access of values prefer using `duckdb_result_get_chunk` /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The boolean value at the specified location, or false if the value cannot be converted. */ DUCKDB_API bool duckdb_value_boolean(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The int8_t value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API int8_t duckdb_value_int8(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The int16_t value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API int16_t duckdb_value_int16(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The int32_t value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API int32_t duckdb_value_int32(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The int64_t value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API int64_t duckdb_value_int64(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The duckdb_hugeint value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API duckdb_hugeint duckdb_value_hugeint(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The duckdb_uhugeint value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API duckdb_uhugeint duckdb_value_uhugeint(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The duckdb_decimal value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API duckdb_decimal duckdb_value_decimal(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The uint8_t value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API uint8_t duckdb_value_uint8(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The uint16_t value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API uint16_t duckdb_value_uint16(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The uint32_t value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API uint32_t duckdb_value_uint32(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The uint64_t value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API uint64_t duckdb_value_uint64(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The float value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API float duckdb_value_float(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The double value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API double duckdb_value_double(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The duckdb_date value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API duckdb_date duckdb_value_date(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The duckdb_time value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API duckdb_time duckdb_value_time(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The duckdb_timestamp value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API duckdb_timestamp duckdb_value_timestamp(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The duckdb_interval value at the specified location, or 0 if the value cannot be converted. */ DUCKDB_API duckdb_interval duckdb_value_interval(duckdb_result *result, idx_t col, idx_t row); @@ -934,7 +1026,10 @@ converted. The result must be freed with `duckdb_free`. DUCKDB_API char *duckdb_value_varchar(duckdb_result *result, idx_t col, idx_t row); /*! - * returns: The string value at the specified location. +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + + * returns: The string value at the specified location. Attempts to cast the result value to string. + * No support for nested types, and for other complex types. * The resulting field "string.data" must be freed with `duckdb_free.` */ DUCKDB_API duckdb_string duckdb_value_string(duckdb_result *result, idx_t col, idx_t row); @@ -960,15 +1055,20 @@ The result must NOT be freed. DUCKDB_API duckdb_string duckdb_value_string_internal(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: The duckdb_blob value at the specified location. Returns a blob with blob.data set to nullptr if the value cannot be converted. The resulting field "blob.data" must be freed with `duckdb_free.` */ DUCKDB_API duckdb_blob duckdb_value_blob(duckdb_result *result, idx_t col, idx_t row); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + * returns: Returns true if the value at the specified index is NULL, and false otherwise. */ DUCKDB_API bool duckdb_value_is_null(duckdb_result *result, idx_t col, idx_t row); +#endif //===--------------------------------------------------------------------===// // Helpers @@ -1356,6 +1456,12 @@ Binds a duckdb_timestamp value to the prepared statement at the specified index. DUCKDB_API duckdb_state duckdb_bind_timestamp(duckdb_prepared_statement prepared_statement, idx_t param_idx, duckdb_timestamp val); +/*! +Binds a duckdb_timestamp value to the prepared statement at the specified index. +*/ +DUCKDB_API duckdb_state duckdb_bind_timestamp_tz(duckdb_prepared_statement prepared_statement, idx_t param_idx, + duckdb_timestamp val); + /*! Binds a duckdb_interval value to the prepared statement at the specified index. */ @@ -1404,7 +1510,10 @@ Note that the result must be freed with `duckdb_destroy_result`. DUCKDB_API duckdb_state duckdb_execute_prepared(duckdb_prepared_statement prepared_statement, duckdb_result *out_result); +#ifndef DUCKDB_API_NO_DEPRECATED /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Executes the prepared statement with the given bound parameters, and returns an optionally-streaming query result. To determine if the resulting query was in fact streamed, use `duckdb_result_is_streaming` @@ -1419,6 +1528,7 @@ Note that the result must be freed with `duckdb_destroy_result`. */ DUCKDB_API duckdb_state duckdb_execute_prepared_streaming(duckdb_prepared_statement prepared_statement, duckdb_result *out_result); +#endif //===--------------------------------------------------------------------===// // Extract Statements @@ -1491,8 +1601,10 @@ Note that after calling `duckdb_pending_prepared`, the pending result should alw */ DUCKDB_API duckdb_state duckdb_pending_prepared(duckdb_prepared_statement prepared_statement, duckdb_pending_result *out_result); - +#ifndef DUCKDB_API_NO_DEPRECATED /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Executes the prepared statement with the given bound parameters, and returns a pending result. This pending result will create a streaming duckdb_result when executed. The pending result represents an intermediate structure for a query that is not yet fully executed. @@ -1506,6 +1618,7 @@ Note that after calling `duckdb_pending_prepared_streaming`, the pending result */ DUCKDB_API duckdb_state duckdb_pending_prepared_streaming(duckdb_prepared_statement prepared_statement, duckdb_pending_result *out_result); +#endif /*! Closes the pending result and de-allocates all memory allocated for the result. @@ -1629,7 +1742,7 @@ Creates a list value from a type and an array of values of length `value_count` DUCKDB_API duckdb_value duckdb_create_list_value(duckdb_logical_type type, duckdb_value *values, idx_t value_count); /*! -Creates a array value from a type and an array of values of length `value_count` +Creates an array value from a type and an array of values of length `value_count` * type: The type of the array * values: The values for the array @@ -1689,7 +1802,7 @@ The resulting type should be destroyed with `duckdb_destroy_logical_type`. DUCKDB_API duckdb_logical_type duckdb_create_list_type(duckdb_logical_type type); /*! -Creates a array type from its child type. +Creates an array type from its child type. The resulting type should be destroyed with `duckdb_destroy_logical_type`. * type: The child type of array type to create. @@ -2169,6 +2282,82 @@ Equivalent to `duckdb_validity_set_row_validity` with valid set to true. */ DUCKDB_API void duckdb_validity_set_row_valid(uint64_t *validity, idx_t row); +#ifndef DUCKDB_NO_EXTENSION_FUNCTIONS +//===--------------------------------------------------------------------===// +// Scalar Functions +//===--------------------------------------------------------------------===// +/*! +Creates a new empty scalar function. + +The return value should be destroyed with `duckdb_destroy_scalar_function`. + +* returns: The scalar function object. +*/ +DUCKDB_API duckdb_scalar_function duckdb_create_scalar_function(); + +/*! +Destroys the given table function object. + +* table_function: The table function to destroy +*/ +DUCKDB_API void duckdb_destroy_scalar_function(duckdb_scalar_function *scalar_function); + +/*! +Sets the name of the given scalar function. + +* table_function: The scalar function +* name: The name of the scalar function +*/ +DUCKDB_API void duckdb_scalar_function_set_name(duckdb_scalar_function scalar_function, const char *name); + +/*! +Adds a parameter to the scalar function. + +* scalar_function: The scalar function +* type: The type of the parameter to add. +*/ +DUCKDB_API void duckdb_scalar_function_add_parameter(duckdb_scalar_function scalar_function, duckdb_logical_type type); + +/*! +Sets the return type of the scalar function. + +* scalar_function: The scalar function +* type: The return type to set +*/ +DUCKDB_API void duckdb_scalar_function_set_return_type(duckdb_scalar_function scalar_function, + duckdb_logical_type type); + +/*! +Assigns extra information to the scalar function that can be fetched during binding, etc. + +* scalar_function: The table function +* extra_info: The extra information +* destroy: The callback that will be called to destroy the bind data (if any) +*/ +DUCKDB_API void duckdb_scalar_function_set_extra_info(duckdb_scalar_function scalar_function, void *extra_info, + duckdb_delete_callback_t destroy); + +/*! +Sets the main function of the table function. + +* table_function: The table function +* function: The function +*/ +DUCKDB_API void duckdb_scalar_function_set_function(duckdb_scalar_function scalar_function, + duckdb_scalar_function_t function); + +/*! +Register the scalar function object within the given connection. + +The function requires at least a name, a function and a return type. + +If the function is incomplete or a function with this name already exists DuckDBError is returned. + +* con: The connection to register it in. +* function: The function pointer +* returns: Whether or not the registration was successful. +*/ +DUCKDB_API duckdb_state duckdb_register_scalar_function(duckdb_connection con, duckdb_scalar_function scalar_function); //===--------------------------------------------------------------------===// // Table Functions //===--------------------------------------------------------------------===// @@ -2515,6 +2704,7 @@ Report that an error has occurred while executing the replacement scan. * error: The error message */ DUCKDB_API void duckdb_replacement_scan_set_error(duckdb_replacement_scan_info info, const char *error); +#endif //===--------------------------------------------------------------------===// // Appender @@ -2578,11 +2768,10 @@ The error message should not be freed. It will be de-allocated when `duckdb_appe DUCKDB_API const char *duckdb_appender_error(duckdb_appender appender); /*! -Flush the appender to the table, forcing the cache of the appender to be cleared and the data to be appended to the -base table. - -This should generally not be used unless you know what you are doing. Instead, call `duckdb_appender_destroy` when you -are done with the appender. +Flush the appender to the table, forcing the cache of the appender to be cleared. If flushing the data triggers a +constraint violation or any other error, then all data is invalidated, and this function returns DuckDBError. +It is not possible to append more values. Call duckdb_appender_error to obtain the error message followed by +duckdb_appender_destroy to destroy the invalidated appender. * appender: The appender to flush. * returns: `DuckDBSuccess` on success or `DuckDBError` on failure. @@ -2590,9 +2779,10 @@ are done with the appender. DUCKDB_API duckdb_state duckdb_appender_flush(duckdb_appender appender); /*! -Close the appender, flushing all intermediate state in the appender to the table and closing it for further appends. - -This is generally not necessary. Call `duckdb_appender_destroy` instead. +Closes the appender by flushing all intermediate states and closing it for further appends. If flushing the data +triggers a constraint violation or any other error, then all data is invalidated, and this function returns DuckDBError. +Call duckdb_appender_error to obtain the error message followed by duckdb_appender_destroy to destroy the invalidated +appender. * appender: The appender to flush and close. * returns: `DuckDBSuccess` on success or `DuckDBError` on failure. @@ -2600,8 +2790,11 @@ This is generally not necessary. Call `duckdb_appender_destroy` instead. DUCKDB_API duckdb_state duckdb_appender_close(duckdb_appender appender); /*! -Close the appender and destroy it. Flushing all intermediate state in the appender to the table, and de-allocating -all memory associated with the appender. +Closes the appender by flushing all intermediate states to the table and destroying it. By destroying it, this function +de-allocates all memory associated with the appender. If flushing the data triggers a constraint violation, +then all data is invalidated, and this function returns DuckDBError. Due to the destruction of the appender, it is no +longer possible to obtain the specific error message with duckdb_appender_error. Therefore, call duckdb_appender_close +before destroying the appender, if you need insights into the specific error. * appender: The appender to flush, close and destroy. * returns: `DuckDBSuccess` on success or `DuckDBError` on failure. @@ -2621,6 +2814,11 @@ Finish the current row of appends. After end_row is called, the next row can be */ DUCKDB_API duckdb_state duckdb_appender_end_row(duckdb_appender appender); +/*! +Append a DEFAULT value (NULL if DEFAULT not available for column) to the appender. +*/ +DUCKDB_API duckdb_state duckdb_append_default(duckdb_appender appender); + /*! Append a bool value to the appender. */ @@ -2739,11 +2937,55 @@ If the append is successful, DuckDBSuccess is returned. */ DUCKDB_API duckdb_state duckdb_append_data_chunk(duckdb_appender appender, duckdb_data_chunk chunk); +//===--------------------------------------------------------------------===// +// TableDescription +//===--------------------------------------------------------------------===// + +/*! +Creates a table description object. +Note that `duckdb_table_description_destroy` should always be called on the resulting table_description, even if the +function returns `DuckDBError`. +* connection: The connection context. +* schema: The schema of the table, or `nullptr` for the default schema. +* table: The table name. +* out: The resulting table description object. +* returns: `DuckDBSuccess` on success or `DuckDBError` on failure. +*/ +DUCKDB_API duckdb_state duckdb_table_description_create(duckdb_connection connection, const char *schema, + const char *table, duckdb_table_description *out); + +/*! +Destroy the TableDescription object. +* table: The table_description to destroy. +*/ +DUCKDB_API void duckdb_table_description_destroy(duckdb_table_description *table_description); + +/*! +Returns the error message associated with the given table_description. +If the table_description has no error message, this returns `nullptr` instead. +The error message should not be freed. It will be de-allocated when `duckdb_table_description_destroy` is called. +* table_description: The table_description to get the error from. +* returns: The error message, or `nullptr` if there is none. +*/ +DUCKDB_API const char *duckdb_table_description_error(duckdb_table_description table); + +/*! +Check if the column at 'index' index of the table has a DEFAULT expression. +* table: The table_description to query. +* index: The index of the column to query. +* out: The out-parameter used to store the result. +* returns: `DuckDBSuccess` on success or `DuckDBError` on failure. +*/ +DUCKDB_API duckdb_state duckdb_column_has_default(duckdb_table_description table_description, idx_t index, bool *out); + +#ifndef DUCKDB_API_NO_DEPRECATED //===--------------------------------------------------------------------===// // Arrow Interface //===--------------------------------------------------------------------===// /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Executes a SQL query within a connection and stores the full (materialized) result in an arrow structure. If the query fails to execute, DuckDBError is returned and the error message can be retrieved by calling `duckdb_query_arrow_error`. @@ -2759,6 +3001,8 @@ query fails, otherwise the error stored within the result will not be freed corr DUCKDB_API duckdb_state duckdb_query_arrow(duckdb_connection connection, const char *query, duckdb_arrow *out_result); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Fetch the internal arrow schema from the arrow result. Remember to call release on the respective ArrowSchema object. @@ -2769,6 +3013,8 @@ ArrowSchema object. DUCKDB_API duckdb_state duckdb_query_arrow_schema(duckdb_arrow result, duckdb_arrow_schema *out_schema); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Fetch the internal arrow schema from the prepared statement. Remember to call release on the respective ArrowSchema object. @@ -2779,6 +3025,8 @@ ArrowSchema object. DUCKDB_API duckdb_state duckdb_prepared_arrow_schema(duckdb_prepared_statement prepared, duckdb_arrow_schema *out_schema); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Convert a data chunk into an arrow struct array. Remember to call release on the respective ArrowArray object. @@ -2789,6 +3037,8 @@ ArrowArray object. DUCKDB_API void duckdb_result_arrow_array(duckdb_result result, duckdb_data_chunk chunk, duckdb_arrow_array *out_array); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Fetch an internal arrow struct array from the arrow result. Remember to call release on the respective ArrowArray object. @@ -2802,6 +3052,8 @@ So consume the out_array before calling this function again. DUCKDB_API duckdb_state duckdb_query_arrow_array(duckdb_arrow result, duckdb_arrow_array *out_array); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Returns the number of columns present in the arrow result object. * result: The result object. @@ -2810,6 +3062,8 @@ Returns the number of columns present in the arrow result object. DUCKDB_API idx_t duckdb_arrow_column_count(duckdb_arrow result); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Returns the number of rows present in the arrow result object. * result: The result object. @@ -2818,6 +3072,8 @@ Returns the number of rows present in the arrow result object. DUCKDB_API idx_t duckdb_arrow_row_count(duckdb_arrow result); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Returns the number of rows changed by the query stored in the arrow result. This is relevant only for INSERT/UPDATE/DELETE queries. For other queries the rows_changed will be 0. @@ -2827,7 +3083,9 @@ INSERT/UPDATE/DELETE queries. For other queries the rows_changed will be 0. DUCKDB_API idx_t duckdb_arrow_rows_changed(duckdb_arrow result); /*! -Returns the error message contained within the result. The error is only set if `duckdb_query_arrow` returns +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + + Returns the error message contained within the result. The error is only set if `duckdb_query_arrow` returns `DuckDBError`. The error message should not be freed. It will be de-allocated when `duckdb_destroy_arrow` is called. @@ -2838,6 +3096,8 @@ The error message should not be freed. It will be de-allocated when `duckdb_dest DUCKDB_API const char *duckdb_query_arrow_error(duckdb_arrow result); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Closes the result and de-allocates all memory allocated for the arrow result. * result: The result to destroy. @@ -2845,6 +3105,8 @@ Closes the result and de-allocates all memory allocated for the arrow result. DUCKDB_API void duckdb_destroy_arrow(duckdb_arrow *result); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Releases the arrow array stream and de-allocates its memory. * stream: The arrow array stream to destroy. @@ -2852,6 +3114,8 @@ Releases the arrow array stream and de-allocates its memory. DUCKDB_API void duckdb_destroy_arrow_stream(duckdb_arrow_stream *stream_p); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Executes the prepared statement with the given bound parameters, and returns an arrow query result. Note that after running `duckdb_execute_prepared_arrow`, `duckdb_destroy_arrow` must be called on the result object. @@ -2863,6 +3127,8 @@ DUCKDB_API duckdb_state duckdb_execute_prepared_arrow(duckdb_prepared_statement duckdb_arrow *out_result); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Scans the Arrow stream and creates a view with the given name. * connection: The connection on which to execute the scan. @@ -2874,6 +3140,8 @@ DUCKDB_API duckdb_state duckdb_arrow_scan(duckdb_connection connection, const ch duckdb_arrow_stream arrow); /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Scans the Arrow array and creates a view with the given name. Note that after running `duckdb_arrow_array_scan`, `duckdb_destroy_arrow_stream` must be called on the out stream. @@ -2887,7 +3155,9 @@ Note that after running `duckdb_arrow_array_scan`, `duckdb_destroy_arrow_stream` DUCKDB_API duckdb_state duckdb_arrow_array_scan(duckdb_connection connection, const char *table_name, duckdb_arrow_schema arrow_schema, duckdb_arrow_array arrow_array, duckdb_arrow_stream *out_stream); +#endif +#ifndef DUCKDB_NO_EXTENSION_FUNCTIONS //===--------------------------------------------------------------------===// // Threading Information //===--------------------------------------------------------------------===// @@ -2968,12 +3238,15 @@ Returns true if the execution of the current query is finished. * con: The connection on which to check */ DUCKDB_API bool duckdb_execution_is_finished(duckdb_connection con); +#endif //===--------------------------------------------------------------------===// // Streaming Result Interface //===--------------------------------------------------------------------===// - +#ifndef DUCKDB_API_NO_DEPRECATED /*! +**DEPRECATION NOTICE**: This method is scheduled for removal in a future release. + Fetches a data chunk from the (streaming) duckdb_result. This function should be called repeatedly until the result is exhausted. @@ -2990,6 +3263,19 @@ It is not known beforehand how many chunks will be returned by this result. * returns: The resulting data chunk. Returns `NULL` if the result has an error. */ DUCKDB_API duckdb_data_chunk duckdb_stream_fetch_chunk(duckdb_result result); +#endif + +/*! +Fetches a data chunk from a duckdb_result. This function should be called repeatedly until the result is exhausted. + +The result must be destroyed with `duckdb_destroy_data_chunk`. + +It is not known beforehand how many chunks will be returned by this result. + +* result: The result object to fetch the data chunk from. +* returns: The resulting data chunk. Returns `NULL` if the result has an error. +*/ +DUCKDB_API duckdb_data_chunk duckdb_fetch_chunk(duckdb_result result); #ifdef __cplusplus } diff --git a/src/include/duckdb/catalog/catalog.hpp b/src/include/duckdb/catalog/catalog.hpp index 31098ba10f6..19d48ef5184 100644 --- a/src/include/duckdb/catalog/catalog.hpp +++ b/src/include/duckdb/catalog/catalog.hpp @@ -229,16 +229,6 @@ class Catalog { const string &schema, const string &name, QueryErrorContext error_context = QueryErrorContext()); - //! Gets the "schema.name" entry without a specified type, if entry does not exist an exception is thrown - DUCKDB_API CatalogEntry &GetEntry(ClientContext &context, const string &schema, const string &name); - - //! Fetches a logical type from the catalog - DUCKDB_API LogicalType GetType(ClientContext &context, const string &schema, const string &names, - OnEntryNotFound if_not_found); - - DUCKDB_API static LogicalType GetType(ClientContext &context, const string &catalog_name, const string &schema, - const string &name); - template optional_ptr GetEntry(ClientContext &context, const string &schema_name, const string &name, OnEntryNotFound if_not_found, QueryErrorContext error_context = QueryErrorContext()) { @@ -262,6 +252,7 @@ class Catalog { DUCKDB_API optional_ptr AddFunction(ClientContext &context, CreateFunctionInfo &info); //! Alter an existing entry in the catalog. + DUCKDB_API void Alter(CatalogTransaction transaction, AlterInfo &info); DUCKDB_API void Alter(ClientContext &context, AlterInfo &info); virtual unique_ptr PlanCreateTableAs(ClientContext &context, LogicalCreateTable &op, diff --git a/src/include/duckdb/catalog/catalog_entry.hpp b/src/include/duckdb/catalog/catalog_entry.hpp index 29c46fa1057..33802d1d991 100644 --- a/src/include/duckdb/catalog/catalog_entry.hpp +++ b/src/include/duckdb/catalog/catalog_entry.hpp @@ -27,6 +27,7 @@ class Serializer; class Deserializer; class Value; +struct CatalogTransaction; struct CreateInfo; //! Abstract base class of an entry in the catalog @@ -54,6 +55,8 @@ class CatalogEntry { atomic timestamp; //! (optional) comment on this entry Value comment; + //! (optional) extra data associated with this entry + unordered_map tags; private: //! Child entry @@ -63,6 +66,7 @@ class CatalogEntry { public: virtual unique_ptr AlterEntry(ClientContext &context, AlterInfo &info); + virtual unique_ptr AlterEntry(CatalogTransaction transaction, AlterInfo &info); virtual void UndoAlter(ClientContext &context, AlterInfo &info); virtual unique_ptr Copy(ClientContext &context) const; diff --git a/src/include/duckdb/catalog/catalog_entry/duck_index_entry.hpp b/src/include/duckdb/catalog/catalog_entry/duck_index_entry.hpp index 3245d0a719b..f0175bbdd2d 100644 --- a/src/include/duckdb/catalog/catalog_entry/duck_index_entry.hpp +++ b/src/include/duckdb/catalog/catalog_entry/duck_index_entry.hpp @@ -14,7 +14,7 @@ namespace duckdb { //! Wrapper class to allow copying a DuckIndexEntry (for altering the DuckIndexEntry metadata such as comments) struct IndexDataTableInfo { - IndexDataTableInfo(shared_ptr &info_p, const string &index_name_p); + IndexDataTableInfo(shared_ptr info_p, const string &index_name_p); ~IndexDataTableInfo(); //! Pointer to the DataTableInfo diff --git a/src/include/duckdb/catalog/catalog_entry/duck_schema_entry.hpp b/src/include/duckdb/catalog/catalog_entry/duck_schema_entry.hpp index 33bbd010685..54ba310a8dd 100644 --- a/src/include/duckdb/catalog/catalog_entry/duck_schema_entry.hpp +++ b/src/include/duckdb/catalog/catalog_entry/duck_schema_entry.hpp @@ -45,7 +45,7 @@ class DuckSchemaEntry : public SchemaCatalogEntry { optional_ptr CreateTable(CatalogTransaction transaction, BoundCreateTableInfo &info) override; optional_ptr CreateFunction(CatalogTransaction transaction, CreateFunctionInfo &info) override; - optional_ptr CreateIndex(ClientContext &context, CreateIndexInfo &info, + optional_ptr CreateIndex(CatalogTransaction transaction, CreateIndexInfo &info, TableCatalogEntry &table) override; optional_ptr CreateView(CatalogTransaction transaction, CreateViewInfo &info) override; optional_ptr CreateSequence(CatalogTransaction transaction, CreateSequenceInfo &info) override; @@ -57,7 +57,7 @@ class DuckSchemaEntry : public SchemaCatalogEntry { CreatePragmaFunctionInfo &info) override; optional_ptr CreateCollation(CatalogTransaction transaction, CreateCollationInfo &info) override; optional_ptr CreateType(CatalogTransaction transaction, CreateTypeInfo &info) override; - void Alter(ClientContext &context, AlterInfo &info) override; + void Alter(CatalogTransaction transaction, AlterInfo &info) override; void Scan(ClientContext &context, CatalogType type, const std::function &callback) override; void Scan(CatalogType type, const std::function &callback) override; void DropEntry(ClientContext &context, DropInfo &info) override; @@ -68,6 +68,9 @@ class DuckSchemaEntry : public SchemaCatalogEntry { void Verify(Catalog &catalog) override; +private: + void OnDropEntry(CatalogTransaction transaction, CatalogEntry &entry); + private: //! Get the catalog set for the specified type CatalogSet &GetCatalogSet(CatalogType type); diff --git a/src/include/duckdb/catalog/catalog_entry/duck_table_entry.hpp b/src/include/duckdb/catalog/catalog_entry/duck_table_entry.hpp index 1ac809f398d..c728b2954fb 100644 --- a/src/include/duckdb/catalog/catalog_entry/duck_table_entry.hpp +++ b/src/include/duckdb/catalog/catalog_entry/duck_table_entry.hpp @@ -21,6 +21,7 @@ class DuckTableEntry : public TableCatalogEntry { public: unique_ptr AlterEntry(ClientContext &context, AlterInfo &info) override; + unique_ptr AlterEntry(CatalogTransaction, AlterInfo &info) override; void UndoAlter(ClientContext &context, AlterInfo &info) override; //! Returns the underlying storage of the table DataTable &GetStorage() override; @@ -53,7 +54,7 @@ class DuckTableEntry : public TableCatalogEntry { unique_ptr ChangeColumnType(ClientContext &context, ChangeColumnTypeInfo &info); unique_ptr SetNotNull(ClientContext &context, SetNotNullInfo &info); unique_ptr DropNotNull(ClientContext &context, DropNotNullInfo &info); - unique_ptr AddForeignKeyConstraint(ClientContext &context, AlterForeignKeyInfo &info); + unique_ptr AddForeignKeyConstraint(optional_ptr context, AlterForeignKeyInfo &info); unique_ptr DropForeignKeyConstraint(ClientContext &context, AlterForeignKeyInfo &info); unique_ptr SetColumnComment(ClientContext &context, SetColumnCommentInfo &info); diff --git a/src/include/duckdb/catalog/catalog_entry/function_entry.hpp b/src/include/duckdb/catalog/catalog_entry/function_entry.hpp index 69f4918c33b..788c6561f0a 100644 --- a/src/include/duckdb/catalog/catalog_entry/function_entry.hpp +++ b/src/include/duckdb/catalog/catalog_entry/function_entry.hpp @@ -21,6 +21,7 @@ class FunctionEntry : public StandardEntry { description = std::move(info.description); parameter_names = std::move(info.parameter_names); example = std::move(info.example); + this->dependencies = info.dependencies; } //! The description (if any) diff --git a/src/include/duckdb/catalog/catalog_entry/schema_catalog_entry.hpp b/src/include/duckdb/catalog/catalog_entry/schema_catalog_entry.hpp index 0356ea30853..a6f7d728aaa 100644 --- a/src/include/duckdb/catalog/catalog_entry/schema_catalog_entry.hpp +++ b/src/include/duckdb/catalog/catalog_entry/schema_catalog_entry.hpp @@ -58,8 +58,9 @@ class SchemaCatalogEntry : public InCatalogEntry { string ToSQL() const override; //! Creates an index with the given name in the schema - virtual optional_ptr CreateIndex(ClientContext &context, CreateIndexInfo &info, + virtual optional_ptr CreateIndex(CatalogTransaction transaction, CreateIndexInfo &info, TableCatalogEntry &table) = 0; + optional_ptr CreateIndex(ClientContext &context, CreateIndexInfo &info, TableCatalogEntry &table); //! Create a scalar or aggregate function within the given schema virtual optional_ptr CreateFunction(CatalogTransaction transaction, CreateFunctionInfo &info) = 0; //! Creates a table with the given name in the schema @@ -91,7 +92,7 @@ class SchemaCatalogEntry : public InCatalogEntry { virtual void DropEntry(ClientContext &context, DropInfo &info) = 0; //! Alters a catalog entry - virtual void Alter(ClientContext &context, AlterInfo &info) = 0; + virtual void Alter(CatalogTransaction transaction, AlterInfo &info) = 0; CatalogTransaction GetCatalogTransaction(ClientContext &context); }; diff --git a/src/include/duckdb/catalog/catalog_entry/sequence_catalog_entry.hpp b/src/include/duckdb/catalog/catalog_entry/sequence_catalog_entry.hpp index ca2b4c47a76..ed12b77a1c3 100644 --- a/src/include/duckdb/catalog/catalog_entry/sequence_catalog_entry.hpp +++ b/src/include/duckdb/catalog/catalog_entry/sequence_catalog_entry.hpp @@ -15,13 +15,10 @@ namespace duckdb { class DuckTransaction; +class SequenceCatalogEntry; struct SequenceValue { - SequenceValue() : usage_count(0), counter(-1) { - } - SequenceValue(uint64_t usage_count, int64_t counter) : usage_count(usage_count), counter(counter) { - } - + SequenceCatalogEntry *entry; uint64_t usage_count; int64_t counter; }; diff --git a/src/include/duckdb/catalog/catalog_entry/type_catalog_entry.hpp b/src/include/duckdb/catalog/catalog_entry/type_catalog_entry.hpp index 97fdce21a42..064ba4c0843 100644 --- a/src/include/duckdb/catalog/catalog_entry/type_catalog_entry.hpp +++ b/src/include/duckdb/catalog/catalog_entry/type_catalog_entry.hpp @@ -26,6 +26,8 @@ class TypeCatalogEntry : public StandardEntry { LogicalType user_type; + bind_type_modifiers_function_t bind_modifiers; + public: unique_ptr GetInfo() const override; unique_ptr Copy(ClientContext &context) const override; diff --git a/src/include/duckdb/catalog/catalog_entry_retriever.hpp b/src/include/duckdb/catalog/catalog_entry_retriever.hpp new file mode 100644 index 00000000000..28b3874c4d7 --- /dev/null +++ b/src/include/duckdb/catalog/catalog_entry_retriever.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include "duckdb/common/enums/catalog_type.hpp" +#include "duckdb/common/enums/on_entry_not_found.hpp" +#include "duckdb/common/string.hpp" +#include "duckdb/parser/query_error_context.hpp" +#include "duckdb/catalog/catalog_entry/schema_catalog_entry.hpp" + +namespace duckdb { + +class ClientContext; +class Catalog; +class CatalogEntry; + +using catalog_entry_callback_t = std::function; + +// Wraps the Catalog::GetEntry method +class CatalogEntryRetriever { +public: + explicit CatalogEntryRetriever(ClientContext &context) : context(context) { + } + CatalogEntryRetriever(const CatalogEntryRetriever &other) : callback(other.callback), context(other.context) { + } + +public: + optional_ptr GetEntry(CatalogType type, const string &catalog, const string &schema, + const string &name, + OnEntryNotFound on_entry_not_found = OnEntryNotFound::THROW_EXCEPTION, + QueryErrorContext error_context = QueryErrorContext()); + + optional_ptr GetEntry(CatalogType type, Catalog &catalog, const string &schema, const string &name, + OnEntryNotFound on_entry_not_found = OnEntryNotFound::THROW_EXCEPTION, + QueryErrorContext error_context = QueryErrorContext()); + + LogicalType GetType(const string &catalog, const string &schema, const string &name, + OnEntryNotFound on_entry_not_found = OnEntryNotFound::RETURN_NULL); + LogicalType GetType(Catalog &catalog, const string &schema, const string &name, + OnEntryNotFound on_entry_not_found = OnEntryNotFound::RETURN_NULL); + + optional_ptr GetSchema(const string &catalog, const string &name, + OnEntryNotFound on_entry_not_found = OnEntryNotFound::THROW_EXCEPTION, + QueryErrorContext error_context = QueryErrorContext()); + + void SetCallback(catalog_entry_callback_t callback) { + this->callback = std::move(callback); + } + catalog_entry_callback_t GetCallback() { + return callback; + } + +private: + using catalog_entry_retrieve_func_t = std::function()>; + optional_ptr GetEntryInternal(const catalog_entry_retrieve_func_t &retriever) { + auto result = retriever(); + if (!result) { + return result; + } + if (callback) { + // Call the callback if it's set + callback(*result); + } + return result; + } + +private: + //! (optional) callback, called on every succesful entry retrieval + catalog_entry_callback_t callback = nullptr; + ClientContext &context; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/catalog/catalog_transaction.hpp b/src/include/duckdb/catalog/catalog_transaction.hpp index f9a327e7a65..ce8024a8328 100644 --- a/src/include/duckdb/catalog/catalog_transaction.hpp +++ b/src/include/duckdb/catalog/catalog_transaction.hpp @@ -27,6 +27,9 @@ struct CatalogTransaction { transaction_t transaction_id; transaction_t start_time; + bool HasContext() const { + return context; + } ClientContext &GetContext(); static CatalogTransaction GetSystemCatalogTransaction(ClientContext &context); diff --git a/src/include/duckdb/catalog/default/default_functions.hpp b/src/include/duckdb/catalog/default/default_functions.hpp index bc05d206183..34665855de6 100644 --- a/src/include/duckdb/catalog/default/default_functions.hpp +++ b/src/include/duckdb/catalog/default/default_functions.hpp @@ -28,15 +28,14 @@ class DefaultFunctionGenerator : public DefaultGenerator { SchemaCatalogEntry &schema; DUCKDB_API static unique_ptr CreateInternalMacroInfo(const DefaultMacro &default_macro); - DUCKDB_API static unique_ptr CreateInternalTableMacroInfo(const DefaultMacro &default_macro); public: unique_ptr CreateDefaultEntry(ClientContext &context, const string &entry_name) override; vector GetDefaultEntries() override; private: - static unique_ptr CreateInternalTableMacroInfo(const DefaultMacro &default_macro, - unique_ptr function); + static unique_ptr CreateInternalMacroInfo(const DefaultMacro &default_macro, + unique_ptr function); }; } // namespace duckdb diff --git a/src/include/duckdb/catalog/default/default_generator.hpp b/src/include/duckdb/catalog/default/default_generator.hpp index 6abc0ecc1ce..02480084aac 100644 --- a/src/include/duckdb/catalog/default/default_generator.hpp +++ b/src/include/duckdb/catalog/default/default_generator.hpp @@ -16,17 +16,16 @@ class ClientContext; class DefaultGenerator { public: - explicit DefaultGenerator(Catalog &catalog) : catalog(catalog), created_all_entries(false) { - } - virtual ~DefaultGenerator() { - } + explicit DefaultGenerator(Catalog &catalog); + virtual ~DefaultGenerator(); Catalog &catalog; atomic created_all_entries; public: //! Creates a default entry with the specified name, or returns nullptr if no such entry can be generated - virtual unique_ptr CreateDefaultEntry(ClientContext &context, const string &entry_name) = 0; + virtual unique_ptr CreateDefaultEntry(ClientContext &context, const string &entry_name); + virtual unique_ptr CreateDefaultEntry(CatalogTransaction transaction, const string &entry_name); //! Get a list of all default entries in the generator virtual vector GetDefaultEntries() = 0; }; diff --git a/src/include/duckdb/catalog/default/default_schemas.hpp b/src/include/duckdb/catalog/default/default_schemas.hpp index 673425c9a17..5b48165f7f6 100644 --- a/src/include/duckdb/catalog/default/default_schemas.hpp +++ b/src/include/duckdb/catalog/default/default_schemas.hpp @@ -17,8 +17,9 @@ class DefaultSchemaGenerator : public DefaultGenerator { explicit DefaultSchemaGenerator(Catalog &catalog); public: - unique_ptr CreateDefaultEntry(ClientContext &context, const string &entry_name) override; + unique_ptr CreateDefaultEntry(CatalogTransaction transaction, const string &entry_name) override; vector GetDefaultEntries() override; + static bool IsDefaultSchema(const string &input_schema); }; } // namespace duckdb diff --git a/src/include/duckdb/catalog/default/default_table_functions.hpp b/src/include/duckdb/catalog/default/default_table_functions.hpp new file mode 100644 index 00000000000..c0eee28552c --- /dev/null +++ b/src/include/duckdb/catalog/default/default_table_functions.hpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/catalog/default/default_table_functions.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/catalog/default/default_generator.hpp" +#include "duckdb/parser/parsed_data/create_macro_info.hpp" + +namespace duckdb { +class SchemaCatalogEntry; + +struct DefaultNamedParameter { + const char *name; + const char *default_value; +}; + +struct DefaultTableMacro { + const char *schema; + const char *name; + const char *parameters[8]; + DefaultNamedParameter named_parameters[8]; + const char *macro; +}; + +class DefaultTableFunctionGenerator : public DefaultGenerator { +public: + DefaultTableFunctionGenerator(Catalog &catalog, SchemaCatalogEntry &schema); + + SchemaCatalogEntry &schema; + +public: + unique_ptr CreateDefaultEntry(ClientContext &context, const string &entry_name) override; + vector GetDefaultEntries() override; + + static unique_ptr CreateTableMacroInfo(const DefaultTableMacro &default_macro); + +private: + static unique_ptr CreateInternalTableMacroInfo(const DefaultTableMacro &default_macro, + unique_ptr function); +}; + +} // namespace duckdb diff --git a/src/include/duckdb/catalog/dependency.hpp b/src/include/duckdb/catalog/dependency.hpp index 120b5fd7d15..4ac3656e75c 100644 --- a/src/include/duckdb/catalog/dependency.hpp +++ b/src/include/duckdb/catalog/dependency.hpp @@ -153,6 +153,10 @@ struct CatalogEntryInfo { } return true; } + +public: + void Serialize(Serializer &serializer) const; + static CatalogEntryInfo Deserialize(Deserializer &deserializer); }; struct Dependency { diff --git a/src/include/duckdb/catalog/dependency_list.hpp b/src/include/duckdb/catalog/dependency_list.hpp index ed08f01ac94..8bbadd21865 100644 --- a/src/include/duckdb/catalog/dependency_list.hpp +++ b/src/include/duckdb/catalog/dependency_list.hpp @@ -32,6 +32,10 @@ struct LogicalDependency { explicit LogicalDependency(CatalogEntry &entry); LogicalDependency(); bool operator==(const LogicalDependency &other) const; + +public: + void Serialize(Serializer &serializer) const; + static LogicalDependency Deserialize(Deserializer &deserializer); }; struct LogicalDependencyHashFunction { @@ -42,7 +46,7 @@ struct LogicalDependencyEquality { bool operator()(const LogicalDependency &a, const LogicalDependency &b) const; }; -//! The DependencyList containing LogicalDependency objects, not looked up in the catalog yet +//! The LogicalDependencyList containing LogicalDependency objects, not looked up in the catalog yet class LogicalDependencyList { using create_info_set_t = unordered_set; @@ -54,6 +58,8 @@ class LogicalDependencyList { public: DUCKDB_API void VerifyDependencies(Catalog &catalog, const string &name); + void Serialize(Serializer &serializer) const; + static LogicalDependencyList Deserialize(Deserializer &deserializer); bool operator==(const LogicalDependencyList &other) const; const create_info_set_t &Set() const; diff --git a/src/include/duckdb/catalog/dependency_manager.hpp b/src/include/duckdb/catalog/dependency_manager.hpp index e580bfccbae..9b191036f56 100644 --- a/src/include/duckdb/catalog/dependency_manager.hpp +++ b/src/include/duckdb/catalog/dependency_manager.hpp @@ -100,7 +100,7 @@ class DependencyManager { bool IsSystemEntry(CatalogEntry &entry) const; optional_ptr LookupEntry(CatalogTransaction transaction, const LogicalDependency &dependency); optional_ptr LookupEntry(CatalogTransaction transaction, CatalogEntry &dependency); - + string CollectDependents(CatalogTransaction transaction, catalog_entry_set_t &entries, CatalogEntryInfo &info); void CleanupDependencies(CatalogTransaction transaction, CatalogEntry &entry); public: @@ -112,7 +112,7 @@ class DependencyManager { private: void AddObject(CatalogTransaction transaction, CatalogEntry &object, const LogicalDependencyList &dependencies); void DropObject(CatalogTransaction transaction, CatalogEntry &object, bool cascade); - void AlterObject(CatalogTransaction transaction, CatalogEntry &old_obj, CatalogEntry &new_obj); + void AlterObject(CatalogTransaction transaction, CatalogEntry &old_obj, CatalogEntry &new_obj, AlterInfo &info); private: void RemoveDependency(CatalogTransaction transaction, const DependencyInfo &info); diff --git a/src/include/duckdb/catalog/standard_entry.hpp b/src/include/duckdb/catalog/standard_entry.hpp index cab74168070..a3fa83d88c4 100644 --- a/src/include/duckdb/catalog/standard_entry.hpp +++ b/src/include/duckdb/catalog/standard_entry.hpp @@ -25,6 +25,8 @@ class StandardEntry : public InCatalogEntry { //! The schema the entry belongs to SchemaCatalogEntry &schema; + //! The dependencies of the entry, can be empty + LogicalDependencyList dependencies; public: SchemaCatalogEntry &ParentSchema() override { diff --git a/src/include/duckdb/common/allocator.hpp b/src/include/duckdb/common/allocator.hpp index ac27d267a9d..9a8a0cd2146 100644 --- a/src/include/duckdb/common/allocator.hpp +++ b/src/include/duckdb/common/allocator.hpp @@ -23,10 +23,13 @@ class ThreadContext; struct AllocatorDebugInfo; +enum class AllocatorFreeType { REQUIRES_FREE, DOES_NOT_REQUIRE_FREE }; + struct PrivateAllocatorData { PrivateAllocatorData(); virtual ~PrivateAllocatorData(); + AllocatorFreeType free_type = AllocatorFreeType::REQUIRES_FREE; unique_ptr debug_info; template @@ -112,8 +115,12 @@ class Allocator { DUCKDB_API static Allocator &DefaultAllocator(); DUCKDB_API static shared_ptr &DefaultAllocatorReference(); + static bool SupportsFlush(); + static int64_t DecayDelay(); static void ThreadFlush(idx_t threshold); + static void ThreadIdle(); static void FlushAll(); + static void SetBackgroundThreads(bool enable); private: allocate_function_ptr_t allocate_function; diff --git a/src/include/duckdb/common/arrow/appender/append_data.hpp b/src/include/duckdb/common/arrow/appender/append_data.hpp index 52845cbd2dc..8414821d073 100644 --- a/src/include/duckdb/common/arrow/appender/append_data.hpp +++ b/src/include/duckdb/common/arrow/appender/append_data.hpp @@ -28,32 +28,56 @@ typedef void (*finalize_t)(ArrowAppendData &append_data, const LogicalType &type struct ArrowAppendData { explicit ArrowAppendData(ClientProperties &options_p) : options(options_p) { dictionary.release = nullptr; + arrow_buffers.resize(3); + } + + //! Getters for the Buffers + ArrowBuffer &GetValidityBuffer() { + return arrow_buffers[0]; + } + + ArrowBuffer &GetMainBuffer() { + return arrow_buffers[1]; + } + + ArrowBuffer &GetAuxBuffer() { + return arrow_buffers[2]; + } + + ArrowBuffer &GetBufferSizeBuffer() { + //! This is a special case, we resize it if necessary since it's a different size than set in the constructor + if (arrow_buffers.size() == 3) { + arrow_buffers.resize(4); + } + return arrow_buffers[3]; } - // the buffers of the arrow vector - ArrowBuffer validity; - ArrowBuffer main_buffer; - ArrowBuffer aux_buffer; idx_t row_count = 0; idx_t null_count = 0; - // function pointers for construction + //! function pointers for construction initialize_t initialize = nullptr; append_vector_t append_vector = nullptr; finalize_t finalize = nullptr; - // child data (if any) + //! child data (if any) vector> child_data; - // the arrow array C API data, only set after Finalize + //! the arrow array C API data, only set after Finalize unique_ptr array; - duckdb::array buffers = {{nullptr, nullptr, nullptr}}; + duckdb::array buffers = {{nullptr, nullptr, nullptr, nullptr}}; vector child_pointers; - // Arrays so the children can be moved + //! Arrays so the children can be moved vector child_arrays; ArrowArray dictionary; ClientProperties options; + //! Offset used to keep data positions when producing a mix of inlined and not-inlined arrow string views. + idx_t offset = 0; + +private: + //! The buffers of the arrow vector + vector arrow_buffers; }; //===--------------------------------------------------------------------===// @@ -90,14 +114,14 @@ static void SetNull(ArrowAppendData &append_data, uint8_t *validity_data, idx_t static void AppendValidity(ArrowAppendData &append_data, UnifiedVectorFormat &format, idx_t from, idx_t to) { // resize the buffer, filling the validity buffer with all valid values idx_t size = to - from; - ResizeValidity(append_data.validity, append_data.row_count + size); + ResizeValidity(append_data.GetValidityBuffer(), append_data.row_count + size); if (format.validity.AllValid()) { // if all values are valid we don't need to do anything else return; } // otherwise we iterate through the validity mask - auto validity_data = (uint8_t *)append_data.validity.data(); + auto validity_data = (uint8_t *)append_data.GetValidityBuffer().data(); uint8_t current_bit; idx_t current_byte; GetBitPosition(append_data.row_count, current_byte, current_bit); diff --git a/src/include/duckdb/common/arrow/appender/enum_data.hpp b/src/include/duckdb/common/arrow/appender/enum_data.hpp index f7f73e05514..90473d9b540 100644 --- a/src/include/duckdb/common/arrow/appender/enum_data.hpp +++ b/src/include/duckdb/common/arrow/appender/enum_data.hpp @@ -23,14 +23,15 @@ struct ArrowEnumData : public ArrowScalarBaseData { static void EnumAppendVector(ArrowAppendData &append_data, const Vector &input, idx_t size) { D_ASSERT(input.GetVectorType() == VectorType::FLAT_VECTOR); - + auto &main_buffer = append_data.GetMainBuffer(); + auto &aux_buffer = append_data.GetAuxBuffer(); // resize the validity mask and set up the validity buffer for iteration - ResizeValidity(append_data.validity, append_data.row_count + size); + ResizeValidity(append_data.GetValidityBuffer(), append_data.row_count + size); // resize the offset buffer - the offset buffer holds the offsets into the child array - append_data.main_buffer.resize(append_data.main_buffer.size() + sizeof(int32_t) * (size + 1)); + main_buffer.resize(main_buffer.size() + sizeof(int32_t) * (size + 1)); auto data = FlatVector::GetData(input); - auto offset_data = append_data.main_buffer.GetData(); + auto offset_data = main_buffer.GetData(); if (append_data.row_count == 0) { // first entry offset_data[0] = 0; @@ -48,8 +49,8 @@ struct ArrowEnumData : public ArrowScalarBaseData { offset_data[offset_idx] = UnsafeNumericCast(current_offset); // resize the string buffer if required, and write the string data - append_data.aux_buffer.resize(current_offset); - WriteData(append_data.aux_buffer.data() + last_offset, data[i]); + aux_buffer.resize(current_offset); + WriteData(aux_buffer.data() + last_offset, data[i]); last_offset = UnsafeNumericCast(current_offset); } @@ -57,7 +58,7 @@ struct ArrowEnumData : public ArrowScalarBaseData { } static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { - result.main_buffer.reserve(capacity * sizeof(TGT)); + result.GetMainBuffer().reserve(capacity * sizeof(TGT)); // construct the enum child data auto enum_data = ArrowAppender::InitializeChild(LogicalType::VARCHAR, EnumType::GetSize(type), result.options); EnumAppendVector(*enum_data, EnumType::GetValuesInsertOrder(type), EnumType::GetSize(type)); @@ -66,7 +67,7 @@ struct ArrowEnumData : public ArrowScalarBaseData { static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { result->n_buffers = 2; - result->buffers[1] = append_data.main_buffer.data(); + result->buffers[1] = append_data.GetMainBuffer().data(); // finalize the enum child data, and assign it to the dictionary result->dictionary = &append_data.dictionary; append_data.dictionary = diff --git a/src/include/duckdb/common/arrow/appender/list.hpp b/src/include/duckdb/common/arrow/appender/list.hpp index 54cc34dd4da..6ce97b5285f 100644 --- a/src/include/duckdb/common/arrow/appender/list.hpp +++ b/src/include/duckdb/common/arrow/appender/list.hpp @@ -2,6 +2,7 @@ #include "duckdb/common/arrow/appender/enum_data.hpp" #include "duckdb/common/arrow/appender/fixed_size_list_data.hpp" #include "duckdb/common/arrow/appender/list_data.hpp" +#include "duckdb/common/arrow/appender/list_view_data.hpp" #include "duckdb/common/arrow/appender/map_data.hpp" #include "duckdb/common/arrow/appender/scalar_data.hpp" #include "duckdb/common/arrow/appender/struct_data.hpp" diff --git a/src/include/duckdb/common/arrow/appender/list_data.hpp b/src/include/duckdb/common/arrow/appender/list_data.hpp index ca11f49a80c..0c2a1de6caf 100644 --- a/src/include/duckdb/common/arrow/appender/list_data.hpp +++ b/src/include/duckdb/common/arrow/appender/list_data.hpp @@ -9,7 +9,7 @@ struct ArrowListData { public: static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { auto &child_type = ListType::GetChildType(type); - result.main_buffer.reserve((capacity + 1) * sizeof(BUFTYPE)); + result.GetMainBuffer().reserve((capacity + 1) * sizeof(BUFTYPE)); auto child_buffer = ArrowAppender::InitializeChild(child_type, capacity, result.options); result.child_data.push_back(std::move(child_buffer)); } @@ -34,7 +34,7 @@ struct ArrowListData { static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { result->n_buffers = 2; - result->buffers[1] = append_data.main_buffer.data(); + result->buffers[1] = append_data.GetMainBuffer().data(); auto &child_type = ListType::GetChildType(type); ArrowAppender::AddChildren(append_data, 1); @@ -48,9 +48,11 @@ struct ArrowListData { vector &child_sel) { // resize the offset buffer - the offset buffer holds the offsets into the child array idx_t size = to - from; - append_data.main_buffer.resize(append_data.main_buffer.size() + sizeof(BUFTYPE) * (size + 1)); + auto &main_buffer = append_data.GetMainBuffer(); + + main_buffer.resize(main_buffer.size() + sizeof(BUFTYPE) * (size + 1)); auto data = UnifiedVectorFormat::GetData(format); - auto offset_data = append_data.main_buffer.GetData(); + auto offset_data = main_buffer.GetData(); if (append_data.row_count == 0) { // first entry offset_data[0] = 0; diff --git a/src/include/duckdb/common/arrow/appender/list_view_data.hpp b/src/include/duckdb/common/arrow/appender/list_view_data.hpp new file mode 100644 index 00000000000..889e2614f16 --- /dev/null +++ b/src/include/duckdb/common/arrow/appender/list_view_data.hpp @@ -0,0 +1,92 @@ +#pragma once + +#include "duckdb/common/arrow/appender/append_data.hpp" + +namespace duckdb { + +template +struct ArrowListViewData { +public: + static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { + auto &child_type = ListType::GetChildType(type); + result.GetMainBuffer().reserve(capacity * sizeof(BUFTYPE)); + result.GetAuxBuffer().reserve(capacity * sizeof(BUFTYPE)); + + auto child_buffer = ArrowAppender::InitializeChild(child_type, capacity, result.options); + result.child_data.push_back(std::move(child_buffer)); + } + + static void Append(ArrowAppendData &append_data, Vector &input, idx_t from, idx_t to, idx_t input_size) { + UnifiedVectorFormat format; + input.ToUnifiedFormat(input_size, format); + idx_t size = to - from; + vector child_indices; + AppendValidity(append_data, format, from, to); + AppendListMetadata(append_data, format, from, to, child_indices); + + // append the child vector of the list + SelectionVector child_sel(child_indices.data()); + auto &child = ListVector::GetEntry(input); + auto child_size = child_indices.size(); + Vector child_copy(child.GetType()); + child_copy.Slice(child, child_sel, child_size); + append_data.child_data[0]->append_vector(*append_data.child_data[0], child_copy, 0, child_size, child_size); + append_data.row_count += size; + } + + static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { + result->n_buffers = 3; + result->buffers[1] = append_data.GetMainBuffer().data(); + result->buffers[2] = append_data.GetAuxBuffer().data(); + + auto &child_type = ListType::GetChildType(type); + ArrowAppender::AddChildren(append_data, 1); + result->children = append_data.child_pointers.data(); + result->n_children = 1; + append_data.child_arrays[0] = *ArrowAppender::FinalizeChild(child_type, std::move(append_data.child_data[0])); + } + +public: + static void AppendListMetadata(ArrowAppendData &append_data, UnifiedVectorFormat &format, idx_t from, idx_t to, + vector &child_sel) { + // resize the offset buffer - the offset buffer holds the offsets into the child array + idx_t size = to - from; + append_data.GetMainBuffer().resize(append_data.GetMainBuffer().size() + sizeof(BUFTYPE) * size); + append_data.GetAuxBuffer().resize(append_data.GetAuxBuffer().size() + sizeof(BUFTYPE) * size); + auto data = UnifiedVectorFormat::GetData(format); + auto offset_data = append_data.GetMainBuffer().GetData(); + auto size_data = append_data.GetAuxBuffer().GetData(); + + BUFTYPE last_offset = + append_data.row_count ? offset_data[append_data.row_count - 1] + size_data[append_data.row_count - 1] : 0; + for (idx_t i = 0; i < size; i++) { + auto source_idx = format.sel->get_index(i + from); + auto offset_idx = append_data.row_count + i; + + if (!format.validity.RowIsValid(source_idx)) { + offset_data[offset_idx] = last_offset; + size_data[offset_idx] = 0; + continue; + } + + // append the offset data + auto list_length = data[source_idx].length; + if (std::is_same::value == true && + (uint64_t)last_offset + list_length > NumericLimits::Maximum()) { + throw InvalidInputException( + "Arrow Appender: The maximum combined list offset for regular list buffers is " + "%u but the offset of %lu exceeds this.", + NumericLimits::Maximum(), last_offset); + } + offset_data[offset_idx] = last_offset; + size_data[offset_idx] = UnsafeNumericCast(list_length); + last_offset += list_length; + + for (idx_t k = 0; k < list_length; k++) { + child_sel.push_back(UnsafeNumericCast(data[source_idx].offset + k)); + } + } + } +}; + +} // namespace duckdb diff --git a/src/include/duckdb/common/arrow/appender/map_data.hpp b/src/include/duckdb/common/arrow/appender/map_data.hpp index 630ff1664f9..afc67decdc5 100644 --- a/src/include/duckdb/common/arrow/appender/map_data.hpp +++ b/src/include/duckdb/common/arrow/appender/map_data.hpp @@ -16,7 +16,7 @@ struct ArrowMapData { // map types are stored in a (too) clever way // the main buffer holds the null values and the offsets // then we have a single child, which is a struct of the map_type, and the key_type - result.main_buffer.reserve((capacity + 1) * sizeof(BUFTYPE)); + result.GetMainBuffer().reserve((capacity + 1) * sizeof(BUFTYPE)); auto &key_type = MapType::KeyType(type); auto &value_type = MapType::ValueType(type); @@ -59,7 +59,7 @@ struct ArrowMapData { // set up the main map buffer D_ASSERT(result); result->n_buffers = 2; - result->buffers[1] = append_data.main_buffer.data(); + result->buffers[1] = append_data.GetMainBuffer().data(); // the main map buffer has a single child: a struct ArrowAppender::AddChildren(append_data, 1); diff --git a/src/include/duckdb/common/arrow/appender/scalar_data.hpp b/src/include/duckdb/common/arrow/appender/scalar_data.hpp index 2c2769e1444..efb4e81415d 100644 --- a/src/include/duckdb/common/arrow/appender/scalar_data.hpp +++ b/src/include/duckdb/common/arrow/appender/scalar_data.hpp @@ -42,6 +42,21 @@ struct ArrowIntervalConverter { } }; +struct ArrowTimeTzConverter { + template + static TGT Operation(SRC input) { + return input.time().micros; + } + + static bool SkipNulls() { + return true; + } + + template + static void SetNull(TGT &value) { + } +}; + template struct ArrowScalarBaseData { static void Append(ArrowAppendData &append_data, Vector &input, idx_t from, idx_t to, idx_t input_size) { @@ -55,9 +70,10 @@ struct ArrowScalarBaseData { AppendValidity(append_data, format, from, to); // append the main data - append_data.main_buffer.resize(append_data.main_buffer.size() + sizeof(TGT) * size); + auto &main_buffer = append_data.GetMainBuffer(); + main_buffer.resize(main_buffer.size() + sizeof(TGT) * size); auto data = UnifiedVectorFormat::GetData(format); - auto result_data = append_data.main_buffer.GetData(); + auto result_data = main_buffer.GetData(); for (idx_t i = from; i < to; i++) { auto source_idx = format.sel->get_index(i); @@ -76,12 +92,12 @@ struct ArrowScalarBaseData { template struct ArrowScalarData : public ArrowScalarBaseData { static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { - result.main_buffer.reserve(capacity * sizeof(TGT)); + result.GetMainBuffer().reserve(capacity * sizeof(TGT)); } static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { result->n_buffers = 2; - result->buffers[1] = append_data.main_buffer.data(); + result->buffers[1] = append_data.GetMainBuffer().data(); } }; diff --git a/src/include/duckdb/common/arrow/appender/varchar_data.hpp b/src/include/duckdb/common/arrow/appender/varchar_data.hpp index 753756b9ea0..25c714548ef 100644 --- a/src/include/duckdb/common/arrow/appender/varchar_data.hpp +++ b/src/include/duckdb/common/arrow/appender/varchar_data.hpp @@ -2,6 +2,7 @@ #include "duckdb/common/arrow/appender/append_data.hpp" #include "duckdb/common/arrow/appender/scalar_data.hpp" +#include "duckdb/common/types/arrow_string_view_type.hpp" namespace duckdb { @@ -35,9 +36,8 @@ struct ArrowUUIDConverter { template struct ArrowVarcharData { static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { - result.main_buffer.reserve((capacity + 1) * sizeof(BUFTYPE)); - - result.aux_buffer.reserve(capacity); + result.GetMainBuffer().reserve((capacity + 1) * sizeof(BUFTYPE)); + result.GetAuxBuffer().reserve(capacity); } template @@ -45,15 +45,18 @@ struct ArrowVarcharData { idx_t size = to - from; UnifiedVectorFormat format; input.ToUnifiedFormat(input_size, format); + auto &main_buffer = append_data.GetMainBuffer(); + auto &validity_buffer = append_data.GetValidityBuffer(); + auto &aux_buffer = append_data.GetAuxBuffer(); // resize the validity mask and set up the validity buffer for iteration - ResizeValidity(append_data.validity, append_data.row_count + size); - auto validity_data = (uint8_t *)append_data.validity.data(); + ResizeValidity(validity_buffer, append_data.row_count + size); + auto validity_data = (uint8_t *)validity_buffer.data(); // resize the offset buffer - the offset buffer holds the offsets into the child array - append_data.main_buffer.resize(append_data.main_buffer.size() + sizeof(BUFTYPE) * (size + 1)); + main_buffer.resize(main_buffer.size() + sizeof(BUFTYPE) * (size + 1)); auto data = UnifiedVectorFormat::GetData(format); - auto offset_data = append_data.main_buffer.GetData(); + auto offset_data = main_buffer.GetData(); if (append_data.row_count == 0) { // first entry offset_data[0] = 0; @@ -89,8 +92,8 @@ struct ArrowVarcharData { offset_data[offset_idx] = UnsafeNumericCast(current_offset); // resize the string buffer if required, and write the string data - append_data.aux_buffer.resize(current_offset); - OP::WriteData(append_data.aux_buffer.data() + last_offset, data[source_idx]); + aux_buffer.resize(current_offset); + OP::WriteData(aux_buffer.data() + last_offset, data[source_idx]); last_offset = UnsafeNumericCast(current_offset); } @@ -108,8 +111,83 @@ struct ArrowVarcharData { static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { result->n_buffers = 3; - result->buffers[1] = append_data.main_buffer.data(); - result->buffers[2] = append_data.aux_buffer.data(); + result->buffers[1] = append_data.GetMainBuffer().data(); + result->buffers[2] = append_data.GetAuxBuffer().data(); + } +}; + +struct ArrowVarcharToStringViewData { + static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { + result.GetMainBuffer().reserve((capacity) * sizeof(arrow_string_view_t)); + result.GetAuxBuffer().reserve(capacity); + result.GetBufferSizeBuffer().reserve(sizeof(int64_t)); + } + + static void Append(ArrowAppendData &append_data, Vector &input, idx_t from, idx_t to, idx_t input_size) { + idx_t size = to - from; + UnifiedVectorFormat format; + input.ToUnifiedFormat(input_size, format); + auto &main_buffer = append_data.GetMainBuffer(); + auto &validity_buffer = append_data.GetValidityBuffer(); + auto &aux_buffer = append_data.GetAuxBuffer(); + // resize the validity mask and set up the validity buffer for iteration + ResizeValidity(validity_buffer, append_data.row_count + size); + auto validity_data = (uint8_t *)validity_buffer.data(); + + main_buffer.resize(main_buffer.size() + sizeof(arrow_string_view_t) * (size)); + // resize the offset buffer - the offset buffer holds the offsets into the child array + auto data = UnifiedVectorFormat::GetData(format); + for (idx_t i = from; i < to; i++) { + auto result_idx = append_data.row_count + i - from; + auto arrow_data = main_buffer.GetData(); + auto source_idx = format.sel->get_index(i); + if (!format.validity.RowIsValid(source_idx)) { + // Null value + uint8_t current_bit; + idx_t current_byte; + GetBitPosition(result_idx, current_byte, current_bit); + SetNull(append_data, validity_data, current_byte, current_bit); + // We have to set these bytes to 0, for some reason + arrow_data[result_idx] = arrow_string_view_t(0, ""); + continue; + } + // These two are now the same buffer + idx_t string_length = ArrowVarcharConverter::GetLength(data[source_idx]); + auto string_data = data[source_idx].GetData(); + if (string_length <= ArrowStringViewConstants::MAX_INLINED_BYTES) { + // This string is inlined + // | Bytes 0-3 | Bytes 4-15 | + // |------------|---------------------------------------| + // | length | data (padded with 0) | + arrow_data[result_idx] = arrow_string_view_t(UnsafeNumericCast(string_length), string_data); + } else { + // This string is not inlined, we have to check a different buffer and offsets + // | Bytes 0-3 | Bytes 4-7 | Bytes 8-11 | Bytes 12-15 | + // |------------|------------|------------|-------------| + // | length | prefix | buf. index | offset | + arrow_data[result_idx] = arrow_string_view_t(UnsafeNumericCast(string_length), string_data, 0, + UnsafeNumericCast(append_data.offset)); + auto current_offset = append_data.offset + string_length; + aux_buffer.resize(current_offset); + ArrowVarcharConverter::WriteData(aux_buffer.data() + append_data.offset, data[source_idx]); + append_data.offset = current_offset; + } + } + append_data.row_count += size; + } + + static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { + // We output four buffers + result->n_buffers = 4; + // Buffer 0 is the validity mask + // Buffer 1 is our string views (short/long strings) + result->buffers[1] = append_data.GetMainBuffer().data(); + // Buffer 2 is our only data buffer, could theoretically be more [ buffers ] + result->buffers[2] = append_data.GetAuxBuffer().data(); + // Buffer 3 is the data-buffer lengths buffer, and we also populate it in to finalize + reinterpret_cast(append_data.GetBufferSizeBuffer().data())[0] = + UnsafeNumericCast(append_data.offset); + result->buffers[3] = append_data.GetBufferSizeBuffer().data(); } }; diff --git a/src/include/duckdb/common/arrow/arrow_buffer.hpp b/src/include/duckdb/common/arrow/arrow_buffer.hpp index e1624ef64da..66dd863f7e6 100644 --- a/src/include/duckdb/common/arrow/arrow_buffer.hpp +++ b/src/include/duckdb/common/arrow/arrow_buffer.hpp @@ -32,7 +32,7 @@ struct ArrowBuffer { ArrowBuffer(const ArrowBuffer &other) = delete; ArrowBuffer &operator=(const ArrowBuffer &) = delete; //! enable move constructors - ArrowBuffer(ArrowBuffer &&other) noexcept { + ArrowBuffer(ArrowBuffer &&other) noexcept : count(0), capacity(0) { std::swap(dataptr, other.dataptr); std::swap(count, other.count); std::swap(capacity, other.capacity); diff --git a/src/include/duckdb/common/bswap.hpp b/src/include/duckdb/common/bswap.hpp index 16119f453a6..fbcafb8f6dd 100644 --- a/src/include/duckdb/common/bswap.hpp +++ b/src/include/duckdb/common/bswap.hpp @@ -25,22 +25,24 @@ namespace duckdb { (((uint64_t)(x)&0x00000000ff000000ull) << 8) | (((uint64_t)(x)&0x0000000000ff0000ull) << 24) | \ (((uint64_t)(x)&0x000000000000ff00ull) << 40) | (((uint64_t)(x)&0x00000000000000ffull) << 56))) -template -static inline T BSwap(const T &x) { - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, - "Size of type must be 1, 2, 4, or 8 for BSwap"); - if (sizeof(T) == 1) { - return x; - } else if (sizeof(T) == 2) { - return BSWAP16(x); - } else if (sizeof(T) == 4) { - // this check is superfluous as the branch is not taken for small return types but the compiler does not realize - // that - return UnsafeNumericCast(BSWAP32(x)); - } else { - // see above - return UnsafeNumericCast(BSWAP64(x)); - } +static inline uint8_t BSwap(const uint8_t &x) { + return x; +} + +static inline uint16_t BSwap(const uint16_t &x) { + return BSWAP16(x); +} + +static inline uint32_t BSwap(const uint32_t &x) { + return BSWAP32(x); +} + +static inline uint64_t BSwap(const uint64_t &x) { + return BSWAP64(x); +} + +static inline int64_t BSwap(const int64_t &x) { + return static_cast(BSWAP64(x)); } } // namespace duckdb diff --git a/src/include/duckdb/common/constants.hpp b/src/include/duckdb/common/constants.hpp index 57d9f1661b6..d4a0d7cda1c 100644 --- a/src/include/duckdb/common/constants.hpp +++ b/src/include/duckdb/common/constants.hpp @@ -57,6 +57,8 @@ extern const double PI; struct DConstants { //! The value used to signify an invalid index entry static constexpr const idx_t INVALID_INDEX = idx_t(-1); + //! The total maximum vector size (128GB) + static constexpr const idx_t MAX_VECTOR_SIZE = 1ULL << 37ULL; }; struct LogicalIndex { diff --git a/src/include/duckdb/common/enable_shared_from_this.ipp b/src/include/duckdb/common/enable_shared_from_this_ipp.hpp similarity index 100% rename from src/include/duckdb/common/enable_shared_from_this.ipp rename to src/include/duckdb/common/enable_shared_from_this_ipp.hpp diff --git a/src/include/duckdb/common/enum_util.hpp b/src/include/duckdb/common/enum_util.hpp index 81b670cd74b..fde2a58e4e6 100644 --- a/src/include/duckdb/common/enum_util.hpp +++ b/src/include/duckdb/common/enum_util.hpp @@ -60,8 +60,12 @@ enum class ArrowDateTimeType : uint8_t; enum class ArrowOffsetSize : uint8_t; +enum class ArrowTypeInfoType : uint8_t; + enum class ArrowVariableSizeType : uint8_t; +enum class BinderType : uint8_t; + enum class BindingMode : uint8_t; enum class BitpackingMode : uint8_t; @@ -96,6 +100,12 @@ enum class ConflictManagerMode : uint8_t; enum class ConstraintType : uint8_t; +enum class CopyFunctionReturnType : uint8_t; + +enum class CopyOverwriteMode : uint8_t; + +enum class CopyToType : uint8_t; + enum class DataFileType : uint8_t; enum class DatePartSpecifier : uint8_t; @@ -120,13 +130,17 @@ enum class ExplainOutputType : uint8_t; enum class ExplainType : uint8_t; +enum class ExponentType : uint8_t; + enum class ExpressionClass : uint8_t; enum class ExpressionType : uint8_t; +enum class ExtensionInstallMode : uint8_t; + enum class ExtensionLoadResult : uint8_t; -enum class ExternalDependenciesType : uint8_t; +enum class ExtensionUpdateResultTag : uint8_t; enum class ExtraDropInfoType : uint8_t; @@ -136,6 +150,8 @@ enum class FileBufferType : uint8_t; enum class FileCompressionType : uint8_t; +enum class FileExpandResult : uint8_t; + enum class FileGlobOptions : uint8_t; enum class FileLockType : uint8_t; @@ -178,6 +194,8 @@ enum class MapInvalidReason : uint8_t; enum class MemoryTag : uint8_t; +enum class MetricsType : uint8_t; + enum class NType : uint8_t; enum class NewLineIdentifier : uint8_t; @@ -242,6 +260,8 @@ enum class ResultModifierType : uint8_t; enum class SampleMethod : uint8_t; +enum class SampleType : uint8_t; + enum class ScanType : uint8_t; enum class SecretDisplayType : uint8_t; @@ -298,6 +318,8 @@ enum class TaskExecutionResult : uint8_t; enum class TimestampCastResult : uint8_t; +enum class TransactionModifierType : uint8_t; + enum class TransactionType : uint8_t; enum class TupleDataPinProperties : uint8_t; @@ -367,9 +389,15 @@ const char* EnumUtil::ToChars(ArrowDateTimeType value); template<> const char* EnumUtil::ToChars(ArrowOffsetSize value); +template<> +const char* EnumUtil::ToChars(ArrowTypeInfoType value); + template<> const char* EnumUtil::ToChars(ArrowVariableSizeType value); +template<> +const char* EnumUtil::ToChars(BinderType value); + template<> const char* EnumUtil::ToChars(BindingMode value); @@ -421,6 +449,15 @@ const char* EnumUtil::ToChars(ConflictManagerMode value); template<> const char* EnumUtil::ToChars(ConstraintType value); +template<> +const char* EnumUtil::ToChars(CopyFunctionReturnType value); + +template<> +const char* EnumUtil::ToChars(CopyOverwriteMode value); + +template<> +const char* EnumUtil::ToChars(CopyToType value); + template<> const char* EnumUtil::ToChars(DataFileType value); @@ -457,17 +494,23 @@ const char* EnumUtil::ToChars(ExplainOutputType value); template<> const char* EnumUtil::ToChars(ExplainType value); +template<> +const char* EnumUtil::ToChars(ExponentType value); + template<> const char* EnumUtil::ToChars(ExpressionClass value); template<> const char* EnumUtil::ToChars(ExpressionType value); +template<> +const char* EnumUtil::ToChars(ExtensionInstallMode value); + template<> const char* EnumUtil::ToChars(ExtensionLoadResult value); template<> -const char* EnumUtil::ToChars(ExternalDependenciesType value); +const char* EnumUtil::ToChars(ExtensionUpdateResultTag value); template<> const char* EnumUtil::ToChars(ExtraDropInfoType value); @@ -481,6 +524,9 @@ const char* EnumUtil::ToChars(FileBufferType value); template<> const char* EnumUtil::ToChars(FileCompressionType value); +template<> +const char* EnumUtil::ToChars(FileExpandResult value); + template<> const char* EnumUtil::ToChars(FileGlobOptions value); @@ -544,6 +590,9 @@ const char* EnumUtil::ToChars(MapInvalidReason value); template<> const char* EnumUtil::ToChars(MemoryTag value); +template<> +const char* EnumUtil::ToChars(MetricsType value); + template<> const char* EnumUtil::ToChars(NType value); @@ -640,6 +689,9 @@ const char* EnumUtil::ToChars(ResultModifierType value); template<> const char* EnumUtil::ToChars(SampleMethod value); +template<> +const char* EnumUtil::ToChars(SampleType value); + template<> const char* EnumUtil::ToChars(ScanType value); @@ -724,6 +776,9 @@ const char* EnumUtil::ToChars(TaskExecutionResult value); template<> const char* EnumUtil::ToChars(TimestampCastResult value); +template<> +const char* EnumUtil::ToChars(TransactionModifierType value); + template<> const char* EnumUtil::ToChars(TransactionType value); @@ -806,9 +861,15 @@ ArrowDateTimeType EnumUtil::FromString(const char *value); template<> ArrowOffsetSize EnumUtil::FromString(const char *value); +template<> +ArrowTypeInfoType EnumUtil::FromString(const char *value); + template<> ArrowVariableSizeType EnumUtil::FromString(const char *value); +template<> +BinderType EnumUtil::FromString(const char *value); + template<> BindingMode EnumUtil::FromString(const char *value); @@ -860,6 +921,15 @@ ConflictManagerMode EnumUtil::FromString(const char *value) template<> ConstraintType EnumUtil::FromString(const char *value); +template<> +CopyFunctionReturnType EnumUtil::FromString(const char *value); + +template<> +CopyOverwriteMode EnumUtil::FromString(const char *value); + +template<> +CopyToType EnumUtil::FromString(const char *value); + template<> DataFileType EnumUtil::FromString(const char *value); @@ -896,17 +966,23 @@ ExplainOutputType EnumUtil::FromString(const char *value); template<> ExplainType EnumUtil::FromString(const char *value); +template<> +ExponentType EnumUtil::FromString(const char *value); + template<> ExpressionClass EnumUtil::FromString(const char *value); template<> ExpressionType EnumUtil::FromString(const char *value); +template<> +ExtensionInstallMode EnumUtil::FromString(const char *value); + template<> ExtensionLoadResult EnumUtil::FromString(const char *value); template<> -ExternalDependenciesType EnumUtil::FromString(const char *value); +ExtensionUpdateResultTag EnumUtil::FromString(const char *value); template<> ExtraDropInfoType EnumUtil::FromString(const char *value); @@ -920,6 +996,9 @@ FileBufferType EnumUtil::FromString(const char *value); template<> FileCompressionType EnumUtil::FromString(const char *value); +template<> +FileExpandResult EnumUtil::FromString(const char *value); + template<> FileGlobOptions EnumUtil::FromString(const char *value); @@ -983,6 +1062,9 @@ MapInvalidReason EnumUtil::FromString(const char *value); template<> MemoryTag EnumUtil::FromString(const char *value); +template<> +MetricsType EnumUtil::FromString(const char *value); + template<> NType EnumUtil::FromString(const char *value); @@ -1079,6 +1161,9 @@ ResultModifierType EnumUtil::FromString(const char *value); template<> SampleMethod EnumUtil::FromString(const char *value); +template<> +SampleType EnumUtil::FromString(const char *value); + template<> ScanType EnumUtil::FromString(const char *value); @@ -1163,6 +1248,9 @@ TaskExecutionResult EnumUtil::FromString(const char *value) template<> TimestampCastResult EnumUtil::FromString(const char *value); +template<> +TransactionModifierType EnumUtil::FromString(const char *value); + template<> TransactionType EnumUtil::FromString(const char *value); diff --git a/src/include/duckdb/common/enums/checkpoint_type.hpp b/src/include/duckdb/common/enums/checkpoint_type.hpp new file mode 100644 index 00000000000..580d810a5e8 --- /dev/null +++ b/src/include/duckdb/common/enums/checkpoint_type.hpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/enums/checkpoint_type.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/constants.hpp" + +namespace duckdb { + +enum class CheckpointWALAction { + //! Delete the WAL file after the checkpoint completes - generally done on shutdown + DELETE_WAL, + //! Leave the WAL file alone + DONT_DELETE_WAL +}; + +enum class CheckpointAction { + //! Checkpoint only if a checkpoint is required (i.e. the WAL has data in it that can be flushed) + CHECKPOINT_IF_REQUIRED, + //! Force a checkpoint regardless of whether or not there is data in the WAL to flush + FORCE_CHECKPOINT +}; + +enum class CheckpointType { + //! Full checkpoints involve vacuuming deleted rows and updates + //! They can only be run if no transaction need to read old data (that would be cleaned up/vacuumed) + FULL_CHECKPOINT, + //! Concurrent checkpoints write committed data to disk but do less clean-up + //! They can be run even when active transactions need to read old data + CONCURRENT_CHECKPOINT +}; + +} // namespace duckdb diff --git a/extension/excel/include/excel_extension.hpp b/src/include/duckdb/common/enums/copy_overwrite_mode.hpp similarity index 50% rename from extension/excel/include/excel_extension.hpp rename to src/include/duckdb/common/enums/copy_overwrite_mode.hpp index 156bb7ec6b0..89644f8993e 100644 --- a/extension/excel/include/excel_extension.hpp +++ b/src/include/duckdb/common/enums/copy_overwrite_mode.hpp @@ -1,22 +1,23 @@ //===----------------------------------------------------------------------===// // DuckDB // -// excel_extension.hpp +// duckdb/common/enums/copy_overwrite_mode.hpp // // //===----------------------------------------------------------------------===// #pragma once -#include "duckdb.hpp" -#include "duckdb/main/client_context.hpp" +#include "duckdb/common/constants.hpp" +#include "duckdb/common/vector.hpp" namespace duckdb { -class ExcelExtension : public Extension { -public: - void Load(DuckDB &db) override; - std::string Name() override; +enum class CopyOverwriteMode : uint8_t { + COPY_ERROR_ON_CONFLICT = 0, + COPY_OVERWRITE = 1, + COPY_OVERWRITE_OR_IGNORE = 2, + COPY_APPEND = 3 }; } // namespace duckdb diff --git a/src/include/duckdb/common/enums/join_type.hpp b/src/include/duckdb/common/enums/join_type.hpp index 4b3446963ea..8ba8e27295f 100644 --- a/src/include/duckdb/common/enums/join_type.hpp +++ b/src/include/duckdb/common/enums/join_type.hpp @@ -29,8 +29,8 @@ enum class JoinType : uint8_t { // (and NULL if no partner is found) RIGHT_SEMI = 9, // RIGHT SEMI join is created by the optimizer when the children of a semi join need to be switched // so that the build side can be the smaller table - RIGHT_ANTI = 10 // RIGHT ANTI join is created by the optimizer when the children of an anti join need to be switched - // so that the build side can be the smaller table + RIGHT_ANTI = 10 // RIGHT ANTI join is created by the optimizer when the children of an anti join need to be + // switched so that the build side can be the smaller table }; //! True if join is left or full outer join diff --git a/src/include/duckdb/common/enums/logical_operator_type.hpp b/src/include/duckdb/common/enums/logical_operator_type.hpp index e9e435ae17b..1375886bac7 100644 --- a/src/include/duckdb/common/enums/logical_operator_type.hpp +++ b/src/include/duckdb/common/enums/logical_operator_type.hpp @@ -100,6 +100,7 @@ enum class LogicalOperatorType : uint8_t { LOGICAL_SET = 179, LOGICAL_LOAD = 180, LOGICAL_RESET = 181, + LOGICAL_UPDATE_EXTENSIONS = 182, // ----------------------------- // Secrets diff --git a/src/include/duckdb/common/enums/optimizer_type.hpp b/src/include/duckdb/common/enums/optimizer_type.hpp index c687ec406e5..04223b4b7c6 100644 --- a/src/include/duckdb/common/enums/optimizer_type.hpp +++ b/src/include/duckdb/common/enums/optimizer_type.hpp @@ -28,6 +28,8 @@ enum class OptimizerType : uint32_t { COMMON_SUBEXPRESSIONS, COMMON_AGGREGATE, COLUMN_LIFETIME, + BUILD_SIDE_PROBE_SIDE, + LIMIT_PUSHDOWN, TOP_N, COMPRESSED_MATERIALIZATION, DUPLICATE_GROUPS, diff --git a/src/include/duckdb/common/enums/physical_operator_type.hpp b/src/include/duckdb/common/enums/physical_operator_type.hpp index 608efb4d0a2..7aadb07b3f2 100644 --- a/src/include/duckdb/common/enums/physical_operator_type.hpp +++ b/src/include/duckdb/common/enums/physical_operator_type.hpp @@ -113,6 +113,7 @@ enum class PhysicalOperatorType : uint8_t { RESET, EXTENSION, VERIFY_VECTOR, + UPDATE_EXTENSIONS, // ----------------------------- // Secret diff --git a/src/include/duckdb/common/enums/relation_type.hpp b/src/include/duckdb/common/enums/relation_type.hpp index f1c5fd33a03..30af8873bee 100644 --- a/src/include/duckdb/common/enums/relation_type.hpp +++ b/src/include/duckdb/common/enums/relation_type.hpp @@ -32,6 +32,7 @@ enum class RelationType : uint8_t { CREATE_TABLE_RELATION, INSERT_RELATION, VALUE_LIST_RELATION, + MATERIALIZED_RELATION, DELETE_RELATION, UPDATE_RELATION, WRITE_CSV_RELATION, diff --git a/src/include/duckdb/common/enums/scan_options.hpp b/src/include/duckdb/common/enums/scan_options.hpp index 3281aff401f..31223e43706 100644 --- a/src/include/duckdb/common/enums/scan_options.hpp +++ b/src/include/duckdb/common/enums/scan_options.hpp @@ -21,7 +21,9 @@ enum class TableScanType : uint8_t { TABLE_SCAN_COMMITTED_ROWS_DISALLOW_UPDATES = 2, //! Scan all rows, excluding any permanently deleted rows. //! Permanently deleted rows are rows which no transaction will ever need again. - TABLE_SCAN_COMMITTED_ROWS_OMIT_PERMANENTLY_DELETED = 3 + TABLE_SCAN_COMMITTED_ROWS_OMIT_PERMANENTLY_DELETED = 3, + //! Scan the latest committed rows + TABLE_SCAN_LATEST_COMMITTED_ROWS = 4 }; } // namespace duckdb diff --git a/extension/sqlsmith/include/sqlsmith_extension.hpp b/src/include/duckdb/common/enums/scan_vector_type.hpp similarity index 61% rename from extension/sqlsmith/include/sqlsmith_extension.hpp rename to src/include/duckdb/common/enums/scan_vector_type.hpp index 2fb3a07896d..dcdf6e90c0a 100644 --- a/extension/sqlsmith/include/sqlsmith_extension.hpp +++ b/src/include/duckdb/common/enums/scan_vector_type.hpp @@ -1,21 +1,17 @@ //===----------------------------------------------------------------------===// // DuckDB // -// sqlsmith_extension.hpp +// duckdb/common/enums/scan_vector_type.hpp // // //===----------------------------------------------------------------------===// #pragma once -#include "duckdb.hpp" +#include "duckdb/common/constants.hpp" namespace duckdb { -class SqlsmithExtension : public Extension { -public: - void Load(DuckDB &db) override; - std::string Name() override; -}; +enum class ScanVectorType { SCAN_ENTIRE_VECTOR, SCAN_FLAT_VECTOR }; } // namespace duckdb diff --git a/src/include/duckdb/common/enums/statement_type.hpp b/src/include/duckdb/common/enums/statement_type.hpp index 26ecce70ad6..e927ee0cd5d 100644 --- a/src/include/duckdb/common/enums/statement_type.hpp +++ b/src/include/duckdb/common/enums/statement_type.hpp @@ -46,6 +46,7 @@ enum class StatementType : uint8_t { DETACH_STATEMENT, MULTI_STATEMENT, COPY_DATABASE_STATEMENT, + UPDATE_EXTENSIONS_STATEMENT, }; DUCKDB_API string StatementTypeToString(StatementType type); diff --git a/src/include/duckdb/common/enums/tableref_type.hpp b/src/include/duckdb/common/enums/tableref_type.hpp index c4cf9844a45..09dff91eddb 100644 --- a/src/include/duckdb/common/enums/tableref_type.hpp +++ b/src/include/duckdb/common/enums/tableref_type.hpp @@ -25,7 +25,8 @@ enum class TableReferenceType : uint8_t { CTE = 7, // Recursive CTE EMPTY_FROM = 8, // placeholder for empty FROM PIVOT = 9, // pivot statement - SHOW_REF = 10 // SHOW statement + SHOW_REF = 10, // SHOW statement + COLUMN_DATA = 11 // column data collection }; } // namespace duckdb diff --git a/src/include/duckdb/common/enums/undo_flags.hpp b/src/include/duckdb/common/enums/undo_flags.hpp index 92816114497..a91548bda39 100644 --- a/src/include/duckdb/common/enums/undo_flags.hpp +++ b/src/include/duckdb/common/enums/undo_flags.hpp @@ -17,7 +17,8 @@ enum class UndoFlags : uint32_t { // far too big but aligned (TM) CATALOG_ENTRY = 1, INSERT_TUPLE = 2, DELETE_TUPLE = 3, - UPDATE_TUPLE = 4 + UPDATE_TUPLE = 4, + SEQUENCE_VALUE = 5 }; } // namespace duckdb diff --git a/src/include/duckdb/common/exception.hpp b/src/include/duckdb/common/exception.hpp index 4f8dc1e16bb..036582a1c25 100644 --- a/src/include/duckdb/common/exception.hpp +++ b/src/include/duckdb/common/exception.hpp @@ -322,7 +322,7 @@ class InvalidInputException : public Exception { : InvalidInputException(ConstructMessage(msg, params...)) { } template - explicit InvalidInputException(Expression &expr, const string &msg, ARGS... params) + explicit InvalidInputException(const Expression &expr, const string &msg, ARGS... params) : InvalidInputException(ConstructMessage(msg, params...), Exception::InitializeExtraInfo(expr)) { } }; diff --git a/src/include/duckdb/common/extra_operator_info.hpp b/src/include/duckdb/common/extra_operator_info.hpp index 194246bc085..ceb24638a50 100644 --- a/src/include/duckdb/common/extra_operator_info.hpp +++ b/src/include/duckdb/common/extra_operator_info.hpp @@ -20,8 +20,20 @@ class ExtraOperatorInfo { ExtraOperatorInfo() : file_filters("") { } ExtraOperatorInfo(ExtraOperatorInfo &extra_info) : file_filters(extra_info.file_filters) { + if (extra_info.total_files.IsValid()) { + total_files = extra_info.total_files.GetIndex(); + } + if (extra_info.filtered_files.IsValid()) { + filtered_files = extra_info.filtered_files.GetIndex(); + } } + + //! Filters that have been pushed down into the main file list string file_filters; + //! Total size of file list + optional_idx total_files; + //! Size of file list after applying filters + optional_idx filtered_files; }; } // namespace duckdb diff --git a/src/include/duckdb/common/extra_type_info.hpp b/src/include/duckdb/common/extra_type_info.hpp index 8c8f8c0a62a..7ed7197b5c9 100644 --- a/src/include/duckdb/common/extra_type_info.hpp +++ b/src/include/duckdb/common/extra_type_info.hpp @@ -36,12 +36,14 @@ struct ExtraTypeInfo { ExtraTypeInfoType type; string alias; + vector modifiers; public: bool Equals(ExtraTypeInfo *other_p) const; virtual void Serialize(Serializer &serializer) const; static shared_ptr Deserialize(Deserializer &source); + virtual shared_ptr Copy() const; template TARGET &Cast() { @@ -67,6 +69,7 @@ struct DecimalTypeInfo : public ExtraTypeInfo { public: void Serialize(Serializer &serializer) const override; static shared_ptr Deserialize(Deserializer &source); + shared_ptr Copy() const override; protected: bool EqualsInternal(ExtraTypeInfo *other_p) const override; @@ -83,6 +86,7 @@ struct StringTypeInfo : public ExtraTypeInfo { public: void Serialize(Serializer &serializer) const override; static shared_ptr Deserialize(Deserializer &source); + shared_ptr Copy() const override; protected: bool EqualsInternal(ExtraTypeInfo *other_p) const override; @@ -99,6 +103,7 @@ struct ListTypeInfo : public ExtraTypeInfo { public: void Serialize(Serializer &serializer) const override; static shared_ptr Deserialize(Deserializer &source); + shared_ptr Copy() const override; protected: bool EqualsInternal(ExtraTypeInfo *other_p) const override; @@ -115,6 +120,7 @@ struct StructTypeInfo : public ExtraTypeInfo { public: void Serialize(Serializer &serializer) const override; static shared_ptr Deserialize(Deserializer &deserializer); + shared_ptr Copy() const override; protected: bool EqualsInternal(ExtraTypeInfo *other_p) const override; @@ -131,6 +137,7 @@ struct AggregateStateTypeInfo : public ExtraTypeInfo { public: void Serialize(Serializer &serializer) const override; static shared_ptr Deserialize(Deserializer &source); + shared_ptr Copy() const override; protected: bool EqualsInternal(ExtraTypeInfo *other_p) const override; @@ -141,15 +148,18 @@ struct AggregateStateTypeInfo : public ExtraTypeInfo { struct UserTypeInfo : public ExtraTypeInfo { explicit UserTypeInfo(string name_p); - UserTypeInfo(string catalog_p, string schema_p, string name_p); + UserTypeInfo(string name_p, vector modifiers_p); + UserTypeInfo(string catalog_p, string schema_p, string name_p, vector modifiers_p); string catalog; string schema; string user_type_name; + vector user_type_modifiers; public: void Serialize(Serializer &serializer) const override; static shared_ptr Deserialize(Deserializer &source); + shared_ptr Copy() const override; protected: bool EqualsInternal(ExtraTypeInfo *other_p) const override; @@ -176,6 +186,7 @@ struct EnumTypeInfo : public ExtraTypeInfo { void Serialize(Serializer &serializer) const override; static shared_ptr Deserialize(Deserializer &source); + shared_ptr Copy() const override; protected: // Equalities are only used in enums with different catalog entries @@ -196,6 +207,7 @@ struct ArrayTypeInfo : public ExtraTypeInfo { public: void Serialize(Serializer &serializer) const override; static shared_ptr Deserialize(Deserializer &reader); + shared_ptr Copy() const override; protected: bool EqualsInternal(ExtraTypeInfo *other_p) const override; @@ -210,6 +222,7 @@ struct AnyTypeInfo : public ExtraTypeInfo { public: void Serialize(Serializer &serializer) const override; static shared_ptr Deserialize(Deserializer &source); + shared_ptr Copy() const override; protected: bool EqualsInternal(ExtraTypeInfo *other_p) const override; @@ -226,6 +239,7 @@ struct IntegerLiteralTypeInfo : public ExtraTypeInfo { public: void Serialize(Serializer &serializer) const override; static shared_ptr Deserialize(Deserializer &source); + shared_ptr Copy() const override; protected: bool EqualsInternal(ExtraTypeInfo *other_p) const override; diff --git a/src/include/duckdb/common/file_buffer.hpp b/src/include/duckdb/common/file_buffer.hpp index 876aeab4978..1a3e6e9cb08 100644 --- a/src/include/duckdb/common/file_buffer.hpp +++ b/src/include/duckdb/common/file_buffer.hpp @@ -17,6 +17,8 @@ struct FileHandle; enum class FileBufferType : uint8_t { BLOCK = 1, MANAGED_BUFFER = 2, TINY_BUFFER = 3 }; +static constexpr const idx_t FILE_BUFFER_TYPE_COUNT = 3; + //! The FileBuffer represents a buffer that can be read or written to a Direct IO FileHandle. class FileBuffer { public: diff --git a/src/include/duckdb/common/file_opener.hpp b/src/include/duckdb/common/file_opener.hpp index 2c4dbc396a8..6f3e5a8e422 100644 --- a/src/include/duckdb/common/file_opener.hpp +++ b/src/include/duckdb/common/file_opener.hpp @@ -14,6 +14,8 @@ namespace duckdb { +struct CatalogTransaction; +class SecretManager; class ClientContext; class Value; @@ -33,8 +35,10 @@ class FileOpener { virtual optional_ptr TryGetClientContext() = 0; virtual optional_ptr TryGetDatabase() = 0; + DUCKDB_API static unique_ptr TryGetCatalogTransaction(optional_ptr opener); DUCKDB_API static optional_ptr TryGetClientContext(optional_ptr opener); DUCKDB_API static optional_ptr TryGetDatabase(optional_ptr opener); + DUCKDB_API static optional_ptr TryGetSecretManager(optional_ptr opener); DUCKDB_API static SettingLookupResult TryGetCurrentSetting(optional_ptr opener, const string &key, Value &result); DUCKDB_API static SettingLookupResult TryGetCurrentSetting(optional_ptr opener, const string &key, diff --git a/src/include/duckdb/common/file_system.hpp b/src/include/duckdb/common/file_system.hpp index e0df2f70c26..fa2b9381999 100644 --- a/src/include/duckdb/common/file_system.hpp +++ b/src/include/duckdb/common/file_system.hpp @@ -238,6 +238,7 @@ class FileSystem { //! Whether or not a file is remote or local, based only on file path DUCKDB_API static bool IsRemoteFile(const string &path); + DUCKDB_API static bool IsRemoteFile(const string &path, string &extension); DUCKDB_API virtual void SetDisabledFileSystems(const vector &names); diff --git a/src/include/duckdb/common/filename_pattern.hpp b/src/include/duckdb/common/filename_pattern.hpp index 311fa602d99..4ec3827f581 100644 --- a/src/include/duckdb/common/filename_pattern.hpp +++ b/src/include/duckdb/common/filename_pattern.hpp @@ -30,6 +30,10 @@ class FilenamePattern { void Serialize(Serializer &serializer) const; static FilenamePattern Deserialize(Deserializer &deserializer); + bool HasUUID() const { + return uuid; + } + private: string base; idx_t pos; diff --git a/src/include/duckdb/common/fsst.hpp b/src/include/duckdb/common/fsst.hpp index f0cf6faf4d6..bf0f94fef00 100644 --- a/src/include/duckdb/common/fsst.hpp +++ b/src/include/duckdb/common/fsst.hpp @@ -8,7 +8,12 @@ #pragma once +#include "duckdb/common/typedefs.hpp" + namespace duckdb { +class Value; +class Vector; +struct string_t; class FSSTPrimitives { public: diff --git a/src/include/duckdb/common/gzip_file_system.hpp b/src/include/duckdb/common/gzip_file_system.hpp index 9d6f6a21924..5a9f5f12335 100644 --- a/src/include/duckdb/common/gzip_file_system.hpp +++ b/src/include/duckdb/common/gzip_file_system.hpp @@ -25,8 +25,11 @@ class GZipFileSystem : public CompressedFileSystem { //! Verifies that a buffer contains a valid GZIP header static void VerifyGZIPHeader(uint8_t gzip_hdr[], idx_t read_count); + static bool CheckIsZip(const char *length, idx_t size); + //! Consumes a byte stream as a gzip string, returning the decompressed string static string UncompressGZIPString(const string &in); + static string UncompressGZIPString(const char *length, idx_t size); unique_ptr CreateStream() override; idx_t InBufferSize() override; diff --git a/src/include/duckdb/common/hive_partitioning.hpp b/src/include/duckdb/common/hive_partitioning.hpp index 9ba4c82a2ff..3bf59313da2 100644 --- a/src/include/duckdb/common/hive_partitioning.hpp +++ b/src/include/duckdb/common/hive_partitioning.hpp @@ -14,11 +14,14 @@ #include "duckdb/optimizer/statistics_propagator.hpp" #include "duckdb/planner/expression_iterator.hpp" #include "duckdb/planner/table_filter.hpp" -#include "re2/re2.h" #include #include +namespace duckdb_re2 { +class RE2; +} // namespace duckdb_re2 + namespace duckdb { class HivePartitioning { diff --git a/src/include/duckdb/common/insertion_order_preserving_map.hpp b/src/include/duckdb/common/insertion_order_preserving_map.hpp new file mode 100644 index 00000000000..518fffc4924 --- /dev/null +++ b/src/include/duckdb/common/insertion_order_preserving_map.hpp @@ -0,0 +1,129 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/insertion_order_preserving_map.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/unordered_map.hpp" +#include "duckdb/common/unordered_set.hpp" +#include "duckdb/common/string.hpp" +#include "duckdb/common/string_util.hpp" +#include "duckdb/common/helper.hpp" +#include "duckdb/common/case_insensitive_map.hpp" +#include "duckdb/common/pair.hpp" + +namespace duckdb { + +template +class InsertionOrderPreservingMap { +public: + typedef vector> VECTOR_TYPE; // NOLINT: matching name of std + typedef string key_type; // NOLINT: matching name of std + +public: + InsertionOrderPreservingMap() { + } + +private: + VECTOR_TYPE map; + case_insensitive_map_t map_idx; + +public: + vector Keys() const { + vector keys; + keys.resize(this->size()); + for (auto &kv : map_idx) { + keys[kv.second] = kv.first; + } + + return keys; + } + + typename VECTOR_TYPE::iterator begin() { // NOLINT: match stl API + return map.begin(); + } + + typename VECTOR_TYPE::iterator end() { // NOLINT: match stl API + return map.end(); + } + + typename VECTOR_TYPE::const_iterator begin() const { // NOLINT: match stl API + return map.begin(); + } + + typename VECTOR_TYPE::const_iterator end() const { // NOLINT: match stl API + return map.end(); + } + + typename VECTOR_TYPE::iterator find(const string &key) { // NOLINT: match stl API + auto entry = map_idx.find(key); + if (entry == map_idx.end()) { + return map.end(); + } + return map.begin() + static_cast(entry->second); + } + + typename VECTOR_TYPE::const_iterator find(const string &key) const { // NOLINT: match stl API + auto entry = map_idx.find(key); + if (entry == map_idx.end()) { + return map.end(); + } + return map.begin() + static_cast(entry->second); + } + + idx_t size() const { // NOLINT: match stl API + return map_idx.size(); + } + + bool empty() const { // NOLINT: match stl API + return map_idx.empty(); + } + + void resize(idx_t nz) { // NOLINT: match stl API + map.resize(nz); + } + + void insert(const string &key, V &value) { // NOLINT: match stl API + map.push_back(make_pair(key, std::move(value))); + map_idx[key] = map.size() - 1; + } + + void insert(pair &&value) { // NOLINT: match stl API + map.push_back(std::move(value)); + map_idx[value.first] = map.size() - 1; + } + + void erase(typename VECTOR_TYPE::iterator it) { // NOLINT: match stl API + auto key = it->first; + auto idx = map_idx[it->first]; + map.erase(it); + map_idx.erase(key); + for (auto &kv : map_idx) { + if (kv.second > idx) { + kv.second--; + } + } + } + + bool contains(const string &key) const { // NOLINT: match stl API + return map_idx.find(key) != map_idx.end(); + } + + const V &at(const string &key) const { // NOLINT: match stl API + return map[map_idx.at(key)].second; + } + + V &operator[](const string &key) { + if (!contains(key)) { + auto v = V(); + insert(key, v); + } + return map[map_idx[key]].second; + } +}; + +} // namespace duckdb diff --git a/src/include/duckdb/common/multi_file_list.hpp b/src/include/duckdb/common/multi_file_list.hpp new file mode 100644 index 00000000000..2c551d6a66c --- /dev/null +++ b/src/include/duckdb/common/multi_file_list.hpp @@ -0,0 +1,151 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/multi_file_list.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/common.hpp" +#include "duckdb/common/multi_file_reader_options.hpp" + +namespace duckdb { +class MultiFileList; + +enum class FileExpandResult : uint8_t { NO_FILES, SINGLE_FILE, MULTIPLE_FILES }; + +struct MultiFileListScanData { + idx_t current_file_idx = DConstants::INVALID_INDEX; +}; + +class MultiFileListIterationHelper { +public: + DUCKDB_API explicit MultiFileListIterationHelper(MultiFileList &collection); + +private: + MultiFileList &file_list; + +private: + class MultiFileListIterator; + + class MultiFileListIterator { + public: + DUCKDB_API explicit MultiFileListIterator(MultiFileList *file_list); + + optional_ptr file_list; + MultiFileListScanData file_scan_data; + string current_file; + + public: + DUCKDB_API void Next(); + + DUCKDB_API MultiFileListIterator &operator++(); + DUCKDB_API bool operator!=(const MultiFileListIterator &other) const; + DUCKDB_API const string &operator*() const; + }; + +public: + MultiFileListIterator begin(); // NOLINT: match stl API + MultiFileListIterator end(); // NOLINT: match stl API +}; + +//! Abstract class for lazily generated list of file paths/globs +//! NOTE: subclasses are responsible for ensuring thread-safety +class MultiFileList { +public: + explicit MultiFileList(vector paths, FileGlobOptions options); + virtual ~MultiFileList(); + + //! Returns the raw, unexpanded paths, pre-filter + const vector GetPaths() const; + + //! Get Iterator over the files for pretty for loops + MultiFileListIterationHelper Files(); + + //! Initialize a sequential scan over a file list + void InitializeScan(MultiFileListScanData &iterator); + //! Scan the next file into result_file, returns false when out of files + bool Scan(MultiFileListScanData &iterator, string &result_file); + + //! Returns the first file or an empty string if GetTotalFileCount() == 0 + string GetFirstFile(); + //! Syntactic sugar for GetExpandResult() == FileExpandResult::NO_FILES + bool IsEmpty(); + + //! Virtual functions for subclasses +public: + virtual unique_ptr ComplexFilterPushdown(ClientContext &context, + const MultiFileReaderOptions &options, LogicalGet &get, + vector> &filters); + virtual vector GetAllFiles() = 0; + virtual FileExpandResult GetExpandResult() = 0; + virtual idx_t GetTotalFileCount() = 0; + +protected: + //! Get the i-th expanded file + virtual string GetFile(idx_t i) = 0; + +protected: + //! The unexpanded input paths + const vector paths; + //! Whether paths can expand to 0 files + const FileGlobOptions glob_options; +}; + +//! MultiFileList that takes a list of files and produces the same list of paths. Useful for quickly wrapping +//! existing vectors of paths in a MultiFileList without changing any code +class SimpleMultiFileList : public MultiFileList { +public: + //! Construct a SimpleMultiFileList from a list of already expanded files + explicit SimpleMultiFileList(vector paths); + //! Copy `paths` to `filtered_files` and apply the filters + unique_ptr ComplexFilterPushdown(ClientContext &context, const MultiFileReaderOptions &options, + LogicalGet &get, vector> &filters) override; + + //! Main MultiFileList API + vector GetAllFiles() override; + FileExpandResult GetExpandResult() override; + idx_t GetTotalFileCount() override; + +protected: + //! Main MultiFileList API + string GetFile(idx_t i) override; +}; + +//! MultiFileList that takes a list of paths and produces a list of files with all globs expanded +class GlobMultiFileList : public MultiFileList { +public: + GlobMultiFileList(ClientContext &context, vector paths, FileGlobOptions options); + //! Calls ExpandAll, then prunes the expanded_files using the hive/filename filters + unique_ptr ComplexFilterPushdown(ClientContext &context, const MultiFileReaderOptions &options, + LogicalGet &get, vector> &filters) override; + + //! Main MultiFileList API + vector GetAllFiles() override; + FileExpandResult GetExpandResult() override; + idx_t GetTotalFileCount() override; + +protected: + //! Main MultiFileList API + string GetFile(idx_t i) override; + + //! Get the i-th expanded file + string GetFileInternal(idx_t i); + //! Grabs the next path and expands it into Expanded paths: returns false if no more files to expand + bool ExpandPathInternal(); + //! Whether all files have been expanded + bool IsFullyExpanded(); + + //! The ClientContext for globbing + ClientContext &context; + //! The current path to expand + idx_t current_path; + //! The expanded files + vector expanded_files; + + mutex lock; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/common/multi_file_reader.hpp b/src/include/duckdb/common/multi_file_reader.hpp index 150e48994cc..5992904c83e 100644 --- a/src/include/duckdb/common/multi_file_reader.hpp +++ b/src/include/duckdb/common/multi_file_reader.hpp @@ -11,6 +11,7 @@ #include "duckdb/common/common.hpp" #include "duckdb/common/enums/file_glob_options.hpp" #include "duckdb/common/multi_file_reader_options.hpp" +#include "duckdb/common/multi_file_list.hpp" #include "duckdb/common/optional_ptr.hpp" #include "duckdb/common/types/value.hpp" #include "duckdb/common/union_by_name.hpp" @@ -47,6 +48,34 @@ struct MultiFileReaderBindData { DUCKDB_API static MultiFileReaderBindData Deserialize(Deserializer &deserializer); }; +//! Global state for MultiFileReads +struct MultiFileReaderGlobalState { + MultiFileReaderGlobalState(vector extra_columns_p, optional_ptr file_list_p) + : extra_columns(std::move(extra_columns_p)), file_list(file_list_p) {}; + virtual ~MultiFileReaderGlobalState(); + + //! extra columns that will be produced during scanning + const vector extra_columns; + // the file list driving the current scan + const optional_ptr file_list; + + //! Indicates that the MultiFileReader has added columns to be scanned that are not in the projection + bool RequiresExtraColumns() { + return !extra_columns.empty(); + } + + template + TARGET &Cast() { + DynamicCastCheck(this); + return reinterpret_cast(*this); + } + template + const TARGET &Cast() const { + DynamicCastCheck(this); + return reinterpret_cast(*this); + } +}; + struct MultiFileFilterEntry { idx_t index = DConstants::INVALID_INDEX; bool is_constant = false; @@ -55,7 +84,6 @@ struct MultiFileFilterEntry { struct MultiFileConstantEntry { MultiFileConstantEntry(idx_t column_id, Value value_p) : column_id(column_id), value(std::move(value_p)) { } - //! The column id to apply the constant value to idx_t column_id; //! The constant value @@ -80,63 +108,105 @@ struct MultiFileReaderData { //! Map of column_id -> cast, used when reading multiple files when files have diverging types //! for the same column unordered_map cast_map; + //! (Optionally) The MultiFileReader-generated metadata corresponding to the currently read file + optional_idx file_list_idx; }; +//! The MultiFileReader class provides a set of helper methods to handle scanning from multiple files struct MultiFileReader { + virtual ~MultiFileReader(); + + //! Create a MultiFileReader for a specific TableFunction, using its function name for errors + DUCKDB_API static unique_ptr Create(const TableFunction &table_function); + //! Create a default MultiFileReader, function_name is used for errors + DUCKDB_API static unique_ptr CreateDefault(const string &function_name = ""); + //! Add the parameters for multi-file readers (e.g. union_by_name, filename) to a table function DUCKDB_API static void AddParameters(TableFunction &table_function); - //! Performs any globbing for the multi-file reader and returns a list of files to be read - DUCKDB_API static vector GetFileList(ClientContext &context, const Value &input, const string &name, - FileGlobOptions options = FileGlobOptions::DISALLOW_EMPTY); + //! Creates a table function set from a single reader function (including e.g. list parameters, etc) + DUCKDB_API static TableFunctionSet CreateFunctionSet(TableFunction table_function); + + //! Parse a Value containing 1 or more paths into a vector of paths. Note: no expansion is performed here + DUCKDB_API virtual vector ParsePaths(const Value &input); + //! Create a MultiFileList from a vector of paths. Any globs will be expanded using the default filesystem + DUCKDB_API virtual unique_ptr + CreateFileList(ClientContext &context, const vector &paths, + FileGlobOptions options = FileGlobOptions::DISALLOW_EMPTY); + //! Shorthand for ParsePaths + CreateFileList + DUCKDB_API unique_ptr CreateFileList(ClientContext &context, const Value &input, + FileGlobOptions options = FileGlobOptions::DISALLOW_EMPTY); + //! Parse the named parameters of a multi-file reader - DUCKDB_API static bool ParseOption(const string &key, const Value &val, MultiFileReaderOptions &options, - ClientContext &context); - //! Perform complex filter pushdown into the multi-file reader, potentially filtering out files that should be read - //! If "true" the first file has been eliminated - DUCKDB_API static bool ComplexFilterPushdown(ClientContext &context, vector &files, - const MultiFileReaderOptions &options, LogicalGet &get, - vector> &filters); + DUCKDB_API virtual bool ParseOption(const string &key, const Value &val, MultiFileReaderOptions &options, + ClientContext &context); + //! Perform filter pushdown into the MultiFileList. Returns a new MultiFileList if filters were pushed down + DUCKDB_API virtual unique_ptr ComplexFilterPushdown(ClientContext &context, MultiFileList &files, + const MultiFileReaderOptions &options, + LogicalGet &get, + vector> &filters); + //! Try to use the MultiFileReader for binding. Returns true if a bind could be made, returns false if the + //! MultiFileReader can not perform the bind and binding should be performed on 1 or more files in the MultiFileList + //! directly. + DUCKDB_API virtual bool Bind(MultiFileReaderOptions &options, MultiFileList &files, + vector &return_types, vector &names, + MultiFileReaderBindData &bind_data); //! Bind the options of the multi-file reader, potentially emitting any extra columns that are required - DUCKDB_API static MultiFileReaderBindData BindOptions(MultiFileReaderOptions &options, const vector &files, - vector &return_types, vector &names); + DUCKDB_API virtual void BindOptions(MultiFileReaderOptions &options, MultiFileList &files, + vector &return_types, vector &names, + MultiFileReaderBindData &bind_data); + + //! Initialize global state used by the MultiFileReader + DUCKDB_API virtual unique_ptr + InitializeGlobalState(ClientContext &context, const MultiFileReaderOptions &file_options, + const MultiFileReaderBindData &bind_data, const MultiFileList &file_list, + const vector &global_types, const vector &global_names, + const vector &global_column_ids); + //! Finalize the bind phase of the multi-file reader after we know (1) the required (output) columns, and (2) the //! pushed down table filters - DUCKDB_API static void FinalizeBind(const MultiFileReaderOptions &file_options, - const MultiFileReaderBindData &options, const string &filename, - const vector &local_names, const vector &global_types, - const vector &global_names, const vector &global_column_ids, - MultiFileReaderData &reader_data, ClientContext &context); - //! Create all required mappings from the global types/names to the file-local types/names - DUCKDB_API static void CreateMapping(const string &file_name, const vector &local_types, + DUCKDB_API virtual void FinalizeBind(const MultiFileReaderOptions &file_options, + const MultiFileReaderBindData &options, const string &filename, const vector &local_names, const vector &global_types, const vector &global_names, const vector &global_column_ids, - optional_ptr filters, MultiFileReaderData &reader_data, - const string &initial_file); + MultiFileReaderData &reader_data, ClientContext &context, + optional_ptr global_state); + + //! Create all required mappings from the global types/names to the file-local types/names + DUCKDB_API virtual void CreateMapping(const string &file_name, const vector &local_types, + const vector &local_names, const vector &global_types, + const vector &global_names, const vector &global_column_ids, + optional_ptr filters, MultiFileReaderData &reader_data, + const string &initial_file, const MultiFileReaderBindData &options, + optional_ptr global_state); //! Populated the filter_map - DUCKDB_API static void CreateFilterMap(const vector &global_types, - optional_ptr filters, MultiFileReaderData &reader_data); + DUCKDB_API virtual void CreateFilterMap(const vector &global_types, + optional_ptr filters, MultiFileReaderData &reader_data, + optional_ptr global_state); + //! Finalize the reading of a chunk - applying any constants that are required - DUCKDB_API static void FinalizeChunk(const MultiFileReaderBindData &bind_data, - const MultiFileReaderData &reader_data, DataChunk &chunk); - //! Creates a table function set from a single reader function (including e.g. list parameters, etc) - DUCKDB_API static TableFunctionSet CreateFunctionSet(TableFunction table_function); + DUCKDB_API virtual void FinalizeChunk(ClientContext &context, const MultiFileReaderBindData &bind_data, + const MultiFileReaderData &reader_data, DataChunk &chunk, + optional_ptr global_state); template - static MultiFileReaderBindData BindUnionReader(ClientContext &context, vector &return_types, - vector &names, RESULT_CLASS &result, - OPTIONS_CLASS &options) { + MultiFileReaderBindData BindUnionReader(ClientContext &context, vector &return_types, + vector &names, MultiFileList &files, RESULT_CLASS &result, + OPTIONS_CLASS &options) { D_ASSERT(options.file_options.union_by_name); vector union_col_names; vector union_col_types; + // obtain the set of union column names + types by unifying the types of all of the files // note that this requires opening readers for each file and reading the metadata of each file - auto union_readers = - UnionByName::UnionCols(context, result.files, union_col_types, union_col_names, options); + // note also that it requires fully expanding the MultiFileList + auto materialized_file_list = files.GetAllFiles(); + auto union_readers = UnionByName::UnionCols(context, materialized_file_list, union_col_types, + union_col_names, options); std::move(union_readers.begin(), union_readers.end(), std::back_inserter(result.union_readers)); // perform the binding on the obtained set of names + types - auto bind_data = - MultiFileReader::BindOptions(options.file_options, result.files, union_col_types, union_col_names); + MultiFileReaderBindData bind_data; + BindOptions(options.file_options, files, union_col_types, union_col_names, bind_data); names = union_col_names; return_types = union_col_types; result.Initialize(result.union_readers[0]); @@ -145,37 +215,40 @@ struct MultiFileReader { } template - static MultiFileReaderBindData BindReader(ClientContext &context, vector &return_types, - vector &names, RESULT_CLASS &result, OPTIONS_CLASS &options) { + MultiFileReaderBindData BindReader(ClientContext &context, vector &return_types, vector &names, + MultiFileList &files, RESULT_CLASS &result, OPTIONS_CLASS &options) { if (options.file_options.union_by_name) { - return BindUnionReader(context, return_types, names, result, options); + return BindUnionReader(context, return_types, names, files, result, options); } else { shared_ptr reader; - reader = make_shared_ptr(context, result.files[0], options); + reader = make_shared_ptr(context, files.GetFirstFile(), options); return_types = reader->return_types; names = reader->names; result.Initialize(std::move(reader)); - return MultiFileReader::BindOptions(options.file_options, result.files, return_types, names); + MultiFileReaderBindData bind_data; + BindOptions(options.file_options, files, return_types, names, bind_data); + return bind_data; } } template - static void InitializeReader(READER_CLASS &reader, const MultiFileReaderOptions &options, - const MultiFileReaderBindData &bind_data, const vector &global_types, - const vector &global_names, const vector &global_column_ids, - optional_ptr table_filters, const string &initial_file, - ClientContext &context) { + void InitializeReader(READER_CLASS &reader, const MultiFileReaderOptions &options, + const MultiFileReaderBindData &bind_data, const vector &global_types, + const vector &global_names, const vector &global_column_ids, + optional_ptr table_filters, const string &initial_file, + ClientContext &context, optional_ptr global_state) { FinalizeBind(options, bind_data, reader.GetFileName(), reader.GetNames(), global_types, global_names, - global_column_ids, reader.reader_data, context); + global_column_ids, reader.reader_data, context, global_state); CreateMapping(reader.GetFileName(), reader.GetTypes(), reader.GetNames(), global_types, global_names, - global_column_ids, table_filters, reader.reader_data, initial_file); + global_column_ids, table_filters, reader.reader_data, initial_file, bind_data, global_state); reader.reader_data.filters = table_filters; } template - static void PruneReaders(BIND_DATA &data) { + static void PruneReaders(BIND_DATA &data, MultiFileList &file_list) { unordered_set file_set; - for (auto &file : data.files) { + + for (const auto &file : file_list.Files()) { file_set.insert(file); } @@ -202,11 +275,15 @@ struct MultiFileReader { } } -private: - static void CreateNameMapping(const string &file_name, const vector &local_types, - const vector &local_names, const vector &global_types, - const vector &global_names, const vector &global_column_ids, - MultiFileReaderData &reader_data, const string &initial_file); +protected: + virtual void CreateNameMapping(const string &file_name, const vector &local_types, + const vector &local_names, const vector &global_types, + const vector &global_names, const vector &global_column_ids, + MultiFileReaderData &reader_data, const string &initial_file, + optional_ptr global_state); + + //! Used in errors to report which function is using this MultiFileReader + string function_name; }; } // namespace duckdb diff --git a/src/include/duckdb/common/multi_file_reader_options.hpp b/src/include/duckdb/common/multi_file_reader_options.hpp index 5b8bd90668c..aa9322db619 100644 --- a/src/include/duckdb/common/multi_file_reader_options.hpp +++ b/src/include/duckdb/common/multi_file_reader_options.hpp @@ -8,13 +8,14 @@ #pragma once -#include "duckdb/common/types.hpp" #include "duckdb/common/case_insensitive_map.hpp" #include "duckdb/common/hive_partitioning.hpp" +#include "duckdb/common/types.hpp" #include "duckdb/main/client_context.hpp" namespace duckdb { struct BindInfo; +class MultiFileList; struct MultiFileReaderOptions { bool filename = false; @@ -24,12 +25,18 @@ struct MultiFileReaderOptions { bool hive_types_autocast = true; case_insensitive_map_t hive_types_schema; + // Default/configurable name of the column containing the file names + static constexpr const char *DEFAULT_FILENAME_COLUMN = "filename"; + string filename_column = DEFAULT_FILENAME_COLUMN; + // These are used to pass options through custom multifilereaders + case_insensitive_map_t custom_options; + DUCKDB_API void Serialize(Serializer &serializer) const; DUCKDB_API static MultiFileReaderOptions Deserialize(Deserializer &source); DUCKDB_API void AddBatchInfo(BindInfo &bind_info) const; - DUCKDB_API void AutoDetectHivePartitioning(const vector &files, ClientContext &context); - DUCKDB_API static bool AutoDetectHivePartitioningInternal(const vector &files, ClientContext &context); - DUCKDB_API void AutoDetectHiveTypesInternal(const vector &file, ClientContext &context); + DUCKDB_API void AutoDetectHivePartitioning(MultiFileList &files, ClientContext &context); + DUCKDB_API static bool AutoDetectHivePartitioningInternal(MultiFileList &files, ClientContext &context); + DUCKDB_API void AutoDetectHiveTypesInternal(MultiFileList &files, ClientContext &context); DUCKDB_API void VerifyHiveTypesArePartitions(const std::map &partitions) const; DUCKDB_API LogicalType GetHiveLogicalType(const string &hive_partition_column) const; DUCKDB_API Value GetHivePartitionValue(const string &base, const string &entry, ClientContext &context) const; diff --git a/src/include/duckdb/common/operator/add.hpp b/src/include/duckdb/common/operator/add.hpp index ff9c3a060cb..75d79a77411 100644 --- a/src/include/duckdb/common/operator/add.hpp +++ b/src/include/duckdb/common/operator/add.hpp @@ -64,6 +64,8 @@ template <> bool TryAddOperator::Operation(uint32_t left, uint32_t right, uint32_t &result); template <> bool TryAddOperator::Operation(uint64_t left, uint64_t right, uint64_t &result); +template <> +bool TryAddOperator::Operation(date_t left, int32_t right, date_t &result); template <> bool TryAddOperator::Operation(int8_t left, int8_t right, int8_t &result); diff --git a/src/include/duckdb/common/operator/cast_operators.hpp b/src/include/duckdb/common/operator/cast_operators.hpp index 0555c83e829..1055b24f3f7 100644 --- a/src/include/duckdb/common/operator/cast_operators.hpp +++ b/src/include/duckdb/common/operator/cast_operators.hpp @@ -596,7 +596,11 @@ DUCKDB_API bool TryCastErrorMessage::Operation(string_t input, timestamp_t &resu template <> DUCKDB_API bool TryCast::Operation(string_t input, timestamp_t &result, bool strict); template <> +DUCKDB_API bool TryCast::Operation(string_t input, timestamp_ns_t &result, bool strict); +template <> timestamp_t Cast::Operation(string_t input); +template <> +timestamp_ns_t Cast::Operation(string_t input); //===--------------------------------------------------------------------===// // String -> Interval Casts //===--------------------------------------------------------------------===// @@ -628,14 +632,14 @@ struct TryCastToTimestampSec { }; template <> -DUCKDB_API bool TryCastToTimestampNS::Operation(string_t input, timestamp_t &result, bool strict); +DUCKDB_API bool TryCastToTimestampNS::Operation(string_t input, timestamp_ns_t &result, bool strict); template <> DUCKDB_API bool TryCastToTimestampMS::Operation(string_t input, timestamp_t &result, bool strict); template <> DUCKDB_API bool TryCastToTimestampSec::Operation(string_t input, timestamp_t &result, bool strict); template <> -DUCKDB_API bool TryCastToTimestampNS::Operation(date_t input, timestamp_t &result, bool strict); +DUCKDB_API bool TryCastToTimestampNS::Operation(date_t input, timestamp_ns_t &result, bool strict); template <> DUCKDB_API bool TryCastToTimestampMS::Operation(date_t input, timestamp_t &result, bool strict); template <> @@ -799,7 +803,7 @@ template <> duckdb::timestamp_t CastTimestampSecToNs::Operation(duckdb::timestamp_t input); template <> -duckdb::string_t CastFromTimestampNS::Operation(duckdb::timestamp_t input, Vector &result); +duckdb::string_t CastFromTimestampNS::Operation(duckdb::timestamp_ns_t input, Vector &result); template <> duckdb::string_t CastFromTimestampMS::Operation(duckdb::timestamp_t input, Vector &result); template <> diff --git a/src/include/duckdb/common/operator/decimal_cast_operators.hpp b/src/include/duckdb/common/operator/decimal_cast_operators.hpp index f3f70cbbdc1..b6f8c054eb1 100644 --- a/src/include/duckdb/common/operator/decimal_cast_operators.hpp +++ b/src/include/duckdb/common/operator/decimal_cast_operators.hpp @@ -9,6 +9,8 @@ #pragma once #include "duckdb/common/operator/cast_operators.hpp" +#include "duckdb/common/types/decimal.hpp" +#include "duckdb/common/operator/integer_cast_operator.hpp" namespace duckdb { @@ -457,4 +459,257 @@ string_t StringCastFromDecimal::Operation(int64_t input, uint8_t width, uint8_t template <> string_t StringCastFromDecimal::Operation(hugeint_t input, uint8_t width, uint8_t scale, Vector &result); +//===--------------------------------------------------------------------===// +// Cast VARCHAR <-> Decimal +//===--------------------------------------------------------------------===// +enum class ExponentType : uint8_t { NONE, POSITIVE, NEGATIVE }; + +template +struct DecimalCastTraits { + using POWERS_OF_TEN_CLASS = NumericHelper; +}; + +template <> +struct DecimalCastTraits { + using POWERS_OF_TEN_CLASS = Hugeint; +}; + +template <> +struct DecimalCastTraits { + using POWERS_OF_TEN_CLASS = Uhugeint; +}; + +template +struct DecimalCastData { + using StoreType = T; + StoreType result; + uint8_t width; + uint8_t scale; + uint8_t digit_count; + uint8_t decimal_count; + //! Whether we have determined if the result should be rounded + bool round_set; + //! If the result should be rounded + bool should_round; + //! Only set when ALLOW_EXPONENT is enabled + uint8_t excessive_decimals; + ExponentType exponent_type; + StoreType limit; +}; + +struct DecimalCastOperation { + template + static bool HandleDigit(T &state, uint8_t digit) { + if (state.result == 0 && digit == 0) { + // leading zero's don't count towards the digit count + return true; + } + if (state.digit_count == state.width - state.scale) { + // width of decimal type is exceeded! + return false; + } + state.digit_count++; + if (NEGATIVE) { + if (state.result < (NumericLimits::Minimum() / 10)) { + return false; + } + state.result = state.result * 10 - digit; + } else { + if (state.result > (NumericLimits::Maximum() / 10)) { + return false; + } + state.result = state.result * 10 + digit; + } + return true; + } + + template + static bool HandleHexDigit(T &state, uint8_t digit) { + return false; + } + + template + static bool HandleBinaryDigit(T &state, uint8_t digit) { + return false; + } + + template + static void RoundUpResult(T &state) { + if (NEGATIVE) { + state.result -= 1; + } else { + state.result += 1; + } + } + + template + static bool HandleExponent(T &state, int32_t exponent) { + auto decimal_excess = (state.decimal_count > state.scale) ? state.decimal_count - state.scale : 0; + if (exponent > 0) { + state.exponent_type = ExponentType::POSITIVE; + // Positive exponents need up to 'exponent' amount of digits + // Everything beyond that amount needs to be truncated + if (decimal_excess > exponent) { + // We've allowed too many decimals + state.excessive_decimals = UnsafeNumericCast(decimal_excess - exponent); + exponent = 0; + } else { + exponent -= decimal_excess; + } + D_ASSERT(exponent >= 0); + } else if (exponent < 0) { + state.exponent_type = ExponentType::NEGATIVE; + } + if (!Finalize(state)) { + return false; + } + if (exponent < 0) { + bool round_up = false; + for (idx_t i = 0; i < idx_t(-int64_t(exponent)); i++) { + auto mod = state.result % 10; + round_up = NEGATIVE ? mod <= -5 : mod >= 5; + state.result /= 10; + if (state.result == 0) { + break; + } + } + if (round_up) { + RoundUpResult(state); + } + return true; + } else { + // positive exponent: append 0's + for (idx_t i = 0; i < idx_t(exponent); i++) { + if (!HandleDigit(state, 0)) { + return false; + } + } + return true; + } + } + + template + static bool HandleDecimal(T &state, uint8_t digit) { + if (state.decimal_count == state.scale && !state.round_set) { + // Determine whether the last registered decimal should be rounded or not + state.round_set = true; + state.should_round = digit >= 5; + } + if (!ALLOW_EXPONENT && state.decimal_count == state.scale) { + // we exceeded the amount of supported decimals + // however, we don't throw an error here + // we just truncate the decimal + return true; + } + //! If we expect an exponent, we need to preserve the decimals + //! But we don't want to overflow, so we prevent overflowing the result with this check + if (state.digit_count + state.decimal_count >= DecimalWidth::max) { + return true; + } + state.decimal_count++; + if (NEGATIVE) { + state.result = state.result * 10 - digit; + } else { + state.result = state.result * 10 + digit; + } + return true; + } + + template + static bool TruncateExcessiveDecimals(T &state) { + D_ASSERT(state.excessive_decimals); + bool round_up = false; + for (idx_t i = 0; i < state.excessive_decimals; i++) { + auto mod = state.result % 10; + round_up = NEGATIVE ? mod <= -5 : mod >= 5; + state.result /= static_cast(10.0); + } + //! Only round up when exponents are involved + if (state.exponent_type == ExponentType::POSITIVE && round_up) { + RoundUpResult(state); + } + D_ASSERT(state.decimal_count > state.scale); + state.decimal_count = state.scale; + return true; + } + + template + static bool Finalize(T &state) { + if (state.exponent_type != ExponentType::POSITIVE && state.decimal_count > state.scale) { + //! Did not encounter an exponent, but ALLOW_EXPONENT was on + state.excessive_decimals = state.decimal_count - state.scale; + } + if (state.excessive_decimals && !TruncateExcessiveDecimals(state)) { + return false; + } + if (state.exponent_type == ExponentType::NONE && state.round_set && state.should_round) { + RoundUpResult(state); + } + // if we have not gotten exactly "scale" decimals, we need to multiply the result + // e.g. if we have a string "1.0" that is cast to a DECIMAL(9,3), the value needs to be 1000 + // but we have only gotten the value "10" so far, so we multiply by 1000 + for (uint8_t i = state.decimal_count; i < state.scale; i++) { + state.result *= 10; + } + if (NEGATIVE) { + return state.result > -state.limit; + } else { + return state.result < state.limit; + } + } +}; + +template +bool TryDecimalStringCast(string_t input, T &result, CastParameters ¶meters, uint8_t width, uint8_t scale) { + return TryDecimalStringCast(input.GetData(), input.GetSize(), result, parameters, width, + scale); +} + +template +bool TryDecimalStringCast(const char *string_ptr, idx_t string_size, T &result, CastParameters ¶meters, + uint8_t width, uint8_t scale) { + DecimalCastData state; + state.result = 0; + state.width = width; + state.scale = scale; + state.digit_count = 0; + state.decimal_count = 0; + state.excessive_decimals = 0; + state.exponent_type = ExponentType::NONE; + state.round_set = false; + state.should_round = false; + state.limit = UnsafeNumericCast(DecimalCastTraits::POWERS_OF_TEN_CLASS::POWERS_OF_TEN[width]); + if (!TryIntegerCast, true, true, DecimalCastOperation, false, decimal_separator>( + string_ptr, string_size, state, false)) { + string_t value(string_ptr, (uint32_t)string_size); + string error = StringUtil::Format("Could not convert string \"%s\" to DECIMAL(%d,%d)", value.GetString(), + (int)width, (int)scale); + HandleCastError::AssignError(error, parameters); + return false; + } + result = state.result; + return true; +} + +template +bool TryDecimalStringCast(const char *string_ptr, idx_t string_size, T &result, uint8_t width, uint8_t scale) { + DecimalCastData state; + state.result = 0; + state.width = width; + state.scale = scale; + state.digit_count = 0; + state.decimal_count = 0; + state.excessive_decimals = 0; + state.exponent_type = ExponentType::NONE; + state.round_set = false; + state.should_round = false; + state.limit = UnsafeNumericCast(DecimalCastTraits::POWERS_OF_TEN_CLASS::POWERS_OF_TEN[width]); + if (!TryIntegerCast, true, true, DecimalCastOperation, false, decimal_separator>( + string_ptr, string_size, state, false)) { + return false; + } + result = state.result; + return true; +} + } // namespace duckdb diff --git a/src/include/duckdb/common/operator/numeric_cast.hpp b/src/include/duckdb/common/operator/numeric_cast.hpp index f48839c4175..939b570ecd1 100644 --- a/src/include/duckdb/common/operator/numeric_cast.hpp +++ b/src/include/duckdb/common/operator/numeric_cast.hpp @@ -19,6 +19,10 @@ namespace duckdb { +//! Note: this should not be included directly, when these methods are required +//! They should be used through the TryCast:: methods defined in 'cast_operators.hpp' +//! This file produces 'unused static method' warnings/errors when included + template static bool TryCastWithOverflowCheck(SRC value, DST &result) { if (!Value::IsFinite(value)) { diff --git a/src/include/duckdb/common/operator/string_cast.hpp b/src/include/duckdb/common/operator/string_cast.hpp index c436b0c6f17..fac7a262a97 100644 --- a/src/include/duckdb/common/operator/string_cast.hpp +++ b/src/include/duckdb/common/operator/string_cast.hpp @@ -61,6 +61,8 @@ template <> DUCKDB_API duckdb::string_t StringCast::Operation(dtime_t input, Vector &result); template <> DUCKDB_API duckdb::string_t StringCast::Operation(timestamp_t input, Vector &result); +template <> +DUCKDB_API duckdb::string_t StringCast::Operation(timestamp_ns_t input, Vector &result); //! Temporary casting for Time Zone types. TODO: turn casting into functions. struct StringCastTZ { diff --git a/src/include/duckdb/common/optional_ptr.hpp b/src/include/duckdb/common/optional_ptr.hpp index 8e357e77438..206a5fe690f 100644 --- a/src/include/duckdb/common/optional_ptr.hpp +++ b/src/include/duckdb/common/optional_ptr.hpp @@ -9,6 +9,7 @@ #pragma once #include "duckdb/common/exception.hpp" +#include "duckdb/common/shared_ptr.hpp" #include "duckdb/common/unique_ptr.hpp" namespace duckdb { @@ -20,8 +21,12 @@ class optional_ptr { // NOLINT: mimic std casing } optional_ptr(T *ptr_p) : ptr(ptr_p) { // NOLINT: allow implicit creation from pointer } + optional_ptr(T &ref) : ptr(&ref) { // NOLINT: allow implicit creation from reference + } optional_ptr(const unique_ptr &ptr_p) : ptr(ptr_p.get()) { // NOLINT: allow implicit creation from unique pointer } + optional_ptr(const shared_ptr &ptr_p) : ptr(ptr_p.get()) { // NOLINT: allow implicit creation from shared pointer + } void CheckValid() const { if (!ptr) { diff --git a/src/include/duckdb/common/optionally_owned_ptr.hpp b/src/include/duckdb/common/optionally_owned_ptr.hpp new file mode 100644 index 00000000000..b7d9e7270f3 --- /dev/null +++ b/src/include/duckdb/common/optionally_owned_ptr.hpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/optionally_owned_ptr.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/exception.hpp" +#include "duckdb/common/unique_ptr.hpp" + +namespace duckdb { + +template +class optionally_owned_ptr { // NOLINT: mimic std casing +public: + optionally_owned_ptr() { + } + optionally_owned_ptr(T *ptr_p) : ptr(ptr_p) { // NOLINT: allow implicit creation from pointer + } + optionally_owned_ptr(T &ref) : ptr(&ref) { // NOLINT: allow implicit creation from reference + } + optionally_owned_ptr(unique_ptr &&owned_p) // NOLINT: allow implicit creation from moved unique_ptr + : owned(std::move(owned_p)), ptr(owned) { + } + // Move constructor + optionally_owned_ptr(optionally_owned_ptr &&other) noexcept : owned(std::move(other.owned)), ptr(other.ptr) { + other.ptr = nullptr; + } + // Copy constructor + optionally_owned_ptr(const optionally_owned_ptr &other) = delete; + + operator bool() const { // NOLINT: allow implicit conversion to bool + return ptr; + } + T &operator*() { + return *ptr; + } + const T &operator*() const { + return *ptr; + } + T *operator->() { + return ptr.get(); + } + const T *operator->() const { + return ptr.get(); + } + T *get() { // NOLINT: mimic std casing + return ptr.get(); + } + const T *get() const { // NOLINT: mimic std casing + return ptr.get(); + } + bool is_owned() const { // NOLINT: mimic std casing + return owned != nullptr; + } + // this looks dirty - but this is the default behavior of raw pointers + T *get_mutable() const { // NOLINT: mimic std casing + return ptr.get(); + } + + optionally_owned_ptr &operator=(T &ref) { + owned = nullptr; + ptr = optional_ptr(ref); + return *this; + } + optionally_owned_ptr &operator=(T *ref) { + owned = nullptr; + ptr = optional_ptr(ref); + return *this; + } + + bool operator==(const optionally_owned_ptr &rhs) const { + if (owned != rhs.owned) { + return false; + } + return ptr == rhs.ptr; + } + + bool operator!=(const optionally_owned_ptr &rhs) const { + return !(*this == rhs); + } + +private: + unique_ptr owned; + optional_ptr ptr; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/common/owning_string_map.hpp b/src/include/duckdb/common/owning_string_map.hpp new file mode 100644 index 00000000000..4f1823bf8aa --- /dev/null +++ b/src/include/duckdb/common/owning_string_map.hpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/owning_string_map.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/common.hpp" +#include "duckdb/common/string_map_set.hpp" +#include "duckdb/common/allocator.hpp" +#include "duckdb/common/pair.hpp" +#include "duckdb/storage/arena_allocator.hpp" +#include + +namespace duckdb { + +//! The owning string map is equivalent to string_map_t, except that it manages ownership of all data using the +//! provided allocator +template > +class OwningStringMap { +public: + using size_type = typename STRING_MAP_TYPE::size_type; + using key_type = typename STRING_MAP_TYPE::key_type; + using mapped_type = typename STRING_MAP_TYPE::mapped_type; + using value_type = typename STRING_MAP_TYPE::value_type; + using iterator = typename STRING_MAP_TYPE::iterator; + using const_iterator = typename STRING_MAP_TYPE::const_iterator; + +public: + explicit OwningStringMap(Allocator &allocator) : allocator(allocator), free_type(AllocatorFreeType::REQUIRES_FREE) { + } + explicit OwningStringMap(ArenaAllocator &allocator) + : allocator(allocator.GetAllocator()), free_type(AllocatorFreeType::DOES_NOT_REQUIRE_FREE) { + } + ~OwningStringMap() { + Destroy(); + } + + pair insert(value_type entry) { // NOLINT: match std style + if (entry.first.IsInlined()) { + return map.insert(std::move(entry)); + } else { + return map.insert(make_pair(CopyString(entry.first), std::move(entry.second))); + } + } + size_type erase(const key_type &k) { // NOLINT: match std style + auto entry = map.find(k); + if (entry == map.end()) { + return 0; + } + string_t erase_string = entry->first; + map.erase(entry); + DestroyString(erase_string); + return 1; + } + + void clear() { // NOLINT: match std style + Destroy(); + } + + size_type size() const noexcept { // NOLINT: match std style + return map.size(); + } + + bool empty() const noexcept { // NOLINT: match std style + return map.empty(); + } + iterator begin() noexcept { // NOLINT: match std style + return map.begin(); + } + const_iterator begin() const noexcept { // NOLINT: match std style + return map.begin(); + } + iterator end() noexcept { // NOLINT: match std style + return map.end(); + } + const_iterator end() const noexcept { // NOLINT: match std style + return map.end(); + } + iterator find(const key_type &k) { // NOLINT: match std style + return map.find(k); + } + const_iterator find(const key_type &k) const { // NOLINT: match std style + return map.find(k); + } + + mapped_type &operator[](const key_type &k) { + return GetOrCreate(k); + } + mapped_type &operator[](key_type &&k) { + return GetOrCreate(std::move(k)); + } + +private: + inline string_t GetInsertionString(string_t input_str) { + if (input_str.IsInlined()) { + // inlined strings can be inserted directly + return input_str; + } else { + return CopyString(input_str); + } + } + + inline string_t CopyString(string_t input_str) { + D_ASSERT(!input_str.IsInlined()); + // if the string is not inlined we need to allocate space for it + auto input_str_size = UnsafeNumericCast(input_str.GetSize()); + auto string_memory = allocator.AllocateData(input_str_size); + // copy over the string + memcpy(string_memory, input_str.GetData(), input_str_size); + // now return the final string_t + return string_t(char_ptr_cast(string_memory), input_str_size); + } + + mapped_type &GetOrCreate(key_type k) { + auto entry = map.find(k); + if (entry != map.end()) { + return entry->second; + } + auto result = insert(make_pair(k, mapped_type())); + return result.first->second; + } + + void DestroyString(const string_t &str) const { + if (free_type != AllocatorFreeType::REQUIRES_FREE) { + return; + } + if (str.IsInlined()) { + return; + } + allocator.FreeData(data_ptr_cast(str.GetDataWriteable()), str.GetSize()); + } + + void Destroy() { + if (free_type == AllocatorFreeType::REQUIRES_FREE) { + for (auto &str : map) { + DestroyString(str.first); + } + } + map.clear(); + } + +private: + Allocator &allocator; + STRING_MAP_TYPE map; + AllocatorFreeType free_type; +}; + +template +using OrderedOwningStringMap = OwningStringMap>; + +} // namespace duckdb diff --git a/src/include/duckdb/common/radix.hpp b/src/include/duckdb/common/radix.hpp index 4b7c89a3374..dc22256c5e1 100644 --- a/src/include/duckdb/common/radix.hpp +++ b/src/include/duckdb/common/radix.hpp @@ -14,6 +14,7 @@ #include "duckdb/common/types.hpp" #include "duckdb/common/types/string_type.hpp" #include "duckdb/common/types/value.hpp" +#include "duckdb/common/limits.hpp" #include #include // strlen() on Solaris @@ -37,6 +38,11 @@ struct Radix { throw NotImplementedException("Cannot create data from this type"); } + template + static inline T DecodeData(const_data_ptr_t input) { + throw NotImplementedException("Cannot read data from this type"); + } + static inline void EncodeStringDataPrefix(data_ptr_t dataptr, string_t value, idx_t prefix_len) { auto len = value.GetSize(); memcpy(dataptr, value.GetData(), MinValue(len, prefix_len)); @@ -51,13 +57,13 @@ struct Radix { static inline uint32_t EncodeFloat(float x) { uint32_t buff; - //! zero if (x == 0) { buff = 0; buff |= (1u << 31); return buff; } + // nan if (Value::IsNan(x)) { return UINT_MAX; @@ -71,8 +77,8 @@ struct Radix { return 0; } buff = Load(const_data_ptr_cast(&x)); - if ((buff & (1u << 31)) == 0) { //! +0 and positive numbers - buff |= (1u << 31); + if ((buff & (1U << 31)) == 0) { //! +0 and positive numbers + buff |= (1U << 31); } else { //! negative numbers buff = ~buff; //! complement 1 } @@ -80,12 +86,35 @@ struct Radix { return buff; } + static inline float DecodeFloat(uint32_t input) { + // nan + if (input == UINT_MAX) { + return std::numeric_limits::quiet_NaN(); + } + if (input == UINT_MAX - 1) { + return std::numeric_limits::infinity(); + } + if (input == 0) { + return -std::numeric_limits::infinity(); + } + float result; + if (input & (1U << 31)) { + // positive numbers - flip sign bit + input = input ^ (1U << 31); + } else { + // negative numbers - invert + input = ~input; + } + Store(input, data_ptr_cast(&result)); + return result; + } + static inline uint64_t EncodeDouble(double x) { uint64_t buff; //! zero if (x == 0) { buff = 0; - buff += (1ull << 63); + buff += (1ULL << 63); return buff; } // nan @@ -101,13 +130,41 @@ struct Radix { return 0; } buff = Load(const_data_ptr_cast(&x)); - if (buff < (1ull << 63)) { //! +0 and positive numbers - buff += (1ull << 63); + if (buff < (1ULL << 63)) { //! +0 and positive numbers + buff += (1ULL << 63); } else { //! negative numbers buff = ~buff; //! complement 1 } return buff; } + static inline double DecodeDouble(uint64_t input) { + // nan + if (input == ULLONG_MAX) { + return std::numeric_limits::quiet_NaN(); + } + if (input == ULLONG_MAX - 1) { + return std::numeric_limits::infinity(); + } + if (input == 0) { + return -std::numeric_limits::infinity(); + } + double result; + if (input & (1ULL << 63)) { + // positive numbers - flip sign bit + input = input ^ (1ULL << 63); + } else { + // negative numbers - invert + input = ~input; + } + Store(input, data_ptr_cast(&result)); + return result; + } + +private: + template + static void EncodeSigned(data_ptr_t dataptr, T value); + template + static T DecodeSigned(const_data_ptr_t input); }; template <> @@ -115,36 +172,33 @@ inline void Radix::EncodeData(data_ptr_t dataptr, bool value) { Store(value ? 1 : 0, dataptr); } +template +void Radix::EncodeSigned(data_ptr_t dataptr, T value) { + using UNSIGNED = typename MakeUnsigned::type; + UNSIGNED bytes; + Store(value, data_ptr_cast(&bytes)); + Store(BSwap(bytes), dataptr); + dataptr[0] = FlipSign(dataptr[0]); +} + template <> inline void Radix::EncodeData(data_ptr_t dataptr, int8_t value) { - uint8_t bytes; // dance around signedness conversion check - Store(value, data_ptr_cast(&bytes)); - Store(bytes, dataptr); - dataptr[0] = FlipSign(dataptr[0]); + EncodeSigned(dataptr, value); } template <> inline void Radix::EncodeData(data_ptr_t dataptr, int16_t value) { - uint16_t bytes; - Store(value, data_ptr_cast(&bytes)); - Store(BSwap(bytes), dataptr); - dataptr[0] = FlipSign(dataptr[0]); + EncodeSigned(dataptr, value); } template <> inline void Radix::EncodeData(data_ptr_t dataptr, int32_t value) { - uint32_t bytes; - Store(value, data_ptr_cast(&bytes)); - Store(BSwap(bytes), dataptr); - dataptr[0] = FlipSign(dataptr[0]); + EncodeSigned(dataptr, value); } template <> inline void Radix::EncodeData(data_ptr_t dataptr, int64_t value) { - uint64_t bytes; - Store(value, data_ptr_cast(&bytes)); - Store(BSwap(bytes), dataptr); - dataptr[0] = FlipSign(dataptr[0]); + EncodeSigned(dataptr, value); } template <> @@ -154,17 +208,17 @@ inline void Radix::EncodeData(data_ptr_t dataptr, uint8_t value) { template <> inline void Radix::EncodeData(data_ptr_t dataptr, uint16_t value) { - Store(BSwap(value), dataptr); + Store(BSwap(value), dataptr); } template <> inline void Radix::EncodeData(data_ptr_t dataptr, uint32_t value) { - Store(BSwap(value), dataptr); + Store(BSwap(value), dataptr); } template <> inline void Radix::EncodeData(data_ptr_t dataptr, uint64_t value) { - Store(BSwap(value), dataptr); + Store(BSwap(value), dataptr); } template <> @@ -182,13 +236,13 @@ inline void Radix::EncodeData(data_ptr_t dataptr, uhugeint_t value) { template <> inline void Radix::EncodeData(data_ptr_t dataptr, float value) { uint32_t converted_value = EncodeFloat(value); - Store(BSwap(converted_value), dataptr); + Store(BSwap(converted_value), dataptr); } template <> inline void Radix::EncodeData(data_ptr_t dataptr, double value) { uint64_t converted_value = EncodeDouble(value); - Store(BSwap(converted_value), dataptr); + Store(BSwap(converted_value), dataptr); } template <> @@ -200,4 +254,95 @@ inline void Radix::EncodeData(data_ptr_t dataptr, interval_t value) { EncodeData(dataptr, value.micros); } +template <> +inline bool Radix::DecodeData(const_data_ptr_t input) { + return Load(input) != 0; +} + +template +T Radix::DecodeSigned(const_data_ptr_t input) { + using UNSIGNED = typename MakeUnsigned::type; + UNSIGNED bytes = Load(input); + auto bytes_data = data_ptr_cast(&bytes); + bytes_data[0] = FlipSign(bytes_data[0]); + T result; + Store(BSwap(bytes), data_ptr_cast(&result)); + return result; +} + +template <> +inline int8_t Radix::DecodeData(const_data_ptr_t input) { + return DecodeSigned(input); +} + +template <> +inline int16_t Radix::DecodeData(const_data_ptr_t input) { + return DecodeSigned(input); +} + +template <> +inline int32_t Radix::DecodeData(const_data_ptr_t input) { + return DecodeSigned(input); +} + +template <> +inline int64_t Radix::DecodeData(const_data_ptr_t input) { + return DecodeSigned(input); +} + +template <> +inline uint8_t Radix::DecodeData(const_data_ptr_t input) { + return Load(input); +} + +template <> +inline uint16_t Radix::DecodeData(const_data_ptr_t input) { + return BSwap(Load(input)); +} + +template <> +inline uint32_t Radix::DecodeData(const_data_ptr_t input) { + return BSwap(Load(input)); +} + +template <> +inline uint64_t Radix::DecodeData(const_data_ptr_t input) { + return BSwap(Load(input)); +} + +template <> +inline hugeint_t Radix::DecodeData(const_data_ptr_t input) { + hugeint_t result; + result.upper = DecodeData(input); + result.lower = DecodeData(input + sizeof(int64_t)); + return result; +} + +template <> +inline uhugeint_t Radix::DecodeData(const_data_ptr_t input) { + uhugeint_t result; + result.upper = DecodeData(input); + result.lower = DecodeData(input + sizeof(uint64_t)); + return result; +} + +template <> +inline float Radix::DecodeData(const_data_ptr_t input) { + return DecodeFloat(BSwap(Load(input))); +} + +template <> +inline double Radix::DecodeData(const_data_ptr_t input) { + return DecodeDouble(BSwap(Load(input))); +} + +template <> +inline interval_t Radix::DecodeData(const_data_ptr_t input) { + interval_t result; + result.months = DecodeData(input); + result.days = DecodeData(input + sizeof(int32_t)); + result.micros = DecodeData(input + sizeof(int32_t) + sizeof(int32_t)); + return result; +} + } // namespace duckdb diff --git a/src/include/duckdb/common/row_operations/row_matcher.hpp b/src/include/duckdb/common/row_operations/row_matcher.hpp index 006e2f6dcb2..2b419b2f7af 100644 --- a/src/include/duckdb/common/row_operations/row_matcher.hpp +++ b/src/include/duckdb/common/row_operations/row_matcher.hpp @@ -36,6 +36,12 @@ struct RowMatcher { //! Initializes the RowMatcher, filling match_functions using layout and predicates void Initialize(const bool no_match_sel, const TupleDataLayout &layout, const Predicates &predicates); + + //! Initializes the RowMatcher, filling match_functions using layout and equality_predicates but only for the given + //! columns + void Initialize(const bool no_match_sel, const TupleDataLayout &layout, const Predicates &predicates, + vector &columns); + //! Given a DataChunk on the LHS, on which we've called TupleDataCollection::ToUnifiedFormat, //! we match it with rows on the RHS, according to the given layout and locations. //! Initially, 'sel' has 'count' entries which point to what needs to be compared. @@ -44,6 +50,12 @@ struct RowMatcher { const TupleDataLayout &rhs_layout, Vector &rhs_row_locations, SelectionVector *no_match_sel, idx_t &no_match_count); + //! Same as Match above, but only compares the column indexes in columns. Needs to be initialized with the same + //! columns. + idx_t Match(DataChunk &lhs, const vector &lhs_formats, SelectionVector &sel, idx_t count, + const TupleDataLayout &rhs_layout, Vector &rhs_row_locations, SelectionVector *no_match_sel, + idx_t &no_match_count, const vector &columns); + private: //! Gets the templated match function for a given column MatchFunction GetMatchFunction(const bool no_match_sel, const LogicalType &type, const ExpressionType predicate); diff --git a/src/include/duckdb/common/row_operations/row_operations.hpp b/src/include/duckdb/common/row_operations/row_operations.hpp index 9347a9f6e83..2973c6b698b 100644 --- a/src/include/duckdb/common/row_operations/row_operations.hpp +++ b/src/include/duckdb/common/row_operations/row_operations.hpp @@ -31,12 +31,14 @@ class NestedValidity { data_ptr_t *struct_validity_locations; idx_t entry_idx; idx_t idx_in_entry; + idx_t list_validity_offset; public: explicit NestedValidity(data_ptr_t validitymask_location); NestedValidity(data_ptr_t *validitymask_locations, idx_t child_vector_index); void SetInvalid(idx_t idx); bool IsValid(idx_t idx); + void OffsetListBy(idx_t offset); }; struct RowOperationsState { diff --git a/src/include/duckdb/common/serializer/binary_deserializer.hpp b/src/include/duckdb/common/serializer/binary_deserializer.hpp index 18f8a1573a5..b291628a2b6 100644 --- a/src/include/duckdb/common/serializer/binary_deserializer.hpp +++ b/src/include/duckdb/common/serializer/binary_deserializer.hpp @@ -89,6 +89,7 @@ class BinaryDeserializer : public Deserializer { } void ReadData(data_ptr_t buffer, idx_t read_size) { + D_ASSERT(!has_buffered_field); stream.ReadData(buffer, read_size); } @@ -102,7 +103,7 @@ class BinaryDeserializer : public Deserializer { template T VarIntDecode() { // FIXME: maybe we should pass a source to EncodingUtil instead - uint8_t buffer[16]; + uint8_t buffer[16] = {}; idx_t varint_size; for (varint_size = 0; varint_size < 16; varint_size++) { ReadData(buffer + varint_size, 1); diff --git a/src/include/duckdb/common/serializer/binary_serializer.hpp b/src/include/duckdb/common/serializer/binary_serializer.hpp index 0cf532b36a1..d24000ad17e 100644 --- a/src/include/duckdb/common/serializer/binary_serializer.hpp +++ b/src/include/duckdb/common/serializer/binary_serializer.hpp @@ -17,9 +17,11 @@ namespace duckdb { class BinarySerializer : public Serializer { public: - explicit BinarySerializer(WriteStream &stream, bool serialize_default_values_p = false) : stream(stream) { - serialize_default_values = serialize_default_values_p; - serialize_enum_as_string = false; + explicit BinarySerializer(WriteStream &stream, SerializationOptions options_p = SerializationOptions()) + : stream(stream) { + options = std::move(options_p); + // Override the value set by the passed in SerializationOptions + options.serialize_enum_as_string = false; } private: @@ -44,7 +46,7 @@ class BinarySerializer : public Serializer { template void VarIntEncode(T value) { - uint8_t buffer[16]; + uint8_t buffer[16] = {}; auto write_size = EncodingUtil::EncodeLEB128(buffer, value); D_ASSERT(write_size <= sizeof(buffer)); WriteData(buffer, write_size); @@ -52,8 +54,8 @@ class BinarySerializer : public Serializer { public: template - static void Serialize(const T &value, WriteStream &stream, bool serialize_default_values = false) { - BinarySerializer serializer(stream, serialize_default_values); + static void Serialize(const T &value, WriteStream &stream, SerializationOptions options = SerializationOptions()) { + BinarySerializer serializer(stream, std::move(options)); serializer.OnObjectBegin(); value.Serialize(serializer); serializer.OnObjectEnd(); diff --git a/src/include/duckdb/common/serializer/buffered_file_writer.hpp b/src/include/duckdb/common/serializer/buffered_file_writer.hpp index 26f0460c437..b360c3ea1b8 100644 --- a/src/include/duckdb/common/serializer/buffered_file_writer.hpp +++ b/src/include/duckdb/common/serializer/buffered_file_writer.hpp @@ -32,14 +32,16 @@ class BufferedFileWriter : public WriteStream { public: DUCKDB_API void WriteData(const_data_ptr_t buffer, idx_t write_size) override; - //! Flush the buffer to disk and sync the file to ensure writing is completed + //! Flush all changes to the file and then close the file + DUCKDB_API void Close(); + //! Flush all changes and fsync the file to disk DUCKDB_API void Sync(); //! Flush the buffer to the file (without sync) DUCKDB_API void Flush(); //! Returns the current size of the file - DUCKDB_API int64_t GetFileSize(); + DUCKDB_API idx_t GetFileSize(); //! Truncate the size to a previous size (given that size <= GetFileSize()) - DUCKDB_API void Truncate(int64_t size); + DUCKDB_API void Truncate(idx_t size); DUCKDB_API idx_t GetTotalWritten(); }; diff --git a/src/include/duckdb/common/serializer/deserialization_data.hpp b/src/include/duckdb/common/serializer/deserialization_data.hpp index d092229b09e..e1fed62ef81 100644 --- a/src/include/duckdb/common/serializer/deserialization_data.hpp +++ b/src/include/duckdb/common/serializer/deserialization_data.hpp @@ -16,6 +16,7 @@ namespace duckdb { class ClientContext; class Catalog; class DatabaseInstance; +class CompressionInfo; enum class ExpressionType : uint8_t; struct DeserializationData { @@ -24,6 +25,7 @@ struct DeserializationData { stack enums; stack> parameter_data; stack> types; + stack> compression_infos; template void Set(T entry) = delete; @@ -189,4 +191,21 @@ inline void DeserializationData::Unset() { types.pop(); } +template <> +inline void DeserializationData::Set(const CompressionInfo &compression_info) { + compression_infos.emplace(compression_info); +} + +template <> +inline const CompressionInfo &DeserializationData::Get() { + AssertNotEmpty(compression_infos); + return compression_infos.top(); +} + +template <> +inline void DeserializationData::Unset() { + AssertNotEmpty(compression_infos); + compression_infos.pop(); +} + } // namespace duckdb diff --git a/src/include/duckdb/common/serializer/deserializer.hpp b/src/include/duckdb/common/serializer/deserializer.hpp index e4096878a81..d8f95c5a9de 100644 --- a/src/include/duckdb/common/serializer/deserializer.hpp +++ b/src/include/duckdb/common/serializer/deserializer.hpp @@ -196,6 +196,12 @@ class Deserializer { return val; } + // Deserialize a optionally_owned_ptr + template ::ELEMENT_TYPE> + inline typename std::enable_if::value, T>::type Read() { + return optionally_owned_ptr(Read>()); + } + // Deserialize unique_ptr if the element type has a Deserialize method template ::ELEMENT_TYPE> inline typename std::enable_if::value && has_deserialize::value, T>::type Read() { @@ -302,6 +308,23 @@ class Deserializer { return map; } + template + inline typename std::enable_if::value, T>::type Read() { + using VALUE_TYPE = typename is_insertion_preserving_map::VALUE_TYPE; + + T map; + auto size = OnListBegin(); + for (idx_t i = 0; i < size; i++) { + OnObjectBegin(); + auto key = ReadProperty(0, "key"); + auto value = ReadProperty(1, "value"); + OnObjectEnd(); + map[key] = std::move(value); + } + OnListEnd(); + return map; + } + // Deserialize an unordered set template inline typename std::enable_if::value, T>::type Read() { @@ -340,6 +363,19 @@ class Deserializer { return std::make_pair(first, second); } + // Deserialize a priority_queue + template + inline typename std::enable_if::value, T>::type Read() { + using ELEMENT_TYPE = typename is_queue::ELEMENT_TYPE; + T queue; + auto size = OnListBegin(); + for (idx_t i = 0; i < size; i++) { + queue.emplace(Read()); + } + OnListEnd(); + return queue; + } + // Primitive types // Deserialize a bool template diff --git a/src/include/duckdb/common/serializer/memory_stream.hpp b/src/include/duckdb/common/serializer/memory_stream.hpp index 16ee46f2331..f8f539c4474 100644 --- a/src/include/duckdb/common/serializer/memory_stream.hpp +++ b/src/include/duckdb/common/serializer/memory_stream.hpp @@ -22,9 +22,11 @@ class MemoryStream : public WriteStream, public ReadStream { data_ptr_t data; public: + static constexpr idx_t DEFAULT_INITIAL_CAPACITY = 512; + // Create a new owning MemoryStream with an internal backing buffer with the specified capacity. The stream will // own the backing buffer, resize it when needed and free its memory when the stream is destroyed - explicit MemoryStream(idx_t capacity = 512); + explicit MemoryStream(idx_t capacity = DEFAULT_INITIAL_CAPACITY); // Create a new non-owning MemoryStream over the specified external buffer and capacity. The stream will not take // ownership of the backing buffer, will not attempt to resize it and will not free the memory when the stream diff --git a/src/include/duckdb/common/serializer/serialization_traits.hpp b/src/include/duckdb/common/serializer/serialization_traits.hpp index 5230a75e4f2..a1c91b8e623 100644 --- a/src/include/duckdb/common/serializer/serialization_traits.hpp +++ b/src/include/duckdb/common/serializer/serialization_traits.hpp @@ -10,8 +10,11 @@ #include "duckdb/common/set.hpp" #include "duckdb/common/shared_ptr.hpp" #include "duckdb/common/unique_ptr.hpp" +#include "duckdb/common/queue.hpp" #include "duckdb/common/optional_ptr.hpp" +#include "duckdb/common/optionally_owned_ptr.hpp" #include "duckdb/common/optional_idx.hpp" +#include "duckdb/common/insertion_order_preserving_map.hpp" namespace duckdb { @@ -99,6 +102,20 @@ struct is_map> : std::true_type { typedef typename std::tuple_element<3, std::tuple>::type EQUAL_TYPE; }; +template +struct is_insertion_preserving_map : std::false_type {}; +template +struct is_insertion_preserving_map> : std::true_type { + typedef typename std::tuple_element<0, std::tuple>::type VALUE_TYPE; +}; + +template +struct is_queue : std::false_type {}; +template +struct is_queue> : std::true_type { + typedef T ELEMENT_TYPE; +}; + template struct is_unique_ptr : std::false_type {}; template @@ -124,6 +141,13 @@ struct is_optional_ptr> : std::true_type { typedef T ELEMENT_TYPE; }; +template +struct is_optionally_owned_ptr : std::false_type {}; +template +struct is_optionally_owned_ptr> : std::true_type { + typedef T ELEMENT_TYPE; +}; + template struct is_pair : std::false_type {}; template @@ -204,6 +228,16 @@ struct SerializationDefaultValue { return !value; } + template + static inline typename std::enable_if::value, T>::type GetDefault() { + return T(); + } + + template + static inline bool IsDefault(const typename std::enable_if::value, T>::type &value) { + return !value; + } + template static inline typename std::enable_if::value, T>::type GetDefault() { return T(); @@ -224,6 +258,16 @@ struct SerializationDefaultValue { return value.empty(); } + template + static inline typename std::enable_if::value, T>::type GetDefault() { + return T(); + } + + template + static inline bool IsDefault(const typename std::enable_if::value, T>::type &value) { + return value.empty(); + } + template static inline typename std::enable_if::value, T>::type GetDefault() { return T(); @@ -264,6 +308,16 @@ struct SerializationDefaultValue { return value.empty(); } + template + static inline typename std::enable_if::value, T>::type GetDefault() { + return T(); + } + + template + static inline bool IsDefault(const typename std::enable_if::value, T>::type &value) { + return value.empty(); + } + template static inline typename std::enable_if::value, T>::type GetDefault() { return T(); diff --git a/src/include/duckdb/common/serializer/serializer.hpp b/src/include/duckdb/common/serializer/serializer.hpp index f791b4a892d..3ee8f138539 100644 --- a/src/include/duckdb/common/serializer/serializer.hpp +++ b/src/include/duckdb/common/serializer/serializer.hpp @@ -16,20 +16,33 @@ #include "duckdb/common/unordered_map.hpp" #include "duckdb/common/unordered_set.hpp" #include "duckdb/common/optional_idx.hpp" +#include "duckdb/common/optionally_owned_ptr.hpp" #include "duckdb/common/value_operations/value_operations.hpp" #include "duckdb/execution/operator/csv_scanner/csv_option.hpp" +#include "duckdb/main/config.hpp" +#include "duckdb/common/insertion_order_preserving_map.hpp" namespace duckdb { -class Serializer { -protected: +class SerializationOptions { +public: bool serialize_enum_as_string = false; bool serialize_default_values = false; + SerializationCompatibility serialization_compatibility = SerializationCompatibility::Default(); +}; + +class Serializer { +protected: + SerializationOptions options; public: virtual ~Serializer() { } + bool ShouldSerialize(idx_t version_added) { + return options.serialization_compatibility.Compare(version_added); + } + class List { friend Serializer; @@ -64,7 +77,7 @@ class Serializer { template void WritePropertyWithDefault(const field_id_t field_id, const char *tag, const T &value) { // If current value is default, don't write it - if (!serialize_default_values && SerializationDefaultValue::IsDefault(value)) { + if (!options.serialize_default_values && SerializationDefaultValue::IsDefault(value)) { OnOptionalPropertyBegin(field_id, tag, false); OnOptionalPropertyEnd(false); return; @@ -77,7 +90,7 @@ class Serializer { template void WritePropertyWithDefault(const field_id_t field_id, const char *tag, const T &value, const T &&default_value) { // If current value is default, don't write it - if (!serialize_default_values && (value == default_value)) { + if (!options.serialize_default_values && (value == default_value)) { OnOptionalPropertyBegin(field_id, tag, false); OnOptionalPropertyEnd(false); return; @@ -92,7 +105,7 @@ class Serializer { void WritePropertyWithDefault(const field_id_t field_id, const char *tag, const CSVOption &value, const T &&default_value) { // If current value is default, don't write it - if (!serialize_default_values && (value == default_value)) { + if (!options.serialize_default_values && (value == default_value)) { OnOptionalPropertyBegin(field_id, tag, false); OnOptionalPropertyEnd(false); return; @@ -134,7 +147,7 @@ class Serializer { protected: template typename std::enable_if::value, void>::type WriteValue(const T value) { - if (serialize_enum_as_string) { + if (options.serialize_enum_as_string) { // Use the enum serializer to lookup tostring function auto str = EnumUtil::ToChars(value); WriteValue(str); @@ -144,6 +157,12 @@ class Serializer { } } + // Optionally Owned Pointer Ref + template + void WriteValue(const optionally_owned_ptr &ptr) { + WriteValue(ptr.get()); + } + // Unique Pointer Ref template void WriteValue(const unique_ptr &ptr) { @@ -259,6 +278,33 @@ class Serializer { OnListEnd(); } + // Insertion Order Preserving Map + // serialized as a list of pairs + template + void WriteValue(const duckdb::InsertionOrderPreservingMap &map) { + auto count = map.size(); + OnListBegin(count); + for (auto &entry : map) { + OnObjectBegin(); + WriteProperty(0, "key", entry.first); + WriteProperty(1, "value", entry.second); + OnObjectEnd(); + } + OnListEnd(); + } + + // priority queue + template + void WriteValue(const std::priority_queue &queue) { + vector placeholder; + auto queue_copy = std::priority_queue(queue); + while (queue_copy.size() > 0) { + placeholder.emplace_back(queue_copy.top()); + queue_copy.pop(); + } + WriteValue(placeholder); + } + // class or struct implementing `Serialize(Serializer& Serializer)`; template typename std::enable_if::value>::type WriteValue(const T &value) { diff --git a/src/include/duckdb/common/shared_ptr.hpp b/src/include/duckdb/common/shared_ptr.hpp index 6d0910ca6bf..eff60e3db2e 100644 --- a/src/include/duckdb/common/shared_ptr.hpp +++ b/src/include/duckdb/common/shared_ptr.hpp @@ -37,9 +37,9 @@ struct compatible_with_t : std::is_convertible {}; // NOLINT: invalid } // namespace duckdb -#include "duckdb/common/shared_ptr.ipp" -#include "duckdb/common/weak_ptr.ipp" -#include "duckdb/common/enable_shared_from_this.ipp" +#include "duckdb/common/shared_ptr_ipp.hpp" +#include "duckdb/common/weak_ptr_ipp.hpp" +#include "duckdb/common/enable_shared_from_this_ipp.hpp" namespace duckdb { diff --git a/src/include/duckdb/common/shared_ptr.ipp b/src/include/duckdb/common/shared_ptr_ipp.hpp similarity index 100% rename from src/include/duckdb/common/shared_ptr.ipp rename to src/include/duckdb/common/shared_ptr_ipp.hpp diff --git a/src/include/duckdb/common/sort/partition_state.hpp b/src/include/duckdb/common/sort/partition_state.hpp index ef12c69e4db..9c1c17bf660 100644 --- a/src/include/duckdb/common/sort/partition_state.hpp +++ b/src/include/duckdb/common/sort/partition_state.hpp @@ -40,7 +40,6 @@ class PartitionGlobalHashGroup { GlobalSortStatePtr global_sort; atomic count; - idx_t batch_base; // Mask computation SortLayout partition_layout; @@ -62,6 +61,7 @@ class PartitionGlobalSinkState { PartitionGlobalSinkState(ClientContext &context, const vector> &partition_bys, const vector &order_bys, const Types &payload_types, const vector> &partitions_stats, idx_t estimated_cardinality); + virtual ~PartitionGlobalSinkState() = default; bool HasMergeTasks() const; @@ -71,6 +71,9 @@ class PartitionGlobalSinkState { void UpdateLocalPartition(GroupingPartition &local_partition, GroupingAppend &local_append); void CombineLocalPartition(GroupingPartition &local_partition, GroupingAppend &local_append); + virtual void OnBeginMerge() {}; + virtual void OnSortedPartition(const idx_t hash_bin_p) {}; + ClientContext &context; BufferManager &buffer_manager; Allocator &allocator; @@ -142,7 +145,7 @@ class PartitionLocalSinkState { void Combine(); }; -enum class PartitionSortStage : uint8_t { INIT, SCAN, PREPARE, MERGE, SORTED }; +enum class PartitionSortStage : uint8_t { INIT, SCAN, PREPARE, MERGE, SORTED, FINISHED }; class PartitionLocalMergeState; @@ -156,9 +159,9 @@ class PartitionGlobalMergeState { // OVER(ORDER BY...) explicit PartitionGlobalMergeState(PartitionGlobalSinkState &sink); - bool IsSorted() const { + bool IsFinished() const { lock_guard guard(lock); - return stage == PartitionSortStage::SORTED; + return stage == PartitionSortStage::FINISHED; } bool AssignTask(PartitionLocalMergeState &local_state); @@ -168,6 +171,7 @@ class PartitionGlobalMergeState { PartitionGlobalSinkState &sink; GroupDataPtr group_data; PartitionGlobalHashGroup *hash_group; + const idx_t group_idx; vector column_ids; TupleDataParallelScanState chunk_state; GlobalSortState *global_sort; @@ -193,6 +197,7 @@ class PartitionLocalMergeState { void Prepare(); void Scan(); void Merge(); + void Sorted(); void ExecuteTask(); diff --git a/src/include/duckdb/common/string.hpp b/src/include/duckdb/common/string.hpp index ad717374c06..553a548d4f5 100644 --- a/src/include/duckdb/common/string.hpp +++ b/src/include/duckdb/common/string.hpp @@ -8,9 +8,10 @@ #pragma once -#include #include +#include namespace duckdb { using std::string; -} +using std::stringstream; +} // namespace duckdb diff --git a/src/include/duckdb/common/string_util.hpp b/src/include/duckdb/common/string_util.hpp index 0b8b6a1d4eb..07a4319bd1f 100644 --- a/src/include/duckdb/common/string_util.hpp +++ b/src/include/duckdb/common/string_util.hpp @@ -188,6 +188,9 @@ class StringUtil { //! Case insensitive compare DUCKDB_API static bool CILessThan(const string &l1, const string &l2); + //! Case insensitive find, returns DConstants::INVALID_INDEX if not found + DUCKDB_API static idx_t CIFind(vector &vec, const string &str); + //! Format a string using printf semantics template static string Format(const string fmt_str, ARGS... params) { diff --git a/src/include/duckdb/common/type_visitor.hpp b/src/include/duckdb/common/type_visitor.hpp new file mode 100644 index 00000000000..9296a75db72 --- /dev/null +++ b/src/include/duckdb/common/type_visitor.hpp @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/type_visitor.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/types.hpp" + +namespace duckdb { + +struct TypeVisitor { + template + static bool Contains(const LogicalType &type, F &&predicate); + + static bool Contains(const LogicalType &type, LogicalTypeId type_id); + + template + static LogicalType VisitReplace(const LogicalType &type, F &&func); +}; + +template +inline LogicalType TypeVisitor::VisitReplace(const LogicalType &type, F &&func) { + switch (type.id()) { + case LogicalTypeId::STRUCT: { + auto children = StructType::GetChildTypes(type); + for (auto &child : children) { + child.second = VisitReplace(child.second, func); + } + return func(LogicalType::STRUCT(children)); + } + case LogicalTypeId::UNION: { + auto children = UnionType::CopyMemberTypes(type); + for (auto &child : children) { + child.second = VisitReplace(child.second, func); + } + return func(LogicalType::UNION(children)); + } + case LogicalTypeId::LIST: { + auto child = ListType::GetChildType(type); + return func(LogicalType::LIST(VisitReplace(child, func))); + } + case LogicalTypeId::ARRAY: { + auto child = ArrayType::GetChildType(type); + return func(LogicalType::ARRAY(VisitReplace(child, func), ArrayType::GetSize(type))); + } + case LogicalTypeId::MAP: { + auto key = MapType::KeyType(type); + auto value = MapType::ValueType(type); + return func(LogicalType::MAP(VisitReplace(key, func), VisitReplace(value, func))); + } + default: + return func(type); + } +} + +template +inline bool TypeVisitor::Contains(const LogicalType &type, F &&predicate) { + if (predicate(type)) { + return true; + } + switch (type.id()) { + case LogicalTypeId::STRUCT: { + for (const auto &child : StructType::GetChildTypes(type)) { + if (Contains(child.second, predicate)) { + return true; + } + } + return false; + } + case LogicalTypeId::UNION: + for (const auto &child : UnionType::CopyMemberTypes(type)) { + if (Contains(child.second, predicate)) { + return true; + } + } + return false; + case LogicalTypeId::LIST: + return Contains(ListType::GetChildType(type), predicate); + case LogicalTypeId::ARRAY: + return Contains(ArrayType::GetChildType(type), predicate); + case LogicalTypeId::MAP: + return Contains(MapType::KeyType(type), predicate) || Contains(MapType::ValueType(type), predicate); + default: + return false; + } +} + +inline bool TypeVisitor::Contains(const LogicalType &type, LogicalTypeId type_id) { + return Contains(type, [&](const LogicalType &ty) { return ty.id() == type_id; }); +} + +} // namespace duckdb diff --git a/src/include/duckdb/common/types.hpp b/src/include/duckdb/common/types.hpp index 6e38fa83b89..cb70134876b 100644 --- a/src/include/duckdb/common/types.hpp +++ b/src/include/duckdb/common/types.hpp @@ -273,6 +273,9 @@ struct LogicalType { return type_info_; } + //! DeepCopy() will make a unique copy of any ExtraTypeInfo as well + LogicalType DeepCopy() const; + inline void CopyAuxInfo(const LogicalType &other) { type_info_ = other.type_info_; } @@ -315,10 +318,16 @@ struct LogicalType { DUCKDB_API string ToString() const; DUCKDB_API bool IsIntegral() const; DUCKDB_API bool IsNumeric() const; + DUCKDB_API bool IsTemporal() const; DUCKDB_API hash_t Hash() const; DUCKDB_API void SetAlias(string alias); DUCKDB_API bool HasAlias() const; DUCKDB_API string GetAlias() const; + DUCKDB_API void SetModifiers(vector modifiers); + DUCKDB_API bool HasModifiers() const; + DUCKDB_API vector GetModifiersCopy() const; + DUCKDB_API optional_ptr> GetModifiers(); + DUCKDB_API optional_ptr> GetModifiers() const; //! Returns the maximum logical type when combining the two types - or throws an exception if combining is not possible DUCKDB_API static LogicalType MaxLogicalType(ClientContext &context, const LogicalType &left, const LogicalType &right); @@ -336,9 +345,6 @@ struct LogicalType { DUCKDB_API bool IsValid() const; - template - bool Contains(F &&predicate) const; - bool Contains(LogicalTypeId type_id) const; private: LogicalTypeId id_; // NOLINT: allow this naming for legacy reasons @@ -394,9 +400,7 @@ struct LogicalType { DUCKDB_API static LogicalType MAP(const LogicalType &child); // NOLINT DUCKDB_API static LogicalType MAP(LogicalType key, LogicalType value); // NOLINT DUCKDB_API static LogicalType UNION(child_list_t members); // NOLINT - DUCKDB_API static LogicalType ARRAY(const LogicalType &child, idx_t size); // NOLINT - // an array of unknown size (only used for binding) - DUCKDB_API static LogicalType ARRAY(const LogicalType &child); // NOLINT + DUCKDB_API static LogicalType ARRAY(const LogicalType &child, optional_idx index); // NOLINT DUCKDB_API static LogicalType ENUM(Vector &ordered_data, idx_t size); // NOLINT // ANY but with special rules (default is LogicalType::ANY, 5) DUCKDB_API static LogicalType ANY_PARAMS(LogicalType target, idx_t cast_score = 5); // NOLINT @@ -405,7 +409,8 @@ struct LogicalType { // DEPRECATED - provided for backwards compatibility DUCKDB_API static LogicalType ENUM(const string &enum_name, Vector &ordered_data, idx_t size); // NOLINT DUCKDB_API static LogicalType USER(const string &user_type_name); // NOLINT - DUCKDB_API static LogicalType USER(string catalog, string schema, string name); // NOLINT + DUCKDB_API static LogicalType USER(const string &user_type_name, const vector &user_type_mods); // NOLINT + DUCKDB_API static LogicalType USER(string catalog, string schema, string name, vector user_type_mods); // NOLINT //! A list of all NUMERIC types (integral and floating point types) DUCKDB_API static const vector Numeric(); //! A list of all INTEGRAL types @@ -440,6 +445,8 @@ struct UserType { DUCKDB_API static const string &GetCatalog(const LogicalType &type); DUCKDB_API static const string &GetSchema(const LogicalType &type); DUCKDB_API static const string &GetTypeName(const LogicalType &type); + DUCKDB_API static const vector &GetTypeModifiers(const LogicalType &type); + DUCKDB_API static vector &GetTypeModifiers(LogicalType &type); }; struct EnumType { @@ -535,37 +542,6 @@ struct aggregate_state_t { vector bound_argument_types; }; -template -bool LogicalType::Contains(F &&predicate) const { - if(predicate(*this)) { - return true; - } - switch(id()) { - case LogicalTypeId::STRUCT: { - for(const auto &child : StructType::GetChildTypes(*this)) { - if(child.second.Contains(predicate)) { - return true; - } - } - } - break; - case LogicalTypeId::LIST: - return ListType::GetChildType(*this).Contains(predicate); - case LogicalTypeId::MAP: - return MapType::KeyType(*this).Contains(predicate) || MapType::ValueType(*this).Contains(predicate); - case LogicalTypeId::UNION: - for(const auto &child : UnionType::CopyMemberTypes(*this)) { - if(child.second.Contains(predicate)) { - return true; - } - } - break; - case LogicalTypeId::ARRAY: - return ArrayType::GetChildType(*this).Contains(predicate); - default: - return false; - } - return false; -} + } // namespace duckdb diff --git a/src/include/duckdb/common/types/arrow_string_view_type.hpp b/src/include/duckdb/common/types/arrow_string_view_type.hpp new file mode 100644 index 00000000000..cf943612da4 --- /dev/null +++ b/src/include/duckdb/common/types/arrow_string_view_type.hpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/arrow_string_view_type.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/numeric_utils.hpp" + +namespace duckdb { + +struct ArrowStringViewConstants { +public: + static constexpr uint8_t MAX_INLINED_BYTES = 12 * sizeof(char); + static constexpr uint8_t PREFIX_BYTES = 4 * sizeof(char); + +public: + ArrowStringViewConstants() = delete; +}; + +union arrow_string_view_t { + arrow_string_view_t() { + } + + //! Constructor for inlined arrow string views + arrow_string_view_t(int32_t length, const char *data) { + D_ASSERT(length <= ArrowStringViewConstants::MAX_INLINED_BYTES); + inlined.length = length; + memcpy(inlined.data, data, UnsafeNumericCast(length)); + if (length < ArrowStringViewConstants::MAX_INLINED_BYTES) { + // have to 0 pad + uint8_t remaining_bytes = ArrowStringViewConstants::MAX_INLINED_BYTES - NumericCast(length); + + memset(&inlined.data[length], '\0', remaining_bytes); + } + } + + //! Constructor for non-inlined arrow string views + arrow_string_view_t(int32_t length, const char *data, int32_t buffer_idx, int32_t offset) { + D_ASSERT(length > ArrowStringViewConstants::MAX_INLINED_BYTES); + ref.length = length; + memcpy(ref.prefix, data, ArrowStringViewConstants::PREFIX_BYTES); + ref.buffer_index = buffer_idx; + ref.offset = offset; + } + + //! Representation of inlined arrow string views + struct { + int32_t length; + char data[ArrowStringViewConstants::MAX_INLINED_BYTES]; + } inlined; + + //! Representation of non-inlined arrow string views + struct { + int32_t length; + char prefix[ArrowStringViewConstants::PREFIX_BYTES]; + int32_t buffer_index; + int32_t offset; + } ref; + + int32_t Length() const { + return inlined.length; + } + bool IsInline() const { + return Length() <= ArrowStringViewConstants::MAX_INLINED_BYTES; + } + + const char *GetInlineData() const { + return IsInline() ? inlined.data : ref.prefix; + } + int32_t GetBufferIndex() { + D_ASSERT(!IsInline()); + return ref.buffer_index; + } + int32_t GetOffset() { + D_ASSERT(!IsInline()); + return ref.offset; + } +}; + +} // namespace duckdb diff --git a/src/include/duckdb/common/types/cast_helpers.hpp b/src/include/duckdb/common/types/cast_helpers.hpp index 2ff2da7594b..f85b142bb51 100644 --- a/src/include/duckdb/common/types/cast_helpers.hpp +++ b/src/include/duckdb/common/types/cast_helpers.hpp @@ -30,6 +30,7 @@ class NumericHelper { public: template static int UnsignedLength(T value); + template static int SignedLength(SIGNED value) { int sign = -(value < 0); @@ -90,6 +91,11 @@ template <> int NumericHelper::UnsignedLength(uint32_t value); template <> int NumericHelper::UnsignedLength(uint64_t value); +template <> +int NumericHelper::UnsignedLength(hugeint_t value); + +template <> +char *NumericHelper::FormatUnsigned(hugeint_t value, char *ptr); template <> std::string NumericHelper::ToString(hugeint_t value); @@ -97,9 +103,13 @@ std::string NumericHelper::ToString(hugeint_t value); template <> std::string NumericHelper::ToString(uhugeint_t value); +template <> +string_t NumericHelper::FormatSigned(hugeint_t value, Vector &vector); + struct DecimalToString { - template + template static int DecimalLength(SIGNED value, uint8_t width, uint8_t scale) { + using UNSIGNED = typename MakeUnsigned::type; if (scale == 0) { // scale is 0: regular number return NumericHelper::SignedLength(value); @@ -116,8 +126,9 @@ struct DecimalToString { NumericHelper::SignedLength(value) + 1); } - template + template static void FormatDecimal(SIGNED value, uint8_t width, uint8_t scale, char *dst, idx_t len) { + using UNSIGNED = typename MakeUnsigned::type; char *end = dst + len; if (value < 0) { value = -value; @@ -149,209 +160,24 @@ struct DecimalToString { } } - template + template static string_t Format(SIGNED value, uint8_t width, uint8_t scale, Vector &vector) { - int len = DecimalLength(value, width, scale); + int len = DecimalLength(value, width, scale); string_t result = StringVector::EmptyString(vector, NumericCast(len)); - FormatDecimal(value, width, scale, result.GetDataWriteable(), UnsafeNumericCast(len)); + FormatDecimal(value, width, scale, result.GetDataWriteable(), UnsafeNumericCast(len)); result.Finalize(); return result; } }; -struct HugeintToStringCast { - static int UnsignedLength(hugeint_t value) { - D_ASSERT(value.upper >= 0); - if (value.upper == 0) { - return NumericHelper::UnsignedLength(value.lower); - } - // search the length using the POWERS_OF_TEN array - // the length has to be between [17] and [38], because the hugeint is bigger than 2^63 - // we use the same approach as above, but split a bit more because comparisons for hugeints are more expensive - if (value >= Hugeint::POWERS_OF_TEN[27]) { - // [27..38] - if (value >= Hugeint::POWERS_OF_TEN[32]) { - if (value >= Hugeint::POWERS_OF_TEN[36]) { - int length = 37; - length += value >= Hugeint::POWERS_OF_TEN[37]; - length += value >= Hugeint::POWERS_OF_TEN[38]; - return length; - } else { - int length = 33; - length += value >= Hugeint::POWERS_OF_TEN[33]; - length += value >= Hugeint::POWERS_OF_TEN[34]; - length += value >= Hugeint::POWERS_OF_TEN[35]; - return length; - } - } else { - if (value >= Hugeint::POWERS_OF_TEN[30]) { - int length = 31; - length += value >= Hugeint::POWERS_OF_TEN[31]; - length += value >= Hugeint::POWERS_OF_TEN[32]; - return length; - } else { - int length = 28; - length += value >= Hugeint::POWERS_OF_TEN[28]; - length += value >= Hugeint::POWERS_OF_TEN[29]; - return length; - } - } - } else { - // [17..27] - if (value >= Hugeint::POWERS_OF_TEN[22]) { - // [22..27] - if (value >= Hugeint::POWERS_OF_TEN[25]) { - int length = 26; - length += value >= Hugeint::POWERS_OF_TEN[26]; - return length; - } else { - int length = 23; - length += value >= Hugeint::POWERS_OF_TEN[23]; - length += value >= Hugeint::POWERS_OF_TEN[24]; - return length; - } - } else { - // [17..22] - if (value >= Hugeint::POWERS_OF_TEN[20]) { - int length = 21; - length += value >= Hugeint::POWERS_OF_TEN[21]; - return length; - } else { - int length = 18; - length += value >= Hugeint::POWERS_OF_TEN[18]; - length += value >= Hugeint::POWERS_OF_TEN[19]; - return length; - } - } - } - } - - // Formats value in reverse and returns a pointer to the beginning. - static char *FormatUnsigned(hugeint_t value, char *ptr) { - while (value.upper > 0) { - // while integer division is slow, hugeint division is MEGA slow - // we want to avoid doing as many divisions as possible - // for that reason we start off doing a division by a large power of ten that uint64_t can hold - // (100000000000000000) - this is the third largest - // the reason we don't use the largest is because that can result in an overflow inside the division - // function - uint64_t remainder; - value = Hugeint::DivModPositive(value, 100000000000000000ULL, remainder); - - auto startptr = ptr; - // now we format the remainder: note that we need to pad with zero's in case - // the remainder is small (i.e. less than 10000000000000000) - ptr = NumericHelper::FormatUnsigned(remainder, ptr); - - int format_length = UnsafeNumericCast(startptr - ptr); - // pad with zero - for (int i = format_length; i < 17; i++) { - *--ptr = '0'; - } - } - // once the value falls in the range of a uint64_t, fallback to formatting as uint64_t to avoid hugeint division - return NumericHelper::FormatUnsigned(value.lower, ptr); - } - - static string_t FormatSigned(hugeint_t value, Vector &vector) { - int negative = value.upper < 0; - if (negative) { - if (value == NumericLimits::Minimum()) { - string_t result = StringVector::AddString(vector, Hugeint::HUGEINT_MINIMUM_STRING); - return result; - } - Hugeint::NegateInPlace(value); - } - int length = UnsignedLength(value) + negative; - string_t result = StringVector::EmptyString(vector, NumericCast(length)); - auto dataptr = result.GetDataWriteable(); - auto endptr = dataptr + length; - if (value.upper == 0) { - // small value: format as uint64_t - endptr = NumericHelper::FormatUnsigned(value.lower, endptr); - } else { - endptr = FormatUnsigned(value, endptr); - } - if (negative) { - *--endptr = '-'; - } - D_ASSERT(endptr == dataptr); - result.Finalize(); - return result; - } - - static int DecimalLength(hugeint_t value, uint8_t width, uint8_t scale) { - D_ASSERT(value > NumericLimits::Minimum()); - int negative; - - if (value.upper < 0) { - Hugeint::NegateInPlace(value); - negative = 1; - } else { - negative = 0; - } - if (scale == 0) { - // scale is 0: regular number - return UnsignedLength(value) + negative; - } - // length is max of either: - // scale + 2 OR - // integer length + 1 - // scale + 2 happens when the number is in the range of (-1, 1) - // in that case we print "0.XXX", which is the scale, plus "0." (2 chars) - // integer length + 1 happens when the number is outside of that range - // in that case we print the integer number, but with one extra character ('.') - auto extra_numbers = width > scale ? 2 : 1; - return MaxValue(scale + extra_numbers, UnsignedLength(value) + 1) + negative; - } - - static void FormatDecimal(hugeint_t value, uint8_t width, uint8_t scale, char *dst, int len) { - auto endptr = dst + len; - - int negative = value.upper < 0; - if (negative) { - Hugeint::NegateInPlace(value); - *dst = '-'; - dst++; - } - if (scale == 0) { - // with scale=0 we format the number as a regular number - FormatUnsigned(value, endptr); - return; - } - - // we write two numbers: - // the numbers BEFORE the decimal (major) - // and the numbers AFTER the decimal (minor) - hugeint_t minor; - hugeint_t major = Hugeint::DivMod(value, Hugeint::POWERS_OF_TEN[scale], minor); - - // write the number after the decimal - dst = FormatUnsigned(minor, endptr); - // (optionally) pad with zeros and add the decimal point - while (dst > (endptr - scale)) { - *--dst = '0'; - } - *--dst = '.'; - // now write the part before the decimal - D_ASSERT(width > scale || major == 0); - if (width > scale) { - dst = FormatUnsigned(major, dst); - } - } - - static string_t FormatDecimal(hugeint_t value, uint8_t width, uint8_t scale, Vector &vector) { - int length = DecimalLength(value, width, scale); - string_t result = StringVector::EmptyString(vector, NumericCast(length)); - - auto dst = result.GetDataWriteable(); +template <> +int DecimalToString::DecimalLength(hugeint_t value, uint8_t width, uint8_t scale); - FormatDecimal(value, width, scale, dst, length); +template <> +string_t DecimalToString::Format(hugeint_t value, uint8_t width, uint8_t scale, Vector &vector); - result.Finalize(); - return result; - } -}; +template <> +void DecimalToString::FormatDecimal(hugeint_t value, uint8_t width, uint8_t scale, char *dst, idx_t len); struct UhugeintToStringCast { static string_t Format(uhugeint_t value, Vector &vector) { diff --git a/src/include/duckdb/common/types/data_chunk.hpp b/src/include/duckdb/common/types/data_chunk.hpp index f3a7304d2f1..37fce1424cb 100644 --- a/src/include/duckdb/common/types/data_chunk.hpp +++ b/src/include/duckdb/common/types/data_chunk.hpp @@ -81,6 +81,8 @@ class DataChunk { DUCKDB_API Value GetValue(idx_t col_idx, idx_t index) const; DUCKDB_API void SetValue(idx_t col_idx, idx_t index, const Value &val); + idx_t GetAllocationSize() const; + //! Returns true if all vectors in the DataChunk are constant DUCKDB_API bool AllConstant() const; diff --git a/src/include/duckdb/common/types/date.hpp b/src/include/duckdb/common/types/date.hpp index f7061cab01a..f2cb08d50e8 100644 --- a/src/include/duckdb/common/types/date.hpp +++ b/src/include/duckdb/common/types/date.hpp @@ -173,9 +173,6 @@ class Date { //! Extract year of a date entry DUCKDB_API static int32_t ExtractYear(date_t date); - //! Extract year of a date entry, but optimized to first try the last year found - DUCKDB_API static int32_t ExtractYear(date_t date, int32_t *last_year); - DUCKDB_API static int32_t ExtractYear(timestamp_t ts, int32_t *last_year); //! Extract month of a date entry DUCKDB_API static int32_t ExtractMonth(date_t date); //! Extract day of a date entry diff --git a/src/include/duckdb/common/types/date_lookup_cache.hpp b/src/include/duckdb/common/types/date_lookup_cache.hpp new file mode 100644 index 00000000000..d008b4a92d4 --- /dev/null +++ b/src/include/duckdb/common/types/date_lookup_cache.hpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/date_lookup_cache.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/types/date.hpp" +#include "duckdb/common/types/timestamp.hpp" +#include "duckdb/common/types/value.hpp" +#include "duckdb/common/types/validity_mask.hpp" + +namespace duckdb { +struct ValidityMask; + +template +class DateLookupCache { +public: + using CACHE_TYPE = uint16_t; + constexpr static int32_t CACHE_MIN_DATE = 0; // 1970-01-01 + constexpr static int32_t CACHE_MAX_DATE = 29584; // 2050-12-31 + +public: + DateLookupCache() { + BuildCache(); + } + + //! Extracts the component, or sets the validity mask to NULL if the date is infinite + int64_t ExtractElement(date_t date, ValidityMask &mask, idx_t idx) const { + if (DUCKDB_UNLIKELY(date.days < CACHE_MIN_DATE || date.days > CACHE_MAX_DATE)) { + if (DUCKDB_UNLIKELY(!Value::IsFinite(date))) { + mask.SetInvalid(idx); + return 0; + } + return OP::template Operation(date); + } + return cache[GetDateCacheEntry(date)]; + } + int64_t ExtractElement(timestamp_t ts, ValidityMask &mask, idx_t idx) const { + return ExtractElement(Timestamp::GetDate(ts), mask, idx); + } + +private: + static idx_t GetDateCacheEntry(date_t day) { + return UnsafeNumericCast(day.days - DateLookupCache::CACHE_MIN_DATE); + } + + void BuildCache() { + D_ASSERT(CACHE_MAX_DATE > CACHE_MIN_DATE); + cache = make_unsafe_uniq_array(CACHE_MAX_DATE - CACHE_MIN_DATE); + for (int32_t d = CACHE_MIN_DATE; d < CACHE_MAX_DATE; d++) { + date_t date(d); + auto cache_entry = OP::template Operation(date); + cache[GetDateCacheEntry(date)] = UnsafeNumericCast(cache_entry); + } + } + +private: + unsafe_unique_array cache; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/common/types/datetime.hpp b/src/include/duckdb/common/types/datetime.hpp index a289a9a4697..a687f1e1bf5 100644 --- a/src/include/duckdb/common/types/datetime.hpp +++ b/src/include/duckdb/common/types/datetime.hpp @@ -1,6 +1,7 @@ #pragma once #include "duckdb/common/common.hpp" +#include "duckdb/common/numeric_utils.hpp" #include @@ -23,7 +24,7 @@ struct dtime_t { // NOLINT return micros; } explicit inline operator double() const { - return micros; + return static_cast(micros); } // comparison operators @@ -92,23 +93,47 @@ struct dtime_tz_t { // NOLINT static constexpr const uint64_t OFFSET_MASK = ~uint64_t(0) >> TIME_BITS; static constexpr const int32_t MAX_OFFSET = 16 * 60 * 60 - 1; // ±15:59:59 static constexpr const int32_t MIN_OFFSET = -MAX_OFFSET; + static constexpr const uint64_t OFFSET_MICROS = 1000000; uint64_t bits; + // Offsets are reverse ordered e.g., 13:00:00+01 < 12:00:00+00 < 11:00:00-01 + // Because we encode them as the low order bits, + // they are also biased into an unsigned integer: (-16, 16) => (32, 0) + static inline uint64_t encode_offset(int32_t offset) { // NOLINT + return uint64_t(MAX_OFFSET - offset); + } + static inline int32_t decode_offset(uint64_t bits) { // NOLINT + return MAX_OFFSET - int32_t(bits & OFFSET_MASK); + } + + static inline uint64_t encode_micros(int64_t micros) { // NOLINT + return uint64_t(micros) << OFFSET_BITS; + } + static inline int64_t decode_micros(uint64_t bits) { // NOLINT + return int64_t(bits >> OFFSET_BITS); + } + dtime_tz_t() = default; - inline dtime_tz_t(dtime_t t, int32_t offset) - : bits((uint64_t(t.micros) << OFFSET_BITS) | uint64_t(MAX_OFFSET - offset)) { + inline dtime_tz_t(dtime_t t, int32_t offset) : bits(encode_micros(t.micros) | encode_offset(offset)) { } explicit inline dtime_tz_t(uint64_t bits_p) : bits(bits_p) { } inline dtime_t time() const { // NOLINT - return dtime_t(bits >> OFFSET_BITS); + return dtime_t(decode_micros(bits)); } inline int32_t offset() const { // NOLINT - return MAX_OFFSET - int32_t(bits & OFFSET_MASK); + return decode_offset(bits); + } + + // Times are compared after adjusting to offset +00:00:00, e.g., 13:01:00+01 > 12:00:00+00 + // Because we encode them as the high order bits, + // they are biased by the maximum offset: (0, 24) => (0, 56) + inline uint64_t sort_key() const { // NOLINT + return bits + encode_micros((bits & OFFSET_MASK) * OFFSET_MICROS); } // comparison operators @@ -119,16 +144,16 @@ struct dtime_tz_t { // NOLINT return bits != rhs.bits; }; inline bool operator<=(const dtime_tz_t &rhs) const { - return bits <= rhs.bits; + return sort_key() <= rhs.sort_key(); }; inline bool operator<(const dtime_tz_t &rhs) const { - return bits < rhs.bits; + return sort_key() < rhs.sort_key(); }; inline bool operator>(const dtime_tz_t &rhs) const { - return bits > rhs.bits; + return sort_key() > rhs.sort_key(); }; inline bool operator>=(const dtime_tz_t &rhs) const { - return bits >= rhs.bits; + return sort_key() >= rhs.sort_key(); }; }; diff --git a/src/include/duckdb/common/types/row/tuple_data_collection.hpp b/src/include/duckdb/common/types/row/tuple_data_collection.hpp index 01fc20ec33d..1612287d570 100644 --- a/src/include/duckdb/common/types/row/tuple_data_collection.hpp +++ b/src/include/duckdb/common/types/row/tuple_data_collection.hpp @@ -145,6 +145,8 @@ class TupleDataCollection { //! Initializes a chunk with the correct types that can be used to call Append/Scan void InitializeChunk(DataChunk &chunk) const; + //! Initializes a chunk with the correct types that can be used to call Append/Scan for the given columns + void InitializeChunk(DataChunk &chunk, const vector &columns) const; //! Initializes a chunk with the correct types for a given scan state void InitializeScanChunk(TupleDataScanState &state, DataChunk &chunk) const; //! Initializes a Scan state for scanning all columns diff --git a/src/include/duckdb/common/types/row/tuple_data_segment.hpp b/src/include/duckdb/common/types/row/tuple_data_segment.hpp index 85496e4da36..cf6ee276715 100644 --- a/src/include/duckdb/common/types/row/tuple_data_segment.hpp +++ b/src/include/duckdb/common/types/row/tuple_data_segment.hpp @@ -32,7 +32,9 @@ struct TupleDataChunkPart { TupleDataChunkPart(TupleDataChunkPart &&other) noexcept; TupleDataChunkPart &operator=(TupleDataChunkPart &&) noexcept; - static constexpr const uint32_t INVALID_INDEX = (uint32_t)-1; +public: + //! Mark heap as empty + void SetHeapEmpty(); public: //! Index/offset of the row block @@ -48,6 +50,10 @@ struct TupleDataChunkPart { uint32_t count; //! Lock for recomputing heap pointers (owned by TupleDataChunk) reference lock; + +private: + //! Marker for empty heaps + static constexpr const uint32_t INVALID_INDEX = (uint32_t)-1; }; struct TupleDataChunk { diff --git a/src/include/duckdb/common/types/selection_vector.hpp b/src/include/duckdb/common/types/selection_vector.hpp index 969c785690d..578aa25b814 100644 --- a/src/include/duckdb/common/types/selection_vector.hpp +++ b/src/include/duckdb/common/types/selection_vector.hpp @@ -111,6 +111,10 @@ struct SelectionVector { inline sel_t &operator[](idx_t index) const { return sel_vector[index]; } + inline bool IsSet() const { + return sel_vector; + } + void Verify(idx_t count, idx_t vector_size) const; private: sel_t *sel_vector; diff --git a/src/include/duckdb/common/types/string_type.hpp b/src/include/duckdb/common/types/string_type.hpp index 1ec8bdc8930..c9155c598cd 100644 --- a/src/include/duckdb/common/types/string_type.hpp +++ b/src/include/duckdb/common/types/string_type.hpp @@ -12,6 +12,7 @@ #include "duckdb/common/constants.hpp" #include "duckdb/common/helper.hpp" #include "duckdb/common/numeric_utils.hpp" +#include "duckdb/common/limits.hpp" #include #include @@ -26,6 +27,7 @@ struct string_t { static constexpr idx_t PREFIX_BYTES = 4 * sizeof(char); static constexpr idx_t INLINE_BYTES = 12 * sizeof(char); static constexpr idx_t HEADER_SIZE = sizeof(uint32_t) + PREFIX_BYTES; + static constexpr idx_t MAX_STRING_SIZE = NumericLimits::Maximum(); #ifndef DUCKDB_DEBUG_NO_INLINE static constexpr idx_t PREFIX_LENGTH = PREFIX_BYTES; static constexpr idx_t INLINE_LENGTH = INLINE_BYTES; diff --git a/src/include/duckdb/common/types/time.hpp b/src/include/duckdb/common/types/time.hpp index 2611de10f51..74085b2ec62 100644 --- a/src/include/duckdb/common/types/time.hpp +++ b/src/include/duckdb/common/types/time.hpp @@ -22,14 +22,17 @@ struct dtime_tz_t; // NOLINT class Time { public: //! Convert a string in the format "hh:mm:ss" to a time object - DUCKDB_API static dtime_t FromString(const string &str, bool strict = false); - DUCKDB_API static dtime_t FromCString(const char *buf, idx_t len, bool strict = false); - DUCKDB_API static bool TryConvertTime(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict = false); + DUCKDB_API static dtime_t FromString(const string &str, bool strict = false, optional_ptr nanos = nullptr); + DUCKDB_API static dtime_t FromCString(const char *buf, idx_t len, bool strict = false, + optional_ptr nanos = nullptr); + DUCKDB_API static bool TryConvertTime(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict = false, + optional_ptr nanos = nullptr); DUCKDB_API static bool TryConvertTimeTZ(const char *buf, idx_t len, idx_t &pos, dtime_tz_t &result, - bool &has_offset, bool strict = false); + bool &has_offset, bool strict = false, + optional_ptr nanos = nullptr); // No hour limit DUCKDB_API static bool TryConvertInterval(const char *buf, idx_t len, idx_t &pos, dtime_t &result, - bool strict = false); + bool strict = false, optional_ptr nanos = nullptr); //! Convert a time object to a string in the format "hh:mm:ss" DUCKDB_API static string ToString(dtime_t time); @@ -37,6 +40,7 @@ class Time { DUCKDB_API static string ToUTCOffset(int hour_offset, int minute_offset); DUCKDB_API static dtime_t FromTime(int32_t hour, int32_t minute, int32_t second, int32_t microseconds = 0); + DUCKDB_API static int64_t ToNanoTime(int32_t hour, int32_t minute, int32_t second, int32_t nanoseconds = 0); //! Normalize a TIME_TZ by adding the offset to the time part and returning the TIME DUCKDB_API static dtime_t NormalizeTimeTZ(dtime_tz_t timetz); @@ -54,7 +58,8 @@ class Time { DUCKDB_API static bool IsValidTime(int32_t hour, int32_t minute, int32_t second, int32_t microseconds); private: - static bool TryConvertInternal(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict); + static bool TryConvertInternal(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict, + optional_ptr nanos = nullptr); }; } // namespace duckdb diff --git a/src/include/duckdb/common/types/timestamp.hpp b/src/include/duckdb/common/types/timestamp.hpp index 526b5a440a9..683d3965041 100644 --- a/src/include/duckdb/common/types/timestamp.hpp +++ b/src/include/duckdb/common/types/timestamp.hpp @@ -106,9 +106,11 @@ class Timestamp { //! If has_offset is true, then the result is an instant that was offset from UTC //! If the tz is not empty, the result is still an instant, but the parts can be extracted and applied to the TZ DUCKDB_API static bool TryConvertTimestampTZ(const char *str, idx_t len, timestamp_t &result, bool &has_offset, - string_t &tz); - DUCKDB_API static TimestampCastResult TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result); - DUCKDB_API static timestamp_t FromCString(const char *str, idx_t len); + string_t &tz, optional_ptr nanos = nullptr); + DUCKDB_API static TimestampCastResult TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result, + optional_ptr nanos = nullptr); + DUCKDB_API static TimestampCastResult TryConvertTimestamp(const char *str, idx_t len, timestamp_ns_t &result); + DUCKDB_API static timestamp_t FromCString(const char *str, idx_t len, optional_ptr nanos = nullptr); //! Convert a date object to a string in the format "YYYY-MM-DD hh:mm:ss" DUCKDB_API static string ToString(timestamp_t timestamp); @@ -119,6 +121,8 @@ class Timestamp { DUCKDB_API static timestamp_t FromDatetime(date_t date, dtime_t time); DUCKDB_API static bool TryFromDatetime(date_t date, dtime_t time, timestamp_t &result); DUCKDB_API static bool TryFromDatetime(date_t date, dtime_tz_t timetz, timestamp_t &result); + //! Scale up to ns + DUCKDB_API static bool TryFromTimestampNanos(timestamp_t ts, int32_t nanos, timestamp_ns_t &result); //! Is the character a valid part of a time zone name? static inline bool CharacterIsTimeZone(char c) { @@ -133,6 +137,8 @@ class Timestamp { //! Extract the date and time from a given timestamp object DUCKDB_API static void Convert(timestamp_t date, date_t &out_date, dtime_t &out_time); + //! Extract the date and time from a given timestamp object + DUCKDB_API static void Convert(timestamp_ns_t date, date_t &out_date, dtime_t &out_time, int32_t &out_nanos); //! Returns current timestamp DUCKDB_API static timestamp_t GetCurrentTimestamp(); @@ -148,6 +154,10 @@ class Timestamp { DUCKDB_API static timestamp_t FromEpochNanoSecondsPossiblyInfinite(int64_t nanos); DUCKDB_API static timestamp_t FromEpochNanoSeconds(int64_t nanos); + //! Construct ns timestamps from various epoch units + DUCKDB_API static timestamp_ns_t TimestampNsFromEpochMicros(int64_t micros); + DUCKDB_API static timestamp_ns_t TimestampNsFromEpochMillis(int64_t millis); + //! Try convert a timestamp to epoch (in nanoseconds) DUCKDB_API static bool TryGetEpochNanoSeconds(timestamp_t timestamp, int64_t &result); //! Convert the epoch (in seconds) to a timestamp @@ -158,6 +168,8 @@ class Timestamp { DUCKDB_API static int64_t GetEpochMicroSeconds(timestamp_t timestamp); //! Convert a timestamp to epoch (in nanoseconds) DUCKDB_API static int64_t GetEpochNanoSeconds(timestamp_t timestamp); + //! Convert a timestamp to a rounded epoch at a given resolution. + DUCKDB_API static int64_t GetEpochRounded(timestamp_t timestamp, const int64_t power_of_ten); //! Convert a timestamp to a Julian Day DUCKDB_API static double GetJulianDay(timestamp_t timestamp); diff --git a/src/include/duckdb/common/types/validity_mask.hpp b/src/include/duckdb/common/types/validity_mask.hpp index fce5f0d1a09..ee24541dc2a 100644 --- a/src/include/duckdb/common/types/validity_mask.hpp +++ b/src/include/duckdb/common/types/validity_mask.hpp @@ -14,6 +14,7 @@ #include "duckdb/common/vector_size.hpp" namespace duckdb { +struct SelectionVector; struct ValidityMask; template @@ -339,6 +340,8 @@ struct ValidityMask : public TemplatedValidityMask { DUCKDB_API idx_t TargetCount(); DUCKDB_API void SliceInPlace(const ValidityMask &other, idx_t target_offset, idx_t source_offset, idx_t count); DUCKDB_API void Slice(const ValidityMask &other, idx_t source_offset, idx_t count); + DUCKDB_API void CopySel(const ValidityMask &other, const SelectionVector &sel, idx_t source_offset, + idx_t target_offset, idx_t count); DUCKDB_API void Combine(const ValidityMask &other, idx_t count); DUCKDB_API string ToString(idx_t count) const; diff --git a/src/include/duckdb/common/types/value.hpp b/src/include/duckdb/common/types/value.hpp index 2e27fdc4409..a59481df24a 100644 --- a/src/include/duckdb/common/types/value.hpp +++ b/src/include/duckdb/common/types/value.hpp @@ -177,6 +177,9 @@ class Value { //! Create a map value with the given entries DUCKDB_API static Value MAP(const LogicalType &key_type, const LogicalType &value_type, vector keys, vector values); + //! Create a map value from a set of key-value pairs + DUCKDB_API static Value MAP(const unordered_map &kv_pairs); + //! Create a union value from a selected value and a tag from a set of alternatives. DUCKDB_API static Value UNION(child_list_t members, uint8_t tag, Value value); diff --git a/src/include/duckdb/common/types/vector.hpp b/src/include/duckdb/common/types/vector.hpp index 49cb9111c46..9026829f872 100644 --- a/src/include/duckdb/common/types/vector.hpp +++ b/src/include/duckdb/common/types/vector.hpp @@ -19,6 +19,11 @@ namespace duckdb { +class VectorCache; +class VectorStructBuffer; +class VectorListBuffer; +struct SelCache; + struct UnifiedVectorFormat { DUCKDB_API UnifiedVectorFormat(); // disable copy constructors @@ -49,11 +54,17 @@ struct RecursiveUnifiedVectorFormat { LogicalType logical_type; }; -class VectorCache; -class VectorStructBuffer; -class VectorListBuffer; +//! This is a helper data structure. It contains all fields necessary to resize a vector. +struct ResizeInfo { + ResizeInfo(Vector &vec, data_ptr_t data, optional_ptr buffer, const idx_t multiplier) + : vec(vec), data(data), buffer(buffer), multiplier(multiplier) { + } -struct SelCache; + Vector &vec; + data_ptr_t data; + optional_ptr buffer; + idx_t multiplier; +}; struct ConsecutiveChildListInfo { ConsecutiveChildListInfo() : is_constant(true), needs_slicing(false), child_list_info(list_entry_t(0, 0)) { @@ -63,7 +74,7 @@ struct ConsecutiveChildListInfo { list_entry_t child_list_info; }; -//! Vector of values of a specified PhysicalType. +//! Vector of values of a specified PhysicalType. class Vector { friend struct ConstantVector; friend struct DictionaryVector; @@ -185,12 +196,16 @@ class Vector { data = other.data; } - //! This functions resizes the vector + //! Resizes the vector. DUCKDB_API void Resize(idx_t cur_size, idx_t new_size); + //! Returns a vector of ResizeInfo containing each (nested) vector to resize. + DUCKDB_API void FindResizeInfos(vector &resize_infos, const idx_t multiplier); DUCKDB_API void Serialize(Serializer &serializer, idx_t count); DUCKDB_API void Deserialize(Deserializer &deserializer, idx_t count); + idx_t GetAllocationSize(idx_t cardinality) const; + // Getters inline VectorType GetVectorType() const { return vector_type; diff --git a/src/include/duckdb/common/vector_operations/generic_executor.hpp b/src/include/duckdb/common/vector_operations/generic_executor.hpp index aeb99c291a7..21ffd6b7cae 100644 --- a/src/include/duckdb/common/vector_operations/generic_executor.hpp +++ b/src/include/duckdb/common/vector_operations/generic_executor.hpp @@ -213,6 +213,35 @@ struct StructTypeQuaternary { } }; +template +struct GenericListType { + vector values; + + using STRUCT_STATE = PrimitiveTypeState; + + static bool ConstructType(STRUCT_STATE &state, idx_t i, GenericListType &result) { + throw InternalException("FIXME: implement ConstructType for lists"); + } + + static void AssignResult(Vector &result, idx_t i, GenericListType value) { + auto &child = ListVector::GetEntry(result); + auto current_size = ListVector::GetListSize(result); + + // reserve space in the child element + auto list_size = value.values.size(); + ListVector::Reserve(result, current_size + list_size); + + auto list_entries = FlatVector::GetData(result); + list_entries[i].offset = current_size; + list_entries[i].length = list_size; + + for (idx_t child_idx = 0; child_idx < list_size; child_idx++) { + CHILD_TYPE::AssignResult(child, current_size + child_idx, value.values[child_idx]); + } + ListVector::SetListSize(result, current_size + list_size); + } +}; + //! The GenericExecutor can handle struct types in addition to primitive types struct GenericExecutor { private: diff --git a/src/include/duckdb/common/vector_operations/unary_executor.hpp b/src/include/duckdb/common/vector_operations/unary_executor.hpp index 569b99abe0d..9f29d7410fa 100644 --- a/src/include/duckdb/common/vector_operations/unary_executor.hpp +++ b/src/include/duckdb/common/vector_operations/unary_executor.hpp @@ -72,7 +72,6 @@ struct UnaryExecutor { #endif if (!mask.AllValid()) { - result_mask.EnsureWritable(); for (idx_t i = 0; i < count; i++) { auto idx = sel_vector->get_index(i); if (mask.RowIsValidUnsafe(idx)) { @@ -83,9 +82,6 @@ struct UnaryExecutor { } } } else { - if (adds_nulls) { - result_mask.EnsureWritable(); - } for (idx_t i = 0; i < count; i++) { auto idx = sel_vector->get_index(i); result_data[i] = @@ -133,9 +129,6 @@ struct UnaryExecutor { } } } else { - if (adds_nulls) { - result_mask.EnsureWritable(); - } for (idx_t i = 0; i < count; i++) { result_data[i] = OPWRAPPER::template Operation(ldata[i], result_mask, i, dataptr); diff --git a/src/include/duckdb/common/weak_ptr.ipp b/src/include/duckdb/common/weak_ptr_ipp.hpp similarity index 100% rename from src/include/duckdb/common/weak_ptr.ipp rename to src/include/duckdb/common/weak_ptr_ipp.hpp diff --git a/src/include/duckdb/core_functions/aggregate/algebraic/covar.hpp b/src/include/duckdb/core_functions/aggregate/algebraic/covar.hpp index 79d7db1e210..1908dfad1b0 100644 --- a/src/include/duckdb/core_functions/aggregate/algebraic/covar.hpp +++ b/src/include/duckdb/core_functions/aggregate/algebraic/covar.hpp @@ -32,7 +32,7 @@ struct CovarOperation { template static void Operation(STATE &state, const A_TYPE &y, const B_TYPE &x, AggregateBinaryInput &idata) { // update running mean and d^2 - const uint64_t n = ++(state.count); + const double n = static_cast(++(state.count)); const double dx = (x - state.meanx); const double meanx = state.meanx + dx / n; @@ -54,14 +54,18 @@ struct CovarOperation { target = source; } else if (source.count > 0) { const auto count = target.count + source.count; - const auto meanx = (source.count * source.meanx + target.count * target.meanx) / count; - const auto meany = (source.count * source.meany + target.count * target.meany) / count; + D_ASSERT(count >= target.count); // This is a check that we are not overflowing + const auto target_count = static_cast(target.count); + const auto source_count = static_cast(source.count); + const auto total_count = static_cast(count); + const auto meanx = (source_count * source.meanx + target_count * target.meanx) / total_count; + const auto meany = (source_count * source.meany + target_count * target.meany) / total_count; // Schubert and Gertz SSDBM 2018, equation 21 const auto deltax = target.meanx - source.meanx; const auto deltay = target.meany - source.meany; target.co_moment = - source.co_moment + target.co_moment + deltax * deltay * source.count * target.count / count; + source.co_moment + target.co_moment + deltax * deltay * source_count * target_count / total_count; target.meanx = meanx; target.meany = meany; target.count = count; diff --git a/src/include/duckdb/core_functions/aggregate/algebraic/stddev.hpp b/src/include/duckdb/core_functions/aggregate/algebraic/stddev.hpp index 88063eea060..bdcafae951e 100644 --- a/src/include/duckdb/core_functions/aggregate/algebraic/stddev.hpp +++ b/src/include/duckdb/core_functions/aggregate/algebraic/stddev.hpp @@ -40,7 +40,6 @@ struct STDDevBaseOperation { state.mean = new_mean; state.dsquared = new_dsquared; - } template @@ -49,7 +48,8 @@ struct STDDevBaseOperation { } template - static void ConstantOperation(STATE &state, const INPUT_TYPE &input, AggregateUnaryInput &unary_input, idx_t count) { + static void ConstantOperation(STATE &state, const INPUT_TYPE &input, AggregateUnaryInput &unary_input, + idx_t count) { for (idx_t i = 0; i < count; i++) { Operation(state, input, unary_input); } @@ -61,10 +61,14 @@ struct STDDevBaseOperation { target = source; } else if (source.count > 0) { const auto count = target.count + source.count; - const auto mean = (source.count * source.mean + target.count * target.mean) / count; + D_ASSERT(count >= target.count); // This is a check that we are not overflowing + const double target_count = static_cast(target.count); + const double source_count = static_cast(source.count); + const double total_count = static_cast(count); + const auto mean = (source_count * source.mean + target_count * target.mean) / total_count; const auto delta = source.mean - target.mean; target.dsquared = - source.dsquared + target.dsquared + delta * delta * source.count * target.count / count; + source.dsquared + target.dsquared + delta * delta * source_count * target_count / total_count; target.mean = mean; target.count = count; } diff --git a/src/include/duckdb/core_functions/aggregate/distributive_functions.hpp b/src/include/duckdb/core_functions/aggregate/distributive_functions.hpp index 3f65ca2666f..dc2ecae9b66 100644 --- a/src/include/duckdb/core_functions/aggregate/distributive_functions.hpp +++ b/src/include/duckdb/core_functions/aggregate/distributive_functions.hpp @@ -17,11 +17,11 @@ namespace duckdb { struct ApproxCountDistinctFun { static constexpr const char *Name = "approx_count_distinct"; - static constexpr const char *Parameters = "x"; + static constexpr const char *Parameters = "any"; static constexpr const char *Description = "Computes the approximate count of distinct elements using HyperLogLog."; static constexpr const char *Example = "approx_count_distinct(A)"; - static AggregateFunctionSet GetFunctions(); + static AggregateFunction GetFunction(); }; struct ArgMinFun { diff --git a/src/include/duckdb/core_functions/aggregate/histogram_helpers.hpp b/src/include/duckdb/core_functions/aggregate/histogram_helpers.hpp new file mode 100644 index 00000000000..a78741df827 --- /dev/null +++ b/src/include/duckdb/core_functions/aggregate/histogram_helpers.hpp @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/core_functions/aggregate/histogram_helpers.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/common.hpp" +#include "duckdb/core_functions/create_sort_key.hpp" + +namespace duckdb { + +struct HistogramFunctor { + template + static void HistogramFinalize(T value, Vector &result, idx_t offset) { + FlatVector::GetData(result)[offset] = value; + } + + static bool CreateExtraState() { + return false; + } + + static void PrepareData(Vector &input, idx_t count, bool &, UnifiedVectorFormat &result) { + input.ToUnifiedFormat(count, result); + } + + template + static T ExtractValue(UnifiedVectorFormat &bin_data, idx_t offset, AggregateInputData &) { + return UnifiedVectorFormat::GetData(bin_data)[bin_data.sel->get_index(offset)]; + } + + static bool RequiresExtract() { + return false; + } +}; + +struct HistogramStringFunctorBase { + template + static T ExtractValue(UnifiedVectorFormat &bin_data, idx_t offset, AggregateInputData &aggr_input) { + auto &input_str = UnifiedVectorFormat::GetData(bin_data)[bin_data.sel->get_index(offset)]; + if (input_str.IsInlined()) { + // inlined strings can be inserted directly + return input_str; + } + // if the string is not inlined we need to allocate space for it + auto input_str_size = UnsafeNumericCast(input_str.GetSize()); + auto string_memory = aggr_input.allocator.Allocate(input_str_size); + // copy over the string + memcpy(string_memory, input_str.GetData(), input_str_size); + // now insert it into the histogram + string_t histogram_str(char_ptr_cast(string_memory), input_str_size); + return histogram_str; + } + + static bool RequiresExtract() { + return true; + } +}; + +struct HistogramStringFunctor : HistogramStringFunctorBase { + template + static void HistogramFinalize(T value, Vector &result, idx_t offset) { + FlatVector::GetData(result)[offset] = StringVector::AddStringOrBlob(result, value); + } + + static bool CreateExtraState() { + return false; + } + + static void PrepareData(Vector &input, idx_t count, bool &, UnifiedVectorFormat &result) { + input.ToUnifiedFormat(count, result); + } +}; + +struct HistogramGenericFunctor : HistogramStringFunctorBase { + template + static void HistogramFinalize(T value, Vector &result, idx_t offset) { + CreateSortKeyHelpers::DecodeSortKey(value, result, offset, + OrderModifiers(OrderType::ASCENDING, OrderByNullType::NULLS_LAST)); + } + + static Vector CreateExtraState() { + return Vector(LogicalType::BLOB); + } + + static void PrepareData(Vector &input, idx_t count, Vector &extra_state, UnifiedVectorFormat &result) { + OrderModifiers modifiers(OrderType::ASCENDING, OrderByNullType::NULLS_LAST); + CreateSortKeyHelpers::CreateSortKey(input, count, modifiers, extra_state); + input.Flatten(count); + extra_state.Flatten(count); + FlatVector::Validity(extra_state).Initialize(FlatVector::Validity(input)); + extra_state.ToUnifiedFormat(count, result); + } +}; + +} // namespace duckdb diff --git a/src/include/duckdb/core_functions/aggregate/nested_functions.hpp b/src/include/duckdb/core_functions/aggregate/nested_functions.hpp index b6511fec8c3..6635f6e9002 100644 --- a/src/include/duckdb/core_functions/aggregate/nested_functions.hpp +++ b/src/include/duckdb/core_functions/aggregate/nested_functions.hpp @@ -23,6 +23,7 @@ struct HistogramFun { static AggregateFunctionSet GetFunctions(); static AggregateFunction GetHistogramUnorderedMap(LogicalType &type); + static AggregateFunction BinnedHistogramFunction(); }; struct ListFun { diff --git a/src/include/duckdb/core_functions/aggregate/quantile_helpers.hpp b/src/include/duckdb/core_functions/aggregate/quantile_helpers.hpp new file mode 100644 index 00000000000..a2d41debadc --- /dev/null +++ b/src/include/duckdb/core_functions/aggregate/quantile_helpers.hpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/core_functions/aggregate/quantile_helpers.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/common.hpp" +#include "duckdb/core_functions/aggregate/quantile_enum.hpp" +#include "duckdb/core_functions/aggregate/holistic_functions.hpp" + +namespace duckdb { + +// Avoid using naked Values in inner loops... +struct QuantileValue { + explicit QuantileValue(const Value &v) : val(v), dbl(v.GetValue()) { + const auto &type = val.type(); + switch (type.id()) { + case LogicalTypeId::DECIMAL: { + integral = IntegralValue::Get(v); + scaling = Hugeint::POWERS_OF_TEN[DecimalType::GetScale(type)]; + break; + } + default: + break; + } + } + + Value val; + + // DOUBLE + double dbl; + + // DECIMAL + hugeint_t integral; + hugeint_t scaling; + + inline bool operator==(const QuantileValue &other) const { + return val == other.val; + } +}; + +struct QuantileBindData : public FunctionData { + QuantileBindData(); + explicit QuantileBindData(const Value &quantile_p); + explicit QuantileBindData(const vector &quantiles_p); + QuantileBindData(const QuantileBindData &other); + + unique_ptr Copy() const override; + bool Equals(const FunctionData &other_p) const override; + + static void Serialize(Serializer &serializer, const optional_ptr bind_data_p, + const AggregateFunction &function); + + static unique_ptr Deserialize(Deserializer &deserializer, AggregateFunction &function); + + vector quantiles; + vector order; + bool desc; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/core_functions/aggregate/quantile_sort_tree.hpp b/src/include/duckdb/core_functions/aggregate/quantile_sort_tree.hpp new file mode 100644 index 00000000000..c30822742c0 --- /dev/null +++ b/src/include/duckdb/core_functions/aggregate/quantile_sort_tree.hpp @@ -0,0 +1,340 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/core_functions/aggregate/quantile_sort_tree.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/core_functions/aggregate/quantile_helpers.hpp" +#include "duckdb/execution/merge_sort_tree.hpp" +#include "duckdb/common/operator/multiply.hpp" +#include +#include +#include +#include + +namespace duckdb { + +// Direct access +template +struct QuantileDirect { + using INPUT_TYPE = T; + using RESULT_TYPE = T; + + inline const INPUT_TYPE &operator()(const INPUT_TYPE &x) const { + return x; + } +}; + +// Indirect access +template +struct QuantileIndirect { + using INPUT_TYPE = idx_t; + using RESULT_TYPE = T; + const RESULT_TYPE *data; + + explicit QuantileIndirect(const RESULT_TYPE *data_p) : data(data_p) { + } + + inline RESULT_TYPE operator()(const idx_t &input) const { + return data[input]; + } +}; + +// Composed access +template +struct QuantileComposed { + using INPUT_TYPE = typename INNER::INPUT_TYPE; + using RESULT_TYPE = typename OUTER::RESULT_TYPE; + + const OUTER &outer; + const INNER &inner; + + explicit QuantileComposed(const OUTER &outer_p, const INNER &inner_p) : outer(outer_p), inner(inner_p) { + } + + inline RESULT_TYPE operator()(const idx_t &input) const { + return outer(inner(input)); + } +}; + +// Accessed comparison +template +struct QuantileCompare { + using INPUT_TYPE = typename ACCESSOR::INPUT_TYPE; + const ACCESSOR &accessor; + const bool desc; + explicit QuantileCompare(const ACCESSOR &accessor_p, bool desc_p) : accessor(accessor_p), desc(desc_p) { + } + + inline bool operator()(const INPUT_TYPE &lhs, const INPUT_TYPE &rhs) const { + const auto lval = accessor(lhs); + const auto rval = accessor(rhs); + + return desc ? (rval < lval) : (lval < rval); + } +}; + +struct CastInterpolation { + template + static inline TARGET_TYPE Cast(const INPUT_TYPE &src, Vector &result) { + return Cast::Operation(src); + } + template + static inline TARGET_TYPE Interpolate(const TARGET_TYPE &lo, const double d, const TARGET_TYPE &hi) { + const auto delta = hi - lo; + return UnsafeNumericCast(lo + delta * d); + } +}; + +template <> +interval_t CastInterpolation::Cast(const dtime_t &src, Vector &result); +template <> +double CastInterpolation::Interpolate(const double &lo, const double d, const double &hi); +template <> +dtime_t CastInterpolation::Interpolate(const dtime_t &lo, const double d, const dtime_t &hi); +template <> +timestamp_t CastInterpolation::Interpolate(const timestamp_t &lo, const double d, const timestamp_t &hi); +template <> +hugeint_t CastInterpolation::Interpolate(const hugeint_t &lo, const double d, const hugeint_t &hi); +template <> +interval_t CastInterpolation::Interpolate(const interval_t &lo, const double d, const interval_t &hi); +template <> +string_t CastInterpolation::Cast(const string_t &src, Vector &result); + +// Continuous interpolation +template +struct Interpolator { + Interpolator(const QuantileValue &q, const idx_t n_p, const bool desc_p) + : desc(desc_p), RN((double)(n_p - 1) * q.dbl), FRN(UnsafeNumericCast(floor(RN))), + CRN(UnsafeNumericCast(ceil(RN))), begin(0), end(n_p) { + } + + template > + TARGET_TYPE Interpolate(INPUT_TYPE lidx, INPUT_TYPE hidx, Vector &result, const ACCESSOR &accessor) const { + using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE; + if (lidx == hidx) { + return CastInterpolation::Cast(accessor(lidx), result); + } else { + auto lo = CastInterpolation::Cast(accessor(lidx), result); + auto hi = CastInterpolation::Cast(accessor(hidx), result); + return CastInterpolation::Interpolate(lo, RN - FRN, hi); + } + } + + template > + TARGET_TYPE Operation(INPUT_TYPE *v_t, Vector &result, const ACCESSOR &accessor = ACCESSOR()) const { + using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE; + QuantileCompare comp(accessor, desc); + if (CRN == FRN) { + std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp); + return CastInterpolation::Cast(accessor(v_t[FRN]), result); + } else { + std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp); + std::nth_element(v_t + FRN, v_t + CRN, v_t + end, comp); + auto lo = CastInterpolation::Cast(accessor(v_t[FRN]), result); + auto hi = CastInterpolation::Cast(accessor(v_t[CRN]), result); + return CastInterpolation::Interpolate(lo, RN - FRN, hi); + } + } + + template + inline TARGET_TYPE Extract(const INPUT_TYPE **dest, Vector &result) const { + if (CRN == FRN) { + return CastInterpolation::Cast(*dest[0], result); + } else { + auto lo = CastInterpolation::Cast(*dest[0], result); + auto hi = CastInterpolation::Cast(*dest[1], result); + return CastInterpolation::Interpolate(lo, RN - FRN, hi); + } + } + + const bool desc; + const double RN; + const idx_t FRN; + const idx_t CRN; + + idx_t begin; + idx_t end; +}; + +// Discrete "interpolation" +template <> +struct Interpolator { + static inline idx_t Index(const QuantileValue &q, const idx_t n) { + idx_t floored; + switch (q.val.type().id()) { + case LogicalTypeId::DECIMAL: { + // Integer arithmetic for accuracy + const auto integral = q.integral; + const auto scaling = q.scaling; + const auto scaled_q = + DecimalMultiplyOverflowCheck::Operation(Hugeint::Convert(n), integral); + const auto scaled_n = + DecimalMultiplyOverflowCheck::Operation(Hugeint::Convert(n), scaling); + floored = Cast::Operation((scaled_n - scaled_q) / scaling); + break; + } + default: + const auto scaled_q = (double)(n * q.dbl); + floored = UnsafeNumericCast(floor(n - scaled_q)); + break; + } + + return MaxValue(1, n - floored) - 1; + } + + Interpolator(const QuantileValue &q, const idx_t n_p, bool desc_p) + : desc(desc_p), FRN(Index(q, n_p)), CRN(FRN), begin(0), end(n_p) { + } + + template > + TARGET_TYPE Interpolate(INPUT_TYPE lidx, INPUT_TYPE hidx, Vector &result, const ACCESSOR &accessor) const { + using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE; + return CastInterpolation::Cast(accessor(lidx), result); + } + + template > + typename ACCESSOR::RESULT_TYPE InterpolateInternal(INPUT_TYPE *v_t, const ACCESSOR &accessor = ACCESSOR()) const { + QuantileCompare comp(accessor, desc); + std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp); + return accessor(v_t[FRN]); + } + + template > + TARGET_TYPE Operation(INPUT_TYPE *v_t, Vector &result, const ACCESSOR &accessor = ACCESSOR()) const { + using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE; + return CastInterpolation::Cast(InterpolateInternal(v_t, accessor), result); + } + + template + TARGET_TYPE Extract(const INPUT_TYPE **dest, Vector &result) const { + return CastInterpolation::Cast(*dest[0], result); + } + + const bool desc; + const idx_t FRN; + const idx_t CRN; + + idx_t begin; + idx_t end; +}; + +struct QuantileIncluded { + inline explicit QuantileIncluded(const ValidityMask &fmask_p, const ValidityMask &dmask_p) + : fmask(fmask_p), dmask(dmask_p) { + } + + inline bool operator()(const idx_t &idx) const { + return fmask.RowIsValid(idx) && dmask.RowIsValid(idx); + } + + inline bool AllValid() const { + return fmask.AllValid() && dmask.AllValid(); + } + + const ValidityMask &fmask; + const ValidityMask &dmask; +}; + +template +struct QuantileSortTree : public MergeSortTree { + + using BaseTree = MergeSortTree; + using Elements = typename BaseTree::Elements; + + explicit QuantileSortTree(Elements &&lowest_level) : BaseTree(std::move(lowest_level)) { + } + + template + static unique_ptr WindowInit(const INPUT_TYPE *data, AggregateInputData &aggr_input_data, + const ValidityMask &data_mask, const ValidityMask &filter_mask, + idx_t count) { + // Build the indirection array + using ElementType = typename QuantileSortTree::ElementType; + vector sorted(count); + if (filter_mask.AllValid() && data_mask.AllValid()) { + std::iota(sorted.begin(), sorted.end(), 0); + } else { + size_t valid = 0; + QuantileIncluded included(filter_mask, data_mask); + for (ElementType i = 0; i < count; ++i) { + if (included(i)) { + sorted[valid++] = i; + } + } + sorted.resize(valid); + } + + // Sort it + auto &bind_data = aggr_input_data.bind_data->Cast(); + using Accessor = QuantileIndirect; + Accessor indirect(data); + QuantileCompare cmp(indirect, bind_data.desc); + std::sort(sorted.begin(), sorted.end(), cmp); + + return make_uniq(std::move(sorted)); + } + + inline IDX SelectNth(const SubFrames &frames, size_t n) const { + return BaseTree::NthElement(BaseTree::SelectNth(frames, n)); + } + + template + RESULT_TYPE WindowScalar(const INPUT_TYPE *data, const SubFrames &frames, const idx_t n, Vector &result, + const QuantileValue &q) const { + D_ASSERT(n > 0); + + // Find the interpolated indicies within the frame + Interpolator interp(q, n, false); + const auto lo_data = SelectNth(frames, interp.FRN); + auto hi_data = lo_data; + if (interp.CRN != interp.FRN) { + hi_data = SelectNth(frames, interp.CRN); + } + + // Interpolate indirectly + using ID = QuantileIndirect; + ID indirect(data); + return interp.template Interpolate(lo_data, hi_data, result, indirect); + } + + template + void WindowList(const INPUT_TYPE *data, const SubFrames &frames, const idx_t n, Vector &list, const idx_t lidx, + const QuantileBindData &bind_data) const { + D_ASSERT(n > 0); + + // Result is a constant LIST with a fixed length + auto ldata = FlatVector::GetData(list); + auto &lentry = ldata[lidx]; + lentry.offset = ListVector::GetListSize(list); + lentry.length = bind_data.quantiles.size(); + + ListVector::Reserve(list, lentry.offset + lentry.length); + ListVector::SetListSize(list, lentry.offset + lentry.length); + auto &result = ListVector::GetEntry(list); + auto rdata = FlatVector::GetData(result); + + using ID = QuantileIndirect; + ID indirect(data); + for (const auto &q : bind_data.order) { + const auto &quantile = bind_data.quantiles[q]; + Interpolator interp(quantile, n, false); + + const auto lo_data = SelectNth(frames, interp.FRN); + auto hi_data = lo_data; + if (interp.CRN != interp.FRN) { + hi_data = SelectNth(frames, interp.CRN); + } + + // Interpolate indirectly + rdata[lentry.offset + q] = + interp.template Interpolate(lo_data, hi_data, result, indirect); + } + } +}; + +} // namespace duckdb diff --git a/src/include/duckdb/core_functions/aggregate/quantile_state.hpp b/src/include/duckdb/core_functions/aggregate/quantile_state.hpp new file mode 100644 index 00000000000..a46340955e9 --- /dev/null +++ b/src/include/duckdb/core_functions/aggregate/quantile_state.hpp @@ -0,0 +1,300 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/core_functions/aggregate/quantile_state.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/core_functions/aggregate/quantile_sort_tree.hpp" +#include "SkipList.h" + +namespace duckdb { + +struct QuantileOperation { + template + static void Initialize(STATE &state) { + new (&state) STATE(); + } + + template + static void ConstantOperation(STATE &state, const INPUT_TYPE &input, AggregateUnaryInput &unary_input, + idx_t count) { + for (idx_t i = 0; i < count; i++) { + Operation(state, input, unary_input); + } + } + + template + static void Operation(STATE &state, const INPUT_TYPE &input, AggregateUnaryInput &aggr_input) { + state.AddElement(input, aggr_input.input); + } + + template + static void Combine(const STATE &source, STATE &target, AggregateInputData &) { + if (source.v.empty()) { + return; + } + target.v.insert(target.v.end(), source.v.begin(), source.v.end()); + } + + template + static void Destroy(STATE &state, AggregateInputData &) { + state.~STATE(); + } + + static bool IgnoreNull() { + return true; + } + + template + static void WindowInit(AggregateInputData &aggr_input_data, const WindowPartitionInput &partition, + data_ptr_t g_state) { + D_ASSERT(partition.input_count == 1); + + auto inputs = partition.inputs; + const auto count = partition.count; + const auto &filter_mask = partition.filter_mask; + const auto &stats = partition.stats; + + // If frames overlap significantly, then use local skip lists. + if (stats[0].end <= stats[1].begin) { + // Frames can overlap + const auto overlap = double(stats[1].begin - stats[0].end); + const auto cover = double(stats[1].end - stats[0].begin); + const auto ratio = overlap / cover; + if (ratio > .75) { + return; + } + } + + const auto data = FlatVector::GetData(inputs[0]); + const auto &data_mask = FlatVector::Validity(inputs[0]); + + // Build the tree + auto &state = *reinterpret_cast(g_state); + auto &window_state = state.GetOrCreateWindowState(); + if (count < std::numeric_limits::max()) { + window_state.qst32 = QuantileSortTree::WindowInit(data, aggr_input_data, data_mask, + filter_mask, count); + } else { + window_state.qst64 = QuantileSortTree::WindowInit(data, aggr_input_data, data_mask, + filter_mask, count); + } + } + + static idx_t FrameSize(const QuantileIncluded &included, const SubFrames &frames) { + // Count the number of valid values + idx_t n = 0; + if (included.AllValid()) { + for (const auto &frame : frames) { + n += frame.end - frame.start; + } + } else { + // NULLs or FILTERed values, + for (const auto &frame : frames) { + for (auto i = frame.start; i < frame.end; ++i) { + n += included(i); + } + } + } + + return n; + } +}; + +template +struct PointerLess { + inline bool operator()(const T &lhi, const T &rhi) const { + return *lhi < *rhi; + } +}; + +template +struct WindowQuantileState { + // Windowed Quantile merge sort trees + using QuantileSortTree32 = QuantileSortTree; + using QuantileSortTree64 = QuantileSortTree; + unique_ptr qst32; + unique_ptr qst64; + + // Windowed Quantile skip lists + using PointerType = const INPUT_TYPE *; + using SkipListType = duckdb_skiplistlib::skip_list::HeadNode>; + SubFrames prevs; + unique_ptr s; + mutable vector dest; + + // Windowed MAD indirection + idx_t count; + vector m; + + WindowQuantileState() : count(0) { + } + + inline void SetCount(size_t count_p) { + count = count_p; + if (count >= m.size()) { + m.resize(count); + } + } + + inline SkipListType &GetSkipList(bool reset = false) { + if (reset || !s) { + s.reset(); + s = make_uniq(); + } + return *s; + } + + struct SkipListUpdater { + SkipListType &skip; + const INPUT_TYPE *data; + const QuantileIncluded &included; + + inline SkipListUpdater(SkipListType &skip, const INPUT_TYPE *data, const QuantileIncluded &included) + : skip(skip), data(data), included(included) { + } + + inline void Neither(idx_t begin, idx_t end) { + } + + inline void Left(idx_t begin, idx_t end) { + for (; begin < end; ++begin) { + if (included(begin)) { + skip.remove(data + begin); + } + } + } + + inline void Right(idx_t begin, idx_t end) { + for (; begin < end; ++begin) { + if (included(begin)) { + skip.insert(data + begin); + } + } + } + + inline void Both(idx_t begin, idx_t end) { + } + }; + + void UpdateSkip(const INPUT_TYPE *data, const SubFrames &frames, const QuantileIncluded &included) { + // No overlap, or no data + if (!s || prevs.back().end <= frames.front().start || frames.back().end <= prevs.front().start) { + auto &skip = GetSkipList(true); + for (const auto &frame : frames) { + for (auto i = frame.start; i < frame.end; ++i) { + if (included(i)) { + skip.insert(data + i); + } + } + } + } else { + auto &skip = GetSkipList(); + SkipListUpdater updater(skip, data, included); + AggregateExecutor::IntersectFrames(prevs, frames, updater); + } + } + + bool HasTrees() const { + return qst32 || qst64; + } + + template + RESULT_TYPE WindowScalar(const INPUT_TYPE *data, const SubFrames &frames, const idx_t n, Vector &result, + const QuantileValue &q) const { + D_ASSERT(n > 0); + if (qst32) { + return qst32->WindowScalar(data, frames, n, result, q); + } else if (qst64) { + return qst64->WindowScalar(data, frames, n, result, q); + } else if (s) { + // Find the position(s) needed + try { + Interpolator interp(q, s->size(), false); + s->at(interp.FRN, interp.CRN - interp.FRN + 1, dest); + return interp.template Extract(dest.data(), result); + } catch (const duckdb_skiplistlib::skip_list::IndexError &idx_err) { + throw InternalException(idx_err.message()); + } + } else { + throw InternalException("No accelerator for scalar QUANTILE"); + } + } + + template + void WindowList(const INPUT_TYPE *data, const SubFrames &frames, const idx_t n, Vector &list, const idx_t lidx, + const QuantileBindData &bind_data) const { + D_ASSERT(n > 0); + // Result is a constant LIST with a fixed length + auto ldata = FlatVector::GetData(list); + auto &lentry = ldata[lidx]; + lentry.offset = ListVector::GetListSize(list); + lentry.length = bind_data.quantiles.size(); + + ListVector::Reserve(list, lentry.offset + lentry.length); + ListVector::SetListSize(list, lentry.offset + lentry.length); + auto &result = ListVector::GetEntry(list); + auto rdata = FlatVector::GetData(result); + + for (const auto &q : bind_data.order) { + const auto &quantile = bind_data.quantiles[q]; + rdata[lentry.offset + q] = WindowScalar(data, frames, n, result, quantile); + } + } +}; + +struct QuantileStandardType { + template + static T Operation(T input, AggregateInputData &) { + return input; + } +}; + +struct QuantileStringType { + template + static T Operation(T input, AggregateInputData &input_data) { + if (input.IsInlined()) { + return input; + } + auto string_data = input_data.allocator.Allocate(input.GetSize()); + memcpy(string_data, input.GetData(), input.GetSize()); + return string_t(char_ptr_cast(string_data), UnsafeNumericCast(input.GetSize())); + } +}; + +template +struct QuantileState { + using InputType = INPUT_TYPE; + + // Regular aggregation + vector v; + + // Window Quantile State + unique_ptr> window_state; + + void AddElement(INPUT_TYPE element, AggregateInputData &aggr_input) { + v.emplace_back(TYPE_OP::Operation(element, aggr_input)); + } + + bool HasTrees() const { + return window_state && window_state->HasTrees(); + } + WindowQuantileState &GetOrCreateWindowState() { + if (!window_state) { + window_state = make_uniq>(); + } + return *window_state; + } + WindowQuantileState &GetWindowState() { + return *window_state; + } + const WindowQuantileState &GetWindowState() const { + return *window_state; + } +}; + +} // namespace duckdb diff --git a/src/include/duckdb/core_functions/aggregate/regression/regr_slope.hpp b/src/include/duckdb/core_functions/aggregate/regression/regr_slope.hpp index 0563a9a5ed7..7010504190a 100644 --- a/src/include/duckdb/core_functions/aggregate/regression/regr_slope.hpp +++ b/src/include/duckdb/core_functions/aggregate/regression/regr_slope.hpp @@ -26,7 +26,7 @@ struct RegrSlopeOperation { template static void Operation(STATE &state, const A_TYPE &y, const B_TYPE &x, AggregateBinaryInput &idata) { - CovarOperation::Operation(state.cov_pop, y, x,idata); + CovarOperation::Operation(state.cov_pop, y, x, idata); STDDevBaseOperation::Execute(state.var_pop, x); } diff --git a/src/include/duckdb/core_functions/aggregate/sort_key_helpers.hpp b/src/include/duckdb/core_functions/aggregate/sort_key_helpers.hpp new file mode 100644 index 00000000000..12798ae3de4 --- /dev/null +++ b/src/include/duckdb/core_functions/aggregate/sort_key_helpers.hpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/core_functions/aggregate/sort_key_helpers.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/common.hpp" +#include "duckdb/core_functions/create_sort_key.hpp" + +namespace duckdb { + +struct AggregateSortKeyHelpers { + template + static void UnaryUpdate(Vector inputs[], AggregateInputData &input_data, idx_t input_count, Vector &state_vector, + idx_t count) { + D_ASSERT(input_count == 1); + auto &input = inputs[0]; + + Vector sort_key(LogicalType::BLOB); + auto modifiers = OrderModifiers(ORDER_TYPE, OrderByNullType::NULLS_LAST); + CreateSortKeyHelpers::CreateSortKey(input, count, modifiers, sort_key); + + UnifiedVectorFormat idata; + if (IGNORE_NULLS) { + input.ToUnifiedFormat(count, idata); + } + + UnifiedVectorFormat kdata; + sort_key.ToUnifiedFormat(count, kdata); + + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); + + auto key_data = UnifiedVectorFormat::GetData(kdata); + auto states = UnifiedVectorFormat::GetData(sdata); + for (idx_t i = 0; i < count; i++) { + const auto sidx = sdata.sel->get_index(i); + if (IGNORE_NULLS) { + auto idx = idata.sel->get_index(i); + if (!idata.validity.RowIsValid(idx)) { + continue; + } + } + const auto key_idx = kdata.sel->get_index(i); + auto &state = *states[sidx]; + OP::template Execute(state, key_data[key_idx], input_data); + } + } +}; + +} // namespace duckdb diff --git a/src/include/duckdb/core_functions/create_sort_key.hpp b/src/include/duckdb/core_functions/create_sort_key.hpp new file mode 100644 index 00000000000..d8c49277f80 --- /dev/null +++ b/src/include/duckdb/core_functions/create_sort_key.hpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/core_functions/create_sort_key.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/function/function_set.hpp" + +namespace duckdb { + +struct OrderModifiers { + OrderModifiers(OrderType order_type, OrderByNullType null_type) : order_type(order_type), null_type(null_type) { + } + + OrderType order_type; + OrderByNullType null_type; + + bool operator==(const OrderModifiers &other) const { + return order_type == other.order_type && null_type == other.null_type; + } + + static OrderModifiers Parse(const string &val) { + auto lcase = StringUtil::Replace(StringUtil::Lower(val), "_", " "); + OrderType order_type; + if (StringUtil::StartsWith(lcase, "asc")) { + order_type = OrderType::ASCENDING; + } else if (StringUtil::StartsWith(lcase, "desc")) { + order_type = OrderType::DESCENDING; + } else { + throw BinderException("create_sort_key modifier must start with either ASC or DESC"); + } + OrderByNullType null_type; + if (StringUtil::EndsWith(lcase, "nulls first")) { + null_type = OrderByNullType::NULLS_FIRST; + } else if (StringUtil::EndsWith(lcase, "nulls last")) { + null_type = OrderByNullType::NULLS_LAST; + } else { + throw BinderException("create_sort_key modifier must end with either NULLS FIRST or NULLS LAST"); + } + return OrderModifiers(order_type, null_type); + } +}; + +struct CreateSortKeyHelpers { + static void CreateSortKey(Vector &input, idx_t input_count, OrderModifiers modifiers, Vector &result); + static void DecodeSortKey(string_t sort_key, Vector &result, idx_t result_idx, OrderModifiers modifiers); +}; + +} // namespace duckdb diff --git a/src/include/duckdb/core_functions/scalar/date_functions.hpp b/src/include/duckdb/core_functions/scalar/date_functions.hpp index 2074da5f066..1d072300930 100644 --- a/src/include/duckdb/core_functions/scalar/date_functions.hpp +++ b/src/include/duckdb/core_functions/scalar/date_functions.hpp @@ -363,6 +363,15 @@ struct MonthNameFun { static ScalarFunctionSet GetFunctions(); }; +struct NanosecondsFun { + static constexpr const char *Name = "nanosecond"; + static constexpr const char *Parameters = "tsns"; + static constexpr const char *Description = "Extract the nanosecond component from a date or timestamp"; + static constexpr const char *Example = "nanosecond(timestamp_ns '2021-08-03 11:59:44.123456789') => 44123456789"; + + static ScalarFunctionSet GetFunctions(); +}; + struct QuarterFun { static constexpr const char *Name = "quarter"; static constexpr const char *Parameters = "ts"; @@ -435,6 +444,15 @@ struct TimezoneMinuteFun { static ScalarFunctionSet GetFunctions(); }; +struct TimeTZSortKeyFun { + static constexpr const char *Name = "timetz_byte_comparable"; + static constexpr const char *Parameters = "time_tz"; + static constexpr const char *Description = "Converts a TIME WITH TIME ZONE to an integer sort key"; + static constexpr const char *Example = "timetz_byte_comparable('18:18:16.21-07:00'::TIME_TZ)"; + + static ScalarFunction GetFunction(); +}; + struct ToCenturiesFun { static constexpr const char *Name = "to_centuries"; static constexpr const char *Parameters = "integer"; @@ -516,6 +534,15 @@ struct ToMonthsFun { static ScalarFunction GetFunction(); }; +struct ToQuartersFun { + static constexpr const char *Name = "to_quarters"; + static constexpr const char *Parameters = "integer"; + static constexpr const char *Description = "Construct a quarter interval"; + static constexpr const char *Example = "to_quarters(5)"; + + static ScalarFunction GetFunction(); +}; + struct ToSecondsFun { static constexpr const char *Name = "to_seconds"; static constexpr const char *Parameters = "double"; diff --git a/src/include/duckdb/core_functions/scalar/generic_functions.hpp b/src/include/duckdb/core_functions/scalar/generic_functions.hpp index 970e61954de..48af1ce5d21 100644 --- a/src/include/duckdb/core_functions/scalar/generic_functions.hpp +++ b/src/include/duckdb/core_functions/scalar/generic_functions.hpp @@ -87,6 +87,15 @@ struct TypeOfFun { static ScalarFunction GetFunction(); }; +struct CanCastImplicitlyFun { + static constexpr const char *Name = "can_cast_implicitly"; + static constexpr const char *Parameters = "source_type,target_type"; + static constexpr const char *Description = "Whether or not we can implicitly cast from the source type to the other type"; + static constexpr const char *Example = "can_implicitly_cast(NULL::INTEGER, NULL::BIGINT)"; + + static ScalarFunction GetFunction(); +}; + struct CurrentQueryFun { static constexpr const char *Name = "current_query"; static constexpr const char *Parameters = ""; @@ -150,4 +159,13 @@ struct VersionFun { static ScalarFunction GetFunction(); }; +struct EquiWidthBinsFun { + static constexpr const char *Name = "equi_width_bins"; + static constexpr const char *Parameters = "min,max,bin_count,nice_rounding"; + static constexpr const char *Description = "Generates bin_count equi-width bins between the min and max. If enabled nice_rounding makes the numbers more readable/less jagged"; + static constexpr const char *Example = "equi_width_bins(0, 10, 2, true)"; + + static ScalarFunctionSet GetFunctions(); +}; + } // namespace duckdb diff --git a/src/include/duckdb/execution/adaptive_filter.hpp b/src/include/duckdb/execution/adaptive_filter.hpp index 61bd50c0e74..f93891b9fad 100644 --- a/src/include/duckdb/execution/adaptive_filter.hpp +++ b/src/include/duckdb/execution/adaptive_filter.hpp @@ -9,6 +9,7 @@ #pragma once #include "duckdb/planner/expression/list.hpp" +#include "duckdb/planner/table_filter.hpp" #include namespace duckdb { diff --git a/src/include/duckdb/execution/aggregate_hashtable.hpp b/src/include/duckdb/execution/aggregate_hashtable.hpp index 797e96ca949..2b424152f2c 100644 --- a/src/include/duckdb/execution/aggregate_hashtable.hpp +++ b/src/include/duckdb/execution/aggregate_hashtable.hpp @@ -11,6 +11,7 @@ #include "duckdb/common/row_operations/row_matcher.hpp" #include "duckdb/common/types/row/partitioned_tuple_data.hpp" #include "duckdb/execution/base_aggregate_hashtable.hpp" +#include "duckdb/execution/ht_entry.hpp" #include "duckdb/storage/arena_allocator.hpp" #include "duckdb/storage/buffer/buffer_handle.hpp" @@ -29,53 +30,6 @@ struct FlushMoveState; stores them in the HT. It uses linear probing for collision resolution. */ -struct aggr_ht_entry_t { // NOLINT -public: - explicit aggr_ht_entry_t(hash_t value_p) : value(value_p) { - } - - inline bool IsOccupied() const { - return value != 0; - } - - inline data_ptr_t GetPointer() const { - D_ASSERT(IsOccupied()); - return reinterpret_cast(value & POINTER_MASK); - } - inline void SetPointer(const data_ptr_t &pointer) { - // Pointer shouldn't use upper bits - D_ASSERT((reinterpret_cast(pointer) & SALT_MASK) == 0); - // Value should have all 1's in the pointer area - D_ASSERT((value & POINTER_MASK) == POINTER_MASK); - // Set upper bits to 1 in pointer so the salt stays intact - value &= reinterpret_cast(pointer) | SALT_MASK; - } - - static inline hash_t ExtractSalt(const hash_t &hash) { - // Leaves upper bits intact, sets lower bits to all 1's - return hash | POINTER_MASK; - } - inline hash_t GetSalt() const { - return ExtractSalt(value); - } - inline void SetSalt(const hash_t &salt) { - // Shouldn't be occupied when we set this - D_ASSERT(!IsOccupied()); - // Salt should have all 1's in the pointer field - D_ASSERT((salt & POINTER_MASK) == POINTER_MASK); - // No need to mask, just put the whole thing there - value = salt; - } - -private: - //! Upper 16 bits are salt - static constexpr const hash_t SALT_MASK = 0xFFFF000000000000; - //! Lower 48 bits are the pointer - static constexpr const hash_t POINTER_MASK = 0x0000FFFFFFFFFFFF; - - hash_t value; -}; - class GroupedAggregateHashTable : public BaseAggregateHashTable { public: GroupedAggregateHashTable(ClientContext &context, Allocator &allocator, vector group_types, @@ -178,7 +132,7 @@ class GroupedAggregateHashTable : public BaseAggregateHashTable { idx_t capacity; //! The hash map (pointer table) of the HT: allocated data and pointer into it AllocatedData hash_map; - aggr_ht_entry_t *entries; + ht_entry_t *entries; //! Offset of the hash column in the rows idx_t hash_offset; //! Bitmask for getting relevant bits from the hashes to determine the position diff --git a/src/include/duckdb/execution/executor.hpp b/src/include/duckdb/execution/executor.hpp index 05a40cb9d7e..7e3074250a8 100644 --- a/src/include/duckdb/execution/executor.hpp +++ b/src/include/duckdb/execution/executor.hpp @@ -16,6 +16,8 @@ #include "duckdb/execution/task_error_manager.hpp" #include "duckdb/parallel/pipeline.hpp" +#include + namespace duckdb { class ClientContext; class DataChunk; @@ -49,6 +51,8 @@ class Executor { void CancelTasks(); PendingExecutionResult ExecuteTask(bool dry_run = false); + void WaitForTask(); + void SignalTaskRescheduled(lock_guard &); void Reset(); @@ -107,6 +111,7 @@ class Executor { } private: + //! Check if the streaming query result is waiting to be fetched from, must hold the 'executor_lock' bool ResultCollectorIsBlocked(); void InitializeInternal(PhysicalOperator &physical_plan); @@ -164,6 +169,8 @@ class Executor { //! Task that have been descheduled unordered_map> to_be_rescheduled_tasks; + //! The semaphore to signal task rescheduling + std::condition_variable task_reschedule; //! Currently alive executor tasks atomic executor_tasks; diff --git a/src/include/duckdb/execution/expression_executor.hpp b/src/include/duckdb/execution/expression_executor.hpp index 804c6f25ad2..80c380d682c 100644 --- a/src/include/duckdb/execution/expression_executor.hpp +++ b/src/include/duckdb/execution/expression_executor.hpp @@ -20,7 +20,7 @@ class ExecutionContext; //! ExpressionExecutor is responsible for executing a set of expressions and storing the result in a data chunk class ExpressionExecutor { - friend class Index; + friend class BoundIndex; friend class CreateIndexLocalSinkState; public: diff --git a/src/include/duckdb/execution/ht_entry.hpp b/src/include/duckdb/execution/ht_entry.hpp new file mode 100644 index 00000000000..43483eaf682 --- /dev/null +++ b/src/include/duckdb/execution/ht_entry.hpp @@ -0,0 +1,94 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/ht_entry.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +namespace duckdb { + +//! The ht_entry_t struct represents an individual entry within a hash table. +/*! + This struct is used by the JoinHashTable and AggregateHashTable to store entries within the hash table. It stores + a pointer to the data and a salt value in a single hash_t and can return or modify the pointer and salt + individually. +*/ +struct ht_entry_t { // NOLINT +public: + //! Upper 16 bits are salt + static constexpr const duckdb::hash_t SALT_MASK = 0xFFFF000000000000; + //! Lower 48 bits are the pointer + static constexpr const duckdb::hash_t POINTER_MASK = 0x0000FFFFFFFFFFFF; + + explicit inline ht_entry_t(duckdb::hash_t value_p) : value(value_p) { + } + + // Add a default constructor for 32-bit linux test case + ht_entry_t() : value(0) { + } + + inline bool IsOccupied() const { + return value != 0; + } + + // Returns a pointer based on the stored value without checking cell occupancy. + // This can return a nullptr if the cell is not occupied. + inline duckdb::data_ptr_t GetPointerOrNull() const { + return reinterpret_cast(value & POINTER_MASK); + } + + // Returns a pointer based on the stored value if the cell is occupied + inline duckdb::data_ptr_t GetPointer() const { + D_ASSERT(IsOccupied()); + return reinterpret_cast(value & POINTER_MASK); + } + + inline void SetPointer(const duckdb::data_ptr_t &pointer) { + // Pointer shouldn't use upper bits + D_ASSERT((reinterpret_cast(pointer) & SALT_MASK) == 0); + // Value should have all 1's in the pointer area + D_ASSERT((value & POINTER_MASK) == POINTER_MASK); + // Set upper bits to 1 in pointer so the salt stays intact + value &= reinterpret_cast(pointer) | SALT_MASK; + } + + // Returns the salt, leaves upper salt bits intact, sets lower bits to all 1's + static inline duckdb::hash_t ExtractSalt(const duckdb::hash_t &hash) { + return hash | POINTER_MASK; + } + + // Returns the salt, leaves upper salt bits intact, sets lower bits to all 0's + static inline duckdb::hash_t ExtractSaltWithNulls(const duckdb::hash_t &hash) { + return hash & SALT_MASK; + } + + inline duckdb::hash_t GetSalt() const { + return ExtractSalt(value); + } + + inline void SetSalt(const duckdb::hash_t &salt) { + // Shouldn't be occupied when we set this + D_ASSERT(!IsOccupied()); + // Salt should have all 1's in the pointer field + D_ASSERT((salt & POINTER_MASK) == POINTER_MASK); + // No need to mask, just put the whole thing there + value = salt; + } + + static inline ht_entry_t GetDesiredEntry(const duckdb::data_ptr_t &pointer, const duckdb::hash_t &salt) { + auto desired = reinterpret_cast(pointer) | (salt & SALT_MASK); + return ht_entry_t(desired); + } + + static inline ht_entry_t GetEmptyEntry() { + return ht_entry_t(0); + } + +private: + duckdb::hash_t value; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/execution/index/art/art.hpp b/src/include/duckdb/execution/index/art/art.hpp index 8a4daf659ba..041e514aaa9 100644 --- a/src/include/duckdb/execution/index/art/art.hpp +++ b/src/include/duckdb/execution/index/art/art.hpp @@ -8,7 +8,7 @@ #pragma once -#include "duckdb/storage/index.hpp" +#include "duckdb/execution/index/bound_index.hpp" #include "duckdb/execution/index/art/node.hpp" #include "duckdb/common/array.hpp" @@ -31,7 +31,7 @@ struct ARTFlags { vector merge_buffer_counts; }; -class ART : public Index { +class ART : public BoundIndex { public: // Index type name for the ART static constexpr const char *TYPE_NAME = "ART"; @@ -64,7 +64,7 @@ class ART : public Index { public: //! Create a index instance of this type - static unique_ptr Create(CreateIndexInput &input) { + static unique_ptr Create(CreateIndexInput &input) { auto art = make_uniq(input.name, input.constraint_type, input.column_ids, input.table_io_manager, input.unbound_expressions, input.db, nullptr, input.storage_info); return std::move(art); @@ -81,22 +81,20 @@ class ART : public Index { //! Delete a chunk of entries from the index. The lock obtained from InitializeLock must be held void Delete(IndexLock &lock, DataChunk &entries, Vector &row_identifiers) override; //! Insert a chunk of entries into the index - ErrorData Insert(IndexLock &lock, DataChunk &data, Vector &row_ids) override; + ErrorData Insert(IndexLock &lock, DataChunk &data, Vector &row_identifiers) override; //! Construct an ART from a vector of sorted keys bool ConstructFromSorted(idx_t count, vector &keys, Vector &row_identifiers); //! Search equal values and fetches the row IDs bool SearchEqual(ARTKey &key, idx_t max_count, vector &result_ids); - //! Search equal values used for joins that do not need to fetch data - void SearchEqualJoinNoFetch(ARTKey &key, idx_t &result_size); //! Returns all ART storage information for serialization IndexStorageInfo GetStorageInfo(const bool get_buffers) override; //! Merge another index into this index. The lock obtained from InitializeLock must be held, and the other //! index must also be locked during the merge - bool MergeIndexes(IndexLock &state, Index &other_index) override; + bool MergeIndexes(IndexLock &state, BoundIndex &other_index) override; //! Traverses an ART and vacuums the qualifying nodes. The lock obtained from InitializeLock must be held void Vacuum(IndexLock &state) override; @@ -105,6 +103,7 @@ class ART : public Index { idx_t GetInMemorySize(IndexLock &index_lock) override; //! Generate ART keys for an input chunk + template static void GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector &keys); //! Generate a string containing all the expressions and their respective values that violate a constraint @@ -163,4 +162,10 @@ class ART : public Index { DataChunk &input) override; }; +template <> +void ART::GenerateKeys<>(ArenaAllocator &allocator, DataChunk &input, vector &keys); + +template <> +void ART::GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector &keys); + } // namespace duckdb diff --git a/src/include/duckdb/execution/index/bound_index.hpp b/src/include/duckdb/execution/index/bound_index.hpp new file mode 100644 index 00000000000..20e26891129 --- /dev/null +++ b/src/include/duckdb/execution/index/bound_index.hpp @@ -0,0 +1,145 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/index.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/enums/index_constraint_type.hpp" +#include "duckdb/common/types/constraint_conflict_info.hpp" +#include "duckdb/common/types/data_chunk.hpp" +#include "duckdb/common/unordered_set.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/parser/parsed_expression.hpp" +#include "duckdb/planner/expression.hpp" +#include "duckdb/storage/table_storage_info.hpp" +#include "duckdb/storage/index.hpp" + +namespace duckdb { + +class ClientContext; +class TableIOManager; +class Transaction; +class ConflictManager; + +struct IndexLock; +struct IndexScanState; + +//! The index is an abstract base class that serves as the basis for indexes +class BoundIndex : public Index { +public: + BoundIndex(const string &name, const string &index_type, IndexConstraintType index_constraint_type, + const vector &column_ids, TableIOManager &table_io_manager, + const vector> &unbound_expressions, AttachedDatabase &db); + + //! The physical types stored in the index + vector types; + //! The logical types of the expressions + vector logical_types; + + //! The name of the index + string name; + //! The index type (ART, B+-tree, Skip-List, ...) + string index_type; + //! The index constraint type + IndexConstraintType index_constraint_type; + +public: + bool IsBound() const override { + return true; + } + + const string &GetIndexType() const override { + return index_type; + } + + const string &GetIndexName() const override { + return name; + } + + IndexConstraintType GetConstraintType() const override { + return index_constraint_type; + } + +public: // Index interface + //! Obtain a lock on the index + void InitializeLock(IndexLock &state); + //! Called when data is appended to the index. The lock obtained from InitializeLock must be held + virtual ErrorData Append(IndexLock &state, DataChunk &entries, Vector &row_identifiers) = 0; + //! Obtains a lock and calls Append while holding that lock + ErrorData Append(DataChunk &entries, Vector &row_identifiers); + //! Verify that data can be appended to the index without a constraint violation + virtual void VerifyAppend(DataChunk &chunk) = 0; + //! Verify that data can be appended to the index without a constraint violation using the conflict manager + virtual void VerifyAppend(DataChunk &chunk, ConflictManager &conflict_manager) = 0; + //! Performs constraint checking for a chunk of input data + virtual void CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_manager) = 0; + + //! Deletes all data from the index. The lock obtained from InitializeLock must be held + virtual void CommitDrop(IndexLock &index_lock) = 0; + //! Deletes all data from the index + void CommitDrop() override; + //! Delete a chunk of entries from the index. The lock obtained from InitializeLock must be held + virtual void Delete(IndexLock &state, DataChunk &entries, Vector &row_identifiers) = 0; + //! Obtains a lock and calls Delete while holding that lock + void Delete(DataChunk &entries, Vector &row_identifiers); + + //! Insert a chunk of entries into the index + virtual ErrorData Insert(IndexLock &lock, DataChunk &input, Vector &row_identifiers) = 0; + + //! Merge another index into this index. The lock obtained from InitializeLock must be held, and the other + //! index must also be locked during the merge + virtual bool MergeIndexes(IndexLock &state, BoundIndex &other_index) = 0; + //! Obtains a lock and calls MergeIndexes while holding that lock + bool MergeIndexes(BoundIndex &other_index); + + //! Traverses an ART and vacuums the qualifying nodes. The lock obtained from InitializeLock must be held + virtual void Vacuum(IndexLock &state) = 0; + //! Obtains a lock and calls Vacuum while holding that lock + void Vacuum(); + + //! Returns the in-memory usage of the index. The lock obtained from InitializeLock must be held + virtual idx_t GetInMemorySize(IndexLock &state) = 0; + //! Returns the in-memory usage of the index + idx_t GetInMemorySize(); + + //! Returns the string representation of an index, or only traverses and verifies the index + virtual string VerifyAndToString(IndexLock &state, const bool only_verify) = 0; + //! Obtains a lock and calls VerifyAndToString while holding that lock + string VerifyAndToString(const bool only_verify); + + //! Returns true if the index is affected by updates on the specified column IDs, and false otherwise + bool IndexIsUpdated(const vector &column_ids) const; + + //! Returns all index storage information for serialization + virtual IndexStorageInfo GetStorageInfo(const bool get_buffers); + + //! Execute the index expressions on an input chunk + void ExecuteExpressions(DataChunk &input, DataChunk &result); + static string AppendRowError(DataChunk &input, idx_t index); + + //! Throw a constraint violation exception + virtual string GetConstraintViolationMessage(VerifyExistenceType verify_type, idx_t failed_index, + DataChunk &input) = 0; + + vector> unbound_expressions; + +protected: + //! Lock used for any changes to the index + mutex lock; + + //! Bound expressions used during expression execution + vector> bound_expressions; + +private: + //! Expression executor to execute the index expressions + ExpressionExecutor executor; + + //! Bind the unbound expressions of the index + unique_ptr BindExpression(unique_ptr expr); +}; + +} // namespace duckdb diff --git a/src/include/duckdb/execution/index/index_type.hpp b/src/include/duckdb/execution/index/index_type.hpp index a2eb16d2301..3417b15ea84 100644 --- a/src/include/duckdb/execution/index/index_type.hpp +++ b/src/include/duckdb/execution/index/index_type.hpp @@ -17,7 +17,7 @@ namespace duckdb { -class Index; +class BoundIndex; enum class IndexConstraintType : uint8_t; class Expression; class TableIOManager; @@ -43,7 +43,7 @@ struct CreateIndexInput { options(options) {}; }; -typedef unique_ptr (*index_create_function_t)(CreateIndexInput &input); +typedef unique_ptr (*index_create_function_t)(CreateIndexInput &input); //! A index "type" class IndexType { public: diff --git a/src/include/duckdb/execution/index/unbound_index.hpp b/src/include/duckdb/execution/index/unbound_index.hpp new file mode 100644 index 00000000000..1c7f859ea09 --- /dev/null +++ b/src/include/duckdb/execution/index/unbound_index.hpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/index/unbound_index.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/storage/index.hpp" +#include "duckdb/parser/parsed_data/create_index_info.hpp" + +namespace duckdb { + +class UnboundIndex final : public Index { +private: + // The create info of the index + unique_ptr create_info; + + // The serialized storage info of the index + IndexStorageInfo storage_info; + +public: + UnboundIndex(unique_ptr create_info, IndexStorageInfo storage_info, TableIOManager &table_io_manager, + AttachedDatabase &db); + + bool IsBound() const override { + return false; + } + + const string &GetIndexType() const override { + return GetCreateInfo().index_type; + } + + const string &GetIndexName() const override { + return GetCreateInfo().index_name; + } + + IndexConstraintType GetConstraintType() const override { + return GetCreateInfo().constraint_type; + } + + const CreateIndexInfo &GetCreateInfo() const { + return create_info->Cast(); + } + + const IndexStorageInfo &GetStorageInfo() const { + return storage_info; + } + + const vector> &GetParsedExpressions() const { + return GetCreateInfo().parsed_expressions; + } + + const string &GetTableName() const { + return GetCreateInfo().table; + } + + void CommitDrop() override; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/execution/index/unknown_index.hpp b/src/include/duckdb/execution/index/unknown_index.hpp deleted file mode 100644 index ac16846e0e4..00000000000 --- a/src/include/duckdb/execution/index/unknown_index.hpp +++ /dev/null @@ -1,65 +0,0 @@ -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/index/unknown_index.hpp -// -// -//===----------------------------------------------------------------------===// - -#pragma once - -#include "duckdb/storage/index.hpp" -#include "duckdb/parser/parsed_data/create_index_info.hpp" - -namespace duckdb { - -// An unknown index is an index that has been created by an extension, which has not been loaded yet. -// It is used as a placeholder for the index until the extension is loaded, at which point the extension will replace -// all recognized unknown indexes with the correct index type. -// Calling any function on an unknown index will throw a NotImplementedException -class UnknownIndex final : public Index { -private: - CreateIndexInfo create_info; - IndexStorageInfo storage_info; - string GenerateErrorMessage() const; - -public: - UnknownIndex(const string &name, const string &index_type, IndexConstraintType index_constraint_type, - const vector &column_ids, TableIOManager &table_io_manager, - const vector> &unbound_expressions, AttachedDatabase &db, - const CreateIndexInfo &create_info, IndexStorageInfo storage_info); - - const CreateIndexInfo &GetCreateInfo() const { - return create_info; - } - const IndexStorageInfo &GetStorageInfo() const { - return storage_info; - } - const string &GetIndexType() { - return create_info.index_type; - } - -public: - bool IsUnknown() override { - return true; - } - - // Index interface (unused) - - ErrorData Append(IndexLock &lock, DataChunk &entries, Vector &row_identifiers) override; - void VerifyAppend(DataChunk &chunk) override; - void VerifyAppend(DataChunk &chunk, ConflictManager &conflict_manager) override; - void CommitDrop(IndexLock &index_lock) override; - void Delete(IndexLock &lock, DataChunk &entries, Vector &row_identifiers) override; - ErrorData Insert(IndexLock &lock, DataChunk &data, Vector &row_ids) override; - IndexStorageInfo GetStorageInfo(bool get_buffers) override; - bool MergeIndexes(IndexLock &state, Index &other_index) override; - void Vacuum(IndexLock &state) override; - idx_t GetInMemorySize(IndexLock &index_lock) override; - void CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_manager) override; - string VerifyAndToString(IndexLock &state, bool only_verify) override; - string GetConstraintViolationMessage(VerifyExistenceType verify_type, idx_t failed_index, - DataChunk &input) override; -}; - -} // namespace duckdb diff --git a/src/include/duckdb/execution/join_hashtable.hpp b/src/include/duckdb/execution/join_hashtable.hpp index b4910a55422..b5af73a8a77 100644 --- a/src/include/duckdb/execution/join_hashtable.hpp +++ b/src/include/duckdb/execution/join_hashtable.hpp @@ -17,6 +17,7 @@ #include "duckdb/common/types/row/tuple_data_layout.hpp" #include "duckdb/common/types/vector.hpp" #include "duckdb/execution/aggregate_hashtable.hpp" +#include "duckdb/execution/ht_entry.hpp" #include "duckdb/planner/operator/logical_comparison_join.hpp" #include "duckdb/storage/storage_info.hpp" @@ -60,15 +61,23 @@ class JoinHashTable { public: using ValidityBytes = TemplatedValidityMask; + // only compare salts with the ht entries if the capacity is larger than 8192 so + // that it does not fit into the CPU cache + static constexpr const idx_t USE_SALT_THRESHOLD = 8192; + //! Scan structure that can be used to resume scans, as a single probe can //! return 1024*N values (where N is the size of the HT). This is //! returned by the JoinHashTable::Scan function and can be used to resume a //! probe. struct ScanStructure { TupleDataChunkState &key_state; + //! Directly point to the entry in the hash table Vector pointers; idx_t count; SelectionVector sel_vector; + SelectionVector chain_match_sel_vector; + SelectionVector chain_no_match_sel_vector; + // whether or not the given tuple has found a match unsafe_unique_array found_match; JoinHashTable &ht; @@ -78,7 +87,7 @@ class JoinHashTable { //! Get the next batch of data from the scan structure void Next(DataChunk &keys, DataChunk &left, DataChunk &result); //! Are pointer chains all pointing to NULL? - bool PointersExhausted(); + bool PointersExhausted() const; private: //! Next operator for the inner join @@ -87,6 +96,8 @@ class JoinHashTable { void NextSemiJoin(DataChunk &keys, DataChunk &left, DataChunk &result); //! Next operator for the anti join void NextAntiJoin(DataChunk &keys, DataChunk &left, DataChunk &result); + //! Next operator for the RIGHT semi and anti join + void NextRightSemiOrAntiJoin(DataChunk &keys, DataChunk &left, DataChunk &result); //! Next operator for the left outer join void NextLeftJoin(DataChunk &keys, DataChunk &left, DataChunk &result); //! Next operator for the mark join @@ -105,7 +116,6 @@ class JoinHashTable { idx_t ScanInnerJoin(DataChunk &keys, SelectionVector &result_vector); public: - void InitializeSelectionVector(const SelectionVector *¤t_sel); void AdvancePointers(); void AdvancePointers(const SelectionVector &sel, idx_t sel_count); void GatherResult(Vector &result, const SelectionVector &result_vector, const SelectionVector &sel_vector, @@ -115,6 +125,38 @@ class JoinHashTable { }; public: + struct SharedState { + + SharedState(); + + // The ptrs to the row to which a key should be inserted into during building + // or matched against during probing + Vector rhs_row_locations; + + SelectionVector salt_match_sel; + SelectionVector key_no_match_sel; + }; + + struct ProbeState : SharedState { + + ProbeState(); + + Vector salt_v; + Vector ht_offsets_v; + Vector ht_offsets_dense_v; + + SelectionVector non_empty_sel; + }; + + struct InsertState : SharedState { + InsertState(const unique_ptr &data_collection, + const vector &equality_predicate_columns); + /// Because of the index hick up + SelectionVector remaining_sel; + SelectionVector key_match_sel; + TupleDataChunkState chunk_state; + }; + JoinHashTable(BufferManager &buffer_manager, const vector &conditions, vector build_types, JoinType type, const vector &output_columns); ~JoinHashTable(); @@ -132,8 +174,8 @@ class JoinHashTable { //! ever called. void Finalize(idx_t chunk_idx_from, idx_t chunk_idx_to, bool parallel); //! Probe the HT with the given input chunk, resulting in the given result - unique_ptr Probe(DataChunk &keys, TupleDataChunkState &key_state, - Vector *precomputed_hashes = nullptr); + unique_ptr Probe(DataChunk &keys, TupleDataChunkState &key_state, ProbeState &probe_state, + optional_ptr precomputed_hashes = nullptr); //! Scan the HT to construct the full outer join result void ScanFullOuter(JoinHTScanState &state, Vector &addresses, DataChunk &result); @@ -167,18 +209,38 @@ class JoinHashTable { vector build_types; //! Positions of the columns that need to output const vector &output_columns; - //! The comparison predicates - vector predicates; + //! The comparison predicates that only contain equality predicates + vector equality_predicates; + //! The comparison predicates that contain non-equality predicates + vector non_equality_predicates; + + //! The column indices of the equality predicates to be used to compare the rows + vector equality_predicate_columns; + //! The column indices of the non-equality predicates to be used to compare the rows + vector non_equality_predicate_columns; //! Data column layout TupleDataLayout layout; - //! Efficiently matches rows - RowMatcher row_matcher; - RowMatcher row_matcher_no_match_sel; + //! Matches the equal condition rows during the build phase of the hash join to prevent + //! duplicates in a list because of hash-collisions + RowMatcher row_matcher_build; + //! Efficiently matches the non-equi rows during the probing phase, only there if non_equality_predicates is not + //! empty + unique_ptr row_matcher_probe; + //! Matches the same rows as the row_matcher, but also returns a vector for no matches + unique_ptr row_matcher_probe_no_match_sel; + //! Is true if there are predicates that are not equality predicates and we need to use the matchers during probing + bool needs_chain_matcher; + + //! If there is more than one element in the chain, we need to scan the next elements of the chain + bool chains_longer_than_one; + + //! The capacity of the HT. Is the same as hash_map.GetSize() / sizeof(ht_entry_t) + idx_t capacity; //! The size of an entry as stored in the HashTable idx_t entry_size; //! The total tuple size idx_t tuple_size; - //! Next pointer offset in tuple + //! Next pointer offset in tuple, also used for the position of the hash, which then gets overwritten by the pointer idx_t pointer_offset; //! A constant false column for initialising right outer joins Vector vfound; @@ -213,13 +275,18 @@ class JoinHashTable { const SelectionVector *¤t_sel); void Hash(DataChunk &keys, const SelectionVector &sel, idx_t count, Vector &hashes); - //! Apply a bitmask to the hashes - void ApplyBitmask(Vector &hashes, idx_t count); - void ApplyBitmask(Vector &hashes, const SelectionVector &sel, idx_t count, Vector &pointers); + bool UseSalt() const; + + //! Gets a pointer to the entry in the HT for each of the hashes_v using linear probing. Will update the + //! key_match_sel vector and the count argument to the number and position of the matches + void GetRowPointers(DataChunk &keys, TupleDataChunkState &key_state, ProbeState &state, Vector &hashes_v, + const SelectionVector &sel, idx_t &count, Vector &pointers_result_v, + SelectionVector &match_sel); private: - //! Insert the given set of locations into the HT with the given set of hashes - void InsertHashes(Vector &hashes, idx_t count, data_ptr_t key_locations[], bool parallel); + //! Insert the given set of locations into the HT with the given set of hashes_v + void InsertHashes(Vector &hashes_v, idx_t count, TupleDataChunkState &chunk_state, InsertState &insert_statebool, + bool parallel); idx_t PrepareKeys(DataChunk &keys, vector &vector_data, const SelectionVector *¤t_sel, SelectionVector &sel, bool build_side); @@ -230,10 +297,14 @@ class JoinHashTable { unique_ptr sink_collection; //! The DataCollection holding the main data of the hash table unique_ptr data_collection; + //! The hash map of the HT, created after finalization AllocatedData hash_map; + ht_entry_t *entries; //! Whether or not NULL values are considered equal in each of the comparisons vector null_values_are_equal; + //! An empty tuple that's a "dead end", can be used to stop chains early + unsafe_unique_array dead_end; //! Copying not allowed JoinHashTable(const JoinHashTable &) = delete; @@ -329,9 +400,9 @@ class JoinHashTable { //! Build HT for the next partitioned probe round bool PrepareExternalFinalize(const idx_t max_ht_size); //! Probe whatever we can, sink the rest into a thread-local HT - unique_ptr ProbeAndSpill(DataChunk &keys, TupleDataChunkState &key_state, DataChunk &payload, - ProbeSpill &probe_spill, ProbeSpillLocalAppendState &spill_state, - DataChunk &spill_chunk); + unique_ptr ProbeAndSpill(DataChunk &keys, TupleDataChunkState &key_state, ProbeState &probe_state, + DataChunk &payload, ProbeSpill &probe_spill, + ProbeSpillLocalAppendState &spill_state, DataChunk &spill_chunk); private: //! The current number of radix bits used to partition diff --git a/src/include/duckdb/execution/operator/aggregate/aggregate_object.hpp b/src/include/duckdb/execution/operator/aggregate/aggregate_object.hpp index b4c7e807750..a67683f72c9 100644 --- a/src/include/duckdb/execution/operator/aggregate/aggregate_object.hpp +++ b/src/include/duckdb/execution/operator/aggregate/aggregate_object.hpp @@ -27,7 +27,7 @@ struct AggregateObject { // NOLINT: work-around bug in clang-tidy AggregateObject(AggregateFunction function, FunctionData *bind_data, idx_t child_count, idx_t payload_size, AggregateType aggr_type, PhysicalType return_type, Expression *filter = nullptr); explicit AggregateObject(BoundAggregateExpression *aggr); - explicit AggregateObject(BoundWindowExpression &window); + explicit AggregateObject(const BoundWindowExpression &window); FunctionData *GetFunctionData() const { return bind_data_wrapper ? bind_data_wrapper->function_data.get() : nullptr; diff --git a/src/include/duckdb/execution/operator/aggregate/physical_streaming_window.hpp b/src/include/duckdb/execution/operator/aggregate/physical_streaming_window.hpp index 512950c1778..6b108380628 100644 --- a/src/include/duckdb/execution/operator/aggregate/physical_streaming_window.hpp +++ b/src/include/duckdb/execution/operator/aggregate/physical_streaming_window.hpp @@ -18,6 +18,8 @@ class PhysicalStreamingWindow : public PhysicalOperator { public: static constexpr const PhysicalOperatorType TYPE = PhysicalOperatorType::STREAMING_WINDOW; + static bool IsStreamingFunction(ClientContext &context, unique_ptr &expr); + public: PhysicalStreamingWindow(vector types, vector> select_list, idx_t estimated_cardinality, @@ -38,6 +40,9 @@ class PhysicalStreamingWindow : public PhysicalOperator { } string ParamsToString() const override; + +private: + void ExecuteAggregate(); }; } // namespace duckdb diff --git a/src/include/duckdb/execution/operator/csv_scanner/base_scanner.hpp b/src/include/duckdb/execution/operator/csv_scanner/base_scanner.hpp index 29a62b8e79a..c32e00b85fc 100644 --- a/src/include/duckdb/execution/operator/csv_scanner/base_scanner.hpp +++ b/src/include/duckdb/execution/operator/csv_scanner/base_scanner.hpp @@ -37,9 +37,10 @@ class ScannerResult { bool escaped = false; idx_t quoted_position = 0; + CSVStateMachine &state_machine; + protected: CSVStates &states; - CSVStateMachine &state_machine; }; //! This is the base of our CSV scanners. @@ -51,10 +52,10 @@ class BaseScanner { shared_ptr csv_file_scan = nullptr, CSVIterator iterator = {}); virtual ~BaseScanner() = default; + //! Returns true if the scanner is finished bool FinishedFile(); - //! Resets the scanner - void Reset(); + //! Parses data into a output_chunk virtual ScannerResult &ParseChunk(); @@ -63,6 +64,8 @@ class BaseScanner { CSVIterator &GetIterator(); + void SetIterator(const CSVIterator &it); + idx_t GetBoundaryIndex() { return iterator.GetBoundaryIdx(); } @@ -71,8 +74,8 @@ class BaseScanner { return lines_read; } - idx_t GetIteratorPosition() { - return iterator.pos.buffer_pos; + CSVPosition GetIteratorPosition() { + return iterator.pos; } CSVStateMachine &GetStateMachine(); @@ -92,6 +95,14 @@ class BaseScanner { bool ever_quoted = false; + //! Shared pointer to the buffer_manager, this is shared across multiple scanners + shared_ptr buffer_manager; + + //! Skips Notes and/or parts of the data, starting from the top. + //! notes are dirty lines on top of the file, before the actual data + static CSVIterator SkipCSVRows(shared_ptr buffer_manager, + const shared_ptr &state_machine, idx_t rows_to_skip); + protected: //! Boundaries of this scanner CSVIterator iterator; @@ -103,9 +114,6 @@ class BaseScanner { //! Hold the current buffer ptr char *buffer_handle_ptr = nullptr; - //! Shared pointer to the buffer_manager, this is shared across multiple scanners - shared_ptr buffer_manager; - //! If this scanner has been initialized bool initialized = false; //! How many lines were read by this scanner diff --git a/src/include/duckdb/execution/operator/csv_scanner/column_count_scanner.hpp b/src/include/duckdb/execution/operator/csv_scanner/column_count_scanner.hpp index de25f08f235..667b2ca847f 100644 --- a/src/include/duckdb/execution/operator/csv_scanner/column_count_scanner.hpp +++ b/src/include/duckdb/execution/operator/csv_scanner/column_count_scanner.hpp @@ -47,7 +47,7 @@ class ColumnCountResult : public ScannerResult { class ColumnCountScanner : public BaseScanner { public: ColumnCountScanner(shared_ptr buffer_manager, const shared_ptr &state_machine, - shared_ptr error_handler); + shared_ptr error_handler, CSVIterator iterator = {}); ColumnCountResult &ParseChunk() override; diff --git a/src/include/duckdb/execution/operator/csv_scanner/csv_buffer_manager.hpp b/src/include/duckdb/execution/operator/csv_scanner/csv_buffer_manager.hpp index c81b2c87ff1..396c60c9ba2 100644 --- a/src/include/duckdb/execution/operator/csv_scanner/csv_buffer_manager.hpp +++ b/src/include/duckdb/execution/operator/csv_scanner/csv_buffer_manager.hpp @@ -22,7 +22,7 @@ class CSVStateMachine; class CSVBufferManager { public: CSVBufferManager(ClientContext &context, const CSVReaderOptions &options, const string &file_path, - const idx_t file_idx); + const idx_t file_idx, bool per_file_single_threaded = false); //! Returns a buffer from a buffer id (starting from 0). If it's in the auto-detection then we cache new buffers //! Otherwise we remove them from the cache if they are already there, or just return them bypassing the cache. shared_ptr GetBuffer(const idx_t buffer_idx); @@ -48,6 +48,7 @@ class CSVBufferManager { ClientContext &context; idx_t skip_rows = 0; bool sniffing = false; + const bool per_file_single_threaded; private: //! Reads next buffer in reference to cached_buffers.front() diff --git a/src/include/duckdb/execution/operator/csv_scanner/csv_file_scanner.hpp b/src/include/duckdb/execution/operator/csv_scanner/csv_file_scanner.hpp index 0ba7c0e02dc..fd77f5e0338 100644 --- a/src/include/duckdb/execution/operator/csv_scanner/csv_file_scanner.hpp +++ b/src/include/duckdb/execution/operator/csv_scanner/csv_file_scanner.hpp @@ -27,10 +27,11 @@ class CSVFileScan { //! Path to this file CSVFileScan(ClientContext &context, const string &file_path, const CSVReaderOptions &options, const idx_t file_idx, const ReadCSVData &bind_data, const vector &column_ids, - const vector &file_schema); + const vector &file_schema, bool per_file_single_threaded); CSVFileScan(ClientContext &context, const string &file_name, CSVReaderOptions &options); + void SetStart(); const string &GetFileName(); const vector &GetNames(); const vector &GetTypes(); @@ -67,5 +68,7 @@ class CSVFileScan { //! Options for this CSV Reader CSVReaderOptions options; + + CSVIterator start_iterator; }; } // namespace duckdb diff --git a/src/include/duckdb/execution/operator/csv_scanner/csv_reader_options.hpp b/src/include/duckdb/execution/operator/csv_scanner/csv_reader_options.hpp index 415b0304973..4f9c57b7a0c 100644 --- a/src/include/duckdb/execution/operator/csv_scanner/csv_reader_options.hpp +++ b/src/include/duckdb/execution/operator/csv_scanner/csv_reader_options.hpp @@ -69,9 +69,9 @@ struct CSVReaderOptions { //! User-defined name list vector name_list; //! Types considered as candidates for auto detection ordered by descending specificity (~ from high to low) - vector auto_type_candidates = {LogicalType::VARCHAR, LogicalType::TIMESTAMP, LogicalType::DATE, - LogicalType::TIME, LogicalType::DOUBLE, LogicalType::BIGINT, - LogicalType::BOOLEAN, LogicalType::SQLNULL}; + vector auto_type_candidates = {LogicalType::VARCHAR, LogicalType::DOUBLE, LogicalType::BIGINT, + LogicalType::TIMESTAMP, LogicalType::DATE, LogicalType::TIME, + LogicalType::BOOLEAN, LogicalType::SQLNULL}; //! In case the sniffer found a mismatch error from user defined types or dialect string sniffer_user_mismatch_error; //! In case the sniffer found a mismatch error from user defined types or dialect @@ -120,8 +120,6 @@ struct CSVReaderOptions { string suffix; string write_newline; - //! The date format to use (if any is specified) - map date_format = {{LogicalTypeId::DATE, {}}, {LogicalTypeId::TIMESTAMP, {}}}; //! The date format to use for writing (if any is specified) map write_date_format = {{LogicalTypeId::DATE, Value()}, {LogicalTypeId::TIMESTAMP, Value()}}; //! Whether or not a type format is specified @@ -138,7 +136,8 @@ struct CSVReaderOptions { string GetEscape() const; void SetEscape(const string &escape); - int64_t GetSkipRows() const; + idx_t GetSkipRows() const; + void SetSkipRows(int64_t rows); string GetQuote() const; diff --git a/src/include/duckdb/execution/operator/csv_scanner/csv_sniffer.hpp b/src/include/duckdb/execution/operator/csv_scanner/csv_sniffer.hpp index cbceddd9f0b..3b76c873ed8 100644 --- a/src/include/duckdb/execution/operator/csv_scanner/csv_sniffer.hpp +++ b/src/include/duckdb/execution/operator/csv_scanner/csv_sniffer.hpp @@ -139,6 +139,7 @@ class CSVSniffer { const vector "erule_candidates, const unordered_map> "e_candidates_map, const unordered_map> &escape_candidates_map); + //! 3. Analyzes if dialect candidate is a good candidate to be considered, if so, it adds it to the candidates void AnalyzeDialectCandidate(unique_ptr, idx_t &rows_read, idx_t &best_consistent_rows, idx_t &prev_padding_count); @@ -166,7 +167,7 @@ class CSVSniffer { string_t &dummy_val); //! If a string_t value can be cast to a type bool CanYouCastIt(const string_t value, const LogicalType &type, const DialectOptions &dialect_options, - const bool is_null); + const bool is_null, const char decimal_separator); //! Variables for Type Detection //! Format Candidates for Date and Timestamp Types diff --git a/src/include/duckdb/execution/operator/csv_scanner/scanner_boundary.hpp b/src/include/duckdb/execution/operator/csv_scanner/scanner_boundary.hpp index 7cf9769575a..9e38f9bedbb 100644 --- a/src/include/duckdb/execution/operator/csv_scanner/scanner_boundary.hpp +++ b/src/include/duckdb/execution/operator/csv_scanner/scanner_boundary.hpp @@ -25,11 +25,9 @@ namespace duckdb { //! Information stored in the buffer struct CSVBoundary { - CSVBoundary(idx_t file_idx, idx_t buffer_idx, idx_t buffer_pos, idx_t boundary_idx, idx_t end_pos); + CSVBoundary(idx_t buffer_idx, idx_t buffer_pos, idx_t boundary_idx, idx_t end_pos); CSVBoundary(); void Print(); - //! File index where we start scanning [0-idx], a scanner can never go over one file. - idx_t file_idx = 0; //! Start Buffer index of the file where we start scanning idx_t buffer_idx = 0; //! Start Buffer position of the buffer of the file where we start scanning @@ -43,10 +41,8 @@ struct CSVBoundary { }; struct CSVPosition { - CSVPosition(idx_t file_idx, idx_t buffer_idx, idx_t buffer_pos); + CSVPosition(idx_t buffer_idx, idx_t buffer_pos); CSVPosition(); - //! File index where we start scanning [0-idx], a scanner can never go over one file. - idx_t file_idx = 0; //! Start Buffer index of the file where we start scanning idx_t buffer_idx = 0; //! Start Buffer position of the buffer of the file where we start scanning @@ -55,8 +51,6 @@ struct CSVPosition { }; struct CSVIterator { public: - CSVIterator(idx_t file_idx, idx_t buffer_idx, idx_t buffer_pos, idx_t boundary_idx, idx_t buffer_size); - CSVIterator(); void Print(); @@ -68,12 +62,13 @@ struct CSVIterator { //! Getters idx_t GetEndPos() const; - idx_t GetFileIdx() const; idx_t GetBufferIdx() const; idx_t GetBoundaryIdx() const; void SetCurrentPositionToBoundary(); + void SetCurrentBoundaryToPosition(bool single_threaded); + void SetStart(idx_t pos); //! 8 MB TODO: Should benchmarks other values @@ -83,6 +78,8 @@ struct CSVIterator { bool done = false; + bool first_one = true; + private: //! The original setting CSVBoundary boundary; diff --git a/src/include/duckdb/execution/operator/csv_scanner/string_value_scanner.hpp b/src/include/duckdb/execution/operator/csv_scanner/string_value_scanner.hpp index ed9d13d8d36..504f42d5334 100644 --- a/src/include/duckdb/execution/operator/csv_scanner/string_value_scanner.hpp +++ b/src/include/duckdb/execution/operator/csv_scanner/string_value_scanner.hpp @@ -67,14 +67,23 @@ class FullLinePosition { unordered_map> &buffer_handles); }; +class StringValueResult; + class CurrentError { public: - CurrentError(CSVErrorType type, idx_t col_idx_p, LinePosition error_position_p) - : type(type), col_idx(col_idx_p), error_position(error_position_p) {}; - + CurrentError(CSVErrorType type, idx_t col_idx_p, idx_t chunk_idx_p, LinePosition error_position_p, + idx_t current_line_size_p) + : type(type), col_idx(col_idx_p), chunk_idx(chunk_idx_p), current_line_size(current_line_size_p), + error_position(error_position_p) {}; + //! Error Type (e.g., Cast, Wrong # of columns, ...) CSVErrorType type; + //! Column index related to the CSV File columns idx_t col_idx; + //! Column index related to the produced chunk (i.e., with projection applied) + idx_t chunk_idx; + //! Current CSV Line size in Bytes idx_t current_line_size; + //! Error Message produced string error_message; //! Exact Position where the error happened LinePosition error_position; @@ -84,12 +93,74 @@ class CurrentError { } }; +class LineError { +public: + explicit LineError(bool ignore_errors_p) : is_error_in_line(false), ignore_errors(ignore_errors_p) {}; + //! We clear up our CurrentError Vector + void Reset() { + current_errors.clear(); + is_error_in_line = false; + } + void Insert(const CSVErrorType &type, const idx_t &col_idx, const idx_t &chunk_idx, + const LinePosition &error_position, const idx_t current_line_size = 0) { + is_error_in_line = true; + if (!ignore_errors) { + // We store it for later + current_errors.push_back({type, col_idx, chunk_idx, error_position, current_line_size}); + current_errors.back().current_line_size = current_line_size; + } + } + //! Set that we currently have an error, but don't really store them + void SetError() { + is_error_in_line = true; + } + //! Dirty hack for adding cast message + void ModifyErrorMessageOfLastError(string error_message) { + D_ASSERT(!current_errors.empty() && current_errors.back().type == CSVErrorType::CAST_ERROR); + current_errors.back().error_message = std::move(error_message); + } + + bool HasErrorType(CSVErrorType type) { + for (auto &error : current_errors) { + if (type == error.type) { + return true; + } + } + return false; + } + + bool HandleErrors(StringValueResult &result); + +private: + vector current_errors; + bool is_error_in_line; + bool ignore_errors; +}; + +struct ParseTypeInfo { + ParseTypeInfo() {}; + ParseTypeInfo(LogicalType &type, bool validate_utf_8_p) : validate_utf8(validate_utf_8_p) { + type_id = type.id(); + internal_type = type.InternalType(); + if (type.id() == LogicalTypeId::DECIMAL) { + // We only care about these if we have a decimal value + type.GetDecimalProperties(width, scale); + } + } + + bool validate_utf8; + LogicalTypeId type_id; + PhysicalType internal_type; + uint8_t scale; + uint8_t width; +}; class StringValueResult : public ScannerResult { public: StringValueResult(CSVStates &states, CSVStateMachine &state_machine, - const shared_ptr &buffer_handle, Allocator &buffer_allocator, idx_t result_size, - idx_t buffer_position, CSVErrorHandler &error_handler, CSVIterator &iterator, - bool store_line_size, shared_ptr csv_file_scan, idx_t &lines_read, bool sniffing); + const shared_ptr &buffer_handle, Allocator &buffer_allocator, + bool figure_out_new_line, idx_t buffer_position, CSVErrorHandler &error_handler, + CSVIterator &iterator, bool store_line_size, shared_ptr csv_file_scan, + idx_t &lines_read, bool sniffing); ~StringValueResult(); @@ -115,6 +186,7 @@ class StringValueResult : public ScannerResult { DataChunk parse_chunk; idx_t number_of_rows = 0; idx_t cur_col_id = 0; + bool figure_out_new_line; idx_t result_size; //! Information to properly handle errors CSVErrorHandler &error_handler; @@ -127,7 +199,7 @@ class StringValueResult : public ScannerResult { bool added_last_line = false; bool quoted_new_line = false; - unsafe_unique_array> parse_types; + unsafe_unique_array parse_types; vector names; shared_ptr csv_file_scan; @@ -144,9 +216,15 @@ class StringValueResult : public ScannerResult { idx_t requested_size; //! Errors happening in the current line (if any) - vector current_errors; + LineError current_errors; StrpTimeFormat date_format, timestamp_format; bool sniffing; + + char decimal_separator; + + //! We store borked rows so we can generate multiple errors during flushing + unordered_set borked_rows; + //! Specialized code for quoted values, makes sure to remove quotes and escapes static inline void AddQuotedValue(StringValueResult &result, const idx_t buffer_pos); //! Adds a Value to the result @@ -163,14 +241,15 @@ class StringValueResult : public ScannerResult { inline bool AddRowInternal(); //! Force the throw of a unicode error void HandleUnicodeError(idx_t col_idx, LinePosition &error_position); - //! Certain errors should only be handled when adding the line, to ensure proper error propagation. - bool HandleError(); - + bool HandleTooManyColumnsError(const char *value_ptr, const idx_t size); inline void AddValueToVector(const char *value_ptr, const idx_t size, bool allocate = false); DataChunk &ToChunk(); //! Resets the state of the result void Reset(); + + //! BOM skipping (https://en.wikipedia.org/wiki/Byte_order_mark) + void SkipBOM(); }; //! Our dialect scanner basically goes over the CSV and actually parses the values to a DuckDB vector of string_t @@ -179,11 +258,11 @@ class StringValueScanner : public BaseScanner { StringValueScanner(idx_t scanner_idx, const shared_ptr &buffer_manager, const shared_ptr &state_machine, const shared_ptr &error_handler, const shared_ptr &csv_file_scan, - bool sniffing = false, CSVIterator boundary = {}, idx_t result_size = STANDARD_VECTOR_SIZE); + bool sniffing = false, CSVIterator boundary = {}, bool figure_out_nl = false); StringValueScanner(const shared_ptr &buffer_manager, const shared_ptr &state_machine, - const shared_ptr &error_handler); + const shared_ptr &error_handler, CSVIterator boundary); StringValueResult &ParseChunk() override; @@ -199,8 +278,7 @@ class StringValueScanner : public BaseScanner { static string_t RemoveEscape(const char *str_ptr, idx_t end, char escape, Vector &vector); //! If we can directly cast the type when consuming the CSV file, or we have to do it later - static bool CanDirectlyCast(const LogicalType &type, - const map> &format_options); + static bool CanDirectlyCast(const LogicalType &type); const idx_t scanner_idx; @@ -219,12 +297,6 @@ class StringValueScanner : public BaseScanner { //! Function used to move from one buffer to the other, if necessary bool MoveToNextBuffer(); - //! BOM skipping (https://en.wikipedia.org/wiki/Byte_order_mark) - void SkipBOM(); - - //! Skips Notes, notes are dirty lines on top of the file, before the actual data - void SkipCSVRows(); - void SkipUntilNewLine(); void SetStart(); diff --git a/src/include/duckdb/execution/operator/helper/physical_buffered_batch_collector.hpp b/src/include/duckdb/execution/operator/helper/physical_buffered_batch_collector.hpp new file mode 100644 index 00000000000..9ec672215a4 --- /dev/null +++ b/src/include/duckdb/execution/operator/helper/physical_buffered_batch_collector.hpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/helper/physical_buffered_batch_collector.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/execution/operator/helper/physical_result_collector.hpp" +#include "duckdb/common/queue.hpp" + +namespace duckdb { + +class BufferedBatchCollectorLocalState : public LocalSinkState { +public: + BufferedBatchCollectorLocalState(); + +public: + idx_t current_batch = 0; +}; + +class PhysicalBufferedBatchCollector : public PhysicalResultCollector { +public: + explicit PhysicalBufferedBatchCollector(PreparedStatementData &data); + +public: + unique_ptr GetResult(GlobalSinkState &state) override; + +public: + // Sink interface + SinkResultType Sink(ExecutionContext &context, DataChunk &chunk, OperatorSinkInput &input) const override; + SinkCombineResultType Combine(ExecutionContext &context, OperatorSinkCombineInput &input) const override; + SinkNextBatchType NextBatch(ExecutionContext &context, OperatorSinkNextBatchInput &input) const override; + + unique_ptr GetLocalSinkState(ExecutionContext &context) const override; + unique_ptr GetGlobalSinkState(ClientContext &context) const override; + + bool RequiresBatchIndex() const override { + return true; + } + + bool ParallelSink() const override { + return true; + } +}; + +} // namespace duckdb diff --git a/src/include/duckdb/execution/operator/helper/physical_update_extensions.hpp b/src/include/duckdb/execution/operator/helper/physical_update_extensions.hpp new file mode 100644 index 00000000000..bb5024b56ae --- /dev/null +++ b/src/include/duckdb/execution/operator/helper/physical_update_extensions.hpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// src/include/duckdb/execution/operator/helper/physical_update_extensions.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/execution/physical_operator.hpp" +#include "duckdb/parser/parsed_data/update_extensions_info.hpp" +#include "duckdb/main/extension_helper.hpp" + +namespace duckdb { + +struct UpdateExtensionsGlobalState : public GlobalSourceState { + UpdateExtensionsGlobalState() : offset(0) { + } + + vector update_result_entries; + idx_t offset; +}; + +//! PhysicalUpdateExtensions represents an extension UPDATE operation +class PhysicalUpdateExtensions : public PhysicalOperator { +public: + static constexpr const PhysicalOperatorType TYPE = PhysicalOperatorType::UPDATE_EXTENSIONS; + +public: + explicit PhysicalUpdateExtensions(unique_ptr info, idx_t estimated_cardinality) + : PhysicalOperator(PhysicalOperatorType::UPDATE_EXTENSIONS, + {LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR, + LogicalType::VARCHAR}, + estimated_cardinality), + info(std::move(info)) { + } + + unique_ptr info; + + unique_ptr GetGlobalSourceState(ClientContext &context) const override; + +public: + // Source interface + SourceResultType GetData(ExecutionContext &context, DataChunk &chunk, OperatorSourceInput &input) const override; + + bool IsSource() const override { + return true; + } +}; + +} // namespace duckdb diff --git a/src/include/duckdb/execution/operator/persistent/batch_memory_manager.hpp b/src/include/duckdb/execution/operator/persistent/batch_memory_manager.hpp index b97071a395d..3a2f727a396 100644 --- a/src/include/duckdb/execution/operator/persistent/batch_memory_manager.hpp +++ b/src/include/duckdb/execution/operator/persistent/batch_memory_manager.hpp @@ -126,10 +126,6 @@ class BatchMemoryManager { return available_memory; } - idx_t GetMinimumBatchIndex() const { - return min_batch_index; - } - mutex &GetBlockedTaskLock() { return blocked_task_lock; } diff --git a/src/include/duckdb/execution/operator/persistent/physical_batch_copy_to_file.hpp b/src/include/duckdb/execution/operator/persistent/physical_batch_copy_to_file.hpp index bb7697876d4..4f01747d44e 100644 --- a/src/include/duckdb/execution/operator/persistent/physical_batch_copy_to_file.hpp +++ b/src/include/duckdb/execution/operator/persistent/physical_batch_copy_to_file.hpp @@ -8,11 +8,11 @@ #pragma once -#include "duckdb/execution/physical_operator.hpp" -#include "duckdb/parser/parsed_data/copy_info.hpp" -#include "duckdb/function/copy_function.hpp" #include "duckdb/common/file_system.hpp" #include "duckdb/common/filename_pattern.hpp" +#include "duckdb/execution/physical_operator.hpp" +#include "duckdb/function/copy_function.hpp" +#include "duckdb/parser/parsed_data/copy_info.hpp" namespace duckdb { struct FixedRawBatchData; @@ -29,6 +29,7 @@ class PhysicalBatchCopyToFile : public PhysicalOperator { unique_ptr bind_data; string file_path; bool use_tmp_file; + CopyFunctionReturnType return_type; public: // Source interface @@ -66,7 +67,7 @@ class PhysicalBatchCopyToFile : public PhysicalOperator { unique_ptr collection) const; void RepartitionBatches(ClientContext &context, GlobalSinkState &gstate_p, idx_t min_index, bool final = false) const; - void FlushBatchData(ClientContext &context, GlobalSinkState &gstate_p, idx_t min_index) const; + void FlushBatchData(ClientContext &context, GlobalSinkState &gstate_p) const; bool ExecuteTask(ClientContext &context, GlobalSinkState &gstate_p) const; void ExecuteTasks(ClientContext &context, GlobalSinkState &gstate_p) const; SinkFinalizeType FinalFlush(ClientContext &context, GlobalSinkState &gstate_p) const; diff --git a/src/include/duckdb/execution/operator/persistent/physical_copy_to_file.hpp b/src/include/duckdb/execution/operator/persistent/physical_copy_to_file.hpp index a405ee5cb68..8a818dadc0c 100644 --- a/src/include/duckdb/execution/operator/persistent/physical_copy_to_file.hpp +++ b/src/include/duckdb/execution/operator/persistent/physical_copy_to_file.hpp @@ -8,11 +8,13 @@ #pragma once +#include "duckdb/common/enums/copy_overwrite_mode.hpp" #include "duckdb/common/file_system.hpp" #include "duckdb/common/filename_pattern.hpp" #include "duckdb/execution/physical_operator.hpp" #include "duckdb/function/copy_function.hpp" #include "duckdb/parser/parsed_data/copy_info.hpp" +#include "duckdb/storage/storage_lock.hpp" namespace duckdb { @@ -31,10 +33,12 @@ class PhysicalCopyToFile : public PhysicalOperator { bool use_tmp_file; FilenamePattern filename_pattern; string file_extension; - bool overwrite_or_ignore; + CopyOverwriteMode overwrite_mode; bool parallel; bool per_thread_output; optional_idx file_size_bytes; + bool rotate; + CopyFunctionReturnType return_type; bool partition_output; vector partition_columns; @@ -71,10 +75,12 @@ class PhysicalCopyToFile : public PhysicalOperator { } static void MoveTmpFile(ClientContext &context, const string &tmp_file_path); + static string GetNonTmpFile(ClientContext &context, const string &tmp_file_path); string GetTrimmedPath(ClientContext &context) const; private: - unique_ptr CreateFileState(ClientContext &context, GlobalSinkState &sink) const; + unique_ptr CreateFileState(ClientContext &context, GlobalSinkState &sink, + StorageLockKey &global_lock) const; }; } // namespace duckdb diff --git a/src/include/duckdb/execution/operator/persistent/physical_export.hpp b/src/include/duckdb/execution/operator/persistent/physical_export.hpp index a74b270fc55..4032aea65c3 100644 --- a/src/include/duckdb/execution/operator/persistent/physical_export.hpp +++ b/src/include/duckdb/execution/operator/persistent/physical_export.hpp @@ -57,6 +57,7 @@ class PhysicalExport : public PhysicalOperator { static void ExtractEntries(ClientContext &context, vector> &schemas, ExportEntries &result); + static catalog_entry_vector_t GetNaiveExportOrder(ClientContext &context, Catalog &catalog); public: // Sink interface diff --git a/src/include/duckdb/execution/operator/projection/physical_tableinout_function.hpp b/src/include/duckdb/execution/operator/projection/physical_tableinout_function.hpp index 659e5cc4a40..b1d42dd9951 100644 --- a/src/include/duckdb/execution/operator/projection/physical_tableinout_function.hpp +++ b/src/include/duckdb/execution/operator/projection/physical_tableinout_function.hpp @@ -39,6 +39,8 @@ class PhysicalTableInOutFunction : public PhysicalOperator { return function.in_out_function_final; } + string ParamsToString() const override; + private: //! The table function TableFunction function; diff --git a/src/include/duckdb/execution/operator/scan/physical_column_data_scan.hpp b/src/include/duckdb/execution/operator/scan/physical_column_data_scan.hpp index 57e452fb57d..9ee9e9e3db1 100644 --- a/src/include/duckdb/execution/operator/scan/physical_column_data_scan.hpp +++ b/src/include/duckdb/execution/operator/scan/physical_column_data_scan.hpp @@ -9,6 +9,7 @@ #pragma once #include "duckdb/common/types/column/column_data_collection.hpp" +#include "duckdb/common/optionally_owned_ptr.hpp" #include "duckdb/execution/physical_operator.hpp" namespace duckdb { @@ -20,15 +21,13 @@ class PhysicalColumnDataScan : public PhysicalOperator { public: PhysicalColumnDataScan(vector types, PhysicalOperatorType op_type, idx_t estimated_cardinality, - unique_ptr owned_collection = nullptr); + optionally_owned_ptr collection); PhysicalColumnDataScan(vector types, PhysicalOperatorType op_type, idx_t estimated_cardinality, idx_t cte_index); - // the column data collection to scan - optional_ptr collection; - //! Owned column data collection, if any - unique_ptr owned_collection; + //! (optionally owned) column data collection to scan + optionally_owned_ptr collection; idx_t cte_index; diff --git a/src/include/duckdb/execution/operator/scan/physical_expression_scan.hpp b/src/include/duckdb/execution/operator/scan/physical_expression_scan.hpp index a6f0d1ae76b..b934bd69eec 100644 --- a/src/include/duckdb/execution/operator/scan/physical_expression_scan.hpp +++ b/src/include/duckdb/execution/operator/scan/physical_expression_scan.hpp @@ -39,8 +39,12 @@ class PhysicalExpressionScan : public PhysicalOperator { public: bool IsFoldable() const; - void EvaluateExpression(ClientContext &context, idx_t expression_idx, DataChunk *child_chunk, - DataChunk &result) const; + void EvaluateExpression(ClientContext &context, idx_t expression_idx, optional_ptr child_chunk, + DataChunk &result, optional_ptr temp_chunk_ptr = nullptr) const; + +private: + void EvaluateExpressionInternal(ClientContext &context, idx_t expression_idx, optional_ptr child_chunk, + DataChunk &result, DataChunk &temp_chunk) const; }; } // namespace duckdb diff --git a/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp b/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp index e00a18ec51f..2fc31168351 100644 --- a/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp +++ b/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp @@ -26,7 +26,7 @@ class PhysicalTableScan : public PhysicalOperator { PhysicalTableScan(vector types, TableFunction function, unique_ptr bind_data, vector returned_types, vector column_ids, vector projection_ids, vector names, unique_ptr table_filters, idx_t estimated_cardinality, - ExtraOperatorInfo extra_info); + ExtraOperatorInfo extra_info, vector parameters); //! The table function TableFunction function; @@ -42,8 +42,10 @@ class PhysicalTableScan : public PhysicalOperator { vector names; //! The table filters unique_ptr table_filters; - //! Currently stores any filters applied to file names (as strings) + //! Currently stores info related to filters pushed down into MultiFileLists ExtraOperatorInfo extra_info; + //! Parameters + vector parameters; public: string GetName() const override; diff --git a/src/include/duckdb/execution/reservoir_sample.hpp b/src/include/duckdb/execution/reservoir_sample.hpp index 87ab341fd06..0edc7e073b9 100644 --- a/src/include/duckdb/execution/reservoir_sample.hpp +++ b/src/include/duckdb/execution/reservoir_sample.hpp @@ -17,6 +17,8 @@ namespace duckdb { +enum class SampleType : uint8_t { BLOCKING_SAMPLE = 0, RESERVOIR_SAMPLE = 1, RESERVOIR_PERCENTAGE_SAMPLE = 2 }; + class BaseReservoirSampling { public: explicit BaseReservoirSampling(int64_t seed); @@ -29,8 +31,6 @@ class BaseReservoirSampling { void ReplaceElement(double with_weight = -1); //! The random generator RandomEngine random; - //! Priority queue of [random element, index] for each of the elements in the sample - std::priority_queue> reservoir_weights; //! The next element to sample idx_t next_index_to_sample; //! The reservoir threshold of the current min entry @@ -43,11 +43,26 @@ class BaseReservoirSampling { //! when collecting a sample in parallel, we want to know how many values each thread has seen //! so we can collect the samples from the thread local states in a uniform manner idx_t num_entries_seen_total; + //! Priority queue of [random element, index] for each of the elements in the sample + std::priority_queue> reservoir_weights; + + void Serialize(Serializer &serializer) const; + static unique_ptr Deserialize(Deserializer &deserializer); }; class BlockingSample { public: - explicit BlockingSample(int64_t seed) : base_reservoir_sample(seed), random(base_reservoir_sample.random) { + static constexpr const SampleType TYPE = SampleType::BLOCKING_SAMPLE; + + unique_ptr base_reservoir_sample; + //! The sample type + SampleType type; + //! has the sample been destroyed due to updates to the referenced table + bool destroyed; + +public: + explicit BlockingSample(int64_t seed) : old_base_reservoir_sample(seed), random(old_base_reservoir_sample.random) { + base_reservoir_sample = nullptr; } virtual ~BlockingSample() { } @@ -59,20 +74,49 @@ class BlockingSample { //! Fetches a chunk from the sample. Note that this method is destructive and should only be used after the //! sample is completely built. virtual unique_ptr GetChunk() = 0; - BaseReservoirSampling base_reservoir_sample; + BaseReservoirSampling old_base_reservoir_sample; virtual void Serialize(Serializer &serializer) const; static unique_ptr Deserialize(Deserializer &deserializer); -protected: +public: + template + TARGET &Cast() { + if (type != TARGET::TYPE && TARGET::TYPE != SampleType::BLOCKING_SAMPLE) { + throw InternalException("Failed to cast sample to type - sample type mismatch"); + } + return reinterpret_cast(*this); + } + + template + const TARGET &Cast() const { + if (type != TARGET::TYPE && TARGET::TYPE != SampleType::BLOCKING_SAMPLE) { + throw InternalException("Failed to cast sample to type - sample type mismatch"); + } + return reinterpret_cast(*this); + } //! The reservoir sampling RandomEngine &random; }; +class ReservoirChunk { +public: + ReservoirChunk() { + } + + DataChunk chunk; + void Serialize(Serializer &serializer) const; + static unique_ptr Deserialize(Deserializer &deserializer); +}; + //! The reservoir sample class maintains a streaming sample of fixed size "sample_count" class ReservoirSample : public BlockingSample { public: - ReservoirSample(Allocator &allocator, idx_t sample_count, int64_t seed); + static constexpr const SampleType TYPE = SampleType::RESERVOIR_SAMPLE; + +public: + ReservoirSample(Allocator &allocator, idx_t sample_count, int64_t seed = 1); + explicit ReservoirSample(idx_t sample_count, int64_t seed = 1); //! Add a chunk of data to the sample void AddToReservoir(DataChunk &input) override; @@ -81,6 +125,8 @@ class ReservoirSample : public BlockingSample { //! sample is completely built. unique_ptr GetChunk() override; void Finalize() override; + void Serialize(Serializer &serializer) const override; + static unique_ptr Deserialize(Deserializer &deserializer); private: //! Replace a single element of the input @@ -96,8 +142,10 @@ class ReservoirSample : public BlockingSample { //! when explicit number used, sample_count = number idx_t sample_count; bool reservoir_initialized; + //! The current reservoir - unique_ptr reservoir_chunk; + unique_ptr reservoir_data_chunk; + unique_ptr reservoir_chunk; }; //! The reservoir sample sample_size class maintains a streaming sample of variable size @@ -105,7 +153,11 @@ class ReservoirSamplePercentage : public BlockingSample { constexpr static idx_t RESERVOIR_THRESHOLD = 100000; public: - ReservoirSamplePercentage(Allocator &allocator, double percentage, int64_t seed); + static constexpr const SampleType TYPE = SampleType::RESERVOIR_PERCENTAGE_SAMPLE; + +public: + ReservoirSamplePercentage(Allocator &allocator, double percentage, int64_t seed = -1); + explicit ReservoirSamplePercentage(double percentage, int64_t seed = -1); //! Add a chunk of data to the sample void AddToReservoir(DataChunk &input) override; @@ -115,6 +167,9 @@ class ReservoirSamplePercentage : public BlockingSample { unique_ptr GetChunk() override; void Finalize() override; + void Serialize(Serializer &serializer) const override; + static unique_ptr Deserialize(Deserializer &deserializer); + private: Allocator &allocator; //! The sample_size to sample diff --git a/src/include/duckdb/execution/window_executor.hpp b/src/include/duckdb/execution/window_executor.hpp index 8d134d05e18..12767d4d291 100644 --- a/src/include/duckdb/execution/window_executor.hpp +++ b/src/include/duckdb/execution/window_executor.hpp @@ -136,181 +136,192 @@ class WindowExecutorState { } }; -class WindowExecutor { -public: - WindowExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); - virtual ~WindowExecutor() { - } +class WindowExecutor; - virtual void Sink(DataChunk &input_chunk, const idx_t input_idx, const idx_t total_count) { - range.Append(input_chunk); - } - - virtual void Finalize() { - } - - virtual unique_ptr GetExecutorState() const; +class WindowExecutorGlobalState : public WindowExecutorState { +public: + WindowExecutorGlobalState(const WindowExecutor &executor, const idx_t payload_count, + const ValidityMask &partition_mask, const ValidityMask &order_mask); - void Evaluate(idx_t row_idx, DataChunk &input_chunk, Vector &result, WindowExecutorState &lstate) const; + const WindowExecutor &executor; -protected: - // The function - BoundWindowExpression &wexpr; - ClientContext &context; const idx_t payload_count; const ValidityMask &partition_mask; const ValidityMask &order_mask; - // Expression collections - DataChunk payload_collection; + // Argument evaluation ExpressionExecutor payload_executor; DataChunk payload_chunk; // evaluate RANGE expressions, if needed WindowInputColumn range; +}; - virtual void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const = 0; +class WindowExecutorLocalState : public WindowExecutorState { +public: + explicit WindowExecutorLocalState(const WindowExecutorGlobalState &gstate) { + } }; -class WindowAggregateExecutor : public WindowExecutor { +class WindowExecutor { public: - bool IsConstantAggregate(); - bool IsCustomAggregate(); - bool IsDistinctAggregate(); + WindowExecutor(BoundWindowExpression &wexpr, ClientContext &context); + virtual ~WindowExecutor() { + } - WindowAggregateExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask, - WindowAggregationMode mode); + virtual unique_ptr + GetGlobalState(const idx_t payload_count, const ValidityMask &partition_mask, const ValidityMask &order_mask) const; + virtual unique_ptr GetLocalState(const WindowExecutorGlobalState &gstate) const; - void Sink(DataChunk &input_chunk, const idx_t input_idx, const idx_t total_count) override; - void Finalize() override; + virtual void Sink(DataChunk &input_chunk, const idx_t input_idx, const idx_t total_count, + WindowExecutorGlobalState &gstate) const { + gstate.range.Append(input_chunk); + } - unique_ptr GetExecutorState() const override; + virtual void Finalize(WindowExecutorGlobalState &gstate) const { + } - const WindowAggregationMode mode; + void Evaluate(idx_t row_idx, DataChunk &input_chunk, Vector &result, WindowExecutorLocalState &lstate, + WindowExecutorGlobalState &gstate) const; + + // The function + const BoundWindowExpression &wexpr; + ClientContext &context; protected: - ExpressionExecutor filter_executor; - SelectionVector filter_sel; + virtual void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const = 0; +}; - // aggregate computation algorithm - unique_ptr aggregator; +class WindowAggregateExecutor : public WindowExecutor { +public: + WindowAggregateExecutor(BoundWindowExpression &wexpr, ClientContext &context, WindowAggregationMode mode); + + void Sink(DataChunk &input_chunk, const idx_t input_idx, const idx_t total_count, + WindowExecutorGlobalState &gstate) const override; + void Finalize(WindowExecutorGlobalState &gstate) const override; - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + unique_ptr GetGlobalState(const idx_t payload_count, const ValidityMask &partition_mask, + const ValidityMask &order_mask) const override; + unique_ptr GetLocalState(const WindowExecutorGlobalState &gstate) const override; + + const WindowAggregationMode mode; + +protected: + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; class WindowRowNumberExecutor : public WindowExecutor { public: - WindowRowNumberExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowRowNumberExecutor(BoundWindowExpression &wexpr, ClientContext &context); protected: - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; // Base class for non-aggregate functions that use peer boundaries class WindowRankExecutor : public WindowExecutor { public: - WindowRankExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowRankExecutor(BoundWindowExpression &wexpr, ClientContext &context); - unique_ptr GetExecutorState() const override; + unique_ptr GetLocalState(const WindowExecutorGlobalState &gstate) const override; protected: - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; class WindowDenseRankExecutor : public WindowExecutor { public: - WindowDenseRankExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowDenseRankExecutor(BoundWindowExpression &wexpr, ClientContext &context); - unique_ptr GetExecutorState() const override; + unique_ptr GetLocalState(const WindowExecutorGlobalState &gstate) const override; protected: - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; class WindowPercentRankExecutor : public WindowExecutor { public: - WindowPercentRankExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowPercentRankExecutor(BoundWindowExpression &wexpr, ClientContext &context); - unique_ptr GetExecutorState() const override; + unique_ptr GetLocalState(const WindowExecutorGlobalState &gstate) const override; protected: - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; class WindowCumeDistExecutor : public WindowExecutor { public: - WindowCumeDistExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowCumeDistExecutor(BoundWindowExpression &wexpr, ClientContext &context); protected: - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; // Base class for non-aggregate functions that have a payload class WindowValueExecutor : public WindowExecutor { public: - WindowValueExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowValueExecutor(BoundWindowExpression &wexpr, ClientContext &context); - void Sink(DataChunk &input_chunk, const idx_t input_idx, const idx_t total_count) override; - unique_ptr GetExecutorState() const override; + void Sink(DataChunk &input_chunk, const idx_t input_idx, const idx_t total_count, + WindowExecutorGlobalState &gstate) const override; -protected: - // IGNORE NULLS - ValidityMask ignore_nulls; + unique_ptr GetGlobalState(const idx_t payload_count, const ValidityMask &partition_mask, + const ValidityMask &order_mask) const override; + unique_ptr GetLocalState(const WindowExecutorGlobalState &gstate) const override; }; // class WindowNtileExecutor : public WindowValueExecutor { public: - WindowNtileExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowNtileExecutor(BoundWindowExpression &wexpr, ClientContext &context); protected: - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; class WindowLeadLagExecutor : public WindowValueExecutor { public: - WindowLeadLagExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowLeadLagExecutor(BoundWindowExpression &wexpr, ClientContext &context); - unique_ptr GetExecutorState() const override; + unique_ptr GetLocalState(const WindowExecutorGlobalState &gstate) const override; protected: - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; class WindowFirstValueExecutor : public WindowValueExecutor { public: - WindowFirstValueExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowFirstValueExecutor(BoundWindowExpression &wexpr, ClientContext &context); protected: - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; class WindowLastValueExecutor : public WindowValueExecutor { public: - WindowLastValueExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowLastValueExecutor(BoundWindowExpression &wexpr, ClientContext &context); protected: - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; class WindowNthValueExecutor : public WindowValueExecutor { public: - WindowNthValueExecutor(BoundWindowExpression &wexpr, ClientContext &context, const idx_t payload_count, - const ValidityMask &partition_mask, const ValidityMask &order_mask); + WindowNthValueExecutor(BoundWindowExpression &wexpr, ClientContext &context); protected: - void EvaluateInternal(WindowExecutorState &lstate, Vector &result, idx_t count, idx_t row_idx) const override; + void EvaluateInternal(WindowExecutorGlobalState &gstate, WindowExecutorLocalState &lstate, Vector &result, + idx_t count, idx_t row_idx) const override; }; } // namespace duckdb diff --git a/src/include/duckdb/execution/window_segment_tree.hpp b/src/include/duckdb/execution/window_segment_tree.hpp index bcdf87439f1..b9d3e557be3 100644 --- a/src/include/duckdb/execution/window_segment_tree.hpp +++ b/src/include/duckdb/execution/window_segment_tree.hpp @@ -41,48 +41,29 @@ class WindowAggregatorState { class WindowAggregator { public: - WindowAggregator(AggregateObject aggr, const LogicalType &result_type_p, const WindowExcludeMode exclude_mode_p, - idx_t partition_count); + WindowAggregator(AggregateObject aggr, const vector &arg_types_p, const LogicalType &result_type_p, + const WindowExcludeMode exclude_mode_p); virtual ~WindowAggregator(); - // Access - const DataChunk &GetInputs() const { - return inputs; - } - const ValidityMask &GetFilterMask() const { - return filter_mask; - } - // Build - virtual void Sink(DataChunk &payload_chunk, SelectionVector *filter_sel, idx_t filtered); - virtual void Finalize(const FrameStats &stats); + virtual unique_ptr GetGlobalState(idx_t group_count, + const ValidityMask &partition_mask) const; + virtual void Sink(WindowAggregatorState &gsink, DataChunk &arg_chunk, SelectionVector *filter_sel, idx_t filtered); + virtual void Finalize(WindowAggregatorState &gsink, const FrameStats &stats); // Probe virtual unique_ptr GetLocalState() const = 0; - virtual void Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &result, idx_t count, - idx_t row_idx) const = 0; + virtual void Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, const DataChunk &bounds, + Vector &result, idx_t count, idx_t row_idx) const = 0; //! A description of the aggregator const AggregateObject aggr; + //! The argument types for the function + const vector arg_types; //! The result type of the window function const LogicalType result_type; - //! The cardinality of the partition - const idx_t partition_count; //! The size of a single aggregate state const idx_t state_size; - -protected: - //! Partition data chunk - DataChunk inputs; - - //! The filtered rows in inputs. - vector filter_bits; - ValidityMask filter_mask; - idx_t filter_pos; - //! The state used by the aggregator to build. - unique_ptr gstate; - -public: //! The window exclusion clause const WindowExcludeMode exclude_mode; }; @@ -90,145 +71,90 @@ class WindowAggregator { // Used for validation class WindowNaiveAggregator : public WindowAggregator { public: - WindowNaiveAggregator(AggregateObject aggr, const LogicalType &result_type_p, - const WindowExcludeMode exclude_mode_p, idx_t partition_count); + WindowNaiveAggregator(AggregateObject aggr, const vector &arg_types_p, + const LogicalType &result_type_p, const WindowExcludeMode exclude_mode); ~WindowNaiveAggregator() override; unique_ptr GetLocalState() const override; - void Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &result, idx_t count, - idx_t row_idx) const override; + void Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, const DataChunk &bounds, + Vector &result, idx_t count, idx_t row_idx) const override; }; class WindowConstantAggregator : public WindowAggregator { public: - WindowConstantAggregator(AggregateObject aggr, const LogicalType &result_type_p, const ValidityMask &partition_mask, - WindowExcludeMode exclude_mode_p, const idx_t count); + WindowConstantAggregator(AggregateObject aggr, const vector &arg_types_p, + const LogicalType &result_type_p, WindowExcludeMode exclude_mode_p); ~WindowConstantAggregator() override { } - void Sink(DataChunk &payload_chunk, SelectionVector *filter_sel, idx_t filtered) override; - void Finalize(const FrameStats &stats) override; + unique_ptr GetGlobalState(idx_t group_count, + const ValidityMask &partition_mask) const override; + void Sink(WindowAggregatorState &gsink, DataChunk &arg_chunk, SelectionVector *filter_sel, idx_t filtered) override; + void Finalize(WindowAggregatorState &gsink, const FrameStats &stats) override; unique_ptr GetLocalState() const override; - void Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &result, idx_t count, - idx_t row_idx) const override; - -private: - void AggregateInit(); - void AggegateFinal(Vector &result, idx_t rid); - - //! Partition starts - vector partition_offsets; - //! Aggregate results - unique_ptr results; - //! The current result partition being built/read - idx_t partition; - //! The current input row being built/read - idx_t row; - //! Data pointer that contains a single state, used for intermediate window segment aggregation - vector state; - //! A vector of pointers to "state", used for intermediate window segment aggregation - Vector statep; - //! Reused result state container for the window functions - Vector statef; + void Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, const DataChunk &bounds, + Vector &result, idx_t count, idx_t row_idx) const override; }; class WindowCustomAggregator : public WindowAggregator { public: - WindowCustomAggregator(AggregateObject aggr, const LogicalType &result_type_p, - const WindowExcludeMode exclude_mode_p, idx_t partition_count); + WindowCustomAggregator(AggregateObject aggr, const vector &arg_types_p, + const LogicalType &result_type_p, const WindowExcludeMode exclude_mode); ~WindowCustomAggregator() override; - void Finalize(const FrameStats &stats) override; + unique_ptr GetGlobalState(idx_t group_count, + const ValidityMask &partition_mask) const override; + void Finalize(WindowAggregatorState &gsink, const FrameStats &stats) override; unique_ptr GetLocalState() const override; - void Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &result, idx_t count, - idx_t row_idx) const override; - - //! Partition description - unique_ptr partition_input; - - //! Data pointer that contains a single state, used for global custom window state - unique_ptr gstate; + void Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, const DataChunk &bounds, + Vector &result, idx_t count, idx_t row_idx) const override; }; class WindowSegmentTree : public WindowAggregator { public: - WindowSegmentTree(AggregateObject aggr, const LogicalType &result_type, WindowAggregationMode mode_p, - const WindowExcludeMode exclude_mode_p, idx_t count); - ~WindowSegmentTree() override; + WindowSegmentTree(AggregateObject aggr, const vector &arg_types_p, const LogicalType &result_type_p, + WindowAggregationMode mode_p, const WindowExcludeMode exclude_mode); - void Finalize(const FrameStats &stats) override; + unique_ptr GetGlobalState(idx_t group_count, + const ValidityMask &partition_mask) const override; + void Finalize(WindowAggregatorState &gsink, const FrameStats &stats) override; unique_ptr GetLocalState() const override; - void Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &result, idx_t count, - idx_t row_idx) const override; + void Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, const DataChunk &bounds, + Vector &result, idx_t count, idx_t row_idx) const override; public: - void ConstructTree(); - //! Use the combine API, if available inline bool UseCombineAPI() const { return mode < WindowAggregationMode::SEPARATE; } - //! The actual window segment tree: an array of aggregate states that represent all the intermediate nodes - unsafe_unique_array levels_flat_native; - //! For each level, the starting location in the levels_flat_native array - vector levels_flat_start; - - //! The total number of internal nodes of the tree, stored in levels_flat_native - idx_t internal_nodes; - //! Use the combine API, if available WindowAggregationMode mode; - - // TREE_FANOUT needs to cleanly divide STANDARD_VECTOR_SIZE - static constexpr idx_t TREE_FANOUT = 16; }; class WindowDistinctAggregator : public WindowAggregator { public: - using GlobalSortStatePtr = unique_ptr; - class DistinctSortTree; - - WindowDistinctAggregator(AggregateObject aggr, const LogicalType &result_type, - const WindowExcludeMode exclude_mode_p, idx_t count, ClientContext &context); - ~WindowDistinctAggregator() override; + WindowDistinctAggregator(AggregateObject aggr, const vector &arg_types_p, + const LogicalType &result_type_p, const WindowExcludeMode exclude_mode_p, + ClientContext &context); // Build - void Sink(DataChunk &args_chunk, SelectionVector *filter_sel, idx_t filtered) override; - void Finalize(const FrameStats &stats) override; + unique_ptr GetGlobalState(idx_t group_count, + const ValidityMask &partition_mask) const override; + void Sink(WindowAggregatorState &gsink, DataChunk &arg_chunk, SelectionVector *filter_sel, idx_t filtered) override; + void Finalize(WindowAggregatorState &gsink, const FrameStats &stats) override; // Evaluate unique_ptr GetLocalState() const override; - void Evaluate(WindowAggregatorState &lstate, const DataChunk &bounds, Vector &result, idx_t count, - idx_t row_idx) const override; + void Evaluate(const WindowAggregatorState &gsink, WindowAggregatorState &lstate, const DataChunk &bounds, + Vector &result, idx_t count, idx_t row_idx) const override; + //! Context for sorting ClientContext &context; - ArenaAllocator allocator; - - // Single threaded sorting for now - GlobalSortStatePtr global_sort; - LocalSortState local_sort; - idx_t payload_pos; - idx_t memory_per_thread; - - vector payload_types; - DataChunk sort_chunk; - DataChunk payload_chunk; - - //! The merge sort tree for the aggregate. - unique_ptr merge_sort_tree; - - //! The actual window segment tree: an array of aggregate states that represent all the intermediate nodes - unsafe_unique_array levels_flat_native; - //! For each level, the starting location in the levels_flat_native array - vector levels_flat_start; - - //! The total number of internal nodes of the tree, stored in levels_flat_native - idx_t internal_nodes; }; } // namespace duckdb diff --git a/src/include/duckdb/function/compression/compression.hpp b/src/include/duckdb/function/compression/compression.hpp index bfc2a90d697..5bcfe278a70 100644 --- a/src/include/duckdb/function/compression/compression.hpp +++ b/src/include/duckdb/function/compression/compression.hpp @@ -15,52 +15,52 @@ namespace duckdb { struct ConstantFun { static CompressionFunction GetFunction(PhysicalType type); - static bool TypeIsSupported(PhysicalType type); + static bool TypeIsSupported(const CompressionInfo &info); }; struct UncompressedFun { static CompressionFunction GetFunction(PhysicalType type); - static bool TypeIsSupported(PhysicalType type); + static bool TypeIsSupported(const CompressionInfo &info); }; struct RLEFun { static CompressionFunction GetFunction(PhysicalType type); - static bool TypeIsSupported(PhysicalType type); + static bool TypeIsSupported(const CompressionInfo &info); }; struct BitpackingFun { static CompressionFunction GetFunction(PhysicalType type); - static bool TypeIsSupported(PhysicalType type); + static bool TypeIsSupported(const CompressionInfo &info); }; struct DictionaryCompressionFun { static CompressionFunction GetFunction(PhysicalType type); - static bool TypeIsSupported(PhysicalType type); + static bool TypeIsSupported(const CompressionInfo &info); }; struct ChimpCompressionFun { static CompressionFunction GetFunction(PhysicalType type); - static bool TypeIsSupported(PhysicalType type); + static bool TypeIsSupported(const CompressionInfo &info); }; struct PatasCompressionFun { static CompressionFunction GetFunction(PhysicalType type); - static bool TypeIsSupported(PhysicalType type); + static bool TypeIsSupported(const CompressionInfo &info); }; struct AlpCompressionFun { static CompressionFunction GetFunction(PhysicalType type); - static bool TypeIsSupported(PhysicalType type); + static bool TypeIsSupported(const CompressionInfo &info); }; struct AlpRDCompressionFun { static CompressionFunction GetFunction(PhysicalType type); - static bool TypeIsSupported(PhysicalType type); + static bool TypeIsSupported(const CompressionInfo &info); }; struct FSSTFun { static CompressionFunction GetFunction(PhysicalType type); - static bool TypeIsSupported(PhysicalType type); + static bool TypeIsSupported(const CompressionInfo &info); }; } // namespace duckdb diff --git a/src/include/duckdb/function/compression_function.hpp b/src/include/duckdb/function/compression_function.hpp index e34e2d0c35e..67743d0c693 100644 --- a/src/include/duckdb/function/compression_function.hpp +++ b/src/include/duckdb/function/compression_function.hpp @@ -9,12 +9,12 @@ #pragma once #include "duckdb/common/common.hpp" -#include "duckdb/function/function.hpp" #include "duckdb/common/enums/compression_type.hpp" #include "duckdb/common/map.hpp" -#include "duckdb/storage/storage_info.hpp" #include "duckdb/common/mutex.hpp" +#include "duckdb/function/function.hpp" #include "duckdb/storage/data_pointer.hpp" +#include "duckdb/storage/storage_info.hpp" namespace duckdb { class DatabaseInstance; @@ -26,9 +26,37 @@ struct ColumnSegmentState; struct ColumnFetchState; struct ColumnScanState; +struct PrefetchState; struct SegmentScanState; +class CompressionInfo { +public: + CompressionInfo(const idx_t block_size, const PhysicalType &physical_type) + : block_size(block_size), physical_type(physical_type) { + D_ASSERT(block_size == Storage::BLOCK_SIZE); + } + +public: + //! The size below which the segment is compacted on flushing. + idx_t GetCompactionFlushLimit() const { + return block_size / 5 * 4; + } + //! The block size for blocks using this compression. + idx_t GetBlockSize() const { + return block_size; + } + //! The physical type to compress. + PhysicalType GetPhysicalType() const { + return physical_type; + } + +private: + idx_t block_size; + PhysicalType physical_type; +}; + struct AnalyzeState { + explicit AnalyzeState(const CompressionInfo &info) : info(info) {}; virtual ~AnalyzeState() { } @@ -42,9 +70,12 @@ struct AnalyzeState { DynamicCastCheck(this); return reinterpret_cast(*this); } + + CompressionInfo info; }; struct CompressionState { + explicit CompressionState(const CompressionInfo &info) : info(info) {}; virtual ~CompressionState() { } @@ -58,6 +89,8 @@ struct CompressionState { DynamicCastCheck(this); return reinterpret_cast(*this); } + + CompressionInfo info; }; struct CompressedSegmentState { @@ -128,6 +161,7 @@ typedef void (*compression_compress_finalize_t)(CompressionState &state); //===--------------------------------------------------------------------===// // Uncompress / Scan //===--------------------------------------------------------------------===// +typedef void (*compression_init_prefetch_t)(ColumnSegment &segment, PrefetchState &prefetch_state); typedef unique_ptr (*compression_init_segment_scan_t)(ColumnSegment &segment); //! Function prototype used for reading an entire vector (STANDARD_VECTOR_SIZE) @@ -178,13 +212,14 @@ class CompressionFunction { compression_revert_append_t revert_append = nullptr, compression_serialize_state_t serialize_state = nullptr, compression_deserialize_state_t deserialize_state = nullptr, - compression_cleanup_state_t cleanup_state = nullptr) + compression_cleanup_state_t cleanup_state = nullptr, + compression_init_prefetch_t init_prefetch = nullptr) : type(type), data_type(data_type), init_analyze(init_analyze), analyze(analyze), final_analyze(final_analyze), init_compression(init_compression), compress(compress), compress_finalize(compress_finalize), - init_scan(init_scan), scan_vector(scan_vector), scan_partial(scan_partial), fetch_row(fetch_row), skip(skip), - init_segment(init_segment), init_append(init_append), append(append), finalize_append(finalize_append), - revert_append(revert_append), serialize_state(serialize_state), deserialize_state(deserialize_state), - cleanup_state(cleanup_state) { + init_prefetch(init_prefetch), init_scan(init_scan), scan_vector(scan_vector), scan_partial(scan_partial), + fetch_row(fetch_row), skip(skip), init_segment(init_segment), init_append(init_append), append(append), + finalize_append(finalize_append), revert_append(revert_append), serialize_state(serialize_state), + deserialize_state(deserialize_state), cleanup_state(cleanup_state) { } //! Compression type @@ -213,6 +248,8 @@ class CompressionFunction { //! compress_finalize is called after compression_compress_finalize_t compress_finalize; + //! Initialize prefetch state with required I/O data to scan this segment + compression_init_prefetch_t init_prefetch; //! init_scan is called to set up the scan state compression_init_segment_scan_t init_scan; //! scan_vector scans an entire vector using the scan state diff --git a/src/include/duckdb/function/copy_function.hpp b/src/include/duckdb/function/copy_function.hpp index 7e3a4808b43..00e4f4da459 100644 --- a/src/include/duckdb/function/copy_function.hpp +++ b/src/include/duckdb/function/copy_function.hpp @@ -74,6 +74,13 @@ struct CopyFunctionBindInput { string file_extension; }; +struct CopyToSelectInput { + ClientContext &context; + case_insensitive_map_t> &options; + vector> select_list; + CopyToType copy_to_type; +}; + enum class CopyFunctionExecutionMode { REGULAR_COPY_TO_FILE, PARALLEL_COPY_TO_FILE, BATCH_COPY_TO_FILE }; typedef BoundStatement (*copy_to_plan_t)(Binder &binder, CopyStatement &stmt); @@ -105,25 +112,31 @@ typedef void (*copy_flush_batch_t)(ClientContext &context, FunctionData &bind_da PreparedBatchData &batch); typedef idx_t (*copy_desired_batch_size_t)(ClientContext &context, FunctionData &bind_data); -typedef idx_t (*copy_file_size_bytes_t)(GlobalFunctionData &gstate); +typedef bool (*copy_rotate_files_t)(FunctionData &bind_data, const optional_idx &file_size_bytes); + +typedef bool (*copy_rotate_next_file_t)(GlobalFunctionData &gstate, FunctionData &bind_data, + const optional_idx &file_size_bytes); -enum class CopyTypeSupport { SUPPORTED, LOSSY, UNSUPPORTED }; +typedef vector> (*copy_to_select_t)(CopyToSelectInput &input); -typedef CopyTypeSupport (*copy_supports_type_t)(const LogicalType &type); +enum class CopyFunctionReturnType : uint8_t { CHANGED_ROWS = 0, CHANGED_ROWS_AND_FILE_LIST = 1 }; +vector GetCopyFunctionReturnNames(CopyFunctionReturnType return_type); +vector GetCopyFunctionReturnLogicalTypes(CopyFunctionReturnType return_type); class CopyFunction : public Function { // NOLINT: work-around bug in clang-tidy public: explicit CopyFunction(const string &name) - : Function(name), plan(nullptr), copy_to_bind(nullptr), copy_to_initialize_local(nullptr), - copy_to_initialize_global(nullptr), copy_to_sink(nullptr), copy_to_combine(nullptr), - copy_to_finalize(nullptr), execution_mode(nullptr), prepare_batch(nullptr), flush_batch(nullptr), - desired_batch_size(nullptr), file_size_bytes(nullptr), serialize(nullptr), deserialize(nullptr), - supports_type(nullptr), copy_from_bind(nullptr) { + : Function(name), plan(nullptr), copy_to_select(nullptr), copy_to_bind(nullptr), + copy_to_initialize_local(nullptr), copy_to_initialize_global(nullptr), copy_to_sink(nullptr), + copy_to_combine(nullptr), copy_to_finalize(nullptr), execution_mode(nullptr), prepare_batch(nullptr), + flush_batch(nullptr), desired_batch_size(nullptr), rotate_files(nullptr), rotate_next_file(nullptr), + serialize(nullptr), deserialize(nullptr), copy_from_bind(nullptr) { } //! Plan rewrite copy function copy_to_plan_t plan; + copy_to_select_t copy_to_select; copy_to_bind_t copy_to_bind; copy_to_initialize_local_t copy_to_initialize_local; copy_to_initialize_global_t copy_to_initialize_global; @@ -135,13 +148,13 @@ class CopyFunction : public Function { // NOLINT: work-around bug in clang-tidy copy_prepare_batch_t prepare_batch; copy_flush_batch_t flush_batch; copy_desired_batch_size_t desired_batch_size; - copy_file_size_bytes_t file_size_bytes; + + copy_rotate_files_t rotate_files; + copy_rotate_next_file_t rotate_next_file; copy_to_serialize_t serialize; copy_to_deserialize_t deserialize; - copy_supports_type_t supports_type; - copy_from_bind_t copy_from_bind; TableFunction copy_from_function; diff --git a/src/include/duckdb/function/function.hpp b/src/include/duckdb/function/function.hpp index 7e89476e252..8575f270fd6 100644 --- a/src/include/duckdb/function/function.hpp +++ b/src/include/duckdb/function/function.hpp @@ -78,11 +78,6 @@ struct TableFunctionData : public FunctionData { DUCKDB_API bool Equals(const FunctionData &other) const override; }; -struct PyTableFunctionData : public TableFunctionData { - //! External dependencies of this table function - unique_ptr external_dependency; -}; - struct FunctionParameters { vector values; named_parameter_map_t named_parameters; diff --git a/src/include/duckdb/function/function_binder.hpp b/src/include/duckdb/function/function_binder.hpp index bddc1ffbb7a..9f1fb315df3 100644 --- a/src/include/duckdb/function/function_binder.hpp +++ b/src/include/duckdb/function/function_binder.hpp @@ -50,14 +50,17 @@ class FunctionBinder { DUCKDB_API unique_ptr BindScalarFunction(const string &schema, const string &name, vector> children, ErrorData &error, - bool is_operator = false, Binder *binder = nullptr); + bool is_operator = false, + optional_ptr binder = nullptr); DUCKDB_API unique_ptr BindScalarFunction(ScalarFunctionCatalogEntry &function, vector> children, ErrorData &error, - bool is_operator = false, Binder *binder = nullptr); + bool is_operator = false, + optional_ptr binder = nullptr); - DUCKDB_API unique_ptr BindScalarFunction(ScalarFunction bound_function, - vector> children, - bool is_operator = false); + DUCKDB_API unique_ptr BindScalarFunction(ScalarFunction bound_function, + vector> children, + bool is_operator = false, + optional_ptr binder = nullptr); DUCKDB_API unique_ptr BindAggregateFunction(AggregateFunction bound_function, vector> children, diff --git a/src/include/duckdb/function/replacement_scan.hpp b/src/include/duckdb/function/replacement_scan.hpp index 455f8ae19eb..70572c209a4 100644 --- a/src/include/duckdb/function/replacement_scan.hpp +++ b/src/include/duckdb/function/replacement_scan.hpp @@ -17,12 +17,34 @@ class ClientContext; class TableRef; struct ReplacementScanData { +public: virtual ~ReplacementScanData() { } + +public: + template + TARGET &Cast() { + DynamicCastCheck(this); + return reinterpret_cast(*this); + } + template + const TARGET &Cast() const { + DynamicCastCheck(this); + return reinterpret_cast(*this); + } +}; + +struct ReplacementScanInput { +public: + explicit ReplacementScanInput(const string &table_name) : table_name(table_name) { + } + +public: + const string &table_name; }; -typedef unique_ptr (*replacement_scan_t)(ClientContext &context, const string &table_name, - ReplacementScanData *data); +typedef unique_ptr (*replacement_scan_t)(ClientContext &context, ReplacementScanInput &input, + optional_ptr data); //! Replacement table scans are automatically attempted when a table name cannot be found in the schema //! This allows you to do e.g. SELECT * FROM 'filename.csv', and automatically convert this into a CSV scan diff --git a/src/include/duckdb/function/scalar/generic_functions.hpp b/src/include/duckdb/function/scalar/generic_functions.hpp index cef16195ccd..1dc54bb0cec 100644 --- a/src/include/duckdb/function/scalar/generic_functions.hpp +++ b/src/include/duckdb/function/scalar/generic_functions.hpp @@ -11,6 +11,8 @@ #include "duckdb/function/scalar_function.hpp" #include "duckdb/function/function_set.hpp" #include "duckdb/function/built_in_functions.hpp" +#include "duckdb/common/serializer/serializer.hpp" +#include "duckdb/common/serializer/deserializer.hpp" namespace duckdb { class BoundFunctionExpression; diff --git a/src/include/duckdb/function/scalar/regexp.hpp b/src/include/duckdb/function/scalar/regexp.hpp index 1b33d3c77fc..fa6a3e91f81 100644 --- a/src/include/duckdb/function/scalar/regexp.hpp +++ b/src/include/duckdb/function/scalar/regexp.hpp @@ -106,9 +106,12 @@ struct RegexStringPieceArgs { } RegexStringPieceArgs &operator=(RegexStringPieceArgs &&other) noexcept { - std::swap(this->size, other.size); - std::swap(this->capacity, other.capacity); - std::swap(this->group_buffer, other.group_buffer); + this->size = other.size; + this->capacity = other.capacity; + this->group_buffer = other.group_buffer; + other.size = 0; + other.capacity = 0; + other.group_buffer = nullptr; return *this; } diff --git a/src/include/duckdb/function/scalar/sequence_functions.hpp b/src/include/duckdb/function/scalar/sequence_functions.hpp index 7323ea03715..34103bfc103 100644 --- a/src/include/duckdb/function/scalar/sequence_functions.hpp +++ b/src/include/duckdb/function/scalar/sequence_functions.hpp @@ -16,12 +16,11 @@ namespace duckdb { struct NextvalBindData : public FunctionData { - explicit NextvalBindData(optional_ptr sequence) - : sequence(sequence), create_info(sequence ? sequence->GetInfo() : nullptr) { + explicit NextvalBindData(SequenceCatalogEntry &sequence) : sequence(sequence), create_info(sequence.GetInfo()) { } //! The sequence to use for the nextval computation; only if the sequence is a constant - optional_ptr sequence; + SequenceCatalogEntry &sequence; //! The CreateInfo for the above sequence, if it exists unique_ptr create_info; @@ -32,7 +31,7 @@ struct NextvalBindData : public FunctionData { bool Equals(const FunctionData &other_p) const override { auto &other = other_p.Cast(); - return sequence == other.sequence; + return RefersToSameObject(sequence, other.sequence); } }; diff --git a/src/include/duckdb/function/scalar/strftime_format.hpp b/src/include/duckdb/function/scalar/strftime_format.hpp index a538db4255b..ff8e6bc0998 100644 --- a/src/include/duckdb/function/scalar/strftime_format.hpp +++ b/src/include/duckdb/function/scalar/strftime_format.hpp @@ -98,6 +98,7 @@ struct StrTimeFormat { struct StrfTimeFormat : public StrTimeFormat { // NOLINT: work-around bug in clang-tidy DUCKDB_API idx_t GetLength(date_t date, dtime_t time, int32_t utc_offset, const char *tz_name); + DUCKDB_API void FormatStringNS(date_t date, int32_t data[8], const char *tz_name, char *target) const; DUCKDB_API void FormatString(date_t date, int32_t data[8], const char *tz_name, char *target); void FormatString(date_t date, dtime_t time, char *target); @@ -105,6 +106,7 @@ struct StrfTimeFormat : public StrTimeFormat { // NOLINT: work-around bug in cla DUCKDB_API void ConvertDateVector(Vector &input, Vector &result, idx_t count); DUCKDB_API void ConvertTimestampVector(Vector &input, Vector &result, idx_t count); + DUCKDB_API void ConvertTimestampNSVector(Vector &input, Vector &result, idx_t count); protected: //! The variable-length specifiers. To determine total string size, these need to be checked. @@ -115,17 +117,21 @@ struct StrfTimeFormat : public StrTimeFormat { // NOLINT: work-around bug in cla protected: DUCKDB_API void AddFormatSpecifier(string preceding_literal, StrTimeSpecifier specifier) override; - static idx_t GetSpecifierLength(StrTimeSpecifier specifier, date_t date, dtime_t time, int32_t utc_offset, - const char *tz_name); - char *WriteString(char *target, const string_t &str); - char *Write2(char *target, uint8_t value); - char *WritePadded2(char *target, uint32_t value); - char *WritePadded3(char *target, uint32_t value); - char *WritePadded(char *target, uint32_t value, size_t padding); + static idx_t GetSpecifierLength(StrTimeSpecifier specifier, date_t date, int32_t data[8], const char *tz_name); + idx_t GetLength(date_t date, int32_t data[8], const char *tz_name) const; + + string_t ConvertTimestampValue(const timestamp_t &input, Vector &result) const; + string_t ConvertTimestampValue(const timestamp_ns_t &input, Vector &result) const; + + char *WriteString(char *target, const string_t &str) const; + char *Write2(char *target, uint8_t value) const; + char *WritePadded2(char *target, uint32_t value) const; + char *WritePadded3(char *target, uint32_t value) const; + char *WritePadded(char *target, uint32_t value, size_t padding) const; bool IsDateSpecifier(StrTimeSpecifier specifier); - char *WriteDateSpecifier(StrTimeSpecifier specifier, date_t date, char *target); + char *WriteDateSpecifier(StrTimeSpecifier specifier, date_t date, char *target) const; char *WriteStandardSpecifier(StrTimeSpecifier specifier, int32_t data[], const char *tz_name, size_t tz_len, - char *target); + char *target) const; }; struct StrpTimeFormat : public StrTimeFormat { // NOLINT: work-around bug in clang-tidy @@ -134,7 +140,7 @@ struct StrpTimeFormat : public StrTimeFormat { // NOLINT: work-around bug in cla //! Type-safe parsing argument struct ParseResult { - int32_t data[8]; // year, month, day, hour, min, sec, µs, offset + int32_t data[8]; // year, month, day, hour, min, sec, ns, offset string tz; string error_message; optional_idx error_position; @@ -142,13 +148,18 @@ struct StrpTimeFormat : public StrTimeFormat { // NOLINT: work-around bug in cla bool is_special; date_t special; + int32_t GetMicros() const; + date_t ToDate(); dtime_t ToTime(); + int64_t ToTimeNS(); timestamp_t ToTimestamp(); + timestamp_ns_t ToTimestampNS(); bool TryToDate(date_t &result); bool TryToTime(dtime_t &result); bool TryToTimestamp(timestamp_t &result); + bool TryToTimestampNS(timestamp_ns_t &result); DUCKDB_API string FormatError(string_t input, const string &format_specifier); }; @@ -165,10 +176,12 @@ struct StrpTimeFormat : public StrTimeFormat { // NOLINT: work-around bug in cla DUCKDB_API bool TryParseDate(const char *data, size_t size, date_t &result) const; DUCKDB_API bool TryParseTimestamp(const char *data, size_t size, timestamp_t &result) const; + DUCKDB_API bool TryParseTimestampNS(const char *data, size_t size, timestamp_ns_t &result) const; DUCKDB_API bool TryParseDate(string_t str, date_t &result, string &error_message) const; DUCKDB_API bool TryParseTime(string_t str, dtime_t &result, string &error_message) const; DUCKDB_API bool TryParseTimestamp(string_t str, timestamp_t &result, string &error_message) const; + DUCKDB_API bool TryParseTimestampNS(string_t str, timestamp_ns_t &result, string &error_message) const; void Serialize(Serializer &serializer) const; static StrpTimeFormat Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/function/scalar/string_functions.hpp b/src/include/duckdb/function/scalar/string_functions.hpp index c96c2b3c33c..743b5b76239 100644 --- a/src/include/duckdb/function/scalar/string_functions.hpp +++ b/src/include/duckdb/function/scalar/string_functions.hpp @@ -9,7 +9,7 @@ #pragma once #include "duckdb/function/function_set.hpp" -#include "utf8proc.hpp" +#include "utf8proc_wrapper.hpp" #include "duckdb/function/built_in_functions.hpp" namespace duckdb_re2 { @@ -44,6 +44,11 @@ struct StripAccentsFun { struct ConcatFun { static void RegisterFunction(BuiltinFunctions &set); + static ScalarFunction GetFunction(); +}; + +struct ConcatWSFun { + static void RegisterFunction(BuiltinFunctions &set); }; struct LengthFun { @@ -69,13 +74,8 @@ struct LengthFun { auto input_length = input.GetSize(); for (idx_t i = 0; i < input_length; i++) { if (input_data[i] & 0x80) { - int64_t length = 0; // non-ascii character: use grapheme iterator on remainder of string - utf8proc_grapheme_callback(input_data, input_length, [&](size_t start, size_t end) { - length++; - return true; - }); - return length; + return UnsafeNumericCast(Utf8Proc::GraphemeCount(input_data, input_length)); } } return UnsafeNumericCast(input_length); diff --git a/src/include/duckdb/function/scalar_function.hpp b/src/include/duckdb/function/scalar_function.hpp index 917f09eed2b..db67afc762c 100644 --- a/src/include/duckdb/function/scalar_function.hpp +++ b/src/include/duckdb/function/scalar_function.hpp @@ -34,6 +34,21 @@ struct FunctionLocalState { } }; +struct ScalarFunctionInfo { + DUCKDB_API virtual ~ScalarFunctionInfo(); + + template + TARGET &Cast() { + DynamicCastCheck(this); + return reinterpret_cast(*this); + } + template + const TARGET &Cast() const { + DynamicCastCheck(this); + return reinterpret_cast(*this); + } +}; + class Binder; class BoundFunctionExpression; class LogicalDependencyList; @@ -51,6 +66,26 @@ struct FunctionStatisticsInput { unique_ptr *expr_ptr; }; +struct FunctionModifiedDatabasesInput { + FunctionModifiedDatabasesInput(optional_ptr bind_data_p, unordered_set &modified_databases_p) + : bind_data(bind_data_p), modified_databases(modified_databases_p) { + } + + optional_ptr bind_data; + unordered_set &modified_databases; +}; + +struct FunctionBindExpressionInput { + FunctionBindExpressionInput(ClientContext &context_p, optional_ptr bind_data_p, + BoundFunctionExpression &function_p) + : context(context_p), bind_data(bind_data_p), function(function_p) { + } + + ClientContext &context; + optional_ptr bind_data; + BoundFunctionExpression &function; +}; + //! The scalar function type typedef std::function scalar_function_t; //! The type to bind the scalar function and to create the function data @@ -66,11 +101,16 @@ typedef void (*dependency_function_t)(BoundFunctionExpression &expr, LogicalDepe typedef unique_ptr (*function_statistics_t)(ClientContext &context, FunctionStatisticsInput &input); //! The type to bind lambda-specific parameter types typedef LogicalType (*bind_lambda_function_t)(const idx_t parameter_idx, const LogicalType &list_child_type); +//! The type to bind lambda-specific parameter types +typedef void (*get_modified_databases_t)(FunctionModifiedDatabasesInput &input); typedef void (*function_serialize_t)(Serializer &serializer, const optional_ptr bind_data, const ScalarFunction &function); typedef unique_ptr (*function_deserialize_t)(Deserializer &deserializer, ScalarFunction &function); +//! The type to bind lambda-specific parameter types +typedef unique_ptr (*function_bind_expression_t)(FunctionBindExpressionInput &input); + class ScalarFunction : public BaseScalarFunction { // NOLINT: work-around bug in clang-tidy public: DUCKDB_API ScalarFunction(string name, vector arguments, LogicalType return_type, @@ -102,9 +142,15 @@ class ScalarFunction : public BaseScalarFunction { // NOLINT: work-around bug in function_statistics_t statistics; //! The lambda bind function (if any) bind_lambda_function_t bind_lambda; + //! Function to bind the result function expression directly (if any) + function_bind_expression_t bind_expression; + //! Gets the modified databases (if any) + get_modified_databases_t get_modified_databases; function_serialize_t serialize; function_deserialize_t deserialize; + //! Additional function info, passed to the bind + shared_ptr function_info; DUCKDB_API bool operator==(const ScalarFunction &rhs) const; DUCKDB_API bool operator!=(const ScalarFunction &rhs) const; diff --git a/src/include/duckdb/function/table/arrow.hpp b/src/include/duckdb/function/table/arrow.hpp index 8a9201217f9..d2ea0230440 100644 --- a/src/include/duckdb/function/table/arrow.hpp +++ b/src/include/duckdb/function/table/arrow.hpp @@ -46,10 +46,12 @@ typedef unique_ptr (*stream_factory_produce_t)(uintptr_ ArrowStreamParameters ¶meters); typedef void (*stream_factory_get_schema_t)(ArrowArrayStream *stream_factory_ptr, ArrowSchema &schema); -struct ArrowScanFunctionData : public PyTableFunctionData { +struct ArrowScanFunctionData : public TableFunctionData { public: - ArrowScanFunctionData(stream_factory_produce_t scanner_producer_p, uintptr_t stream_factory_ptr_p) - : lines_read(0), stream_factory_ptr(stream_factory_ptr_p), scanner_producer(scanner_producer_p) { + ArrowScanFunctionData(stream_factory_produce_t scanner_producer_p, uintptr_t stream_factory_ptr_p, + shared_ptr dependency = nullptr) + : lines_read(0), stream_factory_ptr(stream_factory_ptr_p), scanner_producer(scanner_producer_p), + dependency(std::move(dependency)) { } vector all_types; atomic lines_read; @@ -59,6 +61,8 @@ struct ArrowScanFunctionData : public PyTableFunctionData { uintptr_t stream_factory_ptr; //! Pointer to the scanner factory produce stream_factory_produce_t scanner_producer; + //! The (optional) dependency of this function (used in Python for example) + shared_ptr dependency; //! Arrow table data ArrowTableType arrow_table; }; diff --git a/src/include/duckdb/function/table/arrow/arrow_duck_schema.hpp b/src/include/duckdb/function/table/arrow/arrow_duck_schema.hpp index 2915be4038d..a9ab1e78720 100644 --- a/src/include/duckdb/function/table/arrow/arrow_duck_schema.hpp +++ b/src/include/duckdb/function/table/arrow/arrow_duck_schema.hpp @@ -12,85 +12,39 @@ #include "duckdb/common/unordered_map.hpp" #include "duckdb/common/vector.hpp" #include "duckdb/common/unique_ptr.hpp" +#include "duckdb/function/table/arrow/arrow_type_info.hpp" namespace duckdb { -//===--------------------------------------------------------------------===// -// Arrow Variable Size Types -//===--------------------------------------------------------------------===// -enum class ArrowVariableSizeType : uint8_t { FIXED_SIZE = 0, NORMAL = 1, SUPER_SIZE = 2 }; - -//===--------------------------------------------------------------------===// -// Arrow Time/Date Types -//===--------------------------------------------------------------------===// -enum class ArrowDateTimeType : uint8_t { - MILLISECONDS = 0, - MICROSECONDS = 1, - NANOSECONDS = 2, - SECONDS = 3, - DAYS = 4, - MONTHS = 5, - MONTH_DAY_NANO = 6 -}; class ArrowType { public: //! From a DuckDB type - ArrowType(LogicalType type_p) // NOLINT: allow implicit conversion - : type(std::move(type_p)), size_type(ArrowVariableSizeType::NORMAL), - date_time_precision(ArrowDateTimeType::DAYS) {}; - - //! From a DuckDB type + fixed_size - ArrowType(LogicalType type_p, idx_t fixed_size_p) // NOLINT: work-around bug in clang-tidy - : type(std::move(type_p)), size_type(ArrowVariableSizeType::FIXED_SIZE), - date_time_precision(ArrowDateTimeType::DAYS), fixed_size(fixed_size_p) {}; - - //! From a DuckDB type + variable size type - ArrowType(LogicalType type_p, ArrowVariableSizeType size_type_p) // NOLINT: work-around bug in clang-tidy - : type(std::move(type_p)), size_type(size_type_p), date_time_precision(ArrowDateTimeType::DAYS) {}; - - //! From a DuckDB type + datetime type - ArrowType(LogicalType type_p, ArrowDateTimeType date_time_precision_p) // NOLINT: work-around bug in clang-tidy - : type(std::move(type_p)), size_type(ArrowVariableSizeType::NORMAL), - date_time_precision(date_time_precision_p) {}; - - void AddChild(unique_ptr child); - - void AssignChildren(vector> children); + explicit ArrowType(LogicalType type_p, unique_ptr type_info = nullptr) + : type(std::move(type_p)), type_info(std::move(type_info)) { + } +public: LogicalType GetDuckType(bool use_dictionary = false) const; - ArrowVariableSizeType GetSizeType() const; - - idx_t FixedSize() const; - void SetDictionary(unique_ptr dictionary); - bool HasDictionary() const; - - ArrowDateTimeType GetDateTimeType() const; - - void SetRunEndEncoded(); - const ArrowType &GetDictionary() const; bool RunEndEncoded() const; + void SetRunEndEncoded(); - const ArrowType &operator[](idx_t index) const; + template + const T &GetTypeInfo() const { + return type_info->Cast(); + } private: LogicalType type; - //! If we have a nested type, their children's type. - vector> children; - //! If its a variable size type (e.g., strings, blobs, lists) holds which type it is - ArrowVariableSizeType size_type; - //! If this is a date/time holds its precision - ArrowDateTimeType date_time_precision; - //! Only for size types with fixed size - idx_t fixed_size = 0; //! Hold the optional type if the array is a dictionary unique_ptr dictionary_type; //! Is run-end-encoded bool run_end_encoded = false; + unique_ptr type_info; }; using arrow_column_map_t = unordered_map>; diff --git a/src/include/duckdb/function/table/arrow/arrow_type_info.hpp b/src/include/duckdb/function/table/arrow/arrow_type_info.hpp new file mode 100644 index 00000000000..fa83584961c --- /dev/null +++ b/src/include/duckdb/function/table/arrow/arrow_type_info.hpp @@ -0,0 +1,142 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/function/table/arrow/arrow_type_info.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/types.hpp" +#include "duckdb/common/unordered_map.hpp" +#include "duckdb/common/vector.hpp" +#include "duckdb/common/unique_ptr.hpp" +#include "duckdb/function/table/arrow/enum/arrow_type_info_type.hpp" +#include "duckdb/function/table/arrow/enum/arrow_datetime_type.hpp" +#include "duckdb/function/table/arrow/enum/arrow_variable_size_type.hpp" +#include "duckdb/common/enum_util.hpp" + +namespace duckdb { + +class ArrowType; + +struct ArrowTypeInfo { +public: + explicit ArrowTypeInfo(ArrowTypeInfoType type); + virtual ~ArrowTypeInfo(); + + ArrowTypeInfoType type; + +public: + template + TARGET &Cast() { + D_ASSERT(dynamic_cast(this)); + if (type != TARGET::TYPE) { + throw InternalException("Failed to cast ArrowTypeInfo, type mismatch (expected: %s, got: %s)", + EnumUtil::ToString(TARGET::TYPE), EnumUtil::ToString(type)); + } + return reinterpret_cast(*this); + } + template + const TARGET &Cast() const { + D_ASSERT(dynamic_cast(this)); + if (type != TARGET::TYPE) { + throw InternalException("Failed to cast ArrowTypeInfo, type mismatch (expected: %s, got: %s)", + EnumUtil::ToString(TARGET::TYPE), EnumUtil::ToString(type)); + } + return reinterpret_cast(*this); + } +}; + +struct ArrowStructInfo : public ArrowTypeInfo { +public: + static constexpr const ArrowTypeInfoType TYPE = ArrowTypeInfoType::STRUCT; + +public: + explicit ArrowStructInfo(vector> children); + ~ArrowStructInfo() override; + +public: + idx_t ChildCount() const; + const ArrowType &GetChild(idx_t index) const; + const vector> &GetChildren() const; + +private: + vector> children; +}; + +struct ArrowDateTimeInfo : public ArrowTypeInfo { +public: + static constexpr const ArrowTypeInfoType TYPE = ArrowTypeInfoType::DATE_TIME; + +public: + explicit ArrowDateTimeInfo(ArrowDateTimeType size); + ~ArrowDateTimeInfo() override; + +public: + ArrowDateTimeType GetDateTimeType() const; + +private: + ArrowDateTimeType size_type; +}; + +struct ArrowStringInfo : public ArrowTypeInfo { +public: + static constexpr const ArrowTypeInfoType TYPE = ArrowTypeInfoType::STRING; + +public: + explicit ArrowStringInfo(ArrowVariableSizeType size); + explicit ArrowStringInfo(idx_t fixed_size); + ~ArrowStringInfo() override; + +public: + ArrowVariableSizeType GetSizeType() const; + idx_t FixedSize() const; + +private: + ArrowVariableSizeType size_type; + idx_t fixed_size; +}; + +struct ArrowListInfo : public ArrowTypeInfo { +public: + static constexpr const ArrowTypeInfoType TYPE = ArrowTypeInfoType::LIST; + +public: + static unique_ptr ListView(unique_ptr child, ArrowVariableSizeType size); + static unique_ptr List(unique_ptr child, ArrowVariableSizeType size); + ~ArrowListInfo() override; + +public: + ArrowVariableSizeType GetSizeType() const; + bool IsView() const; + ArrowType &GetChild() const; + +private: + explicit ArrowListInfo(unique_ptr child, ArrowVariableSizeType size); + +private: + ArrowVariableSizeType size_type; + bool is_view = false; + unique_ptr child; +}; + +struct ArrowArrayInfo : public ArrowTypeInfo { +public: + static constexpr const ArrowTypeInfoType TYPE = ArrowTypeInfoType::ARRAY; + +public: + explicit ArrowArrayInfo(unique_ptr child, idx_t fixed_size); + ~ArrowArrayInfo() override; + +public: + idx_t FixedSize() const; + ArrowType &GetChild() const; + +private: + unique_ptr child; + idx_t fixed_size; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/function/table/arrow/enum/arrow_datetime_type.hpp b/src/include/duckdb/function/table/arrow/enum/arrow_datetime_type.hpp new file mode 100644 index 00000000000..41f98738560 --- /dev/null +++ b/src/include/duckdb/function/table/arrow/enum/arrow_datetime_type.hpp @@ -0,0 +1,18 @@ +#pragma once + +namespace duckdb { + +//===--------------------------------------------------------------------===// +// Arrow Time/Date Types +//===--------------------------------------------------------------------===// +enum class ArrowDateTimeType : uint8_t { + MILLISECONDS, + MICROSECONDS, + NANOSECONDS, + SECONDS, + DAYS, + MONTHS, + MONTH_DAY_NANO +}; + +} // namespace duckdb diff --git a/src/include/duckdb/function/table/arrow/enum/arrow_type_info_type.hpp b/src/include/duckdb/function/table/arrow/enum/arrow_type_info_type.hpp new file mode 100644 index 00000000000..e478e153189 --- /dev/null +++ b/src/include/duckdb/function/table/arrow/enum/arrow_type_info_type.hpp @@ -0,0 +1,7 @@ +#pragma once + +namespace duckdb { + +enum class ArrowTypeInfoType : uint8_t { LIST, STRUCT, DATE_TIME, STRING, ARRAY }; + +} // namespace duckdb diff --git a/src/include/duckdb/function/table/arrow/enum/arrow_variable_size_type.hpp b/src/include/duckdb/function/table/arrow/enum/arrow_variable_size_type.hpp new file mode 100644 index 00000000000..be85abc9bc1 --- /dev/null +++ b/src/include/duckdb/function/table/arrow/enum/arrow_variable_size_type.hpp @@ -0,0 +1,10 @@ +#pragma once + +namespace duckdb { + +//===--------------------------------------------------------------------===// +// Arrow Variable Size Types +//===--------------------------------------------------------------------===// +enum class ArrowVariableSizeType : uint8_t { NORMAL, FIXED_SIZE, SUPER_SIZE, VIEW }; + +} // namespace duckdb diff --git a/src/include/duckdb/function/table/range.hpp b/src/include/duckdb/function/table/range.hpp index fa69d615d9a..6070fb25783 100644 --- a/src/include/duckdb/function/table/range.hpp +++ b/src/include/duckdb/function/table/range.hpp @@ -49,4 +49,8 @@ struct ReadTextFunction { static void RegisterFunction(BuiltinFunctions &set); }; +struct QueryTableFunction { + static void RegisterFunction(BuiltinFunctions &set); +}; + } // namespace duckdb diff --git a/src/include/duckdb/function/table/read_csv.hpp b/src/include/duckdb/function/table/read_csv.hpp index 272fbbf6855..0e8cd4b741d 100644 --- a/src/include/duckdb/function/table/read_csv.hpp +++ b/src/include/duckdb/function/table/read_csv.hpp @@ -95,6 +95,7 @@ struct ReadCSVData : public BaseCSVData { vector> union_readers; //! Reader bind data MultiFileReaderBindData reader_bind; + vector column_info; void Initialize(unique_ptr &reader) { diff --git a/src/include/duckdb/function/table_function.hpp b/src/include/duckdb/function/table_function.hpp index bd8e176973e..c03ed17a1f1 100644 --- a/src/include/duckdb/function/table_function.hpp +++ b/src/include/duckdb/function/table_function.hpp @@ -25,6 +25,7 @@ class LogicalDependencyList; class LogicalGet; class TableFilterSet; class TableCatalogEntry; +struct MultiFileReader; struct TableFunctionInfo { DUCKDB_API virtual ~TableFunctionInfo(); @@ -83,9 +84,10 @@ struct LocalTableFunctionState { struct TableFunctionBindInput { TableFunctionBindInput(vector &inputs, named_parameter_map_t &named_parameters, vector &input_table_types, vector &input_table_names, - optional_ptr info, optional_ptr binder) + optional_ptr info, optional_ptr binder, + TableFunction &table_function, const TableFunctionRef &ref) : inputs(inputs), named_parameters(named_parameters), input_table_types(input_table_types), - input_table_names(input_table_names), info(info), binder(binder) { + input_table_names(input_table_names), info(info), binder(binder), table_function(table_function), ref(ref) { } vector &inputs; @@ -94,6 +96,8 @@ struct TableFunctionBindInput { vector &input_table_names; optional_ptr info; optional_ptr binder; + TableFunction &table_function; + const TableFunctionRef &ref; }; struct TableFunctionInitInput { @@ -198,6 +202,8 @@ typedef idx_t (*table_function_get_batch_index_t)(ClientContext &context, const typedef BindInfo (*table_function_get_bind_info_t)(const optional_ptr bind_data); +typedef unique_ptr (*table_function_get_multi_file_reader_t)(); + typedef double (*table_function_progress_t)(ClientContext &context, const FunctionData *bind_data, const GlobalTableFunctionState *global_state); typedef void (*table_function_dependency_t)(LogicalDependencyList &dependencies, const FunctionData *bind_data); @@ -212,6 +218,9 @@ typedef void (*table_function_serialize_t)(Serializer &serializer, const optiona const TableFunction &function); typedef unique_ptr (*table_function_deserialize_t)(Deserializer &deserializer, TableFunction &function); +typedef void (*table_function_type_pushdown_t)(ClientContext &context, optional_ptr bind_data, + const unordered_map &new_column_types); + class TableFunction : public SimpleNamedParameterFunction { // NOLINT: work-around bug in clang-tidy public: DUCKDB_API @@ -267,6 +276,10 @@ class TableFunction : public SimpleNamedParameterFunction { // NOLINT: work-arou table_function_get_batch_index_t get_batch_index; //! (Optional) returns extra bind info table_function_get_bind_info_t get_bind_info; + //! (Optional) pushes down type information to scanner, returns true if pushdown was successful + table_function_type_pushdown_t type_pushdown; + //! (Optional) allows injecting a custom MultiFileReader implementation + table_function_get_multi_file_reader_t get_multi_file_reader; table_function_serialize_t serialize; table_function_deserialize_t deserialize; diff --git a/src/include/duckdb/logging/http_logger.hpp b/src/include/duckdb/logging/http_logger.hpp new file mode 100644 index 00000000000..1ea9fa70e9e --- /dev/null +++ b/src/include/duckdb/logging/http_logger.hpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/logging/http_logger.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/fstream.hpp" +#include "duckdb/common/mutex.hpp" +#include "duckdb/common/printer.hpp" +#include "duckdb/main/client_context.hpp" + +#include + +namespace duckdb { + +//! This has to be templated because we have two namespaces: +//! 1. duckdb_httplib +//! 2. duckdb_httplib_openssl +//! These have essentially the same code, but we cannot convert between them +//! We get around that by templating everything, which requires implementing everything in the header +class HTTPLogger { +public: + explicit HTTPLogger(ClientContext &context_p) : context(context_p) { + } + +public: + template + std::function GetLogger() { + return [&](const REQUEST &req, const RESPONSE &res) { + Log(req, res); + }; + } + +private: + template + static inline void TemplatedWriteRequests(STREAM &out, const REQUEST &req, const RESPONSE &res) { + out << "HTTP Request:\n"; + out << "\t" << req.method << " " << req.path << "\n"; + for (auto &entry : req.headers) { + out << "\t" << entry.first << ": " << entry.second << "\n"; + } + out << "\nHTTP Response:\n"; + out << "\t" << res.status << " " << res.reason << " " << req.version << "\n"; + for (auto &entry : res.headers) { + out << "\t" << entry.first << ": " << entry.second << "\n"; + } + out << "\n"; + } + + template + void Log(const REQUEST &req, const RESPONSE &res) { + const auto &config = ClientConfig::GetConfig(context); + D_ASSERT(config.enable_http_logging); + + lock_guard guard(lock); + if (config.http_logging_output.empty()) { + stringstream out; + TemplatedWriteRequests(out, req, res); + Printer::Print(out.str()); + } else { + ofstream out(config.http_logging_output, ios::app); + TemplatedWriteRequests(out, req, res); + out.close(); + // Throw an IO exception if it fails to write to the file + if (out.fail()) { + throw IOException("Failed to write HTTP log to file \"%s\": %s", config.http_logging_output, + strerror(errno)); + } + } + } + +private: + ClientContext &context; + mutex lock; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/main/appender.hpp b/src/include/duckdb/main/appender.hpp index f433c1941c7..9662e274408 100644 --- a/src/include/duckdb/main/appender.hpp +++ b/src/include/duckdb/main/appender.hpp @@ -27,10 +27,11 @@ enum class AppenderType : uint8_t { //! The Appender class can be used to append elements to a table. class BaseAppender { -protected: +public: //! The amount of tuples that will be gathered in the column data collection before flushing - static constexpr const idx_t FLUSH_COUNT = STANDARD_VECTOR_SIZE * 100ULL; + static constexpr const idx_t DEFAULT_FLUSH_COUNT = STANDARD_VECTOR_SIZE * 100ULL; +protected: Allocator &allocator; //! The append types vector types; @@ -42,10 +43,13 @@ class BaseAppender { idx_t column = 0; //! The type of the appender AppenderType appender_type; + //! The amount of rows after which we flush the appender automatically + idx_t flush_count = DEFAULT_FLUSH_COUNT; protected: DUCKDB_API BaseAppender(Allocator &allocator, AppenderType type); - DUCKDB_API BaseAppender(Allocator &allocator, vector types, AppenderType type); + DUCKDB_API BaseAppender(Allocator &allocator, vector types, AppenderType type, + idx_t flush_count = DEFAULT_FLUSH_COUNT); public: DUCKDB_API virtual ~BaseAppender(); @@ -59,9 +63,7 @@ class BaseAppender { // Append functions template - void Append(T value) { - throw InternalException("Undefined type for Appender::Append!"); - } + void Append(T value) = delete; DUCKDB_API void Append(const char *value, uint32_t length); @@ -116,12 +118,17 @@ class Appender : public BaseAppender { shared_ptr context; //! The table description (including column names) unique_ptr description; + //! The default expressions + unordered_map default_values; public: DUCKDB_API Appender(Connection &con, const string &schema_name, const string &table_name); DUCKDB_API Appender(Connection &con, const string &table_name); DUCKDB_API ~Appender() override; +public: + void AppendDefault(); + protected: void FlushInternal(ColumnDataCollection &collection) override; }; @@ -133,7 +140,8 @@ class InternalAppender : public BaseAppender { TableCatalogEntry &table; public: - DUCKDB_API InternalAppender(ClientContext &context, TableCatalogEntry &table); + DUCKDB_API InternalAppender(ClientContext &context, TableCatalogEntry &table, + idx_t flush_count = DEFAULT_FLUSH_COUNT); DUCKDB_API ~InternalAppender() override; protected: diff --git a/src/include/duckdb/main/attached_database.hpp b/src/include/duckdb/main/attached_database.hpp index b0037d0d36c..af44df43e95 100644 --- a/src/include/duckdb/main/attached_database.hpp +++ b/src/include/duckdb/main/attached_database.hpp @@ -31,19 +31,37 @@ enum class AttachedDatabaseType { TEMP_DATABASE, }; -//! The AttachedDatabase represents an attached database instance +//! AttachOptions holds information about a database we plan to attach. These options are generalized, i.e., +//! they have to apply to any database file type (duckdb, sqlite, etc.). +struct AttachOptions { + //! Constructor for databases we attach outside of the ATTACH DATABASE statement. + explicit AttachOptions(const DBConfigOptions &options); + //! Constructor for databases we attach when using ATTACH DATABASE. + AttachOptions(const unique_ptr &info, const AccessMode default_access_mode); + + //! Defaults to the access mode configured in the DBConfig, unless specified otherwise. + AccessMode access_mode; + //! The file format type. The default type is a duckdb database file, but other file formats are possible. + string db_type; + //! We only set this, if we detect any unrecognized option. + string unrecognized_option; +}; + +//! The AttachedDatabase represents an attached database instance. class AttachedDatabase : public CatalogEntry { public: - //! Create the built-in system attached database (without storage) + //! Create the built-in system database (without storage). explicit AttachedDatabase(DatabaseInstance &db, AttachedDatabaseType type = AttachedDatabaseType::SYSTEM_DATABASE); - //! Create an attached database instance with the specified name and storage - AttachedDatabase(DatabaseInstance &db, Catalog &catalog, string name, string file_path, AccessMode access_mode); - //! Create an attached database instance with the specified storage extension + //! Create an attached database instance with the specified name and storage. + AttachedDatabase(DatabaseInstance &db, Catalog &catalog, string name, string file_path, + const AttachOptions &options); + //! Create an attached database instance with the specified storage extension. AttachedDatabase(DatabaseInstance &db, Catalog &catalog, StorageExtension &ext, ClientContext &context, string name, - const AttachInfo &info, AccessMode access_mode); + const AttachInfo &info, const AttachOptions &options); ~AttachedDatabase() override; - void Initialize(optional_ptr context = nullptr); + //! Initializes the catalog and storage of the attached database. + void Initialize(const optional_idx block_alloc_size); void Close(); Catalog &ParentCatalog() override; @@ -54,6 +72,11 @@ class AttachedDatabase : public CatalogEntry { DatabaseInstance &GetDatabase() { return db; } + + optional_ptr GetStorageExtension() { + return storage_extension; + } + const string &GetName() const { return name; } @@ -74,6 +97,7 @@ class AttachedDatabase : public CatalogEntry { unique_ptr transaction_manager; AttachedDatabaseType type; optional_ptr parent_catalog; + optional_ptr storage_extension; bool is_initial_database = false; bool is_closed = false; }; diff --git a/src/include/duckdb/main/buffered_data/batched_buffered_data.hpp b/src/include/duckdb/main/buffered_data/batched_buffered_data.hpp new file mode 100644 index 00000000000..430c5863c07 --- /dev/null +++ b/src/include/duckdb/main/buffered_data/batched_buffered_data.hpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/main/batched_buffered_data.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/parallel/interrupt.hpp" +#include "duckdb/common/deque.hpp" +#include "duckdb/common/vector_size.hpp" +#include "duckdb/common/types/data_chunk.hpp" +#include "duckdb/main/buffered_data/simple_buffered_data.hpp" +#include "duckdb/common/map.hpp" + +namespace duckdb { + +class StreamQueryResult; + +class InProgressBatch { +public: + //! The chunks that make up the batch + deque> chunks; + //! Whether the batch is completed (NextBatch has been called) + bool completed = false; +}; + +class BatchedBufferedData : public BufferedData { +public: + static constexpr const BufferedData::Type TYPE = BufferedData::Type::BATCHED; + +public: + explicit BatchedBufferedData(weak_ptr context); + +public: + void Append(const DataChunk &chunk, idx_t batch); + void BlockSink(const InterruptState &blocked_sink, idx_t batch); + + bool ShouldBlockBatch(idx_t batch); + PendingExecutionResult ReplenishBuffer(StreamQueryResult &result, ClientContextLock &context_lock) override; + unique_ptr Scan() override; + void UpdateMinBatchIndex(idx_t min_batch_index); + bool IsMinimumBatchIndex(lock_guard &lock, idx_t batch); + void CompleteBatch(idx_t batch); + bool BufferIsEmpty(); + + inline idx_t ReadQueueCapacity() const { + return read_queue_capacity; + } + inline idx_t BufferCapacity() const { + return buffer_capacity; + } + +private: + void ResetReplenishState(); + void UnblockSinks(); + void MoveCompletedBatches(lock_guard &lock); + +private: + //! The buffer where chunks are written before they are ready to be read. + map buffer; + idx_t buffer_capacity; + atomic buffer_byte_count; + + //! The queue containing the chunks that can be read. + deque> read_queue; + idx_t read_queue_capacity; + atomic read_queue_byte_count; + + map blocked_sinks; + + idx_t min_batch; + //! Debug variable to verify that order is preserved correctly. + idx_t lowest_moved_batch = 0; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/main/buffered_data/buffered_data.hpp b/src/include/duckdb/main/buffered_data/buffered_data.hpp index a863d551be6..791d66b49b6 100644 --- a/src/include/duckdb/main/buffered_data/buffered_data.hpp +++ b/src/include/duckdb/main/buffered_data/buffered_data.hpp @@ -22,30 +22,15 @@ namespace duckdb { class StreamQueryResult; class ClientContextLock; -struct BlockedSink { -public: - BlockedSink(InterruptState state, idx_t chunk_size) : state(std::move(state)), chunk_size(chunk_size) { - } - -public: - //! The handle to reschedule the blocked sink - InterruptState state; - //! The amount of tuples this sink would add - idx_t chunk_size; -}; - class BufferedData { protected: - enum class Type { SIMPLE }; + enum class Type { SIMPLE, BATCHED }; public: - BufferedData(Type type, weak_ptr context) : type(type), context(std::move(context)) { - } - virtual ~BufferedData() { - } + BufferedData(Type type, weak_ptr context_p); + virtual ~BufferedData(); public: - virtual bool BufferIsFull() = 0; virtual PendingExecutionResult ReplenishBuffer(StreamQueryResult &result, ClientContextLock &context_lock) = 0; virtual unique_ptr Scan() = 0; shared_ptr GetContext() { @@ -83,6 +68,8 @@ class BufferedData { Type type; //! This is weak to avoid a cyclical reference weak_ptr context; + //! The maximum amount of memory we should keep buffered + idx_t total_buffer_size; //! Protect against populate/fetch race condition mutex glock; }; diff --git a/src/include/duckdb/main/buffered_data/simple_buffered_data.hpp b/src/include/duckdb/main/buffered_data/simple_buffered_data.hpp index f83416c29a8..829511f7553 100644 --- a/src/include/duckdb/main/buffered_data/simple_buffered_data.hpp +++ b/src/include/duckdb/main/buffered_data/simple_buffered_data.hpp @@ -23,31 +23,32 @@ class SimpleBufferedData : public BufferedData { public: static constexpr const BufferedData::Type TYPE = BufferedData::Type::SIMPLE; -private: - //! (roughly) The max amount of tuples we'll keep buffered at a time - static constexpr idx_t BUFFER_SIZE = 100000; - public: explicit SimpleBufferedData(weak_ptr context); ~SimpleBufferedData() override; public: - void Append(unique_ptr chunk); - void BlockSink(const BlockedSink &blocked_sink); - bool BufferIsFull() override; + void Append(const DataChunk &chunk); + void BlockSink(const InterruptState &blocked_sink); + bool BufferIsFull(); PendingExecutionResult ReplenishBuffer(StreamQueryResult &result, ClientContextLock &context_lock) override; unique_ptr Scan() override; + inline idx_t BufferSize() const { + return buffer_size; + } private: void UnblockSinks(); private: //! Our handles to reschedule the blocked sink tasks - queue blocked_sinks; + queue blocked_sinks; //! The queue of chunks queue> buffered_chunks; //! The current capacity of the buffer (tuples) atomic buffered_count; + //! The amount of tuples we should buffer + idx_t buffer_size; }; } // namespace duckdb diff --git a/src/include/duckdb/main/capi/capi_internal.hpp b/src/include/duckdb/main/capi/capi_internal.hpp index a874693997e..0f9a9c213ad 100644 --- a/src/include/duckdb/main/capi/capi_internal.hpp +++ b/src/include/duckdb/main/capi/capi_internal.hpp @@ -57,6 +57,11 @@ struct AppenderWrapper { string error; }; +struct TableDescriptionWrapper { + unique_ptr description; + string error; +}; + enum class CAPIResultSetType : uint8_t { CAPI_RESULT_TYPE_NONE = 0, CAPI_RESULT_TYPE_MATERIALIZED, diff --git a/src/include/duckdb/main/capi/cast/generic.hpp b/src/include/duckdb/main/capi/cast/generic.hpp index ac01ec750cf..aac1d21355c 100644 --- a/src/include/duckdb/main/capi/cast/generic.hpp +++ b/src/include/duckdb/main/capi/cast/generic.hpp @@ -65,8 +65,8 @@ RESULT_TYPE GetInternalCValue(duckdb_result *result, idx_t col, idx_t row) { case DUCKDB_TYPE_BLOB: return TryCastCInternal(result, col, row); default: { // LCOV_EXCL_START - // invalid type for C to C++ conversion - D_ASSERT(0); + // Invalid type for C to C++ conversion. Internally, we set the null mask to NULL. + // This is a deprecated code path. Use the Vector Interface for nested and complex types. return FetchDefaultValue::Operation(); } // LCOV_EXCL_STOP } diff --git a/src/include/duckdb/main/client_config.hpp b/src/include/duckdb/main/client_config.hpp index d4eebc1acc0..0123867780a 100644 --- a/src/include/duckdb/main/client_config.hpp +++ b/src/include/duckdb/main/client_config.hpp @@ -12,13 +12,16 @@ #include "duckdb/common/common.hpp" #include "duckdb/common/enums/output_type.hpp" #include "duckdb/common/enums/profiler_format.hpp" -#include "duckdb/common/types/value.hpp" #include "duckdb/common/progress_bar/progress_bar.hpp" +#include "duckdb/common/types/value.hpp" +#include "duckdb/main/profiling_info.hpp" namespace duckdb { + class ClientContext; class PhysicalResultCollector; class PreparedStatementData; +class HTTPLogger; typedef std::function(ClientContext &context, PreparedStatementData &data)> get_result_collector_t; @@ -35,6 +38,9 @@ struct ClientConfig { //! The file to save query profiling information to, instead of printing it to the console //! (empty = print to console) string profiler_save_location; + //! The custom settings for the profiler + //! (empty = use the default settings) + profiler_settings_t profiler_settings = ProfilingInfo::DefaultSettings(); //! Allows suppressing profiler output, even if enabled. We turn on the profiler on all test runs but don't want //! to output anything @@ -90,6 +96,9 @@ struct ClientConfig { //! The number of rows to accumulate before flushing during a partitioned write idx_t partitioned_write_flush_threshold = idx_t(1) << idx_t(19); + //! The maximum amount of memory to keep buffered in a streaming query result. Default: 1mb. + idx_t streaming_buffer_size = 1000000; + //! Callback to create a progress bar display progress_bar_display_create_func_t display_create_func = nullptr; @@ -115,6 +124,12 @@ struct ClientConfig { //! Defaults to PhysicalMaterializedCollector get_result_collector_t result_collector = nullptr; + //! If HTTP logging is enabled or not. + bool enable_http_logging = false; + //! The file to save query HTTP logging information to, instead of printing it to the console + //! (empty = print to console) + string http_logging_output; + public: static ClientConfig &GetConfig(ClientContext &context); static const ClientConfig &GetConfig(const ClientContext &context); @@ -122,6 +137,9 @@ struct ClientConfig { bool AnyVerification() { return query_verification_enabled || verify_external || verify_serializer || verify_fetch_row; } + +public: + void SetDefaultStreamingBufferSize(); }; } // namespace duckdb diff --git a/src/include/duckdb/main/client_context.hpp b/src/include/duckdb/main/client_context.hpp index d6d4e2b9849..353bd53322b 100644 --- a/src/include/duckdb/main/client_context.hpp +++ b/src/include/duckdb/main/client_context.hpp @@ -60,9 +60,10 @@ struct PendingQueryParameters { //! The ClientContext holds information relevant to the current client session //! during execution class ClientContext : public enable_shared_from_this { - friend class PendingQueryResult; // LockContext - friend class SimpleBufferedData; // ExecuteTaskInternal - friend class StreamQueryResult; // LockContext + friend class PendingQueryResult; // LockContext + friend class SimpleBufferedData; // ExecuteTaskInternal + friend class BatchedBufferedData; // ExecuteTaskInternal + friend class StreamQueryResult; // LockContext friend class ConnectionManager; public: @@ -174,7 +175,6 @@ class ClientContext : public enable_shared_from_this { //! Whether or not the given result object (streaming query result or pending query result) is active DUCKDB_API bool IsActiveResult(ClientContextLock &lock, BaseQueryResult &result); - DUCKDB_API void SetActiveResult(ClientContextLock &lock, BaseQueryResult &result); //! Returns the current executor Executor &GetExecutor(); @@ -245,6 +245,8 @@ class ClientContext : public enable_shared_from_this { void BeginQueryInternal(ClientContextLock &lock, const string &query); ErrorData EndQueryInternal(ClientContextLock &lock, bool success, bool invalidate_transaction); + //! Wait until a task is available to execute + void WaitForTask(ClientContextLock &lock, BaseQueryResult &result); PendingExecutionResult ExecuteTaskInternal(ClientContextLock &lock, BaseQueryResult &result, bool dry_run = false); unique_ptr PendingStatementOrPreparedStatementInternal( @@ -289,22 +291,4 @@ class ClientContextLock { lock_guard client_guard; }; -class ClientContextWrapper { -public: - explicit ClientContextWrapper(const shared_ptr &context) - : client_context(context) { - - }; - shared_ptr GetContext() { - auto actual_context = client_context.lock(); - if (!actual_context) { - throw ConnectionException("Connection has already been closed"); - } - return actual_context; - } - -private: - weak_ptr client_context; -}; - } // namespace duckdb diff --git a/src/include/duckdb/main/client_context_state.hpp b/src/include/duckdb/main/client_context_state.hpp index 5f48c0474ed..6013d862301 100644 --- a/src/include/duckdb/main/client_context_state.hpp +++ b/src/include/duckdb/main/client_context_state.hpp @@ -17,9 +17,19 @@ class ErrorData; class MetaTransaction; class PreparedStatementData; class SQLStatement; +struct PendingQueryParameters; enum class RebindQueryInfo { DO_NOT_REBIND, ATTEMPT_TO_REBIND }; +struct PreparedStatementCallbackInfo { + PreparedStatementCallbackInfo(PreparedStatementData &prepared_statement, const PendingQueryParameters ¶meters) + : prepared_statement(prepared_statement), parameters(parameters) { + } + + PreparedStatementData &prepared_statement; + const PendingQueryParameters ¶meters; +}; + //! ClientContextState is virtual base class for ClientContext-local (or Query-Local, using QueryEnd callback) state //! e.g. caches that need to live as long as a ClientContext or Query. class ClientContextState { @@ -48,7 +58,7 @@ class ClientContextState { PreparedStatementMode mode) { return RebindQueryInfo::DO_NOT_REBIND; } - virtual RebindQueryInfo OnExecutePrepared(ClientContext &context, PreparedStatementData &prepared_statement, + virtual RebindQueryInfo OnExecutePrepared(ClientContext &context, PreparedStatementCallbackInfo &info, RebindQueryInfo current_rebind) { return RebindQueryInfo::DO_NOT_REBIND; } diff --git a/src/include/duckdb/main/client_context_wrapper.hpp b/src/include/duckdb/main/client_context_wrapper.hpp new file mode 100644 index 00000000000..2ee703458ed --- /dev/null +++ b/src/include/duckdb/main/client_context_wrapper.hpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/main/client_context_wrapper.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/shared_ptr.hpp" + +namespace duckdb { + +class ClientContext; + +class ClientContextWrapper { +public: + explicit ClientContextWrapper(const shared_ptr &context); + shared_ptr GetContext(); + shared_ptr TryGetContext(); + +private: + weak_ptr client_context; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/main/client_data.hpp b/src/include/duckdb/main/client_data.hpp index 596cb9f921a..777859755e1 100644 --- a/src/include/duckdb/main/client_data.hpp +++ b/src/include/duckdb/main/client_data.hpp @@ -26,6 +26,7 @@ class HTTPState; class QueryProfiler; class PreparedStatementData; class SchemaCatalogEntry; +class HTTPLogger; struct RandomEngine; struct ClientData { @@ -35,6 +36,9 @@ struct ClientData { //! Query profiler shared_ptr profiler; + //! HTTP logger + shared_ptr http_logger; + //! The set of temporary objects that belong to this client shared_ptr temporary_objects; //! The set of bound prepared statements that belong to this client diff --git a/src/include/duckdb/main/client_properties.hpp b/src/include/duckdb/main/client_properties.hpp index ae75ef101f7..aec86f57ce9 100644 --- a/src/include/duckdb/main/client_properties.hpp +++ b/src/include/duckdb/main/client_properties.hpp @@ -16,11 +16,15 @@ enum class ArrowOffsetSize : uint8_t { REGULAR, LARGE }; //! A set of properties from the client context that can be used to interpret the query result struct ClientProperties { - ClientProperties(string time_zone_p, ArrowOffsetSize arrow_offset_size_p) - : time_zone(std::move(time_zone_p)), arrow_offset_size(arrow_offset_size_p) { + ClientProperties(string time_zone_p, ArrowOffsetSize arrow_offset_size_p, bool arrow_use_list_view_p, + bool produce_arrow_string_view_p) + : time_zone(std::move(time_zone_p)), arrow_offset_size(arrow_offset_size_p), + arrow_use_list_view(arrow_use_list_view_p), produce_arrow_string_view(produce_arrow_string_view_p) { } ClientProperties() {}; string time_zone = "UTC"; ArrowOffsetSize arrow_offset_size = ArrowOffsetSize::REGULAR; + bool arrow_use_list_view = false; + bool produce_arrow_string_view = false; }; } // namespace duckdb diff --git a/src/include/duckdb/main/config.hpp b/src/include/duckdb/main/config.hpp index 12bcebd74e6..edcbb64633c 100644 --- a/src/include/duckdb/main/config.hpp +++ b/src/include/duckdb/main/config.hpp @@ -37,6 +37,7 @@ namespace duckdb { class BufferManager; class BufferPool; class CastFunctionSet; +class CollationBinding; class ClientContext; class ErrorManager; class CompressionFunction; @@ -45,6 +46,7 @@ class OperatorExtension; class StorageExtension; class ExtensionCallback; class SecretManager; +class CompressionInfo; struct CompressionFunctionSet; struct DBConfig; @@ -89,6 +91,27 @@ struct ExtensionOption { Value default_value; }; +class SerializationCompatibility { +public: + static SerializationCompatibility FromString(const string &input); + static SerializationCompatibility Default(); + static SerializationCompatibility Latest(); + +public: + bool Compare(idx_t property_version) const; + +public: + //! The user provided version + string duckdb_version; + //! The max version that should be serialized + idx_t serialization_version; + //! Whether this was set by a manual SET/PRAGMA or default + bool manually_set; + +protected: + SerializationCompatibility() = default; +}; + struct DBConfigOptions { //! Database file path. May be empty for in-memory mode string database_path; @@ -134,6 +157,8 @@ struct DBConfigOptions { //! Whether or not to invoke filesystem trim on free blocks after checkpoint. This will reclaim //! space for sparse files, on platforms that support it. bool trim_free_blocks = false; + //! Record timestamps of buffer manager unpin() events. Usable by custom eviction policies. + bool buffer_manager_track_eviction_timestamps = false; //! Whether or not to allow printing unredacted secrets bool allow_unredacted_secrets = false; //! The collation type of the database @@ -152,6 +177,8 @@ struct DBConfigOptions { bool force_checkpoint = false; //! Run a checkpoint on successful shutdown and delete the WAL, to leave only a single database file behind bool checkpoint_on_shutdown = true; + //! Serialize the metadata on checkpoint with compatibility for a given DuckDB version. + SerializationCompatibility serialization_compatibility = SerializationCompatibility::Default(); //! Debug flag that decides when a checkpoing should be aborted. Only used for testing purposes. CheckpointAbort checkpoint_abort = CheckpointAbort::NO_ABORT; //! Initialize the database with the standard set of DuckDB functions @@ -169,6 +196,10 @@ struct DBConfigOptions { bool preserve_insertion_order = true; //! Whether Arrow Arrays use Large or Regular buffers ArrowOffsetSize arrow_offset_size = ArrowOffsetSize::REGULAR; + //! Whether LISTs should produce Arrow ListViews + bool arrow_use_list_view = false; + //! Whether when producing arrow objects we produce string_views or regular strings + bool produce_arrow_string_views = false; //! Database configuration variables as controlled by SET case_insensitive_map_t set_variables; //! Database configuration variable default values; @@ -177,10 +208,16 @@ struct DBConfigOptions { string extension_directory; //! Whether unsigned extensions should be loaded bool allow_unsigned_extensions = false; + //! Whether community extensions should be loaded + bool allow_community_extensions = true; //! Whether extensions with missing metadata should be loaded bool allow_extensions_metadata_mismatch = false; //! Enable emitting FSST Vectors bool enable_fsst_vectors = false; + //! Enable VIEWs to create dependencies + bool enable_view_dependencies = false; + //! Enable macros to create dependencies + bool enable_macro_dependencies = false; //! Start transactions immediately in all attached databases - instead of lazily when a database is referenced bool immediate_transaction_mode = false; //! Debug setting - how to initialize blocks in the storage layer when allocating @@ -193,12 +230,19 @@ struct DBConfigOptions { static bool debug_print_bindings; // NOLINT: debug setting //! The peak allocation threshold at which to flush the allocator after completing a task (1 << 27, ~128MB) idx_t allocator_flush_threshold = 134217728; + //! Whether the allocator background thread is enabled + bool allocator_background_threads = false; //! DuckDB API surface string duckdb_api; //! Metadata from DuckDB callers string custom_user_agent; //! Use old implicit casting style (i.e. allow everything to be implicitly casted to VARCHAR) bool old_implicit_casting = false; + //! The default block allocation size for new duckdb database files (new as-in, they do not yet exist). + //! NOTE: this becomes the DEFAULT_BLOCK_ALLOC_SIZE once we support different block sizes. + idx_t default_block_alloc_size = Storage::BLOCK_ALLOC_SIZE; + //! Whether or not to abort if a serialization exception is thrown during WAL playback (when reading truncated WAL) + bool abort_on_wal_failure = false; bool operator==(const DBConfigOptions &other) const; }; @@ -276,15 +320,17 @@ struct DBConfig { DUCKDB_API static idx_t ParseMemoryLimit(const string &arg); - //! Return the list of possible compression functions for the specific physical type - DUCKDB_API vector> GetCompressionFunctions(PhysicalType data_type); - //! Return the compression function for the specified compression type/physical type combo - DUCKDB_API optional_ptr GetCompressionFunction(CompressionType type, PhysicalType data_type); + //! Return the list of possible compression functions for the provided compression information. + DUCKDB_API vector> GetCompressionFunctions(const CompressionInfo &info); + //! Return the compression function matching the compression type and its compression information. + DUCKDB_API optional_ptr GetCompressionFunction(CompressionType type, + const CompressionInfo &info); bool operator==(const DBConfig &other); bool operator!=(const DBConfig &other); DUCKDB_API CastFunctionSet &GetCastFunctions(); + DUCKDB_API CollationBinding &GetCollationBinding(); DUCKDB_API IndexTypeSet &GetIndexTypes(); static idx_t GetSystemMaxThreads(FileSystem &fs); void SetDefaultMaxMemory(); @@ -297,6 +343,7 @@ struct DBConfig { private: unique_ptr compression_functions; unique_ptr cast_functions; + unique_ptr collation_bindings; unique_ptr index_types; }; diff --git a/src/include/duckdb/main/connection_manager.hpp b/src/include/duckdb/main/connection_manager.hpp index b59ce503db2..bb21a27604b 100644 --- a/src/include/duckdb/main/connection_manager.hpp +++ b/src/include/duckdb/main/connection_manager.hpp @@ -17,15 +17,6 @@ namespace duckdb { class ClientContext; class DatabaseInstance; -struct ClientLockWrapper { - ClientLockWrapper(mutex &client_lock, shared_ptr connection) - : connection(std::move(connection)), connection_lock(make_uniq>(client_lock)) { - } - - shared_ptr connection; - unique_ptr> connection_lock; -}; - class ConnectionManager { public: ConnectionManager(); @@ -34,18 +25,17 @@ class ConnectionManager { void RemoveConnection(ClientContext &context); vector> GetConnectionList(); - - void LockClients(vector &client_locks, ClientContext &context); + const reference_map_t> &GetConnectionListReference() const { + return connections; + } + idx_t GetConnectionCount() const; static ConnectionManager &Get(DatabaseInstance &db); static ConnectionManager &Get(ClientContext &context); -public: - mutex connections_lock; - unordered_map> connections; - - mutex lock_clients_lock; - bool is_locking; +private: + mutable mutex connections_lock; + reference_map_t> connections; }; } // namespace duckdb diff --git a/src/include/duckdb/main/database.hpp b/src/include/duckdb/main/database.hpp index 1aa976a13ba..c3041a2c33d 100644 --- a/src/include/duckdb/main/database.hpp +++ b/src/include/duckdb/main/database.hpp @@ -12,6 +12,7 @@ #include "duckdb/main/valid_checker.hpp" #include "duckdb/common/winapi.hpp" #include "duckdb/main/extension.hpp" +#include "duckdb/main/extension_install_info.hpp" #include "duckdb/main/settings.hpp" namespace duckdb { @@ -25,18 +26,9 @@ class FileSystem; class TaskScheduler; class ObjectCache; struct AttachInfo; +struct AttachOptions; class DatabaseFileSystem; -struct ExtensionInfo { - explicit ExtensionInfo(const string &version) : extension_version(version) { - } - ExtensionInfo() : ExtensionInfo("defaultme") { - } - ExtensionInfo(const ExtensionInfo &x) : ExtensionInfo(x.extension_version) { - } - string extension_version; -}; - class DatabaseInstance : public enable_shared_from_this { friend class DuckDB; @@ -57,21 +49,21 @@ class DatabaseInstance : public enable_shared_from_this { DUCKDB_API ObjectCache &GetObjectCache(); DUCKDB_API ConnectionManager &GetConnectionManager(); DUCKDB_API ValidChecker &GetValidChecker(); - DUCKDB_API void SetExtensionLoaded(const std::string &extension_name, const std::string &extension_version = ""); + DUCKDB_API void SetExtensionLoaded(const string &extension_name, ExtensionInstallInfo &install_info); idx_t NumberOfThreads(); DUCKDB_API static DatabaseInstance &GetDatabase(ClientContext &context); DUCKDB_API static const DatabaseInstance &GetDatabase(const ClientContext &context); - DUCKDB_API const unordered_set &LoadedExtensions(); - DUCKDB_API const unordered_map &LoadedExtensionsData(); + DUCKDB_API const unordered_set &LoadedExtensions(); + DUCKDB_API const unordered_map &LoadedExtensionsData(); DUCKDB_API bool ExtensionIsLoaded(const string &name); DUCKDB_API SettingLookupResult TryGetCurrentSetting(const string &key, Value &result) const; unique_ptr CreateAttachedDatabase(ClientContext &context, const AttachInfo &info, - const string &type, AccessMode access_mode); + const AttachOptions &options); private: void Initialize(const char *path, DBConfig *config); @@ -86,7 +78,7 @@ class DatabaseInstance : public enable_shared_from_this { unique_ptr object_cache; unique_ptr connection_manager; unordered_set loaded_extensions; - unordered_map loaded_extensions_data; + unordered_map loaded_extensions_data; ValidChecker db_validity; unique_ptr db_file_system; }; @@ -105,14 +97,28 @@ class DuckDB { shared_ptr instance; public: + // Load a statically loaded extension by its class template - void LoadExtension() { + void LoadStaticExtension() { T extension; if (ExtensionIsLoaded(extension.Name())) { return; } extension.Load(*this); - instance->SetExtensionLoaded(extension.Name()); + ExtensionInstallInfo install_info; + install_info.mode = ExtensionInstallMode::STATICALLY_LINKED; + install_info.version = extension.Version(); + instance->SetExtensionLoaded(extension.Name(), install_info); + } + + // DEPRECATED function that some extensions may still use to call their own Load method from the + // _init function of their loadable extension. Don't use this. Instead opt for a static LoadInternal function called + // from both the _init function and the Extension::Load. (see autocomplete extension) + // TODO: when to remove this function? + template + void LoadExtension() { + T extension; + extension.Load(*this); } DUCKDB_API FileSystem &GetFileSystem(); @@ -122,7 +128,7 @@ class DuckDB { DUCKDB_API static const char *LibraryVersion(); DUCKDB_API static idx_t StandardVectorSize(); DUCKDB_API static string Platform(); - DUCKDB_API bool ExtensionIsLoaded(const std::string &name); + DUCKDB_API bool ExtensionIsLoaded(const string &name); }; } // namespace duckdb diff --git a/src/include/duckdb/main/database_manager.hpp b/src/include/duckdb/main/database_manager.hpp index aee2566e10b..c74f2f7d03d 100644 --- a/src/include/duckdb/main/database_manager.hpp +++ b/src/include/duckdb/main/database_manager.hpp @@ -25,6 +25,7 @@ class CatalogSet; class ClientContext; class DatabaseInstance; class TaskScheduler; +struct AttachOptions; //! The DatabaseManager is a class that sits at the root of all attached databases class DatabaseManager { @@ -39,12 +40,13 @@ class DatabaseManager { static DatabaseManager &Get(ClientContext &db); static DatabaseManager &Get(AttachedDatabase &db); + //! Initializes the system catalog of the attached SYSTEM_DATABASE. void InitializeSystemCatalog(); //! Get an attached database by its name optional_ptr GetDatabase(ClientContext &context, const string &name); //! Attach a new database - optional_ptr AttachDatabase(ClientContext &context, const AttachInfo &info, const string &db_type, - AccessMode access_mode); + optional_ptr AttachDatabase(ClientContext &context, const AttachInfo &info, + const AttachOptions &options); //! Detach an existing database void DetachDatabase(ClientContext &context, const string &name, OnEntryNotFound if_not_found); //! Returns a reference to the system catalog @@ -61,8 +63,7 @@ class DatabaseManager { //! Returns the database type. This might require checking the header of the file, in which case the file handle is //! necessary. We can only grab the file handle, if it is not yet held, even for uncommitted changes. Thus, we have //! to lock for this operation. - void GetDatabaseType(ClientContext &context, string &db_type, AttachInfo &info, const DBConfig &config, - const string &unrecognized_option); + void GetDatabaseType(ClientContext &context, AttachInfo &info, const DBConfig &config, AttachOptions &options); //! Scans the catalog set and adds each committed database entry, and each database entry of the current //! transaction, to a vector holding AttachedDatabase references vector> GetDatabases(ClientContext &context); diff --git a/src/include/duckdb/main/extension.hpp b/src/include/duckdb/main/extension.hpp index 5c57996d672..996a7fa66ea 100644 --- a/src/include/duckdb/main/extension.hpp +++ b/src/include/duckdb/main/extension.hpp @@ -21,6 +21,31 @@ class Extension { DUCKDB_API virtual void Load(DuckDB &db) = 0; DUCKDB_API virtual std::string Name() = 0; + DUCKDB_API virtual std::string Version() const { + return ""; + } +}; + +//! The parsed extension metadata footer +struct ParsedExtensionMetaData { + static constexpr const idx_t FOOTER_SIZE = 512; + static constexpr const idx_t SIGNATURE_SIZE = 256; + static constexpr const char *EXPECTED_MAGIC_VALUE = { + "4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}; + + string magic_value; + + string platform; + string duckdb_version; + string extension_version; + string signature; + + bool AppearsValid() { + return magic_value == EXPECTED_MAGIC_VALUE; + } + + // Returns an error string describing which parts of the metadata are mismatcheds + string GetInvalidMetadataError(); }; } // namespace duckdb diff --git a/src/include/duckdb/main/extension_entries.hpp b/src/include/duckdb/main/extension_entries.hpp index c7b3b7e4607..ffe138bfa92 100644 --- a/src/include/duckdb/main/extension_entries.hpp +++ b/src/include/duckdb/main/extension_entries.hpp @@ -35,6 +35,7 @@ static constexpr ExtensionFunctionEntry EXTENSION_FUNCTIONS[] = { {"current_localtime", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, {"current_localtimestamp", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, {"dbgen", "tpch", CatalogType::TABLE_FUNCTION_ENTRY}, + {"delta_scan", "delta", CatalogType::TABLE_FUNCTION_ENTRY}, {"drop_fts_index", "fts", CatalogType::PRAGMA_FUNCTION_ENTRY}, {"dsdgen", "tpcds", CatalogType::TABLE_FUNCTION_ENTRY}, {"excel_text", "excel", CatalogType::SCALAR_FUNCTION_ENTRY}, @@ -54,6 +55,137 @@ static constexpr ExtensionFunctionEntry EXTENSION_FUNCTIONS[] = { {"iceberg_scan", "iceberg", CatalogType::TABLE_FUNCTION_ENTRY}, {"iceberg_snapshots", "iceberg", CatalogType::TABLE_FUNCTION_ENTRY}, {"icu_calendar_names", "icu", CatalogType::TABLE_FUNCTION_ENTRY}, + {"icu_collate_af", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_am", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ar", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ar_sa", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_as", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_az", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_be", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_bg", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_bn", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_bo", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_br", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_bs", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ca", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ceb", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_chr", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_cs", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_cy", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_da", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_de", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_de_at", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_dsb", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_dz", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ee", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_el", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_en", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_en_us", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_eo", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_es", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_et", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_fa", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_fa_af", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ff", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_fi", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_fil", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_fo", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_fr", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_fr_ca", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_fy", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ga", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_gl", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_gu", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ha", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_haw", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_he", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_he_il", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_hi", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_hr", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_hsb", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_hu", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_hy", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_id", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_id_id", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ig", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_is", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_it", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ja", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ka", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_kk", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_kl", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_km", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_kn", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ko", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_kok", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ku", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ky", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_lb", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_lkt", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ln", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_lo", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_lt", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_lv", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_mk", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ml", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_mn", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_mr", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ms", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_mt", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_my", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_nb", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_nb_no", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ne", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_nl", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_nn", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_noaccent", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_om", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_or", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_pa", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_pa_in", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_pl", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ps", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_pt", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ro", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ru", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_sa", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_se", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_si", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_sk", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_sl", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_smn", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_sq", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_sr", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_sr_ba", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_sr_me", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_sr_rs", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_sv", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_sw", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ta", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_te", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_th", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_tk", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_to", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_tr", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ug", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_uk", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_ur", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_uz", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_vi", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_wae", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_wo", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_xh", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_yi", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_yo", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_yue", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_yue_cn", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_zh", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_zh_cn", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_zh_hk", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_zh_mo", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_zh_sg", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_zh_tw", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"icu_collate_zu", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, {"icu_sort_key", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, {"json", "json", CatalogType::MACRO_ENTRY}, {"json_array", "json", CatalogType::SCALAR_FUNCTION_ENTRY}, @@ -82,6 +214,9 @@ static constexpr ExtensionFunctionEntry EXTENSION_FUNCTIONS[] = { {"json_valid", "json", CatalogType::SCALAR_FUNCTION_ENTRY}, {"load_aws_credentials", "aws", CatalogType::TABLE_FUNCTION_ENTRY}, {"make_timestamptz", "icu", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"mysql_clear_cache", "mysql_scanner", CatalogType::TABLE_FUNCTION_ENTRY}, + {"mysql_execute", "mysql_scanner", CatalogType::TABLE_FUNCTION_ENTRY}, + {"mysql_query", "mysql_scanner", CatalogType::TABLE_FUNCTION_ENTRY}, {"parquet_file_metadata", "parquet", CatalogType::TABLE_FUNCTION_ENTRY}, {"parquet_kv_metadata", "parquet", CatalogType::TABLE_FUNCTION_ENTRY}, {"parquet_metadata", "parquet", CatalogType::TABLE_FUNCTION_ENTRY}, @@ -155,6 +290,8 @@ static constexpr ExtensionFunctionEntry EXTENSION_FUNCTIONS[] = { {"st_geomfromhexwkb", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_geomfromtext", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_geomfromwkb", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"st_hasm", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"st_hasz", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_hilbert", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_intersection", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_intersection_agg", "spatial", CatalogType::AGGREGATE_FUNCTION_ENTRY}, @@ -194,6 +331,7 @@ static constexpr ExtensionFunctionEntry EXTENSION_FUNCTIONS[] = { {"st_point4d", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_pointn", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_pointonsurface", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"st_points", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_polygon2dfromwkb", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_quadkey", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_read", "spatial", CatalogType::TABLE_FUNCTION_ENTRY}, @@ -220,6 +358,7 @@ static constexpr ExtensionFunctionEntry EXTENSION_FUNCTIONS[] = { {"st_ymin", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_z", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_zmax", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, + {"st_zmflag", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"st_zmin", "spatial", CatalogType::SCALAR_FUNCTION_ENTRY}, {"stem", "fts", CatalogType::SCALAR_FUNCTION_ENTRY}, {"text", "excel", CatalogType::SCALAR_FUNCTION_ENTRY}, @@ -252,11 +391,18 @@ static constexpr ExtensionEntry EXTENSION_SETTINGS[] = { {"calendar", "icu"}, {"enable_server_cert_verification", "httpfs"}, {"force_download", "httpfs"}, + {"hf_max_per_page", "httpfs"}, + {"hnsw_ef_search", "vss"}, + {"hnsw_enable_experimental_persistence", "vss"}, {"http_keep_alive", "httpfs"}, {"http_retries", "httpfs"}, {"http_retry_backoff", "httpfs"}, {"http_retry_wait_ms", "httpfs"}, {"http_timeout", "httpfs"}, + {"mysql_bit1_as_boolean", "mysql_scanner"}, + {"mysql_debug_show_queries", "mysql_scanner"}, + {"mysql_experimental_filter_pushdown", "mysql_scanner"}, + {"mysql_tinyint1_as_boolean", "mysql_scanner"}, {"pg_array_as_varchar", "postgres_scanner"}, {"pg_connection_cache", "postgres_scanner"}, {"pg_connection_limit", "postgres_scanner"}, @@ -319,9 +465,9 @@ static constexpr ExtensionEntry EXTENSION_COLLATIONS[] = { // Note: these are currently hardcoded in scripts/generate_extensions_function.py // TODO: automate by passing though to script via duckdb static constexpr ExtensionEntry EXTENSION_FILE_PREFIXES[] = { - {"http://", "httpfs"}, {"https://", "httpfs"}, {"s3://", "httpfs"}, {"s3a://", "httpfs"}, - {"s3n://", "httpfs"}, {"gcs://", "httpfs"}, {"gs://", "httpfs"}, {"r2://", "httpfs"}, - {"azure://", "azure"}, {"az://", "azure"}, {"abfss://", "azure"}}; // END_OF_EXTENSION_FILE_PREFIXES + {"http://", "httpfs"}, {"https://", "httpfs"}, {"s3://", "httpfs"}, {"s3a://", "httpfs"}, {"s3n://", "httpfs"}, + {"gcs://", "httpfs"}, {"gs://", "httpfs"}, {"r2://", "httpfs"}, {"azure://", "azure"}, {"az://", "azure"}, + {"abfss://", "azure"}, {"hf://", "httpfs"}}; // END_OF_EXTENSION_FILE_PREFIXES // Note: these are currently hardcoded in scripts/generate_extensions_function.py // TODO: automate by passing though to script via duckdb @@ -339,18 +485,22 @@ static constexpr ExtensionEntry EXTENSION_FILE_CONTAINS[] = {{".parquet?", "parq // Note: these are currently hardcoded in scripts/generate_extensions_function.py // TODO: automate by passing though to script via duckdb static constexpr ExtensionEntry EXTENSION_SECRET_TYPES[] = { - {"s3", "httpfs"}, {"r2", "httpfs"}, {"gcs", "httpfs"}, {"azure", "azure"}}; // EXTENSION_SECRET_TYPES + {"s3", "httpfs"}, {"r2", "httpfs"}, {"gcs", "httpfs"}, + {"azure", "azure"}, {"huggingface", "httpfs"}, {"bearer", "httpfs"}}; // EXTENSION_SECRET_TYPES // Note: these are currently hardcoded in scripts/generate_extensions_function.py // TODO: automate by passing though to script via duckdb static constexpr ExtensionEntry EXTENSION_SECRET_PROVIDERS[] = { - {"s3/config", "httpfs"}, {"gcs/config", "httpfs"}, {"r2/config", "httpfs"}, - {"s3/credential_chain", "aws"}, {"gcs/credential_chain", "aws"}, {"r2/credential_chain", "aws"}, - {"azure/config", "azure"}, {"azure/credential_chain", "azure"}}; // EXTENSION_SECRET_PROVIDERS + {"s3/config", "httpfs"}, {"gcs/config", "httpfs"}, + {"r2/config", "httpfs"}, {"s3/credential_chain", "aws"}, + {"gcs/credential_chain", "aws"}, {"r2/credential_chain", "aws"}, + {"azure/config", "azure"}, {"azure/credential_chain", "azure"}, + {"huggingface/config", "httfps"}, {"huggingface/credential_chain", "httpfs"}, + {"bearer/config", "httpfs"}}; // EXTENSION_SECRET_PROVIDERS static constexpr const char *AUTOLOADABLE_EXTENSIONS[] = { - "aws", "azure", "autocomplete", "excel", "fts", "httpfs", "inet", - "icu", "json", "parquet", "sqlite_scanner", "sqlsmith", "postgres_scanner", "tpcds", - "tpch"}; // END_OF_AUTOLOADABLE_EXTENSIONS + "aws", "azure", "autocomplete", "delta", "excel", "fts", "httpfs", + "inet", "icu", "json", "parquet", "sqlite_scanner", "sqlsmith", "postgres_scanner", + "tpcds", "tpch"}; // END_OF_AUTOLOADABLE_EXTENSIONS } // namespace duckdb diff --git a/src/include/duckdb/main/extension_helper.hpp b/src/include/duckdb/main/extension_helper.hpp index 8d886468504..7438e774e37 100644 --- a/src/include/duckdb/main/extension_helper.hpp +++ b/src/include/duckdb/main/extension_helper.hpp @@ -8,12 +8,18 @@ #pragma once -#include #include "duckdb.hpp" #include "duckdb/main/extension_entries.hpp" +#include "duckdb/main/extension_install_info.hpp" + +#include + +#include namespace duckdb { + class DuckDB; +class HTTPLogger; enum class ExtensionLoadResult : uint8_t { LOADED_EXTENSION = 0, EXTENSION_UNKNOWN = 1, NOT_LOADED = 2 }; @@ -31,11 +37,47 @@ struct ExtensionAlias { struct ExtensionInitResult { string filename; string filebase; - string extension_version; + + // The deserialized install from the `.duckdb_extension.info` file + unique_ptr install_info; void *lib_hdl; }; +// Tags describe what happened during the updating process +enum class ExtensionUpdateResultTag : uint8_t { + // Fallback for when installation information is missing + UNKNOWN = 0, + + // Either a fresh file was downloaded and versions are identical + NO_UPDATE_AVAILABLE = 1, + // Only extensions from repositories can be updated + NOT_A_REPOSITORY = 2, + // Only known, currently installed extensions can be updated + NOT_INSTALLED = 3, + // Statically loaded extensions can not be updated; they are baked into the DuckDB executable + STATICALLY_LOADED = 4, + // This means the .info file written during installation was missing or malformed + MISSING_INSTALL_INFO = 5, + + // The extension was re-downloaded from the repository, but due to a lack of version information + // its impossible to tell if the extension is actually updated + REDOWNLOADED = 254, + // The version was updated to a new version + UPDATED = 255, +}; + +struct ExtensionUpdateResult { + ExtensionUpdateResultTag tag = ExtensionUpdateResultTag::UNKNOWN; + + string extension_name; + string repository; + + string extension_version; + string prev_version; + string installed_version; +}; + class ExtensionHelper { public: static void LoadAllExtensions(DuckDB &db); @@ -43,10 +85,16 @@ class ExtensionHelper { static ExtensionLoadResult LoadExtension(DuckDB &db, const std::string &extension); //! Install an extension - static void InstallExtension(ClientContext &context, const string &extension, bool force_install, - const string &respository = ""); - static void InstallExtension(DBConfig &config, FileSystem &fs, const string &extension, bool force_install, - const string &respository = ""); + static unique_ptr InstallExtension(ClientContext &context, const string &extension, + bool force_install, + optional_ptr repository = nullptr, + bool throw_on_origin_mismatch = false, + const string &version = ""); + static unique_ptr InstallExtension(DBConfig &config, FileSystem &fs, const string &extension, + bool force_install, + optional_ptr repository = nullptr, + bool throw_on_origin_mismatch = false, + const string &version = ""); //! Load an extension static void LoadExternalExtension(ClientContext &context, const string &extension); static void LoadExternalExtension(DatabaseInstance &db, FileSystem &fs, const string &extension); @@ -58,12 +106,25 @@ class ExtensionHelper { //! Autoload an extension (depending on config, potentially a nop. Returns false on failure) DUCKDB_API static bool TryAutoLoadExtension(ClientContext &context, const string &extension_name) noexcept; + //! Update all extensions, return a vector of extension names that were updated; + static vector UpdateExtensions(ClientContext &context); + static vector UpdateExtensions(DatabaseInstance &db, FileSystem &fs); + //! Update a specific extension + static ExtensionUpdateResult UpdateExtension(ClientContext &context, const string &extension_name); + static ExtensionUpdateResult UpdateExtension(DatabaseInstance &db, FileSystem &fs, const string &extension_name); + //! Get the extension directory base on the current config static string ExtensionDirectory(ClientContext &context); static string ExtensionDirectory(DBConfig &config, FileSystem &fs); + static bool CheckExtensionSignature(FileHandle &handle, ParsedExtensionMetaData &parsed_metadata, + const bool allow_community_extensions); + static ParsedExtensionMetaData ParseExtensionMetaData(const char *metadata); + static ParsedExtensionMetaData ParseExtensionMetaData(FileHandle &handle); + //! Get the extension url template, containing placeholders for version, platform and extension name - static string ExtensionUrlTemplate(optional_ptr config, const string &repository); + static string ExtensionUrlTemplate(optional_ptr config, const ExtensionRepository &repository, + const string &version); //! Return the extension url template with the variables replaced static string ExtensionFinalizeUrlTemplate(const string &url, const string &name); @@ -77,11 +138,14 @@ class ExtensionHelper { static ExtensionAlias GetExtensionAlias(idx_t index); //! Get public signing keys for extension signing - static const vector GetPublicKeys(); + static const vector GetPublicKeys(bool allow_community_extension = false); // Returns extension name, or empty string if not a replacement open path static string ExtractExtensionPrefixFromPath(const string &path); + // Returns the user-readable name of a repository URL + static string GetRepositoryName(const string &repository_base_url); + //! Apply any known extension aliases, return the lowercase name static string ApplyExtensionAlias(const string &extension_name); @@ -147,9 +211,14 @@ class ExtensionHelper { //! For tagged releases we use the tag, else we use the git commit hash static const string GetVersionDirectoryName(); + static bool IsRelease(const string &version_tag); + static bool CreateSuggestions(const string &extension_name, string &message); + private: - static void InstallExtensionInternal(DBConfig &config, FileSystem &fs, const string &local_path, - const string &extension, bool force_install, const string &repository); + static unique_ptr InstallExtensionInternal( + DBConfig &config, FileSystem &fs, const string &local_path, const string &extension, bool force_install, + bool throw_on_origin_mismatch, const string &version, optional_ptr repository, + optional_ptr http_logger = nullptr, optional_ptr context = nullptr); static const vector PathComponents(); static string DefaultExtensionFolder(FileSystem &fs); static bool AllowAutoInstall(const string &extension); @@ -158,8 +227,6 @@ class ExtensionHelper { string &error); //! Version tags occur with and without 'v', tag in extension path is always with 'v' static const string NormalizeVersionTag(const string &version_tag); - static bool IsRelease(const string &version_tag); - static bool CreateSuggestions(const string &extension_name, string &message); private: static ExtensionLoadResult LoadExtensionInternal(DuckDB &db, const std::string &extension, bool initial_load); diff --git a/src/include/duckdb/main/extension_install_info.hpp b/src/include/duckdb/main/extension_install_info.hpp new file mode 100644 index 00000000000..a1e5bad4a74 --- /dev/null +++ b/src/include/duckdb/main/extension_install_info.hpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/main/extension_install_info.hpp +// +// +//===----------------------------------------------------------------------===// + +#include "duckdb/common/types.hpp" +#include "duckdb/main/config.hpp" + +#pragma once + +namespace duckdb { +class FileSystem; + +enum class ExtensionInstallMode : uint8_t { + // Fallback for when install info is missing + UNKNOWN = 0, + //! Extension was installed using a url deduced from a repository base url + REPOSITORY = 1, + //! Extension was install from a custom path, this could be either local or remote + CUSTOM_PATH = 2, + //! Extension was statically linked + STATICALLY_LINKED = 3, + //! Extension is not installed, for example the extension might be directly loaded without installing + NOT_INSTALLED = 4 +}; + +class ExtensionInstallInfo { +public: + //! How the extension was installed + ExtensionInstallMode mode = ExtensionInstallMode::UNKNOWN; + //! (optional) Full path where the extension came from + string full_path; + //! (optional) Repository url where the extension came from + string repository_url; + //! (optional) Version of the extension + string version; + //! (optional) ETag of last fetched resource + string etag; + + void Serialize(Serializer &serializer) const; + + //! Try to read install info. returns ExtensionInstallMode::UNKNOWN on missing file, and throws on corrupt file + static unique_ptr TryReadInfoFile(FileSystem &fs, const string &info_file_path, + const string &extension_name); + + static unique_ptr Deserialize(Deserializer &deserializer); +}; + +struct ExtensionRepository { + //! All currently available repositories + static constexpr const char *CORE_REPOSITORY_URL = "http://extensions.duckdb.org"; + static constexpr const char *CORE_NIGHTLY_REPOSITORY_URL = "http://nightly-extensions.duckdb.org"; + static constexpr const char *COMMUNITY_REPOSITORY_URL = "http://community-extensions.duckdb.org"; + + //! Debugging repositories (target local, relative paths that are produced by DuckDB's build system) + static constexpr const char *BUILD_DEBUG_REPOSITORY_PATH = "./build/debug/repository"; + static constexpr const char *BUILD_RELEASE_REPOSITORY_PATH = "./build/release/repository"; + + //! The default is CORE + static constexpr const char *DEFAULT_REPOSITORY_URL = CORE_REPOSITORY_URL; + + //! Returns the repository name is this is a known repository, or the full url if it is not + static string GetRepository(const string &repository_url); + //! Try to convert a repository to a url, will return empty string if the repository is unknown + static string TryGetRepositoryUrl(const string &repository); + //! Try to convert a url to a known repository name, will return empty string if the repository is unknown + static string TryConvertUrlToKnownRepository(const string &url); + + //! Get the default repository, optionally passing a config to allow + static ExtensionRepository GetDefaultRepository(optional_ptr config); + static ExtensionRepository GetDefaultRepository(ClientContext &context); + + static ExtensionRepository GetCoreRepository(); + static ExtensionRepository GetRepositoryByUrl(const string &url); + + ExtensionRepository(); + ExtensionRepository(const string &name, const string &url); + + //! Print the name if it has one, or the full path if not + string ToReadableString(); + + //! Repository name + string name; + //! Repository path/url + string path; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/main/extension_util.hpp b/src/include/duckdb/main/extension_util.hpp index bbfae5f3e18..6d790344de6 100644 --- a/src/include/duckdb/main/extension_util.hpp +++ b/src/include/duckdb/main/extension_util.hpp @@ -12,6 +12,7 @@ #include "duckdb/function/cast/cast_function_set.hpp" #include "duckdb/function/function_set.hpp" #include "duckdb/main/secret/secret.hpp" +#include "duckdb/parser/parsed_data/create_type_info.hpp" namespace duckdb { struct CreateMacroInfo; @@ -59,7 +60,8 @@ class ExtensionUtil { DUCKDB_API static void AddFunctionOverload(DatabaseInstance &db, TableFunctionSet function); //! Registers a new type - DUCKDB_API static void RegisterType(DatabaseInstance &db, string type_name, LogicalType type); + DUCKDB_API static void RegisterType(DatabaseInstance &db, string type_name, LogicalType type, + bind_type_modifiers_function_t bind_type_modifiers = nullptr); //! Registers a new secret type DUCKDB_API static void RegisterSecretType(DatabaseInstance &db, SecretType secret_type); diff --git a/src/include/duckdb/main/external_dependencies.hpp b/src/include/duckdb/main/external_dependencies.hpp index 4523d9133fa..ed6afd4a92c 100644 --- a/src/include/duckdb/main/external_dependencies.hpp +++ b/src/include/duckdb/main/external_dependencies.hpp @@ -6,17 +6,59 @@ // //===----------------------------------------------------------------------===// +#include "duckdb/common/case_insensitive_map.hpp" +#include + #pragma once namespace duckdb { -enum class ExternalDependenciesType : uint8_t { PYTHON_DEPENDENCY }; +class DependencyItem { +public: + virtual ~DependencyItem() {}; + +public: + template + TARGET &Cast() { + DynamicCastCheck(this); + return reinterpret_cast(*this); + } + template + const TARGET &Cast() const { + DynamicCastCheck(this); + return reinterpret_cast(*this); + } +}; + +using dependency_scan_t = std::function item)>; class ExternalDependency { public: - explicit ExternalDependency(ExternalDependenciesType type_p) : type(type_p) {}; - virtual ~ExternalDependency() {}; - ExternalDependenciesType type; + explicit ExternalDependency() { + } + ~ExternalDependency() { + } + +public: + void AddDependency(const string &name, shared_ptr item) { + objects[name] = std::move(item); + } + shared_ptr GetDependency(const string &name) const { + auto it = objects.find(name); + if (it == objects.end()) { + return nullptr; + } + return it->second; + } + void ScanDependencies(const dependency_scan_t &callback) { + for (auto &kv : objects) { + callback(kv.first, kv.second); + } + } + +private: + //! The objects encompassed by this dependency + case_insensitive_map_t> objects; }; } // namespace duckdb diff --git a/src/include/duckdb/main/materialized_query_result.hpp b/src/include/duckdb/main/materialized_query_result.hpp index 483f6de1b6b..25c50d9803b 100644 --- a/src/include/duckdb/main/materialized_query_result.hpp +++ b/src/include/duckdb/main/materialized_query_result.hpp @@ -53,6 +53,9 @@ class MaterializedQueryResult : public QueryResult { //! Returns a reference to the underlying column data collection ColumnDataCollection &Collection(); + //! Takes ownership of the collection, 'collection' is null after this operation + unique_ptr TakeCollection(); + private: unique_ptr collection; //! Row collection, only created if GetValue is called diff --git a/src/include/duckdb/main/pending_query_result.hpp b/src/include/duckdb/main/pending_query_result.hpp index 8b95a025e24..9a3d1846de3 100644 --- a/src/include/duckdb/main/pending_query_result.hpp +++ b/src/include/duckdb/main/pending_query_result.hpp @@ -40,6 +40,8 @@ class PendingQueryResult : public BaseQueryResult { //! The error message can be obtained by calling GetError() on the PendingQueryResult. DUCKDB_API PendingExecutionResult ExecuteTask(); DUCKDB_API PendingExecutionResult CheckPulse(); + //! Halt execution of the thread until a Task is ready to be executed (use with caution) + void WaitForTask(); //! Returns the result of the query as an actual query result. //! This returns (mostly) instantly if ExecuteTask has been called until RESULT_READY was returned. diff --git a/src/include/duckdb/main/profiling_info.hpp b/src/include/duckdb/main/profiling_info.hpp new file mode 100644 index 00000000000..22ebe4dbcf9 --- /dev/null +++ b/src/include/duckdb/main/profiling_info.hpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/main/tree_node_settings.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/common.hpp" +#include "duckdb/common/enums/output_type.hpp" +#include "duckdb/common/enums/profiler_format.hpp" +#include "duckdb/common/progress_bar/progress_bar.hpp" +#include "duckdb/common/types/value.hpp" +#include "duckdb/common/unordered_set.hpp" +#include "duckdb/common/constants.hpp" + +namespace duckdb { + +enum class MetricsType : uint8_t { CPU_TIME, EXTRA_INFO, OPERATOR_CARDINALITY, OPERATOR_TIMING }; + +struct MetricsTypeHashFunction { + uint64_t operator()(const MetricsType &index) const { + return std::hash()(static_cast(index)); + } +}; + +typedef unordered_set profiler_settings_t; + +struct SettingSetFunctions { + static bool Enabled(const profiler_settings_t &settings, const MetricsType setting) { + if (settings.find(setting) != settings.end()) { + return true; + } + if (setting == MetricsType::OPERATOR_TIMING && Enabled(settings, MetricsType::CPU_TIME)) { + return true; + } + return false; + } +}; + +struct Metrics { + double cpu_time; + string extra_info; + idx_t operator_cardinality; + double operator_timing; + + Metrics() : cpu_time(0), operator_cardinality(0), operator_timing(0) { + } +}; + +class ProfilingInfo { +public: + // set of metrics with their values; only enabled metrics are present in the set + profiler_settings_t settings; + Metrics metrics; + +public: + ProfilingInfo() = default; + explicit ProfilingInfo(profiler_settings_t &n_settings) : settings(n_settings) { + } + ProfilingInfo(ProfilingInfo &) = default; + ProfilingInfo &operator=(ProfilingInfo const &) = default; + +public: + // set the metrics set + void SetSettings(profiler_settings_t const &n_settings); + // get the metrics set + const profiler_settings_t &GetSettings(); + static profiler_settings_t DefaultSettings(); + +public: + // reset the metrics to default + void ResetSettings(); + void ResetMetrics(); + bool Enabled(const MetricsType setting) const; + +public: + string GetMetricAsString(MetricsType setting) const; + void PrintAllMetricsToSS(std::ostream &ss, const string &depth); +}; +} // namespace duckdb diff --git a/src/include/duckdb/main/query_profiler.hpp b/src/include/duckdb/main/query_profiler.hpp index 9c231ab530b..ecf48657cb3 100644 --- a/src/include/duckdb/main/query_profiler.hpp +++ b/src/include/duckdb/main/query_profiler.hpp @@ -9,18 +9,20 @@ #pragma once #include "duckdb/common/common.hpp" +#include "duckdb/common/deque.hpp" #include "duckdb/common/enums/profiler_format.hpp" +#include "duckdb/common/pair.hpp" #include "duckdb/common/profiler.hpp" +#include "duckdb/common/reference_map.hpp" #include "duckdb/common/string_util.hpp" #include "duckdb/common/types/data_chunk.hpp" #include "duckdb/common/unordered_map.hpp" #include "duckdb/common/winapi.hpp" -#include "duckdb/execution/physical_operator.hpp" #include "duckdb/execution/expression_executor_state.hpp" -#include "duckdb/common/reference_map.hpp" +#include "duckdb/execution/physical_operator.hpp" +#include "duckdb/main/profiling_info.hpp" + #include -#include "duckdb/common/pair.hpp" -#include "duckdb/common/deque.hpp" namespace duckdb { class ClientContext; @@ -32,31 +34,46 @@ struct OperatorInformation { explicit OperatorInformation(double time_p = 0, idx_t elements_p = 0) : time(time_p), elements(elements_p) { } - double time = 0; - idx_t elements = 0; + double time; + idx_t elements; string name; + + void AddTime(double n_time) { + this->time += n_time; + } + + void AddElements(idx_t n_elements) { + this->elements += n_elements; + } }; //! The OperatorProfiler measures timings of individual operators +//! This class exists once for all operators and collects `OperatorInfo` for each operator class OperatorProfiler { friend class QueryProfiler; public: - DUCKDB_API explicit OperatorProfiler(bool enabled); + DUCKDB_API explicit OperatorProfiler(ClientContext &context); DUCKDB_API void StartOperator(optional_ptr phys_op); DUCKDB_API void EndOperator(optional_ptr chunk); + + //! Adds the timings gathered in the OperatorProfiler (tree) to the QueryProfiler (tree) DUCKDB_API void Flush(const PhysicalOperator &phys_op, ExpressionExecutor &expression_executor, const string &name, int id); + DUCKDB_API OperatorInformation &GetOperatorInfo(const PhysicalOperator &phys_op); + + static bool SettingEnabled(const MetricsType setting) { + return SettingSetFunctions::Enabled(ProfilingInfo::DefaultSettings(), setting); + } ~OperatorProfiler() { } private: - void AddTiming(const PhysicalOperator &op, double time, idx_t elements); - //! Whether or not the profiler is enabled bool enabled; + profiler_settings_t settings; //! The timer used to time the execution time of the individual Physical Operators Profiler op; //! The stack of Physical Operators that are currently active @@ -71,22 +88,28 @@ class QueryProfiler { DUCKDB_API explicit QueryProfiler(ClientContext &context); public: + // Recursive tree that mirrors the operator tree struct TreeNode { PhysicalOperatorType type; string name; - string extra_info; - OperatorInformation info; + ProfilingInfo profiling_info; vector> children; idx_t depth = 0; }; + // Holds the top level query info + struct QueryInfo { + string query; + ProfilingInfo settings; + }; + // Propagate save_location, enabled, detailed_enabled and automatic_print_format. void Propagate(QueryProfiler &qp); using TreeMap = reference_map_t>; private: - unique_ptr CreateTree(const PhysicalOperator &root, idx_t depth = 0); + unique_ptr CreateTree(const PhysicalOperator &root, profiler_settings_t settings, idx_t depth = 0); void Render(const TreeNode &node, std::ostream &str) const; public: @@ -119,6 +142,7 @@ class QueryProfiler { //! the return value is formatted based on the current print format (see GetPrintFormat()). DUCKDB_API string ToString() const; + static string JSONSanitize(const string &text); DUCKDB_API string ToJSON() const; DUCKDB_API void WriteToFile(const char *path, string &info) const; @@ -141,6 +165,10 @@ class QueryProfiler { //! The root of the query tree unique_ptr root; + + //! The query info + unique_ptr query_info; + //! The query string string query; //! The timer used to time the execution time of the entire query @@ -171,6 +199,7 @@ class QueryProfiler { //! Check whether or not an operator type requires query profiling. If none of the ops in a query require profiling //! no profiling information is output. bool OperatorRequiresProfiling(PhysicalOperatorType op_type); + void ReadAndSetCustomProfilerSettings(const string &settings_path); }; } // namespace duckdb diff --git a/src/include/duckdb/main/relation.hpp b/src/include/duckdb/main/relation.hpp index 9b7ca2ee7ac..f53770d8412 100644 --- a/src/include/duckdb/main/relation.hpp +++ b/src/include/duckdb/main/relation.hpp @@ -17,6 +17,7 @@ #include "duckdb/parser/column_definition.hpp" #include "duckdb/common/named_parameter_map.hpp" #include "duckdb/main/client_context.hpp" +#include "duckdb/main/client_context_wrapper.hpp" #include "duckdb/main/external_dependencies.hpp" #include "duckdb/parser/statement/explain_statement.hpp" #include "duckdb/parser/parsed_expression.hpp" @@ -28,7 +29,6 @@ namespace duckdb { struct BoundStatement; -class ClientContextWrapper; class Binder; class LogicalOperator; class QueryNode; @@ -44,10 +44,8 @@ class Relation : public enable_shared_from_this { } ClientContextWrapper context; - RelationType type; - - shared_ptr extra_dependencies; + vector> external_dependencies; public: DUCKDB_API virtual const vector &Columns() = 0; @@ -172,6 +170,7 @@ class Relation : public enable_shared_from_this { virtual Relation *ChildRelation() { return nullptr; } + void AddExternalDependency(shared_ptr dependency); DUCKDB_API vector> GetAllDependencies(); protected: diff --git a/src/include/duckdb/main/relation/materialized_relation.hpp b/src/include/duckdb/main/relation/materialized_relation.hpp new file mode 100644 index 00000000000..74825fe46e2 --- /dev/null +++ b/src/include/duckdb/main/relation/materialized_relation.hpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/main/relation/materialized_relation.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/main/relation.hpp" +#include "duckdb/parser/parsed_expression.hpp" + +namespace duckdb { + +class MaterializedRelation : public Relation { +public: + MaterializedRelation(const shared_ptr &context, unique_ptr &&collection, + vector names, string alias = "materialized"); + MaterializedRelation(const shared_ptr &context, const string &values, vector names, + string alias = "materialized"); + + unique_ptr collection; + vector columns; + string alias; + +public: + const vector &Columns() override; + string ToString(idx_t depth) override; + string GetAlias() override; + unique_ptr GetTableRef() override; + unique_ptr GetQueryNode() override; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/main/relation/query_relation.hpp b/src/include/duckdb/main/relation/query_relation.hpp index f35a8133cd7..478afd9064b 100644 --- a/src/include/duckdb/main/relation/query_relation.hpp +++ b/src/include/duckdb/main/relation/query_relation.hpp @@ -27,6 +27,7 @@ class QueryRelation : public Relation { static unique_ptr ParseStatement(ClientContext &context, const string &query, const string &error); unique_ptr GetQueryNode() override; unique_ptr GetTableRef() override; + BoundStatement Bind(Binder &binder) override; const vector &Columns() override; string ToString(idx_t depth) override; diff --git a/src/include/duckdb/main/settings.hpp b/src/include/duckdb/main/settings.hpp index 72e77c29492..c9bddb9c137 100644 --- a/src/include/duckdb/main/settings.hpp +++ b/src/include/duckdb/main/settings.hpp @@ -206,6 +206,26 @@ struct EnableExternalAccessSetting { static Value GetSetting(const ClientContext &context); }; +struct EnableMacrosDependencies { + static constexpr const char *Name = "enable_macro_dependencies"; + static constexpr const char *Description = + "Enable created MACROs to create dependencies on the referenced objects (such as tables)"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::BOOLEAN; + static void SetGlobal(DatabaseInstance *db, DBConfig &config, const Value ¶meter); + static void ResetGlobal(DatabaseInstance *db, DBConfig &config); + static Value GetSetting(const ClientContext &context); +}; + +struct EnableViewDependencies { + static constexpr const char *Name = "enable_view_dependencies"; + static constexpr const char *Description = + "Enable created VIEWs to create dependencies on the referenced objects (such as tables)"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::BOOLEAN; + static void SetGlobal(DatabaseInstance *db, DBConfig &config, const Value ¶meter); + static void ResetGlobal(DatabaseInstance *db, DBConfig &config); + static Value GetSetting(const ClientContext &context); +}; + struct EnableFSSTVectors { static constexpr const char *Name = "enable_fsst_vectors"; static constexpr const char *Description = @@ -225,6 +245,15 @@ struct AllowUnsignedExtensionsSetting { static Value GetSetting(const ClientContext &context); }; +struct AllowCommunityExtensionsSetting { + static constexpr const char *Name = "allow_community_extensions"; + static constexpr const char *Description = "Allow to load community built extensions"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::BOOLEAN; + static void SetGlobal(DatabaseInstance *db, DBConfig &config, const Value ¶meter); + static void ResetGlobal(DatabaseInstance *db, DBConfig &config); + static Value GetSetting(const ClientContext &context); +}; + struct AllowExtensionsMetadataMismatchSetting { static constexpr const char *Name = "allow_extensions_metadata_mismatch"; static constexpr const char *Description = "Allow to load extensions with not compatible metadata"; @@ -291,6 +320,15 @@ struct EnableObjectCacheSetting { static Value GetSetting(const ClientContext &context); }; +struct StorageCompatibilityVersion { + static constexpr const char *Name = "storage_compatibility_version"; + static constexpr const char *Description = "Serialize on checkpoint with compatibility for a given duckdb version"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::VARCHAR; + static void SetGlobal(DatabaseInstance *db, DBConfig &config, const Value ¶meter); + static void ResetGlobal(DatabaseInstance *db, DBConfig &config); + static Value GetSetting(const ClientContext &context); +}; + struct EnableHTTPMetadataCacheSetting { static constexpr const char *Name = "enable_http_metadata_cache"; static constexpr const char *Description = "Whether or not the global http metadata is used to cache HTTP metadata"; @@ -310,6 +348,15 @@ struct EnableProfilingSetting { static Value GetSetting(const ClientContext &context); }; +struct CustomProfilingSettings { + static constexpr const char *Name = "custom_profiling_settings"; + static constexpr const char *Description = "Accepts a JSON enabling custom metrics"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::VARCHAR; + static void SetLocal(ClientContext &context, const Value ¶meter); + static void ResetLocal(ClientContext &context); + static Value GetSetting(const ClientContext &context); +}; + struct EnableProgressBarSetting { static constexpr const char *Name = "enable_progress_bar"; static constexpr const char *Description = @@ -471,6 +518,16 @@ struct MaximumMemorySetting { static Value GetSetting(const ClientContext &context); }; +struct StreamingBufferSize { + static constexpr const char *Name = "streaming_buffer_size"; + static constexpr const char *Description = + "The maximum memory to buffer between fetching from a streaming result (e.g. 1GB)"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::VARCHAR; + static void SetLocal(ClientContext &context, const Value ¶meter); + static void ResetLocal(ClientContext &context); + static Value GetSetting(const ClientContext &context); +}; + struct MaximumTempDirectorySize { static constexpr const char *Name = "max_temp_directory_size"; static constexpr const char *Description = @@ -500,6 +557,16 @@ struct PartitionedWriteFlushThreshold { static Value GetSetting(const ClientContext &context); }; +struct DefaultBlockAllocSize { + static constexpr const char *Name = "default_block_size"; + static constexpr const char *Description = + "The default block size for new duckdb database files (new as-in, they do not yet exist)."; + static constexpr const LogicalTypeId InputType = LogicalTypeId::UBIGINT; + static void SetGlobal(DatabaseInstance *db, DBConfig &config, const Value ¶meter); + static void ResetGlobal(DatabaseInstance *db, DBConfig &config); + static Value GetSetting(const ClientContext &context); +}; + struct PasswordSetting { static constexpr const char *Name = "password"; static constexpr const char *Description = "The password to use. Ignored for legacy compatibility."; @@ -558,6 +625,26 @@ struct PreserveInsertionOrder { static Value GetSetting(const ClientContext &context); }; +struct ArrowOutputListView { + static constexpr const char *Name = "arrow_output_list_view"; + static constexpr const char *Description = + "If export to arrow format should use ListView as the physical layout for LIST columns"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::BOOLEAN; + static void SetGlobal(DatabaseInstance *db, DBConfig &config, const Value ¶meter); + static void ResetGlobal(DatabaseInstance *db, DBConfig &config); + static Value GetSetting(const ClientContext &context); +}; + +struct ProduceArrowStringView { + static constexpr const char *Name = "produce_arrow_string_view"; + static constexpr const char *Description = + "If strings should be produced by DuckDB in Utf8View format instead of Utf8"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::BOOLEAN; + static void SetGlobal(DatabaseInstance *db, DBConfig &config, const Value ¶meter); + static void ResetGlobal(DatabaseInstance *db, DBConfig &config); + static Value GetSetting(const ClientContext &context); +}; + struct ProfileOutputSetting { static constexpr const char *Name = "profile_output"; static constexpr const char *Description = @@ -653,6 +740,15 @@ struct FlushAllocatorSetting { static Value GetSetting(const ClientContext &context); }; +struct AllocatorBackgroundThreadsSetting { + static constexpr const char *Name = "allocator_background_threads"; + static constexpr const char *Description = "Whether to enable the allocator background thread."; + static constexpr const LogicalTypeId InputType = LogicalTypeId::BOOLEAN; + static void SetGlobal(DatabaseInstance *db, DBConfig &config, const Value ¶meter); + static void ResetGlobal(DatabaseInstance *db, DBConfig &config); + static Value GetSetting(const ClientContext &context); +}; + struct DuckDBApiSetting { static constexpr const char *Name = "duckdb_api"; static constexpr const char *Description = "DuckDB API surface"; @@ -671,4 +767,23 @@ struct CustomUserAgentSetting { static Value GetSetting(const ClientContext &context); }; +struct EnableHTTPLoggingSetting { + static constexpr const char *Name = "enable_http_logging"; + static constexpr const char *Description = "Enables HTTP logging"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::BOOLEAN; + static void SetLocal(ClientContext &context, const Value ¶meter); + static void ResetLocal(ClientContext &context); + static Value GetSetting(const ClientContext &context); +}; + +struct HTTPLoggingOutputSetting { + static constexpr const char *Name = "http_logging_output"; + static constexpr const char *Description = + "The file to which HTTP logging output should be saved, or empty to print to the terminal"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::VARCHAR; + static void SetLocal(ClientContext &context, const Value ¶meter); + static void ResetLocal(ClientContext &context); + static Value GetSetting(const ClientContext &context); +}; + } // namespace duckdb diff --git a/src/include/duckdb/main/stream_query_result.hpp b/src/include/duckdb/main/stream_query_result.hpp index 5b8016c809f..648ac253f7a 100644 --- a/src/include/duckdb/main/stream_query_result.hpp +++ b/src/include/duckdb/main/stream_query_result.hpp @@ -34,6 +34,7 @@ class StreamQueryResult : public QueryResult { DUCKDB_API StreamQueryResult(StatementType statement_type, StatementProperties properties, vector types, vector names, ClientProperties client_properties, shared_ptr buffered_data); + DUCKDB_API explicit StreamQueryResult(ErrorData error); DUCKDB_API ~StreamQueryResult() override; public: diff --git a/src/include/duckdb/optimizer/build_probe_side_optimizer.hpp b/src/include/duckdb/optimizer/build_probe_side_optimizer.hpp new file mode 100644 index 00000000000..617317e984a --- /dev/null +++ b/src/include/duckdb/optimizer/build_probe_side_optimizer.hpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/build_side_probe_side_optimizer.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/unordered_set.hpp" +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb/planner/operator/logical_filter.hpp" +#include "duckdb/common/vector.hpp" + +namespace duckdb { + +class BuildProbeSideOptimizer : LogicalOperatorVisitor { +public: + explicit BuildProbeSideOptimizer(ClientContext &context, LogicalOperator &op); + + void VisitOperator(LogicalOperator &op) override; + void VisitExpression(unique_ptr *expression) override {}; + + void TryFlipJoinChildren(LogicalOperator &op, idx_t cardinality_ratio = 1); + +private: + ClientContext &context; + vector preferred_on_probe_side; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/optimizer/filter_pushdown.hpp b/src/include/duckdb/optimizer/filter_pushdown.hpp index c8c87fd5b92..258f8d0a721 100644 --- a/src/include/duckdb/optimizer/filter_pushdown.hpp +++ b/src/include/duckdb/optimizer/filter_pushdown.hpp @@ -61,6 +61,8 @@ class FilterPushdown { unique_ptr PushdownGet(unique_ptr op); //! Push down a LogicalLimit op unique_ptr PushdownLimit(unique_ptr op); + //! Push down a LogicalWindow op + unique_ptr PushdownWindow(unique_ptr op); // Pushdown an inner join unique_ptr PushdownInnerJoin(unique_ptr op, unordered_set &left_bindings, unordered_set &right_bindings); @@ -88,6 +90,9 @@ class FilterPushdown { //! Adds a filter to the set of filters. Returns FilterResult::UNSATISFIABLE if the subtree should be stripped, or //! FilterResult::SUCCESS otherwise FilterResult AddFilter(unique_ptr expr); + //! Extract filter bindings to compare them with expressions in an operator and determine if the filter + //! can be pushed down + void ExtractFilterBindings(Expression &expr, vector &bindings); //! Generate filters from the current set of filters stored in the FilterCombiner void GenerateFilters(); //! if there are filters in this FilterPushdown node, push them into the combiner diff --git a/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp b/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp index e4862ff5785..5390357102b 100644 --- a/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp +++ b/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp @@ -14,7 +14,17 @@ namespace duckdb { -struct FilterInfo; +class FilterInfo; + +struct DenomInfo { + DenomInfo(JoinRelationSet &numerator_relations, double filter_strength, double denominator) + : numerator_relations(numerator_relations), filter_strength(filter_strength), denominator(denominator) { + } + + JoinRelationSet &numerator_relations; + double filter_strength; + double denominator; +}; struct RelationsToTDom { //! column binding sets that are equivalent in a join plan. @@ -25,7 +35,7 @@ struct RelationsToTDom { //! the estimated total domains of each relation without using HLL idx_t tdom_no_hll; bool has_tdom_hll; - vector filters; + vector> filters; vector column_names; explicit RelationsToTDom(const column_binding_set_t &column_binding_set) @@ -33,23 +43,43 @@ struct RelationsToTDom { has_tdom_hll(false) {}; }; +class FilterInfoWithTotalDomains { +public: + FilterInfoWithTotalDomains(optional_ptr filter_info, RelationsToTDom &relation2tdom) + : filter_info(filter_info), tdom_hll(relation2tdom.tdom_hll), tdom_no_hll(relation2tdom.tdom_no_hll), + has_tdom_hll(relation2tdom.has_tdom_hll) { + } + + optional_ptr filter_info; + //! the estimated total domains of the equivalent relations determined using HLL + idx_t tdom_hll; + //! the estimated total domains of each relation without using HLL + idx_t tdom_no_hll; + bool has_tdom_hll; +}; + struct Subgraph2Denominator { - unordered_set relations; + optional_ptr relations; + optional_ptr numerator_relations; double denom; - Subgraph2Denominator() : relations(), denom(1) {}; + Subgraph2Denominator() : relations(nullptr), numerator_relations(nullptr), denom(1) {}; }; class CardinalityHelper { public: CardinalityHelper() { } - CardinalityHelper(double cardinality_before_filters, double filter_string) - : cardinality_before_filters(cardinality_before_filters), filter_strength(filter_string) {}; + explicit CardinalityHelper(double cardinality_before_filters) + : cardinality_before_filters(cardinality_before_filters) {}; public: + // must be a double. Otherwise we can lose significance between different join orders. + // our cardinality estimator severely underestimates cardinalities for 3+ joins. However, + // if one join order has an estimate of 0.8, and another has an estimate of 0.6, rounding + // them means there is no estimated difference, when in reality there could be a very large + // difference. double cardinality_before_filters; - double filter_strength; vector table_names_joined; vector column_names; @@ -57,6 +87,7 @@ class CardinalityHelper { class CardinalityEstimator { public: + static constexpr double DEFAULT_SEMI_ANTI_SELECTIVITY = 5; explicit CardinalityEstimator() {}; private: @@ -82,12 +113,21 @@ class CardinalityEstimator { void PrintRelationToTdomInfo(); private: - bool SingleRelationFilter(FilterInfo &filter_info); - vector DetermineMatchingEquivalentSets(FilterInfo *filter_info); + double GetNumerator(JoinRelationSet &set); + DenomInfo GetDenominator(JoinRelationSet &set); + + bool SingleColumnFilter(FilterInfo &filter_info); + vector DetermineMatchingEquivalentSets(optional_ptr filter_info); //! Given a filter, add the column bindings to the matching equivalent set at the index //! given in matching equivalent sets. //! If there are multiple equivalence sets, they are merged. - void AddToEquivalenceSets(FilterInfo *filter_info, vector matching_equivalent_sets); + void AddToEquivalenceSets(optional_ptr filter_info, vector matching_equivalent_sets); + + double CalculateUpdatedDenom(Subgraph2Denominator left, Subgraph2Denominator right, + FilterInfoWithTotalDomains &filter); + JoinRelationSet &UpdateNumeratorRelations(Subgraph2Denominator left, Subgraph2Denominator right, + FilterInfoWithTotalDomains &filter); + void AddRelationTdom(FilterInfo &filter_info); bool EmptyFilter(FilterInfo &filter_info); }; diff --git a/src/include/duckdb/optimizer/join_order/cost_model.hpp b/src/include/duckdb/optimizer/join_order/cost_model.hpp index 446a127e19e..d6a9245b8ed 100644 --- a/src/include/duckdb/optimizer/join_order/cost_model.hpp +++ b/src/include/duckdb/optimizer/join_order/cost_model.hpp @@ -8,6 +8,7 @@ #pragma once #include "duckdb/optimizer/join_order/join_node.hpp" +#include "duckdb/common/enums/join_type.hpp" #include "duckdb/optimizer/join_order/cardinality_estimator.hpp" namespace duckdb { diff --git a/src/include/duckdb/optimizer/join_order/estimated_properties.hpp b/src/include/duckdb/optimizer/join_order/estimated_properties.hpp deleted file mode 100644 index 7404d6cea7a..00000000000 --- a/src/include/duckdb/optimizer/join_order/estimated_properties.hpp +++ /dev/null @@ -1,57 +0,0 @@ -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/optimizer/join_order/estimated_properties.hpp -// -// -//===----------------------------------------------------------------------===// - -#pragma once - -#include "duckdb/common/unordered_map.hpp" -#include "duckdb/common/unordered_set.hpp" -#include "duckdb/optimizer/join_order/join_relation.hpp" -#include "duckdb/parser/expression_map.hpp" -#include "duckdb/planner/logical_operator_visitor.hpp" -#include "duckdb/storage/statistics/distinct_statistics.hpp" -#include "duckdb/planner/table_filter.hpp" - -namespace duckdb { - -class EstimatedProperties { -public: - EstimatedProperties(double cardinality, double cost) : cardinality(cardinality), cost(cost) {}; - EstimatedProperties() : cardinality(0), cost(0) {}; - - template - T GetCardinality() const { - throw NotImplementedException("Unsupported type for GetCardinality"); - } - template - T GetCost() const { - throw NotImplementedException("Unsupported type for GetCost"); - } - void SetCost(double new_cost); - void SetCardinality(double cardinality); - -private: - double cardinality; - double cost; - -public: - unique_ptr Copy(); -}; - -template <> -double EstimatedProperties::GetCardinality() const; - -template <> -idx_t EstimatedProperties::GetCardinality() const; - -template <> -double EstimatedProperties::GetCost() const; - -template <> -idx_t EstimatedProperties::GetCost() const; - -} // namespace duckdb diff --git a/src/include/duckdb/optimizer/join_order/join_node.hpp b/src/include/duckdb/optimizer/join_order/join_node.hpp index 9c9a54bfb59..b68f9a0a4e7 100644 --- a/src/include/duckdb/optimizer/join_order/join_node.hpp +++ b/src/include/duckdb/optimizer/join_order/join_node.hpp @@ -30,7 +30,7 @@ class DPJoinNode { //! in the cost model is error prone. If the plan enumerator join node is updated and not the cost model //! the whole Join Order Optimizer can start exhibiting undesired behavior. double cost; - //! used only to populate logical operators with estimated caridnalities after the best join plan has been found. + //! used only to populate logical operators with estimated cardinalities after the best join plan has been found. idx_t cardinality; //! Create an intermediate node in the join tree. base_cardinality = estimated_props.cardinality @@ -43,41 +43,4 @@ class DPJoinNode { explicit DPJoinNode(JoinRelationSet &set); }; -class JoinNode { -public: - //! Represents a node in the join plan - JoinRelationSet &set; - //! information on how left and right are connected - optional_ptr info; - //! left and right plans - unique_ptr left; - unique_ptr right; - - //! The cost of the join node. The cost is stored here so that the cost of - //! a join node stays in sync with how the join node is constructed. Storing the cost in an unordered_set - //! in the cost model is error prone. If the plan enumerator join node is updated and not the cost model - //! the whole Join Order Optimizer can start exhibiting undesired behavior. - double cost; - //! used only to populate logical operators with estimated caridnalities after the best join plan has been found. - idx_t cardinality; - - //! Create an intermediate node in the join tree. base_cardinality = estimated_props.cardinality - JoinNode(JoinRelationSet &set, optional_ptr info, unique_ptr left, - unique_ptr right, double cost); - - //! Create a leaf node in the join tree - //! set cost to 0 for leaf nodes - //! cost will be the cost to *produce* an intermediate table - explicit JoinNode(JoinRelationSet &set); - - bool operator==(const JoinNode &other) { - return other.set.ToString().compare(set.ToString()) == 0; - } - -private: -public: - void Print(); - string ToString(); -}; - } // namespace duckdb diff --git a/src/include/duckdb/optimizer/join_order/join_order_optimizer.hpp b/src/include/duckdb/optimizer/join_order/join_order_optimizer.hpp index 720ec4ab701..5ff52b21722 100644 --- a/src/include/duckdb/optimizer/join_order/join_order_optimizer.hpp +++ b/src/include/duckdb/optimizer/join_order/join_order_optimizer.hpp @@ -31,19 +31,12 @@ class JoinOrderOptimizer { //! Perform join reordering inside a plan unique_ptr Optimize(unique_ptr plan, optional_ptr stats = nullptr); - unique_ptr CreateJoinTree(JoinRelationSet &set, - const vector> &possible_connections, JoinNode &left, - JoinNode &right); - private: ClientContext &context; //! manages the query graph, relations, and edges between relations QueryGraphManager query_graph_manager; - //! The optimal join plan found for the specific JoinRelationSet* - unordered_map> plans; - //! The set of filters extracted from the query graph vector> filters; //! The set of filter infos created from the extracted filters @@ -54,51 +47,7 @@ class JoinOrderOptimizer { CardinalityEstimator cardinality_estimator; - bool full_plan_found; - bool must_update_full_plan; unordered_set join_nodes_in_full_plan; - - //! Extract the bindings referred to by an Expression - bool ExtractBindings(Expression &expression, unordered_set &bindings); - - //! Get column bindings from a filter - void GetColumnBinding(Expression &expression, ColumnBinding &binding); - - //! Traverse the query tree to find (1) base relations, (2) existing join conditions and (3) filters that can be - //! rewritten into joins. Returns true if there are joins in the tree that can be reordered, false otherwise. - bool ExtractJoinRelations(LogicalOperator &input_op, vector> &filter_operators, - optional_ptr parent = nullptr); - - //! Emit a pair as a potential join candidate. Returns the best plan found for the (left, right) connection (either - //! the newly created plan, or an existing plan) - JoinNode &EmitPair(JoinRelationSet &left, JoinRelationSet &right, const vector> &info); - //! Tries to emit a potential join candidate pair. Returns false if too many pairs have already been emitted, - //! cancelling the dynamic programming step. - bool TryEmitPair(JoinRelationSet &left, JoinRelationSet &right, const vector> &info); - - bool EnumerateCmpRecursive(JoinRelationSet &left, JoinRelationSet &right, unordered_set &exclusion_set); - //! Emit a relation set node - bool EmitCSG(JoinRelationSet &node); - //! Enumerate the possible connected subgraphs that can be joined together in the join graph - bool EnumerateCSGRecursive(JoinRelationSet &node, unordered_set &exclusion_set); - //! Rewrite a logical query plan given the join plan - unique_ptr RewritePlan(unique_ptr plan, JoinNode &node); - //! Generate cross product edges inside the side - void GenerateCrossProducts(); - //! Perform the join order solving - void SolveJoinOrder(); - //! Solve the join order exactly using dynamic programming. Returns true if it was completed successfully (i.e. did - //! not time-out) - bool SolveJoinOrderExactly(); - //! Solve the join order approximately using a greedy algorithm - void SolveJoinOrderApproximately(); - - void UpdateDPTree(JoinNode &new_plan); - - void UpdateJoinNodesInFullPlan(JoinNode &node); - bool NodeInFullPlan(JoinNode &node); - - GenerateJoinRelation GenerateJoins(vector> &extracted_relations, JoinNode &node); }; } // namespace duckdb diff --git a/src/include/duckdb/optimizer/join_order/plan_enumerator.hpp b/src/include/duckdb/optimizer/join_order/plan_enumerator.hpp index 5eac876c73b..46aa5ce482d 100644 --- a/src/include/duckdb/optimizer/join_order/plan_enumerator.hpp +++ b/src/include/duckdb/optimizer/join_order/plan_enumerator.hpp @@ -34,16 +34,17 @@ class PlanEnumerator { } //! Perform the join order solving - unique_ptr SolveJoinOrder(); + void SolveJoinOrder(); void InitLeafPlans(); - static unique_ptr BuildSideProbeSideSwaps(unique_ptr plan); + const reference_map_t> &GetPlans() const; private: + //! The set of edges used in the join optimizer QueryGraphEdges const &query_graph; //! The total amount of join pairs that have been considered idx_t pairs = 0; - //! The set of edges used in the join optimizer + //! Grant access to the set manager and the relation manager QueryGraphManager &query_graph_manager; //! Cost model to evaluate cost of joins CostModel &cost_model; @@ -58,13 +59,11 @@ class PlanEnumerator { //! Emit a pair as a potential join candidate. Returns the best plan found for the (left, right) connection (either //! the newly created plan, or an existing plan) - unique_ptr EmitPair(JoinRelationSet &left, JoinRelationSet &right, - const vector> &info); + DPJoinNode &EmitPair(JoinRelationSet &left, JoinRelationSet &right, const vector> &info); //! Tries to emit a potential join candidate pair. Returns false if too many pairs have already been emitted, //! cancelling the dynamic programming step. bool TryEmitPair(JoinRelationSet &left, JoinRelationSet &right, const vector> &info); - unique_ptr CreateJoinNodeFromDPJoinNode(DPJoinNode dp_node); bool EnumerateCmpRecursive(JoinRelationSet &left, JoinRelationSet &right, unordered_set &exclusion_set); //! Emit a relation set node bool EmitCSG(JoinRelationSet &node); diff --git a/src/include/duckdb/optimizer/join_order/query_graph.hpp b/src/include/duckdb/optimizer/join_order/query_graph.hpp index f1c2ded0391..e5ac6713897 100644 --- a/src/include/duckdb/optimizer/join_order/query_graph.hpp +++ b/src/include/duckdb/optimizer/join_order/query_graph.hpp @@ -23,7 +23,7 @@ namespace duckdb { -struct FilterInfo; +class FilterInfo; struct NeighborInfo { explicit NeighborInfo(optional_ptr neighbor) : neighbor(neighbor) { diff --git a/src/include/duckdb/optimizer/join_order/query_graph_manager.hpp b/src/include/duckdb/optimizer/join_order/query_graph_manager.hpp index c65d5131b3f..f5d324bf397 100644 --- a/src/include/duckdb/optimizer/join_order/query_graph_manager.hpp +++ b/src/include/duckdb/optimizer/join_order/query_graph_manager.hpp @@ -9,13 +9,12 @@ #pragma once #include "duckdb/common/common.hpp" +#include "duckdb/common/enums/join_type.hpp" #include "duckdb/common/optional_ptr.hpp" #include "duckdb/common/pair.hpp" -#include "duckdb/common/enums/join_type.hpp" #include "duckdb/common/unordered_map.hpp" #include "duckdb/common/unordered_set.hpp" #include "duckdb/common/vector.hpp" - #include "duckdb/optimizer/join_order/join_node.hpp" #include "duckdb/optimizer/join_order/join_relation.hpp" #include "duckdb/optimizer/join_order/query_graph.hpp" @@ -27,6 +26,8 @@ namespace duckdb { +class QueryGraphEdges; + struct GenerateJoinRelation { GenerateJoinRelation(optional_ptr set, unique_ptr op_p) : set(set), op(std::move(op_p)) { @@ -38,14 +39,18 @@ struct GenerateJoinRelation { //! Filter info struct that is used by the cardinality estimator to set the initial cardinality //! but is also eventually transformed into a query edge. -struct FilterInfo { - FilterInfo(unique_ptr filter, JoinRelationSet &set, idx_t filter_index) - : filter(std::move(filter)), set(set), filter_index(filter_index) { +class FilterInfo { +public: + FilterInfo(unique_ptr filter, JoinRelationSet &set, idx_t filter_index, + JoinType join_type = JoinType::INNER) + : filter(std::move(filter)), set(set), filter_index(filter_index), join_type(join_type) { } +public: unique_ptr filter; JoinRelationSet &set; idx_t filter_index; + JoinType join_type; optional_ptr left_set; optional_ptr right_set; ColumnBinding left_binding; @@ -72,7 +77,7 @@ class QueryGraphManager { bool Build(LogicalOperator &op); //! Reconstruct the logical plan using the plan found by the plan enumerator - unique_ptr Reconstruct(unique_ptr plan, JoinNode &node); + unique_ptr Reconstruct(unique_ptr plan); //! Get a reference to the QueryGraphEdges structure that stores edges between //! nodes and hypernodes. @@ -86,11 +91,8 @@ class QueryGraphManager { //! products to create edges. void CreateQueryGraphCrossProduct(JoinRelationSet &left, JoinRelationSet &right); - //! after join order optimization, we perform build side probe side optimizations. - //! (Basically we put lower expected cardinality columns on the build side, and larger - //! tables on the probe side) - unique_ptr LeftRightOptimizations(unique_ptr op); - void TryFlipChildren(LogicalOperator &op, idx_t cardinality_ratio = 1); + //! A map to store the optimal join plan found for a specific JoinRelationSet* + optional_ptr>> plans; private: vector> filter_operators; @@ -103,14 +105,9 @@ class QueryGraphManager { void GetColumnBinding(Expression &expression, ColumnBinding &binding); - bool ExtractBindings(Expression &expression, unordered_set &bindings); - bool LeftCardLessThanRight(LogicalOperator &op); - void CreateHyperGraphEdges(); - GenerateJoinRelation GenerateJoins(vector> &extracted_relations, JoinNode &node); - - unique_ptr RewritePlan(unique_ptr plan, JoinNode &node); + GenerateJoinRelation GenerateJoins(vector> &extracted_relations, JoinRelationSet &set); }; } // namespace duckdb diff --git a/src/include/duckdb/optimizer/join_order/relation_manager.hpp b/src/include/duckdb/optimizer/join_order/relation_manager.hpp index 54d557adddc..8e25b796c74 100644 --- a/src/include/duckdb/optimizer/join_order/relation_manager.hpp +++ b/src/include/duckdb/optimizer/join_order/relation_manager.hpp @@ -20,7 +20,7 @@ namespace duckdb { -struct FilterInfo; +class FilterInfo; //! Represents a single relation and any metadata accompanying that relation struct SingleJoinRelation { diff --git a/src/include/duckdb/optimizer/limit_pushdown.hpp b/src/include/duckdb/optimizer/limit_pushdown.hpp new file mode 100644 index 00000000000..ad31ae314e0 --- /dev/null +++ b/src/include/duckdb/optimizer/limit_pushdown.hpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/limit_pushdown.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/constants.hpp" + +namespace duckdb { +class LogicalOperator; +class Optimizer; + +class LimitPushdown { +public: + //! Optimize PROJECTION + LIMIT to LIMIT + Projection + unique_ptr Optimize(unique_ptr op); + //! Whether we can perform the optimization on this operator + static bool CanOptimize(LogicalOperator &op); +}; + +} // namespace duckdb diff --git a/src/include/duckdb/optimizer/optimizer.hpp b/src/include/duckdb/optimizer/optimizer.hpp index a33d10c1bc8..4e37ca8eac2 100644 --- a/src/include/duckdb/optimizer/optimizer.hpp +++ b/src/include/duckdb/optimizer/optimizer.hpp @@ -35,6 +35,7 @@ class Optimizer { ExpressionRewriter rewriter; private: + void RunBuiltInOptimizers(); void RunOptimizer(OptimizerType type, const std::function &callback); void Verify(LogicalOperator &op); diff --git a/src/include/duckdb/optimizer/optimizer_extension.hpp b/src/include/duckdb/optimizer/optimizer_extension.hpp index bd2b0c8f703..6ccc6277c1a 100644 --- a/src/include/duckdb/optimizer/optimizer_extension.hpp +++ b/src/include/duckdb/optimizer/optimizer_extension.hpp @@ -13,14 +13,22 @@ namespace duckdb { +class Optimizer; +class ClientContext; + //! The OptimizerExtensionInfo holds static information relevant to the optimizer extension struct OptimizerExtensionInfo { virtual ~OptimizerExtensionInfo() { } }; -typedef void (*optimize_function_t)(ClientContext &context, OptimizerExtensionInfo *info, - unique_ptr &plan); +struct OptimizerExtensionInput { + ClientContext &context; + Optimizer &optimizer; + optional_ptr info; +}; + +typedef void (*optimize_function_t)(OptimizerExtensionInput &input, unique_ptr &plan); class OptimizerExtension { public: diff --git a/src/include/duckdb/optimizer/rule/join_dependent_filter.hpp b/src/include/duckdb/optimizer/rule/join_dependent_filter.hpp new file mode 100644 index 00000000000..4cb48b21b75 --- /dev/null +++ b/src/include/duckdb/optimizer/rule/join_dependent_filter.hpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/rule/join_filter_derivation.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/optimizer/rule.hpp" + +namespace duckdb { + +//! Join-dependent filter derivation as proposed in https://homepages.cwi.nl/~boncz/snb-challenge/chokepoints-tpctc.pdf +//! This rule inspects filters like this: +//! SELECT * +//! FROM nation n1 +//! JOIN nation n2 +//! ON ((n1.n_name = 'FRANCE' +//! AND n2.n_name = 'GERMANY') +//! OR (n1.n_name = 'GERMANY' +//! AND n2.n_name = 'FRANCE')); +//! The join filter as a whole cannot be pushed down, because it references tables from both sides. +//! However, we can derive from this two filters that can be pushed down, namely: +//! WHERE (n1.n_name = 'FRANCE' OR n1.n_name = 'GERMANY') +//! AND (n2.n_name = 'GERMANY' OR n2.n_name = 'FRANCE') +//! By adding this filter, we can reduce both sides of the join before performing the join on the original condition. +class JoinDependentFilterRule : public Rule { +public: + explicit JoinDependentFilterRule(ExpressionRewriter &rewriter); + + unique_ptr Apply(LogicalOperator &op, vector> &bindings, bool &changes_made, + bool is_root) override; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/optimizer/rule/list.hpp b/src/include/duckdb/optimizer/rule/list.hpp index e10f27273b5..361de546d5b 100644 --- a/src/include/duckdb/optimizer/rule/list.hpp +++ b/src/include/duckdb/optimizer/rule/list.hpp @@ -11,3 +11,4 @@ #include "duckdb/optimizer/rule/enum_comparison.hpp" #include "duckdb/optimizer/rule/regex_optimizations.hpp" #include "duckdb/optimizer/rule/ordered_aggregate_optimizer.hpp" +#include "duckdb/optimizer/rule/timestamp_comparison.hpp" diff --git a/src/include/duckdb/optimizer/rule/timestamp_comparison.hpp b/src/include/duckdb/optimizer/rule/timestamp_comparison.hpp new file mode 100644 index 00000000000..a38ed64a899 --- /dev/null +++ b/src/include/duckdb/optimizer/rule/timestamp_comparison.hpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/rule/timestamp_comparison.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/optimizer/rule.hpp" +#include "duckdb/function/scalar/string_functions.hpp" + +namespace duckdb { + +class TimeStampComparison : public Rule { +public: + explicit TimeStampComparison(ClientContext &context, ExpressionRewriter &rewriter); + + unique_ptr Apply(LogicalOperator &op, vector> &bindings, bool &changes_made, + bool is_root) override; + + unique_ptr ApplyRule(BoundFunctionExpression *expr, ScalarFunction function, string pattern, + bool is_not_like); + +private: + ClientContext &context; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/parallel/task_scheduler.hpp b/src/include/duckdb/parallel/task_scheduler.hpp index 42998074fc2..36c35be54da 100644 --- a/src/include/duckdb/parallel/task_scheduler.hpp +++ b/src/include/duckdb/parallel/task_scheduler.hpp @@ -76,6 +76,8 @@ class TaskScheduler { //! Set the allocator flush threshold void SetAllocatorFlushTreshold(idx_t threshold); + //! Sets the allocator background thread + void SetAllocatorBackgroundThreads(bool enable); private: void RelaunchThreadsInternal(int32_t n); @@ -92,6 +94,8 @@ class TaskScheduler { vector>> markers; //! The threshold after which to flush the allocator after completing a task atomic allocator_flush_threshold; + //! Whether allocator background threads are enabled + atomic allocator_background_threads; //! Requested thread count (set by the 'threads' setting) atomic requested_thread_count; //! The amount of threads currently running diff --git a/src/include/duckdb/parser/column_definition.hpp b/src/include/duckdb/parser/column_definition.hpp index 79d1110f6f4..fa5cc8d3872 100644 --- a/src/include/duckdb/parser/column_definition.hpp +++ b/src/include/duckdb/parser/column_definition.hpp @@ -104,6 +104,8 @@ class ColumnDefinition { unique_ptr expression; //! Comment on this column Value comment; + //! Tags on this column + unordered_map tags; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/expression/function_expression.hpp b/src/include/duckdb/parser/expression/function_expression.hpp index 291883df656..f78ae7fee07 100644 --- a/src/include/duckdb/parser/expression/function_expression.hpp +++ b/src/include/duckdb/parser/expression/function_expression.hpp @@ -61,6 +61,9 @@ class FunctionExpression : public ParsedExpression { void Verify() const override; + //! Returns true, if the function has a lambda expression as a child. + bool IsLambdaFunction() const; + public: template static string ToString(const T &entry, const string &catalog, const string &schema, const string &function_name, diff --git a/src/include/duckdb/parser/expression/star_expression.hpp b/src/include/duckdb/parser/expression/star_expression.hpp index 3fa0847d9b0..d95b683d277 100644 --- a/src/include/duckdb/parser/expression/star_expression.hpp +++ b/src/include/duckdb/parser/expression/star_expression.hpp @@ -31,11 +31,16 @@ class StarExpression : public ParsedExpression { unique_ptr expr; //! Whether or not this is a COLUMNS expression bool columns = false; + //! Whether the columns are unpacked + bool unpacked = false; public: string ToString() const override; static bool Equal(const StarExpression &a, const StarExpression &b); + static bool IsStar(const ParsedExpression &a); + static bool IsColumns(const ParsedExpression &a); + static bool IsColumnsUnpacked(const ParsedExpression &a); unique_ptr Copy() const override; diff --git a/src/include/duckdb/parser/parsed_data/alter_info.hpp b/src/include/duckdb/parser/parsed_data/alter_info.hpp index a2f13da220a..88db356afba 100644 --- a/src/include/duckdb/parser/parsed_data/alter_info.hpp +++ b/src/include/duckdb/parser/parsed_data/alter_info.hpp @@ -64,6 +64,7 @@ struct AlterInfo : public ParseInfo { public: virtual CatalogType GetCatalogType() const = 0; virtual unique_ptr Copy() const = 0; + virtual string ToString() const = 0; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/parser/parsed_data/alter_scalar_function_info.hpp b/src/include/duckdb/parser/parsed_data/alter_scalar_function_info.hpp index b33d81d66d0..625f25f318e 100644 --- a/src/include/duckdb/parser/parsed_data/alter_scalar_function_info.hpp +++ b/src/include/duckdb/parser/parsed_data/alter_scalar_function_info.hpp @@ -40,6 +40,7 @@ struct AddScalarFunctionOverloadInfo : public AlterScalarFunctionInfo { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/parsed_data/alter_table_function_info.hpp b/src/include/duckdb/parser/parsed_data/alter_table_function_info.hpp index a518d396759..fc7944c3ff7 100644 --- a/src/include/duckdb/parser/parsed_data/alter_table_function_info.hpp +++ b/src/include/duckdb/parser/parsed_data/alter_table_function_info.hpp @@ -40,6 +40,7 @@ struct AddTableFunctionOverloadInfo : public AlterTableFunctionInfo { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/parsed_data/alter_table_info.hpp b/src/include/duckdb/parser/parsed_data/alter_table_info.hpp index c07f05fc50d..30c53dc1a2a 100644 --- a/src/include/duckdb/parser/parsed_data/alter_table_info.hpp +++ b/src/include/duckdb/parser/parsed_data/alter_table_info.hpp @@ -35,6 +35,7 @@ struct ChangeOwnershipInfo : public AlterInfo { public: CatalogType GetCatalogType() const override; unique_ptr Copy() const override; + string ToString() const override; }; //===--------------------------------------------------------------------===// @@ -50,6 +51,7 @@ struct SetCommentInfo : public AlterInfo { public: CatalogType GetCatalogType() const override; unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); @@ -104,6 +106,7 @@ struct RenameColumnInfo : public AlterTableInfo { public: unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); @@ -124,6 +127,7 @@ struct RenameTableInfo : public AlterTableInfo { public: unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); @@ -146,6 +150,7 @@ struct AddColumnInfo : public AlterTableInfo { public: unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); @@ -170,6 +175,7 @@ struct RemoveColumnInfo : public AlterTableInfo { public: unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); string GetColumnName() const override { @@ -197,6 +203,7 @@ struct ChangeColumnTypeInfo : public AlterTableInfo { public: unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); string GetColumnName() const override { @@ -221,6 +228,7 @@ struct SetDefaultInfo : public AlterTableInfo { public: unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); @@ -245,6 +253,7 @@ struct AlterForeignKeyInfo : public AlterTableInfo { public: unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); @@ -264,6 +273,7 @@ struct SetNotNullInfo : public AlterTableInfo { public: unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); @@ -283,6 +293,7 @@ struct DropNotNullInfo : public AlterTableInfo { public: unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); @@ -322,6 +333,7 @@ struct RenameViewInfo : public AlterViewInfo { public: unique_ptr Copy() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/parser/parsed_data/attach_info.hpp b/src/include/duckdb/parser/parsed_data/attach_info.hpp index 0137592bfc6..7906ac52f36 100644 --- a/src/include/duckdb/parser/parsed_data/attach_info.hpp +++ b/src/include/duckdb/parser/parsed_data/attach_info.hpp @@ -34,7 +34,13 @@ struct AttachInfo : public ParseInfo { OnCreateConflict on_conflict = OnCreateConflict::ERROR_ON_CONFLICT; public: + //! Returns the block allocation size, which is the allocation size of blocks for this attached database file. + //! Returns DConstants::INVALID_INDEX, if not provided. This is NOT the actual memory available on a block + //! (block_size), even though the corresponding option we expose to the user is called "block_size". + optional_idx GetBlockAllocSize() const; + //! Copies this AttachInfo and returns an unique pointer to the new AttachInfo. unique_ptr Copy() const; + string ToString() const; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/parser/parsed_data/comment_on_column_info.hpp b/src/include/duckdb/parser/parsed_data/comment_on_column_info.hpp index b13aaacc474..c274ffb5559 100644 --- a/src/include/duckdb/parser/parsed_data/comment_on_column_info.hpp +++ b/src/include/duckdb/parser/parsed_data/comment_on_column_info.hpp @@ -12,6 +12,7 @@ #include "duckdb/common/types/value.hpp" #include "duckdb/parser/parsed_data/alter_info.hpp" #include "duckdb/parser/qualified_name.hpp" +#include "duckdb/catalog/catalog_entry_retriever.hpp" namespace duckdb { class ClientContext; @@ -35,9 +36,10 @@ struct SetColumnCommentInfo : public AlterInfo { Value comment_value; public: - optional_ptr TryResolveCatalogEntry(ClientContext &context); + optional_ptr TryResolveCatalogEntry(CatalogEntryRetriever &retriever); unique_ptr Copy() const override; CatalogType GetCatalogType() const override; + string ToString() const override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/parser/parsed_data/copy_info.hpp b/src/include/duckdb/parser/parsed_data/copy_info.hpp index 75e8322a32f..46cb8358c3b 100644 --- a/src/include/duckdb/parser/parsed_data/copy_info.hpp +++ b/src/include/duckdb/parser/parsed_data/copy_info.hpp @@ -16,6 +16,8 @@ namespace duckdb { +class QueryNode; + struct CopyInfo : public ParseInfo { public: static constexpr const ParseInfoType TYPE = ParseInfoType::COPY_INFO; @@ -40,20 +42,16 @@ struct CopyInfo : public ParseInfo { string file_path; //! Set of (key, value) options case_insensitive_map_t> options; + // The SQL statement used instead of a table when copying data out to a file + unique_ptr select_statement; public: - unique_ptr Copy() const { - auto result = make_uniq(); - result->catalog = catalog; - result->schema = schema; - result->table = table; - result->select_list = select_list; - result->file_path = file_path; - result->is_from = is_from; - result->format = format; - result->options = options; - return result; - } + static string CopyOptionsToString(const string &format, const case_insensitive_map_t> &options); + +public: + unique_ptr Copy() const; + string ToString() const; + string TablePartToString() const; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/parser/parsed_data/create_info.hpp b/src/include/duckdb/parser/parsed_data/create_info.hpp index 14fd83bfc88..1af6c979012 100644 --- a/src/include/duckdb/parser/parsed_data/create_info.hpp +++ b/src/include/duckdb/parser/parsed_data/create_info.hpp @@ -44,8 +44,12 @@ struct CreateInfo : public ParseInfo { bool internal; //! The SQL string of the CREATE statement string sql; + //! The inherent dependencies of the created entry + LogicalDependencyList dependencies; //! User provided comment Value comment; + //! Key-value tags with additional metadata + unordered_map tags; public: void Serialize(Serializer &serializer) const override; diff --git a/src/include/duckdb/parser/parsed_data/create_type_info.hpp b/src/include/duckdb/parser/parsed_data/create_type_info.hpp index 79f1efaaf19..00551cb46aa 100644 --- a/src/include/duckdb/parser/parsed_data/create_type_info.hpp +++ b/src/include/duckdb/parser/parsed_data/create_type_info.hpp @@ -15,9 +15,18 @@ namespace duckdb { +struct BindTypeModifiersInput { + ClientContext &context; + const LogicalType &type; + const vector &modifiers; +}; + +//! The type to bind type modifiers to a type +typedef LogicalType (*bind_type_modifiers_function_t)(BindTypeModifiersInput &input); + struct CreateTypeInfo : public CreateInfo { CreateTypeInfo(); - CreateTypeInfo(string name_p, LogicalType type_p); + CreateTypeInfo(string name_p, LogicalType type_p, bind_type_modifiers_function_t bind_modifiers_p = nullptr); //! Name of the Type string name; @@ -25,6 +34,8 @@ struct CreateTypeInfo : public CreateInfo { LogicalType type; //! Used by create enum from query unique_ptr query; + //! Bind type modifiers to the type + bind_type_modifiers_function_t bind_modifiers; public: unique_ptr Copy() const override; diff --git a/src/include/duckdb/parser/parsed_data/detach_info.hpp b/src/include/duckdb/parser/parsed_data/detach_info.hpp index 8c0fdedcb7a..a97bafcb96d 100644 --- a/src/include/duckdb/parser/parsed_data/detach_info.hpp +++ b/src/include/duckdb/parser/parsed_data/detach_info.hpp @@ -27,6 +27,7 @@ struct DetachInfo : public ParseInfo { public: unique_ptr Copy() const; + string ToString() const; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/parser/parsed_data/drop_info.hpp b/src/include/duckdb/parser/parsed_data/drop_info.hpp index 841690135d0..40955edcb78 100644 --- a/src/include/duckdb/parser/parsed_data/drop_info.hpp +++ b/src/include/duckdb/parser/parsed_data/drop_info.hpp @@ -44,6 +44,7 @@ struct DropInfo : public ParseInfo { public: virtual unique_ptr Copy() const; + string ToString() const; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/parser/parsed_data/load_info.hpp b/src/include/duckdb/parser/parsed_data/load_info.hpp index b595fa760e1..bc092a41325 100644 --- a/src/include/duckdb/parser/parsed_data/load_info.hpp +++ b/src/include/duckdb/parser/parsed_data/load_info.hpp @@ -24,16 +24,13 @@ struct LoadInfo : public ParseInfo { string filename; string repository; + bool repo_is_alias; + string version; LoadType load_type; public: - unique_ptr Copy() const { - auto result = make_uniq(); - result->filename = filename; - result->repository = repository; - result->load_type = load_type; - return result; - } + unique_ptr Copy() const; + string ToString() const; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/parser/parsed_data/parse_info.hpp b/src/include/duckdb/parser/parsed_data/parse_info.hpp index cb46385cfdf..8810c6c980f 100644 --- a/src/include/duckdb/parser/parsed_data/parse_info.hpp +++ b/src/include/duckdb/parser/parsed_data/parse_info.hpp @@ -13,6 +13,8 @@ namespace duckdb { +enum class CatalogType : uint8_t; + enum class ParseInfoType : uint8_t { ALTER_INFO, ATTACH_INFO, @@ -29,7 +31,8 @@ enum class ParseInfoType : uint8_t { VACUUM_INFO, COMMENT_ON_INFO, COMMENT_ON_COLUMN_INFO, - COPY_DATABASE_INFO + COPY_DATABASE_INFO, + UPDATE_EXTENSIONS_INFO }; struct ParseInfo { diff --git a/src/include/duckdb/parser/parsed_data/pragma_info.hpp b/src/include/duckdb/parser/parsed_data/pragma_info.hpp index 5f76623b726..bbf01242eac 100644 --- a/src/include/duckdb/parser/parsed_data/pragma_info.hpp +++ b/src/include/duckdb/parser/parsed_data/pragma_info.hpp @@ -33,17 +33,8 @@ struct PragmaInfo : public ParseInfo { case_insensitive_map_t> named_parameters; public: - unique_ptr Copy() const { - auto result = make_uniq(); - result->name = name; - for (auto ¶m : parameters) { - result->parameters.push_back(param->Copy()); - } - for (auto &entry : named_parameters) { - result->named_parameters.insert(make_pair(entry.first, entry.second->Copy())); - } - return result; - } + unique_ptr Copy() const; + string ToString() const; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/parser/parsed_data/transaction_info.hpp b/src/include/duckdb/parser/parsed_data/transaction_info.hpp index 59c68914981..ffbc5f128ce 100644 --- a/src/include/duckdb/parser/parsed_data/transaction_info.hpp +++ b/src/include/duckdb/parser/parsed_data/transaction_info.hpp @@ -14,6 +14,12 @@ namespace duckdb { enum class TransactionType : uint8_t { INVALID, BEGIN_TRANSACTION, COMMIT, ROLLBACK }; +enum class TransactionModifierType : uint8_t { + TRANSACTION_DEFAULT_MODIFIER, + TRANSACTION_READ_ONLY, + TRANSACTION_READ_WRITE +}; + struct TransactionInfo : public ParseInfo { public: static constexpr const ParseInfoType TYPE = ParseInfoType::TRANSACTION_INFO; @@ -23,11 +29,16 @@ struct TransactionInfo : public ParseInfo { //! The type of transaction statement TransactionType type; + //! Whether or not a transaction can make modifications to the database + TransactionModifierType modifier; public: void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); + string ToString() const; + unique_ptr Copy() const; + private: TransactionInfo(); }; diff --git a/src/include/duckdb/parser/parsed_data/update_extensions_info.hpp b/src/include/duckdb/parser/parsed_data/update_extensions_info.hpp new file mode 100644 index 00000000000..b43ab89530b --- /dev/null +++ b/src/include/duckdb/parser/parsed_data/update_extensions_info.hpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/parsed_data/update_extensions_info.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/parser/parsed_data/parse_info.hpp" + +namespace duckdb { + +struct UpdateExtensionsInfo : public ParseInfo { +public: + static constexpr const ParseInfoType TYPE = ParseInfoType::UPDATE_EXTENSIONS_INFO; + +public: + UpdateExtensionsInfo() : ParseInfo(TYPE) { + } + + vector extensions_to_update; + +public: + unique_ptr Copy() const { + auto result = make_uniq(); + result->extensions_to_update = extensions_to_update; + return result; + } + + void Serialize(Serializer &serializer) const override; + static unique_ptr Deserialize(Deserializer &deserializer); +}; + +} // namespace duckdb diff --git a/src/include/duckdb/parser/parsed_data/vacuum_info.hpp b/src/include/duckdb/parser/parsed_data/vacuum_info.hpp index 6bd8fe6a60a..5540d38a2f4 100644 --- a/src/include/duckdb/parser/parsed_data/vacuum_info.hpp +++ b/src/include/duckdb/parser/parsed_data/vacuum_info.hpp @@ -44,6 +44,7 @@ struct VacuumInfo : public ParseInfo { public: unique_ptr Copy(); + string ToString() const; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); diff --git a/src/include/duckdb/parser/parser_extension.hpp b/src/include/duckdb/parser/parser_extension.hpp index baf60fb2e67..d530c6af2fe 100644 --- a/src/include/duckdb/parser/parser_extension.hpp +++ b/src/include/duckdb/parser/parser_extension.hpp @@ -33,6 +33,7 @@ struct ParserExtensionParseData { } virtual unique_ptr Copy() const = 0; + virtual string ToString() const = 0; }; struct ParserExtensionParseResult { diff --git a/src/include/duckdb/parser/query_node.hpp b/src/include/duckdb/parser/query_node.hpp index cdd2d7282ad..ec03da095e4 100644 --- a/src/include/duckdb/parser/query_node.hpp +++ b/src/include/duckdb/parser/query_node.hpp @@ -12,7 +12,7 @@ #include "duckdb/parser/parsed_expression.hpp" #include "duckdb/parser/result_modifier.hpp" #include "duckdb/parser/common_table_expression_info.hpp" -#include "duckdb/common/case_insensitive_map.hpp" +#include "duckdb/common/insertion_order_preserving_map.hpp" #include "duckdb/common/exception.hpp" namespace duckdb { @@ -34,7 +34,7 @@ class CommonTableExpressionMap { public: CommonTableExpressionMap(); - case_insensitive_map_t> map; + InsertionOrderPreservingMap> map; public: string ToString() const; diff --git a/src/include/duckdb/parser/sql_statement.hpp b/src/include/duckdb/parser/sql_statement.hpp index dca08e11241..5f9e655ec59 100644 --- a/src/include/duckdb/parser/sql_statement.hpp +++ b/src/include/duckdb/parser/sql_statement.hpp @@ -44,10 +44,7 @@ class SQLStatement { SQLStatement(const SQLStatement &other) = default; public: - virtual string ToString() const { - throw NotImplementedException("ToString not supported for this type of SQLStatement: '%s'", - StatementTypeToString(type)); - } + virtual string ToString() const = 0; //! Create a copy of this SelectStatement DUCKDB_API virtual unique_ptr Copy() const = 0; diff --git a/src/include/duckdb/parser/statement/alter_statement.hpp b/src/include/duckdb/parser/statement/alter_statement.hpp index 67bd648e075..08b26eb47a4 100644 --- a/src/include/duckdb/parser/statement/alter_statement.hpp +++ b/src/include/duckdb/parser/statement/alter_statement.hpp @@ -28,6 +28,7 @@ class AlterStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/attach_statement.hpp b/src/include/duckdb/parser/statement/attach_statement.hpp index 3f1adcc1462..6ee7fb4e5fd 100644 --- a/src/include/duckdb/parser/statement/attach_statement.hpp +++ b/src/include/duckdb/parser/statement/attach_statement.hpp @@ -27,6 +27,7 @@ class AttachStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/call_statement.hpp b/src/include/duckdb/parser/statement/call_statement.hpp index 7fd8fa51680..afd5d256a63 100644 --- a/src/include/duckdb/parser/statement/call_statement.hpp +++ b/src/include/duckdb/parser/statement/call_statement.hpp @@ -28,5 +28,6 @@ class CallStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/copy_database_statement.hpp b/src/include/duckdb/parser/statement/copy_database_statement.hpp index a1f2cfe4aec..d206bc5f600 100644 --- a/src/include/duckdb/parser/statement/copy_database_statement.hpp +++ b/src/include/duckdb/parser/statement/copy_database_statement.hpp @@ -27,13 +27,12 @@ class CopyDatabaseStatement : public SQLStatement { string to_database; CopyDatabaseType copy_type; - string ToString() const override; - protected: CopyDatabaseStatement(const CopyDatabaseStatement &other); public: DUCKDB_API unique_ptr Copy() const override; + string ToString() const override; private: }; diff --git a/src/include/duckdb/parser/statement/copy_statement.hpp b/src/include/duckdb/parser/statement/copy_statement.hpp index 852ac78e6ef..b9318bd6e5f 100644 --- a/src/include/duckdb/parser/statement/copy_statement.hpp +++ b/src/include/duckdb/parser/statement/copy_statement.hpp @@ -14,6 +14,8 @@ namespace duckdb { +enum class CopyToType : uint8_t { COPY_TO_FILE, EXPORT_DATABASE }; + class CopyStatement : public SQLStatement { public: static constexpr const StatementType TYPE = StatementType::COPY_STATEMENT; @@ -22,11 +24,8 @@ class CopyStatement : public SQLStatement { CopyStatement(); unique_ptr info; - // The SQL statement used instead of a table when copying data out to a file - unique_ptr select_statement; string ToString() const override; - static string CopyOptionsToString(const string &format, const case_insensitive_map_t> &options); protected: CopyStatement(const CopyStatement &other); diff --git a/src/include/duckdb/parser/statement/detach_statement.hpp b/src/include/duckdb/parser/statement/detach_statement.hpp index 3d1380cd459..64ab65cf180 100644 --- a/src/include/duckdb/parser/statement/detach_statement.hpp +++ b/src/include/duckdb/parser/statement/detach_statement.hpp @@ -27,6 +27,7 @@ class DetachStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/drop_statement.hpp b/src/include/duckdb/parser/statement/drop_statement.hpp index d8e71e65998..8b865494e89 100644 --- a/src/include/duckdb/parser/statement/drop_statement.hpp +++ b/src/include/duckdb/parser/statement/drop_statement.hpp @@ -27,6 +27,7 @@ class DropStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/execute_statement.hpp b/src/include/duckdb/parser/statement/execute_statement.hpp index 81ca82f500d..2a15165dc15 100644 --- a/src/include/duckdb/parser/statement/execute_statement.hpp +++ b/src/include/duckdb/parser/statement/execute_statement.hpp @@ -29,5 +29,6 @@ class ExecuteStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/explain_statement.hpp b/src/include/duckdb/parser/statement/explain_statement.hpp index f6f6086adad..8e499ef4c15 100644 --- a/src/include/duckdb/parser/statement/explain_statement.hpp +++ b/src/include/duckdb/parser/statement/explain_statement.hpp @@ -30,6 +30,7 @@ class ExplainStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/export_statement.hpp b/src/include/duckdb/parser/statement/export_statement.hpp index 58215e3913b..97430a93018 100644 --- a/src/include/duckdb/parser/statement/export_statement.hpp +++ b/src/include/duckdb/parser/statement/export_statement.hpp @@ -29,6 +29,7 @@ class ExportStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/extension_statement.hpp b/src/include/duckdb/parser/statement/extension_statement.hpp index c75f0668aa0..ddc2aab2727 100644 --- a/src/include/duckdb/parser/statement/extension_statement.hpp +++ b/src/include/duckdb/parser/statement/extension_statement.hpp @@ -27,6 +27,7 @@ class ExtensionStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/list.hpp b/src/include/duckdb/parser/statement/list.hpp index d9d04e17c30..a0d04ce59ce 100644 --- a/src/include/duckdb/parser/statement/list.hpp +++ b/src/include/duckdb/parser/statement/list.hpp @@ -21,4 +21,5 @@ #include "duckdb/parser/statement/set_statement.hpp" #include "duckdb/parser/statement/transaction_statement.hpp" #include "duckdb/parser/statement/update_statement.hpp" +#include "duckdb/parser/statement/update_extensions_statement.hpp" #include "duckdb/parser/statement/vacuum_statement.hpp" diff --git a/src/include/duckdb/parser/statement/load_statement.hpp b/src/include/duckdb/parser/statement/load_statement.hpp index 2333e8f9beb..3667adb79aa 100644 --- a/src/include/duckdb/parser/statement/load_statement.hpp +++ b/src/include/duckdb/parser/statement/load_statement.hpp @@ -25,6 +25,7 @@ class LoadStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; unique_ptr info; }; diff --git a/src/include/duckdb/parser/statement/logical_plan_statement.hpp b/src/include/duckdb/parser/statement/logical_plan_statement.hpp index 811d1b8606a..398003359ae 100644 --- a/src/include/duckdb/parser/statement/logical_plan_statement.hpp +++ b/src/include/duckdb/parser/statement/logical_plan_statement.hpp @@ -27,6 +27,9 @@ class LogicalPlanStatement : public SQLStatement { unique_ptr Copy() const override { throw NotImplementedException("PLAN_STATEMENT"); } + string ToString() const override { + throw NotImplementedException("PLAN STATEMENT"); + } }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/multi_statement.hpp b/src/include/duckdb/parser/statement/multi_statement.hpp index ef1dfc1cfdb..42a26ff6cef 100644 --- a/src/include/duckdb/parser/statement/multi_statement.hpp +++ b/src/include/duckdb/parser/statement/multi_statement.hpp @@ -26,6 +26,7 @@ class MultiStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/pragma_statement.hpp b/src/include/duckdb/parser/statement/pragma_statement.hpp index a1b1e9a267b..249c468b388 100644 --- a/src/include/duckdb/parser/statement/pragma_statement.hpp +++ b/src/include/duckdb/parser/statement/pragma_statement.hpp @@ -28,6 +28,7 @@ class PragmaStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/prepare_statement.hpp b/src/include/duckdb/parser/statement/prepare_statement.hpp index e3df292d41f..c2be759893e 100644 --- a/src/include/duckdb/parser/statement/prepare_statement.hpp +++ b/src/include/duckdb/parser/statement/prepare_statement.hpp @@ -28,5 +28,6 @@ class PrepareStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/relation_statement.hpp b/src/include/duckdb/parser/statement/relation_statement.hpp index f23bd7474a9..b3acb75e353 100644 --- a/src/include/duckdb/parser/statement/relation_statement.hpp +++ b/src/include/duckdb/parser/statement/relation_statement.hpp @@ -27,6 +27,7 @@ class RelationStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/set_statement.hpp b/src/include/duckdb/parser/statement/set_statement.hpp index d477c9cc17b..14c57d3b46e 100644 --- a/src/include/duckdb/parser/statement/set_statement.hpp +++ b/src/include/duckdb/parser/statement/set_statement.hpp @@ -25,10 +25,7 @@ class SetStatement : public SQLStatement { SetStatement(const SetStatement &other) = default; public: - unique_ptr Copy() const override; - -public: - std::string name; + string name; SetScope scope; SetType set_type; }; @@ -42,6 +39,7 @@ class SetVariableStatement : public SetStatement { public: unique_ptr Copy() const override; + string ToString() const override; public: unique_ptr value; @@ -53,6 +51,10 @@ class ResetVariableStatement : public SetStatement { protected: ResetVariableStatement(const ResetVariableStatement &other) = default; + +public: + unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/transaction_statement.hpp b/src/include/duckdb/parser/statement/transaction_statement.hpp index f34ac05f457..3fb5f54fdf8 100644 --- a/src/include/duckdb/parser/statement/transaction_statement.hpp +++ b/src/include/duckdb/parser/statement/transaction_statement.hpp @@ -18,7 +18,7 @@ class TransactionStatement : public SQLStatement { static constexpr const StatementType TYPE = StatementType::TRANSACTION_STATEMENT; public: - explicit TransactionStatement(TransactionType type); + explicit TransactionStatement(unique_ptr info); unique_ptr info; @@ -27,5 +27,6 @@ class TransactionStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/statement/update_extensions_statement.hpp b/src/include/duckdb/parser/statement/update_extensions_statement.hpp new file mode 100644 index 00000000000..2c361b33650 --- /dev/null +++ b/src/include/duckdb/parser/statement/update_extensions_statement.hpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/statement/update_extensions_statement.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/parser/parsed_expression.hpp" +#include "duckdb/parser/sql_statement.hpp" +#include "duckdb/parser/tableref.hpp" +#include "duckdb/common/vector.hpp" +#include "duckdb/parser/query_node.hpp" +#include "duckdb/parser/parsed_data/update_extensions_info.hpp" + +namespace duckdb { + +class UpdateExtensionsStatement : public SQLStatement { +public: + static constexpr const StatementType TYPE = StatementType::UPDATE_EXTENSIONS_STATEMENT; + +public: + UpdateExtensionsStatement(); + unique_ptr info; + +protected: + UpdateExtensionsStatement(const UpdateExtensionsStatement &other); + +public: + string ToString() const override; + unique_ptr Copy() const override; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/parser/statement/vacuum_statement.hpp b/src/include/duckdb/parser/statement/vacuum_statement.hpp index f84fbff01bb..07b04d1cd21 100644 --- a/src/include/duckdb/parser/statement/vacuum_statement.hpp +++ b/src/include/duckdb/parser/statement/vacuum_statement.hpp @@ -28,6 +28,7 @@ class VacuumStatement : public SQLStatement { public: unique_ptr Copy() const override; + string ToString() const override; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/tableref.hpp b/src/include/duckdb/parser/tableref.hpp index 57a7e48548f..3c2efbedd77 100644 --- a/src/include/duckdb/parser/tableref.hpp +++ b/src/include/duckdb/parser/tableref.hpp @@ -12,6 +12,7 @@ #include "duckdb/common/optional_idx.hpp" #include "duckdb/common/enums/tableref_type.hpp" #include "duckdb/parser/parsed_data/sample_options.hpp" +#include "duckdb/main/external_dependencies.hpp" namespace duckdb { @@ -32,6 +33,10 @@ class TableRef { unique_ptr sample; //! The location in the query (if any) optional_idx query_location; + // External dependencies of this table function + shared_ptr external_dependency; + //! Aliases for the column names + vector column_name_alias; public: //! Convert the object to a string diff --git a/src/include/duckdb/parser/tableref/basetableref.hpp b/src/include/duckdb/parser/tableref/basetableref.hpp index 4401fb2830a..16bc1bb868b 100644 --- a/src/include/duckdb/parser/tableref/basetableref.hpp +++ b/src/include/duckdb/parser/tableref/basetableref.hpp @@ -28,8 +28,6 @@ class BaseTableRef : public TableRef { string schema_name; //! Table name string table_name; - //! Aliases for the column names - vector column_name_alias; public: string ToString() const override; diff --git a/src/include/duckdb/parser/tableref/column_data_ref.hpp b/src/include/duckdb/parser/tableref/column_data_ref.hpp new file mode 100644 index 00000000000..300ecf3db80 --- /dev/null +++ b/src/include/duckdb/parser/tableref/column_data_ref.hpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/tableref/column_data_ref.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/parser/tableref.hpp" +#include "duckdb/common/optionally_owned_ptr.hpp" +#include "duckdb/common/types/column/column_data_collection.hpp" + +namespace duckdb { +//! Represents a TableReference to a materialized result +class ColumnDataRef : public TableRef { +public: + static constexpr const TableReferenceType TYPE = TableReferenceType::COLUMN_DATA; + +public: + explicit ColumnDataRef(ColumnDataCollection &collection) + : TableRef(TableReferenceType::COLUMN_DATA), collection(collection) { + } + ColumnDataRef(vector expected_names, optionally_owned_ptr collection_p) + : TableRef(TableReferenceType::COLUMN_DATA), collection(std::move(collection_p)), + expected_names(std::move(expected_names)) { + } + +public: + //! (optionally owned) materialized column data + optionally_owned_ptr collection; + //! The set of expected names + vector expected_names; + +public: + string ToString() const override; + bool Equals(const TableRef &other_p) const override; + + unique_ptr Copy() override; + + //! Deserializes a blob back into a ColumnDataRef + void Serialize(Serializer &serializer) const override; + static unique_ptr Deserialize(Deserializer &source); +}; +} // namespace duckdb diff --git a/src/include/duckdb/parser/tableref/list.hpp b/src/include/duckdb/parser/tableref/list.hpp index c6606dfbc82..c84a82b5872 100644 --- a/src/include/duckdb/parser/tableref/list.hpp +++ b/src/include/duckdb/parser/tableref/list.hpp @@ -1,6 +1,7 @@ #include "duckdb/parser/tableref/basetableref.hpp" #include "duckdb/parser/tableref/emptytableref.hpp" #include "duckdb/parser/tableref/expressionlistref.hpp" +#include "duckdb/parser/tableref/column_data_ref.hpp" #include "duckdb/parser/tableref/joinref.hpp" #include "duckdb/parser/tableref/pivotref.hpp" #include "duckdb/parser/tableref/showref.hpp" diff --git a/src/include/duckdb/parser/tableref/pivotref.hpp b/src/include/duckdb/parser/tableref/pivotref.hpp index 0d521bede7f..ec19f5d6640 100644 --- a/src/include/duckdb/parser/tableref/pivotref.hpp +++ b/src/include/duckdb/parser/tableref/pivotref.hpp @@ -72,8 +72,6 @@ class PivotRef : public TableRef { vector pivots; //! The groups to pivot over. If none are specified all columns not included in the pivots/aggregate are chosen. vector groups; - //! Aliases for the column names - vector column_name_alias; //! Whether or not to include nulls in the result (UNPIVOT only) bool include_nulls; //! The set of values to pivot on (bound pivot only) diff --git a/src/include/duckdb/parser/tableref/subqueryref.hpp b/src/include/duckdb/parser/tableref/subqueryref.hpp index 5e562ced88f..f93b45ab35a 100644 --- a/src/include/duckdb/parser/tableref/subqueryref.hpp +++ b/src/include/duckdb/parser/tableref/subqueryref.hpp @@ -25,8 +25,6 @@ class SubqueryRef : public TableRef { //! The subquery unique_ptr subquery; - //! Aliases for the column names - vector column_name_alias; public: string ToString() const override; diff --git a/src/include/duckdb/parser/tableref/table_function_ref.hpp b/src/include/duckdb/parser/tableref/table_function_ref.hpp index 7d782ca0f61..51c4fd8e331 100644 --- a/src/include/duckdb/parser/tableref/table_function_ref.hpp +++ b/src/include/duckdb/parser/tableref/table_function_ref.hpp @@ -12,7 +12,6 @@ #include "duckdb/parser/tableref.hpp" #include "duckdb/common/vector.hpp" #include "duckdb/parser/statement/select_statement.hpp" -#include "duckdb/main/external_dependencies.hpp" namespace duckdb { //! Represents a Table producing function @@ -24,14 +23,10 @@ class TableFunctionRef : public TableRef { DUCKDB_API TableFunctionRef(); unique_ptr function; - vector column_name_alias; // if the function takes a subquery as argument its in here unique_ptr subquery; - // External dependencies of this table function - unique_ptr external_dependency; - public: string ToString() const override; diff --git a/src/include/duckdb/parser/tokens.hpp b/src/include/duckdb/parser/tokens.hpp index e9d3bb56ca7..f5eeb2c0ca9 100644 --- a/src/include/duckdb/parser/tokens.hpp +++ b/src/include/duckdb/parser/tokens.hpp @@ -28,6 +28,7 @@ class InsertStatement; class SelectStatement; class TransactionStatement; class UpdateStatement; +class UpdateExtensionsStatement; class PrepareStatement; class ExecuteStatement; class PragmaStatement; @@ -96,6 +97,7 @@ class SubqueryRef; class TableFunctionRef; class EmptyTableRef; class ExpressionListRef; +class ColumnDataRef; class PivotRef; class ShowRef; diff --git a/src/include/duckdb/parser/transformer.hpp b/src/include/duckdb/parser/transformer.hpp index 40ed90719a5..aa0daf31309 100644 --- a/src/include/duckdb/parser/transformer.hpp +++ b/src/include/duckdb/parser/transformer.hpp @@ -158,6 +158,8 @@ class Transformer { unique_ptr TransformDelete(duckdb_libpgquery::PGDeleteStmt &stmt); //! Transform a Postgres duckdb_libpgquery::T_PGUpdateStmt node into a UpdateStatement unique_ptr TransformUpdate(duckdb_libpgquery::PGUpdateStmt &stmt); + //! Transform a Postgres duckdb_libpgquery::T_PGUpdateExtensionsStmt node into a UpdateExtensionsStatement + unique_ptr TransformUpdateExtensions(duckdb_libpgquery::PGUpdateExtensionsStmt &stmt); //! Transform a Postgres duckdb_libpgquery::T_PGPragmaStmt node into a PragmaStatement unique_ptr TransformPragma(duckdb_libpgquery::PGPragmaStmt &stmt); //! Transform a Postgres duckdb_libpgquery::T_PGExportStmt node into a ExportStatement @@ -255,9 +257,8 @@ class Transformer { //===--------------------------------------------------------------------===// // Constraints transform //===--------------------------------------------------------------------===// - unique_ptr TransformConstraint(duckdb_libpgquery::PGListCell *cell); - - unique_ptr TransformConstraint(duckdb_libpgquery::PGListCell *cell, ColumnDefinition &column, + unique_ptr TransformConstraint(duckdb_libpgquery::PGListCell &cell); + unique_ptr TransformConstraint(duckdb_libpgquery::PGListCell &cell, ColumnDefinition &column, idx_t index); //===--------------------------------------------------------------------===// @@ -321,6 +322,9 @@ class Transformer { //! Transform a Postgres TypeName string into a LogicalType LogicalType TransformTypeName(duckdb_libpgquery::PGTypeName &name); + //! Transform a list of type modifiers into a list of values + vector TransformTypeModifiers(duckdb_libpgquery::PGTypeName &name); + //! Transform a Postgres GROUP BY expression into a list of Expression bool TransformGroupBy(optional_ptr group, SelectNode &result); void TransformGroupByNode(duckdb_libpgquery::PGNode &n, GroupingExpressionMap &map, SelectNode &result, diff --git a/src/include/duckdb/planner/binder.hpp b/src/include/duckdb/planner/binder.hpp index c2afbc1b8f5..3f58bae8415 100644 --- a/src/include/duckdb/planner/binder.hpp +++ b/src/include/duckdb/planner/binder.hpp @@ -55,7 +55,8 @@ struct BoundLimitNode; struct PivotColumnEntry; struct UnpivotEntry; -enum class BindingMode : uint8_t { STANDARD_BINDING, EXTRACT_NAMES }; +enum class BindingMode : uint8_t { STANDARD_BINDING, EXTRACT_NAMES, EXTRACT_REPLACEMENT_SCANS }; +enum class BinderType : uint8_t { REGULAR_BINDER, VIEW_BINDER }; struct CorrelatedColumnInfo { ColumnBinding binding; @@ -88,7 +89,7 @@ class Binder : public enable_shared_from_this { public: DUCKDB_API static shared_ptr CreateBinder(ClientContext &context, optional_ptr parent = nullptr, - bool inherit_ctes = true); + BinderType binder_type = BinderType::REGULAR_BINDER); //! The client context ClientContext &context; @@ -103,8 +104,6 @@ class Binder : public enable_shared_from_this { vector correlated_columns; //! The set of parameter expressions bound by this binder optional_ptr parameters; - //! Statement properties - StatementProperties properties; //! The alias for the currently processing subquery, if it exists string alias; //! Macro parameter bindings (if any) @@ -122,6 +121,8 @@ class Binder : public enable_shared_from_this { unique_ptr BindCreateTableInfo(unique_ptr info, SchemaCatalogEntry &schema); unique_ptr BindCreateTableInfo(unique_ptr info, SchemaCatalogEntry &schema, vector> &bound_defaults); + static unique_ptr BindCreateTableCheckpoint(unique_ptr info, + SchemaCatalogEntry &schema); static vector> BindConstraints(ClientContext &context, const vector> &constraints, const string &table_name, const ColumnList &columns); @@ -131,6 +132,7 @@ class Binder : public enable_shared_from_this { vector> BindNewConstraints(vector> &constraints, const string &table_name, const ColumnList &columns); + void SetCatalogLookupCallback(catalog_entry_callback_t callback); void BindCreateViewInfo(CreateViewInfo &base); SchemaCatalogEntry &BindSchema(CreateInfo &info); SchemaCatalogEntry &BindCreateFunctionInfo(CreateInfo &info); @@ -146,6 +148,10 @@ class Binder : public enable_shared_from_this { //! Generates an unused index for a table idx_t GenerateTableIndex(); + optional_ptr GetCatalogEntry(CatalogType type, const string &catalog, const string &schema, + const string &name, OnEntryNotFound on_entry_not_found, + QueryErrorContext &error_context); + //! Add a common table expression to the binder void AddCTE(const string &name, CommonTableExpressionInfo &cte); //! Find all candidate common table expression by name; returns empty vector if none exists @@ -178,8 +184,8 @@ class Binder : public enable_shared_from_this { void BindVacuumTable(LogicalVacuum &vacuum, unique_ptr &root); static void BindSchemaOrCatalog(ClientContext &context, string &catalog, string &schema); - static void BindLogicalType(ClientContext &context, LogicalType &type, optional_ptr catalog = nullptr, - const string &schema = INVALID_SCHEMA); + void BindLogicalType(LogicalType &type, optional_ptr catalog = nullptr, + const string &schema = INVALID_SCHEMA); bool HasMatchingBinding(const string &table_name, const string &column_name, ErrorData &error); bool HasMatchingBinding(const string &schema_name, const string &table_name, const string &column_name, @@ -190,7 +196,9 @@ class Binder : public enable_shared_from_this { void SetBindingMode(BindingMode mode); BindingMode GetBindingMode(); void AddTableName(string table_name); + void AddReplacementScan(const string &table_name, unique_ptr replacement); const unordered_set &GetTableNames(); + case_insensitive_map_t> &GetReplacementScans(); optional_ptr GetRootStatement() { return root_statement; } @@ -198,6 +206,8 @@ class Binder : public enable_shared_from_this { void SetCanContainNulls(bool can_contain_nulls); void SetAlwaysRequireRebind(); + StatementProperties &GetStatementProperties(); + private: //! The parent binder (if any) shared_ptr parent; @@ -209,8 +219,8 @@ class Binder : public enable_shared_from_this { bool has_unplanned_dependent_joins = false; //! Whether or not outside dependent joins have been planned and flattened bool is_outside_flattened = true; - //! Whether CTEs should reference the parent binder (if it exists) - bool inherit_ctes = true; + //! What kind of node we are binding using this binder + BinderType binder_type = BinderType::REGULAR_BINDER; //! Whether or not the binder can contain NULLs as the root of expressions bool can_contain_nulls = false; //! The root statement of the query that is currently being parsed @@ -219,10 +229,16 @@ class Binder : public enable_shared_from_this { BindingMode mode = BindingMode::STANDARD_BINDING; //! Table names extracted for BindingMode::EXTRACT_NAMES unordered_set table_names; + //! Replacement Scans extracted for BindingMode::EXTRACT_REPLACEMENT_SCANS + case_insensitive_map_t> replacement_scans; //! The set of bound views reference_set_t bound_views; + //! Used to retrieve CatalogEntry's + CatalogEntryRetriever entry_retriever; //! Unnamed subquery index idx_t unnamed_subquery_index = 1; + //! Statement properties + StatementProperties prop; private: //! Get the root binder (binder with no parent) @@ -248,7 +264,7 @@ class Binder : public enable_shared_from_this { BoundStatement BindWithCTE(T &statement); BoundStatement Bind(SelectStatement &stmt); BoundStatement Bind(InsertStatement &stmt); - BoundStatement Bind(CopyStatement &stmt); + BoundStatement Bind(CopyStatement &stmt, CopyToType copy_to_type); BoundStatement Bind(DeleteStatement &stmt); BoundStatement Bind(UpdateStatement &stmt); BoundStatement Bind(CreateStatement &stmt); @@ -272,6 +288,7 @@ class Binder : public enable_shared_from_this { BoundStatement Bind(AttachStatement &stmt); BoundStatement Bind(DetachStatement &stmt); BoundStatement Bind(CopyDatabaseStatement &stmt); + BoundStatement Bind(UpdateExtensionsStatement &stmt); BoundStatement BindReturning(vector> returning_list, TableCatalogEntry &table, const string &alias, idx_t update_table_index, @@ -302,6 +319,7 @@ class Binder : public enable_shared_from_this { unique_ptr Bind(TableFunctionRef &ref); unique_ptr Bind(EmptyTableRef &ref); unique_ptr Bind(ExpressionListRef &ref); + unique_ptr Bind(ColumnDataRef &ref); unique_ptr Bind(PivotRef &expr); unique_ptr Bind(ShowRef &ref); @@ -317,14 +335,14 @@ class Binder : public enable_shared_from_this { vector> &expressions, vector &arguments, vector ¶meters, named_parameter_map_t &named_parameters, unique_ptr &subquery, ErrorData &error); - bool BindTableInTableOutFunction(vector> &expressions, - unique_ptr &subquery, ErrorData &error); + void BindTableInTableOutFunction(vector> &expressions, + unique_ptr &subquery); unique_ptr BindTableFunction(TableFunction &function, vector parameters); - unique_ptr - BindTableFunctionInternal(TableFunction &table_function, const string &function_name, vector parameters, - named_parameter_map_t named_parameters, vector input_table_types, - vector input_table_names, const vector &column_name_alias, - unique_ptr external_dependency); + unique_ptr BindTableFunctionInternal(TableFunction &table_function, const TableFunctionRef &ref, + vector parameters, + named_parameter_map_t named_parameters, + vector input_table_types, + vector input_table_names); unique_ptr CreatePlan(BoundBaseTableRef &ref); unique_ptr CreatePlan(BoundJoinRef &ref); @@ -332,10 +350,11 @@ class Binder : public enable_shared_from_this { unique_ptr CreatePlan(BoundTableFunction &ref); unique_ptr CreatePlan(BoundEmptyTableRef &ref); unique_ptr CreatePlan(BoundExpressionListRef &ref); + unique_ptr CreatePlan(BoundColumnDataRef &ref); unique_ptr CreatePlan(BoundCTERef &ref); unique_ptr CreatePlan(BoundPivotRef &ref); - BoundStatement BindCopyTo(CopyStatement &stmt); + BoundStatement BindCopyTo(CopyStatement &stmt, CopyToType copy_to_type); BoundStatement BindCopyFrom(CopyStatement &stmt); void PrepareModifiers(OrderBinder &order_binder, QueryNode &statement, BoundQueryNode &result); @@ -372,6 +391,8 @@ class Binder : public enable_shared_from_this { vector> &new_select_list); void ExpandStarExpression(unique_ptr expr, vector> &new_select_list); bool FindStarExpression(unique_ptr &expr, StarExpression **star, bool is_root, bool in_columns); + void ReplaceUnpackedStarExpression(unique_ptr &expr, + vector> &replacements); void ReplaceStarExpression(unique_ptr &expr, unique_ptr &replacement); void BindWhereStarExpression(unique_ptr &expr); @@ -392,7 +413,7 @@ class Binder : public enable_shared_from_this { public: // This should really be a private constructor, but make_shared_ptr does not allow it... // If you are thinking about calling this, you should probably call Binder::CreateBinder - Binder(bool i_know_what_i_am_doing, ClientContext &context, shared_ptr parent, bool inherit_ctes); + Binder(bool i_know_what_i_am_doing, ClientContext &context, shared_ptr parent, BinderType binder_type); }; } // namespace duckdb diff --git a/src/include/duckdb/planner/bound_tokens.hpp b/src/include/duckdb/planner/bound_tokens.hpp index b864b25a634..97800348801 100644 --- a/src/include/duckdb/planner/bound_tokens.hpp +++ b/src/include/duckdb/planner/bound_tokens.hpp @@ -52,6 +52,7 @@ class BoundSubqueryRef; class BoundTableFunction; class BoundEmptyTableRef; class BoundExpressionListRef; +class BoundColumnDataRef; class BoundCTERef; class BoundPivotRef; diff --git a/src/include/duckdb/planner/collation_binding.hpp b/src/include/duckdb/planner/collation_binding.hpp new file mode 100644 index 00000000000..f9f86d69dc6 --- /dev/null +++ b/src/include/duckdb/planner/collation_binding.hpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/collation_binding.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/function/cast/default_casts.hpp" + +namespace duckdb { +struct MapCastInfo; +struct MapCastNode; +struct DBConfig; + +typedef bool (*try_push_collation_t)(ClientContext &context, unique_ptr &source, + const LogicalType &sql_type); + +struct CollationCallback { + explicit CollationCallback(try_push_collation_t try_push_collation_p) : try_push_collation(try_push_collation_p) { + } + + try_push_collation_t try_push_collation; +}; + +class CollationBinding { +public: + CollationBinding(); + +public: + DUCKDB_API static CollationBinding &Get(ClientContext &context); + DUCKDB_API static CollationBinding &Get(DatabaseInstance &db); + + DUCKDB_API void RegisterCollation(CollationCallback callback); + DUCKDB_API bool PushCollation(ClientContext &context, unique_ptr &source, + const LogicalType &sql_type) const; + +private: + vector collations; +}; + +} // namespace duckdb diff --git a/src/include/duckdb/planner/expression_binder.hpp b/src/include/duckdb/planner/expression_binder.hpp index 2f43ab0a927..6009575a142 100644 --- a/src/include/duckdb/planner/expression_binder.hpp +++ b/src/include/duckdb/planner/expression_binder.hpp @@ -18,6 +18,7 @@ #include "duckdb/parser/parsed_expression.hpp" #include "duckdb/parser/tokens.hpp" #include "duckdb/planner/expression.hpp" +#include "duckdb/catalog/catalog_entry_retriever.hpp" #include "duckdb/planner/expression/bound_lambda_expression.hpp" #include "duckdb/function/scalar_function.hpp" @@ -90,6 +91,7 @@ class ExpressionBinder { return bound_columns; } + void SetCatalogLookupCallback(catalog_entry_callback_t callback); ErrorData Bind(unique_ptr &expr, idx_t depth, bool root_expression = false); //! Returns the STRUCT_EXTRACT operator expression @@ -114,8 +116,7 @@ class ExpressionBinder { //! Entry point for qualifying the column references of the expression static void QualifyColumnNames(Binder &binder, unique_ptr &expr); - static bool PushCollation(ClientContext &context, unique_ptr &source, const LogicalType &sql_type, - bool equality_only = false); + static bool PushCollation(ClientContext &context, unique_ptr &source, const LogicalType &sql_type); static void TestCollation(ClientContext &context, const string &collation); BindResult BindCorrelatedColumns(unique_ptr &expr, ErrorData error_message); @@ -135,10 +136,19 @@ class ExpressionBinder { virtual BindResult BindExpression(unique_ptr &expr_ptr, idx_t depth, bool root_expression = false); - //! Recursively replaces macro parameters with the provided input parameters + //! FIXME: Generalise this for extensibility. + //! Recursively replaces macro parameters with the provided input parameters. void ReplaceMacroParameters(unique_ptr &expr, vector> &lambda_params); - //! Enables special-handling of lambda parameters by tracking them in the lambda_params vector + //! Enables special-handling of lambda parameters during macro replacement by tracking them in the lambda_params + //! vector. void ReplaceMacroParametersInLambda(FunctionExpression &function, vector> &lambda_params); + //! Recursively qualifies column references in ON CONFLICT DO UPDATE SET expressions. + void DoUpdateSetQualify(unique_ptr &expr, const string &table_name, + vector> &lambda_params); + //! Enables special-handling of lambda parameters during ON CONFLICT TO UPDATE SET qualification by tracking them in + //! the lambda_params vector. + void DoUpdateSetQualifyInLambda(FunctionExpression &function, const string &table_name, + vector> &lambda_params); static LogicalType GetExpressionReturnType(const Expression &expr); @@ -194,6 +204,9 @@ class ExpressionBinder { virtual string UnsupportedAggregateMessage(); virtual string UnsupportedUnnestMessage(); + optional_ptr GetCatalogEntry(CatalogType type, const string &catalog, const string &schema, + const string &name, OnEntryNotFound on_entry_not_found, + QueryErrorContext &error_context); Binder &binder; ClientContext &context; @@ -202,9 +215,6 @@ class ExpressionBinder { //! Returns true if the function name is an alias for the UNNEST function static bool IsUnnestFunction(const string &function_name); - //! Returns true, if the function contains a lambda expression and is not the '->>' operator - static bool IsLambdaFunction(const FunctionExpression &function); - //! Returns the bind result of binding a lambda or JSON function BindResult TryBindLambdaOrJson(FunctionExpression &function, idx_t depth, CatalogEntry &func); }; diff --git a/src/include/duckdb/planner/expression_binder/alter_binder.hpp b/src/include/duckdb/planner/expression_binder/alter_binder.hpp index 2633a0923ff..dd77e2b0fcc 100644 --- a/src/include/duckdb/planner/expression_binder/alter_binder.hpp +++ b/src/include/duckdb/planner/expression_binder/alter_binder.hpp @@ -14,22 +14,23 @@ namespace duckdb { class TableCatalogEntry; -//! The ALTER binder is responsible for binding an expression within alter statements +//! The AlterBinder binds expressions in ALTER statements. class AlterBinder : public ExpressionBinder { public: AlterBinder(Binder &binder, ClientContext &context, TableCatalogEntry &table, vector &bound_columns, LogicalType target_type); - TableCatalogEntry &table; - vector &bound_columns; - protected: + BindResult BindLambdaReference(LambdaRefExpression &expr, idx_t depth); + BindResult BindColumnReference(ColumnRefExpression &expr, idx_t depth); BindResult BindExpression(unique_ptr &expr_ptr, idx_t depth, bool root_expression = false) override; - BindResult BindColumn(ColumnRefExpression &expr); - string UnsupportedAggregateMessage() override; + +private: + TableCatalogEntry &table; + vector &bound_columns; }; } // namespace duckdb diff --git a/src/include/duckdb/planner/expression_binder/having_binder.hpp b/src/include/duckdb/planner/expression_binder/having_binder.hpp index 919779fc2dc..4cb65dab041 100644 --- a/src/include/duckdb/planner/expression_binder/having_binder.hpp +++ b/src/include/duckdb/planner/expression_binder/having_binder.hpp @@ -14,13 +14,14 @@ namespace duckdb { -//! The HAVING binder is responsible for binding an expression within the HAVING clause of a SQL statement +//! The HAVING binder is responsible for binding an expression within the HAVING clause of a SQL statement. class HavingBinder : public BaseSelectBinder { public: HavingBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info, AggregateHandling aggregate_handling); protected: + BindResult BindLambdaReference(LambdaRefExpression &expr, idx_t depth); BindResult BindWindow(WindowExpression &expr, idx_t depth) override; BindResult BindColumnRef(unique_ptr &expr_ptr, idx_t depth, bool root_expression) override; diff --git a/src/include/duckdb/planner/expression_binder/index_binder.hpp b/src/include/duckdb/planner/expression_binder/index_binder.hpp index 4f7f55173c9..0d2ac67f061 100644 --- a/src/include/duckdb/planner/expression_binder/index_binder.hpp +++ b/src/include/duckdb/planner/expression_binder/index_binder.hpp @@ -12,17 +12,21 @@ #include "duckdb/common/unordered_map.hpp" #include "duckdb/parser/parsed_data/create_index_info.hpp" #include "duckdb/planner/expression_binder.hpp" +#include "duckdb/execution/index/bound_index.hpp" +#include "duckdb/execution/index/unbound_index.hpp" namespace duckdb { class BoundColumnRefExpression; -//! The IndexBinder is responsible for binding an expression within an index statement +//! The IndexBinder is responsible for binding indexes, as well as expressions within an index statement class IndexBinder : public ExpressionBinder { public: IndexBinder(Binder &binder, ClientContext &context, optional_ptr table = nullptr, optional_ptr info = nullptr); + unique_ptr BindIndex(const UnboundIndex &index); + protected: BindResult BindExpression(unique_ptr &expr_ptr, idx_t depth, bool root_expression = false) override; diff --git a/src/include/duckdb/planner/logical_operator.hpp b/src/include/duckdb/planner/logical_operator.hpp index 98aa0fd641f..dcb9cb2e4ce 100644 --- a/src/include/duckdb/planner/logical_operator.hpp +++ b/src/include/duckdb/planner/logical_operator.hpp @@ -11,7 +11,6 @@ #include "duckdb/catalog/catalog.hpp" #include "duckdb/common/common.hpp" #include "duckdb/common/enums/logical_operator_type.hpp" -#include "duckdb/optimizer/join_order/estimated_properties.hpp" #include "duckdb/planner/column_binding.hpp" #include "duckdb/planner/expression.hpp" #include "duckdb/planner/logical_operator_visitor.hpp" diff --git a/src/include/duckdb/planner/logical_operator_visitor.hpp b/src/include/duckdb/planner/logical_operator_visitor.hpp index feb8ca7e1c3..ff0fd75def3 100644 --- a/src/include/duckdb/planner/logical_operator_visitor.hpp +++ b/src/include/duckdb/planner/logical_operator_visitor.hpp @@ -19,7 +19,8 @@ namespace duckdb { //! Visitor pattern on LogicalOperator. class LogicalOperatorVisitor { public: - virtual ~LogicalOperatorVisitor() {}; + virtual ~LogicalOperatorVisitor() { + } virtual void VisitOperator(LogicalOperator &op); virtual void VisitExpression(unique_ptr *expression); diff --git a/src/include/duckdb/planner/operator/logical_column_data_get.hpp b/src/include/duckdb/planner/operator/logical_column_data_get.hpp index 55c09970a28..6d27b679e4e 100644 --- a/src/include/duckdb/planner/operator/logical_column_data_get.hpp +++ b/src/include/duckdb/planner/operator/logical_column_data_get.hpp @@ -10,6 +10,7 @@ #include "duckdb/common/types/column/column_data_collection.hpp" #include "duckdb/planner/logical_operator.hpp" +#include "duckdb/common/optionally_owned_ptr.hpp" namespace duckdb { @@ -20,13 +21,16 @@ class LogicalColumnDataGet : public LogicalOperator { public: LogicalColumnDataGet(idx_t table_index, vector types, unique_ptr collection); + LogicalColumnDataGet(idx_t table_index, vector types, ColumnDataCollection &to_scan); + LogicalColumnDataGet(idx_t table_index, vector types, + optionally_owned_ptr to_scan); //! The table index in the current bind context idx_t table_index; //! The types of the chunk vector chunk_types; - //! The chunk collection to scan - unique_ptr collection; + //! (optionally owned) column data collection + optionally_owned_ptr collection; public: vector GetColumnBindings() override; diff --git a/src/include/duckdb/planner/operator/logical_comparison_join.hpp b/src/include/duckdb/planner/operator/logical_comparison_join.hpp index 4cb62ca332f..8731730c3a4 100644 --- a/src/include/duckdb/planner/operator/logical_comparison_join.hpp +++ b/src/include/duckdb/planner/operator/logical_comparison_join.hpp @@ -51,16 +51,16 @@ class LogicalComparisonJoin : public LogicalJoin { vector conditions, vector> arbitrary_expressions); - static void ExtractJoinConditions(ClientContext &context, JoinType type, unique_ptr &left_child, - unique_ptr &right_child, unique_ptr condition, - vector &conditions, + static void ExtractJoinConditions(ClientContext &context, JoinType type, JoinRefType ref_type, + unique_ptr &left_child, unique_ptr &right_child, + unique_ptr condition, vector &conditions, vector> &arbitrary_expressions); - static void ExtractJoinConditions(ClientContext &context, JoinType type, unique_ptr &left_child, - unique_ptr &right_child, + static void ExtractJoinConditions(ClientContext &context, JoinType type, JoinRefType ref_type, + unique_ptr &left_child, unique_ptr &right_child, vector> &expressions, vector &conditions, vector> &arbitrary_expressions); - static void ExtractJoinConditions(ClientContext &context, JoinType type, unique_ptr &left_child, - unique_ptr &right_child, + static void ExtractJoinConditions(ClientContext &context, JoinType type, JoinRefType ref_type, + unique_ptr &left_child, unique_ptr &right_child, const unordered_set &left_bindings, const unordered_set &right_bindings, vector> &expressions, vector &conditions, diff --git a/src/include/duckdb/planner/operator/logical_copy_to_file.hpp b/src/include/duckdb/planner/operator/logical_copy_to_file.hpp index ea79b940765..3c4a791d387 100644 --- a/src/include/duckdb/planner/operator/logical_copy_to_file.hpp +++ b/src/include/duckdb/planner/operator/logical_copy_to_file.hpp @@ -8,6 +8,7 @@ #pragma once +#include "duckdb/common/enums/copy_overwrite_mode.hpp" #include "duckdb/common/filename_pattern.hpp" #include "duckdb/common/local_file_system.hpp" #include "duckdb/common/optional_idx.hpp" @@ -33,9 +34,11 @@ class LogicalCopyToFile : public LogicalOperator { bool use_tmp_file; FilenamePattern filename_pattern; string file_extension; - bool overwrite_or_ignore; + CopyOverwriteMode overwrite_mode; bool per_thread_output; optional_idx file_size_bytes; + bool rotate; + CopyFunctionReturnType return_type; bool partition_output; vector partition_columns; @@ -43,13 +46,14 @@ class LogicalCopyToFile : public LogicalOperator { vector expected_types; public: + vector GetColumnBindings() override; idx_t EstimateCardinality(ClientContext &context) override; void Serialize(Serializer &serializer) const override; static unique_ptr Deserialize(Deserializer &deserializer); protected: void ResolveTypes() override { - types.emplace_back(LogicalType::BIGINT); + types = GetCopyFunctionReturnLogicalTypes(return_type); } }; } // namespace duckdb diff --git a/src/include/duckdb/planner/operator/logical_execute.hpp b/src/include/duckdb/planner/operator/logical_execute.hpp index 62eb28f2e7f..0c6eff24c80 100644 --- a/src/include/duckdb/planner/operator/logical_execute.hpp +++ b/src/include/duckdb/planner/operator/logical_execute.hpp @@ -34,7 +34,7 @@ class LogicalExecute : public LogicalOperator { protected: void ResolveTypes() override { - // already resolved + types = prepared->types; } vector GetColumnBindings() override { return GenerateColumnBindings(0, types.size()); diff --git a/src/include/duckdb/planner/operator/logical_export.hpp b/src/include/duckdb/planner/operator/logical_export.hpp index 9303a2f59fd..28a3686f378 100644 --- a/src/include/duckdb/planner/operator/logical_export.hpp +++ b/src/include/duckdb/planner/operator/logical_export.hpp @@ -28,6 +28,13 @@ class LogicalExport : public LogicalOperator { unique_ptr copy_info; BoundExportData exported_tables; + void Serialize(Serializer &serializer) const override { + throw NotImplementedException("FIXME: Serialize LogicalExport statement"); + } + unique_ptr Deserialize(Deserializer &deserializer) { + throw NotImplementedException("FIXME: Deserialize LogicalExport statement"); + } + public: protected: void ResolveTypes() override { diff --git a/src/include/duckdb/planner/table_binding.hpp b/src/include/duckdb/planner/table_binding.hpp index aa288a12b00..551ab9b00f5 100644 --- a/src/include/duckdb/planner/table_binding.hpp +++ b/src/include/duckdb/planner/table_binding.hpp @@ -133,12 +133,12 @@ struct DummyBinding : public Binding { public: //! Binding macros - BindResult Bind(ColumnRefExpression &colref, idx_t depth) override; + BindResult Bind(ColumnRefExpression &col_ref, idx_t depth) override; //! Binding lambdas - BindResult Bind(LambdaRefExpression &lambdaref, idx_t depth); + BindResult Bind(LambdaRefExpression &lambda_ref, idx_t depth); - //! Given the parameter colref, returns a copy of the argument that was supplied for this parameter - unique_ptr ParamToArg(ColumnRefExpression &colref); + //! Returns a copy of the col_ref parameter as a parsed expression + unique_ptr ParamToArg(ColumnRefExpression &col_ref); }; } // namespace duckdb diff --git a/src/include/duckdb/planner/tableref/bound_column_data_ref.hpp b/src/include/duckdb/planner/tableref/bound_column_data_ref.hpp new file mode 100644 index 00000000000..025bc47127b --- /dev/null +++ b/src/include/duckdb/planner/tableref/bound_column_data_ref.hpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/tableref/bound_column_data_ref.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/planner/bound_tableref.hpp" +#include "duckdb/common/optionally_owned_ptr.hpp" +#include "duckdb/common/types/column/column_data_collection.hpp" + +namespace duckdb { +//! Represents a TableReference to a base table in the schema +class BoundColumnDataRef : public BoundTableRef { +public: + static constexpr const TableReferenceType TYPE = TableReferenceType::COLUMN_DATA; + +public: + explicit BoundColumnDataRef(optionally_owned_ptr collection) + : BoundTableRef(TableReferenceType::COLUMN_DATA), collection(std::move(collection)) { + } + //! The (optionally owned) materialized column data to scan + optionally_owned_ptr collection; + //! The index in the bind context + idx_t bind_index; +}; +} // namespace duckdb diff --git a/src/include/duckdb/planner/tableref/bound_joinref.hpp b/src/include/duckdb/planner/tableref/bound_joinref.hpp index 9500a34835a..a066604a569 100644 --- a/src/include/duckdb/planner/tableref/bound_joinref.hpp +++ b/src/include/duckdb/planner/tableref/bound_joinref.hpp @@ -44,5 +44,7 @@ class BoundJoinRef : public BoundTableRef { bool lateral; //! The correlated columns of the right-side with the left-side vector correlated_columns; + //! The mark index, for mark joins generated by the relational API + idx_t mark_index {}; }; } // namespace duckdb diff --git a/src/include/duckdb/planner/tableref/bound_subqueryref.hpp b/src/include/duckdb/planner/tableref/bound_subqueryref.hpp index fccd21b0b1b..2d1061c98f5 100644 --- a/src/include/duckdb/planner/tableref/bound_subqueryref.hpp +++ b/src/include/duckdb/planner/tableref/bound_subqueryref.hpp @@ -26,7 +26,7 @@ class BoundSubqueryRef : public BoundTableRef { //! The binder used to bind the subquery shared_ptr binder; - //! The bound subquery node + //! The bound subquery node (if any) unique_ptr subquery; }; } // namespace duckdb diff --git a/src/include/duckdb/planner/tableref/bound_table_function.hpp b/src/include/duckdb/planner/tableref/bound_table_function.hpp index 58d61b19577..6aafe2b36b3 100644 --- a/src/include/duckdb/planner/tableref/bound_table_function.hpp +++ b/src/include/duckdb/planner/tableref/bound_table_function.hpp @@ -10,6 +10,7 @@ #include "duckdb/planner/bound_tableref.hpp" #include "duckdb/planner/logical_operator.hpp" +#include "duckdb/planner/tableref/bound_subqueryref.hpp" namespace duckdb { @@ -24,6 +25,7 @@ class BoundTableFunction : public BoundTableRef { } unique_ptr get; + unique_ptr subquery; }; } // namespace duckdb diff --git a/src/include/duckdb/planner/tableref/list.hpp b/src/include/duckdb/planner/tableref/list.hpp index 1452daaf479..f1c614c408a 100644 --- a/src/include/duckdb/planner/tableref/list.hpp +++ b/src/include/duckdb/planner/tableref/list.hpp @@ -4,5 +4,6 @@ #include "duckdb/planner/tableref/bound_expressionlistref.hpp" #include "duckdb/planner/tableref/bound_joinref.hpp" #include "duckdb/planner/tableref/bound_subqueryref.hpp" +#include "duckdb/planner/tableref/bound_column_data_ref.hpp" #include "duckdb/planner/tableref/bound_table_function.hpp" #include "duckdb/planner/tableref/bound_pivotref.hpp" diff --git a/src/include/duckdb/storage/block.hpp b/src/include/duckdb/storage/block.hpp index b12bab29fe5..cf52c61d41a 100644 --- a/src/include/duckdb/storage/block.hpp +++ b/src/include/duckdb/storage/block.hpp @@ -9,8 +9,8 @@ #pragma once #include "duckdb/common/common.hpp" -#include "duckdb/storage/storage_info.hpp" #include "duckdb/common/file_buffer.hpp" +#include "duckdb/storage/storage_info.hpp" namespace duckdb { @@ -19,7 +19,7 @@ class Deserializer; class Block : public FileBuffer { public: - Block(Allocator &allocator, block_id_t id); + Block(Allocator &allocator, const block_id_t id, const idx_t block_size); Block(Allocator &allocator, block_id_t id, uint32_t internal_size); Block(FileBuffer &source, block_id_t id); diff --git a/src/include/duckdb/storage/block_manager.hpp b/src/include/duckdb/storage/block_manager.hpp index dca511b5528..0903b8df7e0 100644 --- a/src/include/duckdb/storage/block_manager.hpp +++ b/src/include/duckdb/storage/block_manager.hpp @@ -10,6 +10,7 @@ #include "duckdb/common/common.hpp" #include "duckdb/common/mutex.hpp" +#include "duckdb/common/optional_idx.hpp" #include "duckdb/storage/block.hpp" #include "duckdb/storage/storage_info.hpp" #include "duckdb/common/unordered_map.hpp" @@ -22,10 +23,11 @@ class DatabaseInstance; class MetadataManager; //! BlockManager is an abstract representation to manage blocks on DuckDB. When writing or reading blocks, the -//! BlockManager creates and accesses blocks. The concrete types implements how blocks are stored. +//! BlockManager creates and accesses blocks. The concrete types implement specific block storage strategies. class BlockManager { public: - explicit BlockManager(BufferManager &buffer_manager); + BlockManager() = delete; + BlockManager(BufferManager &buffer_manager, const optional_idx block_alloc_size_p); virtual ~BlockManager() = default; //! The buffer manager @@ -37,6 +39,7 @@ class BlockManager { virtual unique_ptr CreateBlock(block_id_t block_id, FileBuffer *source_buffer) = 0; //! Return the next free block id virtual block_id_t GetFreeBlockId() = 0; + virtual block_id_t PeekFreeBlockId() = 0; //! Returns whether or not a specified block is the root block virtual bool IsRootBlock(MetaBlockPointer root) = 0; //! Mark a block as "free"; free blocks are immediately added to the free list and can be immediately overwritten @@ -51,6 +54,8 @@ class BlockManager { virtual idx_t GetMetaBlock() = 0; //! Read the content of the block from disk virtual void Read(Block &block) = 0; + //! Read the content of the block from disk + virtual void ReadBlocks(FileBuffer &buffer, block_id_t start_block, idx_t block_count) = 0; //! Writes the block to disk virtual void Write(FileBuffer &block, block_id_t block_id) = 0; //! Writes the block to disk @@ -64,6 +69,12 @@ class BlockManager { virtual idx_t TotalBlocks() = 0; //! Returns the number of free blocks virtual idx_t FreeBlocks() = 0; + //! Whether or not the attached database is a remote file (e.g. attached over s3/https) + virtual bool IsRemote() { + return false; + } + //! Whether or not the attached database is in-memory + virtual bool InMemory() = 0; //! Truncate the underlying database file after a checkpoint virtual void Truncate(); @@ -75,7 +86,29 @@ class BlockManager { void UnregisterBlock(block_id_t block_id, bool can_destroy); + //! Returns a reference to the metadata manager of this block manager. MetadataManager &GetMetadataManager(); + //! Returns the block allocation size of this block manager. + inline idx_t GetBlockAllocSize() const { + return block_alloc_size.GetIndex(); + } + //! Returns the possibly invalid block allocation size of this block manager. + inline optional_idx GetOptionalBlockAllocSize() const { + return block_alloc_size; + } + //! Returns the block size of this block manager. + inline idx_t GetBlockSize() const { + return block_alloc_size.GetIndex() - Storage::BLOCK_HEADER_SIZE; + } + //! Sets the block allocation size. This should only happen when initializing an existing database. + //! When initializing an existing database, we construct the block manager before reading the file header, + //! which contains the file's actual block allocation size. + void SetBlockAllocSize(const optional_idx block_alloc_size_p) { + if (block_alloc_size.IsValid()) { + throw InternalException("the block allocation size must be set once"); + } + block_alloc_size = block_alloc_size_p.GetIndex(); + } private: //! The lock for the set of blocks @@ -84,5 +117,9 @@ class BlockManager { unordered_map> blocks; //! The metadata manager unique_ptr metadata_manager; + //! The allocation size of blocks managed by this block manager. Defaults to DEFAULT_BLOCK_ALLOC_SIZE + //! for in-memory block managers. Default to default_block_alloc_size for file-backed block managers. + //! This is NOT the actual memory available on a block (block_size). + optional_idx block_alloc_size; }; } // namespace duckdb diff --git a/src/include/duckdb/storage/buffer/block_handle.hpp b/src/include/duckdb/storage/buffer/block_handle.hpp index 34ac9d1c4b7..ab083a12ee5 100644 --- a/src/include/duckdb/storage/buffer/block_handle.hpp +++ b/src/include/duckdb/storage/buffer/block_handle.hpp @@ -59,6 +59,7 @@ class BlockHandle { friend class BufferManager; friend class StandardBufferManager; friend class BufferPool; + friend struct EvictionQueue; public: BlockHandle(BlockManager &block_manager, block_id_t block_id, MemoryTag tag); @@ -106,6 +107,8 @@ class BlockHandle { private: static BufferHandle Load(shared_ptr &handle, unique_ptr buffer = nullptr); + static BufferHandle LoadFromBuffer(shared_ptr &handle, data_ptr_t data, + unique_ptr reusable_buffer); unique_ptr UnloadAndTakeBlock(); void Unload(); bool CanUnload(); @@ -122,8 +125,10 @@ class BlockHandle { MemoryTag tag; //! Pointer to loaded data (if any) unique_ptr buffer; - //! Internal eviction timestamp - atomic eviction_timestamp; + //! Internal eviction sequence number + atomic eviction_seq_num; + //! LRU timestamp (for age-based eviction) + atomic lru_timestamp_msec; //! Whether or not the buffer can be destroyed (only used for temporary buffers) bool can_destroy; //! The memory usage of the block (when loaded). If we are pinning/loading diff --git a/src/include/duckdb/storage/buffer/buffer_pool.hpp b/src/include/duckdb/storage/buffer/buffer_pool.hpp index 57762b63d55..b5a0c78b1cd 100644 --- a/src/include/duckdb/storage/buffer/buffer_pool.hpp +++ b/src/include/duckdb/storage/buffer/buffer_pool.hpp @@ -20,13 +20,10 @@ struct EvictionQueue; struct BufferEvictionNode { BufferEvictionNode() { } - BufferEvictionNode(weak_ptr handle_p, idx_t timestamp_p) - : handle(std::move(handle_p)), timestamp(timestamp_p) { - D_ASSERT(!handle.expired()); - } + BufferEvictionNode(weak_ptr handle_p, idx_t eviction_seq_num); weak_ptr handle; - idx_t timestamp; + idx_t handle_sequence_number; bool CanUnload(BlockHandle &handle_p); shared_ptr TryGetBlockHandle(); @@ -41,7 +38,7 @@ class BufferPool { friend class StandardBufferManager; public: - explicit BufferPool(idx_t maximum_memory); + explicit BufferPool(idx_t maximum_memory, bool track_eviction_timestamps); virtual ~BufferPool(); //! Set a new memory limit to the buffer pool, throws an exception if the new limit is too low and not enough @@ -71,25 +68,21 @@ class BufferPool { }; virtual EvictionResult EvictBlocks(MemoryTag tag, idx_t extra_memory, idx_t memory_limit, unique_ptr *buffer = nullptr); + virtual EvictionResult EvictBlocksInternal(EvictionQueue &queue, MemoryTag tag, idx_t extra_memory, + idx_t memory_limit, unique_ptr *buffer = nullptr); - //! Tries to dequeue an element from the eviction queue, but only after acquiring the purge queue lock. - bool TryDequeueWithLock(BufferEvictionNode &node); - //! Bulk purge dead nodes from the eviction queue. Then, enqueue those that are still alive. - void PurgeIteration(const idx_t purge_size); + //! Purge all blocks that haven't been pinned within the last N seconds + idx_t PurgeAgedBlocks(uint32_t max_age_sec); + idx_t PurgeAgedBlocksInternal(EvictionQueue &queue, uint32_t max_age_sec, int64_t now, int64_t limit); //! Garbage collect dead nodes in the eviction queue. - void PurgeQueue(); + void PurgeQueue(FileBufferType type); //! Add a buffer handle to the eviction queue. Returns true, if the queue is //! ready to be purged, and false otherwise. bool AddToEvictionQueue(shared_ptr &handle); - - //! Increment the dead node counter in the purge queue. - inline void IncrementDeadNodes() { - total_dead_nodes++; - } - //! Decrement the dead node counter in the purge queue. - inline void DecrementDeadNodes() { - total_dead_nodes--; - } + //! Gets the eviction queue for the specified type + EvictionQueue &GetEvictionQueueForType(FileBufferType type); + //! Increments the dead nodes for the queue with specified type + void IncrementDeadNodes(FileBufferType type); protected: //! The lock for changing the memory limit @@ -98,35 +91,14 @@ class BufferPool { atomic current_memory; //! The maximum amount of memory that the buffer manager can keep (in bytes) atomic maximum_memory; - //! Eviction queue - unique_ptr queue; + //! Record timestamps of buffer manager unpin() events. Usable by custom eviction policies. + bool track_eviction_timestamps; + //! Eviction queues + vector> queues; //! Memory manager for concurrently used temporary memory, e.g., for physical operators unique_ptr temporary_memory_manager; //! Memory usage per tag atomic memory_usage_per_tag[MEMORY_TAG_COUNT]; - - //! We trigger a purge of the eviction queue every INSERT_INTERVAL insertions - constexpr static idx_t INSERT_INTERVAL = 4096; - //! We multiply the base purge size by this value. - constexpr static idx_t PURGE_SIZE_MULTIPLIER = 2; - //! We multiply the purge size by this value to determine early-outs. This is the minimum queue size. - //! We never purge below this point. - constexpr static idx_t EARLY_OUT_MULTIPLIER = 4; - //! We multiply the approximate alive nodes by this value to test whether our total dead nodes - //! exceed their allowed ratio. Must be greater than 1. - constexpr static idx_t ALIVE_NODE_MULTIPLIER = 4; - - //! Total number of insertions into the eviction queue. This guides the schedule for calling PurgeQueue. - atomic evict_queue_insertions; - //! Total dead nodes in the eviction queue. There are two scenarios in which a node dies: (1) we destroy its block - //! handle, or (2) we insert a newer version into the eviction queue. - atomic total_dead_nodes; - //! Locked, if a queue purge is currently active or we're trying to forcefully evict a node. - //! Only lets a single thread enter the purge phase. - mutex purge_lock; - - //! A pre-allocated vector of eviction nodes. We reuse this to keep the allocation overhead of purges small. - vector purge_nodes; }; } // namespace duckdb diff --git a/src/include/duckdb/storage/buffer_manager.hpp b/src/include/duckdb/storage/buffer_manager.hpp index b0598f0c22e..2d74bd12392 100644 --- a/src/include/duckdb/storage/buffer_manager.hpp +++ b/src/include/duckdb/storage/buffer_manager.hpp @@ -39,6 +39,8 @@ class BufferManager { //! Reallocate an in-memory buffer that is pinned. virtual void ReAllocate(shared_ptr &handle, idx_t block_size) = 0; virtual BufferHandle Pin(shared_ptr &handle) = 0; + //! Prefetch a series of blocks. Note that this is a performance suggestion. + virtual void Prefetch(vector> &handles) = 0; virtual void Unpin(shared_ptr &handle) = 0; //! Returns the currently allocated memory @@ -50,8 +52,11 @@ class BufferManager { //! Returns the maximum swap space that can be used virtual optional_idx GetMaxSwap() const = 0; - //! Returns a new block of memory that is smaller than Storage::BLOCK_SIZE - virtual shared_ptr RegisterSmallMemory(idx_t block_size); + //! Returns a new block of transient memory. + virtual shared_ptr RegisterTransientMemory(const idx_t size); + //! Returns a new block of memory that is smaller than the block size setting. + virtual shared_ptr RegisterSmallMemory(const idx_t size); + virtual DUCKDB_API Allocator &GetBufferAllocator(); virtual DUCKDB_API void ReserveMemory(idx_t size); virtual DUCKDB_API void FreeReservedMemory(idx_t size); @@ -90,7 +95,7 @@ class BufferManager { virtual TemporaryMemoryManager &GetTemporaryMemoryManager(); protected: - virtual void PurgeQueue() = 0; + virtual void PurgeQueue(FileBufferType type) = 0; virtual void AddToEvictionQueue(shared_ptr &handle); virtual void WriteTemporaryBuffer(MemoryTag tag, block_id_t block_id, FileBuffer &buffer); virtual unique_ptr ReadTemporaryBuffer(MemoryTag tag, block_id_t id, unique_ptr buffer); diff --git a/src/include/duckdb/storage/checkpoint/row_group_writer.hpp b/src/include/duckdb/storage/checkpoint/row_group_writer.hpp index 2c5f78e9f2f..191a93854e5 100644 --- a/src/include/duckdb/storage/checkpoint/row_group_writer.hpp +++ b/src/include/duckdb/storage/checkpoint/row_group_writer.hpp @@ -32,6 +32,7 @@ class RowGroupWriter { virtual void WriteColumnDataPointers(ColumnCheckpointState &column_checkpoint_state, Serializer &serializer) = 0; + virtual CheckpointType GetCheckpointType() const = 0; virtual MetadataWriter &GetPayloadWriter() = 0; PartialBlockManager &GetPartialBlockManager() { @@ -47,18 +48,20 @@ class RowGroupWriter { class SingleFileRowGroupWriter : public RowGroupWriter { public: SingleFileRowGroupWriter(TableCatalogEntry &table, PartialBlockManager &partial_block_manager, - MetadataWriter &table_data_writer) - : RowGroupWriter(table, partial_block_manager), table_data_writer(table_data_writer) { - } - - //! MetadataWriter is a cursor on a given BlockManager. This returns the - //! cursor against which we should write payload data for the specified RowGroup. - MetadataWriter &table_data_writer; + TableDataWriter &writer, MetadataWriter &table_data_writer); public: void WriteColumnDataPointers(ColumnCheckpointState &column_checkpoint_state, Serializer &serializer) override; + CheckpointType GetCheckpointType() const override; MetadataWriter &GetPayloadWriter() override; + +private: + //! Underlying writer object + TableDataWriter &writer; + //! MetadataWriter is a cursor on a given BlockManager. This returns the + //! cursor against which we should write payload data for the specified RowGroup. + MetadataWriter &table_data_writer; }; } // namespace duckdb diff --git a/src/include/duckdb/storage/checkpoint/string_checkpoint_state.hpp b/src/include/duckdb/storage/checkpoint/string_checkpoint_state.hpp index 190e4d5c85c..59eb2efd42d 100644 --- a/src/include/duckdb/storage/checkpoint/string_checkpoint_state.hpp +++ b/src/include/duckdb/storage/checkpoint/string_checkpoint_state.hpp @@ -38,8 +38,9 @@ struct string_location_t { // NOLINT } string_location_t() { } - bool IsValid() { - return offset < int32_t(Storage::BLOCK_SIZE) && (block_id == INVALID_BLOCK || block_id >= MAXIMUM_BLOCK); + bool IsValid(const idx_t block_size) { + auto cast_block_size = NumericCast(block_size); + return offset < cast_block_size && (block_id == INVALID_BLOCK || block_id >= MAXIMUM_BLOCK); } block_id_t block_id; int32_t offset; diff --git a/src/include/duckdb/storage/checkpoint/table_data_writer.hpp b/src/include/duckdb/storage/checkpoint/table_data_writer.hpp index 4ab7a90589c..dfcfec47af8 100644 --- a/src/include/duckdb/storage/checkpoint/table_data_writer.hpp +++ b/src/include/duckdb/storage/checkpoint/table_data_writer.hpp @@ -35,6 +35,7 @@ class TableDataWriter { virtual unique_ptr GetRowGroupWriter(RowGroup &row_group) = 0; virtual void AddRowGroup(RowGroupPointer &&row_group_pointer, unique_ptr writer); + virtual CheckpointType GetCheckpointType() const = 0; TaskScheduler &GetScheduler(); @@ -52,6 +53,7 @@ class SingleFileTableDataWriter : public TableDataWriter { public: void FinalizeTable(const TableStatistics &global_stats, DataTableInfo *info, Serializer &serializer) override; unique_ptr GetRowGroupWriter(RowGroup &row_group) override; + CheckpointType GetCheckpointType() const override; private: SingleFileCheckpointWriter &checkpoint_manager; diff --git a/src/include/duckdb/storage/checkpoint/write_overflow_strings_to_disk.hpp b/src/include/duckdb/storage/checkpoint/write_overflow_strings_to_disk.hpp index c1949a5a07d..ebbffa52d78 100644 --- a/src/include/duckdb/storage/checkpoint/write_overflow_strings_to_disk.hpp +++ b/src/include/duckdb/storage/checkpoint/write_overflow_strings_to_disk.hpp @@ -27,8 +27,6 @@ class WriteOverflowStringsToDisk : public OverflowStringWriter { //! The offset within the current block idx_t offset; - static constexpr idx_t STRING_SPACE = Storage::BLOCK_SIZE - sizeof(block_id_t); - public: void WriteString(UncompressedStringSegmentState &state, string_t string, block_id_t &result_block, int32_t &result_offset) override; @@ -36,6 +34,7 @@ class WriteOverflowStringsToDisk : public OverflowStringWriter { private: void AllocateNewBlock(UncompressedStringSegmentState &state, block_id_t new_block_id); + idx_t GetStringSpace() const; }; } // namespace duckdb diff --git a/src/include/duckdb/storage/checkpoint_manager.hpp b/src/include/duckdb/storage/checkpoint_manager.hpp index 9899565cab7..d72ba118eb8 100644 --- a/src/include/duckdb/storage/checkpoint_manager.hpp +++ b/src/include/duckdb/storage/checkpoint_manager.hpp @@ -40,7 +40,7 @@ class CheckpointWriter { protected: virtual void WriteEntry(CatalogEntry &entry, Serializer &serializer); virtual void WriteSchema(SchemaCatalogEntry &schema, Serializer &serializer); - virtual void WriteTable(TableCatalogEntry &table, Serializer &serializer); + virtual void WriteTable(TableCatalogEntry &table, Serializer &serializer) = 0; virtual void WriteView(ViewCatalogEntry &table, Serializer &serializer); virtual void WriteSequence(SequenceCatalogEntry &table, Serializer &serializer); virtual void WriteMacro(ScalarMacroCatalogEntry &table, Serializer &serializer); @@ -60,18 +60,19 @@ class CheckpointReader { Catalog &catalog; protected: - virtual void LoadCheckpoint(ClientContext &context, MetadataReader &reader); - virtual void ReadEntry(ClientContext &context, Deserializer &deserializer); - virtual void ReadSchema(ClientContext &context, Deserializer &deserializer); - virtual void ReadTable(ClientContext &context, Deserializer &deserializer); - virtual void ReadView(ClientContext &context, Deserializer &deserializer); - virtual void ReadSequence(ClientContext &context, Deserializer &deserializer); - virtual void ReadMacro(ClientContext &context, Deserializer &deserializer); - virtual void ReadTableMacro(ClientContext &context, Deserializer &deserializer); - virtual void ReadIndex(ClientContext &context, Deserializer &deserializer); - virtual void ReadType(ClientContext &context, Deserializer &deserializer); - - virtual void ReadTableData(ClientContext &context, Deserializer &deserializer, BoundCreateTableInfo &bound_info); + virtual void LoadCheckpoint(CatalogTransaction transaction, MetadataReader &reader); + virtual void ReadEntry(CatalogTransaction transaction, Deserializer &deserializer); + virtual void ReadSchema(CatalogTransaction transaction, Deserializer &deserializer); + virtual void ReadTable(CatalogTransaction transaction, Deserializer &deserializer); + virtual void ReadView(CatalogTransaction transaction, Deserializer &deserializer); + virtual void ReadSequence(CatalogTransaction transaction, Deserializer &deserializer); + virtual void ReadMacro(CatalogTransaction transaction, Deserializer &deserializer); + virtual void ReadTableMacro(CatalogTransaction transaction, Deserializer &deserializer); + virtual void ReadIndex(CatalogTransaction transaction, Deserializer &deserializer); + virtual void ReadType(CatalogTransaction transaction, Deserializer &deserializer); + + virtual void ReadTableData(CatalogTransaction transaction, Deserializer &deserializer, + BoundCreateTableInfo &bound_info); }; class SingleFileCheckpointReader final : public CheckpointReader { @@ -80,7 +81,7 @@ class SingleFileCheckpointReader final : public CheckpointReader { : CheckpointReader(Catalog::GetCatalog(storage.GetAttached())), storage(storage) { } - void LoadFromStorage(optional_ptr context = nullptr); + void LoadFromStorage(); MetadataManager &GetMetadataManager(); //! The database @@ -96,7 +97,7 @@ class SingleFileCheckpointWriter final : public CheckpointWriter { friend class SingleFileTableDataWriter; public: - SingleFileCheckpointWriter(AttachedDatabase &db, BlockManager &block_manager); + SingleFileCheckpointWriter(AttachedDatabase &db, BlockManager &block_manager, CheckpointType checkpoint_type); //! Checkpoint the current state of the WAL and flush it to the main storage. This should be called BEFORE any //! connection is available because right now the checkpointing cannot be done online. (TODO) @@ -107,6 +108,12 @@ class SingleFileCheckpointWriter final : public CheckpointWriter { unique_ptr GetTableDataWriter(TableCatalogEntry &table) override; BlockManager &GetBlockManager(); + CheckpointType GetCheckpointType() const { + return checkpoint_type; + } + +public: + void WriteTable(TableCatalogEntry &table, Serializer &serializer) override; private: //! The metadata writer is responsible for writing schema information @@ -116,6 +123,8 @@ class SingleFileCheckpointWriter final : public CheckpointWriter { //! Because this is single-file storage, we can share partial blocks across //! an entire checkpoint. PartialBlockManager partial_block_manager; + //! Checkpoint type + CheckpointType checkpoint_type; }; } // namespace duckdb diff --git a/src/include/duckdb/storage/compression/alp/alp_analyze.hpp b/src/include/duckdb/storage/compression/alp/alp_analyze.hpp index f77b5ffaa33..49a37c11bdd 100644 --- a/src/include/duckdb/storage/compression/alp/alp_analyze.hpp +++ b/src/include/duckdb/storage/compression/alp/alp_analyze.hpp @@ -10,9 +10,10 @@ #include "duckdb/function/compression_function.hpp" #include "duckdb/storage/compression/alp/algorithm/alp.hpp" -#include "duckdb/storage/compression/alp/alp_utils.hpp" #include "duckdb/storage/compression/alp/alp_constants.hpp" +#include "duckdb/storage/compression/alp/alp_utils.hpp" #include "duckdb/storage/compression/patas/patas.hpp" +#include "duckdb/storage/table/column_data.hpp" #include @@ -23,7 +24,7 @@ struct AlpAnalyzeState : public AnalyzeState { public: using EXACT_TYPE = typename FloatingToExact::TYPE; - AlpAnalyzeState() : state() { + explicit AlpAnalyzeState(const CompressionInfo &info) : AnalyzeState(info), state() { } idx_t total_bytes_used = 0; @@ -62,7 +63,7 @@ struct AlpAnalyzeState : public AnalyzeState { idx_t bytes_to_be_used = AlignValue(current_bytes_used_in_segment + RequiredSpace()); // We have enough space if the already used space + the required space for a new vector // does not exceed the space of the block - the segment header (the pointer to the metadata) - return bytes_to_be_used <= (Storage::BLOCK_SIZE - AlpConstants::METADATA_POINTER_SIZE); + return bytes_to_be_used <= (info.GetBlockSize() - AlpConstants::METADATA_POINTER_SIZE); } idx_t TotalUsedBytes() const { @@ -72,7 +73,8 @@ struct AlpAnalyzeState : public AnalyzeState { template unique_ptr AlpInitAnalyze(ColumnData &col_data, PhysicalType type) { - return make_uniq>(); + CompressionInfo info(Storage::BLOCK_SIZE, type); + return make_uniq>(info); } /* diff --git a/src/include/duckdb/storage/compression/alp/alp_compress.hpp b/src/include/duckdb/storage/compression/alp/alp_compress.hpp index e4021d93919..613624da372 100644 --- a/src/include/duckdb/storage/compression/alp/alp_compress.hpp +++ b/src/include/duckdb/storage/compression/alp/alp_compress.hpp @@ -8,21 +8,19 @@ #pragma once -#include "duckdb/storage/compression/patas/patas.hpp" -#include "duckdb/function/compression_function.hpp" -#include "duckdb/storage/compression/alp/algorithm/alp.hpp" -#include "duckdb/storage/compression/alp/alp_analyze.hpp" - #include "duckdb/common/helper.hpp" #include "duckdb/common/limits.hpp" +#include "duckdb/common/operator/subtract.hpp" #include "duckdb/common/types/null_value.hpp" #include "duckdb/function/compression/compression.hpp" +#include "duckdb/function/compression_function.hpp" #include "duckdb/main/config.hpp" #include "duckdb/storage/buffer_manager.hpp" - +#include "duckdb/storage/compression/alp/algorithm/alp.hpp" +#include "duckdb/storage/compression/alp/alp_analyze.hpp" +#include "duckdb/storage/compression/patas/patas.hpp" #include "duckdb/storage/table/column_data_checkpointer.hpp" #include "duckdb/storage/table/column_segment.hpp" -#include "duckdb/common/operator/subtract.hpp" #include @@ -33,8 +31,10 @@ struct AlpCompressionState : public CompressionState { public: using EXACT_TYPE = typename FloatingToExact::TYPE; - explicit AlpCompressionState(ColumnDataCheckpointer &checkpointer, AlpAnalyzeState *analyze_state) - : checkpointer(checkpointer), function(checkpointer.GetCompressionFunction(CompressionType::COMPRESSION_ALP)) { + + AlpCompressionState(ColumnDataCheckpointer &checkpointer, AlpAnalyzeState *analyze_state) + : CompressionState(analyze_state->info), checkpointer(checkpointer), + function(checkpointer.GetCompressionFunction(CompressionType::COMPRESSION_ALP)) { CreateEmptySegment(checkpointer.GetRowGroup().start); //! Combinations found on the analyze step are needed for compression @@ -92,17 +92,18 @@ struct AlpCompressionState : public CompressionState { void CreateEmptySegment(idx_t row_start) { auto &db = checkpointer.GetDatabase(); auto &type = checkpointer.GetType(); + auto compressed_segment = ColumnSegment::CreateTransientSegment(db, type, row_start); current_segment = std::move(compressed_segment); current_segment->function = function; + auto &buffer_manager = BufferManager::GetBufferManager(current_segment->db); handle = buffer_manager.Pin(current_segment->block); - // Pointer to the start of the compressed data + // The pointer to the start of the compressed data. data_ptr = handle.Ptr() + current_segment->GetBlockOffset() + AlpConstants::HEADER_SIZE; - // Pointer to the start of the Metadata - metadata_ptr = handle.Ptr() + current_segment->GetBlockOffset() + Storage::BLOCK_SIZE; - + // The pointer to the start of the metadata. + metadata_ptr = handle.Ptr() + current_segment->GetBlockOffset() + info.GetBlockSize(); next_vector_byte_index_start = AlpConstants::HEADER_SIZE; } @@ -183,10 +184,10 @@ struct AlpCompressionState : public CompressionState { // Verify that the metadata_ptr is not smaller than the space used by the data D_ASSERT(dataptr + metadata_offset <= metadata_ptr); - auto bytes_used_by_metadata = UnsafeNumericCast(dataptr + Storage::BLOCK_SIZE - metadata_ptr); + auto bytes_used_by_metadata = UnsafeNumericCast(dataptr + info.GetBlockSize() - metadata_ptr); // Initially the total segment size is the size of the block - auto total_segment_size = Storage::BLOCK_SIZE; + auto total_segment_size = info.GetBlockSize(); //! We compact the block if the space used is less than a threshold const auto used_space_percentage = diff --git a/src/include/duckdb/storage/compression/alprd/alprd_analyze.hpp b/src/include/duckdb/storage/compression/alprd/alprd_analyze.hpp index e37d873ac52..2bc57c0c374 100644 --- a/src/include/duckdb/storage/compression/alprd/alprd_analyze.hpp +++ b/src/include/duckdb/storage/compression/alprd/alprd_analyze.hpp @@ -8,13 +8,14 @@ #pragma once +#include "duckdb/common/numeric_utils.hpp" #include "duckdb/function/compression_function.hpp" -#include "duckdb/storage/compression/patas/patas.hpp" +#include "duckdb/storage/compression/alp/alp_constants.hpp" +#include "duckdb/storage/compression/alp/alp_utils.hpp" #include "duckdb/storage/compression/alprd/algorithm/alprd.hpp" #include "duckdb/storage/compression/alprd/alprd_constants.hpp" -#include "duckdb/storage/compression/alp/alp_utils.hpp" -#include "duckdb/storage/compression/alp/alp_constants.hpp" -#include "duckdb/common/numeric_utils.hpp" +#include "duckdb/storage/compression/patas/patas.hpp" +#include "duckdb/storage/table/column_data.hpp" #include @@ -25,7 +26,7 @@ struct AlpRDAnalyzeState : public AnalyzeState { public: using EXACT_TYPE = typename FloatingToExact::TYPE; - AlpRDAnalyzeState() : state() { + explicit AlpRDAnalyzeState(const CompressionInfo &info) : AnalyzeState(info), state() { } idx_t vectors_count = 0; @@ -37,7 +38,8 @@ struct AlpRDAnalyzeState : public AnalyzeState { template unique_ptr AlpRDInitAnalyze(ColumnData &col_data, PhysicalType type) { - return make_uniq>(); + CompressionInfo info(Storage::BLOCK_SIZE, type); + return make_uniq>(info); } /* @@ -131,7 +133,7 @@ idx_t AlpRDFinalAnalyze(AnalyzeState &state) { auto estimated_size = (estimed_compressed_bytes * factor_of_sampling) + (n_vectors * per_vector_overhead); uint32_t estimated_n_blocks = - NumericCast(std::ceil(estimated_size / (Storage::BLOCK_SIZE - per_segment_overhead))); + NumericCast(std::ceil(estimated_size / (state.info.GetBlockSize() - per_segment_overhead))); auto final_analyze_size = estimated_size + (estimated_n_blocks * per_segment_overhead); return NumericCast(final_analyze_size); diff --git a/src/include/duckdb/storage/compression/alprd/alprd_compress.hpp b/src/include/duckdb/storage/compression/alprd/alprd_compress.hpp index 3f2a8aca329..2bc081ae47a 100644 --- a/src/include/duckdb/storage/compression/alprd/alprd_compress.hpp +++ b/src/include/duckdb/storage/compression/alprd/alprd_compress.hpp @@ -8,23 +8,21 @@ #pragma once -#include "duckdb/storage/compression/patas/patas.hpp" -#include "duckdb/storage/compression/alprd/algorithm/alprd.hpp" -#include "duckdb/function/compression_function.hpp" -#include "duckdb/storage/compression/alprd/alprd_analyze.hpp" -#include "duckdb/storage/compression/alprd/alprd_constants.hpp" -#include "duckdb/storage/compression/alp/alp_constants.hpp" - #include "duckdb/common/helper.hpp" #include "duckdb/common/limits.hpp" +#include "duckdb/common/operator/subtract.hpp" #include "duckdb/common/types/null_value.hpp" #include "duckdb/function/compression/compression.hpp" +#include "duckdb/function/compression_function.hpp" #include "duckdb/main/config.hpp" #include "duckdb/storage/buffer_manager.hpp" - +#include "duckdb/storage/compression/alp/alp_constants.hpp" +#include "duckdb/storage/compression/alprd/algorithm/alprd.hpp" +#include "duckdb/storage/compression/alprd/alprd_analyze.hpp" +#include "duckdb/storage/compression/alprd/alprd_constants.hpp" +#include "duckdb/storage/compression/patas/patas.hpp" #include "duckdb/storage/table/column_data_checkpointer.hpp" #include "duckdb/storage/table/column_segment.hpp" -#include "duckdb/common/operator/subtract.hpp" #include @@ -35,8 +33,9 @@ struct AlpRDCompressionState : public CompressionState { public: using EXACT_TYPE = typename FloatingToExact::TYPE; - explicit AlpRDCompressionState(ColumnDataCheckpointer &checkpointer, AlpRDAnalyzeState *analyze_state) - : checkpointer(checkpointer), + + AlpRDCompressionState(ColumnDataCheckpointer &checkpointer, AlpRDAnalyzeState *analyze_state) + : CompressionState(analyze_state->info), checkpointer(checkpointer), function(checkpointer.GetCompressionFunction(CompressionType::COMPRESSION_ALPRD)) { //! State variables from the analyze step that are needed for compression state.left_parts_dict_map = std::move(analyze_state->state.left_parts_dict_map); @@ -103,6 +102,7 @@ struct AlpRDCompressionState : public CompressionState { void CreateEmptySegment(idx_t row_start) { auto &db = checkpointer.GetDatabase(); auto &type = checkpointer.GetType(); + auto compressed_segment = ColumnSegment::CreateTransientSegment(db, type, row_start); compressed_segment->function = function; current_segment = std::move(compressed_segment); @@ -110,12 +110,11 @@ struct AlpRDCompressionState : public CompressionState { auto &buffer_manager = BufferManager::GetBufferManager(db); handle = buffer_manager.Pin(current_segment->block); - // Pointer to the start of the compressed data + // The pointer to the start of the compressed data. data_ptr = handle.Ptr() + current_segment->GetBlockOffset() + AlpRDConstants::HEADER_SIZE + actual_dictionary_size_bytes; - // Pointer to the start of the Metadata - metadata_ptr = handle.Ptr() + current_segment->GetBlockOffset() + Storage::BLOCK_SIZE; - + // The pointer to the start of the metadata. + metadata_ptr = handle.Ptr() + current_segment->GetBlockOffset() + info.GetBlockSize(); next_vector_byte_index_start = AlpRDConstants::HEADER_SIZE + actual_dictionary_size_bytes; } @@ -185,10 +184,10 @@ struct AlpRDCompressionState : public CompressionState { // Verify that the metadata_ptr is not smaller than the space used by the data D_ASSERT(dataptr + metadata_offset <= metadata_ptr); - auto bytes_used_by_metadata = UnsafeNumericCast(dataptr + Storage::BLOCK_SIZE - metadata_ptr); + auto bytes_used_by_metadata = UnsafeNumericCast(dataptr + info.GetBlockSize() - metadata_ptr); // Initially the total segment size is the size of the block - auto total_segment_size = Storage::BLOCK_SIZE; + auto total_segment_size = info.GetBlockSize(); //! We compact the block if the space used is less than a threshold const auto used_space_percentage = diff --git a/src/include/duckdb/storage/data_pointer.hpp b/src/include/duckdb/storage/data_pointer.hpp index 97752ee5e14..b91d2e9080b 100644 --- a/src/include/duckdb/storage/data_pointer.hpp +++ b/src/include/duckdb/storage/data_pointer.hpp @@ -19,6 +19,7 @@ namespace duckdb { class Serializer; class Deserializer; +class CompressionInfo; struct ColumnSegmentState { virtual ~ColumnSegmentState() { diff --git a/src/include/duckdb/storage/data_table.hpp b/src/include/duckdb/storage/data_table.hpp index dcde5af382b..58788712165 100644 --- a/src/include/duckdb/storage/data_table.hpp +++ b/src/include/duckdb/storage/data_table.hpp @@ -63,16 +63,18 @@ class DataTable { //! Constructs a DataTable as a delta on an existing data table but with one column added new constraint explicit DataTable(ClientContext &context, DataTable &parent, unique_ptr constraint); - //! The table info - shared_ptr info; - //! The set of physical columns stored by this DataTable - vector column_definitions; //! A reference to the database instance AttachedDatabase &db; public: + AttachedDatabase &GetAttached(); + TableIOManager &GetTableIOManager(); + + bool IsTemporary() const; + //! Returns a list of types of the table vector GetTypes(); + const vector &Columns() const; void InitializeScan(TableScanState &state, const vector &column_ids, TableFilterSet *table_filter = nullptr); @@ -181,12 +183,17 @@ class DataTable { //! Sets statistics of a physical column within the table void SetDistinct(column_t column_id, unique_ptr distinct_stats); + //! Obtains a shared lock to prevent checkpointing while operations are running + unique_ptr GetSharedCheckpointLock(); + //! Obtains a lock during a checkpoint operation that prevents other threads from reading this table + unique_ptr GetCheckpointLock(); //! Checkpoint the table to the specified table data writer void Checkpoint(TableDataWriter &writer, Serializer &serializer); void CommitDropTable(); void CommitDropColumn(idx_t index); - idx_t GetTotalRows(); + idx_t ColumnCount() const; + idx_t GetTotalRows() const; vector GetColumnSegmentInfo(); static bool IsForeignKeyIndex(const vector &fk_keys, Index &index, ForeignKeyType fk_type); @@ -204,13 +211,27 @@ class DataTable { void VerifyAppendConstraints(ConstraintState &state, ClientContext &context, DataChunk &chunk, optional_ptr conflict_manager = nullptr); + shared_ptr &GetDataTableInfo(); + + void InitializeIndexes(ClientContext &context); + bool HasIndexes() const; + void AddIndex(unique_ptr index); + bool HasForeignKeyIndex(const vector &keys, ForeignKeyType type); + void SetIndexStorageInfo(vector index_storage_info); + void VacuumIndexes(); + + string GetTableName() const; + void SetTableName(string new_name); + + TableStorageInfo GetStorageInfo(); + public: static void VerifyUniqueIndexes(TableIndexList &indexes, ClientContext &context, DataChunk &chunk, optional_ptr conflict_manager); private: //! Verify the new added constraints against current persistent&local data - void VerifyNewConstraint(ClientContext &context, DataTable &parent, const BoundConstraint *constraint); + void VerifyNewConstraint(LocalStorage &local_storage, DataTable &parent, const BoundConstraint &constraint); //! Verify constraints with a chunk from the Update containing only the specified column_ids void VerifyUpdateConstraints(ConstraintState &state, ClientContext &context, DataChunk &chunk, const vector &column_ids); @@ -228,6 +249,10 @@ class DataTable { DataChunk &chunk); private: + //! The table info + shared_ptr info; + //! The set of physical columns stored by this DataTable + vector column_definitions; //! Lock for appending entries to the table mutex append_lock; //! The row groups of the table diff --git a/src/include/duckdb/storage/in_memory_block_manager.hpp b/src/include/duckdb/storage/in_memory_block_manager.hpp index 0f3985cb91f..7c09541a3cc 100644 --- a/src/include/duckdb/storage/in_memory_block_manager.hpp +++ b/src/include/duckdb/storage/in_memory_block_manager.hpp @@ -29,6 +29,9 @@ class InMemoryBlockManager : public BlockManager { block_id_t GetFreeBlockId() override { throw InternalException("Cannot perform IO in in-memory database - GetFreeBlockId!"); } + block_id_t PeekFreeBlockId() override { + throw InternalException("Cannot perform IO in in-memory database - PeekFreeBlockId!"); + } bool IsRootBlock(MetaBlockPointer root) override { throw InternalException("Cannot perform IO in in-memory database - IsRootBlock!"); } @@ -47,12 +50,18 @@ class InMemoryBlockManager : public BlockManager { void Read(Block &block) override { throw InternalException("Cannot perform IO in in-memory database - Read!"); } + void ReadBlocks(FileBuffer &buffer, block_id_t start_block, idx_t block_count) override { + throw InternalException("Cannot perform IO in in-memory database - ReadBlocks!"); + } void Write(FileBuffer &block, block_id_t block_id) override { throw InternalException("Cannot perform IO in in-memory database - Write!"); } void WriteHeader(DatabaseHeader header) override { throw InternalException("Cannot perform IO in in-memory database - WriteHeader!"); } + bool InMemory() override { + return true; + } idx_t TotalBlocks() override { throw InternalException("Cannot perform IO in in-memory database - TotalBlocks!"); } diff --git a/src/include/duckdb/storage/index.hpp b/src/include/duckdb/storage/index.hpp index f5e89486b28..d838f60a3b0 100644 --- a/src/include/duckdb/storage/index.hpp +++ b/src/include/duckdb/storage/index.hpp @@ -12,7 +12,6 @@ #include "duckdb/common/types/constraint_conflict_info.hpp" #include "duckdb/common/types/data_chunk.hpp" #include "duckdb/common/unordered_set.hpp" -#include "duckdb/execution/expression_executor.hpp" #include "duckdb/parser/parsed_expression.hpp" #include "duckdb/planner/expression.hpp" #include "duckdb/storage/table_storage_info.hpp" @@ -29,127 +28,64 @@ struct IndexScanState; //! The index is an abstract base class that serves as the basis for indexes class Index { -public: - Index(const string &name, const string &index_type, IndexConstraintType index_constraint_type, - const vector &column_ids, TableIOManager &table_io_manager, - const vector> &unbound_expressions, AttachedDatabase &db); - virtual ~Index() = default; +protected: + Index(const vector &column_ids, TableIOManager &table_io_manager, AttachedDatabase &db); - //! The name of the index - string name; - //! The index type (ART, B+-tree, Skip-List, ...) - string index_type; - //! The index constraint type - IndexConstraintType index_constraint_type; //! The logical column ids of the indexed table vector column_ids; - - //! Associated table io manager - TableIOManager &table_io_manager; //! Unordered set of column_ids used by the index unordered_set column_id_set; - //! Unbound expressions used by the index during optimizations - vector> unbound_expressions; - //! The physical types stored in the index - vector types; - //! The logical types of the expressions - vector logical_types; +public: + //! Associated table io manager + TableIOManager &table_io_manager; //! Attached database instance AttachedDatabase &db; public: - //! Returns true if the index is a unknown index, and false otherwise - virtual bool IsUnknown() { - return false; - } + virtual ~Index() = default; - //! Obtain a lock on the index - void InitializeLock(IndexLock &state); - //! Called when data is appended to the index. The lock obtained from InitializeLock must be held - virtual ErrorData Append(IndexLock &state, DataChunk &entries, Vector &row_identifiers) = 0; - //! Obtains a lock and calls Append while holding that lock - ErrorData Append(DataChunk &entries, Vector &row_identifiers); - //! Verify that data can be appended to the index without a constraint violation - virtual void VerifyAppend(DataChunk &chunk) = 0; - //! Verify that data can be appended to the index without a constraint violation using the conflict manager - virtual void VerifyAppend(DataChunk &chunk, ConflictManager &conflict_manager) = 0; - //! Performs constraint checking for a chunk of input data - virtual void CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_manager) = 0; - - //! Deletes all data from the index. The lock obtained from InitializeLock must be held - virtual void CommitDrop(IndexLock &index_lock) = 0; - //! Deletes all data from the index - void CommitDrop(); - //! Delete a chunk of entries from the index. The lock obtained from InitializeLock must be held - virtual void Delete(IndexLock &state, DataChunk &entries, Vector &row_identifiers) = 0; - //! Obtains a lock and calls Delete while holding that lock - void Delete(DataChunk &entries, Vector &row_identifiers); - - //! Insert a chunk of entries into the index - virtual ErrorData Insert(IndexLock &lock, DataChunk &input, Vector &row_identifiers) = 0; - - //! Merge another index into this index. The lock obtained from InitializeLock must be held, and the other - //! index must also be locked during the merge - virtual bool MergeIndexes(IndexLock &state, Index &other_index) = 0; - //! Obtains a lock and calls MergeIndexes while holding that lock - bool MergeIndexes(Index &other_index); - - //! Traverses an ART and vacuums the qualifying nodes. The lock obtained from InitializeLock must be held - virtual void Vacuum(IndexLock &state) = 0; - //! Obtains a lock and calls Vacuum while holding that lock - void Vacuum(); - - //! Returns the in-memory usage of the index. The lock obtained from InitializeLock must be held - virtual idx_t GetInMemorySize(IndexLock &state) = 0; - //! Returns the in-memory usage of the index - idx_t GetInMemorySize(); - - //! Returns the string representation of an index, or only traverses and verifies the index - virtual string VerifyAndToString(IndexLock &state, const bool only_verify) = 0; - //! Obtains a lock and calls VerifyAndToString while holding that lock - string VerifyAndToString(const bool only_verify); - - //! Returns true if the index is affected by updates on the specified column IDs, and false otherwise - bool IndexIsUpdated(const vector &column_ids) const; + //! Returns true if the index is a bound index, and false otherwise + virtual bool IsBound() const = 0; + + //! The index type (ART, B+-tree, Skip-List, ...) + virtual const string &GetIndexType() const = 0; + + //! The name of the index + virtual const string &GetIndexName() const = 0; + + //! The index constraint type + virtual IndexConstraintType GetConstraintType() const = 0; //! Returns unique flag - bool IsUnique() { + bool IsUnique() const { + auto index_constraint_type = GetConstraintType(); return (index_constraint_type == IndexConstraintType::UNIQUE || index_constraint_type == IndexConstraintType::PRIMARY); } + //! Returns primary key flag - bool IsPrimary() { + bool IsPrimary() const { + auto index_constraint_type = GetConstraintType(); return (index_constraint_type == IndexConstraintType::PRIMARY); } + //! Returns foreign key flag - bool IsForeign() { + bool IsForeign() const { + auto index_constraint_type = GetConstraintType(); return (index_constraint_type == IndexConstraintType::FOREIGN); } - //! Returns all index storage information for serialization - virtual IndexStorageInfo GetStorageInfo(const bool get_buffers); - - //! Execute the index expressions on an input chunk - void ExecuteExpressions(DataChunk &input, DataChunk &result); - static string AppendRowError(DataChunk &input, idx_t index); - - //! Throw a constraint violation exception - virtual string GetConstraintViolationMessage(VerifyExistenceType verify_type, idx_t failed_index, - DataChunk &input) = 0; - -protected: - //! Lock used for any changes to the index - mutex lock; + const vector &GetColumnIds() const { + return column_ids; + } -private: - //! Bound expressions used during expression execution - vector> bound_expressions; - //! Expression executor to execute the index expressions - ExpressionExecutor executor; + const unordered_set &GetColumnIdSet() const { + return column_id_set; + } - //! Bind the unbound expressions of the index - unique_ptr BindExpression(unique_ptr expr); + // All indexes can be dropped, even if they are unbound + virtual void CommitDrop() = 0; public: template diff --git a/src/include/duckdb/storage/metadata/metadata_manager.hpp b/src/include/duckdb/storage/metadata/metadata_manager.hpp index 900dde00970..ec10765be0a 100644 --- a/src/include/duckdb/storage/metadata/metadata_manager.hpp +++ b/src/include/duckdb/storage/metadata/metadata_manager.hpp @@ -44,8 +44,6 @@ class MetadataManager { public: //! The amount of metadata blocks per storage block static constexpr const idx_t METADATA_BLOCK_COUNT = 64; - //! The size of metadata blocks - static constexpr const idx_t METADATA_BLOCK_SIZE = AlignValueFloor(Storage::BLOCK_SIZE / METADATA_BLOCK_COUNT); public: MetadataManager(BlockManager &block_manager, BufferManager &buffer_manager); @@ -58,8 +56,8 @@ class MetadataManager { MetadataPointer FromDiskPointer(MetaBlockPointer pointer); MetadataPointer RegisterDiskPointer(MetaBlockPointer pointer); - static BlockPointer ToBlockPointer(MetaBlockPointer meta_pointer); - static MetaBlockPointer FromBlockPointer(BlockPointer block_pointer); + static BlockPointer ToBlockPointer(MetaBlockPointer meta_pointer, const idx_t metadata_block_size); + static MetaBlockPointer FromBlockPointer(BlockPointer block_pointer, const idx_t metadata_block_size); //! Flush all blocks to disk void Flush(); @@ -68,11 +66,14 @@ class MetadataManager { void ClearModifiedBlocks(const vector &pointers); vector GetMetadataInfo() const; + vector> GetBlocks() const; idx_t BlockCount(); void Write(WriteStream &sink); void Read(ReadStream &source); + idx_t GetMetadataBlockSize() const; + protected: BlockManager &block_manager; BufferManager &buffer_manager; @@ -81,6 +82,7 @@ class MetadataManager { protected: block_id_t AllocateNewBlock(); + block_id_t PeekNextBlockId(); block_id_t GetNextBlockId(); void AddBlock(MetadataBlock new_block, bool if_exists = false); @@ -88,8 +90,4 @@ class MetadataManager { void ConvertToTransient(MetadataBlock &block); }; -//! Detect mismatching constant values -static_assert(MetadataManager::METADATA_BLOCK_SIZE * MetadataManager::METADATA_BLOCK_COUNT <= Storage::BLOCK_SIZE, - "metadata block count exceeds total block alloc size"); - } // namespace duckdb diff --git a/src/include/duckdb/storage/optimistic_data_writer.hpp b/src/include/duckdb/storage/optimistic_data_writer.hpp index 4feb456df8b..802d51bad70 100644 --- a/src/include/duckdb/storage/optimistic_data_writer.hpp +++ b/src/include/duckdb/storage/optimistic_data_writer.hpp @@ -26,7 +26,7 @@ class OptimisticDataWriter { //! Final flush of the optimistic writer - fully flushes the partial block manager void FinalFlush(); //! Flushes a specific row group to disk - void FlushToDisk(RowGroup *row_group); + void FlushToDisk(RowGroup &row_group); //! Merge the partially written blocks from one optimistic writer into another void Merge(OptimisticDataWriter &other); //! Rollback diff --git a/src/include/duckdb/storage/partial_block_manager.hpp b/src/include/duckdb/storage/partial_block_manager.hpp index 935f0126993..6fa08ca379f 100644 --- a/src/include/duckdb/storage/partial_block_manager.hpp +++ b/src/include/duckdb/storage/partial_block_manager.hpp @@ -85,15 +85,13 @@ struct PartialBlockAllocation { unique_ptr partial_block; }; -enum class CheckpointType { FULL_CHECKPOINT, APPEND_TO_TABLE }; +enum class PartialBlockType { FULL_CHECKPOINT, APPEND_TO_TABLE }; //! Enables sharing blocks across some scope. Scope is whatever we want to share //! blocks across. It may be an entire checkpoint or just a single row group. //! In any case, they must share a block manager. class PartialBlockManager { public: - //! 20% free / 80% utilization - static constexpr const idx_t DEFAULT_MAX_PARTIAL_BLOCK_SIZE = Storage::BLOCK_SIZE / 5 * 4; //! Max number of shared references to a block. No effective limit by default. static constexpr const idx_t DEFAULT_MAX_USE_COUNT = 1u << 20; //! No point letting map size grow unbounded. We'll drop blocks with the @@ -101,8 +99,8 @@ class PartialBlockManager { static constexpr const idx_t MAX_BLOCK_MAP_SIZE = 1u << 31; public: - PartialBlockManager(BlockManager &block_manager, CheckpointType checkpoint_type, - uint32_t max_partial_block_size = DEFAULT_MAX_PARTIAL_BLOCK_SIZE, + PartialBlockManager(BlockManager &block_manager, PartialBlockType partial_block_type, + optional_idx max_partial_block_size = optional_idx(), uint32_t max_use_count = DEFAULT_MAX_USE_COUNT); virtual ~PartialBlockManager(); @@ -130,7 +128,7 @@ class PartialBlockManager { protected: BlockManager &block_manager; - CheckpointType checkpoint_type; + PartialBlockType partial_block_type; mutex partial_block_lock; //! A map of (available space -> PartialBlock) for partially filled blocks //! This is a multimap because there might be outstanding partial blocks with diff --git a/src/include/duckdb/storage/serialization/create_info.json b/src/include/duckdb/storage/serialization/create_info.json index c850a71e854..1e9ea1dfbb0 100644 --- a/src/include/duckdb/storage/serialization/create_info.json +++ b/src/include/duckdb/storage/serialization/create_info.json @@ -49,7 +49,20 @@ "name": "comment", "type": "Value", "default": "Value()" - } + }, + { + "id": 108, + "name": "tags", + "type": "unordered_map", + "default": "unordered_map()" + }, + { + "id": 109, + "name": "dependencies", + "type": "LogicalDependencyList", + "default": "LogicalDependencyList()", + "version": "v0.10.3" + } ] }, { diff --git a/src/include/duckdb/storage/serialization/dependency.json b/src/include/duckdb/storage/serialization/dependency.json new file mode 100644 index 00000000000..4800a639aa4 --- /dev/null +++ b/src/include/duckdb/storage/serialization/dependency.json @@ -0,0 +1,56 @@ +[ + { + "class": "CatalogEntryInfo", + "includes": [ + "duckdb/catalog/dependency.hpp" + ], + "members": [ + { + "id": 100, + "name": "type", + "type": "CatalogType" + }, + { + "id": 101, + "name": "schema", + "type": "string" + }, + { + "id": 102, + "name": "name", + "type": "string" + } + ], + "pointer_type": "none" + }, + { + "class": "LogicalDependency", + "includes": [ + "duckdb/catalog/dependency_list.hpp" + ], + "members": [ + { + "id": 100, + "name": "entry", + "type": "CatalogEntryInfo" + }, + { + "id": 101, + "name": "catalog", + "type": "string" + } + ], + "pointer_type": "none" + }, + { + "class": "LogicalDependencyList", + "members": [ + { + "id": 100, + "name": "set", + "type": "create_info_set_t" + } + ], + "pointer_type": "none" + } +] diff --git a/src/include/duckdb/storage/serialization/extension_install_info.json b/src/include/duckdb/storage/serialization/extension_install_info.json new file mode 100644 index 00000000000..be7b011c907 --- /dev/null +++ b/src/include/duckdb/storage/serialization/extension_install_info.json @@ -0,0 +1,35 @@ +[ + { + "class": "ExtensionInstallInfo", + "includes": [ + "duckdb/main/extension_install_info.hpp" + ], + "members": [ + { + "id": 100, + "name": "mode", + "type": "ExtensionInstallMode" + }, + { + "id": 101, + "name": "full_path", + "type": "string" + }, + { + "id": 102, + "name": "repository_url", + "type": "string" + }, + { + "id": 103, + "name": "version", + "type": "string" + }, + { + "id": 104, + "name": "etag", + "type": "string" + } + ] + } +] diff --git a/src/include/duckdb/storage/serialization/logical_operator.json b/src/include/duckdb/storage/serialization/logical_operator.json index 78fd3eb08c3..28eefe9261f 100644 --- a/src/include/duckdb/storage/serialization/logical_operator.json +++ b/src/include/duckdb/storage/serialization/logical_operator.json @@ -247,7 +247,7 @@ { "id": 202, "name": "collection", - "type": "ColumnDataCollection*" + "type": "optionally_owned_ptr" } ], "constructor": ["table_index", "chunk_types", "collection"] @@ -884,6 +884,12 @@ "enum": "LOGICAL_EXTENSION_OPERATOR", "custom_implementation": true }, + { + "class": "LogicalVacuum", + "base": "LogicalOperator", + "enum": "LOGICAL_VACUUM", + "custom_implementation": true + }, { "class": "FilenamePattern", "pointer_type": "none", diff --git a/src/include/duckdb/storage/serialization/nodes.json b/src/include/duckdb/storage/serialization/nodes.json index de4a355fbcb..0edd3680578 100644 --- a/src/include/duckdb/storage/serialization/nodes.json +++ b/src/include/duckdb/storage/serialization/nodes.json @@ -54,7 +54,7 @@ { "id": 100, "name": "map", - "type": "case_insensitive_map_t" + "type": "InsertionOrderPreservingMap" } ], "pointer_type": "none" @@ -202,6 +202,104 @@ } ] }, + { + "class": "BaseReservoirSampling", + "includes": [ + "duckdb/execution/reservoir_sample.hpp", + "duckdb/common/queue.hpp" + ], + "members": [ + { + "id": 100, + "name": "next_index_to_sample", + "type": "idx_t" + }, + { + "id": 101, + "name": "min_weight_threshold", + "type": "double" + }, + { + "id": 102, + "name": "min_weighted_entry_index", + "type": "idx_t" + }, + { + "id": 103, + "name": "num_entries_to_skip_b4_next_sample", + "type": "idx_t" + }, + { + "id": 104, + "name": "num_entries_seen_total", + "type": "idx_t" + }, + { + "id": 105, + "name": "reservoir_weights", + "type": "std::priority_queue>" + } + ] + }, + { + "class": "BlockingSample", + "class_type": "type", + "members": [ + { + "id" : 100, + "name" : "base_reservoir_sample", + "type" : "unique_ptr" + }, + { + "id" : 101, + "name": "type", + "type": "SampleType" + }, + { + "id": 102, + "name": "destroyed", + "type": "bool" + } + ] + }, + { + "class": "ReservoirSample", + "base": "BlockingSample", + "enum": "RESERVOIR_SAMPLE", + "includes": [], + "members": [ + { + "id": 200, + "name": "sample_count", + "type": "idx_t" + }, + { + "id": 201, + "name": "reservoir_chunk", + "type": "unique_ptr" + } + ], + "constructor": ["sample_count"] + }, + { + "class": "ReservoirSamplePercentage", + "base": "BlockingSample", + "enum": "RESERVOIR_PERCENTAGE_SAMPLE", + "includes": [], + "members": [ + { + "id": 200, + "name": "sample_percentage", + "type": "double" + }, + { + "id": 201, + "name": "reservoir_sample_size", + "type": "idx_t" + } + ], + "constructor": ["sample_percentage"] + }, { "class": "PivotColumn", "includes": [ @@ -319,6 +417,12 @@ "name": "comment", "type": "Value", "default": "Value()" + }, + { + "id": 106, + "name": "tags", + "type": "unordered_map", + "default": "unordered_map()" } ], "constructor": ["name", "type", "expression", "category"], @@ -470,6 +574,12 @@ "id": 105, "name": "hive_types_schema", "type": "case_insensitive_map_t" + }, + { + "id": 106, + "name": "filename_column", + "type": "string", + "default": "MultiFileReaderOptions::DEFAULT_FILENAME_COLUMN" } ], "pointer_type": "none" @@ -783,4 +893,4 @@ ], "pointer_type": "none" } -] \ No newline at end of file +] diff --git a/src/include/duckdb/storage/serialization/parse_info.json b/src/include/duckdb/storage/serialization/parse_info.json index a44ccd10fc3..41f9972cb41 100644 --- a/src/include/duckdb/storage/serialization/parse_info.json +++ b/src/include/duckdb/storage/serialization/parse_info.json @@ -405,6 +405,11 @@ "id": 207, "name": "options", "type": "case_insensitive_map_t>" + }, + { + "id": 208, + "name": "select_statement", + "type": "QueryNode*" } ] }, @@ -500,6 +505,31 @@ "id": 202, "name": "repository", "type": "string" + }, + { + "id": 203, + "name": "version", + "type": "string" + }, + { + "id": 204, + "name": "repo_is_alias", + "type": "bool" + } + ] + }, + { + "class": "UpdateExtensionsInfo", + "base": "ParseInfo", + "enum": "UPDATE_EXTENSIONS_INFO", + "includes": [ + "duckdb/parser/parsed_data/update_extensions_info.hpp" + ], + "members": [ + { + "id": 200, + "name": "extensions_to_update", + "type": "vector" } ] }, @@ -540,6 +570,11 @@ "id": 200, "name": "type", "type": "TransactionType" + }, + { + "id": 201, + "name": "modifier", + "type": "TransactionModifierType" } ] }, diff --git a/src/include/duckdb/storage/serialization/parsed_expression.json b/src/include/duckdb/storage/serialization/parsed_expression.json index d9bb9fdb97e..649356a280a 100644 --- a/src/include/duckdb/storage/serialization/parsed_expression.json +++ b/src/include/duckdb/storage/serialization/parsed_expression.json @@ -327,6 +327,11 @@ "id": 204, "name": "expr", "type": "ParsedExpression*" + },{ + "id": 205, + "name": "unpacked", + "type": "bool", + "default": "false" } ] }, diff --git a/src/include/duckdb/storage/serialization/tableref.json b/src/include/duckdb/storage/serialization/tableref.json index 85d5a318ed8..9128af8f23a 100644 --- a/src/include/duckdb/storage/serialization/tableref.json +++ b/src/include/duckdb/storage/serialization/tableref.json @@ -157,6 +157,24 @@ } ] }, + { + "class": "ColumnDataRef", + "base": "TableRef", + "enum": "COLUMN_DATA", + "members": [ + { + "id": 200, + "name": "expected_names", + "type": "vector" + }, + { + "id": 202, + "name": "collection", + "type": "optionally_owned_ptr" + } + ], + "constructor": ["expected_names", "collection"] + }, { "class": "PivotRef", "base": "TableRef", diff --git a/src/include/duckdb/storage/serialization/types.json b/src/include/duckdb/storage/serialization/types.json index 8f3adec0837..34c0d6c597e 100644 --- a/src/include/duckdb/storage/serialization/types.json +++ b/src/include/duckdb/storage/serialization/types.json @@ -15,6 +15,12 @@ "id": 101, "name": "alias", "type": "string" + }, + { + "id": 102, + "name": "modifiers", + "type": "vector", + "default": "vector()" } ], "pointer_type": "shared_ptr" @@ -136,6 +142,12 @@ "name": "schema", "type": "string", "default": "string()" + }, + { + "id": 203, + "name": "user_type_modifiers", + "type": "vector", + "default": "vector()" } ] }, diff --git a/src/include/duckdb/storage/single_file_block_manager.hpp b/src/include/duckdb/storage/single_file_block_manager.hpp index 2c23e154527..8be4b895ff0 100644 --- a/src/include/duckdb/storage/single_file_block_manager.hpp +++ b/src/include/duckdb/storage/single_file_block_manager.hpp @@ -26,6 +26,7 @@ struct StorageManagerOptions { bool read_only = false; bool use_direct_io = false; DebugInitialize debug_initialize = DebugInitialize::NO_INITIALIZE; + optional_idx block_alloc_size = optional_idx(); }; //! SingleFileBlockManager is an implementation for a BlockManager which manages blocks in a single file @@ -34,10 +35,13 @@ class SingleFileBlockManager : public BlockManager { static constexpr uint64_t BLOCK_START = Storage::FILE_HEADER_SIZE * 3; public: - SingleFileBlockManager(AttachedDatabase &db, string path, StorageManagerOptions options); + SingleFileBlockManager(AttachedDatabase &db, const string &path, const StorageManagerOptions &options); FileOpenFlags GetFileFlags(bool create_new) const; + //! Creates a new database. void CreateNewDatabase(); + //! Loads an existing database. We pass the provided block allocation size as a parameter + //! to detect inconsistencies with the file header. void LoadExistingDatabase(); //! Creates a new Block using the specified block_id and returns a pointer @@ -45,6 +49,8 @@ class SingleFileBlockManager : public BlockManager { unique_ptr CreateBlock(block_id_t block_id, FileBuffer *source_buffer) override; //! Return the next free block id block_id_t GetFreeBlockId() override; + //! Check the next free block id - but do not assign or allocate it + block_id_t PeekFreeBlockId() override; //! Returns whether or not a specified block is the root block bool IsRootBlock(MetaBlockPointer root) override; //! Mark a block as free (immediately re-writeable) @@ -57,6 +63,8 @@ class SingleFileBlockManager : public BlockManager { idx_t GetMetaBlock() override; //! Read the content of the block from disk void Read(Block &block) override; + //! Read the content of a range of blocks into a buffer + void ReadBlocks(FileBuffer &buffer, block_id_t start_block, idx_t block_count) override; //! Write the given block to disk void Write(FileBuffer &block, block_id_t block_id) override; //! Write the header to disk, this is the final step of the checkpointing process @@ -64,20 +72,28 @@ class SingleFileBlockManager : public BlockManager { //! Truncate the underlying database file after a checkpoint void Truncate() override; + bool InMemory() override { + return false; + } //! Returns the number of total blocks idx_t TotalBlocks() override; //! Returns the number of free blocks idx_t FreeBlocks() override; + //! Whether or not the attached database is a remote file + bool IsRemote() override; private: - //! Load the free list from the file + //! Loads the free list of the file. void LoadFreeList(); - - void Initialize(DatabaseHeader &header); + //! Initializes the database header. We pass the provided block allocation size as a parameter + //! to detect inconsistencies with the file header. + void Initialize(const DatabaseHeader &header, const optional_idx block_alloc_size); void ReadAndChecksum(FileBuffer &handle, uint64_t location) const; void ChecksumAndWrite(FileBuffer &handle, uint64_t location) const; + idx_t GetBlockLocation(block_id_t block_id); + //! Return the blocks to which we will write the free list and modified blocks vector GetFreeListBlocks(); void TrimFreeBlocks(); diff --git a/src/include/duckdb/storage/standard_buffer_manager.hpp b/src/include/duckdb/storage/standard_buffer_manager.hpp index 91e54b8973c..272cb2161dc 100644 --- a/src/include/duckdb/storage/standard_buffer_manager.hpp +++ b/src/include/duckdb/storage/standard_buffer_manager.hpp @@ -43,10 +43,13 @@ class StandardBufferManager : public BufferManager { static unique_ptr ReadTemporaryBufferInternal(BufferManager &buffer_manager, FileHandle &handle, idx_t position, idx_t size, unique_ptr reusable_buffer); - //! Registers an in-memory buffer that cannot be unloaded until it is destroyed - //! This buffer can be small (smaller than BLOCK_SIZE) - //! Unpin and pin are nops on this block of memory - shared_ptr RegisterSmallMemory(idx_t block_size) final; + + //! Registers a transient memory buffer. + shared_ptr RegisterTransientMemory(const idx_t size) final; + //! Registers an in-memory buffer that cannot be unloaded until it is destroyed. + //! This buffer can be small (smaller than the block size of the temporary block manager). + //! Unpin and Pin are NOPs on this block of memory. + shared_ptr RegisterSmallMemory(const idx_t size) final; idx_t GetUsedMemory() const final; idx_t GetMaxMemory() const final; @@ -62,6 +65,7 @@ class StandardBufferManager : public BufferManager { void ReAllocate(shared_ptr &handle, idx_t block_size) final; BufferHandle Pin(shared_ptr &handle) final; + void Prefetch(vector> &handles) final; void Unpin(shared_ptr &handle) final; //! Set a new memory limit to the buffer manager, throws an exception if the new limit is too low and not enough @@ -109,7 +113,7 @@ class StandardBufferManager : public BufferManager { shared_ptr RegisterMemory(MemoryTag tag, idx_t block_size, bool can_destroy); //! Garbage collect eviction queue - void PurgeQueue() final; + void PurgeQueue(FileBufferType type) final; BufferPool &GetBufferPool() const final; TemporaryMemoryManager &GetTemporaryMemoryManager() final; @@ -139,6 +143,9 @@ class StandardBufferManager : public BufferManager { //! overwrites the data within with garbage. Any readers that do not hold the pin will notice void VerifyZeroReaders(shared_ptr &handle); + void BatchRead(vector> &handles, const map &load_map, + block_id_t first_block, block_id_t last_block); + protected: // These are stored here because temp_directory creation is lazy // so we need to store information related to the temporary directory before it's created diff --git a/src/include/duckdb/storage/storage_extension.hpp b/src/include/duckdb/storage/storage_extension.hpp index 369dd71a9c7..eece0b096fe 100644 --- a/src/include/duckdb/storage/storage_extension.hpp +++ b/src/include/duckdb/storage/storage_extension.hpp @@ -11,6 +11,7 @@ #include "duckdb/common/common.hpp" #include "duckdb/common/enums/access_mode.hpp" #include "duckdb/parser/tableref/table_function_ref.hpp" +#include "duckdb/storage/storage_manager.hpp" namespace duckdb { class AttachedDatabase; @@ -40,6 +41,12 @@ class StorageExtension { virtual ~StorageExtension() { } + + virtual void OnCheckpointStart(AttachedDatabase &db, CheckpointOptions checkpoint_options) { + } + + virtual void OnCheckpointEnd(AttachedDatabase &db, CheckpointOptions checkpoint_options) { + } }; } // namespace duckdb diff --git a/src/include/duckdb/storage/storage_info.hpp b/src/include/duckdb/storage/storage_info.hpp index e3d36025e68..ffb39fa6dd6 100644 --- a/src/include/duckdb/storage/storage_info.hpp +++ b/src/include/duckdb/storage/storage_info.hpp @@ -9,9 +9,9 @@ #pragma once #include "duckdb/common/constants.hpp" +#include "duckdb/common/limits.hpp" #include "duckdb/common/string.hpp" #include "duckdb/common/vector_size.hpp" -#include "duckdb/common/limits.hpp" namespace duckdb { struct FileHandle; @@ -22,8 +22,14 @@ struct FileHandle; #define INVALID_BLOCK (-1) //! The maximum block id is 2^62 #define MAXIMUM_BLOCK 4611686018427388000LL -//! The default block size -#define DEFAULT_BLOCK_ALLOC_SIZE 262144 +//! The default block allocation size. +#define DEFAULT_BLOCK_ALLOC_SIZE 262144ULL +//! The minimum block allocation size. This is the minimum size we test in our nightly tests. +#define MIN_BLOCK_ALLOC_SIZE 16384ULL + +#ifndef DUCKDB_BLOCK_ALLOC_SIZE +#define DUCKDB_BLOCK_ALLOC_SIZE DEFAULT_BLOCK_ALLOC_SIZE +#endif using block_id_t = int64_t; @@ -32,10 +38,10 @@ struct Storage { constexpr static idx_t SECTOR_SIZE = 4096U; //! Block header size for blocks written to the storage constexpr static idx_t BLOCK_HEADER_SIZE = sizeof(uint64_t); - //! Size of a memory slot managed by the StorageManager. This is the quantum of allocation for Blocks on DuckDB. We - //! default to 256KB. (1 << 18) - constexpr static idx_t BLOCK_ALLOC_SIZE = DEFAULT_BLOCK_ALLOC_SIZE; - //! The actual memory space that is available within the blocks + //! Size of a memory slot managed by the StorageManager and the BlockManager. + //! Defaults to DUCKDB_BLOCK_ALLOC_SIZE. + constexpr static idx_t BLOCK_ALLOC_SIZE = DUCKDB_BLOCK_ALLOC_SIZE; + //! The actual memory space that is available within a block. constexpr static idx_t BLOCK_SIZE = BLOCK_ALLOC_SIZE - BLOCK_HEADER_SIZE; //! The size of the headers. This should be small and written more or less atomically by the hard disk. We default //! to the page size, which is 4KB. (1 << 12) @@ -44,11 +50,17 @@ struct Storage { constexpr static const idx_t ROW_GROUP_SIZE = STANDARD_ROW_GROUPS_SIZE; //! The number of vectors per row group constexpr static const idx_t ROW_GROUP_VECTOR_COUNT = ROW_GROUP_SIZE / STANDARD_VECTOR_SIZE; + + //! Ensures that a user-provided block allocation size matches all requirements. + static void VerifyBlockAllocSize(const idx_t block_alloc_size); }; //! The version number of the database storage format extern const uint64_t VERSION_NUMBER; -const char *GetDuckDBVersion(idx_t version_number); +string GetDuckDBVersion(idx_t version_number); +optional_idx GetStorageVersion(const char *version_string); +optional_idx GetSerializationVersion(const char *version_string); +vector GetSerializationCandidates(); //! The MainHeader is the first header in the storage file. The MainHeader is typically written only once for a database //! file. @@ -94,8 +106,8 @@ struct DatabaseHeader { //! The number of blocks that is in the file as of this database header. If the file is larger than BLOCK_SIZE * //! block_count any blocks appearing AFTER block_count are implicitly part of the free_list. uint64_t block_count; - //! The block size of the database file - idx_t block_size; + //! The allocation size of blocks in this database file. Defaults to default_block_alloc_size (DBConfig). + idx_t block_alloc_size; //! The vector size of the database file idx_t vector_size; @@ -111,6 +123,21 @@ struct DatabaseHeader { #if (STANDARD_ROW_GROUPS_SIZE < STANDARD_VECTOR_SIZE) #error Row groups must be able to hold at least one vector #endif +#if (DEFAULT_BLOCK_ALLOC_SIZE & (DEFAULT_BLOCK_ALLOC_SIZE - 1) != 0) +#error The default block allocation size must be a power of two +#endif +#if (DUCKDB_BLOCK_ALLOC_SIZE & (DUCKDB_BLOCK_ALLOC_SIZE - 1) != 0) +#error The duckdb block allocation size must be a power of two +#endif +#if (MIN_BLOCK_ALLOC_SIZE & (MIN_BLOCK_ALLOC_SIZE - 1) != 0) +#error The minimum block allocation size must be a power of two +#endif +#if (DUCKDB_BLOCK_ALLOC_SIZE > 2147483647) +#error The duckdb block allocation size must not exceed the maximum value of a 32-bit signed integer +#endif +#if (DUCKDB_BLOCK_ALLOC_SIZE < MIN_BLOCK_ALLOC_SIZE) +#error The duckdb block allocation size must be greater or equal than the minimum block allocation size +#endif static_assert(Storage::BLOCK_ALLOC_SIZE % Storage::SECTOR_SIZE == 0, "the block allocation size has to be a multiple of the sector size"); diff --git a/src/include/duckdb/storage/storage_lock.hpp b/src/include/duckdb/storage/storage_lock.hpp index b8a6ceb81ac..739aef76439 100644 --- a/src/include/duckdb/storage/storage_lock.hpp +++ b/src/include/duckdb/storage/storage_lock.hpp @@ -11,42 +11,46 @@ #include "duckdb/common/constants.hpp" #include "duckdb/common/atomic.hpp" #include "duckdb/common/mutex.hpp" +#include "duckdb/common/shared_ptr.hpp" namespace duckdb { -class StorageLock; +struct StorageLockInternals; enum class StorageLockType { SHARED = 0, EXCLUSIVE = 1 }; class StorageLockKey { public: - StorageLockKey(StorageLock &lock, StorageLockType type); + StorageLockKey(shared_ptr internals, StorageLockType type); ~StorageLockKey(); + StorageLockType GetType() const { + return type; + } + private: - StorageLock &lock; + shared_ptr internals; StorageLockType type; }; class StorageLock { - friend class StorageLockKey; - public: StorageLock(); + ~StorageLock(); //! Get an exclusive lock unique_ptr GetExclusiveLock(); //! Get a shared lock unique_ptr GetSharedLock(); + //! Try to get an exclusive lock - if we cannot get it immediately we return `nullptr` + unique_ptr TryGetExclusiveLock(); + //! This is a special method that only exists for checkpointing + //! This method takes a shared lock, and returns an exclusive lock if the parameter is the only active shared lock + //! If this method succeeds, we have **both** a shared and exclusive lock active (which normally is not allowed) + //! But this behavior is required for checkpointing + unique_ptr TryUpgradeCheckpointLock(StorageLockKey &lock); private: - mutex exclusive_lock; - atomic read_count; - -private: - //! Release an exclusive lock - void ReleaseExclusiveLock(); - //! Release a shared lock - void ReleaseSharedLock(); + shared_ptr internals; }; } // namespace duckdb diff --git a/src/include/duckdb/storage/storage_manager.hpp b/src/include/duckdb/storage/storage_manager.hpp index e0c07b6b890..9ceed6d8557 100644 --- a/src/include/duckdb/storage/storage_manager.hpp +++ b/src/include/duckdb/storage/storage_manager.hpp @@ -14,6 +14,7 @@ #include "duckdb/storage/table_io_manager.hpp" #include "duckdb/storage/write_ahead_log.hpp" #include "duckdb/storage/database_size.hpp" +#include "duckdb/common/enums/checkpoint_type.hpp" namespace duckdb { class BlockManager; @@ -30,10 +31,23 @@ class StorageCommitState { virtual ~StorageCommitState() { } + //! Revert the commit + virtual void RevertCommit() = 0; // Make the commit persistent virtual void FlushCommit() = 0; }; +struct CheckpointOptions { + CheckpointOptions() + : wal_action(CheckpointWALAction::DONT_DELETE_WAL), action(CheckpointAction::CHECKPOINT_IF_REQUIRED), + type(CheckpointType::FULL_CHECKPOINT) { + } + + CheckpointWALAction wal_action; + CheckpointAction action; + CheckpointType type; +}; + //! StorageManager is responsible for managing the physical storage of the //! database on disk class StorageManager { @@ -45,35 +59,44 @@ class StorageManager { static StorageManager &Get(AttachedDatabase &db); static StorageManager &Get(Catalog &catalog); - //! Initialize a database or load an existing database from the given path - void Initialize(optional_ptr context); + //! Initialize a database or load an existing database from the database file path. The block_alloc_size is + //! either set, or invalid. If invalid, then DuckDB defaults to the default_block_alloc_size (DBConfig), + //! or the file's block allocation size, if it is an existing database. + void Initialize(const optional_idx block_alloc_size); DatabaseInstance &GetDatabase(); AttachedDatabase &GetAttached() { return db; } - //! Get the WAL of the StorageManager, returns nullptr if in-memory - optional_ptr GetWriteAheadLog(); + //! Gets the size of the WAL, or zero, if there is no WAL. + idx_t GetWALSize(); + //! Gets the WAL of the StorageManager, or nullptr, if there is no WAL. + optional_ptr GetWAL(); + //! Deletes the WAL file, and resets the unique pointer. + void ResetWAL(); //! Returns the database file path - string GetDBPath() { + string GetDBPath() const { return path; } + bool IsLoaded() const { + return load_complete; + } //! The path to the WAL, derived from the database file path string GetWALPath(); bool InMemory(); virtual bool AutomaticCheckpoint(idx_t estimated_wal_bytes) = 0; - virtual unique_ptr GenStorageCommitState(Transaction &transaction, bool checkpoint) = 0; + virtual unique_ptr GenStorageCommitState(WriteAheadLog &wal) = 0; virtual bool IsCheckpointClean(MetaBlockPointer checkpoint_id) = 0; - virtual void CreateCheckpoint(bool delete_wal = false, bool force_checkpoint = false) = 0; + virtual void CreateCheckpoint(CheckpointOptions options = CheckpointOptions()) = 0; virtual DatabaseSize GetDatabaseSize() = 0; virtual vector GetMetadataInfo() = 0; virtual shared_ptr GetTableIOManager(BoundCreateTableInfo *info) = 0; protected: - virtual void LoadDatabase(optional_ptr context = nullptr) = 0; + virtual void LoadDatabase(const optional_idx block_alloc_size) = 0; protected: //! The database this storage manager belongs to @@ -104,6 +127,7 @@ class StorageManager { //! Stores database in a single file. class SingleFileStorageManager : public StorageManager { public: + SingleFileStorageManager() = delete; SingleFileStorageManager(AttachedDatabase &db, string path, bool read_only); //! The BlockManager to read/store meta information and data in blocks @@ -113,14 +137,14 @@ class SingleFileStorageManager : public StorageManager { public: bool AutomaticCheckpoint(idx_t estimated_wal_bytes) override; - unique_ptr GenStorageCommitState(Transaction &transaction, bool checkpoint) override; + unique_ptr GenStorageCommitState(WriteAheadLog &wal) override; bool IsCheckpointClean(MetaBlockPointer checkpoint_id) override; - void CreateCheckpoint(bool delete_wal, bool force_checkpoint) override; + void CreateCheckpoint(CheckpointOptions options) override; DatabaseSize GetDatabaseSize() override; vector GetMetadataInfo() override; shared_ptr GetTableIOManager(BoundCreateTableInfo *info) override; protected: - void LoadDatabase(optional_ptr context = nullptr) override; + void LoadDatabase(const optional_idx block_alloc_size) override; }; } // namespace duckdb diff --git a/src/include/duckdb/storage/string_uncompressed.hpp b/src/include/duckdb/storage/string_uncompressed.hpp index a57b851eb86..58a780a1b28 100644 --- a/src/include/duckdb/storage/string_uncompressed.hpp +++ b/src/include/duckdb/storage/string_uncompressed.hpp @@ -1,5 +1,14 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/string_uncompressed.hpp +// +// +//===----------------------------------------------------------------------===// + #pragma once +#include "duckdb/common/likely.hpp" #include "duckdb/common/types/null_value.hpp" #include "duckdb/common/types/vector.hpp" #include "duckdb/common/vector_size.hpp" @@ -9,17 +18,16 @@ #include "duckdb/storage/buffer_manager.hpp" #include "duckdb/storage/checkpoint/string_checkpoint_state.hpp" #include "duckdb/storage/segment/uncompressed.hpp" -#include "duckdb/storage/table/scan_state.hpp" #include "duckdb/storage/string_uncompressed.hpp" #include "duckdb/storage/table/append_state.hpp" #include "duckdb/storage/table/column_segment.hpp" -#include "duckdb/common/likely.hpp" +#include "duckdb/storage/table/scan_state.hpp" namespace duckdb { struct StringDictionaryContainer { //! The size of the dictionary uint32_t size; - //! The end of the dictionary (typically Storage::BLOCK_SIZE) + //! The end of the dictionary, which defaults to the block size. uint32_t end; void Verify() { @@ -43,8 +51,6 @@ struct UncompressedStringStorage { static constexpr idx_t BIG_STRING_MARKER_BASE_SIZE = sizeof(block_id_t) + sizeof(int32_t); //! The marker size of the big string static constexpr idx_t BIG_STRING_MARKER_SIZE = BIG_STRING_MARKER_BASE_SIZE; - //! The size below which the segment is compacted on flushing - static constexpr size_t COMPACTION_FLUSH_LIMIT = (size_t)Storage::BLOCK_SIZE / 5 * 4; public: static unique_ptr StringInitAnalyze(ColumnData &col_data, PhysicalType type); @@ -150,7 +156,8 @@ struct UncompressedStringStorage { // place the dictionary offset into the set of vectors // note: for overflow strings we write negative value - D_ASSERT(*dictionary_size <= int32_t(Storage::BLOCK_SIZE)); + // dictionary_size is an uint32_t value, so we can cast up. + D_ASSERT(NumericCast(*dictionary_size) <= Storage::BLOCK_SIZE); result_data[target_idx] = -NumericCast((*dictionary_size)); } else { // string fits in block, append to dictionary and increment dictionary position @@ -161,8 +168,9 @@ struct UncompressedStringStorage { // now write the actual string data into the dictionary memcpy(dict_pos, source_data[source_idx].GetData(), string_length); - // place the dictionary offset into the set of vectors - D_ASSERT(*dictionary_size <= int32_t(Storage::BLOCK_SIZE)); + // dictionary_size is an uint32_t value, so we can cast up. + D_ASSERT(NumericCast(*dictionary_size) <= Storage::BLOCK_SIZE); + // Place the dictionary offset into the set of vectors. result_data[target_idx] = NumericCast(*dictionary_size); } D_ASSERT(RemainingSpace(segment, handle) <= Storage::BLOCK_SIZE); @@ -193,10 +201,10 @@ struct UncompressedStringStorage { static void WriteStringMarker(data_ptr_t target, block_id_t block_id, int32_t offset); static void ReadStringMarker(data_ptr_t target, block_id_t &block_id, int32_t &offset); - static string_location_t FetchStringLocation(StringDictionaryContainer dict, data_ptr_t baseptr, - int32_t dict_offset); + static string_location_t FetchStringLocation(StringDictionaryContainer dict, data_ptr_t base_ptr, + int32_t dict_offset, const idx_t block_size); static string_t FetchStringFromDict(ColumnSegment &segment, StringDictionaryContainer dict, Vector &result, - data_ptr_t baseptr, int32_t dict_offset, uint32_t string_length); + data_ptr_t base_ptr, int32_t dict_offset, uint32_t string_length); static string_t FetchString(ColumnSegment &segment, StringDictionaryContainer dict, Vector &result, data_ptr_t baseptr, string_location_t location, uint32_t string_length); diff --git a/src/include/duckdb/storage/table/append_state.hpp b/src/include/duckdb/storage/table/append_state.hpp index 4488e0aaa79..0e22d17b941 100644 --- a/src/include/duckdb/storage/table/append_state.hpp +++ b/src/include/duckdb/storage/table/append_state.hpp @@ -22,6 +22,7 @@ class DataTable; class LocalTableStorage; class RowGroup; class UpdateSegment; +class TableCatalogEntry; struct TableAppendState; diff --git a/src/include/duckdb/storage/table/array_column_data.hpp b/src/include/duckdb/storage/table/array_column_data.hpp index 2e676045324..eb1c865a48c 100644 --- a/src/include/duckdb/storage/table/array_column_data.hpp +++ b/src/include/duckdb/storage/table/array_column_data.hpp @@ -28,11 +28,14 @@ class ArrayColumnData : public ColumnData { void SetStart(idx_t new_start) override; bool CheckZonemap(ColumnScanState &state, TableFilter &filter) override; + void InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state, idx_t rows) override; void InitializeScan(ColumnScanState &state) override; void InitializeScanWithOffset(ColumnScanState &state, idx_t row_idx) override; - idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result) override; - idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates) override; + idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t scan_count) override; + idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates, + idx_t scan_count) override; idx_t ScanCount(ColumnScanState &state, Vector &result, idx_t count) override; void Skip(ColumnScanState &state, idx_t count = STANDARD_VECTOR_SIZE) override; @@ -53,8 +56,7 @@ class ArrayColumnData : public ColumnData { unique_ptr CreateCheckpointState(RowGroup &row_group, PartialBlockManager &partial_block_manager) override; - unique_ptr Checkpoint(RowGroup &row_group, PartialBlockManager &partial_block_manager, - ColumnCheckpointInfo &checkpoint_info) override; + unique_ptr Checkpoint(RowGroup &row_group, ColumnCheckpointInfo &info) override; void DeserializeColumn(Deserializer &source, BaseStatistics &target_stats) override; diff --git a/src/include/duckdb/storage/table/column_data.hpp b/src/include/duckdb/storage/table/column_data.hpp index 55020f589cc..28cd114376f 100644 --- a/src/include/duckdb/storage/table/column_data.hpp +++ b/src/include/duckdb/storage/table/column_data.hpp @@ -16,6 +16,7 @@ #include "duckdb/storage/table/segment_tree.hpp" #include "duckdb/storage/table/column_segment_tree.hpp" #include "duckdb/common/mutex.hpp" +#include "duckdb/common/enums/scan_vector_type.hpp" namespace duckdb { class ColumnData; @@ -25,14 +26,21 @@ class RowGroup; class RowGroupWriter; class TableDataWriter; class TableStorageInfo; -struct TransactionData; -struct TableScanOptions; - struct DataTableInfo; +struct PrefetchState; +struct RowGroupWriteInfo; +struct TableScanOptions; +struct TransactionData; struct ColumnCheckpointInfo { - explicit ColumnCheckpointInfo(CompressionType compression_type_p) : compression_type(compression_type_p) {}; - CompressionType compression_type; + ColumnCheckpointInfo(RowGroupWriteInfo &info, idx_t column_idx) : info(info), column_idx(column_idx) { + } + + RowGroupWriteInfo &info; + idx_t column_idx; + +public: + CompressionType GetCompressionType(); }; class ColumnData { @@ -46,7 +54,7 @@ class ColumnData { //! The start row idx_t start; //! The count of the column data - idx_t count; + atomic count; //! The block manager BlockManager &block_manager; //! Table info for the column @@ -76,17 +84,27 @@ class ColumnData { //! The root type of the column const LogicalType &RootType() const; //! Whether or not the column has any updates - virtual bool HasUpdates() const; + bool HasUpdates() const; + //! Whether or not we can scan an entire vector + virtual ScanVectorType GetVectorScanType(ColumnScanState &state, idx_t scan_count); + //! Initialize prefetch state with required I/O data for the next N rows + virtual void InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state, idx_t rows); //! Initialize a scan of the column virtual void InitializeScan(ColumnScanState &state); //! Initialize a scan starting at the specified offset virtual void InitializeScanWithOffset(ColumnScanState &state, idx_t row_idx); //! Scan the next vector from the column - virtual idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result); - virtual idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates); + idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result); + idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates); + virtual idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t scan_count); + virtual idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates, + idx_t scan_count); + virtual void ScanCommittedRange(idx_t row_group_start, idx_t offset_in_row_group, idx_t count, Vector &result); virtual idx_t ScanCount(ColumnScanState &state, Vector &result, idx_t count); + //! Select virtual void Select(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, SelectionVector &sel, idx_t &count, const TableFilter &filter); @@ -124,8 +142,7 @@ class ColumnData { virtual unique_ptr CreateCheckpointState(RowGroup &row_group, PartialBlockManager &partial_block_manager); - virtual unique_ptr - Checkpoint(RowGroup &row_group, PartialBlockManager &partial_block_manager, ColumnCheckpointInfo &checkpoint_info); + virtual unique_ptr Checkpoint(RowGroup &row_group, ColumnCheckpointInfo &info); virtual void CheckpointScan(ColumnSegment &segment, ColumnScanState &state, idx_t row_group_start, idx_t count, Vector &scan_vector); @@ -155,11 +172,12 @@ class ColumnData { void AppendTransientSegment(SegmentLock &l, idx_t start_row); //! Scans a base vector from the column - idx_t ScanVector(ColumnScanState &state, Vector &result, idx_t remaining, bool has_updates); + idx_t ScanVector(ColumnScanState &state, Vector &result, idx_t remaining, ScanVectorType scan_type); //! Scans a vector from the column merged with any potential updates //! If ALLOW_UPDATES is set to false, the function will instead throw an exception if any updates are found template - idx_t ScanVector(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result); + idx_t ScanVector(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t target_scan); void ClearUpdates(); void FetchUpdates(TransactionData transaction, idx_t vector_index, Vector &result, idx_t scan_count, @@ -168,6 +186,8 @@ class ColumnData { void UpdateInternal(TransactionData transaction, idx_t column_index, Vector &update_vector, row_t *row_ids, idx_t update_count, Vector &base_vector); + idx_t GetVectorCount(idx_t vector_index) const; + protected: //! The segments holding the data of this column segment ColumnSegmentTree data; @@ -175,6 +195,8 @@ class ColumnData { mutable mutex update_lock; //! The updates for this column segment unique_ptr updates; + //! The lock for the stats + mutable mutex stats_lock; //! The stats of the root segment unique_ptr stats; //! Total transient allocation size diff --git a/src/include/duckdb/storage/table/column_segment.hpp b/src/include/duckdb/storage/table/column_segment.hpp index fa11971603a..f172c812c18 100644 --- a/src/include/duckdb/storage/table/column_segment.hpp +++ b/src/include/duckdb/storage/table/column_segment.hpp @@ -8,15 +8,16 @@ #pragma once -#include "duckdb/storage/block.hpp" +#include "duckdb/common/enums/scan_vector_type.hpp" #include "duckdb/common/types.hpp" #include "duckdb/common/types/vector.hpp" +#include "duckdb/function/compression_function.hpp" +#include "duckdb/storage/block.hpp" +#include "duckdb/storage/buffer/block_handle.hpp" #include "duckdb/storage/buffer_manager.hpp" #include "duckdb/storage/statistics/segment_statistics.hpp" #include "duckdb/storage/storage_lock.hpp" -#include "duckdb/function/compression_function.hpp" #include "duckdb/storage/table/segment_base.hpp" -#include "duckdb/storage/buffer/block_handle.hpp" namespace duckdb { class ColumnSegment; @@ -30,6 +31,7 @@ class TableFilter; struct ColumnFetchState; struct ColumnScanState; struct ColumnAppendState; +struct PrefetchState; enum class ColumnSegmentType : uint8_t { TRANSIENT, PERSISTENT }; //! TableFilter represents a filter pushed down into the table scan. @@ -58,13 +60,15 @@ class ColumnSegment : public SegmentBase { idx_t start, idx_t count, CompressionType compression_type, BaseStatistics statistics, unique_ptr segment_state); - static unique_ptr CreateTransientSegment(DatabaseInstance &db, const LogicalType &type, idx_t start, - idx_t segment_size = Storage::BLOCK_SIZE); + static unique_ptr CreateTransientSegment(DatabaseInstance &db, const LogicalType &type, + const idx_t start, + const idx_t segment_size = Storage::BLOCK_SIZE); public: + void InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state); void InitializeScan(ColumnScanState &state); //! Scan one vector from this segment - void Scan(ColumnScanState &state, idx_t scan_count, Vector &result, idx_t result_offset, bool entire_vector); + void Scan(ColumnScanState &state, idx_t scan_count, Vector &result, idx_t result_offset, ScanVectorType scan_type); //! Fetch a value of the specific row id and append it to the result void FetchRow(ColumnFetchState &state, row_t row_id, Vector &result, idx_t result_idx); @@ -102,6 +106,9 @@ class ColumnSegment : public SegmentBase { return block_id; } + //! Returns the block manager handling this segment. For transient segments, this might be the temporary block + //! manager. Later, we possibly convert this (transient) segment to a persistent segment. In that case, there + //! exists another block manager handling the ColumnData, of which this segment is a part. BlockManager &GetBlockManager() const { return block->block_manager; } @@ -124,11 +131,15 @@ class ColumnSegment : public SegmentBase { void CommitDropSegment(); public: - ColumnSegment(DatabaseInstance &db, shared_ptr block, LogicalType type, ColumnSegmentType segment_type, - idx_t start, idx_t count, CompressionFunction &function, BaseStatistics statistics, - block_id_t block_id, idx_t offset, idx_t segment_size, - unique_ptr segment_state = nullptr); - ColumnSegment(ColumnSegment &other, idx_t start); + //! Construct a column segment. + ColumnSegment(DatabaseInstance &db, shared_ptr block, const LogicalType &type, + const ColumnSegmentType segment_type, const idx_t start, const idx_t count, + CompressionFunction &function_p, BaseStatistics statistics, const block_id_t block_id_p, + const idx_t offset, const idx_t segment_size_p, + unique_ptr segment_state_p = nullptr); + //! Construct a column segment from another column segment. + //! The other column segment becomes invalid (std::move). + ColumnSegment(ColumnSegment &other, const idx_t start); private: void Scan(ColumnScanState &state, idx_t scan_count, Vector &result); diff --git a/src/include/duckdb/storage/table/data_table_info.hpp b/src/include/duckdb/storage/table/data_table_info.hpp index 598d80e222b..e7fa3bd3757 100644 --- a/src/include/duckdb/storage/table/data_table_info.hpp +++ b/src/include/duckdb/storage/table/data_table_info.hpp @@ -11,25 +11,51 @@ #include "duckdb/common/atomic.hpp" #include "duckdb/common/common.hpp" #include "duckdb/storage/table/table_index_list.hpp" +#include "duckdb/storage/storage_lock.hpp" namespace duckdb { class DatabaseInstance; class TableIOManager; struct DataTableInfo { + friend class DataTable; + +public: DataTableInfo(AttachedDatabase &db, shared_ptr table_io_manager_p, string schema, string table); //! Initialize any unknown indexes whose types might now be present after an extension load, optionally throwing an //! exception if an index can't be initialized - void InitializeIndexes(ClientContext &context, bool throw_on_failure = false); + void InitializeIndexes(ClientContext &context, const char *index_type = nullptr); + + //! Whether or not the table is temporary + bool IsTemporary() const; + + AttachedDatabase &GetDB() { + return db; + } + + TableIOManager &GetIOManager() { + return *table_io_manager; + } + TableIndexList &GetIndexes() { + return indexes; + } + const vector &GetIndexStorageInfo() const { + return index_storage_infos; + } + + string GetSchemaName(); + string GetTableName(); + void SetTableName(string name); + +private: //! The database instance of the table AttachedDatabase &db; //! The table IO manager shared_ptr table_io_manager; - //! The amount of elements in the table. Note that this number signifies the amount of COMMITTED entries in the - //! table. It can be inaccurate inside of transactions. More work is needed to properly support that. - atomic cardinality; + //! Lock for modifying the name + mutex name_lock; //! The schema of the table string schema; //! The name of the table @@ -38,8 +64,8 @@ struct DataTableInfo { TableIndexList indexes; //! Index storage information of the indexes created by this table vector index_storage_infos; - - bool IsTemporary() const; + //! Lock held while checkpointing + StorageLock checkpoint_lock; }; } // namespace duckdb diff --git a/src/include/duckdb/storage/table/list_column_data.hpp b/src/include/duckdb/storage/table/list_column_data.hpp index 3140ea37aa7..0287cffa317 100644 --- a/src/include/duckdb/storage/table/list_column_data.hpp +++ b/src/include/duckdb/storage/table/list_column_data.hpp @@ -28,11 +28,14 @@ class ListColumnData : public ColumnData { void SetStart(idx_t new_start) override; bool CheckZonemap(ColumnScanState &state, TableFilter &filter) override; + void InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state, idx_t rows) override; void InitializeScan(ColumnScanState &state) override; void InitializeScanWithOffset(ColumnScanState &state, idx_t row_idx) override; - idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result) override; - idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates) override; + idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t scan_count) override; + idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates, + idx_t scan_count) override; idx_t ScanCount(ColumnScanState &state, Vector &result, idx_t count) override; void Skip(ColumnScanState &state, idx_t count = STANDARD_VECTOR_SIZE) override; @@ -53,8 +56,7 @@ class ListColumnData : public ColumnData { unique_ptr CreateCheckpointState(RowGroup &row_group, PartialBlockManager &partial_block_manager) override; - unique_ptr Checkpoint(RowGroup &row_group, PartialBlockManager &partial_block_manager, - ColumnCheckpointInfo &checkpoint_info) override; + unique_ptr Checkpoint(RowGroup &row_group, ColumnCheckpointInfo &info) override; void DeserializeColumn(Deserializer &deserializer, BaseStatistics &target_stats) override; diff --git a/src/include/duckdb/storage/table/row_group.hpp b/src/include/duckdb/storage/table/row_group.hpp index 6265279f52c..43bf21ca604 100644 --- a/src/include/duckdb/storage/table/row_group.hpp +++ b/src/include/duckdb/storage/table/row_group.hpp @@ -17,6 +17,7 @@ #include "duckdb/parser/column_list.hpp" #include "duckdb/storage/table/segment_base.hpp" #include "duckdb/storage/block.hpp" +#include "duckdb/common/enums/checkpoint_type.hpp" namespace duckdb { class AttachedDatabase; @@ -43,6 +44,17 @@ struct RowGroupAppendState; class MetadataManager; class RowVersionManager; +struct RowGroupWriteInfo { + RowGroupWriteInfo(PartialBlockManager &manager, const vector &compression_types, + CheckpointType checkpoint_type = CheckpointType::FULL_CHECKPOINT) + : manager(manager), compression_types(compression_types), checkpoint_type(checkpoint_type) { + } + + PartialBlockManager &manager; + const vector &compression_types; + CheckpointType checkpoint_type; +}; + struct RowGroupWriteData { vector> states; vector statistics; @@ -77,7 +89,7 @@ class RowGroup : public SegmentBase { ExpressionExecutor &executor, CollectionScanState &scan_state, DataChunk &scan_chunk); unique_ptr AddColumn(RowGroupCollection &collection, ColumnDefinition &new_column, - ExpressionExecutor &executor, Expression &default_value, Vector &intermediate); + ExpressionExecutor &executor, Vector &intermediate); unique_ptr RemoveColumn(RowGroupCollection &collection, idx_t removed_column); void CommitDrop(); @@ -117,7 +129,7 @@ class RowGroup : public SegmentBase { //! Delete the given set of rows in the version manager idx_t Delete(TransactionData transaction, DataTable &table, row_t *row_ids, idx_t count); - RowGroupWriteData WriteToDisk(PartialBlockManager &manager, const vector &compression_types); + RowGroupWriteData WriteToDisk(RowGroupWriteInfo &info); //! Returns the number of committed rows (count - committed deletes) idx_t GetCommittedRowCount(); RowGroupWriteData WriteToDisk(RowGroupWriter &writer); @@ -171,7 +183,6 @@ class RowGroup : public SegmentBase { private: mutex row_group_lock; - mutex stats_lock; vector column_pointers; unique_ptr[]> is_loaded; vector deletes_pointers; diff --git a/src/include/duckdb/storage/table/row_group_collection.hpp b/src/include/duckdb/storage/table/row_group_collection.hpp index 85d99ba1950..251377b338e 100644 --- a/src/include/duckdb/storage/table/row_group_collection.hpp +++ b/src/include/duckdb/storage/table/row_group_collection.hpp @@ -90,7 +90,8 @@ class RowGroupCollection { void Checkpoint(TableDataWriter &writer, TableStatistics &global_stats); - void InitializeVacuumState(VacuumState &state, vector> &segments); + void InitializeVacuumState(CollectionCheckpointState &checkpoint_state, VacuumState &state, + vector> &segments); bool ScheduleVacuumTasks(CollectionCheckpointState &checkpoint_state, VacuumState &state, idx_t segment_idx); void ScheduleCheckpointTask(CollectionCheckpointState &checkpoint_state, idx_t segment_idx); @@ -101,7 +102,7 @@ class RowGroupCollection { const vector &GetTypes() const; shared_ptr AddColumn(ClientContext &context, ColumnDefinition &new_column, - Expression &default_value); + ExpressionExecutor &default_executor); shared_ptr RemoveColumn(idx_t col_idx); shared_ptr AlterType(ClientContext &context, idx_t changed_idx, const LogicalType &target_type, vector bound_columns, Expression &cast_expr); diff --git a/src/include/duckdb/storage/table/scan_state.hpp b/src/include/duckdb/storage/table/scan_state.hpp index 5c477d15fc0..4579dd930fa 100644 --- a/src/include/duckdb/storage/table/scan_state.hpp +++ b/src/include/duckdb/storage/table/scan_state.hpp @@ -9,6 +9,7 @@ #pragma once #include "duckdb/common/common.hpp" +#include "duckdb/common/map.hpp" #include "duckdb/storage/buffer/buffer_handle.hpp" #include "duckdb/storage/storage_lock.hpp" #include "duckdb/common/enums/scan_options.hpp" @@ -128,6 +129,8 @@ class CollectionScanState { idx_t max_row; //! The current batch index idx_t batch_index; + //! The valid selection + SelectionVector valid_sel; RandomEngine random; @@ -160,6 +163,8 @@ class TableScanState { CollectionScanState local_state; //! Options for scanning TableScanOptions options; + //! Shared lock over the checkpoint to prevent checkpoints while reading + unique_ptr checkpoint_lock; public: void Initialize(vector column_ids, TableFilterSet *table_filters = nullptr); @@ -195,6 +200,16 @@ struct ParallelTableScanState { ParallelCollectionScanState scan_state; //! Parallel scan state for the transaction-local state ParallelCollectionScanState local_state; + //! Shared lock over the checkpoint to prevent checkpoints while reading + unique_ptr checkpoint_lock; +}; + +struct PrefetchState { + ~PrefetchState(); + + void AddBlock(shared_ptr block); + + vector> blocks; }; class CreateIndexScanState : public TableScanState { diff --git a/src/include/duckdb/storage/table/standard_column_data.hpp b/src/include/duckdb/storage/table/standard_column_data.hpp index 9ad0780d0eb..3d5c28c70ae 100644 --- a/src/include/duckdb/storage/table/standard_column_data.hpp +++ b/src/include/duckdb/storage/table/standard_column_data.hpp @@ -23,16 +23,18 @@ class StandardColumnData : public ColumnData { ValidityColumnData validity; public: - bool HasUpdates() const override; - void SetStart(idx_t new_start) override; bool CheckZonemap(ColumnScanState &state, TableFilter &filter) override; + ScanVectorType GetVectorScanType(ColumnScanState &state, idx_t scan_count) override; + void InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state, idx_t rows) override; void InitializeScan(ColumnScanState &state) override; void InitializeScanWithOffset(ColumnScanState &state, idx_t row_idx) override; - idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result) override; - idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates) override; + idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t target_count) override; + idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates, + idx_t target_count) override; idx_t ScanCount(ColumnScanState &state, Vector &result, idx_t count) override; void InitializeAppend(ColumnAppendState &state) override; @@ -51,8 +53,7 @@ class StandardColumnData : public ColumnData { unique_ptr CreateCheckpointState(RowGroup &row_group, PartialBlockManager &partial_block_manager) override; - unique_ptr Checkpoint(RowGroup &row_group, PartialBlockManager &partial_block_manager, - ColumnCheckpointInfo &checkpoint_info) override; + unique_ptr Checkpoint(RowGroup &row_group, ColumnCheckpointInfo &info) override; void CheckpointScan(ColumnSegment &segment, ColumnScanState &state, idx_t row_group_start, idx_t count, Vector &scan_vector) override; diff --git a/src/include/duckdb/storage/table/struct_column_data.hpp b/src/include/duckdb/storage/table/struct_column_data.hpp index 723b2b9f4e8..79e3403de3b 100644 --- a/src/include/duckdb/storage/table/struct_column_data.hpp +++ b/src/include/duckdb/storage/table/struct_column_data.hpp @@ -29,11 +29,14 @@ class StructColumnData : public ColumnData { bool CheckZonemap(ColumnScanState &state, TableFilter &filter) override; idx_t GetMaxEntry() override; + void InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state, idx_t rows) override; void InitializeScan(ColumnScanState &state) override; void InitializeScanWithOffset(ColumnScanState &state, idx_t row_idx) override; - idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result) override; - idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates) override; + idx_t Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t scan_count) override; + idx_t ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates, + idx_t scan_count) override; idx_t ScanCount(ColumnScanState &state, Vector &result, idx_t count) override; void Skip(ColumnScanState &state, idx_t count = STANDARD_VECTOR_SIZE) override; @@ -54,8 +57,7 @@ class StructColumnData : public ColumnData { unique_ptr CreateCheckpointState(RowGroup &row_group, PartialBlockManager &partial_block_manager) override; - unique_ptr Checkpoint(RowGroup &row_group, PartialBlockManager &partial_block_manager, - ColumnCheckpointInfo &checkpoint_info) override; + unique_ptr Checkpoint(RowGroup &row_group, ColumnCheckpointInfo &info) override; void DeserializeColumn(Deserializer &source, BaseStatistics &target_stats) override; diff --git a/src/include/duckdb/storage/table/table_index_list.hpp b/src/include/duckdb/storage/table/table_index_list.hpp index 397bf28243c..2520ba5c886 100644 --- a/src/include/duckdb/storage/table/table_index_list.hpp +++ b/src/include/duckdb/storage/table/table_index_list.hpp @@ -10,6 +10,7 @@ #include "duckdb/common/mutex.hpp" #include "duckdb/storage/index.hpp" +#include "duckdb/parser/constraint.hpp" namespace duckdb { @@ -29,6 +30,29 @@ class TableIndexList { } } } + + //! Scan the indexes, invoking the callback method for every bound entry of a specific type + template + void ScanBound(FUNC &&callback) { + lock_guard lock(indexes_lock); + for (auto &index : indexes) { + if (index->IsBound() && T::TYPE_NAME == index->GetIndexType()) { + if (callback(index->Cast())) { + break; + } + } + } + } + + // Bind any unbound indexes of the specified type and invoke the callback method for every bound entry of the + // specified type, regardless if it was bound before or not + template + void BindAndScan(ClientContext &context, DataTableInfo &table_info, FUNC &&callback) { + // FIXME: optimize this by only looping through the indexes once without re-acquiring the lock + InitializeIndexes(context, table_info, T::TYPE_NAME); + ScanBound(callback); + } + //! Returns a reference to the indexes of this table const vector> &Indexes() const { return indexes; @@ -43,7 +67,7 @@ class TableIndexList { bool NameIsUnique(const string &name); //! Initializes unknown indexes that might now be present after an extension load, optionally throwing an exception //! if a index cant be initialized - void InitializeIndexes(ClientContext &context, DataTableInfo &table_info, bool throw_on_failure = false); + void InitializeIndexes(ClientContext &context, DataTableInfo &table_info, const char *index_type = nullptr); bool Empty(); idx_t Count(); void Move(TableIndexList &other); diff --git a/src/include/duckdb/storage/table/table_statistics.hpp b/src/include/duckdb/storage/table/table_statistics.hpp index 05837184055..633d469463c 100644 --- a/src/include/duckdb/storage/table/table_statistics.hpp +++ b/src/include/duckdb/storage/table/table_statistics.hpp @@ -43,8 +43,11 @@ class TableStatistics { void MergeStats(TableStatisticsLock &lock, idx_t i, BaseStatistics &stats); void CopyStats(TableStatistics &other); + void CopyStats(TableStatisticsLock &lock, TableStatistics &other); unique_ptr CopyStats(idx_t i); - ColumnStatistics &GetStats(idx_t i); + //! Get a reference to the stats - this requires us to hold the lock. + //! The reference can only be safely accessed while the lock is held + ColumnStatistics &GetStats(TableStatisticsLock &lock, idx_t i); bool Empty(); @@ -55,7 +58,7 @@ class TableStatistics { private: //! The statistics lock - mutex stats_lock; + shared_ptr stats_lock; //! Column statistics vector> column_stats; //! The table sample diff --git a/src/include/duckdb/storage/table/validity_column_data.hpp b/src/include/duckdb/storage/table/validity_column_data.hpp index ba203d35b26..d02d09f95a6 100644 --- a/src/include/duckdb/storage/table/validity_column_data.hpp +++ b/src/include/duckdb/storage/table/validity_column_data.hpp @@ -20,6 +20,7 @@ class ValidityColumnData : public ColumnData { public: bool CheckZonemap(ColumnScanState &state, TableFilter &filter) override; + void AppendData(BaseStatistics &stats, ColumnAppendState &state, UnifiedVectorFormat &vdata, idx_t count) override; }; } // namespace duckdb diff --git a/src/include/duckdb/storage/write_ahead_log.hpp b/src/include/duckdb/storage/write_ahead_log.hpp index 6398a20b718..3becc04c8a1 100644 --- a/src/include/duckdb/storage/write_ahead_log.hpp +++ b/src/include/duckdb/storage/write_ahead_log.hpp @@ -44,24 +44,24 @@ class WriteAheadLogDeserializer; class WriteAheadLog { public: //! Initialize the WAL in the specified directory - explicit WriteAheadLog(AttachedDatabase &database, const string &path); + explicit WriteAheadLog(AttachedDatabase &database, const string &wal_path); virtual ~WriteAheadLog(); - //! Skip writing to the WAL - bool skip_writing; - public: //! Replay the WAL static bool Replay(AttachedDatabase &database, unique_ptr handle); - //! Returns the current size of the WAL in bytes - int64_t GetWALSize(); + //! Gets the total bytes written to the WAL since startup + idx_t GetWALSize(); //! Gets the total bytes written to the WAL since startup idx_t GetTotalWritten(); - BufferedFileWriter &GetWriter() { - return *writer; + //! A WAL is initialized, if a writer to a file exists. + bool Initialized() { + return initialized; } + //! Initializes the file of the WAL by creating the file writer. + BufferedFileWriter &Initialize(); void WriteVersion(); @@ -76,7 +76,7 @@ class WriteAheadLog { void WriteCreateSequence(const SequenceCatalogEntry &entry); void WriteDropSequence(const SequenceCatalogEntry &entry); - void WriteSequenceValue(const SequenceCatalogEntry &entry, SequenceValue val); + void WriteSequenceValue(SequenceValue val); void WriteCreateMacro(const ScalarMacroCatalogEntry &entry); void WriteDropMacro(const ScalarMacroCatalogEntry &entry); @@ -90,7 +90,7 @@ class WriteAheadLog { void WriteCreateType(const TypeCatalogEntry &entry); void WriteDropType(const TypeCatalogEntry &entry); //! Sets the table used for subsequent insert/delete/update commands - void WriteSetTable(string &schema, string &table); + void WriteSetTable(const string &schema, const string &table); void WriteAlter(const AlterInfo &info); @@ -107,7 +107,7 @@ class WriteAheadLog { void WriteUpdate(DataChunk &chunk, const vector &column_path); //! Truncate the WAL to a previous size, and clear anything currently set in the writer - void Truncate(int64_t size); + void Truncate(idx_t size); //! Delete the WAL file on disk. The WAL should not be used after this point. void Delete(); void Flush(); @@ -118,6 +118,8 @@ class WriteAheadLog { AttachedDatabase &database; unique_ptr writer; string wal_path; + atomic wal_size; + atomic initialized; }; } // namespace duckdb diff --git a/src/include/duckdb/transaction/commit_state.hpp b/src/include/duckdb/transaction/commit_state.hpp index 3b005c4dcfb..d92056d3679 100644 --- a/src/include/duckdb/transaction/commit_state.hpp +++ b/src/include/duckdb/transaction/commit_state.hpp @@ -23,29 +23,17 @@ struct UpdateInfo; class CommitState { public: - explicit CommitState(transaction_t commit_id, optional_ptr log = nullptr); - - optional_ptr log; - transaction_t commit_id; - UndoFlags current_op; - - optional_ptr current_table_info; - idx_t row_identifiers[STANDARD_VECTOR_SIZE]; - - unique_ptr delete_chunk; - unique_ptr update_chunk; + explicit CommitState(transaction_t commit_id); public: - template void CommitEntry(UndoFlags type, data_ptr_t data); void RevertCommit(UndoFlags type, data_ptr_t data); private: - void SwitchTable(DataTableInfo *table, UndoFlags new_op); + void CommitEntryDrop(CatalogEntry &entry, data_ptr_t extra_data); - void WriteCatalogEntry(CatalogEntry &entry, data_ptr_t extra_data); - void WriteDelete(DeleteInfo &info); - void WriteUpdate(UpdateInfo &info); +private: + transaction_t commit_id; }; } // namespace duckdb diff --git a/src/include/duckdb/transaction/duck_transaction.hpp b/src/include/duckdb/transaction/duck_transaction.hpp index 858072650a9..3b84f55c2f1 100644 --- a/src/include/duckdb/transaction/duck_transaction.hpp +++ b/src/include/duckdb/transaction/duck_transaction.hpp @@ -9,13 +9,18 @@ #pragma once #include "duckdb/transaction/transaction.hpp" +#include "duckdb/common/reference_map.hpp" namespace duckdb { class RowVersionManager; +class DuckTransactionManager; +class StorageLockKey; +class StorageCommitState; +struct UndoBufferProperties; class DuckTransaction : public Transaction { public: - DuckTransaction(TransactionManager &manager, ClientContext &context, transaction_t start_time, + DuckTransaction(DuckTransactionManager &manager, ClientContext &context, transaction_t start_time, transaction_t transaction_id); ~DuckTransaction() override; @@ -25,8 +30,6 @@ class DuckTransaction : public Transaction { transaction_t transaction_id; //! The commit id of this transaction, if it has successfully been committed transaction_t commit_id; - //! Map of all sequences that were used during the transaction and the value they had in this transaction - unordered_map sequence_usage; //! Highest active query when the transaction finished, used for cleaning up transaction_t highest_active_query; @@ -37,11 +40,16 @@ class DuckTransaction : public Transaction { void PushCatalogEntry(CatalogEntry &entry, data_ptr_t extra_data = nullptr, idx_t extra_data_size = 0); + void SetReadWrite() override; + + bool ShouldWriteToWAL(AttachedDatabase &db); + ErrorData WriteToWAL(AttachedDatabase &db, unique_ptr &commit_state) noexcept; //! Commit the current transaction with the given commit identifier. Returns an error message if the transaction //! commit failed, or an empty string if the commit was sucessful - ErrorData Commit(AttachedDatabase &db, transaction_t commit_id, bool checkpoint) noexcept; + ErrorData Commit(AttachedDatabase &db, transaction_t commit_id, + unique_ptr commit_state) noexcept; //! Returns whether or not a commit of this transaction should trigger an automatic checkpoint - bool AutomaticCheckpoint(AttachedDatabase &db); + bool AutomaticCheckpoint(AttachedDatabase &db, const UndoBufferProperties &properties); //! Rollback void Rollback() noexcept; @@ -49,9 +57,11 @@ class DuckTransaction : public Transaction { void Cleanup(); bool ChangesMade(); + UndoBufferProperties GetUndoProperties(); void PushDelete(DataTable &table, RowVersionManager &info, idx_t vector_idx, row_t rows[], idx_t count, idx_t base_row); + void PushSequenceUsage(SequenceCatalogEntry &entry, const SequenceData &data); void PushAppend(DataTable &table, idx_t row_start, idx_t row_count); UpdateInfo *CreateUpdateInfo(idx_t type_size, idx_t entries); @@ -59,12 +69,24 @@ class DuckTransaction : public Transaction { return true; } + unique_ptr TryGetCheckpointLock(); + bool HasWriteLock() const { + return write_lock.get(); + } + private: + DuckTransactionManager &transaction_manager; //! The undo buffer is used to store old versions of rows that are updated //! or deleted UndoBuffer undo_buffer; //! The set of uncommitted appends for the transaction unique_ptr storage; + //! Write lock + unique_ptr write_lock; + //! Lock for accessing sequence_usage + mutex sequence_lock; + //! Map of all sequences that were used during the transaction and the value they had in this transaction + reference_map_t> sequence_usage; }; } // namespace duckdb diff --git a/src/include/duckdb/transaction/duck_transaction_manager.hpp b/src/include/duckdb/transaction/duck_transaction_manager.hpp index 63756e977f9..978b93edbd4 100644 --- a/src/include/duckdb/transaction/duck_transaction_manager.hpp +++ b/src/include/duckdb/transaction/duck_transaction_manager.hpp @@ -9,6 +9,8 @@ #pragma once #include "duckdb/transaction/transaction_manager.hpp" +#include "duckdb/storage/storage_lock.hpp" +#include "duckdb/common/enums/checkpoint_type.hpp" namespace duckdb { class DuckTransaction; @@ -16,8 +18,6 @@ class DuckTransaction; //! The Transaction Manager is responsible for creating and managing //! transactions class DuckTransactionManager : public TransactionManager { - friend struct CheckpointLock; - public: explicit DuckTransactionManager(AttachedDatabase &db); ~DuckTransactionManager() override; @@ -34,27 +34,46 @@ class DuckTransactionManager : public TransactionManager { void Checkpoint(ClientContext &context, bool force = false) override; - transaction_t LowestActiveId() { + transaction_t LowestActiveId() const { return lowest_active_id; } - transaction_t LowestActiveStart() { + transaction_t LowestActiveStart() const { return lowest_active_start; } + transaction_t GetLastCommit() const { + return last_commit; + } bool IsDuckTransactionManager() override { return true; } + //! Obtains a shared lock to the checkpoint lock + unique_ptr SharedCheckpointLock(); + unique_ptr TryUpgradeCheckpointLock(StorageLockKey &lock); + protected: struct CheckpointDecision { + explicit CheckpointDecision(string reason_p); + explicit CheckpointDecision(CheckpointType type); + ~CheckpointDecision(); + bool can_checkpoint; string reason; + CheckpointType type; }; private: - CheckpointDecision CanCheckpoint(optional_ptr current = nullptr); + //! Generates a new commit timestamp + transaction_t GetCommitTimestamp(); //! Remove the given transaction from the list of active transactions void RemoveTransaction(DuckTransaction &transaction) noexcept; + //! Remove the given transaction from the list of active transactions + void RemoveTransaction(DuckTransaction &transaction, bool store_transaction) noexcept; + + //! Whether or not we can checkpoint + CheckpointDecision CanCheckpoint(DuckTransaction &transaction, unique_ptr &checkpoint_lock, + const UndoBufferProperties &properties); private: //! The current start timestamp used by transactions @@ -65,6 +84,8 @@ class DuckTransactionManager : public TransactionManager { atomic lowest_active_id; //! The lowest active transaction timestamp atomic lowest_active_start; + //! The last commit timestamp + atomic last_commit; //! Set of currently running transactions vector> active_transactions; //! Set of recently committed transactions @@ -73,8 +94,12 @@ class DuckTransactionManager : public TransactionManager { vector> old_transactions; //! The lock used for transaction operations mutex transaction_lock; - - bool thread_is_checkpointing; + //! The checkpoint lock + StorageLock checkpoint_lock; + //! Lock necessary to start transactions only - used by FORCE CHECKPOINT to prevent new transactions from starting + mutex start_transaction_lock; + //! Mutex used to control writes to the WAL - separate from the transaction lock + mutex wal_lock; protected: virtual void OnCommitCheckpointDecision(const CheckpointDecision &decision, DuckTransaction &transaction) { diff --git a/src/include/duckdb/transaction/local_storage.hpp b/src/include/duckdb/transaction/local_storage.hpp index a2140444dea..6ee5334cb30 100644 --- a/src/include/duckdb/transaction/local_storage.hpp +++ b/src/include/duckdb/transaction/local_storage.hpp @@ -12,9 +12,11 @@ #include "duckdb/storage/table/table_index_list.hpp" #include "duckdb/storage/table/table_statistics.hpp" #include "duckdb/storage/optimistic_data_writer.hpp" +#include "duckdb/common/reference_map.hpp" namespace duckdb { class AttachedDatabase; +class Catalog; class DataTable; class Transaction; class WriteAheadLog; @@ -24,7 +26,7 @@ struct TableAppendState; class LocalTableStorage : public enable_shared_from_this { public: // Create a new LocalTableStorage - explicit LocalTableStorage(DataTable &table); + explicit LocalTableStorage(ClientContext &context, DataTable &table); // Create a LocalTableStorage from an ALTER TYPE LocalTableStorage(ClientContext &context, DataTable &table, LocalTableStorage &parent, idx_t changed_idx, const LogicalType &target_type, const vector &bound_columns, Expression &cast_expr); @@ -32,7 +34,7 @@ class LocalTableStorage : public enable_shared_from_this { LocalTableStorage(DataTable &table, LocalTableStorage &parent, idx_t drop_idx); // Create a LocalTableStorage from an ADD COLUMN LocalTableStorage(ClientContext &context, DataTable &table, LocalTableStorage &parent, ColumnDefinition &new_column, - Expression &default_value); + ExpressionExecutor &default_executor); ~LocalTableStorage(); reference table_ref; @@ -50,6 +52,8 @@ class LocalTableStorage : public enable_shared_from_this { vector> optimistic_writers; //! Whether or not storage was merged bool merged_storage = false; + //! Whether or not the storage was dropped + bool is_dropped = false; public: void InitializeScan(CollectionScanState &state, optional_ptr table_filters = nullptr); @@ -74,7 +78,7 @@ class LocalTableManager { shared_ptr MoveEntry(DataTable &table); reference_map_t> MoveEntries(); optional_ptr GetStorage(DataTable &table); - LocalTableStorage &GetOrCreateStorage(DataTable &table); + LocalTableStorage &GetOrCreateStorage(ClientContext &context, DataTable &table); idx_t EstimatedSize(); bool IsEmpty(); void InsertEntry(DataTable &table, shared_ptr entry); @@ -132,18 +136,20 @@ class LocalStorage { void Update(DataTable &table, Vector &row_ids, const vector &column_ids, DataChunk &data); //! Commits the local storage, writing it to the WAL and completing the commit - void Commit(LocalStorage::CommitState &commit_state, DuckTransaction &transaction); + void Commit(); //! Rollback the local storage void Rollback(); bool ChangesMade() noexcept; idx_t EstimatedSize(); + void DropTable(DataTable &table); bool Find(DataTable &table); idx_t AddedRows(DataTable &table); - void AddColumn(DataTable &old_dt, DataTable &new_dt, ColumnDefinition &new_column, Expression &default_value); + void AddColumn(DataTable &old_dt, DataTable &new_dt, ColumnDefinition &new_column, + ExpressionExecutor &default_executor); void DropColumn(DataTable &old_dt, DataTable &new_dt, idx_t removed_column); void ChangeType(DataTable &old_dt, DataTable &new_dt, idx_t changed_idx, const LogicalType &target_type, const vector &bound_columns, Expression &cast_expr); diff --git a/src/include/duckdb/transaction/meta_transaction.hpp b/src/include/duckdb/transaction/meta_transaction.hpp index dabbcf6d511..3267b8cdc8f 100644 --- a/src/include/duckdb/transaction/meta_transaction.hpp +++ b/src/include/duckdb/transaction/meta_transaction.hpp @@ -34,8 +34,6 @@ class MetaTransaction { idx_t catalog_version; //! The validity checker of the transaction ValidChecker transaction_validity; - //! Whether or not any transaction have made modifications - bool read_only; //! The active query number transaction_t active_query; @@ -46,6 +44,7 @@ class MetaTransaction { } Transaction &GetTransaction(AttachedDatabase &db); + optional_ptr TryGetTransaction(AttachedDatabase &db); void RemoveTransaction(AttachedDatabase &db); ErrorData Commit(); @@ -54,6 +53,8 @@ class MetaTransaction { idx_t GetActiveQuery(); void SetActiveQuery(transaction_t query_number); + void SetReadOnly(); + bool IsReadOnly() const; void ModifyDatabase(AttachedDatabase &db); optional_ptr ModifiedDatabase() { return modified_database; @@ -71,6 +72,8 @@ class MetaTransaction { vector> all_transactions; //! The database we are modifying - we can only modify one database per transaction optional_ptr modified_database; + //! Whether or not the meta transaction is marked as read only + bool is_read_only; }; } // namespace duckdb diff --git a/src/include/duckdb/transaction/transaction.hpp b/src/include/duckdb/transaction/transaction.hpp index 3ea1e07bb4f..a2122a68f2b 100644 --- a/src/include/duckdb/transaction/transaction.hpp +++ b/src/include/duckdb/transaction/transaction.hpp @@ -51,9 +51,13 @@ class Transaction { public: DUCKDB_API static Transaction &Get(ClientContext &context, AttachedDatabase &db); DUCKDB_API static Transaction &Get(ClientContext &context, Catalog &catalog); + //! Returns the transaction for the given context if it has already been started + DUCKDB_API static optional_ptr TryGet(ClientContext &context, AttachedDatabase &db); //! Whether or not the transaction has made any modifications to the database so far DUCKDB_API bool IsReadOnly(); + //! Promotes the transaction to a read-write transaction + DUCKDB_API virtual void SetReadWrite(); virtual bool IsDuckTransaction() const { return false; @@ -70,6 +74,9 @@ class Transaction { DynamicCastCheck(this); return reinterpret_cast(*this); } + +private: + bool is_read_only; }; } // namespace duckdb diff --git a/src/include/duckdb/transaction/transaction_context.hpp b/src/include/duckdb/transaction/transaction_context.hpp index b0a50103bb4..9623f5a7818 100644 --- a/src/include/duckdb/transaction/transaction_context.hpp +++ b/src/include/duckdb/transaction/transaction_context.hpp @@ -47,6 +47,8 @@ class TransactionContext { return auto_commit; } + void SetReadOnly(); + idx_t GetActiveQuery(); void ResetActiveQuery(); void SetActiveQuery(transaction_t query_number); diff --git a/src/include/duckdb/transaction/undo_buffer.hpp b/src/include/duckdb/transaction/undo_buffer.hpp index 9a212853a8a..ca16ddaca8e 100644 --- a/src/include/duckdb/transaction/undo_buffer.hpp +++ b/src/include/duckdb/transaction/undo_buffer.hpp @@ -16,6 +16,14 @@ namespace duckdb { class WriteAheadLog; +struct UndoBufferProperties { + idx_t estimated_size = 0; + bool has_updates = false; + bool has_deletes = false; + bool has_catalog_changes = false; + bool has_dropped_entries = false; +}; + //! The undo buffer of a transaction is used to hold previous versions of tuples //! that might be required in the future (because of rollbacks or previous //! transactions accessing them) @@ -35,12 +43,14 @@ class UndoBuffer { data_ptr_t CreateEntry(UndoFlags type, idx_t len); bool ChangesMade(); - idx_t EstimatedSize(); + UndoBufferProperties GetProperties(); //! Cleanup the undo buffer void Cleanup(); //! Commit the changes made in the UndoBuffer: should be called on commit - void Commit(UndoBuffer::IteratorState &iterator_state, optional_ptr log, transaction_t commit_id); + void WriteToWAL(WriteAheadLog &wal); + //! Commit the changes made in the UndoBuffer: should be called on commit + void Commit(UndoBuffer::IteratorState &iterator_state, transaction_t commit_id); //! Revert committed changes made in the UndoBuffer up until the currently committed state void RevertCommit(UndoBuffer::IteratorState &iterator_state, transaction_t transaction_id); //! Rollback the changes made in this UndoBuffer: should be called on diff --git a/src/include/duckdb/transaction/wal_write_state.hpp b/src/include/duckdb/transaction/wal_write_state.hpp new file mode 100644 index 00000000000..34d54e8646a --- /dev/null +++ b/src/include/duckdb/transaction/wal_write_state.hpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/transaction/wal_write_state.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/transaction/undo_buffer.hpp" +#include "duckdb/common/vector_size.hpp" + +namespace duckdb { +class CatalogEntry; +class DataChunk; +class WriteAheadLog; +class ClientContext; + +struct DataTableInfo; +struct DeleteInfo; +struct UpdateInfo; + +class WALWriteState { +public: + explicit WALWriteState(WriteAheadLog &log); + +public: + void CommitEntry(UndoFlags type, data_ptr_t data); + +private: + void SwitchTable(DataTableInfo *table, UndoFlags new_op); + + void WriteCatalogEntry(CatalogEntry &entry, data_ptr_t extra_data); + void WriteDelete(DeleteInfo &info); + void WriteUpdate(UpdateInfo &info); + +private: + WriteAheadLog &log; + + optional_ptr current_table_info; + + unique_ptr delete_chunk; + unique_ptr update_chunk; +}; + +} // namespace duckdb diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt index 3dc29b368e0..494fb4d1246 100644 --- a/src/main/CMakeLists.txt +++ b/src/main/CMakeLists.txt @@ -17,8 +17,10 @@ add_library_unity( OBJECT appender.cpp attached_database.cpp + client_config.cpp client_context_file_opener.cpp client_context.cpp + client_context_wrapper.cpp client_data.cpp client_verify.cpp connection_manager.cpp @@ -31,6 +33,7 @@ add_library_unity( db_instance_cache.cpp error_manager.cpp extension.cpp + extension_install_info.cpp materialized_query_result.cpp pending_query_result.cpp prepared_statement.cpp @@ -39,6 +42,7 @@ add_library_unity( query_profiler.cpp query_result.cpp stream_query_result.cpp + profiling_info.cpp valid_checker.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/main/appender.cpp b/src/main/appender.cpp index 1a8fae39cf9..564fff2e923 100644 --- a/src/main/appender.cpp +++ b/src/main/appender.cpp @@ -12,6 +12,9 @@ #include "duckdb/main/connection.hpp" #include "duckdb/main/database.hpp" #include "duckdb/storage/data_table.hpp" +#include "duckdb/planner/expression_binder/constant_binder.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/execution/expression_executor.hpp" namespace duckdb { @@ -19,9 +22,10 @@ BaseAppender::BaseAppender(Allocator &allocator, AppenderType type_p) : allocator(allocator), column(0), appender_type(type_p) { } -BaseAppender::BaseAppender(Allocator &allocator_p, vector types_p, AppenderType type_p) +BaseAppender::BaseAppender(Allocator &allocator_p, vector types_p, AppenderType type_p, + idx_t flush_count_p) : allocator(allocator_p), types(std::move(types_p)), collection(make_uniq(allocator, types)), - column(0), appender_type(type_p) { + column(0), appender_type(type_p), flush_count(flush_count_p) { InitializeChunk(); } @@ -40,9 +44,9 @@ void BaseAppender::Destructor() { } } -InternalAppender::InternalAppender(ClientContext &context_p, TableCatalogEntry &table_p) - : BaseAppender(Allocator::DefaultAllocator(), table_p.GetTypes(), AppenderType::PHYSICAL), context(context_p), - table(table_p) { +InternalAppender::InternalAppender(ClientContext &context_p, TableCatalogEntry &table_p, idx_t flush_count_p) + : BaseAppender(Allocator::DefaultAllocator(), table_p.GetTypes(), AppenderType::PHYSICAL, flush_count_p), + context(context_p), table(table_p) { } InternalAppender::~InternalAppender() { @@ -56,9 +60,39 @@ Appender::Appender(Connection &con, const string &schema_name, const string &tab // table could not be found throw CatalogException(StringUtil::Format("Table \"%s.%s\" could not be found", schema_name, table_name)); } + vector> defaults; for (auto &column : description->columns) { types.push_back(column.Type()); + defaults.push_back(column.HasDefaultValue() ? &column.DefaultValue() : nullptr); } + auto binder = Binder::CreateBinder(*context); + + context->RunFunctionInTransaction([&]() { + for (idx_t i = 0; i < types.size(); i++) { + auto &type = types[i]; + auto &expr = defaults[i]; + + if (!expr) { + // Insert NULL + default_values[i] = Value(type); + continue; + } + auto default_copy = expr->Copy(); + D_ASSERT(!default_copy->HasParameter()); + ConstantBinder default_binder(*binder, *context, "DEFAULT value"); + default_binder.target_type = type; + auto bound_default = default_binder.Bind(default_copy); + Value result_value; + if (bound_default->IsFoldable() && + ExpressionExecutor::TryEvaluateScalar(*context, *bound_default, result_value)) { + // Insert the evaluated Value + default_values[i] = result_value; + } else { + // These are not supported currently, we don't add them to the 'default_values' map + } + } + }); + InitializeChunk(); collection = make_uniq(allocator, types); } @@ -339,7 +373,7 @@ void BaseAppender::AppendDataChunk(DataChunk &chunk) { } } collection->Append(chunk); - if (collection->Count() >= FLUSH_COUNT) { + if (collection->Count() >= flush_count) { Flush(); } } @@ -350,7 +384,7 @@ void BaseAppender::FlushChunk() { } collection->Append(chunk); chunk.Reset(); - if (collection->Count() >= FLUSH_COUNT) { + if (collection->Count() >= flush_count) { Flush(); } } @@ -375,6 +409,18 @@ void Appender::FlushInternal(ColumnDataCollection &collection) { context->Append(*description, collection); } +void Appender::AppendDefault() { + auto it = default_values.find(column); + auto &column_def = description->columns[column]; + if (it == default_values.end()) { + throw NotImplementedException( + "AppendDefault is currently not supported for column \"%s\" because default expression is not foldable.", + column_def.Name()); + } + auto &default_value = it->second; + Append(default_value); +} + void InternalAppender::FlushInternal(ColumnDataCollection &collection) { auto binder = Binder::CreateBinder(context); auto bound_constraints = binder->BindConstraints(table); diff --git a/src/main/attached_database.cpp b/src/main/attached_database.cpp index ce9ce5f4a82..4f3d43c9b52 100644 --- a/src/main/attached_database.cpp +++ b/src/main/attached_database.cpp @@ -13,11 +13,67 @@ namespace duckdb { +//===--------------------------------------------------------------------===// +// Attach Options +//===--------------------------------------------------------------------===// + +AttachOptions::AttachOptions(const DBConfigOptions &options) + : access_mode(options.access_mode), db_type(options.database_type) { +} + +AttachOptions::AttachOptions(const unique_ptr &info, const AccessMode default_access_mode) + : access_mode(default_access_mode) { + + for (auto &entry : info->options) { + + if (entry.first == "readonly" || entry.first == "read_only") { + // Extract the read access mode. + + auto read_only = BooleanValue::Get(entry.second.DefaultCastAs(LogicalType::BOOLEAN)); + if (read_only) { + access_mode = AccessMode::READ_ONLY; + } else { + access_mode = AccessMode::READ_WRITE; + } + continue; + } + + if (entry.first == "readwrite" || entry.first == "read_write") { + // Extract the write access mode. + + auto read_write = BooleanValue::Get(entry.second.DefaultCastAs(LogicalType::BOOLEAN)); + if (!read_write) { + access_mode = AccessMode::READ_ONLY; + } else { + access_mode = AccessMode::READ_WRITE; + } + continue; + } + + if (entry.first == "type") { + // Extract the database type. + db_type = StringValue::Get(entry.second.DefaultCastAs(LogicalType::VARCHAR)); + continue; + } + + // We allow unrecognized options in storage extensions. To track that we saw an unrecognized option, + // we set unrecognized_option. + if (unrecognized_option.empty()) { + unrecognized_option = entry.first; + } + } +} + +//===--------------------------------------------------------------------===// +// Attached Database +//===--------------------------------------------------------------------===// + AttachedDatabase::AttachedDatabase(DatabaseInstance &db, AttachedDatabaseType type) : CatalogEntry(CatalogType::DATABASE_ENTRY, type == AttachedDatabaseType::SYSTEM_DATABASE ? SYSTEM_CATALOG : TEMP_CATALOG, 0), db(db), type(type) { + // This database does not have storage, or uses temporary_objects for in-memory storage. D_ASSERT(type == AttachedDatabaseType::TEMP_DATABASE || type == AttachedDatabaseType::SYSTEM_DATABASE); if (type == AttachedDatabaseType::TEMP_DATABASE) { storage = make_uniq(*this, string(IN_MEMORY_PATH), false); @@ -29,35 +85,46 @@ AttachedDatabase::AttachedDatabase(DatabaseInstance &db, AttachedDatabaseType ty } AttachedDatabase::AttachedDatabase(DatabaseInstance &db, Catalog &catalog_p, string name_p, string file_path_p, - AccessMode access_mode) + const AttachOptions &options) : CatalogEntry(CatalogType::DATABASE_ENTRY, catalog_p, std::move(name_p)), db(db), parent_catalog(&catalog_p) { - type = access_mode == AccessMode::READ_ONLY ? AttachedDatabaseType::READ_ONLY_DATABASE - : AttachedDatabaseType::READ_WRITE_DATABASE; + + if (options.access_mode == AccessMode::READ_ONLY) { + type = AttachedDatabaseType::READ_ONLY_DATABASE; + } else { + type = AttachedDatabaseType::READ_WRITE_DATABASE; + } + + // We create the storage after the catalog to guarantee we allow extensions to instantiate the DuckCatalog. catalog = make_uniq(*this); - // do this after catalog to guarnatee we allow extension to instantionate DuckCatalog causing creation - // of the storage - storage = make_uniq(*this, std::move(file_path_p), access_mode == AccessMode::READ_ONLY); + auto read_only = options.access_mode == AccessMode::READ_ONLY; + storage = make_uniq(*this, std::move(file_path_p), read_only); transaction_manager = make_uniq(*this); internal = true; } -AttachedDatabase::AttachedDatabase(DatabaseInstance &db, Catalog &catalog_p, StorageExtension &storage_extension, +AttachedDatabase::AttachedDatabase(DatabaseInstance &db, Catalog &catalog_p, StorageExtension &storage_extension_p, ClientContext &context, string name_p, const AttachInfo &info, - AccessMode access_mode) - : CatalogEntry(CatalogType::DATABASE_ENTRY, catalog_p, std::move(name_p)), db(db), parent_catalog(&catalog_p) { - type = access_mode == AccessMode::READ_ONLY ? AttachedDatabaseType::READ_ONLY_DATABASE - : AttachedDatabaseType::READ_WRITE_DATABASE; - catalog = - storage_extension.attach(storage_extension.storage_info.get(), context, *this, name, *info.Copy(), access_mode); + const AttachOptions &options) + : CatalogEntry(CatalogType::DATABASE_ENTRY, catalog_p, std::move(name_p)), db(db), parent_catalog(&catalog_p), + storage_extension(&storage_extension_p) { + + if (options.access_mode == AccessMode::READ_ONLY) { + type = AttachedDatabaseType::READ_ONLY_DATABASE; + } else { + type = AttachedDatabaseType::READ_WRITE_DATABASE; + } + + StorageExtensionInfo *storage_info = storage_extension->storage_info.get(); + catalog = storage_extension->attach(storage_info, context, *this, name, *info.Copy(), options.access_mode); if (!catalog) { throw InternalException("AttachedDatabase - attach function did not return a catalog"); } if (catalog->IsDuckCatalog()) { - // DuckCatalog, instantiate storage - storage = make_uniq(*this, info.path, access_mode == AccessMode::READ_ONLY); + // The attached database uses the DuckCatalog. + auto read_only = options.access_mode == AccessMode::READ_ONLY; + storage = make_uniq(*this, info.path, read_only); } - transaction_manager = - storage_extension.create_transaction_manager(storage_extension.storage_info.get(), *this, *catalog); + transaction_manager = storage_extension->create_transaction_manager(storage_info, *this, *catalog); if (!transaction_manager) { throw InternalException( "AttachedDatabase - create_transaction_manager function did not return a transaction manager"); @@ -82,7 +149,7 @@ bool AttachedDatabase::IsReadOnly() const { } bool AttachedDatabase::NameIsReserved(const string &name) { - return name == DEFAULT_SCHEMA || name == TEMP_CATALOG; + return name == DEFAULT_SCHEMA || name == TEMP_CATALOG || name == SYSTEM_CATALOG; } string AttachedDatabase::ExtractDatabaseName(const string &dbpath, FileSystem &fs) { @@ -96,14 +163,14 @@ string AttachedDatabase::ExtractDatabaseName(const string &dbpath, FileSystem &f return name; } -void AttachedDatabase::Initialize(optional_ptr context) { +void AttachedDatabase::Initialize(const optional_idx block_alloc_size) { if (IsSystem()) { catalog->Initialize(true); } else { catalog->Initialize(false); } if (storage) { - storage->Initialize(context); + storage->Initialize(block_alloc_size); } } @@ -168,7 +235,9 @@ void AttachedDatabase::Close() { if (!config.options.checkpoint_on_shutdown) { return; } - storage->CreateCheckpoint(true); + CheckpointOptions options; + options.wal_action = CheckpointWALAction::DELETE_WAL; + storage->CreateCheckpoint(options); } } catch (...) { // NOLINT } diff --git a/src/main/buffered_data/CMakeLists.txt b/src/main/buffered_data/CMakeLists.txt index 7cffd1ee152..68ae8abd0e0 100644 --- a/src/main/buffered_data/CMakeLists.txt +++ b/src/main/buffered_data/CMakeLists.txt @@ -1,4 +1,5 @@ -add_library_unity(duckdb_main_buffered_data OBJECT simple_buffered_data.cpp) +add_library_unity(duckdb_main_buffered_data OBJECT buffered_data.cpp + simple_buffered_data.cpp batched_buffered_data.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/main/buffered_data/batched_buffered_data.cpp b/src/main/buffered_data/batched_buffered_data.cpp new file mode 100644 index 00000000000..85037f31ac5 --- /dev/null +++ b/src/main/buffered_data/batched_buffered_data.cpp @@ -0,0 +1,212 @@ +#include "duckdb/main/buffered_data/batched_buffered_data.hpp" +#include "duckdb/common/printer.hpp" +#include "duckdb/main/client_context.hpp" +#include "duckdb/main/stream_query_result.hpp" +#include "duckdb/common/helper.hpp" +#include "duckdb/execution/operator/helper/physical_buffered_batch_collector.hpp" +#include "duckdb/common/stack.hpp" + +namespace duckdb { + +void BatchedBufferedData::BlockSink(const InterruptState &blocked_sink, idx_t batch) { + lock_guard lock(glock); + D_ASSERT(!blocked_sinks.count(batch)); + blocked_sinks.emplace(std::make_pair(batch, blocked_sink)); +} + +BatchedBufferedData::BatchedBufferedData(weak_ptr context) + : BufferedData(BufferedData::Type::BATCHED, std::move(context)), buffer_byte_count(0), read_queue_byte_count(0), + min_batch(0) { + read_queue_capacity = (idx_t)(total_buffer_size * 0.6); + buffer_capacity = (idx_t)(total_buffer_size * 0.4); +} + +bool BatchedBufferedData::ShouldBlockBatch(idx_t batch) { + lock_guard lock(glock); + bool is_minimum = IsMinimumBatchIndex(lock, batch); + if (is_minimum) { + // If there is room in the read queue, we want to process the minimum batch + return read_queue_byte_count >= ReadQueueCapacity(); + } + return buffer_byte_count >= BufferCapacity(); +} + +bool BatchedBufferedData::BufferIsEmpty() { + lock_guard lock(glock); + return read_queue.empty(); +} + +bool BatchedBufferedData::IsMinimumBatchIndex(lock_guard &lock, idx_t batch) { + return min_batch == batch; +} + +void BatchedBufferedData::UnblockSinks() { + lock_guard lock(glock); + stack to_remove; + for (auto it = blocked_sinks.begin(); it != blocked_sinks.end(); it++) { + auto batch = it->first; + auto &blocked_sink = it->second; + const bool is_minimum = IsMinimumBatchIndex(lock, batch); + if (is_minimum) { + if (read_queue_byte_count >= ReadQueueCapacity()) { + continue; + } + } else { + if (buffer_byte_count >= BufferCapacity()) { + continue; + } + } + blocked_sink.Callback(); + to_remove.push(batch); + } + while (!to_remove.empty()) { + auto batch = to_remove.top(); + to_remove.pop(); + blocked_sinks.erase(batch); + } +} + +void BatchedBufferedData::MoveCompletedBatches(lock_guard &lock) { + stack to_remove; + for (auto &it : buffer) { + auto batch_index = it.first; + auto &in_progress_batch = it.second; + if (batch_index > min_batch) { + break; + } + D_ASSERT(in_progress_batch.completed || batch_index == min_batch); + // min_batch - took longer than others + // min_batch+1 - completed before min_batch + // min_batch+2 - completed before min_batch + // new min_batch + // + // To preserve the order, the completed batches have to be processed before we can start scanning the "new + // min_batch" + auto &chunks = in_progress_batch.chunks; + + idx_t batch_allocation_size = 0; + for (auto it = chunks.begin(); it != chunks.end(); it++) { + auto chunk = std::move(*it); + auto allocation_size = chunk->GetAllocationSize(); + batch_allocation_size += allocation_size; + read_queue.push_back(std::move(chunk)); + } + // Verification to make sure we're not breaking the order by moving batches before the previous ones have + // finished + if (lowest_moved_batch > batch_index) { + throw InternalException("Lowest moved batch is %d, attempted to move %d afterwards\nAttempted to move %d " + "chunks, of %d bytes in total\nmin_batch is %d", + lowest_moved_batch, batch_index, chunks.size(), batch_allocation_size, min_batch); + } + D_ASSERT(lowest_moved_batch <= batch_index); + lowest_moved_batch = batch_index; + + buffer_byte_count -= batch_allocation_size; + read_queue_byte_count += batch_allocation_size; + to_remove.push(batch_index); + } + while (!to_remove.empty()) { + auto batch_index = to_remove.top(); + to_remove.pop(); + buffer.erase(batch_index); + } +} + +void BatchedBufferedData::UpdateMinBatchIndex(idx_t min_batch_index) { + lock_guard lock(glock); + + auto old_min_batch = min_batch; + auto new_min_batch = MaxValue(old_min_batch, min_batch_index); + if (new_min_batch == min_batch) { + // No change, early out + return; + } + min_batch = new_min_batch; + MoveCompletedBatches(lock); +} + +PendingExecutionResult BatchedBufferedData::ReplenishBuffer(StreamQueryResult &result, + ClientContextLock &context_lock) { + if (Closed()) { + return PendingExecutionResult::EXECUTION_ERROR; + } + // Unblock any pending sinks if the buffer isnt full + UnblockSinks(); + if (!BufferIsEmpty()) { + // The buffer isn't empty yet, just return + return PendingExecutionResult::RESULT_READY; + } + // Let the executor run until the buffer is no longer empty + auto cc = context.lock(); + auto res = cc->ExecuteTaskInternal(context_lock, result); + while (!PendingQueryResult::IsFinished(res)) { + if (!BufferIsEmpty()) { + break; + } + // Check if we need to unblock more sinks to reach the buffer size + UnblockSinks(); + res = cc->ExecuteTaskInternal(context_lock, result); + } + return res; +} + +void BatchedBufferedData::CompleteBatch(idx_t batch) { + lock_guard lock(glock); + auto it = buffer.find(batch); + if (it == buffer.end()) { + return; + } + + auto &in_progress_batch = it->second; + in_progress_batch.completed = true; +} + +unique_ptr BatchedBufferedData::Scan() { + unique_ptr chunk; + lock_guard lock(glock); + if (!read_queue.empty()) { + chunk = std::move(read_queue.front()); + read_queue.pop_front(); + auto allocation_size = chunk->GetAllocationSize(); + read_queue_byte_count -= allocation_size; + } else { + context.reset(); + D_ASSERT(blocked_sinks.empty()); + D_ASSERT(buffer.empty()); + return nullptr; + } + return chunk; +} + +void BatchedBufferedData::Append(const DataChunk &to_append, idx_t batch) { + // We should never find any chunks with a smaller batch index than the minimum + + auto chunk = make_uniq(); + chunk->Initialize(Allocator::DefaultAllocator(), to_append.GetTypes()); + to_append.Copy(*chunk, 0); + auto allocation_size = chunk->GetAllocationSize(); + + lock_guard lock(glock); + D_ASSERT(batch >= min_batch); + auto is_minimum = IsMinimumBatchIndex(lock, batch); + if (is_minimum) { + for (auto &it : buffer) { + auto batch_index = it.first; + if (batch_index >= min_batch) { + break; + } + // There should not be any batches in the buffer that are lower or equal to the minimum batch index + throw InternalException("Batches remaining in buffer"); + } + read_queue.push_back(std::move(chunk)); + read_queue_byte_count += allocation_size; + } else { + auto &in_progress_batch = buffer[batch]; + auto &chunks = in_progress_batch.chunks; + in_progress_batch.completed = false; + buffer_byte_count += allocation_size; + chunks.push_back(std::move(chunk)); + } +} + +} // namespace duckdb diff --git a/src/main/buffered_data/buffered_data.cpp b/src/main/buffered_data/buffered_data.cpp new file mode 100644 index 00000000000..ceddaccd6ec --- /dev/null +++ b/src/main/buffered_data/buffered_data.cpp @@ -0,0 +1,16 @@ +#include "duckdb/main/buffered_data/buffered_data.hpp" +#include "duckdb/main/client_config.hpp" +#include "duckdb/main/client_context.hpp" + +namespace duckdb { + +BufferedData::BufferedData(Type type, weak_ptr context_p) : type(type), context(std::move(context_p)) { + auto client_context = context.lock(); + auto &config = ClientConfig::GetConfig(*client_context); + total_buffer_size = config.streaming_buffer_size; +} + +BufferedData::~BufferedData() { +} + +} // namespace duckdb diff --git a/src/main/buffered_data/simple_buffered_data.cpp b/src/main/buffered_data/simple_buffered_data.cpp index f84cae8a1c7..62e3d6ab5b7 100644 --- a/src/main/buffered_data/simple_buffered_data.cpp +++ b/src/main/buffered_data/simple_buffered_data.cpp @@ -9,36 +9,37 @@ namespace duckdb { SimpleBufferedData::SimpleBufferedData(weak_ptr context) : BufferedData(BufferedData::Type::SIMPLE, std::move(context)) { buffered_count = 0; + buffer_size = total_buffer_size; } SimpleBufferedData::~SimpleBufferedData() { } -void SimpleBufferedData::BlockSink(const BlockedSink &blocked_sink) { +void SimpleBufferedData::BlockSink(const InterruptState &blocked_sink) { lock_guard lock(glock); blocked_sinks.push(blocked_sink); } bool SimpleBufferedData::BufferIsFull() { - return buffered_count >= BUFFER_SIZE; + return buffered_count >= BufferSize(); } void SimpleBufferedData::UnblockSinks() { if (Closed()) { return; } - if (buffered_count >= BUFFER_SIZE) { + if (buffered_count >= BufferSize()) { return; } // Reschedule enough blocked sinks to populate the buffer lock_guard lock(glock); while (!blocked_sinks.empty()) { auto &blocked_sink = blocked_sinks.front(); - if (buffered_count >= BUFFER_SIZE) { + if (buffered_count >= BufferSize()) { // We have unblocked enough sinks already break; } - blocked_sink.state.Callback(); + blocked_sink.Callback(); blocked_sinks.pop(); } } @@ -56,7 +57,7 @@ PendingExecutionResult SimpleBufferedData::ReplenishBuffer(StreamQueryResult &re // Let the executor run until the buffer is no longer empty auto res = cc->ExecuteTaskInternal(context_lock, result); while (!PendingQueryResult::IsFinished(res)) { - if (buffered_count >= BUFFER_SIZE) { + if (buffered_count >= BufferSize()) { break; } // Check if we need to unblock more sinks to reach the buffer size @@ -82,14 +83,20 @@ unique_ptr SimpleBufferedData::Scan() { buffered_chunks.pop(); if (chunk) { - buffered_count -= chunk->size(); + auto allocation_size = chunk->GetAllocationSize(); + buffered_count -= allocation_size; } return chunk; } -void SimpleBufferedData::Append(unique_ptr chunk) { +void SimpleBufferedData::Append(const DataChunk &to_append) { + auto chunk = make_uniq(); + chunk->Initialize(Allocator::DefaultAllocator(), to_append.GetTypes()); + to_append.Copy(*chunk, 0); + auto allocation_size = chunk->GetAllocationSize(); + unique_lock lock(glock); - buffered_count += chunk->size(); + buffered_count += allocation_size; buffered_chunks.push(std::move(chunk)); } diff --git a/src/main/capi/CMakeLists.txt b/src/main/capi/CMakeLists.txt index e690b245619..8173f557f88 100644 --- a/src/main/capi/CMakeLists.txt +++ b/src/main/capi/CMakeLists.txt @@ -17,8 +17,10 @@ add_library_unity( prepared-c.cpp replacement_scan-c.cpp result-c.cpp + scalar_function-c.cpp stream-c.cpp table_function-c.cpp + table_description-c.cpp threading-c.cpp value-c.cpp) diff --git a/src/main/capi/appender-c.cpp b/src/main/capi/appender-c.cpp index 2b0789bc133..eed34fb974f 100644 --- a/src/main/capi/appender-c.cpp +++ b/src/main/capi/appender-c.cpp @@ -42,13 +42,13 @@ duckdb_state duckdb_appender_destroy(duckdb_appender *appender) { if (!appender || !*appender) { return DuckDBError; } - duckdb_appender_close(*appender); + auto state = duckdb_appender_close(*appender); auto wrapper = reinterpret_cast(*appender); if (wrapper) { delete wrapper; } *appender = nullptr; - return DuckDBSuccess; + return state; } template @@ -67,7 +67,7 @@ duckdb_state duckdb_appender_run_function(duckdb_appender appender, FUN &&functi wrapper->error = error.RawMessage(); return DuckDBError; } catch (...) { // LCOV_EXCL_START - wrapper->error = "Unknown error"; + wrapper->error = "Unknown appender error."; return DuckDBError; } // LCOV_EXCL_STOP return DuckDBSuccess; @@ -110,6 +110,24 @@ duckdb_state duckdb_append_internal(duckdb_appender appender, T value) { return DuckDBSuccess; } +duckdb_state duckdb_append_default(duckdb_appender appender) { + if (!appender) { + return DuckDBError; + } + auto *appender_instance = reinterpret_cast(appender); + + try { + appender_instance->appender->AppendDefault(); + } catch (std::exception &ex) { + ErrorData error(ex); + appender_instance->error = error.RawMessage(); + return DuckDBError; + } catch (...) { + return DuckDBError; + } + return DuckDBSuccess; +} + duckdb_state duckdb_append_bool(duckdb_appender appender, bool value) { return duckdb_append_internal(appender, value); } @@ -199,6 +217,7 @@ duckdb_state duckdb_append_varchar(duckdb_appender appender, const char *val) { duckdb_state duckdb_append_varchar_length(duckdb_appender appender, const char *val, idx_t length) { return duckdb_append_internal(appender, string_t(val, duckdb::UnsafeNumericCast(length))); } + duckdb_state duckdb_append_blob(duckdb_appender appender, const void *data, idx_t length) { auto value = duckdb::Value::BLOB((duckdb::const_data_ptr_t)data, length); return duckdb_append_internal(appender, value); diff --git a/src/main/capi/config-c.cpp b/src/main/capi/config-c.cpp index d607f0bb262..daa4bcb0a45 100644 --- a/src/main/capi/config-c.cpp +++ b/src/main/capi/config-c.cpp @@ -10,14 +10,14 @@ duckdb_state duckdb_create_config(duckdb_config *out_config) { if (!out_config) { return DuckDBError; } - DBConfig *config; try { - config = new DBConfig(); + *out_config = nullptr; + auto config = new DBConfig(); + *out_config = reinterpret_cast(config); config->SetOptionByName("duckdb_api", "capi"); } catch (...) { // LCOV_EXCL_START return DuckDBError; } // LCOV_EXCL_STOP - *out_config = reinterpret_cast(config); return DuckDBSuccess; } diff --git a/src/main/capi/helper-c.cpp b/src/main/capi/helper-c.cpp index 39cacbf2628..6ee26e90287 100644 --- a/src/main/capi/helper-c.cpp +++ b/src/main/capi/helper-c.cpp @@ -180,9 +180,9 @@ idx_t GetCTypeSize(duckdb_type type) { case DUCKDB_TYPE_DECIMAL: return sizeof(duckdb_hugeint); default: // LCOV_EXCL_START - // unsupported type - D_ASSERT(0); - return sizeof(const char *); + // Unsupported nested or complex type. Internally, we set the null mask to NULL. + // This is a deprecated code path. Use the Vector Interface for nested and complex types. + return 0; } // LCOV_EXCL_STOP } diff --git a/src/main/capi/prepared-c.cpp b/src/main/capi/prepared-c.cpp index c7aac1419a7..8ac414978f7 100644 --- a/src/main/capi/prepared-c.cpp +++ b/src/main/capi/prepared-c.cpp @@ -280,6 +280,12 @@ duckdb_state duckdb_bind_timestamp(duckdb_prepared_statement prepared_statement, return duckdb_bind_value(prepared_statement, param_idx, (duckdb_value)&value); } +duckdb_state duckdb_bind_timestamp_tz(duckdb_prepared_statement prepared_statement, idx_t param_idx, + duckdb_timestamp val) { + auto value = Value::TIMESTAMPTZ(timestamp_t(val.micros)); + return duckdb_bind_value(prepared_statement, param_idx, (duckdb_value)&value); +} + duckdb_state duckdb_bind_interval(duckdb_prepared_statement prepared_statement, idx_t param_idx, duckdb_interval val) { auto value = Value::INTERVAL(val.months, val.days, val.micros); return duckdb_bind_value(prepared_statement, param_idx, (duckdb_value)&value); @@ -332,7 +338,12 @@ duckdb_state duckdb_execute_prepared(duckdb_prepared_statement prepared_statemen return DuckDBError; } - auto result = wrapper->statement->Execute(wrapper->values, false); + duckdb::unique_ptr result; + try { + result = wrapper->statement->Execute(wrapper->values, false); + } catch (...) { + return DuckDBError; + } return DuckDBTranslateResult(std::move(result), out_result); } diff --git a/src/main/capi/replacement_scan-c.cpp b/src/main/capi/replacement_scan-c.cpp index 2941b25a495..ff3eae4ff5a 100644 --- a/src/main/capi/replacement_scan-c.cpp +++ b/src/main/capi/replacement_scan-c.cpp @@ -19,18 +19,19 @@ struct CAPIReplacementScanData : public ReplacementScanData { }; struct CAPIReplacementScanInfo { - CAPIReplacementScanInfo(CAPIReplacementScanData *data) : data(data) { + CAPIReplacementScanInfo(optional_ptr data) : data(data) { } - CAPIReplacementScanData *data; + optional_ptr data; string function_name; vector parameters; string error; }; -unique_ptr duckdb_capi_replacement_callback(ClientContext &context, const string &table_name, - ReplacementScanData *data) { - auto &scan_data = reinterpret_cast(*data); +unique_ptr duckdb_capi_replacement_callback(ClientContext &context, ReplacementScanInput &input, + optional_ptr data) { + auto &table_name = input.table_name; + auto &scan_data = data->Cast(); CAPIReplacementScanInfo info(&scan_data); scan_data.callback((duckdb_replacement_scan_info)&info, table_name.c_str(), scan_data.extra_data); diff --git a/src/main/capi/result-c.cpp b/src/main/capi/result-c.cpp index fae2b0cb2c2..d3ffcadf84b 100644 --- a/src/main/capi/result-c.cpp +++ b/src/main/capi/result-c.cpp @@ -146,7 +146,18 @@ duckdb_state deprecated_duckdb_translate_column(MaterializedQueryResult &result, auto &collection = result.Collection(); idx_t row_count = collection.Count(); column->__deprecated_nullmask = (bool *)duckdb_malloc(sizeof(bool) * collection.Count()); - column->__deprecated_data = duckdb_malloc(GetCTypeSize(column->__deprecated_type) * row_count); + + auto type_size = GetCTypeSize(column->__deprecated_type); + if (type_size == 0) { + for (idx_t row_id = 0; row_id < row_count; row_id++) { + column->__deprecated_nullmask[row_id] = false; + } + // Unsupported type, e.g., a LIST. By returning DuckDBSuccess here, + // we allow filling other columns, and return NULL for all unsupported types. + return DuckDBSuccess; + } + + column->__deprecated_data = duckdb_malloc(type_size * row_count); if (!column->__deprecated_nullmask || !column->__deprecated_data) { // LCOV_EXCL_START // malloc failure return DuckDBError; @@ -295,7 +306,7 @@ duckdb_state DuckDBTranslateResult(unique_ptr result_p, duckdb_resu return DuckDBError; } // copy the data - // first write the meta data + // first write the metadata out->__deprecated_column_count = result.ColumnCount(); out->__deprecated_rows_changed = 0; return DuckDBSuccess; @@ -329,6 +340,7 @@ bool DeprecatedMaterializeResult(duckdb_result *result) { // malloc failure return DuckDBError; } // LCOV_EXCL_STOP + if (result_data->result->type == QueryResultType::STREAM_RESULT) { // if we are dealing with a stream result, convert it to a materialized result first auto &stream_result = (StreamQueryResult &)*result_data->result; @@ -344,6 +356,7 @@ bool DeprecatedMaterializeResult(duckdb_result *result) { result->__deprecated_columns[i].__deprecated_type = ConvertCPPTypeToC(result_data->result->types[i]); result->__deprecated_columns[i].__deprecated_name = (char *)result_data->result->names[i].c_str(); // NOLINT } + result->__deprecated_row_count = materialized.RowCount(); if (result->__deprecated_row_count > 0 && materialized.properties.return_type == StatementReturnType::CHANGED_ROWS) { @@ -353,7 +366,8 @@ bool DeprecatedMaterializeResult(duckdb_result *result) { result->__deprecated_rows_changed = NumericCast(row_changes.GetValue()); } } - // now write the data + + // Now write the data and skip any unsupported columns. for (idx_t col = 0; col < column_count; col++) { auto state = deprecated_duckdb_translate_column(materialized, &result->__deprecated_columns[col], col); if (state != DuckDBSuccess) { diff --git a/src/main/capi/scalar_function-c.cpp b/src/main/capi/scalar_function-c.cpp new file mode 100644 index 00000000000..c0d825e9cfc --- /dev/null +++ b/src/main/capi/scalar_function-c.cpp @@ -0,0 +1,151 @@ +#include "duckdb/main/capi/capi_internal.hpp" +#include "duckdb/function/scalar_function.hpp" +#include "duckdb/parser/parsed_data/create_scalar_function_info.hpp" +#include "duckdb/catalog/catalog.hpp" +#include "duckdb/main/client_context.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" + +namespace duckdb { + +struct CScalarFunctionInfo : public ScalarFunctionInfo { + ~CScalarFunctionInfo() override { + if (extra_info && delete_callback) { + delete_callback(extra_info); + } + extra_info = nullptr; + delete_callback = nullptr; + } + + duckdb_scalar_function_t function = nullptr; + duckdb_function_info extra_info = nullptr; + duckdb_delete_callback_t delete_callback = nullptr; +}; + +struct CScalarFunctionBindData : public FunctionData { + explicit CScalarFunctionBindData(CScalarFunctionInfo &info) : info(info) { + } + + unique_ptr Copy() const override { + return make_uniq(info); + } + bool Equals(const FunctionData &other_p) const override { + auto &other = other_p.Cast(); + return info.extra_info == other.info.extra_info && info.function == other.info.function; + } + + CScalarFunctionInfo &info; +}; + +duckdb::ScalarFunction &GetCScalarFunction(duckdb_scalar_function function) { + return *reinterpret_cast(function); +} + +unique_ptr BindCAPIScalarFunction(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + auto &info = bound_function.function_info->Cast(); + return make_uniq(info); +} + +void CAPIScalarFunction(DataChunk &input, ExpressionState &state, Vector &result) { + auto &bind_info = state.expr.Cast().bind_info; + auto &c_bind_info = bind_info->Cast(); + + auto all_const = input.AllConstant(); + input.Flatten(); + auto c_input = reinterpret_cast(&input); + auto c_result = reinterpret_cast(&result); + c_bind_info.info.function(c_bind_info.info.extra_info, c_input, c_result); + if (all_const) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + } +} + +} // namespace duckdb + +using duckdb::GetCScalarFunction; + +duckdb_scalar_function duckdb_create_scalar_function() { + auto function = new duckdb::ScalarFunction("", {}, duckdb::LogicalType::INVALID, duckdb::CAPIScalarFunction, + duckdb::BindCAPIScalarFunction); + function->function_info = duckdb::make_shared_ptr(); + return reinterpret_cast(function); +} + +void duckdb_destroy_scalar_function(duckdb_scalar_function *function) { + if (function && *function) { + auto scalar_function = reinterpret_cast(*function); + delete scalar_function; + *function = nullptr; + } +} + +void duckdb_scalar_function_set_name(duckdb_scalar_function function, const char *name) { + if (!function || !name) { + return; + } + auto &scalar_function = GetCScalarFunction(function); + scalar_function.name = name; +} + +void duckdb_scalar_function_add_parameter(duckdb_scalar_function function, duckdb_logical_type type) { + if (!function || !type) { + return; + } + auto &scalar_function = GetCScalarFunction(function); + auto logical_type = reinterpret_cast(type); + scalar_function.arguments.push_back(*logical_type); +} + +void duckdb_scalar_function_set_return_type(duckdb_scalar_function function, duckdb_logical_type type) { + if (!function || !type) { + return; + } + auto &scalar_function = GetCScalarFunction(function); + auto logical_type = reinterpret_cast(type); + scalar_function.return_type = *logical_type; +} + +void duckdb_scalar_function_set_extra_info(duckdb_scalar_function function, void *extra_info, + duckdb_delete_callback_t destroy) { + if (!function || !extra_info) { + return; + } + auto &scalar_function = GetCScalarFunction(function); + auto &info = scalar_function.function_info->Cast(); + info.extra_info = reinterpret_cast(extra_info); + info.delete_callback = destroy; +} + +void duckdb_scalar_function_set_function(duckdb_scalar_function function, duckdb_scalar_function_t execute_func) { + if (!function || !execute_func) { + return; + } + auto &scalar_function = GetCScalarFunction(function); + auto &info = scalar_function.function_info->Cast(); + info.function = execute_func; +} + +duckdb_state duckdb_register_scalar_function(duckdb_connection connection, duckdb_scalar_function function) { + if (!connection || !function) { + return DuckDBError; + } + auto &scalar_function = GetCScalarFunction(function); + auto &info = scalar_function.function_info->Cast(); + if (scalar_function.name.empty() || !info.function || + scalar_function.return_type.id() == duckdb::LogicalTypeId::INVALID) { + return DuckDBError; + } + auto con = reinterpret_cast(connection); + try { + con->context->RunFunctionInTransaction([&]() { + auto &catalog = duckdb::Catalog::GetSystemCatalog(*con->context); + duckdb::CreateScalarFunctionInfo sf_info(scalar_function); + + // create the function in the catalog + catalog.CreateFunction(*con->context, sf_info); + }); + } catch (...) { + return DuckDBError; + } + return DuckDBSuccess; +} diff --git a/src/main/capi/stream-c.cpp b/src/main/capi/stream-c.cpp index 8fcc42fbab2..5b950599f23 100644 --- a/src/main/capi/stream-c.cpp +++ b/src/main/capi/stream-c.cpp @@ -7,19 +7,28 @@ duckdb_data_chunk duckdb_stream_fetch_chunk(duckdb_result result) { return nullptr; } auto &result_data = *((duckdb::DuckDBResultData *)result.internal_data); - if (result_data.result_set_type == duckdb::CAPIResultSetType::CAPI_RESULT_TYPE_DEPRECATED) { - return nullptr; - } if (result_data.result->type != duckdb::QueryResultType::STREAM_RESULT) { // We can only fetch from a StreamQueryResult return nullptr; } - result_data.result_set_type = duckdb::CAPIResultSetType::CAPI_RESULT_TYPE_STREAMING; - auto &streaming = (duckdb::StreamQueryResult &)*result_data.result; - if (!streaming.IsOpen()) { + return duckdb_fetch_chunk(result); +} + +duckdb_data_chunk duckdb_fetch_chunk(duckdb_result result) { + if (!result.internal_data) { return nullptr; } + auto &result_data = *((duckdb::DuckDBResultData *)result.internal_data); + if (result_data.result_set_type == duckdb::CAPIResultSetType::CAPI_RESULT_TYPE_DEPRECATED) { + return nullptr; + } + result_data.result_set_type = duckdb::CAPIResultSetType::CAPI_RESULT_TYPE_STREAMING; + auto &result_instance = (duckdb::QueryResult &)*result_data.result; // FetchRaw ? Do we care about flattening them? - auto chunk = streaming.Fetch(); - return reinterpret_cast(chunk.release()); + try { + auto chunk = result_instance.Fetch(); + return reinterpret_cast(chunk.release()); + } catch (std::exception &e) { + return nullptr; + } } diff --git a/src/main/capi/table_description-c.cpp b/src/main/capi/table_description-c.cpp new file mode 100644 index 00000000000..495267f984e --- /dev/null +++ b/src/main/capi/table_description-c.cpp @@ -0,0 +1,82 @@ +#include "duckdb/main/capi/capi_internal.hpp" +#include "duckdb/common/string_util.hpp" + +using duckdb::Connection; +using duckdb::ErrorData; +using duckdb::TableDescription; +using duckdb::TableDescriptionWrapper; + +duckdb_state duckdb_table_description_create(duckdb_connection connection, const char *schema, const char *table, + duckdb_table_description *out) { + Connection *conn = reinterpret_cast(connection); + + if (!out) { + return DuckDBError; + } + auto wrapper = new TableDescriptionWrapper(); + *out = (duckdb_table_description)wrapper; + + if (!connection || !table) { + return DuckDBError; + } + + if (schema == nullptr) { + schema = DEFAULT_SCHEMA; + } + + try { + wrapper->description = conn->TableInfo(schema, table); + } catch (std::exception &ex) { + ErrorData error(ex); + wrapper->error = error.RawMessage(); + return DuckDBError; + } catch (...) { // LCOV_EXCL_START + wrapper->error = "Unknown Connection::TableInfo error"; + return DuckDBError; + } // LCOV_EXCL_STOP + if (!wrapper->description) { + wrapper->error = "No table with that schema+name could be located"; + return DuckDBError; + } + return DuckDBSuccess; +} + +void duckdb_table_description_destroy(duckdb_table_description *table) { + if (!table || !*table) { + return; + } + auto wrapper = reinterpret_cast(*table); + delete wrapper; + *table = nullptr; +} + +const char *duckdb_table_description_error(duckdb_table_description table) { + if (!table) { + return nullptr; + } + auto wrapper = reinterpret_cast(table); + if (wrapper->error.empty()) { + return nullptr; + } + return wrapper->error.c_str(); +} + +duckdb_state duckdb_column_has_default(duckdb_table_description table_description, idx_t index, bool *out) { + auto wrapper = reinterpret_cast(table_description); + if (!wrapper || !out) { + if (wrapper) { + wrapper->error = "Please provide a valid (non-null) 'out' variable"; + } + return DuckDBError; + } + + auto &table = wrapper->description; + if (index >= table->columns.size()) { + wrapper->error = duckdb::StringUtil::Format("Column index %d is out of range, table only has %d columns", index, + table->columns.size()); + return DuckDBError; + } + auto &column = table->columns[index]; + *out = column.HasDefaultValue(); + return DuckDBSuccess; +} diff --git a/src/main/capi/table_function-c.cpp b/src/main/capi/table_function-c.cpp index a6916e8e200..4d0116e37d6 100644 --- a/src/main/capi/table_function-c.cpp +++ b/src/main/capi/table_function-c.cpp @@ -7,8 +7,11 @@ namespace duckdb { +//===--------------------------------------------------------------------===// +// Structures +//===--------------------------------------------------------------------===// struct CTableFunctionInfo : public TableFunctionInfo { - ~CTableFunctionInfo() { + ~CTableFunctionInfo() override { if (extra_info && delete_callback) { delete_callback(extra_info); } @@ -25,9 +28,9 @@ struct CTableFunctionInfo : public TableFunctionInfo { }; struct CTableBindData : public TableFunctionData { - CTableBindData(CTableFunctionInfo &info) : info(info) { + explicit CTableBindData(CTableFunctionInfo &info) : info(info) { } - ~CTableBindData() { + ~CTableBindData() override { if (bind_data && delete_callback) { delete_callback(bind_data); } @@ -110,13 +113,50 @@ struct CTableInternalFunctionInfo { string error; }; +//===--------------------------------------------------------------------===// +// Helper Functions +//===--------------------------------------------------------------------===// +duckdb::TableFunction &GetCTableFunction(duckdb_table_function function) { + return *reinterpret_cast(function); +} + +duckdb::CTableInternalBindInfo &GetCBindInfo(duckdb_bind_info info) { + D_ASSERT(info); + return *reinterpret_cast(info); +} + +duckdb_bind_info ToCBindInfo(duckdb::CTableInternalBindInfo &info) { + return reinterpret_cast(&info); +} + +duckdb::CTableInternalInitInfo &GetCInitInfo(duckdb_init_info info) { + D_ASSERT(info); + return *reinterpret_cast(info); +} + +duckdb_init_info ToCInitInfo(duckdb::CTableInternalInitInfo &info) { + return reinterpret_cast(&info); +} + +duckdb::CTableInternalFunctionInfo &GetCFunctionInfo(duckdb_function_info info) { + D_ASSERT(info); + return *reinterpret_cast(info); +} + +duckdb_function_info ToCFunctionInfo(duckdb::CTableInternalFunctionInfo &info) { + return reinterpret_cast(&info); +} + +//===--------------------------------------------------------------------===// +// Table Callbacks +//===--------------------------------------------------------------------===// unique_ptr CTableFunctionBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { auto &info = input.info->Cast(); D_ASSERT(info.bind && info.function && info.init); auto result = make_uniq(info); CTableInternalBindInfo bind_info(context, input, return_types, names, *result, info); - info.bind(&bind_info); + info.bind(ToCBindInfo(bind_info)); if (!bind_info.success) { throw BinderException(bind_info.error); } @@ -129,7 +169,7 @@ unique_ptr CTableFunctionInit(ClientContext &context, auto result = make_uniq(); CTableInternalInitInfo init_info(bind_data, result->init_data, data_p.column_ids, data_p.filters); - bind_data.info.init(&init_info); + bind_data.info.init(ToCInitInfo(init_info)); if (!init_info.success) { throw InvalidInputException(init_info.error); } @@ -145,7 +185,7 @@ unique_ptr CTableFunctionLocalInit(ExecutionContext &co } CTableInternalInitInfo init_info(bind_data, result->init_data, data_p.column_ids, data_p.filters); - bind_data.info.local_init(&init_info); + bind_data.info.local_init(ToCInitInfo(init_info)); if (!init_info.success) { throw InvalidInputException(init_info.error); } @@ -162,10 +202,10 @@ unique_ptr CTableFunctionCardinality(ClientContext &context, con void CTableFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { auto &bind_data = data_p.bind_data->Cast(); - auto &global_data = (CTableGlobalInitData &)*data_p.global_state; - auto &local_data = (CTableLocalInitData &)*data_p.local_state; + auto &global_data = data_p.global_state->Cast(); + auto &local_data = data_p.local_state->Cast(); CTableInternalFunctionInfo function_info(bind_data, global_data.init_data, local_data.init_data); - bind_data.info.function(&function_info, reinterpret_cast(&output)); + bind_data.info.function(ToCFunctionInfo(function_info), reinterpret_cast(&output)); if (!function_info.success) { throw InvalidInputException(function_info.error); } @@ -176,17 +216,19 @@ void CTableFunction(ClientContext &context, TableFunctionInput &data_p, DataChun //===--------------------------------------------------------------------===// // Table Function //===--------------------------------------------------------------------===// +using duckdb::GetCTableFunction; + duckdb_table_function duckdb_create_table_function() { auto function = new duckdb::TableFunction("", {}, duckdb::CTableFunction, duckdb::CTableFunctionBind, duckdb::CTableFunctionInit, duckdb::CTableFunctionLocalInit); function->function_info = duckdb::make_shared_ptr(); function->cardinality = duckdb::CTableFunctionCardinality; - return function; + return reinterpret_cast(function); } void duckdb_destroy_table_function(duckdb_table_function *function) { if (function && *function) { - auto tf = (duckdb::TableFunction *)*function; + auto tf = reinterpret_cast(*function); delete tf; *function = nullptr; } @@ -196,17 +238,17 @@ void duckdb_table_function_set_name(duckdb_table_function function, const char * if (!function || !name) { return; } - auto tf = (duckdb::TableFunction *)function; - tf->name = name; + auto &tf = GetCTableFunction(function); + tf.name = name; } void duckdb_table_function_add_parameter(duckdb_table_function function, duckdb_logical_type type) { if (!function || !type) { return; } - auto tf = (duckdb::TableFunction *)function; - auto logical_type = (duckdb::LogicalType *)type; - tf->arguments.push_back(*logical_type); + auto &tf = GetCTableFunction(function); + auto logical_type = reinterpret_cast(type); + tf.arguments.push_back(*logical_type); } void duckdb_table_function_add_named_parameter(duckdb_table_function function, const char *name, @@ -214,9 +256,9 @@ void duckdb_table_function_add_named_parameter(duckdb_table_function function, c if (!function || !type) { return; } - auto tf = (duckdb::TableFunction *)function; - auto logical_type = (duckdb::LogicalType *)type; - tf->named_parameters.insert({name, *logical_type}); + auto &tf = GetCTableFunction(function); + auto logical_type = reinterpret_cast(type); + tf.named_parameters.insert({name, *logical_type}); } void duckdb_table_function_set_extra_info(duckdb_table_function function, void *extra_info, @@ -224,119 +266,124 @@ void duckdb_table_function_set_extra_info(duckdb_table_function function, void * if (!function) { return; } - auto tf = (duckdb::TableFunction *)function; - auto info = (duckdb::CTableFunctionInfo *)tf->function_info.get(); - info->extra_info = extra_info; - info->delete_callback = destroy; + auto &tf = GetCTableFunction(function); + auto &info = tf.function_info->Cast(); + info.extra_info = extra_info; + info.delete_callback = destroy; } void duckdb_table_function_set_bind(duckdb_table_function function, duckdb_table_function_bind_t bind) { if (!function || !bind) { return; } - auto tf = (duckdb::TableFunction *)function; - auto info = (duckdb::CTableFunctionInfo *)tf->function_info.get(); - info->bind = bind; + auto &tf = GetCTableFunction(function); + auto &info = tf.function_info->Cast(); + info.bind = bind; } void duckdb_table_function_set_init(duckdb_table_function function, duckdb_table_function_init_t init) { if (!function || !init) { return; } - auto tf = (duckdb::TableFunction *)function; - auto info = (duckdb::CTableFunctionInfo *)tf->function_info.get(); - info->init = init; + auto &tf = GetCTableFunction(function); + auto &info = tf.function_info->Cast(); + info.init = init; } void duckdb_table_function_set_local_init(duckdb_table_function function, duckdb_table_function_init_t init) { if (!function || !init) { return; } - auto tf = (duckdb::TableFunction *)function; - auto info = (duckdb::CTableFunctionInfo *)tf->function_info.get(); - info->local_init = init; + auto &tf = GetCTableFunction(function); + auto &info = tf.function_info->Cast(); + info.local_init = init; } void duckdb_table_function_set_function(duckdb_table_function table_function, duckdb_table_function_t function) { if (!table_function || !function) { return; } - auto tf = (duckdb::TableFunction *)table_function; - auto info = (duckdb::CTableFunctionInfo *)tf->function_info.get(); - info->function = function; + auto &tf = GetCTableFunction(table_function); + auto &info = tf.function_info->Cast(); + info.function = function; } void duckdb_table_function_supports_projection_pushdown(duckdb_table_function table_function, bool pushdown) { if (!table_function) { return; } - auto tf = (duckdb::TableFunction *)table_function; - tf->projection_pushdown = pushdown; + auto &tf = GetCTableFunction(table_function); + tf.projection_pushdown = pushdown; } duckdb_state duckdb_register_table_function(duckdb_connection connection, duckdb_table_function function) { if (!connection || !function) { return DuckDBError; } - auto con = (duckdb::Connection *)connection; - auto tf = (duckdb::TableFunction *)function; - auto info = (duckdb::CTableFunctionInfo *)tf->function_info.get(); - if (tf->name.empty() || !info->bind || !info->init || !info->function) { + auto con = reinterpret_cast(connection); + auto &tf = GetCTableFunction(function); + auto &info = tf.function_info->Cast(); + if (tf.name.empty() || !info.bind || !info.init || !info.function) { return DuckDBError; } - con->context->RunFunctionInTransaction([&]() { - auto &catalog = duckdb::Catalog::GetSystemCatalog(*con->context); - duckdb::CreateTableFunctionInfo tf_info(*tf); - - // create the function in the catalog - catalog.CreateTableFunction(*con->context, tf_info); - }); + try { + con->context->RunFunctionInTransaction([&]() { + auto &catalog = duckdb::Catalog::GetSystemCatalog(*con->context); + duckdb::CreateTableFunctionInfo tf_info(tf); + // create the function in the catalog + catalog.CreateTableFunction(*con->context, tf_info); + }); + } catch (...) { // LCOV_EXCL_START + return DuckDBError; + } // LCOV_EXCL_STOP return DuckDBSuccess; } //===--------------------------------------------------------------------===// // Bind Interface //===--------------------------------------------------------------------===// +using duckdb::GetCBindInfo; + void *duckdb_bind_get_extra_info(duckdb_bind_info info) { if (!info) { return nullptr; } - auto bind_info = (duckdb::CTableInternalBindInfo *)info; - return bind_info->function_info.extra_info; + auto &bind_info = GetCBindInfo(info); + return bind_info.function_info.extra_info; } void duckdb_bind_add_result_column(duckdb_bind_info info, const char *name, duckdb_logical_type type) { if (!info || !name || !type) { return; } - auto bind_info = (duckdb::CTableInternalBindInfo *)info; - bind_info->names.push_back(name); - bind_info->return_types.push_back(*(reinterpret_cast(type))); + auto &bind_info = GetCBindInfo(info); + bind_info.names.push_back(name); + bind_info.return_types.push_back(*(reinterpret_cast(type))); } idx_t duckdb_bind_get_parameter_count(duckdb_bind_info info) { if (!info) { return 0; } - auto bind_info = (duckdb::CTableInternalBindInfo *)info; - return bind_info->input.inputs.size(); + auto &bind_info = GetCBindInfo(info); + return bind_info.input.inputs.size(); } duckdb_value duckdb_bind_get_parameter(duckdb_bind_info info, idx_t index) { if (!info || index >= duckdb_bind_get_parameter_count(info)) { return nullptr; } - auto bind_info = (duckdb::CTableInternalBindInfo *)info; - return reinterpret_cast(new duckdb::Value(bind_info->input.inputs[index])); + auto &bind_info = GetCBindInfo(info); + return reinterpret_cast(new duckdb::Value(bind_info.input.inputs[index])); } duckdb_value duckdb_bind_get_named_parameter(duckdb_bind_info info, const char *name) { if (!info || !name) { return nullptr; } - auto bind_info = (duckdb::CTableInternalBindInfo *)info; - auto t = bind_info->input.named_parameters.find(name); - if (t == bind_info->input.named_parameters.end()) { + auto &bind_info = GetCBindInfo(info); + auto t = bind_info.input.named_parameters.find(name); + if (t == bind_info.input.named_parameters.end()) { return nullptr; } else { return reinterpret_cast(new duckdb::Value(t->second)); @@ -347,20 +394,20 @@ void duckdb_bind_set_bind_data(duckdb_bind_info info, void *bind_data, duckdb_de if (!info) { return; } - auto bind_info = (duckdb::CTableInternalBindInfo *)info; - bind_info->bind_data.bind_data = bind_data; - bind_info->bind_data.delete_callback = destroy; + auto &bind_info = GetCBindInfo(info); + bind_info.bind_data.bind_data = bind_data; + bind_info.bind_data.delete_callback = destroy; } void duckdb_bind_set_cardinality(duckdb_bind_info info, idx_t cardinality, bool is_exact) { if (!info) { return; } - auto bind_info = (duckdb::CTableInternalBindInfo *)info; + auto &bind_info = GetCBindInfo(info); if (is_exact) { - bind_info->bind_data.stats = duckdb::make_uniq(cardinality); + bind_info.bind_data.stats = duckdb::make_uniq(cardinality); } else { - bind_info->bind_data.stats = duckdb::make_uniq(cardinality, cardinality); + bind_info.bind_data.stats = duckdb::make_uniq(cardinality, cardinality); } } @@ -368,19 +415,21 @@ void duckdb_bind_set_error(duckdb_bind_info info, const char *error) { if (!info || !error) { return; } - auto function_info = (duckdb::CTableInternalBindInfo *)info; - function_info->error = error; - function_info->success = false; + auto &bind_info = GetCBindInfo(info); + bind_info.error = error; + bind_info.success = false; } //===--------------------------------------------------------------------===// // Init Interface //===--------------------------------------------------------------------===// +using duckdb::GetCInitInfo; + void *duckdb_init_get_extra_info(duckdb_init_info info) { if (!info) { return nullptr; } - auto init_info = (duckdb::CTableInternalInitInfo *)info; + auto init_info = reinterpret_cast(info); return init_info->bind_data.info.extra_info; } @@ -388,95 +437,97 @@ void *duckdb_init_get_bind_data(duckdb_init_info info) { if (!info) { return nullptr; } - auto init_info = (duckdb::CTableInternalInitInfo *)info; - return init_info->bind_data.bind_data; + auto &init_info = GetCInitInfo(info); + return init_info.bind_data.bind_data; } void duckdb_init_set_init_data(duckdb_init_info info, void *init_data, duckdb_delete_callback_t destroy) { if (!info) { return; } - auto init_info = (duckdb::CTableInternalInitInfo *)info; - init_info->init_data.init_data = init_data; - init_info->init_data.delete_callback = destroy; + auto &init_info = GetCInitInfo(info); + init_info.init_data.init_data = init_data; + init_info.init_data.delete_callback = destroy; } void duckdb_init_set_error(duckdb_init_info info, const char *error) { if (!info || !error) { return; } - auto function_info = (duckdb::CTableInternalInitInfo *)info; - function_info->error = error; - function_info->success = false; + auto &init_info = GetCInitInfo(info); + init_info.error = error; + init_info.success = false; } idx_t duckdb_init_get_column_count(duckdb_init_info info) { if (!info) { return 0; } - auto function_info = (duckdb::CTableInternalInitInfo *)info; - return function_info->column_ids.size(); + auto &init_info = GetCInitInfo(info); + return init_info.column_ids.size(); } idx_t duckdb_init_get_column_index(duckdb_init_info info, idx_t column_index) { if (!info) { return 0; } - auto function_info = (duckdb::CTableInternalInitInfo *)info; - if (column_index >= function_info->column_ids.size()) { + auto &init_info = GetCInitInfo(info); + if (column_index >= init_info.column_ids.size()) { return 0; } - return function_info->column_ids[column_index]; + return init_info.column_ids[column_index]; } void duckdb_init_set_max_threads(duckdb_init_info info, idx_t max_threads) { if (!info) { return; } - auto function_info = (duckdb::CTableInternalInitInfo *)info; - function_info->init_data.max_threads = max_threads; + auto &init_info = GetCInitInfo(info); + init_info.init_data.max_threads = max_threads; } //===--------------------------------------------------------------------===// // Function Interface //===--------------------------------------------------------------------===// +using duckdb::GetCFunctionInfo; + void *duckdb_function_get_extra_info(duckdb_function_info info) { if (!info) { return nullptr; } - auto function_info = (duckdb::CTableInternalFunctionInfo *)info; - return function_info->bind_data.info.extra_info; + auto &function_info = GetCFunctionInfo(info); + return function_info.bind_data.info.extra_info; } void *duckdb_function_get_bind_data(duckdb_function_info info) { if (!info) { return nullptr; } - auto function_info = (duckdb::CTableInternalFunctionInfo *)info; - return function_info->bind_data.bind_data; + auto &function_info = GetCFunctionInfo(info); + return function_info.bind_data.bind_data; } void *duckdb_function_get_init_data(duckdb_function_info info) { if (!info) { return nullptr; } - auto function_info = (duckdb::CTableInternalFunctionInfo *)info; - return function_info->init_data.init_data; + auto &function_info = GetCFunctionInfo(info); + return function_info.init_data.init_data; } void *duckdb_function_get_local_init_data(duckdb_function_info info) { if (!info) { return nullptr; } - auto function_info = (duckdb::CTableInternalFunctionInfo *)info; - return function_info->local_data.init_data; + auto &function_info = GetCFunctionInfo(info); + return function_info.local_data.init_data; } void duckdb_function_set_error(duckdb_function_info info, const char *error) { if (!info || !error) { return; } - auto function_info = (duckdb::CTableInternalFunctionInfo *)info; - function_info->error = error; - function_info->success = false; + auto &function_info = GetCFunctionInfo(info); + function_info.error = error; + function_info.success = false; } diff --git a/src/main/client_config.cpp b/src/main/client_config.cpp new file mode 100644 index 00000000000..c3350a6be78 --- /dev/null +++ b/src/main/client_config.cpp @@ -0,0 +1,17 @@ +#include "duckdb/main/client_config.hpp" + +#include "duckdb/common/file_system.hpp" + +namespace duckdb { + +void ClientConfig::SetDefaultStreamingBufferSize() { + auto memory = FileSystem::GetAvailableMemory(); + auto default_size = ClientConfig().streaming_buffer_size; + if (!memory.IsValid()) { + streaming_buffer_size = default_size; + return; + } + streaming_buffer_size = MinValue(memory.GetIndex(), default_size); +} + +} // namespace duckdb diff --git a/src/main/client_context.cpp b/src/main/client_context.cpp index 29a4b3e3fab..ebea69db927 100644 --- a/src/main/client_context.cpp +++ b/src/main/client_context.cpp @@ -127,7 +127,7 @@ struct DebugClientContextState : public ClientContextState { } return RebindQueryInfo::DO_NOT_REBIND; } - RebindQueryInfo OnExecutePrepared(ClientContext &context, PreparedStatementData &prepared_statement, + RebindQueryInfo OnExecutePrepared(ClientContext &context, PreparedStatementCallbackInfo &info, RebindQueryInfo current_rebind) override { return RebindQueryInfo::ATTEMPT_TO_REBIND; } @@ -520,7 +520,8 @@ unique_ptr ClientContext::PendingPreparedStatement(ClientCon rebind = RebindQueryInfo::ATTEMPT_TO_REBIND; } for (auto const &s : registered_state) { - auto new_rebind = s.second->OnExecutePrepared(*this, *prepared, rebind); + PreparedStatementCallbackInfo info(*prepared, parameters); + auto new_rebind = s.second->OnExecutePrepared(*this, info, rebind); if (new_rebind == RebindQueryInfo::ATTEMPT_TO_REBIND) { rebind = RebindQueryInfo::ATTEMPT_TO_REBIND; } @@ -531,6 +532,10 @@ unique_ptr ClientContext::PendingPreparedStatement(ClientCon return PendingPreparedStatementInternal(lock, prepared, parameters); } +void ClientContext::WaitForTask(ClientContextLock &lock, BaseQueryResult &result) { + active_query->executor->WaitForTask(); +} + PendingExecutionResult ClientContext::ExecuteTaskInternal(ClientContextLock &lock, BaseQueryResult &result, bool dry_run) { D_ASSERT(active_query); @@ -753,13 +758,6 @@ bool ClientContext::IsActiveResult(ClientContextLock &lock, BaseQueryResult &res return active_query->IsOpenResult(result); } -void ClientContext::SetActiveResult(ClientContextLock &lock, BaseQueryResult &result) { - if (!active_query) { - return; - } - return active_query->SetOpenResult(result); -} - unique_ptr ClientContext::PendingStatementOrPreparedStatementInternal( ClientContextLock &lock, const string &query, unique_ptr statement, shared_ptr &prepared, const PendingQueryParameters ¶meters) { @@ -797,9 +795,12 @@ unique_ptr ClientContext::PendingStatementOrPreparedStatemen bool reparse_statement = false; #endif statement = std::move(copied_statement); + if (statement->type == StatementType::RELATION_STATEMENT) { + reparse_statement = false; + } if (reparse_statement) { try { - Parser parser; + Parser parser(GetParserOptions()); ErrorData error; parser.ParseQuery(statement->ToString()); statement = std::move(parser.statements[0]); @@ -1103,7 +1104,7 @@ unique_ptr ClientContext::TableInfo(const string &schema_name, result->schema = schema_name; result->table = table_name; for (auto &column : table->GetColumns().Logical()) { - result->columns.emplace_back(column.Name(), column.Type()); + result->columns.emplace_back(column.Copy()); } }); return result; @@ -1124,6 +1125,7 @@ void ClientContext::Append(TableDescription &description, ColumnDataCollection & } auto binder = Binder::CreateBinder(*this); auto bound_constraints = binder->BindConstraints(table_entry); + MetaTransaction::Get(*this).ModifyDatabase(table_entry.ParentCatalog().GetAttached()); table_entry.GetStorage().LocalAppend(table_entry, *this, collection, bound_constraints); }); } @@ -1278,7 +1280,8 @@ ClientProperties ClientContext::GetClientProperties() const { if (TryGetCurrentSetting("TimeZone", result)) { timezone = result.ToString(); } - return {timezone, db->config.options.arrow_offset_size}; + return {timezone, db->config.options.arrow_offset_size, db->config.options.arrow_use_list_view, + db->config.options.produce_arrow_string_views}; } bool ClientContext::ExecutionIsFinished() { diff --git a/src/main/client_context_file_opener.cpp b/src/main/client_context_file_opener.cpp index 17ddef4f03a..5c7387b864b 100644 --- a/src/main/client_context_file_opener.cpp +++ b/src/main/client_context_file_opener.cpp @@ -1,5 +1,7 @@ #include "duckdb/main/client_context_file_opener.hpp" +#include "duckdb/catalog/catalog_transaction.hpp" +#include "duckdb/main/database.hpp" #include "duckdb/common/file_opener.hpp" #include "duckdb/main/client_context.hpp" @@ -18,6 +20,22 @@ optional_ptr ClientContextFileOpener::TryGetDatabase() { return context.db.get(); } +unique_ptr FileOpener::TryGetCatalogTransaction(optional_ptr opener) { + if (!opener) { + return nullptr; + } + auto context = opener->TryGetClientContext(); + if (context) { + return make_uniq(CatalogTransaction::GetSystemCatalogTransaction(*context)); + } + + auto db = opener->TryGetDatabase(); + if (db) { + return make_uniq(CatalogTransaction::GetSystemTransaction(*db)); + } + return nullptr; +} + optional_ptr FileOpener::TryGetClientContext(optional_ptr opener) { if (!opener) { return nullptr; @@ -32,6 +50,19 @@ optional_ptr FileOpener::TryGetDatabase(optional_ptrTryGetDatabase(); } +optional_ptr FileOpener::TryGetSecretManager(optional_ptr opener) { + if (!opener) { + return nullptr; + } + + auto db = opener->TryGetDatabase(); + if (!db) { + return nullptr; + } + + return &db->GetSecretManager(); +} + SettingLookupResult FileOpener::TryGetCurrentSetting(optional_ptr opener, const string &key, Value &result) { if (!opener) { diff --git a/src/main/client_context_wrapper.cpp b/src/main/client_context_wrapper.cpp new file mode 100644 index 00000000000..d79b0930043 --- /dev/null +++ b/src/main/client_context_wrapper.cpp @@ -0,0 +1,22 @@ +#include "duckdb/main/client_context_wrapper.hpp" +#include "duckdb/main/client_context.hpp" + +namespace duckdb { + +ClientContextWrapper::ClientContextWrapper(const shared_ptr &context) : client_context(context) { +} + +shared_ptr ClientContextWrapper::TryGetContext() { + auto actual_context = client_context.lock(); + return actual_context; +} + +shared_ptr ClientContextWrapper::GetContext() { + auto actual_context = TryGetContext(); + if (!actual_context) { + throw ConnectionException("Connection has already been closed"); + } + return actual_context; +} + +} // namespace duckdb diff --git a/src/main/client_data.cpp b/src/main/client_data.cpp index 54c5292cf33..86c7bcf8ec1 100644 --- a/src/main/client_data.cpp +++ b/src/main/client_data.cpp @@ -3,15 +3,16 @@ #include "duckdb/catalog/catalog.hpp" #include "duckdb/catalog/catalog_search_path.hpp" #include "duckdb/common/http_state.hpp" +#include "duckdb/common/opener_file_system.hpp" #include "duckdb/common/random_engine.hpp" #include "duckdb/common/serializer/buffered_file_writer.hpp" +#include "duckdb/logging/http_logger.hpp" #include "duckdb/main/attached_database.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/main/client_context_file_opener.hpp" #include "duckdb/main/database.hpp" #include "duckdb/main/database_manager.hpp" #include "duckdb/main/query_profiler.hpp" -#include "duckdb/common/opener_file_system.hpp" namespace duckdb { @@ -36,12 +37,15 @@ class ClientFileSystem : public OpenerFileSystem { ClientData::ClientData(ClientContext &context) : catalog_search_path(make_uniq(context)) { auto &db = DatabaseInstance::GetDatabase(context); profiler = make_shared_ptr(context); + http_logger = make_shared_ptr(context); temporary_objects = make_shared_ptr(db, AttachedDatabaseType::TEMP_DATABASE); temporary_objects->oid = DatabaseManager::Get(db).ModifyCatalog(); random_engine = make_uniq(); file_opener = make_uniq(context); client_file_system = make_uniq(context); - temporary_objects->Initialize(); + + // NOTE: this becomes DEFAULT_BLOCK_ALLOC_SIZE once we start supporting different block sizes. + temporary_objects->Initialize(Storage::BLOCK_ALLOC_SIZE); } ClientData::~ClientData() { } diff --git a/src/main/config.cpp b/src/main/config.cpp index 56df902575a..bb1b3bf3068 100644 --- a/src/main/config.cpp +++ b/src/main/config.cpp @@ -10,8 +10,8 @@ #include "duckdb/common/thread.hpp" #endif -#include #include +#include namespace duckdb { @@ -59,6 +59,7 @@ static const ConfigurationOption internal_options[] = { DUCKDB_GLOBAL(AllowPersistentSecrets), DUCKDB_GLOBAL(CheckpointThresholdSetting), DUCKDB_GLOBAL(DebugCheckpointAbort), + DUCKDB_GLOBAL(StorageCompatibilityVersion), DUCKDB_LOCAL(DebugForceExternal), DUCKDB_LOCAL(DebugForceNoCrossProduct), DUCKDB_LOCAL(DebugAsOfIEJoin), @@ -72,6 +73,7 @@ static const ConfigurationOption internal_options[] = { DUCKDB_GLOBAL(EnableExternalAccessSetting), DUCKDB_GLOBAL(EnableFSSTVectors), DUCKDB_GLOBAL(AllowUnsignedExtensionsSetting), + DUCKDB_GLOBAL(AllowCommunityExtensionsSetting), DUCKDB_GLOBAL(AllowExtensionsMetadataMismatchSetting), DUCKDB_GLOBAL(AllowUnredactedSecretsSetting), DUCKDB_GLOBAL(CustomExtensionRepository), @@ -92,10 +94,13 @@ static const ConfigurationOption internal_options[] = { DUCKDB_GLOBAL(ForceBitpackingModeSetting), DUCKDB_LOCAL(HomeDirectorySetting), DUCKDB_LOCAL(LogQueryPathSetting), + DUCKDB_GLOBAL(EnableMacrosDependencies), + DUCKDB_GLOBAL(EnableViewDependencies), DUCKDB_GLOBAL(LockConfigurationSetting), DUCKDB_GLOBAL(ImmediateTransactionModeSetting), DUCKDB_LOCAL(IntegerDivisionSetting), DUCKDB_LOCAL(MaximumExpressionDepthSetting), + DUCKDB_LOCAL(StreamingBufferSize), DUCKDB_GLOBAL(MaximumMemorySetting), DUCKDB_GLOBAL(MaximumTempDirectorySize), DUCKDB_GLOBAL(OldImplicitCasting), @@ -111,6 +116,7 @@ static const ConfigurationOption internal_options[] = { DUCKDB_LOCAL(ProfileOutputSetting), DUCKDB_LOCAL(ProfilingModeSetting), DUCKDB_LOCAL_ALIAS("profiling_output", ProfileOutputSetting), + DUCKDB_LOCAL(CustomProfilingSettings), DUCKDB_LOCAL(ProgressBarTimeSetting), DUCKDB_LOCAL(SchemaSetting), DUCKDB_LOCAL(SearchPathSetting), @@ -120,13 +126,19 @@ static const ConfigurationOption internal_options[] = { DUCKDB_GLOBAL(ThreadsSetting), DUCKDB_GLOBAL(UsernameSetting), DUCKDB_GLOBAL(ExportLargeBufferArrow), + DUCKDB_GLOBAL(ArrowOutputListView), + DUCKDB_GLOBAL(ProduceArrowStringView), DUCKDB_GLOBAL_ALIAS("user", UsernameSetting), DUCKDB_GLOBAL_ALIAS("wal_autocheckpoint", CheckpointThresholdSetting), DUCKDB_GLOBAL_ALIAS("worker_threads", ThreadsSetting), DUCKDB_GLOBAL(FlushAllocatorSetting), + DUCKDB_GLOBAL(AllocatorBackgroundThreadsSetting), DUCKDB_GLOBAL(DuckDBApiSetting), DUCKDB_GLOBAL(CustomUserAgentSetting), DUCKDB_LOCAL(PartitionedWriteFlushThreshold), + DUCKDB_GLOBAL(DefaultBlockAllocSize), + DUCKDB_LOCAL(EnableHTTPLoggingSetting), + DUCKDB_LOCAL(HTTPLoggingOutputSetting), FINAL_SETTING}; vector DBConfig::GetOptions() { @@ -268,15 +280,21 @@ CastFunctionSet &DBConfig::GetCastFunctions() { return *cast_functions; } +CollationBinding &DBConfig::GetCollationBinding() { + return *collation_bindings; +} + IndexTypeSet &DBConfig::GetIndexTypes() { return *index_types; } void DBConfig::SetDefaultMaxMemory() { auto memory = FileSystem::GetAvailableMemory(); - if (memory.IsValid()) { - options.maximum_memory = memory.GetIndex() * 8 / 10; + if (!memory.IsValid()) { + options.maximum_memory = DBConfigOptions().maximum_memory; + return; } + options.maximum_memory = memory.GetIndex() * 8 / 10; } void DBConfig::SetDefaultTempDirectory() { @@ -477,4 +495,44 @@ const std::string DBConfig::UserAgent() const { return user_agent; } +SerializationCompatibility SerializationCompatibility::FromString(const string &input) { + if (input.empty()) { + throw InvalidInputException("Version string can not be empty"); + } + + auto serialization_version = GetSerializationVersion(input.c_str()); + if (!serialization_version.IsValid()) { + auto candidates = GetSerializationCandidates(); + throw InvalidInputException("The version string '%s' is not a valid DuckDB version, valid options are: %s", + input, StringUtil::Join(candidates, ", ")); + } + SerializationCompatibility result; + result.duckdb_version = input; + result.serialization_version = serialization_version.GetIndex(); + result.manually_set = true; + return result; +} + +SerializationCompatibility SerializationCompatibility::Default() { +#ifdef DUCKDB_ALTERNATIVE_VERIFY + auto res = FromString("latest"); + res.manually_set = false; + return res; +#else + auto res = FromString("v0.10.2"); + res.manually_set = false; + return res; +#endif +} + +SerializationCompatibility SerializationCompatibility::Latest() { + auto res = FromString("latest"); + res.manually_set = false; + return res; +} + +bool SerializationCompatibility::Compare(idx_t property_version) const { + return property_version <= serialization_version; +} + } // namespace duckdb diff --git a/src/main/connection_manager.cpp b/src/main/connection_manager.cpp index ef6b8017154..c0b53c6f45f 100644 --- a/src/main/connection_manager.cpp +++ b/src/main/connection_manager.cpp @@ -5,7 +5,7 @@ namespace duckdb { -ConnectionManager::ConnectionManager() : is_locking(false) { +ConnectionManager::ConnectionManager() { } void ConnectionManager::AddConnection(ClientContext &context) { @@ -13,7 +13,7 @@ void ConnectionManager::AddConnection(ClientContext &context) { for (auto &callback : DBConfig::GetConfig(context).extension_callbacks) { callback->OnConnectionOpened(context); } - connections.insert(make_pair(&context, weak_ptr(context.shared_from_this()))); + connections[context] = weak_ptr(context.shared_from_this()); } void ConnectionManager::RemoveConnection(ClientContext &context) { @@ -21,10 +21,16 @@ void ConnectionManager::RemoveConnection(ClientContext &context) { for (auto &callback : DBConfig::GetConfig(context).extension_callbacks) { callback->OnConnectionClosed(context); } - connections.erase(&context); + connections.erase(context); +} + +idx_t ConnectionManager::GetConnectionCount() const { + lock_guard lock(connections_lock); + return connections.size(); } vector> ConnectionManager::GetConnectionList() { + lock_guard lock(connections_lock); vector> result; for (auto &it : connections) { auto connection = it.second.lock(); @@ -39,24 +45,4 @@ vector> ConnectionManager::GetConnectionList() { return result; } -void ConnectionManager::LockClients(vector &client_locks, ClientContext &context) { - { - lock_guard l(lock_clients_lock); - if (is_locking) { - throw TransactionException("Failed to lock clients - another thread is running FORCE CHECKPOINT"); - } - is_locking = true; - } - client_locks.emplace_back(connections_lock, nullptr); - auto connection_list = GetConnectionList(); - for (auto &con : connection_list) { - if (con.get() == &context) { - continue; - } - auto &context_lock = con->context_lock; - client_locks.emplace_back(context_lock, std::move(con)); - } - is_locking = false; -} - } // namespace duckdb diff --git a/src/main/database.cpp b/src/main/database.cpp index a9a9354cf39..4fab31dd272 100644 --- a/src/main/database.cpp +++ b/src/main/database.cpp @@ -23,6 +23,7 @@ #include "duckdb/transaction/transaction_manager.hpp" #include "duckdb/execution/index/index_type_set.hpp" #include "duckdb/main/database_file_opener.hpp" +#include "duckdb/planner/collation_binding.hpp" #ifndef DUCKDB_NO_THREADS #include "duckdb/common/thread.hpp" @@ -33,6 +34,7 @@ namespace duckdb { DBConfig::DBConfig() { compression_functions = make_uniq(); cast_functions = make_uniq(*this); + collation_bindings = make_uniq(); index_types = make_uniq(); error_manager = make_uniq(); secret_manager = make_uniq(); @@ -63,8 +65,11 @@ DatabaseInstance::~DatabaseInstance() { scheduler.reset(); db_manager.reset(); buffer_manager.reset(); - // finally, flush allocations - Allocator::FlushAll(); + // finally, flush allocations and disable the background thread + if (Allocator::SupportsFlush()) { + Allocator::FlushAll(); + } + Allocator::SetBackgroundThreads(false); } BufferManager &BufferManager::GetBufferManager(DatabaseInstance &db) { @@ -143,29 +148,31 @@ ConnectionManager &ConnectionManager::Get(ClientContext &context) { } unique_ptr DatabaseInstance::CreateAttachedDatabase(ClientContext &context, const AttachInfo &info, - const string &type, AccessMode access_mode) { + const AttachOptions &options) { unique_ptr attached_database; - if (!type.empty()) { - // find the storage extension - auto extension_name = ExtensionHelper::ApplyExtensionAlias(type); + auto &catalog = Catalog::GetSystemCatalog(*this); + + if (!options.db_type.empty()) { + // Find the storage extension for this database file. + auto extension_name = ExtensionHelper::ApplyExtensionAlias(options.db_type); auto entry = config.storage_extensions.find(extension_name); if (entry == config.storage_extensions.end()) { - throw BinderException("Unrecognized storage type \"%s\"", type); + throw BinderException("Unrecognized storage type \"%s\"", options.db_type); } if (entry->second->attach != nullptr && entry->second->create_transaction_manager != nullptr) { - // use storage extension to create the initial database - attached_database = make_uniq(*this, Catalog::GetSystemCatalog(*this), *entry->second, - context, info.name, info, access_mode); - } else { + // Use the storage extension to create the initial database. attached_database = - make_uniq(*this, Catalog::GetSystemCatalog(*this), info.name, info.path, access_mode); + make_uniq(*this, catalog, *entry->second, context, info.name, info, options); + return attached_database; } - } else { - // check if this is an in-memory database or not - attached_database = - make_uniq(*this, Catalog::GetSystemCatalog(*this), info.name, info.path, access_mode); + + attached_database = make_uniq(*this, catalog, info.name, info.path, options); + return attached_database; } + + // An empty db_type defaults to a duckdb database file. + attached_database = make_uniq(*this, catalog, info.name, info.path, options); return attached_database; } @@ -178,13 +185,13 @@ void DatabaseInstance::CreateMainDatabase() { { Connection con(*this); con.BeginTransaction(); - initial_database = - db_manager->AttachDatabase(*con.context, info, config.options.database_type, config.options.access_mode); + AttachOptions options(config.options); + initial_database = db_manager->AttachDatabase(*con.context, info, options); con.Commit(); } initial_database->SetInitialDatabase(); - initial_database->Initialize(); + initial_database->Initialize(config.options.default_block_alloc_size); } void ThrowExtensionSetUnrecognizedOptions(const unordered_map &unrecognized_options) { @@ -375,7 +382,8 @@ void DatabaseInstance::Configure(DBConfig &new_config, const char *database_path if (new_config.buffer_pool) { config.buffer_pool = std::move(new_config.buffer_pool); } else { - config.buffer_pool = make_shared_ptr(config.options.maximum_memory); + config.buffer_pool = make_shared_ptr(config.options.maximum_memory, + config.options.buffer_manager_track_eviction_timestamps); } } @@ -395,7 +403,7 @@ const unordered_set &DatabaseInstance::LoadedExtensions() { return loaded_extensions; } -const unordered_map &DatabaseInstance::LoadedExtensionsData() { +const unordered_map &DatabaseInstance::LoadedExtensionsData() { return loaded_extensions_data; } @@ -412,10 +420,10 @@ bool DuckDB::ExtensionIsLoaded(const std::string &name) { return instance->ExtensionIsLoaded(name); } -void DatabaseInstance::SetExtensionLoaded(const std::string &name, const std::string &extension_version) { +void DatabaseInstance::SetExtensionLoaded(const string &name, ExtensionInstallInfo &install_info) { auto extension_name = ExtensionHelper::GetExtensionName(name); loaded_extensions.insert(extension_name); - loaded_extensions_data.insert({extension_name, ExtensionInfo(extension_version)}); + loaded_extensions_data.insert({extension_name, install_info}); auto &callbacks = DBConfig::GetConfig(*this).extension_callbacks; for (auto &callback : callbacks) { diff --git a/src/main/database_manager.cpp b/src/main/database_manager.cpp index e9b6812ece0..a66eda6da91 100644 --- a/src/main/database_manager.cpp +++ b/src/main/database_manager.cpp @@ -24,7 +24,8 @@ DatabaseManager &DatabaseManager::Get(AttachedDatabase &db) { } void DatabaseManager::InitializeSystemCatalog() { - system->Initialize(); + // The SYSTEM_DATABASE has no persistent storage. + system->Initialize(optional_idx()); } optional_ptr DatabaseManager::GetDatabase(ClientContext &context, const string &name) { @@ -35,15 +36,15 @@ optional_ptr DatabaseManager::GetDatabase(ClientContext &conte } optional_ptr DatabaseManager::AttachDatabase(ClientContext &context, const AttachInfo &info, - const string &db_type, AccessMode access_mode) { + const AttachOptions &options) { if (AttachedDatabase::NameIsReserved(info.name)) { throw BinderException("Attached database name \"%s\" cannot be used because it is a reserved name", info.name); } // now create the attached database auto &db = DatabaseInstance::GetDatabase(context); - auto attached_db = db.CreateAttachedDatabase(context, info, db_type, access_mode); + auto attached_db = db.CreateAttachedDatabase(context, info, options); - if (db_type.empty()) { + if (options.db_type.empty()) { InsertDatabasePath(context, info.path, attached_db->name); } @@ -133,42 +134,43 @@ void DatabaseManager::EraseDatabasePath(const string &path) { } } -void DatabaseManager::GetDatabaseType(ClientContext &context, string &db_type, AttachInfo &info, const DBConfig &config, - const string &unrecognized_option) { +void DatabaseManager::GetDatabaseType(ClientContext &context, AttachInfo &info, const DBConfig &config, + AttachOptions &options) { - // duckdb database file - if (StringUtil::CIEquals(db_type, "DUCKDB")) { - db_type = ""; + // Test if the database is a DuckDB database file. + if (StringUtil::CIEquals(options.db_type, "DUCKDB")) { + options.db_type = ""; - // DUCKDB format does not allow unrecognized options - if (!unrecognized_option.empty()) { - throw BinderException("Unrecognized option for attach \"%s\"", unrecognized_option); + // The DuckDB format does not allow unrecognized options. + if (!options.unrecognized_option.empty()) { + throw BinderException("Unrecognized option for attach \"%s\"", options.unrecognized_option); } return; } - // try to extract database type from path - if (db_type.empty()) { + // Try to extract the database type from the path. + if (options.db_type.empty()) { CheckPathConflict(context, info.path); auto &fs = FileSystem::GetFileSystem(context); - DBPathAndType::CheckMagicBytes(fs, info.path, db_type); + DBPathAndType::CheckMagicBytes(fs, info.path, options.db_type); } - // if we are loading a database type from an extension - check if that extension is loaded - if (!db_type.empty()) { - if (!Catalog::TryAutoLoad(context, db_type)) { + // If we are loading a database type from an extension, then we need to check if that extension is loaded. + if (!options.db_type.empty()) { + if (!Catalog::TryAutoLoad(context, options.db_type)) { // FIXME: Here it might be preferable to use an AutoLoadOrThrow kind of function // so that either there will be success or a message to throw, and load will be // attempted only once respecting the auto-loading options - ExtensionHelper::LoadExternalExtension(context, db_type); + ExtensionHelper::LoadExternalExtension(context, options.db_type); } return; } - // DUCKDB format does not allow unrecognized options - if (!unrecognized_option.empty()) { - throw BinderException("Unrecognized option for attach \"%s\"", unrecognized_option); + // The DuckDB file format does not allow unrecognized options, except for the block_size option, + // which is specific to DuckDB files. + if (!options.unrecognized_option.empty() && options.unrecognized_option != "block_size") { + throw BinderException("Unrecognized option for attach \"%s\"", options.unrecognized_option); } } diff --git a/src/main/extension.cpp b/src/main/extension.cpp index 4bfc5c87d28..8e81033b589 100644 --- a/src/main/extension.cpp +++ b/src/main/extension.cpp @@ -1,8 +1,64 @@ #include "duckdb/main/extension.hpp" +#include "duckdb/common/string_util.hpp" +#include "duckdb/main/extension_helper.hpp" namespace duckdb { Extension::~Extension() { } +static string PrettyPrintString(const string &s) { + string res = ""; + for (auto c : s) { + if (StringUtil::CharacterIsAlpha(c) || StringUtil::CharacterIsDigit(c) || c == '_' || c == '-' || c == ' ' || + c == '.') { + res += c; + } else { + auto value = UnsafeNumericCast(c); + res += "\\x"; + uint8_t first = value / 16; + if (first < 10) { + res.push_back((char)('0' + first)); + } else { + res.push_back((char)('a' + first - 10)); + } + uint8_t second = value % 16; + if (second < 10) { + res.push_back((char)('0' + second)); + } else { + res.push_back((char)('a' + second - 10)); + } + } + } + return res; +} + +string ParsedExtensionMetaData::GetInvalidMetadataError() { + const string engine_version = string(ExtensionHelper::GetVersionDirectoryName()); + const string engine_platform = string(DuckDB::Platform()); + + if (!AppearsValid()) { + return "The file is not a DuckDB extension. The metadata at the end of the file is invalid"; + } + + string result; + if (engine_version != duckdb_version) { + result += StringUtil::Format("The file was built for DuckDB version '%s', but we can only load extensions " + "built for DuckDB version '%s'.", + PrettyPrintString(duckdb_version), engine_version); + } + if (engine_platform != platform) { + if (!result.empty()) { + result += " Also, t"; + } else { + result += "T"; + } + result += StringUtil::Format( + "he file was built for the platform '%s', but we can only load extensions built for platform '%s'.", + PrettyPrintString(platform), engine_platform); + } + + return result; +} + } // namespace duckdb diff --git a/src/main/extension/CMakeLists.txt b/src/main/extension/CMakeLists.txt index 66a02231bda..4b4b6584f43 100644 --- a/src/main/extension/CMakeLists.txt +++ b/src/main/extension/CMakeLists.txt @@ -44,7 +44,7 @@ if(NOT ${DISABLE_BUILTIN_EXTENSIONS}) set(EXT_LOADER_BODY "${EXT_LOADER_BODY}\ if (extension==\"${EXT_NAME}\") { - db.LoadExtension<${EXT_NAME_CAMELCASE}Extension>(); + db.LoadStaticExtension<${EXT_NAME_CAMELCASE}Extension>(); return true; } ") diff --git a/src/main/extension/extension_helper.cpp b/src/main/extension/extension_helper.cpp index 818a25850b7..bbf98349ccf 100644 --- a/src/main/extension/extension_helper.cpp +++ b/src/main/extension/extension_helper.cpp @@ -1,10 +1,14 @@ #include "duckdb/main/extension_helper.hpp" #include "duckdb/common/file_system.hpp" +#include "duckdb/common/serializer/binary_deserializer.hpp" +#include "duckdb/common/serializer/buffered_file_reader.hpp" #include "duckdb/common/string_util.hpp" #include "duckdb/common/windows.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/main/database.hpp" +#include "duckdb/main/extension.hpp" +#include "duckdb/main/extension_install_info.hpp" // Note that c++ preprocessor doesn't have a nice way to clean this up so we need to set the defines we use to false // explicitly when they are undefined @@ -58,10 +62,6 @@ #include "icu_extension.hpp" #endif -#if DUCKDB_EXTENSION_EXCEL_LINKED -#include "excel_extension.hpp" -#endif - #if DUCKDB_EXTENSION_PARQUET_LINKED #include "parquet_extension.hpp" #endif @@ -122,6 +122,8 @@ static const DefaultExtension internal_extensions[] = { {"arrow", "A zero-copy data integration between Apache Arrow and DuckDB", false}, {"azure", "Adds a filesystem abstraction for Azure blob storage to DuckDB", false}, {"iceberg", "Adds support for Apache Iceberg", false}, + {"vss", "Adds indexing support to accelerate Vector Similarity Search", false}, + {"delta", "Adds support for Delta Lake", false}, {nullptr, nullptr, false}}; idx_t ExtensionHelper::DefaultExtensionCount() { @@ -208,8 +210,8 @@ bool ExtensionHelper::TryAutoLoadExtension(ClientContext &context, const string try { if (dbconfig.options.autoinstall_known_extensions) { auto &config = DBConfig::GetConfig(context); - ExtensionHelper::InstallExtension(context, extension_name, false, - config.options.autoinstall_extension_repo); + auto autoinstall_repo = ExtensionRepository::GetRepositoryByUrl(config.options.autoinstall_extension_repo); + ExtensionHelper::InstallExtension(context, extension_name, false, autoinstall_repo, false); } ExtensionHelper::LoadExternalExtension(context, extension_name); return true; @@ -218,6 +220,133 @@ bool ExtensionHelper::TryAutoLoadExtension(ClientContext &context, const string } } +static ExtensionUpdateResult UpdateExtensionInternal(DatabaseInstance &db, FileSystem &fs, + const string &full_extension_path, const string &extension_name) { + ExtensionUpdateResult result; + result.extension_name = extension_name; + + auto &config = DBConfig::GetConfig(db); + + if (!fs.FileExists(full_extension_path)) { + result.tag = ExtensionUpdateResultTag::NOT_INSTALLED; + return result; + } + + // Extension exists, check for .info file + const string info_file_path = full_extension_path + ".info"; + if (!fs.FileExists(info_file_path)) { + result.tag = ExtensionUpdateResultTag::MISSING_INSTALL_INFO; + return result; + } + + // Parse the version of the extension before updating + auto ext_binary_handle = fs.OpenFile(full_extension_path, FileOpenFlags::FILE_FLAGS_READ); + auto parsed_metadata = ExtensionHelper::ParseExtensionMetaData(*ext_binary_handle); + if (!parsed_metadata.AppearsValid() && !config.options.allow_extensions_metadata_mismatch) { + throw IOException( + "Failed to update extension: '%s', the metadata of the extension appears invalid! To resolve this, either " + "reinstall the extension using 'FORCE INSTALL %s', manually remove the file '%s', or enable '" + "SET allow_extensions_metadata_mismatch=true'", + extension_name, extension_name, full_extension_path); + } + + result.prev_version = parsed_metadata.AppearsValid() ? parsed_metadata.extension_version : ""; + + auto extension_install_info = ExtensionInstallInfo::TryReadInfoFile(fs, info_file_path, extension_name); + + // Early out: no info file found + if (extension_install_info->mode == ExtensionInstallMode::UNKNOWN) { + result.tag = ExtensionUpdateResultTag::MISSING_INSTALL_INFO; + return result; + } + + // Early out: we can only update extensions from repositories + if (extension_install_info->mode != ExtensionInstallMode::REPOSITORY) { + result.tag = ExtensionUpdateResultTag::NOT_A_REPOSITORY; + result.installed_version = result.prev_version; + return result; + } + + auto repository_from_info = ExtensionRepository::GetRepositoryByUrl(extension_install_info->repository_url); + result.repository = repository_from_info.ToReadableString(); + + // We force install the full url found in this file, throwing + unique_ptr install_result; + try { + install_result = ExtensionHelper::InstallExtension(config, fs, extension_name, true, repository_from_info); + } catch (std::exception &e) { + ErrorData error(e); + error.Throw("Extension updating failed when trying to install '" + extension_name + "', original error: "); + } + + result.installed_version = install_result->version; + + if (result.installed_version.empty()) { + result.tag = ExtensionUpdateResultTag::REDOWNLOADED; + } else if (result.installed_version != result.prev_version) { + result.tag = ExtensionUpdateResultTag::UPDATED; + } else { + result.tag = ExtensionUpdateResultTag::NO_UPDATE_AVAILABLE; + } + + return result; +} + +vector ExtensionHelper::UpdateExtensions(ClientContext &context) { + auto &fs = FileSystem::GetFileSystem(context); + return ExtensionHelper::UpdateExtensions(DatabaseInstance::GetDatabase(context), fs); +} + +vector ExtensionHelper::UpdateExtensions(DatabaseInstance &db, FileSystem &fs) { + vector result; + + auto &config = DBConfig::GetConfig(db); + +#ifndef WASM_LOADABLE_EXTENSIONS + case_insensitive_set_t seen_extensions; + + // scan the install directory for installed extensions + auto ext_directory = ExtensionHelper::ExtensionDirectory(config, fs); + fs.ListFiles(ext_directory, [&](const string &path, bool is_directory) { + if (!StringUtil::EndsWith(path, ".duckdb_extension")) { + return; + } + + auto extension_file_name = StringUtil::GetFileName(path); + auto extension_name = StringUtil::Split(extension_file_name, ".")[0]; + + seen_extensions.insert(extension_name); + + result.push_back(UpdateExtensionInternal(db, fs, fs.JoinPath(ext_directory, path), extension_name)); + }); +#endif + + return result; +} + +ExtensionUpdateResult ExtensionHelper::UpdateExtension(ClientContext &context, const string &extension_name) { + auto &fs = FileSystem::GetFileSystem(context); + return ExtensionHelper::UpdateExtension(DatabaseInstance::GetDatabase(context), fs, extension_name); +} + +ExtensionUpdateResult ExtensionHelper::UpdateExtension(DatabaseInstance &db, FileSystem &fs, + const string &extension_name) { + auto &config = DBConfig::GetConfig(db); + auto ext_directory = ExtensionHelper::ExtensionDirectory(config, fs); + + auto full_extension_path = fs.JoinPath(ext_directory, extension_name + ".duckdb_extension"); + + auto update_result = UpdateExtensionInternal(db, fs, full_extension_path, extension_name); + + if (update_result.tag == ExtensionUpdateResultTag::NOT_INSTALLED) { + throw InvalidInputException("Failed to update the extension '%s', the extension is not installed!", + extension_name); + } else if (update_result.tag == ExtensionUpdateResultTag::UNKNOWN) { + throw InternalException("Failed to update extension '%s', an unknown error ocurred", extension_name); + } + return update_result; +} + void ExtensionHelper::AutoLoadExtension(ClientContext &context, const string &extension_name) { return ExtensionHelper::AutoLoadExtension(*context.db, extension_name); } @@ -232,8 +361,9 @@ void ExtensionHelper::AutoLoadExtension(DatabaseInstance &db, const string &exte auto fs = FileSystem::CreateLocal(); #ifndef DUCKDB_WASM if (dbconfig.options.autoinstall_known_extensions) { - ExtensionHelper::InstallExtension(db.config, *fs, extension_name, false, - dbconfig.options.autoinstall_extension_repo); + //! Get the autoloading repository + auto repository = ExtensionRepository::GetRepositoryByUrl(dbconfig.options.autoinstall_extension_repo); + ExtensionHelper::InstallExtension(db.config, *fs, extension_name, false, repository); } #endif ExtensionHelper::LoadExternalExtension(db, *fs, extension_name); @@ -250,8 +380,8 @@ void ExtensionHelper::LoadAllExtensions(DuckDB &db) { // The in-tree extensions that we check. Non-cmake builds are currently limited to these for static linking // TODO: rewrite package_build.py to allow also loading out-of-tree extensions in non-cmake builds, after that // these can be removed - unordered_set extensions {"parquet", "icu", "tpch", "tpcds", "fts", "httpfs", - "json", "excel", "sqlsmith", "inet", "jemalloc", "autocomplete"}; + unordered_set extensions {"parquet", "icu", "tpch", "tpcds", "fts", "httpfs", + "json", "excel", "inet", "jemalloc", "autocomplete"}; for (auto &ext : extensions) { LoadExtensionInternal(db, ext, true); } @@ -313,83 +443,76 @@ ExtensionLoadResult ExtensionHelper::LoadExtensionInternal(DuckDB &db, const std // TODO: rewrite package_build.py to allow also loading out-of-tree extensions in non-cmake builds if (extension == "parquet") { #if DUCKDB_EXTENSION_PARQUET_LINKED - db.LoadExtension(); + db.LoadStaticExtension(); #else // parquet extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "icu") { #if DUCKDB_EXTENSION_ICU_LINKED - db.LoadExtension(); + db.LoadStaticExtension(); #else // icu extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "tpch") { #if DUCKDB_EXTENSION_TPCH_LINKED - db.LoadExtension(); + db.LoadStaticExtension(); #else // icu extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "tpcds") { #if DUCKDB_EXTENSION_TPCDS_LINKED - db.LoadExtension(); + db.LoadStaticExtension(); #else // icu extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "fts") { #if DUCKDB_EXTENSION_FTS_LINKED -// db.LoadExtension(); +// db.LoadStaticExtension(); #else // fts extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "httpfs") { #if DUCKDB_EXTENSION_HTTPFS_LINKED - db.LoadExtension(); + db.LoadStaticExtension(); #else return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "json") { #if DUCKDB_EXTENSION_JSON_LINKED - db.LoadExtension(); + db.LoadStaticExtension(); #else // json extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "excel") { #if DUCKDB_EXTENSION_EXCEL_LINKED - db.LoadExtension(); -#else - // excel extension required but not build: skip this test - return ExtensionLoadResult::NOT_LOADED; -#endif - } else if (extension == "sqlsmith") { -#if DUCKDB_EXTENSION_SQLSMITH_LINKED - db.LoadExtension(); + db.LoadStaticExtension(); #else // excel extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "jemalloc") { #if DUCKDB_EXTENSION_JEMALLOC_LINKED - db.LoadExtension(); + db.LoadStaticExtension(); #else // jemalloc extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "autocomplete") { #if DUCKDB_EXTENSION_AUTOCOMPLETE_LINKED - db.LoadExtension(); + db.LoadStaticExtension(); #else // autocomplete extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "inet") { #if DUCKDB_EXTENSION_INET_LINKED - db.LoadExtension(); + db.LoadStaticExtension(); #else // inet extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; @@ -621,11 +744,238 @@ EMS5gLv50CzQqJXK9mNzPuYXNUIc4Pw4ssVWe0OfN3Od90gl5uFUwk/G9lWSYnBN -----END PUBLIC KEY----- )", nullptr}; -const vector ExtensionHelper::GetPublicKeys() { +static const char *const community_public_keys[] = { + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv+Jki3aiZt0eOzShgD2g +BYPjPpkhHowOwPzUKtTVPob7vxyzd2wPyWDF/Zn6sN8QzravAdlXFE3SNF7ayO86 +IPHhMxO6P2YlxbipyKzPOUJsasXBiwYw2aSvb0RtwnYwD5lJs8Tz2ET1RQCFgXGc +LW7bDjKRbHSME0Me5rLRWVztOqULeoMeY1oCOmKKeAYxjFOASJJfQF9oQxkuu3j1 +qpcXnfHldlPGzFM77OFlWFtlc9QW4WNoxkO3HwskFW6ZRaQipM8vgSzkIfPFESGL +TtDRw+RcUPqmS6NVW8nhaiptBIMXy+9cP/l1LGmGwrZRhWP0YBlk6V9MUMzjyo+R +JQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtXl28loGwAH3ZGQXXgJQ +3omhIEiUb3z9Petjl+jmdtEQnMNUFEZiXkfJB02UFWBL1OoKKnjiGhcr5oGiIZKR +CoaL6SfmWe//7o8STM44stE0exzZcv8W4tWwjrzSWQnwh2JgSnHN64xoDQjdvG3X +9uQ1xXMXghWOKqEpgArpJQkHoPW3CD5sCS2NLFrBG6KgX0W+GTV5HaKhTMr2754F +l260drcBJZhLFCeesze2DXtQC+R9D25Zwn2ehHHd2Fd1M10ZL/iKN8NeerB4Jnph +w6E3orA0DusDLDLtpJUHhmpLoU/1eYQFQOpGw2ce5I88Tkx7SKnCRy1UiE7BA82W +YQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvTgQ+mJs8vG/TQTJ6sV+ +tACTZTbmp8NkgTuwEyHZSNhX6W8FYwAqPzbePo7wudsUdBWV8j+kUYaBiqeiPUp0 +7neO/3oTUQkMJLq9FeIXfoYkS3+/5CIuvsfas6PJP9U2ge6MV1Ndgbd7a12cmX8V +4eNwQRDv/H4zgL7YI2ZZSG1loxgMffZrpflNB87t/f0QYdmnwphMC5RqxiCkDZPA +a5/5KbmD6kjLh8RRRw3lAZbPQe5r7o2Xqqwg9gc6rQ/WFBB1Oj+Q5Bggqznl6dCB +JcLOA7rhYatv/mvt1h6ogQwQ9FGRM3PifV9boZxOQGBAkMD6ngpd5kVoOxdygC7v +twIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7KvnA+Ixj4ZCLR+aXSFz +ICGbQdVrZ/hhjImDQcWgWY+z/bEbybslDvy5KEPrxTNxKZ0VfFFAVEUj2cw8B5KI +naK8U2VIpdD6LpEJvkOuWKg3bym4COhyAcRNqKKu/GPzS90wICJ2aaayF1mVoCIL +dsp2ZShSIVRJa55gVvfRN1ZEkqBnZryKNt/h3DNqqq2Sn3n3HIZ8H9oEO+L+2Efe +kyET7o9OHy6QZXhf4SJ8QlQAwxxe/L4bln8CBlBHKrUNNqxpjhC37EnY2jpuu3a9 +EZcNFj8R4qIJx7hcltntZyKrEIXqc6I6x4oZ4qhZj3RQ5Lr+pJ++idoc1LmBS3k5 +yQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7SF+5RZ9jXyruBkhxhk2 +BSWPbohevxxv++7Uw0HXC/3Xw4jzii0tYaJ6O8QWXyggEAkvmONblAN1rfiz+h5M +oJUQwHjTTZ8BmKUmWrNayVokUXLu4IpCAHk4uSXfx4U/AINnNfWW7z8mUJf6nGsM +XePuKPBRUsw+JmTWOXEIVrkc/66B+gpgi+DwRFLUPh96D8XRAhp7QbHE9UMD3HpA +mPMX7ICVsVS+NGdCHNsdWfH4noaESjgmMdApKekgeeo8Zu1pvQ3y8iew1xOQVBoR +V+PCGWAJYB7ulqBBkRz+NhPLWw7wRA4yLNcZVlZuDFxH9EoavWdfIyYYUn4efSz9 +tQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAszmZ6Slv/oJvFpOLtSMx +58AKMia9y+qcVfw77/Alb3b+Qi5L2uy6nHfJElT7RIeeXhJ8mFglZ70MecTfj0jl +5WhW+yMg6jmPCJL2JMt/oeC4iY4Cf/3C9RHU4IO13VN4dnVQ5S+SEEmSbXnno9Pe +06yyVgZeJ0REJMV1JZj9gOPc/wbeLHsx4UC5qsu32Ammy6J7tS+k7JvRc9CPOEpe +IhWoZmpONydcI6IRfyH2xl4uLY3hWDrRei0I2zGH45G2hPNeTtRh27t+SzXO7h9j +y072CgHytRgQBiH711i8fe4bHMmtVPhPjFrbuzbJSgE7SyikrWIHMDsnPz443bdR +cQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAleywAb7xZKYTFE08gGA9 +ffTeYPRcECl/J060fUziIiFu0NHTOZO+a4BH2X+E1WjjNNQkbn00g+op4nqg3/U+ +UaKuXNjWY2Rvd8s91fUD0YOdRpPmsTm2QqhgmYYzO8Oh3YXBNRpXaqALbjL9Nahw +YEAsI3o5yenZGUIEk3JaZFHsAZPL5wGgDVpZgmVUHJ0EO8N5LQh01aHxnP5+ey2z +L5h6IdWLubb07wEBk5bnmIvdhd6dIBzUql27BAqvxKJbW0/okjrhIgcIANDCavfV +L8UP7MCGnfozK7VIl5DG85gCQVAD8+lGUDzOuhzZjl7XKpkFAIWaS8pl4AJbJuG8 +nwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxiKgcR7Kb1CGTNczbuX+ +S7OFpnVLDD5XGVKvYWxL+2By2QRFPWtMs8c24omLIgZ/CWBFPraMiNKS4+V9ar2C +wJhToJnAOKyayA0Gw2wNZx1mgHAZ/5mT+ImfkmZu2HPwtzJmJDQlESD4p40BWBNa +ZpWFGPMKn4GqvOOSGevC/r9inXm6NaPkM+B/piVDEgiJ7g/kpoqImmNb/c2/3XG5 +3kbDIHdbd2m3A3jWCjNGSANKsR5C0/rZtvsA8tjDlNWIuKmkU3C2nfj3UduU4dNP +Cisod/pDY8ov0U9sdkM9XZsTXjtbAIGLzMshmOv4ajRFUueGnsZW0GRqp9DSnKmj +2QIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuh334hUmJcdDJUSmeXqE +GUfGnASD2QrnuoS+gsXgW5BQW8YMDFASvADQhoDUdcwZMlAF+p+CxKCX/gBp40nC +5eyPXv1e0K6PFcCdHtJq8MhGYAr1sy+7cOpzv0r9whobYUykGoHjdwZeu3VbA3uz +go80oYQlwY+v4zZFafCz3cXw8u7n/9PlddgeqHuIPsNZLocICuBUxwg5rHTzycg2 +Pa68CRselONGN12V0/wlOg+NZpKCym58CM9SS/0v4YZ6LnmINo8gdRYnGE2zhvey +pHR8IJ8WSJXbl8NwyIY1AmtT/Z0dbAclfD8Wt/w5KA/sttnQzrB7fPsLRyLP1Alq +iQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvWuRMEbez/Ud2o/0KA04 +K9u3HePWud9rEqMsPv2HlclH3k+cezoUJzVre0lopv3R4aG3LDoFETrgGgUVrfPG +z3Zh7vyk0kb4IGkv+kLQu/cWQXyNzigxV+WQnpIWQ28vrP45y5f+GhwwgzFaDAQR +u1o1HH1FEnP7SSzHVvisNTecY95+F5AOvtOOUg4VlegXdUeGZHEza/0D9V8gODPL +DzbOJDDiqX8ahhRnIZyGEg6y7QqftZFz7j0siCHTXXYJBOcPjD4TqTUNpGvBox44 +wgLlLcDsZ/n2Ck4doLXxVz9F80VKOriHSk+qIwseykKVzWQDQTOMOsjCmQsDvram +RwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyJmGd1GuBv/WD80IcVyr +dZcmuYe/7azLuV1wsgtH4gsUx+ifUwLZUhLFGOTAPFitbFYPPdhQKncO+BcbvOIo +9FGKj9jGVpMU6C+0JQfi+koESevtO1tYzG8c2dMOGNUO0Hlj2Hezm3tZY4nAbo1J +DYqQSY7qvOYZPFvOS/zL+q2vMx93w9jDHJK4iU02ovAqK9xCWfTp4W7rtbDeTgiX +W/75rMG8DWI1ZHA2JXAOFPsiOHa0/yyvCvUIWvRuNHqTTN5NFiJRIcbTCKKbNwNM +xcNkBQCx4xwOqD9TkDbHpBOC/pfW7j3ygJdYRjFFqm10+KwPACYo/f0n4n4DI8Zz +twIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnmxbunsK+2pL8Cva9F8E +9o/dQ35TuIqcgpl9/oIc++x+6G5/8UT5mgGCQTITJRIAPnHsZ9XEnMxTAuSCDkYG +CA3JMl1MT7Zxu8TQJBPiXxOaAE1UmA13JuQ2Uu0v7T6TucQxR9KMvcdCxOZ5cBU4 +uyJObnZVy/WjM2vWcWDUaYGfMss3eYxcDpavspBANdtSZfv11+8/VC+gEGBOe+oW +zDR+BlQx//MAzwSP5HVQcmLHsT073IvkoUWJUxSCCwlLe60ylpY16BLT6dB0RU8B +sxFcIwmYg0kq19EEPPvZLvRKjG/TJRm1MFzOE5LP2VxLGdMltWYEVsBZHTcWU7HR +8wIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlo7eDZOpCptanajUtDK3 +q8Q/ykxmDDw6lVSiLBm54zwMxaqfM+tV/xqalvIVv3BrucRkCs6H+R0bpd7XhbE5 +a7ZFSrWCBf1V6y/NZrEn4qcRbk/WsG4UFqu7CG4r+EgQ4nmoIH/A5+e8FUcur3Y8 +2ie9Foi1CUpZojWYZJeHKbb2yYn4MFHszEb5w9HVxY+i9jR1B8Rvn6OEK3OYDrtA +KnPXp4OiDx6CviYEmipX815PPj7Sv8KKL96JqGWjC4kYw6ALgV/GxiX++tv6rh2O +paW9MBv1y+5oZ8ls5S2T/LXbxDpjUEKC9guSSWmsPHRMxOumXsw0H43grC3Ce8Ui +CwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ACgf0kJeQgDh+vHj2aj +K/6FQ794MknLxlwTARGlktoVwZgW/qc6vMZsILRUP1gb/gPXdpSTqqad/GLG4f5R +1Ji1It6BniJOPWu1YyTz0C/BXzTGWbwPnIaawbpQE8n4A+tjGGvAoauPtzr0bWfV +XOXPfIW9XB51dcaVTZgHN55Y8Yd/Pcu9/lqXqXyE23tDLXR/QgGpwK9VxTSbRmuC +WspwqWY6L3MIw+3HIXERTM1uNhc9oHxMOCRbJmUghG0wCWB0ed3Xhbnl9mHlX+l1 +rfCJAP4lVWKFjkKBNUejaf+WHxASMjrQubgHLZ2fpf3Ra8TfI3rgPABsAqEIFw3T +QwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt635/P50bMbEDTapjAQz +ARTb3y8jMHxVruX0tJU1tycmkX3J8tBALmc6TkSHNTJcQmR8L8Sj3h76l/vuL373 +HFSGZ4xghBQqR1lUd2kVomoh+rzEte+0rHWm0JMhjmTQBx+AkDCOw4z3vi5AxWx0 +4EbYpQm2akVGKXQrQPyds0UirmdLACCH6WM6exgAXr75DB4PUpG85oI9Q+5ee1Km ++4atVJ4FNa6ZnjWccrlMYT0W7a0Y7feJPAPvfizrs2MG9/ijyBX34eCWA5dtUSIm +2uqI6DxITZlLTvXVDSKQGlq5TEGMvRULWTatqWy4g+tOZ8rSbRuj32pcBnXlwuVu +7QIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwqO3yWSLKqz1uQ54iFd/ +VcQzgT6chLVuhktt7EFvi3tKaQqz2h2KPkDR+MssRV/BZ/41GNlR6r6p5CaPVDDe +Cuj5IcxrIFZIOBMBi1YZ/bknF9edJacINxNfGK/lXBNEAdUvxcOxX8WeP69uvl2l +SKyO3yAdx6HOyL9if95bYQD19HYPZzbfccPX1aD4pjnej6uMfd7yZErH7i8y0oj4 +eSKSe1CisjFlR9NzRGO42jU9rtqnAFH9sK5wU9xKQ7bQwlz7yKBF2RuuQweMpXb6 +lSObI7ZqYN+7jkf9F5hKRx4kX3+MMBeYmFOy1aYZ08u6sdJ2ua/hFNSDRg7e/UCe +AwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkJihnfMECaa6YCg6avam +cb8Sy1GshJ7c7+EW6C4vnspSSvEi04AEBB29pnEF9+VO6VSUHLxunVCpbmKFaLH+ +5fDLnc/wCkjPQww49da9MEScCmVGjROlmog65cxQbv4lfxyw55sFV3s/5CPcGlVc +1gojHRABrx4YocpeYies04mEVoOYg1DBG4Uf+aFd5+hm3ZtBa4mqTK2iQa4ILkHa +a0/Us1drRuDjjI4zSbgRzy9x0JVDvqDdLubHyaEf7d7SdrKzodhydG84qpsPFxIj +LK7Bu5v7P4ZTJmxMG3PBM2kB//hlYVR4vO4VEu66mQIM6km+vT9cwxz77qIJhLn3 +ywIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9NbP7ijUxZh4j0NVF6yO +IZ0rzROwl4pP4HGeN+Woyi9+qpdE874WlVoquGEpsshF4Ojzbu2BtXuihb783awa +GLx66MYPeID1FjTKmuCJ2aluOP+DkVo6K1EoqVJXyeIxZzVSqhSIuAdb/vmPlgLz +Fzdk3FgNNOERuGV363DRGz1YxZVnJeSs76g+/9ddhMk8cqIRup5S4YgTOSr0vKem +1E6lyE8IbLoq9J7w5Ur8VjzE2cI+eLKGFqr46Q8pf0pJq72gd+Z3mH5D2LmvEtAR +9jAQXVlLfHauQR2M0K6mqDy9GxL19OU4tGO+GY86VvDTU+wZppAZRz9AKoL1fwfI +BQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjrI16GdC2zJriLbyzcre +AqvckBSTMd4bdGaodUBNBTBVbITsOw/k7D62y2hSZHt2nHOyEVkJINJHADrpNZuY +ybS4ssEXxD8+NnjATqQxDMuSz8lUj/Jnf49uzLh84fep3DTksDcQX6Nvio5q8Xbh +HRgvl5I+tPfLtme0oW9cVuVja2i5lHB3SzYCW9Kk/V4/d2WiceYf91a1Nae6m7QV +5bmbYoHmsxT8refTQq+5lAhzVXYU9QRgiKdbE8sSmkV+YiZEtGijefUXgmOxx3I9 +B3y03796WBS/RHpSzdMNJw/xPWJcSEMqaUdSYr0DuPCnrn7ojFeF/EFC47CBq5DU +swIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjS1+My6OhQCCD1DgrzKu +db4Fvc3aqqEhQyjqMLnalp0uoGFpSLoPsZiPGloTE8FSs1ZBFKQ8h2SsGwSdhRKF +xIqoOnS0B/ORjGJxTj7Q2YWjzkCZUD4Ul2AxIbv3TmZM2LeyHJL3A71tSuck8EQY +PE2aj1tLzXsSfRaByy5xwXiU6UpnwCY1xb8tK8QxavRCo5T9Si9tNsolStoNVXV0 +k9EbTcRNnxCvab/oqjvgyRuSmIES00v8jZOGQZQUpw02RN6yCBeX2i8GPsGjj/T9 +6Gu1Z3G4zUjLlJxl8vjo8KIDaQ8NVWT0j7gx9Knvb5tWnAORI1aJA8AHQvaoOT1W +1wIDAQAB +-----END PUBLIC KEY----- +)", nullptr}; + +const vector ExtensionHelper::GetPublicKeys(bool allow_community_extensions) { vector keys; for (idx_t i = 0; public_keys[i]; i++) { keys.emplace_back(public_keys[i]); } + if (allow_community_extensions) { + for (idx_t i = 0; community_public_keys[i]; i++) { + keys.emplace_back(community_public_keys[i]); + } + } return keys; } diff --git a/src/main/extension/extension_install.cpp b/src/main/extension/extension_install.cpp index 7e182510f59..997a072d1a3 100644 --- a/src/main/extension/extension_install.cpp +++ b/src/main/extension/extension_install.cpp @@ -1,8 +1,13 @@ +#include "duckdb/common/exception/http_exception.hpp" #include "duckdb/common/gzip_file_system.hpp" -#include "duckdb/common/types/uuid.hpp" +#include "duckdb/common/local_file_system.hpp" +#include "duckdb/common/serializer/binary_serializer.hpp" #include "duckdb/common/string_util.hpp" -#include "duckdb/common/exception/http_exception.hpp" +#include "duckdb/common/types/uuid.hpp" +#include "duckdb/logging/http_logger.hpp" +#include "duckdb/main/client_data.hpp" #include "duckdb/main/extension_helper.hpp" +#include "duckdb/main/extension_install_info.hpp" #ifndef DISABLE_DUCKDB_REMOTE_INSTALL #ifndef DUCKDB_DISABLE_EXTENSION_LOAD @@ -128,26 +133,36 @@ bool ExtensionHelper::CreateSuggestions(const string &extension_name, string &me return false; } -void ExtensionHelper::InstallExtension(DBConfig &config, FileSystem &fs, const string &extension, bool force_install, - const string &repository) { +unique_ptr ExtensionHelper::InstallExtension(DBConfig &config, FileSystem &fs, + const string &extension, bool force_install, + optional_ptr repository, + bool throw_on_origin_mismatch, + const string &version) { #ifdef WASM_LOADABLE_EXTENSIONS // Install is currently a no-op - return; + return nullptr; #endif string local_path = ExtensionDirectory(config, fs); - InstallExtensionInternal(config, fs, local_path, extension, force_install, repository); + return InstallExtensionInternal(config, fs, local_path, extension, force_install, throw_on_origin_mismatch, version, + repository); } -void ExtensionHelper::InstallExtension(ClientContext &context, const string &extension, bool force_install, - const string &repository) { +unique_ptr ExtensionHelper::InstallExtension(ClientContext &context, const string &extension, + bool force_install, + optional_ptr repository, + bool throw_on_origin_mismatch, + const string &version) { #ifdef WASM_LOADABLE_EXTENSIONS // Install is currently a no-op - return; + return nullptr; #endif - auto &config = DBConfig::GetConfig(context); + auto &db_config = DBConfig::GetConfig(context); auto &fs = FileSystem::GetFileSystem(context); string local_path = ExtensionDirectory(context); - InstallExtensionInternal(config, fs, local_path, extension, force_install, repository); + optional_ptr http_logger = + ClientConfig::GetConfig(context).enable_http_logging ? context.client_data->http_logger.get() : nullptr; + return InstallExtensionInternal(db_config, fs, local_path, extension, force_install, throw_on_origin_mismatch, + version, repository, http_logger, context); } unsafe_unique_array ReadExtensionFileFromDisk(FileSystem &fs, const string &path, idx_t &file_size) { @@ -159,7 +174,7 @@ unsafe_unique_array ReadExtensionFileFromDisk(FileSystem &fs, const stri return in_buffer; } -void WriteExtensionFileToDisk(FileSystem &fs, const string &path, void *data, idx_t data_size) { +static void WriteExtensionFileToDisk(FileSystem &fs, const string &path, void *data, idx_t data_size) { auto target_file = fs.OpenFile(path, FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_APPEND | FileFlags::FILE_FLAGS_FILE_CREATE_NEW); target_file->Write(data, data_size); @@ -167,25 +182,28 @@ void WriteExtensionFileToDisk(FileSystem &fs, const string &path, void *data, id target_file.reset(); } -string ExtensionHelper::ExtensionUrlTemplate(optional_ptr db_config, const string &repository) { - string versioned_path = "/${REVISION}/${PLATFORM}/${NAME}.duckdb_extension"; +static void WriteExtensionMetadataFileToDisk(FileSystem &fs, const string &path, ExtensionInstallInfo &metadata) { + auto file_writer = BufferedFileWriter(fs, path); + BinarySerializer::Serialize(metadata, file_writer); + file_writer.Sync(); +} + +string ExtensionHelper::ExtensionUrlTemplate(optional_ptr db_config, + const ExtensionRepository &repository, const string &version) { + string versioned_path; + if (!version.empty()) { + versioned_path = "/${NAME}/" + version + "/${REVISION}/${PLATFORM}/${NAME}.duckdb_extension"; + } else { + versioned_path = "/${REVISION}/${PLATFORM}/${NAME}.duckdb_extension"; + } #ifdef WASM_LOADABLE_EXTENSIONS - string default_endpoint = "https://extensions.duckdb.org"; + string default_endpoint = DEFAULT_REPOSITORY; versioned_path = versioned_path + ".wasm"; #else - string default_endpoint = "http://extensions.duckdb.org"; + string default_endpoint = ExtensionRepository::DEFAULT_REPOSITORY_URL; versioned_path = versioned_path + ".gz"; #endif - string custom_endpoint = db_config ? db_config->options.custom_extension_repo : string(); - string endpoint; - if (!repository.empty()) { - endpoint = repository; - } else if (!custom_endpoint.empty()) { - endpoint = custom_endpoint; - } else { - endpoint = default_endpoint; - } - string url_template = endpoint + versioned_path; + string url_template = repository.path + versioned_path; return url_template; } @@ -196,56 +214,128 @@ string ExtensionHelper::ExtensionFinalizeUrlTemplate(const string &url_template, return url; } -void ExtensionHelper::InstallExtensionInternal(DBConfig &config, FileSystem &fs, const string &local_path, - const string &extension, bool force_install, const string &repository) { -#ifdef DUCKDB_DISABLE_EXTENSION_LOAD - throw PermissionException("Installing external extensions is disabled through a compile time flag"); -#else - if (!config.options.enable_external_access) { - throw PermissionException("Installing extensions is disabled through configuration"); +static void CheckExtensionMetadataOnInstall(DBConfig &config, void *in_buffer, idx_t file_size, + ExtensionInstallInfo &info, const string &extension_name) { + if (file_size < ParsedExtensionMetaData::FOOTER_SIZE) { + throw IOException("Failed to install '%s', file too small to be a valid DuckDB extension!", extension_name); } - auto extension_name = ApplyExtensionAlias(fs.ExtractBaseName(extension)); - string local_extension_path = fs.JoinPath(local_path, extension_name + ".duckdb_extension"); - if (fs.FileExists(local_extension_path) && !force_install) { - return; + auto parsed_metadata = ExtensionHelper::ParseExtensionMetaData(static_cast(in_buffer) + + (file_size - ParsedExtensionMetaData::FOOTER_SIZE)); + + auto metadata_mismatch_error = parsed_metadata.GetInvalidMetadataError(); + + if (!metadata_mismatch_error.empty() && !config.options.allow_extensions_metadata_mismatch) { + throw IOException("Failed to install '%s'\n%s", extension_name, metadata_mismatch_error); } - auto uuid = UUID::ToString(UUID::GenerateRandomUUID()); - string temp_path = local_extension_path + ".tmp-" + uuid; - if (fs.FileExists(temp_path)) { - fs.RemoveFile(temp_path); + info.version = parsed_metadata.extension_version; +} + +// Note: since this method is not atomic, this can fail in different ways, that should all be handled properly by +// DuckDB: +// 1. Crash after extension removal: extension is now uninstalled, metadata file still present +// 2. Crash after metadata removal: extension is now uninstalled, extension dir is clean +// 3. Crash after extension move: extension is now uninstalled, new metadata file present +static void WriteExtensionFiles(FileSystem &fs, const string &temp_path, const string &local_extension_path, + void *in_buffer, idx_t file_size, ExtensionInstallInfo &info) { + // Write extension to tmp file + WriteExtensionFileToDisk(fs, temp_path, in_buffer, file_size); + + // Write metadata to tmp file + auto metadata_tmp_path = temp_path + ".info"; + auto metadata_file_path = local_extension_path + ".info"; + WriteExtensionMetadataFileToDisk(fs, metadata_tmp_path, info); + + // First remove the local extension we are about to replace + if (fs.FileExists(local_extension_path)) { + fs.RemoveFile(local_extension_path); } - auto is_http_url = StringUtil::Contains(extension, "http://"); - if (ExtensionHelper::IsFullPath(extension)) { - if (fs.FileExists(extension)) { - idx_t file_size; - auto in_buffer = ReadExtensionFileFromDisk(fs, extension, file_size); - WriteExtensionFileToDisk(fs, temp_path, in_buffer.get(), file_size); - if (fs.FileExists(local_extension_path) && force_install) { - fs.RemoveFile(local_extension_path); - } - fs.MoveFile(temp_path, local_extension_path); - return; - } else if (!is_http_url) { - throw IOException("Failed to read extension from \"%s\": no such file", extension); + // Then remove the old metadata file + if (fs.FileExists(metadata_file_path)) { + fs.RemoveFile(metadata_file_path); + } + + fs.MoveFile(metadata_tmp_path, metadata_file_path); + fs.MoveFile(temp_path, local_extension_path); +} + +// Install an extension using a filesystem +static unique_ptr DirectInstallExtension(DBConfig &config, FileSystem &fs, const string &path, + const string &temp_path, const string &extension_name, + const string &local_extension_path, bool force_install, + optional_ptr repository, + optional_ptr context) { + string file = fs.ConvertSeparators(path); + + // Try autoloading httpfs for loading extensions over https + if (context) { + auto &db = DatabaseInstance::GetDatabase(*context); + if (StringUtil::StartsWith(path, "https://") && !db.ExtensionIsLoaded("httpfs") && + db.config.options.autoload_known_extensions) { + ExtensionHelper::AutoLoadExtension(*context, "httpfs"); } } -#ifdef DISABLE_DUCKDB_REMOTE_INSTALL - throw BinderException("Remote extension installation is disabled through configuration"); -#else + // Check if file exists + bool exists = fs.FileExists(file); - string url_template = ExtensionUrlTemplate(&config, repository); + // Recheck without .gz + if (!exists && StringUtil::EndsWith(file, ".gz")) { + file = file.substr(0, file.size() - 3); + exists = fs.FileExists(file); + } - if (is_http_url) { - url_template = extension; - extension_name = ""; + // Throw error on failure + if (!exists) { + if (!fs.IsRemoteFile(file)) { + throw IOException("Failed to copy local extension \"%s\" at PATH \"%s\"\n", extension_name, file); + } + if (StringUtil::StartsWith(file, "https://")) { + throw IOException("Failed to install remote extension \"%s\" from url \"%s\"", extension_name, file); + } } - string url = ExtensionFinalizeUrlTemplate(url_template, extension_name); + idx_t file_size; + auto in_buffer = ReadExtensionFileFromDisk(fs, file, file_size); + ExtensionInstallInfo info; + + string decompressed_data; + void *extension_decompressed; + idx_t extension_decompressed_size; + + if (GZipFileSystem::CheckIsZip(const_char_ptr_cast(in_buffer.get()), file_size)) { + decompressed_data = GZipFileSystem::UncompressGZIPString(const_char_ptr_cast(in_buffer.get()), file_size); + extension_decompressed = (void *)decompressed_data.data(); + extension_decompressed_size = decompressed_data.size(); + } else { + extension_decompressed = (void *)in_buffer.get(); + extension_decompressed_size = file_size; + } + + CheckExtensionMetadataOnInstall(config, extension_decompressed, extension_decompressed_size, info, extension_name); + + if (!repository) { + info.mode = ExtensionInstallMode::CUSTOM_PATH; + info.full_path = file; + } else { + info.mode = ExtensionInstallMode::REPOSITORY; + info.full_path = file; + info.repository_url = repository->path; + } + + WriteExtensionFiles(fs, temp_path, local_extension_path, extension_decompressed, extension_decompressed_size, info); + + return make_uniq(info); +} + +static unique_ptr InstallFromHttpUrl(DBConfig &config, const string &url, + const string &extension_name, const string &temp_path, + const string &local_extension_path, bool force_install, + optional_ptr repository, + optional_ptr http_logger) { string no_http = StringUtil::Replace(url, "http://", ""); idx_t next = no_http.find('/', 0); @@ -253,50 +343,46 @@ void ExtensionHelper::InstallExtensionInternal(DBConfig &config, FileSystem &fs, throw IOException("No slash in URL template"); } - // Special case to install extension from a local file, useful for testing - if (!StringUtil::Contains(url_template, "http://")) { - string file = fs.ConvertSeparators(url); - if (!fs.FileExists(file)) { - // check for non-gzipped variant - file = file.substr(0, file.size() - 3); - if (!fs.FileExists(file)) { - throw IOException("Failed to copy local extension \"%s\" at PATH \"%s\"\n", extension_name, file); - } - } - auto read_handle = fs.OpenFile(file, FileFlags::FILE_FLAGS_READ); - auto test_data = std::unique_ptr {new unsigned char[read_handle->GetFileSize()]}; - read_handle->Read(test_data.get(), read_handle->GetFileSize()); - WriteExtensionFileToDisk(fs, temp_path, (void *)test_data.get(), read_handle->GetFileSize()); - - if (fs.FileExists(local_extension_path) && force_install) { - fs.RemoveFile(local_extension_path); - } - fs.MoveFile(temp_path, local_extension_path); - return; - } - // Push the substring [last, next) on to splits auto hostname_without_http = no_http.substr(0, next); auto url_local_part = no_http.substr(next); auto url_base = "http://" + hostname_without_http; duckdb_httplib::Client cli(url_base.c_str()); + if (http_logger) { + cli.set_logger(http_logger->GetLogger()); + } duckdb_httplib::Headers headers = { {"User-Agent", StringUtil::Format("%s %s", config.UserAgent(), DuckDB::SourceID())}}; + unique_ptr install_info; + { + auto fs = FileSystem::CreateLocal(); + if (fs->FileExists(local_extension_path + ".info")) { + install_info = ExtensionInstallInfo::TryReadInfoFile(*fs, local_extension_path + ".info", extension_name); + } + if (install_info && !install_info->etag.empty()) { + headers.insert({"If-None-Match", StringUtil::Format("%s", install_info->etag)}); + } + } + auto res = cli.Get(url_local_part.c_str(), headers); + if (install_info && res && res->status == 304) { + return install_info; + } + if (!res || res->status != 200) { // create suggestions string message; auto exact_match = ExtensionHelper::CreateSuggestions(extension_name, message); - if (exact_match && !IsRelease(DuckDB::LibraryVersion())) { + if (exact_match && !ExtensionHelper::IsRelease(DuckDB::LibraryVersion())) { message += "\nAre you using a development build? In this case, extensions might not (yet) be uploaded."; } if (res.error() == duckdb_httplib::Error::Success) { - throw HTTPException(res.value(), "Failed to download extension \"%s\" at URL \"%s%s\"\n%s", extension_name, - url_base, url_local_part, message); + throw HTTPException(res.value(), "Failed to download extension \"%s\" at URL \"%s%s\" (HTTP %n)\n%s", + extension_name, url_base, url_local_part, res->status, message); } else { throw IOException("Failed to download extension \"%s\" at URL \"%s%s\"\n%s (ERROR %s)", extension_name, url_base, url_local_part, message, to_string(res.error())); @@ -304,12 +390,156 @@ void ExtensionHelper::InstallExtensionInternal(DBConfig &config, FileSystem &fs, } auto decompressed_body = GZipFileSystem::UncompressGZIPString(res->body); - WriteExtensionFileToDisk(fs, temp_path, (void *)decompressed_body.data(), decompressed_body.size()); + ExtensionInstallInfo info; + CheckExtensionMetadataOnInstall(config, (void *)decompressed_body.data(), decompressed_body.size(), info, + extension_name); + if (res->has_header("ETag")) { + info.etag = res->get_header_value("ETag"); + } - if (fs.FileExists(local_extension_path) && force_install) { - fs.RemoveFile(local_extension_path); + if (repository) { + info.mode = ExtensionInstallMode::REPOSITORY; + info.full_path = url; + info.repository_url = repository->path; + } else { + info.mode = ExtensionInstallMode::CUSTOM_PATH; + info.full_path = url; } - fs.MoveFile(temp_path, local_extension_path); + + auto fs = FileSystem::CreateLocal(); + WriteExtensionFiles(*fs, temp_path, local_extension_path, (void *)decompressed_body.data(), + decompressed_body.size(), info); + + return make_uniq(info); +} + +// Install an extension using a hand-rolled http request +static unique_ptr InstallFromRepository(DBConfig &config, FileSystem &fs, const string &url, + const string &extension_name, + ExtensionRepository &repository, const string &temp_path, + const string &local_extension_path, const string &version, + bool force_install, optional_ptr http_logger, + optional_ptr context) { + string url_template = ExtensionHelper::ExtensionUrlTemplate(&config, repository, version); + string generated_url = ExtensionHelper::ExtensionFinalizeUrlTemplate(url_template, extension_name); + + // Special handling for http repository: avoid using regular filesystem (note: the filesystem is not used here) + if (StringUtil::StartsWith(repository.path, "http://")) { + return InstallFromHttpUrl(config, generated_url, extension_name, temp_path, local_extension_path, force_install, + repository, http_logger); + } + + // Default case, let the FileSystem figure it out + return DirectInstallExtension(config, fs, generated_url, temp_path, extension_name, local_extension_path, + force_install, repository, context); +} + +static bool IsHTTP(const string &path) { + return StringUtil::StartsWith(path, "http://") || !StringUtil::StartsWith(path, "https://"); +} + +static void ThrowErrorOnMismatchingExtensionOrigin(FileSystem &fs, const string &local_extension_path, + const string &extension_name, const string &extension, + optional_ptr repository) { + auto install_info = ExtensionInstallInfo::TryReadInfoFile(fs, local_extension_path + ".info", extension_name); + + string format_string = "Installing extension '%s' failed. The extension is already installed " + "but the origin is different.\n" + "Currently installed extension is from %s '%s', while the extension to be " + "installed is from %s '%s'.\n" + "To solve this rerun this command with `FORCE INSTALL`"; + string repo = "repository"; + string custom_path = "custom_path"; + + if (install_info) { + if (install_info->mode == ExtensionInstallMode::REPOSITORY && repository && + install_info->repository_url != repository->path) { + throw InvalidInputException(format_string, extension_name, repo, install_info->repository_url, repo, + repository->path); + } + if (install_info->mode == ExtensionInstallMode::REPOSITORY && ExtensionHelper::IsFullPath(extension)) { + throw InvalidInputException(format_string, extension_name, repo, install_info->repository_url, custom_path, + extension); + } + } +} + +unique_ptr +ExtensionHelper::InstallExtensionInternal(DBConfig &config, FileSystem &fs, const string &local_path, + const string &extension, bool force_install, bool throw_on_origin_mismatch, + const string &version, optional_ptr repository, + optional_ptr http_logger, optional_ptr context) { +#ifdef DUCKDB_DISABLE_EXTENSION_LOAD + throw PermissionException("Installing external extensions is disabled through a compile time flag"); +#else + if (!config.options.enable_external_access) { + throw PermissionException("Installing extensions is disabled through configuration"); + } + + auto extension_name = ApplyExtensionAlias(fs.ExtractBaseName(extension)); + string local_extension_path = fs.JoinPath(local_path, extension_name + ".duckdb_extension"); + string temp_path = local_extension_path + ".tmp-" + UUID::ToString(UUID::GenerateRandomUUID()); + + if (fs.FileExists(local_extension_path) && !force_install) { + // File exists: throw error if origin mismatches + if (throw_on_origin_mismatch && !config.options.allow_extensions_metadata_mismatch && + fs.FileExists(local_extension_path + ".info")) { + ThrowErrorOnMismatchingExtensionOrigin(fs, local_extension_path, extension_name, extension, repository); + } + + // File exists, but that's okay, install is now a NOP + return nullptr; + } + + if (fs.FileExists(temp_path)) { + fs.RemoveFile(temp_path); + } + + if (ExtensionHelper::IsFullPath(extension) && repository) { + throw InvalidInputException("Cannot pass both a repository and a full path url"); + } + + // Resolve default repository if there is none set + ExtensionRepository resolved_repository; + if (!ExtensionHelper::IsFullPath(extension) && !repository) { + resolved_repository = ExtensionRepository::GetDefaultRepository(config); + repository = resolved_repository; + } + + // Install extension from local, direct url + if (ExtensionHelper::IsFullPath(extension) && !IsHTTP(extension)) { + LocalFileSystem local_fs; + return DirectInstallExtension(config, local_fs, extension, temp_path, extension, local_extension_path, + force_install, nullptr, context); + } + + // Install extension from local url based on a repository (Note that this will install it as a local file) + if (repository && !IsHTTP(repository->path)) { + LocalFileSystem local_fs; + return InstallFromRepository(config, fs, extension, extension_name, *repository, temp_path, + local_extension_path, version, force_install, http_logger, context); + } + +#ifdef DISABLE_DUCKDB_REMOTE_INSTALL + throw BinderException("Remote extension installation is disabled through configuration"); +#else + + // Full path direct installation + if (IsFullPath(extension)) { + if (StringUtil::StartsWith(extension, "http://")) { + // HTTP takes separate path to avoid dependency on httpfs extension + return InstallFromHttpUrl(config, extension, extension_name, temp_path, local_extension_path, force_install, + nullptr, http_logger); + } + + // Direct installation from local or remote path + return DirectInstallExtension(config, fs, extension, temp_path, extension, local_extension_path, force_install, + nullptr, context); + } + + // Repository installation + return InstallFromRepository(config, fs, extension, extension_name, *repository, temp_path, local_extension_path, + version, force_install, http_logger, context); #endif #endif } diff --git a/src/main/extension/extension_load.cpp b/src/main/extension/extension_load.cpp index 58a1b698ab4..65438aa8ec1 100644 --- a/src/main/extension/extension_load.cpp +++ b/src/main/extension/extension_load.cpp @@ -1,7 +1,9 @@ #include "duckdb/common/dl.hpp" #include "duckdb/common/virtual_file_system.hpp" -#include "duckdb/main/extension_helper.hpp" #include "duckdb/main/error_manager.hpp" +#include "duckdb/main/extension_helper.hpp" +#include "duckdb/common/serializer/buffered_file_reader.hpp" +#include "duckdb/common/serializer/binary_deserializer.hpp" #include "mbedtls_wrapper.hpp" #ifndef DUCKDB_NO_THREADS @@ -31,18 +33,18 @@ static T LoadFunctionFromDLL(void *dll, const string &function_name, const strin return (T)function; } -static void ComputeSHA256String(const std::string &to_hash, std::string *res) { +static void ComputeSHA256String(const string &to_hash, string *res) { // Invoke MbedTls function to actually compute sha256 *res = duckdb_mbedtls::MbedTlsWrapper::ComputeSha256Hash(to_hash); } -static void ComputeSHA256FileSegment(FileHandle *handle, const idx_t start, const idx_t end, std::string *res) { +static void ComputeSHA256FileSegment(FileHandle *handle, const idx_t start, const idx_t end, string *res) { idx_t iter = start; const idx_t segment_size = 1024ULL * 8ULL; duckdb_mbedtls::MbedTlsWrapper::SHA256State state; - std::string to_hash; + string to_hash; while (iter < end) { idx_t len = std::min(end - iter, segment_size); to_hash.resize(len); @@ -64,30 +66,96 @@ static string FilterZeroAtEnd(string s) { return s; } -static string PrettyPrintString(const string &s) { - string res = ""; - for (auto c : s) { - if (StringUtil::CharacterIsAlpha(c) || StringUtil::CharacterIsDigit(c) || c == '_' || c == '-' || c == ' ' || - c == '.') { - res += c; - } else { - auto value = UnsafeNumericCast(c); - res += "\\x"; - uint8_t first = value / 16; - if (first < 10) { - res.push_back((char)('0' + first)); - } else { - res.push_back((char)('a' + first - 10)); - } - uint8_t second = value % 16; - if (second < 10) { - res.push_back((char)('0' + second)); - } else { - res.push_back((char)('a' + second - 10)); - } +ParsedExtensionMetaData ExtensionHelper::ParseExtensionMetaData(const char *metadata) { + ParsedExtensionMetaData result; + + vector metadata_field; + for (idx_t i = 0; i < 8; i++) { + string field = string(metadata + i * 32, 32); + metadata_field.emplace_back(field); + } + + std::reverse(metadata_field.begin(), metadata_field.end()); + + result.magic_value = FilterZeroAtEnd(metadata_field[0]); + result.platform = FilterZeroAtEnd(metadata_field[1]); + result.duckdb_version = FilterZeroAtEnd(metadata_field[2]); + result.extension_version = FilterZeroAtEnd(metadata_field[3]); + + result.signature = string(metadata, ParsedExtensionMetaData::FOOTER_SIZE - ParsedExtensionMetaData::SIGNATURE_SIZE); + return result; +} + +ParsedExtensionMetaData ExtensionHelper::ParseExtensionMetaData(FileHandle &handle) { + const string engine_version = string(ExtensionHelper::GetVersionDirectoryName()); + const string engine_platform = string(DuckDB::Platform()); + + string metadata_segment; + metadata_segment.resize(ParsedExtensionMetaData::FOOTER_SIZE); + + if (handle.GetFileSize() < ParsedExtensionMetaData::FOOTER_SIZE) { + throw InvalidInputException( + "File '%s' is not a DuckDB extension. Valid DuckDB extensions must be at least %llu bytes", handle.path, + ParsedExtensionMetaData::FOOTER_SIZE); + } + + handle.Read((void *)metadata_segment.data(), metadata_segment.size(), + handle.GetFileSize() - ParsedExtensionMetaData::FOOTER_SIZE); + + return ParseExtensionMetaData(metadata_segment.data()); +} + +bool ExtensionHelper::CheckExtensionSignature(FileHandle &handle, ParsedExtensionMetaData &parsed_metadata, + const bool allow_community_extensions) { + auto signature_offset = handle.GetFileSize() - ParsedExtensionMetaData::SIGNATURE_SIZE; + + const idx_t maxLenChunks = 1024ULL * 1024ULL; + const idx_t numChunks = (signature_offset + maxLenChunks - 1) / maxLenChunks; + vector hash_chunks(numChunks); + vector splits(numChunks + 1); + + for (idx_t i = 0; i < numChunks; i++) { + splits[i] = maxLenChunks * i; + } + splits.back() = signature_offset; + +#ifndef DUCKDB_NO_THREADS + vector threads; + threads.reserve(numChunks); + for (idx_t i = 0; i < numChunks; i++) { + threads.emplace_back(ComputeSHA256FileSegment, &handle, splits[i], splits[i + 1], &hash_chunks[i]); + } + + for (auto &thread : threads) { + thread.join(); + } +#else + for (idx_t i = 0; i < numChunks; i++) { + ComputeSHA256FileSegment(&handle, splits[i], splits[i + 1], &hash_chunks[i]); + } +#endif // DUCKDB_NO_THREADS + + string hash_concatenation; + hash_concatenation.reserve(32 * numChunks); // 256 bits -> 32 bytes per chunk + + for (auto &hash_chunk : hash_chunks) { + hash_concatenation += hash_chunk; + } + + string two_level_hash; + ComputeSHA256String(hash_concatenation, &two_level_hash); + + // TODO maybe we should do a stream read / hash update here + handle.Read((void *)parsed_metadata.signature.data(), parsed_metadata.signature.size(), signature_offset); + + for (auto &key : ExtensionHelper::GetPublicKeys(allow_community_extensions)) { + if (duckdb_mbedtls::MbedTlsWrapper::IsValidSha256Signature(key, parsed_metadata.signature, two_level_hash)) { + return true; + break; } } - return res; + + return false; } bool ExtensionHelper::TryInitialLoad(DBConfig &config, FileSystem &fs, const string &extension, @@ -100,8 +168,11 @@ bool ExtensionHelper::TryInitialLoad(DBConfig &config, FileSystem &fs, const str } auto filename = fs.ConvertSeparators(extension); + bool direct_load; + // shorthand case if (!ExtensionHelper::IsFullPath(extension)) { + direct_load = false; string extension_name = ApplyExtensionAlias(extension); #ifdef WASM_LOADABLE_EXTENSIONS string url_template = ExtensionUrlTemplate(&config, ""); @@ -121,7 +192,7 @@ bool ExtensionHelper::TryInitialLoad(DBConfig &config, FileSystem &fs, const str return stringOnWasmHeap; }, filename.c_str(), url.c_str()); - std::string address(str); + string address(str); free(str); filename = address; @@ -141,6 +212,7 @@ bool ExtensionHelper::TryInitialLoad(DBConfig &config, FileSystem &fs, const str filename = fs.JoinPath(local_path, extension_name + ".duckdb_extension"); #endif } else { + direct_load = true; filename = fs.ExpandPath(filename); } if (!fs.FileExists(filename)) { @@ -153,133 +225,38 @@ bool ExtensionHelper::TryInitialLoad(DBConfig &config, FileSystem &fs, const str return false; } - string metadata_segment; - metadata_segment.resize(512); - - const std::string engine_version = std::string(GetVersionDirectoryName()); - const std::string engine_platform = std::string(DuckDB::Platform()); - auto handle = fs.OpenFile(filename, FileFlags::FILE_FLAGS_READ); - idx_t file_size = handle->GetFileSize(); - - if (file_size < 1024) { - throw InvalidInputException( - "Extension \"%s\" do not have metadata compatible with DuckDB loading it " - "(version %s, platform %s). File size in particular is lower than minimum threshold of 1024", - filename, engine_version, engine_platform); - } - - auto metadata_offset = file_size - metadata_segment.size(); + // Parse the extension metadata from the extension binary + auto parsed_metadata = ParseExtensionMetaData(*handle); - handle->Read((void *)metadata_segment.data(), metadata_segment.size(), metadata_offset); + auto metadata_mismatch_error = parsed_metadata.GetInvalidMetadataError(); - std::vector metadata_field; - for (idx_t i = 0; i < 8; i++) { - metadata_field.emplace_back(metadata_segment, i * 32, 32); - } - - std::reverse(metadata_field.begin(), metadata_field.end()); - - std::string extension_duckdb_platform = FilterZeroAtEnd(metadata_field[1]); - std::string extension_duckdb_version = FilterZeroAtEnd(metadata_field[2]); - std::string extension_version = FilterZeroAtEnd(metadata_field[3]); - - string metadata_mismatch_error = ""; - { - char a[32] = {0}; - a[0] = '4'; - if (strncmp(a, metadata_field[0].data(), 32) != 0) { - // metadata do not looks right, add this to the error message - metadata_mismatch_error = - "\n" + StringUtil::Format("Extension \"%s\" do not have metadata compatible with DuckDB " - "loading it (version %s, platform %s)", - filename, engine_version, engine_platform); - } else if (engine_version != extension_duckdb_version || engine_platform != extension_duckdb_platform) { - metadata_mismatch_error = "\n" + StringUtil::Format("Extension \"%s\" (version %s, platfrom %s) does not " - "match DuckDB loading it (version %s, platform %s)", - filename, PrettyPrintString(extension_duckdb_version), - PrettyPrintString(extension_duckdb_platform), - engine_version, engine_platform); - - } else { - // All looks good - } + if (!metadata_mismatch_error.empty()) { + metadata_mismatch_error = StringUtil::Format("Failed to load '%s', %s", extension, metadata_mismatch_error); } if (!config.options.allow_unsigned_extensions) { - // signature is the last 256 bytes of the file - string signature(metadata_segment, metadata_segment.size() - 256); - - auto signature_offset = metadata_offset + metadata_segment.size() - signature.size(); - - const idx_t maxLenChunks = 1024ULL * 1024ULL; - const idx_t numChunks = (signature_offset + maxLenChunks - 1) / maxLenChunks; - std::vector hash_chunks(numChunks); - std::vector splits(numChunks + 1); - - for (idx_t i = 0; i < numChunks; i++) { - splits[i] = maxLenChunks * i; - } - splits.back() = signature_offset; + bool signature_valid = + CheckExtensionSignature(*handle, parsed_metadata, config.options.allow_community_extensions); -#ifndef DUCKDB_NO_THREADS - std::vector threads; - threads.reserve(numChunks); - for (idx_t i = 0; i < numChunks; i++) { - threads.emplace_back(ComputeSHA256FileSegment, handle.get(), splits[i], splits[i + 1], &hash_chunks[i]); - } - - for (auto &thread : threads) { - thread.join(); - } -#else - for (idx_t i = 0; i < numChunks; i++) { - ComputeSHA256FileSegment(handle.get(), splits[i], splits[i + 1], &hash_chunks[i]); - } -#endif // DUCKDB_NO_THREADS - - string hash_concatenation; - hash_concatenation.reserve(32 * numChunks); // 256 bits -> 32 bytes per chunk - - for (auto &hash_chunk : hash_chunks) { - hash_concatenation += hash_chunk; - } - - string two_level_hash; - ComputeSHA256String(hash_concatenation, &two_level_hash); - - // TODO maybe we should do a stream read / hash update here - handle->Read((void *)signature.data(), signature.size(), signature_offset); - - bool any_valid = false; - for (auto &key : ExtensionHelper::GetPublicKeys()) { - if (duckdb_mbedtls::MbedTlsWrapper::IsValidSha256Signature(key, signature, two_level_hash)) { - any_valid = true; - break; - } - } - if (!any_valid) { + if (!signature_valid) { throw IOException(config.error_manager->FormatException(ErrorType::UNSIGNED_EXTENSION, filename) + metadata_mismatch_error); } if (!metadata_mismatch_error.empty()) { // Signed extensions perform the full check - throw InvalidInputException(metadata_mismatch_error.substr(1)); + throw InvalidInputException(metadata_mismatch_error); } } else if (!config.options.allow_extensions_metadata_mismatch) { if (!metadata_mismatch_error.empty()) { - // Unsigned extensions AND configuration allowing metadata_mismatch_error, loading allowed, mainly for + // Unsigned extensions AND configuration allowing n, loading allowed, mainly for // debugging purposes - throw InvalidInputException(metadata_mismatch_error.substr(1)); + throw InvalidInputException(metadata_mismatch_error); } } - idx_t number_metadata_fields = 3; - D_ASSERT(number_metadata_fields == 3); // Currently hardcoded value - metadata_field.resize(number_metadata_fields + 1); - auto filebase = fs.ExtractBaseName(filename); #ifdef WASM_LOADABLE_EXTENSIONS @@ -311,10 +288,33 @@ bool ExtensionHelper::TryInitialLoad(DBConfig &config, FileSystem &fs, const str auto lowercase_extension_name = StringUtil::Lower(filebase); + // Initialize the ExtensionInitResult result.filebase = lowercase_extension_name; - result.extension_version = extension_version; result.filename = filename; result.lib_hdl = lib_hdl; + + if (!direct_load) { + auto info_file_name = filename + ".info"; + + result.install_info = ExtensionInstallInfo::TryReadInfoFile(fs, info_file_name, lowercase_extension_name); + + if (result.install_info->mode == ExtensionInstallMode::UNKNOWN) { + // The info file was missing, we just set the version, since we have it from the parsed footer + result.install_info->version = parsed_metadata.extension_version; + } + + if (result.install_info->version != parsed_metadata.extension_version) { + throw IOException("Metadata mismatch detected when loading extension '%s'\nPlease try reinstalling the " + "extension using `FORCE INSTALL '%s'`", + filename, extension); + } + } else { + result.install_info = make_uniq(); + result.install_info->mode = ExtensionInstallMode::NOT_INSTALLED; + result.install_info->full_path = filename; + result.install_info->version = parsed_metadata.extension_version; + } + return true; #endif } @@ -378,7 +378,9 @@ void ExtensionHelper::LoadExternalExtension(DatabaseInstance &db, FileSystem &fs init_fun_name, res.filename, error.RawMessage()); } - db.SetExtensionLoaded(extension, res.extension_version); + D_ASSERT(res.install_info); + + db.SetExtensionLoaded(extension, *res.install_info); #endif } diff --git a/src/main/extension/extension_util.cpp b/src/main/extension/extension_util.cpp index 9d72104c45e..f2071c7812b 100644 --- a/src/main/extension/extension_util.cpp +++ b/src/main/extension/extension_util.cpp @@ -101,6 +101,11 @@ void ExtensionUtil::RegisterCollation(DatabaseInstance &db, CreateCollationInfo auto data = CatalogTransaction::GetSystemTransaction(db); info.on_conflict = OnCreateConflict::IGNORE_ON_CONFLICT; system_catalog.CreateCollation(data, info); + + // Also register as a function for serialisation + CreateScalarFunctionInfo finfo(info.function); + finfo.on_conflict = OnCreateConflict::IGNORE_ON_CONFLICT; + system_catalog.CreateFunction(data, finfo); } void ExtensionUtil::AddFunctionOverload(DatabaseInstance &db, ScalarFunction function) { @@ -149,9 +154,10 @@ TableFunctionCatalogEntry &ExtensionUtil::GetTableFunction(DatabaseInstance &db, return catalog_entry->Cast(); } -void ExtensionUtil::RegisterType(DatabaseInstance &db, string type_name, LogicalType type) { +void ExtensionUtil::RegisterType(DatabaseInstance &db, string type_name, LogicalType type, + bind_type_modifiers_function_t bind_modifiers) { D_ASSERT(!type_name.empty()); - CreateTypeInfo info(std::move(type_name), std::move(type)); + CreateTypeInfo info(std::move(type_name), std::move(type), bind_modifiers); info.temporary = true; info.internal = true; auto &system_catalog = Catalog::GetSystemCatalog(db); diff --git a/src/main/extension_install_info.cpp b/src/main/extension_install_info.cpp new file mode 100644 index 00000000000..933a4a960c8 --- /dev/null +++ b/src/main/extension_install_info.cpp @@ -0,0 +1,116 @@ +#include "duckdb/main/extension_install_info.hpp" +#include "duckdb/common/string.hpp" +#include "duckdb/common/file_system.hpp" +#include "duckdb/common/serializer/buffered_file_reader.hpp" +#include "duckdb/common/serializer/binary_deserializer.hpp" + +namespace duckdb { + +string ExtensionRepository::GetRepository(const string &repository_url) { + auto resolved_repository = TryConvertUrlToKnownRepository(repository_url); + if (resolved_repository.empty()) { + return repository_url; + } + return resolved_repository; +} + +string ExtensionRepository::TryGetRepositoryUrl(const string &repository) { + if (repository == "core") { + return CORE_REPOSITORY_URL; + } else if (repository == "core_nightly") { + return CORE_NIGHTLY_REPOSITORY_URL; + } else if (repository == "community") { + return COMMUNITY_REPOSITORY_URL; + } else if (repository == "local_build_debug") { + return BUILD_DEBUG_REPOSITORY_PATH; + } else if (repository == "local_build_release") { + return BUILD_RELEASE_REPOSITORY_PATH; + } + return ""; +} + +string ExtensionRepository::TryConvertUrlToKnownRepository(const string &url) { + if (url == CORE_REPOSITORY_URL) { + return "core"; + } else if (url == CORE_NIGHTLY_REPOSITORY_URL) { + return "core_nightly"; + } else if (url == COMMUNITY_REPOSITORY_URL) { + return "community"; + } else if (url == BUILD_DEBUG_REPOSITORY_PATH) { + return "local_build_debug"; + } else if (url == BUILD_RELEASE_REPOSITORY_PATH) { + return "local_build_release"; + } + return ""; +} + +ExtensionRepository ExtensionRepository::GetDefaultRepository(optional_ptr config) { + if (config && !config->options.custom_extension_repo.empty()) { + return ExtensionRepository("", config->options.custom_extension_repo); + } + + return GetCoreRepository(); +} +ExtensionRepository ExtensionRepository::GetDefaultRepository(ClientContext &context) { + auto &config = DBConfig::GetConfig(context); + return GetDefaultRepository(config); +} + +ExtensionRepository ExtensionRepository::GetCoreRepository() { + return {"core", CORE_REPOSITORY_URL}; +} + +ExtensionRepository ExtensionRepository::GetRepositoryByUrl(const string &url) { + if (url.empty()) { + return GetCoreRepository(); + } + + auto repo_name = TryConvertUrlToKnownRepository(url); + return {repo_name, url}; +} + +ExtensionRepository::ExtensionRepository() : name("core"), path(CORE_REPOSITORY_URL) { +} +ExtensionRepository::ExtensionRepository(const string &name_p, const string &path_p) : name(name_p), path(path_p) { +} + +string ExtensionRepository::ToReadableString() { + if (!name.empty()) { + return name; + } + return path; +} + +unique_ptr ExtensionInstallInfo::TryReadInfoFile(FileSystem &fs, + const std::string &info_file_path, + const std::string &extension_name) { + unique_ptr result; + + string hint = StringUtil::Format("Try reinstalling the extension using 'FORCE INSTALL %s;'", extension_name); + + // Return empty info if the file is missing (TODO: throw error here in the future?) + if (!fs.FileExists(info_file_path)) { + return make_uniq(); + } + + BufferedFileReader file_reader(fs, info_file_path.c_str()); + if (!file_reader.Finished()) { + try { + result = BinaryDeserializer::Deserialize(file_reader); + } catch (std::exception &ex) { + ErrorData error(ex); + throw IOException( + "Failed to read info file for '%s' extension: '%s'.\nA serialization error occured: '%s'\n%s", + extension_name, info_file_path, error.RawMessage(), hint); + } + } + + if (!result) { + throw IOException("Failed to read info file for '%s' extension: '%s'.\nThe file appears to be empty!\n%s", + extension_name, info_file_path, hint); + } + + return result; +} + +} // namespace duckdb diff --git a/src/main/materialized_query_result.cpp b/src/main/materialized_query_result.cpp index 85bff412dfb..d319d5686b8 100644 --- a/src/main/materialized_query_result.cpp +++ b/src/main/materialized_query_result.cpp @@ -73,6 +73,17 @@ ColumnDataCollection &MaterializedQueryResult::Collection() { return *collection; } +unique_ptr MaterializedQueryResult::TakeCollection() { + if (HasError()) { + throw InvalidInputException("Attempting to get collection from an unsuccessful query result\n: Error %s", + GetError()); + } + if (!collection) { + throw InternalException("Missing collection from materialized query result"); + } + return std::move(collection); +} + unique_ptr MaterializedQueryResult::Fetch() { return FetchRaw(); } diff --git a/src/main/pending_query_result.cpp b/src/main/pending_query_result.cpp index a112286e2f9..ddc211b24ae 100644 --- a/src/main/pending_query_result.cpp +++ b/src/main/pending_query_result.cpp @@ -43,6 +43,11 @@ void PendingQueryResult::CheckExecutableInternal(ClientContextLock &lock) { } } +void PendingQueryResult::WaitForTask() { + auto lock = LockContext(); + context->WaitForTask(*lock, *this); +} + PendingExecutionResult PendingQueryResult::ExecuteTask() { auto lock = LockContext(); return ExecuteTaskInternal(*lock); @@ -65,16 +70,21 @@ PendingExecutionResult PendingQueryResult::ExecuteTaskInternal(ClientContextLock unique_ptr PendingQueryResult::ExecuteInternal(ClientContextLock &lock) { CheckExecutableInternal(lock); - // Busy wait while execution is not finished - if (allow_stream_result) { - while (!IsFinishedOrBlocked(ExecuteTaskInternal(lock))) { - } - } else { - while (!IsFinished(ExecuteTaskInternal(lock))) { + + const auto is_finished = allow_stream_result ? IsFinishedOrBlocked : IsFinished; + PendingExecutionResult execution_result; + while (!is_finished(execution_result = ExecuteTaskInternal(lock))) { + if (execution_result == PendingExecutionResult::BLOCKED) { + CheckExecutableInternal(lock); + context->WaitForTask(lock, *this); } } if (HasError()) { - return make_uniq(error); + if (allow_stream_result) { + return make_uniq(error); + } else { + return make_uniq(error); + } } auto result = context->FetchResultInternal(lock, *this); Close(); diff --git a/src/main/profiling_info.cpp b/src/main/profiling_info.cpp new file mode 100644 index 00000000000..5bf47c72301 --- /dev/null +++ b/src/main/profiling_info.cpp @@ -0,0 +1,65 @@ +#include "duckdb/main/profiling_info.hpp" + +#include "duckdb/common/enum_util.hpp" +#include "duckdb/main/query_profiler.hpp" + +namespace duckdb { + +void ProfilingInfo::SetSettings(profiler_settings_t const &n_settings) { + this->settings = n_settings; +} + +const profiler_settings_t &ProfilingInfo::GetSettings() { + return settings; +} + +profiler_settings_t ProfilingInfo::DefaultSettings() { + return { + MetricsType::CPU_TIME, + MetricsType::EXTRA_INFO, + MetricsType::OPERATOR_CARDINALITY, + MetricsType::OPERATOR_TIMING, + }; +} + +void ProfilingInfo::ResetSettings() { + settings.clear(); + settings = DefaultSettings(); +} + +void ProfilingInfo::ResetMetrics() { + metrics = Metrics(); +} + +bool ProfilingInfo::Enabled(const MetricsType setting) const { + if (settings.find(setting) != settings.end()) { + return true; + } + if (setting == MetricsType::OPERATOR_TIMING && Enabled(MetricsType::CPU_TIME)) { + return true; + } + return false; +} + +string ProfilingInfo::GetMetricAsString(MetricsType setting) const { + switch (setting) { + case MetricsType::CPU_TIME: + return to_string(metrics.cpu_time); + case MetricsType::EXTRA_INFO: + return "\"" + QueryProfiler::JSONSanitize(metrics.extra_info) + "\""; + case MetricsType::OPERATOR_CARDINALITY: + return to_string(metrics.operator_cardinality); + case MetricsType::OPERATOR_TIMING: + return to_string(metrics.operator_timing); + } + return ""; +} + +void ProfilingInfo::PrintAllMetricsToSS(std::ostream &ss, const string &depth) { + for (auto &metric : settings) { + ss << depth << " \"" << StringUtil::Lower(EnumUtil::ToString(metric)) << "\": " << GetMetricAsString(metric) + << ",\n"; + } +} + +} // namespace duckdb diff --git a/src/main/query_profiler.cpp b/src/main/query_profiler.cpp index 79e3020679c..71fa241941a 100644 --- a/src/main/query_profiler.cpp +++ b/src/main/query_profiler.cpp @@ -116,8 +116,9 @@ bool QueryProfiler::OperatorRequiresProfiling(PhysicalOperatorType op_type) { void QueryProfiler::Finalize(TreeNode &node) { for (auto &child : node.children) { Finalize(*child); - if (node.type == PhysicalOperatorType::UNION) { - node.info.elements += child->info.elements; + if (node.type == PhysicalOperatorType::UNION && + node.profiling_info.Enabled(MetricsType::OPERATOR_CARDINALITY)) { + node.profiling_info.metrics.operator_cardinality += child->profiling_info.metrics.operator_cardinality; } } } @@ -126,6 +127,16 @@ void QueryProfiler::StartExplainAnalyze() { this->is_explain_analyze = true; } +static void GetTotalCPUTime(QueryProfiler::TreeNode &node) { + node.profiling_info.metrics.cpu_time = node.profiling_info.metrics.operator_timing; + if (!node.children.empty()) { + for (const auto &i : node.children) { + GetTotalCPUTime(*i); + node.profiling_info.metrics.cpu_time += i->profiling_info.metrics.cpu_time; + } + } +} + void QueryProfiler::EndQuery() { lock_guard guard(flush_lock); if (!IsEnabled() || !running) { @@ -133,26 +144,41 @@ void QueryProfiler::EndQuery() { } main_query.End(); - if (root) { + if (root && root->profiling_info.Enabled(MetricsType::OPERATOR_CARDINALITY)) { Finalize(*root); } this->running = false; // print or output the query profiling after termination // EXPLAIN ANALYSE should not be outputted by the profiler if (IsEnabled() && !is_explain_analyze) { - string query_info = ToString(); + // initialize the query info + if (root) { + query_info->query = query; + query_info->settings = ProfilingInfo(ClientConfig::GetConfig(context).profiler_settings); + if (query_info->settings.Enabled(MetricsType::OPERATOR_TIMING)) { + query_info->settings.metrics.operator_timing = main_query.Elapsed(); + } + if (query_info->settings.Enabled(MetricsType::CPU_TIME)) { + GetTotalCPUTime(*root); + query_info->settings.metrics.cpu_time = root->profiling_info.metrics.cpu_time; + } + } + + string tree = ToString(); auto save_location = GetSaveLocation(); + if (!ClientConfig::GetConfig(context).emit_profiler_output) { // disable output } else if (save_location.empty()) { - Printer::Print(query_info); + Printer::Print(tree); Printer::Print("\n"); } else { - WriteToFile(save_location.c_str(), query_info); + WriteToFile(save_location.c_str(), tree); } } this->is_explain_analyze = false; } + string QueryProfiler::ToString() const { const auto format = GetPrintFormat(); switch (format) { @@ -215,7 +241,9 @@ void QueryProfiler::Initialize(const PhysicalOperator &root_op) { return; } this->query_requires_profiling = false; - this->root = CreateTree(root_op); + ClientConfig &config = ClientConfig::GetConfig(context); + this->root = CreateTree(root_op, config.profiler_settings, 0); + this->query_info = make_uniq(); if (!query_requires_profiling) { // query does not require profiling: disable profiling for this query this->running = false; @@ -226,7 +254,9 @@ void QueryProfiler::Initialize(const PhysicalOperator &root_op) { } } -OperatorProfiler::OperatorProfiler(bool enabled_p) : enabled(enabled_p), active_operator(nullptr) { +OperatorProfiler::OperatorProfiler(ClientContext &context) { + enabled = QueryProfiler::Get(context).IsEnabled(); + settings = ClientConfig::GetConfig(context).profiler_settings; } void OperatorProfiler::StartOperator(optional_ptr phys_op) { @@ -241,7 +271,9 @@ void OperatorProfiler::StartOperator(optional_ptr phys_o active_operator = phys_op; // start timing for current element - op.Start(); + if (SettingEnabled(MetricsType::OPERATOR_TIMING)) { + op.Start(); + } } void OperatorProfiler::EndOperator(optional_ptr chunk) { @@ -253,30 +285,35 @@ void OperatorProfiler::EndOperator(optional_ptr chunk) { throw InternalException("OperatorProfiler: Attempting to call EndOperator while another operator is active"); } - // finish timing for the current element - op.End(); + bool timing_enabled = SettingEnabled(MetricsType::OPERATOR_TIMING); + bool cardinality_enabled = SettingEnabled(MetricsType::OPERATOR_CARDINALITY); + if (timing_enabled || cardinality_enabled) { + // get the operator info for the current element + auto &curr_operator_info = GetOperatorInfo(*active_operator); - AddTiming(*active_operator, op.Elapsed(), chunk ? chunk->size() : 0); + // finish timing for the current element + if (timing_enabled) { + op.End(); + curr_operator_info.AddTime(op.Elapsed()); + } + if (cardinality_enabled && chunk) { + curr_operator_info.AddElements(chunk->size()); + } + } active_operator = nullptr; } -void OperatorProfiler::AddTiming(const PhysicalOperator &op, double time, idx_t elements) { - if (!enabled) { - return; - } - if (!Value::DoubleIsFinite(time)) { - return; - } - auto entry = timings.find(op); - if (entry == timings.end()) { - // add new entry - timings[op] = OperatorInformation(time, elements); +OperatorInformation &OperatorProfiler::GetOperatorInfo(const PhysicalOperator &phys_op) { + auto entry = timings.find(phys_op); + if (entry != timings.end()) { + return entry->second; } else { - // add to existing entry - entry->second.time += time; - entry->second.elements += elements; + // add new entry + timings[phys_op] = OperatorInformation(); + return timings[phys_op]; } } + void OperatorProfiler::Flush(const PhysicalOperator &phys_op, ExpressionExecutor &expression_executor, const string &name, int id) { auto entry = timings.find(phys_op); @@ -298,10 +335,11 @@ void QueryProfiler::Flush(OperatorProfiler &profiler) { D_ASSERT(entry != tree_map.end()); auto &tree_node = entry->second.get(); - tree_node.info.time += node.second.time; - tree_node.info.elements += node.second.elements; - if (!IsDetailedEnabled()) { - continue; + if (profiler.SettingEnabled(MetricsType::OPERATOR_TIMING)) { + tree_node.profiling_info.metrics.operator_timing += node.second.time; + } + if (profiler.SettingEnabled(MetricsType::OPERATOR_CARDINALITY)) { + tree_node.profiling_info.metrics.operator_cardinality += node.second.elements; } } profiler.timings.clear(); @@ -436,11 +474,11 @@ void QueryProfiler::QueryTreeToStream(std::ostream &ss) const { } } -static string JSONSanitize(const string &text) { +string QueryProfiler::JSONSanitize(const std::string &text) { string result; result.reserve(text.size()); - for (idx_t i = 0; i < text.size(); i++) { - switch (text[i]) { + for (char i : text) { + switch (i) { case '\b': result += "\\b"; break; @@ -463,7 +501,7 @@ static string JSONSanitize(const string &text) { result += "\\\\"; break; default: - result += text[i]; + result += i; break; } } @@ -472,10 +510,13 @@ static string JSONSanitize(const string &text) { static void ToJSONRecursive(QueryProfiler::TreeNode &node, std::ostream &ss, idx_t depth = 1) { ss << string(depth * 3, ' ') << " {\n"; - ss << string(depth * 3, ' ') << " \"name\": \"" + JSONSanitize(node.name) + "\",\n"; - ss << string(depth * 3, ' ') << " \"timing\":" + to_string(node.info.time) + ",\n"; - ss << string(depth * 3, ' ') << " \"cardinality\":" + to_string(node.info.elements) + ",\n"; - ss << string(depth * 3, ' ') << " \"extra_info\": \"" + JSONSanitize(node.extra_info) + "\",\n"; + ss << string(depth * 3, ' ') << " \"name\": \"" + QueryProfiler::JSONSanitize(node.name) + "\",\n"; + ss << string(depth * 3, ' ') + << " \"operator_timing\":" + to_string(node.profiling_info.metrics.operator_timing) + ",\n"; + ss << string(depth * 3, ' ') + << " \"operator_cardinality\":" + to_string(node.profiling_info.metrics.operator_cardinality) + ",\n"; + ss << string(depth * 3, ' ') + << " \"extra_info\": \"" + QueryProfiler::JSONSanitize(node.profiling_info.metrics.extra_info) + "\",\n"; ss << string(depth * 3, ' ') << " \"children\": [\n"; if (node.children.empty()) { ss << string(depth * 3, ' ') << " ]\n"; @@ -501,32 +542,33 @@ string QueryProfiler::ToJSON() const { if (!root) { return "{ \"result\": \"error\" }\n"; } + + auto &settings = query_info->settings; + std::stringstream ss; ss << "{\n"; - ss << " \"name\": \"Query\", \n"; - ss << " \"result\": " + to_string(main_query.Elapsed()) + ",\n"; - ss << " \"timing\": " + to_string(main_query.Elapsed()) + ",\n"; - ss << " \"cardinality\": " + to_string(root->info.elements) + ",\n"; + ss << " \"Query\": \"" + JSONSanitize(query_info->query) + "\",\n"; + + settings.PrintAllMetricsToSS(ss, ""); // JSON cannot have literal control characters in string literals - string extra_info = JSONSanitize(query); - ss << " \"extra-info\": \"" + extra_info + "\", \n"; - // print the phase timings - ss << " \"timings\": [\n"; - const auto &ordered_phase_timings = GetOrderedPhaseTimings(); - for (idx_t i = 0; i < ordered_phase_timings.size(); i++) { - if (i > 0) { - ss << ",\n"; + if (settings.Enabled(MetricsType::EXTRA_INFO)) { + ss << " \"timings\": [\n"; + const auto &ordered_phase_timings = GetOrderedPhaseTimings(); + for (idx_t i = 0; i < ordered_phase_timings.size(); i++) { + if (i > 0) { + ss << ",\n"; + } + ss << " {\n"; + ss << " \"annotation\": \"" + ordered_phase_timings[i].first + "\", \n"; + ss << " \"timing\": " + to_string(ordered_phase_timings[i].second) + "\n"; + ss << " }"; } - ss << " {\n"; - ss << " \"annotation\": \"" + ordered_phase_timings[i].first + "\", \n"; - ss << " \"timing\": " + to_string(ordered_phase_timings[i].second) + "\n"; - ss << " }"; + ss << "\n"; + ss << " ],\n"; } - ss << "\n"; - ss << " ],\n"; // recursively print the physical operator tree ss << " \"children\": [\n"; - ToJSONRecursive(*root, ss); + ToJSONRecursive(*root->children[0], ss); ss << " ]\n"; ss << "}"; return ss.str(); @@ -542,19 +584,23 @@ void QueryProfiler::WriteToFile(const char *path, string &info) const { } } -unique_ptr QueryProfiler::CreateTree(const PhysicalOperator &root, idx_t depth) { +unique_ptr QueryProfiler::CreateTree(const PhysicalOperator &root, + profiler_settings_t settings, idx_t depth) { if (OperatorRequiresProfiling(root.type)) { this->query_requires_profiling = true; } auto node = make_uniq(); node->type = root.type; node->name = root.GetName(); - node->extra_info = root.ParamsToString(); node->depth = depth; + node->profiling_info = ProfilingInfo(settings); + if (node->profiling_info.Enabled(MetricsType::EXTRA_INFO)) { + node->profiling_info.metrics.extra_info = root.ParamsToString(); + } tree_map.insert(make_pair(reference(root), reference(*node))); auto children = root.GetChildren(); for (auto &child : children) { - auto child_node = CreateTree(child.get(), depth + 1); + auto child_node = CreateTree(child.get(), settings, depth + 1); node->children.push_back(std::move(child_node)); } return node; diff --git a/src/main/query_result.cpp b/src/main/query_result.cpp index cd3e3b943ec..901865b902a 100644 --- a/src/main/query_result.cpp +++ b/src/main/query_result.cpp @@ -61,7 +61,7 @@ QueryResult::QueryResult(QueryResultType type, StatementType statement_type, Sta } QueryResult::QueryResult(QueryResultType type, ErrorData error) - : BaseQueryResult(type, std::move(error)), client_properties("UTC", ArrowOffsetSize::REGULAR) { + : BaseQueryResult(type, std::move(error)), client_properties("UTC", ArrowOffsetSize::REGULAR, false, false) { } QueryResult::~QueryResult() { diff --git a/src/main/relation.cpp b/src/main/relation.cpp index 2848a552c9b..6215b037261 100644 --- a/src/main/relation.cpp +++ b/src/main/relation.cpp @@ -387,12 +387,16 @@ string Relation::RenderWhitespace(idx_t depth) { return string(depth * 2, ' '); } +void Relation::AddExternalDependency(shared_ptr dependency) { + external_dependencies.push_back(std::move(dependency)); +} + vector> Relation::GetAllDependencies() { vector> all_dependencies; Relation *cur = this; while (cur) { - if (cur->extra_dependencies) { - all_dependencies.push_back(cur->extra_dependencies); + for (auto &dep : cur->external_dependencies) { + all_dependencies.push_back(dep); } cur = cur->ChildRelation(); } diff --git a/src/main/relation/CMakeLists.txt b/src/main/relation/CMakeLists.txt index fc119bb7293..78584625d52 100644 --- a/src/main/relation/CMakeLists.txt +++ b/src/main/relation/CMakeLists.txt @@ -23,6 +23,7 @@ add_library_unity( table_function_relation.cpp table_relation.cpp value_relation.cpp + materialized_relation.cpp view_relation.cpp write_parquet_relation.cpp write_csv_relation.cpp) diff --git a/src/main/relation/create_view_relation.cpp b/src/main/relation/create_view_relation.cpp index b9c80c07451..92dcf755c48 100644 --- a/src/main/relation/create_view_relation.cpp +++ b/src/main/relation/create_view_relation.cpp @@ -9,6 +9,9 @@ CreateViewRelation::CreateViewRelation(shared_ptr child_p, string view bool temporary_p) : Relation(child_p->context, RelationType::CREATE_VIEW_RELATION), child(std::move(child_p)), view_name(std::move(view_name_p)), replace(replace_p), temporary(temporary_p) { + if (child->type == RelationType::MATERIALIZED_RELATION) { + throw NotImplementedException("Creating a VIEW from a MaterializedRelation is not supported"); + } context.GetContext()->TryBindRelation(*this, this->columns); } @@ -17,6 +20,9 @@ CreateViewRelation::CreateViewRelation(shared_ptr child_p, string sche : Relation(child_p->context, RelationType::CREATE_VIEW_RELATION), child(std::move(child_p)), schema_name(std::move(schema_name_p)), view_name(std::move(view_name_p)), replace(replace_p), temporary(temporary_p) { + if (child->type == RelationType::MATERIALIZED_RELATION) { + throw NotImplementedException("Creating a VIEW from a MaterializedRelation is not supported"); + } context.GetContext()->TryBindRelation(*this, this->columns); } diff --git a/src/main/relation/materialized_relation.cpp b/src/main/relation/materialized_relation.cpp new file mode 100644 index 00000000000..4445240ea3f --- /dev/null +++ b/src/main/relation/materialized_relation.cpp @@ -0,0 +1,58 @@ +#include "duckdb/main/relation/materialized_relation.hpp" +#include "duckdb/parser/query_node/select_node.hpp" +#include "duckdb/main/client_context.hpp" +#include "duckdb/planner/bound_statement.hpp" +#include "duckdb/planner/operator/logical_column_data_get.hpp" +#include "duckdb/parser/tableref/column_data_ref.hpp" +#include "duckdb/parser/expression/star_expression.hpp" +#include "duckdb/common/exception.hpp" + +namespace duckdb { + +MaterializedRelation::MaterializedRelation(const shared_ptr &context, + unique_ptr &&collection_p, vector names, + string alias_p) + : Relation(context, RelationType::MATERIALIZED_RELATION), collection(std::move(collection_p)), + alias(std::move(alias_p)) { + // create constant expressions for the values + auto types = collection->Types(); + D_ASSERT(types.size() == names.size()); + + QueryResult::DeduplicateColumns(names); + for (idx_t i = 0; i < types.size(); i++) { + auto &type = types[i]; + auto &name = names[i]; + auto column_definition = ColumnDefinition(name, type); + columns.push_back(std::move(column_definition)); + } +} + +unique_ptr MaterializedRelation::GetQueryNode() { + auto result = make_uniq(); + result->select_list.push_back(make_uniq()); + result->from_table = GetTableRef(); + return std::move(result); +} + +unique_ptr MaterializedRelation::GetTableRef() { + auto table_ref = make_uniq(*collection); + for (auto &col : columns) { + table_ref->expected_names.push_back(col.Name()); + } + table_ref->alias = GetAlias(); + return std::move(table_ref); +} + +string MaterializedRelation::GetAlias() { + return alias; +} + +const vector &MaterializedRelation::Columns() { + return columns; +} + +string MaterializedRelation::ToString(idx_t depth) { + return collection->ToString(); +} + +} // namespace duckdb diff --git a/src/main/relation/query_relation.cpp b/src/main/relation/query_relation.cpp index 0ce867f5157..3d30a154481 100644 --- a/src/main/relation/query_relation.cpp +++ b/src/main/relation/query_relation.cpp @@ -1,8 +1,15 @@ #include "duckdb/main/relation/query_relation.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/parser/statement/select_statement.hpp" +#include "duckdb/parser/expression/star_expression.hpp" #include "duckdb/parser/tableref/subqueryref.hpp" +#include "duckdb/parser/tableref/joinref.hpp" #include "duckdb/parser/parser.hpp" +#include "duckdb/planner/bound_statement.hpp" +#include "duckdb/planner/binder.hpp" +#include "duckdb/parser/query_node/select_node.hpp" +#include "duckdb/planner/query_node/bound_select_node.hpp" +#include "duckdb/parser/common_table_expression_info.hpp" namespace duckdb { @@ -43,6 +50,42 @@ unique_ptr QueryRelation::GetTableRef() { return std::move(subquery_ref); } +BoundStatement QueryRelation::Bind(Binder &binder) { + auto saved_binding_mode = binder.GetBindingMode(); + binder.SetBindingMode(BindingMode::EXTRACT_REPLACEMENT_SCANS); + bool first_bind = columns.empty(); + auto result = Relation::Bind(binder); + auto &replacements = binder.GetReplacementScans(); + if (first_bind) { + auto &query_node = *select_stmt->node; + auto &cte_map = query_node.cte_map; + for (auto &kv : replacements) { + auto &name = kv.first; + auto &tableref = kv.second; + + if (!tableref->external_dependency) { + // Only push a CTE for objects that are out of our control (i.e Python) + // This makes sure replacement scans for files (parquet/csv/json etc) are not transformed into a CTE + continue; + } + + auto select = make_uniq(); + auto select_node = make_uniq(); + select_node->select_list.push_back(make_uniq()); + select_node->from_table = std::move(tableref); + select->node = std::move(select_node); + + auto cte_info = make_uniq(); + cte_info->query = std::move(select); + + cte_map.map[name] = std::move(cte_info); + } + } + replacements.clear(); + binder.SetBindingMode(saved_binding_mode); + return result; +} + string QueryRelation::GetAlias() { return alias; } diff --git a/src/main/relation/read_csv_relation.cpp b/src/main/relation/read_csv_relation.cpp index cce7dba4ec8..4c37e301e72 100644 --- a/src/main/relation/read_csv_relation.cpp +++ b/src/main/relation/read_csv_relation.cpp @@ -39,8 +39,10 @@ ReadCSVRelation::ReadCSVRelation(const shared_ptr &context, const auto file_list = CreateValueFromFileList(input); + auto multi_file_reader = MultiFileReader::CreateDefault("ReadCSVRelation"); vector files; - context->RunFunctionInTransaction([&]() { files = MultiFileReader::GetFileList(*context, file_list, "CSV"); }); + context->RunFunctionInTransaction( + [&]() { files = multi_file_reader->CreateFileList(*context, file_list)->GetAllFiles(); }); D_ASSERT(!files.empty()); auto &file_name = files[0]; diff --git a/src/main/relation/write_csv_relation.cpp b/src/main/relation/write_csv_relation.cpp index 016ea0186bd..a521f8cae0f 100644 --- a/src/main/relation/write_csv_relation.cpp +++ b/src/main/relation/write_csv_relation.cpp @@ -15,8 +15,8 @@ WriteCSVRelation::WriteCSVRelation(shared_ptr child_p, string csv_file BoundStatement WriteCSVRelation::Bind(Binder &binder) { CopyStatement copy; - copy.select_statement = child->GetQueryNode(); auto info = make_uniq(); + info->select_statement = child->GetQueryNode(); info->is_from = false; info->file_path = csv_file; info->format = "csv"; diff --git a/src/main/relation/write_parquet_relation.cpp b/src/main/relation/write_parquet_relation.cpp index 6cedc29cb38..c2d937a2f84 100644 --- a/src/main/relation/write_parquet_relation.cpp +++ b/src/main/relation/write_parquet_relation.cpp @@ -15,8 +15,8 @@ WriteParquetRelation::WriteParquetRelation(shared_ptr child_p, string BoundStatement WriteParquetRelation::Bind(Binder &binder) { CopyStatement copy; - copy.select_statement = child->GetQueryNode(); auto info = make_uniq(); + info->select_statement = child->GetQueryNode(); info->is_from = false; info->file_path = parquet_file; info->format = "parquet"; diff --git a/src/main/settings/settings.cpp b/src/main/settings/settings.cpp index c7da7bfbea1..3a26fb3a3cf 100644 --- a/src/main/settings/settings.cpp +++ b/src/main/settings/settings.cpp @@ -437,6 +437,38 @@ Value EnableExternalAccessSetting::GetSetting(const ClientContext &context) { return Value::BOOLEAN(config.options.enable_external_access); } +//===--------------------------------------------------------------------===// +// Enable Macro Dependencies +//===--------------------------------------------------------------------===// +void EnableMacrosDependencies::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { + config.options.enable_macro_dependencies = input.GetValue(); +} + +void EnableMacrosDependencies::ResetGlobal(DatabaseInstance *db, DBConfig &config) { + config.options.enable_macro_dependencies = DBConfig().options.enable_macro_dependencies; +} + +Value EnableMacrosDependencies::GetSetting(const ClientContext &context) { + auto &config = DBConfig::GetConfig(context); + return Value::BOOLEAN(config.options.enable_macro_dependencies); +} + +//===--------------------------------------------------------------------===// +// Enable View Dependencies +//===--------------------------------------------------------------------===// +void EnableViewDependencies::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { + config.options.enable_view_dependencies = input.GetValue(); +} + +void EnableViewDependencies::ResetGlobal(DatabaseInstance *db, DBConfig &config) { + config.options.enable_view_dependencies = DBConfig().options.enable_view_dependencies; +} + +Value EnableViewDependencies::GetSetting(const ClientContext &context) { + auto &config = DBConfig::GetConfig(context); + return Value::BOOLEAN(config.options.enable_view_dependencies); +} + //===--------------------------------------------------------------------===// // Enable FSST Vectors //===--------------------------------------------------------------------===// @@ -476,6 +508,36 @@ Value AllowUnsignedExtensionsSetting::GetSetting(const ClientContext &context) { return Value::BOOLEAN(config.options.allow_unsigned_extensions); } +//===--------------------------------------------------------------------===// +// Allow Community Extensions +//===--------------------------------------------------------------------===// +void AllowCommunityExtensionsSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { + if (db && !config.options.allow_community_extensions) { + auto new_value = input.GetValue(); + if (new_value) { + throw InvalidInputException("Cannot upgrade allow_community_extensions setting while database is running"); + } + return; + } + auto new_value = input.GetValue(); + config.options.allow_community_extensions = new_value; +} + +void AllowCommunityExtensionsSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) { + if (db && !config.options.allow_community_extensions) { + if (DBConfig().options.allow_community_extensions) { + throw InvalidInputException("Cannot upgrade allow_community_extensions setting while database is running"); + } + return; + } + config.options.allow_community_extensions = DBConfig().options.allow_community_extensions; +} + +Value AllowCommunityExtensionsSetting::GetSetting(const ClientContext &context) { + auto &config = DBConfig::GetConfig(context); + return Value::BOOLEAN(config.options.allow_community_extensions); +} + //===--------------------------------------------------------------------===// // Allow Extensions Metadata Mismatch //===--------------------------------------------------------------------===// @@ -532,6 +594,26 @@ Value EnableObjectCacheSetting::GetSetting(const ClientContext &context) { return Value::BOOLEAN(config.options.object_cache_enable); } +//===--------------------------------------------------------------------===// +// Storage Compatibility Version (for serialization) +//===--------------------------------------------------------------------===// +void StorageCompatibilityVersion::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { + auto version_string = input.GetValue(); + auto serialization_compatibility = SerializationCompatibility::FromString(version_string); + config.options.serialization_compatibility = serialization_compatibility; +} + +void StorageCompatibilityVersion::ResetGlobal(DatabaseInstance *db, DBConfig &config) { + config.options.serialization_compatibility = DBConfig().options.serialization_compatibility; +} + +Value StorageCompatibilityVersion::GetSetting(const ClientContext &context) { + auto &config = DBConfig::GetConfig(context); + + auto &version_name = config.options.serialization_compatibility.duckdb_version; + return Value(version_name); +} + //===--------------------------------------------------------------------===// // Enable HTTP Metadata Cache //===--------------------------------------------------------------------===// @@ -593,6 +675,70 @@ Value EnableProfilingSetting::GetSetting(const ClientContext &context) { } } +//===--------------------------------------------------------------------===// +// Custom Profiling Settings +//===--------------------------------------------------------------------===// + +static profiler_settings_t FillTreeNodeSettings(unordered_map &json) { + profiler_settings_t metrics; + + string invalid_settings; + for (auto &entry : json) { + MetricsType setting; + try { + setting = EnumUtil::FromString(StringUtil::Upper(entry.first)); + } catch (std::exception &ex) { + if (!invalid_settings.empty()) { + invalid_settings += ", "; + } + invalid_settings += entry.first; + continue; + } + if (StringUtil::Lower(entry.second) == "true") { + metrics.insert(setting); + } + } + + if (!invalid_settings.empty()) { + throw IOException("Invalid custom profiler settings: \"%s\"", invalid_settings); + } + return metrics; +} + +void CustomProfilingSettings::SetLocal(ClientContext &context, const Value &input) { + auto &config = ClientConfig::GetConfig(context); + + // parse the file content + unordered_map json; + try { + json = StringUtil::ParseJSONMap(input.ToString()); + } catch (std::exception &ex) { + throw IOException("Could not parse the custom profiler settings file due to incorrect JSON: \"%s\". Make sure " + "all the keys and values start with a quote. ", + input.ToString()); + } + + config.profiler_settings = FillTreeNodeSettings(json); +} + +void CustomProfilingSettings::ResetLocal(ClientContext &context) { + auto &config = ClientConfig::GetConfig(context); + config.profiler_settings = ProfilingInfo::DefaultSettings(); +} + +Value CustomProfilingSettings::GetSetting(const ClientContext &context) { + auto &config = ClientConfig::GetConfig(context); + + string profiling_settings_str; + for (auto &entry : config.profiler_settings) { + if (!profiling_settings_str.empty()) { + profiling_settings_str += ", "; + } + profiling_settings_str += StringUtil::Format("\"%s\": \"true\"", EnumUtil::ToString(entry)); + } + return Value(StringUtil::Format("{%s}", profiling_settings_str)); +} + //===--------------------------------------------------------------------===// // Custom Extension Repository //===--------------------------------------------------------------------===// @@ -988,6 +1134,24 @@ Value MaximumMemorySetting::GetSetting(const ClientContext &context) { return Value(StringUtil::BytesToHumanReadableString(config.options.maximum_memory)); } +//===--------------------------------------------------------------------===// +// Streaming Buffer Size +//===--------------------------------------------------------------------===// +void StreamingBufferSize::SetLocal(ClientContext &context, const Value &input) { + auto &config = ClientConfig::GetConfig(context); + config.streaming_buffer_size = DBConfig::ParseMemoryLimit(input.ToString()); +} + +void StreamingBufferSize::ResetLocal(ClientContext &context) { + auto &config = ClientConfig::GetConfig(context); + config.SetDefaultStreamingBufferSize(); +} + +Value StreamingBufferSize::GetSetting(const ClientContext &context) { + auto &config = ClientConfig::GetConfig(context); + return Value(StringUtil::BytesToHumanReadableString(config.streaming_buffer_size)); +} + //===--------------------------------------------------------------------===// // Maximum Temp Directory Size //===--------------------------------------------------------------------===// @@ -1065,6 +1229,24 @@ Value PartitionedWriteFlushThreshold::GetSetting(const ClientContext &context) { return Value::BIGINT(NumericCast(ClientConfig::GetConfig(context).partitioned_write_flush_threshold)); } +//===--------------------------------------------------------------------===// +// Preferred block allocation size +//===--------------------------------------------------------------------===// +void DefaultBlockAllocSize::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { + idx_t block_alloc_size = input.GetValue(); + Storage::VerifyBlockAllocSize(block_alloc_size); + config.options.default_block_alloc_size = block_alloc_size; +} + +void DefaultBlockAllocSize::ResetGlobal(DatabaseInstance *db, DBConfig &config) { + config.options.default_block_alloc_size = DBConfig().options.default_block_alloc_size; +} + +Value DefaultBlockAllocSize::GetSetting(const ClientContext &context) { + auto &config = DBConfig::GetConfig(context); + return Value::UBIGINT(config.options.default_block_alloc_size); +} + //===--------------------------------------------------------------------===// // Password Setting //===--------------------------------------------------------------------===// @@ -1179,6 +1361,39 @@ Value ExportLargeBufferArrow::GetSetting(const ClientContext &context) { return Value::BOOLEAN(export_large_buffers_arrow); } +//===--------------------------------------------------------------------===// +// ArrowOutputListView +//===--------------------------------------------------------------------===// +void ArrowOutputListView::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { + auto arrow_output_list_view = input.GetValue(); + + config.options.arrow_use_list_view = arrow_output_list_view; +} + +void ArrowOutputListView::ResetGlobal(DatabaseInstance *db, DBConfig &config) { + config.options.arrow_use_list_view = DBConfig().options.arrow_use_list_view; +} + +Value ArrowOutputListView::GetSetting(const ClientContext &context) { + auto &config = DBConfig::GetConfig(context); + bool arrow_output_list_view = config.options.arrow_use_list_view; + return Value::BOOLEAN(arrow_output_list_view); +} + +// ProduceArrowStringView +//===--------------------------------------------------------------------===// +void ProduceArrowStringView::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { + config.options.produce_arrow_string_views = input.GetValue(); +} + +void ProduceArrowStringView::ResetGlobal(DatabaseInstance *db, DBConfig &config) { + config.options.produce_arrow_string_views = DBConfig().options.produce_arrow_string_views; +} + +Value ProduceArrowStringView::GetSetting(const ClientContext &context) { + return Value::BOOLEAN(DBConfig::GetConfig(context).options.produce_arrow_string_views); +} + //===--------------------------------------------------------------------===// // Profile Output //===--------------------------------------------------------------------===// @@ -1400,6 +1615,28 @@ Value FlushAllocatorSetting::GetSetting(const ClientContext &context) { return Value(StringUtil::BytesToHumanReadableString(config.options.allocator_flush_threshold)); } +//===--------------------------------------------------------------------===// +// Allocator Background Thread +//===--------------------------------------------------------------------===// +void AllocatorBackgroundThreadsSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { + config.options.allocator_background_threads = input.GetValue(); + if (db) { + TaskScheduler::GetScheduler(*db).SetAllocatorBackgroundThreads(config.options.allocator_background_threads); + } +} + +void AllocatorBackgroundThreadsSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config) { + config.options.allocator_background_threads = DBConfig().options.allocator_background_threads; + if (db) { + TaskScheduler::GetScheduler(*db).SetAllocatorBackgroundThreads(config.options.allocator_background_threads); + } +} + +Value AllocatorBackgroundThreadsSetting::GetSetting(const ClientContext &context) { + auto &config = DBConfig::GetConfig(context); + return Value(config.options.allocator_background_threads); +} + //===--------------------------------------------------------------------===// // DuckDBApi Setting //===--------------------------------------------------------------------===// @@ -1449,4 +1686,34 @@ Value CustomUserAgentSetting::GetSetting(const ClientContext &context) { return Value(config.options.custom_user_agent); } +//===--------------------------------------------------------------------===// +// EnableHTTPLogging Setting +//===--------------------------------------------------------------------===// +void EnableHTTPLoggingSetting::ResetLocal(ClientContext &context) { + ClientConfig::GetConfig(context).enable_http_logging = ClientConfig().enable_http_logging; +} + +void EnableHTTPLoggingSetting::SetLocal(ClientContext &context, const Value &input) { + ClientConfig::GetConfig(context).enable_http_logging = input.GetValue(); +} + +Value EnableHTTPLoggingSetting::GetSetting(const ClientContext &context) { + return Value(ClientConfig::GetConfig(context).enable_http_logging); +} + +//===--------------------------------------------------------------------===// +// HTTPLoggingOutput Setting +//===--------------------------------------------------------------------===// +void HTTPLoggingOutputSetting::ResetLocal(ClientContext &context) { + ClientConfig::GetConfig(context).http_logging_output = ClientConfig().http_logging_output; +} + +void HTTPLoggingOutputSetting::SetLocal(ClientContext &context, const Value &input) { + ClientConfig::GetConfig(context).http_logging_output = input.GetValue(); +} + +Value HTTPLoggingOutputSetting::GetSetting(const ClientContext &context) { + return Value(ClientConfig::GetConfig(context).http_logging_output); +} + } // namespace duckdb diff --git a/src/main/stream_query_result.cpp b/src/main/stream_query_result.cpp index 73ab07c39d4..868f5d9f630 100644 --- a/src/main/stream_query_result.cpp +++ b/src/main/stream_query_result.cpp @@ -16,6 +16,9 @@ StreamQueryResult::StreamQueryResult(StatementType statement_type, StatementProp context = buffered_data->GetContext(); } +StreamQueryResult::StreamQueryResult(ErrorData error) : QueryResult(QueryResultType::STREAM_RESULT, std::move(error)) { +} + StreamQueryResult::~StreamQueryResult() { } diff --git a/src/optimizer/CMakeLists.txt b/src/optimizer/CMakeLists.txt index bcdcb90d13f..1c036de74d1 100644 --- a/src/optimizer/CMakeLists.txt +++ b/src/optimizer/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory(statistics) add_library_unity( duckdb_optimizer OBJECT + build_probe_side_optimizer.cpp column_binding_replacer.cpp column_lifetime_analyzer.cpp common_aggregate_optimizer.cpp @@ -26,6 +27,7 @@ add_library_unity( remove_duplicate_groups.cpp remove_unused_columns.cpp statistics_propagator.cpp + limit_pushdown.cpp topn_optimizer.cpp unnest_rewriter.cpp) set(ALL_OBJECT_FILES diff --git a/src/optimizer/build_probe_side_optimizer.cpp b/src/optimizer/build_probe_side_optimizer.cpp new file mode 100644 index 00000000000..715b4a646c7 --- /dev/null +++ b/src/optimizer/build_probe_side_optimizer.cpp @@ -0,0 +1,151 @@ +#include "duckdb/optimizer/build_probe_side_optimizer.hpp" +#include "duckdb/planner/operator/logical_join.hpp" +#include "duckdb/execution/physical_plan_generator.hpp" +#include "duckdb/planner/operator/logical_any_join.hpp" +#include "duckdb/planner/operator/logical_get.hpp" +#include "duckdb/planner/operator/logical_comparison_join.hpp" +#include "duckdb/common/enums/join_type.hpp" + +namespace duckdb { + +static void GetRowidBindings(LogicalOperator &op, vector &bindings) { + if (op.type == LogicalOperatorType::LOGICAL_GET) { + auto &get = op.Cast(); + auto get_bindings = get.GetColumnBindings(); + auto column_ids = get.column_ids; + if (std::find(column_ids.begin(), column_ids.end(), DConstants::INVALID_INDEX) != column_ids.end()) { + for (auto &binding : get_bindings) { + bindings.push_back(binding); + } + } + } + for (auto &child : op.children) { + GetRowidBindings(*child, bindings); + } +} + +BuildProbeSideOptimizer::BuildProbeSideOptimizer(ClientContext &context, LogicalOperator &op) : context(context) { + vector updating_columns, current_op_bindings; + auto bindings = op.GetColumnBindings(); + vector row_id_bindings; + // If any column bindings are a row_id, there is a good chance the statement is an insert/delete/update statement. + // As an initialization step, we travers the plan and find which bindings are row_id bindings. + // When we eventually do our build side probe side optimizations, if we get to a join where the left and right + // cardinalities are the same, we prefer to have the child with the rowid bindings in the probe side. + GetRowidBindings(op, preferred_on_probe_side); +} + +static void FlipChildren(LogicalOperator &op) { + std::swap(op.children[0], op.children[1]); + if (op.type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN || op.type == LogicalOperatorType::LOGICAL_DELIM_JOIN) { + auto &join = op.Cast(); + join.join_type = InverseJoinType(join.join_type); + for (auto &cond : join.conditions) { + std::swap(cond.left, cond.right); + cond.comparison = FlipComparisonExpression(cond.comparison); + } + std::swap(join.left_projection_map, join.right_projection_map); + } + if (op.type == LogicalOperatorType::LOGICAL_ANY_JOIN) { + auto &join = op.Cast(); + join.join_type = InverseJoinType(join.join_type); + std::swap(join.left_projection_map, join.right_projection_map); + } +} + +static inline idx_t ComputeOverlappingBindings(const vector &haystack, + const vector &needles) { + idx_t result = 0; + for (auto &needle : needles) { + if (std::find(haystack.begin(), haystack.end(), needle) != haystack.end()) { + result++; + } + } + return result; +} + +void BuildProbeSideOptimizer::TryFlipJoinChildren(LogicalOperator &op, idx_t cardinality_ratio) { + auto &left_child = op.children[0]; + auto &right_child = op.children[1]; + auto lhs_cardinality = left_child->has_estimated_cardinality ? left_child->estimated_cardinality + : left_child->EstimateCardinality(context); + auto rhs_cardinality = right_child->has_estimated_cardinality ? right_child->estimated_cardinality + : right_child->EstimateCardinality(context); + + if (rhs_cardinality < lhs_cardinality * cardinality_ratio) { + return; + } + if (rhs_cardinality == lhs_cardinality * cardinality_ratio && !preferred_on_probe_side.empty()) { + // inspect final bindings, we prefer them on the probe side + auto bindings_left = left_child->GetColumnBindings(); + auto bindings_right = right_child->GetColumnBindings(); + auto bindings_in_left = ComputeOverlappingBindings(bindings_left, preferred_on_probe_side); + auto bindings_in_right = ComputeOverlappingBindings(bindings_right, preferred_on_probe_side); + if (bindings_in_right > bindings_in_left) { + FlipChildren(op); + } + return; + } + FlipChildren(op); +} + +void BuildProbeSideOptimizer::VisitOperator(LogicalOperator &op) { + switch (op.type) { + case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: { + auto &join = op.Cast(); + + switch (join.join_type) { + case JoinType::INNER: + case JoinType::OUTER: + TryFlipJoinChildren(join); + break; + case JoinType::LEFT: + case JoinType::RIGHT: + if (join.right_projection_map.empty()) { + TryFlipJoinChildren(join, 2); + } + break; + case JoinType::SEMI: + case JoinType::ANTI: { + idx_t has_range = 0; + if (!PhysicalPlanGenerator::HasEquality(join.conditions, has_range)) { + // if the conditions have no equality, do not flip the children. + // There is no physical join operator (yet) that can do a right_semi/anti join. + break; + } + TryFlipJoinChildren(join, 2); + break; + } + default: + break; + } + break; + } + case LogicalOperatorType::LOGICAL_CROSS_PRODUCT: { + TryFlipJoinChildren(op, 1); + break; + } + case LogicalOperatorType::LOGICAL_ANY_JOIN: { + auto &join = op.Cast(); + if (join.join_type == JoinType::LEFT && join.right_projection_map.empty()) { + TryFlipJoinChildren(join, 2); + } else if (join.join_type == JoinType::INNER) { + TryFlipJoinChildren(join, 1); + } + break; + } + case LogicalOperatorType::LOGICAL_DELIM_JOIN: { + auto &join = op.Cast(); + if (HasInverseJoinType(join.join_type) && join.right_projection_map.empty()) { + FlipChildren(join); + join.delim_flipped = true; + } + break; + } + default: + break; + } + VisitOperatorChildren(op); +} + +} // namespace duckdb diff --git a/src/optimizer/column_lifetime_analyzer.cpp b/src/optimizer/column_lifetime_analyzer.cpp index 7a934546d05..1f514e028c9 100644 --- a/src/optimizer/column_lifetime_analyzer.cpp +++ b/src/optimizer/column_lifetime_analyzer.cpp @@ -2,7 +2,9 @@ #include "duckdb/planner/expression/bound_columnref_expression.hpp" #include "duckdb/planner/operator/logical_comparison_join.hpp" +#include "duckdb/planner/operator/logical_order.hpp" #include "duckdb/planner/operator/logical_filter.hpp" +#include "duckdb/planner/expression_iterator.hpp" namespace duckdb { @@ -46,6 +48,14 @@ void ColumnLifetimeAnalyzer::StandardVisitOperator(LogicalOperator &op) { LogicalOperatorVisitor::VisitOperatorChildren(op); } +void ExtractColumnBindings(Expression &expr, vector &bindings) { + if (expr.type == ExpressionType::BOUND_COLUMN_REF) { + auto &bound_ref = expr.Cast(); + bindings.push_back(bound_ref.binding); + } + ExpressionIterator::EnumerateChildren(expr, [&](Expression &expr) { ExtractColumnBindings(expr, bindings); }); +} + void ColumnLifetimeAnalyzer::VisitOperator(LogicalOperator &op) { switch (op.type) { case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY: { @@ -63,10 +73,6 @@ void ColumnLifetimeAnalyzer::VisitOperator(LogicalOperator &op) { break; } auto &comp_join = op.Cast(); - if (comp_join.join_type == JoinType::MARK || comp_join.join_type == JoinType::SEMI || - comp_join.join_type == JoinType::ANTI) { - break; - } // FIXME for now, we only push into the projection map for equality (hash) joins // FIXME: add projection to LHS as well bool has_equality = false; @@ -83,7 +89,7 @@ void ColumnLifetimeAnalyzer::VisitOperator(LogicalOperator &op) { LogicalOperatorVisitor::VisitOperatorExpressions(op); column_binding_set_t unused_bindings; - auto old_op_bindings = op.GetColumnBindings(); + auto old_bindings = op.GetColumnBindings(); ExtractUnusedColumnBindings(op.children[1]->GetColumnBindings(), unused_bindings); // now recurse into the filter and its children @@ -91,6 +97,7 @@ void ColumnLifetimeAnalyzer::VisitOperator(LogicalOperator &op) { // then generate the projection map GenerateProjectionMap(op.children[1]->GetColumnBindings(), unused_bindings, comp_join.right_projection_map); + auto new_bindings = op.GetColumnBindings(); return; } case LogicalOperatorType::LOGICAL_UNION: @@ -112,6 +119,20 @@ void ColumnLifetimeAnalyzer::VisitOperator(LogicalOperator &op) { return; } case LogicalOperatorType::LOGICAL_ORDER_BY: + if (!everything_referenced) { + auto &order = op.Cast(); + + column_binding_set_t unused_bindings; + ExtractUnusedColumnBindings(op.children[0]->GetColumnBindings(), unused_bindings); + + // now recurse into the order and its children + LogicalOperatorVisitor::VisitOperatorExpressions(op); + LogicalOperatorVisitor::VisitOperatorChildren(op); + + // then generate the projection map + GenerateProjectionMap(op.children[0]->GetColumnBindings(), unused_bindings, order.projections); + return; + } // order by, for now reference all columns // FIXME: for ORDER BY we remove columns below an ORDER BY, we just need to make sure that the projections are // updated diff --git a/src/optimizer/filter_combiner.cpp b/src/optimizer/filter_combiner.cpp index 97cabfba613..a9563713fe9 100644 --- a/src/optimizer/filter_combiner.cpp +++ b/src/optimizer/filter_combiner.cpp @@ -569,6 +569,16 @@ TableFilterSet FilterCombiner::GenerateTableScanFilters(vector &column_id auto &fst_const_value_expr = func.children[1]->Cast(); auto &type = fst_const_value_expr.value.type(); + if ((type.IsNumeric() || type.id() == LogicalTypeId::VARCHAR || type.id() == LogicalTypeId::BOOLEAN) && + func.children.size() == 2) { + auto bound_eq_comparison = + make_uniq(ExpressionType::COMPARE_EQUAL, fst_const_value_expr.value); + table_filters.PushFilter(column_index, std::move(bound_eq_comparison)); + table_filters.PushFilter(column_index, make_uniq()); + remaining_filters.erase_at(rem_fil_idx); + continue; + } + //! Check if values are consecutive, if yes transform them to >= <= (only for integers) // e.g. if we have x IN (1, 2, 3, 4, 5) we transform this into x >= 1 AND x <= 5 if (!type.IsIntegral()) { diff --git a/src/optimizer/filter_pullup.cpp b/src/optimizer/filter_pullup.cpp index 04986f19957..e7be6de95d8 100644 --- a/src/optimizer/filter_pullup.cpp +++ b/src/optimizer/filter_pullup.cpp @@ -38,7 +38,12 @@ unique_ptr FilterPullup::PullupJoin(unique_ptr switch (join.join_type) { case JoinType::INNER: - return PullupInnerJoin(std::move(op)); + if (op->type == LogicalOperatorType::LOGICAL_ASOF_JOIN) { + // We can only move filters through the left side of AsOf joins. + return PullupFromLeft(std::move(op)); + } else { + return PullupInnerJoin(std::move(op)); + } case JoinType::LEFT: case JoinType::ANTI: case JoinType::SEMI: { diff --git a/src/optimizer/filter_pushdown.cpp b/src/optimizer/filter_pushdown.cpp index 856b031f195..274c4114def 100644 --- a/src/optimizer/filter_pushdown.cpp +++ b/src/optimizer/filter_pushdown.cpp @@ -3,6 +3,7 @@ #include "duckdb/optimizer/filter_combiner.hpp" #include "duckdb/planner/operator/logical_filter.hpp" #include "duckdb/planner/operator/logical_join.hpp" +#include "duckdb/planner/operator/logical_window.hpp" #include "duckdb/optimizer/optimizer.hpp" namespace duckdb { @@ -44,6 +45,8 @@ unique_ptr FilterPushdown::Rewrite(unique_ptr return PushdownGet(std::move(op)); case LogicalOperatorType::LOGICAL_LIMIT: return PushdownLimit(std::move(op)); + case LogicalOperatorType::LOGICAL_WINDOW: + return PushdownWindow(std::move(op)); default: return FinishPushdown(std::move(op)); } diff --git a/src/optimizer/join_order/CMakeLists.txt b/src/optimizer/join_order/CMakeLists.txt index 1b72ae546e4..8b6469c44ef 100644 --- a/src/optimizer/join_order/CMakeLists.txt +++ b/src/optimizer/join_order/CMakeLists.txt @@ -4,7 +4,6 @@ add_library_unity( query_graph.cpp join_relation_set.cpp join_node.cpp - estimated_properties.cpp join_order_optimizer.cpp cardinality_estimator.cpp cost_model.cpp diff --git a/src/optimizer/join_order/cardinality_estimator.cpp b/src/optimizer/join_order/cardinality_estimator.cpp index 4745b00addd..b2767786199 100644 --- a/src/optimizer/join_order/cardinality_estimator.cpp +++ b/src/optimizer/join_order/cardinality_estimator.cpp @@ -1,9 +1,7 @@ #include "duckdb/function/table/table_scan.hpp" #include "duckdb/optimizer/join_order/join_node.hpp" -#include "duckdb/optimizer/join_order/join_order_optimizer.hpp" -#include "duckdb/planner/filter/conjunction_filter.hpp" #include "duckdb/planner/operator/logical_comparison_join.hpp" -#include "duckdb/planner/operator/logical_get.hpp" +#include "duckdb/optimizer/join_order/query_graph_manager.hpp" #include "duckdb/storage/data_table.hpp" #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" #include "duckdb/common/printer.hpp" @@ -37,7 +35,7 @@ void CardinalityEstimator::AddRelationTdom(FilterInfo &filter_info) { relations_to_tdoms.emplace_back(new_r2tdom); } -bool CardinalityEstimator::SingleRelationFilter(FilterInfo &filter_info) { +bool CardinalityEstimator::SingleColumnFilter(duckdb::FilterInfo &filter_info) { if (filter_info.left_set && filter_info.right_set && filter_info.set.count > 1) { // Both set and are from different relations return false; @@ -48,7 +46,7 @@ bool CardinalityEstimator::SingleRelationFilter(FilterInfo &filter_info) { return true; } -vector CardinalityEstimator::DetermineMatchingEquivalentSets(FilterInfo *filter_info) { +vector CardinalityEstimator::DetermineMatchingEquivalentSets(optional_ptr filter_info) { vector matching_equivalent_sets; idx_t equivalent_relation_index = 0; @@ -66,7 +64,8 @@ vector CardinalityEstimator::DetermineMatchingEquivalentSets(FilterInfo * return matching_equivalent_sets; } -void CardinalityEstimator::AddToEquivalenceSets(FilterInfo *filter_info, vector matching_equivalent_sets) { +void CardinalityEstimator::AddToEquivalenceSets(optional_ptr filter_info, + vector matching_equivalent_sets) { D_ASSERT(matching_equivalent_sets.size() <= 2); if (matching_equivalent_sets.size() > 1) { // an equivalence relation is connecting two sets of equivalence relations @@ -100,8 +99,8 @@ void CardinalityEstimator::InitEquivalentRelations(const vector::iterator subgraph, - vector::iterator end) { - for (; subgraph != end; subgraph++) { - if (subgraph->relations.count(find_me) >= 1) { - for (auto &relation : subgraph->relations) { - merge_to.relations.insert(relation); +bool EdgeConnects(FilterInfoWithTotalDomains &edge, Subgraph2Denominator &subgraph) { + if (edge.filter_info->left_set) { + if (JoinRelationSet::IsSubset(*subgraph.relations, *edge.filter_info->left_set)) { + // cool + return true; + } + } + if (edge.filter_info->right_set) { + if (JoinRelationSet::IsSubset(*subgraph.relations, *edge.filter_info->right_set)) { + return true; + } + } + return false; +} + +vector GetEdges(vector &relations_to_tdom, + JoinRelationSet &requested_set) { + vector res; + for (auto &relation_2_tdom : relations_to_tdom) { + for (auto &filter : relation_2_tdom.filters) { + if (JoinRelationSet::IsSubset(requested_set, filter->set)) { + FilterInfoWithTotalDomains new_edge(filter, relation_2_tdom); + res.push_back(new_edge); } - subgraph->relations.clear(); - merge_to.denom *= subgraph->denom; - return; } } + return res; } -template <> -double CardinalityEstimator::EstimateCardinalityWithSet(JoinRelationSet &new_set) { +vector SubgraphsConnectedByEdge(FilterInfoWithTotalDomains &edge, vector &subgraphs) { + vector res; + if (subgraphs.empty()) { + return res; + } else { + // check the combinations of subgraphs and see if the edge connects two of them, + // if so, return the indexes of the two subgraphs within the vector + for (idx_t outer = 0; outer != subgraphs.size(); outer++) { + // check if the edge connects two subgraphs. + for (idx_t inner = outer + 1; inner != subgraphs.size(); inner++) { + if (EdgeConnects(edge, subgraphs.at(outer)) && EdgeConnects(edge, subgraphs.at(inner))) { + // order is important because we will delete the inner subgraph later + res.push_back(outer); + res.push_back(inner); + return res; + } + } + // if the edge does not connect two subgraphs, see if the edge connects with just outer + // merge subgraph.at(outer) with the RelationSet(s) that edge connects + if (EdgeConnects(edge, subgraphs.at(outer))) { + res.push_back(outer); + return res; + } + } + } + // this edge connects only the relations it connects. Return an empty result so a new subgraph is created. + return res; +} - if (relation_set_2_cardinality.find(new_set.ToString()) != relation_set_2_cardinality.end()) { - return relation_set_2_cardinality[new_set.ToString()].cardinality_before_filters; +JoinRelationSet &CardinalityEstimator::UpdateNumeratorRelations(Subgraph2Denominator left, Subgraph2Denominator right, + FilterInfoWithTotalDomains &filter) { + switch (filter.filter_info->join_type) { + case JoinType::SEMI: + case JoinType::ANTI: { + if (JoinRelationSet::IsSubset(*left.relations, *filter.filter_info->left_set) && + JoinRelationSet::IsSubset(*right.relations, *filter.filter_info->right_set)) { + return *left.numerator_relations; + } + return *right.numerator_relations; } - double numerator = 1; - unordered_set actual_set; + default: + // cross product or inner join + return set_manager.Union(*left.numerator_relations, *right.numerator_relations); + } +} - for (idx_t i = 0; i < new_set.count; i++) { - auto &single_node_set = set_manager.GetJoinRelation(new_set.relations[i]); - auto card_helper = relation_set_2_cardinality[single_node_set.ToString()]; - numerator *= card_helper.cardinality_before_filters == 0 ? 1 : card_helper.cardinality_before_filters; - actual_set.insert(new_set.relations[i]); +double CardinalityEstimator::CalculateUpdatedDenom(Subgraph2Denominator left, Subgraph2Denominator right, + FilterInfoWithTotalDomains &filter) { + double new_denom = left.denom * right.denom; + switch (filter.filter_info->join_type) { + case JoinType::INNER: { + new_denom *= filter.has_tdom_hll ? (double)filter.tdom_hll : (double)filter.tdom_no_hll; + return new_denom; } + case JoinType::SEMI: + case JoinType::ANTI: { + if (JoinRelationSet::IsSubset(*left.relations, *filter.filter_info->left_set) && + JoinRelationSet::IsSubset(*right.relations, *filter.filter_info->right_set)) { + new_denom = left.denom * CardinalityEstimator::DEFAULT_SEMI_ANTI_SELECTIVITY; + return new_denom; + } + new_denom = right.denom * CardinalityEstimator::DEFAULT_SEMI_ANTI_SELECTIVITY; + return new_denom; + } + default: + // cross product + return new_denom; + } +} +DenomInfo CardinalityEstimator::GetDenominator(JoinRelationSet &set) { vector subgraphs; - bool done = false; - bool found_match = false; // Finding the denominator is tricky. You need to go through the tdoms in decreasing order // Then loop through all filters in the equivalence set of the tdom to see if both the @@ -170,87 +242,104 @@ double CardinalityEstimator::EstimateCardinalityWithSet(JoinRelationSet &new_set // TODO: Implement a method to cache subgraphs so you don't have to build them up every // time the cardinality of a new set is requested - // relations_to_tdoms has already been sorted. - for (auto &relation_2_tdom : relations_to_tdoms) { - // loop through each filter in the tdom. - if (done) { - break; - } - for (auto &filter : relation_2_tdom.filters) { - if (actual_set.count(filter->left_binding.table_index) == 0 || - actual_set.count(filter->right_binding.table_index) == 0) { - continue; + // relations_to_tdoms has already been sorted by largest to smallest total domain + // then we look through the filters for the relations_to_tdoms, + // and we start to choose the filters that join relations in the set. + + // edges are guaranteed to be in order of largest tdom to smallest tdom. + auto edges = GetEdges(relations_to_tdoms, set); + for (auto &edge : edges) { + auto subgraph_connections = SubgraphsConnectedByEdge(edge, subgraphs); + + if (subgraph_connections.empty()) { + // create a subgraph out of left and right, then merge right into left and add left to subgraphs. + // this helps cover a case where there are no subgraphs yet, and the only join filter is a SEMI JOIN + auto left_subgraph = Subgraph2Denominator(); + auto right_subgraph = Subgraph2Denominator(); + left_subgraph.relations = edge.filter_info->left_set; + left_subgraph.numerator_relations = edge.filter_info->left_set; + right_subgraph.relations = edge.filter_info->right_set; + right_subgraph.numerator_relations = edge.filter_info->right_set; + + left_subgraph.numerator_relations = &UpdateNumeratorRelations(left_subgraph, right_subgraph, edge); + left_subgraph.relations = &edge.filter_info->set; + left_subgraph.denom = CalculateUpdatedDenom(left_subgraph, right_subgraph, edge); + subgraphs.push_back(left_subgraph); + } else if (subgraph_connections.size() == 1) { + auto left_subgraph = &subgraphs.at(subgraph_connections.at(0)); + auto right_subgraph = Subgraph2Denominator(); + right_subgraph.relations = edge.filter_info->right_set; + right_subgraph.numerator_relations = edge.filter_info->right_set; + if (JoinRelationSet::IsSubset(*left_subgraph->relations, *right_subgraph.relations)) { + right_subgraph.relations = edge.filter_info->left_set; + right_subgraph.numerator_relations = edge.filter_info->left_set; } - // the join filter is on relations in the new set. - found_match = false; - vector::iterator it; - for (it = subgraphs.begin(); it != subgraphs.end(); it++) { - auto left_in = it->relations.count(filter->left_binding.table_index); - auto right_in = it->relations.count(filter->right_binding.table_index); - if (left_in && right_in) { - // if both left and right bindings are in the subgraph, continue. - // This means another filter is connecting relations already in the - // subgraph it, but it has a tdom that is less, and we don't care. - found_match = true; - continue; - } - if (!left_in && !right_in) { - // if both left and right bindings are *not* in the subgraph, continue - // without finding a match. This will trigger the process to add a new - // subgraph - continue; - } - idx_t find_table; - if (left_in) { - find_table = filter->right_binding.table_index; - } else { - D_ASSERT(right_in); - find_table = filter->left_binding.table_index; - } - auto next_subgraph = it + 1; - // iterate through other subgraphs and merge. - FindSubgraphMatchAndMerge(*it, find_table, next_subgraph, subgraphs.end()); - // Now insert the right binding and update denominator with the - // tdom of the filter - it->relations.insert(find_table); - UpdateDenom(*it, relation_2_tdom); - found_match = true; - break; - } - // means that the filter joins relations in the given set, but there is no - // connection to any subgraph in subgraphs. Add a new subgraph, and maybe later there will be - // a connection. - if (!found_match) { - subgraphs.emplace_back(); - auto &subgraph = subgraphs.back(); - subgraph.relations.insert(filter->left_binding.table_index); - subgraph.relations.insert(filter->right_binding.table_index); - UpdateDenom(subgraph, relation_2_tdom); + + if (JoinRelationSet::IsSubset(*left_subgraph->relations, *edge.filter_info->left_set) && + JoinRelationSet::IsSubset(*left_subgraph->relations, *edge.filter_info->right_set)) { + // here we have an edge that connects the same subgraph to the same subgraph. Just continue. no need to + // update the denom + continue; } + left_subgraph->numerator_relations = &UpdateNumeratorRelations(*left_subgraph, right_subgraph, edge); + left_subgraph->relations = &set_manager.Union(*left_subgraph->relations, *right_subgraph.relations); + left_subgraph->denom = CalculateUpdatedDenom(*left_subgraph, right_subgraph, edge); + } else if (subgraph_connections.size() == 2) { + // The two subgraphs in the subgraph_connections can be merged by this edge. + D_ASSERT(subgraph_connections.at(0) < subgraph_connections.at(1)); + auto subgraph_to_merge_into = &subgraphs.at(subgraph_connections.at(0)); + auto subgraph_to_delete = &subgraphs.at(subgraph_connections.at(1)); + subgraph_to_merge_into->relations = + &set_manager.Union(*subgraph_to_merge_into->relations, *subgraph_to_delete->relations); + subgraph_to_merge_into->numerator_relations = + &UpdateNumeratorRelations(*subgraph_to_merge_into, *subgraph_to_delete, edge); + subgraph_to_delete->relations = nullptr; + subgraph_to_merge_into->denom = CalculateUpdatedDenom(*subgraph_to_merge_into, *subgraph_to_delete, edge); auto remove_start = std::remove_if(subgraphs.begin(), subgraphs.end(), - [](Subgraph2Denominator &s) { return s.relations.empty(); }); + [](Subgraph2Denominator &s) { return !s.relations; }); subgraphs.erase(remove_start, subgraphs.end()); + } + if (subgraphs.size() == 1 && subgraphs.at(0).relations->ToString() == set.ToString()) { + // the first subgraph has connected all the desired relations, no need to iterate + // through the rest of the edges. + break; + } + } - if (subgraphs.size() == 1 && subgraphs.at(0).relations.size() == new_set.count) { - // You have found enough filters to connect the relations. These are guaranteed - // to be the filters with the highest Tdoms. - done = true; - break; - } + // It's possible cross-products were added and are not present in the filters in the relation_2_tdom + // structures. When that's the case, merge all remaining subgraphs. + if (subgraphs.size() > 1) { + auto final_subgraph = subgraphs.at(0); + for (auto merge_with = subgraphs.begin() + 1; merge_with != subgraphs.end(); merge_with++) { + D_ASSERT(final_subgraph.relations && merge_with->relations); + final_subgraph.relations = &set_manager.Union(*final_subgraph.relations, *merge_with->relations); + D_ASSERT(final_subgraph.numerator_relations && merge_with->numerator_relations); + final_subgraph.numerator_relations = + &set_manager.Union(*final_subgraph.numerator_relations, *merge_with->numerator_relations); + final_subgraph.denom *= merge_with->denom; } } - double denom = 1; - // TODO: It's possible cross-products were added and are not present in the filters in the relation_2_tdom - // structures. When that's the case, multiply the denom structures that have no intersection - for (auto &match : subgraphs) { - denom *= match.denom; + // can happen if a table has cardinality 0, a tdom is set to 0, or if a cross product is used. + if (subgraphs.empty() || subgraphs.at(0).denom == 0) { + // denominator is 1 and numerators are a cross product of cardinalities. + return DenomInfo(set, 1, 1); } - // can happen if a table has cardinality 0, or a tdom is set to 0 - if (denom <= 1) { - denom = 1; + return DenomInfo(*subgraphs.at(0).numerator_relations, 1, subgraphs.at(0).denom); +} + +template <> +double CardinalityEstimator::EstimateCardinalityWithSet(JoinRelationSet &new_set) { + + if (relation_set_2_cardinality.find(new_set.ToString()) != relation_set_2_cardinality.end()) { + return relation_set_2_cardinality[new_set.ToString()].cardinality_before_filters; } - auto result = numerator / denom; - auto new_entry = CardinalityHelper((double)result, 1); + + // can happen if a table has cardinality 0, or a tdom is set to 0 + auto denom = GetDenominator(new_set); + auto numerator = GetNumerator(denom.numerator_relations); + + double result = numerator / denom.denominator; + auto new_entry = CardinalityHelper(result); relation_set_2_cardinality[new_set.ToString()] = new_entry; return result; } @@ -259,7 +348,7 @@ template <> idx_t CardinalityEstimator::EstimateCardinalityWithSet(JoinRelationSet &new_set) { auto cardinality_as_double = EstimateCardinalityWithSet(new_set); auto max = NumericLimits::Maximum(); - if (cardinality_as_double >= max) { + if (cardinality_as_double >= (double)max) { return max; } return (idx_t)cardinality_as_double; @@ -282,9 +371,8 @@ void CardinalityEstimator::InitCardinalityEstimatorProps(optional_ptrToString()] = card_helper; UpdateTotalDomains(set, stats); diff --git a/src/optimizer/join_order/estimated_properties.cpp b/src/optimizer/join_order/estimated_properties.cpp deleted file mode 100644 index 9e907331abc..00000000000 --- a/src/optimizer/join_order/estimated_properties.cpp +++ /dev/null @@ -1,36 +0,0 @@ - -#include "duckdb/optimizer/join_order/estimated_properties.hpp" - -namespace duckdb { - -template <> -double EstimatedProperties::GetCardinality() const { - return cardinality; -} - -template <> -idx_t EstimatedProperties::GetCardinality() const { - auto max_idx_t = NumericLimits::Maximum() - 10000; - return MinValue(NumericCast(cardinality), max_idx_t); -} - -template <> -double EstimatedProperties::GetCost() const { - return cost; -} - -template <> -idx_t EstimatedProperties::GetCost() const { - auto max_idx_t = NumericLimits::Maximum() - 10000; - return MinValue(NumericCast(cost), max_idx_t); -} - -void EstimatedProperties::SetCardinality(double new_card) { - cardinality = new_card; -} - -void EstimatedProperties::SetCost(double new_cost) { - cost = new_cost; -} - -} // namespace duckdb diff --git a/src/optimizer/join_order/join_node.cpp b/src/optimizer/join_order/join_node.cpp index f4958563e4c..031f56ce26a 100644 --- a/src/optimizer/join_order/join_node.cpp +++ b/src/optimizer/join_order/join_node.cpp @@ -6,38 +6,6 @@ namespace duckdb { -JoinNode::JoinNode(JoinRelationSet &set) : set(set) { -} - -JoinNode::JoinNode(JoinRelationSet &set, optional_ptr info, unique_ptr left, - unique_ptr right, double cost) - : set(set), info(info), left(std::move(left)), right(std::move(right)), cost(cost) { -} - -unique_ptr EstimatedProperties::Copy() { - auto result = make_uniq(cardinality, cost); - return result; -} - -string JoinNode::ToString() { - string result = "-------------------------------\n"; - result += set.ToString() + "\n"; - result += "cost = " + to_string(cost) + "\n"; - result += "left = \n"; - if (left) { - result += left->ToString(); - } - result += "right = \n"; - if (right) { - result += right->ToString(); - } - return result; -} - -void JoinNode::Print() { - Printer::Print(ToString()); -} - DPJoinNode::DPJoinNode(JoinRelationSet &set) : set(set), info(nullptr), is_leaf(true), left_set(set), right_set(set) { } diff --git a/src/optimizer/join_order/join_order_optimizer.cpp b/src/optimizer/join_order/join_order_optimizer.cpp index cafc47a8022..516acd751be 100644 --- a/src/optimizer/join_order/join_order_optimizer.cpp +++ b/src/optimizer/join_order/join_order_optimizer.cpp @@ -5,23 +5,10 @@ #include "duckdb/common/limits.hpp" #include "duckdb/common/pair.hpp" #include "duckdb/planner/expression/list.hpp" -#include "duckdb/planner/expression_iterator.hpp" #include "duckdb/planner/operator/list.hpp" namespace duckdb { -static bool HasJoin(LogicalOperator *op) { - while (!op->children.empty()) { - if (op->children.size() == 1) { - op = op->children[0].get(); - } - if (op->children.size() == 2) { - return true; - } - } - return false; -} - unique_ptr JoinOrderOptimizer::Optimize(unique_ptr plan, optional_ptr stats) { @@ -32,7 +19,7 @@ unique_ptr JoinOrderOptimizer::Optimize(unique_ptr new_logical_plan = nullptr; @@ -46,12 +33,11 @@ unique_ptr JoinOrderOptimizer::Optimize(unique_ptr JoinOrderOptimizer::Optimize(unique_ptrEstimateCardinality(context); diff --git a/src/optimizer/join_order/join_relation_set.cpp b/src/optimizer/join_order/join_relation_set.cpp index d08ac4c89bb..aa5767427ae 100644 --- a/src/optimizer/join_order/join_relation_set.cpp +++ b/src/optimizer/join_order/join_relation_set.cpp @@ -99,11 +99,15 @@ JoinRelationSet &JoinRelationSetManager::Union(JoinRelationSet &left, JoinRelati // left is smaller, progress left and add it to the set relations[count++] = left.relations[i]; i++; - } else { - D_ASSERT(left.relations[i] > right.relations[j]); + } else if (left.relations[i] > right.relations[j]) { // right is smaller, progress right and add it to the set relations[count++] = right.relations[j]; j++; + } else { + D_ASSERT(left.relations[i] == right.relations[j]); + relations[count++] = left.relations[i]; + i++; + j++; } } return GetJoinRelation(std::move(relations), count); diff --git a/src/optimizer/join_order/plan_enumerator.cpp b/src/optimizer/join_order/plan_enumerator.cpp index 83b5a584e62..a5e618fc677 100644 --- a/src/optimizer/join_order/plan_enumerator.cpp +++ b/src/optimizer/join_order/plan_enumerator.cpp @@ -91,22 +91,8 @@ void PlanEnumerator::GenerateCrossProducts() { // query_graph = query_graph_manager.GetQueryGraph(); } -unique_ptr PlanEnumerator::CreateJoinNodeFromDPJoinNode(DPJoinNode dp_node) { - if (dp_node.is_leaf) { - auto res = make_uniq(dp_node.set); - res->cardinality = dp_node.cardinality; - return res; - } else { - auto left_dp_join_node = plans.find(dp_node.left_set); - auto right_dp_join_node = plans.find(dp_node.right_set); - D_ASSERT(left_dp_join_node->second); - D_ASSERT(right_dp_join_node->second); - auto left = CreateJoinNodeFromDPJoinNode(*left_dp_join_node->second); - auto right = CreateJoinNodeFromDPJoinNode(*right_dp_join_node->second); - auto res = make_uniq(dp_node.set, dp_node.info, std::move(left), std::move(right), dp_node.cost); - res->cardinality = dp_node.cardinality; - return res; - } +const reference_map_t> &PlanEnumerator::GetPlans() const { + return plans; } //! Create a new JoinTree node by joining together two previous JoinTree nodes @@ -118,20 +104,32 @@ unique_ptr PlanEnumerator::CreateJoinTree(JoinRelationSet &set, // FIXME: we should probably actually benchmark that as well // FIXME: should consider different join algorithms, should we pick a join algorithm here as well? (probably) optional_ptr best_connection = nullptr; - - // cross products are techincally still connections, but the filter expression is a null_ptr + // cross products are technically still connections, but the filter expression is a null_ptr if (!possible_connections.empty()) { best_connection = &possible_connections.back().get(); } + auto join_type = JoinType::INVALID; + for (auto &filter_binding : best_connection->filters) { + if (!filter_binding->left_set || !filter_binding->right_set) { + continue; + } + join_type = filter_binding->join_type; + // prefer joining on semi and anti joins as they have a higher chance of being more + // selective + if (join_type == JoinType::SEMI || join_type == JoinType::ANTI) { + break; + } + } + // need the filter info from the Neighborhood info. auto cost = cost_model.ComputeCost(left, right); auto result = make_uniq(set, best_connection, left.set, right.set, cost); result->cardinality = cost_model.cardinality_estimator.EstimateCardinalityWithSet(set); return result; } -unique_ptr PlanEnumerator::EmitPair(JoinRelationSet &left, JoinRelationSet &right, - const vector> &info) { +DPJoinNode &PlanEnumerator::EmitPair(JoinRelationSet &left, JoinRelationSet &right, + const vector> &info) { // get the left and right join plans auto left_plan = plans.find(left); auto right_plan = plans.find(right); @@ -151,10 +149,10 @@ unique_ptr PlanEnumerator::EmitPair(JoinRelationSet &left, JoinRelatio if (entry == plans.end() || new_cost < old_cost) { // the new plan costs less than the old plan. Update our DP table. plans[new_set] = std::move(new_plan); - return CreateJoinNodeFromDPJoinNode(*plans[new_set]); + return *plans[new_set]; } // Create join node from the plan currently in the DP table. - return CreateJoinNodeFromDPJoinNode(*entry->second); + return *entry->second; } bool PlanEnumerator::TryEmitPair(JoinRelationSet &left, JoinRelationSet &right, @@ -342,8 +340,10 @@ void PlanEnumerator::SolveJoinOrderApproximately() { // now in every step of the algorithm, we greedily pick the join between the to-be-joined relations that has the // smallest cost. This is O(r^2) per step, and every step will reduce the total amount of relations to-be-joined // by 1, so the total cost is O(r^3) in the amount of relations + // long is needed to prevent clang-tidy complaints. (idx_t) cannot be added to an iterator position because it + // is unsigned. idx_t best_left = 0, best_right = 0; - unique_ptr best_connection; + optional_ptr best_connection; for (idx_t i = 0; i < join_relations.size(); i++) { auto left = join_relations[i]; for (idx_t j = i + 1; j < join_relations.size(); j++) { @@ -359,9 +359,9 @@ void PlanEnumerator::SolveJoinOrderApproximately() { // error if future plans rely on the old node that was just replaced. // if node in FullPath, then updateDP tree. - if (!best_connection || node->cost < best_connection->cost) { + if (!best_connection || node.cost < best_connection->cost) { // best pair found so far - best_connection = std::move(node); + best_connection = &EmitPair(left, right, connection); best_left = i; best_right = j; } @@ -371,15 +371,15 @@ void PlanEnumerator::SolveJoinOrderApproximately() { if (!best_connection) { // could not find a connection, but we were not done with finding a completed plan // we have to add a cross product; we add it between the two smallest relations - unique_ptr smallest_plans[2]; - idx_t smallest_index[2]; + optional_ptr smallest_plans[2]; + size_t smallest_index[2]; D_ASSERT(join_relations.size() >= 2); // first just add the first two join relations. It doesn't matter the cost as the JOO // will swap them on estimated cardinality anyway. for (idx_t i = 0; i < 2; i++) { - auto current_plan = CreateJoinNodeFromDPJoinNode(*plans[join_relations[i]]); - smallest_plans[i] = std::move(current_plan); + optional_ptr current_plan = plans[join_relations[i]]; + smallest_plans[i] = current_plan; smallest_index[i] = i; } @@ -387,11 +387,11 @@ void PlanEnumerator::SolveJoinOrderApproximately() { // add them if they have lower estimated cardinality. for (idx_t i = 2; i < join_relations.size(); i++) { // get the plan for this relation - auto current_plan = CreateJoinNodeFromDPJoinNode(*plans[join_relations[i]]); + optional_ptr current_plan = plans[join_relations[i]]; // check if the cardinality is smaller than the smallest two found so far for (idx_t j = 0; j < 2; j++) { if (!smallest_plans[j] || smallest_plans[j]->cost > current_plan->cost) { - smallest_plans[j] = std::move(current_plan); + smallest_plans[j] = current_plan; smallest_index[j] = i; break; } @@ -410,7 +410,7 @@ void PlanEnumerator::SolveJoinOrderApproximately() { auto connections = query_graph.GetConnections(left, right); D_ASSERT(!connections.empty()); - best_connection = EmitPair(left, right, connections); + best_connection = &EmitPair(left, right, connections); best_left = smallest_index[0]; best_right = smallest_index[1]; @@ -424,10 +424,12 @@ void PlanEnumerator::SolveJoinOrderApproximately() { // important to erase the biggest element first // if we erase the smallest element first the index of the biggest element changes + auto &new_set = query_graph_manager.set_manager.Union(join_relations.at(best_left).get(), + join_relations.at(best_right).get()); D_ASSERT(best_right > best_left); - join_relations.erase_at(best_right); - join_relations.erase_at(best_left); - join_relations.push_back(best_connection->set); + join_relations.erase(join_relations.begin() + (int64_t)best_right); + join_relations.erase(join_relations.begin() + (int64_t)best_left); + join_relations.push_back(new_set); } } @@ -457,7 +459,7 @@ void PlanEnumerator::InitLeafPlans() { // the plan enumeration is a straight implementation of the paper "Dynamic Programming Strikes Back" by Guido // Moerkotte and Thomas Neumannn, see that paper for additional info/documentation bonus slides: // https://db.in.tum.de/teaching/ws1415/queryopt/chapter3.pdf?lang=de -unique_ptr PlanEnumerator::SolveJoinOrder() { +void PlanEnumerator::SolveJoinOrder() { bool force_no_cross_product = query_graph_manager.context.config.force_no_cross_product; // first try to solve the join order exactly if (!SolveJoinOrderExactly()) { @@ -485,7 +487,6 @@ unique_ptr PlanEnumerator::SolveJoinOrder() { //! solve the join order again, returning the final plan return SolveJoinOrder(); } - return CreateJoinNodeFromDPJoinNode(*final_plan->second); } } // namespace duckdb diff --git a/src/optimizer/join_order/query_graph_manager.cpp b/src/optimizer/join_order/query_graph_manager.cpp index 13b7807b896..446a3ad610d 100644 --- a/src/optimizer/join_order/query_graph_manager.cpp +++ b/src/optimizer/join_order/query_graph_manager.cpp @@ -2,7 +2,6 @@ #include "duckdb/common/assert.hpp" #include "duckdb/common/enums/join_type.hpp" -#include "duckdb/common/printer.hpp" #include "duckdb/common/string_util.hpp" #include "duckdb/execution/physical_plan_generator.hpp" #include "duckdb/optimizer/join_order/join_relation.hpp" @@ -22,7 +21,6 @@ static bool Disjoint(const unordered_set &a, const unordered_set &b) { } bool QueryGraphManager::Build(LogicalOperator &op) { - vector> filter_operators; // have the relation manager extract the join relations and create a reference list of all the // filter operators. auto can_reorder = relation_manager.ExtractJoinRelations(op, filter_operators); @@ -123,34 +121,94 @@ static unique_ptr ExtractJoinRelation(unique_ptr QueryGraphManager::Reconstruct(unique_ptr plan, JoinNode &node) { - return RewritePlan(std::move(plan), node); +unique_ptr QueryGraphManager::Reconstruct(unique_ptr plan) { + // now we have to rewrite the plan + bool root_is_join = plan->children.size() > 1; + + unordered_set bindings; + for (idx_t i = 0; i < relation_manager.NumRelations(); i++) { + bindings.insert(i); + } + auto &total_relation = set_manager.GetJoinRelation(bindings); + + // first we will extract all relations from the main plan + vector> extracted_relations; + extracted_relations.reserve(relation_manager.NumRelations()); + for (auto &relation : relation_manager.GetRelations()) { + extracted_relations.push_back(ExtractJoinRelation(relation)); + } + + // now we generate the actual joins + auto join_tree = GenerateJoins(extracted_relations, total_relation); + + // perform the final pushdown of remaining filters + for (auto &filter : filters_and_bindings) { + // check if the filter has already been extracted + if (filter->filter) { + // if not we need to push it + join_tree.op = PushFilter(std::move(join_tree.op), std::move(filter->filter)); + } + } + + // find the first join in the relation to know where to place this node + if (root_is_join) { + // first node is the join, return it immediately + return std::move(join_tree.op); + } + D_ASSERT(plan->children.size() == 1); + // have to move up through the relations + auto op = plan.get(); + auto parent = plan.get(); + while (op->type != LogicalOperatorType::LOGICAL_CROSS_PRODUCT && + op->type != LogicalOperatorType::LOGICAL_COMPARISON_JOIN && + op->type != LogicalOperatorType::LOGICAL_ASOF_JOIN) { + D_ASSERT(op->children.size() == 1); + parent = op; + op = op->children[0].get(); + } + // have to replace at this node + parent->children[0] = std::move(join_tree.op); + return plan; } GenerateJoinRelation QueryGraphManager::GenerateJoins(vector> &extracted_relations, - JoinNode &node) { + JoinRelationSet &set) { optional_ptr left_node; optional_ptr right_node; optional_ptr result_relation; unique_ptr result_operator; - if (node.left && node.right && node.info) { - // generate the left and right children - auto left = GenerateJoins(extracted_relations, *node.left); - auto right = GenerateJoins(extracted_relations, *node.right); - if (node.info->filters.empty()) { + auto dp_entry = plans->find(set); + if (dp_entry == plans->end()) { + throw InternalException("Join Order Optimizer Error: No full plan was created"); + } + auto &node = dp_entry->second; + if (!dp_entry->second->is_leaf) { + + // generate the left and right children + auto left = GenerateJoins(extracted_relations, node->left_set); + auto right = GenerateJoins(extracted_relations, node->right_set); + if (dp_entry->second->info->filters.empty()) { // no filters, create a cross product result_operator = LogicalCrossProduct::Create(std::move(left.op), std::move(right.op)); } else { // we have filters, create a join node - auto join = make_uniq(JoinType::INNER); + auto chosen_filter = node->info->filters.at(0); + for (idx_t i = 0; i < node->info->filters.size(); i++) { + if (node->info->filters.at(i)->join_type == JoinType::INNER) { + chosen_filter = node->info->filters.at(i); + break; + } + } + + auto join = make_uniq(chosen_filter->join_type); // Here we optimize build side probe side. Our build side is the right side // So the right plans should have lower cardinalities. join->children.push_back(std::move(left.op)); join->children.push_back(std::move(right.op)); // set the join conditions from the join node - for (auto &filter_ref : node.info->filters) { + for (auto &filter_ref : node->info->filters) { auto f = filter_ref.get(); // extract the filter from the operator it originally belonged to D_ASSERT(filters_and_bindings[f->filter_index]->filter); @@ -166,7 +224,14 @@ GenerateJoinRelation QueryGraphManager::GenerateJoins(vectorCast(); // we need to figure out which side is which by looking at the relations available to us + // left/right (build side/probe side) optimizations happen later. bool invert = !JoinRelationSet::IsSubset(*left.set, *f->left_set); + // If the left and right set are inverted AND it is a semi or anti join + // swap left and right children back. + if (invert && (f->join_type == JoinType::SEMI || f->join_type == JoinType::ANTI)) { + std::swap(left, right); + invert = false; + } cond.left = !invert ? std::move(comparison.left) : std::move(comparison.right); cond.right = !invert ? std::move(comparison.right) : std::move(comparison.left); cond.comparison = condition->type; @@ -185,23 +250,23 @@ GenerateJoinRelation QueryGraphManager::GenerateJoins(vectorset.count == 1); + D_ASSERT(extracted_relations[node->set.relations[0]]); + result_relation = &node->set; + result_operator = std::move(extracted_relations[result_relation->relations[0]]); } // TODO: this is where estimated properties start coming into play. // when creating the result operator, we should ask the cost model and cardinality estimator what // the cost and cardinality are // result_operator->estimated_props = node.estimated_props->Copy(); - result_operator->estimated_cardinality = node.cardinality; + result_operator->estimated_cardinality = node->cardinality; result_operator->has_estimated_cardinality = true; if (result_operator->type == LogicalOperatorType::LOGICAL_FILTER && result_operator->children[0]->type == LogicalOperatorType::LOGICAL_GET) { // FILTER on top of GET, add estimated properties to both // auto &filter_props = *result_operator->estimated_props; auto &child_operator = *result_operator->children[0]; - child_operator.estimated_cardinality = node.cardinality; + child_operator.estimated_cardinality = node->cardinality; child_operator.has_estimated_cardinality = true; } // check if we should do a pushdown on this node @@ -292,149 +357,4 @@ void QueryGraphManager::CreateQueryGraphCrossProduct(JoinRelationSet &left, Join query_graph.CreateEdge(right, left, nullptr); } -unique_ptr QueryGraphManager::RewritePlan(unique_ptr plan, JoinNode &node) { - // now we have to rewrite the plan - bool root_is_join = plan->children.size() > 1; - - // first we will extract all relations from the main plan - vector> extracted_relations; - extracted_relations.reserve(relation_manager.NumRelations()); - for (auto &relation : relation_manager.GetRelations()) { - extracted_relations.push_back(ExtractJoinRelation(relation)); - } - - // now we generate the actual joins - auto join_tree = GenerateJoins(extracted_relations, node); - // perform the final pushdown of remaining filters - for (auto &filter : filters_and_bindings) { - // check if the filter has already been extracted - if (filter->filter) { - // if not we need to push it - join_tree.op = PushFilter(std::move(join_tree.op), std::move(filter->filter)); - } - } - - // find the first join in the relation to know where to place this node - if (root_is_join) { - // first node is the join, return it immediately - return std::move(join_tree.op); - } - D_ASSERT(plan->children.size() == 1); - // have to move up through the relations - auto op = plan.get(); - auto parent = plan.get(); - while (op->type != LogicalOperatorType::LOGICAL_CROSS_PRODUCT && - op->type != LogicalOperatorType::LOGICAL_COMPARISON_JOIN && - op->type != LogicalOperatorType::LOGICAL_ASOF_JOIN) { - D_ASSERT(op->children.size() == 1); - parent = op; - op = op->children[0].get(); - } - // have to replace at this node - parent->children[0] = std::move(join_tree.op); - return plan; -} - -static void FlipChildren(LogicalOperator &op) { - std::swap(op.children[0], op.children[1]); - if (op.type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN || op.type == LogicalOperatorType::LOGICAL_DELIM_JOIN) { - auto &join = op.Cast(); - join.join_type = InverseJoinType(join.join_type); - for (auto &cond : join.conditions) { - std::swap(cond.left, cond.right); - cond.comparison = FlipComparisonExpression(cond.comparison); - } - } - if (op.type == LogicalOperatorType::LOGICAL_ANY_JOIN) { - auto &join = op.Cast(); - join.join_type = InverseJoinType(join.join_type); - } -} - -void QueryGraphManager::TryFlipChildren(LogicalOperator &op, idx_t cardinality_ratio) { - auto &left_child = op.children[0]; - auto &right_child = op.children[1]; - auto lhs_cardinality = left_child->has_estimated_cardinality ? left_child->estimated_cardinality - : left_child->EstimateCardinality(context); - auto rhs_cardinality = right_child->has_estimated_cardinality ? right_child->estimated_cardinality - : right_child->EstimateCardinality(context); - if (rhs_cardinality < lhs_cardinality * cardinality_ratio) { - return; - } - FlipChildren(op); -} - -unique_ptr QueryGraphManager::LeftRightOptimizations(unique_ptr input_op) { - auto op = input_op.get(); - // pass through single child operators - while (!op->children.empty()) { - if (op->children.size() == 2) { - switch (op->type) { - case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: { - auto &join = op->Cast(); - - switch (join.join_type) { - case JoinType::INNER: - case JoinType::OUTER: - TryFlipChildren(join); - break; - case JoinType::LEFT: - case JoinType::RIGHT: - if (join.right_projection_map.empty()) { - TryFlipChildren(join, 2); - } - break; - case JoinType::SEMI: - case JoinType::ANTI: { - idx_t has_range = 0; - if (!PhysicalPlanGenerator::HasEquality(join.conditions, has_range)) { - // if the conditions have no equality, do not flip the children. - // There is no physical join operator (yet) that can do a right_semi/anti join. - break; - } - TryFlipChildren(join, 2); - break; - } - default: - break; - } - break; - } - case LogicalOperatorType::LOGICAL_CROSS_PRODUCT: { - // cross product not a comparison join so JoinType::INNER will get ignored - TryFlipChildren(*op, 1); - break; - } - case LogicalOperatorType::LOGICAL_ANY_JOIN: { - auto &join = op->Cast(); - if (join.join_type == JoinType::LEFT && join.right_projection_map.empty()) { - TryFlipChildren(join, 2); - } else if (join.join_type == JoinType::INNER) { - TryFlipChildren(join, 1); - } - break; - } - case LogicalOperatorType::LOGICAL_DELIM_JOIN: { - auto &join = op->Cast(); - if (HasInverseJoinType(join.join_type) && join.right_projection_map.empty()) { - FlipChildren(join); - join.delim_flipped = true; - } - break; - } - default: - break; - } - op->children[0] = LeftRightOptimizations(std::move(op->children[0])); - op->children[1] = LeftRightOptimizations(std::move(op->children[1])); - // break from while loop - break; - } - if (op->children.size() == 1) { - op = op->children[0].get(); - } - } - return input_op; -} - } // namespace duckdb diff --git a/src/optimizer/join_order/relation_manager.cpp b/src/optimizer/join_order/relation_manager.cpp index 3df21b77e7f..29710d7c1d3 100644 --- a/src/optimizer/join_order/relation_manager.cpp +++ b/src/optimizer/join_order/relation_manager.cpp @@ -9,8 +9,6 @@ #include "duckdb/planner/expression/list.hpp" #include "duckdb/planner/operator/list.hpp" -#include - namespace duckdb { const vector RelationManager::GetRelationStats() { @@ -102,6 +100,23 @@ static bool OperatorIsNonReorderable(LogicalOperatorType op_type) { } } +static bool JoinIsReorderable(LogicalOperator &op) { + if (op.type == LogicalOperatorType::LOGICAL_CROSS_PRODUCT) { + return true; + } else if (op.type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN) { + auto &join = op.Cast(); + switch (join.join_type) { + case JoinType::INNER: + case JoinType::SEMI: + case JoinType::ANTI: + return true; + default: + return false; + } + } + return false; +} + static bool HasNonReorderableChild(LogicalOperator &op) { LogicalOperator *tmp = &op; while (tmp->children.size() == 1) { @@ -110,8 +125,7 @@ static bool HasNonReorderableChild(LogicalOperator &op) { } tmp = tmp->children[0].get(); if (tmp->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN) { - auto &join = tmp->Cast(); - if (join.join_type != JoinType::INNER) { + if (!JoinIsReorderable(*tmp)) { return true; } } @@ -141,8 +155,7 @@ bool RelationManager::ExtractJoinRelations(LogicalOperator &input_op, } if (op->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN) { - auto &join = op->Cast(); - if (join.join_type == JoinType::INNER) { + if (JoinIsReorderable(*op)) { // extract join conditions from inner join filter_operators.push_back(*op); } else { @@ -314,7 +327,6 @@ vector> RelationManager::ExtractEdges(LogicalOperator &op if (f_op.type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN || f_op.type == LogicalOperatorType::LOGICAL_ASOF_JOIN) { auto &join = f_op.Cast(); - D_ASSERT(join.join_type == JoinType::INNER); D_ASSERT(join.expressions.empty()); for (auto &cond : join.conditions) { auto comparison = @@ -324,7 +336,8 @@ vector> RelationManager::ExtractEdges(LogicalOperator &op unordered_set bindings; ExtractBindings(*comparison, bindings); auto &set = set_manager.GetJoinRelation(bindings); - auto filter_info = make_uniq(std::move(comparison), set, filters_and_bindings.size()); + auto filter_info = + make_uniq(std::move(comparison), set, filters_and_bindings.size(), join.join_type); filters_and_bindings.push_back(std::move(filter_info)); } } diff --git a/src/optimizer/join_order/relation_statistics_helper.cpp b/src/optimizer/join_order/relation_statistics_helper.cpp index 79af3bd8ca3..5432d004f9a 100644 --- a/src/optimizer/join_order/relation_statistics_helper.cpp +++ b/src/optimizer/join_order/relation_statistics_helper.cpp @@ -59,10 +59,10 @@ RelationStats RelationStatisticsHelper::ExtractGetStats(LogicalGet &get, ClientC auto cardinality_after_filters = base_table_cardinality; unique_ptr column_statistics; - auto table_thing = get.GetTable(); + auto catalog_table = get.GetTable(); auto name = string("some table"); - if (table_thing) { - name = table_thing->name; + if (catalog_table) { + name = catalog_table->name; return_stats.table_name = name; } @@ -82,7 +82,8 @@ RelationStats RelationStatisticsHelper::ExtractGetStats(LogicalGet &get, ClientC if (get.function.statistics) { column_statistics = get.function.statistics(context, get.bind_data.get(), get.column_ids[i]); if (column_statistics && have_catalog_table_statistics) { - auto column_distinct_count = DistinctCount({column_statistics->GetDistinctCount(), true}); + auto distinct_count = MaxValue((idx_t)1, column_statistics->GetDistinctCount()); + auto column_distinct_count = DistinctCount({distinct_count, true}); return_stats.column_distinct_count.push_back(column_distinct_count); return_stats.column_names.push_back(name + "." + get.names.at(get.column_ids.at(i))); have_distinct_count_stats = true; @@ -105,9 +106,8 @@ RelationStats RelationStatisticsHelper::ExtractGetStats(LogicalGet &get, ClientC if (!get.table_filters.filters.empty()) { column_statistics = nullptr; for (auto &it : get.table_filters.filters) { - if (get.bind_data && get.function.name.compare("seq_scan") == 0) { - auto &table_scan_bind_data = get.bind_data->Cast(); - column_statistics = get.function.statistics(context, &table_scan_bind_data, it.first); + if (get.bind_data && get.function.statistics) { + column_statistics = get.function.statistics(context, get.bind_data.get(), it.first); } if (column_statistics && it.second->filter_type == TableFilterType::CONJUNCTION_AND) { diff --git a/src/optimizer/limit_pushdown.cpp b/src/optimizer/limit_pushdown.cpp new file mode 100644 index 00000000000..d6f2b66b6a1 --- /dev/null +++ b/src/optimizer/limit_pushdown.cpp @@ -0,0 +1,42 @@ +#include "duckdb/optimizer/limit_pushdown.hpp" + +#include "duckdb/planner/operator/logical_limit.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" + +namespace duckdb { + +bool LimitPushdown::CanOptimize(duckdb::LogicalOperator &op) { + if (op.type == LogicalOperatorType::LOGICAL_LIMIT && + op.children[0]->type == LogicalOperatorType::LOGICAL_PROJECTION) { + auto &limit = op.Cast(); + + if (limit.offset_val.Type() == LimitNodeType::EXPRESSION_PERCENTAGE || + limit.offset_val.Type() == LimitNodeType::EXPRESSION_VALUE) { + // Offset cannot be an expression + return false; + } + + if (limit.limit_val.Type() == LimitNodeType::CONSTANT_VALUE && limit.limit_val.GetConstantValue() < 8192) { + // Push down only when limit value is smaller than 8192. + // when physical_limit is introduced, it will end a parallel pipeline + // restrict the limit value to be small so that remaining operations run fast without parallelization. + return true; + } + } + return false; +} + +unique_ptr LimitPushdown::Optimize(unique_ptr op) { + if (CanOptimize(*op)) { + auto projection = std::move(op->children[0]); + op->children[0] = std::move(projection->children[0]); + projection->children[0] = std::move(op); + swap(projection, op); + } + for (auto &child : op->children) { + child = Optimize(std::move(child)); + } + return op; +} + +} // namespace duckdb diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index b4bbd37ce7d..c8e4096d70a 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -4,6 +4,7 @@ #include "duckdb/main/client_context.hpp" #include "duckdb/main/config.hpp" #include "duckdb/main/query_profiler.hpp" +#include "duckdb/optimizer/build_probe_side_optimizer.hpp" #include "duckdb/optimizer/column_lifetime_analyzer.hpp" #include "duckdb/optimizer/common_aggregate_optimizer.hpp" #include "duckdb/optimizer/cse_optimizer.hpp" @@ -18,8 +19,10 @@ #include "duckdb/optimizer/remove_unused_columns.hpp" #include "duckdb/optimizer/rule/equal_or_null_simplification.hpp" #include "duckdb/optimizer/rule/in_clause_simplification.hpp" +#include "duckdb/optimizer/rule/join_dependent_filter.hpp" #include "duckdb/optimizer/rule/list.hpp" #include "duckdb/optimizer/statistics_propagator.hpp" +#include "duckdb/optimizer/limit_pushdown.hpp" #include "duckdb/optimizer/topn_optimizer.hpp" #include "duckdb/optimizer/unnest_rewriter.hpp" #include "duckdb/planner/binder.hpp" @@ -43,6 +46,8 @@ Optimizer::Optimizer(Binder &binder, ClientContext &context) : context(context), rewriter.rules.push_back(make_uniq(rewriter)); rewriter.rules.push_back(make_uniq(rewriter)); rewriter.rules.push_back(make_uniq(rewriter)); + rewriter.rules.push_back(make_uniq(rewriter)); + rewriter.rules.push_back(make_uniq(context, rewriter)); #ifdef DEBUG for (auto &rule : rewriter.rules) { @@ -79,17 +84,19 @@ void Optimizer::Verify(LogicalOperator &op) { ColumnBindingResolver::Verify(op); } -unique_ptr Optimizer::Optimize(unique_ptr plan_p) { - Verify(*plan_p); - - switch (plan_p->type) { +void Optimizer::RunBuiltInOptimizers() { + switch (plan->type) { case LogicalOperatorType::LOGICAL_TRANSACTION: - return plan_p; // skip optimizing simple & often-occurring plans unaffected by rewrites + case LogicalOperatorType::LOGICAL_PRAGMA: + case LogicalOperatorType::LOGICAL_SET: + case LogicalOperatorType::LOGICAL_UPDATE_EXTENSIONS: + case LogicalOperatorType::LOGICAL_CREATE_SECRET: + case LogicalOperatorType::LOGICAL_EXTENSION_OPERATOR: + // skip optimizing simple & often-occurring plans unaffected by rewrites + return; default: break; } - - this->plan = std::move(plan_p); // first we perform expression rewrites using the ExpressionRewriter // this does not change the logical plan structure, but only simplifies the expression trees RunOptimizer(OptimizerType::EXPRESSION_REWRITER, [&]() { rewriter.VisitOperator(*plan); }); @@ -153,6 +160,19 @@ unique_ptr Optimizer::Optimize(unique_ptr plan cse_optimizer.VisitOperator(*plan); }); + // Once we know the column lifetime, we have more information regarding + // what relations should be the build side/probe side. + RunOptimizer(OptimizerType::BUILD_SIDE_PROBE_SIDE, [&]() { + BuildProbeSideOptimizer build_probe_side_optimizer(context, *plan); + build_probe_side_optimizer.VisitOperator(*plan); + }); + + // pushes LIMIT below PROJECTION + RunOptimizer(OptimizerType::LIMIT_PUSHDOWN, [&]() { + LimitPushdown limit_pushdown; + plan = limit_pushdown.Optimize(std::move(plan)); + }); + // transform ORDER BY + LIMIT to TopN RunOptimizer(OptimizerType::TOP_N, [&]() { TopN topn; @@ -190,10 +210,19 @@ unique_ptr Optimizer::Optimize(unique_ptr plan ExpressionHeuristics expression_heuristics(*this); plan = expression_heuristics.Rewrite(std::move(plan)); }); +} + +unique_ptr Optimizer::Optimize(unique_ptr plan_p) { + Verify(*plan_p); + + this->plan = std::move(plan_p); + + RunBuiltInOptimizers(); for (auto &optimizer_extension : DBConfig::GetConfig(context).optimizer_extensions) { RunOptimizer(OptimizerType::EXTENSION, [&]() { - optimizer_extension.optimize_function(context, optimizer_extension.optimizer_info.get(), plan); + OptimizerExtensionInput input {GetContext(), *this, optimizer_extension.optimizer_info.get()}; + optimizer_extension.optimize_function(input, plan); }); } diff --git a/src/optimizer/pushdown/CMakeLists.txt b/src/optimizer/pushdown/CMakeLists.txt index 4ce1f851ba8..c1df2b42f0b 100644 --- a/src/optimizer/pushdown/CMakeLists.txt +++ b/src/optimizer/pushdown/CMakeLists.txt @@ -13,7 +13,8 @@ add_library_unity( pushdown_projection.cpp pushdown_semi_anti_join.cpp pushdown_set_operation.cpp - pushdown_single_join.cpp) + pushdown_single_join.cpp + pushdown_window.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/optimizer/pushdown/pushdown_aggregate.cpp b/src/optimizer/pushdown/pushdown_aggregate.cpp index cb6db6661a6..747ab103d4c 100644 --- a/src/optimizer/pushdown/pushdown_aggregate.cpp +++ b/src/optimizer/pushdown/pushdown_aggregate.cpp @@ -9,14 +9,6 @@ namespace duckdb { using Filter = FilterPushdown::Filter; -static void ExtractFilterBindings(Expression &expr, vector &bindings) { - if (expr.type == ExpressionType::BOUND_COLUMN_REF) { - auto &colref = expr.Cast(); - bindings.push_back(colref.binding); - } - ExpressionIterator::EnumerateChildren(expr, [&](Expression &child) { ExtractFilterBindings(child, bindings); }); -} - static unique_ptr ReplaceGroupBindings(LogicalAggregate &proj, unique_ptr expr) { if (expr->type == ExpressionType::BOUND_COLUMN_REF) { auto &colref = expr->Cast(); @@ -31,6 +23,14 @@ static unique_ptr ReplaceGroupBindings(LogicalAggregate &proj, uniqu return expr; } +void FilterPushdown::ExtractFilterBindings(Expression &expr, vector &bindings) { + if (expr.type == ExpressionType::BOUND_COLUMN_REF) { + auto &colref = expr.Cast(); + bindings.push_back(colref.binding); + } + ExpressionIterator::EnumerateChildren(expr, [&](Expression &child) { ExtractFilterBindings(child, bindings); }); +} + unique_ptr FilterPushdown::PushdownAggregate(unique_ptr op) { D_ASSERT(op->type == LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY); auto &aggr = op->Cast(); @@ -58,13 +58,12 @@ unique_ptr FilterPushdown::PushdownAggregate(unique_ptr FilterPushdown::PushdownCrossProduct(unique_ptrfilter)); + } else { + right_pushdown.filters.push_back(std::move(f)); + } } else { D_ASSERT(side == JoinSide::BOTH || side == JoinSide::NONE); // bindings match both: turn into join condition @@ -52,9 +58,9 @@ unique_ptr FilterPushdown::PushdownCrossProduct(unique_ptr conditions; vector> arbitrary_expressions; const auto join_type = JoinType::INNER; - LogicalComparisonJoin::ExtractJoinConditions(GetContext(), join_type, op->children[0], op->children[1], - left_bindings, right_bindings, join_expressions, conditions, - arbitrary_expressions); + LogicalComparisonJoin::ExtractJoinConditions(GetContext(), join_type, join_ref_type, op->children[0], + op->children[1], left_bindings, right_bindings, join_expressions, + conditions, arbitrary_expressions); // create the join from the join conditions return LogicalComparisonJoin::CreateJoin(GetContext(), join_type, join_ref_type, std::move(op->children[0]), std::move(op->children[1]), std::move(conditions), diff --git a/src/optimizer/pushdown/pushdown_window.cpp b/src/optimizer/pushdown/pushdown_window.cpp new file mode 100644 index 00000000000..be4fe70c2af --- /dev/null +++ b/src/optimizer/pushdown/pushdown_window.cpp @@ -0,0 +1,91 @@ +#include "duckdb/optimizer/filter_pushdown.hpp" +#include "duckdb/parser/expression/window_expression.hpp" +#include "duckdb/planner/expression/bound_columnref_expression.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/planner/expression/bound_window_expression.hpp" +#include "duckdb/planner/expression_iterator.hpp" +#include "duckdb/planner/operator/logical_window.hpp" + +namespace duckdb { + +using Filter = FilterPushdown::Filter; + +bool CanPushdownFilter(vector window_exprs_partition_bindings, + const vector &bindings) { + auto filter_on_all_partitions = true; + for (auto &partition_binding_set : window_exprs_partition_bindings) { + auto filter_on_binding_set = true; + for (auto &binding : bindings) { + if (partition_binding_set.find(binding) == partition_binding_set.end()) { + filter_on_binding_set = false; + break; + } + } + filter_on_all_partitions = filter_on_all_partitions && filter_on_binding_set; + if (!filter_on_all_partitions) { + break; + } + } + return filter_on_all_partitions; +} + +unique_ptr FilterPushdown::PushdownWindow(unique_ptr op) { + D_ASSERT(op->type == LogicalOperatorType::LOGICAL_WINDOW); + auto &window = op->Cast(); + FilterPushdown pushdown(optimizer); + + // 1. Loop throguh the expressions, find the window expressions and investigate the partitions + // if a filter applies to a partition in each window expression then you can push the filter + // into the children. + vector window_exprs_partition_bindings; + for (auto &expr : window.expressions) { + if (expr->expression_class != ExpressionClass::BOUND_WINDOW) { + continue; + } + auto &window_expr = expr->Cast(); + auto &partitions = window_expr.partitions; + if (partitions.empty()) { + // If any window expression does not have partitions, we cannot push any filters. + // all window expressions need to be partitioned by the same column + // in order to push down the window. + return FinishPushdown(std::move(op)); + } + column_binding_set_t partition_bindings; + // 2. Get the binding information of the partitions of the window expression + for (auto &partition_expr : partitions) { + switch (partition_expr->type) { + // TODO: Add expressions for function expressions like FLOOR, CEIL etc. + case ExpressionType::BOUND_COLUMN_REF: { + auto &partition_col = partition_expr->Cast(); + partition_bindings.insert(partition_col.binding); + break; + } + default: + break; + } + } + window_exprs_partition_bindings.push_back(partition_bindings); + } + + if (window_exprs_partition_bindings.empty()) { + return FinishPushdown(std::move(op)); + } + + vector> leftover_filters; + // Loop through the filters. If a filter is on a partition in every window expression + // it can be pushed down. + for (idx_t i = 0; i < filters.size(); i++) { + // the filter must be on all partition bindings + vector bindings; + ExtractFilterBindings(*filters.at(i)->filter, bindings); + if (CanPushdownFilter(window_exprs_partition_bindings, bindings)) { + pushdown.filters.push_back(std::move(filters.at(i))); + } else { + leftover_filters.push_back(std::move(filters.at(i))); + } + } + op->children[0] = pushdown.Rewrite(std::move(op->children[0])); + filters = std::move(leftover_filters); + return FinishPushdown(std::move(op)); +} +} // namespace duckdb diff --git a/src/optimizer/remove_unused_columns.cpp b/src/optimizer/remove_unused_columns.cpp index 85932a13ca7..b9d027d1cae 100644 --- a/src/optimizer/remove_unused_columns.cpp +++ b/src/optimizer/remove_unused_columns.cpp @@ -11,6 +11,7 @@ #include "duckdb/planner/expression_iterator.hpp" #include "duckdb/planner/operator/logical_aggregate.hpp" #include "duckdb/planner/operator/logical_comparison_join.hpp" +#include "duckdb/planner/operator/logical_distinct.hpp" #include "duckdb/planner/operator/logical_filter.hpp" #include "duckdb/planner/operator/logical_get.hpp" #include "duckdb/planner/operator/logical_order.hpp" @@ -158,30 +159,14 @@ void RemoveUnusedColumns::VisitOperator(LogicalOperator &op) { return; } case LogicalOperatorType::LOGICAL_EXCEPT: - case LogicalOperatorType::LOGICAL_INTERSECT: + case LogicalOperatorType::LOGICAL_INTERSECT: { // for INTERSECT/EXCEPT operations we can't remove anything, just recursively visit the children for (auto &child : op.children) { RemoveUnusedColumns remove(binder, context, true); remove.VisitOperator(*child); } return; - case LogicalOperatorType::LOGICAL_ORDER_BY: - if (!everything_referenced) { - auto &order = op.Cast(); - D_ASSERT(order.projections.empty()); // should not yet be set - const auto all_bindings = order.GetColumnBindings(); - - for (idx_t col_idx = 0; col_idx < all_bindings.size(); col_idx++) { - if (column_references.find(all_bindings[col_idx]) != column_references.end()) { - order.projections.push_back(col_idx); - } - } - } - for (auto &child : op.children) { - RemoveUnusedColumns remove(binder, context, true); - remove.VisitOperator(*child); - } - return; + } case LogicalOperatorType::LOGICAL_PROJECTION: { if (!everything_referenced) { auto &proj = op.Cast(); @@ -293,6 +278,12 @@ void RemoveUnusedColumns::VisitOperator(LogicalOperator &op) { break; } case LogicalOperatorType::LOGICAL_DISTINCT: { + auto &distinct = op.Cast(); + if (distinct.distinct_type == DistinctType::DISTINCT_ON) { + // distinct type references columns that need to be distinct on, so no + // need to implicity reference everything. + break; + } // distinct, all projected columns are used for the DISTINCT computation // mark all columns as used and continue to the children // FIXME: DISTINCT with expression list does not implicitly reference everything diff --git a/src/optimizer/rule/CMakeLists.txt b/src/optimizer/rule/CMakeLists.txt index 1ebbb4a0708..115a8504edd 100644 --- a/src/optimizer/rule/CMakeLists.txt +++ b/src/optimizer/rule/CMakeLists.txt @@ -12,10 +12,12 @@ add_library_unity( enum_comparison.cpp equal_or_null_simplification.cpp in_clause_simplification_rule.cpp + join_dependent_filter.cpp like_optimizations.cpp move_constants.cpp ordered_aggregate_optimizer.cpp - regex_optimizations.cpp) + regex_optimizations.cpp + timestamp_comparison.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/optimizer/rule/join_dependent_filter.cpp b/src/optimizer/rule/join_dependent_filter.cpp new file mode 100644 index 00000000000..339bc46bb60 --- /dev/null +++ b/src/optimizer/rule/join_dependent_filter.cpp @@ -0,0 +1,135 @@ +#include "duckdb/optimizer/rule/join_dependent_filter.hpp" + +#include "duckdb/optimizer/expression_rewriter.hpp" +#include "duckdb/planner/expression/bound_columnref_expression.hpp" +#include "duckdb/planner/expression/bound_comparison_expression.hpp" +#include "duckdb/planner/expression/bound_conjunction_expression.hpp" +#include "duckdb/planner/expression_iterator.hpp" + +namespace duckdb { + +JoinDependentFilterRule::JoinDependentFilterRule(ExpressionRewriter &rewriter) : Rule(rewriter) { + // Match on a ConjunctionExpression that has at least two ConjunctionExpressions as children + auto op = make_uniq(); + op->matchers.push_back(make_uniq()); + op->policy = SetMatcher::Policy::SOME; + root = std::move(op); +} + +static inline void GetTableIndices(const Expression &expression, unordered_set &table_idxs) { + ExpressionIterator::EnumerateChildren(expression, [&](const Expression &child) { + if (child.GetExpressionClass() == ExpressionClass::BOUND_COLUMN_REF) { + auto &colref = child.Cast(); + table_idxs.insert(colref.binding.table_index); + } else { + GetTableIndices(child, table_idxs); + } + }); +} + +static inline bool ExpressionReferencesMultipleTables(const Expression &binding) { + unordered_set table_idxs; + GetTableIndices(binding, table_idxs); + return table_idxs.size() > 1; +} + +static inline void ExtractConjunctedExpressions(Expression &expression, + unordered_map> &expressions) { + if (expression.GetExpressionType() == ExpressionType::CONJUNCTION_AND) { + auto &conjunction = expression.Cast(); + for (auto &child : conjunction.children) { + ExtractConjunctedExpressions(*child, expressions); + } + } else if (!expression.IsVolatile()) { + unordered_set table_idxs; + GetTableIndices(expression, table_idxs); + if (table_idxs.size() != 1) { + return; // Needs to reference exactly one table + } + + // If there was already an expression, AND it together + auto &table_expressions = expressions[*table_idxs.begin()]; + table_expressions = table_expressions + ? make_uniq(ExpressionType::CONJUNCTION_AND, + std::move(table_expressions), expression.Copy()) + : expression.Copy(); + } +} + +unique_ptr JoinDependentFilterRule::Apply(LogicalOperator &op, vector> &bindings, + bool &changes_made, bool is_root) { + // Only applies to top-level FILTER expressions + if ((op.type != LogicalOperatorType::LOGICAL_FILTER && op.type != LogicalOperatorType::LOGICAL_ANY_JOIN) || + !is_root) { + return nullptr; + } + + // The expression must be an OR + auto &conjunction = bindings[0].get().Cast(); + if (conjunction.GetExpressionType() != ExpressionType::CONJUNCTION_OR) { + return nullptr; + } + + // Must have at least one join-dependent AND expression + auto &children = conjunction.children; + bool eligible = false; + for (const auto &child : children) { + if (child->GetExpressionClass() == ExpressionClass::BOUND_CONJUNCTION && + child->GetExpressionType() == ExpressionType::CONJUNCTION_AND && + ExpressionReferencesMultipleTables(*child)) { + eligible = true; + break; + } + } + if (!eligible) { + return nullptr; + } + + // Extract all comparison expressions between column references and constants that are AND'ed together + auto conjuncted_expressions = make_uniq_array>>(children.size()); + for (idx_t child_idx = 0; child_idx < children.size(); child_idx++) { + conjuncted_expressions[child_idx] = unordered_map>(); + ExtractConjunctedExpressions(*children[child_idx], conjuncted_expressions[child_idx]); + } + + auto derived_filter = make_uniq(ExpressionType::CONJUNCTION_AND); + for (auto &entry : conjuncted_expressions[0]) { + auto derived_entry_filter = make_uniq(ExpressionType::CONJUNCTION_OR); + derived_entry_filter->children.push_back(entry.second->Copy()); + + bool found = true; + for (idx_t conj_idx = 1; conj_idx < children.size(); conj_idx++) { + auto &other_entry = conjuncted_expressions[conj_idx]; + auto other_it = other_entry.find(entry.first); + if (other_it == other_entry.end()) { + found = false; + break; // Expression does not appear in every conjuncted expression, cannot derive any restriction + } + derived_entry_filter->children.push_back(other_it->second->Copy()); + } + + if (!found) { + continue; // Expression must show up in every entry + } + + derived_filter->children.push_back(std::move(derived_entry_filter)); + } + + if (derived_filter->children.empty()) { + return nullptr; // Could not derive filters that can be pushed down + } + + // Add the derived expression to the original expression with an AND + auto result = make_uniq_base(ExpressionType::CONJUNCTION_AND); + auto &result_conjunction = result->Cast(); + result_conjunction.children.push_back(conjunction.Copy()); + + if (derived_filter->children.size() == 1) { + result_conjunction.children.push_back(std::move(derived_filter->children[0])); + } else { + result_conjunction.children.push_back(std::move(derived_filter)); + } + return result; +} + +} // namespace duckdb diff --git a/src/optimizer/rule/move_constants.cpp b/src/optimizer/rule/move_constants.cpp index 636265ff913..29404164f7d 100644 --- a/src/optimizer/rule/move_constants.cpp +++ b/src/optimizer/rule/move_constants.cpp @@ -41,6 +41,10 @@ unique_ptr MoveConstantsRule::Apply(LogicalOperator &op, vectorreturn_type.IsIntegral()); if (inner_constant.value.IsNull() || outer_constant.value.IsNull()) { + if (comparison.type == ExpressionType::COMPARE_DISTINCT_FROM || + comparison.type == ExpressionType::COMPARE_NOT_DISTINCT_FROM) { + return nullptr; + } return make_uniq(Value(comparison.return_type)); } auto &constant_type = outer_constant.return_type; diff --git a/src/optimizer/rule/timestamp_comparison.cpp b/src/optimizer/rule/timestamp_comparison.cpp new file mode 100644 index 00000000000..3b1d22eeba9 --- /dev/null +++ b/src/optimizer/rule/timestamp_comparison.cpp @@ -0,0 +1,107 @@ + +#include "duckdb/optimizer/rule/timestamp_comparison.hpp" +#include "duckdb/optimizer/matcher/expression_matcher.hpp" +#include "duckdb/planner/expression_iterator.hpp" +#include "duckdb/common/constants.hpp" +#include "duckdb/execution/expression_executor.hpp" +#include "duckdb/planner/expression/bound_cast_expression.hpp" +#include "duckdb/planner/expression/bound_conjunction_expression.hpp" +#include "duckdb/planner/expression/bound_comparison_expression.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/optimizer/matcher/type_matcher_id.hpp" +#include "duckdb/optimizer/expression_rewriter.hpp" +#include "duckdb/common/types.hpp" +#include "duckdb/common/operator/add.hpp" + +namespace duckdb { + +TimeStampComparison::TimeStampComparison(ClientContext &context, ExpressionRewriter &rewriter) + : Rule(rewriter), context(context) { + // match on a ComparisonExpression that is an Equality and has a VARCHAR and ENUM as its children + auto op = make_uniq(); + op->policy = SetMatcher::Policy::UNORDERED; + // Enum requires expression to be root + op->expr_type = make_uniq(ExpressionType::COMPARE_EQUAL); + + // one side is timestamp cast to date + auto left = make_uniq(); + left->type = make_uniq(LogicalTypeId::DATE); + left->matcher = make_uniq(); + left->matcher->expr_class = ExpressionClass::BOUND_COLUMN_REF; + left->matcher->type = make_uniq(LogicalTypeId::TIMESTAMP); + op->matchers.push_back(std::move(left)); + + // other side is varchar to date? + auto right = make_uniq(); + right->type = make_uniq(LogicalTypeId::DATE); + right->matcher = make_uniq(); + right->matcher->expr_class = ExpressionClass::BOUND_CONSTANT; + right->matcher->type = make_uniq(LogicalTypeId::VARCHAR); + op->matchers.push_back(std::move(right)); + + root = std::move(op); +} + +static void ExpressionIsConstant(Expression &expr, bool &is_constant) { + if (expr.type == ExpressionType::BOUND_COLUMN_REF) { + is_constant = false; + return; + } + ExpressionIterator::EnumerateChildren(expr, [&](Expression &child) { ExpressionIsConstant(child, is_constant); }); +} + +unique_ptr TimeStampComparison::Apply(LogicalOperator &op, vector> &bindings, + bool &changes_made, bool is_root) { + auto cast_constant = bindings[3].get().Copy(); + auto cast_columnref = bindings[2].get().Copy(); + auto is_constant = true; + ExpressionIsConstant(*cast_constant, is_constant); + if (!is_constant) { + // means the matchers are flipped, so we need to flip our bindings + // for some reason an extra binding is added in this case. + cast_constant = bindings[4].get().Copy(); + cast_columnref = bindings[3].get().Copy(); + } + auto new_expr = make_uniq(ExpressionType::CONJUNCTION_AND); + + Value result; + if (ExpressionExecutor::TryEvaluateScalar(context, *cast_constant, result)) { + D_ASSERT(result.type() == LogicalType::DATE); + auto original_val = result.GetValue(); + auto no_seconds = dtime_t(0); + + // original date as timestamp with no seconds + auto original_val_ts = Value::TIMESTAMP(original_val, no_seconds); + auto original_val_for_comparison = make_uniq(original_val_ts); + + // add one day and validate the new date + // code is inspired by AddOperator::Operation(date_t left, int32_t right). The function wasn't used directly + // since it throws errors that I cannot catch here. + + auto date_t_copy = result.GetValue(); + date_t date_t_result; + // attempt to add 1 day + if (!TryAddOperator::Operation(date_t_copy, 1, date_t_result)) { + // don't rewrite the expression and let the expression executor handle the invalid date + return nullptr; + } + + auto result_as_val = Value::DATE(date_t_result); + auto original_val_plus_on_date_ts = Value::TIMESTAMP(result_as_val.GetValue()); + + auto val_for_comparison = make_uniq(original_val_plus_on_date_ts); + + auto left_copy = cast_columnref->Copy(); + auto right_copy = cast_columnref->Copy(); + auto lt_eq_expr = make_uniq_base( + ExpressionType::COMPARE_LESSTHAN, std::move(right_copy), std::move(val_for_comparison)); + auto gt_eq_expr = make_uniq_base( + ExpressionType::COMPARE_GREATERTHANOREQUALTO, std::move(left_copy), std::move(original_val_for_comparison)); + new_expr->children.push_back(std::move(gt_eq_expr)); + new_expr->children.push_back(std::move(lt_eq_expr)); + return std::move(new_expr); + } + return nullptr; +} + +} // namespace duckdb diff --git a/src/optimizer/statistics/operator/propagate_filter.cpp b/src/optimizer/statistics/operator/propagate_filter.cpp index 6bd1d30c160..7dbdc6da75b 100644 --- a/src/optimizer/statistics/operator/propagate_filter.cpp +++ b/src/optimizer/statistics/operator/propagate_filter.cpp @@ -241,7 +241,12 @@ unique_ptr StatisticsPropagator::PropagateStatistics(LogicalFilt filter.expressions.erase_at(i); i--; if (filter.expressions.empty()) { - // just break. The physical filter planner will plan a projection instead + // if there is a projection map, we should keep the filter + // the physical planner will eventually skip the filter, but will keep + // the correct columns. + if (filter.projection_map.empty()) { + node_ptr = std::move(filter.children[0]); + } break; } } else if (ExpressionIsConstant(*condition, Value::BOOLEAN(false)) || diff --git a/src/optimizer/topn_optimizer.cpp b/src/optimizer/topn_optimizer.cpp index 7c227cc70d5..574e8c6625e 100644 --- a/src/optimizer/topn_optimizer.cpp +++ b/src/optimizer/topn_optimizer.cpp @@ -8,8 +8,7 @@ namespace duckdb { bool TopN::CanOptimize(LogicalOperator &op) { - if (op.type == LogicalOperatorType::LOGICAL_LIMIT && - op.children[0]->type == LogicalOperatorType::LOGICAL_ORDER_BY) { + if (op.type == LogicalOperatorType::LOGICAL_LIMIT) { auto &limit = op.Cast(); if (limit.limit_val.Type() != LimitNodeType::CONSTANT_VALUE) { @@ -20,15 +19,42 @@ bool TopN::CanOptimize(LogicalOperator &op) { // we need offset to be either not set (i.e. limit without offset) OR have offset be return false; } - return true; + + auto child_op = op.children[0].get(); + + while (child_op->type == LogicalOperatorType::LOGICAL_PROJECTION) { + D_ASSERT(!child_op->children.empty()); + child_op = child_op->children[0].get(); + } + + return child_op->type == LogicalOperatorType::LOGICAL_ORDER_BY; } return false; } unique_ptr TopN::Optimize(unique_ptr op) { if (CanOptimize(*op)) { + + vector> projections; + + // traverse operator tree and collect all projection nodes until we reach + // the order by operator + + auto child = std::move(op->children[0]); + // collect all projections until we get to the order by + while (child->type == LogicalOperatorType::LOGICAL_PROJECTION) { + D_ASSERT(!child->children.empty()); + auto tmp = std::move(child->children[0]); + projections.push_back(std::move(child)); + child = std::move(tmp); + } + D_ASSERT(child->type == LogicalOperatorType::LOGICAL_ORDER_BY); + auto &order_by = child->Cast(); + + // Move order by operator into children of limit operator + op->children[0] = std::move(child); + auto &limit = op->Cast(); - auto &order_by = (op->children[0])->Cast(); auto limit_val = limit.limit_val.GetConstantValue(); idx_t offset_val = 0; if (limit.offset_val.Type() == LimitNodeType::CONSTANT_VALUE) { @@ -37,11 +63,19 @@ unique_ptr TopN::Optimize(unique_ptr op) { auto topn = make_uniq(std::move(order_by.orders), limit_val, offset_val); topn->AddChild(std::move(order_by.children[0])); op = std::move(topn); - } else { - for (auto &child : op->children) { - child = Optimize(std::move(child)); + + // reconstruct all projection nodes above limit operator + while (!projections.empty()) { + auto node = std::move(projections.back()); + node->children[0] = std::move(op); + op = std::move(node); + projections.pop_back(); } } + + for (auto &child : op->children) { + child = Optimize(std::move(child)); + } return op; } diff --git a/src/parallel/executor.cpp b/src/parallel/executor.cpp index 408eb1ea0b6..a0343f5d9af 100644 --- a/src/parallel/executor.cpp +++ b/src/parallel/executor.cpp @@ -17,6 +17,7 @@ #include "duckdb/parallel/thread_context.hpp" #include +#include namespace duckdb { @@ -426,6 +427,23 @@ void Executor::WorkOnTasks() { } } +void Executor::SignalTaskRescheduled(lock_guard &) { + task_reschedule.notify_one(); +} + +void Executor::WaitForTask() { + static constexpr std::chrono::milliseconds WAIT_TIME = std::chrono::milliseconds(20); + std::unique_lock l(executor_lock); + if (to_be_rescheduled_tasks.empty()) { + return; + } + if (ResultCollectorIsBlocked()) { + return; + } + + task_reschedule.wait_for(l, WAIT_TIME); +} + void Executor::RescheduleTask(shared_ptr &task_p) { // This function will spin lock until the task provided is added to the to_be_rescheduled_tasks while (true) { @@ -438,6 +456,7 @@ void Executor::RescheduleTask(shared_ptr &task_p) { auto &scheduler = TaskScheduler::GetScheduler(context); to_be_rescheduled_tasks.erase(task_p.get()); scheduler.ScheduleTask(GetToken(), task_p); + SignalTaskRescheduled(l); break; } } @@ -448,7 +467,6 @@ bool Executor::ResultCollectorIsBlocked() { // The result collector is always in the last pipeline return false; } - lock_guard l(executor_lock); if (to_be_rescheduled_tasks.empty()) { return false; } @@ -503,6 +521,7 @@ PendingExecutionResult Executor::ExecuteTask(bool dry_run) { if (!current_task && !HasError()) { // there are no tasks to be scheduled and there are tasks blocked + lock_guard l(executor_lock); if (ResultCollectorIsBlocked()) { // The blocked tasks are processing the Sink of a BufferedResultCollector // We return here so the query result can be made and fetched from diff --git a/src/parallel/task_scheduler.cpp b/src/parallel/task_scheduler.cpp index d11b144bf3e..baf93b9c9d2 100644 --- a/src/parallel/task_scheduler.cpp +++ b/src/parallel/task_scheduler.cpp @@ -23,10 +23,6 @@ struct SchedulerThread { explicit SchedulerThread(unique_ptr thread_p) : internal_thread(std::move(thread_p)) { } - ~SchedulerThread() { - Allocator::ThreadFlush(0); - } - unique_ptr internal_thread; #endif }; @@ -103,8 +99,10 @@ ProducerToken::~ProducerToken() { TaskScheduler::TaskScheduler(DatabaseInstance &db) : db(db), queue(make_uniq()), - allocator_flush_threshold(db.config.options.allocator_flush_threshold), requested_thread_count(0), + allocator_flush_threshold(db.config.options.allocator_flush_threshold), + allocator_background_threads(db.config.options.allocator_background_threads), requested_thread_count(0), current_thread_count(1) { + SetAllocatorBackgroundThreads(db.config.options.allocator_background_threads); } TaskScheduler::~TaskScheduler() { @@ -141,11 +139,24 @@ bool TaskScheduler::GetTaskFromProducer(ProducerToken &token, shared_ptr & void TaskScheduler::ExecuteForever(atomic *marker) { #ifndef DUCKDB_NO_THREADS + static constexpr const int64_t INITIAL_FLUSH_WAIT = 500000; // initial wait time of 0.5s (in mus) before flushing + shared_ptr task; // loop until the marker is set to false while (*marker) { - // wait for a signal with a timeout - queue->semaphore.wait(); + if (!Allocator::SupportsFlush() || allocator_background_threads) { + // allocator can't flush, or background threads clean up allocations, just start an untimed wait + queue->semaphore.wait(); + } else if (!queue->semaphore.wait(INITIAL_FLUSH_WAIT)) { + // no background threads, flush this threads outstanding allocations after it was idle for 0.5s + Allocator::ThreadFlush(allocator_flush_threshold); + if (!queue->semaphore.wait(Allocator::DecayDelay() * 1000000 - INITIAL_FLUSH_WAIT)) { + // in total, the thread was idle for the entire decay delay (note: seconds converted to mus) + // mark it as idle and start an untimed wait + Allocator::ThreadIdle(); + queue->semaphore.wait(); + } + } if (queue->q.try_dequeue(task)) { auto execute_result = task->Execute(TaskExecutionMode::PROCESS_ALL); @@ -161,11 +172,13 @@ void TaskScheduler::ExecuteForever(atomic *marker) { task.reset(); break; } - - // Flushes the outstanding allocator's outstanding allocations - Allocator::ThreadFlush(allocator_flush_threshold); } } + // this thread will exit, flush all of its outstanding allocations + if (Allocator::SupportsFlush()) { + Allocator::ThreadFlush(0); + Allocator::ThreadIdle(); + } #else throw NotImplementedException("DuckDB was compiled without threads! Background thread loop is not allowed."); #endif @@ -258,9 +271,18 @@ void TaskScheduler::SetThreads(idx_t total_threads, idx_t external_threads) { } #endif requested_thread_count = NumericCast(total_threads - external_threads); + if (Allocator::SupportsFlush()) { + Allocator::FlushAll(); + } } void TaskScheduler::SetAllocatorFlushTreshold(idx_t threshold) { + allocator_flush_threshold = threshold; +} + +void TaskScheduler::SetAllocatorBackgroundThreads(bool enable) { + allocator_background_threads = enable; + Allocator::SetBackgroundThreads(enable); } void TaskScheduler::Signal(idx_t n) { diff --git a/src/parallel/thread_context.cpp b/src/parallel/thread_context.cpp index 049a8fcf9bb..2eb15a3c3c9 100644 --- a/src/parallel/thread_context.cpp +++ b/src/parallel/thread_context.cpp @@ -4,7 +4,7 @@ namespace duckdb { -ThreadContext::ThreadContext(ClientContext &context) : profiler(QueryProfiler::Get(context).IsEnabled()) { +ThreadContext::ThreadContext(ClientContext &context) : profiler(context) { } } // namespace duckdb diff --git a/src/parser/column_definition.cpp b/src/parser/column_definition.cpp index e73fdb02561..245bcd47d8f 100644 --- a/src/parser/column_definition.cpp +++ b/src/parser/column_definition.cpp @@ -23,6 +23,7 @@ ColumnDefinition ColumnDefinition::Copy() const { copy.compression_type = compression_type; copy.category = category; copy.comment = comment; + copy.tags = tags; return copy; } diff --git a/src/parser/expression/function_expression.cpp b/src/parser/expression/function_expression.cpp index 1658d0a39e2..8cd5d4c7056 100644 --- a/src/parser/expression/function_expression.cpp +++ b/src/parser/expression/function_expression.cpp @@ -95,4 +95,18 @@ void FunctionExpression::Verify() const { D_ASSERT(!function_name.empty()); } +bool FunctionExpression::IsLambdaFunction() const { + // Ignore the ->> operator (JSON extension). + if (function_name == "->>") { + return false; + } + // Check the children for lambda expressions. + for (auto &child : children) { + if (child->expression_class == ExpressionClass::LAMBDA) { + return true; + } + } + return false; +} + } // namespace duckdb diff --git a/src/parser/expression/star_expression.cpp b/src/parser/expression/star_expression.cpp index a3b4dd048ce..3589b9533c7 100644 --- a/src/parser/expression/star_expression.cpp +++ b/src/parser/expression/star_expression.cpp @@ -12,11 +12,16 @@ StarExpression::StarExpression(string relation_name_p) } string StarExpression::ToString() const { + string result; + if (unpacked) { + D_ASSERT(columns); + result += "*"; + } if (expr) { D_ASSERT(columns); - return "COLUMNS(" + expr->ToString() + ")"; + result += "COLUMNS(" + expr->ToString() + ")"; + return result; } - string result; if (columns) { result += "COLUMNS("; } @@ -60,6 +65,9 @@ bool StarExpression::Equal(const StarExpression &a, const StarExpression &b) { if (a.columns != b.columns) { return false; } + if (a.unpacked != b.unpacked) { + return false; + } if (a.replace_list.size() != b.replace_list.size()) { return false; } @@ -78,6 +86,30 @@ bool StarExpression::Equal(const StarExpression &a, const StarExpression &b) { return true; } +bool StarExpression::IsStar(const ParsedExpression &a) { + if (a.GetExpressionClass() != ExpressionClass::STAR) { + return false; + } + auto &star = a.Cast(); + return star.columns == false; +} + +bool StarExpression::IsColumns(const ParsedExpression &a) { + if (a.GetExpressionClass() != ExpressionClass::STAR) { + return false; + } + auto &star = a.Cast(); + return star.columns == true && star.unpacked == false; +} + +bool StarExpression::IsColumnsUnpacked(const ParsedExpression &a) { + if (a.GetExpressionClass() != ExpressionClass::STAR) { + return false; + } + auto &star = a.Cast(); + return star.columns == true && star.unpacked == true; +} + unique_ptr StarExpression::Copy() const { auto copy = make_uniq(relation_name); copy->exclude_list = exclude_list; @@ -87,6 +119,7 @@ unique_ptr StarExpression::Copy() const { copy->columns = columns; copy->expr = expr ? expr->Copy() : nullptr; copy->CopyProperties(*this); + copy->unpacked = unpacked; return std::move(copy); } diff --git a/src/parser/parsed_data/CMakeLists.txt b/src/parser/parsed_data/CMakeLists.txt index 9f36fe3d2ce..45419115b90 100644 --- a/src/parser/parsed_data/CMakeLists.txt +++ b/src/parser/parsed_data/CMakeLists.txt @@ -7,6 +7,7 @@ add_library_unity( alter_table_info.cpp attach_info.cpp comment_on_column_info.cpp + copy_info.cpp create_info.cpp create_index_info.cpp create_aggregate_function_info.cpp @@ -25,9 +26,11 @@ add_library_unity( detach_info.cpp drop_info.cpp extra_drop_info.cpp + load_info.cpp sample_options.cpp parse_info.cpp transaction_info.cpp + pragma_info.cpp vacuum_info.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/parser/parsed_data/alter_scalar_function_info.cpp b/src/parser/parsed_data/alter_scalar_function_info.cpp index 363019cf4ec..269a87d6672 100644 --- a/src/parser/parsed_data/alter_scalar_function_info.cpp +++ b/src/parser/parsed_data/alter_scalar_function_info.cpp @@ -35,4 +35,8 @@ unique_ptr AddScalarFunctionOverloadInfo::Copy() const { return make_uniq_base(GetAlterEntryData(), new_overloads); } +string AddScalarFunctionOverloadInfo::ToString() const { + throw NotImplementedException("NOT PARSABLE CURRENTLY"); +} + } // namespace duckdb diff --git a/src/parser/parsed_data/alter_table_function_info.cpp b/src/parser/parsed_data/alter_table_function_info.cpp index 347eb3fd5cf..e7ce608c829 100644 --- a/src/parser/parsed_data/alter_table_function_info.cpp +++ b/src/parser/parsed_data/alter_table_function_info.cpp @@ -35,4 +35,8 @@ unique_ptr AddTableFunctionOverloadInfo::Copy() const { return make_uniq_base(GetAlterEntryData(), new_overloads); } +string AddTableFunctionOverloadInfo::ToString() const { + throw NotImplementedException("NOT PARSABLE"); +} + } // namespace duckdb diff --git a/src/parser/parsed_data/alter_table_info.cpp b/src/parser/parsed_data/alter_table_info.cpp index 977c66d6f13..175ef5f7e53 100644 --- a/src/parser/parsed_data/alter_table_info.cpp +++ b/src/parser/parsed_data/alter_table_info.cpp @@ -1,4 +1,5 @@ #include "duckdb/parser/parsed_data/alter_table_info.hpp" +#include "duckdb/common/extra_type_info.hpp" #include "duckdb/parser/constraint.hpp" @@ -25,6 +26,21 @@ unique_ptr ChangeOwnershipInfo::Copy() const { owner_name, if_not_found); } +string ChangeOwnershipInfo::ToString() const { + string result = ""; + + result += "ALTER "; + result += TypeToString(entry_catalog_type); + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += QualifierToString(catalog, schema, name); + result += " OWNED BY "; + result += QualifierToString(catalog, owner_schema, owner_name); + result += ";"; + return result; +} + //===--------------------------------------------------------------------===// // SetCommentInfo //===--------------------------------------------------------------------===// @@ -44,6 +60,20 @@ unique_ptr SetCommentInfo::Copy() const { if_not_found); } +string SetCommentInfo::ToString() const { + string result = ""; + + result += "COMMENT ON "; + result += ParseInfo::TypeToString(entry_catalog_type); + result += " "; + result += QualifierToString(catalog, schema, name); + result += " IS "; + result += comment_value.ToSQLString(); + + result += ";"; + return result; +} + SetCommentInfo::SetCommentInfo() : AlterInfo(AlterType::SET_COMMENT) { } @@ -82,6 +112,21 @@ unique_ptr RenameColumnInfo::Copy() const { return make_uniq_base(GetAlterEntryData(), old_name, new_name); } +string RenameColumnInfo::ToString() const { + string result = ""; + result += "ALTER TABLE "; + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += QualifierToString(catalog, schema, name); + result += " RENAME COLUMN "; + result += KeywordHelper::WriteOptionallyQuoted(old_name); + result += " TO "; + result += KeywordHelper::WriteOptionallyQuoted(new_name); + result += ";"; + return result; +} + //===--------------------------------------------------------------------===// // RenameTableInfo //===--------------------------------------------------------------------===// @@ -99,6 +144,19 @@ unique_ptr RenameTableInfo::Copy() const { return make_uniq_base(GetAlterEntryData(), new_table_name); } +string RenameTableInfo::ToString() const { + string result = ""; + result += "ALTER TABLE "; + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += QualifierToString(catalog, schema, name); + result += " RENAME TO "; + result += KeywordHelper::WriteOptionallyQuoted(new_table_name); + result += ";"; + return result; +} + //===--------------------------------------------------------------------===// // AddColumnInfo //===--------------------------------------------------------------------===// @@ -118,6 +176,22 @@ unique_ptr AddColumnInfo::Copy() const { return make_uniq_base(GetAlterEntryData(), new_column.Copy(), if_column_not_exists); } +string AddColumnInfo::ToString() const { + string result = ""; + result += "ALTER TABLE "; + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += QualifierToString(catalog, schema, name); + result += " ADD COLUMN"; + if (if_column_not_exists) { + result += " IF NOT EXISTS"; + } + throw NotImplementedException("COLUMN SERIALIZATION"); + result += ";"; + return result; +} + //===--------------------------------------------------------------------===// // RemoveColumnInfo //===--------------------------------------------------------------------===// @@ -135,6 +209,25 @@ unique_ptr RemoveColumnInfo::Copy() const { return make_uniq_base(GetAlterEntryData(), removed_column, if_column_exists, cascade); } +string RemoveColumnInfo::ToString() const { + string result = ""; + result += "ALTER TABLE "; + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += QualifierToString(catalog, schema, name); + result += " DROP COLUMN "; + if (if_column_exists) { + result += "IF EXISTS "; + } + result += KeywordHelper::WriteOptionallyQuoted(removed_column); + if (cascade) { + result += " CASCADE"; + } + result += ";"; + return result; +} + //===--------------------------------------------------------------------===// // ChangeColumnTypeInfo //===--------------------------------------------------------------------===// @@ -154,6 +247,32 @@ unique_ptr ChangeColumnTypeInfo::Copy() const { expression->Copy()); } +string ChangeColumnTypeInfo::ToString() const { + string result = ""; + result += "ALTER TABLE "; + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += QualifierToString(catalog, schema, name); + result += " ALTER COLUMN "; + result += KeywordHelper::WriteOptionallyQuoted(column_name); + result += " TYPE "; + result += target_type.ToString(); // FIXME: ToSQLString ? + auto extra_type_info = target_type.AuxInfo(); + if (extra_type_info && extra_type_info->type == ExtraTypeInfoType::STRING_TYPE_INFO) { + auto &string_info = extra_type_info->Cast(); + if (!string_info.collation.empty()) { + result += " COLLATE " + string_info.collation; + } + } + if (expression) { + result += " USING "; + result += expression->ToString(); + } + result += ";"; + return result; +} + //===--------------------------------------------------------------------===// // SetDefaultInfo //===--------------------------------------------------------------------===// @@ -172,6 +291,25 @@ unique_ptr SetDefaultInfo::Copy() const { expression ? expression->Copy() : nullptr); } +string SetDefaultInfo::ToString() const { + string result = ""; + result += "ALTER TABLE "; + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += QualifierToString(catalog, schema, name); + result += " ALTER COLUMN "; + result += KeywordHelper::WriteOptionallyQuoted(column_name); + if (expression) { + result += " SET DEFAULT "; + result += expression->ToString(); + } else { + result += " DROP DEFAULT"; + } + result += ";"; + return result; +} + //===--------------------------------------------------------------------===// // SetNotNullInfo //===--------------------------------------------------------------------===// @@ -188,6 +326,20 @@ unique_ptr SetNotNullInfo::Copy() const { return make_uniq_base(GetAlterEntryData(), column_name); } +string SetNotNullInfo::ToString() const { + string result = ""; + result += "ALTER TABLE "; + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += QualifierToString(catalog, schema, name); + result += " ALTER COLUMN "; + result += KeywordHelper::WriteOptionallyQuoted(column_name); + result += " SET NOT NULL"; + result += ";"; + return result; +} + //===--------------------------------------------------------------------===// // DropNotNullInfo //===--------------------------------------------------------------------===// @@ -204,6 +356,20 @@ unique_ptr DropNotNullInfo::Copy() const { return make_uniq_base(GetAlterEntryData(), column_name); } +string DropNotNullInfo::ToString() const { + string result = ""; + result += "ALTER TABLE "; + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += QualifierToString(catalog, schema, name); + result += " ALTER COLUMN "; + result += KeywordHelper::WriteOptionallyQuoted(column_name); + result += " DROP NOT NULL"; + result += ";"; + return result; +} + //===--------------------------------------------------------------------===// // AlterForeignKeyInfo //===--------------------------------------------------------------------===// @@ -225,6 +391,10 @@ unique_ptr AlterForeignKeyInfo::Copy() const { pk_keys, fk_keys, type); } +string AlterForeignKeyInfo::ToString() const { + throw NotImplementedException("NOT PARSABLE CURRENTLY"); +} + //===--------------------------------------------------------------------===// // Alter View //===--------------------------------------------------------------------===// @@ -258,4 +428,17 @@ unique_ptr RenameViewInfo::Copy() const { return make_uniq_base(GetAlterEntryData(), new_view_name); } +string RenameViewInfo::ToString() const { + string result = ""; + result += "ALTER VIEW "; + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += QualifierToString(catalog, schema, name); + result += " RENAME TO "; + result += KeywordHelper::WriteOptionallyQuoted(new_view_name); + result += ";"; + return result; +} + } // namespace duckdb diff --git a/src/parser/parsed_data/attach_info.cpp b/src/parser/parsed_data/attach_info.cpp index dea165bccb9..63cf8b66c59 100644 --- a/src/parser/parsed_data/attach_info.cpp +++ b/src/parser/parsed_data/attach_info.cpp @@ -1,7 +1,25 @@ #include "duckdb/parser/parsed_data/attach_info.hpp" +#include "duckdb/parser/keyword_helper.hpp" + +#include "duckdb/storage/storage_info.hpp" +#include "duckdb/common/optional_idx.hpp" namespace duckdb { +optional_idx AttachInfo::GetBlockAllocSize() const { + + for (auto &entry : options) { + if (entry.first == "block_size") { + // Extract the block allocation size. This is NOT the actual memory available on a block (block_size), + // even though the corresponding option we expose to the user is called "block_size". + idx_t block_alloc_size = UBigIntValue::Get(entry.second.DefaultCastAs(LogicalType::UBIGINT)); + Storage::VerifyBlockAllocSize(block_alloc_size); + return block_alloc_size; + } + } + return optional_idx(); +} + unique_ptr AttachInfo::Copy() const { auto result = make_uniq(); result->name = name; @@ -11,4 +29,26 @@ unique_ptr AttachInfo::Copy() const { return result; } +string AttachInfo::ToString() const { + string result = ""; + result += "ATTACH"; + if (on_conflict == OnCreateConflict::IGNORE_ON_CONFLICT) { + result += " IF NOT EXISTS"; + } + result += " DATABASE"; + result += StringUtil::Format(" '%s'", path); + if (!name.empty()) { + result += " AS " + KeywordHelper::WriteOptionallyQuoted(name); + } + if (!options.empty()) { + vector stringified; + for (auto &opt : options) { + stringified.push_back(StringUtil::Format("%s %s", opt.first, opt.second.ToSQLString())); + } + result += " (" + StringUtil::Join(stringified, ", ") + ")"; + } + result += ";"; + return result; +} + } // namespace duckdb diff --git a/src/parser/parsed_data/comment_on_column_info.cpp b/src/parser/parsed_data/comment_on_column_info.cpp index 909990d69d7..4bc3324820b 100644 --- a/src/parser/parsed_data/comment_on_column_info.cpp +++ b/src/parser/parsed_data/comment_on_column_info.cpp @@ -1,5 +1,6 @@ #include "duckdb/parser/parsed_data/comment_on_column_info.hpp" #include "duckdb/catalog/catalog.hpp" +#include "duckdb/catalog/catalog_entry_retriever.hpp" namespace duckdb { @@ -21,8 +22,20 @@ unique_ptr SetColumnCommentInfo::Copy() const { return std::move(result); } -optional_ptr SetColumnCommentInfo::TryResolveCatalogEntry(ClientContext &context) { - auto entry = Catalog::GetEntry(context, CatalogType::TABLE_ENTRY, catalog, schema, name, if_not_found); +string SetColumnCommentInfo::ToString() const { + string result = ""; + + D_ASSERT(catalog_entry_type == CatalogType::INVALID); + result += "COMMENT ON COLUMN "; + result += QualifierToString(catalog, schema, name); + result += " IS "; + result += comment_value.ToSQLString(); + result += ";"; + return result; +} + +optional_ptr SetColumnCommentInfo::TryResolveCatalogEntry(CatalogEntryRetriever &retriever) { + auto entry = retriever.GetEntry(CatalogType::TABLE_ENTRY, catalog, schema, name, if_not_found); if (entry) { catalog_entry_type = entry->type; diff --git a/src/parser/parsed_data/copy_info.cpp b/src/parser/parsed_data/copy_info.cpp new file mode 100644 index 00000000000..c46263a7f00 --- /dev/null +++ b/src/parser/parsed_data/copy_info.cpp @@ -0,0 +1,100 @@ +#include "duckdb/parser/parsed_data/copy_info.hpp" +#include "duckdb/parser/query_node.hpp" + +namespace duckdb { + +unique_ptr CopyInfo::Copy() const { + auto result = make_uniq(); + result->catalog = catalog; + result->schema = schema; + result->table = table; + result->select_list = select_list; + result->file_path = file_path; + result->is_from = is_from; + result->format = format; + result->options = options; + if (select_statement) { + result->select_statement = select_statement->Copy(); + } + return result; +} + +string CopyInfo::CopyOptionsToString(const string &format, const case_insensitive_map_t> &options) { + if (format.empty() && options.empty()) { + return string(); + } + string result; + + result += " ("; + vector stringified; + if (!format.empty()) { + stringified.push_back(StringUtil::Format(" FORMAT %s", format)); + } + for (auto &opt : options) { + auto &name = opt.first; + auto &values = opt.second; + + auto option = name + " "; + if (values.empty()) { + // Options like HEADER don't need an explicit value + // just providing the name already sets it to true + stringified.push_back(option); + } else if (values.size() == 1) { + stringified.push_back(option + values[0].ToSQLString()); + } else { + vector sub_values; + for (auto &val : values) { + sub_values.push_back(val.ToSQLString()); + } + stringified.push_back(option + "( " + StringUtil::Join(sub_values, ", ") + " )"); + } + } + result += StringUtil::Join(stringified, ", "); + result += " )"; + return result; +} + +string CopyInfo::TablePartToString() const { + string result; + + D_ASSERT(!table.empty()); + result += QualifierToString(catalog, schema, table); + + // (c1, c2, ..) + if (!select_list.empty()) { + vector options; + for (auto &option : select_list) { + options.push_back(KeywordHelper::WriteOptionallyQuoted(option)); + } + result += " ("; + result += StringUtil::Join(options, ", "); + result += " )"; + } + return result; +} + +string CopyInfo::ToString() const { + string result = ""; + result += "COPY "; + if (is_from) { + D_ASSERT(!select_statement); + result += TablePartToString(); + result += " FROM"; + result += StringUtil::Format(" %s", SQLString(file_path)); + result += CopyOptionsToString(format, options); + } else { + if (select_statement) { + // COPY (select-node) TO ... + result += "(" + select_statement->ToString() + ")"; + } else { + result += TablePartToString(); + } + result += " TO "; + result += StringUtil::Format("%s", SQLString(file_path)); + result += CopyOptionsToString(format, options); + } + result += ";"; + return result; +} + +} // namespace duckdb diff --git a/src/parser/parsed_data/create_info.cpp b/src/parser/parsed_data/create_info.cpp index a548955b31d..92777cd7f20 100644 --- a/src/parser/parsed_data/create_info.cpp +++ b/src/parser/parsed_data/create_info.cpp @@ -19,7 +19,9 @@ void CreateInfo::CopyProperties(CreateInfo &other) const { other.temporary = temporary; other.internal = internal; other.sql = sql; + other.dependencies = dependencies; other.comment = comment; + other.tags = tags; } unique_ptr CreateInfo::GetAlterInfo() const { diff --git a/src/parser/parsed_data/create_type_info.cpp b/src/parser/parsed_data/create_type_info.cpp index 55834f09885..3c0472c9fd5 100644 --- a/src/parser/parsed_data/create_type_info.cpp +++ b/src/parser/parsed_data/create_type_info.cpp @@ -6,10 +6,11 @@ namespace duckdb { -CreateTypeInfo::CreateTypeInfo() : CreateInfo(CatalogType::TYPE_ENTRY) { +CreateTypeInfo::CreateTypeInfo() : CreateInfo(CatalogType::TYPE_ENTRY), bind_modifiers(nullptr) { } -CreateTypeInfo::CreateTypeInfo(string name_p, LogicalType type_p) - : CreateInfo(CatalogType::TYPE_ENTRY), name(std::move(name_p)), type(std::move(type_p)) { +CreateTypeInfo::CreateTypeInfo(string name_p, LogicalType type_p, bind_type_modifiers_function_t bind_modifiers_p) + : CreateInfo(CatalogType::TYPE_ENTRY), name(std::move(name_p)), type(std::move(type_p)), + bind_modifiers(bind_modifiers_p) { } unique_ptr CreateTypeInfo::Copy() const { @@ -20,6 +21,7 @@ unique_ptr CreateTypeInfo::Copy() const { if (query) { result->query = query->Copy(); } + result->bind_modifiers = bind_modifiers; return std::move(result); } diff --git a/src/parser/parsed_data/detach_info.cpp b/src/parser/parsed_data/detach_info.cpp index 04a8a71ae27..623023157d1 100644 --- a/src/parser/parsed_data/detach_info.cpp +++ b/src/parser/parsed_data/detach_info.cpp @@ -1,4 +1,5 @@ #include "duckdb/parser/parsed_data/detach_info.hpp" +#include "duckdb/parser/keyword_helper.hpp" namespace duckdb { @@ -12,4 +13,15 @@ unique_ptr DetachInfo::Copy() const { return result; } +string DetachInfo::ToString() const { + string result = ""; + result += "DETACH DATABASE"; + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += " " + KeywordHelper::WriteOptionallyQuoted(name); + result += ";"; + return result; +} + } // namespace duckdb diff --git a/src/parser/parsed_data/drop_info.cpp b/src/parser/parsed_data/drop_info.cpp index ce8567504b3..c5db57ddce4 100644 --- a/src/parser/parsed_data/drop_info.cpp +++ b/src/parser/parsed_data/drop_info.cpp @@ -16,4 +16,25 @@ unique_ptr DropInfo::Copy() const { return make_uniq(*this); } +string DropInfo::ToString() const { + string result = ""; + if (type == CatalogType::PREPARED_STATEMENT) { + result += "DEALLOCATE PREPARE "; + result += KeywordHelper::WriteOptionallyQuoted(name); + } else { + result += "DROP"; + result += " " + ParseInfo::TypeToString(type); + if (if_not_found == OnEntryNotFound::RETURN_NULL) { + result += " IF EXISTS"; + } + result += " "; + result += QualifierToString(catalog, schema, name); + if (cascade) { + result += " CASCADE"; + } + } + result += ";"; + return result; +} + } // namespace duckdb diff --git a/src/parser/parsed_data/load_info.cpp b/src/parser/parsed_data/load_info.cpp new file mode 100644 index 00000000000..30142961c70 --- /dev/null +++ b/src/parser/parsed_data/load_info.cpp @@ -0,0 +1,46 @@ +#include "duckdb/parser/parsed_data/load_info.hpp" +#include "duckdb/common/enum_util.hpp" +#include "duckdb/common/string_util.hpp" +#include "duckdb/parser/keyword_helper.hpp" + +namespace duckdb { + +unique_ptr LoadInfo::Copy() const { + auto result = make_uniq(); + result->filename = filename; + result->repository = repository; + result->load_type = load_type; + result->repo_is_alias = repo_is_alias; + return result; +} + +static string LoadInfoToString(LoadType load_type) { + switch (load_type) { + case LoadType::LOAD: + return "LOAD"; + case LoadType::INSTALL: + return "INSTALL"; + case LoadType::FORCE_INSTALL: + return "FORCE INSTALL"; + default: + throw InternalException("ToString for LoadType with type: %s not implemented", EnumUtil::ToString(load_type)); + } +} + +string LoadInfo::ToString() const { + string result = ""; + result += LoadInfoToString(load_type); + result += StringUtil::Format(" '%s'", filename); + if (!repository.empty()) { + if (repo_is_alias) { + result += " FROM " + KeywordHelper::WriteOptionallyQuoted(repository); + } else { + result += " FROM " + KeywordHelper::WriteQuoted(repository); + } + } + + result += ";"; + return result; +} + +} // namespace duckdb diff --git a/src/parser/parsed_data/pragma_info.cpp b/src/parser/parsed_data/pragma_info.cpp new file mode 100644 index 00000000000..3052c44155c --- /dev/null +++ b/src/parser/parsed_data/pragma_info.cpp @@ -0,0 +1,33 @@ +#include "duckdb/parser/parsed_data/pragma_info.hpp" + +namespace duckdb { + +unique_ptr PragmaInfo::Copy() const { + auto result = make_uniq(); + result->name = name; + for (auto ¶m : parameters) { + result->parameters.push_back(param->Copy()); + } + for (auto &entry : named_parameters) { + result->named_parameters.insert(make_pair(entry.first, entry.second->Copy())); + } + return result; +} + +string PragmaInfo::ToString() const { + string result = ""; + result += "PRAGMA"; + // FIXME: Can pragma's live in different catalog/schemas ? + result += " " + KeywordHelper::WriteOptionallyQuoted(name); + if (!parameters.empty()) { + vector stringified; + for (auto ¶m : parameters) { + stringified.push_back(param->ToString()); + } + result += "(" + StringUtil::Join(stringified, ", ") + ")"; + } + result += ";"; + return result; +} + +} // namespace duckdb diff --git a/src/parser/parsed_data/transaction_info.cpp b/src/parser/parsed_data/transaction_info.cpp index d0cc8112218..af102e6e34c 100644 --- a/src/parser/parsed_data/transaction_info.cpp +++ b/src/parser/parsed_data/transaction_info.cpp @@ -1,11 +1,53 @@ #include "duckdb/parser/parsed_data/transaction_info.hpp" +#include "duckdb/common/enum_util.hpp" namespace duckdb { TransactionInfo::TransactionInfo() : ParseInfo(TYPE) { } -TransactionInfo::TransactionInfo(TransactionType type) : ParseInfo(TYPE), type(type) { +TransactionInfo::TransactionInfo(TransactionType type) + : ParseInfo(TYPE), type(type), modifier(TransactionModifierType::TRANSACTION_DEFAULT_MODIFIER) { +} + +string TransactionInfo::ToString() const { + string result = ""; + switch (type) { + case TransactionType::BEGIN_TRANSACTION: + result += "BEGIN"; + break; + case TransactionType::COMMIT: + result += "COMMIT"; + break; + case TransactionType::ROLLBACK: + result += "ROLLBACK"; + break; + default: { + throw InternalException("ToString for TransactionStatement with type: %s not implemented", + EnumUtil::ToString(type)); + } + } + switch (modifier) { + case TransactionModifierType::TRANSACTION_DEFAULT_MODIFIER: + break; + case TransactionModifierType::TRANSACTION_READ_ONLY: + result += " READ ONLY"; + break; + case TransactionModifierType::TRANSACTION_READ_WRITE: + result += " READ WRITE"; + break; + default: + throw InternalException("ToString for TransactionStatement with modifier type: %s not implemented", + EnumUtil::ToString(modifier)); + } + result += ";"; + return result; +} + +unique_ptr TransactionInfo::Copy() const { + auto result = make_uniq(type); + result->modifier = modifier; + return result; } } // namespace duckdb diff --git a/src/parser/parsed_data/vacuum_info.cpp b/src/parser/parsed_data/vacuum_info.cpp index cf8326938e9..7fff15e83ab 100644 --- a/src/parser/parsed_data/vacuum_info.cpp +++ b/src/parser/parsed_data/vacuum_info.cpp @@ -15,4 +15,24 @@ unique_ptr VacuumInfo::Copy() { return result; } +string VacuumInfo::ToString() const { + string result = ""; + result += "VACUUM"; + if (options.analyze) { + result += " ANALYZE"; + } + if (ref) { + result += " " + ref->ToString(); + if (!columns.empty()) { + vector names; + for (auto &column : columns) { + names.push_back(KeywordHelper::WriteOptionallyQuoted(column)); + } + result += "(" + StringUtil::Join(names, ", ") + ")"; + } + } + result += ";"; + return result; +} + } // namespace duckdb diff --git a/src/parser/parsed_expression_iterator.cpp b/src/parser/parsed_expression_iterator.cpp index 50a4669176e..cb2516c7050 100644 --- a/src/parser/parsed_expression_iterator.cpp +++ b/src/parser/parsed_expression_iterator.cpp @@ -242,6 +242,7 @@ void ParsedExpressionIterator::EnumerateTableRefChildren( case TableReferenceType::BASE_TABLE: case TableReferenceType::EMPTY_FROM: case TableReferenceType::SHOW_REF: + case TableReferenceType::COLUMN_DATA: // these TableRefs do not need to be unfolded break; case TableReferenceType::INVALID: diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index 7dd7a43d9f6..65ee319704d 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -1,5 +1,6 @@ #include "duckdb/parser/parser.hpp" +#include "duckdb/parser/group_by_node.hpp" #include "duckdb/parser/parsed_data/create_table_info.hpp" #include "duckdb/parser/parser_extension.hpp" #include "duckdb/parser/query_error_context.hpp" @@ -8,7 +9,6 @@ #include "duckdb/parser/statement/extension_statement.hpp" #include "duckdb/parser/statement/select_statement.hpp" #include "duckdb/parser/statement/update_statement.hpp" -#include "duckdb/parser/group_by_node.hpp" #include "duckdb/parser/tableref/expressionlistref.hpp" #include "duckdb/parser/transformer.hpp" #include "parser/parser.hpp" @@ -42,6 +42,16 @@ static bool ReplaceUnicodeSpaces(const string &query, string &new_query, vector< return true; } +static bool IsValidDollarQuotedStringTagFirstChar(const unsigned char &c) { + // the first character can be between A-Z, a-z, or \200 - \377 + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c >= 0x80; +} + +static bool IsValidDollarQuotedStringTagSubsequentChar(const unsigned char &c) { + // subsequent characters can also be between 0-9 + return IsValidDollarQuotedStringTagFirstChar(c) || (c >= '0' && c <= '9'); +} + // This function strips unicode space characters from the query and replaces them with regular spaces // It returns true if any unicode space characters were found and stripped // See here for a list of unicode space characters - https://jkorpela.fi/chars/spaces.html @@ -50,6 +60,7 @@ bool Parser::StripUnicodeSpaces(const string &query_str, string &new_query) { const idx_t USP_LEN = 3; idx_t pos = 0; unsigned char quote; + string_t dollar_quote_tag; vector unicode_spaces; auto query = const_uchar_ptr_cast(query_str.c_str()); auto qsize = query_str.size(); @@ -95,6 +106,24 @@ bool Parser::StripUnicodeSpaces(const string &query_str, string &new_query) { quote = query[pos]; pos++; goto in_quotes; + } else if (query[pos] == '$' && + (query[pos + 1] == '$' || IsValidDollarQuotedStringTagFirstChar(query[pos + 1]))) { + // (optionally tagged) dollar-quoted string + auto start = &query[++pos]; + for (; pos + 2 < qsize; pos++) { + if (query[pos] == '$') { + // end of tag + dollar_quote_tag = + string_t(const_char_ptr_cast(start), NumericCast(&query[pos] - start)); + goto in_dollar_quotes; + } + + if (!IsValidDollarQuotedStringTagSubsequentChar(query[pos])) { + // invalid char in dollar-quoted string, continue as normal + goto regular; + } + } + goto end; } else if (query[pos] == '-' && query[pos + 1] == '-') { goto in_comment; } @@ -113,6 +142,17 @@ bool Parser::StripUnicodeSpaces(const string &query_str, string &new_query) { } } goto end; +in_dollar_quotes: + for (; pos + 2 < qsize; pos++) { + if (query[pos] == '$' && + qsize - (pos + 1) >= dollar_quote_tag.GetSize() + 1 && // found '$' and enough space left + query[pos + dollar_quote_tag.GetSize() + 1] == '$' && // ending '$' at the right spot + memcmp(&query[pos + 1], dollar_quote_tag.GetData(), dollar_quote_tag.GetSize()) == 0) { // tags match + pos += dollar_quote_tag.GetSize() + 1; + goto regular; + } + } + goto end; in_comment: for (; pos < qsize; pos++) { if (query[pos] == '\n' || query[pos] == '\r') { diff --git a/src/parser/query_node.cpp b/src/parser/query_node.cpp index dab1375faf9..7b084c5c8c7 100644 --- a/src/parser/query_node.cpp +++ b/src/parser/query_node.cpp @@ -24,6 +24,7 @@ CommonTableExpressionMap CommonTableExpressionMap::Copy() const { kv_info->materialized = kv.second->materialized; res.map[kv.first] = std::move(kv_info); } + return res; } @@ -44,6 +45,7 @@ string CommonTableExpressionMap::ToString() const { result += "RECURSIVE "; } bool first_cte = true; + for (auto &kv : map) { if (!first_cte) { result += ", "; @@ -131,15 +133,17 @@ bool QueryNode::Equals(const QueryNode *other) const { if (cte_map.map.size() != other->cte_map.map.size()) { return false; } + for (auto &entry : cte_map.map) { auto other_entry = other->cte_map.map.find(entry.first); if (other_entry == other->cte_map.map.end()) { return false; } - if (entry.second->aliases != other_entry->second->aliases) { + + if (entry.second->aliases != other->cte_map.map.at(entry.first)->aliases) { return false; } - if (!entry.second->query->Equals(*other_entry->second->query)) { + if (!entry.second->query->Equals(*other->cte_map.map.at(entry.first)->query)) { return false; } } diff --git a/src/parser/statement/CMakeLists.txt b/src/parser/statement/CMakeLists.txt index 81ec3aa3d50..4ec1d62c92b 100644 --- a/src/parser/statement/CMakeLists.txt +++ b/src/parser/statement/CMakeLists.txt @@ -24,6 +24,7 @@ add_library_unity( set_statement.cpp transaction_statement.cpp update_statement.cpp + update_extensions_statement.cpp vacuum_statement.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/parser/statement/alter_statement.cpp b/src/parser/statement/alter_statement.cpp index f9a05f08232..e964783cadf 100644 --- a/src/parser/statement/alter_statement.cpp +++ b/src/parser/statement/alter_statement.cpp @@ -12,4 +12,8 @@ unique_ptr AlterStatement::Copy() const { return unique_ptr(new AlterStatement(*this)); } +string AlterStatement::ToString() const { + return info->ToString(); +} + } // namespace duckdb diff --git a/src/parser/statement/attach_statement.cpp b/src/parser/statement/attach_statement.cpp index 0bae08cd087..12958a22b65 100644 --- a/src/parser/statement/attach_statement.cpp +++ b/src/parser/statement/attach_statement.cpp @@ -12,4 +12,8 @@ unique_ptr AttachStatement::Copy() const { return unique_ptr(new AttachStatement(*this)); } +string AttachStatement::ToString() const { + return info->ToString(); +} + } // namespace duckdb diff --git a/src/parser/statement/call_statement.cpp b/src/parser/statement/call_statement.cpp index cd7a2218a5c..646765afa6a 100644 --- a/src/parser/statement/call_statement.cpp +++ b/src/parser/statement/call_statement.cpp @@ -12,4 +12,12 @@ unique_ptr CallStatement::Copy() const { return unique_ptr(new CallStatement(*this)); } +string CallStatement::ToString() const { + string result = ""; + result += "CALL"; + result += " " + function->ToString(); + result += ";"; + return result; +} + } // namespace duckdb diff --git a/src/parser/statement/copy_statement.cpp b/src/parser/statement/copy_statement.cpp index 286787dc12e..5a77447bda9 100644 --- a/src/parser/statement/copy_statement.cpp +++ b/src/parser/statement/copy_statement.cpp @@ -6,95 +6,10 @@ CopyStatement::CopyStatement() : SQLStatement(StatementType::COPY_STATEMENT), in } CopyStatement::CopyStatement(const CopyStatement &other) : SQLStatement(other), info(other.info->Copy()) { - if (other.select_statement) { - select_statement = other.select_statement->Copy(); - } -} - -string CopyStatement::CopyOptionsToString(const string &format, const case_insensitive_map_t> &options) { - if (format.empty() && options.empty()) { - return string(); - } - string result; - - result += " ("; - vector stringified; - if (!format.empty()) { - stringified.push_back(StringUtil::Format(" FORMAT %s", format)); - } - for (auto &opt : options) { - auto &name = opt.first; - auto &values = opt.second; - - auto option = name + " "; - if (values.empty()) { - // Options like HEADER don't need an explicit value - // just providing the name already sets it to true - stringified.push_back(option); - } else if (values.size() == 1) { - stringified.push_back(option + values[0].ToSQLString()); - } else { - vector sub_values; - for (auto &val : values) { - sub_values.push_back(val.ToSQLString()); - } - stringified.push_back(option + "( " + StringUtil::Join(sub_values, ", ") + " )"); - } - } - result += StringUtil::Join(stringified, ", "); - result += " )"; - return result; -} - -// COPY table-name (c1, c2, ..) -string TablePart(const CopyInfo &info) { - string result; - - if (!info.catalog.empty()) { - result += KeywordHelper::WriteOptionallyQuoted(info.catalog) + "."; - } - if (!info.schema.empty()) { - result += KeywordHelper::WriteOptionallyQuoted(info.schema) + "."; - } - D_ASSERT(!info.table.empty()); - result += KeywordHelper::WriteOptionallyQuoted(info.table); - - // (c1, c2, ..) - if (!info.select_list.empty()) { - result += " ("; - for (idx_t i = 0; i < info.select_list.size(); i++) { - if (i > 0) { - result += ", "; - } - result += KeywordHelper::WriteOptionallyQuoted(info.select_list[i]); - } - result += " )"; - } - return result; } string CopyStatement::ToString() const { - string result; - - result += "COPY "; - if (info->is_from) { - D_ASSERT(!select_statement); - result += TablePart(*info); - result += " FROM"; - result += StringUtil::Format(" %s", SQLString(info->file_path)); - result += CopyOptionsToString(info->format, info->options); - } else { - if (select_statement) { - // COPY (select-node) TO ... - result += "(" + select_statement->ToString() + ")"; - } else { - result += TablePart(*info); - } - result += " TO "; - result += StringUtil::Format("%s", SQLString(info->file_path)); - result += CopyOptionsToString(info->format, info->options); - } - return result; + return info->ToString(); } unique_ptr CopyStatement::Copy() const { diff --git a/src/parser/statement/detach_statement.cpp b/src/parser/statement/detach_statement.cpp index 1ca52f71bc5..0239e9403dd 100644 --- a/src/parser/statement/detach_statement.cpp +++ b/src/parser/statement/detach_statement.cpp @@ -12,4 +12,8 @@ unique_ptr DetachStatement::Copy() const { return unique_ptr(new DetachStatement(*this)); } +string DetachStatement::ToString() const { + return info->ToString(); +} + } // namespace duckdb diff --git a/src/parser/statement/drop_statement.cpp b/src/parser/statement/drop_statement.cpp index 7bf363f3fd4..b1ad8fd690d 100644 --- a/src/parser/statement/drop_statement.cpp +++ b/src/parser/statement/drop_statement.cpp @@ -12,4 +12,8 @@ unique_ptr DropStatement::Copy() const { return unique_ptr(new DropStatement(*this)); } +string DropStatement::ToString() const { + return info->ToString(); +} + } // namespace duckdb diff --git a/src/parser/statement/execute_statement.cpp b/src/parser/statement/execute_statement.cpp index 2a2fa13163e..b052b71b9e0 100644 --- a/src/parser/statement/execute_statement.cpp +++ b/src/parser/statement/execute_statement.cpp @@ -15,4 +15,19 @@ unique_ptr ExecuteStatement::Copy() const { return unique_ptr(new ExecuteStatement(*this)); } +string ExecuteStatement::ToString() const { + string result = ""; + result += "EXECUTE"; + result += " " + name; + if (!named_values.empty()) { + vector stringified; + for (auto &val : named_values) { + stringified.push_back(StringUtil::Format("\"%s\" := %s", val.first, val.second->ToString())); + } + result += "(" + StringUtil::Join(stringified, ", ") + ")"; + } + result += ";"; + return result; +} + } // namespace duckdb diff --git a/src/parser/statement/explain_statement.cpp b/src/parser/statement/explain_statement.cpp index 2ad08fecb4f..8ab2b94e3ea 100644 --- a/src/parser/statement/explain_statement.cpp +++ b/src/parser/statement/explain_statement.cpp @@ -1,4 +1,5 @@ #include "duckdb/parser/statement/explain_statement.hpp" +#include "duckdb/common/enum_util.hpp" namespace duckdb { @@ -14,4 +15,22 @@ unique_ptr ExplainStatement::Copy() const { return unique_ptr(new ExplainStatement(*this)); } +static string ExplainTypeToString(ExplainType type) { + switch (type) { + case ExplainType::EXPLAIN_STANDARD: + return "EXPLAIN"; + case ExplainType::EXPLAIN_ANALYZE: + return "EXPLAIN ANALYZE"; + default: + throw InternalException("ToString for ExplainType with type: %s not implemented", EnumUtil::ToString(type)); + } +} + +string ExplainStatement::ToString() const { + string result = ""; + result += ExplainTypeToString(explain_type); + result += " " + stmt->ToString(); + return result; +} + } // namespace duckdb diff --git a/src/parser/statement/export_statement.cpp b/src/parser/statement/export_statement.cpp index e4b7f07be28..2b2e0c831f4 100644 --- a/src/parser/statement/export_statement.cpp +++ b/src/parser/statement/export_statement.cpp @@ -1,4 +1,6 @@ #include "duckdb/parser/statement/export_statement.hpp" +#include "duckdb/parser/parsed_data/copy_info.hpp" +#include "duckdb/parser/query_node.hpp" namespace duckdb { @@ -14,4 +16,20 @@ unique_ptr ExportStatement::Copy() const { return unique_ptr(new ExportStatement(*this)); } +string ExportStatement::ToString() const { + string result = ""; + result += "EXPORT DATABASE"; + if (!database.empty()) { + result += " " + database + " TO"; + } + auto &path = info->file_path; + D_ASSERT(info->is_from == false); + auto &options = info->options; + auto &format = info->format; + result += StringUtil::Format(" '%s'", path); + result += CopyInfo::CopyOptionsToString(format, options); + result += ";"; + return result; +} + } // namespace duckdb diff --git a/src/parser/statement/extension_statement.cpp b/src/parser/statement/extension_statement.cpp index 22d6dec1642..ac0e66f5536 100644 --- a/src/parser/statement/extension_statement.cpp +++ b/src/parser/statement/extension_statement.cpp @@ -11,4 +11,8 @@ unique_ptr ExtensionStatement::Copy() const { return make_uniq(extension, parse_data->Copy()); } +string ExtensionStatement::ToString() const { + return parse_data->ToString(); +} + } // namespace duckdb diff --git a/src/parser/statement/load_statement.cpp b/src/parser/statement/load_statement.cpp index da59355c2fd..8ab6e37ad68 100644 --- a/src/parser/statement/load_statement.cpp +++ b/src/parser/statement/load_statement.cpp @@ -12,4 +12,8 @@ unique_ptr LoadStatement::Copy() const { return unique_ptr(new LoadStatement(*this)); } +string LoadStatement::ToString() const { + return info->ToString(); +} + } // namespace duckdb diff --git a/src/parser/statement/multi_statement.cpp b/src/parser/statement/multi_statement.cpp index 3daea30f002..2821084cdd1 100644 --- a/src/parser/statement/multi_statement.cpp +++ b/src/parser/statement/multi_statement.cpp @@ -15,4 +15,12 @@ unique_ptr MultiStatement::Copy() const { return unique_ptr(new MultiStatement(*this)); } +string MultiStatement::ToString() const { + vector stringified; + for (auto &stmt : statements) { + stringified.push_back(stmt->ToString()); + } + return StringUtil::Join(stringified, ";") + ";"; +} + } // namespace duckdb diff --git a/src/parser/statement/pragma_statement.cpp b/src/parser/statement/pragma_statement.cpp index 7c083b292e7..b15034568ff 100644 --- a/src/parser/statement/pragma_statement.cpp +++ b/src/parser/statement/pragma_statement.cpp @@ -12,4 +12,8 @@ unique_ptr PragmaStatement::Copy() const { return unique_ptr(new PragmaStatement(*this)); } +string PragmaStatement::ToString() const { + return info->ToString(); +} + } // namespace duckdb diff --git a/src/parser/statement/prepare_statement.cpp b/src/parser/statement/prepare_statement.cpp index 5e50dfc30c9..69c8ba9e7df 100644 --- a/src/parser/statement/prepare_statement.cpp +++ b/src/parser/statement/prepare_statement.cpp @@ -13,4 +13,17 @@ unique_ptr PrepareStatement::Copy() const { return unique_ptr(new PrepareStatement(*this)); } +string PrepareStatement::ToString() const { + string result = ""; + result += "PREPARE"; + result += " "; + result += name; + result += " "; + result += "AS"; + result += " "; + result += statement->ToString(); + // NOTE: We expect SQLStatement->ToString() to always end in a ';' ^ + return result; +} + } // namespace duckdb diff --git a/src/parser/statement/relation_statement.cpp b/src/parser/statement/relation_statement.cpp index 50721ee3fa9..3fd5ade1241 100644 --- a/src/parser/statement/relation_statement.cpp +++ b/src/parser/statement/relation_statement.cpp @@ -10,4 +10,8 @@ unique_ptr RelationStatement::Copy() const { return unique_ptr(new RelationStatement(*this)); } +string RelationStatement::ToString() const { + return relation->ToString(); +} + } // namespace duckdb diff --git a/src/parser/statement/set_statement.cpp b/src/parser/statement/set_statement.cpp index fd98ab6acc3..a487421d999 100644 --- a/src/parser/statement/set_statement.cpp +++ b/src/parser/statement/set_statement.cpp @@ -1,4 +1,5 @@ #include "duckdb/parser/statement/set_statement.hpp" +#include "duckdb/common/enum_util.hpp" namespace duckdb { @@ -6,10 +7,6 @@ SetStatement::SetStatement(std::string name_p, SetScope scope_p, SetType type_p) : SQLStatement(StatementType::SET_STATEMENT), name(std::move(name_p)), scope(scope_p), set_type(type_p) { } -unique_ptr SetStatement::Copy() const { - return unique_ptr(new SetStatement(*this)); -} - // Set Variable SetVariableStatement::SetVariableStatement(std::string name_p, unique_ptr value_p, SetScope scope_p) @@ -24,10 +21,42 @@ unique_ptr SetVariableStatement::Copy() const { return unique_ptr(new SetVariableStatement(*this)); } +static string ScopeToString(SetScope scope) { + switch (scope) { + case SetScope::AUTOMATIC: + return ""; + case SetScope::LOCAL: + return "LOCAL"; + case SetScope::SESSION: + return "SESSION"; + case SetScope::GLOBAL: + return "GLOBAL"; + default: + throw InternalException("ToString not implemented for SetScope of type: %s", EnumUtil::ToString(scope)); + } +} + +string SetVariableStatement::ToString() const { + return StringUtil::Format("SET %s %s TO %s;", ScopeToString(scope), name, value->ToString()); +} + // Reset Variable ResetVariableStatement::ResetVariableStatement(std::string name_p, SetScope scope_p) : SetStatement(std::move(name_p), scope_p, SetType::RESET) { } +unique_ptr ResetVariableStatement::Copy() const { + return unique_ptr(new ResetVariableStatement(*this)); +} + +string ResetVariableStatement::ToString() const { + string result = ""; + result += "RESET"; + result += " " + ScopeToString(scope); + result += " " + name; + result += ";"; + return result; +} + } // namespace duckdb diff --git a/src/parser/statement/transaction_statement.cpp b/src/parser/statement/transaction_statement.cpp index 6903ab84585..f1098536bb5 100644 --- a/src/parser/statement/transaction_statement.cpp +++ b/src/parser/statement/transaction_statement.cpp @@ -2,16 +2,20 @@ namespace duckdb { -TransactionStatement::TransactionStatement(TransactionType type) - : SQLStatement(StatementType::TRANSACTION_STATEMENT), info(make_uniq(type)) { +TransactionStatement::TransactionStatement(unique_ptr info) + : SQLStatement(StatementType::TRANSACTION_STATEMENT), info(std::move(info)) { } TransactionStatement::TransactionStatement(const TransactionStatement &other) - : SQLStatement(other), info(make_uniq(other.info->type)) { + : SQLStatement(other), info(other.info->Copy()) { } unique_ptr TransactionStatement::Copy() const { return unique_ptr(new TransactionStatement(*this)); } +string TransactionStatement::ToString() const { + return info->ToString(); +} + } // namespace duckdb diff --git a/src/parser/statement/update_extensions_statement.cpp b/src/parser/statement/update_extensions_statement.cpp new file mode 100644 index 00000000000..73fea01d686 --- /dev/null +++ b/src/parser/statement/update_extensions_statement.cpp @@ -0,0 +1,34 @@ +#include "duckdb/parser/statement/update_extensions_statement.hpp" + +namespace duckdb { + +UpdateExtensionsStatement::UpdateExtensionsStatement() : SQLStatement(StatementType::UPDATE_EXTENSIONS_STATEMENT) { +} + +UpdateExtensionsStatement::UpdateExtensionsStatement(const UpdateExtensionsStatement &other) + : SQLStatement(other), info(other.info->Copy()) { +} + +string UpdateExtensionsStatement::ToString() const { + string result; + result += "UPDATE EXTENSIONS"; + + if (!info->extensions_to_update.empty()) { + result += "("; + for (idx_t i = 0; i < info->extensions_to_update.size(); i++) { + if (i > 0) { + result += ", "; + } + result += info->extensions_to_update[i]; + } + result += ")"; + } + + return result; +} + +unique_ptr UpdateExtensionsStatement::Copy() const { + return unique_ptr(new UpdateExtensionsStatement(*this)); +} + +} // namespace duckdb diff --git a/src/parser/statement/vacuum_statement.cpp b/src/parser/statement/vacuum_statement.cpp index 5596acf8537..e78f422b802 100644 --- a/src/parser/statement/vacuum_statement.cpp +++ b/src/parser/statement/vacuum_statement.cpp @@ -13,4 +13,8 @@ unique_ptr VacuumStatement::Copy() const { return unique_ptr(new VacuumStatement(*this)); } +string VacuumStatement::ToString() const { + return info->ToString(); +} + } // namespace duckdb diff --git a/src/parser/tableref.cpp b/src/parser/tableref.cpp index 3d72020f59e..f8b8db70cd0 100644 --- a/src/parser/tableref.cpp +++ b/src/parser/tableref.cpp @@ -48,6 +48,7 @@ void TableRef::CopyProperties(TableRef &target) const { target.alias = alias; target.query_location = query_location; target.sample = sample ? sample->Copy() : nullptr; + target.external_dependency = external_dependency; } void TableRef::Print() { diff --git a/src/parser/tableref/CMakeLists.txt b/src/parser/tableref/CMakeLists.txt index d1f1fccd3e4..dc3fbaae397 100644 --- a/src/parser/tableref/CMakeLists.txt +++ b/src/parser/tableref/CMakeLists.txt @@ -4,6 +4,7 @@ add_library_unity( basetableref.cpp emptytableref.cpp expressionlistref.cpp + column_data_ref.cpp joinref.cpp pivotref.cpp showref.cpp diff --git a/src/parser/tableref/column_data_ref.cpp b/src/parser/tableref/column_data_ref.cpp new file mode 100644 index 00000000000..e815451dfdb --- /dev/null +++ b/src/parser/tableref/column_data_ref.cpp @@ -0,0 +1,81 @@ +#include "duckdb/parser/tableref/column_data_ref.hpp" +#include "duckdb/common/string_util.hpp" + +#include "duckdb/common/serializer/serializer.hpp" +#include "duckdb/common/serializer/deserializer.hpp" + +namespace duckdb { + +string ColumnDataRef::ToString() const { + auto result = collection->ToString(); + return BaseToString(result, expected_names); +} + +bool ColumnDataRef::Equals(const TableRef &other_p) const { + if (!TableRef::Equals(other_p)) { + return false; + } + auto &other = other_p.Cast(); + auto expected_types = collection->Types(); + auto other_expected_types = other.collection->Types(); + if (expected_types.size() != other_expected_types.size()) { + return false; + } + if (expected_names.size() != other.expected_names.size()) { + return false; + } + D_ASSERT(expected_types.size() == expected_names.size()); + for (idx_t i = 0; i < expected_types.size(); i++) { + auto &this_type = expected_types[i]; + auto &other_type = other_expected_types[i]; + + auto &this_name = expected_names[i]; + auto &other_name = other.expected_names[i]; + + if (this_type != other_type) { + return false; + } + if (!StringUtil::CIEquals(this_name, other_name)) { + return false; + } + } + string unused; + if (!ColumnDataCollection::ResultEquals(*collection, *other.collection, unused, true)) { + return false; + } + return true; +} + +unique_ptr ColumnDataRef::Copy() { + unique_ptr result; + if (collection.is_owned()) { + // This collection is owned, the copy should be self sufficient so it needs a copy + auto new_collection = make_uniq(*collection); + + DataChunk chunk; + collection->InitializeScanChunk(chunk); + + ColumnDataScanState scan_state; + collection->InitializeScan(scan_state); + + ColumnDataAppendState append_state; + new_collection->InitializeAppend(append_state); + while (collection->Scan(scan_state, chunk)) { + new_collection->Append(append_state, chunk); + } +#ifdef DEBUG + string error_message; + if (!ColumnDataCollection::ResultEquals(*collection, *new_collection, error_message, true)) { + throw InternalException("Copied ColumnDataCollection was not equal: %s", error_message); + } +#endif + result = make_uniq(expected_names, std::move(new_collection)); + } else { + result = make_uniq(*collection); + } + result->expected_names = expected_names; + CopyProperties(*result); + return std::move(result); +} + +} // namespace duckdb diff --git a/src/parser/transform/constraint/transform_constraint.cpp b/src/parser/transform/constraint/transform_constraint.cpp index ef601ac47f2..dcb467e9cd1 100644 --- a/src/parser/transform/constraint/transform_constraint.cpp +++ b/src/parser/transform/constraint/transform_constraint.cpp @@ -5,16 +5,12 @@ namespace duckdb { -static void ParseSchemaTableNameFK(duckdb_libpgquery::PGRangeVar *input, ForeignKeyInfo &fk_info) { - if (input->catalogname) { +static void ParseSchemaTableNameFK(duckdb_libpgquery::PGRangeVar &input, ForeignKeyInfo &fk_info) { + if (input.catalogname) { throw ParserException("FOREIGN KEY constraints cannot be defined cross-database"); } - if (input->schemaname) { - fk_info.schema = input->schemaname; - } else { - fk_info.schema = ""; - }; - fk_info.table = input->relname; + fk_info.schema = input.schemaname ? input.schemaname : ""; + fk_info.table = input.relname; } static bool ForeignKeyActionSupported(char action) { @@ -33,28 +29,34 @@ static bool ForeignKeyActionSupported(char action) { } static unique_ptr -TransformForeignKeyConstraint(duckdb_libpgquery::PGConstraint *constraint, +TransformForeignKeyConstraint(duckdb_libpgquery::PGConstraint &constraint, optional_ptr override_fk_column = nullptr) { - D_ASSERT(constraint); - if (!ForeignKeyActionSupported(constraint->fk_upd_action) || - !ForeignKeyActionSupported(constraint->fk_del_action)) { + if (!ForeignKeyActionSupported(constraint.fk_upd_action) || !ForeignKeyActionSupported(constraint.fk_del_action)) { throw ParserException("FOREIGN KEY constraints cannot use CASCADE, SET NULL or SET DEFAULT"); } + ForeignKeyInfo fk_info; fk_info.type = ForeignKeyType::FK_TYPE_FOREIGN_KEY_TABLE; - ParseSchemaTableNameFK(constraint->pktable, fk_info); - vector pk_columns, fk_columns; + ParseSchemaTableNameFK(*constraint.pktable, fk_info); + + vector pk_columns; + vector fk_columns; + if (override_fk_column) { - D_ASSERT(!constraint->fk_attrs); + D_ASSERT(!constraint.fk_attrs); fk_columns.emplace_back(*override_fk_column); - } else if (constraint->fk_attrs) { - for (auto kc = constraint->fk_attrs->head; kc; kc = kc->next) { - fk_columns.emplace_back(reinterpret_cast(kc->data.ptr_value)->val.str); + + } else if (constraint.fk_attrs) { + for (auto kc = constraint.fk_attrs->head; kc; kc = kc->next) { + auto value = Transformer::PGPointerCast(kc->data.ptr_value); + fk_columns.emplace_back(value->val.str); } } - if (constraint->pk_attrs) { - for (auto kc = constraint->pk_attrs->head; kc; kc = kc->next) { - pk_columns.emplace_back(reinterpret_cast(kc->data.ptr_value)->val.str); + + if (constraint.pk_attrs) { + for (auto kc = constraint.pk_attrs->head; kc; kc = kc->next) { + auto value = Transformer::PGPointerCast(kc->data.ptr_value); + pk_columns.emplace_back(value->val.str); } } if (!pk_columns.empty() && pk_columns.size() != fk_columns.size()) { @@ -66,9 +68,11 @@ TransformForeignKeyConstraint(duckdb_libpgquery::PGConstraint *constraint, return make_uniq(pk_columns, fk_columns, std::move(fk_info)); } -unique_ptr Transformer::TransformConstraint(duckdb_libpgquery::PGListCell *cell) { - auto constraint = reinterpret_cast(cell->data.ptr_value); +unique_ptr Transformer::TransformConstraint(duckdb_libpgquery::PGListCell &cell) { + + auto constraint = PGPointerCast(cell.data.ptr_value); D_ASSERT(constraint); + switch (constraint->contype) { case duckdb_libpgquery::PG_CONSTR_UNIQUE: case duckdb_libpgquery::PG_CONSTR_PRIMARY: { @@ -78,7 +82,8 @@ unique_ptr Transformer::TransformConstraint(duckdb_libpgquery::PGLis } vector columns; for (auto kc = constraint->keys->head; kc; kc = kc->next) { - columns.emplace_back(reinterpret_cast(kc->data.ptr_value)->val.str); + auto value = PGPointerCast(kc->data.ptr_value); + columns.emplace_back(value->val.str); } return make_uniq(columns, is_primary_key); } @@ -90,17 +95,18 @@ unique_ptr Transformer::TransformConstraint(duckdb_libpgquery::PGLis return make_uniq(TransformExpression(constraint->raw_expr)); } case duckdb_libpgquery::PG_CONSTR_FOREIGN: - return TransformForeignKeyConstraint(constraint); - + return TransformForeignKeyConstraint(*constraint.get()); default: throw NotImplementedException("Constraint type not handled yet!"); } } -unique_ptr Transformer::TransformConstraint(duckdb_libpgquery::PGListCell *cell, ColumnDefinition &column, +unique_ptr Transformer::TransformConstraint(duckdb_libpgquery::PGListCell &cell, ColumnDefinition &column, idx_t index) { - auto constraint = reinterpret_cast(cell->data.ptr_value); + + auto constraint = PGPointerCast(cell.data.ptr_value); D_ASSERT(constraint); + switch (constraint->contype) { case duckdb_libpgquery::PG_CONSTR_NOTNULL: return make_uniq(LogicalIndex(index)); @@ -133,7 +139,7 @@ unique_ptr Transformer::TransformConstraint(duckdb_libpgquery::PGLis } return nullptr; case duckdb_libpgquery::PG_CONSTR_FOREIGN: - return TransformForeignKeyConstraint(constraint, &column.Name()); + return TransformForeignKeyConstraint(*constraint.get(), &column.Name()); default: throw NotImplementedException("Constraint not implemented!"); } diff --git a/src/parser/transform/expression/transform_array_access.cpp b/src/parser/transform/expression/transform_array_access.cpp index 88571c047ac..b5d149d5392 100644 --- a/src/parser/transform/expression/transform_array_access.cpp +++ b/src/parser/transform/expression/transform_array_access.cpp @@ -7,71 +7,71 @@ namespace duckdb { unique_ptr Transformer::TransformArrayAccess(duckdb_libpgquery::PGAIndirection &indirection_node) { - // transform the source expression + + // Transform the source expression. unique_ptr result; result = TransformExpression(indirection_node.arg); - // now go over the indices - // note that a single indirection node can contain multiple indices - // this happens for e.g. more complex accesses (e.g. (foo).field1[42]) + // Iterate the indices. + // For more complex expressions like (foo).field_name[42] a single indirection + // node can contain multiple indices. idx_t list_size = 0; for (auto node = indirection_node.indirection->head; node != nullptr; node = node->next) { - auto target = reinterpret_cast(node->data.ptr_value); - D_ASSERT(target); + auto target = PGPointerCast(node->data.ptr_value); switch (target->type) { case duckdb_libpgquery::T_PGAIndices: { - // index access (either slice or extract) - auto index = PGPointerCast(target); + // Index access. + auto indices = PGCast(*target.get()); vector> children; children.push_back(std::move(result)); - if (index->is_slice) { - // slice - // if either the lower or upper bound is not specified, we use an empty const list so that we can - // handle it in the execution - unique_ptr lower = - index->lidx ? TransformExpression(index->lidx) - : make_uniq(Value::LIST(LogicalType::INTEGER, vector())); + + if (indices.is_slice) { + // If either the lower or upper bound is not specified, we use an empty constant LIST, + // which we handle in the execution. + auto constant_list = make_uniq(Value::LIST(LogicalType::INTEGER, vector())); + + auto lower = indices.lidx ? TransformExpression(indices.lidx) : constant_list->Copy(); children.push_back(std::move(lower)); - unique_ptr upper = - index->uidx ? TransformExpression(index->uidx) - : make_uniq(Value::LIST(LogicalType::INTEGER, vector())); + auto upper = indices.uidx ? TransformExpression(indices.uidx) : constant_list->Copy(); children.push_back(std::move(upper)); - if (index->step) { - children.push_back(TransformExpression(index->step)); + + if (indices.step) { + children.push_back(TransformExpression(indices.step)); } result = make_uniq(ExpressionType::ARRAY_SLICE, std::move(children)); - } else { - // array access - D_ASSERT(!index->lidx); - D_ASSERT(index->uidx); - children.push_back(TransformExpression(index->uidx)); - result = make_uniq(ExpressionType::ARRAY_EXTRACT, std::move(children)); + break; } + + // Array access. + D_ASSERT(!indices.lidx && indices.uidx); + children.push_back(TransformExpression(indices.uidx)); + result = make_uniq(ExpressionType::ARRAY_EXTRACT, std::move(children)); break; } case duckdb_libpgquery::T_PGString: { - auto val = PGPointerCast(target); + auto value = PGCast(*target.get()); vector> children; children.push_back(std::move(result)); - children.push_back(TransformValue(*val)); + children.push_back(TransformValue(value)); result = make_uniq(ExpressionType::STRUCT_EXTRACT, std::move(children)); break; } case duckdb_libpgquery::T_PGFuncCall: { - auto func = PGPointerCast(target); - auto function = TransformFuncCall(*func); + auto func = PGCast(*target.get()); + auto function = TransformFuncCall(func); if (function->type != ExpressionType::FUNCTION) { throw ParserException("%s.%s() call must be a function", result->ToString(), function->ToString()); } - auto &f = function->Cast(); - f.children.insert(f.children.begin(), std::move(result)); + auto &function_expr = function->Cast(); + function_expr.children.insert(function_expr.children.begin(), std::move(result)); result = std::move(function); break; } default: throw NotImplementedException("Unimplemented subscript type"); } + list_size++; StackCheck(list_size); } diff --git a/src/parser/transform/expression/transform_columnref.cpp b/src/parser/transform/expression/transform_columnref.cpp index b93ff1a3095..7137169f8ad 100644 --- a/src/parser/transform/expression/transform_columnref.cpp +++ b/src/parser/transform/expression/transform_columnref.cpp @@ -43,7 +43,7 @@ unique_ptr Transformer::TransformStarExpression(duckdb_libpgqu D_ASSERT(result->exclude_list.empty()); D_ASSERT(result->replace_list.empty()); result->expr = TransformExpression(star.expr); - if (result->expr->type == ExpressionType::STAR) { + if (StarExpression::IsStar(*result->expr)) { auto &child_star = result->expr->Cast(); result->relation_name = child_star.relation_name; result->exclude_list = std::move(child_star.exclude_list); @@ -58,6 +58,7 @@ unique_ptr Transformer::TransformStarExpression(duckdb_libpgqu } } result->columns = star.columns; + result->unpacked = star.unpacked; SetQueryLocation(*result, star.location); return std::move(result); } diff --git a/src/parser/transform/expression/transform_function.cpp b/src/parser/transform/expression/transform_function.cpp index 9b9019b67b8..16c50fa70a5 100644 --- a/src/parser/transform/expression/transform_function.cpp +++ b/src/parser/transform/expression/transform_function.cpp @@ -27,6 +27,11 @@ void Transformer::TransformWindowDef(duckdb_libpgquery::PGWindowDef &window_spec throw ParserException("Cannot override ORDER BY clause of window \"%s\"", window_name); } TransformOrderBy(window_spec.orderClause, expr.orders); + for (auto &order : expr.orders) { + if (order.expression->GetExpressionType() == ExpressionType::STAR) { + throw ParserException("Cannot ORDER BY ALL in a window expression"); + } + } } } diff --git a/src/parser/transform/expression/transform_interval.cpp b/src/parser/transform/expression/transform_interval.cpp index 50450f5fe46..421ebde9376 100644 --- a/src/parser/transform/expression/transform_interval.cpp +++ b/src/parser/transform/expression/transform_interval.cpp @@ -34,7 +34,7 @@ unique_ptr Transformer::TransformInterval(duckdb_libpgquery::P int32_t mask = NumericCast( PGPointerCast(node.typmods->head->data.ptr_value)->val.val.ival); - // these seemingly random constants are from datetime.hpp + // these seemingly random constants are from libpg_query/include/utils/datetime.hpp // they are copied here to avoid having to include this header // the bitshift is from the function INTERVAL_MASK in the parser constexpr int32_t MONTH_MASK = 1 << 1; @@ -49,6 +49,7 @@ unique_ptr Transformer::TransformInterval(duckdb_libpgquery::P constexpr int32_t DECADE_MASK = 1 << 25; constexpr int32_t CENTURY_MASK = 1 << 26; constexpr int32_t MILLENNIUM_MASK = 1 << 27; + constexpr int32_t QUARTER_MASK = 1 << 29; // we need to check certain combinations // because certain interval masks (e.g. INTERVAL '10' HOURS TO DAYS) set multiple bits @@ -115,6 +116,10 @@ unique_ptr Transformer::TransformInterval(duckdb_libpgquery::P // WEEK fname = "to_weeks"; target_type = LogicalType::INTEGER; + } else if (mask & QUARTER_MASK) { + // QUARTER + fname = "to_quarters"; + target_type = LogicalType::INTEGER; } else if (mask & DECADE_MASK) { // DECADE fname = "to_decades"; diff --git a/src/parser/transform/expression/transform_multi_assign_reference.cpp b/src/parser/transform/expression/transform_multi_assign_reference.cpp index 658e617ab4b..28dc623f330 100644 --- a/src/parser/transform/expression/transform_multi_assign_reference.cpp +++ b/src/parser/transform/expression/transform_multi_assign_reference.cpp @@ -4,41 +4,43 @@ namespace duckdb { unique_ptr Transformer::TransformMultiAssignRef(duckdb_libpgquery::PGMultiAssignRef &root) { - // Multi assignment for the ROW function - if (root.source->type == duckdb_libpgquery::T_PGFuncCall) { - auto func = PGCast(*root.source); - - // Explicitly only allow ROW function - char const *function_name = - PGPointerCast(func.funcname->tail->data.ptr_value)->val.str; - if (function_name == nullptr || strlen(function_name) != 3 || strncmp(function_name, "row", 3) != 0) { - return TransformExpression(root.source); - } - - int provided_values = func.args ? func.args->length : 0; - // Too many columns (ie. (x, y) = (1, 2, 3) ) - if (root.ncolumns < provided_values || !func.args) { - throw ParserException( - "Could not perform multiple assignment, target only expects %d values, %d were provided", root.ncolumns, - provided_values); - } - // Get the expression corresponding with the current column - idx_t idx = 1; - auto list = func.args->head; - while (list && idx < static_cast(root.colno)) { - list = list->next; - ++idx; - } - - // Not enough columns (ie. (x, y, z) = (1, 2) ) - if (!list) { - throw ParserException( - "Could not perform multiple assignment, target expects %d values, only %d were provided", root.ncolumns, - func.args->length); - } - return TransformExpression(reinterpret_cast(list->data.ptr_value)); + + // Early-out, if the root is not a function call. + if (root.source->type != duckdb_libpgquery::T_PGFuncCall) { + return TransformExpression(root.source); + } + + auto func = PGCast(*root.source); + + // Only allow ROW function. + auto function = PGPointerCast(func.funcname->tail->data.ptr_value); + char const *function_name = function->val.str; + if (!function_name || !StringUtil::CIEquals(function_name, "row")) { + return TransformExpression(root.source); + } + + // Too many columns, e.g., (x, y) != (1, 2, 3). + int64_t value_count = func.args ? func.args->length : 0; + if (int64_t(root.ncolumns) < value_count || !func.args) { + throw ParserException("Could not perform assignment, expected %d values, got %d", root.ncolumns, value_count); } - return TransformExpression(root.source); + + // Get the expression corresponding with the current column. + int64_t idx = 1; + auto list = func.args->head; + while (list && idx < int64_t(root.colno)) { + list = list->next; + ++idx; + } + + // Not enough columns, e.g., (x, y, z) != (1, 2). + if (!list) { + throw ParserException("Could not perform assignment, expected %d values, got %d", root.ncolumns, + func.args->length); + } + + auto node = PGPointerCast(list->data.ptr_value); + return TransformExpression(node); } } // namespace duckdb diff --git a/src/parser/transform/expression/transform_subquery.cpp b/src/parser/transform/expression/transform_subquery.cpp index c8dbe23a48c..2a06d5907e9 100644 --- a/src/parser/transform/expression/transform_subquery.cpp +++ b/src/parser/transform/expression/transform_subquery.cpp @@ -4,9 +4,23 @@ #include "duckdb/parser/tableref/subqueryref.hpp" #include "duckdb/parser/expression/constant_expression.hpp" #include "duckdb/parser/expression/positional_reference_expression.hpp" +#include "duckdb/parser/parsed_expression_iterator.hpp" namespace duckdb { +void RemoveOrderQualificationRecursive(unique_ptr &expr) { + if (expr->GetExpressionType() == ExpressionType::COLUMN_REF) { + auto &col_ref = expr->Cast(); + auto &col_names = col_ref.column_names; + if (col_names.size() > 1) { + col_names = vector {col_names.back()}; + } + } else { + ParsedExpressionIterator::EnumerateChildren( + *expr, [](unique_ptr &child) { RemoveOrderQualificationRecursive(child); }); + } +} + unique_ptr Transformer::TransformSubquery(duckdb_libpgquery::PGSubLink &root) { auto subquery_expr = make_uniq(); @@ -90,6 +104,8 @@ unique_ptr Transformer::TransformSubquery(duckdb_libpgquery::P idx_t positional_index = order_index < 0 ? NumericLimits::Maximum() : idx_t(order_index); order.expression = make_uniq(positional_index); } + } else { + RemoveOrderQualificationRecursive(order.expression); } } } diff --git a/src/parser/transform/helpers/nodetype_to_string.cpp b/src/parser/transform/helpers/nodetype_to_string.cpp index 14563286672..ed9e2e37fb7 100644 --- a/src/parser/transform/helpers/nodetype_to_string.cpp +++ b/src/parser/transform/helpers/nodetype_to_string.cpp @@ -458,6 +458,8 @@ std::string Transformer::NodetypeToString(duckdb_libpgquery::PGNodeTag type) { / return "T_DeleteStmt"; case duckdb_libpgquery::T_PGUpdateStmt: return "T_UpdateStmt"; + case duckdb_libpgquery::T_PGUpdateExtensionsStmt: + return "T_UpdateExtensionsStmt"; case duckdb_libpgquery::T_PGSelectStmt: return "T_SelectStmt"; case duckdb_libpgquery::T_PGAlterTableStmt: diff --git a/src/parser/transform/helpers/transform_alias.cpp b/src/parser/transform/helpers/transform_alias.cpp index 637e94a5aac..5f0ef56e9c4 100644 --- a/src/parser/transform/helpers/transform_alias.cpp +++ b/src/parser/transform/helpers/transform_alias.cpp @@ -8,7 +8,8 @@ vector Transformer::TransformStringList(duckdb_libpgquery::PGList *list) return result; } for (auto node = list->head; node != nullptr; node = node->next) { - result.emplace_back(reinterpret_cast(node->data.ptr_value)->val.str); + auto value = PGPointerCast(node->data.ptr_value); + result.emplace_back(value->val.str); } return result; } diff --git a/src/parser/transform/helpers/transform_cte.cpp b/src/parser/transform/helpers/transform_cte.cpp index c4678bdd98f..a481dac2483 100644 --- a/src/parser/transform/helpers/transform_cte.cpp +++ b/src/parser/transform/helpers/transform_cte.cpp @@ -42,8 +42,8 @@ void Transformer::TransformCTE(duckdb_libpgquery::PGWithClause &de_with_clause, auto &cte = *PGPointerCast(cte_ele->data.ptr_value); if (cte.aliascolnames) { for (auto node = cte.aliascolnames->head; node != nullptr; node = node->next) { - info->aliases.emplace_back( - reinterpret_cast(node->data.ptr_value)->val.str); + auto value = PGPointerCast(node->data.ptr_value); + info->aliases.emplace_back(value->val.str); } } // lets throw some errors on unsupported features early diff --git a/src/parser/transform/helpers/transform_orderby.cpp b/src/parser/transform/helpers/transform_orderby.cpp index d448e11400e..0feec0eadc0 100644 --- a/src/parser/transform/helpers/transform_orderby.cpp +++ b/src/parser/transform/helpers/transform_orderby.cpp @@ -1,7 +1,7 @@ #include "duckdb/parser/expression/constant_expression.hpp" +#include "duckdb/parser/expression/star_expression.hpp" #include "duckdb/parser/statement/select_statement.hpp" #include "duckdb/parser/transformer.hpp" -#include "duckdb/parser/expression/star_expression.hpp" namespace duckdb { @@ -11,35 +11,38 @@ bool Transformer::TransformOrderBy(duckdb_libpgquery::PGList *order, vectorhead; node != nullptr; node = node->next) { - auto temp = reinterpret_cast(node->data.ptr_value); - if (temp->type == duckdb_libpgquery::T_PGSortBy) { - OrderType type; - OrderByNullType null_order; - auto sort = reinterpret_cast(temp); - auto target = sort->node; - if (sort->sortby_dir == duckdb_libpgquery::PG_SORTBY_DEFAULT) { - type = OrderType::ORDER_DEFAULT; - } else if (sort->sortby_dir == duckdb_libpgquery::PG_SORTBY_ASC) { - type = OrderType::ASCENDING; - } else if (sort->sortby_dir == duckdb_libpgquery::PG_SORTBY_DESC) { - type = OrderType::DESCENDING; - } else { - throw NotImplementedException("Unimplemented order by type"); - } - if (sort->sortby_nulls == duckdb_libpgquery::PG_SORTBY_NULLS_DEFAULT) { - null_order = OrderByNullType::ORDER_DEFAULT; - } else if (sort->sortby_nulls == duckdb_libpgquery::PG_SORTBY_NULLS_FIRST) { - null_order = OrderByNullType::NULLS_FIRST; - } else if (sort->sortby_nulls == duckdb_libpgquery::PG_SORTBY_NULLS_LAST) { - null_order = OrderByNullType::NULLS_LAST; - } else { - throw NotImplementedException("Unimplemented order by type"); - } - auto order_expression = TransformExpression(target); - result.emplace_back(type, null_order, std::move(order_expression)); + auto temp_node = PGPointerCast(node->data.ptr_value); + if (temp_node->type != duckdb_libpgquery::T_PGSortBy) { + throw NotImplementedException("ORDER BY list member type %d\n", temp_node->type); + } + + OrderType type; + OrderByNullType null_order; + auto sort = PGCast(*temp_node.get()); + auto target = sort.node; + + if (sort.sortby_dir == duckdb_libpgquery::PG_SORTBY_DEFAULT) { + type = OrderType::ORDER_DEFAULT; + } else if (sort.sortby_dir == duckdb_libpgquery::PG_SORTBY_ASC) { + type = OrderType::ASCENDING; + } else if (sort.sortby_dir == duckdb_libpgquery::PG_SORTBY_DESC) { + type = OrderType::DESCENDING; } else { - throw NotImplementedException("ORDER BY list member type %d\n", temp->type); + throw NotImplementedException("Unimplemented order by type"); } + + if (sort.sortby_nulls == duckdb_libpgquery::PG_SORTBY_NULLS_DEFAULT) { + null_order = OrderByNullType::ORDER_DEFAULT; + } else if (sort.sortby_nulls == duckdb_libpgquery::PG_SORTBY_NULLS_FIRST) { + null_order = OrderByNullType::NULLS_FIRST; + } else if (sort.sortby_nulls == duckdb_libpgquery::PG_SORTBY_NULLS_LAST) { + null_order = OrderByNullType::NULLS_LAST; + } else { + throw NotImplementedException("Unimplemented order by type"); + } + + auto order_expression = TransformExpression(target); + result.emplace_back(type, null_order, std::move(order_expression)); } return true; } diff --git a/src/parser/transform/helpers/transform_typename.cpp b/src/parser/transform/helpers/transform_typename.cpp index 01c1697107e..e3cab9205f6 100644 --- a/src/parser/transform/helpers/transform_typename.cpp +++ b/src/parser/transform/helpers/transform_typename.cpp @@ -5,9 +5,72 @@ #include "duckdb/parser/transformer.hpp" #include "duckdb/common/types/decimal.hpp" #include "duckdb/common/types/vector.hpp" +#include "duckdb/parser/expression/constant_expression.hpp" namespace duckdb { +struct SizeModifiers { + int64_t width = 0; + int64_t scale = 0; + // How many modifiers were found + idx_t count = 0; +}; + +static SizeModifiers GetSizeModifiers(duckdb_libpgquery::PGTypeName &type_name, LogicalTypeId base_type) { + + SizeModifiers result; + + if (base_type == LogicalTypeId::DECIMAL) { + // Defaults for DECIMAL + result.width = 18; + result.scale = 3; + } + + if (type_name.typmods) { + for (auto node = type_name.typmods->head; node; node = node->next) { + auto &const_val = *Transformer::PGPointerCast(node->data.ptr_value); + if (const_val.type != duckdb_libpgquery::T_PGAConst || + const_val.val.type != duckdb_libpgquery::T_PGInteger) { + throw ParserException("Expected an integer constant as type modifier"); + } + if (const_val.val.val.ival < 0) { + throw ParserException("Negative modifier not supported"); + } + if (result.count == 0) { + result.width = const_val.val.val.ival; + if (base_type == LogicalTypeId::BIT && const_val.location != -1) { + result.width = 0; + } + } else if (result.count == 1) { + result.scale = const_val.val.val.ival; + } else { + throw ParserException("A maximum of two modifiers is supported"); + } + result.count++; + } + } + return result; +} + +vector Transformer::TransformTypeModifiers(duckdb_libpgquery::PGTypeName &type_name) { + vector type_mods; + if (type_name.typmods) { + for (auto node = type_name.typmods->head; node; node = node->next) { + if (type_mods.size() > 9) { + auto name = PGPointerCast(type_name.names->tail->data.ptr_value)->val.str; + throw ParserException("'%s': a maximum of 9 type modifiers is allowed", name); + } + auto &const_val = *PGPointerCast(node->data.ptr_value); + if (const_val.type != duckdb_libpgquery::T_PGAConst) { + throw ParserException("Expected a constant as type modifier"); + } + auto const_expr = TransformValue(const_val.val); + type_mods.push_back(std::move(const_expr->value)); + } + } + return type_mods; +} + LogicalType Transformer::TransformTypeName(duckdb_libpgquery::PGTypeName &type_name) { if (type_name.type != duckdb_libpgquery::T_PGTypeName) { throw ParserException("Expected a type"); @@ -20,11 +83,13 @@ LogicalType Transformer::TransformTypeName(duckdb_libpgquery::PGTypeName &type_n for (auto cell = type_name.names->head; cell; cell = cell->next) { names.push_back(PGPointerCast(cell->data.ptr_value)->val.str); } + vector type_mods = TransformTypeModifiers(type_name); switch (type_name.names->length) { case 2: - return LogicalType::USER(INVALID_CATALOG, std::move(names[0]), std::move(names[1])); + return LogicalType::USER(INVALID_CATALOG, std::move(names[0]), std::move(names[1]), std::move(type_mods)); case 3: - return LogicalType::USER(std::move(names[0]), std::move(names[1]), std::move(names[2])); + return LogicalType::USER(std::move(names[0]), std::move(names[1]), std::move(names[2]), + std::move(type_mods)); default: throw ParserException( "Too many qualifications for type name - expected [catalog.schema.name] or [schema.name]"); @@ -131,97 +196,66 @@ LogicalType Transformer::TransformTypeName(duckdb_libpgquery::PGTypeName &type_n } D_ASSERT(!children.empty()); result_type = LogicalType::UNION(std::move(children)); + } else if (base_type == LogicalTypeId::USER) { + string user_type_name {name}; + vector type_mods = TransformTypeModifiers(type_name); + result_type = LogicalType::USER(user_type_name, type_mods); } else { - idx_t width, scale; - if (base_type == LogicalTypeId::DECIMAL) { - // default decimal width/scale - width = 18; - scale = 3; - } else { - width = 0; - scale = 0; - } - // check any modifiers - int modifier_idx = 0; - if (type_name.typmods) { - for (auto node = type_name.typmods->head; node; node = node->next) { - auto &const_val = *PGPointerCast(node->data.ptr_value); - if (const_val.type != duckdb_libpgquery::T_PGAConst || - const_val.val.type != duckdb_libpgquery::T_PGInteger) { - throw ParserException("Expected an integer constant as type modifier"); - } - if (const_val.val.val.ival < 0) { - throw ParserException("Negative modifier not supported"); - } - if (modifier_idx == 0) { - width = NumericCast(const_val.val.val.ival); - if (base_type == LogicalTypeId::BIT && const_val.location != -1) { - width = 0; - } - } else if (modifier_idx == 1) { - scale = NumericCast(const_val.val.val.ival); - } else { - throw ParserException("A maximum of two modifiers is supported"); - } - modifier_idx++; - } - } + SizeModifiers modifiers = GetSizeModifiers(type_name, base_type); switch (base_type) { case LogicalTypeId::VARCHAR: - if (modifier_idx > 1) { + if (modifiers.count > 1) { throw ParserException("VARCHAR only supports a single modifier"); } // FIXME: create CHECK constraint based on varchar width - width = 0; + modifiers.width = 0; result_type = LogicalType::VARCHAR; break; case LogicalTypeId::DECIMAL: - if (modifier_idx == 1) { + if (modifiers.count > 2) { + throw ParserException("DECIMAL only supports a maximum of two modifiers"); + } + if (modifiers.count == 1) { // only width is provided: set scale to 0 - scale = 0; + modifiers.scale = 0; } - if (width <= 0 || width > Decimal::MAX_WIDTH_DECIMAL) { + if (modifiers.width <= 0 || modifiers.width > Decimal::MAX_WIDTH_DECIMAL) { throw ParserException("Width must be between 1 and %d!", (int)Decimal::MAX_WIDTH_DECIMAL); } - if (scale > width) { + if (modifiers.scale > modifiers.width) { throw ParserException("Scale cannot be bigger than width"); } - result_type = LogicalType::DECIMAL(NumericCast(width), NumericCast(scale)); + result_type = + LogicalType::DECIMAL(NumericCast(modifiers.width), NumericCast(modifiers.scale)); break; case LogicalTypeId::INTERVAL: - if (modifier_idx > 1) { + if (modifiers.count > 1) { throw ParserException("INTERVAL only supports a single modifier"); } - width = 0; + modifiers.width = 0; result_type = LogicalType::INTERVAL; break; - case LogicalTypeId::USER: { - string user_type_name {name}; - result_type = LogicalType::USER(user_type_name); - break; - } - case LogicalTypeId::BIT: { - if (!width && type_name.typmods) { + case LogicalTypeId::BIT: + if (!modifiers.width && type_name.typmods) { throw ParserException("Type %s does not support any modifiers!", LogicalType(base_type).ToString()); } result_type = LogicalType(base_type); break; - } case LogicalTypeId::TIMESTAMP: - if (modifier_idx == 0) { + if (modifiers.count == 0) { result_type = LogicalType::TIMESTAMP; } else { - if (modifier_idx > 1) { + if (modifiers.count > 1) { throw ParserException("TIMESTAMP only supports a single modifier"); } - if (width > 10) { + if (modifiers.width > 10) { throw ParserException("TIMESTAMP only supports until nano-second precision (9)"); } - if (width == 0) { + if (modifiers.width == 0) { result_type = LogicalType::TIMESTAMP_S; - } else if (width <= 3) { + } else if (modifiers.width <= 3) { result_type = LogicalType::TIMESTAMP_MS; - } else if (width <= 6) { + } else if (modifiers.width <= 6) { result_type = LogicalType::TIMESTAMP; } else { result_type = LogicalType::TIMESTAMP_NS; @@ -229,7 +263,7 @@ LogicalType Transformer::TransformTypeName(duckdb_libpgquery::PGTypeName &type_n } break; default: - if (modifier_idx > 0) { + if (modifiers.count > 0) { throw ParserException("Type %s does not support any modifiers!", LogicalType(base_type).ToString()); } result_type = LogicalType(base_type); diff --git a/src/parser/transform/statement/transform_alter_table.cpp b/src/parser/transform/statement/transform_alter_table.cpp index cd2fc7fc406..d3b57c8e2e4 100644 --- a/src/parser/transform/statement/transform_alter_table.cpp +++ b/src/parser/transform/statement/transform_alter_table.cpp @@ -11,47 +11,47 @@ OnEntryNotFound Transformer::TransformOnEntryNotFound(bool missing_ok) { } unique_ptr Transformer::TransformAlter(duckdb_libpgquery::PGAlterTableStmt &stmt) { - D_ASSERT(stmt.relation); + D_ASSERT(stmt.relation); if (stmt.cmds->length != 1) { throw ParserException("Only one ALTER command per statement is supported"); } auto result = make_uniq(); - auto qname = TransformQualifiedName(*stmt.relation); + auto qualified_name = TransformQualifiedName(*stmt.relation); - // first we check the type of ALTER + // Check the ALTER type. for (auto c = stmt.cmds->head; c != nullptr; c = c->next) { - auto command = reinterpret_cast(lfirst(c)); - AlterEntryData data(qname.catalog, qname.schema, qname.name, TransformOnEntryNotFound(stmt.missing_ok)); - // TODO: Include more options for command->subtype + + auto command = PGPointerCast(c->data.ptr_value); + AlterEntryData data(qualified_name.catalog, qualified_name.schema, qualified_name.name, + TransformOnEntryNotFound(stmt.missing_ok)); + switch (command->subtype) { case duckdb_libpgquery::PG_AT_AddColumn: { - auto cdef = PGPointerCast(command->def); - + auto column_def = PGPointerCast(command->def); if (stmt.relkind != duckdb_libpgquery::PG_OBJECT_TABLE) { throw ParserException("Adding columns is only supported for tables"); } - if (cdef->category == duckdb_libpgquery::COL_GENERATED) { + if (column_def->category == duckdb_libpgquery::COL_GENERATED) { throw ParserException("Adding generated columns after table creation is not supported yet"); } - auto centry = TransformColumnDefinition(*cdef); - if (cdef->constraints) { - for (auto constr = cdef->constraints->head; constr != nullptr; constr = constr->next) { - auto constraint = TransformConstraint(constr, centry, 0); + auto column_entry = TransformColumnDefinition(*column_def); + if (column_def->constraints) { + for (auto constr = column_def->constraints->head; constr != nullptr; constr = constr->next) { + auto constraint = TransformConstraint(*constr, column_entry, 0); if (!constraint) { continue; } throw ParserException("Adding columns with constraints not yet supported"); } } - result->info = make_uniq(std::move(data), std::move(centry), command->missing_ok); + result->info = make_uniq(std::move(data), std::move(column_entry), command->missing_ok); break; } case duckdb_libpgquery::PG_AT_DropColumn: { - bool cascade = command->behavior == duckdb_libpgquery::PG_DROP_CASCADE; - + auto cascade = command->behavior == duckdb_libpgquery::PG_DROP_CASCADE; if (stmt.relkind != duckdb_libpgquery::PG_OBJECT_TABLE) { throw ParserException("Dropping columns is only supported for tables"); } @@ -60,7 +60,6 @@ unique_ptr Transformer::TransformAlter(duckdb_libpgquery::PGAlte } case duckdb_libpgquery::PG_AT_ColumnDefault: { auto expr = TransformExpression(command->def); - if (stmt.relkind != duckdb_libpgquery::PG_OBJECT_TABLE) { throw ParserException("Alter column's default is only supported for tables"); } @@ -68,21 +67,21 @@ unique_ptr Transformer::TransformAlter(duckdb_libpgquery::PGAlte break; } case duckdb_libpgquery::PG_AT_AlterColumnType: { - auto cdef = PGPointerCast(command->def); - auto column_definition = TransformColumnDefinition(*cdef); - unique_ptr expr; + auto column_def = PGPointerCast(command->def); + auto column_entry = TransformColumnDefinition(*column_def); + unique_ptr expr; if (stmt.relkind != duckdb_libpgquery::PG_OBJECT_TABLE) { throw ParserException("Alter column's type is only supported for tables"); } - if (cdef->raw_default) { - expr = TransformExpression(cdef->raw_default); + if (column_def->raw_default) { + expr = TransformExpression(column_def->raw_default); } else { - auto colref = make_uniq(command->name); - expr = make_uniq(column_definition.Type(), std::move(colref)); + auto col_ref = make_uniq(command->name); + expr = make_uniq(column_entry.Type(), std::move(col_ref)); } - result->info = make_uniq(std::move(data), command->name, column_definition.Type(), - std::move(expr)); + result->info = + make_uniq(std::move(data), command->name, column_entry.Type(), std::move(expr)); break; } case duckdb_libpgquery::PG_AT_SetNotNull: { @@ -98,7 +97,6 @@ unique_ptr Transformer::TransformAlter(duckdb_libpgquery::PGAlte throw NotImplementedException("No support for that ALTER TABLE option yet!"); } } - return result; } diff --git a/src/parser/transform/statement/transform_checkpoint.cpp b/src/parser/transform/statement/transform_checkpoint.cpp index e52d1df21b3..6f8fded60d8 100644 --- a/src/parser/transform/statement/transform_checkpoint.cpp +++ b/src/parser/transform/statement/transform_checkpoint.cpp @@ -11,6 +11,8 @@ unique_ptr Transformer::TransformCheckpoint(duckdb_libpgquery::PGC auto checkpoint_name = stmt.force ? "force_checkpoint" : "checkpoint"; auto result = make_uniq(); auto function = make_uniq(checkpoint_name, std::move(children)); + function->catalog = SYSTEM_CATALOG; + function->schema = DEFAULT_SCHEMA; if (stmt.name) { function->children.push_back(make_uniq(Value(stmt.name))); } diff --git a/src/parser/transform/statement/transform_copy.cpp b/src/parser/transform/statement/transform_copy.cpp index 909ab168b58..5da207ddcac 100644 --- a/src/parser/transform/statement/transform_copy.cpp +++ b/src/parser/transform/statement/transform_copy.cpp @@ -117,7 +117,7 @@ unique_ptr Transformer::TransformCopy(duckdb_libpgquery::PGCopySt info.schema = table.schema_name; info.catalog = table.catalog_name; } else { - result->select_statement = TransformSelectNode(*PGPointerCast(stmt.query)); + info.select_statement = TransformSelectNode(*PGPointerCast(stmt.query)); } // handle the different options of the COPY statement diff --git a/src/parser/transform/statement/transform_create_table.cpp b/src/parser/transform/statement/transform_create_table.cpp index f1ac88eb71a..e0177e4fac8 100644 --- a/src/parser/transform/statement/transform_create_table.cpp +++ b/src/parser/transform/statement/transform_create_table.cpp @@ -1,9 +1,9 @@ -#include "duckdb/parser/statement/create_statement.hpp" -#include "duckdb/parser/parsed_data/create_table_info.hpp" -#include "duckdb/parser/transformer.hpp" +#include "duckdb/catalog/catalog_entry/table_column_type.hpp" #include "duckdb/parser/constraint.hpp" #include "duckdb/parser/expression/collate_expression.hpp" -#include "duckdb/catalog/catalog_entry/table_column_type.hpp" +#include "duckdb/parser/parsed_data/create_table_info.hpp" +#include "duckdb/parser/statement/create_statement.hpp" +#include "duckdb/parser/transformer.hpp" namespace duckdb { @@ -101,7 +101,7 @@ unique_ptr Transformer::TransformCreateTable(duckdb_libpgquery: auto centry = TransformColumnDefinition(*cdef); if (cdef->constraints) { for (auto constr = cdef->constraints->head; constr != nullptr; constr = constr->next) { - auto constraint = TransformConstraint(constr, centry, info->columns.LogicalColumnCount()); + auto constraint = TransformConstraint(*constr, centry, info->columns.LogicalColumnCount()); if (constraint) { info->constraints.push_back(std::move(constraint)); } @@ -112,7 +112,7 @@ unique_ptr Transformer::TransformCreateTable(duckdb_libpgquery: break; } case duckdb_libpgquery::T_PGConstraint: { - info->constraints.push_back(TransformConstraint(c)); + info->constraints.push_back(TransformConstraint(*c)); break; } default: diff --git a/src/parser/transform/statement/transform_load.cpp b/src/parser/transform/statement/transform_load.cpp index 4e8ec950036..50ef37837e8 100644 --- a/src/parser/transform/statement/transform_load.cpp +++ b/src/parser/transform/statement/transform_load.cpp @@ -8,8 +8,10 @@ unique_ptr Transformer::TransformLoad(duckdb_libpgquery::PGLoadSt auto load_stmt = make_uniq(); auto load_info = make_uniq(); - load_info->filename = std::string(stmt.filename); - load_info->repository = std::string(stmt.repository); + load_info->filename = stmt.filename ? string(stmt.filename) : ""; + load_info->repository = stmt.repository ? string(stmt.repository) : ""; + load_info->repo_is_alias = stmt.repo_is_alias; + load_info->version = stmt.version ? string(stmt.version) : ""; switch (stmt.load_type) { case duckdb_libpgquery::PG_LOAD_TYPE_LOAD: load_info->load_type = LoadType::LOAD; diff --git a/src/parser/transform/statement/transform_transaction.cpp b/src/parser/transform/statement/transform_transaction.cpp index e35bf9ac17f..ba4c04527ae 100644 --- a/src/parser/transform/statement/transform_transaction.cpp +++ b/src/parser/transform/statement/transform_transaction.cpp @@ -3,18 +3,39 @@ namespace duckdb { -unique_ptr Transformer::TransformTransaction(duckdb_libpgquery::PGTransactionStmt &stmt) { - switch (stmt.kind) { +TransactionType TransformTransactionType(duckdb_libpgquery::PGTransactionStmtKind kind) { + switch (kind) { case duckdb_libpgquery::PG_TRANS_STMT_BEGIN: case duckdb_libpgquery::PG_TRANS_STMT_START: - return make_uniq(TransactionType::BEGIN_TRANSACTION); + return TransactionType::BEGIN_TRANSACTION; case duckdb_libpgquery::PG_TRANS_STMT_COMMIT: - return make_uniq(TransactionType::COMMIT); + return TransactionType::COMMIT; case duckdb_libpgquery::PG_TRANS_STMT_ROLLBACK: - return make_uniq(TransactionType::ROLLBACK); + return TransactionType::ROLLBACK; + default: + throw NotImplementedException("Transaction type %d not implemented yet", kind); + } +} + +TransactionModifierType TransformTransactionModifier(duckdb_libpgquery::PGTransactionStmtType type) { + switch (type) { + case duckdb_libpgquery::PG_TRANS_TYPE_DEFAULT: + return TransactionModifierType::TRANSACTION_DEFAULT_MODIFIER; + case duckdb_libpgquery::PG_TRANS_TYPE_READ_ONLY: + return TransactionModifierType::TRANSACTION_READ_ONLY; + case duckdb_libpgquery::PG_TRANS_TYPE_READ_WRITE: + return TransactionModifierType::TRANSACTION_READ_WRITE; default: - throw NotImplementedException("Transaction type %d not implemented yet", stmt.kind); + throw NotImplementedException("Transaction modifier %d not implemented yet", type); } } +unique_ptr Transformer::TransformTransaction(duckdb_libpgquery::PGTransactionStmt &stmt) { + // stmt.transaction_type + auto type = TransformTransactionType(stmt.kind); + auto info = make_uniq(type); + info->modifier = TransformTransactionModifier(stmt.transaction_type); + return make_uniq(std::move(info)); +} + } // namespace duckdb diff --git a/src/parser/transform/statement/transform_update.cpp b/src/parser/transform/statement/transform_update.cpp index 6d7048355e1..9f5951d02c4 100644 --- a/src/parser/transform/statement/transform_update.cpp +++ b/src/parser/transform/statement/transform_update.cpp @@ -1,3 +1,4 @@ +#include "duckdb/parser/statement/update_extensions_statement.hpp" #include "duckdb/parser/statement/update_statement.hpp" #include "duckdb/parser/transformer.hpp" @@ -6,13 +7,14 @@ namespace duckdb { unique_ptr Transformer::TransformUpdateSetInfo(duckdb_libpgquery::PGList *target_list, duckdb_libpgquery::PGNode *where_clause) { auto result = make_uniq(); - auto root = target_list; + for (auto cell = root->head; cell != nullptr; cell = cell->next) { auto target = PGPointerCast(cell->data.ptr_value); result->columns.emplace_back(target->name); result->expressions.push_back(TransformExpression(target->val)); } + result->condition = TransformExpression(where_clause); return result; } @@ -20,21 +22,37 @@ unique_ptr Transformer::TransformUpdateSetInfo(duckdb_libpgquery: unique_ptr Transformer::TransformUpdate(duckdb_libpgquery::PGUpdateStmt &stmt) { auto result = make_uniq(); if (stmt.withClause) { - TransformCTE(*PGPointerCast(stmt.withClause), result->cte_map); + auto with_clause = PGPointerCast(stmt.withClause); + TransformCTE(*with_clause, result->cte_map); } result->table = TransformRangeVar(*stmt.relation); if (stmt.fromClause) { result->from_table = TransformFrom(stmt.fromClause); } - result->set_info = TransformUpdateSetInfo(stmt.targetList, stmt.whereClause); // Grab and transform the returning columns from the parser. if (stmt.returningList) { TransformExpressionList(*stmt.returningList, result->returning_list); } + return result; +} + +unique_ptr +Transformer::TransformUpdateExtensions(duckdb_libpgquery::PGUpdateExtensionsStmt &stmt) { + auto result = make_uniq(); + auto info = make_uniq(); + + if (stmt.extensions) { + auto column_list = PGPointerCast(stmt.extensions); + for (auto c = column_list->head; c != nullptr; c = c->next) { + auto value = PGPointerCast(c->data.ptr_value); + info->extensions_to_update.emplace_back(value->val.str); + } + } + result->info = std::move(info); return result; } diff --git a/src/parser/transform/statement/transform_upsert.cpp b/src/parser/transform/statement/transform_upsert.cpp index 3c550cb083b..aa0130f3c82 100644 --- a/src/parser/transform/statement/transform_upsert.cpp +++ b/src/parser/transform/statement/transform_upsert.cpp @@ -1,5 +1,4 @@ #include "duckdb/parser/statement/insert_statement.hpp" -#include "duckdb/parser/statement/update_statement.hpp" #include "duckdb/parser/tableref/expressionlistref.hpp" #include "duckdb/parser/transformer.hpp" @@ -67,23 +66,23 @@ unique_ptr Transformer::DummyOnConflictClause(duckdb_libpgquery: } unique_ptr Transformer::TransformOnConflictClause(duckdb_libpgquery::PGOnConflictClause *node, - const string &relname) { - auto stmt = reinterpret_cast(node); + const string &) { + + auto stmt = PGPointerCast(node); D_ASSERT(stmt); auto result = make_uniq(); - result->action_type = TransformOnConflictAction(stmt); + result->action_type = TransformOnConflictAction(stmt.get()); + if (stmt->infer) { - // A filter for the ON CONFLICT ... is specified - if (stmt->infer->indexElems) { - // Columns are specified - result->indexed_columns = TransformConflictTarget(*stmt->infer->indexElems); - if (stmt->infer->whereClause) { - result->condition = TransformExpression(stmt->infer->whereClause); - } - } else { + // A filter for the ON CONFLICT ... is specified. + if (!stmt->infer->indexElems) { throw NotImplementedException("ON CONSTRAINT conflict target is not supported yet"); } + result->indexed_columns = TransformConflictTarget(*stmt->infer->indexElems); + if (stmt->infer->whereClause) { + result->condition = TransformExpression(stmt->infer->whereClause); + } } if (result->action_type == OnConflictAction::UPDATE) { diff --git a/src/parser/transform/statement/transform_vacuum.cpp b/src/parser/transform/statement/transform_vacuum.cpp index c61934cca7c..e18dedad134 100644 --- a/src/parser/transform/statement/transform_vacuum.cpp +++ b/src/parser/transform/statement/transform_vacuum.cpp @@ -3,7 +3,7 @@ namespace duckdb { -VacuumOptions ParseOptions(int options) { +VacuumOptions ParseOptions(const int32_t options) { VacuumOptions result; if (options & duckdb_libpgquery::PGVacuumOption::PG_VACOPT_VACUUM) { result.vacuum = true; @@ -43,8 +43,8 @@ unique_ptr Transformer::TransformVacuum(duckdb_libpgquery::PGVacuu if (stmt.va_cols) { D_ASSERT(result->info->has_table); for (auto col_node = stmt.va_cols->head; col_node != nullptr; col_node = col_node->next) { - result->info->columns.emplace_back( - reinterpret_cast(col_node->data.ptr_value)->val.str); + auto value = PGPointerCast(col_node->data.ptr_value); + result->info->columns.emplace_back(value->val.str); } } return std::move(result); diff --git a/src/parser/transform/tableref/transform_join.cpp b/src/parser/transform/tableref/transform_join.cpp index 9c60ec244b4..5aa6637ea78 100644 --- a/src/parser/transform/tableref/transform_join.cpp +++ b/src/parser/transform/tableref/transform_join.cpp @@ -39,14 +39,14 @@ unique_ptr Transformer::TransformJoin(duckdb_libpgquery::PGJoinExpr &r result->ref_type = JoinRefType::POSITIONAL; break; } - default: { + default: throw NotImplementedException("Join type %d not supported\n", root.jointype); } - } - // Check the type of left arg and right arg before transform + // Check the type of the left and right argument before transforming. result->left = TransformTableRefNode(*root.larg); result->right = TransformTableRefNode(*root.rarg); + switch (root.joinreftype) { case duckdb_libpgquery::PG_JOIN_NATURAL: result->ref_type = JoinRefType::NATURAL; @@ -57,32 +57,38 @@ unique_ptr Transformer::TransformJoin(duckdb_libpgquery::PGJoinExpr &r default: break; } + SetQueryLocation(*result, root.location); if (root.usingClause && root.usingClause->length > 0) { - // usingClause is a list of strings + // usingClause is a list of strings. for (auto node = root.usingClause->head; node != nullptr; node = node->next) { - auto target = reinterpret_cast(node->data.ptr_value); + auto target = PGPointerCast(node->data.ptr_value); D_ASSERT(target->type == duckdb_libpgquery::T_PGString); - auto column_name = string(reinterpret_cast(target)->val.str); - result->using_columns.push_back(column_name); + auto value = PGCast(*target.get()); + result->using_columns.push_back(string(value.val.str)); } return std::move(result); } - if (!root.quals && result->using_columns.empty() && result->ref_type == JoinRefType::REGULAR) { // CROSS PRODUCT + // Check if this is a cross product. + if (!root.quals && result->using_columns.empty() && result->ref_type == JoinRefType::REGULAR) { result->ref_type = JoinRefType::CROSS; } result->condition = TransformExpression(root.quals); + if (root.alias) { - // join with an alias - wrap it in a subquery + // This is a join with an alias, so we wrap it in a subquery. auto select_node = make_uniq(); select_node->select_list.push_back(make_uniq()); select_node->from_table = std::move(result); + auto select = make_uniq(); select->node = std::move(select_node); + auto subquery = make_uniq(std::move(select)); SetQueryLocation(*subquery, root.location); - // apply the alias to that subquery + + // Apply the alias to the subquery. subquery->alias = TransformAlias(root.alias, subquery->column_name_alias); return std::move(subquery); } diff --git a/src/parser/transformer.cpp b/src/parser/transformer.cpp index f12e0d17882..b713f3c2c3e 100644 --- a/src/parser/transformer.cpp +++ b/src/parser/transformer.cpp @@ -163,6 +163,8 @@ unique_ptr Transformer::TransformStatementInternal(duckdb_libpgque return TransformDelete(PGCast(stmt)); case duckdb_libpgquery::T_PGUpdateStmt: return TransformUpdate(PGCast(stmt)); + case duckdb_libpgquery::T_PGUpdateExtensionsStmt: + return TransformUpdateExtensions(PGCast(stmt)); case duckdb_libpgquery::T_PGIndexStmt: return TransformCreateIndex(PGCast(stmt)); case duckdb_libpgquery::T_PGAlterTableStmt: @@ -225,6 +227,7 @@ unique_ptr Transformer::TransformStatementInternal(duckdb_libpgque unique_ptr Transformer::TransformMaterializedCTE(unique_ptr root) { // Extract materialized CTEs from cte_map vector> materialized_ctes; + for (auto &cte : root->cte_map.map) { auto &cte_entry = cte.second; if (cte_entry->materialized == CTEMaterialize::CTE_MATERIALIZE_ALWAYS) { diff --git a/src/planner/CMakeLists.txt b/src/planner/CMakeLists.txt index 19f4c28a075..7530b87644a 100644 --- a/src/planner/CMakeLists.txt +++ b/src/planner/CMakeLists.txt @@ -10,6 +10,7 @@ add_library_unity( OBJECT bound_result_modifier.cpp bound_parameter_map.cpp + collation_binding.cpp expression_iterator.cpp expression.cpp table_binding.cpp diff --git a/src/planner/binder.cpp b/src/planner/binder.cpp index 66d0949ddd5..7de9d98bd89 100644 --- a/src/planner/binder.cpp +++ b/src/planner/binder.cpp @@ -17,6 +17,7 @@ #include "duckdb/planner/operator/logical_sample.hpp" #include "duckdb/parser/query_node/list.hpp" #include "duckdb/common/helper.hpp" +#include "duckdb/common/enum_util.hpp" #include @@ -40,26 +41,27 @@ idx_t Binder::GetBinderDepth() const { return depth; } -shared_ptr Binder::CreateBinder(ClientContext &context, optional_ptr parent, bool inherit_ctes) { +shared_ptr Binder::CreateBinder(ClientContext &context, optional_ptr parent, BinderType binder_type) { auto depth = parent ? parent->GetBinderDepth() : 0; if (depth > context.config.max_expression_depth) { throw BinderException("Max expression depth limit of %lld exceeded. Use \"SET max_expression_depth TO x\" to " "increase the maximum expression depth.", context.config.max_expression_depth); } - return make_shared_ptr(true, context, parent ? parent->shared_from_this() : nullptr, inherit_ctes); + return make_shared_ptr(true, context, parent ? parent->shared_from_this() : nullptr, binder_type); } -Binder::Binder(bool, ClientContext &context, shared_ptr parent_p, bool inherit_ctes_p) - : context(context), bind_context(*this), parent(std::move(parent_p)), bound_tables(0), - inherit_ctes(inherit_ctes_p) { +Binder::Binder(bool, ClientContext &context, shared_ptr parent_p, BinderType binder_type) + : context(context), bind_context(*this), parent(std::move(parent_p)), bound_tables(0), binder_type(binder_type), + entry_retriever(context) { if (parent) { + entry_retriever.SetCallback(parent->entry_retriever.GetCallback()); // We have to inherit macro and lambda parameter bindings and from the parent binder, if there is a parent. macro_binding = parent->macro_binding; lambda_bindings = parent->lambda_bindings; - if (inherit_ctes) { + if (binder_type == BinderType::REGULAR_BINDER) { // We have to inherit CTE bindings from the parent bind_context, if there is a parent. bind_context.SetCTEBindings(parent->bind_context.GetCTEBindings()); bind_context.cte_references = parent->bind_context.cte_references; @@ -111,22 +113,22 @@ BoundStatement Binder::BindWithCTE(T &statement) { BoundStatement bound_statement; auto bound_cte = BindMaterializedCTE(statement.template Cast().cte_map); if (bound_cte) { - BoundCTENode *tail = bound_cte.get(); + reference tail_ref = *bound_cte; - while (tail->child && tail->child->type == QueryNodeType::CTE_NODE) { - tail = &tail->child->Cast(); + while (tail_ref.get().child && tail_ref.get().child->type == QueryNodeType::CTE_NODE) { + tail_ref = tail_ref.get().child->Cast(); } - bound_statement = tail->child_binder->Bind(statement.template Cast()); + auto &tail = tail_ref.get(); + bound_statement = tail.child_binder->Bind(statement.template Cast()); - tail->types = bound_statement.types; - tail->names = bound_statement.names; + tail.types = bound_statement.types; + tail.names = bound_statement.names; - for (auto &c : tail->query_binder->correlated_columns) { - tail->child_binder->AddCorrelatedColumn(c); + for (auto &c : tail.query_binder->correlated_columns) { + tail.child_binder->AddCorrelatedColumn(c); } - - MoveCorrelatedExpressions(*tail->child_binder); + MoveCorrelatedExpressions(*tail.child_binder); // extract operator below root operation auto plan = std::move(bound_statement.plan->children[0]); @@ -146,7 +148,7 @@ BoundStatement Binder::Bind(SQLStatement &statement) { case StatementType::INSERT_STATEMENT: return Bind(statement.Cast()); case StatementType::COPY_STATEMENT: - return Bind(statement.Cast()); + return Bind(statement.Cast(), CopyToType::COPY_TO_FILE); case StatementType::DELETE_STATEMENT: return BindWithCTE(statement.Cast()); case StatementType::UPDATE_STATEMENT: @@ -189,6 +191,8 @@ BoundStatement Binder::Bind(SQLStatement &statement) { return Bind(statement.Cast()); case StatementType::COPY_DATABASE_STATEMENT: return Bind(statement.Cast()); + case StatementType::UPDATE_EXTENSIONS_STATEMENT: + return Bind(statement.Cast()); default: // LCOV_EXCL_START throw NotImplementedException("Unimplemented statement type \"%s\" for Bind", StatementTypeToString(statement.type)); @@ -272,6 +276,9 @@ unique_ptr Binder::Bind(TableRef &ref) { case TableReferenceType::EXPRESSION_LIST: result = Bind(ref.Cast()); break; + case TableReferenceType::COLUMN_DATA: + result = Bind(ref.Cast()); + break; case TableReferenceType::PIVOT: result = Bind(ref.Cast()); break; @@ -281,7 +288,7 @@ unique_ptr Binder::Bind(TableRef &ref) { case TableReferenceType::CTE: case TableReferenceType::INVALID: default: - throw InternalException("Unknown table ref type"); + throw InternalException("Unknown table ref type (%s)", EnumUtil::ToString(ref.type)); } result->sample = std::move(ref.sample); return result; @@ -308,6 +315,9 @@ unique_ptr Binder::CreatePlan(BoundTableRef &ref) { case TableReferenceType::EXPRESSION_LIST: root = CreatePlan(ref.Cast()); break; + case TableReferenceType::COLUMN_DATA: + root = CreatePlan(ref.Cast()); + break; case TableReferenceType::CTE: root = CreatePlan(ref.Cast()); break; @@ -316,7 +326,7 @@ unique_ptr Binder::CreatePlan(BoundTableRef &ref) { break; case TableReferenceType::INVALID: default: - throw InternalException("Unsupported bound table ref type"); + throw InternalException("Unsupported bound table ref type (%s)", EnumUtil::ToString(ref.type)); } // plan the sample clause if (ref.sample) { @@ -342,7 +352,7 @@ vector> Binder::FindCTE(const string &name, ctes.push_back(entry->second); } } - if (parent && inherit_ctes) { + if (parent && binder_type == BinderType::REGULAR_BINDER) { auto parent_ctes = parent->FindCTE(name, name == alias); ctes.insert(ctes.end(), parent_ctes.begin(), parent_ctes.end()); } @@ -353,7 +363,7 @@ bool Binder::CTEIsAlreadyBound(CommonTableExpressionInfo &cte) { if (bound_ctes.find(cte) != bound_ctes.end()) { return true; } - if (parent && inherit_ctes) { + if (parent && binder_type == BinderType::REGULAR_BINDER) { return parent->CTEIsAlreadyBound(cte); } return false; @@ -376,6 +386,11 @@ idx_t Binder::GenerateTableIndex() { return root_binder.bound_tables++; } +StatementProperties &Binder::GetStatementProperties() { + auto &root_binder = GetRootBinder(); + return root_binder.prop; +} + void Binder::PushExpressionBinder(ExpressionBinder &binder) { GetActiveBinders().push_back(binder); } @@ -399,7 +414,11 @@ bool Binder::HasActiveBinder() { } vector> &Binder::GetActiveBinders() { - auto &root_binder = GetRootBinder(); + reference root = *this; + while (root.get().parent && root.get().binder_type == BinderType::REGULAR_BINDER) { + root = *root.get().parent; + } + auto &root_binder = root.get(); return root_binder.active_binders; } @@ -488,15 +507,8 @@ void Binder::SetCanContainNulls(bool can_contain_nulls_p) { } void Binder::SetAlwaysRequireRebind() { - reference current_binder = *this; - while (true) { - auto ¤t = current_binder.get(); - current.properties.always_require_rebind = true; - if (!current.parent) { - break; - } - current_binder = *current.parent; - } + auto &properties = GetStatementProperties(); + properties.always_require_rebind = true; } void Binder::AddTableName(string table_name) { @@ -504,11 +516,28 @@ void Binder::AddTableName(string table_name) { root_binder.table_names.insert(std::move(table_name)); } +void Binder::AddReplacementScan(const string &table_name, unique_ptr replacement) { + auto &root_binder = GetRootBinder(); + auto it = root_binder.replacement_scans.find(table_name); + replacement->column_name_alias.clear(); + replacement->alias.clear(); + if (it == root_binder.replacement_scans.end()) { + root_binder.replacement_scans[table_name] = std::move(replacement); + } else { + // A replacement scan by this name was previously registered, we can just use it + } +} + const unordered_set &Binder::GetTableNames() { auto &root_binder = GetRootBinder(); return root_binder.table_names; } +case_insensitive_map_t> &Binder::GetReplacementScans() { + auto &root_binder = GetRootBinder(); + return root_binder.replacement_scans; +} + // FIXME: this is extremely naive void VerifyNotExcluded(ParsedExpression &expr) { if (expr.type == ExpressionType::COLUMN_REF) { @@ -572,9 +601,16 @@ BoundStatement Binder::BindReturning(vector> return // where the data modification doesn't take place until the streamed result is exhausted. Once a row is // returned, it should be guaranteed that the row has been inserted. // see https://github.com/duckdb/duckdb/issues/8310 + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; properties.return_type = StatementReturnType::QUERY_RESULT; return result; } +optional_ptr Binder::GetCatalogEntry(CatalogType type, const string &catalog, const string &schema, + const string &name, OnEntryNotFound on_entry_not_found, + QueryErrorContext &error_context) { + return entry_retriever.GetEntry(type, catalog, schema, name, on_entry_not_found, error_context); +} + } // namespace duckdb diff --git a/src/planner/binder/expression/CMakeLists.txt b/src/planner/binder/expression/CMakeLists.txt index 99a1924ec51..e10f803ea13 100644 --- a/src/planner/binder/expression/CMakeLists.txt +++ b/src/planner/binder/expression/CMakeLists.txt @@ -16,6 +16,7 @@ add_library_unity( bind_operator_expression.cpp bind_parameter_expression.cpp bind_positional_reference_expression.cpp + bind_unpacked_star_expression.cpp bind_star_expression.cpp bind_subquery_expression.cpp bind_unnest_expression.cpp diff --git a/src/planner/binder/expression/bind_aggregate_expression.cpp b/src/planner/binder/expression/bind_aggregate_expression.cpp index eecd07ea9d1..5caf89a6560 100644 --- a/src/planner/binder/expression/bind_aggregate_expression.cpp +++ b/src/planner/binder/expression/bind_aggregate_expression.cpp @@ -6,6 +6,8 @@ #include "duckdb/planner/expression/bound_cast_expression.hpp" #include "duckdb/planner/expression/bound_columnref_expression.hpp" #include "duckdb/planner/expression/bound_constant_expression.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/planner/expression_iterator.hpp" #include "duckdb/planner/expression_binder/aggregate_binder.hpp" #include "duckdb/planner/expression_binder/base_select_binder.hpp" #include "duckdb/planner/query_node/bound_select_node.hpp" @@ -17,6 +19,18 @@ namespace duckdb { +static bool ExtractFunctionalDependencies(column_binding_set_t &deps, const unique_ptr &expr) { + if (expr->type == ExpressionType::BOUND_COLUMN_REF) { + auto &colref = expr->Cast(); + deps.insert(colref.binding); + } + + bool is_volatile = expr->IsVolatile(); + ExpressionIterator::EnumerateChildren( + *expr, [&](unique_ptr &child) { is_volatile |= ExtractFunctionalDependencies(deps, child); }); + return is_volatile; +} + static Value NegatePercentileValue(const Value &v, const bool desc) { if (v.IsNull()) { return v; @@ -233,19 +247,32 @@ BindResult BaseSelectBinder::BindAggregate(FunctionExpression &aggr, AggregateFu } } - // If the aggregate is DISTINCT then the ORDER BYs need to be arguments. + // If the aggregate is DISTINCT then the ORDER BYs need to be functional dependencies of the arguments. if (aggr.distinct && order_bys) { + column_binding_set_t child_dependencies; + bool children_volatile = false; + for (const auto &child : children) { + children_volatile |= ExtractFunctionalDependencies(child_dependencies, child); + } + + column_binding_set_t order_dependencies; + bool order_volatile = false; for (const auto &order_by : order_bys->orders) { - bool is_arg = false; - for (const auto &child : children) { - if (order_by.expression->Equals(*child)) { - is_arg = true; + order_volatile |= ExtractFunctionalDependencies(order_dependencies, order_by.expression); + } + + bool in_args = !children_volatile && !order_volatile; + if (in_args) { + for (const auto &binding : order_dependencies) { + if (!child_dependencies.count(binding)) { + in_args = false; break; } } - if (!is_arg) { - throw BinderException("In a DISTINCT aggregate, ORDER BY expressions must appear in the argument list"); - } + } + + if (!in_args) { + throw BinderException("In a DISTINCT aggregate, ORDER BY expressions must appear in the argument list"); } } diff --git a/src/planner/binder/expression/bind_between_expression.cpp b/src/planner/binder/expression/bind_between_expression.cpp index b32dec1977d..6a0043fc651 100644 --- a/src/planner/binder/expression/bind_between_expression.cpp +++ b/src/planner/binder/expression/bind_between_expression.cpp @@ -46,9 +46,9 @@ BindResult ExpressionBinder::BindExpression(BetweenExpression &expr, idx_t depth lower = BoundCastExpression::AddCastToType(context, std::move(lower), input_type); upper = BoundCastExpression::AddCastToType(context, std::move(upper), input_type); // handle collation - PushCollation(context, input, input_type, false); - PushCollation(context, lower, input_type, false); - PushCollation(context, upper, input_type, false); + PushCollation(context, input, input_type); + PushCollation(context, lower, input_type); + PushCollation(context, upper, input_type); if (!input->IsVolatile() && !input->HasParameter() && !input->HasSubquery()) { // the expression does not have side effects and can be copied: create two comparisons diff --git a/src/planner/binder/expression/bind_cast_expression.cpp b/src/planner/binder/expression/bind_cast_expression.cpp index 68272d0a187..79d9047e1b8 100644 --- a/src/planner/binder/expression/bind_cast_expression.cpp +++ b/src/planner/binder/expression/bind_cast_expression.cpp @@ -14,7 +14,7 @@ BindResult ExpressionBinder::BindExpression(CastExpression &expr, idx_t depth) { } // FIXME: We can also implement 'hello'::schema.custom_type; and pass by the schema down here. // Right now just considering its DEFAULT_SCHEMA always - Binder::BindLogicalType(context, expr.cast_type); + binder.BindLogicalType(expr.cast_type); // the children have been successfully resolved auto &child = BoundExpression::GetExpression(*expr.child); if (expr.try_cast) { diff --git a/src/planner/binder/expression/bind_collate_expression.cpp b/src/planner/binder/expression/bind_collate_expression.cpp index 7e0633a5a88..1f84cb17d7e 100644 --- a/src/planner/binder/expression/bind_collate_expression.cpp +++ b/src/planner/binder/expression/bind_collate_expression.cpp @@ -20,7 +20,7 @@ BindResult ExpressionBinder::BindExpression(CollateExpression &expr, idx_t depth // Validate the collation, but don't use it auto child_copy = child->Copy(); auto collation_type = LogicalType::VARCHAR_COLLATION(expr.collation); - PushCollation(context, child_copy, collation_type, false); + PushCollation(context, child_copy, collation_type); child->return_type = collation_type; return BindResult(std::move(child)); } diff --git a/src/planner/binder/expression/bind_columnref_expression.cpp b/src/planner/binder/expression/bind_columnref_expression.cpp index ce6cb104b72..94d92670441 100644 --- a/src/planner/binder/expression/bind_columnref_expression.cpp +++ b/src/planner/binder/expression/bind_columnref_expression.cpp @@ -155,10 +155,9 @@ void ExpressionBinder::QualifyColumnNames(unique_ptr &expr, break; } case ExpressionType::FUNCTION: { - // special-handling for lambdas, which are inside function expressions, + // Special-handling for lambdas, which are inside function expressions. auto &function = expr->Cast(); - if (IsLambdaFunction(function)) { - // special case + if (function.IsLambdaFunction()) { return QualifyColumnNamesInLambda(function, lambda_params); } diff --git a/src/planner/binder/expression/bind_comparison_expression.cpp b/src/planner/binder/expression/bind_comparison_expression.cpp index 522e85b6a43..151bf65a456 100644 --- a/src/planner/binder/expression/bind_comparison_expression.cpp +++ b/src/planner/binder/expression/bind_comparison_expression.cpp @@ -11,61 +11,14 @@ #include "duckdb/function/scalar/string_functions.hpp" #include "duckdb/common/types/decimal.hpp" - -#include "duckdb/main/config.hpp" -#include "duckdb/catalog/catalog.hpp" -#include "duckdb/function/function_binder.hpp" +#include "duckdb/planner/collation_binding.hpp" namespace duckdb { bool ExpressionBinder::PushCollation(ClientContext &context, unique_ptr &source, - const LogicalType &sql_type, bool equality_only) { - if (sql_type.id() != LogicalTypeId::VARCHAR) { - // only VARCHAR columns require collation - return false; - } - // replace default collation with system collation - auto str_collation = StringType::GetCollation(sql_type); - string collation; - if (str_collation.empty()) { - collation = DBConfig::GetConfig(context).options.collation; - } else { - collation = str_collation; - } - collation = StringUtil::Lower(collation); - // bind the collation - if (collation.empty() || collation == "binary" || collation == "c" || collation == "posix") { - // no collation or binary collation: skip - return false; - } - auto &catalog = Catalog::GetSystemCatalog(context); - auto splits = StringUtil::Split(StringUtil::Lower(collation), "."); - vector> entries; - for (auto &collation_argument : splits) { - auto &collation_entry = catalog.GetEntry(context, DEFAULT_SCHEMA, collation_argument); - if (collation_entry.combinable) { - entries.insert(entries.begin(), collation_entry); - } else { - if (!entries.empty() && !entries.back().get().combinable) { - throw BinderException("Cannot combine collation types \"%s\" and \"%s\"", entries.back().get().name, - collation_entry.name); - } - entries.push_back(collation_entry); - } - } - for (auto &entry : entries) { - auto &collation_entry = entry.get(); - if (equality_only && collation_entry.not_required_for_equality) { - continue; - } - vector> children; - children.push_back(std::move(source)); - - FunctionBinder function_binder(context); - auto function = function_binder.BindScalarFunction(collation_entry.function, std::move(children)); - source = std::move(function); - } - return true; + const LogicalType &sql_type) { + auto &collation_binding = CollationBinding::Get(context); + return collation_binding.PushCollation(context, source, sql_type); } void ExpressionBinder::TestCollation(ClientContext &context, const string &collation) { @@ -226,8 +179,8 @@ BindResult ExpressionBinder::BindExpression(ComparisonExpression &expr, idx_t de right = BoundCastExpression::AddCastToType(context, std::move(right), input_type, input_type.id() == LogicalTypeId::ENUM); - PushCollation(context, left, input_type, expr.type == ExpressionType::COMPARE_EQUAL); - PushCollation(context, right, input_type, expr.type == ExpressionType::COMPARE_EQUAL); + PushCollation(context, left, input_type); + PushCollation(context, right, input_type); // now create the bound comparison expression return BindResult(make_uniq(expr.type, std::move(left), std::move(right))); diff --git a/src/planner/binder/expression/bind_function_expression.cpp b/src/planner/binder/expression/bind_function_expression.cpp index 0d888e37b58..f1f137a834d 100644 --- a/src/planner/binder/expression/bind_function_expression.cpp +++ b/src/planner/binder/expression/bind_function_expression.cpp @@ -39,13 +39,12 @@ BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t // lookup the function in the catalog QueryErrorContext error_context(function.query_location); binder.BindSchemaOrCatalog(function.catalog, function.schema); - auto func = Catalog::GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, function.catalog, function.schema, - function.function_name, OnEntryNotFound::RETURN_NULL, error_context); + auto func = GetCatalogEntry(CatalogType::SCALAR_FUNCTION_ENTRY, function.catalog, function.schema, + function.function_name, OnEntryNotFound::RETURN_NULL, error_context); if (!func) { // function was not found - check if we this is a table function - auto table_func = - Catalog::GetEntry(context, CatalogType::TABLE_FUNCTION_ENTRY, function.catalog, function.schema, - function.function_name, OnEntryNotFound::RETURN_NULL, error_context); + auto table_func = GetCatalogEntry(CatalogType::TABLE_FUNCTION_ENTRY, function.catalog, function.schema, + function.function_name, OnEntryNotFound::RETURN_NULL, error_context); if (table_func) { throw BinderException(function, "Function \"%s\" is a table function but it was used as a scalar function. This " @@ -75,8 +74,8 @@ BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t } } // rebind the function - func = Catalog::GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, function.catalog, function.schema, - function.function_name, OnEntryNotFound::THROW_EXCEPTION, error_context); + func = GetCatalogEntry(CatalogType::SCALAR_FUNCTION_ENTRY, function.catalog, function.schema, + function.function_name, OnEntryNotFound::THROW_EXCEPTION, error_context); } if (func->type != CatalogType::AGGREGATE_FUNCTION_ENTRY && @@ -88,9 +87,7 @@ BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t switch (func->type) { case CatalogType::SCALAR_FUNCTION_ENTRY: { - // scalar function - if (IsLambdaFunction(function)) { - // special case + if (function.IsLambdaFunction()) { return TryBindLambdaOrJson(function, depth, *func); } return BindFunction(function, func->Cast(), depth); @@ -281,4 +278,11 @@ string ExpressionBinder::UnsupportedUnnestMessage() { return "UNNEST not supported here"; } +optional_ptr ExpressionBinder::GetCatalogEntry(CatalogType type, const string &catalog, + const string &schema, const string &name, + OnEntryNotFound on_entry_not_found, + QueryErrorContext &error_context) { + return binder.GetCatalogEntry(type, catalog, schema, name, on_entry_not_found, error_context); +} + } // namespace duckdb diff --git a/src/planner/binder/expression/bind_macro_expression.cpp b/src/planner/binder/expression/bind_macro_expression.cpp index ced09d18028..d35d9a57973 100644 --- a/src/planner/binder/expression/bind_macro_expression.cpp +++ b/src/planner/binder/expression/bind_macro_expression.cpp @@ -14,19 +14,18 @@ void ExpressionBinder::ReplaceMacroParametersInLambda(FunctionExpression &functi for (auto &child : function.children) { if (child->expression_class != ExpressionClass::LAMBDA) { - // not a lambda expression ReplaceMacroParameters(child, lambda_params); continue; } - // special-handling for LHS lambda parameters - // we do not replace them, and we add them to the lambda_params vector + // Special-handling for LHS lambda parameters. + // We do not replace them, and we add them to the lambda_params vector. auto &lambda_expr = child->Cast(); string error_message; auto column_ref_expressions = lambda_expr.ExtractColumnRefExpressions(error_message); if (!error_message.empty()) { - // possibly a JSON function, replace both LHS and RHS + // Possibly a JSON function, replace both LHS and RHS. ParsedExpressionIterator::EnumerateChildren(*lambda_expr.lhs, [&](unique_ptr &child) { ReplaceMacroParameters(child, lambda_params); }); @@ -36,21 +35,18 @@ void ExpressionBinder::ReplaceMacroParametersInLambda(FunctionExpression &functi continue; } - // push this level + // Push the lambda parameter names of this level. lambda_params.emplace_back(); - - // push the lambda parameter names for (const auto &column_ref_expr : column_ref_expressions) { const auto &column_ref = column_ref_expr.get().Cast(); lambda_params.back().emplace(column_ref.GetName()); } - // only replace in RHS + // Only replace in the RHS of the expression. ParsedExpressionIterator::EnumerateChildren(*lambda_expr.expr, [&](unique_ptr &child) { ReplaceMacroParameters(child, lambda_params); }); - // pop this level lambda_params.pop_back(); } } @@ -60,10 +56,8 @@ void ExpressionBinder::ReplaceMacroParameters(unique_ptr &expr switch (expr->GetExpressionClass()) { case ExpressionClass::COLUMN_REF: { - // if the expression is a parameter, replace it with its argument + // If the expression is a column reference, we replace it with its argument. auto &col_ref = expr->Cast(); - - // don't replace lambda parameters if (LambdaExpression::IsLambdaParameter(lambda_params, col_ref.GetName())) { return; } @@ -84,10 +78,9 @@ void ExpressionBinder::ReplaceMacroParameters(unique_ptr &expr return; } case ExpressionClass::FUNCTION: { - // special-handling for lambdas, which are inside function expressions, + // Special-handling for lambdas, which are inside function expressions. auto &function = expr->Cast(); - if (IsLambdaFunction(function)) { - // special case + if (function.IsLambdaFunction()) { return ReplaceMacroParametersInLambda(function, lambda_params); } break; @@ -98,11 +91,10 @@ void ExpressionBinder::ReplaceMacroParameters(unique_ptr &expr *sq->node, [&](unique_ptr &child) { ReplaceMacroParameters(child, lambda_params); }); break; } - default: // fall through + default: break; } - // replace macro parameters in child expressions ParsedExpressionIterator::EnumerateChildren( *expr, [&](unique_ptr &child) { ReplaceMacroParameters(child, lambda_params); }); } diff --git a/src/planner/binder/expression/bind_operator_expression.cpp b/src/planner/binder/expression/bind_operator_expression.cpp index 3ac3f7881c3..17f2faf3456 100644 --- a/src/planner/binder/expression/bind_operator_expression.cpp +++ b/src/planner/binder/expression/bind_operator_expression.cpp @@ -50,7 +50,7 @@ LogicalType ExpressionBinder::ResolveInType(OperatorExpression &op, vector &expr, StarExpressi bool has_star = false; if (expr->GetExpressionClass() == ExpressionClass::STAR) { auto ¤t_star = expr->Cast(); - if (!current_star.columns) { + if (StarExpression::IsStar(*expr)) { if (is_root) { + D_ASSERT(!in_columns); + // At the root level *star = ¤t_star; return true; } + if (!in_columns) { + // '*' can only appear inside COLUMNS or at the root level throw BinderException( "STAR expression is only allowed as the root element of an expression. Use COLUMNS(*) instead."); } - // star expression inside a COLUMNS - convert to a constant list + if (!current_star.replace_list.empty()) { + // '*' inside COLUMNS can not have a REPLACE list throw BinderException( "STAR expression with REPLACE list is only allowed as the root element of COLUMNS"); } + + // '*' expression inside a COLUMNS - convert to a constant list of strings (column names) vector> star_list; bind_context.GenerateAllColumnExpressions(current_star, star_list); vector values; values.reserve(star_list.size()); - for (auto &expr : star_list) { - values.emplace_back(GetColumnsStringValue(*expr)); + for (auto &element : star_list) { + values.emplace_back(GetColumnsStringValue(*element)); } D_ASSERT(!values.empty()); - expr = make_uniq(Value::LIST(LogicalType::VARCHAR, values)); return true; } @@ -55,6 +62,7 @@ bool Binder::FindStarExpression(unique_ptr &expr, StarExpressi throw BinderException("COLUMNS expression is not allowed inside another COLUMNS expression"); } in_columns = true; + if (*star) { // we can have multiple if (!(*star)->Equals(current_star)) { @@ -76,7 +84,7 @@ bool Binder::FindStarExpression(unique_ptr &expr, StarExpressi void Binder::ReplaceStarExpression(unique_ptr &expr, unique_ptr &replacement) { D_ASSERT(expr); - if (expr->GetExpressionClass() == ExpressionClass::STAR) { + if (StarExpression::IsColumns(*expr) || StarExpression::IsStar(*expr)) { D_ASSERT(replacement); auto alias = expr->alias; expr = replacement->Copy(); @@ -221,10 +229,18 @@ void Binder::ExpandStarExpression(unique_ptr expr, } // now perform the replacement + if (StarExpression::IsColumnsUnpacked(*star)) { + if (StarExpression::IsColumnsUnpacked(*expr)) { + throw BinderException("*COLUMNS not allowed at the root level, use COLUMNS instead"); + } + ReplaceUnpackedStarExpression(expr, star_list); + new_select_list.push_back(std::move(expr)); + return; + } for (idx_t i = 0; i < star_list.size(); i++) { auto new_expr = expr->Copy(); ReplaceStarExpression(new_expr, star_list[i]); - if (star->columns) { + if (StarExpression::IsColumns(*star)) { optional_ptr expr = star_list[i].get(); while (expr) { if (expr->type == ExpressionType::COLUMN_REF) { diff --git a/src/planner/binder/expression/bind_unpacked_star_expression.cpp b/src/planner/binder/expression/bind_unpacked_star_expression.cpp new file mode 100644 index 00000000000..24e70812952 --- /dev/null +++ b/src/planner/binder/expression/bind_unpacked_star_expression.cpp @@ -0,0 +1,91 @@ +#include "duckdb/planner/binder.hpp" +#include "duckdb/parser/expression/star_expression.hpp" +#include "duckdb/parser/expression/operator_expression.hpp" +#include "duckdb/parser/expression/function_expression.hpp" +#include "duckdb/parser/parsed_expression_iterator.hpp" + +namespace duckdb { + +using expression_list_t = vector>; + +static void AddChild(unique_ptr &child, expression_list_t &new_children, + expression_list_t &replacements) { + if (!StarExpression::IsColumnsUnpacked(*child)) { + // Just add the child directly + new_children.push_back(std::move(child)); + return; + } + // Replace the child with the replacement expression(s) + for (auto &replacement : replacements) { + new_children.push_back(replacement->Copy()); + } +} + +static void ReplaceInFunction(unique_ptr &expr, expression_list_t &star_list) { + auto &function_expr = expr->Cast(); + + // Replace children + expression_list_t new_children; + for (auto &child : function_expr.children) { + AddChild(child, new_children, star_list); + } + function_expr.children = std::move(new_children); + + // Replace ORDER_BY + if (function_expr.order_bys) { + expression_list_t new_orders; + for (auto &order : function_expr.order_bys->orders) { + AddChild(order.expression, new_orders, star_list); + } + if (new_orders.size() != function_expr.order_bys->orders.size()) { + throw NotImplementedException("*COLUMNS(...) is not supported in the order expression"); + } + for (idx_t i = 0; i < new_orders.size(); i++) { + auto &new_order = new_orders[i]; + function_expr.order_bys->orders[i].expression = std::move(new_order); + } + } +} + +static void ReplaceInOperator(unique_ptr &expr, expression_list_t &star_list) { + auto &operator_expr = expr->Cast(); + + // Replace children + expression_list_t new_children; + for (auto &child : operator_expr.children) { + AddChild(child, new_children, star_list); + } + operator_expr.children = std::move(new_children); +} + +void Binder::ReplaceUnpackedStarExpression(unique_ptr &expr, expression_list_t &star_list) { + D_ASSERT(expr); + auto expression_class = expr->GetExpressionClass(); + // Replace *COLUMNS(...) in the supported places + switch (expression_class) { + case ExpressionClass::STAR: { + if (!StarExpression::IsColumnsUnpacked(*expr)) { + break; + } + // Deal with any *COLUMNS that was not replaced + throw BinderException("*COLUMNS() can not be used in this place"); + } + case ExpressionClass::FUNCTION: { + ReplaceInFunction(expr, star_list); + break; + } + case ExpressionClass::OPERATOR: { + ReplaceInOperator(expr, star_list); + break; + } + default: { + break; + } + } + + // Visit the children of this expression, collecting the unpacked expressions + ParsedExpressionIterator::EnumerateChildren( + *expr, [&](unique_ptr &child_expr) { ReplaceUnpackedStarExpression(child_expr, star_list); }); +} + +} // namespace duckdb diff --git a/src/planner/binder/expression/bind_window_expression.cpp b/src/planner/binder/expression/bind_window_expression.cpp index 677ec8dd126..5909df50745 100644 --- a/src/planner/binder/expression/bind_window_expression.cpp +++ b/src/planner/binder/expression/bind_window_expression.cpp @@ -202,12 +202,12 @@ BindResult BaseSelectBinder::BindWindow(WindowExpression &window, idx_t depth) { // Restore any collation expressions for (auto &part_expr : window.partitions) { auto &bound_partition = BoundExpression::GetExpression(*part_expr); - ExpressionBinder::PushCollation(context, bound_partition, bound_partition->return_type, true); + ExpressionBinder::PushCollation(context, bound_partition, bound_partition->return_type); } for (auto &order : window.orders) { auto &order_expr = order.expression; auto &bound_order = BoundExpression::GetExpression(*order_expr); - ExpressionBinder::PushCollation(context, bound_order, bound_order->return_type, false); + ExpressionBinder::PushCollation(context, bound_order, bound_order->return_type); } // successfully bound all children: create bound window function vector types; diff --git a/src/planner/binder/query_node/bind_select_node.cpp b/src/planner/binder/query_node/bind_select_node.cpp index 8c557a45151..fae7b2979bb 100644 --- a/src/planner/binder/query_node/bind_select_node.cpp +++ b/src/planner/binder/query_node/bind_select_node.cpp @@ -45,7 +45,7 @@ unique_ptr Binder::BindOrderExpression(OrderBinder &order_binder, un BoundLimitNode Binder::BindLimitValue(OrderBinder &order_binder, unique_ptr limit_val, bool is_percentage, bool is_offset) { - auto new_binder = Binder::CreateBinder(context, this, true); + auto new_binder = Binder::CreateBinder(context, this); ExpressionBinder expr_binder(*new_binder, context); auto target_type = is_percentage ? LogicalType::DOUBLE : LogicalType::BIGINT; expr_binder.target_type = target_type; @@ -314,7 +314,7 @@ void Binder::BindModifiers(BoundQueryNode &result, idx_t table_index, const vect } } for (auto &expr : distinct.target_distincts) { - ExpressionBinder::PushCollation(context, expr, expr->return_type, true); + ExpressionBinder::PushCollation(context, expr, expr->return_type); } break; } @@ -480,7 +480,7 @@ unique_ptr Binder::BindSelectNode(SelectNode &statement, unique_ bool contains_subquery = bound_expr_ref.HasSubquery(); // push a potential collation, if necessary - bool requires_collation = ExpressionBinder::PushCollation(context, bound_expr, group_type, true); + bool requires_collation = ExpressionBinder::PushCollation(context, bound_expr, group_type); if (!contains_subquery && requires_collation) { // if there is a collation on a group x, we should group by the collated expr, // but also push a first(x) aggregate in case x is selected (uncollated) diff --git a/src/planner/binder/query_node/plan_setop.cpp b/src/planner/binder/query_node/plan_setop.cpp index caccbc45de8..c7ddf17b312 100644 --- a/src/planner/binder/query_node/plan_setop.cpp +++ b/src/planner/binder/query_node/plan_setop.cpp @@ -4,6 +4,8 @@ #include "duckdb/planner/operator/logical_projection.hpp" #include "duckdb/planner/operator/logical_set_operation.hpp" #include "duckdb/planner/query_node/bound_set_operation_node.hpp" +#include "duckdb/function/table/read_csv.hpp" +#include "duckdb/planner/operator/logical_get.hpp" namespace duckdb { @@ -23,14 +25,45 @@ unique_ptr Binder::CastLogicalOperatorToTypes(vectortype == LogicalOperatorType::LOGICAL_PROJECTION) { // "node" is a projection; we can just do the casts in there D_ASSERT(node->expressions.size() == source_types.size()); + if (node->children.size() == 1 && node->children[0]->type == LogicalOperatorType::LOGICAL_GET) { + // If this projection only has one child and that child is a logical get we can try to pushdown types + auto &logical_get = node->children[0]->Cast(); + if (logical_get.function.type_pushdown) { + unordered_map new_column_types; + bool do_pushdown = true; + for (idx_t i = 0; i < op->expressions.size(); i++) { + if (op->expressions[i]->type == ExpressionType::BOUND_COLUMN_REF) { + auto &col_ref = op->expressions[i]->Cast(); + if (new_column_types.find(logical_get.column_ids[col_ref.binding.column_index]) != + new_column_types.end()) { + // Only one reference per column is accepted + do_pushdown = false; + break; + } + new_column_types[logical_get.column_ids[col_ref.binding.column_index]] = target_types[i]; + } else { + do_pushdown = false; + break; + } + } + if (do_pushdown) { + logical_get.function.type_pushdown(context, logical_get.bind_data, new_column_types); + // We also have to modify the types to the logical_get.returned_types + for (auto &type : new_column_types) { + logical_get.returned_types[type.first] = type.second; + } + return op; + } + } + } // add the casts to the selection list for (idx_t i = 0; i < target_types.size(); i++) { if (source_types[i] != target_types[i]) { // differing types, have to add a cast - string alias = node->expressions[i]->alias; + string cur_alias = node->expressions[i]->alias; node->expressions[i] = BoundCastExpression::AddCastToType(context, std::move(node->expressions[i]), target_types[i]); - node->expressions[i]->alias = alias; + node->expressions[i]->alias = cur_alias; } } return op; diff --git a/src/planner/binder/query_node/plan_subquery.cpp b/src/planner/binder/query_node/plan_subquery.cpp index 3f3aaa92c9a..af70d7e033e 100644 --- a/src/planner/binder/query_node/plan_subquery.cpp +++ b/src/planner/binder/query_node/plan_subquery.cpp @@ -6,7 +6,6 @@ #include "duckdb/planner/expression/bound_columnref_expression.hpp" #include "duckdb/planner/expression/bound_comparison_expression.hpp" #include "duckdb/planner/expression/bound_constant_expression.hpp" -#include "duckdb/planner/expression/bound_reference_expression.hpp" #include "duckdb/planner/expression/bound_subquery_expression.hpp" #include "duckdb/planner/expression/bound_window_expression.hpp" #include "duckdb/planner/expression_iterator.hpp" @@ -16,7 +15,6 @@ #include "duckdb/planner/subquery/flatten_dependent_join.hpp" #include "duckdb/common/enums/logical_operator_type.hpp" #include "duckdb/planner/operator/logical_dependent_join.hpp" -#include "duckdb/planner/expression_binder/lateral_binder.hpp" #include "duckdb/planner/subquery/recursive_dependent_join_planner.hpp" namespace duckdb { @@ -419,8 +417,8 @@ unique_ptr Binder::PlanLateralJoin(unique_ptr vector> arbitrary_expressions; if (condition) { // extract join conditions, if there are any - LogicalComparisonJoin::ExtractJoinConditions(context, join_type, left, right, std::move(condition), conditions, - arbitrary_expressions); + LogicalComparisonJoin::ExtractJoinConditions(context, join_type, JoinRefType::REGULAR, left, right, + std::move(condition), conditions, arbitrary_expressions); } auto perform_delim = PerformDuplicateElimination(*this, correlated); diff --git a/src/planner/binder/statement/CMakeLists.txt b/src/planner/binder/statement/CMakeLists.txt index 6ce554d48ae..c28541fd892 100644 --- a/src/planner/binder/statement/CMakeLists.txt +++ b/src/planner/binder/statement/CMakeLists.txt @@ -25,6 +25,7 @@ add_library_unity( bind_simple.cpp bind_summarize.cpp bind_update.cpp + bind_update_extensions.cpp bind_vacuum.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/planner/binder/statement/bind_attach.cpp b/src/planner/binder/statement/bind_attach.cpp index 6392191189c..480324161a2 100644 --- a/src/planner/binder/statement/bind_attach.cpp +++ b/src/planner/binder/statement/bind_attach.cpp @@ -12,6 +12,8 @@ BoundStatement Binder::Bind(AttachStatement &stmt) { result.names = {"Success"}; result.plan = make_uniq(LogicalOperatorType::LOGICAL_ATTACH, std::move(stmt.info)); + + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; properties.return_type = StatementReturnType::NOTHING; return result; diff --git a/src/planner/binder/statement/bind_call.cpp b/src/planner/binder/statement/bind_call.cpp index 8f910bb9670..2767ba2d653 100644 --- a/src/planner/binder/statement/bind_call.cpp +++ b/src/planner/binder/statement/bind_call.cpp @@ -24,6 +24,8 @@ BoundStatement Binder::Bind(CallStatement &stmt) { result.types = get.returned_types; result.names = get.names; result.plan = CreatePlan(*bound_func); + + auto &properties = GetStatementProperties(); properties.return_type = StatementReturnType::QUERY_RESULT; return result; } diff --git a/src/planner/binder/statement/bind_copy.cpp b/src/planner/binder/statement/bind_copy.cpp index 80cdc0025be..b960af3160f 100644 --- a/src/planner/binder/statement/bind_copy.cpp +++ b/src/planner/binder/statement/bind_copy.cpp @@ -18,6 +18,7 @@ #include "duckdb/planner/operator/logical_copy_to_file.hpp" #include "duckdb/planner/operator/logical_get.hpp" #include "duckdb/planner/operator/logical_insert.hpp" +#include "duckdb/planner/operator/logical_projection.hpp" #include @@ -27,15 +28,12 @@ static bool GetBooleanArg(ClientContext &context, const vector &arg) { return arg.empty() || arg[0].CastAs(context, LogicalType::BOOLEAN).GetValue(); } -BoundStatement Binder::BindCopyTo(CopyStatement &stmt) { +BoundStatement Binder::BindCopyTo(CopyStatement &stmt, CopyToType copy_to_type) { // COPY TO a file auto &config = DBConfig::GetConfig(context); if (!config.options.enable_external_access) { throw PermissionException("COPY TO is disabled by configuration"); } - BoundStatement result; - result.types = {LogicalType::BIGINT}; - result.names = {"Count"}; // lookup the format in the catalog auto ©_function = @@ -45,20 +43,25 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt) { return copy_function.function.plan(*this, stmt); } + auto ©_info = *stmt.info; // bind the select statement - auto select_node = Bind(*stmt.select_statement); + auto node_copy = copy_info.select_statement->Copy(); + auto select_node = Bind(*node_copy); if (!copy_function.function.copy_to_bind) { throw NotImplementedException("COPY TO is not supported for FORMAT \"%s\"", stmt.info->format); } bool use_tmp_file = true; - bool overwrite_or_ignore = false; + CopyOverwriteMode overwrite_mode = CopyOverwriteMode::COPY_ERROR_ON_CONFLICT; FilenamePattern filename_pattern; bool user_set_use_tmp_file = false; bool per_thread_output = false; optional_idx file_size_bytes; vector partition_cols; + bool seen_overwrite_mode = false; + bool seen_filepattern = false; + CopyFunctionReturnType return_type = CopyFunctionReturnType::CHANGED_ROWS; CopyFunctionBindInput bind_input(*stmt.info); @@ -66,20 +69,37 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt) { auto original_options = stmt.info->options; stmt.info->options.clear(); - for (auto &option : original_options) { auto loption = StringUtil::Lower(option.first); if (loption == "use_tmp_file") { use_tmp_file = GetBooleanArg(context, option.second); user_set_use_tmp_file = true; - } else if (loption == "overwrite_or_ignore") { - overwrite_or_ignore = GetBooleanArg(context, option.second); + } else if (loption == "overwrite_or_ignore" || loption == "overwrite" || loption == "append") { + if (seen_overwrite_mode) { + throw BinderException("Can only set one of OVERWRITE_OR_IGNORE, OVERWRITE or APPEND"); + } + seen_overwrite_mode = true; + + auto boolean = GetBooleanArg(context, option.second); + if (boolean) { + if (loption == "overwrite_or_ignore") { + overwrite_mode = CopyOverwriteMode::COPY_OVERWRITE_OR_IGNORE; + } else if (loption == "overwrite") { + overwrite_mode = CopyOverwriteMode::COPY_OVERWRITE; + } else if (loption == "append") { + if (!seen_filepattern) { + filename_pattern.SetFilenamePattern("{uuid}"); + } + overwrite_mode = CopyOverwriteMode::COPY_APPEND; + } + } } else if (loption == "filename_pattern") { if (option.second.empty()) { throw IOException("FILENAME_PATTERN cannot be empty"); } filename_pattern.SetFilenamePattern( option.second[0].CastAs(context, LogicalType::VARCHAR).GetValue()); + seen_filepattern = true; } else if (loption == "file_extension") { if (option.second.empty()) { throw IOException("FILE_EXTENSION cannot be empty"); @@ -91,7 +111,7 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt) { if (option.second.empty()) { throw BinderException("FILE_SIZE_BYTES cannot be empty"); } - if (!copy_function.function.file_size_bytes) { + if (!copy_function.function.rotate_files) { throw NotImplementedException("FILE_SIZE_BYTES not implemented for FORMAT \"%s\"", stmt.info->format); } if (option.second[0].GetTypeMutable().id() == LogicalTypeId::VARCHAR) { @@ -102,10 +122,32 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt) { } else if (loption == "partition_by") { auto converted = ConvertVectorToValue(std::move(option.second)); partition_cols = ParseColumnsOrdered(converted, select_node.names, loption); + } else if (loption == "return_files") { + if (GetBooleanArg(context, option.second)) { + return_type = CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST; + } } else { + if (loption == "compression") { + if (option.second.empty()) { + // This can't be empty + throw BinderException("COMPRESSION option, in the file scanner, can't be empty. It should be set " + "to AUTO, UNCOMPRESSED, GZIP, SNAPPY or ZSTD. Depending on the file format."); + } + auto parameter = StringUtil::Lower(option.second[0].ToString()); + if (parameter == "gzip" && !StringUtil::EndsWith(bind_input.file_extension, ".gz")) { + // We just add .gz + bind_input.file_extension += ".gz"; + } else if (parameter == "zstd" && !StringUtil::EndsWith(bind_input.file_extension, ".zst")) { + // We just add .zst + bind_input.file_extension += ".zst"; + } + } stmt.info->options[option.first] = option.second; } } + if (overwrite_mode == CopyOverwriteMode::COPY_APPEND && !filename_pattern.HasUUID()) { + throw BinderException("APPEND mode requires a {uuid} label in filename_pattern"); + } if (user_set_use_tmp_file && per_thread_output) { throw NotImplementedException("Can't combine USE_TMP_FILE and PER_THREAD_OUTPUT for COPY"); } @@ -133,6 +175,40 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt) { } } + // Allow the copy function to intercept the select list and types and push a new projection on top of the plan + if (copy_function.function.copy_to_select) { + auto bindings = select_node.plan->GetColumnBindings(); + + CopyToSelectInput input = {context, stmt.info->options, {}, copy_to_type}; + input.select_list.reserve(bindings.size()); + + // Create column references for the select list + for (idx_t i = 0; i < bindings.size(); i++) { + auto &binding = bindings[i]; + auto &name = select_node.names[i]; + auto &type = select_node.types[i]; + input.select_list.push_back(make_uniq(name, type, binding)); + } + + auto new_select_list = copy_function.function.copy_to_select(input); + if (!new_select_list.empty()) { + + // We have a new select list, create a projection on top of the current plan + auto projection = make_uniq(GenerateTableIndex(), std::move(new_select_list)); + projection->children.push_back(std::move(select_node.plan)); + projection->ResolveOperatorTypes(); + + // Update the names and types of the select node + select_node.names.clear(); + select_node.types.clear(); + for (auto &expr : projection->expressions) { + select_node.names.push_back(expr->GetName()); + select_node.types.push_back(expr->return_type); + } + select_node.plan = std::move(projection); + } + } + auto unique_column_names = select_node.names; QueryResult::DeduplicateColumns(unique_column_names); auto file_path = stmt.info->file_path; @@ -140,25 +216,58 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt) { auto function_data = copy_function.function.copy_to_bind(context, bind_input, unique_column_names, select_node.types); + const auto rotate = + copy_function.function.rotate_files && copy_function.function.rotate_files(*function_data, file_size_bytes); + if (rotate) { + if (!copy_function.function.rotate_next_file) { + throw InternalException("rotate_next_file not implemented for \"%s\"", copy_function.function.extension); + } + if (user_set_use_tmp_file) { + throw NotImplementedException( + "Can't combine USE_TMP_FILE and file rotation (e.g., ROW_GROUPS_PER_FILE) for COPY"); + } + if (!partition_cols.empty()) { + throw NotImplementedException( + "Can't combine file rotation (e.g., ROW_GROUPS_PER_FILE) and PARTITION_BY for COPY"); + } + } + // now create the copy information auto copy = make_uniq(copy_function.function, std::move(function_data), std::move(stmt.info)); copy->file_path = file_path; copy->use_tmp_file = use_tmp_file; - copy->overwrite_or_ignore = overwrite_or_ignore; + copy->overwrite_mode = overwrite_mode; copy->filename_pattern = filename_pattern; copy->file_extension = bind_input.file_extension; copy->per_thread_output = per_thread_output; if (file_size_bytes.IsValid()) { copy->file_size_bytes = file_size_bytes; } + copy->rotate = rotate; copy->partition_output = !partition_cols.empty(); copy->partition_columns = std::move(partition_cols); + copy->return_type = return_type; copy->names = unique_column_names; copy->expected_types = select_node.types; copy->AddChild(std::move(select_node.plan)); + auto &properties = GetStatementProperties(); + switch (copy->return_type) { + case CopyFunctionReturnType::CHANGED_ROWS: + properties.return_type = StatementReturnType::CHANGED_ROWS; + break; + case CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST: + properties.return_type = StatementReturnType::QUERY_RESULT; + break; + default: + throw NotImplementedException("Unknown CopyFunctionReturnType"); + } + + BoundStatement result; + result.names = GetCopyFunctionReturnNames(copy->return_type); + result.types = GetCopyFunctionReturnLogicalTypes(copy->return_type); result.plan = std::move(copy); return result; @@ -228,8 +337,8 @@ BoundStatement Binder::BindCopyFrom(CopyStatement &stmt) { return result; } -BoundStatement Binder::Bind(CopyStatement &stmt) { - if (!stmt.info->is_from && !stmt.select_statement) { +BoundStatement Binder::Bind(CopyStatement &stmt, CopyToType copy_to_type) { + if (!stmt.info->is_from && !stmt.info->select_statement) { // copy table into file without a query // generate SELECT * FROM table; auto ref = make_uniq(); @@ -246,14 +355,16 @@ BoundStatement Binder::Bind(CopyStatement &stmt) { } else { statement->select_list.push_back(make_uniq()); } - stmt.select_statement = std::move(statement); + stmt.info->select_statement = std::move(statement); } + + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; properties.return_type = StatementReturnType::CHANGED_ROWS; if (stmt.info->is_from) { return BindCopyFrom(stmt); } else { - return BindCopyTo(stmt); + return BindCopyTo(stmt, copy_to_type); } } diff --git a/src/planner/binder/statement/bind_copy_database.cpp b/src/planner/binder/statement/bind_copy_database.cpp index 7954e250058..c6cf8c00050 100644 --- a/src/planner/binder/statement/bind_copy_database.cpp +++ b/src/planner/binder/statement/bind_copy_database.cpp @@ -15,81 +15,31 @@ #include "duckdb/planner/expression/bound_constant_expression.hpp" #include "duckdb/planner/operator/logical_dummy_scan.hpp" #include "duckdb/planner/operator/logical_expression_get.hpp" +#include "duckdb/catalog/duck_catalog.hpp" +#include "duckdb/catalog/dependency_manager.hpp" namespace duckdb { -unique_ptr Binder::BindCopyDatabaseSchema(Catalog &source_catalog, - const string &target_database_name) { - auto source_schemas = source_catalog.GetSchemas(context); +unique_ptr Binder::BindCopyDatabaseSchema(Catalog &from_database, const string &target_database_name) { - ExportEntries entries; - PhysicalExport::ExtractEntries(context, source_schemas, entries); + catalog_entry_vector_t catalog_entries; + catalog_entries = PhysicalExport::GetNaiveExportOrder(context, from_database); auto info = make_uniq(target_database_name); - - // get a list of all schemas to copy over - for (auto &schema_ref : source_schemas) { - auto &schema = schema_ref.get().Cast(); - if (schema.internal) { - continue; - } - auto create_info = schema.GetInfo(); - create_info->catalog = target_database_name; - create_info->on_conflict = OnCreateConflict::IGNORE_ON_CONFLICT; - info->entries.push_back(std::move(create_info)); - } - // get a list of all types to copy over - for (auto &seq_ref : entries.sequences) { - auto &seq_entry = seq_ref.get().Cast(); - if (seq_entry.internal) { - continue; - } - auto create_info = seq_entry.GetInfo(); - create_info->catalog = target_database_name; - create_info->on_conflict = OnCreateConflict::ERROR_ON_CONFLICT; - info->entries.push_back(std::move(create_info)); - } - // get a list of all types to copy over - for (auto &type_ref : entries.custom_types) { - auto &type_entry = type_ref.get().Cast(); - if (type_entry.internal) { - continue; - } - auto create_info = type_entry.GetInfo(); + for (auto &entry : catalog_entries) { + auto create_info = entry.get().GetInfo(); create_info->catalog = target_database_name; - create_info->on_conflict = OnCreateConflict::ERROR_ON_CONFLICT; - info->entries.push_back(std::move(create_info)); - } - // get a list of all tables to copy over - for (auto &table_ref : entries.tables) { - auto &table = table_ref.get().Cast(); - if (table.internal) { - continue; + auto on_conflict = create_info->type == CatalogType::SCHEMA_ENTRY ? OnCreateConflict::IGNORE_ON_CONFLICT + : OnCreateConflict::ERROR_ON_CONFLICT; + // Update all the dependencies of the entry to point to the newly created entries on the target database + LogicalDependencyList altered_dependencies; + for (auto &dep : create_info->dependencies.Set()) { + auto altered_dep = dep; + altered_dep.catalog = target_database_name; + altered_dependencies.AddDependency(altered_dep); } - auto create_info = table.GetInfo(); - create_info->catalog = target_database_name; - create_info->on_conflict = OnCreateConflict::ERROR_ON_CONFLICT; - info->entries.push_back(std::move(create_info)); - } - for (auto ¯o_ref : entries.macros) { - auto ¯o = macro_ref.get().Cast(); - if (macro.internal) { - continue; - } - auto create_info = macro.GetInfo(); - create_info->catalog = target_database_name; - create_info->on_conflict = OnCreateConflict::ERROR_ON_CONFLICT; - info->entries.push_back(std::move(create_info)); - } - // get a list of all views to copy over - for (auto &view_ref : entries.views) { - auto &view = view_ref.get().Cast(); - if (view.internal) { - continue; - } - auto create_info = view.GetInfo(); - create_info->catalog = target_database_name; - create_info->on_conflict = OnCreateConflict::ERROR_ON_CONFLICT; + create_info->dependencies = altered_dependencies; + create_info->on_conflict = on_conflict; info->entries.push_back(std::move(create_info)); } @@ -100,6 +50,7 @@ unique_ptr Binder::BindCopyDatabaseSchema(Catalog &source_catal unique_ptr Binder::BindCopyDatabaseData(Catalog &source_catalog, const string &target_database_name) { auto source_schemas = source_catalog.GetSchemas(context); + // We can just use ExtractEntries here because the order doesn't matter ExportEntries entries; PhysicalExport::ExtractEntries(context, source_schemas, entries); @@ -173,6 +124,8 @@ BoundStatement Binder::Bind(CopyDatabaseStatement &stmt) { } result.plan = std::move(plan); + + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; properties.return_type = StatementReturnType::NOTHING; properties.modified_databases.insert(target_catalog.GetName()); diff --git a/src/planner/binder/statement/bind_create.cpp b/src/planner/binder/statement/bind_create.cpp index 8f66ea03cc4..b8c5c7bc19d 100644 --- a/src/planner/binder/statement/bind_create.cpp +++ b/src/planner/binder/statement/bind_create.cpp @@ -121,6 +121,7 @@ SchemaCatalogEntry &Binder::BindSchema(CreateInfo &info) { D_ASSERT(schema_obj.type == CatalogType::SCHEMA_ENTRY); info.schema = schema_obj.name; if (!info.temporary) { + auto &properties = GetStatementProperties(); properties.modified_databases.insert(schema_obj.catalog.GetName()); } return schema_obj; @@ -134,10 +135,29 @@ SchemaCatalogEntry &Binder::BindCreateSchema(CreateInfo &info) { return schema; } +void Binder::SetCatalogLookupCallback(catalog_entry_callback_t callback) { + entry_retriever.SetCallback(std::move(callback)); +} + void Binder::BindCreateViewInfo(CreateViewInfo &base) { // bind the view as if it were a query so we can catch errors // note that we bind the original, and replace the original with a copy auto view_binder = Binder::CreateBinder(context); + auto &dependencies = base.dependencies; + auto &catalog = Catalog::GetCatalog(context, base.catalog); + + auto &db_config = DBConfig::GetConfig(context); + auto should_create_dependencies = db_config.options.enable_view_dependencies; + + if (should_create_dependencies) { + view_binder->SetCatalogLookupCallback([&dependencies, &catalog](CatalogEntry &entry) { + if (&catalog != &entry.ParentCatalog()) { + // Don't register dependencies between catalogs + return; + } + dependencies.AddDependency(entry); + }); + } view_binder->can_contain_nulls = true; auto copy = base.query->Copy(); @@ -188,6 +208,21 @@ SchemaCatalogEntry &Binder::BindCreateFunctionInfo(CreateInfo &info) { BoundSelectNode sel_node; BoundGroupInformation group_info; SelectBinder binder(*this, context, sel_node, group_info); + auto &dependencies = base.dependencies; + auto &catalog = Catalog::GetCatalog(context, info.catalog); + auto &db_config = DBConfig::GetConfig(context); + auto should_create_dependencies = db_config.options.enable_macro_dependencies; + + if (should_create_dependencies) { + binder.SetCatalogLookupCallback([&dependencies, &catalog](CatalogEntry &entry) { + if (&catalog != &entry.ParentCatalog()) { + // Don't register any cross-catalog dependencies + return; + } + // Register any catalog entry required to bind the macro function + dependencies.AddDependency(entry); + }); + } error = binder.Bind(expression, 0, false); if (error.HasError()) { error.Throw(); @@ -196,12 +231,12 @@ SchemaCatalogEntry &Binder::BindCreateFunctionInfo(CreateInfo &info) { return BindCreateSchema(info); } -void Binder::BindLogicalType(ClientContext &context, LogicalType &type, optional_ptr catalog, - const string &schema) { +void Binder::BindLogicalType(LogicalType &type, optional_ptr catalog, const string &schema) { if (type.id() == LogicalTypeId::LIST || type.id() == LogicalTypeId::MAP) { auto child_type = ListType::GetChildType(type); - BindLogicalType(context, child_type, catalog, schema); + BindLogicalType(child_type, catalog, schema); auto alias = type.GetAlias(); + auto modifiers = type.GetModifiersCopy(); if (type.id() == LogicalTypeId::LIST) { type = LogicalType::LIST(child_type); } else { @@ -210,54 +245,116 @@ void Binder::BindLogicalType(ClientContext &context, LogicalType &type, optional } type.SetAlias(alias); + type.SetModifiers(modifiers); } else if (type.id() == LogicalTypeId::STRUCT) { auto child_types = StructType::GetChildTypes(type); for (auto &child_type : child_types) { - BindLogicalType(context, child_type.second, catalog, schema); + BindLogicalType(child_type.second, catalog, schema); } // Generate new Struct Type auto alias = type.GetAlias(); + auto modifiers = type.GetModifiersCopy(); type = LogicalType::STRUCT(child_types); type.SetAlias(alias); + type.SetModifiers(modifiers); } else if (type.id() == LogicalTypeId::ARRAY) { auto child_type = ArrayType::GetChildType(type); auto array_size = ArrayType::GetSize(type); - BindLogicalType(context, child_type, catalog, schema); + BindLogicalType(child_type, catalog, schema); auto alias = type.GetAlias(); + auto modifiers = type.GetModifiersCopy(); type = LogicalType::ARRAY(child_type, array_size); type.SetAlias(alias); + type.SetModifiers(modifiers); } else if (type.id() == LogicalTypeId::UNION) { auto member_types = UnionType::CopyMemberTypes(type); for (auto &member_type : member_types) { - BindLogicalType(context, member_type.second, catalog, schema); + BindLogicalType(member_type.second, catalog, schema); } // Generate new Union Type auto alias = type.GetAlias(); + auto modifiers = type.GetModifiersCopy(); type = LogicalType::UNION(member_types); type.SetAlias(alias); + type.SetModifiers(modifiers); } else if (type.id() == LogicalTypeId::USER) { auto user_type_name = UserType::GetTypeName(type); + auto user_type_mods = UserType::GetTypeModifiers(type); + + bind_type_modifiers_function_t user_bind_modifiers_func = nullptr; + if (catalog) { // The search order is: // 1) In the same schema as the table // 2) In the same catalog // 3) System catalog - type = catalog->GetType(context, schema, user_type_name, OnEntryNotFound::RETURN_NULL); - - if (type.id() == LogicalTypeId::INVALID) { - type = catalog->GetType(context, INVALID_SCHEMA, user_type_name, OnEntryNotFound::RETURN_NULL); - } - - if (type.id() == LogicalTypeId::INVALID) { - type = Catalog::GetType(context, INVALID_CATALOG, INVALID_SCHEMA, user_type_name); + auto entry = entry_retriever.GetEntry(CatalogType::TYPE_ENTRY, *catalog, schema, user_type_name, + OnEntryNotFound::RETURN_NULL); + if (!entry || entry->Cast().user_type.id() == LogicalTypeId::INVALID) { + entry = entry_retriever.GetEntry(CatalogType::TYPE_ENTRY, *catalog, INVALID_SCHEMA, user_type_name, + OnEntryNotFound::RETURN_NULL); + if (!entry || entry->Cast().user_type.id() == LogicalTypeId::INVALID) { + entry = entry_retriever.GetEntry(CatalogType::TYPE_ENTRY, INVALID_CATALOG, INVALID_SCHEMA, + user_type_name, OnEntryNotFound::THROW_EXCEPTION); + } } + auto &type_entry = entry->Cast(); + type = type_entry.user_type; + user_bind_modifiers_func = type_entry.bind_modifiers; } else { string type_catalog = UserType::GetCatalog(type); string type_schema = UserType::GetSchema(type); + BindSchemaOrCatalog(context, type_catalog, type_schema); - type = Catalog::GetType(context, type_catalog, type_schema, user_type_name); + auto entry = entry_retriever.GetEntry(CatalogType::TYPE_ENTRY, type_catalog, type_schema, user_type_name); + auto &type_entry = entry->Cast(); + type = type_entry.user_type; + user_bind_modifiers_func = type_entry.bind_modifiers; + } + + BindLogicalType(type, catalog, schema); + + // Apply the type modifiers (if any) + if (user_bind_modifiers_func) { + // If an explicit bind_modifiers function was provided, use that to set the type modifier + BindTypeModifiersInput input {context, type, user_type_mods}; + type = user_bind_modifiers_func(input); + } else if (type.HasModifiers()) { + // If the type already has modifiers, try to replace them with the user-provided ones if they are compatible + // This enables registering custom types with "default" type modifiers that can be overridden, without + // having to provide a custom bind_modifiers function + auto type_mods_size = type.GetModifiers()->size(); + + // Are we trying to pass more type modifiers than the type has? + if (user_type_mods.size() > type_mods_size) { + throw BinderException( + "Cannot apply '%d' type modifier(s) to type '%s' taking at most '%d' type modifier(s)", + user_type_mods.size(), user_type_name, type_mods_size); + } + + // Deep copy the type so that we can replace the type modifiers + type = type.DeepCopy(); + + // Re-fetch the type modifiers now that we've deduplicated the ExtraTypeInfo + auto &type_mods = *type.GetModifiers(); + + // Replace them in order, casting if necessary + for (idx_t i = 0; i < MinValue(type_mods.size(), user_type_mods.size()); i++) { + auto &type_mod = type_mods[i]; + auto user_type_mod = user_type_mods[i]; + if (type_mod.type() == user_type_mod.type()) { + type_mod = std::move(user_type_mod); + } else if (user_type_mod.DefaultTryCastAs(type_mod.type())) { + type_mod = std::move(user_type_mod); + } else { + throw BinderException("Cannot apply type modifier '%s' to type '%s', expected value of type '%s'", + user_type_mod.ToString(), user_type_name, type_mod.type().ToString()); + } + } + } else if (!user_type_mods.empty()) { + // We're trying to pass type modifiers to a type that doesnt have any + throw BinderException("Type '%s' does not take any type modifiers", user_type_name); } - BindLogicalType(context, type, catalog, schema); } } @@ -447,6 +544,15 @@ unique_ptr DuckCatalog::BindCreateIndex(Binder &binder, CreateS auto &get = plan->Cast(); // bind the index expressions IndexBinder index_binder(binder, binder.context); + auto &dependencies = base.dependencies; + auto &catalog = Catalog::GetCatalog(binder.context, base.catalog); + index_binder.SetCatalogLookupCallback([&dependencies, &catalog](CatalogEntry &entry) { + if (&catalog != &entry.ParentCatalog()) { + // Don't register any cross-catalog dependencies + return; + } + dependencies.AddDependency(entry); + }); vector> expressions; expressions.reserve(base.expressions.size()); for (auto &expr : base.expressions) { @@ -479,6 +585,7 @@ BoundStatement Binder::Bind(CreateStatement &stmt) { result.types = {LogicalType::BIGINT}; auto catalog_type = stmt.info->type; + auto &properties = GetStatementProperties(); switch (catalog_type) { case CatalogType::SCHEMA_ENTRY: { auto &base = stmt.info->Cast(); @@ -509,16 +616,14 @@ BoundStatement Binder::Bind(CreateStatement &stmt) { } case CatalogType::MACRO_ENTRY: { auto &schema = BindCreateFunctionInfo(*stmt.info); - result.plan = + auto logical_create = make_uniq(LogicalOperatorType::LOGICAL_CREATE_MACRO, std::move(stmt.info), &schema); + result.plan = std::move(logical_create); break; } case CatalogType::INDEX_ENTRY: { auto &base = stmt.info->Cast(); - auto catalog = BindCatalog(base.catalog); - properties.modified_databases.insert(catalog); - // visit the table reference auto table_ref = make_uniq(); table_ref->catalog_name = base.catalog; @@ -534,6 +639,8 @@ BoundStatement Binder::Bind(CreateStatement &stmt) { if (table.temporary) { stmt.info->temporary = true; } + properties.modified_databases.insert(table.catalog.GetName()); + // create a plan over the bound table auto plan = CreatePlan(*bound_table); if (plan->type != LogicalOperatorType::LOGICAL_GET) { @@ -566,16 +673,16 @@ BoundStatement Binder::Bind(CreateStatement &stmt) { CheckForeignKeyTypes(create_info.columns, create_info.columns, fk); } else { // have to resolve referenced table - auto &pk_table_entry_ptr = - Catalog::GetEntry(context, INVALID_CATALOG, fk.info.schema, fk.info.table); + auto table_entry = + entry_retriever.GetEntry(CatalogType::TABLE_ENTRY, INVALID_CATALOG, fk.info.schema, fk.info.table); + auto &pk_table_entry_ptr = table_entry->Cast(); fk_schemas.insert(pk_table_entry_ptr.schema); FindMatchingPrimaryKeyColumns(pk_table_entry_ptr.GetColumns(), pk_table_entry_ptr.GetConstraints(), fk); FindForeignKeyIndexes(pk_table_entry_ptr.GetColumns(), fk.pk_columns, fk.info.pk_keys); CheckForeignKeyTypes(pk_table_entry_ptr.GetColumns(), create_info.columns, fk); auto &storage = pk_table_entry_ptr.GetStorage(); - auto index = storage.info->indexes.FindForeignKeyIndex(fk.info.pk_keys, - ForeignKeyType::FK_TYPE_PRIMARY_KEY_TABLE); - if (!index) { + + if (!storage.HasForeignKeyIndex(fk.info.pk_keys, ForeignKeyType::FK_TYPE_PRIMARY_KEY_TABLE)) { auto fk_column_names = StringUtil::Join(fk.pk_columns, ","); throw BinderException("Failed to create foreign key on %s(%s): no UNIQUE or PRIMARY KEY constraint " "present on these columns", @@ -612,6 +719,16 @@ BoundStatement Binder::Bind(CreateStatement &stmt) { auto &schema = BindCreateSchema(*stmt.info); auto &create_type_info = stmt.info->Cast(); result.plan = make_uniq(LogicalOperatorType::LOGICAL_CREATE_TYPE, std::move(stmt.info), &schema); + + auto &catalog = Catalog::GetCatalog(context, create_type_info.catalog); + auto &dependencies = create_type_info.dependencies; + auto dependency_callback = [&dependencies, &catalog](CatalogEntry &entry) { + if (&catalog != &entry.ParentCatalog()) { + // Don't register any cross-catalog dependencies + return; + } + dependencies.AddDependency(entry); + }; if (create_type_info.query) { // CREATE TYPE mood AS ENUM (SELECT 'happy') auto query_obj = Bind(*create_type_info.query); @@ -636,16 +753,23 @@ BoundStatement Binder::Bind(CreateStatement &stmt) { result.plan->AddChild(std::move(query)); } else if (create_type_info.type.id() == LogicalTypeId::USER) { + SetCatalogLookupCallback(dependency_callback); // two cases: // 1: create a type with a non-existent type as source, Binder::BindLogicalType(...) will throw exception. // 2: create a type alias with a custom type. // eg. CREATE TYPE a AS INT; CREATE TYPE b AS a; // We set b to be an alias for the underlying type of a - create_type_info.type = Catalog::GetType(context, schema.catalog.GetName(), schema.name, - UserType::GetTypeName(create_type_info.type)); + auto type_entry_p = entry_retriever.GetEntry(CatalogType::TYPE_ENTRY, schema.catalog.GetName(), schema.name, + UserType::GetTypeName(create_type_info.type)); + D_ASSERT(type_entry_p); + auto &type_entry = type_entry_p->Cast(); + create_type_info.type = type_entry.user_type; } else { + SetCatalogLookupCallback(dependency_callback); + // This is done so that if the type contains a USER type, + // we register this dependency auto preserved_type = create_type_info.type; - BindLogicalType(context, create_type_info.type); + BindLogicalType(create_type_info.type); create_type_info.type = preserved_type; } break; diff --git a/src/planner/binder/statement/bind_create_table.cpp b/src/planner/binder/statement/bind_create_table.cpp index 4651ede86de..ec39dae974f 100644 --- a/src/planner/binder/statement/bind_create_table.cpp +++ b/src/planner/binder/statement/bind_create_table.cpp @@ -201,6 +201,7 @@ void Binder::BindGeneratedColumns(BoundCreateTableInfo &info) { // Create a new binder because we dont need (or want) these bindings in this scope auto binder = Binder::CreateBinder(context); + binder->SetCatalogLookupCallback(entry_retriever.GetCallback()); binder->bind_context.AddGenericBinding(table_index, base.table, names, types); auto expr_binder = ExpressionBinder(*binder, context); ErrorData ignore; @@ -292,10 +293,18 @@ unique_ptr Binder::BindCreateTableInfo(unique_ptr Binder::BindCreateTableCheckpoint(unique_ptr info, + SchemaCatalogEntry &schema) { + auto result = make_uniq(schema, std::move(info)); + CreateColumnDependencyManager(*result); + return result; +} + unique_ptr Binder::BindCreateTableInfo(unique_ptr info, SchemaCatalogEntry &schema, vector> &bound_defaults) { auto &base = info->Cast(); auto result = make_uniq(schema, std::move(info)); + auto &dependencies = result->dependencies; vector> bound_constraints; if (base.query) { @@ -312,10 +321,14 @@ unique_ptr Binder::BindCreateTableInfo(unique_ptr Binder::BindCreateTableInfo(unique_ptrschema.catalog); + BindLogicalType(column.TypeMutable(), &result->schema.catalog); } result->dependencies.VerifyDependencies(schema.catalog, result->Base().table); + + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; return result; } diff --git a/src/planner/binder/statement/bind_delete.cpp b/src/planner/binder/statement/bind_delete.cpp index da170716077..c32b4b58482 100644 --- a/src/planner/binder/statement/bind_delete.cpp +++ b/src/planner/binder/statement/bind_delete.cpp @@ -29,6 +29,7 @@ BoundStatement Binder::Bind(DeleteStatement &stmt) { if (!table.temporary) { // delete from persistent table: not read only! + auto &properties = GetStatementProperties(); properties.modified_databases.insert(table.catalog.GetName()); } @@ -90,6 +91,8 @@ BoundStatement Binder::Bind(DeleteStatement &stmt) { result.plan = std::move(del); result.names = {"Count"}; result.types = {LogicalType::BIGINT}; + + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; properties.return_type = StatementReturnType::CHANGED_ROWS; diff --git a/src/planner/binder/statement/bind_detach.cpp b/src/planner/binder/statement/bind_detach.cpp index 14c99e9e1eb..98db5805596 100644 --- a/src/planner/binder/statement/bind_detach.cpp +++ b/src/planner/binder/statement/bind_detach.cpp @@ -11,6 +11,8 @@ BoundStatement Binder::Bind(DetachStatement &stmt) { result.plan = make_uniq(LogicalOperatorType::LOGICAL_DETACH, std::move(stmt.info)); result.names = {"Success"}; result.types = {LogicalType::BOOLEAN}; + + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; properties.return_type = StatementReturnType::NOTHING; return result; diff --git a/src/planner/binder/statement/bind_drop.cpp b/src/planner/binder/statement/bind_drop.cpp index 9c5f43dfaea..61973047148 100644 --- a/src/planner/binder/statement/bind_drop.cpp +++ b/src/planner/binder/statement/bind_drop.cpp @@ -14,6 +14,7 @@ namespace duckdb { BoundStatement Binder::Bind(DropStatement &stmt) { BoundStatement result; + auto &properties = GetStatementProperties(); switch (stmt.info->type) { case CatalogType::PREPARED_STATEMENT: // dropping prepared statements is always possible @@ -61,6 +62,7 @@ BoundStatement Binder::Bind(DropStatement &stmt) { result.plan = make_uniq(LogicalOperatorType::LOGICAL_DROP, std::move(stmt.info)); result.names = {"Success"}; result.types = {LogicalType::BOOLEAN}; + properties.allow_stream_result = false; properties.return_type = StatementReturnType::NOTHING; return result; diff --git a/src/planner/binder/statement/bind_execute.cpp b/src/planner/binder/statement/bind_execute.cpp index f235c14420d..b8c43c711f7 100644 --- a/src/planner/binder/statement/bind_execute.cpp +++ b/src/planner/binder/statement/bind_execute.cpp @@ -54,8 +54,10 @@ BoundStatement Binder::Bind(ExecuteStatement &stmt) { this->bound_tables = prepared_planner.binder->bound_tables; } // copy the properties of the prepared statement into the planner - this->properties = prepared->properties; - this->properties.parameter_count = parameter_count; + auto &properties = GetStatementProperties(); + properties = prepared->properties; + properties.parameter_count = parameter_count; + BoundStatement result; result.names = prepared->names; result.types = prepared->types; diff --git a/src/planner/binder/statement/bind_explain.cpp b/src/planner/binder/statement/bind_explain.cpp index 2e1fd3ac2be..ab18635649b 100644 --- a/src/planner/binder/statement/bind_explain.cpp +++ b/src/planner/binder/statement/bind_explain.cpp @@ -17,6 +17,8 @@ BoundStatement Binder::Bind(ExplainStatement &stmt) { result.plan = std::move(explain); result.names = {"explain_key", "explain_value"}; result.types = {LogicalType::VARCHAR, LogicalType::VARCHAR}; + + auto &properties = GetStatementProperties(); properties.return_type = StatementReturnType::QUERY_RESULT; return result; } diff --git a/src/planner/binder/statement/bind_export.cpp b/src/planner/binder/statement/bind_export.cpp index 7e25c66d1a7..19abaf3a8a1 100644 --- a/src/planner/binder/statement/bind_export.cpp +++ b/src/planner/binder/statement/bind_export.cpp @@ -117,100 +117,7 @@ string CreateFileName(const string &id_suffix, TableCatalogEntry &table, const s return StringUtil::Format("%s_%s%s.%s", schema, name, id_suffix, extension); } -static bool IsSupported(CopyTypeSupport support_level) { - // For export purposes we don't want to lose information, so we only accept fully supported types - return support_level == CopyTypeSupport::SUPPORTED; -} - -static LogicalType AlterLogicalType(const LogicalType &original, copy_supports_type_t type_check) { - D_ASSERT(type_check); - auto id = original.id(); - switch (id) { - case LogicalTypeId::LIST: { - auto child = AlterLogicalType(ListType::GetChildType(original), type_check); - return LogicalType::LIST(child); - } - case LogicalTypeId::ARRAY: { - // Attempt to convert the array to a list - auto &child = ArrayType::GetChildType(original); - return AlterLogicalType(LogicalType::LIST(child), type_check); - } - case LogicalTypeId::STRUCT: { - auto &original_children = StructType::GetChildTypes(original); - child_list_t new_children; - for (auto &child : original_children) { - auto &child_name = child.first; - auto &child_type = child.second; - - LogicalType new_type; - if (!IsSupported(type_check(child_type))) { - new_type = AlterLogicalType(child_type, type_check); - } else { - new_type = child_type; - } - new_children.push_back(std::make_pair(child_name, new_type)); - } - return LogicalType::STRUCT(std::move(new_children)); - } - case LogicalTypeId::UNION: { - auto member_count = UnionType::GetMemberCount(original); - child_list_t new_children; - for (idx_t i = 0; i < member_count; i++) { - auto &child_name = UnionType::GetMemberName(original, i); - auto &child_type = UnionType::GetMemberType(original, i); - - LogicalType new_type; - if (!IsSupported(type_check(child_type))) { - new_type = AlterLogicalType(child_type, type_check); - } else { - new_type = child_type; - } - - new_children.push_back(std::make_pair(child_name, new_type)); - } - return LogicalType::UNION(std::move(new_children)); - } - case LogicalTypeId::MAP: { - auto &key_type = MapType::KeyType(original); - auto &value_type = MapType::ValueType(original); - - LogicalType new_key_type; - LogicalType new_value_type; - if (!IsSupported(type_check(key_type))) { - new_key_type = AlterLogicalType(key_type, type_check); - } else { - new_key_type = key_type; - } - - if (!IsSupported(type_check(value_type))) { - new_value_type = AlterLogicalType(value_type, type_check); - } else { - new_value_type = value_type; - } - return LogicalType::MAP(new_key_type, new_value_type); - } - default: { - D_ASSERT(!IsSupported(type_check(original))); - return LogicalType::VARCHAR; - } - } -} - -static bool NeedsCast(LogicalType &type, copy_supports_type_t type_check) { - if (!type_check) { - return false; - } - if (IsSupported(type_check(type))) { - // The type is supported in it's entirety, no cast is required - return false; - } - // Change the type to something that is supported - type = AlterLogicalType(type, type_check); - return true; -} - -static unique_ptr CreateSelectStatement(CopyStatement &stmt, child_list_t &select_list, - copy_supports_type_t type_check) { +static unique_ptr CreateSelectStatement(CopyStatement &stmt, child_list_t &select_list) { auto ref = make_uniq(); ref->catalog_name = stmt.info->catalog; ref->schema_name = stmt.info->schema; @@ -221,14 +128,7 @@ static unique_ptr CreateSelectStatement(CopyStatement &stmt, child_li vector> expressions; for (auto &col : select_list) { - auto &name = col.first; - auto &type = col.second; - - auto expression = make_uniq_base(name); - if (NeedsCast(type, type_check)) { - // Add a cast to a type supported by the copy function - expression = make_uniq_base(type, std::move(expression)); - } + auto expression = make_uniq_base(col.first); expressions.push_back(std::move(expression)); } @@ -330,11 +230,11 @@ BoundStatement Binder::Bind(ExportStatement &stmt) { // generate the copy statement and bind it CopyStatement copy_stmt; copy_stmt.info = std::move(info); - copy_stmt.select_statement = - CreateSelectStatement(copy_stmt, select_list, copy_function.function.supports_type); + copy_stmt.info->select_statement = CreateSelectStatement(copy_stmt, select_list); auto copy_binder = Binder::CreateBinder(context, this); - auto bound_statement = copy_binder->Bind(copy_stmt); + auto bound_statement = copy_binder->Bind(copy_stmt, CopyToType::EXPORT_DATABASE); + auto plan = std::move(bound_statement.plan); if (child_operator) { @@ -353,6 +253,7 @@ BoundStatement Binder::Bind(ExportStatement &stmt) { fs.CreateDirectory(stmt.info->file_path); } + stmt.info->catalog = catalog; // create the export node auto export_node = make_uniq(copy_function.function, std::move(stmt.info), exported_tables); @@ -361,6 +262,8 @@ BoundStatement Binder::Bind(ExportStatement &stmt) { } result.plan = std::move(export_node); + + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; properties.return_type = StatementReturnType::NOTHING; return result; diff --git a/src/planner/binder/statement/bind_extension.cpp b/src/planner/binder/statement/bind_extension.cpp index f0884cdcd5c..c258530922f 100644 --- a/src/planner/binder/statement/bind_extension.cpp +++ b/src/planner/binder/statement/bind_extension.cpp @@ -12,6 +12,7 @@ BoundStatement Binder::Bind(ExtensionStatement &stmt) { auto parse_result = stmt.extension.plan_function(stmt.extension.parser_info.get(), context, std::move(stmt.parse_data)); + auto &properties = GetStatementProperties(); properties.modified_databases = parse_result.modified_databases; properties.requires_valid_transaction = parse_result.requires_valid_transaction; properties.return_type = parse_result.return_type; diff --git a/src/planner/binder/statement/bind_insert.cpp b/src/planner/binder/statement/bind_insert.cpp index 13ad3ea7ca9..ec565c56ac1 100644 --- a/src/planner/binder/statement/bind_insert.cpp +++ b/src/planner/binder/statement/bind_insert.cpp @@ -1,5 +1,6 @@ #include "duckdb/catalog/catalog.hpp" #include "duckdb/parser/expression/constant_expression.hpp" +#include "duckdb/parser/expression/function_expression.hpp" #include "duckdb/parser/statement/insert_statement.hpp" #include "duckdb/parser/query_node/select_node.hpp" #include "duckdb/parser/tableref/expressionlistref.hpp" @@ -12,13 +13,10 @@ #include "duckdb/planner/operator/logical_dummy_scan.hpp" #include "duckdb/planner/operator/logical_projection.hpp" #include "duckdb/planner/expression_iterator.hpp" -#include "duckdb/planner/expression_binder/returning_binder.hpp" #include "duckdb/planner/expression_binder/where_binder.hpp" #include "duckdb/planner/expression_binder/update_binder.hpp" -#include "duckdb/planner/operator/logical_filter.hpp" #include "duckdb/parser/statement/update_statement.hpp" #include "duckdb/planner/expression/bound_default_expression.hpp" -#include "duckdb/storage/data_table.hpp" #include "duckdb/catalog/catalog_entry/index_catalog_entry.hpp" #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" #include "duckdb/planner/bound_tableref.hpp" @@ -54,18 +52,85 @@ void ReplaceDefaultExpression(unique_ptr &expr, const ColumnDe expr = ExpandDefaultExpression(column); } -void QualifyColumnReferences(unique_ptr &expr, const string &table_name) { - // To avoid ambiguity with 'excluded', we explicitly qualify all column references - if (expr->type == ExpressionType::COLUMN_REF) { - auto &column_ref = expr->Cast(); - if (column_ref.IsQualified()) { +void ExpressionBinder::DoUpdateSetQualifyInLambda(FunctionExpression &function, const string &table_name, + vector> &lambda_params) { + + for (auto &child : function.children) { + if (child->expression_class != ExpressionClass::LAMBDA) { + DoUpdateSetQualify(child, table_name, lambda_params); + continue; + } + + // Special-handling for LHS lambda parameters. + // We do not qualify them, and we add them to the lambda_params vector. + auto &lambda_expr = child->Cast(); + string error_message; + auto column_ref_expressions = lambda_expr.ExtractColumnRefExpressions(error_message); + + if (!error_message.empty()) { + // Possibly a JSON function, qualify both LHS and RHS. + ParsedExpressionIterator::EnumerateChildren(*lambda_expr.lhs, [&](unique_ptr &child) { + DoUpdateSetQualify(child, table_name, lambda_params); + }); + ParsedExpressionIterator::EnumerateChildren(*lambda_expr.expr, [&](unique_ptr &child) { + DoUpdateSetQualify(child, table_name, lambda_params); + }); + continue; + } + + // Push the lambda parameter names of this level. + lambda_params.emplace_back(); + for (const auto &column_ref_expr : column_ref_expressions) { + const auto &column_ref = column_ref_expr.get().Cast(); + lambda_params.back().emplace(column_ref.GetName()); + } + + // Only qualify in the RHS of the expression. + ParsedExpressionIterator::EnumerateChildren(*lambda_expr.expr, [&](unique_ptr &child) { + DoUpdateSetQualify(child, table_name, lambda_params); + }); + + lambda_params.pop_back(); + } +} + +void ExpressionBinder::DoUpdateSetQualify(unique_ptr &expr, const string &table_name, + vector> &lambda_params) { + + // We avoid ambiguity with EXCLUDED columns by qualifying all column references. + switch (expr->GetExpressionClass()) { + case ExpressionClass::COLUMN_REF: { + auto &col_ref = expr->Cast(); + if (col_ref.IsQualified()) { + return; + } + + // Don't qualify lambda parameters. + if (LambdaExpression::IsLambdaParameter(lambda_params, col_ref.GetName())) { return; } - auto column_name = column_ref.GetColumnName(); - expr = make_uniq(column_name, table_name); + + // Qualify the column reference. + expr = make_uniq(col_ref.GetColumnName(), table_name); + return; + } + case ExpressionClass::FUNCTION: { + // Special-handling for lambdas, which are inside function expressions. + auto &function = expr->Cast(); + if (function.IsLambdaFunction()) { + return DoUpdateSetQualifyInLambda(function, table_name, lambda_params); + } + break; + } + case ExpressionClass::SUBQUERY: { + throw BinderException("DO UPDATE SET clause cannot contain a subquery"); } + default: + break; + } + ParsedExpressionIterator::EnumerateChildren( - *expr, [&](unique_ptr &child) { QualifyColumnReferences(child, table_name); }); + *expr, [&](unique_ptr &child) { DoUpdateSetQualify(child, table_name, lambda_params); }); } // Replace binding.table_index with 'dest' if it's 'source' @@ -110,18 +175,17 @@ void Binder::BindDoUpdateSetExpressions(const string &table_alias, LogicalInsert if (expr->type == ExpressionType::VALUE_DEFAULT) { expr = ExpandDefaultExpression(column); } - UpdateBinder binder(*this, context); - binder.target_type = column.Type(); - // Avoid ambiguity issues - QualifyColumnReferences(expr, table_alias); + // Qualify and bind the ON CONFLICT DO UPDATE SET expression. + UpdateBinder update_binder(*this, context); + update_binder.target_type = column.Type(); - auto bound_expr = binder.Bind(expr); - D_ASSERT(bound_expr); - if (bound_expr->expression_class == ExpressionClass::BOUND_SUBQUERY) { - throw BinderException("Expression in the DO UPDATE SET clause can not be a subquery"); - } + // Avoid ambiguity between existing table columns and EXCLUDED columns. + vector> lambda_params; + update_binder.DoUpdateSetQualify(expr, table_alias, lambda_params); + auto bound_expr = update_binder.Bind(expr); + D_ASSERT(bound_expr); insert.expressions.push_back(std::move(bound_expr)); } @@ -293,18 +357,17 @@ void Binder::BindOnConflictClause(LogicalInsert &insert, TableCatalogEntry &tabl bind_context.AddGenericBinding(excluded_index, "excluded", table_column_names, table_column_types); if (on_conflict.condition) { - // Avoid ambiguity between binding and 'excluded' - QualifyColumnReferences(on_conflict.condition, table_alias); - // Bind the ON CONFLICT ... WHERE clause WhereBinder where_binder(*this, context); + + // Avoid ambiguity between existing table columns and EXCLUDED columns. + vector> lambda_params; + where_binder.DoUpdateSetQualify(on_conflict.condition, table_alias, lambda_params); + + // Bind the ON CONFLICT ... WHERE clause. auto condition = where_binder.Bind(on_conflict.condition); - if (condition && condition->expression_class == ExpressionClass::BOUND_SUBQUERY) { - throw BinderException("conflict_target WHERE clause can not be a subquery"); - } insert.on_conflict_condition = std::move(condition); } - auto bindings = insert.children[0]->GetColumnBindings(); optional_idx projection_index; reference>> insert_child_operators = insert.children; while (!projection_index.IsValid()) { @@ -363,14 +426,14 @@ void Binder::BindOnConflictClause(LogicalInsert &insert, TableCatalogEntry &tabl D_ASSERT(set_info.columns.size() == set_info.expressions.size()); if (set_info.condition) { - // Avoid ambiguity between binding and 'excluded' - QualifyColumnReferences(set_info.condition, table_alias); - // Bind the SET ... WHERE clause WhereBinder where_binder(*this, context); + + // Avoid ambiguity between existing table columns and EXCLUDED columns. + vector> lambda_params; + where_binder.DoUpdateSetQualify(set_info.condition, table_alias, lambda_params); + + // Bind the SET ... WHERE clause. auto condition = where_binder.Bind(set_info.condition); - if (condition && condition->expression_class == ExpressionClass::BOUND_SUBQUERY) { - throw BinderException("conflict_target WHERE clause can not be a subquery"); - } insert.do_update_condition = std::move(condition); } @@ -402,6 +465,7 @@ BoundStatement Binder::Bind(InsertStatement &stmt) { auto &table = Catalog::GetEntry(context, stmt.catalog, stmt.schema, stmt.table); if (!table.temporary) { // inserting into a non-temporary table: alters underlying database + auto &properties = GetStatementProperties(); properties.modified_databases.insert(table.catalog.GetName()); } @@ -486,7 +550,7 @@ BoundStatement Binder::Bind(InsertStatement &stmt) { expr_list.expected_types.resize(expected_columns); expr_list.expected_names.resize(expected_columns); - D_ASSERT(expr_list.values.size() > 0); + D_ASSERT(!expr_list.values.empty()); CheckInsertColumnCountMismatch(expected_columns, expr_list.values[0].size(), !stmt.columns.empty(), table.name.c_str()); @@ -544,6 +608,8 @@ BoundStatement Binder::Bind(InsertStatement &stmt) { D_ASSERT(result.types.size() == result.names.size()); result.plan = std::move(insert); + + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; properties.return_type = StatementReturnType::CHANGED_ROWS; return result; diff --git a/src/planner/binder/statement/bind_load.cpp b/src/planner/binder/statement/bind_load.cpp index a179ba2b7bd..53d8f57922e 100644 --- a/src/planner/binder/statement/bind_load.cpp +++ b/src/planner/binder/statement/bind_load.cpp @@ -1,6 +1,7 @@ #include "duckdb/parser/statement/load_statement.hpp" #include "duckdb/planner/binder.hpp" #include "duckdb/planner/operator/logical_simple.hpp" +#include "duckdb/main/extension_install_info.hpp" #include namespace duckdb { @@ -10,7 +11,19 @@ BoundStatement Binder::Bind(LoadStatement &stmt) { result.types = {LogicalType::BOOLEAN}; result.names = {"Success"}; + // Ensure the repository exists if it's an alias + if (!stmt.info->repository.empty() && stmt.info->repo_is_alias) { + auto repository_url = ExtensionRepository::TryGetRepositoryUrl(stmt.info->repository); + if (repository_url.empty()) { + throw BinderException("'%s' is not a known repository name. Are you trying to query from a repository by " + "path? Use single quotes: `FROM '%s'`", + stmt.info->repository, stmt.info->repository); + } + } + result.plan = make_uniq(LogicalOperatorType::LOGICAL_LOAD, std::move(stmt.info)); + + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; properties.return_type = StatementReturnType::NOTHING; return result; diff --git a/src/planner/binder/statement/bind_logical_plan.cpp b/src/planner/binder/statement/bind_logical_plan.cpp index 9a7ae93abbd..5b187c8e3e2 100644 --- a/src/planner/binder/statement/bind_logical_plan.cpp +++ b/src/planner/binder/statement/bind_logical_plan.cpp @@ -24,6 +24,8 @@ BoundStatement Binder::Bind(LogicalPlanStatement &stmt) { result.names.push_back(StringUtil::Format("col%d", i)); } result.plan = std::move(stmt.plan); + + auto &properties = GetStatementProperties(); properties.allow_stream_result = true; properties.return_type = StatementReturnType::QUERY_RESULT; // TODO could also be something else diff --git a/src/planner/binder/statement/bind_pragma.cpp b/src/planner/binder/statement/bind_pragma.cpp index 61bf0672082..8f89dec5b66 100644 --- a/src/planner/binder/statement/bind_pragma.cpp +++ b/src/planner/binder/statement/bind_pragma.cpp @@ -55,6 +55,8 @@ BoundStatement Binder::Bind(PragmaStatement &stmt) { result.names = {"Success"}; result.types = {LogicalType::BOOLEAN}; result.plan = make_uniq(std::move(bound_info)); + + auto &properties = GetStatementProperties(); properties.return_type = StatementReturnType::QUERY_RESULT; return result; } diff --git a/src/planner/binder/statement/bind_prepare.cpp b/src/planner/binder/statement/bind_prepare.cpp index 700e91756a7..74062e41333 100644 --- a/src/planner/binder/statement/bind_prepare.cpp +++ b/src/planner/binder/statement/bind_prepare.cpp @@ -13,6 +13,7 @@ BoundStatement Binder::Bind(PrepareStatement &stmt) { auto prepare = make_uniq(stmt.name, std::move(prepared_data), std::move(prepared_planner.plan)); // we can always prepare, even if the transaction has been invalidated // this is required because most clients ALWAYS invoke prepared statements + auto &properties = GetStatementProperties(); properties.requires_valid_transaction = false; properties.allow_stream_result = false; properties.bound_all_parameters = true; diff --git a/src/planner/binder/statement/bind_select.cpp b/src/planner/binder/statement/bind_select.cpp index 711a07c573b..ee68d0e25ae 100644 --- a/src/planner/binder/statement/bind_select.cpp +++ b/src/planner/binder/statement/bind_select.cpp @@ -5,6 +5,7 @@ namespace duckdb { BoundStatement Binder::Bind(SelectStatement &stmt) { + auto &properties = GetStatementProperties(); properties.allow_stream_result = true; properties.return_type = StatementReturnType::QUERY_RESULT; return Bind(*stmt.node); diff --git a/src/planner/binder/statement/bind_set.cpp b/src/planner/binder/statement/bind_set.cpp index 77c23e22ffd..35c8484f8cc 100644 --- a/src/planner/binder/statement/bind_set.cpp +++ b/src/planner/binder/statement/bind_set.cpp @@ -21,6 +21,8 @@ BoundStatement Binder::Bind(SetVariableStatement &stmt) { auto value = ExpressionExecutor::EvaluateScalar(context, *bound_value, true); result.plan = make_uniq(stmt.name, std::move(value), stmt.scope); + + auto &properties = GetStatementProperties(); properties.return_type = StatementReturnType::NOTHING; return result; } @@ -31,6 +33,8 @@ BoundStatement Binder::Bind(ResetVariableStatement &stmt) { result.names = {"Success"}; result.plan = make_uniq(stmt.name, stmt.scope); + + auto &properties = GetStatementProperties(); properties.return_type = StatementReturnType::NOTHING; return result; } diff --git a/src/planner/binder/statement/bind_simple.cpp b/src/planner/binder/statement/bind_simple.cpp index 08c73ef8473..d285fc29dc7 100644 --- a/src/planner/binder/statement/bind_simple.cpp +++ b/src/planner/binder/statement/bind_simple.cpp @@ -17,23 +17,27 @@ BoundStatement Binder::Bind(AlterStatement &stmt) { BoundStatement result; result.names = {"Success"}; result.types = {LogicalType::BOOLEAN}; + BindSchemaOrCatalog(stmt.info->catalog, stmt.info->schema); optional_ptr entry; - if (stmt.info->type == AlterType::SET_COLUMN_COMMENT) { // for column comments we need to an extra step: they can alter a table or a view, we resolve that here. auto &info = stmt.info->Cast(); - entry = info.TryResolveCatalogEntry(context); + entry = info.TryResolveCatalogEntry(entry_retriever); } else { // All other AlterTypes - entry = Catalog::GetEntry(context, stmt.info->GetCatalogType(), stmt.info->catalog, stmt.info->schema, - stmt.info->name, stmt.info->if_not_found); + entry = entry_retriever.GetEntry(stmt.info->GetCatalogType(), stmt.info->catalog, stmt.info->schema, + stmt.info->name, stmt.info->if_not_found); } + auto &properties = GetStatementProperties(); if (entry) { D_ASSERT(!entry->deleted); auto &catalog = entry->ParentCatalog(); + if (catalog.IsSystemCatalog()) { + throw BinderException("Can not comment on System Catalog entries"); + } if (!entry->temporary) { // we can only alter temporary tables/views in read-only mode properties.modified_databases.insert(catalog.GetName()); @@ -47,6 +51,7 @@ BoundStatement Binder::Bind(AlterStatement &stmt) { } BoundStatement Binder::Bind(TransactionStatement &stmt) { + auto &properties = GetStatementProperties(); // transaction statements do not require a valid transaction properties.requires_valid_transaction = stmt.info->type == TransactionType::BEGIN_TRANSACTION; diff --git a/src/planner/binder/statement/bind_summarize.cpp b/src/planner/binder/statement/bind_summarize.cpp index e8eb87f3e38..6fb6403dbce 100644 --- a/src/planner/binder/statement/bind_summarize.cpp +++ b/src/planner/binder/statement/bind_summarize.cpp @@ -112,12 +112,15 @@ unique_ptr Binder::BindSummarize(ShowRef &ref) { if (plan.types[i].IsNumeric()) { avg_children.push_back(SummarizeCreateAggregate("avg", plan.names[i])); std_children.push_back(SummarizeCreateAggregate("stddev", plan.names[i])); + } else { + avg_children.push_back(make_uniq(Value())); + std_children.push_back(make_uniq(Value())); + } + if (plan.types[i].IsNumeric() || plan.types[i].IsTemporal()) { q25_children.push_back(SummarizeCreateAggregate("approx_quantile", plan.names[i], Value::FLOAT(0.25))); q50_children.push_back(SummarizeCreateAggregate("approx_quantile", plan.names[i], Value::FLOAT(0.50))); q75_children.push_back(SummarizeCreateAggregate("approx_quantile", plan.names[i], Value::FLOAT(0.75))); } else { - avg_children.push_back(make_uniq(Value())); - std_children.push_back(make_uniq(Value())); q25_children.push_back(make_uniq(Value())); q50_children.push_back(make_uniq(Value())); q75_children.push_back(make_uniq(Value())); diff --git a/src/planner/binder/statement/bind_update.cpp b/src/planner/binder/statement/bind_update.cpp index 2d0f6687ca6..5bfcfca400c 100644 --- a/src/planner/binder/statement/bind_update.cpp +++ b/src/planner/binder/statement/bind_update.cpp @@ -96,6 +96,7 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) { if (!table.temporary) { // update of persistent table: not read only! + auto &properties = GetStatementProperties(); properties.modified_databases.insert(table.catalog.GetName()); } auto update = make_uniq(table); @@ -149,6 +150,8 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) { result.names = {"Count"}; result.types = {LogicalType::BIGINT}; result.plan = std::move(update); + + auto &properties = GetStatementProperties(); properties.allow_stream_result = false; properties.return_type = StatementReturnType::CHANGED_ROWS; return result; diff --git a/src/planner/binder/statement/bind_update_extensions.cpp b/src/planner/binder/statement/bind_update_extensions.cpp new file mode 100644 index 00000000000..e355adc786c --- /dev/null +++ b/src/planner/binder/statement/bind_update_extensions.cpp @@ -0,0 +1,28 @@ +#include "duckdb/parser/statement/load_statement.hpp" +#include "duckdb/planner/binder.hpp" +#include "duckdb/parser/statement/update_extensions_statement.hpp" +#include "duckdb/planner/operator/logical_simple.hpp" +#include + +namespace duckdb { + +BoundStatement Binder::Bind(UpdateExtensionsStatement &stmt) { + BoundStatement result; + + result.names.emplace_back("extension_name"); + result.types.emplace_back(LogicalType::VARCHAR); + result.names.emplace_back("repository"); + result.types.emplace_back(LogicalType::VARCHAR); + result.names.emplace_back("update_result"); + result.types.emplace_back(LogicalType::VARCHAR); + result.names.emplace_back("previous_version"); + result.types.emplace_back(LogicalType::VARCHAR); + result.names.emplace_back("current_version"); + result.types.emplace_back(LogicalType::VARCHAR); + + result.plan = make_uniq(LogicalOperatorType::LOGICAL_UPDATE_EXTENSIONS, std::move(stmt.info)); + + return result; +} + +} // namespace duckdb diff --git a/src/planner/binder/statement/bind_vacuum.cpp b/src/planner/binder/statement/bind_vacuum.cpp index 5d48772eeab..729daf150c6 100644 --- a/src/planner/binder/statement/bind_vacuum.cpp +++ b/src/planner/binder/statement/bind_vacuum.cpp @@ -17,7 +17,7 @@ void Binder::BindVacuumTable(LogicalVacuum &vacuum, unique_ptr D_ASSERT(vacuum.column_id_map.empty()); auto bound_table = Bind(*info.ref); if (bound_table->type != TableReferenceType::BASE_TABLE) { - throw InvalidInputException("Can only vacuum/analyze base tables!"); + throw InvalidInputException("can only vacuum or analyze base tables"); } auto ref = unique_ptr_cast(std::move(bound_table)); auto &table = ref->table; @@ -35,7 +35,8 @@ void Binder::BindVacuumTable(LogicalVacuum &vacuum, unique_ptr vector non_generated_column_names; for (auto &col_name : columns) { if (column_name_set.count(col_name) > 0) { - throw BinderException("Vacuum the same column twice(same name in column name list)"); + throw BinderException("cannot vacuum or analyze the same column twice, i.e., there is a duplicate entry in " + "the list of column names"); } column_name_set.insert(col_name); if (!table.ColumnExists(col_name)) { @@ -89,6 +90,8 @@ BoundStatement Binder::Bind(VacuumStatement &stmt) { result.names = {"Success"}; result.types = {LogicalType::BOOLEAN}; result.plan = std::move(vacuum); + + auto &properties = GetStatementProperties(); properties.return_type = StatementReturnType::NOTHING; return result; } diff --git a/src/planner/binder/tableref/CMakeLists.txt b/src/planner/binder/tableref/CMakeLists.txt index f7002e01c65..fde1207c90e 100644 --- a/src/planner/binder/tableref/CMakeLists.txt +++ b/src/planner/binder/tableref/CMakeLists.txt @@ -4,6 +4,7 @@ add_library_unity( bind_basetableref.cpp bind_emptytableref.cpp bind_expressionlistref.cpp + bind_column_data_ref.cpp bind_joinref.cpp bind_pivot.cpp bind_showref.cpp @@ -13,6 +14,7 @@ add_library_unity( plan_basetableref.cpp plan_dummytableref.cpp plan_expressionlistref.cpp + plan_column_data_ref.cpp plan_joinref.cpp plan_subqueryref.cpp plan_table_function.cpp diff --git a/src/planner/binder/tableref/bind_basetableref.cpp b/src/planner/binder/tableref/bind_basetableref.cpp index 30b2b2640eb..5455a53a964 100644 --- a/src/planner/binder/tableref/bind_basetableref.cpp +++ b/src/planner/binder/tableref/bind_basetableref.cpp @@ -1,20 +1,20 @@ #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" #include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp" +#include "duckdb/common/string_util.hpp" +#include "duckdb/main/client_context.hpp" +#include "duckdb/main/config.hpp" +#include "duckdb/main/extension_helper.hpp" +#include "duckdb/parser/query_node/select_node.hpp" +#include "duckdb/parser/statement/select_statement.hpp" #include "duckdb/parser/tableref/basetableref.hpp" #include "duckdb/parser/tableref/subqueryref.hpp" -#include "duckdb/parser/query_node/select_node.hpp" +#include "duckdb/parser/tableref/table_function_ref.hpp" #include "duckdb/planner/binder.hpp" +#include "duckdb/planner/operator/logical_get.hpp" #include "duckdb/planner/tableref/bound_basetableref.hpp" -#include "duckdb/planner/tableref/bound_subqueryref.hpp" #include "duckdb/planner/tableref/bound_cteref.hpp" -#include "duckdb/planner/operator/logical_get.hpp" -#include "duckdb/parser/statement/select_statement.hpp" -#include "duckdb/common/string_util.hpp" -#include "duckdb/main/extension_helper.hpp" -#include "duckdb/parser/tableref/table_function_ref.hpp" -#include "duckdb/main/config.hpp" #include "duckdb/planner/tableref/bound_dummytableref.hpp" -#include "duckdb/main/client_context.hpp" +#include "duckdb/planner/tableref/bound_subqueryref.hpp" namespace duckdb { @@ -46,31 +46,36 @@ static bool TryLoadExtensionForReplacementScan(ClientContext &context, const str unique_ptr Binder::BindWithReplacementScan(ClientContext &context, const string &table_name, BaseTableRef &ref) { auto &config = DBConfig::GetConfig(context); - if (context.config.use_replacement_scans) { - for (auto &scan : config.replacement_scans) { - auto replacement_function = scan.function(context, table_name, scan.data.get()); - if (replacement_function) { - if (!ref.alias.empty()) { - // user-provided alias overrides the default alias - replacement_function->alias = ref.alias; - } else if (replacement_function->alias.empty()) { - // if the replacement scan itself did not provide an alias we use the table name - replacement_function->alias = ref.table_name; - } - if (replacement_function->type == TableReferenceType::TABLE_FUNCTION) { - auto &table_function = replacement_function->Cast(); - table_function.column_name_alias = ref.column_name_alias; - } else if (replacement_function->type == TableReferenceType::SUBQUERY) { - auto &subquery = replacement_function->Cast(); - subquery.column_name_alias = ref.column_name_alias; - } else { - throw InternalException("Replacement scan should return either a table function or a subquery"); - } - return Bind(*replacement_function); - } + if (!context.config.use_replacement_scans) { + return nullptr; + } + for (auto &scan : config.replacement_scans) { + ReplacementScanInput input(table_name); + auto replacement_function = scan.function(context, input, scan.data.get()); + if (!replacement_function) { + continue; + } + if (!ref.alias.empty()) { + // user-provided alias overrides the default alias + replacement_function->alias = ref.alias; + } else if (replacement_function->alias.empty()) { + // if the replacement scan itself did not provide an alias we use the table name + replacement_function->alias = ref.table_name; } + if (replacement_function->type == TableReferenceType::TABLE_FUNCTION) { + auto &table_function = replacement_function->Cast(); + table_function.column_name_alias = ref.column_name_alias; + } else if (replacement_function->type == TableReferenceType::SUBQUERY) { + auto &subquery = replacement_function->Cast(); + subquery.column_name_alias = ref.column_name_alias; + } else { + throw InternalException("Replacement scan should return either a table function or a subquery"); + } + if (GetBindingMode() == BindingMode::EXTRACT_REPLACEMENT_SCANS) { + AddReplacementScan(ref.table_name, replacement_function->Copy()); + } + return Bind(*replacement_function); } - return nullptr; } @@ -91,26 +96,8 @@ unique_ptr Binder::Bind(BaseTableRef &ref) { for (auto found_cte : found_ctes) { auto &cte = found_cte.get(); auto ctebinding = bind_context.GetCTEBinding(ref.table_name); - if (!ctebinding) { - if (CTEIsAlreadyBound(cte)) { - // remember error state - circular_cte = true; - // retry with next candidate CTE - continue; - } - // Move CTE to subquery and bind recursively - SubqueryRef subquery(unique_ptr_cast(cte.query->Copy())); - subquery.alias = ref.alias.empty() ? ref.table_name : ref.alias; - subquery.column_name_alias = cte.aliases; - for (idx_t i = 0; i < ref.column_name_alias.size(); i++) { - if (i < subquery.column_name_alias.size()) { - subquery.column_name_alias[i] = ref.column_name_alias[i]; - } else { - subquery.column_name_alias.push_back(ref.column_name_alias[i]); - } - } - return Bind(subquery, &found_cte.get()); - } else { + if (ctebinding && (cte.query->node->type == QueryNodeType::RECURSIVE_CTE_NODE || + cte.materialized == CTEMaterialize::CTE_MATERIALIZE_ALWAYS)) { // There is a CTE binding in the BindContext. // This can only be the case if there is a recursive CTE, // or a materialized CTE present. @@ -135,9 +122,39 @@ unique_ptr Binder::Bind(BaseTableRef &ref) { result->types = ctebinding->types; result->bound_columns = std::move(names); return std::move(result); + } else { + if (CTEIsAlreadyBound(cte)) { + // remember error state + circular_cte = true; + // retry with next candidate CTE + continue; + } + // Move CTE to subquery and bind recursively + SubqueryRef subquery(unique_ptr_cast(cte.query->Copy())); + subquery.alias = ref.alias.empty() ? ref.table_name : ref.alias; + subquery.column_name_alias = cte.aliases; + for (idx_t i = 0; i < ref.column_name_alias.size(); i++) { + if (i < subquery.column_name_alias.size()) { + subquery.column_name_alias[i] = ref.column_name_alias[i]; + } else { + subquery.column_name_alias.push_back(ref.column_name_alias[i]); + } + } + return Bind(subquery, &found_cte.get()); } } if (circular_cte) { + string table_name = ref.catalog_name; + if (!ref.schema_name.empty()) { + table_name += (!table_name.empty() ? "." : "") + ref.schema_name; + } + table_name += (!table_name.empty() ? "." : "") + ref.table_name; + + auto replacement_scan_bind_result = BindWithReplacementScan(context, table_name, ref); + if (replacement_scan_bind_result) { + return replacement_scan_bind_result; + } + throw BinderException( "Circular reference to CTE \"%s\", There are two possible solutions. \n1. use WITH RECURSIVE to " "use recursive CTEs. \n2. If " @@ -149,8 +166,8 @@ unique_ptr Binder::Bind(BaseTableRef &ref) { // not a CTE // extract a table or view from the catalog BindSchemaOrCatalog(ref.catalog_name, ref.schema_name); - auto table_or_view = Catalog::GetEntry(context, CatalogType::TABLE_ENTRY, ref.catalog_name, ref.schema_name, - ref.table_name, OnEntryNotFound::RETURN_NULL, error_context); + auto table_or_view = entry_retriever.GetEntry(CatalogType::TABLE_ENTRY, ref.catalog_name, ref.schema_name, + ref.table_name, OnEntryNotFound::RETURN_NULL, error_context); // we still didn't find the table if (GetBindingMode() == BindingMode::EXTRACT_NAMES) { if (!table_or_view || table_or_view->type == CatalogType::TABLE_ENTRY) { @@ -189,8 +206,8 @@ unique_ptr Binder::Bind(BaseTableRef &ref) { } // could not find an alternative: bind again to get the error - Catalog::GetEntry(context, CatalogType::TABLE_ENTRY, ref.catalog_name, ref.schema_name, ref.table_name, - OnEntryNotFound::THROW_EXCEPTION, error_context); + (void)entry_retriever.GetEntry(CatalogType::TABLE_ENTRY, ref.catalog_name, ref.schema_name, ref.table_name, + OnEntryNotFound::THROW_EXCEPTION, error_context); throw InternalException("Catalog::GetEntry should have thrown an exception above"); } @@ -199,6 +216,8 @@ unique_ptr Binder::Bind(BaseTableRef &ref) { // base table: create the BoundBaseTableRef node auto table_index = GenerateTableIndex(); auto &table = table_or_view->Cast(); + + auto &properties = GetStatementProperties(); properties.read_databases.insert(table.ParentCatalog().GetName()); unique_ptr bind_data; @@ -231,8 +250,7 @@ unique_ptr Binder::Bind(BaseTableRef &ref) { // We need to use a new binder for the view that doesn't reference any CTEs // defined for this binder so there are no collisions between the CTEs defined // for the view and for the current query - bool inherit_ctes = false; - auto view_binder = Binder::CreateBinder(context, this, inherit_ctes); + auto view_binder = Binder::CreateBinder(context, this, BinderType::VIEW_BINDER); view_binder->can_contain_nulls = true; SubqueryRef subquery(unique_ptr_cast(view_catalog_entry.query->Copy())); subquery.alias = ref.alias.empty() ? ref.table_name : ref.alias; diff --git a/src/planner/binder/tableref/bind_column_data_ref.cpp b/src/planner/binder/tableref/bind_column_data_ref.cpp new file mode 100644 index 00000000000..e6b2c45ef24 --- /dev/null +++ b/src/planner/binder/tableref/bind_column_data_ref.cpp @@ -0,0 +1,16 @@ +#include "duckdb/planner/binder.hpp" +#include "duckdb/parser/tableref/column_data_ref.hpp" +#include "duckdb/planner/tableref/bound_column_data_ref.hpp" +#include "duckdb/planner/operator/logical_column_data_get.hpp" + +namespace duckdb { + +unique_ptr Binder::Bind(ColumnDataRef &ref) { + auto types = ref.collection->Types(); + auto result = make_uniq(std::move(ref.collection)); + result->bind_index = GenerateTableIndex(); + bind_context.AddGenericBinding(result->bind_index, ref.alias, ref.expected_names, types); + return unique_ptr_cast(std::move(result)); +} + +} // namespace duckdb diff --git a/src/planner/binder/tableref/bind_joinref.cpp b/src/planner/binder/tableref/bind_joinref.cpp index 7d1d882210c..30f60b9cbbf 100644 --- a/src/planner/binder/tableref/bind_joinref.cpp +++ b/src/planner/binder/tableref/bind_joinref.cpp @@ -317,8 +317,15 @@ unique_ptr Binder::Bind(JoinRef &ref) { result->condition = binder.Bind(ref.condition); } - if (result->type == JoinType::SEMI || result->type == JoinType::ANTI) { + if (result->type == JoinType::SEMI || result->type == JoinType::ANTI || result->type == JoinType::MARK) { bind_context.RemoveContext(right_bindings_list_copy); + if (result->type == JoinType::MARK) { + auto mark_join_idx = GenerateTableIndex(); + string mark_join_alias = "__internal_mark_join_ref" + to_string(mark_join_idx); + bind_context.AddGenericBinding(mark_join_idx, mark_join_alias, {"__mark_index_column"}, + {LogicalType::BOOLEAN}); + result->mark_index = mark_join_idx; + } } return std::move(result); diff --git a/src/planner/binder/tableref/bind_pivot.cpp b/src/planner/binder/tableref/bind_pivot.cpp index f71bf410b38..7b1f776ad05 100644 --- a/src/planner/binder/tableref/bind_pivot.cpp +++ b/src/planner/binder/tableref/bind_pivot.cpp @@ -19,6 +19,7 @@ #include "duckdb/planner/expression/bound_aggregate_expression.hpp" #include "duckdb/main/client_config.hpp" #include "duckdb/catalog/catalog_entry/aggregate_function_catalog_entry.hpp" +#include "duckdb/catalog/catalog_entry/type_catalog_entry.hpp" #include "duckdb/main/query_result.hpp" namespace duckdb { @@ -378,7 +379,9 @@ unique_ptr Binder::BindPivot(PivotRef &ref, vector(context, INVALID_CATALOG, INVALID_SCHEMA, pivot.pivot_enum); + auto type = type_entry.user_type; if (type.id() != LogicalTypeId::ENUM) { throw BinderException(ref, "Pivot must reference an ENUM type: \"%s\" is of type \"%s\"", pivot.pivot_enum, type.ToString()); diff --git a/src/planner/binder/tableref/bind_table_function.cpp b/src/planner/binder/tableref/bind_table_function.cpp index be9848683b5..bbd79ec5985 100644 --- a/src/planner/binder/tableref/bind_table_function.cpp +++ b/src/planner/binder/tableref/bind_table_function.cpp @@ -23,32 +23,71 @@ namespace duckdb { -static bool IsTableInTableOutFunction(TableFunctionCatalogEntry &table_function) { - auto fun = table_function.functions.GetFunctionByOffset(0); - return table_function.functions.Size() == 1 && fun.arguments.size() == 1 && - fun.arguments[0].id() == LogicalTypeId::TABLE; +enum class TableFunctionBindType { STANDARD_TABLE_FUNCTION, TABLE_IN_OUT_FUNCTION, TABLE_PARAMETER_FUNCTION }; + +static TableFunctionBindType GetTableFunctionBindType(TableFunctionCatalogEntry &table_function, + vector> &expressions) { + // first check if all expressions are scalar + // if they are we always bind as a standard table function + bool all_scalar = true; + for (auto &expr : expressions) { + if (!expr->IsScalar()) { + all_scalar = false; + break; + } + } + if (all_scalar) { + return TableFunctionBindType::STANDARD_TABLE_FUNCTION; + } + // if we have non-scalar parameters - we need to look at the function definition to decide how to bind + // if a function does not have an in_out_function defined, we need to bind as a standard table function regardless + bool has_in_out_function = false; + bool has_standard_table_function = false; + bool has_table_parameter = false; + for (idx_t function_idx = 0; function_idx < table_function.functions.Size(); function_idx++) { + const auto &function = table_function.functions.GetFunctionReferenceByOffset(function_idx); + for (auto &arg : function.arguments) { + if (arg.id() == LogicalTypeId::TABLE) { + has_table_parameter = true; + } + } + if (function.in_out_function) { + has_in_out_function = true; + } else if (function.function || function.bind_replace) { + has_standard_table_function = true; + } else { + throw InternalException("Function \"%s\" has neither in_out_function nor function defined", + table_function.name); + } + } + if (has_table_parameter) { + if (table_function.functions.Size() != 1) { + throw InternalException( + "Function \"%s\" has a TABLE parameter, and multiple function overloads - this is not supported", + table_function.name); + } + return TableFunctionBindType::TABLE_PARAMETER_FUNCTION; + } + if (has_in_out_function && has_standard_table_function) { + throw InternalException("Function \"%s\" is both an in_out_function and a table function", table_function.name); + } + return has_in_out_function ? TableFunctionBindType::TABLE_IN_OUT_FUNCTION + : TableFunctionBindType::STANDARD_TABLE_FUNCTION; } -bool Binder::BindTableInTableOutFunction(vector> &expressions, - unique_ptr &subquery, ErrorData &error) { - auto binder = Binder::CreateBinder(this->context, this, true); +void Binder::BindTableInTableOutFunction(vector> &expressions, + unique_ptr &subquery) { + auto binder = Binder::CreateBinder(this->context, this); unique_ptr subquery_node; - if (expressions.size() == 1 && expressions[0]->type == ExpressionType::SUBQUERY) { - // general case: argument is a subquery, bind it as part of the node - auto &se = expressions[0]->Cast(); - subquery_node = std::move(se.subquery->node); - } else { - // special case: non-subquery parameter to table-in table-out function - // generate a subquery and bind that (i.e. UNNEST([1,2,3]) becomes UNNEST((SELECT [1,2,3])) - auto select_node = make_uniq(); - select_node->select_list = std::move(expressions); - select_node->from_table = make_uniq(); - subquery_node = std::move(select_node); - } + // generate a subquery and bind that (i.e. UNNEST([1,2,3]) becomes UNNEST((SELECT [1,2,3])) + auto select_node = make_uniq(); + select_node->select_list = std::move(expressions); + select_node->from_table = make_uniq(); + subquery_node = std::move(select_node); + binder->can_contain_nulls = true; auto node = binder->BindNode(*subquery_node); subquery = make_uniq(std::move(binder), std::move(node)); MoveCorrelatedExpressions(*subquery->binder); - return true; } bool Binder::BindTableFunctionParameters(TableFunctionCatalogEntry &table_function, @@ -56,10 +95,13 @@ bool Binder::BindTableFunctionParameters(TableFunctionCatalogEntry &table_functi vector &arguments, vector ¶meters, named_parameter_map_t &named_parameters, unique_ptr &subquery, ErrorData &error) { - if (IsTableInTableOutFunction(table_function)) { - // special case binding for table-in table-out function - arguments.emplace_back(LogicalTypeId::TABLE); - return BindTableInTableOutFunction(expressions, subquery, error); + auto bind_type = GetTableFunctionBindType(table_function, expressions); + if (bind_type == TableFunctionBindType::TABLE_IN_OUT_FUNCTION) { + // bind table in-out function + BindTableInTableOutFunction(expressions, subquery); + // fetch the arguments from the subquery + arguments = subquery->subquery->types; + return true; } bool seen_subquery = false; for (auto &child : expressions) { @@ -77,7 +119,8 @@ bool Binder::BindTableFunctionParameters(TableFunctionCatalogEntry &table_functi } } } - if (child->type == ExpressionType::SUBQUERY) { + if (bind_type == TableFunctionBindType::TABLE_PARAMETER_FUNCTION && child->type == ExpressionType::SUBQUERY) { + D_ASSERT(table_function.functions.Size() == 1); auto fun = table_function.functions.GetFunctionByOffset(0); if (table_function.functions.Size() != 1 || fun.arguments.empty() || fun.arguments[0].id() != LogicalTypeId::TABLE) { @@ -85,20 +128,19 @@ bool Binder::BindTableFunctionParameters(TableFunctionCatalogEntry &table_functi "Only table-in-out functions can have subquery parameters - %s only accepts constant parameters", fun.name); } - // this separate subquery binding path is only used by python_map - // FIXME: this should be unified with `BindTableInTableOutFunction` above if (seen_subquery) { error = ErrorData("Table function can have at most one subquery parameter"); return false; } - auto binder = Binder::CreateBinder(this->context, this, true); + auto binder = Binder::CreateBinder(this->context, this); + binder->can_contain_nulls = true; auto &se = child->Cast(); auto node = binder->BindNode(*se.subquery->node); subquery = make_uniq(std::move(binder), std::move(node)); + MoveCorrelatedExpressions(*subquery->binder); seen_subquery = true; arguments.emplace_back(LogicalTypeId::TABLE); - parameters.emplace_back( - Value(LogicalType::INVALID)); // this is a dummy value so the lengths of arguments and parameter match + parameters.emplace_back(Value()); continue; } @@ -128,11 +170,25 @@ bool Binder::BindTableFunctionParameters(TableFunctionCatalogEntry &table_functi return true; } -unique_ptr -Binder::BindTableFunctionInternal(TableFunction &table_function, const string &function_name, vector parameters, - named_parameter_map_t named_parameters, vector input_table_types, - vector input_table_names, const vector &column_name_alias, - unique_ptr external_dependency) { +static string GetAlias(const TableFunctionRef &ref) { + if (!ref.alias.empty()) { + return ref.alias; + } + if (ref.function && ref.function->type == ExpressionType::FUNCTION) { + auto &function_expr = ref.function->Cast(); + return function_expr.function_name; + } + return string(); +} + +unique_ptr Binder::BindTableFunctionInternal(TableFunction &table_function, + const TableFunctionRef &ref, vector parameters, + named_parameter_map_t named_parameters, + vector input_table_types, + vector input_table_names) { + auto function_name = GetAlias(ref); + auto &column_name_alias = ref.column_name_alias; + auto bind_index = GenerateTableIndex(); // perform the binding unique_ptr bind_data; @@ -140,7 +196,7 @@ Binder::BindTableFunctionInternal(TableFunction &table_function, const string &f vector return_names; if (table_function.bind || table_function.bind_replace) { TableFunctionBindInput bind_input(parameters, named_parameters, input_table_types, input_table_names, - table_function.function_info.get(), this); + table_function.function_info.get(), this, table_function, ref); if (table_function.bind_replace) { auto new_plan = table_function.bind_replace(context, bind_input); if (new_plan != nullptr) { @@ -151,10 +207,6 @@ Binder::BindTableFunctionInternal(TableFunction &table_function, const string &f } } bind_data = table_function.bind(context, bind_input, return_types, return_names); - if (table_function.name == "pandas_scan" || table_function.name == "arrow_scan") { - auto &arrow_bind = bind_data->Cast(); - arrow_bind.external_dependency = std::move(external_dependency); - } } else { throw InvalidInputException("Cannot call function \"%s\" directly - it has no bind function", table_function.name); @@ -197,10 +249,12 @@ unique_ptr Binder::BindTableFunction(TableFunction &function, v named_parameter_map_t named_parameters; vector input_table_types; vector input_table_names; - vector column_name_aliases; - return BindTableFunctionInternal(function, function.name, std::move(parameters), std::move(named_parameters), - std::move(input_table_types), std::move(input_table_names), column_name_aliases, - nullptr); + + TableFunctionRef ref; + ref.alias = function.name; + D_ASSERT(!ref.alias.empty()); + return BindTableFunctionInternal(function, ref, std::move(parameters), std::move(named_parameters), + std::move(input_table_types), std::move(input_table_names)); } unique_ptr Binder::Bind(TableFunctionRef &ref) { @@ -210,8 +264,8 @@ unique_ptr Binder::Bind(TableFunctionRef &ref) { auto &fexpr = ref.function->Cast(); // fetch the function from the catalog - auto &func_catalog = Catalog::GetEntry(context, CatalogType::TABLE_FUNCTION_ENTRY, fexpr.catalog, fexpr.schema, - fexpr.function_name, error_context); + auto &func_catalog = *GetCatalogEntry(CatalogType::TABLE_FUNCTION_ENTRY, fexpr.catalog, fexpr.schema, + fexpr.function_name, OnEntryNotFound::THROW_EXCEPTION, error_context); if (func_catalog.type == CatalogType::TABLE_MACRO_ENTRY) { auto ¯o_func = func_catalog.Cast(); @@ -261,32 +315,46 @@ unique_ptr Binder::Bind(TableFunctionRef &ref) { // now check the named parameters BindNamedParameters(table_function.named_parameters, named_parameters, error_context, table_function.name); - // cast the parameters to the type of the function - for (idx_t i = 0; i < arguments.size(); i++) { - auto target_type = i < table_function.arguments.size() ? table_function.arguments[i] : table_function.varargs; - - if (target_type != LogicalType::ANY && target_type != LogicalType::TABLE && - target_type != LogicalType::POINTER && target_type.id() != LogicalTypeId::LIST) { - parameters[i] = parameters[i].CastAs(context, target_type); - } - } - vector input_table_types; vector input_table_names; if (subquery) { input_table_types = subquery->subquery->types; input_table_names = subquery->subquery->names; + } else if (table_function.in_out_function) { + for (auto ¶m : parameters) { + input_table_types.push_back(param.type()); + input_table_names.push_back(string()); + } } - auto get = BindTableFunctionInternal(table_function, ref.alias.empty() ? fexpr.function_name : ref.alias, - std::move(parameters), std::move(named_parameters), - std::move(input_table_types), std::move(input_table_names), - ref.column_name_alias, std::move(ref.external_dependency)); - if (subquery) { - get->children.push_back(Binder::CreatePlan(*subquery)); + if (!parameters.empty()) { + // cast the parameters to the type of the function + for (idx_t i = 0; i < arguments.size(); i++) { + auto target_type = + i < table_function.arguments.size() ? table_function.arguments[i] : table_function.varargs; + + if (target_type != LogicalType::ANY && target_type != LogicalType::POINTER && + target_type.id() != LogicalTypeId::LIST && target_type != LogicalType::TABLE) { + parameters[i] = parameters[i].CastAs(context, target_type); + } + } + } else if (subquery) { + for (idx_t i = 0; i < arguments.size(); i++) { + auto target_type = + i < table_function.arguments.size() ? table_function.arguments[i] : table_function.varargs; + + if (target_type != LogicalType::ANY && target_type != LogicalType::POINTER && + target_type.id() != LogicalTypeId::LIST) { + input_table_types[i] = target_type; + } + } } - return make_uniq_base(std::move(get)); + auto get = BindTableFunctionInternal(table_function, ref, std::move(parameters), std::move(named_parameters), + std::move(input_table_types), std::move(input_table_names)); + auto table_function_ref = make_uniq(std::move(get)); + table_function_ref->subquery = std::move(subquery); + return std::move(table_function_ref); } } // namespace duckdb diff --git a/src/planner/binder/tableref/plan_column_data_ref.cpp b/src/planner/binder/tableref/plan_column_data_ref.cpp new file mode 100644 index 00000000000..83e965b5e5c --- /dev/null +++ b/src/planner/binder/tableref/plan_column_data_ref.cpp @@ -0,0 +1,15 @@ +#include "duckdb/planner/binder.hpp" +#include "duckdb/planner/tableref/bound_column_data_ref.hpp" +#include "duckdb/planner/operator/logical_column_data_get.hpp" + +namespace duckdb { + +unique_ptr Binder::CreatePlan(BoundColumnDataRef &ref) { + auto types = ref.collection->Types(); + // Create a (potentially owning) LogicalColumnDataGet + auto root = make_uniq_base(ref.bind_index, std::move(types), + std::move(ref.collection)); + return root; +} + +} // namespace duckdb diff --git a/src/planner/binder/tableref/plan_joinref.cpp b/src/planner/binder/tableref/plan_joinref.cpp index bf447eaa8db..cbaacd268bb 100644 --- a/src/planner/binder/tableref/plan_joinref.cpp +++ b/src/planner/binder/tableref/plan_joinref.cpp @@ -20,6 +20,26 @@ namespace duckdb { +//! Only use conditions that are valid for the join ref type +static bool IsJoinTypeCondition(const JoinRefType ref_type, const ExpressionType expr_type) { + switch (ref_type) { + case JoinRefType::ASOF: + switch (expr_type) { + case ExpressionType::COMPARE_EQUAL: + case ExpressionType::COMPARE_NOT_DISTINCT_FROM: + case ExpressionType::COMPARE_GREATERTHANOREQUALTO: + case ExpressionType::COMPARE_GREATERTHAN: + case ExpressionType::COMPARE_LESSTHANOREQUALTO: + case ExpressionType::COMPARE_LESSTHAN: + return true; + default: + return false; + } + default: + return true; + } +} + //! Create a JoinCondition from a comparison static bool CreateJoinCondition(Expression &expr, const unordered_set &left_bindings, const unordered_set &right_bindings, vector &conditions) { @@ -47,7 +67,7 @@ static bool CreateJoinCondition(Expression &expr, const unordered_set &le } void LogicalComparisonJoin::ExtractJoinConditions( - ClientContext &context, JoinType type, unique_ptr &left_child, + ClientContext &context, JoinType type, JoinRefType ref_type, unique_ptr &left_child, unique_ptr &right_child, const unordered_set &left_bindings, const unordered_set &right_bindings, vector> &expressions, vector &conditions, vector> &arbitrary_expressions) { @@ -56,7 +76,9 @@ void LogicalComparisonJoin::ExtractJoinConditions( auto total_side = JoinSide::GetJoinSide(*expr, left_bindings, right_bindings); if (total_side != JoinSide::BOTH) { // join condition does not reference both sides, add it as filter under the join - if (type == JoinType::LEFT && total_side == JoinSide::RIGHT) { + // BUT don't push right side filters into AsOf because it is really a table lookup + // and we shouldn't remove anything from the table. + if (type == JoinType::LEFT && total_side == JoinSide::RIGHT && ref_type != JoinRefType::ASOF) { // filter is on RHS and the join is a LEFT OUTER join, we can push it in the right child if (right_child->type != LogicalOperatorType::LOGICAL_FILTER) { // not a filter yet, push a new empty filter @@ -90,7 +112,8 @@ void LogicalComparisonJoin::ExtractJoinConditions( { // comparison, check if we can create a comparison JoinCondition - if (CreateJoinCondition(*expr, left_bindings, right_bindings, conditions)) { + if (IsJoinTypeCondition(ref_type, expr->type) && + CreateJoinCondition(*expr, left_bindings, right_bindings, conditions)) { // successfully created the join condition continue; } @@ -99,7 +122,7 @@ void LogicalComparisonJoin::ExtractJoinConditions( } } -void LogicalComparisonJoin::ExtractJoinConditions(ClientContext &context, JoinType type, +void LogicalComparisonJoin::ExtractJoinConditions(ClientContext &context, JoinType type, JoinRefType ref_type, unique_ptr &left_child, unique_ptr &right_child, vector> &expressions, @@ -108,11 +131,11 @@ void LogicalComparisonJoin::ExtractJoinConditions(ClientContext &context, JoinTy unordered_set left_bindings, right_bindings; LogicalJoin::GetTableReferences(*left_child, left_bindings); LogicalJoin::GetTableReferences(*right_child, right_bindings); - return ExtractJoinConditions(context, type, left_child, right_child, left_bindings, right_bindings, expressions, - conditions, arbitrary_expressions); + return ExtractJoinConditions(context, type, ref_type, left_child, right_child, left_bindings, right_bindings, + expressions, conditions, arbitrary_expressions); } -void LogicalComparisonJoin::ExtractJoinConditions(ClientContext &context, JoinType type, +void LogicalComparisonJoin::ExtractJoinConditions(ClientContext &context, JoinType type, JoinRefType ref_type, unique_ptr &left_child, unique_ptr &right_child, unique_ptr condition, vector &conditions, @@ -121,7 +144,7 @@ void LogicalComparisonJoin::ExtractJoinConditions(ClientContext &context, JoinTy vector> expressions; expressions.push_back(std::move(condition)); LogicalFilter::SplitPredicates(expressions); - return ExtractJoinConditions(context, type, left_child, right_child, expressions, conditions, + return ExtractJoinConditions(context, type, ref_type, left_child, right_child, expressions, conditions, arbitrary_expressions); } @@ -135,9 +158,6 @@ unique_ptr LogicalComparisonJoin::CreateJoin(ClientContext &con bool need_to_consider_arbitrary_expressions = true; switch (reftype) { case JoinRefType::ASOF: { - if (!arbitrary_expressions.empty()) { - throw BinderException("Invalid ASOF JOIN condition"); - } need_to_consider_arbitrary_expressions = false; auto asof_idx = conditions.size(); for (size_t c = 0; c < conditions.size(); ++c) { @@ -249,7 +269,7 @@ unique_ptr LogicalComparisonJoin::CreateJoin(ClientContext &con unique_ptr condition) { vector conditions; vector> arbitrary_expressions; - LogicalComparisonJoin::ExtractJoinConditions(context, type, left_child, right_child, std::move(condition), + LogicalComparisonJoin::ExtractJoinConditions(context, type, reftype, left_child, right_child, std::move(condition), conditions, arbitrary_expressions); return LogicalComparisonJoin::CreateJoin(context, type, reftype, std::move(left_child), std::move(right_child), std::move(conditions), std::move(arbitrary_expressions)); @@ -324,13 +344,16 @@ unique_ptr Binder::CreatePlan(BoundJoinRef &ref) { // now create the join operator from the join condition auto result = LogicalComparisonJoin::CreateJoin(context, ref.type, ref.ref_type, std::move(left), std::move(right), std::move(ref.condition)); - optional_ptr join; if (result->type == LogicalOperatorType::LOGICAL_FILTER) { join = result->children[0].get(); } else { join = result.get(); } + + if (ref.type == JoinType::MARK) { + join->Cast().mark_index = ref.mark_index; + } for (auto &child : join->children) { if (child->type == LogicalOperatorType::LOGICAL_FILTER) { auto &filter = child->Cast(); diff --git a/src/planner/binder/tableref/plan_table_function.cpp b/src/planner/binder/tableref/plan_table_function.cpp index dffbd320adf..3be48aa6c22 100644 --- a/src/planner/binder/tableref/plan_table_function.cpp +++ b/src/planner/binder/tableref/plan_table_function.cpp @@ -4,6 +4,10 @@ namespace duckdb { unique_ptr Binder::CreatePlan(BoundTableFunction &ref) { + if (ref.subquery) { + auto child_node = CreatePlan(*ref.subquery); + ref.get->children.push_back(std::move(child_node)); + } return std::move(ref.get); } diff --git a/src/planner/collation_binding.cpp b/src/planner/collation_binding.cpp new file mode 100644 index 00000000000..d68ffc60890 --- /dev/null +++ b/src/planner/collation_binding.cpp @@ -0,0 +1,99 @@ +#include "duckdb/planner/collation_binding.hpp" +#include "duckdb/catalog/catalog_entry/collate_catalog_entry.hpp" +#include "duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp" +#include "duckdb/planner/expression/bound_function_expression.hpp" +#include "duckdb/main/config.hpp" +#include "duckdb/catalog/catalog.hpp" +#include "duckdb/function/function_binder.hpp" + +namespace duckdb { + +bool PushVarcharCollation(ClientContext &context, unique_ptr &source, const LogicalType &sql_type) { + if (sql_type.id() != LogicalTypeId::VARCHAR) { + // only VARCHAR columns require collation + return false; + } + // replace default collation with system collation + auto str_collation = StringType::GetCollation(sql_type); + string collation; + if (str_collation.empty()) { + collation = DBConfig::GetConfig(context).options.collation; + } else { + collation = str_collation; + } + collation = StringUtil::Lower(collation); + // bind the collation + if (collation.empty() || collation == "binary" || collation == "c" || collation == "posix") { + // no collation or binary collation: skip + return false; + } + auto &catalog = Catalog::GetSystemCatalog(context); + auto splits = StringUtil::Split(StringUtil::Lower(collation), "."); + vector> entries; + for (auto &collation_argument : splits) { + auto &collation_entry = catalog.GetEntry(context, DEFAULT_SCHEMA, collation_argument); + if (collation_entry.combinable) { + entries.insert(entries.begin(), collation_entry); + } else { + if (!entries.empty() && !entries.back().get().combinable) { + throw BinderException("Cannot combine collation types \"%s\" and \"%s\"", entries.back().get().name, + collation_entry.name); + } + entries.push_back(collation_entry); + } + } + for (auto &entry : entries) { + auto &collation_entry = entry.get(); + vector> children; + children.push_back(std::move(source)); + + FunctionBinder function_binder(context); + auto function = function_binder.BindScalarFunction(collation_entry.function, std::move(children)); + source = std::move(function); + } + return true; +} + +bool PushTimeTZCollation(ClientContext &context, unique_ptr &source, const LogicalType &sql_type) { + if (sql_type.id() != LogicalTypeId::TIME_TZ) { + return false; + } + + auto &catalog = Catalog::GetSystemCatalog(context); + auto &function_entry = + catalog.GetEntry(context, DEFAULT_SCHEMA, "timetz_byte_comparable"); + if (function_entry.functions.Size() != 1) { + throw InternalException("timetz_byte_comparable should only have a single overload"); + } + auto &scalar_function = function_entry.functions.GetFunctionReferenceByOffset(0); + vector> children; + children.push_back(std::move(source)); + + FunctionBinder function_binder(context); + auto function = function_binder.BindScalarFunction(scalar_function, std::move(children)); + source = std::move(function); + return true; +} + +// timetz_byte_comparable +CollationBinding::CollationBinding() { + RegisterCollation(CollationCallback(PushVarcharCollation)); + RegisterCollation(CollationCallback(PushTimeTZCollation)); +} + +void CollationBinding::RegisterCollation(CollationCallback callback) { + collations.push_back(callback); +} + +bool CollationBinding::PushCollation(ClientContext &context, unique_ptr &source, + const LogicalType &sql_type) const { + for (auto &collation : collations) { + if (collation.try_push_collation(context, source, sql_type)) { + // successfully pushed a collation + return true; + } + } + return false; +} + +} // namespace duckdb diff --git a/src/planner/expression/bound_cast_expression.cpp b/src/planner/expression/bound_cast_expression.cpp index 81aaf32108a..bc23de68f65 100644 --- a/src/planner/expression/bound_cast_expression.cpp +++ b/src/planner/expression/bound_cast_expression.cpp @@ -158,17 +158,7 @@ bool BoundCastExpression::CastIsInvertible(const LogicalType &source_type, const } break; case LogicalTypeId::VARCHAR: - switch (target_type.id()) { - case LogicalTypeId::TIMESTAMP: - case LogicalTypeId::TIMESTAMP_NS: - case LogicalTypeId::TIMESTAMP_MS: - case LogicalTypeId::TIMESTAMP_SEC: - case LogicalTypeId::TIMESTAMP_TZ: - return true; - default: - return false; - } - break; + return false; default: break; } diff --git a/src/planner/expression/bound_expression.cpp b/src/planner/expression/bound_expression.cpp index e5cdfb1c6a2..864357ff659 100644 --- a/src/planner/expression/bound_expression.cpp +++ b/src/planner/expression/bound_expression.cpp @@ -1,4 +1,5 @@ #include "duckdb/parser/expression/bound_expression.hpp" +#include "duckdb/common/enum_util.hpp" namespace duckdb { @@ -30,11 +31,11 @@ hash_t BoundExpression::Hash() const { } unique_ptr BoundExpression::Copy() const { - throw SerializationException("Cannot copy or serialize bound expression"); + throw SerializationException("Cannot copy bound expression"); } void BoundExpression::Serialize(Serializer &serializer) const { - throw SerializationException("Cannot copy or serialize bound expression"); + throw SerializationException("Cannot serialize bound expression"); } } // namespace duckdb diff --git a/src/planner/expression_binder.cpp b/src/planner/expression_binder.cpp index fa03fabdf51..4551525b62c 100644 --- a/src/planner/expression_binder.cpp +++ b/src/planner/expression_binder.cpp @@ -9,6 +9,10 @@ namespace duckdb { +void ExpressionBinder::SetCatalogLookupCallback(catalog_entry_callback_t callback) { + binder.SetCatalogLookupCallback(std::move(callback)); +} + ExpressionBinder::ExpressionBinder(Binder &binder, ClientContext &context, bool replace_binder) : binder(binder), context(context) { InitializeStackCheck(); @@ -282,16 +286,4 @@ bool ExpressionBinder::IsUnnestFunction(const string &function_name) { return function_name == "unnest" || function_name == "unlist"; } -bool ExpressionBinder::IsLambdaFunction(const FunctionExpression &function) { - // check for lambda parameters, ignore ->> operator (JSON extension) - if (function.function_name != "->>") { - for (auto &child : function.children) { - if (child->expression_class == ExpressionClass::LAMBDA) { - return true; - } - } - } - return false; -} - } // namespace duckdb diff --git a/src/planner/expression_binder/alter_binder.cpp b/src/planner/expression_binder/alter_binder.cpp index 597ef0ca6f6..e8c4d547066 100644 --- a/src/planner/expression_binder/alter_binder.cpp +++ b/src/planner/expression_binder/alter_binder.cpp @@ -1,8 +1,9 @@ #include "duckdb/planner/expression_binder/alter_binder.hpp" +#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" #include "duckdb/parser/expression/columnref_expression.hpp" #include "duckdb/planner/expression/bound_reference_expression.hpp" -#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" +#include "duckdb/planner/table_binding.hpp" namespace duckdb { @@ -12,6 +13,12 @@ AlterBinder::AlterBinder(Binder &binder, ClientContext &context, TableCatalogEnt this->target_type = std::move(target_type); } +BindResult AlterBinder::BindLambdaReference(LambdaRefExpression &expr, idx_t depth) { + D_ASSERT(lambda_bindings && expr.lambda_idx < lambda_bindings->size()); + auto &lambda_ref = expr.Cast(); + return (*lambda_bindings)[expr.lambda_idx].Bind(lambda_ref, depth); +} + BindResult AlterBinder::BindExpression(unique_ptr &expr_ptr, idx_t depth, bool root_expression) { auto &expr = *expr_ptr; switch (expr.GetExpressionClass()) { @@ -20,7 +27,7 @@ BindResult AlterBinder::BindExpression(unique_ptr &expr_ptr, i case ExpressionClass::SUBQUERY: return BindResult("cannot use subquery in alter statement"); case ExpressionClass::COLUMN_REF: - return BindColumn(expr.Cast()); + return BindColumnReference(expr.Cast(), depth); default: return ExpressionBinder::BindExpression(expr_ptr, depth); } @@ -30,14 +37,24 @@ string AlterBinder::UnsupportedAggregateMessage() { return "aggregate functions are not allowed in alter statement"; } -BindResult AlterBinder::BindColumn(ColumnRefExpression &colref) { - if (colref.column_names.size() > 1) { - return BindQualifiedColumnName(colref, table.name); +BindResult AlterBinder::BindColumnReference(ColumnRefExpression &col_ref, idx_t depth) { + + // try binding as a lambda parameter + if (!col_ref.IsQualified()) { + auto lambda_ref = LambdaRefExpression::FindMatchingBinding(lambda_bindings, col_ref.GetName()); + if (lambda_ref) { + return BindLambdaReference(lambda_ref->Cast(), depth); + } + } + + if (col_ref.column_names.size() > 1) { + return BindQualifiedColumnName(col_ref, table.name); } - auto idx = table.GetColumnIndex(colref.column_names[0], true); + + auto idx = table.GetColumnIndex(col_ref.column_names[0], true); if (!idx.IsValid()) { throw BinderException("Table does not contain column %s referenced in alter statement!", - colref.column_names[0]); + col_ref.column_names[0]); } if (table.GetColumn(idx).Generated()) { throw BinderException("Using generated columns in alter statement not supported"); diff --git a/src/planner/expression_binder/base_select_binder.cpp b/src/planner/expression_binder/base_select_binder.cpp index cadc3ac6aba..30a1eeaaa26 100644 --- a/src/planner/expression_binder/base_select_binder.cpp +++ b/src/planner/expression_binder/base_select_binder.cpp @@ -3,9 +3,12 @@ #include "duckdb/common/string_util.hpp" #include "duckdb/parser/expression/columnref_expression.hpp" #include "duckdb/parser/expression/operator_expression.hpp" +#include "duckdb/planner/expression/bound_operator_expression.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" #include "duckdb/parser/expression/window_expression.hpp" #include "duckdb/planner/binder.hpp" #include "duckdb/planner/expression/bound_columnref_expression.hpp" +#include "duckdb/planner/expression/bound_case_expression.hpp" #include "duckdb/planner/expression_binder/aggregate_binder.hpp" #include "duckdb/planner/query_node/bound_select_node.hpp" #include "duckdb/planner/expression_binder/select_bind_state.hpp" @@ -98,8 +101,30 @@ BindResult BaseSelectBinder::BindGroup(ParsedExpression &expr, idx_t depth, idx_ if (it != info.collated_groups.end()) { // This is an implicitly collated group, so we need to refer to the first() aggregate const auto &aggr_index = it->second; - return BindResult(make_uniq(expr.GetName(), node.aggregates[aggr_index]->return_type, - ColumnBinding(node.aggregate_index, aggr_index), depth)); + auto uncollated_first_expression = + make_uniq(expr.GetName(), node.aggregates[aggr_index]->return_type, + ColumnBinding(node.aggregate_index, aggr_index), depth); + + if (node.groups.grouping_sets.size() <= 1) { + // if there are no more than two grouping sets, you can return the uncollated first expression. + // "first" meaning the aggreagte function. + return BindResult(std::move(uncollated_first_expression)); + } + + // otherwise we insert a case statement to return NULL when the collated group expression is NULL + // otherwise you can return the "first" of the uncollated expression. + auto &group = node.groups.group_expressions[group_index]; + auto collated_group_expression = make_uniq( + expr.GetName(), group->return_type, ColumnBinding(node.group_index, group_index), depth); + + auto sql_null = make_uniq(Value(LogicalType::VARCHAR)); + auto when_expr = make_uniq(ExpressionType::OPERATOR_IS_NULL, LogicalType::BOOLEAN); + when_expr->children.push_back(std::move(collated_group_expression)); + auto then_expr = make_uniq(Value(LogicalType::VARCHAR)); + auto else_expr = std::move(uncollated_first_expression); + auto case_expr = + make_uniq(std::move(when_expr), std::move(then_expr), std::move(else_expr)); + return BindResult(std::move(case_expr)); } else { auto &group = node.groups.group_expressions[group_index]; return BindResult(make_uniq(expr.GetName(), group->return_type, diff --git a/src/planner/expression_binder/having_binder.cpp b/src/planner/expression_binder/having_binder.cpp index 5a987ef7f3f..1a2bd35a64d 100644 --- a/src/planner/expression_binder/having_binder.cpp +++ b/src/planner/expression_binder/having_binder.cpp @@ -15,14 +15,29 @@ HavingBinder::HavingBinder(Binder &binder, ClientContext &context, BoundSelectNo target_type = LogicalType(LogicalTypeId::BOOLEAN); } +BindResult HavingBinder::BindLambdaReference(LambdaRefExpression &expr, idx_t depth) { + D_ASSERT(lambda_bindings && expr.lambda_idx < lambda_bindings->size()); + auto &lambda_ref = expr.Cast(); + return (*lambda_bindings)[expr.lambda_idx].Bind(lambda_ref, depth); +} + BindResult HavingBinder::BindColumnRef(unique_ptr &expr_ptr, idx_t depth, bool root_expression) { + // Keep the original column name to return a meaningful error message. - auto column_name = expr_ptr->Cast().GetColumnName(); + auto col_ref = expr_ptr->Cast(); + const auto &column_name = col_ref.GetColumnName(); + + // Try binding as a lambda parameter + if (!col_ref.IsQualified()) { + auto lambda_ref = LambdaRefExpression::FindMatchingBinding(lambda_bindings, col_ref.GetName()); + if (lambda_ref) { + return BindLambdaReference(lambda_ref->Cast(), depth); + } + } // Bind the alias. BindResult alias_result; auto found_alias = column_alias_binder.BindAlias(*this, expr_ptr, depth, root_expression, alias_result); - if (found_alias) { if (depth > 0) { throw BinderException("Having clause cannot reference alias \"%s\" in correlated subquery", column_name); @@ -30,27 +45,27 @@ BindResult HavingBinder::BindColumnRef(unique_ptr &expr_ptr, i return alias_result; } - if (aggregate_handling == AggregateHandling::FORCE_AGGREGATES) { - if (depth > 0) { - throw BinderException( - "Having clause cannot reference column \"%s\" in correlated subquery and group by all", column_name); - } + if (aggregate_handling != AggregateHandling::FORCE_AGGREGATES) { + return BindResult(StringUtil::Format( + "column %s must appear in the GROUP BY clause or be used in an aggregate function", column_name)); + } - auto expr = duckdb::BaseSelectBinder::BindColumnRef(expr_ptr, depth, root_expression); - if (expr.HasError()) { - return expr; - } + if (depth > 0) { + throw BinderException("Having clause cannot reference column \"%s\" in correlated subquery and group by all", + column_name); + } - // Return a GROUP BY column reference expression. - auto return_type = expr.expression->return_type; - auto column_binding = ColumnBinding(node.group_index, node.groups.group_expressions.size()); - auto group_ref = make_uniq(return_type, column_binding); - node.groups.group_expressions.push_back(std::move(expr.expression)); - return BindResult(std::move(group_ref)); + auto expr = duckdb::BaseSelectBinder::BindColumnRef(expr_ptr, depth, root_expression); + if (expr.HasError()) { + return expr; } - return BindResult(StringUtil::Format( - "column %s must appear in the GROUP BY clause or be used in an aggregate function", column_name)); + // Return a GROUP BY column reference expression. + auto return_type = expr.expression->return_type; + auto column_binding = ColumnBinding(node.group_index, node.groups.group_expressions.size()); + auto group_ref = make_uniq(return_type, column_binding); + node.groups.group_expressions.push_back(std::move(expr.expression)); + return BindResult(std::move(group_ref)); } BindResult HavingBinder::BindWindow(WindowExpression &expr, idx_t depth) { diff --git a/src/planner/expression_binder/index_binder.cpp b/src/planner/expression_binder/index_binder.cpp index 5bdf1f0448a..988948ae406 100644 --- a/src/planner/expression_binder/index_binder.cpp +++ b/src/planner/expression_binder/index_binder.cpp @@ -4,6 +4,10 @@ #include "duckdb/parser/expression/columnref_expression.hpp" #include "duckdb/planner/expression/bound_columnref_expression.hpp" #include "duckdb/planner/column_binding.hpp" +#include "duckdb/execution/index/bound_index.hpp" +#include "duckdb/execution/index/unbound_index.hpp" +#include "duckdb/main/config.hpp" +#include "duckdb/main/database.hpp" namespace duckdb { @@ -12,6 +16,35 @@ IndexBinder::IndexBinder(Binder &binder, ClientContext &context, optional_ptr IndexBinder::BindIndex(const UnboundIndex &unbound_index) { + auto &index_type_name = unbound_index.GetIndexType(); + // Do we know the type of this index now? + auto index_type = context.db->config.GetIndexTypes().FindByName(index_type_name); + if (!index_type) { + throw MissingExtensionException("Cannot bind index '%s', unknown index type '%s'. You need to load the " + "extension that provides this index type before table '%s' can be modified.", + unbound_index.GetTableName(), index_type_name, unbound_index.GetTableName()); + } + + auto &create_info = unbound_index.GetCreateInfo(); + auto &storage_info = unbound_index.GetStorageInfo(); + auto &parsed_expressions = unbound_index.GetParsedExpressions(); + + // bind the parsed expressions to create unbound expressions + vector> unbound_expressions; + unbound_expressions.reserve(parsed_expressions.size()); + for (auto &expr : parsed_expressions) { + auto copy = expr->Copy(); + unbound_expressions.push_back(Bind(copy)); + } + + CreateIndexInput input(unbound_index.table_io_manager, unbound_index.db, create_info.constraint_type, + create_info.index_name, create_info.column_ids, unbound_expressions, storage_info, + create_info.options); + + return index_type->create_instance(input); +} + BindResult IndexBinder::BindExpression(unique_ptr &expr_ptr, idx_t depth, bool root_expression) { auto &expr = *expr_ptr; switch (expr.expression_class) { diff --git a/src/planner/expression_binder/order_binder.cpp b/src/planner/expression_binder/order_binder.cpp index 2924a3a5017..4a277b3adc5 100644 --- a/src/planner/expression_binder/order_binder.cpp +++ b/src/planner/expression_binder/order_binder.cpp @@ -108,6 +108,14 @@ unique_ptr OrderBinder::Bind(unique_ptr expr) { auto &collation = expr->Cast(); if (collation.child->expression_class == ExpressionClass::CONSTANT) { auto &constant = collation.child->Cast(); + + // non-integral expression, we just leave the constant here. + // ORDER BY has no effect + // CONTROVERSIAL: maybe we should throw an error + if (!constant.value.type().IsIntegral()) { + return nullptr; + } + D_ASSERT(constant.value.GetValue() > 0); auto index = constant.value.GetValue() - 1; child_list_t values; diff --git a/src/planner/expression_iterator.cpp b/src/planner/expression_iterator.cpp index 8bf1622041c..1b271112e39 100644 --- a/src/planner/expression_iterator.cpp +++ b/src/planner/expression_iterator.cpp @@ -7,6 +7,7 @@ #include "duckdb/planner/query_node/bound_recursive_cte_node.hpp" #include "duckdb/planner/query_node/bound_cte_node.hpp" #include "duckdb/planner/tableref/list.hpp" +#include "duckdb/common/enum_util.hpp" namespace duckdb { @@ -238,6 +239,21 @@ void BoundNodeVisitor::VisitBoundQueryNode(BoundQueryNode &node) { } } +class LogicalBoundNodeVisitor : public LogicalOperatorVisitor { +public: + explicit LogicalBoundNodeVisitor(BoundNodeVisitor &parent) : parent(parent) { + } + + void VisitExpression(unique_ptr *expression) override { + auto &expr = **expression; + parent.VisitExpression(*expression); + VisitExpressionChildren(expr); + } + +protected: + BoundNodeVisitor &parent; +}; + void BoundNodeVisitor::VisitBoundTableRef(BoundTableRef &ref) { switch (ref.type) { case TableReferenceType::EXPRESSION_LIST: { @@ -263,13 +279,24 @@ void BoundNodeVisitor::VisitBoundTableRef(BoundTableRef &ref) { VisitBoundQueryNode(*bound_subquery.subquery); break; } - case TableReferenceType::TABLE_FUNCTION: + case TableReferenceType::TABLE_FUNCTION: { + auto &bound_table_function = ref.Cast(); + LogicalBoundNodeVisitor node_visitor(*this); + if (bound_table_function.get) { + node_visitor.VisitOperator(*bound_table_function.get); + } + if (bound_table_function.subquery) { + VisitBoundTableRef(*bound_table_function.subquery); + } + break; + } case TableReferenceType::EMPTY_FROM: case TableReferenceType::BASE_TABLE: case TableReferenceType::CTE: break; default: - throw NotImplementedException("Unimplemented table reference type in ExpressionIterator"); + throw NotImplementedException("Unimplemented table reference type (%s) in ExpressionIterator", + EnumUtil::ToString(ref.type)); } } diff --git a/src/planner/filter/constant_filter.cpp b/src/planner/filter/constant_filter.cpp index 1388aa42aaf..1243e9b7bb3 100644 --- a/src/planner/filter/constant_filter.cpp +++ b/src/planner/filter/constant_filter.cpp @@ -32,7 +32,7 @@ FilterPropagateResult ConstantFilter::CheckStatistics(BaseStatistics &stats) { } string ConstantFilter::ToString(const string &column_name) { - return column_name + ExpressionTypeToOperator(comparison_type) + constant.ToString(); + return column_name + ExpressionTypeToOperator(comparison_type) + constant.ToSQLString(); } bool ConstantFilter::Equals(const TableFilter &other_p) const { diff --git a/src/planner/operator/logical_column_data_get.cpp b/src/planner/operator/logical_column_data_get.cpp index b99c9121a55..28b0e76bd34 100644 --- a/src/planner/operator/logical_column_data_get.cpp +++ b/src/planner/operator/logical_column_data_get.cpp @@ -6,9 +6,23 @@ namespace duckdb { LogicalColumnDataGet::LogicalColumnDataGet(idx_t table_index, vector types, - unique_ptr collection) + unique_ptr collection_p) : LogicalOperator(LogicalOperatorType::LOGICAL_CHUNK_GET), table_index(table_index), - collection(std::move(collection)) { + collection(std::move(collection_p)) { + D_ASSERT(types.size() > 0); + chunk_types = std::move(types); +} + +LogicalColumnDataGet::LogicalColumnDataGet(idx_t table_index, vector types, ColumnDataCollection &to_scan) + : LogicalOperator(LogicalOperatorType::LOGICAL_CHUNK_GET), table_index(table_index), collection(to_scan) { + D_ASSERT(types.size() > 0); + chunk_types = std::move(types); +} + +LogicalColumnDataGet::LogicalColumnDataGet(idx_t table_index, vector types, + optionally_owned_ptr collection_p) + : LogicalOperator(LogicalOperatorType::LOGICAL_CHUNK_GET), table_index(table_index), + collection(std::move(collection_p)) { D_ASSERT(types.size() > 0); chunk_types = std::move(types); } diff --git a/src/planner/operator/logical_copy_to_file.cpp b/src/planner/operator/logical_copy_to_file.cpp index 67f684d8461..6b6e2116084 100644 --- a/src/planner/operator/logical_copy_to_file.cpp +++ b/src/planner/operator/logical_copy_to_file.cpp @@ -13,7 +13,7 @@ void LogicalCopyToFile::Serialize(Serializer &serializer) const { serializer.WriteProperty(200, "file_path", file_path); serializer.WriteProperty(201, "use_tmp_file", use_tmp_file); serializer.WriteProperty(202, "filename_pattern", filename_pattern); - serializer.WriteProperty(203, "overwrite_or_ignore", overwrite_or_ignore); + serializer.WriteProperty(203, "overwrite_or_ignore", overwrite_mode); serializer.WriteProperty(204, "per_thread_output", per_thread_output); serializer.WriteProperty(205, "partition_output", partition_output); serializer.WriteProperty(206, "partition_columns", partition_columns); @@ -33,13 +33,15 @@ void LogicalCopyToFile::Serialize(Serializer &serializer) const { } serializer.WriteProperty(213, "file_extension", file_extension); + serializer.WriteProperty(214, "rotate", rotate); + serializer.WriteProperty(215, "return_type", return_type); } unique_ptr LogicalCopyToFile::Deserialize(Deserializer &deserializer) { auto file_path = deserializer.ReadProperty(200, "file_path"); auto use_tmp_file = deserializer.ReadProperty(201, "use_tmp_file"); auto filename_pattern = deserializer.ReadProperty(202, "filename_pattern"); - auto overwrite_or_ignore = deserializer.ReadProperty(203, "overwrite_or_ignore"); + auto overwrite_mode = deserializer.ReadProperty(203, "overwrite_mode"); auto per_thread_output = deserializer.ReadProperty(204, "per_thread_output"); auto partition_output = deserializer.ReadProperty(205, "partition_output"); auto partition_columns = deserializer.ReadProperty>(206, "partition_columns"); @@ -81,21 +83,37 @@ unique_ptr LogicalCopyToFile::Deserialize(Deserializer &deseria auto file_extension = deserializer.ReadPropertyWithDefault(213, "file_extension", std::move(default_extension)); + auto rotate = deserializer.ReadPropertyWithDefault(214, "rotate", false); + auto return_type = deserializer.ReadPropertyWithDefault(215, "return_type", CopyFunctionReturnType::CHANGED_ROWS); + auto result = make_uniq(function, std::move(bind_data), std::move(copy_info)); result->file_path = file_path; result->use_tmp_file = use_tmp_file; result->filename_pattern = filename_pattern; result->file_extension = file_extension; - result->overwrite_or_ignore = overwrite_or_ignore; + result->overwrite_mode = overwrite_mode; result->per_thread_output = per_thread_output; result->partition_output = partition_output; result->partition_columns = partition_columns; result->names = names; result->expected_types = expected_types; + result->rotate = rotate; + result->return_type = return_type; return std::move(result); } +vector LogicalCopyToFile::GetColumnBindings() { + switch (return_type) { + case CopyFunctionReturnType::CHANGED_ROWS: + return {ColumnBinding(0, 0)}; + case CopyFunctionReturnType::CHANGED_ROWS_AND_FILE_LIST: + return {ColumnBinding(0, 0), ColumnBinding(0, 1)}; + default: + throw NotImplementedException("Unknown CopyFunctionReturnType"); + } +} + idx_t LogicalCopyToFile::EstimateCardinality(ClientContext &context) { return 1; } diff --git a/src/planner/operator/logical_get.cpp b/src/planner/operator/logical_get.cpp index 077eb6cbbaa..fa344303797 100644 --- a/src/planner/operator/logical_get.cpp +++ b/src/planner/operator/logical_get.cpp @@ -9,6 +9,7 @@ #include "duckdb/storage/data_table.hpp" #include "duckdb/common/serializer/serializer.hpp" #include "duckdb/common/serializer/deserializer.hpp" +#include "duckdb/parser/tableref/table_function_ref.hpp" namespace duckdb { @@ -42,6 +43,10 @@ string LogicalGet::ParamsToString() const { if (!extra_info.file_filters.empty()) { result += "\n[INFOSEPARATOR]\n"; result += "File Filters: " + extra_info.file_filters; + if (extra_info.filtered_files.IsValid() && extra_info.total_files.IsValid()) { + result += StringUtil::Format("\nScanning: %llu/%llu files", extra_info.filtered_files.GetIndex(), + extra_info.total_files.GetIndex()); + } } if (!function.to_string) { return result; @@ -121,6 +126,9 @@ idx_t LogicalGet::EstimateCardinality(ClientContext &context) { return node_stats->estimated_cardinality; } } + if (!children.empty()) { + return children[0]->EstimateCardinality(context); + } return 1; } @@ -164,8 +172,10 @@ unique_ptr LogicalGet::Deserialize(Deserializer &deserializer) deserializer.ReadProperty(207, "named_parameters", result->named_parameters); deserializer.ReadProperty(208, "input_table_types", result->input_table_types); deserializer.ReadProperty(209, "input_table_names", result->input_table_names); + TableFunctionRef empty_ref; TableFunctionBindInput input(result->parameters, result->named_parameters, result->input_table_types, - result->input_table_names, function.function_info.get(), nullptr); + result->input_table_names, function.function_info.get(), nullptr, result->function, + empty_ref); vector bind_return_types; vector bind_names; diff --git a/src/planner/operator/logical_vacuum.cpp b/src/planner/operator/logical_vacuum.cpp index f2a82d7b84f..36352a0ead5 100644 --- a/src/planner/operator/logical_vacuum.cpp +++ b/src/planner/operator/logical_vacuum.cpp @@ -47,7 +47,7 @@ unique_ptr LogicalVacuum::Deserialize(Deserializer &deserialize auto binder = Binder::CreateBinder(context); auto bound_table = binder->Bind(*info.ref); if (bound_table->type != TableReferenceType::BASE_TABLE) { - throw InvalidInputException("Can only vacuum/analyze base tables!"); + throw InvalidInputException("can only vacuum or analyze base tables"); } auto ref = unique_ptr_cast(std::move(bound_table)); auto &table = ref->table; diff --git a/src/planner/planner.cpp b/src/planner/planner.cpp index 0ec47a7bfbd..6449872f4ed 100644 --- a/src/planner/planner.cpp +++ b/src/planner/planner.cpp @@ -13,6 +13,7 @@ #include "duckdb/planner/expression/bound_parameter_expression.hpp" #include "duckdb/transaction/meta_transaction.hpp" #include "duckdb/execution/column_binding_resolver.hpp" +#include "duckdb/main/attached_database.hpp" namespace duckdb { @@ -76,7 +77,7 @@ void Planner::CreatePlan(SQLStatement &statement) { throw; } } - this->properties = binder->properties; + this->properties = binder->GetStatementProperties(); this->properties.parameter_count = parameter_count; properties.bound_all_parameters = !bound_parameters.rebind && parameters_resolved; @@ -138,6 +139,7 @@ void Planner::CreatePlan(unique_ptr statement) { case StatementType::ATTACH_STATEMENT: case StatementType::DETACH_STATEMENT: case StatementType::COPY_DATABASE_STATEMENT: + case StatementType::UPDATE_EXTENSIONS_STATEMENT: CreatePlan(*statement); break; default: @@ -156,9 +158,20 @@ static bool OperatorSupportsSerialization(LogicalOperator &op) { void Planner::VerifyPlan(ClientContext &context, unique_ptr &op, optional_ptr map) { + auto &config = DBConfig::GetConfig(context); #ifdef DUCKDB_ALTERNATIVE_VERIFY - // if alternate verification is enabled we run the original operator - return; + { + auto &serialize_comp = config.options.serialization_compatibility; + auto latest_version = SerializationCompatibility::Latest(); + if (serialize_comp.manually_set && + serialize_comp.serialization_version != latest_version.serialization_version) { + // Serialization should not be skipped, this test relies on the serialization to remove certain fields for + // compatibility with older versions. This might change behavior, not doing this might make this test fail. + } else { + // if alternate verification is enabled we run the original operator + return; + } + } #endif if (!op || !ClientConfig::GetConfig(context).verify_serializer) { return; @@ -173,7 +186,16 @@ void Planner::VerifyPlan(ClientContext &context, unique_ptr &op // format (de)serialization of this operator try { MemoryStream stream; - BinarySerializer::Serialize(*op, stream, true); + + SerializationOptions options; + if (config.options.serialization_compatibility.manually_set) { + // Override the default of 'latest' if this was manually set (for testing, mostly) + options.serialization_compatibility = config.options.serialization_compatibility; + } else { + options.serialization_compatibility = SerializationCompatibility::Latest(); + } + + BinarySerializer::Serialize(*op, stream, options); stream.Rewind(); bound_parameter_map_t parameters; auto new_plan = BinaryDeserializer::Deserialize(stream, context, parameters); @@ -182,10 +204,14 @@ void Planner::VerifyPlan(ClientContext &context, unique_ptr &op *map = std::move(parameters); } op = std::move(new_plan); - } catch (SerializationException &ex) { // NOLINT: explicitly allowing these errors (for now) - // pass - } catch (NotImplementedException &ex) { // NOLINT: explicitly allowing these errors (for now) - // pass + } catch (std::exception &ex) { + ErrorData error(ex); + switch (error.Type()) { + case ExceptionType::NOT_IMPLEMENTED: // NOLINT: explicitly allowing these errors (for now) + break; // pass + default: + throw; + } } } diff --git a/src/planner/subquery/flatten_dependent_join.cpp b/src/planner/subquery/flatten_dependent_join.cpp index 7e863703472..4a8a128fc39 100644 --- a/src/planner/subquery/flatten_dependent_join.cpp +++ b/src/planner/subquery/flatten_dependent_join.cpp @@ -119,6 +119,8 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal idx_t lateral_depth) { // first check if the logical operator has correlated expressions auto entry = has_correlated_expressions.find(*plan); + bool exit_projection = false; + unique_ptr delim_scan; D_ASSERT(entry != has_correlated_expressions.end()); if (!entry->second) { // we reached a node without correlated expressions @@ -136,13 +138,21 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal } } - auto left_columns = plan->GetColumnBindings().size(); + // create cross product with Delim Join auto delim_index = binder.GenerateTableIndex(); - this->base_binding = ColumnBinding(delim_index, 0); - this->delim_offset = left_columns; - this->data_offset = 0; - auto delim_scan = make_uniq(delim_index, delim_types); - return LogicalCrossProduct::Create(std::move(plan), std::move(delim_scan)); + base_binding = ColumnBinding(delim_index, 0); + + auto left_columns = plan->GetColumnBindings().size(); + delim_offset = left_columns; + data_offset = 0; + delim_scan = make_uniq(delim_index, delim_types); + if (plan->type == LogicalOperatorType::LOGICAL_PROJECTION) { + // we want to keep the logical projection for positionality. + exit_projection = true; + } else { + auto cross_product = LogicalCrossProduct::Create(std::move(plan), std::move(delim_scan)); + return cross_product; + } } switch (plan->type) { case LogicalOperatorType::LOGICAL_UNNEST: @@ -166,8 +176,18 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal for (auto &expr : plan->expressions) { parent_propagate_null_values &= expr->PropagatesNullValues(); } - plan->children[0] = - PushDownDependentJoinInternal(std::move(plan->children[0]), parent_propagate_null_values, lateral_depth); + + // if the node has no correlated expressions, + // push the cross product with the delim get only below the projection. + // This will preserve positionality of the columns and prevent errors when reordering of + // delim gets is enabled. + if (exit_projection) { + auto cross_product = LogicalCrossProduct::Create(std::move(plan->children[0]), std::move(delim_scan)); + plan->children[0] = std::move(cross_product); + } else { + plan->children[0] = PushDownDependentJoinInternal(std::move(plan->children[0]), + parent_propagate_null_values, lateral_depth); + } // then we replace any correlated expressions with the corresponding entry in the correlated_map RewriteCorrelatedExpressions rewriter(base_binding, correlated_map, lateral_depth); @@ -248,7 +268,7 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal } } auto left_index = binder.GenerateTableIndex(); - auto delim_scan = make_uniq(left_index, delim_types); + delim_scan = make_uniq(left_index, delim_types); join->children.push_back(std::move(delim_scan)); join->children.push_back(std::move(plan)); for (idx_t i = 0; i < new_group_count; i++) { @@ -555,6 +575,11 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal // push into children plan->children[0] = PushDownDependentJoinInternal(std::move(plan->children[0]), parent_propagate_null_values, lateral_depth); + + // we replace any correlated expressions with the corresponding entry in the correlated_map + RewriteCorrelatedExpressions rewriter(base_binding, correlated_map, lateral_depth); + rewriter.VisitOperator(*plan); + // add the correlated columns to the PARTITION BY clauses in the Window for (auto &expr : window.expressions) { D_ASSERT(expr->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); @@ -642,6 +667,9 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal } this->delim_offset = get.returned_types.size(); this->data_offset = 0; + + RewriteCorrelatedExpressions rewriter(base_binding, correlated_map, lateral_depth); + rewriter.VisitOperator(*plan); return plan; } case LogicalOperatorType::LOGICAL_MATERIALIZED_CTE: diff --git a/src/storage/arena_allocator.cpp b/src/storage/arena_allocator.cpp index d7198c06281..b64a58888b2 100644 --- a/src/storage/arena_allocator.cpp +++ b/src/storage/arena_allocator.cpp @@ -26,6 +26,7 @@ ArenaChunk::~ArenaChunk() { //===--------------------------------------------------------------------===// struct ArenaAllocatorData : public PrivateAllocatorData { explicit ArenaAllocatorData(ArenaAllocator &allocator) : allocator(allocator) { + free_type = AllocatorFreeType::DOES_NOT_REQUIRE_FREE; } ArenaAllocator &allocator; diff --git a/src/storage/block.cpp b/src/storage/block.cpp index e90b621c31a..f97da28b803 100644 --- a/src/storage/block.cpp +++ b/src/storage/block.cpp @@ -1,10 +1,11 @@ #include "duckdb/storage/block.hpp" + #include "duckdb/common/assert.hpp" namespace duckdb { -Block::Block(Allocator &allocator, block_id_t id) - : FileBuffer(allocator, FileBufferType::BLOCK, Storage::BLOCK_SIZE), id(id) { +Block::Block(Allocator &allocator, const block_id_t id, const idx_t block_size) + : FileBuffer(allocator, FileBufferType::BLOCK, block_size), id(id) { } Block::Block(Allocator &allocator, block_id_t id, uint32_t internal_size) diff --git a/src/storage/buffer/block_handle.cpp b/src/storage/buffer/block_handle.cpp index 6e7a96c0d02..92ad1bb2ce0 100644 --- a/src/storage/buffer/block_handle.cpp +++ b/src/storage/buffer/block_handle.cpp @@ -1,25 +1,26 @@ #include "duckdb/storage/buffer/block_handle.hpp" + +#include "duckdb/common/file_buffer.hpp" #include "duckdb/storage/block.hpp" #include "duckdb/storage/block_manager.hpp" #include "duckdb/storage/buffer/buffer_handle.hpp" -#include "duckdb/storage/buffer_manager.hpp" #include "duckdb/storage/buffer/buffer_pool.hpp" -#include "duckdb/common/file_buffer.hpp" +#include "duckdb/storage/buffer_manager.hpp" namespace duckdb { BlockHandle::BlockHandle(BlockManager &block_manager, block_id_t block_id_p, MemoryTag tag) - : block_manager(block_manager), readers(0), block_id(block_id_p), tag(tag), buffer(nullptr), eviction_timestamp(0), + : block_manager(block_manager), readers(0), block_id(block_id_p), tag(tag), buffer(nullptr), eviction_seq_num(0), can_destroy(false), memory_charge(tag, block_manager.buffer_manager.GetBufferPool()), unswizzled(nullptr) { - eviction_timestamp = 0; + eviction_seq_num = 0; state = BlockState::BLOCK_UNLOADED; - memory_usage = Storage::BLOCK_ALLOC_SIZE; + memory_usage = block_manager.GetBlockAllocSize(); } BlockHandle::BlockHandle(BlockManager &block_manager, block_id_t block_id_p, MemoryTag tag, unique_ptr buffer_p, bool can_destroy_p, idx_t block_size, BufferPoolReservation &&reservation) - : block_manager(block_manager), readers(0), block_id(block_id_p), tag(tag), eviction_timestamp(0), + : block_manager(block_manager), readers(0), block_id(block_id_p), tag(tag), eviction_seq_num(0), can_destroy(can_destroy_p), memory_charge(tag, block_manager.buffer_manager.GetBufferPool()), unswizzled(nullptr) { buffer = std::move(buffer_p); @@ -34,7 +35,7 @@ BlockHandle::~BlockHandle() { // NOLINT: allow internal exceptions if (buffer && buffer->type != FileBufferType::TINY_BUFFER) { // we kill the latest version in the eviction queue auto &buffer_manager = block_manager.buffer_manager; - buffer_manager.GetBufferPool().IncrementDeadNodes(); + buffer_manager.GetBufferPool().IncrementDeadNodes(buffer->type); } // no references remain to this block: erase @@ -69,6 +70,17 @@ unique_ptr AllocateBlock(BlockManager &block_manager, unique_ptr &handle, data_ptr_t data, + unique_ptr reusable_buffer) { + D_ASSERT(handle->state != BlockState::BLOCK_LOADED); + // copy over the data into the block from the file buffer + auto block = AllocateBlock(handle->block_manager, std::move(reusable_buffer), handle->block_id); + memcpy(block->InternalBuffer(), data, block->AllocSize()); + handle->buffer = std::move(block); + handle->state = BlockState::BLOCK_LOADED; + return BufferHandle(handle, handle->buffer.get()); +} + BufferHandle BlockHandle::Load(shared_ptr &handle, unique_ptr reusable_buffer) { if (handle->state == BlockState::BLOCK_LOADED) { // already loaded diff --git a/src/storage/buffer/block_manager.cpp b/src/storage/buffer/block_manager.cpp index e5e21b0e3cb..0ead4cff01c 100644 --- a/src/storage/buffer/block_manager.cpp +++ b/src/storage/buffer/block_manager.cpp @@ -6,8 +6,9 @@ namespace duckdb { -BlockManager::BlockManager(BufferManager &buffer_manager) - : buffer_manager(buffer_manager), metadata_manager(make_uniq(*this, buffer_manager)) { +BlockManager::BlockManager(BufferManager &buffer_manager, const optional_idx block_alloc_size_p) + : buffer_manager(buffer_manager), metadata_manager(make_uniq(*this, buffer_manager)), + block_alloc_size(block_alloc_size_p) { } shared_ptr BlockManager::RegisterBlock(block_id_t block_id) { @@ -37,7 +38,7 @@ shared_ptr BlockManager::ConvertToPersistent(block_id_t block_id, s // Temp buffers can be larger than the storage block size. // But persistent buffers cannot. - D_ASSERT(old_block->buffer->AllocSize() <= Storage::BLOCK_ALLOC_SIZE); + D_ASSERT(old_block->buffer->AllocSize() <= GetBlockAllocSize()); // register a block with the new block id auto new_block = RegisterBlock(block_id); @@ -63,7 +64,7 @@ shared_ptr BlockManager::ConvertToPersistent(block_id_t block_id, s // potentially purge the queue auto purge_queue = buffer_manager.GetBufferPool().AddToEvictionQueue(new_block); if (purge_queue) { - buffer_manager.GetBufferPool().PurgeQueue(); + buffer_manager.GetBufferPool().PurgeQueue(new_block->buffer->type); } return new_block; diff --git a/src/storage/buffer/buffer_handle.cpp b/src/storage/buffer/buffer_handle.cpp index dc3be3f2844..21226eb685d 100644 --- a/src/storage/buffer/buffer_handle.cpp +++ b/src/storage/buffer/buffer_handle.cpp @@ -11,7 +11,7 @@ BufferHandle::BufferHandle(shared_ptr handle_p, FileBuffer *node_p) : handle(std::move(handle_p)), node(node_p) { } -BufferHandle::BufferHandle(BufferHandle &&other) noexcept { +BufferHandle::BufferHandle(BufferHandle &&other) noexcept : node(nullptr) { std::swap(node, other.node); std::swap(handle, other.handle); } diff --git a/src/storage/buffer/buffer_pool.cpp b/src/storage/buffer/buffer_pool.cpp index d94b87d20cf..c5054aece34 100644 --- a/src/storage/buffer/buffer_pool.cpp +++ b/src/storage/buffer/buffer_pool.cpp @@ -3,17 +3,17 @@ #include "duckdb/common/exception.hpp" #include "duckdb/parallel/concurrentqueue.hpp" #include "duckdb/storage/temporary_memory_manager.hpp" +#include "duckdb/common/chrono.hpp" namespace duckdb { -typedef duckdb_moodycamel::ConcurrentQueue eviction_queue_t; - -struct EvictionQueue { - eviction_queue_t q; -}; +BufferEvictionNode::BufferEvictionNode(weak_ptr handle_p, idx_t eviction_seq_num) + : handle(std::move(handle_p)), handle_sequence_number(eviction_seq_num) { + D_ASSERT(!handle.expired()); +} bool BufferEvictionNode::CanUnload(BlockHandle &handle_p) { - if (timestamp != handle_p.eviction_timestamp) { + if (handle_sequence_number != handle_p.eviction_seq_num) { // handle was used in between return false; } @@ -34,9 +34,170 @@ shared_ptr BufferEvictionNode::TryGetBlockHandle() { return handle_p; } -BufferPool::BufferPool(idx_t maximum_memory) - : current_memory(0), maximum_memory(maximum_memory), queue(make_uniq()), - temporary_memory_manager(make_uniq()), evict_queue_insertions(0), total_dead_nodes(0) { +typedef duckdb_moodycamel::ConcurrentQueue eviction_queue_t; + +struct EvictionQueue { +public: + EvictionQueue() : evict_queue_insertions(0), total_dead_nodes(0) { + } + +public: + //! Add a buffer handle to the eviction queue. Returns true, if the queue is + //! ready to be purged, and false otherwise. + bool AddToEvictionQueue(BufferEvictionNode &&node); + //! Tries to dequeue an element from the eviction queue, but only after acquiring the purge queue lock. + bool TryDequeueWithLock(BufferEvictionNode &node); + //! Garbage collect dead nodes in the eviction queue. + void Purge(); + template + void IterateUnloadableBlocks(FN fn); + + //! Increment the dead node counter in the purge queue. + inline void IncrementDeadNodes() { + total_dead_nodes++; + } + //! Decrement the dead node counter in the purge queue. + inline void DecrementDeadNodes() { + total_dead_nodes--; + } + +private: + //! Bulk purge dead nodes from the eviction queue. Then, enqueue those that are still alive. + void PurgeIteration(const idx_t purge_size); + +public: + //! The concurrent queue + eviction_queue_t q; + +private: + //! We trigger a purge of the eviction queue every INSERT_INTERVAL insertions + constexpr static idx_t INSERT_INTERVAL = 4096; + //! We multiply the base purge size by this value. + constexpr static idx_t PURGE_SIZE_MULTIPLIER = 2; + //! We multiply the purge size by this value to determine early-outs. This is the minimum queue size. + //! We never purge below this point. + constexpr static idx_t EARLY_OUT_MULTIPLIER = 4; + //! We multiply the approximate alive nodes by this value to test whether our total dead nodes + //! exceed their allowed ratio. Must be greater than 1. + constexpr static idx_t ALIVE_NODE_MULTIPLIER = 4; + +private: + //! Total number of insertions into the eviction queue. This guides the schedule for calling PurgeQueue. + atomic evict_queue_insertions; + //! Total dead nodes in the eviction queue. There are two scenarios in which a node dies: (1) we destroy its block + //! handle, or (2) we insert a newer version into the eviction queue. + atomic total_dead_nodes; + + //! Locked, if a queue purge is currently active or we're trying to forcefully evict a node. + //! Only lets a single thread enter the purge phase. + mutex purge_lock; + //! A pre-allocated vector of eviction nodes. We reuse this to keep the allocation overhead of purges small. + vector purge_nodes; +}; + +bool EvictionQueue::AddToEvictionQueue(BufferEvictionNode &&node) { + q.enqueue(std::move(node)); + return ++evict_queue_insertions % INSERT_INTERVAL == 0; +} + +bool EvictionQueue::TryDequeueWithLock(BufferEvictionNode &node) { + lock_guard lock(purge_lock); + return q.try_dequeue(node); +} + +void EvictionQueue::Purge() { + // only one thread purges the queue, all other threads early-out + if (!purge_lock.try_lock()) { + return; + } + lock_guard lock {purge_lock, std::adopt_lock}; + + // we purge INSERT_INTERVAL * PURGE_SIZE_MULTIPLIER nodes + idx_t purge_size = INSERT_INTERVAL * PURGE_SIZE_MULTIPLIER; + + // get an estimate of the queue size as-of now + idx_t approx_q_size = q.size_approx(); + + // early-out, if the queue is not big enough to justify purging + // - we want to keep the LRU characteristic alive + if (approx_q_size < purge_size * EARLY_OUT_MULTIPLIER) { + return; + } + + // There are two types of situations. + + // For most scenarios, purging INSERT_INTERVAL * PURGE_SIZE_MULTIPLIER nodes is enough. + // Purging more nodes than we insert also counters oscillation for scenarios where most nodes are dead. + // If we always purge slightly more, we trigger a purge less often, as we purge below the trigger. + + // However, if the pressure on the queue becomes too contested, we need to purge more aggressively, + // i.e., we actively seek a specific number of dead nodes to purge. We use the total number of existing dead nodes. + // We detect this situation by observing the queue's ratio between alive vs. dead nodes. If the ratio of alive vs. + // dead nodes grows faster than we can purge, we keep purging until we hit one of the following conditions. + + // 2.1. We're back at an approximate queue size less than purge_size * EARLY_OUT_MULTIPLIER. + // 2.2. We're back at a ratio of 1*alive_node:ALIVE_NODE_MULTIPLIER*dead_nodes. + // 2.3. We've purged the entire queue: max_purges is zero. This is a worst-case scenario, + // guaranteeing that we always exit the loop. + + idx_t max_purges = approx_q_size / purge_size; + while (max_purges != 0) { + PurgeIteration(purge_size); + + // update relevant sizes and potentially early-out + approx_q_size = q.size_approx(); + + // early-out according to (2.1) + if (approx_q_size < purge_size * EARLY_OUT_MULTIPLIER) { + break; + } + + idx_t approx_dead_nodes = total_dead_nodes; + approx_dead_nodes = approx_dead_nodes > approx_q_size ? approx_q_size : approx_dead_nodes; + idx_t approx_alive_nodes = approx_q_size - approx_dead_nodes; + + // early-out according to (2.2) + if (approx_alive_nodes * (ALIVE_NODE_MULTIPLIER - 1) > approx_dead_nodes) { + break; + } + + max_purges--; + } +} + +void EvictionQueue::PurgeIteration(const idx_t purge_size) { + // if this purge is significantly smaller or bigger than the previous purge, then + // we need to resize the purge_nodes vector. Note that this barely happens, as we + // purge queue_insertions * PURGE_SIZE_MULTIPLIER nodes + idx_t previous_purge_size = purge_nodes.size(); + if (purge_size < previous_purge_size / 2 || purge_size > previous_purge_size) { + purge_nodes.resize(purge_size); + } + + // bulk purge + idx_t actually_dequeued = q.try_dequeue_bulk(purge_nodes.begin(), purge_size); + + // retrieve all alive nodes that have been wrongly dequeued + idx_t alive_nodes = 0; + for (idx_t i = 0; i < actually_dequeued; i++) { + auto &node = purge_nodes[i]; + auto handle = node.TryGetBlockHandle(); + if (handle) { + q.enqueue(std::move(node)); + alive_nodes++; + } + } + + total_dead_nodes -= actually_dequeued - alive_nodes; +} + +BufferPool::BufferPool(idx_t maximum_memory, bool track_eviction_timestamps) + : current_memory(0), maximum_memory(maximum_memory), track_eviction_timestamps(track_eviction_timestamps), + temporary_memory_manager(make_uniq()) { + queues.reserve(FILE_BUFFER_TYPE_COUNT); + for (idx_t i = 0; i < FILE_BUFFER_TYPE_COUNT; i++) { + queues.push_back(make_uniq()); + } for (idx_t i = 0; i < MEMORY_TAG_COUNT; i++) { memory_usage_per_tag[i] = 0; } @@ -45,25 +206,34 @@ BufferPool::~BufferPool() { } bool BufferPool::AddToEvictionQueue(shared_ptr &handle) { + auto &queue = GetEvictionQueueForType(handle->buffer->type); // The block handle is locked during this operation (Unpin), // or the block handle is still a local variable (ConvertToPersistent) - D_ASSERT(handle->readers == 0); - auto ts = ++handle->eviction_timestamp; - - BufferEvictionNode evict_node(weak_ptr(handle), ts); - queue->q.enqueue(evict_node); + auto ts = ++handle->eviction_seq_num; + if (track_eviction_timestamps) { + handle->lru_timestamp_msec = + std::chrono::time_point_cast(std::chrono::steady_clock::now()) + .time_since_epoch() + .count(); + } if (ts != 1) { // we add a newer version, i.e., we kill exactly one previous version - IncrementDeadNodes(); + queue.IncrementDeadNodes(); } - if (++evict_queue_insertions % INSERT_INTERVAL == 0) { - return true; - } - return false; + // Get the eviction queue for the buffer type and add it + return queue.AddToEvictionQueue(BufferEvictionNode(weak_ptr(handle), ts)); +} + +EvictionQueue &BufferPool::GetEvictionQueueForType(FileBufferType type) { + return *queues[uint8_t(type) - 1]; +} + +void BufferPool::IncrementDeadNodes(FileBufferType type) { + GetEvictionQueueForType(type).IncrementDeadNodes(); } void BufferPool::UpdateUsedMemory(MemoryTag tag, int64_t size) { @@ -94,142 +264,125 @@ TemporaryMemoryManager &BufferPool::GetTemporaryMemoryManager() { BufferPool::EvictionResult BufferPool::EvictBlocks(MemoryTag tag, idx_t extra_memory, idx_t memory_limit, unique_ptr *buffer) { - BufferEvictionNode node; - TempBufferPoolReservation r(tag, *this, extra_memory); + // First, we try to evict persistent table data + auto block_result = + EvictBlocksInternal(GetEvictionQueueForType(FileBufferType::BLOCK), tag, extra_memory, memory_limit, buffer); + if (block_result.success) { + return block_result; + } - while (current_memory > memory_limit) { - // get a block to unpin from the queue - if (!queue->q.try_dequeue(node)) { - // we could not dequeue any eviction node, so we try one more time, - // but more aggressively - if (!TryDequeueWithLock(node)) { - // still no success, we return - r.Resize(0); - return {false, std::move(r)}; - } - } + // If that does not succeed, we try to evict temporary data + auto managed_buffer_result = EvictBlocksInternal(GetEvictionQueueForType(FileBufferType::MANAGED_BUFFER), tag, + extra_memory, memory_limit, buffer); + if (managed_buffer_result.success) { + return managed_buffer_result; + } - // get a reference to the underlying block pointer - auto handle = node.TryGetBlockHandle(); - if (!handle) { - DecrementDeadNodes(); - continue; - } + // Finally, we try to evict tiny buffers + return EvictBlocksInternal(GetEvictionQueueForType(FileBufferType::TINY_BUFFER), tag, extra_memory, memory_limit, + buffer); +} - // we might be able to free this block: grab the mutex and check if we can free it - lock_guard lock(handle->lock); - if (!node.CanUnload(*handle)) { - // something changed in the mean-time, bail out - DecrementDeadNodes(); - continue; - } +BufferPool::EvictionResult BufferPool::EvictBlocksInternal(EvictionQueue &queue, MemoryTag tag, idx_t extra_memory, + idx_t memory_limit, unique_ptr *buffer) { + TempBufferPoolReservation r(tag, *this, extra_memory); + bool found = false; + + if (current_memory <= memory_limit) { + return {true, std::move(r)}; + } + queue.IterateUnloadableBlocks([&](BufferEvictionNode &, const shared_ptr &handle) { // hooray, we can unload the block if (buffer && handle->buffer->AllocSize() == extra_memory) { // we can re-use the memory directly *buffer = handle->UnloadAndTakeBlock(); - return {true, std::move(r)}; + found = true; + return false; } // release the memory and mark the block as unloaded handle->Unload(); - } - return {true, std::move(r)}; -} -bool BufferPool::TryDequeueWithLock(BufferEvictionNode &node) { - lock_guard lock(purge_lock); - return queue->q.try_dequeue(node); -} - -void BufferPool::PurgeIteration(const idx_t purge_size) { - // if this purge is significantly smaller or bigger than the previous purge, then - // we need to resize the purge_nodes vector. Note that this barely happens, as we - // purge queue_insertions * PURGE_SIZE_MULTIPLIER nodes - idx_t previous_purge_size = purge_nodes.size(); - if (purge_size < previous_purge_size / 2 || purge_size > previous_purge_size) { - purge_nodes.resize(purge_size); - } + if (current_memory <= memory_limit) { + found = true; + return false; + } - // bulk purge - idx_t actually_dequeued = queue->q.try_dequeue_bulk(purge_nodes.begin(), purge_size); + // Continue iteration + return true; + }); - // retrieve all alive nodes that have been wrongly dequeued - idx_t alive_nodes = 0; - for (idx_t i = 0; i < actually_dequeued; i++) { - auto &node = purge_nodes[i]; - auto handle = node.TryGetBlockHandle(); - if (handle) { - queue->q.enqueue(std::move(node)); - alive_nodes++; - } + if (!found) { + r.Resize(0); } - total_dead_nodes -= actually_dequeued - alive_nodes; + return {found, std::move(r)}; } -void BufferPool::PurgeQueue() { - - // only one thread purges the queue, all other threads early-out - if (!purge_lock.try_lock()) { - return; +idx_t BufferPool::PurgeAgedBlocks(uint32_t max_age_sec) { + int64_t now = std::chrono::time_point_cast(std::chrono::steady_clock::now()) + .time_since_epoch() + .count(); + int64_t limit = now - (static_cast(max_age_sec) * 1000); + idx_t purged_bytes = 0; + for (auto &queue : queues) { + purged_bytes += PurgeAgedBlocksInternal(*queue, max_age_sec, now, limit); } - lock_guard lock {purge_lock, std::adopt_lock}; - - // we purge INSERT_INTERVAL * PURGE_SIZE_MULTIPLIER nodes - idx_t purge_size = INSERT_INTERVAL * PURGE_SIZE_MULTIPLIER; - - // get an estimate of the queue size as-of now - idx_t approx_q_size = queue->q.size_approx(); - - // early-out, if the queue is not big enough to justify purging - // - we want to keep the LRU characteristic alive - if (approx_q_size < purge_size * EARLY_OUT_MULTIPLIER) { - return; - } - - // There are two types of situations. - - // For most scenarios, purging INSERT_INTERVAL * PURGE_SIZE_MULTIPLIER nodes is enough. - // Purging more nodes than we insert also counters oscillation for scenarios where most nodes are dead. - // If we always purge slightly more, we trigger a purge less often, as we purge below the trigger. - - // However, if the pressure on the queue becomes too contested, we need to purge more aggressively, - // i.e., we actively seek a specific number of dead nodes to purge. We use the total number of existing dead nodes. - // We detect this situation by observing the queue's ratio between alive vs. dead nodes. If the ratio of alive vs. - // dead nodes grows faster than we can purge, we keep purging until we hit one of the following conditions. - - // 2.1. We're back at an approximate queue size less than purge_size * EARLY_OUT_MULTIPLIER. - // 2.2. We're back at a ratio of 1*alive_node:ALIVE_NODE_MULTIPLIER*dead_nodes. - // 2.3. We've purged the entire queue: max_purges is zero. This is a worst-case scenario, - // guaranteeing that we always exit the loop. - - idx_t max_purges = approx_q_size / purge_size; - while (max_purges != 0) { + return purged_bytes; +} - PurgeIteration(purge_size); +idx_t BufferPool::PurgeAgedBlocksInternal(EvictionQueue &queue, uint32_t max_age_sec, int64_t now, int64_t limit) { + idx_t purged_bytes = 0; + queue.IterateUnloadableBlocks([&](BufferEvictionNode &node, const shared_ptr &handle) { + // We will unload this block regardless. But stop the iteration immediately afterward if this + // block is younger than the age threshold. + bool is_fresh = handle->lru_timestamp_msec >= limit && handle->lru_timestamp_msec <= now; + purged_bytes += handle->GetMemoryUsage(); + handle->Unload(); + return is_fresh; + }); + return purged_bytes; +} - // update relevant sizes and potentially early-out - approx_q_size = queue->q.size_approx(); +template +void EvictionQueue::IterateUnloadableBlocks(FN fn) { + for (;;) { + // get a block to unpin from the queue + BufferEvictionNode node; + if (!q.try_dequeue(node)) { + // we could not dequeue any eviction node, so we try one more time, + // but more aggressively + if (!TryDequeueWithLock(node)) { + return; + } + } - // early-out according to (2.1) - if (approx_q_size < purge_size * EARLY_OUT_MULTIPLIER) { - break; + // get a reference to the underlying block pointer + auto handle = node.TryGetBlockHandle(); + if (!handle) { + DecrementDeadNodes(); + continue; } - idx_t approx_dead_nodes = total_dead_nodes; - approx_dead_nodes = approx_dead_nodes > approx_q_size ? approx_q_size : approx_dead_nodes; - idx_t approx_alive_nodes = approx_q_size - approx_dead_nodes; + // we might be able to free this block: grab the mutex and check if we can free it + lock_guard lock(handle->lock); + if (!node.CanUnload(*handle)) { + // something changed in the mean-time, bail out + DecrementDeadNodes(); + continue; + } - // early-out according to (2.2) - if (approx_alive_nodes * (ALIVE_NODE_MULTIPLIER - 1) > approx_dead_nodes) { + if (!fn(node, handle)) { break; } - - max_purges--; } } +void BufferPool::PurgeQueue(FileBufferType type) { + GetEvictionQueueForType(type).Purge(); +} + void BufferPool::SetLimit(idx_t limit, const char *exception_postscript) { lock_guard l_lock(limit_lock); // try to evict until the limit is reached diff --git a/src/storage/buffer_manager.cpp b/src/storage/buffer_manager.cpp index f234a3911c7..50e40fb5393 100644 --- a/src/storage/buffer_manager.cpp +++ b/src/storage/buffer_manager.cpp @@ -8,7 +8,11 @@ namespace duckdb { -shared_ptr BufferManager::RegisterSmallMemory(idx_t block_size) { +shared_ptr BufferManager::RegisterTransientMemory(const idx_t size) { + throw NotImplementedException("This type of BufferManager can not create 'transient-memory' blocks"); +} + +shared_ptr BufferManager::RegisterSmallMemory(const idx_t size) { throw NotImplementedException("This type of BufferManager can not create 'small-memory' blocks"); } diff --git a/src/storage/checkpoint/row_group_writer.cpp b/src/storage/checkpoint/row_group_writer.cpp index 3845782cad3..90f7ba42955 100644 --- a/src/storage/checkpoint/row_group_writer.cpp +++ b/src/storage/checkpoint/row_group_writer.cpp @@ -9,12 +9,21 @@ CompressionType RowGroupWriter::GetColumnCompressionType(idx_t i) { return table.GetColumn(LogicalIndex(i)).CompressionType(); } +SingleFileRowGroupWriter::SingleFileRowGroupWriter(TableCatalogEntry &table, PartialBlockManager &partial_block_manager, + TableDataWriter &writer, MetadataWriter &table_data_writer) + : RowGroupWriter(table, partial_block_manager), writer(writer), table_data_writer(table_data_writer) { +} + void SingleFileRowGroupWriter::WriteColumnDataPointers(ColumnCheckpointState &column_checkpoint_state, Serializer &serializer) { const auto &data_pointers = column_checkpoint_state.data_pointers; serializer.WriteProperty(100, "data_pointers", data_pointers); } +CheckpointType SingleFileRowGroupWriter::GetCheckpointType() const { + return writer.GetCheckpointType(); +} + MetadataWriter &SingleFileRowGroupWriter::GetPayloadWriter() { return table_data_writer; } diff --git a/src/storage/checkpoint/table_data_writer.cpp b/src/storage/checkpoint/table_data_writer.cpp index b90cae8901c..dad7e96a22c 100644 --- a/src/storage/checkpoint/table_data_writer.cpp +++ b/src/storage/checkpoint/table_data_writer.cpp @@ -39,7 +39,12 @@ SingleFileTableDataWriter::SingleFileTableDataWriter(SingleFileCheckpointWriter } unique_ptr SingleFileTableDataWriter::GetRowGroupWriter(RowGroup &row_group) { - return make_uniq(table, checkpoint_manager.partial_block_manager, table_data_writer); + return make_uniq(table, checkpoint_manager.partial_block_manager, *this, + table_data_writer); +} + +CheckpointType SingleFileTableDataWriter::GetCheckpointType() const { + return checkpoint_manager.GetCheckpointType(); } void SingleFileTableDataWriter::FinalizeTable(const TableStatistics &global_stats, DataTableInfo *info, @@ -75,7 +80,7 @@ void SingleFileTableDataWriter::FinalizeTable(const TableStatistics &global_stat serializer.WriteProperty(101, "table_pointer", pointer); serializer.WriteProperty(102, "total_rows", total_rows); - auto index_storage_infos = info->indexes.GetStorageInfos(); + auto index_storage_infos = info->GetIndexes().GetStorageInfos(); // write empty block pointers for forwards compatibility vector compat_block_pointers; serializer.WriteProperty(103, "index_pointers", compat_block_pointers); diff --git a/src/storage/checkpoint/write_overflow_strings_to_disk.cpp b/src/storage/checkpoint/write_overflow_strings_to_disk.cpp index fd75132a9ac..5c5b5f0c0e7 100644 --- a/src/storage/checkpoint/write_overflow_strings_to_disk.cpp +++ b/src/storage/checkpoint/write_overflow_strings_to_disk.cpp @@ -40,10 +40,10 @@ void WriteOverflowStringsToDisk::WriteString(UncompressedStringSegmentState &sta block_id_t &result_block, int32_t &result_offset) { auto &buffer_manager = block_manager.buffer_manager; if (!handle.IsValid()) { - handle = buffer_manager.Allocate(MemoryTag::OVERFLOW_STRINGS, Storage::BLOCK_SIZE); + handle = buffer_manager.Allocate(MemoryTag::OVERFLOW_STRINGS, block_manager.GetBlockSize()); } // first write the length of the string - if (block_id == INVALID_BLOCK || offset + 2 * sizeof(uint32_t) >= STRING_SPACE) { + if (block_id == INVALID_BLOCK || offset + 2 * sizeof(uint32_t) >= GetStringSpace()) { AllocateNewBlock(state, block_manager.GetFreeBlockId()); } result_block = block_id; @@ -59,7 +59,7 @@ void WriteOverflowStringsToDisk::WriteString(UncompressedStringSegmentState &sta auto strptr = string.GetData(); auto remaining = UnsafeNumericCast(string_length); while (remaining > 0) { - uint32_t to_write = MinValue(remaining, UnsafeNumericCast(STRING_SPACE - offset)); + uint32_t to_write = MinValue(remaining, UnsafeNumericCast(GetStringSpace() - offset)); if (to_write > 0) { memcpy(data_ptr + offset, strptr, to_write); @@ -68,7 +68,7 @@ void WriteOverflowStringsToDisk::WriteString(UncompressedStringSegmentState &sta strptr += to_write; } if (remaining > 0) { - D_ASSERT(offset == WriteOverflowStringsToDisk::STRING_SPACE); + D_ASSERT(offset == GetStringSpace()); // there is still remaining stuff to write // now write the current block to disk and allocate a new block AllocateNewBlock(state, block_manager.GetFreeBlockId()); @@ -79,8 +79,8 @@ void WriteOverflowStringsToDisk::WriteString(UncompressedStringSegmentState &sta void WriteOverflowStringsToDisk::Flush() { if (block_id != INVALID_BLOCK && offset > 0) { // zero-initialize the empty part of the overflow string buffer (if any) - if (offset < STRING_SPACE) { - memset(handle.Ptr() + offset, 0, STRING_SPACE - offset); + if (offset < GetStringSpace()) { + memset(handle.Ptr() + offset, 0, GetStringSpace() - offset); } // write to disk block_manager.Write(handle.GetFileBuffer(), block_id); @@ -93,7 +93,7 @@ void WriteOverflowStringsToDisk::AllocateNewBlock(UncompressedStringSegmentState if (block_id != INVALID_BLOCK) { // there is an old block, write it first // write the new block id at the end of the previous block - Store(new_block_id, handle.Ptr() + WriteOverflowStringsToDisk::STRING_SPACE); + Store(new_block_id, handle.Ptr() + GetStringSpace()); Flush(); } offset = 0; @@ -101,4 +101,8 @@ void WriteOverflowStringsToDisk::AllocateNewBlock(UncompressedStringSegmentState state.RegisterBlock(block_manager, new_block_id); } +idx_t WriteOverflowStringsToDisk::GetStringSpace() const { + return block_manager.GetBlockSize() - sizeof(block_id_t); +} + } // namespace duckdb diff --git a/src/storage/checkpoint_manager.cpp b/src/storage/checkpoint_manager.cpp index 429e0b9d1d5..e4d578cbbf2 100644 --- a/src/storage/checkpoint_manager.cpp +++ b/src/storage/checkpoint_manager.cpp @@ -2,15 +2,17 @@ #include "duckdb/catalog/catalog_entry/duck_index_entry.hpp" #include "duckdb/catalog/catalog_entry/duck_table_entry.hpp" +#include "duckdb/catalog/catalog_entry/index_catalog_entry.hpp" #include "duckdb/catalog/catalog_entry/scalar_macro_catalog_entry.hpp" #include "duckdb/catalog/catalog_entry/schema_catalog_entry.hpp" #include "duckdb/catalog/catalog_entry/sequence_catalog_entry.hpp" #include "duckdb/catalog/catalog_entry/type_catalog_entry.hpp" #include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp" -#include "duckdb/catalog/catalog_entry/index_catalog_entry.hpp" #include "duckdb/catalog/duck_catalog.hpp" #include "duckdb/common/serializer/binary_deserializer.hpp" #include "duckdb/common/serializer/binary_serializer.hpp" +#include "duckdb/execution/index/art/art.hpp" +#include "duckdb/execution/index/unbound_index.hpp" #include "duckdb/main/attached_database.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/main/config.hpp" @@ -20,23 +22,23 @@ #include "duckdb/parser/parsed_data/create_view_info.hpp" #include "duckdb/planner/binder.hpp" #include "duckdb/planner/bound_tableref.hpp" -#include "duckdb/planner/expression_binder/index_binder.hpp" #include "duckdb/planner/parsed_data/bound_create_table_info.hpp" #include "duckdb/storage/block_manager.hpp" #include "duckdb/storage/checkpoint/table_data_reader.hpp" #include "duckdb/storage/checkpoint/table_data_writer.hpp" #include "duckdb/storage/metadata/metadata_reader.hpp" #include "duckdb/storage/table/column_checkpoint_state.hpp" +#include "duckdb/transaction/meta_transaction.hpp" #include "duckdb/transaction/transaction_manager.hpp" -#include "duckdb/execution/index/art/art.hpp" -#include "duckdb/execution/index/unknown_index.hpp" namespace duckdb { void ReorderTableEntries(catalog_entry_vector_t &tables); -SingleFileCheckpointWriter::SingleFileCheckpointWriter(AttachedDatabase &db, BlockManager &block_manager) - : CheckpointWriter(db), partial_block_manager(block_manager, CheckpointType::FULL_CHECKPOINT) { +SingleFileCheckpointWriter::SingleFileCheckpointWriter(AttachedDatabase &db, BlockManager &block_manager, + CheckpointType checkpoint_type) + : CheckpointWriter(db), partial_block_manager(block_manager, PartialBlockType::FULL_CHECKPOINT), + checkpoint_type(checkpoint_type) { } BlockManager &SingleFileCheckpointWriter::GetBlockManager() { @@ -168,7 +170,11 @@ void SingleFileCheckpointWriter::CreateCheckpoint() { } */ auto catalog_entries = GetCatalogEntries(schemas); - BinarySerializer serializer(*metadata_writer); + SerializationOptions serialization_options; + + serialization_options.serialization_compatibility = config.options.serialization_compatibility; + + BinarySerializer serializer(*metadata_writer, serialization_options); serializer.Begin(); serializer.WriteList(100, "catalog_entries", catalog_entries.size(), [&](Serializer::List &list, idx_t i) { auto &entry = catalog_entries[i]; @@ -176,7 +182,6 @@ void SingleFileCheckpointWriter::CreateCheckpoint() { }); serializer.End(); - partial_block_manager.FlushPartialBlocks(); metadata_writer->Flush(); table_metadata_writer->Flush(); @@ -185,9 +190,9 @@ void SingleFileCheckpointWriter::CreateCheckpoint() { // WAL we write an entry CHECKPOINT "meta_block_id" into the WAL upon loading, if we see there is an entry // CHECKPOINT "meta_block_id", and the id MATCHES the head idin the file we know that the database was successfully // checkpointed, so we know that we should avoid replaying the WAL to avoid duplicating data - auto wal = storage_manager.GetWriteAheadLog(); - bool wal_is_empty = wal->GetWALSize() == 0; + bool wal_is_empty = storage_manager.GetWALSize() == 0; if (!wal_is_empty) { + auto wal = storage_manager.GetWAL(); wal->WriteCheckpoint(meta_block); wal->Flush(); } @@ -199,7 +204,7 @@ void SingleFileCheckpointWriter::CreateCheckpoint() { // finally write the updated header DatabaseHeader header; header.meta_block = meta_block.block_pointer; - header.block_size = Storage::BLOCK_ALLOC_SIZE; + header.block_alloc_size = block_manager.GetBlockAllocSize(); header.vector_size = STANDARD_VECTOR_SIZE; block_manager.WriteHeader(header); @@ -212,15 +217,15 @@ void SingleFileCheckpointWriter::CreateCheckpoint() { // truncate the WAL if (!wal_is_empty) { - wal->Truncate(0); + storage_manager.ResetWAL(); } } -void CheckpointReader::LoadCheckpoint(ClientContext &context, MetadataReader &reader) { +void CheckpointReader::LoadCheckpoint(CatalogTransaction transaction, MetadataReader &reader) { BinaryDeserializer deserializer(reader); deserializer.Begin(); deserializer.ReadList(100, "catalog_entries", [&](Deserializer::List &list, idx_t i) { - return list.ReadObject([&](Deserializer &obj) { ReadEntry(context, obj); }); + return list.ReadObject([&](Deserializer &obj) { ReadEntry(transaction, obj); }); }); deserializer.End(); } @@ -229,7 +234,7 @@ MetadataManager &SingleFileCheckpointReader::GetMetadataManager() { return storage.block_manager->GetMetadataManager(); } -void SingleFileCheckpointReader::LoadFromStorage(optional_ptr context) { +void SingleFileCheckpointReader::LoadFromStorage() { auto &block_manager = *storage.block_manager; auto &metadata_manager = GetMetadataManager(); MetaBlockPointer meta_block(block_manager.GetMetaBlock(), 0); @@ -238,20 +243,16 @@ void SingleFileCheckpointReader::LoadFromStorage(optional_ptr con return; } - if (context) { - // create the MetadataReader to read from the storage - MetadataReader reader(metadata_manager, meta_block); - // reader.SetContext(*con.context); - LoadCheckpoint(*context, reader); - } else { - Connection con(storage.GetDatabase()); - con.BeginTransaction(); - // create the MetadataReader to read from the storage - MetadataReader reader(metadata_manager, meta_block); - // reader.SetContext(*con.context); - LoadCheckpoint(*con.context, reader); - con.Commit(); + if (block_manager.IsRemote()) { + auto metadata_blocks = metadata_manager.GetBlocks(); + auto &buffer_manager = BufferManager::GetBufferManager(storage.GetDatabase()); + buffer_manager.Prefetch(metadata_blocks); } + + // create the MetadataReader to read from the storage + MetadataReader reader(metadata_manager, meta_block); + auto transaction = CatalogTransaction::GetSystemTransaction(catalog.GetDatabase()); + LoadCheckpoint(transaction, reader); } void CheckpointWriter::WriteEntry(CatalogEntry &entry, Serializer &serializer) { @@ -311,40 +312,40 @@ void CheckpointWriter::WriteSchema(SchemaCatalogEntry &schema, Serializer &seria serializer.WriteProperty(100, "schema", &schema); } -void CheckpointReader::ReadEntry(ClientContext &context, Deserializer &deserializer) { +void CheckpointReader::ReadEntry(CatalogTransaction transaction, Deserializer &deserializer) { auto type = deserializer.ReadProperty(99, "type"); switch (type) { case CatalogType::SCHEMA_ENTRY: { - ReadSchema(context, deserializer); + ReadSchema(transaction, deserializer); break; } case CatalogType::TYPE_ENTRY: { - ReadType(context, deserializer); + ReadType(transaction, deserializer); break; } case CatalogType::SEQUENCE_ENTRY: { - ReadSequence(context, deserializer); + ReadSequence(transaction, deserializer); break; } case CatalogType::TABLE_ENTRY: { - ReadTable(context, deserializer); + ReadTable(transaction, deserializer); break; } case CatalogType::VIEW_ENTRY: { - ReadView(context, deserializer); + ReadView(transaction, deserializer); break; } case CatalogType::MACRO_ENTRY: { - ReadMacro(context, deserializer); + ReadMacro(transaction, deserializer); break; } case CatalogType::TABLE_MACRO_ENTRY: { - ReadTableMacro(context, deserializer); + ReadTableMacro(transaction, deserializer); break; } case CatalogType::INDEX_ENTRY: { - ReadIndex(context, deserializer); + ReadIndex(transaction, deserializer); break; } default: @@ -352,14 +353,14 @@ void CheckpointReader::ReadEntry(ClientContext &context, Deserializer &deseriali } } -void CheckpointReader::ReadSchema(ClientContext &context, Deserializer &deserializer) { +void CheckpointReader::ReadSchema(CatalogTransaction transaction, Deserializer &deserializer) { // Read the schema and create it in the catalog auto info = deserializer.ReadProperty>(100, "schema"); auto &schema_info = info->Cast(); // we set create conflict to IGNORE_ON_CONFLICT, so that we can ignore a failure when recreating the main schema schema_info.on_conflict = OnCreateConflict::IGNORE_ON_CONFLICT; - catalog.CreateSchema(context, schema_info); + catalog.CreateSchema(transaction, schema_info); } //===--------------------------------------------------------------------===// @@ -369,10 +370,10 @@ void CheckpointWriter::WriteView(ViewCatalogEntry &view, Serializer &serializer) serializer.WriteProperty(100, "view", &view); } -void CheckpointReader::ReadView(ClientContext &context, Deserializer &deserializer) { +void CheckpointReader::ReadView(CatalogTransaction transaction, Deserializer &deserializer) { auto info = deserializer.ReadProperty>(100, "view"); auto &view_info = info->Cast(); - catalog.CreateView(context, view_info); + catalog.CreateView(transaction, view_info); } //===--------------------------------------------------------------------===// @@ -382,10 +383,10 @@ void CheckpointWriter::WriteSequence(SequenceCatalogEntry &seq, Serializer &seri serializer.WriteProperty(100, "sequence", &seq); } -void CheckpointReader::ReadSequence(ClientContext &context, Deserializer &deserializer) { +void CheckpointReader::ReadSequence(CatalogTransaction transaction, Deserializer &deserializer) { auto info = deserializer.ReadProperty>(100, "sequence"); auto &sequence_info = info->Cast(); - catalog.CreateSequence(context, sequence_info); + catalog.CreateSequence(transaction, sequence_info); } //===--------------------------------------------------------------------===// @@ -399,7 +400,7 @@ void CheckpointWriter::WriteIndex(IndexCatalogEntry &index_catalog_entry, Serial serializer.WriteProperty(100, "index", &index_catalog_entry); } -void CheckpointReader::ReadIndex(ClientContext &context, Deserializer &deserializer) { +void CheckpointReader::ReadIndex(CatalogTransaction transaction, Deserializer &deserializer) { // we need to keep the tag "index", even though it is slightly misleading. auto create_info = deserializer.ReadProperty>(100, "index"); @@ -413,8 +414,8 @@ void CheckpointReader::ReadIndex(ClientContext &context, Deserializer &deseriali // create the index in the catalog // look for the table in the catalog - auto &table = - catalog.GetEntry(context, CatalogType::TABLE_ENTRY, create_info->schema, info.table).Cast(); + auto &schema = catalog.GetSchema(transaction, create_info->schema); + auto &table = schema.GetEntry(transaction, CatalogType::TABLE_ENTRY, info.table)->Cast(); // we also need to make sure the index type is loaded // backwards compatability: @@ -424,43 +425,17 @@ void CheckpointReader::ReadIndex(ClientContext &context, Deserializer &deseriali } // now we can look for the index in the catalog and assign the table info - auto &index = catalog.CreateIndex(context, info)->Cast(); - index.info = make_shared_ptr(table.GetStorage().info, info.index_name); + auto &index = catalog.CreateIndex(transaction, info)->Cast(); + auto data_table_info = table.GetStorage().GetDataTableInfo(); + index.info = make_shared_ptr(data_table_info, info.index_name); // insert the parsed expressions into the index so that we can (de)serialize them during consecutive checkpoints for (auto &parsed_expr : info.parsed_expressions) { index.parsed_expressions.push_back(parsed_expr->Copy()); } - - // obtain the parsed expressions of the ART from the index metadata - vector> parsed_expressions; - for (auto &parsed_expr : info.parsed_expressions) { - parsed_expressions.push_back(parsed_expr->Copy()); - } - D_ASSERT(!parsed_expressions.empty()); - - // add the table to the bind context to bind the parsed expressions - auto binder = Binder::CreateBinder(context); - vector column_types; - vector column_names; - for (auto &col : table.GetColumns().Logical()) { - column_types.push_back(col.Type()); - column_names.push_back(col.Name()); - } - - // create a binder to bind the parsed expressions - vector column_ids; - binder->bind_context.AddBaseTable(0, info.table, column_names, column_types, column_ids, &table); - IndexBinder idx_binder(*binder, context); - - // bind the parsed expressions to create unbound expressions - vector> unbound_expressions; - unbound_expressions.reserve(parsed_expressions.size()); - for (auto &expr : parsed_expressions) { - unbound_expressions.push_back(idx_binder.Bind(expr)); - } - + D_ASSERT(!info.parsed_expressions.empty()); auto &data_table = table.GetStorage(); + IndexStorageInfo index_storage_info; if (root_block_pointer.IsValid()) { // this code path is necessary to read older duckdb files @@ -469,7 +444,7 @@ void CheckpointReader::ReadIndex(ClientContext &context, Deserializer &deseriali } else { // get the matching index storage info - for (auto const &elem : data_table.info->index_storage_infos) { + for (auto const &elem : data_table.GetDataTableInfo()->GetIndexStorageInfo()) { if (elem.name == info.index_name) { index_storage_info = elem; break; @@ -479,19 +454,11 @@ void CheckpointReader::ReadIndex(ClientContext &context, Deserializer &deseriali D_ASSERT(index_storage_info.IsValid() && !index_storage_info.name.empty()); - // This is executed before any extensions can be loaded, which is why we must treat any index type that is not - // built-in (ART) as unknown - if (info.index_type == ART::TYPE_NAME) { - data_table.info->indexes.AddIndex(make_uniq(info.index_name, info.constraint_type, info.column_ids, - TableIOManager::Get(data_table), unbound_expressions, - data_table.db, nullptr, index_storage_info)); - } else { - auto unknown_index = make_uniq(info.index_name, info.index_type, info.constraint_type, - info.column_ids, TableIOManager::Get(data_table), - unbound_expressions, data_table.db, info, index_storage_info); + // Create an unbound index and add it to the table + auto unbound_index = make_uniq(std::move(create_info), index_storage_info, + TableIOManager::Get(data_table), data_table.db); - data_table.info->indexes.AddIndex(std::move(unknown_index)); - } + data_table.GetDataTableInfo()->GetIndexes().AddIndex(std::move(unbound_index)); } //===--------------------------------------------------------------------===// @@ -501,10 +468,10 @@ void CheckpointWriter::WriteType(TypeCatalogEntry &type, Serializer &serializer) serializer.WriteProperty(100, "type", &type); } -void CheckpointReader::ReadType(ClientContext &context, Deserializer &deserializer) { +void CheckpointReader::ReadType(CatalogTransaction transaction, Deserializer &deserializer) { auto info = deserializer.ReadProperty>(100, "type"); auto &type_info = info->Cast(); - catalog.CreateType(context, type_info); + catalog.CreateType(transaction, type_info); } //===--------------------------------------------------------------------===// @@ -514,50 +481,53 @@ void CheckpointWriter::WriteMacro(ScalarMacroCatalogEntry ¯o, Serializer &se serializer.WriteProperty(100, "macro", ¯o); } -void CheckpointReader::ReadMacro(ClientContext &context, Deserializer &deserializer) { +void CheckpointReader::ReadMacro(CatalogTransaction transaction, Deserializer &deserializer) { auto info = deserializer.ReadProperty>(100, "macro"); auto ¯o_info = info->Cast(); - catalog.CreateFunction(context, macro_info); + catalog.CreateFunction(transaction, macro_info); } void CheckpointWriter::WriteTableMacro(TableMacroCatalogEntry ¯o, Serializer &serializer) { serializer.WriteProperty(100, "table_macro", ¯o); } -void CheckpointReader::ReadTableMacro(ClientContext &context, Deserializer &deserializer) { +void CheckpointReader::ReadTableMacro(CatalogTransaction transaction, Deserializer &deserializer) { auto info = deserializer.ReadProperty>(100, "table_macro"); auto ¯o_info = info->Cast(); - catalog.CreateFunction(context, macro_info); + catalog.CreateFunction(transaction, macro_info); } //===--------------------------------------------------------------------===// // Table Metadata //===--------------------------------------------------------------------===// -void CheckpointWriter::WriteTable(TableCatalogEntry &table, Serializer &serializer) { +void SingleFileCheckpointWriter::WriteTable(TableCatalogEntry &table, Serializer &serializer) { // Write the table metadata serializer.WriteProperty(100, "table", &table); // Write the table data + auto table_lock = table.GetStorage().GetCheckpointLock(); if (auto writer = GetTableDataWriter(table)) { writer->WriteTableData(serializer); } + // flush any partial blocks BEFORE releasing the table lock + // flushing partial blocks updates where data lives and is not thread-safe + partial_block_manager.FlushPartialBlocks(); } -void CheckpointReader::ReadTable(ClientContext &context, Deserializer &deserializer) { +void CheckpointReader::ReadTable(CatalogTransaction transaction, Deserializer &deserializer) { // deserialize the table meta data auto info = deserializer.ReadProperty>(100, "table"); - auto binder = Binder::CreateBinder(context); - auto &schema = catalog.GetSchema(context, info->schema); - auto bound_info = binder->BindCreateTableInfo(std::move(info), schema); + auto &schema = catalog.GetSchema(transaction, info->schema); + auto bound_info = Binder::BindCreateTableCheckpoint(std::move(info), schema); // now read the actual table data and place it into the CreateTableInfo - ReadTableData(context, deserializer, *bound_info); + ReadTableData(transaction, deserializer, *bound_info); // finally create the table in the catalog - catalog.CreateTable(context, *bound_info); + catalog.CreateTable(transaction, *bound_info); } -void CheckpointReader::ReadTableData(ClientContext &context, Deserializer &deserializer, +void CheckpointReader::ReadTableData(CatalogTransaction transaction, Deserializer &deserializer, BoundCreateTableInfo &bound_info) { // written in "SingleFileTableDataWriter::FinalizeTable" diff --git a/src/storage/compression/alp/alp.cpp b/src/storage/compression/alp/alp.cpp index 62d9caa2299..c4acaa795ce 100644 --- a/src/storage/compression/alp/alp.cpp +++ b/src/storage/compression/alp/alp.cpp @@ -1,14 +1,9 @@ -#include "duckdb/storage/compression/alp/alp_compress.hpp" -#include "duckdb/storage/compression/alp/alp_scan.hpp" -#include "duckdb/storage/compression/alp/alp_fetch.hpp" -#include "duckdb/storage/compression/alp/alp_analyze.hpp" - #include "duckdb/function/compression/compression.hpp" #include "duckdb/function/compression_function.hpp" -#include "duckdb/main/config.hpp" - -#include -#include +#include "duckdb/storage/compression/alp/alp_analyze.hpp" +#include "duckdb/storage/compression/alp/alp_compress.hpp" +#include "duckdb/storage/compression/alp/alp_fetch.hpp" +#include "duckdb/storage/compression/alp/alp_scan.hpp" namespace duckdb { @@ -44,8 +39,8 @@ CompressionFunction AlpCompressionFun::GetFunction(PhysicalType type) { } } -bool AlpCompressionFun::TypeIsSupported(PhysicalType type) { - switch (type) { +bool AlpCompressionFun::TypeIsSupported(const CompressionInfo &info) { + switch (info.GetPhysicalType()) { case PhysicalType::FLOAT: case PhysicalType::DOUBLE: return true; diff --git a/src/storage/compression/alprd.cpp b/src/storage/compression/alprd.cpp index 1ca62367356..01658d55bf9 100644 --- a/src/storage/compression/alprd.cpp +++ b/src/storage/compression/alprd.cpp @@ -1,15 +1,11 @@ +#include "duckdb/common/limits.hpp" +#include "duckdb/function/compression/compression.hpp" +#include "duckdb/function/compression_function.hpp" #include "duckdb/storage/compression/alprd/alprd_analyze.hpp" #include "duckdb/storage/compression/alprd/alprd_compress.hpp" #include "duckdb/storage/compression/alprd/alprd_fetch.hpp" #include "duckdb/storage/compression/alprd/alprd_scan.hpp" -#include "duckdb/common/limits.hpp" -#include "duckdb/function/compression/compression.hpp" -#include "duckdb/function/compression_function.hpp" - -#include -#include - namespace duckdb { template @@ -44,8 +40,8 @@ CompressionFunction AlpRDCompressionFun::GetFunction(PhysicalType type) { } } -bool AlpRDCompressionFun::TypeIsSupported(PhysicalType type) { - switch (type) { +bool AlpRDCompressionFun::TypeIsSupported(const CompressionInfo &info) { + switch (info.GetPhysicalType()) { case PhysicalType::FLOAT: case PhysicalType::DOUBLE: return true; diff --git a/src/storage/compression/bitpacking.cpp b/src/storage/compression/bitpacking.cpp index cb10b9c9281..c06ac36a934 100644 --- a/src/storage/compression/bitpacking.cpp +++ b/src/storage/compression/bitpacking.cpp @@ -3,9 +3,9 @@ #include "duckdb/common/limits.hpp" #include "duckdb/common/numeric_utils.hpp" #include "duckdb/common/operator/add.hpp" +#include "duckdb/common/operator/cast_operators.hpp" #include "duckdb/common/operator/multiply.hpp" #include "duckdb/common/operator/subtract.hpp" -#include "duckdb/common/operator/cast_operators.hpp" #include "duckdb/function/compression/compression.hpp" #include "duckdb/function/compression_function.hpp" #include "duckdb/main/config.hpp" @@ -317,6 +317,7 @@ struct BitpackingState { //===--------------------------------------------------------------------===// template struct BitpackingAnalyzeState : public AnalyzeState { + explicit BitpackingAnalyzeState(const CompressionInfo &info) : AnalyzeState(info) {}; BitpackingState state; }; @@ -324,7 +325,8 @@ template unique_ptr BitpackingInitAnalyze(ColumnData &col_data, PhysicalType type) { auto &config = DBConfig::GetConfig(col_data.GetDatabase()); - auto state = make_uniq>(); + CompressionInfo info(Storage::BLOCK_SIZE, type); + auto state = make_uniq>(info); state->state.mode = config.options.force_bitpacking_mode; return std::move(state); @@ -362,8 +364,8 @@ idx_t BitpackingFinalAnalyze(AnalyzeState &state) { template ::type> struct BitpackingCompressState : public CompressionState { public: - explicit BitpackingCompressState(ColumnDataCheckpointer &checkpointer) - : checkpointer(checkpointer), + explicit BitpackingCompressState(ColumnDataCheckpointer &checkpointer, const CompressionInfo &info) + : CompressionState(info), checkpointer(checkpointer), function(checkpointer.GetCompressionFunction(CompressionType::COMPRESSION_BITPACKING)) { CreateEmptySegment(checkpointer.GetRowGroup().start); @@ -473,23 +475,25 @@ struct BitpackingCompressState : public CompressionState { bool CanStore(idx_t data_bytes, idx_t meta_bytes) { auto required_data_bytes = AlignValue(UnsafeNumericCast((data_ptr + data_bytes) - data_ptr)); - auto required_meta_bytes = Storage::BLOCK_SIZE - UnsafeNumericCast(metadata_ptr - data_ptr) + meta_bytes; + auto required_meta_bytes = info.GetBlockSize() - UnsafeNumericCast(metadata_ptr - data_ptr) + meta_bytes; return required_data_bytes + required_meta_bytes <= - Storage::BLOCK_SIZE - BitpackingPrimitives::BITPACKING_HEADER_SIZE; + info.GetBlockSize() - BitpackingPrimitives::BITPACKING_HEADER_SIZE; } void CreateEmptySegment(idx_t row_start) { auto &db = checkpointer.GetDatabase(); auto &type = checkpointer.GetType(); + auto compressed_segment = ColumnSegment::CreateTransientSegment(db, type, row_start); compressed_segment->function = function; current_segment = std::move(compressed_segment); + auto &buffer_manager = BufferManager::GetBufferManager(db); handle = buffer_manager.Pin(current_segment->block); data_ptr = handle.Ptr() + BitpackingPrimitives::BITPACKING_HEADER_SIZE; - metadata_ptr = handle.Ptr() + Storage::BLOCK_SIZE; + metadata_ptr = handle.Ptr() + info.GetBlockSize(); } void Append(UnifiedVectorFormat &vdata, idx_t count) { @@ -518,7 +522,7 @@ struct BitpackingCompressState : public CompressionState { idx_t unaligned_offset = NumericCast(data_ptr - base_ptr); idx_t metadata_offset = AlignValue(unaligned_offset); - idx_t metadata_size = NumericCast(base_ptr + Storage::BLOCK_SIZE - metadata_ptr); + idx_t metadata_size = NumericCast(base_ptr + info.GetBlockSize() - metadata_ptr); idx_t total_segment_size = metadata_offset + metadata_size; // Asserting things are still sane here @@ -549,7 +553,7 @@ struct BitpackingCompressState : public CompressionState { template unique_ptr BitpackingInitCompression(ColumnDataCheckpointer &checkpointer, unique_ptr state) { - return make_uniq>(checkpointer); + return make_uniq>(checkpointer, state->info); } template @@ -772,7 +776,7 @@ unique_ptr BitpackingInitScan(ColumnSegment &segment) { //===--------------------------------------------------------------------===// // Scan base data //===--------------------------------------------------------------------===// -template ::type> +template ::type, class T_U = typename MakeUnsigned::type> void BitpackingScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t scan_count, Vector &result, idx_t result_offset) { auto &scan_state = state.scan_state->Cast>(); @@ -811,11 +815,10 @@ void BitpackingScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t T *target_ptr = result_data + result_offset + scanned; for (idx_t i = 0; i < to_scan; i++) { - T multiplier; - auto success = TryCast::Operation(scan_state.current_group_offset + i, multiplier); - D_ASSERT(success); - (void)success; - target_ptr[i] = (multiplier * scan_state.current_constant) + scan_state.current_frame_of_reference; + idx_t multiplier = scan_state.current_group_offset + i; + // intended static casts to unsigned and back for defined wrapping of integers + target_ptr[i] = static_cast((static_cast(scan_state.current_constant) * multiplier) + + static_cast(scan_state.current_frame_of_reference)); } scanned += to_scan; @@ -977,17 +980,17 @@ CompressionFunction BitpackingFun::GetFunction(PhysicalType type) { } } -bool BitpackingFun::TypeIsSupported(PhysicalType type) { +bool BitpackingFun::TypeIsSupported(const CompressionInfo &info) { // we calculate on BITPACKING_METADATA_GROUP_SIZE tuples, but they can exceed the block size, // in which case we have to disable bitpacking for that data type // we are conservative here by multiplying by 2 - auto type_size = GetTypeIdSize(type); - if (type_size * BITPACKING_METADATA_GROUP_SIZE * 2 > Storage::BLOCK_SIZE) { + auto type_size = GetTypeIdSize(info.GetPhysicalType()); + if (type_size * BITPACKING_METADATA_GROUP_SIZE * 2 > info.GetBlockSize()) { return false; } - switch (type) { + switch (info.GetPhysicalType()) { case PhysicalType::BOOL: case PhysicalType::INT8: case PhysicalType::INT16: diff --git a/src/storage/compression/chimp/chimp.cpp b/src/storage/compression/chimp/chimp.cpp index f697c9e7448..e6c89781932 100644 --- a/src/storage/compression/chimp/chimp.cpp +++ b/src/storage/compression/chimp/chimp.cpp @@ -1,11 +1,9 @@ -#include "duckdb/storage/compression/chimp/chimp.hpp" -#include "duckdb/storage/compression/chimp/chimp_compress.hpp" -#include "duckdb/storage/compression/chimp/chimp_scan.hpp" -#include "duckdb/storage/compression/chimp/chimp_fetch.hpp" -#include "duckdb/storage/compression/chimp/chimp_analyze.hpp" - #include "duckdb/function/compression/compression.hpp" #include "duckdb/function/compression_function.hpp" +#include "duckdb/storage/compression/chimp/chimp_analyze.hpp" +#include "duckdb/storage/compression/chimp/chimp_compress.hpp" +#include "duckdb/storage/compression/chimp/chimp_fetch.hpp" +#include "duckdb/storage/compression/chimp/chimp_scan.hpp" namespace duckdb { @@ -28,8 +26,8 @@ CompressionFunction ChimpCompressionFun::GetFunction(PhysicalType type) { } } -bool ChimpCompressionFun::TypeIsSupported(PhysicalType type) { - switch (type) { +bool ChimpCompressionFun::TypeIsSupported(const CompressionInfo &info) { + switch (info.GetPhysicalType()) { case PhysicalType::FLOAT: case PhysicalType::DOUBLE: return true; diff --git a/src/storage/compression/dictionary_compression.cpp b/src/storage/compression/dictionary_compression.cpp index 58529e72aa1..de889f758d7 100644 --- a/src/storage/compression/dictionary_compression.cpp +++ b/src/storage/compression/dictionary_compression.cpp @@ -11,8 +11,11 @@ namespace duckdb { -// Abstract class for keeping compression state either for compression or size analysis +//! Abstract class managing the compression state for size analysis or compression. class DictionaryCompressionState : public CompressionState { +public: + explicit DictionaryCompressionState(const CompressionInfo &info) : CompressionState(info) {}; + public: bool UpdateState(Vector &scan_vector, idx_t count) { UnifiedVectorFormat vdata; @@ -22,7 +25,7 @@ class DictionaryCompressionState : public CompressionState { for (idx_t i = 0; i < count; i++) { auto idx = vdata.sel->get_index(i); - size_t string_size = 0; + idx_t string_size = 0; bool new_string = false; auto row_is_valid = vdata.validity.RowIsValid(idx); @@ -72,7 +75,7 @@ class DictionaryCompressionState : public CompressionState { // Add a null value to the compression state virtual void AddNull() = 0; // Needs to be called before adding a value. Will return false if a flush is required first. - virtual bool CalculateSpaceRequirements(bool new_string, size_t string_size) = 0; + virtual bool CalculateSpaceRequirements(bool new_string, idx_t string_size) = 0; // Flush the segment to disk if compressing or reset the counters if analyzing virtual void Flush(bool final = false) = 0; }; @@ -87,8 +90,8 @@ typedef struct { struct DictionaryCompressionStorage { static constexpr float MINIMUM_COMPRESSION_RATIO = 1.2F; + //! Dictionary header size at the beginning of the string segment (offset + length) static constexpr uint16_t DICTIONARY_HEADER_SIZE = sizeof(dictionary_compression_header_t); - static constexpr size_t COMPACTION_FLUSH_LIMIT = (size_t)Storage::BLOCK_SIZE / 5 * 4; static unique_ptr StringInitAnalyze(ColumnData &col_data, PhysicalType type); static bool StringAnalyze(AnalyzeState &state_p, Vector &input, idx_t count); @@ -108,7 +111,7 @@ struct DictionaryCompressionStorage { idx_t result_idx); static bool HasEnoughSpace(idx_t current_count, idx_t index_count, idx_t dict_size, - bitpacking_width_t packing_width); + bitpacking_width_t packing_width, const idx_t block_size); static idx_t RequiredSpace(idx_t current_count, idx_t index_count, idx_t dict_size, bitpacking_width_t packing_width); @@ -129,8 +132,8 @@ struct DictionaryCompressionStorage { // scanning the whole dictionary at once and then scanning the selection buffer for each emitted vector. Secondly, it // allows for efficient bitpacking compression as the selection values should remain relatively small. struct DictionaryCompressionCompressState : public DictionaryCompressionState { - explicit DictionaryCompressionCompressState(ColumnDataCheckpointer &checkpointer_p) - : checkpointer(checkpointer_p), + DictionaryCompressionCompressState(ColumnDataCheckpointer &checkpointer_p, const CompressionInfo &info) + : DictionaryCompressionState(info), checkpointer(checkpointer_p), function(checkpointer.GetCompressionFunction(CompressionType::COMPRESSION_DICTIONARY)), heap(BufferAllocator::Get(checkpointer.GetDatabase())) { CreateEmptySegment(checkpointer.GetRowGroup().start); @@ -161,21 +164,23 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { void CreateEmptySegment(idx_t row_start) { auto &db = checkpointer.GetDatabase(); auto &type = checkpointer.GetType(); + auto compressed_segment = ColumnSegment::CreateTransientSegment(db, type, row_start); current_segment = std::move(compressed_segment); - current_segment->function = function; - // Reset the buffers and string map + // Reset the buffers and the string map. current_string_map.clear(); index_buffer.clear(); - index_buffer.push_back(0); // Reserve index 0 for null strings + + // Reserve index 0 for null strings. + index_buffer.push_back(0); selection_buffer.clear(); current_width = 0; next_width = 0; - // Reset the pointers into the current segment + // Reset the pointers into the current segment. auto &buffer_manager = BufferManager::GetBufferManager(checkpointer.GetDatabase()); current_handle = buffer_manager.Pin(current_segment->block); current_dictionary = DictionaryCompressionStorage::GetDictionary(*current_segment, current_handle); @@ -186,8 +191,9 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { current_dictionary.Verify(); D_ASSERT(current_segment->count == selection_buffer.size()); D_ASSERT(DictionaryCompressionStorage::HasEnoughSpace(current_segment->count.load(), index_buffer.size(), - current_dictionary.size, current_width)); - D_ASSERT(current_dictionary.end == Storage::BLOCK_SIZE); + current_dictionary.size, current_width, + info.GetBlockSize())); + D_ASSERT(current_dictionary.end == info.GetBlockSize()); D_ASSERT(index_buffer.size() == current_string_map.size() + 1); // +1 is for null value } @@ -209,7 +215,7 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { auto dict_pos = current_end_ptr - current_dictionary.size; memcpy(dict_pos, str.GetData(), str.GetSize()); current_dictionary.Verify(); - D_ASSERT(current_dictionary.end == Storage::BLOCK_SIZE); + D_ASSERT(current_dictionary.end == info.GetBlockSize()); // Update buffers and map index_buffer.push_back(current_dictionary.size); @@ -235,16 +241,16 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { current_segment->count++; } - bool CalculateSpaceRequirements(bool new_string, size_t string_size) override { - if (new_string) { - next_width = BitpackingPrimitives::MinimumBitWidth(index_buffer.size() - 1 + new_string); - return DictionaryCompressionStorage::HasEnoughSpace(current_segment->count.load() + 1, - index_buffer.size() + 1, - current_dictionary.size + string_size, next_width); - } else { + bool CalculateSpaceRequirements(bool new_string, idx_t string_size) override { + if (!new_string) { return DictionaryCompressionStorage::HasEnoughSpace(current_segment->count.load() + 1, index_buffer.size(), - current_dictionary.size, current_width); + current_dictionary.size, current_width, + info.GetBlockSize()); } + next_width = BitpackingPrimitives::MinimumBitWidth(index_buffer.size() - 1 + new_string); + return DictionaryCompressionStorage::HasEnoughSpace(current_segment->count.load() + 1, index_buffer.size() + 1, + current_dictionary.size + string_size, next_width, + info.GetBlockSize()); } void Flush(bool final = false) override { @@ -262,7 +268,7 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { idx_t Finalize() { auto &buffer_manager = BufferManager::GetBufferManager(checkpointer.GetDatabase()); auto handle = buffer_manager.Pin(current_segment->block); - D_ASSERT(current_dictionary.end == Storage::BLOCK_SIZE); + D_ASSERT(current_dictionary.end == info.GetBlockSize()); // calculate sizes auto compressed_selection_buffer_size = @@ -291,24 +297,27 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { Store((uint32_t)current_width, data_ptr_cast(&header_ptr->bitpacking_width)); D_ASSERT(current_width == BitpackingPrimitives::MinimumBitWidth(index_buffer.size() - 1)); - D_ASSERT(DictionaryCompressionStorage::HasEnoughSpace(current_segment->count, index_buffer.size(), - current_dictionary.size, current_width)); + D_ASSERT(DictionaryCompressionStorage::HasEnoughSpace( + current_segment->count, index_buffer.size(), current_dictionary.size, current_width, info.GetBlockSize())); D_ASSERT((uint64_t)*max_element(std::begin(selection_buffer), std::end(selection_buffer)) == index_buffer.size() - 1); - if (total_size >= DictionaryCompressionStorage::COMPACTION_FLUSH_LIMIT) { - // the block is full enough, don't bother moving around the dictionary - return Storage::BLOCK_SIZE; + // Early-out, if the block is sufficiently full. + if (total_size >= info.GetCompactionFlushLimit()) { + return info.GetBlockSize(); } - // the block has space left: figure out how much space we can save - auto move_amount = Storage::BLOCK_SIZE - total_size; - // move the dictionary so it lines up exactly with the offsets + + // Sufficient space: calculate how much space we can save. + auto move_amount = info.GetBlockSize() - total_size; + + // Move the dictionary to align it with the offsets. auto new_dictionary_offset = index_buffer_offset + index_buffer_size; memmove(base_ptr + new_dictionary_offset, base_ptr + current_dictionary.end - current_dictionary.size, current_dictionary.size); current_dictionary.end -= move_amount; D_ASSERT(current_dictionary.end == total_size); - // write the new dictionary (with the updated "end") + + // Write the new dictionary with the updated "end". DictionaryCompressionStorage::SetDictionary(*current_segment, handle, current_dictionary); return total_size; } @@ -318,15 +327,15 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { // Analyze //===--------------------------------------------------------------------===// struct DictionaryAnalyzeState : public DictionaryCompressionState { - DictionaryAnalyzeState() - : segment_count(0), current_tuple_count(0), current_unique_count(0), current_dict_size(0), current_width(0), - next_width(0) { + explicit DictionaryAnalyzeState(const CompressionInfo &info) + : DictionaryCompressionState(info), segment_count(0), current_tuple_count(0), current_unique_count(0), + current_dict_size(0), current_width(0), next_width(0) { } - size_t segment_count; + idx_t segment_count; idx_t current_tuple_count; idx_t current_unique_count; - size_t current_dict_size; + idx_t current_dict_size; StringHeap heap; string_set_t current_set; bitpacking_width_t current_width; @@ -356,16 +365,15 @@ struct DictionaryAnalyzeState : public DictionaryCompressionState { current_tuple_count++; } - bool CalculateSpaceRequirements(bool new_string, size_t string_size) override { - if (new_string) { - next_width = - BitpackingPrimitives::MinimumBitWidth(current_unique_count + 2); // 1 for null, one for new string - return DictionaryCompressionStorage::HasEnoughSpace(current_tuple_count + 1, current_unique_count + 1, - current_dict_size + string_size, next_width); - } else { + bool CalculateSpaceRequirements(bool new_string, idx_t string_size) override { + if (!new_string) { return DictionaryCompressionStorage::HasEnoughSpace(current_tuple_count + 1, current_unique_count, - current_dict_size, current_width); + current_dict_size, current_width, info.GetBlockSize()); } + next_width = BitpackingPrimitives::MinimumBitWidth(current_unique_count + 2); // 1 for null, one for new string + return DictionaryCompressionStorage::HasEnoughSpace(current_tuple_count + 1, current_unique_count + 1, + current_dict_size + string_size, next_width, + info.GetBlockSize()); } void Flush(bool final = false) override { @@ -379,14 +387,16 @@ struct DictionaryAnalyzeState : public DictionaryCompressionState { }; struct DictionaryCompressionAnalyzeState : public AnalyzeState { - DictionaryCompressionAnalyzeState() : analyze_state(make_uniq()) { + explicit DictionaryCompressionAnalyzeState(const CompressionInfo &info) + : AnalyzeState(info), analyze_state(make_uniq(info)) { } unique_ptr analyze_state; }; unique_ptr DictionaryCompressionStorage::StringInitAnalyze(ColumnData &col_data, PhysicalType type) { - return make_uniq(); + CompressionInfo info(Storage::BLOCK_SIZE, type); + return make_uniq(info); } bool DictionaryCompressionStorage::StringAnalyze(AnalyzeState &state_p, Vector &input, idx_t count) { @@ -402,7 +412,8 @@ idx_t DictionaryCompressionStorage::StringFinalAnalyze(AnalyzeState &state_p) { auto req_space = RequiredSpace(state.current_tuple_count, state.current_unique_count, state.current_dict_size, width); - return NumericCast(MINIMUM_COMPRESSION_RATIO * (state.segment_count * Storage::BLOCK_SIZE + req_space)); + const auto total_space = state.segment_count * state.info.GetBlockSize() + req_space; + return NumericCast(MINIMUM_COMPRESSION_RATIO * float(total_space)); } //===--------------------------------------------------------------------===// @@ -410,7 +421,7 @@ idx_t DictionaryCompressionStorage::StringFinalAnalyze(AnalyzeState &state_p) { //===--------------------------------------------------------------------===// unique_ptr DictionaryCompressionStorage::InitCompression(ColumnDataCheckpointer &checkpointer, unique_ptr state) { - return make_uniq(checkpointer); + return make_uniq(checkpointer, state->info); } void DictionaryCompressionStorage::Compress(CompressionState &state_p, Vector &scan_vector, idx_t count) { @@ -580,8 +591,8 @@ void DictionaryCompressionStorage::StringFetchRow(ColumnSegment &segment, Column // Helper Functions //===--------------------------------------------------------------------===// bool DictionaryCompressionStorage::HasEnoughSpace(idx_t current_count, idx_t index_count, idx_t dict_size, - bitpacking_width_t packing_width) { - return RequiredSpace(current_count, index_count, dict_size, packing_width) <= Storage::BLOCK_SIZE; + bitpacking_width_t packing_width, const idx_t block_size) { + return RequiredSpace(current_count, index_count, dict_size, packing_width) <= block_size; } idx_t DictionaryCompressionStorage::RequiredSpace(idx_t current_count, idx_t index_count, idx_t dict_size, @@ -613,11 +624,12 @@ void DictionaryCompressionStorage::SetDictionary(ColumnSegment &segment, BufferH string_t DictionaryCompressionStorage::FetchStringFromDict(ColumnSegment &segment, StringDictionaryContainer dict, data_ptr_t baseptr, int32_t dict_offset, uint16_t string_len) { - D_ASSERT(dict_offset >= 0 && dict_offset <= int32_t(Storage::BLOCK_SIZE)); + D_ASSERT(dict_offset >= 0 && dict_offset <= NumericCast(Storage::BLOCK_SIZE)); if (dict_offset == 0) { return string_t(nullptr, 0); } + // normal string: read string from this block auto dict_end = baseptr + dict.end; auto dict_pos = dict_end - dict_offset; @@ -647,7 +659,7 @@ CompressionFunction DictionaryCompressionFun::GetFunction(PhysicalType data_type DictionaryCompressionStorage::StringFetchRow, UncompressedFunctions::EmptySkip); } -bool DictionaryCompressionFun::TypeIsSupported(PhysicalType type) { - return type == PhysicalType::VARCHAR; +bool DictionaryCompressionFun::TypeIsSupported(const CompressionInfo &info) { + return info.GetPhysicalType() == PhysicalType::VARCHAR; } } // namespace duckdb diff --git a/src/storage/compression/fixed_size_uncompressed.cpp b/src/storage/compression/fixed_size_uncompressed.cpp index bbccd3f0e16..f7ce99e640d 100644 --- a/src/storage/compression/fixed_size_uncompressed.cpp +++ b/src/storage/compression/fixed_size_uncompressed.cpp @@ -1,11 +1,9 @@ #include "duckdb/common/types/null_value.hpp" #include "duckdb/common/types/vector.hpp" #include "duckdb/function/compression_function.hpp" -#include "duckdb/main/config.hpp" #include "duckdb/storage/buffer_manager.hpp" #include "duckdb/storage/checkpoint/write_overflow_strings_to_disk.hpp" #include "duckdb/storage/segment/uncompressed.hpp" - #include "duckdb/storage/table/append_state.hpp" #include "duckdb/storage/table/column_data_checkpointer.hpp" #include "duckdb/storage/table/column_segment.hpp" @@ -17,14 +15,15 @@ namespace duckdb { // Analyze //===--------------------------------------------------------------------===// struct FixedSizeAnalyzeState : public AnalyzeState { - FixedSizeAnalyzeState() : count(0) { + explicit FixedSizeAnalyzeState(const CompressionInfo &info) : AnalyzeState(info), count(0) { } idx_t count; }; unique_ptr FixedSizeInitAnalyze(ColumnData &col_data, PhysicalType type) { - return make_uniq(); + CompressionInfo info(Storage::BLOCK_SIZE, type); + return make_uniq(info); } bool FixedSizeAnalyze(AnalyzeState &state_p, Vector &input, idx_t count) { @@ -43,7 +42,7 @@ idx_t FixedSizeFinalAnalyze(AnalyzeState &state_p) { // Compress //===--------------------------------------------------------------------===// struct UncompressedCompressState : public CompressionState { - explicit UncompressedCompressState(ColumnDataCheckpointer &checkpointer); + UncompressedCompressState(ColumnDataCheckpointer &checkpointer, const CompressionInfo &info); ColumnDataCheckpointer &checkpointer; unique_ptr current_segment; @@ -54,14 +53,15 @@ struct UncompressedCompressState : public CompressionState { void Finalize(idx_t segment_size); }; -UncompressedCompressState::UncompressedCompressState(ColumnDataCheckpointer &checkpointer) - : checkpointer(checkpointer) { +UncompressedCompressState::UncompressedCompressState(ColumnDataCheckpointer &checkpointer, const CompressionInfo &info) + : CompressionState(info), checkpointer(checkpointer) { UncompressedCompressState::CreateEmptySegment(checkpointer.GetRowGroup().start); } void UncompressedCompressState::CreateEmptySegment(idx_t row_start) { auto &db = checkpointer.GetDatabase(); auto &type = checkpointer.GetType(); + auto compressed_segment = ColumnSegment::CreateTransientSegment(db, type, row_start); if (type.InternalType() == PhysicalType::VARCHAR) { auto &state = compressed_segment->GetSegmentState()->Cast(); @@ -88,7 +88,7 @@ void UncompressedCompressState::Finalize(idx_t segment_size) { unique_ptr UncompressedFunctions::InitCompression(ColumnDataCheckpointer &checkpointer, unique_ptr state) { - return make_uniq(checkpointer); + return make_uniq(checkpointer, state->info); } void UncompressedFunctions::Compress(CompressionState &state_p, Vector &data, idx_t count) { @@ -260,7 +260,7 @@ CompressionFunction FixedSizeGetFunction(PhysicalType data_type) { UncompressedFunctions::Compress, UncompressedFunctions::FinalizeCompress, FixedSizeInitScan, FixedSizeScan, FixedSizeScanPartial, FixedSizeFetchRow, UncompressedFunctions::EmptySkip, nullptr, FixedSizeInitAppend, - FixedSizeAppend, FixedSizeFinalizeAppend, nullptr); + FixedSizeAppend, FixedSizeFinalizeAppend); } CompressionFunction FixedSizeUncompressed::GetFunction(PhysicalType data_type) { diff --git a/src/storage/compression/fsst.cpp b/src/storage/compression/fsst.cpp index fcccab4af95..34f4995530e 100644 --- a/src/storage/compression/fsst.cpp +++ b/src/storage/compression/fsst.cpp @@ -1,14 +1,16 @@ +#include "duckdb/common/fsst.hpp" + #include "duckdb/common/bitpacking.hpp" +#include "duckdb/common/constants.hpp" +#include "duckdb/common/random_engine.hpp" +#include "duckdb/function/compression/compression.hpp" +#include "duckdb/main/config.hpp" #include "duckdb/storage/checkpoint/write_overflow_strings_to_disk.hpp" #include "duckdb/storage/string_uncompressed.hpp" -#include "duckdb/function/compression/compression.hpp" #include "duckdb/storage/table/column_data_checkpointer.hpp" -#include "duckdb/main/config.hpp" -#include "duckdb/common/constants.hpp" -#include "duckdb/common/random_engine.hpp" -#include "duckdb/common/fsst.hpp" -#include "miniz_wrapper.hpp" + #include "fsst.h" +#include "miniz_wrapper.hpp" namespace duckdb { @@ -33,7 +35,6 @@ typedef struct BPDeltaDecodeOffsets { } bp_delta_offsets_t; struct FSSTStorage { - static constexpr size_t COMPACTION_FLUSH_LIMIT = (size_t)Storage::BLOCK_SIZE / 5 * 4; static constexpr double MINIMUM_COMPRESSION_RATIO = 1.2; static constexpr double ANALYSIS_SAMPLE_SIZE = 0.25; @@ -67,7 +68,8 @@ struct FSSTStorage { // Analyze //===--------------------------------------------------------------------===// struct FSSTAnalyzeState : public AnalyzeState { - FSSTAnalyzeState() : count(0), fsst_string_total_size(0), empty_strings(0) { + explicit FSSTAnalyzeState(const CompressionInfo &info) + : AnalyzeState(info), count(0), fsst_string_total_size(0), empty_strings(0) { } ~FSSTAnalyzeState() override { @@ -90,7 +92,8 @@ struct FSSTAnalyzeState : public AnalyzeState { }; unique_ptr FSSTStorage::StringInitAnalyze(ColumnData &col_data, PhysicalType type) { - return make_uniq(); + CompressionInfo info(Storage::BLOCK_SIZE, type); + return make_uniq(info); } bool FSSTStorage::StringAnalyze(AnalyzeState &state_p, Vector &input, idx_t count) { @@ -185,10 +188,9 @@ idx_t FSSTStorage::StringFinalAnalyze(AnalyzeState &state_p) { auto bitpacked_offsets_size = BitpackingPrimitives::GetRequiredSize(string_count + state.empty_strings, minimum_width); - auto estimated_base_size = (bitpacked_offsets_size + compressed_dict_size) * (1 / ANALYSIS_SAMPLE_SIZE); - auto num_blocks = estimated_base_size / (Storage::BLOCK_SIZE - sizeof(duckdb_fsst_decoder_t)); + auto estimated_base_size = double(bitpacked_offsets_size + compressed_dict_size) * (1 / ANALYSIS_SAMPLE_SIZE); + auto num_blocks = estimated_base_size / double(state.info.GetBlockSize() - sizeof(duckdb_fsst_decoder_t)); auto symtable_size = num_blocks * sizeof(duckdb_fsst_decoder_t); - auto estimated_size = estimated_base_size + symtable_size; return NumericCast(estimated_size * MINIMUM_COMPRESSION_RATIO); @@ -200,8 +202,9 @@ idx_t FSSTStorage::StringFinalAnalyze(AnalyzeState &state_p) { class FSSTCompressionState : public CompressionState { public: - explicit FSSTCompressionState(ColumnDataCheckpointer &checkpointer) - : checkpointer(checkpointer), function(checkpointer.GetCompressionFunction(CompressionType::COMPRESSION_FSST)) { + FSSTCompressionState(ColumnDataCheckpointer &checkpointer, const CompressionInfo &info) + : CompressionState(info), checkpointer(checkpointer), + function(checkpointer.GetCompressionFunction(CompressionType::COMPRESSION_FSST)) { CreateEmptySegment(checkpointer.GetRowGroup().start); } @@ -227,6 +230,7 @@ class FSSTCompressionState : public CompressionState { void CreateEmptySegment(idx_t row_start) { auto &db = checkpointer.GetDatabase(); auto &type = checkpointer.GetType(); + auto compressed_segment = ColumnSegment::CreateTransientSegment(db, type, row_start); current_segment = std::move(compressed_segment); current_segment->function = function; @@ -297,7 +301,7 @@ class FSSTCompressionState : public CompressionState { bool HasEnoughSpace(size_t string_len) { auto required_size = GetRequiredSize(string_len); - if (required_size <= Storage::BLOCK_SIZE) { + if (required_size <= info.GetBlockSize()) { last_fitting_size = required_size; return true; } @@ -319,7 +323,7 @@ class FSSTCompressionState : public CompressionState { idx_t Finalize() { auto &buffer_manager = BufferManager::GetBufferManager(current_segment->db); auto handle = buffer_manager.Pin(current_segment->block); - D_ASSERT(current_dictionary.end == Storage::BLOCK_SIZE); + D_ASSERT(current_dictionary.end == info.GetBlockSize()); // calculate sizes auto compressed_index_buffer_size = @@ -353,12 +357,13 @@ class FSSTCompressionState : public CompressionState { data_ptr_cast(&header_ptr->fsst_symbol_table_offset)); Store((uint32_t)current_width, data_ptr_cast(&header_ptr->bitpacking_width)); - if (total_size >= FSSTStorage::COMPACTION_FLUSH_LIMIT) { + if (total_size >= info.GetCompactionFlushLimit()) { // the block is full enough, don't bother moving around the dictionary - return Storage::BLOCK_SIZE; + return info.GetBlockSize(); } + // the block has space left: figure out how much space we can save - auto move_amount = Storage::BLOCK_SIZE - total_size; + auto move_amount = info.GetBlockSize() - total_size; // move the dictionary so it lines up exactly with the offsets auto new_dictionary_offset = symbol_table_offset + fsst_serialized_symbol_table_size; memmove(base_ptr + new_dictionary_offset, base_ptr + current_dictionary.end - current_dictionary.size, @@ -395,7 +400,7 @@ class FSSTCompressionState : public CompressionState { unique_ptr FSSTStorage::InitCompression(ColumnDataCheckpointer &checkpointer, unique_ptr analyze_state_p) { auto &analyze_state = analyze_state_p->Cast(); - auto compression_state = make_uniq(checkpointer); + auto compression_state = make_uniq(checkpointer, analyze_state.info); if (analyze_state.fsst_encoder == nullptr) { throw InternalException("No encoder found during FSST compression"); @@ -693,8 +698,8 @@ CompressionFunction FSSTFun::GetFunction(PhysicalType data_type) { FSSTStorage::StringScanPartial, FSSTStorage::StringFetchRow, UncompressedFunctions::EmptySkip); } -bool FSSTFun::TypeIsSupported(PhysicalType type) { - return type == PhysicalType::VARCHAR; +bool FSSTFun::TypeIsSupported(const CompressionInfo &info) { + return info.GetPhysicalType() == PhysicalType::VARCHAR; } //===--------------------------------------------------------------------===// diff --git a/src/storage/compression/numeric_constant.cpp b/src/storage/compression/numeric_constant.cpp index 3741f71a384..189f57b5469 100644 --- a/src/storage/compression/numeric_constant.cpp +++ b/src/storage/compression/numeric_constant.cpp @@ -1,9 +1,8 @@ -#include "duckdb/function/compression/compression.hpp" #include "duckdb/common/types/vector.hpp" - -#include "duckdb/storage/table/column_segment.hpp" +#include "duckdb/function/compression/compression.hpp" #include "duckdb/function/compression_function.hpp" #include "duckdb/storage/segment/uncompressed.hpp" +#include "duckdb/storage/table/column_segment.hpp" #include "duckdb/storage/table/scan_state.hpp" namespace duckdb { @@ -139,8 +138,8 @@ CompressionFunction ConstantFun::GetFunction(PhysicalType data_type) { } } -bool ConstantFun::TypeIsSupported(PhysicalType type) { - switch (type) { +bool ConstantFun::TypeIsSupported(const CompressionInfo &info) { + switch (info.GetPhysicalType()) { case PhysicalType::BIT: case PhysicalType::BOOL: case PhysicalType::INT8: diff --git a/src/storage/compression/patas.cpp b/src/storage/compression/patas.cpp index 8df7f5c5c7e..95e5835794e 100644 --- a/src/storage/compression/patas.cpp +++ b/src/storage/compression/patas.cpp @@ -1,21 +1,10 @@ -#include "duckdb/storage/compression/patas/patas.hpp" -#include "duckdb/storage/compression/patas/patas_compress.hpp" -#include "duckdb/storage/compression/patas/patas_scan.hpp" -#include "duckdb/storage/compression/patas/patas_fetch.hpp" -#include "duckdb/storage/compression/patas/patas_analyze.hpp" - #include "duckdb/common/limits.hpp" -#include "duckdb/common/types/null_value.hpp" #include "duckdb/function/compression/compression.hpp" #include "duckdb/function/compression_function.hpp" -#include "duckdb/main/config.hpp" -#include "duckdb/storage/buffer_manager.hpp" - -#include "duckdb/storage/table/column_data_checkpointer.hpp" -#include "duckdb/storage/table/column_segment.hpp" -#include "duckdb/common/operator/subtract.hpp" - -#include +#include "duckdb/storage/compression/patas/patas_analyze.hpp" +#include "duckdb/storage/compression/patas/patas_compress.hpp" +#include "duckdb/storage/compression/patas/patas_fetch.hpp" +#include "duckdb/storage/compression/patas/patas_scan.hpp" namespace duckdb { @@ -51,8 +40,8 @@ CompressionFunction PatasCompressionFun::GetFunction(PhysicalType type) { } } -bool PatasCompressionFun::TypeIsSupported(PhysicalType type) { - switch (type) { +bool PatasCompressionFun::TypeIsSupported(const CompressionInfo &info) { + switch (info.GetPhysicalType()) { case PhysicalType::FLOAT: case PhysicalType::DOUBLE: return true; diff --git a/src/storage/compression/rle.cpp b/src/storage/compression/rle.cpp index e518b14602f..df0843892ab 100644 --- a/src/storage/compression/rle.cpp +++ b/src/storage/compression/rle.cpp @@ -1,12 +1,11 @@ +#include "duckdb/common/types/null_value.hpp" #include "duckdb/function/compression/compression.hpp" - -#include "duckdb/storage/table/column_segment.hpp" #include "duckdb/function/compression_function.hpp" -#include "duckdb/main/config.hpp" -#include "duckdb/storage/table/column_data_checkpointer.hpp" #include "duckdb/storage/buffer_manager.hpp" -#include "duckdb/common/types/null_value.hpp" +#include "duckdb/storage/table/column_data_checkpointer.hpp" +#include "duckdb/storage/table/column_segment.hpp" #include "duckdb/storage/table/scan_state.hpp" + #include namespace duckdb { @@ -81,7 +80,7 @@ struct RLEState { template struct RLEAnalyzeState : public AnalyzeState { - RLEAnalyzeState() { + explicit RLEAnalyzeState(const CompressionInfo &info) : AnalyzeState(info) { } RLEState state; @@ -89,7 +88,8 @@ struct RLEAnalyzeState : public AnalyzeState { template unique_ptr RLEInitAnalyze(ColumnData &col_data, PhysicalType type) { - return make_uniq>(); + CompressionInfo info(Storage::BLOCK_SIZE, type); + return make_uniq>(info); } template @@ -129,14 +129,13 @@ struct RLECompressState : public CompressionState { } }; - static idx_t MaxRLECount() { + idx_t MaxRLECount() { auto entry_size = sizeof(T) + sizeof(rle_count_t); - auto entry_count = (Storage::BLOCK_SIZE - RLEConstants::RLE_HEADER_SIZE) / entry_size; - return entry_count; + return (info.GetBlockSize() - RLEConstants::RLE_HEADER_SIZE) / entry_size; } - explicit RLECompressState(ColumnDataCheckpointer &checkpointer_p) - : checkpointer(checkpointer_p), + RLECompressState(ColumnDataCheckpointer &checkpointer_p, const CompressionInfo &info) + : CompressionState(info), checkpointer(checkpointer_p), function(checkpointer.GetCompressionFunction(CompressionType::COMPRESSION_RLE)) { CreateEmptySegment(checkpointer.GetRowGroup().start); @@ -147,9 +146,11 @@ struct RLECompressState : public CompressionState { void CreateEmptySegment(idx_t row_start) { auto &db = checkpointer.GetDatabase(); auto &type = checkpointer.GetType(); + auto column_segment = ColumnSegment::CreateTransientSegment(db, type, row_start); column_segment->function = function; current_segment = std::move(column_segment); + auto &buffer_manager = BufferManager::GetBufferManager(db); handle = buffer_manager.Pin(current_segment->block); } @@ -222,7 +223,7 @@ struct RLECompressState : public CompressionState { template unique_ptr RLEInitCompression(ColumnDataCheckpointer &checkpointer, unique_ptr state) { - return make_uniq>(checkpointer); + return make_uniq>(checkpointer, state->info); } template @@ -431,8 +432,8 @@ CompressionFunction RLEFun::GetFunction(PhysicalType type) { } } -bool RLEFun::TypeIsSupported(PhysicalType type) { - switch (type) { +bool RLEFun::TypeIsSupported(const CompressionInfo &info) { + switch (info.GetPhysicalType()) { case PhysicalType::BOOL: case PhysicalType::INT8: case PhysicalType::INT16: diff --git a/src/storage/compression/string_uncompressed.cpp b/src/storage/compression/string_uncompressed.cpp index dea2ef6fc9f..9c238ad14f6 100644 --- a/src/storage/compression/string_uncompressed.cpp +++ b/src/storage/compression/string_uncompressed.cpp @@ -1,9 +1,9 @@ #include "duckdb/storage/string_uncompressed.hpp" #include "duckdb/common/pair.hpp" -#include "duckdb/storage/checkpoint/write_overflow_strings_to_disk.hpp" -#include "duckdb/common/serializer/serializer.hpp" #include "duckdb/common/serializer/deserializer.hpp" +#include "duckdb/common/serializer/serializer.hpp" +#include "duckdb/storage/checkpoint/write_overflow_strings_to_disk.hpp" #include "duckdb/storage/table/column_data.hpp" namespace duckdb { @@ -22,7 +22,8 @@ UncompressedStringSegmentState::~UncompressedStringSegmentState() { // Analyze //===--------------------------------------------------------------------===// struct StringAnalyzeState : public AnalyzeState { - StringAnalyzeState() : count(0), total_string_size(0), overflow_strings(0) { + explicit StringAnalyzeState(const CompressionInfo &info) + : AnalyzeState(info), count(0), total_string_size(0), overflow_strings(0) { } idx_t count; @@ -31,7 +32,8 @@ struct StringAnalyzeState : public AnalyzeState { }; unique_ptr UncompressedStringStorage::StringInitAnalyze(ColumnData &col_data, PhysicalType type) { - return make_uniq(); + CompressionInfo info(Storage::BLOCK_SIZE, type); + return make_uniq(info); } bool UncompressedStringStorage::StringAnalyze(AnalyzeState &state_p, Vector &input, idx_t count) { @@ -62,6 +64,19 @@ idx_t UncompressedStringStorage::StringFinalAnalyze(AnalyzeState &state_p) { //===--------------------------------------------------------------------===// // Scan //===--------------------------------------------------------------------===// +void UncompressedStringInitPrefetch(ColumnSegment &segment, PrefetchState &prefetch_state) { + prefetch_state.AddBlock(segment.block); + auto segment_state = segment.GetSegmentState(); + if (segment_state) { + auto &state = segment_state->Cast(); + auto &block_manager = segment.GetBlockManager(); + for (auto &block_id : state.on_disk_blocks) { + auto block_handle = state.GetHandle(block_manager, block_id); + prefetch_state.AddBlock(block_handle); + } + } +} + unique_ptr UncompressedStringStorage::StringInitScan(ColumnSegment &segment) { auto result = make_uniq(); auto &buffer_manager = BufferManager::GetBufferManager(segment.db); @@ -175,7 +190,7 @@ UncompressedStringStorage::StringInitSegment(ColumnSegment &segment, block_id_t return std::move(result); } -idx_t UncompressedStringStorage::FinalizeAppend(ColumnSegment &segment, SegmentStatistics &stats) { +idx_t UncompressedStringStorage::FinalizeAppend(ColumnSegment &segment, SegmentStatistics &) { auto &buffer_manager = BufferManager::GetBufferManager(segment.db); auto handle = buffer_manager.Pin(segment.block); auto dict = GetDictionary(segment, handle); @@ -183,10 +198,13 @@ idx_t UncompressedStringStorage::FinalizeAppend(ColumnSegment &segment, SegmentS // compute the total size required to store this segment auto offset_size = DICTIONARY_HEADER_SIZE + segment.count * sizeof(int32_t); auto total_size = offset_size + dict.size; - if (total_size >= COMPACTION_FLUSH_LIMIT) { + + CompressionInfo info(Storage::BLOCK_SIZE, segment.type.InternalType()); + if (total_size >= info.GetCompactionFlushLimit()) { // the block is full enough, don't bother moving around the dictionary return segment.SegmentSize(); } + // the block has space left: figure out how much space we can save auto move_amount = segment.SegmentSize() - total_size; // move the dictionary so it lines up exactly with the offsets @@ -240,7 +258,7 @@ CompressionFunction StringUncompressed::GetFunction(PhysicalType data_type) { UncompressedStringStorage::StringInitAppend, UncompressedStringStorage::StringAppend, UncompressedStringStorage::FinalizeAppend, nullptr, UncompressedStringStorage::SerializeState, UncompressedStringStorage::DeserializeState, - UncompressedStringStorage::CleanupState); + UncompressedStringStorage::CleanupState, UncompressedStringInitPrefetch); } //===--------------------------------------------------------------------===// @@ -322,11 +340,12 @@ void UncompressedStringStorage::WriteStringMemory(ColumnSegment &segment, string string_t UncompressedStringStorage::ReadOverflowString(ColumnSegment &segment, Vector &result, block_id_t block, int32_t offset) { D_ASSERT(block != INVALID_BLOCK); - D_ASSERT(offset < int32_t(Storage::BLOCK_SIZE)); + D_ASSERT(offset < NumericCast(Storage::BLOCK_SIZE)); auto &block_manager = segment.GetBlockManager(); auto &buffer_manager = block_manager.buffer_manager; auto &state = segment.GetSegmentState()->Cast(); + if (block < MAXIMUM_BLOCK) { // read the overflow string from disk // pin the initial handle and read the length @@ -365,16 +384,16 @@ string_t UncompressedStringStorage::ReadOverflowString(ColumnSegment &segment, V auto final_buffer = target_handle.Ptr(); StringVector::AddHandle(result, std::move(target_handle)); return ReadString(final_buffer, 0, length); - } else { - // read the overflow string from memory - // first pin the handle, if it is not pinned yet - auto entry = state.overflow_blocks.find(block); - D_ASSERT(entry != state.overflow_blocks.end()); - auto handle = buffer_manager.Pin(entry->second.get().block); - auto final_buffer = handle.Ptr(); - StringVector::AddHandle(result, std::move(handle)); - return ReadStringWithLength(final_buffer, offset); } + + // read the overflow string from memory + // first pin the handle, if it is not pinned yet + auto entry = state.overflow_blocks.find(block); + D_ASSERT(entry != state.overflow_blocks.end()); + auto handle = buffer_manager.Pin(entry->second.get().block); + auto final_buffer = handle.Ptr(); + StringVector::AddHandle(result, std::move(handle)); + return ReadStringWithLength(final_buffer, offset); } string_t UncompressedStringStorage::ReadString(data_ptr_t target, int32_t offset, uint32_t string_length) { @@ -402,44 +421,44 @@ void UncompressedStringStorage::ReadStringMarker(data_ptr_t target, block_id_t & memcpy(&offset, target, sizeof(int32_t)); } -string_location_t UncompressedStringStorage::FetchStringLocation(StringDictionaryContainer dict, data_ptr_t baseptr, - int32_t dict_offset) { - D_ASSERT(dict_offset >= -1 * int32_t(Storage::BLOCK_SIZE) && dict_offset <= int32_t(Storage::BLOCK_SIZE)); - if (dict_offset < 0) { - string_location_t result; - ReadStringMarker(baseptr + dict.end - idx_t(-1 * dict_offset), result.block_id, result.offset); - return result; - } else { +string_location_t UncompressedStringStorage::FetchStringLocation(StringDictionaryContainer dict, data_ptr_t base_ptr, + int32_t dict_offset, const idx_t block_size) { + D_ASSERT(dict_offset + NumericCast(block_size) >= 0 && dict_offset <= NumericCast(block_size)); + if (dict_offset >= 0) { return string_location_t(INVALID_BLOCK, dict_offset); } + + string_location_t result; + ReadStringMarker(base_ptr + dict.end - NumericCast(-1 * dict_offset), result.block_id, result.offset); + return result; } string_t UncompressedStringStorage::FetchStringFromDict(ColumnSegment &segment, StringDictionaryContainer dict, - Vector &result, data_ptr_t baseptr, int32_t dict_offset, + Vector &result, data_ptr_t base_ptr, int32_t dict_offset, uint32_t string_length) { - // fetch base data - D_ASSERT(dict_offset <= int32_t(Storage::BLOCK_SIZE)); - string_location_t location = FetchStringLocation(dict, baseptr, dict_offset); - return FetchString(segment, dict, result, baseptr, location, string_length); + // Fetch the base data. + D_ASSERT(dict_offset <= NumericCast(Storage::BLOCK_SIZE)); + string_location_t location = FetchStringLocation(dict, base_ptr, dict_offset, Storage::BLOCK_SIZE); + return FetchString(segment, dict, result, base_ptr, location, string_length); } string_t UncompressedStringStorage::FetchString(ColumnSegment &segment, StringDictionaryContainer dict, Vector &result, - data_ptr_t baseptr, string_location_t location, + data_ptr_t base_ptr, string_location_t location, uint32_t string_length) { if (location.block_id != INVALID_BLOCK) { // big string marker: read from separate block return ReadOverflowString(segment, result, location.block_id, location.offset); - } else { - if (location.offset == 0) { - return string_t(nullptr, 0); - } - // normal string: read string from this block - auto dict_end = baseptr + dict.end; - auto dict_pos = dict_end - location.offset; - - auto str_ptr = char_ptr_cast(dict_pos); - return string_t(str_ptr, string_length); } + if (location.offset == 0) { + return string_t(nullptr, 0); + } + + // normal string: read string from this block + auto dict_end = base_ptr + dict.end; + auto dict_pos = dict_end - location.offset; + + auto str_ptr = char_ptr_cast(dict_pos); + return string_t(str_ptr, string_length); } } // namespace duckdb diff --git a/src/storage/compression/uncompressed.cpp b/src/storage/compression/uncompressed.cpp index b68c4fce07c..92ff424e57d 100644 --- a/src/storage/compression/uncompressed.cpp +++ b/src/storage/compression/uncompressed.cpp @@ -1,5 +1,5 @@ -#include "duckdb/function/compression/compression.hpp" #include "duckdb/storage/segment/uncompressed.hpp" +#include "duckdb/function/compression/compression.hpp" namespace duckdb { @@ -30,7 +30,7 @@ CompressionFunction UncompressedFun::GetFunction(PhysicalType type) { } } -bool UncompressedFun::TypeIsSupported(PhysicalType type) { +bool UncompressedFun::TypeIsSupported(const CompressionInfo &) { return true; } diff --git a/src/storage/compression/validity_uncompressed.cpp b/src/storage/compression/validity_uncompressed.cpp index f2f01533b89..2c1afd347cb 100644 --- a/src/storage/compression/validity_uncompressed.cpp +++ b/src/storage/compression/validity_uncompressed.cpp @@ -1,11 +1,11 @@ -#include "duckdb/storage/segment/uncompressed.hpp" -#include "duckdb/storage/buffer_manager.hpp" +#include "duckdb/common/types/null_value.hpp" #include "duckdb/common/types/vector.hpp" +#include "duckdb/function/compression_function.hpp" +#include "duckdb/storage/buffer_manager.hpp" +#include "duckdb/storage/segment/uncompressed.hpp" #include "duckdb/storage/table/append_state.hpp" - -#include "duckdb/common/types/null_value.hpp" +#include "duckdb/storage/table/column_data.hpp" #include "duckdb/storage/table/column_segment.hpp" -#include "duckdb/function/compression_function.hpp" #include "duckdb/storage/table/scan_state.hpp" namespace duckdb { @@ -177,14 +177,15 @@ const validity_t ValidityUncompressed::UPPER_MASKS[] = {0x0, // Analyze //===--------------------------------------------------------------------===// struct ValidityAnalyzeState : public AnalyzeState { - ValidityAnalyzeState() : count(0) { + explicit ValidityAnalyzeState(const CompressionInfo &info) : AnalyzeState(info), count(0) { } idx_t count; }; unique_ptr ValidityInitAnalyze(ColumnData &col_data, PhysicalType type) { - return make_uniq(); + CompressionInfo info(Storage::BLOCK_SIZE, type); + return make_uniq(info); } bool ValidityAnalyze(AnalyzeState &state_p, Vector &input, idx_t count) { diff --git a/src/storage/data_pointer.cpp b/src/storage/data_pointer.cpp index 92c57245af0..32bee27e7de 100644 --- a/src/storage/data_pointer.cpp +++ b/src/storage/data_pointer.cpp @@ -9,8 +9,9 @@ namespace duckdb { unique_ptr ColumnSegmentState::Deserialize(Deserializer &deserializer) { auto compression_type = deserializer.Get(); auto &db = deserializer.Get(); - auto &type = deserializer.Get(); - auto compression_function = DBConfig::GetConfig(db).GetCompressionFunction(compression_type, type.InternalType()); + auto &info = deserializer.Get(); + + auto compression_function = DBConfig::GetConfig(db).GetCompressionFunction(compression_type, info); if (!compression_function || !compression_function->deserialize_state) { throw SerializationException("Deserializing a ColumnSegmentState but could not find deserialize method"); } diff --git a/src/storage/data_table.cpp b/src/storage/data_table.cpp index 588b7c38139..a65245c50a2 100644 --- a/src/storage/data_table.cpp +++ b/src/storage/data_table.cpp @@ -32,12 +32,11 @@ namespace duckdb { DataTableInfo::DataTableInfo(AttachedDatabase &db, shared_ptr table_io_manager_p, string schema, string table) - : db(db), table_io_manager(std::move(table_io_manager_p)), cardinality(0), schema(std::move(schema)), - table(std::move(table)) { + : db(db), table_io_manager(std::move(table_io_manager_p)), schema(std::move(schema)), table(std::move(table)) { } -void DataTableInfo::InitializeIndexes(ClientContext &context, bool throw_on_failure) { - indexes.InitializeIndexes(context, *this, throw_on_failure); +void DataTableInfo::InitializeIndexes(ClientContext &context, const char *index_type) { + indexes.InitializeIndexes(context, *this, index_type); } bool DataTableInfo::IsTemporary() const { @@ -47,8 +46,8 @@ bool DataTableInfo::IsTemporary() const { DataTable::DataTable(AttachedDatabase &db, shared_ptr table_io_manager_p, const string &schema, const string &table, vector column_definitions_p, unique_ptr data) - : info(make_shared_ptr(db, std::move(table_io_manager_p), schema, table)), - column_definitions(std::move(column_definitions_p)), db(db), is_root(true) { + : db(db), info(make_shared_ptr(db, std::move(table_io_manager_p), schema, table)), + column_definitions(std::move(column_definitions_p)), is_root(true) { // initialize the table with the existing data from disk, if any auto types = GetTypes(); this->row_groups = @@ -63,28 +62,34 @@ DataTable::DataTable(AttachedDatabase &db, shared_ptr table_io_m } DataTable::DataTable(ClientContext &context, DataTable &parent, ColumnDefinition &new_column, Expression &default_value) - : info(parent.info), db(parent.db), is_root(true) { + : db(parent.db), info(parent.info), is_root(true) { // add the column definitions from this DataTable for (auto &column_def : parent.column_definitions) { column_definitions.emplace_back(column_def.Copy()); } column_definitions.emplace_back(new_column.Copy()); + + auto &local_storage = LocalStorage::Get(context, db); + + ExpressionExecutor default_executor(context); + default_executor.AddExpression(default_value); + // prevent any new tuples from being added to the parent lock_guard parent_lock(parent.append_lock); - this->row_groups = parent.row_groups->AddColumn(context, new_column, default_value); + this->row_groups = parent.row_groups->AddColumn(context, new_column, default_executor); // also add this column to client local storage - auto &local_storage = LocalStorage::Get(context, db); - local_storage.AddColumn(parent, *this, new_column, default_value); + local_storage.AddColumn(parent, *this, new_column, default_executor); // this table replaces the previous table, hence the parent is no longer the root DataTable parent.is_root = false; } DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t removed_column) - : info(parent.info), db(parent.db), is_root(true) { + : db(parent.db), info(parent.info), is_root(true) { // prevent any new tuples from being added to the parent + auto &local_storage = LocalStorage::Get(context, db); lock_guard parent_lock(parent.append_lock); for (auto &column_def : parent.column_definitions) { @@ -95,7 +100,7 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t removed_co // first check if there are any indexes that exist that point to the removed column info->indexes.Scan([&](Index &index) { - for (auto &column_id : index.column_ids) { + for (auto &column_id : index.GetColumnIds()) { if (column_id == removed_column) { throw CatalogException("Cannot drop this column: an index depends on it!"); } else if (column_id > removed_column) { @@ -123,7 +128,6 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t removed_co this->row_groups = parent.row_groups->RemoveColumn(removed_column); // scan the original table, and fill the new column with the transformed value - auto &local_storage = LocalStorage::Get(context, db); local_storage.DropColumn(parent, *this, removed_column); // this table replaces the previous table, hence the parent is no longer the root DataTable @@ -132,8 +136,9 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t removed_co // Alter column to add new constraint DataTable::DataTable(ClientContext &context, DataTable &parent, unique_ptr constraint) - : info(parent.info), db(parent.db), row_groups(parent.row_groups), is_root(true) { + : db(parent.db), info(parent.info), row_groups(parent.row_groups), is_root(true) { + auto &local_storage = LocalStorage::Get(context, db); lock_guard parent_lock(parent.append_lock); for (auto &column_def : parent.column_definitions) { column_definitions.emplace_back(column_def.Copy()); @@ -142,10 +147,9 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, unique_ptrInitializeIndexes(context); // Verify the new constraint against current persistent/local data - VerifyNewConstraint(context, parent, constraint.get()); + VerifyNewConstraint(local_storage, parent, *constraint); // Get the local data ownership from old dt - auto &local_storage = LocalStorage::Get(context, db); local_storage.MoveStorage(parent, *this); // this table replaces the previous table, hence the parent is no longer the root DataTable parent.is_root = false; @@ -153,7 +157,8 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, unique_ptr &bound_columns, Expression &cast_expr) - : info(parent.info), db(parent.db), is_root(true) { + : db(parent.db), info(parent.info), is_root(true) { + auto &local_storage = LocalStorage::Get(context, db); // prevent any tuples from being added to the parent lock_guard lock(append_lock); for (auto &column_def : parent.column_definitions) { @@ -164,7 +169,7 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t changed_id // first check if there are any indexes that exist that point to the changed column info->indexes.Scan([&](Index &index) { - for (auto &column_id : index.column_ids) { + for (auto &column_id : index.GetColumnIds()) { if (column_id == changed_idx) { throw CatalogException("Cannot change the type of this column: an index depends on it!"); } @@ -180,7 +185,6 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t changed_id this->row_groups = parent.row_groups->AlterType(context, changed_idx, target_type, bound_columns, cast_expr); // scan the original table, and fill the new column with the transformed value - auto &local_storage = LocalStorage::Get(context, db); local_storage.ChangeType(parent, *this, changed_idx, target_type, bound_columns, cast_expr); // this table replaces the previous table, hence the parent is no longer the root DataTable @@ -195,8 +199,25 @@ vector DataTable::GetTypes() { return types; } +bool DataTable::IsTemporary() const { + return info->IsTemporary(); +} + +AttachedDatabase &DataTable::GetAttached() { + D_ASSERT(RefersToSameObject(db, info->db)); + return db; +} + +const vector &DataTable::Columns() const { + return column_definitions; +} + +TableIOManager &DataTable::GetTableIOManager() { + return *info->table_io_manager; +} + TableIOManager &TableIOManager::Get(DataTable &table) { - return *table.info->table_io_manager; + return table.GetTableIOManager(); } //===--------------------------------------------------------------------===// @@ -204,19 +225,21 @@ TableIOManager &TableIOManager::Get(DataTable &table) { //===--------------------------------------------------------------------===// void DataTable::InitializeScan(TableScanState &state, const vector &column_ids, TableFilterSet *table_filters) { + state.checkpoint_lock = info->checkpoint_lock.GetSharedLock(); state.Initialize(column_ids, table_filters); row_groups->InitializeScan(state.table_state, column_ids, table_filters); } void DataTable::InitializeScan(DuckTransaction &transaction, TableScanState &state, const vector &column_ids, TableFilterSet *table_filters) { - InitializeScan(state, column_ids, table_filters); auto &local_storage = LocalStorage::Get(transaction); + InitializeScan(state, column_ids, table_filters); local_storage.InitializeScan(*this, state.local_state, table_filters); } void DataTable::InitializeScanWithOffset(TableScanState &state, const vector &column_ids, idx_t start_row, idx_t end_row) { + state.checkpoint_lock = info->checkpoint_lock.GetSharedLock(); state.Initialize(column_ids); row_groups->InitializeScanWithOffset(state.table_state, column_ids, start_row, end_row); } @@ -231,9 +254,10 @@ idx_t DataTable::MaxThreads(ClientContext &context) { } void DataTable::InitializeParallelScan(ClientContext &context, ParallelTableScanState &state) { + auto &local_storage = LocalStorage::Get(context, db); + state.checkpoint_lock = info->checkpoint_lock.GetSharedLock(); row_groups->InitializeParallelScan(state.scan_state); - auto &local_storage = LocalStorage::Get(context, db); local_storage.InitializeParallelScan(*this, state.local_state); } @@ -266,15 +290,89 @@ bool DataTable::CreateIndexScan(TableScanState &state, DataChunk &result, TableS return state.table_state.ScanCommitted(result, type); } +//===--------------------------------------------------------------------===// +// Index Methods +//===--------------------------------------------------------------------===// +shared_ptr &DataTable::GetDataTableInfo() { + return info; +} + +void DataTable::InitializeIndexes(ClientContext &context) { + info->InitializeIndexes(context); +} + +bool DataTable::HasIndexes() const { + return !info->indexes.Empty(); +} + +void DataTable::AddIndex(unique_ptr index) { + info->indexes.AddIndex(std::move(index)); +} + +bool DataTable::HasForeignKeyIndex(const vector &keys, ForeignKeyType type) { + return info->indexes.FindForeignKeyIndex(keys, type) != nullptr; +} + +void DataTable::SetIndexStorageInfo(vector index_storage_info) { + info->index_storage_infos = std::move(index_storage_info); +} + +void DataTable::VacuumIndexes() { + info->indexes.Scan([&](Index &index) { + if (index.IsBound()) { + index.Cast().Vacuum(); + } + return false; + }); +} + bool DataTable::IndexNameIsUnique(const string &name) { return info->indexes.NameIsUnique(name); } +string DataTableInfo::GetSchemaName() { + return schema; +} + +string DataTableInfo::GetTableName() { + lock_guard l(name_lock); + return table; +} + +void DataTableInfo::SetTableName(string name) { + lock_guard l(name_lock); + table = std::move(name); +} + +string DataTable::GetTableName() const { + return info->GetTableName(); +} + +void DataTable::SetTableName(string new_name) { + info->SetTableName(std::move(new_name)); +} + +TableStorageInfo DataTable::GetStorageInfo() { + TableStorageInfo result; + result.cardinality = GetTotalRows(); + info->indexes.Scan([&](Index &index) { + IndexInfo index_info; + index_info.is_primary = index.IsPrimary(); + index_info.is_unique = index.IsUnique() || index_info.is_primary; + index_info.is_foreign = index.IsForeign(); + index_info.column_set = index.GetColumnIdSet(); + result.index_info.push_back(std::move(index_info)); + return false; + }); + return result; +} + //===--------------------------------------------------------------------===// // Fetch //===--------------------------------------------------------------------===// void DataTable::Fetch(DuckTransaction &transaction, DataChunk &result, const vector &column_ids, const Vector &row_identifiers, idx_t fetch_count, ColumnFetchState &state) { + auto lock = info->checkpoint_lock.GetSharedLock(); row_groups->Fetch(transaction, result, column_ids, row_identifiers, fetch_count, state); } @@ -335,12 +433,12 @@ bool DataTable::IsForeignKeyIndex(const vector &fk_keys, Index &i if (fk_type == ForeignKeyType::FK_TYPE_PRIMARY_KEY_TABLE ? !index.IsUnique() : !index.IsForeign()) { return false; } - if (fk_keys.size() != index.column_ids.size()) { + if (fk_keys.size() != index.GetColumnIds().size()) { return false; } for (auto &fk_key : fk_keys) { bool is_found = false; - for (auto &index_key : index.column_ids) { + for (auto &index_key : index.GetColumnIds()) { if (fk_key.index == index_key) { is_found = true; break; @@ -380,9 +478,11 @@ idx_t LocateErrorIndex(bool is_append, const ManagedSelection &matches) { return failed_index; } -[[noreturn]] static void ThrowForeignKeyConstraintError(idx_t failed_index, bool is_append, Index &index, +[[noreturn]] static void ThrowForeignKeyConstraintError(idx_t failed_index, bool is_append, Index &conflict_index, DataChunk &input) { - + // The index that caused the conflict has to be bound by this point (or we would not have gotten here) + D_ASSERT(conflict_index.IsBound()); + auto &index = conflict_index.Cast(); auto verify_type = is_append ? VerifyExistenceType::APPEND_FK : VerifyExistenceType::DELETE_FK; D_ASSERT(failed_index != DConstants::INVALID_INDEX); auto message = index.GetConstraintViolationMessage(verify_type, failed_index, input); @@ -511,7 +611,8 @@ void DataTable::VerifyForeignKeyConstraint(const BoundForeignKeyConstraint &bfk, } ThrowForeignKeyConstraintError(failed_index, true, *index, dst_chunk); } - if (!is_append && transaction_check) { + if (!is_append) { + D_ASSERT(transaction_check); auto &transaction_matches = transaction_conflicts.Conflicts(); if (error) { auto failed_index = LocateErrorIndex(false, regular_matches); @@ -537,14 +638,13 @@ void DataTable::VerifyDeleteForeignKeyConstraint(const BoundForeignKeyConstraint VerifyForeignKeyConstraint(bfk, context, chunk, VerifyExistenceType::DELETE_FK); } -void DataTable::VerifyNewConstraint(ClientContext &context, DataTable &parent, const BoundConstraint *constraint) { - if (constraint->type != ConstraintType::NOT_NULL) { +void DataTable::VerifyNewConstraint(LocalStorage &local_storage, DataTable &parent, const BoundConstraint &constraint) { + if (constraint.type != ConstraintType::NOT_NULL) { throw NotImplementedException("FIXME: ALTER COLUMN with such constraint is not supported yet"); } - parent.row_groups->VerifyNewConstraint(parent, *constraint); - auto &local_storage = LocalStorage::Get(context, db); - local_storage.VerifyNewConstraint(parent, *constraint); + parent.row_groups->VerifyNewConstraint(parent, constraint); + local_storage.VerifyNewConstraint(parent, constraint); } bool HasUniqueIndexes(TableIndexList &list) { @@ -568,7 +668,8 @@ void DataTable::VerifyUniqueIndexes(TableIndexList &indexes, ClientContext &cont if (!index.IsUnique()) { return false; } - index.VerifyAppend(chunk); + D_ASSERT(index.IsBound()); + index.Cast().VerifyAppend(chunk); return false; }); return; @@ -594,7 +695,8 @@ void DataTable::VerifyUniqueIndexes(TableIndexList &indexes, ClientContext &cont return false; } if (conflict_info.ConflictTargetMatches(index)) { - index.VerifyAppend(chunk, *conflict_manager); + D_ASSERT(index.IsBound()); + index.Cast().VerifyAppend(chunk, *conflict_manager); checked_indexes.insert(&index); } return false; @@ -611,7 +713,8 @@ void DataTable::VerifyUniqueIndexes(TableIndexList &indexes, ClientContext &cont // Already checked this constraint return false; } - index.VerifyAppend(chunk, *conflict_manager); + D_ASSERT(index.IsBound()); + index.Cast().VerifyAppend(chunk, *conflict_manager); return false; }); } @@ -838,9 +941,6 @@ void DataTable::MergeStorage(RowGroupCollection &data, TableIndexList &indexes) } void DataTable::WriteToLog(WriteAheadLog &log, idx_t row_start, idx_t count) { - if (log.skip_writing) { - return; - } log.WriteSetTable(info->schema, info->table); ScanTableSegment(row_start, count, [&](DataChunk &chunk) { log.WriteInsert(chunk); }); } @@ -848,12 +948,9 @@ void DataTable::WriteToLog(WriteAheadLog &log, idx_t row_start, idx_t count) { void DataTable::CommitAppend(transaction_t commit_id, idx_t row_start, idx_t count) { lock_guard lock(append_lock); row_groups->CommitAppend(commit_id, row_start, count); - info->cardinality += count; } void DataTable::RevertAppendInternal(idx_t start_row) { - // adjust the cardinality - info->cardinality = start_row; D_ASSERT(is_root); // revert appends made to row_groups row_groups->RevertAppendInternal(start_row); @@ -873,8 +970,9 @@ void DataTable::RevertAppend(idx_t start_row, idx_t count) { row_data[i] = NumericCast(current_row_base + i); } info->indexes.Scan([&](Index &index) { - if (!index.IsUnknown()) { - index.Delete(chunk, row_identifiers); + // We cant add to unbound indexes anyways, so there is no need to revert them + if (index.IsBound()) { + index.Cast().Delete(chunk, row_identifiers); } return false; }); @@ -885,8 +983,9 @@ void DataTable::RevertAppend(idx_t start_row, idx_t count) { // we need to vacuum the indexes to remove any buffers that are now empty // due to reverting the appends info->indexes.Scan([&](Index &index) { - if (!index.IsUnknown()) { - index.Vacuum(); + // We cant add to unbound indexes anyway, so there is no need to vacuum them + if (index.IsBound()) { + index.Cast().Vacuum(); } return false; }); @@ -907,10 +1006,16 @@ ErrorData DataTable::AppendToIndexes(TableIndexList &indexes, DataChunk &chunk, Vector row_identifiers(LogicalType::ROW_TYPE); VectorOperations::GenerateSequence(row_identifiers, chunk.size(), row_start, 1); - vector already_appended; + vector already_appended; bool append_failed = false; // now append the entries to the indices - indexes.Scan([&](Index &index) { + indexes.Scan([&](Index &index_to_append) { + if (!index_to_append.IsBound()) { + error = ErrorData("Unbound index found in DataTable::AppendToIndexes"); + append_failed = true; + return true; + } + auto &index = index_to_append.Cast(); try { error = index.Append(chunk, row_identifiers); } catch (std::exception &ex) { @@ -955,7 +1060,10 @@ void DataTable::RemoveFromIndexes(TableAppendState &state, DataChunk &chunk, row void DataTable::RemoveFromIndexes(TableAppendState &state, DataChunk &chunk, Vector &row_identifiers) { D_ASSERT(is_root); info->indexes.Scan([&](Index &index) { - index.Delete(chunk, row_identifiers); + if (!index.IsBound()) { + throw InternalException("Unbound index found in DataTable::RemoveFromIndexes"); + } + index.Cast().Delete(chunk, row_identifiers); return false; }); } @@ -1014,7 +1122,7 @@ void DataTable::VerifyDeleteConstraints(TableDeleteState &state, ClientContext & unique_ptr DataTable::InitializeDelete(TableCatalogEntry &table, ClientContext &context, const vector> &bound_constraints) { // initialize indexes (if any) - info->InitializeIndexes(context, true); + info->InitializeIndexes(context); auto binder = Binder::CreateBinder(context); vector types; @@ -1164,7 +1272,8 @@ void DataTable::VerifyUpdateConstraints(ConstraintState &state, ClientContext &c // instead update should have been rewritten to delete + update on higher layer #ifdef DEBUG info->indexes.Scan([&](Index &index) { - D_ASSERT(!index.IndexIsUpdated(column_ids)); + D_ASSERT(index.IsBound()); + D_ASSERT(!index.Cast().IndexIsUpdated(column_ids)); return false; }); @@ -1174,7 +1283,7 @@ void DataTable::VerifyUpdateConstraints(ConstraintState &state, ClientContext &c unique_ptr DataTable::InitializeUpdate(TableCatalogEntry &table, ClientContext &context, const vector> &bound_constraints) { // check that there are no unknown indexes - info->InitializeIndexes(context, true); + info->InitializeIndexes(context); auto result = make_uniq(); result->constraint_state = InitializeConstraintState(table, bound_constraints); @@ -1271,8 +1380,15 @@ void DataTable::SetDistinct(column_t column_id, unique_ptr d //===--------------------------------------------------------------------===// // Checkpoint //===--------------------------------------------------------------------===// -void DataTable::Checkpoint(TableDataWriter &writer, Serializer &serializer) { +unique_ptr DataTable::GetSharedCheckpointLock() { + return info->checkpoint_lock.GetSharedLock(); +} +unique_ptr DataTable::GetCheckpointLock() { + return info->checkpoint_lock.GetExclusiveLock(); +} + +void DataTable::Checkpoint(TableDataWriter &writer, Serializer &serializer) { // checkpoint each individual row group TableStatistics global_stats; row_groups->CopyStats(global_stats); @@ -1290,7 +1406,11 @@ void DataTable::CommitDropColumn(idx_t index) { row_groups->CommitDropColumn(index); } -idx_t DataTable::GetTotalRows() { +idx_t DataTable::ColumnCount() const { + return column_definitions.size(); +} + +idx_t DataTable::GetTotalRows() const { return row_groups->GetTotalRows(); } @@ -1300,7 +1420,8 @@ void DataTable::CommitDropTable() { // propagate dropping this table to its indexes: frees all index memory info->indexes.Scan([&](Index &index) { - index.CommitDrop(); + D_ASSERT(index.IsBound()); + index.Cast().CommitDrop(); return false; }); } @@ -1309,6 +1430,7 @@ void DataTable::CommitDropTable() { // GetColumnSegmentInfo //===--------------------------------------------------------------------===// vector DataTable::GetColumnSegmentInfo() { + auto lock = GetSharedCheckpointLock(); return row_groups->GetColumnSegmentInfo(); } diff --git a/src/storage/index.cpp b/src/storage/index.cpp index 01b2b6c5fe2..ca136d631f9 100644 --- a/src/storage/index.cpp +++ b/src/storage/index.cpp @@ -1,122 +1,18 @@ #include "duckdb/storage/index.hpp" - #include "duckdb/common/radix.hpp" #include "duckdb/common/serializer/serializer.hpp" -#include "duckdb/planner/expression/bound_columnref_expression.hpp" -#include "duckdb/planner/expression/bound_reference_expression.hpp" -#include "duckdb/planner/expression_iterator.hpp" -#include "duckdb/storage/table/append_state.hpp" namespace duckdb { -Index::Index(const string &name, const string &index_type, IndexConstraintType index_constraint_type, - const vector &column_ids, TableIOManager &table_io_manager, - const vector> &unbound_expressions, AttachedDatabase &db) +Index::Index(const vector &column_ids, TableIOManager &table_io_manager, AttachedDatabase &db) - : name(name), index_type(index_type), index_constraint_type(index_constraint_type), column_ids(column_ids), - table_io_manager(table_io_manager), db(db) { + : column_ids(column_ids), table_io_manager(table_io_manager), db(db) { if (!Radix::IsLittleEndian()) { throw NotImplementedException("indexes are not supported on big endian architectures"); } - - for (auto &expr : unbound_expressions) { - types.push_back(expr->return_type.InternalType()); - logical_types.push_back(expr->return_type); - auto unbound_expression = expr->Copy(); - bound_expressions.push_back(BindExpression(unbound_expression->Copy())); - this->unbound_expressions.emplace_back(std::move(unbound_expression)); - } - for (auto &bound_expr : bound_expressions) { - executor.AddExpression(*bound_expr); - } - // create the column id set column_id_set.insert(column_ids.begin(), column_ids.end()); } -void Index::InitializeLock(IndexLock &state) { - state.index_lock = unique_lock(lock); -} - -ErrorData Index::Append(DataChunk &entries, Vector &row_identifiers) { - IndexLock state; - InitializeLock(state); - return Append(state, entries, row_identifiers); -} - -void Index::CommitDrop() { - IndexLock index_lock; - InitializeLock(index_lock); - CommitDrop(index_lock); -} - -void Index::Delete(DataChunk &entries, Vector &row_identifiers) { - IndexLock state; - InitializeLock(state); - Delete(state, entries, row_identifiers); -} - -bool Index::MergeIndexes(Index &other_index) { - IndexLock state; - InitializeLock(state); - return MergeIndexes(state, other_index); -} - -string Index::VerifyAndToString(const bool only_verify) { - IndexLock state; - InitializeLock(state); - return VerifyAndToString(state, only_verify); -} - -void Index::Vacuum() { - IndexLock state; - InitializeLock(state); - Vacuum(state); -} - -idx_t Index::GetInMemorySize() { - IndexLock state; - InitializeLock(state); - return GetInMemorySize(state); -} - -void Index::ExecuteExpressions(DataChunk &input, DataChunk &result) { - executor.Execute(input, result); -} - -unique_ptr Index::BindExpression(unique_ptr expr) { - if (expr->type == ExpressionType::BOUND_COLUMN_REF) { - auto &bound_colref = expr->Cast(); - return make_uniq(expr->return_type, column_ids[bound_colref.binding.column_index]); - } - ExpressionIterator::EnumerateChildren( - *expr, [this](unique_ptr &expr) { expr = BindExpression(std::move(expr)); }); - return expr; -} - -bool Index::IndexIsUpdated(const vector &column_ids_p) const { - for (auto &column : column_ids_p) { - if (column_id_set.find(column.index) != column_id_set.end()) { - return true; - } - } - return false; -} - -IndexStorageInfo Index::GetStorageInfo(const bool get_buffers) { - throw NotImplementedException("The implementation of this index serialization does not exist."); -} - -string Index::AppendRowError(DataChunk &input, idx_t index) { - string error; - for (idx_t c = 0; c < input.ColumnCount(); c++) { - if (c > 0) { - error += ", "; - } - error += input.GetValue(c, index).ToString(); - } - return error; -} - } // namespace duckdb diff --git a/src/storage/local_storage.cpp b/src/storage/local_storage.cpp index d04888d76c5..580937c7733 100644 --- a/src/storage/local_storage.cpp +++ b/src/storage/local_storage.cpp @@ -14,30 +14,25 @@ namespace duckdb { -LocalTableStorage::LocalTableStorage(DataTable &table) +LocalTableStorage::LocalTableStorage(ClientContext &context, DataTable &table) : table_ref(table), allocator(Allocator::Get(table.db)), deleted_rows(0), optimistic_writer(table), merged_storage(false) { auto types = table.GetTypes(); - row_groups = make_shared_ptr(table.info, TableIOManager::Get(table).GetBlockManagerForRowData(), - types, MAX_ROW_ID, 0); + auto data_table_info = table.GetDataTableInfo(); + row_groups = make_shared_ptr( + data_table_info, TableIOManager::Get(table).GetBlockManagerForRowData(), types, MAX_ROW_ID, 0); row_groups->InitializeEmpty(); - table.info->indexes.Scan([&](Index &index) { - if (index.index_type != ART::TYPE_NAME) { - return false; - } - D_ASSERT(index.index_type == ART::TYPE_NAME); - - auto &art = index.Cast(); - if (art.index_constraint_type != IndexConstraintType::NONE) { + data_table_info->GetIndexes().BindAndScan(context, *data_table_info, [&](ART &art) { + if (art.GetConstraintType() != IndexConstraintType::NONE) { // unique index: create a local ART index that maintains the same unique constraint vector> unbound_expressions; unbound_expressions.reserve(art.unbound_expressions.size()); for (auto &expr : art.unbound_expressions) { unbound_expressions.push_back(expr->Copy()); } - indexes.AddIndex(make_uniq(art.name, art.index_constraint_type, art.column_ids, art.table_io_manager, - std::move(unbound_expressions), art.db)); + indexes.AddIndex(make_uniq(art.GetIndexName(), art.GetConstraintType(), art.GetColumnIds(), + art.table_io_manager, std::move(unbound_expressions), art.db)); } return false; }); @@ -64,11 +59,11 @@ LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &paren } LocalTableStorage::LocalTableStorage(ClientContext &context, DataTable &new_dt, LocalTableStorage &parent, - ColumnDefinition &new_column, Expression &default_value) + ColumnDefinition &new_column, ExpressionExecutor &default_executor) : table_ref(new_dt), allocator(Allocator::Get(new_dt.db)), deleted_rows(parent.deleted_rows), optimistic_writer(new_dt, parent.optimistic_writer), optimistic_writers(std::move(parent.optimistic_writers)), merged_storage(parent.merged_storage) { - row_groups = parent.row_groups->AddColumn(context, new_column, default_value); + row_groups = parent.row_groups->AddColumn(context, new_column, default_executor); parent.row_groups.reset(); indexes.Move(parent.indexes); } @@ -97,7 +92,8 @@ idx_t LocalTableStorage::EstimatedSize() { // get the index size idx_t index_sizes = 0; indexes.Scan([&](Index &index) { - index_sizes += index.GetInMemorySize(); + D_ASSERT(index.IsBound()); + index_sizes += index.Cast().GetInMemorySize(); return false; }); @@ -167,8 +163,9 @@ void LocalTableStorage::AppendToIndexes(DuckTransaction &transaction, TableAppen return true; }); } else { - error = - AppendToIndexes(transaction, *row_groups, table.info->indexes, table.GetTypes(), append_state.current_row); + auto data_table_info = table.GetDataTableInfo(); + auto &index_list = data_table_info->GetIndexes(); + error = AppendToIndexes(transaction, *row_groups, index_list, table.GetTypes(), append_state.current_row); } if (error.HasError()) { // need to revert all appended row ids @@ -196,14 +193,7 @@ void LocalTableStorage::AppendToIndexes(DuckTransaction &transaction, TableAppen // we need to vacuum the indexes to remove any buffers that are now empty // due to reverting the appends - table.info->indexes.Scan([&](Index &index) { - try { - index.Vacuum(); - } catch (std::exception &ex) { // LCOV_EXCL_START - error = ErrorData(ex); - } // LCOV_EXCL_STOP - return false; - }); + table.VacuumIndexes(); error.Throw(); } if (append_to_table) { @@ -250,11 +240,11 @@ optional_ptr LocalTableManager::GetStorage(DataTable &table) return entry == table_storage.end() ? nullptr : entry->second.get(); } -LocalTableStorage &LocalTableManager::GetOrCreateStorage(DataTable &table) { +LocalTableStorage &LocalTableManager::GetOrCreateStorage(ClientContext &context, DataTable &table) { lock_guard l(table_storage_lock); auto entry = table_storage.find(table); if (entry == table_storage.end()) { - auto new_storage = make_shared_ptr(table); + auto new_storage = make_shared_ptr(context, table); auto storage = new_storage.get(); table_storage.insert(make_pair(reference(table), std::move(new_storage))); return *storage; @@ -358,8 +348,8 @@ bool LocalStorage::NextParallelScan(ClientContext &context, DataTable &table, Pa } void LocalStorage::InitializeAppend(LocalAppendState &state, DataTable &table) { - table.info->InitializeIndexes(context); - state.storage = &table_manager.GetOrCreateStorage(table); + table.InitializeIndexes(context); + state.storage = &table_manager.GetOrCreateStorage(context, table); state.storage->row_groups->InitializeAppend(TransactionData(transaction), state.append_state); } @@ -386,7 +376,7 @@ void LocalStorage::FinalizeAppend(LocalAppendState &state) { } void LocalStorage::LocalMerge(DataTable &table, RowGroupCollection &collection) { - auto &storage = table_manager.GetOrCreateStorage(table); + auto &storage = table_manager.GetOrCreateStorage(context, table); if (!storage.indexes.Empty()) { // append data to indexes if required row_t base_id = MAX_ROW_ID + NumericCast(storage.row_groups->GetTotalRows()); @@ -400,12 +390,12 @@ void LocalStorage::LocalMerge(DataTable &table, RowGroupCollection &collection) } OptimisticDataWriter &LocalStorage::CreateOptimisticWriter(DataTable &table) { - auto &storage = table_manager.GetOrCreateStorage(table); + auto &storage = table_manager.GetOrCreateStorage(context, table); return storage.CreateOptimisticWriter(); } void LocalStorage::FinalizeOptimisticWriter(DataTable &table, OptimisticDataWriter &writer) { - auto &storage = table_manager.GetOrCreateStorage(table); + auto &storage = table_manager.GetOrCreateStorage(context, table); storage.FinalizeOptimisticWriter(writer); } @@ -446,12 +436,15 @@ void LocalStorage::Update(DataTable &table, Vector &row_ids, const vectorGetTotalRows() <= storage.deleted_rows) { return; } idx_t append_count = storage.row_groups->GetTotalRows() - storage.deleted_rows; - table.info->InitializeIndexes(context); + table.InitializeIndexes(context); TableAppendState append_state; table.AppendLock(append_state); @@ -464,7 +457,7 @@ void LocalStorage::Flush(DataTable &table, LocalTableStorage &storage) { // now append to the indexes (if there are any) // FIXME: we should be able to merge the transaction-local index directly into the main table index // as long we just rewrite some row-ids - if (!table.info->indexes.Empty()) { + if (table.HasIndexes()) { storage.AppendToIndexes(transaction, append_state, append_count, false); } // finally move over the row groups @@ -479,13 +472,10 @@ void LocalStorage::Flush(DataTable &table, LocalTableStorage &storage) { } // possibly vacuum any excess index data - table.info->indexes.Scan([&](Index &index) { - index.Vacuum(); - return false; - }); + table.VacuumIndexes(); } -void LocalStorage::Commit(LocalStorage::CommitState &commit_state, DuckTransaction &transaction) { +void LocalStorage::Commit() { // commit local storage // iterate over all entries in the table storage map and commit them // after this, the local storage is no longer required and can be cleared @@ -521,6 +511,14 @@ idx_t LocalStorage::AddedRows(DataTable &table) { return storage->row_groups->GetTotalRows() - storage->deleted_rows; } +void LocalStorage::DropTable(DataTable &table) { + auto storage = table_manager.GetStorage(table); + if (!storage) { + return; + } + storage->is_dropped = true; +} + void LocalStorage::MoveStorage(DataTable &old_dt, DataTable &new_dt) { // check if there are any pending appends for the old version of the table auto new_storage = table_manager.MoveEntry(old_dt); @@ -533,13 +531,13 @@ void LocalStorage::MoveStorage(DataTable &old_dt, DataTable &new_dt) { } void LocalStorage::AddColumn(DataTable &old_dt, DataTable &new_dt, ColumnDefinition &new_column, - Expression &default_value) { + ExpressionExecutor &default_executor) { // check if there are any pending appends for the old version of the table auto storage = table_manager.MoveEntry(old_dt); if (!storage) { return; } - auto new_storage = make_shared_ptr(context, new_dt, *storage, new_column, default_value); + auto new_storage = make_shared_ptr(context, new_dt, *storage, new_column, default_executor); table_manager.InsertEntry(new_dt, std::move(new_storage)); } diff --git a/src/storage/metadata/metadata_manager.cpp b/src/storage/metadata/metadata_manager.cpp index 2fba4fc1bbc..dc2ff931a8e 100644 --- a/src/storage/metadata/metadata_manager.cpp +++ b/src/storage/metadata/metadata_manager.cpp @@ -26,7 +26,7 @@ MetadataHandle MetadataManager::AllocateHandle() { break; } } - if (free_block == INVALID_BLOCK) { + if (free_block == INVALID_BLOCK || free_block > PeekNextBlockId()) { free_block = AllocateNewBlock(); } D_ASSERT(free_block != INVALID_BLOCK); @@ -67,11 +67,10 @@ void MetadataManager::ConvertToTransient(MetadataBlock &block) { // allocate a new transient block to replace it shared_ptr new_block; - auto new_buffer = buffer_manager.Allocate(MemoryTag::METADATA, Storage::BLOCK_SIZE, false, &new_block); + auto new_buffer = buffer_manager.Allocate(MemoryTag::METADATA, block_manager.GetBlockSize(), false, &new_block); // copy the data to the transient block - memcpy(new_buffer.Ptr(), old_buffer.Ptr(), Storage::BLOCK_SIZE); - + memcpy(new_buffer.Ptr(), old_buffer.Ptr(), block_manager.GetBlockSize()); block.block = std::move(new_block); // unregister the old block @@ -82,13 +81,13 @@ block_id_t MetadataManager::AllocateNewBlock() { auto new_block_id = GetNextBlockId(); MetadataBlock new_block; - auto handle = buffer_manager.Allocate(MemoryTag::METADATA, Storage::BLOCK_SIZE, false, &new_block.block); + auto handle = buffer_manager.Allocate(MemoryTag::METADATA, block_manager.GetBlockSize(), false, &new_block.block); new_block.block_id = new_block_id; for (idx_t i = 0; i < METADATA_BLOCK_COUNT; i++) { new_block.free_blocks.push_back(NumericCast(METADATA_BLOCK_COUNT - i - 1)); } // zero-initialize the handle - memset(handle.Ptr(), 0, Storage::BLOCK_SIZE); + memset(handle.Ptr(), 0, block_manager.GetBlockSize()); AddBlock(std::move(new_block)); return new_block_id; } @@ -147,22 +146,22 @@ MetadataPointer MetadataManager::RegisterDiskPointer(MetaBlockPointer pointer) { return FromDiskPointer(pointer); } -BlockPointer MetadataManager::ToBlockPointer(MetaBlockPointer meta_pointer) { +BlockPointer MetadataManager::ToBlockPointer(MetaBlockPointer meta_pointer, const idx_t metadata_block_size) { BlockPointer result; result.block_id = meta_pointer.GetBlockId(); - result.offset = meta_pointer.GetBlockIndex() * MetadataManager::METADATA_BLOCK_SIZE + meta_pointer.offset; - D_ASSERT(result.offset < MetadataManager::METADATA_BLOCK_SIZE * MetadataManager::METADATA_BLOCK_COUNT); + result.offset = meta_pointer.GetBlockIndex() * NumericCast(metadata_block_size) + meta_pointer.offset; + D_ASSERT(result.offset < metadata_block_size * MetadataManager::METADATA_BLOCK_COUNT); return result; } -MetaBlockPointer MetadataManager::FromBlockPointer(BlockPointer block_pointer) { +MetaBlockPointer MetadataManager::FromBlockPointer(BlockPointer block_pointer, const idx_t metadata_block_size) { if (!block_pointer.IsValid()) { return MetaBlockPointer(); } - idx_t index = block_pointer.offset / MetadataManager::METADATA_BLOCK_SIZE; - auto offset = block_pointer.offset % MetadataManager::METADATA_BLOCK_SIZE; + idx_t index = block_pointer.offset / metadata_block_size; + auto offset = block_pointer.offset % metadata_block_size; D_ASSERT(index < MetadataManager::METADATA_BLOCK_COUNT); - D_ASSERT(offset < MetadataManager::METADATA_BLOCK_SIZE); + D_ASSERT(offset < metadata_block_size); MetaBlockPointer result; result.block_pointer = idx_t(block_pointer.block_id) | index << 56ULL; result.offset = UnsafeNumericCast(offset); @@ -174,13 +173,14 @@ idx_t MetadataManager::BlockCount() { } void MetadataManager::Flush() { - const idx_t total_metadata_size = MetadataManager::METADATA_BLOCK_SIZE * MetadataManager::METADATA_BLOCK_COUNT; + const idx_t total_metadata_size = GetMetadataBlockSize() * MetadataManager::METADATA_BLOCK_COUNT; + // write the blocks of the metadata manager to disk for (auto &kv : blocks) { auto &block = kv.second; auto handle = buffer_manager.Pin(block.block); // there are a few bytes left-over at the end of the block, zero-initialize them - memset(handle.Ptr() + total_metadata_size, 0, Storage::BLOCK_SIZE - total_metadata_size); + memset(handle.Ptr() + total_metadata_size, 0, block_manager.GetBlockSize() - total_metadata_size); D_ASSERT(kv.first == block.block_id); if (block.block->BlockId() >= MAXIMUM_BLOCK) { // temporary block - convert to persistent @@ -220,6 +220,10 @@ void MetadataBlock::Write(WriteStream &sink) { sink.Write(FreeBlocksToInteger()); } +idx_t MetadataManager::GetMetadataBlockSize() const { + return AlignValueFloor(block_manager.GetBlockSize() / METADATA_BLOCK_COUNT); +} + MetadataBlock MetadataBlock::Read(ReadStream &source) { MetadataBlock result; result.block_id = source.Read(); @@ -315,6 +319,18 @@ vector MetadataManager::GetMetadataInfo() const { return result; } +vector> MetadataManager::GetBlocks() const { + vector> result; + for (auto &entry : blocks) { + result.push_back(entry.second.block); + } + return result; +} + +block_id_t MetadataManager::PeekNextBlockId() { + return block_manager.PeekFreeBlockId(); +} + block_id_t MetadataManager::GetNextBlockId() { return block_manager.GetFreeBlockId(); } diff --git a/src/storage/metadata/metadata_reader.cpp b/src/storage/metadata/metadata_reader.cpp index 91677253573..833a6e656f7 100644 --- a/src/storage/metadata/metadata_reader.cpp +++ b/src/storage/metadata/metadata_reader.cpp @@ -13,7 +13,7 @@ MetadataReader::MetadataReader(MetadataManager &manager, MetaBlockPointer pointe } MetadataReader::MetadataReader(MetadataManager &manager, BlockPointer pointer) - : MetadataReader(manager, MetadataManager::FromBlockPointer(pointer)) { + : MetadataReader(manager, MetadataManager::FromBlockPointer(pointer, manager.GetMetadataBlockSize())) { } MetadataPointer MetadataReader::FromDiskPointer(MetaBlockPointer pointer) { @@ -70,16 +70,16 @@ void MetadataReader::ReadNextBlock() { if (next_offset < sizeof(block_id_t)) { next_offset = sizeof(block_id_t); } - if (next_offset > MetadataManager::METADATA_BLOCK_SIZE) { + if (next_offset > GetMetadataManager().GetMetadataBlockSize()) { throw InternalException("next_offset cannot be bigger than block size"); } offset = next_offset; next_offset = sizeof(block_id_t); - capacity = MetadataManager::METADATA_BLOCK_SIZE; + capacity = GetMetadataManager().GetMetadataBlockSize(); } data_ptr_t MetadataReader::BasePtr() { - return block.handle.Ptr() + index * MetadataManager::METADATA_BLOCK_SIZE; + return block.handle.Ptr() + index * GetMetadataManager().GetMetadataBlockSize(); } data_ptr_t MetadataReader::Ptr() { diff --git a/src/storage/metadata/metadata_writer.cpp b/src/storage/metadata/metadata_writer.cpp index cc95b9086a8..a059d7cca52 100644 --- a/src/storage/metadata/metadata_writer.cpp +++ b/src/storage/metadata/metadata_writer.cpp @@ -18,7 +18,7 @@ MetadataWriter::~MetadataWriter() { } BlockPointer MetadataWriter::GetBlockPointer() { - return MetadataManager::ToBlockPointer(GetMetaBlockPointer()); + return MetadataManager::ToBlockPointer(GetMetaBlockPointer(), GetManager().GetMetadataBlockSize()); } MetaBlockPointer MetadataWriter::GetMetaBlockPointer() { @@ -47,7 +47,7 @@ void MetadataWriter::NextBlock() { block = std::move(new_handle); current_pointer = block.pointer; offset = sizeof(idx_t); - capacity = MetadataManager::METADATA_BLOCK_SIZE; + capacity = GetManager().GetMetadataBlockSize(); Store(static_cast(-1), BasePtr()); if (written_pointers) { written_pointers->push_back(manager.GetDiskPointer(current_pointer)); @@ -82,7 +82,7 @@ void MetadataWriter::Flush() { } data_ptr_t MetadataWriter::BasePtr() { - return block.handle.Ptr() + current_pointer.index * MetadataManager::METADATA_BLOCK_SIZE; + return block.handle.Ptr() + current_pointer.index * GetManager().GetMetadataBlockSize(); } data_ptr_t MetadataWriter::Ptr() { diff --git a/src/storage/optimistic_data_writer.cpp b/src/storage/optimistic_data_writer.cpp index df352698ffc..0a1966c500b 100644 --- a/src/storage/optimistic_data_writer.cpp +++ b/src/storage/optimistic_data_writer.cpp @@ -19,14 +19,14 @@ OptimisticDataWriter::~OptimisticDataWriter() { bool OptimisticDataWriter::PrepareWrite() { // check if we should pre-emptively write the table to disk - if (table.info->IsTemporary() || StorageManager::Get(table.info->db).InMemory()) { + if (table.IsTemporary() || StorageManager::Get(table.GetAttached()).InMemory()) { return false; } // we should! write the second-to-last row group to disk // allocate the partial block-manager if none is allocated yet if (!partial_manager) { - auto &block_manager = table.info->table_io_manager->GetBlockManagerForRowData(); - partial_manager = make_uniq(block_manager, CheckpointType::APPEND_TO_TABLE); + auto &block_manager = table.GetTableIOManager().GetBlockManagerForRowData(); + partial_manager = make_uniq(block_manager, PartialBlockType::APPEND_TO_TABLE); } return true; } @@ -38,7 +38,7 @@ void OptimisticDataWriter::WriteNewRowGroup(RowGroupCollection &row_groups) { } // flush second-to-last row group auto row_group = row_groups.GetRowGroup(-2); - FlushToDisk(row_group); + FlushToDisk(*row_group); } void OptimisticDataWriter::WriteLastRowGroup(RowGroupCollection &row_groups) { @@ -51,20 +51,18 @@ void OptimisticDataWriter::WriteLastRowGroup(RowGroupCollection &row_groups) { if (!row_group) { return; } - FlushToDisk(row_group); + FlushToDisk(*row_group); } -void OptimisticDataWriter::FlushToDisk(RowGroup *row_group) { - if (!row_group) { - throw InternalException("FlushToDisk called without a RowGroup"); - } +void OptimisticDataWriter::FlushToDisk(RowGroup &row_group) { //! The set of column compression types (if any) vector compression_types; D_ASSERT(compression_types.empty()); - for (auto &column : table.column_definitions) { + for (auto &column : table.Columns()) { compression_types.push_back(column.CompressionType()); } - row_group->WriteToDisk(*partial_manager, compression_types); + RowGroupWriteInfo info(*partial_manager, compression_types); + row_group.WriteToDisk(info); } void OptimisticDataWriter::Merge(OptimisticDataWriter &other) { diff --git a/src/storage/partial_block_manager.cpp b/src/storage/partial_block_manager.cpp index 7fd73d6ff0b..43b29a23707 100644 --- a/src/storage/partial_block_manager.cpp +++ b/src/storage/partial_block_manager.cpp @@ -26,7 +26,7 @@ void PartialBlock::FlushInternal(const idx_t free_space_left) { memset(buffer_handle.Ptr() + uninitialized.start, 0, uninitialized.end - uninitialized.start); } // memset any free space at the end of the block to 0 prior to writing to disk - memset(buffer_handle.Ptr() + Storage::BLOCK_SIZE - free_space_left, 0, free_space_left); + memset(buffer_handle.Ptr() + block_manager.GetBlockSize() - free_space_left, 0, free_space_left); } } @@ -34,10 +34,17 @@ void PartialBlock::FlushInternal(const idx_t free_space_left) { // PartialBlockManager //===--------------------------------------------------------------------===// -PartialBlockManager::PartialBlockManager(BlockManager &block_manager, CheckpointType checkpoint_type, - uint32_t max_partial_block_size, uint32_t max_use_count) - : block_manager(block_manager), checkpoint_type(checkpoint_type), max_partial_block_size(max_partial_block_size), - max_use_count(max_use_count) { +PartialBlockManager::PartialBlockManager(BlockManager &block_manager, PartialBlockType partial_block_type, + optional_idx max_partial_block_size_p, uint32_t max_use_count) + : block_manager(block_manager), partial_block_type(partial_block_type), max_use_count(max_use_count) { + + if (max_partial_block_size_p.IsValid()) { + max_partial_block_size = NumericCast(max_partial_block_size_p.GetIndex()); + return; + } + + // Use the default maximum partial block size with a ratio of 20% free and 80% utilization. + max_partial_block_size = NumericCast(block_manager.GetBlockSize() / 5 * 4); } PartialBlockManager::~PartialBlockManager() { } @@ -54,7 +61,7 @@ PartialBlockAllocation PartialBlockManager::GetBlockAllocation(uint32_t segment_ //! there is! increase the reference count of this block allocation.partial_block->state.block_use_count += 1; allocation.state = allocation.partial_block->state; - if (checkpoint_type == CheckpointType::FULL_CHECKPOINT) { + if (partial_block_type == PartialBlockType::FULL_CHECKPOINT) { block_manager.IncreaseBlockReferenceCount(allocation.state.block_id); } } else { @@ -70,13 +77,13 @@ bool PartialBlockManager::HasBlockAllocation(uint32_t segment_size) { } void PartialBlockManager::AllocateBlock(PartialBlockState &state, uint32_t segment_size) { - D_ASSERT(segment_size <= Storage::BLOCK_SIZE); - if (checkpoint_type == CheckpointType::FULL_CHECKPOINT) { + D_ASSERT(segment_size <= block_manager.GetBlockSize()); + if (partial_block_type == PartialBlockType::FULL_CHECKPOINT) { state.block_id = block_manager.GetFreeBlockId(); } else { state.block_id = INVALID_BLOCK; } - state.block_size = Storage::BLOCK_SIZE; + state.block_size = NumericCast(block_manager.GetBlockSize()); state.offset = 0; state.block_use_count = 1; } @@ -97,7 +104,7 @@ bool PartialBlockManager::GetPartialBlock(idx_t segment_size, unique_ptrstate; - D_ASSERT(checkpoint_type != CheckpointType::FULL_CHECKPOINT || state.block_id >= 0); + D_ASSERT(partial_block_type != PartialBlockType::FULL_CHECKPOINT || state.block_id >= 0); if (state.block_use_count < max_use_count) { auto unaligned_size = allocation.allocation_size + state.offset; auto new_size = AlignValue(unaligned_size); @@ -108,7 +115,7 @@ void PartialBlockManager::RegisterPartialBlock(PartialBlockAllocation allocation state.offset = new_size; auto new_space_left = state.block_size - new_size; // check if the block is STILL partially filled after adding the segment_size - if (new_space_left >= Storage::BLOCK_SIZE - max_partial_block_size) { + if (new_space_left >= block_manager.GetBlockSize() - max_partial_block_size) { // the block is still partially filled: add it to the partially_filled_blocks list partially_filled_blocks.insert(make_pair(new_space_left, std::move(allocation.partial_block))); } @@ -139,7 +146,7 @@ void PartialBlockManager::Merge(PartialBlockManager &other) { if (!e.second) { throw InternalException("Empty partially filled block found"); } - auto used_space = NumericCast(Storage::BLOCK_SIZE - e.first); + auto used_space = NumericCast(block_manager.GetBlockSize() - e.first); if (HasBlockAllocation(used_space)) { // we can merge this block into an existing block - merge them // merge blocks diff --git a/src/storage/serialization/CMakeLists.txt b/src/storage/serialization/CMakeLists.txt index 0f6914fb256..ced81c3b2c3 100644 --- a/src/storage/serialization/CMakeLists.txt +++ b/src/storage/serialization/CMakeLists.txt @@ -3,7 +3,9 @@ add_library_unity( OBJECT serialize_constraint.cpp serialize_create_info.cpp + serialize_dependency.cpp serialize_expression.cpp + serialize_extension_install_info.cpp serialize_extra_drop_info.cpp serialize_logical_operator.cpp serialize_macro_function.cpp diff --git a/src/storage/serialization/serialize_create_info.cpp b/src/storage/serialization/serialize_create_info.cpp index 3196a1d107d..29d9c06d447 100644 --- a/src/storage/serialization/serialize_create_info.cpp +++ b/src/storage/serialization/serialize_create_info.cpp @@ -25,6 +25,10 @@ void CreateInfo::Serialize(Serializer &serializer) const { serializer.WriteProperty(105, "on_conflict", on_conflict); serializer.WritePropertyWithDefault(106, "sql", sql); serializer.WritePropertyWithDefault(107, "comment", comment, Value()); + serializer.WritePropertyWithDefault>(108, "tags", tags, unordered_map()); + if (serializer.ShouldSerialize(2)) { + serializer.WritePropertyWithDefault(109, "dependencies", dependencies, LogicalDependencyList()); + } } unique_ptr CreateInfo::Deserialize(Deserializer &deserializer) { @@ -36,6 +40,8 @@ unique_ptr CreateInfo::Deserialize(Deserializer &deserializer) { auto on_conflict = deserializer.ReadProperty(105, "on_conflict"); auto sql = deserializer.ReadPropertyWithDefault(106, "sql"); auto comment = deserializer.ReadPropertyWithDefault(107, "comment", Value()); + auto tags = deserializer.ReadPropertyWithDefault>(108, "tags", unordered_map()); + auto dependencies = deserializer.ReadPropertyWithDefault(109, "dependencies", LogicalDependencyList()); deserializer.Set(type); unique_ptr result; switch (type) { @@ -74,6 +80,8 @@ unique_ptr CreateInfo::Deserialize(Deserializer &deserializer) { result->on_conflict = on_conflict; result->sql = std::move(sql); result->comment = comment; + result->tags = std::move(tags); + result->dependencies = dependencies; return result; } diff --git a/src/storage/serialization/serialize_dependency.cpp b/src/storage/serialization/serialize_dependency.cpp new file mode 100644 index 00000000000..b2c22375a43 --- /dev/null +++ b/src/storage/serialization/serialize_dependency.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// This file is automatically generated by scripts/generate_serialization.py +// Do not edit this file manually, your changes will be overwritten +//===----------------------------------------------------------------------===// + +#include "duckdb/common/serializer/serializer.hpp" +#include "duckdb/common/serializer/deserializer.hpp" +#include "duckdb/catalog/dependency.hpp" +#include "duckdb/catalog/dependency_list.hpp" + +namespace duckdb { + +void CatalogEntryInfo::Serialize(Serializer &serializer) const { + serializer.WriteProperty(100, "type", type); + serializer.WritePropertyWithDefault(101, "schema", schema); + serializer.WritePropertyWithDefault(102, "name", name); +} + +CatalogEntryInfo CatalogEntryInfo::Deserialize(Deserializer &deserializer) { + CatalogEntryInfo result; + deserializer.ReadProperty(100, "type", result.type); + deserializer.ReadPropertyWithDefault(101, "schema", result.schema); + deserializer.ReadPropertyWithDefault(102, "name", result.name); + return result; +} + +void LogicalDependency::Serialize(Serializer &serializer) const { + serializer.WriteProperty(100, "entry", entry); + serializer.WritePropertyWithDefault(101, "catalog", catalog); +} + +LogicalDependency LogicalDependency::Deserialize(Deserializer &deserializer) { + LogicalDependency result; + deserializer.ReadProperty(100, "entry", result.entry); + deserializer.ReadPropertyWithDefault(101, "catalog", result.catalog); + return result; +} + +void LogicalDependencyList::Serialize(Serializer &serializer) const { + serializer.WriteProperty(100, "set", set); +} + +LogicalDependencyList LogicalDependencyList::Deserialize(Deserializer &deserializer) { + LogicalDependencyList result; + deserializer.ReadProperty(100, "set", result.set); + return result; +} + +} // namespace duckdb diff --git a/src/storage/serialization/serialize_extension_install_info.cpp b/src/storage/serialization/serialize_extension_install_info.cpp new file mode 100644 index 00000000000..9d43be0ced8 --- /dev/null +++ b/src/storage/serialization/serialize_extension_install_info.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// This file is automatically generated by scripts/generate_serialization.py +// Do not edit this file manually, your changes will be overwritten +//===----------------------------------------------------------------------===// + +#include "duckdb/common/serializer/serializer.hpp" +#include "duckdb/common/serializer/deserializer.hpp" +#include "duckdb/main/extension_install_info.hpp" + +namespace duckdb { + +void ExtensionInstallInfo::Serialize(Serializer &serializer) const { + serializer.WriteProperty(100, "mode", mode); + serializer.WritePropertyWithDefault(101, "full_path", full_path); + serializer.WritePropertyWithDefault(102, "repository_url", repository_url); + serializer.WritePropertyWithDefault(103, "version", version); + serializer.WritePropertyWithDefault(104, "etag", etag); +} + +unique_ptr ExtensionInstallInfo::Deserialize(Deserializer &deserializer) { + auto result = duckdb::unique_ptr(new ExtensionInstallInfo()); + deserializer.ReadProperty(100, "mode", result->mode); + deserializer.ReadPropertyWithDefault(101, "full_path", result->full_path); + deserializer.ReadPropertyWithDefault(102, "repository_url", result->repository_url); + deserializer.ReadPropertyWithDefault(103, "version", result->version); + deserializer.ReadPropertyWithDefault(104, "etag", result->etag); + return result; +} + +} // namespace duckdb diff --git a/src/storage/serialization/serialize_logical_operator.cpp b/src/storage/serialization/serialize_logical_operator.cpp index 0fec4cbe140..055c4e773ab 100644 --- a/src/storage/serialization/serialize_logical_operator.cpp +++ b/src/storage/serialization/serialize_logical_operator.cpp @@ -172,6 +172,9 @@ unique_ptr LogicalOperator::Deserialize(Deserializer &deseriali case LogicalOperatorType::LOGICAL_UPDATE: result = LogicalUpdate::Deserialize(deserializer); break; + case LogicalOperatorType::LOGICAL_VACUUM: + result = LogicalVacuum::Deserialize(deserializer); + break; case LogicalOperatorType::LOGICAL_WINDOW: result = LogicalWindow::Deserialize(deserializer); break; @@ -262,13 +265,13 @@ void LogicalColumnDataGet::Serialize(Serializer &serializer) const { LogicalOperator::Serialize(serializer); serializer.WritePropertyWithDefault(200, "table_index", table_index); serializer.WritePropertyWithDefault>(201, "chunk_types", chunk_types); - serializer.WritePropertyWithDefault>(202, "collection", collection); + serializer.WritePropertyWithDefault>(202, "collection", collection); } unique_ptr LogicalColumnDataGet::Deserialize(Deserializer &deserializer) { auto table_index = deserializer.ReadPropertyWithDefault(200, "table_index"); auto chunk_types = deserializer.ReadPropertyWithDefault>(201, "chunk_types"); - auto collection = deserializer.ReadPropertyWithDefault>(202, "collection"); + auto collection = deserializer.ReadPropertyWithDefault>(202, "collection"); auto result = duckdb::unique_ptr(new LogicalColumnDataGet(table_index, std::move(chunk_types), std::move(collection))); return std::move(result); } diff --git a/src/storage/serialization/serialize_nodes.cpp b/src/storage/serialization/serialize_nodes.cpp index 03afa0d566e..a454c9210e9 100644 --- a/src/storage/serialization/serialize_nodes.cpp +++ b/src/storage/serialization/serialize_nodes.cpp @@ -14,6 +14,8 @@ #include "duckdb/parser/expression/case_expression.hpp" #include "duckdb/planner/expression/bound_case_expression.hpp" #include "duckdb/parser/parsed_data/sample_options.hpp" +#include "duckdb/execution/reservoir_sample.hpp" +#include "duckdb/common/queue.hpp" #include "duckdb/parser/tableref/pivotref.hpp" #include "duckdb/planner/tableref/bound_pivotref.hpp" #include "duckdb/parser/column_definition.hpp" @@ -33,6 +35,52 @@ namespace duckdb { +void BlockingSample::Serialize(Serializer &serializer) const { + serializer.WritePropertyWithDefault>(100, "base_reservoir_sample", base_reservoir_sample); + serializer.WriteProperty(101, "type", type); + serializer.WritePropertyWithDefault(102, "destroyed", destroyed); +} + +unique_ptr BlockingSample::Deserialize(Deserializer &deserializer) { + auto base_reservoir_sample = deserializer.ReadPropertyWithDefault>(100, "base_reservoir_sample"); + auto type = deserializer.ReadProperty(101, "type"); + auto destroyed = deserializer.ReadPropertyWithDefault(102, "destroyed"); + unique_ptr result; + switch (type) { + case SampleType::RESERVOIR_PERCENTAGE_SAMPLE: + result = ReservoirSamplePercentage::Deserialize(deserializer); + break; + case SampleType::RESERVOIR_SAMPLE: + result = ReservoirSample::Deserialize(deserializer); + break; + default: + throw SerializationException("Unsupported type for deserialization of BlockingSample!"); + } + result->base_reservoir_sample = std::move(base_reservoir_sample); + result->destroyed = destroyed; + return result; +} + +void BaseReservoirSampling::Serialize(Serializer &serializer) const { + serializer.WritePropertyWithDefault(100, "next_index_to_sample", next_index_to_sample); + serializer.WriteProperty(101, "min_weight_threshold", min_weight_threshold); + serializer.WritePropertyWithDefault(102, "min_weighted_entry_index", min_weighted_entry_index); + serializer.WritePropertyWithDefault(103, "num_entries_to_skip_b4_next_sample", num_entries_to_skip_b4_next_sample); + serializer.WritePropertyWithDefault(104, "num_entries_seen_total", num_entries_seen_total); + serializer.WritePropertyWithDefault>>(105, "reservoir_weights", reservoir_weights); +} + +unique_ptr BaseReservoirSampling::Deserialize(Deserializer &deserializer) { + auto result = duckdb::unique_ptr(new BaseReservoirSampling()); + deserializer.ReadPropertyWithDefault(100, "next_index_to_sample", result->next_index_to_sample); + deserializer.ReadProperty(101, "min_weight_threshold", result->min_weight_threshold); + deserializer.ReadPropertyWithDefault(102, "min_weighted_entry_index", result->min_weighted_entry_index); + deserializer.ReadPropertyWithDefault(103, "num_entries_to_skip_b4_next_sample", result->num_entries_to_skip_b4_next_sample); + deserializer.ReadPropertyWithDefault(104, "num_entries_seen_total", result->num_entries_seen_total); + deserializer.ReadPropertyWithDefault>>(105, "reservoir_weights", result->reservoir_weights); + return result; +} + void BoundCaseCheck::Serialize(Serializer &serializer) const { serializer.WritePropertyWithDefault>(100, "when_expr", when_expr); serializer.WritePropertyWithDefault>(101, "then_expr", then_expr); @@ -222,6 +270,7 @@ void ColumnDefinition::Serialize(Serializer &serializer) const { serializer.WriteProperty(103, "category", category); serializer.WriteProperty(104, "compression_type", compression_type); serializer.WritePropertyWithDefault(105, "comment", comment, Value()); + serializer.WritePropertyWithDefault>(106, "tags", tags, unordered_map()); } ColumnDefinition ColumnDefinition::Deserialize(Deserializer &deserializer) { @@ -232,6 +281,7 @@ ColumnDefinition ColumnDefinition::Deserialize(Deserializer &deserializer) { ColumnDefinition result(std::move(name), std::move(type), std::move(expression), category); deserializer.ReadProperty(104, "compression_type", result.compression_type); deserializer.ReadPropertyWithDefault(105, "comment", result.comment, Value()); + deserializer.ReadPropertyWithDefault>(106, "tags", result.tags, unordered_map()); return result; } @@ -272,12 +322,12 @@ unique_ptr CommonTableExpressionInfo::Deserialize(Des } void CommonTableExpressionMap::Serialize(Serializer &serializer) const { - serializer.WritePropertyWithDefault>>(100, "map", map); + serializer.WritePropertyWithDefault>>(100, "map", map); } CommonTableExpressionMap CommonTableExpressionMap::Deserialize(Deserializer &deserializer) { CommonTableExpressionMap result; - deserializer.ReadPropertyWithDefault>>(100, "map", result.map); + deserializer.ReadPropertyWithDefault>>(100, "map", result.map); return result; } @@ -338,6 +388,7 @@ void MultiFileReaderOptions::Serialize(Serializer &serializer) const { serializer.WritePropertyWithDefault(103, "union_by_name", union_by_name); serializer.WritePropertyWithDefault(104, "hive_types_autocast", hive_types_autocast); serializer.WritePropertyWithDefault>(105, "hive_types_schema", hive_types_schema); + serializer.WritePropertyWithDefault(106, "filename_column", filename_column, MultiFileReaderOptions::DEFAULT_FILENAME_COLUMN); } MultiFileReaderOptions MultiFileReaderOptions::Deserialize(Deserializer &deserializer) { @@ -348,6 +399,7 @@ MultiFileReaderOptions MultiFileReaderOptions::Deserialize(Deserializer &deseria deserializer.ReadPropertyWithDefault(103, "union_by_name", result.union_by_name); deserializer.ReadPropertyWithDefault(104, "hive_types_autocast", result.hive_types_autocast); deserializer.ReadPropertyWithDefault>(105, "hive_types_schema", result.hive_types_schema); + deserializer.ReadPropertyWithDefault(106, "filename_column", result.filename_column, MultiFileReaderOptions::DEFAULT_FILENAME_COLUMN); return result; } @@ -421,6 +473,32 @@ unique_ptr ReadCSVData::Deserialize(Deserializer &deserializer) { return result; } +void ReservoirSample::Serialize(Serializer &serializer) const { + BlockingSample::Serialize(serializer); + serializer.WritePropertyWithDefault(200, "sample_count", sample_count); + serializer.WritePropertyWithDefault>(201, "reservoir_chunk", reservoir_chunk); +} + +unique_ptr ReservoirSample::Deserialize(Deserializer &deserializer) { + auto sample_count = deserializer.ReadPropertyWithDefault(200, "sample_count"); + auto result = duckdb::unique_ptr(new ReservoirSample(sample_count)); + deserializer.ReadPropertyWithDefault>(201, "reservoir_chunk", result->reservoir_chunk); + return std::move(result); +} + +void ReservoirSamplePercentage::Serialize(Serializer &serializer) const { + BlockingSample::Serialize(serializer); + serializer.WriteProperty(200, "sample_percentage", sample_percentage); + serializer.WritePropertyWithDefault(201, "reservoir_sample_size", reservoir_sample_size); +} + +unique_ptr ReservoirSamplePercentage::Deserialize(Deserializer &deserializer) { + auto sample_percentage = deserializer.ReadProperty(200, "sample_percentage"); + auto result = duckdb::unique_ptr(new ReservoirSamplePercentage(sample_percentage)); + deserializer.ReadPropertyWithDefault(201, "reservoir_sample_size", result->reservoir_sample_size); + return std::move(result); +} + void SampleOptions::Serialize(Serializer &serializer) const { serializer.WriteProperty(100, "sample_size", sample_size); serializer.WritePropertyWithDefault(101, "is_percentage", is_percentage); diff --git a/src/storage/serialization/serialize_parse_info.cpp b/src/storage/serialization/serialize_parse_info.cpp index fbd3d32c1e8..6a8925345bf 100644 --- a/src/storage/serialization/serialize_parse_info.cpp +++ b/src/storage/serialization/serialize_parse_info.cpp @@ -15,6 +15,7 @@ #include "duckdb/parser/parsed_data/detach_info.hpp" #include "duckdb/parser/parsed_data/drop_info.hpp" #include "duckdb/parser/parsed_data/load_info.hpp" +#include "duckdb/parser/parsed_data/update_extensions_info.hpp" #include "duckdb/parser/parsed_data/pragma_info.hpp" #include "duckdb/parser/parsed_data/transaction_info.hpp" #include "duckdb/parser/parsed_data/vacuum_info.hpp" @@ -56,6 +57,9 @@ unique_ptr ParseInfo::Deserialize(Deserializer &deserializer) { case ParseInfoType::TRANSACTION_INFO: result = TransactionInfo::Deserialize(deserializer); break; + case ParseInfoType::UPDATE_EXTENSIONS_INFO: + result = UpdateExtensionsInfo::Deserialize(deserializer); + break; case ParseInfoType::VACUUM_INFO: result = VacuumInfo::Deserialize(deserializer); break; @@ -256,6 +260,7 @@ void CopyInfo::Serialize(Serializer &serializer) const { serializer.WritePropertyWithDefault(205, "format", format); serializer.WritePropertyWithDefault(206, "file_path", file_path); serializer.WritePropertyWithDefault>>(207, "options", options); + serializer.WritePropertyWithDefault>(208, "select_statement", select_statement); } unique_ptr CopyInfo::Deserialize(Deserializer &deserializer) { @@ -268,6 +273,7 @@ unique_ptr CopyInfo::Deserialize(Deserializer &deserializer) { deserializer.ReadPropertyWithDefault(205, "format", result->format); deserializer.ReadPropertyWithDefault(206, "file_path", result->file_path); deserializer.ReadPropertyWithDefault>>(207, "options", result->options); + deserializer.ReadPropertyWithDefault>(208, "select_statement", result->select_statement); return std::move(result); } @@ -325,6 +331,8 @@ void LoadInfo::Serialize(Serializer &serializer) const { serializer.WritePropertyWithDefault(200, "filename", filename); serializer.WriteProperty(201, "load_type", load_type); serializer.WritePropertyWithDefault(202, "repository", repository); + serializer.WritePropertyWithDefault(203, "version", version); + serializer.WritePropertyWithDefault(204, "repo_is_alias", repo_is_alias); } unique_ptr LoadInfo::Deserialize(Deserializer &deserializer) { @@ -332,6 +340,8 @@ unique_ptr LoadInfo::Deserialize(Deserializer &deserializer) { deserializer.ReadPropertyWithDefault(200, "filename", result->filename); deserializer.ReadProperty(201, "load_type", result->load_type); deserializer.ReadPropertyWithDefault(202, "repository", result->repository); + deserializer.ReadPropertyWithDefault(203, "version", result->version); + deserializer.ReadPropertyWithDefault(204, "repo_is_alias", result->repo_is_alias); return std::move(result); } @@ -455,11 +465,24 @@ unique_ptr SetNotNullInfo::Deserialize(Deserializer &deserialize void TransactionInfo::Serialize(Serializer &serializer) const { ParseInfo::Serialize(serializer); serializer.WriteProperty(200, "type", type); + serializer.WriteProperty(201, "modifier", modifier); } unique_ptr TransactionInfo::Deserialize(Deserializer &deserializer) { auto result = duckdb::unique_ptr(new TransactionInfo()); deserializer.ReadProperty(200, "type", result->type); + deserializer.ReadProperty(201, "modifier", result->modifier); + return std::move(result); +} + +void UpdateExtensionsInfo::Serialize(Serializer &serializer) const { + ParseInfo::Serialize(serializer); + serializer.WritePropertyWithDefault>(200, "extensions_to_update", extensions_to_update); +} + +unique_ptr UpdateExtensionsInfo::Deserialize(Deserializer &deserializer) { + auto result = duckdb::unique_ptr(new UpdateExtensionsInfo()); + deserializer.ReadPropertyWithDefault>(200, "extensions_to_update", result->extensions_to_update); return std::move(result); } diff --git a/src/storage/serialization/serialize_parsed_expression.cpp b/src/storage/serialization/serialize_parsed_expression.cpp index 9c7752f636e..6cdc1269b08 100644 --- a/src/storage/serialization/serialize_parsed_expression.cpp +++ b/src/storage/serialization/serialize_parsed_expression.cpp @@ -292,6 +292,7 @@ void StarExpression::Serialize(Serializer &serializer) const { serializer.WritePropertyWithDefault>>(202, "replace_list", replace_list); serializer.WritePropertyWithDefault(203, "columns", columns); serializer.WritePropertyWithDefault>(204, "expr", expr); + serializer.WritePropertyWithDefault(205, "unpacked", unpacked, false); } unique_ptr StarExpression::Deserialize(Deserializer &deserializer) { @@ -301,6 +302,7 @@ unique_ptr StarExpression::Deserialize(Deserializer &deseriali deserializer.ReadPropertyWithDefault>>(202, "replace_list", result->replace_list); deserializer.ReadPropertyWithDefault(203, "columns", result->columns); deserializer.ReadPropertyWithDefault>(204, "expr", result->expr); + deserializer.ReadPropertyWithDefault(205, "unpacked", result->unpacked, false); return std::move(result); } diff --git a/src/storage/serialization/serialize_tableref.cpp b/src/storage/serialization/serialize_tableref.cpp index e97e823297a..e59594cc66b 100644 --- a/src/storage/serialization/serialize_tableref.cpp +++ b/src/storage/serialization/serialize_tableref.cpp @@ -26,6 +26,9 @@ unique_ptr TableRef::Deserialize(Deserializer &deserializer) { case TableReferenceType::BASE_TABLE: result = BaseTableRef::Deserialize(deserializer); break; + case TableReferenceType::COLUMN_DATA: + result = ColumnDataRef::Deserialize(deserializer); + break; case TableReferenceType::EMPTY_FROM: result = EmptyTableRef::Deserialize(deserializer); break; @@ -73,6 +76,19 @@ unique_ptr BaseTableRef::Deserialize(Deserializer &deserializer) { return std::move(result); } +void ColumnDataRef::Serialize(Serializer &serializer) const { + TableRef::Serialize(serializer); + serializer.WritePropertyWithDefault>(200, "expected_names", expected_names); + serializer.WritePropertyWithDefault>(202, "collection", collection); +} + +unique_ptr ColumnDataRef::Deserialize(Deserializer &deserializer) { + auto expected_names = deserializer.ReadPropertyWithDefault>(200, "expected_names"); + auto collection = deserializer.ReadPropertyWithDefault>(202, "collection"); + auto result = duckdb::unique_ptr(new ColumnDataRef(std::move(expected_names), std::move(collection))); + return std::move(result); +} + void EmptyTableRef::Serialize(Serializer &serializer) const { TableRef::Serialize(serializer); } diff --git a/src/storage/serialization/serialize_types.cpp b/src/storage/serialization/serialize_types.cpp index f937c0e0df7..bd7f619ba83 100644 --- a/src/storage/serialization/serialize_types.cpp +++ b/src/storage/serialization/serialize_types.cpp @@ -12,11 +12,13 @@ namespace duckdb { void ExtraTypeInfo::Serialize(Serializer &serializer) const { serializer.WriteProperty(100, "type", type); serializer.WritePropertyWithDefault(101, "alias", alias); + serializer.WritePropertyWithDefault>(102, "modifiers", modifiers, vector()); } shared_ptr ExtraTypeInfo::Deserialize(Deserializer &deserializer) { auto type = deserializer.ReadProperty(100, "type"); auto alias = deserializer.ReadPropertyWithDefault(101, "alias"); + auto modifiers = deserializer.ReadPropertyWithDefault>(102, "modifiers", vector()); shared_ptr result; switch (type) { case ExtraTypeInfoType::AGGREGATE_STATE_TYPE_INFO: @@ -58,6 +60,7 @@ shared_ptr ExtraTypeInfo::Deserialize(Deserializer &deserializer) throw SerializationException("Unsupported type for deserialization of ExtraTypeInfo!"); } result->alias = std::move(alias); + result->modifiers = std::move(modifiers); return result; } @@ -164,6 +167,7 @@ void UserTypeInfo::Serialize(Serializer &serializer) const { serializer.WritePropertyWithDefault(200, "user_type_name", user_type_name); serializer.WritePropertyWithDefault(201, "catalog", catalog, string()); serializer.WritePropertyWithDefault(202, "schema", schema, string()); + serializer.WritePropertyWithDefault>(203, "user_type_modifiers", user_type_modifiers, vector()); } shared_ptr UserTypeInfo::Deserialize(Deserializer &deserializer) { @@ -171,6 +175,7 @@ shared_ptr UserTypeInfo::Deserialize(Deserializer &deserializer) deserializer.ReadPropertyWithDefault(200, "user_type_name", result->user_type_name); deserializer.ReadPropertyWithDefault(201, "catalog", result->catalog, string()); deserializer.ReadPropertyWithDefault(202, "schema", result->schema, string()); + deserializer.ReadPropertyWithDefault>(203, "user_type_modifiers", result->user_type_modifiers, vector()); return std::move(result); } diff --git a/src/storage/single_file_block_manager.cpp b/src/storage/single_file_block_manager.cpp index 98775c1c745..19b6a9d42bb 100644 --- a/src/storage/single_file_block_manager.cpp +++ b/src/storage/single_file_block_manager.cpp @@ -4,11 +4,11 @@ #include "duckdb/common/checksum.hpp" #include "duckdb/common/exception.hpp" #include "duckdb/common/serializer/memory_stream.hpp" -#include "duckdb/storage/metadata/metadata_reader.hpp" -#include "duckdb/storage/metadata/metadata_writer.hpp" -#include "duckdb/storage/buffer_manager.hpp" #include "duckdb/main/config.hpp" #include "duckdb/main/database.hpp" +#include "duckdb/storage/buffer_manager.hpp" +#include "duckdb/storage/metadata/metadata_reader.hpp" +#include "duckdb/storage/metadata/metadata_writer.hpp" #include #include @@ -62,7 +62,7 @@ MainHeader MainHeader::Read(ReadStream &source) { if (header.version_number != VERSION_NUMBER) { auto version = GetDuckDBVersion(header.version_number); string version_text; - if (version) { + if (!version.empty()) { // known version version_text = "DuckDB version " + string(version); } else { @@ -95,7 +95,7 @@ void DatabaseHeader::Write(WriteStream &ser) { ser.Write(meta_block); ser.Write(free_list); ser.Write(block_count); - ser.Write(block_size); + ser.Write(block_alloc_size); ser.Write(vector_size); } @@ -106,15 +106,10 @@ DatabaseHeader DatabaseHeader::Read(ReadStream &source) { header.free_list = source.Read(); header.block_count = source.Read(); - header.block_size = source.Read(); - if (!header.block_size) { + header.block_alloc_size = source.Read(); + if (!header.block_alloc_size) { // backwards compatibility - header.block_size = DEFAULT_BLOCK_ALLOC_SIZE; - } - if (header.block_size != Storage::BLOCK_ALLOC_SIZE) { - throw IOException("Cannot read database file: DuckDB's compiled block size is %llu bytes, but the file has a " - "block size of %llu bytes.", - Storage::BLOCK_ALLOC_SIZE, header.block_size); + header.block_alloc_size = DEFAULT_BLOCK_ALLOC_SIZE; } header.vector_size = source.Read(); @@ -143,8 +138,9 @@ T DeserializeHeaderStructure(data_ptr_t ptr) { return T::Read(source); } -SingleFileBlockManager::SingleFileBlockManager(AttachedDatabase &db, string path_p, StorageManagerOptions options) - : BlockManager(BufferManager::GetBufferManager(db)), db(db), path(std::move(path_p)), +SingleFileBlockManager::SingleFileBlockManager(AttachedDatabase &db, const string &path_p, + const StorageManagerOptions &options) + : BlockManager(BufferManager::GetBufferManager(db), options.block_alloc_size), db(db), path(path_p), header_buffer(Allocator::Get(db), FileBufferType::MANAGED_BUFFER, Storage::FILE_HEADER_SIZE - Storage::BLOCK_HEADER_SIZE), iteration_count(0), options(options) { @@ -198,20 +194,24 @@ void SingleFileBlockManager::CreateNewDatabase() { h1.meta_block = idx_t(INVALID_BLOCK); h1.free_list = idx_t(INVALID_BLOCK); h1.block_count = 0; - h1.block_size = Storage::BLOCK_ALLOC_SIZE; + // We create the SingleFileBlockManager with the desired block allocation size before calling CreateNewDatabase. + h1.block_alloc_size = GetBlockAllocSize(); h1.vector_size = STANDARD_VECTOR_SIZE; SerializeHeaderStructure(h1, header_buffer.buffer); ChecksumAndWrite(header_buffer, Storage::FILE_HEADER_SIZE); + // header 2 DatabaseHeader h2; h2.iteration = 0; h2.meta_block = idx_t(INVALID_BLOCK); h2.free_list = idx_t(INVALID_BLOCK); h2.block_count = 0; - h2.block_size = Storage::BLOCK_ALLOC_SIZE; + // We create the SingleFileBlockManager with the desired block allocation size before calling CreateNewDatabase. + h2.block_alloc_size = GetBlockAllocSize(); h2.vector_size = STANDARD_VECTOR_SIZE; SerializeHeaderStructure(h2, header_buffer.buffer); ChecksumAndWrite(header_buffer, Storage::FILE_HEADER_SIZE * 2ULL); + // ensure that writing to disk is completed before returning handle->Sync(); // we start with h2 as active_header, this way our initial write will be in h1 @@ -228,7 +228,7 @@ void SingleFileBlockManager::LoadExistingDatabase() { handle = fs.OpenFile(path, flags); if (!handle) { // this can only happen in read-only mode - as that is when we set FILE_FLAGS_NULL_IF_NOT_EXISTS - throw CatalogException("Cannot open database \"%s\" in read-only mode: database does not exist", path); + throw IOException("Cannot open database \"%s\" in read-only mode: database does not exist", path); } MainHeader::CheckMagicBytes(*handle); @@ -240,18 +240,20 @@ void SingleFileBlockManager::LoadExistingDatabase() { DatabaseHeader h1; ReadAndChecksum(header_buffer, Storage::FILE_HEADER_SIZE); h1 = DeserializeHeaderStructure(header_buffer.buffer); + DatabaseHeader h2; ReadAndChecksum(header_buffer, Storage::FILE_HEADER_SIZE * 2ULL); h2 = DeserializeHeaderStructure(header_buffer.buffer); + // check the header with the highest iteration count if (h1.iteration > h2.iteration) { // h1 is active header active_header = 0; - Initialize(h1); + Initialize(h1, GetOptionalBlockAllocSize()); } else { // h2 is active header active_header = 1; - Initialize(h2); + Initialize(h2, GetOptionalBlockAllocSize()); } LoadFreeList(); } @@ -266,8 +268,9 @@ void SingleFileBlockManager::ReadAndChecksum(FileBuffer &block, uint64_t locatio // verify the checksum if (stored_checksum != computed_checksum) { - throw IOException("Corrupt database file: computed checksum %llu does not match stored checksum %llu in block", - computed_checksum, stored_checksum); + throw IOException("Corrupt database file: computed checksum %llu does not match stored checksum %llu in block " + "at location %llu", + computed_checksum, stored_checksum, location); } } @@ -279,11 +282,26 @@ void SingleFileBlockManager::ChecksumAndWrite(FileBuffer &block, uint64_t locati block.Write(*handle, location); } -void SingleFileBlockManager::Initialize(DatabaseHeader &header) { +void SingleFileBlockManager::Initialize(const DatabaseHeader &header, const optional_idx block_alloc_size) { free_list_id = header.free_list; meta_block = header.meta_block; iteration_count = header.iteration; max_block = NumericCast(header.block_count); + + if (block_alloc_size.IsValid() && block_alloc_size.GetIndex() != header.block_alloc_size) { + throw InvalidInputException("cannot initialize the same database with a different block size: provided block " + "size: %llu, file block size: %llu", + GetBlockAllocSize(), header.block_alloc_size); + } + + // NOTE: remove this once we start supporting different block sizes. + if (Storage::BLOCK_ALLOC_SIZE != header.block_alloc_size) { + throw NotImplementedException("cannot initialize a database with a different block size than the default block " + "size: default block size: %llu, file block size: %llu", + Storage::BLOCK_ALLOC_SIZE, header.block_alloc_size); + } + + SetBlockAllocSize(header.block_alloc_size); } void SingleFileBlockManager::LoadFreeList() { @@ -319,8 +337,7 @@ block_id_t SingleFileBlockManager::GetFreeBlockId() { lock_guard lock(block_lock); block_id_t block; if (!free_list.empty()) { - // free list is non empty - // take an entry from the free list + // The free list is not empty, so we take its first element. block = *free_list.begin(); // erase the entry from the free list again free_list.erase(free_list.begin()); @@ -331,6 +348,15 @@ block_id_t SingleFileBlockManager::GetFreeBlockId() { return block; } +block_id_t SingleFileBlockManager::PeekFreeBlockId() { + lock_guard lock(block_lock); + if (!free_list.empty()) { + return *free_list.begin(); + } else { + return max_block; + } +} + void SingleFileBlockManager::MarkBlockAsFree(block_id_t block_id) { lock_guard lock(block_lock); D_ASSERT(block_id >= 0); @@ -394,8 +420,12 @@ idx_t SingleFileBlockManager::FreeBlocks() { return free_list.size(); } +bool SingleFileBlockManager::IsRemote() { + return !handle->OnDiskFile(); +} + unique_ptr SingleFileBlockManager::ConvertBlock(block_id_t block_id, FileBuffer &source_buffer) { - D_ASSERT(source_buffer.AllocSize() == Storage::BLOCK_ALLOC_SIZE); + D_ASSERT(source_buffer.AllocSize() == GetBlockAllocSize()); return make_uniq(source_buffer, block_id); } @@ -404,21 +434,50 @@ unique_ptr SingleFileBlockManager::CreateBlock(block_id_t block_id, FileB if (source_buffer) { result = ConvertBlock(block_id, *source_buffer); } else { - result = make_uniq(Allocator::Get(db), block_id); + result = make_uniq(Allocator::Get(db), block_id, GetBlockSize()); } result->Initialize(options.debug_initialize); return result; } +idx_t SingleFileBlockManager::GetBlockLocation(block_id_t block_id) { + return BLOCK_START + NumericCast(block_id) * GetBlockAllocSize(); +} + void SingleFileBlockManager::Read(Block &block) { D_ASSERT(block.id >= 0); D_ASSERT(std::find(free_list.begin(), free_list.end(), block.id) == free_list.end()); - ReadAndChecksum(block, BLOCK_START + NumericCast(block.id) * Storage::BLOCK_ALLOC_SIZE); + ReadAndChecksum(block, GetBlockLocation(block.id)); +} + +void SingleFileBlockManager::ReadBlocks(FileBuffer &buffer, block_id_t start_block, idx_t block_count) { + D_ASSERT(start_block >= 0); + D_ASSERT(block_count >= 1); + + // read the buffer from disk + auto location = GetBlockLocation(start_block); + buffer.Read(*handle, location); + + // for each of the blocks - verify the checksum + auto ptr = buffer.InternalBuffer(); + for (idx_t i = 0; i < block_count; i++) { + // compute the checksum + auto start_ptr = ptr + i * GetBlockAllocSize(); + auto stored_checksum = Load(start_ptr); + uint64_t computed_checksum = Checksum(start_ptr + Storage::BLOCK_HEADER_SIZE, GetBlockSize()); + // verify the checksum + if (stored_checksum != computed_checksum) { + throw IOException( + "Corrupt database file: computed checksum %llu does not match stored checksum %llu in block " + "at location %llu", + computed_checksum, stored_checksum, location + i * GetBlockAllocSize()); + } + } } void SingleFileBlockManager::Write(FileBuffer &buffer, block_id_t block_id) { D_ASSERT(block_id >= 0); - ChecksumAndWrite(buffer, BLOCK_START + NumericCast(block_id) * Storage::BLOCK_ALLOC_SIZE); + ChecksumAndWrite(buffer, BLOCK_START + NumericCast(block_id) * GetBlockAllocSize()); } void SingleFileBlockManager::Truncate() { @@ -440,15 +499,16 @@ void SingleFileBlockManager::Truncate() { // truncate the file free_list.erase(free_list.lower_bound(max_block), free_list.end()); newly_freed_list.erase(newly_freed_list.lower_bound(max_block), newly_freed_list.end()); - handle->Truncate(NumericCast(BLOCK_START + NumericCast(max_block) * Storage::BLOCK_ALLOC_SIZE)); + handle->Truncate(NumericCast(BLOCK_START + NumericCast(max_block) * GetBlockAllocSize())); } vector SingleFileBlockManager::GetFreeListBlocks() { vector free_list_blocks; + auto &metadata_manager = GetMetadataManager(); // reserve all blocks that we are going to write the free list to // since these blocks are no longer free we cannot just include them in the free list! - auto block_size = MetadataManager::METADATA_BLOCK_SIZE - sizeof(idx_t); + auto block_size = metadata_manager.GetMetadataBlockSize() - sizeof(idx_t); idx_t allocated_size = 0; while (true) { auto free_list_size = sizeof(uint64_t) + sizeof(block_id_t) * (free_list.size() + modified_blocks.size()); @@ -488,15 +548,17 @@ class FreeListBlockWriter : public MetadataWriter { }; void SingleFileBlockManager::WriteHeader(DatabaseHeader header) { - // set the iteration count - header.iteration = ++iteration_count; - auto free_list_blocks = GetFreeListBlocks(); // now handle the free list auto &metadata_manager = GetMetadataManager(); // add all modified blocks to the free list: they can now be written to again metadata_manager.MarkBlocksAsModified(); + + lock_guard lock(block_lock); + // set the iteration count + header.iteration = ++iteration_count; + for (auto &block : modified_blocks) { free_list.insert(block); newly_freed_list.insert(block); @@ -569,8 +631,8 @@ void SingleFileBlockManager::TrimFreeBlocks() { // We are now one too far. --itr; // Trim the range. - handle->Trim(BLOCK_START + (NumericCast(first) * Storage::BLOCK_ALLOC_SIZE), - NumericCast(last + 1 - first) * Storage::BLOCK_ALLOC_SIZE); + handle->Trim(BLOCK_START + (NumericCast(first) * GetBlockAllocSize()), + NumericCast(last + 1 - first) * GetBlockAllocSize()); } } newly_freed_list.clear(); diff --git a/src/storage/standard_buffer_manager.cpp b/src/storage/standard_buffer_manager.cpp index 43ee2cb03f7..70b7b196846 100644 --- a/src/storage/standard_buffer_manager.cpp +++ b/src/storage/standard_buffer_manager.cpp @@ -8,8 +8,8 @@ #include "duckdb/storage/buffer/buffer_pool.hpp" #include "duckdb/storage/in_memory_block_manager.hpp" #include "duckdb/storage/storage_manager.hpp" -#include "duckdb/storage/temporary_memory_manager.hpp" #include "duckdb/storage/temporary_file_manager.hpp" +#include "duckdb/storage/temporary_memory_manager.hpp" namespace duckdb { @@ -53,8 +53,8 @@ StandardBufferManager::StandardBufferManager(DatabaseInstance &db, string tmp) : BufferManager(), db(db), buffer_pool(db.GetBufferPool()), temporary_id(MAXIMUM_BLOCK), buffer_allocator(BufferAllocatorAllocate, BufferAllocatorFree, BufferAllocatorRealloc, make_uniq(*this)) { + temp_block_manager = make_uniq(*this, DEFAULT_BLOCK_ALLOC_SIZE); temporary_directory.path = std::move(tmp); - temp_block_manager = make_uniq(*this); for (idx_t i = 0; i < MEMORY_TAG_COUNT; i++) { evicted_data_per_tag[i] = 0; } @@ -107,17 +107,28 @@ TempBufferPoolReservation StandardBufferManager::EvictBlocksOrThrow(MemoryTag ta return std::move(r.reservation); } -shared_ptr StandardBufferManager::RegisterSmallMemory(idx_t block_size) { - D_ASSERT(block_size < Storage::BLOCK_SIZE); - auto reservation = - EvictBlocksOrThrow(MemoryTag::BASE_TABLE, block_size, nullptr, "could not allocate block of size %s%s", - StringUtil::BytesToHumanReadableString(block_size)); +shared_ptr StandardBufferManager::RegisterTransientMemory(const idx_t size) { + const idx_t block_size = Storage::BLOCK_SIZE; + D_ASSERT(size <= block_size); + if (size < block_size) { + return RegisterSmallMemory(size); + } - auto buffer = ConstructManagedBuffer(block_size, nullptr, FileBufferType::TINY_BUFFER); + shared_ptr block; + Allocate(MemoryTag::IN_MEMORY_TABLE, size, false, &block); + return block; +} + +shared_ptr StandardBufferManager::RegisterSmallMemory(const idx_t size) { + D_ASSERT(size < Storage::BLOCK_SIZE); + auto reservation = EvictBlocksOrThrow(MemoryTag::BASE_TABLE, size, nullptr, "could not allocate block of size %s%s", + StringUtil::BytesToHumanReadableString(size)); - // create a new block pointer for this block + auto buffer = ConstructManagedBuffer(size, nullptr, FileBufferType::TINY_BUFFER); + + // Create a new block pointer for this block. auto result = make_shared_ptr(*temp_block_manager, ++temporary_id, MemoryTag::BASE_TABLE, - std::move(buffer), false, block_size, std::move(reservation)); + std::move(buffer), false, size, std::move(reservation)); #ifdef DUCKDB_DEBUG_DESTROY_BLOCKS // Initialize the memory with garbage data WriteGarbageIntoBuffer(*result->buffer); @@ -128,14 +139,14 @@ shared_ptr StandardBufferManager::RegisterSmallMemory(idx_t block_s shared_ptr StandardBufferManager::RegisterMemory(MemoryTag tag, idx_t block_size, bool can_destroy) { D_ASSERT(block_size >= Storage::BLOCK_SIZE); auto alloc_size = GetAllocSize(block_size); - // first evict blocks until we have enough memory to store this buffer + + // Evict blocks until there is enough memory to store the buffer. unique_ptr reusable_buffer; auto res = EvictBlocksOrThrow(tag, alloc_size, &reusable_buffer, "could not allocate block of size %s%s", StringUtil::BytesToHumanReadableString(alloc_size)); + // Create a new buffer and a block to hold the buffer. auto buffer = ConstructManagedBuffer(block_size, std::move(reusable_buffer)); - - // create a new block pointer for this block return make_shared_ptr(*temp_block_manager, ++temporary_id, tag, std::move(buffer), can_destroy, alloc_size, std::move(res)); } @@ -184,51 +195,159 @@ void StandardBufferManager::ReAllocate(shared_ptr &handle, idx_t bl handle->ResizeBuffer(block_size, memory_delta); } +void StandardBufferManager::BatchRead(vector> &handles, const map &load_map, + block_id_t first_block, block_id_t last_block) { + auto &block_manager = handles[0]->block_manager; + idx_t block_count = NumericCast(last_block - first_block + 1); +#ifndef DUCKDB_ALTERNATIVE_VERIFY + if (block_count == 1) { + // prefetching with block_count == 1 has no performance impact since we can't batch reads + // skip the prefetch in this case + // we do it anyway if alternative_verify is on for extra testing + return; + } +#endif + + // allocate a buffer to hold the data of all of the blocks + auto intermediate_buffer = Allocate(MemoryTag::BASE_TABLE, block_count * Storage::BLOCK_SIZE); + // perform a batch read of the blocks into the buffer + block_manager.ReadBlocks(intermediate_buffer.GetFileBuffer(), first_block, block_count); + + // the blocks are read - now we need to assign them to the individual blocks + for (idx_t block_idx = 0; block_idx < block_count; block_idx++) { + block_id_t block_id = first_block + NumericCast(block_idx); + auto entry = load_map.find(block_id); + D_ASSERT(entry != load_map.end()); // if we allow gaps we might not return true here + auto &handle = handles[entry->second]; + + // reserve memory for the block + idx_t required_memory = handle->memory_usage; + unique_ptr reusable_buffer; + auto reservation = + EvictBlocksOrThrow(handle->tag, required_memory, &reusable_buffer, "failed to pin block of size %s%s", + StringUtil::BytesToHumanReadableString(required_memory)); + // now load the block from the buffer + // note that we discard the buffer handle - we do not keep it around + // the prefetching relies on the block handle being pinned again during the actual read before it is evicted + BufferHandle buf; + { + lock_guard lock(handle->lock); + if (handle->state == BlockState::BLOCK_LOADED) { + // the block is loaded already by another thread - free up the reservation and continue + reservation.Resize(0); + continue; + } + auto block_ptr = + intermediate_buffer.GetFileBuffer().InternalBuffer() + block_idx * Storage::BLOCK_ALLOC_SIZE; + buf = BlockHandle::LoadFromBuffer(handle, block_ptr, std::move(reusable_buffer)); + handle->readers = 1; + handle->memory_charge = std::move(reservation); + } + } +} + +void StandardBufferManager::Prefetch(vector> &handles) { + // figure out which set of blocks we should load + map to_be_loaded; + for (idx_t block_idx = 0; block_idx < handles.size(); block_idx++) { + auto &handle = handles[block_idx]; + lock_guard lock(handle->lock); + if (handle->state != BlockState::BLOCK_LOADED) { + // need to load this block - add it to the map + to_be_loaded.insert(make_pair(handle->BlockId(), block_idx)); + } + } + if (to_be_loaded.empty()) { + // nothing to fetch + return; + } + // iterate over the blocks and perform bulk reads + block_id_t first_block = -1; + block_id_t previous_block_id = -1; + for (auto &entry : to_be_loaded) { + if (previous_block_id < 0) { + // this the first block we are seeing + first_block = entry.first; + previous_block_id = first_block; + } else if (previous_block_id + 1 == entry.first) { + // this block is adjacent to the previous block - add it to the batch read + previous_block_id = entry.first; + } else { + // this block is not adjacent to the previous block + // perform the batch read for the previous batch + BatchRead(handles, to_be_loaded, first_block, previous_block_id); + + // set the first_block and previous_block_id to the current block + first_block = entry.first; + previous_block_id = entry.first; + } + } + // batch read the final batch + BatchRead(handles, to_be_loaded, first_block, previous_block_id); +} + BufferHandle StandardBufferManager::Pin(shared_ptr &handle) { + // we need to be careful not to return the BufferHandle to this block while holding the BlockHandle's lock + // as exiting this function's scope may cause the destructor of the BufferHandle to be called while holding the lock + // the destructor calls Unpin, which grabs the BlockHandle's lock again, causing a deadlock + BufferHandle buf; + idx_t required_memory; { // lock the block lock_guard lock(handle->lock); // check if the block is already loaded if (handle->state == BlockState::BLOCK_LOADED) { - // the block is loaded, increment the reader count and return a pointer to the handle + // the block is loaded, increment the reader count and set the BufferHandle handle->readers++; - return handle->Load(handle); + buf = handle->Load(handle); } required_memory = handle->memory_usage; } - // evict blocks until we have space for the current block - unique_ptr reusable_buffer; - auto reservation = - EvictBlocksOrThrow(handle->tag, required_memory, &reusable_buffer, "failed to pin block of size %s%s", - StringUtil::BytesToHumanReadableString(required_memory)); - // lock the handle again and repeat the check (in case anybody loaded in the meantime) - lock_guard lock(handle->lock); - // check if the block is already loaded - if (handle->state == BlockState::BLOCK_LOADED) { - // the block is loaded, increment the reader count and return a pointer to the handle - handle->readers++; - reservation.Resize(0); - return handle->Load(handle); - } - // now we can actually load the current block - D_ASSERT(handle->readers == 0); - handle->readers = 1; - auto buf = handle->Load(handle, std::move(reusable_buffer)); - handle->memory_charge = std::move(reservation); - // In the case of a variable sized block, the buffer may be smaller than a full block. - int64_t delta = NumericCast(handle->buffer->AllocSize()) - NumericCast(handle->memory_usage); - if (delta) { - D_ASSERT(delta < 0); - handle->memory_usage += NumericCast(delta); - handle->memory_charge.Resize(handle->memory_usage); + + if (buf.IsValid()) { + return buf; // the block was already loaded, return it without holding the BlockHandle's lock + } else { + // evict blocks until we have space for the current block + unique_ptr reusable_buffer; + auto reservation = + EvictBlocksOrThrow(handle->tag, required_memory, &reusable_buffer, "failed to pin block of size %s%s", + StringUtil::BytesToHumanReadableString(required_memory)); + + // lock the handle again and repeat the check (in case anybody loaded in the meantime) + lock_guard lock(handle->lock); + // check if the block is already loaded + if (handle->state == BlockState::BLOCK_LOADED) { + // the block is loaded, increment the reader count and return a pointer to the handle + handle->readers++; + reservation.Resize(0); + buf = handle->Load(handle); + } else { + // now we can actually load the current block + D_ASSERT(handle->readers == 0); + handle->readers = 1; + buf = handle->Load(handle, std::move(reusable_buffer)); + handle->memory_charge = std::move(reservation); + // in the case of a variable sized block, the buffer may be smaller than a full block. + int64_t delta = + NumericCast(handle->buffer->AllocSize()) - NumericCast(handle->memory_usage); + if (delta) { + D_ASSERT(delta < 0); + handle->memory_usage += static_cast(delta); + handle->memory_charge.Resize(handle->memory_usage); + } + D_ASSERT(handle->memory_usage == handle->buffer->AllocSize()); + } } - D_ASSERT(handle->memory_usage == handle->buffer->AllocSize()); + + // we should have a valid BufferHandle by now, either because the block was already loaded, or because we loaded it + // return it without holding the BlockHandle's lock + D_ASSERT(buf.IsValid()); return buf; } -void StandardBufferManager::PurgeQueue() { - buffer_pool.PurgeQueue(); +void StandardBufferManager::PurgeQueue(FileBufferType type) { + buffer_pool.PurgeQueue(type); } void StandardBufferManager::AddToEvictionQueue(shared_ptr &handle) { @@ -262,12 +381,15 @@ void StandardBufferManager::Unpin(shared_ptr &handle) { // We do not have to keep the handle locked while purging. if (purge) { - PurgeQueue(); + PurgeQueue(handle->buffer->type); } } void StandardBufferManager::SetMemoryLimit(idx_t limit) { buffer_pool.SetLimit(limit, InMemoryWarning()); + if (Allocator::SupportsFlush()) { + Allocator::FlushAll(); + } } void StandardBufferManager::SetSwapLimit(optional_idx limit) { @@ -320,17 +442,22 @@ void StandardBufferManager::RequireTemporaryDirectory() { } void StandardBufferManager::WriteTemporaryBuffer(MemoryTag tag, block_id_t block_id, FileBuffer &buffer) { + RequireTemporaryDirectory(); + + // Append to a few grouped files. if (buffer.size == Storage::BLOCK_SIZE) { evicted_data_per_tag[uint8_t(tag)] += Storage::BLOCK_SIZE; temporary_directory.handle->GetTempFile().WriteTemporaryBuffer(block_id, buffer); return; } - evicted_data_per_tag[uint8_t(tag)] += buffer.size; - // get the path to write to - auto path = GetTemporaryPath(block_id); + + // Get the path to write to. D_ASSERT(buffer.size > Storage::BLOCK_SIZE); - // create the file and write the size followed by the buffer contents + auto path = GetTemporaryPath(block_id); + evicted_data_per_tag[uint8_t(tag)] += buffer.size; + + // Create the file and write the size followed by the buffer contents. auto &fs = FileSystem::GetFileSystem(db); auto handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE); handle->Write(&buffer.size, sizeof(idx_t), 0); @@ -345,18 +472,20 @@ unique_ptr StandardBufferManager::ReadTemporaryBuffer(MemoryTag tag, evicted_data_per_tag[uint8_t(tag)] -= Storage::BLOCK_SIZE; return temporary_directory.handle->GetTempFile().ReadTemporaryBuffer(id, std::move(reusable_buffer)); } + + // Open the temporary file and read its size. idx_t block_size; - // open the temporary file and read the size auto path = GetTemporaryPath(id); auto &fs = FileSystem::GetFileSystem(db); auto handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_READ); handle->Read(&block_size, sizeof(idx_t), 0); evicted_data_per_tag[uint8_t(tag)] -= block_size; - // now allocate a buffer of this size and read the data into that buffer + // Allocate a buffer of the file's size and read the data into that buffer. auto buffer = ReadTemporaryBufferInternal(*this, *handle, sizeof(idx_t), block_size, std::move(reusable_buffer)); - handle.reset(); + + // Delete the file and return the buffer. DeleteTemporaryFile(id); return buffer; } @@ -408,9 +537,15 @@ vector StandardBufferManager::GetTemporaryFiles() { if (!StringUtil::EndsWith(name, ".block")) { return; } + + // Another process or thread can delete the file before we can get its file size. + auto handle = fs.OpenFile(name, FileFlags::FILE_FLAGS_READ | FileFlags::FILE_FLAGS_NULL_IF_NOT_EXISTS); + if (!handle) { + return; + } + TemporaryFileInformation info; info.path = name; - auto handle = fs.OpenFile(name, FileFlags::FILE_FLAGS_READ); info.size = NumericCast(fs.GetFileSize(*handle)); handle.reset(); result.push_back(info); diff --git a/src/storage/storage_info.cpp b/src/storage/storage_info.cpp index a8fd657bce6..c300edb13b4 100644 --- a/src/storage/storage_info.cpp +++ b/src/storage/storage_info.cpp @@ -1,5 +1,8 @@ #include "duckdb/storage/storage_info.hpp" +#include "duckdb/common/numeric_utils.hpp" +#include "duckdb/common/optional_idx.hpp" + namespace duckdb { const uint64_t VERSION_NUMBER = 64; @@ -9,33 +12,99 @@ struct StorageVersionInfo { idx_t storage_version; }; -static const StorageVersionInfo storage_version_info[] = {{"v0.9.0, v0.9.1, v0.9.2 or v0.10.0", 64}, - {"v0.8.0 or v0.8.1", 51}, - {"v0.7.0 or v0.7.1", 43}, - {"v0.6.0 or v0.6.1", 39}, - {"v0.5.0 or v0.5.1", 38}, - {"v0.3.3, v0.3.4 or v0.4.0", 33}, - {"v0.3.2", 31}, - {"v0.3.1", 27}, - {"v0.3.0", 25}, - {"v0.2.9", 21}, - {"v0.2.8", 18}, - {"v0.2.7", 17}, - {"v0.2.6", 15}, - {"v0.2.5", 13}, - {"v0.2.4", 11}, - {"v0.2.3", 6}, - {"v0.2.2", 4}, - {"v0.2.1 and prior", 1}, - {nullptr, 0}}; - -const char *GetDuckDBVersion(idx_t version_number) { +struct SerializationVersionInfo { + const char *version_name; + idx_t serialization_version; +}; + +// These sections are automatically generated by scripts/generate_storage_info.py +// Do not edit them manually, your changes will be overwritten + +// START OF STORAGE VERSION INFO +static const StorageVersionInfo storage_version_info[] = { + {"v0.0.4", 1}, {"v0.1.0", 1}, {"v0.1.1", 1}, {"v0.1.2", 1}, {"v0.1.3", 1}, {"v0.1.4", 1}, {"v0.1.5", 1}, + {"v0.1.6", 1}, {"v0.1.7", 1}, {"v0.1.8", 1}, {"v0.1.9", 1}, {"v0.2.0", 1}, {"v0.2.1", 1}, {"v0.2.2", 4}, + {"v0.2.3", 6}, {"v0.2.4", 11}, {"v0.2.5", 13}, {"v0.2.6", 15}, {"v0.2.7", 17}, {"v0.2.8", 18}, {"v0.2.9", 21}, + {"v0.3.0", 25}, {"v0.3.1", 27}, {"v0.3.2", 31}, {"v0.3.3", 33}, {"v0.3.4", 33}, {"v0.3.5", 33}, {"v0.4.0", 33}, + {"v0.5.0", 38}, {"v0.5.1", 38}, {"v0.6.0", 39}, {"v0.6.1", 39}, {"v0.7.0", 43}, {"v0.7.1", 43}, {"v0.8.0", 51}, + {"v0.8.1", 51}, {"v0.9.0", 64}, {"v0.9.1", 64}, {"v0.9.2", 64}, {"v0.10.0", 64}, {"v0.10.1", 64}, {"v0.10.2", 64}, + {nullptr, 0}}; +// END OF STORAGE VERSION INFO + +// START OF SERIALIZATION VERSION INFO +static const SerializationVersionInfo serialization_version_info[] = { + {"v0.10.0", 1}, {"v0.10.1", 1}, {"v0.10.2", 1}, {"latest", 2}, {nullptr, 0}}; +// END OF SERIALIZATION VERSION INFO + +optional_idx GetStorageVersion(const char *version_string) { + for (idx_t i = 0; storage_version_info[i].version_name; i++) { + if (!strcmp(storage_version_info[i].version_name, version_string)) { + return storage_version_info[i].storage_version; + } + } + return optional_idx(); +} + +optional_idx GetSerializationVersion(const char *version_string) { + for (idx_t i = 0; serialization_version_info[i].version_name; i++) { + if (!strcmp(serialization_version_info[i].version_name, version_string)) { + return serialization_version_info[i].serialization_version; + } + } + return optional_idx(); +} + +vector GetSerializationCandidates() { + vector candidates; + for (idx_t i = 0; serialization_version_info[i].version_name; i++) { + candidates.push_back(serialization_version_info[i].version_name); + } + return candidates; +} + +string GetDuckDBVersion(idx_t version_number) { + vector versions; for (idx_t i = 0; storage_version_info[i].version_name; i++) { if (version_number == storage_version_info[i].storage_version) { - return storage_version_info[i].version_name; + versions.push_back(string(storage_version_info[i].version_name)); + } + } + if (versions.empty()) { + return string(); + } + string result; + for (idx_t i = 0; i < versions.size(); i++) { + string sep = ""; + if (i) { + sep = i + 1 == versions.size() ? " or " : ", "; } + result += sep; + result += versions[i]; + } + return result; +} + +void Storage::VerifyBlockAllocSize(const idx_t block_alloc_size) { + if (!IsPowerOfTwo(block_alloc_size)) { + throw InvalidInputException("the block size must be a power of two, got %llu", block_alloc_size); + } + if (block_alloc_size < MIN_BLOCK_ALLOC_SIZE) { + throw InvalidInputException( + "the block size must be greater or equal than the minimum block size of %llu, got %llu", + MIN_BLOCK_ALLOC_SIZE, block_alloc_size); + } + auto max_value = NumericCast(NumericLimits().Maximum()); + if (block_alloc_size > max_value) { + throw InvalidInputException( + "the block size must not be greater than the maximum 32-bit signed integer value of %llu, got %llu", + max_value, block_alloc_size); + } + // NOTE: remove this once we start supporting different block sizes. + if (block_alloc_size != BLOCK_ALLOC_SIZE) { + throw NotImplementedException( + "other block sizes than the default block size are not supported, expected %llu, got %llu", + BLOCK_ALLOC_SIZE, block_alloc_size); } - return nullptr; } } // namespace duckdb diff --git a/src/storage/storage_lock.cpp b/src/storage/storage_lock.cpp index 1b7b157760f..9b7cafb8b79 100644 --- a/src/storage/storage_lock.cpp +++ b/src/storage/storage_lock.cpp @@ -4,41 +4,101 @@ namespace duckdb { -StorageLockKey::StorageLockKey(StorageLock &lock, StorageLockType type) : lock(lock), type(type) { +struct StorageLockInternals : enable_shared_from_this { +public: + StorageLockInternals() : read_count(0) { + } + + mutex exclusive_lock; + atomic read_count; + +public: + unique_ptr GetExclusiveLock() { + exclusive_lock.lock(); + while (read_count != 0) { + } + return make_uniq(shared_from_this(), StorageLockType::EXCLUSIVE); + } + + unique_ptr GetSharedLock() { + exclusive_lock.lock(); + read_count++; + exclusive_lock.unlock(); + return make_uniq(shared_from_this(), StorageLockType::SHARED); + } + + unique_ptr TryGetExclusiveLock() { + if (!exclusive_lock.try_lock()) { + // could not lock mutex + return nullptr; + } + if (read_count != 0) { + // there are active readers - cannot get exclusive lock + exclusive_lock.unlock(); + return nullptr; + } + // success! + return make_uniq(shared_from_this(), StorageLockType::EXCLUSIVE); + } + + unique_ptr TryUpgradeCheckpointLock(StorageLockKey &lock) { + if (lock.GetType() != StorageLockType::SHARED) { + throw InternalException("StorageLock::TryUpgradeLock called on an exclusive lock"); + } + if (!exclusive_lock.try_lock()) { + // could not lock mutex + return nullptr; + } + if (read_count != 1) { + // other shared locks are active: failed to upgrade + D_ASSERT(read_count != 0); + exclusive_lock.unlock(); + return nullptr; + } + // no other shared locks active: success! + return make_uniq(shared_from_this(), StorageLockType::EXCLUSIVE); + } + + void ReleaseExclusiveLock() { + exclusive_lock.unlock(); + } + void ReleaseSharedLock() { + read_count--; + } +}; + +StorageLockKey::StorageLockKey(shared_ptr internals_p, StorageLockType type) + : internals(std::move(internals_p)), type(type) { } StorageLockKey::~StorageLockKey() { if (type == StorageLockType::EXCLUSIVE) { - lock.ReleaseExclusiveLock(); + internals->ReleaseExclusiveLock(); } else { D_ASSERT(type == StorageLockType::SHARED); - lock.ReleaseSharedLock(); + internals->ReleaseSharedLock(); } } -StorageLock::StorageLock() : read_count(0) { +StorageLock::StorageLock() : internals(make_shared_ptr()) { +} +StorageLock::~StorageLock() { } unique_ptr StorageLock::GetExclusiveLock() { - exclusive_lock.lock(); - while (read_count != 0) { - } - return make_uniq(*this, StorageLockType::EXCLUSIVE); + return internals->GetExclusiveLock(); } -unique_ptr StorageLock::GetSharedLock() { - exclusive_lock.lock(); - read_count++; - exclusive_lock.unlock(); - return make_uniq(*this, StorageLockType::SHARED); +unique_ptr StorageLock::TryGetExclusiveLock() { + return internals->TryGetExclusiveLock(); } -void StorageLock::ReleaseExclusiveLock() { - exclusive_lock.unlock(); +unique_ptr StorageLock::GetSharedLock() { + return internals->GetSharedLock(); } -void StorageLock::ReleaseSharedLock() { - read_count--; +unique_ptr StorageLock::TryUpgradeCheckpointLock(StorageLockKey &lock) { + return internals->TryUpgradeCheckpointLock(lock); } } // namespace duckdb diff --git a/src/storage/storage_manager.cpp b/src/storage/storage_manager.cpp index 7d7a92ff483..389c27cc843 100644 --- a/src/storage/storage_manager.cpp +++ b/src/storage/storage_manager.cpp @@ -1,29 +1,32 @@ #include "duckdb/storage/storage_manager.hpp" -#include "duckdb/storage/checkpoint_manager.hpp" -#include "duckdb/storage/in_memory_block_manager.hpp" -#include "duckdb/storage/single_file_block_manager.hpp" -#include "duckdb/storage/object_cache.hpp" #include "duckdb/catalog/catalog.hpp" #include "duckdb/common/file_system.hpp" -#include "duckdb/main/database.hpp" -#include "duckdb/main/client_context.hpp" -#include "duckdb/function/function.hpp" -#include "duckdb/transaction/transaction_manager.hpp" #include "duckdb/common/serializer/buffered_file_reader.hpp" +#include "duckdb/function/function.hpp" #include "duckdb/main/attached_database.hpp" +#include "duckdb/main/client_context.hpp" +#include "duckdb/main/database.hpp" #include "duckdb/main/database_manager.hpp" +#include "duckdb/storage/checkpoint_manager.hpp" +#include "duckdb/storage/in_memory_block_manager.hpp" +#include "duckdb/storage/object_cache.hpp" +#include "duckdb/storage/single_file_block_manager.hpp" +#include "duckdb/transaction/transaction_manager.hpp" + +#include "duckdb/storage/storage_extension.hpp" namespace duckdb { StorageManager::StorageManager(AttachedDatabase &db, string path_p, bool read_only) : db(db), path(std::move(path_p)), read_only(read_only) { + if (path.empty()) { path = IN_MEMORY_PATH; - } else { - auto &fs = FileSystem::Get(db); - this->path = fs.ExpandPath(path); + return; } + auto &fs = FileSystem::Get(db); + path = fs.ExpandPath(path); } StorageManager::~StorageManager() { @@ -56,20 +59,34 @@ bool ObjectCache::ObjectCacheEnabled(ClientContext &context) { return context.db->config.options.object_cache_enable; } -optional_ptr StorageManager::GetWriteAheadLog() { +idx_t StorageManager::GetWALSize() { + auto wal_ptr = GetWAL(); + if (!wal_ptr) { + return 0; + } + return wal_ptr->GetWALSize(); +} + +optional_ptr StorageManager::GetWAL() { if (InMemory() || read_only || !load_complete) { return nullptr; } - if (wal) { - return wal.get(); + if (!wal) { + auto wal_path = GetWALPath(); + wal = make_uniq(db, wal_path); } - - // lazy WAL creation - wal = make_uniq(db, GetWALPath()); return wal.get(); } +void StorageManager::ResetWAL() { + auto wal_ptr = GetWAL(); + if (wal_ptr) { + wal_ptr->Delete(); + } + wal.reset(); +} + string StorageManager::GetWALPath() { std::size_t question_mark_pos = path.find('?'); @@ -87,14 +104,14 @@ bool StorageManager::InMemory() { return path == IN_MEMORY_PATH; } -void StorageManager::Initialize(optional_ptr context) { +void StorageManager::Initialize(const optional_idx block_alloc_size) { bool in_memory = InMemory(); if (in_memory && read_only) { throw CatalogException("Cannot launch in-memory database in read-only mode!"); } - // create or load the database from disk, if not in-memory mode - LoadDatabase(context); + // Create or load the database from disk, if not in-memory mode. + LoadDatabase(block_alloc_size); } /////////////////////////////////////////////////////////////////////////// @@ -121,9 +138,13 @@ SingleFileStorageManager::SingleFileStorageManager(AttachedDatabase &db, string : StorageManager(db, std::move(path), read_only) { } -void SingleFileStorageManager::LoadDatabase(optional_ptr context) { +void SingleFileStorageManager::LoadDatabase(const optional_idx block_alloc_size) { if (InMemory()) { - block_manager = make_uniq(BufferManager::GetBufferManager(db)); + // NOTE: this becomes DEFAULT_BLOCK_ALLOC_SIZE once we start supporting different block sizes. + if (block_alloc_size.IsValid() && block_alloc_size.GetIndex() != Storage::BLOCK_ALLOC_SIZE) { + throw InternalException("in-memory databases must have the compiled block allocation size"); + } + block_manager = make_uniq(BufferManager::GetBufferManager(db), DEFAULT_BLOCK_ALLOC_SIZE); table_io_manager = make_uniq(*block_manager); return; } @@ -141,7 +162,8 @@ void SingleFileStorageManager::LoadDatabase(optional_ptr context) options.use_direct_io = config.options.use_direct_io; options.debug_initialize = config.options.debug_initialize; - // first check if the database exists + // Check if the database file already exists. + // Note: a file can also exist if there was a ROLLBACK on a previous transaction creating that file. if (!read_only && !fs.FileExists(path)) { // file does not exist and we are in read-write mode // create a new file @@ -154,16 +176,28 @@ void SingleFileStorageManager::LoadDatabase(optional_ptr context) fs.RemoveFile(wal_path); } - // initialize the block manager while creating a new db file + // Set the block allocation size for the new database file. + if (block_alloc_size.IsValid()) { + // Use the option provided by the user. + options.block_alloc_size = block_alloc_size; + } else { + // No explicit option provided: use the default option. + options.block_alloc_size = config.options.default_block_alloc_size; + } + + // Initialize the block manager before creating a new database. auto sf_block_manager = make_uniq(db, path, options); sf_block_manager->CreateNewDatabase(); block_manager = std::move(sf_block_manager); table_io_manager = make_uniq(*block_manager); + } else { - // either the file exists, or we are in read-only mode - // try to read the existing file on disk + // Either the file exists, or we are in read-only mode, so we + // try to read the existing file on disk. - // initialize the block manager while loading the current db file + // Initialize the block manager while loading the database file. + // We'll construct the SingleFileBlockManager with the default block allocation size, + // and later adjust it when reading the file header. auto sf_block_manager = make_uniq(db, path, options); sf_block_manager->LoadExistingDatabase(); block_manager = std::move(sf_block_manager); @@ -171,7 +205,7 @@ void SingleFileStorageManager::LoadDatabase(optional_ptr context) // load the db from storage auto checkpoint_reader = SingleFileCheckpointReader(*this); - checkpoint_reader.LoadFromStorage(context); + checkpoint_reader.LoadFromStorage(); // check if the WAL file exists auto wal_path = GetWALPath(); @@ -189,92 +223,94 @@ void SingleFileStorageManager::LoadDatabase(optional_ptr context) /////////////////////////////////////////////////////////////////////////////// -class SingleFileStorageCommitState : public StorageCommitState { - idx_t initial_wal_size = 0; - idx_t initial_written = 0; - optional_ptr log; - bool checkpoint; +enum class WALCommitState { IN_PROGRESS, FLUSHED, TRUNCATED }; +class SingleFileStorageCommitState : public StorageCommitState { public: - SingleFileStorageCommitState(StorageManager &storage_manager, bool checkpoint); - ~SingleFileStorageCommitState() override { - // If log is non-null, then commit threw an exception before flushing. - if (log) { - auto &wal = *log.get(); - wal.skip_writing = false; - if (wal.GetTotalWritten() > initial_written) { - // remove any entries written into the WAL by truncating it - wal.Truncate(NumericCast(initial_wal_size)); - } - } - } + SingleFileStorageCommitState(StorageManager &storage, WriteAheadLog &log); + ~SingleFileStorageCommitState() override; + //! Revert the commit + void RevertCommit() override; // Make the commit persistent void FlushCommit() override; + +private: + idx_t initial_wal_size = 0; + idx_t initial_written = 0; + WriteAheadLog &wal; + WALCommitState state; }; -SingleFileStorageCommitState::SingleFileStorageCommitState(StorageManager &storage_manager, bool checkpoint) - : checkpoint(checkpoint) { - log = storage_manager.GetWriteAheadLog(); - if (log) { - auto initial_size = log->GetWALSize(); - initial_written = log->GetTotalWritten(); - initial_wal_size = initial_size < 0 ? 0 : idx_t(initial_size); - - if (checkpoint) { - // check if we are checkpointing after this commit - // if we are checkpointing, we don't need to write anything to the WAL - // this saves us a lot of unnecessary writes to disk in the case of large commits - log->skip_writing = true; - } - } else { - D_ASSERT(!checkpoint); +SingleFileStorageCommitState::SingleFileStorageCommitState(StorageManager &storage, WriteAheadLog &wal) + : wal(wal), state(WALCommitState::IN_PROGRESS) { + auto initial_size = storage.GetWALSize(); + initial_written = wal.GetTotalWritten(); + initial_wal_size = initial_size; +} + +SingleFileStorageCommitState::~SingleFileStorageCommitState() { + if (state != WALCommitState::IN_PROGRESS) { + return; } + try { + // truncate the WAL in case of a destructor + RevertCommit(); + } catch (...) { // NOLINT + } +} + +void SingleFileStorageCommitState::RevertCommit() { + if (state != WALCommitState::IN_PROGRESS) { + return; + } + if (wal.GetTotalWritten() > initial_written) { + // remove any entries written into the WAL by truncating it + wal.Truncate(initial_wal_size); + } + state = WALCommitState::TRUNCATED; } -// Make the commit persistent void SingleFileStorageCommitState::FlushCommit() { - if (log) { - // flush the WAL if any changes were made - if (log->GetTotalWritten() > initial_written) { - (void)checkpoint; - D_ASSERT(!checkpoint); - D_ASSERT(!log->skip_writing); - log->Flush(); - } - log->skip_writing = false; + if (state != WALCommitState::IN_PROGRESS) { + return; } - // Null so that the destructor will not truncate the log. - log = nullptr; + wal.Flush(); + state = WALCommitState::FLUSHED; } -unique_ptr SingleFileStorageManager::GenStorageCommitState(Transaction &transaction, - bool checkpoint) { - return make_uniq(*this, checkpoint); +unique_ptr SingleFileStorageManager::GenStorageCommitState(WriteAheadLog &wal) { + return make_uniq(*this, wal); } bool SingleFileStorageManager::IsCheckpointClean(MetaBlockPointer checkpoint_id) { return block_manager->IsRootBlock(checkpoint_id); } -void SingleFileStorageManager::CreateCheckpoint(bool delete_wal, bool force_checkpoint) { - if (InMemory() || read_only || !wal) { +void SingleFileStorageManager::CreateCheckpoint(CheckpointOptions options) { + if (InMemory() || read_only || !load_complete) { return; } + if (db.GetStorageExtension()) { + db.GetStorageExtension()->OnCheckpointStart(db, options); + } auto &config = DBConfig::Get(db); - if (wal->GetWALSize() > 0 || config.options.force_checkpoint || force_checkpoint) { + if (GetWALSize() > 0 || config.options.force_checkpoint || options.action == CheckpointAction::FORCE_CHECKPOINT) { // we only need to checkpoint if there is anything in the WAL try { - SingleFileCheckpointWriter checkpointer(db, *block_manager); + SingleFileCheckpointWriter checkpointer(db, *block_manager, options.type); checkpointer.CreateCheckpoint(); } catch (std::exception &ex) { ErrorData error(ex); throw FatalException("Failed to create checkpoint because of error: %s", error.RawMessage()); } } - if (delete_wal) { - wal->Delete(); - wal.reset(); + if (options.wal_action == CheckpointWALAction::DELETE_WAL) { + ResetWAL(); + } + + if (db.GetStorageExtension()) { + db.GetStorageExtension()->OnCheckpointEnd(db, options); } } @@ -287,9 +323,7 @@ DatabaseSize SingleFileStorageManager::GetDatabaseSize() { ds.free_blocks = block_manager->FreeBlocks(); ds.used_blocks = ds.total_blocks - ds.free_blocks; ds.bytes = (ds.total_blocks * ds.block_size); - if (auto wal = GetWriteAheadLog()) { - ds.wal_size = NumericCast(wal->GetWALSize()); - } + ds.wal_size = NumericCast(GetWALSize()); } return ds; } @@ -300,15 +334,9 @@ vector SingleFileStorageManager::GetMetadataInfo() { } bool SingleFileStorageManager::AutomaticCheckpoint(idx_t estimated_wal_bytes) { - auto log = GetWriteAheadLog(); - if (!log) { - return false; - } - - auto &config = DBConfig::Get(db); - auto initial_size = NumericCast(log->GetWALSize()); + auto initial_size = NumericCast(GetWALSize()); idx_t expected_wal_size = initial_size + estimated_wal_bytes; - return expected_wal_size > config.options.checkpoint_wal_size; + return expected_wal_size > DBConfig::Get(db).options.checkpoint_wal_size; } shared_ptr SingleFileStorageManager::GetTableIOManager(BoundCreateTableInfo *info /*info*/) { diff --git a/src/storage/table/array_column_data.cpp b/src/storage/table/array_column_data.cpp index be8b8a219c8..af9a54f028e 100644 --- a/src/storage/table/array_column_data.cpp +++ b/src/storage/table/array_column_data.cpp @@ -30,6 +30,13 @@ bool ArrayColumnData::CheckZonemap(ColumnScanState &state, TableFilter &filter) return false; } +void ArrayColumnData::InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state, idx_t rows) { + ColumnData::InitializePrefetch(prefetch_state, scan_state, rows); + validity.InitializePrefetch(prefetch_state, scan_state.child_states[0], rows); + auto array_size = ArrayType::GetSize(type); + child_column->InitializePrefetch(prefetch_state, scan_state.child_states[1], rows * array_size); +} + void ArrayColumnData::InitializeScan(ColumnScanState &state) { // initialize the validity segment D_ASSERT(state.child_states.size() == 2); @@ -67,12 +74,14 @@ void ArrayColumnData::InitializeScanWithOffset(ColumnScanState &state, idx_t row } } -idx_t ArrayColumnData::Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result) { - return ScanCount(state, result, STANDARD_VECTOR_SIZE); +idx_t ArrayColumnData::Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t scan_count) { + return ScanCount(state, result, scan_count); } -idx_t ArrayColumnData::ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates) { - return ScanCount(state, result, STANDARD_VECTOR_SIZE); +idx_t ArrayColumnData::ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates, + idx_t scan_count) { + return ScanCount(state, result, scan_count); } idx_t ArrayColumnData::ScanCount(ColumnScanState &state, Vector &result, idx_t count) { @@ -203,12 +212,11 @@ unique_ptr ArrayColumnData::CreateCheckpointState(RowGrou } unique_ptr ArrayColumnData::Checkpoint(RowGroup &row_group, - PartialBlockManager &partial_block_manager, ColumnCheckpointInfo &checkpoint_info) { - auto checkpoint_state = make_uniq(row_group, *this, partial_block_manager); - checkpoint_state->validity_state = validity.Checkpoint(row_group, partial_block_manager, checkpoint_info); - checkpoint_state->child_state = child_column->Checkpoint(row_group, partial_block_manager, checkpoint_info); + auto checkpoint_state = make_uniq(row_group, *this, checkpoint_info.info.manager); + checkpoint_state->validity_state = validity.Checkpoint(row_group, checkpoint_info); + checkpoint_state->child_state = child_column->Checkpoint(row_group, checkpoint_info); return std::move(checkpoint_state); } @@ -219,7 +227,7 @@ void ArrayColumnData::DeserializeColumn(Deserializer &deserializer, BaseStatisti auto &child_stats = ArrayStats::GetChildStats(target_stats); deserializer.ReadObject(102, "child_column", [&](Deserializer &source) { child_column->DeserializeColumn(source, child_stats); }); - this->count = validity.count; + this->count = validity.count.load(); } void ArrayColumnData::GetColumnSegmentInfo(idx_t row_group_index, vector col_path, diff --git a/src/storage/table/column_checkpoint_state.cpp b/src/storage/table/column_checkpoint_state.cpp index 2c5d27e8239..a44729908bc 100644 --- a/src/storage/table/column_checkpoint_state.cpp +++ b/src/storage/table/column_checkpoint_state.cpp @@ -114,6 +114,7 @@ void PartialBlockForCheckpoint::Clear() { void ColumnCheckpointState::FlushSegment(unique_ptr segment, idx_t segment_size) { D_ASSERT(segment_size <= Storage::BLOCK_SIZE); + auto tuple_count = segment->count.load(); if (tuple_count == 0) { // LCOV_EXCL_START return; @@ -167,8 +168,8 @@ void ColumnCheckpointState::FlushSegment(unique_ptr segment, idx_ // constant block: no need to write anything to disk besides the stats // set up the compression function to constant auto &config = DBConfig::GetConfig(db); - segment->function = - *config.GetCompressionFunction(CompressionType::COMPRESSION_CONSTANT, segment->type.InternalType()); + CompressionInfo compression_info(Storage::BLOCK_SIZE, segment->type.InternalType()); + segment->function = *config.GetCompressionFunction(CompressionType::COMPRESSION_CONSTANT, compression_info); segment->ConvertToPersistent(nullptr, INVALID_BLOCK); } diff --git a/src/storage/table/column_data.cpp b/src/storage/table/column_data.cpp index cc68b462529..d23d563121d 100644 --- a/src/storage/table/column_data.cpp +++ b/src/storage/table/column_data.cpp @@ -43,7 +43,7 @@ void ColumnData::SetStart(idx_t new_start) { } DatabaseInstance &ColumnData::GetDatabase() const { - return info.db.GetDatabase(); + return info.GetDB().GetDatabase(); } DataTableInfo &ColumnData::GetTableInfo() const { @@ -91,7 +91,51 @@ void ColumnData::InitializeScanWithOffset(ColumnScanState &state, idx_t row_idx) state.last_offset = 0; } -idx_t ColumnData::ScanVector(ColumnScanState &state, Vector &result, idx_t remaining, bool has_updates) { +ScanVectorType ColumnData::GetVectorScanType(ColumnScanState &state, idx_t scan_count) { + if (HasUpdates()) { + // if we have updates we need to merge in the updates + // always need to scan flat vectors + return ScanVectorType::SCAN_FLAT_VECTOR; + } + // check if the current segment has enough data remaining + idx_t remaining_in_segment = state.current->start + state.current->count - state.row_index; + if (remaining_in_segment < scan_count) { + // there is not enough data remaining in the current segment so we need to scan across segments + // we need flat vectors here + return ScanVectorType::SCAN_FLAT_VECTOR; + } + return ScanVectorType::SCAN_ENTIRE_VECTOR; +} + +void ColumnData::InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state, idx_t remaining) { + auto current_segment = scan_state.current; + if (!current_segment) { + return; + } + if (!scan_state.initialized) { + // need to prefetch for the current segment if we have not yet initialized the scan for this segment + scan_state.current->InitializePrefetch(prefetch_state, scan_state); + } + idx_t row_index = scan_state.row_index; + while (remaining > 0) { + idx_t scan_count = MinValue(remaining, current_segment->start + current_segment->count - row_index); + remaining -= scan_count; + row_index += scan_count; + if (remaining > 0) { + auto next = data.GetNextSegment(current_segment); + if (!next) { + break; + } + next->InitializePrefetch(prefetch_state, scan_state); + current_segment = next; + } + } +} + +idx_t ColumnData::ScanVector(ColumnScanState &state, Vector &result, idx_t remaining, ScanVectorType scan_type) { + if (scan_type == ScanVectorType::SCAN_FLAT_VECTOR && result.GetVectorType() != VectorType::FLAT_VECTOR) { + throw InternalException("ScanVector called with SCAN_FLAT_VECTOR but result is not a flat vector"); + } state.previous_states.clear(); if (!state.initialized) { D_ASSERT(state.current); @@ -119,8 +163,7 @@ idx_t ColumnData::ScanVector(ColumnScanState &state, Vector &result, idx_t remai result_offset + i); } } else { - state.current->Scan(state, scan_count, result, result_offset, - !has_updates && scan_count == initial_remaining); + state.current->Scan(state, scan_count, result, result_offset, scan_type); } state.row_index += scan_count; @@ -184,42 +227,58 @@ void ColumnData::UpdateInternal(TransactionData transaction, idx_t column_index, } template -idx_t ColumnData::ScanVector(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result) { - idx_t current_row = vector_index * STANDARD_VECTOR_SIZE; - auto vector_count = MinValue(STANDARD_VECTOR_SIZE, count - current_row); - - auto scan_count = ScanVector(state, result, vector_count, HasUpdates()); +idx_t ColumnData::ScanVector(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t target_scan) { + auto scan_count = ScanVector(state, result, target_scan, GetVectorScanType(state, target_scan)); FetchUpdates(transaction, vector_index, result, scan_count, ALLOW_UPDATES, SCAN_COMMITTED); return scan_count; } template idx_t ColumnData::ScanVector(TransactionData transaction, idx_t vector_index, - ColumnScanState &state, Vector &result); + ColumnScanState &state, Vector &result, idx_t target_scan); template idx_t ColumnData::ScanVector(TransactionData transaction, idx_t vector_index, - ColumnScanState &state, Vector &result); + ColumnScanState &state, Vector &result, idx_t target_scan); template idx_t ColumnData::ScanVector(TransactionData transaction, idx_t vector_index, - ColumnScanState &state, Vector &result); + ColumnScanState &state, Vector &result, idx_t target_scan); template idx_t ColumnData::ScanVector(TransactionData transaction, idx_t vector_index, - ColumnScanState &state, Vector &result); + ColumnScanState &state, Vector &result, idx_t target_scan); idx_t ColumnData::Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result) { - return ScanVector(transaction, vector_index, state, result); + auto target_count = GetVectorCount(vector_index); + return Scan(transaction, vector_index, state, result, target_count); } idx_t ColumnData::ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates) { + auto target_count = GetVectorCount(vector_index); + return ScanCommitted(vector_index, state, result, allow_updates, target_count); +} + +idx_t ColumnData::Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t scan_count) { + return ScanVector(transaction, vector_index, state, result, scan_count); +} + +idx_t ColumnData::ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates, + idx_t scan_count) { if (allow_updates) { - return ScanVector(TransactionData(0, 0), vector_index, state, result); + return ScanVector(TransactionData(0, 0), vector_index, state, result, scan_count); } else { - return ScanVector(TransactionData(0, 0), vector_index, state, result); + return ScanVector(TransactionData(0, 0), vector_index, state, result, scan_count); } } +idx_t ColumnData::GetVectorCount(idx_t vector_index) const { + idx_t current_row = vector_index * STANDARD_VECTOR_SIZE; + return MinValue(STANDARD_VECTOR_SIZE, count - current_row); +} + void ColumnData::ScanCommittedRange(idx_t row_group_start, idx_t offset_in_row_group, idx_t s_count, Vector &result) { ColumnScanState child_state; InitializeScanWithOffset(child_state, row_group_start + offset_in_row_group); bool has_updates = HasUpdates(); - auto scan_count = ScanVector(child_state, result, s_count, has_updates); + auto scan_count = ScanVector(child_state, result, s_count, ScanVectorType::SCAN_FLAT_VECTOR); if (has_updates) { + D_ASSERT(result.GetVectorType() == VectorType::FLAT_VECTOR); result.Flatten(scan_count); updates->FetchCommittedRange(offset_in_row_group, s_count, result); } @@ -231,7 +290,7 @@ idx_t ColumnData::ScanCount(ColumnScanState &state, Vector &result, idx_t scan_c } // ScanCount can only be used if there are no updates D_ASSERT(!HasUpdates()); - return ScanVector(state, result, scan_count, false); + return ScanVector(state, result, scan_count, ScanVectorType::SCAN_FLAT_VECTOR); } void ColumnData::Select(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, @@ -261,7 +320,7 @@ void ColumnData::Skip(ColumnScanState &state, idx_t s_count) { void ColumnData::Append(BaseStatistics &append_stats, ColumnAppendState &state, Vector &vector, idx_t append_count) { UnifiedVectorFormat vdata; - vector.ToUnifiedFormat(count, vdata); + vector.ToUnifiedFormat(append_count, vdata); AppendData(append_stats, state, vdata, append_count); } @@ -269,6 +328,7 @@ void ColumnData::Append(ColumnAppendState &state, Vector &vector, idx_t append_c if (parent || !stats) { throw InternalException("ColumnData::Append called on a column with a parent or without stats"); } + lock_guard l(stats_lock); Append(stats->statistics, state, vector, append_count); } @@ -276,6 +336,7 @@ bool ColumnData::CheckZonemap(TableFilter &filter) { if (!stats) { throw InternalException("ColumnData::CheckZonemap called on a column without stats"); } + lock_guard l(stats_lock); auto propagate_result = filter.CheckStatistics(stats->statistics); if (propagate_result == FilterPropagateResult::FILTER_ALWAYS_FALSE || propagate_result == FilterPropagateResult::FILTER_FALSE_OR_NULL) { @@ -288,6 +349,7 @@ unique_ptr ColumnData::GetStatistics() { if (!stats) { throw InternalException("ColumnData::GetStatistics called on a column without stats"); } + lock_guard l(stats_lock); return stats->statistics.ToUnique(); } @@ -295,6 +357,7 @@ void ColumnData::MergeStatistics(const BaseStatistics &other) { if (!stats) { throw InternalException("ColumnData::MergeStatistics called on a column without stats"); } + lock_guard l(stats_lock); return stats->statistics.Merge(other); } @@ -302,6 +365,7 @@ void ColumnData::MergeIntoStatistics(BaseStatistics &other) { if (!stats) { throw InternalException("ColumnData::MergeIntoStatistics called on a column without stats"); } + lock_guard l(stats_lock); return other.Merge(stats->statistics); } @@ -355,9 +419,9 @@ void ColumnData::RevertAppend(row_t start_row) { auto l = data.Lock(); // check if this row is in the segment tree at all auto last_segment = data.GetLastSegment(l); - if (idx_t(start_row) >= last_segment->start + last_segment->count) { + if (NumericCast(start_row) >= last_segment->start + last_segment->count) { // the start row is equal to the final portion of the column data: nothing was ever appended here - D_ASSERT(idx_t(start_row) == last_segment->start + last_segment->count); + D_ASSERT(NumericCast(start_row) == last_segment->start + last_segment->count); return; } // find the segment index that the current row belongs to @@ -376,13 +440,13 @@ void ColumnData::RevertAppend(row_t start_row) { idx_t ColumnData::Fetch(ColumnScanState &state, row_t row_id, Vector &result) { D_ASSERT(row_id >= 0); - D_ASSERT(idx_t(row_id) >= start); + D_ASSERT(NumericCast(row_id) >= start); // perform the fetch within the segment state.row_index = start + ((UnsafeNumericCast(row_id) - start) / STANDARD_VECTOR_SIZE * STANDARD_VECTOR_SIZE); state.current = data.GetSegment(state.row_index); state.internal_index = state.current->start; - return ScanVector(state, result, STANDARD_VECTOR_SIZE, false); + return ScanVector(state, result, STANDARD_VECTOR_SIZE, ScanVectorType::SCAN_FLAT_VECTOR); } void ColumnData::FetchRow(TransactionData transaction, ColumnFetchState &state, row_t row_id, Vector &result, @@ -415,16 +479,18 @@ void ColumnData::UpdateColumn(TransactionData transaction, const vector(MAX_ROW_ID)) { #if STANDARD_VECTOR_SIZE < 1024 - vector_segment_size = 1024 * GetTypeIdSize(type.InternalType()); + vector_segment_size = 1024 * type_size; #else - vector_segment_size = STANDARD_VECTOR_SIZE * GetTypeIdSize(type.InternalType()); + vector_segment_size = STANDARD_VECTOR_SIZE * type_size; #endif } - // the segment size is bound by the block size, but can be smaller + // The segment size is bound by the block size, but can be smaller. idx_t segment_size = Storage::BLOCK_SIZE < vector_segment_size ? Storage::BLOCK_SIZE : vector_segment_size; allocation_size += segment_size; auto new_segment = ColumnSegment::CreateTransientSegment(GetDatabase(), type, start_row, segment_size); @@ -451,7 +517,7 @@ void ColumnData::CheckpointScan(ColumnSegment &segment, ColumnScanState &state, segment.FetchRow(fetch_state, UnsafeNumericCast(state.row_index + i), scan_vector, i); } } else { - segment.Scan(state, count, scan_vector, 0, !HasUpdates()); + segment.Scan(state, count, scan_vector, 0, ScanVectorType::SCAN_FLAT_VECTOR); } if (updates) { @@ -460,12 +526,10 @@ void ColumnData::CheckpointScan(ColumnSegment &segment, ColumnScanState &state, } } -unique_ptr ColumnData::Checkpoint(RowGroup &row_group, - PartialBlockManager &partial_block_manager, - ColumnCheckpointInfo &checkpoint_info) { +unique_ptr ColumnData::Checkpoint(RowGroup &row_group, ColumnCheckpointInfo &checkpoint_info) { // scan the segments of the column data // set up the checkpoint state - auto checkpoint_state = CreateCheckpointState(row_group, partial_block_manager); + auto checkpoint_state = CreateCheckpointState(row_group, checkpoint_info.info.manager); checkpoint_state->global_stats = BaseStatistics::CreateEmpty(type).ToUnique(); auto l = data.Lock(); @@ -486,15 +550,18 @@ unique_ptr ColumnData::Checkpoint(RowGroup &row_group, } void ColumnData::DeserializeColumn(Deserializer &deserializer, BaseStatistics &target_stats) { - // load the data pointers for the column - deserializer.Set(info.db.GetDatabase()); + // Set the stack of the deserializer to load the data pointers. + deserializer.Set(info.GetDB().GetDatabase()); deserializer.Set(type); + CompressionInfo compression_info(Storage::BLOCK_SIZE, type.InternalType()); + deserializer.Set(compression_info); vector data_pointers; deserializer.ReadProperty(100, "data_pointers", data_pointers); deserializer.Unset(); deserializer.Unset(); + deserializer.Unset(); // construct the segments based on the data pointers this->count = 0; @@ -543,7 +610,7 @@ void ColumnData::GetColumnSegmentInfo(idx_t row_group_index, vector col_p // iterate over the segments idx_t segment_idx = 0; - auto segment = (ColumnSegment *)data.GetRootSegment(); + auto segment = data.GetRootSegment(); while (segment) { ColumnSegmentInfo column_info; column_info.row_group_index = row_group_index; @@ -554,7 +621,10 @@ void ColumnData::GetColumnSegmentInfo(idx_t row_group_index, vector col_p column_info.segment_start = segment->start; column_info.segment_count = segment->count; column_info.compression_type = CompressionTypeToString(segment->function.get().type); - column_info.segment_stats = segment->stats.statistics.ToString(); + { + lock_guard l(stats_lock); + column_info.segment_stats = segment->stats.statistics.ToString(); + } column_info.has_updates = ColumnData::HasUpdates(); // persistent // block_id diff --git a/src/storage/table/column_data_checkpointer.cpp b/src/storage/table/column_data_checkpointer.cpp index 9ecfe43eb7d..617f58b5f70 100644 --- a/src/storage/table/column_data_checkpointer.cpp +++ b/src/storage/table/column_data_checkpointer.cpp @@ -13,8 +13,10 @@ ColumnDataCheckpointer::ColumnDataCheckpointer(ColumnData &col_data_p, RowGroup is_validity(GetType().id() == LogicalTypeId::VALIDITY), intermediate(is_validity ? LogicalType::BOOLEAN : GetType(), true, is_validity), checkpoint_info(checkpoint_info_p) { + auto &config = DBConfig::GetConfig(GetDatabase()); - auto functions = config.GetCompressionFunctions(GetType().InternalType()); + CompressionInfo info(Storage::BLOCK_SIZE, GetType().InternalType()); + auto functions = config.GetCompressionFunctions(info); for (auto &func : functions) { compression_functions.push_back(&func.get()); } @@ -100,7 +102,7 @@ unique_ptr ColumnDataCheckpointer::DetectBestCompressionMethod(idx auto &config = DBConfig::GetConfig(GetDatabase()); CompressionType forced_method = CompressionType::COMPRESSION_AUTO; - auto compression_type = checkpoint_info.compression_type; + auto compression_type = checkpoint_info.GetCompressionType(); if (compression_type != CompressionType::COMPRESSION_AUTO) { forced_method = ForceCompression(compression_functions, compression_type); } @@ -267,7 +269,8 @@ CompressionFunction &ColumnDataCheckpointer::GetCompressionFunction(CompressionT auto &db = GetDatabase(); auto &column_type = GetType(); auto &config = DBConfig::GetConfig(db); - return *config.GetCompressionFunction(compression_type, column_type.InternalType()); + CompressionInfo info(Storage::BLOCK_SIZE, column_type.InternalType()); + return *config.GetCompressionFunction(compression_type, info); } } // namespace duckdb diff --git a/src/storage/table/column_segment.cpp b/src/storage/table/column_segment.cpp index d0f2cd69545..417a7785420 100644 --- a/src/storage/table/column_segment.cpp +++ b/src/storage/table/column_segment.cpp @@ -1,16 +1,17 @@ #include "duckdb/storage/table/column_segment.hpp" + #include "duckdb/common/limits.hpp" -#include "duckdb/storage/table/update_segment.hpp" #include "duckdb/common/types/null_value.hpp" #include "duckdb/common/types/vector.hpp" -#include "duckdb/storage/table/append_state.hpp" -#include "duckdb/storage/storage_manager.hpp" +#include "duckdb/main/config.hpp" #include "duckdb/planner/filter/conjunction_filter.hpp" #include "duckdb/planner/filter/constant_filter.hpp" #include "duckdb/planner/filter/struct_filter.hpp" -#include "duckdb/main/config.hpp" -#include "duckdb/storage/table/scan_state.hpp" #include "duckdb/storage/data_pointer.hpp" +#include "duckdb/storage/storage_manager.hpp" +#include "duckdb/storage/table/append_state.hpp" +#include "duckdb/storage/table/scan_state.hpp" +#include "duckdb/storage/table/update_segment.hpp" #include @@ -31,35 +32,33 @@ unique_ptr ColumnSegment::CreatePersistentSegment(DatabaseInstanc optional_ptr function; shared_ptr block; + CompressionInfo info(Storage::BLOCK_SIZE, type.InternalType()); + if (block_id == INVALID_BLOCK) { // constant segment, no need to allocate an actual block - function = config.GetCompressionFunction(CompressionType::COMPRESSION_CONSTANT, type.InternalType()); + function = config.GetCompressionFunction(CompressionType::COMPRESSION_CONSTANT, info); } else { - function = config.GetCompressionFunction(compression_type, type.InternalType()); + function = config.GetCompressionFunction(compression_type, info); block = block_manager.RegisterBlock(block_id); } - auto segment_size = Storage::BLOCK_SIZE; + auto segment_size = block_manager.GetBlockSize(); return make_uniq(db, std::move(block), type, ColumnSegmentType::PERSISTENT, start, count, *function, std::move(statistics), block_id, offset, segment_size, std::move(segment_state)); } unique_ptr ColumnSegment::CreateTransientSegment(DatabaseInstance &db, const LogicalType &type, - idx_t start, idx_t segment_size) { + const idx_t start, const idx_t segment_size) { - D_ASSERT(segment_size <= Storage::BLOCK_SIZE); + // Allocate a buffer for the uncompressed segment. + auto &buffer_manager = BufferManager::GetBufferManager(db); + auto block = buffer_manager.RegisterTransientMemory(segment_size); + // Get the segment compression function. auto &config = DBConfig::GetConfig(db); - auto function = config.GetCompressionFunction(CompressionType::COMPRESSION_UNCOMPRESSED, type.InternalType()); - auto &buffer_manager = BufferManager::GetBufferManager(db); - shared_ptr block; + CompressionInfo info(Storage::BLOCK_SIZE, type.InternalType()); + auto function = config.GetCompressionFunction(CompressionType::COMPRESSION_UNCOMPRESSED, info); - // transient: allocate a buffer for the uncompressed segment - if (segment_size < Storage::BLOCK_SIZE) { - block = buffer_manager.RegisterSmallMemory(segment_size); - } else { - buffer_manager.Allocate(MemoryTag::IN_MEMORY_TABLE, segment_size, false, &block); - } return make_uniq(db, std::move(block), type, ColumnSegmentType::TRANSIENT, start, 0U, *function, BaseStatistics::CreateEmpty(type), INVALID_BLOCK, 0U, segment_size); } @@ -67,30 +66,33 @@ unique_ptr ColumnSegment::CreateTransientSegment(DatabaseInstance //===--------------------------------------------------------------------===// // Construct/Destruct //===--------------------------------------------------------------------===// -ColumnSegment::ColumnSegment(DatabaseInstance &db, shared_ptr block, LogicalType type_p, - ColumnSegmentType segment_type, idx_t start, idx_t count, CompressionFunction &function_p, - BaseStatistics statistics, block_id_t block_id_p, idx_t offset_p, idx_t segment_size_p, - unique_ptr segment_state) +ColumnSegment::ColumnSegment(DatabaseInstance &db, shared_ptr block_p, const LogicalType &type, + const ColumnSegmentType segment_type, const idx_t start, const idx_t count, + CompressionFunction &function_p, BaseStatistics statistics, const block_id_t block_id_p, + const idx_t offset, const idx_t segment_size_p, + const unique_ptr segment_state_p) - : SegmentBase(start, count), db(db), type(std::move(type_p)), - type_size(GetTypeIdSize(type.InternalType())), segment_type(segment_type), function(function_p), - stats(std::move(statistics)), block(std::move(block)), block_id(block_id_p), offset(offset_p), - segment_size(segment_size_p) { + : SegmentBase(start, count), db(db), type(type), type_size(GetTypeIdSize(type.InternalType())), + segment_type(segment_type), function(function_p), stats(std::move(statistics)), block(std::move(block_p)), + block_id(block_id_p), offset(offset), segment_size(segment_size_p) { if (function.get().init_segment) { - this->segment_state = function.get().init_segment(*this, block_id, segment_state.get()); + segment_state = function.get().init_segment(*this, block_id, segment_state_p.get()); } - D_ASSERT(segment_size <= Storage::BLOCK_SIZE); + + // For constant segments (CompressionType::COMPRESSION_CONSTANT) the block is a nullptr. + D_ASSERT(!block || segment_size <= GetBlockManager().GetBlockSize()); } -ColumnSegment::ColumnSegment(ColumnSegment &other, idx_t start) +ColumnSegment::ColumnSegment(ColumnSegment &other, const idx_t start) : SegmentBase(start, other.count.load()), db(other.db), type(std::move(other.type)), type_size(other.type_size), segment_type(other.segment_type), function(other.function), stats(std::move(other.stats)), block(std::move(other.block)), block_id(other.block_id), offset(other.offset), segment_size(other.segment_size), segment_state(std::move(other.segment_state)) { - D_ASSERT(segment_size <= Storage::BLOCK_SIZE); + // For constant segments (CompressionType::COMPRESSION_CONSTANT) the block is a nullptr. + D_ASSERT(!block || segment_size <= GetBlockManager().GetBlockSize()); } ColumnSegment::~ColumnSegment() { @@ -99,13 +101,25 @@ ColumnSegment::~ColumnSegment() { //===--------------------------------------------------------------------===// // Scan //===--------------------------------------------------------------------===// +void ColumnSegment::InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &) { + if (!block || block->BlockId() >= MAXIMUM_BLOCK) { + // not an on-disk block + return; + } + if (function.get().init_prefetch) { + function.get().init_prefetch(*this, prefetch_state); + } else { + prefetch_state.AddBlock(block); + } +} + void ColumnSegment::InitializeScan(ColumnScanState &state) { state.scan_state = function.get().init_scan(*this); } void ColumnSegment::Scan(ColumnScanState &state, idx_t scan_count, Vector &result, idx_t result_offset, - bool entire_vector) { - if (entire_vector) { + ScanVectorType scan_type) { + if (scan_type == ScanVectorType::SCAN_ENTIRE_VECTOR) { D_ASSERT(result_offset == 0); Scan(state, scan_count, result); } else { @@ -144,9 +158,9 @@ idx_t ColumnSegment::SegmentSize() const { } void ColumnSegment::Resize(idx_t new_size) { - D_ASSERT(new_size > this->segment_size); + D_ASSERT(new_size > segment_size); D_ASSERT(offset == 0); - D_ASSERT(new_size <= Storage::BLOCK_SIZE); + D_ASSERT(block && new_size <= GetBlockManager().GetBlockSize()); auto &buffer_manager = BufferManager::GetBufferManager(db); auto old_handle = buffer_manager.Pin(block); @@ -253,9 +267,10 @@ static idx_t TemplatedFilterSelection(UnifiedVectorFormat &vdata, T predicate, S for (idx_t i = 0; i < approved_tuple_count; i++) { auto idx = sel.get_index(i); auto vector_idx = vdata.sel->get_index(idx); - if ((!HAS_NULL || mask.RowIsValid(vector_idx)) && OP::Operation(vec[vector_idx], predicate)) { - result_sel.set_index(result_count++, idx); - } + bool comparison_result = + (!HAS_NULL || mask.RowIsValid(vector_idx)) && OP::Operation(vec[vector_idx], predicate); + result_sel.set_index(result_count, idx); + result_count += comparison_result; } return result_count; } diff --git a/src/storage/table/list_column_data.cpp b/src/storage/table/list_column_data.cpp index 21aa9b5af41..6e730607e6b 100644 --- a/src/storage/table/list_column_data.cpp +++ b/src/storage/table/list_column_data.cpp @@ -29,6 +29,20 @@ bool ListColumnData::CheckZonemap(ColumnScanState &state, TableFilter &filter) { return false; } +void ListColumnData::InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state, idx_t rows) { + ColumnData::InitializePrefetch(prefetch_state, scan_state, rows); + validity.InitializePrefetch(prefetch_state, scan_state.child_states[0], rows); + + // we can't know how many rows we need to prefetch for the child of this list without looking at the actual data + // we make an estimation by looking at how many rows the child column has versus this column + // e.g if the child column has 10K rows, and we have 1K rows, we estimate that each list has 10 elements + idx_t rows_per_list = 1; + if (child_column->count > this->count && this->count > 0) { + rows_per_list = child_column->count / this->count; + } + child_column->InitializePrefetch(prefetch_state, scan_state.child_states[1], rows * rows_per_list); +} + void ListColumnData::InitializeScan(ColumnScanState &state) { ColumnData::InitializeScan(state); @@ -70,12 +84,14 @@ void ListColumnData::InitializeScanWithOffset(ColumnScanState &state, idx_t row_ state.last_offset = child_offset; } -idx_t ListColumnData::Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result) { - return ScanCount(state, result, STANDARD_VECTOR_SIZE); +idx_t ListColumnData::Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t scan_count) { + return ScanCount(state, result, scan_count); } -idx_t ListColumnData::ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates) { - return ScanCount(state, result, STANDARD_VECTOR_SIZE); +idx_t ListColumnData::ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates, + idx_t scan_count) { + return ScanCount(state, result, scan_count); } idx_t ListColumnData::ScanCount(ColumnScanState &state, Vector &result, idx_t count) { @@ -86,7 +102,7 @@ idx_t ListColumnData::ScanCount(ColumnScanState &state, Vector &result, idx_t co D_ASSERT(!updates); Vector offset_vector(LogicalType::UBIGINT, count); - idx_t scan_count = ScanVector(state, offset_vector, count, false); + idx_t scan_count = ScanVector(state, offset_vector, count, ScanVectorType::SCAN_FLAT_VECTOR); D_ASSERT(scan_count > 0); validity.ScanCount(state.child_states[0], result, count); @@ -133,7 +149,7 @@ void ListColumnData::Skip(ColumnScanState &state, idx_t count) { // note that we only need to read the first and last entry // however, let's just read all "count" entries for now Vector offset_vector(LogicalType::UBIGINT, count); - idx_t scan_count = ScanVector(state, offset_vector, count, false); + idx_t scan_count = ScanVector(state, offset_vector, count, ScanVectorType::SCAN_FLAT_VECTOR); D_ASSERT(scan_count > 0); UnifiedVectorFormat offsets; @@ -339,11 +355,10 @@ unique_ptr ListColumnData::CreateCheckpointState(RowGroup } unique_ptr ListColumnData::Checkpoint(RowGroup &row_group, - PartialBlockManager &partial_block_manager, ColumnCheckpointInfo &checkpoint_info) { - auto base_state = ColumnData::Checkpoint(row_group, partial_block_manager, checkpoint_info); - auto validity_state = validity.Checkpoint(row_group, partial_block_manager, checkpoint_info); - auto child_state = child_column->Checkpoint(row_group, partial_block_manager, checkpoint_info); + auto base_state = ColumnData::Checkpoint(row_group, checkpoint_info); + auto validity_state = validity.Checkpoint(row_group, checkpoint_info); + auto child_state = child_column->Checkpoint(row_group, checkpoint_info); auto &checkpoint_state = base_state->Cast(); checkpoint_state.validity_state = std::move(validity_state); diff --git a/src/storage/table/row_group.cpp b/src/storage/table/row_group.cpp index 8c90272dba3..1cc641ca38e 100644 --- a/src/storage/table/row_group.cpp +++ b/src/storage/table/row_group.cpp @@ -106,7 +106,7 @@ ColumnData &RowGroup::GetColumn(storage_t c) { if (this->columns[c]->count != this->count) { throw InternalException("Corrupted database - loaded column with index %llu at row start %llu, count %llu did " "not match count of row group %llu", - c, start, this->columns[c]->count, this->count.load()); + c, start, this->columns[c]->count.load(), this->count.load()); } return *columns[c]; } @@ -284,7 +284,7 @@ unique_ptr RowGroup::AlterType(RowGroupCollection &new_collection, con } unique_ptr RowGroup::AddColumn(RowGroupCollection &new_collection, ColumnDefinition &new_column, - ExpressionExecutor &executor, Expression &default_value, Vector &result) { + ExpressionExecutor &executor, Vector &result) { Verify(); // construct a new column data for the new column @@ -418,6 +418,9 @@ bool RowGroup::CheckZonemapSegments(CollectionScanState &state) { if (!read_segment) { idx_t target_row = GetFilterScanCount(state.column_scans[column_idx], *entry.second); + if (target_row >= state.max_row) { + target_row = state.max_row; + } D_ASSERT(target_row >= this->start); D_ASSERT(target_row <= this->start + this->count); @@ -468,11 +471,11 @@ void RowGroup::TemplatedScan(TransactionData transaction, CollectionScanState &s if (!CheckZonemapSegments(state)) { continue; } + // second, scan the version chunk manager to figure out which tuples to load for this transaction idx_t count; - SelectionVector valid_sel(STANDARD_VECTOR_SIZE); if (TYPE == TableScanType::TABLE_SCAN_REGULAR) { - count = state.row_group->GetSelVector(transaction, state.vector_index, valid_sel, max_count); + count = state.row_group->GetSelVector(transaction, state.vector_index, state.valid_sel, max_count); if (count == 0) { // nothing to scan for this vector, skip the entire vector NextVector(state); @@ -480,7 +483,7 @@ void RowGroup::TemplatedScan(TransactionData transaction, CollectionScanState &s } } else if (TYPE == TableScanType::TABLE_SCAN_COMMITTED_ROWS_OMIT_PERMANENTLY_DELETED) { count = state.row_group->GetCommittedSelVector(transaction.start_time, transaction.transaction_id, - state.vector_index, valid_sel, max_count); + state.vector_index, state.valid_sel, max_count); if (count == 0) { // nothing to scan for this vector, skip the entire vector NextVector(state); @@ -489,6 +492,26 @@ void RowGroup::TemplatedScan(TransactionData transaction, CollectionScanState &s } else { count = max_count; } + auto &block_manager = GetBlockManager(); +#ifndef DUCKDB_ALTERNATIVE_VERIFY + // // in regular operation we only prefetch from remote file systems + // // when alternative verify is set, we always prefetch for testing purposes + if (block_manager.IsRemote()) +#else + if (!block_manager.InMemory()) +#endif + { + PrefetchState prefetch_state; + for (idx_t i = 0; i < column_ids.size(); i++) { + const auto &column = column_ids[i]; + if (column != COLUMN_IDENTIFIER_ROW_ID) { + GetColumn(column).InitializePrefetch(prefetch_state, state.column_scans[i], max_count); + } + } + auto &buffer_manager = block_manager.buffer_manager; + buffer_manager.Prefetch(prefetch_state.blocks); + } + if (count == max_count && !table_filters) { // scan all vectors completely: full scan without deletions or table filters for (idx_t i = 0; i < column_ids.size(); i++) { @@ -512,7 +535,7 @@ void RowGroup::TemplatedScan(TransactionData transaction, CollectionScanState &s idx_t approved_tuple_count = count; SelectionVector sel; if (count != max_count) { - sel.Initialize(valid_sel); + sel.Initialize(state.valid_sel); } else { sel.Initialize(nullptr); } @@ -595,9 +618,16 @@ void RowGroup::Scan(TransactionData transaction, CollectionScanState &state, Dat void RowGroup::ScanCommitted(CollectionScanState &state, DataChunk &result, TableScanType type) { auto &transaction_manager = DuckTransactionManager::Get(GetCollection().GetAttached()); - auto lowest_active_start = transaction_manager.LowestActiveStart(); - auto lowest_active_id = transaction_manager.LowestActiveId(); - TransactionData data(lowest_active_id, lowest_active_start); + transaction_t start_ts; + transaction_t transaction_id; + if (type == TableScanType::TABLE_SCAN_LATEST_COMMITTED_ROWS) { + start_ts = transaction_manager.GetLastCommit() + 1; + transaction_id = MAX_TRANSACTION_ID; + } else { + start_ts = transaction_manager.LowestActiveStart(); + transaction_id = transaction_manager.LowestActiveId(); + } + TransactionData data(transaction_id, start_ts); switch (type) { case TableScanType::TABLE_SCAN_COMMITTED_ROWS: TemplatedScan(data, state, result); @@ -606,6 +636,7 @@ void RowGroup::ScanCommitted(CollectionScanState &state, DataChunk &result, Tabl TemplatedScan(data, state, result); break; case TableScanType::TABLE_SCAN_COMMITTED_ROWS_OMIT_PERMANENTLY_DELETED: + case TableScanType::TABLE_SCAN_LATEST_COMMITTED_ROWS: TemplatedScan(data, state, result); break; default: @@ -780,24 +811,24 @@ void RowGroup::UpdateColumn(TransactionData transaction, DataChunk &updates, Vec unique_ptr RowGroup::GetStatistics(idx_t column_idx) { auto &col_data = GetColumn(column_idx); - lock_guard slock(stats_lock); return col_data.GetStatistics(); } void RowGroup::MergeStatistics(idx_t column_idx, const BaseStatistics &other) { auto &col_data = GetColumn(column_idx); - lock_guard slock(stats_lock); col_data.MergeStatistics(other); } void RowGroup::MergeIntoStatistics(idx_t column_idx, BaseStatistics &other) { auto &col_data = GetColumn(column_idx); - lock_guard slock(stats_lock); col_data.MergeIntoStatistics(other); } -RowGroupWriteData RowGroup::WriteToDisk(PartialBlockManager &manager, - const vector &compression_types) { +CompressionType ColumnCheckpointInfo::GetCompressionType() { + return info.compression_types[column_idx]; +} + +RowGroupWriteData RowGroup::WriteToDisk(RowGroupWriteInfo &info) { RowGroupWriteData result; result.states.reserve(columns.size()); result.statistics.reserve(columns.size()); @@ -812,8 +843,8 @@ RowGroupWriteData RowGroup::WriteToDisk(PartialBlockManager &manager, // pointers all end up densely packed, and thus more cache-friendly. for (idx_t column_idx = 0; column_idx < GetColumnCount(); column_idx++) { auto &column = GetColumn(column_idx); - ColumnCheckpointInfo checkpoint_info {compression_types[column_idx]}; - auto checkpoint_state = column.Checkpoint(*this, manager, checkpoint_info); + ColumnCheckpointInfo checkpoint_info(info, column_idx); + auto checkpoint_state = column.Checkpoint(*this, checkpoint_info); D_ASSERT(checkpoint_state); auto stats = checkpoint_state->GetStatistics(); @@ -851,20 +882,22 @@ RowGroupWriteData RowGroup::WriteToDisk(RowGroupWriter &writer) { if (column.count != this->count) { throw InternalException("Corrupted in-memory column - column with index %llu has misaligned count (row " "group has %llu rows, column has %llu)", - column_idx, this->count.load(), column.count); + column_idx, this->count.load(), column.count.load()); } compression_types.push_back(writer.GetColumnCompressionType(column_idx)); } - return WriteToDisk(writer.GetPartialBlockManager(), compression_types); + RowGroupWriteInfo info(writer.GetPartialBlockManager(), compression_types, writer.GetCheckpointType()); + return WriteToDisk(info); } RowGroupPointer RowGroup::Checkpoint(RowGroupWriteData write_data, RowGroupWriter &writer, TableStatistics &global_stats) { RowGroupPointer row_group_pointer; + auto lock = global_stats.GetLock(); for (idx_t column_idx = 0; column_idx < GetColumnCount(); column_idx++) { - global_stats.GetStats(column_idx).Statistics().Merge(write_data.statistics[column_idx]); + global_stats.GetStats(*lock, column_idx).Statistics().Merge(write_data.statistics[column_idx]); } // construct the row group pointer and write the column meta data to disk diff --git a/src/storage/table/row_group_collection.cpp b/src/storage/table/row_group_collection.cpp index 9c0c3b5b9c5..a3029a60476 100644 --- a/src/storage/table/row_group_collection.cpp +++ b/src/storage/table/row_group_collection.cpp @@ -14,6 +14,7 @@ #include "duckdb/parallel/task_scheduler.hpp" #include "duckdb/execution/task_error_manager.hpp" #include "duckdb/storage/table/column_checkpoint_state.hpp" +#include "duckdb/execution/index/bound_index.hpp" namespace duckdb { @@ -67,11 +68,11 @@ const vector &RowGroupCollection::GetTypes() const { } Allocator &RowGroupCollection::GetAllocator() const { - return Allocator::Get(info->db); + return Allocator::Get(info->GetDB()); } AttachedDatabase &RowGroupCollection::GetAttached() { - return GetTableInfo().db; + return GetTableInfo().GetDB(); } MetadataManager &RowGroupCollection::GetMetadataManager() { @@ -347,7 +348,7 @@ bool RowGroupCollection::Append(DataChunk &chunk, TableAppendState &state) { // merge the stats auto stats_lock = stats.GetLock(); for (idx_t i = 0; i < types.size(); i++) { - current_row_group->MergeIntoStatistics(i, stats.GetStats(i).Statistics()); + current_row_group->MergeIntoStatistics(i, stats.GetStats(*stats_lock, i).Statistics()); } } remaining -= append_count; @@ -376,7 +377,7 @@ bool RowGroupCollection::Append(DataChunk &chunk, TableAppendState &state) { state.current_row += row_t(total_append_count); auto stats_lock = stats.GetLock(); for (idx_t col_idx = 0; col_idx < types.size(); col_idx++) { - stats.GetStats(col_idx).UpdateDistinctStatistics(chunk.data[col_idx], chunk.size()); + stats.GetStats(*stats_lock, col_idx).UpdateDistinctStatistics(chunk.data[col_idx], chunk.size()); } return new_row_group; } @@ -574,7 +575,14 @@ void RowGroupCollection::RemoveFromIndexes(TableIndexList &indexes, Vector &row_ result.Slice(sel, sel_count); indexes.Scan([&](Index &index) { - index.Delete(result, row_identifiers); + if (index.IsBound()) { + index.Cast().Delete(result, row_identifiers); + } else { + throw MissingExtensionException( + "Cannot delete from index '%s', unknown index type '%s'. You need to load the " + "extension that provides this index type before table '%s' can be modified.", + index.GetIndexName(), index.GetIndexType(), info->GetTableName()); + } return false; }); } @@ -591,7 +599,8 @@ void RowGroupCollection::UpdateColumn(TransactionData transaction, Vector &row_i auto row_group = row_groups->GetSegment(UnsafeNumericCast(first_id)); row_group->UpdateColumn(transaction, updates, row_ids, column_path); - row_group->MergeIntoStatistics(primary_column_idx, stats.GetStats(primary_column_idx).Statistics()); + auto lock = stats.GetLock(); + row_group->MergeIntoStatistics(primary_column_idx, stats.GetStats(*lock, primary_column_idx).Statistics()); } //===--------------------------------------------------------------------===// @@ -791,7 +800,7 @@ class VacuumTask : public BaseCheckpointTask { scan_chunk.Reset(); current_row_group.ScanCommitted(scan_state.table_state, scan_chunk, - TableScanType::TABLE_SCAN_COMMITTED_ROWS_OMIT_PERMANENTLY_DELETED); + TableScanType::TABLE_SCAN_LATEST_COMMITTED_ROWS); if (scan_chunk.size() == 0) { break; } @@ -845,8 +854,11 @@ class VacuumTask : public BaseCheckpointTask { idx_t row_start; }; -void RowGroupCollection::InitializeVacuumState(VacuumState &state, vector> &segments) { - state.can_vacuum_deletes = info->indexes.Empty(); +void RowGroupCollection::InitializeVacuumState(CollectionCheckpointState &checkpoint_state, VacuumState &state, + vector> &segments) { + bool is_full_checkpoint = checkpoint_state.writer.GetCheckpointType() == CheckpointType::FULL_CHECKPOINT; + // currently we can only vacuum deletes if we are doing a full checkpoint and there are no indexes + state.can_vacuum_deletes = info->GetIndexes().Empty() && is_full_checkpoint; if (!state.can_vacuum_deletes) { return; } @@ -943,7 +955,7 @@ void RowGroupCollection::Checkpoint(TableDataWriter &writer, TableStatistics &gl CollectionCheckpointState checkpoint_state(*this, writer, segments, global_stats); VacuumState vacuum_state; - InitializeVacuumState(vacuum_state, segments); + InitializeVacuumState(checkpoint_state, vacuum_state, segments); // schedule tasks for (idx_t segment_idx = 0; segment_idx < segments.size(); segment_idx++) { auto &entry = segments[segment_idx]; @@ -1028,25 +1040,24 @@ vector RowGroupCollection::GetColumnSegmentInfo() { // Alter //===--------------------------------------------------------------------===// shared_ptr RowGroupCollection::AddColumn(ClientContext &context, ColumnDefinition &new_column, - Expression &default_value) { + ExpressionExecutor &default_executor) { idx_t new_column_idx = types.size(); auto new_types = types; new_types.push_back(new_column.GetType()); auto result = make_shared_ptr(info, block_manager, std::move(new_types), row_start, total_rows.load()); - ExpressionExecutor executor(context); DataChunk dummy_chunk; Vector default_vector(new_column.GetType()); - executor.AddExpression(default_value); result->stats.InitializeAddColumn(stats, new_column.GetType()); - auto &new_column_stats = result->stats.GetStats(new_column_idx); + auto lock = result->stats.GetLock(); + auto &new_column_stats = result->stats.GetStats(*lock, new_column_idx); // fill the column with its DEFAULT value, or NULL if none is specified auto new_stats = make_uniq(new_column.GetType()); for (auto ¤t_row_group : row_groups->Segments()) { - auto new_row_group = current_row_group.AddColumn(*result, new_column, executor, default_value, default_vector); + auto new_row_group = current_row_group.AddColumn(*result, new_column, default_executor, default_vector); // merge in the statistics new_row_group->MergeIntoStatistics(new_column_idx, new_column_stats.Statistics()); @@ -1101,7 +1112,8 @@ shared_ptr RowGroupCollection::AlterType(ClientContext &cont scan_state.table_state.max_row = row_start + total_rows; // now alter the type of the column within all of the row_groups individually - auto &changed_stats = result->stats.GetStats(changed_idx); + auto lock = result->stats.GetLock(); + auto &changed_stats = result->stats.GetStats(*lock, changed_idx); for (auto ¤t_row_group : row_groups->Segments()) { auto new_row_group = current_row_group.AlterType(*result, target_type, changed_idx, executor, scan_state.table_state, scan_chunk); @@ -1141,8 +1153,8 @@ void RowGroupCollection::VerifyNewConstraint(DataTable &parent, const BoundConst } // Check constraint if (VectorOperations::HasNull(scan_chunk.data[0], scan_chunk.size())) { - throw ConstraintException("NOT NULL constraint failed: %s.%s", info->table, - parent.column_definitions[physical_index].GetName()); + throw ConstraintException("NOT NULL constraint failed: %s.%s", info->GetTableName(), + parent.Columns()[physical_index].GetName()); } } } @@ -1160,8 +1172,8 @@ unique_ptr RowGroupCollection::CopyStats(column_t column_id) { void RowGroupCollection::SetDistinct(column_t column_id, unique_ptr distinct_stats) { D_ASSERT(column_id != COLUMN_IDENTIFIER_ROW_ID); - auto stats_guard = stats.GetLock(); - stats.GetStats(column_id).SetDistinct(std::move(distinct_stats)); + auto stats_lock = stats.GetLock(); + stats.GetStats(*stats_lock, column_id).SetDistinct(std::move(distinct_stats)); } } // namespace duckdb diff --git a/src/storage/table/scan_state.cpp b/src/storage/table/scan_state.cpp index baa4c310e0c..8f099726d5f 100644 --- a/src/storage/table/scan_state.cpp +++ b/src/storage/table/scan_state.cpp @@ -77,7 +77,7 @@ ParallelCollectionScanState::ParallelCollectionScanState() CollectionScanState::CollectionScanState(TableScanState &parent_p) : row_group(nullptr), vector_index(0), max_row_group_row(0), row_groups(nullptr), max_row(0), batch_index(0), - random(-1), parent(parent_p) { + valid_sel(STANDARD_VECTOR_SIZE), random(-1), parent(parent_p) { } bool CollectionScanState::Scan(DuckTransaction &transaction, DataChunk &result) { @@ -138,4 +138,11 @@ bool CollectionScanState::ScanCommitted(DataChunk &result, TableScanType type) { return false; } +PrefetchState::~PrefetchState() { +} + +void PrefetchState::AddBlock(shared_ptr block) { + blocks.push_back(std::move(block)); +} + } // namespace duckdb diff --git a/src/storage/table/standard_column_data.cpp b/src/storage/table/standard_column_data.cpp index ce851f00e74..928cfc63881 100644 --- a/src/storage/table/standard_column_data.cpp +++ b/src/storage/table/standard_column_data.cpp @@ -21,8 +21,16 @@ void StandardColumnData::SetStart(idx_t new_start) { validity.SetStart(new_start); } -bool StandardColumnData::HasUpdates() const { - return ColumnData::HasUpdates() || validity.HasUpdates(); +ScanVectorType StandardColumnData::GetVectorScanType(ColumnScanState &state, idx_t scan_count) { + // if either the current column data, or the validity column data requires flat vectors, we scan flat vectors + auto scan_type = ColumnData::GetVectorScanType(state, scan_count); + if (scan_type == ScanVectorType::SCAN_FLAT_VECTOR) { + return ScanVectorType::SCAN_FLAT_VECTOR; + } + if (state.child_states.empty()) { + return scan_type; + } + return validity.GetVectorScanType(state.child_states[0], scan_count); } bool StandardColumnData::CheckZonemap(ColumnScanState &state, TableFilter &filter) { @@ -31,10 +39,15 @@ bool StandardColumnData::CheckZonemap(ColumnScanState &state, TableFilter &filte return true; } state.segment_checked = true; - auto prune_result = filter.CheckStatistics(state.current->stats.statistics); - if (prune_result != FilterPropagateResult::FILTER_ALWAYS_FALSE) { - return true; + FilterPropagateResult prune_result; + { + lock_guard l(stats_lock); + prune_result = filter.CheckStatistics(state.current->stats.statistics); + if (prune_result != FilterPropagateResult::FILTER_ALWAYS_FALSE) { + return true; + } } + lock_guard l(update_lock); if (updates) { auto update_stats = updates->GetStatistics(); prune_result = filter.CheckStatistics(*update_stats); @@ -47,6 +60,11 @@ bool StandardColumnData::CheckZonemap(ColumnScanState &state, TableFilter &filte } } +void StandardColumnData::InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state, idx_t rows) { + ColumnData::InitializePrefetch(prefetch_state, scan_state, rows); + validity.InitializePrefetch(prefetch_state, scan_state.child_states[0], rows); +} + void StandardColumnData::InitializeScan(ColumnScanState &state) { ColumnData::InitializeScan(state); @@ -63,19 +81,19 @@ void StandardColumnData::InitializeScanWithOffset(ColumnScanState &state, idx_t validity.InitializeScanWithOffset(state.child_states[0], row_idx); } -idx_t StandardColumnData::Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, - Vector &result) { +idx_t StandardColumnData::Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t target_count) { D_ASSERT(state.row_index == state.child_states[0].row_index); - auto scan_count = ColumnData::Scan(transaction, vector_index, state, result); - validity.Scan(transaction, vector_index, state.child_states[0], result); + auto scan_count = ColumnData::Scan(transaction, vector_index, state, result, target_count); + validity.Scan(transaction, vector_index, state.child_states[0], result, target_count); return scan_count; } -idx_t StandardColumnData::ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, - bool allow_updates) { +idx_t StandardColumnData::ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates, + idx_t target_count) { D_ASSERT(state.row_index == state.child_states[0].row_index); - auto scan_count = ColumnData::ScanCommitted(vector_index, state, result, allow_updates); - validity.ScanCommitted(vector_index, state.child_states[0], result, allow_updates); + auto scan_count = ColumnData::ScanCommitted(vector_index, state, result, allow_updates, target_count); + validity.ScanCommitted(vector_index, state.child_states[0], result, allow_updates, target_count); return scan_count; } @@ -87,7 +105,6 @@ idx_t StandardColumnData::ScanCount(ColumnScanState &state, Vector &result, idx_ void StandardColumnData::InitializeAppend(ColumnAppendState &state) { ColumnData::InitializeAppend(state); - ColumnAppendState child_append; validity.InitializeAppend(child_append); state.child_appends.push_back(std::move(child_append)); @@ -192,15 +209,14 @@ StandardColumnData::CreateCheckpointState(RowGroup &row_group, PartialBlockManag } unique_ptr StandardColumnData::Checkpoint(RowGroup &row_group, - PartialBlockManager &partial_block_manager, ColumnCheckpointInfo &checkpoint_info) { // we need to checkpoint the main column data first // that is because the checkpointing of the main column data ALSO scans the validity data // to prevent reading the validity data immediately after it is checkpointed we first checkpoint the main column // this is necessary for concurrent checkpointing as due to the partial block manager checkpointed data might be // flushed to disk by a different thread than the one that wrote it, causing a data race - auto base_state = ColumnData::Checkpoint(row_group, partial_block_manager, checkpoint_info); - auto validity_state = validity.Checkpoint(row_group, partial_block_manager, checkpoint_info); + auto base_state = ColumnData::Checkpoint(row_group, checkpoint_info); + auto validity_state = validity.Checkpoint(row_group, checkpoint_info); auto &checkpoint_state = base_state->Cast(); checkpoint_state.validity_state = std::move(validity_state); return base_state; diff --git a/src/storage/table/struct_column_data.cpp b/src/storage/table/struct_column_data.cpp index e31867a2412..59124048f6a 100644 --- a/src/storage/table/struct_column_data.cpp +++ b/src/storage/table/struct_column_data.cpp @@ -42,10 +42,16 @@ bool StructColumnData::CheckZonemap(ColumnScanState &state, TableFilter &filter) return true; } state.segment_checked = true; - auto prune_result = filter.CheckStatistics(state.current->stats.statistics); - if (prune_result != FilterPropagateResult::FILTER_ALWAYS_FALSE) { - return true; + + FilterPropagateResult prune_result; + { + lock_guard l(stats_lock); + prune_result = filter.CheckStatistics(state.current->stats.statistics); + if (prune_result != FilterPropagateResult::FILTER_ALWAYS_FALSE) { + return true; + } } + lock_guard l(update_lock); if (updates) { auto update_stats = updates->GetStatistics(); prune_result = filter.CheckStatistics(*update_stats); @@ -62,6 +68,13 @@ idx_t StructColumnData::GetMaxEntry() { return sub_columns[0]->GetMaxEntry(); } +void StructColumnData::InitializePrefetch(PrefetchState &prefetch_state, ColumnScanState &scan_state, idx_t rows) { + validity.InitializePrefetch(prefetch_state, scan_state.child_states[0], rows); + for (idx_t i = 0; i < sub_columns.size(); i++) { + sub_columns[i]->InitializePrefetch(prefetch_state, scan_state.child_states[i + 1], rows); + } +} + void StructColumnData::InitializeScan(ColumnScanState &state) { D_ASSERT(state.child_states.size() == sub_columns.size() + 1); state.row_index = 0; @@ -90,20 +103,23 @@ void StructColumnData::InitializeScanWithOffset(ColumnScanState &state, idx_t ro } } -idx_t StructColumnData::Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result) { - auto scan_count = validity.Scan(transaction, vector_index, state.child_states[0], result); +idx_t StructColumnData::Scan(TransactionData transaction, idx_t vector_index, ColumnScanState &state, Vector &result, + idx_t target_count) { + auto scan_count = validity.Scan(transaction, vector_index, state.child_states[0], result, target_count); auto &child_entries = StructVector::GetEntries(result); for (idx_t i = 0; i < sub_columns.size(); i++) { - sub_columns[i]->Scan(transaction, vector_index, state.child_states[i + 1], *child_entries[i]); + sub_columns[i]->Scan(transaction, vector_index, state.child_states[i + 1], *child_entries[i], target_count); } return scan_count; } -idx_t StructColumnData::ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates) { - auto scan_count = validity.ScanCommitted(vector_index, state.child_states[0], result, allow_updates); +idx_t StructColumnData::ScanCommitted(idx_t vector_index, ColumnScanState &state, Vector &result, bool allow_updates, + idx_t target_count) { + auto scan_count = validity.ScanCommitted(vector_index, state.child_states[0], result, allow_updates, target_count); auto &child_entries = StructVector::GetEntries(result); for (idx_t i = 0; i < sub_columns.size(); i++) { - sub_columns[i]->ScanCommitted(vector_index, state.child_states[i + 1], *child_entries[i], allow_updates); + sub_columns[i]->ScanCommitted(vector_index, state.child_states[i + 1], *child_entries[i], allow_updates, + target_count); } return scan_count; } @@ -281,13 +297,11 @@ unique_ptr StructColumnData::CreateCheckpointState(RowGro } unique_ptr StructColumnData::Checkpoint(RowGroup &row_group, - PartialBlockManager &partial_block_manager, ColumnCheckpointInfo &checkpoint_info) { - auto checkpoint_state = make_uniq(row_group, *this, partial_block_manager); - checkpoint_state->validity_state = validity.Checkpoint(row_group, partial_block_manager, checkpoint_info); + auto checkpoint_state = make_uniq(row_group, *this, checkpoint_info.info.manager); + checkpoint_state->validity_state = validity.Checkpoint(row_group, checkpoint_info); for (auto &sub_column : sub_columns) { - checkpoint_state->child_states.push_back( - sub_column->Checkpoint(row_group, partial_block_manager, checkpoint_info)); + checkpoint_state->child_states.push_back(sub_column->Checkpoint(row_group, checkpoint_info)); } return std::move(checkpoint_state); } @@ -301,7 +315,7 @@ void StructColumnData::DeserializeColumn(Deserializer &deserializer, BaseStatist list.ReadObject([&](Deserializer &item) { sub_columns[i]->DeserializeColumn(item, child_stats); }); }); - this->count = validity.count; + this->count = validity.count.load(); } void StructColumnData::GetColumnSegmentInfo(duckdb::idx_t row_group_index, vector col_path, diff --git a/src/storage/table/table_statistics.cpp b/src/storage/table/table_statistics.cpp index 5d3a00e106d..78245236151 100644 --- a/src/storage/table/table_statistics.cpp +++ b/src/storage/table/table_statistics.cpp @@ -9,6 +9,7 @@ namespace duckdb { void TableStatistics::Initialize(const vector &types, PersistentTableData &data) { D_ASSERT(Empty()); + stats_lock = make_shared_ptr(); column_stats = std::move(data.table_stats.column_stats); if (column_stats.size() != types.size()) { // LCOV_EXCL_START throw IOException("Table statistics column count is not aligned with table column count. Corrupt file?"); @@ -18,6 +19,7 @@ void TableStatistics::Initialize(const vector &types, PersistentTab void TableStatistics::InitializeEmpty(const vector &types) { D_ASSERT(Empty()); + stats_lock = make_shared_ptr(); for (auto &type : types) { column_stats.push_back(ColumnStatistics::CreateEmptyStats(type)); } @@ -25,8 +27,10 @@ void TableStatistics::InitializeEmpty(const vector &types) { void TableStatistics::InitializeAddColumn(TableStatistics &parent, const LogicalType &new_column_type) { D_ASSERT(Empty()); + D_ASSERT(parent.stats_lock); - lock_guard stats_lock(parent.stats_lock); + stats_lock = parent.stats_lock; + lock_guard lock(*stats_lock); for (idx_t i = 0; i < parent.column_stats.size(); i++) { column_stats.push_back(parent.column_stats[i]); } @@ -35,8 +39,10 @@ void TableStatistics::InitializeAddColumn(TableStatistics &parent, const Logical void TableStatistics::InitializeRemoveColumn(TableStatistics &parent, idx_t removed_column) { D_ASSERT(Empty()); + D_ASSERT(parent.stats_lock); - lock_guard stats_lock(parent.stats_lock); + stats_lock = parent.stats_lock; + lock_guard lock(*stats_lock); for (idx_t i = 0; i < parent.column_stats.size(); i++) { if (i != removed_column) { column_stats.push_back(parent.column_stats[i]); @@ -46,8 +52,10 @@ void TableStatistics::InitializeRemoveColumn(TableStatistics &parent, idx_t remo void TableStatistics::InitializeAlterType(TableStatistics &parent, idx_t changed_idx, const LogicalType &new_type) { D_ASSERT(Empty()); + D_ASSERT(parent.stats_lock); - lock_guard stats_lock(parent.stats_lock); + stats_lock = parent.stats_lock; + lock_guard lock(*stats_lock); for (idx_t i = 0; i < parent.column_stats.size(); i++) { if (i == changed_idx) { column_stats.push_back(ColumnStatistics::CreateEmptyStats(new_type)); @@ -59,8 +67,10 @@ void TableStatistics::InitializeAlterType(TableStatistics &parent, idx_t changed void TableStatistics::InitializeAddConstraint(TableStatistics &parent) { D_ASSERT(Empty()); + D_ASSERT(parent.stats_lock); - lock_guard stats_lock(parent.stats_lock); + stats_lock = parent.stats_lock; + lock_guard lock(*stats_lock); for (idx_t i = 0; i < parent.column_stats.size(); i++) { column_stats.push_back(parent.column_stats[i]); } @@ -86,12 +96,12 @@ void TableStatistics::MergeStats(TableStatisticsLock &lock, idx_t i, BaseStatist column_stats[i]->Statistics().Merge(stats); } -ColumnStatistics &TableStatistics::GetStats(idx_t i) { +ColumnStatistics &TableStatistics::GetStats(TableStatisticsLock &lock, idx_t i) { return *column_stats[i]; } unique_ptr TableStatistics::CopyStats(idx_t i) { - lock_guard l(stats_lock); + lock_guard l(*stats_lock); auto result = column_stats[i]->Statistics().Copy(); if (column_stats[i]->HasDistinctStats()) { result.SetDistinctCount(column_stats[i]->DistinctStats().GetCount()); @@ -100,6 +110,13 @@ unique_ptr TableStatistics::CopyStats(idx_t i) { } void TableStatistics::CopyStats(TableStatistics &other) { + TableStatisticsLock lock(*stats_lock); + CopyStats(lock, other); +} + +void TableStatistics::CopyStats(TableStatisticsLock &lock, TableStatistics &other) { + D_ASSERT(other.Empty()); + other.stats_lock = make_shared_ptr(); for (auto &stats : column_stats) { other.column_stats.push_back(stats->Copy()); } @@ -125,14 +142,16 @@ void TableStatistics::Deserialize(Deserializer &deserializer, ColumnList &column deserializer.Unset(); }); - table_sample = deserializer.ReadPropertyWithDefault>(101, "sample", nullptr); + table_sample = deserializer.ReadPropertyWithDefault>(101, "table_sample", nullptr); } unique_ptr TableStatistics::GetLock() { - return make_uniq(stats_lock); + D_ASSERT(stats_lock); + return make_uniq(*stats_lock); } bool TableStatistics::Empty() { + D_ASSERT(column_stats.empty() == (stats_lock.get() == nullptr)); return column_stats.empty(); } diff --git a/src/storage/table/validity_column_data.cpp b/src/storage/table/validity_column_data.cpp index bd594fd1be8..c6659d90860 100644 --- a/src/storage/table/validity_column_data.cpp +++ b/src/storage/table/validity_column_data.cpp @@ -13,4 +13,9 @@ bool ValidityColumnData::CheckZonemap(ColumnScanState &state, TableFilter &filte return true; } +void ValidityColumnData::AppendData(BaseStatistics &stats, ColumnAppendState &state, UnifiedVectorFormat &vdata, + idx_t count) { + lock_guard l(stats_lock); + ColumnData::AppendData(stats, state, vdata, count); +} } // namespace duckdb diff --git a/src/storage/table_index_list.cpp b/src/storage/table_index_list.cpp index da8a22a0e18..8cc8487e487 100644 --- a/src/storage/table_index_list.cpp +++ b/src/storage/table_index_list.cpp @@ -1,12 +1,14 @@ #include "duckdb/storage/table/table_index_list.hpp" -#include "duckdb/storage/data_table.hpp" #include "duckdb/common/types/conflict_manager.hpp" -#include "duckdb/execution/index/unknown_index.hpp" #include "duckdb/execution/index/index_type_set.hpp" -#include "duckdb/storage/table/data_table_info.hpp" -#include "duckdb/main/database.hpp" +#include "duckdb/execution/index/unbound_index.hpp" #include "duckdb/main/config.hpp" +#include "duckdb/main/database.hpp" +#include "duckdb/storage/data_table.hpp" +#include "duckdb/storage/table/data_table_info.hpp" +#include "duckdb/catalog/catalog_entry/duck_table_entry.hpp" +#include "duckdb/planner/expression_binder/index_binder.hpp" namespace duckdb { void TableIndexList::AddIndex(unique_ptr index) { @@ -20,7 +22,8 @@ void TableIndexList::RemoveIndex(const string &name) { for (idx_t index_idx = 0; index_idx < indexes.size(); index_idx++) { auto &index_entry = indexes[index_idx]; - if (index_entry->name == name) { + + if (index_entry->GetIndexName() == name) { indexes.erase_at(index_idx); break; } @@ -32,9 +35,8 @@ void TableIndexList::CommitDrop(const string &name) { for (idx_t index_idx = 0; index_idx < indexes.size(); index_idx++) { auto &index_entry = indexes[index_idx]; - if (index_entry->name == name) { + if (index_entry->GetIndexName() == name) { index_entry->CommitDrop(); - break; } } } @@ -46,7 +48,7 @@ bool TableIndexList::NameIsUnique(const string &name) { for (idx_t index_idx = 0; index_idx < indexes.size(); index_idx++) { auto &index_entry = indexes[index_idx]; if (index_entry->IsPrimary() || index_entry->IsForeign() || index_entry->IsUnique()) { - if (index_entry->name == name) { + if (index_entry->GetIndexName() == name) { return false; } } @@ -55,38 +57,53 @@ bool TableIndexList::NameIsUnique(const string &name) { return true; } -void TableIndexList::InitializeIndexes(ClientContext &context, DataTableInfo &table_info, bool throw_on_failure) { - lock_guard lock(indexes_lock); - for (auto &index : indexes) { - if (!index->IsUnknown()) { - continue; - } - - auto &unknown_index = index->Cast(); - auto &index_type_name = unknown_index.GetIndexType(); - - // Do we know the type of this index now? - auto index_type = context.db->config.GetIndexTypes().FindByName(index_type_name); - if (!index_type) { - if (throw_on_failure) { - throw MissingExtensionException( - "Cannot initialize index '%s', unknown index type '%s'. You probably need to load an extension.", - unknown_index.name, index_type_name); +void TableIndexList::InitializeIndexes(ClientContext &context, DataTableInfo &table_info, const char *index_type) { + // Fast path: do we have any unbound indexes? + bool needs_binding = false; + { + lock_guard lock(indexes_lock); + for (auto &index : indexes) { + if (!index->IsBound() && (index_type == nullptr || index->GetIndexType() == index_type)) { + needs_binding = true; + break; } - continue; } + } + if (!needs_binding) { + return; + } - // Swap this with a new index - auto &create_info = unknown_index.GetCreateInfo(); - auto &storage_info = unknown_index.GetStorageInfo(); - - CreateIndexInput input(*table_info.table_io_manager, table_info.db, create_info.constraint_type, - create_info.index_name, create_info.column_ids, unknown_index.unbound_expressions, - storage_info, create_info.options); - - auto index_instance = index_type->create_instance(input); + // Get the table from the catalog so we can add it to the binder + auto &catalog = table_info.GetDB().GetCatalog(); + auto &table = + catalog.GetEntry(context, CatalogType::TABLE_ENTRY, table_info.GetSchemaName(), table_info.GetTableName()) + .Cast(); + vector column_types; + vector column_names; + for (auto &col : table.GetColumns().Logical()) { + column_types.push_back(col.Type()); + column_names.push_back(col.Name()); + } - index = std::move(index_instance); + lock_guard lock(indexes_lock); + for (auto &index : indexes) { + if (!index->IsBound() && (index_type == nullptr || index->GetIndexType() == index_type)) { + // Create a binder to bind this index (we cant reuse this binder for other indexes) + auto binder = Binder::CreateBinder(context); + + // Add the table to the binder + // We're not interested in the column_ids here, so just pass a dummy vector + vector dummy_column_ids; + binder->bind_context.AddBaseTable(0, table_info.GetTableName(), column_names, column_types, + dummy_column_ids, &table); + + // Create an IndexBinder to bind the index + IndexBinder idx_binder(*binder, context); + + // Replace the unbound index with a bound index + auto bound_idx = idx_binder.BindIndex(index->Cast()); + index = std::move(bound_idx); + } } } @@ -127,15 +144,18 @@ void TableIndexList::VerifyForeignKey(const vector &fk_keys, Data if (!index) { throw InternalException("Internal Foreign Key error: could not find index to verify..."); } + if (!index->IsBound()) { + throw InternalException("Internal Foreign Key error: trying to verify an unbound index..."); + } conflict_manager.SetIndexCount(1); - index->CheckConstraintsForChunk(chunk, conflict_manager); + index->Cast().CheckConstraintsForChunk(chunk, conflict_manager); } vector TableIndexList::GetRequiredColumns() { lock_guard lock(indexes_lock); set unique_indexes; for (auto &index : indexes) { - for (auto col_index : index->column_ids) { + for (auto col_index : index->GetColumnIds()) { unique_indexes.insert(col_index); } } @@ -151,9 +171,16 @@ vector TableIndexList::GetStorageInfos() { vector index_storage_infos; for (auto &index : indexes) { - auto index_storage_info = index->GetStorageInfo(false); - D_ASSERT(index_storage_info.IsValid() && !index_storage_info.name.empty()); - index_storage_infos.push_back(index_storage_info); + if (index->IsBound()) { + auto index_storage_info = index->Cast().GetStorageInfo(false); + D_ASSERT(index_storage_info.IsValid() && !index_storage_info.name.empty()); + index_storage_infos.push_back(index_storage_info); + } else { + // TODO: Will/should this ever happen? + auto index_storage_info = index->Cast().GetStorageInfo(); + D_ASSERT(index_storage_info.IsValid() && !index_storage_info.name.empty()); + index_storage_infos.push_back(index_storage_info); + } } return index_storage_infos; } diff --git a/src/storage/version_map.json b/src/storage/version_map.json new file mode 100644 index 00000000000..73d04985ab0 --- /dev/null +++ b/src/storage/version_map.json @@ -0,0 +1,52 @@ +{ + "storage": { + "v0.0.4": 1, + "v0.1.0": 1, + "v0.1.1": 1, + "v0.1.2": 1, + "v0.1.3": 1, + "v0.1.4": 1, + "v0.1.5": 1, + "v0.1.6": 1, + "v0.1.7": 1, + "v0.1.8": 1, + "v0.1.9": 1, + "v0.2.0": 1, + "v0.2.1": 1, + "v0.2.2": 4, + "v0.2.3": 6, + "v0.2.4": 11, + "v0.2.5": 13, + "v0.2.6": 15, + "v0.2.7": 17, + "v0.2.8": 18, + "v0.2.9": 21, + "v0.3.0": 25, + "v0.3.1": 27, + "v0.3.2": 31, + "v0.3.3": 33, + "v0.3.4": 33, + "v0.3.5": 33, + "v0.4.0": 33, + "v0.5.0": 38, + "v0.5.1": 38, + "v0.6.0": 39, + "v0.6.1": 39, + "v0.7.0": 43, + "v0.7.1": 43, + "v0.8.0": 51, + "v0.8.1": 51, + "v0.9.0": 64, + "v0.9.1": 64, + "v0.9.2": 64, + "v0.10.0": 64, + "v0.10.1": 64, + "v0.10.2": 64 + }, + "serialization": { + "v0.10.0": 1, + "v0.10.1": 1, + "v0.10.2": 1, + "latest": 2 + } +} diff --git a/src/storage/wal_replay.cpp b/src/storage/wal_replay.cpp index f0d78083e42..4c3c6f5b849 100644 --- a/src/storage/wal_replay.cpp +++ b/src/storage/wal_replay.cpp @@ -25,7 +25,9 @@ #include "duckdb/common/checksum.hpp" #include "duckdb/execution/index/index_type_set.hpp" #include "duckdb/execution/index/art/art.hpp" +#include "duckdb/main/config.hpp" #include "duckdb/storage/table/delete_state.hpp" +#include "duckdb/transaction/meta_transaction.hpp" namespace duckdb { @@ -161,6 +163,7 @@ class WriteAheadLogDeserializer { //===--------------------------------------------------------------------===// bool WriteAheadLog::Replay(AttachedDatabase &database, unique_ptr handle) { Connection con(database.GetDatabase()); + auto wal_path = handle->GetPath(); BufferedFileReader reader(FileSystem::Get(database), std::move(handle)); if (reader.Finished()) { // WAL is empty @@ -168,7 +171,9 @@ bool WriteAheadLog::Replay(AttachedDatabase &database, unique_ptr ha } con.BeginTransaction(); + MetaTransaction::Get(*con.context).ModifyDatabase(database); + auto &config = DBConfig::GetConfig(database.GetDatabase()); // first deserialize the WAL to look for a checkpoint flag // if there is a checkpoint flag, we might have already flushed the contents of the WAL to disk ReplayState checkpoint_state(database, *con.context); @@ -186,16 +191,10 @@ bool WriteAheadLog::Replay(AttachedDatabase &database, unique_ptr ha } } catch (std::exception &ex) { // LCOV_EXCL_START ErrorData error(ex); - if (error.Type() == ExceptionType::SERIALIZATION) { - // serialization exception - torn WAL - // continue reading - } else { - Printer::PrintF("Exception in WAL playback during initial read: %s\n", error.RawMessage()); - return false; + // ignore serialization exceptions - they signal a torn WAL + if (error.Type() != ExceptionType::SERIALIZATION) { + error.Throw("Failure while replaying WAL file \"" + wal_path + "\": "); } - } catch (...) { - Printer::Print("Unknown Exception in WAL playback during initial read"); - return false; } // LCOV_EXCL_STOP if (checkpoint_state.checkpoint_id.IsValid()) { // there is a checkpoint flag: check if we need to deserialize the WAL @@ -216,7 +215,6 @@ bool WriteAheadLog::Replay(AttachedDatabase &database, unique_ptr ha // replay the WAL // note that everything is wrapped inside a try/catch block here // there can be errors in WAL replay because of a corrupt WAL file - // in this case we should throw a warning but startup anyway try { while (true) { // read the current entry @@ -229,20 +227,23 @@ bool WriteAheadLog::Replay(AttachedDatabase &database, unique_ptr ha break; } con.BeginTransaction(); + MetaTransaction::Get(*con.context).ModifyDatabase(database); } } } catch (std::exception &ex) { // LCOV_EXCL_START + // exception thrown in WAL replay: rollback + con.Query("ROLLBACK"); ErrorData error(ex); - if (error.Type() != ExceptionType::SERIALIZATION) { - // FIXME: this should report a proper warning in the connection - Printer::PrintF("Exception in WAL playback: %s\n", error.RawMessage()); - // exception thrown in WAL replay: rollback + // serialization failure means a truncated WAL + // these failures are ignored unless abort_on_wal_failure is true + // other failures always result in an error + if (config.options.abort_on_wal_failure || error.Type() != ExceptionType::SERIALIZATION) { + error.Throw("Failure while replaying WAL file \"" + wal_path + "\": "); } - con.Rollback(); } catch (...) { - Printer::Print("Unknown Exception in WAL playback: %s\n"); // exception thrown in WAL replay: rollback - con.Rollback(); + con.Query("ROLLBACK"); + throw; } // LCOV_EXCL_STOP return false; } @@ -347,7 +348,7 @@ void WriteAheadLogDeserializer::ReplayCreateTable() { // bind the constraints to the table again auto binder = Binder::CreateBinder(context); auto &schema = catalog.GetSchema(context, info->schema); - auto bound_info = binder->BindCreateTableInfo(std::move(info), schema); + auto bound_info = Binder::BindCreateTableCheckpoint(std::move(info), schema); catalog.CreateTable(context, *bound_info); } @@ -550,7 +551,7 @@ void WriteAheadLogDeserializer::ReplayCreateIndex() { // read the data into a buffer handle shared_ptr block_handle; - buffer_manager.Allocate(MemoryTag::ART_INDEX, Storage::BLOCK_SIZE, false, &block_handle); + buffer_manager.Allocate(MemoryTag::ART_INDEX, block_manager->GetBlockSize(), false, &block_handle); auto buffer_handle = buffer_manager.Pin(block_handle); auto data_ptr = buffer_handle.Ptr(); @@ -581,7 +582,7 @@ void WriteAheadLogDeserializer::ReplayCreateIndex() { // create the index in the catalog auto &table = catalog.GetEntry(context, create_info->schema, info.table).Cast(); auto &index = catalog.CreateIndex(context, info)->Cast(); - index.info = make_shared_ptr(table.GetStorage().info, index.name); + index.info = make_shared_ptr(table.GetStorage().GetDataTableInfo(), index.name); // insert the parsed expressions into the index so that we can (de)serialize them during consecutive checkpoints for (auto &parsed_expr : info.parsed_expressions) { @@ -622,7 +623,7 @@ void WriteAheadLogDeserializer::ReplayCreateIndex() { info.column_ids, unbound_expressions, index_info, info.options); auto index_instance = index_type->create_instance(input); - data_table.info->indexes.AddIndex(std::move(index_instance)); + data_table.AddIndex(std::move(index_instance)); } void WriteAheadLogDeserializer::ReplayDropIndex() { diff --git a/src/storage/write_ahead_log.cpp b/src/storage/write_ahead_log.cpp index 165ef10e88a..b7d06fe219b 100644 --- a/src/storage/write_ahead_log.cpp +++ b/src/storage/write_ahead_log.cpp @@ -10,6 +10,7 @@ #include "duckdb/main/database.hpp" #include "duckdb/parser/parsed_data/alter_table_info.hpp" #include "duckdb/storage/index.hpp" +#include "duckdb/execution/index/bound_index.hpp" #include "duckdb/storage/table/data_table_info.hpp" #include "duckdb/storage/table_io_manager.hpp" #include "duckdb/common/checksum.hpp" @@ -19,28 +20,52 @@ namespace duckdb { const uint64_t WAL_VERSION_NUMBER = 2; -WriteAheadLog::WriteAheadLog(AttachedDatabase &database, const string &path) : skip_writing(false), database(database) { - wal_path = path; - writer = make_uniq(FileSystem::Get(database), path, - FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE | - FileFlags::FILE_FLAGS_APPEND); +WriteAheadLog::WriteAheadLog(AttachedDatabase &database, const string &wal_path) + : database(database), wal_path(wal_path), wal_size(0), initialized(false) { } WriteAheadLog::~WriteAheadLog() { } -int64_t WriteAheadLog::GetWALSize() { - D_ASSERT(writer); - return writer->GetFileSize(); +BufferedFileWriter &WriteAheadLog::Initialize() { + if (initialized) { + return *writer; + } + if (!writer) { + writer = make_uniq(FileSystem::Get(database), wal_path, + FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE | + FileFlags::FILE_FLAGS_APPEND); + wal_size = writer->GetFileSize(); + initialized = true; + } + return *writer; +} + +//! Gets the total bytes written to the WAL since startup +idx_t WriteAheadLog::GetWALSize() { + if (!Initialized()) { + auto &fs = FileSystem::Get(database); + if (!fs.FileExists(wal_path)) { + return 0; + } + Initialize(); + } + return wal_size; } idx_t WriteAheadLog::GetTotalWritten() { - D_ASSERT(writer); + if (!writer) { + return 0; + } return writer->GetTotalWritten(); } -void WriteAheadLog::Truncate(int64_t size) { +void WriteAheadLog::Truncate(idx_t size) { + if (!writer) { + return; + } writer->Truncate(size); + wal_size = writer->GetFileSize(); } void WriteAheadLog::Delete() { @@ -48,9 +73,9 @@ void WriteAheadLog::Delete() { return; } writer.reset(); - auto &fs = FileSystem::Get(database); fs.RemoveFile(wal_path); + wal_size = 0; } //===--------------------------------------------------------------------===// @@ -58,46 +83,42 @@ void WriteAheadLog::Delete() { //===--------------------------------------------------------------------===// class ChecksumWriter : public WriteStream { public: - explicit ChecksumWriter(WriteAheadLog &wal) : wal(wal), stream(wal.GetWriter()) { + explicit ChecksumWriter(WriteAheadLog &wal) : wal(wal) { } void WriteData(const_data_ptr_t buffer, idx_t write_size) override { - if (wal.skip_writing) { - return; - } // buffer data into the memory stream memory_stream.WriteData(buffer, write_size); } void Flush() { - if (wal.skip_writing) { - return; + if (!stream) { + stream = wal.Initialize(); } auto data = memory_stream.GetData(); auto size = memory_stream.GetPosition(); // compute the checksum over the entry auto checksum = Checksum(data, size); // write the checksum and the length of the entry - stream.Write(size); - stream.Write(checksum); + stream->Write(size); + stream->Write(checksum); // write data to the underlying stream - stream.WriteData(memory_stream.GetData(), memory_stream.GetPosition()); + stream->WriteData(memory_stream.GetData(), memory_stream.GetPosition()); // rewind the buffer memory_stream.Rewind(); } private: WriteAheadLog &wal; - WriteStream &stream; + optional_ptr stream; MemoryStream memory_stream; }; class WriteAheadLogSerializer { public: - WriteAheadLogSerializer(WriteAheadLog &wal, WALType wal_type) - : wal(wal), checksum_writer(wal), serializer(checksum_writer) { - if (wal.skip_writing) { - return; + WriteAheadLogSerializer(WriteAheadLog &wal, WALType wal_type) : checksum_writer(wal), serializer(checksum_writer) { + if (!wal.Initialized()) { + wal.Initialize(); } // write a version marker if none has been written yet wal.WriteVersion(); @@ -106,31 +127,21 @@ class WriteAheadLogSerializer { } void End() { - if (wal.skip_writing) { - return; - } serializer.End(); checksum_writer.Flush(); } template void WriteProperty(const field_id_t field_id, const char *tag, const T &value) { - if (wal.skip_writing) { - return; - } serializer.WriteProperty(field_id, tag, value); } template void WriteList(const field_id_t field_id, const char *tag, idx_t count, FUNC func) { - if (wal.skip_writing) { - return; - } serializer.WriteList(field_id, tag, count, func); } private: - WriteAheadLog &wal; ChecksumWriter checksum_writer; BinarySerializer serializer; }; @@ -139,6 +150,7 @@ class WriteAheadLogSerializer { // Write Entries //===--------------------------------------------------------------------===// void WriteAheadLog::WriteVersion() { + D_ASSERT(writer); if (writer->GetFileSize() > 0) { // already written - no need to write a version marker return; @@ -202,10 +214,11 @@ void WriteAheadLog::WriteDropSequence(const SequenceCatalogEntry &entry) { serializer.End(); } -void WriteAheadLog::WriteSequenceValue(const SequenceCatalogEntry &entry, SequenceValue val) { +void WriteAheadLog::WriteSequenceValue(SequenceValue val) { + auto &sequence = *val.entry; WriteAheadLogSerializer serializer(*this, WALType::SEQUENCE_VALUE); - serializer.WriteProperty(101, "schema", entry.schema.name); - serializer.WriteProperty(102, "name", entry.name); + serializer.WriteProperty(101, "schema", sequence.schema.name); + serializer.WriteProperty(102, "name", sequence.name); serializer.WriteProperty(103, "usage_count", val.usage_count); serializer.WriteProperty(104, "counter", val.counter); serializer.End(); @@ -246,7 +259,9 @@ void WriteAheadLog::WriteDropTableMacro(const TableMacroCatalogEntry &entry) { void SerializeIndexToWAL(WriteAheadLogSerializer &serializer, const unique_ptr &index) { - auto index_storage_info = index->GetStorageInfo(true); + // We will never write an index to the WAL that is not bound + D_ASSERT(index->IsBound()); + auto index_storage_info = index->Cast().GetStorageInfo(true); serializer.WriteProperty(102, "index_storage_info", index_storage_info); serializer.WriteList(103, "index_storage", index_storage_info.buffers.size(), [&](Serializer::List &list, idx_t i) { @@ -258,20 +273,16 @@ void SerializeIndexToWAL(WriteAheadLogSerializer &serializer, const unique_ptr(); - auto &indexes = duck_index_entry.GetDataTableInfo().indexes.Indexes(); + auto &indexes = duck_index_entry.GetDataTableInfo().GetIndexes().Indexes(); // get the matching index and serialize its storage info for (auto const &index : indexes) { - if (duck_index_entry.name == index->name) { + if (duck_index_entry.name == index->GetIndexName()) { SerializeIndexToWAL(serializer, index); break; } @@ -331,7 +342,7 @@ void WriteAheadLog::WriteDropSchema(const SchemaCatalogEntry &entry) { //===--------------------------------------------------------------------===// // DATA //===--------------------------------------------------------------------===// -void WriteAheadLog::WriteSetTable(string &schema, string &table) { +void WriteAheadLog::WriteSetTable(const string &schema, const string &table) { WriteAheadLogSerializer serializer(*this, WALType::USE_TABLE); serializer.WriteProperty(101, "schema", schema); serializer.WriteProperty(102, "table", table); @@ -382,7 +393,7 @@ void WriteAheadLog::WriteAlter(const AlterInfo &info) { // FLUSH //===--------------------------------------------------------------------===// void WriteAheadLog::Flush() { - if (skip_writing) { + if (!writer) { return; } @@ -392,6 +403,7 @@ void WriteAheadLog::Flush() { // flushes all changes made to the WAL to disk writer->Sync(); + wal_size = writer->GetFileSize(); } } // namespace duckdb diff --git a/src/transaction/CMakeLists.txt b/src/transaction/CMakeLists.txt index f8dc68b3ed6..9d2d582f723 100644 --- a/src/transaction/CMakeLists.txt +++ b/src/transaction/CMakeLists.txt @@ -10,7 +10,8 @@ add_library_unity( transaction_manager.cpp commit_state.cpp rollback_state.cpp - cleanup_state.cpp) + cleanup_state.cpp + wal_write_state.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/transaction/cleanup_state.cpp b/src/transaction/cleanup_state.cpp index 802405483ae..ab63d7bb175 100644 --- a/src/transaction/cleanup_state.cpp +++ b/src/transaction/cleanup_state.cpp @@ -52,10 +52,7 @@ void CleanupState::CleanupUpdate(UpdateInfo &info) { void CleanupState::CleanupDelete(DeleteInfo &info) { auto version_table = info.table; - D_ASSERT(version_table->info->cardinality >= info.count); - version_table->info->cardinality -= info.count; - - if (version_table->info->indexes.Empty()) { + if (!version_table->HasIndexes()) { // this table has no indexes: no cleanup to be done return; } @@ -67,7 +64,7 @@ void CleanupState::CleanupDelete(DeleteInfo &info) { } // possibly vacuum any indexes in this table later - indexed_tables[current_table->info->table] = current_table; + indexed_tables[current_table->GetTableName()] = current_table; count = 0; if (info.is_consecutive) { diff --git a/src/transaction/commit_state.cpp b/src/transaction/commit_state.cpp index ae78d0d0c84..e3c601cc03b 100644 --- a/src/transaction/commit_state.cpp +++ b/src/transaction/commit_state.cpp @@ -5,14 +5,11 @@ #include "duckdb/catalog/catalog_entry/scalar_macro_catalog_entry.hpp" #include "duckdb/catalog/catalog_entry/type_catalog_entry.hpp" #include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp" -#include "duckdb/catalog/catalog_set.hpp" #include "duckdb/catalog/duck_catalog.hpp" #include "duckdb/common/serializer/binary_deserializer.hpp" #include "duckdb/common/serializer/memory_stream.hpp" -#include "duckdb/storage/data_table.hpp" #include "duckdb/storage/table/chunk_info.hpp" #include "duckdb/storage/table/column_data.hpp" -#include "duckdb/storage/table/row_group.hpp" #include "duckdb/storage/table/row_version_manager.hpp" #include "duckdb/storage/table/update_segment.hpp" #include "duckdb/storage/write_ahead_log.hpp" @@ -22,23 +19,13 @@ namespace duckdb { -CommitState::CommitState(transaction_t commit_id, optional_ptr log) - : log(log), commit_id(commit_id), current_table_info(nullptr) { +CommitState::CommitState(transaction_t commit_id) : commit_id(commit_id) { } -void CommitState::SwitchTable(DataTableInfo *table_info, UndoFlags new_op) { - if (current_table_info != table_info) { - // write the current table to the log - log->WriteSetTable(table_info->schema, table_info->table); - current_table_info = table_info; - } -} - -void CommitState::WriteCatalogEntry(CatalogEntry &entry, data_ptr_t dataptr) { +void CommitState::CommitEntryDrop(CatalogEntry &entry, data_ptr_t dataptr) { if (entry.temporary || entry.Parent().temporary) { return; } - D_ASSERT(log); // look at the type of the parent entry auto &parent = entry.Parent(); @@ -84,36 +71,15 @@ void CommitState::WriteCatalogEntry(CatalogEntry &entry, data_ptr_t dataptr) { default: throw InternalException("Don't know how to alter this type!"); } - - auto &alter_info = parse_info->Cast(); - log->WriteAlter(alter_info); } else { switch (parent.type) { case CatalogType::TABLE_ENTRY: - // CREATE TABLE statement - log->WriteCreateTable(parent.Cast()); - break; case CatalogType::VIEW_ENTRY: - // CREATE VIEW statement - log->WriteCreateView(parent.Cast()); - break; case CatalogType::INDEX_ENTRY: - // CREATE INDEX statement - log->WriteCreateIndex(parent.Cast()); - break; case CatalogType::SEQUENCE_ENTRY: - // CREATE SEQUENCE statement - log->WriteCreateSequence(parent.Cast()); - break; case CatalogType::TYPE_ENTRY: - // CREATE TYPE statement - log->WriteCreateType(parent.Cast()); - break; case CatalogType::MACRO_ENTRY: - log->WriteCreateMacro(parent.Cast()); - break; case CatalogType::TABLE_MACRO_ENTRY: - log->WriteCreateTableMacro(parent.Cast()); break; default: throw InternalException("Don't know how to create this type!"); @@ -121,11 +87,6 @@ void CommitState::WriteCatalogEntry(CatalogEntry &entry, data_ptr_t dataptr) { } break; case CatalogType::SCHEMA_ENTRY: - if (entry.type == CatalogType::RENAMED_ENTRY || entry.type == CatalogType::SCHEMA_ENTRY) { - // ALTER TABLE statement, skip it - return; - } - log->WriteCreateSchema(parent.Cast()); break; case CatalogType::RENAMED_ENTRY: // This is a rename, nothing needs to be done for this @@ -138,43 +99,19 @@ void CommitState::WriteCatalogEntry(CatalogEntry &entry, data_ptr_t dataptr) { // If the table was renamed, we do not need to drop the DataTable. table_entry.CommitDrop(); - log->WriteDropTable(table_entry); break; } - case CatalogType::SCHEMA_ENTRY: - log->WriteDropSchema(entry.Cast()); - break; - case CatalogType::VIEW_ENTRY: - log->WriteDropView(entry.Cast()); - break; - case CatalogType::SEQUENCE_ENTRY: - log->WriteDropSequence(entry.Cast()); - break; - case CatalogType::MACRO_ENTRY: - log->WriteDropMacro(entry.Cast()); - break; - case CatalogType::TABLE_MACRO_ENTRY: - log->WriteDropTableMacro(entry.Cast()); - break; - case CatalogType::TYPE_ENTRY: - log->WriteDropType(entry.Cast()); - break; case CatalogType::INDEX_ENTRY: { auto &index_entry = entry.Cast(); index_entry.CommitDrop(); - log->WriteDropIndex(entry.Cast()); break; } - case CatalogType::RENAMED_ENTRY: - case CatalogType::PREPARED_STATEMENT: - case CatalogType::SCALAR_FUNCTION_ENTRY: - case CatalogType::DEPENDENCY_ENTRY: - // do nothing, prepared statements and scalar functions aren't persisted to disk - break; default: - throw InternalException("Don't know how to drop this type!"); + // no action required + break; } break; + case CatalogType::DATABASE_ENTRY: case CatalogType::PREPARED_STATEMENT: case CatalogType::AGGREGATE_FUNCTION_ENTRY: case CatalogType::SCALAR_FUNCTION_ENTRY: @@ -193,86 +130,6 @@ void CommitState::WriteCatalogEntry(CatalogEntry &entry, data_ptr_t dataptr) { } } -void CommitState::WriteDelete(DeleteInfo &info) { - D_ASSERT(log); - // switch to the current table, if necessary - SwitchTable(info.table->info.get(), UndoFlags::DELETE_TUPLE); - - if (!delete_chunk) { - delete_chunk = make_uniq(); - vector delete_types = {LogicalType::ROW_TYPE}; - delete_chunk->Initialize(Allocator::DefaultAllocator(), delete_types); - } - auto rows = FlatVector::GetData(delete_chunk->data[0]); - if (info.is_consecutive) { - for (idx_t i = 0; i < info.count; i++) { - rows[i] = UnsafeNumericCast(info.base_row + i); - } - } else { - auto delete_rows = info.GetRows(); - for (idx_t i = 0; i < info.count; i++) { - rows[i] = UnsafeNumericCast(info.base_row) + delete_rows[i]; - } - } - delete_chunk->SetCardinality(info.count); - log->WriteDelete(*delete_chunk); -} - -void CommitState::WriteUpdate(UpdateInfo &info) { - D_ASSERT(log); - // switch to the current table, if necessary - auto &column_data = info.segment->column_data; - auto &table_info = column_data.GetTableInfo(); - - SwitchTable(&table_info, UndoFlags::UPDATE_TUPLE); - - // initialize the update chunk - vector update_types; - if (column_data.type.id() == LogicalTypeId::VALIDITY) { - update_types.emplace_back(LogicalType::BOOLEAN); - } else { - update_types.push_back(column_data.type); - } - update_types.emplace_back(LogicalType::ROW_TYPE); - - update_chunk = make_uniq(); - update_chunk->Initialize(Allocator::DefaultAllocator(), update_types); - - // fetch the updated values from the base segment - info.segment->FetchCommitted(info.vector_index, update_chunk->data[0]); - - // write the row ids into the chunk - auto row_ids = FlatVector::GetData(update_chunk->data[1]); - idx_t start = column_data.start + info.vector_index * STANDARD_VECTOR_SIZE; - for (idx_t i = 0; i < info.N; i++) { - row_ids[info.tuples[i]] = UnsafeNumericCast(start + info.tuples[i]); - } - if (column_data.type.id() == LogicalTypeId::VALIDITY) { - // zero-initialize the booleans - // FIXME: this is only required because of NullValue in Vector::Serialize... - auto booleans = FlatVector::GetData(update_chunk->data[0]); - for (idx_t i = 0; i < info.N; i++) { - auto idx = info.tuples[i]; - booleans[idx] = false; - } - } - SelectionVector sel(info.tuples); - update_chunk->Slice(sel, info.N); - - // construct the column index path - vector column_indexes; - reference current_column_data = column_data; - while (current_column_data.get().parent) { - column_indexes.push_back(current_column_data.get().column_index); - current_column_data = *current_column_data.get().parent; - } - column_indexes.push_back(info.column_index); - std::reverse(column_indexes.begin(), column_indexes.end()); - - log->WriteUpdate(*update_chunk, column_indexes); -} - -template void CommitState::CommitEntry(UndoFlags type, data_ptr_t data) { switch (type) { case UndoFlags::CATALOG_ENTRY: { @@ -294,18 +151,13 @@ void CommitState::CommitEntry(UndoFlags type, data_ptr_t data) { // modify catalog on commit duck_catalog.ModifyCatalog(); - if (HAS_LOG) { - // push the catalog update to the WAL - WriteCatalogEntry(*catalog_entry, data + sizeof(CatalogEntry *)); - } + // drop any blocks associated with the catalog entry if possible (e.g. in case of a DROP or ALTER) + CommitEntryDrop(*catalog_entry, data + sizeof(CatalogEntry *)); break; } case UndoFlags::INSERT_TUPLE: { // append: auto info = reinterpret_cast(data); - if (HAS_LOG && !info->table->info->IsTemporary()) { - info->table->WriteToLog(*log, info->start_row, info->count); - } // mark the tuples as committed info->table->CommitAppend(commit_id, info->start_row, info->count); break; @@ -313,9 +165,6 @@ void CommitState::CommitEntry(UndoFlags type, data_ptr_t data) { case UndoFlags::DELETE_TUPLE: { // deletion: auto info = reinterpret_cast(data); - if (HAS_LOG && !info->table->info->IsTemporary()) { - WriteDelete(*info); - } // mark the tuples as committed info->version_info->CommitDelete(info->vector_idx, commit_id, *info); break; @@ -323,12 +172,12 @@ void CommitState::CommitEntry(UndoFlags type, data_ptr_t data) { case UndoFlags::UPDATE_TUPLE: { // update: auto info = reinterpret_cast(data); - if (HAS_LOG && !info->segment->column_data.GetTableInfo().IsTemporary()) { - WriteUpdate(*info); - } info->version_number = commit_id; break; } + case UndoFlags::SEQUENCE_VALUE: { + break; + } default: throw InternalException("UndoBuffer - don't know how to commit this type!"); } @@ -356,7 +205,6 @@ void CommitState::RevertCommit(UndoFlags type, data_ptr_t data) { case UndoFlags::DELETE_TUPLE: { // deletion: auto info = reinterpret_cast(data); - info->table->info->cardinality += info->count; // revert the commit by writing the (uncommitted) transaction_id back into the version info info->version_info->CommitDelete(info->vector_idx, transaction_id, *info); break; @@ -367,12 +215,12 @@ void CommitState::RevertCommit(UndoFlags type, data_ptr_t data) { info->version_number = transaction_id; break; } + case UndoFlags::SEQUENCE_VALUE: { + break; + } default: throw InternalException("UndoBuffer - don't know how to revert commit of this type!"); } } -template void CommitState::CommitEntry(UndoFlags type, data_ptr_t data); -template void CommitState::CommitEntry(UndoFlags type, data_ptr_t data); - } // namespace duckdb diff --git a/src/transaction/duck_transaction.cpp b/src/transaction/duck_transaction.cpp index d2ce36578b2..eba07263424 100644 --- a/src/transaction/duck_transaction.cpp +++ b/src/transaction/duck_transaction.cpp @@ -1,5 +1,5 @@ #include "duckdb/transaction/duck_transaction.hpp" - +#include "duckdb/transaction/duck_transaction_manager.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" #include "duckdb/common/exception.hpp" @@ -16,6 +16,7 @@ #include "duckdb/storage/table/column_data.hpp" #include "duckdb/main/client_data.hpp" #include "duckdb/main/attached_database.hpp" +#include "duckdb/storage/storage_lock.hpp" namespace duckdb { @@ -26,10 +27,11 @@ TransactionData::TransactionData(transaction_t transaction_id_p, transaction_t s : transaction(nullptr), transaction_id(transaction_id_p), start_time(start_time_p) { } -DuckTransaction::DuckTransaction(TransactionManager &manager, ClientContext &context_p, transaction_t start_time, +DuckTransaction::DuckTransaction(DuckTransactionManager &manager, ClientContext &context_p, transaction_t start_time, transaction_t transaction_id) : Transaction(manager, context_p), start_time(start_time), transaction_id(transaction_id), commit_id(0), - highest_active_query(0), undo_buffer(context_p), storage(make_uniq(context_p, *this)) { + highest_active_query(0), transaction_manager(manager), undo_buffer(context_p), + storage(make_uniq(context_p, *this)) { } DuckTransaction::~DuckTransaction() { @@ -122,49 +124,108 @@ UpdateInfo *DuckTransaction::CreateUpdateInfo(idx_t type_size, idx_t entries) { return update_info; } +void DuckTransaction::PushSequenceUsage(SequenceCatalogEntry &sequence, const SequenceData &data) { + lock_guard l(sequence_lock); + auto entry = sequence_usage.find(sequence); + if (entry == sequence_usage.end()) { + auto sequence_ptr = undo_buffer.CreateEntry(UndoFlags::SEQUENCE_VALUE, sizeof(SequenceValue)); + auto sequence_info = reinterpret_cast(sequence_ptr); + sequence_info->entry = &sequence; + sequence_info->usage_count = data.usage_count; + sequence_info->counter = data.counter; + sequence_usage.emplace(sequence, *sequence_info); + } else { + auto &sequence_info = entry->second.get(); + D_ASSERT(RefersToSameObject(*sequence_info.entry, sequence)); + sequence_info.usage_count = data.usage_count; + sequence_info.counter = data.counter; + } +} + bool DuckTransaction::ChangesMade() { return undo_buffer.ChangesMade() || storage->ChangesMade(); } -bool DuckTransaction::AutomaticCheckpoint(AttachedDatabase &db) { +UndoBufferProperties DuckTransaction::GetUndoProperties() { + return undo_buffer.GetProperties(); +} + +bool DuckTransaction::AutomaticCheckpoint(AttachedDatabase &db, const UndoBufferProperties &properties) { + if (!ChangesMade()) { + // read-only transactions cannot trigger an automated checkpoint + return false; + } + if (db.IsReadOnly()) { + // when attaching a database in read-only mode we cannot checkpoint + // note that attaching a database in read-only mode does NOT mean we never make changes + // WAL replay can make changes to the database - but only in the in-memory copy of the + return false; + } + auto &storage_manager = db.GetStorageManager(); + return storage_manager.AutomaticCheckpoint(storage->EstimatedSize() + properties.estimated_size); +} + +bool DuckTransaction::ShouldWriteToWAL(AttachedDatabase &db) { + if (!ChangesMade()) { + return false; + } + if (db.IsSystem()) { + return false; + } auto &storage_manager = db.GetStorageManager(); - return storage_manager.AutomaticCheckpoint(storage->EstimatedSize() + undo_buffer.EstimatedSize()); + auto log = storage_manager.GetWAL(); + if (!log) { + return false; + } + return true; +} + +ErrorData DuckTransaction::WriteToWAL(AttachedDatabase &db, unique_ptr &commit_state) noexcept { + try { + D_ASSERT(ShouldWriteToWAL(db)); + auto &storage_manager = db.GetStorageManager(); + auto log = storage_manager.GetWAL(); + storage->Commit(); + commit_state = storage_manager.GenStorageCommitState(*log); + undo_buffer.WriteToWAL(*log); + } catch (std::exception &ex) { + if (commit_state) { + commit_state->RevertCommit(); + commit_state.reset(); + } + return ErrorData(ex); + } + return ErrorData(); } -ErrorData DuckTransaction::Commit(AttachedDatabase &db, transaction_t commit_id, bool checkpoint) noexcept { +ErrorData DuckTransaction::Commit(AttachedDatabase &db, transaction_t new_commit_id, + unique_ptr commit_state) noexcept { // "checkpoint" parameter indicates if the caller will checkpoint. If checkpoint == // true: Then this function will NOT write to the WAL or flush/persist. // This method only makes commit in memory, expecting caller to checkpoint/flush. // false: Then this function WILL write to the WAL and Flush/Persist it. - this->commit_id = commit_id; - - UndoBuffer::IteratorState iterator_state; - LocalStorage::CommitState commit_state; - unique_ptr storage_commit_state; - optional_ptr log; - if (!db.IsSystem()) { - auto &storage_manager = db.GetStorageManager(); - log = storage_manager.GetWriteAheadLog(); - storage_commit_state = storage_manager.GenStorageCommitState(*this, checkpoint); - } else { - log = nullptr; + this->commit_id = new_commit_id; + if (!ChangesMade()) { + // no need to flush anything if we made no changes + return ErrorData(); } + D_ASSERT(db.IsSystem() || db.IsTemporary() || !IsReadOnly()); + UndoBuffer::IteratorState iterator_state; try { - storage->Commit(commit_state, *this); - undo_buffer.Commit(iterator_state, log, commit_id); - if (log) { - // commit any sequences that were used to the WAL - for (auto &entry : sequence_usage) { - log->WriteSequenceValue(*entry.first, entry.second); - } - } - if (storage_commit_state) { - storage_commit_state->FlushCommit(); + storage->Commit(); + undo_buffer.Commit(iterator_state, commit_id); + if (commit_state) { + // if we have written to the WAL - flush after the commit has been successful + commit_state->FlushCommit(); } return ErrorData(); } catch (std::exception &ex) { undo_buffer.RevertCommit(iterator_state, this->transaction_id); + if (commit_state) { + // if we have written to the WAL - truncate the WAL on failure + commit_state->RevertCommit(); + } return ErrorData(ex); } } @@ -178,4 +239,17 @@ void DuckTransaction::Cleanup() { undo_buffer.Cleanup(); } +void DuckTransaction::SetReadWrite() { + Transaction::SetReadWrite(); + // obtain a shared checkpoint lock to prevent concurrent checkpoints while this transaction is running + write_lock = transaction_manager.SharedCheckpointLock(); +} + +unique_ptr DuckTransaction::TryGetCheckpointLock() { + if (!write_lock) { + throw InternalException("TryUpgradeCheckpointLock - but thread has no shared lock!?"); + } + return transaction_manager.TryUpgradeCheckpointLock(*write_lock); +} + } // namespace duckdb diff --git a/src/transaction/duck_transaction_manager.cpp b/src/transaction/duck_transaction_manager.cpp index 42e099cdf39..5dfa5516db9 100644 --- a/src/transaction/duck_transaction_manager.cpp +++ b/src/transaction/duck_transaction_manager.cpp @@ -17,33 +17,7 @@ namespace duckdb { -struct CheckpointLock { - explicit CheckpointLock(DuckTransactionManager &manager) : manager(manager), is_locked(false) { - } - ~CheckpointLock() { - Unlock(); - } - - DuckTransactionManager &manager; - bool is_locked; - - void Lock() { - D_ASSERT(!manager.thread_is_checkpointing); - manager.thread_is_checkpointing = true; - is_locked = true; - } - void Unlock() { - if (!is_locked) { - return; - } - D_ASSERT(manager.thread_is_checkpointing); - manager.thread_is_checkpointing = false; - is_locked = false; - } -}; - -DuckTransactionManager::DuckTransactionManager(AttachedDatabase &db) - : TransactionManager(db), thread_is_checkpointing(false) { +DuckTransactionManager::DuckTransactionManager(AttachedDatabase &db) : TransactionManager(db) { // start timestamp starts at two current_start_timestamp = 2; // transaction ID starts very high: @@ -68,6 +42,11 @@ DuckTransactionManager &DuckTransactionManager::Get(AttachedDatabase &db) { Transaction &DuckTransactionManager::StartTransaction(ClientContext &context) { // obtain the transaction lock during this function + auto &meta_transaction = MetaTransaction::Get(context); + unique_ptr> start_lock; + if (!meta_transaction.IsReadOnly()) { + start_lock = make_uniq>(start_transaction_lock); + } lock_guard lock(transaction_lock); if (current_start_timestamp >= TRANSACTION_ID_START) { // LCOV_EXCL_START throw InternalException("Cannot start more transactions, ran out of " @@ -91,136 +70,215 @@ Transaction &DuckTransactionManager::StartTransaction(ClientContext &context) { return transaction_ref; } -void DuckTransactionManager::Checkpoint(ClientContext &context, bool force) { +DuckTransactionManager::CheckpointDecision::CheckpointDecision(string reason_p) + : can_checkpoint(false), reason(std::move(reason_p)) { +} + +DuckTransactionManager::CheckpointDecision::CheckpointDecision(CheckpointType type) : can_checkpoint(true), type(type) { +} + +DuckTransactionManager::CheckpointDecision::~CheckpointDecision() { +} + +DuckTransactionManager::CheckpointDecision +DuckTransactionManager::CanCheckpoint(DuckTransaction &transaction, unique_ptr &lock, + const UndoBufferProperties &undo_properties) { + if (db.IsSystem()) { + return CheckpointDecision("system transaction"); + } auto &storage_manager = db.GetStorageManager(); if (storage_manager.InMemory()) { - return; + return CheckpointDecision("in memory db"); } - - // first check if no other thread is checkpointing right now - auto current = &DuckTransaction::Get(context, db); - auto lock = unique_lock(transaction_lock); - if (thread_is_checkpointing) { - throw TransactionException("Cannot CHECKPOINT: another thread is checkpointing right now"); + if (!storage_manager.IsLoaded()) { + return CheckpointDecision("cannot checkpoint while loading"); } - CheckpointLock checkpoint_lock(*this); - checkpoint_lock.Lock(); - if (current->ChangesMade()) { - throw TransactionException("Cannot CHECKPOINT: the current transaction has transaction local changes"); + if (!transaction.AutomaticCheckpoint(db, undo_properties)) { + return CheckpointDecision("no reason to automatically checkpoint"); } - if (!force) { - if (!CanCheckpoint(current).can_checkpoint) { - throw TransactionException("Cannot CHECKPOINT: there are other transactions. Use FORCE CHECKPOINT to abort " - "the other transactions and force a checkpoint"); - } - } else { - lock.unlock(); - - // lock all the clients AND the connection manager now - // this ensures no new queries can be started, and no new connections to the database can be made - // to avoid deadlock we release the transaction lock while locking the clients - auto &connection_manager = ConnectionManager::Get(context); - vector client_locks; - connection_manager.LockClients(client_locks, context); - - lock.lock(); - if (!CanCheckpoint(current).can_checkpoint) { - for (size_t i = 0; i < active_transactions.size(); i++) { - auto &transaction = active_transactions[i]; - // rollback the transaction - transaction->Rollback(); - auto transaction_context = transaction->context.lock(); - - // remove the transaction id from the list of active transactions - // potentially resulting in garbage collection - RemoveTransaction(*transaction); - if (transaction_context) { - // invalidate the active transaction for this connection - auto &meta_transaction = MetaTransaction::Get(*transaction_context); - meta_transaction.RemoveTransaction(db); - ValidChecker::Get(meta_transaction).Invalidate("Invalidated due to FORCE CHECKPOINT"); + // try to lock the checkpoint lock + lock = transaction.TryGetCheckpointLock(); + if (!lock) { + return CheckpointDecision("Failed to obtain checkpoint lock - another thread is writing/checkpointing or " + "another read transaction relies on data that is not yet committed"); + } + auto checkpoint_type = CheckpointType::FULL_CHECKPOINT; + if (undo_properties.has_updates || undo_properties.has_deletes || undo_properties.has_dropped_entries) { + // if we have made updates/deletes/catalog changes in this transaction we might need to change our strategy + // in the presence of other transactions + string other_transactions; + for (auto &active_transaction : active_transactions) { + if (!RefersToSameObject(*active_transaction, transaction)) { + if (!other_transactions.empty()) { + other_transactions += ", "; } - i--; + other_transactions += "[" + to_string(active_transaction->transaction_id) + "]"; + } + } + if (!other_transactions.empty()) { + // there are other transactions! + // these active transactions might need data from BEFORE this transaction + // we might need to change our strategy here based on what changes THIS transaction has made + if (undo_properties.has_dropped_entries) { + // this transaction has changed the catalog - we cannot checkpoint + return CheckpointDecision("Transaction has dropped catalog entries and there are other transactions " + "active\nActive transactions: " + + other_transactions); + } else if (undo_properties.has_updates) { + // this transaction has performed updates - we cannot checkpoint + return CheckpointDecision( + "Transaction has performed updates and there are other transactions active\nActive transactions: " + + other_transactions); + } else { + // this transaction has performed deletes - we cannot vacuum - initiate a concurrent checkpoint instead + D_ASSERT(undo_properties.has_deletes); + checkpoint_type = CheckpointType::CONCURRENT_CHECKPOINT; } - D_ASSERT(CanCheckpoint(nullptr).can_checkpoint); } } - storage_manager.CreateCheckpoint(); + return CheckpointDecision(checkpoint_type); } -DuckTransactionManager::CheckpointDecision -DuckTransactionManager::CanCheckpoint(optional_ptr current) { - if (db.IsSystem()) { - return {false, "system transaction"}; - } +void DuckTransactionManager::Checkpoint(ClientContext &context, bool force) { auto &storage_manager = db.GetStorageManager(); if (storage_manager.InMemory()) { - return {false, "in memory db"}; - } - auto trans_to_string = [](const unique_ptr &t) { - return std::to_string(t->transaction_id); - }; - if (!recently_committed_transactions.empty()) { - return {false, "recently committed transactions: [" + - StringUtil::Join(recently_committed_transactions, recently_committed_transactions.size(), - ",", trans_to_string) + - "]"}; + return; } - if (!old_transactions.empty()) { - return {false, "old transactions: [" + - StringUtil::Join(old_transactions, old_transactions.size(), ",", trans_to_string) + "]"}; + + auto current = Transaction::TryGet(context, db); + if (current) { + if (force) { + throw TransactionException( + "Cannot FORCE CHECKPOINT: the current transaction has been started for this database"); + } else { + auto &duck_transaction = current->Cast(); + if (duck_transaction.ChangesMade()) { + throw TransactionException("Cannot CHECKPOINT: the current transaction has transaction local changes"); + } + } } - for (auto &transaction : active_transactions) { - if (transaction.get() != current.get()) { - return {false, "current transaction [" + std::to_string(current->transaction_id) + "] isn't active"}; + unique_ptr lock; + if (!force) { + // not a force checkpoint + // try to get the checkpoint lock + lock = checkpoint_lock.TryGetExclusiveLock(); + if (!lock) { + // we could not manage to get the lock - cancel + throw TransactionException( + "Cannot CHECKPOINT: there are other write transactions active. Use FORCE CHECKPOINT to abort " + "the other transactions and force a checkpoint"); + } + + } else { + // force checkpoint - wait to get an exclusive lock + // grab the start_transaction_lock to prevent new transactions from starting + lock_guard start_lock(start_transaction_lock); + // wait until any active transactions are finished + while (!lock) { + if (context.interrupted) { + throw InterruptException(); + } + lock = checkpoint_lock.TryGetExclusiveLock(); } } - return {true, ""}; + CheckpointOptions options; + if (GetLastCommit() > LowestActiveStart()) { + // we cannot do a full checkpoint if any transaction needs to read old data + options.type = CheckpointType::CONCURRENT_CHECKPOINT; + } + storage_manager.CreateCheckpoint(options); +} + +unique_ptr DuckTransactionManager::SharedCheckpointLock() { + return checkpoint_lock.GetSharedLock(); +} + +unique_ptr DuckTransactionManager::TryUpgradeCheckpointLock(StorageLockKey &lock) { + return checkpoint_lock.TryUpgradeCheckpointLock(lock); +} + +transaction_t DuckTransactionManager::GetCommitTimestamp() { + auto commit_ts = current_start_timestamp++; + last_commit = commit_ts; + return commit_ts; } ErrorData DuckTransactionManager::CommitTransaction(ClientContext &context, Transaction &transaction_p) { auto &transaction = transaction_p.Cast(); - vector client_locks; - auto lock = make_uniq>(transaction_lock); - CheckpointLock checkpoint_lock(*this); - // check if we can checkpoint - auto checkpoint_decision = thread_is_checkpointing ? CheckpointDecision {false, "another thread is checkpointing"} - : CanCheckpoint(&transaction); - if (checkpoint_decision.can_checkpoint) { - if (transaction.AutomaticCheckpoint(db)) { - checkpoint_lock.Lock(); - } else { - checkpoint_decision = {false, "no reason to automatically checkpoint"}; + unique_lock tlock(transaction_lock); + if (!db.IsSystem() && !db.IsTemporary()) { + if (transaction.ChangesMade()) { + if (transaction.IsReadOnly()) { + throw InternalException("Attempting to commit a transaction that is read-only but has made changes - " + "this should not be possible"); + } } } - OnCommitCheckpointDecision(checkpoint_decision, transaction); + // check if we can checkpoint + unique_ptr lock; + auto undo_properties = transaction.GetUndoProperties(); + auto checkpoint_decision = CanCheckpoint(transaction, lock, undo_properties); + ErrorData error; + unique_ptr> held_wal_lock; + unique_ptr commit_state; + if (!checkpoint_decision.can_checkpoint && transaction.ShouldWriteToWAL(db)) { + // if we are committing changes and we are not checkpointing, we need to write to the WAL + // since WAL writes can take a long time - we grab the WAL lock here and unlock the transaction lock + // read-only transactions can bypass this branch and start/commit while the WAL write is happening + if (!transaction.HasWriteLock()) { + // sanity check - this transaction should have a write lock + // the write lock prevents other transactions from checkpointing until this transaction is fully finished + // if we do not hold the write lock here, other transactions can bypass this branch by auto-checkpoint + // this would lead to a checkpoint WHILE this thread is writing to the WAL + // this should never happen + throw InternalException("Transaction writing to WAL does not have the write lock"); + } + // unlock the transaction lock while we write to the WAL + tlock.unlock(); + // grab the WAL lock and hold it until the entire commit is finished + held_wal_lock = make_uniq>(wal_lock); + error = transaction.WriteToWAL(db, commit_state); + + // after we finish writing to the WAL we grab the transaction lock again + tlock.lock(); + } // obtain a commit id for the transaction - transaction_t commit_id = current_start_timestamp++; + transaction_t commit_id = GetCommitTimestamp(); // commit the UndoBuffer of the transaction - auto error = transaction.Commit(db, commit_id, checkpoint_decision.can_checkpoint); + if (!error.HasError()) { + error = transaction.Commit(db, commit_id, std::move(commit_state)); + } if (error.HasError()) { // commit unsuccessful: rollback the transaction instead - checkpoint_decision = CheckpointDecision {false, error.Message()}; + checkpoint_decision = CheckpointDecision(error.Message()); transaction.commit_id = 0; transaction.Rollback(); } - if (!checkpoint_decision.can_checkpoint) { - // we won't checkpoint after all: unlock the clients again - checkpoint_lock.Unlock(); - client_locks.clear(); + OnCommitCheckpointDecision(checkpoint_decision, transaction); + + if (!checkpoint_decision.can_checkpoint && lock) { + // we won't checkpoint after all: unlock the checkpoint lock again + lock.reset(); } // commit successful: remove the transaction id from the list of active transactions // potentially resulting in garbage collection - RemoveTransaction(transaction); + bool store_transaction = undo_properties.has_updates || undo_properties.has_catalog_changes || error.HasError(); + RemoveTransaction(transaction, store_transaction); // now perform a checkpoint if (1) we are able to checkpoint, and (2) the WAL has reached sufficient size to // checkpoint if (checkpoint_decision.can_checkpoint) { + D_ASSERT(lock); + // we can unlock the transaction lock while checkpointing + tlock.unlock(); // checkpoint the database to disk + CheckpointOptions options; + options.action = CheckpointAction::FORCE_CHECKPOINT; + options.type = checkpoint_decision.type; auto &storage_manager = db.GetStorageManager(); - storage_manager.CreateCheckpoint(false, true); + storage_manager.CreateCheckpoint(options); } return error; } @@ -239,7 +297,10 @@ void DuckTransactionManager::RollbackTransaction(Transaction &transaction_p) { } void DuckTransactionManager::RemoveTransaction(DuckTransaction &transaction) noexcept { - bool changes_made = transaction.ChangesMade(); + RemoveTransaction(transaction, transaction.ChangesMade()); +} + +void DuckTransactionManager::RemoveTransaction(DuckTransaction &transaction, bool store_transaction) noexcept { // remove the transaction from the list of active transactions idx_t t_index = active_transactions.size(); // check for the lowest and highest start time in the list of transactions @@ -263,7 +324,7 @@ void DuckTransactionManager::RemoveTransaction(DuckTransaction &transaction) noe D_ASSERT(t_index != active_transactions.size()); auto current_transaction = std::move(active_transactions[t_index]); auto current_query = DatabaseManager::Get(db).ActiveQueryNumber(); - if (changes_made) { + if (store_transaction) { // if the transaction made any changes we need to keep it around if (transaction.commit_id != 0) { // the transaction was committed, add it to the list of recently @@ -275,6 +336,8 @@ void DuckTransactionManager::RemoveTransaction(DuckTransaction &transaction) noe current_transaction->highest_active_query = current_query; old_transactions.push_back(std::move(current_transaction)); } + } else if (transaction.ChangesMade()) { + transaction.Cleanup(); } // remove the transaction from the set of currently active transactions active_transactions.unsafe_erase_at(t_index); diff --git a/src/transaction/meta_transaction.cpp b/src/transaction/meta_transaction.cpp index 6cf12cca5d2..697dbcc6874 100644 --- a/src/transaction/meta_transaction.cpp +++ b/src/transaction/meta_transaction.cpp @@ -7,8 +7,8 @@ namespace duckdb { MetaTransaction::MetaTransaction(ClientContext &context_p, timestamp_t start_timestamp_p, idx_t catalog_version_p) - : context(context_p), start_timestamp(start_timestamp_p), catalog_version(catalog_version_p), read_only(true), - active_query(MAXIMUM_QUERY_ID), modified_database(nullptr) { + : context(context_p), start_timestamp(start_timestamp_p), catalog_version(catalog_version_p), + active_query(MAXIMUM_QUERY_ID), modified_database(nullptr), is_read_only(false) { } MetaTransaction &MetaTransaction::Get(ClientContext &context) { @@ -24,6 +24,11 @@ Transaction &Transaction::Get(ClientContext &context, AttachedDatabase &db) { return meta_transaction.GetTransaction(db); } +optional_ptr Transaction::TryGet(ClientContext &context, AttachedDatabase &db) { + auto &meta_transaction = MetaTransaction::Get(context); + return meta_transaction.TryGetTransaction(db); +} + #ifdef DEBUG static void VerifyAllTransactionsUnique(AttachedDatabase &db, vector> &all_transactions) { for (auto &tx : all_transactions) { @@ -34,6 +39,16 @@ static void VerifyAllTransactionsUnique(AttachedDatabase &db, vector MetaTransaction::TryGetTransaction(AttachedDatabase &db) { + lock_guard guard(lock); + auto entry = transactions.find(db); + if (entry == transactions.end()) { + return nullptr; + } else { + return &entry->second.get(); + } +} + Transaction &MetaTransaction::GetTransaction(AttachedDatabase &db) { lock_guard guard(lock); auto entry = transactions.find(db); @@ -69,6 +84,17 @@ void MetaTransaction::RemoveTransaction(AttachedDatabase &db) { } } +void MetaTransaction::SetReadOnly() { + if (modified_database) { + throw InternalException("Cannot set MetaTransaction to read only - modifications have already been made"); + } + this->is_read_only = true; +} + +bool MetaTransaction::IsReadOnly() const { + return is_read_only; +} + Transaction &Transaction::Get(ClientContext &context, Catalog &catalog) { return Transaction::Get(context, catalog.GetAttached()); } @@ -132,8 +158,15 @@ void MetaTransaction::ModifyDatabase(AttachedDatabase &db) { // we can always modify the system and temp databases return; } + if (IsReadOnly()) { + throw TransactionException("Cannot write to database \"%s\" - transaction is launched in read-only mode", + db.GetName()); + } if (!modified_database) { modified_database = &db; + + auto &transaction = GetTransaction(db); + transaction.SetReadWrite(); return; } if (&db != modified_database.get()) { diff --git a/src/transaction/rollback_state.cpp b/src/transaction/rollback_state.cpp index 3210cffb465..f7d1410c7da 100644 --- a/src/transaction/rollback_state.cpp +++ b/src/transaction/rollback_state.cpp @@ -39,6 +39,8 @@ void RollbackState::RollbackEntry(UndoFlags type, data_ptr_t data) { info->segment->RollbackUpdate(*info); break; } + case UndoFlags::SEQUENCE_VALUE: + break; default: // LCOV_EXCL_START D_ASSERT(type == UndoFlags::EMPTY_ENTRY); break; diff --git a/src/transaction/transaction.cpp b/src/transaction/transaction.cpp index 5c37879d1a3..1f18a6d564e 100644 --- a/src/transaction/transaction.cpp +++ b/src/transaction/transaction.cpp @@ -6,19 +6,19 @@ namespace duckdb { Transaction::Transaction(TransactionManager &manager_p, ClientContext &context_p) - : manager(manager_p), context(context_p.shared_from_this()), active_query(MAXIMUM_QUERY_ID) { + : manager(manager_p), context(context_p.shared_from_this()), active_query(MAXIMUM_QUERY_ID), is_read_only(true) { } Transaction::~Transaction() { } bool Transaction::IsReadOnly() { - auto ctxt = context.lock(); - if (!ctxt) { - throw InternalException("Transaction::IsReadOnly() called after client context has been destroyed"); - } - auto &db = manager.GetDB(); - return MetaTransaction::Get(*ctxt).ModifiedDatabase().get() != &db; + return is_read_only; +} + +void Transaction::SetReadWrite() { + D_ASSERT(is_read_only); + is_read_only = false; } } // namespace duckdb diff --git a/src/transaction/transaction_context.cpp b/src/transaction/transaction_context.cpp index 7185a263894..fa9327a8c3c 100644 --- a/src/transaction/transaction_context.cpp +++ b/src/transaction/transaction_context.cpp @@ -64,6 +64,10 @@ void TransactionContext::SetAutoCommit(bool value) { } } +void TransactionContext::SetReadOnly() { + current_transaction->SetReadOnly(); +} + void TransactionContext::Rollback() { if (!current_transaction) { throw TransactionException("failed to rollback: no transaction active"); diff --git a/src/transaction/undo_buffer.cpp b/src/transaction/undo_buffer.cpp index 2e94aa7fef6..69a63b946b3 100644 --- a/src/transaction/undo_buffer.cpp +++ b/src/transaction/undo_buffer.cpp @@ -10,6 +10,8 @@ #include "duckdb/transaction/cleanup_state.hpp" #include "duckdb/transaction/commit_state.hpp" #include "duckdb/transaction/rollback_state.hpp" +#include "duckdb/execution/index/bound_index.hpp" +#include "duckdb/transaction/wal_write_state.hpp" namespace duckdb { constexpr uint32_t UNDO_ENTRY_HEADER_SIZE = sizeof(UndoFlags) + sizeof(uint32_t); @@ -99,31 +101,55 @@ void UndoBuffer::ReverseIterateEntries(T &&callback) { } bool UndoBuffer::ChangesMade() { + // we need to search for any index creation entries return !allocator.IsEmpty(); } -idx_t UndoBuffer::EstimatedSize() { - - idx_t estimated_size = 0; +UndoBufferProperties UndoBuffer::GetProperties() { + UndoBufferProperties properties; + if (!ChangesMade()) { + return properties; + } auto node = allocator.GetHead(); while (node) { - estimated_size += node->current_position; + properties.estimated_size += node->current_position; node = node->next.get(); } // we need to search for any index creation entries IteratorState iterator_state; IterateEntries(iterator_state, [&](UndoFlags entry_type, data_ptr_t data) { - if (entry_type == UndoFlags::CATALOG_ENTRY) { + switch (entry_type) { + case UndoFlags::UPDATE_TUPLE: + properties.has_updates = true; + break; + case UndoFlags::DELETE_TUPLE: + properties.has_deletes = true; + break; + case UndoFlags::CATALOG_ENTRY: { + properties.has_catalog_changes = true; + auto catalog_entry = Load(data); - if (catalog_entry->Parent().type == CatalogType::INDEX_ENTRY) { - auto &index = catalog_entry->Parent().Cast(); - estimated_size += index.initial_index_size; + auto &parent = catalog_entry->Parent(); + switch (parent.type) { + case CatalogType::DELETED_ENTRY: + properties.has_dropped_entries = true; + break; + case CatalogType::INDEX_ENTRY: { + auto &index = parent.Cast(); + properties.estimated_size += index.initial_index_size; + break; + } + default: + break; } + break; + } + default: + break; } }); - - return estimated_size; + return properties; } void UndoBuffer::Cleanup() { @@ -140,30 +166,24 @@ void UndoBuffer::Cleanup() { IterateEntries(iterator_state, [&](UndoFlags type, data_ptr_t data) { state.CleanupEntry(type, data); }); // possibly vacuum indexes - for (const auto &table : state.indexed_tables) { - table.second->info->indexes.Scan([&](Index &index) { - if (!index.IsUnknown()) { - index.Vacuum(); - } - return false; - }); + for (auto &table : state.indexed_tables) { + table.second->VacuumIndexes(); } } -void UndoBuffer::Commit(UndoBuffer::IteratorState &iterator_state, optional_ptr log, - transaction_t commit_id) { - CommitState state(commit_id, log); - if (log) { - // commit WITH write ahead log - IterateEntries(iterator_state, [&](UndoFlags type, data_ptr_t data) { state.CommitEntry(type, data); }); - } else { - // commit WITHOUT write ahead log - IterateEntries(iterator_state, [&](UndoFlags type, data_ptr_t data) { state.CommitEntry(type, data); }); - } +void UndoBuffer::WriteToWAL(WriteAheadLog &wal) { + WALWriteState state(wal); + UndoBuffer::IteratorState iterator_state; + IterateEntries(iterator_state, [&](UndoFlags type, data_ptr_t data) { state.CommitEntry(type, data); }); +} + +void UndoBuffer::Commit(UndoBuffer::IteratorState &iterator_state, transaction_t commit_id) { + CommitState state(commit_id); + IterateEntries(iterator_state, [&](UndoFlags type, data_ptr_t data) { state.CommitEntry(type, data); }); } void UndoBuffer::RevertCommit(UndoBuffer::IteratorState &end_state, transaction_t transaction_id) { - CommitState state(transaction_id, nullptr); + CommitState state(transaction_id); UndoBuffer::IteratorState start_state; IterateEntries(start_state, end_state, [&](UndoFlags type, data_ptr_t data) { state.RevertCommit(type, data); }); } diff --git a/src/transaction/wal_write_state.cpp b/src/transaction/wal_write_state.cpp new file mode 100644 index 00000000000..133973d02fe --- /dev/null +++ b/src/transaction/wal_write_state.cpp @@ -0,0 +1,291 @@ +#include "duckdb/transaction/wal_write_state.hpp" + +#include "duckdb/catalog/catalog_entry/duck_index_entry.hpp" +#include "duckdb/catalog/catalog_entry/duck_table_entry.hpp" +#include "duckdb/catalog/catalog_entry/scalar_macro_catalog_entry.hpp" +#include "duckdb/catalog/catalog_entry/type_catalog_entry.hpp" +#include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp" +#include "duckdb/catalog/catalog_set.hpp" +#include "duckdb/catalog/duck_catalog.hpp" +#include "duckdb/common/serializer/binary_deserializer.hpp" +#include "duckdb/common/serializer/memory_stream.hpp" +#include "duckdb/storage/data_table.hpp" +#include "duckdb/storage/table/chunk_info.hpp" +#include "duckdb/storage/table/column_data.hpp" +#include "duckdb/storage/table/row_group.hpp" +#include "duckdb/storage/table/row_version_manager.hpp" +#include "duckdb/storage/table/update_segment.hpp" +#include "duckdb/storage/write_ahead_log.hpp" +#include "duckdb/transaction/append_info.hpp" +#include "duckdb/transaction/delete_info.hpp" +#include "duckdb/transaction/update_info.hpp" + +namespace duckdb { + +WALWriteState::WALWriteState(WriteAheadLog &log) : log(log), current_table_info(nullptr) { +} + +void WALWriteState::SwitchTable(DataTableInfo *table_info, UndoFlags new_op) { + if (current_table_info != table_info) { + // write the current table to the log + log.WriteSetTable(table_info->GetSchemaName(), table_info->GetTableName()); + current_table_info = table_info; + } +} + +void WALWriteState::WriteCatalogEntry(CatalogEntry &entry, data_ptr_t dataptr) { + if (entry.temporary || entry.Parent().temporary) { + return; + } + + // look at the type of the parent entry + auto &parent = entry.Parent(); + + switch (parent.type) { + case CatalogType::TABLE_ENTRY: + case CatalogType::VIEW_ENTRY: + case CatalogType::INDEX_ENTRY: + case CatalogType::SEQUENCE_ENTRY: + case CatalogType::TYPE_ENTRY: + case CatalogType::MACRO_ENTRY: + case CatalogType::TABLE_MACRO_ENTRY: + if (entry.type == CatalogType::RENAMED_ENTRY || entry.type == parent.type) { + // ALTER statement, read the extra data after the entry + auto extra_data_size = Load(dataptr); + auto extra_data = data_ptr_cast(dataptr + sizeof(idx_t)); + + MemoryStream source(extra_data, extra_data_size); + BinaryDeserializer deserializer(source); + deserializer.Begin(); + auto column_name = deserializer.ReadProperty(100, "column_name"); + auto parse_info = deserializer.ReadProperty>(101, "alter_info"); + deserializer.End(); + + auto &alter_info = parse_info->Cast(); + log.WriteAlter(alter_info); + } else { + switch (parent.type) { + case CatalogType::TABLE_ENTRY: + // CREATE TABLE statement + log.WriteCreateTable(parent.Cast()); + break; + case CatalogType::VIEW_ENTRY: + // CREATE VIEW statement + log.WriteCreateView(parent.Cast()); + break; + case CatalogType::INDEX_ENTRY: + // CREATE INDEX statement + log.WriteCreateIndex(parent.Cast()); + break; + case CatalogType::SEQUENCE_ENTRY: + // CREATE SEQUENCE statement + log.WriteCreateSequence(parent.Cast()); + break; + case CatalogType::TYPE_ENTRY: + // CREATE TYPE statement + log.WriteCreateType(parent.Cast()); + break; + case CatalogType::MACRO_ENTRY: + log.WriteCreateMacro(parent.Cast()); + break; + case CatalogType::TABLE_MACRO_ENTRY: + log.WriteCreateTableMacro(parent.Cast()); + break; + default: + throw InternalException("Don't know how to create this type!"); + } + } + break; + case CatalogType::SCHEMA_ENTRY: + if (entry.type == CatalogType::RENAMED_ENTRY || entry.type == CatalogType::SCHEMA_ENTRY) { + // ALTER TABLE statement, skip it + return; + } + log.WriteCreateSchema(parent.Cast()); + break; + case CatalogType::RENAMED_ENTRY: + // This is a rename, nothing needs to be done for this + break; + case CatalogType::DELETED_ENTRY: + switch (entry.type) { + case CatalogType::TABLE_ENTRY: { + auto &table_entry = entry.Cast(); + D_ASSERT(table_entry.IsDuckTable()); + log.WriteDropTable(table_entry); + break; + } + case CatalogType::SCHEMA_ENTRY: + log.WriteDropSchema(entry.Cast()); + break; + case CatalogType::VIEW_ENTRY: + log.WriteDropView(entry.Cast()); + break; + case CatalogType::SEQUENCE_ENTRY: + log.WriteDropSequence(entry.Cast()); + break; + case CatalogType::MACRO_ENTRY: + log.WriteDropMacro(entry.Cast()); + break; + case CatalogType::TABLE_MACRO_ENTRY: + log.WriteDropTableMacro(entry.Cast()); + break; + case CatalogType::TYPE_ENTRY: + log.WriteDropType(entry.Cast()); + break; + case CatalogType::INDEX_ENTRY: { + log.WriteDropIndex(entry.Cast()); + break; + } + case CatalogType::RENAMED_ENTRY: + case CatalogType::PREPARED_STATEMENT: + case CatalogType::SCALAR_FUNCTION_ENTRY: + case CatalogType::DEPENDENCY_ENTRY: + case CatalogType::SECRET_ENTRY: + case CatalogType::SECRET_TYPE_ENTRY: + case CatalogType::SECRET_FUNCTION_ENTRY: + // do nothing, prepared statements and scalar functions aren't persisted to disk + break; + default: + throw InternalException("Don't know how to drop this type!"); + } + break; + case CatalogType::PREPARED_STATEMENT: + case CatalogType::AGGREGATE_FUNCTION_ENTRY: + case CatalogType::SCALAR_FUNCTION_ENTRY: + case CatalogType::TABLE_FUNCTION_ENTRY: + case CatalogType::COPY_FUNCTION_ENTRY: + case CatalogType::PRAGMA_FUNCTION_ENTRY: + case CatalogType::COLLATION_ENTRY: + case CatalogType::DEPENDENCY_ENTRY: + case CatalogType::SECRET_ENTRY: + case CatalogType::SECRET_TYPE_ENTRY: + case CatalogType::SECRET_FUNCTION_ENTRY: + // do nothing, these entries are not persisted to disk + break; + default: + throw InternalException("UndoBuffer - don't know how to write this entry to the WAL"); + } +} + +void WALWriteState::WriteDelete(DeleteInfo &info) { + // switch to the current table, if necessary + SwitchTable(info.table->GetDataTableInfo().get(), UndoFlags::DELETE_TUPLE); + + if (!delete_chunk) { + delete_chunk = make_uniq(); + vector delete_types = {LogicalType::ROW_TYPE}; + delete_chunk->Initialize(Allocator::DefaultAllocator(), delete_types); + } + auto rows = FlatVector::GetData(delete_chunk->data[0]); + if (info.is_consecutive) { + for (idx_t i = 0; i < info.count; i++) { + rows[i] = UnsafeNumericCast(info.base_row + i); + } + } else { + auto delete_rows = info.GetRows(); + for (idx_t i = 0; i < info.count; i++) { + rows[i] = UnsafeNumericCast(info.base_row) + delete_rows[i]; + } + } + delete_chunk->SetCardinality(info.count); + log.WriteDelete(*delete_chunk); +} + +void WALWriteState::WriteUpdate(UpdateInfo &info) { + // switch to the current table, if necessary + auto &column_data = info.segment->column_data; + auto &table_info = column_data.GetTableInfo(); + + SwitchTable(&table_info, UndoFlags::UPDATE_TUPLE); + + // initialize the update chunk + vector update_types; + if (column_data.type.id() == LogicalTypeId::VALIDITY) { + update_types.emplace_back(LogicalType::BOOLEAN); + } else { + update_types.push_back(column_data.type); + } + update_types.emplace_back(LogicalType::ROW_TYPE); + + update_chunk = make_uniq(); + update_chunk->Initialize(Allocator::DefaultAllocator(), update_types); + + // fetch the updated values from the base segment + info.segment->FetchCommitted(info.vector_index, update_chunk->data[0]); + + // write the row ids into the chunk + auto row_ids = FlatVector::GetData(update_chunk->data[1]); + idx_t start = column_data.start + info.vector_index * STANDARD_VECTOR_SIZE; + for (idx_t i = 0; i < info.N; i++) { + row_ids[info.tuples[i]] = UnsafeNumericCast(start + info.tuples[i]); + } + if (column_data.type.id() == LogicalTypeId::VALIDITY) { + // zero-initialize the booleans + // FIXME: this is only required because of NullValue in Vector::Serialize... + auto booleans = FlatVector::GetData(update_chunk->data[0]); + for (idx_t i = 0; i < info.N; i++) { + auto idx = info.tuples[i]; + booleans[idx] = false; + } + } + SelectionVector sel(info.tuples); + update_chunk->Slice(sel, info.N); + + // construct the column index path + vector column_indexes; + reference current_column_data = column_data; + while (current_column_data.get().parent) { + column_indexes.push_back(current_column_data.get().column_index); + current_column_data = *current_column_data.get().parent; + } + column_indexes.push_back(info.column_index); + std::reverse(column_indexes.begin(), column_indexes.end()); + + log.WriteUpdate(*update_chunk, column_indexes); +} + +void WALWriteState::CommitEntry(UndoFlags type, data_ptr_t data) { + switch (type) { + case UndoFlags::CATALOG_ENTRY: { + // set the commit timestamp of the catalog entry to the given id + auto catalog_entry = Load(data); + D_ASSERT(catalog_entry->HasParent()); + // push the catalog update to the WAL + WriteCatalogEntry(*catalog_entry, data + sizeof(CatalogEntry *)); + break; + } + case UndoFlags::INSERT_TUPLE: { + // append: + auto info = reinterpret_cast(data); + if (!info->table->IsTemporary()) { + info->table->WriteToLog(log, info->start_row, info->count); + } + break; + } + case UndoFlags::DELETE_TUPLE: { + // deletion: + auto info = reinterpret_cast(data); + if (!info->table->IsTemporary()) { + WriteDelete(*info); + } + break; + } + case UndoFlags::UPDATE_TUPLE: { + // update: + auto info = reinterpret_cast(data); + if (!info->segment->column_data.GetTableInfo().IsTemporary()) { + WriteUpdate(*info); + } + break; + } + case UndoFlags::SEQUENCE_VALUE: { + auto info = reinterpret_cast(data); + log.WriteSequenceValue(*info); + break; + } + default: + throw InternalException("UndoBuffer - don't know how to commit this type!"); + } +} + +} // namespace duckdb diff --git a/test/api/adbc/test_adbc.cpp b/test/api/adbc/test_adbc.cpp index d612a43d7fc..04e35d16ab9 100644 --- a/test/api/adbc/test_adbc.cpp +++ b/test/api/adbc/test_adbc.cpp @@ -848,7 +848,7 @@ TEST_CASE("Test ADBC ConnectionGetTableSchema", "[adbc]") { // Test successful schema return REQUIRE(SUCCESS( AdbcConnectionGetTableSchema(&adbc_connection, nullptr, "main", "duckdb_indexes", &arrow_schema, &adbc_error))); - REQUIRE(arrow_schema.n_children == 13); + REQUIRE(arrow_schema.n_children == 14); arrow_schema.release(&arrow_schema); // Test Catalog Name @@ -859,13 +859,13 @@ TEST_CASE("Test ADBC ConnectionGetTableSchema", "[adbc]") { REQUIRE(SUCCESS(AdbcConnectionGetTableSchema(&adbc_connection, "memory", "main", "duckdb_indexes", &arrow_schema, &adbc_error))); - REQUIRE(arrow_schema.n_children == 13); + REQUIRE(arrow_schema.n_children == 14); arrow_schema.release(&arrow_schema); // Empty schema should be fine REQUIRE(SUCCESS( AdbcConnectionGetTableSchema(&adbc_connection, nullptr, "", "duckdb_indexes", &arrow_schema, &adbc_error))); - REQUIRE(arrow_schema.n_children == 13); + REQUIRE(arrow_schema.n_children == 14); arrow_schema.release(&arrow_schema); // Test null and empty table name @@ -975,8 +975,7 @@ TEST_CASE("Test ADBC Substrait", "[adbc]") { // Broken Plan REQUIRE(!SUCCESS(AdbcStatementSetSubstraitPlan(&adbc_statement, plan, 5, &adbc_error))); - REQUIRE(std::strcmp(adbc_error.message, "Conversion Error: Invalid hex escape code encountered in string -> blob " - "conversion: unterminated escape code at end of blob") == 0); + REQUIRE(StringUtil::Contains(adbc_error.message, "unterminated escape code at end of blob")); REQUIRE(SUCCESS(AdbcStatementRelease(&adbc_statement, &adbc_error))); REQUIRE(SUCCESS(AdbcConnectionRelease(&adbc_connection, &adbc_error))); diff --git a/test/api/capi/CMakeLists.txt b/test/api/capi/CMakeLists.txt index 0ec21685214..f9faa782f91 100644 --- a/test/api/capi/CMakeLists.txt +++ b/test/api/capi/CMakeLists.txt @@ -1,6 +1,7 @@ add_library_unity( test_sql_capi OBJECT + capi_scalar_functions.cpp capi_table_functions.cpp test_capi.cpp test_starting_database.cpp @@ -14,7 +15,9 @@ add_library_unity( test_capi_complex_types.cpp test_capi_to_decimal.cpp test_capi_replacement_scan.cpp - test_capi_streaming.cpp) + test_capi_streaming.cpp + test_capi_table_description.cpp + test_without_disabled_functions.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/test/api/capi/capi_scalar_functions.cpp b/test/api/capi/capi_scalar_functions.cpp new file mode 100644 index 00000000000..fc63a1763e8 --- /dev/null +++ b/test/api/capi/capi_scalar_functions.cpp @@ -0,0 +1,184 @@ +#include "capi_tester.hpp" + +using namespace duckdb; +using namespace std; + +void AddNumbersTogether(duckdb_function_info info, duckdb_data_chunk input, duckdb_vector output) { + // get the total number of rows in this chunk + idx_t input_size = duckdb_data_chunk_get_size(input); + // extract the two input vectors + duckdb_vector a = duckdb_data_chunk_get_vector(input, 0); + duckdb_vector b = duckdb_data_chunk_get_vector(input, 1); + // get the data pointers for the input vectors (both int64 as specified by the parameter types) + auto a_data = (int64_t *)duckdb_vector_get_data(a); + auto b_data = (int64_t *)duckdb_vector_get_data(b); + auto result_data = (int64_t *)duckdb_vector_get_data(output); + // get the validity vectors + auto a_validity = duckdb_vector_get_validity(a); + auto b_validity = duckdb_vector_get_validity(b); + if (a_validity || b_validity) { + // if either a_validity or b_validity is defined there might be NULL values + duckdb_vector_ensure_validity_writable(output); + auto result_validity = duckdb_vector_get_validity(output); + for (idx_t row = 0; row < input_size; row++) { + if (duckdb_validity_row_is_valid(a_validity, row) && duckdb_validity_row_is_valid(b_validity, row)) { + // not null - do the addition + result_data[row] = a_data[row] + b_data[row]; + } else { + // either a or b is NULL - set the result row to NULL + duckdb_validity_set_row_invalid(result_validity, row); + } + } + } else { + // no NULL values - iterate and do the operation directly + for (idx_t row = 0; row < input_size; row++) { + result_data[row] = a_data[row] + b_data[row]; + } + } +} + +static void CAPIRegisterAddition(duckdb_connection connection, const char *name, duckdb_state expected_outcome) { + duckdb_state status; + + // create a scalar function + auto function = duckdb_create_scalar_function(); + duckdb_scalar_function_set_name(nullptr, name); + duckdb_scalar_function_set_name(function, nullptr); + duckdb_scalar_function_set_name(function, name); + duckdb_scalar_function_set_name(function, name); + + // add a two bigint parameters + duckdb_logical_type type = duckdb_create_logical_type(DUCKDB_TYPE_BIGINT); + duckdb_scalar_function_add_parameter(nullptr, type); + duckdb_scalar_function_add_parameter(function, nullptr); + duckdb_scalar_function_add_parameter(function, type); + duckdb_scalar_function_add_parameter(function, type); + + // set the return type to bigint + duckdb_scalar_function_set_return_type(nullptr, type); + duckdb_scalar_function_set_return_type(function, nullptr); + duckdb_scalar_function_set_return_type(function, type); + duckdb_destroy_logical_type(&type); + + // set up the function + duckdb_scalar_function_set_function(nullptr, AddNumbersTogether); + duckdb_scalar_function_set_function(function, nullptr); + duckdb_scalar_function_set_function(function, AddNumbersTogether); + + // register and cleanup + status = duckdb_register_scalar_function(connection, function); + REQUIRE(status == expected_outcome); + + duckdb_destroy_scalar_function(&function); + duckdb_destroy_scalar_function(&function); + duckdb_destroy_scalar_function(nullptr); +} + +TEST_CASE("Test Scalar Functions C API", "[capi]") { + CAPITester tester; + duckdb::unique_ptr result; + + REQUIRE(tester.OpenDatabase(nullptr)); + CAPIRegisterAddition(tester.connection, "my_addition", DuckDBSuccess); + // try to register it again - this should be an error + CAPIRegisterAddition(tester.connection, "my_addition", DuckDBError); + + // now call it + result = tester.Query("SELECT my_addition(40, 2)"); + REQUIRE_NO_FAIL(*result); + REQUIRE(result->Fetch(0, 0) == 42); + + result = tester.Query("SELECT my_addition(40, NULL)"); + REQUIRE_NO_FAIL(*result); + REQUIRE(result->IsNull(0, 0)); + + result = tester.Query("SELECT my_addition(NULL, 2)"); + REQUIRE_NO_FAIL(*result); + REQUIRE(result->IsNull(0, 0)); + + // call it over a vector of values + result = tester.Query("SELECT my_addition(1000000, i) FROM range(10000) t(i)"); + REQUIRE_NO_FAIL(*result); + for (idx_t row = 0; row < 10000; row++) { + REQUIRE(result->Fetch(0, row) == static_cast(1000000 + row)); + } +} + +void ReturnStringInfo(duckdb_function_info info, duckdb_data_chunk input, duckdb_vector output) { + auto extra_info = string((const char *)info); + // get the total number of rows in this chunk + idx_t input_size = duckdb_data_chunk_get_size(input); + // extract the two input vectors + duckdb_vector input_vector = duckdb_data_chunk_get_vector(input, 0); + // get the data pointers for the input vectors (both int64 as specified by the parameter types) + auto input_data = (duckdb_string_t *)duckdb_vector_get_data(input_vector); + // get the validity vectors + auto input_validity = duckdb_vector_get_validity(input_vector); + duckdb_vector_ensure_validity_writable(output); + auto result_validity = duckdb_vector_get_validity(output); + for (idx_t row = 0; row < input_size; row++) { + if (duckdb_validity_row_is_valid(input_validity, row)) { + // not null - do the operation + auto input_string = input_data[row]; + string result = extra_info + "_"; + if (duckdb_string_is_inlined(input_string)) { + result += string(input_string.value.inlined.inlined, input_string.value.inlined.length); + } else { + result += input_string.value.pointer.ptr; + } + duckdb_vector_assign_string_element_len(output, row, result.c_str(), result.size()); + } else { + // either a or b is NULL - set the result row to NULL + duckdb_validity_set_row_invalid(result_validity, row); + } + } +} + +static void CAPIRegisterStringInfo(duckdb_connection connection, const char *name, duckdb_function_info info, + duckdb_delete_callback_t destroy_func) { + duckdb_state status; + + // create a scalar function + auto function = duckdb_create_scalar_function(); + duckdb_scalar_function_set_name(function, name); + + // add a single varchar parameter + duckdb_logical_type type = duckdb_create_logical_type(DUCKDB_TYPE_VARCHAR); + duckdb_scalar_function_add_parameter(function, type); + + // set the return type to varchar + duckdb_scalar_function_set_return_type(function, type); + duckdb_destroy_logical_type(&type); + + // set up the function + duckdb_scalar_function_set_function(function, ReturnStringInfo); + + // set the extra info + duckdb_scalar_function_set_extra_info(function, info, destroy_func); + + // register and cleanup + status = duckdb_register_scalar_function(connection, function); + REQUIRE(status == DuckDBSuccess); + + duckdb_destroy_scalar_function(&function); +} + +TEST_CASE("Test Scalar Functions - strings & extra_info", "[capi]") { + CAPITester tester; + duckdb::unique_ptr result; + + auto string_data = (char *)malloc(100); + strcpy(string_data, "my_prefix"); + + REQUIRE(tester.OpenDatabase(nullptr)); + CAPIRegisterStringInfo(tester.connection, "my_prefix", (duckdb_function_info)string_data, free); + + // now call it + result = tester.Query("SELECT my_prefix('hello_world')"); + REQUIRE_NO_FAIL(*result); + REQUIRE(result->Fetch(0, 0) == "my_prefix_hello_world"); + + result = tester.Query("SELECT my_prefix(NULL)"); + REQUIRE_NO_FAIL(*result); + REQUIRE(result->IsNull(0, 0)); +} diff --git a/test/api/capi/capi_table_functions.cpp b/test/api/capi/capi_table_functions.cpp index e7e865ec041..f534a723d80 100644 --- a/test/api/capi/capi_table_functions.cpp +++ b/test/api/capi/capi_table_functions.cpp @@ -52,9 +52,8 @@ void my_function(duckdb_function_info info, duckdb_data_chunk output) { static void capi_register_table_function(duckdb_connection connection, const char *name, duckdb_table_function_bind_t bind, duckdb_table_function_init_t init, - duckdb_table_function_t f) { + duckdb_table_function_t f, duckdb_state expected_state = DuckDBSuccess) { duckdb_state status; - // create a table function auto function = duckdb_create_table_function(); duckdb_table_function_set_name(nullptr, name); @@ -79,11 +78,10 @@ static void capi_register_table_function(duckdb_connection connection, const cha // register and cleanup status = duckdb_register_table_function(connection, function); - REQUIRE(status == DuckDBSuccess); - duckdb_destroy_table_function(&function); duckdb_destroy_table_function(&function); duckdb_destroy_table_function(nullptr); + REQUIRE(status == expected_state); } TEST_CASE("Test Table Functions C API", "[capi]") { @@ -92,6 +90,8 @@ TEST_CASE("Test Table Functions C API", "[capi]") { REQUIRE(tester.OpenDatabase(nullptr)); capi_register_table_function(tester.connection, "my_function", my_bind, my_init, my_function); + // registering again causes an error + capi_register_table_function(tester.connection, "my_function", my_bind, my_init, my_function, DuckDBError); // now call it result = tester.Query("SELECT * FROM my_function(1)"); @@ -153,6 +153,15 @@ TEST_CASE("Test Table Function errors in C API", "[capi]") { REQUIRE(result->HasError()); } +TEST_CASE("Test Table Function register errors in C API", "[capi]") { + CAPITester tester; + REQUIRE(tester.OpenDatabase(nullptr)); + + capi_register_table_function(tester.connection, "x", my_error_bind, my_init, my_function, DuckDBSuccess); + // Try to register it again with the same name, name collision + capi_register_table_function(tester.connection, "x", my_error_bind, my_init, my_function, DuckDBError); +} + struct my_named_bind_data_struct { int64_t size; int64_t multiplier; diff --git a/test/api/capi/test_capi.cpp b/test/api/capi/test_capi.cpp index 2d6202a53e5..a0c212ac987 100644 --- a/test/api/capi/test_capi.cpp +++ b/test/api/capi/test_capi.cpp @@ -703,3 +703,35 @@ TEST_CASE("Test custom_user_agent config", "[capi]") { duckdb_close(&db); } } + +TEST_CASE("Test unsupported types in the deprecated C API", "[capi]") { + CAPITester tester; + REQUIRE(tester.OpenDatabase(nullptr)); + + string query_1 = R"EOF( + CREATE TABLE test( + id BIGINT, + one DECIMAL(18,3)[] + ); + )EOF"; + string query_2 = "INSERT INTO test VALUES (410, '[]');"; + string query_3 = "INSERT INTO test VALUES (412, '[]');"; + string query_4 = "SELECT id, one FROM test;"; + REQUIRE_NO_FAIL(tester.Query(query_1)); + REQUIRE_NO_FAIL(tester.Query(query_2)); + REQUIRE_NO_FAIL(tester.Query(query_3)); + + // Passes, but does return invalid data for unsupported types. + auto result = tester.Query(query_4); + auto &result_c = result->InternalResult(); + + auto first_bigint_row = duckdb_value_string(&result_c, 0, 0).data; + REQUIRE(!string(first_bigint_row).compare("410")); + duckdb_free(first_bigint_row); + REQUIRE(duckdb_value_string(&result_c, 1, 0).data == nullptr); + + auto second_bigint_row = duckdb_value_string(&result_c, 0, 1).data; + REQUIRE(!string(second_bigint_row).compare("412")); + duckdb_free(second_bigint_row); + REQUIRE(duckdb_value_string(&result_c, 1, 1).data == nullptr); +} diff --git a/test/api/capi/test_capi_appender.cpp b/test/api/capi/test_capi_appender.cpp index f364627f10a..f48b68baad8 100644 --- a/test/api/capi/test_capi_appender.cpp +++ b/test/api/capi/test_capi_appender.cpp @@ -4,6 +4,38 @@ using namespace duckdb; using namespace std; +namespace { + +struct CAPIAppender { +public: + CAPIAppender(CAPITester &tester, const char *schema, const char *table) { + auto status = duckdb_appender_create(tester.connection, schema, table, &appender); + REQUIRE(status == DuckDBSuccess); + } + ~CAPIAppender() { + auto status = duckdb_appender_close(appender); + REQUIRE(status == DuckDBSuccess); + duckdb_appender_destroy(&appender); + } + operator duckdb_appender() const { + return appender; + } + operator duckdb_appender *() { + return &appender; + } + +public: + duckdb_appender appender = nullptr; +}; + +} // namespace + +void TestAppenderError(duckdb_appender &appender, const string &expected) { + auto error = duckdb_appender_error(appender); + REQUIRE(error != nullptr); + REQUIRE(duckdb::StringUtil::Contains(error, expected)); +} + void AssertDecimalValueMatches(duckdb::unique_ptr &result, duckdb_decimal expected) { duckdb_decimal actual; @@ -167,64 +199,56 @@ TEST_CASE("Test appender statements in C API", "[capi]") { duckdb::unique_ptr result; duckdb_state status; - // open the database in in-memory mode REQUIRE(tester.OpenDatabase(nullptr)); - tester.Query("CREATE TABLE test (i INTEGER, d double, s string)"); duckdb_appender appender; - status = duckdb_appender_create(tester.connection, nullptr, "nonexistant-table", &appender); - REQUIRE(status == DuckDBError); + // Creating the table with an unknown table fails, but creates an appender object. + REQUIRE(duckdb_appender_create(tester.connection, nullptr, "unknown_table", &appender) == DuckDBError); REQUIRE(appender != nullptr); - REQUIRE(duckdb_appender_error(appender) != nullptr); - REQUIRE(duckdb_appender_destroy(&appender) == DuckDBSuccess); - REQUIRE(duckdb_appender_destroy(nullptr) == DuckDBError); - - status = duckdb_appender_create(tester.connection, nullptr, "test", nullptr); - REQUIRE(status == DuckDBError); - - status = duckdb_appender_create(tester.connection, nullptr, "test", &appender); - REQUIRE(status == DuckDBSuccess); - REQUIRE(duckdb_appender_error(appender) == nullptr); + TestAppenderError(appender, "could not be found"); - status = duckdb_appender_begin_row(appender); - REQUIRE(status == DuckDBSuccess); - - status = duckdb_append_int32(appender, 42); - REQUIRE(status == DuckDBSuccess); - - status = duckdb_append_double(appender, 4.2); - REQUIRE(status == DuckDBSuccess); + // Flushing, closing, or destroying the appender also fails due to its invalid table. + REQUIRE(duckdb_appender_close(appender) == DuckDBError); + TestAppenderError(appender, "could not be found"); - status = duckdb_append_varchar(appender, "Hello, World"); - REQUIRE(status == DuckDBSuccess); + // Any data is still destroyed, so there are no leaks, even if duckdb_appender_destroy returns DuckDBError. + REQUIRE(duckdb_appender_destroy(&appender) == DuckDBError); + REQUIRE(duckdb_appender_destroy(nullptr) == DuckDBError); - // out of cols here - status = duckdb_append_int32(appender, 42); - REQUIRE(status == DuckDBError); + // Appender creation also fails if not providing an appender object. + REQUIRE(duckdb_appender_create(tester.connection, nullptr, "test", nullptr) == DuckDBError); - status = duckdb_appender_end_row(appender); - REQUIRE(status == DuckDBSuccess); + // Now, create a valid appender. + REQUIRE(duckdb_appender_create(tester.connection, nullptr, "test", &appender) == DuckDBSuccess); + REQUIRE(duckdb_appender_error(appender) == nullptr); - status = duckdb_appender_flush(appender); - REQUIRE(status == DuckDBSuccess); + // Start appending rows. + REQUIRE(duckdb_appender_begin_row(appender) == DuckDBSuccess); + REQUIRE(duckdb_append_int32(appender, 42) == DuckDBSuccess); + REQUIRE(duckdb_append_double(appender, 4.2) == DuckDBSuccess); + REQUIRE(duckdb_append_varchar(appender, "Hello, World") == DuckDBSuccess); - status = duckdb_appender_begin_row(appender); - REQUIRE(status == DuckDBSuccess); + // Exceed the column count. + REQUIRE(duckdb_append_int32(appender, 42) == DuckDBError); + TestAppenderError(appender, "Too many appends for chunk"); - status = duckdb_append_int32(appender, 42); - REQUIRE(status == DuckDBSuccess); + // Finish and flush the row. + REQUIRE(duckdb_appender_end_row(appender) == DuckDBSuccess); + REQUIRE(duckdb_appender_flush(appender) == DuckDBSuccess); - status = duckdb_append_double(appender, 4.2); - REQUIRE(status == DuckDBSuccess); + // Next row. + REQUIRE(duckdb_appender_begin_row(appender) == DuckDBSuccess); + REQUIRE(duckdb_append_int32(appender, 42) == DuckDBSuccess); + REQUIRE(duckdb_append_double(appender, 4.2) == DuckDBSuccess); - // not enough cols here - status = duckdb_appender_end_row(appender); - REQUIRE(status == DuckDBError); + // Missing column. + REQUIRE(duckdb_appender_end_row(appender) == DuckDBError); REQUIRE(duckdb_appender_error(appender) != nullptr); + TestAppenderError(appender, "Call to EndRow before all rows have been appended to"); - status = duckdb_append_varchar(appender, "Hello, World"); - REQUIRE(status == DuckDBSuccess); + // Append the missing column. + REQUIRE(duckdb_append_varchar(appender, "Hello, World") == DuckDBSuccess); // out of cols here status = duckdb_append_int32(appender, 42); @@ -569,6 +593,59 @@ TEST_CASE("Test appender statements in C API", "[capi]") { REQUIRE(uhugeint.upper == 0); } +TEST_CASE("Test append DEFAULT in C API", "[capi]") { + CAPITester tester; + duckdb::unique_ptr result; + + REQUIRE(tester.OpenDatabase(nullptr)); + + SECTION("BASIC DEFAULT VALUE") { + tester.Query("CREATE OR REPLACE TABLE test (a INTEGER, b INTEGER DEFAULT 5)"); + { + CAPIAppender appender(tester, nullptr, "test"); + auto status = duckdb_appender_begin_row(appender); + REQUIRE(status == DuckDBSuccess); + duckdb_append_int32(appender, 42); + // Even though the column has a DEFAULT, we still require explicitly appending a value/default + status = duckdb_appender_end_row(appender); + REQUIRE(status == DuckDBError); + status = duckdb_appender_flush(appender); + REQUIRE(status == DuckDBError); + + status = duckdb_append_default(appender); + REQUIRE(status == DuckDBSuccess); + status = duckdb_appender_end_row(appender); + REQUIRE(status == DuckDBSuccess); + } + result = tester.Query("SELECT * FROM test"); + REQUIRE_NO_FAIL(*result); + REQUIRE(result->Fetch(0, 0) == 42); + REQUIRE(result->Fetch(1, 0) == 5); + } + + SECTION("NON DEFAULT VALUE") { + tester.Query("CREATE OR REPLACE TABLE test (a INTEGER, b INTEGER DEFAULT 5)"); + { + CAPIAppender appender(tester, nullptr, "test"); + auto status = duckdb_appender_begin_row(appender); + REQUIRE(status == DuckDBSuccess); + + // Append default to column without a default + status = duckdb_append_default(appender); + REQUIRE(status == DuckDBSuccess); + + status = duckdb_append_int32(appender, 42); + REQUIRE(status == DuckDBSuccess); + status = duckdb_appender_end_row(appender); + REQUIRE(status == DuckDBSuccess); + } + result = tester.Query("SELECT * FROM test"); + REQUIRE_NO_FAIL(*result); + REQUIRE(result->IsNull(0, 0)); + REQUIRE(result->Fetch(1, 0) == 42); + } +} + TEST_CASE("Test append timestamp in C API", "[capi]") { CAPITester tester; duckdb::unique_ptr result; diff --git a/test/api/capi/test_capi_complex_types.cpp b/test/api/capi/test_capi_complex_types.cpp index ff84948beb9..aef19e5b301 100644 --- a/test/api/capi/test_capi_complex_types.cpp +++ b/test/api/capi/test_capi_complex_types.cpp @@ -1,6 +1,7 @@ #include "capi_tester.hpp" #include "duckdb/main/database_manager.hpp" #include "duckdb/parser/parsed_data/create_type_info.hpp" +#include "duckdb/transaction/meta_transaction.hpp" using namespace duckdb; using namespace std; @@ -274,7 +275,9 @@ TEST_CASE("Logical types with aliases", "[capi]") { CreateTypeInfo info(type_name, id); auto &catalog_name = DatabaseManager::GetDefaultDatabase(*connection->context); + auto &transaction = MetaTransaction::Get(*connection->context); auto &catalog = Catalog::GetCatalog(*connection->context, catalog_name); + transaction.ModifyDatabase(catalog.GetAttached()); catalog.CreateType(*connection->context, info); connection->Commit(); @@ -291,6 +294,7 @@ TEST_CASE("Logical types with aliases", "[capi]") { REQUIRE(logical_type); auto alias = duckdb_logical_type_get_alias(logical_type); + REQUIRE(alias); REQUIRE(string(alias) == "test_type"); duckdb_free(alias); diff --git a/test/api/capi/test_capi_data_chunk.cpp b/test/api/capi/test_capi_data_chunk.cpp index 9d5e82aa38b..be43c6efe84 100644 --- a/test/api/capi/test_capi_data_chunk.cpp +++ b/test/api/capi/test_capi_data_chunk.cpp @@ -458,3 +458,74 @@ TEST_CASE("Test DataChunk populate ArrayVector in C API", "[capi]") { duckdb_destroy_logical_type(&array_type); duckdb_destroy_logical_type(&elem_type); } + +TEST_CASE("Test PK violation in the C API appender", "[capi]") { + CAPITester tester; + duckdb::unique_ptr result; + + REQUIRE(tester.OpenDatabase(nullptr)); + REQUIRE(duckdb_vector_size() == STANDARD_VECTOR_SIZE); + + // Create column types. + const idx_t COLUMN_COUNT = 1; + duckdb_logical_type types[COLUMN_COUNT]; + types[0] = duckdb_create_logical_type(DUCKDB_TYPE_BIGINT); + + // Create data chunk. + auto data_chunk = duckdb_create_data_chunk(types, COLUMN_COUNT); + auto bigint_vector = duckdb_data_chunk_get_vector(data_chunk, 0); + auto int64_ptr = reinterpret_cast(duckdb_vector_get_data(bigint_vector)); + int64_ptr[0] = 42; + int64_ptr[1] = 42; + duckdb_data_chunk_set_size(data_chunk, 2); + + // Use the appender to append the data chunk. + tester.Query("CREATE TABLE test(i BIGINT PRIMARY KEY)"); + duckdb_appender appender; + REQUIRE(duckdb_appender_create(tester.connection, nullptr, "test", &appender) == DuckDBSuccess); + + // We only flush when destroying the appender. Thus, we expect this to succeed, as we only + // detect constraint violations when flushing the results. + REQUIRE(duckdb_append_data_chunk(appender, data_chunk) == DuckDBSuccess); + + // duckdb_appender_close attempts to flush the data and fails. + auto state = duckdb_appender_close(appender); + REQUIRE(state == DuckDBError); + auto error = duckdb_appender_error(appender); + REQUIRE(duckdb::StringUtil::Contains(error, "PRIMARY KEY or UNIQUE constraint violated")); + + // Destroy the appender despite the error to avoid leaks. + state = duckdb_appender_destroy(&appender); + REQUIRE(state == DuckDBError); + + // Clean-up. + duckdb_destroy_data_chunk(&data_chunk); + for (idx_t i = 0; i < COLUMN_COUNT; i++) { + duckdb_destroy_logical_type(&types[i]); + } + + // Ensure that no rows were appended. + result = tester.Query("SELECT * FROM test;"); + REQUIRE_NO_FAIL(*result); + REQUIRE(result->row_count() == 0); + + // Try again by appending rows and flushing. + REQUIRE(duckdb_appender_create(tester.connection, nullptr, "test", &appender) == DuckDBSuccess); + REQUIRE(duckdb_appender_begin_row(appender) == DuckDBSuccess); + REQUIRE(duckdb_append_int64(appender, 42) == DuckDBSuccess); + REQUIRE(duckdb_appender_end_row(appender) == DuckDBSuccess); + REQUIRE(duckdb_appender_begin_row(appender) == DuckDBSuccess); + REQUIRE(duckdb_append_int64(appender, 42) == DuckDBSuccess); + REQUIRE(duckdb_appender_end_row(appender) == DuckDBSuccess); + + state = duckdb_appender_flush(appender); + REQUIRE(state == DuckDBError); + error = duckdb_appender_error(appender); + REQUIRE(duckdb::StringUtil::Contains(error, "PRIMARY KEY or UNIQUE constraint violated")); + REQUIRE(duckdb_appender_destroy(&appender) == DuckDBError); + + // Ensure that only the last row was appended. + result = tester.Query("SELECT * FROM test;"); + REQUIRE_NO_FAIL(*result); + REQUIRE(result->row_count() == 0); +} diff --git a/test/api/capi/test_capi_prepared.cpp b/test/api/capi/test_capi_prepared.cpp index 76d54ddcca1..7ee8a6c1509 100644 --- a/test/api/capi/test_capi_prepared.cpp +++ b/test/api/capi/test_capi_prepared.cpp @@ -206,6 +206,14 @@ TEST_CASE("Test prepared statements in C API", "[capi]") { duckdb_free(value); duckdb_destroy_result(&res); + duckdb_bind_timestamp_tz(stmt, 1, duckdb_to_timestamp(ts)); + status = duckdb_execute_prepared(stmt, &res); + REQUIRE(status == DuckDBSuccess); + value = duckdb_value_varchar(&res, 0, 0); + REQUIRE(StringUtil::Contains(string(value), "1992-09")); + duckdb_free(value); + duckdb_destroy_result(&res); + duckdb_interval interval; interval.months = 3; interval.days = 0; diff --git a/test/api/capi/test_capi_table_description.cpp b/test/api/capi/test_capi_table_description.cpp new file mode 100644 index 00000000000..67d24b00ce1 --- /dev/null +++ b/test/api/capi/test_capi_table_description.cpp @@ -0,0 +1,47 @@ +#include "capi_tester.hpp" +#include "duckdb.h" + +using namespace duckdb; +using namespace std; + +TEST_CASE("Test table description in C API", "[capi]") { + CAPITester tester; + duckdb_state status; + duckdb_table_description table_description = nullptr; + + // open the database in in-memory mode + REQUIRE(tester.OpenDatabase(nullptr)); + + // Table doesn't exist yet + status = duckdb_table_description_create(tester.connection, nullptr, "test", &table_description); + REQUIRE(status == DuckDBError); + duckdb_table_description_destroy(&table_description); + + tester.Query("CREATE TABLE test (i integer, j integer default 5)"); + + // The table was not created in this schema + status = duckdb_table_description_create(tester.connection, "non-existant", "test", &table_description); + REQUIRE(status == DuckDBError); + duckdb_table_description_destroy(&table_description); + + status = duckdb_table_description_create(tester.connection, nullptr, "test", &table_description); + REQUIRE(status == DuckDBSuccess); + REQUIRE(duckdb_table_description_error(table_description) == nullptr); + + bool has_default; + SECTION("Out of range column") { + status = duckdb_column_has_default(table_description, 2, &has_default); + REQUIRE(status == DuckDBError); + } + SECTION("In range column - not default") { + status = duckdb_column_has_default(table_description, 0, &has_default); + REQUIRE(status == DuckDBSuccess); + REQUIRE(has_default == false); + } + SECTION("In range column - default") { + status = duckdb_column_has_default(table_description, 1, &has_default); + REQUIRE(status == DuckDBSuccess); + REQUIRE(has_default == true); + } + duckdb_table_description_destroy(&table_description); +} diff --git a/test/api/capi/test_without_disabled_functions.cpp b/test/api/capi/test_without_disabled_functions.cpp new file mode 100644 index 00000000000..32dce046765 --- /dev/null +++ b/test/api/capi/test_without_disabled_functions.cpp @@ -0,0 +1,41 @@ +#include "catch.hpp" +#define DUCKDB_API_NO_DEPRECATED +#define DUCKDB_NO_EXTENSION_FUNCTIONS + +#include "duckdb.h" + +using namespace std; + +// we only use functions that are cool to use in the 1.0 API +TEST_CASE("Test without deprecated or future moved functions", "[capi]") { + duckdb_database database; + duckdb_connection connection; + duckdb_prepared_statement statement; + duckdb_result result; + + REQUIRE(duckdb_open(NULL, &database) == DuckDBSuccess); + REQUIRE(duckdb_connect(database, &connection) == DuckDBSuccess); + REQUIRE(duckdb_prepare(connection, "SELECT ?::INTEGER AS a", &statement) == DuckDBSuccess); + REQUIRE(duckdb_bind_int32(statement, 1, 42) == DuckDBSuccess); + REQUIRE(duckdb_execute_prepared(statement, &result) == DuckDBSuccess); + + REQUIRE(duckdb_column_count(&result) == 1); + REQUIRE(string(duckdb_column_name(&result, 0)) == "a"); + REQUIRE(duckdb_column_type(&result, 0) == DUCKDB_TYPE_INTEGER); + + auto chunk = duckdb_fetch_chunk(result); + REQUIRE(chunk); + auto vector = duckdb_data_chunk_get_vector(chunk, 0); + REQUIRE(vector); + auto validity = duckdb_vector_get_validity(vector); + REQUIRE(duckdb_validity_row_is_valid(validity, 0)); + auto data = (int *)duckdb_vector_get_data(vector); + REQUIRE(data); + REQUIRE(data[0] == 42); + + duckdb_destroy_data_chunk(&chunk); + duckdb_destroy_result(&result); + duckdb_destroy_prepare(&statement); + duckdb_disconnect(&connection); + duckdb_close(&database); +} diff --git a/test/api/serialized_plans/queries.sql b/test/api/serialized_plans/queries.sql index a8f73eb1223..14ceee7b690 100644 --- a/test/api/serialized_plans/queries.sql +++ b/test/api/serialized_plans/queries.sql @@ -19,3 +19,6 @@ SELECT c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, sum(l_quantity) SELECT sum(l_extendedprice * (1 - l_discount)) AS revenue FROM lineitem, part WHERE (p_partkey = l_partkey AND p_brand = 'Brand#12' AND p_container IN ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG') AND l_quantity >= 1 AND l_quantity <= 1 + 10 AND p_size BETWEEN 1 AND 5 AND l_shipmode IN ('AIR', 'AIR REG') AND l_shipinstruct = 'DELIVER IN PERSON') OR (p_partkey = l_partkey AND p_brand = 'Brand#23' AND p_container IN ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK') AND l_quantity >= 10 AND l_quantity <= 10 + 10 AND p_size BETWEEN 1 AND 10 AND l_shipmode IN ('AIR', 'AIR REG') AND l_shipinstruct = 'DELIVER IN PERSON') OR (p_partkey = l_partkey AND p_brand = 'Brand#34' AND p_container IN ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG') AND l_quantity >= 20 AND l_quantity <= 20 + 10 AND p_size BETWEEN 1 AND 15 AND l_shipmode IN ('AIR', 'AIR REG') AND l_shipinstruct = 'DELIVER IN PERSON'); SELECT s_name, s_address FROM supplier, nation WHERE s_suppkey IN ( SELECT ps_suppkey FROM partsupp WHERE ps_partkey IN ( SELECT p_partkey FROM part WHERE p_name LIKE 'forest%') AND ps_availqty > ( SELECT 0.5 * sum(l_quantity) FROM lineitem WHERE l_partkey = ps_partkey AND l_suppkey = ps_suppkey AND l_shipdate >= CAST('1994-01-01' AS date) AND l_shipdate < CAST('1995-01-01' AS date))) AND s_nationkey = n_nationkey AND n_name = 'CANADA' ORDER BY s_name; SELECT s_name, count(*) AS numwait FROM supplier, lineitem l1, orders, nation WHERE s_suppkey = l1.l_suppkey AND o_orderkey = l1.l_orderkey AND o_orderstatus = 'F' AND l1.l_receiptdate > l1.l_commitdate AND EXISTS ( SELECT * FROM lineitem l2 WHERE l2.l_orderkey = l1.l_orderkey AND l2.l_suppkey <> l1.l_suppkey) AND NOT EXISTS ( SELECT * FROM lineitem l3 WHERE l3.l_orderkey = l1.l_orderkey AND l3.l_suppkey <> l1.l_suppkey AND l3.l_receiptdate > l3.l_commitdate) AND s_nationkey = n_nationkey AND n_name = 'SAUDI ARABIA' GROUP BY s_name ORDER BY numwait DESC, s_name LIMIT 100; +SELECT * FROM range(10); +SELECT * FROM range(0, 100); +SELECT * FROM generate_series(0, 10) t(i); diff --git a/test/api/serialized_plans/serialized_plans.binary b/test/api/serialized_plans/serialized_plans.binary index ec497ee84bd110cd6cebac41abe8e1723f49d1f7..d85bcb9aca3bb3929630c1a809b784bd27d1093e 100644 GIT binary patch delta 654 zcmbQbmgUR_mJRJJj0}@M*u0$lJ4JkQJrDcle%44vu+X8&|BARKZ)HCU=7mqLap9P3 zP{KXAV7u~W4$gTpVBy!BC#l7XF*0oaU~^CeqHS|Ykb?k}S)P1^56b*kw3!>KWp4dP zcA%F2_B2+YNPm0w=EPnmNvJxt<@+G^zutUdWfxE#&~>jTUs%b$*>}?ph+|(*))p6; z9JPsWv+xcL3%ClQ&6XcyR4325%~>ybf`Q>A17ivU-~a!o7#LZL67$kiPctwwoMB)% z%kcmI7pTxzMu?hkj11oy8P0)pfc2y@Fr+bX{r`WSf#CuJ!$k&$OAJ6=Cm0xkh62^d zq%u5VOk;o;djg{6Bv1heq%bh1)`L|M?+7NarCpBN?HBTPOc3;+njb{V0_0HMz!x zW3oXB_vC`@%9}Yj=gB}N?rol=7ApqgZ2oJrMFggOb4iec0Gv~ve1s3q`B$`=8_K!2 zd2anj_Q`rde4FRAN3wz#ljpR@ZBFcEl7y>QTfPtGs(YI+tn6ZkX`XyxCHrRIO*>#7 cxi?u`Tx4?8Cce$WJ2WhiR0(ai{1~GO0FEtpwg3PC diff --git a/test/api/test_api.cpp b/test/api/test_api.cpp index 23d4bb3d02e..3452604e406 100644 --- a/test/api/test_api.cpp +++ b/test/api/test_api.cpp @@ -553,13 +553,13 @@ TEST_CASE("Test large number of connections to a single database", "[api]") { connections.push_back(std::move(conn)); } - REQUIRE(connection_manager.connections.size() == createdConnections); + REQUIRE(connection_manager.GetConnectionCount() == createdConnections); for (size_t i = 0; i < toRemove; i++) { connections.erase(connections.begin()); } - REQUIRE(connection_manager.connections.size() == remainingConnections); + REQUIRE(connection_manager.GetConnectionCount() == remainingConnections); } TEST_CASE("Issue #4583: Catch Insert/Update/Delete errors", "[api]") { @@ -664,3 +664,13 @@ TEST_CASE("Test insert returning in CPP API", "[api]") { REQUIRE(CHECK_COLUMN(result, 0, {"query_1", "query_2", "query_arg_1", "query_arg_2", "prepared_arg_1", "prepared_arg_2"})); } + +TEST_CASE("Test a logical execute still has types after an optimization pass", "[api]") { + DuckDB db(nullptr); + Connection con(db); + con.Query("PREPARE test AS SELECT 42::INTEGER;"); + const auto query_plan = con.ExtractPlan("EXECUTE test"); + REQUIRE((query_plan->type == LogicalOperatorType::LOGICAL_EXECUTE)); + REQUIRE((query_plan->types.size() == 1)); + REQUIRE((query_plan->types[0].id() == LogicalTypeId::INTEGER)); +} diff --git a/test/api/test_get_table_names.cpp b/test/api/test_get_table_names.cpp index 9abe4b89075..59a73dd6475 100644 --- a/test/api/test_get_table_names.cpp +++ b/test/api/test_get_table_names.cpp @@ -90,6 +90,11 @@ TEST_CASE("Test GetTableNames", "[api]") { REQUIRE(table_names.size() == 1); REQUIRE(table_names.count("df")); + // generate_series + table_names = con.GetTableNames("with series_generator as (select * from generate_series(TIMESTAMP '2001-04-10', " + "TIMESTAMP '2001-04-11', INTERVAL 1 HOUR)) select * from series_generator"); + REQUIRE(table_names.empty()); + if (!db.ExtensionIsLoaded("tpch")) { return; } diff --git a/test/api/test_relation_api.cpp b/test/api/test_relation_api.cpp index 740adedef62..95a35aeb1e5 100644 --- a/test/api/test_relation_api.cpp +++ b/test/api/test_relation_api.cpp @@ -873,6 +873,17 @@ TEST_CASE("Test CSV reading/writing from relations", "[relation_api]") { REQUIRE_THROWS(con.ReadCSV(csv_file, {"i INTEGER, j INTEGER"})); } +TEST_CASE("Test CSV reading from weather.csv", "[relation_api]") { + DuckDB db(nullptr); + Connection con(db); + con.EnableQueryVerification(); + duckdb::unique_ptr result; + + auto auto_csv_scan = con.ReadCSV("data/csv/weather.csv")->Limit(1); + result = auto_csv_scan->Execute(); + REQUIRE(CHECK_COLUMN(result, 0, {"2016-01-01"})); +} + TEST_CASE("Test query relation", "[relation_api]") { DuckDB db(nullptr); Connection con(db); diff --git a/test/api/test_reset.cpp b/test/api/test_reset.cpp index bdb6621a62f..683fd2a8822 100644 --- a/test/api/test_reset.cpp +++ b/test/api/test_reset.cpp @@ -60,6 +60,8 @@ OptionValueSet &GetValueForOption(const string &name) { {"prefer_range_joins", {Value(true)}}, {"allow_persistent_secrets", {Value(false)}}, {"secret_directory", {"/tmp/some/path"}}, + {"enable_macro_dependencies", {Value(true)}}, + {"enable_view_dependencies", {Value(true)}}, {"default_secret_storage", {"custom_storage"}}, {"custom_extension_repository", {"duckdb.org/no-extensions-here", "duckdb.org/no-extensions-here"}}, {"autoinstall_extension_repository", {"duckdb.org/no-extensions-here", "duckdb.org/no-extensions-here"}}, @@ -90,6 +92,7 @@ OptionValueSet &GetValueForOption(const string &name) { {"max_memory", {"4.0 GiB"}}, {"max_temp_directory_size", {"10.0 GiB"}}, {"memory_limit", {"4.0 GiB"}}, + {"storage_compatibility_version", {"v0.10.0"}}, {"ordered_aggregate_threshold", {Value::UBIGINT(idx_t(1) << 12)}}, {"null_order", {"nulls_first"}}, {"perfect_ht_threshold", {0}}, @@ -107,8 +110,14 @@ OptionValueSet &GetValueForOption(const string &name) { {"worker_threads", {42}}, {"enable_http_metadata_cache", {true}}, {"force_bitpacking_mode", {"constant"}}, + {"arrow_large_buffer_size", {true}}, + {"arrow_output_list_view", {true}}, + {"produce_arrow_string_view", {true}}, + {"enable_http_logging", {true}}, + {"http_logging_output", {"my_cool_outputfile"}}, + {"produce_arrow_string_view", {true}}, {"allocator_flush_threshold", {"4.0 GiB"}}, - {"arrow_large_buffer_size", {true}}}; + {"allocator_background_threads", {true}}}; // Every option that's not excluded has to be part of this map if (!value_map.count(name)) { REQUIRE(name == "MISSING_FROM_MAP"); @@ -123,11 +132,13 @@ bool OptionIsExcludedFromTest(const string &name) { "search_path", "debug_window_mode", "experimental_parallel_csv", - "lock_configuration", // cant change this while db is running - "disabled_filesystems", // cant change this while db is running - "enable_external_access", // cant change this while db is running - "allow_unsigned_extensions", // cant change this while db is running - "allow_unredacted_secrets", // cant change this while db is running + "lock_configuration", // cant change this while db is running + "disabled_filesystems", // cant change this while db is running + "enable_external_access", // cant change this while db is running + "allow_unsigned_extensions", // cant change this while db is running + "allow_community_extensions", // cant change this while db is running + "allow_unredacted_secrets", // cant change this while db is running + "streaming_buffer_size", "log_query_path", "password", "username", @@ -135,7 +146,10 @@ bool OptionIsExcludedFromTest(const string &name) { "external_threads", // tested in test_threads.cpp "profiling_output", // just an alias "duckdb_api", - "custom_user_agent"}; + "custom_user_agent", + "custom_profiling_settings", + "custom_user_agent", + "default_block_size"}; return excluded_options.count(name) == 1; } diff --git a/test/api/test_results.cpp b/test/api/test_results.cpp index e4c3ec89e3a..6c760bd5d98 100644 --- a/test/api/test_results.cpp +++ b/test/api/test_results.cpp @@ -158,12 +158,7 @@ TEST_CASE("Error in streaming result after initial query", "[api][.]") { // now create a streaming result auto result = con.SendQuery("SELECT CAST(v AS INTEGER) FROM strings"); - REQUIRE_NO_FAIL(*result); - auto chunk = result->Fetch(); - REQUIRE(!chunk); - REQUIRE(result->HasError()); - auto str = result->ToString(); - REQUIRE(!str.empty()); + REQUIRE_FAIL(result); } TEST_CASE("Test UUID", "[api][uuid]") { diff --git a/test/appender/test_appender.cpp b/test/appender/test_appender.cpp index 527cbc27a5a..bb659982e2c 100644 --- a/test/appender/test_appender.cpp +++ b/test/appender/test_appender.cpp @@ -169,6 +169,113 @@ TEST_CASE("Test AppendRow", "[appender]") { REQUIRE(CHECK_COLUMN(result, 2, {Value::TIMESTAMP(1992, 1, 1, 1, 1, 1, 0)})); } +TEST_CASE("Test default value appender", "[appender]") { + duckdb::unique_ptr result; + DuckDB db(nullptr); + Connection con(db); + + SECTION("Insert DEFAULT into default column") { + REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i iNTEGER, j INTEGER DEFAULT 5)")); + { + Appender appender(con, "integers"); + appender.BeginRow(); + appender.Append(2); + appender.AppendDefault(); + REQUIRE_NOTHROW(appender.EndRow()); + REQUIRE_NOTHROW(appender.Close()); + } + result = con.Query("SELECT * FROM integers"); + REQUIRE(CHECK_COLUMN(result, 0, {Value::INTEGER(2)})); + REQUIRE(CHECK_COLUMN(result, 1, {Value::INTEGER(5)})); + } + + SECTION("Insert DEFAULT into non-default column") { + REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i iNTEGER, j INTEGER DEFAULT 5)")); + { + Appender appender(con, "integers"); + appender.BeginRow(); + // 'i' does not have a DEFAULT value, so it gets NULL + REQUIRE_NOTHROW(appender.AppendDefault()); + REQUIRE_NOTHROW(appender.AppendDefault()); + REQUIRE_NOTHROW(appender.EndRow()); + REQUIRE_NOTHROW(appender.Close()); + } + result = con.Query("SELECT * FROM integers"); + REQUIRE(CHECK_COLUMN(result, 0, {Value(LogicalTypeId::INTEGER)})); + REQUIRE(CHECK_COLUMN(result, 1, {Value::INTEGER(5)})); + } + + SECTION("Insert DEFAULT into column that can't be NULL") { + REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i integer NOT NULL)")); + { + Appender appender(con, "integers"); + appender.BeginRow(); + REQUIRE_NOTHROW(appender.AppendDefault()); + REQUIRE_NOTHROW(appender.EndRow()); + // NOT NULL constraint failed + REQUIRE_THROWS(appender.Close()); + } + result = con.Query("SELECT * FROM integers"); + auto chunk = result->Fetch(); + REQUIRE(chunk == nullptr); + } + + SECTION("DEFAULT nextval('seq')") { + REQUIRE_NO_FAIL(con.Query("CREATE SEQUENCE seq")); + REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i iNTEGER, j INTEGER DEFAULT nextval('seq'))")); + { + Appender appender(con, "integers"); + appender.BeginRow(); + appender.Append(1); + + // NOT_IMPLEMENTED: Non-foldable default values are not supported currently + REQUIRE_THROWS(appender.AppendDefault()); + REQUIRE_THROWS(appender.EndRow()); + REQUIRE_NOTHROW(appender.Close()); + } + // result = con.Query("SELECT * FROM integers"); + // REQUIRE(CHECK_COLUMN(result, 0, {Value::INTEGER(1)})); + // REQUIRE(CHECK_COLUMN(result, 1, {Value::INTEGER(1)})); + } + + SECTION("DEFAULT random()") { + REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i iNTEGER, j DOUBLE DEFAULT random())")); + con.Query("select setseed(0.42)"); + { + Appender appender(con, "integers"); + appender.BeginRow(); + appender.Append(1); + // NOT_IMPLEMENTED: Non-foldable default values are not supported currently + REQUIRE_THROWS(appender.AppendDefault()); + REQUIRE_THROWS(appender.EndRow()); + REQUIRE_NOTHROW(appender.Close()); + } + // result = con.Query("SELECT * FROM integers"); + // REQUIRE(CHECK_COLUMN(result, 0, {Value::INTEGER(1)})); + // REQUIRE(CHECK_COLUMN(result, 1, {Value::DOUBLE(0.4729174713138491)})); + } + + SECTION("DEFAULT now()") { + REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i iNTEGER, j TIMESTAMPTZ DEFAULT now())")); + con.Query("BEGIN TRANSACTION"); + result = con.Query("select now()"); + auto &materialized_result = result->Cast(); + auto current_time = materialized_result.GetValue(0, 0); + { + Appender appender(con, "integers"); + appender.BeginRow(); + appender.Append(1); + REQUIRE_NOTHROW(appender.AppendDefault()); + REQUIRE_NOTHROW(appender.EndRow()); + REQUIRE_NOTHROW(appender.Close()); + } + result = con.Query("SELECT * FROM integers"); + REQUIRE(CHECK_COLUMN(result, 0, {Value::INTEGER(1)})); + REQUIRE(CHECK_COLUMN(result, 1, {current_time})); + con.Query("COMMIT"); + } +} + TEST_CASE("Test incorrect usage of appender", "[appender]") { duckdb::unique_ptr result; DuckDB db(nullptr); diff --git a/test/arrow/arrow_roundtrip.cpp b/test/arrow/arrow_roundtrip.cpp index e953791a9da..091f167a7c6 100644 --- a/test/arrow/arrow_roundtrip.cpp +++ b/test/arrow/arrow_roundtrip.cpp @@ -15,6 +15,14 @@ static void TestArrowRoundtrip(const string &query, bool export_large_buffer = f REQUIRE(ArrowTestHelper::RunArrowComparison(con, query, false)); } +static void TestArrowRoundtripStringView(const string &query) { + DuckDB db; + Connection con(db); + auto res = con.Query("SET produce_arrow_string_view=True"); + REQUIRE(!res->HasError()); + REQUIRE(ArrowTestHelper::RunArrowComparison(con, query, false)); +} + static void TestParquetRoundtrip(const string &path) { DBConfig config; // This needs to be set since this test will be triggered when testing autoloading @@ -78,6 +86,25 @@ TEST_CASE("Test arrow roundtrip", "[arrow]") { "FROM test_all_types()"); } +TEST_CASE("Test Arrow String View", "[arrow][.]") { + // Test Small Strings + TestArrowRoundtripStringView("SELECT (i*10^i)::varchar str FROM range(5) tbl(i)"); + + // Test Small Strings + Nulls + TestArrowRoundtripStringView("SELECT (i*10^i)::varchar str FROM range(5) tbl(i) UNION SELECT NULL"); + + // Test Big Strings + TestArrowRoundtripStringView("SELECT 'Imaverybigstringmuchbiggerthanfourbytes' str FROM range(5) tbl(i)"); + + // Test Big Strings + Nulls + TestArrowRoundtripStringView("SELECT 'Imaverybigstringmuchbiggerthanfourbytes'||i::varchar str FROM range(5) " + "tbl(i) UNION SELECT NULL order by str"); + + // Test Mix of Small/Big/NULL Strings + TestArrowRoundtripStringView( + "SELECT 'Imaverybigstringmuchbiggerthanfourbytes'||i::varchar str FROM range(10000) tbl(i) UNION " + "SELECT NULL UNION SELECT (i*10^i)::varchar str FROM range(10000) tbl(i)"); +} TEST_CASE("Test Parquet Files round-trip", "[arrow][.]") { std::vector data; // data.emplace_back("data/parquet-testing/7-set.snappy.arrow2.parquet"); diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt index 7646cf6947b..faeac6b0bcc 100644 --- a/test/common/CMakeLists.txt +++ b/test/common/CMakeLists.txt @@ -9,6 +9,7 @@ add_library_unity( test_utf.cpp test_strftime.cpp test_string_util.cpp) + set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/test/extension/CMakeLists.txt b/test/extension/CMakeLists.txt index ca149cc58c3..325f6f59d99 100644 --- a/test/extension/CMakeLists.txt +++ b/test/extension/CMakeLists.txt @@ -1,4 +1,5 @@ set(PARAMETERS "-warnings") + build_loadable_extension_directory( loadable_extension_demo test/extension "default-version" ${PARAMETERS} loadable_extension_demo.cpp) diff --git a/test/extension/duckdb_extensions.test b/test/extension/duckdb_extensions.test new file mode 100644 index 00000000000..27e53c60ee5 --- /dev/null +++ b/test/extension/duckdb_extensions.test @@ -0,0 +1,47 @@ +# name: test/extension/duckdb_extensions.test +# description: Tests for the duckdb_extensions() table function +# group: [extension] + +# This test assumes icu and json to be available in the LOCAL_EXTENSION_REPO and NOT linked into duckdb statically +# -> this should be the case for our autoloading tests where we have the local_extension_repo variable set +require-env LOCAL_EXTENSION_REPO + +require no_extension_autoloading + +statement ok +PRAGMA enable_verification + +# Set the repository to the correct one +statement ok +set custom_extension_repository='${LOCAL_EXTENSION_REPO}' + +# Ensure we have a clean extension directory without any preinstalled extensions +statement ok +set extension_directory='__TEST_DIR__/duckdb_extensions' + +require json + +# json is statically linked +query II +SELECT extension_name, install_mode from duckdb_extensions() where extension_name='json' +---- +json STATICALLY_LINKED + +# now we install json (happens when users install extensions that are also statically loaded) +statement ok +install json + +# json still shown as statically linked +query II +SELECT extension_name, install_mode from duckdb_extensions() where extension_name='json' +---- +json STATICALLY_LINKED + +statement ok +load json + +# json still shown as statically linked +query II +SELECT extension_name, install_mode from duckdb_extensions() where extension_name='json' +---- +json STATICALLY_LINKED diff --git a/test/extension/install_extension.test b/test/extension/install_extension.test new file mode 100644 index 00000000000..1c20345e374 --- /dev/null +++ b/test/extension/install_extension.test @@ -0,0 +1,39 @@ +# name: test/extension/install_extension.test +# description: Test various ways of installing extensions +# group: [extension] + +statement ok +PRAGMA enable_verification + +statement ok +set extension_directory='__TEST_DIR__/install_extension' + +# Check defaults are correct +statement error +INSTALL will_never_exist; +---- +Failed to download extension "will_never_exist" at URL "http://extensions.duckdb.org + +# Explicitly install from core +statement error +INSTALL will_never_exist FROM core; +---- +Failed to download extension "will_never_exist" at URL "http://extensions.duckdb.org + +# Explicitly install from nightly +statement error +INSTALL will_never_exist FROM core_nightly; +---- +Failed to download extension "will_never_exist" at URL "http://nightly-extensions.duckdb.org + +# Explicitly install from community +statement error +INSTALL will_never_exist FROM community; +---- +Failed to download extension "will_never_exist" at URL "http://community-extensions.duckdb.org + +# Alias can not quoted: string literals are interpreted as paths +statement error +INSTALL will_never_exist FROM 'core'; +---- +IO Error: Failed to copy local extension "will_never_exist" at PATH diff --git a/test/extension/install_extension.test_slow b/test/extension/install_extension.test_slow index 020913ea459..e5850adaf63 100644 --- a/test/extension/install_extension.test_slow +++ b/test/extension/install_extension.test_slow @@ -39,7 +39,7 @@ restart statement maybe FORCE INSTALL '__BUILD_DIRECTORY__/test/extension/loadable_extension_DEMO.duckdb_extension'; ---- -IO Error: Failed to read extension from +IO Error: Failed to copy local extension statement ok FORCE INSTALL '__BUILD_DIRECTORY__/test/extension/loadable_extension_demo.duckdb_extension'; diff --git a/test/extension/install_version.test b/test/extension/install_version.test new file mode 100644 index 00000000000..54518f33fa7 --- /dev/null +++ b/test/extension/install_version.test @@ -0,0 +1,31 @@ +# name: test/extension/install_version.test +# description: test installing extensions of specific versions +# group: [extension] + +# This test assumes icu and json to be available in the LOCAL_EXTENSION_REPO and NOT linked into duckdb statically +# -> this should be the case for our autoloading tests where we have the local_extension_repo variable set +require-env LOCAL_EXTENSION_REPO + +require notwindows + +# Ensure we have a clean extension directory without any preinstalled extensions +statement ok +set extension_directory='__TEST_DIR__/install_version' + +statement ok +set custom_extension_repository='${LOCAL_EXTENSION_REPO}' + +# Confirm the version ends up in the url we search. +# TODO: the script to create a local extension repo should be able to produce versioned extension paths then we can properly +# test this +statement error +INSTALL quack FROM '${LOCAL_EXTENSION_REPO}' VERSION 'myversion'; +---- +/quack/myversion/ + +# Using the default extension repository +statement error +INSTALL quack VERSION 'myversion'; +---- +/quack/myversion/ + diff --git a/test/extension/load_extension.test b/test/extension/load_extension.test index 5a1fe822ea7..c40b06f929e 100644 --- a/test/extension/load_extension.test +++ b/test/extension/load_extension.test @@ -12,14 +12,17 @@ PRAGMA enable_verification statement error LOAD 'asdf'; ---- +:IO Error: Extension.*not found.* statement error LOAD 'Makefile'; ---- +:IO Error: Extension.*not found.* statement error LOAD NULL; ---- +:Parser Error: syntax error.* statement ok LOAD '__BUILD_DIRECTORY__/test/extension/loadable_extension_demo.duckdb_extension'; @@ -50,10 +53,12 @@ QUACK statement error QUAC ---- +:Parser Error: Did you mean.* statement error QUACK NOT QUACK ---- +:Parser Error: This is not a quack.* query I SELECT contains(loaded_extensions(), 'loadable_extension_demo') diff --git a/test/extension/loadable_extension_demo.cpp b/test/extension/loadable_extension_demo.cpp index 413ae8cdc7c..206a3a76f09 100644 --- a/test/extension/loadable_extension_demo.cpp +++ b/test/extension/loadable_extension_demo.cpp @@ -7,6 +7,11 @@ #include "duckdb/parser/parsed_data/create_type_info.hpp" #include "duckdb/catalog/catalog_entry/type_catalog_entry.hpp" #include "duckdb/planner/extension_callback.hpp" +#include "duckdb/function/cast/cast_function_set.hpp" +#include "duckdb/main/extension_util.hpp" +#include "duckdb/common/vector_operations/generic_executor.hpp" +#include "duckdb/common/exception/conversion_exception.hpp" +#include "duckdb/planner/expression/bound_constant_expression.hpp" using namespace duckdb; @@ -172,6 +177,14 @@ struct QuackExtensionData : public ParserExtensionParseData { duckdb::unique_ptr Copy() const override { return make_uniq(number_of_quacks); } + + string ToString() const override { + vector quacks; + for (idx_t i = 0; i < number_of_quacks; i++) { + quacks.push_back("QUACK"); + } + return StringUtil::Join(quacks, " "); + } }; class QuackExtension : public ParserExtension { @@ -235,6 +248,240 @@ inline void LoadedExtensionsFunction(DataChunk &args, ExpressionState &state, Ve } result.Reference(Value(result_str)); } +//===--------------------------------------------------------------------===// +// Bounded type +//===--------------------------------------------------------------------===// + +struct BoundedType { + static LogicalType Get(int32_t max_val) { + auto type = LogicalType(LogicalTypeId::INTEGER); + type.SetAlias("BOUNDED"); + type.SetModifiers({Value::INTEGER(max_val)}); + return type; + } + + static LogicalType GetDefault() { + auto type = LogicalType(LogicalTypeId::INTEGER); + type.SetAlias("BOUNDED"); + // By default we set a NULL max value to indicate that it can be any value + type.SetModifiers({Value(LogicalType::INTEGER)}); + return type; + } + + static int32_t GetMaxValue(const LogicalType &type) { + auto mods_ptr = type.GetModifiers(); + if (!mods_ptr) { + throw InvalidInputException("BOUNDED type must have a max value"); + } + auto &mods = *mods_ptr; + if (mods[0].IsNull()) { + throw InvalidInputException("BOUNDED type must have a max value"); + } + return mods[0].GetValue(); + } +}; + +static void BoundedMaxFunc(DataChunk &args, ExpressionState &state, Vector &result) { + result.Reference(BoundedType::GetMaxValue(args.data[0].GetType())); +} + +static unique_ptr BoundedMaxBind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + if (arguments[0]->return_type == BoundedType::GetDefault()) { + bound_function.arguments[0] = arguments[0]->return_type; + } else { + throw BinderException("bounded_max expects a BOUNDED type"); + } + return nullptr; +} + +static void BoundedAddFunc(DataChunk &args, ExpressionState &state, Vector &result) { + auto &left_vector = args.data[0]; + auto &right_vector = args.data[1]; + const auto count = args.size(); + BinaryExecutor::Execute(left_vector, right_vector, result, count, + [&](int32_t left, int32_t right) { return left + right; }); +} + +static unique_ptr BoundedAddBind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + if (BoundedType::GetDefault() == arguments[0]->return_type && + BoundedType::GetDefault() == arguments[1]->return_type) { + auto left_max_val = BoundedType::GetMaxValue(arguments[0]->return_type); + auto right_max_val = BoundedType::GetMaxValue(arguments[1]->return_type); + + auto new_max_val = left_max_val + right_max_val; + bound_function.arguments[0] = arguments[0]->return_type; + bound_function.arguments[1] = arguments[1]->return_type; + bound_function.return_type = BoundedType::Get(new_max_val); + } else { + throw BinderException("bounded_add expects two BOUNDED types"); + } + return nullptr; +} + +struct BoundedFunctionData : public FunctionData { + int32_t max_val; + + unique_ptr Copy() const override { + auto copy = make_uniq(); + copy->max_val = max_val; + return std::move(copy); + } + + bool Equals(const FunctionData &other_p) const override { + auto &other = other_p.Cast(); + return max_val == other.max_val; + } +}; + +static unique_ptr BoundedInvertBind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + if (arguments[0]->return_type == BoundedType::GetDefault()) { + bound_function.arguments[0] = arguments[0]->return_type; + bound_function.return_type = arguments[0]->return_type; + } else { + throw BinderException("bounded_invert expects a BOUNDED type"); + } + auto result = make_uniq(); + result->max_val = BoundedType::GetMaxValue(bound_function.return_type); + return std::move(result); +} + +static void BoundedInvertFunc(DataChunk &args, ExpressionState &state, Vector &result) { + auto &source_vector = args.data[0]; + const auto count = args.size(); + + auto result_type = result.GetType(); + auto output_max_val = BoundedType::GetMaxValue(result_type); + + UnaryExecutor::Execute(source_vector, result, count, + [&](int32_t input) { return std::min(-input, output_max_val); }); +} + +static void BoundedEvenFunc(DataChunk &args, ExpressionState &state, Vector &result) { + auto &source_vector = args.data[0]; + const auto count = args.size(); + UnaryExecutor::Execute(source_vector, result, count, [&](int32_t input) { return input % 2 == 0; }); +} + +static void BoundedToAsciiFunc(DataChunk &args, ExpressionState &state, Vector &result) { + auto &source_vector = args.data[0]; + const auto count = args.size(); + + UnaryExecutor::Execute(source_vector, result, count, [&](int32_t input) { + if (input < 0) { + throw NotImplementedException("Negative values not supported"); + } + string s; + s.push_back(static_cast(input)); + return StringVector::AddString(result, s); + }); +} + +static bool BoundedToBoundedCast(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { + auto input_max_val = BoundedType::GetMaxValue(source.GetType()); + auto output_max_val = BoundedType::GetMaxValue(result.GetType()); + + if (input_max_val <= output_max_val) { + result.Reinterpret(source); + return true; + } else { + throw ConversionException(source.GetType(), result.GetType()); + } +} + +static bool IntToBoundedCast(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { + auto &ty = result.GetType(); + auto output_max_val = BoundedType::GetMaxValue(ty); + UnaryExecutor::Execute(source, result, count, [&](int32_t input) { + if (input > output_max_val) { + throw ConversionException(StringUtil::Format("Value %s exceeds max value of bounded type (%s)", + to_string(input), to_string(output_max_val))); + } + return input; + }); + return true; +} + +//===--------------------------------------------------------------------===// +// MINMAX type +//===--------------------------------------------------------------------===// +// This is like the BOUNDED type, except it has a custom bind_modifiers function +// to verify that the range is valid + +struct MinMaxType { + static LogicalType Bind(BindTypeModifiersInput &input) { + auto &modifiers = input.modifiers; + + if (modifiers.size() != 2) { + throw BinderException("MINMAX type must have two modifiers"); + } + if (modifiers[0].type() != LogicalType::INTEGER || modifiers[1].type() != LogicalType::INTEGER) { + throw BinderException("MINMAX type modifiers must be integers"); + } + if (modifiers[0].IsNull() || modifiers[1].IsNull()) { + throw BinderException("MINMAX type modifiers cannot be NULL"); + } + + auto min_val = modifiers[0].GetValue(); + auto max_val = modifiers[1].GetValue(); + if (min_val >= max_val) { + throw BinderException("MINMAX type min value must be less than max value"); + } + + auto type = LogicalType(LogicalTypeId::INTEGER); + type.SetAlias("MINMAX"); + type.SetModifiers({Value::INTEGER(min_val), Value::INTEGER(max_val)}); + return type; + } + + static int32_t GetMinValue(const LogicalType &type) { + D_ASSERT(type.HasModifiers()); + auto &mods = *type.GetModifiers(); + return mods[0].GetValue(); + } + + static int32_t GetMaxValue(const LogicalType &type) { + D_ASSERT(type.HasModifiers()); + auto &mods = *type.GetModifiers(); + return mods[1].GetValue(); + } + + static LogicalType Get(int32_t min_val, int32_t max_val) { + auto type = LogicalType(LogicalTypeId::INTEGER); + type.SetAlias("MINMAX"); + type.SetModifiers({Value::INTEGER(min_val), Value::INTEGER(max_val)}); + return type; + } + + static LogicalType GetDefault() { + auto type = LogicalType(LogicalTypeId::INTEGER); + type.SetAlias("MINMAX"); + return type; + } +}; + +static bool IntToMinMaxCast(Vector &source, Vector &result, idx_t count, CastParameters ¶meters) { + auto &ty = result.GetType(); + auto min_val = MinMaxType::GetMinValue(ty); + auto max_val = MinMaxType::GetMaxValue(ty); + UnaryExecutor::Execute(source, result, count, [&](int32_t input) { + if (input < min_val || input > max_val) { + throw ConversionException(StringUtil::Format("Value %s is outside of range [%s,%s]", to_string(input), + to_string(min_val), to_string(max_val))); + } + return input; + }); + return true; +} + +static void MinMaxRangeFunc(DataChunk &args, ExpressionState &state, Vector &result) { + auto &ty = args.data[0].GetType(); + auto min_val = MinMaxType::GetMinValue(ty); + auto max_val = MinMaxType::GetMaxValue(ty); + result.Reference(Value::INTEGER(max_val - min_val)); +} //===--------------------------------------------------------------------===// // Extension load + setup @@ -265,17 +512,23 @@ DUCKDB_EXTENSION_API void loadable_extension_demo_init(duckdb::DatabaseInstance target_type.SetAlias(alias_name); alias_info->type = target_type; - catalog.CreateType(client_context, *alias_info); + auto type_entry = catalog.CreateType(client_context, *alias_info); + type_entry->tags["ext:name"] = "loadable_extension_demo"; + type_entry->tags["ext:author"] = "DuckDB Labs"; // Function add point ScalarFunction add_point_func("add_point", {target_type, target_type}, target_type, AddPointFunction); CreateScalarFunctionInfo add_point_info(add_point_func); - catalog.CreateFunction(client_context, add_point_info); + auto add_point_entry = catalog.CreateFunction(client_context, add_point_info); + add_point_entry->tags["ext:name"] = "loadable_extension_demo"; + add_point_entry->tags["ext:author"] = "DuckDB Labs"; // Function sub point ScalarFunction sub_point_func("sub_point", {target_type, target_type}, target_type, SubPointFunction); CreateScalarFunctionInfo sub_point_info(sub_point_func); - catalog.CreateFunction(client_context, sub_point_info); + auto sub_point_entry = catalog.CreateFunction(client_context, sub_point_info); + sub_point_entry->tags["ext:name"] = "loadable_extension_demo"; + sub_point_entry->tags["ext:author"] = "DuckDB Labs"; // Function sub point ScalarFunction loaded_extensions("loaded_extensions", {}, LogicalType::VARCHAR, LoadedExtensionsFunction); @@ -293,6 +546,48 @@ DUCKDB_EXTENSION_API void loadable_extension_demo_init(duckdb::DatabaseInstance auto &config = DBConfig::GetConfig(db); config.parser_extensions.push_back(QuackExtension()); config.extension_callbacks.push_back(make_uniq()); + + // Bounded type + auto bounded_type = BoundedType::GetDefault(); + ExtensionUtil::RegisterType(db, "BOUNDED", bounded_type); + + // Example of function inspecting the type property + ScalarFunction bounded_max("bounded_max", {bounded_type}, LogicalType::INTEGER, BoundedMaxFunc, BoundedMaxBind); + ExtensionUtil::RegisterFunction(db, bounded_max); + + // Example of function inspecting the type property and returning the same type + ScalarFunction bounded_invert("bounded_invert", {bounded_type}, bounded_type, BoundedInvertFunc, BoundedInvertBind); + // bounded_invert.serialize = BoundedReturnSerialize; + // bounded_invert.deserialize = BoundedReturnDeserialize; + ExtensionUtil::RegisterFunction(db, bounded_invert); + + // Example of function inspecting the type property of both arguments and returning a new type + ScalarFunction bounded_add("bounded_add", {bounded_type, bounded_type}, bounded_type, BoundedAddFunc, + BoundedAddBind); + ExtensionUtil::RegisterFunction(db, bounded_add); + + // Example of function that is generic over the type property (the bound is not important) + ScalarFunction bounded_even("bounded_even", {bounded_type}, LogicalType::BOOLEAN, BoundedEvenFunc); + ExtensionUtil::RegisterFunction(db, bounded_even); + + // Example of function that is specialized over type property + auto bounded_specialized_type = BoundedType::Get(0xFF); + ScalarFunction bounded_to_ascii("bounded_ascii", {bounded_specialized_type}, LogicalType::VARCHAR, + BoundedToAsciiFunc); + ExtensionUtil::RegisterFunction(db, bounded_to_ascii); + + // Enable explicit casting to our specialized type + ExtensionUtil::RegisterCastFunction(db, bounded_type, bounded_specialized_type, BoundCastInfo(BoundedToBoundedCast), + 0); + // Casts + ExtensionUtil::RegisterCastFunction(db, LogicalType::INTEGER, bounded_type, BoundCastInfo(IntToBoundedCast), 0); + + // MinMax Type + auto minmax_type = MinMaxType::GetDefault(); + ExtensionUtil::RegisterType(db, "MINMAX", minmax_type, MinMaxType::Bind); + ExtensionUtil::RegisterCastFunction(db, LogicalType::INTEGER, minmax_type, BoundCastInfo(IntToMinMaxCast), 0); + ExtensionUtil::RegisterFunction( + db, ScalarFunction("minmax_range", {minmax_type}, LogicalType::INTEGER, MinMaxRangeFunc)); } DUCKDB_EXTENSION_API const char *loadable_extension_demo_version() { diff --git a/test/extension/loadable_extension_optimizer_demo.cpp b/test/extension/loadable_extension_optimizer_demo.cpp index 85b720fb73d..8644afcf946 100644 --- a/test/extension/loadable_extension_optimizer_demo.cpp +++ b/test/extension/loadable_extension_optimizer_demo.cpp @@ -68,13 +68,14 @@ class WaggleExtension : public OptimizerExtension { } } - static void WaggleOptimizeFunction(ClientContext &context, OptimizerExtensionInfo *info, - duckdb::unique_ptr &plan) { + static void WaggleOptimizeFunction(OptimizerExtensionInput &input, duckdb::unique_ptr &plan) { if (!HasParquetScan(*plan)) { return; } // rpc + auto &context = input.context; + Value host, port; if (!context.TryGetCurrentSetting("waggle_location_host", host) || !context.TryGetCurrentSetting("waggle_location_port", port)) { diff --git a/test/extension/test_alias_point.test b/test/extension/test_alias_point.test index 4ea6a10ed64..1b95a9360b4 100644 --- a/test/extension/test_alias_point.test +++ b/test/extension/test_alias_point.test @@ -40,10 +40,12 @@ SELECT sub_point(({'x': 2, 'y': 3})::POINT, ({'x': 3, 'y': 4})::POINT) statement error SELECT add_point(pt, pt) from points; ---- +:Binder Error:.*No function matches.* statement error SELECT sub_point(pt, pt) from points; ---- +:Binder Error:.*No function matches.* query I SELECT add_point(point, point) from points; diff --git a/test/extension/test_custom_type_modifier.test_slow b/test/extension/test_custom_type_modifier.test_slow new file mode 100644 index 00000000000..366263ca46d --- /dev/null +++ b/test/extension/test_custom_type_modifier.test_slow @@ -0,0 +1,199 @@ +# name: test/extension/test_custom_type_modifier.test_slow +# description: Test custom type level metadata. +# group: [extension] + +require skip_reload + +require notmingw + +statement ok +PRAGMA enable_verification + +statement ok +LOAD '__BUILD_DIRECTORY__/test/extension/loadable_extension_demo.duckdb_extension'; + +statement ok +CREATE TABLE t1 (i BOUNDED(200)); + +statement ok +INSERT INTO t1 VALUES (97), (98), (99); + +# Example of function ignoring the type property (no cast needed) +query I +SELECT bounded_even(i) FROM t1 ORDER BY 1; +---- +false +false +true + +query II +EXPLAIN SELECT bounded_even(i) FROM t1 ORDER BY 1; +---- +physical_plan :.*CAST.* + +# Example of function inspecting the type property +query I +SELECT bounded_max(i) FROM t1; +---- +200 +200 +200 + +# Example of function inspecting the type property to return value of the same type +query II +SELECT bounded_invert(i) as b, typeof(b) FROM t1 ORDER BY 1; +---- +-99 BOUNDED(200) +-98 BOUNDED(200) +-97 BOUNDED(200) + +statement ok +CREATE TABLE t2 (i BOUNDED(500)); + +statement ok +INSERT INTO t2 VALUES (100), (500); + +# Example of function inspecting both arguments type property to return a new type +query II +SELECT bounded_add(t1.i, t2.i) as s, typeof(s) FROM t1, t2 ORDER BY 1; +---- +197 BOUNDED(700) +198 BOUNDED(700) +199 BOUNDED(700) +597 BOUNDED(700) +598 BOUNDED(700) +599 BOUNDED(700) + +# Example of function that is specialized by the type property +query II +EXPLAIN SELECT bounded_ascii(i) FROM t1 ORDER BY 1; +---- +physical_plan :.*CAST.* + +query I +SELECT bounded_ascii(i) FROM t1 ORDER BY 1; +---- +a +b +c + +statement error +SELECT bounded_ascii(i) FROM t2 ORDER BY 1; +---- +Conversion Error: Type BOUNDED(500) can't be cast as BOUNDED(255) + +query I +SELECT bounded_ascii(i::INTEGER::BOUNDED(255)) FROM t2 WHERE i < 255; +---- +d + +# Test that we cant apply too many modifiers +statement error +CREATE TABLE t3 (i BOUNDED(200, 300)); +---- +Binder Error: Cannot apply '2' type modifier(s) to type 'BOUNDED' taking at most '1' type modifier(s) + +statement ok +CREATE TYPE user_type AS INTEGER + +# We cant apply a modifier to a type without modifiers +statement error +CREATE TABLE t4 (i user_type(NULL)); +---- +Binder Error: Type 'user_type' does not take any type modifiers + +statement error +SELECT 1::BOUNDED(NULL) +---- +Invalid Input Error: BOUNDED type must have a max value + +statement error +SELECT 1::BOUNDED(900000000000000000) +---- +Binder Error: Cannot apply type modifier '900000000000000000' to type 'BOUNDED', expected value of type 'INTEGER' + + +# MinMax Type +# This is similar to bounded, except it uses a custom bind function to enforce the min/max values at construction time +statement ok +CREATE TABLE t5 (i MINMAX(200, 300)); + +statement ok +INSERT INTO t5 VALUES (200), (300); + +statement error +INSERT INTO t5 VALUES (199); +---- +Conversion Error: Value 199 is outside of range [200,300] + +statement error +INSERT INTO t5 VALUES (301); +---- +Conversion Error: Value 301 is outside of range [200,300] + +statement error +SELECT 10::MINMAX(0, 1); +---- +Conversion Error: Value 10 is outside of range [0,1] + +statement error +SELECT 10::MINMAX(1337); +---- +Binder Error: MINMAX type must have two modifiers + +statement error +SELECT 10::MINMAX('foob', 10); +---- +Binder Error: MINMAX type modifiers must be integers + +statement error +SELECT 10::MINMAX(10, NULL::INTEGER); +---- +Parser Error: Expected a constant as type modifier + +statement error +SELECT 10::MINMAX(15, 10); +---- +Binder Error: MINMAX type min value must be less than max value + + + +# Test with creating an index +statement ok +CREATE TABLE minmax_table (i MINMAX(0, 100)); + +statement ok +INSERT INTO minmax_table VALUES (0), (10), (20), (30), (40), (50), (60), (70), (80), (90), (100); + +statement ok +CREATE INDEX minmax_index ON minmax_table(i); + +query I +SELECT * FROM minmax_table WHERE i = 50; +---- +50 + +statement ok +PRAGMA explain_output='optimized_only' + +query II +EXPLAIN SELECT * FROM minmax_table WHERE i = 50; +---- +logical_opt :.*INDEX_SCAN.* + +# Check the typename in the catalog +query I +SELECT parameter_types from duckdb_functions() where function_name = 'minmax_range'; +---- +[MINMAX] + +query I +SELECT parameter_types from duckdb_functions() where function_name = 'bounded_ascii'; +---- +[BOUNDED(255)] + +# BOUNDED's default type modifier values is NULL, but it could theorietically be set to something else +query I +SELECT parameter_types from duckdb_functions() where function_name = 'bounded_add'; +---- +[BOUNDED(NULL), BOUNDED(NULL)] diff --git a/test/extension/test_tags.test b/test/extension/test_tags.test new file mode 100644 index 00000000000..581a0209788 --- /dev/null +++ b/test/extension/test_tags.test @@ -0,0 +1,24 @@ +# name: test/extension/test_tags.test +# description: Test querying tagged extension items. +# group: [extension] + +require skip_reload + +require notmingw + +statement ok +PRAGMA enable_verification + +statement ok +LOAD '__BUILD_DIRECTORY__/test/extension/loadable_extension_demo.duckdb_extension'; + +query II +SELECT function_name, tags['ext:author'] FROM duckdb_functions() WHERE tags['ext:name'] = ['loadable_extension_demo'] ORDER BY function_name; +---- +add_point [DuckDB Labs] +sub_point [DuckDB Labs] + +query II +SELECT type_name, tags['ext:author'] FROM duckdb_types() WHERE tags['ext:name'] = ['loadable_extension_demo'] ORDER BY type_name; +---- +POINT [DuckDB Labs] \ No newline at end of file diff --git a/test/extension/update_extensions.test b/test/extension/update_extensions.test new file mode 100644 index 00000000000..963218e2047 --- /dev/null +++ b/test/extension/update_extensions.test @@ -0,0 +1,67 @@ +# name: test/extension/update_extensions.test +# description: Tests for the update extensions statement +# group: [extension] + +# This test assumes icu and json to be available in the LOCAL_EXTENSION_REPO and NOT linked into duckdb statically +# -> this should be the case for our autoloading tests where we have the local_extension_repo variable set +require-env LOCAL_EXTENSION_REPO + +require no_extension_autoloading + +statement ok +PRAGMA enable_verification + +# Set the repository to the correct one +statement ok +set custom_extension_repository='${LOCAL_EXTENSION_REPO}' + +# Ensure we have a clean extension directory without any preinstalled extensions +statement ok +set extension_directory='__TEST_DIR__/update_extensions' + +statement error +with cte as (select 42 AS a) UPDATE EXTENSIONS +---- +Providing a with clause with an UPDATE EXTENSIONS statement is not allowed + +# No extensions installed -> update returns empty list +query IIIII +UPDATE EXTENSIONS; +---- + +statement ok +INSTALL json + +query IIIII +UPDATE EXTENSIONS; +---- +json :.* NO_UPDATE_AVAILABLE :.* :.* + +query IIIII +UPDATE EXTENSIONS (json); +---- +json :.* NO_UPDATE_AVAILABLE :.* :.* + +statement error +UPDATE EXTENSIONS (foobar); +---- +Failed to update the extension 'foobar', the extension is not installed! + +statement ok +INSTALL '__BUILD_DIRECTORY__/test/extension/loadable_extension_demo.duckdb_extension'; + +# The loadable_extension_demo is loaded as a direct URL, these are not considered for updating +query IIIII rowsort +UPDATE EXTENSIONS; +---- +json :.* NO_UPDATE_AVAILABLE :.* :.* +loadable_extension_demo (empty) NOT_A_REPOSITORY default-version default-version + +# Doublecheck duckdb_extensions() +query IIII rowsort +SELECT extension_name, extension_version, install_mode, installed_from from duckdb_extensions() where installed +---- +json :.* REPOSITORY :.* +loadable_extension_demo default-version CUSTOM_PATH :.*loadable\_extension\_demo\.duckdb_extension +parquet :.* STATICALLY_LINKED :.* + diff --git a/test/extension/update_extensions_ci.test b/test/extension/update_extensions_ci.test new file mode 100644 index 00000000000..1606f7c08a5 --- /dev/null +++ b/test/extension/update_extensions_ci.test @@ -0,0 +1,391 @@ +# name: test/extension/update_extensions_ci.test +# description: Tests for the update extensions statement +# group: [extension] + +# NOTE: this test requires specific setup and should probably only by ran through `scripts/run_extension_medata_tests.sh` + +load __TEST_DIR__/update_extensions_ci.db + +# This test expects a specific state, which is marked to be present through setting this env variable. +require-env RUN_EXTENSION_UPDATE_TEST + +# This repo is expected to contain json and tpch, where tpch was updated from v0.0.1 to v0.0.2 +require-env LOCAL_EXTENSION_REPO_UPDATED + +# This repo is expected to contain the json extension built with a binary with an incorrect platform +require-env LOCAL_EXTENSION_REPO_INCORRECT_PLATFORM + +# This repo is expected to contain the json extension built with a binary with an incorrect duckdb_version +require-env LOCAL_EXTENSION_REPO_INCORRECT_DUCKDB_VERSION + +# This repo is expected to contain the json extension built with a binary with an incorrect version and platform +require-env LOCAL_EXTENSION_REPO_VERSION_AND_PLATFORM_INCORRECT + +# This extension dir is expected to contain json, tpch and tpcds all at version v0.0.1 and tpcds installed directly, not through +# a repo +require-env LOCAL_EXTENSION_DIR + +# This dir holds some directly installable, incorrectly matched extensions, but also a correctly installable +require-env DIRECT_INSTALL_DIR + +# This extension dir is expected to contain tpch and tpcds, but with a corrupted tpcds metadata file +require-env LOCAL_EXTENSION_DIR_MALFORMED_INFO + +# This extension dir is expected to contain tpch and tpcds, but with a corrupted tpcds metadata file +require-env LOCAL_EXTENSION_DIR_INFO_INCORRECT_VERSION + +# Address on a minio server that has the LOCAL_EXTENSION_REPO_UPDATED copied to it +require-env REMOTE_EXTENSION_REPO_UPDATED + +# Direct path with version and platform, for testing http direct install +require-env REMOTE_EXTENSION_REPO_DIRECT_PATH + +# Parquet is statically loaded for this test +require parquet + +# We start by testing some malformed dirs +statement ok +set extension_directory='${LOCAL_EXTENSION_DIR_MALFORMED_INFO}' + +# this will now throw IOError +statement error +FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +IO Error: Failed to read info file for 'tpcds' extension + +# this will now throw IOError +statement error +UPDATE EXTENSIONS +---- +IO Error: Failed to read info file for 'tpcds' extension + +# lets restore by reinstalling tpcds +statement ok +FORCE INSTALL '${DIRECT_INSTALL_DIR}/tpcds.duckdb_extension'; + +# Things are back to normal +query IIII +SELECT extension_name, install_mode, installed_from, extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +tpcds CUSTOM_PATH ./build/extension_metadata_test_data/direct_install/tpcds.duckdb_extension v0.0.1 + +statement ok +load tpcds + +# Same here +query IIIII +UPDATE EXTENSIONS +---- +tpcds (empty) NOT_A_REPOSITORY v0.0.1 v0.0.1 + +restart + +# Here the metadata mismatches the actually installed extension +statement ok +set extension_directory='${LOCAL_EXTENSION_DIR_INFO_INCORRECT_VERSION}' + +# duckdb_extensions() only reads the metadata. No extension files are opened +query IIII +SELECT extension_name, install_mode, installed_from, extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +tpch REPOSITORY ./build/extension_metadata_test_data/repository v0.0.1 + +# However when trying to load, we detect the mismatch +statement error +load tpch +---- +Metadata mismatch detected when loading extension + +# Recovery is done by force installing +statement ok +FORCE INSTALL tpch FROM '${LOCAL_EXTENSION_REPO_UPDATED}' + +statement ok +load tpch; + +restart + +statement ok +set custom_extension_repository='${LOCAL_EXTENSION_REPO_UPDATED}' + +statement ok +set extension_directory='${LOCAL_EXTENSION_DIR}' + +query IIII rowsort +SELECT extension_name, install_mode, installed_from, extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +inet UNKNOWN (empty) (empty) +json REPOSITORY ./build/extension_metadata_test_data/repository v0.0.1 +tpcds CUSTOM_PATH ./build/extension_metadata_test_data/direct_install/tpcds.duckdb_extension v0.0.1 +tpch REPOSITORY ./build/extension_metadata_test_data/repository v0.0.1 + +query III rowsort +SELECT extension_name, install_mode, installed_from FROM duckdb_extensions() where extension_name = 'parquet' +---- +parquet STATICALLY_LINKED (empty) + +# Get the parquet version +query I rowsort parquet_version +SELECT extension_version FROM duckdb_extensions() where extension_name = 'parquet' +---- + +# ensure the parquet version matches duckdb's sourceid +query I rowsort parquet_version +select source_id from pragma_version(); +---- + +query IIIII rowsort +UPDATE EXTENSIONS; +---- +inet (empty) MISSING_INSTALL_INFO (empty) (empty) +json :.* NO_UPDATE_AVAILABLE v0.0.1 v0.0.1 +tpcds :.* NOT_A_REPOSITORY v0.0.1 v0.0.1 +tpch :.* UPDATED v0.0.1 v0.0.2 + +# duckdb_extensions() now also showing updated version +query IIII rowsort +SELECT extension_name, install_mode, installed_from, extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +inet UNKNOWN (empty) (empty) +json REPOSITORY ./build/extension_metadata_test_data/repository v0.0.1 +tpcds CUSTOM_PATH ./build/extension_metadata_test_data/direct_install/tpcds.duckdb_extension v0.0.1 +tpch REPOSITORY ./build/extension_metadata_test_data/repository v0.0.2 + +# Now lets restored the corrupt inet extension (it has a missing info file) +statement ok +FORCE INSTALL inet; + +# Rerunning update will now show everything being up-to-date (inet extension was force installed and is now v0.0.2) +query IIIII rowsort +UPDATE EXTENSIONS; +---- +inet :.* NO_UPDATE_AVAILABLE v0.0.2 v0.0.2 +json :.* NO_UPDATE_AVAILABLE v0.0.1 v0.0.1 +tpcds :.* NOT_A_REPOSITORY v0.0.1 v0.0.1 +tpch :.* NO_UPDATE_AVAILABLE v0.0.2 v0.0.2 + +statement ok +load json; + +statement ok +load tpch; + +statement ok +load tpcds; + +statement ok +load inet; + +# Ensure the result is still fine after loading; this will ensure Version() call matches the encoded footer value +query IIII rowsort +SELECT extension_name, install_mode, installed_from, extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +inet REPOSITORY ./build/extension_metadata_test_data/repository v0.0.2 +json REPOSITORY ./build/extension_metadata_test_data/repository v0.0.1 +tpcds CUSTOM_PATH ./build/extension_metadata_test_data/direct_install/tpcds.duckdb_extension v0.0.1 +tpch REPOSITORY ./build/extension_metadata_test_data/repository v0.0.2 + +## Try various failing installations and match their error +statement error +FORCE INSTALL '${DIRECT_INSTALL_DIR}/json_incorrect_platform.duckdb_extension'; +---- +Failed to install './build/extension_metadata_test_data/direct_install/json_incorrect_platform.duckdb_extension' +The file was built for the platform 'test_platform', but we can only load extensions built for platform + +statement error +FORCE INSTALL json_incorrect_platform FROM '${LOCAL_EXTENSION_REPO_INCORRECT_PLATFORM}' +---- +Failed to install 'json_incorrect_platform' +The file was built for the platform 'test_platform', but we can only load extensions built for platform + +statement error +FORCE INSTALL '${DIRECT_INSTALL_DIR}/json_incorrect_version.duckdb_extension'; +---- +Failed to install './build/extension_metadata_test_data/direct_install/json_incorrect_version.duckdb_extension' +The file was built for DuckDB version 'v1337', but we can only load extensions built for DuckDB version + +statement error +FORCE INSTALL json_incorrect_version FROM '${LOCAL_EXTENSION_REPO_INCORRECT_DUCKDB_VERSION}'; +---- +Failed to install 'json_incorrect_version' +The file was built for DuckDB version 'v1337', but we can only load extensions built for DuckDB version + +# These should print both errors +statement error +FORCE INSTALL '${DIRECT_INSTALL_DIR}/json_incorrect_version_and_platform.duckdb_extension'; +---- +Also, the file was built for the platform 'test_platform', but we can only load extensions built for platform + +statement error +FORCE INSTALL json_incorrect_version_and_platform FROM '${LOCAL_EXTENSION_REPO_VERSION_AND_PLATFORM_INCORRECT}' +---- +Also, the file was built for the platform 'test_platform', but we can only load extensions built for platform + +## Now try the same for loading, this time only with the direct load syntax +statement error +LOAD '${DIRECT_INSTALL_DIR}/json_incorrect_version_and_platform.duckdb_extension'; +---- +Also, the file was built for the platform 'test_platform', but we can only load extensions built for platform + +statement error +LOAD '${DIRECT_INSTALL_DIR}/json_incorrect_platform.duckdb_extension'; +---- +The file was built for the platform 'test_platform', but we can only load extensions built for platform + +statement error +LOAD '${DIRECT_INSTALL_DIR}/json_incorrect_version.duckdb_extension'; +---- +The file was built for DuckDB version 'v1337', but we can only load extensions built for DuckDB version + +# Note that this is the json extension with incorrect platform and version +statement error +FORCE INSTALL '${DIRECT_INSTALL_DIR}/json.duckdb_extension'; +---- +Also, the file was built for the platform 'test_platform', but we can only load extensions built for platform + +restart + +# override the default behaviour of skipping HTTP errors and connection failures: this test fails on connection issues +set ignore_error_messages + +# Set extension dir to a fresh one +statement ok +set extension_directory='__TEST_DIR__/update_extensions_ci_fresh' + +# Nothing installed beforehand +query IIII +SELECT extension_name, install_mode, installed_from, extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- + +# Install from the remote repo +statement ok +force install inet from '${REMOTE_EXTENSION_REPO_UPDATED}' + +# Installed from the minio repo now +query IIII +SELECT extension_name, install_mode, installed_from, extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +inet REPOSITORY http://duckdb-minio.com:9000/test-bucket-public/ci-test-repo v0.0.2 + +# Installed from the minio repo now +query IIIII +UPDATE EXTENSIONS +---- +inet http://duckdb-minio.com:9000/test-bucket-public/ci-test-repo NO_UPDATE_AVAILABLE v0.0.2 v0.0.2 + +# Rerunning install with matching origin is a NOP and totally fine +statement ok +install inet from '${REMOTE_EXTENSION_REPO_UPDATED}' + +# Direct installing the same extension is now not allowed +statement error +install '${REMOTE_EXTENSION_REPO_DIRECT_PATH}/inet.duckdb_extension.gz' +---- +Invalid Input Error: Installing extension 'inet' failed. The extension is already installed but the origin is different. +Currently installed extension is from repository 'http://duckdb-minio.com:9000/test-bucket-public/ci-test-repo', while the extension to be installed is from custom_path + +# Installing the same extension from a different repository is also not allowed +statement error +install '${REMOTE_EXTENSION_REPO_DIRECT_PATH}/inet.duckdb_extension.gz' FROM './dummy_repo' +---- +Invalid Input Error: Installing extension 'inet' failed. The extension is already installed but the origin is different. +Currently installed extension is from repository 'http://duckdb-minio.com:9000/test-bucket-public/ci-test-repo', while the extension to be installed is from repository './dummy_repo'. +To solve this rerun this command with `FORCE INSTALL` + +# We can circumvent this by disabling metadata checks +statement ok +set allow_extensions_metadata_mismatch=true; + +# Note that this is a NOP +statement ok +install '${REMOTE_EXTENSION_REPO_DIRECT_PATH}/inet.duckdb_extension.gz' + +# inet still the same +query IIII +SELECT extension_name, install_mode, installed_from, extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +inet REPOSITORY http://duckdb-minio.com:9000/test-bucket-public/ci-test-repo v0.0.2 + +# now we force install to override +statement ok +force install '${REMOTE_EXTENSION_REPO_DIRECT_PATH}/inet.duckdb_extension.gz' + +# inet is now from a custom path +query IIII +SELECT extension_name, install_mode, parse_filename(installed_from), extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +inet CUSTOM_PATH inet.duckdb_extension.gz v0.0.2 + +# Other way around is fine and still a nop for now +statement ok +install inet from '${REMOTE_EXTENSION_REPO_UPDATED}' + +query IIII +SELECT extension_name, install_mode, parse_filename(installed_from), extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +inet CUSTOM_PATH inet.duckdb_extension.gz v0.0.2 + +statement ok +set allow_extensions_metadata_mismatch=false; + +### Now we test autoloading: it should be unaffected by error messages +statement ok +set autoload_known_extensions=true + +statement ok +set autoinstall_known_extensions=true + +# Set a non-existent autoinstall repo +statement ok +set autoinstall_extension_repository='hocus_pocus_this_is_bogus' + +statement ok +set custom_extension_repository='hocus_pocus_this_is_bogus' + +statement ok +FORCE INSTALL tpcds FROM '${LOCAL_EXTENSION_REPO_UPDATED}'; + +# Note: this would trigger the origin check normally, but now +statement ok +from tpcds_queries(); + +# The file should be from the custom path, NOT the autoinstall repo +query IIII +SELECT extension_name, install_mode, parse_filename(installed_from), extension_version FROM duckdb_extensions() where installed and extension_name != 'jemalloc' and extension_name != 'parquet' +---- +inet CUSTOM_PATH inet.duckdb_extension.gz v0.0.2 +tpcds REPOSITORY repository v0.0.1 + +### Tests with allow_unsigned extensions = false +restart + +statement ok +set extension_directory='${LOCAL_EXTENSION_DIR}' + +# Now we allow mismatching metadata +statement ok +set allow_extensions_metadata_mismatch=true; + +# Meaning that now it works +statement ok +FORCE INSTALL '${DIRECT_INSTALL_DIR}/json.duckdb_extension'; + +# We can even load it +statement ok +LOAD json; + +restart + +# However, when signed unsigned extensions are not allowed, things are different +statement ok +set allow_unsigned_extensions=false + +# Installing is still fine +statement ok +FORCE INSTALL '${DIRECT_INSTALL_DIR}/json.duckdb_extension'; + +# But loading is not +statement error +LOAD json; +---- + Also, the file was built for the platform 'test_platform', but we can only load extensions built for platform diff --git a/test/fuzzer/duckfuzz/array_const_columndatacopy.test b/test/fuzzer/duckfuzz/array_const_columndatacopy.test new file mode 100644 index 00000000000..4980258764b --- /dev/null +++ b/test/fuzzer/duckfuzz/array_const_columndatacopy.test @@ -0,0 +1,19 @@ +# name: test/fuzzer/duckfuzz/array_const_columndatacopy.test +# group: [duckfuzz] + +# Fuzzyduck issue #2392 +# Caused by not copying over enough child vector data when adding a const array vector to a column data collection +statement ok +CREATE TABLE uuids(uuid UUID); + +statement ok +INSERT INTO uuids VALUES('00000000-0000-0000-0000-000000000000'); + +statement ok +INSERT INTO uuids VALUES('ffffffff-ffff-ffff-ffff-ffffffffffff'); + +query I +SELECT TRY_CAST(uuid AS STRUCT(b VARCHAR[3])) FROM uuids; +---- +NULL +NULL \ No newline at end of file diff --git a/test/fuzzer/duckfuzz/array_distance.test b/test/fuzzer/duckfuzz/array_distance.test new file mode 100644 index 00000000000..e3b2651f841 --- /dev/null +++ b/test/fuzzer/duckfuzz/array_distance.test @@ -0,0 +1,22 @@ +# name: test/fuzzer/duckfuzz/array_distance.test +# description: Repeat row with NULL argument +# group: [duckfuzz] + +statement ok +PRAGMA enable_verification + + +statement error +SELECT array_distance('asdf', [42]::INTEGER[1]); +---- +array_distance: Arguments must be arrays of FLOAT or DOUBLE + +# original issue: https://github.com/duckdb/duckdb-fuzzer/issues/2693 + +statement ok +create table all_types as select * exclude(small_enum, medium_enum, large_enum) from test_all_types(); + +statement error +SELECT array_distance('db6d3411-3fe9-4668-bf60-06d94108c0f7', c43) FROM all_types AS t51(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37, c38, c39, c40, c41, c42, c43, c44, c45, c46, c47, c48, c49, c50) +---- +array_distance: Arguments must be arrays of FLOAT or DOUBLE diff --git a/test/fuzzer/duckfuzz/array_group_by_sample.test b/test/fuzzer/duckfuzz/array_group_by_sample.test index 3d66a22b404..e667b7b7aed 100644 --- a/test/fuzzer/duckfuzz/array_group_by_sample.test +++ b/test/fuzzer/duckfuzz/array_group_by_sample.test @@ -1,10 +1,12 @@ # name: test/fuzzer/duckfuzz/array_group_by_sample.test +# description: Test allocating enough dummy list_entry_t's during tuple format serialization. # group: [duckfuzz] -# Internal Issue #1408 -# Caused by not allocating enough fake list_entry_t's during tuple format serialization statement ok -CREATE TABLE array_tbl(c50 INTEGER[2][]);; +PRAGMA enable_verification + +statement ok +CREATE TABLE array_tbl(c50 INTEGER[2][]); statement ok INSERT INTO array_tbl VALUES('[[1, 2], [1, 2]]'); @@ -16,4 +18,21 @@ query I rowsort SELECT c50 FROM array_tbl GROUP BY ALL USING SAMPLE 3; ---- [[1, 2], [1, 2]] -[[3, 4], [3, 4]] \ No newline at end of file +[[3, 4], [3, 4]] + +# Three-level nested ARRAY. + +statement ok +CREATE TABLE array_tbl_three_level(c50 INTEGER[2][2][]); + +statement ok +INSERT INTO array_tbl_three_level VALUES('[[[42, 43], [44, 45]], [[46, 47], [48, 49]]]'); + +statement ok +INSERT INTO array_tbl_three_level VALUES('[[[12, 13], [14, 15]], [[16, 17], [18, 19]]]'); + +query I rowsort +SELECT c50 FROM array_tbl_three_level GROUP BY ALL USING SAMPLE 3 ORDER BY ALL; +---- +[[[12, 13], [14, 15]], [[16, 17], [18, 19]]] +[[[42, 43], [44, 45]], [[46, 47], [48, 49]]] \ No newline at end of file diff --git a/test/fuzzer/duckfuzz/array_hash.test b/test/fuzzer/duckfuzz/array_hash.test index 3d768be6dc0..621d075c072 100644 --- a/test/fuzzer/duckfuzz/array_hash.test +++ b/test/fuzzer/duckfuzz/array_hash.test @@ -18,4 +18,4 @@ SELECT subq_0.c2 AS c4 FROM (SELECT ref_1.fixed_nested_int_array AS c2 FROM main NULL [[4, 5, 6], [NULL, 2, 3], [4, 5, 6]] [[4, 5, 6], [NULL, 2, 3], [4, 5, 6]] -[[NULL, 2, 3], NULL, [NULL, 2, 3]] \ No newline at end of file +[[NULL, 2, 3], NULL, [NULL, 2, 3]] diff --git a/test/fuzzer/duckfuzz/array_slice_nullness.test b/test/fuzzer/duckfuzz/array_slice_nullness.test new file mode 100644 index 00000000000..dff5517aeb2 --- /dev/null +++ b/test/fuzzer/duckfuzz/array_slice_nullness.test @@ -0,0 +1,16 @@ +# name: test/fuzzer/duckfuzz/array_slice_nullness.test +# description: array_slice did not early out on NULL +# group: [duckfuzz] + +statement ok +PRAGMA enable_verification + +# simplified +query I +SELECT array_reverse(NULL::INTEGER[]) +---- +NULL + +# https://github.com/duckdb/duckdb-fuzzer/issues/2692 +statement ok +SELECT NULL LIMIT array_reverse(TRY_CAST(5722 AS TIMESTAMP WITH TIME ZONE[])) \ No newline at end of file diff --git a/test/fuzzer/duckfuzz/create_sort_key_strings.test b/test/fuzzer/duckfuzz/create_sort_key_strings.test new file mode 100644 index 00000000000..64ea975c496 --- /dev/null +++ b/test/fuzzer/duckfuzz/create_sort_key_strings.test @@ -0,0 +1,23 @@ +# name: test/fuzzer/duckfuzz/create_sort_key_strings.test +# description: create_sort_key with string boundaries +# group: [duckfuzz] + +statement ok +PRAGMA enable_verification + +statement ok +CREATE TABLE t2(c38 STRUCT(a INTEGER, b VARCHAR)); + +statement ok +INSERT INTO t2 VALUES({'a': NULL, 'b': NULL}); + +statement ok +INSERT INTO t2 VALUES({'a': 42, 'b': '🦆🦆🦆🦆🦆🦆'}); + +statement ok +INSERT INTO t2 VALUES(NULL); + +query I +SELECT any_value(NULL ORDER BY c38 ASC) FROM t2 +---- +NULL diff --git a/test/fuzzer/duckfuzz/duck_fuzz_column_binding_tests.test b/test/fuzzer/duckfuzz/duck_fuzz_column_binding_tests.test index f55e47d2c6c..eae05e8f33d 100644 --- a/test/fuzzer/duckfuzz/duck_fuzz_column_binding_tests.test +++ b/test/fuzzer/duckfuzz/duck_fuzz_column_binding_tests.test @@ -8,22 +8,20 @@ create table all_types as select * exclude(small_enum, medium_enum, large_enum) # https://github.com/duckdb/duckdb-fuzzer/issues/1357 # simplified query statement ok -SELECT ref_8.uint AS c0, - Argmin(Cast(ref_8."timestamp" AS TIMESTAMP), Cast(ref_10."timestamp" AS TIMESTAMP)) OVER (partition BY ref_10."nested_int_array", ref_10."timestamp" ORDER BY ref_8.hugeint) AS c1 -FROM main.all_types AS ref_8 -INNER JOIN main.all_types AS ref_9 -INNER JOIN main.all_types AS ref_10 -ON ( ref_10.dec38_10 IS NOT NULL) - OR EXISTS - ( SELECT ref_9."float" FROM main.all_types) -ON ((ref_9."smallint" = ref_8."smallint")) - +SELECT ref_8.uint AS c0, + Argmin(Cast(ref_8."timestamp" AS TIMESTAMP), Cast(ref_10."timestamp" AS TIMESTAMP)) OVER (partition BY ref_10."nested_int_array", ref_10."timestamp" ORDER BY ref_8.hugeint) AS c1 +FROM main.all_types AS ref_8 +INNER JOIN main.all_types AS ref_9 +INNER JOIN main.all_types AS ref_10 +ON ( ref_10.dec38_10 IS NOT NULL) + OR EXISTS + ( SELECT ref_9."float" FROM main.all_types) +ON ((ref_9."smallint" = ref_8."smallint")) # original query from fuzzer statement ok SELECT ref_8.uint AS c0, CASE WHEN ((min_by(CAST(ref_8."varchar" AS VARCHAR), CAST(ref_3."varchar" AS VARCHAR)) OVER (PARTITION BY subq_3.c1, ref_10.double_array ORDER BY ref_7."varchar") ~~* ref_10."varchar")) THEN (argmin(CAST(ref_6."timestamp" AS TIMESTAMP), CAST(ref_10."timestamp" AS TIMESTAMP)) OVER (PARTITION BY ref_10.nested_int_array, ref_10."timestamp" ORDER BY ref_8.hugeint)) ELSE argmin(CAST(ref_6."timestamp" AS TIMESTAMP), CAST(ref_10."timestamp" AS TIMESTAMP)) OVER (PARTITION BY ref_10.nested_int_array, ref_10."timestamp" ORDER BY ref_8.hugeint) END AS c1 FROM main.all_types AS ref_0 INNER JOIN (SELECT ref_1.timestamp_array AS c1 FROM main.all_types AS ref_1 INNER JOIN main.all_types AS ref_2 ON (NULL) WHERE (((CAST(NULL AS VARCHAR) ~~~ CAST(NULL AS VARCHAR)) OR (ref_1.blob IS NOT NULL) OR 0) AND (ref_1.timestamp_ms IS NULL) AND ((SELECT histogram("varchar") FROM main.all_types) IS NOT NULL) AND ((ref_2.timestamp_s IS NULL) OR (((ref_2."varchar" ~~~ ref_1."varchar") OR 1 OR (ref_2."varchar" ~~ (SELECT "varchar" FROM main.all_types LIMIT 1 OFFSET 5))) AND (ref_2."varchar" ~~ ref_2."varchar")) OR ((SELECT "varchar" FROM main.all_types LIMIT 1 OFFSET 6) !~~* ref_1."varchar")))) AS subq_0 ON (ref_0."varchar") LEFT JOIN main.all_types AS ref_3 LEFT JOIN (SELECT ref_4.ubigint AS c0, 13 AS c1, ref_4."time" AS c2, ref_4."float" AS c3, (SELECT double_array FROM main.all_types LIMIT 1 OFFSET 6) AS c4 FROM main.all_types AS ref_4 WHERE NULL) AS subq_1 ON ((ref_3."float" = subq_1.c3)) ON (NULL) INNER JOIN (SELECT ref_5.timestamp_ms AS c4 FROM main.all_types AS ref_5) AS subq_2 LEFT JOIN main.all_types AS ref_6 INNER JOIN main.all_types AS ref_7 ON (((SELECT "varchar" FROM main.all_types LIMIT 1 OFFSET 1) ~~* ref_7."varchar")) INNER JOIN main.all_types AS ref_8 INNER JOIN main.all_types AS ref_9 INNER JOIN main.all_types AS ref_10 ON (((ref_9."varchar" !~~* ref_9."varchar") OR (ref_10.dec38_10 IS NOT NULL) OR EXISTS(SELECT ref_9."float" AS c0, ref_9.usmallint AS c1, ref_10."bigint" AS c2, (SELECT bool FROM main.all_types LIMIT 1 OFFSET 5) AS c3, ref_10.nested_int_array AS c4, ref_9.timestamp_ms AS c5, 4 AS c6, ref_11."map" AS c7, (SELECT uint FROM main.all_types LIMIT 1 OFFSET 3) AS c8, ref_9.dec_4_1 AS c9 FROM main.all_types AS ref_11 WHERE (1 AND EXISTS(SELECT ref_10.varchar_array AS c0 FROM main.all_types AS ref_12 WHERE 0 LIMIT 149) AND 1) LIMIT 180))) ON (EXISTS(SELECT ref_8.double_array AS c0, ref_10."timestamp" AS c1, ref_8.uuid AS c2, ref_13.dec_9_4 AS c3, ref_13."int" AS c4, ref_13.timestamp_ns AS c5, ref_8."float" AS c6, 63 AS c7 FROM main.all_types AS ref_13 WHERE (ref_13."varchar" ~~ ref_9."varchar"))) ON ((ref_7."smallint" = ref_8."smallint")) INNER JOIN (SELECT ref_14."interval" AS c1 FROM main.all_types AS ref_14 WHERE ref_14."varchar") AS subq_3 ON (EXISTS(SELECT ref_15.utinyint AS c0 FROM main.all_types AS ref_15 WHERE (ref_9."varchar" ~~* (SELECT "varchar" FROM main.all_types LIMIT 1 OFFSET 4)))) ON ((ref_9."varchar" !~~ ref_6."varchar")) ON ((ref_3.timestamp_array = ref_6.timestamp_array)) - # https://github.com/duckdb/duckdb-fuzzer/issues/1358 statement ok SELECT subq_0.c6 AS c1, subq_0.c14 AS c2, subq_0.c7 AS c4, subq_0.c4 AS c5 FROM (SELECT (SELECT date FROM main.all_types LIMIT 1 OFFSET 6) AS c3, ref_2."time" AS c4, (SELECT uuid FROM main.all_types LIMIT 1 OFFSET 1) AS c5, ref_3.array_of_structs AS c6, CASE WHEN (((ref_0."varchar" !~~* ref_1."varchar") OR (ref_5."varchar" ~~~ ref_6."varchar"))) THEN (ref_2."bigint") ELSE ref_2."bigint" END AS c7, rtrim(CAST(CASE WHEN ((((ref_8."varchar" ~~~ ref_2."varchar") AND (ref_2."varchar" ~~~ ref_0."varchar")) OR (1 AND (ref_7."varchar" ~~ ref_2."varchar")))) THEN (ref_8."varchar") ELSE ref_8."varchar" END AS VARCHAR), CAST(ref_2."varchar" AS VARCHAR)) AS c9, ref_8.ubigint AS c14 FROM main.all_types AS ref_0 INNER JOIN main.all_types AS ref_1 INNER JOIN main.all_types AS ref_2 ON ((ref_1.int_array = ref_2.int_array)) ON (((ref_2."varchar" !~~ ref_1."varchar") OR (ref_1.blob IS NOT NULL))) INNER JOIN main.all_types AS ref_3 INNER JOIN main.all_types AS ref_4 RIGHT JOIN main.all_types AS ref_5 ON ((ref_4.dec_18_6 = ref_5.dec_18_6)) ON (ref_5."varchar") LEFT JOIN main.all_types AS ref_6 RIGHT JOIN main.all_types AS ref_7 INNER JOIN main.all_types AS ref_8 ON ((ref_7.timestamp_array = ref_8.timestamp_array)) ON (1) ON (NULL) ON ((ref_0.dec_18_6 = ref_3.dec_18_6)) WHERE (ref_5."varchar" ^@ (SELECT "varchar" FROM main.all_types LIMIT 1 OFFSET 6)) LIMIT 96) AS subq_0 WHERE subq_0.c9 diff --git a/test/fuzzer/duckfuzz/duckfuzz_tests/test_duckfuzz.test b/test/fuzzer/duckfuzz/duckfuzz_tests/test_duckfuzz.test deleted file mode 100644 index 55073d30eb9..00000000000 --- a/test/fuzzer/duckfuzz/duckfuzz_tests/test_duckfuzz.test +++ /dev/null @@ -1,16 +0,0 @@ -# name: test/fuzzer/duckfuzz/duckfuzz_tests/test_duckfuzz.test -# description: Invalid make time -# group: [duckfuzz_tests] - -# To run these tests make remove require not_available -require not_available - -require sqlsmith - -loop i 1000 2000 - -statement ok -call fuzzyduck(max_queries=1, seed=${i}, verbose_output=1); - -endloop - diff --git a/test/fuzzer/duckfuzz/generate_null_timestamp.test b/test/fuzzer/duckfuzz/generate_null_timestamp.test index d3546fe5311..d2b7125dad4 100644 --- a/test/fuzzer/duckfuzz/generate_null_timestamp.test +++ b/test/fuzzer/duckfuzz/generate_null_timestamp.test @@ -5,8 +5,7 @@ statement ok PRAGMA enable_verification -statement error +query I SELECT NULL FROM generate_series(CAST('294247-01-10 04:00:54.775806' AS TIMESTAMP), NULL, NULL) AS t3(c1, c2) ---- -RANGE with NULL argument is not supported diff --git a/test/fuzzer/duckfuzz/repeat_wrong_number.test b/test/fuzzer/duckfuzz/repeat_wrong_number.test new file mode 100644 index 00000000000..1e24d1c50e7 --- /dev/null +++ b/test/fuzzer/duckfuzz/repeat_wrong_number.test @@ -0,0 +1,38 @@ +# name: test/fuzzer/duckfuzz/repeat_wrong_number.test +# description: Repeat row with NULL argument +# group: [duckfuzz] + +statement ok +PRAGMA enable_verification + +query I +FROM repeat(42, 1) +---- +42 + +query I +FROM repeat(42, 0) +---- + +statement error +FROM repeat(42, -1) +---- +Repeat second parameter cannot be be less than 0 + +# original issue https://github.com/duckdb/duckdb-fuzzer/issues/2688 +statement error +SELECT NULL FROM repeat('7fb6658b-4f42-44ce-bbd0-b22ba2faf7ad', -32768) +---- +Repeat second parameter cannot be be less than 0 + +# original issue https://github.com/duckdb/duckdb-fuzzer/issues/2685 +statement error +SELECT NULL FROM repeat(NULL, -9223372036854775808) +---- +Repeat second parameter cannot be be less than 0 + +# original issue https://github.com/duckdb/duckdb-fuzzer/issues/2686 +statement error +SELECT NULL FROM repeat(1050, -128) +---- +Repeat second parameter cannot be be less than 0 diff --git a/test/fuzzer/duckfuzz/try_cast_string_to_list.test_slow b/test/fuzzer/duckfuzz/try_cast_string_to_list.test_slow new file mode 100644 index 00000000000..25c50783805 --- /dev/null +++ b/test/fuzzer/duckfuzz/try_cast_string_to_list.test_slow @@ -0,0 +1,18 @@ +# name: test/fuzzer/duckfuzz/try_cast_string_to_list.test_slow +# description: Fuzzyduck issue #2696 +# group: [duckfuzz] + +require tpch + +statement ok +call dbgen(sf=0.1); + +query I +SELECT DISTINCT TRY_CAST(c_name AS TIMESTAMP[]) FROM customer USING SAMPLE 63.0% (Reservoir); +---- +NULL + +query I +SELECT DISTINCT TRY_CAST(c_name AS TIMESTAMP[3]) FROM customer USING SAMPLE 63.0% (Reservoir); +---- +NULL diff --git a/test/fuzzer/duckfuzz/tuple_data_empty_heap.test b/test/fuzzer/duckfuzz/tuple_data_empty_heap.test new file mode 100644 index 00000000000..477a3e0e716 --- /dev/null +++ b/test/fuzzer/duckfuzz/tuple_data_empty_heap.test @@ -0,0 +1,14 @@ +# name: test/fuzzer/duckfuzz/tuple_data_empty_heap.test +# description: Check if we handle empty heaps correctly (duckdb-fuzzer issue 2690) +# group: [duckfuzz] + +require tpch + +statement ok +set threads=4; + +statement ok +create table all_types as select * exclude(small_enum, medium_enum, large_enum) from test_all_types(); + +statement ok +SELECT DISTINCT c1, #1, c3, c1, c3, c1, c2 FROM tpch_answers() AS t4(c1, c2, c3) GROUP BY ALL; diff --git a/test/fuzzer/duckfuzz/vector_type.test b/test/fuzzer/duckfuzz/vector_type.test new file mode 100644 index 00000000000..da7f757fb92 --- /dev/null +++ b/test/fuzzer/duckfuzz/vector_type.test @@ -0,0 +1,34 @@ +# name: test/fuzzer/duckfuzz/vector_type.test +# description: Properly propogate empty results. +# group: [duckfuzz] + +require noforcestorage + +statement ok +pragma enable_verification + +query I +SELECT vector_type(42::INTEGER) +---- +CONSTANT_VECTOR + +query I +SELECT vector_type(NULL::INTEGER) +---- +CONSTANT_VECTOR + +statement ok +CREATE TABLE fuu (i INTEGER, j INTEGER); + +statement ok +INSERT INTO fuu VALUES (42, NULL), (43, NULL); + +statement ok +SELECT vector_type(i), vector_type(j) FROM fuu; + +# issue https://github.com/duckdb/duckdb-fuzzer/issues/2683 +statement ok +create table all_types as select * exclude(small_enum, medium_enum, large_enum) from test_all_types(); + +statement ok +SELECT vector_type(COLUMNS(*)) FROM all_types diff --git a/test/fuzzer/pedro/alter_dependency_conflict.test b/test/fuzzer/pedro/alter_dependency_conflict.test index 0373e36b35c..8323705c99e 100644 --- a/test/fuzzer/pedro/alter_dependency_conflict.test +++ b/test/fuzzer/pedro/alter_dependency_conflict.test @@ -10,14 +10,11 @@ CREATE TABLE t4 (c0 DATE, c3 VARCHAR(10)); statement ok CREATE INDEX i2 ON t4 (c3); -# Catalog Error: Cannot alter entry "t4" because there are entries that depend on it. -statement error +statement ok ALTER TABLE t4 ADD c1 BLOB; ----- -# the table should still be in a usable state after the alter statement ok -INSERT INTO t4 VALUES (NULL, NULL) +INSERT INTO t4 VALUES (NULL, NULL, NULL) statement ok START TRANSACTION; diff --git a/test/fuzzer/pedro/currval_sequence_dependency.test b/test/fuzzer/pedro/currval_sequence_dependency.test index a7126d70b9e..92cbe97f1a4 100644 --- a/test/fuzzer/pedro/currval_sequence_dependency.test +++ b/test/fuzzer/pedro/currval_sequence_dependency.test @@ -2,6 +2,9 @@ # description: Test sequence dependency in currval # group: [pedro] +# FIXME - during checkpoint recovery we no longer bind so we no longer have dependency information +require skip_reload + statement ok PRAGMA enable_verification @@ -16,7 +19,7 @@ CREATE TABLE t1(c1 INT, CHECK(${fun}('seq'))); statement error DROP SEQUENCE seq; ---- -there are entries that depend +table "t1" depends on index "seq". statement ok DROP SEQUENCE seq CASCADE; diff --git a/test/fuzzer/pedro/nested_subquery_table_function.test b/test/fuzzer/pedro/nested_subquery_table_function.test index 99f53f4b3e1..b20737af107 100644 --- a/test/fuzzer/pedro/nested_subquery_table_function.test +++ b/test/fuzzer/pedro/nested_subquery_table_function.test @@ -5,10 +5,18 @@ statement ok PRAGMA enable_verification -statement error +query I SELECT 1 FROM range((SELECT 1) - 0); ---- +1 -statement error +query I SELECT (SELECT 1 FROM range((SELECT 1) - 0)); ---- +1 + +query I +FROM range((SELECT 3) - 1) +---- +0 +1 diff --git a/test/fuzzer/pedro/vacuum_table_with_generated_column.test b/test/fuzzer/pedro/vacuum_table_with_generated_column.test index 189f6beae40..651c3fd22d9 100644 --- a/test/fuzzer/pedro/vacuum_table_with_generated_column.test +++ b/test/fuzzer/pedro/vacuum_table_with_generated_column.test @@ -1,8 +1,9 @@ # name: test/fuzzer/pedro/vacuum_table_with_generated_column.test +# description: Test the ANALYZE statement with generated columns. # group: [pedro] -# need this, else the distinct stats sampling is different -require vector_size 1024 +# The distinct statistics sampling relies on the vector size. +require vector_size 2048 require skip_reload @@ -12,10 +13,11 @@ require no_vector_verification statement ok CREATE TABLE test (x INT, y AS (x + 100)); -# Error: Vacuum the same column twice +# We cannot vacuum duplicate columns. statement error ANALYZE test(x, x); ---- +cannot vacuum or analyze the same column twice statement ok ANALYZE test(y, x); @@ -23,7 +25,7 @@ ANALYZE test(y, x); statement ok INSERT INTO test SELECT range % 5000 FROM range(10000); -# inaccurate approx unique due to sampling +# The approximate unique count is inaccurate due to sampling. query T SELECT stats(x) FROM test LIMIT 1; ---- @@ -34,23 +36,22 @@ SELECT stats(y) FROM test LIMIT 1; ---- [Min: 100, Max: 5099][Has Null: false, Has No Null: true] -# we enable verify_parallelism only for ANALYZE statement ok PRAGMA verify_parallelism; statement ok -ANALYZE test(x) +ANALYZE test(x); statement ok PRAGMA disable_verify_parallelism; -# x is more accurate now +# The approximate unique count is more accurate now. query T -SELECT stats(x) FROM test LIMIT 1 +SELECT stats(x) FROM test LIMIT 1; ---- [Min: 0, Max: 4999][Has Null: false, Has No Null: true][Approx Unique: 5080] query T -SELECT stats(y) FROM test LIMIT 1 +SELECT stats(y) FROM test LIMIT 1; ---- -[Min: 100, Max: 5099][Has Null: false, Has No Null: true] +[Min: 100, Max: 5099][Has Null: false, Has No Null: true] \ No newline at end of file diff --git a/test/fuzzer/pedro/view_not_rebound_error.test b/test/fuzzer/pedro/view_not_rebound_error.test index 5906b17648e..d2d3665e63a 100644 --- a/test/fuzzer/pedro/view_not_rebound_error.test +++ b/test/fuzzer/pedro/view_not_rebound_error.test @@ -1,14 +1,26 @@ # name: test/fuzzer/pedro/view_not_rebound_error.test # group: [pedro] +# FIXME: for this to work we need to serialize/deserialize dependencies +require skip_reload + +statement ok +set enable_view_dependencies=true + statement ok CREATE TABLE t1 (c1 INT); statement ok CREATE VIEW t0 AS SELECT 1 FROM t1 GROUP BY c1; -statement ok +statement error DROP TABLE t1; +---- +view "t0" depends on table "t1". + +# We need CASCADE to drop t1 because t0 depends on it +statement ok +DROP TABLE t1 CASCADE; statement ok CREATE TABLE t2 (c1 INT); @@ -16,7 +28,8 @@ CREATE TABLE t2 (c1 INT); statement ok CREATE TABLE t1 (c2 INT); +# t0 has been deleted, so this query fails statement error SELECT 1 FROM t2 JOIN t1 ON (SELECT TRUE FROM t0); ---- -Contents of view were altered +Catalog Error: Table with name t0 does not exist! diff --git a/test/fuzzer/pedro/view_not_rebound_error_no_view_dependencies.test b/test/fuzzer/pedro/view_not_rebound_error_no_view_dependencies.test new file mode 100644 index 00000000000..b2719a97e97 --- /dev/null +++ b/test/fuzzer/pedro/view_not_rebound_error_no_view_dependencies.test @@ -0,0 +1,24 @@ +# name: test/fuzzer/pedro/view_not_rebound_error_no_view_dependencies.test +# group: [pedro] + +# FIXME: for this to work we need to serialize/deserialize dependencies +require skip_reload + +statement ok +CREATE TABLE t1 (c1 INT); + +statement ok +CREATE VIEW t0 AS SELECT 1 FROM t1 GROUP BY c1; + +statement ok +DROP TABLE t1; + +statement ok +CREATE TABLE t2 (c1 INT); + +statement ok +CREATE TABLE t1 (c2 INT); + +statement error +SELECT 1 FROM t2 JOIN t1 ON (SELECT TRUE FROM t0); +---- diff --git a/test/fuzzer/sqlsmith/timestamptz_null_range.test b/test/fuzzer/sqlsmith/timestamptz_null_range.test index 1d44b7c1ab5..2425c3e89a9 100644 --- a/test/fuzzer/sqlsmith/timestamptz_null_range.test +++ b/test/fuzzer/sqlsmith/timestamptz_null_range.test @@ -6,7 +6,10 @@ require icu require no_extension_autoloading -statement error +statement ok +PRAGMA enable_verification + +query I SELECT NULL FROM ( SELECT 4767 FROM generate_series(CAST('290309-12-22 (BC) 00:00:00+00' AS TIMESTAMP WITH TIME ZONE), NULL, NULL) @@ -14,4 +17,3 @@ SELECT NULL FROM ( ) AS t64 ---- -RANGE with NULL bounds is not supported diff --git a/test/helpers/test_helpers.cpp b/test/helpers/test_helpers.cpp index c0639a82196..4028800c292 100644 --- a/test/helpers/test_helpers.cpp +++ b/test/helpers/test_helpers.cpp @@ -147,6 +147,7 @@ unique_ptr GetTestConfig() { #else result->options.checkpoint_on_shutdown = false; #endif + result->options.abort_on_wal_failure = true; #ifdef DUCKDB_RUN_SLOW_VERIFIERS // This mode isn't slow, but we want test coverage both when it's enabled // and when it's not, so we enable only when DUCKDB_RUN_SLOW_VERIFIERS is set. diff --git a/test/issues/general/test_11391.test b/test/issues/general/test_11391.test index 637c901a6de..0a228b11228 100644 --- a/test/issues/general/test_11391.test +++ b/test/issues/general/test_11391.test @@ -1,5 +1,5 @@ # name: test/issues/general/test_11391.test -# description: Issue 1091: Catalog Error with nested CTEs +# description: Issue 11391: Catalog Error with nested CTEs # group: [general] query I diff --git a/test/issues/general/test_11566.test b/test/issues/general/test_11566.test new file mode 100644 index 00000000000..8dd5a792b8c --- /dev/null +++ b/test/issues/general/test_11566.test @@ -0,0 +1,18 @@ +# name: test/issues/general/test_11566.test +# description: Issue 11566: Assertion failure when using DISTINCT ON + ORDER BY with JSON column +# group: [general] + +require json + +statement ok +PRAGMA enable_verification + +query I +SELECT typeof(arg_min({foo: 'bar'}::JSON, 1)); +---- +JSON + +query II +SELECT DISTINCT ON (my_row_id) my_row_id, value FROM (SELECT * FROM (VALUES ('1', {foo: 'bar'}::JSON, 1), ('1', {foo: 'baz'}::JSON, 2), ) AS t(my_row_id, value, idx)) ORDER BY idx; +---- +1 {"foo":"bar"} diff --git a/test/issues/general/test_5614.test b/test/issues/general/test_5614.test index e03778fed51..7eb5ff6e5f4 100644 --- a/test/issues/general/test_5614.test +++ b/test/issues/general/test_5614.test @@ -2,6 +2,9 @@ # description: Issue 5614: # group: [general] +statement ok +pragma enable_verification + statement ok create table t0 as select (UNNEST(['hello', 'duckdb', 'duck LORD', 'lord duck'])) as column0; diff --git a/test/issues/general/test_9399.test b/test/issues/general/test_9399.test_slow similarity index 93% rename from test/issues/general/test_9399.test rename to test/issues/general/test_9399.test_slow index b1fb7f95f0d..86dac620f80 100644 --- a/test/issues/general/test_9399.test +++ b/test/issues/general/test_9399.test_slow @@ -1,4 +1,4 @@ -# name: test/issues/general/test_9399.test +# name: test/issues/general/test_9399.test_slow # description: Issue 9399: Incorrect query output from group by query (regression in 0.9.0) # group: [general] diff --git a/test/optimizer/column_lifetime_analyzer/must_visit_operator_expressions_first.test b/test/optimizer/column_lifetime_analyzer/must_visit_operator_expressions_first.test new file mode 100644 index 00000000000..5965e3b7af4 --- /dev/null +++ b/test/optimizer/column_lifetime_analyzer/must_visit_operator_expressions_first.test @@ -0,0 +1,19 @@ +# name: test/optimizer/column_lifetime_analyzer/must_visit_operator_expressions_first.test +# description: Test column lifetime analyzer +# group: [column_lifetime_analyzer] + +statement ok +create table t5 as select (range + 1000) a5, range b5, (range + 50)::INT::VARCHAR || '__suffix__' c5 from range(50); + +statement ok +create table t1 as select range::INT a1, (range + 45)::INT b1, (range)::INT::VARCHAR || '__suffix__' c1 from range(900); + + +query II +select a5, c1 from t1, t5 where b5=b1; +---- +1045 0__suffix__ +1046 1__suffix__ +1047 2__suffix__ +1048 3__suffix__ +1049 4__suffix__ diff --git a/test/optimizer/deliminator.test b/test/optimizer/deliminator.test index cf450051949..de5233c94b8 100644 --- a/test/optimizer/deliminator.test +++ b/test/optimizer/deliminator.test @@ -31,6 +31,7 @@ explain SELECT sum(l_extendedprice) / 7.0 AS avg_yearly FROM lineitem, part WHER ---- logical_opt :.*DELIM_JOIN.* + # Q 20: join with JoinType::SINGLE (created when pushing down dependent joins) is converted to LEFT query II explain SELECT s_name, s_address FROM supplier, nation WHERE s_suppkey IN ( SELECT ps_suppkey FROM partsupp WHERE ps_partkey IN ( SELECT p_partkey FROM part WHERE p_name LIKE 'forest%') AND ps_availqty > ( SELECT 0.5 * sum(l_quantity) FROM lineitem WHERE l_partkey = ps_partkey AND l_suppkey = ps_suppkey AND l_shipdate >= CAST('1994-01-01' AS date) AND l_shipdate < CAST('1995-01-01' AS date))) AND s_nationkey = n_nationkey AND n_name = 'CANADA' ORDER BY s_name; diff --git a/test/optimizer/issue_12181.test b/test/optimizer/issue_12181.test new file mode 100644 index 00000000000..873b90cde7e --- /dev/null +++ b/test/optimizer/issue_12181.test @@ -0,0 +1,22 @@ +# name: test/optimizer/issue_12181.test +# description: Test move constants optimization involving DISTINCT FROM comparison +# group: [optimizer] + +statement ok +CREATE TABLE t0(c0 INT) + +statement ok +CREATE TABLE t1(c0 INT, c1 INT) + +statement ok +INSERT INTO t1(c0, c1) VALUES (0, 1) + +query I +SELECT NULL IS DISTINCT FROM (1 + t1.c1) FROM t1 NATURAL LEFT JOIN t0 +---- +true + +query II +SELECT * FROM t0 NATURAL RIGHT JOIN t1 WHERE (CASE t0.c0 WHEN t0.c0 THEN 1 ELSE NULL END) IS DISTINCT FROM (1 + (CASE t1.c1 WHEN t1.c1 THEN 2 ELSE NULL END)) +---- +0 1 diff --git a/test/optimizer/join_dependent_filter.test b/test/optimizer/join_dependent_filter.test new file mode 100644 index 00000000000..6712efabe39 --- /dev/null +++ b/test/optimizer/join_dependent_filter.test @@ -0,0 +1,254 @@ +# name: test/optimizer/join_dependent_filter.test +# description: Join dependent filter rule test +# group: [optimizer] + +statement ok +create table test as select range i, range j from range(10) + +# can derive two filters for this query +query I +select count(*) +from test t1, test t2 +where (t1.i = 2 and t2.i = 4) or (t1.i = 0 and t2.i = 2) +---- +2 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = 2 and t2.i = 4) or (t1.i = 0 and t2.i = 2) +---- +physical_plan :.*FILTER.*FILTER.* + +# not if the constants are volatile however +query II +explain select count(*) +from test t1, test t2 +where (t1.i = random() and t2.i = random()) or (t1.i = 0 and t2.i = 2) +---- +physical_plan :.*FILTER.* + +# which wouldn't be there without the expression rewriter +statement ok +set disabled_optimizers to 'expression_rewriter' + +query I +select count(*) +from test t1, test t2 +where (t1.i = 2 and t2.i = 4) or (t1.i = 0 and t2.i = 2) +---- +2 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = 2 and t2.i = 4) or (t1.i = 0 and t2.i = 2) +---- +physical_plan :.*FILTER.* + +statement ok +set disabled_optimizers to '' + +# in this case we can only derive one filter +query I +select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i > 7) or (t1.i != t2.i and t1.i < 3) +---- +29 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i > 7) or (t1.i != t2.i and t1.i < 3) +---- +physical_plan :.*FILTER.* + +# a predicate for a column must show up on both sides, +# so, adding a predicate for t2.i to only one side won't create a filter +query I +select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i > 7 and t2.i = 0) or (t1.i != t2.i and t1.i < 3) +---- +27 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i > 7 and t2.i = 0) or (t1.i != t2.i and t1.i < 3) +---- +physical_plan :.*FILTER.*FILTER.* + +# if we add another predicate to the other side, we get another filter +query I +select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i > 7 and t2.i = 0) or (t1.i != t2.i and t1.i < 3 and t2.i = 5) +---- +3 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i > 7 and t2.i = 0) or (t1.i != t2.i and t1.i < 3 and t2.i = 5) +---- +physical_plan :.*FILTER.*FILTER.* + +# one side filters t1, and the other side filter t2, so we can't derive a filter +query I +select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i > 7) or (t1.i != t2.i and t2.i = 5) +---- +11 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i > 7) or (t1.i != t2.i and t2.i = 5) +---- +physical_plan :.*FILTER.* + +# we can still derive filters if there's 3 entries in the OR +query I +select count(*) +from test t1, test t2 +where (t1.i = 0 and t2.i = 1) or (t1.i = 2 and t2.i = 3) or (t1.i = 3 and t2.i = 4) +---- +3 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = 0 and t2.i = 1) or (t1.i = 2 and t2.i = 3) or (t1.i = 3 and t2.i = 4) +---- +physical_plan :.*FILTER.*FILTER.* + +# not everything in the OR needs to be an AND +# we can still derive one filter (on t2.i) +query I +select count(*) +from test t1, test t2 +where (t1.i = 0 and t2.i = 1) or (t1.i = 2 and t2.i = 3) or (t1.i = 3 and t2.i = 4) or (t2.i = 8) +---- +13 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = 0 and t2.i = 1) or (t1.i = 2 and t2.i = 3) or (t1.i = 3 and t2.i = 4) or (t2.i = 8) +---- +physical_plan :.*FILTER.* + +# also works if we have a restriction i on and j, just needs to be the same table +query I +select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i = 7) or (t1.j = 3) +---- +11 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i = 7) or (t1.j = 3) +---- +physical_plan :.*FILTER.* + +# we can also do more complex expressions, like modulo +query I +select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i % 5 = 0) or (t1.j % 6 = 0) +---- +21 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i % 5 = 0) or (t1.j % 6 = 0) +---- +physical_plan :.*FILTER.* + +# or something like IN +query I +select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i IN (1, 2)) or (t1.j IN (3, 4)) +---- +22 + +query II +explain select count(*) +from test t1, test t2 +where (t1.i = t2.i and t1.i IN (1, 2)) or (t1.j IN (3, 4)) +---- +physical_plan :.*FILTER.* + +require tpch + +statement ok +CALL dbgen(sf=0.01) + +# there should be 3 filter operators instead of just one, because we derived two +query II +EXPLAIN SELECT + supp_nation, + cust_nation, + l_year, + sum(volume) AS revenue +FROM ( + SELECT + n1.n_name AS supp_nation, + n2.n_name AS cust_nation, + extract(year FROM l_shipdate) AS l_year, + l_extendedprice * (1 - l_discount) AS volume + FROM + supplier, + lineitem, + orders, + customer, + nation n1, + nation n2 + WHERE + s_suppkey = l_suppkey + AND o_orderkey = l_orderkey + AND c_custkey = o_custkey + AND s_nationkey = n1.n_nationkey + AND c_nationkey = n2.n_nationkey + AND ((n1.n_name = 'FRANCE' + AND n2.n_name = 'GERMANY') + OR (n1.n_name = 'GERMANY' + AND n2.n_name = 'FRANCE')) + AND l_shipdate BETWEEN CAST('1995-01-01' AS date) + AND CAST('1996-12-31' AS date)) AS shipping +GROUP BY + supp_nation, + cust_nation, + l_year +ORDER BY + supp_nation, + cust_nation, + l_year; +---- +physical_plan :.*FILTER.*FILTER.*FILTER.* + +# results should still be the same +query IIII +PRAGMA tpch(7) +---- +:extension/tpch/dbgen/answers/sf0.01/q07.csv + +# if we put the join-dependent filter explicitly as a join condition, we get a blockwise NL join, +# but we should still derive the same two filters +query II +EXPLAIN SELECT * +FROM nation n1 +JOIN nation n2 +ON ((n1.n_name = 'FRANCE' + AND n2.n_name = 'GERMANY') + OR (n1.n_name = 'GERMANY' + AND n2.n_name = 'FRANCE')) +---- +physical_plan :.*FILTER.*FILTER.* diff --git a/test/optimizer/joins/many_joins_and_one_non_reorderable_join.test b/test/optimizer/joins/many_joins_and_one_non_reorderable_join.test_slow similarity index 97% rename from test/optimizer/joins/many_joins_and_one_non_reorderable_join.test rename to test/optimizer/joins/many_joins_and_one_non_reorderable_join.test_slow index b24afe35fa1..1610e4f31d7 100644 --- a/test/optimizer/joins/many_joins_and_one_non_reorderable_join.test +++ b/test/optimizer/joins/many_joins_and_one_non_reorderable_join.test_slow @@ -1,4 +1,4 @@ -# name: test/optimizer/joins/many_joins_and_one_non_reorderable_join.test +# name: test/optimizer/joins/many_joins_and_one_non_reorderable_join.test_slow # description: In the join order optimizer queries need to have the correct bindings # group: [joins] diff --git a/test/optimizer/joins/pushdown_semi_anti.test b/test/optimizer/joins/pushdown_semi_anti.test new file mode 100644 index 00000000000..6decef39690 --- /dev/null +++ b/test/optimizer/joins/pushdown_semi_anti.test @@ -0,0 +1,29 @@ +# name: test/optimizer/joins/pushdown_semi_anti.test +# description: Verify semi anti joins are pushed down +# group: [joins] + +statement ok +create table tbl1 as select range a from range(10000); + +statement ok +create table tbl2 as select range b from range(1000); + +statement ok +create table tbl3 as select range c from range(100); + +statement ok +set disabled_optimizers='statistics_propagation'; + +query II +EXPLAIN select * from tbl1, tbl2 where b in (select * from tbl3) and tbl1.a = tbl2.b; +---- +physical_plan :.*INNER.*SEMI.* + +statement ok +set disabled_optimizers='statistics_propagation,join_order'; + +# make sure non-optimized plan has semi on top of the inner +query II +EXPLAIN select * from tbl1, tbl2 where b in (select * from tbl3) and tbl1.a = tbl2.b; +---- +physical_plan :.*SEMI.*INNER.* diff --git a/test/optimizer/joins/update_nodes_in_full_path.test b/test/optimizer/joins/update_nodes_in_full_path.test_slow similarity index 95% rename from test/optimizer/joins/update_nodes_in_full_path.test rename to test/optimizer/joins/update_nodes_in_full_path.test_slow index 83b3db332dd..6de28fa35f9 100644 --- a/test/optimizer/joins/update_nodes_in_full_path.test +++ b/test/optimizer/joins/update_nodes_in_full_path.test_slow @@ -1,11 +1,11 @@ -# name: test/optimizer/joins/update_nodes_in_full_path.test +# name: test/optimizer/joins/update_nodes_in_full_path.test_slow # description: updating nodes in full path should throw no errors # group: [joins] require tpch statement ok -call dbgen(sf=0.1); +call dbgen(sf=0.01); statement ok SELECT NULL diff --git a/test/optimizer/joins/updating_the_join_node_hash_map_has_no_errors.test b/test/optimizer/joins/updating_the_join_node_hash_map_has_no_errors.test_slow similarity index 98% rename from test/optimizer/joins/updating_the_join_node_hash_map_has_no_errors.test rename to test/optimizer/joins/updating_the_join_node_hash_map_has_no_errors.test_slow index 94b768fce27..b793da62480 100644 --- a/test/optimizer/joins/updating_the_join_node_hash_map_has_no_errors.test +++ b/test/optimizer/joins/updating_the_join_node_hash_map_has_no_errors.test_slow @@ -1,10 +1,9 @@ -# name: test/optimizer/joins/updating_the_join_node_hash_map_has_no_errors.test +# name: test/optimizer/joins/updating_the_join_node_hash_map_has_no_errors.test_slow # description: # group: [joins] require tpch - statement ok call dbgen(sf=0.05); diff --git a/test/optimizer/limit_pushdown.test b/test/optimizer/limit_pushdown.test new file mode 100644 index 00000000000..48a52d514f8 --- /dev/null +++ b/test/optimizer/limit_pushdown.test @@ -0,0 +1,65 @@ +# name: test/optimizer/limit_pushdown.test +# description: Test Limit Pushdown optimization +# group: [optimizer] + +statement ok +CREATE TABLE integers(i INTEGER, j INTEGER) + +statement ok +PRAGMA explain_output = OPTIMIZED_ONLY; + +statement ok +INSERT INTO integers VALUES (1,1), (2,2), (3, 3), (4,4) + +# project + limit becomes limit + project +query II +EXPLAIN SELECT i FROM integers LIMIT 4 +---- +logical_opt :.*PROJECTION.*LIMIT.* + +# verify result for project + limit to limit + project +query I +SELECT i FROM integers LIMIT 4 +---- +1 +2 +3 +4 + +# recursive limit pushdown +query II +EXPLAIN SELECT i FROM (SELECT i, i+1 FROM integers) LIMIT 4 +---- +logical_opt :.*PROJECTION.*PROJECTION.*LIMIT.* + +# verify result for recursive limit pushdown and offset +query I +SELECT i FROM (SELECT i, i+1 FROM integers) LIMIT 4 OFFSET 2 +---- +3 +4 + +# only offset: no pushdown +query II +EXPLAIN SELECT i FROM integers OFFSET 4 +---- +logical_opt :.*LIMIT.*PROJECTION.* + +# limit and offset +query II +EXPLAIN SELECT i FROM integers LIMIT 4 OFFSET 2 +---- +logical_opt :.*PROJECTION.*LIMIT.* + +# verify result for limit and offset +query I +SELECT i FROM integers LIMIT 4 OFFSET 2 +---- +3 +4 + +# limit value > 8192: no pushdown +query II +EXPLAIN SELECT i FROM integers LIMIT 8192 +---- +logical_opt :.*LIMIT.*PROJECTION.* diff --git a/test/optimizer/perfect_ht.test b/test/optimizer/perfect_ht.test index daf408e8275..9ce52eb56eb 100644 --- a/test/optimizer/perfect_ht.test +++ b/test/optimizer/perfect_ht.test @@ -51,7 +51,9 @@ physical_plan :.*PERFECT_HASH_GROUP_BY.* statement error PRAGMA perfect_ht_threshold=-1; ---- +:Parser Error:.*out of range.* statement error PRAGMA perfect_ht_threshold=100; ---- +:Parser Error:.*out of range.* \ No newline at end of file diff --git a/test/optimizer/prefer_final_projected_columns_on_probe_side.test b/test/optimizer/prefer_final_projected_columns_on_probe_side.test new file mode 100644 index 00000000000..5caa12ef4eb --- /dev/null +++ b/test/optimizer/prefer_final_projected_columns_on_probe_side.test @@ -0,0 +1,34 @@ +# name: test/optimizer/prefer_final_projected_columns_on_probe_side.test +# description: Test Limit Pushdown optimization +# group: [optimizer] + +statement ok +create table t(ts_start timestamptz, ts_stop timestamptz, id text); + +statement ok +with dates as ( + select '2023-01-01'::timestamp + i * interval '1 DAY' as x + from generate_series(0, 999) as t(i) +), +ids as ( + select 'id_' || lpad(i::text, 4, '0') as y + from generate_series(0, 999) as t(i) +) +insert into t(ts_start, ts_stop, id) + select d.x, null, i.y from dates d, ids i; + + +# this is hard to test but basically you need to make sure that the left child of the hash +# join is a projection, and the right is a sequential scan. +# the child of the projection is then the window and sequential scan +query II +explain update t as this +set ts_stop = next.ts_start_next +from ( +select id, ts_start, LEAD(ts_start) over (partition by id order by ts_start) + as ts_start_next +from t +) as next +where this.id=next.id and this.ts_start=next.ts_start; +---- +physical_plan :.*HASH_JOIN.*SEQ_SCAN.*PROJECTION.*WINDOW.*SEQ_SCAN.* diff --git a/test/optimizer/pushdown/pushdown_in_to_parquet.test b/test/optimizer/pushdown/pushdown_in_to_parquet.test new file mode 100644 index 00000000000..12353715009 --- /dev/null +++ b/test/optimizer/pushdown/pushdown_in_to_parquet.test @@ -0,0 +1,25 @@ +# name: test/optimizer/pushdown/pushdown_in_to_parquet.test +# description: Parquet filter of IN with 1 argument can be converted to = +# group: [pushdown] + +require parquet + +statement ok +PRAGMA enable_verification + +statement ok +create table t1 as select range::VARCHAR a from range(1000); + +statement ok +copy t1 to '__TEST_DIR__/t1.parquet' (FORMAT PARQUET); + +query II +explain select * from '__TEST_DIR__/t1.parquet' where a in ('400'); +---- +physical_plan :.*FILTER.*PARQUET_SCAN.* + +query II +explain select * from '__TEST_DIR__/t1.parquet' where a in ('400'); +---- +physical_plan :.*PARQUET_SCAN.*Filters:.* + diff --git a/test/optimizer/pushdown/pushdown_window_partition_filter.test b/test/optimizer/pushdown/pushdown_window_partition_filter.test new file mode 100644 index 00000000000..24e7ec60c87 --- /dev/null +++ b/test/optimizer/pushdown/pushdown_window_partition_filter.test @@ -0,0 +1,153 @@ +# name: test/optimizer/pushdown/pushdown_window_partition_filter.test +# description: Test pushdown of filters through window operators that are partitioned by. +# group: [pushdown] + +statement ok +pragma enable_verification; + +statement ok +create table t1 as from VALUES + ('A', 1), + ('B', 3), + ('C', 12), + ('A', 5), + ('B', 8), + ('C', 9), + ('A', 10), + ('B', 20), + ('C', 3) + t(a, b); + +statement ok +pragma explain_output=OPTIMIZED_ONLY + +statement ok +create view window_with_filter as select a, b, LEAD(b) OVER (partition by a) as lead from t1 where a != 'C'; + +statement ok +create view window_no_filter as select a, b, LEAD(b) OVER (partition by a) as lead from t1; + +query III no_sort result_1 +select * from window_with_filter where a != 'C' order by a; +---- + +query III no_sort result_1 +select * from window_no_filter where a != 'C' order by a; +---- + +statement ok +create table partition_and_rank_me as from values + ('A', 10, 'A', 'id'), + ('A', 20, 'A', 'id'), + ('A', 30, 'B', 'id'), + ('D', 40, 'B', 'id'), + ('D', 50, 'C', 'id'), + ('D', 60, 'C', 'id') +t(a, b, c, d); + +query IIII +select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY d ORDER BY b) +from partition_and_rank_me order by all +---- +A A 30 1 +A A 30 2 +A B 70 3 +D B 70 4 +D C 110 5 +D C 110 6 + +# can't push down the filter c!='B', since the values of the rank() window function +# are affected by the existence of the rows where c='B' +query IIII +select * from ( + select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY d ORDER BY b) + from partition_and_rank_me +) where c != 'B' order by all; +---- +A A 30 1 +A A 30 2 +D C 110 5 +D C 110 6 + +# One filter clause is on the partitioned column but the filter clause is an AND conjunction, so we don't push that down. +query IIII +select * from ( + select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY c ORDER BY b) + from partition_and_rank_me +) where (c = 'B' AND a = 'D') order by all; +---- +D B 70 2 + +# result of above query with pushdown +query IIII +select * from ( + select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY c ORDER BY b) + from partition_and_rank_me where (c = 'B' AND a = 'D') +) order by all; +---- +D B 40 1 + + +# The filter is on the partitioned column, but is part of an OR conjunction, so we can push it down +query IIII +select * from ( + select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY c ORDER BY b) + from partition_and_rank_me +) where (c = 'B' OR a = 'D') order by all; +---- +A B 70 1 +D B 70 2 +D C 110 1 +D C 110 2 + +# result of above query with pushdown +query IIII +select * from ( + select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY c ORDER BY b) + from partition_and_rank_me + where (c = 'B' OR a = 'D') +) order by all; +---- +A B 70 1 +D B 70 2 +D C 110 1 +D C 110 2 + +# The filter is a function expression, so we don't push it down +query IIII +select * from ( + select a, c, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY c ORDER BY b) + from partition_and_rank_me +) where (c || 'Z' = 'BZ') order by all; +---- +A B 70 1 +D B 70 2 + + +# can't push down the filter c!='B', since the values of the rank() window function +# are affected by the existence of the rows where c='B' +query II +explain select * from (select a, sum(b) OVER (PARTITION BY c), rank() OVER (PARTITION BY d ORDER BY b), c from partition_and_rank_me) where c != 'B' order by all; +---- +logical_opt :.*FILTER.*WINDOW.* + +query II +explain select * from window_no_filter where a != 'C' order by a; +---- +logical_opt :.*WINDOW.*FILTER.* + +statement ok +create table t2 as select range a, range%50 b, range%25 c from range(500); + +# second window expression is not paritioned on b, so filter expression cannot be +# pushed down +query II +explain select * from (select a, b, c, sum(a) OVER (PARTITION BY b, c), sum(b) OVER (PARTITION BY a, c) from t2) where b > 25; +---- +logical_opt :.*FILTER.*WINDOW.* + +query II +explain select * from (select a, b, c, sum(a) OVER (PARTITION BY b, c), sum(b) OVER (PARTITION BY a, c) from t2) where c = 20; +---- +logical_opt :.*WINDOW.*c=20.* + diff --git a/test/optimizer/pushdown/timestamp_to_date_pushdown.test b/test/optimizer/pushdown/timestamp_to_date_pushdown.test new file mode 100644 index 00000000000..12e33db10f6 --- /dev/null +++ b/test/optimizer/pushdown/timestamp_to_date_pushdown.test @@ -0,0 +1,79 @@ +# name: test/optimizer/pushdown/timestamp_to_date_pushdown.test +# description: Test Tpushdown of timestamp to date filters +# group: [pushdown] + +require icu + +foreach timezone UTC ECT + +statement ok +set TimeZone='${timezone}'; + +statement ok +create or replace table t1 (ts timestamp, i int); + +statement ok +insert into t1 select '2024-05-01 00:00:00'::timestamp, i from generate_series(1, 2000) g(i); + +statement ok +insert into t1 select '2024-05-02 00:00:00'::timestamp, i from generate_series(1, 1000) g(i); + +statement ok +insert into t1 select '2024-05-02 00:22:00'::timestamp, i from generate_series(1, 1000) g(i); + +statement ok +insert into t1 select '2024-05-03 00:00:00'::timestamp, i from generate_series(1, 2000) g(i); + +query II +explain select * from t1 where ts::date == '2024-05-02'; +---- +physical_plan :.*SEQ_SCAN.*Filters:.* + +query II +explain select * from t1 where '2024-05-02' == ts::date; +---- +physical_plan :.*SEQ_SCAN.*Filters:.* + + +statement ok +pragma disable_optimizer; + +query II nosort no_opt_result +select * from t1 where ts::date == '2024-05-02'; +---- + +statement ok +pragma enable_optimizer; + +query II nosort no_opt_result +select * from t1 where ts::date == '2024-05-02'; +---- + +# pattern is still recognized in conjunction +query II +explain select count(*) from t1 where ts::date == '2024-05-02' and i > 122880/2; +---- +physical_plan :.*FILTER.*SEQ_SCAN:.* + + +query I +select count(*) from t1 where ts::date == '2024-05-02' and i > 1000; +---- +0 + +query I +select count(*) from t1 where ts::date == '2024-05-02' and i <= 500; +---- +1000 + +endloop + +query I +select count(*) from t1 where ts::date == '2024-05-01' and i <= 500; +---- +500 + +query I +select count(*) from t1 where ts::date == '2024-05-03'; +---- +2000 diff --git a/test/optimizer/statistics/statistics_case.test b/test/optimizer/statistics/statistics_case.test index c3fe5c59a23..0aaa0367dba 100644 --- a/test/optimizer/statistics/statistics_case.test +++ b/test/optimizer/statistics/statistics_case.test @@ -28,6 +28,7 @@ logical_opt :.*EMPTY_RESULT.* statement error SELECT 123::TINYINT + (CASE WHEN i=2 THEN (i+1)::TINYINT ELSE (i+2)::TINYINT END) FROM integers; ---- +:Out of Range Error:.*Overflow in addition.* # this does not query I diff --git a/test/optimizer/topn/complex_top_n.test b/test/optimizer/topn/complex_top_n.test index 8cc82573629..6e81978f7c5 100644 --- a/test/optimizer/topn/complex_top_n.test +++ b/test/optimizer/topn/complex_top_n.test @@ -4,6 +4,8 @@ require skip_reload +require vector_size 1024 + statement ok SELECT SETSEED(0.42); @@ -28,7 +30,7 @@ WITH CTE AS ( WHERE (ORDERVIEW.ORDER_ISEXPEDITEDSHIPPED IS TRUE) GROUP BY ORDERVIEW.ORDER_CUSTOMERID ) AS J1J ON (J1J.ORDER_CUSTOMERID = CUSTOMERVIEW.CUSTOMER_ID) - ORDER BY CUSTOMER_PRIORITY ASC + ORDER BY CUSTOMER_PRIORITY ASC, CUSTOMER_ID ASC LIMIT 50 OFFSET 50 ) SELECT J1P, Q2P, Q3P FROM CTE LEFT JOIN ( @@ -40,9 +42,9 @@ LEFT JOIN ( LEFT JOIN ( SELECT ORDER_CUSTOMERID Q3P FROM ORDERVIEW LEFT JOIN ORDERITEMVIEW ON ORDERVIEW.ORDER_ID = ORDERITEM_ORDERID -) AS Q3J ON (Q3J.Q3P = CTE.CUSTOMER_ID); +) AS Q3J ON (Q3J.Q3P = CTE.CUSTOMER_ID) order by all; ---- -423 values hashing to 88bbd750b435b7616e6596774a8d5689 +285 values hashing to 9b1c4d195c0e3c4de5b190b1ab7b357b query II explain WITH CTE AS ( diff --git a/test/optimizer/topn/topn_optimizer.test b/test/optimizer/topn/topn_optimizer.test index 96e0c9ec1c6..6d9f41253ac 100644 --- a/test/optimizer/topn/topn_optimizer.test +++ b/test/optimizer/topn/topn_optimizer.test @@ -37,3 +37,23 @@ query II EXPLAIN SELECT i FROM integers ORDER BY i OFFSET 3 ---- logical_opt :.*TOP_N.* + +# only limit, but in subquery with projection pull up optimization +query II +EXPLAIN SELECT * FROM (SELECT * FROM range(100000000) AS _(x) ORDER BY x) AS cte LIMIT 10 +---- +logical_opt :.*TOP_N.* + +# top n optimization with more complex projection pull up +query II +EXPLAIN +WITH cte1 AS (SELECT range%2000 a, + (range%2000 + 2000) b, + (range%2000 + 4000) c, + (range%2000 + 6000) d + FROM range(10000) ORDER BY range), + cte2 as (select *, a as x, b as y, c as z from cte1), + cte3 as (select *, a as l, b as m, c as n, d as o from cte2) +SELECT * FROM cte3 LIMIT 4; +---- +logical_opt :.*TOP_N.* diff --git a/test/optimizer/unnest_rewriter.test b/test/optimizer/unnest_rewriter.test_slow similarity index 99% rename from test/optimizer/unnest_rewriter.test rename to test/optimizer/unnest_rewriter.test_slow index c8cf268cc72..01e8894e9a4 100644 --- a/test/optimizer/unnest_rewriter.test +++ b/test/optimizer/unnest_rewriter.test_slow @@ -1,4 +1,4 @@ -# name: test/optimizer/unnest_rewriter.test +# name: test/optimizer/unnest_rewriter.test_slow # description: Test the UnnestRewriter optimizer # group: [optimizer] diff --git a/test/optimizer/unused_columns/distinct_on_projection_pushdown.test b/test/optimizer/unused_columns/distinct_on_projection_pushdown.test new file mode 100644 index 00000000000..adffe6ba4c0 --- /dev/null +++ b/test/optimizer/unused_columns/distinct_on_projection_pushdown.test @@ -0,0 +1,50 @@ +# name: test/optimizer/unused_columns/distinct_on_projection_pushdown.test +# description: Test DISTINCT ON ORDER BY +# group: [unused_columns] + +statement ok +PRAGMA enable_verification + +statement ok +create table t0 as select range%1000 col0, random()*1000 col1, random()*100 col2, '1' col3, '2' col4, '3' col5 from range(10000); + +query I nosort res_1 +SELECT col0 +FROM +( + SELECT + DISTINCT ON (floor(col0)) + * + FROM t0 + ORDER by col0 DESC +); +---- +1000 values hashing to 796a92aea33b9601284e2a4ac9e6587e + +query I nosort res_1 +SELECT col0 +FROM +( + SELECT + DISTINCT ON (floor(col0)) + col0 + FROM t0 + ORDER by col0 DESC +); +---- + +statement ok +PRAGMA explain_output = OPTIMIZED_ONLY; + +query II +EXPLAIN SELECT col0 +FROM +( + SELECT + DISTINCT ON (floor(col0)) + * + FROM t0 + ORDER by col0 DESC +) +---- +logical_opt :.*col[1-5].* diff --git a/test/parquet/test_filename_column.test b/test/parquet/test_filename_column.test new file mode 100644 index 00000000000..593f46c1345 --- /dev/null +++ b/test/parquet/test_filename_column.test @@ -0,0 +1,58 @@ +# name: test/parquet/test_filename_column.test +# description: Test MultiFileReader filename column rename +# group: [parquet] + +require parquet + +statement ok +PRAGMA enable_verification + +# anything non-VARCHAR will be cast to boolean, and interpreted as such +query I +SELECT pq.filename FROM read_parquet('data/parquet-testing/enum.parquet', filename=true) pq LIMIT 1 +---- +data/parquet-testing/enum.parquet + +query I +SELECT pq.filename FROM read_parquet('data/parquet-testing/enum.parquet', filename=1) pq LIMIT 1 +---- +data/parquet-testing/enum.parquet + +# the string TRUE can be a column name +query I +SELECT "TRUE" FROM read_parquet('data/parquet-testing/enum.parquet', filename='TRUE') pq LIMIT 1 +---- +data/parquet-testing/enum.parquet + +# FALSR too +query I +SELECT "FALSE" FROM read_parquet('data/parquet-testing/enum.parquet', filename='FALSE') pq LIMIT 1 +---- +data/parquet-testing/enum.parquet + +# this is the output without an additional filename column +query IIIIIII nosort q0 +SELECT * FROM read_parquet('data/parquet-testing/enum.parquet') +---- + +# this shouldn't somehow add a column with the name false/0/FALSE +query IIIIIII nosort q0 +SELECT * FROM read_parquet('data/parquet-testing/enum.parquet', filename=false) +---- + + +query IIIIIII nosort q0 +SELECT * FROM read_parquet('data/parquet-testing/enum.parquet', filename=0) +---- + + +# cool names work too +query I +SELECT my_cool_filename FROM read_parquet('data/parquet-testing/enum.parquet', filename='my_cool_filename') LIMIT 1 +---- +data/parquet-testing/enum.parquet + +query I +SELECT my_cool_filename FROM read_parquet('data/parquet-testing/enum.parquet', filename=my_cool_filename) LIMIT 1 +---- +data/parquet-testing/enum.parquet diff --git a/test/parquet/test_parquet_reader_compression.test b/test/parquet/test_parquet_reader_compression.test index 6eb1ea932ce..b33f1596608 100644 --- a/test/parquet/test_parquet_reader_compression.test +++ b/test/parquet/test_parquet_reader_compression.test @@ -7,255 +7,11 @@ require parquet statement ok PRAGMA enable_verification -query IIII -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=1_NONE.parquet', hive_partitioning=0) limit 50 ----- -0 20 {'string': foo, 'int': 22} [] -1 6 {'string': baz, 'int': 10} NULL -2 23 {'string': bar, 'int': NULL} NULL -3 9 {'string': baz, 'int': 12} [25, 7, 5, 22, 24, 18, 30, 7, 19, 7, 17, 11, 30, 40, 30] -4 6 {'string': foo, 'int': 41} NULL -5 23 NULL [5, 22, 17, 7, 9, 37, 28, 37, 26, 30, 38, 40, 2] -6 19 {'string': foo, 'int': NULL} [NULL, 25, 21] -7 20 {'string': baz, 'int': 10} [35, 32, 11, 26, 27, 4, 1, 13, 31, 2, 32, 38, 16, 0, 29, 23, 32, 7, 17] -8 29 {'string': baz, 'int': 35} NULL -9 11 NULL [14, 0, NULL, 29, 23, 14, 13, 13, 15, 26, 29, 32, 5, 13, 32, 29, 38] -10 25 {'string': baz, 'int': 23} [5, 20, 9, 18, 32, 6, 21, 18, 1, 32, 34, 17, 3, 26, NULL, 1, 16, 9, 41] -11 9 NULL [] -12 17 {'string': bar, 'int': 25} [8, 37, NULL, 34, 1, 5, 9, 40, 1, 28, 27, 14, 28, 0, 14, 33, 1, 26, 18] -13 17 {'string': foo, 'int': 20} [38, 7, 40, 18, 26] -14 6 NULL [16, 31, 9, 30, 36, 24, 29, 20, 20, 20, 17, 37, 4, 41, 25, 12, 21, 24] -15 5 {'string': bar, 'int': NULL} [38, 35, 41, 4, 34, NULL, 37, 12, 21, 31, 16, 13, 20, 36, 22, 19, 35] -16 6 {'string': bar, 'int': 25} [3] -17 20 {'string': bar, 'int': 35} [6, 11, 25, 14, 38, 19, 9, 21, 12, 41, 36, 31] -18 18 {'string': NULL, 'int': 19} [28] -19 28 NULL [0, 41, 26, 27, 23, 40] -20 21 {'string': bar, 'int': 3} [15, 35, 40, 29, 37, 8, 4, 9, 6, 37, 16, 14, 32, 29, NULL, 18, 1] -21 7 {'string': NULL, 'int': 36} [19] -22 27 NULL [3, 0, 15, 35, 6, 13, 24, 14, 7, 3, 32] -23 28 {'string': NULL, 'int': NULL} [26, 17, 33, 17, 21, 34, 20, 25, 33, 21, 4, 1, 23, 9, 32] -24 21 {'string': foo, 'int': 12} [19, 15, 36, 37, 1, 19, 21, 4, 40, NULL, NULL, 19, 4] -25 20 {'string': foo, 'int': NULL} NULL -26 3 {'string': NULL, 'int': 15} [32, 31, 3, 26, 34, 1, 6, 29, 5, 22, 11, 1, 18] -27 2 {'string': foo, 'int': 25} [19] -28 7 {'string': foo, 'int': 34} [20, 1, 18, 20, 1, 3, 25, 2, 31, 22, NULL, 40, 23, 32, 40, 10] -29 13 {'string': bar, 'int': 8} [40, 32, 9, 2, 2, 40, 7, 0, 32, 31, 11, 14, 4, 14, 40, 20, 29, 17, 41] - -query IIII -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=2_NONE.parquet', hive_partitioning=0) limit 50 ----- -0 20 {'string': foo, 'int': 22} [] -1 6 {'string': baz, 'int': 10} NULL -2 23 {'string': bar, 'int': NULL} NULL -3 9 {'string': baz, 'int': 12} [25, 7, 5, 22, 24, 18, 30, 7, 19, 7, 17, 11, 30, 40, 30] -4 6 {'string': foo, 'int': 41} NULL -5 23 NULL [5, 22, 17, 7, 9, 37, 28, 37, 26, 30, 38, 40, 2] -6 19 {'string': foo, 'int': NULL} [NULL, 25, 21] -7 20 {'string': baz, 'int': 10} [35, 32, 11, 26, 27, 4, 1, 13, 31, 2, 32, 38, 16, 0, 29, 23, 32, 7, 17] -8 29 {'string': baz, 'int': 35} NULL -9 11 NULL [14, 0, NULL, 29, 23, 14, 13, 13, 15, 26, 29, 32, 5, 13, 32, 29, 38] -10 25 {'string': baz, 'int': 23} [5, 20, 9, 18, 32, 6, 21, 18, 1, 32, 34, 17, 3, 26, NULL, 1, 16, 9, 41] -11 9 NULL [] -12 17 {'string': bar, 'int': 25} [8, 37, NULL, 34, 1, 5, 9, 40, 1, 28, 27, 14, 28, 0, 14, 33, 1, 26, 18] -13 17 {'string': foo, 'int': 20} [38, 7, 40, 18, 26] -14 6 NULL [16, 31, 9, 30, 36, 24, 29, 20, 20, 20, 17, 37, 4, 41, 25, 12, 21, 24] -15 5 {'string': bar, 'int': NULL} [38, 35, 41, 4, 34, NULL, 37, 12, 21, 31, 16, 13, 20, 36, 22, 19, 35] -16 6 {'string': bar, 'int': 25} [3] -17 20 {'string': bar, 'int': 35} [6, 11, 25, 14, 38, 19, 9, 21, 12, 41, 36, 31] -18 18 {'string': NULL, 'int': 19} [28] -19 28 NULL [0, 41, 26, 27, 23, 40] -20 21 {'string': bar, 'int': 3} [15, 35, 40, 29, 37, 8, 4, 9, 6, 37, 16, 14, 32, 29, NULL, 18, 1] -21 7 {'string': NULL, 'int': 36} [19] -22 27 NULL [3, 0, 15, 35, 6, 13, 24, 14, 7, 3, 32] -23 28 {'string': NULL, 'int': NULL} [26, 17, 33, 17, 21, 34, 20, 25, 33, 21, 4, 1, 23, 9, 32] -24 21 {'string': foo, 'int': 12} [19, 15, 36, 37, 1, 19, 21, 4, 40, NULL, NULL, 19, 4] -25 20 {'string': foo, 'int': NULL} NULL -26 3 {'string': NULL, 'int': 15} [32, 31, 3, 26, 34, 1, 6, 29, 5, 22, 11, 1, 18] -27 2 {'string': foo, 'int': 25} [19] -28 7 {'string': foo, 'int': 34} [20, 1, 18, 20, 1, 3, 25, 2, 31, 22, NULL, 40, 23, 32, 40, 10] -29 13 {'string': bar, 'int': 8} [40, 32, 9, 2, 2, 40, 7, 0, 32, 31, 11, 14, 4, 14, 40, 20, 29, 17, 41] - -query IIII -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=1_SNAPPY.parquet', hive_partitioning=0) limit 50 ----- -0 20 {'string': foo, 'int': 22} [] -1 6 {'string': baz, 'int': 10} NULL -2 23 {'string': bar, 'int': NULL} NULL -3 9 {'string': baz, 'int': 12} [25, 7, 5, 22, 24, 18, 30, 7, 19, 7, 17, 11, 30, 40, 30] -4 6 {'string': foo, 'int': 41} NULL -5 23 NULL [5, 22, 17, 7, 9, 37, 28, 37, 26, 30, 38, 40, 2] -6 19 {'string': foo, 'int': NULL} [NULL, 25, 21] -7 20 {'string': baz, 'int': 10} [35, 32, 11, 26, 27, 4, 1, 13, 31, 2, 32, 38, 16, 0, 29, 23, 32, 7, 17] -8 29 {'string': baz, 'int': 35} NULL -9 11 NULL [14, 0, NULL, 29, 23, 14, 13, 13, 15, 26, 29, 32, 5, 13, 32, 29, 38] -10 25 {'string': baz, 'int': 23} [5, 20, 9, 18, 32, 6, 21, 18, 1, 32, 34, 17, 3, 26, NULL, 1, 16, 9, 41] -11 9 NULL [] -12 17 {'string': bar, 'int': 25} [8, 37, NULL, 34, 1, 5, 9, 40, 1, 28, 27, 14, 28, 0, 14, 33, 1, 26, 18] -13 17 {'string': foo, 'int': 20} [38, 7, 40, 18, 26] -14 6 NULL [16, 31, 9, 30, 36, 24, 29, 20, 20, 20, 17, 37, 4, 41, 25, 12, 21, 24] -15 5 {'string': bar, 'int': NULL} [38, 35, 41, 4, 34, NULL, 37, 12, 21, 31, 16, 13, 20, 36, 22, 19, 35] -16 6 {'string': bar, 'int': 25} [3] -17 20 {'string': bar, 'int': 35} [6, 11, 25, 14, 38, 19, 9, 21, 12, 41, 36, 31] -18 18 {'string': NULL, 'int': 19} [28] -19 28 NULL [0, 41, 26, 27, 23, 40] -20 21 {'string': bar, 'int': 3} [15, 35, 40, 29, 37, 8, 4, 9, 6, 37, 16, 14, 32, 29, NULL, 18, 1] -21 7 {'string': NULL, 'int': 36} [19] -22 27 NULL [3, 0, 15, 35, 6, 13, 24, 14, 7, 3, 32] -23 28 {'string': NULL, 'int': NULL} [26, 17, 33, 17, 21, 34, 20, 25, 33, 21, 4, 1, 23, 9, 32] -24 21 {'string': foo, 'int': 12} [19, 15, 36, 37, 1, 19, 21, 4, 40, NULL, NULL, 19, 4] -25 20 {'string': foo, 'int': NULL} NULL -26 3 {'string': NULL, 'int': 15} [32, 31, 3, 26, 34, 1, 6, 29, 5, 22, 11, 1, 18] -27 2 {'string': foo, 'int': 25} [19] -28 7 {'string': foo, 'int': 34} [20, 1, 18, 20, 1, 3, 25, 2, 31, 22, NULL, 40, 23, 32, 40, 10] -29 13 {'string': bar, 'int': 8} [40, 32, 9, 2, 2, 40, 7, 0, 32, 31, 11, 14, 4, 14, 40, 20, 29, 17, 41] - -query IIII -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=2_SNAPPY.parquet', hive_partitioning=0) limit 50 ----- -0 20 {'string': foo, 'int': 22} [] -1 6 {'string': baz, 'int': 10} NULL -2 23 {'string': bar, 'int': NULL} NULL -3 9 {'string': baz, 'int': 12} [25, 7, 5, 22, 24, 18, 30, 7, 19, 7, 17, 11, 30, 40, 30] -4 6 {'string': foo, 'int': 41} NULL -5 23 NULL [5, 22, 17, 7, 9, 37, 28, 37, 26, 30, 38, 40, 2] -6 19 {'string': foo, 'int': NULL} [NULL, 25, 21] -7 20 {'string': baz, 'int': 10} [35, 32, 11, 26, 27, 4, 1, 13, 31, 2, 32, 38, 16, 0, 29, 23, 32, 7, 17] -8 29 {'string': baz, 'int': 35} NULL -9 11 NULL [14, 0, NULL, 29, 23, 14, 13, 13, 15, 26, 29, 32, 5, 13, 32, 29, 38] -10 25 {'string': baz, 'int': 23} [5, 20, 9, 18, 32, 6, 21, 18, 1, 32, 34, 17, 3, 26, NULL, 1, 16, 9, 41] -11 9 NULL [] -12 17 {'string': bar, 'int': 25} [8, 37, NULL, 34, 1, 5, 9, 40, 1, 28, 27, 14, 28, 0, 14, 33, 1, 26, 18] -13 17 {'string': foo, 'int': 20} [38, 7, 40, 18, 26] -14 6 NULL [16, 31, 9, 30, 36, 24, 29, 20, 20, 20, 17, 37, 4, 41, 25, 12, 21, 24] -15 5 {'string': bar, 'int': NULL} [38, 35, 41, 4, 34, NULL, 37, 12, 21, 31, 16, 13, 20, 36, 22, 19, 35] -16 6 {'string': bar, 'int': 25} [3] -17 20 {'string': bar, 'int': 35} [6, 11, 25, 14, 38, 19, 9, 21, 12, 41, 36, 31] -18 18 {'string': NULL, 'int': 19} [28] -19 28 NULL [0, 41, 26, 27, 23, 40] -20 21 {'string': bar, 'int': 3} [15, 35, 40, 29, 37, 8, 4, 9, 6, 37, 16, 14, 32, 29, NULL, 18, 1] -21 7 {'string': NULL, 'int': 36} [19] -22 27 NULL [3, 0, 15, 35, 6, 13, 24, 14, 7, 3, 32] -23 28 {'string': NULL, 'int': NULL} [26, 17, 33, 17, 21, 34, 20, 25, 33, 21, 4, 1, 23, 9, 32] -24 21 {'string': foo, 'int': 12} [19, 15, 36, 37, 1, 19, 21, 4, 40, NULL, NULL, 19, 4] -25 20 {'string': foo, 'int': NULL} NULL -26 3 {'string': NULL, 'int': 15} [32, 31, 3, 26, 34, 1, 6, 29, 5, 22, 11, 1, 18] -27 2 {'string': foo, 'int': 25} [19] -28 7 {'string': foo, 'int': 34} [20, 1, 18, 20, 1, 3, 25, 2, 31, 22, NULL, 40, 23, 32, 40, 10] -29 13 {'string': bar, 'int': 8} [40, 32, 9, 2, 2, 40, 7, 0, 32, 31, 11, 14, 4, 14, 40, 20, 29, 17, 41] - -query IIII -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=1_GZIP.parquet', hive_partitioning=0) limit 50 ----- -0 20 {'string': foo, 'int': 22} [] -1 6 {'string': baz, 'int': 10} NULL -2 23 {'string': bar, 'int': NULL} NULL -3 9 {'string': baz, 'int': 12} [25, 7, 5, 22, 24, 18, 30, 7, 19, 7, 17, 11, 30, 40, 30] -4 6 {'string': foo, 'int': 41} NULL -5 23 NULL [5, 22, 17, 7, 9, 37, 28, 37, 26, 30, 38, 40, 2] -6 19 {'string': foo, 'int': NULL} [NULL, 25, 21] -7 20 {'string': baz, 'int': 10} [35, 32, 11, 26, 27, 4, 1, 13, 31, 2, 32, 38, 16, 0, 29, 23, 32, 7, 17] -8 29 {'string': baz, 'int': 35} NULL -9 11 NULL [14, 0, NULL, 29, 23, 14, 13, 13, 15, 26, 29, 32, 5, 13, 32, 29, 38] -10 25 {'string': baz, 'int': 23} [5, 20, 9, 18, 32, 6, 21, 18, 1, 32, 34, 17, 3, 26, NULL, 1, 16, 9, 41] -11 9 NULL [] -12 17 {'string': bar, 'int': 25} [8, 37, NULL, 34, 1, 5, 9, 40, 1, 28, 27, 14, 28, 0, 14, 33, 1, 26, 18] -13 17 {'string': foo, 'int': 20} [38, 7, 40, 18, 26] -14 6 NULL [16, 31, 9, 30, 36, 24, 29, 20, 20, 20, 17, 37, 4, 41, 25, 12, 21, 24] -15 5 {'string': bar, 'int': NULL} [38, 35, 41, 4, 34, NULL, 37, 12, 21, 31, 16, 13, 20, 36, 22, 19, 35] -16 6 {'string': bar, 'int': 25} [3] -17 20 {'string': bar, 'int': 35} [6, 11, 25, 14, 38, 19, 9, 21, 12, 41, 36, 31] -18 18 {'string': NULL, 'int': 19} [28] -19 28 NULL [0, 41, 26, 27, 23, 40] -20 21 {'string': bar, 'int': 3} [15, 35, 40, 29, 37, 8, 4, 9, 6, 37, 16, 14, 32, 29, NULL, 18, 1] -21 7 {'string': NULL, 'int': 36} [19] -22 27 NULL [3, 0, 15, 35, 6, 13, 24, 14, 7, 3, 32] -23 28 {'string': NULL, 'int': NULL} [26, 17, 33, 17, 21, 34, 20, 25, 33, 21, 4, 1, 23, 9, 32] -24 21 {'string': foo, 'int': 12} [19, 15, 36, 37, 1, 19, 21, 4, 40, NULL, NULL, 19, 4] -25 20 {'string': foo, 'int': NULL} NULL -26 3 {'string': NULL, 'int': 15} [32, 31, 3, 26, 34, 1, 6, 29, 5, 22, 11, 1, 18] -27 2 {'string': foo, 'int': 25} [19] -28 7 {'string': foo, 'int': 34} [20, 1, 18, 20, 1, 3, 25, 2, 31, 22, NULL, 40, 23, 32, 40, 10] -29 13 {'string': bar, 'int': 8} [40, 32, 9, 2, 2, 40, 7, 0, 32, 31, 11, 14, 4, 14, 40, 20, 29, 17, 41] - -query IIII -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=2_GZIP.parquet', hive_partitioning=0) limit 50 ----- -0 20 {'string': foo, 'int': 22} [] -1 6 {'string': baz, 'int': 10} NULL -2 23 {'string': bar, 'int': NULL} NULL -3 9 {'string': baz, 'int': 12} [25, 7, 5, 22, 24, 18, 30, 7, 19, 7, 17, 11, 30, 40, 30] -4 6 {'string': foo, 'int': 41} NULL -5 23 NULL [5, 22, 17, 7, 9, 37, 28, 37, 26, 30, 38, 40, 2] -6 19 {'string': foo, 'int': NULL} [NULL, 25, 21] -7 20 {'string': baz, 'int': 10} [35, 32, 11, 26, 27, 4, 1, 13, 31, 2, 32, 38, 16, 0, 29, 23, 32, 7, 17] -8 29 {'string': baz, 'int': 35} NULL -9 11 NULL [14, 0, NULL, 29, 23, 14, 13, 13, 15, 26, 29, 32, 5, 13, 32, 29, 38] -10 25 {'string': baz, 'int': 23} [5, 20, 9, 18, 32, 6, 21, 18, 1, 32, 34, 17, 3, 26, NULL, 1, 16, 9, 41] -11 9 NULL [] -12 17 {'string': bar, 'int': 25} [8, 37, NULL, 34, 1, 5, 9, 40, 1, 28, 27, 14, 28, 0, 14, 33, 1, 26, 18] -13 17 {'string': foo, 'int': 20} [38, 7, 40, 18, 26] -14 6 NULL [16, 31, 9, 30, 36, 24, 29, 20, 20, 20, 17, 37, 4, 41, 25, 12, 21, 24] -15 5 {'string': bar, 'int': NULL} [38, 35, 41, 4, 34, NULL, 37, 12, 21, 31, 16, 13, 20, 36, 22, 19, 35] -16 6 {'string': bar, 'int': 25} [3] -17 20 {'string': bar, 'int': 35} [6, 11, 25, 14, 38, 19, 9, 21, 12, 41, 36, 31] -18 18 {'string': NULL, 'int': 19} [28] -19 28 NULL [0, 41, 26, 27, 23, 40] -20 21 {'string': bar, 'int': 3} [15, 35, 40, 29, 37, 8, 4, 9, 6, 37, 16, 14, 32, 29, NULL, 18, 1] -21 7 {'string': NULL, 'int': 36} [19] -22 27 NULL [3, 0, 15, 35, 6, 13, 24, 14, 7, 3, 32] -23 28 {'string': NULL, 'int': NULL} [26, 17, 33, 17, 21, 34, 20, 25, 33, 21, 4, 1, 23, 9, 32] -24 21 {'string': foo, 'int': 12} [19, 15, 36, 37, 1, 19, 21, 4, 40, NULL, NULL, 19, 4] -25 20 {'string': foo, 'int': NULL} NULL -26 3 {'string': NULL, 'int': 15} [32, 31, 3, 26, 34, 1, 6, 29, 5, 22, 11, 1, 18] -27 2 {'string': foo, 'int': 25} [19] -28 7 {'string': foo, 'int': 34} [20, 1, 18, 20, 1, 3, 25, 2, 31, 22, NULL, 40, 23, 32, 40, 10] -29 13 {'string': bar, 'int': 8} [40, 32, 9, 2, 2, 40, 7, 0, 32, 31, 11, 14, 4, 14, 40, 20, 29, 17, 41] - -# Unsupported formats -statement error -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=1_BROTLI.parquet') limit 50 ----- - -statement error -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=2_BROTLI.parquet') limit 50 ----- +foreach codec NONE SNAPPY GZIP ZSTD LZ4 BROTLI -query IIII -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=1_ZSTD.parquet', hive_partitioning=0) limit 50 ----- -0 20 {'string': foo, 'int': 22} [] -1 6 {'string': baz, 'int': 10} NULL -2 23 {'string': bar, 'int': NULL} NULL -3 9 {'string': baz, 'int': 12} [25, 7, 5, 22, 24, 18, 30, 7, 19, 7, 17, 11, 30, 40, 30] -4 6 {'string': foo, 'int': 41} NULL -5 23 NULL [5, 22, 17, 7, 9, 37, 28, 37, 26, 30, 38, 40, 2] -6 19 {'string': foo, 'int': NULL} [NULL, 25, 21] -7 20 {'string': baz, 'int': 10} [35, 32, 11, 26, 27, 4, 1, 13, 31, 2, 32, 38, 16, 0, 29, 23, 32, 7, 17] -8 29 {'string': baz, 'int': 35} NULL -9 11 NULL [14, 0, NULL, 29, 23, 14, 13, 13, 15, 26, 29, 32, 5, 13, 32, 29, 38] -10 25 {'string': baz, 'int': 23} [5, 20, 9, 18, 32, 6, 21, 18, 1, 32, 34, 17, 3, 26, NULL, 1, 16, 9, 41] -11 9 NULL [] -12 17 {'string': bar, 'int': 25} [8, 37, NULL, 34, 1, 5, 9, 40, 1, 28, 27, 14, 28, 0, 14, 33, 1, 26, 18] -13 17 {'string': foo, 'int': 20} [38, 7, 40, 18, 26] -14 6 NULL [16, 31, 9, 30, 36, 24, 29, 20, 20, 20, 17, 37, 4, 41, 25, 12, 21, 24] -15 5 {'string': bar, 'int': NULL} [38, 35, 41, 4, 34, NULL, 37, 12, 21, 31, 16, 13, 20, 36, 22, 19, 35] -16 6 {'string': bar, 'int': 25} [3] -17 20 {'string': bar, 'int': 35} [6, 11, 25, 14, 38, 19, 9, 21, 12, 41, 36, 31] -18 18 {'string': NULL, 'int': 19} [28] -19 28 NULL [0, 41, 26, 27, 23, 40] -20 21 {'string': bar, 'int': 3} [15, 35, 40, 29, 37, 8, 4, 9, 6, 37, 16, 14, 32, 29, NULL, 18, 1] -21 7 {'string': NULL, 'int': 36} [19] -22 27 NULL [3, 0, 15, 35, 6, 13, 24, 14, 7, 3, 32] -23 28 {'string': NULL, 'int': NULL} [26, 17, 33, 17, 21, 34, 20, 25, 33, 21, 4, 1, 23, 9, 32] -24 21 {'string': foo, 'int': 12} [19, 15, 36, 37, 1, 19, 21, 4, 40, NULL, NULL, 19, 4] -25 20 {'string': foo, 'int': NULL} NULL -26 3 {'string': NULL, 'int': 15} [32, 31, 3, 26, 34, 1, 6, 29, 5, 22, 11, 1, 18] -27 2 {'string': foo, 'int': 25} [19] -28 7 {'string': foo, 'int': 34} [20, 1, 18, 20, 1, 3, 25, 2, 31, 22, NULL, 40, 23, 32, 40, 10] -29 13 {'string': bar, 'int': 8} [40, 32, 9, 2, 2, 40, 7, 0, 32, 31, 11, 14, 4, 14, 40, 20, 29, 17, 41] query IIII -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=2_ZSTD.parquet', hive_partitioning=0) limit 50 +SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=1_${codec}.parquet', hive_partitioning=0) limit 50 ---- 0 20 {'string': foo, 'int': 22} [] 1 6 {'string': baz, 'int': 10} NULL @@ -288,11 +44,8 @@ SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page 28 7 {'string': foo, 'int': 34} [20, 1, 18, 20, 1, 3, 25, 2, 31, 22, NULL, 40, 23, 32, 40, 10] 29 13 {'string': bar, 'int': 8} [40, 32, 9, 2, 2, 40, 7, 0, 32, 31, 11, 14, 4, 14, 40, 20, 29, 17, 41] - - - query IIII -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=1_LZ4.parquet', hive_partitioning=0) limit 50 +SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=2_${codec}.parquet', hive_partitioning=0) limit 50 ---- 0 20 {'string': foo, 'int': 22} [] 1 6 {'string': baz, 'int': 10} NULL @@ -325,36 +78,4 @@ SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page 28 7 {'string': foo, 'int': 34} [20, 1, 18, 20, 1, 3, 25, 2, 31, 22, NULL, 40, 23, 32, 40, 10] 29 13 {'string': bar, 'int': 8} [40, 32, 9, 2, 2, 40, 7, 0, 32, 31, 11, 14, 4, 14, 40, 20, 29, 17, 41] -query IIII -SELECT * FROM parquet_scan('data/parquet-testing/compression/generated/data_page=2_LZ4.parquet', hive_partitioning=0) limit 50 ----- -0 20 {'string': foo, 'int': 22} [] -1 6 {'string': baz, 'int': 10} NULL -2 23 {'string': bar, 'int': NULL} NULL -3 9 {'string': baz, 'int': 12} [25, 7, 5, 22, 24, 18, 30, 7, 19, 7, 17, 11, 30, 40, 30] -4 6 {'string': foo, 'int': 41} NULL -5 23 NULL [5, 22, 17, 7, 9, 37, 28, 37, 26, 30, 38, 40, 2] -6 19 {'string': foo, 'int': NULL} [NULL, 25, 21] -7 20 {'string': baz, 'int': 10} [35, 32, 11, 26, 27, 4, 1, 13, 31, 2, 32, 38, 16, 0, 29, 23, 32, 7, 17] -8 29 {'string': baz, 'int': 35} NULL -9 11 NULL [14, 0, NULL, 29, 23, 14, 13, 13, 15, 26, 29, 32, 5, 13, 32, 29, 38] -10 25 {'string': baz, 'int': 23} [5, 20, 9, 18, 32, 6, 21, 18, 1, 32, 34, 17, 3, 26, NULL, 1, 16, 9, 41] -11 9 NULL [] -12 17 {'string': bar, 'int': 25} [8, 37, NULL, 34, 1, 5, 9, 40, 1, 28, 27, 14, 28, 0, 14, 33, 1, 26, 18] -13 17 {'string': foo, 'int': 20} [38, 7, 40, 18, 26] -14 6 NULL [16, 31, 9, 30, 36, 24, 29, 20, 20, 20, 17, 37, 4, 41, 25, 12, 21, 24] -15 5 {'string': bar, 'int': NULL} [38, 35, 41, 4, 34, NULL, 37, 12, 21, 31, 16, 13, 20, 36, 22, 19, 35] -16 6 {'string': bar, 'int': 25} [3] -17 20 {'string': bar, 'int': 35} [6, 11, 25, 14, 38, 19, 9, 21, 12, 41, 36, 31] -18 18 {'string': NULL, 'int': 19} [28] -19 28 NULL [0, 41, 26, 27, 23, 40] -20 21 {'string': bar, 'int': 3} [15, 35, 40, 29, 37, 8, 4, 9, 6, 37, 16, 14, 32, 29, NULL, 18, 1] -21 7 {'string': NULL, 'int': 36} [19] -22 27 NULL [3, 0, 15, 35, 6, 13, 24, 14, 7, 3, 32] -23 28 {'string': NULL, 'int': NULL} [26, 17, 33, 17, 21, 34, 20, 25, 33, 21, 4, 1, 23, 9, 32] -24 21 {'string': foo, 'int': 12} [19, 15, 36, 37, 1, 19, 21, 4, 40, NULL, NULL, 19, 4] -25 20 {'string': foo, 'int': NULL} NULL -26 3 {'string': NULL, 'int': 15} [32, 31, 3, 26, 34, 1, 6, 29, 5, 22, 11, 1, 18] -27 2 {'string': foo, 'int': 25} [19] -28 7 {'string': foo, 'int': 34} [20, 1, 18, 20, 1, 3, 25, 2, 31, 22, NULL, 40, 23, 32, 40, 10] -29 13 {'string': bar, 'int': 8} [40, 32, 9, 2, 2, 40, 7, 0, 32, 31, 11, 14, 4, 14, 40, 20, 29, 17, 41] +endloop \ No newline at end of file diff --git a/test/parquet/timetz_parquet.test b/test/parquet/timetz_parquet.test index 586d794cc09..90914894458 100644 --- a/test/parquet/timetz_parquet.test +++ b/test/parquet/timetz_parquet.test @@ -15,3 +15,24 @@ query I select COL_TIME from 'data/parquet-testing/date-with-timezone-int64.parquet' ; ---- 12:00:00+00 + +query II +select pruefbahn_id, arbeits_beginn +from 'data/parquet-testing/timetz-nanos.parquet' +where pruefbahn_id = '58981'; +---- +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 +58981 07:20:00+00 diff --git a/test/serialize/serialization_test.cpp b/test/serialize/serialization_test.cpp index 15e637f84f8..eb3f8f386b2 100644 --- a/test/serialize/serialization_test.cpp +++ b/test/serialize/serialization_test.cpp @@ -48,7 +48,9 @@ TEST_CASE("Test default values", "[serialization]") { foo_in.c = 44; MemoryStream stream; - BinarySerializer::Serialize(foo_in, stream, false); + SerializationOptions options; + options.serialize_default_values = false; + BinarySerializer::Serialize(foo_in, stream, options); auto pos1 = stream.GetPosition(); stream.Rewind(); auto foo_out_ptr = BinaryDeserializer::Deserialize(stream); @@ -63,7 +65,8 @@ TEST_CASE("Test default values", "[serialization]") { stream.Rewind(); - BinarySerializer::Serialize(foo_in, stream, false); + options.serialize_default_values = false; + BinarySerializer::Serialize(foo_in, stream, options); auto pos2 = stream.GetPosition(); stream.Rewind(); @@ -164,8 +167,10 @@ TEST_CASE("Test deleted values", "[serialization]") { FooV2 v2_in = {1, 3, make_uniq(1, "foo"), nullptr}; MemoryStream stream; + SerializationOptions options; + options.serialize_default_values = false; // First of, sanity check that foov1 <-> foov1 works - BinarySerializer::Serialize(v1_in, stream, false); + BinarySerializer::Serialize(v1_in, stream, options); { stream.Rewind(); auto v1_out_ptr = BinaryDeserializer::Deserialize(stream); @@ -184,7 +189,8 @@ TEST_CASE("Test deleted values", "[serialization]") { stream.Rewind(); // Also check that foov2 <-> foov2 works - BinarySerializer::Serialize(v2_in, stream, false); + options.serialize_default_values = false; + BinarySerializer::Serialize(v2_in, stream, options); { stream.Rewind(); auto v2_out_ptr = BinaryDeserializer::Deserialize(stream); @@ -198,7 +204,8 @@ TEST_CASE("Test deleted values", "[serialization]") { // Check that foov1 -> foov2 works (backwards compatible) stream.Rewind(); - BinarySerializer::Serialize(v1_in, stream, false); + options.serialize_default_values = false; + BinarySerializer::Serialize(v1_in, stream, options); { stream.Rewind(); auto v2_out_ptr = BinaryDeserializer::Deserialize(stream); @@ -213,7 +220,8 @@ TEST_CASE("Test deleted values", "[serialization]") { // Check that foov2 -> foov1 works (forwards compatible) // This should be ok, since the property we deleted was optional (had a default value) stream.Rewind(); - BinarySerializer::Serialize(v2_in, stream, false); + options.serialize_default_values = false; + BinarySerializer::Serialize(v2_in, stream, options); { stream.Rewind(); auto v1_out_ptr = BinaryDeserializer::Deserialize(stream); @@ -229,7 +237,8 @@ TEST_CASE("Test deleted values", "[serialization]") { // But thats life. Tough shit. stream.Rewind(); v2_in.p5 = make_uniq(2, "foo"); - BinarySerializer::Serialize(v2_in, stream, false); + options.serialize_default_values = false; + BinarySerializer::Serialize(v2_in, stream, options); { stream.Rewind(); REQUIRE_THROWS(BinaryDeserializer::Deserialize(stream)); @@ -237,7 +246,8 @@ TEST_CASE("Test deleted values", "[serialization]") { // However, the new value should be read correctly! stream.Rewind(); - BinarySerializer::Serialize(v2_in, stream, false); + options.serialize_default_values = false; + BinarySerializer::Serialize(v2_in, stream, options); { stream.Rewind(); auto v2_out_ptr = BinaryDeserializer::Deserialize(stream); diff --git a/test/sql/aggregate/aggregates/arg_min_max_all_types.test_slow b/test/sql/aggregate/aggregates/arg_min_max_all_types.test_slow new file mode 100644 index 00000000000..4a5fcedd409 --- /dev/null +++ b/test/sql/aggregate/aggregates/arg_min_max_all_types.test_slow @@ -0,0 +1,23 @@ +# name: test/sql/aggregate/aggregates/arg_min_max_all_types.test_slow +# description: Test argmin and argmax operator for all types +# group: [aggregates] + +statement ok +PRAGMA enable_verification + +statement ok +create table all_types as from test_all_types() + +foreach col bool tinyint smallint int bigint hugeint uhugeint utinyint usmallint uint ubigint date time timestamp timestamp_s timestamp_ms timestamp_ns time_tz timestamp_tz float double dec_4_1 dec_9_4 dec_18_6 dec38_10 uuid interval varchar blob bit small_enum medium_enum large_enum int_array double_array date_array timestamp_array timestamptz_array varchar_array nested_int_array struct struct_of_arrays array_of_structs map union fixed_int_array fixed_varchar_array fixed_nested_int_array fixed_nested_varchar_array fixed_struct_array struct_of_fixed_array fixed_array_of_int_list list_of_fixed_int_array + +query I +SELECT MIN("${col}") IS NOT DISTINCT FROM ARG_MIN("${col}", "${col}") FROM all_types +---- +true + +query I +SELECT MAX("${col}") IS NOT DISTINCT FROM ARG_MAX("${col}", "${col}") FROM all_types +---- +true + +endloop diff --git a/test/sql/aggregate/aggregates/binning.test b/test/sql/aggregate/aggregates/binning.test new file mode 100644 index 00000000000..d5ad0c5c088 --- /dev/null +++ b/test/sql/aggregate/aggregates/binning.test @@ -0,0 +1,269 @@ +# name: test/sql/aggregate/aggregates/binning.test +# description: Test binning functions +# group: [aggregates] + +statement ok +PRAGMA enable_verification + +query I +SELECT equi_width_bins(0, 10, 2, true) +---- +[5, 10] + +# small bins with big base +query I +SELECT equi_width_bins(1000000, 1000010, 2, true) +---- +[1000005, 1000010] + +# bounds cannot be nice because of step size +query I +SELECT equi_width_bins(99, 101, 2, true) +---- +[100, 101] + +query I +SELECT equi_width_bins(9, 11, 2, true) +---- +[10, 11] + +query I +SELECT equi_width_bins(10, 11, 2, true) +---- +[10, 11] + +# we cannot have duplicate bin boundaries +query I +SELECT equi_width_bins(0, 5, 10, true) +---- +[0, 1, 2, 3, 4, 5] + +query I +SELECT equi_width_bins(0, 10, 5, true) +---- +[2, 4, 6, 8, 10] + +query I +SELECT equi_width_bins(-10, 0, 5, true) +---- +[-8, -6, -4, -2, 0] + +query I +SELECT equi_width_bins(-10, 10, 5, true) +---- +[-6, -2, 2, 6, 10] + +query I +SELECT equi_width_bins(0, 9, 5, true) +---- +[1, 3, 5, 7, 9] + +query I +SELECT equi_width_bins(0, 1734, 10, true) +---- +[120, 300, 480, 660, 840, 1020, 1200, 1380, 1560, 1740] + +query I +SELECT equi_width_bins(0, 1724, 10, true) +---- +[120, 300, 480, 660, 840, 1020, 1200, 1380, 1560, 1740] + +# not nice +query I +SELECT equi_width_bins(0, 1734, 10, false) +---- +[173, 346, 520, 693, 867, 1040, 1213, 1387, 1560, 1734] + +query I +SELECT equi_width_bins(0, 39343341, 10, true) +---- +[3400000, 7400000, 11400000, 15400000, 19400000, 23400000, 27400000, 31400000, 35400000, 39400000] + +query I +SELECT equi_width_bins(1, 6000000, 7, true) +---- +[840000, 1700000, 2560000, 3420000, 4280000, 5140000, 6000000] + +query I +SELECT equi_width_bins(1, 6000000, 7, false) +---- +[857143, 1714286, 2571429, 3428571, 4285714, 5142857, 6000000] + +# big numbers +query I +SELECT equi_width_bins(-9223372036854775808, 9223372036854775807, 5, true) +---- +[-5000000000000000000, -1400000000000000000, 2200000000000000000, 5800000000000000000, 9223372036854775807] + +# floating point numbers +query I +SELECT equi_width_bins(0.0, 9.0, 5, true); +---- +[1.8, 3.6, 5.4, 7.2, 9.0] + +query I +SELECT equi_width_bins(0.0, 9.0, 7, true); +---- +[1.8, 3.0, 4.2, 5.4, 6.6, 7.8, 9.0] + +query I +SELECT unnest(equi_width_bins(0.0, 9.0, 7, false)); +---- +1.2857142857142863 +2.571428571428572 +3.8571428571428577 +5.142857142857143 +6.428571428571429 +7.714285714285714 +9.0 + +query I +SELECT equi_width_bins(0.0, 90.0, 5, true); +---- +[18.0, 36.0, 54.0, 72.0, 90.0] + +query I +SELECT equi_width_bins(0.0, 1.0, 5, true); +---- +[0.2, 0.4, 0.6, 0.8, 1.0] + +query I +SELECT equi_width_bins(0.0, 1.0, 5, true); +---- +[0.2, 0.4, 0.6, 0.8, 1.0] + +query I +SELECT equi_width_bins(-1.0, 0.0, 5, true); +---- +[-0.8, -0.6, -0.4, -0.2, 0.0] + +query I +SELECT equi_width_bins(-1.0, 1.0, 5, true); +---- +[-0.6, -0.2, 0.2, 0.6, 1.0] + +# test giant numberss +query I +SELECT unnest(equi_width_bins(-1e308, 1e308, 5, true)); +---- +-5.8e+307 +-1.8e+307 +2.2e+307 +6.2e+307 +1.02e+308 + +# last bin should always be bigger than the input max +query I +select equi_width_bins(0, 101, 5, true); +---- +[22, 42, 62, 82, 102] + +query I +select equi_width_bins(0, 101.5, 5, true); +---- +[22.0, 42.0, 62.0, 82.0, 102.0] + +# dates/timestamps +query I +SELECT equi_width_bins(date '1992-01-01', date '2000-01-01', 2, true) +---- +[1996-01-01, 2000-01-01] + +query I +SELECT equi_width_bins(timestamp '1992-01-01', timestamp '2000-01-01', 2, true) +---- +[1996-01-01 00:00:00, 2000-01-01 00:00:00] + +query I +SELECT equi_width_bins(timestamp '1992-01-01 12:23:37', timestamp '2000-01-01 04:03:21', 2, true) +---- +[1996-02-01 00:00:00, 2000-02-01 00:00:00] + +query I +SELECT equi_width_bins(timestamp '1992-01-01 12:23:37', timestamp '2000-01-01 04:03:21', 5, true) +---- +[1993-10-01 00:00:00, 1995-05-01 00:00:00, 1996-12-01 00:00:00, 1998-07-01 00:00:00, 2000-02-01 00:00:00] + +# bins within a year +query I +SELECT equi_width_bins(timestamp '1992-01-01 12:23:37', timestamp '1992-12-01 04:03:21', 4, true) +---- +[1992-03-27 00:00:00, 1992-06-18 00:00:00, 1992-09-10 00:00:00, 1992-12-02 00:00:00] + +# bins within a month +query I +SELECT equi_width_bins(timestamp '1992-01-01 12:23:37', timestamp '1992-01-31 04:03:21', 4, true) +---- +[1992-01-11 00:00:00, 1992-01-18 00:00:00, 1992-01-25 00:00:00, 1992-02-01 00:00:00] + +# bins within a day +query I +SELECT equi_width_bins(timestamp '1992-01-01 01:23:37.999', timestamp '1992-01-01 23:03:21.3', 4, true) +---- +[1992-01-01 07:30:00, 1992-01-01 13:00:00, 1992-01-01 18:30:00, 1992-01-02 00:00:00] + +# bins within an hour +query I +SELECT equi_width_bins(timestamp '1992-01-01 01:23:37.999', timestamp '1992-01-01 01:53:21.3', 4, true) +---- +[1992-01-01 01:31:30, 1992-01-01 01:39:00, 1992-01-01 01:46:30, 1992-01-01 01:54:00] + +# bins within a minute +query I +SELECT equi_width_bins(timestamp '1992-01-01 01:23:01.999', timestamp '1992-01-01 01:23:49.377', 4, true) +---- +[1992-01-01 01:23:14, 1992-01-01 01:23:26, 1992-01-01 01:23:38, 1992-01-01 01:23:50] + +# bins within a second +query I +SELECT equi_width_bins(timestamp '1992-01-01 01:23:01.2', timestamp '1992-01-01 01:23:01.943', 4, true) +---- +[1992-01-01 01:23:01.38575, 1992-01-01 01:23:01.5715, 1992-01-01 01:23:01.75725, 1992-01-01 01:23:01.943] + +# difference is more than one day, but step size is less than one day +query I +select equi_width_bins(timestamp '2024-06-21 15:00:00', timestamp '2024-06-22 9:00:00', 4, true); +---- +[2024-06-21 19:30:00, 2024-06-22 00:00:00, 2024-06-22 04:30:00, 2024-06-22 09:00:00] + +# difference is more than one month, but step size is less than one month +query I +select equi_width_bins(timestamp '2024-06-21 15:00:00', timestamp '2024-07-21 9:00:00', 4, true); +---- +[2024-07-01 00:00:00, 2024-07-08 00:00:00, 2024-07-15 00:00:00, 2024-07-22 00:00:00] + +# what if we create more partitions than there are microseconds +query I +select equi_width_bins(timestamp '2024-06-21 15:00:00.123456', timestamp '2024-06-21 15:00:00.123458', 10, true); +---- +[2024-06-21 15:00:00.123456, 2024-06-21 15:00:00.123457, 2024-06-21 15:00:00.123458] + +statement error +SELECT equi_width_bins(-0.0, -1.0, 5, true); +---- +max value is smaller than min value + +statement error +SELECT equi_width_bins(0.0, 'inf'::double, 5, true); +---- +does not support infinite or nan as min/max value + +statement error +SELECT equi_width_bins(0.0, 'nan'::double, 5, true); +---- +does not support infinite or nan as min/max value + +statement error +SELECT equi_width_bins(0.0, 1.0, -1, true); +---- +there must be > 0 bins + +statement error +SELECT equi_width_bins(0.0, 1.0, 99999999, true); +---- +max bin count + +statement error +SELECT equi_width_bins('a'::VARCHAR, 'z'::VARCHAR, 2, true) +---- +Unsupported type "VARCHAR" diff --git a/test/sql/aggregate/aggregates/first_test_all_types.test_slow b/test/sql/aggregate/aggregates/first_test_all_types.test_slow new file mode 100644 index 00000000000..5ff7fe76afd --- /dev/null +++ b/test/sql/aggregate/aggregates/first_test_all_types.test_slow @@ -0,0 +1,22 @@ +# name: test/sql/aggregate/aggregates/first_test_all_types.test_slow +# description: Test the first aggregate on all types +# group: [aggregates] + +statement ok +pragma enable_verification + +# verify that first produces the same result as limit 1 for all types +statement ok +CREATE TABLE all_types AS FROM test_all_types(); + +query I nosort all_types_first +SELECT * FROM all_types LIMIT 1 + +query I nosort all_types_first +SELECT FIRST(COLUMNS(*)) FROM all_types + +query I nosort all_types_last +SELECT * FROM all_types LIMIT 1 OFFSET 2 + +query I nosort all_types_last +SELECT LAST(COLUMNS(*)) FROM all_types diff --git a/test/sql/aggregate/aggregates/histogram_table_function.test b/test/sql/aggregate/aggregates/histogram_table_function.test new file mode 100644 index 00000000000..a128902a0b5 --- /dev/null +++ b/test/sql/aggregate/aggregates/histogram_table_function.test @@ -0,0 +1,149 @@ +# name: test/sql/aggregate/aggregates/histogram_table_function.test +# description: Test the histogram table function +# group: [aggregates] + +statement ok +pragma enable_verification + +# integers +statement ok +create table integers(i int); + +statement ok +insert into integers values (42); + +statement ok +insert into integers values (84); + +query II +SELECT * FROM histogram_values(integers, i, bin_count := 2) +---- +64 1 +84 1 + +statement ok +INSERT INTO integers FROM range(127) + +query II +SELECT * FROM histogram_values(integers, i, bin_count := 10, technique := 'equi-width') +---- +12 13 +25 13 +37 12 +50 14 +63 13 +75 12 +88 14 +100 12 +113 13 +126 13 + +query II +SELECT bin, count FROM histogram(integers, i, bin_count := 10, technique := 'equi-width') +---- +x <= 12 13 +12 < x <= 25 13 +25 < x <= 37 12 +37 < x <= 50 14 +50 < x <= 63 13 +63 < x <= 75 12 +75 < x <= 88 14 +88 < x <= 100 12 +100 < x <= 113 13 +113 < x <= 126 13 + +statement ok +INSERT INTO integers VALUES (99999999) + +query II +SELECT * FROM histogram_values(integers, i, technique := 'equi-height') +---- +12 13 +25 13 +38 13 +50 13 +63 13 +76 13 +88 13 +101 13 +114 13 +99999999 13 + +# sample integers +query II +SELECT * FROM histogram_values(integers, i%2, technique := 'sample') +---- +0 66 +1 64 + +# varchar +query II +SELECT * FROM histogram_values(integers, (i%2)::VARCHAR) +---- +0 66 +1 64 + +# varchar does not work with equi-width-bins +statement error +SELECT * FROM histogram_values(integers, (i%2)::VARCHAR, technique := 'equi-width') +---- +Unsupported + +# but it works with equi-height +query II +SELECT * FROM histogram_values(integers, i::VARCHAR, technique := 'equi-height') +---- +109 13 +120 13 +19 13 +30 13 +42 14 +53 12 +65 13 +77 13 +88 13 +99999999 13 + +# histogram with ranges +query II +SELECT bin, count FROM histogram(integers, i::VARCHAR, technique := 'equi-height') +---- +x <= 109 13 +109 < x <= 120 13 +120 < x <= 19 13 +19 < x <= 30 13 +30 < x <= 42 14 +42 < x <= 53 12 +53 < x <= 65 13 +65 < x <= 77 13 +77 < x <= 88 13 +88 < x <= 99999999 13 + + +# booleans +statement ok +create table booleans(b bool); + +statement ok +insert into booleans select case when i%4=0 then true else false end from range(100) t(i) + +query II +SELECT * FROM histogram_values(booleans, b::INTEGER) +---- +0 75 +1 25 + +mode skip + +# FIXME: booleans do not work yet because of quantile turning any unsupported type into VARCHAR +query II +SELECT * FROM histogram_values(booleans, b) +---- + +# lists +# FIXME: lists do not work yet because of quantile turning any unsupported type into VARCHAR +query II +SELECT * FROM histogram_values(integers, [i%2]) +---- + +mode unskip diff --git a/test/sql/aggregate/aggregates/histogram_test_all_types.test_slow b/test/sql/aggregate/aggregates/histogram_test_all_types.test_slow new file mode 100644 index 00000000000..1a32a66382e --- /dev/null +++ b/test/sql/aggregate/aggregates/histogram_test_all_types.test_slow @@ -0,0 +1,30 @@ +# name: test/sql/aggregate/aggregates/histogram_test_all_types.test_slow +# description: Test histogram operator for all types +# group: [aggregates] + +statement ok +PRAGMA enable_verification + +statement ok +create table all_types as from test_all_types() + +foreach col bool tinyint smallint int bigint hugeint uhugeint utinyint usmallint uint ubigint date time timestamp timestamp_s timestamp_ms timestamp_ns time_tz timestamp_tz float double dec_4_1 dec_9_4 dec_18_6 dec38_10 uuid interval varchar blob bit small_enum medium_enum large_enum int_array double_array date_array timestamp_array timestamptz_array varchar_array nested_int_array struct struct_of_arrays array_of_structs map union fixed_int_array fixed_varchar_array fixed_nested_int_array fixed_nested_varchar_array fixed_struct_array struct_of_fixed_array fixed_array_of_int_list list_of_fixed_int_array + +query II +SELECT histogram[min], histogram[max] FROM ( + SELECT HISTOGRAM("${col}") histogram, MIN("${col}") min, MAX("${col}") max + FROM all_types +) +---- +[1] [1] + +# binned histogram +query II +SELECT histogram[min], histogram[max] FROM ( + SELECT HISTOGRAM("${col}", [(select min("${col}") from all_types), ((select max("${col}") from all_types))]) histogram, MIN("${col}") min, MAX("${col}") max + FROM all_types +) +---- +[1] [1] + +endloop diff --git a/test/sql/aggregate/aggregates/histogram_tpch.test_slow b/test/sql/aggregate/aggregates/histogram_tpch.test_slow new file mode 100644 index 00000000000..bb40549091e --- /dev/null +++ b/test/sql/aggregate/aggregates/histogram_tpch.test_slow @@ -0,0 +1,99 @@ +# name: test/sql/aggregate/aggregates/histogram_tpch.test_slow +# description: Test histogram operator on TPC-H +# group: [aggregates] + +require tpch + +statement ok +CALL dbgen(sf=1); + +query I +SELECT histogram(l_orderkey, range(0, 7000000, 1000000)) +FROM lineitem +---- +{0=0, 1000000=1000049, 2000000=1000448, 3000000=999174, 4000000=1000987, 5000000=1000496, 6000000=1000061} + +query I +SELECT histogram(l_orderkey // 1000000) +FROM lineitem +---- +{0=1000048, 1=1000447, 2=999171, 3=1000989, 4=1000498, 5=1000060, 6=2} + +query I +SELECT histogram(l_shipdate, list_append(range((SELECT MIN(l_shipdate) FROM lineitem), (SELECT MAX(l_shipdate) FROM lineitem), interval '1' year), 'infinity'::timestamp)) +FROM lineitem +---- +{1992-01-02=17, 1993-01-02=761193, 1994-01-02=908785, 1995-01-02=909464, 1996-01-02=914963, 1997-01-02=913658, 1998-01-02=911349, infinity=681786} + +# grouped histogram +query II nosort grouped_map +SELECT l_returnflag, histogram(l_orderkey, range(0, 7000000, 1000000)) +FROM lineitem +GROUP BY l_returnflag +ORDER BY l_returnflag +---- + +# compute using filtered aggregates - this should produce the same result +query II nosort grouped_map +SELECT l_returnflag, + map { + '0': case when sum(1) filter(l_orderkey <= 0) is null then 0 end, + '1000000': sum(1) filter(l_orderkey > 0 and l_orderkey <= 1000000), + '2000000': sum(1) filter(l_orderkey > 1000000 and l_orderkey <= 2000000), + '3000000': sum(1) filter(l_orderkey > 2000000 and l_orderkey <= 3000000), + '4000000': sum(1) filter(l_orderkey > 3000000 and l_orderkey <= 4000000), + '5000000': sum(1) filter(l_orderkey > 4000000 and l_orderkey <= 5000000), + '6000000': sum(1) filter(l_orderkey > 5000000 and l_orderkey <= 6000000) + } +FROM lineitem +GROUP BY l_returnflag +ORDER BY l_returnflag +---- + +# histogram table function +# decimals +query II +SELECT bin, count FROM histogram(lineitem, l_extendedprice) +---- +x <= 15000.00 1188999 +15000.00 < x <= 25000.00 834011 +25000.00 < x <= 35000.00 833788 +35000.00 < x <= 45000.00 834114 +45000.00 < x <= 55000.00 798432 +55000.00 < x <= 65000.00 626547 +65000.00 < x <= 75000.00 439844 +75000.00 < x <= 85000.00 279917 +85000.00 < x <= 95000.00 139040 +95000.00 < x <= 105000.00 26523 + +# dates +query II +SELECT bin, count FROM histogram(lineitem, l_shipdate) +---- +x <= 1992-12-01 682114 +1992-12-01 < x <= 1993-08-01 603468 +1993-08-01 < x <= 1994-04-01 606065 +1994-04-01 < x <= 1994-12-01 608515 +1994-12-01 < x <= 1995-08-01 608265 +1995-08-01 < x <= 1996-04-01 609527 +1996-04-01 < x <= 1996-12-01 609621 +1996-12-01 < x <= 1997-08-01 607911 +1997-08-01 < x <= 1998-04-01 605815 +1998-04-01 < x <= 1998-12-01 459914 + +# varchar +query II +SELECT bin, count FROM histogram(lineitem, l_returnflag) +---- +A 1478493 +N 3043852 +R 1478870 + +# string stress test +query I nosort histstrings +SELECT unnest(map_keys(histogram(l_comment))) FROM lineitem +---- + +query I nosort histstrings +SELECT DISTINCT l_comment FROM lineitem ORDER BY l_comment +---- diff --git a/test/sql/aggregate/aggregates/mode_test_all_types.test_slow b/test/sql/aggregate/aggregates/mode_test_all_types.test_slow new file mode 100644 index 00000000000..4c2fdf568ce --- /dev/null +++ b/test/sql/aggregate/aggregates/mode_test_all_types.test_slow @@ -0,0 +1,29 @@ +# name: test/sql/aggregate/aggregates/mode_test_all_types.test_slow +# description: Test mode operator for all types +# group: [aggregates] + +statement ok +PRAGMA enable_verification + +statement ok +create table all_types as from test_all_types() + +foreach col bool tinyint smallint int bigint hugeint uhugeint utinyint usmallint uint ubigint date time timestamp timestamp_s timestamp_ms timestamp_ns time_tz timestamp_tz float double dec_4_1 dec_9_4 dec_18_6 dec38_10 uuid interval varchar blob bit small_enum medium_enum large_enum int_array double_array date_array timestamp_array timestamptz_array varchar_array nested_int_array struct struct_of_arrays array_of_structs map union fixed_int_array fixed_varchar_array fixed_nested_int_array fixed_nested_varchar_array fixed_struct_array struct_of_fixed_array fixed_array_of_int_list list_of_fixed_int_array + +query I +SELECT mode IS NOT DISTINCT FROM min_val FROM ( + SELECT MODE(v) AS mode, MIN(v) AS min_val + FROM (SELECT "${col}" AS v FROM all_types UNION ALL SELECT MIN("${col}"), FROM all_types) +) +---- +true + +query I +SELECT mode IS NOT DISTINCT FROM max_val FROM ( + SELECT MODE(v) AS mode, MAX(v) AS max_val + FROM (SELECT "${col}" AS v FROM all_types UNION ALL SELECT MAX("${col}"), FROM all_types) +) +---- +true + +endloop diff --git a/test/sql/aggregate/aggregates/mode_tpch.test_slow b/test/sql/aggregate/aggregates/mode_tpch.test_slow new file mode 100644 index 00000000000..2d86dc7a745 --- /dev/null +++ b/test/sql/aggregate/aggregates/mode_tpch.test_slow @@ -0,0 +1,34 @@ +# name: test/sql/aggregate/aggregates/mode_tpch.test_slow +# description: Test mode function with large data sets +# group: [aggregates] + +require tpch + +statement ok +CALL dbgen(sf=1); + +query II +select l_returnflag, mode(l_comment) from lineitem where l_returnflag <> 'N' group by l_returnflag; +---- +A furiously +R furiously + +# run a windowed mode +query I +SELECT avg(strlen(padded_mode)) FROM +(SELECT mode(l_comment) OVER (ORDER BY rowid ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING) AS padded_mode FROM lineitem) +---- +26.4927 + +# mode on nested types +query III +SELECT mode(l_shipdate), mode([l_shipdate]), mode({'i': l_shipdate}) from lineitem; +---- +1997-06-01 [1997-06-01] {'i': 1997-06-01} + +query IIII +SELECT l_returnflag, mode(l_shipdate), mode([l_shipdate]), mode({'i': l_shipdate}) from lineitem group by l_returnflag order by l_returnflag +---- +A 1995-03-24 [1995-03-24] {'i': 1995-03-24} +N 1997-06-01 [1997-06-01] {'i': 1997-06-01} +R 1994-08-23 [1994-08-23] {'i': 1994-08-23} diff --git a/test/sql/aggregate/aggregates/quantile_test_all_types.test_slow b/test/sql/aggregate/aggregates/quantile_test_all_types.test_slow new file mode 100644 index 00000000000..2e55298a0e7 --- /dev/null +++ b/test/sql/aggregate/aggregates/quantile_test_all_types.test_slow @@ -0,0 +1,26 @@ +# name: test/sql/aggregate/aggregates/quantile_test_all_types.test_slow +# description: Test quantile operator for all types +# group: [aggregates] + +statement ok +PRAGMA enable_verification + +statement ok +create table all_types as from test_all_types() + +foreach col bool tinyint smallint int bigint hugeint uhugeint utinyint usmallint uint ubigint time timestamp timestamp_s timestamp_ms timestamp_ns time_tz timestamp_tz float double dec_4_1 dec_9_4 dec_18_6 dec38_10 uuid interval varchar blob bit small_enum medium_enum large_enum int_array double_array date_array timestamp_array timestamptz_array varchar_array nested_int_array struct struct_of_arrays array_of_structs map union fixed_int_array fixed_varchar_array fixed_nested_int_array fixed_nested_varchar_array fixed_struct_array struct_of_fixed_array fixed_array_of_int_list list_of_fixed_int_array + +# quantile_disc +query III +SELECT quantile_disc("${col}", 0.2) IS NOT DISTINCT FROM MIN("${col}"), + quantile_disc("${col}", 0.8) IS NOT DISTINCT FROM MAX("${col}"), + quantile_disc("${col}", [0.8, 0.2]) IS NOT DISTINCT FROM [MAX("${col}"), MIN("${col}")] +FROM all_types +---- +true true true + +# median +statement ok +SELECT median("${col}") >= min("${col}") AND median("${col}") <= max("${col}") FROM all_types + +endloop diff --git a/test/sql/aggregate/aggregates/test_approx_quantile.test b/test/sql/aggregate/aggregates/test_approx_quantile.test index daffb0c20f5..20253584d5f 100644 --- a/test/sql/aggregate/aggregates/test_approx_quantile.test +++ b/test/sql/aggregate/aggregates/test_approx_quantile.test @@ -141,6 +141,19 @@ FROM ( ---- [true, true, true] +# Array lists +query I +SELECT approx_quantile(col, [0.5, 0.4, 0.1]) AS percentile +FROM VALUES (0), (1), (2), (10) AS tab(col); +---- +[2, 1, 0] + +query I +SELECT approx_quantile(col, ARRAY_VALUE(0.5, 0.4, 0.1)) AS percentile +FROM VALUES (0), (1), (2), (10) AS tab(col); +---- +[2, 1, 0] + # Errors statement error SELECT approx_quantile(r, -0.1) FROM quantile @@ -170,6 +183,11 @@ statement error SELECT approx_quantile(r, 0.1, 0.2) FROM quantile ---- +statement error +SELECT approx_quantile(42, CAST(NULL AS INT[])); +---- +APPROXIMATE QUANTILE parameter list cannot be NULL + statement ok pragma threads=4 @@ -266,3 +284,9 @@ SELECT reservoir_quantile(r, random()::float) from quantile statement error SELECT reservoir_quantile(r, 0.9, random()::float) from quantile ---- + +# DECIMAL binding +query I +SELECT RESERVOIR_QUANTILE(0., 0.9, 1000); +---- +0 diff --git a/test/sql/aggregate/aggregates/test_approximate_distinct_count.test b/test/sql/aggregate/aggregates/test_approximate_distinct_count.test index c9cc5fa0f3d..bd9b8bf43d9 100644 --- a/test/sql/aggregate/aggregates/test_approximate_distinct_count.test +++ b/test/sql/aggregate/aggregates/test_approximate_distinct_count.test @@ -62,13 +62,13 @@ create table t as select range a, mod(range,10) b from range(2000); query III SELECT COUNT( a),approx_count_distinct(a),approx_count_distinct(b) from t ---- -2000 1991 10 +2000 2322 11 query I SELECT approx_count_distinct(a) from t group by a %2 order by all; ---- -986 -993 +1006 +1230 query I SELECT count(*) from t where a < 10; @@ -92,7 +92,7 @@ SELECT approx_count_distinct(a) over (partition by a%2) from t where a < 10; query II SELECT COUNT( t),approx_count_distinct(t) from timestamp ---- -7 7 +7 6 query II SELECT COUNT( t),approx_count_distinct(t) from dates diff --git a/test/sql/aggregate/aggregates/test_arg_min_max.test b/test/sql/aggregate/aggregates/test_arg_min_max.test index 906c80db81e..23fa937af1a 100644 --- a/test/sql/aggregate/aggregates/test_arg_min_max.test +++ b/test/sql/aggregate/aggregates/test_arg_min_max.test @@ -158,3 +158,38 @@ query II select arg_min(name,salary),arg_max(name,salary) from names; ---- Pedro Hubert-Blaine-Wolfeschlegelsteinhausenbergerdorff + +statement ok +CREATE OR REPLACE TABLE employees( + employee_id NUMERIC, + department_id NUMERIC, + salary NUMERIC); + +statement ok +INSERT INTO employees VALUES + (1001, 10, 10000), + (1020, 10, 9000), + (1030, 10, 8000), + (900, 20, 15000), + (2000, 20, NULL), + (2010, 20, 15000), + (2020, 20, 8000); + +foreach casting true false + +statement ok +SET old_implicit_casting=${casting}; + +query I +SELECT MAX_BY(employee_id, salary) as employee_with_biggest_salary +FROM employees; +---- +900 + +query I +SELECT MIN_BY(employee_id, salary) as employee_with_least_salary +FROM employees; +---- +1030 + +endloop diff --git a/test/sql/aggregate/aggregates/test_arg_min_max_nested.test b/test/sql/aggregate/aggregates/test_arg_min_max_nested.test_slow similarity index 99% rename from test/sql/aggregate/aggregates/test_arg_min_max_nested.test rename to test/sql/aggregate/aggregates/test_arg_min_max_nested.test_slow index 4016d042176..0ade396048f 100644 --- a/test/sql/aggregate/aggregates/test_arg_min_max_nested.test +++ b/test/sql/aggregate/aggregates/test_arg_min_max_nested.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/aggregate/aggregates/test_arg_min_max_nested.test +# name: test/sql/aggregate/aggregates/test_arg_min_max_nested.test_slow # description: Test arg_min/arg_max with nested types # group: [aggregates] diff --git a/test/sql/aggregate/aggregates/test_arg_min_max_null_nested.test b/test/sql/aggregate/aggregates/test_arg_min_max_null_nested.test_slow similarity index 99% rename from test/sql/aggregate/aggregates/test_arg_min_max_null_nested.test rename to test/sql/aggregate/aggregates/test_arg_min_max_null_nested.test_slow index e0aa31cdb8b..42810d7eabc 100644 --- a/test/sql/aggregate/aggregates/test_arg_min_max_null_nested.test +++ b/test/sql/aggregate/aggregates/test_arg_min_max_null_nested.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/aggregate/aggregates/test_arg_min_max_null_nested.test +# name: test/sql/aggregate/aggregates/test_arg_min_max_null_nested.test_slow # description: Test arg_min_null/arg_max_null with nested types # group: [aggregates] diff --git a/test/sql/aggregate/aggregates/test_arg_min_max_null_strings.test b/test/sql/aggregate/aggregates/test_arg_min_max_null_strings.test_slow similarity index 99% rename from test/sql/aggregate/aggregates/test_arg_min_max_null_strings.test rename to test/sql/aggregate/aggregates/test_arg_min_max_null_strings.test_slow index 345844bb30a..438e79b122e 100644 --- a/test/sql/aggregate/aggregates/test_arg_min_max_null_strings.test +++ b/test/sql/aggregate/aggregates/test_arg_min_max_null_strings.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/aggregate/aggregates/test_arg_min_max_null_strings.test +# name: test/sql/aggregate/aggregates/test_arg_min_max_null_strings.test_slow # description: Test arg_min_null/arg_max_null with strings # group: [aggregates] diff --git a/test/sql/aggregate/aggregates/test_binned_histogram.test b/test/sql/aggregate/aggregates/test_binned_histogram.test new file mode 100644 index 00000000000..7a9ef36a64c --- /dev/null +++ b/test/sql/aggregate/aggregates/test_binned_histogram.test @@ -0,0 +1,122 @@ +# name: test/sql/aggregate/aggregates/test_binned_histogram.test +# description: Test binned histograms +# group: [aggregates] + +statement ok +PRAGMA enable_verification + +statement ok +CREATE TABLE obs(n BIGINT); + +statement ok +INSERT INTO obs VALUES (0), (5), (7), (12), (20), (23), (24), (25), (26), (28), (31), (34), (36), (41), (47) + +query I +SELECT histogram(n, [10, 20, 30, 40, 50]) FROM obs +---- +{10=3, 20=2, 30=5, 40=3, 50=2} + +# empty bins +query I +SELECT histogram(n, []) FROM obs +---- +{} + +# bounds that are not sorted +query I +SELECT histogram(n, [10, 40, 50, 30, 20]) FROM obs +---- +{10=3, 20=2, 30=5, 40=3, 50=2} + +# grouped aggregation +# uneven: 5, 7, 23, 25, 31, 41, 47 +# even: 0, 12, 20, 24, 26, 28, 34, 36 +query II +SELECT n%2=0 is_even, histogram(n, [10, 20, 30, 40, 50]) FROM obs GROUP BY is_even ORDER BY is_even +---- +false {10=2, 20=0, 30=2, 40=1, 50=2} +true {10=1, 20=2, 30=3, 40=2, 50=0} + +# different bounds per group +query II +SELECT n%2=0 is_even, histogram(n, case when n%2=0 then [10, 20, 30, 40, 50] else [11, 21, 31, 41, 51] end) FROM obs GROUP BY is_even ORDER BY is_even +---- +0 {11=2, 21=0, 31=3, 41=1, 51=1} +1 {10=1, 20=2, 30=3, 40=2, 50=0} + +# values bigger than the max bin are ignored +query I +SELECT histogram(n, [10, 20, 30, 40, 50]) FROM obs +---- +{10=3, 20=2, 30=5, 40=3, 50=2} + +# larger bins +query I +SELECT histogram(i, range(999, 10000, 1000)) FROM range(10000) t(i) +---- +{999=1000, 1999=1000, 2999=1000, 3999=1000, 4999=1000, 5999=1000, 6999=1000, 7999=1000, 8999=1000, 9999=1000} + +# extreme values +query I +SELECT histogram(v, [-9223372036854775808, -9223372036854775807, 9223372036854775807]) FROM +(VALUES (-9223372036854775808), (-9223372036854775807), (0), (9223372036854775807)) t(v) +---- +{-9223372036854775808=1, -9223372036854775807=1, 9223372036854775807=2} + +# extreme doubles/negative values +query I +SELECT histogram(v, ['-infinity'::double, -10, 0, 10, 'infinity']) FROM +(VALUES (-1e308), (-0.5), (0), ('inf'), ('-inf'), (0.5)) t(v) +---- +{-inf=1, -10.0=1, 0.0=2, 10.0=1, inf=1} + +# timestamps +query I +SELECT histogram(v, range(timestamp '2000-01-01', timestamp '2005-01-01', interval '1 year')) FROM +(VALUES (timestamp '2000-01-01'), (timestamp '2003-01-01')) t(v) +---- +{2000-01-01 00:00:00=1, 2001-01-01 00:00:00=0, 2002-01-01 00:00:00=0, 2003-01-01 00:00:00=1, 2004-01-01 00:00:00=0} + +# strings +query I +SELECT histogram(v, ['a', 'b', 'c', 'z']) FROM +(VALUES ('a'), ('aaaa'), ('b'), ('c'), ('d')) t(v) +---- +{a=1, b=2, c=1, z=1} + +# non-inlined strings +query I +SELECT histogram(concat('thisisalongprefix_', v), ['thisisalongprefix_'||x for x in ['a', 'b', 'c', 'z']]) FROM +(VALUES ('a'), ('aaaa'), ('b'), ('c'), ('d')) t(v) +---- +{thisisalongprefix_a=1, thisisalongprefix_b=2, thisisalongprefix_c=1, thisisalongprefix_z=1} + +# structs +query I +SELECT histogram({'i': n}, [{'i': x} for x in [10, 20, 30, 40, 50]]) FROM obs +---- +{{'i': 10}=3, {'i': 20}=2, {'i': 30}=5, {'i': 40}=3, {'i': 50}=2} + +# lists +query I +SELECT histogram([n], [[x] for x in [10, 20, 30, 40, 50]]) FROM obs +---- +{[10]=3, [20]=2, [30]=5, [40]=3, [50]=2} + +# duplicate bounds in bins +query I +SELECT histogram(n, [10, 10, 10, 10]) FROM obs +---- +{10=3} + +# null WITHIN bins +statement error +SELECT histogram(n, [10, 20, NULL]) FROM obs +---- +Histogram bin entry cannot be NULL + +# NULL bins +statement error +SELECT histogram(n, NULL::BIGINT[]) FROM obs +---- +Histogram bin list cannot be NULL diff --git a/test/sql/aggregate/aggregates/test_histogram.test b/test/sql/aggregate/aggregates/test_histogram.test index 75af60b5645..aba8d0fb18f 100644 --- a/test/sql/aggregate/aggregates/test_histogram.test +++ b/test/sql/aggregate/aggregates/test_histogram.test @@ -143,4 +143,4 @@ INSERT INTO enums VALUES ('happy'), ('ok') query I SELECT histogram(e) FROM enums ---- -{happy=1, ok=1} +{ok=1, happy=1} diff --git a/test/sql/aggregate/aggregates/test_median.test b/test/sql/aggregate/aggregates/test_median.test index ce37f85f82c..6502370773c 100644 --- a/test/sql/aggregate/aggregates/test_median.test +++ b/test/sql/aggregate/aggregates/test_median.test @@ -70,7 +70,30 @@ SELECT median(r::hugeint) FROM quantile query I SELECT median(r::decimal(10,2)) FROM quantile ---- -4999 +4999.50 + +query I +SELECT median(case when r is null then null else [r] end) FROM quantile +---- +[4999] + +query I +SELECT median(case when r is null then null else {'i': r} end) FROM quantile +---- +{'i': 4999} + +# sorting order is different for varchars and numbers +# so a different result here is expected +query I +SELECT median(r::varchar) FROM quantile +---- +5498 + +# adding a prefix +query I +SELECT median(case when r is null then null else concat('thishasalongprefix_', r::varchar) end) FROM quantile +---- +thishasalongprefix_5498 query I SELECT median(NULL) FROM quantile diff --git a/test/sql/aggregate/aggregates/test_minmax.test b/test/sql/aggregate/aggregates/test_minmax.test index 9d00b3c856e..f34432928e7 100644 --- a/test/sql/aggregate/aggregates/test_minmax.test +++ b/test/sql/aggregate/aggregates/test_minmax.test @@ -1,5 +1,5 @@ # name: test/sql/aggregate/aggregates/test_minmax.test -# description: Test MEDIAN aggregate +# description: Test min/max aggregate # group: [aggregates] statement ok diff --git a/test/sql/aggregate/aggregates/test_quantile_disc.test b/test/sql/aggregate/aggregates/test_quantile_disc.test index 53a5c4acac5..e507b8886ad 100644 --- a/test/sql/aggregate/aggregates/test_quantile_disc.test +++ b/test/sql/aggregate/aggregates/test_quantile_disc.test @@ -28,6 +28,16 @@ SELECT quantile_disc(r::decimal(10,2), 0.5) FROM quantile ---- 4999 +query I +SELECT quantile_disc(case when r is null then null else [r] end, 0.5) FROM quantile +---- +[4999] + +query I +SELECT quantile_disc(case when r is null then null else {'i': r} end, 0.5) FROM quantile +---- +{'i': 4999} + query I SELECT quantile_disc(r, 1.0) FROM quantile ---- diff --git a/test/sql/aggregate/aggregates/test_quantile_disc_list.test b/test/sql/aggregate/aggregates/test_quantile_disc_list.test index fd03d04d756..8014c9c219a 100644 --- a/test/sql/aggregate/aggregates/test_quantile_disc_list.test +++ b/test/sql/aggregate/aggregates/test_quantile_disc_list.test @@ -21,6 +21,16 @@ SELECT quantile_disc(r, [0.1, 0.5, 0.9]) FROM quantiles ---- [999, 4999, 8999] +query I +SELECT quantile_disc(case when r is null then null else [r] end, [0.1, 0.5, 0.9]) FROM quantiles +---- +[[999], [4999], [8999]] + +query I +SELECT quantile_disc(case when r is null then null else {'i': r} end, [0.1, 0.5, 0.9]) FROM quantiles +---- +[{'i': 999}, {'i': 4999}, {'i': 8999}] + foreach type decimal(4,1) decimal(8,1) decimal(12,1) decimal(18,1) decimal(24,1) query I @@ -165,6 +175,13 @@ SELECT quantile_disc(42::UTINYINT, 0.5); ---- 42 +# Array arguments +query I +SELECT quantile_disc(col, ARRAY_VALUE(0.5, 0.4, 0.1)) AS percentile +FROM VALUES (0), (1), (2), (10) AS tab(col); +---- +[1, 1, 0] + # Invalid use statement error SELECT quantile_disc(r, [-0.1, 0.5, 0.9]) FROM quantiles diff --git a/test/sql/aggregate/aggregates/test_state_export.test b/test/sql/aggregate/aggregates/test_state_export.test index c9a03f028b8..64980e3e278 100644 --- a/test/sql/aggregate/aggregates/test_state_export.test +++ b/test/sql/aggregate/aggregates/test_state_export.test @@ -111,6 +111,10 @@ SELECT finalize(count(*) EXPORT_STATE), finalize(count(d) EXPORT_STATE), finaliz # more aggregates +# we skip these for now as argmin/argmax now has a custom binder (so that it can work with extension types like JSON) +# otherwise we get "Binder Error: Cannot use EXPORT_STATE on aggregate functions with custom binders" +mode skip + query II nosort res7 select argmin(a,b), argmax(a,b) from (values (1,1), (2,2), (8,8), (10,10)) s(a,b); ---- @@ -119,6 +123,8 @@ query II nosort res7 select FINALIZE(argmin(a,b) EXPORT_STATE), FINALIZE(argmax(a,b) EXPORT_STATE) from (values (1,1), (2,2), (8,8), (10,10)) s(a,b); ---- +mode unskip + query IIIIIII nosort res8 SELECT g, first(d), last(d), fsum(d), favg(d), product(d), bit_xor(d), bool_and(d > 5) FROM dummy GROUP BY g ORDER BY g; ---- diff --git a/test/sql/aggregate/aggregates/test_string_agg.test b/test/sql/aggregate/aggregates/test_string_agg.test index 2ed047711f2..5571866ad2f 100644 --- a/test/sql/aggregate/aggregates/test_string_agg.test +++ b/test/sql/aggregate/aggregates/test_string_agg.test @@ -193,3 +193,41 @@ ORDER BY 1 NULLS LAST 2 1,2 3 1,2,3 NULL NULL + +# DISTINCT + ORDER BY on non-volatile functional dependencies +query I +SELECT string_agg(DISTINCT CellType, '&' ORDER BY list_position(['L900','L1800','L2100','L2600'], CellType)) +FROM (VALUES + ('L900'), + ('L2600'), + ('L2100'), + ('L2100'), + ('L1800') + ) AS t(CellType); +---- +L900&L1800&L2100&L2600 + +# DISTINCT + ORDER BY on volatile functional dependencies +statement error +SELECT first(DISTINCT i ORDER BY random() * i) +FROM (VALUES + (900), + (2600), + (2100), + (2100), + (1800) + ) AS t(i); +---- +Binder Error: In a DISTINCT aggregate, ORDER BY expressions must appear in the argument list + +statement error +SELECT first(DISTINCT random() * i ORDER BY i) +FROM (VALUES + (900), + (2600), + (2100), + (2100), + (1800) + ) AS t(i); +---- +Binder Error: In a DISTINCT aggregate, ORDER BY expressions must appear in the argument list diff --git a/test/sql/aggregate/distinct/grouped/distinct_and_non_distinct_mixed.test b/test/sql/aggregate/distinct/grouped/distinct_and_non_distinct_mixed.test_slow similarity index 99% rename from test/sql/aggregate/distinct/grouped/distinct_and_non_distinct_mixed.test rename to test/sql/aggregate/distinct/grouped/distinct_and_non_distinct_mixed.test_slow index a37e298cf2d..bcd884ea433 100644 --- a/test/sql/aggregate/distinct/grouped/distinct_and_non_distinct_mixed.test +++ b/test/sql/aggregate/distinct/grouped/distinct_and_non_distinct_mixed.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/aggregate/distinct/grouped/distinct_and_non_distinct_mixed.test +# name: test/sql/aggregate/distinct/grouped/distinct_and_non_distinct_mixed.test_slow # description: DISTINCT aggregations # group: [grouped] diff --git a/test/sql/aggregate/distinct/grouped/multiple_grouping_sets.test b/test/sql/aggregate/distinct/grouped/multiple_grouping_sets.test index 11eb24d2cbc..7431e380784 100644 --- a/test/sql/aggregate/distinct/grouped/multiple_grouping_sets.test +++ b/test/sql/aggregate/distinct/grouped/multiple_grouping_sets.test @@ -268,3 +268,16 @@ select sum(distinct value), count(*), course, type 10 7 NULL NULL 25 2 Math NULL 30 2 NULL Bachelor + +# re-do the first query with one thread (internal issue 2046) +statement ok +set threads=1 + +query IIII +select course, type, count(*), sum(distinct value) from students group by course, type order by all; +---- +CS NULL 2 -5 +CS Bachelor 2 30 +CS PhD 1 -20 +Math NULL 1 15 +Math Masters 1 10 \ No newline at end of file diff --git a/test/sql/aggregate/qualify/test_qualify_view.test b/test/sql/aggregate/qualify/test_qualify_view.test index e054aa9c304..7f654524853 100644 --- a/test/sql/aggregate/qualify/test_qualify_view.test +++ b/test/sql/aggregate/qualify/test_qualify_view.test @@ -7,6 +7,9 @@ require skip_reload # load the DB from disk load __TEST_DIR__/view_storage.db +statement ok +set enable_view_dependencies=true + statement ok PRAGMA disable_checkpoint_on_shutdown @@ -37,21 +40,29 @@ ORDER BY ALL 22 11 # drop the table the view is based on -statement ok +statement error DROP TABLE test.t +---- +view "v" depends on table "t". + +statement ok +DROP TABLE test.t CASCADE; loop i 0 2 # restart the system restart -# after recreating the table, we can query the view again +# we first need to recreate both the table and the view before we can query it again statement ok CREATE TABLE test.t (a INTEGER, b INTEGER); statement ok INSERT INTO test.t VALUES (11, 22), (13, 22), (12, 21) +statement ok +CREATE VIEW test.v AS SELECT * FROM test.t QUALIFY row_number() OVER (PARTITION BY b) = 1; + query II SELECT b, SUM(a) FROM test.v @@ -64,10 +75,12 @@ ORDER BY ALL # drop the table again statement ok -DROP TABLE test.t +DROP TABLE test.t CASCADE; +# dropping the table also caused the view to be dropped statement error SELECT * FROM test.v ---- +Catalog Error: Table with name v does not exist! endloop diff --git a/test/sql/aggregate/qualify/test_qualify_view_no_view_dependencies.test b/test/sql/aggregate/qualify/test_qualify_view_no_view_dependencies.test new file mode 100644 index 00000000000..83d4c966975 --- /dev/null +++ b/test/sql/aggregate/qualify/test_qualify_view_no_view_dependencies.test @@ -0,0 +1,73 @@ +# name: test/sql/aggregate/qualify/test_qualify_view_no_view_dependencies.test +# description: Test QUALIFY clause in a view over different runs +# group: [qualify] + +require skip_reload + +# load the DB from disk +load __TEST_DIR__/view_storage.db + +statement ok +PRAGMA disable_checkpoint_on_shutdown + +statement ok +PRAGMA wal_autocheckpoint='1TB'; + +# create a schema and view +statement ok +CREATE SCHEMA test; + +statement ok +CREATE TABLE test.t (a INTEGER, b INTEGER); + +statement ok +INSERT INTO test.t VALUES (11, 22), (13, 22), (12, 21) + +statement ok +CREATE VIEW test.v AS SELECT * FROM test.t QUALIFY row_number() OVER (PARTITION BY b) = 1; + +query II +SELECT b, SUM(a) +FROM test.v +GROUP BY b +QUALIFY row_number() OVER (PARTITION BY b) = 1 +ORDER BY ALL +---- +21 12 +22 11 + +# drop the table the view is based on +statement ok +DROP TABLE test.t + +loop i 0 2 + +# restart the system +restart + +# after recreating the table, we can query the view again +statement ok +CREATE TABLE test.t (a INTEGER, b INTEGER); + +statement ok +INSERT INTO test.t VALUES (11, 22), (13, 22), (12, 21) + +query II +SELECT b, SUM(a) +FROM test.v +GROUP BY b +QUALIFY row_number() OVER (PARTITION BY b) = 1 +ORDER BY ALL +---- +21 12 +22 11 + +# drop the table again +statement ok +DROP TABLE test.t + +statement error +SELECT * FROM test.v +---- + +endloop diff --git a/test/sql/alter/rename_table/test_rename_table_with_dependency_check.test b/test/sql/alter/rename_table/test_rename_table_with_dependency_check.test index 8f505ab28dc..6dce4f3b7c9 100644 --- a/test/sql/alter/rename_table/test_rename_table_with_dependency_check.test +++ b/test/sql/alter/rename_table/test_rename_table_with_dependency_check.test @@ -8,24 +8,24 @@ CREATE TABLE t0 (c0 INT); statement ok CREATE UNIQUE INDEX i1 ON t0 (c0); -# Cannot alter entry "t0" because there are entries that depend on it statement error ALTER TABLE t0 RENAME TO t3; ---- +Cannot alter entry "t0" because there are entries that depend on it # t3 is not exist statement ok CREATE TABLE t3 (c0 INT); -# Cannot alter entry "t0" because there are entries that depend on it statement error ALTER TABLE t0 RENAME TO t4; ---- +Cannot alter entry "t0" because there are entries that depend on it statement ok DROP TABLE t0; -# t4 is not exist statement error ANALYZE t4; ---- +Table with name t4 does not exist! diff --git a/test/sql/attach/attach_checkpoint_deadlock.test_slow b/test/sql/attach/attach_checkpoint_deadlock.test_slow index b6b9784ac9f..c14147e074f 100644 --- a/test/sql/attach/attach_checkpoint_deadlock.test_slow +++ b/test/sql/attach/attach_checkpoint_deadlock.test_slow @@ -20,7 +20,7 @@ insert into ${dbname}.${dbname} select sum(i) from range(1000000) t(i) statement maybe checkpoint ${dbname} ---- -there are other transactions +there are other write transactions statement ok select diff --git a/test/sql/attach/attach_concurrent_checkpoint.test_slow b/test/sql/attach/attach_concurrent_checkpoint.test_slow index 761f30f05e4..1b5bd4543ec 100644 --- a/test/sql/attach/attach_concurrent_checkpoint.test_slow +++ b/test/sql/attach/attach_concurrent_checkpoint.test_slow @@ -20,7 +20,7 @@ INSERT INTO db.integers FROM range(1000000); statement maybe CHECKPOINT db ---- -there are other transactions +other write transactions active endloop diff --git a/test/sql/attach/attach_create_index.test b/test/sql/attach/attach_create_index.test new file mode 100644 index 00000000000..1dbd031ae73 --- /dev/null +++ b/test/sql/attach/attach_create_index.test @@ -0,0 +1,14 @@ +# name: test/sql/attach/attach_create_index.test +# description: Test create index on an attached database with an alias +# group: [attach] + +require skip_reload + +statement ok +ATTACH '' AS tmp; + +statement ok +CREATE TABLE tmp.t1(id int); + +statement ok +CREATE INDEX idx ON tmp.t1(id); diff --git a/test/sql/attach/attach_custom_block_size.test b/test/sql/attach/attach_custom_block_size.test new file mode 100644 index 00000000000..5bba30851ca --- /dev/null +++ b/test/sql/attach/attach_custom_block_size.test @@ -0,0 +1,85 @@ +# name: test/sql/attach/attach_custom_block_size.test +# description: Tests attaching database files with different block allocation sizes. +# group: [attach] + +# We currently throw 'Not implemented' exceptions for other block sizes. +require block_size 262144 + +require skip_reload + +statement ok +PRAGMA enable_verification + +statement error +ATTACH '__TEST_DIR__/not_pow_of_two.db' (BLOCK_SIZE 123456); +---- +must be a power of two + +statement error +ATTACH '__TEST_DIR__/exceeds_maximum.db' (BLOCK_SIZE 2147483648); +---- +the block size must not be greater than the maximum 32-bit signed integer value + +# FIXME: once we implement this feature, we expect this to work +statement error +ATTACH '__TEST_DIR__/not_default.db' (BLOCK_SIZE 16384); +---- +Not implemented + +statement error +ATTACH '__TEST_DIR__/too_small.db' (BLOCK_SIZE 128); +---- +must be greater or equal than the minimum + +# default block allocation size works + +statement ok +ATTACH '__TEST_DIR__/default_size.db' (BLOCK_SIZE 262144); + +# detach and then try to attach with a different block size parameter +statement ok +DETACH default_size; + +# FIXME: once we implement this feature, we expect this to fail because the file +# FIXME: already exists with a different block allocation size +statement error +ATTACH '__TEST_DIR__/default_size.dbe' (BLOCK_SIZE 16384); +---- +not supported + +statement ok +ATTACH '__TEST_DIR__/default_size.db'; + +statement ok +DETACH default_size; + +# FIXME: once we implement the custom block size feature, we expect this to work. +# We detect the block allocation size in the header. +# ATTACH 'dbname.db' (BLOCK_SIZE 16384); +# DETACH dbname; +# ATTACH 'dbname.db'; + +statement error +SET default_block_size = '123456'; +---- +must be a power of two + +statement error +SET default_block_size = '16384'; +---- +Not implemented + +statement error +SET default_block_size = '128'; +---- +must be greater or equal than the minimum + +statement ok +SET default_block_size = '262144'; + +statement ok +ATTACH '__TEST_DIR__/default_size.db'; + +# FIXME: once we implement the custom block size feature, we need a test that (in a tx) attaches a new +# database file. Then, we ROLLBACK the transaction. Then, we attach the same file with a different block size. +# We'll create an error in SingleFileStorageManager::LoadDatabase, as we do not remove the file on ROLLBACK. \ No newline at end of file diff --git a/test/sql/attach/attach_huggingface_index.test b/test/sql/attach/attach_huggingface_index.test new file mode 100644 index 00000000000..614d13003ac --- /dev/null +++ b/test/sql/attach/attach_huggingface_index.test @@ -0,0 +1,15 @@ +# name: test/sql/attach/attach_huggingface_index.test +# description: Test attach mixed with sequences and default values +# group: [attach] + +require skip_reload + +# database is written with vector size of 2048 +require vector_size 2048 + +require block_size 262144 + +unzip data/storage/huggingface_index.db.gz __TEST_DIR__/huggingface_index.db + +statement ok +ATTACH '__TEST_DIR__/huggingface_index.db' \ No newline at end of file diff --git a/test/sql/attach/attach_icu_collation.test b/test/sql/attach/attach_icu_collation.test new file mode 100644 index 00000000000..db8cc389d1e --- /dev/null +++ b/test/sql/attach/attach_icu_collation.test @@ -0,0 +1,45 @@ +# name: test/sql/attach/attach_icu_collation.test +# description: ATTACH to a database that uses ICU collations in types +# group: [attach] + +require skip_reload + +require no_extension_autoloading + +# database is written with vector size of 2048 +require vector_size 2048 + +require block_size 262144 + +unzip data/storage/german_collation.db.gz __TEST_DIR__/german_collation.db + +statement ok +ATTACH '__TEST_DIR__/german_collation.db' AS db + +query I rowsort +SELECT * FROM db.strings +---- +Gabel +Goethe +Goldmann +Göbel +Göthe +Götz + +# cannot order by without ICU +statement error +SELECT * FROM db.strings ORDER BY 1 +---- +not in the catalog + +require icu + +query I +SELECT * FROM db.strings ORDER BY 1 +---- +Gabel +Göbel +Goethe +Goldmann +Göthe +Götz diff --git a/test/sql/attach/attach_read_only_transaction.test b/test/sql/attach/attach_read_only_transaction.test new file mode 100644 index 00000000000..b5ab4949f42 --- /dev/null +++ b/test/sql/attach/attach_read_only_transaction.test @@ -0,0 +1,33 @@ +# name: test/sql/attach/attach_read_only_transaction.test +# description: Test attach with explicit READ ONLY transactions +# group: [attach] + +require skip_reload + +statement ok +PRAGMA enable_verification + +statement ok +ATTACH ':memory:' AS db1; + +statement ok +CREATE TABLE db1.integers(i INTEGER); + +statement ok +INSERT INTO db1.integers VALUES (42); + +statement ok +BEGIN TRANSACTION READ ONLY + +query I +FROM db1.integers +---- +42 + +statement error +INSERT INTO db1.integers VALUES (48) +---- +transaction is launched in read-only mode + +statement ok +COMMIT \ No newline at end of file diff --git a/test/sql/attach/attach_remote.test b/test/sql/attach/attach_remote.test new file mode 100644 index 00000000000..1745c85afc3 --- /dev/null +++ b/test/sql/attach/attach_remote.test @@ -0,0 +1,20 @@ +# name: test/sql/attach/attach_remote.test +# description: Test attaching of remote database +# group: [attach] + +require httpfs + +statement error +ATTACH 'https://duckdb.org/non_existing.db' AS db2 (READ_ONLY) +---- +IO Error: Cannot open database "https://duckdb.org/non_existing.db" in read-only mode: database does not exist + +statement error +ATTACH 'https://duckdb.org/non_existing.db' AS db2 +---- +IO Error: Cannot open database "https://duckdb.org/non_existing.db" in read-only mode: database does not exist + +statement error +ATTACH 'https://duckdb.org/non_existing.db' AS db2 (READ_WRITE) +---- +Not implemented Error: Writing to HTTP files not implemented diff --git a/test/sql/attach/attach_reserved.test b/test/sql/attach/attach_reserved.test index 986f7801ce2..f1a4709ec6b 100644 --- a/test/sql/attach/attach_reserved.test +++ b/test/sql/attach/attach_reserved.test @@ -18,6 +18,16 @@ CREATE TABLE temp_db.integers(i INTEGER); statement ok DETACH temp_db; +# attach a new database called temp +statement ok +ATTACH DATABASE '__TEST_DIR__/system.db'; + +statement ok +CREATE TABLE system_db.integers(i INTEGER); + +statement ok +DETACH system_db; + # explicitly selecting these aliases leads to an error statement error ATTACH DATABASE ':memory:' AS temp; @@ -28,3 +38,8 @@ statement error ATTACH DATABASE ':memory:' AS main; ---- reserved name + +statement error +ATTACH DATABASE ':memory:' AS system; +---- +reserved name diff --git a/test/sql/attach/attach_s3_tpch.test_slow b/test/sql/attach/attach_s3_tpch.test_slow index 76f895cad61..68a1cb2bda0 100644 --- a/test/sql/attach/attach_s3_tpch.test_slow +++ b/test/sql/attach/attach_s3_tpch.test_slow @@ -55,3 +55,20 @@ PRAGMA tpch(${i}) :extension/tpch/dbgen/answers/sf1/q${i}.csv endloop + +statement ok +USE memory + +statement ok +DETACH db + +statement ok +ATTACH 's3://test-bucket/presigned/lineitem_sf1.db' AS db (READONLY 1); + +statement ok +USE db + +query IIIIIIIIIIIIIIII +select count(distinct columns(*)) from lineitem; +---- +1500000 200000 10000 7 50 933900 11 9 3 2 2526 2466 2554 4 7 3610733 diff --git a/test/sql/attach/attach_wal_alter.test b/test/sql/attach/attach_wal_alter.test new file mode 100644 index 00000000000..5a67e68f995 --- /dev/null +++ b/test/sql/attach/attach_wal_alter.test @@ -0,0 +1,49 @@ +# name: test/sql/attach/attach_wal_alter.test +# description: WAL cannot alter table +# group: [attach] + +require skip_reload + +statement ok +PRAGMA enable_verification + +statement ok +ATTACH DATABASE '__TEST_DIR__/wal_crash.db' as db1; + +statement ok +USE db1; + +statement ok +CREATE TABLE t2(c1 INT); + +statement ok +CHECKPOINT; + +statement ok +SET wal_autocheckpoint='1TB'; + +statement ok +PRAGMA disable_checkpoint_on_shutdown; + +statement ok +ALTER TABLE t2 ALTER c1 SET DEFAULT 0; + +statement ok +ATTACH DATABASE ':memory:' as db2; + +statement ok +USE db2; + +statement ok +detach db1; + +statement ok +ATTACH DATABASE '__TEST_DIR__/wal_crash.db' as db1; + +statement ok +INSERT INTO db1.t2 DEFAULT VALUES + +query I +SELECT * FROM db1.t2 +---- +0 diff --git a/test/sql/binder/order_by_view.test b/test/sql/binder/order_by_view.test index bea21976777..e3cf4272d9e 100644 --- a/test/sql/binder/order_by_view.test +++ b/test/sql/binder/order_by_view.test @@ -9,7 +9,35 @@ statement ok CREATE TABLE src("Name" VARCHAR, CreatedAt TIMESTAMP, userID VARCHAR, "Version" VARCHAR, Clients BIGINT, HasDocumentation BOOLEAN, HasCustomAddress BOOLEAN, HasHostname BOOLEAN, RunningContainers BIGINT, HasActions BOOLEAN); statement ok -CREATE VIEW model AS SELECT DISTINCT on(userID, date_trunc('day', CreatedAt)) date_trunc('day', CreatedAt) AS CreatedAt, "Version", Clients, HasCustomAddress, HasHostname, RunningContainers, HasDocumentation, HasActions FROM src WHERE name = 'events' ORDER BY userID, CreatedAt DESC; +CREATE VIEW model AS + SELECT DISTINCT on(userID, date_trunc('day', CreatedAt)) + date_trunc('day', CreatedAt) AS CreatedAt, + "Version", + Clients, + HasCustomAddress, + HasHostname, + RunningContainers, + HasDocumentation, + HasActions +FROM src +WHERE name = 'events' +ORDER BY userID, CreatedAt DESC; statement ok -SELECT HasCustomAddress,count(*) AS total_records FROM model WHERE 1 = 1 AND CreatedAt >= '2023-12-01' AND CreatedAt < '2023-12-13' GROUP BY HasCustomAddress ORDER BY true, total_records DESC NULLS LAST LIMIT 250 OFFSET 0; +SELECT HasCustomAddress, count(*) AS total_records +FROM model +WHERE +1 = 1 AND +CreatedAt >= '2023-12-01' AND +CreatedAt < '2023-12-13' +GROUP BY HasCustomAddress ; + +statement ok +SELECT HasCustomAddress, count(*) AS total_records +FROM model +WHERE 1 = 1 AND +CreatedAt >= '2023-12-01' AND +CreatedAt < '2023-12-13' +GROUP BY HasCustomAddress +ORDER BY true, total_records DESC NULLS LAST +LIMIT 250 OFFSET 0; diff --git a/test/sql/cast/string_to_map_cast.test b/test/sql/cast/string_to_map_cast.test_slow similarity index 99% rename from test/sql/cast/string_to_map_cast.test rename to test/sql/cast/string_to_map_cast.test_slow index da60eea7812..bced678b844 100644 --- a/test/sql/cast/string_to_map_cast.test +++ b/test/sql/cast/string_to_map_cast.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/cast/string_to_map_cast.test +# name: test/sql/cast/string_to_map_cast.test_slow # description: cast strings into map structures # group: [cast] diff --git a/test/sql/cast/string_to_nested_types_cast.test_slow b/test/sql/cast/string_to_nested_types_cast.test_slow index 3cf832821e0..90c97c24128 100644 --- a/test/sql/cast/string_to_nested_types_cast.test_slow +++ b/test/sql/cast/string_to_nested_types_cast.test_slow @@ -73,7 +73,7 @@ SELECT CAST(LIST(timestamp_ms)::VARCHAR AS TIME[]) FROM test_all_types(); query I SELECT CAST(LIST(timestamp_ns)::VARCHAR AS TIME[]) FROM test_all_types(); ---- -[00:12:43.145225, 23:47:16.854775, NULL] +[00:00:00, 23:47:16.854775, NULL] query I SELECT CAST(LIST(blob)::VARCHAR AS BLOB[]) FROM test_all_types(); @@ -184,7 +184,7 @@ SELECT CAST(struct_pack(A=>timestamp_ms)::VARCHAR AS STRUCT(A TIME)) FROM test_a query I SELECT CAST(struct_pack(A=>timestamp_ns)::VARCHAR AS STRUCT(A TIME)) FROM test_all_types(); ---- -{'A': 00:12:43.145225} +{'A': 00:00:00} {'A': 23:47:16.854775} {'A': NULL} diff --git a/test/sql/cast/test_boolean_cast.test b/test/sql/cast/test_boolean_cast.test index c66f6f2c7a4..73ac1d2bb61 100644 --- a/test/sql/cast/test_boolean_cast.test +++ b/test/sql/cast/test_boolean_cast.test @@ -15,6 +15,12 @@ SELECT CAST(1=0 AS VARCHAR) ---- false + +query T +SELECT CAST(12345 AS BOOLEAN) +---- +true + query T SELECT CAST('true' AS BOOLEAN) ---- @@ -30,6 +36,21 @@ SELECT CAST('TRUE' AS BOOLEAN) ---- 1 +query T +SELECT CAST('yes' AS BOOLEAN) +---- +1 + +query T +SELECT CAST('YeS' AS BOOLEAN) +---- +1 + +query T +SELECT CAST('y' AS BOOLEAN) +---- +1 + query T SELECT CAST('false' AS BOOLEAN) ---- @@ -45,10 +66,38 @@ SELECT CAST('FALSE' AS BOOLEAN) ---- 0 +query T +SELECT CAST('no' AS BOOLEAN) +---- +0 + +query T +SELECT CAST('nO' AS BOOLEAN) +---- +0 + +query T +SELECT CAST('n' AS BOOLEAN) +---- +0 + statement error SELECT CAST('12345' AS BOOLEAN) ---- +statement ok +CREATE TABLE tbl AS SELECT 0 AS yes + +query T +SELECT CAST(yes AS BOOLEAN) FROM tbl +---- +0 + +statement error +SELECT CAST(yes AS BOOLEAN) +---- +Binder Error: Referenced column "yes" not found in FROM clause! + query T SELECT CAST(CAST('12345' AS INTEGER) AS BOOLEAN) ---- diff --git a/test/sql/catalog/comment_on.test b/test/sql/catalog/comment_on.test index 03956e22f3d..d5309b1789b 100644 --- a/test/sql/catalog/comment_on.test +++ b/test/sql/catalog/comment_on.test @@ -18,6 +18,11 @@ COMMENT ON TABLE hahahoehoe IS 'blablabloebloe' ---- Catalog Error: Table with name hahahoehoe does not exist! +statement error +COMMENT ON FUNCTION add IS 'foobar' +---- +Can not comment on System Catalog entries + ### Comment on Tables statement ok CREATE TABLE test_table as SELECT 1 as test_table_column diff --git a/test/sql/catalog/comment_on_dependencies.test b/test/sql/catalog/comment_on_dependencies.test index 25ee671f94c..10c7e01b7e5 100644 --- a/test/sql/catalog/comment_on_dependencies.test +++ b/test/sql/catalog/comment_on_dependencies.test @@ -9,8 +9,49 @@ CREATE TABLE t1 AS SELECT 1 as c1 statement ok CREATE INDEX test_index ON t1 using art(c1) -# TODO: this doesn't work: we should fix it -statement error +statement ok COMMENT ON TABLE t1 IS 'very niceee' + +# Create a table +statement ok +CREATE TABLE a (i INTEGER) + +# Create a view that depends on the table +statement ok +CREATE VIEW b AS SELECT i::STRING AS j FROM a + +# Comment on the table +statement ok +COMMENT ON TABLE a IS 'a table' + +# Comment on the table's column +statement ok +COMMENT ON COLUMN a.i IS 'a column' + +# Comment on the view +statement ok +COMMENT ON VIEW b IS 'a view' + +# Comment on the view's column +statement ok +COMMENT ON COLUMN b.j IS 'a column' + +query I +select comment from duckdb_columns() where column_name='i'; +---- +a column + +query I +select comment from duckdb_tables() where table_name='a'; +---- +a table + +query I +select comment from duckdb_views() where view_name='b'; +---- +a view + +query I +select comment from duckdb_columns() where column_name='j'; ---- -Dependency Error: Cannot alter entry "t1" because there are entries that depend on it. \ No newline at end of file +a column diff --git a/test/sql/catalog/dependencies/add_column_to_table_referenced_by_fk.test b/test/sql/catalog/dependencies/add_column_to_table_referenced_by_fk.test new file mode 100644 index 00000000000..c2701079052 --- /dev/null +++ b/test/sql/catalog/dependencies/add_column_to_table_referenced_by_fk.test @@ -0,0 +1,33 @@ +# name: test/sql/catalog/dependencies/add_column_to_table_referenced_by_fk.test +# group: [dependencies] + +statement ok +pragma enable_verification; + +statement ok +create table tbl(a varchar primary key); + +statement ok +create table tbl2( + a varchar, + foreign key (a) references tbl(a) +) + +statement ok +insert into tbl values('abc'); + +statement ok +insert into tbl2 values ('abc'); + +statement ok +alter table tbl add column b integer default 5; + +query II +select * from tbl; +---- +abc 5 + +query I +select * from tbl2; +---- +abc diff --git a/test/sql/catalog/dependencies/add_column_to_table_referenced_by_macro.test b/test/sql/catalog/dependencies/add_column_to_table_referenced_by_macro.test new file mode 100644 index 00000000000..8d067eb866c --- /dev/null +++ b/test/sql/catalog/dependencies/add_column_to_table_referenced_by_macro.test @@ -0,0 +1,27 @@ +# name: test/sql/catalog/dependencies/add_column_to_table_referenced_by_macro.test +# group: [dependencies] + +statement ok +pragma enable_verification; + +statement ok +create table tbl(a varchar default 'abc'); + +statement ok +insert into tbl values(DEFAULT); + +statement ok +create macro mcr() as table select * from tbl; + +query I +select * from mcr(); +---- +abc + +statement ok +alter table tbl add column b integer default 5; + +query II +select * from mcr(); +---- +abc 5 diff --git a/test/sql/catalog/dependencies/add_column_to_table_referenced_by_view.test b/test/sql/catalog/dependencies/add_column_to_table_referenced_by_view.test new file mode 100644 index 00000000000..59ab7d4aed2 --- /dev/null +++ b/test/sql/catalog/dependencies/add_column_to_table_referenced_by_view.test @@ -0,0 +1,27 @@ +# name: test/sql/catalog/dependencies/add_column_to_table_referenced_by_view.test +# group: [dependencies] + +statement ok +pragma enable_verification; + +statement ok +create table tbl(a varchar default 'abc'); + +statement ok +insert into tbl values(DEFAULT); + +statement ok +create view vw as select * from tbl; + +query I +select * from vw; +---- +abc + +statement ok +alter table tbl add column b integer default 5; + +statement error +select * from vw; +---- +Contents of view were altered: types don't match! Expected [VARCHAR], but found [VARCHAR, INTEGER] instead diff --git a/test/sql/catalog/dependencies/change_type_of_table_column_referenced_by_index.test b/test/sql/catalog/dependencies/change_type_of_table_column_referenced_by_index.test new file mode 100644 index 00000000000..e6770922e55 --- /dev/null +++ b/test/sql/catalog/dependencies/change_type_of_table_column_referenced_by_index.test @@ -0,0 +1,16 @@ +# name: test/sql/catalog/dependencies/change_type_of_table_column_referenced_by_index.test +# group: [dependencies] + +statement ok +pragma enable_verification; + +statement ok +create table tbl(a varchar, b integer); + +statement ok +create index idx on tbl(a); + +statement error +alter table tbl alter a set type integer; +---- +Catalog Error: Cannot change the type of this column: an index depends on it! diff --git a/test/sql/catalog/dependencies/remove_table_column_referenced_by_index.test b/test/sql/catalog/dependencies/remove_table_column_referenced_by_index.test new file mode 100644 index 00000000000..1c629891866 --- /dev/null +++ b/test/sql/catalog/dependencies/remove_table_column_referenced_by_index.test @@ -0,0 +1,16 @@ +# name: test/sql/catalog/dependencies/remove_table_column_referenced_by_index.test +# group: [dependencies] + +statement ok +pragma enable_verification; + +statement ok +create table tbl(a varchar, b integer); + +statement ok +create index idx on tbl(a); + +statement error +alter table tbl drop column a; +---- +Catalog Error: Cannot drop this column: an index depends on it! diff --git a/test/sql/catalog/dependencies/rename_table_column_referenced_by_index.test b/test/sql/catalog/dependencies/rename_table_column_referenced_by_index.test new file mode 100644 index 00000000000..1b8a73c0731 --- /dev/null +++ b/test/sql/catalog/dependencies/rename_table_column_referenced_by_index.test @@ -0,0 +1,16 @@ +# name: test/sql/catalog/dependencies/rename_table_column_referenced_by_index.test +# group: [dependencies] + +statement ok +pragma enable_verification; + +statement ok +create table tbl(a varchar); + +statement ok +create index idx on tbl(a); + +statement error +alter table tbl rename a to b; +---- +Cannot alter entry "tbl" because there are entries that depend on it. diff --git a/test/sql/catalog/dependencies/rename_view_referenced_by_table_macro.test b/test/sql/catalog/dependencies/rename_view_referenced_by_table_macro.test new file mode 100644 index 00000000000..014282b9613 --- /dev/null +++ b/test/sql/catalog/dependencies/rename_view_referenced_by_table_macro.test @@ -0,0 +1,27 @@ +# name: test/sql/catalog/dependencies/rename_view_referenced_by_table_macro.test +# group: [dependencies] + +statement ok +pragma enable_verification; + +# Create a table so our view has something to reference +statement ok +create table tbl (a varchar); + +# Create the view +statement ok +create view vw as select * from tbl; + +# Create a table macro that references the view +statement ok +create macro static_table() as table select * from vw; + +# Rename the view (Postgres 16.0 does not block this ALTER) +statement ok +alter view vw rename to vw2; + +# Our table macro now errors +statement error +select * from static_table(); +---- +Catalog Error: Table with name vw does not exist! diff --git a/test/sql/catalog/dependencies/set_default_of_table_column_referenced_by_index.test b/test/sql/catalog/dependencies/set_default_of_table_column_referenced_by_index.test new file mode 100644 index 00000000000..fe71c702c96 --- /dev/null +++ b/test/sql/catalog/dependencies/set_default_of_table_column_referenced_by_index.test @@ -0,0 +1,17 @@ +# name: test/sql/catalog/dependencies/set_default_of_table_column_referenced_by_index.test +# group: [dependencies] + +statement ok +pragma enable_verification; + +statement ok +create table tbl(a varchar, b integer); + +statement ok +create index idx on tbl(a); + +statement error +alter table tbl alter a set default 'test'; +---- +Dependency Error: Cannot alter entry "tbl" because there are entries that depend on it. + diff --git a/test/sql/catalog/dependencies/test_alter_dependency_ownership.test b/test/sql/catalog/dependencies/test_alter_dependency_ownership.test index 857e2fbadfd..b79fa8c3aee 100644 --- a/test/sql/catalog/dependencies/test_alter_dependency_ownership.test +++ b/test/sql/catalog/dependencies/test_alter_dependency_ownership.test @@ -23,6 +23,7 @@ DROP TABLE tablename; statement error SELECT nextval('sequence1'); ---- +Catalog Error: Sequence with name sequence1 does not exist! ##TEST: If the table is dropped, then the sequence is also droppped, using schemas statement ok @@ -42,6 +43,7 @@ DROP TABLE main.tablename; statement error SELECT nextval('main.sequence1'); ---- +Catalog Error: Sequence with name sequence1 does not exist! ##TEST: If the owned sequence is dropped with CASCADE, then the table is also dropped statement ok @@ -61,6 +63,7 @@ DROP SEQUENCE sequence1 CASCADE; statement error SELECT * FROM tablename; ---- +Catalog Error: Table with name tablename does not exist! ##TEST: The owned sequence cannot be dropped without CASCADE statement ok @@ -77,6 +80,7 @@ ALTER SEQUENCE sequence1 OWNED BY tablename; statement error DROP SEQUENCE sequence1; ---- +table "tablename" depends on index "sequence1". statement ok DROP TABLE tablename; @@ -163,14 +167,17 @@ DROP TABLE tablename; statement error SELECT nextval('sequence1'); ---- +Catalog Error: Sequence with name sequence1 does not exist! statement error SELECT nextval('sequence2'); ---- +Catalog Error: Sequence with name sequence2 does not exist! statement error SELECT nextval('sequence3'); ---- +Catalog Error: Sequence with name sequence3 does not exist! ##TEST: When owning a sequence, insertions work normally statement ok @@ -234,15 +241,17 @@ CREATE TABLE tablename ( statement error ALTER SEQUENCE sequence1 OWNED BY tablename; ---- +sequence1 is already owned by new_tablename statement error DROP SEQUENCE sequence1; ---- +table "new_tablename" depends on index "sequence1". statement error CREATE OR REPLACE SEQUENCE sequence1; ---- -there are entries that depend on it +table "new_tablename" depends on index "sequence1". # Owning the sequence with the same table shouldn't return any error statement ok @@ -275,6 +284,7 @@ ALTER SEQUENCE sequence1 OWNED BY tablename; statement error DROP SEQUENCE sequence1; ---- +table "tablename" depends on index "sequence1". statement ok DROP TABLE tablename; @@ -298,6 +308,7 @@ ALTER TABLE tablename DROP colname2; statement error DROP SEQUENCE sequence1; ---- +table "tablename" depends on index "sequence1". statement ok DROP TABLE tablename; @@ -320,6 +331,7 @@ ALTER TABLE tablename ALTER colname TYPE float; statement error DROP SEQUENCE sequence1; ---- +table "tablename" depends on index "sequence1". statement ok DROP TABLE tablename; @@ -345,6 +357,7 @@ ALTER TABLE tablename DROP colname4; statement error DROP SEQUENCE sequence1; ---- +table "tablename" depends on index "sequence1". statement ok ALTER TABLE tablename DROP colname3; @@ -352,6 +365,7 @@ ALTER TABLE tablename DROP colname3; statement error DROP SEQUENCE sequence1; ---- +table "tablename" depends on index "sequence1". statement ok ALTER TABLE tablename DROP colname2; @@ -359,6 +373,7 @@ ALTER TABLE tablename DROP colname2; statement error DROP SEQUENCE sequence1; ---- +table "tablename" depends on index "sequence1". statement ok DROP TABLE tablename; @@ -384,6 +399,7 @@ DROP TABLE tablename; statement error select nextval('sequence1'); ---- +Catalog Error: Sequence with name sequence1 does not exist! statement ok ROLLBACK; @@ -396,6 +412,7 @@ select nextval('sequence1'); statement error DROP SEQUENCE sequence1; ---- +table "tablename" depends on index "sequence1". statement ok DROP TABLE tablename; @@ -413,6 +430,7 @@ ALTER SEQUENCE sequence1 OWNED BY v1_sequence1; statement error DROP SEQUENCE sequence1; ---- +view "v1_sequence1" depends on index "sequence1". statement ok DROP VIEW v1_sequence1; @@ -420,6 +438,7 @@ DROP VIEW v1_sequence1; statement error SELECT nextval('sequence1'); ---- +Catalog Error: Sequence with name sequence1 does not exist! ##TEST: Sequence can own a sequence statement ok @@ -434,6 +453,7 @@ ALTER SEQUENCE sequence1 OWNED BY sequence2; statement error DROP SEQUENCE sequence1; ---- +index "sequence2" depends on index "sequence1". statement ok DROP SEQUENCE sequence2; @@ -441,6 +461,7 @@ DROP SEQUENCE sequence2; statement error SELECT nextval('sequence1'); ---- +Catalog Error: Sequence with name sequence1 does not exist! ##TEST: Sequence cant own its owner statement ok @@ -481,6 +502,8 @@ ALTER SEQUENCE sequence3 OWNED BY sequence2; ---- Dependency Error: sequence2 can not become the owner, it is already owned by sequence1 +# FIXME: this error makes no sense, if there is no circular dependency +# this should be allowed statement error ALTER SEQUENCE sequence1 OWNED BY sequence3; ---- @@ -498,15 +521,19 @@ DROP SEQUENCE sequence4; statement error SELECT nextval('sequence1'); ---- +Catalog Error: Sequence with name sequence1 does not exist! statement error SELECT nextval('sequence2'); ---- +Catalog Error: Sequence with name sequence2 does not exist! statement error SELECT nextval('sequence3'); ---- +Catalog Error: Sequence with name sequence3 does not exist! statement error SELECT nextval('sequence4'); ---- +Catalog Error: Sequence with name sequence4 does not exist! diff --git a/test/sql/catalog/dependencies/test_alter_owning_table.test b/test/sql/catalog/dependencies/test_alter_owning_table.test index 2d2f99878a9..390b769a97a 100644 --- a/test/sql/catalog/dependencies/test_alter_owning_table.test +++ b/test/sql/catalog/dependencies/test_alter_owning_table.test @@ -25,12 +25,12 @@ alter table tbl rename to tbl2; statement error drop sequence seq; ---- -Cannot drop entry "seq" because there are entries that depend on it +table "tbl2" depends on index "seq". statement error drop sequence other_seq; ---- -Cannot drop entry "other_seq" because there are entries that depend on it +table "tbl2" depends on index "other_seq". statement ok drop table tbl2; diff --git a/test/sql/catalog/dependencies/test_concurrent_drop.test b/test/sql/catalog/dependencies/test_concurrent_drop.test index d8c2cc9585e..aad43a2264d 100644 --- a/test/sql/catalog/dependencies/test_concurrent_drop.test +++ b/test/sql/catalog/dependencies/test_concurrent_drop.test @@ -20,7 +20,7 @@ create table tbl${i} ( statement error drop sequence seq; ---- -Cannot drop entry "seq" because there are entries that depend on it +Cannot drop entry "seq" because there are entries that depend on it. # Use the sequence statement ok diff --git a/test/sql/catalog/dependencies/test_default_value_dependency.test b/test/sql/catalog/dependencies/test_default_value_dependency.test index 4469b2996db..57e38f59604 100644 --- a/test/sql/catalog/dependencies/test_default_value_dependency.test +++ b/test/sql/catalog/dependencies/test_default_value_dependency.test @@ -44,42 +44,35 @@ CREATE SEQUENCE seq1 statement ok con1 CREATE SEQUENCE seq2 -statement ok con1 +statement error con1 CREATE TABLE integers(i INTEGER DEFAULT nextval('seq' || CAST(nextval('seq') AS VARCHAR)), j INTEGER) +---- +non-constant sequences are no longer supported -# seq1 exists, so the result of the first default value is 1 -statement ok con1 -INSERT INTO integers (j) VALUES (1) - -# we can drop seq1 and seq2: the dependency is not fixed statement ok con1 -DROP SEQUENCE seq1 +CREATE TABLE integers(i INTEGER DEFAULT nextval('seq1') + nextval('seq2'), j INTEGER) +# seq1 exists, so the result of the first default value is 1 statement ok con1 -DROP SEQUENCE seq2 - -# seq2 does not exist after this drop, so another insert fails -statement error con1 INSERT INTO integers (j) VALUES (1) ----- -# table is now [1, 1]: query it -query R con1 -SELECT SUM(i) FROM integers +# we canot drop seq1 and seq2: the dependency is fixed +statement error con1 +DROP SEQUENCE seq1 ---- -1.000000 +Cannot drop entry -# we can't drop seq however: the dependency is fixed statement error con1 -DROP SEQUENCE seq +DROP SEQUENCE seq2 ---- +Cannot drop entry # need to do a cascading drop statement ok con1 -DROP SEQUENCE seq CASCADE +DROP SEQUENCE seq1 CASCADE # now the table is gone statement error con1 SELECT * FROM integers ---- - +does not exist diff --git a/test/sql/catalog/dependencies/test_prepare_dependencies_transactions.test b/test/sql/catalog/dependencies/test_prepare_dependencies_transactions.test index 8ce56fda4e0..7c866d21d68 100644 --- a/test/sql/catalog/dependencies/test_prepare_dependencies_transactions.test +++ b/test/sql/catalog/dependencies/test_prepare_dependencies_transactions.test @@ -33,6 +33,7 @@ EXECUTE v statement error con2 DROP TABLE integers CASCADE ---- +Catalog write-write conflict on alter # now we rollback statement ok con2 diff --git a/test/sql/catalog/dependencies/test_schema_dependency.test b/test/sql/catalog/dependencies/test_schema_dependency.test index a3069584e50..9db91b7370b 100644 --- a/test/sql/catalog/dependencies/test_schema_dependency.test +++ b/test/sql/catalog/dependencies/test_schema_dependency.test @@ -17,6 +17,7 @@ SELECT * FROM s1.integers statement error con1 DROP SCHEMA s1 ---- +table "integers" depends on schema "s1". query I con1 SELECT * FROM s1.integers @@ -30,6 +31,7 @@ DROP SCHEMA s1 CASCADE statement error con1 SELECT * FROM s1.integers ---- +Table with name integers does not exist # schemas and dependencies # create a schema and a table inside the schema @@ -53,6 +55,7 @@ DROP TABLE s1.integers statement error con2 DROP SCHEMA s1 ---- +table "integers" depends on schema "s1". # now rollback the table drop statement ok con1 @@ -97,4 +100,4 @@ ROLLBACK statement error con2 CREATE TABLE s1.dummy(i INTEGER) ---- - +Schema with name s1 does not exist diff --git a/test/sql/catalog/function/query_function.test b/test/sql/catalog/function/query_function.test new file mode 100644 index 00000000000..f539c32b3bc --- /dev/null +++ b/test/sql/catalog/function/query_function.test @@ -0,0 +1,283 @@ +# name: test/sql/catalog/function/query_function.test +# description: test query() function +# group: [function] + +statement ok +PRAGMA enable_verification + +query I +SELECT * FROM query('SELECT 42'); +---- +42 + +query I +FROM query('SELECT 42 AS a'); +---- +42 + +query I +FROM query('SELECT 10 + 32;'); +---- +42 + +query I +FROM query('SELECT abs(-42)'); +---- +42 + +query I +SELECT * FROM query('SELECT * FROM (SELECT 1 + 2)'); +---- +3 + +query III +FROM query('SELECT 1, 2, 3'); +---- +1 2 3 + +query I +FROM query('SELECT 42;;;--- hello;'); +---- +42 + +# query text +query I +SELECT * FROM query('SELECT ''hello'''); +---- +hello + +# query a table +statement ok +CREATE TABLE tbl (a INT, b INT, c INT); + +statement ok +FROM query('SELECT *, 1 + 2 FROM tbl'); + +statement ok +INSERT INTO tbl VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9); + +query III +SELECT * FROM query('FROM tbl'); +---- +1 2 3 +4 5 6 +7 8 9 + +query I +SELECT * FROM query('SELECT a + b + c FROM tbl'); +---- +6 +15 +24 + +# query multiple nested type tags +query II +SELECT * FROM query('WITH a(i) AS (SELECT 1) SELECT a1.i AS i1, a2.i AS i2 FROM a AS a1, a AS a2'); +---- +1 1 + +# test incorrect usage +statement error +SELECT * FROM query(NULL); +---- +Parser Error: syntax error at or near "NULL" + +statement error +SELECT * FROM query(' '); +---- +Parser Error: Expected a single SELECT statement + +statement error +SELECT * FROM query(''); +---- +Parser Error: Expected a single SELECT statement + +statement error +SELECT * FROM query('FROM query(FROM)'); +---- +Parser Error: syntax error at or near "FROM" + +# multiple statements are not supported +statement error +SELECT * FROM query('SELECT 1; SELECT 2'); +---- +Parser Error: Expected a single SELECT statement + +# invalid input +statement error +SELECT query(SELECT 1); +---- +Parser Error: syntax error at or near "SELECT" + +statement error +SELECT * FROM query('CREATE TABLE tbl (a INT)'); +---- +Parser Error: Expected a single SELECT statement + + +# test query_table() +statement ok +CREATE TABLE tbl_int AS SELECT 42; + +statement ok +CREATE TABLE tbl_varchar AS SELECT 'duckdb'; + +statement ok +CREATE TABLE tbl2_varchar AS SELECT '1?ch@racter$'; + +statement ok +CREATE TABLE tbl_empty AS SELECT ''; + +query I +FROM query_table('tbl_int'); +---- +42 + +query I +FROM query_table(['tbl_int']); +---- +42 + +query III +FROM query_table(tbl); +---- +1 2 3 +4 5 6 +7 8 9 + +statement ok +CREATE TABLE tbl2 (a INT, b INT, c INT); + +statement ok +INSERT INTO tbl2 VALUES (9, 8, 7), (6, 5, 4), (3, 2, 1); + +query III +FROM query_table([tbl, tbl2]); +---- +1 2 3 +4 5 6 +7 8 9 +9 8 7 +6 5 4 +3 2 1 + +# test incorrect usage +statement error +FROM query_table(); +---- +No function matches the given name and argument types 'query_table()'. + +statement error +FROM query_table(NULL); +---- +Catalog Error: Table with name NULL does not exist! + +statement error +FROM query_table([]); +---- +Binder Error: No function matches the given name and argument types 'query_table(INTEGER[])'. + +statement error +FROM query_table(['']); +---- +Parser Error: syntax error at end of input + +statement error +FROM query_table('tbl_int', 'tbl_varchar', tbl2_varchar); +---- +Binder Error: No function matches the given name and argument types 'query_table(VARCHAR, VARCHAR, VARCHAR)'. + +statement error +FROM query_table([tbl_int, tbl2]); +---- +Binder Error: Set operations can only apply to expressions with the same number of result columns + +statement error +FROM query_table(not_defined_tbl); +---- +Catalog Error: Table with name not_defined_tbl does not exist! + +statement error +FROM query_table('FROM query(''select 1 + 2;'')'); +---- +Catalog Error: Table with name FROM query('select 1 + 2;') does not exist! + +statement error +FROM query_table('FROM query("select 1 + 2;")'); +---- +Catalog Error: Table with name FROM query("select 1 + 2;") does not exist! + +statement error +FROM query_table('(SELECT 17 + 25)'); +---- +Catalog Error: Table with name (SELECT 17 + 25) does not exist! + +# tables with special table names +statement ok +CREATE TABLE "(SELECT 17 + 25)"(i int); + +statement ok +insert into "(SELECT 17 + 25)" values (100); + +query I +SELECT * FROM "(SELECT 17 + 25)"; +---- +100 + +query I +FROM query_table("(SELECT 17 + 25)"); +---- +100 + +query I +FROM query_table('(SELECT 17 + 25)'); +---- +100 + +statement error +FROM query_table(SELECT 17 + 25); +---- +Parser Error: syntax error at or near "SELECT" + +statement error +FROM query_table("SELECT 4 + 2"); +---- +Catalog Error: Table with name SELECT 4 + 2 does not exist! + +statement error +FROM query_table('SELECT 4 + 2'); +---- +Catalog Error: Table with name SELECT 4 + 2 does not exist! + +# test by_name argument +query I +FROM query_table(['tbl_int', 'tbl_varchar', 'tbl_empty', 'tbl2_varchar'], false); +---- +42 +duckdb +(empty) +1?ch@racter$ + +query IIII +from query_table([tbl_int, tbl_varchar, tbl_empty, tbl2_varchar], true); +---- +42 NULL NULL NULL +NULL duckdb NULL NULL +NULL NULL (empty) NULL +NULL NULL NULL 1?ch@racter$ + +# test incorrect usage +statement error +FROM query_table(true); +---- +Binder Error: No function matches the given name and argument types 'query_table(BOOLEAN)'. + +statement error +FROM query_table(tbl2, true); +---- +Binder Error: No function matches the given name and argument types 'query_table(VARCHAR, BOOLEAN)'. + +statement error +FROM query_table(['tbl_int', 'tbl_varchar', 'tbl_empty', '(select ''I am a subquery'')'], false); +---- +Catalog Error: Table with name (select 'I am a subquery') does not exist! diff --git a/test/sql/catalog/function/test_cross_catalog_macros.test b/test/sql/catalog/function/test_cross_catalog_macros.test new file mode 100644 index 00000000000..3b5981fc3e6 --- /dev/null +++ b/test/sql/catalog/function/test_cross_catalog_macros.test @@ -0,0 +1,16 @@ +# name: test/sql/catalog/function/test_cross_catalog_macros.test +# description: Test cross-catalog dependencies in macros +# group: [function] + +require skip_reload + +statement ok +CREATE MACRO my_first_macro() AS (84) + +statement ok +CREATE TEMPORARY MACRO my_second_macro() AS my_first_macro() + 42; + +query I +SELECT my_second_macro() +---- +126 diff --git a/test/sql/catalog/function/test_macro_default_arg.test b/test/sql/catalog/function/test_macro_default_arg.test index 471f2f9ab2c..4c3914766fd 100644 --- a/test/sql/catalog/function/test_macro_default_arg.test +++ b/test/sql/catalog/function/test_macro_default_arg.test @@ -1,6 +1,9 @@ # name: test/sql/catalog/function/test_macro_default_arg.test # group: [function] +statement ok +set storage_compatibility_version='v0.10.2' + statement ok pragma enable_verification; diff --git a/test/sql/catalog/function/test_macro_default_arg_with_dependencies.test b/test/sql/catalog/function/test_macro_default_arg_with_dependencies.test new file mode 100644 index 00000000000..9809762850c --- /dev/null +++ b/test/sql/catalog/function/test_macro_default_arg_with_dependencies.test @@ -0,0 +1,107 @@ +# name: test/sql/catalog/function/test_macro_default_arg_with_dependencies.test +# group: [function] + +statement ok +set storage_compatibility_version='latest' + +statement ok +set enable_macro_dependencies=true + +statement ok +pragma enable_verification; + +statement ok +CREATE MACRO f(x := NULL) AS x+1; + +query I +SELECT f(); +---- +NULL + +query I +SELECT f(x := 41) +---- +42 + +query I +SELECT f(x := (SELECT 41)); +---- +42 + +query I +select f(x:=(select 1 a)); +---- +2 + +query I +select f(x:=a) from (select 41) t(a); +---- +42 + +statement ok +create table t as select 41 a; + +query I +select f(x:=a) from t; +---- +42 + +statement error +create macro my_macro1(a, b := a) as a + b; +---- +Binder Error: table "0_macro_parametersmy_macro1" has duplicate column name "a" + +statement ok +create table integers (a integer); + +statement ok +create macro my_macro2(a := i) as ( + select min(a) from integers +); + +statement ok +insert into integers values (5), (10), (13) + +query I +select my_macro2(can_not_be_empty) +---- +5 + +statement error +drop table integers; +---- +macro function "my_macro2" depends on table "integers". + +statement ok +drop table integers cascade; + +# The macro was dropped by the CASCADE +statement error +select my_macro2(5); +---- +Catalog Error: Scalar Function with name my_macro2 does not exist! + +statement ok +Create table t1 (a int, b int); + +statement ok +Create table t2 (c int, d int); + +statement ok +CREATE OR REPLACE MACRO eq(x := NULL, y := NULL) AS x = y + +statement ok +INSERT INTO t1 VALUES (1, 1), (1, 2), (2, 2), (3, 4); + +statement ok +INSERT INTO t2 VALUES (4, 1), (2, 10), (6, 2), (2, 6); + +statement ok +SELECT * FROM t1 as t1_alias inner join (select * from t2) as t2_alias ON (eq(x := t1_alias.a, y := t2_alias.c)) + +# no default parameters with incorrect names +statement error +SELECT * FROM t1 as t1_alias inner join (select * from t2) as t2_alias ON (eq(a := t1_alias.a, c := t2_alias.c)) +---- +Binder Error + diff --git a/test/sql/catalog/function/test_recursive_macro.test b/test/sql/catalog/function/test_recursive_macro.test index be973956167..71bdcf05a3e 100644 --- a/test/sql/catalog/function/test_recursive_macro.test +++ b/test/sql/catalog/function/test_recursive_macro.test @@ -2,6 +2,9 @@ # description: Test recursive macros # group: [function] +statement ok +set enable_macro_dependencies=true + statement ok CREATE MACRO "sum"(x) AS (CASE WHEN sum(x) IS NULL THEN 0 ELSE sum(x) END); @@ -39,13 +42,10 @@ create macro m1(a) as a+1; statement ok create macro m2(a) as m1(a)+1; -statement ok -create or replace macro m1(a) as m2(a)+1; - statement error -select m2(42); +create or replace macro m1(a) as m2(a)+1; ---- -Binder Error: Maximum recursion depth exceeded +Catalog Error: CREATE OR REPLACE is not allowed to depend on itself # also table macros statement ok @@ -54,10 +54,7 @@ create macro m3(a) as a+1; statement ok create macro m4(a) as table select m3(a); -statement ok -create or replace macro m3(a) as (from m4(42)); - statement error -select m3(42); +create or replace macro m3(a) as (from m4(42)); ---- -Binder Error: Maximum recursion depth exceeded +Catalog Error: CREATE OR REPLACE is not allowed to depend on itself diff --git a/test/sql/catalog/function/test_recursive_macro_no_dependency.test b/test/sql/catalog/function/test_recursive_macro_no_dependency.test new file mode 100644 index 00000000000..0e608309be1 --- /dev/null +++ b/test/sql/catalog/function/test_recursive_macro_no_dependency.test @@ -0,0 +1,53 @@ +# name: test/sql/catalog/function/test_recursive_macro_no_dependency.test +# description: Test recursive macros +# group: [function] + +statement ok +CREATE MACRO "sum"(x) AS (CASE WHEN sum(x) IS NULL THEN 0 ELSE sum(x) END); + +statement error +SELECT sum(1); +---- +Binder Error: Maximum recursion depth exceeded + +statement error +SELECT sum(1) WHERE 42=0 +---- +Binder Error: Maximum recursion depth exceeded + +statement ok +DROP MACRO sum + +# recursive macro with explicit qualification +statement ok +CREATE MACRO "sum"(x) AS (CASE WHEN system.main.sum(x) IS NULL THEN 0 ELSE system.main.sum(x) END); + +query I +SELECT sum(1); +---- +1 + +query I +SELECT sum(1) WHERE 42=0 +---- +0 + +# evil test case by Mark +statement ok +create macro m1(a) as a+1; + +statement ok +create macro m2(a) as m1(a)+1; + +statement ok +create or replace macro m1(a) as m2(a)+1; + +# also table macros +statement ok +create macro m3(a) as a+1; + +statement ok +create macro m4(a) as table select m3(a); + +statement ok +create or replace macro m3(a) as (from m4(42)); diff --git a/test/sql/catalog/sequence/test_sequence.test b/test/sql/catalog/sequence/test_sequence.test index fc352bd4101..1724d502789 100644 --- a/test/sql/catalog/sequence/test_sequence.test +++ b/test/sql/catalog/sequence/test_sequence.test @@ -77,19 +77,15 @@ SELECT currval(NULL) ---- NULL -query I +statement error SELECT nextval(a) FROM (VALUES ('seq'), (NULL), ('seq')) tbl1(a) ---- -5 -NULL -6 +non-constant sequences are no longer supported -query I +statement error SELECT currval(a) FROM (VALUES ('seq'), (NULL), ('seq')) tbl1(a) ---- -6 -NULL -6 +non-constant sequences are no longer supported # can't create a sequence that already exists statement error @@ -479,18 +475,16 @@ SELECT s, currval('seq') FROM strings seq 2 seq2 2 -# we can also use the strings from the table as input to the sequence -query TI +# we cannot use the strings from the table as input to the sequence +statement error SELECT s, nextval(s) FROM strings ---- -seq 3 -seq2 1 +non-constant sequences are no longer supported -query TI +statement error SELECT s, currval(s) FROM strings ---- -seq 3 -seq2 1 +non-constant sequences are no longer supported # this will also cause an error if the sequence does not exist statement ok diff --git a/test/sql/catalog/test_catalog_errors.test b/test/sql/catalog/test_catalog_errors.test index 765ccac3420..7afb1790ad3 100644 --- a/test/sql/catalog/test_catalog_errors.test +++ b/test/sql/catalog/test_catalog_errors.test @@ -40,6 +40,7 @@ CREATE INDEX i_index ON integers(i); statement error CREATE INDEX i_index ON integers(i); ---- +already exists # with IF NOT EXISTS it does not fail! statement ok @@ -58,9 +59,19 @@ DROP INDEX i_index statement ok DROP INDEX IF EXISTS i_index -# create the index again +# create the index again, but as unique to exercise special handling due to indexes generated column constraints statement ok -CREATE INDEX i_index ON integers(i); +CREATE UNIQUE INDEX i_index ON integers(i); + +# cannot create an index that already exists +statement error +CREATE UNIQUE INDEX i_index ON integers(i); +---- +already exists + +# with IF NOT EXISTS it does not fail! +statement ok +CREATE UNIQUE INDEX IF NOT EXISTS i_index ON integers(i); # dropping the table also drops the index statement ok diff --git a/test/sql/catalog/test_schema.test b/test/sql/catalog/test_schema.test index 6db40ab83c3..4b9c0708f50 100644 --- a/test/sql/catalog/test_schema.test +++ b/test/sql/catalog/test_schema.test @@ -18,7 +18,7 @@ CREATE TABLE test.hello(i INTEGER); statement error con1 CREATE OR REPLACE SCHEMA test; ---- -there are entries that depend on it +table "hello" depends on schema "test". # in one transaction drop the table and then the schema (without cascade) statement ok con1 @@ -76,4 +76,4 @@ ROLLBACK; statement error con2 SELECT * FROM test.hello ---- - +Table with name hello does not exist diff --git a/test/sql/catalog/view/recursive_view.test b/test/sql/catalog/view/recursive_view.test index ce9290ac9ea..569b4ae9a2d 100644 --- a/test/sql/catalog/view/recursive_view.test +++ b/test/sql/catalog/view/recursive_view.test @@ -2,6 +2,9 @@ # description: Issue #3017: Querying View of a View Crashes # group: [view] +statement ok +set storage_compatibility_version='v0.10.2' + statement ok PRAGMA enable_verification diff --git a/test/sql/catalog/view/recursive_view_with_dependencies.test b/test/sql/catalog/view/recursive_view_with_dependencies.test new file mode 100644 index 00000000000..138ed3d1068 --- /dev/null +++ b/test/sql/catalog/view/recursive_view_with_dependencies.test @@ -0,0 +1,39 @@ +# name: test/sql/catalog/view/recursive_view_with_dependencies.test +# description: Issue #3017: Querying View of a View Crashes +# group: [view] + +statement ok +set storage_compatibility_version='latest' + +statement ok +set enable_view_dependencies=true + +statement ok +PRAGMA enable_verification + +statement ok +CREATE TABLE IF NOT EXISTS test (val INTEGER); + +statement ok +INSERT INTO test(val) VALUES (1), (2), (3); + +# recursive view definition +statement ok +CREATE OR REPLACE VIEW foo AS (SELECT * FROM test); + +statement error +CREATE OR REPLACE VIEW foo AS (SELECT * FROM foo); +---- +Catalog Error: CREATE OR REPLACE is not allowed to depend on itself + +# more complex recursive view definition +statement ok +CREATE OR REPLACE VIEW foo AS (SELECT * FROM test); + +statement ok +CREATE OR REPLACE VIEW foo2 AS (SELECT * FROM foo); + +statement error +CREATE OR REPLACE VIEW foo AS (SELECT (SELECT * FROM foo2)); +---- +Catalog Error: CREATE OR REPLACE is not allowed to depend on itself diff --git a/test/sql/catalog/view/test_view_schema_change.test b/test/sql/catalog/view/test_view_schema_change.test index f669b36ef7f..02a15939d39 100644 --- a/test/sql/catalog/view/test_view_schema_change.test +++ b/test/sql/catalog/view/test_view_schema_change.test @@ -2,6 +2,9 @@ # description: Test views with changing schema # group: [view] +statement ok +set storage_compatibility_version='v0.10.2' + statement ok PRAGMA enable_verification diff --git a/test/sql/catalog/view/test_view_schema_change_with_dependencies.test b/test/sql/catalog/view/test_view_schema_change_with_dependencies.test new file mode 100644 index 00000000000..3ec9283089e --- /dev/null +++ b/test/sql/catalog/view/test_view_schema_change_with_dependencies.test @@ -0,0 +1,115 @@ +# name: test/sql/catalog/view/test_view_schema_change_with_dependencies.test +# description: Test views with changing schema +# group: [view] + +statement ok +set storage_compatibility_version='latest' + +statement ok +set enable_view_dependencies=true + +statement ok +PRAGMA enable_verification + +# create a table +statement ok +CREATE TABLE t1(i INTEGER) + +statement ok +INSERT INTO t1 VALUES (41), (42), (43) + +# create a view that queries that table +statement ok +CREATE VIEW v1 AS SELECT * FROM t1 + +query I +SELECT * FROM v1 +---- +41 +42 +43 + +# now drop the table and create a table that has a different schema +statement error +DROP TABLE t1 +---- +view "v1" depends on table "t1". + +statement ok +DROP TABLE t1 CASCADE + +statement ok +CREATE TABLE t1(i DATE) + +# querying the view fails because the column types don't match the expected types +statement error +SELECT * FROM v1 +---- + +# now drop the table and create one that has extra columns +statement ok +DROP TABLE t1 + +statement ok +CREATE TABLE t1(i INTEGER, j INTEGER) + +# again querying the view fails: there are extra columns present +statement error +SELECT * FROM v1 +---- + +# now drop the table and create one that has differently named columns +statement ok +DROP TABLE t1 + +statement ok +CREATE TABLE t1(k INTEGER) + +# Was dropped by the CASCADE from earlier +statement error +SELECT * FROM v1 +---- +Catalog Error: Table with name v1 does not exist! + +statement ok +DROP TABLE t1 + +statement ok +CREATE TABLE t1(i INTEGER) + +statement error +SELECT * FROM v1 +---- +Table with name v1 does not exist! + +# Recreate the VIEW +statement ok +CREATE VIEW v1 AS SELECT * FROM t1 + +# Changing the types of the table can't be done because we have dependencies +statement error +ALTER TABLE t1 ALTER i TYPE VARCHAR; +---- +Dependency Error: Cannot alter entry "t1" because there are entries that depend on it. + +statement ok +drop view v1; + +statement ok +ALTER TABLE t1 ALTER i TYPE VARCHAR; + +# Recreate the VIEW +statement ok +CREATE VIEW v1 AS SELECT * FROM t1 + +# Changing the column names is also not possible while V1 is alive +statement error +ALTER TABLE t1 RENAME i TO j +---- +Dependency Error: Cannot alter entry "t1" because there are entries that depend on it. + +statement ok +drop view v1; + +statement ok +ALTER TABLE t1 RENAME i TO j diff --git a/test/sql/catalog/view/test_view_sql.test b/test/sql/catalog/view/test_view_sql.test index 32560dead30..3f180d9cfbc 100644 --- a/test/sql/catalog/view/test_view_sql.test +++ b/test/sql/catalog/view/test_view_sql.test @@ -2,6 +2,9 @@ # description: Test behavior of 'sql' on various different views # group: [view] +statement ok +set storage_compatibility_version='v0.10.2' + statement ok PRAGMA enable_verification diff --git a/test/sql/catalog/view/test_view_sql_with_dependencies.test b/test/sql/catalog/view/test_view_sql_with_dependencies.test new file mode 100644 index 00000000000..75d8640575f --- /dev/null +++ b/test/sql/catalog/view/test_view_sql_with_dependencies.test @@ -0,0 +1,111 @@ +# name: test/sql/catalog/view/test_view_sql_with_dependencies.test +# description: Test behavior of 'sql' on various different views +# group: [view] + +statement ok +set storage_compatibility_version='latest' + +statement ok +set enable_view_dependencies=true + +statement ok +PRAGMA enable_verification + +statement ok +create schema my_schema; + +# X contains columns `a` and `y` +statement ok +CREATE VIEW my_schema.X (a) AS SELECT 'x' as x, 'y' as y; + +query I +select trim(sql, chr(10)) from duckdb_views() where internal = false; +---- +CREATE VIEW my_schema.X (a) AS SELECT 'x' AS x, 'y' AS y; + +statement ok +alter view my_schema.X rename to Y; + +# Properly renamed to Y +query I +select trim(sql, chr(10)) from duckdb_views() where internal = false; +---- +CREATE VIEW my_schema.Y (a) AS SELECT 'x' AS x, 'y' AS y; + +statement ok +drop schema my_schema cascade; + +query I +select trim(sql, chr(10)) from duckdb_views() where internal = false; +---- + +statement ok +create table tbl ( + a integer, + b varchar +) + +statement ok +create view vw as select * from tbl; + +# sql is not affected by the column names of the table +query I +select trim(sql, chr(10)) from duckdb_views() where internal = false; +---- +CREATE VIEW vw AS SELECT * FROM tbl; + +statement error +alter table tbl rename column b to x; +---- +Dependency Error: Cannot alter entry "tbl" because there are entries that depend on it. + +# The VIEW has to be dropped before the table can be altered +statement ok +drop view vw; + +statement ok +alter table tbl rename column b to x; + +# Recreate the view +statement ok +CREATE VIEW vw AS SELECT * FROM tbl; + +# sql is not affected by the column names of the table +query I +select trim(sql, chr(10)) from duckdb_views() where internal = false; +---- +CREATE VIEW vw AS SELECT * FROM tbl; + +statement ok +create or replace view vw (c1, c2) as select * from tbl; + +statement ok +create or replace table "table name" ( + "column name 1" integer, + "column name 2" varchar +) + +statement ok +create or replace view "view name" as select * from "table name"; + +statement ok +drop view vw; + +query I +select trim(sql, chr(10)) from duckdb_views() where internal = false; +---- +CREATE VIEW "view name" AS SELECT * FROM "table name"; + +statement ok +drop view "view name" + +statement ok +create schema "schema name"; + +statement ok +CREATE VIEW "schema name"."view name" ("other name 1", "column name 2") AS SELECT * FROM "table name"; + +query I +select trim(sql, chr(10)) from duckdb_views() where internal = false; +---- +CREATE VIEW "schema name"."view name" ("other name 1", "column name 2") AS SELECT * FROM "table name"; diff --git a/test/sql/collate/test_collate_and_grouping_sets.test b/test/sql/collate/test_collate_and_grouping_sets.test new file mode 100644 index 00000000000..4c117ea8f3d --- /dev/null +++ b/test/sql/collate/test_collate_and_grouping_sets.test @@ -0,0 +1,84 @@ +# name: test/sql/collate/test_collate_and_grouping_sets.test +# description: Test collation and grouping sets. +# group: [collate] + +require icu + +require skip_reload + +statement ok +set default_collation=c; + +statement ok +CREATE TABLE sales ( + product_id INT, + region VARCHAR(50), + year INT, + amount_sold DECIMAL(10,2) +); + +statement ok +INSERT INTO sales VALUES + (1, 'North', 2020, 1000.00), + (1, 'North', 2021, 1500.00), + (1, 'South', 2020, 800.00), + (1, 'South', 2021, 700.00), + (2, 'North', 2020, 500.00), + (2, 'North', 2021, 600.00), + (2, 'South', 2020, 400.00), + (2, 'South', 2021, 550.00); + +statement ok +set default_collation=c; + +query III nosort grouping_sets_collation_result +SELECT product_id, region, SUM(amount_sold) AS total_amount +FROM sales +GROUP BY GROUPING SETS ((product_id), (region), ()) +ORDER BY product_id, region, total_amount; + +statement ok +set default_collation=en_us; + +query III nosort grouping_sets_collation_result +SELECT product_id, region, SUM(amount_sold) AS total_amount +FROM sales +GROUP BY GROUPING SETS ((product_id), (region), ()) +ORDER BY product_id, region, total_amount; + + +statement ok +set default_collation=c + +query III nosort union_groups_collation_result +select NULL product_id, region, sum(amount_sold) from sales group by region +UNION ALL +select NULL product_id, NULL region, sum(amount_sold) from sales +UNION ALL +select product_id, NULL region, sum(amount_sold) from sales group by product_id order by 1,2; + + +statement ok +set default_collation=en_us; + +query III nosort union_groups_collation_result +select NULL product_id, region, sum(amount_sold) from sales group by region +UNION ALL +select NULL product_id, NULL region, sum(amount_sold) from sales +UNION ALL +select product_id, NULL region, sum(amount_sold) from sales group by product_id order by 1,2; + +# also test that union all is the same as using grouping sets + +query III nosort grouping_sets_collation +SELECT product_id, region, SUM(amount_sold) AS total_amount +FROM sales +GROUP BY GROUPING SETS ((product_id), (region), ()) +ORDER BY product_id, region, total_amount; + +query III nosort grouping_sets_collation +select NULL product_id, region, sum(amount_sold) from sales group by region +UNION ALL +select NULL product_id, NULL region, sum(amount_sold) from sales +UNION ALL +select product_id, NULL region, sum(amount_sold) from sales group by product_id order by 1,2; diff --git a/test/sql/collate/test_icu_collate.test b/test/sql/collate/test_icu_collate.test index 1f2233bc5a6..8ffb644f377 100644 --- a/test/sql/collate/test_icu_collate.test +++ b/test/sql/collate/test_icu_collate.test @@ -84,6 +84,12 @@ SELECT icu_sort_key('goose', 'DUCK_DUCK_ENUM'); ---- Invalid Input Error +statement ok +select icu_sort_key('æ', 'icu_noaccent'); + +statement ok +select icu_sort_key('Æ', 'icu_noaccent'); + # issue duckdb/duckdb#9692 query I select chr(2*16*256+1*256+2*16+11) collate da =chr(12*16+5) collate da; @@ -120,3 +126,29 @@ query I select count(*) from (select chr(2*16*256+1*256+2*16+11) union select chr(12*16+5)) as t(s) group by s collate nfc; ---- 2 + +# ICU noaccent collate +statement ok +CREATE TABLE t1 (c1 CHAR(10)) + +statement ok +INSERT INTO t1 VALUES('z'),('Z'),('a'),('A'),('æ'),('Æ'),('à'),('À'),('á'),('Á'),('â'),('Â'), +('ã'),('Ã'),('ä'),('Ä'),('å'),('Å'),('b'),('B') + +query I +SELECT GROUP_CONCAT(c1, '') as group_c1 FROM t1 GROUP BY c1 COLLATE "NOCASE.ICU_NOACCENT" ORDER BY group_c1 COLLATE "NOCASE.ICU_NOACCENT" +---- +aAàÀáÁâÂãÃäÄåÅ +æÆ +bB +zZ + +statement error +SELECT 'Á' COLLATE "ICU_NOACCENT.NOACCENT" +---- +Binder Error: Cannot combine collation types "icu_noaccent" and "noaccent" + +statement error +SELECT 'Á' COLLATE "NOACCENT.ICU_NOACCENT" +---- +Binder Error: Cannot combine collation types "noaccent" and "icu_noaccent" diff --git a/test/sql/constraints/foreignkey/test_fk_alter.test b/test/sql/constraints/foreignkey/test_fk_alter.test new file mode 100644 index 00000000000..b7d75485305 --- /dev/null +++ b/test/sql/constraints/foreignkey/test_fk_alter.test @@ -0,0 +1,36 @@ +# name: test/sql/constraints/foreignkey/test_fk_alter.test +# group: [foreignkey] + +statement ok +CREATE TABLE departments ( + department_id INTEGER PRIMARY KEY, + department_name VARCHAR(100) NOT NULL +); + +statement ok +CREATE TABLE employees ( + employee_id INTEGER PRIMARY KEY, + employee_name VARCHAR(100) NOT NULL, + department_id INT REFERENCES departments(department_id) +); + +statement error +drop table departments +---- +Catalog Error: Could not drop the table because this table is main key table of the table "employees" + +# FIXME: we would need to update the foreign key constraint of the tables that are referencing 'employees' +# to fix this, propagating an alter down. +# (or use Postgres's solution of using oids to add a layer of indirection so we dont need to do cleanup whenever a rename is done) +statement error +ALTER TABLE departments RENAME TO old_departments +---- +Dependency Error: Cannot alter entry "departments" because there are entries that depend on it. + +statement error +drop table departments +---- +Catalog Error: Could not drop the table because this table is main key table of the table "employees" + +statement ok +ALTER TABLE employees RENAME TO old_employees diff --git a/test/sql/constraints/foreignkey/test_fk_multiple.test b/test/sql/constraints/foreignkey/test_fk_multiple.test index e2e843688b0..202857079ea 100644 --- a/test/sql/constraints/foreignkey/test_fk_multiple.test +++ b/test/sql/constraints/foreignkey/test_fk_multiple.test @@ -2,17 +2,37 @@ # description: Test multiple foreign key constraint # group: [foreignkey] +# Create a table with a primary key statement ok -CREATE TABLE pkt1(i1 INTEGER PRIMARY KEY CHECK(i1 < 3), j1 INTEGER UNIQUE); +CREATE TABLE pkt1( + i1 INTEGER PRIMARY KEY CHECK(i1 < 3), + j1 INTEGER UNIQUE +); +# Create another table with a primary key statement ok -CREATE TABLE pkt2(i2 INTEGER PRIMARY KEY, j2 INTEGER UNIQUE CHECK (j2 > 1000)); +CREATE TABLE pkt2( + i2 INTEGER PRIMARY KEY, + j2 INTEGER UNIQUE CHECK (j2 > 1000) +); +# Reference both of the previous tables with foreign keys in this table statement ok -CREATE TABLE fkt1(k1 INTEGER, l1 INTEGER, FOREIGN KEY(k1) REFERENCES pkt1(i1), FOREIGN KEY(l1) REFERENCES pkt2(i2)); +CREATE TABLE fkt1( + k1 INTEGER, + l1 INTEGER, + FOREIGN KEY(k1) REFERENCES pkt1(i1), + FOREIGN KEY(l1) REFERENCES pkt2(i2) +); +# Reference both of the primary key tables again statement ok -CREATE TABLE fkt2(k2 INTEGER, l2 INTEGER, FOREIGN KEY(k2) REFERENCES pkt1(j1), FOREIGN KEY(l2) REFERENCES pkt2(j2)); +CREATE TABLE fkt2( + k2 INTEGER, + l2 INTEGER, + FOREIGN KEY(k2) REFERENCES pkt1(j1), + FOREIGN KEY(l2) REFERENCES pkt2(j2) +); # ensure the constraints are being correctly copied statement error @@ -131,10 +151,12 @@ SELECT * FROM pkt2; statement error DROP TABLE pkt1 ---- +Could not drop the table because this table is main key table of the table "fkt1" statement error DROP TABLE pkt2 ---- +Could not drop the table because this table is main key table of the table "fkt1" statement ok DROP TABLE fkt2 @@ -142,10 +164,12 @@ DROP TABLE fkt2 statement error DROP TABLE pkt1 ---- +Could not drop the table because this table is main key table of the table "fkt1" statement error DROP TABLE pkt2 ---- +Could not drop the table because this table is main key table of the table "fkt1" statement ok DROP TABLE fkt1 diff --git a/test/sql/constraints/foreignkey/test_fk_rollback.test b/test/sql/constraints/foreignkey/test_fk_rollback.test index 8500780abe5..fc60337f804 100644 --- a/test/sql/constraints/foreignkey/test_fk_rollback.test +++ b/test/sql/constraints/foreignkey/test_fk_rollback.test @@ -18,6 +18,7 @@ CREATE TABLE fk_integers(j INTEGER, FOREIGN KEY (j) REFERENCES pk_integers(i)) statement error DROP TABLE pk_integers ---- +Could not drop the table because this table is main key table of the table "fk_integers" statement ok ROLLBACK diff --git a/test/sql/copy/csv/auto/test_type_detection.test b/test/sql/copy/csv/auto/test_type_detection.test index 4df1e94075a..68e40cdb0e6 100644 --- a/test/sql/copy/csv/auto/test_type_detection.test +++ b/test/sql/copy/csv/auto/test_type_detection.test @@ -2,6 +2,8 @@ # description: Test csv type detection # group: [auto] +require vector_size 2048 + # a CSV file with many strings statement ok CREATE TABLE test AS SELECT * FROM read_csv_auto ('test/sql/copy/csv/data/auto/large_mixed_data.csv', SAMPLE_SIZE=-1); diff --git a/test/sql/copy/csv/batched_write/batch_csv_mixed_batches.test_slow b/test/sql/copy/csv/batched_write/batch_csv_mixed_batches.test_slow index cc9799af8b0..43d2224d66a 100644 --- a/test/sql/copy/csv/batched_write/batch_csv_mixed_batches.test_slow +++ b/test/sql/copy/csv/batched_write/batch_csv_mixed_batches.test_slow @@ -154,6 +154,15 @@ DROP TABLE mixed_batches_v3 statement ok DROP TABLE mixed_batches_v4 +statement ok +drop view if exists v2; + +statement ok +drop view if exists v3; + +statement ok +drop view if exists v4; + # create views that read the batches using unions statement ok CREATE OR REPLACE VIEW v1 AS FROM '__TEST_DIR__/mix_batches_small.parquet' UNION ALL FROM '__TEST_DIR__/mix_batches_large.parquet' UNION ALL FROM '__TEST_DIR__/mix_batches_odd.parquet' UNION ALL FROM '__TEST_DIR__/mix_batches_odd_again.parquet' diff --git a/test/sql/copy/csv/parallel/csv_parallel_clickbench.test_slow b/test/sql/copy/csv/parallel/csv_parallel_clickbench.test_slow index 529a24ae5c5..354440d4d99 100644 --- a/test/sql/copy/csv/parallel/csv_parallel_clickbench.test_slow +++ b/test/sql/copy/csv/parallel/csv_parallel_clickbench.test_slow @@ -133,7 +133,7 @@ statement ok create table hits as select * from hits_og limit 0; statement ok -copy hits from '__TEST_DIR__/hits.csv' (nullstr 'null'); +insert into hits from read_csv('__TEST_DIR__/hits.csv', compression = 'none', nullstr = 'null'); #Q 01 query I diff --git a/test/sql/copy/csv/read_csv_subquery.test b/test/sql/copy/csv/read_csv_subquery.test index 0eb5c1576fd..5b59510ffbe 100644 --- a/test/sql/copy/csv/read_csv_subquery.test +++ b/test/sql/copy/csv/read_csv_subquery.test @@ -14,7 +14,7 @@ FROM read_csv_auto((SELECT url FROM urls LIMIT 3), delim=',') WHERE properties.height > -1.0 LIMIT 10 ---- -Only table-in-out functions can have subquery parameters +subqueries statement error SELECT * diff --git a/test/sql/copy/csv/recursive_query_csv.test_slow b/test/sql/copy/csv/recursive_query_csv.test_slow index 3f529433143..4dd015811b8 100644 --- a/test/sql/copy/csv/recursive_query_csv.test_slow +++ b/test/sql/copy/csv/recursive_query_csv.test_slow @@ -38,68 +38,172 @@ with recursive and chains.endTS < base."date recorded" and base."date recorded" < (chains.endTS + interval 6 days) ) - select * from chains; + select * from chains + order by all; ---- -Greenwich 2007-05-15 2007-05-15 [{'date': 2007-05-15, 'amt': 1215000.0, 'type': Condo}] -Fairfield 2007-06-15 2007-06-15 [{'date': 2007-06-15, 'amt': 1100000.0, 'type': Condo}] -Greenwich 2007-01-31 2007-01-31 [{'date': 2007-01-31, 'amt': 4600000.0, 'type': Condo}] -Greenwich 2007-07-10 2007-07-10 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}] -Greenwich 2007-01-19 2007-01-19 [{'date': 2007-01-19, 'amt': 2227500.0, 'type': Condo}] -Greenwich 2006-11-20 2006-11-20 [{'date': 2006-11-20, 'amt': 2050000.0, 'type': Condo}] -Greenwich 2007-08-16 2007-08-16 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}] -Greenwich 2007-07-17 2007-07-17 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}] -Greenwich 2007-06-15 2007-06-15 [{'date': 2007-06-15, 'amt': 2264564.0, 'type': Condo}] -New Canaan 2007-02-15 2007-02-15 [{'date': 2007-02-15, 'amt': 2230000.0, 'type': Condo}] -Greenwich 2007-03-12 2007-03-12 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}] -Greenwich 2007-02-27 2007-02-27 [{'date': 2007-02-27, 'amt': 1120000.0, 'type': Condo}] +Clinton 2007-08-22 2007-08-22 [{'date': 2007-08-22, 'amt': 1175000.0, 'type': Condo}] Danbury 2007-05-02 2007-05-02 [{'date': 2007-05-02, 'amt': 3105000.0, 'type': Condo}] -Darien 2007-09-12 2007-09-12 [{'date': 2007-09-12, 'amt': 1150000.0, 'type': Condo}] Danbury 2007-05-09 2007-05-09 [{'date': 2007-05-09, 'amt': 1014205.0, 'type': Condo}] -Greenwich 2007-03-30 2007-03-30 [{'date': 2007-03-30, 'amt': 1200000.0, 'type': Condo}] -Greenwich 2007-03-20 2007-03-20 [{'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}] -Greenwich 2006-12-14 2006-12-14 [{'date': 2006-12-14, 'amt': 1800000.0, 'type': Condo}] -Clinton 2007-08-22 2007-08-22 [{'date': 2007-08-22, 'amt': 1175000.0, 'type': Condo}] -New Canaan 2007-01-22 2007-01-22 [{'date': 2007-01-22, 'amt': 1735000.0, 'type': Condo}] -Greenwich 2007-07-17 2007-07-19 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-19, 'amt': 3600000.0, 'type': Single Family}] -Greenwich 2007-08-16 2007-08-21 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-21, 'amt': 4100000.0, 'type': Single Family}] -Greenwich 2007-02-27 2007-03-02 [{'date': 2007-02-27, 'amt': 1120000.0, 'type': Condo}, {'date': 2007-03-02, 'amt': 6500000.0, 'type': Single Family}] -Greenwich 2007-03-12 2007-03-16 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}] -Greenwich 2007-06-15 2007-06-19 [{'date': 2007-06-15, 'amt': 2264564.0, 'type': Condo}, {'date': 2007-06-19, 'amt': 1965000.0, 'type': Single Family}] +Darien 2007-09-12 2007-09-12 [{'date': 2007-09-12, 'amt': 1150000.0, 'type': Condo}] +Fairfield 2007-06-15 2007-06-15 [{'date': 2007-06-15, 'amt': 1100000.0, 'type': Condo}] +Greenwich 2006-11-20 2006-11-20 [{'date': 2006-11-20, 'amt': 2050000.0, 'type': Condo}] Greenwich 2006-11-20 2006-11-21 [{'date': 2006-11-20, 'amt': 2050000.0, 'type': Condo}, {'date': 2006-11-21, 'amt': 6500000.0, 'type': Single Family}] -Greenwich 2007-07-10 2007-07-11 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-11, 'amt': 3250000.0, 'type': Single Family}] +Greenwich 2006-12-14 2006-12-14 [{'date': 2006-12-14, 'amt': 1800000.0, 'type': Condo}] +Greenwich 2006-12-14 2006-12-15 [{'date': 2006-12-14, 'amt': 1800000.0, 'type': Condo}, {'date': 2006-12-15, 'amt': 2195000.0, 'type': Single Family}] +Greenwich 2006-12-14 2006-12-15 [{'date': 2006-12-14, 'amt': 1800000.0, 'type': Condo}, {'date': 2006-12-15, 'amt': 5500000.0, 'type': Single Family}] +Greenwich 2006-12-14 2006-12-18 [{'date': 2006-12-14, 'amt': 1800000.0, 'type': Condo}, {'date': 2006-12-18, 'amt': 5010000.0, 'type': Single Family}] +Greenwich 2007-01-19 2007-01-19 [{'date': 2007-01-19, 'amt': 2227500.0, 'type': Condo}] +Greenwich 2007-01-19 2007-01-24 [{'date': 2007-01-19, 'amt': 2227500.0, 'type': Condo}, {'date': 2007-01-24, 'amt': 1750000.0, 'type': Single Family}] +Greenwich 2007-01-31 2007-01-31 [{'date': 2007-01-31, 'amt': 4600000.0, 'type': Condo}] +Greenwich 2007-02-27 2007-02-27 [{'date': 2007-02-27, 'amt': 1120000.0, 'type': Condo}] Greenwich 2007-02-27 2007-02-28 [{'date': 2007-02-27, 'amt': 1120000.0, 'type': Condo}, {'date': 2007-02-28, 'amt': 2260000.0, 'type': Single Family}] -Greenwich 2007-07-17 2007-07-20 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 18000000.0, 'type': Single Family}] -Greenwich 2007-07-10 2007-07-12 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}] Greenwich 2007-02-27 2007-03-01 [{'date': 2007-02-27, 'amt': 1120000.0, 'type': Condo}, {'date': 2007-03-01, 'amt': 1900000.0, 'type': Single Family}] +Greenwich 2007-02-27 2007-03-02 [{'date': 2007-02-27, 'amt': 1120000.0, 'type': Condo}, {'date': 2007-03-02, 'amt': 6500000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-12 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}] +Greenwich 2007-03-12 2007-03-13 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-13, 'amt': 1600000.0, 'type': Single Family}] Greenwich 2007-03-12 2007-03-16 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}] -Greenwich 2007-08-16 2007-08-17 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-17, 'amt': 3400000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-16 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-20 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}] +Greenwich 2007-03-12 2007-03-20 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}] +Greenwich 2007-03-12 2007-03-22 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-22, 'amt': 1580000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-22 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-22, 'amt': 1580000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-23 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-23, 'amt': 2850000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-23 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-23, 'amt': 2850000.0, 'type': Single Family}] +Greenwich 2007-03-20 2007-03-20 [{'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}] +Greenwich 2007-03-20 2007-03-22 [{'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-22, 'amt': 1580000.0, 'type': Single Family}] +Greenwich 2007-03-20 2007-03-23 [{'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-23, 'amt': 2850000.0, 'type': Single Family}] +Greenwich 2007-03-30 2007-03-30 [{'date': 2007-03-30, 'amt': 1200000.0, 'type': Condo}] +Greenwich 2007-05-15 2007-05-15 [{'date': 2007-05-15, 'amt': 1215000.0, 'type': Condo}] +Greenwich 2007-05-15 2007-05-17 [{'date': 2007-05-15, 'amt': 1215000.0, 'type': Condo}, {'date': 2007-05-17, 'amt': 2250000.0, 'type': Single Family}] +Greenwich 2007-06-15 2007-06-15 [{'date': 2007-06-15, 'amt': 2264564.0, 'type': Condo}] +Greenwich 2007-06-15 2007-06-19 [{'date': 2007-06-15, 'amt': 2264564.0, 'type': Condo}, {'date': 2007-06-19, 'amt': 1470000.0, 'type': Single Family}] +Greenwich 2007-06-15 2007-06-19 [{'date': 2007-06-15, 'amt': 2264564.0, 'type': Condo}, {'date': 2007-06-19, 'amt': 1965000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-10 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}] Greenwich 2007-07-10 2007-07-11 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-11, 'amt': 3150000.0, 'type': Single Family}] -Greenwich 2007-08-16 2007-08-17 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-17, 'amt': 1925000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-11 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-11, 'amt': 3250000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-11 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-11, 'amt': 7050000.0, 'type': Single Family}] Greenwich 2007-07-10 2007-07-12 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}] -Greenwich 2006-12-14 2006-12-15 [{'date': 2006-12-14, 'amt': 1800000.0, 'type': Condo}, {'date': 2006-12-15, 'amt': 2195000.0, 'type': Single Family}] -Greenwich 2007-03-20 2007-03-22 [{'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-22, 'amt': 1580000.0, 'type': Single Family}] -Greenwich 2007-03-12 2007-03-13 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-13, 'amt': 1600000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-12 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-17 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}] +Greenwich 2007-07-10 2007-07-17 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}] +Greenwich 2007-07-10 2007-07-19 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-19, 'amt': 3600000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-19 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-19, 'amt': 3600000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-20 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 7225000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-20 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 18000000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-20 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 7225000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-20 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 18000000.0, 'type': Single Family}] +Greenwich 2007-07-17 2007-07-17 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}] +Greenwich 2007-07-17 2007-07-19 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-19, 'amt': 3600000.0, 'type': Single Family}] Greenwich 2007-07-17 2007-07-20 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 7225000.0, 'type': Single Family}] +Greenwich 2007-07-17 2007-07-20 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 18000000.0, 'type': Single Family}] +Greenwich 2007-08-16 2007-08-16 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}] +Greenwich 2007-08-16 2007-08-17 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-17, 'amt': 1925000.0, 'type': Single Family}] +Greenwich 2007-08-16 2007-08-17 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-17, 'amt': 3400000.0, 'type': Single Family}] Greenwich 2007-08-16 2007-08-20 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-20, 'amt': 2590000.0, 'type': Single Family}] +Greenwich 2007-08-16 2007-08-21 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-21, 'amt': 4100000.0, 'type': Single Family}] +New Canaan 2007-01-22 2007-01-22 [{'date': 2007-01-22, 'amt': 1735000.0, 'type': Condo}] +New Canaan 2007-02-15 2007-02-15 [{'date': 2007-02-15, 'amt': 2230000.0, 'type': Condo}] + +# JoinDependentFilter triggers on this test, make sure that the result is the same with and without +statement ok +set disabled_optimizers to 'expression_rewriter' + +query IIII +with recursive + base as + ( select * + from 'https://github.com/duckdb/duckdb-data/releases/download/v1.0/Real_Estate_Sales_2001-2021_GL.csv' + where '2003-01-01' < "date recorded" and "date recorded" < '2010-01-01' and "sale amount" > 1000000 + ) + , chains as + ( + select + town + , "date recorded" as begTS + , "date recorded" as endTS + , [struct_pack(date:= "date recorded", amt:="sale amount", type:="property type")] as chain + from base + where "property type" = 'Condo' + union all + select + chains.town + , chains.begTS + , base."date recorded" as endTS + , list_append(chains.chain, struct_pack(date:= "date recorded", amt:="sale amount", type:="property type")) as chain + from base, chains + where + base.town = chains.town + and + ( + (len(chains.chain) = 1 and list_contains(['Residential', 'Single Family'], base."property type")) + or (len(chains.chain) = 2 and base."property type" = 'Condo') + or (len(chains.chain) = 3 and list_contains(['Residential', 'Single Family'], base."property type")) + ) + and chains.endTS < base."date recorded" + and base."date recorded" < (chains.endTS + interval 6 days) + ) + select * from chains + order by all; +---- +Clinton 2007-08-22 2007-08-22 [{'date': 2007-08-22, 'amt': 1175000.0, 'type': Condo}] +Danbury 2007-05-02 2007-05-02 [{'date': 2007-05-02, 'amt': 3105000.0, 'type': Condo}] +Danbury 2007-05-09 2007-05-09 [{'date': 2007-05-09, 'amt': 1014205.0, 'type': Condo}] +Darien 2007-09-12 2007-09-12 [{'date': 2007-09-12, 'amt': 1150000.0, 'type': Condo}] +Fairfield 2007-06-15 2007-06-15 [{'date': 2007-06-15, 'amt': 1100000.0, 'type': Condo}] +Greenwich 2006-11-20 2006-11-20 [{'date': 2006-11-20, 'amt': 2050000.0, 'type': Condo}] +Greenwich 2006-11-20 2006-11-21 [{'date': 2006-11-20, 'amt': 2050000.0, 'type': Condo}, {'date': 2006-11-21, 'amt': 6500000.0, 'type': Single Family}] +Greenwich 2006-12-14 2006-12-14 [{'date': 2006-12-14, 'amt': 1800000.0, 'type': Condo}] +Greenwich 2006-12-14 2006-12-15 [{'date': 2006-12-14, 'amt': 1800000.0, 'type': Condo}, {'date': 2006-12-15, 'amt': 2195000.0, 'type': Single Family}] Greenwich 2006-12-14 2006-12-15 [{'date': 2006-12-14, 'amt': 1800000.0, 'type': Condo}, {'date': 2006-12-15, 'amt': 5500000.0, 'type': Single Family}] -Greenwich 2007-01-19 2007-01-24 [{'date': 2007-01-19, 'amt': 2227500.0, 'type': Condo}, {'date': 2007-01-24, 'amt': 1750000.0, 'type': Single Family}] Greenwich 2006-12-14 2006-12-18 [{'date': 2006-12-14, 'amt': 1800000.0, 'type': Condo}, {'date': 2006-12-18, 'amt': 5010000.0, 'type': Single Family}] +Greenwich 2007-01-19 2007-01-19 [{'date': 2007-01-19, 'amt': 2227500.0, 'type': Condo}] +Greenwich 2007-01-19 2007-01-24 [{'date': 2007-01-19, 'amt': 2227500.0, 'type': Condo}, {'date': 2007-01-24, 'amt': 1750000.0, 'type': Single Family}] +Greenwich 2007-01-31 2007-01-31 [{'date': 2007-01-31, 'amt': 4600000.0, 'type': Condo}] +Greenwich 2007-02-27 2007-02-27 [{'date': 2007-02-27, 'amt': 1120000.0, 'type': Condo}] +Greenwich 2007-02-27 2007-02-28 [{'date': 2007-02-27, 'amt': 1120000.0, 'type': Condo}, {'date': 2007-02-28, 'amt': 2260000.0, 'type': Single Family}] +Greenwich 2007-02-27 2007-03-01 [{'date': 2007-02-27, 'amt': 1120000.0, 'type': Condo}, {'date': 2007-03-01, 'amt': 1900000.0, 'type': Single Family}] +Greenwich 2007-02-27 2007-03-02 [{'date': 2007-02-27, 'amt': 1120000.0, 'type': Condo}, {'date': 2007-03-02, 'amt': 6500000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-12 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}] +Greenwich 2007-03-12 2007-03-13 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-13, 'amt': 1600000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-16 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-16 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-20 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}] +Greenwich 2007-03-12 2007-03-20 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}] +Greenwich 2007-03-12 2007-03-22 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-22, 'amt': 1580000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-22 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-22, 'amt': 1580000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-23 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-23, 'amt': 2850000.0, 'type': Single Family}] +Greenwich 2007-03-12 2007-03-23 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-23, 'amt': 2850000.0, 'type': Single Family}] +Greenwich 2007-03-20 2007-03-20 [{'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}] +Greenwich 2007-03-20 2007-03-22 [{'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-22, 'amt': 1580000.0, 'type': Single Family}] Greenwich 2007-03-20 2007-03-23 [{'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-23, 'amt': 2850000.0, 'type': Single Family}] +Greenwich 2007-03-30 2007-03-30 [{'date': 2007-03-30, 'amt': 1200000.0, 'type': Condo}] +Greenwich 2007-05-15 2007-05-15 [{'date': 2007-05-15, 'amt': 1215000.0, 'type': Condo}] +Greenwich 2007-05-15 2007-05-17 [{'date': 2007-05-15, 'amt': 1215000.0, 'type': Condo}, {'date': 2007-05-17, 'amt': 2250000.0, 'type': Single Family}] +Greenwich 2007-06-15 2007-06-15 [{'date': 2007-06-15, 'amt': 2264564.0, 'type': Condo}] Greenwich 2007-06-15 2007-06-19 [{'date': 2007-06-15, 'amt': 2264564.0, 'type': Condo}, {'date': 2007-06-19, 'amt': 1470000.0, 'type': Single Family}] +Greenwich 2007-06-15 2007-06-19 [{'date': 2007-06-15, 'amt': 2264564.0, 'type': Condo}, {'date': 2007-06-19, 'amt': 1965000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-10 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}] +Greenwich 2007-07-10 2007-07-11 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-11, 'amt': 3150000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-11 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-11, 'amt': 3250000.0, 'type': Single Family}] Greenwich 2007-07-10 2007-07-11 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-11, 'amt': 7050000.0, 'type': Single Family}] -Greenwich 2007-05-15 2007-05-17 [{'date': 2007-05-15, 'amt': 1215000.0, 'type': Condo}, {'date': 2007-05-17, 'amt': 2250000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-12 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-12 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}] Greenwich 2007-07-10 2007-07-17 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}] Greenwich 2007-07-10 2007-07-17 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}] -Greenwich 2007-03-12 2007-03-20 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}] -Greenwich 2007-03-12 2007-03-20 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}] -Greenwich 2007-07-10 2007-07-19 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-19, 'amt': 3600000.0, 'type': Single Family}] Greenwich 2007-07-10 2007-07-19 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-19, 'amt': 3600000.0, 'type': Single Family}] -Greenwich 2007-07-10 2007-07-20 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 18000000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-19 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-19, 'amt': 3600000.0, 'type': Single Family}] +Greenwich 2007-07-10 2007-07-20 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 7225000.0, 'type': Single Family}] Greenwich 2007-07-10 2007-07-20 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 18000000.0, 'type': Single Family}] -Greenwich 2007-03-12 2007-03-22 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-22, 'amt': 1580000.0, 'type': Single Family}] -Greenwich 2007-03-12 2007-03-22 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-22, 'amt': 1580000.0, 'type': Single Family}] Greenwich 2007-07-10 2007-07-20 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 7225000.0, 'type': Single Family}] -Greenwich 2007-07-10 2007-07-20 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 1269000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 7225000.0, 'type': Single Family}] -Greenwich 2007-03-12 2007-03-23 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 12500000.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-23, 'amt': 2850000.0, 'type': Single Family}] -Greenwich 2007-03-12 2007-03-23 [{'date': 2007-03-12, 'amt': 1084687.0, 'type': Condo}, {'date': 2007-03-16, 'amt': 6537500.0, 'type': Single Family}, {'date': 2007-03-20, 'amt': 4100000.0, 'type': Condo}, {'date': 2007-03-23, 'amt': 2850000.0, 'type': Single Family}] - +Greenwich 2007-07-10 2007-07-20 [{'date': 2007-07-10, 'amt': 1240000.0, 'type': Condo}, {'date': 2007-07-12, 'amt': 3565000.0, 'type': Single Family}, {'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 18000000.0, 'type': Single Family}] +Greenwich 2007-07-17 2007-07-17 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}] +Greenwich 2007-07-17 2007-07-19 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-19, 'amt': 3600000.0, 'type': Single Family}] +Greenwich 2007-07-17 2007-07-20 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 7225000.0, 'type': Single Family}] +Greenwich 2007-07-17 2007-07-20 [{'date': 2007-07-17, 'amt': 3000000.0, 'type': Condo}, {'date': 2007-07-20, 'amt': 18000000.0, 'type': Single Family}] +Greenwich 2007-08-16 2007-08-16 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}] +Greenwich 2007-08-16 2007-08-17 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-17, 'amt': 1925000.0, 'type': Single Family}] +Greenwich 2007-08-16 2007-08-17 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-17, 'amt': 3400000.0, 'type': Single Family}] +Greenwich 2007-08-16 2007-08-20 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-20, 'amt': 2590000.0, 'type': Single Family}] +Greenwich 2007-08-16 2007-08-21 [{'date': 2007-08-16, 'amt': 2430000.0, 'type': Condo}, {'date': 2007-08-21, 'amt': 4100000.0, 'type': Single Family}] +New Canaan 2007-01-22 2007-01-22 [{'date': 2007-01-22, 'amt': 1735000.0, 'type': Condo}] +New Canaan 2007-02-15 2007-02-15 [{'date': 2007-02-15, 'amt': 2230000.0, 'type': Condo}] diff --git a/test/sql/copy/csv/rejects/csv_buffer_size_rejects.test b/test/sql/copy/csv/rejects/csv_buffer_size_rejects.test_slow similarity index 74% rename from test/sql/copy/csv/rejects/csv_buffer_size_rejects.test rename to test/sql/copy/csv/rejects/csv_buffer_size_rejects.test_slow index 35f44da755a..218362cf58c 100644 --- a/test/sql/copy/csv/rejects/csv_buffer_size_rejects.test +++ b/test/sql/copy/csv/rejects/csv_buffer_size_rejects.test_slow @@ -1,13 +1,13 @@ -# name: test/sql/copy/csv/rejects/csv_buffer_size_rejects.test +# name: test/sql/copy/csv/rejects/csv_buffer_size_rejects.test_slow # description: Force CSV Lines from errors to fall mid-buffers # group: [rejects] require skip_reload -# Test will fail on windows because byte_position is slightly different due to \r\n instead of \n +# Test fails on windows because byte_position is slightly different due to \r\n instead of \n. require notwindows -loop buffer_size 5 8 +loop buffer_size 5 10 # Ensure that we can get the schema if we reduce the sample size and ignore errors query IIIII @@ -22,9 +22,8 @@ BIGINT VARCHAR 11044 11044 2 query IIIIIIIIIII rowsort SELECT * EXCLUDE (scan_id, user_arguments) FROM reject_scans order by all; ---- -0 test/sql/copy/csv/data/error/mismatch/big_bad.csv , \0 \0 \n 0 false {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL -1 test/sql/copy/csv/data/error/mismatch/big_bad2.csv , \0 \0 \n 0 false {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL - +0 test/sql/copy/csv/data/error/mismatch/big_bad.csv , " " \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL +1 test/sql/copy/csv/data/error/mismatch/big_bad2.csv , " " \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL query IIIIIIIII rowsort SELECT * EXCLUDE (scan_id) FROM reject_errors order by all; diff --git a/test/sql/copy/csv/rejects/csv_incorrect_columns_amount_rejects.test b/test/sql/copy/csv/rejects/csv_incorrect_columns_amount_rejects.test index f1b63112a4c..6fc829c263b 100644 --- a/test/sql/copy/csv/rejects/csv_incorrect_columns_amount_rejects.test +++ b/test/sql/copy/csv/rejects/csv_incorrect_columns_amount_rejects.test @@ -18,8 +18,13 @@ SELECT * EXCLUDE (scan_id) FROM reject_errors order by all; ---- 0 1814 14505 14510 3 d MISSING COLUMNS 1,2,3 Expected Number of Columns: 4 Found: 3 0 1823 14575 14576 1 b MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 1 +0 1823 14575 14576 2 c MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 2 +0 1823 14575 14576 3 d MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 3 0 2378 19009 19010 1 b MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 1 +0 2378 19009 19010 2 c MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 2 +0 2378 19009 19010 3 d MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 3 0 2762 22075 22078 2 c MISSING COLUMNS 1,2 Expected Number of Columns: 4 Found: 2 +0 2762 22075 22078 3 d MISSING COLUMNS 1,2 Expected Number of Columns: 4 Found: 3 statement ok DROP TABLE reject_errors; @@ -59,9 +64,12 @@ query IIIIIIIII rowsort SELECT * EXCLUDE (scan_id) FROM reject_errors order by all; ---- 0 1604 12825 12826 1 b MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 1 +0 1604 12825 12826 2 c MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 2 +0 1604 12825 12826 3 d MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 3 0 1671 13355 13362 5 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 5 0 1671 13355 13364 6 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 6 0 2751 21999 22002 2 c MISSING COLUMNS 1,2 Expected Number of Columns: 4 Found: 2 +0 2751 21999 22002 3 d MISSING COLUMNS 1,2 Expected Number of Columns: 4 Found: 3 0 2768 22131 22138 5 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 5 0 2768 22131 22140 6 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 6 @@ -107,8 +115,13 @@ SELECT * EXCLUDE (scan_id) FROM reject_errors order by all ---- 0 1814 14505 14510 3 d MISSING COLUMNS 1,2,3 Expected Number of Columns: 4 Found: 3 0 1823 14575 14576 1 b MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 1 +0 1823 14575 14576 2 c MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 2 +0 1823 14575 14576 3 d MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 3 0 2378 19009 19010 1 b MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 1 +0 2378 19009 19010 2 c MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 2 +0 2378 19009 19010 3 d MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 3 0 2762 22075 22078 2 c MISSING COLUMNS 1,2 Expected Number of Columns: 4 Found: 2 +0 2762 22075 22078 3 d MISSING COLUMNS 1,2 Expected Number of Columns: 4 Found: 3 1 1096 8761 8768 5 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 5 1 1096 8761 8770 6 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 6 1 1159 9269 9276 5 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 5 @@ -116,9 +129,12 @@ SELECT * EXCLUDE (scan_id) FROM reject_errors order by all 1 1206 9649 9656 5 NULL TOO MANY COLUMNS 1,2,3,4,5 Expected Number of Columns: 4 Found: 5 1 2769 22155 22162 5 NULL TOO MANY COLUMNS 1,2,3,4,5 Expected Number of Columns: 4 Found: 5 2 1604 12825 12826 1 b MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 1 +2 1604 12825 12826 2 c MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 2 +2 1604 12825 12826 3 d MISSING COLUMNS 1 Expected Number of Columns: 4 Found: 3 2 1671 13355 13362 5 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 5 2 1671 13355 13364 6 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 6 2 2751 21999 22002 2 c MISSING COLUMNS 1,2 Expected Number of Columns: 4 Found: 2 +2 2751 21999 22002 3 d MISSING COLUMNS 1,2 Expected Number of Columns: 4 Found: 3 2 2768 22131 22138 5 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 5 2 2768 22131 22140 6 NULL TOO MANY COLUMNS 1,2,3,4,5,6 Expected Number of Columns: 4 Found: 6 3 3 17 24 5 NULL TOO MANY COLUMNS 1,2,3,4,5 Expected Number of Columns: 4 Found: 5 diff --git a/test/sql/copy/csv/rejects/csv_rejects_flush_cast.test b/test/sql/copy/csv/rejects/csv_rejects_flush_cast.test index 09daa735d6e..a40ae18bf46 100644 --- a/test/sql/copy/csv/rejects/csv_rejects_flush_cast.test +++ b/test/sql/copy/csv/rejects/csv_rejects_flush_cast.test @@ -7,15 +7,15 @@ require skip_reload # Test will fail on windows because byte_position is slightly different due to \r\n instead of \n require notwindows -query III -SELECT typeof(first(a)), typeof(first(b)), COUNT(*) FROM read_csv( +query IIIII +SELECT first(a), first(b), typeof(first(a)), typeof(first(b)), COUNT(*) FROM read_csv( 'data/csv/error/flush_cast.csv', columns = {'a': 'DATE', 'b': 'VARCHAR'}, store_rejects = true, delim = ',', dateformat = '%d-%m-%Y'); ---- -DATE VARCHAR 2811 +2001-09-25 bla DATE VARCHAR 2811 query IIIIIIIII SELECT * EXCLUDE (scan_id) FROM reject_errors order by all; diff --git a/test/sql/copy/csv/rejects/csv_rejects_flush_message.test b/test/sql/copy/csv/rejects/csv_rejects_flush_message.test index cb409c240f2..8cf25b447da 100644 --- a/test/sql/copy/csv/rejects/csv_rejects_flush_message.test +++ b/test/sql/copy/csv/rejects/csv_rejects_flush_message.test @@ -20,8 +20,7 @@ SELECT * FROM read_csv( query IIIIIIIII SELECT * EXCLUDE (scan_id) FROM reject_errors order by all; ---- -0 2 10 NULL 1 a CAST "not-a-number" Error when converting column "a". Could not convert string "not-a-number" to 'DECIMAL' -0 3 25 NULL 1 a CAST "-26,9568" Error when converting column "a". Could not convert string "-26,9568" to 'DECIMAL' -0 5 44 NULL 1 a CAST "33,4386" Error when converting column "a". Could not convert string "33,4386" to 'DECIMAL' -0 6 54 NULL 1 a CAST "33.4386,00" Error when converting column "a". Could not convert string "33.4386,00" to 'DECIMAL' - +0 2 10 10 1 a CAST "not-a-number" Error when converting column "a". Could not convert string "not-a-number" to 'DECIMAL' +0 3 25 25 1 a CAST "-26,9568" Error when converting column "a". Could not convert string "-26,9568" to 'DECIMAL' +0 5 44 44 1 a CAST "33,4386" Error when converting column "a". Could not convert string "33,4386" to 'DECIMAL' +0 6 54 54 1 a CAST "33.4386,00" Error when converting column "a". Could not convert string "33.4386,00" to 'DECIMAL' \ No newline at end of file diff --git a/test/sql/copy/csv/rejects/csv_rejects_read.test b/test/sql/copy/csv/rejects/csv_rejects_read.test index ba090366ac6..7e758eba777 100644 --- a/test/sql/copy/csv/rejects/csv_rejects_read.test +++ b/test/sql/copy/csv/rejects/csv_rejects_read.test @@ -231,3 +231,22 @@ DROP TABLE reject_errors; statement ok DROP TABLE reject_scans; +query IIIII rowsort +FROM read_csv('data/csv/rejects/dr_who.csv', columns={ 'date': 'DATE', 'datetime': 'TIMESTAMPTZ', 'time': 'TIME', 'timestamp': 'TIMESTAMP', 'time_tz': 'TIMETZ' }, store_rejects=true); +---- + + +query IIIIIIIII +SELECT * EXCLUDE (scan_id) FROM reject_errors ORDER BY ALL; +---- +0 2 38 38 1 date CAST not-a-date,not-a-datetime,not-a-time,not-a-timestamp,not-a-time-tz Error when converting column "date". Could not convert string "not-a-date" to 'DATE' +0 2 38 64 3 time CAST not-a-date,not-a-datetime,not-a-time,not-a-timestamp,not-a-time-tz Error when converting column "time". Could not convert string "not-a-time" to 'TIME' +0 2 38 75 4 timestamp CAST not-a-date,not-a-datetime,not-a-time,not-a-timestamp,not-a-time-tz Error when converting column "timestamp". Could not convert string "not-a-timestamp" to 'TIMESTAMP' +0 2 38 NULL 2 datetime CAST not-a-date,not-a-datetime,not-a-time,not-a-timestamp,not-a-time-tz Error when converting column "datetime". Could not convert string "not-a-datetime" to 'TIMESTAMP WITH TIME ZONE' +0 2 38 NULL 5 time_tz CAST not-a-date,not-a-datetime,not-a-time,not-a-timestamp,not-a-time-tz Error when converting column "time_tz". Could not convert string "not-a-time-tz" to 'TIME WITH TIME ZONE' + +statement ok +DROP TABLE reject_errors; + +statement ok +DROP TABLE reject_scans; \ No newline at end of file diff --git a/test/sql/copy/csv/rejects/csv_rejects_two_tables.test b/test/sql/copy/csv/rejects/csv_rejects_two_tables.test index 902031695f9..d5b00345470 100644 --- a/test/sql/copy/csv/rejects/csv_rejects_two_tables.test +++ b/test/sql/copy/csv/rejects/csv_rejects_two_tables.test @@ -19,8 +19,8 @@ BIGINT VARCHAR 11044 11044 2 query IIIIIIIIIIII SELECT * EXCLUDE (scan_id) FROM reject_scans order by all; ---- -0 test/sql/copy/csv/data/error/mismatch/big_bad.csv , \0 \0 \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL sample_size=1, store_rejects=true -1 test/sql/copy/csv/data/error/mismatch/big_bad2.csv , \0 \0 \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL sample_size=1, store_rejects=true +0 test/sql/copy/csv/data/error/mismatch/big_bad.csv , " " \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL sample_size=1, store_rejects=true +1 test/sql/copy/csv/data/error/mismatch/big_bad2.csv , " " \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL sample_size=1, store_rejects=true query IIIIIIIII SELECT * EXCLUDE (scan_id) FROM reject_errors order by all; @@ -54,8 +54,8 @@ BIGINT VARCHAR 11044 11044 2 query IIIIIIIIIIII SELECT * EXCLUDE (scan_id) FROM reject_scans order by all; ---- -0 test/sql/copy/csv/data/error/mismatch/big_bad.csv , \0 \0 \n 0 false {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_table='rejects_errors_2', sample_size=1 -1 test/sql/copy/csv/data/error/mismatch/big_bad2.csv , \0 \0 \n 0 false {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_table='rejects_errors_2', sample_size=1 +0 test/sql/copy/csv/data/error/mismatch/big_bad.csv , " " \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_table='rejects_errors_2', sample_size=1 +1 test/sql/copy/csv/data/error/mismatch/big_bad2.csv , " " \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_table='rejects_errors_2', sample_size=1 query IIIIIIIII SELECT * EXCLUDE (scan_id) FROM rejects_errors_2 order by all; @@ -80,8 +80,8 @@ BIGINT VARCHAR 11044 11044 2 query IIIIIIIIIIII SELECT * EXCLUDE (scan_id) FROM rejects_scan_2 order by all; ---- -0 test/sql/copy/csv/data/error/mismatch/big_bad.csv , \0 \0 \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_scan='rejects_scan_2', sample_size=1 -1 test/sql/copy/csv/data/error/mismatch/big_bad2.csv , \0 \0 \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_scan='rejects_scan_2', sample_size=1 +0 test/sql/copy/csv/data/error/mismatch/big_bad.csv , " " \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_scan='rejects_scan_2', sample_size=1 +1 test/sql/copy/csv/data/error/mismatch/big_bad2.csv , " " \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_scan='rejects_scan_2', sample_size=1 query IIIIIIIII SELECT * EXCLUDE (scan_id) FROM reject_errors order by all; @@ -106,8 +106,8 @@ query IIIIIIIIIIII SELECT * EXCLUDE (scan_id) FROM rejects_scan_3 order by all; ---- -0 test/sql/copy/csv/data/error/mismatch/big_bad.csv , \0 \0 \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_scan='rejects_scan_3', rejects_table='rejects_errors_3', sample_size=1 -1 test/sql/copy/csv/data/error/mismatch/big_bad2.csv , \0 \0 \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_scan='rejects_scan_3', rejects_table='rejects_errors_3', sample_size=1 +0 test/sql/copy/csv/data/error/mismatch/big_bad.csv , " " \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_scan='rejects_scan_3', rejects_table='rejects_errors_3', sample_size=1 +1 test/sql/copy/csv/data/error/mismatch/big_bad2.csv , " " \n 0 0 {'column0': 'BIGINT','column1': 'VARCHAR'} NULL NULL rejects_scan='rejects_scan_3', rejects_table='rejects_errors_3', sample_size=1 query IIIIIIIII SELECT * EXCLUDE (scan_id) FROM rejects_errors_3 order by all; diff --git a/test/sql/copy/csv/test_11840.test b/test/sql/copy/csv/test_11840.test new file mode 100644 index 00000000000..b84462d7c6f --- /dev/null +++ b/test/sql/copy/csv/test_11840.test @@ -0,0 +1,19 @@ +# name: test/sql/copy/csv/test_11840.test +# description: Test CSV Sniffing detects correct typesfor issue 11840 +# group: [csv] + +statement ok +PRAGMA enable_verification + +query I +FROM 'data/csv/date_specificity.csv' +---- +0.00 +12/17/2019 + +query I +select d FROM 'data/csv/special_date.csv' +---- +2000-01-01 +2002-02-02 +2004-12-13 \ No newline at end of file diff --git a/test/sql/copy/csv/test_12314.test_slow b/test/sql/copy/csv/test_12314.test_slow new file mode 100644 index 00000000000..ffebbb3093f --- /dev/null +++ b/test/sql/copy/csv/test_12314.test_slow @@ -0,0 +1,15 @@ +# name: test/sql/copy/csv/test_12314.test_slow +# description: Test CSV reading for issue 12314 +# group: [csv] + +require httpfs + +statement error +from read_csv('https://github.com/duckdb/duckdb-data/releases/download/v1.0/sample_data_12314.csv.gz',HEADER = 1, PARALLEL=false); +---- +Change the maximum length size, e.g., max_line_size=2097408 + +query I +select count(*) from read_csv('https://github.com/duckdb/duckdb-data/releases/download/v1.0/sample_data_12314.csv.gz',HEADER = 1, PARALLEL=false , max_line_size=2097408); +---- +26238 diff --git a/test/sql/copy/csv/test_big_header.test b/test/sql/copy/csv/test_big_header.test index 6aae677279f..f48c22e99da 100644 --- a/test/sql/copy/csv/test_big_header.test +++ b/test/sql/copy/csv/test_big_header.test @@ -2,6 +2,8 @@ # description: Test big header # group: [csv] +require vector_size 2048 + statement ok PRAGMA enable_verification diff --git a/test/sql/copy/csv/test_bug_9952.test b/test/sql/copy/csv/test_bug_9952.test deleted file mode 100644 index a33f791ef32..00000000000 --- a/test/sql/copy/csv/test_bug_9952.test +++ /dev/null @@ -1,12 +0,0 @@ -# name: test/sql/copy/csv/test_bug_9952.test -# description: Test bug from issue 9952 -# group: [csv] - -statement ok -PRAGMA enable_verification - -statement ok -FROM 'data/csv/num.tsv.gz' - -statement ok -FROM read_csv('data/csv/num.tsv.gz', sample_size=-1) diff --git a/test/sql/copy/csv/test_bug_9952.test_slow b/test/sql/copy/csv/test_bug_9952.test_slow new file mode 100644 index 00000000000..04e6cbc4599 --- /dev/null +++ b/test/sql/copy/csv/test_bug_9952.test_slow @@ -0,0 +1,16 @@ +# name: test/sql/copy/csv/test_bug_9952.test_slow +# description: Test bug from issue 9952 +# group: [csv] + +statement ok +PRAGMA enable_verification + +# This will fail because by default we will use " as quote if none is found. +statement error +FROM 'data/csv/num.tsv.gz' +---- +Value with unterminated quote found. + +# This works because we are sampling the whole thing +statement ok +FROM read_csv('data/csv/num.tsv.gz', sample_size=-1) diff --git a/test/sql/copy/csv/test_column_inconsistencies.test b/test/sql/copy/csv/test_column_inconsistencies.test index 022d65f9404..d2af08d7b0a 100644 --- a/test/sql/copy/csv/test_column_inconsistencies.test +++ b/test/sql/copy/csv/test_column_inconsistencies.test @@ -2,6 +2,8 @@ # description: Test bug from issue 10273 # group: [csv] +require vector_size 2048 + statement ok PRAGMA enable_verification diff --git a/test/sql/copy/csv/test_csv_error_message_type.test b/test/sql/copy/csv/test_csv_error_message_type.test index 93a564c2461..a107d033777 100644 --- a/test/sql/copy/csv/test_csv_error_message_type.test +++ b/test/sql/copy/csv/test_csv_error_message_type.test @@ -45,14 +45,29 @@ CREATE TABLE venue_2 ( , venuecity VARCHAR (30) , venuestate CHAR (2) , venueseats VARCHAR -) -; +); -# Similar to the https://tech.marksblogg.com/duckdb-1b-taxi-rides.html issue -statement error +statement ok INSERT INTO venue_2 SELECT * FROM read_csv('data/csv/venue_pipe_big.csv', sample_size = 1); + +query I +SELECT COUNT(*) from venue_2 ---- -This type was auto-detected from the CSV file. +2662 + +statement ok +DROP TABLE venue_2 + +statement ok +CREATE TABLE venue_2 ( + venueid SMALLINT NOT NULL /*PRIMARY KEY*/ + , venuename VARCHAR (100) + , venuecity VARCHAR (30) + , venuestate CHAR (2) + , venueseats VARCHAR +); + + # Check our possible solutions: #* Override the type for this column manually by setting the type explicitly, e.g. types={'venueseats': 'VARCHAR'} @@ -76,4 +91,4 @@ This type was auto-detected from the CSV file. statement error INSERT INTO venue SELECT * FROM read_csv('data/csv/venue_pipe.csv'); ---- -Conversion Error: Could not convert string '\N' to INT32 \ No newline at end of file +Could not convert string "\N" to 'INTEGER' \ No newline at end of file diff --git a/test/sql/copy/csv/test_csv_remote.test b/test/sql/copy/csv/test_csv_remote.test index 12a2876c688..688fc02f1ab 100644 --- a/test/sql/copy/csv/test_csv_remote.test +++ b/test/sql/copy/csv/test_csv_remote.test @@ -29,4 +29,4 @@ PRAGMA enable_verification query IIIIIIIIIII FROM sniff_csv('https://github.com/duckdb/duckdb/raw/main/data/csv/customer.csv?v=1') ---- -, " " \n 0 0 {'column00': 'BIGINT', 'column01': 'VARCHAR', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'BIGINT', 'column06': 'BIGINT', 'column07': 'VARCHAR', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'VARCHAR', 'column11': 'BIGINT', 'column12': 'BIGINT', 'column13': 'BIGINT', 'column14': 'VARCHAR', 'column15': 'VARCHAR', 'column16': 'VARCHAR', 'column17': 'BIGINT'} NULL NULL NULL FROM read_csv('https://github.com/duckdb/duckdb/raw/main/data/csv/customer.csv?v=1', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'VARCHAR', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'BIGINT', 'column06': 'BIGINT', 'column07': 'VARCHAR', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'VARCHAR', 'column11': 'BIGINT', 'column12': 'BIGINT', 'column13': 'BIGINT', 'column14': 'VARCHAR', 'column15': 'VARCHAR', 'column16': 'VARCHAR', 'column17': 'BIGINT'}); +, " " \n 0 0 [{'name': column00, 'type': BIGINT}, {'name': column01, 'type': VARCHAR}, {'name': column02, 'type': BIGINT}, {'name': column03, 'type': BIGINT}, {'name': column04, 'type': BIGINT}, {'name': column05, 'type': BIGINT}, {'name': column06, 'type': BIGINT}, {'name': column07, 'type': VARCHAR}, {'name': column08, 'type': VARCHAR}, {'name': column09, 'type': VARCHAR}, {'name': column10, 'type': VARCHAR}, {'name': column11, 'type': BIGINT}, {'name': column12, 'type': BIGINT}, {'name': column13, 'type': BIGINT}, {'name': column14, 'type': VARCHAR}, {'name': column15, 'type': VARCHAR}, {'name': column16, 'type': VARCHAR}, {'name': column17, 'type': BIGINT}] NULL NULL NULL FROM read_csv('https://github.com/duckdb/duckdb/raw/main/data/csv/customer.csv?v=1', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'VARCHAR', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'BIGINT', 'column06': 'BIGINT', 'column07': 'VARCHAR', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'VARCHAR', 'column11': 'BIGINT', 'column12': 'BIGINT', 'column13': 'BIGINT', 'column14': 'VARCHAR', 'column15': 'VARCHAR', 'column16': 'VARCHAR', 'column17': 'BIGINT'}); diff --git a/test/sql/copy/csv/test_headers_12089.test b/test/sql/copy/csv/test_headers_12089.test new file mode 100644 index 00000000000..f1c098c49a0 --- /dev/null +++ b/test/sql/copy/csv/test_headers_12089.test @@ -0,0 +1,17 @@ +# name: test/sql/copy/csv/test_headers_12089.test +# description: Test that headers described on #12089 are properly parsed. +# group: [csv] + +statement ok +PRAGMA enable_verification + +query I +select columns FROM sniff_csv('data/csv/headers/escaped_quote.csv'); +---- +[{'name': Name, 'type': VARCHAR}, {'name': Escaped''Quote, 'type': BIGINT}] + + +query I +select columns FROM sniff_csv('data/csv/headers/unescaped_quote.csv'); +---- +[{'name': Name, 'type': VARCHAR}, {'name': Unescaped'Quote, 'type': BIGINT}] \ No newline at end of file diff --git a/test/sql/copy/csv/test_ignore_errors.test b/test/sql/copy/csv/test_ignore_errors.test index 046b07995e8..85739dfc7cc 100644 --- a/test/sql/copy/csv/test_ignore_errors.test +++ b/test/sql/copy/csv/test_ignore_errors.test @@ -125,4 +125,13 @@ FROM read_csv('data/csv/titanic.csv', ignore_errors=1) limit 10 7 0 1 McCarthy, Mr. Timothy J male 54.0 0 0 17463 51.8625 E46 S 8 0 3 Palsson, Master. Gosta Leonard male 2.0 3 1 349909 21.075 NULL S 9 1 3 Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg) female 27.0 0 2 347742 11.1333 NULL S -10 1 2 Nasser, Mrs. Nicholas (Adele Achem) female 14.0 1 0 237736 30.0708 NULL C \ No newline at end of file +10 1 2 Nasser, Mrs. Nicholas (Adele Achem) female 14.0 1 0 237736 30.0708 NULL C + +query I +SELECT * FROM read_csv('data/csv/test_ignore_errors.csv', columns = {'Order ref ID': 'VARCHAR'}, ignore_errors=true); +---- + +query IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII +SELECT * FROM read_csv('data/csv/test_ignore_errors.csv', types = {'Order ref ID': 'VARCHAR'}, ignore_errors=true); +---- +40243121-bechamelfoodsin@gmail_com_item_01_2024.csv 523944955 163178211923806 163178211923806 swiggy Completed AMD_VASTRAPUR_JUNOS NFD - - AMD_VASTRAPUR_JUNOS_swiggy_JP 675029 NFD NFD NFD - 2024-01-02 20:46:54 2235571 474092 Exotica Pizza exotica pizza 1 539.0 26.95 aggregator 10.0 575.95 Medium | 1mm" Thin Crust 1797632 | 1876675 None Ahmedabad JP 1.0 0.0 27.45 10.0 0.0 27.45 10.0 Cooked 996331 5.0 0.0 549.0 \ No newline at end of file diff --git a/test/sql/copy/csv/test_insert_into_types.test b/test/sql/copy/csv/test_insert_into_types.test new file mode 100644 index 00000000000..51cb7601610 --- /dev/null +++ b/test/sql/copy/csv/test_insert_into_types.test @@ -0,0 +1,245 @@ +# name: test/sql/copy/csv/test_insert_into_types.test +# description: Test type pushdown from insert into operator +# group: [csv] + +statement ok +PRAGMA enable_verification + +statement ok +CREATE TABLE users ( + id INTEGER NOT NULL, /*primary key*/ + name VARCHAR(10) NOT NULL, + email VARCHAR +); + +statement ok +INSERT INTO users +SELECT * +FROM read_csv('data/csv/file_error.csv', ignore_errors=true, null_padding=true); + +query III +select * from users; +---- +1 alice alice@email.com +2 eve NULL + +# Test Projection +statement ok +CREATE TABLE proj ( + id INTEGER NOT NULL, /*primary key*/ +); + +statement ok +INSERT INTO proj +SELECT id +FROM read_csv('data/csv/file_error.csv', ignore_errors=true, null_padding=true); + +query I +select * from proj; +---- +1 +2 + +statement error +INSERT INTO proj +SELECT id +FROM read_csv('data/csv/file_error.csv'); +---- +Error when converting column "id". Could not convert string "3r" to 'INTEGER' + +statement ok +DROP table proj; + +statement ok +CREATE TABLE proj ( + name VARCHAR(10) NOT NULL, + id INTEGER NOT NULL, /*primary key*/ +); + +statement ok +INSERT INTO proj +SELECT name, id +FROM read_csv('data/csv/file_error.csv', ignore_errors=true, null_padding=true); + +query II +select * from proj; +---- +alice 1 +eve 2 + +statement error +INSERT INTO proj +SELECT name, id +FROM read_csv('data/csv/file_error.csv'); +---- +Could not convert string "3r" to 'INTEGER' + +statement ok +DROP table proj; + +statement ok +CREATE TABLE proj ( + email VARCHAR, + id INTEGER NOT NULL, /*primary key*/ +); + +statement ok +INSERT INTO proj +SELECT email, id +FROM read_csv('data/csv/file_error.csv', ignore_errors=true, null_padding=true); + +query II +select * from proj; +---- +alice@email.com 1 +NULL 2 + +statement error +INSERT INTO proj +SELECT name, id +FROM read_csv('data/csv/file_error.csv'); +---- +Could not convert string "3r" to 'INTEGER' + +statement ok +DROP table proj; + +statement ok +CREATE TABLE proj ( + email VARCHAR, + id VARCHAR NOT NULL, /*primary key*/ +); + +# A cast will not be pushed down +statement error +INSERT INTO proj +SELECT name, id::INTEGER +FROM read_csv('data/csv/file_error.csv'); +---- +Could not convert string '3r' to INT32 + +statement ok +DROP table proj; + +statement ok +CREATE TABLE proj ( + email VARCHAR, + id integer NOT NULL, /*primary key*/ +); + +# No pushdown if we have weird projections +statement error +INSERT INTO proj +SELECT 'Pedro', id +FROM read_csv('data/csv/file_error.csv'); +---- +Could not convert string '3r' to INT32 + +# No pushdown with mid-ops +statement ok +CREATE TABLE ppl ( + name VARCHAR +); + +statement ok +insert into ppl values ('alice'), ('bob'), ('pedro') + +statement error +INSERT INTO proj +SELECT ppl.name,id +FROM read_csv('data/csv/file_error.csv') T inner join ppl on (ppl.name = T.name); +---- +Could not convert string '3r' to INT32 + +statement error +INSERT INTO proj +SELECT T.name,id +FROM read_csv('data/csv/file_error.csv') T inner join ppl on (ppl.name = T.name); +---- +Could not convert string '3r' to INT32 + +# Test Glob +statement ok +DROP table users; + +statement ok +CREATE TABLE users ( + id INTEGER NOT NULL, /*primary key*/ + name VARCHAR(10) NOT NULL, + email VARCHAR +); + +statement ok +INSERT INTO users +SELECT * +FROM read_csv('data/csv/glob/f_*.csv', ignore_errors=true, null_padding=true); + +query III +select * from users; +---- +1 alice alice@email.com +2 eve eve@email.com +1 alice alice@email.com +3 bob bob@email.com +1 alice alice@email.com +3 bob bob@email.com + +# Test Glob + Projection + +statement ok +DROP table proj; + +statement ok +CREATE TABLE proj ( + email VARCHAR, + id integer NOT NULL +); + +statement ok +INSERT INTO proj +SELECT email, id +FROM read_csv('data/csv/glob/f_*.csv', ignore_errors=true, null_padding=true); + +query II +select * from proj; +---- +alice@email.com 1 +eve@email.com 2 +alice@email.com 1 +bob@email.com 3 +alice@email.com 1 +bob@email.com 3 + +# Test union by name +statement ok +CREATE TABLE users_age ( + id INTEGER NOT NULL, + name VARCHAR(10) NOT NULL, + email VARCHAR, + age integer +); + +statement ok +INSERT INTO users_age +SELECT * +FROM read_csv('data/csv/union-by-name/type_mismatch/f_*.csv', ignore_errors=true, null_padding=true, union_by_name=true); + +query IIII +select * from users_age; +---- +1 alice alice@email.com NULL +2 eve eve@email.com NULL +1 alice NULL 20 +3 bob NULL 32 + +# Only accept one reference per column +statement ok +create table timestamps(ts timestamp, dt date); + +statement ok +insert into timestamps select ts,ts from read_csv('data/csv/timestamp.csv'); + +query II +from timestamps; +---- +2020-01-01 01:02:03 2020-01-01 \ No newline at end of file diff --git a/test/sql/copy/csv/test_lineitem_gz.test b/test/sql/copy/csv/test_lineitem_gz.test new file mode 100644 index 00000000000..45d10ff86ee --- /dev/null +++ b/test/sql/copy/csv/test_lineitem_gz.test @@ -0,0 +1,38 @@ +# name: test/sql/copy/csv/test_lineitem_gz.test +# description: Test small memory limit on gzipped csv files +# group: [csv] + +# No way CI can handle this +mode skip + +statement ok +PRAGMA enable_verification + + +require tpch + +statement ok +CALL dbgen(sf=10); + +statement ok +copy lineitem to '__TEST_DIR__/lineitem1.csv.gz' + +statement ok +set memory_limit='32gb'; + +# Run it over 50 TPCHs +query I +select count(*) from read_csv([ +'__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz', +'__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz', +'__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz', +'__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz', +'__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz', +'__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz', +'__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz', +'__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz', +'__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz', +'__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz','__TEST_DIR__/lineitem1.csv.gz' +]); +---- +0 \ No newline at end of file diff --git a/test/sql/copy/csv/test_mixed_line_endings.test b/test/sql/copy/csv/test_mixed_line_endings.test index 894a4702905..ad27e310005 100644 --- a/test/sql/copy/csv/test_mixed_line_endings.test +++ b/test/sql/copy/csv/test_mixed_line_endings.test @@ -20,6 +20,13 @@ SELECT LENGTH(b) FROM test ORDER BY a; 5 4 +query III +select * from test; +---- +10 hello 20 +20 world 30 +30 test 30 + query RR SELECT SUM(a), SUM(c) FROM test; ---- diff --git a/test/sql/copy/csv/test_mixed_lines.test b/test/sql/copy/csv/test_mixed_lines.test_slow similarity index 99% rename from test/sql/copy/csv/test_mixed_lines.test rename to test/sql/copy/csv/test_mixed_lines.test_slow index 85959c9fe11..b8db9caf9d5 100644 --- a/test/sql/copy/csv/test_mixed_lines.test +++ b/test/sql/copy/csv/test_mixed_lines.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/copy/csv/test_mixed_lines.test +# name: test/sql/copy/csv/test_mixed_lines.test_slow # description: Test mixed lines # group: [csv] diff --git a/test/sql/copy/csv/test_partition_compression.test b/test/sql/copy/csv/test_partition_compression.test new file mode 100644 index 00000000000..c81ebcd1768 --- /dev/null +++ b/test/sql/copy/csv/test_partition_compression.test @@ -0,0 +1,63 @@ +# name: test/sql/copy/csv/test_partition_compression.test +# description: Test we can round-trip partitioned compressed CSV files +# group: [csv] + +statement ok +PRAGMA enable_verification + +require no_extension_autoloading + +statement ok +CREATE TABLE test AS VALUES ('a', 'foo', 1), ('a', 'foo', 2), ('a', 'bar', 1), ('b', 'bar', 1); + +statement ok +COPY (FROM test) TO '__TEST_DIR__/data.csv.d' (FORMAT 'csv', COMPRESSION 'gzip', PARTITION_BY ('col0', 'col1')); + +# Specify Compression +statement error +FROM read_csv_auto('__TEST_DIR__/data.csv.d/*/*/*.csv') +---- +No files found that match the pattern + +query III +FROM read_csv_auto('__TEST_DIR__/data.csv.d/*/*/*.csv.gz'); +---- +a bar 1 +a foo 1 +a foo 2 +b bar 1 + +query III +FROM read_csv_auto('__TEST_DIR__/data.csv.d/*/*/*.csv.*'); +---- +a bar 1 +a foo 1 +a foo 2 +b bar 1 + +require parquet + +statement ok +COPY (FROM test) TO '__TEST_DIR__/data.csv.d2' (FORMAT 'csv', COMPRESSION 'zstd', PARTITION_BY ('col0', 'col1')); + +# Specify Compression +statement error +FROM read_csv_auto('__TEST_DIR__/data.csv.d2/*/*/*.csv') +---- +No files found that match the pattern + +query III +FROM read_csv_auto('__TEST_DIR__/data.csv.d2/*/*/*.csv.zst'); +---- +a bar 1 +a foo 1 +a foo 2 +b bar 1 + +query III +FROM read_csv_auto('__TEST_DIR__/data.csv.d2/*/*/*.csv.*'); +---- +a bar 1 +a foo 1 +a foo 2 +b bar 1 diff --git a/test/sql/copy/csv/test_quote_default.test b/test/sql/copy/csv/test_quote_default.test new file mode 100644 index 00000000000..b548063fb88 --- /dev/null +++ b/test/sql/copy/csv/test_quote_default.test @@ -0,0 +1,13 @@ +# name: test/sql/copy/csv/test_quote_default.test +# description: Test quote and escape are set as default quoted option +# group: [csv] + +query III +select quote,escape,delimiter from sniff_csv('data/csv/test_default_option.csv') +---- +" " , + +query III +select quote,escape,delimiter from sniff_csv('data/csv/test_default_option_2.csv') +---- +" " | \ No newline at end of file diff --git a/test/sql/copy/csv/test_skip.test_slow b/test/sql/copy/csv/test_skip.test_slow new file mode 100644 index 00000000000..a3ae8ff7eca --- /dev/null +++ b/test/sql/copy/csv/test_skip.test_slow @@ -0,0 +1,284 @@ +# name: test/sql/copy/csv/test_skip.test_slow +# description: Test that the skip option works for csv files +# group: [csv] + +statement ok +PRAGMA enable_verification + +statement ok +copy (from range(10000)) to '__TEST_DIR__/skip.csv' (HEADER 0); + + +foreach auto_detect true false + +# Test -1 +statement error +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=-1, auto_detect = ${auto_detect}, columns = {'i': 'INTEGER'}); +---- +skip_rows option from read_csv scanner, must be equal or higher than 0 + +# Test 0 +query I +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=0, auto_detect = ${auto_detect}, columns = {'i': 'INTEGER'}); +---- +10000 + +# Test 3000 +query I +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=3000, auto_detect = ${auto_detect}, columns = {'i': 'INTEGER'}); +---- +7000 + +query I +select * from read_csv('__TEST_DIR__/skip.csv', skip=3000, auto_detect = ${auto_detect}, columns = {'i': 'INTEGER'}) order by all limit 1; +---- +3000 + +# Test 9999 +query I +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=9999, auto_detect = ${auto_detect}, columns = {'i': 'INTEGER'}); +---- +1 + +query I +select * from read_csv('__TEST_DIR__/skip.csv', skip=9999, auto_detect = ${auto_detect}, columns = {'i': 'INTEGER'}) order by all limit 1; +---- +9999 + +# test 10001 +query I +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=10001, auto_detect = ${auto_detect}, columns = {'i': 'INTEGER'}); +---- +0 + +# Test 11000 +query I +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=11000, auto_detect = ${auto_detect}, columns = {'i': 'INTEGER'}); +---- +0 + +endloop + +# Test sniff_csv function, exclude prompt since this is path dependent +query IIIIIIIIII +SELECT * EXCLUDE (prompt) from sniff_csv('__TEST_DIR__/skip.csv',skip=3000) +---- +, " " \n 3000 false [{'name': column0, 'type': BIGINT}] NULL NULL skip=3000 + +query IIIIIIIIII +SELECT * EXCLUDE (prompt) from sniff_csv('__TEST_DIR__/skip.csv',skip=11000) +---- +, " " \n 11000 0 [{'name': column0, 'type': BIGINT}] NULL NULL skip=11000 + +# Test with different buffer sizes + +loop buffer_size 5 10 + +# Test -1 +statement error +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=-1, buffer_size=${buffer_size}); +---- +skip_rows option from read_csv scanner, must be equal or higher than 0 + +# Test 0 +query I +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=0, buffer_size=${buffer_size}); +---- +10000 + +# Test 3000 +query I +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=3000, buffer_size=${buffer_size}); +---- +7000 + +query I +select * from read_csv('__TEST_DIR__/skip.csv', skip=3000, buffer_size=${buffer_size}) order by all limit 1; +---- +3000 + +# Test 9999 +query I +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=9999, buffer_size=${buffer_size}); +---- +1 + +query I +select * from read_csv('__TEST_DIR__/skip.csv', skip=9999, buffer_size=${buffer_size}) order by all limit 1; +---- +9999 + +# test 10001 +query I +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=10001, buffer_size=${buffer_size}); +---- +0 + +# Test 11000 +query I +select count(*) from read_csv('__TEST_DIR__/skip.csv', skip=11000, buffer_size=${buffer_size}); +---- +0 + +endloop + +# Now lets test a csv file with many lines of notes +statement ok +create table t (a varchar) + +statement ok +insert into t select '#This is a comment' from range(10000) + +statement ok +insert into t select '1,2,3' from range(10) + +statement ok +copy t to '__TEST_DIR__/skip_2.csv' (HEADER 0, delim ';'); + + +query III +from read_csv('__TEST_DIR__/skip_2.csv',skip=10000, buffer_size = 26) +---- +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 + +query IIIIIIIIII +SELECT * EXCLUDE (prompt) from sniff_csv('__TEST_DIR__/skip_2.csv',skip=10000) +---- +, " " \n 10000 0 [{'name': column0, 'type': BIGINT}, {'name': column1, 'type': BIGINT}, {'name': column2, 'type': BIGINT}] NULL NULL skip=10000 + +query III +from read_csv('__TEST_DIR__/skip_2.csv',skip=10000) +---- +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 + +loop buffer_size 20 25 + +query III +from read_csv('__TEST_DIR__/skip_2.csv',skip=10000, buffer_size = ${buffer_size}) +---- +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 + +endloop + +# Multifile Testing + +query III +from read_csv(['__TEST_DIR__/skip_2.csv','__TEST_DIR__/skip_2.csv','__TEST_DIR__/skip_2.csv'],skip=10000, buffer_size = 26) +---- +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 + +query III +from read_csv(['__TEST_DIR__/skip_2.csv','__TEST_DIR__/skip_2.csv','__TEST_DIR__/skip_2.csv'],skip=10000) +---- +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 +1 2 3 + +require tpch + +statement ok +CALL dbgen(sf=0.1); + +# Lineitem has about 75 mb +statement ok +COPY lineitem TO '__TEST_DIR__/lineitem.csv' (DELIMITER '|', HEADER); + +# Lets check skipping ~ 15 mb +query I +select count(*) from read_csv('__TEST_DIR__/lineitem.csv') +---- +600572 + +query I +select count(*) from read_csv('__TEST_DIR__/lineitem.csv', skip=158310) +---- +442263 + +# Lets check skipping ~ 40 mb +query I +select count(*) from read_csv('__TEST_DIR__/lineitem.csv', skip=474930) +---- +125643 \ No newline at end of file diff --git a/test/sql/copy/csv/test_sniff_csv.test b/test/sql/copy/csv/test_sniff_csv.test index ebebabb29e5..518115274db 100644 --- a/test/sql/copy/csv/test_sniff_csv.test +++ b/test/sql/copy/csv/test_sniff_csv.test @@ -24,7 +24,7 @@ FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=fal query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv'); ---- -| " " \n 0 0 {'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'} %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d'); +| " " \n 0 0 [{'name': column00, 'type': BIGINT}, {'name': column01, 'type': BIGINT}, {'name': column02, 'type': BIGINT}, {'name': column03, 'type': BIGINT}, {'name': column04, 'type': BIGINT}, {'name': column05, 'type': DOUBLE}, {'name': column06, 'type': DOUBLE}, {'name': column07, 'type': DOUBLE}, {'name': column08, 'type': VARCHAR}, {'name': column09, 'type': VARCHAR}, {'name': column10, 'type': DATE}, {'name': column11, 'type': DATE}, {'name': column12, 'type': DATE}, {'name': column13, 'type': VARCHAR}, {'name': column14, 'type': VARCHAR}, {'name': column15, 'type': VARCHAR}] %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d'); # Test Invalid Path statement error @@ -37,7 +37,7 @@ Cannot open file "test/sql/copy/csv/data/real/non_ecziste.csv": No such file or query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/error/mismatch/big_bad.csv', sample_size=1); ---- -, \0 \0 \n 0 0 {'column0': 'BIGINT', 'column1': 'VARCHAR'} NULL NULL sample_size=1 FROM read_csv('test/sql/copy/csv/data/error/mismatch/big_bad.csv', auto_detect=false, delim=',', quote='\0', escape='\0', new_line='\n', skip=0, header=false, columns={'column0': 'BIGINT', 'column1': 'VARCHAR'}, sample_size=1); +, " " \n 0 0 [{'name': column0, 'type': BIGINT}, {'name': column1, 'type': VARCHAR}] NULL NULL sample_size=1 FROM read_csv('test/sql/copy/csv/data/error/mismatch/big_bad.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column0': 'BIGINT', 'column1': 'VARCHAR'}, sample_size=1); statement error FROM read_csv('test/sql/copy/csv/data/error/mismatch/big_bad.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=0, columns={'column0': 'BIGINT', 'column1': 'VARCHAR'}, sample_size=1); @@ -47,18 +47,18 @@ Conversion Error: CSV Error on Line: 2176 query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/error/mismatch/big_bad.csv', sample_size=10000); ---- -, \0 \0 \n 0 1 {'1': 'VARCHAR', 'A': 'VARCHAR'} NULL NULL sample_size=10000 FROM read_csv('test/sql/copy/csv/data/error/mismatch/big_bad.csv', auto_detect=false, delim=',', quote='\0', escape='\0', new_line='\n', skip=0, header=true, columns={'1': 'VARCHAR', 'A': 'VARCHAR'}, sample_size=10000); +, " " \n 0 1 [{'name': 1, 'type': VARCHAR}, {'name': A, 'type': VARCHAR}] NULL NULL sample_size=10000 FROM read_csv('test/sql/copy/csv/data/error/mismatch/big_bad.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'1': 'VARCHAR', 'A': 'VARCHAR'}, sample_size=10000); query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/error/mismatch/big_bad.csv', sample_size=-1); ---- -, \0 \0 \n 0 1 {'1': 'VARCHAR', 'A': 'VARCHAR'} NULL NULL sample_size=-1 FROM read_csv('test/sql/copy/csv/data/error/mismatch/big_bad.csv', auto_detect=false, delim=',', quote='\0', escape='\0', new_line='\n', skip=0, header=true, columns={'1': 'VARCHAR', 'A': 'VARCHAR'}, sample_size=-1); +, " " \n 0 1 [{'name': 1, 'type': VARCHAR}, {'name': A, 'type': VARCHAR}] NULL NULL sample_size=-1 FROM read_csv('test/sql/copy/csv/data/error/mismatch/big_bad.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'1': 'VARCHAR', 'A': 'VARCHAR'}, sample_size=-1); # Test with defined time and timestamp query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/test/dateformat.csv') ---- -, " " \n 0 0 {'column0': 'DATE'} %d/%m/%Y NULL NULL FROM read_csv('test/sql/copy/csv/data/test/dateformat.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column0': 'DATE'}, dateformat='%d/%m/%Y'); +, " " \n 0 0 [{'name': column0, 'type': DATE}] %d/%m/%Y NULL NULL FROM read_csv('test/sql/copy/csv/data/test/dateformat.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column0': 'DATE'}, dateformat='%d/%m/%Y'); query I FROM read_csv('test/sql/copy/csv/data/test/dateformat.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column0': 'DATE'}, dateformat='%d/%m/%Y'); @@ -69,7 +69,7 @@ FROM read_csv('test/sql/copy/csv/data/test/dateformat.csv', auto_detect=false, d query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv') ---- -, " " \n 0 1 {'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'} %Y.%m.%d %Y.%m.%d %H:%M:%S NULL FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'}, dateformat='%Y.%m.%d', timestampformat='%Y.%m.%d %H:%M:%S'); +, " " \n 0 1 [{'name': a, 'type': BIGINT}, {'name': b, 'type': VARCHAR}, {'name': t, 'type': TIME}, {'name': d, 'type': DATE}, {'name': ts, 'type': TIMESTAMP}] %Y.%m.%d %Y.%m.%d %H:%M:%S NULL FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'}, dateformat='%Y.%m.%d', timestampformat='%Y.%m.%d %H:%M:%S'); query IIIII FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'}, dateformat='%Y.%m.%d', timestampformat='%Y.%m.%d %H:%M:%S'); @@ -82,7 +82,7 @@ FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', query IIIIIIIIIII FROM sniff_csv('data/csv/inconsistent_cells.csv') ---- -, " " \n 3 0 {'column0': 'BIGINT', 'column1': 'BIGINT', 'column2': 'BIGINT', 'column3': 'BIGINT', 'column4': 'BIGINT'} NULL NULL NULL FROM read_csv('data/csv/inconsistent_cells.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=3, header=false, columns={'column0': 'BIGINT', 'column1': 'BIGINT', 'column2': 'BIGINT', 'column3': 'BIGINT', 'column4': 'BIGINT'}); +, " " \n 3 0 [{'name': column0, 'type': BIGINT}, {'name': column1, 'type': BIGINT}, {'name': column2, 'type': BIGINT}, {'name': column3, 'type': BIGINT}, {'name': column4, 'type': BIGINT}] NULL NULL NULL FROM read_csv('data/csv/inconsistent_cells.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=3, header=false, columns={'column0': 'BIGINT', 'column1': 'BIGINT', 'column2': 'BIGINT', 'column3': 'BIGINT', 'column4': 'BIGINT'}); query IIIII FROM read_csv('data/csv/inconsistent_cells.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=3, header=false, columns={'column0': 'BIGINT', 'column1': 'BIGINT', 'column2': 'BIGINT', 'column3': 'BIGINT', 'column4': 'BIGINT'}); @@ -94,7 +94,7 @@ FROM read_csv('data/csv/inconsistent_cells.csv', auto_detect=false, delim=',', q query IIIIIIIIIII FROM sniff_csv('data/csv/timings.csv') ---- -| " " \n 0 1 {'tool': 'VARCHAR', 'sf': 'BIGINT', 'day': 'DATE', 'batch_type': 'VARCHAR', 'q': 'VARCHAR', 'parameters': 'VARCHAR', 'time': 'DOUBLE'} %Y-%m-%d NULL NULL FROM read_csv('data/csv/timings.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'tool': 'VARCHAR', 'sf': 'BIGINT', 'day': 'DATE', 'batch_type': 'VARCHAR', 'q': 'VARCHAR', 'parameters': 'VARCHAR', 'time': 'DOUBLE'}, dateformat='%Y-%m-%d'); +| " " \n 0 1 [{'name': tool, 'type': VARCHAR}, {'name': sf, 'type': BIGINT}, {'name': day, 'type': DATE}, {'name': batch_type, 'type': VARCHAR}, {'name': q, 'type': VARCHAR}, {'name': parameters, 'type': VARCHAR}, {'name': time, 'type': DOUBLE}] %Y-%m-%d NULL NULL FROM read_csv('data/csv/timings.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'tool': 'VARCHAR', 'sf': 'BIGINT', 'day': 'DATE', 'batch_type': 'VARCHAR', 'q': 'VARCHAR', 'parameters': 'VARCHAR', 'time': 'DOUBLE'}, dateformat='%Y-%m-%d'); query IIIIIII FROM read_csv('data/csv/timings.csv', auto_detect=false, delim='|', quote='"', escape='\', new_line='\n', skip=0, header=true, columns={'tool': 'VARCHAR', 'sf': 'BIGINT', 'day': 'DATE', 'batch_type': 'VARCHAR', 'q': 'VARCHAR', 'parameters': 'VARCHAR', 'time': 'DOUBLE'}, dateformat='%Y-%m-%d') order by all limit 1; @@ -105,7 +105,7 @@ Umbra 100 2012-11-29 power 1 {"datetime": "2010-02-26T03:51:21.000+00:00"} 0.054 query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/auto/backslash_escape.csv') ---- -| " \ \n 0 false {'column0': 'BIGINT', 'column1': 'VARCHAR', 'column2': 'VARCHAR'} NULL NULL NULL FROM read_csv('test/sql/copy/csv/data/auto/backslash_escape.csv', auto_detect=false, delim='|', quote='"', escape='\', new_line='\n', skip=0, header=false, columns={'column0': 'BIGINT', 'column1': 'VARCHAR', 'column2': 'VARCHAR'}); +| " \ \n 0 0 [{'name': column0, 'type': BIGINT}, {'name': column1, 'type': VARCHAR}, {'name': column2, 'type': VARCHAR}] NULL NULL NULL FROM read_csv('test/sql/copy/csv/data/auto/backslash_escape.csv', auto_detect=false, delim='|', quote='"', escape='\', new_line='\n', skip=0, header=false, columns={'column0': 'BIGINT', 'column1': 'VARCHAR', 'column2': 'VARCHAR'}); query III FROM read_csv('test/sql/copy/csv/data/auto/backslash_escape.csv', auto_detect=false, delim='|', quote='"', escape='\', new_line='\n', skip=0, header=false, columns={'column0': 'BIGINT', 'column1': 'VARCHAR', 'column2': 'VARCHAR'}); diff --git a/test/sql/copy/csv/test_sniff_csv_options.test b/test/sql/copy/csv/test_sniff_csv_options.test index aa402aa58cb..b5845518369 100644 --- a/test/sql/copy/csv/test_sniff_csv_options.test +++ b/test/sql/copy/csv/test_sniff_csv_options.test @@ -17,31 +17,31 @@ CSV options could not be auto-detected. Consider setting parser options manually query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', delim='|'); ---- -| " " \n 0 false {'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'} %Y-%m-%d NULL delim='|' FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d', delim='|'); +| " " \n 0 0 [{'name': column00, 'type': BIGINT}, {'name': column01, 'type': BIGINT}, {'name': column02, 'type': BIGINT}, {'name': column03, 'type': BIGINT}, {'name': column04, 'type': BIGINT}, {'name': column05, 'type': DOUBLE}, {'name': column06, 'type': DOUBLE}, {'name': column07, 'type': DOUBLE}, {'name': column08, 'type': VARCHAR}, {'name': column09, 'type': VARCHAR}, {'name': column10, 'type': DATE}, {'name': column11, 'type': DATE}, {'name': column12, 'type': DATE}, {'name': column13, 'type': VARCHAR}, {'name': column14, 'type': VARCHAR}, {'name': column15, 'type': VARCHAR}] %Y-%m-%d NULL delim='|' FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d', delim='|'); # quote query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', quote='"'); ---- -| " " \n 0 0 {'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'} %Y-%m-%d NULL quote='"' FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d', quote='"'); +| " " \n 0 0 [{'name': column00, 'type': BIGINT}, {'name': column01, 'type': BIGINT}, {'name': column02, 'type': BIGINT}, {'name': column03, 'type': BIGINT}, {'name': column04, 'type': BIGINT}, {'name': column05, 'type': DOUBLE}, {'name': column06, 'type': DOUBLE}, {'name': column07, 'type': DOUBLE}, {'name': column08, 'type': VARCHAR}, {'name': column09, 'type': VARCHAR}, {'name': column10, 'type': DATE}, {'name': column11, 'type': DATE}, {'name': column12, 'type': DATE}, {'name': column13, 'type': VARCHAR}, {'name': column14, 'type': VARCHAR}, {'name': column15, 'type': VARCHAR}] %Y-%m-%d NULL quote='"' FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d', quote='"'); # escape query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', escape='"'); ---- -| " " \n 0 0 {'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'} %Y-%m-%d NULL escape='"' FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d', escape='"'); +| " " \n 0 0 [{'name': column00, 'type': BIGINT}, {'name': column01, 'type': BIGINT}, {'name': column02, 'type': BIGINT}, {'name': column03, 'type': BIGINT}, {'name': column04, 'type': BIGINT}, {'name': column05, 'type': DOUBLE}, {'name': column06, 'type': DOUBLE}, {'name': column07, 'type': DOUBLE}, {'name': column08, 'type': VARCHAR}, {'name': column09, 'type': VARCHAR}, {'name': column10, 'type': DATE}, {'name': column11, 'type': DATE}, {'name': column12, 'type': DATE}, {'name': column13, 'type': VARCHAR}, {'name': column14, 'type': VARCHAR}, {'name': column15, 'type': VARCHAR}] %Y-%m-%d NULL escape='"' FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d', escape='"'); # column names query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', escape='"'); ---- -| " " \n 0 0 {'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'} %Y-%m-%d NULL escape='"' FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d', escape='"'); +| " " \n 0 0 [{'name': column00, 'type': BIGINT}, {'name': column01, 'type': BIGINT}, {'name': column02, 'type': BIGINT}, {'name': column03, 'type': BIGINT}, {'name': column04, 'type': BIGINT}, {'name': column05, 'type': DOUBLE}, {'name': column06, 'type': DOUBLE}, {'name': column07, 'type': DOUBLE}, {'name': column08, 'type': VARCHAR}, {'name': column09, 'type': VARCHAR}, {'name': column10, 'type': DATE}, {'name': column11, 'type': DATE}, {'name': column12, 'type': DATE}, {'name': column13, 'type': VARCHAR}, {'name': column14, 'type': VARCHAR}, {'name': column15, 'type': VARCHAR}] %Y-%m-%d NULL escape='"' FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', new_line='\n', skip=0, header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d', escape='"'); # column names and types query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', names=['c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10', 'c11', 'c12', 'c13', 'c14', 'c15', 'c16']); ---- -| " " \n 0 0 {'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'} %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'}, dateformat='%Y-%m-%d'); +| " " \n 0 0 [{'name': c1, 'type': BIGINT}, {'name': c2, 'type': BIGINT}, {'name': c3, 'type': BIGINT}, {'name': c4, 'type': BIGINT}, {'name': c5, 'type': BIGINT}, {'name': c6, 'type': DOUBLE}, {'name': c7, 'type': DOUBLE}, {'name': c8, 'type': DOUBLE}, {'name': c9, 'type': VARCHAR}, {'name': c10, 'type': VARCHAR}, {'name': c11, 'type': DATE}, {'name': c12, 'type': DATE}, {'name': c13, 'type': DATE}, {'name': c14, 'type': VARCHAR}, {'name': c15, 'type': VARCHAR}, {'name': c16, 'type': VARCHAR}] %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'}, dateformat='%Y-%m-%d'); query IIIIIIIIIIIIIIII @@ -52,37 +52,37 @@ FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=fal query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', columns={'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'}); ---- -| " " \n 0 0 {'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'} %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'}, dateformat='%Y-%m-%d'); +| " " \n 0 0 [{'name': c1, 'type': BIGINT}, {'name': c2, 'type': BIGINT}, {'name': c3, 'type': BIGINT}, {'name': c4, 'type': BIGINT}, {'name': c5, 'type': BIGINT}, {'name': c6, 'type': DOUBLE}, {'name': c7, 'type': DOUBLE}, {'name': c8, 'type': DOUBLE}, {'name': c9, 'type': VARCHAR}, {'name': c10, 'type': VARCHAR}, {'name': c11, 'type': DATE}, {'name': c12, 'type': DATE}, {'name': c13, 'type': DATE}, {'name': c14, 'type': VARCHAR}, {'name': c15, 'type': VARCHAR}, {'name': c16, 'type': VARCHAR}] %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'}, dateformat='%Y-%m-%d'); # skip rows query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', skip=1); ---- -| " " \n 1 false {'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'} %Y-%m-%d NULL skip=1 FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d', skip=1); +| " " \n 1 0 [{'name': column00, 'type': BIGINT}, {'name': column01, 'type': BIGINT}, {'name': column02, 'type': BIGINT}, {'name': column03, 'type': BIGINT}, {'name': column04, 'type': BIGINT}, {'name': column05, 'type': DOUBLE}, {'name': column06, 'type': DOUBLE}, {'name': column07, 'type': DOUBLE}, {'name': column08, 'type': VARCHAR}, {'name': column09, 'type': VARCHAR}, {'name': column10, 'type': DATE}, {'name': column11, 'type': DATE}, {'name': column12, 'type': DATE}, {'name': column13, 'type': VARCHAR}, {'name': column14, 'type': VARCHAR}, {'name': column15, 'type': VARCHAR}] %Y-%m-%d NULL skip=1 FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', header=false, columns={'column00': 'BIGINT', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d', skip=1); # header exists query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', header=true); ---- -| " " \n 0 true {'1': 'BIGINT', '15519': 'BIGINT', '785': 'BIGINT', '1_1': 'BIGINT', '17': 'BIGINT', '24386.670000': 'DOUBLE', '0.040000': 'DOUBLE', '0.020000': 'DOUBLE', 'N': 'VARCHAR', 'O': 'VARCHAR', '1996-03-13': 'DATE', '1996-02-12': 'DATE', '1996-03-22': 'DATE', 'DELIVER IN PERSON': 'VARCHAR', 'TRUCK': 'VARCHAR', 'egular courts above the': 'VARCHAR'} %Y-%m-%d NULL header=true FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', escape='"', new_line='\n', skip=0, columns={'1': 'BIGINT', '15519': 'BIGINT', '785': 'BIGINT', '1_1': 'BIGINT', '17': 'BIGINT', '24386.670000': 'DOUBLE', '0.040000': 'DOUBLE', '0.020000': 'DOUBLE', 'N': 'VARCHAR', 'O': 'VARCHAR', '1996-03-13': 'DATE', '1996-02-12': 'DATE', '1996-03-22': 'DATE', 'DELIVER IN PERSON': 'VARCHAR', 'TRUCK': 'VARCHAR', 'egular courts above the': 'VARCHAR'}, dateformat='%Y-%m-%d', header=true); +| " " \n 0 1 [{'name': 1, 'type': BIGINT}, {'name': 15519, 'type': BIGINT}, {'name': 785, 'type': BIGINT}, {'name': 1_1, 'type': BIGINT}, {'name': 17, 'type': BIGINT}, {'name': 24386.670000, 'type': DOUBLE}, {'name': 0.040000, 'type': DOUBLE}, {'name': 0.020000, 'type': DOUBLE}, {'name': N, 'type': VARCHAR}, {'name': O, 'type': VARCHAR}, {'name': 1996-03-13, 'type': DATE}, {'name': 1996-02-12, 'type': DATE}, {'name': 1996-03-22, 'type': DATE}, {'name': DELIVER IN PERSON, 'type': VARCHAR}, {'name': TRUCK, 'type': VARCHAR}, {'name': egular courts above the, 'type': VARCHAR}] %Y-%m-%d NULL header=true FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', escape='"', new_line='\n', skip=0, columns={'1': 'BIGINT', '15519': 'BIGINT', '785': 'BIGINT', '1_1': 'BIGINT', '17': 'BIGINT', '24386.670000': 'DOUBLE', '0.040000': 'DOUBLE', '0.020000': 'DOUBLE', 'N': 'VARCHAR', 'O': 'VARCHAR', '1996-03-13': 'DATE', '1996-02-12': 'DATE', '1996-03-22': 'DATE', 'DELIVER IN PERSON': 'VARCHAR', 'TRUCK': 'VARCHAR', 'egular courts above the': 'VARCHAR'}, dateformat='%Y-%m-%d', header=true); # timestampformat query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', dateformat='%Y.%m.%d') ---- -, " " \n 0 true {'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'} %Y.%m.%d %Y.%m.%d %H:%M:%S dateformat='%Y.%m.%d' FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'}, timestampformat='%Y.%m.%d %H:%M:%S', dateformat='%Y.%m.%d'); +, " " \n 0 1 [{'name': a, 'type': BIGINT}, {'name': b, 'type': VARCHAR}, {'name': t, 'type': TIME}, {'name': d, 'type': DATE}, {'name': ts, 'type': TIMESTAMP}] %Y.%m.%d %Y.%m.%d %H:%M:%S dateformat='%Y.%m.%d' FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'}, timestampformat='%Y.%m.%d %H:%M:%S', dateformat='%Y.%m.%d'); # dateformat query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', timestampformat='%Y.%m.%d %H:%M:%S') ---- -, " " \n 0 1 {'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'} %Y.%m.%d %Y.%m.%d %H:%M:%S timestampformat='%Y.%m.%d %H:%M:%S' FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'}, dateformat='%Y.%m.%d', timestampformat='%Y.%m.%d %H:%M:%S'); +, " " \n 0 1 [{'name': a, 'type': BIGINT}, {'name': b, 'type': VARCHAR}, {'name': t, 'type': TIME}, {'name': d, 'type': DATE}, {'name': ts, 'type': TIMESTAMP}] %Y.%m.%d %Y.%m.%d %H:%M:%S timestampformat='%Y.%m.%d %H:%M:%S' FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'}, dateformat='%Y.%m.%d', timestampformat='%Y.%m.%d %H:%M:%S'); # Test a combination query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', dateformat='%Y.%m.%d', timestampformat='%Y.%m.%d %H:%M:%S') ---- -, " " \n 0 1 {'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'} %Y.%m.%d %Y.%m.%d %H:%M:%S dateformat='%Y.%m.%d', timestampformat='%Y.%m.%d %H:%M:%S' FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'}, dateformat='%Y.%m.%d', timestampformat='%Y.%m.%d %H:%M:%S'); +, " " \n 0 1 [{'name': a, 'type': BIGINT}, {'name': b, 'type': VARCHAR}, {'name': t, 'type': TIME}, {'name': d, 'type': DATE}, {'name': ts, 'type': TIMESTAMP}] %Y.%m.%d %Y.%m.%d %H:%M:%S dateformat='%Y.%m.%d', timestampformat='%Y.%m.%d %H:%M:%S' FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'}, dateformat='%Y.%m.%d', timestampformat='%Y.%m.%d %H:%M:%S'); query IIIII FROM read_csv('test/sql/copy/csv/data/auto/time_date_timestamp_yyyy.mm.dd.csv', auto_detect=false, delim=',', quote='"', escape='"', new_line='\n', skip=0, header=true, columns={'a': 'BIGINT', 'b': 'VARCHAR', 't': 'TIME', 'd': 'DATE', 'ts': 'TIMESTAMP'}, timestampformat='%Y.%m.%d %H:%M:%S', dateformat='%Y.%m.%d') order by all limit 1; @@ -98,13 +98,13 @@ sniff_csv function does not accept auto_detect variable set to false query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', columns={'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'}, auto_detect = true); ---- -| " " \n 0 0 {'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'} %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'}, dateformat='%Y-%m-%d'); +| " " \n 0 0 [{'name': c1, 'type': BIGINT}, {'name': c2, 'type': BIGINT}, {'name': c3, 'type': BIGINT}, {'name': c4, 'type': BIGINT}, {'name': c5, 'type': BIGINT}, {'name': c6, 'type': DOUBLE}, {'name': c7, 'type': DOUBLE}, {'name': c8, 'type': DOUBLE}, {'name': c9, 'type': VARCHAR}, {'name': c10, 'type': VARCHAR}, {'name': c11, 'type': DATE}, {'name': c12, 'type': DATE}, {'name': c13, 'type': DATE}, {'name': c14, 'type': VARCHAR}, {'name': c15, 'type': VARCHAR}, {'name': c16, 'type': VARCHAR}] %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'c1': 'BIGINT', 'c2': 'BIGINT', 'c3': 'BIGINT', 'c4': 'BIGINT', 'c5': 'BIGINT', 'c6': 'DOUBLE', 'c7': 'DOUBLE', 'c8': 'DOUBLE', 'c9': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'}, dateformat='%Y-%m-%d'); # auto_type_candidates query IIIIIIIIIII FROM sniff_csv('data/csv/autotypecandidates.csv', auto_type_candidates=['SMALLINT','BIGINT', 'DOUBLE', 'FLOAT','VARCHAR']); ---- -| " " \n 0 0 {'column0': 'SMALLINT', 'column1': 'FLOAT', 'column2': 'VARCHAR'} NULL NULL NULL FROM read_csv('data/csv/autotypecandidates.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column0': 'SMALLINT', 'column1': 'FLOAT', 'column2': 'VARCHAR'}); +| " " \n 0 0 [{'name': column0, 'type': SMALLINT}, {'name': column1, 'type': FLOAT}, {'name': column2, 'type': VARCHAR}] NULL NULL NULL FROM read_csv('data/csv/autotypecandidates.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column0': 'SMALLINT', 'column1': 'FLOAT', 'column2': 'VARCHAR'}); query III FROM read_csv('data/csv/autotypecandidates.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column0': 'SMALLINT', 'column1': 'FLOAT', 'column2': 'VARCHAR'}); @@ -127,24 +127,24 @@ Invalid named parameter "oop" for function sniff_csv query IIIIIIIIIII FROM sniff_csv('data/csv/autotypecandidates.csv', HIVE_PARTITIONING=1); ---- -| " " \n 0 false {'column0': 'BIGINT', 'column1': 'DOUBLE', 'column2': 'VARCHAR'} NULL NULL NULL FROM read_csv('data/csv/autotypecandidates.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column0': 'BIGINT', 'column1': 'DOUBLE', 'column2': 'VARCHAR'}); +| " " \n 0 0 [{'name': column0, 'type': BIGINT}, {'name': column1, 'type': DOUBLE}, {'name': column2, 'type': VARCHAR}] NULL NULL NULL FROM read_csv('data/csv/autotypecandidates.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column0': 'BIGINT', 'column1': 'DOUBLE', 'column2': 'VARCHAR'}); query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', types=['INTEGER','BIGINT','BIGINT','BIGINT','BIGINT', 'DOUBLE','DOUBLE','DOUBLE','VARCHAR', 'VARCHAR','DATE', 'DATE', 'DATE', 'VARCHAR', 'VARCHAR', 'VARCHAR']); ---- -| " " \n 0 0 {'column00': 'INTEGER', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'} %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'INTEGER', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d'); +| " " \n 0 0 [{'name': column00, 'type': INTEGER}, {'name': column01, 'type': BIGINT}, {'name': column02, 'type': BIGINT}, {'name': column03, 'type': BIGINT}, {'name': column04, 'type': BIGINT}, {'name': column05, 'type': DOUBLE}, {'name': column06, 'type': DOUBLE}, {'name': column07, 'type': DOUBLE}, {'name': column08, 'type': VARCHAR}, {'name': column09, 'type': VARCHAR}, {'name': column10, 'type': DATE}, {'name': column11, 'type': DATE}, {'name': column12, 'type': DATE}, {'name': column13, 'type': VARCHAR}, {'name': column14, 'type': VARCHAR}, {'name': column15, 'type': VARCHAR}] %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'INTEGER', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d'); query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', dtypes=['INTEGER','BIGINT','BIGINT','BIGINT','BIGINT', 'DOUBLE','DOUBLE','DOUBLE','VARCHAR', 'VARCHAR','DATE', 'DATE', 'DATE', 'VARCHAR', 'VARCHAR', 'VARCHAR']); ---- -| " " \n 0 0 {'column00': 'INTEGER', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'} %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'INTEGER', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d'); +| " " \n 0 0 [{'name': column00, 'type': INTEGER}, {'name': column01, 'type': BIGINT}, {'name': column02, 'type': BIGINT}, {'name': column03, 'type': BIGINT}, {'name': column04, 'type': BIGINT}, {'name': column05, 'type': DOUBLE}, {'name': column06, 'type': DOUBLE}, {'name': column07, 'type': DOUBLE}, {'name': column08, 'type': VARCHAR}, {'name': column09, 'type': VARCHAR}, {'name': column10, 'type': DATE}, {'name': column11, 'type': DATE}, {'name': column12, 'type': DATE}, {'name': column13, 'type': VARCHAR}, {'name': column14, 'type': VARCHAR}, {'name': column15, 'type': VARCHAR}] %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'INTEGER', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d'); query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', column_types=['INTEGER','BIGINT','BIGINT','BIGINT','BIGINT', 'DOUBLE','DOUBLE','DOUBLE','VARCHAR', 'VARCHAR','DATE', 'DATE', 'DATE', 'VARCHAR', 'VARCHAR', 'VARCHAR']); ---- -| " " \n 0 0 {'column00': 'INTEGER', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'} %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'INTEGER', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d'); +| " " \n 0 0 [{'name': column00, 'type': INTEGER}, {'name': column01, 'type': BIGINT}, {'name': column02, 'type': BIGINT}, {'name': column03, 'type': BIGINT}, {'name': column04, 'type': BIGINT}, {'name': column05, 'type': DOUBLE}, {'name': column06, 'type': DOUBLE}, {'name': column07, 'type': DOUBLE}, {'name': column08, 'type': VARCHAR}, {'name': column09, 'type': VARCHAR}, {'name': column10, 'type': DATE}, {'name': column11, 'type': DATE}, {'name': column12, 'type': DATE}, {'name': column13, 'type': VARCHAR}, {'name': column14, 'type': VARCHAR}, {'name': column15, 'type': VARCHAR}] %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'column00': 'INTEGER', 'column01': 'BIGINT', 'column02': 'BIGINT', 'column03': 'BIGINT', 'column04': 'BIGINT', 'column05': 'DOUBLE', 'column06': 'DOUBLE', 'column07': 'DOUBLE', 'column08': 'VARCHAR', 'column09': 'VARCHAR', 'column10': 'DATE', 'column11': 'DATE', 'column12': 'DATE', 'column13': 'VARCHAR', 'column14': 'VARCHAR', 'column15': 'VARCHAR'}, dateformat='%Y-%m-%d'); query IIIIIIIIIII FROM sniff_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', names=['c01','c02','c03','c04','c5', 'c06','c07','c08','c09', 'c10','c11', 'c12', 'c13', 'c14', 'c15', 'c16']); ---- -| " " \n 0 0 {'c01': 'BIGINT', 'c02': 'BIGINT', 'c03': 'BIGINT', 'c04': 'BIGINT', 'c5': 'BIGINT', 'c06': 'DOUBLE', 'c07': 'DOUBLE', 'c08': 'DOUBLE', 'c09': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'} %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'c01': 'BIGINT', 'c02': 'BIGINT', 'c03': 'BIGINT', 'c04': 'BIGINT', 'c5': 'BIGINT', 'c06': 'DOUBLE', 'c07': 'DOUBLE', 'c08': 'DOUBLE', 'c09': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'}, dateformat='%Y-%m-%d'); +| " " \n 0 0 [{'name': c01, 'type': BIGINT}, {'name': c02, 'type': BIGINT}, {'name': c03, 'type': BIGINT}, {'name': c04, 'type': BIGINT}, {'name': c5, 'type': BIGINT}, {'name': c06, 'type': DOUBLE}, {'name': c07, 'type': DOUBLE}, {'name': c08, 'type': DOUBLE}, {'name': c09, 'type': VARCHAR}, {'name': c10, 'type': VARCHAR}, {'name': c11, 'type': DATE}, {'name': c12, 'type': DATE}, {'name': c13, 'type': DATE}, {'name': c14, 'type': VARCHAR}, {'name': c15, 'type': VARCHAR}, {'name': c16, 'type': VARCHAR}] %Y-%m-%d NULL NULL FROM read_csv('test/sql/copy/csv/data/real/lineitem_sample.csv', auto_detect=false, delim='|', quote='"', escape='"', new_line='\n', skip=0, header=false, columns={'c01': 'BIGINT', 'c02': 'BIGINT', 'c03': 'BIGINT', 'c04': 'BIGINT', 'c5': 'BIGINT', 'c06': 'DOUBLE', 'c07': 'DOUBLE', 'c08': 'DOUBLE', 'c09': 'VARCHAR', 'c10': 'VARCHAR', 'c11': 'DATE', 'c12': 'DATE', 'c13': 'DATE', 'c14': 'VARCHAR', 'c15': 'VARCHAR', 'c16': 'VARCHAR'}, dateformat='%Y-%m-%d'); diff --git a/test/sql/copy/file_size_bytes.test b/test/sql/copy/file_size_bytes.test index eed3409583d..ca0c39c22d3 100644 --- a/test/sql/copy/file_size_bytes.test +++ b/test/sql/copy/file_size_bytes.test @@ -128,11 +128,11 @@ SELECT COUNT(*) FROM read_csv_auto('__TEST_DIR__/file_size_bytes_csv5/*.csv') ---- 100000 -# 4 threads, 4 files +# should yield multiple files, can be less than 4 because we create files lazily query I -SELECT count(*) FROM glob('__TEST_DIR__/file_size_bytes_csv5/*.csv') +SELECT count(*) > 2 FROM glob('__TEST_DIR__/file_size_bytes_csv5/*.csv') ---- -4 +true # each thread sees ~240kb if it's balanced, what about a 190kb limit # even in the case of extreme thread imbalance, this always yield around 8 files diff --git a/test/sql/copy/format_uuid.test b/test/sql/copy/format_uuid.test index 8e3b7f53e60..cc1286b8b77 100644 --- a/test/sql/copy/format_uuid.test +++ b/test/sql/copy/format_uuid.test @@ -61,6 +61,7 @@ SELECT * FROM '__TEST_DIR__/part/a=9/leading_????????-????-4???-????-??????????? query III sort SELECT * FROM '__TEST_DIR__/part/a=9/leading_????????-????-4???-????-????????????*.parquet'; ---- +9 18 81 9 27 729 # Test without a specified format name for the outputfile. @@ -77,6 +78,8 @@ SELECT * FROM '__TEST_DIR__/part/a=9/data_[0-9]*.parquet'; query III sort SELECT * FROM '__TEST_DIR__/part/a=9/*.parquet'; ---- +9 18 81 +9 27 729 9 36 6561 # Test where the FILENAME_PATTERN does not contain "{i}" or "{uuid}". @@ -93,6 +96,9 @@ SELECT * FROM '__TEST_DIR__/part/a=9/basename[0-9]*.parquet'; query III sort SELECT * FROM '__TEST_DIR__/part/a=9/*.parquet'; ---- +9 18 81 +9 27 729 +9 36 6561 9 45 59049 # Test without the overwrite_or_ignore param, that tries to add a file to an existing directory @@ -107,7 +113,7 @@ Directory statement error COPY test4 TO '__TEST_DIR__/to_be_overwritten' (FORMAT PARQUET, PARTITION_BY (a), FILENAME_PATTERN); ---- -FILENAME_PATTERN +FILENAME_PATTERN cannot be empty statement ok COPY test4 TO '__TEST_DIR__/to_be_overwritten' (FORMAT PARQUET, PARTITION_BY (a), FILENAME_PATTERN a_file_name); @@ -142,9 +148,9 @@ SELECT COUNT(*) FROM '__TEST_DIR__/pto/basename_????????-????-4???-????-???????? 10000 query I -SELECT COUNT(*) FROM GLOB('__TEST_DIR__/pto/basename_????????-????-4???-????-????????????.parquet'); +SELECT COUNT(*) > 1 FROM GLOB('__TEST_DIR__/pto/basename_????????-????-4???-????-????????????.parquet'); ---- -4 +true diff --git a/test/sql/copy/hive_types.test b/test/sql/copy/hive_types.test_slow similarity index 95% rename from test/sql/copy/hive_types.test rename to test/sql/copy/hive_types.test_slow index 30411309a04..7953298c9a5 100644 --- a/test/sql/copy/hive_types.test +++ b/test/sql/copy/hive_types.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/copy/hive_types.test +# name: test/sql/copy/hive_types.test_slow # description: basic tests hive_types flag + hive_types_autocast flag # group: [copy] @@ -30,7 +30,7 @@ select typeof(season),typeof(director),typeof(aired) from read_parquet('__TEST_D SMALLINT VARCHAR DATE statement error -select typeof(season),typeof(director),typeof(aired) from read_parquet('__TEST_DIR__/partition/**/*.parquet', hive_types={'season':date}) limit 1; +select season,director,aired from read_parquet('__TEST_DIR__/partition/**/*.parquet', hive_types={'season':date}) limit 1; ---- Invalid Input Error: Unable to cast diff --git a/test/sql/copy/parquet/batched_write/parquet_write_mixed_batches.test_slow b/test/sql/copy/parquet/batched_write/parquet_write_mixed_batches.test_slow index cb0466166bf..f6c69e000f2 100644 --- a/test/sql/copy/parquet/batched_write/parquet_write_mixed_batches.test_slow +++ b/test/sql/copy/parquet/batched_write/parquet_write_mixed_batches.test_slow @@ -154,6 +154,17 @@ DROP TABLE mixed_batches_v3 statement ok DROP TABLE mixed_batches_v4 +# Drop the VIEWs that depend on V1 + +statement ok +DROP VIEW IF EXISTS v2 + +statement ok +DROP VIEW IF EXISTS v3 + +statement ok +DROP VIEW IF EXISTS v4 + # create views that read the batches using unions statement ok CREATE OR REPLACE VIEW v1 AS FROM '__TEST_DIR__/mix_batches_small.parquet' UNION ALL FROM '__TEST_DIR__/mix_batches_large.parquet' UNION ALL FROM '__TEST_DIR__/mix_batches_odd.parquet' UNION ALL FROM '__TEST_DIR__/mix_batches_odd_again.parquet' diff --git a/test/sql/copy/parquet/broken/broken_structure.parquet b/test/sql/copy/parquet/broken/broken_structure.parquet new file mode 100644 index 0000000000000000000000000000000000000000..59c61b55ee661131f4b53217ff5b12f4846ed695 GIT binary patch literal 212 zcmWG=3^EjD5fu;>@DXJaWnf_V4*~U}45ECZd^)24fP8+SJOfCQ5zJ!{Ws=k}WsqPg z%FizmWnvIzQDu-|Oadwp`vp|3FKHtwqh=%{$|5N$APJTb1M3q@5=&Au0;)=a@ENG9 NjA1&^g#keS001P7KJ@?q literal 0 HcmV?d00001 diff --git a/test/sql/copy/parquet/broken_parquet.test b/test/sql/copy/parquet/broken_parquet.test index 0cacbd3627b..d3210224c6c 100644 --- a/test/sql/copy/parquet/broken_parquet.test +++ b/test/sql/copy/parquet/broken_parquet.test @@ -34,3 +34,8 @@ select count(*) from parquet_scan('test/sql/copy/parquet/broken/hugefooter.parqu statement error select count(*) from parquet_scan('test/sql/copy/parquet/broken/garbledfooter.parquet') ---- + +statement error +from parquet_scan('test/sql/copy/parquet/broken/broken_structure.parquet') +---- +Parquet file is likely corrupted \ No newline at end of file diff --git a/test/sql/copy/parquet/parquet_encryption.test b/test/sql/copy/parquet/parquet_encryption.test index 67972227bd5..57638c06533 100644 --- a/test/sql/copy/parquet/parquet_encryption.test +++ b/test/sql/copy/parquet/parquet_encryption.test @@ -10,10 +10,16 @@ require noforcestorage statement ok PRAGMA enable_verification -# AES key must have one of the three specified lengths +# AES key must have one of the three specified lengths or be valid Base64 statement error PRAGMA add_parquet_key('my_cool_key', '42') ---- +Invalid Input Error: Invalid AES key. Not a plain AES key NOR a base64 encoded string + +# Valid Base64 AES key must have one of the three specified lengths +statement error +PRAGMA add_parquet_key('my_invalid_duck_key', 'ZHVjaw==') +---- Invalid Input Error: Invalid AES key. Must have a length of 128, 192, or 256 bits (16, 24, or 32 bytes) # we dont support this yet @@ -87,3 +93,12 @@ statement error SELECT * FROM read_parquet('__TEST_DIR__/unencrypted.parquet', encryption_config={footer_key: 'key256'}) ---- Invalid Input Error + +# Use Base64 encoded key +statement ok +PRAGMA add_parquet_key('key256base64', 'MDEyMzQ1Njc4OTExMjM0NTAxMjM0NTY3ODkxMTIzNDU=') + +query I +SELECT * FROM read_parquet('__TEST_DIR__/encrypted256.parquet', encryption_config={footer_key: 'key256base64'}) +---- +42 \ No newline at end of file diff --git a/test/sql/copy/parquet/parquet_stats.test b/test/sql/copy/parquet/parquet_stats.test index deb290f6363..6fdbf7313d2 100644 --- a/test/sql/copy/parquet/parquet_stats.test +++ b/test/sql/copy/parquet/parquet_stats.test @@ -186,3 +186,17 @@ statement ok select * from parquet_metadata('${parquet_file}'); endloop + +# internal issue 2037 +statement ok +copy (select '' i) to '__TEST_DIR__/test.parquet'; + +query I +select i is null c0 from '__TEST_DIR__/test.parquet'; +---- +false + +query II +select stats_min_value is null c0, stats_max_value is null c1 from parquet_metadata('__TEST_DIR__/test.parquet'); +---- +false false diff --git a/test/sql/copy/parquet/parquet_write_codecs.test b/test/sql/copy/parquet/parquet_write_codecs.test index 50be4ffa1f6..6ee94c0e390 100644 --- a/test/sql/copy/parquet/parquet_write_codecs.test +++ b/test/sql/copy/parquet/parquet_write_codecs.test @@ -4,58 +4,26 @@ require parquet -# codec uncompressed -statement ok -COPY (SELECT 42, 'hello') TO '__TEST_DIR__/uncompressed.parquet' (FORMAT 'parquet', CODEC 'UNCOMPRESSED'); - -query II -SELECT * FROM parquet_scan('__TEST_DIR__/uncompressed.parquet'); ----- -42 hello -# codec snappy -statement ok -COPY (SELECT 42, 'hello') TO '__TEST_DIR__/snappy.parquet' (FORMAT 'parquet', CODEC 'SNAPPY'); - -query II -SELECT * FROM parquet_scan('__TEST_DIR__/snappy.parquet'); ----- -42 hello +foreach codec UNCOMPRESSED SNAPPY GZIP ZSTD LZ4 LZ4_RAW BROTLI -# codec gzip +# codec uncompressed statement ok -COPY (SELECT 42, 'hello') TO '__TEST_DIR__/gzip.parquet' (FORMAT 'parquet', CODEC 'GZIP'); +COPY (SELECT 42, 'hello') TO '__TEST_DIR__/${codec}.parquet' (FORMAT 'parquet', CODEC '${codec}'); query II -SELECT * FROM parquet_scan('__TEST_DIR__/gzip.parquet'); +SELECT * FROM parquet_scan('__TEST_DIR__/${codec}.parquet'); ---- 42 hello -# codec zstd statement ok -COPY (SELECT 42, 'hello') TO '__TEST_DIR__/zstd.parquet' (FORMAT 'parquet', CODEC 'ZSTD'); +COPY (FROM "data/parquet-testing/userdata1.parquet") TO '__TEST_DIR__/userdata-${codec}.parquet' (FORMAT 'parquet', CODEC '${codec}', ROW_GROUP_SIZE 10); -query II -SELECT * FROM parquet_scan('__TEST_DIR__/zstd.parquet'); ----- -42 hello - -# codec lz4 statement ok -COPY (SELECT 42, 'hello') TO '__TEST_DIR__/lz4.parquet' (FORMAT 'parquet', CODEC 'LZ4'); - -query II -SELECT * FROM parquet_scan('__TEST_DIR__/lz4.parquet'); ----- -42 hello +FROM "__TEST_DIR__/userdata-${codec}.parquet"; -statement ok -COPY (SELECT 42, 'hello') TO '__TEST_DIR__/lz4_raw.parquet' (FORMAT 'parquet', CODEC 'LZ4_RAW'); +endloop -query II -SELECT * FROM parquet_scan('__TEST_DIR__/lz4_raw.parquet'); ----- -42 hello # unsupported codec statement error diff --git a/test/sql/copy/parquet/recursive_parquet_union_by_name.test b/test/sql/copy/parquet/recursive_parquet_union_by_name.test index 60c927e2887..4a3a6b4a1cb 100644 --- a/test/sql/copy/parquet/recursive_parquet_union_by_name.test +++ b/test/sql/copy/parquet/recursive_parquet_union_by_name.test @@ -1,5 +1,5 @@ # name: test/sql/copy/parquet/recursive_parquet_union_by_name.test -# description: Test read CSV function in a recursive CTE with union by name +# description: Test read parquet function in a recursive CTE with union by name # group: [parquet] require parquet diff --git a/test/sql/copy/parquet/test_parquet_force_download.test b/test/sql/copy/parquet/test_parquet_force_download.test index 90b01c75d3e..d953f039953 100644 --- a/test/sql/copy/parquet/test_parquet_force_download.test +++ b/test/sql/copy/parquet/test_parquet_force_download.test @@ -65,11 +65,13 @@ UNION ALL SELECT * FROM PARQUET_SCAN('https://raw.githubusercontent.com/duckdb/d UNION ALL SELECT * FROM PARQUET_SCAN('https://raw.githubusercontent.com/duckdb/duckdb/main/data/parquet-testing/userdata1.parquet') UNION ALL SELECT * FROM PARQUET_SCAN('https://raw.githubusercontent.com/duckdb/duckdb/main/data/parquet-testing/userdata1.parquet') +# ROW_GROUP_SIZE for these tests used to be 2048, but because the parquet writer checked '>' instead of '>=' +# the row group sizes were actually two chunks, so 4096. This has since been fixed, and this needed to be updated statement ok -COPY (from user_info) TO 's3://test-bucket/row-user-data.parquet' (FORMAT PARQUET, ROW_GROUP_SIZE 2048); +COPY (from user_info) TO 's3://test-bucket/row-user-data.parquet' (FORMAT PARQUET, ROW_GROUP_SIZE 4096); statement ok -COPY (from user_info limit 100) TO 's3://test-bucket/row-user-data_1.parquet' (FORMAT PARQUET, ROW_GROUP_SIZE 2048); +COPY (from user_info limit 100) TO 's3://test-bucket/row-user-data_1.parquet' (FORMAT PARQUET, ROW_GROUP_SIZE 4096); statement ok PRAGMA threads=10 diff --git a/test/sql/copy/parquet/writer/parquet_test_all_types.test b/test/sql/copy/parquet/writer/parquet_test_all_types.test index 10c0410a56d..7ed9d6762ce 100644 --- a/test/sql/copy/parquet/writer/parquet_test_all_types.test +++ b/test/sql/copy/parquet/writer/parquet_test_all_types.test @@ -34,6 +34,25 @@ query I nosort alltypes SELECT * FROM '__TEST_DIR__/all_types.parquet' ---- -false -128 -32768 -2147483648 -9223372036854775808 -1.7014118346046923e+38 0 0 0 0 5877642-06-25 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 1677-09-21 00:12:43.145225 00:00:00+00 290309-12-22 (BC) 00:00:00+00 -3.4028235e+38 -1.7976931348623157e+308 -999.9 -99999.9999 -999999999999.999999 -9999999999999999999999999999.9999999999 00000000-0000-0000-0000-000000000000 00:00:00 🦆🦆🦆🦆🦆🦆 thisisalongblob\x00withnullbytes DUCK_DUCK_ENUM enum_0 enum_0 [] [] [] [] [] [] [] {'a': NULL, 'b': NULL} {'a': NULL, 'b': NULL} [] {} -true 127 32767 2147483647 9223372036854775807 1.7014118346046923e+38 255 65535 4294967295 18446744073709551615 5881580-07-10 24:00:00 294247-01-10 04:00:54.775806 294247-01-10 04:00:54 294247-01-10 04:00:54.775 2262-04-11 23:47:16.854775 23:59:59.999999+00 294247-01-10 04:00:54.775806+00 3.4028235e+38 1.7976931348623157e+308 999.9 99999.9999 999999999999.999999 9999999999999999999999999999.9999999999 ffffffff-ffff-ffff-ffff-ffffffffffff 1 month 1 day 12:13:34.123 goo\0se \x00\x00\x00a GOOSE enum_299 enum_69999 [42, 999, NULL, NULL, -42] [42.0, nan, inf, -inf, NULL, -42.0] [1970-01-01, infinity, -infinity, NULL, 2022-05-12] [1970-01-01 00:00:00, infinity, -infinity, NULL, 2022-05-12 16:23:45] [1970-01-01 00:00:00+00, infinity, -infinity, NULL, 2022-05-12 23:23:45+00] [🦆🦆🦆🦆🦆🦆, goose, NULL, ] [[], [42, 999, NULL, NULL, -42], NULL, [], [42, 999, NULL, NULL, -42]] {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆} {'a': [42, 999, NULL, NULL, -42], 'b': [🦆🦆🦆🦆🦆🦆, goose, NULL, ]} [{'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, NULL] {key1=🦆🦆🦆🦆🦆🦆, key2=goose} -NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL + +foreach type TINYINT SMALLINT INT BIGINT UTINYINT USMALLINT UINT UBIGINT HUGEINT UHUGEINT FLOAT DOUBLE + +query II +explain select "${type}" from '__TEST_DIR__/all_types.parquet' +WHERE "${type}" IN (127); +---- +physical_plan :.*PARQUET_SCAN.*Filters.* + +endloop + +query II +explain select "VARCHAR" from '__TEST_DIR__/all_types.parquet' +WHERE "VARCHAR" IN ('🦆🦆🦆🦆🦆🦆'); +---- +physical_plan :.*PARQUET_SCAN.*Filters.* + +query II +explain select "bool" from '__TEST_DIR__/all_types.parquet' +WHERE "bool" IN (true); +---- +physical_plan :.*PARQUET_SCAN.*Filters.* diff --git a/test/sql/copy/parquet/writer/parquet_write_timestamp.test b/test/sql/copy/parquet/writer/parquet_write_timestamp.test index f2fe0637f72..e953f82fc0d 100644 --- a/test/sql/copy/parquet/writer/parquet_write_timestamp.test +++ b/test/sql/copy/parquet/writer/parquet_write_timestamp.test @@ -7,7 +7,7 @@ require parquet statement ok PRAGMA enable_verification -foreach type TIMESTAMP TIMESTAMP_MS TIMESTAMP_NS TIMESTAMP_S +foreach type TIMESTAMP TIMESTAMP_MS TIMESTAMP_S statement ok CREATE OR REPLACE TABLE timestamps(d ${type}) @@ -41,3 +41,39 @@ SELECT typeof(d) FROM '__TEST_DIR__/timestamps.parquet' LIMIT 1 TIMESTAMP endloop + +# Nanoseconds are their own type +statement ok +CREATE OR REPLACE TABLE timestamps(d TIMESTAMP_NS) + +statement ok +INSERT INTO timestamps VALUES + ('1992-01-01 12:03:27.123456789'), + ('1900-01-01 03:08:47.987654321'), + (NULL), + ('2020-09-27 13:12:01') + +query I nosort ns_scan +SELECT * FROM timestamps +---- +1992-01-01 12:03:27.123456789 +1900-01-01 03:08:47.987654321 +NULL +2020-09-27 13:12:01 + +statement ok +COPY timestamps TO '__TEST_DIR__/timestamps.parquet' (FORMAT 'parquet'); + +query I nosort ns_scan +SELECT * FROM '__TEST_DIR__/timestamps.parquet' +---- + +query I +SELECT * FROM '__TEST_DIR__/timestamps.parquet' WHERE d='1992-01-01 12:03:27.123456789' +---- +1992-01-01 12:03:27.123456789 + +query I +SELECT typeof(d) FROM '__TEST_DIR__/timestamps.parquet' LIMIT 1 +---- +TIMESTAMP_NS diff --git a/test/sql/copy/partitioned/hive_filter_pushdown.test b/test/sql/copy/partitioned/hive_filter_pushdown.test index e03265ff2b6..0523a973969 100644 --- a/test/sql/copy/partitioned/hive_filter_pushdown.test +++ b/test/sql/copy/partitioned/hive_filter_pushdown.test @@ -42,12 +42,12 @@ physical_plan :.*PARQUET_SCAN.*File Filters:.* query II explain SELECT * FROM parquet_scan('__TEST_DIR__/hive_pushdown_bug/*/*.parquet', HIVE_PARTITIONING=1, HIVE_TYPES_AUTOCAST=1) where c=500; ---- -physical_plan :.*PARQUET_SCAN.*File Filters: \(c = 500\).* +physical_plan :.*PARQUET_SCAN.*File Filters: \(c = 500\).*Scanning: 1\/10 files.* query II explain SELECT * FROM parquet_scan('__TEST_DIR__/hive_pushdown_bug/*/*.parquet', HIVE_PARTITIONING=1, HIVE_TYPES_AUTOCAST=1) where c=500 and b='20'; ---- -physical_plan :.*PARQUET_SCAN.*File Filters: \(c = 500\).* +physical_plan :.*PARQUET_SCAN.*File Filters: \(c = 500\).*Scanning: 1\/10 files.* # File Filters show up in read csv auto for hive partitioned csv files. statement ok @@ -56,7 +56,7 @@ COPY (SELECT i::VARCHAR as a, (i*10)::VARCHAR as b, (i*100)::VARCHAR as c from r query II explain SELECT * FROM read_csv_auto('__TEST_DIR__/hive_pushdown_bug_csv/*/*.csv', HIVE_PARTITIONING=1, HIVE_TYPES_AUTOCAST=1, names=['a','b','c']) where c=500; ---- -physical_plan :.*READ_CSV_AUTO.*File Filters: \(c = 500\).* +physical_plan :.*READ_CSV_AUTO.*File Filters: \(c = 500\).*Scanning: 1\/10 files.* # same for json paritioned files #statement ok diff --git a/test/sql/copy/partitioned/hive_partition_append.test b/test/sql/copy/partitioned/hive_partition_append.test new file mode 100644 index 00000000000..a9869b71993 --- /dev/null +++ b/test/sql/copy/partitioned/hive_partition_append.test @@ -0,0 +1,63 @@ +# name: test/sql/copy/partitioned/hive_partition_append.test +# description: test APPEND mode for hive partitioned write +# group: [partitioned] + +require parquet + +statement ok +CREATE TABLE sensor_data(ts TIMESTAMP, value INT); + +statement ok +INSERT INTO sensor_data VALUES + (TIMESTAMP '2000-01-01 01:02:03', 42), + (TIMESTAMP '2000-02-01 01:02:03', 100), + (TIMESTAMP '2000-03-01 12:11:10', 1000) +; + +statement ok +COPY (SELECT YEAR(ts) AS year, MONTH(ts) AS month, * FROM sensor_data) +TO '__TEST_DIR__/partitioned_append' (FORMAT PARQUET, PARTITION_BY (year, month), APPEND); + +query III +SELECT year, month, SUM(value) FROM '__TEST_DIR__/partitioned_append/**/*.parquet' GROUP BY ALL ORDER BY ALL +---- +2000 1 42 +2000 2 100 +2000 3 1000 + +statement ok +DELETE FROM sensor_data; + +statement ok +INSERT INTO sensor_data VALUES + (TIMESTAMP '2000-01-01 02:02:03', 62), + (TIMESTAMP '2000-03-01 13:11:10', 50) +; + +statement ok +COPY (SELECT YEAR(ts) AS year, MONTH(ts) AS month, * FROM sensor_data) +TO '__TEST_DIR__/partitioned_append' (FORMAT PARQUET, PARTITION_BY (year, month), APPEND, FILENAME_PATTERN 'my_pattern_{uuid}'); + +query III +SELECT year, month, SUM(value) FROM '__TEST_DIR__/partitioned_append/**/*.parquet' GROUP BY ALL ORDER BY ALL +---- +2000 1 104 +2000 2 100 +2000 3 1050 + +statement ok +COPY (SELECT YEAR(ts) AS year, MONTH(ts) AS month, * FROM sensor_data) +TO '__TEST_DIR__/partitioned_append' (FORMAT PARQUET, PARTITION_BY (year, month), FILENAME_PATTERN 'my_pattern_{uuid}', APPEND); + +query III +SELECT year, month, SUM(value) FROM '__TEST_DIR__/partitioned_append/**/*.parquet' GROUP BY ALL ORDER BY ALL +---- +2000 1 166 +2000 2 100 +2000 3 1100 + +statement error +COPY (SELECT YEAR(ts) AS year, MONTH(ts) AS month, * FROM sensor_data) +TO '__TEST_DIR__/partitioned_append' (FORMAT PARQUET, PARTITION_BY (year, month), APPEND, FILENAME_PATTERN 'my_pattern_without_uuid'); +---- +APPEND mode requires a {uuid} label in filename_pattern diff --git a/test/sql/copy/partitioned/hive_partitioning_overwrite.test b/test/sql/copy/partitioned/hive_partitioning_overwrite.test index 1b458a47a37..4035c38c34c 100644 --- a/test/sql/copy/partitioned/hive_partitioning_overwrite.test +++ b/test/sql/copy/partitioned/hive_partitioning_overwrite.test @@ -12,11 +12,11 @@ COPY (SELECT 42 AS part_col) TO '__TEST_DIR__/overwrite_test' (FORMAT PARQUET, P statement error COPY (SELECT 84 AS part_col) TO '__TEST_DIR__/overwrite_test' (FORMAT PARQUET, PARTITION_BY (part_col)); ---- -Enable OVERWRITE_OR_IGNORE option to force writing +Enable OVERWRITE option to overwrite files # test the overwrite setting statement ok -COPY (SELECT 84 AS part_col) TO '__TEST_DIR__/overwrite_test' (FORMAT PARQUET, PARTITION_BY (part_col), OVERWRITE_OR_IGNORE 1); +COPY (SELECT 84 AS part_col) TO '__TEST_DIR__/overwrite_test' (FORMAT PARQUET, PARTITION_BY (part_col), OVERWRITE 1); # the old file (with part_col=42) should now be removed query I @@ -34,9 +34,14 @@ COPY (SELECT 84 AS part_col) TO '__TEST_DIR__/overwrite_test2' (FORMAT PARQUET, it exists and is a file statement ok -COPY (SELECT 84 AS part_col) TO '__TEST_DIR__/overwrite_test2' (FORMAT PARQUET, PARTITION_BY (part_col), OVERWRITE_OR_IGNORE 1); +COPY (SELECT 84 AS part_col) TO '__TEST_DIR__/overwrite_test2' (FORMAT PARQUET, PARTITION_BY (part_col), OVERWRITE 1); query I SELECT * FROM '__TEST_DIR__/overwrite_test2/**/*.parquet' ---- 84 + +statement error +COPY (SELECT 84 AS part_col) TO '__TEST_DIR__/overwrite_test' (FORMAT PARQUET, PARTITION_BY (part_col), OVERWRITE 1, OVERWRITE_OR_IGNORE 1); +---- +OVERWRITE diff --git a/test/sql/copy/per_thread_output.test b/test/sql/copy/per_thread_output.test index 49ad11d6e92..0efcf832842 100644 --- a/test/sql/copy/per_thread_output.test +++ b/test/sql/copy/per_thread_output.test @@ -14,37 +14,35 @@ statement ok CREATE TABLE bigdata AS SELECT i AS col_a, i AS col_b FROM range(0,10000) tbl(i); statement ok -COPY (FROM bigdata) TO '__TEST_DIR__/per_thread_output' (FORMAT PARQUET, PER_THREAD_OUTPUT TRUE); +COPY (FROM bigdata UNION ALL FROM bigdata) TO '__TEST_DIR__/per_thread_output' (FORMAT PARQUET, PER_THREAD_OUTPUT TRUE); query I SELECT COUNT(*) FROM PARQUET_SCAN('__TEST_DIR__/per_thread_output/*.parquet') ---- -10000 +20000 +# we now lazily create the files to prevent empty files from being created +# despite setting 4 threads, this may result in less than 4 files +# instead of checking we have file 0, 1, 2, and 3 like we did previously, +# we just check if we created more than one file that matches the glob pattern query I -SELECT STR_SPLIT(REPLACE(file, '\','/'), '/')[-1] f FROM GLOB('__TEST_DIR__/per_thread_output/*.parquet') ORDER BY f +SELECT COUNT(*) > 1 f FROM GLOB('__TEST_DIR__/per_thread_output/data_*.parquet') ORDER BY f ---- -data_0.parquet -data_1.parquet -data_2.parquet -data_3.parquet +true # CSV also works statement ok -COPY (FROM bigdata) TO '__TEST_DIR__/per_thread_output_csv' (FORMAT CSV, PER_THREAD_OUTPUT TRUE); +COPY (FROM bigdata UNION ALL FROM bigdata) TO '__TEST_DIR__/per_thread_output_csv' (FORMAT CSV, PER_THREAD_OUTPUT TRUE); query I SELECT COUNT(*) FROM read_csv('__TEST_DIR__/per_thread_output_csv/*.csv', columns={'col_a': 'INT', 'col_b' : 'INT'}); ---- -10000 +20000 query I -SELECT STR_SPLIT(REPLACE(file, '\','/'), '/')[-1] f FROM GLOB('__TEST_DIR__/per_thread_output_csv/*.csv') ORDER BY f +SELECT COUNT(*) > 2 f FROM GLOB('__TEST_DIR__/per_thread_output_csv/data_*.csv') ORDER BY f ---- -data_0.csv -data_1.csv -data_2.csv -data_3.csv +true # with a trailing slash statement ok @@ -56,10 +54,10 @@ SELECT COUNT(*) FROM PARQUET_SCAN('__TEST_DIR__/per_thread_output2/*.parquet') 10000 -# cant write to existing folders statement error COPY (FROM bigdata) TO '__TEST_DIR__/per_thread_output2/' (FORMAT PARQUET, PER_THREAD_OUTPUT TRUE); ---- +IO Error # we have not added anything query I @@ -68,7 +66,7 @@ SELECT COUNT(*) FROM PARQUET_SCAN('__TEST_DIR__/per_thread_output2/*.parquet') 10000 -# this should not work statement error COPY (FROM bigdata) TO '__TEST_DIR__/per_thread_output3' (FORMAT PARQUET, PER_THREAD_OUTPUT TRUE, USE_TMP_FILE TRUE); ---- +Not implemented Error \ No newline at end of file diff --git a/test/sql/copy/return_files.test b/test/sql/copy/return_files.test new file mode 100644 index 00000000000..8c815bc4e9d --- /dev/null +++ b/test/sql/copy/return_files.test @@ -0,0 +1,45 @@ +# name: test/sql/copy/return_files.test +# description: test RETURN_FILES parameter for COPY +# group: [copy] + +require parquet + +statement ok +CREATE TABLE integers AS SELECT range i FROM range(200000); + +statement ok +SET preserve_insertion_order=false; + +query II +COPY integers TO '__TEST_DIR__/test_copy_to_file.parquet' (RETURN_FILES); +---- +200000 :.*test_copy_to_file.parquet.* + +statement ok +SET preserve_insertion_order=true; + +query II +COPY integers TO '__TEST_DIR__/test_batch_copy_to_file.parquet' (RETURN_FILES TRUE); +---- +200000 :.*test_batch_copy_to_file.parquet.* + +statement ok +SET threads=2; + +query II +COPY integers TO '__TEST_DIR__/test_per_thread_output' (RETURN_FILES, PER_THREAD_OUTPUT); +---- +200000 :.*data_0.csv.*data_1.csv.* + +require notwindows + +statement ok +SET threads=1; + +statement ok +CREATE TABLE integers2 AS SELECT range i, range % 4 j FROM range(200000); + +query II +COPY integers2 TO '__TEST_DIR__/test_partition_by' (RETURN_FILES TRUE, PARTITION_BY j); +---- +200000 :.*test_partition_by/j=0/data_0.csv.*test_partition_by/j=1/data_0.csv.*test_partition_by/j=2/data_0.csv.*test_partition_by/j=3/data_0.csv.* diff --git a/test/sql/copy/row_groups_per_file.test b/test/sql/copy/row_groups_per_file.test new file mode 100644 index 00000000000..498660559d1 --- /dev/null +++ b/test/sql/copy/row_groups_per_file.test @@ -0,0 +1,153 @@ +# name: test/sql/copy/row_groups_per_file.test +# description: test ROW_GROUPS_PER_FILE parameter for parquet COPY +# group: [copy] + +require parquet + +require vector_size 2048 + +statement ok +CREATE TABLE bigdata AS SELECT i AS col_a, i AS col_b FROM range(0,10000) tbl(i); + +statement ok +set threads=1 + +# creates a new file after every chunk, 5 chunks in total, so 5 parquet files +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file1' (FORMAT PARQUET, ROW_GROUP_SIZE 2000, ROW_GROUPS_PER_FILE 1) + +query I +SELECT count(*) FROM '__TEST_DIR__/row_groups_per_file1/*.parquet' +---- +10000 + +query I +SELECT count(*) FROM glob('__TEST_DIR__/row_groups_per_file1/*.parquet') +---- +5 + +# new file after every other chunk, 3 in total +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file2' (FORMAT PARQUET, ROW_GROUP_SIZE 4000, ROW_GROUPS_PER_FILE 1) + +query I +SELECT count(*) FROM '__TEST_DIR__/row_groups_per_file2/*.parquet' +---- +10000 + +query I +SELECT count(*) FROM glob('__TEST_DIR__/row_groups_per_file2/*.parquet') +---- +3 + +# new row group after every chunk, new file after every 2 row groups, again 3 in total +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file3' (FORMAT PARQUET, ROW_GROUP_SIZE 2000, ROW_GROUPS_PER_FILE 2) + +query I +SELECT count(*) FROM '__TEST_DIR__/row_groups_per_file3/*.parquet' +---- +10000 + +query I +SELECT count(*) FROM glob('__TEST_DIR__/row_groups_per_file3/*.parquet') +---- +3 + +# now we crank up the threads +statement ok +PRAGMA verify_parallelism + +statement ok +set threads=4 + +# with multiple threads writing to the same file this is best-effort +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file4' (FORMAT PARQUET, ROW_GROUP_SIZE 2000, ROW_GROUPS_PER_FILE 1) + +query I +SELECT count(*) FROM '__TEST_DIR__/row_groups_per_file4/*.parquet' +---- +10000 + +query I +SELECT count(*) BETWEEN 2 and 5 FROM glob('__TEST_DIR__/row_groups_per_file4/*.parquet') +---- +true + +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file5' (FORMAT PARQUET, ROW_GROUP_SIZE 4000, ROW_GROUPS_PER_FILE 1) + +query I +SELECT count(*) FROM '__TEST_DIR__/row_groups_per_file5/*.parquet' +---- +10000 + +query I +SELECT count(*) BETWEEN 1 and 3 FROM glob('__TEST_DIR__/row_groups_per_file5/*.parquet') +---- +true + +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file6' (FORMAT PARQUET, ROW_GROUP_SIZE 2000, ROW_GROUPS_PER_FILE 2) + +query I +SELECT count(*) FROM '__TEST_DIR__/row_groups_per_file6/*.parquet' +---- +10000 + +query I +SELECT count(*) BETWEEN 1 and 3 FROM glob('__TEST_DIR__/row_groups_per_file6/*.parquet') +---- +true + +# should work nicely with PER_THREAD_OUTPUT +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file7' (FORMAT PARQUET, PER_THREAD_OUTPUT TRUE, ROW_GROUP_SIZE 2000, ROW_GROUPS_PER_FILE 1) + +query I +SELECT count(*) FROM '__TEST_DIR__/row_groups_per_file7/*.parquet' +---- +10000 + +query I +SELECT count(*) FROM glob('__TEST_DIR__/row_groups_per_file7/*.parquet') +---- +5 + +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file8' (FORMAT PARQUET, PER_THREAD_OUTPUT TRUE, ROW_GROUP_SIZE 4000, ROW_GROUPS_PER_FILE 1) + +query I +SELECT count(*) FROM '__TEST_DIR__/row_groups_per_file8/*.parquet' +---- +10000 + +query I +SELECT count(*) BETWEEN 3 AND 5 FROM glob('__TEST_DIR__/row_groups_per_file8/*.parquet') +---- +true + +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file9' (FORMAT PARQUET, PER_THREAD_OUTPUT TRUE, ROW_GROUP_SIZE 2000, ROW_GROUPS_PER_FILE 2) + +query I +SELECT count(*) FROM '__TEST_DIR__/row_groups_per_file9/*.parquet' +---- +10000 + +query I +SELECT count(*) BETWEEN 3 AND 5 FROM glob('__TEST_DIR__/row_groups_per_file9/*.parquet') +---- +true + +# doesn't work in combination with certain params +statement error +COPY bigdata TO '__TEST_DIR__/row_groups_per_file_error' (FORMAT PARQUET, ROW_GROUPS_PER_FILE 1, USE_TMP_FILE TRUE); +---- +Not implemented Error + +statement error +COPY bigdata TO '__TEST_DIR__/row_groups_per_file_error' (FORMAT PARQUET, ROW_GROUPS_PER_FILE 1, PARTITION_BY col_a); +---- +Not implemented Error diff --git a/test/sql/copy/row_groups_per_file_large.test_slow b/test/sql/copy/row_groups_per_file_large.test_slow new file mode 100644 index 00000000000..e3be83ec543 --- /dev/null +++ b/test/sql/copy/row_groups_per_file_large.test_slow @@ -0,0 +1,48 @@ +# name: test/sql/copy/row_groups_per_file_large.test_slow +# description: test ROW_GROUPS_PER_FILE parameter for parquet COPY (slow test) +# group: [copy] + +require parquet + +statement ok +SET threads=4 + +statement ok +CREATE TABLE bigdata AS SELECT i AS col_a, i AS col_b FROM range(0, 10000000) tbl(i) + +# parallel, so best effort, not an exact number of files: around 82 row groups, 4 per file, ~20 files +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file42' (FORMAT PARQUET, ROW_GROUP_SIZE 122880, ROW_GROUPS_PER_FILE 4) + +query I +SELECT count(*) FROM read_parquet('__TEST_DIR__/row_groups_per_file42/*.parquet') +---- +10000000 + +query II +SELECT avg(col_a), avg(col_b) FROM read_parquet('__TEST_DIR__/row_groups_per_file42/*.parquet') +---- +4999999.5 4999999.5 + +query I +SELECT count(*) BETWEEN 15 AND 25 FROM glob('__TEST_DIR__/row_groups_per_file42/*.parquet') +---- +true + +statement ok +COPY bigdata TO '__TEST_DIR__/row_groups_per_file43' (FORMAT PARQUET, ROW_GROUP_SIZE 122880, ROW_GROUPS_PER_FILE 4, PER_THREAD_OUTPUT TRUE) + +query I +SELECT count(*) FROM read_parquet('__TEST_DIR__/row_groups_per_file43/*.parquet') +---- +10000000 + +query II +SELECT avg(col_a), avg(col_b) FROM read_parquet('__TEST_DIR__/row_groups_per_file43/*.parquet') +---- +4999999.5 4999999.5 + +query I +SELECT count(*) BETWEEN 15 AND 25 FROM glob('__TEST_DIR__/row_groups_per_file43/*.parquet') +---- +true diff --git a/test/sql/copy/s3/s3_hive_partition.test b/test/sql/copy/s3/s3_hive_partition.test index 47b3c028b16..efa534738ac 100644 --- a/test/sql/copy/s3/s3_hive_partition.test +++ b/test/sql/copy/s3/s3_hive_partition.test @@ -98,3 +98,7 @@ EXPLAIN select a from read_csv_auto('s3://test-bucket/hive-partitioning/filter-t ---- physical_plan :.*FILTER.*(a < 4).*READ_CSV_AUTO.*File Filters: \(CAST\(c AS.*INTEGER\) = 500\).* +statement error +COPY (SELECT * FROM t1) TO 's3://test-bucket/hive-partitioning/filter-test-parquet' (FORMAT PARQUET, PARTITION_BY c, OVERWRITE); +---- +OVERWRITE is not supported for remote file systems diff --git a/test/sql/copy_database/copy_database_different_types.test b/test/sql/copy_database/copy_database_different_types.test index d39ac221e17..ff2a03edd99 100644 --- a/test/sql/copy_database/copy_database_different_types.test +++ b/test/sql/copy_database/copy_database_different_types.test @@ -36,6 +36,9 @@ CREATE TABLE enums(i mood) statement ok INSERT INTO enums VALUES ('ok'), ('sad'), (NULL) +statement ok +select * from db1.enums + statement ok CREATE SEQUENCE seq; diff --git a/test/sql/copy_database/copy_database_index.test b/test/sql/copy_database/copy_database_index.test new file mode 100644 index 00000000000..69c39c220bc --- /dev/null +++ b/test/sql/copy_database/copy_database_index.test @@ -0,0 +1,27 @@ +# name: test/sql/copy_database/copy_database_index.test +# description: Test COPY DATABASE with indexes +# group: [copy_database] + +require noforcestorage + +statement ok +PRAGMA enable_verification + +statement ok +ATTACH DATABASE ':memory:' AS db1; + +statement ok +USE db1 + +statement ok +CREATE TABLE test(a INTEGER, b INTEGER, c VARCHAR(10)); + +statement ok +CREATE INDEX i_index ON test(a) + +statement ok +INSERT INTO test VALUES (42, 88, 'hello'); + +statement error +COPY FROM DATABASE db1 TO memory +---- diff --git a/test/sql/create/create_as_issue_11968.test b/test/sql/create/create_as_issue_11968.test new file mode 100644 index 00000000000..04ec83c2d7a --- /dev/null +++ b/test/sql/create/create_as_issue_11968.test @@ -0,0 +1,16 @@ +# name: test/sql/create/create_as_issue_11968.test +# group: [create] + +load __TEST_DIR__/temp_create_as.db + +statement ok +CREATE TABLE test (x INTEGER[]); + +statement ok +INSERT INTO test SELECT CASE WHEN x <= 520 THEN [0, 0] ELSE [0] END FROM generate_series(1, 2048) s(x); + +statement ok +CHECKPOINT; + +statement ok +CREATE TABLE test2 AS SELECT x FROM test; diff --git a/test/sql/cte/materialized/dml_materialized_cte.test b/test/sql/cte/materialized/dml_materialized_cte.test index 478f989281c..306678f6a15 100644 --- a/test/sql/cte/materialized/dml_materialized_cte.test +++ b/test/sql/cte/materialized/dml_materialized_cte.test @@ -13,37 +13,99 @@ create table a(i integer); statement ok insert into a values (42); -statement ok +query I WITH t(x) AS MATERIALIZED (VALUES (42)) INSERT INTO a (SELECT * FROM t); +---- +1 -statement ok +query I WITH t(x) AS MATERIALIZED (VALUES (42)) DELETE FROM a WHERE a.i IN (SELECT * FROM t); +---- +2 statement ok +insert into a values (42); + +query I WITH t(x) AS MATERIALIZED (VALUES (42)) UPDATE a SET i = 0 WHERE a.i IN (SELECT * FROM t); +---- +1 + +query I +FROM a +---- +0 statement ok +insert into a values (2); + +query I WITH t(x) AS MATERIALIZED (SELECT 1), u(x) AS MATERIALIZED (SELECT 2 UNION ALL SELECT * FROM t) DELETE FROM a WHERE a.i IN (SELECT * FROM u); +---- +1 statement ok +insert into a values (2); + +query I WITH t(x) AS MATERIALIZED (SELECT 1), u(x) AS MATERIALIZED (SELECT 2 UNION ALL SELECT * FROM t) -UPDATE a SET i = 0 WHERE a.i IN (SELECT * FROM u); +UPDATE a SET i = 99 WHERE a.i IN (SELECT * FROM u); +---- +1 -statement ok +query I +FROM a ORDER BY 1 +---- +0 +99 + +query I WITH t(x) AS MATERIALIZED (SELECT 1), u(x) AS MATERIALIZED (SELECT 2 UNION ALL SELECT * FROM t) INSERT INTO a (SELECT * FROM u); +---- +2 + +query I +FROM a ORDER BY 1 +---- +0 +1 +2 +99 statement ok +insert into a values (42); + +query I WITH t(x) AS MATERIALIZED (SELECT 1) DELETE FROM a WHERE i IN (WITH s(x) AS MATERIALIZED (SELECT x + 41 FROM t) SELECT * FROM t); +---- +1 -statement ok +query I +FROM a ORDER BY 1 +---- +0 +2 +42 +99 + +query I WITH t(x) AS MATERIALIZED (SELECT 1) DELETE FROM a WHERE i IN (WITH s(x) AS MATERIALIZED (SELECT x + 41 FROM t) SELECT * FROM s); +---- +1 + +query I +FROM a ORDER BY 1 +---- +0 +2 +99 diff --git a/test/sql/cte/materialized/materialized_cte_prepared.test b/test/sql/cte/materialized/materialized_cte_prepared.test new file mode 100644 index 00000000000..8853f5bc9ba --- /dev/null +++ b/test/sql/cte/materialized/materialized_cte_prepared.test @@ -0,0 +1,51 @@ +# name: test/sql/cte/materialized/materialized_cte_prepared.test +# description: Test DML statements with materialized Common Table Expressions (CTE) +# group: [materialized] + +statement ok +PRAGMA enable_verification + +require noalternativeverify + +statement ok +create table a(i integer); + +statement ok +insert into a values (1), (2), (3), (NULL), (42), (84); + +# prepare in materialized cte +statement ok +PREPARE v1 AS WITH t(x) AS MATERIALIZED (VALUES ($1)) +DELETE FROM a WHERE i IN (FROM t); + +query I +EXECUTE v1(42) +---- +1 + +query I +FROM a ORDER BY 1 +---- +1 +2 +3 +84 +NULL + +# prepare in both materialized cte and delete +statement ok +PREPARE v2 AS WITH t(x) AS MATERIALIZED (VALUES ($1)) +DELETE FROM a WHERE (i + $2) IN (FROM t); + +query I +EXECUTE v2(5, 2) +---- +1 + +query I +FROM a ORDER BY 1 +---- +1 +2 +84 +NULL diff --git a/test/sql/cte/materialized/test_correlated_recursive_cte_materialized.test b/test/sql/cte/materialized/test_correlated_recursive_cte_materialized.test index ddd2d9c9bf3..4763e8e9996 100644 --- a/test/sql/cte/materialized/test_correlated_recursive_cte_materialized.test +++ b/test/sql/cte/materialized/test_correlated_recursive_cte_materialized.test @@ -103,7 +103,7 @@ SELECT x, y, (WITH RECURSIVE t(z) AS MATERIALIZED ( FROM t WHERE z < 3 ) SELECT sum(z) FROM t) AS z -FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y); +FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all; ---- 1 1 5 1 2 3 @@ -127,7 +127,7 @@ SELECT x, y, (WITH RECURSIVE t(z) AS MATERIALIZED ( SELECT * FROM g) AS t(z) WHERE z < 5 ) SELECT sum(z) FROM t) AS z -FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y); +FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all; ---- 1 1 23 1 2 12 @@ -234,7 +234,7 @@ SELECT x, y, (WITH RECURSIVE t(z) AS MATERIALIZED ( FROM t WHERE z < 3 ) SELECT sum(z) FROM t) AS z -FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y); +FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all; ---- 1 1 5 1 2 3 @@ -257,7 +257,7 @@ SELECT x, y, (WITH RECURSIVE t(z) AS MATERIALIZED ( SELECT * FROM g) AS t(z) WHERE z < 5 ) SELECT sum(z) FROM t) AS z -FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y); +FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all; ---- 1 1 14 1 2 12 diff --git a/test/sql/cte/materialized/test_cte_in_cte_materialized.test b/test/sql/cte/materialized/test_cte_in_cte_materialized.test index a6587af9b63..0c7aa484ed3 100644 --- a/test/sql/cte/materialized/test_cte_in_cte_materialized.test +++ b/test/sql/cte/materialized/test_cte_in_cte_materialized.test @@ -48,6 +48,11 @@ with cte1 as MATERIALIZED (Select i as j from a) select * from cte1 where j = (w ---- 42 +query I +with cte as materialized (Select i as j from a) select * from cte where j = (with cte as (select max(j) as j from cte) select j from cte); +---- +42 + require noalternativeverify # refer to same-named CTE in a subquery expression diff --git a/test/sql/cte/test_correlated_recursive_cte.test b/test/sql/cte/test_correlated_recursive_cte.test index 69e81629e98..144a46a522c 100644 --- a/test/sql/cte/test_correlated_recursive_cte.test +++ b/test/sql/cte/test_correlated_recursive_cte.test @@ -103,7 +103,7 @@ SELECT x, y, (WITH RECURSIVE t(z) AS ( FROM t WHERE z < 3 ) SELECT sum(z) FROM t) AS z -FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y); +FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all; ---- 1 1 5 1 2 3 @@ -127,7 +127,7 @@ SELECT x, y, (WITH RECURSIVE t(z) AS ( SELECT * FROM g) AS t(z) WHERE z < 5 ) SELECT sum(z) FROM t) AS z -FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y); +FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all; ---- 1 1 23 1 2 12 @@ -304,7 +304,7 @@ SELECT x, y, (WITH RECURSIVE t(z) AS ( FROM t WHERE z < 3 ) SELECT sum(z) FROM t) AS z -FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y); +FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all; ---- 1 1 5 1 2 3 @@ -327,7 +327,7 @@ SELECT x, y, (WITH RECURSIVE t(z) AS ( SELECT * FROM g) AS t(z) WHERE z < 5 ) SELECT sum(z) FROM t) AS z -FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y); +FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all; ---- 1 1 14 1 2 12 diff --git a/test/sql/delete/large_deletes_transactions.test b/test/sql/delete/large_deletes_transactions.test new file mode 100644 index 00000000000..b2d83562c44 --- /dev/null +++ b/test/sql/delete/large_deletes_transactions.test @@ -0,0 +1,40 @@ +# name: test/sql/delete/large_deletes_transactions.test +# description: Test large deletions with transactions +# group: [delete] + +statement ok +PRAGMA enable_verification + +statement ok con1 +CREATE TABLE a AS SELECT * FROM range(1000000) t1(i); + +statement ok con2 +BEGIN TRANSACTION + +query I con2 +SELECT COUNT(*) FROM a +---- +1000000 + +query I con1 +DELETE FROM a WHERE i%2=0 +---- +500000 + +query I con1 +SELECT COUNT(*) FROM a +---- +500000 + +query I con2 +SELECT COUNT(*) FROM a +---- +1000000 + +statement ok con2 +COMMIT + +query I con2 +SELECT COUNT(*) FROM a +---- +500000 diff --git a/test/sql/excel/test_excel_numformat.test b/test/sql/excel/test_excel_numformat.test deleted file mode 100644 index 5d900e32a41..00000000000 --- a/test/sql/excel/test_excel_numformat.test +++ /dev/null @@ -1,568 +0,0 @@ -# name: test/sql/excel/test_excel_numformat.test -# description: Test number format -# group: [excel] - -require excel - -statement ok -PRAGMA enable_verification - -# Hours, minutes, seconds -query T -SELECT text(1234567.897, 'h') ----- -21 - -query T -SELECT text(1234567.897, 'hh') ----- -21 - -query T -SELECT text(1234567.897, 's') ----- -41 - -query T -SELECT text(1234567.897, 'ss') ----- -41 - -query T -SELECT text(12345.678, '[h]') ----- -296296 - -query T -SELECT text(12345.678, '[m]') ----- -17777776 - -query T -SELECT text(12345.678, '[s]') ----- -1066666579 - -query T -SELECT text(12345.678, '[hh]') ----- -296296 - -query T -SELECT text(12345.678, '[mm]') ----- -17777776 - -query T -SELECT text(12345.678, '[ss]') ----- -1066666579 - -# composed time formats -query T -SELECT text(1234567.897, 'h AM/PM') ----- -9 PM - -query T -SELECT text(1234567.897, 'h:mm AM/PM') ----- -9:31 PM - -query T -SELECT text(1234567.897, 'h:mm:ss A/P') ----- -9:31:41 p - -query T -SELECT text(1234567.897, 'h:mm:ss.00') ----- -21:31:40.80 - -query T -SELECT text(12345.678, '[h]:mm') ----- -296296:16 - -query T -SELECT text(1234567.897, 'h m') ----- -21 31 - -query T -SELECT text(1234567.897, 'm') ----- -2 - -query T -SELECT text(1234567.897, 'mm') ----- -02 - -query T -SELECT text(1234567.897, 'h m') ----- -21 31 - -query T -SELECT text(1234567.897, 'm s') ----- -31 41 - -query T -SELECT text(12345.678, '[mm]:ss') ----- -17777776:19 - -query T -SELECT text(12345.678, '[m]:ss') ----- -17777776:19 - -query T -SELECT text(12345.678, '[s].00') ----- -1066666579.20 - -query T -SELECT text(12345.678, '[ss].00') ----- -1066666579.20 - -# Date & Time -query T -SELECT text(1234567.897, 'dd') ----- -15 - -query T -SELECT text(1234567.897, 'd') ----- -15 - -query T -SELECT text(1234567.897, 'dd.mm') ----- -15.02 - -query T -SELECT text(1234567.897, 'dd/mm') ----- -15/02 - -query T -SELECT text(1234567.897, 'mm/dd/yyyy') ----- -02/15/5280 - -query T -SELECT text(1234567.897, 'm/d/yyyy h:mm AM/PM') ----- -2/15/5280 9:31 PM - -query T -SELECT text(1234567.897, 'dddd, dd of MMMM of YYYY') ----- -Thursday, 15 of February of 5280 - -query T -SELECT text(1234567.897, 'aaa') ----- -Thu - -query T -SELECT text(1234567.897, 'AaaA') ----- -Thursday - -query T -SELECT text(1234567.897, 'dddD') ----- -Thursday - -query T -SELECT text(1234567.897, 'dDd, dd of MMMM') ----- -Thu, 15 of February - -query T -SELECT text(1234567.897, 'mmmm') ----- -February - -query T -SELECT text(1234567.897, 'mmM') ----- -Feb - -# Percentage -query T -SELECT text(1234567.897, '.00_0%') ----- -123456789.70 % - -query T -SELECT text(1234567.897, '0.0%') ----- -123456789.7% - -query T -SELECT text(1234567.897, '0.00%') ----- -123456789.70% - -query T -SELECT text(1234567.897, '0.00%') ----- -123456789.70% - -# Fraction -query T -SELECT text(1234567.897, '# ?/?') ----- -1234567 8/9 - -query T -SELECT text(1234567.897, '# ??/??') ----- -1234567 61/68 - -query T -SELECT text(1234567.897, '# ???/???') ----- -1234567 688/767 - -query T -SELECT text(1234567.897, '# ?/2') ----- -1234568 - -query T -SELECT text(1234567.897, '# ?/4') ----- -1234568 - -query T -SELECT text(1234567.897, '# ??/16') ----- -1234567 14/16 - -query T -SELECT text(1234567.897, '# ??/10') ----- -1234567 9/10 - -query T -SELECT text(1234567.897, '# ??/100') ----- -1234567 90/100 - -query T -SELECT text(1234567.897, '### #/0') ----- -1234567 8/9 - -query T -SELECT text(1234567.897, '#,### ??/123') ----- -1,234,567 110/123 - -query T -SELECT text(1234567.897, '0/0') ----- -11111111/9 - -query T -SELECT text(1234567.897, '00/0') ----- -11111111/9 - -query T -SELECT text(258.9876, '0/57') ----- -14762/57 - -# Scientific notation -query T -SELECT text(1234567.897, '0.00E+00') ----- -1.23E+06 - -query T -SELECT text(1234567.897, '0.00E+0') ----- -1.23E+6 - -query T -SELECT text(1234567.897, '0.0E+0') ----- -1.2E+6 - -query T -SELECT text(1234567.897, '#.##E+000') ----- -1.23E+006 - -query T -SELECT text(1234567.897, '#.##E-000') ----- -1.23E006 - -query T -SELECT text(1234567.897, '#.#_#E+00x0') ----- -1.2 E+00x6 - -query T -SELECT text(1234567.897, '0.E+00') ----- -1.E+06 - -query T -SELECT text(1234567.897, '#.00E+0') ----- -1.23E+6 - -# Special -query T -SELECT text(1234567.897, '00000') ----- -1234568 - -query T -SELECT text(1234567.897, '000-00-0000') ----- -001-23-4568 - -query T -SELECT text(12345678912, '(###) ###-####') ----- -(1234) 567-8912 - -query T -SELECT text(1234567.897, '##-#00') ----- -1234-568 - -query T -SELECT text(123456789712, '(000)000-00-0000') ----- -(123)456-78-9712 - -# separators -query T -SELECT text(1234567.897, '#,###') ----- -1,234,568 - -query T -SELECT text(1234567.897, '0,000.00') ----- -1,234,567.90 - -query T -SELECT text(1234567.897, '#,') ----- -1235 - -query T -SELECT text(1234567.897, '#,000.0') ----- -1,234,567.9 - -query T -SELECT text(1234567.897, '0.0,,') ----- -1.2 - -query T -SELECT text(1234567.897, '#,') ----- -1235 - -query T -SELECT text(1234567.897, '$#,###.00') ----- -$1,234,567.90 - -query T -SELECT text(1234567.897, '0,0,0,0') ----- -1,234,568 - -# Number, currency, accounting -query T -SELECT text(1234567.897, '$#,##0') ----- -$1,234,568 - -query T -SELECT text(1234567.897, '$,##0.00_') ----- -$,1234567.90 - -query T -SELECT text(1234567.897, '$#,##0.00') ----- -$1,234,567.90 - -query T -SELECT text(1234567.897, '$*#,##0') ----- -$,1234568 - -query T -SELECT text(1234567.897, '$*#,##0.00') ----- -$,1234567.90 - -query T -SELECT text(1234567.897, '$ 0.##') ----- -$ 1234567.9 - -# Others -query T -SELECT text(1234567.897, '####') ----- -1234568 - -query T -SELECT text(1234567.897, '##.###') ----- -1234567.897 - -query T -SELECT text(1234567.897, '0.00') ----- -1234567.90 - -query T -SELECT text(1234567.897, '#.') ----- -1234568. - -query T -SELECT text(1234567.897, '#') ----- -1234568 - -query T -SELECT text(1234567.897, '#;#') ----- -1234568 - -query T -SELECT text(1234567.897, '#.') ----- -1234568. - -query T -SELECT text(1234567.897, '.##000#') ----- -1234567.89700 - -query T -SELECT text(1234567.897, '#.#') ----- -1234567.9 - -query T -SELECT text(1234567.897, '##.00##') ----- -1234567.897 - -query T -SELECT text(1234567.897, '#_x#') ----- -123456 8 - -query T -SELECT text(1234567.897, '[>1]##') ----- -1234568 - -query T -SELECT text(1234567.897, '[<=0]##;[>0]##.0') ----- -1234567.9 - -query T -SELECT text(1234567.897, '[<>3.90e2]##') ----- -1234568 - -query T -SELECT text(1234567.897, '0') ----- -1234568 - -query T -SELECT excel_text(123456789123, '[<=9999999]##-####;[>9999999](###) ###-####') ----- -(12345) 678-9123 - -query T -SELECT excel_text(1234567, '[<=9999999]##-####;[>9999999](###) ###-####') ----- -123-4567 - -query T -SELECT excel_text(1234567.897, '$$$$$$$0') ----- -$$$$$$$1234568 - -query T -SELECT text(1234567.897, '_ $* #,##0_ ;_ $* -#,##0_ ;_ $* - _ ;_ @_ ') ----- - $1,234,568 - -query T -SELECT excel_text(-1234567.897, '_ $* #,##0_ ;_ $* -#,##0_ ;_ $* - _ ;_ @_ ') ----- - $-1,234,568 - -query T -SELECT text(0.0, '_ $* #,##0_ ;_ $* -#,##0_ ;_ $* - _ ;_ @_ ') ----- - $ - - -query T -SELECT text(1234567.897, '_ $* #,##0.00_ ;_ $* -#,##0.00_ ;_ $* - ??_ ;_ @_ ') ----- - $1,234,567.90 - -query T -SELECT excel_text(-1234567.897, '_ $* #,##0.00_ ;_ $* -#,##0.00_ ;_ $* - ??_ ;_ @_ ') ----- - $-1,234,567.90 - -query T -SELECT excel_text(0.0, '_ $* #,##0.00_ ;_ $* -#,##0.00_ ;_ $* - ??_ ;_ @_ ') ----- - $ - - -query T -SELECT text(1.0, '3.5') ----- -3.5 - -statement error -SELECT text('hello', 1.0) ----- - -statement error -SELECT text('hello', '@') ----- - -# Days -query T -SELECT excel_text(i, 'dddd') FROM range(7) as t(i); ----- -Saturday -Sunday -Monday -Tuesday -Wednesday -Thursday -Friday diff --git a/test/sql/explain/test_explain_analyze.test b/test/sql/explain/test_explain_analyze.test index ab6b36200cd..76cff92a3a1 100644 --- a/test/sql/explain/test_explain_analyze.test +++ b/test/sql/explain/test_explain_analyze.test @@ -63,9 +63,9 @@ PRAGMA enable_profiling='json' query II EXPLAIN ANALYZE SELECT SUM(i) FROM integers ---- -analyzed_plan :.*integers.*"timings":.* +analyzed_plan :.*"extra_info".*integers.*:.* -statement ok +statement ok PRAGMA disable_profiling statement ok diff --git a/test/sql/extensions/checked_load.test b/test/sql/extensions/checked_load.test index dcead8139aa..186cf7aa356 100644 --- a/test/sql/extensions/checked_load.test +++ b/test/sql/extensions/checked_load.test @@ -5,7 +5,7 @@ statement error LOAD 'README.md'; ---- -Invalid Input Error: Extension "README.md" do not have metadata compatible with DuckDB loading it +The file is not a DuckDB extension. The metadata at the end of the file is invalid statement ok SET allow_extensions_metadata_mismatch=true; @@ -19,7 +19,7 @@ Error: Extension "README.md" could not be loaded statement error LOAD 'data/csv/no_opt.csv'; ---- -File size in particular is lower than minimum threshold of 1024 +is not a DuckDB extension. Valid DuckDB extensions must be at least 512 bytes statement ok SET allow_unsigned_extensions=false; @@ -27,4 +27,4 @@ SET allow_unsigned_extensions=false; statement error LOAD 'README.md'; ---- -IO Error: Extension "README.md" could not be loaded because its signature is either missing or invalid and unsigned extensions are disabled by configuration +The file is not a DuckDB extension. The metadata at the end of the file is invalid diff --git a/test/sql/extensions/description_is_valid.test b/test/sql/extensions/description_is_valid.test new file mode 100644 index 00000000000..203141bee59 --- /dev/null +++ b/test/sql/extensions/description_is_valid.test @@ -0,0 +1,19 @@ +# name: test/sql/extensions/description_is_valid.test +# description: Test version metadata on load +# group: [extensions] + +require inet + +statement ok +SET autoinstall_known_extensions=true; + +statement ok +SET autoload_known_extensions=true; + +statement ok +LOAD inet; + +query I +SELECT description FROM duckdb_extensions() WHERE extension_name == 'inet'; +---- +Adds support for IP-related data types and functions diff --git a/test/sql/filter/test_struct_pushdown.test b/test/sql/filter/test_struct_pushdown.test index 2a944f48693..f738a3a87d2 100644 --- a/test/sql/filter/test_struct_pushdown.test +++ b/test/sql/filter/test_struct_pushdown.test @@ -78,7 +78,7 @@ INSERT INTO string_structs VALUES ({'a': 'foo', 'b': 'bar'}), ({'a': 'baz', 'b': query II EXPLAIN SELECT * FROM string_structs WHERE s.a = 'foo'; ---- -physical_plan :.*Filters: s\.a=foo AND s\.a IS.*NOT NULL.* +physical_plan :.*Filters: s\.a='foo' AND s\.a.*IS NOT NULL.* query I SELECT * FROM string_structs WHERE s.a = 'foo'; @@ -148,7 +148,7 @@ SELECT * FROM nested_structs WHERE s.a.c = true AND s.d.e = 5; query II EXPLAIN SELECT * FROM nested_structs WHERE s.d.f = 'bar'; ---- -physical_plan :.*Filters: s\.d\.f=bar AND s\.d.*\.f IS NOT NULL.* +physical_plan :.*Filters: s\.d\.f='bar' AND s.*\.d\.f IS NOT NULL.* query I SELECT * FROM nested_structs WHERE s.d.f = 'bar'; @@ -192,7 +192,7 @@ COPY (FROM string_structs) TO '__TEST_DIR__/string_structs.parquet' (FORMAT PARQ query II EXPLAIN SELECT * FROM read_parquet('__TEST_DIR__/string_structs.parquet') WHERE s.a = 'foo'; ---- -physical_plan :.*Filters: s\.a=foo AND s\.a IS.*NOT NULL.* +physical_plan :.*Filters: s\.a='foo' AND s\.a.*IS NOT NULL.* query I SELECT * FROM read_parquet('__TEST_DIR__/string_structs.parquet') WHERE s.a = 'foo'; diff --git a/test/sql/fts/issue_12330.test b/test/sql/fts/issue_12330.test new file mode 100644 index 00000000000..60433e1bc94 --- /dev/null +++ b/test/sql/fts/issue_12330.test @@ -0,0 +1,34 @@ +# name: test/sql/fts/issue_12330.test +# description: Issue 12330: BM25 matching scores seems to be invalid +# group: [fts] + +# issue #7384 and #8141 + +require fts + +statement ok +CREATE OR REPLACE TABLE documents ( + id VARCHAR, + content VARCHAR +); + +statement ok +INSERT INTO documents VALUES + ('doc1', 'DuckDB database lorem'), + ('doc2', 'DuckDB database ipsum'), + ('doc3', 'DuckDB database ipsum dolor'); + +statement ok +PRAGMA create_fts_index('documents', 'id', 'content'); + +query I +SELECT + id +FROM + documents +ORDER BY + fts_main_documents.match_bm25(id, 'DuckDB database ipsum') DESC; +---- +doc2 +doc3 +doc1 diff --git a/test/sql/fts/test_indexing.test_slow b/test/sql/fts/test_indexing.test_slow index bc99f0e0298..7ff6928d1a9 100644 --- a/test/sql/fts/test_indexing.test_slow +++ b/test/sql/fts/test_indexing.test_slow @@ -135,8 +135,8 @@ doc1 0.36835264087244074 query III SELECT score, id, body FROM (SELECT *, fts_main_documents.match_bm25(id, 'quacked barked') AS score FROM documents) sq WHERE score IS NOT NULL ORDER BY score DESC ---- -0.37543634550460314 doc2 BÁRKING+BÁRKING+BÁRKING+BÁRKING -0.3683526408724408 doc1 QUÁCKING+QUÁCKING+QUÁCKING +0.7208701623069375 doc2 BÁRKING+BÁRKING+BÁRKING+BÁRKING +0.7072688384898254 doc1 QUÁCKING+QUÁCKING+QUÁCKING # drop and re-create, but index both the 'body' and 'author' column this time statement ok diff --git a/test/sql/fts/test_issue_10254.test b/test/sql/fts/test_issue_10254.test index 0d5cd0cef1b..fd149745a10 100644 --- a/test/sql/fts/test_issue_10254.test +++ b/test/sql/fts/test_issue_10254.test @@ -21,5 +21,5 @@ PRAGMA create_fts_index('data', 'id', 'context', 'question', stemmer='russian', query I SELECT id FROM (SELECT *, fts_main_data.match_bm25(id, 'Какие') AS score FROM data) sq WHERE score IS NOT NULL ORDER BY score DESC; ---- -1 0 +1 diff --git a/test/sql/function/array/array_and_map.test b/test/sql/function/array/array_and_map.test new file mode 100644 index 00000000000..09726717b36 --- /dev/null +++ b/test/sql/function/array/array_and_map.test @@ -0,0 +1,23 @@ +# name: test/sql/function/array/array_and_map.test +# description: Test flattening ARRAY types inside the MAP function. +# group: [array] + +statement ok +PRAGMA enable_verification + +query I +SELECT MAP([MAP([ARRAY_VALUE('1', NULL), ARRAY_VALUE(NULL, '2')], [1, 2])], [1]); +---- +{{[1, NULL]=1, [NULL, 2]=2}=1} + +query I +SELECT MAP([2], [{'key1': MAP([ARRAY_VALUE('1', NULL), ARRAY_VALUE(NULL, '2')], [1, 2])}]); +---- +{2={'key1': {[1, NULL]=1, [NULL, 2]=2}}} + +# Issue https://github.com/duckdb/duckdb/issues/12007. + +query I +SELECT [MAP([2], [{'key1': MAP([ARRAY_VALUE('1', NULL), ARRAY_VALUE(NULL, '2')], [1, 2]), 'key2': 2}])]; +---- +[{2={'key1': {[1, NULL]=1, [NULL, 2]=2}, 'key2': 2}}] \ No newline at end of file diff --git a/test/sql/function/date/test_date_part.test b/test/sql/function/date/test_date_part.test index b676a815a65..d02538c86a4 100644 --- a/test/sql/function/date/test_date_part.test +++ b/test/sql/function/date/test_date_part.test @@ -459,6 +459,18 @@ NULL NULL 2022-01-01 1640995200000 infinity NULL +query II +SELECT d, nanosecond(d) FROM dates ORDER BY ALL; +---- +NULL NULL +-infinity NULL +0044-03-15 (BC) 0 +1992-01-01 0 +1992-03-03 0 +1992-05-05 0 +2022-01-01 0 +infinity NULL + # # Structs # diff --git a/test/sql/function/date/test_extract.test b/test/sql/function/date/test_extract.test index 1c459fe0838..7daef627ea6 100644 --- a/test/sql/function/date/test_extract.test +++ b/test/sql/function/date/test_extract.test @@ -26,6 +26,13 @@ SELECT EXTRACT(month FROM i) FROM dates 8 NULL +# quarter +query I +SELECT EXTRACT(quarter FROM i) FROM dates +---- +3 +NULL + # day query I SELECT EXTRACT(day FROM i) FROM dates diff --git a/test/sql/function/generic/can_cast_implicitly.test b/test/sql/function/generic/can_cast_implicitly.test new file mode 100644 index 00000000000..8ecfcc7aa0e --- /dev/null +++ b/test/sql/function/generic/can_cast_implicitly.test @@ -0,0 +1,31 @@ +# name: test/sql/function/generic/can_cast_implicitly.test +# description: Test the can cast implicitly function +# group: [generic] + +statement ok +PRAGMA enable_verification + +statement ok +CREATE TABLE tbl AS SELECT * FROM range(10) tbl(i) + +# can cast bigint -> bigint implicitly +query I +SELECT can_cast_implicitly(i, NULL::BIGINT) FROM tbl LIMIT 1 +---- +true + +query I +SELECT can_cast_implicitly(i, NULL::HUGEINT) FROM tbl LIMIT 1 +---- +true + +# cannot cast bigint -> int implicitly +query I +SELECT can_cast_implicitly(i, NULL::INTEGER) FROM tbl LIMIT 1 +---- +false + +query I +SELECT can_cast_implicitly(i, NULL::VARCHAR) FROM tbl LIMIT 1 +---- +false diff --git a/test/sql/function/generic/test_set.test b/test/sql/function/generic/test_set.test index 05ce9c6691c..117f0a31c39 100644 --- a/test/sql/function/generic/test_set.test +++ b/test/sql/function/generic/test_set.test @@ -50,6 +50,10 @@ statement error SELECT CURRENT_SETTING(NULL) ---- +statement error +SELECT CURRENT_SETTING(CAST(NULL AS TEXT)) +---- + statement error SELECT CURRENT_SETTING('') ---- diff --git a/test/sql/function/interval/test_date_part.test b/test/sql/function/interval/test_date_part.test index a04eebc8465..3d49242183a 100644 --- a/test/sql/function/interval/test_date_part.test +++ b/test/sql/function/interval/test_date_part.test @@ -205,6 +205,16 @@ ORDER BY 1; 1 year 4 months 41472000000 2 years 62208000000 +query II +SELECT i, nanosecond(i) AS parts +FROM intervals +ORDER BY 1; +---- +00:34:26.3434 26343400000 +42 days 0 +1 year 4 months 0 +2 years 0 + # Invalid parts foreach datepart dow isodow doy week isoyear yearweek era timezone timezone_hour timezone_minute diff --git a/test/sql/function/list/aggregates/approx_count_distinct.test b/test/sql/function/list/aggregates/approx_count_distinct.test index d1258b0c755..110006f9a71 100644 --- a/test/sql/function/list/aggregates/approx_count_distinct.test +++ b/test/sql/function/list/aggregates/approx_count_distinct.test @@ -56,7 +56,7 @@ INSERT INTO timestamp VALUES (['2008-01-01 00:00:01', NULL, '2007-01-01 00:00:01 query II SELECT list_count(t), list_approx_count_distinct(t) from timestamp ---- -7 7 +7 6 # strings statement ok @@ -80,7 +80,7 @@ INSERT INTO list_ints_2 SELECT LIST(a), LIST(mod(a, 10)) FROM range(2000) tbl(a) query III SELECT list_count(a), list_approx_count_distinct(a), list_approx_count_distinct(b) from list_ints_2 ---- -2000 1991 10 +2000 2322 11 statement ok DELETE FROM list_ints_2 @@ -94,5 +94,5 @@ INSERT INTO list_ints_2 SELECT LIST(a), NULL FROM range(2000) tbl(a, b) WHERE a query I SELECT list_approx_count_distinct(a) from list_ints_2; ---- -993 -986 +1006 +1230 diff --git a/test/sql/function/list/aggregates/median.test b/test/sql/function/list/aggregates/median.test index 79872fe6c3a..90598374758 100644 --- a/test/sql/function/list/aggregates/median.test +++ b/test/sql/function/list/aggregates/median.test @@ -12,7 +12,7 @@ CREATE TABLE quantile AS SELECT LIST(r::${type}) AS r FROM range(10000) t1(r); query I SELECT list_median(r) FROM quantile ---- -4999 +4999.5 statement ok DROP TABLE quantile diff --git a/test/sql/function/list/aggregates/minmax_all_types.test_slow b/test/sql/function/list/aggregates/minmax_all_types.test_slow new file mode 100644 index 00000000000..3aa22ff50e5 --- /dev/null +++ b/test/sql/function/list/aggregates/minmax_all_types.test_slow @@ -0,0 +1,24 @@ +# name: test/sql/function/list/aggregates/minmax_all_types.test_slow +# description: Test the min/max functions on all types +# group: [aggregates] + +statement ok +pragma enable_verification + +# verify that min/max produces the same results as ORDER BY .. LIMIT 1 for all types +statement ok +CREATE TABLE all_types AS FROM test_all_types(); + +foreach col bool tinyint smallint int bigint hugeint uhugeint utinyint usmallint uint ubigint date time timestamp timestamp_s timestamp_ms timestamp_ns time_tz timestamp_tz float double dec_4_1 dec_9_4 dec_18_6 dec38_10 uuid interval varchar blob bit small_enum medium_enum large_enum int_array double_array date_array timestamp_array timestamptz_array varchar_array nested_int_array struct struct_of_arrays array_of_structs map union fixed_int_array fixed_varchar_array fixed_nested_int_array fixed_nested_varchar_array fixed_struct_array struct_of_fixed_array fixed_array_of_int_list list_of_fixed_int_array + +query I +SELECT MIN({'val': "${col}"}).val IS NOT DISTINCT FROM (SELECT "${col}" FROM all_types ORDER BY "${col}" LIMIT 1) FROM all_types WHERE bool IS NOT NULL +---- +true + +query I +SELECT MAX({'val': "${col}"}).val IS NOT DISTINCT FROM (SELECT "${col}" FROM all_types ORDER BY "${col}" DESC LIMIT 1) FROM all_types WHERE bool IS NOT NULL +---- +true + +endloop diff --git a/test/sql/function/list/aggregates/minmax_nested.test b/test/sql/function/list/aggregates/minmax_nested.test new file mode 100644 index 00000000000..a2e690c2b4d --- /dev/null +++ b/test/sql/function/list/aggregates/minmax_nested.test @@ -0,0 +1,227 @@ +# name: test/sql/function/list/aggregates/minmax_nested.test +# description: Test the min/max functions on complex nested types aggregate function +# group: [aggregates] + +statement ok +pragma enable_verification + +# structs +statement ok +CREATE TABLE structs AS SELECT {'i': i} s FROM range(1000) t(i); + +query II +SELECT MIN(s), MAX(s) FROM structs; +---- +{'i': 0} {'i': 999} + +# larger values +statement ok +INSERT INTO structs VALUES ({'i': 99999999}); + +query II +SELECT MIN(s), MAX(s) FROM structs; +---- +{'i': 0} {'i': 99999999} + +# limits +statement ok +INSERT INTO structs VALUES ({'i': -9223372036854775808}), ({'i': 9223372036854775807}); + +query II +SELECT MIN(s), MAX(s) FROM structs; +---- +{'i': -9223372036854775808} {'i': 9223372036854775807} + +# null values +statement ok +INSERT INTO structs VALUES ({'i': NULL}), (NULL) + +query II +SELECT MIN(s), MAX(s) FROM structs; +---- +{'i': -9223372036854775808} {'i': NULL} + +# structs with varchars +statement ok +CREATE TABLE varchar_structs AS SELECT {'i': concat('long_prefix_', i)} s FROM range(1000) t(i); + +query II +SELECT MIN(s), MAX(s) FROM varchar_structs; +---- +{'i': long_prefix_0} {'i': long_prefix_999} + +# null bytes +statement ok +INSERT INTO varchar_structs VALUES ({'i': chr(0)}), ({'i': 'zzzzz' || chr(0)}) + +query II +SELECT MIN(s), MAX(s) FROM varchar_structs; +---- +{'i': \0} {'i': zzzzz\0} + +# structs with blobs +statement ok +CREATE TABLE blob_structs AS SELECT {'i': concat('long_prefix_', '\x', 16+i%239)::blob} s FROM range(1000) t(i); + +query II +SELECT MIN(s), MAX(s) FROM blob_structs; +---- +{'i': long_prefix_\x100} {'i': long_prefix_\x99} + +# null bytes +statement ok +INSERT INTO blob_structs VALUES ({'i': '\x00z\x00\x00z\x00zzzz\x00'::blob}), ({'i': 'zzzzzz\x01\x01\x01\x00\x01\x01\x00'::blob}) + +query II +SELECT MIN(s), MAX(s) FROM blob_structs; +---- +{'i': \x00z\x00\x00z\x00zzzz\x00} {'i': zzzzzz\x01\x01\x01\x00\x01\x01\x00} + +# multi-member structs +statement ok +CREATE TABLE multi_member_struct AS SELECT {'i': (1000-i)//5, 'j': i} s FROM range(1000) t(i); + +query II +SELECT MIN(s), MAX(s) FROM multi_member_struct; +---- +{'i': 0, 'j': 996} {'i': 200, 'j': 0} + +# lists +statement ok +CREATE TABLE lists AS SELECT case when i<500 then [i, i + 1, i + 2] else [i, 0] end AS l FROM range(1000) t(i); + +query II +SELECT MIN(l), MAX(l) FROM lists; +---- +[0, 1, 2] [999, 0] + +# empty list and null entries +statement ok +INSERT INTO lists VALUES ([]), (NULL), ([NULL, NULL, NULL]); + +query II +SELECT MIN(l), MAX(l) FROM lists; +---- +[] [NULL, NULL, NULL] + +# lists with structs +statement ok +CREATE TABLE list_with_structs AS SELECT case when i<500 then [{'i': i}, {'i': i + 1}, {'i': i + 2}] else [{'i': i}, {'i': 0}] end AS l FROM range(1000) t(i); + +query II +SELECT MIN(l), MAX(l) FROM list_with_structs; +---- +[{'i': 0}, {'i': 1}, {'i': 2}] [{'i': 999}, {'i': 0}] + +# null within a struct +statement ok +INSERT INTO list_with_structs VALUES ([{'i': NULL}, {'i': 100}, NULL, {'i': NULL}]); + +query II +SELECT MIN(l), MAX(l) FROM list_with_structs; +---- +[{'i': 0}, {'i': 1}, {'i': 2}] [{'i': NULL}, {'i': 100}, NULL, {'i': NULL}] + +# empty list and null entries +statement ok +INSERT INTO list_with_structs VALUES ([]), (NULL), ([NULL, NULL, NULL]); + +query II +SELECT MIN(l), MAX(l) FROM list_with_structs; +---- +[] [NULL, NULL, NULL] + +# list with multi member struct +statement ok +CREATE TABLE list_multi_member_struct AS SELECT [NULL, {'i': (1000-i)//5, 'j': i}, NULL] l FROM range(1000) t(i); + +query II +SELECT MIN(l), MAX(l) FROM list_multi_member_struct; +---- +[NULL, {'i': 0, 'j': 996}, NULL] [NULL, {'i': 200, 'j': 0}, NULL] + +# nulls at different levels +statement ok +INSERT INTO list_multi_member_struct VALUES ([{'i': NULL, 'j': 42}]), ([NULL, NULL, {'i': 84, 'j': NULL}]) + +query II +SELECT MIN(l), MAX(l) FROM list_multi_member_struct; +---- +[{'i': NULL, 'j': 42}] [NULL, NULL, {'i': 84, 'j': NULL}] + +# struct with lists +statement ok +CREATE TABLE struct_with_lists AS SELECT {'i': case when i<500 then [i, i + 1, i + 2] else [i, 0] end} AS s FROM range(1000) t(i); + +query II +SELECT MIN(s), MAX(s) FROM struct_with_lists; +---- +{'i': [0, 1, 2]} {'i': [999, 0]} + +# empty list and null entries +statement ok +INSERT INTO struct_with_lists VALUES ({'i': []}), (NULL), ({'i': [NULL, NULL, NULL]}) + +query II +SELECT MIN(s), MAX(s) FROM struct_with_lists; +---- +{'i': []} {'i': [NULL, NULL, NULL]} + +statement ok +INSERT INTO struct_with_lists VALUES ({'i': NULL}) + +query I +SELECT MAX(s) FROM struct_with_lists; +---- +{'i': NULL} + +# arrays +statement ok +CREATE TABLE arrays AS SELECT (case when i<500 then [i, i + 1, i + 2] else [i, 0, 0] end)::BIGINT[3] AS l FROM range(1000) t(i); + +query II +SELECT MIN(l), MAX(l) FROM arrays; +---- +[0, 1, 2] [999, 0, 0] + +# null entries +statement ok +INSERT INTO arrays VALUES (NULL), ([NULL, NULL, NULL]); + +query II +SELECT MIN(l), MAX(l) FROM arrays; +---- +[0, 1, 2] [NULL, NULL, NULL] + +# floats +statement ok +CREATE TABLE float_values(f FLOAT); + +statement ok +INSERT INTO float_values VALUES ('0'), ('-3.4e38'), ('3.4e38'), ('nan'), ('inf'), ('-inf') + +query II +SELECT f, (SELECT MIN({'v': x}) FROM (VALUES (f)) t(x)) FROM float_values; +---- +0.0 {'v': 0.0} +-3.4e+38 {'v': -3.4e+38} +3.4e+38 {'v': 3.4e+38} +nan {'v': nan} +inf {'v': inf} +-inf {'v': -inf} + +statement ok +CREATE TABLE double_values(d DOUBLE); + +statement ok +INSERT INTO double_values VALUES ('0'), ('-1e308'), ('1e308'), ('nan'), ('inf'), ('-inf') + +query II +SELECT d, (SELECT MIN({'v': x}) FROM (VALUES (d)) t(x)) FROM double_values; +---- +0.0 {'v': 0.0} +-1e+308 {'v': -1e+308} +1e+308 {'v': 1e+308} +nan {'v': nan} +inf {'v': inf} +-inf {'v': -inf} diff --git a/test/sql/function/list/aggregates/mode.test b/test/sql/function/list/aggregates/mode.test index 080925aea9a..704f9e1e5fd 100644 --- a/test/sql/function/list/aggregates/mode.test +++ b/test/sql/function/list/aggregates/mode.test @@ -2,8 +2,6 @@ # description: Test the list_mode aggregate function # group: [aggregates] -require strinline - # incorrect usage statement error select list_mode() diff --git a/test/sql/function/list/aggregates/types.test b/test/sql/function/list/aggregates/types.test index fe504b31245..fba39d9e694 100644 --- a/test/sql/function/list/aggregates/types.test +++ b/test/sql/function/list/aggregates/types.test @@ -5,7 +5,8 @@ # This file specifically tests the functionality for each type, # it does not necessarily test the correctness (statement ok suffices for some tests) -require strinline +statement ok +PRAGMA enable_verification # BOOLEAN @@ -391,7 +392,7 @@ SELECT list_aggr([{'a': 1}], '${func_name}') endloop # list, struct, any other result -foreach func_name approx_count_distinct count entropy array_agg list string_agg group_concat +foreach func_name approx_count_distinct count entropy array_agg list string_agg group_concat histogram statement ok SELECT list_aggr([[1]], '${func_name}') @@ -404,7 +405,7 @@ endloop # statement error for NESTED types # list, struct -foreach func_name avg favg bit_and bit_or bit_xor bool_and bool_or histogram kurtosis mad product sem skewness sum fsum sumKahan kahan_sum var_samp var_pop stddev stddev_pop variance stddev_samp +foreach func_name avg favg bit_and bit_or bit_xor bool_and bool_or kurtosis mad product sem skewness sum fsum sumKahan kahan_sum var_samp var_pop stddev stddev_pop variance stddev_samp statement error SELECT list_aggr([[1]], '${func_name}') diff --git a/test/sql/function/list/lambdas/lambda_scope.test b/test/sql/function/list/lambdas/lambda_scope.test index d9a1888845c..a0f91af5792 100644 --- a/test/sql/function/list/lambdas/lambda_scope.test +++ b/test/sql/function/list/lambdas/lambda_scope.test @@ -1,8 +1,8 @@ # name: test/sql/function/list/lambdas/lambda_scope.test -# description: Test the scoping of lambda variables +# description: Test the scoping of lambda variables. # group: [lambdas] -# lambda parameters have precedence over columns +# Lambda parameters have precedence over columns. statement ok CREATE TABLE t1 AS SELECT [1, 2, 3] AS x; diff --git a/test/sql/function/list/lambdas/lambdas_and_group_by.test b/test/sql/function/list/lambdas/lambdas_and_group_by.test index 04b35d7f0f3..3da3a9fee31 100644 --- a/test/sql/function/list/lambdas/lambdas_and_group_by.test +++ b/test/sql/function/list/lambdas/lambdas_and_group_by.test @@ -33,3 +33,16 @@ query I FROM uniform_purchase_forecast SELECT list(forecast).list_transform(x -> x + 10); ---- [20, 25, 310] + +# HAVING binder issues. + +query I +FROM (SELECT 1) GROUP BY ALL HAVING list_filter(NULL, x -> x); +---- + +statement ok +FROM test_all_types() GROUP BY ALL HAVING array_intersect(NULL, NULL); + +query I +SELECT x FROM (VALUES (42)) t(x) GROUP BY x HAVING list_filter(NULL, lambda_param -> lambda_param = 1); +---- \ No newline at end of file diff --git a/test/sql/function/list/lambdas/reduce.test b/test/sql/function/list/lambdas/reduce.test_slow similarity index 99% rename from test/sql/function/list/lambdas/reduce.test rename to test/sql/function/list/lambdas/reduce.test_slow index a702b0fa73a..24140ef953d 100644 --- a/test/sql/function/list/lambdas/reduce.test +++ b/test/sql/function/list/lambdas/reduce.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/function/list/lambdas/reduce.test +# name: test/sql/function/list/lambdas/reduce.test_slow # description: Test list_reduce function # group: [lambdas] diff --git a/test/sql/function/list/lambdas/table_functions.test b/test/sql/function/list/lambdas/table_functions.test index f8141a4e0f8..25b6eed868b 100644 --- a/test/sql/function/list/lambdas/table_functions.test +++ b/test/sql/function/list/lambdas/table_functions.test @@ -72,3 +72,19 @@ list_string_agg([lower(s) for s in ['a=1', 'b=2', 'c=3']]) || '.parquet'); ---- 10 +# lambdas in ALTER TABLE statements + +statement ok +CREATE TABLE cities AS +SELECT * FROM (VALUES ('Amsterdam', [90, 10]), ('London', [89, 102])) cities (name, prices); + +statement ok +ALTER TABLE cities +ALTER COLUMN prices SET DATA TYPE INTEGER[] USING + list_filter(cities.prices, price -> price < 100); + +query II +SELECT name, prices AS cheap_options FROM cities; +---- +Amsterdam [90, 10] +London [89] \ No newline at end of file diff --git a/test/sql/function/list/list_distinct.test b/test/sql/function/list/list_distinct.test index 3ab48396228..0c8d01a4e1f 100644 --- a/test/sql/function/list/list_distinct.test +++ b/test/sql/function/list/list_distinct.test @@ -45,15 +45,11 @@ No function matches # test incorrect parameter type -foreach type boolean varchar tinyint smallint integer bigint hugeint uhugeint utinyint usmallint uinteger ubigint float double decimal(4,1) decimal(9,4) decimal(18,6) decimal(38,10) date time timestamp timestamp_s timestamp_ms timestamp_ns timetz timestamptz interval blob - statement error -SELECT list_distinct(NULL::${type}) +SELECT list_distinct(NULL::boolean) ---- No function matches -endloop - # other tests query I @@ -269,31 +265,6 @@ SELECT list_sort(list_distinct(['a', 'b、c', 'a'])) statement ok CREATE TABLE all_types AS SELECT * FROM test_all_types(); -# unsupported histogram types -foreach colname bool tinyint smallint int bigint utinyint usmallint uint ubigint date time timestamp timestamp_s timestamp_ms timestamp_ns time_tz timestamp_tz float double dec_4_1 dec_9_4 uuid interval varchar small_enum medium_enum large_enum - -statement ok -select list_distinct(["${colname}"]) FROM all_types; - -endloop - -# we support histogram for the min/max values of these types -foreach colname hugeint dec_18_6 dec38_10 - +# list distinct is supported for all types statement ok -select list_distinct(["${colname}"]) FROM all_types; - -endloop - -statement ok -select list_distinct(["blob"]) FROM all_types; - -# we don't support histogram for nested types -foreach colname int_array double_array date_array timestamp_array timestamptz_array varchar_array nested_int_array struct struct_of_arrays array_of_structs map - -statement error -select list_distinct(["${colname}"]) FROM all_types; ----- -Not implemented Error - -endloop +SELECT list_distinct([COLUMNS(*)]) FROM all_types; diff --git a/test/sql/function/list/list_grade_up.test b/test/sql/function/list/list_grade_up.test_slow similarity index 98% rename from test/sql/function/list/list_grade_up.test rename to test/sql/function/list/list_grade_up.test_slow index 7e5f0063799..7e05d37789a 100644 --- a/test/sql/function/list/list_grade_up.test +++ b/test/sql/function/list/list_grade_up.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/function/list/list_grade_up.test +# name: test/sql/function/list/list_grade_up.test_slow # description: Test list_grade_up function # group: [list] diff --git a/test/sql/function/list/list_intersect.test b/test/sql/function/list/list_intersect.test index 94f3e39605a..ae5a0b9872c 100644 --- a/test/sql/function/list/list_intersect.test +++ b/test/sql/function/list/list_intersect.test @@ -48,10 +48,11 @@ insert into list_of_list values (NULL, NULL); statement ok insert into list_of_list values ([[1 , 2, 3], NULL, [3, 2, 1]], [[ 2, 3, 4], NULL, [1, 2, 3]]); -statement error +query I select ${f}(l1, l2) from list_of_list; ---- -Not implemented +NULL +[[1, 2, 3]] statement ok drop table list_of_list; diff --git a/test/sql/function/list/list_resize.test b/test/sql/function/list/list_resize.test index ba85805314e..d12ad71ddf8 100644 --- a/test/sql/function/list/list_resize.test +++ b/test/sql/function/list/list_resize.test @@ -297,6 +297,17 @@ execute ${q}([1, 2, 3], 1.4); statement ok execute ${q}([2], 2::TINYINT); + +statement error +execute ${q}([1, 2, 3], -1); +---- +Conversion Error: Type INT32 with value -1 can't be cast because the value is out of range for the destination type UINT64 + +statement error +SELECT LIST_RESIZE([1, 2, 3], 9999999999999999999); +---- +maximum allowed vector size + endloop query I diff --git a/test/sql/function/list/list_select.test b/test/sql/function/list/list_select.test_slow similarity index 97% rename from test/sql/function/list/list_select.test rename to test/sql/function/list/list_select.test_slow index f43ebda4201..c0e2f6dd159 100644 --- a/test/sql/function/list/list_select.test +++ b/test/sql/function/list/list_select.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/function/list/list_select.test +# name: test/sql/function/list/list_select.test_slow # description: Test list_select function # group: [list] @@ -324,4 +324,9 @@ SELECT list_select(c34, 'enum_0') FROM all_types AS t43(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37, c38, c39, c40, c41, c42), all_types AS t86(c44, c45, c46, c47, c48, c49, c50, c51, c52, c53, c54, c55, c56, c57, c58, c59, c60, c61, c62, c63, c64, c65, c66, c67, c68, c69, c70, c71, c72, c73, c74, c75, c76, c77, c78, c79, c80, c81, c82, c83, c84, c85); ---- -Conversion Error \ No newline at end of file +Conversion Error + +query I +SELECT LIST_SELECT(ARRAY_VALUE('1', NULL), [1, 2, 3]); +---- +[1, NULL, NULL] \ No newline at end of file diff --git a/test/sql/function/list/list_unique.test b/test/sql/function/list/list_unique.test index 7652779cd68..e726e080228 100644 --- a/test/sql/function/list/list_unique.test +++ b/test/sql/function/list/list_unique.test @@ -38,15 +38,10 @@ SELECT list_unique([1, 2], 2) ---- # test incorrect parameter type - -foreach type boolean varchar tinyint smallint integer bigint hugeint utinyint usmallint uinteger ubigint uhugeint float double decimal(4,1) decimal(9,4) decimal(18,6) decimal(38,10) date time timestamp timestamp_s timestamp_ms timestamp_ns timetz timestamptz interval blob - statement error -SELECT list_unique(NULL::${type}) +SELECT list_unique(NULL::tinyint) ---- -endloop - # other tests query I diff --git a/test/sql/function/list/list_where.test b/test/sql/function/list/list_where.test index 67d7d5db07c..80272c9d654 100644 --- a/test/sql/function/list/list_where.test +++ b/test/sql/function/list/list_where.test @@ -226,4 +226,15 @@ SELECT list_where([{'a': 1}, {'a': 5}, {'a': 3}], [true, true, true]) query I SELECT list_where([1,2,3]::INT[3], [true, false, true]::BOOLEAN[3]); ---- -[1, 3] \ No newline at end of file +[1, 3] + +query I +SELECT LIST_WHERE(ARRAY_VALUE('1', NULL), [TRUE, TRUE, TRUE]); +---- +[1, NULL, NULL] + + +query I +SELECT LIST_WHERE(ARRAY_VALUE('1', NULL), [TRUE, TRUE, FALSE]); +---- +[1, NULL] \ No newline at end of file diff --git a/test/sql/function/list/list_zip.test b/test/sql/function/list/list_zip.test index b6565d08171..da2ef5a8832 100644 --- a/test/sql/function/list/list_zip.test +++ b/test/sql/function/list/list_zip.test @@ -291,3 +291,12 @@ SELECT list_zip([{'a': 1}, {'a': 5}, {'a': 3}]) ---- [({'a': 1}), ({'a': 5}), ({'a': 3})] +# Non-list type + +statement error +SELECT list_zip('') +---- + +statement error +SELECT list_zip(3, 4) +---- diff --git a/test/sql/function/operator/test_date_arithmetic.test b/test/sql/function/operator/test_date_arithmetic.test index ec5f158fd6a..bbe9a12f00d 100644 --- a/test/sql/function/operator/test_date_arithmetic.test +++ b/test/sql/function/operator/test_date_arithmetic.test @@ -121,34 +121,34 @@ ORDER BY 1, 2 ---- NULL NULL NULL NULL 00:01:20+00 NULL -NULL 20:08:10.001-15:59 NULL NULL 20:08:10.33+12 NULL NULL 20:08:10.998-07 NULL +NULL 20:08:10.001-15:59 NULL 0044-03-15 (BC) NULL NULL 0044-03-15 (BC) 00:01:20+00 0044-03-15 (BC) 00:01:20+00 -0044-03-15 (BC) 20:08:10.001-15:59 0044-03-16 (BC) 12:07:10.001+00 0044-03-15 (BC) 20:08:10.33+12 0044-03-15 (BC) 08:08:10.33+00 0044-03-15 (BC) 20:08:10.998-07 0044-03-16 (BC) 03:08:10.998+00 +0044-03-15 (BC) 20:08:10.001-15:59 0044-03-16 (BC) 12:07:10.001+00 1992-01-01 NULL NULL 1992-01-01 00:01:20+00 1992-01-01 00:01:20+00 -1992-01-01 20:08:10.001-15:59 1992-01-02 12:07:10.001+00 1992-01-01 20:08:10.33+12 1992-01-01 08:08:10.33+00 1992-01-01 20:08:10.998-07 1992-01-02 03:08:10.998+00 +1992-01-01 20:08:10.001-15:59 1992-01-02 12:07:10.001+00 1992-03-03 NULL NULL 1992-03-03 00:01:20+00 1992-03-03 00:01:20+00 -1992-03-03 20:08:10.001-15:59 1992-03-04 12:07:10.001+00 1992-03-03 20:08:10.33+12 1992-03-03 08:08:10.33+00 1992-03-03 20:08:10.998-07 1992-03-04 03:08:10.998+00 +1992-03-03 20:08:10.001-15:59 1992-03-04 12:07:10.001+00 1992-05-05 NULL NULL 1992-05-05 00:01:20+00 1992-05-05 00:01:20+00 -1992-05-05 20:08:10.001-15:59 1992-05-06 12:07:10.001+00 1992-05-05 20:08:10.33+12 1992-05-05 08:08:10.33+00 1992-05-05 20:08:10.998-07 1992-05-06 03:08:10.998+00 +1992-05-05 20:08:10.001-15:59 1992-05-06 12:07:10.001+00 2022-01-01 NULL NULL 2022-01-01 00:01:20+00 2022-01-01 00:01:20+00 -2022-01-01 20:08:10.001-15:59 2022-01-02 12:07:10.001+00 2022-01-01 20:08:10.33+12 2022-01-01 08:08:10.33+00 2022-01-01 20:08:10.998-07 2022-01-02 03:08:10.998+00 +2022-01-01 20:08:10.001-15:59 2022-01-02 12:07:10.001+00 query III SELECT d, ttz, ttz + d @@ -157,34 +157,34 @@ ORDER BY 1, 2 ---- NULL NULL NULL NULL 00:01:20+00 NULL -NULL 20:08:10.001-15:59 NULL NULL 20:08:10.33+12 NULL NULL 20:08:10.998-07 NULL +NULL 20:08:10.001-15:59 NULL 0044-03-15 (BC) NULL NULL 0044-03-15 (BC) 00:01:20+00 0044-03-15 (BC) 00:01:20+00 -0044-03-15 (BC) 20:08:10.001-15:59 0044-03-16 (BC) 12:07:10.001+00 0044-03-15 (BC) 20:08:10.33+12 0044-03-15 (BC) 08:08:10.33+00 0044-03-15 (BC) 20:08:10.998-07 0044-03-16 (BC) 03:08:10.998+00 +0044-03-15 (BC) 20:08:10.001-15:59 0044-03-16 (BC) 12:07:10.001+00 1992-01-01 NULL NULL 1992-01-01 00:01:20+00 1992-01-01 00:01:20+00 -1992-01-01 20:08:10.001-15:59 1992-01-02 12:07:10.001+00 1992-01-01 20:08:10.33+12 1992-01-01 08:08:10.33+00 1992-01-01 20:08:10.998-07 1992-01-02 03:08:10.998+00 +1992-01-01 20:08:10.001-15:59 1992-01-02 12:07:10.001+00 1992-03-03 NULL NULL 1992-03-03 00:01:20+00 1992-03-03 00:01:20+00 -1992-03-03 20:08:10.001-15:59 1992-03-04 12:07:10.001+00 1992-03-03 20:08:10.33+12 1992-03-03 08:08:10.33+00 1992-03-03 20:08:10.998-07 1992-03-04 03:08:10.998+00 +1992-03-03 20:08:10.001-15:59 1992-03-04 12:07:10.001+00 1992-05-05 NULL NULL 1992-05-05 00:01:20+00 1992-05-05 00:01:20+00 -1992-05-05 20:08:10.001-15:59 1992-05-06 12:07:10.001+00 1992-05-05 20:08:10.33+12 1992-05-05 08:08:10.33+00 1992-05-05 20:08:10.998-07 1992-05-06 03:08:10.998+00 +1992-05-05 20:08:10.001-15:59 1992-05-06 12:07:10.001+00 2022-01-01 NULL NULL 2022-01-01 00:01:20+00 2022-01-01 00:01:20+00 -2022-01-01 20:08:10.001-15:59 2022-01-02 12:07:10.001+00 2022-01-01 20:08:10.33+12 2022-01-01 08:08:10.33+00 2022-01-01 20:08:10.998-07 2022-01-02 03:08:10.998+00 +2022-01-01 20:08:10.001-15:59 2022-01-02 12:07:10.001+00 # Overflow statement error diff --git a/test/sql/function/string/test_concat.test b/test/sql/function/string/test_concat.test index 9fdaefe4cc7..0a0a5f1d1d0 100644 --- a/test/sql/function/string/test_concat.test +++ b/test/sql/function/string/test_concat.test @@ -81,4 +81,3 @@ SELECT CONCAT('hello', ' ', s) FROM strings ORDER BY s hello hello hello hello world - diff --git a/test/sql/function/string/test_concat_binding.test b/test/sql/function/string/test_concat_binding.test new file mode 100644 index 00000000000..7904df568af --- /dev/null +++ b/test/sql/function/string/test_concat_binding.test @@ -0,0 +1,69 @@ +# name: test/sql/function/string/test_concat_binding.test +# description: Test the binding of the concat function +# group: [string] + +statement ok +PRAGMA enable_verification + +statement ok +SET default_null_order='nulls_first'; + +query I +select [1] || [2]; +---- +[1, 2] + +query I +select [1] || NULL; +---- +NULL + +query I +select list_concat([1], NULL); +---- +[1] + +query I +SELECT CONCAT('hello') +---- +hello + +query I +select array[1] || array[2]; +---- +[1, 2] + +query I +select array[1] || array[NULL]; +---- +[1, NULL] + +query I +select list_concat(array[1], array[NULL]); +---- +[1, NULL] + +query I +select array[1] || cast(NULL as int array); +---- +NULL + +statement error +select concat([1], 'hello'); +---- +Binder Error: Cannot concatenate types INTEGER[] and VARCHAR + +query I +select 'hi' || NULL; +---- +NULL + +statement error +select list_concat([1], [2], [3]); +---- +Binder Error: No function matches the given name and argument types 'list_concat(INTEGER[], INTEGER[], INTEGER[])'. + +query I +select [1] || [2] || [3]; +---- +[1, 2, 3] diff --git a/test/sql/function/time/test_date_part.test b/test/sql/function/time/test_date_part.test index c456340ff55..663cfebb58e 100644 --- a/test/sql/function/time/test_date_part.test +++ b/test/sql/function/time/test_date_part.test @@ -235,6 +235,14 @@ SELECT d, epoch_ms(d) FROM times ORDER BY ALL; 20:08:10.33 72490330 20:08:10.998 72490998 +query II +SELECT d, nanosecond(d) FROM times ORDER BY ALL; +---- +00:01:20 20000000000 +20:08:10.001 10001000000 +20:08:10.33 10330000000 +20:08:10.998 10998000000 + # Invalid parts foreach datepart year month day decade century millennium quarter dow isodow doy week isoyear yearweek era julian diff --git a/test/sql/function/timestamp/test_date_part.test b/test/sql/function/timestamp/test_date_part.test index 178f570ea23..7885753ffaf 100644 --- a/test/sql/function/timestamp/test_date_part.test +++ b/test/sql/function/timestamp/test_date_part.test @@ -842,6 +842,96 @@ NULL NULL 2022-01-01 00:00:41+00 1640995241000000000 infinity NULL +query II +SELECT ts, nanosecond(ts) FROM timestamps ORDER BY ALL; +---- +NULL NULL +-infinity NULL +1962-07-31 12:20:48.123456 48123456000 +1969-01-01 01:03:20.45432 20454320000 +1992-01-01 01:01:01.4 1400000000 +1992-01-01 01:01:02.2 2200000000 +1992-01-01 01:01:02.4 2400000000 +1993-08-14 08:22:33 33000000000 +1993-08-14 08:22:33.42 33420000000 +2001-04-20 14:42:11 11000000000 +2001-04-20 14:42:11.123 11123000000 +2004-01-31 12:00:00.00005 50000 +2004-01-31 12:00:00.05 50000000 +2004-02-01 12:00:00.00005 50000 +2004-02-01 12:00:00.05 50000000 +2004-02-29 13:05:47.123456 47123456000 +2008-01-01 00:00:01.5 1500000000 +2008-01-01 00:00:01.594 1594000000 +2008-01-01 00:00:01.794 1794000000 +2008-01-01 00:00:01.88926 1889260000 +2008-01-01 00:00:01.894 1894000000 +2008-01-01 00:00:01.98926 1989260000 +2008-01-01 00:00:01.99926 1999260000 +2008-01-01 00:00:11.1 11100000000 +2019-01-06 04:03:02.123456 2123456000 +2019-01-06 04:03:02.5 2500000000 +2020-01-01 00:00:01.88926 1889260000 +2020-12-31 21:25:58.745232 58745232000 +2021-04-15 14:55:17.915 17915000000 +2021-04-15 14:55:17.915 17915000000 +2021-05-02 12:11:49.5 49500000000 +2021-12-01 13:54:48.123456 48123456000 +2022-01-01 00:00:41 41000000000 +infinity NULL + +query II +SELECT ts::TIMESTAMPTZ, nanosecond(ts::TIMESTAMPTZ) FROM timestamps ORDER BY ALL; +---- +NULL NULL +-infinity NULL +1962-07-31 12:20:48.123456+00 48123456000 +1969-01-01 01:03:20.45432+00 20454320000 +1992-01-01 01:01:01.4+00 1400000000 +1992-01-01 01:01:02.2+00 2200000000 +1992-01-01 01:01:02.4+00 2400000000 +1993-08-14 08:22:33+00 33000000000 +1993-08-14 08:22:33.42+00 33420000000 +2001-04-20 14:42:11+00 11000000000 +2001-04-20 14:42:11.123+00 11123000000 +2004-01-31 12:00:00.00005+00 50000 +2004-01-31 12:00:00.05+00 50000000 +2004-02-01 12:00:00.00005+00 50000 +2004-02-01 12:00:00.05+00 50000000 +2004-02-29 13:05:47.123456+00 47123456000 +2008-01-01 00:00:01.5+00 1500000000 +2008-01-01 00:00:01.594+00 1594000000 +2008-01-01 00:00:01.794+00 1794000000 +2008-01-01 00:00:01.88926+00 1889260000 +2008-01-01 00:00:01.894+00 1894000000 +2008-01-01 00:00:01.98926+00 1989260000 +2008-01-01 00:00:01.99926+00 1999260000 +2008-01-01 00:00:11.1+00 11100000000 +2019-01-06 04:03:02.123456+00 2123456000 +2019-01-06 04:03:02.5+00 2500000000 +2020-01-01 00:00:01.88926+00 1889260000 +2020-12-31 21:25:58.745232+00 58745232000 +2021-04-15 14:55:17.915+00 17915000000 +2021-04-15 14:55:17.915+00 17915000000 +2021-05-02 12:11:49.5+00 49500000000 +2021-12-01 13:54:48.123456+00 48123456000 +2022-01-01 00:00:41+00 41000000000 +infinity NULL + +query I +SELECT nanosecond(t) +FROM VALUES + ('1992-01-01 12:03:27.123456789'::TIMESTAMP_NS), + ('1900-01-01 03:08:47.987654'::TIMESTAMP_NS), + (NULL::TIMESTAMP_NS), + ('2020-09-27 13:12:01'::TIMESTAMP_NS) + AS tbl(t); +---- +27123456789 +47987654000 +NULL +1000000000 + # Invalid parts statement error SELECT ts, DATE_PART(['duck', 'month', 'day'], ts) AS parts diff --git a/test/sql/function/timestamp/test_icu_datetrunc.test b/test/sql/function/timestamp/test_icu_datetrunc.test index 9b67ef3a0c9..74968fc5ad9 100644 --- a/test/sql/function/timestamp/test_icu_datetrunc.test +++ b/test/sql/function/timestamp/test_icu_datetrunc.test @@ -238,3 +238,11 @@ select date_trunc('minute', '2022-10-30 02:17:00+02'::TIMESTAMPTZ); ---- 2022-10-30 02:17:00+02 +# Comparisons to DATE +statement ok +set time zone 'UTC'; + +query I +select date_trunc('day', '2024-05-06 16:09:28+05:00'::timestamptz) >= '2024-05-06 17:19:18+05:20'::date as r +---- +True diff --git a/test/sql/function/timestamp/test_icu_strptime.test b/test/sql/function/timestamp/test_icu_strptime.test index c6de0be1894..ff9c14ca4f7 100644 --- a/test/sql/function/timestamp/test_icu_strptime.test +++ b/test/sql/function/timestamp/test_icu_strptime.test @@ -421,6 +421,96 @@ ORDER BY ALL 2022-03-05 20:59:17.877-08 Pacific/Niue 2022-03-05 21:59:17.877-08 Etc/GMT+12 +# First has no TZ +query II +SELECT ${func}('2022-03-05 17:59:17.877 ' || tz_name, ['%Y-%m-%d %H:%M:%S.%g', '%Y-%m-%d %H:%M:%S.%g %Z']) tstz, tz_name +FROM zones +ORDER BY ALL +---- +2022-03-04 19:59:17.877-08 Etc/GMT-14 +2022-03-04 20:14:17.877-08 NZ-CHAT +2022-03-04 20:59:17.877-08 Pacific/Auckland +2022-03-04 20:59:17.877-08 Pacific/Enderbury +2022-03-04 22:59:17.877-08 Australia/LHI +2022-03-04 22:59:17.877-08 Australia/Melbourne +2022-03-04 22:59:17.877-08 Pacific/Efate +2022-03-05 00:29:17.877-08 Australia/Darwin +2022-03-05 00:59:17.877-08 Asia/Tokyo +2022-03-05 01:14:17.877-08 Australia/Eucla +2022-03-05 01:59:17.877-08 Asia/Shanghai +2022-03-05 02:59:17.877-08 Asia/Novosibirsk +2022-03-05 03:29:17.877-08 Asia/Yangon +2022-03-05 03:59:17.877-08 Asia/Omsk +2022-03-05 04:14:17.877-08 Asia/Kathmandu +2022-03-05 04:29:17.877-08 Asia/Colombo +2022-03-05 04:59:17.877-08 Asia/Oral +2022-03-05 05:29:17.877-08 Asia/Kabul +2022-03-05 05:59:17.877-08 Europe/Astrakhan +2022-03-05 06:29:17.877-08 Asia/Tehran +2022-03-05 06:59:17.877-08 Asia/Kuwait +2022-03-05 07:59:17.877-08 Asia/Nicosia +2022-03-05 08:59:17.877-08 Europe/Budapest +2022-03-05 09:59:17.877-08 Etc/GMT-0 +2022-03-05 10:59:17.877-08 Atlantic/Azores +2022-03-05 12:59:17.877-08 America/Cayenne +2022-03-05 12:59:17.877-08 America/Nuuk +2022-03-05 13:29:17.877-08 CNT +2022-03-05 13:59:17.877-08 America/Martinique +2022-03-05 14:59:17.877-08 America/Louisville +2022-03-05 15:59:17.877-08 America/Rainy_River +2022-03-05 16:59:17.877-08 America/Shiprock +2022-03-05 17:59:17.877-08 Mexico/BajaNorte +2022-03-05 18:59:17.877-08 America/Sitka +2022-03-05 19:29:17.877-08 Pacific/Marquesas +2022-03-05 19:59:17.877-08 Pacific/Johnston +2022-03-05 20:59:17.877-08 Pacific/Niue +2022-03-05 21:59:17.877-08 Etc/GMT+12 + +# Neither has TZ - should be TS not TSTZ +query II +SELECT ${func}('2022-03-05 17:59:17.877', ['%m/%d/%Y %H:%M:%S.%g', '%Y-%m-%d %H:%M:%S.%g']) tstz, tz_name +FROM zones +ORDER BY ALL +---- +2022-03-05 17:59:17.877 America/Cayenne +2022-03-05 17:59:17.877 America/Louisville +2022-03-05 17:59:17.877 America/Martinique +2022-03-05 17:59:17.877 America/Nuuk +2022-03-05 17:59:17.877 America/Rainy_River +2022-03-05 17:59:17.877 America/Shiprock +2022-03-05 17:59:17.877 America/Sitka +2022-03-05 17:59:17.877 Asia/Colombo +2022-03-05 17:59:17.877 Asia/Kabul +2022-03-05 17:59:17.877 Asia/Kathmandu +2022-03-05 17:59:17.877 Asia/Kuwait +2022-03-05 17:59:17.877 Asia/Nicosia +2022-03-05 17:59:17.877 Asia/Novosibirsk +2022-03-05 17:59:17.877 Asia/Omsk +2022-03-05 17:59:17.877 Asia/Oral +2022-03-05 17:59:17.877 Asia/Shanghai +2022-03-05 17:59:17.877 Asia/Tehran +2022-03-05 17:59:17.877 Asia/Tokyo +2022-03-05 17:59:17.877 Asia/Yangon +2022-03-05 17:59:17.877 Atlantic/Azores +2022-03-05 17:59:17.877 Australia/Darwin +2022-03-05 17:59:17.877 Australia/Eucla +2022-03-05 17:59:17.877 Australia/LHI +2022-03-05 17:59:17.877 Australia/Melbourne +2022-03-05 17:59:17.877 CNT +2022-03-05 17:59:17.877 Etc/GMT+12 +2022-03-05 17:59:17.877 Etc/GMT-0 +2022-03-05 17:59:17.877 Etc/GMT-14 +2022-03-05 17:59:17.877 Europe/Astrakhan +2022-03-05 17:59:17.877 Europe/Budapest +2022-03-05 17:59:17.877 Mexico/BajaNorte +2022-03-05 17:59:17.877 NZ-CHAT +2022-03-05 17:59:17.877 Pacific/Auckland +2022-03-05 17:59:17.877 Pacific/Efate +2022-03-05 17:59:17.877 Pacific/Enderbury +2022-03-05 17:59:17.877 Pacific/Johnston +2022-03-05 17:59:17.877 Pacific/Marquesas +2022-03-05 17:59:17.877 Pacific/Niue + endloop # diff --git a/test/sql/function/timestamp/test_strftime_timestamp_ns.test b/test/sql/function/timestamp/test_strftime_timestamp_ns.test new file mode 100644 index 00000000000..fdf807a4aee --- /dev/null +++ b/test/sql/function/timestamp/test_strftime_timestamp_ns.test @@ -0,0 +1,398 @@ +# name: test/sql/function/timestamp/test_strftime_timestamp_ns.test +# description: Test all strftime % codes with the TIMESTAMP_NS type +# group: [timestamp] + +statement ok +SET default_null_order='nulls_first'; + +statement ok +PRAGMA enable_verification + +statement ok +CREATE TABLE timestamps(d TIMESTAMP_NS); +INSERT INTO timestamps VALUES + ('1992-01-01 01:20:30'), + ('1993-03-20 23:50:01.123'), + ('2020-08-09 12:01:55.123456'), + ('2020-08-10 10:10:10.123456789'), + (NULL); + +# %a: Abbreviated weekday name +query I +SELECT strftime(d, '%a') FROM timestamps ORDER BY d; +---- +NULL +Wed +Sat +Sun +Mon + +# %A: Full weekday name +query I +SELECT strftime(d, '%A') FROM timestamps ORDER BY d; +---- +NULL +Wednesday +Saturday +Sunday +Monday + +# %w - Weekday as a decimal number. +query I +SELECT strftime(d, '%w') FROM timestamps ORDER BY d; +---- +NULL +3 +6 +0 +1 + +# %u - ISO Weekday as a decimal number. +query I +SELECT strftime(d, '%u') FROM timestamps ORDER BY d; +---- +NULL +3 +6 +7 +1 + +# %d - Day of the month as a zero-padded decimal. +query I +SELECT strftime(d, '%d') FROM timestamps ORDER BY d; +---- +NULL +01 +20 +09 +10 + +# %-d - Day of the month as a decimal number. +query I +SELECT strftime(d, '%-d') FROM timestamps ORDER BY d; +---- +NULL +1 +20 +9 +10 + +# %b - Abbreviated month name. +query I +SELECT strftime(d, '%b') FROM timestamps ORDER BY d; +---- +NULL +Jan +Mar +Aug +Aug + +# %h - alias for %b +query I +SELECT strftime(d, '%h') FROM timestamps ORDER BY d; +---- +NULL +Jan +Mar +Aug +Aug + +# %B - Full month name +query I +SELECT strftime(d, '%B') FROM timestamps ORDER BY d; +---- +NULL +January +March +August +August + +# %m - Month as a zero-padded decimal number +query I +SELECT strftime(d, '%m') FROM timestamps ORDER BY d; +---- +NULL +01 +03 +08 +08 + +# %-m - Month as a decimal number. (1, 2, ..., 12) +query I +SELECT strftime(d, '%-m') FROM timestamps ORDER BY d; +---- +NULL +1 +3 +8 +8 + +# %y - Year without century as a zero-padded decimal number. +query I +SELECT strftime(d, '%y') FROM timestamps ORDER BY d; +---- +NULL +92 +93 +20 +20 + +# %-y - Year without century as a decimal number. +query I +SELECT strftime(d, '%-y') FROM timestamps ORDER BY d; +---- +NULL +92 +93 +20 +20 + +query I +SELECT strftime(DATE '2001-01-01', '%-y') +---- +1 + +# %Y - Year with century as a decimal number. +query I +SELECT strftime(d, '%Y') FROM timestamps ORDER BY d; +---- +NULL +1992 +1993 +2020 +2020 + +# %G - ISO Year with century as a decimal number. +query I +SELECT strftime(d, '%G') FROM timestamps ORDER BY d; +---- +NULL +1992 +1993 +2020 +2020 + +# %H - Hour (24-hour clock) as a zero-padded decimal number. +query I +SELECT strftime(d, '%H') FROM timestamps ORDER BY d; +---- +NULL +01 +23 +12 +10 + +# %-H - Hour (24-hour clock) as a decimal number. (0, 1, ..., 23) +query I +SELECT strftime(d, '%-H') FROM timestamps ORDER BY d; +---- +NULL +1 +23 +12 +10 + +# %I - Hour (12-hour clock) as a zero-padded decimal number. +query I +SELECT strftime(d, '%I') FROM timestamps ORDER BY d; +---- +NULL +01 +11 +12 +10 + +# %-I - Hour (12-hour clock) as a decimal number. (1, 2, ... 12) +query I +SELECT strftime(d, '%-I') FROM timestamps ORDER BY d; +---- +NULL +1 +11 +12 +10 + +# %p - Locale’s AM or PM. +query I +SELECT strftime(d, '%p') FROM timestamps ORDER BY d; +---- +NULL +AM +PM +PM +AM + +# %M - Minute as a zero-padded decimal number. +query I +SELECT strftime(d, '%M') FROM timestamps ORDER BY d; +---- +NULL +20 +50 +01 +10 + +# %-M - Minute as a decimal number. (0, 1, ..., 59) +query I +SELECT strftime(d, '%-M') FROM timestamps ORDER BY d; +---- +NULL +20 +50 +1 +10 + +# %S - Second as a zero-padded decimal number. +query I +SELECT strftime(d, '%S') FROM timestamps ORDER BY d; +---- +NULL +30 +01 +55 +10 + +# %-S - Second as a decimal number. (0, 1, ..., 59) +query I +SELECT strftime(d, '%-S') FROM timestamps ORDER BY d; +---- +NULL +30 +1 +55 +10 + +# %f - Microsecond as a decimal number, zero-padded on the left. +query I +SELECT strftime(d, '%f') FROM timestamps ORDER BY d; +---- +NULL +000000 +123000 +123456 +123456 + +# %g - Millisecond as a decimal number, zero-padded on the left. +query I +SELECT strftime(d, '%g') +FROM timestamps +ORDER BY d; +---- +NULL +000 +123 +123 +123 + +# %n - Nanosecond as a decimal number, zero-padded on the left. +query I +SELECT strftime(d, '%n') +FROM timestamps +ORDER BY d; +---- +NULL +000000000 +123000000 +123456000 +123456789 + +# %z - UTC offset in the form +HHMM or -HHMM. +query I +SELECT strftime(d, '%z') FROM timestamps ORDER BY d; +---- +NULL ++00 ++00 ++00 ++00 + +# %Z - Time zone name. +query I +SELECT strftime(d, '%Z') FROM timestamps ORDER BY d; +---- +NULL +(empty) +(empty) +(empty) +(empty) + +# %j - Day of the year as a zero-padded decimal number. +query I +SELECT strftime(d, '%j') FROM timestamps ORDER BY d; +---- +NULL +001 +079 +222 +223 + +# %-j - Day of the year as a decimal number. (1, 2, ..., 366) +query I +SELECT strftime(d, '%-j') FROM timestamps ORDER BY d; +---- +NULL +1 +79 +222 +223 + + +# %U - Week number of the year (Sunday as the first day of the week). +query I +SELECT strftime(d, '%U') FROM timestamps ORDER BY d; +---- +NULL +00 +11 +32 +32 + +# %W - Week number of the year (Monday as the first day of the week). +query I +SELECT strftime(d, '%W') FROM timestamps ORDER BY d; +---- +NULL +00 +11 +31 +32 + +# %V - ISO Week number of the year (Week 1 contains Jan 4). +query I +SELECT strftime(d, '%V') FROM timestamps ORDER BY d; +---- +NULL +01 +11 +32 +33 + +# %c - Locale’s appropriate date and time representation. +query I +SELECT strftime(d, '%c') FROM timestamps ORDER BY d; +---- +NULL +1992-01-01 01:20:30 +1993-03-20 23:50:01 +2020-08-09 12:01:55 +2020-08-10 10:10:10 + +# %x - Locale’s appropriate date representation. +query I +SELECT strftime(d, '%x') FROM timestamps ORDER BY d; +---- +NULL +1992-01-01 +1993-03-20 +2020-08-09 +2020-08-10 + +# X - Locale’s appropriate time representation. +query I +SELECT strftime(d, '%X') FROM timestamps ORDER BY d; +---- +NULL +01:20:30 +23:50:01 +12:01:55 +10:10:10 diff --git a/test/sql/function/timestamp/test_strptime.test b/test/sql/function/timestamp/test_strptime.test index 257b740a87a..9be03a0310d 100644 --- a/test/sql/function/timestamp/test_strptime.test +++ b/test/sql/function/timestamp/test_strptime.test @@ -261,13 +261,13 @@ SELECT strptime('Jun 30 2003 2:03:10AM', '%b %d %Y %-I:%M:%S%p'); query I select strptime('2020-12-31 21:25:58.745232159', '%Y-%m-%d %H:%M:%S.%n'); ---- -2020-12-31 21:25:58.745232 +2020-12-31 21:25:58.745232159 # Rounding of ns query I select strptime('2020-12-31 21:25:58.745232951', '%Y-%m-%d %H:%M:%S.%n'); ---- -2020-12-31 21:25:58.745233 +2020-12-31 21:25:58.745232951 query I select strptime('2020-12-31 21:25:58.745232', '%Y-%m-%d %H:%M:%S.%f'); diff --git a/test/sql/function/timetz/test_date_part.test b/test/sql/function/timetz/test_date_part.test index 1ae4cad3ecc..3e6a908adcb 100644 --- a/test/sql/function/timetz/test_date_part.test +++ b/test/sql/function/timetz/test_date_part.test @@ -352,6 +352,22 @@ SELECT d, epoch_ms(d) FROM timetzs ORDER BY ALL; 24:00:00-15:59 86400000 NULL NULL +query II +SELECT d, nanosecond(d) FROM timetzs ORDER BY ALL; +---- +00:00:00+15:59 0 +00:00:00+15:58 0 +02:30:00+12 0 +02:30:00+04:30:45 0 +02:30:00+04:30 0 +02:30:00+04 0 +02:30:00+00 0 +02:30:00-12 0 +16:15:03.123456+00 3123456000 +24:00:00-15:58 0 +24:00:00-15:59 0 +NULL NULL + # Invalid parts foreach datepart year month day decade century millennium quarter dow isodow doy week isoyear yearweek era julian diff --git a/test/sql/generated_columns/virtual/cascading_delete.test b/test/sql/generated_columns/virtual/cascading_delete.test index d568ea96016..befd5ff1444 100644 --- a/test/sql/generated_columns/virtual/cascading_delete.test +++ b/test/sql/generated_columns/virtual/cascading_delete.test @@ -28,6 +28,7 @@ SELECT * FROM unit; statement error ALTER TABLE unit DROP COLUMN price; ---- +Cannot drop column: column is a dependency of 1 or more generated column(s) statement ok ALTER TABLE unit DROP COLUMN price CASCADE; diff --git a/test/sql/httpfs/hffs.test b/test/sql/httpfs/hffs.test new file mode 100644 index 00000000000..82231fb9a67 --- /dev/null +++ b/test/sql/httpfs/hffs.test @@ -0,0 +1,42 @@ +# name: test/sql/httpfs/hffs.test +# description: Ensure the HuggingFace filesystem works as expected +# group: [httpfs] + +require parquet + +require httpfs + +statement error +FROM parquet_scan('hf://') +---- +IO Error: Failed to parse 'hf://'. Please format url like: 'hf://datasets/my-username/my-dataset/path/to/file.parquet' + +statement error +FROM 'hf://file.parquet' +---- +IO Error: Failed to parse 'hf://file.parquet'. Please format url like: 'hf://datasets/my-username/my-dataset/path/to/file.parquet' + +statement error +FROM 'hf://yepthisdoesntwork/file.parquet' +---- +IO Error: Failed to parse: 'hf://yepthisdoesntwork/file.parquet'. Currently DuckDB only supports querying datasets or spaces, so the url should start with 'hf://datasets' or 'hf://spaces' + +statement error +FROM 'hf://stil/not/file.parquet' +---- +IO Error: Failed to parse: 'hf://stil/not/file.parquet'. Currently DuckDB only supports querying datasets or spaces, so the url should start with 'hf://datasets' or 'hf://spaces' + +statement error +FROM 'hf://datasets/file.parquet' +---- +IO Error: Failed to parse 'hf://datasets/file.parquet'. Please format url like: 'hf://datasets/my-username/my-dataset/path/to/file.parquet' + +statement error +FROM 'hf://datasets/myname/file.parquet' +---- +IO Error: Failed to parse 'hf://datasets/myname/file.parquet'. Please format url like: 'hf://datasets/my-username/my-dataset/path/to/file.parquet' + +statement error +FROM 'hf://datasets/**/file.parquet' +---- +IO Error: Failed to parse 'hf://datasets/**/file.parquet'. Please format url like: 'hf://datasets/my-username/my-dataset/path/to/file.parquet' diff --git a/test/sql/httpfs/hffs.test_slow b/test/sql/httpfs/hffs.test_slow new file mode 100644 index 00000000000..527916e5d11 --- /dev/null +++ b/test/sql/httpfs/hffs.test_slow @@ -0,0 +1,122 @@ +# name: test/sql/httpfs/hffs.test_slow +# description: Ensure the HuggingFace filesystem works as expected +# group: [httpfs] + +require parquet + +require httpfs + +# FIXME: currently this will not fail the Linux HTTPFS ci job if it fails, because it might do so due to networking issues +# however having a CI job dedicated to remote tests that may spuriously fail would solve this + +# Non existent repos get a 401 +statement error +FROM parquet_scan('hf://datasets/samansmink/non-existent/*.parquet'); +---- +HTTP 401 + +# Globbing non-existent repo is also 401 +statement error +FROM parquet_scan('hf://datasets/samansmink/non-existent/**/*.parquet'); +---- +HTTP 401 + +query III rowsort +FROM parquet_scan('hf://datasets/samansmink/duckdb_ci_tests/hive_data/**/*.parquet', FILENAME=1, hive_partitioning=0); +---- +1 value1 hf://datasets/samansmink/duckdb_ci_tests/hive_data/part=a/date=2012-01-01/test.parquet +2 value2 hf://datasets/samansmink/duckdb_ci_tests/hive_data/part=b/date=2013-01-01/test.parquet + + +query III rowsort +FROM parquet_scan('hf://datasets/samansmink/duckdb_ci_tests/hive_data/*/*/**/*.parquet', FILENAME=1, hive_partitioning=0); +---- +1 value1 hf://datasets/samansmink/duckdb_ci_tests/hive_data/part=a/date=2012-01-01/test.parquet +2 value2 hf://datasets/samansmink/duckdb_ci_tests/hive_data/part=b/date=2013-01-01/test.parquet + +query III rowsort +FROM parquet_scan('hf://datasets/samansmink/duckdb_ci_tests/hive_data/part=[ab]/**/*.parquet', FILENAME=1, hive_partitioning=0); +---- +1 value1 hf://datasets/samansmink/duckdb_ci_tests/hive_data/part=a/date=2012-01-01/test.parquet +2 value2 hf://datasets/samansmink/duckdb_ci_tests/hive_data/part=b/date=2013-01-01/test.parquet + +# This ensures the next query is forced to use pagination, testing our support for it +statement ok +set hf_max_per_page=1; + +query III rowsort +FROM parquet_scan('hf://datasets/samansmink/duckdb_ci_tests/hive_data/part=[b]/**/*.parquet', FILENAME=1, hive_partitioning=0); +---- +2 value2 hf://datasets/samansmink/duckdb_ci_tests/hive_data/part=b/date=2013-01-01/test.parquet + +statement ok +reset hf_max_per_page; + +# Ensure we only open 1 of the files here to confirm filter pushdown has eliminated the other paths +query II rowsort +explain analyze SELECT id, part FROM parquet_scan('hf://datasets/samansmink/duckdb_ci_tests/hive_data/**/*.parquet') where part='a'; +---- +analyzed_plan :.*HTTP Stats.*\#HEAD\: 1 .* + +statement ok +set hf_max_per_page=1; + +# Branches can be specified, including the special branch types with '~' +query III rowsort +FROM parquet_scan('hf://datasets/samansmink/duckdb_ci_tests@~parquet/**/*.parquet', FILENAME=1, hive_partitioning=0); +---- +1 value1 hf://datasets/samansmink/duckdb_ci_tests@~parquet/default/test/0000.parquet +2 value2 hf://datasets/samansmink/duckdb_ci_tests@~parquet/default/test/0001.parquet + +# Secret provider 'config' (default) allows setting the token directly +statement ok +CREATE SECRET hf_token (TYPE HUGGINGFACE, token 'some_hf_token'); + +# Secret provider 'credential chain' scans several places for a token +statement ok +CREATE SECRET hf_token_from_credential_chain (TYPE HUGGINGFACE, PROVIDER credential_chain); + +statement ok +DROP SECRET hf_token + +statement ok +DROP SECRET hf_token_from_credential_chain + +# Private bucket is not allowed without credentials +statement error +FROM parquet_scan('hf://datasets/samansmink/duckdb_ci_private/hive_data/**/*.parquet', FILENAME=1, hive_partitioning=0); +---- +401 + +# Ensure spaces work too +query I +select size from read_text('hf://spaces/samansmink/duckdb_ci_tests/README.md'); +---- +199 + +# FIXME: push auth key into CI for this to ensure it is tested in CI properly +require-env HUGGING_FACE_TOKEN + +statement ok +CREATE SECRET hf1 (TYPE HUGGINGFACE, TOKEN '${HUGGING_FACE_TOKEN}'); + +query III rowsort +FROM parquet_scan('hf://datasets/samansmink/duckdb_ci_private/hive_data/**/*.parquet', FILENAME=1, hive_partitioning=0); +---- +1 value1 hf://datasets/samansmink/duckdb_ci_private/hive_data/part=a/date=2012-01-01/test.parquet +2 value2 hf://datasets/samansmink/duckdb_ci_private/hive_data/part=b/date=2013-01-01/test.parquet + +statement ok +DROP SECRET hf1 + +# FIXME: test this from CI as well +require-env HUGGING_FACE_TOKEN_IN_CACHE + +statement ok +CREATE SECRET hf1 (TYPE HUGGINGFACE, PROVIDER credential_chain); + +query III rowsort +FROM parquet_scan('hf://datasets/samansmink/duckdb_ci_private/hive_data/**/*.parquet', FILENAME=1, hive_partitioning=0); +---- +1 value1 hf://datasets/samansmink/duckdb_ci_private/hive_data/part=a/date=2012-01-01/test.parquet +2 value2 hf://datasets/samansmink/duckdb_ci_private/hive_data/part=b/date=2013-01-01/test.parquet \ No newline at end of file diff --git a/test/sql/index/art/storage/test_art_auto_checkpoint.test b/test/sql/index/art/storage/test_art_auto_checkpoint.test index 98f9c8ec9b4..d6dd05b53af 100644 --- a/test/sql/index/art/storage/test_art_auto_checkpoint.test +++ b/test/sql/index/art/storage/test_art_auto_checkpoint.test @@ -2,13 +2,13 @@ # description: Test auto checkpointing of the ART after CREATE and INSERT # group: [storage] +# this test does not work with vsize = 2 because a low vector size changes the WAL threshold +require vector_size 2048 + # test auto checkpointing after CREATE INDEX load __TEST_DIR__/idx_checkpoint_create.db -# this test does not work with vsize = 2 because a low vector size changes the WAL threshold -require vector_size 2048 - statement ok PRAGMA enable_verification; diff --git a/test/sql/index/art/vacuum/test_art_vacuum.test b/test/sql/index/art/vacuum/test_art_vacuum.test_slow similarity index 93% rename from test/sql/index/art/vacuum/test_art_vacuum.test rename to test/sql/index/art/vacuum/test_art_vacuum.test_slow index 34f09d1a6c2..1caf295c1c6 100644 --- a/test/sql/index/art/vacuum/test_art_vacuum.test +++ b/test/sql/index/art/vacuum/test_art_vacuum.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/index/art/vacuum/test_art_vacuum.test +# name: test/sql/index/art/vacuum/test_art_vacuum.test_slow # description: Test vacuuming leaves # group: [vacuum] diff --git a/test/sql/insert/insert_non_order_preserving.test b/test/sql/insert/insert_non_order_preserving.test_slow similarity index 95% rename from test/sql/insert/insert_non_order_preserving.test rename to test/sql/insert/insert_non_order_preserving.test_slow index ec45828761b..ba11b84936a 100644 --- a/test/sql/insert/insert_non_order_preserving.test +++ b/test/sql/insert/insert_non_order_preserving.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/insert/insert_non_order_preserving.test +# name: test/sql/insert/insert_non_order_preserving.test_slow # description: Test parallel non order-preserving insert # group: [insert] diff --git a/test/sql/join/asof/test_asof_join.test b/test/sql/join/asof/test_asof_join.test index 762d57936db..4f8e0ae0123 100644 --- a/test/sql/join/asof/test_asof_join.test +++ b/test/sql/join/asof/test_asof_join.test @@ -37,6 +37,42 @@ FROM trades t ASOF JOIN prices p ---- 2020-01-01 00:00:03 1 42 +# Ignore non-join conditions +query II +SELECT p.ts, e.value +FROM range(0,10) p(ts) ASOF JOIN events0 e +ON 1 = 1 AND p.ts >= e.begin +ORDER BY p.ts ASC +---- +1 0 +2 0 +3 1 +4 1 +5 1 +6 2 +7 2 +8 3 +9 3 + +query II +WITH samples AS ( + SELECT col0 AS starts, col1 AS ends + FROM (VALUES + (5, 9), + (10, 13), + (14, 20), + (21, 23) + ) +) +SELECT + s1.starts as s1_starts, + s2.starts as s2_starts, +FROM samples AS s1 ASOF JOIN samples as s2 ON s2.ends >= (s1.ends - 5) +WHERE s1_starts <> s2_starts; +---- +21 14 +10 5 + # Use an ASOF join inside of a correlated subquery @@ -51,16 +87,7 @@ FROM range(0,10) p(ts) ASOF JOIN events0 e ON p.ts <> e.begin ORDER BY p.ts ASC ---- -Binder Error: Invalid ASOF JOIN comparison - -# Invalid ASOF JOIN condition -statement error -SELECT p.ts, e.value -FROM range(0,10) p(ts) ASOF JOIN events0 e -ON 1 = 1 AND p.ts >= e.begin -ORDER BY p.ts ASC ----- -Binder Error: Invalid ASOF JOIN condition +Binder Error: Missing ASOF JOIN inequality # Missing ASOF JOIN inequality statement error diff --git a/test/sql/join/asof/test_asof_join_pushdown.test b/test/sql/join/asof/test_asof_join_pushdown.test index 49a3f8d9055..ba298378c49 100644 --- a/test/sql/join/asof/test_asof_join_pushdown.test +++ b/test/sql/join/asof/test_asof_join_pushdown.test @@ -43,3 +43,39 @@ ASOF LEFT JOIN ( ---- 0 0 0.0 0.0 1 0 NULL 0.0 + +query II +WITH t as ( + SELECT + t1.col0 AS left_val, + t2.col0 AS right_val, + FROM + (VALUES (0), (5), (10), (15)) AS t1 + ASOF JOIN (VALUES (1), (6), (11), (16)) AS t2 + ON t2.col0 > t1.col0 +) +SELECT * +FROM t +WHERE right_val BETWEEN 3 AND 12 +ORDER BY ALL +---- +5 6 +10 11 + +query II +WITH t as ( + SELECT + t1.col0 AS left_val, + t2.col0 AS right_val, + FROM + (VALUES (0), (5), (10), (15)) AS t1 + ASOF LEFT JOIN (VALUES (1), (6), (11), (16)) AS t2 + ON t2.col0 > t1.col0 +) +SELECT * +FROM t +WHERE right_val BETWEEN 3 AND 12 +ORDER BY ALL +---- +5 6 +10 11 diff --git a/test/sql/join/external/simple_external_join.test_coverage b/test/sql/join/external/simple_external_join.test_coverage index 6a0a5ab3b73..af05c5b506f 100644 --- a/test/sql/join/external/simple_external_join.test_coverage +++ b/test/sql/join/external/simple_external_join.test_coverage @@ -27,7 +27,7 @@ statement ok pragma threads=1 statement ok -pragma memory_limit='75mb' +pragma memory_limit='100mb' query I select count(*) from t1, t2 where i = j diff --git a/test/sql/join/inner/test_join_perfect_hash.test b/test/sql/join/inner/test_join_perfect_hash.test_slow similarity index 98% rename from test/sql/join/inner/test_join_perfect_hash.test rename to test/sql/join/inner/test_join_perfect_hash.test_slow index 02ca8bf83c8..8c2514b75e2 100644 --- a/test/sql/join/inner/test_join_perfect_hash.test +++ b/test/sql/join/inner/test_join_perfect_hash.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/join/inner/test_join_perfect_hash.test +# name: test/sql/join/inner/test_join_perfect_hash.test_slow # description: Test joins that would generate a perfect hashtable # group: [inner] diff --git a/test/sql/join/test_complex_join_expr.test b/test/sql/join/test_complex_join_expr.test index 064d61346cb..fb0df5bd784 100644 --- a/test/sql/join/test_complex_join_expr.test +++ b/test/sql/join/test_complex_join_expr.test @@ -19,7 +19,7 @@ statement ok CREATE TABLE test2 (b INTEGER, c INTEGER); statement ok -INSERT INTO test2 VALUES (1, 2), (3, 0) +INSERT INTO test2 VALUES (1, 2), (3, 0) query IIII SELECT * FROM test JOIN test2 ON test.a+test2.c=test.b+test2.b diff --git a/test/sql/join/test_nested_keys.test b/test/sql/join/test_nested_keys.test index 06596d2ee23..0ec77e2eceb 100644 --- a/test/sql/join/test_nested_keys.test +++ b/test/sql/join/test_nested_keys.test @@ -2,9 +2,6 @@ # description: Test join with nested types for the keys # group: [join] -# FIXME bug in nested shuffle vector handling -require no_vector_verification - statement ok SET default_null_order='nulls_first'; diff --git a/test/sql/join/test_nested_payloads.test b/test/sql/join/test_nested_payloads.test_slow similarity index 99% rename from test/sql/join/test_nested_payloads.test rename to test/sql/join/test_nested_payloads.test_slow index 0be3eeb0213..9d89acec5af 100644 --- a/test/sql/join/test_nested_payloads.test +++ b/test/sql/join/test_nested_payloads.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/join/test_nested_payloads.test +# name: test/sql/join/test_nested_payloads.test_slow # description: Test join with nested types in the payload # group: [join] diff --git a/test/sql/json/issues/issue11804.test b/test/sql/json/issues/issue11804.test new file mode 100644 index 00000000000..014f7ba7460 --- /dev/null +++ b/test/sql/json/issues/issue11804.test @@ -0,0 +1,20 @@ +# name: test/sql/json/issues/issue11804.test +# description: Test issue 11804 - json_type(...) with path does not return "NULL" +# group: [issues] + +require json + +query I +select json_type(JSON 'null') = 'NULL'; +---- +true + +query I +select json_type(JSON '{"a": null}', '/a') = 'NULL'; +---- +true + +query I +select json_type(JSON '{"a": null}', '$.a') = 'NULL'; +---- +true diff --git a/test/sql/json/issues/issue12188.test b/test/sql/json/issues/issue12188.test new file mode 100644 index 00000000000..e1c06a2a036 --- /dev/null +++ b/test/sql/json/issues/issue12188.test @@ -0,0 +1,20 @@ +# name: test/sql/json/issues/issue12188.test +# description: Test issue 12188 - Issue with Parsing NDJSON File in DuckDB: Unexpected Quotation Marks +# group: [issues] + +require parquet + +query II +SELECT typeof(field1), typeof(field2) FROM 'data/parquet-testing/parquet_with_json.parquet' LIMIT 1 +---- +JSON JSON + +require json + +statement ok +COPY (SELECT * FROM read_ndjson('data/json/12188.ndjson', maximum_depth=1)) TO '__TEST_DIR__/my.parquet'; + +query II +SELECT typeof(field1), typeof(field2) FROM '__TEST_DIR__/my.parquet' LIMIT 1 +---- +JSON JSON diff --git a/test/sql/json/scalar/test_json_create.test b/test/sql/json/scalar/test_json_create.test index de69739ded4..0816bdb0001 100644 --- a/test/sql/json/scalar/test_json_create.test +++ b/test/sql/json/scalar/test_json_create.test @@ -317,3 +317,9 @@ SELECT json_array( 99); ---- [-9223372036854775808,9223372036854775807,0,1,-1,0.0,1.0,-1.0,-1e99,2e100,"one","two","three",4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,null,21,22,23,24,25,26,27,28,29,30,31,"abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ",99] + +# test issue 12002 +query I +SELECT CAST((MAP([5, 3, 4], ['a', 'b', 'c']), 2) AS JSON); +---- +{"":{"5":"a","3":"b","4":"c"},"":2} diff --git a/test/sql/json/scalar/test_json_extract.test b/test/sql/json/scalar/test_json_extract.test index 6e13039fb2e..7bb2717919b 100644 --- a/test/sql/json/scalar/test_json_extract.test +++ b/test/sql/json/scalar/test_json_extract.test @@ -314,3 +314,41 @@ query T execute q1('a') ---- 1 + +# test issue 11997 +query I +select json_extract_string(json('{"j[so]n_\"key": 67}'), '$."j[so]n_\"key"'); +---- +67 + +query I +select '{"\"duck\"": 42}'->'$."\"duck\""'; +---- +42 + +query I +select '{"\"du\\ck\"": 42}'->'$."\"du\\ck\""'; +---- +42 + +query I +select '{"\"du\\ck\"": 42}'->'$."\"du\ck\""'; +---- +42 + +query I +select '{"du\\ck": 42}'->'$.du\ck'; +---- +42 + +# characters other than \\ or \" get ignored (for now) +query I +select '{"\"du\nck\"": 42}'->'$."\"du\nck\""'; +---- +NULL + +# need to use chr(10) for \n +query I +select '{"\"du\nck\"": 42}'->('$."\"du' || chr(10) || 'ck\""'); +---- +42 diff --git a/test/sql/json/scalar/test_json_merge_patch.test b/test/sql/json/scalar/test_json_merge_patch.test index d9035297301..863e0ab7686 100644 --- a/test/sql/json/scalar/test_json_merge_patch.test +++ b/test/sql/json/scalar/test_json_merge_patch.test @@ -16,12 +16,12 @@ SELECT json_merge_patch('{"a": 1}', '{"a": 2}') query T SELECT json_merge_patch('{"a": 1}', '{"b": 2}') ---- -{"b":2,"a":1} +{"a":1,"b":2} query T SELECT json_merge_patch('{"a": {"c": 1}}', '{"a": {"d": 2}}') ---- -{"a":{"d":2,"c":1}} +{"a":{"c":1,"d":2}} query T SELECT json_merge_patch('{"a": {"b": 1}}', '{"a": {"b": 2}}') @@ -37,7 +37,7 @@ SELECT JSON_MERGE_PATCH('[1, 2]', '[true, false]'); query T SELECT JSON_MERGE_PATCH('{"name": "x"}', '{"id": 47}'); ---- -{"id":47,"name":"x"} +{"name":"x","id":47} query T SELECT JSON_MERGE_PATCH('1', 'true'); @@ -52,12 +52,12 @@ SELECT JSON_MERGE_PATCH('[1, 2]', '{"id": 47}'); query T SELECT JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }'); ---- -{"a":3,"c":4,"b":2} +{"b":2,"a":3,"c":4} query T SELECT JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }','{ "a": 5, "d":6 }'); ---- -{"a":5,"d":6,"c":4,"b":2} +{"b":2,"c":4,"a":5,"d":6} query T SELECT JSON_MERGE_PATCH('{"a":1, "b":2}', '{"b":null}'); @@ -67,7 +67,7 @@ SELECT JSON_MERGE_PATCH('{"a":1, "b":2}', '{"b":null}'); query T SELECT JSON_MERGE_PATCH('{"a":{"x":1}}', '{"a":{"y":2}}'); ---- -{"a":{"y":2,"x":1}} +{"a":{"x":1,"y":2}} # test NULL behaviour query T @@ -89,12 +89,12 @@ NULL query T select json_merge_patch('{"a":1}', '{"b":2}', '{"c":3}') ---- -{"c":3,"b":2,"a":1} +{"a":1,"b":2,"c":3} query T select json_merge_patch(NULL, '{"b":2}', '{"c":3}') ---- -{"c":3,"b":2} +{"b":2,"c":3} query T select json_merge_patch('{"a":1}', NULL, '{"c":3}') diff --git a/test/sql/json/scalar/test_json_structure.test b/test/sql/json/scalar/test_json_structure.test index 9997f8e88d7..9f899a77e91 100644 --- a/test/sql/json/scalar/test_json_structure.test +++ b/test/sql/json/scalar/test_json_structure.test @@ -152,10 +152,11 @@ select json_structure('[[1], {"a": 1}]') ---- ["JSON"] -# duplicate key -statement error +# duplicate key, used to throw an error, now the error is ignored +query I select json_structure('{"a": 42, "a": 7}') ---- +{"a":"UBIGINT"} # from a table statement ok @@ -177,3 +178,9 @@ select json_structure(j) from test NULL {"family":"NULL","species":"NULL","hair":"NULL","coolness":"NULL"} {"family":"VARCHAR","species":["VARCHAR"],"hair":"BOOLEAN","coolness":"UBIGINT"} + +# issue 11886 +query I +select json_structure('{"a": 1, "A": 1}'); +---- +{"a":"UBIGINT","A":"UBIGINT"} diff --git a/test/sql/json/table/read_json_auto.test_slow b/test/sql/json/table/read_json_auto.test_slow index 09c0a8063f0..e4e404dd0e7 100644 --- a/test/sql/json/table/read_json_auto.test_slow +++ b/test/sql/json/table/read_json_auto.test_slow @@ -153,15 +153,15 @@ select * from read_json_auto('data/json/different_schemas.ndjson', sample_size=- 4 NULL 5 Raising Arizona -# if we require fields to appear in all objects by setting field_appearance_threshold=1, we default to JSON +# if we require fields to appear in all objects by setting field_appearance_threshold=1, we default to MAP query I select * from read_json_auto('data/json/different_schemas.ndjson', field_appearance_threshold=1) ---- -{"id":1,"name":"O Brother, Where Art Thou?"} -{"id":2} -{"id":3,"name":"The Firm"} -{"id":4} -{"id":5,"name":"Raising Arizona"} +{id=1, name="O Brother, Where Art Thou?"} +{id=2} +{id=3, name="The Firm"} +{id=4} +{id=5, name="Raising Arizona"} # if we set it to 0.5 it should work already since "name" appears in 3/5 objects, which is greater than 0.5 query II @@ -221,6 +221,95 @@ select * from read_json_auto(['data/json/empty_array.json', 'data/json/example_n 4 Broadcast News 5 Raising Arizona +# Simple map inference with default threshold +query T +select distinct typeof(a) from read_json_auto('data/json/simple_map.jsonl') +---- +MAP(VARCHAR, BIGINT) + +# Test setting map_inference_threshold high +query T +select distinct typeof(a) from read_json_auto('data/json/simple_map.jsonl', map_inference_threshold=1000) +---- +MAP(VARCHAR, BIGINT) + +# Map inference can be disabled +query T +select distinct typeof(a) from read_json_auto('data/json/simple_map.jsonl', map_inference_threshold=-1, field_appearance_threshold=0) +---- +STRUCT("1" JSON, "2" BIGINT, "3" BIGINT, "4" BIGINT, "5" BIGINT, "6" BIGINT, "7" BIGINT, "8" BIGINT, "9" BIGINT, "10" BIGINT, "11" BIGINT, "12" BIGINT, "13" BIGINT, "14" BIGINT, "15" BIGINT, "16" JSON, "17" BIGINT, "18" BIGINT, "19" BIGINT, "20" BIGINT, "21" BIGINT, "22" BIGINT, "23" BIGINT, "24" BIGINT, "25" BIGINT, "26" BIGINT, "27" BIGINT, "28" BIGINT, "29" BIGINT, "30" BIGINT, "31" BIGINT, "32" BIGINT, "33" BIGINT, "34" BIGINT, "35" BIGINT, "36" BIGINT, "37" BIGINT, "38" BIGINT, "39" BIGINT, "40" BIGINT, "41" BIGINT, "42" BIGINT, "43" BIGINT, "44" BIGINT, "45" BIGINT, "46" BIGINT, "47" BIGINT, "48" BIGINT, "49" BIGINT, "50" BIGINT, "51" BIGINT, "52" BIGINT, "53" BIGINT, "54" BIGINT, "55" BIGINT, "56" BIGINT, "57" BIGINT, "58" BIGINT, "59" BIGINT, "60" BIGINT, "61" BIGINT, "62" BIGINT, "63" BIGINT, "64" BIGINT, "65" BIGINT, "66" BIGINT, "67" BIGINT, "68" BIGINT, "69" BIGINT, "70" BIGINT, "71" BIGINT, "72" BIGINT, "73" BIGINT, "74" BIGINT, "75" BIGINT, "76" BIGINT, "77" BIGINT, "78" BIGINT, "79" BIGINT, "80" BIGINT, "81" BIGINT, "82" BIGINT, "83" BIGINT, "84" BIGINT, "85" BIGINT, "86" BIGINT, "87" BIGINT, "88" BIGINT, "89" BIGINT, "90" BIGINT, "91" BIGINT, "92" BIGINT, "93" BIGINT, "94" BIGINT, "95" BIGINT, "96" BIGINT, "97" BIGINT, "98" BIGINT, "99" BIGINT, "100" BIGINT) + +# Map inference with max_depth works as expected +query T +select distinct typeof(a) from read_json_auto('data/json/simple_map.jsonl', maximum_depth=2) +---- +MAP(VARCHAR, JSON) + +query T +select distinct typeof(a) from read_json_auto('data/json/simple_map.jsonl', maximum_depth=1) +---- +JSON + +# Map where all values are null +query T +select distinct typeof(a) from read_json_auto('data/json/map_of_nulls.jsonl') +---- +MAP(VARCHAR, JSON) + +# Map type can be inferred at the top level +query T +select distinct typeof(json) from read_json_auto('data/json/top_level_map.jsonl') +---- +MAP(VARCHAR, BIGINT) + +# Map type can be inferred for struct value type +query T +select distinct typeof(a) from read_json_auto('data/json/map_of_structs.jsonl') +---- +MAP(VARCHAR, STRUCT(b BIGINT)) + +# Map 80% similarity check works +query T +select distinct typeof(a) from read_json_auto('data/json/map_50_50.jsonl', map_inference_threshold=10) +---- +STRUCT(s1 STRUCT(f1 BIGINT[]), s2 STRUCT(f2 BIGINT[]), s3 STRUCT(f1 BIGINT[]), s4 STRUCT(f2 BIGINT[]), s5 STRUCT(f1 BIGINT[]), s6 STRUCT(f2 BIGINT[]), s7 STRUCT(f1 BIGINT[]), s8 STRUCT(f2 BIGINT[]), s9 STRUCT(f1 BIGINT[]), s10 STRUCT(f2 BIGINT[])) + +# Map of maps +query T +select distinct typeof(a) from read_json_auto('data/json/map_of_map.jsonl', map_inference_threshold=10) +---- +MAP(VARCHAR, MAP(VARCHAR, BIGINT)) + +# All NULL types get converted to JSON if we do map inference +query T +select distinct typeof(a) from read_json_auto('data/json/map_of_struct_with_nulls.jsonl', map_inference_threshold=10) +---- +MAP(VARCHAR, STRUCT(a JSON[])) + +# Candidate types are properly handled for map inference +query I +SELECT distinct typeof(a) FROM read_json_auto('data/json/map_of_dates.jsonl') +---- +MAP(VARCHAR, DATE) + +# Mixed candidate types are also handled +query I +SELECT distinct typeof(a) FROM read_json_auto('data/json/map_of_mixed_date_timestamps.jsonl') +---- +MAP(VARCHAR, VARCHAR) + +# Incompatible types are handled correctly +query T +select distinct typeof(a) from read_json_auto('data/json/map_incompatible.jsonl', map_inference_threshold=10) +---- +STRUCT(s1 STRUCT("1" JSON), s2 STRUCT("1" MAP(VARCHAR, JSON)), s3 STRUCT("1" VARCHAR), s4 STRUCT("1" BIGINT[]), s5 STRUCT("1" BIGINT), s6 STRUCT("1" VARCHAR), s7 STRUCT("1" BIGINT[]), s8 STRUCT("1" BIGINT), s9 STRUCT("1" VARCHAR), s10 STRUCT("1" BIGINT[])) + +# Can't set map_inference_threshold to a negative value (except -1) +statement error +select * from read_json_auto('data/json/simple_map.jsonl', map_inference_threshold=-10) +---- +Binder Error: read_json_auto "map_inference_threshold" parameter must be 0 or positive, or -1 to disable map inference for consistent objects. + # if we only sample the first file, we default to a single JSON column query I select * from read_json_auto(['data/json/empty_array.json', 'data/json/example_n.ndjson'], maximum_sample_files=1); diff --git a/test/sql/json/test_json_empty_object.test b/test/sql/json/test_json_empty_object.test index 775851f214b..7d8a3abc43a 100644 --- a/test/sql/json/test_json_empty_object.test +++ b/test/sql/json/test_json_empty_object.test @@ -26,7 +26,7 @@ copy (select '{"a": {}}') to '__TEST_DIR__/my.json' (FORMAT CSV, quote '', heade query T select typeof(a) from '__TEST_DIR__/my.json' ---- -JSON +MAP(VARCHAR, JSON) # can't force it to have an empty struct statement error @@ -44,8 +44,8 @@ CREATE OR REPLACE TABLE tbl AS SELECT * FROM read_ndjson_auto('__TEST_DIR__/data query II select typeof(c1), typeof(c2) from tbl; ---- -VARCHAR STRUCT(k1 VARCHAR, k2 JSON) -VARCHAR STRUCT(k1 VARCHAR, k2 JSON) +VARCHAR STRUCT(k1 VARCHAR, k2 MAP(VARCHAR, JSON)) +VARCHAR STRUCT(k1 VARCHAR, k2 MAP(VARCHAR, JSON)) require parquet diff --git a/test/sql/optimizer/expression/test_timestamp_offset.test b/test/sql/optimizer/expression/test_timestamp_offset.test new file mode 100644 index 00000000000..d2adaee0d88 --- /dev/null +++ b/test/sql/optimizer/expression/test_timestamp_offset.test @@ -0,0 +1,50 @@ +# name: test/sql/optimizer/expression/test_timestamp_offset.test +# description: Test pushdown of varchars converted to timestamps +# group: [expression] + +statement ok +PRAGMA enable_verification + +statement ok +create or replace table table1 ( + timestamp_str varchar +); + +statement ok +insert into table1 values ('2024-05-03 01:00:00'), ('2024-05-03 01:00:02'); + +query II +select timestamp_str, cast(timestamp_str as timestamp) +from table1 +where cast(timestamp_str as timestamp) > cast('2024-05-03 01:00:00' as timestamp); +---- +2024-05-03 01:00:02 2024-05-03 01:00:02 + +statement ok +truncate table table1; + +statement ok +insert into table1 values ('2024-05-03T01:00:00+00:00'), ('2024-05-03T01:00:02+00:00'); + +query II +select timestamp_str, cast(timestamp_str as timestamp) +from table1 +where cast(timestamp_str as timestamp) > cast('2024-05-03 01:00:00' as timestamp); +---- +2024-05-03T01:00:02+00:00 2024-05-03 01:00:02 + +query II +select timestamp_str, cast(timestamp_str as timestamp) +from table1 +where cast(timestamp_str as timestamp) > cast('2024-05-03T01:00:00+00:00' as timestamp); +---- +2024-05-03T01:00:02+00:00 2024-05-03 01:00:02 + +query II +select * from ( + select timestamp_str, cast(timestamp_str as timestamp) as timestamp_column + from table1 +) +where timestamp_column > cast('2024-05-03 01:00:00' as timestamp); +---- +2024-05-03T01:00:02+00:00 2024-05-03 01:00:02 diff --git a/test/sql/order/issue_11936.test b/test/sql/order/issue_11936.test new file mode 100644 index 00000000000..028ac5ba410 --- /dev/null +++ b/test/sql/order/issue_11936.test @@ -0,0 +1,21 @@ +# name: test/sql/order/issue_11936.test +# description: Test order nested list +# group: [order] + +statement ok +PRAGMA enable_verification + +statement ok +CREATE TABLE test(col1 INT, col2 INT2[][][][][][]); + +statement ok +INSERT INTO test VALUES(1000000000, null), (1000000001, [[[[[[]]]]]]), (null, [[[[[[]]]]]]), (null, [[[[[[]]]]]]), (1, [[[[[[]]]]]]); + +query II +SELECT col1, col2 FROM test ORDER BY col1 NULLS LAST, col2; +---- +1 [[[[[[]]]]]] +1000000000 NULL +1000000001 [[[[[[]]]]]] +NULL [[[[[[]]]]]] +NULL [[[[[[]]]]]] diff --git a/test/sql/outofcore/leftover_temp_files_issue_6420.test_slow b/test/sql/outofcore/leftover_temp_files_issue_6420.test_slow index 1f3ec2a01bb..1fe121f02f8 100644 --- a/test/sql/outofcore/leftover_temp_files_issue_6420.test_slow +++ b/test/sql/outofcore/leftover_temp_files_issue_6420.test_slow @@ -1,11 +1,15 @@ # name: test/sql/outofcore/leftover_temp_files_issue_6420.test_slow -# description: Issue #6420: Large joins in persistent databases have left over temporary directory +# description: Issue #6420: Large joins in persistent databases have a leftover temporary directory. # group: [outofcore] -load __TEST_DIR__/leftover_temp_files.db +# FIXME: commenting out load __TEST_DIR__/leftover_temp_files.db passes the failing line. +# FIXME: This possibly indicates that we're writing the temporary table to the database file? +require block_size 262144 require tpch +load __TEST_DIR__/leftover_temp_files.db + statement ok SET threads=8 @@ -23,7 +27,7 @@ CREATE TABLE lineitem2 AS FROM lineitem1 # creating and dropping a temp table should not leave temp files statement ok -CREATE OR REPLACE TEMPORARY TABLE ans as select l1.* from lineitem1 l1; +CREATE OR REPLACE TEMPORARY TABLE ans AS SELECT l1.* FROM lineitem1 l1; query I SELECT COUNT(*) > 0 FROM duckdb_temporary_files() diff --git a/test/sql/parallelism/interquery/concurrent_append_metadata_queries.test_slow b/test/sql/parallelism/interquery/concurrent_append_metadata_queries.test_slow new file mode 100644 index 00000000000..b5c9d55fd86 --- /dev/null +++ b/test/sql/parallelism/interquery/concurrent_append_metadata_queries.test_slow @@ -0,0 +1,92 @@ +# name: test/sql/parallelism/interquery/concurrent_append_metadata_queries.test_slow +# description: Run metadata queries while appending/checkpointing +# group: [interquery] + +statement ok +CREATE TABLE integers(i INTEGER) + +statement ok +CREATE INDEX i_index ON integers(i); + +statement ok +CREATE VIEW v1 AS FROM integers; + +statement ok +INSERT INTO integers SELECT * FROM range(10000); + +concurrentloop threadid 0 20 + +loop i 0 20 + +onlyif threadid=0 +statement ok +CREATE SCHEMA s1; + +onlyif threadid=0 +statement ok +CREATE TABLE s1.tbl(i INTEGER); + +onlyif threadid=0 +statement ok +CREATE INDEX i_index ON s1.tbl(i); + +onlyif threadid=0 +statement ok +INSERT INTO s1.tbl FROM range(10000); + +onlyif threadid=0 +statement ok +INSERT INTO integers SELECT * FROM range(10000 + ${i} * 100, 10100 + ${i} * 100); + +onlyif threadid=0 +statement ok +DROP TABLE s1.tbl; + +onlyif threadid=0 +statement ok +DROP SCHEMA s1; + +endloop + +loop i 0 100 + +skipif threadid=0 +statement ok +FROM duckdb_tables(); + +skipif threadid=0 +statement ok +FROM duckdb_indexes(); + +skipif threadid=0 +statement ok +FROM duckdb_schemas(); + +skipif threadid=0 +statement ok +FROM pragma_metadata_info(); + +skipif threadid=0 +statement ok +FROM pragma_storage_info('integers'); + +skipif threadid=0 +statement ok +from pragma_table_info('integers'); + +skipif threadid=0 +statement ok +from duckdb_dependencies(); + +skipif threadid=0 +statement ok +from duckdb_temporary_files(); + +endloop + +endloop + +query II +SELECT COUNT(*), SUM(i) FROM integers +---- +12000 71994000 diff --git a/test/sql/parallelism/interquery/concurrent_append_transactions_indexes.test_slow b/test/sql/parallelism/interquery/concurrent_append_transactions_indexes.test_slow index 8d66f78dbd2..af3fd33ea53 100644 --- a/test/sql/parallelism/interquery/concurrent_append_transactions_indexes.test_slow +++ b/test/sql/parallelism/interquery/concurrent_append_transactions_indexes.test_slow @@ -2,10 +2,6 @@ # description: Test concurrent appends and transaction isolation # group: [interquery] -# FIXME: this test causes a data race in the statistics code -# FIXME: reproducible by running this test with THREADSAN=1 make reldebug -require nothreadsan - statement ok CREATE TABLE integers(i INTEGER PRIMARY KEY) diff --git a/test/sql/parallelism/interquery/concurrent_force_checkpoint.test b/test/sql/parallelism/interquery/concurrent_force_checkpoint.test new file mode 100644 index 00000000000..cf81e99f24f --- /dev/null +++ b/test/sql/parallelism/interquery/concurrent_force_checkpoint.test @@ -0,0 +1,72 @@ +# name: test/sql/parallelism/interquery/concurrent_force_checkpoint.test +# description: Test concurrent force checkpoints with a mix of operations +# group: [interquery] + +statement ok +CREATE TABLE integers(i INTEGER) + +statement ok +INSERT INTO integers SELECT * FROM range(10000); + +concurrentloop threadid 0 21 + +# thread 1 is appending +loop i 0 20 + +onlyif threadid=0 +statement ok +INSERT INTO integers SELECT * FROM range(10000 + ${i} * 100, 10100 + ${i} * 100); + +endloop + +# thread 1-10 are deleting rows between 0..1000 +loop i 0 100 + +onlyif threadid>=1&&threadid<=10 +statement ok +DELETE FROM integers WHERE i=(${threadid}-1)*100+${i} + +endloop + +# thread 11-15 are updating rows between 1000..2000 +loop i 0 100 + +onlyif threadid>=11&&threadid<=15 +statement ok +UPDATE integers SET i=100000+i WHERE i=(${threadid}-1)*100+${i} + +endloop + +# thread 16-20 are reading +loop i 0 100 + +onlyif threadid>=16&&threadid<20 +statement ok +BEGIN TRANSACTION READ ONLY + +onlyif threadid>=16&&threadid<20 +statement ok +SELECT COUNT(*), SUM(i) FROM integers; + +onlyif threadid>=16&&threadid<20 +statement ok +COMMIT + +endloop + +# thread 21 is force checkpointing +loop i 0 20 + +onlyif threadid==20 +statement ok +FORCE CHECKPOINT + +endloop + +endloop + +query II +SELECT COUNT(*), SUM(i) FROM integers +---- +11000 121494500 + diff --git a/test/sql/parallelism/interquery/concurrent_index_scans_while_appending.test b/test/sql/parallelism/interquery/concurrent_index_scans_while_appending.test new file mode 100644 index 00000000000..672fc5b21b3 --- /dev/null +++ b/test/sql/parallelism/interquery/concurrent_index_scans_while_appending.test @@ -0,0 +1,34 @@ +# name: test/sql/parallelism/interquery/concurrent_index_scans_while_appending.test +# description: Test concurrent index scans while appending +# group: [interquery] + +statement ok +CREATE TABLE integers(i INTEGER PRIMARY KEY) + +statement ok +INSERT INTO integers SELECT * FROM range(10000); + +concurrentloop threadid 0 20 + +loop i 0 20 + +onlyif threadid=0 +statement ok +INSERT INTO integers SELECT * FROM range(10000 + ${i} * 100, 10100 + ${i} * 100); + +endloop + +loop i 0 100 + +skipif threadid=0 +statement ok +SELECT * FROM integers WHERE i=${i} * (${threadid} * 300); + +endloop + +endloop + +query II +SELECT COUNT(*), SUM(i) FROM integers +---- +12000 71994000 diff --git a/test/sql/parallelism/interquery/concurrent_mix_operations.test_slow b/test/sql/parallelism/interquery/concurrent_mix_operations.test_slow new file mode 100644 index 00000000000..b25903fc90a --- /dev/null +++ b/test/sql/parallelism/interquery/concurrent_mix_operations.test_slow @@ -0,0 +1,55 @@ +# name: test/sql/parallelism/interquery/concurrent_mix_operations.test_slow +# description: Test concurrent mix of operations +# group: [interquery] + +statement ok +CREATE TABLE integers(i INTEGER) + +statement ok +INSERT INTO integers SELECT * FROM range(10000); + +concurrentloop threadid 0 20 + +# thread 1 is appending +loop i 0 20 + +onlyif threadid=0 +statement ok +INSERT INTO integers SELECT * FROM range(10000 + ${i} * 100, 10100 + ${i} * 100); + +endloop + +# thread 1-10 are deleting rows between 0..1000 +loop i 0 100 + +onlyif threadid>=1&&threadid<=10 +statement ok +DELETE FROM integers WHERE i=(${threadid}-1)*100+${i} + +endloop + +# thread 11-15 are updating rows between 1000..2000 +loop i 0 100 + +onlyif threadid>=11&&threadid<=15 +statement ok +UPDATE integers SET i=100000+i WHERE i=(${threadid}-1)*100+${i} + +endloop + +# thread 16-20 are reading +loop i 0 100 + +onlyif threadid>=16 +statement ok +SELECT COUNT(*), SUM(i) FROM integers; + +endloop + +endloop + +query II +SELECT COUNT(*), SUM(i) FROM integers +---- +11000 121494500 + diff --git a/test/sql/parallelism/interquery/concurrent_reads_append_list.test_slow b/test/sql/parallelism/interquery/concurrent_reads_append_list.test_slow new file mode 100644 index 00000000000..f1a19eb1800 --- /dev/null +++ b/test/sql/parallelism/interquery/concurrent_reads_append_list.test_slow @@ -0,0 +1,40 @@ +# name: test/sql/parallelism/interquery/concurrent_reads_append_list.test_slow +# description: Test concurrent reads while appending +# group: [interquery] + +statement ok +CREATE TABLE lists(l INTEGER[]) + +statement ok +INSERT INTO lists SELECT [i, i + 1, i + 2] FROM range(10000) t(i); + +concurrentloop threadid 0 20 + +loop i 0 20 + +onlyif threadid=0 +statement ok +INSERT INTO lists SELECT [i, i + 1, i + 2] FROM range(100) t(i); + +endloop + +loop i 0 200 + +skipif threadid=0 +query II +SELECT COUNT(*) >= 30000 AND COUNT(*) <= 36000 + , SUM(i) >= 150015000 AND SUM(i) <= 150318000 +FROM +(SELECT UNNEST(l) AS i FROM lists); +---- +true true + +endloop + +endloop + +query II +SELECT COUNT(*), SUM(i) FROM (SELECT UNNEST(l) AS i FROM lists) +---- +36000 150318000 + diff --git a/test/sql/parallelism/interquery/concurrent_reads_while_altering.test b/test/sql/parallelism/interquery/concurrent_reads_while_altering.test new file mode 100644 index 00000000000..953bcfc38c1 --- /dev/null +++ b/test/sql/parallelism/interquery/concurrent_reads_while_altering.test @@ -0,0 +1,47 @@ +# name: test/sql/parallelism/interquery/concurrent_reads_while_altering.test +# description: Test concurrent reads while altering +# group: [interquery] + +statement ok +CREATE OR REPLACE TABLE integers(i INTEGER) + +statement ok +INSERT INTO integers SELECT * FROM range(10000); + +concurrentloop threadid 0 20 + +loop i 0 20 + +onlyif threadid=0 +statement ok +BEGIN; + +onlyif threadid=0 +statement ok +ALTER TABLE integers ADD COLUMN newcol_${i} INTEGER + +onlyif threadid=0 +statement ok +INSERT INTO integers (i) SELECT * FROM range(10000 + ${i} * 100, 10100 + ${i} * 100); + +onlyif threadid=0 +statement ok +COMMIT + +endloop + +loop i 0 20 + +skipif threadid=0 +statement ok +SELECT * FROM integers + +endloop + +endloop + +query II +SELECT COUNT(*), SUM(i) FROM integers +---- +12000 71994000 + diff --git a/test/sql/parallelism/interquery/concurrent_reads_while_appending.test_slow b/test/sql/parallelism/interquery/concurrent_reads_while_appending.test_slow new file mode 100644 index 00000000000..f96006dda05 --- /dev/null +++ b/test/sql/parallelism/interquery/concurrent_reads_while_appending.test_slow @@ -0,0 +1,38 @@ +# name: test/sql/parallelism/interquery/concurrent_reads_while_appending.test_slow +# description: Test concurrent reads while appending +# group: [interquery] + +statement ok +CREATE TABLE integers(i INTEGER) + +statement ok +INSERT INTO integers SELECT * FROM range(10000); + +concurrentloop threadid 0 20 + +loop i 0 20 + +onlyif threadid=0 +statement ok +INSERT INTO integers SELECT * FROM range(100); + +endloop + +loop i 0 200 + +skipif threadid=0 +query II +SELECT COUNT(*)>=10000 AND COUNT(*)<=12000, + SUM(i)>= 49995000 AND SUM(i) <= 50094000 FROM integers; +---- +true true + +endloop + +endloop + +query II +SELECT COUNT(*), SUM(i) FROM integers +---- +12000 50094000 + diff --git a/test/sql/parallelism/interquery/concurrent_reads_while_appending_nulls.test_slow b/test/sql/parallelism/interquery/concurrent_reads_while_appending_nulls.test_slow new file mode 100644 index 00000000000..13d7660707b --- /dev/null +++ b/test/sql/parallelism/interquery/concurrent_reads_while_appending_nulls.test_slow @@ -0,0 +1,39 @@ +# name: test/sql/parallelism/interquery/concurrent_reads_while_appending_nulls.test_slow +# description: Test concurrent reads while appending NULL values +# group: [interquery] + +statement ok +CREATE TABLE integers(i INTEGER) + +statement ok +INSERT INTO integers SELECT * FROM range(10000); + +concurrentloop threadid 0 20 + +loop i 0 20 + +onlyif threadid=0 +statement ok +INSERT INTO integers SELECT CASE WHEN i%2=0 THEN NULL ELSE i END FROM range(100) t(i); + +endloop + +loop i 0 200 + +skipif threadid=0 +query III +SELECT COUNT(*)>=10000 AND COUNT(*)<=12000, + COUNT(i) >= 10000 AND COUNT(i) <= 11000, + SUM(i)>= 49995000 AND SUM(i) <= 50094000 FROM integers; +---- +true true true + +endloop + +endloop + +query III +SELECT COUNT(*), COUNT(i), SUM(i) FROM integers +---- +12000 11000 50045000 + diff --git a/test/sql/parallelism/interquery/concurrent_reads_while_renaming.test b/test/sql/parallelism/interquery/concurrent_reads_while_renaming.test new file mode 100644 index 00000000000..28c94ec0305 --- /dev/null +++ b/test/sql/parallelism/interquery/concurrent_reads_while_renaming.test @@ -0,0 +1,40 @@ +# name: test/sql/parallelism/interquery/concurrent_reads_while_renaming.test +# description: Test concurrent reads while renaming +# group: [interquery] + +statement ok +CREATE OR REPLACE TABLE integers(i INTEGER) + +statement ok +INSERT INTO integers SELECT * FROM range(10000); + +concurrentloop threadid 0 20 + +loop i 0 20 + +onlyif threadid=0 +statement ok +ALTER TABLE integers RENAME TO integers_${i} + +onlyif threadid=0 +statement ok +ALTER TABLE integers_${i} RENAME TO integers + +endloop + +loop i 0 20 + +skipif threadid=0 +statement maybe +SELECT * FROM integers +---- +does not exist + +endloop + +endloop + +query II +SELECT COUNT(*), SUM(i) FROM integers +---- +10000 49995000 diff --git a/test/sql/parallelism/interquery/concurrent_reads_while_updating.test_slow b/test/sql/parallelism/interquery/concurrent_reads_while_updating.test_slow new file mode 100644 index 00000000000..972ca438401 --- /dev/null +++ b/test/sql/parallelism/interquery/concurrent_reads_while_updating.test_slow @@ -0,0 +1,38 @@ +# name: test/sql/parallelism/interquery/concurrent_reads_while_updating.test_slow +# description: Test concurrent reads while updating +# group: [interquery] + +statement ok +CREATE TABLE integers(i INTEGER) + +statement ok +INSERT INTO integers SELECT * FROM range(10000); + +concurrentloop threadid 0 20 + +loop i 0 20 + +onlyif threadid=0 +statement ok +UPDATE integers SET i=i+1; + +endloop + +loop i 0 200 + +skipif threadid=0 +query II +SELECT COUNT(*)==10000, + SUM(i)>= 49995000 AND SUM(i) <= 50195000 FROM integers; +---- +true true + +endloop + +endloop + +query II +SELECT COUNT(*), SUM(i) FROM integers +---- +10000 50195000 + diff --git a/test/sql/parallelism/interquery/test_concurrent_index.cpp b/test/sql/parallelism/interquery/test_concurrent_index.cpp index 5e4896e0b37..a98793243fd 100644 --- a/test/sql/parallelism/interquery/test_concurrent_index.cpp +++ b/test/sql/parallelism/interquery/test_concurrent_index.cpp @@ -268,36 +268,44 @@ TEST_CASE("Mix updates and inserts on PRIMARY KEY", "[index][.]") { } static void TransactionalAppendToPK(DuckDB *db, idx_t thread_idx) { + duckdb::unique_ptr result; Connection con(*db); - REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION")); + result = con.Query("BEGIN TRANSACTION"); + if (result->HasError()) { + FAIL(result->GetError()); + } // get the initial count - auto result = con.Query("SELECT COUNT(*) FROM integers WHERE i >= 0"); - REQUIRE_NO_FAIL(*result); + result = con.Query("SELECT COUNT(*) FROM integers WHERE i >= 0"); + if (result->HasError()) { + FAIL(result->GetError()); + } auto chunk = result->Fetch(); auto initial_count = chunk->GetValue(0, 0).GetValue(); for (idx_t i = 0; i < 50; i++) { - auto loop_result = con.Query("INSERT INTO integers VALUES ($1)", (int32_t)(thread_idx * 1000 + i)); - REQUIRE_NO_FAIL(*result); + result = con.Query("INSERT INTO integers VALUES ($1)", (int32_t)(thread_idx * 1000 + i)); + if (result->HasError()) { + FAIL(result->GetError()); + } // check the count - loop_result = con.Query("SELECT COUNT(*), COUNT(DISTINCT i) FROM integers WHERE i >= 0"); - REQUIRE(CHECK_COLUMN(loop_result, 0, {Value::INTEGER(initial_count + i + 1)})); + result = con.Query("SELECT COUNT(*), COUNT(DISTINCT i) FROM integers WHERE i >= 0"); + if (!CHECK_COLUMN(result, 0, {Value::INTEGER(initial_count + i + 1)})) { + FAIL("Incorrect result in TransactionalAppendToPK"); + } } - REQUIRE_NO_FAIL(con.Query("COMMIT")); + result = con.Query("COMMIT"); + if (result->HasError()) { + FAIL(result->GetError()); + } } TEST_CASE("Parallel transactional appends to indexed table", "[index][.]") { - - // FIXME: this test causes a data race in the statistics code - // FIXME: reproducible by running this test with THREADSAN=1 make reldebug - -#ifndef DUCKDB_THREAD_SANITIZER DuckDB db(nullptr); Connection con(db); REQUIRE_NO_FAIL(con.Query("SET immediate_transaction_mode=true")); @@ -320,7 +328,6 @@ TEST_CASE("Parallel transactional appends to indexed table", "[index][.]") { REQUIRE_NO_FAIL(*result); REQUIRE(CHECK_COLUMN(result, 0, {Value::BIGINT(idx_t(CONCURRENT_INDEX_THREAD_COUNT * 50))})); REQUIRE(CHECK_COLUMN(result, 1, {Value::BIGINT(idx_t(CONCURRENT_INDEX_THREAD_COUNT * 50))})); -#endif } static void JoinIntegers(Connection *con) { diff --git a/test/sql/parallelism/interquery/tpch_concurrent_operations.test_slow b/test/sql/parallelism/interquery/tpch_concurrent_operations.test_slow new file mode 100644 index 00000000000..bb70f029655 --- /dev/null +++ b/test/sql/parallelism/interquery/tpch_concurrent_operations.test_slow @@ -0,0 +1,63 @@ +# name: test/sql/parallelism/interquery/tpch_concurrent_operations.test_slow +# description: Run TPC-H queries while doing concurrent operations +# group: [interquery] + +require tpch + +statement ok +CALL dbgen(sf=1); + +concurrentloop threadid 0 5 + +loop i 0 20 + +onlyif threadid=0 +query I +INSERT INTO lineitem SELECT * REPLACE ('this is an extra row' AS l_comment) FROM lineitem USING SAMPLE (1000); +---- +1000 + +onlyif threadid=0 +query I +UPDATE lineitem SET l_orderkey = l_orderkey + 100 WHERE l_comment = 'this is an extra row' +---- +1000 + +onlyif threadid=0 +query I +DELETE FROM lineitem WHERE l_comment = 'this is an extra row' +---- +1000 + +endloop + +loop i 0 30 + +skipif threadid=0 +statement ok +PRAGMA tpch((${threadid} + ${i}) % 22 + 1) + +endloop + +endloop + +# verify that all TPC-H results are correct after this + +loop i 1 9 + +query I +PRAGMA tpch(${i}) +---- +:extension/tpch/dbgen/answers/sf1/q0${i}.csv + +endloop + +loop i 10 23 + +query I +PRAGMA tpch(${i}) +---- +:extension/tpch/dbgen/answers/sf1/q${i}.csv + +endloop + diff --git a/test/sql/parallelism/intraquery/test_aggregations_parallelism.test_slow b/test/sql/parallelism/intraquery/test_aggregations_parallelism.test_slow index e6bc05b297f..fbd93fa6264 100644 --- a/test/sql/parallelism/intraquery/test_aggregations_parallelism.test_slow +++ b/test/sql/parallelism/intraquery/test_aggregations_parallelism.test_slow @@ -90,8 +90,8 @@ from bool; query II rowsort select approx_count_distinct(a), approx_count_distinct(b) from t group by b%2; ---- -49874 5 -51026 5 +41234 5 +50630 5 query II select arg_min(b,a), arg_max(b,a) from t; diff --git a/test/sql/parser/dollar_quotes_internal_issue2224.test b/test/sql/parser/dollar_quotes_internal_issue2224.test new file mode 100644 index 00000000000..30bf93d7eb6 --- /dev/null +++ b/test/sql/parser/dollar_quotes_internal_issue2224.test @@ -0,0 +1,81 @@ +# name: test/sql/parser/dollar_quotes_internal_issue2224.test +# description: Unexpected implicit conversion of string literal with full-width space +# group: [parser] + +# we replace unicode spaces in query strings, except if they are quoted +# internal issue 2224 found that this doesn't work properly for double-dollar quoting +# lhs is regular space, rhs is a wider unicode space, so this should be false +#query I +#select $$ $$ = $$ $$; +#---- +#false + +query I +select $tag$ $tag$ = $tag$ $tag$; +---- +false + +# worked properly before for these quotes +query I +select ' ' = ' '; +---- +false + +# just checking if parsing didn't break by fixing the dollar thing +query I +select $$$$ = ''; +---- +true + +query I +select $tag$$tag$ = ''; +---- +true + +query I +select '' = $$$$; +---- +true + +query I +select '' = $tag$$tag$; +---- +true + +query I +select $$ $$ = $$ $$ or ' ' = ' '; +---- +false + +query I +select $tag$ $tag$ = $tag$ $tag$ or ' ' = ' '; +---- +false + +query I +select ' ' = ' ' or $$ $$ = $$ $$; +---- +false + +query I +select ' ' = ' ' or $tag$ $tag$ = $tag$ $tag$; +---- +false + +# we can nest dollars if tags don't match +query I +select $tag$ $duck$ $tag$ = $tag$ $duck$ $tag$; +---- +false + +# of course we have to try this too +query I +select $🦆$du ck$🦆$ = $🦆$du ck$🦆$; +---- +false + +# and some more unicode +query I +select $ü$x x$ü$ = $ü$x x$ü$; +---- +false diff --git a/test/sql/parser/star_expression.test b/test/sql/parser/star_expression.test index c0eb9f3bb18..67088ec0bf3 100644 --- a/test/sql/parser/star_expression.test +++ b/test/sql/parser/star_expression.test @@ -64,6 +64,6 @@ VALUES (*) not supported statement error -FROM range(*, *); +FROM read_csv(*, *); ---- not supported diff --git a/test/sql/parser/test_columns_lists.test b/test/sql/parser/test_columns_lists.test index 9b3c9795dc2..a95e253b445 100644 --- a/test/sql/parser/test_columns_lists.test +++ b/test/sql/parser/test_columns_lists.test @@ -72,6 +72,11 @@ SELECT COLUMNS([x for x in COLUMNS(*)]) FROM integers ---- COLUMNS expression is not allowed inside another COLUMNS expression +statement error +SELECT COLUMNS(COLUMNS(*)) FROM integers +---- +COLUMNS expression is not allowed inside another COLUMNS expression + statement error SELECT * + 42 FROM integers ---- diff --git a/test/sql/parser/test_columns_unpacked.test b/test/sql/parser/test_columns_unpacked.test new file mode 100644 index 00000000000..33b5da43608 --- /dev/null +++ b/test/sql/parser/test_columns_unpacked.test @@ -0,0 +1,190 @@ +# name: test/sql/parser/test_columns_unpacked.test +# group: [parser] + +statement ok +PRAGMA enable_verification + +query I +select COALESCE(*COLUMNS(*)) from (select NULL, 2, 3) t(a, b, c); +---- +2 + +query I +select column_name from (describe select COALESCE(*COLUMNS(*)) from (select NULL, 2, 3) t(a, b, c)); +---- +COALESCE(t.a, t.b, t.c) + +# Aliasing the result +query I +select column_name from (describe select COALESCE(*COLUMNS(*)) as a from (select NULL, 2, 3) t(a, b, c)); +---- +a + +statement ok +create table contains_test as select '123abc234' a, 4 b, 'abc' c; + +# Feed columns a and c into contains, equivalent to contains(a, c) +query I +select contains(*COLUMNS('[a|c]')) from contains_test; +---- +true + +# COLUMNS and *COLUMNS are equivalent as a root expression +query II +select COLUMNS('[a|c]') from contains_test; +---- +123abc234 abc + +statement error +select *COLUMNS('[a|c]') from contains_test; +---- +*COLUMNS not allowed at the root level, use COLUMNS instead + +statement ok +create table sales as from ( values + (150, '2017/06/12'::DATE, 3), + (125, '2017/08/29'::DATE, 2), + (175, '2017/06/12'::DATE, 4), +) t(amount, date, priority) + +query I +SELECT first(amount ORDER BY date ASC, priority DESC) FROM sales; +---- +175 + +# TODO: this could be supported +statement error +select first(amount ORDER BY *COLUMNS('date|priority') ASC) from sales; +---- +*COLUMNS(...) is not supported in the order expression + +# Using a lambda in *COLUMNS +query I +select COALESCE(*COLUMNS(c -> c in ('a', 'c'))) from (select NULL, 2, 3) t(a, b, c); +---- +3 + +# IN (...) +query I +select 2 in (*COLUMNS(*)) from (select 1, 2, 3) t(a, b, c); +---- +true + +# IN in WHERE clause +query III +from (VALUES (1, 2, 3), (2, 3, 0), (0, 0, 1)) tbl(a, b, c) where 1 IN (*COLUMNS(*)); +---- +1 2 3 +0 0 1 + +statement ok +create table data AS ( + SELECT * FROM (VALUES + (1, 'Alice'), + (2, 'Bob'), + (3, 'Alice'), + (4, 'Carol') + ) AS t(id, name) +) + +# Using struct pack: +query I +select struct_pack(*COLUMNS(*)) from data +---- +{'id': 1, 'name': Alice} +{'id': 2, 'name': Bob} +{'id': 3, 'name': Alice} +{'id': 4, 'name': Carol} + +# It can not be used inside a COLUMNS expression +statement error +SELECT COLUMNS(*COLUMNS(*)) FROM (VALUES ('test')) +---- +COLUMNS expression is not allowed inside another COLUMNS expression + +statement error +SELECT *COLUMNS(COLUMNS(*)) FROM (VALUES ('test')) +---- +COLUMNS expression is not allowed inside another COLUMNS expression + +# COLUMNS and *COLUMNS of different expressions +query III +select COLUMNS(*), struct_pack(COLUMNS(['id'])) from data +---- +1 Alice {'id': 1} +2 Bob {'id': 2} +3 Alice {'id': 3} +4 Carol {'id': 4} + +# (temporary limitation) +# *COLUMNS with different expressions can not appear in the same expression +statement error +select struct_pack(struct_pack(*COLUMNS(['id']), struct_pack(*COLUMNS(['name'])))) from data +---- +Multiple different STAR/COLUMNS in the same expression are not supported + +# When they share the same expression, this is allowed: +query I +select struct_pack( + b := struct_pack(*COLUMNS(['id'])), + a := struct_pack(*COLUMNS(['id'])) +) from data +---- +{'b': {'id': 1}, 'a': {'id': 1}} +{'b': {'id': 2}, 'a': {'id': 2}} +{'b': {'id': 3}, 'a': {'id': 3}} +{'b': {'id': 4}, 'a': {'id': 4}} + +# Multiple *COLUMNS in the same statement are allowed +# Whether they share the same expression or not: +query II +select struct_pack(*COLUMNS('id')) a, struct_pack(*COLUMNS('name')) from data +---- +{'id': 1} {'name': Alice} +{'id': 2} {'name': Bob} +{'id': 3} {'name': Alice} +{'id': 4} {'name': Carol} + +# Varargs function +query I +select CONCAT(*COLUMNS(*), *COLUMNS(*)) from data +---- +1Alice1Alice +2Bob2Bob +3Alice3Alice +4Carol4Carol + +# *COLUMNS inside COLUMNS lambda +statement error +select COLUMNS(col -> *COLUMNS('id')) from data +---- +COLUMNS expression is not allowed inside another COLUMNS expression + +statement error +select *COLUMNS(col -> *COLUMNS(*)) from data +---- +COLUMNS expression is not allowed inside another COLUMNS expression + +# *COLUMNS expanding to more than one column in binary op +statement error +with integers as ( + SELECT * FROM (VALUES + (42, 31), + (85, 76), + ) as t(a, b) +) +select *COLUMNS(*) + 42 from integers +---- +No function matches the given name and argument types '+(INTEGER, INTEGER, INTEGER_LITERAL)'. + +query I +with integers as ( + SELECT * FROM (VALUES + (42, 31), + (85, 76), + ) as t(a, b) +) +select *COLUMNS('a') + 42 from integers +---- +84 +127 \ No newline at end of file diff --git a/test/sql/pg_catalog/pg_type.test b/test/sql/pg_catalog/pg_type.test new file mode 100644 index 00000000000..4a7035ab737 --- /dev/null +++ b/test/sql/pg_catalog/pg_type.test @@ -0,0 +1,117 @@ +# name: test/sql/pg_catalog/pg_type.test +# description: Test pg_type function +# group: [pg_catalog] + +statement ok +CREATE TYPE greeting AS ENUM('hi', 'bonjour', 'konnichiwa', 'howdy') + +statement ok +SELECT * FROM pg_type + +statement ok +SELECT * FROM pg_catalog.pg_type + +query I +SELECT oid FROM pg_type WHERE typname = 'int8' AND oid IS NOT NULL +---- +20 + +query I +SELECT oid FROM pg_type WHERE typname = 'bytea' AND oid IS NOT NULL +---- +17 + +query I +SELECT oid FROM pg_type WHERE typname = 'bit' AND oid IS NOT NULL +---- +1560 + +query I +SELECT oid FROM pg_type WHERE typname = 'bool' AND oid IS NOT NULL +---- +16 + +query I +SELECT oid FROM pg_type WHERE typname = 'varchar' AND oid IS NOT NULL +---- +1043 + +query I +SELECT oid FROM pg_type WHERE typname = 'date' AND oid IS NOT NULL +---- +1082 + +query I +SELECT oid FROM pg_type WHERE typname = 'float8' AND oid IS NOT NULL +---- +701 + +query I +SELECT oid FROM pg_type WHERE typname = 'float4' AND oid IS NOT NULL +---- +700 + +query I +SELECT oid FROM pg_type WHERE typname = 'uuid' AND oid IS NOT NULL +---- +2950 + +query I +SELECT oid FROM pg_type WHERE typname = 'int4' AND oid IS NOT NULL +---- +23 + +query I +SELECT oid FROM pg_type WHERE typname = 'int2' AND oid IS NOT NULL +---- +21 + +query I +SELECT oid FROM pg_type WHERE typname = 'interval' AND oid IS NOT NULL +---- +1186 + +query I +SELECT oid FROM pg_type WHERE typname = 'time' AND oid IS NOT NULL +---- +1083 + +query I +SELECT oid FROM pg_type WHERE typname = 'timestamp' AND oid IS NOT NULL +---- +1114 + +query I +SELECT oid FROM pg_type WHERE typname = 'timestamptz' AND oid IS NOT NULL +---- +1184 + +query I +SELECT oid FROM pg_type WHERE typname = 'timetz' AND oid IS NOT NULL +---- +1266 + +query I +SELECT count(*) FROM pg_type where typname = 'greeting' +---- +1 + +query I +SELECT oid FROM pg_type WHERE typname = 'numeric' AND oid IS NOT NULL +---- +1700 + +query I +SELECT count(*) FROM pg_type where typname = 'enum' AND oid is NOT NULL +---- +0 + +query I +SELECT pg_catalog.format_pg_type('DECIMAL', 'test'); +---- +numeric + +query I +SELECT pg_catalog.format_pg_type('decimal', 'test'); +---- +numeric \ No newline at end of file diff --git a/test/sql/pg_catalog/sqlalchemy.test b/test/sql/pg_catalog/sqlalchemy.test index 8d910cc6589..a2a89428d8a 100644 --- a/test/sql/pg_catalog/sqlalchemy.test +++ b/test/sql/pg_catalog/sqlalchemy.test @@ -82,21 +82,25 @@ n.nspname='main' and relname='f' ---- # has_type -statement ok +query I SELECT EXISTS ( SELECT * FROM pg_catalog.pg_type t, pg_catalog.pg_namespace n WHERE t.typnamespace = n.oid - AND t.typname = 'INTEGER' + AND t.typname = 'integer' AND n.nspname = 'main' ) +---- +false -statement ok +query I SELECT EXISTS ( SELECT * FROM pg_catalog.pg_type t, pg_catalog.pg_namespace n WHERE t.typnamespace = n.oid - AND t.typname = 'INTEGER' + AND t.typname = 'int4' AND n.nspname = 'main' ) +---- +true # get_table_oid query I @@ -178,20 +182,20 @@ WHERE a.attrelid = (SELECT MIN(oid) FROM pg_class WHERE relname='integral_values AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum; ---- -j smallint NULL false -k integer NULL false -l bigint NULL false -i real NULL false -z double precision NULL false +j int2 NULL false +k int4 NULL false +l int8 NULL false +i float4 NULL false +z float8 NULL false m numeric(4,1) NULL false n numeric(9,2) NULL false o numeric(18,4) NULL false p numeric(37,2) NULL false -q character varying NULL false +q varchar NULL false r bytea NULL false s date NULL false -t time without time zone NULL false -u timestamp without time zone NULL false +t time NULL false +u timestamp NULL false v list NULL false w enum NULL false @@ -353,7 +357,7 @@ SELECT t.typname as "name", FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace LEFT JOIN pg_catalog.pg_enum e ON t.oid = e.enumtypid -WHERE t.typtype = 'e' +WHERE t.typtype = 'e' AND e.enumlabel IS NOT NULL ORDER BY e.enumsortorder ---- greeting true main hi diff --git a/test/sql/pivot/pivot_struct_aggregate.test b/test/sql/pivot/pivot_struct_aggregate.test new file mode 100644 index 00000000000..abc3d3168e4 --- /dev/null +++ b/test/sql/pivot/pivot_struct_aggregate.test @@ -0,0 +1,23 @@ +# name: test/sql/pivot/pivot_struct_aggregate.test +# description: Issue #12328: Segmentation fault during PIVOTING table (CLI) using struct field +# group: [pivot] + +statement ok +PRAGMA enable_verification + +statement ok +create table donnees_csv as select {'year': i::varchar, 'month': i::varchar} AS donnee, i%5 as variable_id, i%10 id_niv from range(1000) t(i); + +query IIIIII +pivot donnees_csv on variable_id using first(donnee) group by id_niv order by all; +---- +0 {'year': 0, 'month': 0} NULL NULL NULL NULL +1 NULL {'year': 1, 'month': 1} NULL NULL NULL +2 NULL NULL {'year': 2, 'month': 2} NULL NULL +3 NULL NULL NULL {'year': 3, 'month': 3} NULL +4 NULL NULL NULL NULL {'year': 4, 'month': 4} +5 {'year': 5, 'month': 5} NULL NULL NULL NULL +6 NULL {'year': 6, 'month': 6} NULL NULL NULL +7 NULL NULL {'year': 7, 'month': 7} NULL NULL +8 NULL NULL NULL {'year': 8, 'month': 8} NULL +9 NULL NULL NULL NULL {'year': 9, 'month': 9} diff --git a/test/sql/pragma/not_a_valid.json b/test/sql/pragma/not_a_valid.json new file mode 100644 index 00000000000..c831bd0c528 --- /dev/null +++ b/test/sql/pragma/not_a_valid.json @@ -0,0 +1,10 @@ +{{ + "This is not" + "a valid JSON" + + "file" +{ + + + ] +} diff --git a/test/sql/pragma/test_custom_profiling_settings.test b/test/sql/pragma/test_custom_profiling_settings.test new file mode 100644 index 00000000000..913cb25a002 --- /dev/null +++ b/test/sql/pragma/test_custom_profiling_settings.test @@ -0,0 +1,181 @@ +# name: test/sql/pragma/test_custom_profiling_settings.test +# description: Test PRAGMA custom_profiling_settings +# group: [pragma] + +require json + +statement ok +PRAGMA enable_verification; + +# Check that the default settings are as expected +statement ok +PRAGMA enable_profiling = 'json'; + +statement ok +PRAGMA profiling_output = 'test/sql/pragma/output.json'; + +statement ok +select unnest(['Maia', 'Thijs', 'Mark', 'Hannes', 'Tom', 'Max', 'Carlo', 'Sam', 'Tania']) as names order by random(); + +statement ok +CREATE OR REPLACE TABLE metrics_output AS SELECT * FROM 'test/sql/pragma/output.json'; + +statement ok +SELECT cpu_time, extra_info, operator_cardinality, operator_timing FROM metrics_output; + +query I rowsort +SELECT unnest(res) from ( + select current_setting('custom_profiling_settings') as raw_setting, + raw_setting.trim('{}') as setting, + string_split(setting, ', ') as res +) +---- +"CPU_TIME": "true" +"EXTRA_INFO": "true" +"OPERATOR_CARDINALITY": "true" +"OPERATOR_TIMING": "true" + +# Turn off all settings +statement ok +PRAGMA custom_profiling_settings='{}' + +query I rowsort +SELECT unnest(res) from ( + select current_setting('custom_profiling_settings') as raw_setting, + raw_setting.trim('{}') as setting, + string_split(setting, ', ') as res +) +---- +(empty) + +statement ok +PRAGMA enable_profiling = 'json'; + +statement ok +PRAGMA profiling_output = 'test/sql/pragma/output.json'; + +statement ok +select unnest(['Maia', 'Thijs', 'Mark', 'Hannes', 'Tom', 'Max', 'Carlo', 'Sam', 'Tania']) as names order by random(); + +statement ok +CREATE OR REPLACE TABLE metrics_output AS SELECT * FROM 'test/sql/pragma/output.json'; + +statement error +SELECT cpu_time FROM metrics_output; +---- +Referenced column "cpu_time" not found in FROM clause! + +statement error +SELECT extra_info FROM metrics_output; +---- +Referenced column "extra_info" not found in FROM clause! + +statement error +SELECT operator_cardinality FROM metrics_output; +---- +Referenced column "operator_cardinality" not found in FROM clause! + +statement error +SELECT operator_timing FROM metrics_output; +---- +Referenced column "operator_timing" not found in FROM clause! + +# change the cpu time to false and the rest to true and re-run the query +statement ok +PRAGMA custom_profiling_settings='{"CPU_TIME": "false", "EXTRA_INFO": "true", "OPERATOR_CARDINALITY": "true", "OPERATOR_TIMING": "true"}' + +query I rowsort +SELECT unnest(res) from ( + select current_setting('custom_profiling_settings') as raw_setting, + raw_setting.trim('{}') as setting, + string_split(setting, ', ') as res +) +---- +"EXTRA_INFO": "true" +"OPERATOR_CARDINALITY": "true" +"OPERATOR_TIMING": "true" + +statement ok +PRAGMA enable_profiling = 'json'; + +statement ok +PRAGMA profiling_output = 'test/sql/pragma/output.json'; + +statement ok +select unnest(['Maia', 'Thijs', 'Mark', 'Hannes', 'Tom', 'Max', 'Carlo', 'Sam', 'Tania']) as names order by random(); + +statement ok +CREATE OR REPLACE TABLE metrics_output AS SELECT * FROM 'test/sql/pragma/output.json'; + +statement error +select cpu_time from metrics_output; +---- +Referenced column "cpu_time" not found in FROM clause! + +statement ok +SELECT extra_info, operator_cardinality, operator_timing FROM metrics_output; + +# Remove time from the settings file but add back the cpu time +statement ok +PRAGMA custom_profiling_settings='{"CPU_TIME": "true", "EXTRA_INFO": "true", "OPERATOR_CARDINALITY": "true"}' + +query I rowsort +SELECT unnest(res) from ( + select current_setting('custom_profiling_settings') as raw_setting, + raw_setting.trim('{}') as setting, + string_split(setting, ', ') as res +) +---- +"CPU_TIME": "true" +"EXTRA_INFO": "true" +"OPERATOR_CARDINALITY": "true" + +statement ok +PRAGMA enable_profiling = 'json'; + +statement ok +PRAGMA profiling_output = 'test/sql/pragma/output.json'; + +statement ok +select unnest(['Maia', 'Thijs', 'Mark', 'Hannes', 'Tom', 'Max', 'Carlo', 'Sam', 'Tania']) as names order by random(); + +statement ok +CREATE OR REPLACE TABLE metrics_output AS SELECT * FROM 'test/sql/pragma/output.json'; + +# Even though operator timing is set to false, it still should have been collected so that CPU timing can be calculated +query I +SELECT +CASE + WHEN cpu_time > 0 THEN 'true' + ELSE 'false' +END +FROM metrics_output; +---- +true + +statement error +SELECT operator_timing FROM metrics_output; +---- +Referenced column "operator_timing" not found in FROM clause! + +# Error cases +statement error +PRAGMA custom_profiling_settings='}}}}}}' +---- +Could not parse the custom profiler settings file due to incorrect JSON: "}}}}}}" + +statement error +PRAGMA custom_profiling_settings=BONJOUR +---- +IO Error: Could not parse the custom profiler settings file due to incorrect JSON: "BONJOUR" + +statement error +PRAGMA custom_profiling_settings=[NOT_A_JSON] +---- +Binder Error: SET value cannot contain column names + +## add an invalid setting to the file +statement error +PRAGMA custom_profiling_settings='{"INVALID_SETTING": "true"}' +---- +Invalid custom profiler settings: "INVALID_SETTING" diff --git a/test/sql/pragma/test_enable_http_logging.test b/test/sql/pragma/test_enable_http_logging.test new file mode 100644 index 00000000000..982d44110a6 --- /dev/null +++ b/test/sql/pragma/test_enable_http_logging.test @@ -0,0 +1,18 @@ +# name: test/sql/pragma/test_enable_http_logging.test +# description: Test PRAGMA enable_http_logging parsing +# group: [pragma] + +# disable/enable +statement ok +SET enable_http_logging=false + +statement ok +SET enable_http_logging=true + +# select the location of where to save the http logging output (instead of printing to stdout) +statement ok +SET http_logging_output='__TEST_DIR__/httplog.txt' + +# but we can clear it again +statement ok +SET http_logging_output='' diff --git a/test/sql/sample/same_seed_same_sample.test b/test/sql/sample/same_seed_same_sample.test_slow similarity index 94% rename from test/sql/sample/same_seed_same_sample.test rename to test/sql/sample/same_seed_same_sample.test_slow index 24103cb55e9..f0aa486e130 100644 --- a/test/sql/sample/same_seed_same_sample.test +++ b/test/sql/sample/same_seed_same_sample.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/sample/same_seed_same_sample.test +# name: test/sql/sample/same_seed_same_sample.test_slow # description: Test SAMPLE keyword # group: [sample] diff --git a/test/sql/secrets/create_secret_hffs.test b/test/sql/secrets/create_secret_hffs.test new file mode 100644 index 00000000000..e86ead9d900 --- /dev/null +++ b/test/sql/secrets/create_secret_hffs.test @@ -0,0 +1,39 @@ +# name: test/sql/secrets/create_secret_hffs.test +# description: Test huggingface secrets +# group: [secrets] + +statement ok +PRAGMA enable_verification; + +require httpfs + +statement ok +set allow_persistent_secrets=false; + +# Generic bearer token secret is now available, not actually used yet +statement ok +CREATE SECRET b1 ( + TYPE BEARER, + TOKEN 'bla' +) + +# Manually setting token is simplest +statement ok +CREATE SECRET hf1 ( + TYPE HUGGINGFACE, + TOKEN 'bla' +) + +# Cache provider will automatically try to fetch the token from the cache +statement ok +CREATE SECRET hf2 ( + TYPE HUGGINGFACE, + PROVIDER 'credential_chain' +) + +query IIII +SELECT name, type, provider, scope FROM duckdb_secrets() order by name; +---- +b1 bearer config [] +hf1 huggingface config [hf://] +hf2 huggingface credential_chain [hf://] diff --git a/test/sql/secrets/create_secret_hffs_autoload.test b/test/sql/secrets/create_secret_hffs_autoload.test new file mode 100644 index 00000000000..63722f1e2eb --- /dev/null +++ b/test/sql/secrets/create_secret_hffs_autoload.test @@ -0,0 +1,37 @@ +# name: test/sql/secrets/create_secret_hffs_autoload.test +# description: Test huggingface secrets autoload +# group: [secrets] + +require no_extension_autoloading + +statement ok +PRAGMA enable_verification; + +statement ok +set allow_persistent_secrets=false; + +statement error +CREATE SECRET hf1 ( + TYPE HUGGINGFACE, + TOKEN 'bla' +) +---- +Secret type 'huggingface' does not exist, but it exists in the httpfs extension. + +statement error +CREATE SECRET hf1 ( + TYPE HUGGINGFACE, + PROVIDER config, + TOKEN 'bla' +) +---- +Secret provider 'config' for type 'huggingface' does not exist, but it exists in the httfps extension. + +# Cache provider will automatically try to fetch the token from the cache +statement error +CREATE SECRET hf2 ( + TYPE HUGGINGFACE, + PROVIDER 'credential_chain' +) +---- +Secret provider 'credential_chain' for type 'huggingface' does not exist, but it exists in the httpfs extension. diff --git a/test/sql/show_select/test_summarize.test b/test/sql/show_select/test_summarize.test index 6ea6f4aa541..89c34db003f 100644 --- a/test/sql/show_select/test_summarize.test +++ b/test/sql/show_select/test_summarize.test @@ -45,6 +45,25 @@ k HUGEINT -12 12 2 0.0 16.97056274847714 -12 0 12 3 33.33 d DOUBLE -0.5 0.5 2 0.0 0.7071067811865476 -0.5 0.0 0.5 3 33.33 e BLOB (empty) a\x00b\x00c 2 NULL NULL NULL NULL NULL 3 33.33 +# Temporal types +query IIIIIIIIIIII +summarize +from range('2024-01-01'::TIMESTAMP, '2024-04-10'::TIMESTAMP, INTERVAL 1 DAY); +---- +range TIMESTAMP 2024-01-01 00:00:00 2024-04-09 00:00:00 99 NULL NULL 2024-01-25 12:00:00 2024-02-19 12:00:00 2024-03-15 12:00:00 100 0.00 + +query IIIIIIIIIIII +summarize +SELECT range::DATE AS range from range('2024-01-01'::DATE, '2024-04-10'::DATE, INTERVAL 1 DAY); +---- +range DATE 2024-01-01 2024-04-09 98 NULL NULL 2024-01-26 2024-02-19 2024-03-16 100 0.00 + +query IIIIIIIIIIII +summarize +SELECT range::TIME AS range from range('2024-01-01'::DATE, '2024-04-10'::DATE, INTERVAL 1 HOUR); +---- +range TIME 00:00:00 23:00:00 28 NULL NULL 05:24:35.480769 11:28:55.400975 17:30:41.666667 2400 0.00 + statement ok SUMMARIZE VALUES (1.0),(6754950520); diff --git a/test/sql/storage/bc/internal_schemas_0102.test b/test/sql/storage/bc/internal_schemas_0102.test new file mode 100644 index 00000000000..00ea7a12a74 --- /dev/null +++ b/test/sql/storage/bc/internal_schemas_0102.test @@ -0,0 +1,22 @@ +# name: test/sql/storage/bc/internal_schemas_0102.test +# description: Verify internal schemas are not duplicated in the main schema when reading older databases +# group: [bc] + +require skip_reload + +# we cannot read/open a file with a different block size +require block_size 262144 + +require vector_size 2048 + +unzip data/storage/bc_0102.db.gz __TEST_DIR__/bc_0102.db + +load __TEST_DIR__/bc_0102.db readonly + +statement ok +PRAGMA enable_verification + +query II +select database_name, schema_name from duckdb_schemas where not internal +---- +bc_0102 s1 \ No newline at end of file diff --git a/test/sql/storage/buffer_manager_temp_dir.test b/test/sql/storage/buffer_manager_temp_dir.test index 01438ab38ba..52377f26027 100644 --- a/test/sql/storage/buffer_manager_temp_dir.test +++ b/test/sql/storage/buffer_manager_temp_dir.test @@ -2,6 +2,10 @@ # description: Test setting of the temporary directory # group: [storage] +# FIXME: Fails with --force-storage for non-default block sizes. +# FIXME: Possibly related to leftover_temp_files_issue_6420.test_slow, as we successfully create the table in both cases. +require block_size 262144 + require skip_reload # set temporary directory to an empty directory diff --git a/test/sql/storage/catalog/test_view_explicit_aliases.test b/test/sql/storage/catalog/test_view_explicit_aliases.test index f6ee0db8899..2d6f6c7344c 100644 --- a/test/sql/storage/catalog/test_view_explicit_aliases.test +++ b/test/sql/storage/catalog/test_view_explicit_aliases.test @@ -2,9 +2,15 @@ # description: Test views with explicit column aliases # group: [catalog] +# FIXME: for this to work we need to serialize/deserialize dependencies +require skip_reload + # load the DB from disk load __TEST_DIR__/view_explicit_aliases_storage.db +statement ok +set enable_view_dependencies=true + # create a database and insert the table/view statement ok CREATE SCHEMA test; @@ -17,18 +23,19 @@ statement ok CREATE VIEW test.v (b,c) AS SELECT * FROM test.t; # check the view info -query II nosort view_info +query IIIIII PRAGMA table_info('test.v') ---- +0 b INTEGER false NULL false +1 c INTEGER false NULL false statement ok SELECT * FROM test.v statement ok -DROP TABLE test.t +DROP TABLE test.t CASCADE; -# we can still query this after the table is gone -query II nosort view_info +statement error PRAGMA table_info('test.v') ---- @@ -37,8 +44,7 @@ loop i 0 2 # now reload restart -# can check info, but not query the view -query II nosort view_info +statement error PRAGMA table_info('test.v') ---- @@ -53,10 +59,14 @@ CREATE TABLE test.t (a INTEGER, b INTEGER); statement ok SELECT * FROM test.t -statement ok +statement error SELECT b,c FROM test.v +---- + +statement ok +CREATE VIEW test.v (b,c) AS SELECT * FROM test.t; statement ok -DROP TABLE test.t +DROP TABLE test.t CASCADE; endloop diff --git a/test/sql/storage/catalog/test_view_storage.test b/test/sql/storage/catalog/test_view_storage.test index d69e519193e..d2efb3c72e0 100644 --- a/test/sql/storage/catalog/test_view_storage.test +++ b/test/sql/storage/catalog/test_view_storage.test @@ -2,9 +2,15 @@ # description: Create and drop a view over different runs # group: [catalog] +# FIXME: for this to work we need to serialize/deserialize dependencies +require skip_reload + # load the DB from disk load __TEST_DIR__/view_storage.db +statement ok +set enable_view_dependencies=true + # create a schema and view statement ok CREATE SCHEMA test; @@ -24,14 +30,11 @@ PRAGMA table_info('test.v') # drop the table the view is based on statement ok -DROP TABLE test.t +DROP TABLE test.t CASCADE; -# we can still query the types and column names -query IIIIII +statement error PRAGMA table_info('test.v') ---- -0 a INTEGER 0 NULL 0 -1 b INTEGER 0 NULL 0 # but querying the view fails statement error @@ -44,13 +47,9 @@ loop i 0 2 # restart the system restart -# the view still exists, but the table does not -# we can check the types, but not query it -query IIIIII +statement error PRAGMA table_info('test.v') ---- -0 a INTEGER 0 NULL 0 -1 b INTEGER 0 NULL 0 statement error SELECT * FROM test.v @@ -63,6 +62,13 @@ CREATE TABLE test.t (a INTEGER, b INTEGER); statement ok SELECT * FROM test.t +statement error +SELECT * FROM test.v +---- + +statement ok +CREATE VIEW test.v AS SELECT * FROM test.t; + statement ok SELECT * FROM test.v @@ -74,6 +80,6 @@ PRAGMA table_info('test.v') # drop the table again statement ok -DROP TABLE test.t +DROP TABLE test.t CASCADE; endloop diff --git a/test/sql/storage/catalog/test_view_storage_no_view_dependencies.test b/test/sql/storage/catalog/test_view_storage_no_view_dependencies.test new file mode 100644 index 00000000000..195ac67e3cd --- /dev/null +++ b/test/sql/storage/catalog/test_view_storage_no_view_dependencies.test @@ -0,0 +1,79 @@ +# name: test/sql/storage/catalog/test_view_storage_no_view_dependencies.test +# description: Create and drop a view over different runs +# group: [catalog] + +# load the DB from disk +load __TEST_DIR__/view_storage.db + +# create a schema and view +statement ok +CREATE SCHEMA test; + +statement ok +CREATE TABLE test.t (a INTEGER, b INTEGER); + +statement ok +CREATE VIEW test.v AS SELECT * FROM test.t; + +# read the info from the view +query IIIIII +PRAGMA table_info('test.v') +---- +0 a INTEGER 0 NULL 0 +1 b INTEGER 0 NULL 0 + +# drop the table the view is based on +statement ok +DROP TABLE test.t + +# we can still query the types and column names +query IIIIII +PRAGMA table_info('test.v') +---- +0 a INTEGER 0 NULL 0 +1 b INTEGER 0 NULL 0 + +# but querying the view fails +statement error +SELECT * FROM test.v +---- + + +loop i 0 2 + +# restart the system +restart + +# the view still exists, but the table does not +# we can check the types, but not query it +query IIIIII +PRAGMA table_info('test.v') +---- +0 a INTEGER 0 NULL 0 +1 b INTEGER 0 NULL 0 + +statement error +SELECT * FROM test.v +---- + +# after recreating the table, we can query the view again +statement ok +CREATE TABLE test.t (a INTEGER, b INTEGER); + +statement ok +SELECT * FROM test.t + +statement ok +SELECT * FROM test.v + +query IIIIII +PRAGMA table_info('test.v') +---- +0 a INTEGER 0 NULL 0 +1 b INTEGER 0 NULL 0 + +# drop the table again +statement ok +DROP TABLE test.t + +endloop diff --git a/test/sql/storage/compact_block_size/compact_block_size.test b/test/sql/storage/compact_block_size/compact_block_size.test index 67045916dd2..eb001975935 100644 --- a/test/sql/storage/compact_block_size/compact_block_size.test +++ b/test/sql/storage/compact_block_size/compact_block_size.test @@ -6,11 +6,12 @@ require exact_vector_size 2048 require block_size 16384 +# FIXME: once we implement the configurable block size feature, we expect this to work # vector size is 2048, block size is 256KB statement error ATTACH 'data/storage/index_0-9-1.db' (TYPE DUCKDB, READONLY); ---- -Cannot read database file +Not implemented # vector size is 2048, block size is 16KB statement ok diff --git a/test/sql/storage/compact_block_size/default_block_size.test b/test/sql/storage/compact_block_size/default_block_size.test index dd7c453cb59..96ad8e2aae6 100644 --- a/test/sql/storage/compact_block_size/default_block_size.test +++ b/test/sql/storage/compact_block_size/default_block_size.test @@ -6,10 +6,12 @@ require block_size 262144 require vector_size 2048 +# FIXME: once we support custom block sizes, this test should work, as we detect the block +# FIXME: size in the database header statement error ATTACH 'data/storage/block_size_16kb.db' (TYPE DUCKDB, READONLY) ---- -Cannot read database file +Not implemented statement error ATTACH 'data/storage/vector_size_512.db' (TYPE DUCKDB, READONLY) diff --git a/test/sql/storage/compression/alp/alp_many_segments.test b/test/sql/storage/compression/alp/alp_many_segments.test_slow similarity index 94% rename from test/sql/storage/compression/alp/alp_many_segments.test rename to test/sql/storage/compression/alp/alp_many_segments.test_slow index d06dd8aa1f0..7cdd10fa635 100644 --- a/test/sql/storage/compression/alp/alp_many_segments.test +++ b/test/sql/storage/compression/alp/alp_many_segments.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/compression/alp/alp_many_segments.test +# name: test/sql/storage/compression/alp/alp_many_segments.test_slow # description: Test storage of alp, but simple # group: [alp] diff --git a/test/sql/storage/compression/alp/alp_many_segments_float.test b/test/sql/storage/compression/alp/alp_many_segments_float.test_slow similarity index 99% rename from test/sql/storage/compression/alp/alp_many_segments_float.test rename to test/sql/storage/compression/alp/alp_many_segments_float.test_slow index 0680eab2703..ed3dcd3bbab 100644 --- a/test/sql/storage/compression/alp/alp_many_segments_float.test +++ b/test/sql/storage/compression/alp/alp_many_segments_float.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/compression/alp/alp_many_segments_float.test +# name: test/sql/storage/compression/alp/alp_many_segments_float.test_slow # description: Test storage of alp, but simple # group: [alp] diff --git a/test/sql/storage/compression/alp/alp_middle_flush.test b/test/sql/storage/compression/alp/alp_middle_flush.test_slow similarity index 94% rename from test/sql/storage/compression/alp/alp_middle_flush.test rename to test/sql/storage/compression/alp/alp_middle_flush.test_slow index 520eb0138b2..ec1ee64e58c 100644 --- a/test/sql/storage/compression/alp/alp_middle_flush.test +++ b/test/sql/storage/compression/alp/alp_middle_flush.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/compression/alp/alp_middle_flush.test +# name: test/sql/storage/compression/alp/alp_middle_flush.test_slow # description: Test storage of alp, but simple # group: [alp] diff --git a/test/sql/storage/compression/alprd/alprd_many_segments.test b/test/sql/storage/compression/alprd/alprd_many_segments.test_slow similarity index 99% rename from test/sql/storage/compression/alprd/alprd_many_segments.test rename to test/sql/storage/compression/alprd/alprd_many_segments.test_slow index be81b75c10a..7b31c2352a3 100644 --- a/test/sql/storage/compression/alprd/alprd_many_segments.test +++ b/test/sql/storage/compression/alprd/alprd_many_segments.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/compression/alprd/alprd_many_segments.test +# name: test/sql/storage/compression/alprd/alprd_many_segments.test_slow # description: Test storage of alprd, but simple # group: [alprd] diff --git a/test/sql/storage/compression/alprd/alprd_many_segments_float.test b/test/sql/storage/compression/alprd/alprd_many_segments_float.test_slow similarity index 98% rename from test/sql/storage/compression/alprd/alprd_many_segments_float.test rename to test/sql/storage/compression/alprd/alprd_many_segments_float.test_slow index a9f6c5e8e3f..775b75d80df 100644 --- a/test/sql/storage/compression/alprd/alprd_many_segments_float.test +++ b/test/sql/storage/compression/alprd/alprd_many_segments_float.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/compression/alprd/alprd_many_segments_float.test +# name: test/sql/storage/compression/alprd/alprd_many_segments_float.test_slow # description: Test storage of alprd, but simple # group: [alprd] diff --git a/test/sql/storage/compression/alprd/alprd_middle_flush.test b/test/sql/storage/compression/alprd/alprd_middle_flush.test_slow similarity index 99% rename from test/sql/storage/compression/alprd/alprd_middle_flush.test rename to test/sql/storage/compression/alprd/alprd_middle_flush.test_slow index 2f6ea93b25f..a0c934b82d6 100644 --- a/test/sql/storage/compression/alprd/alprd_middle_flush.test +++ b/test/sql/storage/compression/alprd/alprd_middle_flush.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/compression/alprd/alprd_middle_flush.test +# name: test/sql/storage/compression/alprd/alprd_middle_flush.test_slow # description: Test storage of alprd, but simple # group: [alprd] diff --git a/test/sql/storage/compression/chimp/chimp_read.test b/test/sql/storage/compression/chimp/chimp_read.test_slow similarity index 93% rename from test/sql/storage/compression/chimp/chimp_read.test rename to test/sql/storage/compression/chimp/chimp_read.test_slow index fedda503817..94bf126b808 100644 --- a/test/sql/storage/compression/chimp/chimp_read.test +++ b/test/sql/storage/compression/chimp/chimp_read.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/compression/chimp/chimp_read.test +# name: test/sql/storage/compression/chimp/chimp_read.test_slow # group: [chimp] # we cannot read/open a file with a different block size diff --git a/test/sql/storage/compression/patas/patas_read.test b/test/sql/storage/compression/patas/patas_read.test_slow similarity index 93% rename from test/sql/storage/compression/patas/patas_read.test rename to test/sql/storage/compression/patas/patas_read.test_slow index 1380d2699e1..ea09a60c4f1 100644 --- a/test/sql/storage/compression/patas/patas_read.test +++ b/test/sql/storage/compression/patas/patas_read.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/compression/patas/patas_read.test +# name: test/sql/storage/compression/patas/patas_read.test_slow # group: [patas] # we cannot read/open a file with a different block size diff --git a/test/sql/storage/compression/string/blob.test b/test/sql/storage/compression/string/blob.test index d2bd74c6638..448e45f6c0f 100644 --- a/test/sql/storage/compression/string/blob.test +++ b/test/sql/storage/compression/string/blob.test @@ -2,6 +2,9 @@ # description: blob tests # group: [string] +# FIXME: fails for VERIFY_VECTOR=constant_operator +require no_vector_verification + load __TEST_DIR__/test_string_compression.db statement ok diff --git a/test/sql/storage/compression/string/null.test b/test/sql/storage/compression/string/null.test_slow similarity index 96% rename from test/sql/storage/compression/string/null.test rename to test/sql/storage/compression/string/null.test_slow index 183bb2ee587..e8ff9f51f8d 100644 --- a/test/sql/storage/compression/string/null.test +++ b/test/sql/storage/compression/string/null.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/compression/string/null.test +# name: test/sql/storage/compression/string/null.test_slow # description: Test storage of string columns with compression and many null values # group: [string] diff --git a/test/sql/storage/concurrent_table_insertion.test_slow b/test/sql/storage/concurrent_table_insertion.test_slow index 96710b56019..50bad063202 100644 --- a/test/sql/storage/concurrent_table_insertion.test_slow +++ b/test/sql/storage/concurrent_table_insertion.test_slow @@ -2,7 +2,11 @@ # description: Test concurrent table insertions # group: [storage] -# load the DB from disk +# Fails with VERIFY_VECTOR=dictionary_expression. +# The test calls into VerifyFlatVector after emitting a dictionary vector. +# This is spurious and I cannot reproduce it locally. +require no_vector_verification + load __TEST_DIR__/concurrent_table_insertions.db statement ok diff --git a/test/sql/storage/force_checkpoint_abort.test b/test/sql/storage/force_checkpoint_abort.test deleted file mode 100644 index 287f6fcd166..00000000000 --- a/test/sql/storage/force_checkpoint_abort.test +++ /dev/null @@ -1,38 +0,0 @@ -# name: test/sql/storage/force_checkpoint_abort.test -# description: Test behavior of FORCE CHECKPOINT -# group: [storage] - -require skip_reload - -load __TEST_DIR__/force_checkpoint_abort.db - -statement ok -CREATE TABLE integers(i INT) - -statement ok -INSERT INTO integers VALUES (1), (2), (3), (NULL); - -statement ok con2 -BEGIN - -statement ok con2 -UPDATE integers SET i=i+1; - -statement ok con1 -FORCE CHECKPOINT - -statement error con2 -SELECT * FROM integers ----- -Current transaction is aborted - -statement ok con2 -ROLLBACK - -query I con2 -SELECT * FROM integers ----- -1 -2 -3 -NULL diff --git a/test/sql/storage/icu_collation.test b/test/sql/storage/icu_collation.test new file mode 100644 index 00000000000..3a256165555 --- /dev/null +++ b/test/sql/storage/icu_collation.test @@ -0,0 +1,44 @@ +# name: test/sql/storage/icu_collation.test +# description: ATTACH to a database that uses ICU collations in types +# group: [storage] + +require skip_reload + +require no_extension_autoloading + +# database file is written with vsize = 2048 +require vector_size 2048 + +require block_size 262144 + +unzip data/storage/german_collation.db.gz __TEST_DIR__/icu_collation.db + +load __TEST_DIR__/icu_collation.db readonly + +query I rowsort +SELECT * FROM strings +---- +Gabel +Goethe +Goldmann +Göbel +Göthe +Götz + +# cannot order by without ICU +statement error +SELECT * FROM strings ORDER BY 1 +---- +not in the catalog + +require icu + +query I +SELECT * FROM strings ORDER BY 1 +---- +Gabel +Göbel +Goethe +Goldmann +Göthe +Götz diff --git a/test/sql/storage/issue7582_list_storage.test b/test/sql/storage/issue7582_list_storage.test index cefca52a46a..a9faaaae662 100644 --- a/test/sql/storage/issue7582_list_storage.test +++ b/test/sql/storage/issue7582_list_storage.test @@ -7,21 +7,21 @@ require parquet load __TEST_DIR__/issue7582.db statement ok -SET wal_autocheckpoint='1GB' +SET wal_autocheckpoint='1GB'; statement ok CREATE TABLE tbl (n TEXT[]); statement ok -INSERT INTO tbl (n) SELECT CASE WHEN i<100 THEN ['a', 'b'] ELSE [] END l FROM range(1026) t(i); +INSERT INTO tbl (n) SELECT CASE WHEN i < 100 THEN ['a', 'b'] ELSE [] END l FROM range(1026) t(i); statement ok -INSERT INTO tbl (n) SELECT CASE WHEN i<100 THEN ['a', 'b'] ELSE [] END l FROM range(1026) t(i); +INSERT INTO tbl (n) SELECT CASE WHEN i < 100 THEN ['a', 'b'] ELSE [] END l FROM range(1026) t(i); statement ok -INSERT INTO tbl (n) SELECT CASE WHEN i<100 THEN ['a', 'b'] ELSE [] END l FROM range(1026) t(i); +INSERT INTO tbl (n) SELECT CASE WHEN i < 100 THEN ['a', 'b'] ELSE [] END l FROM range(1026) t(i); restart statement ok -FROM tbl +FROM tbl; diff --git a/test/sql/storage/list_dictionary.test b/test/sql/storage/list_dictionary.test_slow similarity index 97% rename from test/sql/storage/list_dictionary.test rename to test/sql/storage/list_dictionary.test_slow index 524208881c5..51fbb56acf3 100644 --- a/test/sql/storage/list_dictionary.test +++ b/test/sql/storage/list_dictionary.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/list_dictionary.test +# name: test/sql/storage/list_dictionary.test_slow # description: Test list functions on a list with a child with dictionary encoding # group: [storage] diff --git a/test/sql/storage/multiple_clients_checkpoing_dependents.test_slow b/test/sql/storage/multiple_clients_checkpoing_dependents.test_slow index e87006afd7e..5d99c63e702 100644 --- a/test/sql/storage/multiple_clients_checkpoing_dependents.test_slow +++ b/test/sql/storage/multiple_clients_checkpoing_dependents.test_slow @@ -40,9 +40,11 @@ SELECT MIN(i), MAX(i), COUNT(*) FROM test; ---- 1 1000000 1000000 -# con2 now refers back to the undo buffer of con1, but we can still checkpoint -statement ok con2 +# con2 now refers back to the undo buffer of con1, we cannot checkpoint +statement error con2 FORCE CHECKPOINT +---- +the current transaction has been started for this database query III SELECT MIN(i), MAX(i), COUNT(*) FROM test; diff --git a/test/sql/storage/multiple_clients_checkpoint_pending_updates.test b/test/sql/storage/multiple_clients_checkpoint_pending_updates.test index 2220e0e048d..afbb71ffc7b 100644 --- a/test/sql/storage/multiple_clients_checkpoint_pending_updates.test +++ b/test/sql/storage/multiple_clients_checkpoint_pending_updates.test @@ -20,16 +20,7 @@ UPDATE test SET i=i+1; statement error con2 CHECKPOINT ---- -TransactionContext Error: Cannot CHECKPOINT: there are other transactions. Use FORCE CHECKPOINT to abort the other transactions and force a checkpoint - -statement ok con2 -FORCE CHECKPOINT - -# force checkpoint rolled back the transaction of con1 -statement error con1 -SELECT MIN(i), MAX(i), COUNT(*) FROM test; ----- -transaction is aborted +Cannot CHECKPOINT: there are other write transactions statement ok con1 ROLLBACK @@ -86,10 +77,7 @@ UPDATE test SET i=i+1 WHERE i > 3000 AND i < 4000 statement error CHECKPOINT ---- -TransactionContext Error: Cannot CHECKPOINT: there are other transactions. Use FORCE CHECKPOINT to abort the other transactions and force a checkpoint - -statement ok -FORCE CHECKPOINT +Cannot CHECKPOINT: there are other write transactions query III SELECT MIN(i), MAX(i), COUNT(*) FROM test; @@ -101,11 +89,6 @@ SELECT MIN(i), MAX(i), COUNT(*) FROM test; ---- 0 999999 1000000 -statement error con2 -SELECT MIN(i), MAX(i), COUNT(*) FROM test; ----- -transaction is aborted - statement ok con2 ROLLBACK @@ -114,11 +97,6 @@ SELECT MIN(i), MAX(i), COUNT(*) FROM test; ---- 0 999999 1000000 -statement error con3 -SELECT MIN(i), MAX(i), COUNT(*) FROM test; ----- -transaction is aborted - statement ok con3 ROLLBACK @@ -127,11 +105,6 @@ SELECT MIN(i), MAX(i), COUNT(*) FROM test; ---- 0 999999 1000000 -statement error con4 -SELECT MIN(i), MAX(i), COUNT(*) FROM test; ----- -transaction is aborted - statement ok con4 ROLLBACK @@ -140,11 +113,6 @@ SELECT MIN(i), MAX(i), COUNT(*) FROM test; ---- 0 999999 1000000 -statement error con5 -SELECT MIN(i), MAX(i), COUNT(*) FROM test; ----- -transaction is aborted - statement ok con5 ROLLBACK diff --git a/test/sql/storage/parallel/batch_insert_mix_batches.test_slow b/test/sql/storage/parallel/batch_insert_mix_batches.test_slow index 2808151c95c..8145c9254b3 100644 --- a/test/sql/storage/parallel/batch_insert_mix_batches.test_slow +++ b/test/sql/storage/parallel/batch_insert_mix_batches.test_slow @@ -162,6 +162,12 @@ DROP TABLE integers2 statement ok DROP TABLE integers3 +statement ok +drop view if exists v2; + +statement ok +drop view if exists v3; + # create views that read the batches using unions statement ok CREATE OR REPLACE VIEW v1 AS FROM '__TEST_DIR__/mix_batches_small.parquet' UNION ALL FROM '__TEST_DIR__/mix_batches_large.parquet' UNION ALL FROM '__TEST_DIR__/mix_batches_odd.parquet' UNION ALL FROM '__TEST_DIR__/mix_batches_odd_again.parquet' diff --git a/test/sql/storage/parallel/batch_insert_small_batches.test_slow b/test/sql/storage/parallel/batch_insert_small_batches.test_slow index 54a1842c1d0..bb92cb76db7 100644 --- a/test/sql/storage/parallel/batch_insert_small_batches.test_slow +++ b/test/sql/storage/parallel/batch_insert_small_batches.test_slow @@ -11,6 +11,12 @@ foreach row_group_size 5000 100000 statement ok COPY (FROM range(1000000) tbl(i)) TO '__TEST_DIR__/small_batches.parquet' (ROW_GROUP_SIZE ${row_group_size}) +statement ok +drop view if exists v2; + +statement ok +drop view if exists v3; + statement ok CREATE VIEW v1 AS SELECT * FROM '__TEST_DIR__/small_batches.parquet' @@ -158,15 +164,15 @@ SELECT * FROM integers3 LIMIT 5 OFFSET 9999 20002 20003 -statement ok -DROP VIEW v1 - statement ok DROP VIEW v2 statement ok DROP VIEW v3 +statement ok +DROP VIEW v1; + statement ok DROP TABLE integers diff --git a/test/sql/storage/parallel/memory_limit_batch_load.test_slow b/test/sql/storage/parallel/memory_limit_batch_load.test_slow index 46db9e464e8..78f95153d11 100644 --- a/test/sql/storage/parallel/memory_limit_batch_load.test_slow +++ b/test/sql/storage/parallel/memory_limit_batch_load.test_slow @@ -4,6 +4,10 @@ require parquet +# FIXME: Occassionally fails in the CI nightly with "No space left on device". +# FIXME: Most likely a false positive, as it is one of the last tests running. +require block_size 262144 + load __TEST_DIR__/memory_limit_batch_load.db # in this test we load data of around 100M rows - uncompressed this will be 1.4GB~2GB (without/with NULLs) diff --git a/test/sql/storage/reclaim_space/reclaim_space_drop_column_overflow_strings.test_slow b/test/sql/storage/reclaim_space/reclaim_space_drop_column_overflow_strings.test_slow index cf6461213ff..ad43eabbe7a 100644 --- a/test/sql/storage/reclaim_space/reclaim_space_drop_column_overflow_strings.test_slow +++ b/test/sql/storage/reclaim_space/reclaim_space_drop_column_overflow_strings.test_slow @@ -21,7 +21,12 @@ SELECT AVG(STRLEN(s)), MIN(STRLEN(S)), MAX(STRLEN(S)), SUM(STRLEN(S)), MIN(S[1]) ---- 296.955 0 5000 44543527 (empty) X -loop i 0 10 +# For smaller block sizes (16KB) the total blocks alternate between a few values in the loop, +# therefore, we need to compare to a range of total block counts. +statement ok +CREATE TABLE total_blocks_tbl AS SELECT total_blocks FROM pragma_database_size(); + +loop i 0 30 statement ok ALTER TABLE strings DROP COLUMN s; @@ -40,10 +45,22 @@ SELECT AVG(STRLEN(s)), MIN(STRLEN(S)), MAX(STRLEN(S)), SUM(STRLEN(S)), MIN(S[1]) statement ok CHECKPOINT; -# ensure that the expected total storage size is the same as in the first iteration of the loop +# Ensure that the total blocks don't exceed the total blocks by more than 1.2. + +query I +SELECT CASE WHEN ${i} < 10 THEN True + WHEN current.total_blocks <= total_blocks_tbl.total_blocks * 1.2 THEN True + ELSE False END +FROM pragma_database_size() AS current, total_blocks_tbl; +---- +1 + +# Adjust total_blocks_tbl to the count after 10 warm-up iterations. -query I nosort expected_blocks -SELECT total_blocks FROM pragma_database_size(); +statement ok +UPDATE total_blocks_tbl SET total_blocks = ( + SELECT CASE WHEN ${i} < 10 THEN (SELECT current.total_blocks FROM pragma_database_size() AS current) + ELSE (total_blocks) END); restart diff --git a/test/sql/storage/reclaim_space/test_reclaim_space_alter_type.test_slow b/test/sql/storage/reclaim_space/test_reclaim_space_alter_type.test_slow index b4cebfac6cf..299c77e70c2 100644 --- a/test/sql/storage/reclaim_space/test_reclaim_space_alter_type.test_slow +++ b/test/sql/storage/reclaim_space/test_reclaim_space_alter_type.test_slow @@ -21,12 +21,12 @@ SELECT MIN(i), MAX(i), COUNT(*) FROM integers ---- 0 999999 1000000 -# for smaller block sizes (16KB) the total blocks alternate between a few values in the loop, -# therefore, we need to compare to a range of total block counts +# For smaller block sizes (16KB) the total blocks alternate between a few values in the loop, +# therefore, we need to compare to a range of total block counts. statement ok CREATE TABLE total_blocks_tbl AS SELECT total_blocks FROM pragma_database_size(); -loop i 0 10 +loop i 0 20 statement ok ALTER TABLE integers ALTER i SET DATA TYPE BIGINT; @@ -53,22 +53,21 @@ SELECT MIN(i), MAX(i), COUNT(*) FROM integers statement ok CHECKPOINT; -# ensure that the total blocks don't exceed the total blocks after the first iteration -# by more than 1.2 +# Ensure that the total blocks don't exceed the total blocks by more than 1.2. query I -SELECT CASE WHEN ${i} = 0 THEN True +SELECT CASE WHEN ${i} < 10 THEN True WHEN current.total_blocks <= total_blocks_tbl.total_blocks * 1.2 THEN True ELSE False END FROM pragma_database_size() AS current, total_blocks_tbl; ---- 1 -# adjust total_blocks_tbl once to the count after the first iteration +# Adjust total_blocks_tbl to the count after 10 warm-up iterations. statement ok UPDATE total_blocks_tbl SET total_blocks = ( - SELECT CASE WHEN ${i} = 0 THEN (SELECT current.total_blocks FROM pragma_database_size() AS current) + SELECT CASE WHEN ${i} < 10 THEN (SELECT current.total_blocks FROM pragma_database_size() AS current) ELSE (total_blocks) END); query III diff --git a/test/sql/storage/reclaim_space/test_reclaim_space_update.test_slow b/test/sql/storage/reclaim_space/test_reclaim_space_update.test_slow index 4156115c3a7..c81b66fa3b2 100644 --- a/test/sql/storage/reclaim_space/test_reclaim_space_update.test_slow +++ b/test/sql/storage/reclaim_space/test_reclaim_space_update.test_slow @@ -21,7 +21,12 @@ SELECT MIN(i), MAX(i), COUNT(*) FROM integers ---- 0 999999 1000000 -loop i 0 10 +# For smaller block sizes (16KB) the total blocks alternate between a few values in the loop, +# therefore, we need to compare to a range of total block counts. +statement ok +CREATE TABLE total_blocks_tbl AS SELECT total_blocks FROM pragma_database_size(); + +loop i 0 20 statement ok UPDATE integers SET i=i; @@ -48,10 +53,22 @@ SELECT MIN(i), MAX(i), COUNT(*) FROM integers statement ok CHECKPOINT; -# ensure that the expected total storage size is the same as in the first iteration of the loop +# Ensure that the total blocks don't exceed the total blocks by more than 1.2. + +query I +SELECT CASE WHEN ${i} < 10 THEN True + WHEN current.total_blocks <= total_blocks_tbl.total_blocks * 1.2 THEN True + ELSE False END +FROM pragma_database_size() AS current, total_blocks_tbl; +---- +1 + +# Adjust total_blocks_tbl to the count after 10 warm-up iterations. -query I nosort expected_blocks -SELECT total_blocks FROM pragma_database_size(); +statement ok +UPDATE total_blocks_tbl SET total_blocks = ( + SELECT CASE WHEN ${i} < 10 THEN (SELECT current.total_blocks FROM pragma_database_size() AS current) + ELSE (total_blocks) END); query III SELECT MIN(i), MAX(i), COUNT(*) FROM integers diff --git a/test/sql/storage/relocate_metadata.test_slow b/test/sql/storage/relocate_metadata.test_slow new file mode 100644 index 00000000000..606cf63081d --- /dev/null +++ b/test/sql/storage/relocate_metadata.test_slow @@ -0,0 +1,53 @@ +# name: test/sql/storage/relocate_metadata.test_slow +# description: Verify that metadata is relocated to allow the database to free up space +# group: [storage] + +# load the DB from disk +load __TEST_DIR__/relocate_metadata.db + +statement ok +CREATE TABLE test (x INT, y AS (x + 100)); + +statement ok +insert into test select range FROM range(100000000); + +statement ok +delete from test where x % 10 = 7; + +statement ok +delete from test where x % 10 = 6; + +statement ok +delete from test where x % 10 = 5; + +statement ok +delete from test where x % 10 = 4; + +statement ok +delete from test where x % 10 = 3; + +statement ok +delete from test where x % 10 = 2; + +statement ok +delete from test where x % 10 = 1; + +statement ok +delete from test where x % 10 = 0; + +statement ok +delete from test where x % 10 = 8; + +statement ok +delete from test where x % 10 = 9; + +statement ok +drop table test; + +statement ok +checkpoint + +query I +SELECT MAX(block_id)<5 FROM pragma_metadata_info(); +---- +true diff --git a/test/sql/storage/storage_types.test b/test/sql/storage/storage_types.test index 1750acb4edf..e8e5acc9570 100644 --- a/test/sql/storage/storage_types.test +++ b/test/sql/storage/storage_types.test @@ -2,7 +2,6 @@ # description: Test storage of columns with various types # group: [storage] -# load the DB from disk load __TEST_DIR__/storage_types.db foreach type @@ -16,13 +15,12 @@ SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_${type} 0 99 100 100 query IIII -SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_${type} WHERE i=1 +SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_${type} WHERE i = 1 ---- 1 1 1 1 endloop -# interval statement ok CREATE TABLE a_interval AS SELECT interval (range) year i FROM range(1,1001) @@ -32,13 +30,12 @@ SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_interval 1 year 1000 years 1000 1000 query IIII -SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_interval WHERE i=interval 1 year +SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_interval WHERE i = interval 1 year ---- 1 year 1 year 1 1 -# bool statement ok -CREATE TABLE a_bool AS SELECT range%2=0 i FROM range(1000) +CREATE TABLE a_bool AS SELECT range % 2 = 0 AS i FROM range(1000) query IIII SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_bool @@ -46,13 +43,13 @@ SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_bool false true 1000 1000 query IIII -SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_bool WHERE not i +SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_bool WHERE NOT i ---- false false 500 500 restart -# restart and check all types again +# Restart and check all types. foreach type @@ -62,7 +59,7 @@ SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_${type} 0 99 100 100 query IIII -SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_${type} WHERE i=1 +SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_${type} WHERE i = 1 ---- 1 1 1 1 @@ -74,7 +71,7 @@ SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_interval 1 year 1000 years 1000 1000 query IIII -SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_interval WHERE i=interval 1 year +SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_interval WHERE i = interval 1 year ---- 1 year 1 year 1 1 @@ -84,6 +81,6 @@ SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_bool false true 1000 1000 query IIII -SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_bool WHERE not i +SELECT MIN(i), MAX(i), COUNT(*), COUNT(i) FROM a_bool WHERE NOT i ---- false false 500 500 diff --git a/test/sql/storage/temp_directory/max_swap_space_error.test b/test/sql/storage/temp_directory/max_swap_space_error.test index d9512df2230..0d25b4d0e4e 100644 --- a/test/sql/storage/temp_directory/max_swap_space_error.test +++ b/test/sql/storage/temp_directory/max_swap_space_error.test @@ -5,6 +5,12 @@ require skip_reload require noforcestorage +# this test performs many comparisons against the default block size of 256KiB +require block_size 262144 + +# temp directory usage changes with vector size +require vector_size 2048 + # Set a temp_directory to offload data statement ok set temp_directory='__TEST_DIR__/max_swap_space_reached' @@ -13,33 +19,33 @@ set temp_directory='__TEST_DIR__/max_swap_space_reached' statement ok PRAGMA memory_limit='1024KiB' -# 0 blocks +# Zero blocks statement ok set max_temp_directory_size='0KiB' statement error CREATE OR REPLACE TABLE t2 AS SELECT * FROM range(1000000); ---- -failed to offload data block of size 256.0 KiB (0 bytes/0 bytes used) +failed to offload data block query I select "size" from duckdb_temporary_files() ---- 0 -# 1 block max +# Max. one block for the default block allocation size statement ok set max_temp_directory_size='256KiB' statement error CREATE OR REPLACE TABLE t2 AS SELECT * FROM range(1000000); ---- -failed to offload data block of size 256.0 KiB (256.0 KiB/256.0 KiB used) +failed to offload data block statement error CREATE OR REPLACE TABLE t2 AS SELECT * FROM range(1000000); ---- -failed to offload data block of size 256.0 KiB (256.0 KiB/256.0 KiB used) +failed to offload data block query I select "size" from duckdb_temporary_files() @@ -64,10 +70,10 @@ CREATE OR REPLACE TABLE t2 AS SELECT * FROM range(200000); statement error CREATE OR REPLACE TABLE t2 AS SELECT * FROM range(300000); ---- -failed to offload data block of size 256.0 KiB (1.5 MiB/1.5 MiB used) +failed to offload data block query I -select "size" from duckdb_temporary_files() +SELECT "size" FROM duckdb_temporary_files(); ---- 1572864 diff --git a/test/sql/storage/temp_directory/max_swap_space_inmemory.test b/test/sql/storage/temp_directory/max_swap_space_inmemory.test index f02c6fada81..d66cabe965c 100644 --- a/test/sql/storage/temp_directory/max_swap_space_inmemory.test +++ b/test/sql/storage/temp_directory/max_swap_space_inmemory.test @@ -1,6 +1,10 @@ # name: test/sql/storage/temp_directory/max_swap_space_inmemory.test # group: [temp_directory] +# FIXME: Fails with --force-storage for non-default block sizes. +# FIXME: Does this rely on a default block size similar to max_swap_space_persistent.test? +require block_size 262144 + require skip_reload # In in-memory mode, the 'temp_directory' defaults to '.tmp' diff --git a/test/sql/storage/temp_directory/max_swap_space_persistent.test b/test/sql/storage/temp_directory/max_swap_space_persistent.test index 3b409394819..d3bc90b8c34 100644 --- a/test/sql/storage/temp_directory/max_swap_space_persistent.test +++ b/test/sql/storage/temp_directory/max_swap_space_persistent.test @@ -1,124 +1,113 @@ # name: test/sql/storage/temp_directory/max_swap_space_persistent.test +# description: Test the maximum swap space for temporary directories. # group: [temp_directory] require skip_reload -# Create a persistent database +# Implicitly relies on the assumption that the block allocation size is 256KB. +require block_size 262144 + load __TEST_DIR__/max_swap_space.db -# Default temp_directory for a persistent database is .tmp +# The default temp_directory for a persistent database is .tmp. query I -select current_setting('temp_directory').split('/')[-1] +SELECT current_setting('temp_directory').split('/')[-1]; ---- max_swap_space.db.tmp -## If 'temp_directory' is not set, this defaults to 0 -#query I -#select current_setting('max_temp_directory_size') -#---- -#0 bytes - statement ok -set temp_directory=''; +SET temp_directory=''; statement ok -PRAGMA memory_limit='2MB' - -# --- Set by default to 0 when temp_directory is not set --- +PRAGMA memory_limit='2MB'; -# If 'temp_directory' is not set, this defaults to 0 +# If the 'temp_directory' is not set, then this defaults to zero. query I -select current_setting('max_temp_directory_size') +SELECT current_setting('max_temp_directory_size'); ---- 0 bytes -# Set the max size explicitly +# Set the maximum size. statement ok -set max_temp_directory_size='15gb' +SET max_temp_directory_size='15GB'; -# Should not be 0 anymore +# Empty result, as the size should not be zero anymore. query I -select current_setting('max_temp_directory_size') a where a == '0 bytes' +SELECT current_setting('max_temp_directory_size') a WHERE a == '0 bytes'; ---- -# Then reset it, default should be 0 again +# Back to zero after resetting. statement ok -reset max_temp_directory_size; +RESET max_temp_directory_size; query I -select current_setting('max_temp_directory_size') +SELECT current_setting('max_temp_directory_size'); ---- 0 bytes -# --- Set by default to the available disk space when temp_directory exists --- - +# The maximum size is by default set to the available disk space, if the temp_directory exists. statement ok -set temp_directory = '__TEST_DIR__'; +SET temp_directory = '__TEST_DIR__'; -# Even though __TEST_DIR__ exists, the handle is not created so the size is still 0 (unknown) +# Even though __TEST_DIR__ exists, the handle is not created so the size is still zero (unknown). query I -select current_setting('max_temp_directory_size') +SELECT current_setting('max_temp_directory_size'); ---- 0 bytes -# --- Set explicitly by the user --- - -# If we set 'max_temp_directory_size' explicitly, it will not be overridden +# If we set 'max_temp_directory_size', it cannot be overwritten. statement ok -set max_temp_directory_size='15gb' +SET max_temp_directory_size='15GB'; -# Reported size should not be 0, we set it explicitly +# The reported size should not be zero, as we set it explicitly. query I -select current_setting('max_temp_directory_size') a where a == '0 bytes' +SELECT current_setting('max_temp_directory_size') a WHERE a == '0 bytes'; ---- query I nosort unchanged -select current_setting('max_temp_directory_size') +SELECT current_setting('max_temp_directory_size'); ---- -# When we change the temp_directory to something that doesnt exist +# Change the temp_directory to a path that does not exist, which does not affect the setting. statement ok -set temp_directory = '__TEST_DIR__/does_not_exist' +SET temp_directory = '__TEST_DIR__/does_not_exist'; query I nosort unchanged -select current_setting('max_temp_directory_size') +SELECT current_setting('max_temp_directory_size'); ---- -# When we change the temp_directory to something that does exist statement ok -set temp_directory = '__TEST_DIR__' +SET temp_directory = '__TEST_DIR__'; query I nosort unchanged -select current_setting('max_temp_directory_size') +SELECT current_setting('max_temp_directory_size'); ---- -# When we reset the temp_directory .. statement ok -reset temp_directory; +RESET temp_directory; query I nosort unchanged -select current_setting('max_temp_directory_size') +SELECT current_setting('max_temp_directory_size'); ---- -# --- Set to the available disk space when we create the (previously non-existant) 'temp_directory' +# Set the maximum size to the available disk space, +# if we create the previously non-existant 'temp_directory'. -# Reset it so it's no longer set explicitly statement ok -reset max_temp_directory_size; +RESET max_temp_directory_size; -# When we change the temp_directory to something that doesnt exist statement ok -set temp_directory = '__TEST_DIR__/does_not_exist' +SET temp_directory = '__TEST_DIR__/does_not_exist'; query I -select current_setting('max_temp_directory_size') +SELECT current_setting('max_temp_directory_size'); ---- 0 bytes statement ok CREATE TABLE t2 AS SELECT * FROM range(1000000); -# Reported size should not be 0, the directory was created +# The reported size should not be zero, as the directory was created. query I -select current_setting('max_temp_directory_size') a where a == '0 bytes' +SELECT current_setting('max_temp_directory_size') a where a == '0 bytes'; ---- diff --git a/test/sql/storage/test_empty_table.test b/test/sql/storage/test_empty_table.test index 7b49ae4d48e..00b3b66d354 100644 --- a/test/sql/storage/test_empty_table.test +++ b/test/sql/storage/test_empty_table.test @@ -1,8 +1,7 @@ # name: test/sql/storage/test_empty_table.test -# description: Test empty table +# description: Test empty table storage. # group: [storage] -# load the DB from disk load __TEST_DIR__/test_empty_table.db statement ok @@ -13,8 +12,7 @@ SELECT COUNT(*) FROM test ---- 0 - -# verify that the table is still there after restart +# Verify that the table exists after restarting the database. restart @@ -23,7 +21,6 @@ SELECT COUNT(*) FROM test ---- 0 -# insert into empty table statement ok INSERT INTO test VALUES (1, 2) diff --git a/test/sql/storage/test_purge_queue.test b/test/sql/storage/test_purge_queue.test_slow similarity index 91% rename from test/sql/storage/test_purge_queue.test rename to test/sql/storage/test_purge_queue.test_slow index 91129761181..a859d5e8d72 100644 --- a/test/sql/storage/test_purge_queue.test +++ b/test/sql/storage/test_purge_queue.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/storage/test_purge_queue.test +# name: test/sql/storage/test_purge_queue.test_slow # description: Test purging the eviction queue # group: [storage] diff --git a/test/sql/storage/types/test_timestamp_storage.test b/test/sql/storage/types/test_timestamp_storage.test index b0f90518616..5aea2b247af 100644 --- a/test/sql/storage/types/test_timestamp_storage.test +++ b/test/sql/storage/types/test_timestamp_storage.test @@ -29,15 +29,15 @@ restart query TTTT SELECT * FROM timestamp ORDER BY sec ---- -2008-01-01 00:00:01 2008-01-01 00:00:01.594 2008-01-01 00:00:01.88926 2008-01-01 00:00:01.889268 -2008-01-01 00:00:11 2008-01-01 00:00:01.794 2008-01-01 00:00:01.98926 2008-01-01 00:00:01.899268 -2008-01-01 00:00:51 2008-01-01 00:00:01.894 2008-01-01 00:00:01.99926 2008-01-01 00:00:01.999268 +2008-01-01 00:00:01 2008-01-01 00:00:01.594 2008-01-01 00:00:01.88926 2008-01-01 00:00:01.889268321 +2008-01-01 00:00:11 2008-01-01 00:00:01.794 2008-01-01 00:00:01.98926 2008-01-01 00:00:01.899268321 +2008-01-01 00:00:51 2008-01-01 00:00:01.894 2008-01-01 00:00:01.99926 2008-01-01 00:00:01.999268321 NULL NULL NULL NULL query TTTT SELECT * FROM timestamp WHERE micro=TIMESTAMP '2008-01-01 00:00:01.88926' ORDER BY micro ---- -2008-01-01 00:00:01 2008-01-01 00:00:01.594 2008-01-01 00:00:01.88926 2008-01-01 00:00:01.889268 +2008-01-01 00:00:01 2008-01-01 00:00:01.594 2008-01-01 00:00:01.88926 2008-01-01 00:00:01.889268321 query TTTT SELECT * FROM timestamp WHERE micro=TIMESTAMP '2020-01-01 00:00:01.88926' ORDER BY micro diff --git a/test/sql/storage/vacuum/test_truncate_after_delete.test_slow b/test/sql/storage/vacuum/test_truncate_after_delete.test_slow index a49e627f2b0..063914c81d0 100644 --- a/test/sql/storage/vacuum/test_truncate_after_delete.test_slow +++ b/test/sql/storage/vacuum/test_truncate_after_delete.test_slow @@ -7,12 +7,12 @@ load __TEST_DIR__/truncate_after_delete.db statement ok CREATE TABLE uuids (i VARCHAR); -# for smaller block sizes (16KB) the total blocks alternate between a few values in the loop, -# therefore, we need to compare to a range of total block counts +# For smaller block sizes (16KB) the total blocks alternate between a few values in the loop, +# therefore, we need to compare to a range of total block counts. statement ok CREATE TABLE total_blocks_tbl AS SELECT total_blocks FROM pragma_database_size(); -loop i 0 10 +loop i 0 20 statement ok DROP TABLE IF EXISTS integers; @@ -43,23 +43,22 @@ INSERT INTO integers VALUES (1), (2), (3); statement ok CHECKPOINT; -# ensure that the total blocks don't exceed the total blocks after the first iteration -# by more than 1.2 +# Ensure that the total blocks don't exceed the total blocks by more than 1.2. query I -SELECT CASE WHEN ${i} = 0 THEN True +SELECT CASE WHEN ${i} < 10 THEN True WHEN current.total_blocks <= total_blocks_tbl.total_blocks * 1.2 THEN True ELSE False END FROM pragma_database_size() AS current, total_blocks_tbl; ---- 1 -# adjust total_blocks_tbl once to the count after the first iteration +# Adjust total_blocks_tbl to the count after 10 warm-up iterations. statement ok UPDATE total_blocks_tbl SET total_blocks = ( - SELECT CASE WHEN ${i} = 0 THEN (SELECT current.total_blocks FROM pragma_database_size() AS current) - ELSE (total_blocks) END); + SELECT CASE WHEN ${i} < 10 THEN (SELECT current.total_blocks FROM pragma_database_size() AS current) + ELSE (total_blocks) END); endloop diff --git a/test/sql/storage/wal/wal_create_insert_drop.test b/test/sql/storage/wal/wal_create_insert_drop.test new file mode 100644 index 00000000000..61f026bfd12 --- /dev/null +++ b/test/sql/storage/wal/wal_create_insert_drop.test @@ -0,0 +1,107 @@ +# name: test/sql/storage/wal/wal_create_insert_drop.test +# description: Test serialization of CHECK constraint +# group: [wal] + +# load the DB from disk +load __TEST_DIR__/wal_create_insert_drop.db + +statement ok +PRAGMA disable_checkpoint_on_shutdown; + +statement ok +SET checkpoint_threshold='999999GB'; + +statement ok +begin + +statement ok +create table bla as select 42; + +statement ok +drop table bla; + +statement ok +create table bla as select 84; + +statement ok +commit; + +restart + +statement ok +PRAGMA disable_checkpoint_on_shutdown; + +statement ok +SET checkpoint_threshold='999999GB'; + +query I +SELECT * FROM bla +---- +84 + +statement ok +drop table bla + +statement ok +begin + +statement ok +create table bla as select 42; + +statement ok +drop table bla; + +statement ok +commit; + +restart + +statement ok +PRAGMA disable_checkpoint_on_shutdown; + +statement ok +SET checkpoint_threshold='999999GB'; + +statement ok +begin + +statement ok +create table bla as select 84; + +statement ok +alter table bla rename to bla2 + +statement ok +commit + +restart + +statement ok +PRAGMA disable_checkpoint_on_shutdown; + +statement ok +SET checkpoint_threshold='999999GB'; + +query I +from bla2 +---- +84 + +statement ok +begin + +statement ok +create or replace table bla as select 84; + +statement ok +create or replace table bla as select 42; + +statement ok +commit + +restart + +query I +from bla +---- +42 diff --git a/test/sql/storage/wal/wal_lazy_creation.test b/test/sql/storage/wal/wal_lazy_creation.test new file mode 100644 index 00000000000..522c7c55d22 --- /dev/null +++ b/test/sql/storage/wal/wal_lazy_creation.test @@ -0,0 +1,38 @@ +# name: test/sql/storage/wal/wal_lazy_creation.test +# description: Verify the WAL is lazily created when attaching. +# group: [wal] + +# If we enable alternative verification, then we disable checkpointing on shutdown. +# Thus, we'll keep the WAL alive when detaching the database. +require noalternativeverify + +require noforcestorage + +require skip_reload + +statement ok +ATTACH '__TEST_DIR__/attach_no_wal.db'; + +statement ok +CREATE TABLE attach_no_wal.integers(i INTEGER); + +statement ok +INSERT INTO attach_no_wal.integers FROM range(10000); + +statement ok +DETACH attach_no_wal; + +statement ok +ATTACH '__TEST_DIR__/attach_no_wal.db'; + +# Verify that we don't have a WAL after attaching. +query I +SELECT COUNT(*) FROM glob('__TEST_DIR__/attach_no_wal.db.wal'); +---- +0 + +# Verify that we checkpointed the WAL. +query I +SELECT COUNT(*) FROM attach_no_wal.integers; +---- +10000 \ No newline at end of file diff --git a/test/sql/storage/wal/wal_view_explicit_aliases.test b/test/sql/storage/wal/wal_view_explicit_aliases.test index 8056aa378a9..6a7375f4a43 100644 --- a/test/sql/storage/wal/wal_view_explicit_aliases.test +++ b/test/sql/storage/wal/wal_view_explicit_aliases.test @@ -4,10 +4,12 @@ require skip_reload - # load the DB from disk load __TEST_DIR__/view_explicit_aliases_storage.db +statement ok +set enable_view_dependencies=true + statement ok PRAGMA disable_checkpoint_on_shutdown @@ -34,12 +36,7 @@ statement ok SELECT * FROM test.v statement ok -DROP TABLE test.t - -# we can still query this after the table is gone -query II nosort view_info -PRAGMA table_info('test.v') ----- +DROP TABLE test.t CASCADE; loop i 0 2 @@ -50,25 +47,31 @@ statement ok PRAGMA disable_checkpoint_on_shutdown # can check info, but not query the view -query II nosort view_info +statement error PRAGMA table_info('test.v') ---- +Catalog Error: Table with name v does not exist! statement error SELECT * FROM test.v ---- -# we can query again after recreating the table statement ok CREATE TABLE test.t (a INTEGER, b INTEGER); statement ok SELECT * FROM test.t -statement ok +# we need to recreate the view to query 'v' after recreating the table + +statement error SELECT b,c FROM test.v +---- + +statement ok +CREATE VIEW test.v (b,c) AS SELECT * FROM test.t; statement ok -DROP TABLE test.t +DROP TABLE test.t CASCADE; endloop diff --git a/test/sql/storage/wal/wal_view_explicit_aliases_no_view_dependencies.test b/test/sql/storage/wal/wal_view_explicit_aliases_no_view_dependencies.test new file mode 100644 index 00000000000..1ae05c663d5 --- /dev/null +++ b/test/sql/storage/wal/wal_view_explicit_aliases_no_view_dependencies.test @@ -0,0 +1,74 @@ +# name: test/sql/storage/wal/wal_view_explicit_aliases_no_view_dependencies.test +# description: Test views with explicit column aliases +# group: [wal] + +require skip_reload + + +# load the DB from disk +load __TEST_DIR__/view_explicit_aliases_storage.db + +statement ok +PRAGMA disable_checkpoint_on_shutdown + +statement ok +PRAGMA wal_autocheckpoint='1TB'; + +# create a database and insert the table/view +statement ok +CREATE SCHEMA test; + +statement ok +CREATE TABLE test.t (a INTEGER, b INTEGER); + +# the view has aliases (b, c) +statement ok +CREATE VIEW test.v (b,c) AS SELECT * FROM test.t; + +# check the view info +query II nosort view_info +PRAGMA table_info('test.v') +---- + +statement ok +SELECT * FROM test.v + +statement ok +DROP TABLE test.t + +# we can still query this after the table is gone +query II nosort view_info +PRAGMA table_info('test.v') +---- + +loop i 0 2 + +# now reload +restart + +statement ok +PRAGMA disable_checkpoint_on_shutdown + +# can check info, but not query the view +query II nosort view_info +PRAGMA table_info('test.v') +---- + +statement error +SELECT * FROM test.v +---- + +# we can query again after recreating the table +statement ok +CREATE TABLE test.t (a INTEGER, b INTEGER); + +statement ok +SELECT * FROM test.t + +statement ok +SELECT b,c FROM test.v + +statement ok +DROP TABLE test.t + +endloop diff --git a/test/sql/storage/wal/wal_view_storage.test b/test/sql/storage/wal/wal_view_storage.test index 953332f6e4b..be0915a0aea 100644 --- a/test/sql/storage/wal/wal_view_storage.test +++ b/test/sql/storage/wal/wal_view_storage.test @@ -4,24 +4,23 @@ require skip_reload - # load the DB from disk load __TEST_DIR__/view_storage.db +statement ok +set enable_view_dependencies=true + statement ok PRAGMA disable_checkpoint_on_shutdown +# Make sure the WAL doesn't get flushed by a checkpoint statement ok PRAGMA wal_autocheckpoint='1TB'; -# create a schema and view +# Create a schema containing a table and a view statement ok CREATE SCHEMA test; - -statement ok CREATE TABLE test.t (a INTEGER, b INTEGER); - -statement ok CREATE VIEW test.v AS SELECT * FROM test.t; # read the info from the view @@ -31,21 +30,20 @@ PRAGMA table_info('test.v') 0 a INTEGER 0 NULL 0 1 b INTEGER 0 NULL 0 -# drop the table the view is based on -statement ok -DROP TABLE test.t - -# we can still query the types and column names -query IIIIII -PRAGMA table_info('test.v') +# Try to drop the table +statement error +drop table test.t; ---- -0 a INTEGER 0 NULL 0 -1 b INTEGER 0 NULL 0 +view "v" depends on table "t". + +# Now with CASCADE +statement ok +drop table test.t cascade; -# but querying the view fails statement error -SELECT * FROM test.v +PRAGMA table_info('test.v') ---- +Catalog Error: Table with name v does not exist! statement ok CREATE VIEW test.v2 AS SELECT 42 @@ -55,16 +53,14 @@ DROP VIEW test.v2 loop i 0 2 -# restart the system +# restart the system, causing the database to restore from the WAL restart -# the view still exists, but the table does not -# we can check the types, but not query it -query IIIIII +# the view no longer exists +statement error PRAGMA table_info('test.v') ---- -0 a INTEGER 0 NULL 0 -1 b INTEGER 0 NULL 0 +Catalog Error: Table with name v does not exist! statement error SELECT * FROM test.v @@ -77,8 +73,14 @@ CREATE TABLE test.t (a INTEGER, b INTEGER); statement ok SELECT * FROM test.t -statement ok +# We created the table, but the view still doesn't exist +statement error SELECT * FROM test.v +---- +Catalog Error: Table with name v does not exist! + +statement ok +CREATE VIEW test.v AS SELECT * FROM test.t; query IIIIII PRAGMA table_info('test.v') @@ -86,9 +88,15 @@ PRAGMA table_info('test.v') 0 a INTEGER 0 NULL 0 1 b INTEGER 0 NULL 0 -# drop the table again +# Try to drop the table +statement error +drop table test.t; +---- +view "v" depends on table "t". + +# Now with CASCADE statement ok -DROP TABLE test.t +drop table test.t cascade; statement error SELECT * FROM test.v2 diff --git a/test/sql/storage/wal/wal_view_storage_no_view_dependencies.test b/test/sql/storage/wal/wal_view_storage_no_view_dependencies.test new file mode 100644 index 00000000000..7214c3f4942 --- /dev/null +++ b/test/sql/storage/wal/wal_view_storage_no_view_dependencies.test @@ -0,0 +1,97 @@ +# name: test/sql/storage/wal/wal_view_storage_no_view_dependencies.test +# description: Create and drop a view over different runs +# group: [wal] + +require skip_reload + + +# load the DB from disk +load __TEST_DIR__/view_storage.db + +statement ok +PRAGMA disable_checkpoint_on_shutdown + +statement ok +PRAGMA wal_autocheckpoint='1TB'; + +# create a schema and view +statement ok +CREATE SCHEMA test; + +statement ok +CREATE TABLE test.t (a INTEGER, b INTEGER); + +statement ok +CREATE VIEW test.v AS SELECT * FROM test.t; + +# read the info from the view +query IIIIII +PRAGMA table_info('test.v') +---- +0 a INTEGER 0 NULL 0 +1 b INTEGER 0 NULL 0 + +# drop the table the view is based on +statement ok +DROP TABLE test.t + +# we can still query the types and column names +query IIIIII +PRAGMA table_info('test.v') +---- +0 a INTEGER 0 NULL 0 +1 b INTEGER 0 NULL 0 + +# but querying the view fails +statement error +SELECT * FROM test.v +---- + +statement ok +CREATE VIEW test.v2 AS SELECT 42 + +statement ok +DROP VIEW test.v2 + +loop i 0 2 + +# restart the system +restart + +# the view still exists, but the table does not +# we can check the types, but not query it +query IIIIII +PRAGMA table_info('test.v') +---- +0 a INTEGER 0 NULL 0 +1 b INTEGER 0 NULL 0 + +statement error +SELECT * FROM test.v +---- + +# after recreating the table, we can query the view again +statement ok +CREATE TABLE test.t (a INTEGER, b INTEGER); + +statement ok +SELECT * FROM test.t + +statement ok +SELECT * FROM test.v + +query IIIIII +PRAGMA table_info('test.v') +---- +0 a INTEGER 0 NULL 0 +1 b INTEGER 0 NULL 0 + +# drop the table again +statement ok +DROP TABLE test.t + +statement error +SELECT * FROM test.v2 +---- + +endloop diff --git a/test/sql/storage/wal_torn_write.cpp b/test/sql/storage/wal_torn_write.cpp index 803e4e77f8e..938d3d4f5b3 100644 --- a/test/sql/storage/wal_torn_write.cpp +++ b/test/sql/storage/wal_torn_write.cpp @@ -25,6 +25,7 @@ TEST_CASE("Test torn WAL writes", "[storage][.]") { LocalFileSystem lfs; config->options.checkpoint_wal_size = idx_t(-1); config->options.checkpoint_on_shutdown = false; + config->options.abort_on_wal_failure = false; idx_t wal_size_one_table; idx_t wal_size_two_table; // obtain the size of the WAL when writing one table, and then when writing two tables @@ -79,6 +80,7 @@ TEST_CASE("Test WAL checksums", "[storage][.]") { LocalFileSystem lfs; config->options.checkpoint_wal_size = idx_t(-1); config->options.checkpoint_on_shutdown = false; + config->options.abort_on_wal_failure = false; idx_t wal_size_one_table; idx_t wal_size_two_table; // obtain the size of the WAL when writing one table, and then when writing two tables diff --git a/test/sql/storage_version/storage_version.db b/test/sql/storage_version/storage_version.db index c816c3c219ae67be0cd4d3baba1882e446509dd2..0216bb14476417932e86d1ccf2ab05168062a7ba 100644 GIT binary patch delta 8845 zcmeHMdvsLQxu3oFnRlKflaL2_2?PZ4z(9BzCP+c0h_*gJuV|D3gTzRwh$3Vnl8hM0 zW0Rafv6(h5G6_^-rm(|BNYuM-Q(cBY*S$cnB(+u2vTDZSD!5vietXY3lR1Nn{?k91 zwI*}U?|VP?xA!@54(B4pzAdueEw#>{uX~FEn%w(tjTQ64l2h;JK0B%$T8c(=RiAe7R=j z(EDCfUe|1d=|k)9prh0#VTaB{i%Tc#;lhP!{kmkjw0#_He=dq6by%g*jdj`$4?zwEv-4`^~XHjS~XijMqS9_hF zStppTM*t~_?kv5Fi+Cb~>Y~Bvi8NxpjpLosD&83j_&lzno7zi-itadoCeh*biNb1} z%GzfWs_oBD;rNJ6#YYk$iX_=M2_;dh%S`PX^qk>(qRMbRNfETrX&aI`tvOkxHK&SD zYB%I@ygOCJyVC$)%(3%nDt10Y@NO%cF7#)p`1LG~8=UVqy!$?-->rmDn|X+mp7m63i@ zo+crOj(A7PPe{gZlKlR)IzpW<<2tlWuuwz43Sgry-zCr?$->qqB5) zb1nXY(2XyDhTj?oKl#+Tr5b;gBrfN@vJ7`7&_8U>r`@kC$Jb&6I_K4G$VHF6`T_1p z5J1P)2hd6S?baj6>urB+Au+Gjtx&T{$$4?0D`-FYgX zd!`5~p)!|esCTA{_ZA3zPvv6XDLz^f5cJI!iR&2@eaJ=JgmbznhB(^t zdITp9%vJRb%%>mhuu%?VqhSa`Sz(vMH0Et`=?G zyo{$p9-WWlX-budt9uy;r_y<@z}<48puDP>=juEy-kCyU_8Tn*C5-bcz;Lqcn@sf7 zUnL6QdN5Rh>qm-$7`nZB8u!}sqfie#4~ydcty;+TJ{&6B`)E*h%bT-Ah8_)-9bPG9 zM_u`x=2{gh>v|$w*7HQDtmny4*?}iRWe1)L$nGiMkStKQ5Ux}#p?pjf8&oiNd zo;8ZmNJx1ujXV&;74)qMHQcvW@bHr4)#w8q_};E8i$&G{9MA(LiB)<=CAmw5v7Q>C z*8M!FO{KmXF<9JXKog_eT`t-#Vm{8IPgA2s?YMz*F5S>5mj1v-McB$c9M}}}Ntt)P zO`$&fUJCl8wn^RQ(7@}q2nFSVjCF3|!oiGnz8adbkyp83ir=pbe2jj-W?_uHCR9b& zZ52h`Cj6{u7>mPIp|~#Mc2&xm*(A6LxpvUZ{R#3-!FTWAY!m1lSCjz)?%s(45!Y|$ zR?hFFU&|BewT2A(RgKAl)#k3|%4mPXBb><>xGSPh@H@8)L?+M^R3y;73pj0bm`>z0 z&n}Hmo*JQM+1?yp?LJ!4kV>8FBIrMAU`O1W&L#Tx2=|oY^wkO7d5so9YoH4o=khCG zLnxPTZzz|q35B;vXHAcUVW`gb zy2GGQINx_zqo?m(A${MzNEr8(&FL_E#8~R<3g)CMG+N)U6=y}}e8+-0VL`Q^=!1Ph zMV=F&C=pice4e7=6N zOcz!Bkf+)*PF>|63Kib72lS*q!{R;Haul%xGw>$l9X^_6kRO~(40K_Cf_G`V%K!}Y z^pTZJP9qQNRZ=27ye^KeygZTRNqCEax{GImmLBAF7uO>Co1QD)g`ZDCDtA)Xhdq(p zP|s;(0Lqud+j+srHM4d%-i`r!QP7W!enNzh+;SI5@Vc)WBe?lC|MW4Gy02P}5_BM% zi?>80KVhT)i~cBSIq0(Iqgn5GbWT`lnS#;?IC&rK{G|rFhC@~a+m??kQJkTAA)0Ik4e!CXRgEoyn#)q@%l*@Mg03RPz-G)UR-iA(Qc1U! zrLp!$QNIZ^p?FrGj(!{n6%w7O7w0W@d@FjFKnX_mZT~P595fU3N1VFG`T2g1*64^s znPN8jbo+#(x#%$-;|(UFg(LXxKu&liY3+tAHgq@g@Cto{*t!a|z!)Bijlucs9wRtN z5}n9f(s4DYz(xb7v+-=-UUZ75OMa{c4YK)e6fX*~;s_!JIinx9fD2{Zh1fuNtl~K8 z)ARH#?Llpl%2Lb|1+0&$d9=|zm9rs_CwVm=KNmWRW;6cN9(H?57B~3&QUNJ0OO+uAvqlHOuy+ zVo8S7KRc%43c&?dPE3!+(c$eeN{vmQVZHas%e$oT1r#hA?RmolflXu=QgIOmRp7@3 z3F>oM+p}hP4hmPt4M*qVj6fr?g|qNdV?}Ee-?f~|2fAQ)bQth$IPm9~FpfXQh5;kc zRvM*$f@7lw_%uEMR0IrzU1keoX@x_%MrLnf81TmUFyQNO;0hf2H9CfpwLpdL|6l{x zu$)c}19~Qe0mswAfVT8dK=07a2)o~h!hkn%08ruwkxCNAvPTL7s6Gt191aW`!ZR6qU0i)rUu}*(8KF=I&KP14boZ(o}~!2HwK=AE9}@PUmV0{Hs6jLBhXj!nIGbK zB&iH6YB~N3YFdHgO-j1%VDT$(mnHsVNXeL9#P?={I6SX@9A_CzbqMK@o=tch4@xj7 zli0P@_<)fQCX>7;iA2VM1Z)CoqhvXBAKBO(J1H=+(HHQY!O^W}cW=TSR<1(6ydBqY z4Fz&<1| zX0V|>_z)ID-8*n?xp0pk9c(g4rL%#3*r*qL=YEd65Z~=z(NAsFtgJ~6-A-j?1!4i< zDgclg89DJ}ImLrxg=feV;?@5j#F=_in5%cU;i(b_`Kuwhd=;ch1b4U%&l1f1olqLn zd+^8n%rb?YeixSn4>dL!l*X}@Bls=ibr)Ot2HXX6I#Xi5IfXw8?ie=qX)pd8kADj5 z>BrO(EK1D1(pW{Z9lGCZ+7Ez}n)U;rRkP{nUY0yCnfy?1 z;rSBL+Ox?DBk&cn+8pw`z)E3o;vC^o6te0fQY?xs7Fvva@+ZV<%XR2lG{pm8Co8m* zd!vL<#RFufXoO^B6{~o{Dv~2v9l8vWdOcjZ;qVWyWLB*uA+Kb_;~o&Zg=;dn7E9l< zXR?IHNePd|F2B5*9Aj`O$=7?e=a!XgNur6fu<{qk-^EF3%;TtWzg70@z^a-F+co?B zPsk2F3GDLI+sOf5D4RjNTHvobljY47WRVo%(D64x>GIQdtf#ZvV>w*FvYq7q2=ifB zx?*N|>x-vj_S7Cylq!*Df9jBP50M1<^dT56Qx1{c^4lHcEk+KL<>MUc+_Nh4Pl8{I za*g5FtX%8iSLNkAMg=GE%lY`n4c`cU0UwSbai!DgS;;A~Y@_*qR&PC8z2of#-^pLk zll;t-FU`er>2~rvR<{X1X1)FQb_O&V=$(mvWihSa{X}c}+K-Mg`(4uOvBnjjf4*Gj zyur>qAi;^>xmt>0BR`P5vrR=&x;ebzSnF%jBYNwS4Jl`yTijZ9@fc#{b!i$wI+nXr zDwKG~%70xir8C!?QVg*!DHt3Rt&vJ4Q&fDQaanx5w1*g!8_!3v#Yhd<6 z#@;tVJ%$mGj7|4`_i=XfGnZrJ&PFMN?c9W)x!u~gGw?kbfOaV)CfBpIWgFKlx`Pcg zO2g!Kzl1KR+t*44U=;RSs`5-#dFHA-xUky3`-|Vd{K_xK^9^@Ae7}JgPx`<=cyDLz zb_QFtii0e1$NCbGvq&PX87n? z{r5z}cjsH|(6{#eW-2^jo|V2QntyW;xLMJy5uP-osj)v@Zf{+O>Z}g~8Nd`WGhMXr=%F delta 5919 zcmZ`+33yXQ9?#56lh?FKFVfP3Hk6~>P0LjfZ7Qs;B8RRb`YDLeQjyZ4a*Fg-q)j>6 z!XQ%)rLL}x9MUBVgNP6oR_n1+V3l$QW#xt{h}B)l&dhrg^5VDozNUG<|Nr;D=Xi?0 z1t@-}_1GoXxlezXl{eyv;UitBz>(E!wzJ=me*ODSDV#lE(7*wP-+d+xp6r}lG%$DY z^WFl-pJQZPz34v^mYgZYlWIW{93pu;$DYZMzf&^b*mdsKXs_(tHYfrV8g`n{A$Kxr zdc%TF7ugx&GoeXSyYpW%mks+M0gaw&V@R_sWX%>XTfN z&htkLncs$ftW8{5V#H;KK_psQoW<-aF+#4yg~BB@#Swhs*Qxl0gN22x9)49W*LZ_uS(_yt_IYpwG zGdgj%y@f(sUtwR1sIH$7)j4^p@otcWic5L18k|Ddkjo91J|da%E2}^%I$dh=UM$^Z zG~Y=M1d0q2QfBo-t*;CKr;v5lG;jdToi)vTIFZQ!mGwdP*b525U zJpGr0l(|)KLkj;nblymKHW8hjor8AH8wEd%<7nRe*T7!1WBxvPDUkykUmXo@qhDX$ z3V!o`upnQu7-*fOBEuBwsi2}4OV~Gn=kjd>u%m|+n~_4z=uicp%;rHG=L5`^)l#;tV<&;YUniR`-O&Y1k*szF3RRnj1YMH0~~Kr@%je^UjGoqbxXeC zAt7rRsmUBX@{t1fj0)#8jS{k^G3c-Bx?tMvG?c!~iZ+x)FmlTnRDe69GmF)yM|nvC zi@Pvc+oNb-O%ML-Pl9Yl3oH9FsP1t_w3v90=;Ju<`lc%MjT21Yc*aC!)n@cs74MaQ ze5gnN)0EcyNhVLol#6}e`d#1#4|E#8F`8+p#!?Igg4AzEJ*%o)XDRVpu8CBKq+C)MS1M<3Vk;Nl0sQ^8%4r^TN<-Tv*6s7uC3+pnb?Ls?kt^ z9$nK>){Zwb%2|}ayf-XD1?!Sf+0rQFUtvRzI$kE`jmQjI840~#=VcM}0-DJdOL%}*q7{bKI; zf+?aNp=;2dwMn?|FqnuAt~OgD#b~Sv=Xll$j^{1zw9i^~5Z?;bWbO2$ILvoQ|2tHa zX-U;=`ri%pr4Gw`oZN!>c)H)GPpmPj%%fwwH=^m7&tmh&P*U?|L88ZW`kG9%VPyo$ ztG|yvjarkzn`os$iNu<>p~iY{M)8K4QMPk4`D?7K)C!?bYJolq4ccr{?Vy^q8KDLB zd@S@mpXiG7NvIG1UZLgRN3A}_Jk|f5Vwsj0tw!|+=m-tv-9DgEgX87@R2wfVo#=cX z=4VugPcj;|p08Tvb6vQWc+t<#g*ES2>w)B*w|g(}E_-K)4ISJ%eucy0&1za5gFf4P znf>;C(+yzf-(afur+xda-n|EbNrkUQlIjNNhE(GR35|8!;95v|p__N~`6p%X*6UwN zRFk9pF6C{waXSh%2Kt1e(ca$z>te`;7!csvzU6YPcdX-xG03ygi&8W-dDKK2a=}aq z`6nh(jen|95qeW{TS#p-@B(3%T}8>%9FS-uRr#QMB*htt#<*7dzl>WaX%B;^B1rid z@B_<9#guX2sth`ix?J$Aqy|xX7+B~vlU;vey(M2i2B`aABShX~bvBvr4tEw+Daw_f zYdQo10c{(y@8}5^7+D6J%-kxfp58?mb3rn-91Ju6-$3adX}B3Ak-W_iL+ZU4s==16 z0;eqa$qnE*i@#)`v_!?}J*3n|#%u)=ON=a80iyx)9j9hQmV5-f5#+(WpwY;PRPNWZ z_(=<{Vi4)^DX>P8{DZ(A>?5J2*b_|#p8+`PZm!2H?GFqNJqF4Dm z+(feQ7qG!hvI3xhyKQ+%mPwfe{}M$qVqlD}f8J~BFS1Oxu*qyP)3U~sO=<9Xb=;`n zT!b1at+!71Wk6!Gp(EH(tPF)R_TK|LkWDjs@!Wh&~2YOF~L1FAcQ0k^_|HhMdrV$e(| z)W*3KJy32qo~lO-|4Iu34s;3w_N0dan=?Xzh(bed*z?;U45)!Bpyf{~l~R}rGKK;5 z5n;fUaNvw7OyjUQ4ETqv2g(gwBK3%2wIvL=6AoO84%4`(8zP#_N!^H0;CtOfP~Z|D z07JRDA!LdcF;!jP8K7$-CwUDX?FcC8OwungU1Y3{N!}m@9h18H;50+C(oqU-Gj_yg1@A7c}E7$6+Mt zN!2_P{(4UZeiFB9N;GaBni#{QwQ1y4+tqOhk3#=)a@0$ft6 zOs>y>y^LIg?t4*qoD0Shhf7);h0ia9%edgVg;Ffe?k;u3rxcigca=l_-sd~QPF{Ww z!L{$hOq{(Ors6p#H0d{C(m4v`_e9^(pa6|6NF>zecUE$y25y4Xn}hA|eXZo^+i)A; z&-7fL7twXMZV7fPG`y=VL3Q*fuu{TXj=|peMk9>78^y7pGZy1;cDL}I&|#T4sS)<% zf>U9Fz*jH}Z*J5QIun$VQ;qNo6FK-HoD@N0>_KShN-gBGJ#asZxd-3Onb}n0^TDH5 zviECJqt|{=jZb~Vz6K_5SNAh^j1|w1%;2Z`msI0(@ z?sdf&X`FN_OgIhhX$8n-nO1N9li$N*zoPehxA*bP1mURw4 z+c1m4TUIc^M7Cao@3Hda@Ny99T(*$LJJ87btb){M-1egqwvr7tDV1Hka5>DdUKRRNW^PuzCzu<1c+lO15Xy*MD7O zDe&>n?w?;_WQeIzq$E;yQ7 zsBH%AKQaQLZ+h5>=S+}xP!}%DE-BvUzBMQA)&UlT?N;ZClX1Y*Nj%kQe94 zPeeqGh>bf`JmTGw6FUx(FBi(aB`Mxuz!k5`NhJ1lIo$|jV~Mj;c1ltA5BS0yC+KZ$xbKz%b|a{jk2?UWu>!2rPE&NOssS!{SQ}3dQt!Y diff --git a/test/sql/storage_version/storage_version.test_slow b/test/sql/storage_version/storage_version.test_slow index 8512e078a41..944864b20b0 100644 --- a/test/sql/storage_version/storage_version.test_slow +++ b/test/sql/storage_version/storage_version.test_slow @@ -48,11 +48,6 @@ SELECT * FROM date_values ORDER BY 1 1992-01-01 12:00:03 1992-09-20 10:00:03 NULL NULL NULL -query I -SELECT nextval('test3.bla') ----- -1 - query IIIII SELECT * FROM v1 ORDER BY 1 ---- @@ -191,3 +186,8 @@ SELECT i, V29(i) FROM integral_values ORDER BY 1 NULLS LAST ---- 1 1 NULL 1 + +statement error +SELECT nextval('test3.bla') +---- +read-only mode diff --git a/test/sql/subquery/complex/nested_correlated_list.test_slow b/test/sql/subquery/complex/nested_correlated_list.test_slow index dbf7450a8c3..59f3a23bd40 100644 --- a/test/sql/subquery/complex/nested_correlated_list.test_slow +++ b/test/sql/subquery/complex/nested_correlated_list.test_slow @@ -8,9 +8,6 @@ SET default_null_order='nulls_first'; statement ok PRAGMA enable_verification -# FIXME: bug in nested shuffle -require no_vector_verification - statement ok CREATE TABLE lists(l INTEGER[]); diff --git a/test/sql/subquery/exists/test_exists_union_by_name.test b/test/sql/subquery/exists/test_exists_union_by_name.test new file mode 100644 index 00000000000..8ed2ff80650 --- /dev/null +++ b/test/sql/subquery/exists/test_exists_union_by_name.test @@ -0,0 +1,24 @@ +# name: test/sql/subquery/exists/test_exists_union_by_name.test +# description: Test exists subquery with union by name +# group: [exists] + +statement ok +create table all_types as select * exclude(small_enum, medium_enum, large_enum) from test_all_types() limit 0; + +statement ok +SELECT ( + EXISTS( + ( + SELECT + DISTINCT outer_alltypes."BIGINT", outer_alltypes."INT" + FROM all_types inner_alltypes_1 + WHERE inner_alltypes_1."BIGINT" GROUP BY NULL + ) + UNION BY NAME + ( + SELECT inner2."FLOAT" from all_types inner2 + ) + ) IS DISTINCT FROM outer_alltypes."struct" + ) +FROM all_types outer_alltypes GROUP BY ALL; + diff --git a/test/sql/subquery/lateral/lateral_binding_views.test b/test/sql/subquery/lateral/lateral_binding_views.test new file mode 100644 index 00000000000..3fb630e907e --- /dev/null +++ b/test/sql/subquery/lateral/lateral_binding_views.test @@ -0,0 +1,19 @@ +# name: test/sql/subquery/lateral/lateral_binding_views.test +# description: Verify that views cannot reference lateral join columns +# group: [lateral] + +statement ok +copy (select date '2000-01-01' as dt) to '__TEST_DIR__/datetest.csv'; + +statement ok +create view v1 as select * from read_csv('__TEST_DIR__/datetest.csv', columns={'dt': date}); + +query I +from v1 +---- +2000-01-01 + +query II +select * from (select date '1992-01-01' as date), v1; +---- +1992-01-01 2000-01-01 diff --git a/test/sql/subquery/lateral/test_lateral_join.test b/test/sql/subquery/lateral/test_lateral_join.test index 91237b50440..1c1f2b556ff 100644 --- a/test/sql/subquery/lateral/test_lateral_join.test +++ b/test/sql/subquery/lateral/test_lateral_join.test @@ -13,6 +13,18 @@ select (select MIN(val) from unnest((select a)) t(val)) from (select ARRAY[1, 2, ---- 1 +query I +select (select MIN(val) from unnest((select (select a))) t(val)) from (select ARRAY[1, 2, 3, NULL]) t(a); +---- +1 + +query II +select * from (select array[1, 2, 3] a), unnest((select (select (select a)))) +---- +[1, 2, 3] 1 +[1, 2, 3] 2 +[1, 2, 3] 3 + query I select (select MIN(val) from unnest(a) t(val)) from (select ARRAY[1, 2, 3, NULL]) t(a); ---- diff --git a/test/sql/subquery/scalar/array_order_subquery.test b/test/sql/subquery/scalar/array_order_subquery.test index 13af1aa1816..759a93589e4 100644 --- a/test/sql/subquery/scalar/array_order_subquery.test +++ b/test/sql/subquery/scalar/array_order_subquery.test @@ -19,7 +19,6 @@ select ---- [4, 3, 2, 1] [4, 3, 2, 1] [4, 3, 2, 1] - # correlated query I select array(select unnest(l) AS i order by i desc nulls last) as a from (values ([NULL, 1, 2, 3, 4]), ([5, 6, NULL, 7, 8]), ([]), ([10, 11, 12])) t(l); @@ -47,6 +46,25 @@ SELECT ARRAY ---- [1, 2, 3] +# qualified names +query I +select + array(select distinct i from t order by t.i desc) as a +---- +[4, 3, 2, 1] + +query I +select + array(select distinct i from t union all select distinct i from t order by t.i desc) as a +---- +[4, 4, 3, 3, 2, 2, 1, 1] + +statement error +select + array(select distinct i from t order by x.i desc) as a +---- +Referenced table "x" not found + query I SELECT ARRAY (SELECT 1 UNION ALL diff --git a/test/sql/subquery/scalar/nested_subquery_window.test b/test/sql/subquery/scalar/nested_subquery_window.test new file mode 100644 index 00000000000..74a8d3ee51f --- /dev/null +++ b/test/sql/subquery/scalar/nested_subquery_window.test @@ -0,0 +1,21 @@ +# name: test/sql/subquery/scalar/nested_subquery_window.test +# description: Fuzzer issue - nested subquery inside a window function +# group: [scalar] + +statement ok +PRAGMA enable_verification + +query I +SELECT (SELECT max((SELECT subq_0.c0 AS c1))) FROM (SELECT NULL AS c0) AS subq_0; +---- +NULL + +query I +SELECT (SELECT max(42) OVER (PARTITION BY (SELECT subq_0.c0 AS c1)) AS c6) FROM (SELECT NULL AS c0) AS subq_0; +---- +42 + +query I +SELECT (SELECT max((SELECT subq_0.c0 AS c1)) OVER () AS c6) FROM (SELECT NULL AS c0) AS subq_0; +---- +NULL diff --git a/test/sql/subquery/scalar/test_correlated_window.test b/test/sql/subquery/scalar/test_correlated_window.test new file mode 100644 index 00000000000..450b172cc8a --- /dev/null +++ b/test/sql/subquery/scalar/test_correlated_window.test @@ -0,0 +1,54 @@ +# name: test/sql/subquery/scalar/test_correlated_window.test +# description: Test correlated window functions +# group: [scalar] + +statement ok +SET default_null_order='nulls_first'; + +statement ok +PRAGMA enable_verification + +statement ok +CREATE TABLE integers(i INTEGER); + +statement ok +INSERT INTO integers VALUES (1), (2), (3), (NULL); + +# FIXME - why not? +statement error +SELECT i, (SELECT SUM(i + 1) OVER ()) FROM integers ORDER BY i +---- +not supported + +query II +SELECT i, (SELECT SUM((SELECT i + 1)) OVER ()) FROM integers ORDER BY i +---- +NULL NULL +1 2 +2 3 +3 4 + +query II +SELECT i, (SELECT SUM((SELECT i + 1)) OVER () WHERE i>=2) FROM integers ORDER BY i +---- +NULL NULL +1 NULL +2 3 +3 4 + +# mix of aggregates and windows +query II +SELECT i, (SELECT SUM((SELECT SUM(i))) OVER ()) FROM integers GROUP BY i ORDER BY i +---- +NULL NULL +1 1 +2 2 +3 3 + +query II +SELECT i, (SELECT SUM(win) FROM (SELECT SUM((SELECT i1.i + integers.i)) OVER () AS win FROM integers i1) t) FROM integers ORDER BY i +---- +NULL NULL +1 36 +2 48 +3 60 diff --git a/test/sql/table_function/duckdb_columns.test b/test/sql/table_function/duckdb_columns.test index f9dc3c3a18f..cda0f58f4d9 100644 --- a/test/sql/table_function/duckdb_columns.test +++ b/test/sql/table_function/duckdb_columns.test @@ -2,6 +2,9 @@ # description: Test duckdb_columns function # group: [table_function] +statement ok +set storage_compatibility_version='v0.10.2' + require noforcestorage statement ok diff --git a/test/sql/table_function/duckdb_functions.test b/test/sql/table_function/duckdb_functions.test_slow similarity index 93% rename from test/sql/table_function/duckdb_functions.test rename to test/sql/table_function/duckdb_functions.test_slow index 2ccd7e4f265..f87f7a0e189 100644 --- a/test/sql/table_function/duckdb_functions.test +++ b/test/sql/table_function/duckdb_functions.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/table_function/duckdb_functions.test +# name: test/sql/table_function/duckdb_functions.test_slow # description: Test duckdb_functions function # group: [table_function] diff --git a/test/sql/table_function/range_function_lateral.test b/test/sql/table_function/range_function_lateral.test new file mode 100644 index 00000000000..63e53186049 --- /dev/null +++ b/test/sql/table_function/range_function_lateral.test @@ -0,0 +1,134 @@ +# name: test/sql/table_function/range_function_lateral.test +# description: Test range functions with lateral functions +# group: [table_function] + +statement ok +PRAGMA enable_verification + +query I +SELECT * FROM range(1, NULL, 1); +---- + +query II +SELECT * FROM (SELECT NULL a), range(a); +---- + +query II +SELECT * FROM (SELECT NULL a), range(timestamp '2010-01-01', a, null); +---- + +query II +SELECT * FROM range(3) t(i), range(i) t2(j) ORDER BY i, j; +---- +1 0 +2 0 +2 1 + +query III +SELECT * FROM range(4) t(i), range(i) t2(j), range(j) t3(k) ORDER BY i, j, k; +---- +2 1 0 +3 1 0 +3 2 0 +3 2 1 + +query III +SELECT * FROM generate_series(0,2) t(i), generate_series(0,i) t2(j), generate_series(0,j) t3(k) ORDER BY i, j, k; +---- +0 0 0 +1 0 0 +1 1 0 +1 1 1 +2 0 0 +2 1 0 +2 1 1 +2 2 0 +2 2 1 +2 2 2 + +query IIII +SELECT i, j, l, str FROM (SELECT ARRAY['null'], NULL, 'null' UNION ALL SELECT ARRAY['five'], 5, 'five' UNION ALL SELECT ARRAY['two'], 2, 'two') t(l, i, str), generate_series(0,i-1) t2(j) order by i, j +---- +2 0 [two] two +2 1 [two] two +5 0 [five] five +5 1 [five] five +5 2 [five] five +5 3 [five] five +5 4 [five] five + +query II +SELECT * FROM (SELECT 42 WHERE 42>84) t(i), range(i) t2(j) +---- + +statement error +SELECT * FROM (SELECT '5'::VARCHAR) t(str), range(str) t2(j) +---- +No function matches the given name and argument types + +statement ok +PREPARE v1 AS SELECT * FROM range(?); + +query I +EXECUTE v1(5) +---- +0 +1 +2 +3 +4 + +query IIII +SELECT * FROM (SELECT 3, 1, -1 UNION ALL SELECT 1, 3, 2) t(s, e, increment), range(s, e, increment) t2(j) ORDER BY s, j +---- +1 3 2 1 +3 1 -1 2 +3 1 -1 3 + +query IIII +SELECT * FROM (SELECT DATE '2000-01-01', DATE '2000-10-1', INTERVAL '3' MONTHS) t(s, e, increment), range(s, e, increment) t2(j) ORDER BY s, j +---- +2000-01-01 2000-10-01 3 months 2000-01-01 00:00:00 +2000-01-01 2000-10-01 3 months 2000-04-01 00:00:00 +2000-01-01 2000-10-01 3 months 2000-07-01 00:00:00 + +query IIII +SELECT * FROM (SELECT DATE '2000-01-01', DATE '2000-10-1', INTERVAL '3' MONTHS) t(s, e, increment), generate_series(s, e, increment) t2(j) ORDER BY s, j +---- +2000-01-01 2000-10-01 3 months 2000-01-01 00:00:00 +2000-01-01 2000-10-01 3 months 2000-04-01 00:00:00 +2000-01-01 2000-10-01 3 months 2000-07-01 00:00:00 +2000-01-01 2000-10-01 3 months 2000-10-01 00:00:00 + +query IIII +SELECT * FROM (SELECT DATE '2000-01-01', DATE '2000-10-1', NULL) t(s, e, increment), generate_series(s, e, increment) t2(j) ORDER BY s, j +---- + +# many rows +query I +select count(*) from (values (1), (10), (100), (1000), (10000)) t(a), range(a); +---- +11111 + +require icu + +statement ok +SET TimeZone='UTC' + +query IIII +SELECT * FROM (SELECT TIMESTAMPTZ '2000-01-01', TIMESTAMPTZ '2000-10-1', INTERVAL '3' MONTHS) t(s, e, increment), range(s, e, increment) t2(j) ORDER BY s, j +---- +2000-01-01 00:00:00+00 2000-10-01 00:00:00+00 3 months 2000-01-01 00:00:00+00 +2000-01-01 00:00:00+00 2000-10-01 00:00:00+00 3 months 2000-04-01 00:00:00+00 +2000-01-01 00:00:00+00 2000-10-01 00:00:00+00 3 months 2000-07-01 00:00:00+00 + +query IIII +SELECT * FROM (SELECT TIMESTAMPTZ '2000-01-01', TIMESTAMPTZ '2000-10-1', NULL) t(s, e, increment), range(s, e, increment) t2(j) ORDER BY s, j +---- + +query IIII +SELECT * FROM (SELECT TIMESTAMPTZ '2000-01-01', TIMESTAMPTZ '2000-10-1', NULL UNION ALL SELECT TIMESTAMPTZ '2000-10-01', TIMESTAMPTZ '2000-01-1', INTERVAL '-3 months') t(s, e, increment), range(s, e, increment) t2(j) ORDER BY s, j +---- +2000-10-01 00:00:00+00 2000-01-01 00:00:00+00 -3 months 2000-04-01 00:00:00+00 +2000-10-01 00:00:00+00 2000-01-01 00:00:00+00 -3 months 2000-07-01 00:00:00+00 +2000-10-01 00:00:00+00 2000-01-01 00:00:00+00 -3 months 2000-10-01 00:00:00+00 diff --git a/test/sql/table_function/range_timestamp.test b/test/sql/table_function/range_timestamp.test index 5bdcfb19bf0..103b97e7aee 100644 --- a/test/sql/table_function/range_timestamp.test +++ b/test/sql/table_function/range_timestamp.test @@ -115,6 +115,17 @@ SELECT COUNT(*) FROM generate_series(TIMESTAMP '1992-01-01 00:00:00', TIMESTAMP ---- 10228 +# null values result in no rows +query I +SELECT COUNT(*) FROM range(NULL, TIMESTAMP '1992-12-31 12:00:00', INTERVAL '1 MONTH') tbl(d) +---- +0 + +query I +SELECT COUNT(*) FROM generate_series(NULL, TIMESTAMP '1992-12-31 12:00:00', INTERVAL '1 MONTH') tbl(d) +---- +0 + # zero interval not supported statement error SELECT d FROM range(TIMESTAMP '1992-01-01 00:00:00', TIMESTAMP '1992-12-31 12:00:00', INTERVAL '0 MONTH') tbl(d) diff --git a/test/sql/transactions/test_read_only_transactions.test b/test/sql/transactions/test_read_only_transactions.test new file mode 100644 index 00000000000..46b6943ebb1 --- /dev/null +++ b/test/sql/transactions/test_read_only_transactions.test @@ -0,0 +1,30 @@ +# name: test/sql/transactions/test_read_only_transactions.test +# description: Test read only transactions +# group: [transactions] + +statement ok +PRAGMA enable_verification + +statement ok +CREATE TABLE a(i INTEGER) + +statement ok +INSERT INTO a VALUES (42) + +statement ok +BEGIN TRANSACTION READ ONLY + +# we can read from the database +query I +SELECT * FROM a +---- +42 + +# we cannot modify the database in a read-only transaction +statement error +INSERT INTO a VALUES (48) +---- +transaction is launched in read-only mode + +statement ok +COMMIT diff --git a/test/sql/types/date/date_implicit_cast.test b/test/sql/types/date/date_implicit_cast.test new file mode 100644 index 00000000000..eda2bb362b0 --- /dev/null +++ b/test/sql/types/date/date_implicit_cast.test @@ -0,0 +1,25 @@ +# name: test/sql/types/date/date_implicit_cast.test +# description: Test date implicit casts +# group: [date] + +statement ok +PRAGMA enable_verification + +foreach type timestamp timestamp_ms timestamp_ns timestamp_s + +statement ok +CREATE TABLE timestamps(ts ${type}) + +statement ok +INSERT INTO timestamps VALUES ('1993-08-14 00:00:00'), ('1993-08-15 01:01:02'), ('1993-08-16 00:00:00') + +query I +SELECT * FROM timestamps WHERE ts >= date '1993-08-15' +---- +1993-08-15 01:01:02 +1993-08-16 00:00:00 + +statement ok +DROP TABLE timestamps + +endloop diff --git a/test/sql/types/decimal/decimal_automatic_cast.test b/test/sql/types/decimal/decimal_automatic_cast.test index d614c83c0b9..582c6f6c010 100644 --- a/test/sql/types/decimal/decimal_automatic_cast.test +++ b/test/sql/types/decimal/decimal_automatic_cast.test @@ -18,7 +18,7 @@ SELECT [0.1, 1.33, 10.0, 9999999.999999999] query I SELECT [99999999999999999999999999999999999.9, 9.99999999999999999999999999999999999] ---- -[99999999999999999999999999999999999.900, 9.999] +[99999999999999999999999999999999999.900, 10.000] statement ok CREATE TABLE foo diff --git a/test/sql/types/decimal/test_decimal.test b/test/sql/types/decimal/test_decimal.test index 1a5ef352f0f..554775e8067 100644 --- a/test/sql/types/decimal/test_decimal.test +++ b/test/sql/types/decimal/test_decimal.test @@ -114,6 +114,17 @@ select '0.00003'::DECIMAL(38,10)::VARCHAR ---- 0.0000300000 +# Downcasting should round +query I +select CAST(33.846 AS DECIMAL(5,0)) d0; +---- +34 + +query I +select CAST(-33.846 AS DECIMAL(5,0)) d0; +---- +-34 + # various error conditions # scale must be bigger than or equal to width statement error diff --git a/test/sql/types/decimal/test_decimal_from_string.test b/test/sql/types/decimal/test_decimal_from_string.test index 1d5c318ca3a..08c5226a8e8 100644 --- a/test/sql/types/decimal/test_decimal_from_string.test +++ b/test/sql/types/decimal/test_decimal_from_string.test @@ -48,3 +48,8 @@ endloop endloop endloop + +statement error +select cast('9.99' as decimal(1,0)); +---- +Conversion Error: Could not convert string diff --git a/test/sql/types/enum/test_enum_from_query.test b/test/sql/types/enum/test_enum_from_query.test_slow similarity index 97% rename from test/sql/types/enum/test_enum_from_query.test rename to test/sql/types/enum/test_enum_from_query.test_slow index 5be718504b2..d9d1d68cd2e 100644 --- a/test/sql/types/enum/test_enum_from_query.test +++ b/test/sql/types/enum/test_enum_from_query.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/types/enum/test_enum_from_query.test +# name: test/sql/types/enum/test_enum_from_query.test_slow # description: ENUM tests # group: [enum] diff --git a/test/sql/types/interval/test_interval.test b/test/sql/types/interval/test_interval.test index 18cb49a893e..51bcad6f1f5 100644 --- a/test/sql/types/interval/test_interval.test +++ b/test/sql/types/interval/test_interval.test @@ -147,6 +147,11 @@ SELECT INTERVAL '90' YEAR; ---- 90 years +query T +SELECT INTERVAL '90' QUARTER; +---- +22 years 6 months + query T SELECT INTERVAL '90' MONTH; ---- diff --git a/test/sql/types/list/unnest_many_empty_lists.test b/test/sql/types/list/unnest_many_empty_lists.test_slow similarity index 82% rename from test/sql/types/list/unnest_many_empty_lists.test rename to test/sql/types/list/unnest_many_empty_lists.test_slow index cb04f1fb9ce..7c48da68d5a 100644 --- a/test/sql/types/list/unnest_many_empty_lists.test +++ b/test/sql/types/list/unnest_many_empty_lists.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/types/list/unnest_many_empty_lists.test +# name: test/sql/types/list/unnest_many_empty_lists.test_slow # description: Test unnest with many empty lists # group: [list] diff --git a/test/sql/types/list/unnest_table_function.test b/test/sql/types/list/unnest_table_function.test index 322783df97f..5b33cdc3203 100644 --- a/test/sql/types/list/unnest_table_function.test +++ b/test/sql/types/list/unnest_table_function.test @@ -70,29 +70,28 @@ SELECT i FROM UNNEST([]::INT[]) AS tbl(i); ---- # unnest from a subquery +# postgres returns an error here query I -SELECT * FROM UNNEST((SELECT [1,2,3] UNION ALL SELECT [4,5])); +SELECT * FROM UNNEST((SELECT ARRAY[1,2,3] UNION ALL SELECT ARRAY[1,2,3])); ---- 1 2 3 -4 -5 statement ok CREATE TABLE lists AS SELECT [1,2,3] l UNION ALL SELECT [4,5] UNION ALL SELECT [] UNION ALL SELECT [NULL] UNION ALL SELECT [7, 8]; query I -SELECT * FROM UNNEST((SELECT l FROM lists)); +SELECT u FROM lists, UNNEST(l) AS unnest(u) ORDER BY l, u; ---- 1 2 3 4 5 -NULL 7 8 +NULL # unnest with a prepared statement parameter statement ok @@ -156,3 +155,33 @@ SELECT k, a, b, a [4, 5, 5] [5, 7] [5] b [2, 3] [1, 2, 3, 4] [2, 3] c [2, 3] [4] [] + + +# aliases +query I +SELECT unnest FROM UNNEST(ARRAY[1,2,3]); +---- +1 +2 +3 + +query I +SELECT a FROM UNNEST(ARRAY[1,2,3]) t(a); +---- +1 +2 +3 + +query I +SELECT unnest FROM (SELECT ARRAY[1,2,3] AS x), UNNEST(x); +---- +1 +2 +3 + +query I +SELECT b FROM (SELECT ARRAY[1,2,3] AS x), UNNEST(x) t(b); +---- +1 +2 +3 diff --git a/test/sql/types/nested/array/array_sort.test b/test/sql/types/nested/array/array_sort.test_slow similarity index 95% rename from test/sql/types/nested/array/array_sort.test rename to test/sql/types/nested/array/array_sort.test_slow index 5c79241bcbb..e751f229ccb 100644 --- a/test/sql/types/nested/array/array_sort.test +++ b/test/sql/types/nested/array/array_sort.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/types/nested/array/array_sort.test +# name: test/sql/types/nested/array/array_sort.test_slow # group: [array] statement ok @@ -36,6 +36,21 @@ SELECT * FROM (VALUES (array_value(0,1,2,3,4,NULL,6,7,8,9)), (array_value(10,11, [0, 1, 2, 3, 4, NULL, 6, 7, 8, 9] +query I +SELECT * FROM (VALUES (array_value(0,1,2,NULL)), (array_value(10,11,NULL,13))) ORDER BY 1 ASC; +---- +[0, 1, 2, NULL] +[10, 11, NULL, 13] + +# (make sure we didnt break struct validity) +query I +SELECT * FROM (VALUES ({a: 0, b: 1, c: 2, d: NULL}), ({a: 10, b: 11, c: NULL, d: 13})) ORDER BY 1 ASC; +---- +{'a': 0, 'b': 1, 'c': 2, 'd': NULL} +{'a': 10, 'b': 11, 'c': NULL, 'd': 13} + + + # Nested larger array sorting query I SELECT * FROM (VALUES @@ -63,8 +78,8 @@ foreach COLLECTION_MIDDLE array_value list_value foreach COLLECTION_INNER array_value list_value query I -WITH - a(i) AS (SELECT * FROM range(0,2)), +WITH + a(i) AS (SELECT * FROM range(0,2)), b(i) AS (SELECT ${COLLECTION_INNER}(a1.i, a2.i) FROM a as a1, a as a2), c(i) AS (SELECT ${COLLECTION_MIDDLE}(b1.i, b2.i) FROM b as b1, b as b2) SELECT ${COLLECTION_OUTER}(c1.i, c2.i) FROM c as c1, c as c2 diff --git a/test/sql/types/nested/array/array_storage_2.test b/test/sql/types/nested/array/array_storage_2.test_slow similarity index 88% rename from test/sql/types/nested/array/array_storage_2.test rename to test/sql/types/nested/array/array_storage_2.test_slow index 99348055765..223d259bf87 100644 --- a/test/sql/types/nested/array/array_storage_2.test +++ b/test/sql/types/nested/array/array_storage_2.test_slow @@ -1,4 +1,4 @@ -# name: test/sql/types/nested/array/array_storage_2.test +# name: test/sql/types/nested/array/array_storage_2.test_slow # group: [array] load __TEST_DIR__/temp_array_storage_2.db diff --git a/test/sql/types/nested/map/test_map_concat.test b/test/sql/types/nested/map/test_map_concat.test index 470a20fbe0f..c686c904068 100644 --- a/test/sql/types/nested/map/test_map_concat.test +++ b/test/sql/types/nested/map/test_map_concat.test @@ -39,6 +39,12 @@ select map_concat(NULL, NULL); ---- NULL +# issue 12009 +query I +select map_concat(map([1], NULL), NULL) +---- +NULL + # Appending NULL to a non-empty map query I select map_concat(map([1], [1]), NULL); @@ -90,6 +96,9 @@ insert into tbl values map([5, 1337, 0], ['long', 'longer', 'longest']), map([], []), NULL +), +( + NULL, NULL, NULL ); query I @@ -98,12 +107,14 @@ select map_concat(x, y, z) from tbl; {3=1, 4=over_twelve_characters, 2=c, 1=a, 5=b, 7=NULL, 6=123} {42=small, 1=this is a long string, 0=tiny} {5=long, 1337=longer, 0=longest} +NULL query I select map_concat(x, y, z) from tbl where rowid != 0; ---- {42=small, 1=this is a long string, 0=tiny} {5=long, 1337=longer, 0=longest} +NULL query I select map_concat(x, y, z) from tbl where rowid == 1; diff --git a/test/sql/types/nested/map/test_map_entries.test b/test/sql/types/nested/map/test_map_entries.test index c3202243a42..e913f931f14 100644 --- a/test/sql/types/nested/map/test_map_entries.test +++ b/test/sql/types/nested/map/test_map_entries.test @@ -82,3 +82,28 @@ SELECT map_entries(map_from_entries( )); ---- [{'key': a, 'value': 5}, {'key': b, 'value': 6}, {'key': x, 'value': 21}, {'key': abc, 'value': 0}] + +query I +select MAP_ENTRIES(MAP([],[])) +---- +[] + +query I +select MAP_ENTRIES(MAP(NULL, NULL)) +---- +NULL + +query I +select MAP_ENTRIES(NULL) +---- +NULL + +query I +select MAP_ENTRIES(NULL::MAP("NULL", "NULL")) +---- +NULL + +query I +select MAP_ENTRIES(NULL::MAP(INT, BIGINT)) +---- +NULL diff --git a/test/sql/types/nested/map/test_map_keys.test b/test/sql/types/nested/map/test_map_keys.test index 0a5b70c5f4f..7b60efd445d 100644 --- a/test/sql/types/nested/map/test_map_keys.test +++ b/test/sql/types/nested/map/test_map_keys.test @@ -138,3 +138,28 @@ select map_keys(col) from filtered where idx % 2 != 0; ---- [6, 3, 87, 2] [9, 2, 7, 5, 8, 1] + +query I +select MAP_KEYS(MAP([],[])) +---- +[] + +query I +select MAP_KEYS(MAP(NULL, NULL)) +---- +NULL + +query I +select MAP_KEYS(NULL) +---- +NULL + +query I +select MAP_KEYS(NULL::MAP("NULL", "NULL")) +---- +NULL + +query I +select MAP_KEYS(NULL::MAP(INT, BIGINT)) +---- +NULL diff --git a/test/sql/types/nested/map/test_map_subscript.test b/test/sql/types/nested/map/test_map_subscript.test index 8ad48d29e48..4aa03da877d 100644 --- a/test/sql/types/nested/map/test_map_subscript.test +++ b/test/sql/types/nested/map/test_map_subscript.test @@ -205,3 +205,28 @@ from (SELECT a%4 as grp, list(a) as lsta, list(a) as lstb FROM range(7) tbl(a) g 1 {1=1, 5=5} [NULL] 2 {2=2, 6=6} [] 3 {3=3} [] + +query I +select MAP_EXTRACT(MAP([],[]), NULL) +---- +[] + +query I +select MAP_EXTRACT(MAP(NULL, NULL), NULL) +---- +[] + +query I +select MAP_EXTRACT(NULL, NULL) +---- +[] + +query I +select MAP_EXTRACT(NULL::MAP("NULL", "NULL"), NULL) +---- +[] + +query I +select MAP_EXTRACT(NULL::MAP(INT, BIGINT), NULL) +---- +[] diff --git a/test/sql/types/nested/map/test_map_values.test b/test/sql/types/nested/map/test_map_values.test index edb10bb14ae..b3a205ad24a 100644 --- a/test/sql/types/nested/map/test_map_values.test +++ b/test/sql/types/nested/map/test_map_values.test @@ -143,3 +143,28 @@ select map_values(col) from filtered where idx % 2 != 0; ---- [0, NULL, 5, NULL] [NULL, NULL, 4, 5, 6, 7] + +query I +select MAP_VALUES(MAP([],[])) +---- +[] + +query I +select MAP_VALUES(MAP(NULL, NULL)) +---- +NULL + +query I +select MAP_VALUES(NULL) +---- +NULL + +query I +select MAP_VALUES(NULL::MAP("NULL", "NULL")) +---- +NULL + +query I +select MAP_VALUES(NULL::MAP(INT, BIGINT)) +---- +NULL diff --git a/test/sql/types/nested/map/test_null_map_interaction.test b/test/sql/types/nested/map/test_null_map_interaction.test new file mode 100644 index 00000000000..f4e73f57346 --- /dev/null +++ b/test/sql/types/nested/map/test_null_map_interaction.test @@ -0,0 +1,45 @@ +# name: test/sql/types/nested/map/test_null_map_interaction.test +# group: [map] + +statement ok +pragma enable_verification + +query I +SELECT TYPEOF(MAP_KEYS(NULL::MAP(TEXT, BIGINT))); +---- +VARCHAR[] + +query I +SELECT TYPEOF(MAP_KEYS(NULL)); +---- +"NULL"[] + +query I +SELECT TYPEOF(MAP_VALUES(NULL::MAP(TEXT, BIGINT))); +---- +BIGINT[] + +query I +SELECT TYPEOF(MAP_VALUES(NULL)); +---- +"NULL"[] + +query I +SELECT TYPEOF(MAP_ENTRIES(NULL::MAP(TEXT, BIGINT))); +---- +STRUCT("key" VARCHAR, "value" BIGINT)[] + +query I +SELECT TYPEOF(MAP_ENTRIES(NULL)); +---- +STRUCT("key" "NULL", "value" "NULL")[] + +query I +SELECT TYPEOF(MAP_EXTRACT(NULL::MAP(TEXT, BIGINT), 'a')); +---- +BIGINT[] + +query I +SELECT TYPEOF(MAP_EXTRACT(NULL, 'a')); +---- +"NULL"[] diff --git a/test/sql/types/numeric/combinations/decimal_combinations.test b/test/sql/types/numeric/combinations/decimal_combinations.test index a375d93e864..f95a0061d73 100644 --- a/test/sql/types/numeric/combinations/decimal_combinations.test +++ b/test/sql/types/numeric/combinations/decimal_combinations.test @@ -46,11 +46,11 @@ DECIMAL # HUGEINT sets width to 38+scale, so it will never fit into DECIMAL statement error -select (typeof([(SELECT min from hugeint_limits), 1.00005])::VARCHAR)[:7] +select [(SELECT min from hugeint_limits), 1.00005] ---- statement error -select (typeof([(SELECT max from hugeint_limits), 1.00005])::VARCHAR)[:7] +select [(SELECT max from hugeint_limits), 1.00005] ---- endloop diff --git a/test/sql/types/struct/update_empty_row.test b/test/sql/types/struct/update_empty_row.test index af4c8b22cfe..deb5f869e2c 100644 --- a/test/sql/types/struct/update_empty_row.test +++ b/test/sql/types/struct/update_empty_row.test @@ -1,8 +1,8 @@ # name: test/sql/types/struct/update_empty_row.test -# description: Test storing structs in in-memory tables +# description: Test storing structs in in-memory tables. # group: [struct] statement error -UPDATE t0 SET ( c0 ) = ROW ( ); +UPDATE t0 SET (c0) = ROW(); ---- -target only expects 1 values, 0 were provided +expected 1 values, got 0 diff --git a/test/sql/types/test_all_types.test_slow b/test/sql/types/test_all_types.test_slow index 7d6facc7a37..3adbb314f69 100644 --- a/test/sql/types/test_all_types.test_slow +++ b/test/sql/types/test_all_types.test_slow @@ -8,8 +8,8 @@ PRAGMA enable_verification query IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII SELECT * FROM test_all_types(); ---- -False -128 -32768 -2147483648 -9223372036854775808 -170141183460469231731687303715884105728 0 0 0 0 0 5877642-06-25 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 1677-09-21 00:12:43.145225 00:00:00+15:59:59 290309-12-22 (BC) 00:00:00+00 -340282346638528859811704183484516925440.000000 -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 -999.9 -99999.9999 -999999999999.999999 -9999999999999999999999999999.9999999999 00000000-0000-0000-0000-000000000000 00:00:00 🦆🦆🦆🦆🦆🦆 thisisalongblob\x00withnullbytes 0010001001011100010101011010111 DUCK_DUCK_ENUM enum_0 enum_0 [] [] [] [] [] [] [] {'a': NULL, 'b': NULL} {'a': NULL, 'b': NULL} [] {} Frank [NULL, 2, 3] [a, NULL, c] [[NULL, 2, 3], NULL, [NULL, 2, 3]] [[a, NULL, c], NULL, [a, NULL, c]] [{'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, {'a': NULL, 'b': NULL}] {'a': [NULL, 2, 3], 'b': [a, NULL, c]} [[], [42, 999, NULL, NULL, -42], []] [[NULL, 2, 3], [4, 5, 6], [NULL, 2, 3]] -True 127 32767 2147483647 9223372036854775807 170141183460469231731687303715884105727 340282366920938463463374607431768211455 255 65535 4294967295 18446744073709551615 5881580-07-10 24:00:00 294247-01-10 04:00:54.775806 294247-01-10 04:00:54 294247-01-10 04:00:54.775 2262-04-11 23:47:16.854775 24:00:00-15:59:59 294247-01-10 04:00:54.775806+00 340282346638528859811704183484516925440.000000 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 999.9 99999.9999 999999999999.999999 9999999999999999999999999999.9999999999 ffffffff-ffff-ffff-ffff-ffffffffffff 83 years 3 months 999 days 00:16:39.999999 goo\0se \x00\x00\x00a 10101 GOOSE enum_299 enum_69999 [42, 999, NULL, NULL, -42] [42.0, nan, inf, -inf, NULL, -42.0] [1970-01-01, infinity, -infinity, NULL, 2022-05-12] [1970-01-01 00:00:00, infinity, -infinity, NULL, 2022-05-12 16:23:45] [1970-01-01 00:00:00+00, infinity, -infinity, NULL, 2022-05-12 23:23:45+00] [🦆🦆🦆🦆🦆🦆, goose, NULL, ] [[], [42, 999, NULL, NULL, -42], NULL, [], [42, 999, NULL, NULL, -42]] {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆} {'a': [42, 999, NULL, NULL, -42], 'b': [🦆🦆🦆🦆🦆🦆, goose, NULL, ]} [{'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, NULL] {key1=🦆🦆🦆🦆🦆🦆, key2=goose} 5 [4, 5, 6] [d, e, f] [[4, 5, 6], [NULL, 2, 3], [4, 5, 6]] [[d, e, f], [a, NULL, c], [d, e, f]] [{'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, {'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}] {'a': [4, 5, 6], 'b': [d, e, f]} [[42, 999, NULL, NULL, -42], [], [42, 999, NULL, NULL, -42]] [[4, 5, 6], [NULL, 2, 3], [4, 5, 6]] +False -128 -32768 -2147483648 -9223372036854775808 -170141183460469231731687303715884105728 0 0 0 0 0 5877642-06-25 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 1677-09-22 00:00:00 00:00:00+15:59:59 290309-12-22 (BC) 00:00:00+00 -340282346638528859811704183484516925440.000000 -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 -999.9 -99999.9999 -999999999999.999999 -9999999999999999999999999999.9999999999 00000000-0000-0000-0000-000000000000 00:00:00 🦆🦆🦆🦆🦆🦆 thisisalongblob\x00withnullbytes 0010001001011100010101011010111 DUCK_DUCK_ENUM enum_0 enum_0 [] [] [] [] [] [] [] {'a': NULL, 'b': NULL} {'a': NULL, 'b': NULL} [] {} Frank [NULL, 2, 3] [a, NULL, c] [[NULL, 2, 3], NULL, [NULL, 2, 3]] [[a, NULL, c], NULL, [a, NULL, c]] [{'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, {'a': NULL, 'b': NULL}] {'a': [NULL, 2, 3], 'b': [a, NULL, c]} [[], [42, 999, NULL, NULL, -42], []] [[NULL, 2, 3], [4, 5, 6], [NULL, 2, 3]] +True 127 32767 2147483647 9223372036854775807 170141183460469231731687303715884105727 340282366920938463463374607431768211455 255 65535 4294967295 18446744073709551615 5881580-07-10 24:00:00 294247-01-10 04:00:54.775806 294247-01-10 04:00:54 294247-01-10 04:00:54.775 2262-04-11 23:47:16.854775806 24:00:00-15:59:59 294247-01-10 04:00:54.775806+00 340282346638528859811704183484516925440.000000 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 999.9 99999.9999 999999999999.999999 9999999999999999999999999999.9999999999 ffffffff-ffff-ffff-ffff-ffffffffffff 83 years 3 months 999 days 00:16:39.999999 goo\0se \x00\x00\x00a 10101 GOOSE enum_299 enum_69999 [42, 999, NULL, NULL, -42] [42.0, nan, inf, -inf, NULL, -42.0] [1970-01-01, infinity, -infinity, NULL, 2022-05-12] [1970-01-01 00:00:00, infinity, -infinity, NULL, 2022-05-12 16:23:45] [1970-01-01 00:00:00+00, infinity, -infinity, NULL, 2022-05-12 23:23:45+00] [🦆🦆🦆🦆🦆🦆, goose, NULL, ] [[], [42, 999, NULL, NULL, -42], NULL, [], [42, 999, NULL, NULL, -42]] {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆} {'a': [42, 999, NULL, NULL, -42], 'b': [🦆🦆🦆🦆🦆🦆, goose, NULL, ]} [{'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, NULL] {key1=🦆🦆🦆🦆🦆🦆, key2=goose} 5 [4, 5, 6] [d, e, f] [[4, 5, 6], [NULL, 2, 3], [4, 5, 6]] [[d, e, f], [a, NULL, c], [d, e, f]] [{'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, {'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}] {'a': [4, 5, 6], 'b': [d, e, f]} [[42, 999, NULL, NULL, -42], [], [42, 999, NULL, NULL, -42]] [[4, 5, 6], [NULL, 2, 3], [4, 5, 6]] NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL statement ok diff --git a/test/sql/types/time/test_time_tz_collate.test b/test/sql/types/time/test_time_tz_collate.test new file mode 100644 index 00000000000..eb10178a374 --- /dev/null +++ b/test/sql/types/time/test_time_tz_collate.test @@ -0,0 +1,249 @@ +# name: test/sql/types/time/test_time_tz_collate.test +# description: Test Time With Time Zone +# group: [time] + +statement ok +PRAGMA enable_verification + +statement ok +CREATE TABLE timetzs (ttz TIMETZ); + +statement ok +INSERT INTO timetzs VALUES + (NULL), + ('00:00:00+1559'), + ('00:00:00+1558'), + ('02:30:00'), + ('02:30:00+04'), + ('02:30:00+04:30'), + ('02:30:00+04:30:45'), + ('16:15:03.123456'), + ('02:30:00+1200'), + ('02:30:00-1200'), + ('24:00:00-1558'), + ('24:00:00-1559'), +; + +# Comparison order is unintuitive: Positive offsets are before negative ones. +# This is similar to how a clock time east of Greenwich is earlier +# than the same clock time further west. +# Moreover, the time portions are compared by applying the offsets +# before comparing them as times + +foreach comparison_type timetz_byte_comparable( ( + +query I +SELECT ${comparison_type}'09:00:00+00:00'::TIMETZ) >${comparison_type}'09:01:00+01:00'::TIMETZ); +---- +True + +query I +SELECT ${comparison_type}'08:00:00+01:00'::TIMETZ) >${comparison_type}'09:01:00+01:00'::TIMETZ); +---- +False + +query I +SELECT ${comparison_type}'08:00:00+01:00'::TIMETZ) = ${comparison_type}'09:01:00+01:00'::TIMETZ); +---- +False + +query I +SELECT ${comparison_type}'08:01:00+00:00'::TIMETZ) = ${comparison_type}'09:01:00+01:00'::TIMETZ); +---- +False + +query I +SELECT ${comparison_type}'08:01:00+00:00'::TIMETZ) > ${comparison_type}'09:01:00+01:00'::TIMETZ); +---- +True + +query I +SELECT ${comparison_type}'08:02:00+00:00'::TIMETZ) > ${comparison_type}'09:01:00+01:00'::TIMETZ); +---- +True + +query I +SELECT ${comparison_type}'08:00:00+00:00'::TIMETZ) > ${comparison_type}'09:01:00+01:00'::TIMETZ); +---- +False + +query I +SELECT ${comparison_type}'10:01:00+02:00'::TIMETZ) > ${comparison_type}'09:01:00+01:00'::TIMETZ); +---- +False + +query I +SELECT * FROM timetzs ORDER BY ${comparison_type}ttz) +---- +00:00:00+15:59 +00:00:00+15:58 +02:30:00+12 +02:30:00+04:30:45 +02:30:00+04:30 +02:30:00+04 +02:30:00+00 +02:30:00-12 +16:15:03.123456+00 +24:00:00-15:58 +24:00:00-15:59 +NULL + +query IIIIIIII +SELECT + lhs.ttz, + rhs.ttz, + ${comparison_type}lhs.ttz) < ${comparison_type}rhs.ttz), + ${comparison_type}lhs.ttz) <= ${comparison_type}rhs.ttz), + ${comparison_type}lhs.ttz) = ${comparison_type}rhs.ttz), + ${comparison_type}lhs.ttz) >= ${comparison_type}rhs.ttz), + ${comparison_type}lhs.ttz) > ${comparison_type}rhs.ttz), + ${comparison_type}lhs.ttz) <> ${comparison_type}rhs.ttz), +FROM timetzs lhs, timetzs rhs +ORDER BY ${comparison_type}lhs.ttz), ${comparison_type}rhs.ttz) +---- +00:00:00+15:59 00:00:00+15:59 false true true true false false +00:00:00+15:59 00:00:00+15:58 true true false false false true +00:00:00+15:59 02:30:00+12 true true false false false true +00:00:00+15:59 02:30:00+04:30:45 true true false false false true +00:00:00+15:59 02:30:00+04:30 true true false false false true +00:00:00+15:59 02:30:00+04 true true false false false true +00:00:00+15:59 02:30:00+00 true true false false false true +00:00:00+15:59 02:30:00-12 true true false false false true +00:00:00+15:59 16:15:03.123456+00 true true false false false true +00:00:00+15:59 24:00:00-15:58 true true false false false true +00:00:00+15:59 24:00:00-15:59 true true false false false true +00:00:00+15:59 NULL NULL NULL NULL NULL NULL NULL +00:00:00+15:58 00:00:00+15:59 false false false true true true +00:00:00+15:58 00:00:00+15:58 false true true true false false +00:00:00+15:58 02:30:00+12 true true false false false true +00:00:00+15:58 02:30:00+04:30:45 true true false false false true +00:00:00+15:58 02:30:00+04:30 true true false false false true +00:00:00+15:58 02:30:00+04 true true false false false true +00:00:00+15:58 02:30:00+00 true true false false false true +00:00:00+15:58 02:30:00-12 true true false false false true +00:00:00+15:58 16:15:03.123456+00 true true false false false true +00:00:00+15:58 24:00:00-15:58 true true false false false true +00:00:00+15:58 24:00:00-15:59 true true false false false true +00:00:00+15:58 NULL NULL NULL NULL NULL NULL NULL +02:30:00+12 00:00:00+15:59 false false false true true true +02:30:00+12 00:00:00+15:58 false false false true true true +02:30:00+12 02:30:00+12 false true true true false false +02:30:00+12 02:30:00+04:30:45 true true false false false true +02:30:00+12 02:30:00+04:30 true true false false false true +02:30:00+12 02:30:00+04 true true false false false true +02:30:00+12 02:30:00+00 true true false false false true +02:30:00+12 02:30:00-12 true true false false false true +02:30:00+12 16:15:03.123456+00 true true false false false true +02:30:00+12 24:00:00-15:58 true true false false false true +02:30:00+12 24:00:00-15:59 true true false false false true +02:30:00+12 NULL NULL NULL NULL NULL NULL NULL +02:30:00+04:30:45 00:00:00+15:59 false false false true true true +02:30:00+04:30:45 00:00:00+15:58 false false false true true true +02:30:00+04:30:45 02:30:00+12 false false false true true true +02:30:00+04:30:45 02:30:00+04:30:45 false true true true false false +02:30:00+04:30:45 02:30:00+04:30 true true false false false true +02:30:00+04:30:45 02:30:00+04 true true false false false true +02:30:00+04:30:45 02:30:00+00 true true false false false true +02:30:00+04:30:45 02:30:00-12 true true false false false true +02:30:00+04:30:45 16:15:03.123456+00 true true false false false true +02:30:00+04:30:45 24:00:00-15:58 true true false false false true +02:30:00+04:30:45 24:00:00-15:59 true true false false false true +02:30:00+04:30:45 NULL NULL NULL NULL NULL NULL NULL +02:30:00+04:30 00:00:00+15:59 false false false true true true +02:30:00+04:30 00:00:00+15:58 false false false true true true +02:30:00+04:30 02:30:00+12 false false false true true true +02:30:00+04:30 02:30:00+04:30:45 false false false true true true +02:30:00+04:30 02:30:00+04:30 false true true true false false +02:30:00+04:30 02:30:00+04 true true false false false true +02:30:00+04:30 02:30:00+00 true true false false false true +02:30:00+04:30 02:30:00-12 true true false false false true +02:30:00+04:30 16:15:03.123456+00 true true false false false true +02:30:00+04:30 24:00:00-15:58 true true false false false true +02:30:00+04:30 24:00:00-15:59 true true false false false true +02:30:00+04:30 NULL NULL NULL NULL NULL NULL NULL +02:30:00+04 00:00:00+15:59 false false false true true true +02:30:00+04 00:00:00+15:58 false false false true true true +02:30:00+04 02:30:00+12 false false false true true true +02:30:00+04 02:30:00+04:30:45 false false false true true true +02:30:00+04 02:30:00+04:30 false false false true true true +02:30:00+04 02:30:00+04 false true true true false false +02:30:00+04 02:30:00+00 true true false false false true +02:30:00+04 02:30:00-12 true true false false false true +02:30:00+04 16:15:03.123456+00 true true false false false true +02:30:00+04 24:00:00-15:58 true true false false false true +02:30:00+04 24:00:00-15:59 true true false false false true +02:30:00+04 NULL NULL NULL NULL NULL NULL NULL +02:30:00+00 00:00:00+15:59 false false false true true true +02:30:00+00 00:00:00+15:58 false false false true true true +02:30:00+00 02:30:00+12 false false false true true true +02:30:00+00 02:30:00+04:30:45 false false false true true true +02:30:00+00 02:30:00+04:30 false false false true true true +02:30:00+00 02:30:00+04 false false false true true true +02:30:00+00 02:30:00+00 false true true true false false +02:30:00+00 02:30:00-12 true true false false false true +02:30:00+00 16:15:03.123456+00 true true false false false true +02:30:00+00 24:00:00-15:58 true true false false false true +02:30:00+00 24:00:00-15:59 true true false false false true +02:30:00+00 NULL NULL NULL NULL NULL NULL NULL +02:30:00-12 00:00:00+15:59 false false false true true true +02:30:00-12 00:00:00+15:58 false false false true true true +02:30:00-12 02:30:00+12 false false false true true true +02:30:00-12 02:30:00+04:30:45 false false false true true true +02:30:00-12 02:30:00+04:30 false false false true true true +02:30:00-12 02:30:00+04 false false false true true true +02:30:00-12 02:30:00+00 false false false true true true +02:30:00-12 02:30:00-12 false true true true false false +02:30:00-12 16:15:03.123456+00 true true false false false true +02:30:00-12 24:00:00-15:58 true true false false false true +02:30:00-12 24:00:00-15:59 true true false false false true +02:30:00-12 NULL NULL NULL NULL NULL NULL NULL +16:15:03.123456+00 00:00:00+15:59 false false false true true true +16:15:03.123456+00 00:00:00+15:58 false false false true true true +16:15:03.123456+00 02:30:00+12 false false false true true true +16:15:03.123456+00 02:30:00+04:30:45 false false false true true true +16:15:03.123456+00 02:30:00+04:30 false false false true true true +16:15:03.123456+00 02:30:00+04 false false false true true true +16:15:03.123456+00 02:30:00+00 false false false true true true +16:15:03.123456+00 02:30:00-12 false false false true true true +16:15:03.123456+00 16:15:03.123456+00 false true true true false false +16:15:03.123456+00 24:00:00-15:58 true true false false false true +16:15:03.123456+00 24:00:00-15:59 true true false false false true +16:15:03.123456+00 NULL NULL NULL NULL NULL NULL NULL +24:00:00-15:58 00:00:00+15:59 false false false true true true +24:00:00-15:58 00:00:00+15:58 false false false true true true +24:00:00-15:58 02:30:00+12 false false false true true true +24:00:00-15:58 02:30:00+04:30:45 false false false true true true +24:00:00-15:58 02:30:00+04:30 false false false true true true +24:00:00-15:58 02:30:00+04 false false false true true true +24:00:00-15:58 02:30:00+00 false false false true true true +24:00:00-15:58 02:30:00-12 false false false true true true +24:00:00-15:58 16:15:03.123456+00 false false false true true true +24:00:00-15:58 24:00:00-15:58 false true true true false false +24:00:00-15:58 24:00:00-15:59 true true false false false true +24:00:00-15:58 NULL NULL NULL NULL NULL NULL NULL +24:00:00-15:59 00:00:00+15:59 false false false true true true +24:00:00-15:59 00:00:00+15:58 false false false true true true +24:00:00-15:59 02:30:00+12 false false false true true true +24:00:00-15:59 02:30:00+04:30:45 false false false true true true +24:00:00-15:59 02:30:00+04:30 false false false true true true +24:00:00-15:59 02:30:00+04 false false false true true true +24:00:00-15:59 02:30:00+00 false false false true true true +24:00:00-15:59 02:30:00-12 false false false true true true +24:00:00-15:59 16:15:03.123456+00 false false false true true true +24:00:00-15:59 24:00:00-15:58 false false false true true true +24:00:00-15:59 24:00:00-15:59 false true true true false false +24:00:00-15:59 NULL NULL NULL NULL NULL NULL NULL +NULL 00:00:00+15:59 NULL NULL NULL NULL NULL NULL +NULL 00:00:00+15:58 NULL NULL NULL NULL NULL NULL +NULL 02:30:00+12 NULL NULL NULL NULL NULL NULL +NULL 02:30:00+04:30:45 NULL NULL NULL NULL NULL NULL +NULL 02:30:00+04:30 NULL NULL NULL NULL NULL NULL +NULL 02:30:00+04 NULL NULL NULL NULL NULL NULL +NULL 02:30:00+00 NULL NULL NULL NULL NULL NULL +NULL 02:30:00-12 NULL NULL NULL NULL NULL NULL +NULL 16:15:03.123456+00 NULL NULL NULL NULL NULL NULL +NULL 24:00:00-15:58 NULL NULL NULL NULL NULL NULL +NULL 24:00:00-15:59 NULL NULL NULL NULL NULL NULL +NULL NULL NULL NULL NULL NULL NULL NULL + +endloop diff --git a/test/sql/types/timestamp/alternative_timestamp_casts.test b/test/sql/types/timestamp/alternative_timestamp_casts.test index 130d4748e17..256b5751107 100644 --- a/test/sql/types/timestamp/alternative_timestamp_casts.test +++ b/test/sql/types/timestamp/alternative_timestamp_casts.test @@ -34,3 +34,51 @@ query I select '2023-12-08 08:51:39.123456'::TIMESTAMP_NS::TIME; ---- 08:51:39.123456 + +# Rounding +query I +select '2024-05-10 11:06:33.446'::TIMESTAMP_S; +---- +2024-05-10 11:06:33 + +query I +select '2024-05-10 11:06:33.846'::TIMESTAMP_S; +---- +2024-05-10 11:06:34 + +query I +select '2024-05-10 11:06:33.123446'::TIMESTAMP_MS; +---- +2024-05-10 11:06:33.123 + +query I +select '2024-05-10 11:06:33.123846'::TIMESTAMP_MS; +---- +2024-05-10 11:06:33.124 + +# Rounding +statement ok +CREATE TABLE issue11995 (t TIMESTAMP); + +statement ok +INSERT INTO issue11995 VALUES + ('2024-05-10 11:06:33.446'), + ('2024-05-10 11:06:33.846'), + ('2024-05-10 11:06:33.123446'), + ('2024-05-10 11:06:33.523846') +; + +query III +SELECT t, t::TIMESTAMP_MS, t::TIMESTAMP_S +FROM issue11995 +---- +2024-05-10 11:06:33.446 2024-05-10 11:06:33.446 2024-05-10 11:06:33 +2024-05-10 11:06:33.846 2024-05-10 11:06:33.846 2024-05-10 11:06:34 +2024-05-10 11:06:33.123446 2024-05-10 11:06:33.123 2024-05-10 11:06:33 +2024-05-10 11:06:33.523846 2024-05-10 11:06:33.524 2024-05-10 11:06:34 + +# Negative rounding +query I +select '1900-01-01 03:08:47'::TIMESTAMP::TIMESTAMP_MS; +---- +1900-01-01 03:08:47 diff --git a/test/sql/types/timestamp/test_timestamp.test b/test/sql/types/timestamp/test_timestamp.test index 4699bab623f..1dac51cb0cc 100644 --- a/test/sql/types/timestamp/test_timestamp.test +++ b/test/sql/types/timestamp/test_timestamp.test @@ -153,3 +153,9 @@ query T SELECT TIMESTAMP '100000-01-01 00:00:01.5'::VARCHAR ---- 100000-01-01 00:00:01.5 + +# Avoid infinite recursion. +statement error +SELECT CAST(REPEAT('1992-02-02 ', 100000) AS TIMESTAMP); +---- +Conversion Error: timestamp field value out of range diff --git a/test/sql/types/timestamp/test_timestamp_types.test b/test/sql/types/timestamp/test_timestamp_types.test index 87064765e95..297fa17b3d0 100644 --- a/test/sql/types/timestamp/test_timestamp_types.test +++ b/test/sql/types/timestamp/test_timestamp_types.test @@ -11,11 +11,10 @@ CREATE TABLE IF NOT EXISTS timestamp (sec TIMESTAMP_S, milli TIMESTAMP_MS,micro statement ok INSERT INTO timestamp VALUES ('2008-01-01 00:00:01','2008-01-01 00:00:01.594','2008-01-01 00:00:01.88926','2008-01-01 00:00:01.889268321' ) -#FIXME: The timestamp->string string->timestamp functions go only up to microsec right now query TTTT SELECT * from timestamp; ---- -2008-01-01 00:00:01 2008-01-01 00:00:01.594 2008-01-01 00:00:01.88926 2008-01-01 00:00:01.889268 +2008-01-01 00:00:01 2008-01-01 00:00:01.594 2008-01-01 00:00:01.88926 2008-01-01 00:00:01.889268321 # Apply Year Function query TTT @@ -32,7 +31,7 @@ SELECT nano::TIMESTAMP, milli::TIMESTAMP,sec::TIMESTAMP from timestamp; query TTT SELECT micro::TIMESTAMP_S, micro::TIMESTAMP_MS,micro::TIMESTAMP_NS from timestamp; ---- -2008-01-01 00:00:01 2008-01-01 00:00:01.889 2008-01-01 00:00:01.88926 +2008-01-01 00:00:02 2008-01-01 00:00:01.889 2008-01-01 00:00:01.88926 statement ok @@ -47,6 +46,34 @@ statement error select '90000-01-19 03:14:07.999999'::TIMESTAMP_US::TIMESTAMP_NS ---- +query I +SELECT s::TIMESTAMP_NS +FROM VALUES + ('2024-06-04 10:17:10.987654321'), + ('2024-06-04 10:17:10.98765432'), + ('2024-06-04 10:17:10.9876543'), + ('2024-06-04 10:17:10.9876543'), + ('2024-06-04 10:17:10.987654'), + ('2024-06-04 10:17:10.98765'), + ('2024-06-04 10:17:10.9876'), + ('2024-06-04 10:17:10.987'), + ('2024-06-04 10:17:10.98'), + ('2024-06-04 10:17:10.9'), + ('2024-06-04 10:17:10') +AS tbl(s) +---- +2024-06-04 10:17:10.987654321 +2024-06-04 10:17:10.98765432 +2024-06-04 10:17:10.9876543 +2024-06-04 10:17:10.9876543 +2024-06-04 10:17:10.987654 +2024-06-04 10:17:10.98765 +2024-06-04 10:17:10.9876 +2024-06-04 10:17:10.987 +2024-06-04 10:17:10.98 +2024-06-04 10:17:10.9 +2024-06-04 10:17:10 + # TIME conversions are now supported query I select sec::TIME from timestamp; @@ -113,9 +140,9 @@ select milli from timestamp order by milli; query T select nano from timestamp order by nano; ---- -2008-01-01 00:00:01.889268 -2008-01-01 00:00:01.899268 -2008-01-01 00:00:01.999268 +2008-01-01 00:00:01.889268321 +2008-01-01 00:00:01.899268321 +2008-01-01 00:00:01.999268321 #GROUP BY on each of these timestamp types statement ok @@ -127,9 +154,9 @@ INSERT INTO timestamp VALUES ('2008-01-01 00:00:11','2008-01-01 00:00:01.794','2 query TT select count(*), nano from timestamp group by nano order by nano; ---- -1 2008-01-01 00:00:01.889268 -2 2008-01-01 00:00:01.899268 -2 2008-01-01 00:00:01.999268 +1 2008-01-01 00:00:01.889268321 +2 2008-01-01 00:00:01.899268321 +2 2008-01-01 00:00:01.999268321 query TT select count(*), sec from timestamp group by sec order by sec; @@ -167,8 +194,8 @@ select timestamp.milli from timestamp inner join timestamp_two on (timestamp.mi query T select timestamp.nano from timestamp inner join timestamp_two on (timestamp.nano = timestamp_two.nano); ---- -2008-01-01 00:00:01.899268 -2008-01-01 00:00:01.899268 +2008-01-01 00:00:01.899268321 +2008-01-01 00:00:01.899268321 #Comparisons between all the different timestamp types (e.g. TIMESTAMP = TIMESTAMP_MS, etc) query T diff --git a/test/sql/types/timestamp/timestamp_precision.test b/test/sql/types/timestamp/timestamp_precision.test index 022dcfdb5ef..eeff391894e 100644 --- a/test/sql/types/timestamp/timestamp_precision.test +++ b/test/sql/types/timestamp/timestamp_precision.test @@ -16,11 +16,10 @@ CREATE TABLE ts_precision( statement ok INSERT INTO ts_precision VALUES ('2020-01-01 01:23:45.123456789', '2020-01-01 01:23:45.123456789', '2020-01-01 01:23:45.123456789', '2020-01-01 01:23:45.123456789'); -# FIXME: nano seconds do not render correctly query IIII SELECT sec::VARCHAR, msec::VARCHAR, micros::VARCHAR, nanos::VARCHAR FROM ts_precision ---- -2020-01-01 01:23:45 2020-01-01 01:23:45.123 2020-01-01 01:23:45.123456 2020-01-01 01:23:45.123456 +2020-01-01 01:23:45 2020-01-01 01:23:45.123 2020-01-01 01:23:45.123456 2020-01-01 01:23:45.123456789 query IIII SELECT EXTRACT(microseconds FROM sec), EXTRACT(microseconds FROM msec), EXTRACT(microseconds FROM micros), EXTRACT(microseconds FROM nanos) FROM ts_precision @@ -53,7 +52,7 @@ loop i 7 9 query I SELECT '2020-01-01 01:23:45.123456789'::TIMESTAMP(${i}) ---- -2020-01-01 01:23:45.123456 +2020-01-01 01:23:45.123456789 endloop diff --git a/test/sql/update/test_cascading_updates.test b/test/sql/update/test_cascading_updates.test new file mode 100644 index 00000000000..3319a6b4a05 --- /dev/null +++ b/test/sql/update/test_cascading_updates.test @@ -0,0 +1,71 @@ +# name: test/sql/update/test_cascading_updates.test +# description: Test many different updates +# group: [update] + +load __TEST_DIR__/cascading_updates.db + +statement ok +SET default_null_order='nulls_first'; + +statement ok +SET immediate_transaction_mode=true + +statement ok con1 +BEGIN + +statement ok +CREATE TABLE integers(id INTEGER, val INTEGER); + +statement ok +INSERT INTO integers SELECT i, i FROM range(10000) t(i) + +statement ok +PRAGMA checkpoint_threshold='1GB' + +statement ok +UPDATE integers SET val=val+1000000 WHERE id=1 + +statement ok con2 +BEGIN + +statement ok +UPDATE integers SET val=val+1000000 WHERE id=2 + +statement ok con3 +BEGIN + +statement ok +UPDATE integers SET val=val+1000000 WHERE id=3 + +statement ok con1 +COMMIT + +query I +SELECT COUNT(*) FROM integers WHERE val>1000000 +---- +3 + +# we cannot checkpoint because con2/con3 rely on older changes +statement error +CHECKPOINT +---- +Cannot CHECKPOINT + +# after committing, we can checkpoint +statement ok con2 +COMMIT + +statement ok con3 +COMMIT + +# even if con2 is active, we can still checkpoint +statement ok con2 +BEGIN + +statement ok +CHECKPOINT + +query I +SELECT COUNT(*) FROM integers WHERE val>1000000 +---- +3 diff --git a/test/sql/update/test_multiple_assignment.test b/test/sql/update/test_multiple_assignment.test index 66f320f5704..642dbeb99e6 100644 --- a/test/sql/update/test_multiple_assignment.test +++ b/test/sql/update/test_multiple_assignment.test @@ -48,14 +48,14 @@ SELECT * FROM tbl; statement error UPDATE tbl SET (key, fruit, cost) = (1, 2); ---- -Parser Error: Could not perform multiple assignment, target expects 3 values, only 2 were provided +expected 3 values, got 2 # too many values # --------------------------------------------------- statement error UPDATE tbl SET (key, fruit, cost) = (1, 2, 3, 4); ---- -Parser Error: Could not perform multiple assignment, target only expects 3 values, 4 were provided +expected 3 values, got 4 # functions should still work # --------------------------------------------------- diff --git a/test/sql/upsert/insert_or_replace/returning_nothing.test b/test/sql/upsert/insert_or_replace/returning_nothing.test new file mode 100644 index 00000000000..44d66c19a99 --- /dev/null +++ b/test/sql/upsert/insert_or_replace/returning_nothing.test @@ -0,0 +1,31 @@ +# name: test/sql/upsert/insert_or_replace/returning_nothing.test +# group: [insert_or_replace] + +statement ok +CREATE SEQUENCE seq START 1; + +statement ok +CREATE TABLE bug ( + id INTEGER PRIMARY KEY DEFAULT NEXTVAL('seq'), + name VARCHAR +); + +statement ok +CREATE UNIQUE INDEX idx ON bug (name); + +query I +INSERT OR IGNORE INTO bug VALUES + (DEFAULT, 'toto') RETURNING(id); +---- +1 + +query I +INSERT OR IGNORE INTO bug VALUES + (DEFAULT, 'toto') RETURNING(id); +---- + +query I +INSERT OR IGNORE INTO bug VALUES + (DEFAULT, 'toto'), (DEFAULT, 'yoyo') RETURNING(id); +---- +4 diff --git a/test/sql/upsert/postgres/composite_key.test b/test/sql/upsert/postgres/composite_key.test index 054c8077e69..fdf5db0780e 100644 --- a/test/sql/upsert/postgres/composite_key.test +++ b/test/sql/upsert/postgres/composite_key.test @@ -37,7 +37,7 @@ statement error insert into insertconflicttest values (0, 'Crowberry', 0) on conflict (key, fruit) do update set other = 1 where exists (select 1 from insertconflicttest ii where ii.key = excluded.key); ---- -Binder Error: conflict_target WHERE clause can not be a subquery +DO UPDATE SET clause cannot contain a subquery # inference succeeds: diff --git a/test/sql/upsert/upsert_conflict_in_different_chunk.test b/test/sql/upsert/upsert_conflict_in_different_chunk.test new file mode 100644 index 00000000000..aa5f88d998f --- /dev/null +++ b/test/sql/upsert/upsert_conflict_in_different_chunk.test @@ -0,0 +1,41 @@ +# name: test/sql/upsert/upsert_conflict_in_different_chunk.test +# group: [upsert] + +statement ok +PRAGMA enable_verification; + +statement ok +SET threads=1; + +statement ok +CREATE TABLE create_or_replace(i BIGINT PRIMARY KEY, s VARCHAR); + +statement ok +CREATE TABLE inserts (i BIGINT, s VARCHAR); + +statement ok +INSERT INTO inserts VALUES (1, 'hello'), (1, 'world'); + +# We cannot perform on-conflict handling in the same chunk. This is a known limitation. +statement maybe +INSERT OR REPLACE INTO create_or_replace SELECT i, s FROM inserts; +---- +PRIMARY KEY or UNIQUE constraint violated + +statement ok +DELETE FROM inserts; + +statement ok +INSERT INTO inserts (SELECT range, 'hello' FROM range(2050) UNION SELECT 1, 'world'); + +# We can perform on-conflict handling in a different chunk. Appending duplicated values with INSERT OR REPLACE in the +# same statement/transaction is currently not officially supported (known limitations). +# We fix it for this case, as we introduced changes in https://github.com/duckdb/duckdb/pull/7407 that would +# otherwise throw an InternalException in the segment tree: https://github.com/duckdb/duckdb/issues/11924. +statement ok +INSERT OR REPLACE INTO create_or_replace SELECT i, s FROM inserts; + +query II +FROM create_or_replace WHERE s != 'hello'; +---- +1 world \ No newline at end of file diff --git a/test/sql/upsert/upsert_lambda.test b/test/sql/upsert/upsert_lambda.test new file mode 100644 index 00000000000..74f5fb7fd31 --- /dev/null +++ b/test/sql/upsert/upsert_lambda.test @@ -0,0 +1,91 @@ +# name: test/sql/upsert/upsert_lambda.test +# group: [upsert] + +statement ok +PRAGMA enable_verification; + +statement ok +CREATE OR REPLACE TABLE foo ( + pk_col INT PRIMARY KEY, + str VARCHAR, + str_list VARCHAR[], + payload_col INT +); + +statement ok +INSERT INTO foo +SELECT 1, 'hello', ['x', 'y', 'z'], 40 +ON CONFLICT DO UPDATE SET + str = list_reduce(EXCLUDED.str_list, (x, y) -> x || '||' || y); + +query IIII +FROM foo; +---- +1 hello [x, y, z] 40 + +# Use the new (excluded) list as input. + +statement ok +INSERT INTO foo +SELECT 1, 'world', ['a', 'b', 'c'], 41 +ON CONFLICT DO UPDATE SET + str = list_reduce(EXCLUDED.str_list, (x, y) -> x || '||' || y); + +query IIII +FROM foo; +---- +1 a||b||c [x, y, z] 40 + +# Additionally update the payload. + +statement ok +INSERT INTO foo +SELECT 1, '', ['1', '2'], 42 +ON CONFLICT DO UPDATE SET + str = list_reduce(EXCLUDED.str_list, (x, y) -> x || '||' || y), + payload_col = EXCLUDED.payload_col; + +query IIII +FROM foo; +---- +1 1||2 [x, y, z] 42 + +# Use the existing list as input. + +statement ok +INSERT INTO foo +SELECT 1, '', ['l', 'm', 'n'], 43 +ON CONFLICT DO UPDATE SET + str = list_reduce(str_list, (x, y) -> x || '||' || y); + +query IIII +FROM foo; +---- +1 x||y||z [x, y, z] 42 + +# Reference the existing and the new (excluded) str column without qualification. + +statement ok +INSERT INTO foo +SELECT 1, 'world', ['s', 't'], 42 +ON CONFLICT DO UPDATE SET + str = list_reduce(EXCLUDED.str_list, (x, y) -> x || str || y || EXCLUDED.str); + +query IIII +FROM foo; +---- +1 sx||y||ztworld [x, y, z] 42 + +# Lambda function in the WHERE clause. + +statement ok +INSERT INTO foo +SELECT 1, 'motorcycle', ['brrr', 'brrrrrr'], 1042 +ON CONFLICT DO UPDATE SET + str = 'black-bellied whistling duck' + WHERE list_reduce(EXCLUDED.str_list, (x, y) -> x || str || y || EXCLUDED.str) = 'brrrsx||y||ztworldbrrrrrrmotorcycle'; + +query IIII +FROM foo; +---- +1 black-bellied whistling duck [x, y, z] 42 diff --git a/test/sql/vacuum/test_analyze.test b/test/sql/vacuum/test_analyze.test index 3bee1c017ed..5c4913a35ae 100644 --- a/test/sql/vacuum/test_analyze.test +++ b/test/sql/vacuum/test_analyze.test @@ -1,98 +1,100 @@ # name: test/sql/vacuum/test_analyze.test -# description: Test ANALYZE statement +# description: Test the ANALYZE statement. # group: [vacuum] -# need this, else the distinct stats sampling is different +# The distinct statistics sampling relies on the vector size. require vector_size 1024 require skip_reload -# distinct stats sampling is different for different vector sizes +# Distinct statistics sampling is different for different vector sizes. require no_vector_verification statement ok -analyze +ANALYZE; statement ok -vacuum; +VACUUM; statement error -vacuum test +VACUUM test; ---- +Table with name test does not exist statement error -analyze test +ANALYZE test; ---- +Table with name test does not exist statement ok -create table test (i int, j int) +CREATE TABLE test (i INT, j INT); statement ok -analyze test +ANALYZE test; statement ok -create view testview as select * from test +CREATE VIEW testview AS SELECT * FROM test; statement error -analyze testview +ANALYZE testview; ---- +can only vacuum or analyze base tables statement ok -insert into test select range % 5000, range % 5000 from range(10000) +INSERT INTO test SELECT range % 5000, range % 5000 FROM range(10000); -# inaccurate approx unique due to sampling +# The approximate unique count is inaccurate due to sampling. query T -select stats(i) from test limit 1 +SELECT stats(i) FROM test LIMIT 1; ---- [Min: 0, Max: 4999][Has Null: false, Has No Null: true][Approx Unique: 9435] query T -select stats(j) from test limit 1 +SELECT stats(j) FROM test LIMIT 1; ---- [Min: 0, Max: 4999][Has Null: false, Has No Null: true][Approx Unique: 9435] -# we enable verify_parallelism only for ANALYZE statement ok -pragma verify_parallelism +PRAGMA verify_parallelism; statement ok -analyze test(i) +ANALYZE test(i); statement ok -vacuum test(i) +VACUUM test(i); statement ok -pragma disable_verify_parallelism +PRAGMA disable_verify_parallelism; -# i is more accurate now +# The approximate unique count for i is more accurate now. query T -select stats(i) from test limit 1 +SELECT stats(i) FROM test LIMIT 1; ---- [Min: 0, Max: 4999][Has Null: false, Has No Null: true][Approx Unique: 5080] -# j is not yet accurate +# The approximate unique count for j is not yet accurate. query T -select stats(j) from test limit 1 +SELECT stats(j) FROM test LIMIT 1; ---- [Min: 0, Max: 4999][Has Null: false, Has No Null: true][Approx Unique: 9435] -# now we analyze the whole table +# Now we analyze the entire table. statement ok -pragma verify_parallelism +PRAGMA verify_parallelism; statement ok -analyze test +ANALYZE test; statement ok -pragma disable_verify_parallelism +PRAGMA disable_verify_parallelism; -# both i and j should be more accurate +# The approximate unique count for i and j is more accurate now. query T -select stats(i) from test limit 1 +SELECT stats(i) FROM test LIMIT 1; ---- [Min: 0, Max: 4999][Has Null: false, Has No Null: true][Approx Unique: 5080] query T -select stats(j) from test limit 1 +SELECT stats(j) FROM test LIMIT 1; ---- -[Min: 0, Max: 4999][Has Null: false, Has No Null: true][Approx Unique: 5080] +[Min: 0, Max: 4999][Has Null: false, Has No Null: true][Approx Unique: 5080] \ No newline at end of file diff --git a/test/sql/vacuum/vacuum_nested_types.test b/test/sql/vacuum/vacuum_nested_types.test index ff1e1706858..5c862798385 100644 --- a/test/sql/vacuum/vacuum_nested_types.test +++ b/test/sql/vacuum/vacuum_nested_types.test @@ -3,10 +3,10 @@ # group: [vacuum] statement ok -CREATE TABLE test (x INT[], y AS (x || 100)); +CREATE TABLE test (x INT[], y AS (x || [100])); statement ok ANALYZE test(y, x); statement ok -INSERT INTO test SELECT [range % 5000] FROM range(10000); \ No newline at end of file +INSERT INTO test SELECT [range % 5000] FROM range(10000); diff --git a/test/sql/window/test_order_by_all.test b/test/sql/window/test_order_by_all.test new file mode 100644 index 00000000000..4420239052c --- /dev/null +++ b/test/sql/window/test_order_by_all.test @@ -0,0 +1,16 @@ +# name: test/sql/window/test_order_by_all.test +# description: Window Order By All +# group: [window] + +statement ok +PRAGMA enable_verification + +statement error +SELECT i, j, ROW_NUMBER() OVER (ORDER BY ALL) AS rn +FROM ( + SELECT i ,j + FROM generate_series(1, 5) s(i) + CROSS JOIN generate_series(1, 2) t(j) +) t; +---- +Cannot ORDER BY ALL in a window expression diff --git a/test/sql/window/test_streaming_lead_lag.test b/test/sql/window/test_streaming_lead_lag.test new file mode 100644 index 00000000000..fe989734905 --- /dev/null +++ b/test/sql/window/test_streaming_lead_lag.test @@ -0,0 +1,156 @@ +# name: test/sql/window/test_streaming_lead_lag.test +# description: Streaming window functions +# group: [window] + +statement ok +PRAGMA enable_verification + +statement ok +PRAGMA explain_output = PHYSICAL_ONLY; + +query TT +EXPLAIN +SELECT i, LAG(i, 1) OVER() AS i1 +FROM range(10) tbl(i); +---- +physical_plan :.*STREAMING_WINDOW.* + +query II +SELECT i, LAG(i, 1) OVER() AS i1 +FROM range(10) tbl(i); +---- +0 NULL +1 0 +2 1 +3 2 +4 3 +5 4 +6 5 +7 6 +8 7 +9 8 + +query TT +EXPLAIN +SELECT i, LAG(i, -1) OVER() AS i1 +FROM range(10) tbl(i); +---- +physical_plan :.*STREAMING_WINDOW.* + +query TT +EXPLAIN +SELECT i, LEAD(i, -1) OVER() AS i1 +FROM range(10) tbl(i); +---- +physical_plan :.*STREAMING_WINDOW.* + +query II +SELECT i, LEAD(i, -1) OVER() AS i1 +FROM range(10) tbl(i); +---- +0 NULL +1 0 +2 1 +3 2 +4 3 +5 4 +6 5 +7 6 +8 7 +9 8 + +query TT +EXPLAIN +SELECT i, LEAD(i, 1) OVER() AS i1 +FROM range(10) tbl(i); +---- +physical_plan :.*STREAMING_WINDOW.* + +# Test shift down +query TT +EXPLAIN +SELECT i, LAG(i, 1) OVER() AS i1 +FROM range(3000) tbl(i) +WHERE i % 2 = 0 +QUALIFY i1 <> i - 2 +---- +physical_plan :.*STREAMING_WINDOW.* + +query TT +SELECT i, LAG(i, 1) OVER() AS i1 +FROM range(3000) tbl(i) +WHERE i % 2 = 0 +QUALIFY i1 <> i - 2 +---- + +# Test constant default value +query TT +EXPLAIN +SELECT i, LAG(i, 1, 50) OVER() AS i1 +FROM range(10) tbl(i); +---- +physical_plan :.*STREAMING_WINDOW.* + +query II +SELECT i, LAG(i, 1, 50) OVER() AS i1 +FROM range(10) tbl(i); +---- +0 50 +1 0 +2 1 +3 2 +4 3 +5 4 +6 5 +7 6 +8 7 +9 8 + +# Test all data types +query II +EXPLAIN +SELECT + lag(COLUMNS(*), 1) OVER (), + lead(COLUMNS(*), -1) OVER() +FROM test_all_types() +---- +physical_plan :.*STREAMING_WINDOW.* + +query IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII +SELECT + lag(COLUMNS(*), 1) OVER (), + lead(COLUMNS(*), -1) OVER() +FROM test_all_types() +---- +NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL +false -128 -32768 -2147483648 -9223372036854775808 -170141183460469231731687303715884105728 0 0 0 0 0 5877642-06-25 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 1677-09-22 00:00:00 00:00:00+15:59:59 290309-12-22 (BC) 00:00:00+00 -3.4028235e+38 -1.7976931348623157e+308 -999.9 -99999.9999 -999999999999.999999 -9999999999999999999999999999.9999999999 00000000-0000-0000-0000-000000000000 00:00:00 🦆🦆🦆🦆🦆🦆 thisisalongblob\x00withnullbytes 0010001001011100010101011010111 DUCK_DUCK_ENUM enum_0 enum_0 [] [] [] [] [] [] [] {'a': NULL, 'b': NULL} {'a': NULL, 'b': NULL} [] {} Frank [NULL, 2, 3] [a, NULL, c] [[NULL, 2, 3], NULL, [NULL, 2, 3]] [[a, NULL, c], NULL, [a, NULL, c]] [{'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, {'a': NULL, 'b': NULL}] {'a': [NULL, 2, 3], 'b': [a, NULL, c]} [[], [42, 999, NULL, NULL, -42], []] [[NULL, 2, 3], [4, 5, 6], [NULL, 2, 3]] false -128 -32768 -2147483648 -9223372036854775808 -170141183460469231731687303715884105728 0 0 0 0 0 5877642-06-25 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 290309-12-22 (BC) 00:00:00 1677-09-22 00:00:00 00:00:00+15:59:59 290309-12-22 (BC) 00:00:00+00 -3.4028235e+38 -1.7976931348623157e+308 -999.9 -99999.9999 -999999999999.999999 -9999999999999999999999999999.9999999999 00000000-0000-0000-0000-000000000000 00:00:00 🦆🦆🦆🦆🦆🦆 thisisalongblob\x00withnullbytes 0010001001011100010101011010111 DUCK_DUCK_ENUM enum_0 enum_0 [] [] [] [] [] [] [] {'a': NULL, 'b': NULL} {'a': NULL, 'b': NULL} [] {} Frank [NULL, 2, 3] [a, NULL, c] [[NULL, 2, 3], NULL, [NULL, 2, 3]] [[a, NULL, c], NULL, [a, NULL, c]] [{'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, {'a': NULL, 'b': NULL}] {'a': [NULL, 2, 3], 'b': [a, NULL, c]} [[], [42, 999, NULL, NULL, -42], []] [[NULL, 2, 3], [4, 5, 6], [NULL, 2, 3]] +true 127 32767 2147483647 9223372036854775807 170141183460469231731687303715884105727 340282366920938463463374607431768211455 255 65535 4294967295 18446744073709551615 5881580-07-10 24:00:00 294247-01-10 04:00:54.775806 294247-01-10 04:00:54 294247-01-10 04:00:54.775 2262-04-11 23:47:16.854775806 24:00:00-15:59:59 294247-01-10 04:00:54.775806+00 3.4028235e+38 1.7976931348623157e+308 999.9 99999.9999 999999999999.999999 9999999999999999999999999999.9999999999 ffffffff-ffff-ffff-ffff-ffffffffffff 83 years 3 months 999 days 00:16:39.999999 goo\0se \x00\x00\x00a 10101 GOOSE enum_299 enum_69999 [42, 999, NULL, NULL, -42] [42.0, nan, inf, -inf, NULL, -42.0] [1970-01-01, infinity, -infinity, NULL, 2022-05-12] [1970-01-01 00:00:00, infinity, -infinity, NULL, 2022-05-12 16:23:45] [1970-01-01 00:00:00+00, infinity, -infinity, NULL, 2022-05-12 23:23:45+00] [🦆🦆🦆🦆🦆🦆, goose, NULL, ] [[], [42, 999, NULL, NULL, -42], NULL, [], [42, 999, NULL, NULL, -42]] {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆} {'a': [42, 999, NULL, NULL, -42], 'b': [🦆🦆🦆🦆🦆🦆, goose, NULL, ]} [{'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, NULL] {key1=🦆🦆🦆🦆🦆🦆, key2=goose} 5 [4, 5, 6] [d, e, f] [[4, 5, 6], [NULL, 2, 3], [4, 5, 6]] [[d, e, f], [a, NULL, c], [d, e, f]] [{'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, {'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}] {'a': [4, 5, 6], 'b': [d, e, f]} [[42, 999, NULL, NULL, -42], [], [42, 999, NULL, NULL, -42]] [[4, 5, 6], [NULL, 2, 3], [4, 5, 6]] true 127 32767 2147483647 9223372036854775807 170141183460469231731687303715884105727 340282366920938463463374607431768211455 255 65535 4294967295 18446744073709551615 5881580-07-10 24:00:00 294247-01-10 04:00:54.775806 294247-01-10 04:00:54 294247-01-10 04:00:54.775 2262-04-11 23:47:16.854775806 24:00:00-15:59:59 294247-01-10 04:00:54.775806+00 3.4028235e+38 1.7976931348623157e+308 999.9 99999.9999 999999999999.999999 9999999999999999999999999999.9999999999 ffffffff-ffff-ffff-ffff-ffffffffffff 83 years 3 months 999 days 00:16:39.999999 goo\0se \x00\x00\x00a 10101 GOOSE enum_299 enum_69999 [42, 999, NULL, NULL, -42] [42.0, nan, inf, -inf, NULL, -42.0] [1970-01-01, infinity, -infinity, NULL, 2022-05-12] [1970-01-01 00:00:00, infinity, -infinity, NULL, 2022-05-12 16:23:45] [1970-01-01 00:00:00+00, infinity, -infinity, NULL, 2022-05-12 23:23:45+00] [🦆🦆🦆🦆🦆🦆, goose, NULL, ] [[], [42, 999, NULL, NULL, -42], NULL, [], [42, 999, NULL, NULL, -42]] {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆} {'a': [42, 999, NULL, NULL, -42], 'b': [🦆🦆🦆🦆🦆🦆, goose, NULL, ]} [{'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, NULL] {key1=🦆🦆🦆🦆🦆🦆, key2=goose} 5 [4, 5, 6] [d, e, f] [[4, 5, 6], [NULL, 2, 3], [4, 5, 6]] [[d, e, f], [a, NULL, c], [d, e, f]] [{'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}, {'a': NULL, 'b': NULL}, {'a': 42, 'b': 🦆🦆🦆🦆🦆🦆}] {'a': [4, 5, 6], 'b': [d, e, f]} [[42, 999, NULL, NULL, -42], [], [42, 999, NULL, NULL, -42]] [[4, 5, 6], [NULL, 2, 3], [4, 5, 6]] + +# Test round trip for all types +statement ok +create table all_types as from test_all_types() + +foreach col bool tinyint smallint int bigint hugeint uhugeint utinyint usmallint uint ubigint date time timestamp timestamp_s timestamp_ms timestamp_ns time_tz timestamp_tz float double dec_4_1 dec_9_4 dec_18_6 dec38_10 uuid interval varchar blob bit small_enum medium_enum large_enum int_array double_array date_array timestamp_array timestamptz_array varchar_array nested_int_array struct struct_of_arrays array_of_structs map union fixed_int_array fixed_varchar_array fixed_nested_int_array fixed_nested_varchar_array fixed_struct_array struct_of_fixed_array fixed_array_of_int_list list_of_fixed_int_array + +query TT +EXPLAIN +SELECT lead(lag, -1) over () IS NOT DISTINCT FROM lag(lead, 1) over () +FROM ( + SELECT lag("${col}", 1) OVER () AS lag, lead("${col}", -1) OVER () AS lead + FROM test_all_types() +) +QUALIFY row_number() over ()==2; +---- +physical_plan :.*STREAMING_WINDOW.* + +query I +SELECT lead(lag, -1) over () IS NOT DISTINCT FROM lag(lead, 1) over () +FROM ( + SELECT lag("${col}", 1) OVER () AS lag, lead("${col}", -1) OVER () AS lead + FROM test_all_types() +) +QUALIFY row_number() over ()==2; +---- +true + +endloop diff --git a/test/sql/window/test_streaming_window.test b/test/sql/window/test_streaming_window.test index 46193039292..78458005868 100644 --- a/test/sql/window/test_streaming_window.test +++ b/test/sql/window/test_streaming_window.test @@ -36,13 +36,19 @@ query TT EXPLAIN SELECT j, COUNT(j) FILTER(WHERE i = 2) OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM integers; ---- -physical_plan :.*STREAMING_WINDOW.* +physical_plan :.*STREAMING_WINDOW.* + +query TT +EXPLAIN +SELECT j, COUNT(*) FILTER(WHERE i = 2) OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM integers; +---- +physical_plan :.*STREAMING_WINDOW.* query TT EXPLAIN SELECT j, SUM(j) FILTER(WHERE i = 2) OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM integers; ---- -physical_plan :.*STREAMING_WINDOW.* +physical_plan :.*STREAMING_WINDOW.* # Test each of the streaming window functions query TT @@ -97,6 +103,64 @@ select percent_rank() over (), i, j from integers 0.0 1 2 0.0 1 NULL +query TT +EXPLAIN +SELECT i, LAG(i, 1) OVER() AS i1 +FROM range(10) tbl(i); +---- +physical_plan :.*STREAMING_WINDOW.* + +query II +SELECT i, LAG(i, 1) OVER() AS i1 +FROM range(10) tbl(i); +---- +0 NULL +1 0 +2 1 +3 2 +4 3 +5 4 +6 5 +7 6 +8 7 +9 8 + +query TT +EXPLAIN +SELECT i, LAG(i, -1) OVER() AS i1 +FROM range(10) tbl(i); +---- +physical_plan :.*STREAMING_WINDOW.* + +query TT +EXPLAIN +SELECT i, LEAD(i, -1) OVER() AS i1 +FROM range(10) tbl(i); +---- +physical_plan :.*STREAMING_WINDOW.* + +query II +SELECT i, LEAD(i, -1) OVER() AS i1 +FROM range(10) tbl(i); +---- +0 NULL +1 0 +2 1 +3 2 +4 3 +5 4 +6 5 +7 6 +8 7 +9 8 + +query TT +EXPLAIN +SELECT i, LEAD(i, 1) OVER() AS i1 +FROM range(10) tbl(i); +---- +physical_plan :.*STREAMING_WINDOW.* + # Test running aggregates query TT EXPLAIN @@ -112,6 +176,20 @@ SELECT i, COUNT(*) OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM i 1 3 1 4 +query TT +EXPLAIN +SELECT i, COUNT(*) FILTER(WHERE i = 2) OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM integers; +---- +physical_plan :.*STREAMING_WINDOW.* + +query II +SELECT i, COUNT(*) FILTER(WHERE i = 2) OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM integers; +---- +2 1 +2 2 +1 2 +1 2 + query TT EXPLAIN SELECT j, COUNT(j) OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM integers; @@ -295,3 +373,13 @@ EXECUTE sw1(2); ---- 10 1 11 2 + +# Struct Slicing +query I +from (values ({'key': 'A'}), ({'key': 'B'}), ({'key': 'C'})) +select + list(col0) over (rows between unbounded preceding and current row) as result +---- +[{'key': A}] +[{'key': A}, {'key': B}] +[{'key': A}, {'key': B}, {'key': C}] diff --git a/test/sql/window/test_streaming_window_distinct.test b/test/sql/window/test_streaming_window_distinct.test new file mode 100644 index 00000000000..27f02cf7242 --- /dev/null +++ b/test/sql/window/test_streaming_window_distinct.test @@ -0,0 +1,87 @@ +# name: test/sql/window/test_streaming_window_distinct.test +# description: Test streaming window support for DISTINCT (+FILTER) +# group: [window] + +statement ok +PRAGMA enable_verification + +statement ok +PRAGMA explain_output = PHYSICAL_ONLY; + +# DISTINCT only +query TT +explain +SELECT i, + SUM(DISTINCT i % 3) OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) +FROM range(10) tbl(i) +---- +physical_plan :.*STREAMING_WINDOW.* + +query II +SELECT i, + SUM(DISTINCT i % 3) OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) +FROM range(10) tbl(i) +---- +0 0 +1 1 +2 3 +3 3 +4 3 +5 3 +6 3 +7 3 +8 3 +9 3 + +# DISTINCT LISTs +query TT +EXPLAIN +SELECT + LIST(DISTINCT col0) OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS result +FROM (VALUES ({'key': 'A'}), ({'key': 'B'}), ({'key': 'A'})) +---- +physical_plan :.*STREAMING_WINDOW.* + +query I +SELECT + LIST(DISTINCT col0) OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS result +FROM (VALUES ({'key': 'A'}), ({'key': 'B'}), ({'key': 'A'})) +---- +[{'key': A}] +[{'key': A}, {'key': B}] +[{'key': A}, {'key': B}] + +# DISTINCT + FILTER +query TT +explain +SELECT i, + SUM(DISTINCT i % 5) FILTER (i % 3 = 0) OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) +FROM range(20) tbl(i) +---- +physical_plan :.*STREAMING_WINDOW.* + +query II +SELECT i, + SUM(DISTINCT i % 5) FILTER (i % 3 = 0) OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) +FROM range(20) tbl(i) +---- +0 0 +1 0 +2 0 +3 3 +4 3 +5 3 +6 4 +7 4 +8 4 +9 8 +10 8 +11 8 +12 10 +13 10 +14 10 +15 10 +16 10 +17 10 +18 10 +19 10 diff --git a/test/sql/window/test_window_cse.test b/test/sql/window/test_window_cse.test index 6a1731f6807..f89568b502f 100644 --- a/test/sql/window/test_window_cse.test +++ b/test/sql/window/test_window_cse.test @@ -75,4 +75,4 @@ FROM generate_series(1, 10) as tbl(x); query II EXPLAIN FROM noncse; ---- -physical_plan :.*quantile\(x\).*quantile\(x\).* +physical_plan :.*quantile_disc\(x\).*quantile_disc\(x\).* diff --git a/test/sql/window/test_window_fusion.test b/test/sql/window/test_window_fusion.test index c95cc9b8a42..64c257e913b 100644 --- a/test/sql/window/test_window_fusion.test +++ b/test/sql/window/test_window_fusion.test @@ -82,7 +82,7 @@ select l_orderkey, sum(l_extendedprice) over(), from lineitem -order by l_partkey, l_orderkey +order by l_partkey, l_orderkey, l_extendedprice ---- 29733.00 1 2883 1314442.00 1802.00 1 5121 1314442.00 @@ -133,8 +133,8 @@ order by l_partkey, l_orderkey 17138.00 2 46913 1314442.00 31570.00 2 50499 1314442.00 37884.00 2 54086 1314442.00 -26158.00 2 54436 1314442.00 4510.00 2 54436 1314442.00 +26158.00 2 54436 1314442.00 3608.00 2 54630 1314442.00 41492.00 2 55136 1314442.00 @@ -145,7 +145,7 @@ select l_orderkey, sum(l_extendedprice) over(order by l_partkey), from lineitem -order by l_partkey, l_orderkey +order by l_partkey, l_orderkey, l_extendedprice ---- 29733.00 1 2883 607274.00 1802.00 1 5121 607274.00 @@ -196,8 +196,8 @@ order by l_partkey, l_orderkey 17138.00 2 46913 1314442.00 31570.00 2 50499 1314442.00 37884.00 2 54086 1314442.00 -26158.00 2 54436 1314442.00 4510.00 2 54436 1314442.00 +26158.00 2 54436 1314442.00 3608.00 2 54630 1314442.00 41492.00 2 55136 1314442.00 @@ -208,7 +208,7 @@ select l_orderkey, sum(l_extendedprice) over(order by l_partkey, l_orderkey), from lineitem -order by l_partkey, l_orderkey +order by l_partkey, l_orderkey, l_extendedprice desc ---- 29733.00 1 2883 29733.00 1802.00 1 5121 31535.00 @@ -271,7 +271,7 @@ select l_orderkey, sum(l_extendedprice) over(order by l_partkey, l_orderkey desc), from lineitem -order by l_partkey, l_orderkey +order by l_partkey, l_orderkey, l_extendedprice desc ---- 29733.00 1 2883 607274.00 1802.00 1 5121 577541.00 @@ -338,7 +338,7 @@ select sum(l_extendedprice) over(order by l_partkey, l_orderkey), sum(l_extendedprice) over(order by l_partkey, l_orderkey desc), from lineitem -order by l_partkey, l_orderkey +order by l_partkey, l_orderkey, l_extendedprice desc ---- 29733.00 1 2883 1314442.00 607274.00 29733.00 607274.00 1802.00 1 5121 1314442.00 607274.00 31535.00 577541.00 @@ -406,7 +406,7 @@ select l_orderkey, sum(l_extendedprice) over(partition by l_partkey), from lineitem -order by l_partkey, l_orderkey +order by l_partkey, l_orderkey, l_extendedprice desc ---- 29733.00 1 2883 607274.00 1802.00 1 5121 607274.00 @@ -469,7 +469,7 @@ select l_orderkey, sum(l_extendedprice) over(partition by l_partkey order by l_orderkey), from lineitem -order by l_partkey, l_orderkey +order by l_partkey, l_orderkey, l_extendedprice desc ---- 29733.00 1 2883 29733.00 1802.00 1 5121 31535.00 diff --git a/test/sqlite/result_helper.cpp b/test/sqlite/result_helper.cpp index b30d7b90ca5..2911c3d06b7 100644 --- a/test/sqlite/result_helper.cpp +++ b/test/sqlite/result_helper.cpp @@ -1,12 +1,13 @@ #include "result_helper.hpp" -#include "re2/re2.h" + #include "catch.hpp" -#include "termcolor.hpp" -#include "sqllogic_test_runner.hpp" #include "duckdb/common/crypto/md5.hpp" #include "duckdb/parser/qualified_name.hpp" -#include "test_helpers.hpp" +#include "re2/re2.h" #include "sqllogic_test_logger.hpp" +#include "sqllogic_test_runner.hpp" +#include "termcolor.hpp" +#include "test_helpers.hpp" #include @@ -124,6 +125,9 @@ bool TestResultHelper::CheckQueryResult(const Query &query, ExecuteContext &cont expected_column_count = result.ColumnCount(); column_count_mismatch = true; } + if (expected_column_count == 0) { + return false; + } idx_t expected_rows = comparison_values.size() / expected_column_count; // we first check the counts: if the values are equal to the amount of rows we expect the results to be row-wise bool row_wise = expected_column_count > 1 && comparison_values.size() == result.RowCount(); @@ -181,7 +185,9 @@ bool TestResultHelper::CheckQueryResult(const Query &query, ExecuteContext &cont return false; } // we do this just to increment the assertion counter - REQUIRE(success); + string success_log = + StringUtil::Format("CheckQueryResult: %s:%d", query.file_name, query.query_line); + REQUIRE(success_log.c_str()); } current_row++; } @@ -196,7 +202,8 @@ bool TestResultHelper::CheckQueryResult(const Query &query, ExecuteContext &cont return false; } // we do this just to increment the assertion counter - REQUIRE(success); + string success_log = StringUtil::Format("CheckQueryResult: %s:%d", query.file_name, query.query_line); + REQUIRE(success_log.c_str()); current_column++; if (current_column == expected_column_count) { @@ -273,8 +280,19 @@ bool TestResultHelper::CheckStatementResult(const Statement &statement, ExecuteC } if (result.HasError() && !statement.expected_error.empty()) { if (!StringUtil::Contains(result.GetError(), statement.expected_error)) { - logger.ExpectedErrorMismatch(statement.expected_error, result); - return false; + bool success = false; + if (StringUtil::StartsWith(statement.expected_error, ":") || + StringUtil::StartsWith(statement.expected_error, ":")) { + success = MatchesRegex(logger, result, statement.expected_error); + } + if (!success) { + logger.ExpectedErrorMismatch(statement.expected_error, result); + return false; + } + string success_log = + StringUtil::Format("CheckStatementResult: %s:%d", statement.file_name, statement.query_line); + REQUIRE(success_log.c_str()); + return true; } } } @@ -288,7 +306,13 @@ bool TestResultHelper::CheckStatementResult(const Statement &statement, ExecuteC } return false; } - REQUIRE(!error); + if (error) { + REQUIRE(false); + } else { + string success_log = + StringUtil::Format("CheckStatementResult: %s:%d", statement.file_name, statement.query_line); + REQUIRE(success_log.c_str()); + } return true; } @@ -426,21 +450,7 @@ bool TestResultHelper::CompareValues(SQLLogicTestLogger &logger, MaterializedQue return true; } if (StringUtil::StartsWith(rvalue_str, ":") || StringUtil::StartsWith(rvalue_str, ":")) { - bool want_match = StringUtil::StartsWith(rvalue_str, ":"); - string regex_str = StringUtil::Replace(StringUtil::Replace(rvalue_str, ":", ""), ":", ""); - RE2::Options options; - options.set_dot_nl(true); - RE2 re(regex_str, options); - if (!re.ok()) { - logger.PrintErrorHeader("Test error!"); - logger.PrintLineSep(); - std::cerr << termcolor::red << termcolor::bold << "Failed to parse regex: " << re.error() - << termcolor::reset << std::endl; - logger.PrintLineSep(); - return false; - } - bool regex_matches = RE2::FullMatch(lvalue_str, re); - if (regex_matches == want_match) { + if (MatchesRegex(logger, result, rvalue_str)) { return true; } } @@ -511,4 +521,27 @@ bool TestResultHelper::CompareValues(SQLLogicTestLogger &logger, MaterializedQue return true; } +bool TestResultHelper::MatchesRegex(SQLLogicTestLogger &logger, MaterializedQueryResult &result, string rvalue_str) { + bool want_match = StringUtil::StartsWith(rvalue_str, ":"); + string regex_str = StringUtil::Replace(StringUtil::Replace(rvalue_str, ":", ""), ":", ""); + + RE2::Options options; + options.set_dot_nl(true); + RE2 re(regex_str, options); + if (!re.ok()) { + logger.PrintErrorHeader("Test error!"); + logger.PrintLineSep(); + std::cerr << termcolor::red << termcolor::bold << "Failed to parse regex: " << re.error() << termcolor::reset + << std::endl; + logger.PrintLineSep(); + return false; + } + auto resString = result.ToString(); + bool regex_matches = RE2::FullMatch(result.ToString(), re); + if ((want_match && regex_matches) || (!want_match && !regex_matches)) { + return true; + } + return false; +} + } // namespace duckdb diff --git a/test/sqlite/result_helper.hpp b/test/sqlite/result_helper.hpp index b074da7bd66..f313e9b0c08 100644 --- a/test/sqlite/result_helper.hpp +++ b/test/sqlite/result_helper.hpp @@ -27,13 +27,13 @@ class TestResultHelper { duckdb::unique_ptr owned_result); bool CheckStatementResult(const Statement &statement, ExecuteContext &context, duckdb::unique_ptr owned_result); - string SQLLogicTestConvertValue(Value value, LogicalType sql_type, bool original_sqlite_test); void DuckDBConvertResult(MaterializedQueryResult &result, bool original_sqlite_test, vector &out_result); static bool ResultIsHash(const string &result); static bool ResultIsFile(string result); + bool MatchesRegex(SQLLogicTestLogger &logger, MaterializedQueryResult &result, string rvalue_str); bool CompareValues(SQLLogicTestLogger &logger, MaterializedQueryResult &result, string lvalue_str, string rvalue_str, idx_t current_row, idx_t current_column, vector &values, idx_t expected_column_count, bool row_wise, vector &result_values); diff --git a/test/sqlite/select4.test_slow b/test/sqlite/select4.test_slow index 25a41e513ba..39d2fa34739 100644 --- a/test/sqlite/select4.test_slow +++ b/test/sqlite/select4.test_slow @@ -48300,4 +48300,3 @@ SELECT c6*856, x5 AND c5 in (820,44,696,824,668,723,598) ---- 28 values hashing to 8ceb8232c1e6c7b7f5d87ea5c54e08d0 - diff --git a/test/sqlite/sqllogic_command.cpp b/test/sqlite/sqllogic_command.cpp index bd1b3e45972..a2484394321 100644 --- a/test/sqlite/sqllogic_command.cpp +++ b/test/sqlite/sqllogic_command.cpp @@ -68,17 +68,20 @@ void Command::RestartDatabase(ExecuteContext &context, Connection *&connection, query_fail = true; } bool can_restart = true; - for (auto &conn : connection->context->db->GetConnectionManager().connections) { - if (!conn.first->client_data->prepared_statements.empty()) { + auto &connection_manager = connection->context->db->GetConnectionManager(); + auto &connection_list = connection_manager.GetConnectionListReference(); + for (auto &conn_ref : connection_list) { + auto &conn = conn_ref.first.get(); + if (!conn.client_data->prepared_statements.empty()) { can_restart = false; } - if (conn.first->transaction.HasActiveTransaction()) { + if (conn.transaction.HasActiveTransaction()) { can_restart = false; } } if (!query_fail && can_restart && !runner.skip_reload) { // We basically restart the database if no transaction is active and if the query is valid - auto command = make_uniq(runner); + auto command = make_uniq(runner, true); runner.ExecuteCommand(std::move(command)); connection = CommandConnection(context); } @@ -105,10 +108,89 @@ unique_ptr Command::ExecuteQuery(ExecuteContext &contex #endif } +bool CheckLoopCondition(ExecuteContext &context, const vector &conditions) { + if (conditions.empty()) { + // no conditions + return true; + } + if (context.running_loops.empty()) { + throw BinderException("Conditions (onlyif/skipif) on loop parameters can only occur within a loop"); + } + for (auto &condition : conditions) { + bool condition_holds = false; + bool found_loop = false; + for (auto &loop : context.running_loops) { + if (loop.loop_iterator_name != condition.keyword) { + continue; + } + found_loop = true; + + string loop_value; + if (loop.tokens.empty()) { + loop_value = to_string(loop.loop_idx); + } else { + loop_value = loop.tokens[loop.loop_idx]; + } + if (condition.comparison == ExpressionType::COMPARE_EQUAL || + condition.comparison == ExpressionType::COMPARE_NOTEQUAL) { + // equality/non-equality is done on the string value + if (condition.comparison == ExpressionType::COMPARE_EQUAL) { + condition_holds = loop_value == condition.value; + } else { + condition_holds = loop_value != condition.value; + } + } else { + // > >= < <= are done on numeric values + int64_t loop_val = std::stoll(loop_value); + int64_t condition_val = std::stoll(condition.value); + switch (condition.comparison) { + case ExpressionType::COMPARE_GREATERTHAN: + condition_holds = loop_val > condition_val; + break; + case ExpressionType::COMPARE_LESSTHAN: + condition_holds = loop_val < condition_val; + break; + case ExpressionType::COMPARE_GREATERTHANOREQUALTO: + condition_holds = loop_val >= condition_val; + break; + case ExpressionType::COMPARE_LESSTHANOREQUALTO: + condition_holds = loop_val <= condition_val; + break; + default: + throw BinderException("Unrecognized comparison for loop condition"); + } + } + } + if (!found_loop) { + throw BinderException("Condition in onlyif/skipif not found: %s must be a loop iterator name", + condition.keyword); + } + if (condition_holds) { + // the condition holds + if (condition.skip_if) { + // skip on condition holding + return false; + } + } else { + // the condition does not hold + if (!condition.skip_if) { + // skip on condition not holding + return false; + } + } + } + // all conditions pass - execute + return true; +} + void Command::Execute(ExecuteContext &context) const { if (runner.finished_processing_file) { return; } + if (!CheckLoopCondition(context, conditions)) { + // condition excludes this file + return; + } if (context.running_loops.empty()) { context.sql_query = base_sql_query; ExecuteInternal(context); @@ -126,7 +208,8 @@ Statement::Statement(SQLLogicTestRunner &runner) : Command(runner) { Query::Query(SQLLogicTestRunner &runner) : Command(runner) { } -RestartCommand::RestartCommand(SQLLogicTestRunner &runner) : Command(runner) { +RestartCommand::RestartCommand(SQLLogicTestRunner &runner, bool load_extensions_p) + : Command(runner), load_extensions(load_extensions_p) { } ReconnectCommand::ReconnectCommand(SQLLogicTestRunner &runner) : Command(runner) { @@ -291,7 +374,7 @@ void RestartCommand::ExecuteInternal(ExecuteContext &context) const { low_query_writer_path = runner.con->context->client_data->log_query_writer->path; } - runner.LoadDatabase(runner.dbpath); + runner.LoadDatabase(runner.dbpath, load_extensions); runner.con->context->config = client_config; diff --git a/test/sqlite/sqllogic_command.hpp b/test/sqlite/sqllogic_command.hpp index 863d9a3419d..173c93b1176 100644 --- a/test/sqlite/sqllogic_command.hpp +++ b/test/sqlite/sqllogic_command.hpp @@ -41,6 +41,13 @@ struct ExecuteContext { int error_line; }; +struct Condition { + string keyword; + string value; + ExpressionType comparison; + bool skip_if; +}; + class Command { public: Command(SQLLogicTestRunner &runner); @@ -51,6 +58,7 @@ class Command { int query_line; string base_sql_query; string file_name; + vector conditions; public: Connection *CommandConnection(ExecuteContext &context) const; @@ -92,7 +100,8 @@ class Query : public Command { class RestartCommand : public Command { public: - RestartCommand(SQLLogicTestRunner &runner); + bool load_extensions; + RestartCommand(SQLLogicTestRunner &runner, bool load_extensions); public: void ExecuteInternal(ExecuteContext &context) const override; diff --git a/test/sqlite/sqllogic_test_logger.cpp b/test/sqlite/sqllogic_test_logger.cpp index a3d21a368dc..060eacdbdd9 100644 --- a/test/sqlite/sqllogic_test_logger.cpp +++ b/test/sqlite/sqllogic_test_logger.cpp @@ -100,10 +100,17 @@ void SQLLogicTestLogger::PrintSQLFormatted() { std::cerr << std::endl; } -void SQLLogicTestLogger::PrintErrorHeader(const string &description) { +void SQLLogicTestLogger::PrintErrorHeader(const string &file_name, idx_t query_line, const string &description) { PrintLineSep(); std::cerr << termcolor::red << termcolor::bold << description << " " << termcolor::reset; - std::cerr << termcolor::bold << "(" << file_name << ":" << query_line << ")!" << termcolor::reset << std::endl; + if (!file_name.empty()) { + std::cerr << termcolor::bold << "(" << file_name << ":" << query_line << ")!" << termcolor::reset; + } + std::cerr << std::endl; +} + +void SQLLogicTestLogger::PrintErrorHeader(const string &description) { + PrintErrorHeader(file_name, query_line, description); } void SQLLogicTestLogger::PrintResultError(const vector &result_values, const vector &values, @@ -269,4 +276,11 @@ void SQLLogicTestLogger::ExpectedErrorMismatch(const string &expected_error, Mat result.Print(); } +void SQLLogicTestLogger::LoadDatabaseFail(const string &dbpath, const string &message) { + PrintErrorHeader(string(), 0, "Failed to load database " + dbpath); + PrintLineSep(); + Log("Error message: " + message + "\n"); + PrintLineSep(); +} + } // namespace duckdb diff --git a/test/sqlite/sqllogic_test_logger.hpp b/test/sqlite/sqllogic_test_logger.hpp index 60a8c990d63..487935a1d92 100644 --- a/test/sqlite/sqllogic_test_logger.hpp +++ b/test/sqlite/sqllogic_test_logger.hpp @@ -22,14 +22,15 @@ class SQLLogicTestLogger { SQLLogicTestLogger(ExecuteContext &context, const Command &command); ~SQLLogicTestLogger(); - void Log(const string &str); + static void Log(const string &str); void PrintExpectedResult(const vector &values, idx_t columns, bool row_wise); - void PrintLineSep(); - void PrintHeader(string header); + static void PrintLineSep(); + static void PrintHeader(string header); void PrintFileHeader(); void PrintSQL(); void PrintSQLFormatted(); void PrintErrorHeader(const string &description); + static void PrintErrorHeader(const string &file_name, idx_t query_line, const string &description); void PrintResultError(const vector &result_values, const vector &values, idx_t expected_column_count, bool row_wise); void PrintResultError(MaterializedQueryResult &result, const vector &values, idx_t expected_column_count, @@ -48,6 +49,7 @@ class SQLLogicTestLogger { void WrongResultHash(QueryResult *expected_result, MaterializedQueryResult &result); void UnexpectedStatement(bool expect_ok, MaterializedQueryResult &result); void ExpectedErrorMismatch(const string &expected_error, MaterializedQueryResult &result); + static void LoadDatabaseFail(const string &dbpath, const string &message); private: lock_guard log_lock; diff --git a/test/sqlite/sqllogic_test_runner.cpp b/test/sqlite/sqllogic_test_runner.cpp index 628a1fc4922..09a7bd4970c 100644 --- a/test/sqlite/sqllogic_test_runner.cpp +++ b/test/sqlite/sqllogic_test_runner.cpp @@ -1,13 +1,15 @@ -#include "catch.hpp" -#include "test_helpers.hpp" -#include "sqllogic_parser.hpp" #include "sqllogic_test_runner.hpp" -#include "duckdb/main/extension_helper.hpp" + +#include "catch.hpp" +#include "duckdb/common/file_open_flags.hpp" +#include "duckdb/common/virtual_file_system.hpp" #include "duckdb/main/extension/generated_extension_loader.hpp" #include "duckdb/main/extension_entries.hpp" -#include "duckdb/common/virtual_file_system.hpp" -#include "duckdb/common/file_open_flags.hpp" +#include "duckdb/main/extension_helper.hpp" +#include "sqllogic_parser.hpp" +#include "test_helpers.hpp" +#include "sqllogic_test_logger.hpp" #ifdef DUCKDB_OUT_OF_TREE #include DUCKDB_EXTENSION_HEADER @@ -77,7 +79,7 @@ void SQLLogicTestRunner::EndLoop() { } } -void SQLLogicTestRunner::LoadDatabase(string dbpath) { +void SQLLogicTestRunner::LoadDatabase(string dbpath, bool load_extensions) { loaded_databases.push_back(dbpath); // restart the database with the specified db path @@ -86,12 +88,20 @@ void SQLLogicTestRunner::LoadDatabase(string dbpath) { named_connection_map.clear(); // now re-open the current database - db = make_uniq(dbpath, config.get()); + try { + db = make_uniq(dbpath, config.get()); + } catch (std::exception &ex) { + ErrorData err(ex); + SQLLogicTestLogger::LoadDatabaseFail(dbpath, err.Message()); + FAIL(); + } Reconnect(); // load any previously loaded extensions again - for (auto &extension : extensions) { - ExtensionHelper::LoadExtension(*db, extension); + if (load_extensions) { + for (auto &extension : extensions) { + ExtensionHelper::LoadExtension(*db, extension); + } } } @@ -100,6 +110,7 @@ void SQLLogicTestRunner::Reconnect() { if (original_sqlite_test) { con->Query("SET integer_division=true"); } + con->Query("SET secret_directory='" + TestCreatePath("test_secret_dir") + "'"); #ifdef DUCKDB_ALTERNATIVE_VERIFY con->Query("SET pivot_filter_threshold=0"); #endif @@ -381,6 +392,61 @@ RequireResult SQLLogicTestRunner::CheckRequire(SQLLogicParser &parser, const vec return RequireResult::PRESENT; } +bool TryParseConditions(SQLLogicParser &parser, const string &condition_text, vector &conditions, + bool skip_if) { + bool is_condition = false; + for (auto &c : condition_text) { + switch (c) { + case '=': + case '>': + case '<': + is_condition = true; + break; + default: + break; + } + } + if (!is_condition) { + // not a condition + return false; + } + // split based on && + auto condition_strings = StringUtil::Split(condition_text, "&&"); + for (auto &condition_str : condition_strings) { + vector> comparators { + {"<>", ExpressionType::COMPARE_NOTEQUAL}, {">=", ExpressionType::COMPARE_GREATERTHANOREQUALTO}, + {">", ExpressionType::COMPARE_GREATERTHAN}, {"<=", ExpressionType::COMPARE_LESSTHANOREQUALTO}, + {"<", ExpressionType::COMPARE_LESSTHAN}, {"=", ExpressionType::COMPARE_EQUAL}}; + ExpressionType comparison_type = ExpressionType::INVALID; + vector splits; + for (auto &comparator : comparators) { + if (!StringUtil::Contains(condition_str, comparator.first)) { + continue; + } + splits = StringUtil::Split(condition_str, comparator.first); + comparison_type = comparator.second; + break; + } + // loop condition, e.g. skipif threadid=0 + if (splits.size() != 2) { + parser.Fail("skipif/onlyif must be in the form of x=y or x>y, potentially separated by &&"); + } + // strip white space + for (auto &split : splits) { + StringUtil::Trim(split); + } + + // now create the condition + Condition condition; + condition.keyword = splits[0]; + condition.value = splits[1]; + condition.comparison = comparison_type; + condition.skip_if = skip_if; + conditions.push_back(condition); + } + return true; +} + void SQLLogicTestRunner::ExecuteFile(string script) { SQLLogicParser parser; idx_t skip_level = 0; @@ -400,7 +466,7 @@ void SQLLogicTestRunner::ExecuteFile(string script) { } // initialize the database with the default dbpath - LoadDatabase(dbpath); + LoadDatabase(dbpath, true); // open the file and parse it bool success = parser.OpenFile(script); @@ -418,6 +484,7 @@ void SQLLogicTestRunner::ExecuteFile(string script) { parser.Fail("all test statements need to be separated by an empty line"); } + vector conditions; bool skip_statement = false; while (token.type == SQLLogicTokenType::SQLLOGIC_SKIP_IF || token.type == SQLLogicTokenType::SQLLOGIC_ONLY_IF) { // skipif/onlyif @@ -426,16 +493,32 @@ void SQLLogicTestRunner::ExecuteFile(string script) { parser.Fail("skipif/onlyif requires a single parameter (e.g. skipif duckdb)"); } auto system_name = StringUtil::Lower(token.parameters[0]); - bool our_system = system_name == "duckdb"; + // we support two kinds of conditions here + // (for original sqllogictests) system comparisons, e.g.: + // (1) skipif duckdb + // (2) onlyif + // conditions on loop variables, e.g.: + // (1) skipif i=2 + // (2) onlyif threadid=0 + // the latter is only supported in our own tests (not in original sqllogic tests) + bool is_system_comparison; if (original_sqlite_test) { - our_system = our_system || system_name == "postgresql"; + is_system_comparison = true; + } else { + is_system_comparison = !TryParseConditions(parser, system_name, conditions, skip_if); } - if (our_system == skip_if) { - // we skip this command in two situations - // (1) skipif duckdb - // (2) onlyif - skip_statement = true; - break; + if (is_system_comparison) { + bool our_system = system_name == "duckdb"; + if (original_sqlite_test) { + our_system = our_system || system_name == "postgresql"; + } + if (our_system == skip_if) { + // we skip this command in two situations + // (1) skipif duckdb + // (2) onlyif + skip_statement = true; + break; + } } parser.NextLine(); token = parser.Tokenize(); @@ -482,6 +565,7 @@ void SQLLogicTestRunner::ExecuteFile(string script) { if (token.parameters.size() >= 2) { command->connection_name = token.parameters[1]; } + command->conditions = std::move(conditions); ExecuteCommand(std::move(command)); } else if (token.type == SQLLogicTokenType::SQLLOGIC_QUERY) { if (token.parameters.size() < 1) { @@ -543,6 +627,7 @@ void SQLLogicTestRunner::ExecuteFile(string script) { } else { command->query_has_label = false; } + command->conditions = std::move(conditions); ExecuteCommand(std::move(command)); } else if (token.type == SQLLogicTokenType::SQLLOGIC_HASH_THRESHOLD) { if (token.parameters.size() != 1) { @@ -714,13 +799,16 @@ void SQLLogicTestRunner::ExecuteFile(string script) { config->options.access_mode = AccessMode::AUTOMATIC; } // now create the database file - LoadDatabase(dbpath); + LoadDatabase(dbpath, true); } else if (token.type == SQLLogicTokenType::SQLLOGIC_RESTART) { if (dbpath.empty()) { parser.Fail("cannot restart an in-memory database, did you forget to call \"load\"?"); } + + bool load_extensions = !(token.parameters.size() == 1 && token.parameters[0] == "no_extension_load"); + // restart the current database - auto command = make_uniq(*this); + auto command = make_uniq(*this, load_extensions); ExecuteCommand(std::move(command)); } else if (token.type == SQLLogicTokenType::SQLLOGIC_RECONNECT) { auto command = make_uniq(*this); diff --git a/test/sqlite/sqllogic_test_runner.hpp b/test/sqlite/sqllogic_test_runner.hpp index dfeb1cc2578..cac1f6a0ec0 100644 --- a/test/sqlite/sqllogic_test_runner.hpp +++ b/test/sqlite/sqllogic_test_runner.hpp @@ -57,7 +57,7 @@ class SQLLogicTestRunner { public: void ExecuteFile(string script); - virtual void LoadDatabase(string dbpath); + virtual void LoadDatabase(string dbpath, bool load_extensions); string ReplaceKeywords(string input); diff --git a/test/sqlite/test_sqllogictest.cpp b/test/sqlite/test_sqllogictest.cpp index fa1c534f536..a89c6772c84 100644 --- a/test/sqlite/test_sqllogictest.cpp +++ b/test/sqlite/test_sqllogictest.cpp @@ -171,6 +171,15 @@ void RegisterSqllogictests() { "test/random/expr/slt_good_80.test", "test/random/expr/slt_good_75.test", "test/random/expr/slt_good_42.test", "test/random/expr/slt_good_49.test", "test/random/expr/slt_good_24.test", "test/random/expr/slt_good_30.test", "test/random/expr/slt_good_8.test", "test/random/expr/slt_good_61.test", + // dependencies between tables/views prevent dropping in DuckDB without CASCADE + "test/index/view/1000/slt_good_0.test", "test/index/view/100/slt_good_0.test", + "test/index/view/100/slt_good_5.test", "test/index/view/100/slt_good_1.test", + "test/index/view/100/slt_good_3.test", "test/index/view/100/slt_good_4.test", + "test/index/view/100/slt_good_2.test", "test/index/view/10000/slt_good_0.test", + "test/index/view/10/slt_good_5.test", "test/index/view/10/slt_good_7.test", + "test/index/view/10/slt_good_1.test", "test/index/view/10/slt_good_3.test", + "test/index/view/10/slt_good_4.test", "test/index/view/10/slt_good_6.test", + "test/index/view/10/slt_good_2.test", // strange error in hash comparison, results appear correct... "test/index/random/10/slt_good_7.test", "test/index/random/10/slt_good_9.test"}; duckdb::unique_ptr fs = FileSystem::CreateLocal(); diff --git a/test/sqlsmith/sql_reduce.test b/test/sqlsmith/sql_reduce.test deleted file mode 100644 index 432fc8581bb..00000000000 --- a/test/sqlsmith/sql_reduce.test +++ /dev/null @@ -1,79 +0,0 @@ -# name: test/sqlsmith/sql_reduce.test -# description: Test reduce SQL statement -# group: [sqlsmith] - -require sqlsmith - -query I -SELECT * FROM reduce_sql_statement('SELECT a, b FROM tbl') ORDER BY 1 ----- -SELECT NULL, b FROM tbl -SELECT NULL, b FROM tbl -SELECT a FROM tbl -SELECT a, NULL FROM tbl -SELECT a, NULL FROM tbl -SELECT a, b -SELECT a, b FROM tbl -SELECT a, b FROM tbl -SELECT b FROM tbl - -query I -SELECT * FROM reduce_sql_statement('SELECT a, b FROM tbl WHERE a AND b') ORDER BY 1 ----- -SELECT NULL, b FROM tbl WHERE (a AND b) -SELECT NULL, b FROM tbl WHERE (a AND b) -SELECT a FROM tbl WHERE (a AND b) -SELECT a, NULL FROM tbl WHERE (a AND b) -SELECT a, NULL FROM tbl WHERE (a AND b) -SELECT a, b FROM tbl -SELECT a, b FROM tbl WHERE (NULL AND b) -SELECT a, b FROM tbl WHERE (NULL AND b) -SELECT a, b FROM tbl WHERE (a AND NULL) -SELECT a, b FROM tbl WHERE (a AND NULL) -SELECT a, b FROM tbl WHERE (a AND b) -SELECT a, b FROM tbl WHERE (a AND b) -SELECT a, b FROM tbl WHERE NULL -SELECT a, b FROM tbl WHERE NULL -SELECT a, b FROM tbl WHERE a -SELECT a, b FROM tbl WHERE a -SELECT a, b FROM tbl WHERE b -SELECT a, b FROM tbl WHERE b -SELECT a, b WHERE (a AND b) -SELECT b FROM tbl WHERE (a AND b) - -query I -SELECT * FROM reduce_sql_statement('INSERT INTO tbl VALUES (1, 2)') ORDER BY 1 ----- -INSERT INTO tbl (VALUES (1)) -INSERT INTO tbl (VALUES (1, 2)) -INSERT INTO tbl (VALUES (2)) -INSERT INTO tbl SELECT * -INSERT INTO tbl SELECT NULL FROM (VALUES (1, 2)) -INSERT INTO tbl SELECT NULL FROM (VALUES (1, 2)) AS valueslist - -query I -SELECT * FROM reduce_sql_statement('UPDATE tbl SET i=3, j=4 WHERE z=5') ORDER BY 1 ----- -UPDATE tbl SET i = 3 WHERE (z = 5) -UPDATE tbl SET i = 3, j = 4 -UPDATE tbl SET i = 3, j = 4 WHERE (NULL = 5) -UPDATE tbl SET i = 3, j = 4 WHERE 5 -UPDATE tbl SET i = 3, j = 4 WHERE NULL -UPDATE tbl SET i = 3, j = 4 WHERE z -UPDATE tbl SET j = 4 WHERE (z = 5) - -query I -SELECT * FROM reduce_sql_statement('DELETE FROM a WHERE i >= 2000 AND i < 5000;') ORDER BY 1 ----- -DELETE FROM a -DELETE FROM a WHERE ((NULL >= 2000) AND (i < 5000)) -DELETE FROM a WHERE ((i >= 2000) AND (NULL < 5000)) -DELETE FROM a WHERE ((i >= 2000) AND 5000) -DELETE FROM a WHERE ((i >= 2000) AND NULL) -DELETE FROM a WHERE ((i >= 2000) AND i) -DELETE FROM a WHERE (2000 AND (i < 5000)) -DELETE FROM a WHERE (NULL AND (i < 5000)) -DELETE FROM a WHERE (i < 5000) -DELETE FROM a WHERE (i >= 2000) -DELETE FROM a WHERE (i AND (i < 5000)) -DELETE FROM a WHERE NULL diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 7452dc78bac..bd38e32e607 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -12,6 +12,7 @@ if(NOT AMALGAMATION_BUILD) add_subdirectory(fastpforlib) add_subdirectory(mbedtls) add_subdirectory(fsst) + add_subdirectory(yyjson) endif() if(NOT WIN32 diff --git a/third_party/brotli/LICENSE b/third_party/brotli/LICENSE new file mode 100644 index 00000000000..33b7cdd2dba --- /dev/null +++ b/third_party/brotli/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. + +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. diff --git a/third_party/brotli/VERSION b/third_party/brotli/VERSION new file mode 100644 index 00000000000..1cc5f657e05 --- /dev/null +++ b/third_party/brotli/VERSION @@ -0,0 +1 @@ +1.1.0 \ No newline at end of file diff --git a/third_party/brotli/common/brotli_constants.h b/third_party/brotli/common/brotli_constants.h new file mode 100644 index 00000000000..cb52343e29d --- /dev/null +++ b/third_party/brotli/common/brotli_constants.h @@ -0,0 +1,204 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/** + * @file + * Common constants used in decoder and encoder API. + */ + +#ifndef BROTLI_COMMON_CONSTANTS_H_ +#define BROTLI_COMMON_CONSTANTS_H_ + +#include +#include + +#include "brotli_platform.h" + +namespace duckdb_brotli { + +/* Specification: 7.3. Encoding of the context map */ +#define BROTLI_CONTEXT_MAP_MAX_RLE 16 + +/* Specification: 2. Compressed representation overview */ +#define BROTLI_MAX_NUMBER_OF_BLOCK_TYPES 256 + +/* Specification: 3.3. Alphabet sizes: insert-and-copy length */ +#define BROTLI_NUM_LITERAL_SYMBOLS 256 +#define BROTLI_NUM_COMMAND_SYMBOLS 704 +#define BROTLI_NUM_BLOCK_LEN_SYMBOLS 26 +#define BROTLI_MAX_CONTEXT_MAP_SYMBOLS (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + \ + BROTLI_CONTEXT_MAP_MAX_RLE) +#define BROTLI_MAX_BLOCK_TYPE_SYMBOLS (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 2) + +/* Specification: 3.5. Complex prefix codes */ +#define BROTLI_REPEAT_PREVIOUS_CODE_LENGTH 16 +#define BROTLI_REPEAT_ZERO_CODE_LENGTH 17 +#define BROTLI_CODE_LENGTH_CODES (BROTLI_REPEAT_ZERO_CODE_LENGTH + 1) +/* "code length of 8 is repeated" */ +#define BROTLI_INITIAL_REPEATED_CODE_LENGTH 8 + +/* "Large Window Brotli" */ + +/** + * The theoretical maximum number of distance bits specified for large window + * brotli, for 64-bit encoders and decoders. Even when in practice 32-bit + * encoders and decoders only support up to 30 max distance bits, the value is + * set to 62 because it affects the large window brotli file format. + * Specifically, it affects the encoding of simple huffman tree for distances, + * see Specification RFC 7932 chapter 3.4. + */ +#define BROTLI_LARGE_MAX_DISTANCE_BITS 62U +#define BROTLI_LARGE_MIN_WBITS 10 +/** + * The maximum supported large brotli window bits by the encoder and decoder. + * Large window brotli allows up to 62 bits, however the current encoder and + * decoder, designed for 32-bit integers, only support up to 30 bits maximum. + */ +#define BROTLI_LARGE_MAX_WBITS 30 + +/* Specification: 4. Encoding of distances */ +#define BROTLI_NUM_DISTANCE_SHORT_CODES 16 +/** + * Maximal number of "postfix" bits. + * + * Number of "postfix" bits is stored as 2 bits in meta-block header. + */ +#define BROTLI_MAX_NPOSTFIX 3 +#define BROTLI_MAX_NDIRECT 120 +#define BROTLI_MAX_DISTANCE_BITS 24U +#define BROTLI_DISTANCE_ALPHABET_SIZE(NPOSTFIX, NDIRECT, MAXNBITS) ( \ + BROTLI_NUM_DISTANCE_SHORT_CODES + (NDIRECT) + \ + ((MAXNBITS) << ((NPOSTFIX) + 1))) +/* BROTLI_NUM_DISTANCE_SYMBOLS == 1128 */ +#define BROTLI_NUM_DISTANCE_SYMBOLS \ + BROTLI_DISTANCE_ALPHABET_SIZE( \ + BROTLI_MAX_NDIRECT, BROTLI_MAX_NPOSTFIX, BROTLI_LARGE_MAX_DISTANCE_BITS) + +/* ((1 << 26) - 4) is the maximal distance that can be expressed in RFC 7932 + brotli stream using NPOSTFIX = 0 and NDIRECT = 0. With other NPOSTFIX and + NDIRECT values distances up to ((1 << 29) + 88) could be expressed. */ +#define BROTLI_MAX_DISTANCE 0x3FFFFFC + +/* ((1 << 31) - 4) is the safe distance limit. Using this number as a limit + allows safe distance calculation without overflows, given the distance + alphabet size is limited to corresponding size + (see kLargeWindowDistanceCodeLimits). */ +#define BROTLI_MAX_ALLOWED_DISTANCE 0x7FFFFFFC + + +/* Specification: 4. Encoding of Literal Insertion Lengths and Copy Lengths */ +#define BROTLI_NUM_INS_COPY_CODES 24 + +/* 7.1. Context modes and context ID lookup for literals */ +/* "context IDs for literals are in the range of 0..63" */ +#define BROTLI_LITERAL_CONTEXT_BITS 6 + +/* 7.2. Context ID for distances */ +#define BROTLI_DISTANCE_CONTEXT_BITS 2 + +/* 9.1. Format of the Stream Header */ +/* Number of slack bytes for window size. Don't confuse + with BROTLI_NUM_DISTANCE_SHORT_CODES. */ +#define BROTLI_WINDOW_GAP 16 +#define BROTLI_MAX_BACKWARD_LIMIT(W) (((size_t)1 << (W)) - BROTLI_WINDOW_GAP) + +typedef struct BrotliDistanceCodeLimit { + uint32_t max_alphabet_size; + uint32_t max_distance; +} BrotliDistanceCodeLimit; + +/* This function calculates maximal size of distance alphabet, such that the + distances greater than the given values can not be represented. + + This limits are designed to support fast and safe 32-bit decoders. + "32-bit" means that signed integer values up to ((1 << 31) - 1) could be + safely expressed. + + Brotli distance alphabet symbols do not represent consecutive distance + ranges. Each distance alphabet symbol (excluding direct distances and short + codes), represent interleaved (for NPOSTFIX > 0) range of distances. + A "group" of consecutive (1 << NPOSTFIX) symbols represent non-interleaved + range. Two consecutive groups require the same amount of "extra bits". + + It is important that distance alphabet represents complete "groups". + To avoid complex logic on encoder side about interleaved ranges + it was decided to restrict both sides to complete distance code "groups". + */ +BROTLI_UNUSED_FUNCTION BrotliDistanceCodeLimit BrotliCalculateDistanceCodeLimit( + uint32_t max_distance, uint32_t npostfix, uint32_t ndirect) { + BrotliDistanceCodeLimit result; + /* Marking this function as unused, because not all files + including "constants.h" use it -> compiler warns about that. */ + BROTLI_UNUSED(&BrotliCalculateDistanceCodeLimit); + if (max_distance <= ndirect) { + /* This case never happens / exists only for the sake of completeness. */ + result.max_alphabet_size = max_distance + BROTLI_NUM_DISTANCE_SHORT_CODES; + result.max_distance = max_distance; + return result; + } else { + /* The first prohibited value. */ + uint32_t forbidden_distance = max_distance + 1; + /* Subtract "directly" encoded region. */ + uint32_t offset = forbidden_distance - ndirect - 1; + uint32_t ndistbits = 0; + uint32_t tmp; + uint32_t half; + uint32_t group; + /* Postfix for the last dcode in the group. */ + uint32_t postfix = (1u << npostfix) - 1; + uint32_t extra; + uint32_t start; + /* Remove postfix and "head-start". */ + offset = (offset >> npostfix) + 4; + /* Calculate the number of distance bits. */ + tmp = offset / 2; + /* Poor-man's log2floor, to avoid extra dependencies. */ + while (tmp != 0) {ndistbits++; tmp = tmp >> 1;} + /* One bit is covered with subrange addressing ("half"). */ + ndistbits--; + /* Find subrange. */ + half = (offset >> ndistbits) & 1; + /* Calculate the "group" part of dcode. */ + group = ((ndistbits - 1) << 1) | half; + /* Calculated "group" covers the prohibited distance value. */ + if (group == 0) { + /* This case is added for correctness; does not occur for limit > 128. */ + result.max_alphabet_size = ndirect + BROTLI_NUM_DISTANCE_SHORT_CODES; + result.max_distance = ndirect; + return result; + } + /* Decrement "group", so it is the last permitted "group". */ + group--; + /* After group was decremented, ndistbits and half must be recalculated. */ + ndistbits = (group >> 1) + 1; + /* The last available distance in the subrange has all extra bits set. */ + extra = (1u << ndistbits) - 1; + /* Calculate region start. NB: ndistbits >= 1. */ + start = (1u << (ndistbits + 1)) - 4; + /* Move to subregion. */ + start += (group & 1) << ndistbits; + /* Calculate the alphabet size. */ + result.max_alphabet_size = ((group << npostfix) | postfix) + ndirect + + BROTLI_NUM_DISTANCE_SHORT_CODES + 1; + /* Calculate the maximal distance representable by alphabet. */ + result.max_distance = ((start + extra) << npostfix) + postfix + ndirect + 1; + return result; + } +} + +/* Represents the range of values belonging to a prefix code: + [offset, offset + 2^nbits) */ +typedef struct { + uint16_t offset; + uint8_t nbits; +} BrotliPrefixCodeRange; + +/* "Soft-private", it is exported, but not "advertised" as API. */ +BROTLI_COMMON_API extern const BrotliPrefixCodeRange + _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS]; + +} +#endif /* BROTLI_COMMON_CONSTANTS_H_ */ diff --git a/third_party/brotli/common/brotli_platform.h b/third_party/brotli/common/brotli_platform.h new file mode 100644 index 00000000000..e5fa77b40b9 --- /dev/null +++ b/third_party/brotli/common/brotli_platform.h @@ -0,0 +1,543 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +Distributed under MIT license. +See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Macros for compiler / platform specific features and build options. + + Build options are: + * BROTLI_BUILD_32_BIT disables 64-bit optimizations + * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations + * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations + * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations + * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations + * BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs + * BROTLI_BUILD_NO_UNALIGNED_READ_FAST forces off the fast-unaligned-read + optimizations (mainly for testing purposes) + * BROTLI_DEBUG dumps file name and line number when decoder detects stream + or memory error + * BROTLI_ENABLE_LOG enables asserts and dumps various state information + * BROTLI_ENABLE_DUMP overrides default "dump" behaviour +*/ + +#ifndef BROTLI_COMMON_PLATFORM_H_ +#define BROTLI_COMMON_PLATFORM_H_ + +#include /* memcpy */ + +#include +#include + +#if defined(OS_LINUX) || defined(OS_CYGWIN) || defined(__EMSCRIPTEN__) +#include +#elif defined(OS_FREEBSD) +#include +#elif defined(OS_MACOSX) +#include +/* Let's try and follow the Linux convention */ +#define BROTLI_X_BYTE_ORDER BYTE_ORDER +#define BROTLI_X_LITTLE_ENDIAN LITTLE_ENDIAN +#define BROTLI_X_BIG_ENDIAN BIG_ENDIAN +#endif + +#if BROTLI_MSVC_VERSION_CHECK(18, 0, 0) +#include +#endif + +#if defined(BROTLI_ENABLE_LOG) || defined(BROTLI_DEBUG) +#include +#include +#endif + +/* The following macros were borrowed from https://github.com/nemequ/hedley +* with permission of original author - Evan Nemerson */ + +/* >>> >>> >>> hedley macros */ + +/* Define "BROTLI_PREDICT_TRUE" and "BROTLI_PREDICT_FALSE" macros for capable + compilers. + +To apply compiler hint, enclose the branching condition into macros, like this: + + if (BROTLI_PREDICT_TRUE(zero == 0)) { + // main execution path + } else { + // compiler should place this code outside of main execution path + } + +OR: + + if (BROTLI_PREDICT_FALSE(something_rare_or_unexpected_happens)) { + // compiler should place this code outside of main execution path + } + +*/ +#if BROTLI_GNUC_HAS_BUILTIN(__builtin_expect, 3, 0, 0) || \ + BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ + BROTLI_SUNPRO_VERSION_CHECK(5, 15, 0) || \ + BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ + BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ + BROTLI_TI_VERSION_CHECK(7, 3, 0) || \ + BROTLI_TINYC_VERSION_CHECK(0, 9, 27) +#define BROTLI_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) +#define BROTLI_PREDICT_FALSE(x) (__builtin_expect(x, 0)) +#else +#define BROTLI_PREDICT_FALSE(x) (x) +#define BROTLI_PREDICT_TRUE(x) (x) +#endif + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__cplusplus) +#define BROTLI_RESTRICT restrict +#elif BROTLI_GNUC_VERSION_CHECK(3, 1, 0) || \ + BROTLI_MSVC_VERSION_CHECK(14, 0, 0) || \ + BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ + BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ + BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ + BROTLI_PGI_VERSION_CHECK(17, 10, 0) || \ + BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ + BROTLI_IAR_VERSION_CHECK(8, 0, 0) || \ + (BROTLI_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus)) +#define BROTLI_RESTRICT __restrict +#elif BROTLI_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus) +#define BROTLI_RESTRICT _Restrict +#else +#define BROTLI_RESTRICT +#endif + +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) +#define BROTLI_MAYBE_INLINE inline +#elif defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__) || \ + BROTLI_ARM_VERSION_CHECK(6, 2, 0) +#define BROTLI_MAYBE_INLINE __inline__ +#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0) || \ + BROTLI_ARM_VERSION_CHECK(4, 1, 0) || BROTLI_TI_VERSION_CHECK(8, 0, 0) +#define BROTLI_MAYBE_INLINE __inline +#else +#define BROTLI_MAYBE_INLINE +#endif + +#if BROTLI_GNUC_HAS_ATTRIBUTE(always_inline, 4, 0, 0) || \ + BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ + BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ + BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ + BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ + (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) +#define BROTLI_INLINE BROTLI_MAYBE_INLINE __attribute__((__always_inline__)) +#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0) +#define BROTLI_INLINE BROTLI_MAYBE_INLINE __forceinline +#elif BROTLI_TI_VERSION_CHECK(7, 0, 0) && defined(__cplusplus) +#define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif BROTLI_IAR_VERSION_CHECK(8, 0, 0) +#define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma("inline=forced") +#else +#define BROTLI_INLINE BROTLI_MAYBE_INLINE +#endif + +#if BROTLI_GNUC_HAS_ATTRIBUTE(noinline, 4, 0, 0) || \ + BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ + BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ + BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ + BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ + (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) +#define BROTLI_NOINLINE __attribute__((__noinline__)) +#elif BROTLI_MSVC_VERSION_CHECK(13, 10, 0) +#define BROTLI_NOINLINE __declspec(noinline) +#elif BROTLI_PGI_VERSION_CHECK(10, 2, 0) +#define BROTLI_NOINLINE _Pragma("noinline") +#elif BROTLI_TI_VERSION_CHECK(6, 0, 0) && defined(__cplusplus) +#define BROTLI_NOINLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif BROTLI_IAR_VERSION_CHECK(8, 0, 0) +#define BROTLI_NOINLINE _Pragma("inline=never") +#else +#define BROTLI_NOINLINE +#endif + +/* <<< <<< <<< end of hedley macros. */ + +#if BROTLI_GNUC_HAS_ATTRIBUTE(unused, 2, 7, 0) || \ + BROTLI_INTEL_VERSION_CHECK(16, 0, 0) +#define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE __attribute__ ((unused)) +#else +#define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE +#endif + +#if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) +#define BROTLI_ALIGNED(N) __attribute__((aligned(N))) +#else +#define BROTLI_ALIGNED(N) +#endif + +#if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \ + (defined(M_ARM) && (M_ARM == 7)) +#define BROTLI_TARGET_ARMV7 +#endif /* ARMv7 */ + +#if (defined(__ARM_ARCH) && (__ARM_ARCH == 8)) || \ + defined(__aarch64__) || defined(__ARM64_ARCH_8__) +#define BROTLI_TARGET_ARMV8_ANY + +#if defined(__ARM_32BIT_STATE) +#define BROTLI_TARGET_ARMV8_32 +#elif defined(__ARM_64BIT_STATE) +#define BROTLI_TARGET_ARMV8_64 +#endif + +#endif /* ARMv8 */ + +#if defined(__ARM_NEON__) || defined(__ARM_NEON) +#define BROTLI_TARGET_NEON +#endif + +#if defined(__i386) || defined(_M_IX86) +#define BROTLI_TARGET_X86 +#endif + +#if defined(__x86_64__) || defined(_M_X64) +#define BROTLI_TARGET_X64 +#endif + +#if defined(__PPC64__) +#define BROTLI_TARGET_POWERPC64 +#endif + +#if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64 +#define BROTLI_TARGET_RISCV64 +#endif + +#if defined(__loongarch_lp64) +#define BROTLI_TARGET_LOONGARCH64 +#endif + +#if defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \ + defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64) || \ + defined(BROTLI_TARGET_LOONGARCH64) +#define BROTLI_TARGET_64_BITS 1 +#else +#define BROTLI_TARGET_64_BITS 0 +#endif + +#if defined(BROTLI_BUILD_64_BIT) +#define BROTLI_64_BITS 1 +#elif defined(BROTLI_BUILD_32_BIT) +#define BROTLI_64_BITS 0 +#else +#define BROTLI_64_BITS BROTLI_TARGET_64_BITS +#endif + +#if (BROTLI_64_BITS) +#define brotli_reg_t uint64_t +#else +#define brotli_reg_t uint32_t +#endif + +#if defined(BROTLI_BUILD_BIG_ENDIAN) +#define BROTLI_BIG_ENDIAN 1 +#elif defined(BROTLI_BUILD_LITTLE_ENDIAN) +#define BROTLI_LITTLE_ENDIAN 1 +#elif defined(BROTLI_BUILD_ENDIAN_NEUTRAL) +/* Just break elif chain. */ +#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#define BROTLI_LITTLE_ENDIAN 1 +#elif defined(_WIN32) || defined(BROTLI_TARGET_X64) +/* Win32 & x64 can currently always be assumed to be little endian */ +#define BROTLI_LITTLE_ENDIAN 1 +#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#define BROTLI_BIG_ENDIAN 1 +#elif defined(BROTLI_X_BYTE_ORDER) +#if BROTLI_X_BYTE_ORDER == BROTLI_X_LITTLE_ENDIAN +#define BROTLI_LITTLE_ENDIAN 1 +#elif BROTLI_X_BYTE_ORDER == BROTLI_X_BIG_ENDIAN +#define BROTLI_BIG_ENDIAN 1 +#endif +#endif /* BROTLI_X_BYTE_ORDER */ + +#if !defined(BROTLI_LITTLE_ENDIAN) +#define BROTLI_LITTLE_ENDIAN 0 +#endif + +#if !defined(BROTLI_BIG_ENDIAN) +#define BROTLI_BIG_ENDIAN 0 +#endif + +#if defined(BROTLI_X_BYTE_ORDER) +#undef BROTLI_X_BYTE_ORDER +#undef BROTLI_X_LITTLE_ENDIAN +#undef BROTLI_X_BIG_ENDIAN +#endif + +#if defined(BROTLI_BUILD_NO_UNALIGNED_READ_FAST) +#define BROTLI_UNALIGNED_READ_FAST (!!0) +#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \ + defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) || \ + defined(BROTLI_TARGET_RISCV64) || defined(BROTLI_TARGET_LOONGARCH64) +/* These targets are known to generate efficient code for unaligned reads +* (e.g. a single instruction, not multiple 1-byte loads, shifted and or'd +* together). */ +#define BROTLI_UNALIGNED_READ_FAST (!!1) +#else +#define BROTLI_UNALIGNED_READ_FAST (!!0) +#endif + +/* Portable unaligned memory access: read / write values via memcpy. */ +static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) { + uint16_t t; + memcpy(&t, p, sizeof t); + return t; +} +static BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) { + uint32_t t; + memcpy(&t, p, sizeof t); + return t; +} +static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) { + uint64_t t; + memcpy(&t, p, sizeof t); + return t; +} +static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) { + memcpy(p, &v, sizeof v); +} + +#if BROTLI_LITTLE_ENDIAN +/* Straight endianness. Just read / write values. */ +#define BROTLI_UNALIGNED_LOAD16LE BrotliUnalignedRead16 +#define BROTLI_UNALIGNED_LOAD32LE BrotliUnalignedRead32 +#define BROTLI_UNALIGNED_LOAD64LE BrotliUnalignedRead64 +#define BROTLI_UNALIGNED_STORE64LE BrotliUnalignedWrite64 +#elif BROTLI_BIG_ENDIAN /* BROTLI_LITTLE_ENDIAN */ +/* Explain compiler to byte-swap values. */ +#define BROTLI_BSWAP16_(V) ((uint16_t)( \ +(((V) & 0xFFU) << 8) | \ +(((V) >> 8) & 0xFFU))) +static BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) { + uint16_t value = BrotliUnalignedRead16(p); + return BROTLI_BSWAP16_(value); +} +#define BROTLI_BSWAP32_(V) ( \ +(((V) & 0xFFU) << 24) | (((V) & 0xFF00U) << 8) | \ +(((V) >> 8) & 0xFF00U) | (((V) >> 24) & 0xFFU)) +static BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) { + uint32_t value = BrotliUnalignedRead32(p); + return BROTLI_BSWAP32_(value); +} +#define BROTLI_BSWAP64_(V) ( \ +(((V) & 0xFFU) << 56) | (((V) & 0xFF00U) << 40) | \ +(((V) & 0xFF0000U) << 24) | (((V) & 0xFF000000U) << 8) | \ +(((V) >> 8) & 0xFF000000U) | (((V) >> 24) & 0xFF0000U) | \ +(((V) >> 40) & 0xFF00U) | (((V) >> 56) & 0xFFU)) +static BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64LE(const void* p) { + uint64_t value = BrotliUnalignedRead64(p); + return BROTLI_BSWAP64_(value); +} +static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) { + uint64_t value = BROTLI_BSWAP64_(v); + BrotliUnalignedWrite64(p, value); +} +#else /* BROTLI_LITTLE_ENDIAN */ +/* Read / store values byte-wise; hopefully compiler will understand. */ +static BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) { + const uint8_t* in = (const uint8_t*)p; + return (uint16_t)(in[0] | (in[1] << 8)); +} +static BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) { + const uint8_t* in = (const uint8_t*)p; + uint32_t value = (uint32_t)(in[0]); + value |= (uint32_t)(in[1]) << 8; + value |= (uint32_t)(in[2]) << 16; + value |= (uint32_t)(in[3]) << 24; + return value; +} +static BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64LE(const void* p) { + const uint8_t* in = (const uint8_t*)p; + uint64_t value = (uint64_t)(in[0]); + value |= (uint64_t)(in[1]) << 8; + value |= (uint64_t)(in[2]) << 16; + value |= (uint64_t)(in[3]) << 24; + value |= (uint64_t)(in[4]) << 32; + value |= (uint64_t)(in[5]) << 40; + value |= (uint64_t)(in[6]) << 48; + value |= (uint64_t)(in[7]) << 56; + return value; +} +static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) { + uint8_t* out = (uint8_t*)p; + out[0] = (uint8_t)v; + out[1] = (uint8_t)(v >> 8); + out[2] = (uint8_t)(v >> 16); + out[3] = (uint8_t)(v >> 24); + out[4] = (uint8_t)(v >> 32); + out[5] = (uint8_t)(v >> 40); + out[6] = (uint8_t)(v >> 48); + out[7] = (uint8_t)(v >> 56); +} +#endif /* BROTLI_LITTLE_ENDIAN */ + +static BROTLI_INLINE void* BROTLI_UNALIGNED_LOAD_PTR(const void* p) { + void* v; + memcpy(&v, p, sizeof(void*)); + return v; +} + +static BROTLI_INLINE void BROTLI_UNALIGNED_STORE_PTR(void* p, const void* v) { + memcpy(p, &v, sizeof(void*)); +} + +/* BROTLI_IS_CONSTANT macros returns true for compile-time constants. */ +#if BROTLI_GNUC_HAS_BUILTIN(__builtin_constant_p, 3, 0, 1) || \ + BROTLI_INTEL_VERSION_CHECK(16, 0, 0) +#define BROTLI_IS_CONSTANT(x) (!!__builtin_constant_p(x)) +#else +#define BROTLI_IS_CONSTANT(x) (!!0) +#endif + +#if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) +#define BROTLI_HAS_UBFX (!!1) +#else +#define BROTLI_HAS_UBFX (!!0) +#endif + +#if defined(BROTLI_ENABLE_LOG) +#define BROTLI_LOG(x) printf x +#else +#define BROTLI_LOG(x) +#endif + +#if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG) +#define BROTLI_ENABLE_DUMP_DEFAULT 1 +#define BROTLI_DCHECK(x) assert(x) +#else +#define BROTLI_ENABLE_DUMP_DEFAULT 0 +#define BROTLI_DCHECK(x) +#endif + +#if !defined(BROTLI_ENABLE_DUMP) +#define BROTLI_ENABLE_DUMP BROTLI_ENABLE_DUMP_DEFAULT +#endif + +#if BROTLI_ENABLE_DUMP +static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) { + fprintf(stderr, "%s:%d (%s)\n", f, l, fn); + fflush(stderr); +} +#define BROTLI_DUMP() BrotliDump(__FILE__, __LINE__, __FUNCTION__) +#else +#define BROTLI_DUMP() (void)(0) +#endif + +/* BrotliRBit assumes brotli_reg_t fits native CPU register type. */ +#if (BROTLI_64_BITS == BROTLI_TARGET_64_BITS) +/* TODO(eustas): add appropriate icc/sunpro/arm/ibm/ti checks. */ +#if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \ + !defined(BROTLI_BUILD_NO_RBIT) +#if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) +/* TODO(eustas): detect ARMv6T2 and enable this code for it. */ +static BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) { + brotli_reg_t output; + __asm__("rbit %0, %1\n" : "=r"(output) : "r"(input)); + return output; +} +#define BROTLI_RBIT(x) BrotliRBit(x) +#endif /* armv7 / armv8 */ +#endif /* gcc || clang */ +#endif /* brotli_reg_t is native */ +#if !defined(BROTLI_RBIT) +static BROTLI_INLINE void BrotliRBit(void) { /* Should break build if used. */ } +#endif /* BROTLI_RBIT */ + +#define BROTLI_REPEAT_4(X) {X; X; X; X;} +#define BROTLI_REPEAT_5(X) {X; X; X; X; X;} +#define BROTLI_REPEAT_6(X) {X; X; X; X; X; X;} + +#define BROTLI_UNUSED(X) (void)(X) + +#define BROTLI_MIN_MAX(T) \ +static BROTLI_INLINE T brotli_min_ ## T (T a, T b) { return a < b ? a : b; } \ +static BROTLI_INLINE T brotli_max_ ## T (T a, T b) { return a > b ? a : b; } +BROTLI_MIN_MAX(double) BROTLI_MIN_MAX(float) BROTLI_MIN_MAX(int) + BROTLI_MIN_MAX(size_t) BROTLI_MIN_MAX(uint32_t) BROTLI_MIN_MAX(uint8_t) +#undef BROTLI_MIN_MAX +#define BROTLI_MIN(T, A, B) (brotli_min_ ## T((A), (B))) +#define BROTLI_MAX(T, A, B) (brotli_max_ ## T((A), (B))) + +#define BROTLI_SWAP(T, A, I, J) { \ +T __brotli_swap_tmp = (A)[(I)]; \ +(A)[(I)] = (A)[(J)]; \ +(A)[(J)] = __brotli_swap_tmp; \ +} + +#if BROTLI_64_BITS +#if BROTLI_GNUC_HAS_BUILTIN(__builtin_ctzll, 3, 4, 0) || \ + BROTLI_INTEL_VERSION_CHECK(16, 0, 0) +#define BROTLI_TZCNT64 __builtin_ctzll +#elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0) +#if defined(BROTLI_TARGET_X64) +#define BROTLI_TZCNT64 _tzcnt_u64 +#else /* BROTLI_TARGET_X64 */ + static BROTLI_INLINE uint32_t BrotliBsf64Msvc(uint64_t x) { + uint32_t lsb; + _BitScanForward64(&lsb, x); + return lsb; +} +#define BROTLI_TZCNT64 BrotliBsf64Msvc +#endif /* BROTLI_TARGET_X64 */ +#endif /* __builtin_ctzll */ +#endif /* BROTLI_64_BITS */ + +#if BROTLI_GNUC_HAS_BUILTIN(__builtin_clz, 3, 4, 0) || \ + BROTLI_INTEL_VERSION_CHECK(16, 0, 0) +#define BROTLI_BSR32(x) (31u ^ (uint32_t)__builtin_clz(x)) +#elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0) + static BROTLI_INLINE uint32_t BrotliBsr32Msvc(uint32_t x) { + unsigned long msb; + _BitScanReverse(&msb, x); + return (uint32_t)msb; +} +#define BROTLI_BSR32 BrotliBsr32Msvc +#endif /* __builtin_clz */ + + namespace duckdb_brotli { + + /* Default brotli_alloc_func */ + BROTLI_COMMON_API void *BrotliDefaultAllocFunc(void *opaque, size_t size); + + /* Default brotli_free_func */ + BROTLI_COMMON_API void BrotliDefaultFreeFunc(void *opaque, void *address); + + BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) { + BROTLI_UNUSED(&BrotliSuppressUnusedFunctions); + BROTLI_UNUSED(&BrotliUnalignedRead16); + BROTLI_UNUSED(&BrotliUnalignedRead32); + BROTLI_UNUSED(&BrotliUnalignedRead64); + BROTLI_UNUSED(&BrotliUnalignedWrite64); + BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD16LE); + BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD32LE); + BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD64LE); + BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE64LE); + BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD_PTR); + BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE_PTR); + BROTLI_UNUSED(&BrotliRBit); + BROTLI_UNUSED(&brotli_min_double); + BROTLI_UNUSED(&brotli_max_double); + BROTLI_UNUSED(&brotli_min_float); + BROTLI_UNUSED(&brotli_max_float); + BROTLI_UNUSED(&brotli_min_int); + BROTLI_UNUSED(&brotli_max_int); + BROTLI_UNUSED(&brotli_min_size_t); + BROTLI_UNUSED(&brotli_max_size_t); + BROTLI_UNUSED(&brotli_min_uint32_t); + BROTLI_UNUSED(&brotli_max_uint32_t); + BROTLI_UNUSED(&brotli_min_uint8_t); + BROTLI_UNUSED(&brotli_max_uint8_t); + BROTLI_UNUSED(&BrotliDefaultAllocFunc); + BROTLI_UNUSED(&BrotliDefaultFreeFunc); +#if BROTLI_ENABLE_DUMP + BROTLI_UNUSED(&BrotliDump); +#endif + } +} +#endif /* BROTLI_COMMON_PLATFORM_H_ */ \ No newline at end of file diff --git a/third_party/brotli/common/constants.cpp b/third_party/brotli/common/constants.cpp new file mode 100644 index 00000000000..23f291c2829 --- /dev/null +++ b/third_party/brotli/common/constants.cpp @@ -0,0 +1,17 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include "brotli_constants.h" + +using namespace duckdb_brotli; + +const BrotliPrefixCodeRange + duckdb_brotli::_kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = { + {1, 2}, {5, 2}, {9, 2}, {13, 2}, {17, 3}, {25, 3}, + {33, 3}, {41, 3}, {49, 4}, {65, 4}, {81, 4}, {97, 4}, + {113, 5}, {145, 5}, {177, 5}, {209, 5}, {241, 6}, {305, 6}, + {369, 7}, {497, 8}, {753, 9}, {1265, 10}, {2289, 11}, {4337, 12}, + {8433, 13}, {16625, 24}}; diff --git a/third_party/brotli/common/context.cpp b/third_party/brotli/common/context.cpp new file mode 100644 index 00000000000..2cc58005ab7 --- /dev/null +++ b/third_party/brotli/common/context.cpp @@ -0,0 +1,156 @@ +#include "context.h" + +#include + +/* Common context lookup table for all context modes. */ +const uint8_t duckdb_brotli::_kBrotliContextLookupTable[2048] = { + /* CONTEXT_LSB6, last byte. */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + + /* CONTEXT_LSB6, second last byte, */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + /* CONTEXT_MSB6, last byte. */ + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, + 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, + 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, + 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, + 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, + 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, + 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, + 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, + 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, + 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, + 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, + 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, 59, + 60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63, + + /* CONTEXT_MSB6, second last byte, */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + /* CONTEXT_UTF8, last byte. */ + /* ASCII range. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 12, 16, 12, 12, 20, 12, 16, 24, 28, 12, 12, 32, 12, 36, 12, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 32, 32, 24, 40, 28, 12, + 12, 48, 52, 52, 52, 48, 52, 52, 52, 48, 52, 52, 52, 52, 52, 48, + 52, 52, 52, 52, 52, 48, 52, 52, 52, 52, 52, 24, 12, 28, 12, 12, + 12, 56, 60, 60, 60, 56, 60, 60, 60, 56, 60, 60, 60, 60, 60, 56, + 60, 60, 60, 60, 60, 56, 60, 60, 60, 60, 60, 24, 12, 28, 12, 0, + /* UTF8 continuation byte range. */ + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + /* UTF8 lead byte range. */ + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + + /* CONTEXT_UTF8 second last byte. */ + /* ASCII range. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, + 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 0, + /* UTF8 continuation byte range. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* UTF8 lead byte range. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + + /* CONTEXT_SIGNED, last byte, same as the above values shifted by 3 bits. */ + 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 56, + + /* CONTEXT_SIGNED, second last byte. */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, +}; diff --git a/third_party/brotli/common/context.h b/third_party/brotli/common/context.h new file mode 100644 index 00000000000..4e575528fce --- /dev/null +++ b/third_party/brotli/common/context.h @@ -0,0 +1,110 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Lookup table to map the previous two bytes to a context id. + + There are four different context modeling modes defined here: + CONTEXT_LSB6: context id is the least significant 6 bits of the last byte, + CONTEXT_MSB6: context id is the most significant 6 bits of the last byte, + CONTEXT_UTF8: second-order context model tuned for UTF8-encoded text, + CONTEXT_SIGNED: second-order context model tuned for signed integers. + + If |p1| and |p2| are the previous two bytes, and |mode| is current context + mode, we calculate the context as: + + context = ContextLut(mode)[p1] | ContextLut(mode)[p2 + 256]. + + For CONTEXT_UTF8 mode, if the previous two bytes are ASCII characters + (i.e. < 128), this will be equivalent to + + context = 4 * context1(p1) + context2(p2), + + where context1 is based on the previous byte in the following way: + + 0 : non-ASCII control + 1 : \t, \n, \r + 2 : space + 3 : other punctuation + 4 : " ' + 5 : % + 6 : ( < [ { + 7 : ) > ] } + 8 : , ; : + 9 : . + 10 : = + 11 : number + 12 : upper-case vowel + 13 : upper-case consonant + 14 : lower-case vowel + 15 : lower-case consonant + + and context2 is based on the second last byte: + + 0 : control, space + 1 : punctuation + 2 : upper-case letter, number + 3 : lower-case letter + + If the last byte is ASCII, and the second last byte is not (in a valid UTF8 + stream it will be a continuation byte, value between 128 and 191), the + context is the same as if the second last byte was an ASCII control or space. + + If the last byte is a UTF8 lead byte (value >= 192), then the next byte will + be a continuation byte and the context id is 2 or 3 depending on the LSB of + the last byte and to a lesser extent on the second last byte if it is ASCII. + + If the last byte is a UTF8 continuation byte, the second last byte can be: + - continuation byte: the next byte is probably ASCII or lead byte (assuming + 4-byte UTF8 characters are rare) and the context id is 0 or 1. + - lead byte (192 - 207): next byte is ASCII or lead byte, context is 0 or 1 + - lead byte (208 - 255): next byte is continuation byte, context is 2 or 3 + + The possible value combinations of the previous two bytes, the range of + context ids and the type of the next byte is summarized in the table below: + + |--------\-----------------------------------------------------------------| + | \ Last byte | + | Second \---------------------------------------------------------------| + | last byte \ ASCII | cont. byte | lead byte | + | \ (0-127) | (128-191) | (192-) | + |=============|===================|=====================|==================| + | ASCII | next: ASCII/lead | not valid | next: cont. | + | (0-127) | context: 4 - 63 | | context: 2 - 3 | + |-------------|-------------------|---------------------|------------------| + | cont. byte | next: ASCII/lead | next: ASCII/lead | next: cont. | + | (128-191) | context: 4 - 63 | context: 0 - 1 | context: 2 - 3 | + |-------------|-------------------|---------------------|------------------| + | lead byte | not valid | next: ASCII/lead | not valid | + | (192-207) | | context: 0 - 1 | | + |-------------|-------------------|---------------------|------------------| + | lead byte | not valid | next: cont. | not valid | + | (208-) | | context: 2 - 3 | | + |-------------|-------------------|---------------------|------------------| +*/ + +#ifndef BROTLI_COMMON_CONTEXT_H_ +#define BROTLI_COMMON_CONTEXT_H_ + +#include +#include + +namespace duckdb_brotli { + +typedef enum ContextType { CONTEXT_LSB6 = 0, CONTEXT_MSB6 = 1, CONTEXT_UTF8 = 2, CONTEXT_SIGNED = 3 } ContextType; + +/* "Soft-private", it is exported, but not "advertised" as API. */ +/* Common context lookup table for all context modes. */ +BROTLI_COMMON_API extern const uint8_t _kBrotliContextLookupTable[2048]; + +typedef const uint8_t *ContextLut; + +/* typeof(MODE) == ContextType; returns ContextLut */ +#define BROTLI_CONTEXT_LUT(MODE) (&_kBrotliContextLookupTable[(MODE) << 9]) + +/* typeof(LUT) == ContextLut */ +#define BROTLI_CONTEXT(P1, P2, LUT) ((LUT)[P1] | ((LUT) + 256)[P2]) +} +#endif /* BROTLI_COMMON_CONTEXT_H_ */ diff --git a/third_party/brotli/common/dictionary.cpp b/third_party/brotli/common/dictionary.cpp new file mode 100644 index 00000000000..78bec35d8fa --- /dev/null +++ b/third_party/brotli/common/dictionary.cpp @@ -0,0 +1,5912 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include "dictionary.h" +#include "brotli_platform.h" + +using namespace duckdb_brotli; + +#if !defined(BROTLI_EXTERNAL_DICTIONARY_DATA) +static const uint8_t kBrotliDictionaryData[] = +/* GENERATED CODE START */ +{ +116,105,109,101,100,111,119,110,108,105,102,101,108,101,102,116,98,97,99,107,99, +111,100,101,100,97,116,97,115,104,111,119,111,110,108,121,115,105,116,101,99,105 +,116,121,111,112,101,110,106,117,115,116,108,105,107,101,102,114,101,101,119,111 +,114,107,116,101,120,116,121,101,97,114,111,118,101,114,98,111,100,121,108,111, +118,101,102,111,114,109,98,111,111,107,112,108,97,121,108,105,118,101,108,105, +110,101,104,101,108,112,104,111,109,101,115,105,100,101,109,111,114,101,119,111, +114,100,108,111,110,103,116,104,101,109,118,105,101,119,102,105,110,100,112,97, +103,101,100,97,121,115,102,117,108,108,104,101,97,100,116,101,114,109,101,97,99, +104,97,114,101,97,102,114,111,109,116,114,117,101,109,97,114,107,97,98,108,101, +117,112,111,110,104,105,103,104,100,97,116,101,108,97,110,100,110,101,119,115, +101,118,101,110,110,101,120,116,99,97,115,101,98,111,116,104,112,111,115,116,117 +,115,101,100,109,97,100,101,104,97,110,100,104,101,114,101,119,104,97,116,110,97 +,109,101,76,105,110,107,98,108,111,103,115,105,122,101,98,97,115,101,104,101,108 +,100,109,97,107,101,109,97,105,110,117,115,101,114,39,41,32,43,104,111,108,100, +101,110,100,115,119,105,116,104,78,101,119,115,114,101,97,100,119,101,114,101, +115,105,103,110,116,97,107,101,104,97,118,101,103,97,109,101,115,101,101,110,99, +97,108,108,112,97,116,104,119,101,108,108,112,108,117,115,109,101,110,117,102, +105,108,109,112,97,114,116,106,111,105,110,116,104,105,115,108,105,115,116,103, +111,111,100,110,101,101,100,119,97,121,115,119,101,115,116,106,111,98,115,109, +105,110,100,97,108,115,111,108,111,103,111,114,105,99,104,117,115,101,115,108,97 +,115,116,116,101,97,109,97,114,109,121,102,111,111,100,107,105,110,103,119,105, +108,108,101,97,115,116,119,97,114,100,98,101,115,116,102,105,114,101,80,97,103, +101,107,110,111,119,97,119,97,121,46,112,110,103,109,111,118,101,116,104,97,110, +108,111,97,100,103,105,118,101,115,101,108,102,110,111,116,101,109,117,99,104, +102,101,101,100,109,97,110,121,114,111,99,107,105,99,111,110,111,110,99,101,108, +111,111,107,104,105,100,101,100,105,101,100,72,111,109,101,114,117,108,101,104, +111,115,116,97,106,97,120,105,110,102,111,99,108,117,98,108,97,119,115,108,101, +115,115,104,97,108,102,115,111,109,101,115,117,99,104,122,111,110,101,49,48,48, +37,111,110,101,115,99,97,114,101,84,105,109,101,114,97,99,101,98,108,117,101,102 +,111,117,114,119,101,101,107,102,97,99,101,104,111,112,101,103,97,118,101,104,97 +,114,100,108,111,115,116,119,104,101,110,112,97,114,107,107,101,112,116,112,97, +115,115,115,104,105,112,114,111,111,109,72,84,77,76,112,108,97,110,84,121,112, +101,100,111,110,101,115,97,118,101,107,101,101,112,102,108,97,103,108,105,110, +107,115,111,108,100,102,105,118,101,116,111,111,107,114,97,116,101,116,111,119, +110,106,117,109,112,116,104,117,115,100,97,114,107,99,97,114,100,102,105,108,101 +,102,101,97,114,115,116,97,121,107,105,108,108,116,104,97,116,102,97,108,108,97, +117,116,111,101,118,101,114,46,99,111,109,116,97,108,107,115,104,111,112,118,111 +,116,101,100,101,101,112,109,111,100,101,114,101,115,116,116,117,114,110,98,111, +114,110,98,97,110,100,102,101,108,108,114,111,115,101,117,114,108,40,115,107,105 +,110,114,111,108,101,99,111,109,101,97,99,116,115,97,103,101,115,109,101,101,116 +,103,111,108,100,46,106,112,103,105,116,101,109,118,97,114,121,102,101,108,116, +116,104,101,110,115,101,110,100,100,114,111,112,86,105,101,119,99,111,112,121,49 +,46,48,34,60,47,97,62,115,116,111,112,101,108,115,101,108,105,101,115,116,111, +117,114,112,97,99,107,46,103,105,102,112,97,115,116,99,115,115,63,103,114,97,121 +,109,101,97,110,38,103,116,59,114,105,100,101,115,104,111,116,108,97,116,101,115 +,97,105,100,114,111,97,100,118,97,114,32,102,101,101,108,106,111,104,110,114,105 +,99,107,112,111,114,116,102,97,115,116,39,85,65,45,100,101,97,100,60,47,98,62, +112,111,111,114,98,105,108,108,116,121,112,101,85,46,83,46,119,111,111,100,109, +117,115,116,50,112,120,59,73,110,102,111,114,97,110,107,119,105,100,101,119,97, +110,116,119,97,108,108,108,101,97,100,91,48,93,59,112,97,117,108,119,97,118,101, +115,117,114,101,36,40,39,35,119,97,105,116,109,97,115,115,97,114,109,115,103,111 +,101,115,103,97,105,110,108,97,110,103,112,97,105,100,33,45,45,32,108,111,99,107 +,117,110,105,116,114,111,111,116,119,97,108,107,102,105,114,109,119,105,102,101, +120,109,108,34,115,111,110,103,116,101,115,116,50,48,112,120,107,105,110,100,114 +,111,119,115,116,111,111,108,102,111,110,116,109,97,105,108,115,97,102,101,115, +116,97,114,109,97,112,115,99,111,114,101,114,97,105,110,102,108,111,119,98,97,98 +,121,115,112,97,110,115,97,121,115,52,112,120,59,54,112,120,59,97,114,116,115, +102,111,111,116,114,101,97,108,119,105,107,105,104,101,97,116,115,116,101,112, +116,114,105,112,111,114,103,47,108,97,107,101,119,101,97,107,116,111,108,100,70, +111,114,109,99,97,115,116,102,97,110,115,98,97,110,107,118,101,114,121,114,117, +110,115,106,117,108,121,116,97,115,107,49,112,120,59,103,111,97,108,103,114,101, +119,115,108,111,119,101,100,103,101,105,100,61,34,115,101,116,115,53,112,120,59, +46,106,115,63,52,48,112,120,105,102,32,40,115,111,111,110,115,101,97,116,110,111 +,110,101,116,117,98,101,122,101,114,111,115,101,110,116,114,101,101,100,102,97, +99,116,105,110,116,111,103,105,102,116,104,97,114,109,49,56,112,120,99,97,109, +101,104,105,108,108,98,111,108,100,122,111,111,109,118,111,105,100,101,97,115, +121,114,105,110,103,102,105,108,108,112,101,97,107,105,110,105,116,99,111,115, +116,51,112,120,59,106,97,99,107,116,97,103,115,98,105,116,115,114,111,108,108, +101,100,105,116,107,110,101,119,110,101,97,114,60,33,45,45,103,114,111,119,74,83 +,79,78,100,117,116,121,78,97,109,101,115,97,108,101,121,111,117,32,108,111,116, +115,112,97,105,110,106,97,122,122,99,111,108,100,101,121,101,115,102,105,115,104 +,119,119,119,46,114,105,115,107,116,97,98,115,112,114,101,118,49,48,112,120,114, +105,115,101,50,53,112,120,66,108,117,101,100,105,110,103,51,48,48,44,98,97,108, +108,102,111,114,100,101,97,114,110,119,105,108,100,98,111,120,46,102,97,105,114, +108,97,99,107,118,101,114,115,112,97,105,114,106,117,110,101,116,101,99,104,105, +102,40,33,112,105,99,107,101,118,105,108,36,40,34,35,119,97,114,109,108,111,114, +100,100,111,101,115,112,117,108,108,44,48,48,48,105,100,101,97,100,114,97,119, +104,117,103,101,115,112,111,116,102,117,110,100,98,117,114,110,104,114,101,102, +99,101,108,108,107,101,121,115,116,105,99,107,104,111,117,114,108,111,115,115, +102,117,101,108,49,50,112,120,115,117,105,116,100,101,97,108,82,83,83,34,97,103, +101,100,103,114,101,121,71,69,84,34,101,97,115,101,97,105,109,115,103,105,114, +108,97,105,100,115,56,112,120,59,110,97,118,121,103,114,105,100,116,105,112,115, +35,57,57,57,119,97,114,115,108,97,100,121,99,97,114,115,41,59,32,125,112,104,112 +,63,104,101,108,108,116,97,108,108,119,104,111,109,122,104,58,229,42,47,13,10,32 +,49,48,48,104,97,108,108,46,10,10,65,55,112,120,59,112,117,115,104,99,104,97,116 +,48,112,120,59,99,114,101,119,42,47,60,47,104,97,115,104,55,53,112,120,102,108, +97,116,114,97,114,101,32,38,38,32,116,101,108,108,99,97,109,112,111,110,116,111, +108,97,105,100,109,105,115,115,115,107,105,112,116,101,110,116,102,105,110,101, +109,97,108,101,103,101,116,115,112,108,111,116,52,48,48,44,13,10,13,10,99,111, +111,108,102,101,101,116,46,112,104,112,60,98,114,62,101,114,105,99,109,111,115, +116,103,117,105,100,98,101,108,108,100,101,115,99,104,97,105,114,109,97,116,104, +97,116,111,109,47,105,109,103,38,35,56,50,108,117,99,107,99,101,110,116,48,48,48 +,59,116,105,110,121,103,111,110,101,104,116,109,108,115,101,108,108,100,114,117, +103,70,82,69,69,110,111,100,101,110,105,99,107,63,105,100,61,108,111,115,101,110 +,117,108,108,118,97,115,116,119,105,110,100,82,83,83,32,119,101,97,114,114,101, +108,121,98,101,101,110,115,97,109,101,100,117,107,101,110,97,115,97,99,97,112, +101,119,105,115,104,103,117,108,102,84,50,51,58,104,105,116,115,115,108,111,116, +103,97,116,101,107,105,99,107,98,108,117,114,116,104,101,121,49,53,112,120,39,39 +,41,59,41,59,34,62,109,115,105,101,119,105,110,115,98,105,114,100,115,111,114, +116,98,101,116,97,115,101,101,107,84,49,56,58,111,114,100,115,116,114,101,101, +109,97,108,108,54,48,112,120,102,97,114,109,226,128,153,115,98,111,121,115,91,48 +,93,46,39,41,59,34,80,79,83,84,98,101,97,114,107,105,100,115,41,59,125,125,109, +97,114,121,116,101,110,100,40,85,75,41,113,117,97,100,122,104,58,230,45,115,105, +122,45,45,45,45,112,114,111,112,39,41,59,13,108,105,102,116,84,49,57,58,118,105, +99,101,97,110,100,121,100,101,98,116,62,82,83,83,112,111,111,108,110,101,99,107, +98,108,111,119,84,49,54,58,100,111,111,114,101,118,97,108,84,49,55,58,108,101, +116,115,102,97,105,108,111,114,97,108,112,111,108,108,110,111,118,97,99,111,108, +115,103,101,110,101,32,226,128,148,115,111,102,116,114,111,109,101,116,105,108, +108,114,111,115,115,60,104,51,62,112,111,117,114,102,97,100,101,112,105,110,107, +60,116,114,62,109,105,110,105,41,124,33,40,109,105,110,101,122,104,58,232,98,97, +114,115,104,101,97,114,48,48,41,59,109,105,108,107,32,45,45,62,105,114,111,110, +102,114,101,100,100,105,115,107,119,101,110,116,115,111,105,108,112,117,116,115, +47,106,115,47,104,111,108,121,84,50,50,58,73,83,66,78,84,50,48,58,97,100,97,109, +115,101,101,115,60,104,50,62,106,115,111,110,39,44,32,39,99,111,110,116,84,50,49 +,58,32,82,83,83,108,111,111,112,97,115,105,97,109,111,111,110,60,47,112,62,115, +111,117,108,76,73,78,69,102,111,114,116,99,97,114,116,84,49,52,58,60,104,49,62, +56,48,112,120,33,45,45,60,57,112,120,59,84,48,52,58,109,105,107,101,58,52,54,90, +110,105,99,101,105,110,99,104,89,111,114,107,114,105,99,101,122,104,58,228,39,41 +,41,59,112,117,114,101,109,97,103,101,112,97,114,97,116,111,110,101,98,111,110, +100,58,51,55,90,95,111,102,95,39,93,41,59,48,48,48,44,122,104,58,231,116,97,110, +107,121,97,114,100,98,111,119,108,98,117,115,104,58,53,54,90,74,97,118,97,51,48, +112,120,10,124,125,10,37,67,51,37,58,51,52,90,106,101,102,102,69,88,80,73,99,97, +115,104,118,105,115,97,103,111,108,102,115,110,111,119,122,104,58,233,113,117, +101,114,46,99,115,115,115,105,99,107,109,101,97,116,109,105,110,46,98,105,110, +100,100,101,108,108,104,105,114,101,112,105,99,115,114,101,110,116,58,51,54,90, +72,84,84,80,45,50,48,49,102,111,116,111,119,111,108,102,69,78,68,32,120,98,111, +120,58,53,52,90,66,79,68,89,100,105,99,107,59,10,125,10,101,120,105,116,58,51,53 +,90,118,97,114,115,98,101,97,116,39,125,41,59,100,105,101,116,57,57,57,59,97,110 +,110,101,125,125,60,47,91,105,93,46,76,97,110,103,107,109,194,178,119,105,114, +101,116,111,121,115,97,100,100,115,115,101,97,108,97,108,101,120,59,10,9,125,101 +,99,104,111,110,105,110,101,46,111,114,103,48,48,53,41,116,111,110,121,106,101, +119,115,115,97,110,100,108,101,103,115,114,111,111,102,48,48,48,41,32,50,48,48, +119,105,110,101,103,101,97,114,100,111,103,115,98,111,111,116,103,97,114,121,99, +117,116,115,116,121,108,101,116,101,109,112,116,105,111,110,46,120,109,108,99, +111,99,107,103,97,110,103,36,40,39,46,53,48,112,120,80,104,46,68,109,105,115,99, +97,108,97,110,108,111,97,110,100,101,115,107,109,105,108,101,114,121,97,110,117, +110,105,120,100,105,115,99,41,59,125,10,100,117,115,116,99,108,105,112,41,46,10, +10,55,48,112,120,45,50,48,48,68,86,68,115,55,93,62,60,116,97,112,101,100,101,109 +,111,105,43,43,41,119,97,103,101,101,117,114,111,112,104,105,108,111,112,116,115 +,104,111,108,101,70,65,81,115,97,115,105,110,45,50,54,84,108,97,98,115,112,101, +116,115,85,82,76,32,98,117,108,107,99,111,111,107,59,125,13,10,72,69,65,68,91,48 +,93,41,97,98,98,114,106,117,97,110,40,49,57,56,108,101,115,104,116,119,105,110, +60,47,105,62,115,111,110,121,103,117,121,115,102,117,99,107,112,105,112,101,124, +45,10,33,48,48,50,41,110,100,111,119,91,49,93,59,91,93,59,10,76,111,103,32,115, +97,108,116,13,10,9,9,98,97,110,103,116,114,105,109,98,97,116,104,41,123,13,10,48 +,48,112,120,10,125,41,59,107,111,58,236,102,101,101,115,97,100,62,13,115,58,47, +47,32,91,93,59,116,111,108,108,112,108,117,103,40,41,123,10,123,13,10,32,46,106, +115,39,50,48,48,112,100,117,97,108,98,111,97,116,46,74,80,71,41,59,10,125,113, +117,111,116,41,59,10,10,39,41,59,10,13,10,125,13,50,48,49,52,50,48,49,53,50,48, +49,54,50,48,49,55,50,48,49,56,50,48,49,57,50,48,50,48,50,48,50,49,50,48,50,50,50 +,48,50,51,50,48,50,52,50,48,50,53,50,48,50,54,50,48,50,55,50,48,50,56,50,48,50, +57,50,48,51,48,50,48,51,49,50,48,51,50,50,48,51,51,50,48,51,52,50,48,51,53,50,48 +,51,54,50,48,51,55,50,48,49,51,50,48,49,50,50,48,49,49,50,48,49,48,50,48,48,57, +50,48,48,56,50,48,48,55,50,48,48,54,50,48,48,53,50,48,48,52,50,48,48,51,50,48,48 +,50,50,48,48,49,50,48,48,48,49,57,57,57,49,57,57,56,49,57,57,55,49,57,57,54,49, +57,57,53,49,57,57,52,49,57,57,51,49,57,57,50,49,57,57,49,49,57,57,48,49,57,56,57 +,49,57,56,56,49,57,56,55,49,57,56,54,49,57,56,53,49,57,56,52,49,57,56,51,49,57, +56,50,49,57,56,49,49,57,56,48,49,57,55,57,49,57,55,56,49,57,55,55,49,57,55,54,49 +,57,55,53,49,57,55,52,49,57,55,51,49,57,55,50,49,57,55,49,49,57,55,48,49,57,54, +57,49,57,54,56,49,57,54,55,49,57,54,54,49,57,54,53,49,57,54,52,49,57,54,51,49,57 +,54,50,49,57,54,49,49,57,54,48,49,57,53,57,49,57,53,56,49,57,53,55,49,57,53,54, +49,57,53,53,49,57,53,52,49,57,53,51,49,57,53,50,49,57,53,49,49,57,53,48,49,48,48 +,48,49,48,50,52,49,51,57,52,48,48,48,48,57,57,57,57,99,111,109,111,109,195,161, +115,101,115,116,101,101,115,116,97,112,101,114,111,116,111,100,111,104,97,99,101 +,99,97,100,97,97,195,177,111,98,105,101,110,100,195,173,97,97,115,195,173,118, +105,100,97,99,97,115,111,111,116,114,111,102,111,114,111,115,111,108,111,111,116 +,114,97,99,117,97,108,100,105,106,111,115,105,100,111,103,114,97,110,116,105,112 +,111,116,101,109,97,100,101,98,101,97,108,103,111,113,117,195,169,101,115,116, +111,110,97,100,97,116,114,101,115,112,111,99,111,99,97,115,97,98,97,106,111,116, +111,100,97,115,105,110,111,97,103,117,97,112,117,101,115,117,110,111,115,97,110, +116,101,100,105,99,101,108,117,105,115,101,108,108,97,109,97,121,111,122,111,110 +,97,97,109,111,114,112,105,115,111,111,98,114,97,99,108,105,99,101,108,108,111, +100,105,111,115,104,111,114,97,99,97,115,105,208,183,208,176,208,189,208,176,208 +,190,208,188,209,128,208,176,209,128,209,131,209,130,208,176,208,189,208,181,208 +,191,208,190,208,190,209,130,208,184,208,183,208,189,208,190,208,180,208,190,209 +,130,208,190,208,182,208,181,208,190,208,189,208,184,209,133,208,157,208,176,208 +,181,208,181,208,177,209,139,208,188,209,139,208,146,209,139,209,129,208,190,208 +,178,209,139,208,178,208,190,208,157,208,190,208,190,208,177,208,159,208,190,208 +,187,208,184,208,189,208,184,208,160,208,164,208,157,208,181,208,156,209,139,209 +,130,209,139,208,158,208,189,208,184,208,188,208,180,208,176,208,151,208,176,208 +,148,208,176,208,157,209,131,208,158,208,177,209,130,208,181,208,152,208,183,208 +,181,208,185,208,189,209,131,208,188,208,188,208,162,209,139,209,131,208,182,217 +,129,217,138,216,163,217,134,217,133,216,167,217,133,216,185,217,131,217,132,216 +,163,217,136,216,177,216,175,217,138,216,167,217,129,217,137,217,135,217,136,217 +,132,217,133,217,132,217,131,216,167,217,136,217,132,217,135,216,168,216,179,216 +,167,217,132,216,165,217,134,217,135,217,138,216,163,217,138,217,130,216,175,217 +,135,217,132,216,171,217,133,216,168,217,135,217,132,217,136,217,132,217,138,216 +,168,217,132,216,167,217,138,216,168,217,131,216,180,217,138,216,167,217,133,216 +,163,217,133,217,134,216,170,216,168,217,138,217,132,217,134,216,173,216,168,217 +,135,217,133,217,133,216,180,217,136,216,180,102,105,114,115,116,118,105,100,101 +,111,108,105,103,104,116,119,111,114,108,100,109,101,100,105,97,119,104,105,116, +101,99,108,111,115,101,98,108,97,99,107,114,105,103,104,116,115,109,97,108,108, +98,111,111,107,115,112,108,97,99,101,109,117,115,105,99,102,105,101,108,100,111, +114,100,101,114,112,111,105,110,116,118,97,108,117,101,108,101,118,101,108,116, +97,98,108,101,98,111,97,114,100,104,111,117,115,101,103,114,111,117,112,119,111, +114,107,115,121,101,97,114,115,115,116,97,116,101,116,111,100,97,121,119,97,116, +101,114,115,116,97,114,116,115,116,121,108,101,100,101,97,116,104,112,111,119, +101,114,112,104,111,110,101,110,105,103,104,116,101,114,114,111,114,105,110,112, +117,116,97,98,111,117,116,116,101,114,109,115,116,105,116,108,101,116,111,111, +108,115,101,118,101,110,116,108,111,99,97,108,116,105,109,101,115,108,97,114,103 +,101,119,111,114,100,115,103,97,109,101,115,115,104,111,114,116,115,112,97,99, +101,102,111,99,117,115,99,108,101,97,114,109,111,100,101,108,98,108,111,99,107, +103,117,105,100,101,114,97,100,105,111,115,104,97,114,101,119,111,109,101,110,97 +,103,97,105,110,109,111,110,101,121,105,109,97,103,101,110,97,109,101,115,121, +111,117,110,103,108,105,110,101,115,108,97,116,101,114,99,111,108,111,114,103, +114,101,101,110,102,114,111,110,116,38,97,109,112,59,119,97,116,99,104,102,111, +114,99,101,112,114,105,99,101,114,117,108,101,115,98,101,103,105,110,97,102,116, +101,114,118,105,115,105,116,105,115,115,117,101,97,114,101,97,115,98,101,108,111 +,119,105,110,100,101,120,116,111,116,97,108,104,111,117,114,115,108,97,98,101, +108,112,114,105,110,116,112,114,101,115,115,98,117,105,108,116,108,105,110,107, +115,115,112,101,101,100,115,116,117,100,121,116,114,97,100,101,102,111,117,110, +100,115,101,110,115,101,117,110,100,101,114,115,104,111,119,110,102,111,114,109, +115,114,97,110,103,101,97,100,100,101,100,115,116,105,108,108,109,111,118,101, +100,116,97,107,101,110,97,98,111,118,101,102,108,97,115,104,102,105,120,101,100, +111,102,116,101,110,111,116,104,101,114,118,105,101,119,115,99,104,101,99,107, +108,101,103,97,108,114,105,118,101,114,105,116,101,109,115,113,117,105,99,107, +115,104,97,112,101,104,117,109,97,110,101,120,105,115,116,103,111,105,110,103, +109,111,118,105,101,116,104,105,114,100,98,97,115,105,99,112,101,97,99,101,115, +116,97,103,101,119,105,100,116,104,108,111,103,105,110,105,100,101,97,115,119, +114,111,116,101,112,97,103,101,115,117,115,101,114,115,100,114,105,118,101,115, +116,111,114,101,98,114,101,97,107,115,111,117,116,104,118,111,105,99,101,115,105 +,116,101,115,109,111,110,116,104,119,104,101,114,101,98,117,105,108,100,119,104, +105,99,104,101,97,114,116,104,102,111,114,117,109,116,104,114,101,101,115,112, +111,114,116,112,97,114,116,121,67,108,105,99,107,108,111,119,101,114,108,105,118 +,101,115,99,108,97,115,115,108,97,121,101,114,101,110,116,114,121,115,116,111, +114,121,117,115,97,103,101,115,111,117,110,100,99,111,117,114,116,121,111,117, +114,32,98,105,114,116,104,112,111,112,117,112,116,121,112,101,115,97,112,112,108 +,121,73,109,97,103,101,98,101,105,110,103,117,112,112,101,114,110,111,116,101, +115,101,118,101,114,121,115,104,111,119,115,109,101,97,110,115,101,120,116,114, +97,109,97,116,99,104,116,114,97,99,107,107,110,111,119,110,101,97,114,108,121,98 +,101,103,97,110,115,117,112,101,114,112,97,112,101,114,110,111,114,116,104,108, +101,97,114,110,103,105,118,101,110,110,97,109,101,100,101,110,100,101,100,84,101 +,114,109,115,112,97,114,116,115,71,114,111,117,112,98,114,97,110,100,117,115,105 +,110,103,119,111,109,97,110,102,97,108,115,101,114,101,97,100,121,97,117,100,105 +,111,116,97,107,101,115,119,104,105,108,101,46,99,111,109,47,108,105,118,101,100 +,99,97,115,101,115,100,97,105,108,121,99,104,105,108,100,103,114,101,97,116,106, +117,100,103,101,116,104,111,115,101,117,110,105,116,115,110,101,118,101,114,98, +114,111,97,100,99,111,97,115,116,99,111,118,101,114,97,112,112,108,101,102,105, +108,101,115,99,121,99,108,101,115,99,101,110,101,112,108,97,110,115,99,108,105, +99,107,119,114,105,116,101,113,117,101,101,110,112,105,101,99,101,101,109,97,105 +,108,102,114,97,109,101,111,108,100,101,114,112,104,111,116,111,108,105,109,105, +116,99,97,99,104,101,99,105,118,105,108,115,99,97,108,101,101,110,116,101,114, +116,104,101,109,101,116,104,101,114,101,116,111,117,99,104,98,111,117,110,100, +114,111,121,97,108,97,115,107,101,100,119,104,111,108,101,115,105,110,99,101,115 +,116,111,99,107,32,110,97,109,101,102,97,105,116,104,104,101,97,114,116,101,109, +112,116,121,111,102,102,101,114,115,99,111,112,101,111,119,110,101,100,109,105, +103,104,116,97,108,98,117,109,116,104,105,110,107,98,108,111,111,100,97,114,114, +97,121,109,97,106,111,114,116,114,117,115,116,99,97,110,111,110,117,110,105,111, +110,99,111,117,110,116,118,97,108,105,100,115,116,111,110,101,83,116,121,108,101 +,76,111,103,105,110,104,97,112,112,121,111,99,99,117,114,108,101,102,116,58,102, +114,101,115,104,113,117,105,116,101,102,105,108,109,115,103,114,97,100,101,110, +101,101,100,115,117,114,98,97,110,102,105,103,104,116,98,97,115,105,115,104,111, +118,101,114,97,117,116,111,59,114,111,117,116,101,46,104,116,109,108,109,105,120 +,101,100,102,105,110,97,108,89,111,117,114,32,115,108,105,100,101,116,111,112, +105,99,98,114,111,119,110,97,108,111,110,101,100,114,97,119,110,115,112,108,105, +116,114,101,97,99,104,82,105,103,104,116,100,97,116,101,115,109,97,114,99,104, +113,117,111,116,101,103,111,111,100,115,76,105,110,107,115,100,111,117,98,116,97 +,115,121,110,99,116,104,117,109,98,97,108,108,111,119,99,104,105,101,102,121,111 +,117,116,104,110,111,118,101,108,49,48,112,120,59,115,101,114,118,101,117,110, +116,105,108,104,97,110,100,115,67,104,101,99,107,83,112,97,99,101,113,117,101, +114,121,106,97,109,101,115,101,113,117,97,108,116,119,105,99,101,48,44,48,48,48, +83,116,97,114,116,112,97,110,101,108,115,111,110,103,115,114,111,117,110,100,101 +,105,103,104,116,115,104,105,102,116,119,111,114,116,104,112,111,115,116,115,108 +,101,97,100,115,119,101,101,107,115,97,118,111,105,100,116,104,101,115,101,109, +105,108,101,115,112,108,97,110,101,115,109,97,114,116,97,108,112,104,97,112,108, +97,110,116,109,97,114,107,115,114,97,116,101,115,112,108,97,121,115,99,108,97, +105,109,115,97,108,101,115,116,101,120,116,115,115,116,97,114,115,119,114,111, +110,103,60,47,104,51,62,116,104,105,110,103,46,111,114,103,47,109,117,108,116, +105,104,101,97,114,100,80,111,119,101,114,115,116,97,110,100,116,111,107,101,110 +,115,111,108,105,100,40,116,104,105,115,98,114,105,110,103,115,104,105,112,115, +115,116,97,102,102,116,114,105,101,100,99,97,108,108,115,102,117,108,108,121,102 +,97,99,116,115,97,103,101,110,116,84,104,105,115,32,47,47,45,45,62,97,100,109, +105,110,101,103,121,112,116,69,118,101,110,116,49,53,112,120,59,69,109,97,105, +108,116,114,117,101,34,99,114,111,115,115,115,112,101,110,116,98,108,111,103,115 +,98,111,120,34,62,110,111,116,101,100,108,101,97,118,101,99,104,105,110,97,115, +105,122,101,115,103,117,101,115,116,60,47,104,52,62,114,111,98,111,116,104,101, +97,118,121,116,114,117,101,44,115,101,118,101,110,103,114,97,110,100,99,114,105, +109,101,115,105,103,110,115,97,119,97,114,101,100,97,110,99,101,112,104,97,115, +101,62,60,33,45,45,101,110,95,85,83,38,35,51,57,59,50,48,48,112,120,95,110,97, +109,101,108,97,116,105,110,101,110,106,111,121,97,106,97,120,46,97,116,105,111, +110,115,109,105,116,104,85,46,83,46,32,104,111,108,100,115,112,101,116,101,114, +105,110,100,105,97,110,97,118,34,62,99,104,97,105,110,115,99,111,114,101,99,111, +109,101,115,100,111,105,110,103,112,114,105,111,114,83,104,97,114,101,49,57,57, +48,115,114,111,109,97,110,108,105,115,116,115,106,97,112,97,110,102,97,108,108, +115,116,114,105,97,108,111,119,110,101,114,97,103,114,101,101,60,47,104,50,62,97 +,98,117,115,101,97,108,101,114,116,111,112,101,114,97,34,45,47,47,87,99,97,114, +100,115,104,105,108,108,115,116,101,97,109,115,80,104,111,116,111,116,114,117, +116,104,99,108,101,97,110,46,112,104,112,63,115,97,105,110,116,109,101,116,97, +108,108,111,117,105,115,109,101,97,110,116,112,114,111,111,102,98,114,105,101, +102,114,111,119,34,62,103,101,110,114,101,116,114,117,99,107,108,111,111,107,115 +,86,97,108,117,101,70,114,97,109,101,46,110,101,116,47,45,45,62,10,60,116,114, +121,32,123,10,118,97,114,32,109,97,107,101,115,99,111,115,116,115,112,108,97,105 +,110,97,100,117,108,116,113,117,101,115,116,116,114,97,105,110,108,97,98,111,114 +,104,101,108,112,115,99,97,117,115,101,109,97,103,105,99,109,111,116,111,114,116 +,104,101,105,114,50,53,48,112,120,108,101,97,115,116,115,116,101,112,115,67,111, +117,110,116,99,111,117,108,100,103,108,97,115,115,115,105,100,101,115,102,117, +110,100,115,104,111,116,101,108,97,119,97,114,100,109,111,117,116,104,109,111, +118,101,115,112,97,114,105,115,103,105,118,101,115,100,117,116,99,104,116,101, +120,97,115,102,114,117,105,116,110,117,108,108,44,124,124,91,93,59,116,111,112, +34,62,10,60,33,45,45,80,79,83,84,34,111,99,101,97,110,60,98,114,47,62,102,108, +111,111,114,115,112,101,97,107,100,101,112,116,104,32,115,105,122,101,98,97,110, +107,115,99,97,116,99,104,99,104,97,114,116,50,48,112,120,59,97,108,105,103,110, +100,101,97,108,115,119,111,117,108,100,53,48,112,120,59,117,114,108,61,34,112,97 +,114,107,115,109,111,117,115,101,77,111,115,116,32,46,46,46,60,47,97,109,111,110 +,103,98,114,97,105,110,98,111,100,121,32,110,111,110,101,59,98,97,115,101,100,99 +,97,114,114,121,100,114,97,102,116,114,101,102,101,114,112,97,103,101,95,104,111 +,109,101,46,109,101,116,101,114,100,101,108,97,121,100,114,101,97,109,112,114, +111,118,101,106,111,105,110,116,60,47,116,114,62,100,114,117,103,115,60,33,45,45 +,32,97,112,114,105,108,105,100,101,97,108,97,108,108,101,110,101,120,97,99,116, +102,111,114,116,104,99,111,100,101,115,108,111,103,105,99,86,105,101,119,32,115, +101,101,109,115,98,108,97,110,107,112,111,114,116,115,32,40,50,48,48,115,97,118, +101,100,95,108,105,110,107,103,111,97,108,115,103,114,97,110,116,103,114,101,101 +,107,104,111,109,101,115,114,105,110,103,115,114,97,116,101,100,51,48,112,120,59 +,119,104,111,115,101,112,97,114,115,101,40,41,59,34,32,66,108,111,99,107,108,105 +,110,117,120,106,111,110,101,115,112,105,120,101,108,39,41,59,34,62,41,59,105, +102,40,45,108,101,102,116,100,97,118,105,100,104,111,114,115,101,70,111,99,117, +115,114,97,105,115,101,98,111,120,101,115,84,114,97,99,107,101,109,101,110,116, +60,47,101,109,62,98,97,114,34,62,46,115,114,99,61,116,111,119,101,114,97,108,116 +,61,34,99,97,98,108,101,104,101,110,114,121,50,52,112,120,59,115,101,116,117,112 +,105,116,97,108,121,115,104,97,114,112,109,105,110,111,114,116,97,115,116,101, +119,97,110,116,115,116,104,105,115,46,114,101,115,101,116,119,104,101,101,108, +103,105,114,108,115,47,99,115,115,47,49,48,48,37,59,99,108,117,98,115,115,116, +117,102,102,98,105,98,108,101,118,111,116,101,115,32,49,48,48,48,107,111,114,101 +,97,125,41,59,13,10,98,97,110,100,115,113,117,101,117,101,61,32,123,125,59,56,48 +,112,120,59,99,107,105,110,103,123,13,10,9,9,97,104,101,97,100,99,108,111,99,107 +,105,114,105,115,104,108,105,107,101,32,114,97,116,105,111,115,116,97,116,115,70 +,111,114,109,34,121,97,104,111,111,41,91,48,93,59,65,98,111,117,116,102,105,110, +100,115,60,47,104,49,62,100,101,98,117,103,116,97,115,107,115,85,82,76,32,61,99, +101,108,108,115,125,41,40,41,59,49,50,112,120,59,112,114,105,109,101,116,101,108 +,108,115,116,117,114,110,115,48,120,54,48,48,46,106,112,103,34,115,112,97,105, +110,98,101,97,99,104,116,97,120,101,115,109,105,99,114,111,97,110,103,101,108,45 +,45,62,60,47,103,105,102,116,115,115,116,101,118,101,45,108,105,110,107,98,111, +100,121,46,125,41,59,10,9,109,111,117,110,116,32,40,49,57,57,70,65,81,60,47,114, +111,103,101,114,102,114,97,110,107,67,108,97,115,115,50,56,112,120,59,102,101, +101,100,115,60,104,49,62,60,115,99,111,116,116,116,101,115,116,115,50,50,112,120 +,59,100,114,105,110,107,41,32,124,124,32,108,101,119,105,115,115,104,97,108,108, +35,48,51,57,59,32,102,111,114,32,108,111,118,101,100,119,97,115,116,101,48,48, +112,120,59,106,97,58,227,130,115,105,109,111,110,60,102,111,110,116,114,101,112, +108,121,109,101,101,116,115,117,110,116,101,114,99,104,101,97,112,116,105,103, +104,116,66,114,97,110,100,41,32,33,61,32,100,114,101,115,115,99,108,105,112,115, +114,111,111,109,115,111,110,107,101,121,109,111,98,105,108,109,97,105,110,46,78, +97,109,101,32,112,108,97,116,101,102,117,110,110,121,116,114,101,101,115,99,111, +109,47,34,49,46,106,112,103,119,109,111,100,101,112,97,114,97,109,83,84,65,82,84 +,108,101,102,116,32,105,100,100,101,110,44,32,50,48,49,41,59,10,125,10,102,111, +114,109,46,118,105,114,117,115,99,104,97,105,114,116,114,97,110,115,119,111,114, +115,116,80,97,103,101,115,105,116,105,111,110,112,97,116,99,104,60,33,45,45,10, +111,45,99,97,99,102,105,114,109,115,116,111,117,114,115,44,48,48,48,32,97,115, +105,97,110,105,43,43,41,123,97,100,111,98,101,39,41,91,48,93,105,100,61,49,48,98 +,111,116,104,59,109,101,110,117,32,46,50,46,109,105,46,112,110,103,34,107,101, +118,105,110,99,111,97,99,104,67,104,105,108,100,98,114,117,99,101,50,46,106,112, +103,85,82,76,41,43,46,106,112,103,124,115,117,105,116,101,115,108,105,99,101,104 +,97,114,114,121,49,50,48,34,32,115,119,101,101,116,116,114,62,13,10,110,97,109, +101,61,100,105,101,103,111,112,97,103,101,32,115,119,105,115,115,45,45,62,10,10, +35,102,102,102,59,34,62,76,111,103,46,99,111,109,34,116,114,101,97,116,115,104, +101,101,116,41,32,38,38,32,49,52,112,120,59,115,108,101,101,112,110,116,101,110, +116,102,105,108,101,100,106,97,58,227,131,105,100,61,34,99,78,97,109,101,34,119, +111,114,115,101,115,104,111,116,115,45,98,111,120,45,100,101,108,116,97,10,38, +108,116,59,98,101,97,114,115,58,52,56,90,60,100,97,116,97,45,114,117,114,97,108, +60,47,97,62,32,115,112,101,110,100,98,97,107,101,114,115,104,111,112,115,61,32, +34,34,59,112,104,112,34,62,99,116,105,111,110,49,51,112,120,59,98,114,105,97,110 +,104,101,108,108,111,115,105,122,101,61,111,61,37,50,70,32,106,111,105,110,109, +97,121,98,101,60,105,109,103,32,105,109,103,34,62,44,32,102,106,115,105,109,103, +34,32,34,41,91,48,93,77,84,111,112,66,84,121,112,101,34,110,101,119,108,121,68, +97,110,115,107,99,122,101,99,104,116,114,97,105,108,107,110,111,119,115,60,47, +104,53,62,102,97,113,34,62,122,104,45,99,110,49,48,41,59,10,45,49,34,41,59,116, +121,112,101,61,98,108,117,101,115,116,114,117,108,121,100,97,118,105,115,46,106, +115,39,59,62,13,10,60,33,115,116,101,101,108,32,121,111,117,32,104,50,62,13,10, +102,111,114,109,32,106,101,115,117,115,49,48,48,37,32,109,101,110,117,46,13,10,9 +,13,10,119,97,108,101,115,114,105,115,107,115,117,109,101,110,116,100,100,105, +110,103,98,45,108,105,107,116,101,97,99,104,103,105,102,34,32,118,101,103,97,115 +,100,97,110,115,107,101,101,115,116,105,115,104,113,105,112,115,117,111,109,105, +115,111,98,114,101,100,101,115,100,101,101,110,116,114,101,116,111,100,111,115, +112,117,101,100,101,97,195,177,111,115,101,115,116,195,161,116,105,101,110,101, +104,97,115,116,97,111,116,114,111,115,112,97,114,116,101,100,111,110,100,101,110 +,117,101,118,111,104,97,99,101,114,102,111,114,109,97,109,105,115,109,111,109, +101,106,111,114,109,117,110,100,111,97,113,117,195,173,100,195,173,97,115,115, +195,179,108,111,97,121,117,100,97,102,101,99,104,97,116,111,100,97,115,116,97, +110,116,111,109,101,110,111,115,100,97,116,111,115,111,116,114,97,115,115,105, +116,105,111,109,117,99,104,111,97,104,111,114,97,108,117,103,97,114,109,97,121, +111,114,101,115,116,111,115,104,111,114,97,115,116,101,110,101,114,97,110,116, +101,115,102,111,116,111,115,101,115,116,97,115,112,97,195,173,115,110,117,101, +118,97,115,97,108,117,100,102,111,114,111,115,109,101,100,105,111,113,117,105, +101,110,109,101,115,101,115,112,111,100,101,114,99,104,105,108,101,115,101,114, +195,161,118,101,99,101,115,100,101,99,105,114,106,111,115,195,169,101,115,116,97 +,114,118,101,110,116,97,103,114,117,112,111,104,101,99,104,111,101,108,108,111, +115,116,101,110,103,111,97,109,105,103,111,99,111,115,97,115,110,105,118,101,108 +,103,101,110,116,101,109,105,115,109,97,97,105,114,101,115,106,117,108,105,111, +116,101,109,97,115,104,97,99,105,97,102,97,118,111,114,106,117,110,105,111,108, +105,98,114,101,112,117,110,116,111,98,117,101,110,111,97,117,116,111,114,97,98, +114,105,108,98,117,101,110,97,116,101,120,116,111,109,97,114,122,111,115,97,98, +101,114,108,105,115,116,97,108,117,101,103,111,99,195,179,109,111,101,110,101, +114,111,106,117,101,103,111,112,101,114,195,186,104,97,98,101,114,101,115,116, +111,121,110,117,110,99,97,109,117,106,101,114,118,97,108,111,114,102,117,101,114 +,97,108,105,98,114,111,103,117,115,116,97,105,103,117,97,108,118,111,116,111,115 +,99,97,115,111,115,103,117,195,173,97,112,117,101,100,111,115,111,109,111,115,97 +,118,105,115,111,117,115,116,101,100,100,101,98,101,110,110,111,99,104,101,98, +117,115,99,97,102,97,108,116,97,101,117,114,111,115,115,101,114,105,101,100,105, +99,104,111,99,117,114,115,111,99,108,97,118,101,99,97,115,97,115,108,101,195,179 +,110,112,108,97,122,111,108,97,114,103,111,111,98,114,97,115,118,105,115,116,97, +97,112,111,121,111,106,117,110,116,111,116,114,97,116,97,118,105,115,116,111,99, +114,101,97,114,99,97,109,112,111,104,101,109,111,115,99,105,110,99,111,99,97,114 +,103,111,112,105,115,111,115,111,114,100,101,110,104,97,99,101,110,195,161,114, +101,97,100,105,115,99,111,112,101,100,114,111,99,101,114,99,97,112,117,101,100, +97,112,97,112,101,108,109,101,110,111,114,195,186,116,105,108,99,108,97,114,111, +106,111,114,103,101,99,97,108,108,101,112,111,110,101,114,116,97,114,100,101,110 +,97,100,105,101,109,97,114,99,97,115,105,103,117,101,101,108,108,97,115,115,105, +103,108,111,99,111,99,104,101,109,111,116,111,115,109,97,100,114,101,99,108,97, +115,101,114,101,115,116,111,110,105,195,177,111,113,117,101,100,97,112,97,115,97 +,114,98,97,110,99,111,104,105,106,111,115,118,105,97,106,101,112,97,98,108,111, +195,169,115,116,101,118,105,101,110,101,114,101,105,110,111,100,101,106,97,114, +102,111,110,100,111,99,97,110,97,108,110,111,114,116,101,108,101,116,114,97,99, +97,117,115,97,116,111,109,97,114,109,97,110,111,115,108,117,110,101,115,97,117, +116,111,115,118,105,108,108,97,118,101,110,100,111,112,101,115,97,114,116,105, +112,111,115,116,101,110,103,97,109,97,114,99,111,108,108,101,118,97,112,97,100, +114,101,117,110,105,100,111,118,97,109,111,115,122,111,110,97,115,97,109,98,111, +115,98,97,110,100,97,109,97,114,105,97,97,98,117,115,111,109,117,99,104,97,115, +117,98,105,114,114,105,111,106,97,118,105,118,105,114,103,114,97,100,111,99,104, +105,99,97,97,108,108,195,173,106,111,118,101,110,100,105,99,104,97,101,115,116, +97,110,116,97,108,101,115,115,97,108,105,114,115,117,101,108,111,112,101,115,111 +,115,102,105,110,101,115,108,108,97,109,97,98,117,115,99,111,195,169,115,116,97, +108,108,101,103,97,110,101,103,114,111,112,108,97,122,97,104,117,109,111,114,112 +,97,103,97,114,106,117,110,116,97,100,111,98,108,101,105,115,108,97,115,98,111, +108,115,97,98,97,195,177,111,104,97,98,108,97,108,117,99,104,97,195,129,114,101, +97,100,105,99,101,110,106,117,103,97,114,110,111,116,97,115,118,97,108,108,101, +97,108,108,195,161,99,97,114,103,97,100,111,108,111,114,97,98,97,106,111,101,115 +,116,195,169,103,117,115,116,111,109,101,110,116,101,109,97,114,105,111,102,105, +114,109,97,99,111,115,116,111,102,105,99,104,97,112,108,97,116,97,104,111,103,97 +,114,97,114,116,101,115,108,101,121,101,115,97,113,117,101,108,109,117,115,101, +111,98,97,115,101,115,112,111,99,111,115,109,105,116,97,100,99,105,101,108,111, +99,104,105,99,111,109,105,101,100,111,103,97,110,97,114,115,97,110,116,111,101, +116,97,112,97,100,101,98,101,115,112,108,97,121,97,114,101,100,101,115,115,105, +101,116,101,99,111,114,116,101,99,111,114,101,97,100,117,100,97,115,100,101,115, +101,111,118,105,101,106,111,100,101,115,101,97,97,103,117,97,115,38,113,117,111, +116,59,100,111,109,97,105,110,99,111,109,109,111,110,115,116,97,116,117,115,101, +118,101,110,116,115,109,97,115,116,101,114,115,121,115,116,101,109,97,99,116,105 +,111,110,98,97,110,110,101,114,114,101,109,111,118,101,115,99,114,111,108,108, +117,112,100,97,116,101,103,108,111,98,97,108,109,101,100,105,117,109,102,105,108 +,116,101,114,110,117,109,98,101,114,99,104,97,110,103,101,114,101,115,117,108, +116,112,117,98,108,105,99,115,99,114,101,101,110,99,104,111,111,115,101,110,111, +114,109,97,108,116,114,97,118,101,108,105,115,115,117,101,115,115,111,117,114,99 +,101,116,97,114,103,101,116,115,112,114,105,110,103,109,111,100,117,108,101,109, +111,98,105,108,101,115,119,105,116,99,104,112,104,111,116,111,115,98,111,114,100 +,101,114,114,101,103,105,111,110,105,116,115,101,108,102,115,111,99,105,97,108, +97,99,116,105,118,101,99,111,108,117,109,110,114,101,99,111,114,100,102,111,108, +108,111,119,116,105,116,108,101,62,101,105,116,104,101,114,108,101,110,103,116, +104,102,97,109,105,108,121,102,114,105,101,110,100,108,97,121,111,117,116,97,117 +,116,104,111,114,99,114,101,97,116,101,114,101,118,105,101,119,115,117,109,109, +101,114,115,101,114,118,101,114,112,108,97,121,101,100,112,108,97,121,101,114, +101,120,112,97,110,100,112,111,108,105,99,121,102,111,114,109,97,116,100,111,117 +,98,108,101,112,111,105,110,116,115,115,101,114,105,101,115,112,101,114,115,111, +110,108,105,118,105,110,103,100,101,115,105,103,110,109,111,110,116,104,115,102, +111,114,99,101,115,117,110,105,113,117,101,119,101,105,103,104,116,112,101,111, +112,108,101,101,110,101,114,103,121,110,97,116,117,114,101,115,101,97,114,99,104 +,102,105,103,117,114,101,104,97,118,105,110,103,99,117,115,116,111,109,111,102, +102,115,101,116,108,101,116,116,101,114,119,105,110,100,111,119,115,117,98,109, +105,116,114,101,110,100,101,114,103,114,111,117,112,115,117,112,108,111,97,100, +104,101,97,108,116,104,109,101,116,104,111,100,118,105,100,101,111,115,115,99, +104,111,111,108,102,117,116,117,114,101,115,104,97,100,111,119,100,101,98,97,116 +,101,118,97,108,117,101,115,79,98,106,101,99,116,111,116,104,101,114,115,114,105 +,103,104,116,115,108,101,97,103,117,101,99,104,114,111,109,101,115,105,109,112, +108,101,110,111,116,105,99,101,115,104,97,114,101,100,101,110,100,105,110,103, +115,101,97,115,111,110,114,101,112,111,114,116,111,110,108,105,110,101,115,113, +117,97,114,101,98,117,116,116,111,110,105,109,97,103,101,115,101,110,97,98,108, +101,109,111,118,105,110,103,108,97,116,101,115,116,119,105,110,116,101,114,70, +114,97,110,99,101,112,101,114,105,111,100,115,116,114,111,110,103,114,101,112, +101,97,116,76,111,110,100,111,110,100,101,116,97,105,108,102,111,114,109,101,100 +,100,101,109,97,110,100,115,101,99,117,114,101,112,97,115,115,101,100,116,111, +103,103,108,101,112,108,97,99,101,115,100,101,118,105,99,101,115,116,97,116,105, +99,99,105,116,105,101,115,115,116,114,101,97,109,121,101,108,108,111,119,97,116, +116,97,99,107,115,116,114,101,101,116,102,108,105,103,104,116,104,105,100,100, +101,110,105,110,102,111,34,62,111,112,101,110,101,100,117,115,101,102,117,108, +118,97,108,108,101,121,99,97,117,115,101,115,108,101,97,100,101,114,115,101,99, +114,101,116,115,101,99,111,110,100,100,97,109,97,103,101,115,112,111,114,116,115 +,101,120,99,101,112,116,114,97,116,105,110,103,115,105,103,110,101,100,116,104, +105,110,103,115,101,102,102,101,99,116,102,105,101,108,100,115,115,116,97,116, +101,115,111,102,102,105,99,101,118,105,115,117,97,108,101,100,105,116,111,114, +118,111,108,117,109,101,82,101,112,111,114,116,109,117,115,101,117,109,109,111, +118,105,101,115,112,97,114,101,110,116,97,99,99,101,115,115,109,111,115,116,108, +121,109,111,116,104,101,114,34,32,105,100,61,34,109,97,114,107,101,116,103,114, +111,117,110,100,99,104,97,110,99,101,115,117,114,118,101,121,98,101,102,111,114, +101,115,121,109,98,111,108,109,111,109,101,110,116,115,112,101,101,99,104,109, +111,116,105,111,110,105,110,115,105,100,101,109,97,116,116,101,114,67,101,110, +116,101,114,111,98,106,101,99,116,101,120,105,115,116,115,109,105,100,100,108, +101,69,117,114,111,112,101,103,114,111,119,116,104,108,101,103,97,99,121,109,97, +110,110,101,114,101,110,111,117,103,104,99,97,114,101,101,114,97,110,115,119,101 +,114,111,114,105,103,105,110,112,111,114,116,97,108,99,108,105,101,110,116,115, +101,108,101,99,116,114,97,110,100,111,109,99,108,111,115,101,100,116,111,112,105 +,99,115,99,111,109,105,110,103,102,97,116,104,101,114,111,112,116,105,111,110, +115,105,109,112,108,121,114,97,105,115,101,100,101,115,99,97,112,101,99,104,111, +115,101,110,99,104,117,114,99,104,100,101,102,105,110,101,114,101,97,115,111,110 +,99,111,114,110,101,114,111,117,116,112,117,116,109,101,109,111,114,121,105,102, +114,97,109,101,112,111,108,105,99,101,109,111,100,101,108,115,78,117,109,98,101, +114,100,117,114,105,110,103,111,102,102,101,114,115,115,116,121,108,101,115,107, +105,108,108,101,100,108,105,115,116,101,100,99,97,108,108,101,100,115,105,108, +118,101,114,109,97,114,103,105,110,100,101,108,101,116,101,98,101,116,116,101, +114,98,114,111,119,115,101,108,105,109,105,116,115,71,108,111,98,97,108,115,105, +110,103,108,101,119,105,100,103,101,116,99,101,110,116,101,114,98,117,100,103, +101,116,110,111,119,114,97,112,99,114,101,100,105,116,99,108,97,105,109,115,101, +110,103,105,110,101,115,97,102,101,116,121,99,104,111,105,99,101,115,112,105,114 +,105,116,45,115,116,121,108,101,115,112,114,101,97,100,109,97,107,105,110,103, +110,101,101,100,101,100,114,117,115,115,105,97,112,108,101,97,115,101,101,120, +116,101,110,116,83,99,114,105,112,116,98,114,111,107,101,110,97,108,108,111,119, +115,99,104,97,114,103,101,100,105,118,105,100,101,102,97,99,116,111,114,109,101, +109,98,101,114,45,98,97,115,101,100,116,104,101,111,114,121,99,111,110,102,105, +103,97,114,111,117,110,100,119,111,114,107,101,100,104,101,108,112,101,100,67, +104,117,114,99,104,105,109,112,97,99,116,115,104,111,117,108,100,97,108,119,97, +121,115,108,111,103,111,34,32,98,111,116,116,111,109,108,105,115,116,34,62,41, +123,118,97,114,32,112,114,101,102,105,120,111,114,97,110,103,101,72,101,97,100, +101,114,46,112,117,115,104,40,99,111,117,112,108,101,103,97,114,100,101,110,98, +114,105,100,103,101,108,97,117,110,99,104,82,101,118,105,101,119,116,97,107,105, +110,103,118,105,115,105,111,110,108,105,116,116,108,101,100,97,116,105,110,103, +66,117,116,116,111,110,98,101,97,117,116,121,116,104,101,109,101,115,102,111,114 +,103,111,116,83,101,97,114,99,104,97,110,99,104,111,114,97,108,109,111,115,116, +108,111,97,100,101,100,67,104,97,110,103,101,114,101,116,117,114,110,115,116,114 +,105,110,103,114,101,108,111,97,100,77,111,98,105,108,101,105,110,99,111,109,101 +,115,117,112,112,108,121,83,111,117,114,99,101,111,114,100,101,114,115,118,105, +101,119,101,100,38,110,98,115,112,59,99,111,117,114,115,101,65,98,111,117,116,32 +,105,115,108,97,110,100,60,104,116,109,108,32,99,111,111,107,105,101,110,97,109, +101,61,34,97,109,97,122,111,110,109,111,100,101,114,110,97,100,118,105,99,101, +105,110,60,47,97,62,58,32,84,104,101,32,100,105,97,108,111,103,104,111,117,115, +101,115,66,69,71,73,78,32,77,101,120,105,99,111,115,116,97,114,116,115,99,101, +110,116,114,101,104,101,105,103,104,116,97,100,100,105,110,103,73,115,108,97,110 +,100,97,115,115,101,116,115,69,109,112,105,114,101,83,99,104,111,111,108,101,102 +,102,111,114,116,100,105,114,101,99,116,110,101,97,114,108,121,109,97,110,117,97 +,108,83,101,108,101,99,116,46,10,10,79,110,101,106,111,105,110,101,100,109,101, +110,117,34,62,80,104,105,108,105,112,97,119,97,114,100,115,104,97,110,100,108, +101,105,109,112,111,114,116,79,102,102,105,99,101,114,101,103,97,114,100,115,107 +,105,108,108,115,110,97,116,105,111,110,83,112,111,114,116,115,100,101,103,114, +101,101,119,101,101,107,108,121,32,40,101,46,103,46,98,101,104,105,110,100,100, +111,99,116,111,114,108,111,103,103,101,100,117,110,105,116,101,100,60,47,98,62, +60,47,98,101,103,105,110,115,112,108,97,110,116,115,97,115,115,105,115,116,97, +114,116,105,115,116,105,115,115,117,101,100,51,48,48,112,120,124,99,97,110,97, +100,97,97,103,101,110,99,121,115,99,104,101,109,101,114,101,109,97,105,110,66, +114,97,122,105,108,115,97,109,112,108,101,108,111,103,111,34,62,98,101,121,111, +110,100,45,115,99,97,108,101,97,99,99,101,112,116,115,101,114,118,101,100,109,97 +,114,105,110,101,70,111,111,116,101,114,99,97,109,101,114,97,60,47,104,49,62,10, +95,102,111,114,109,34,108,101,97,118,101,115,115,116,114,101,115,115,34,32,47,62 +,13,10,46,103,105,102,34,32,111,110,108,111,97,100,108,111,97,100,101,114,79,120 +,102,111,114,100,115,105,115,116,101,114,115,117,114,118,105,118,108,105,115,116 +,101,110,102,101,109,97,108,101,68,101,115,105,103,110,115,105,122,101,61,34,97, +112,112,101,97,108,116,101,120,116,34,62,108,101,118,101,108,115,116,104,97,110, +107,115,104,105,103,104,101,114,102,111,114,99,101,100,97,110,105,109,97,108,97, +110,121,111,110,101,65,102,114,105,99,97,97,103,114,101,101,100,114,101,99,101, +110,116,80,101,111,112,108,101,60,98,114,32,47,62,119,111,110,100,101,114,112, +114,105,99,101,115,116,117,114,110,101,100,124,124,32,123,125,59,109,97,105,110, +34,62,105,110,108,105,110,101,115,117,110,100,97,121,119,114,97,112,34,62,102,97 +,105,108,101,100,99,101,110,115,117,115,109,105,110,117,116,101,98,101,97,99,111 +,110,113,117,111,116,101,115,49,53,48,112,120,124,101,115,116,97,116,101,114,101 +,109,111,116,101,101,109,97,105,108,34,108,105,110,107,101,100,114,105,103,104, +116,59,115,105,103,110,97,108,102,111,114,109,97,108,49,46,104,116,109,108,115, +105,103,110,117,112,112,114,105,110,99,101,102,108,111,97,116,58,46,112,110,103, +34,32,102,111,114,117,109,46,65,99,99,101,115,115,112,97,112,101,114,115,115,111 +,117,110,100,115,101,120,116,101,110,100,72,101,105,103,104,116,115,108,105,100, +101,114,85,84,70,45,56,34,38,97,109,112,59,32,66,101,102,111,114,101,46,32,87, +105,116,104,115,116,117,100,105,111,111,119,110,101,114,115,109,97,110,97,103, +101,112,114,111,102,105,116,106,81,117,101,114,121,97,110,110,117,97,108,112,97, +114,97,109,115,98,111,117,103,104,116,102,97,109,111,117,115,103,111,111,103,108 +,101,108,111,110,103,101,114,105,43,43,41,32,123,105,115,114,97,101,108,115,97, +121,105,110,103,100,101,99,105,100,101,104,111,109,101,34,62,104,101,97,100,101, +114,101,110,115,117,114,101,98,114,97,110,99,104,112,105,101,99,101,115,98,108, +111,99,107,59,115,116,97,116,101,100,116,111,112,34,62,60,114,97,99,105,110,103, +114,101,115,105,122,101,45,45,38,103,116,59,112,97,99,105,116,121,115,101,120, +117,97,108,98,117,114,101,97,117,46,106,112,103,34,32,49,48,44,48,48,48,111,98, +116,97,105,110,116,105,116,108,101,115,97,109,111,117,110,116,44,32,73,110,99,46 +,99,111,109,101,100,121,109,101,110,117,34,32,108,121,114,105,99,115,116,111,100 +,97,121,46,105,110,100,101,101,100,99,111,117,110,116,121,95,108,111,103,111,46, +70,97,109,105,108,121,108,111,111,107,101,100,77,97,114,107,101,116,108,115,101, +32,105,102,80,108,97,121,101,114,116,117,114,107,101,121,41,59,118,97,114,32,102 +,111,114,101,115,116,103,105,118,105,110,103,101,114,114,111,114,115,68,111,109, +97,105,110,125,101,108,115,101,123,105,110,115,101,114,116,66,108,111,103,60,47, +102,111,111,116,101,114,108,111,103,105,110,46,102,97,115,116,101,114,97,103,101 +,110,116,115,60,98,111,100,121,32,49,48,112,120,32,48,112,114,97,103,109,97,102, +114,105,100,97,121,106,117,110,105,111,114,100,111,108,108,97,114,112,108,97,99, +101,100,99,111,118,101,114,115,112,108,117,103,105,110,53,44,48,48,48,32,112,97, +103,101,34,62,98,111,115,116,111,110,46,116,101,115,116,40,97,118,97,116,97,114, +116,101,115,116,101,100,95,99,111,117,110,116,102,111,114,117,109,115,115,99,104 +,101,109,97,105,110,100,101,120,44,102,105,108,108,101,100,115,104,97,114,101, +115,114,101,97,100,101,114,97,108,101,114,116,40,97,112,112,101,97,114,83,117,98 +,109,105,116,108,105,110,101,34,62,98,111,100,121,34,62,10,42,32,84,104,101,84, +104,111,117,103,104,115,101,101,105,110,103,106,101,114,115,101,121,78,101,119, +115,60,47,118,101,114,105,102,121,101,120,112,101,114,116,105,110,106,117,114, +121,119,105,100,116,104,61,67,111,111,107,105,101,83,84,65,82,84,32,97,99,114, +111,115,115,95,105,109,97,103,101,116,104,114,101,97,100,110,97,116,105,118,101, +112,111,99,107,101,116,98,111,120,34,62,10,83,121,115,116,101,109,32,68,97,118, +105,100,99,97,110,99,101,114,116,97,98,108,101,115,112,114,111,118,101,100,65, +112,114,105,108,32,114,101,97,108,108,121,100,114,105,118,101,114,105,116,101, +109,34,62,109,111,114,101,34,62,98,111,97,114,100,115,99,111,108,111,114,115,99, +97,109,112,117,115,102,105,114,115,116,32,124,124,32,91,93,59,109,101,100,105,97 +,46,103,117,105,116,97,114,102,105,110,105,115,104,119,105,100,116,104,58,115, +104,111,119,101,100,79,116,104,101,114,32,46,112,104,112,34,32,97,115,115,117, +109,101,108,97,121,101,114,115,119,105,108,115,111,110,115,116,111,114,101,115, +114,101,108,105,101,102,115,119,101,100,101,110,67,117,115,116,111,109,101,97, +115,105,108,121,32,121,111,117,114,32,83,116,114,105,110,103,10,10,87,104,105, +108,116,97,121,108,111,114,99,108,101,97,114,58,114,101,115,111,114,116,102,114, +101,110,99,104,116,104,111,117,103,104,34,41,32,43,32,34,60,98,111,100,121,62,98 +,117,121,105,110,103,98,114,97,110,100,115,77,101,109,98,101,114,110,97,109,101, +34,62,111,112,112,105,110,103,115,101,99,116,111,114,53,112,120,59,34,62,118,115 +,112,97,99,101,112,111,115,116,101,114,109,97,106,111,114,32,99,111,102,102,101, +101,109,97,114,116,105,110,109,97,116,117,114,101,104,97,112,112,101,110,60,47, +110,97,118,62,107,97,110,115,97,115,108,105,110,107,34,62,73,109,97,103,101,115, +61,102,97,108,115,101,119,104,105,108,101,32,104,115,112,97,99,101,48,38,97,109, +112,59,32,10,10,73,110,32,32,112,111,119,101,114,80,111,108,115,107,105,45,99, +111,108,111,114,106,111,114,100,97,110,66,111,116,116,111,109,83,116,97,114,116, +32,45,99,111,117,110,116,50,46,104,116,109,108,110,101,119,115,34,62,48,49,46, +106,112,103,79,110,108,105,110,101,45,114,105,103,104,116,109,105,108,108,101, +114,115,101,110,105,111,114,73,83,66,78,32,48,48,44,48,48,48,32,103,117,105,100, +101,115,118,97,108,117,101,41,101,99,116,105,111,110,114,101,112,97,105,114,46, +120,109,108,34,32,32,114,105,103,104,116,115,46,104,116,109,108,45,98,108,111,99 +,107,114,101,103,69,120,112,58,104,111,118,101,114,119,105,116,104,105,110,118, +105,114,103,105,110,112,104,111,110,101,115,60,47,116,114,62,13,117,115,105,110, +103,32,10,9,118,97,114,32,62,39,41,59,10,9,60,47,116,100,62,10,60,47,116,114,62, +10,98,97,104,97,115,97,98,114,97,115,105,108,103,97,108,101,103,111,109,97,103, +121,97,114,112,111,108,115,107,105,115,114,112,115,107,105,216,177,216,175,217, +136,228,184,173,230,150,135,231,174,128,228,189,147,231,185,129,233,171,148,228, +191,161,230,129,175,228,184,173,229,155,189,230,136,145,228,187,172,228,184,128, +228,184,170,229,133,172,229,143,184,231,174,161,231,144,134,232,174,186,229,157, +155,229,143,175,228,187,165,230,156,141,229,138,161,230,151,182,233,151,180,228, +184,170,228,186,186,228,186,167,229,147,129,232,135,170,229,183,177,228,188,129, +228,184,154,230,159,165,231,156,139,229,183,165,228,189,156,232,129,148,231,179, +187,230,178,161,230,156,137,231,189,145,231,171,153,230,137,128,230,156,137,232, +175,132,232,174,186,228,184,173,229,191,131,230,150,135,231,171,160,231,148,168, +230,136,183,233,166,150,233,161,181,228,189,156,232,128,133,230,138,128,230,156, +175,233,151,174,233,162,152,231,155,184,229,133,179,228,184,139,232,189,189,230, +144,156,231,180,162,228,189,191,231,148,168,232,189,175,228,187,182,229,156,168, +231,186,191,228,184,187,233,162,152,232,181,132,230,150,153,232,167,134,233,162, +145,229,155,158,229,164,141,230,179,168,229,134,140,231,189,145,231,187,156,230, +148,182,232,151,143,229,134,133,229,174,185,230,142,168,232,141,144,229,184,130, +229,156,186,230,182,136,230,129,175,231,169,186,233,151,180,229,143,145,229,184, +131,228,187,128,228,185,136,229,165,189,229,143,139,231,148,159,230,180,187,229, +155,190,231,137,135,229,143,145,229,177,149,229,166,130,230,158,156,230,137,139, +230,156,186,230,150,176,233,151,187,230,156,128,230,150,176,230,150,185,229,188, +143,229,140,151,228,186,172,230,143,144,228,190,155,229,133,179,228,186,142,230, +155,180,229,164,154,232,191,153,228,184,170,231,179,187,231,187,159,231,159,165, +233,129,147,230,184,184,230,136,143,229,185,191,229,145,138,229,133,182,228,187, +150,229,143,145,232,161,168,229,174,137,229,133,168,231,172,172,228,184,128,228, +188,154,229,145,152,232,191,155,232,161,140,231,130,185,229,135,187,231,137,136, +230,157,131,231,148,181,229,173,144,228,184,150,231,149,140,232,174,190,232,174, +161,229,133,141,232,180,185,230,149,153,232,130,178,229,138,160,229,133,165,230, +180,187,229,138,168,228,187,150,228,187,172,229,149,134,229,147,129,229,141,154, +229,174,162,231,142,176,229,156,168,228,184,138,230,181,183,229,166,130,228,189, +149,229,183,178,231,187,143,231,149,153,232,168,128,232,175,166,231,187,134,231, +164,190,229,140,186,231,153,187,229,189,149,230,156,172,231,171,153,233,156,128, +232,166,129,228,187,183,230,160,188,230,148,175,230,140,129,229,155,189,233,153, +133,233,147,190,230,142,165,229,155,189,229,174,182,229,187,186,232,174,190,230, +156,139,229,143,139,233,152,133,232,175,187,230,179,149,229,190,139,228,189,141, +231,189,174,231,187,143,230,181,142,233,128,137,230,139,169,232,191,153,230,160, +183,229,189,147,229,137,141,229,136,134,231,177,187,230,142,146,232,161,140,229, +155,160,228,184,186,228,186,164,230,152,147,230,156,128,229,144,142,233,159,179, +228,185,144,228,184,141,232,131,189,233,128,154,232,191,135,232,161,140,228,184, +154,231,167,145,230,138,128,229,143,175,232,131,189,232,174,190,229,164,135,229, +144,136,228,189,156,229,164,167,229,174,182,231,164,190,228,188,154,231,160,148, +231,169,182,228,184,147,228,184,154,229,133,168,233,131,168,233,161,185,231,155, +174,232,191,153,233,135,140,232,191,152,230,152,175,229,188,128,229,167,139,230, +131,133,229,134,181,231,148,181,232,132,145,230,150,135,228,187,182,229,147,129, +231,137,140,229,184,174,229,138,169,230,150,135,229,140,150,232,181,132,230,186, +144,229,164,167,229,173,166,229,173,166,228,185,160,229,156,176,229,157,128,230, +181,143,232,167,136,230,138,149,232,181,132,229,183,165,231,168,139,232,166,129, +230,177,130,230,128,142,228,185,136,230,151,182,229,128,153,229,138,159,232,131, +189,228,184,187,232,166,129,231,155,174,229,137,141,232,181,132,232,174,175,229, +159,142,229,184,130,230,150,185,230,179,149,231,148,181,229,189,177,230,139,155, +232,129,152,229,163,176,230,152,142,228,187,187,228,189,149,229,129,165,229,186, +183,230,149,176,230,141,174,231,190,142,229,155,189,230,177,189,232,189,166,228, +187,139,231,187,141,228,189,134,230,152,175,228,186,164,230,181,129,231,148,159, +228,186,167,230,137,128,228,187,165,231,148,181,232,175,157,230,152,190,231,164, +186,228,184,128,228,186,155,229,141,149,228,189,141,228,186,186,229,145,152,229, +136,134,230,158,144,229,156,176,229,155,190,230,151,133,230,184,184,229,183,165, +229,133,183,229,173,166,231,148,159,231,179,187,229,136,151,231,189,145,229,143, +139,229,184,150,229,173,144,229,175,134,231,160,129,233,162,145,233,129,147,230, +142,167,229,136,182,229,156,176,229,140,186,229,159,186,230,156,172,229,133,168, +229,155,189,231,189,145,228,184,138,233,135,141,232,166,129,231,172,172,228,186, +140,229,150,156,230,172,162,232,191,155,229,133,165,229,143,139,230,131,133,232, +191,153,228,186,155,232,128,131,232,175,149,229,143,145,231,142,176,229,159,185, +232,174,173,228,187,165,228,184,138,230,148,191,229,186,156,230,136,144,228,184, +186,231,142,175,229,162,131,233,166,153,230,184,175,229,144,140,230,151,182,229, +168,177,228,185,144,229,143,145,233,128,129,228,184,128,229,174,154,229,188,128, +229,143,145,228,189,156,229,147,129,230,160,135,229,135,134,230,172,162,232,191, +142,232,167,163,229,134,179,229,156,176,230,150,185,228,184,128,228,184,139,228, +187,165,229,143,138,232,180,163,228,187,187,230,136,150,232,128,133,229,174,162, +230,136,183,228,187,163,232,161,168,231,167,175,229,136,134,229,165,179,228,186, +186,230,149,176,231,160,129,233,148,128,229,148,174,229,135,186,231,142,176,231, +166,187,231,186,191,229,186,148,231,148,168,229,136,151,232,161,168,228,184,141, +229,144,140,231,188,150,232,190,145,231,187,159,232,174,161,230,159,165,232,175, +162,228,184,141,232,166,129,230,156,137,229,133,179,230,156,186,230,158,132,229, +190,136,229,164,154,230,146,173,230,148,190,231,187,132,231,187,135,230,148,191, +231,173,150,231,155,180,230,142,165,232,131,189,229,138,155,230,157,165,230,186, +144,230,153,130,233,150,147,231,156,139,229,136,176,231,131,173,233,151,168,229, +133,179,233,148,174,228,184,147,229,140,186,233,157,158,229,184,184,232,139,177, +232,175,173,231,153,190,229,186,166,229,184,140,230,156,155,231,190,142,229,165, +179,230,175,148,232,190,131,231,159,165,232,175,134,232,167,132,229,174,154,229, +187,186,232,174,174,233,131,168,233,151,168,230,132,143,232,167,129,231,178,190, +229,189,169,230,151,165,230,156,172,230,143,144,233,171,152,229,143,145,232,168, +128,230,150,185,233,157,162,229,159,186,233,135,145,229,164,132,231,144,134,230, +157,131,233,153,144,229,189,177,231,137,135,233,147,182,232,161,140,232,191,152, +230,156,137,229,136,134,228,186,171,231,137,169,229,147,129,231,187,143,232,144, +165,230,183,187,229,138,160,228,184,147,229,174,182,232,191,153,231,167,141,232, +175,157,233,162,152,232,181,183,230,157,165,228,184,154,229,138,161,229,133,172, +229,145,138,232,174,176,229,189,149,231,174,128,228,187,139,232,180,168,233,135, +143,231,148,183,228,186,186,229,189,177,229,147,141,229,188,149,231,148,168,230, +138,165,229,145,138,233,131,168,229,136,134,229,191,171,233,128,159,229,146,168, +232,175,162,230,151,182,229,176,154,230,179,168,230,132,143,231,148,179,232,175, +183,229,173,166,230,160,161,229,186,148,232,175,165,229,142,134,229,143,178,229, +143,170,230,152,175,232,191,148,229,155,158,232,180,173,228,185,176,229,144,141, +231,167,176,228,184,186,228,186,134,230,136,144,229,138,159,232,175,180,230,152, +142,228,190,155,229,186,148,229,173,169,229,173,144,228,184,147,233,162,152,231, +168,139,229,186,143,228,184,128,232,136,172,230,156,131,229,147,161,229,143,170, +230,156,137,229,133,182,229,174,131,228,191,157,230,138,164,232,128,140,228,184, +148,228,187,138,229,164,169,231,170,151,229,143,163,229,138,168,230,128,129,231, +138,182,230,128,129,231,137,185,229,136,171,232,174,164,228,184,186,229,191,133, +233,161,187,230,155,180,230,150,176,229,176,143,232,175,180,230,136,145,229,128, +145,228,189,156,228,184,186,229,170,146,228,189,147,229,140,133,230,139,172,233, +130,163,228,185,136,228,184,128,230,160,183,229,155,189,229,134,133,230,152,175, +229,144,166,230,160,185,230,141,174,231,148,181,232,167,134,229,173,166,233,153, +162,229,133,183,230,156,137,232,191,135,231,168,139,231,148,177,228,186,142,228, +186,186,230,137,141,229,135,186,230,157,165,228,184,141,232,191,135,230,173,163, +229,156,168,230,152,142,230,152,159,230,149,133,228,186,139,229,133,179,231,179, +187,230,160,135,233,162,152,229,149,134,229,138,161,232,190,147,229,133,165,228, +184,128,231,155,180,229,159,186,231,161,128,230,149,153,229,173,166,228,186,134, +232,167,163,229,187,186,231,173,145,231,187,147,230,158,156,229,133,168,231,144, +131,233,128,154,231,159,165,232,174,161,229,136,146,229,175,185,228,186,142,232, +137,186,230,156,175,231,155,184,229,134,140,229,143,145,231,148,159,231,156,159, +231,154,132,229,187,186,231,171,139,231,173,137,231,186,167,231,177,187,229,158, +139,231,187,143,233,170,140,229,174,158,231,142,176,229,136,182,228,189,156,230, +157,165,232,135,170,230,160,135,231,173,190,228,187,165,228,184,139,229,142,159, +229,136,155,230,151,160,230,179,149,229,133,182,228,184,173,229,128,139,228,186, +186,228,184,128,229,136,135,230,140,135,229,141,151,229,133,179,233,151,173,233, +155,134,229,155,162,231,172,172,228,184,137,229,133,179,230,179,168,229,155,160, +230,173,164,231,133,167,231,137,135,230,183,177,229,156,179,229,149,134,228,184, +154,229,185,191,229,183,158,230,151,165,230,156,159,233,171,152,231,186,167,230, +156,128,232,191,145,231,187,188,229,144,136,232,161,168,231,164,186,228,184,147, +232,190,145,232,161,140,228,184,186,228,186,164,233,128,154,232,175,132,228,187, +183,232,167,137,229,190,151,231,178,190,229,141,142,229,174,182,229,186,173,229, +174,140,230,136,144,230,132,159,232,167,137,229,174,137,232,163,133,229,190,151, +229,136,176,233,130,174,228,187,182,229,136,182,229,186,166,233,163,159,229,147, +129,232,153,189,231,132,182,232,189,172,232,189,189,230,138,165,228,187,183,232, +174,176,232,128,133,230,150,185,230,161,136,232,161,140,230,148,191,228,186,186, +230,176,145,231,148,168,229,147,129,228,184,156,232,165,191,230,143,144,229,135, +186,233,133,146,229,186,151,231,132,182,229,144,142,228,187,152,230,172,190,231, +131,173,231,130,185,228,187,165,229,137,141,229,174,140,229,133,168,229,143,145, +229,184,150,232,174,190,231,189,174,233,162,134,229,175,188,229,183,165,228,184, +154,229,140,187,233,153,162,231,156,139,231,156,139,231,187,143,229,133,184,229, +142,159,229,155,160,229,185,179,229,143,176,229,144,132,231,167,141,229,162,158, +229,138,160,230,157,144,230,150,153,230,150,176,229,162,158,228,185,139,229,144, +142,232,129,140,228,184,154,230,149,136,230,158,156,228,187,138,229,185,180,232, +174,186,230,150,135,230,136,145,229,155,189,229,145,138,232,175,137,231,137,136, +228,184,187,228,191,174,230,148,185,229,143,130,228,184,142,230,137,147,229,141, +176,229,191,171,228,185,144,230,156,186,230,162,176,232,167,130,231,130,185,229, +173,152,229,156,168,231,178,190,231,165,158,232,142,183,229,190,151,229,136,169, +231,148,168,231,187,167,231,187,173,228,189,160,228,187,172,232,191,153,228,185, +136,230,168,161,229,188,143,232,175,173,232,168,128,232,131,189,229,164,159,233, +155,133,232,153,142,230,147,141,228,189,156,233,163,142,230,160,188,228,184,128, +232,181,183,231,167,145,229,173,166,228,189,147,232,130,178,231,159,173,228,191, +161,230,157,161,228,187,182,230,178,187,231,150,151,232,191,144,229,138,168,228, +186,167,228,184,154,228,188,154,232,174,174,229,175,188,232,136,170,229,133,136, +231,148,159,232,129,148,231,155,159,229,143,175,230,152,175,229,149,143,233,161, +140,231,187,147,230,158,132,228,189,156,231,148,168,232,176,131,230,159,165,232, +179,135,230,150,153,232,135,170,229,138,168,232,180,159,232,180,163,229,134,156, +228,184,154,232,174,191,233,151,174,229,174,158,230,150,189,230,142,165,229,143, +151,232,174,168,232,174,186,233,130,163,228,184,170,229,143,141,233,166,136,229, +138,160,229,188,186,229,165,179,230,128,167,232,140,131,229,155,180,230,156,141, +229,139,153,228,188,145,233,151,178,228,187,138,230,151,165,229,174,162,230,156, +141,232,167,128,231,156,139,229,143,130,229,138,160,231,154,132,232,175,157,228, +184,128,231,130,185,228,191,157,232,175,129,229,155,190,228,185,166,230,156,137, +230,149,136,230,181,139,232,175,149,231,167,187,229,138,168,230,137,141,232,131, +189,229,134,179,229,174,154,232,130,161,231,165,168,228,184,141,230,150,173,233, +156,128,230,177,130,228,184,141,229,190,151,229,138,158,230,179,149,228,185,139, +233,151,180,233,135,135,231,148,168,232,144,165,233,148,128,230,138,149,232,175, +137,231,155,174,230,160,135,231,136,177,230,131,133,230,145,132,229,189,177,230, +156,137,228,186,155,232,164,135,232,163,189,230,150,135,229,173,166,230,156,186, +228,188,154,230,149,176,229,173,151,232,163,133,228,191,174,232,180,173,231,137, +169,229,134,156,230,157,145,229,133,168,233,157,162,231,178,190,229,147,129,229, +133,182,229,174,158,228,186,139,230,131,133,230,176,180,229,185,179,230,143,144, +231,164,186,228,184,138,229,184,130,232,176,162,232,176,162,230,153,174,233,128, +154,230,149,153,229,184,136,228,184,138,228,188,160,231,177,187,229,136,171,230, +173,140,230,155,178,230,139,165,230,156,137,229,136,155,230,150,176,233,133,141, +228,187,182,229,143,170,232,166,129,230,151,182,228,187,163,232,179,135,232,168, +138,232,190,190,229,136,176,228,186,186,231,148,159,232,174,162,233,152,133,232, +128,129,229,184,136,229,177,149,231,164,186,229,191,131,231,144,134,232,180,180, +229,173,144,231,182,178,231,171,153,228,184,187,233,161,140,232,135,170,231,132, +182,231,186,167,229,136,171,231,174,128,229,141,149,230,148,185,233,157,169,233, +130,163,228,186,155,230,157,165,232,175,180,230,137,147,229,188,128,228,187,163, +231,160,129,229,136,160,233,153,164,232,175,129,229,136,184,232,138,130,231,155, +174,233,135,141,231,130,185,230,172,161,230,149,184,229,164,154,229,176,145,232, +167,132,229,136,146,232,181,132,233,135,145,230,137,190,229,136,176,228,187,165, +229,144,142,229,164,167,229,133,168,228,184,187,233,161,181,230,156,128,228,189, +179,229,155,158,231,173,148,229,164,169,228,184,139,228,191,157,233,154,156,231, +142,176,228,187,163,230,163,128,230,159,165,230,138,149,231,165,168,229,176,143, +230,151,182,230,178,146,230,156,137,230,173,163,229,184,184,231,148,154,232,135, +179,228,187,163,231,144,134,231,155,174,229,189,149,229,133,172,229,188,128,229, +164,141,229,136,182,233,135,145,232,158,141,229,185,184,231,166,143,231,137,136, +230,156,172,229,189,162,230,136,144,229,135,134,229,164,135,232,161,140,230,131, +133,229,155,158,229,136,176,230,128,157,230,131,179,230,128,142,230,160,183,229, +141,143,232,174,174,232,174,164,232,175,129,230,156,128,229,165,189,228,186,167, +231,148,159,230,140,137,231,133,167,230,156,141,232,163,133,229,185,191,228,184, +156,229,138,168,230,188,171,233,135,135,232,180,173,230,150,176,230,137,139,231, +187,132,229,155,190,233,157,162,230,157,191,229,143,130,232,128,131,230,148,191, +230,178,187,229,174,185,230,152,147,229,164,169,229,156,176,229,138,170,229,138, +155,228,186,186,228,187,172,229,141,135,231,186,167,233,128,159,229,186,166,228, +186,186,231,137,169,232,176,131,230,149,180,230,181,129,232,161,140,233,128,160, +230,136,144,230,150,135,229,173,151,233,159,169,229,155,189,232,180,184,230,152, +147,229,188,128,229,177,149,231,155,184,233,151,156,232,161,168,231,142,176,229, +189,177,232,167,134,229,166,130,230,173,164,231,190,142,229,174,185,229,164,167, +229,176,143,230,138,165,233,129,147,230,157,161,230,172,190,229,191,131,230,131, +133,232,174,184,229,164,154,230,179,149,232,167,132,229,174,182,229,177,133,228, +185,166,229,186,151,232,191,158,230,142,165,231,171,139,229,141,179,228,184,190, +230,138,165,230,138,128,229,183,167,229,165,165,232,191,144,231,153,187,229,133, +165,228,187,165,230,157,165,231,144,134,232,174,186,228,186,139,228,187,182,232, +135,170,231,148,177,228,184,173,229,141,142,229,138,158,229,133,172,229,166,136, +229,166,136,231,156,159,230,173,163,228,184,141,233,148,153,229,133,168,230,150, +135,229,144,136,229,144,140,228,187,183,229,128,188,229,136,171,228,186,186,231, +155,145,231,157,163,229,133,183,228,189,147,228,184,150,231,186,170,229,155,162, +233,152,159,229,136,155,228,184,154,230,137,191,230,139,133,229,162,158,233,149, +191,230,156,137,228,186,186,228,191,157,230,140,129,229,149,134,229,174,182,231, +187,180,228,191,174,229,143,176,230,185,190,229,183,166,229,143,179,232,130,161, +228,187,189,231,173,148,230,161,136,229,174,158,233,153,133,231,148,181,228,191, +161,231,187,143,231,144,134,231,148,159,229,145,189,229,174,163,228,188,160,228, +187,187,229,138,161,230,173,163,229,188,143,231,137,185,232,137,178,228,184,139, +230,157,165,229,141,143,228,188,154,229,143,170,232,131,189,229,189,147,231,132, +182,233,135,141,230,150,176,229,133,167,229,174,185,230,140,135,229,175,188,232, +191,144,232,161,140,230,151,165,229,191,151,232,179,163,229,174,182,232,182,133, +232,191,135,229,156,159,229,156,176,230,181,153,230,177,159,230,148,175,228,187, +152,230,142,168,229,135,186,231,171,153,233,149,191,230,157,173,229,183,158,230, +137,167,232,161,140,229,136,182,233,128,160,228,185,139,228,184,128,230,142,168, +229,185,191,231,142,176,229,156,186,230,143,143,232,191,176,229,143,152,229,140, +150,228,188,160,231,187,159,230,173,140,230,137,139,228,191,157,233,153,169,232, +175,190,231,168,139,229,140,187,231,150,151,231,187,143,232,191,135,232,191,135, +229,142,187,228,185,139,229,137,141,230,148,182,229,133,165,229,185,180,229,186, +166,230,157,130,229,191,151,231,190,142,228,184,189,230,156,128,233,171,152,231, +153,187,233,153,134,230,156,170,230,157,165,229,138,160,229,183,165,229,133,141, +232,180,163,230,149,153,231,168,139,231,137,136,229,157,151,232,186,171,228,189, +147,233,135,141,229,186,134,229,135,186,229,148,174,230,136,144,230,156,172,229, +189,162,229,188,143,229,156,159,232,177,134,229,135,186,229,131,185,228,184,156, +230,150,185,233,130,174,231,174,177,229,141,151,228,186,172,230,177,130,232,129, +140,229,143,150,229,190,151,232,129,140,228,189,141,231,155,184,228,191,161,233, +161,181,233,157,162,229,136,134,233,146,159,231,189,145,233,161,181,231,161,174, +229,174,154,229,155,190,228,190,139,231,189,145,229,157,128,231,167,175,230,158, +129,233,148,153,232,175,175,231,155,174,231,154,132,229,174,157,232,180,157,230, +156,186,229,133,179,233,163,142,233,153,169,230,142,136,230,157,131,231,151,133, +230,175,146,229,174,160,231,137,169,233,153,164,228,186,134,232,169,149,232,171, +150,231,150,190,231,151,133,229,143,138,230,151,182,230,177,130,232,180,173,231, +171,153,231,130,185,229,132,191,231,171,165,230,175,143,229,164,169,228,184,173, +229,164,174,232,174,164,232,175,134,230,175,143,228,184,170,229,164,169,230,180, +165,229,173,151,228,189,147,229,143,176,231,129,163,231,187,180,230,138,164,230, +156,172,233,161,181,228,184,170,230,128,167,229,174,152,230,150,185,229,184,184, +232,167,129,231,155,184,230,156,186,230,136,152,231,149,165,229,186,148,229,189, +147,229,190,139,229,184,136,230,150,185,228,190,191,230,160,161,229,155,173,232, +130,161,229,184,130,230,136,191,229,177,139,230,160,143,231,155,174,229,145,152, +229,183,165,229,175,188,232,135,180,231,170,129,231,132,182,233,129,147,229,133, +183,230,156,172,231,189,145,231,187,147,229,144,136,230,161,163,230,161,136,229, +138,179,229,138,168,229,143,166,229,164,150,231,190,142,229,133,131,229,188,149, +232,181,183,230,148,185,229,143,152,231,172,172,229,155,155,228,188,154,232,174, +161,232,170,170,230,152,142,233,154,144,231,167,129,229,174,157,229,174,157,232, +167,132,232,140,131,230,182,136,232,180,185,229,133,177,229,144,140,229,191,152, +232,174,176,228,189,147,231,179,187,229,184,166,230,157,165,229,144,141,229,173, +151,231,153,188,232,161,168,229,188,128,230,148,190,229,138,160,231,155,159,229, +143,151,229,136,176,228,186,140,230,137,139,229,164,167,233,135,143,230,136,144, +228,186,186,230,149,176,233,135,143,229,133,177,228,186,171,229,140,186,229,159, +159,229,165,179,229,173,169,229,142,159,229,136,153,230,137,128,229,156,168,231, +187,147,230,157,159,233,128,154,228,191,161,232,182,133,231,186,167,233,133,141, +231,189,174,229,189,147,230,151,182,228,188,152,231,167,128,230,128,167,230,132, +159,230,136,191,228,186,167,233,129,138,230,136,178,229,135,186,229,143,163,230, +143,144,228,186,164,229,176,177,228,184,154,228,191,157,229,129,165,231,168,139, +229,186,166,229,143,130,230,149,176,228,186,139,228,184,154,230,149,180,228,184, +170,229,177,177,228,184,156,230,131,133,230,132,159,231,137,185,230,174,138,229, +136,134,233,161,158,230,144,156,229,176,139,229,177,158,228,186,142,233,151,168, +230,136,183,232,180,162,229,138,161,229,163,176,233,159,179,229,143,138,229,133, +182,232,180,162,231,187,143,229,157,154,230,140,129,229,185,178,233,131,168,230, +136,144,231,171,139,229,136,169,231,155,138,232,128,131,232,153,145,230,136,144, +233,131,189,229,140,133,232,163,133,231,148,168,230,136,182,230,175,148,232,181, +155,230,150,135,230,152,142,230,139,155,229,149,134,229,174,140,230,149,180,231, +156,159,230,152,175,231,156,188,231,157,155,228,188,153,228,188,180,229,168,129, +230,156,155,233,162,134,229,159,159,229,141,171,231,148,159,228,188,152,230,131, +160,232,171,150,229,163,135,229,133,172,229,133,177,232,137,175,229,165,189,229, +133,133,229,136,134,231,172,166,229,144,136,233,153,132,228,187,182,231,137,185, +231,130,185,228,184,141,229,143,175,232,139,177,230,150,135,232,181,132,228,186, +167,230,160,185,230,156,172,230,152,142,230,152,190,229,175,134,231,162,188,229, +133,172,228,188,151,230,176,145,230,151,143,230,155,180,229,138,160,228,186,171, +229,143,151,229,144,140,229,173,166,229,144,175,229,138,168,233,128,130,229,144, +136,229,142,159,230,157,165,233,151,174,231,173,148,230,156,172,230,150,135,231, +190,142,233,163,159,231,187,191,232,137,178,231,168,179,229,174,154,231,187,136, +228,186,142,231,148,159,231,137,169,228,190,155,230,177,130,230,144,156,231,139, +144,229,138,155,233,135,143,228,184,165,233,135,141,230,176,184,232,191,156,229, +134,153,231,156,159,230,156,137,233,153,144,231,171,158,228,186,137,229,175,185, +232,177,161,232,180,185,231,148,168,228,184,141,229,165,189,231,187,157,229,175, +185,229,141,129,229,136,134,228,191,131,232,191,155,231,130,185,232,175,132,229, +189,177,233,159,179,228,188,152,229,138,191,228,184,141,229,176,145,230,172,163, +232,181,143,229,185,182,228,184,148,230,156,137,231,130,185,230,150,185,229,144, +145,229,133,168,230,150,176,228,191,161,231,148,168,232,174,190,230,150,189,229, +189,162,232,177,161,232,181,132,230,160,188,231,170,129,231,160,180,233,154,143, +231,157,128,233,135,141,229,164,167,228,186,142,230,152,175,230,175,149,228,184, +154,230,153,186,232,131,189,229,140,150,229,183,165,229,174,140,231,190,142,229, +149,134,229,159,142,231,187,159,228,184,128,229,135,186,231,137,136,230,137,147, +233,128,160,231,148,162,229,147,129,230,166,130,229,134,181,231,148,168,228,186, +142,228,191,157,231,149,153,229,155,160,231,180,160,228,184,173,229,156,139,229, +173,152,229,130,168,232,180,180,229,155,190,230,156,128,230,132,155,233,149,191, +230,156,159,229,143,163,228,187,183,231,144,134,232,180,162,229,159,186,229,156, +176,229,174,137,230,142,146,230,173,166,230,177,137,233,135,140,233,157,162,229, +136,155,229,187,186,229,164,169,231,169,186,233,166,150,229,133,136,229,174,140, +229,150,132,233,169,177,229,138,168,228,184,139,233,157,162,228,184,141,229,134, +141,232,175,154,228,191,161,230,132,143,228,185,137,233,152,179,229,133,137,232, +139,177,229,155,189,230,188,130,228,186,174,229,134,155,228,186,139,231,142,169, +229,174,182,231,190,164,228,188,151,229,134,156,230,176,145,229,141,179,229,143, +175,229,144,141,231,168,177,229,174,182,229,133,183,229,138,168,231,148,187,230, +131,179,229,136,176,230,179,168,230,152,142,229,176,143,229,173,166,230,128,167, +232,131,189,232,128,131,231,160,148,231,161,172,228,187,182,232,167,130,231,156, +139,230,184,133,230,165,154,230,144,158,231,172,145,233,166,150,233,160,129,233, +187,132,233,135,145,233,128,130,231,148,168,230,177,159,232,139,143,231,156,159, +229,174,158,228,184,187,231,174,161,233,152,182,230,174,181,232,168,187,229,134, +138,231,191,187,232,175,145,230,157,131,229,136,169,229,129,154,229,165,189,228, +188,188,228,185,142,233,128,154,232,174,175,230,150,189,229,183,165,231,139,128, +230,133,139,228,185,159,232,174,184,231,142,175,228,191,157,229,159,185,229,133, +187,230,166,130,229,191,181,229,164,167,229,158,139,230,156,186,231,165,168,231, +144,134,232,167,163,229,140,191,229,144,141,99,117,97,110,100,111,101,110,118, +105,97,114,109,97,100,114,105,100,98,117,115,99,97,114,105,110,105,99,105,111, +116,105,101,109,112,111,112,111,114,113,117,101,99,117,101,110,116,97,101,115, +116,97,100,111,112,117,101,100,101,110,106,117,101,103,111,115,99,111,110,116, +114,97,101,115,116,195,161,110,110,111,109,98,114,101,116,105,101,110,101,110, +112,101,114,102,105,108,109,97,110,101,114,97,97,109,105,103,111,115,99,105,117, +100,97,100,99,101,110,116,114,111,97,117,110,113,117,101,112,117,101,100,101,115 +,100,101,110,116,114,111,112,114,105,109,101,114,112,114,101,99,105,111,115,101, +103,195,186,110,98,117,101,110,111,115,118,111,108,118,101,114,112,117,110,116, +111,115,115,101,109,97,110,97,104,97,98,195,173,97,97,103,111,115,116,111,110, +117,101,118,111,115,117,110,105,100,111,115,99,97,114,108,111,115,101,113,117, +105,112,111,110,105,195,177,111,115,109,117,99,104,111,115,97,108,103,117,110,97 +,99,111,114,114,101,111,105,109,97,103,101,110,112,97,114,116,105,114,97,114,114 +,105,98,97,109,97,114,195,173,97,104,111,109,98,114,101,101,109,112,108,101,111, +118,101,114,100,97,100,99,97,109,98,105,111,109,117,99,104,97,115,102,117,101, +114,111,110,112,97,115,97,100,111,108,195,173,110,101,97,112,97,114,101,99,101, +110,117,101,118,97,115,99,117,114,115,111,115,101,115,116,97,98,97,113,117,105, +101,114,111,108,105,98,114,111,115,99,117,97,110,116,111,97,99,99,101,115,111, +109,105,103,117,101,108,118,97,114,105,111,115,99,117,97,116,114,111,116,105,101 +,110,101,115,103,114,117,112,111,115,115,101,114,195,161,110,101,117,114,111,112 +,97,109,101,100,105,111,115,102,114,101,110,116,101,97,99,101,114,99,97,100,101, +109,195,161,115,111,102,101,114,116,97,99,111,99,104,101,115,109,111,100,101,108 +,111,105,116,97,108,105,97,108,101,116,114,97,115,97,108,103,195,186,110,99,111, +109,112,114,97,99,117,97,108,101,115,101,120,105,115,116,101,99,117,101,114,112, +111,115,105,101,110,100,111,112,114,101,110,115,97,108,108,101,103,97,114,118, +105,97,106,101,115,100,105,110,101,114,111,109,117,114,99,105,97,112,111,100,114 +,195,161,112,117,101,115,116,111,100,105,97,114,105,111,112,117,101,98,108,111, +113,117,105,101,114,101,109,97,110,117,101,108,112,114,111,112,105,111,99,114, +105,115,105,115,99,105,101,114,116,111,115,101,103,117,114,111,109,117,101,114, +116,101,102,117,101,110,116,101,99,101,114,114,97,114,103,114,97,110,100,101,101 +,102,101,99,116,111,112,97,114,116,101,115,109,101,100,105,100,97,112,114,111, +112,105,97,111,102,114,101,99,101,116,105,101,114,114,97,101,45,109,97,105,108, +118,97,114,105,97,115,102,111,114,109,97,115,102,117,116,117,114,111,111,98,106, +101,116,111,115,101,103,117,105,114,114,105,101,115,103,111,110,111,114,109,97, +115,109,105,115,109,111,115,195,186,110,105,99,111,99,97,109,105,110,111,115,105 +,116,105,111,115,114,97,122,195,179,110,100,101,98,105,100,111,112,114,117,101, +98,97,116,111,108,101,100,111,116,101,110,195,173,97,106,101,115,195,186,115,101 +,115,112,101,114,111,99,111,99,105,110,97,111,114,105,103,101,110,116,105,101, +110,100,97,99,105,101,110,116,111,99,195,161,100,105,122,104,97,98,108,97,114, +115,101,114,195,173,97,108,97,116,105,110,97,102,117,101,114,122,97,101,115,116, +105,108,111,103,117,101,114,114,97,101,110,116,114,97,114,195,169,120,105,116, +111,108,195,179,112,101,122,97,103,101,110,100,97,118,195,173,100,101,111,101, +118,105,116,97,114,112,97,103,105,110,97,109,101,116,114,111,115,106,97,118,105, +101,114,112,97,100,114,101,115,102,195,161,99,105,108,99,97,98,101,122,97,195, +161,114,101,97,115,115,97,108,105,100,97,101,110,118,195,173,111,106,97,112,195, +179,110,97,98,117,115,111,115,98,105,101,110,101,115,116,101,120,116,111,115,108 +,108,101,118,97,114,112,117,101,100,97,110,102,117,101,114,116,101,99,111,109, +195,186,110,99,108,97,115,101,115,104,117,109,97,110,111,116,101,110,105,100,111 +,98,105,108,98,97,111,117,110,105,100,97,100,101,115,116,195,161,115,101,100,105 +,116,97,114,99,114,101,97,100,111,208,180,208,187,209,143,209,135,209,130,208, +190,208,186,208,176,208,186,208,184,208,187,208,184,209,141,209,130,208,190,208, +178,209,129,208,181,208,181,208,179,208,190,208,191,209,128,208,184,209,130,208, +176,208,186,208,181,209,137,208,181,209,131,208,182,208,181,208,154,208,176,208, +186,208,177,208,181,208,183,208,177,209,139,208,187,208,190,208,189,208,184,208, +146,209,129,208,181,208,191,208,190,208,180,208,173,209,130,208,190,209,130,208, +190,208,188,209,135,208,181,208,188,208,189,208,181,209,130,208,187,208,181,209, +130,209,128,208,176,208,183,208,190,208,189,208,176,208,179,208,180,208,181,208, +188,208,189,208,181,208,148,208,187,209,143,208,159,209,128,208,184,208,189,208, +176,209,129,208,189,208,184,209,133,209,130,208,181,208,188,208,186,209,130,208, +190,208,179,208,190,208,180,208,178,208,190,209,130,209,130,208,176,208,188,208, +161,208,168,208,144,208,188,208,176,209,143,208,167,209,130,208,190,208,178,208, +176,209,129,208,178,208,176,208,188,208,181,208,188,209,131,208,162,208,176,208, +186,208,180,208,178,208,176,208,189,208,176,208,188,209,141,209,130,208,184,209, +141,209,130,209,131,208,146,208,176,208,188,209,130,208,181,209,133,208,191,209, +128,208,190,209,130,209,131,209,130,208,189,208,176,208,180,208,180,208,189,209, +143,208,146,208,190,209,130,209,130,209,128,208,184,208,189,208,181,208,185,208, +146,208,176,209,129,208,189,208,184,208,188,209,129,208,176,208,188,209,130,208, +190,209,130,209,128,209,131,208,177,208,158,208,189,208,184,208,188,208,184,209, +128,208,189,208,181,208,181,208,158,208,158,208,158,208,187,208,184,209,134,209, +141,209,130,208,176,208,158,208,189,208,176,208,189,208,181,208,188,208,180,208, +190,208,188,208,188,208,190,208,185,208,180,208,178,208,181,208,190,208,189,208, +190,209,129,209,131,208,180,224,164,149,224,165,135,224,164,185,224,165,136,224, +164,149,224,165,128,224,164,184,224,165,135,224,164,149,224,164,190,224,164,149, +224,165,139,224,164,148,224,164,176,224,164,170,224,164,176,224,164,168,224,165, +135,224,164,143,224,164,149,224,164,149,224,164,191,224,164,173,224,165,128,224, +164,135,224,164,184,224,164,149,224,164,176,224,164,164,224,165,139,224,164,185, +224,165,139,224,164,134,224,164,170,224,164,185,224,165,128,224,164,175,224,164, +185,224,164,175,224,164,190,224,164,164,224,164,149,224,164,165,224,164,190,106, +97,103,114,97,110,224,164,134,224,164,156,224,164,156,224,165,139,224,164,133, +224,164,172,224,164,166,224,165,139,224,164,151,224,164,136,224,164,156,224,164, +190,224,164,151,224,164,143,224,164,185,224,164,174,224,164,135,224,164,168,224, +164,181,224,164,185,224,164,175,224,165,135,224,164,165,224,165,135,224,164,165, +224,165,128,224,164,152,224,164,176,224,164,156,224,164,172,224,164,166,224,165, +128,224,164,149,224,164,136,224,164,156,224,165,128,224,164,181,224,165,135,224, +164,168,224,164,136,224,164,168,224,164,143,224,164,185,224,164,176,224,164,137, +224,164,184,224,164,174,224,165,135,224,164,149,224,164,174,224,164,181,224,165, +139,224,164,178,224,165,135,224,164,184,224,164,172,224,164,174,224,164,136,224, +164,166,224,165,135,224,164,147,224,164,176,224,164,134,224,164,174,224,164,172, +224,164,184,224,164,173,224,164,176,224,164,172,224,164,168,224,164,154,224,164, +178,224,164,174,224,164,168,224,164,134,224,164,151,224,164,184,224,165,128,224, +164,178,224,165,128,216,185,217,132,217,137,216,165,217,132,217,137,217,135,216, +176,216,167,216,162,216,174,216,177,216,185,216,175,216,175,216,167,217,132,217, +137,217,135,216,176,217,135,216,181,217,136,216,177,216,186,217,138,216,177,217, +131,216,167,217,134,217,136,217,132,216,167,216,168,217,138,217,134,216,185,216, +177,216,182,216,176,217,132,217,131,217,135,217,134,216,167,217,138,217,136,217, +133,217,130,216,167,217,132,216,185,217,132,217,138,216,167,217,134,216,167,217, +132,217,131,217,134,216,173,216,170,217,137,217,130,216,168,217,132,217,136,216, +173,216,169,216,167,216,174,216,177,217,129,217,130,216,183,216,185,216,168,216, +175,216,177,217,131,217,134,216,165,216,176,216,167,217,131,217,133,216,167,216, +167,216,173,216,175,216,165,217,132,216,167,217,129,217,138,217,135,216,168,216, +185,216,182,217,131,217,138,217,129,216,168,216,173,216,171,217,136,217,133,217, +134,217,136,217,135,217,136,216,163,217,134,216,167,216,172,216,175,216,167,217, +132,217,135,216,167,216,179,217,132,217,133,216,185,217,134,216,175,217,132,217, +138,216,179,216,185,216,168,216,177,216,181,217,132,217,137,217,133,217,134,216, +176,216,168,217,135,216,167,216,163,217,134,217,135,217,133,216,171,217,132,217, +131,217,134,216,170,216,167,217,132,216,167,216,173,217,138,216,171,217,133,216, +181,216,177,216,180,216,177,216,173,216,173,217,136,217,132,217,136,217,129,217, +138,216,167,216,176,216,167,217,132,217,131,217,132,217,133,216,177,216,169,216, +167,217,134,216,170,216,167,217,132,217,129,216,163,216,168,217,136,216,174,216, +167,216,181,216,163,217,134,216,170,216,167,217,134,217,135,216,167,217,132,217, +138,216,185,216,182,217,136,217,136,217,130,216,175,216,167,216,168,217,134,216, +174,217,138,216,177,216,168,217,134,216,170,217,132,217,131,217,133,216,180,216, +167,216,161,217,136,217,135,217,138,216,167,216,168,217,136,217,130,216,181,216, +181,217,136,217,133,216,167,216,177,217,130,217,133,216,163,216,173,216,175,217, +134,216,173,217,134,216,185,216,175,217,133,216,177,216,163,217,138,216,167,216, +173,216,169,217,131,216,170,216,168,216,175,217,136,217,134,217,138,216,172,216, +168,217,133,217,134,217,135,216,170,216,173,216,170,216,172,217,135,216,169,216, +179,217,134,216,169,217,138,216,170,217,133,217,131,216,177,216,169,216,186,216, +178,216,169,217,134,217,129,216,179,216,168,217,138,216,170,217,132,217,132,217, +135,217,132,217,134,216,167,216,170,217,132,217,131,217,130,217,132,216,168,217, +132,217,133,216,167,216,185,217,134,217,135,216,163,217,136,217,132,216,180,217, +138,216,161,217,134,217,136,216,177,216,163,217,133,216,167,217,129,217,138,217, +131,216,168,217,131,217,132,216,176,216,167,216,170,216,177,216,170,216,168,216, +168,216,163,217,134,217,135,217,133,216,179,216,167,217,134,217,131,216,168,217, +138,216,185,217,129,217,130,216,175,216,173,216,179,217,134,217,132,217,135,217, +133,216,180,216,185,216,177,216,163,217,135,217,132,216,180,217,135,216,177,217, +130,216,183,216,177,216,183,217,132,216,168,112,114,111,102,105,108,101,115,101, +114,118,105,99,101,100,101,102,97,117,108,116,104,105,109,115,101,108,102,100, +101,116,97,105,108,115,99,111,110,116,101,110,116,115,117,112,112,111,114,116, +115,116,97,114,116,101,100,109,101,115,115,97,103,101,115,117,99,99,101,115,115, +102,97,115,104,105,111,110,60,116,105,116,108,101,62,99,111,117,110,116,114,121, +97,99,99,111,117,110,116,99,114,101,97,116,101,100,115,116,111,114,105,101,115, +114,101,115,117,108,116,115,114,117,110,110,105,110,103,112,114,111,99,101,115, +115,119,114,105,116,105,110,103,111,98,106,101,99,116,115,118,105,115,105,98,108 +,101,119,101,108,99,111,109,101,97,114,116,105,99,108,101,117,110,107,110,111, +119,110,110,101,116,119,111,114,107,99,111,109,112,97,110,121,100,121,110,97,109 +,105,99,98,114,111,119,115,101,114,112,114,105,118,97,99,121,112,114,111,98,108, +101,109,83,101,114,118,105,99,101,114,101,115,112,101,99,116,100,105,115,112,108 +,97,121,114,101,113,117,101,115,116,114,101,115,101,114,118,101,119,101,98,115, +105,116,101,104,105,115,116,111,114,121,102,114,105,101,110,100,115,111,112,116, +105,111,110,115,119,111,114,107,105,110,103,118,101,114,115,105,111,110,109,105, +108,108,105,111,110,99,104,97,110,110,101,108,119,105,110,100,111,119,46,97,100, +100,114,101,115,115,118,105,115,105,116,101,100,119,101,97,116,104,101,114,99, +111,114,114,101,99,116,112,114,111,100,117,99,116,101,100,105,114,101,99,116,102 +,111,114,119,97,114,100,121,111,117,32,99,97,110,114,101,109,111,118,101,100,115 +,117,98,106,101,99,116,99,111,110,116,114,111,108,97,114,99,104,105,118,101,99, +117,114,114,101,110,116,114,101,97,100,105,110,103,108,105,98,114,97,114,121,108 +,105,109,105,116,101,100,109,97,110,97,103,101,114,102,117,114,116,104,101,114, +115,117,109,109,97,114,121,109,97,99,104,105,110,101,109,105,110,117,116,101,115 +,112,114,105,118,97,116,101,99,111,110,116,101,120,116,112,114,111,103,114,97, +109,115,111,99,105,101,116,121,110,117,109,98,101,114,115,119,114,105,116,116, +101,110,101,110,97,98,108,101,100,116,114,105,103,103,101,114,115,111,117,114,99 +,101,115,108,111,97,100,105,110,103,101,108,101,109,101,110,116,112,97,114,116, +110,101,114,102,105,110,97,108,108,121,112,101,114,102,101,99,116,109,101,97,110 +,105,110,103,115,121,115,116,101,109,115,107,101,101,112,105,110,103,99,117,108, +116,117,114,101,38,113,117,111,116,59,44,106,111,117,114,110,97,108,112,114,111, +106,101,99,116,115,117,114,102,97,99,101,115,38,113,117,111,116,59,101,120,112, +105,114,101,115,114,101,118,105,101,119,115,98,97,108,97,110,99,101,69,110,103, +108,105,115,104,67,111,110,116,101,110,116,116,104,114,111,117,103,104,80,108, +101,97,115,101,32,111,112,105,110,105,111,110,99,111,110,116,97,99,116,97,118, +101,114,97,103,101,112,114,105,109,97,114,121,118,105,108,108,97,103,101,83,112, +97,110,105,115,104,103,97,108,108,101,114,121,100,101,99,108,105,110,101,109,101 +,101,116,105,110,103,109,105,115,115,105,111,110,112,111,112,117,108,97,114,113, +117,97,108,105,116,121,109,101,97,115,117,114,101,103,101,110,101,114,97,108,115 +,112,101,99,105,101,115,115,101,115,115,105,111,110,115,101,99,116,105,111,110, +119,114,105,116,101,114,115,99,111,117,110,116,101,114,105,110,105,116,105,97, +108,114,101,112,111,114,116,115,102,105,103,117,114,101,115,109,101,109,98,101, +114,115,104,111,108,100,105,110,103,100,105,115,112,117,116,101,101,97,114,108, +105,101,114,101,120,112,114,101,115,115,100,105,103,105,116,97,108,112,105,99, +116,117,114,101,65,110,111,116,104,101,114,109,97,114,114,105,101,100,116,114,97 +,102,102,105,99,108,101,97,100,105,110,103,99,104,97,110,103,101,100,99,101,110, +116,114,97,108,118,105,99,116,111,114,121,105,109,97,103,101,115,47,114,101,97, +115,111,110,115,115,116,117,100,105,101,115,102,101,97,116,117,114,101,108,105, +115,116,105,110,103,109,117,115,116,32,98,101,115,99,104,111,111,108,115,86,101, +114,115,105,111,110,117,115,117,97,108,108,121,101,112,105,115,111,100,101,112, +108,97,121,105,110,103,103,114,111,119,105,110,103,111,98,118,105,111,117,115, +111,118,101,114,108,97,121,112,114,101,115,101,110,116,97,99,116,105,111,110,115 +,60,47,117,108,62,13,10,119,114,97,112,112,101,114,97,108,114,101,97,100,121,99, +101,114,116,97,105,110,114,101,97,108,105,116,121,115,116,111,114,97,103,101,97, +110,111,116,104,101,114,100,101,115,107,116,111,112,111,102,102,101,114,101,100, +112,97,116,116,101,114,110,117,110,117,115,117,97,108,68,105,103,105,116,97,108, +99,97,112,105,116,97,108,87,101,98,115,105,116,101,102,97,105,108,117,114,101,99 +,111,110,110,101,99,116,114,101,100,117,99,101,100,65,110,100,114,111,105,100, +100,101,99,97,100,101,115,114,101,103,117,108,97,114,32,38,97,109,112,59,32,97, +110,105,109,97,108,115,114,101,108,101,97,115,101,65,117,116,111,109,97,116,103, +101,116,116,105,110,103,109,101,116,104,111,100,115,110,111,116,104,105,110,103, +80,111,112,117,108,97,114,99,97,112,116,105,111,110,108,101,116,116,101,114,115, +99,97,112,116,117,114,101,115,99,105,101,110,99,101,108,105,99,101,110,115,101, +99,104,97,110,103,101,115,69,110,103,108,97,110,100,61,49,38,97,109,112,59,72, +105,115,116,111,114,121,32,61,32,110,101,119,32,67,101,110,116,114,97,108,117, +112,100,97,116,101,100,83,112,101,99,105,97,108,78,101,116,119,111,114,107,114, +101,113,117,105,114,101,99,111,109,109,101,110,116,119,97,114,110,105,110,103,67 +,111,108,108,101,103,101,116,111,111,108,98,97,114,114,101,109,97,105,110,115,98 +,101,99,97,117,115,101,101,108,101,99,116,101,100,68,101,117,116,115,99,104,102, +105,110,97,110,99,101,119,111,114,107,101,114,115,113,117,105,99,107,108,121,98, +101,116,119,101,101,110,101,120,97,99,116,108,121,115,101,116,116,105,110,103, +100,105,115,101,97,115,101,83,111,99,105,101,116,121,119,101,97,112,111,110,115, +101,120,104,105,98,105,116,38,108,116,59,33,45,45,67,111,110,116,114,111,108,99, +108,97,115,115,101,115,99,111,118,101,114,101,100,111,117,116,108,105,110,101,97 +,116,116,97,99,107,115,100,101,118,105,99,101,115,40,119,105,110,100,111,119,112 +,117,114,112,111,115,101,116,105,116,108,101,61,34,77,111,98,105,108,101,32,107, +105,108,108,105,110,103,115,104,111,119,105,110,103,73,116,97,108,105,97,110,100 +,114,111,112,112,101,100,104,101,97,118,105,108,121,101,102,102,101,99,116,115, +45,49,39,93,41,59,10,99,111,110,102,105,114,109,67,117,114,114,101,110,116,97, +100,118,97,110,99,101,115,104,97,114,105,110,103,111,112,101,110,105,110,103,100 +,114,97,119,105,110,103,98,105,108,108,105,111,110,111,114,100,101,114,101,100, +71,101,114,109,97,110,121,114,101,108,97,116,101,100,60,47,102,111,114,109,62, +105,110,99,108,117,100,101,119,104,101,116,104,101,114,100,101,102,105,110,101, +100,83,99,105,101,110,99,101,99,97,116,97,108,111,103,65,114,116,105,99,108,101, +98,117,116,116,111,110,115,108,97,114,103,101,115,116,117,110,105,102,111,114, +109,106,111,117,114,110,101,121,115,105,100,101,98,97,114,67,104,105,99,97,103, +111,104,111,108,105,100,97,121,71,101,110,101,114,97,108,112,97,115,115,97,103, +101,44,38,113,117,111,116,59,97,110,105,109,97,116,101,102,101,101,108,105,110, +103,97,114,114,105,118,101,100,112,97,115,115,105,110,103,110,97,116,117,114,97, +108,114,111,117,103,104,108,121,46,10,10,84,104,101,32,98,117,116,32,110,111,116 +,100,101,110,115,105,116,121,66,114,105,116,97,105,110,67,104,105,110,101,115, +101,108,97,99,107,32,111,102,116,114,105,98,117,116,101,73,114,101,108,97,110, +100,34,32,100,97,116,97,45,102,97,99,116,111,114,115,114,101,99,101,105,118,101, +116,104,97,116,32,105,115,76,105,98,114,97,114,121,104,117,115,98,97,110,100,105 +,110,32,102,97,99,116,97,102,102,97,105,114,115,67,104,97,114,108,101,115,114,97 +,100,105,99,97,108,98,114,111,117,103,104,116,102,105,110,100,105,110,103,108,97 +,110,100,105,110,103,58,108,97,110,103,61,34,114,101,116,117,114,110,32,108,101, +97,100,101,114,115,112,108,97,110,110,101,100,112,114,101,109,105,117,109,112,97 +,99,107,97,103,101,65,109,101,114,105,99,97,69,100,105,116,105,111,110,93,38,113 +,117,111,116,59,77,101,115,115,97,103,101,110,101,101,100,32,116,111,118,97,108, +117,101,61,34,99,111,109,112,108,101,120,108,111,111,107,105,110,103,115,116,97, +116,105,111,110,98,101,108,105,101,118,101,115,109,97,108,108,101,114,45,109,111 +,98,105,108,101,114,101,99,111,114,100,115,119,97,110,116,32,116,111,107,105,110 +,100,32,111,102,70,105,114,101,102,111,120,121,111,117,32,97,114,101,115,105,109 +,105,108,97,114,115,116,117,100,105,101,100,109,97,120,105,109,117,109,104,101, +97,100,105,110,103,114,97,112,105,100,108,121,99,108,105,109,97,116,101,107,105, +110,103,100,111,109,101,109,101,114,103,101,100,97,109,111,117,110,116,115,102, +111,117,110,100,101,100,112,105,111,110,101,101,114,102,111,114,109,117,108,97, +100,121,110,97,115,116,121,104,111,119,32,116,111,32,83,117,112,112,111,114,116, +114,101,118,101,110,117,101,101,99,111,110,111,109,121,82,101,115,117,108,116, +115,98,114,111,116,104,101,114,115,111,108,100,105,101,114,108,97,114,103,101, +108,121,99,97,108,108,105,110,103,46,38,113,117,111,116,59,65,99,99,111,117,110, +116,69,100,119,97,114,100,32,115,101,103,109,101,110,116,82,111,98,101,114,116, +32,101,102,102,111,114,116,115,80,97,99,105,102,105,99,108,101,97,114,110,101, +100,117,112,32,119,105,116,104,104,101,105,103,104,116,58,119,101,32,104,97,118, +101,65,110,103,101,108,101,115,110,97,116,105,111,110,115,95,115,101,97,114,99, +104,97,112,112,108,105,101,100,97,99,113,117,105,114,101,109,97,115,115,105,118, +101,103,114,97,110,116,101,100,58,32,102,97,108,115,101,116,114,101,97,116,101, +100,98,105,103,103,101,115,116,98,101,110,101,102,105,116,100,114,105,118,105, +110,103,83,116,117,100,105,101,115,109,105,110,105,109,117,109,112,101,114,104, +97,112,115,109,111,114,110,105,110,103,115,101,108,108,105,110,103,105,115,32, +117,115,101,100,114,101,118,101,114,115,101,118,97,114,105,97,110,116,32,114,111 +,108,101,61,34,109,105,115,115,105,110,103,97,99,104,105,101,118,101,112,114,111 +,109,111,116,101,115,116,117,100,101,110,116,115,111,109,101,111,110,101,101,120 +,116,114,101,109,101,114,101,115,116,111,114,101,98,111,116,116,111,109,58,101, +118,111,108,118,101,100,97,108,108,32,116,104,101,115,105,116,101,109,97,112,101 +,110,103,108,105,115,104,119,97,121,32,116,111,32,32,65,117,103,117,115,116,115, +121,109,98,111,108,115,67,111,109,112,97,110,121,109,97,116,116,101,114,115,109, +117,115,105,99,97,108,97,103,97,105,110,115,116,115,101,114,118,105,110,103,125, +41,40,41,59,13,10,112,97,121,109,101,110,116,116,114,111,117,98,108,101,99,111, +110,99,101,112,116,99,111,109,112,97,114,101,112,97,114,101,110,116,115,112,108, +97,121,101,114,115,114,101,103,105,111,110,115,109,111,110,105,116,111,114,32,39 +,39,84,104,101,32,119,105,110,110,105,110,103,101,120,112,108,111,114,101,97,100 +,97,112,116,101,100,71,97,108,108,101,114,121,112,114,111,100,117,99,101,97,98, +105,108,105,116,121,101,110,104,97,110,99,101,99,97,114,101,101,114,115,41,46,32 +,84,104,101,32,99,111,108,108,101,99,116,83,101,97,114,99,104,32,97,110,99,105, +101,110,116,101,120,105,115,116,101,100,102,111,111,116,101,114,32,104,97,110, +100,108,101,114,112,114,105,110,116,101,100,99,111,110,115,111,108,101,69,97,115 +,116,101,114,110,101,120,112,111,114,116,115,119,105,110,100,111,119,115,67,104, +97,110,110,101,108,105,108,108,101,103,97,108,110,101,117,116,114,97,108,115,117 +,103,103,101,115,116,95,104,101,97,100,101,114,115,105,103,110,105,110,103,46, +104,116,109,108,34,62,115,101,116,116,108,101,100,119,101,115,116,101,114,110,99 +,97,117,115,105,110,103,45,119,101,98,107,105,116,99,108,97,105,109,101,100,74, +117,115,116,105,99,101,99,104,97,112,116,101,114,118,105,99,116,105,109,115,84, +104,111,109,97,115,32,109,111,122,105,108,108,97,112,114,111,109,105,115,101,112 +,97,114,116,105,101,115,101,100,105,116,105,111,110,111,117,116,115,105,100,101, +58,102,97,108,115,101,44,104,117,110,100,114,101,100,79,108,121,109,112,105,99, +95,98,117,116,116,111,110,97,117,116,104,111,114,115,114,101,97,99,104,101,100, +99,104,114,111,110,105,99,100,101,109,97,110,100,115,115,101,99,111,110,100,115, +112,114,111,116,101,99,116,97,100,111,112,116,101,100,112,114,101,112,97,114,101 +,110,101,105,116,104,101,114,103,114,101,97,116,108,121,103,114,101,97,116,101, +114,111,118,101,114,97,108,108,105,109,112,114,111,118,101,99,111,109,109,97,110 +,100,115,112,101,99,105,97,108,115,101,97,114,99,104,46,119,111,114,115,104,105, +112,102,117,110,100,105,110,103,116,104,111,117,103,104,116,104,105,103,104,101, +115,116,105,110,115,116,101,97,100,117,116,105,108,105,116,121,113,117,97,114, +116,101,114,67,117,108,116,117,114,101,116,101,115,116,105,110,103,99,108,101,97 +,114,108,121,101,120,112,111,115,101,100,66,114,111,119,115,101,114,108,105,98, +101,114,97,108,125,32,99,97,116,99,104,80,114,111,106,101,99,116,101,120,97,109, +112,108,101,104,105,100,101,40,41,59,70,108,111,114,105,100,97,97,110,115,119, +101,114,115,97,108,108,111,119,101,100,69,109,112,101,114,111,114,100,101,102, +101,110,115,101,115,101,114,105,111,117,115,102,114,101,101,100,111,109,83,101, +118,101,114,97,108,45,98,117,116,116,111,110,70,117,114,116,104,101,114,111,117, +116,32,111,102,32,33,61,32,110,117,108,108,116,114,97,105,110,101,100,68,101,110 +,109,97,114,107,118,111,105,100,40,48,41,47,97,108,108,46,106,115,112,114,101, +118,101,110,116,82,101,113,117,101,115,116,83,116,101,112,104,101,110,10,10,87, +104,101,110,32,111,98,115,101,114,118,101,60,47,104,50,62,13,10,77,111,100,101, +114,110,32,112,114,111,118,105,100,101,34,32,97,108,116,61,34,98,111,114,100,101 +,114,115,46,10,10,70,111,114,32,10,10,77,97,110,121,32,97,114,116,105,115,116, +115,112,111,119,101,114,101,100,112,101,114,102,111,114,109,102,105,99,116,105, +111,110,116,121,112,101,32,111,102,109,101,100,105,99,97,108,116,105,99,107,101, +116,115,111,112,112,111,115,101,100,67,111,117,110,99,105,108,119,105,116,110, +101,115,115,106,117,115,116,105,99,101,71,101,111,114,103,101,32,66,101,108,103, +105,117,109,46,46,46,60,47,97,62,116,119,105,116,116,101,114,110,111,116,97,98, +108,121,119,97,105,116,105,110,103,119,97,114,102,97,114,101,32,79,116,104,101, +114,32,114,97,110,107,105,110,103,112,104,114,97,115,101,115,109,101,110,116,105 +,111,110,115,117,114,118,105,118,101,115,99,104,111,108,97,114,60,47,112,62,13, +10,32,67,111,117,110,116,114,121,105,103,110,111,114,101,100,108,111,115,115,32, +111,102,106,117,115,116,32,97,115,71,101,111,114,103,105,97,115,116,114,97,110, +103,101,60,104,101,97,100,62,60,115,116,111,112,112,101,100,49,39,93,41,59,13,10 +,105,115,108,97,110,100,115,110,111,116,97,98,108,101,98,111,114,100,101,114,58, +108,105,115,116,32,111,102,99,97,114,114,105,101,100,49,48,48,44,48,48,48,60,47, +104,51,62,10,32,115,101,118,101,114,97,108,98,101,99,111,109,101,115,115,101,108 +,101,99,116,32,119,101,100,100,105,110,103,48,48,46,104,116,109,108,109,111,110, +97,114,99,104,111,102,102,32,116,104,101,116,101,97,99,104,101,114,104,105,103, +104,108,121,32,98,105,111,108,111,103,121,108,105,102,101,32,111,102,111,114,32, +101,118,101,110,114,105,115,101,32,111,102,38,114,97,113,117,111,59,112,108,117, +115,111,110,101,104,117,110,116,105,110,103,40,116,104,111,117,103,104,68,111, +117,103,108,97,115,106,111,105,110,105,110,103,99,105,114,99,108,101,115,70,111, +114,32,116,104,101,65,110,99,105,101,110,116,86,105,101,116,110,97,109,118,101, +104,105,99,108,101,115,117,99,104,32,97,115,99,114,121,115,116,97,108,118,97,108 +,117,101,32,61,87,105,110,100,111,119,115,101,110,106,111,121,101,100,97,32,115, +109,97,108,108,97,115,115,117,109,101,100,60,97,32,105,100,61,34,102,111,114,101 +,105,103,110,32,65,108,108,32,114,105,104,111,119,32,116,104,101,68,105,115,112, +108,97,121,114,101,116,105,114,101,100,104,111,119,101,118,101,114,104,105,100, +100,101,110,59,98,97,116,116,108,101,115,115,101,101,107,105,110,103,99,97,98, +105,110,101,116,119,97,115,32,110,111,116,108,111,111,107,32,97,116,99,111,110, +100,117,99,116,103,101,116,32,116,104,101,74,97,110,117,97,114,121,104,97,112, +112,101,110,115,116,117,114,110,105,110,103,97,58,104,111,118,101,114,79,110,108 +,105,110,101,32,70,114,101,110,99,104,32,108,97,99,107,105,110,103,116,121,112, +105,99,97,108,101,120,116,114,97,99,116,101,110,101,109,105,101,115,101,118,101, +110,32,105,102,103,101,110,101,114,97,116,100,101,99,105,100,101,100,97,114,101, +32,110,111,116,47,115,101,97,114,99,104,98,101,108,105,101,102,115,45,105,109,97 +,103,101,58,108,111,99,97,116,101,100,115,116,97,116,105,99,46,108,111,103,105, +110,34,62,99,111,110,118,101,114,116,118,105,111,108,101,110,116,101,110,116,101 +,114,101,100,102,105,114,115,116,34,62,99,105,114,99,117,105,116,70,105,110,108, +97,110,100,99,104,101,109,105,115,116,115,104,101,32,119,97,115,49,48,112,120,59 +,34,62,97,115,32,115,117,99,104,100,105,118,105,100,101,100,60,47,115,112,97,110 +,62,119,105,108,108,32,98,101,108,105,110,101,32,111,102,97,32,103,114,101,97, +116,109,121,115,116,101,114,121,47,105,110,100,101,120,46,102,97,108,108,105,110 +,103,100,117,101,32,116,111,32,114,97,105,108,119,97,121,99,111,108,108,101,103, +101,109,111,110,115,116,101,114,100,101,115,99,101,110,116,105,116,32,119,105, +116,104,110,117,99,108,101,97,114,74,101,119,105,115,104,32,112,114,111,116,101, +115,116,66,114,105,116,105,115,104,102,108,111,119,101,114,115,112,114,101,100, +105,99,116,114,101,102,111,114,109,115,98,117,116,116,111,110,32,119,104,111,32, +119,97,115,108,101,99,116,117,114,101,105,110,115,116,97,110,116,115,117,105,99, +105,100,101,103,101,110,101,114,105,99,112,101,114,105,111,100,115,109,97,114, +107,101,116,115,83,111,99,105,97,108,32,102,105,115,104,105,110,103,99,111,109, +98,105,110,101,103,114,97,112,104,105,99,119,105,110,110,101,114,115,60,98,114, +32,47,62,60,98,121,32,116,104,101,32,78,97,116,117,114,97,108,80,114,105,118,97, +99,121,99,111,111,107,105,101,115,111,117,116,99,111,109,101,114,101,115,111,108 +,118,101,83,119,101,100,105,115,104,98,114,105,101,102,108,121,80,101,114,115, +105,97,110,115,111,32,109,117,99,104,67,101,110,116,117,114,121,100,101,112,105, +99,116,115,99,111,108,117,109,110,115,104,111,117,115,105,110,103,115,99,114,105 +,112,116,115,110,101,120,116,32,116,111,98,101,97,114,105,110,103,109,97,112,112 +,105,110,103,114,101,118,105,115,101,100,106,81,117,101,114,121,40,45,119,105, +100,116,104,58,116,105,116,108,101,34,62,116,111,111,108,116,105,112,83,101,99, +116,105,111,110,100,101,115,105,103,110,115,84,117,114,107,105,115,104,121,111, +117,110,103,101,114,46,109,97,116,99,104,40,125,41,40,41,59,10,10,98,117,114,110 +,105,110,103,111,112,101,114,97,116,101,100,101,103,114,101,101,115,115,111,117, +114,99,101,61,82,105,99,104,97,114,100,99,108,111,115,101,108,121,112,108,97,115 +,116,105,99,101,110,116,114,105,101,115,60,47,116,114,62,13,10,99,111,108,111, +114,58,35,117,108,32,105,100,61,34,112,111,115,115,101,115,115,114,111,108,108, +105,110,103,112,104,121,115,105,99,115,102,97,105,108,105,110,103,101,120,101,99 +,117,116,101,99,111,110,116,101,115,116,108,105,110,107,32,116,111,68,101,102,97 +,117,108,116,60,98,114,32,47,62,10,58,32,116,114,117,101,44,99,104,97,114,116, +101,114,116,111,117,114,105,115,109,99,108,97,115,115,105,99,112,114,111,99,101, +101,100,101,120,112,108,97,105,110,60,47,104,49,62,13,10,111,110,108,105,110,101 +,46,63,120,109,108,32,118,101,104,101,108,112,105,110,103,100,105,97,109,111,110 +,100,117,115,101,32,116,104,101,97,105,114,108,105,110,101,101,110,100,32,45,45, +62,41,46,97,116,116,114,40,114,101,97,100,101,114,115,104,111,115,116,105,110, +103,35,102,102,102,102,102,102,114,101,97,108,105,122,101,86,105,110,99,101,110, +116,115,105,103,110,97,108,115,32,115,114,99,61,34,47,80,114,111,100,117,99,116, +100,101,115,112,105,116,101,100,105,118,101,114,115,101,116,101,108,108,105,110, +103,80,117,98,108,105,99,32,104,101,108,100,32,105,110,74,111,115,101,112,104,32 +,116,104,101,97,116,114,101,97,102,102,101,99,116,115,60,115,116,121,108,101,62, +97,32,108,97,114,103,101,100,111,101,115,110,39,116,108,97,116,101,114,44,32,69, +108,101,109,101,110,116,102,97,118,105,99,111,110,99,114,101,97,116,111,114,72, +117,110,103,97,114,121,65,105,114,112,111,114,116,115,101,101,32,116,104,101,115 +,111,32,116,104,97,116,77,105,99,104,97,101,108,83,121,115,116,101,109,115,80, +114,111,103,114,97,109,115,44,32,97,110,100,32,32,119,105,100,116,104,61,101,38, +113,117,111,116,59,116,114,97,100,105,110,103,108,101,102,116,34,62,10,112,101, +114,115,111,110,115,71,111,108,100,101,110,32,65,102,102,97,105,114,115,103,114, +97,109,109,97,114,102,111,114,109,105,110,103,100,101,115,116,114,111,121,105, +100,101,97,32,111,102,99,97,115,101,32,111,102,111,108,100,101,115,116,32,116, +104,105,115,32,105,115,46,115,114,99,32,61,32,99,97,114,116,111,111,110,114,101, +103,105,115,116,114,67,111,109,109,111,110,115,77,117,115,108,105,109,115,87,104 +,97,116,32,105,115,105,110,32,109,97,110,121,109,97,114,107,105,110,103,114,101, +118,101,97,108,115,73,110,100,101,101,100,44,101,113,117,97,108,108,121,47,115, +104,111,119,95,97,111,117,116,100,111,111,114,101,115,99,97,112,101,40,65,117, +115,116,114,105,97,103,101,110,101,116,105,99,115,121,115,116,101,109,44,73,110, +32,116,104,101,32,115,105,116,116,105,110,103,72,101,32,97,108,115,111,73,115, +108,97,110,100,115,65,99,97,100,101,109,121,10,9,9,60,33,45,45,68,97,110,105,101 +,108,32,98,105,110,100,105,110,103,98,108,111,99,107,34,62,105,109,112,111,115, +101,100,117,116,105,108,105,122,101,65,98,114,97,104,97,109,40,101,120,99,101, +112,116,123,119,105,100,116,104,58,112,117,116,116,105,110,103,41,46,104,116,109 +,108,40,124,124,32,91,93,59,10,68,65,84,65,91,32,42,107,105,116,99,104,101,110, +109,111,117,110,116,101,100,97,99,116,117,97,108,32,100,105,97,108,101,99,116, +109,97,105,110,108,121,32,95,98,108,97,110,107,39,105,110,115,116,97,108,108,101 +,120,112,101,114,116,115,105,102,40,116,121,112,101,73,116,32,97,108,115,111,38, +99,111,112,121,59,32,34,62,84,101,114,109,115,98,111,114,110,32,105,110,79,112, +116,105,111,110,115,101,97,115,116,101,114,110,116,97,108,107,105,110,103,99,111 +,110,99,101,114,110,103,97,105,110,101,100,32,111,110,103,111,105,110,103,106, +117,115,116,105,102,121,99,114,105,116,105,99,115,102,97,99,116,111,114,121,105, +116,115,32,111,119,110,97,115,115,97,117,108,116,105,110,118,105,116,101,100,108 +,97,115,116,105,110,103,104,105,115,32,111,119,110,104,114,101,102,61,34,47,34, +32,114,101,108,61,34,100,101,118,101,108,111,112,99,111,110,99,101,114,116,100, +105,97,103,114,97,109,100,111,108,108,97,114,115,99,108,117,115,116,101,114,112, +104,112,63,105,100,61,97,108,99,111,104,111,108,41,59,125,41,40,41,59,117,115, +105,110,103,32,97,62,60,115,112,97,110,62,118,101,115,115,101,108,115,114,101, +118,105,118,97,108,65,100,100,114,101,115,115,97,109,97,116,101,117,114,97,110, +100,114,111,105,100,97,108,108,101,103,101,100,105,108,108,110,101,115,115,119, +97,108,107,105,110,103,99,101,110,116,101,114,115,113,117,97,108,105,102,121,109 +,97,116,99,104,101,115,117,110,105,102,105,101,100,101,120,116,105,110,99,116,68 +,101,102,101,110,115,101,100,105,101,100,32,105,110,10,9,60,33,45,45,32,99,117, +115,116,111,109,115,108,105,110,107,105,110,103,76,105,116,116,108,101,32,66,111 +,111,107,32,111,102,101,118,101,110,105,110,103,109,105,110,46,106,115,63,97,114 +,101,32,116,104,101,107,111,110,116,97,107,116,116,111,100,97,121,39,115,46,104, +116,109,108,34,32,116,97,114,103,101,116,61,119,101,97,114,105,110,103,65,108, +108,32,82,105,103,59,10,125,41,40,41,59,114,97,105,115,105,110,103,32,65,108,115 +,111,44,32,99,114,117,99,105,97,108,97,98,111,117,116,34,62,100,101,99,108,97, +114,101,45,45,62,10,60,115,99,102,105,114,101,102,111,120,97,115,32,109,117,99, +104,97,112,112,108,105,101,115,105,110,100,101,120,44,32,115,44,32,98,117,116,32 +,116,121,112,101,32,61,32,10,13,10,60,33,45,45,116,111,119,97,114,100,115,82,101 +,99,111,114,100,115,80,114,105,118,97,116,101,70,111,114,101,105,103,110,80,114, +101,109,105,101,114,99,104,111,105,99,101,115,86,105,114,116,117,97,108,114,101, +116,117,114,110,115,67,111,109,109,101,110,116,80,111,119,101,114,101,100,105, +110,108,105,110,101,59,112,111,118,101,114,116,121,99,104,97,109,98,101,114,76, +105,118,105,110,103,32,118,111,108,117,109,101,115,65,110,116,104,111,110,121, +108,111,103,105,110,34,32,82,101,108,97,116,101,100,69,99,111,110,111,109,121, +114,101,97,99,104,101,115,99,117,116,116,105,110,103,103,114,97,118,105,116,121, +108,105,102,101,32,105,110,67,104,97,112,116,101,114,45,115,104,97,100,111,119, +78,111,116,97,98,108,101,60,47,116,100,62,13,10,32,114,101,116,117,114,110,115, +116,97,100,105,117,109,119,105,100,103,101,116,115,118,97,114,121,105,110,103, +116,114,97,118,101,108,115,104,101,108,100,32,98,121,119,104,111,32,97,114,101, +119,111,114,107,32,105,110,102,97,99,117,108,116,121,97,110,103,117,108,97,114, +119,104,111,32,104,97,100,97,105,114,112,111,114,116,116,111,119,110,32,111,102, +10,10,83,111,109,101,32,39,99,108,105,99,107,39,99,104,97,114,103,101,115,107, +101,121,119,111,114,100,105,116,32,119,105,108,108,99,105,116,121,32,111,102,40, +116,104,105,115,41,59,65,110,100,114,101,119,32,117,110,105,113,117,101,32,99, +104,101,99,107,101,100,111,114,32,109,111,114,101,51,48,48,112,120,59,32,114,101 +,116,117,114,110,59,114,115,105,111,110,61,34,112,108,117,103,105,110,115,119, +105,116,104,105,110,32,104,101,114,115,101,108,102,83,116,97,116,105,111,110,70, +101,100,101,114,97,108,118,101,110,116,117,114,101,112,117,98,108,105,115,104, +115,101,110,116,32,116,111,116,101,110,115,105,111,110,97,99,116,114,101,115,115 +,99,111,109,101,32,116,111,102,105,110,103,101,114,115,68,117,107,101,32,111,102 +,112,101,111,112,108,101,44,101,120,112,108,111,105,116,119,104,97,116,32,105, +115,104,97,114,109,111,110,121,97,32,109,97,106,111,114,34,58,34,104,116,116,112 +,105,110,32,104,105,115,32,109,101,110,117,34,62,10,109,111,110,116,104,108,121, +111,102,102,105,99,101,114,99,111,117,110,99,105,108,103,97,105,110,105,110,103, +101,118,101,110,32,105,110,83,117,109,109,97,114,121,100,97,116,101,32,111,102, +108,111,121,97,108,116,121,102,105,116,110,101,115,115,97,110,100,32,119,97,115, +101,109,112,101,114,111,114,115,117,112,114,101,109,101,83,101,99,111,110,100,32 +,104,101,97,114,105,110,103,82,117,115,115,105,97,110,108,111,110,103,101,115, +116,65,108,98,101,114,116,97,108,97,116,101,114,97,108,115,101,116,32,111,102,32 +,115,109,97,108,108,34,62,46,97,112,112,101,110,100,100,111,32,119,105,116,104, +102,101,100,101,114,97,108,98,97,110,107,32,111,102,98,101,110,101,97,116,104,68 +,101,115,112,105,116,101,67,97,112,105,116,97,108,103,114,111,117,110,100,115,41 +,44,32,97,110,100,32,112,101,114,99,101,110,116,105,116,32,102,114,111,109,99, +108,111,115,105,110,103,99,111,110,116,97,105,110,73,110,115,116,101,97,100,102, +105,102,116,101,101,110,97,115,32,119,101,108,108,46,121,97,104,111,111,46,114, +101,115,112,111,110,100,102,105,103,104,116,101,114,111,98,115,99,117,114,101, +114,101,102,108,101,99,116,111,114,103,97,110,105,99,61,32,77,97,116,104,46,101, +100,105,116,105,110,103,111,110,108,105,110,101,32,112,97,100,100,105,110,103,97 +,32,119,104,111,108,101,111,110,101,114,114,111,114,121,101,97,114,32,111,102, +101,110,100,32,111,102,32,98,97,114,114,105,101,114,119,104,101,110,32,105,116, +104,101,97,100,101,114,32,104,111,109,101,32,111,102,114,101,115,117,109,101,100 +,114,101,110,97,109,101,100,115,116,114,111,110,103,62,104,101,97,116,105,110, +103,114,101,116,97,105,110,115,99,108,111,117,100,102,114,119,97,121,32,111,102, +32,77,97,114,99,104,32,49,107,110,111,119,105,110,103,105,110,32,112,97,114,116, +66,101,116,119,101,101,110,108,101,115,115,111,110,115,99,108,111,115,101,115, +116,118,105,114,116,117,97,108,108,105,110,107,115,34,62,99,114,111,115,115,101, +100,69,78,68,32,45,45,62,102,97,109,111,117,115,32,97,119,97,114,100,101,100,76, +105,99,101,110,115,101,72,101,97,108,116,104,32,102,97,105,114,108,121,32,119, +101,97,108,116,104,121,109,105,110,105,109,97,108,65,102,114,105,99,97,110,99, +111,109,112,101,116,101,108,97,98,101,108,34,62,115,105,110,103,105,110,103,102, +97,114,109,101,114,115,66,114,97,115,105,108,41,100,105,115,99,117,115,115,114, +101,112,108,97,99,101,71,114,101,103,111,114,121,102,111,110,116,32,99,111,112, +117,114,115,117,101,100,97,112,112,101,97,114,115,109,97,107,101,32,117,112,114, +111,117,110,100,101,100,98,111,116,104,32,111,102,98,108,111,99,107,101,100,115, +97,119,32,116,104,101,111,102,102,105,99,101,115,99,111,108,111,117,114,115,105, +102,40,100,111,99,117,119,104,101,110,32,104,101,101,110,102,111,114,99,101,112, +117,115,104,40,102,117,65,117,103,117,115,116,32,85,84,70,45,56,34,62,70,97,110, +116,97,115,121,105,110,32,109,111,115,116,105,110,106,117,114,101,100,85,115,117 +,97,108,108,121,102,97,114,109,105,110,103,99,108,111,115,117,114,101,111,98,106 +,101,99,116,32,100,101,102,101,110,99,101,117,115,101,32,111,102,32,77,101,100, +105,99,97,108,60,98,111,100,121,62,10,101,118,105,100,101,110,116,98,101,32,117, +115,101,100,107,101,121,67,111,100,101,115,105,120,116,101,101,110,73,115,108,97 +,109,105,99,35,48,48,48,48,48,48,101,110,116,105,114,101,32,119,105,100,101,108, +121,32,97,99,116,105,118,101,32,40,116,121,112,101,111,102,111,110,101,32,99,97, +110,99,111,108,111,114,32,61,115,112,101,97,107,101,114,101,120,116,101,110,100, +115,80,104,121,115,105,99,115,116,101,114,114,97,105,110,60,116,98,111,100,121, +62,102,117,110,101,114,97,108,118,105,101,119,105,110,103,109,105,100,100,108, +101,32,99,114,105,99,107,101,116,112,114,111,112,104,101,116,115,104,105,102,116 +,101,100,100,111,99,116,111,114,115,82,117,115,115,101,108,108,32,116,97,114,103 +,101,116,99,111,109,112,97,99,116,97,108,103,101,98,114,97,115,111,99,105,97,108 +,45,98,117,108,107,32,111,102,109,97,110,32,97,110,100,60,47,116,100,62,10,32, +104,101,32,108,101,102,116,41,46,118,97,108,40,41,102,97,108,115,101,41,59,108, +111,103,105,99,97,108,98,97,110,107,105,110,103,104,111,109,101,32,116,111,110, +97,109,105,110,103,32,65,114,105,122,111,110,97,99,114,101,100,105,116,115,41,59 +,10,125,41,59,10,102,111,117,110,100,101,114,105,110,32,116,117,114,110,67,111, +108,108,105,110,115,98,101,102,111,114,101,32,66,117,116,32,116,104,101,99,104, +97,114,103,101,100,84,105,116,108,101,34,62,67,97,112,116,97,105,110,115,112,101 +,108,108,101,100,103,111,100,100,101,115,115,84,97,103,32,45,45,62,65,100,100, +105,110,103,58,98,117,116,32,119,97,115,82,101,99,101,110,116,32,112,97,116,105, +101,110,116,98,97,99,107,32,105,110,61,102,97,108,115,101,38,76,105,110,99,111, +108,110,119,101,32,107,110,111,119,67,111,117,110,116,101,114,74,117,100,97,105, +115,109,115,99,114,105,112,116,32,97,108,116,101,114,101,100,39,93,41,59,10,32, +32,104,97,115,32,116,104,101,117,110,99,108,101,97,114,69,118,101,110,116,39,44, +98,111,116,104,32,105,110,110,111,116,32,97,108,108,10,10,60,33,45,45,32,112,108 +,97,99,105,110,103,104,97,114,100,32,116,111,32,99,101,110,116,101,114,115,111, +114,116,32,111,102,99,108,105,101,110,116,115,115,116,114,101,101,116,115,66,101 +,114,110,97,114,100,97,115,115,101,114,116,115,116,101,110,100,32,116,111,102,97 +,110,116,97,115,121,100,111,119,110,32,105,110,104,97,114,98,111,117,114,70,114, +101,101,100,111,109,106,101,119,101,108,114,121,47,97,98,111,117,116,46,46,115, +101,97,114,99,104,108,101,103,101,110,100,115,105,115,32,109,97,100,101,109,111, +100,101,114,110,32,111,110,108,121,32,111,110,111,110,108,121,32,116,111,105,109 +,97,103,101,34,32,108,105,110,101,97,114,32,112,97,105,110,116,101,114,97,110, +100,32,110,111,116,114,97,114,101,108,121,32,97,99,114,111,110,121,109,100,101, +108,105,118,101,114,115,104,111,114,116,101,114,48,48,38,97,109,112,59,97,115,32 +,109,97,110,121,119,105,100,116,104,61,34,47,42,32,60,33,91,67,116,105,116,108, +101,32,61,111,102,32,116,104,101,32,108,111,119,101,115,116,32,112,105,99,107, +101,100,32,101,115,99,97,112,101,100,117,115,101,115,32,111,102,112,101,111,112, +108,101,115,32,80,117,98,108,105,99,77,97,116,116,104,101,119,116,97,99,116,105, +99,115,100,97,109,97,103,101,100,119,97,121,32,102,111,114,108,97,119,115,32,111 +,102,101,97,115,121,32,116,111,32,119,105,110,100,111,119,115,116,114,111,110, +103,32,32,115,105,109,112,108,101,125,99,97,116,99,104,40,115,101,118,101,110, +116,104,105,110,102,111,98,111,120,119,101,110,116,32,116,111,112,97,105,110,116 +,101,100,99,105,116,105,122,101,110,73,32,100,111,110,39,116,114,101,116,114,101 +,97,116,46,32,83,111,109,101,32,119,119,46,34,41,59,10,98,111,109,98,105,110,103 +,109,97,105,108,116,111,58,109,97,100,101,32,105,110,46,32,77,97,110,121,32,99, +97,114,114,105,101,115,124,124,123,125,59,119,105,119,111,114,107,32,111,102,115 +,121,110,111,110,121,109,100,101,102,101,97,116,115,102,97,118,111,114,101,100, +111,112,116,105,99,97,108,112,97,103,101,84,114,97,117,110,108,101,115,115,32, +115,101,110,100,105,110,103,108,101,102,116,34,62,60,99,111,109,83,99,111,114,65 +,108,108,32,116,104,101,106,81,117,101,114,121,46,116,111,117,114,105,115,116,67 +,108,97,115,115,105,99,102,97,108,115,101,34,32,87,105,108,104,101,108,109,115, +117,98,117,114,98,115,103,101,110,117,105,110,101,98,105,115,104,111,112,115,46, +115,112,108,105,116,40,103,108,111,98,97,108,32,102,111,108,108,111,119,115,98, +111,100,121,32,111,102,110,111,109,105,110,97,108,67,111,110,116,97,99,116,115, +101,99,117,108,97,114,108,101,102,116,32,116,111,99,104,105,101,102,108,121,45, +104,105,100,100,101,110,45,98,97,110,110,101,114,60,47,108,105,62,10,10,46,32,87 +,104,101,110,32,105,110,32,98,111,116,104,100,105,115,109,105,115,115,69,120,112 +,108,111,114,101,97,108,119,97,121,115,32,118,105,97,32,116,104,101,115,112,97, +195,177,111,108,119,101,108,102,97,114,101,114,117,108,105,110,103,32,97,114,114 +,97,110,103,101,99,97,112,116,97,105,110,104,105,115,32,115,111,110,114,117,108, +101,32,111,102,104,101,32,116,111,111,107,105,116,115,101,108,102,44,61,48,38,97 +,109,112,59,40,99,97,108,108,101,100,115,97,109,112,108,101,115,116,111,32,109, +97,107,101,99,111,109,47,112,97,103,77,97,114,116,105,110,32,75,101,110,110,101, +100,121,97,99,99,101,112,116,115,102,117,108,108,32,111,102,104,97,110,100,108, +101,100,66,101,115,105,100,101,115,47,47,45,45,62,60,47,97,98,108,101,32,116,111 +,116,97,114,103,101,116,115,101,115,115,101,110,99,101,104,105,109,32,116,111,32 +,105,116,115,32,98,121,32,99,111,109,109,111,110,46,109,105,110,101,114,97,108, +116,111,32,116,97,107,101,119,97,121,115,32,116,111,115,46,111,114,103,47,108,97 +,100,118,105,115,101,100,112,101,110,97,108,116,121,115,105,109,112,108,101,58, +105,102,32,116,104,101,121,76,101,116,116,101,114,115,97,32,115,104,111,114,116, +72,101,114,98,101,114,116,115,116,114,105,107,101,115,32,103,114,111,117,112,115 +,46,108,101,110,103,116,104,102,108,105,103,104,116,115,111,118,101,114,108,97, +112,115,108,111,119,108,121,32,108,101,115,115,101,114,32,115,111,99,105,97,108, +32,60,47,112,62,10,9,9,105,116,32,105,110,116,111,114,97,110,107,101,100,32,114, +97,116,101,32,111,102,117,108,62,13,10,32,32,97,116,116,101,109,112,116,112,97, +105,114,32,111,102,109,97,107,101,32,105,116,75,111,110,116,97,107,116,65,110, +116,111,110,105,111,104,97,118,105,110,103,32,114,97,116,105,110,103,115,32,97, +99,116,105,118,101,115,116,114,101,97,109,115,116,114,97,112,112,101,100,34,41, +46,99,115,115,40,104,111,115,116,105,108,101,108,101,97,100,32,116,111,108,105, +116,116,108,101,32,103,114,111,117,112,115,44,80,105,99,116,117,114,101,45,45,62 +,13,10,13,10,32,114,111,119,115,61,34,32,111,98,106,101,99,116,105,110,118,101, +114,115,101,60,102,111,111,116,101,114,67,117,115,116,111,109,86,62,60,92,47,115 +,99,114,115,111,108,118,105,110,103,67,104,97,109,98,101,114,115,108,97,118,101, +114,121,119,111,117,110,100,101,100,119,104,101,114,101,97,115,33,61,32,39,117, +110,100,102,111,114,32,97,108,108,112,97,114,116,108,121,32,45,114,105,103,104, +116,58,65,114,97,98,105,97,110,98,97,99,107,101,100,32,99,101,110,116,117,114, +121,117,110,105,116,32,111,102,109,111,98,105,108,101,45,69,117,114,111,112,101, +44,105,115,32,104,111,109,101,114,105,115,107,32,111,102,100,101,115,105,114,101 +,100,67,108,105,110,116,111,110,99,111,115,116,32,111,102,97,103,101,32,111,102, +32,98,101,99,111,109,101,32,110,111,110,101,32,111,102,112,38,113,117,111,116,59 +,77,105,100,100,108,101,32,101,97,100,39,41,91,48,67,114,105,116,105,99,115,115, +116,117,100,105,111,115,62,38,99,111,112,121,59,103,114,111,117,112,34,62,97,115 +,115,101,109,98,108,109,97,107,105,110,103,32,112,114,101,115,115,101,100,119, +105,100,103,101,116,46,112,115,58,34,32,63,32,114,101,98,117,105,108,116,98,121, +32,115,111,109,101,70,111,114,109,101,114,32,101,100,105,116,111,114,115,100,101 +,108,97,121,101,100,67,97,110,111,110,105,99,104,97,100,32,116,104,101,112,117, +115,104,105,110,103,99,108,97,115,115,61,34,98,117,116,32,97,114,101,112,97,114, +116,105,97,108,66,97,98,121,108,111,110,98,111,116,116,111,109,32,99,97,114,114, +105,101,114,67,111,109,109,97,110,100,105,116,115,32,117,115,101,65,115,32,119, +105,116,104,99,111,117,114,115,101,115,97,32,116,104,105,114,100,100,101,110,111 +,116,101,115,97,108,115,111,32,105,110,72,111,117,115,116,111,110,50,48,112,120, +59,34,62,97,99,99,117,115,101,100,100,111,117,98,108,101,32,103,111,97,108,32, +111,102,70,97,109,111,117,115,32,41,46,98,105,110,100,40,112,114,105,101,115,116 +,115,32,79,110,108,105,110,101,105,110,32,74,117,108,121,115,116,32,43,32,34,103 +,99,111,110,115,117,108,116,100,101,99,105,109,97,108,104,101,108,112,102,117, +108,114,101,118,105,118,101,100,105,115,32,118,101,114,121,114,39,43,39,105,112, +116,108,111,115,105,110,103,32,102,101,109,97,108,101,115,105,115,32,97,108,115, +111,115,116,114,105,110,103,115,100,97,121,115,32,111,102,97,114,114,105,118,97, +108,102,117,116,117,114,101,32,60,111,98,106,101,99,116,102,111,114,99,105,110, +103,83,116,114,105,110,103,40,34,32,47,62,10,9,9,104,101,114,101,32,105,115,101, +110,99,111,100,101,100,46,32,32,84,104,101,32,98,97,108,108,111,111,110,100,111, +110,101,32,98,121,47,99,111,109,109,111,110,98,103,99,111,108,111,114,108,97,119 +,32,111,102,32,73,110,100,105,97,110,97,97,118,111,105,100,101,100,98,117,116,32 +,116,104,101,50,112,120,32,51,112,120,106,113,117,101,114,121,46,97,102,116,101, +114,32,97,112,111,108,105,99,121,46,109,101,110,32,97,110,100,102,111,111,116, +101,114,45,61,32,116,114,117,101,59,102,111,114,32,117,115,101,115,99,114,101, +101,110,46,73,110,100,105,97,110,32,105,109,97,103,101,32,61,102,97,109,105,108, +121,44,104,116,116,112,58,47,47,32,38,110,98,115,112,59,100,114,105,118,101,114, +115,101,116,101,114,110,97,108,115,97,109,101,32,97,115,110,111,116,105,99,101, +100,118,105,101,119,101,114,115,125,41,40,41,59,10,32,105,115,32,109,111,114,101 +,115,101,97,115,111,110,115,102,111,114,109,101,114,32,116,104,101,32,110,101, +119,105,115,32,106,117,115,116,99,111,110,115,101,110,116,32,83,101,97,114,99, +104,119,97,115,32,116,104,101,119,104,121,32,116,104,101,115,104,105,112,112,101 +,100,98,114,62,60,98,114,62,119,105,100,116,104,58,32,104,101,105,103,104,116,61 +,109,97,100,101,32,111,102,99,117,105,115,105,110,101,105,115,32,116,104,97,116, +97,32,118,101,114,121,32,65,100,109,105,114,97,108,32,102,105,120,101,100,59,110 +,111,114,109,97,108,32,77,105,115,115,105,111,110,80,114,101,115,115,44,32,111, +110,116,97,114,105,111,99,104,97,114,115,101,116,116,114,121,32,116,111,32,105, +110,118,97,100,101,100,61,34,116,114,117,101,34,115,112,97,99,105,110,103,105, +115,32,109,111,115,116,97,32,109,111,114,101,32,116,111,116,97,108,108,121,102, +97,108,108,32,111,102,125,41,59,13,10,32,32,105,109,109,101,110,115,101,116,105, +109,101,32,105,110,115,101,116,32,111,117,116,115,97,116,105,115,102,121,116,111 +,32,102,105,110,100,100,111,119,110,32,116,111,108,111,116,32,111,102,32,80,108, +97,121,101,114,115,105,110,32,74,117,110,101,113,117,97,110,116,117,109,110,111, +116,32,116,104,101,116,105,109,101,32,116,111,100,105,115,116,97,110,116,70,105, +110,110,105,115,104,115,114,99,32,61,32,40,115,105,110,103,108,101,32,104,101, +108,112,32,111,102,71,101,114,109,97,110,32,108,97,119,32,97,110,100,108,97,98, +101,108,101,100,102,111,114,101,115,116,115,99,111,111,107,105,110,103,115,112, +97,99,101,34,62,104,101,97,100,101,114,45,119,101,108,108,32,97,115,83,116,97, +110,108,101,121,98,114,105,100,103,101,115,47,103,108,111,98,97,108,67,114,111, +97,116,105,97,32,65,98,111,117,116,32,91,48,93,59,10,32,32,105,116,44,32,97,110, +100,103,114,111,117,112,101,100,98,101,105,110,103,32,97,41,123,116,104,114,111, +119,104,101,32,109,97,100,101,108,105,103,104,116,101,114,101,116,104,105,99,97, +108,70,70,70,70,70,70,34,98,111,116,116,111,109,34,108,105,107,101,32,97,32,101, +109,112,108,111,121,115,108,105,118,101,32,105,110,97,115,32,115,101,101,110,112 +,114,105,110,116,101,114,109,111,115,116,32,111,102,117,98,45,108,105,110,107, +114,101,106,101,99,116,115,97,110,100,32,117,115,101,105,109,97,103,101,34,62, +115,117,99,99,101,101,100,102,101,101,100,105,110,103,78,117,99,108,101,97,114, +105,110,102,111,114,109,97,116,111,32,104,101,108,112,87,111,109,101,110,39,115, +78,101,105,116,104,101,114,77,101,120,105,99,97,110,112,114,111,116,101,105,110, +60,116,97,98,108,101,32,98,121,32,109,97,110,121,104,101,97,108,116,104,121,108, +97,119,115,117,105,116,100,101,118,105,115,101,100,46,112,117,115,104,40,123,115 +,101,108,108,101,114,115,115,105,109,112,108,121,32,84,104,114,111,117,103,104, +46,99,111,111,107,105,101,32,73,109,97,103,101,40,111,108,100,101,114,34,62,117, +115,46,106,115,34,62,32,83,105,110,99,101,32,117,110,105,118,101,114,115,108,97, +114,103,101,114,32,111,112,101,110,32,116,111,33,45,45,32,101,110,100,108,105, +101,115,32,105,110,39,93,41,59,13,10,32,32,109,97,114,107,101,116,119,104,111,32 +,105,115,32,40,34,68,79,77,67,111,109,97,110,97,103,101,100,111,110,101,32,102, +111,114,116,121,112,101,111,102,32,75,105,110,103,100,111,109,112,114,111,102, +105,116,115,112,114,111,112,111,115,101,116,111,32,115,104,111,119,99,101,110, +116,101,114,59,109,97,100,101,32,105,116,100,114,101,115,115,101,100,119,101,114 +,101,32,105,110,109,105,120,116,117,114,101,112,114,101,99,105,115,101,97,114, +105,115,105,110,103,115,114,99,32,61,32,39,109,97,107,101,32,97,32,115,101,99, +117,114,101,100,66,97,112,116,105,115,116,118,111,116,105,110,103,32,10,9,9,118, +97,114,32,77,97,114,99,104,32,50,103,114,101,119,32,117,112,67,108,105,109,97, +116,101,46,114,101,109,111,118,101,115,107,105,108,108,101,100,119,97,121,32,116 +,104,101,60,47,104,101,97,100,62,102,97,99,101,32,111,102,97,99,116,105,110,103, +32,114,105,103,104,116,34,62,116,111,32,119,111,114,107,114,101,100,117,99,101, +115,104,97,115,32,104,97,100,101,114,101,99,116,101,100,115,104,111,119,40,41,59 +,97,99,116,105,111,110,61,98,111,111,107,32,111,102,97,110,32,97,114,101,97,61, +61,32,34,104,116,116,60,104,101,97,100,101,114,10,60,104,116,109,108,62,99,111, +110,102,111,114,109,102,97,99,105,110,103,32,99,111,111,107,105,101,46,114,101, +108,121,32,111,110,104,111,115,116,101,100,32,46,99,117,115,116,111,109,104,101, +32,119,101,110,116,98,117,116,32,102,111,114,115,112,114,101,97,100,32,70,97,109 +,105,108,121,32,97,32,109,101,97,110,115,111,117,116,32,116,104,101,102,111,114, +117,109,115,46,102,111,111,116,97,103,101,34,62,77,111,98,105,108,67,108,101,109 +,101,110,116,115,34,32,105,100,61,34,97,115,32,104,105,103,104,105,110,116,101, +110,115,101,45,45,62,60,33,45,45,102,101,109,97,108,101,32,105,115,32,115,101, +101,110,105,109,112,108,105,101,100,115,101,116,32,116,104,101,97,32,115,116,97, +116,101,97,110,100,32,104,105,115,102,97,115,116,101,115,116,98,101,115,105,100, +101,115,98,117,116,116,111,110,95,98,111,117,110,100,101,100,34,62,60,105,109, +103,32,73,110,102,111,98,111,120,101,118,101,110,116,115,44,97,32,121,111,117, +110,103,97,110,100,32,97,114,101,78,97,116,105,118,101,32,99,104,101,97,112,101, +114,84,105,109,101,111,117,116,97,110,100,32,104,97,115,101,110,103,105,110,101, +115,119,111,110,32,116,104,101,40,109,111,115,116,108,121,114,105,103,104,116,58 +,32,102,105,110,100,32,97,32,45,98,111,116,116,111,109,80,114,105,110,99,101,32, +97,114,101,97,32,111,102,109,111,114,101,32,111,102,115,101,97,114,99,104,95,110 +,97,116,117,114,101,44,108,101,103,97,108,108,121,112,101,114,105,111,100,44,108 +,97,110,100,32,111,102,111,114,32,119,105,116,104,105,110,100,117,99,101,100,112 +,114,111,118,105,110,103,109,105,115,115,105,108,101,108,111,99,97,108,108,121, +65,103,97,105,110,115,116,116,104,101,32,119,97,121,107,38,113,117,111,116,59, +112,120,59,34,62,13,10,112,117,115,104,101,100,32,97,98,97,110,100,111,110,110, +117,109,101,114,97,108,67,101,114,116,97,105,110,73,110,32,116,104,105,115,109, +111,114,101,32,105,110,111,114,32,115,111,109,101,110,97,109,101,32,105,115,97, +110,100,44,32,105,110,99,114,111,119,110,101,100,73,83,66,78,32,48,45,99,114,101 +,97,116,101,115,79,99,116,111,98,101,114,109,97,121,32,110,111,116,99,101,110, +116,101,114,32,108,97,116,101,32,105,110,68,101,102,101,110,99,101,101,110,97,99 +,116,101,100,119,105,115,104,32,116,111,98,114,111,97,100,108,121,99,111,111,108 +,105,110,103,111,110,108,111,97,100,61,105,116,46,32,84,104,101,114,101,99,111, +118,101,114,77,101,109,98,101,114,115,104,101,105,103,104,116,32,97,115,115,117, +109,101,115,60,104,116,109,108,62,10,112,101,111,112,108,101,46,105,110,32,111, +110,101,32,61,119,105,110,100,111,119,102,111,111,116,101,114,95,97,32,103,111, +111,100,32,114,101,107,108,97,109,97,111,116,104,101,114,115,44,116,111,32,116, +104,105,115,95,99,111,111,107,105,101,112,97,110,101,108,34,62,76,111,110,100, +111,110,44,100,101,102,105,110,101,115,99,114,117,115,104,101,100,98,97,112,116, +105,115,109,99,111,97,115,116,97,108,115,116,97,116,117,115,32,116,105,116,108, +101,34,32,109,111,118,101,32,116,111,108,111,115,116,32,105,110,98,101,116,116, +101,114,32,105,109,112,108,105,101,115,114,105,118,97,108,114,121,115,101,114, +118,101,114,115,32,83,121,115,116,101,109,80,101,114,104,97,112,115,101,115,32, +97,110,100,32,99,111,110,116,101,110,100,102,108,111,119,105,110,103,108,97,115, +116,101,100,32,114,105,115,101,32,105,110,71,101,110,101,115,105,115,118,105,101 +,119,32,111,102,114,105,115,105,110,103,32,115,101,101,109,32,116,111,98,117,116 +,32,105,110,32,98,97,99,107,105,110,103,104,101,32,119,105,108,108,103,105,118, +101,110,32,97,103,105,118,105,110,103,32,99,105,116,105,101,115,46,102,108,111, +119,32,111,102,32,76,97,116,101,114,32,97,108,108,32,98,117,116,72,105,103,104, +119,97,121,111,110,108,121,32,98,121,115,105,103,110,32,111,102,104,101,32,100, +111,101,115,100,105,102,102,101,114,115,98,97,116,116,101,114,121,38,97,109,112, +59,108,97,115,105,110,103,108,101,115,116,104,114,101,97,116,115,105,110,116,101 +,103,101,114,116,97,107,101,32,111,110,114,101,102,117,115,101,100,99,97,108,108 +,101,100,32,61,85,83,38,97,109,112,83,101,101,32,116,104,101,110,97,116,105,118, +101,115,98,121,32,116,104,105,115,115,121,115,116,101,109,46,104,101,97,100,32, +111,102,58,104,111,118,101,114,44,108,101,115,98,105,97,110,115,117,114,110,97, +109,101,97,110,100,32,97,108,108,99,111,109,109,111,110,47,104,101,97,100,101, +114,95,95,112,97,114,97,109,115,72,97,114,118,97,114,100,47,112,105,120,101,108, +46,114,101,109,111,118,97,108,115,111,32,108,111,110,103,114,111,108,101,32,111, +102,106,111,105,110,116,108,121,115,107,121,115,99,114,97,85,110,105,99,111,100, +101,98,114,32,47,62,13,10,65,116,108,97,110,116,97,110,117,99,108,101,117,115,67 +,111,117,110,116,121,44,112,117,114,101,108,121,32,99,111,117,110,116,34,62,101, +97,115,105,108,121,32,98,117,105,108,100,32,97,111,110,99,108,105,99,107,97,32, +103,105,118,101,110,112,111,105,110,116,101,114,104,38,113,117,111,116,59,101, +118,101,110,116,115,32,101,108,115,101,32,123,10,100,105,116,105,111,110,115,110 +,111,119,32,116,104,101,44,32,119,105,116,104,32,109,97,110,32,119,104,111,111, +114,103,47,87,101,98,111,110,101,32,97,110,100,99,97,118,97,108,114,121,72,101, +32,100,105,101,100,115,101,97,116,116,108,101,48,48,44,48,48,48,32,123,119,105, +110,100,111,119,104,97,118,101,32,116,111,105,102,40,119,105,110,100,97,110,100, +32,105,116,115,115,111,108,101,108,121,32,109,38,113,117,111,116,59,114,101,110, +101,119,101,100,68,101,116,114,111,105,116,97,109,111,110,103,115,116,101,105, +116,104,101,114,32,116,104,101,109,32,105,110,83,101,110,97,116,111,114,85,115, +60,47,97,62,60,75,105,110,103,32,111,102,70,114,97,110,99,105,115,45,112,114,111 +,100,117,99,104,101,32,117,115,101,100,97,114,116,32,97,110,100,104,105,109,32, +97,110,100,117,115,101,100,32,98,121,115,99,111,114,105,110,103,97,116,32,104, +111,109,101,116,111,32,104,97,118,101,114,101,108,97,116,101,115,105,98,105,108, +105,116,121,102,97,99,116,105,111,110,66,117,102,102,97,108,111,108,105,110,107, +34,62,60,119,104,97,116,32,104,101,102,114,101,101,32,116,111,67,105,116,121,32, +111,102,99,111,109,101,32,105,110,115,101,99,116,111,114,115,99,111,117,110,116, +101,100,111,110,101,32,100,97,121,110,101,114,118,111,117,115,115,113,117,97,114 +,101,32,125,59,105,102,40,103,111,105,110,32,119,104,97,116,105,109,103,34,32,97 +,108,105,115,32,111,110,108,121,115,101,97,114,99,104,47,116,117,101,115,100,97, +121,108,111,111,115,101,108,121,83,111,108,111,109,111,110,115,101,120,117,97, +108,32,45,32,60,97,32,104,114,109,101,100,105,117,109,34,68,79,32,78,79,84,32,70 +,114,97,110,99,101,44,119,105,116,104,32,97,32,119,97,114,32,97,110,100,115,101, +99,111,110,100,32,116,97,107,101,32,97,32,62,13,10,13,10,13,10,109,97,114,107, +101,116,46,104,105,103,104,119,97,121,100,111,110,101,32,105,110,99,116,105,118, +105,116,121,34,108,97,115,116,34,62,111,98,108,105,103,101,100,114,105,115,101, +32,116,111,34,117,110,100,101,102,105,109,97,100,101,32,116,111,32,69,97,114,108 +,121,32,112,114,97,105,115,101,100,105,110,32,105,116,115,32,102,111,114,32,104, +105,115,97,116,104,108,101,116,101,74,117,112,105,116,101,114,89,97,104,111,111, +33,32,116,101,114,109,101,100,32,115,111,32,109,97,110,121,114,101,97,108,108, +121,32,115,46,32,84,104,101,32,97,32,119,111,109,97,110,63,118,97,108,117,101,61 +,100,105,114,101,99,116,32,114,105,103,104,116,34,32,98,105,99,121,99,108,101,97 +,99,105,110,103,61,34,100,97,121,32,97,110,100,115,116,97,116,105,110,103,82,97, +116,104,101,114,44,104,105,103,104,101,114,32,79,102,102,105,99,101,32,97,114, +101,32,110,111,119,116,105,109,101,115,44,32,119,104,101,110,32,97,32,112,97,121 +,32,102,111,114,111,110,32,116,104,105,115,45,108,105,110,107,34,62,59,98,111, +114,100,101,114,97,114,111,117,110,100,32,97,110,110,117,97,108,32,116,104,101, +32,78,101,119,112,117,116,32,116,104,101,46,99,111,109,34,32,116,97,107,105,110, +32,116,111,97,32,98,114,105,101,102,40,105,110,32,116,104,101,103,114,111,117, +112,115,46,59,32,119,105,100,116,104,101,110,122,121,109,101,115,115,105,109,112 +,108,101,32,105,110,32,108,97,116,101,123,114,101,116,117,114,110,116,104,101, +114,97,112,121,97,32,112,111,105,110,116,98,97,110,110,105,110,103,105,110,107, +115,34,62,10,40,41,59,34,32,114,101,97,32,112,108,97,99,101,92,117,48,48,51,67, +97,97,98,111,117,116,32,97,116,114,62,13,10,9,9,99,99,111,117,110,116,32,103,105 +,118,101,115,32,97,60,83,67,82,73,80,84,82,97,105,108,119,97,121,116,104,101,109 +,101,115,47,116,111,111,108,98,111,120,66,121,73,100,40,34,120,104,117,109,97, +110,115,44,119,97,116,99,104,101,115,105,110,32,115,111,109,101,32,105,102,32,40 +,119,105,99,111,109,105,110,103,32,102,111,114,109,97,116,115,32,85,110,100,101, +114,32,98,117,116,32,104,97,115,104,97,110,100,101,100,32,109,97,100,101,32,98, +121,116,104,97,110,32,105,110,102,101,97,114,32,111,102,100,101,110,111,116,101, +100,47,105,102,114,97,109,101,108,101,102,116,32,105,110,118,111,108,116,97,103, +101,105,110,32,101,97,99,104,97,38,113,117,111,116,59,98,97,115,101,32,111,102, +73,110,32,109,97,110,121,117,110,100,101,114,103,111,114,101,103,105,109,101,115 +,97,99,116,105,111,110,32,60,47,112,62,13,10,60,117,115,116,111,109,86,97,59,38, +103,116,59,60,47,105,109,112,111,114,116,115,111,114,32,116,104,97,116,109,111, +115,116,108,121,32,38,97,109,112,59,114,101,32,115,105,122,101,61,34,60,47,97,62 +,60,47,104,97,32,99,108,97,115,115,112,97,115,115,105,118,101,72,111,115,116,32, +61,32,87,104,101,116,104,101,114,102,101,114,116,105,108,101,86,97,114,105,111, +117,115,61,91,93,59,40,102,117,99,97,109,101,114,97,115,47,62,60,47,116,100,62, +97,99,116,115,32,97,115,73,110,32,115,111,109,101,62,13,10,13,10,60,33,111,114, +103,97,110,105,115,32,60,98,114,32,47,62,66,101,105,106,105,110,103,99,97,116,97 +,108,195,160,100,101,117,116,115,99,104,101,117,114,111,112,101,117,101,117,115, +107,97,114,97,103,97,101,105,108,103,101,115,118,101,110,115,107,97,101,115,112, +97,195,177,97,109,101,110,115,97,106,101,117,115,117,97,114,105,111,116,114,97, +98,97,106,111,109,195,169,120,105,99,111,112,195,161,103,105,110,97,115,105,101, +109,112,114,101,115,105,115,116,101,109,97,111,99,116,117,98,114,101,100,117,114 +,97,110,116,101,97,195,177,97,100,105,114,101,109,112,114,101,115,97,109,111,109 +,101,110,116,111,110,117,101,115,116,114,111,112,114,105,109,101,114,97,116,114, +97,118,195,169,115,103,114,97,99,105,97,115,110,117,101,115,116,114,97,112,114, +111,99,101,115,111,101,115,116,97,100,111,115,99,97,108,105,100,97,100,112,101, +114,115,111,110,97,110,195,186,109,101,114,111,97,99,117,101,114,100,111,109,195 +,186,115,105,99,97,109,105,101,109,98,114,111,111,102,101,114,116,97,115,97,108, +103,117,110,111,115,112,97,195,173,115,101,115,101,106,101,109,112,108,111,100, +101,114,101,99,104,111,97,100,101,109,195,161,115,112,114,105,118,97,100,111,97, +103,114,101,103,97,114,101,110,108,97,99,101,115,112,111,115,105,98,108,101,104, +111,116,101,108,101,115,115,101,118,105,108,108,97,112,114,105,109,101,114,111, +195,186,108,116,105,109,111,101,118,101,110,116,111,115,97,114,99,104,105,118, +111,99,117,108,116,117,114,97,109,117,106,101,114,101,115,101,110,116,114,97,100 +,97,97,110,117,110,99,105,111,101,109,98,97,114,103,111,109,101,114,99,97,100, +111,103,114,97,110,100,101,115,101,115,116,117,100,105,111,109,101,106,111,114, +101,115,102,101,98,114,101,114,111,100,105,115,101,195,177,111,116,117,114,105, +115,109,111,99,195,179,100,105,103,111,112,111,114,116,97,100,97,101,115,112,97, +99,105,111,102,97,109,105,108,105,97,97,110,116,111,110,105,111,112,101,114,109, +105,116,101,103,117,97,114,100,97,114,97,108,103,117,110,97,115,112,114,101,99, +105,111,115,97,108,103,117,105,101,110,115,101,110,116,105,100,111,118,105,115, +105,116,97,115,116,195,173,116,117,108,111,99,111,110,111,99,101,114,115,101,103 +,117,110,100,111,99,111,110,115,101,106,111,102,114,97,110,99,105,97,109,105,110 +,117,116,111,115,115,101,103,117,110,100,97,116,101,110,101,109,111,115,101,102, +101,99,116,111,115,109,195,161,108,97,103,97,115,101,115,105,195,179,110,114,101 +,118,105,115,116,97,103,114,97,110,97,100,97,99,111,109,112,114,97,114,105,110, +103,114,101,115,111,103,97,114,99,195,173,97,97,99,99,105,195,179,110,101,99,117 +,97,100,111,114,113,117,105,101,110,101,115,105,110,99,108,117,115,111,100,101, +98,101,114,195,161,109,97,116,101,114,105,97,104,111,109,98,114,101,115,109,117, +101,115,116,114,97,112,111,100,114,195,173,97,109,97,195,177,97,110,97,195,186, +108,116,105,109,97,101,115,116,97,109,111,115,111,102,105,99,105,97,108,116,97, +109,98,105,101,110,110,105,110,103,195,186,110,115,97,108,117,100,111,115,112, +111,100,101,109,111,115,109,101,106,111,114,97,114,112,111,115,105,116,105,111, +110,98,117,115,105,110,101,115,115,104,111,109,101,112,97,103,101,115,101,99,117 +,114,105,116,121,108,97,110,103,117,97,103,101,115,116,97,110,100,97,114,100,99, +97,109,112,97,105,103,110,102,101,97,116,117,114,101,115,99,97,116,101,103,111, +114,121,101,120,116,101,114,110,97,108,99,104,105,108,100,114,101,110,114,101, +115,101,114,118,101,100,114,101,115,101,97,114,99,104,101,120,99,104,97,110,103, +101,102,97,118,111,114,105,116,101,116,101,109,112,108,97,116,101,109,105,108, +105,116,97,114,121,105,110,100,117,115,116,114,121,115,101,114,118,105,99,101, +115,109,97,116,101,114,105,97,108,112,114,111,100,117,99,116,115,122,45,105,110, +100,101,120,58,99,111,109,109,101,110,116,115,115,111,102,116,119,97,114,101,99, +111,109,112,108,101,116,101,99,97,108,101,110,100,97,114,112,108,97,116,102,111, +114,109,97,114,116,105,99,108,101,115,114,101,113,117,105,114,101,100,109,111, +118,101,109,101,110,116,113,117,101,115,116,105,111,110,98,117,105,108,100,105, +110,103,112,111,108,105,116,105,99,115,112,111,115,115,105,98,108,101,114,101, +108,105,103,105,111,110,112,104,121,115,105,99,97,108,102,101,101,100,98,97,99, +107,114,101,103,105,115,116,101,114,112,105,99,116,117,114,101,115,100,105,115, +97,98,108,101,100,112,114,111,116,111,99,111,108,97,117,100,105,101,110,99,101, +115,101,116,116,105,110,103,115,97,99,116,105,118,105,116,121,101,108,101,109, +101,110,116,115,108,101,97,114,110,105,110,103,97,110,121,116,104,105,110,103,97 +,98,115,116,114,97,99,116,112,114,111,103,114,101,115,115,111,118,101,114,118, +105,101,119,109,97,103,97,122,105,110,101,101,99,111,110,111,109,105,99,116,114, +97,105,110,105,110,103,112,114,101,115,115,117,114,101,118,97,114,105,111,117, +115,32,60,115,116,114,111,110,103,62,112,114,111,112,101,114,116,121,115,104,111 +,112,112,105,110,103,116,111,103,101,116,104,101,114,97,100,118,97,110,99,101, +100,98,101,104,97,118,105,111,114,100,111,119,110,108,111,97,100,102,101,97,116, +117,114,101,100,102,111,111,116,98,97,108,108,115,101,108,101,99,116,101,100,76, +97,110,103,117,97,103,101,100,105,115,116,97,110,99,101,114,101,109,101,109,98, +101,114,116,114,97,99,107,105,110,103,112,97,115,115,119,111,114,100,109,111,100 +,105,102,105,101,100,115,116,117,100,101,110,116,115,100,105,114,101,99,116,108, +121,102,105,103,104,116,105,110,103,110,111,114,116,104,101,114,110,100,97,116, +97,98,97,115,101,102,101,115,116,105,118,97,108,98,114,101,97,107,105,110,103, +108,111,99,97,116,105,111,110,105,110,116,101,114,110,101,116,100,114,111,112, +100,111,119,110,112,114,97,99,116,105,99,101,101,118,105,100,101,110,99,101,102, +117,110,99,116,105,111,110,109,97,114,114,105,97,103,101,114,101,115,112,111,110 +,115,101,112,114,111,98,108,101,109,115,110,101,103,97,116,105,118,101,112,114, +111,103,114,97,109,115,97,110,97,108,121,115,105,115,114,101,108,101,97,115,101, +100,98,97,110,110,101,114,34,62,112,117,114,99,104,97,115,101,112,111,108,105,99 +,105,101,115,114,101,103,105,111,110,97,108,99,114,101,97,116,105,118,101,97,114 +,103,117,109,101,110,116,98,111,111,107,109,97,114,107,114,101,102,101,114,114, +101,114,99,104,101,109,105,99,97,108,100,105,118,105,115,105,111,110,99,97,108, +108,98,97,99,107,115,101,112,97,114,97,116,101,112,114,111,106,101,99,116,115,99 +,111,110,102,108,105,99,116,104,97,114,100,119,97,114,101,105,110,116,101,114, +101,115,116,100,101,108,105,118,101,114,121,109,111,117,110,116,97,105,110,111, +98,116,97,105,110,101,100,61,32,102,97,108,115,101,59,102,111,114,40,118,97,114, +32,97,99,99,101,112,116,101,100,99,97,112,97,99,105,116,121,99,111,109,112,117, +116,101,114,105,100,101,110,116,105,116,121,97,105,114,99,114,97,102,116,101,109 +,112,108,111,121,101,100,112,114,111,112,111,115,101,100,100,111,109,101,115,116 +,105,99,105,110,99,108,117,100,101,115,112,114,111,118,105,100,101,100,104,111, +115,112,105,116,97,108,118,101,114,116,105,99,97,108,99,111,108,108,97,112,115, +101,97,112,112,114,111,97,99,104,112,97,114,116,110,101,114,115,108,111,103,111, +34,62,60,97,100,97,117,103,104,116,101,114,97,117,116,104,111,114,34,32,99,117, +108,116,117,114,97,108,102,97,109,105,108,105,101,115,47,105,109,97,103,101,115, +47,97,115,115,101,109,98,108,121,112,111,119,101,114,102,117,108,116,101,97,99, +104,105,110,103,102,105,110,105,115,104,101,100,100,105,115,116,114,105,99,116, +99,114,105,116,105,99,97,108,99,103,105,45,98,105,110,47,112,117,114,112,111,115 +,101,115,114,101,113,117,105,114,101,115,101,108,101,99,116,105,111,110,98,101, +99,111,109,105,110,103,112,114,111,118,105,100,101,115,97,99,97,100,101,109,105, +99,101,120,101,114,99,105,115,101,97,99,116,117,97,108,108,121,109,101,100,105, +99,105,110,101,99,111,110,115,116,97,110,116,97,99,99,105,100,101,110,116,77,97, +103,97,122,105,110,101,100,111,99,117,109,101,110,116,115,116,97,114,116,105,110 +,103,98,111,116,116,111,109,34,62,111,98,115,101,114,118,101,100,58,32,38,113, +117,111,116,59,101,120,116,101,110,100,101,100,112,114,101,118,105,111,117,115, +83,111,102,116,119,97,114,101,99,117,115,116,111,109,101,114,100,101,99,105,115, +105,111,110,115,116,114,101,110,103,116,104,100,101,116,97,105,108,101,100,115, +108,105,103,104,116,108,121,112,108,97,110,110,105,110,103,116,101,120,116,97, +114,101,97,99,117,114,114,101,110,99,121,101,118,101,114,121,111,110,101,115,116 +,114,97,105,103,104,116,116,114,97,110,115,102,101,114,112,111,115,105,116,105, +118,101,112,114,111,100,117,99,101,100,104,101,114,105,116,97,103,101,115,104, +105,112,112,105,110,103,97,98,115,111,108,117,116,101,114,101,99,101,105,118,101 +,100,114,101,108,101,118,97,110,116,98,117,116,116,111,110,34,32,118,105,111,108 +,101,110,99,101,97,110,121,119,104,101,114,101,98,101,110,101,102,105,116,115, +108,97,117,110,99,104,101,100,114,101,99,101,110,116,108,121,97,108,108,105,97, +110,99,101,102,111,108,108,111,119,101,100,109,117,108,116,105,112,108,101,98, +117,108,108,101,116,105,110,105,110,99,108,117,100,101,100,111,99,99,117,114,114 +,101,100,105,110,116,101,114,110,97,108,36,40,116,104,105,115,41,46,114,101,112, +117,98,108,105,99,62,60,116,114,62,60,116,100,99,111,110,103,114,101,115,115,114 +,101,99,111,114,100,101,100,117,108,116,105,109,97,116,101,115,111,108,117,116, +105,111,110,60,117,108,32,105,100,61,34,100,105,115,99,111,118,101,114,72,111, +109,101,60,47,97,62,119,101,98,115,105,116,101,115,110,101,116,119,111,114,107, +115,97,108,116,104,111,117,103,104,101,110,116,105,114,101,108,121,109,101,109, +111,114,105,97,108,109,101,115,115,97,103,101,115,99,111,110,116,105,110,117,101 +,97,99,116,105,118,101,34,62,115,111,109,101,119,104,97,116,118,105,99,116,111, +114,105,97,87,101,115,116,101,114,110,32,32,116,105,116,108,101,61,34,76,111,99, +97,116,105,111,110,99,111,110,116,114,97,99,116,118,105,115,105,116,111,114,115, +68,111,119,110,108,111,97,100,119,105,116,104,111,117,116,32,114,105,103,104,116 +,34,62,10,109,101,97,115,117,114,101,115,119,105,100,116,104,32,61,32,118,97,114 +,105,97,98,108,101,105,110,118,111,108,118,101,100,118,105,114,103,105,110,105, +97,110,111,114,109,97,108,108,121,104,97,112,112,101,110,101,100,97,99,99,111, +117,110,116,115,115,116,97,110,100,105,110,103,110,97,116,105,111,110,97,108,82, +101,103,105,115,116,101,114,112,114,101,112,97,114,101,100,99,111,110,116,114, +111,108,115,97,99,99,117,114,97,116,101,98,105,114,116,104,100,97,121,115,116, +114,97,116,101,103,121,111,102,102,105,99,105,97,108,103,114,97,112,104,105,99, +115,99,114,105,109,105,110,97,108,112,111,115,115,105,98,108,121,99,111,110,115, +117,109,101,114,80,101,114,115,111,110,97,108,115,112,101,97,107,105,110,103,118 +,97,108,105,100,97,116,101,97,99,104,105,101,118,101,100,46,106,112,103,34,32,47 +,62,109,97,99,104,105,110,101,115,60,47,104,50,62,10,32,32,107,101,121,119,111, +114,100,115,102,114,105,101,110,100,108,121,98,114,111,116,104,101,114,115,99, +111,109,98,105,110,101,100,111,114,105,103,105,110,97,108,99,111,109,112,111,115 +,101,100,101,120,112,101,99,116,101,100,97,100,101,113,117,97,116,101,112,97,107 +,105,115,116,97,110,102,111,108,108,111,119,34,32,118,97,108,117,97,98,108,101, +60,47,108,97,98,101,108,62,114,101,108,97,116,105,118,101,98,114,105,110,103,105 +,110,103,105,110,99,114,101,97,115,101,103,111,118,101,114,110,111,114,112,108, +117,103,105,110,115,47,76,105,115,116,32,111,102,32,72,101,97,100,101,114,34,62, +34,32,110,97,109,101,61,34,32,40,38,113,117,111,116,59,103,114,97,100,117,97,116 +,101,60,47,104,101,97,100,62,10,99,111,109,109,101,114,99,101,109,97,108,97,121, +115,105,97,100,105,114,101,99,116,111,114,109,97,105,110,116,97,105,110,59,104, +101,105,103,104,116,58,115,99,104,101,100,117,108,101,99,104,97,110,103,105,110, +103,98,97,99,107,32,116,111,32,99,97,116,104,111,108,105,99,112,97,116,116,101, +114,110,115,99,111,108,111,114,58,32,35,103,114,101,97,116,101,115,116,115,117, +112,112,108,105,101,115,114,101,108,105,97,98,108,101,60,47,117,108,62,10,9,9,60 +,115,101,108,101,99,116,32,99,105,116,105,122,101,110,115,99,108,111,116,104,105 +,110,103,119,97,116,99,104,105,110,103,60,108,105,32,105,100,61,34,115,112,101, +99,105,102,105,99,99,97,114,114,121,105,110,103,115,101,110,116,101,110,99,101, +60,99,101,110,116,101,114,62,99,111,110,116,114,97,115,116,116,104,105,110,107, +105,110,103,99,97,116,99,104,40,101,41,115,111,117,116,104,101,114,110,77,105,99 +,104,97,101,108,32,109,101,114,99,104,97,110,116,99,97,114,111,117,115,101,108, +112,97,100,100,105,110,103,58,105,110,116,101,114,105,111,114,46,115,112,108,105 +,116,40,34,108,105,122,97,116,105,111,110,79,99,116,111,98,101,114,32,41,123,114 +,101,116,117,114,110,105,109,112,114,111,118,101,100,45,45,38,103,116,59,10,10, +99,111,118,101,114,97,103,101,99,104,97,105,114,109,97,110,46,112,110,103,34,32, +47,62,115,117,98,106,101,99,116,115,82,105,99,104,97,114,100,32,119,104,97,116, +101,118,101,114,112,114,111,98,97,98,108,121,114,101,99,111,118,101,114,121,98, +97,115,101,98,97,108,108,106,117,100,103,109,101,110,116,99,111,110,110,101,99, +116,46,46,99,115,115,34,32,47,62,32,119,101,98,115,105,116,101,114,101,112,111, +114,116,101,100,100,101,102,97,117,108,116,34,47,62,60,47,97,62,13,10,101,108, +101,99,116,114,105,99,115,99,111,116,108,97,110,100,99,114,101,97,116,105,111, +110,113,117,97,110,116,105,116,121,46,32,73,83,66,78,32,48,100,105,100,32,110, +111,116,32,105,110,115,116,97,110,99,101,45,115,101,97,114,99,104,45,34,32,108, +97,110,103,61,34,115,112,101,97,107,101,114,115,67,111,109,112,117,116,101,114, +99,111,110,116,97,105,110,115,97,114,99,104,105,118,101,115,109,105,110,105,115, +116,101,114,114,101,97,99,116,105,111,110,100,105,115,99,111,117,110,116,73,116, +97,108,105,97,110,111,99,114,105,116,101,114,105,97,115,116,114,111,110,103,108, +121,58,32,39,104,116,116,112,58,39,115,99,114,105,112,116,39,99,111,118,101,114, +105,110,103,111,102,102,101,114,105,110,103,97,112,112,101,97,114,101,100,66,114 +,105,116,105,115,104,32,105,100,101,110,116,105,102,121,70,97,99,101,98,111,111, +107,110,117,109,101,114,111,117,115,118,101,104,105,99,108,101,115,99,111,110,99 +,101,114,110,115,65,109,101,114,105,99,97,110,104,97,110,100,108,105,110,103,100 +,105,118,32,105,100,61,34,87,105,108,108,105,97,109,32,112,114,111,118,105,100, +101,114,95,99,111,110,116,101,110,116,97,99,99,117,114,97,99,121,115,101,99,116, +105,111,110,32,97,110,100,101,114,115,111,110,102,108,101,120,105,98,108,101,67, +97,116,101,103,111,114,121,108,97,119,114,101,110,99,101,60,115,99,114,105,112, +116,62,108,97,121,111,117,116,61,34,97,112,112,114,111,118,101,100,32,109,97,120 +,105,109,117,109,104,101,97,100,101,114,34,62,60,47,116,97,98,108,101,62,83,101, +114,118,105,99,101,115,104,97,109,105,108,116,111,110,99,117,114,114,101,110,116 +,32,99,97,110,97,100,105,97,110,99,104,97,110,110,101,108,115,47,116,104,101,109 +,101,115,47,47,97,114,116,105,99,108,101,111,112,116,105,111,110,97,108,112,111, +114,116,117,103,97,108,118,97,108,117,101,61,34,34,105,110,116,101,114,118,97, +108,119,105,114,101,108,101,115,115,101,110,116,105,116,108,101,100,97,103,101, +110,99,105,101,115,83,101,97,114,99,104,34,32,109,101,97,115,117,114,101,100,116 +,104,111,117,115,97,110,100,115,112,101,110,100,105,110,103,38,104,101,108,108, +105,112,59,110,101,119,32,68,97,116,101,34,32,115,105,122,101,61,34,112,97,103, +101,78,97,109,101,109,105,100,100,108,101,34,32,34,32,47,62,60,47,97,62,104,105, +100,100,101,110,34,62,115,101,113,117,101,110,99,101,112,101,114,115,111,110,97, +108,111,118,101,114,102,108,111,119,111,112,105,110,105,111,110,115,105,108,108, +105,110,111,105,115,108,105,110,107,115,34,62,10,9,60,116,105,116,108,101,62,118 +,101,114,115,105,111,110,115,115,97,116,117,114,100,97,121,116,101,114,109,105, +110,97,108,105,116,101,109,112,114,111,112,101,110,103,105,110,101,101,114,115, +101,99,116,105,111,110,115,100,101,115,105,103,110,101,114,112,114,111,112,111, +115,97,108,61,34,102,97,108,115,101,34,69,115,112,97,195,177,111,108,114,101,108 +,101,97,115,101,115,115,117,98,109,105,116,34,32,101,114,38,113,117,111,116,59, +97,100,100,105,116,105,111,110,115,121,109,112,116,111,109,115,111,114,105,101, +110,116,101,100,114,101,115,111,117,114,99,101,114,105,103,104,116,34,62,60,112, +108,101,97,115,117,114,101,115,116,97,116,105,111,110,115,104,105,115,116,111, +114,121,46,108,101,97,118,105,110,103,32,32,98,111,114,100,101,114,61,99,111,110 +,116,101,110,116,115,99,101,110,116,101,114,34,62,46,10,10,83,111,109,101,32,100 +,105,114,101,99,116,101,100,115,117,105,116,97,98,108,101,98,117,108,103,97,114, +105,97,46,115,104,111,119,40,41,59,100,101,115,105,103,110,101,100,71,101,110, +101,114,97,108,32,99,111,110,99,101,112,116,115,69,120,97,109,112,108,101,115, +119,105,108,108,105,97,109,115,79,114,105,103,105,110,97,108,34,62,60,115,112,97 +,110,62,115,101,97,114,99,104,34,62,111,112,101,114,97,116,111,114,114,101,113, +117,101,115,116,115,97,32,38,113,117,111,116,59,97,108,108,111,119,105,110,103, +68,111,99,117,109,101,110,116,114,101,118,105,115,105,111,110,46,32,10,10,84,104 +,101,32,121,111,117,114,115,101,108,102,67,111,110,116,97,99,116,32,109,105,99, +104,105,103,97,110,69,110,103,108,105,115,104,32,99,111,108,117,109,98,105,97, +112,114,105,111,114,105,116,121,112,114,105,110,116,105,110,103,100,114,105,110, +107,105,110,103,102,97,99,105,108,105,116,121,114,101,116,117,114,110,101,100,67 +,111,110,116,101,110,116,32,111,102,102,105,99,101,114,115,82,117,115,115,105,97 +,110,32,103,101,110,101,114,97,116,101,45,56,56,53,57,45,49,34,105,110,100,105, +99,97,116,101,102,97,109,105,108,105,97,114,32,113,117,97,108,105,116,121,109,97 +,114,103,105,110,58,48,32,99,111,110,116,101,110,116,118,105,101,119,112,111,114 +,116,99,111,110,116,97,99,116,115,45,116,105,116,108,101,34,62,112,111,114,116, +97,98,108,101,46,108,101,110,103,116,104,32,101,108,105,103,105,98,108,101,105, +110,118,111,108,118,101,115,97,116,108,97,110,116,105,99,111,110,108,111,97,100, +61,34,100,101,102,97,117,108,116,46,115,117,112,112,108,105,101,100,112,97,121, +109,101,110,116,115,103,108,111,115,115,97,114,121,10,10,65,102,116,101,114,32, +103,117,105,100,97,110,99,101,60,47,116,100,62,60,116,100,101,110,99,111,100,105 +,110,103,109,105,100,100,108,101,34,62,99,97,109,101,32,116,111,32,100,105,115, +112,108,97,121,115,115,99,111,116,116,105,115,104,106,111,110,97,116,104,97,110, +109,97,106,111,114,105,116,121,119,105,100,103,101,116,115,46,99,108,105,110,105 +,99,97,108,116,104,97,105,108,97,110,100,116,101,97,99,104,101,114,115,60,104, +101,97,100,62,10,9,97,102,102,101,99,116,101,100,115,117,112,112,111,114,116,115 +,112,111,105,110,116,101,114,59,116,111,83,116,114,105,110,103,60,47,115,109,97, +108,108,62,111,107,108,97,104,111,109,97,119,105,108,108,32,98,101,32,105,110, +118,101,115,116,111,114,48,34,32,97,108,116,61,34,104,111,108,105,100,97,121,115 +,82,101,115,111,117,114,99,101,108,105,99,101,110,115,101,100,32,40,119,104,105, +99,104,32,46,32,65,102,116,101,114,32,99,111,110,115,105,100,101,114,118,105,115 +,105,116,105,110,103,101,120,112,108,111,114,101,114,112,114,105,109,97,114,121, +32,115,101,97,114,99,104,34,32,97,110,100,114,111,105,100,34,113,117,105,99,107, +108,121,32,109,101,101,116,105,110,103,115,101,115,116,105,109,97,116,101,59,114 +,101,116,117,114,110,32,59,99,111,108,111,114,58,35,32,104,101,105,103,104,116, +61,97,112,112,114,111,118,97,108,44,32,38,113,117,111,116,59,32,99,104,101,99, +107,101,100,46,109,105,110,46,106,115,34,109,97,103,110,101,116,105,99,62,60,47, +97,62,60,47,104,102,111,114,101,99,97,115,116,46,32,87,104,105,108,101,32,116, +104,117,114,115,100,97,121,100,118,101,114,116,105,115,101,38,101,97,99,117,116, +101,59,104,97,115,67,108,97,115,115,101,118,97,108,117,97,116,101,111,114,100, +101,114,105,110,103,101,120,105,115,116,105,110,103,112,97,116,105,101,110,116, +115,32,79,110,108,105,110,101,32,99,111,108,111,114,97,100,111,79,112,116,105, +111,110,115,34,99,97,109,112,98,101,108,108,60,33,45,45,32,101,110,100,60,47,115 +,112,97,110,62,60,60,98,114,32,47,62,13,10,95,112,111,112,117,112,115,124,115,99 +,105,101,110,99,101,115,44,38,113,117,111,116,59,32,113,117,97,108,105,116,121, +32,87,105,110,100,111,119,115,32,97,115,115,105,103,110,101,100,104,101,105,103, +104,116,58,32,60,98,32,99,108,97,115,115,108,101,38,113,117,111,116,59,32,118,97 +,108,117,101,61,34,32,67,111,109,112,97,110,121,101,120,97,109,112,108,101,115, +60,105,102,114,97,109,101,32,98,101,108,105,101,118,101,115,112,114,101,115,101, +110,116,115,109,97,114,115,104,97,108,108,112,97,114,116,32,111,102,32,112,114, +111,112,101,114,108,121,41,46,10,10,84,104,101,32,116,97,120,111,110,111,109,121 +,109,117,99,104,32,111,102,32,60,47,115,112,97,110,62,10,34,32,100,97,116,97,45, +115,114,116,117,103,117,195,170,115,115,99,114,111,108,108,84,111,32,112,114,111 +,106,101,99,116,60,104,101,97,100,62,13,10,97,116,116,111,114,110,101,121,101, +109,112,104,97,115,105,115,115,112,111,110,115,111,114,115,102,97,110,99,121,98, +111,120,119,111,114,108,100,39,115,32,119,105,108,100,108,105,102,101,99,104,101 +,99,107,101,100,61,115,101,115,115,105,111,110,115,112,114,111,103,114,97,109, +109,112,120,59,102,111,110,116,45,32,80,114,111,106,101,99,116,106,111,117,114, +110,97,108,115,98,101,108,105,101,118,101,100,118,97,99,97,116,105,111,110,116, +104,111,109,112,115,111,110,108,105,103,104,116,105,110,103,97,110,100,32,116, +104,101,32,115,112,101,99,105,97,108,32,98,111,114,100,101,114,61,48,99,104,101, +99,107,105,110,103,60,47,116,98,111,100,121,62,60,98,117,116,116,111,110,32,67, +111,109,112,108,101,116,101,99,108,101,97,114,102,105,120,10,60,104,101,97,100, +62,10,97,114,116,105,99,108,101,32,60,115,101,99,116,105,111,110,102,105,110,100 +,105,110,103,115,114,111,108,101,32,105,110,32,112,111,112,117,108,97,114,32,32, +79,99,116,111,98,101,114,119,101,98,115,105,116,101,32,101,120,112,111,115,117, +114,101,117,115,101,100,32,116,111,32,32,99,104,97,110,103,101,115,111,112,101, +114,97,116,101,100,99,108,105,99,107,105,110,103,101,110,116,101,114,105,110,103 +,99,111,109,109,97,110,100,115,105,110,102,111,114,109,101,100,32,110,117,109,98 +,101,114,115,32,32,60,47,100,105,118,62,99,114,101,97,116,105,110,103,111,110,83 +,117,98,109,105,116,109,97,114,121,108,97,110,100,99,111,108,108,101,103,101,115 +,97,110,97,108,121,116,105,99,108,105,115,116,105,110,103,115,99,111,110,116,97, +99,116,46,108,111,103,103,101,100,73,110,97,100,118,105,115,111,114,121,115,105, +98,108,105,110,103,115,99,111,110,116,101,110,116,34,115,38,113,117,111,116,59, +41,115,46,32,84,104,105,115,32,112,97,99,107,97,103,101,115,99,104,101,99,107,98 +,111,120,115,117,103,103,101,115,116,115,112,114,101,103,110,97,110,116,116,111, +109,111,114,114,111,119,115,112,97,99,105,110,103,61,105,99,111,110,46,112,110, +103,106,97,112,97,110,101,115,101,99,111,100,101,98,97,115,101,98,117,116,116, +111,110,34,62,103,97,109,98,108,105,110,103,115,117,99,104,32,97,115,32,44,32, +119,104,105,108,101,32,60,47,115,112,97,110,62,32,109,105,115,115,111,117,114, +105,115,112,111,114,116,105,110,103,116,111,112,58,49,112,120,32,46,60,47,115, +112,97,110,62,116,101,110,115,105,111,110,115,119,105,100,116,104,61,34,50,108, +97,122,121,108,111,97,100,110,111,118,101,109,98,101,114,117,115,101,100,32,105, +110,32,104,101,105,103,104,116,61,34,99,114,105,112,116,34,62,10,38,110,98,115, +112,59,60,47,60,116,114,62,60,116,100,32,104,101,105,103,104,116,58,50,47,112, +114,111,100,117,99,116,99,111,117,110,116,114,121,32,105,110,99,108,117,100,101, +32,102,111,111,116,101,114,34,32,38,108,116,59,33,45,45,32,116,105,116,108,101, +34,62,60,47,106,113,117,101,114,121,46,60,47,102,111,114,109,62,10,40,231,174, +128,228,189,147,41,40,231,185,129,233,171,148,41,104,114,118,97,116,115,107,105, +105,116,97,108,105,97,110,111,114,111,109,195,162,110,196,131,116,195,188,114, +107,195,167,101,216,167,216,177,216,175,217,136,116,97,109,98,105,195,169,110, +110,111,116,105,99,105,97,115,109,101,110,115,97,106,101,115,112,101,114,115,111 +,110,97,115,100,101,114,101,99,104,111,115,110,97,99,105,111,110,97,108,115,101, +114,118,105,99,105,111,99,111,110,116,97,99,116,111,117,115,117,97,114,105,111, +115,112,114,111,103,114,97,109,97,103,111,98,105,101,114,110,111,101,109,112,114 +,101,115,97,115,97,110,117,110,99,105,111,115,118,97,108,101,110,99,105,97,99, +111,108,111,109,98,105,97,100,101,115,112,117,195,169,115,100,101,112,111,114, +116,101,115,112,114,111,121,101,99,116,111,112,114,111,100,117,99,116,111,112, +195,186,98,108,105,99,111,110,111,115,111,116,114,111,115,104,105,115,116,111, +114,105,97,112,114,101,115,101,110,116,101,109,105,108,108,111,110,101,115,109, +101,100,105,97,110,116,101,112,114,101,103,117,110,116,97,97,110,116,101,114,105 +,111,114,114,101,99,117,114,115,111,115,112,114,111,98,108,101,109,97,115,97,110 +,116,105,97,103,111,110,117,101,115,116,114,111,115,111,112,105,110,105,195,179, +110,105,109,112,114,105,109,105,114,109,105,101,110,116,114,97,115,97,109,195, +169,114,105,99,97,118,101,110,100,101,100,111,114,115,111,99,105,101,100,97,100, +114,101,115,112,101,99,116,111,114,101,97,108,105,122,97,114,114,101,103,105,115 +,116,114,111,112,97,108,97,98,114,97,115,105,110,116,101,114,195,169,115,101,110 +,116,111,110,99,101,115,101,115,112,101,99,105,97,108,109,105,101,109,98,114,111 +,115,114,101,97,108,105,100,97,100,99,195,179,114,100,111,98,97,122,97,114,97, +103,111,122,97,112,195,161,103,105,110,97,115,115,111,99,105,97,108,101,115,98, +108,111,113,117,101,97,114,103,101,115,116,105,195,179,110,97,108,113,117,105, +108,101,114,115,105,115,116,101,109,97,115,99,105,101,110,99,105,97,115,99,111, +109,112,108,101,116,111,118,101,114,115,105,195,179,110,99,111,109,112,108,101, +116,97,101,115,116,117,100,105,111,115,112,195,186,98,108,105,99,97,111,98,106, +101,116,105,118,111,97,108,105,99,97,110,116,101,98,117,115,99,97,100,111,114,99 +,97,110,116,105,100,97,100,101,110,116,114,97,100,97,115,97,99,99,105,111,110, +101,115,97,114,99,104,105,118,111,115,115,117,112,101,114,105,111,114,109,97,121 +,111,114,195,173,97,97,108,101,109,97,110,105,97,102,117,110,99,105,195,179,110, +195,186,108,116,105,109,111,115,104,97,99,105,101,110,100,111,97,113,117,101,108 +,108,111,115,101,100,105,99,105,195,179,110,102,101,114,110,97,110,100,111,97, +109,98,105,101,110,116,101,102,97,99,101,98,111,111,107,110,117,101,115,116,114, +97,115,99,108,105,101,110,116,101,115,112,114,111,99,101,115,111,115,98,97,115, +116,97,110,116,101,112,114,101,115,101,110,116,97,114,101,112,111,114,116,97,114 +,99,111,110,103,114,101,115,111,112,117,98,108,105,99,97,114,99,111,109,101,114, +99,105,111,99,111,110,116,114,97,116,111,106,195,179,118,101,110,101,115,100,105 +,115,116,114,105,116,111,116,195,169,99,110,105,99,97,99,111,110,106,117,110,116 +,111,101,110,101,114,103,195,173,97,116,114,97,98,97,106,97,114,97,115,116,117, +114,105,97,115,114,101,99,105,101,110,116,101,117,116,105,108,105,122,97,114,98, +111,108,101,116,195,173,110,115,97,108,118,97,100,111,114,99,111,114,114,101,99, +116,97,116,114,97,98,97,106,111,115,112,114,105,109,101,114,111,115,110,101,103, +111,99,105,111,115,108,105,98,101,114,116,97,100,100,101,116,97,108,108,101,115, +112,97,110,116,97,108,108,97,112,114,195,179,120,105,109,111,97,108,109,101,114, +195,173,97,97,110,105,109,97,108,101,115,113,117,105,195,169,110,101,115,99,111, +114,97,122,195,179,110,115,101,99,99,105,195,179,110,98,117,115,99,97,110,100, +111,111,112,99,105,111,110,101,115,101,120,116,101,114,105,111,114,99,111,110,99 +,101,112,116,111,116,111,100,97,118,195,173,97,103,97,108,101,114,195,173,97,101 +,115,99,114,105,98,105,114,109,101,100,105,99,105,110,97,108,105,99,101,110,99, +105,97,99,111,110,115,117,108,116,97,97,115,112,101,99,116,111,115,99,114,195, +173,116,105,99,97,100,195,179,108,97,114,101,115,106,117,115,116,105,99,105,97, +100,101,98,101,114,195,161,110,112,101,114,195,173,111,100,111,110,101,99,101, +115,105,116,97,109,97,110,116,101,110,101,114,112,101,113,117,101,195,177,111, +114,101,99,105,98,105,100,97,116,114,105,98,117,110,97,108,116,101,110,101,114, +105,102,101,99,97,110,99,105,195,179,110,99,97,110,97,114,105,97,115,100,101,115 +,99,97,114,103,97,100,105,118,101,114,115,111,115,109,97,108,108,111,114,99,97, +114,101,113,117,105,101,114,101,116,195,169,99,110,105,99,111,100,101,98,101,114 +,195,173,97,118,105,118,105,101,110,100,97,102,105,110,97,110,122,97,115,97,100, +101,108,97,110,116,101,102,117,110,99,105,111,110,97,99,111,110,115,101,106,111, +115,100,105,102,195,173,99,105,108,99,105,117,100,97,100,101,115,97,110,116,105, +103,117,97,115,97,118,97,110,122,97,100,97,116,195,169,114,109,105,110,111,117, +110,105,100,97,100,101,115,115,195,161,110,99,104,101,122,99,97,109,112,97,195, +177,97,115,111,102,116,111,110,105,99,114,101,118,105,115,116,97,115,99,111,110, +116,105,101,110,101,115,101,99,116,111,114,101,115,109,111,109,101,110,116,111, +115,102,97,99,117,108,116,97,100,99,114,195,169,100,105,116,111,100,105,118,101, +114,115,97,115,115,117,112,117,101,115,116,111,102,97,99,116,111,114,101,115,115 +,101,103,117,110,100,111,115,112,101,113,117,101,195,177,97,208,179,208,190,208, +180,208,176,208,181,209,129,208,187,208,184,208,181,209,129,209,130,209,140,208, +177,209,139,208,187,208,190,208,177,209,139,209,130,209,140,209,141,209,130,208, +190,208,188,208,149,209,129,208,187,208,184,209,130,208,190,208,179,208,190,208, +188,208,181,208,189,209,143,208,178,209,129,208,181,209,133,209,141,209,130,208, +190,208,185,208,180,208,176,208,182,208,181,208,177,209,139,208,187,208,184,208, +179,208,190,208,180,209,131,208,180,208,181,208,189,209,140,209,141,209,130,208, +190,209,130,208,177,209,139,208,187,208,176,209,129,208,181,208,177,209,143,208, +190,208,180,208,184,208,189,209,129,208,181,208,177,208,181,208,189,208,176,208, +180,208,190,209,129,208,176,208,185,209,130,209,132,208,190,209,130,208,190,208, +189,208,181,208,179,208,190,209,129,208,178,208,190,208,184,209,129,208,178,208, +190,208,185,208,184,208,179,209,128,209,139,209,130,208,190,208,182,208,181,208, +178,209,129,208,181,208,188,209,129,208,178,208,190,209,142,208,187,208,184,209, +136,209,140,209,141,209,130,208,184,209,133,208,191,208,190,208,186,208,176,208, +180,208,189,208,181,208,185,208,180,208,190,208,188,208,176,208,188,208,184,209, +128,208,176,208,187,208,184,208,177,208,190,209,130,208,181,208,188,209,131,209, +133,208,190,209,130,209,143,208,180,208,178,209,131,209,133,209,129,208,181,209, +130,208,184,208,187,209,142,208,180,208,184,208,180,208,181,208,187,208,190,208, +188,208,184,209,128,208,181,209,130,208,181,208,177,209,143,209,129,208,178,208, +190,208,181,208,178,208,184,208,180,208,181,209,135,208,181,208,179,208,190,209, +141,209,130,208,184,208,188,209,129,209,135,208,181,209,130,209,130,208,181,208, +188,209,139,209,134,208,181,208,189,209,139,209,129,209,130,208,176,208,187,208, +178,208,181,208,180,209,140,209,130,208,181,208,188,208,181,208,178,208,190,208, +180,209,139,209,130,208,181,208,177,208,181,208,178,209,139,209,136,208,181,208, +189,208,176,208,188,208,184,209,130,208,184,208,191,208,176,209,130,208,190,208, +188,209,131,208,191,209,128,208,176,208,178,208,187,208,184,209,134,208,176,208, +190,208,180,208,189,208,176,208,179,208,190,208,180,209,139,208,183,208,189,208, +176,209,142,208,188,208,190,208,179,209,131,208,180,209,128,209,131,208,179,208, +178,209,129,208,181,208,185,208,184,208,180,208,181,209,130,208,186,208,184,208, +189,208,190,208,190,208,180,208,189,208,190,208,180,208,181,208,187,208,176,208, +180,208,181,208,187,208,181,209,129,209,128,208,190,208,186,208,184,209,142,208, +189,209,143,208,178,208,181,209,129,209,140,208,149,209,129,209,130,209,140,209, +128,208,176,208,183,208,176,208,189,208,176,209,136,208,184,216,167,217,132,217, +132,217,135,216,167,217,132,216,170,217,138,216,172,217,133,217,138,216,185,216, +174,216,167,216,181,216,169,216,167,217,132,216,176,217,138,216,185,217,132,217, +138,217,135,216,172,216,175,217,138,216,175,216,167,217,132,216,162,217,134,216, +167,217,132,216,177,216,175,216,170,216,173,217,131,217,133,216,181,217,129,216, +173,216,169,217,131,216,167,217,134,216,170,216,167,217,132,217,132,217,138,217, +138,217,131,217,136,217,134,216,180,216,168,217,131,216,169,217,129,217,138,217, +135,216,167,216,168,217,134,216,167,216,170,216,173,217,136,216,167,216,161,216, +163,217,131,216,171,216,177,216,174,217,132,216,167,217,132,216,167,217,132,216, +173,216,168,216,175,217,132,217,138,217,132,216,175,216,177,217,136,216,179,216, +167,216,182,216,186,216,183,216,170,217,131,217,136,217,134,217,135,217,134,216, +167,217,131,216,179,216,167,216,173,216,169,217,134,216,167,216,175,217,138,216, +167,217,132,216,183,216,168,216,185,217,132,217,138,217,131,216,180,217,131,216, +177,216,167,217,138,217,133,217,131,217,134,217,133,217,134,217,135,216,167,216, +180,216,177,217,131,216,169,216,177,216,166,217,138,216,179,217,134,216,180,217, +138,216,183,217,133,216,167,216,176,216,167,216,167,217,132,217,129,217,134,216, +180,216,168,216,167,216,168,216,170,216,185,216,168,216,177,216,177,216,173,217, +133,216,169,217,131,216,167,217,129,216,169,217,138,217,130,217,136,217,132,217, +133,216,177,217,131,216,178,217,131,217,132,217,133,216,169,216,163,216,173,217, +133,216,175,217,130,217,132,216,168,217,138,217,138,216,185,217,134,217,138,216, +181,217,136,216,177,216,169,216,183,216,177,217,138,217,130,216,180,216,167,216, +177,217,131,216,172,217,136,216,167,217,132,216,163,216,174,216,177,217,137,217, +133,216,185,217,134,216,167,216,167,216,168,216,173,216,171,216,185,216,177,217, +136,216,182,216,168,216,180,217,131,217,132,217,133,216,179,216,172,217,132,216, +168,217,134,216,167,217,134,216,174,216,167,217,132,216,175,217,131,216,170,216, +167,216,168,217,131,217,132,217,138,216,169,216,168,216,175,217,136,217,134,216, +163,217,138,216,182,216,167,217,138,217,136,216,172,216,175,217,129,216,177,217, +138,217,130,217,131,216,170,216,168,216,170,216,163,217,129,216,182,217,132,217, +133,216,183,216,168,216,174,216,167,217,131,216,171,216,177,216,168,216,167,216, +177,217,131,216,167,217,129,216,182,217,132,216,167,216,173,217,132,217,137,217, +134,217,129,216,179,217,135,216,163,217,138,216,167,217,133,216,177,216,175,217, +136,216,175,216,163,217,134,217,135,216,167,216,175,217,138,217,134,216,167,216, +167,217,132,216,167,217,134,217,133,216,185,216,177,216,182,216,170,216,185,217, +132,217,133,216,175,216,167,216,174,217,132,217,133,217,133,217,131,217,134,0,0, +0,0,0,0,0,0,1,0,1,0,1,0,1,0,2,0,2,0,2,0,2,0,4,0,4,0,4,0,4,0,0,1,2,3,4,5,6,7,7,6, +5,4,3,2,1,0,8,9,10,11,12,13,14,15,15,14,13,12,11,10,9,8,16,17,18,19,20,21,22,23, +23,22,21,20,19,18,17,16,24,25,26,27,28,29,30,31,31,30,29,28,27,26,25,24,255,255, +255,255,0,0,0,0,0,0,0,0,255,255,255,255,1,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,1,0,0,0, +3,0,0,0,255,255,0,1,0,0,0,1,0,0,255,255,0,1,0,0,0,8,0,8,0,8,0,8,0,0,0,1,0,2,0,3, +0,4,0,5,0,6,0,7,114,101,115,111,117,114,99,101,115,99,111,117,110,116,114,105, +101,115,113,117,101,115,116,105,111,110,115,101,113,117,105,112,109,101,110,116, +99,111,109,109,117,110,105,116,121,97,118,97,105,108,97,98,108,101,104,105,103, +104,108,105,103,104,116,68,84,68,47,120,104,116,109,108,109,97,114,107,101,116, +105,110,103,107,110,111,119,108,101,100,103,101,115,111,109,101,116,104,105,110, +103,99,111,110,116,97,105,110,101,114,100,105,114,101,99,116,105,111,110,115,117 +,98,115,99,114,105,98,101,97,100,118,101,114,116,105,115,101,99,104,97,114,97,99 +,116,101,114,34,32,118,97,108,117,101,61,34,60,47,115,101,108,101,99,116,62,65, +117,115,116,114,97,108,105,97,34,32,99,108,97,115,115,61,34,115,105,116,117,97, +116,105,111,110,97,117,116,104,111,114,105,116,121,102,111,108,108,111,119,105, +110,103,112,114,105,109,97,114,105,108,121,111,112,101,114,97,116,105,111,110,99 +,104,97,108,108,101,110,103,101,100,101,118,101,108,111,112,101,100,97,110,111, +110,121,109,111,117,115,102,117,110,99,116,105,111,110,32,102,117,110,99,116,105 +,111,110,115,99,111,109,112,97,110,105,101,115,115,116,114,117,99,116,117,114, +101,97,103,114,101,101,109,101,110,116,34,32,116,105,116,108,101,61,34,112,111, +116,101,110,116,105,97,108,101,100,117,99,97,116,105,111,110,97,114,103,117,109, +101,110,116,115,115,101,99,111,110,100,97,114,121,99,111,112,121,114,105,103,104 +,116,108,97,110,103,117,97,103,101,115,101,120,99,108,117,115,105,118,101,99,111 +,110,100,105,116,105,111,110,60,47,102,111,114,109,62,13,10,115,116,97,116,101, +109,101,110,116,97,116,116,101,110,116,105,111,110,66,105,111,103,114,97,112,104 +,121,125,32,101,108,115,101,32,123,10,115,111,108,117,116,105,111,110,115,119, +104,101,110,32,116,104,101,32,65,110,97,108,121,116,105,99,115,116,101,109,112, +108,97,116,101,115,100,97,110,103,101,114,111,117,115,115,97,116,101,108,108,105 +,116,101,100,111,99,117,109,101,110,116,115,112,117,98,108,105,115,104,101,114, +105,109,112,111,114,116,97,110,116,112,114,111,116,111,116,121,112,101,105,110, +102,108,117,101,110,99,101,38,114,97,113,117,111,59,60,47,101,102,102,101,99,116 +,105,118,101,103,101,110,101,114,97,108,108,121,116,114,97,110,115,102,111,114, +109,98,101,97,117,116,105,102,117,108,116,114,97,110,115,112,111,114,116,111,114 +,103,97,110,105,122,101,100,112,117,98,108,105,115,104,101,100,112,114,111,109, +105,110,101,110,116,117,110,116,105,108,32,116,104,101,116,104,117,109,98,110,97 +,105,108,78,97,116,105,111,110,97,108,32,46,102,111,99,117,115,40,41,59,111,118, +101,114,32,116,104,101,32,109,105,103,114,97,116,105,111,110,97,110,110,111,117, +110,99,101,100,102,111,111,116,101,114,34,62,10,101,120,99,101,112,116,105,111, +110,108,101,115,115,32,116,104,97,110,101,120,112,101,110,115,105,118,101,102, +111,114,109,97,116,105,111,110,102,114,97,109,101,119,111,114,107,116,101,114, +114,105,116,111,114,121,110,100,105,99,97,116,105,111,110,99,117,114,114,101,110 +,116,108,121,99,108,97,115,115,78,97,109,101,99,114,105,116,105,99,105,115,109, +116,114,97,100,105,116,105,111,110,101,108,115,101,119,104,101,114,101,65,108, +101,120,97,110,100,101,114,97,112,112,111,105,110,116,101,100,109,97,116,101,114 +,105,97,108,115,98,114,111,97,100,99,97,115,116,109,101,110,116,105,111,110,101, +100,97,102,102,105,108,105,97,116,101,60,47,111,112,116,105,111,110,62,116,114, +101,97,116,109,101,110,116,100,105,102,102,101,114,101,110,116,47,100,101,102,97 +,117,108,116,46,80,114,101,115,105,100,101,110,116,111,110,99,108,105,99,107,61, +34,98,105,111,103,114,97,112,104,121,111,116,104,101,114,119,105,115,101,112,101 +,114,109,97,110,101,110,116,70,114,97,110,195,167,97,105,115,72,111,108,108,121, +119,111,111,100,101,120,112,97,110,115,105,111,110,115,116,97,110,100,97,114,100 +,115,60,47,115,116,121,108,101,62,10,114,101,100,117,99,116,105,111,110,68,101, +99,101,109,98,101,114,32,112,114,101,102,101,114,114,101,100,67,97,109,98,114, +105,100,103,101,111,112,112,111,110,101,110,116,115,66,117,115,105,110,101,115, +115,32,99,111,110,102,117,115,105,111,110,62,10,60,116,105,116,108,101,62,112, +114,101,115,101,110,116,101,100,101,120,112,108,97,105,110,101,100,100,111,101, +115,32,110,111,116,32,119,111,114,108,100,119,105,100,101,105,110,116,101,114, +102,97,99,101,112,111,115,105,116,105,111,110,115,110,101,119,115,112,97,112,101 +,114,60,47,116,97,98,108,101,62,10,109,111,117,110,116,97,105,110,115,108,105, +107,101,32,116,104,101,32,101,115,115,101,110,116,105,97,108,102,105,110,97,110, +99,105,97,108,115,101,108,101,99,116,105,111,110,97,99,116,105,111,110,61,34,47, +97,98,97,110,100,111,110,101,100,69,100,117,99,97,116,105,111,110,112,97,114,115 +,101,73,110,116,40,115,116,97,98,105,108,105,116,121,117,110,97,98,108,101,32, +116,111,60,47,116,105,116,108,101,62,10,114,101,108,97,116,105,111,110,115,78, +111,116,101,32,116,104,97,116,101,102,102,105,99,105,101,110,116,112,101,114,102 +,111,114,109,101,100,116,119,111,32,121,101,97,114,115,83,105,110,99,101,32,116, +104,101,116,104,101,114,101,102,111,114,101,119,114,97,112,112,101,114,34,62,97, +108,116,101,114,110,97,116,101,105,110,99,114,101,97,115,101,100,66,97,116,116, +108,101,32,111,102,112,101,114,99,101,105,118,101,100,116,114,121,105,110,103,32 +,116,111,110,101,99,101,115,115,97,114,121,112,111,114,116,114,97,121,101,100, +101,108,101,99,116,105,111,110,115,69,108,105,122,97,98,101,116,104,60,47,105, +102,114,97,109,101,62,100,105,115,99,111,118,101,114,121,105,110,115,117,114,97, +110,99,101,115,46,108,101,110,103,116,104,59,108,101,103,101,110,100,97,114,121, +71,101,111,103,114,97,112,104,121,99,97,110,100,105,100,97,116,101,99,111,114, +112,111,114,97,116,101,115,111,109,101,116,105,109,101,115,115,101,114,118,105, +99,101,115,46,105,110,104,101,114,105,116,101,100,60,47,115,116,114,111,110,103, +62,67,111,109,109,117,110,105,116,121,114,101,108,105,103,105,111,117,115,108, +111,99,97,116,105,111,110,115,67,111,109,109,105,116,116,101,101,98,117,105,108, +100,105,110,103,115,116,104,101,32,119,111,114,108,100,110,111,32,108,111,110, +103,101,114,98,101,103,105,110,110,105,110,103,114,101,102,101,114,101,110,99, +101,99,97,110,110,111,116,32,98,101,102,114,101,113,117,101,110,99,121,116,121, +112,105,99,97,108,108,121,105,110,116,111,32,116,104,101,32,114,101,108,97,116, +105,118,101,59,114,101,99,111,114,100,105,110,103,112,114,101,115,105,100,101, +110,116,105,110,105,116,105,97,108,108,121,116,101,99,104,110,105,113,117,101, +116,104,101,32,111,116,104,101,114,105,116,32,99,97,110,32,98,101,101,120,105, +115,116,101,110,99,101,117,110,100,101,114,108,105,110,101,116,104,105,115,32, +116,105,109,101,116,101,108,101,112,104,111,110,101,105,116,101,109,115,99,111, +112,101,112,114,97,99,116,105,99,101,115,97,100,118,97,110,116,97,103,101,41,59, +114,101,116,117,114,110,32,70,111,114,32,111,116,104,101,114,112,114,111,118,105 +,100,105,110,103,100,101,109,111,99,114,97,99,121,98,111,116,104,32,116,104,101, +32,101,120,116,101,110,115,105,118,101,115,117,102,102,101,114,105,110,103,115, +117,112,112,111,114,116,101,100,99,111,109,112,117,116,101,114,115,32,102,117, +110,99,116,105,111,110,112,114,97,99,116,105,99,97,108,115,97,105,100,32,116,104 +,97,116,105,116,32,109,97,121,32,98,101,69,110,103,108,105,115,104,60,47,102,114 +,111,109,32,116,104,101,32,115,99,104,101,100,117,108,101,100,100,111,119,110, +108,111,97,100,115,60,47,108,97,98,101,108,62,10,115,117,115,112,101,99,116,101, +100,109,97,114,103,105,110,58,32,48,115,112,105,114,105,116,117,97,108,60,47,104 +,101,97,100,62,10,10,109,105,99,114,111,115,111,102,116,103,114,97,100,117,97, +108,108,121,100,105,115,99,117,115,115,101,100,104,101,32,98,101,99,97,109,101, +101,120,101,99,117,116,105,118,101,106,113,117,101,114,121,46,106,115,104,111, +117,115,101,104,111,108,100,99,111,110,102,105,114,109,101,100,112,117,114,99, +104,97,115,101,100,108,105,116,101,114,97,108,108,121,100,101,115,116,114,111, +121,101,100,117,112,32,116,111,32,116,104,101,118,97,114,105,97,116,105,111,110, +114,101,109,97,105,110,105,110,103,105,116,32,105,115,32,110,111,116,99,101,110, +116,117,114,105,101,115,74,97,112,97,110,101,115,101,32,97,109,111,110,103,32, +116,104,101,99,111,109,112,108,101,116,101,100,97,108,103,111,114,105,116,104, +109,105,110,116,101,114,101,115,116,115,114,101,98,101,108,108,105,111,110,117, +110,100,101,102,105,110,101,100,101,110,99,111,117,114,97,103,101,114,101,115, +105,122,97,98,108,101,105,110,118,111,108,118,105,110,103,115,101,110,115,105, +116,105,118,101,117,110,105,118,101,114,115,97,108,112,114,111,118,105,115,105, +111,110,40,97,108,116,104,111,117,103,104,102,101,97,116,117,114,105,110,103,99, +111,110,100,117,99,116,101,100,41,44,32,119,104,105,99,104,32,99,111,110,116,105 +,110,117,101,100,45,104,101,97,100,101,114,34,62,70,101,98,114,117,97,114,121,32 +,110,117,109,101,114,111,117,115,32,111,118,101,114,102,108,111,119,58,99,111, +109,112,111,110,101,110,116,102,114,97,103,109,101,110,116,115,101,120,99,101, +108,108,101,110,116,99,111,108,115,112,97,110,61,34,116,101,99,104,110,105,99,97 +,108,110,101,97,114,32,116,104,101,32,65,100,118,97,110,99,101,100,32,115,111, +117,114,99,101,32,111,102,101,120,112,114,101,115,115,101,100,72,111,110,103,32, +75,111,110,103,32,70,97,99,101,98,111,111,107,109,117,108,116,105,112,108,101,32 +,109,101,99,104,97,110,105,115,109,101,108,101,118,97,116,105,111,110,111,102, +102,101,110,115,105,118,101,60,47,102,111,114,109,62,10,9,115,112,111,110,115, +111,114,101,100,100,111,99,117,109,101,110,116,46,111,114,32,38,113,117,111,116, +59,116,104,101,114,101,32,97,114,101,116,104,111,115,101,32,119,104,111,109,111, +118,101,109,101,110,116,115,112,114,111,99,101,115,115,101,115,100,105,102,102, +105,99,117,108,116,115,117,98,109,105,116,116,101,100,114,101,99,111,109,109,101 +,110,100,99,111,110,118,105,110,99,101,100,112,114,111,109,111,116,105,110,103, +34,32,119,105,100,116,104,61,34,46,114,101,112,108,97,99,101,40,99,108,97,115, +115,105,99,97,108,99,111,97,108,105,116,105,111,110,104,105,115,32,102,105,114, +115,116,100,101,99,105,115,105,111,110,115,97,115,115,105,115,116,97,110,116,105 +,110,100,105,99,97,116,101,100,101,118,111,108,117,116,105,111,110,45,119,114,97 +,112,112,101,114,34,101,110,111,117,103,104,32,116,111,97,108,111,110,103,32,116 +,104,101,100,101,108,105,118,101,114,101,100,45,45,62,13,10,60,33,45,45,65,109, +101,114,105,99,97,110,32,112,114,111,116,101,99,116,101,100,78,111,118,101,109, +98,101,114,32,60,47,115,116,121,108,101,62,60,102,117,114,110,105,116,117,114, +101,73,110,116,101,114,110,101,116,32,32,111,110,98,108,117,114,61,34,115,117, +115,112,101,110,100,101,100,114,101,99,105,112,105,101,110,116,98,97,115,101,100 +,32,111,110,32,77,111,114,101,111,118,101,114,44,97,98,111,108,105,115,104,101, +100,99,111,108,108,101,99,116,101,100,119,101,114,101,32,109,97,100,101,101,109, +111,116,105,111,110,97,108,101,109,101,114,103,101,110,99,121,110,97,114,114,97, +116,105,118,101,97,100,118,111,99,97,116,101,115,112,120,59,98,111,114,100,101, +114,99,111,109,109,105,116,116,101,100,100,105,114,61,34,108,116,114,34,101,109, +112,108,111,121,101,101,115,114,101,115,101,97,114,99,104,46,32,115,101,108,101, +99,116,101,100,115,117,99,99,101,115,115,111,114,99,117,115,116,111,109,101,114, +115,100,105,115,112,108,97,121,101,100,83,101,112,116,101,109,98,101,114,97,100, +100,67,108,97,115,115,40,70,97,99,101,98,111,111,107,32,115,117,103,103,101,115, +116,101,100,97,110,100,32,108,97,116,101,114,111,112,101,114,97,116,105,110,103, +101,108,97,98,111,114,97,116,101,83,111,109,101,116,105,109,101,115,73,110,115, +116,105,116,117,116,101,99,101,114,116,97,105,110,108,121,105,110,115,116,97,108 +,108,101,100,102,111,108,108,111,119,101,114,115,74,101,114,117,115,97,108,101, +109,116,104,101,121,32,104,97,118,101,99,111,109,112,117,116,105,110,103,103,101 +,110,101,114,97,116,101,100,112,114,111,118,105,110,99,101,115,103,117,97,114,97 +,110,116,101,101,97,114,98,105,116,114,97,114,121,114,101,99,111,103,110,105,122 +,101,119,97,110,116,101,100,32,116,111,112,120,59,119,105,100,116,104,58,116,104 +,101,111,114,121,32,111,102,98,101,104,97,118,105,111,117,114,87,104,105,108,101 +,32,116,104,101,101,115,116,105,109,97,116,101,100,98,101,103,97,110,32,116,111, +32,105,116,32,98,101,99,97,109,101,109,97,103,110,105,116,117,100,101,109,117, +115,116,32,104,97,118,101,109,111,114,101,32,116,104,97,110,68,105,114,101,99, +116,111,114,121,101,120,116,101,110,115,105,111,110,115,101,99,114,101,116,97, +114,121,110,97,116,117,114,97,108,108,121,111,99,99,117,114,114,105,110,103,118, +97,114,105,97,98,108,101,115,103,105,118,101,110,32,116,104,101,112,108,97,116, +102,111,114,109,46,60,47,108,97,98,101,108,62,60,102,97,105,108,101,100,32,116, +111,99,111,109,112,111,117,110,100,115,107,105,110,100,115,32,111,102,32,115,111 +,99,105,101,116,105,101,115,97,108,111,110,103,115,105,100,101,32,45,45,38,103, +116,59,10,10,115,111,117,116,104,119,101,115,116,116,104,101,32,114,105,103,104, +116,114,97,100,105,97,116,105,111,110,109,97,121,32,104,97,118,101,32,117,110, +101,115,99,97,112,101,40,115,112,111,107,101,110,32,105,110,34,32,104,114,101, +102,61,34,47,112,114,111,103,114,97,109,109,101,111,110,108,121,32,116,104,101, +32,99,111,109,101,32,102,114,111,109,100,105,114,101,99,116,111,114,121,98,117, +114,105,101,100,32,105,110,97,32,115,105,109,105,108,97,114,116,104,101,121,32, +119,101,114,101,60,47,102,111,110,116,62,60,47,78,111,114,119,101,103,105,97,110 +,115,112,101,99,105,102,105,101,100,112,114,111,100,117,99,105,110,103,112,97, +115,115,101,110,103,101,114,40,110,101,119,32,68,97,116,101,116,101,109,112,111, +114,97,114,121,102,105,99,116,105,111,110,97,108,65,102,116,101,114,32,116,104, +101,101,113,117,97,116,105,111,110,115,100,111,119,110,108,111,97,100,46,114,101 +,103,117,108,97,114,108,121,100,101,118,101,108,111,112,101,114,97,98,111,118, +101,32,116,104,101,108,105,110,107,101,100,32,116,111,112,104,101,110,111,109, +101,110,97,112,101,114,105,111,100,32,111,102,116,111,111,108,116,105,112,34,62, +115,117,98,115,116,97,110,99,101,97,117,116,111,109,97,116,105,99,97,115,112,101 +,99,116,32,111,102,65,109,111,110,103,32,116,104,101,99,111,110,110,101,99,116, +101,100,101,115,116,105,109,97,116,101,115,65,105,114,32,70,111,114,99,101,115, +121,115,116,101,109,32,111,102,111,98,106,101,99,116,105,118,101,105,109,109,101 +,100,105,97,116,101,109,97,107,105,110,103,32,105,116,112,97,105,110,116,105,110 +,103,115,99,111,110,113,117,101,114,101,100,97,114,101,32,115,116,105,108,108, +112,114,111,99,101,100,117,114,101,103,114,111,119,116,104,32,111,102,104,101,97 +,100,101,100,32,98,121,69,117,114,111,112,101,97,110,32,100,105,118,105,115,105, +111,110,115,109,111,108,101,99,117,108,101,115,102,114,97,110,99,104,105,115,101 +,105,110,116,101,110,116,105,111,110,97,116,116,114,97,99,116,101,100,99,104,105 +,108,100,104,111,111,100,97,108,115,111,32,117,115,101,100,100,101,100,105,99,97 +,116,101,100,115,105,110,103,97,112,111,114,101,100,101,103,114,101,101,32,111, +102,102,97,116,104,101,114,32,111,102,99,111,110,102,108,105,99,116,115,60,47,97 +,62,60,47,112,62,10,99,97,109,101,32,102,114,111,109,119,101,114,101,32,117,115, +101,100,110,111,116,101,32,116,104,97,116,114,101,99,101,105,118,105,110,103,69, +120,101,99,117,116,105,118,101,101,118,101,110,32,109,111,114,101,97,99,99,101, +115,115,32,116,111,99,111,109,109,97,110,100,101,114,80,111,108,105,116,105,99, +97,108,109,117,115,105,99,105,97,110,115,100,101,108,105,99,105,111,117,115,112, +114,105,115,111,110,101,114,115,97,100,118,101,110,116,32,111,102,85,84,70,45,56 +,34,32,47,62,60,33,91,67,68,65,84,65,91,34,62,67,111,110,116,97,99,116,83,111, +117,116,104,101,114,110,32,98,103,99,111,108,111,114,61,34,115,101,114,105,101, +115,32,111,102,46,32,73,116,32,119,97,115,32,105,110,32,69,117,114,111,112,101, +112,101,114,109,105,116,116,101,100,118,97,108,105,100,97,116,101,46,97,112,112, +101,97,114,105,110,103,111,102,102,105,99,105,97,108,115,115,101,114,105,111,117 +,115,108,121,45,108,97,110,103,117,97,103,101,105,110,105,116,105,97,116,101,100 +,101,120,116,101,110,100,105,110,103,108,111,110,103,45,116,101,114,109,105,110, +102,108,97,116,105,111,110,115,117,99,104,32,116,104,97,116,103,101,116,67,111, +111,107,105,101,109,97,114,107,101,100,32,98,121,60,47,98,117,116,116,111,110,62 +,105,109,112,108,101,109,101,110,116,98,117,116,32,105,116,32,105,115,105,110,99 +,114,101,97,115,101,115,100,111,119,110,32,116,104,101,32,114,101,113,117,105, +114,105,110,103,100,101,112,101,110,100,101,110,116,45,45,62,10,60,33,45,45,32, +105,110,116,101,114,118,105,101,119,87,105,116,104,32,116,104,101,32,99,111,112, +105,101,115,32,111,102,99,111,110,115,101,110,115,117,115,119,97,115,32,98,117, +105,108,116,86,101,110,101,122,117,101,108,97,40,102,111,114,109,101,114,108,121 +,116,104,101,32,115,116,97,116,101,112,101,114,115,111,110,110,101,108,115,116, +114,97,116,101,103,105,99,102,97,118,111,117,114,32,111,102,105,110,118,101,110, +116,105,111,110,87,105,107,105,112,101,100,105,97,99,111,110,116,105,110,101,110 +,116,118,105,114,116,117,97,108,108,121,119,104,105,99,104,32,119,97,115,112,114 +,105,110,99,105,112,108,101,67,111,109,112,108,101,116,101,32,105,100,101,110, +116,105,99,97,108,115,104,111,119,32,116,104,97,116,112,114,105,109,105,116,105, +118,101,97,119,97,121,32,102,114,111,109,109,111,108,101,99,117,108,97,114,112, +114,101,99,105,115,101,108,121,100,105,115,115,111,108,118,101,100,85,110,100, +101,114,32,116,104,101,118,101,114,115,105,111,110,61,34,62,38,110,98,115,112,59 +,60,47,73,116,32,105,115,32,116,104,101,32,84,104,105,115,32,105,115,32,119,105, +108,108,32,104,97,118,101,111,114,103,97,110,105,115,109,115,115,111,109,101,32, +116,105,109,101,70,114,105,101,100,114,105,99,104,119,97,115,32,102,105,114,115, +116,116,104,101,32,111,110,108,121,32,102,97,99,116,32,116,104,97,116,102,111, +114,109,32,105,100,61,34,112,114,101,99,101,100,105,110,103,84,101,99,104,110, +105,99,97,108,112,104,121,115,105,99,105,115,116,111,99,99,117,114,115,32,105, +110,110,97,118,105,103,97,116,111,114,115,101,99,116,105,111,110,34,62,115,112, +97,110,32,105,100,61,34,115,111,117,103,104,116,32,116,111,98,101,108,111,119,32 +,116,104,101,115,117,114,118,105,118,105,110,103,125,60,47,115,116,121,108,101, +62,104,105,115,32,100,101,97,116,104,97,115,32,105,110,32,116,104,101,99,97,117, +115,101,100,32,98,121,112,97,114,116,105,97,108,108,121,101,120,105,115,116,105, +110,103,32,117,115,105,110,103,32,116,104,101,119,97,115,32,103,105,118,101,110, +97,32,108,105,115,116,32,111,102,108,101,118,101,108,115,32,111,102,110,111,116, +105,111,110,32,111,102,79,102,102,105,99,105,97,108,32,100,105,115,109,105,115, +115,101,100,115,99,105,101,110,116,105,115,116,114,101,115,101,109,98,108,101, +115,100,117,112,108,105,99,97,116,101,101,120,112,108,111,115,105,118,101,114, +101,99,111,118,101,114,101,100,97,108,108,32,111,116,104,101,114,103,97,108,108, +101,114,105,101,115,123,112,97,100,100,105,110,103,58,112,101,111,112,108,101,32 +,111,102,114,101,103,105,111,110,32,111,102,97,100,100,114,101,115,115,101,115, +97,115,115,111,99,105,97,116,101,105,109,103,32,97,108,116,61,34,105,110,32,109, +111,100,101,114,110,115,104,111,117,108,100,32,98,101,109,101,116,104,111,100,32 +,111,102,114,101,112,111,114,116,105,110,103,116,105,109,101,115,116,97,109,112, +110,101,101,100,101,100,32,116,111,116,104,101,32,71,114,101,97,116,114,101,103, +97,114,100,105,110,103,115,101,101,109,101,100,32,116,111,118,105,101,119,101, +100,32,97,115,105,109,112,97,99,116,32,111,110,105,100,101,97,32,116,104,97,116, +116,104,101,32,87,111,114,108,100,104,101,105,103,104,116,32,111,102,101,120,112 +,97,110,100,105,110,103,84,104,101,115,101,32,97,114,101,99,117,114,114,101,110, +116,34,62,99,97,114,101,102,117,108,108,121,109,97,105,110,116,97,105,110,115,99 +,104,97,114,103,101,32,111,102,67,108,97,115,115,105,99,97,108,97,100,100,114, +101,115,115,101,100,112,114,101,100,105,99,116,101,100,111,119,110,101,114,115, +104,105,112,60,100,105,118,32,105,100,61,34,114,105,103,104,116,34,62,13,10,114, +101,115,105,100,101,110,99,101,108,101,97,118,101,32,116,104,101,99,111,110,116, +101,110,116,34,62,97,114,101,32,111,102,116,101,110,32,32,125,41,40,41,59,13,10, +112,114,111,98,97,98,108,121,32,80,114,111,102,101,115,115,111,114,45,98,117,116 +,116,111,110,34,32,114,101,115,112,111,110,100,101,100,115,97,121,115,32,116,104 +,97,116,104,97,100,32,116,111,32,98,101,112,108,97,99,101,100,32,105,110,72,117, +110,103,97,114,105,97,110,115,116,97,116,117,115,32,111,102,115,101,114,118,101, +115,32,97,115,85,110,105,118,101,114,115,97,108,101,120,101,99,117,116,105,111, +110,97,103,103,114,101,103,97,116,101,102,111,114,32,119,104,105,99,104,105,110, +102,101,99,116,105,111,110,97,103,114,101,101,100,32,116,111,104,111,119,101,118 +,101,114,44,32,112,111,112,117,108,97,114,34,62,112,108,97,99,101,100,32,111,110 +,99,111,110,115,116,114,117,99,116,101,108,101,99,116,111,114,97,108,115,121,109 +,98,111,108,32,111,102,105,110,99,108,117,100,105,110,103,114,101,116,117,114, +110,32,116,111,97,114,99,104,105,116,101,99,116,67,104,114,105,115,116,105,97, +110,112,114,101,118,105,111,117,115,32,108,105,118,105,110,103,32,105,110,101,97 +,115,105,101,114,32,116,111,112,114,111,102,101,115,115,111,114,10,38,108,116,59 +,33,45,45,32,101,102,102,101,99,116,32,111,102,97,110,97,108,121,116,105,99,115, +119,97,115,32,116,97,107,101,110,119,104,101,114,101,32,116,104,101,116,111,111, +107,32,111,118,101,114,98,101,108,105,101,102,32,105,110,65,102,114,105,107,97, +97,110,115,97,115,32,102,97,114,32,97,115,112,114,101,118,101,110,116,101,100, +119,111,114,107,32,119,105,116,104,97,32,115,112,101,99,105,97,108,60,102,105, +101,108,100,115,101,116,67,104,114,105,115,116,109,97,115,82,101,116,114,105,101 +,118,101,100,10,10,73,110,32,116,104,101,32,98,97,99,107,32,105,110,116,111,110, +111,114,116,104,101,97,115,116,109,97,103,97,122,105,110,101,115,62,60,115,116, +114,111,110,103,62,99,111,109,109,105,116,116,101,101,103,111,118,101,114,110, +105,110,103,103,114,111,117,112,115,32,111,102,115,116,111,114,101,100,32,105, +110,101,115,116,97,98,108,105,115,104,97,32,103,101,110,101,114,97,108,105,116, +115,32,102,105,114,115,116,116,104,101,105,114,32,111,119,110,112,111,112,117, +108,97,116,101,100,97,110,32,111,98,106,101,99,116,67,97,114,105,98,98,101,97, +110,97,108,108,111,119,32,116,104,101,100,105,115,116,114,105,99,116,115,119,105 +,115,99,111,110,115,105,110,108,111,99,97,116,105,111,110,46,59,32,119,105,100, +116,104,58,32,105,110,104,97,98,105,116,101,100,83,111,99,105,97,108,105,115,116 +,74,97,110,117,97,114,121,32,49,60,47,102,111,111,116,101,114,62,115,105,109,105 +,108,97,114,108,121,99,104,111,105,99,101,32,111,102,116,104,101,32,115,97,109, +101,32,115,112,101,99,105,102,105,99,32,98,117,115,105,110,101,115,115,32,84,104 +,101,32,102,105,114,115,116,46,108,101,110,103,116,104,59,32,100,101,115,105,114 +,101,32,116,111,100,101,97,108,32,119,105,116,104,115,105,110,99,101,32,116,104, +101,117,115,101,114,65,103,101,110,116,99,111,110,99,101,105,118,101,100,105,110 +,100,101,120,46,112,104,112,97,115,32,38,113,117,111,116,59,101,110,103,97,103, +101,32,105,110,114,101,99,101,110,116,108,121,44,102,101,119,32,121,101,97,114, +115,119,101,114,101,32,97,108,115,111,10,60,104,101,97,100,62,10,60,101,100,105, +116,101,100,32,98,121,97,114,101,32,107,110,111,119,110,99,105,116,105,101,115, +32,105,110,97,99,99,101,115,115,107,101,121,99,111,110,100,101,109,110,101,100, +97,108,115,111,32,104,97,118,101,115,101,114,118,105,99,101,115,44,102,97,109, +105,108,121,32,111,102,83,99,104,111,111,108,32,111,102,99,111,110,118,101,114, +116,101,100,110,97,116,117,114,101,32,111,102,32,108,97,110,103,117,97,103,101, +109,105,110,105,115,116,101,114,115,60,47,111,98,106,101,99,116,62,116,104,101, +114,101,32,105,115,32,97,32,112,111,112,117,108,97,114,115,101,113,117,101,110, +99,101,115,97,100,118,111,99,97,116,101,100,84,104,101,121,32,119,101,114,101,97 +,110,121,32,111,116,104,101,114,108,111,99,97,116,105,111,110,61,101,110,116,101 +,114,32,116,104,101,109,117,99,104,32,109,111,114,101,114,101,102,108,101,99,116 +,101,100,119,97,115,32,110,97,109,101,100,111,114,105,103,105,110,97,108,32,97, +32,116,121,112,105,99,97,108,119,104,101,110,32,116,104,101,121,101,110,103,105, +110,101,101,114,115,99,111,117,108,100,32,110,111,116,114,101,115,105,100,101, +110,116,115,119,101,100,110,101,115,100,97,121,116,104,101,32,116,104,105,114, +100,32,112,114,111,100,117,99,116,115,74,97,110,117,97,114,121,32,50,119,104,97, +116,32,116,104,101,121,97,32,99,101,114,116,97,105,110,114,101,97,99,116,105,111 +,110,115,112,114,111,99,101,115,115,111,114,97,102,116,101,114,32,104,105,115, +116,104,101,32,108,97,115,116,32,99,111,110,116,97,105,110,101,100,34,62,60,47, +100,105,118,62,10,60,47,97,62,60,47,116,100,62,100,101,112,101,110,100,32,111, +110,115,101,97,114,99,104,34,62,10,112,105,101,99,101,115,32,111,102,99,111,109, +112,101,116,105,110,103,82,101,102,101,114,101,110,99,101,116,101,110,110,101, +115,115,101,101,119,104,105,99,104,32,104,97,115,32,118,101,114,115,105,111,110, +61,60,47,115,112,97,110,62,32,60,60,47,104,101,97,100,101,114,62,103,105,118,101 +,115,32,116,104,101,104,105,115,116,111,114,105,97,110,118,97,108,117,101,61,34, +34,62,112,97,100,100,105,110,103,58,48,118,105,101,119,32,116,104,97,116,116,111 +,103,101,116,104,101,114,44,116,104,101,32,109,111,115,116,32,119,97,115,32,102, +111,117,110,100,115,117,98,115,101,116,32,111,102,97,116,116,97,99,107,32,111, +110,99,104,105,108,100,114,101,110,44,112,111,105,110,116,115,32,111,102,112,101 +,114,115,111,110,97,108,32,112,111,115,105,116,105,111,110,58,97,108,108,101,103 +,101,100,108,121,67,108,101,118,101,108,97,110,100,119,97,115,32,108,97,116,101, +114,97,110,100,32,97,102,116,101,114,97,114,101,32,103,105,118,101,110,119,97, +115,32,115,116,105,108,108,115,99,114,111,108,108,105,110,103,100,101,115,105, +103,110,32,111,102,109,97,107,101,115,32,116,104,101,109,117,99,104,32,108,101, +115,115,65,109,101,114,105,99,97,110,115,46,10,10,65,102,116,101,114,32,44,32,98 +,117,116,32,116,104,101,77,117,115,101,117,109,32,111,102,108,111,117,105,115, +105,97,110,97,40,102,114,111,109,32,116,104,101,109,105,110,110,101,115,111,116, +97,112,97,114,116,105,99,108,101,115,97,32,112,114,111,99,101,115,115,68,111,109 +,105,110,105,99,97,110,118,111,108,117,109,101,32,111,102,114,101,116,117,114, +110,105,110,103,100,101,102,101,110,115,105,118,101,48,48,112,120,124,114,105, +103,104,109,97,100,101,32,102,114,111,109,109,111,117,115,101,111,118,101,114,34 +,32,115,116,121,108,101,61,34,115,116,97,116,101,115,32,111,102,40,119,104,105, +99,104,32,105,115,99,111,110,116,105,110,117,101,115,70,114,97,110,99,105,115,99 +,111,98,117,105,108,100,105,110,103,32,119,105,116,104,111,117,116,32,97,119,105 +,116,104,32,115,111,109,101,119,104,111,32,119,111,117,108,100,97,32,102,111,114 +,109,32,111,102,97,32,112,97,114,116,32,111,102,98,101,102,111,114,101,32,105, +116,107,110,111,119,110,32,97,115,32,32,83,101,114,118,105,99,101,115,108,111,99 +,97,116,105,111,110,32,97,110,100,32,111,102,116,101,110,109,101,97,115,117,114, +105,110,103,97,110,100,32,105,116,32,105,115,112,97,112,101,114,98,97,99,107,118 +,97,108,117,101,115,32,111,102,13,10,60,116,105,116,108,101,62,61,32,119,105,110 +,100,111,119,46,100,101,116,101,114,109,105,110,101,101,114,38,113,117,111,116, +59,32,112,108,97,121,101,100,32,98,121,97,110,100,32,101,97,114,108,121,60,47,99 +,101,110,116,101,114,62,102,114,111,109,32,116,104,105,115,116,104,101,32,116, +104,114,101,101,112,111,119,101,114,32,97,110,100,111,102,32,38,113,117,111,116, +59,105,110,110,101,114,72,84,77,76,60,97,32,104,114,101,102,61,34,121,58,105,110 +,108,105,110,101,59,67,104,117,114,99,104,32,111,102,116,104,101,32,101,118,101, +110,116,118,101,114,121,32,104,105,103,104,111,102,102,105,99,105,97,108,32,45, +104,101,105,103,104,116,58,32,99,111,110,116,101,110,116,61,34,47,99,103,105,45, +98,105,110,47,116,111,32,99,114,101,97,116,101,97,102,114,105,107,97,97,110,115, +101,115,112,101,114,97,110,116,111,102,114,97,110,195,167,97,105,115,108,97,116, +118,105,101,197,161,117,108,105,101,116,117,118,105,197,179,196,140,101,197,161, +116,105,110,97,196,141,101,197,161,116,105,110,97,224,185,132,224,184,151,224, +184,162,230,151,165,230,156,172,232,170,158,231,174,128,228,189,147,229,173,151, +231,185,129,233,171,148,229,173,151,237,149,156,234,181,173,236,150,180,228,184, +186,228,187,128,228,185,136,232,174,161,231,174,151,230,156,186,231,172,148,232, +174,176,230,156,172,232,168,142,232,171,150,229,141,128,230,156,141,229,138,161, +229,153,168,228,186,146,232,129,148,231,189,145,230,136,191,229,156,176,228,186, +167,228,191,177,228,185,144,233,131,168,229,135,186,231,137,136,231,164,190,230, +142,146,232,161,140,230,166,156,233,131,168,232,144,189,230,160,188,232,191,155, +228,184,128,230,173,165,230,148,175,228,187,152,229,174,157,233,170,140,232,175, +129,231,160,129,229,167,148,229,145,152,228,188,154,230,149,176,230,141,174,229, +186,147,230,182,136,232,180,185,232,128,133,229,138,158,229,133,172,229,174,164, +232,174,168,232,174,186,229,140,186,230,183,177,229,156,179,229,184,130,230,146, +173,230,148,190,229,153,168,229,140,151,228,186,172,229,184,130,229,164,167,229, +173,166,231,148,159,232,182,138,230,157,165,232,182,138,231,174,161,231,144,134, +229,145,152,228,191,161,230,129,175,231,189,145,115,101,114,118,105,99,105,111, +115,97,114,116,195,173,99,117,108,111,97,114,103,101,110,116,105,110,97,98,97, +114,99,101,108,111,110,97,99,117,97,108,113,117,105,101,114,112,117,98,108,105, +99,97,100,111,112,114,111,100,117,99,116,111,115,112,111,108,195,173,116,105,99, +97,114,101,115,112,117,101,115,116,97,119,105,107,105,112,101,100,105,97,115,105 +,103,117,105,101,110,116,101,98,195,186,115,113,117,101,100,97,99,111,109,117, +110,105,100,97,100,115,101,103,117,114,105,100,97,100,112,114,105,110,99,105,112 +,97,108,112,114,101,103,117,110,116,97,115,99,111,110,116,101,110,105,100,111, +114,101,115,112,111,110,100,101,114,118,101,110,101,122,117,101,108,97,112,114, +111,98,108,101,109,97,115,100,105,99,105,101,109,98,114,101,114,101,108,97,99, +105,195,179,110,110,111,118,105,101,109,98,114,101,115,105,109,105,108,97,114, +101,115,112,114,111,121,101,99,116,111,115,112,114,111,103,114,97,109,97,115,105 +,110,115,116,105,116,117,116,111,97,99,116,105,118,105,100,97,100,101,110,99,117 +,101,110,116,114,97,101,99,111,110,111,109,195,173,97,105,109,195,161,103,101, +110,101,115,99,111,110,116,97,99,116,97,114,100,101,115,99,97,114,103,97,114,110 +,101,99,101,115,97,114,105,111,97,116,101,110,99,105,195,179,110,116,101,108,195 +,169,102,111,110,111,99,111,109,105,115,105,195,179,110,99,97,110,99,105,111,110 +,101,115,99,97,112,97,99,105,100,97,100,101,110,99,111,110,116,114,97,114,97,110 +,195,161,108,105,115,105,115,102,97,118,111,114,105,116,111,115,116,195,169,114, +109,105,110,111,115,112,114,111,118,105,110,99,105,97,101,116,105,113,117,101, +116,97,115,101,108,101,109,101,110,116,111,115,102,117,110,99,105,111,110,101, +115,114,101,115,117,108,116,97,100,111,99,97,114,195,161,99,116,101,114,112,114, +111,112,105,101,100,97,100,112,114,105,110,99,105,112,105,111,110,101,99,101,115 +,105,100,97,100,109,117,110,105,99,105,112,97,108,99,114,101,97,99,105,195,179, +110,100,101,115,99,97,114,103,97,115,112,114,101,115,101,110,99,105,97,99,111, +109,101,114,99,105,97,108,111,112,105,110,105,111,110,101,115,101,106,101,114,99 +,105,99,105,111,101,100,105,116,111,114,105,97,108,115,97,108,97,109,97,110,99, +97,103,111,110,122,195,161,108,101,122,100,111,99,117,109,101,110,116,111,112, +101,108,195,173,99,117,108,97,114,101,99,105,101,110,116,101,115,103,101,110,101 +,114,97,108,101,115,116,97,114,114,97,103,111,110,97,112,114,195,161,99,116,105, +99,97,110,111,118,101,100,97,100,101,115,112,114,111,112,117,101,115,116,97,112, +97,99,105,101,110,116,101,115,116,195,169,99,110,105,99,97,115,111,98,106,101, +116,105,118,111,115,99,111,110,116,97,99,116,111,115,224,164,174,224,165,135,224 +,164,130,224,164,178,224,164,191,224,164,143,224,164,185,224,165,136,224,164,130 +,224,164,151,224,164,175,224,164,190,224,164,184,224,164,190,224,164,165,224,164 +,143,224,164,181,224,164,130,224,164,176,224,164,185,224,165,135,224,164,149,224 +,165,139,224,164,136,224,164,149,224,165,129,224,164,155,224,164,176,224,164,185 +,224,164,190,224,164,172,224,164,190,224,164,166,224,164,149,224,164,185,224,164 +,190,224,164,184,224,164,173,224,165,128,224,164,185,224,165,129,224,164,143,224 +,164,176,224,164,185,224,165,128,224,164,174,224,165,136,224,164,130,224,164,166 +,224,164,191,224,164,168,224,164,172,224,164,190,224,164,164,100,105,112,108,111 +,100,111,99,115,224,164,184,224,164,174,224,164,175,224,164,176,224,165,130,224, +164,170,224,164,168,224,164,190,224,164,174,224,164,170,224,164,164,224,164,190, +224,164,171,224,164,191,224,164,176,224,164,148,224,164,184,224,164,164,224,164, +164,224,164,176,224,164,185,224,164,178,224,165,139,224,164,151,224,164,185,224, +165,129,224,164,134,224,164,172,224,164,190,224,164,176,224,164,166,224,165,135, +224,164,182,224,164,185,224,165,129,224,164,136,224,164,150,224,165,135,224,164, +178,224,164,175,224,164,166,224,164,191,224,164,149,224,164,190,224,164,174,224, +164,181,224,165,135,224,164,172,224,164,164,224,165,128,224,164,168,224,164,172, +224,165,128,224,164,154,224,164,174,224,165,140,224,164,164,224,164,184,224,164, +190,224,164,178,224,164,178,224,165,135,224,164,150,224,164,156,224,165,137,224, +164,172,224,164,174,224,164,166,224,164,166,224,164,164,224,164,165,224,164,190, +224,164,168,224,164,185,224,165,128,224,164,182,224,164,185,224,164,176,224,164, +133,224,164,178,224,164,151,224,164,149,224,164,173,224,165,128,224,164,168,224, +164,151,224,164,176,224,164,170,224,164,190,224,164,184,224,164,176,224,164,190, +224,164,164,224,164,149,224,164,191,224,164,143,224,164,137,224,164,184,224,165, +135,224,164,151,224,164,175,224,165,128,224,164,185,224,165,130,224,164,129,224, +164,134,224,164,151,224,165,135,224,164,159,224,165,128,224,164,174,224,164,150, +224,165,139,224,164,156,224,164,149,224,164,190,224,164,176,224,164,133,224,164, +173,224,165,128,224,164,151,224,164,175,224,165,135,224,164,164,224,165,129,224, +164,174,224,164,181,224,165,139,224,164,159,224,164,166,224,165,135,224,164,130, +224,164,133,224,164,151,224,164,176,224,164,144,224,164,184,224,165,135,224,164, +174,224,165,135,224,164,178,224,164,178,224,164,151,224,164,190,224,164,185,224, +164,190,224,164,178,224,164,138,224,164,170,224,164,176,224,164,154,224,164,190, +224,164,176,224,164,144,224,164,184,224,164,190,224,164,166,224,165,135,224,164, +176,224,164,156,224,164,191,224,164,184,224,164,166,224,164,191,224,164,178,224, +164,172,224,164,130,224,164,166,224,164,172,224,164,168,224,164,190,224,164,185, +224,165,130,224,164,130,224,164,178,224,164,190,224,164,150,224,164,156,224,165, +128,224,164,164,224,164,172,224,164,159,224,164,168,224,164,174,224,164,191,224, +164,178,224,164,135,224,164,184,224,165,135,224,164,134,224,164,168,224,165,135, +224,164,168,224,164,175,224,164,190,224,164,149,224,165,129,224,164,178,224,164, +178,224,165,137,224,164,151,224,164,173,224,164,190,224,164,151,224,164,176,224, +165,135,224,164,178,224,164,156,224,164,151,224,164,185,224,164,176,224,164,190, +224,164,174,224,164,178,224,164,151,224,165,135,224,164,170,224,165,135,224,164, +156,224,164,185,224,164,190,224,164,165,224,164,135,224,164,184,224,165,128,224, +164,184,224,164,185,224,165,128,224,164,149,224,164,178,224,164,190,224,164,160, +224,165,128,224,164,149,224,164,185,224,164,190,224,164,129,224,164,166,224,165, +130,224,164,176,224,164,164,224,164,185,224,164,164,224,164,184,224,164,190,224, +164,164,224,164,175,224,164,190,224,164,166,224,164,134,224,164,175,224,164,190, +224,164,170,224,164,190,224,164,149,224,164,149,224,165,140,224,164,168,224,164, +182,224,164,190,224,164,174,224,164,166,224,165,135,224,164,150,224,164,175,224, +164,185,224,165,128,224,164,176,224,164,190,224,164,175,224,164,150,224,165,129, +224,164,166,224,164,178,224,164,151,224,165,128,99,97,116,101,103,111,114,105, +101,115,101,120,112,101,114,105,101,110,99,101,60,47,116,105,116,108,101,62,13, +10,67,111,112,121,114,105,103,104,116,32,106,97,118,97,115,99,114,105,112,116,99 +,111,110,100,105,116,105,111,110,115,101,118,101,114,121,116,104,105,110,103,60, +112,32,99,108,97,115,115,61,34,116,101,99,104,110,111,108,111,103,121,98,97,99, +107,103,114,111,117,110,100,60,97,32,99,108,97,115,115,61,34,109,97,110,97,103, +101,109,101,110,116,38,99,111,112,121,59,32,50,48,49,106,97,118,97,83,99,114,105 +,112,116,99,104,97,114,97,99,116,101,114,115,98,114,101,97,100,99,114,117,109,98 +,116,104,101,109,115,101,108,118,101,115,104,111,114,105,122,111,110,116,97,108, +103,111,118,101,114,110,109,101,110,116,67,97,108,105,102,111,114,110,105,97,97, +99,116,105,118,105,116,105,101,115,100,105,115,99,111,118,101,114,101,100,78,97, +118,105,103,97,116,105,111,110,116,114,97,110,115,105,116,105,111,110,99,111,110 +,110,101,99,116,105,111,110,110,97,118,105,103,97,116,105,111,110,97,112,112,101 +,97,114,97,110,99,101,60,47,116,105,116,108,101,62,60,109,99,104,101,99,107,98, +111,120,34,32,116,101,99,104,110,105,113,117,101,115,112,114,111,116,101,99,116, +105,111,110,97,112,112,97,114,101,110,116,108,121,97,115,32,119,101,108,108,32, +97,115,117,110,116,39,44,32,39,85,65,45,114,101,115,111,108,117,116,105,111,110, +111,112,101,114,97,116,105,111,110,115,116,101,108,101,118,105,115,105,111,110, +116,114,97,110,115,108,97,116,101,100,87,97,115,104,105,110,103,116,111,110,110, +97,118,105,103,97,116,111,114,46,32,61,32,119,105,110,100,111,119,46,105,109,112 +,114,101,115,115,105,111,110,38,108,116,59,98,114,38,103,116,59,108,105,116,101, +114,97,116,117,114,101,112,111,112,117,108,97,116,105,111,110,98,103,99,111,108, +111,114,61,34,35,101,115,112,101,99,105,97,108,108,121,32,99,111,110,116,101,110 +,116,61,34,112,114,111,100,117,99,116,105,111,110,110,101,119,115,108,101,116, +116,101,114,112,114,111,112,101,114,116,105,101,115,100,101,102,105,110,105,116, +105,111,110,108,101,97,100,101,114,115,104,105,112,84,101,99,104,110,111,108,111 +,103,121,80,97,114,108,105,97,109,101,110,116,99,111,109,112,97,114,105,115,111, +110,117,108,32,99,108,97,115,115,61,34,46,105,110,100,101,120,79,102,40,34,99, +111,110,99,108,117,115,105,111,110,100,105,115,99,117,115,115,105,111,110,99,111 +,109,112,111,110,101,110,116,115,98,105,111,108,111,103,105,99,97,108,82,101,118 +,111,108,117,116,105,111,110,95,99,111,110,116,97,105,110,101,114,117,110,100, +101,114,115,116,111,111,100,110,111,115,99,114,105,112,116,62,60,112,101,114,109 +,105,115,115,105,111,110,101,97,99,104,32,111,116,104,101,114,97,116,109,111,115 +,112,104,101,114,101,32,111,110,102,111,99,117,115,61,34,60,102,111,114,109,32, +105,100,61,34,112,114,111,99,101,115,115,105,110,103,116,104,105,115,46,118,97, +108,117,101,103,101,110,101,114,97,116,105,111,110,67,111,110,102,101,114,101, +110,99,101,115,117,98,115,101,113,117,101,110,116,119,101,108,108,45,107,110,111 +,119,110,118,97,114,105,97,116,105,111,110,115,114,101,112,117,116,97,116,105, +111,110,112,104,101,110,111,109,101,110,111,110,100,105,115,99,105,112,108,105, +110,101,108,111,103,111,46,112,110,103,34,32,40,100,111,99,117,109,101,110,116, +44,98,111,117,110,100,97,114,105,101,115,101,120,112,114,101,115,115,105,111,110 +,115,101,116,116,108,101,109,101,110,116,66,97,99,107,103,114,111,117,110,100, +111,117,116,32,111,102,32,116,104,101,101,110,116,101,114,112,114,105,115,101,40 +,34,104,116,116,112,115,58,34,32,117,110,101,115,99,97,112,101,40,34,112,97,115, +115,119,111,114,100,34,32,100,101,109,111,99,114,97,116,105,99,60,97,32,104,114, +101,102,61,34,47,119,114,97,112,112,101,114,34,62,10,109,101,109,98,101,114,115, +104,105,112,108,105,110,103,117,105,115,116,105,99,112,120,59,112,97,100,100,105 +,110,103,112,104,105,108,111,115,111,112,104,121,97,115,115,105,115,116,97,110, +99,101,117,110,105,118,101,114,115,105,116,121,102,97,99,105,108,105,116,105,101 +,115,114,101,99,111,103,110,105,122,101,100,112,114,101,102,101,114,101,110,99, +101,105,102,32,40,116,121,112,101,111,102,109,97,105,110,116,97,105,110,101,100, +118,111,99,97,98,117,108,97,114,121,104,121,112,111,116,104,101,115,105,115,46, +115,117,98,109,105,116,40,41,59,38,97,109,112,59,110,98,115,112,59,97,110,110, +111,116,97,116,105,111,110,98,101,104,105,110,100,32,116,104,101,70,111,117,110, +100,97,116,105,111,110,112,117,98,108,105,115,104,101,114,34,97,115,115,117,109, +112,116,105,111,110,105,110,116,114,111,100,117,99,101,100,99,111,114,114,117, +112,116,105,111,110,115,99,105,101,110,116,105,115,116,115,101,120,112,108,105, +99,105,116,108,121,105,110,115,116,101,97,100,32,111,102,100,105,109,101,110,115 +,105,111,110,115,32,111,110,67,108,105,99,107,61,34,99,111,110,115,105,100,101, +114,101,100,100,101,112,97,114,116,109,101,110,116,111,99,99,117,112,97,116,105, +111,110,115,111,111,110,32,97,102,116,101,114,105,110,118,101,115,116,109,101, +110,116,112,114,111,110,111,117,110,99,101,100,105,100,101,110,116,105,102,105, +101,100,101,120,112,101,114,105,109,101,110,116,77,97,110,97,103,101,109,101,110 +,116,103,101,111,103,114,97,112,104,105,99,34,32,104,101,105,103,104,116,61,34, +108,105,110,107,32,114,101,108,61,34,46,114,101,112,108,97,99,101,40,47,100,101, +112,114,101,115,115,105,111,110,99,111,110,102,101,114,101,110,99,101,112,117, +110,105,115,104,109,101,110,116,101,108,105,109,105,110,97,116,101,100,114,101, +115,105,115,116,97,110,99,101,97,100,97,112,116,97,116,105,111,110,111,112,112, +111,115,105,116,105,111,110,119,101,108,108,32,107,110,111,119,110,115,117,112, +112,108,101,109,101,110,116,100,101,116,101,114,109,105,110,101,100,104,49,32,99 +,108,97,115,115,61,34,48,112,120,59,109,97,114,103,105,110,109,101,99,104,97,110 +,105,99,97,108,115,116,97,116,105,115,116,105,99,115,99,101,108,101,98,114,97, +116,101,100,71,111,118,101,114,110,109,101,110,116,10,10,68,117,114,105,110,103, +32,116,100,101,118,101,108,111,112,101,114,115,97,114,116,105,102,105,99,105,97, +108,101,113,117,105,118,97,108,101,110,116,111,114,105,103,105,110,97,116,101, +100,67,111,109,109,105,115,115,105,111,110,97,116,116,97,99,104,109,101,110,116, +60,115,112,97,110,32,105,100,61,34,116,104,101,114,101,32,119,101,114,101,78,101 +,100,101,114,108,97,110,100,115,98,101,121,111,110,100,32,116,104,101,114,101, +103,105,115,116,101,114,101,100,106,111,117,114,110,97,108,105,115,116,102,114, +101,113,117,101,110,116,108,121,97,108,108,32,111,102,32,116,104,101,108,97,110, +103,61,34,101,110,34,32,60,47,115,116,121,108,101,62,13,10,97,98,115,111,108,117 +,116,101,59,32,115,117,112,112,111,114,116,105,110,103,101,120,116,114,101,109, +101,108,121,32,109,97,105,110,115,116,114,101,97,109,60,47,115,116,114,111,110, +103,62,32,112,111,112,117,108,97,114,105,116,121,101,109,112,108,111,121,109,101 +,110,116,60,47,116,97,98,108,101,62,13,10,32,99,111,108,115,112,97,110,61,34,60, +47,102,111,114,109,62,10,32,32,99,111,110,118,101,114,115,105,111,110,97,98,111, +117,116,32,116,104,101,32,60,47,112,62,60,47,100,105,118,62,105,110,116,101,103, +114,97,116,101,100,34,32,108,97,110,103,61,34,101,110,80,111,114,116,117,103,117 +,101,115,101,115,117,98,115,116,105,116,117,116,101,105,110,100,105,118,105,100, +117,97,108,105,109,112,111,115,115,105,98,108,101,109,117,108,116,105,109,101, +100,105,97,97,108,109,111,115,116,32,97,108,108,112,120,32,115,111,108,105,100, +32,35,97,112,97,114,116,32,102,114,111,109,115,117,98,106,101,99,116,32,116,111, +105,110,32,69,110,103,108,105,115,104,99,114,105,116,105,99,105,122,101,100,101, +120,99,101,112,116,32,102,111,114,103,117,105,100,101,108,105,110,101,115,111, +114,105,103,105,110,97,108,108,121,114,101,109,97,114,107,97,98,108,101,116,104, +101,32,115,101,99,111,110,100,104,50,32,99,108,97,115,115,61,34,60,97,32,116,105 +,116,108,101,61,34,40,105,110,99,108,117,100,105,110,103,112,97,114,97,109,101, +116,101,114,115,112,114,111,104,105,98,105,116,101,100,61,32,34,104,116,116,112, +58,47,47,100,105,99,116,105,111,110,97,114,121,112,101,114,99,101,112,116,105, +111,110,114,101,118,111,108,117,116,105,111,110,102,111,117,110,100,97,116,105, +111,110,112,120,59,104,101,105,103,104,116,58,115,117,99,99,101,115,115,102,117, +108,115,117,112,112,111,114,116,101,114,115,109,105,108,108,101,110,110,105,117, +109,104,105,115,32,102,97,116,104,101,114,116,104,101,32,38,113,117,111,116,59, +110,111,45,114,101,112,101,97,116,59,99,111,109,109,101,114,99,105,97,108,105, +110,100,117,115,116,114,105,97,108,101,110,99,111,117,114,97,103,101,100,97,109, +111,117,110,116,32,111,102,32,117,110,111,102,102,105,99,105,97,108,101,102,102, +105,99,105,101,110,99,121,82,101,102,101,114,101,110,99,101,115,99,111,111,114, +100,105,110,97,116,101,100,105,115,99,108,97,105,109,101,114,101,120,112,101,100 +,105,116,105,111,110,100,101,118,101,108,111,112,105,110,103,99,97,108,99,117, +108,97,116,101,100,115,105,109,112,108,105,102,105,101,100,108,101,103,105,116, +105,109,97,116,101,115,117,98,115,116,114,105,110,103,40,48,34,32,99,108,97,115, +115,61,34,99,111,109,112,108,101,116,101,108,121,105,108,108,117,115,116,114,97, +116,101,102,105,118,101,32,121,101,97,114,115,105,110,115,116,114,117,109,101, +110,116,80,117,98,108,105,115,104,105,110,103,49,34,32,99,108,97,115,115,61,34, +112,115,121,99,104,111,108,111,103,121,99,111,110,102,105,100,101,110,99,101,110 +,117,109,98,101,114,32,111,102,32,97,98,115,101,110,99,101,32,111,102,102,111,99 +,117,115,101,100,32,111,110,106,111,105,110,101,100,32,116,104,101,115,116,114, +117,99,116,117,114,101,115,112,114,101,118,105,111,117,115,108,121,62,60,47,105, +102,114,97,109,101,62,111,110,99,101,32,97,103,97,105,110,98,117,116,32,114,97, +116,104,101,114,105,109,109,105,103,114,97,110,116,115,111,102,32,99,111,117,114 +,115,101,44,97,32,103,114,111,117,112,32,111,102,76,105,116,101,114,97,116,117, +114,101,85,110,108,105,107,101,32,116,104,101,60,47,97,62,38,110,98,115,112,59, +10,102,117,110,99,116,105,111,110,32,105,116,32,119,97,115,32,116,104,101,67,111 +,110,118,101,110,116,105,111,110,97,117,116,111,109,111,98,105,108,101,80,114, +111,116,101,115,116,97,110,116,97,103,103,114,101,115,115,105,118,101,97,102,116 +,101,114,32,116,104,101,32,83,105,109,105,108,97,114,108,121,44,34,32,47,62,60, +47,100,105,118,62,99,111,108,108,101,99,116,105,111,110,13,10,102,117,110,99,116 +,105,111,110,118,105,115,105,98,105,108,105,116,121,116,104,101,32,117,115,101, +32,111,102,118,111,108,117,110,116,101,101,114,115,97,116,116,114,97,99,116,105, +111,110,117,110,100,101,114,32,116,104,101,32,116,104,114,101,97,116,101,110,101 +,100,42,60,33,91,67,68,65,84,65,91,105,109,112,111,114,116,97,110,99,101,105,110 +,32,103,101,110,101,114,97,108,116,104,101,32,108,97,116,116,101,114,60,47,102, +111,114,109,62,10,60,47,46,105,110,100,101,120,79,102,40,39,105,32,61,32,48,59, +32,105,32,60,100,105,102,102,101,114,101,110,99,101,100,101,118,111,116,101,100, +32,116,111,116,114,97,100,105,116,105,111,110,115,115,101,97,114,99,104,32,102, +111,114,117,108,116,105,109,97,116,101,108,121,116,111,117,114,110,97,109,101, +110,116,97,116,116,114,105,98,117,116,101,115,115,111,45,99,97,108,108,101,100, +32,125,10,60,47,115,116,121,108,101,62,101,118,97,108,117,97,116,105,111,110,101 +,109,112,104,97,115,105,122,101,100,97,99,99,101,115,115,105,98,108,101,60,47, +115,101,99,116,105,111,110,62,115,117,99,99,101,115,115,105,111,110,97,108,111, +110,103,32,119,105,116,104,77,101,97,110,119,104,105,108,101,44,105,110,100,117, +115,116,114,105,101,115,60,47,97,62,60,98,114,32,47,62,104,97,115,32,98,101,99, +111,109,101,97,115,112,101,99,116,115,32,111,102,84,101,108,101,118,105,115,105, +111,110,115,117,102,102,105,99,105,101,110,116,98,97,115,107,101,116,98,97,108, +108,98,111,116,104,32,115,105,100,101,115,99,111,110,116,105,110,117,105,110,103 +,97,110,32,97,114,116,105,99,108,101,60,105,109,103,32,97,108,116,61,34,97,100, +118,101,110,116,117,114,101,115,104,105,115,32,109,111,116,104,101,114,109,97, +110,99,104,101,115,116,101,114,112,114,105,110,99,105,112,108,101,115,112,97,114 +,116,105,99,117,108,97,114,99,111,109,109,101,110,116,97,114,121,101,102,102,101 +,99,116,115,32,111,102,100,101,99,105,100,101,100,32,116,111,34,62,60,115,116, +114,111,110,103,62,112,117,98,108,105,115,104,101,114,115,74,111,117,114,110,97, +108,32,111,102,100,105,102,102,105,99,117,108,116,121,102,97,99,105,108,105,116, +97,116,101,97,99,99,101,112,116,97,98,108,101,115,116,121,108,101,46,99,115,115, +34,9,102,117,110,99,116,105,111,110,32,105,110,110,111,118,97,116,105,111,110,62 +,67,111,112,121,114,105,103,104,116,115,105,116,117,97,116,105,111,110,115,119, +111,117,108,100,32,104,97,118,101,98,117,115,105,110,101,115,115,101,115,68,105, +99,116,105,111,110,97,114,121,115,116,97,116,101,109,101,110,116,115,111,102,116 +,101,110,32,117,115,101,100,112,101,114,115,105,115,116,101,110,116,105,110,32, +74,97,110,117,97,114,121,99,111,109,112,114,105,115,105,110,103,60,47,116,105, +116,108,101,62,10,9,100,105,112,108,111,109,97,116,105,99,99,111,110,116,97,105, +110,105,110,103,112,101,114,102,111,114,109,105,110,103,101,120,116,101,110,115, +105,111,110,115,109,97,121,32,110,111,116,32,98,101,99,111,110,99,101,112,116,32 +,111,102,32,111,110,99,108,105,99,107,61,34,73,116,32,105,115,32,97,108,115,111, +102,105,110,97,110,99,105,97,108,32,109,97,107,105,110,103,32,116,104,101,76,117 +,120,101,109,98,111,117,114,103,97,100,100,105,116,105,111,110,97,108,97,114,101 +,32,99,97,108,108,101,100,101,110,103,97,103,101,100,32,105,110,34,115,99,114, +105,112,116,34,41,59,98,117,116,32,105,116,32,119,97,115,101,108,101,99,116,114, +111,110,105,99,111,110,115,117,98,109,105,116,61,34,10,60,33,45,45,32,69,110,100 +,32,101,108,101,99,116,114,105,99,97,108,111,102,102,105,99,105,97,108,108,121, +115,117,103,103,101,115,116,105,111,110,116,111,112,32,111,102,32,116,104,101, +117,110,108,105,107,101,32,116,104,101,65,117,115,116,114,97,108,105,97,110,79, +114,105,103,105,110,97,108,108,121,114,101,102,101,114,101,110,99,101,115,10,60, +47,104,101,97,100,62,13,10,114,101,99,111,103,110,105,115,101,100,105,110,105, +116,105,97,108,105,122,101,108,105,109,105,116,101,100,32,116,111,65,108,101,120 +,97,110,100,114,105,97,114,101,116,105,114,101,109,101,110,116,65,100,118,101, +110,116,117,114,101,115,102,111,117,114,32,121,101,97,114,115,10,10,38,108,116, +59,33,45,45,32,105,110,99,114,101,97,115,105,110,103,100,101,99,111,114,97,116, +105,111,110,104,51,32,99,108,97,115,115,61,34,111,114,105,103,105,110,115,32,111 +,102,111,98,108,105,103,97,116,105,111,110,114,101,103,117,108,97,116,105,111, +110,99,108,97,115,115,105,102,105,101,100,40,102,117,110,99,116,105,111,110,40, +97,100,118,97,110,116,97,103,101,115,98,101,105,110,103,32,116,104,101,32,104, +105,115,116,111,114,105,97,110,115,60,98,97,115,101,32,104,114,101,102,114,101, +112,101,97,116,101,100,108,121,119,105,108,108,105,110,103,32,116,111,99,111,109 +,112,97,114,97,98,108,101,100,101,115,105,103,110,97,116,101,100,110,111,109,105 +,110,97,116,105,111,110,102,117,110,99,116,105,111,110,97,108,105,110,115,105, +100,101,32,116,104,101,114,101,118,101,108,97,116,105,111,110,101,110,100,32,111 +,102,32,116,104,101,115,32,102,111,114,32,116,104,101,32,97,117,116,104,111,114, +105,122,101,100,114,101,102,117,115,101,100,32,116,111,116,97,107,101,32,112,108 +,97,99,101,97,117,116,111,110,111,109,111,117,115,99,111,109,112,114,111,109,105 +,115,101,112,111,108,105,116,105,99,97,108,32,114,101,115,116,97,117,114,97,110, +116,116,119,111,32,111,102,32,116,104,101,70,101,98,114,117,97,114,121,32,50,113 +,117,97,108,105,116,121,32,111,102,115,119,102,111,98,106,101,99,116,46,117,110, +100,101,114,115,116,97,110,100,110,101,97,114,108,121,32,97,108,108,119,114,105, +116,116,101,110,32,98,121,105,110,116,101,114,118,105,101,119,115,34,32,119,105, +100,116,104,61,34,49,119,105,116,104,100,114,97,119,97,108,102,108,111,97,116,58 +,108,101,102,116,105,115,32,117,115,117,97,108,108,121,99,97,110,100,105,100,97, +116,101,115,110,101,119,115,112,97,112,101,114,115,109,121,115,116,101,114,105, +111,117,115,68,101,112,97,114,116,109,101,110,116,98,101,115,116,32,107,110,111, +119,110,112,97,114,108,105,97,109,101,110,116,115,117,112,112,114,101,115,115, +101,100,99,111,110,118,101,110,105,101,110,116,114,101,109,101,109,98,101,114, +101,100,100,105,102,102,101,114,101,110,116,32,115,121,115,116,101,109,97,116, +105,99,104,97,115,32,108,101,100,32,116,111,112,114,111,112,97,103,97,110,100,97 +,99,111,110,116,114,111,108,108,101,100,105,110,102,108,117,101,110,99,101,115, +99,101,114,101,109,111,110,105,97,108,112,114,111,99,108,97,105,109,101,100,80, +114,111,116,101,99,116,105,111,110,108,105,32,99,108,97,115,115,61,34,83,99,105, +101,110,116,105,102,105,99,99,108,97,115,115,61,34,110,111,45,116,114,97,100,101 +,109,97,114,107,115,109,111,114,101,32,116,104,97,110,32,119,105,100,101,115,112 +,114,101,97,100,76,105,98,101,114,97,116,105,111,110,116,111,111,107,32,112,108, +97,99,101,100,97,121,32,111,102,32,116,104,101,97,115,32,108,111,110,103,32,97, +115,105,109,112,114,105,115,111,110,101,100,65,100,100,105,116,105,111,110,97, +108,10,60,104,101,97,100,62,10,60,109,76,97,98,111,114,97,116,111,114,121,78,111 +,118,101,109,98,101,114,32,50,101,120,99,101,112,116,105,111,110,115,73,110,100, +117,115,116,114,105,97,108,118,97,114,105,101,116,121,32,111,102,102,108,111,97, +116,58,32,108,101,102,68,117,114,105,110,103,32,116,104,101,97,115,115,101,115, +115,109,101,110,116,104,97,118,101,32,98,101,101,110,32,100,101,97,108,115,32, +119,105,116,104,83,116,97,116,105,115,116,105,99,115,111,99,99,117,114,114,101, +110,99,101,47,117,108,62,60,47,100,105,118,62,99,108,101,97,114,102,105,120,34, +62,116,104,101,32,112,117,98,108,105,99,109,97,110,121,32,121,101,97,114,115,119 +,104,105,99,104,32,119,101,114,101,111,118,101,114,32,116,105,109,101,44,115,121 +,110,111,110,121,109,111,117,115,99,111,110,116,101,110,116,34,62,10,112,114,101 +,115,117,109,97,98,108,121,104,105,115,32,102,97,109,105,108,121,117,115,101,114 +,65,103,101,110,116,46,117,110,101,120,112,101,99,116,101,100,105,110,99,108,117 +,100,105,110,103,32,99,104,97,108,108,101,110,103,101,100,97,32,109,105,110,111, +114,105,116,121,117,110,100,101,102,105,110,101,100,34,98,101,108,111,110,103, +115,32,116,111,116,97,107,101,110,32,102,114,111,109,105,110,32,79,99,116,111,98 +,101,114,112,111,115,105,116,105,111,110,58,32,115,97,105,100,32,116,111,32,98, +101,114,101,108,105,103,105,111,117,115,32,70,101,100,101,114,97,116,105,111,110 +,32,114,111,119,115,112,97,110,61,34,111,110,108,121,32,97,32,102,101,119,109, +101,97,110,116,32,116,104,97,116,108,101,100,32,116,111,32,116,104,101,45,45,62, +13,10,60,100,105,118,32,60,102,105,101,108,100,115,101,116,62,65,114,99,104,98, +105,115,104,111,112,32,99,108,97,115,115,61,34,110,111,98,101,105,110,103,32,117 +,115,101,100,97,112,112,114,111,97,99,104,101,115,112,114,105,118,105,108,101, +103,101,115,110,111,115,99,114,105,112,116,62,10,114,101,115,117,108,116,115,32, +105,110,109,97,121,32,98,101,32,116,104,101,69,97,115,116,101,114,32,101,103,103 +,109,101,99,104,97,110,105,115,109,115,114,101,97,115,111,110,97,98,108,101,80, +111,112,117,108,97,116,105,111,110,67,111,108,108,101,99,116,105,111,110,115,101 +,108,101,99,116,101,100,34,62,110,111,115,99,114,105,112,116,62,13,47,105,110, +100,101,120,46,112,104,112,97,114,114,105,118,97,108,32,111,102,45,106,115,115, +100,107,39,41,41,59,109,97,110,97,103,101,100,32,116,111,105,110,99,111,109,112, +108,101,116,101,99,97,115,117,97,108,116,105,101,115,99,111,109,112,108,101,116, +105,111,110,67,104,114,105,115,116,105,97,110,115,83,101,112,116,101,109,98,101, +114,32,97,114,105,116,104,109,101,116,105,99,112,114,111,99,101,100,117,114,101, +115,109,105,103,104,116,32,104,97,118,101,80,114,111,100,117,99,116,105,111,110, +105,116,32,97,112,112,101,97,114,115,80,104,105,108,111,115,111,112,104,121,102, +114,105,101,110,100,115,104,105,112,108,101,97,100,105,110,103,32,116,111,103, +105,118,105,110,103,32,116,104,101,116,111,119,97,114,100,32,116,104,101,103,117 +,97,114,97,110,116,101,101,100,100,111,99,117,109,101,110,116,101,100,99,111,108 +,111,114,58,35,48,48,48,118,105,100,101,111,32,103,97,109,101,99,111,109,109,105 +,115,115,105,111,110,114,101,102,108,101,99,116,105,110,103,99,104,97,110,103, +101,32,116,104,101,97,115,115,111,99,105,97,116,101,100,115,97,110,115,45,115, +101,114,105,102,111,110,107,101,121,112,114,101,115,115,59,32,112,97,100,100,105 +,110,103,58,72,101,32,119,97,115,32,116,104,101,117,110,100,101,114,108,121,105, +110,103,116,121,112,105,99,97,108,108,121,32,44,32,97,110,100,32,116,104,101,32, +115,114,99,69,108,101,109,101,110,116,115,117,99,99,101,115,115,105,118,101,115, +105,110,99,101,32,116,104,101,32,115,104,111,117,108,100,32,98,101,32,110,101, +116,119,111,114,107,105,110,103,97,99,99,111,117,110,116,105,110,103,117,115,101 +,32,111,102,32,116,104,101,108,111,119,101,114,32,116,104,97,110,115,104,111,119 +,115,32,116,104,97,116,60,47,115,112,97,110,62,10,9,9,99,111,109,112,108,97,105, +110,116,115,99,111,110,116,105,110,117,111,117,115,113,117,97,110,116,105,116, +105,101,115,97,115,116,114,111,110,111,109,101,114,104,101,32,100,105,100,32,110 +,111,116,100,117,101,32,116,111,32,105,116,115,97,112,112,108,105,101,100,32,116 +,111,97,110,32,97,118,101,114,97,103,101,101,102,102,111,114,116,115,32,116,111, +116,104,101,32,102,117,116,117,114,101,97,116,116,101,109,112,116,32,116,111,84, +104,101,114,101,102,111,114,101,44,99,97,112,97,98,105,108,105,116,121,82,101, +112,117,98,108,105,99,97,110,119,97,115,32,102,111,114,109,101,100,69,108,101,99 +,116,114,111,110,105,99,107,105,108,111,109,101,116,101,114,115,99,104,97,108, +108,101,110,103,101,115,112,117,98,108,105,115,104,105,110,103,116,104,101,32, +102,111,114,109,101,114,105,110,100,105,103,101,110,111,117,115,100,105,114,101, +99,116,105,111,110,115,115,117,98,115,105,100,105,97,114,121,99,111,110,115,112, +105,114,97,99,121,100,101,116,97,105,108,115,32,111,102,97,110,100,32,105,110,32 +,116,104,101,97,102,102,111,114,100,97,98,108,101,115,117,98,115,116,97,110,99, +101,115,114,101,97,115,111,110,32,102,111,114,99,111,110,118,101,110,116,105,111 +,110,105,116,101,109,116,121,112,101,61,34,97,98,115,111,108,117,116,101,108,121 +,115,117,112,112,111,115,101,100,108,121,114,101,109,97,105,110,101,100,32,97,97 +,116,116,114,97,99,116,105,118,101,116,114,97,118,101,108,108,105,110,103,115, +101,112,97,114,97,116,101,108,121,102,111,99,117,115,101,115,32,111,110,101,108, +101,109,101,110,116,97,114,121,97,112,112,108,105,99,97,98,108,101,102,111,117, +110,100,32,116,104,97,116,115,116,121,108,101,115,104,101,101,116,109,97,110,117 +,115,99,114,105,112,116,115,116,97,110,100,115,32,102,111,114,32,110,111,45,114, +101,112,101,97,116,40,115,111,109,101,116,105,109,101,115,67,111,109,109,101,114 +,99,105,97,108,105,110,32,65,109,101,114,105,99,97,117,110,100,101,114,116,97, +107,101,110,113,117,97,114,116,101,114,32,111,102,97,110,32,101,120,97,109,112, +108,101,112,101,114,115,111,110,97,108,108,121,105,110,100,101,120,46,112,104, +112,63,60,47,98,117,116,116,111,110,62,10,112,101,114,99,101,110,116,97,103,101, +98,101,115,116,45,107,110,111,119,110,99,114,101,97,116,105,110,103,32,97,34,32, +100,105,114,61,34,108,116,114,76,105,101,117,116,101,110,97,110,116,10,60,100, +105,118,32,105,100,61,34,116,104,101,121,32,119,111,117,108,100,97,98,105,108, +105,116,121,32,111,102,109,97,100,101,32,117,112,32,111,102,110,111,116,101,100, +32,116,104,97,116,99,108,101,97,114,32,116,104,97,116,97,114,103,117,101,32,116, +104,97,116,116,111,32,97,110,111,116,104,101,114,99,104,105,108,100,114,101,110, +39,115,112,117,114,112,111,115,101,32,111,102,102,111,114,109,117,108,97,116,101 +,100,98,97,115,101,100,32,117,112,111,110,116,104,101,32,114,101,103,105,111,110 +,115,117,98,106,101,99,116,32,111,102,112,97,115,115,101,110,103,101,114,115,112 +,111,115,115,101,115,115,105,111,110,46,10,10,73,110,32,116,104,101,32,66,101, +102,111,114,101,32,116,104,101,97,102,116,101,114,119,97,114,100,115,99,117,114, +114,101,110,116,108,121,32,97,99,114,111,115,115,32,116,104,101,115,99,105,101, +110,116,105,102,105,99,99,111,109,109,117,110,105,116,121,46,99,97,112,105,116, +97,108,105,115,109,105,110,32,71,101,114,109,97,110,121,114,105,103,104,116,45, +119,105,110,103,116,104,101,32,115,121,115,116,101,109,83,111,99,105,101,116,121 +,32,111,102,112,111,108,105,116,105,99,105,97,110,100,105,114,101,99,116,105,111 +,110,58,119,101,110,116,32,111,110,32,116,111,114,101,109,111,118,97,108,32,111, +102,32,78,101,119,32,89,111,114,107,32,97,112,97,114,116,109,101,110,116,115,105 +,110,100,105,99,97,116,105,111,110,100,117,114,105,110,103,32,116,104,101,117, +110,108,101,115,115,32,116,104,101,104,105,115,116,111,114,105,99,97,108,104,97, +100,32,98,101,101,110,32,97,100,101,102,105,110,105,116,105,118,101,105,110,103, +114,101,100,105,101,110,116,97,116,116,101,110,100,97,110,99,101,67,101,110,116, +101,114,32,102,111,114,112,114,111,109,105,110,101,110,99,101,114,101,97,100,121 +,83,116,97,116,101,115,116,114,97,116,101,103,105,101,115,98,117,116,32,105,110, +32,116,104,101,97,115,32,112,97,114,116,32,111,102,99,111,110,115,116,105,116, +117,116,101,99,108,97,105,109,32,116,104,97,116,108,97,98,111,114,97,116,111,114 +,121,99,111,109,112,97,116,105,98,108,101,102,97,105,108,117,114,101,32,111,102, +44,32,115,117,99,104,32,97,115,32,98,101,103,97,110,32,119,105,116,104,117,115, +105,110,103,32,116,104,101,32,116,111,32,112,114,111,118,105,100,101,102,101,97, +116,117,114,101,32,111,102,102,114,111,109,32,119,104,105,99,104,47,34,32,99,108 +,97,115,115,61,34,103,101,111,108,111,103,105,99,97,108,115,101,118,101,114,97, +108,32,111,102,100,101,108,105,98,101,114,97,116,101,105,109,112,111,114,116,97, +110,116,32,104,111,108,100,115,32,116,104,97,116,105,110,103,38,113,117,111,116, +59,32,118,97,108,105,103,110,61,116,111,112,116,104,101,32,71,101,114,109,97,110 +,111,117,116,115,105,100,101,32,111,102,110,101,103,111,116,105,97,116,101,100, +104,105,115,32,99,97,114,101,101,114,115,101,112,97,114,97,116,105,111,110,105, +100,61,34,115,101,97,114,99,104,119,97,115,32,99,97,108,108,101,100,116,104,101, +32,102,111,117,114,116,104,114,101,99,114,101,97,116,105,111,110,111,116,104,101 +,114,32,116,104,97,110,112,114,101,118,101,110,116,105,111,110,119,104,105,108, +101,32,116,104,101,32,101,100,117,99,97,116,105,111,110,44,99,111,110,110,101,99 +,116,105,110,103,97,99,99,117,114,97,116,101,108,121,119,101,114,101,32,98,117, +105,108,116,119,97,115,32,107,105,108,108,101,100,97,103,114,101,101,109,101,110 +,116,115,109,117,99,104,32,109,111,114,101,32,68,117,101,32,116,111,32,116,104, +101,119,105,100,116,104,58,32,49,48,48,115,111,109,101,32,111,116,104,101,114,75 +,105,110,103,100,111,109,32,111,102,116,104,101,32,101,110,116,105,114,101,102, +97,109,111,117,115,32,102,111,114,116,111,32,99,111,110,110,101,99,116,111,98, +106,101,99,116,105,118,101,115,116,104,101,32,70,114,101,110,99,104,112,101,111, +112,108,101,32,97,110,100,102,101,97,116,117,114,101,100,34,62,105,115,32,115,97 +,105,100,32,116,111,115,116,114,117,99,116,117,114,97,108,114,101,102,101,114, +101,110,100,117,109,109,111,115,116,32,111,102,116,101,110,97,32,115,101,112,97, +114,97,116,101,45,62,10,60,100,105,118,32,105,100,32,79,102,102,105,99,105,97, +108,32,119,111,114,108,100,119,105,100,101,46,97,114,105,97,45,108,97,98,101,108 +,116,104,101,32,112,108,97,110,101,116,97,110,100,32,105,116,32,119,97,115,100, +34,32,118,97,108,117,101,61,34,108,111,111,107,105,110,103,32,97,116,98,101,110, +101,102,105,99,105,97,108,97,114,101,32,105,110,32,116,104,101,109,111,110,105, +116,111,114,105,110,103,114,101,112,111,114,116,101,100,108,121,116,104,101,32, +109,111,100,101,114,110,119,111,114,107,105,110,103,32,111,110,97,108,108,111, +119,101,100,32,116,111,119,104,101,114,101,32,116,104,101,32,105,110,110,111,118 +,97,116,105,118,101,60,47,97,62,60,47,100,105,118,62,115,111,117,110,100,116,114 +,97,99,107,115,101,97,114,99,104,70,111,114,109,116,101,110,100,32,116,111,32,98 +,101,105,110,112,117,116,32,105,100,61,34,111,112,101,110,105,110,103,32,111,102 +,114,101,115,116,114,105,99,116,101,100,97,100,111,112,116,101,100,32,98,121,97, +100,100,114,101,115,115,105,110,103,116,104,101,111,108,111,103,105,97,110,109, +101,116,104,111,100,115,32,111,102,118,97,114,105,97,110,116,32,111,102,67,104, +114,105,115,116,105,97,110,32,118,101,114,121,32,108,97,114,103,101,97,117,116, +111,109,111,116,105,118,101,98,121,32,102,97,114,32,116,104,101,114,97,110,103, +101,32,102,114,111,109,112,117,114,115,117,105,116,32,111,102,102,111,108,108, +111,119,32,116,104,101,98,114,111,117,103,104,116,32,116,111,105,110,32,69,110, +103,108,97,110,100,97,103,114,101,101,32,116,104,97,116,97,99,99,117,115,101,100 +,32,111,102,99,111,109,101,115,32,102,114,111,109,112,114,101,118,101,110,116, +105,110,103,100,105,118,32,115,116,121,108,101,61,104,105,115,32,111,114,32,104, +101,114,116,114,101,109,101,110,100,111,117,115,102,114,101,101,100,111,109,32, +111,102,99,111,110,99,101,114,110,105,110,103,48,32,49,101,109,32,49,101,109,59, +66,97,115,107,101,116,98,97,108,108,47,115,116,121,108,101,46,99,115,115,97,110, +32,101,97,114,108,105,101,114,101,118,101,110,32,97,102,116,101,114,47,34,32,116 +,105,116,108,101,61,34,46,99,111,109,47,105,110,100,101,120,116,97,107,105,110, +103,32,116,104,101,112,105,116,116,115,98,117,114,103,104,99,111,110,116,101,110 +,116,34,62,13,60,115,99,114,105,112,116,62,40,102,116,117,114,110,101,100,32,111 +,117,116,104,97,118,105,110,103,32,116,104,101,60,47,115,112,97,110,62,13,10,32, +111,99,99,97,115,105,111,110,97,108,98,101,99,97,117,115,101,32,105,116,115,116, +97,114,116,101,100,32,116,111,112,104,121,115,105,99,97,108,108,121,62,60,47,100 +,105,118,62,10,32,32,99,114,101,97,116,101,100,32,98,121,67,117,114,114,101,110, +116,108,121,44,32,98,103,99,111,108,111,114,61,34,116,97,98,105,110,100,101,120, +61,34,100,105,115,97,115,116,114,111,117,115,65,110,97,108,121,116,105,99,115,32 +,97,108,115,111,32,104,97,115,32,97,62,60,100,105,118,32,105,100,61,34,60,47,115 +,116,121,108,101,62,10,60,99,97,108,108,101,100,32,102,111,114,115,105,110,103, +101,114,32,97,110,100,46,115,114,99,32,61,32,34,47,47,118,105,111,108,97,116,105 +,111,110,115,116,104,105,115,32,112,111,105,110,116,99,111,110,115,116,97,110, +116,108,121,105,115,32,108,111,99,97,116,101,100,114,101,99,111,114,100,105,110, +103,115,100,32,102,114,111,109,32,116,104,101,110,101,100,101,114,108,97,110,100 +,115,112,111,114,116,117,103,117,195,170,115,215,162,215,145,215,168,215,153,215 +,170,217,129,216,167,216,177,216,179,219,140,100,101,115,97,114,114,111,108,108, +111,99,111,109,101,110,116,97,114,105,111,101,100,117,99,97,99,105,195,179,110, +115,101,112,116,105,101,109,98,114,101,114,101,103,105,115,116,114,97,100,111, +100,105,114,101,99,99,105,195,179,110,117,98,105,99,97,99,105,195,179,110,112, +117,98,108,105,99,105,100,97,100,114,101,115,112,117,101,115,116,97,115,114,101, +115,117,108,116,97,100,111,115,105,109,112,111,114,116,97,110,116,101,114,101, +115,101,114,118,97,100,111,115,97,114,116,195,173,99,117,108,111,115,100,105,102 +,101,114,101,110,116,101,115,115,105,103,117,105,101,110,116,101,115,114,101,112 +,195,186,98,108,105,99,97,115,105,116,117,97,99,105,195,179,110,109,105,110,105, +115,116,101,114,105,111,112,114,105,118,97,99,105,100,97,100,100,105,114,101,99, +116,111,114,105,111,102,111,114,109,97,99,105,195,179,110,112,111,98,108,97,99, +105,195,179,110,112,114,101,115,105,100,101,110,116,101,99,111,110,116,101,110, +105,100,111,115,97,99,99,101,115,111,114,105,111,115,116,101,99,104,110,111,114, +97,116,105,112,101,114,115,111,110,97,108,101,115,99,97,116,101,103,111,114,195, +173,97,101,115,112,101,99,105,97,108,101,115,100,105,115,112,111,110,105,98,108, +101,97,99,116,117,97,108,105,100,97,100,114,101,102,101,114,101,110,99,105,97, +118,97,108,108,97,100,111,108,105,100,98,105,98,108,105,111,116,101,99,97,114, +101,108,97,99,105,111,110,101,115,99,97,108,101,110,100,97,114,105,111,112,111, +108,195,173,116,105,99,97,115,97,110,116,101,114,105,111,114,101,115,100,111,99, +117,109,101,110,116,111,115,110,97,116,117,114,97,108,101,122,97,109,97,116,101, +114,105,97,108,101,115,100,105,102,101,114,101,110,99,105,97,101,99,111,110,195, +179,109,105,99,97,116,114,97,110,115,112,111,114,116,101,114,111,100,114,195,173 +,103,117,101,122,112,97,114,116,105,99,105,112,97,114,101,110,99,117,101,110,116 +,114,97,110,100,105,115,99,117,115,105,195,179,110,101,115,116,114,117,99,116, +117,114,97,102,117,110,100,97,99,105,195,179,110,102,114,101,99,117,101,110,116, +101,115,112,101,114,109,97,110,101,110,116,101,116,111,116,97,108,109,101,110, +116,101,208,188,208,190,208,182,208,189,208,190,208,177,209,131,208,180,208,181, +209,130,208,188,208,190,208,182,208,181,209,130,208,178,209,128,208,181,208,188, +209,143,209,130,208,176,208,186,208,182,208,181,209,135,209,130,208,190,208,177, +209,139,208,177,208,190,208,187,208,181,208,181,208,190,209,135,208,181,208,189, +209,140,209,141,209,130,208,190,208,179,208,190,208,186,208,190,208,179,208,180, +208,176,208,191,208,190,209,129,208,187,208,181,208,178,209,129,208,181,208,179, +208,190,209,129,208,176,208,185,209,130,208,181,209,135,208,181,209,128,208,181, +208,183,208,188,208,190,208,179,209,131,209,130,209,129,208,176,208,185,209,130, +208,176,208,182,208,184,208,183,208,189,208,184,208,188,208,181,208,182,208,180, +209,131,208,177,209,131,208,180,209,131,209,130,208,159,208,190,208,184,209,129, +208,186,208,183,208,180,208,181,209,129,209,140,208,178,208,184,208,180,208,181, +208,190,209,129,208,178,209,143,208,183,208,184,208,189,209,131,208,182,208,189, +208,190,209,129,208,178,208,190,208,181,208,185,208,187,209,142,208,180,208,181, +208,185,208,191,208,190,209,128,208,189,208,190,208,188,208,189,208,190,208,179, +208,190,208,180,208,181,209,130,208,181,208,185,209,129,208,178,208,190,208,184, +209,133,208,191,209,128,208,176,208,178,208,176,209,130,208,176,208,186,208,190, +208,185,208,188,208,181,209,129,209,130,208,190,208,184,208,188,208,181,208,181, +209,130,208,182,208,184,208,183,208,189,209,140,208,190,208,180,208,189,208,190, +208,185,208,187,209,131,209,135,209,136,208,181,208,191,208,181,209,128,208,181, +208,180,209,135,208,176,209,129,209,130,208,184,209,135,208,176,209,129,209,130, +209,140,209,128,208,176,208,177,208,190,209,130,208,189,208,190,208,178,209,139, +209,133,208,191,209,128,208,176,208,178,208,190,209,129,208,190,208,177,208,190, +208,185,208,191,208,190,209,130,208,190,208,188,208,188,208,181,208,189,208,181, +208,181,209,135,208,184,209,129,208,187,208,181,208,189,208,190,208,178,209,139, +208,181,209,131,209,129,208,187,209,131,208,179,208,190,208,186,208,190,208,187, +208,190,208,189,208,176,208,183,208,176,208,180,209,130,208,176,208,186,208,190, +208,181,209,130,208,190,208,179,208,180,208,176,208,191,208,190,209,135,209,130, +208,184,208,159,208,190,209,129,208,187,208,181,209,130,208,176,208,186,208,184, +208,181,208,189,208,190,208,178,209,139,208,185,209,129,209,130,208,190,208,184, +209,130,209,130,208,176,208,186,208,184,209,133,209,129,209,128,208,176,208,183, +209,131,208,161,208,176,208,189,208,186,209,130,209,132,208,190,209,128,209,131, +208,188,208,154,208,190,208,179,208,180,208,176,208,186,208,189,208,184,208,179, +208,184,209,129,208,187,208,190,208,178,208,176,208,189,208,176,209,136,208,181, +208,185,208,189,208,176,208,185,209,130,208,184,209,129,208,178,208,190,208,184, +208,188,209,129,208,178,209,143,208,183,209,140,208,187,209,142,208,177,208,190, +208,185,209,135,208,176,209,129,209,130,208,190,209,129,209,128,208,181,208,180, +208,184,208,154,209,128,208,190,208,188,208,181,208,164,208,190,209,128,209,131, +208,188,209,128,209,139,208,189,208,186,208,181,209,129,209,130,208,176,208,187, +208,184,208,191,208,190,208,184,209,129,208,186,209,130,209,139,209,129,209,143, +209,135,208,188,208,181,209,129,209,143,209,134,209,134,208,181,208,189,209,130, +209,128,209,130,209,128,209,131,208,180,208,176,209,129,208,176,208,188,209,139, +209,133,209,128,209,139,208,189,208,186,208,176,208,157,208,190,208,178,209,139, +208,185,209,135,208,176,209,129,208,190,208,178,208,188,208,181,209,129,209,130, +208,176,209,132,208,184,208,187,209,140,208,188,208,188,208,176,209,128,209,130, +208,176,209,129,209,130,209,128,208,176,208,189,208,188,208,181,209,129,209,130, +208,181,209,130,208,181,208,186,209,129,209,130,208,189,208,176,209,136,208,184, +209,133,208,188,208,184,208,189,209,131,209,130,208,184,208,188,208,181,208,189, +208,184,208,184,208,188,208,181,209,142,209,130,208,189,208,190,208,188,208,181, +209,128,208,179,208,190,209,128,208,190,208,180,209,129,208,176,208,188,208,190, +208,188,209,141,209,130,208,190,208,188,209,131,208,186,208,190,208,189,209,134, +208,181,209,129,208,178,208,190,208,181,208,188,208,186,208,176,208,186,208,190, +208,185,208,144,209,128,209,133,208,184,208,178,217,133,217,134,216,170,216,175, +217,137,216,165,216,177,216,179,216,167,217,132,216,177,216,179,216,167,217,132, +216,169,216,167,217,132,216,185,216,167,217,133,217,131,216,170,216,168,217,135, +216,167,216,168,216,177,216,167,217,133,216,172,216,167,217,132,217,138,217,136, +217,133,216,167,217,132,216,181,217,136,216,177,216,172,216,175,217,138,216,175, +216,169,216,167,217,132,216,185,216,182,217,136,216,165,216,182,216,167,217,129, +216,169,216,167,217,132,217,130,216,179,217,133,216,167,217,132,216,185,216,167, +216,168,216,170,216,173,217,133,217,138,217,132,217,133,217,132,217,129,216,167, +216,170,217,133,217,132,216,170,217,130,217,137,216,170,216,185,216,175,217,138, +217,132,216,167,217,132,216,180,216,185,216,177,216,163,216,174,216,168,216,167, +216,177,216,170,216,183,217,136,217,138,216,177,216,185,217,132,217,138,217,131, +217,133,216,165,216,177,217,129,216,167,217,130,216,183,217,132,216,168,216,167, +216,170,216,167,217,132,217,132,216,186,216,169,216,170,216,177,216,170,217,138, +216,168,216,167,217,132,217,134,216,167,216,179,216,167,217,132,216,180,217,138, +216,174,217,133,217,134,216,170,216,175,217,138,216,167,217,132,216,185,216,177, +216,168,216,167,217,132,217,130,216,181,216,181,216,167,217,129,217,132,216,167, +217,133,216,185,217,132,217,138,217,135,216,167,216,170,216,173,216,175,217,138, +216,171,216,167,217,132,217,132,217,135,217,133,216,167,217,132,216,185,217,133, +217,132,217,133,217,131,216,170,216,168,216,169,217,138,217,133,217,131,217,134, +217,131,216,167,217,132,216,183,217,129,217,132,217,129,217,138,216,175,217,138, +217,136,216,165,216,175,216,167,216,177,216,169,216,170,216,167,216,177,217,138, +216,174,216,167,217,132,216,181,216,173,216,169,216,170,216,179,216,172,217,138, +217,132,216,167,217,132,217,136,217,130,216,170,216,185,217,134,216,175,217,133, +216,167,217,133,216,175,217,138,217,134,216,169,216,170,216,181,217,133,217,138, +217,133,216,163,216,177,216,180,217,138,217,129,216,167,217,132,216,176,217,138, +217,134,216,185,216,177,216,168,217,138,216,169,216,168,217,136,216,167,216,168, +216,169,216,163,217,132,216,185,216,167,216,168,216,167,217,132,216,179,217,129, +216,177,217,133,216,180,216,167,217,131,217,132,216,170,216,185,216,167,217,132, +217,137,216,167,217,132,216,163,217,136,217,132,216,167,217,132,216,179,217,134, +216,169,216,172,216,167,217,133,216,185,216,169,216,167,217,132,216,181,216,173, +217,129,216,167,217,132,216,175,217,138,217,134,217,131,217,132,217,133,216,167, +216,170,216,167,217,132,216,174,216,167,216,181,216,167,217,132,217,133,217,132, +217,129,216,163,216,185,216,182,216,167,216,161,217,131,216,170,216,167,216,168, +216,169,216,167,217,132,216,174,217,138,216,177,216,177,216,179,216,167,216,166, +217,132,216,167,217,132,217,130,217,132,216,168,216,167,217,132,216,163,216,175, +216,168,217,133,217,130,216,167,216,183,216,185,217,133,216,177,216,167,216,179, +217,132,217,133,217,134,216,183,217,130,216,169,216,167,217,132,217,131,216,170, +216,168,216,167,217,132,216,177,216,172,217,132,216,167,216,180,216,170,216,177, +217,131,216,167,217,132,217,130,216,175,217,133,217,138,216,185,216,183,217,138, +217,131,115,66,121,84,97,103,78,97,109,101,40,46,106,112,103,34,32,97,108,116,61 +,34,49,112,120,32,115,111,108,105,100,32,35,46,103,105,102,34,32,97,108,116,61, +34,116,114,97,110,115,112,97,114,101,110,116,105,110,102,111,114,109,97,116,105, +111,110,97,112,112,108,105,99,97,116,105,111,110,34,32,111,110,99,108,105,99,107 +,61,34,101,115,116,97,98,108,105,115,104,101,100,97,100,118,101,114,116,105,115, +105,110,103,46,112,110,103,34,32,97,108,116,61,34,101,110,118,105,114,111,110, +109,101,110,116,112,101,114,102,111,114,109,97,110,99,101,97,112,112,114,111,112 +,114,105,97,116,101,38,97,109,112,59,109,100,97,115,104,59,105,109,109,101,100, +105,97,116,101,108,121,60,47,115,116,114,111,110,103,62,60,47,114,97,116,104,101 +,114,32,116,104,97,110,116,101,109,112,101,114,97,116,117,114,101,100,101,118, +101,108,111,112,109,101,110,116,99,111,109,112,101,116,105,116,105,111,110,112, +108,97,99,101,104,111,108,100,101,114,118,105,115,105,98,105,108,105,116,121,58, +99,111,112,121,114,105,103,104,116,34,62,48,34,32,104,101,105,103,104,116,61,34, +101,118,101,110,32,116,104,111,117,103,104,114,101,112,108,97,99,101,109,101,110 +,116,100,101,115,116,105,110,97,116,105,111,110,67,111,114,112,111,114,97,116, +105,111,110,60,117,108,32,99,108,97,115,115,61,34,65,115,115,111,99,105,97,116, +105,111,110,105,110,100,105,118,105,100,117,97,108,115,112,101,114,115,112,101, +99,116,105,118,101,115,101,116,84,105,109,101,111,117,116,40,117,114,108,40,104, +116,116,112,58,47,47,109,97,116,104,101,109,97,116,105,99,115,109,97,114,103,105 +,110,45,116,111,112,58,101,118,101,110,116,117,97,108,108,121,32,100,101,115,99, +114,105,112,116,105,111,110,41,32,110,111,45,114,101,112,101,97,116,99,111,108, +108,101,99,116,105,111,110,115,46,74,80,71,124,116,104,117,109,98,124,112,97,114 +,116,105,99,105,112,97,116,101,47,104,101,97,100,62,60,98,111,100,121,102,108, +111,97,116,58,108,101,102,116,59,60,108,105,32,99,108,97,115,115,61,34,104,117, +110,100,114,101,100,115,32,111,102,10,10,72,111,119,101,118,101,114,44,32,99,111 +,109,112,111,115,105,116,105,111,110,99,108,101,97,114,58,98,111,116,104,59,99, +111,111,112,101,114,97,116,105,111,110,119,105,116,104,105,110,32,116,104,101,32 +,108,97,98,101,108,32,102,111,114,61,34,98,111,114,100,101,114,45,116,111,112,58 +,78,101,119,32,90,101,97,108,97,110,100,114,101,99,111,109,109,101,110,100,101, +100,112,104,111,116,111,103,114,97,112,104,121,105,110,116,101,114,101,115,116, +105,110,103,38,108,116,59,115,117,112,38,103,116,59,99,111,110,116,114,111,118, +101,114,115,121,78,101,116,104,101,114,108,97,110,100,115,97,108,116,101,114,110 +,97,116,105,118,101,109,97,120,108,101,110,103,116,104,61,34,115,119,105,116,122 +,101,114,108,97,110,100,68,101,118,101,108,111,112,109,101,110,116,101,115,115, +101,110,116,105,97,108,108,121,10,10,65,108,116,104,111,117,103,104,32,60,47,116 +,101,120,116,97,114,101,97,62,116,104,117,110,100,101,114,98,105,114,100,114,101 +,112,114,101,115,101,110,116,101,100,38,97,109,112,59,110,100,97,115,104,59,115, +112,101,99,117,108,97,116,105,111,110,99,111,109,109,117,110,105,116,105,101,115 +,108,101,103,105,115,108,97,116,105,111,110,101,108,101,99,116,114,111,110,105, +99,115,10,9,60,100,105,118,32,105,100,61,34,105,108,108,117,115,116,114,97,116, +101,100,101,110,103,105,110,101,101,114,105,110,103,116,101,114,114,105,116,111, +114,105,101,115,97,117,116,104,111,114,105,116,105,101,115,100,105,115,116,114, +105,98,117,116,101,100,54,34,32,104,101,105,103,104,116,61,34,115,97,110,115,45, +115,101,114,105,102,59,99,97,112,97,98,108,101,32,111,102,32,100,105,115,97,112, +112,101,97,114,101,100,105,110,116,101,114,97,99,116,105,118,101,108,111,111,107 +,105,110,103,32,102,111,114,105,116,32,119,111,117,108,100,32,98,101,65,102,103, +104,97,110,105,115,116,97,110,119,97,115,32,99,114,101,97,116,101,100,77,97,116, +104,46,102,108,111,111,114,40,115,117,114,114,111,117,110,100,105,110,103,99,97, +110,32,97,108,115,111,32,98,101,111,98,115,101,114,118,97,116,105,111,110,109,97 +,105,110,116,101,110,97,110,99,101,101,110,99,111,117,110,116,101,114,101,100,60 +,104,50,32,99,108,97,115,115,61,34,109,111,114,101,32,114,101,99,101,110,116,105 +,116,32,104,97,115,32,98,101,101,110,105,110,118,97,115,105,111,110,32,111,102, +41,46,103,101,116,84,105,109,101,40,41,102,117,110,100,97,109,101,110,116,97,108 +,68,101,115,112,105,116,101,32,116,104,101,34,62,60,100,105,118,32,105,100,61,34 +,105,110,115,112,105,114,97,116,105,111,110,101,120,97,109,105,110,97,116,105, +111,110,112,114,101,112,97,114,97,116,105,111,110,101,120,112,108,97,110,97,116, +105,111,110,60,105,110,112,117,116,32,105,100,61,34,60,47,97,62,60,47,115,112,97 +,110,62,118,101,114,115,105,111,110,115,32,111,102,105,110,115,116,114,117,109, +101,110,116,115,98,101,102,111,114,101,32,116,104,101,32,32,61,32,39,104,116,116 +,112,58,47,47,68,101,115,99,114,105,112,116,105,111,110,114,101,108,97,116,105, +118,101,108,121,32,46,115,117,98,115,116,114,105,110,103,40,101,97,99,104,32,111 +,102,32,116,104,101,101,120,112,101,114,105,109,101,110,116,115,105,110,102,108, +117,101,110,116,105,97,108,105,110,116,101,103,114,97,116,105,111,110,109,97,110 +,121,32,112,101,111,112,108,101,100,117,101,32,116,111,32,116,104,101,32,99,111, +109,98,105,110,97,116,105,111,110,100,111,32,110,111,116,32,104,97,118,101,77, +105,100,100,108,101,32,69,97,115,116,60,110,111,115,99,114,105,112,116,62,60,99, +111,112,121,114,105,103,104,116,34,32,112,101,114,104,97,112,115,32,116,104,101, +105,110,115,116,105,116,117,116,105,111,110,105,110,32,68,101,99,101,109,98,101, +114,97,114,114,97,110,103,101,109,101,110,116,109,111,115,116,32,102,97,109,111, +117,115,112,101,114,115,111,110,97,108,105,116,121,99,114,101,97,116,105,111,110 +,32,111,102,108,105,109,105,116,97,116,105,111,110,115,101,120,99,108,117,115, +105,118,101,108,121,115,111,118,101,114,101,105,103,110,116,121,45,99,111,110, +116,101,110,116,34,62,10,60,116,100,32,99,108,97,115,115,61,34,117,110,100,101, +114,103,114,111,117,110,100,112,97,114,97,108,108,101,108,32,116,111,100,111,99, +116,114,105,110,101,32,111,102,111,99,99,117,112,105,101,100,32,98,121,116,101, +114,109,105,110,111,108,111,103,121,82,101,110,97,105,115,115,97,110,99,101,97, +32,110,117,109,98,101,114,32,111,102,115,117,112,112,111,114,116,32,102,111,114, +101,120,112,108,111,114,97,116,105,111,110,114,101,99,111,103,110,105,116,105, +111,110,112,114,101,100,101,99,101,115,115,111,114,60,105,109,103,32,115,114,99, +61,34,47,60,104,49,32,99,108,97,115,115,61,34,112,117,98,108,105,99,97,116,105, +111,110,109,97,121,32,97,108,115,111,32,98,101,115,112,101,99,105,97,108,105,122 +,101,100,60,47,102,105,101,108,100,115,101,116,62,112,114,111,103,114,101,115, +115,105,118,101,109,105,108,108,105,111,110,115,32,111,102,115,116,97,116,101, +115,32,116,104,97,116,101,110,102,111,114,99,101,109,101,110,116,97,114,111,117, +110,100,32,116,104,101,32,111,110,101,32,97,110,111,116,104,101,114,46,112,97, +114,101,110,116,78,111,100,101,97,103,114,105,99,117,108,116,117,114,101,65,108, +116,101,114,110,97,116,105,118,101,114,101,115,101,97,114,99,104,101,114,115,116 +,111,119,97,114,100,115,32,116,104,101,77,111,115,116,32,111,102,32,116,104,101, +109,97,110,121,32,111,116,104,101,114,32,40,101,115,112,101,99,105,97,108,108, +121,60,116,100,32,119,105,100,116,104,61,34,59,119,105,100,116,104,58,49,48,48, +37,105,110,100,101,112,101,110,100,101,110,116,60,104,51,32,99,108,97,115,115,61 +,34,32,111,110,99,104,97,110,103,101,61,34,41,46,97,100,100,67,108,97,115,115,40 +,105,110,116,101,114,97,99,116,105,111,110,79,110,101,32,111,102,32,116,104,101, +32,100,97,117,103,104,116,101,114,32,111,102,97,99,99,101,115,115,111,114,105, +101,115,98,114,97,110,99,104,101,115,32,111,102,13,10,60,100,105,118,32,105,100, +61,34,116,104,101,32,108,97,114,103,101,115,116,100,101,99,108,97,114,97,116,105 +,111,110,114,101,103,117,108,97,116,105,111,110,115,73,110,102,111,114,109,97, +116,105,111,110,116,114,97,110,115,108,97,116,105,111,110,100,111,99,117,109,101 +,110,116,97,114,121,105,110,32,111,114,100,101,114,32,116,111,34,62,10,60,104, +101,97,100,62,10,60,34,32,104,101,105,103,104,116,61,34,49,97,99,114,111,115,115 +,32,116,104,101,32,111,114,105,101,110,116,97,116,105,111,110,41,59,60,47,115,99 +,114,105,112,116,62,105,109,112,108,101,109,101,110,116,101,100,99,97,110,32,98, +101,32,115,101,101,110,116,104,101,114,101,32,119,97,115,32,97,100,101,109,111, +110,115,116,114,97,116,101,99,111,110,116,97,105,110,101,114,34,62,99,111,110, +110,101,99,116,105,111,110,115,116,104,101,32,66,114,105,116,105,115,104,119,97, +115,32,119,114,105,116,116,101,110,33,105,109,112,111,114,116,97,110,116,59,112, +120,59,32,109,97,114,103,105,110,45,102,111,108,108,111,119,101,100,32,98,121,97 +,98,105,108,105,116,121,32,116,111,32,99,111,109,112,108,105,99,97,116,101,100, +100,117,114,105,110,103,32,116,104,101,32,105,109,109,105,103,114,97,116,105,111 +,110,97,108,115,111,32,99,97,108,108,101,100,60,104,52,32,99,108,97,115,115,61, +34,100,105,115,116,105,110,99,116,105,111,110,114,101,112,108,97,99,101,100,32, +98,121,103,111,118,101,114,110,109,101,110,116,115,108,111,99,97,116,105,111,110 +,32,111,102,105,110,32,78,111,118,101,109,98,101,114,119,104,101,116,104,101,114 +,32,116,104,101,60,47,112,62,10,60,47,100,105,118,62,97,99,113,117,105,115,105, +116,105,111,110,99,97,108,108,101,100,32,116,104,101,32,112,101,114,115,101,99, +117,116,105,111,110,100,101,115,105,103,110,97,116,105,111,110,123,102,111,110, +116,45,115,105,122,101,58,97,112,112,101,97,114,101,100,32,105,110,105,110,118, +101,115,116,105,103,97,116,101,101,120,112,101,114,105,101,110,99,101,100,109, +111,115,116,32,108,105,107,101,108,121,119,105,100,101,108,121,32,117,115,101, +100,100,105,115,99,117,115,115,105,111,110,115,112,114,101,115,101,110,99,101,32 +,111,102,32,40,100,111,99,117,109,101,110,116,46,101,120,116,101,110,115,105,118 +,101,108,121,73,116,32,104,97,115,32,98,101,101,110,105,116,32,100,111,101,115, +32,110,111,116,99,111,110,116,114,97,114,121,32,116,111,105,110,104,97,98,105, +116,97,110,116,115,105,109,112,114,111,118,101,109,101,110,116,115,99,104,111, +108,97,114,115,104,105,112,99,111,110,115,117,109,112,116,105,111,110,105,110, +115,116,114,117,99,116,105,111,110,102,111,114,32,101,120,97,109,112,108,101,111 +,110,101,32,111,114,32,109,111,114,101,112,120,59,32,112,97,100,100,105,110,103, +116,104,101,32,99,117,114,114,101,110,116,97,32,115,101,114,105,101,115,32,111, +102,97,114,101,32,117,115,117,97,108,108,121,114,111,108,101,32,105,110,32,116, +104,101,112,114,101,118,105,111,117,115,108,121,32,100,101,114,105,118,97,116, +105,118,101,115,101,118,105,100,101,110,99,101,32,111,102,101,120,112,101,114, +105,101,110,99,101,115,99,111,108,111,114,115,99,104,101,109,101,115,116,97,116, +101,100,32,116,104,97,116,99,101,114,116,105,102,105,99,97,116,101,60,47,97,62, +60,47,100,105,118,62,10,32,115,101,108,101,99,116,101,100,61,34,104,105,103,104, +32,115,99,104,111,111,108,114,101,115,112,111,110,115,101,32,116,111,99,111,109, +102,111,114,116,97,98,108,101,97,100,111,112,116,105,111,110,32,111,102,116,104, +114,101,101,32,121,101,97,114,115,116,104,101,32,99,111,117,110,116,114,121,105, +110,32,70,101,98,114,117,97,114,121,115,111,32,116,104,97,116,32,116,104,101,112 +,101,111,112,108,101,32,119,104,111,32,112,114,111,118,105,100,101,100,32,98,121 +,60,112,97,114,97,109,32,110,97,109,101,97,102,102,101,99,116,101,100,32,98,121, +105,110,32,116,101,114,109,115,32,111,102,97,112,112,111,105,110,116,109,101,110 +,116,73,83,79,45,56,56,53,57,45,49,34,119,97,115,32,98,111,114,110,32,105,110, +104,105,115,116,111,114,105,99,97,108,32,114,101,103,97,114,100,101,100,32,97, +115,109,101,97,115,117,114,101,109,101,110,116,105,115,32,98,97,115,101,100,32, +111,110,32,97,110,100,32,111,116,104,101,114,32,58,32,102,117,110,99,116,105,111 +,110,40,115,105,103,110,105,102,105,99,97,110,116,99,101,108,101,98,114,97,116, +105,111,110,116,114,97,110,115,109,105,116,116,101,100,47,106,115,47,106,113,117 +,101,114,121,46,105,115,32,107,110,111,119,110,32,97,115,116,104,101,111,114,101 +,116,105,99,97,108,32,116,97,98,105,110,100,101,120,61,34,105,116,32,99,111,117, +108,100,32,98,101,60,110,111,115,99,114,105,112,116,62,10,104,97,118,105,110,103 +,32,98,101,101,110,13,10,60,104,101,97,100,62,13,10,60,32,38,113,117,111,116,59, +84,104,101,32,99,111,109,112,105,108,97,116,105,111,110,104,101,32,104,97,100,32 +,98,101,101,110,112,114,111,100,117,99,101,100,32,98,121,112,104,105,108,111,115 +,111,112,104,101,114,99,111,110,115,116,114,117,99,116,101,100,105,110,116,101, +110,100,101,100,32,116,111,97,109,111,110,103,32,111,116,104,101,114,99,111,109, +112,97,114,101,100,32,116,111,116,111,32,115,97,121,32,116,104,97,116,69,110,103 +,105,110,101,101,114,105,110,103,97,32,100,105,102,102,101,114,101,110,116,114, +101,102,101,114,114,101,100,32,116,111,100,105,102,102,101,114,101,110,99,101, +115,98,101,108,105,101,102,32,116,104,97,116,112,104,111,116,111,103,114,97,112, +104,115,105,100,101,110,116,105,102,121,105,110,103,72,105,115,116,111,114,121, +32,111,102,32,82,101,112,117,98,108,105,99,32,111,102,110,101,99,101,115,115,97, +114,105,108,121,112,114,111,98,97,98,105,108,105,116,121,116,101,99,104,110,105, +99,97,108,108,121,108,101,97,118,105,110,103,32,116,104,101,115,112,101,99,116, +97,99,117,108,97,114,102,114,97,99,116,105,111,110,32,111,102,101,108,101,99,116 +,114,105,99,105,116,121,104,101,97,100,32,111,102,32,116,104,101,114,101,115,116 +,97,117,114,97,110,116,115,112,97,114,116,110,101,114,115,104,105,112,101,109, +112,104,97,115,105,115,32,111,110,109,111,115,116,32,114,101,99,101,110,116,115, +104,97,114,101,32,119,105,116,104,32,115,97,121,105,110,103,32,116,104,97,116, +102,105,108,108,101,100,32,119,105,116,104,100,101,115,105,103,110,101,100,32, +116,111,105,116,32,105,115,32,111,102,116,101,110,34,62,60,47,105,102,114,97,109 +,101,62,97,115,32,102,111,108,108,111,119,115,58,109,101,114,103,101,100,32,119, +105,116,104,116,104,114,111,117,103,104,32,116,104,101,99,111,109,109,101,114,99 +,105,97,108,32,112,111,105,110,116,101,100,32,111,117,116,111,112,112,111,114, +116,117,110,105,116,121,118,105,101,119,32,111,102,32,116,104,101,114,101,113, +117,105,114,101,109,101,110,116,100,105,118,105,115,105,111,110,32,111,102,112, +114,111,103,114,97,109,109,105,110,103,104,101,32,114,101,99,101,105,118,101,100 +,115,101,116,73,110,116,101,114,118,97,108,34,62,60,47,115,112,97,110,62,60,47, +105,110,32,78,101,119,32,89,111,114,107,97,100,100,105,116,105,111,110,97,108,32 +,99,111,109,112,114,101,115,115,105,111,110,10,10,60,100,105,118,32,105,100,61, +34,105,110,99,111,114,112,111,114,97,116,101,59,60,47,115,99,114,105,112,116,62, +60,97,116,116,97,99,104,69,118,101,110,116,98,101,99,97,109,101,32,116,104,101, +32,34,32,116,97,114,103,101,116,61,34,95,99,97,114,114,105,101,100,32,111,117, +116,83,111,109,101,32,111,102,32,116,104,101,115,99,105,101,110,99,101,32,97,110 +,100,116,104,101,32,116,105,109,101,32,111,102,67,111,110,116,97,105,110,101,114 +,34,62,109,97,105,110,116,97,105,110,105,110,103,67,104,114,105,115,116,111,112, +104,101,114,77,117,99,104,32,111,102,32,116,104,101,119,114,105,116,105,110,103, +115,32,111,102,34,32,104,101,105,103,104,116,61,34,50,115,105,122,101,32,111,102 +,32,116,104,101,118,101,114,115,105,111,110,32,111,102,32,109,105,120,116,117, +114,101,32,111,102,32,98,101,116,119,101,101,110,32,116,104,101,69,120,97,109, +112,108,101,115,32,111,102,101,100,117,99,97,116,105,111,110,97,108,99,111,109, +112,101,116,105,116,105,118,101,32,111,110,115,117,98,109,105,116,61,34,100,105, +114,101,99,116,111,114,32,111,102,100,105,115,116,105,110,99,116,105,118,101,47, +68,84,68,32,88,72,84,77,76,32,114,101,108,97,116,105,110,103,32,116,111,116,101, +110,100,101,110,99,121,32,116,111,112,114,111,118,105,110,99,101,32,111,102,119, +104,105,99,104,32,119,111,117,108,100,100,101,115,112,105,116,101,32,116,104,101 +,115,99,105,101,110,116,105,102,105,99,32,108,101,103,105,115,108,97,116,117,114 +,101,46,105,110,110,101,114,72,84,77,76,32,97,108,108,101,103,97,116,105,111,110 +,115,65,103,114,105,99,117,108,116,117,114,101,119,97,115,32,117,115,101,100,32, +105,110,97,112,112,114,111,97,99,104,32,116,111,105,110,116,101,108,108,105,103, +101,110,116,121,101,97,114,115,32,108,97,116,101,114,44,115,97,110,115,45,115, +101,114,105,102,100,101,116,101,114,109,105,110,105,110,103,80,101,114,102,111, +114,109,97,110,99,101,97,112,112,101,97,114,97,110,99,101,115,44,32,119,104,105, +99,104,32,105,115,32,102,111,117,110,100,97,116,105,111,110,115,97,98,98,114,101 +,118,105,97,116,101,100,104,105,103,104,101,114,32,116,104,97,110,115,32,102,114 +,111,109,32,116,104,101,32,105,110,100,105,118,105,100,117,97,108,32,99,111,109, +112,111,115,101,100,32,111,102,115,117,112,112,111,115,101,100,32,116,111,99,108 +,97,105,109,115,32,116,104,97,116,97,116,116,114,105,98,117,116,105,111,110,102, +111,110,116,45,115,105,122,101,58,49,101,108,101,109,101,110,116,115,32,111,102, +72,105,115,116,111,114,105,99,97,108,32,104,105,115,32,98,114,111,116,104,101, +114,97,116,32,116,104,101,32,116,105,109,101,97,110,110,105,118,101,114,115,97, +114,121,103,111,118,101,114,110,101,100,32,98,121,114,101,108,97,116,101,100,32, +116,111,32,117,108,116,105,109,97,116,101,108,121,32,105,110,110,111,118,97,116, +105,111,110,115,105,116,32,105,115,32,115,116,105,108,108,99,97,110,32,111,110, +108,121,32,98,101,100,101,102,105,110,105,116,105,111,110,115,116,111,71,77,84, +83,116,114,105,110,103,65,32,110,117,109,98,101,114,32,111,102,105,109,103,32,99 +,108,97,115,115,61,34,69,118,101,110,116,117,97,108,108,121,44,119,97,115,32,99, +104,97,110,103,101,100,111,99,99,117,114,114,101,100,32,105,110,110,101,105,103, +104,98,111,114,105,110,103,100,105,115,116,105,110,103,117,105,115,104,119,104, +101,110,32,104,101,32,119,97,115,105,110,116,114,111,100,117,99,105,110,103,116, +101,114,114,101,115,116,114,105,97,108,77,97,110,121,32,111,102,32,116,104,101, +97,114,103,117,101,115,32,116,104,97,116,97,110,32,65,109,101,114,105,99,97,110, +99,111,110,113,117,101,115,116,32,111,102,119,105,100,101,115,112,114,101,97,100 +,32,119,101,114,101,32,107,105,108,108,101,100,115,99,114,101,101,110,32,97,110, +100,32,73,110,32,111,114,100,101,114,32,116,111,101,120,112,101,99,116,101,100, +32,116,111,100,101,115,99,101,110,100,97,110,116,115,97,114,101,32,108,111,99,97 +,116,101,100,108,101,103,105,115,108,97,116,105,118,101,103,101,110,101,114,97, +116,105,111,110,115,32,98,97,99,107,103,114,111,117,110,100,109,111,115,116,32, +112,101,111,112,108,101,121,101,97,114,115,32,97,102,116,101,114,116,104,101,114 +,101,32,105,115,32,110,111,116,104,101,32,104,105,103,104,101,115,116,102,114, +101,113,117,101,110,116,108,121,32,116,104,101,121,32,100,111,32,110,111,116,97, +114,103,117,101,100,32,116,104,97,116,115,104,111,119,101,100,32,116,104,97,116, +112,114,101,100,111,109,105,110,97,110,116,116,104,101,111,108,111,103,105,99,97 +,108,98,121,32,116,104,101,32,116,105,109,101,99,111,110,115,105,100,101,114,105 +,110,103,115,104,111,114,116,45,108,105,118,101,100,60,47,115,112,97,110,62,60, +47,97,62,99,97,110,32,98,101,32,117,115,101,100,118,101,114,121,32,108,105,116, +116,108,101,111,110,101,32,111,102,32,116,104,101,32,104,97,100,32,97,108,114, +101,97,100,121,105,110,116,101,114,112,114,101,116,101,100,99,111,109,109,117, +110,105,99,97,116,101,102,101,97,116,117,114,101,115,32,111,102,103,111,118,101, +114,110,109,101,110,116,44,60,47,110,111,115,99,114,105,112,116,62,101,110,116, +101,114,101,100,32,116,104,101,34,32,104,101,105,103,104,116,61,34,51,73,110,100 +,101,112,101,110,100,101,110,116,112,111,112,117,108,97,116,105,111,110,115,108, +97,114,103,101,45,115,99,97,108,101,46,32,65,108,116,104,111,117,103,104,32,117, +115,101,100,32,105,110,32,116,104,101,100,101,115,116,114,117,99,116,105,111,110 +,112,111,115,115,105,98,105,108,105,116,121,115,116,97,114,116,105,110,103,32, +105,110,116,119,111,32,111,114,32,109,111,114,101,101,120,112,114,101,115,115, +105,111,110,115,115,117,98,111,114,100,105,110,97,116,101,108,97,114,103,101,114 +,32,116,104,97,110,104,105,115,116,111,114,121,32,97,110,100,60,47,111,112,116, +105,111,110,62,13,10,67,111,110,116,105,110,101,110,116,97,108,101,108,105,109, +105,110,97,116,105,110,103,119,105,108,108,32,110,111,116,32,98,101,112,114,97, +99,116,105,99,101,32,111,102,105,110,32,102,114,111,110,116,32,111,102,115,105, +116,101,32,111,102,32,116,104,101,101,110,115,117,114,101,32,116,104,97,116,116, +111,32,99,114,101,97,116,101,32,97,109,105,115,115,105,115,115,105,112,112,105, +112,111,116,101,110,116,105,97,108,108,121,111,117,116,115,116,97,110,100,105, +110,103,98,101,116,116,101,114,32,116,104,97,110,119,104,97,116,32,105,115,32, +110,111,119,115,105,116,117,97,116,101,100,32,105,110,109,101,116,97,32,110,97, +109,101,61,34,84,114,97,100,105,116,105,111,110,97,108,115,117,103,103,101,115, +116,105,111,110,115,84,114,97,110,115,108,97,116,105,111,110,116,104,101,32,102, +111,114,109,32,111,102,97,116,109,111,115,112,104,101,114,105,99,105,100,101,111 +,108,111,103,105,99,97,108,101,110,116,101,114,112,114,105,115,101,115,99,97,108 +,99,117,108,97,116,105,110,103,101,97,115,116,32,111,102,32,116,104,101,114,101, +109,110,97,110,116,115,32,111,102,112,108,117,103,105,110,115,112,97,103,101,47, +105,110,100,101,120,46,112,104,112,63,114,101,109,97,105,110,101,100,32,105,110, +116,114,97,110,115,102,111,114,109,101,100,72,101,32,119,97,115,32,97,108,115, +111,119,97,115,32,97,108,114,101,97,100,121,115,116,97,116,105,115,116,105,99,97 +,108,105,110,32,102,97,118,111,114,32,111,102,77,105,110,105,115,116,114,121,32, +111,102,109,111,118,101,109,101,110,116,32,111,102,102,111,114,109,117,108,97, +116,105,111,110,105,115,32,114,101,113,117,105,114,101,100,60,108,105,110,107,32 +,114,101,108,61,34,84,104,105,115,32,105,115,32,116,104,101,32,60,97,32,104,114, +101,102,61,34,47,112,111,112,117,108,97,114,105,122,101,100,105,110,118,111,108, +118,101,100,32,105,110,97,114,101,32,117,115,101,100,32,116,111,97,110,100,32, +115,101,118,101,114,97,108,109,97,100,101,32,98,121,32,116,104,101,115,101,101, +109,115,32,116,111,32,98,101,108,105,107,101,108,121,32,116,104,97,116,80,97,108 +,101,115,116,105,110,105,97,110,110,97,109,101,100,32,97,102,116,101,114,105,116 +,32,104,97,100,32,98,101,101,110,109,111,115,116,32,99,111,109,109,111,110,116, +111,32,114,101,102,101,114,32,116,111,98,117,116,32,116,104,105,115,32,105,115, +99,111,110,115,101,99,117,116,105,118,101,116,101,109,112,111,114,97,114,105,108 +,121,73,110,32,103,101,110,101,114,97,108,44,99,111,110,118,101,110,116,105,111, +110,115,116,97,107,101,115,32,112,108,97,99,101,115,117,98,100,105,118,105,115, +105,111,110,116,101,114,114,105,116,111,114,105,97,108,111,112,101,114,97,116, +105,111,110,97,108,112,101,114,109,97,110,101,110,116,108,121,119,97,115,32,108, +97,114,103,101,108,121,111,117,116,98,114,101,97,107,32,111,102,105,110,32,116, +104,101,32,112,97,115,116,102,111,108,108,111,119,105,110,103,32,97,32,120,109, +108,110,115,58,111,103,61,34,62,60,97,32,99,108,97,115,115,61,34,99,108,97,115, +115,61,34,116,101,120,116,67,111,110,118,101,114,115,105,111,110,32,109,97,121, +32,98,101,32,117,115,101,100,109,97,110,117,102,97,99,116,117,114,101,97,102,116 +,101,114,32,98,101,105,110,103,99,108,101,97,114,102,105,120,34,62,10,113,117, +101,115,116,105,111,110,32,111,102,119,97,115,32,101,108,101,99,116,101,100,116, +111,32,98,101,99,111,109,101,32,97,98,101,99,97,117,115,101,32,111,102,32,115, +111,109,101,32,112,101,111,112,108,101,105,110,115,112,105,114,101,100,32,98,121 +,115,117,99,99,101,115,115,102,117,108,32,97,32,116,105,109,101,32,119,104,101, +110,109,111,114,101,32,99,111,109,109,111,110,97,109,111,110,103,115,116,32,116, +104,101,97,110,32,111,102,102,105,99,105,97,108,119,105,100,116,104,58,49,48,48, +37,59,116,101,99,104,110,111,108,111,103,121,44,119,97,115,32,97,100,111,112,116 +,101,100,116,111,32,107,101,101,112,32,116,104,101,115,101,116,116,108,101,109, +101,110,116,115,108,105,118,101,32,98,105,114,116,104,115,105,110,100,101,120,46 +,104,116,109,108,34,67,111,110,110,101,99,116,105,99,117,116,97,115,115,105,103, +110,101,100,32,116,111,38,97,109,112,59,116,105,109,101,115,59,97,99,99,111,117, +110,116,32,102,111,114,97,108,105,103,110,61,114,105,103,104,116,116,104,101,32, +99,111,109,112,97,110,121,97,108,119,97,121,115,32,98,101,101,110,114,101,116, +117,114,110,101,100,32,116,111,105,110,118,111,108,118,101,109,101,110,116,66, +101,99,97,117,115,101,32,116,104,101,116,104,105,115,32,112,101,114,105,111,100, +34,32,110,97,109,101,61,34,113,34,32,99,111,110,102,105,110,101,100,32,116,111, +97,32,114,101,115,117,108,116,32,111,102,118,97,108,117,101,61,34,34,32,47,62, +105,115,32,97,99,116,117,97,108,108,121,69,110,118,105,114,111,110,109,101,110, +116,13,10,60,47,104,101,97,100,62,13,10,67,111,110,118,101,114,115,101,108,121, +44,62,10,60,100,105,118,32,105,100,61,34,48,34,32,119,105,100,116,104,61,34,49, +105,115,32,112,114,111,98,97,98,108,121,104,97,118,101,32,98,101,99,111,109,101, +99,111,110,116,114,111,108,108,105,110,103,116,104,101,32,112,114,111,98,108,101 +,109,99,105,116,105,122,101,110,115,32,111,102,112,111,108,105,116,105,99,105,97 +,110,115,114,101,97,99,104,101,100,32,116,104,101,97,115,32,101,97,114,108,121, +32,97,115,58,110,111,110,101,59,32,111,118,101,114,60,116,97,98,108,101,32,99, +101,108,108,118,97,108,105,100,105,116,121,32,111,102,100,105,114,101,99,116,108 +,121,32,116,111,111,110,109,111,117,115,101,100,111,119,110,119,104,101,114,101, +32,105,116,32,105,115,119,104,101,110,32,105,116,32,119,97,115,109,101,109,98, +101,114,115,32,111,102,32,114,101,108,97,116,105,111,110,32,116,111,97,99,99,111 +,109,109,111,100,97,116,101,97,108,111,110,103,32,119,105,116,104,32,73,110,32, +116,104,101,32,108,97,116,101,116,104,101,32,69,110,103,108,105,115,104,100,101, +108,105,99,105,111,117,115,34,62,116,104,105,115,32,105,115,32,110,111,116,116, +104,101,32,112,114,101,115,101,110,116,105,102,32,116,104,101,121,32,97,114,101, +97,110,100,32,102,105,110,97,108,108,121,97,32,109,97,116,116,101,114,32,111,102 +,13,10,9,60,47,100,105,118,62,13,10,13,10,60,47,115,99,114,105,112,116,62,102,97 +,115,116,101,114,32,116,104,97,110,109,97,106,111,114,105,116,121,32,111,102,97, +102,116,101,114,32,119,104,105,99,104,99,111,109,112,97,114,97,116,105,118,101, +116,111,32,109,97,105,110,116,97,105,110,105,109,112,114,111,118,101,32,116,104, +101,97,119,97,114,100,101,100,32,116,104,101,101,114,34,32,99,108,97,115,115,61, +34,102,114,97,109,101,98,111,114,100,101,114,114,101,115,116,111,114,97,116,105, +111,110,105,110,32,116,104,101,32,115,97,109,101,97,110,97,108,121,115,105,115, +32,111,102,116,104,101,105,114,32,102,105,114,115,116,68,117,114,105,110,103,32, +116,104,101,32,99,111,110,116,105,110,101,110,116,97,108,115,101,113,117,101,110 +,99,101,32,111,102,102,117,110,99,116,105,111,110,40,41,123,102,111,110,116,45, +115,105,122,101,58,32,119,111,114,107,32,111,110,32,116,104,101,60,47,115,99,114 +,105,112,116,62,10,60,98,101,103,105,110,115,32,119,105,116,104,106,97,118,97, +115,99,114,105,112,116,58,99,111,110,115,116,105,116,117,101,110,116,119,97,115, +32,102,111,117,110,100,101,100,101,113,117,105,108,105,98,114,105,117,109,97,115 +,115,117,109,101,32,116,104,97,116,105,115,32,103,105,118,101,110,32,98,121,110, +101,101,100,115,32,116,111,32,98,101,99,111,111,114,100,105,110,97,116,101,115, +116,104,101,32,118,97,114,105,111,117,115,97,114,101,32,112,97,114,116,32,111, +102,111,110,108,121,32,105,110,32,116,104,101,115,101,99,116,105,111,110,115,32, +111,102,105,115,32,97,32,99,111,109,109,111,110,116,104,101,111,114,105,101,115, +32,111,102,100,105,115,99,111,118,101,114,105,101,115,97,115,115,111,99,105,97, +116,105,111,110,101,100,103,101,32,111,102,32,116,104,101,115,116,114,101,110, +103,116,104,32,111,102,112,111,115,105,116,105,111,110,32,105,110,112,114,101, +115,101,110,116,45,100,97,121,117,110,105,118,101,114,115,97,108,108,121,116,111 +,32,102,111,114,109,32,116,104,101,98,117,116,32,105,110,115,116,101,97,100,99, +111,114,112,111,114,97,116,105,111,110,97,116,116,97,99,104,101,100,32,116,111, +105,115,32,99,111,109,109,111,110,108,121,114,101,97,115,111,110,115,32,102,111, +114,32,38,113,117,111,116,59,116,104,101,32,99,97,110,32,98,101,32,109,97,100, +101,119,97,115,32,97,98,108,101,32,116,111,119,104,105,99,104,32,109,101,97,110, +115,98,117,116,32,100,105,100,32,110,111,116,111,110,77,111,117,115,101,79,118, +101,114,97,115,32,112,111,115,115,105,98,108,101,111,112,101,114,97,116,101,100, +32,98,121,99,111,109,105,110,103,32,102,114,111,109,116,104,101,32,112,114,105, +109,97,114,121,97,100,100,105,116,105,111,110,32,111,102,102,111,114,32,115,101, +118,101,114,97,108,116,114,97,110,115,102,101,114,114,101,100,97,32,112,101,114, +105,111,100,32,111,102,97,114,101,32,97,98,108,101,32,116,111,104,111,119,101, +118,101,114,44,32,105,116,115,104,111,117,108,100,32,104,97,118,101,109,117,99, +104,32,108,97,114,103,101,114,10,9,60,47,115,99,114,105,112,116,62,97,100,111, +112,116,101,100,32,116,104,101,112,114,111,112,101,114,116,121,32,111,102,100, +105,114,101,99,116,101,100,32,98,121,101,102,102,101,99,116,105,118,101,108,121, +119,97,115,32,98,114,111,117,103,104,116,99,104,105,108,100,114,101,110,32,111, +102,80,114,111,103,114,97,109,109,105,110,103,108,111,110,103,101,114,32,116,104 +,97,110,109,97,110,117,115,99,114,105,112,116,115,119,97,114,32,97,103,97,105, +110,115,116,98,121,32,109,101,97,110,115,32,111,102,97,110,100,32,109,111,115, +116,32,111,102,115,105,109,105,108,97,114,32,116,111,32,112,114,111,112,114,105, +101,116,97,114,121,111,114,105,103,105,110,97,116,105,110,103,112,114,101,115, +116,105,103,105,111,117,115,103,114,97,109,109,97,116,105,99,97,108,101,120,112, +101,114,105,101,110,99,101,46,116,111,32,109,97,107,101,32,116,104,101,73,116,32 +,119,97,115,32,97,108,115,111,105,115,32,102,111,117,110,100,32,105,110,99,111, +109,112,101,116,105,116,111,114,115,105,110,32,116,104,101,32,85,46,83,46,114, +101,112,108,97,99,101,32,116,104,101,98,114,111,117,103,104,116,32,116,104,101, +99,97,108,99,117,108,97,116,105,111,110,102,97,108,108,32,111,102,32,116,104,101 +,116,104,101,32,103,101,110,101,114,97,108,112,114,97,99,116,105,99,97,108,108, +121,105,110,32,104,111,110,111,114,32,111,102,114,101,108,101,97,115,101,100,32, +105,110,114,101,115,105,100,101,110,116,105,97,108,97,110,100,32,115,111,109,101 +,32,111,102,107,105,110,103,32,111,102,32,116,104,101,114,101,97,99,116,105,111, +110,32,116,111,49,115,116,32,69,97,114,108,32,111,102,99,117,108,116,117,114,101 +,32,97,110,100,112,114,105,110,99,105,112,97,108,108,121,60,47,116,105,116,108, +101,62,10,32,32,116,104,101,121,32,99,97,110,32,98,101,98,97,99,107,32,116,111, +32,116,104,101,115,111,109,101,32,111,102,32,104,105,115,101,120,112,111,115,117 +,114,101,32,116,111,97,114,101,32,115,105,109,105,108,97,114,102,111,114,109,32, +111,102,32,116,104,101,97,100,100,70,97,118,111,114,105,116,101,99,105,116,105, +122,101,110,115,104,105,112,112,97,114,116,32,105,110,32,116,104,101,112,101,111 +,112,108,101,32,119,105,116,104,105,110,32,112,114,97,99,116,105,99,101,116,111, +32,99,111,110,116,105,110,117,101,38,97,109,112,59,109,105,110,117,115,59,97,112 +,112,114,111,118,101,100,32,98,121,32,116,104,101,32,102,105,114,115,116,32,97, +108,108,111,119,101,100,32,116,104,101,97,110,100,32,102,111,114,32,116,104,101, +102,117,110,99,116,105,111,110,105,110,103,112,108,97,121,105,110,103,32,116,104 +,101,115,111,108,117,116,105,111,110,32,116,111,104,101,105,103,104,116,61,34,48 +,34,32,105,110,32,104,105,115,32,98,111,111,107,109,111,114,101,32,116,104,97, +110,32,97,102,111,108,108,111,119,115,32,116,104,101,99,114,101,97,116,101,100, +32,116,104,101,112,114,101,115,101,110,99,101,32,105,110,38,110,98,115,112,59,60 +,47,116,100,62,110,97,116,105,111,110,97,108,105,115,116,116,104,101,32,105,100, +101,97,32,111,102,97,32,99,104,97,114,97,99,116,101,114,119,101,114,101,32,102, +111,114,99,101,100,32,99,108,97,115,115,61,34,98,116,110,100,97,121,115,32,111, +102,32,116,104,101,102,101,97,116,117,114,101,100,32,105,110,115,104,111,119,105 +,110,103,32,116,104,101,105,110,116,101,114,101,115,116,32,105,110,105,110,32, +112,108,97,99,101,32,111,102,116,117,114,110,32,111,102,32,116,104,101,116,104, +101,32,104,101,97,100,32,111,102,76,111,114,100,32,111,102,32,116,104,101,112, +111,108,105,116,105,99,97,108,108,121,104,97,115,32,105,116,115,32,111,119,110, +69,100,117,99,97,116,105,111,110,97,108,97,112,112,114,111,118,97,108,32,111,102 +,115,111,109,101,32,111,102,32,116,104,101,101,97,99,104,32,111,116,104,101,114, +44,98,101,104,97,118,105,111,114,32,111,102,97,110,100,32,98,101,99,97,117,115, +101,97,110,100,32,97,110,111,116,104,101,114,97,112,112,101,97,114,101,100,32, +111,110,114,101,99,111,114,100,101,100,32,105,110,98,108,97,99,107,38,113,117, +111,116,59,109,97,121,32,105,110,99,108,117,100,101,116,104,101,32,119,111,114, +108,100,39,115,99,97,110,32,108,101,97,100,32,116,111,114,101,102,101,114,115,32 +,116,111,32,97,98,111,114,100,101,114,61,34,48,34,32,103,111,118,101,114,110,109 +,101,110,116,32,119,105,110,110,105,110,103,32,116,104,101,114,101,115,117,108, +116,101,100,32,105,110,32,119,104,105,108,101,32,116,104,101,32,87,97,115,104, +105,110,103,116,111,110,44,116,104,101,32,115,117,98,106,101,99,116,99,105,116, +121,32,105,110,32,116,104,101,62,60,47,100,105,118,62,13,10,9,9,114,101,102,108, +101,99,116,32,116,104,101,116,111,32,99,111,109,112,108,101,116,101,98,101,99,97 +,109,101,32,109,111,114,101,114,97,100,105,111,97,99,116,105,118,101,114,101,106 +,101,99,116,101,100,32,98,121,119,105,116,104,111,117,116,32,97,110,121,104,105, +115,32,102,97,116,104,101,114,44,119,104,105,99,104,32,99,111,117,108,100,99,111 +,112,121,32,111,102,32,116,104,101,116,111,32,105,110,100,105,99,97,116,101,97, +32,112,111,108,105,116,105,99,97,108,97,99,99,111,117,110,116,115,32,111,102,99, +111,110,115,116,105,116,117,116,101,115,119,111,114,107,101,100,32,119,105,116, +104,101,114,60,47,97,62,60,47,108,105,62,111,102,32,104,105,115,32,108,105,102, +101,97,99,99,111,109,112,97,110,105,101,100,99,108,105,101,110,116,87,105,100, +116,104,112,114,101,118,101,110,116,32,116,104,101,76,101,103,105,115,108,97,116 +,105,118,101,100,105,102,102,101,114,101,110,116,108,121,116,111,103,101,116,104 +,101,114,32,105,110,104,97,115,32,115,101,118,101,114,97,108,102,111,114,32,97, +110,111,116,104,101,114,116,101,120,116,32,111,102,32,116,104,101,102,111,117, +110,100,101,100,32,116,104,101,101,32,119,105,116,104,32,116,104,101,32,105,115, +32,117,115,101,100,32,102,111,114,99,104,97,110,103,101,100,32,116,104,101,117, +115,117,97,108,108,121,32,116,104,101,112,108,97,99,101,32,119,104,101,114,101, +119,104,101,114,101,97,115,32,116,104,101,62,32,60,97,32,104,114,101,102,61,34, +34,62,60,97,32,104,114,101,102,61,34,116,104,101,109,115,101,108,118,101,115,44, +97,108,116,104,111,117,103,104,32,104,101,116,104,97,116,32,99,97,110,32,98,101, +116,114,97,100,105,116,105,111,110,97,108,114,111,108,101,32,111,102,32,116,104, +101,97,115,32,97,32,114,101,115,117,108,116,114,101,109,111,118,101,67,104,105, +108,100,100,101,115,105,103,110,101,100,32,98,121,119,101,115,116,32,111,102,32, +116,104,101,83,111,109,101,32,112,101,111,112,108,101,112,114,111,100,117,99,116 +,105,111,110,44,115,105,100,101,32,111,102,32,116,104,101,110,101,119,115,108, +101,116,116,101,114,115,117,115,101,100,32,98,121,32,116,104,101,100,111,119,110 +,32,116,111,32,116,104,101,97,99,99,101,112,116,101,100,32,98,121,108,105,118, +101,32,105,110,32,116,104,101,97,116,116,101,109,112,116,115,32,116,111,111,117, +116,115,105,100,101,32,116,104,101,102,114,101,113,117,101,110,99,105,101,115,72 +,111,119,101,118,101,114,44,32,105,110,112,114,111,103,114,97,109,109,101,114, +115,97,116,32,108,101,97,115,116,32,105,110,97,112,112,114,111,120,105,109,97, +116,101,97,108,116,104,111,117,103,104,32,105,116,119,97,115,32,112,97,114,116, +32,111,102,97,110,100,32,118,97,114,105,111,117,115,71,111,118,101,114,110,111, +114,32,111,102,116,104,101,32,97,114,116,105,99,108,101,116,117,114,110,101,100, +32,105,110,116,111,62,60,97,32,104,114,101,102,61,34,47,116,104,101,32,101,99, +111,110,111,109,121,105,115,32,116,104,101,32,109,111,115,116,109,111,115,116,32 +,119,105,100,101,108,121,119,111,117,108,100,32,108,97,116,101,114,97,110,100,32 +,112,101,114,104,97,112,115,114,105,115,101,32,116,111,32,116,104,101,111,99,99, +117,114,115,32,119,104,101,110,117,110,100,101,114,32,119,104,105,99,104,99,111, +110,100,105,116,105,111,110,115,46,116,104,101,32,119,101,115,116,101,114,110, +116,104,101,111,114,121,32,116,104,97,116,105,115,32,112,114,111,100,117,99,101, +100,116,104,101,32,99,105,116,121,32,111,102,105,110,32,119,104,105,99,104,32, +104,101,115,101,101,110,32,105,110,32,116,104,101,116,104,101,32,99,101,110,116, +114,97,108,98,117,105,108,100,105,110,103,32,111,102,109,97,110,121,32,111,102, +32,104,105,115,97,114,101,97,32,111,102,32,116,104,101,105,115,32,116,104,101,32 +,111,110,108,121,109,111,115,116,32,111,102,32,116,104,101,109,97,110,121,32,111 +,102,32,116,104,101,116,104,101,32,87,101,115,116,101,114,110,84,104,101,114,101 +,32,105,115,32,110,111,101,120,116,101,110,100,101,100,32,116,111,83,116,97,116, +105,115,116,105,99,97,108,99,111,108,115,112,97,110,61,50,32,124,115,104,111,114 +,116,32,115,116,111,114,121,112,111,115,115,105,98,108,101,32,116,111,116,111, +112,111,108,111,103,105,99,97,108,99,114,105,116,105,99,97,108,32,111,102,114, +101,112,111,114,116,101,100,32,116,111,97,32,67,104,114,105,115,116,105,97,110, +100,101,99,105,115,105,111,110,32,116,111,105,115,32,101,113,117,97,108,32,116, +111,112,114,111,98,108,101,109,115,32,111,102,84,104,105,115,32,99,97,110,32,98, +101,109,101,114,99,104,97,110,100,105,115,101,102,111,114,32,109,111,115,116,32, +111,102,110,111,32,101,118,105,100,101,110,99,101,101,100,105,116,105,111,110, +115,32,111,102,101,108,101,109,101,110,116,115,32,105,110,38,113,117,111,116,59, +46,32,84,104,101,99,111,109,47,105,109,97,103,101,115,47,119,104,105,99,104,32, +109,97,107,101,115,116,104,101,32,112,114,111,99,101,115,115,114,101,109,97,105, +110,115,32,116,104,101,108,105,116,101,114,97,116,117,114,101,44,105,115,32,97, +32,109,101,109,98,101,114,116,104,101,32,112,111,112,117,108,97,114,116,104,101, +32,97,110,99,105,101,110,116,112,114,111,98,108,101,109,115,32,105,110,116,105, +109,101,32,111,102,32,116,104,101,100,101,102,101,97,116,101,100,32,98,121,98, +111,100,121,32,111,102,32,116,104,101,97,32,102,101,119,32,121,101,97,114,115, +109,117,99,104,32,111,102,32,116,104,101,116,104,101,32,119,111,114,107,32,111, +102,67,97,108,105,102,111,114,110,105,97,44,115,101,114,118,101,100,32,97,115,32 +,97,103,111,118,101,114,110,109,101,110,116,46,99,111,110,99,101,112,116,115,32, +111,102,109,111,118,101,109,101,110,116,32,105,110,9,9,60,100,105,118,32,105,100 +,61,34,105,116,34,32,118,97,108,117,101,61,34,108,97,110,103,117,97,103,101,32, +111,102,97,115,32,116,104,101,121,32,97,114,101,112,114,111,100,117,99,101,100, +32,105,110,105,115,32,116,104,97,116,32,116,104,101,101,120,112,108,97,105,110, +32,116,104,101,100,105,118,62,60,47,100,105,118,62,10,72,111,119,101,118,101,114 +,32,116,104,101,108,101,97,100,32,116,111,32,116,104,101,9,60,97,32,104,114,101, +102,61,34,47,119,97,115,32,103,114,97,110,116,101,100,112,101,111,112,108,101,32 +,104,97,118,101,99,111,110,116,105,110,117,97,108,108,121,119,97,115,32,115,101, +101,110,32,97,115,97,110,100,32,114,101,108,97,116,101,100,116,104,101,32,114, +111,108,101,32,111,102,112,114,111,112,111,115,101,100,32,98,121,111,102,32,116, +104,101,32,98,101,115,116,101,97,99,104,32,111,116,104,101,114,46,67,111,110,115 +,116,97,110,116,105,110,101,112,101,111,112,108,101,32,102,114,111,109,100,105, +97,108,101,99,116,115,32,111,102,116,111,32,114,101,118,105,115,105,111,110,119, +97,115,32,114,101,110,97,109,101,100,97,32,115,111,117,114,99,101,32,111,102,116 +,104,101,32,105,110,105,116,105,97,108,108,97,117,110,99,104,101,100,32,105,110, +112,114,111,118,105,100,101,32,116,104,101,116,111,32,116,104,101,32,119,101,115 +,116,119,104,101,114,101,32,116,104,101,114,101,97,110,100,32,115,105,109,105, +108,97,114,98,101,116,119,101,101,110,32,116,119,111,105,115,32,97,108,115,111, +32,116,104,101,69,110,103,108,105,115,104,32,97,110,100,99,111,110,100,105,116, +105,111,110,115,44,116,104,97,116,32,105,116,32,119,97,115,101,110,116,105,116, +108,101,100,32,116,111,116,104,101,109,115,101,108,118,101,115,46,113,117,97,110 +,116,105,116,121,32,111,102,114,97,110,115,112,97,114,101,110,99,121,116,104,101 +,32,115,97,109,101,32,97,115,116,111,32,106,111,105,110,32,116,104,101,99,111, +117,110,116,114,121,32,97,110,100,116,104,105,115,32,105,115,32,116,104,101,84, +104,105,115,32,108,101,100,32,116,111,97,32,115,116,97,116,101,109,101,110,116, +99,111,110,116,114,97,115,116,32,116,111,108,97,115,116,73,110,100,101,120,79, +102,116,104,114,111,117,103,104,32,104,105,115,105,115,32,100,101,115,105,103, +110,101,100,116,104,101,32,116,101,114,109,32,105,115,105,115,32,112,114,111,118 +,105,100,101,100,112,114,111,116,101,99,116,32,116,104,101,110,103,60,47,97,62, +60,47,108,105,62,84,104,101,32,99,117,114,114,101,110,116,116,104,101,32,115,105 +,116,101,32,111,102,115,117,98,115,116,97,110,116,105,97,108,101,120,112,101,114 +,105,101,110,99,101,44,105,110,32,116,104,101,32,87,101,115,116,116,104,101,121, +32,115,104,111,117,108,100,115,108,111,118,101,110,196,141,105,110,97,99,111,109 +,101,110,116,97,114,105,111,115,117,110,105,118,101,114,115,105,100,97,100,99, +111,110,100,105,99,105,111,110,101,115,97,99,116,105,118,105,100,97,100,101,115, +101,120,112,101,114,105,101,110,99,105,97,116,101,99,110,111,108,111,103,195,173 +,97,112,114,111,100,117,99,99,105,195,179,110,112,117,110,116,117,97,99,105,195, +179,110,97,112,108,105,99,97,99,105,195,179,110,99,111,110,116,114,97,115,101, +195,177,97,99,97,116,101,103,111,114,195,173,97,115,114,101,103,105,115,116,114, +97,114,115,101,112,114,111,102,101,115,105,111,110,97,108,116,114,97,116,97,109, +105,101,110,116,111,114,101,103,195,173,115,116,114,97,116,101,115,101,99,114, +101,116,97,114,195,173,97,112,114,105,110,99,105,112,97,108,101,115,112,114,111, +116,101,99,99,105,195,179,110,105,109,112,111,114,116,97,110,116,101,115,105,109 +,112,111,114,116,97,110,99,105,97,112,111,115,105,98,105,108,105,100,97,100,105, +110,116,101,114,101,115,97,110,116,101,99,114,101,99,105,109,105,101,110,116,111 +,110,101,99,101,115,105,100,97,100,101,115,115,117,115,99,114,105,98,105,114,115 +,101,97,115,111,99,105,97,99,105,195,179,110,100,105,115,112,111,110,105,98,108, +101,115,101,118,97,108,117,97,99,105,195,179,110,101,115,116,117,100,105,97,110, +116,101,115,114,101,115,112,111,110,115,97,98,108,101,114,101,115,111,108,117,99 +,105,195,179,110,103,117,97,100,97,108,97,106,97,114,97,114,101,103,105,115,116, +114,97,100,111,115,111,112,111,114,116,117,110,105,100,97,100,99,111,109,101,114 +,99,105,97,108,101,115,102,111,116,111,103,114,97,102,195,173,97,97,117,116,111, +114,105,100,97,100,101,115,105,110,103,101,110,105,101,114,195,173,97,116,101, +108,101,118,105,115,105,195,179,110,99,111,109,112,101,116,101,110,99,105,97,111 +,112,101,114,97,99,105,111,110,101,115,101,115,116,97,98,108,101,99,105,100,111, +115,105,109,112,108,101,109,101,110,116,101,97,99,116,117,97,108,109,101,110,116 +,101,110,97,118,101,103,97,99,105,195,179,110,99,111,110,102,111,114,109,105,100 +,97,100,108,105,110,101,45,104,101,105,103,104,116,58,102,111,110,116,45,102,97, +109,105,108,121,58,34,32,58,32,34,104,116,116,112,58,47,47,97,112,112,108,105,99 +,97,116,105,111,110,115,108,105,110,107,34,32,104,114,101,102,61,34,115,112,101, +99,105,102,105,99,97,108,108,121,47,47,60,33,91,67,68,65,84,65,91,10,79,114,103, +97,110,105,122,97,116,105,111,110,100,105,115,116,114,105,98,117,116,105,111,110 +,48,112,120,59,32,104,101,105,103,104,116,58,114,101,108,97,116,105,111,110,115, +104,105,112,100,101,118,105,99,101,45,119,105,100,116,104,60,100,105,118,32,99, +108,97,115,115,61,34,60,108,97,98,101,108,32,102,111,114,61,34,114,101,103,105, +115,116,114,97,116,105,111,110,60,47,110,111,115,99,114,105,112,116,62,10,47,105 +,110,100,101,120,46,104,116,109,108,34,119,105,110,100,111,119,46,111,112,101, +110,40,32,33,105,109,112,111,114,116,97,110,116,59,97,112,112,108,105,99,97,116, +105,111,110,47,105,110,100,101,112,101,110,100,101,110,99,101,47,47,119,119,119, +46,103,111,111,103,108,101,111,114,103,97,110,105,122,97,116,105,111,110,97,117, +116,111,99,111,109,112,108,101,116,101,114,101,113,117,105,114,101,109,101,110, +116,115,99,111,110,115,101,114,118,97,116,105,118,101,60,102,111,114,109,32,110, +97,109,101,61,34,105,110,116,101,108,108,101,99,116,117,97,108,109,97,114,103, +105,110,45,108,101,102,116,58,49,56,116,104,32,99,101,110,116,117,114,121,97,110 +,32,105,109,112,111,114,116,97,110,116,105,110,115,116,105,116,117,116,105,111, +110,115,97,98,98,114,101,118,105,97,116,105,111,110,60,105,109,103,32,99,108,97, +115,115,61,34,111,114,103,97,110,105,115,97,116,105,111,110,99,105,118,105,108, +105,122,97,116,105,111,110,49,57,116,104,32,99,101,110,116,117,114,121,97,114,99 +,104,105,116,101,99,116,117,114,101,105,110,99,111,114,112,111,114,97,116,101, +100,50,48,116,104,32,99,101,110,116,117,114,121,45,99,111,110,116,97,105,110,101 +,114,34,62,109,111,115,116,32,110,111,116,97,98,108,121,47,62,60,47,97,62,60,47, +100,105,118,62,110,111,116,105,102,105,99,97,116,105,111,110,39,117,110,100,101, +102,105,110,101,100,39,41,70,117,114,116,104,101,114,109,111,114,101,44,98,101, +108,105,101,118,101,32,116,104,97,116,105,110,110,101,114,72,84,77,76,32,61,32, +112,114,105,111,114,32,116,111,32,116,104,101,100,114,97,109,97,116,105,99,97, +108,108,121,114,101,102,101,114,114,105,110,103,32,116,111,110,101,103,111,116, +105,97,116,105,111,110,115,104,101,97,100,113,117,97,114,116,101,114,115,83,111, +117,116,104,32,65,102,114,105,99,97,117,110,115,117,99,99,101,115,115,102,117, +108,80,101,110,110,115,121,108,118,97,110,105,97,65,115,32,97,32,114,101,115,117 +,108,116,44,60,104,116,109,108,32,108,97,110,103,61,34,38,108,116,59,47,115,117, +112,38,103,116,59,100,101,97,108,105,110,103,32,119,105,116,104,112,104,105,108, +97,100,101,108,112,104,105,97,104,105,115,116,111,114,105,99,97,108,108,121,41, +59,60,47,115,99,114,105,112,116,62,10,112,97,100,100,105,110,103,45,116,111,112, +58,101,120,112,101,114,105,109,101,110,116,97,108,103,101,116,65,116,116,114,105 +,98,117,116,101,105,110,115,116,114,117,99,116,105,111,110,115,116,101,99,104, +110,111,108,111,103,105,101,115,112,97,114,116,32,111,102,32,116,104,101,32,61, +102,117,110,99,116,105,111,110,40,41,123,115,117,98,115,99,114,105,112,116,105, +111,110,108,46,100,116,100,34,62,13,10,60,104,116,103,101,111,103,114,97,112,104 +,105,99,97,108,67,111,110,115,116,105,116,117,116,105,111,110,39,44,32,102,117, +110,99,116,105,111,110,40,115,117,112,112,111,114,116,101,100,32,98,121,97,103, +114,105,99,117,108,116,117,114,97,108,99,111,110,115,116,114,117,99,116,105,111, +110,112,117,98,108,105,99,97,116,105,111,110,115,102,111,110,116,45,115,105,122, +101,58,32,49,97,32,118,97,114,105,101,116,121,32,111,102,60,100,105,118,32,115, +116,121,108,101,61,34,69,110,99,121,99,108,111,112,101,100,105,97,105,102,114,97 +,109,101,32,115,114,99,61,34,100,101,109,111,110,115,116,114,97,116,101,100,97, +99,99,111,109,112,108,105,115,104,101,100,117,110,105,118,101,114,115,105,116, +105,101,115,68,101,109,111,103,114,97,112,104,105,99,115,41,59,60,47,115,99,114, +105,112,116,62,60,100,101,100,105,99,97,116,101,100,32,116,111,107,110,111,119, +108,101,100,103,101,32,111,102,115,97,116,105,115,102,97,99,116,105,111,110,112, +97,114,116,105,99,117,108,97,114,108,121,60,47,100,105,118,62,60,47,100,105,118, +62,69,110,103,108,105,115,104,32,40,85,83,41,97,112,112,101,110,100,67,104,105, +108,100,40,116,114,97,110,115,109,105,115,115,105,111,110,115,46,32,72,111,119, +101,118,101,114,44,32,105,110,116,101,108,108,105,103,101,110,99,101,34,32,116, +97,98,105,110,100,101,120,61,34,102,108,111,97,116,58,114,105,103,104,116,59,67, +111,109,109,111,110,119,101,97,108,116,104,114,97,110,103,105,110,103,32,102,114 +,111,109,105,110,32,119,104,105,99,104,32,116,104,101,97,116,32,108,101,97,115, +116,32,111,110,101,114,101,112,114,111,100,117,99,116,105,111,110,101,110,99,121 +,99,108,111,112,101,100,105,97,59,102,111,110,116,45,115,105,122,101,58,49,106, +117,114,105,115,100,105,99,116,105,111,110,97,116,32,116,104,97,116,32,116,105, +109,101,34,62,60,97,32,99,108,97,115,115,61,34,73,110,32,97,100,100,105,116,105, +111,110,44,100,101,115,99,114,105,112,116,105,111,110,43,99,111,110,118,101,114, +115,97,116,105,111,110,99,111,110,116,97,99,116,32,119,105,116,104,105,115,32, +103,101,110,101,114,97,108,108,121,114,34,32,99,111,110,116,101,110,116,61,34, +114,101,112,114,101,115,101,110,116,105,110,103,38,108,116,59,109,97,116,104,38, +103,116,59,112,114,101,115,101,110,116,97,116,105,111,110,111,99,99,97,115,105, +111,110,97,108,108,121,60,105,109,103,32,119,105,100,116,104,61,34,110,97,118, +105,103,97,116,105,111,110,34,62,99,111,109,112,101,110,115,97,116,105,111,110, +99,104,97,109,112,105,111,110,115,104,105,112,109,101,100,105,97,61,34,97,108, +108,34,32,118,105,111,108,97,116,105,111,110,32,111,102,114,101,102,101,114,101, +110,99,101,32,116,111,114,101,116,117,114,110,32,116,114,117,101,59,83,116,114, +105,99,116,47,47,69,78,34,32,116,114,97,110,115,97,99,116,105,111,110,115,105, +110,116,101,114,118,101,110,116,105,111,110,118,101,114,105,102,105,99,97,116, +105,111,110,73,110,102,111,114,109,97,116,105,111,110,32,100,105,102,102,105,99, +117,108,116,105,101,115,67,104,97,109,112,105,111,110,115,104,105,112,99,97,112, +97,98,105,108,105,116,105,101,115,60,33,91,101,110,100,105,102,93,45,45,62,125, +10,60,47,115,99,114,105,112,116,62,10,67,104,114,105,115,116,105,97,110,105,116, +121,102,111,114,32,101,120,97,109,112,108,101,44,80,114,111,102,101,115,115,105, +111,110,97,108,114,101,115,116,114,105,99,116,105,111,110,115,115,117,103,103, +101,115,116,32,116,104,97,116,119,97,115,32,114,101,108,101,97,115,101,100,40, +115,117,99,104,32,97,115,32,116,104,101,114,101,109,111,118,101,67,108,97,115, +115,40,117,110,101,109,112,108,111,121,109,101,110,116,116,104,101,32,65,109,101 +,114,105,99,97,110,115,116,114,117,99,116,117,114,101,32,111,102,47,105,110,100, +101,120,46,104,116,109,108,32,112,117,98,108,105,115,104,101,100,32,105,110,115, +112,97,110,32,99,108,97,115,115,61,34,34,62,60,97,32,104,114,101,102,61,34,47, +105,110,116,114,111,100,117,99,116,105,111,110,98,101,108,111,110,103,105,110, +103,32,116,111,99,108,97,105,109,101,100,32,116,104,97,116,99,111,110,115,101, +113,117,101,110,99,101,115,60,109,101,116,97,32,110,97,109,101,61,34,71,117,105, +100,101,32,116,111,32,116,104,101,111,118,101,114,119,104,101,108,109,105,110, +103,97,103,97,105,110,115,116,32,116,104,101,32,99,111,110,99,101,110,116,114,97 +,116,101,100,44,10,46,110,111,110,116,111,117,99,104,32,111,98,115,101,114,118, +97,116,105,111,110,115,60,47,97,62,10,60,47,100,105,118,62,10,102,32,40,100,111, +99,117,109,101,110,116,46,98,111,114,100,101,114,58,32,49,112,120,32,123,102,111 +,110,116,45,115,105,122,101,58,49,116,114,101,97,116,109,101,110,116,32,111,102, +48,34,32,104,101,105,103,104,116,61,34,49,109,111,100,105,102,105,99,97,116,105, +111,110,73,110,100,101,112,101,110,100,101,110,99,101,100,105,118,105,100,101, +100,32,105,110,116,111,103,114,101,97,116,101,114,32,116,104,97,110,97,99,104, +105,101,118,101,109,101,110,116,115,101,115,116,97,98,108,105,115,104,105,110, +103,74,97,118,97,83,99,114,105,112,116,34,32,110,101,118,101,114,116,104,101,108 +,101,115,115,115,105,103,110,105,102,105,99,97,110,99,101,66,114,111,97,100,99, +97,115,116,105,110,103,62,38,110,98,115,112,59,60,47,116,100,62,99,111,110,116, +97,105,110,101,114,34,62,10,115,117,99,104,32,97,115,32,116,104,101,32,105,110, +102,108,117,101,110,99,101,32,111,102,97,32,112,97,114,116,105,99,117,108,97,114 +,115,114,99,61,39,104,116,116,112,58,47,47,110,97,118,105,103,97,116,105,111,110 +,34,32,104,97,108,102,32,111,102,32,116,104,101,32,115,117,98,115,116,97,110,116 +,105,97,108,32,38,110,98,115,112,59,60,47,100,105,118,62,97,100,118,97,110,116, +97,103,101,32,111,102,100,105,115,99,111,118,101,114,121,32,111,102,102,117,110, +100,97,109,101,110,116,97,108,32,109,101,116,114,111,112,111,108,105,116,97,110, +116,104,101,32,111,112,112,111,115,105,116,101,34,32,120,109,108,58,108,97,110, +103,61,34,100,101,108,105,98,101,114,97,116,101,108,121,97,108,105,103,110,61,99 +,101,110,116,101,114,101,118,111,108,117,116,105,111,110,32,111,102,112,114,101, +115,101,114,118,97,116,105,111,110,105,109,112,114,111,118,101,109,101,110,116, +115,98,101,103,105,110,110,105,110,103,32,105,110,74,101,115,117,115,32,67,104, +114,105,115,116,80,117,98,108,105,99,97,116,105,111,110,115,100,105,115,97,103, +114,101,101,109,101,110,116,116,101,120,116,45,97,108,105,103,110,58,114,44,32, +102,117,110,99,116,105,111,110,40,41,115,105,109,105,108,97,114,105,116,105,101, +115,98,111,100,121,62,60,47,104,116,109,108,62,105,115,32,99,117,114,114,101,110 +,116,108,121,97,108,112,104,97,98,101,116,105,99,97,108,105,115,32,115,111,109, +101,116,105,109,101,115,116,121,112,101,61,34,105,109,97,103,101,47,109,97,110, +121,32,111,102,32,116,104,101,32,102,108,111,119,58,104,105,100,100,101,110,59, +97,118,97,105,108,97,98,108,101,32,105,110,100,101,115,99,114,105,98,101,32,116, +104,101,101,120,105,115,116,101,110,99,101,32,111,102,97,108,108,32,111,118,101, +114,32,116,104,101,116,104,101,32,73,110,116,101,114,110,101,116,9,60,117,108,32 +,99,108,97,115,115,61,34,105,110,115,116,97,108,108,97,116,105,111,110,110,101, +105,103,104,98,111,114,104,111,111,100,97,114,109,101,100,32,102,111,114,99,101, +115,114,101,100,117,99,105,110,103,32,116,104,101,99,111,110,116,105,110,117,101 +,115,32,116,111,78,111,110,101,116,104,101,108,101,115,115,44,116,101,109,112, +101,114,97,116,117,114,101,115,10,9,9,60,97,32,104,114,101,102,61,34,99,108,111, +115,101,32,116,111,32,116,104,101,101,120,97,109,112,108,101,115,32,111,102,32, +105,115,32,97,98,111,117,116,32,116,104,101,40,115,101,101,32,98,101,108,111,119 +,41,46,34,32,105,100,61,34,115,101,97,114,99,104,112,114,111,102,101,115,115,105 +,111,110,97,108,105,115,32,97,118,97,105,108,97,98,108,101,116,104,101,32,111, +102,102,105,99,105,97,108,9,9,60,47,115,99,114,105,112,116,62,10,10,9,9,60,100, +105,118,32,105,100,61,34,97,99,99,101,108,101,114,97,116,105,111,110,116,104,114 +,111,117,103,104,32,116,104,101,32,72,97,108,108,32,111,102,32,70,97,109,101,100 +,101,115,99,114,105,112,116,105,111,110,115,116,114,97,110,115,108,97,116,105, +111,110,115,105,110,116,101,114,102,101,114,101,110,99,101,32,116,121,112,101,61 +,39,116,101,120,116,47,114,101,99,101,110,116,32,121,101,97,114,115,105,110,32, +116,104,101,32,119,111,114,108,100,118,101,114,121,32,112,111,112,117,108,97,114 +,123,98,97,99,107,103,114,111,117,110,100,58,116,114,97,100,105,116,105,111,110, +97,108,32,115,111,109,101,32,111,102,32,116,104,101,32,99,111,110,110,101,99,116 +,101,100,32,116,111,101,120,112,108,111,105,116,97,116,105,111,110,101,109,101, +114,103,101,110,99,101,32,111,102,99,111,110,115,116,105,116,117,116,105,111,110 +,65,32,72,105,115,116,111,114,121,32,111,102,115,105,103,110,105,102,105,99,97, +110,116,32,109,97,110,117,102,97,99,116,117,114,101,100,101,120,112,101,99,116, +97,116,105,111,110,115,62,60,110,111,115,99,114,105,112,116,62,60,99,97,110,32, +98,101,32,102,111,117,110,100,98,101,99,97,117,115,101,32,116,104,101,32,104,97, +115,32,110,111,116,32,98,101,101,110,110,101,105,103,104,98,111,117,114,105,110, +103,119,105,116,104,111,117,116,32,116,104,101,32,97,100,100,101,100,32,116,111, +32,116,104,101,9,60,108,105,32,99,108,97,115,115,61,34,105,110,115,116,114,117, +109,101,110,116,97,108,83,111,118,105,101,116,32,85,110,105,111,110,97,99,107, +110,111,119,108,101,100,103,101,100,119,104,105,99,104,32,99,97,110,32,98,101, +110,97,109,101,32,102,111,114,32,116,104,101,97,116,116,101,110,116,105,111,110, +32,116,111,97,116,116,101,109,112,116,115,32,116,111,32,100,101,118,101,108,111, +112,109,101,110,116,115,73,110,32,102,97,99,116,44,32,116,104,101,60,108,105,32, +99,108,97,115,115,61,34,97,105,109,112,108,105,99,97,116,105,111,110,115,115,117 +,105,116,97,98,108,101,32,102,111,114,109,117,99,104,32,111,102,32,116,104,101, +32,99,111,108,111,110,105,122,97,116,105,111,110,112,114,101,115,105,100,101,110 +,116,105,97,108,99,97,110,99,101,108,66,117,98,98,108,101,32,73,110,102,111,114, +109,97,116,105,111,110,109,111,115,116,32,111,102,32,116,104,101,32,105,115,32, +100,101,115,99,114,105,98,101,100,114,101,115,116,32,111,102,32,116,104,101,32, +109,111,114,101,32,111,114,32,108,101,115,115,105,110,32,83,101,112,116,101,109, +98,101,114,73,110,116,101,108,108,105,103,101,110,99,101,115,114,99,61,34,104, +116,116,112,58,47,47,112,120,59,32,104,101,105,103,104,116,58,32,97,118,97,105, +108,97,98,108,101,32,116,111,109,97,110,117,102,97,99,116,117,114,101,114,104, +117,109,97,110,32,114,105,103,104,116,115,108,105,110,107,32,104,114,101,102,61, +34,47,97,118,97,105,108,97,98,105,108,105,116,121,112,114,111,112,111,114,116, +105,111,110,97,108,111,117,116,115,105,100,101,32,116,104,101,32,97,115,116,114, +111,110,111,109,105,99,97,108,104,117,109,97,110,32,98,101,105,110,103,115,110, +97,109,101,32,111,102,32,116,104,101,32,97,114,101,32,102,111,117,110,100,32,105 +,110,97,114,101,32,98,97,115,101,100,32,111,110,115,109,97,108,108,101,114,32, +116,104,97,110,97,32,112,101,114,115,111,110,32,119,104,111,101,120,112,97,110, +115,105,111,110,32,111,102,97,114,103,117,105,110,103,32,116,104,97,116,110,111, +119,32,107,110,111,119,110,32,97,115,73,110,32,116,104,101,32,101,97,114,108,121 +,105,110,116,101,114,109,101,100,105,97,116,101,100,101,114,105,118,101,100,32, +102,114,111,109,83,99,97,110,100,105,110,97,118,105,97,110,60,47,97,62,60,47,100 +,105,118,62,13,10,99,111,110,115,105,100,101,114,32,116,104,101,97,110,32,101, +115,116,105,109,97,116,101,100,116,104,101,32,78,97,116,105,111,110,97,108,60, +100,105,118,32,105,100,61,34,112,97,103,114,101,115,117,108,116,105,110,103,32, +105,110,99,111,109,109,105,115,115,105,111,110,101,100,97,110,97,108,111,103,111 +,117,115,32,116,111,97,114,101,32,114,101,113,117,105,114,101,100,47,117,108,62, +10,60,47,100,105,118,62,10,119,97,115,32,98,97,115,101,100,32,111,110,97,110,100 +,32,98,101,99,97,109,101,32,97,38,110,98,115,112,59,38,110,98,115,112,59,116,34, +32,118,97,108,117,101,61,34,34,32,119,97,115,32,99,97,112,116,117,114,101,100, +110,111,32,109,111,114,101,32,116,104,97,110,114,101,115,112,101,99,116,105,118, +101,108,121,99,111,110,116,105,110,117,101,32,116,111,32,62,13,10,60,104,101,97, +100,62,13,10,60,119,101,114,101,32,99,114,101,97,116,101,100,109,111,114,101,32, +103,101,110,101,114,97,108,105,110,102,111,114,109,97,116,105,111,110,32,117,115 +,101,100,32,102,111,114,32,116,104,101,105,110,100,101,112,101,110,100,101,110, +116,32,116,104,101,32,73,109,112,101,114,105,97,108,99,111,109,112,111,110,101, +110,116,32,111,102,116,111,32,116,104,101,32,110,111,114,116,104,105,110,99,108, +117,100,101,32,116,104,101,32,67,111,110,115,116,114,117,99,116,105,111,110,115, +105,100,101,32,111,102,32,116,104,101,32,119,111,117,108,100,32,110,111,116,32, +98,101,102,111,114,32,105,110,115,116,97,110,99,101,105,110,118,101,110,116,105, +111,110,32,111,102,109,111,114,101,32,99,111,109,112,108,101,120,99,111,108,108, +101,99,116,105,118,101,108,121,98,97,99,107,103,114,111,117,110,100,58,32,116, +101,120,116,45,97,108,105,103,110,58,32,105,116,115,32,111,114,105,103,105,110, +97,108,105,110,116,111,32,97,99,99,111,117,110,116,116,104,105,115,32,112,114, +111,99,101,115,115,97,110,32,101,120,116,101,110,115,105,118,101,104,111,119,101 +,118,101,114,44,32,116,104,101,116,104,101,121,32,97,114,101,32,110,111,116,114, +101,106,101,99,116,101,100,32,116,104,101,99,114,105,116,105,99,105,115,109,32, +111,102,100,117,114,105,110,103,32,119,104,105,99,104,112,114,111,98,97,98,108, +121,32,116,104,101,116,104,105,115,32,97,114,116,105,99,108,101,40,102,117,110, +99,116,105,111,110,40,41,123,73,116,32,115,104,111,117,108,100,32,98,101,97,110, +32,97,103,114,101,101,109,101,110,116,97,99,99,105,100,101,110,116,97,108,108, +121,100,105,102,102,101,114,115,32,102,114,111,109,65,114,99,104,105,116,101,99, +116,117,114,101,98,101,116,116,101,114,32,107,110,111,119,110,97,114,114,97,110, +103,101,109,101,110,116,115,105,110,102,108,117,101,110,99,101,32,111,110,97,116 +,116,101,110,100,101,100,32,116,104,101,105,100,101,110,116,105,99,97,108,32,116 +,111,115,111,117,116,104,32,111,102,32,116,104,101,112,97,115,115,32,116,104,114 +,111,117,103,104,120,109,108,34,32,116,105,116,108,101,61,34,119,101,105,103,104 +,116,58,98,111,108,100,59,99,114,101,97,116,105,110,103,32,116,104,101,100,105, +115,112,108,97,121,58,110,111,110,101,114,101,112,108,97,99,101,100,32,116,104, +101,60,105,109,103,32,115,114,99,61,34,47,105,104,116,116,112,115,58,47,47,119, +119,119,46,87,111,114,108,100,32,87,97,114,32,73,73,116,101,115,116,105,109,111, +110,105,97,108,115,102,111,117,110,100,32,105,110,32,116,104,101,114,101,113,117 +,105,114,101,100,32,116,111,32,97,110,100,32,116,104,97,116,32,116,104,101,98, +101,116,119,101,101,110,32,116,104,101,32,119,97,115,32,100,101,115,105,103,110, +101,100,99,111,110,115,105,115,116,115,32,111,102,32,99,111,110,115,105,100,101, +114,97,98,108,121,112,117,98,108,105,115,104,101,100,32,98,121,116,104,101,32, +108,97,110,103,117,97,103,101,67,111,110,115,101,114,118,97,116,105,111,110,99, +111,110,115,105,115,116,101,100,32,111,102,114,101,102,101,114,32,116,111,32,116 +,104,101,98,97,99,107,32,116,111,32,116,104,101,32,99,115,115,34,32,109,101,100, +105,97,61,34,80,101,111,112,108,101,32,102,114,111,109,32,97,118,97,105,108,97, +98,108,101,32,111,110,112,114,111,118,101,100,32,116,111,32,98,101,115,117,103, +103,101,115,116,105,111,110,115,34,119,97,115,32,107,110,111,119,110,32,97,115, +118,97,114,105,101,116,105,101,115,32,111,102,108,105,107,101,108,121,32,116,111 +,32,98,101,99,111,109,112,114,105,115,101,100,32,111,102,115,117,112,112,111,114 +,116,32,116,104,101,32,104,97,110,100,115,32,111,102,32,116,104,101,99,111,117, +112,108,101,100,32,119,105,116,104,99,111,110,110,101,99,116,32,97,110,100,32,98 +,111,114,100,101,114,58,110,111,110,101,59,112,101,114,102,111,114,109,97,110,99 +,101,115,98,101,102,111,114,101,32,98,101,105,110,103,108,97,116,101,114,32,98, +101,99,97,109,101,99,97,108,99,117,108,97,116,105,111,110,115,111,102,116,101, +110,32,99,97,108,108,101,100,114,101,115,105,100,101,110,116,115,32,111,102,109, +101,97,110,105,110,103,32,116,104,97,116,62,60,108,105,32,99,108,97,115,115,61, +34,101,118,105,100,101,110,99,101,32,102,111,114,101,120,112,108,97,110,97,116, +105,111,110,115,101,110,118,105,114,111,110,109,101,110,116,115,34,62,60,47,97, +62,60,47,100,105,118,62,119,104,105,99,104,32,97,108,108,111,119,115,73,110,116, +114,111,100,117,99,116,105,111,110,100,101,118,101,108,111,112,101,100,32,98,121 +,97,32,119,105,100,101,32,114,97,110,103,101,111,110,32,98,101,104,97,108,102,32 +,111,102,118,97,108,105,103,110,61,34,116,111,112,34,112,114,105,110,99,105,112, +108,101,32,111,102,97,116,32,116,104,101,32,116,105,109,101,44,60,47,110,111,115 +,99,114,105,112,116,62,13,115,97,105,100,32,116,111,32,104,97,118,101,105,110,32 +,116,104,101,32,102,105,114,115,116,119,104,105,108,101,32,111,116,104,101,114, +115,104,121,112,111,116,104,101,116,105,99,97,108,112,104,105,108,111,115,111, +112,104,101,114,115,112,111,119,101,114,32,111,102,32,116,104,101,99,111,110,116 +,97,105,110,101,100,32,105,110,112,101,114,102,111,114,109,101,100,32,98,121,105 +,110,97,98,105,108,105,116,121,32,116,111,119,101,114,101,32,119,114,105,116,116 +,101,110,115,112,97,110,32,115,116,121,108,101,61,34,105,110,112,117,116,32,110, +97,109,101,61,34,116,104,101,32,113,117,101,115,116,105,111,110,105,110,116,101, +110,100,101,100,32,102,111,114,114,101,106,101,99,116,105,111,110,32,111,102,105 +,109,112,108,105,101,115,32,116,104,97,116,105,110,118,101,110,116,101,100,32, +116,104,101,116,104,101,32,115,116,97,110,100,97,114,100,119,97,115,32,112,114, +111,98,97,98,108,121,108,105,110,107,32,98,101,116,119,101,101,110,112,114,111, +102,101,115,115,111,114,32,111,102,105,110,116,101,114,97,99,116,105,111,110,115 +,99,104,97,110,103,105,110,103,32,116,104,101,73,110,100,105,97,110,32,79,99,101 +,97,110,32,99,108,97,115,115,61,34,108,97,115,116,119,111,114,107,105,110,103,32 +,119,105,116,104,39,104,116,116,112,58,47,47,119,119,119,46,121,101,97,114,115, +32,98,101,102,111,114,101,84,104,105,115,32,119,97,115,32,116,104,101,114,101,99 +,114,101,97,116,105,111,110,97,108,101,110,116,101,114,105,110,103,32,116,104, +101,109,101,97,115,117,114,101,109,101,110,116,115,97,110,32,101,120,116,114,101 +,109,101,108,121,118,97,108,117,101,32,111,102,32,116,104,101,115,116,97,114,116 +,32,111,102,32,116,104,101,10,60,47,115,99,114,105,112,116,62,10,10,97,110,32, +101,102,102,111,114,116,32,116,111,105,110,99,114,101,97,115,101,32,116,104,101, +116,111,32,116,104,101,32,115,111,117,116,104,115,112,97,99,105,110,103,61,34,48 +,34,62,115,117,102,102,105,99,105,101,110,116,108,121,116,104,101,32,69,117,114, +111,112,101,97,110,99,111,110,118,101,114,116,101,100,32,116,111,99,108,101,97, +114,84,105,109,101,111,117,116,100,105,100,32,110,111,116,32,104,97,118,101,99, +111,110,115,101,113,117,101,110,116,108,121,102,111,114,32,116,104,101,32,110, +101,120,116,101,120,116,101,110,115,105,111,110,32,111,102,101,99,111,110,111, +109,105,99,32,97,110,100,97,108,116,104,111,117,103,104,32,116,104,101,97,114, +101,32,112,114,111,100,117,99,101,100,97,110,100,32,119,105,116,104,32,116,104, +101,105,110,115,117,102,102,105,99,105,101,110,116,103,105,118,101,110,32,98,121 +,32,116,104,101,115,116,97,116,105,110,103,32,116,104,97,116,101,120,112,101,110 +,100,105,116,117,114,101,115,60,47,115,112,97,110,62,60,47,97,62,10,116,104,111, +117,103,104,116,32,116,104,97,116,111,110,32,116,104,101,32,98,97,115,105,115,99 +,101,108,108,112,97,100,100,105,110,103,61,105,109,97,103,101,32,111,102,32,116, +104,101,114,101,116,117,114,110,105,110,103,32,116,111,105,110,102,111,114,109, +97,116,105,111,110,44,115,101,112,97,114,97,116,101,100,32,98,121,97,115,115,97, +115,115,105,110,97,116,101,100,115,34,32,99,111,110,116,101,110,116,61,34,97,117 +,116,104,111,114,105,116,121,32,111,102,110,111,114,116,104,119,101,115,116,101, +114,110,60,47,100,105,118,62,10,60,100,105,118,32,34,62,60,47,100,105,118,62,13, +10,32,32,99,111,110,115,117,108,116,97,116,105,111,110,99,111,109,109,117,110, +105,116,121,32,111,102,116,104,101,32,110,97,116,105,111,110,97,108,105,116,32, +115,104,111,117,108,100,32,98,101,112,97,114,116,105,99,105,112,97,110,116,115, +32,97,108,105,103,110,61,34,108,101,102,116,116,104,101,32,103,114,101,97,116, +101,115,116,115,101,108,101,99,116,105,111,110,32,111,102,115,117,112,101,114, +110,97,116,117,114,97,108,100,101,112,101,110,100,101,110,116,32,111,110,105,115 +,32,109,101,110,116,105,111,110,101,100,97,108,108,111,119,105,110,103,32,116, +104,101,119,97,115,32,105,110,118,101,110,116,101,100,97,99,99,111,109,112,97, +110,121,105,110,103,104,105,115,32,112,101,114,115,111,110,97,108,97,118,97,105, +108,97,98,108,101,32,97,116,115,116,117,100,121,32,111,102,32,116,104,101,111, +110,32,116,104,101,32,111,116,104,101,114,101,120,101,99,117,116,105,111,110,32, +111,102,72,117,109,97,110,32,82,105,103,104,116,115,116,101,114,109,115,32,111, +102,32,116,104,101,97,115,115,111,99,105,97,116,105,111,110,115,114,101,115,101, +97,114,99,104,32,97,110,100,115,117,99,99,101,101,100,101,100,32,98,121,100,101, +102,101,97,116,101,100,32,116,104,101,97,110,100,32,102,114,111,109,32,116,104, +101,98,117,116,32,116,104,101,121,32,97,114,101,99,111,109,109,97,110,100,101, +114,32,111,102,115,116,97,116,101,32,111,102,32,116,104,101,121,101,97,114,115, +32,111,102,32,97,103,101,116,104,101,32,115,116,117,100,121,32,111,102,60,117, +108,32,99,108,97,115,115,61,34,115,112,108,97,99,101,32,105,110,32,116,104,101, +119,104,101,114,101,32,104,101,32,119,97,115,60,108,105,32,99,108,97,115,115,61, +34,102,116,104,101,114,101,32,97,114,101,32,110,111,119,104,105,99,104,32,98,101 +,99,97,109,101,104,101,32,112,117,98,108,105,115,104,101,100,101,120,112,114,101 +,115,115,101,100,32,105,110,116,111,32,119,104,105,99,104,32,116,104,101,99,111, +109,109,105,115,115,105,111,110,101,114,102,111,110,116,45,119,101,105,103,104, +116,58,116,101,114,114,105,116,111,114,121,32,111,102,101,120,116,101,110,115, +105,111,110,115,34,62,82,111,109,97,110,32,69,109,112,105,114,101,101,113,117,97 +,108,32,116,111,32,116,104,101,73,110,32,99,111,110,116,114,97,115,116,44,104, +111,119,101,118,101,114,44,32,97,110,100,105,115,32,116,121,112,105,99,97,108, +108,121,97,110,100,32,104,105,115,32,119,105,102,101,40,97,108,115,111,32,99,97, +108,108,101,100,62,60,117,108,32,99,108,97,115,115,61,34,101,102,102,101,99,116, +105,118,101,108,121,32,101,118,111,108,118,101,100,32,105,110,116,111,115,101, +101,109,32,116,111,32,104,97,118,101,119,104,105,99,104,32,105,115,32,116,104, +101,116,104,101,114,101,32,119,97,115,32,110,111,97,110,32,101,120,99,101,108, +108,101,110,116,97,108,108,32,111,102,32,116,104,101,115,101,100,101,115,99,114, +105,98,101,100,32,98,121,73,110,32,112,114,97,99,116,105,99,101,44,98,114,111,97 +,100,99,97,115,116,105,110,103,99,104,97,114,103,101,100,32,119,105,116,104,114, +101,102,108,101,99,116,101,100,32,105,110,115,117,98,106,101,99,116,101,100,32, +116,111,109,105,108,105,116,97,114,121,32,97,110,100,116,111,32,116,104,101,32, +112,111,105,110,116,101,99,111,110,111,109,105,99,97,108,108,121,115,101,116,84, +97,114,103,101,116,105,110,103,97,114,101,32,97,99,116,117,97,108,108,121,118, +105,99,116,111,114,121,32,111,118,101,114,40,41,59,60,47,115,99,114,105,112,116, +62,99,111,110,116,105,110,117,111,117,115,108,121,114,101,113,117,105,114,101, +100,32,102,111,114,101,118,111,108,117,116,105,111,110,97,114,121,97,110,32,101, +102,102,101,99,116,105,118,101,110,111,114,116,104,32,111,102,32,116,104,101,44, +32,119,104,105,99,104,32,119,97,115,32,102,114,111,110,116,32,111,102,32,116,104 +,101,111,114,32,111,116,104,101,114,119,105,115,101,115,111,109,101,32,102,111, +114,109,32,111,102,104,97,100,32,110,111,116,32,98,101,101,110,103,101,110,101, +114,97,116,101,100,32,98,121,105,110,102,111,114,109,97,116,105,111,110,46,112, +101,114,109,105,116,116,101,100,32,116,111,105,110,99,108,117,100,101,115,32,116 +,104,101,100,101,118,101,108,111,112,109,101,110,116,44,101,110,116,101,114,101, +100,32,105,110,116,111,116,104,101,32,112,114,101,118,105,111,117,115,99,111,110 +,115,105,115,116,101,110,116,108,121,97,114,101,32,107,110,111,119,110,32,97,115 +,116,104,101,32,102,105,101,108,100,32,111,102,116,104,105,115,32,116,121,112, +101,32,111,102,103,105,118,101,110,32,116,111,32,116,104,101,116,104,101,32,116, +105,116,108,101,32,111,102,99,111,110,116,97,105,110,115,32,116,104,101,105,110, +115,116,97,110,99,101,115,32,111,102,105,110,32,116,104,101,32,110,111,114,116, +104,100,117,101,32,116,111,32,116,104,101,105,114,97,114,101,32,100,101,115,105, +103,110,101,100,99,111,114,112,111,114,97,116,105,111,110,115,119,97,115,32,116, +104,97,116,32,116,104,101,111,110,101,32,111,102,32,116,104,101,115,101,109,111, +114,101,32,112,111,112,117,108,97,114,115,117,99,99,101,101,100,101,100,32,105, +110,115,117,112,112,111,114,116,32,102,114,111,109,105,110,32,100,105,102,102, +101,114,101,110,116,100,111,109,105,110,97,116,101,100,32,98,121,100,101,115,105 +,103,110,101,100,32,102,111,114,111,119,110,101,114,115,104,105,112,32,111,102, +97,110,100,32,112,111,115,115,105,98,108,121,115,116,97,110,100,97,114,100,105, +122,101,100,114,101,115,112,111,110,115,101,84,101,120,116,119,97,115,32,105,110 +,116,101,110,100,101,100,114,101,99,101,105,118,101,100,32,116,104,101,97,115, +115,117,109,101,100,32,116,104,97,116,97,114,101,97,115,32,111,102,32,116,104, +101,112,114,105,109,97,114,105,108,121,32,105,110,116,104,101,32,98,97,115,105, +115,32,111,102,105,110,32,116,104,101,32,115,101,110,115,101,97,99,99,111,117, +110,116,115,32,102,111,114,100,101,115,116,114,111,121,101,100,32,98,121,97,116, +32,108,101,97,115,116,32,116,119,111,119,97,115,32,100,101,99,108,97,114,101,100 +,99,111,117,108,100,32,110,111,116,32,98,101,83,101,99,114,101,116,97,114,121,32 +,111,102,97,112,112,101,97,114,32,116,111,32,98,101,109,97,114,103,105,110,45, +116,111,112,58,49,47,94,92,115,43,124,92,115,43,36,47,103,101,41,123,116,104,114 +,111,119,32,101,125,59,116,104,101,32,115,116,97,114,116,32,111,102,116,119,111, +32,115,101,112,97,114,97,116,101,108,97,110,103,117,97,103,101,32,97,110,100,119 +,104,111,32,104,97,100,32,98,101,101,110,111,112,101,114,97,116,105,111,110,32, +111,102,100,101,97,116,104,32,111,102,32,116,104,101,114,101,97,108,32,110,117, +109,98,101,114,115,9,60,108,105,110,107,32,114,101,108,61,34,112,114,111,118,105 +,100,101,100,32,116,104,101,116,104,101,32,115,116,111,114,121,32,111,102,99,111 +,109,112,101,116,105,116,105,111,110,115,101,110,103,108,105,115,104,32,40,85,75 +,41,101,110,103,108,105,115,104,32,40,85,83,41,208,156,208,190,208,189,208,179, +208,190,208,187,208,161,209,128,208,191,209,129,208,186,208,184,209,129,209,128, +208,191,209,129,208,186,208,184,209,129,209,128,208,191,209,129,208,186,208,190, +217,132,216,185,216,177,216,168,217,138,216,169,230,173,163,233,171,148,228,184, +173,230,150,135,231,174,128,228,189,147,228,184,173,230,150,135,231,185,129,228, +189,147,228,184,173,230,150,135,230,156,137,233,153,144,229,133,172,229,143,184, +228,186,186,230,176,145,230,148,191,229,186,156,233,152,191,233,135,140,229,183, +180,229,183,180,231,164,190,228,188,154,228,184,187,228,185,137,230,147,141,228, +189,156,231,179,187,231,187,159,230,148,191,231,173,150,230,179,149,232,167,132, +105,110,102,111,114,109,97,99,105,195,179,110,104,101,114,114,97,109,105,101,110 +,116,97,115,101,108,101,99,116,114,195,179,110,105,99,111,100,101,115,99,114,105 +,112,99,105,195,179,110,99,108,97,115,105,102,105,99,97,100,111,115,99,111,110, +111,99,105,109,105,101,110,116,111,112,117,98,108,105,99,97,99,105,195,179,110, +114,101,108,97,99,105,111,110,97,100,97,115,105,110,102,111,114,109,195,161,116, +105,99,97,114,101,108,97,99,105,111,110,97,100,111,115,100,101,112,97,114,116,97 +,109,101,110,116,111,116,114,97,98,97,106,97,100,111,114,101,115,100,105,114,101 +,99,116,97,109,101,110,116,101,97,121,117,110,116,97,109,105,101,110,116,111,109 +,101,114,99,97,100,111,76,105,98,114,101,99,111,110,116,195,161,99,116,101,110, +111,115,104,97,98,105,116,97,99,105,111,110,101,115,99,117,109,112,108,105,109, +105,101,110,116,111,114,101,115,116,97,117,114,97,110,116,101,115,100,105,115, +112,111,115,105,99,105,195,179,110,99,111,110,115,101,99,117,101,110,99,105,97, +101,108,101,99,116,114,195,179,110,105,99,97,97,112,108,105,99,97,99,105,111,110 +,101,115,100,101,115,99,111,110,101,99,116,97,100,111,105,110,115,116,97,108,97, +99,105,195,179,110,114,101,97,108,105,122,97,99,105,195,179,110,117,116,105,108, +105,122,97,99,105,195,179,110,101,110,99,105,99,108,111,112,101,100,105,97,101, +110,102,101,114,109,101,100,97,100,101,115,105,110,115,116,114,117,109,101,110, +116,111,115,101,120,112,101,114,105,101,110,99,105,97,115,105,110,115,116,105, +116,117,99,105,195,179,110,112,97,114,116,105,99,117,108,97,114,101,115,115,117, +98,99,97,116,101,103,111,114,105,97,209,130,208,190,208,187,209,140,208,186,208, +190,208,160,208,190,209,129,209,129,208,184,208,184,209,128,208,176,208,177,208, +190,209,130,209,139,208,177,208,190,208,187,209,140,209,136,208,181,208,191,209, +128,208,190,209,129,209,130,208,190,208,188,208,190,208,182,208,181,209,130,208, +181,208,180,209,128,209,131,208,179,208,184,209,133,209,129,208,187,209,131,209, +135,208,176,208,181,209,129,208,181,208,185,209,135,208,176,209,129,208,178,209, +129,208,181,208,179,208,180,208,176,208,160,208,190,209,129,209,129,208,184,209, +143,208,156,208,190,209,129,208,186,208,178,208,181,208,180,209,128,209,131,208, +179,208,184,208,181,208,179,208,190,209,128,208,190,208,180,208,176,208,178,208, +190,208,191,209,128,208,190,209,129,208,180,208,176,208,189,208,189,209,139,209, +133,208,180,208,190,208,187,208,182,208,189,209,139,208,184,208,188,208,181,208, +189,208,189,208,190,208,156,208,190,209,129,208,186,208,178,209,139,209,128,209, +131,208,177,208,187,208,181,208,185,208,156,208,190,209,129,208,186,208,178,208, +176,209,129,209,130,209,128,208,176,208,189,209,139,208,189,208,184,209,135,208, +181,208,179,208,190,209,128,208,176,208,177,208,190,209,130,208,181,208,180,208, +190,208,187,208,182,208,181,208,189,209,131,209,129,208,187,209,131,208,179,208, +184,209,130,208,181,208,191,208,181,209,128,209,140,208,158,208,180,208,189,208, +176,208,186,208,190,208,191,208,190,209,130,208,190,208,188,209,131,209,128,208, +176,208,177,208,190,209,130,209,131,208,176,208,191,209,128,208,181,208,187,209, +143,208,178,208,190,208,190,208,177,209,137,208,181,208,190,208,180,208,189,208, +190,208,179,208,190,209,129,208,178,208,190,208,181,208,179,208,190,209,129,209, +130,208,176,209,130,209,140,208,184,208,180,209,128,209,131,208,179,208,190,208, +185,209,132,208,190,209,128,209,131,208,188,208,181,209,133,208,190,209,128,208, +190,209,136,208,190,208,191,209,128,208,190,209,130,208,184,208,178,209,129,209, +129,209,139,208,187,208,186,208,176,208,186,208,176,208,182,208,180,209,139,208, +185,208,178,208,187,208,176,209,129,209,130,208,184,208,179,209,128,209,131,208, +191,208,191,209,139,208,178,208,188,208,181,209,129,209,130,208,181,209,128,208, +176,208,177,208,190,209,130,208,176,209,129,208,186,208,176,208,183,208,176,208, +187,208,191,208,181,209,128,208,178,209,139,208,185,208,180,208,181,208,187,208, +176,209,130,209,140,208,180,208,181,208,189,209,140,208,179,208,184,208,191,208, +181,209,128,208,184,208,190,208,180,208,177,208,184,208,183,208,189,208,181,209, +129,208,190,209,129,208,189,208,190,208,178,208,181,208,188,208,190,208,188,208, +181,208,189,209,130,208,186,209,131,208,191,208,184,209,130,209,140,208,180,208, +190,208,187,208,182,208,189,208,176,209,128,208,176,208,188,208,186,208,176,209, +133,208,189,208,176,209,135,208,176,208,187,208,190,208,160,208,176,208,177,208, +190,209,130,208,176,208,162,208,190,208,187,209,140,208,186,208,190,209,129,208, +190,208,178,209,129,208,181,208,188,208,178,209,130,208,190,209,128,208,190,208, +185,208,189,208,176,209,135,208,176,208,187,208,176,209,129,208,191,208,184,209, +129,208,190,208,186,209,129,208,187,209,131,208,182,208,177,209,139,209,129,208, +184,209,129,209,130,208,181,208,188,208,191,208,181,209,135,208,176,209,130,208, +184,208,189,208,190,208,178,208,190,208,179,208,190,208,191,208,190,208,188,208, +190,209,137,208,184,209,129,208,176,208,185,209,130,208,190,208,178,208,191,208, +190,209,135,208,181,208,188,209,131,208,191,208,190,208,188,208,190,209,137,209, +140,208,180,208,190,208,187,208,182,208,189,208,190,209,129,209,129,209,139,208, +187,208,186,208,184,208,177,209,139,209,129,209,130,209,128,208,190,208,180,208, +176,208,189,208,189,209,139,208,181,208,188,208,189,208,190,208,179,208,184,208, +181,208,191,209,128,208,190,208,181,208,186,209,130,208,161,208,181,208,185,209, +135,208,176,209,129,208,188,208,190,208,180,208,181,208,187,208,184,209,130,208, +176,208,186,208,190,208,179,208,190,208,190,208,189,208,187,208,176,208,185,208, +189,208,179,208,190,209,128,208,190,208,180,208,181,208,178,208,181,209,128,209, +129,208,184,209,143,209,129,209,130,209,128,208,176,208,189,208,181,209,132,208, +184,208,187,209,140,208,188,209,139,209,131,209,128,208,190,208,178,208,189,209, +143,209,128,208,176,208,183,208,189,209,139,209,133,208,184,209,129,208,186,208, +176,209,130,209,140,208,189,208,181,208,180,208,181,208,187,209,142,209,143,208, +189,208,178,208,176,209,128,209,143,208,188,208,181,208,189,209,140,209,136,208, +181,208,188,208,189,208,190,208,179,208,184,209,133,208,180,208,176,208,189,208, +189,208,190,208,185,208,183,208,189,208,176,209,135,208,184,209,130,208,189,208, +181,208,187,209,140,208,183,209,143,209,132,208,190,209,128,209,131,208,188,208, +176,208,162,208,181,208,191,208,181,209,128,209,140,208,188,208,181,209,129,209, +143,209,134,208,176,208,183,208,176,209,137,208,184,209,130,209,139,208,155,209, +131,209,135,209,136,208,184,208,181,224,164,168,224,164,185,224,165,128,224,164, +130,224,164,149,224,164,176,224,164,168,224,165,135,224,164,133,224,164,170,224, +164,168,224,165,135,224,164,149,224,164,191,224,164,175,224,164,190,224,164,149, +224,164,176,224,165,135,224,164,130,224,164,133,224,164,168,224,165,141,224,164, +175,224,164,149,224,165,141,224,164,175,224,164,190,224,164,151,224,164,190,224, +164,135,224,164,161,224,164,172,224,164,190,224,164,176,224,165,135,224,164,149, +224,164,191,224,164,184,224,165,128,224,164,166,224,164,191,224,164,175,224,164, +190,224,164,170,224,164,185,224,164,178,224,165,135,224,164,184,224,164,191,224, +164,130,224,164,185,224,164,173,224,164,190,224,164,176,224,164,164,224,164,133, +224,164,170,224,164,168,224,165,128,224,164,181,224,164,190,224,164,178,224,165, +135,224,164,184,224,165,135,224,164,181,224,164,190,224,164,149,224,164,176,224, +164,164,224,165,135,224,164,174,224,165,135,224,164,176,224,165,135,224,164,185, +224,165,139,224,164,168,224,165,135,224,164,184,224,164,149,224,164,164,224,165, +135,224,164,172,224,164,185,224,165,129,224,164,164,224,164,184,224,164,190,224, +164,135,224,164,159,224,164,185,224,165,139,224,164,151,224,164,190,224,164,156, +224,164,190,224,164,168,224,165,135,224,164,174,224,164,191,224,164,168,224,164, +159,224,164,149,224,164,176,224,164,164,224,164,190,224,164,149,224,164,176,224, +164,168,224,164,190,224,164,137,224,164,168,224,164,149,224,165,135,224,164,175, +224,164,185,224,164,190,224,164,129,224,164,184,224,164,172,224,164,184,224,165, +135,224,164,173,224,164,190,224,164,183,224,164,190,224,164,134,224,164,170,224, +164,149,224,165,135,224,164,178,224,164,191,224,164,175,224,165,135,224,164,182, +224,165,129,224,164,176,224,165,130,224,164,135,224,164,184,224,164,149,224,165, +135,224,164,152,224,164,130,224,164,159,224,165,135,224,164,174,224,165,135,224, +164,176,224,165,128,224,164,184,224,164,149,224,164,164,224,164,190,224,164,174, +224,165,135,224,164,176,224,164,190,224,164,178,224,165,135,224,164,149,224,164, +176,224,164,133,224,164,167,224,164,191,224,164,149,224,164,133,224,164,170,224, +164,168,224,164,190,224,164,184,224,164,174,224,164,190,224,164,156,224,164,174, +224,165,129,224,164,157,224,165,135,224,164,149,224,164,190,224,164,176,224,164, +163,224,164,185,224,165,139,224,164,164,224,164,190,224,164,149,224,164,161,224, +164,188,224,165,128,224,164,175,224,164,185,224,164,190,224,164,130,224,164,185, +224,165,139,224,164,159,224,164,178,224,164,182,224,164,172,224,165,141,224,164, +166,224,164,178,224,164,191,224,164,175,224,164,190,224,164,156,224,165,128,224, +164,181,224,164,168,224,164,156,224,164,190,224,164,164,224,164,190,224,164,149, +224,165,136,224,164,184,224,165,135,224,164,134,224,164,170,224,164,149,224,164, +190,224,164,181,224,164,190,224,164,178,224,165,128,224,164,166,224,165,135,224, +164,168,224,165,135,224,164,170,224,165,130,224,164,176,224,165,128,224,164,170, +224,164,190,224,164,168,224,165,128,224,164,137,224,164,184,224,164,149,224,165, +135,224,164,185,224,165,139,224,164,151,224,165,128,224,164,172,224,165,136,224, +164,160,224,164,149,224,164,134,224,164,170,224,164,149,224,165,128,224,164,181, +224,164,176,224,165,141,224,164,183,224,164,151,224,164,190,224,164,130,224,164, +181,224,164,134,224,164,170,224,164,149,224,165,139,224,164,156,224,164,191,224, +164,178,224,164,190,224,164,156,224,164,190,224,164,168,224,164,190,224,164,184, +224,164,185,224,164,174,224,164,164,224,164,185,224,164,174,224,165,135,224,164, +130,224,164,137,224,164,168,224,164,149,224,165,128,224,164,175,224,164,190,224, +164,185,224,165,130,224,164,166,224,164,176,224,165,141,224,164,156,224,164,184, +224,165,130,224,164,154,224,165,128,224,164,170,224,164,184,224,164,130,224,164, +166,224,164,184,224,164,181,224,164,190,224,164,178,224,164,185,224,165,139,224, +164,168,224,164,190,224,164,185,224,165,139,224,164,164,224,165,128,224,164,156, +224,165,136,224,164,184,224,165,135,224,164,181,224,164,190,224,164,170,224,164, +184,224,164,156,224,164,168,224,164,164,224,164,190,224,164,168,224,165,135,224, +164,164,224,164,190,224,164,156,224,164,190,224,164,176,224,165,128,224,164,152, +224,164,190,224,164,175,224,164,178,224,164,156,224,164,191,224,164,178,224,165, +135,224,164,168,224,165,128,224,164,154,224,165,135,224,164,156,224,164,190,224, +164,130,224,164,154,224,164,170,224,164,164,224,165,141,224,164,176,224,164,151, +224,165,130,224,164,151,224,164,178,224,164,156,224,164,190,224,164,164,224,165, +135,224,164,172,224,164,190,224,164,185,224,164,176,224,164,134,224,164,170,224, +164,168,224,165,135,224,164,181,224,164,190,224,164,185,224,164,168,224,164,135, +224,164,184,224,164,149,224,164,190,224,164,184,224,165,129,224,164,172,224,164, +185,224,164,176,224,164,185,224,164,168,224,165,135,224,164,135,224,164,184,224, +164,184,224,165,135,224,164,184,224,164,185,224,164,191,224,164,164,224,164,172, +224,164,161,224,164,188,224,165,135,224,164,152,224,164,159,224,164,168,224,164, +190,224,164,164,224,164,178,224,164,190,224,164,182,224,164,170,224,164,190,224, +164,130,224,164,154,224,164,182,224,165,141,224,164,176,224,165,128,224,164,172, +224,164,161,224,164,188,224,165,128,224,164,185,224,165,139,224,164,164,224,165, +135,224,164,184,224,164,190,224,164,136,224,164,159,224,164,182,224,164,190,224, +164,175,224,164,166,224,164,184,224,164,149,224,164,164,224,165,128,224,164,156, +224,164,190,224,164,164,224,165,128,224,164,181,224,164,190,224,164,178,224,164, +190,224,164,185,224,164,156,224,164,190,224,164,176,224,164,170,224,164,159,224, +164,168,224,164,190,224,164,176,224,164,150,224,164,168,224,165,135,224,164,184, +224,164,161,224,164,188,224,164,149,224,164,174,224,164,191,224,164,178,224,164, +190,224,164,137,224,164,184,224,164,149,224,165,128,224,164,149,224,165,135,224, +164,181,224,164,178,224,164,178,224,164,151,224,164,164,224,164,190,224,164,150, +224,164,190,224,164,168,224,164,190,224,164,133,224,164,176,224,165,141,224,164, +165,224,164,156,224,164,185,224,164,190,224,164,130,224,164,166,224,165,135,224, +164,150,224,164,190,224,164,170,224,164,185,224,164,178,224,165,128,224,164,168, +224,164,191,224,164,175,224,164,174,224,164,172,224,164,191,224,164,168,224,164, +190,224,164,172,224,165,136,224,164,130,224,164,149,224,164,149,224,164,185,224, +165,128,224,164,130,224,164,149,224,164,185,224,164,168,224,164,190,224,164,166, +224,165,135,224,164,164,224,164,190,224,164,185,224,164,174,224,164,178,224,165, +135,224,164,149,224,164,190,224,164,171,224,165,128,224,164,156,224,164,172,224, +164,149,224,164,191,224,164,164,224,165,129,224,164,176,224,164,164,224,164,174, +224,164,190,224,164,130,224,164,151,224,164,181,224,164,185,224,165,128,224,164, +130,224,164,176,224,165,139,224,164,156,224,164,188,224,164,174,224,164,191,224, +164,178,224,165,128,224,164,134,224,164,176,224,165,139,224,164,170,224,164,184, +224,165,135,224,164,168,224,164,190,224,164,175,224,164,190,224,164,166,224,164, +181,224,164,178,224,165,135,224,164,168,224,165,135,224,164,150,224,164,190,224, +164,164,224,164,190,224,164,149,224,164,176,224,165,128,224,164,172,224,164,137, +224,164,168,224,164,149,224,164,190,224,164,156,224,164,181,224,164,190,224,164, +172,224,164,170,224,165,130,224,164,176,224,164,190,224,164,172,224,164,161,224, +164,188,224,164,190,224,164,184,224,165,140,224,164,166,224,164,190,224,164,182, +224,165,135,224,164,175,224,164,176,224,164,149,224,164,191,224,164,175,224,165, +135,224,164,149,224,164,185,224,164,190,224,164,130,224,164,133,224,164,149,224, +164,184,224,164,176,224,164,172,224,164,168,224,164,190,224,164,143,224,164,181, +224,164,185,224,164,190,224,164,130,224,164,184,224,165,141,224,164,165,224,164, +178,224,164,174,224,164,191,224,164,178,224,165,135,224,164,178,224,165,135,224, +164,150,224,164,149,224,164,181,224,164,191,224,164,183,224,164,175,224,164,149, +224,165,141,224,164,176,224,164,130,224,164,184,224,164,174,224,165,130,224,164, +185,224,164,165,224,164,190,224,164,168,224,164,190,216,170,216,179,216,170,216, +183,217,138,216,185,217,133,216,180,216,167,216,177,217,131,216,169,216,168,217, +136,216,167,216,179,216,183,216,169,216,167,217,132,216,181,217,129,216,173,216, +169,217,133,217,136,216,167,216,182,217,138,216,185,216,167,217,132,216,174,216, +167,216,181,216,169,216,167,217,132,217,133,216,178,217,138,216,175,216,167,217, +132,216,185,216,167,217,133,216,169,216,167,217,132,217,131,216,167,216,170,216, +168,216,167,217,132,216,177,216,175,217,136,216,175,216,168,216,177,217,134,216, +167,217,133,216,172,216,167,217,132,216,175,217,136,217,132,216,169,216,167,217, +132,216,185,216,167,217,132,217,133,216,167,217,132,217,133,217,136,217,130,216, +185,216,167,217,132,216,185,216,177,216,168,217,138,216,167,217,132,216,179,216, +177,217,138,216,185,216,167,217,132,216,172,217,136,216,167,217,132,216,167,217, +132,216,176,217,135,216,167,216,168,216,167,217,132,216,173,217,138,216,167,216, +169,216,167,217,132,216,173,217,130,217,136,217,130,216,167,217,132,217,131,216, +177,217,138,217,133,216,167,217,132,216,185,216,177,216,167,217,130,217,133,216, +173,217,129,217,136,216,184,216,169,216,167,217,132,216,171,216,167,217,134,217, +138,217,133,216,180,216,167,217,135,216,175,216,169,216,167,217,132,217,133,216, +177,216,163,216,169,216,167,217,132,217,130,216,177,216,162,217,134,216,167,217, +132,216,180,216,168,216,167,216,168,216,167,217,132,216,173,217,136,216,167,216, +177,216,167,217,132,216,172,216,175,217,138,216,175,216,167,217,132,216,163,216, +179,216,177,216,169,216,167,217,132,216,185,217,132,217,136,217,133,217,133,216, +172,217,133,217,136,216,185,216,169,216,167,217,132,216,177,216,173,217,133,217, +134,216,167,217,132,217,134,217,130,216,167,216,183,217,129,217,132,216,179,216, +183,217,138,217,134,216,167,217,132,217,131,217,136,217,138,216,170,216,167,217, +132,216,175,217,134,217,138,216,167,216,168,216,177,217,131,216,167,216,170,217, +135,216,167,217,132,216,177,217,138,216,167,216,182,216,170,216,173,217,138,216, +167,216,170,217,138,216,168,216,170,217,136,217,130,217,138,216,170,216,167,217, +132,216,163,217,136,217,132,217,137,216,167,217,132,216,168,216,177,217,138,216, +175,216,167,217,132,217,131,217,132,216,167,217,133,216,167,217,132,216,177,216, +167,216,168,216,183,216,167,217,132,216,180,216,174,216,181,217,138,216,179,217, +138,216,167,216,177,216,167,216,170,216,167,217,132,216,171,216,167,217,132,216, +171,216,167,217,132,216,181,217,132,216,167,216,169,216,167,217,132,216,173,216, +175,217,138,216,171,216,167,217,132,216,178,217,136,216,167,216,177,216,167,217, +132,216,174,217,132,217,138,216,172,216,167,217,132,216,172,217,133,217,138,216, +185,216,167,217,132,216,185,216,167,217,133,217,135,216,167,217,132,216,172,217, +133,216,167,217,132,216,167,217,132,216,179,216,167,216,185,216,169,217,133,216, +180,216,167,217,135,216,175,217,135,216,167,217,132,216,177,216,166,217,138,216, +179,216,167,217,132,216,175,216,174,217,136,217,132,216,167,217,132,217,129,217, +134,217,138,216,169,216,167,217,132,217,131,216,170,216,167,216,168,216,167,217, +132,216,175,217,136,216,177,217,138,216,167,217,132,216,175,216,177,217,136,216, +179,216,167,216,179,216,170,216,186,216,177,217,130,216,170,216,181,216,167,217, +133,217,138,217,133,216,167,217,132,216,168,217,134,216,167,216,170,216,167,217, +132,216,185,216,184,217,138,217,133,101,110,116,101,114,116,97,105,110,109,101, +110,116,117,110,100,101,114,115,116,97,110,100,105,110,103,32,61,32,102,117,110, +99,116,105,111,110,40,41,46,106,112,103,34,32,119,105,100,116,104,61,34,99,111, +110,102,105,103,117,114,97,116,105,111,110,46,112,110,103,34,32,119,105,100,116, +104,61,34,60,98,111,100,121,32,99,108,97,115,115,61,34,77,97,116,104,46,114,97, +110,100,111,109,40,41,99,111,110,116,101,109,112,111,114,97,114,121,32,85,110, +105,116,101,100,32,83,116,97,116,101,115,99,105,114,99,117,109,115,116,97,110,99 +,101,115,46,97,112,112,101,110,100,67,104,105,108,100,40,111,114,103,97,110,105, +122,97,116,105,111,110,115,60,115,112,97,110,32,99,108,97,115,115,61,34,34,62,60 +,105,109,103,32,115,114,99,61,34,47,100,105,115,116,105,110,103,117,105,115,104, +101,100,116,104,111,117,115,97,110,100,115,32,111,102,32,99,111,109,109,117,110, +105,99,97,116,105,111,110,99,108,101,97,114,34,62,60,47,100,105,118,62,105,110, +118,101,115,116,105,103,97,116,105,111,110,102,97,118,105,99,111,110,46,105,99, +111,34,32,109,97,114,103,105,110,45,114,105,103,104,116,58,98,97,115,101,100,32, +111,110,32,116,104,101,32,77,97,115,115,97,99,104,117,115,101,116,116,115,116,97 +,98,108,101,32,98,111,114,100,101,114,61,105,110,116,101,114,110,97,116,105,111, +110,97,108,97,108,115,111,32,107,110,111,119,110,32,97,115,112,114,111,110,117, +110,99,105,97,116,105,111,110,98,97,99,107,103,114,111,117,110,100,58,35,102,112 +,97,100,100,105,110,103,45,108,101,102,116,58,70,111,114,32,101,120,97,109,112, +108,101,44,32,109,105,115,99,101,108,108,97,110,101,111,117,115,38,108,116,59,47 +,109,97,116,104,38,103,116,59,112,115,121,99,104,111,108,111,103,105,99,97,108, +105,110,32,112,97,114,116,105,99,117,108,97,114,101,97,114,99,104,34,32,116,121, +112,101,61,34,102,111,114,109,32,109,101,116,104,111,100,61,34,97,115,32,111,112 +,112,111,115,101,100,32,116,111,83,117,112,114,101,109,101,32,67,111,117,114,116 +,111,99,99,97,115,105,111,110,97,108,108,121,32,65,100,100,105,116,105,111,110, +97,108,108,121,44,78,111,114,116,104,32,65,109,101,114,105,99,97,112,120,59,98, +97,99,107,103,114,111,117,110,100,111,112,112,111,114,116,117,110,105,116,105, +101,115,69,110,116,101,114,116,97,105,110,109,101,110,116,46,116,111,76,111,119, +101,114,67,97,115,101,40,109,97,110,117,102,97,99,116,117,114,105,110,103,112, +114,111,102,101,115,115,105,111,110,97,108,32,99,111,109,98,105,110,101,100,32, +119,105,116,104,70,111,114,32,105,110,115,116,97,110,99,101,44,99,111,110,115, +105,115,116,105,110,103,32,111,102,34,32,109,97,120,108,101,110,103,116,104,61, +34,114,101,116,117,114,110,32,102,97,108,115,101,59,99,111,110,115,99,105,111, +117,115,110,101,115,115,77,101,100,105,116,101,114,114,97,110,101,97,110,101,120 +,116,114,97,111,114,100,105,110,97,114,121,97,115,115,97,115,115,105,110,97,116, +105,111,110,115,117,98,115,101,113,117,101,110,116,108,121,32,98,117,116,116,111 +,110,32,116,121,112,101,61,34,116,104,101,32,110,117,109,98,101,114,32,111,102, +116,104,101,32,111,114,105,103,105,110,97,108,32,99,111,109,112,114,101,104,101, +110,115,105,118,101,114,101,102,101,114,115,32,116,111,32,116,104,101,60,47,117, +108,62,10,60,47,100,105,118,62,10,112,104,105,108,111,115,111,112,104,105,99,97, +108,108,111,99,97,116,105,111,110,46,104,114,101,102,119,97,115,32,112,117,98, +108,105,115,104,101,100,83,97,110,32,70,114,97,110,99,105,115,99,111,40,102,117, +110,99,116,105,111,110,40,41,123,10,60,100,105,118,32,105,100,61,34,109,97,105, +110,115,111,112,104,105,115,116,105,99,97,116,101,100,109,97,116,104,101,109,97, +116,105,99,97,108,32,47,104,101,97,100,62,13,10,60,98,111,100,121,115,117,103, +103,101,115,116,115,32,116,104,97,116,100,111,99,117,109,101,110,116,97,116,105, +111,110,99,111,110,99,101,110,116,114,97,116,105,111,110,114,101,108,97,116,105, +111,110,115,104,105,112,115,109,97,121,32,104,97,118,101,32,98,101,101,110,40, +102,111,114,32,101,120,97,109,112,108,101,44,84,104,105,115,32,97,114,116,105,99 +,108,101,32,105,110,32,115,111,109,101,32,99,97,115,101,115,112,97,114,116,115, +32,111,102,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102, +71,114,101,97,116,32,66,114,105,116,97,105,110,32,99,101,108,108,112,97,100,100, +105,110,103,61,101,113,117,105,118,97,108,101,110,116,32,116,111,112,108,97,99, +101,104,111,108,100,101,114,61,34,59,32,102,111,110,116,45,115,105,122,101,58,32 +,106,117,115,116,105,102,105,99,97,116,105,111,110,98,101,108,105,101,118,101, +100,32,116,104,97,116,115,117,102,102,101,114,101,100,32,102,114,111,109,97,116, +116,101,109,112,116,101,100,32,116,111,32,108,101,97,100,101,114,32,111,102,32, +116,104,101,99,114,105,112,116,34,32,115,114,99,61,34,47,40,102,117,110,99,116, +105,111,110,40,41,32,123,97,114,101,32,97,118,97,105,108,97,98,108,101,10,9,60, +108,105,110,107,32,114,101,108,61,34,32,115,114,99,61,39,104,116,116,112,58,47, +47,105,110,116,101,114,101,115,116,101,100,32,105,110,99,111,110,118,101,110,116 +,105,111,110,97,108,32,34,32,97,108,116,61,34,34,32,47,62,60,47,97,114,101,32, +103,101,110,101,114,97,108,108,121,104,97,115,32,97,108,115,111,32,98,101,101, +110,109,111,115,116,32,112,111,112,117,108,97,114,32,99,111,114,114,101,115,112, +111,110,100,105,110,103,99,114,101,100,105,116,101,100,32,119,105,116,104,116, +121,108,101,61,34,98,111,114,100,101,114,58,60,47,97,62,60,47,115,112,97,110,62, +60,47,46,103,105,102,34,32,119,105,100,116,104,61,34,60,105,102,114,97,109,101, +32,115,114,99,61,34,116,97,98,108,101,32,99,108,97,115,115,61,34,105,110,108,105 +,110,101,45,98,108,111,99,107,59,97,99,99,111,114,100,105,110,103,32,116,111,32, +116,111,103,101,116,104,101,114,32,119,105,116,104,97,112,112,114,111,120,105, +109,97,116,101,108,121,112,97,114,108,105,97,109,101,110,116,97,114,121,109,111, +114,101,32,97,110,100,32,109,111,114,101,100,105,115,112,108,97,121,58,110,111, +110,101,59,116,114,97,100,105,116,105,111,110,97,108,108,121,112,114,101,100,111 +,109,105,110,97,110,116,108,121,38,110,98,115,112,59,124,38,110,98,115,112,59,38 +,110,98,115,112,59,60,47,115,112,97,110,62,32,99,101,108,108,115,112,97,99,105, +110,103,61,60,105,110,112,117,116,32,110,97,109,101,61,34,111,114,34,32,99,111, +110,116,101,110,116,61,34,99,111,110,116,114,111,118,101,114,115,105,97,108,112, +114,111,112,101,114,116,121,61,34,111,103,58,47,120,45,115,104,111,99,107,119,97 +,118,101,45,100,101,109,111,110,115,116,114,97,116,105,111,110,115,117,114,114, +111,117,110,100,101,100,32,98,121,78,101,118,101,114,116,104,101,108,101,115,115 +,44,119,97,115,32,116,104,101,32,102,105,114,115,116,99,111,110,115,105,100,101, +114,97,98,108,101,32,65,108,116,104,111,117,103,104,32,116,104,101,32,99,111,108 +,108,97,98,111,114,97,116,105,111,110,115,104,111,117,108,100,32,110,111,116,32, +98,101,112,114,111,112,111,114,116,105,111,110,32,111,102,60,115,112,97,110,32, +115,116,121,108,101,61,34,107,110,111,119,110,32,97,115,32,116,104,101,32,115, +104,111,114,116,108,121,32,97,102,116,101,114,102,111,114,32,105,110,115,116,97, +110,99,101,44,100,101,115,99,114,105,98,101,100,32,97,115,32,47,104,101,97,100, +62,10,60,98,111,100,121,32,115,116,97,114,116,105,110,103,32,119,105,116,104,105 +,110,99,114,101,97,115,105,110,103,108,121,32,116,104,101,32,102,97,99,116,32, +116,104,97,116,100,105,115,99,117,115,115,105,111,110,32,111,102,109,105,100,100 +,108,101,32,111,102,32,116,104,101,97,110,32,105,110,100,105,118,105,100,117,97, +108,100,105,102,102,105,99,117,108,116,32,116,111,32,112,111,105,110,116,32,111, +102,32,118,105,101,119,104,111,109,111,115,101,120,117,97,108,105,116,121,97,99, +99,101,112,116,97,110,99,101,32,111,102,60,47,115,112,97,110,62,60,47,100,105, +118,62,109,97,110,117,102,97,99,116,117,114,101,114,115,111,114,105,103,105,110, +32,111,102,32,116,104,101,99,111,109,109,111,110,108,121,32,117,115,101,100,105, +109,112,111,114,116,97,110,99,101,32,111,102,100,101,110,111,109,105,110,97,116, +105,111,110,115,98,97,99,107,103,114,111,117,110,100,58,32,35,108,101,110,103, +116,104,32,111,102,32,116,104,101,100,101,116,101,114,109,105,110,97,116,105,111 +,110,97,32,115,105,103,110,105,102,105,99,97,110,116,34,32,98,111,114,100,101, +114,61,34,48,34,62,114,101,118,111,108,117,116,105,111,110,97,114,121,112,114, +105,110,99,105,112,108,101,115,32,111,102,105,115,32,99,111,110,115,105,100,101, +114,101,100,119,97,115,32,100,101,118,101,108,111,112,101,100,73,110,100,111,45, +69,117,114,111,112,101,97,110,118,117,108,110,101,114,97,98,108,101,32,116,111, +112,114,111,112,111,110,101,110,116,115,32,111,102,97,114,101,32,115,111,109,101 +,116,105,109,101,115,99,108,111,115,101,114,32,116,111,32,116,104,101,78,101,119 +,32,89,111,114,107,32,67,105,116,121,32,110,97,109,101,61,34,115,101,97,114,99, +104,97,116,116,114,105,98,117,116,101,100,32,116,111,99,111,117,114,115,101,32, +111,102,32,116,104,101,109,97,116,104,101,109,97,116,105,99,105,97,110,98,121,32 +,116,104,101,32,101,110,100,32,111,102,97,116,32,116,104,101,32,101,110,100,32, +111,102,34,32,98,111,114,100,101,114,61,34,48,34,32,116,101,99,104,110,111,108, +111,103,105,99,97,108,46,114,101,109,111,118,101,67,108,97,115,115,40,98,114,97, +110,99,104,32,111,102,32,116,104,101,101,118,105,100,101,110,99,101,32,116,104, +97,116,33,91,101,110,100,105,102,93,45,45,62,13,10,73,110,115,116,105,116,117, +116,101,32,111,102,32,105,110,116,111,32,97,32,115,105,110,103,108,101,114,101, +115,112,101,99,116,105,118,101,108,121,46,97,110,100,32,116,104,101,114,101,102, +111,114,101,112,114,111,112,101,114,116,105,101,115,32,111,102,105,115,32,108, +111,99,97,116,101,100,32,105,110,115,111,109,101,32,111,102,32,119,104,105,99, +104,84,104,101,114,101,32,105,115,32,97,108,115,111,99,111,110,116,105,110,117, +101,100,32,116,111,32,97,112,112,101,97,114,97,110,99,101,32,111,102,32,38,97, +109,112,59,110,100,97,115,104,59,32,100,101,115,99,114,105,98,101,115,32,116,104 +,101,99,111,110,115,105,100,101,114,97,116,105,111,110,97,117,116,104,111,114,32 +,111,102,32,116,104,101,105,110,100,101,112,101,110,100,101,110,116,108,121,101, +113,117,105,112,112,101,100,32,119,105,116,104,100,111,101,115,32,110,111,116,32 +,104,97,118,101,60,47,97,62,60,97,32,104,114,101,102,61,34,99,111,110,102,117, +115,101,100,32,119,105,116,104,60,108,105,110,107,32,104,114,101,102,61,34,47,97 +,116,32,116,104,101,32,97,103,101,32,111,102,97,112,112,101,97,114,32,105,110,32 +,116,104,101,84,104,101,115,101,32,105,110,99,108,117,100,101,114,101,103,97,114 +,100,108,101,115,115,32,111,102,99,111,117,108,100,32,98,101,32,117,115,101,100, +32,115,116,121,108,101,61,38,113,117,111,116,59,115,101,118,101,114,97,108,32, +116,105,109,101,115,114,101,112,114,101,115,101,110,116,32,116,104,101,98,111, +100,121,62,10,60,47,104,116,109,108,62,116,104,111,117,103,104,116,32,116,111,32 +,98,101,112,111,112,117,108,97,116,105,111,110,32,111,102,112,111,115,115,105,98 +,105,108,105,116,105,101,115,112,101,114,99,101,110,116,97,103,101,32,111,102,97 +,99,99,101,115,115,32,116,111,32,116,104,101,97,110,32,97,116,116,101,109,112, +116,32,116,111,112,114,111,100,117,99,116,105,111,110,32,111,102,106,113,117,101 +,114,121,47,106,113,117,101,114,121,116,119,111,32,100,105,102,102,101,114,101, +110,116,98,101,108,111,110,103,32,116,111,32,116,104,101,101,115,116,97,98,108, +105,115,104,109,101,110,116,114,101,112,108,97,99,105,110,103,32,116,104,101,100 +,101,115,99,114,105,112,116,105,111,110,34,32,100,101,116,101,114,109,105,110, +101,32,116,104,101,97,118,97,105,108,97,98,108,101,32,102,111,114,65,99,99,111, +114,100,105,110,103,32,116,111,32,119,105,100,101,32,114,97,110,103,101,32,111, +102,9,60,100,105,118,32,99,108,97,115,115,61,34,109,111,114,101,32,99,111,109, +109,111,110,108,121,111,114,103,97,110,105,115,97,116,105,111,110,115,102,117, +110,99,116,105,111,110,97,108,105,116,121,119,97,115,32,99,111,109,112,108,101, +116,101,100,32,38,97,109,112,59,109,100,97,115,104,59,32,112,97,114,116,105,99, +105,112,97,116,105,111,110,116,104,101,32,99,104,97,114,97,99,116,101,114,97,110 +,32,97,100,100,105,116,105,111,110,97,108,97,112,112,101,97,114,115,32,116,111, +32,98,101,102,97,99,116,32,116,104,97,116,32,116,104,101,97,110,32,101,120,97, +109,112,108,101,32,111,102,115,105,103,110,105,102,105,99,97,110,116,108,121,111 +,110,109,111,117,115,101,111,118,101,114,61,34,98,101,99,97,117,115,101,32,116, +104,101,121,32,97,115,121,110,99,32,61,32,116,114,117,101,59,112,114,111,98,108, +101,109,115,32,119,105,116,104,115,101,101,109,115,32,116,111,32,104,97,118,101, +116,104,101,32,114,101,115,117,108,116,32,111,102,32,115,114,99,61,34,104,116, +116,112,58,47,47,102,97,109,105,108,105,97,114,32,119,105,116,104,112,111,115, +115,101,115,115,105,111,110,32,111,102,102,117,110,99,116,105,111,110,32,40,41, +32,123,116,111,111,107,32,112,108,97,99,101,32,105,110,97,110,100,32,115,111,109 +,101,116,105,109,101,115,115,117,98,115,116,97,110,116,105,97,108,108,121,60,115 +,112,97,110,62,60,47,115,112,97,110,62,105,115,32,111,102,116,101,110,32,117,115 +,101,100,105,110,32,97,110,32,97,116,116,101,109,112,116,103,114,101,97,116,32, +100,101,97,108,32,111,102,69,110,118,105,114,111,110,109,101,110,116,97,108,115, +117,99,99,101,115,115,102,117,108,108,121,32,118,105,114,116,117,97,108,108,121, +32,97,108,108,50,48,116,104,32,99,101,110,116,117,114,121,44,112,114,111,102,101 +,115,115,105,111,110,97,108,115,110,101,99,101,115,115,97,114,121,32,116,111,32, +100,101,116,101,114,109,105,110,101,100,32,98,121,99,111,109,112,97,116,105,98, +105,108,105,116,121,98,101,99,97,117,115,101,32,105,116,32,105,115,68,105,99,116 +,105,111,110,97,114,121,32,111,102,109,111,100,105,102,105,99,97,116,105,111,110 +,115,84,104,101,32,102,111,108,108,111,119,105,110,103,109,97,121,32,114,101,102 +,101,114,32,116,111,58,67,111,110,115,101,113,117,101,110,116,108,121,44,73,110, +116,101,114,110,97,116,105,111,110,97,108,97,108,116,104,111,117,103,104,32,115, +111,109,101,116,104,97,116,32,119,111,117,108,100,32,98,101,119,111,114,108,100, +39,115,32,102,105,114,115,116,99,108,97,115,115,105,102,105,101,100,32,97,115,98 +,111,116,116,111,109,32,111,102,32,116,104,101,40,112,97,114,116,105,99,117,108, +97,114,108,121,97,108,105,103,110,61,34,108,101,102,116,34,32,109,111,115,116,32 +,99,111,109,109,111,110,108,121,98,97,115,105,115,32,102,111,114,32,116,104,101, +102,111,117,110,100,97,116,105,111,110,32,111,102,99,111,110,116,114,105,98,117, +116,105,111,110,115,112,111,112,117,108,97,114,105,116,121,32,111,102,99,101,110 +,116,101,114,32,111,102,32,116,104,101,116,111,32,114,101,100,117,99,101,32,116, +104,101,106,117,114,105,115,100,105,99,116,105,111,110,115,97,112,112,114,111, +120,105,109,97,116,105,111,110,32,111,110,109,111,117,115,101,111,117,116,61,34, +78,101,119,32,84,101,115,116,97,109,101,110,116,99,111,108,108,101,99,116,105, +111,110,32,111,102,60,47,115,112,97,110,62,60,47,97,62,60,47,105,110,32,116,104, +101,32,85,110,105,116,101,100,102,105,108,109,32,100,105,114,101,99,116,111,114, +45,115,116,114,105,99,116,46,100,116,100,34,62,104,97,115,32,98,101,101,110,32, +117,115,101,100,114,101,116,117,114,110,32,116,111,32,116,104,101,97,108,116,104 +,111,117,103,104,32,116,104,105,115,99,104,97,110,103,101,32,105,110,32,116,104, +101,115,101,118,101,114,97,108,32,111,116,104,101,114,98,117,116,32,116,104,101, +114,101,32,97,114,101,117,110,112,114,101,99,101,100,101,110,116,101,100,105,115 +,32,115,105,109,105,108,97,114,32,116,111,101,115,112,101,99,105,97,108,108,121, +32,105,110,119,101,105,103,104,116,58,32,98,111,108,100,59,105,115,32,99,97,108, +108,101,100,32,116,104,101,99,111,109,112,117,116,97,116,105,111,110,97,108,105, +110,100,105,99,97,116,101,32,116,104,97,116,114,101,115,116,114,105,99,116,101, +100,32,116,111,9,60,109,101,116,97,32,110,97,109,101,61,34,97,114,101,32,116,121 +,112,105,99,97,108,108,121,99,111,110,102,108,105,99,116,32,119,105,116,104,72, +111,119,101,118,101,114,44,32,116,104,101,32,65,110,32,101,120,97,109,112,108, +101,32,111,102,99,111,109,112,97,114,101,100,32,119,105,116,104,113,117,97,110, +116,105,116,105,101,115,32,111,102,114,97,116,104,101,114,32,116,104,97,110,32, +97,99,111,110,115,116,101,108,108,97,116,105,111,110,110,101,99,101,115,115,97, +114,121,32,102,111,114,114,101,112,111,114,116,101,100,32,116,104,97,116,115,112 +,101,99,105,102,105,99,97,116,105,111,110,112,111,108,105,116,105,99,97,108,32, +97,110,100,38,110,98,115,112,59,38,110,98,115,112,59,60,114,101,102,101,114,101, +110,99,101,115,32,116,111,116,104,101,32,115,97,109,101,32,121,101,97,114,71,111 +,118,101,114,110,109,101,110,116,32,111,102,103,101,110,101,114,97,116,105,111, +110,32,111,102,104,97,118,101,32,110,111,116,32,98,101,101,110,115,101,118,101, +114,97,108,32,121,101,97,114,115,99,111,109,109,105,116,109,101,110,116,32,116, +111,9,9,60,117,108,32,99,108,97,115,115,61,34,118,105,115,117,97,108,105,122,97, +116,105,111,110,49,57,116,104,32,99,101,110,116,117,114,121,44,112,114,97,99,116 +,105,116,105,111,110,101,114,115,116,104,97,116,32,104,101,32,119,111,117,108, +100,97,110,100,32,99,111,110,116,105,110,117,101,100,111,99,99,117,112,97,116, +105,111,110,32,111,102,105,115,32,100,101,102,105,110,101,100,32,97,115,99,101, +110,116,114,101,32,111,102,32,116,104,101,116,104,101,32,97,109,111,117,110,116, +32,111,102,62,60,100,105,118,32,115,116,121,108,101,61,34,101,113,117,105,118,97 +,108,101,110,116,32,111,102,100,105,102,102,101,114,101,110,116,105,97,116,101, +98,114,111,117,103,104,116,32,97,98,111,117,116,109,97,114,103,105,110,45,108, +101,102,116,58,32,97,117,116,111,109,97,116,105,99,97,108,108,121,116,104,111, +117,103,104,116,32,111,102,32,97,115,83,111,109,101,32,111,102,32,116,104,101, +115,101,10,60,100,105,118,32,99,108,97,115,115,61,34,105,110,112,117,116,32,99, +108,97,115,115,61,34,114,101,112,108,97,99,101,100,32,119,105,116,104,105,115,32 +,111,110,101,32,111,102,32,116,104,101,101,100,117,99,97,116,105,111,110,32,97, +110,100,105,110,102,108,117,101,110,99,101,100,32,98,121,114,101,112,117,116,97, +116,105,111,110,32,97,115,10,60,109,101,116,97,32,110,97,109,101,61,34,97,99,99, +111,109,109,111,100,97,116,105,111,110,60,47,100,105,118,62,10,60,47,100,105,118 +,62,108,97,114,103,101,32,112,97,114,116,32,111,102,73,110,115,116,105,116,117, +116,101,32,102,111,114,116,104,101,32,115,111,45,99,97,108,108,101,100,32,97,103 +,97,105,110,115,116,32,116,104,101,32,73,110,32,116,104,105,115,32,99,97,115,101 +,44,119,97,115,32,97,112,112,111,105,110,116,101,100,99,108,97,105,109,101,100, +32,116,111,32,98,101,72,111,119,101,118,101,114,44,32,116,104,105,115,68,101,112 +,97,114,116,109,101,110,116,32,111,102,116,104,101,32,114,101,109,97,105,110,105 +,110,103,101,102,102,101,99,116,32,111,110,32,116,104,101,112,97,114,116,105,99, +117,108,97,114,108,121,32,100,101,97,108,32,119,105,116,104,32,116,104,101,10,60 +,100,105,118,32,115,116,121,108,101,61,34,97,108,109,111,115,116,32,97,108,119, +97,121,115,97,114,101,32,99,117,114,114,101,110,116,108,121,101,120,112,114,101, +115,115,105,111,110,32,111,102,112,104,105,108,111,115,111,112,104,121,32,111, +102,102,111,114,32,109,111,114,101,32,116,104,97,110,99,105,118,105,108,105,122, +97,116,105,111,110,115,111,110,32,116,104,101,32,105,115,108,97,110,100,115,101, +108,101,99,116,101,100,73,110,100,101,120,99,97,110,32,114,101,115,117,108,116, +32,105,110,34,32,118,97,108,117,101,61,34,34,32,47,62,116,104,101,32,115,116,114 +,117,99,116,117,114,101,32,47,62,60,47,97,62,60,47,100,105,118,62,77,97,110,121, +32,111,102,32,116,104,101,115,101,99,97,117,115,101,100,32,98,121,32,116,104,101 +,111,102,32,116,104,101,32,85,110,105,116,101,100,115,112,97,110,32,99,108,97, +115,115,61,34,109,99,97,110,32,98,101,32,116,114,97,99,101,100,105,115,32,114, +101,108,97,116,101,100,32,116,111,98,101,99,97,109,101,32,111,110,101,32,111,102 +,105,115,32,102,114,101,113,117,101,110,116,108,121,108,105,118,105,110,103,32, +105,110,32,116,104,101,116,104,101,111,114,101,116,105,99,97,108,108,121,70,111, +108,108,111,119,105,110,103,32,116,104,101,82,101,118,111,108,117,116,105,111, +110,97,114,121,103,111,118,101,114,110,109,101,110,116,32,105,110,105,115,32,100 +,101,116,101,114,109,105,110,101,100,116,104,101,32,112,111,108,105,116,105,99, +97,108,105,110,116,114,111,100,117,99,101,100,32,105,110,115,117,102,102,105,99, +105,101,110,116,32,116,111,100,101,115,99,114,105,112,116,105,111,110,34,62,115, +104,111,114,116,32,115,116,111,114,105,101,115,115,101,112,97,114,97,116,105,111 +,110,32,111,102,97,115,32,116,111,32,119,104,101,116,104,101,114,107,110,111,119 +,110,32,102,111,114,32,105,116,115,119,97,115,32,105,110,105,116,105,97,108,108, +121,100,105,115,112,108,97,121,58,98,108,111,99,107,105,115,32,97,110,32,101,120 +,97,109,112,108,101,116,104,101,32,112,114,105,110,99,105,112,97,108,99,111,110, +115,105,115,116,115,32,111,102,32,97,114,101,99,111,103,110,105,122,101,100,32, +97,115,47,98,111,100,121,62,60,47,104,116,109,108,62,97,32,115,117,98,115,116,97 +,110,116,105,97,108,114,101,99,111,110,115,116,114,117,99,116,101,100,104,101,97 +,100,32,111,102,32,115,116,97,116,101,114,101,115,105,115,116,97,110,99,101,32, +116,111,117,110,100,101,114,103,114,97,100,117,97,116,101,84,104,101,114,101,32, +97,114,101,32,116,119,111,103,114,97,118,105,116,97,116,105,111,110,97,108,97, +114,101,32,100,101,115,99,114,105,98,101,100,105,110,116,101,110,116,105,111,110 +,97,108,108,121,115,101,114,118,101,100,32,97,115,32,116,104,101,99,108,97,115, +115,61,34,104,101,97,100,101,114,111,112,112,111,115,105,116,105,111,110,32,116, +111,102,117,110,100,97,109,101,110,116,97,108,108,121,100,111,109,105,110,97,116 +,101,100,32,116,104,101,97,110,100,32,116,104,101,32,111,116,104,101,114,97,108, +108,105,97,110,99,101,32,119,105,116,104,119,97,115,32,102,111,114,99,101,100,32 +,116,111,114,101,115,112,101,99,116,105,118,101,108,121,44,97,110,100,32,112,111 +,108,105,116,105,99,97,108,105,110,32,115,117,112,112,111,114,116,32,111,102,112 +,101,111,112,108,101,32,105,110,32,116,104,101,50,48,116,104,32,99,101,110,116, +117,114,121,46,97,110,100,32,112,117,98,108,105,115,104,101,100,108,111,97,100, +67,104,97,114,116,98,101,97,116,116,111,32,117,110,100,101,114,115,116,97,110, +100,109,101,109,98,101,114,32,115,116,97,116,101,115,101,110,118,105,114,111,110 +,109,101,110,116,97,108,102,105,114,115,116,32,104,97,108,102,32,111,102,99,111, +117,110,116,114,105,101,115,32,97,110,100,97,114,99,104,105,116,101,99,116,117, +114,97,108,98,101,32,99,111,110,115,105,100,101,114,101,100,99,104,97,114,97,99, +116,101,114,105,122,101,100,99,108,101,97,114,73,110,116,101,114,118,97,108,97, +117,116,104,111,114,105,116,97,116,105,118,101,70,101,100,101,114,97,116,105,111 +,110,32,111,102,119,97,115,32,115,117,99,99,101,101,100,101,100,97,110,100,32, +116,104,101,114,101,32,97,114,101,97,32,99,111,110,115,101,113,117,101,110,99, +101,116,104,101,32,80,114,101,115,105,100,101,110,116,97,108,115,111,32,105,110, +99,108,117,100,101,100,102,114,101,101,32,115,111,102,116,119,97,114,101,115,117 +,99,99,101,115,115,105,111,110,32,111,102,100,101,118,101,108,111,112,101,100,32 +,116,104,101,119,97,115,32,100,101,115,116,114,111,121,101,100,97,119,97,121,32, +102,114,111,109,32,116,104,101,59,10,60,47,115,99,114,105,112,116,62,10,60,97, +108,116,104,111,117,103,104,32,116,104,101,121,102,111,108,108,111,119,101,100, +32,98,121,32,97,109,111,114,101,32,112,111,119,101,114,102,117,108,114,101,115, +117,108,116,101,100,32,105,110,32,97,85,110,105,118,101,114,115,105,116,121,32, +111,102,72,111,119,101,118,101,114,44,32,109,97,110,121,116,104,101,32,112,114, +101,115,105,100,101,110,116,72,111,119,101,118,101,114,44,32,115,111,109,101,105 +,115,32,116,104,111,117,103,104,116,32,116,111,117,110,116,105,108,32,116,104, +101,32,101,110,100,119,97,115,32,97,110,110,111,117,110,99,101,100,97,114,101,32 +,105,109,112,111,114,116,97,110,116,97,108,115,111,32,105,110,99,108,117,100,101 +,115,62,60,105,110,112,117,116,32,116,121,112,101,61,116,104,101,32,99,101,110, +116,101,114,32,111,102,32,68,79,32,78,79,84,32,65,76,84,69,82,117,115,101,100,32 +,116,111,32,114,101,102,101,114,116,104,101,109,101,115,47,63,115,111,114,116,61 +,116,104,97,116,32,104,97,100,32,98,101,101,110,116,104,101,32,98,97,115,105,115 +,32,102,111,114,104,97,115,32,100,101,118,101,108,111,112,101,100,105,110,32,116 +,104,101,32,115,117,109,109,101,114,99,111,109,112,97,114,97,116,105,118,101,108 +,121,100,101,115,99,114,105,98,101,100,32,116,104,101,115,117,99,104,32,97,115, +32,116,104,111,115,101,116,104,101,32,114,101,115,117,108,116,105,110,103,105, +115,32,105,109,112,111,115,115,105,98,108,101,118,97,114,105,111,117,115,32,111, +116,104,101,114,83,111,117,116,104,32,65,102,114,105,99,97,110,104,97,118,101,32 +,116,104,101,32,115,97,109,101,101,102,102,101,99,116,105,118,101,110,101,115, +115,105,110,32,119,104,105,99,104,32,99,97,115,101,59,32,116,101,120,116,45,97, +108,105,103,110,58,115,116,114,117,99,116,117,114,101,32,97,110,100,59,32,98,97, +99,107,103,114,111,117,110,100,58,114,101,103,97,114,100,105,110,103,32,116,104, +101,115,117,112,112,111,114,116,101,100,32,116,104,101,105,115,32,97,108,115,111 +,32,107,110,111,119,110,115,116,121,108,101,61,34,109,97,114,103,105,110,105,110 +,99,108,117,100,105,110,103,32,116,104,101,98,97,104,97,115,97,32,77,101,108,97, +121,117,110,111,114,115,107,32,98,111,107,109,195,165,108,110,111,114,115,107,32 +,110,121,110,111,114,115,107,115,108,111,118,101,110,197,161,196,141,105,110,97, +105,110,116,101,114,110,97,99,105,111,110,97,108,99,97,108,105,102,105,99,97,99, +105,195,179,110,99,111,109,117,110,105,99,97,99,105,195,179,110,99,111,110,115, +116,114,117,99,99,105,195,179,110,34,62,60,100,105,118,32,99,108,97,115,115,61, +34,100,105,115,97,109,98,105,103,117,97,116,105,111,110,68,111,109,97,105,110,78 +,97,109,101,39,44,32,39,97,100,109,105,110,105,115,116,114,97,116,105,111,110, +115,105,109,117,108,116,97,110,101,111,117,115,108,121,116,114,97,110,115,112, +111,114,116,97,116,105,111,110,73,110,116,101,114,110,97,116,105,111,110,97,108, +32,109,97,114,103,105,110,45,98,111,116,116,111,109,58,114,101,115,112,111,110, +115,105,98,105,108,105,116,121,60,33,91,101,110,100,105,102,93,45,45,62,10,60,47 +,62,60,109,101,116,97,32,110,97,109,101,61,34,105,109,112,108,101,109,101,110, +116,97,116,105,111,110,105,110,102,114,97,115,116,114,117,99,116,117,114,101,114 +,101,112,114,101,115,101,110,116,97,116,105,111,110,98,111,114,100,101,114,45,98 +,111,116,116,111,109,58,60,47,104,101,97,100,62,10,60,98,111,100,121,62,61,104, +116,116,112,37,51,65,37,50,70,37,50,70,60,102,111,114,109,32,109,101,116,104,111 +,100,61,34,109,101,116,104,111,100,61,34,112,111,115,116,34,32,47,102,97,118,105 +,99,111,110,46,105,99,111,34,32,125,41,59,10,60,47,115,99,114,105,112,116,62,10, +46,115,101,116,65,116,116,114,105,98,117,116,101,40,65,100,109,105,110,105,115, +116,114,97,116,105,111,110,61,32,110,101,119,32,65,114,114,97,121,40,41,59,60,33 +,91,101,110,100,105,102,93,45,45,62,13,10,100,105,115,112,108,97,121,58,98,108, +111,99,107,59,85,110,102,111,114,116,117,110,97,116,101,108,121,44,34,62,38,110, +98,115,112,59,60,47,100,105,118,62,47,102,97,118,105,99,111,110,46,105,99,111,34 +,62,61,39,115,116,121,108,101,115,104,101,101,116,39,32,105,100,101,110,116,105, +102,105,99,97,116,105,111,110,44,32,102,111,114,32,101,120,97,109,112,108,101,44 +,60,108,105,62,60,97,32,104,114,101,102,61,34,47,97,110,32,97,108,116,101,114, +110,97,116,105,118,101,97,115,32,97,32,114,101,115,117,108,116,32,111,102,112, +116,34,62,60,47,115,99,114,105,112,116,62,10,116,121,112,101,61,34,115,117,98, +109,105,116,34,32,10,40,102,117,110,99,116,105,111,110,40,41,32,123,114,101,99, +111,109,109,101,110,100,97,116,105,111,110,102,111,114,109,32,97,99,116,105,111, +110,61,34,47,116,114,97,110,115,102,111,114,109,97,116,105,111,110,114,101,99, +111,110,115,116,114,117,99,116,105,111,110,46,115,116,121,108,101,46,100,105,115 +,112,108,97,121,32,65,99,99,111,114,100,105,110,103,32,116,111,32,104,105,100, +100,101,110,34,32,110,97,109,101,61,34,97,108,111,110,103,32,119,105,116,104,32, +116,104,101,100,111,99,117,109,101,110,116,46,98,111,100,121,46,97,112,112,114, +111,120,105,109,97,116,101,108,121,32,67,111,109,109,117,110,105,99,97,116,105, +111,110,115,112,111,115,116,34,32,97,99,116,105,111,110,61,34,109,101,97,110,105 +,110,103,32,38,113,117,111,116,59,45,45,60,33,91,101,110,100,105,102,93,45,45,62 +,80,114,105,109,101,32,77,105,110,105,115,116,101,114,99,104,97,114,97,99,116, +101,114,105,115,116,105,99,60,47,97,62,32,60,97,32,99,108,97,115,115,61,116,104, +101,32,104,105,115,116,111,114,121,32,111,102,32,111,110,109,111,117,115,101,111 +,118,101,114,61,34,116,104,101,32,103,111,118,101,114,110,109,101,110,116,104, +114,101,102,61,34,104,116,116,112,115,58,47,47,119,97,115,32,111,114,105,103,105 +,110,97,108,108,121,119,97,115,32,105,110,116,114,111,100,117,99,101,100,99,108, +97,115,115,105,102,105,99,97,116,105,111,110,114,101,112,114,101,115,101,110,116 +,97,116,105,118,101,97,114,101,32,99,111,110,115,105,100,101,114,101,100,60,33, +91,101,110,100,105,102,93,45,45,62,10,10,100,101,112,101,110,100,115,32,111,110, +32,116,104,101,85,110,105,118,101,114,115,105,116,121,32,111,102,32,105,110,32, +99,111,110,116,114,97,115,116,32,116,111,32,112,108,97,99,101,104,111,108,100, +101,114,61,34,105,110,32,116,104,101,32,99,97,115,101,32,111,102,105,110,116,101 +,114,110,97,116,105,111,110,97,108,32,99,111,110,115,116,105,116,117,116,105,111 +,110,97,108,115,116,121,108,101,61,34,98,111,114,100,101,114,45,58,32,102,117, +110,99,116,105,111,110,40,41,32,123,66,101,99,97,117,115,101,32,111,102,32,116, +104,101,45,115,116,114,105,99,116,46,100,116,100,34,62,10,60,116,97,98,108,101, +32,99,108,97,115,115,61,34,97,99,99,111,109,112,97,110,105,101,100,32,98,121,97, +99,99,111,117,110,116,32,111,102,32,116,104,101,60,115,99,114,105,112,116,32,115 +,114,99,61,34,47,110,97,116,117,114,101,32,111,102,32,116,104,101,32,116,104,101 +,32,112,101,111,112,108,101,32,105,110,32,105,110,32,97,100,100,105,116,105,111, +110,32,116,111,115,41,59,32,106,115,46,105,100,32,61,32,105,100,34,32,119,105, +100,116,104,61,34,49,48,48,37,34,114,101,103,97,114,100,105,110,103,32,116,104, +101,32,82,111,109,97,110,32,67,97,116,104,111,108,105,99,97,110,32,105,110,100, +101,112,101,110,100,101,110,116,102,111,108,108,111,119,105,110,103,32,116,104, +101,32,46,103,105,102,34,32,119,105,100,116,104,61,34,49,116,104,101,32,102,111, +108,108,111,119,105,110,103,32,100,105,115,99,114,105,109,105,110,97,116,105,111 +,110,97,114,99,104,97,101,111,108,111,103,105,99,97,108,112,114,105,109,101,32, +109,105,110,105,115,116,101,114,46,106,115,34,62,60,47,115,99,114,105,112,116,62 +,99,111,109,98,105,110,97,116,105,111,110,32,111,102,32,109,97,114,103,105,110, +119,105,100,116,104,61,34,99,114,101,97,116,101,69,108,101,109,101,110,116,40, +119,46,97,116,116,97,99,104,69,118,101,110,116,40,60,47,97,62,60,47,116,100,62, +60,47,116,114,62,115,114,99,61,34,104,116,116,112,115,58,47,47,97,73,110,32,112, +97,114,116,105,99,117,108,97,114,44,32,97,108,105,103,110,61,34,108,101,102,116, +34,32,67,122,101,99,104,32,82,101,112,117,98,108,105,99,85,110,105,116,101,100, +32,75,105,110,103,100,111,109,99,111,114,114,101,115,112,111,110,100,101,110,99, +101,99,111,110,99,108,117,100,101,100,32,116,104,97,116,46,104,116,109,108,34,32 +,116,105,116,108,101,61,34,40,102,117,110,99,116,105,111,110,32,40,41,32,123,99, +111,109,101,115,32,102,114,111,109,32,116,104,101,97,112,112,108,105,99,97,116, +105,111,110,32,111,102,60,115,112,97,110,32,99,108,97,115,115,61,34,115,98,101, +108,105,101,118,101,100,32,116,111,32,98,101,101,109,101,110,116,40,39,115,99, +114,105,112,116,39,60,47,97,62,10,60,47,108,105,62,10,60,108,105,118,101,114,121 +,32,100,105,102,102,101,114,101,110,116,62,60,115,112,97,110,32,99,108,97,115, +115,61,34,111,112,116,105,111,110,32,118,97,108,117,101,61,34,40,97,108,115,111, +32,107,110,111,119,110,32,97,115,9,60,108,105,62,60,97,32,104,114,101,102,61,34, +62,60,105,110,112,117,116,32,110,97,109,101,61,34,115,101,112,97,114,97,116,101, +100,32,102,114,111,109,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32, +118,97,108,105,103,110,61,34,116,111,112,34,62,102,111,117,110,100,101,114,32, +111,102,32,116,104,101,97,116,116,101,109,112,116,105,110,103,32,116,111,32,99, +97,114,98,111,110,32,100,105,111,120,105,100,101,10,10,60,100,105,118,32,99,108, +97,115,115,61,34,99,108,97,115,115,61,34,115,101,97,114,99,104,45,47,98,111,100, +121,62,10,60,47,104,116,109,108,62,111,112,112,111,114,116,117,110,105,116,121, +32,116,111,99,111,109,109,117,110,105,99,97,116,105,111,110,115,60,47,104,101,97 +,100,62,13,10,60,98,111,100,121,32,115,116,121,108,101,61,34,119,105,100,116,104 +,58,84,105,225,186,191,110,103,32,86,105,225,187,135,116,99,104,97,110,103,101, +115,32,105,110,32,116,104,101,98,111,114,100,101,114,45,99,111,108,111,114,58,35 +,48,34,32,98,111,114,100,101,114,61,34,48,34,32,60,47,115,112,97,110,62,60,47, +100,105,118,62,60,119,97,115,32,100,105,115,99,111,118,101,114,101,100,34,32,116 +,121,112,101,61,34,116,101,120,116,34,32,41,59,10,60,47,115,99,114,105,112,116, +62,10,10,68,101,112,97,114,116,109,101,110,116,32,111,102,32,101,99,99,108,101, +115,105,97,115,116,105,99,97,108,116,104,101,114,101,32,104,97,115,32,98,101,101 +,110,114,101,115,117,108,116,105,110,103,32,102,114,111,109,60,47,98,111,100,121 +,62,60,47,104,116,109,108,62,104,97,115,32,110,101,118,101,114,32,98,101,101,110 +,116,104,101,32,102,105,114,115,116,32,116,105,109,101,105,110,32,114,101,115, +112,111,110,115,101,32,116,111,97,117,116,111,109,97,116,105,99,97,108,108,121, +32,60,47,100,105,118,62,10,10,60,100,105,118,32,105,119,97,115,32,99,111,110,115 +,105,100,101,114,101,100,112,101,114,99,101,110,116,32,111,102,32,116,104,101,34 +,32,47,62,60,47,97,62,60,47,100,105,118,62,99,111,108,108,101,99,116,105,111,110 +,32,111,102,32,100,101,115,99,101,110,100,101,100,32,102,114,111,109,115,101,99, +116,105,111,110,32,111,102,32,116,104,101,97,99,99,101,112,116,45,99,104,97,114, +115,101,116,116,111,32,98,101,32,99,111,110,102,117,115,101,100,109,101,109,98, +101,114,32,111,102,32,116,104,101,32,112,97,100,100,105,110,103,45,114,105,103, +104,116,58,116,114,97,110,115,108,97,116,105,111,110,32,111,102,105,110,116,101, +114,112,114,101,116,97,116,105,111,110,32,104,114,101,102,61,39,104,116,116,112, +58,47,47,119,104,101,116,104,101,114,32,111,114,32,110,111,116,84,104,101,114, +101,32,97,114,101,32,97,108,115,111,116,104,101,114,101,32,97,114,101,32,109,97, +110,121,97,32,115,109,97,108,108,32,110,117,109,98,101,114,111,116,104,101,114, +32,112,97,114,116,115,32,111,102,105,109,112,111,115,115,105,98,108,101,32,116, +111,32,32,99,108,97,115,115,61,34,98,117,116,116,111,110,108,111,99,97,116,101, +100,32,105,110,32,116,104,101,46,32,72,111,119,101,118,101,114,44,32,116,104,101 +,97,110,100,32,101,118,101,110,116,117,97,108,108,121,65,116,32,116,104,101,32, +101,110,100,32,111,102,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,114 +,101,112,114,101,115,101,110,116,115,32,116,104,101,60,102,111,114,109,32,97,99, +116,105,111,110,61,34,32,109,101,116,104,111,100,61,34,112,111,115,116,34,105, +116,32,105,115,32,112,111,115,115,105,98,108,101,109,111,114,101,32,108,105,107, +101,108,121,32,116,111,97,110,32,105,110,99,114,101,97,115,101,32,105,110,104,97 +,118,101,32,97,108,115,111,32,98,101,101,110,99,111,114,114,101,115,112,111,110, +100,115,32,116,111,97,110,110,111,117,110,99,101,100,32,116,104,97,116,97,108, +105,103,110,61,34,114,105,103,104,116,34,62,109,97,110,121,32,99,111,117,110,116 +,114,105,101,115,102,111,114,32,109,97,110,121,32,121,101,97,114,115,101,97,114, +108,105,101,115,116,32,107,110,111,119,110,98,101,99,97,117,115,101,32,105,116, +32,119,97,115,112,116,34,62,60,47,115,99,114,105,112,116,62,13,32,118,97,108,105 +,103,110,61,34,116,111,112,34,32,105,110,104,97,98,105,116,97,110,116,115,32,111 +,102,102,111,108,108,111,119,105,110,103,32,121,101,97,114,13,10,60,100,105,118, +32,99,108,97,115,115,61,34,109,105,108,108,105,111,110,32,112,101,111,112,108, +101,99,111,110,116,114,111,118,101,114,115,105,97,108,32,99,111,110,99,101,114, +110,105,110,103,32,116,104,101,97,114,103,117,101,32,116,104,97,116,32,116,104, +101,103,111,118,101,114,110,109,101,110,116,32,97,110,100,97,32,114,101,102,101, +114,101,110,99,101,32,116,111,116,114,97,110,115,102,101,114,114,101,100,32,116, +111,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,115,116,121,108,101, +61,34,99,111,108,111,114,58,97,108,116,104,111,117,103,104,32,116,104,101,114, +101,98,101,115,116,32,107,110,111,119,110,32,102,111,114,115,117,98,109,105,116, +34,32,110,97,109,101,61,34,109,117,108,116,105,112,108,105,99,97,116,105,111,110 +,109,111,114,101,32,116,104,97,110,32,111,110,101,32,114,101,99,111,103,110,105, +116,105,111,110,32,111,102,67,111,117,110,99,105,108,32,111,102,32,116,104,101, +101,100,105,116,105,111,110,32,111,102,32,116,104,101,32,32,60,109,101,116,97,32 +,110,97,109,101,61,34,69,110,116,101,114,116,97,105,110,109,101,110,116,32,97, +119,97,121,32,102,114,111,109,32,116,104,101,32,59,109,97,114,103,105,110,45,114 +,105,103,104,116,58,97,116,32,116,104,101,32,116,105,109,101,32,111,102,105,110, +118,101,115,116,105,103,97,116,105,111,110,115,99,111,110,110,101,99,116,101,100 +,32,119,105,116,104,97,110,100,32,109,97,110,121,32,111,116,104,101,114,97,108, +116,104,111,117,103,104,32,105,116,32,105,115,98,101,103,105,110,110,105,110,103 +,32,119,105,116,104,32,60,115,112,97,110,32,99,108,97,115,115,61,34,100,101,115, +99,101,110,100,97,110,116,115,32,111,102,60,115,112,97,110,32,99,108,97,115,115, +61,34,105,32,97,108,105,103,110,61,34,114,105,103,104,116,34,60,47,104,101,97, +100,62,10,60,98,111,100,121,32,97,115,112,101,99,116,115,32,111,102,32,116,104, +101,104,97,115,32,115,105,110,99,101,32,98,101,101,110,69,117,114,111,112,101,97 +,110,32,85,110,105,111,110,114,101,109,105,110,105,115,99,101,110,116,32,111,102 +,109,111,114,101,32,100,105,102,102,105,99,117,108,116,86,105,99,101,32,80,114, +101,115,105,100,101,110,116,99,111,109,112,111,115,105,116,105,111,110,32,111, +102,112,97,115,115,101,100,32,116,104,114,111,117,103,104,109,111,114,101,32,105 +,109,112,111,114,116,97,110,116,102,111,110,116,45,115,105,122,101,58,49,49,112, +120,101,120,112,108,97,110,97,116,105,111,110,32,111,102,116,104,101,32,99,111, +110,99,101,112,116,32,111,102,119,114,105,116,116,101,110,32,105,110,32,116,104, +101,9,60,115,112,97,110,32,99,108,97,115,115,61,34,105,115,32,111,110,101,32,111 +,102,32,116,104,101,32,114,101,115,101,109,98,108,97,110,99,101,32,116,111,111, +110,32,116,104,101,32,103,114,111,117,110,100,115,119,104,105,99,104,32,99,111, +110,116,97,105,110,115,105,110,99,108,117,100,105,110,103,32,116,104,101,32,100, +101,102,105,110,101,100,32,98,121,32,116,104,101,112,117,98,108,105,99,97,116, +105,111,110,32,111,102,109,101,97,110,115,32,116,104,97,116,32,116,104,101,111, +117,116,115,105,100,101,32,111,102,32,116,104,101,115,117,112,112,111,114,116,32 +,111,102,32,116,104,101,60,105,110,112,117,116,32,99,108,97,115,115,61,34,60,115 +,112,97,110,32,99,108,97,115,115,61,34,116,40,77,97,116,104,46,114,97,110,100, +111,109,40,41,109,111,115,116,32,112,114,111,109,105,110,101,110,116,100,101,115 +,99,114,105,112,116,105,111,110,32,111,102,67,111,110,115,116,97,110,116,105,110 +,111,112,108,101,119,101,114,101,32,112,117,98,108,105,115,104,101,100,60,100, +105,118,32,99,108,97,115,115,61,34,115,101,97,112,112,101,97,114,115,32,105,110, +32,116,104,101,49,34,32,104,101,105,103,104,116,61,34,49,34,32,109,111,115,116, +32,105,109,112,111,114,116,97,110,116,119,104,105,99,104,32,105,110,99,108,117, +100,101,115,119,104,105,99,104,32,104,97,100,32,98,101,101,110,100,101,115,116, +114,117,99,116,105,111,110,32,111,102,116,104,101,32,112,111,112,117,108,97,116, +105,111,110,10,9,60,100,105,118,32,99,108,97,115,115,61,34,112,111,115,115,105, +98,105,108,105,116,121,32,111,102,115,111,109,101,116,105,109,101,115,32,117,115 +,101,100,97,112,112,101,97,114,32,116,111,32,104,97,118,101,115,117,99,99,101, +115,115,32,111,102,32,116,104,101,105,110,116,101,110,100,101,100,32,116,111,32, +98,101,112,114,101,115,101,110,116,32,105,110,32,116,104,101,115,116,121,108,101 +,61,34,99,108,101,97,114,58,98,13,10,60,47,115,99,114,105,112,116,62,13,10,60, +119,97,115,32,102,111,117,110,100,101,100,32,105,110,105,110,116,101,114,118,105 +,101,119,32,119,105,116,104,95,105,100,34,32,99,111,110,116,101,110,116,61,34,99 +,97,112,105,116,97,108,32,111,102,32,116,104,101,13,10,60,108,105,110,107,32,114 +,101,108,61,34,115,114,101,108,101,97,115,101,32,111,102,32,116,104,101,112,111, +105,110,116,32,111,117,116,32,116,104,97,116,120,77,76,72,116,116,112,82,101,113 +,117,101,115,116,97,110,100,32,115,117,98,115,101,113,117,101,110,116,115,101,99 +,111,110,100,32,108,97,114,103,101,115,116,118,101,114,121,32,105,109,112,111, +114,116,97,110,116,115,112,101,99,105,102,105,99,97,116,105,111,110,115,115,117, +114,102,97,99,101,32,111,102,32,116,104,101,97,112,112,108,105,101,100,32,116, +111,32,116,104,101,102,111,114,101,105,103,110,32,112,111,108,105,99,121,95,115, +101,116,68,111,109,97,105,110,78,97,109,101,101,115,116,97,98,108,105,115,104, +101,100,32,105,110,105,115,32,98,101,108,105,101,118,101,100,32,116,111,73,110, +32,97,100,100,105,116,105,111,110,32,116,111,109,101,97,110,105,110,103,32,111, +102,32,116,104,101,105,115,32,110,97,109,101,100,32,97,102,116,101,114,116,111, +32,112,114,111,116,101,99,116,32,116,104,101,105,115,32,114,101,112,114,101,115, +101,110,116,101,100,68,101,99,108,97,114,97,116,105,111,110,32,111,102,109,111, +114,101,32,101,102,102,105,99,105,101,110,116,67,108,97,115,115,105,102,105,99, +97,116,105,111,110,111,116,104,101,114,32,102,111,114,109,115,32,111,102,104,101 +,32,114,101,116,117,114,110,101,100,32,116,111,60,115,112,97,110,32,99,108,97, +115,115,61,34,99,112,101,114,102,111,114,109,97,110,99,101,32,111,102,40,102,117 +,110,99,116,105,111,110,40,41,32,123,13,105,102,32,97,110,100,32,111,110,108,121 +,32,105,102,114,101,103,105,111,110,115,32,111,102,32,116,104,101,108,101,97,100 +,105,110,103,32,116,111,32,116,104,101,114,101,108,97,116,105,111,110,115,32,119 +,105,116,104,85,110,105,116,101,100,32,78,97,116,105,111,110,115,115,116,121,108 +,101,61,34,104,101,105,103,104,116,58,111,116,104,101,114,32,116,104,97,110,32, +116,104,101,121,112,101,34,32,99,111,110,116,101,110,116,61,34,65,115,115,111,99 +,105,97,116,105,111,110,32,111,102,10,60,47,104,101,97,100,62,10,60,98,111,100, +121,108,111,99,97,116,101,100,32,111,110,32,116,104,101,105,115,32,114,101,102, +101,114,114,101,100,32,116,111,40,105,110,99,108,117,100,105,110,103,32,116,104, +101,99,111,110,99,101,110,116,114,97,116,105,111,110,115,116,104,101,32,105,110, +100,105,118,105,100,117,97,108,97,109,111,110,103,32,116,104,101,32,109,111,115, +116,116,104,97,110,32,97,110,121,32,111,116,104,101,114,47,62,10,60,108,105,110, +107,32,114,101,108,61,34,32,114,101,116,117,114,110,32,102,97,108,115,101,59,116 +,104,101,32,112,117,114,112,111,115,101,32,111,102,116,104,101,32,97,98,105,108, +105,116,121,32,116,111,59,99,111,108,111,114,58,35,102,102,102,125,10,46,10,60, +115,112,97,110,32,99,108,97,115,115,61,34,116,104,101,32,115,117,98,106,101,99, +116,32,111,102,100,101,102,105,110,105,116,105,111,110,115,32,111,102,62,13,10, +60,108,105,110,107,32,114,101,108,61,34,99,108,97,105,109,32,116,104,97,116,32, +116,104,101,104,97,118,101,32,100,101,118,101,108,111,112,101,100,60,116,97,98, +108,101,32,119,105,100,116,104,61,34,99,101,108,101,98,114,97,116,105,111,110,32 +,111,102,70,111,108,108,111,119,105,110,103,32,116,104,101,32,116,111,32,100,105 +,115,116,105,110,103,117,105,115,104,60,115,112,97,110,32,99,108,97,115,115,61, +34,98,116,97,107,101,115,32,112,108,97,99,101,32,105,110,117,110,100,101,114,32, +116,104,101,32,110,97,109,101,110,111,116,101,100,32,116,104,97,116,32,116,104, +101,62,60,33,91,101,110,100,105,102,93,45,45,62,10,115,116,121,108,101,61,34,109 +,97,114,103,105,110,45,105,110,115,116,101,97,100,32,111,102,32,116,104,101,105, +110,116,114,111,100,117,99,101,100,32,116,104,101,116,104,101,32,112,114,111,99, +101,115,115,32,111,102,105,110,99,114,101,97,115,105,110,103,32,116,104,101,100, +105,102,102,101,114,101,110,99,101,115,32,105,110,101,115,116,105,109,97,116,101 +,100,32,116,104,97,116,101,115,112,101,99,105,97,108,108,121,32,116,104,101,47, +100,105,118,62,60,100,105,118,32,105,100,61,34,119,97,115,32,101,118,101,110,116 +,117,97,108,108,121,116,104,114,111,117,103,104,111,117,116,32,104,105,115,116, +104,101,32,100,105,102,102,101,114,101,110,99,101,115,111,109,101,116,104,105, +110,103,32,116,104,97,116,115,112,97,110,62,60,47,115,112,97,110,62,60,47,115, +105,103,110,105,102,105,99,97,110,116,108,121,32,62,60,47,115,99,114,105,112,116 +,62,13,10,13,10,101,110,118,105,114,111,110,109,101,110,116,97,108,32,116,111,32 +,112,114,101,118,101,110,116,32,116,104,101,104,97,118,101,32,98,101,101,110,32, +117,115,101,100,101,115,112,101,99,105,97,108,108,121,32,102,111,114,117,110,100 +,101,114,115,116,97,110,100,32,116,104,101,105,115,32,101,115,115,101,110,116, +105,97,108,108,121,119,101,114,101,32,116,104,101,32,102,105,114,115,116,105,115 +,32,116,104,101,32,108,97,114,103,101,115,116,104,97,118,101,32,98,101,101,110, +32,109,97,100,101,34,32,115,114,99,61,34,104,116,116,112,58,47,47,105,110,116, +101,114,112,114,101,116,101,100,32,97,115,115,101,99,111,110,100,32,104,97,108, +102,32,111,102,99,114,111,108,108,105,110,103,61,34,110,111,34,32,105,115,32,99, +111,109,112,111,115,101,100,32,111,102,73,73,44,32,72,111,108,121,32,82,111,109, +97,110,105,115,32,101,120,112,101,99,116,101,100,32,116,111,104,97,118,101,32, +116,104,101,105,114,32,111,119,110,100,101,102,105,110,101,100,32,97,115,32,116, +104,101,116,114,97,100,105,116,105,111,110,97,108,108,121,32,104,97,118,101,32, +100,105,102,102,101,114,101,110,116,97,114,101,32,111,102,116,101,110,32,117,115 +,101,100,116,111,32,101,110,115,117,114,101,32,116,104,97,116,97,103,114,101,101 +,109,101,110,116,32,119,105,116,104,99,111,110,116,97,105,110,105,110,103,32,116 +,104,101,97,114,101,32,102,114,101,113,117,101,110,116,108,121,105,110,102,111, +114,109,97,116,105,111,110,32,111,110,101,120,97,109,112,108,101,32,105,115,32, +116,104,101,114,101,115,117,108,116,105,110,103,32,105,110,32,97,60,47,97,62,60, +47,108,105,62,60,47,117,108,62,32,99,108,97,115,115,61,34,102,111,111,116,101, +114,97,110,100,32,101,115,112,101,99,105,97,108,108,121,116,121,112,101,61,34,98 +,117,116,116,111,110,34,32,60,47,115,112,97,110,62,60,47,115,112,97,110,62,119, +104,105,99,104,32,105,110,99,108,117,100,101,100,62,10,60,109,101,116,97,32,110, +97,109,101,61,34,99,111,110,115,105,100,101,114,101,100,32,116,104,101,99,97,114 +,114,105,101,100,32,111,117,116,32,98,121,72,111,119,101,118,101,114,44,32,105, +116,32,105,115,98,101,99,97,109,101,32,112,97,114,116,32,111,102,105,110,32,114, +101,108,97,116,105,111,110,32,116,111,112,111,112,117,108,97,114,32,105,110,32, +116,104,101,116,104,101,32,99,97,112,105,116,97,108,32,111,102,119,97,115,32,111 +,102,102,105,99,105,97,108,108,121,119,104,105,99,104,32,104,97,115,32,98,101, +101,110,116,104,101,32,72,105,115,116,111,114,121,32,111,102,97,108,116,101,114, +110,97,116,105,118,101,32,116,111,100,105,102,102,101,114,101,110,116,32,102,114 +,111,109,116,111,32,115,117,112,112,111,114,116,32,116,104,101,115,117,103,103, +101,115,116,101,100,32,116,104,97,116,105,110,32,116,104,101,32,112,114,111,99, +101,115,115,32,32,60,100,105,118,32,99,108,97,115,115,61,34,116,104,101,32,102, +111,117,110,100,97,116,105,111,110,98,101,99,97,117,115,101,32,111,102,32,104, +105,115,99,111,110,99,101,114,110,101,100,32,119,105,116,104,116,104,101,32,117, +110,105,118,101,114,115,105,116,121,111,112,112,111,115,101,100,32,116,111,32, +116,104,101,116,104,101,32,99,111,110,116,101,120,116,32,111,102,60,115,112,97, +110,32,99,108,97,115,115,61,34,112,116,101,120,116,34,32,110,97,109,101,61,34, +113,34,9,9,60,100,105,118,32,99,108,97,115,115,61,34,116,104,101,32,115,99,105, +101,110,116,105,102,105,99,114,101,112,114,101,115,101,110,116,101,100,32,98,121 +,109,97,116,104,101,109,97,116,105,99,105,97,110,115,101,108,101,99,116,101,100, +32,98,121,32,116,104,101,116,104,97,116,32,104,97,118,101,32,98,101,101,110,62, +60,100,105,118,32,99,108,97,115,115,61,34,99,100,105,118,32,105,100,61,34,104, +101,97,100,101,114,105,110,32,112,97,114,116,105,99,117,108,97,114,44,99,111,110 +,118,101,114,116,101,100,32,105,110,116,111,41,59,10,60,47,115,99,114,105,112, +116,62,10,60,112,104,105,108,111,115,111,112,104,105,99,97,108,32,115,114,112, +115,107,111,104,114,118,97,116,115,107,105,116,105,225,186,191,110,103,32,86,105 +,225,187,135,116,208,160,209,131,209,129,209,129,208,186,208,184,208,185,209,128 +,209,131,209,129,209,129,208,186,208,184,208,185,105,110,118,101,115,116,105,103 +,97,99,105,195,179,110,112,97,114,116,105,99,105,112,97,99,105,195,179,110,208, +186,208,190,209,130,208,190,209,128,209,139,208,181,208,190,208,177,208,187,208, +176,209,129,209,130,208,184,208,186,208,190,209,130,208,190,209,128,209,139,208, +185,209,135,208,181,208,187,208,190,208,178,208,181,208,186,209,129,208,184,209, +129,209,130,208,181,208,188,209,139,208,157,208,190,208,178,208,190,209,129,209, +130,208,184,208,186,208,190,209,130,208,190,209,128,209,139,209,133,208,190,208, +177,208,187,208,176,209,129,209,130,209,140,208,178,209,128,208,181,208,188,208, +181,208,189,208,184,208,186,208,190,209,130,208,190,209,128,208,176,209,143,209, +129,208,181,208,179,208,190,208,180,208,189,209,143,209,129,208,186,208,176,209, +135,208,176,209,130,209,140,208,189,208,190,208,178,208,190,209,129,209,130,208, +184,208,163,208,186,209,128,208,176,208,184,208,189,209,139,208,178,208,190,208, +191,209,128,208,190,209,129,209,139,208,186,208,190,209,130,208,190,209,128,208, +190,208,185,209,129,208,180,208,181,208,187,208,176,209,130,209,140,208,191,208, +190,208,188,208,190,209,137,209,140,209,142,209,129,209,128,208,181,208,180,209, +129,209,130,208,178,208,190,208,177,209,128,208,176,208,183,208,190,208,188,209, +129,209,130,208,190,209,128,208,190,208,189,209,139,209,131,209,135,208,176,209, +129,209,130,208,184,208,181,209,130,208,181,209,135,208,181,208,189,208,184,208, +181,208,147,208,187,208,176,208,178,208,189,208,176,209,143,208,184,209,129,209, +130,208,190,209,128,208,184,208,184,209,129,208,184,209,129,209,130,208,181,208, +188,208,176,209,128,208,181,209,136,208,181,208,189,208,184,209,143,208,161,208, +186,208,176,209,135,208,176,209,130,209,140,208,191,208,190,209,141,209,130,208, +190,208,188,209,131,209,129,208,187,208,181,208,180,209,131,208,181,209,130,209, +129,208,186,208,176,208,183,208,176,209,130,209,140,209,130,208,190,208,178,208, +176,209,128,208,190,208,178,208,186,208,190,208,189,208,181,209,135,208,189,208, +190,209,128,208,181,209,136,208,181,208,189,208,184,208,181,208,186,208,190,209, +130,208,190,209,128,208,190,208,181,208,190,209,128,208,179,208,176,208,189,208, +190,208,178,208,186,208,190,209,130,208,190,209,128,208,190,208,188,208,160,208, +181,208,186,208,187,208,176,208,188,208,176,216,167,217,132,217,133,217,134,216, +170,216,175,217,137,217,133,217,134,216,170,216,175,217,138,216,167,216,170,216, +167,217,132,217,133,217,136,216,182,217,136,216,185,216,167,217,132,216,168,216, +177,216,167,217,133,216,172,216,167,217,132,217,133,217,136,216,167,217,130,216, +185,216,167,217,132,216,177,216,179,216,167,216,166,217,132,217,133,216,180,216, +167,216,177,217,131,216,167,216,170,216,167,217,132,216,163,216,185,216,182,216, +167,216,161,216,167,217,132,216,177,217,138,216,167,216,182,216,169,216,167,217, +132,216,170,216,181,217,133,217,138,217,133,216,167,217,132,216,167,216,185,216, +182,216,167,216,161,216,167,217,132,217,134,216,170,216,167,216,166,216,172,216, +167,217,132,216,163,217,132,216,185,216,167,216,168,216,167,217,132,216,170,216, +179,216,172,217,138,217,132,216,167,217,132,216,163,217,130,216,179,216,167,217, +133,216,167,217,132,216,182,216,186,216,183,216,167,216,170,216,167,217,132,217, +129,217,138,216,175,217,138,217,136,216,167,217,132,216,170,216,177,216,173,217, +138,216,168,216,167,217,132,216,172,216,175,217,138,216,175,216,169,216,167,217, +132,216,170,216,185,217,132,217,138,217,133,216,167,217,132,216,163,216,174,216, +168,216,167,216,177,216,167,217,132,216,167,217,129,217,132,216,167,217,133,216, +167,217,132,216,163,217,129,217,132,216,167,217,133,216,167,217,132,216,170,216, +167,216,177,217,138,216,174,216,167,217,132,216,170,217,130,217,134,217,138,216, +169,216,167,217,132,216,167,217,132,216,185,216,167,216,168,216,167,217,132,216, +174,217,136,216,167,216,183,216,177,216,167,217,132,217,133,216,172,216,170,217, +133,216,185,216,167,217,132,216,175,217,138,217,131,217,136,216,177,216,167,217, +132,216,179,217,138,216,167,216,173,216,169,216,185,216,168,216,175,216,167,217, +132,217,132,217,135,216,167,217,132,216,170,216,177,216,168,217,138,216,169,216, +167,217,132,216,177,217,136,216,167,216,168,216,183,216,167,217,132,216,163,216, +175,216,168,217,138,216,169,216,167,217,132,216,167,216,174,216,168,216,167,216, +177,216,167,217,132,217,133,216,170,216,173,216,175,216,169,216,167,217,132,216, +167,216,186,216,167,217,134,217,138,99,117,114,115,111,114,58,112,111,105,110, +116,101,114,59,60,47,116,105,116,108,101,62,10,60,109,101,116,97,32,34,32,104, +114,101,102,61,34,104,116,116,112,58,47,47,34,62,60,115,112,97,110,32,99,108,97, +115,115,61,34,109,101,109,98,101,114,115,32,111,102,32,116,104,101,32,119,105, +110,100,111,119,46,108,111,99,97,116,105,111,110,118,101,114,116,105,99,97,108, +45,97,108,105,103,110,58,47,97,62,32,124,32,60,97,32,104,114,101,102,61,34,60,33 +,100,111,99,116,121,112,101,32,104,116,109,108,62,109,101,100,105,97,61,34,115, +99,114,101,101,110,34,32,60,111,112,116,105,111,110,32,118,97,108,117,101,61,34, +102,97,118,105,99,111,110,46,105,99,111,34,32,47,62,10,9,9,60,100,105,118,32,99, +108,97,115,115,61,34,99,104,97,114,97,99,116,101,114,105,115,116,105,99,115,34, +32,109,101,116,104,111,100,61,34,103,101,116,34,32,47,98,111,100,121,62,10,60,47 +,104,116,109,108,62,10,115,104,111,114,116,99,117,116,32,105,99,111,110,34,32, +100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,112,97,100,100,105,110, +103,45,98,111,116,116,111,109,58,114,101,112,114,101,115,101,110,116,97,116,105, +118,101,115,115,117,98,109,105,116,34,32,118,97,108,117,101,61,34,97,108,105,103 +,110,61,34,99,101,110,116,101,114,34,32,116,104,114,111,117,103,104,111,117,116, +32,116,104,101,32,115,99,105,101,110,99,101,32,102,105,99,116,105,111,110,10,32, +32,60,100,105,118,32,99,108,97,115,115,61,34,115,117,98,109,105,116,34,32,99,108 +,97,115,115,61,34,111,110,101,32,111,102,32,116,104,101,32,109,111,115,116,32, +118,97,108,105,103,110,61,34,116,111,112,34,62,60,119,97,115,32,101,115,116,97, +98,108,105,115,104,101,100,41,59,13,10,60,47,115,99,114,105,112,116,62,13,10,114 +,101,116,117,114,110,32,102,97,108,115,101,59,34,62,41,46,115,116,121,108,101,46 +,100,105,115,112,108,97,121,98,101,99,97,117,115,101,32,111,102,32,116,104,101, +32,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,60,102,111,114,109, +32,97,99,116,105,111,110,61,34,47,125,98,111,100,121,123,109,97,114,103,105,110, +58,48,59,69,110,99,121,99,108,111,112,101,100,105,97,32,111,102,118,101,114,115, +105,111,110,32,111,102,32,116,104,101,32,46,99,114,101,97,116,101,69,108,101,109 +,101,110,116,40,110,97,109,101,34,32,99,111,110,116,101,110,116,61,34,60,47,100, +105,118,62,10,60,47,100,105,118,62,10,10,97,100,109,105,110,105,115,116,114,97, +116,105,118,101,32,60,47,98,111,100,121,62,10,60,47,104,116,109,108,62,104,105, +115,116,111,114,121,32,111,102,32,116,104,101,32,34,62,60,105,110,112,117,116,32 +,116,121,112,101,61,34,112,111,114,116,105,111,110,32,111,102,32,116,104,101,32, +97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,38,110,98,115,112,59,60,97 +,32,104,114,101,102,61,34,111,116,104,101,114,32,99,111,117,110,116,114,105,101, +115,34,62,10,60,100,105,118,32,99,108,97,115,115,61,34,60,47,115,112,97,110,62, +60,47,115,112,97,110,62,60,73,110,32,111,116,104,101,114,32,119,111,114,100,115, +44,100,105,115,112,108,97,121,58,32,98,108,111,99,107,59,99,111,110,116,114,111, +108,32,111,102,32,116,104,101,32,105,110,116,114,111,100,117,99,116,105,111,110, +32,111,102,47,62,10,60,109,101,116,97,32,110,97,109,101,61,34,97,115,32,119,101, +108,108,32,97,115,32,116,104,101,32,105,110,32,114,101,99,101,110,116,32,121,101 +,97,114,115,13,10,9,60,100,105,118,32,99,108,97,115,115,61,34,60,47,100,105,118, +62,10,9,60,47,100,105,118,62,10,105,110,115,112,105,114,101,100,32,98,121,32,116 +,104,101,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,99,111,109,112, +97,116,105,98,108,101,32,119,105,116,104,98,101,99,97,109,101,32,107,110,111,119 +,110,32,97,115,32,115,116,121,108,101,61,34,109,97,114,103,105,110,58,46,106,115 +,34,62,60,47,115,99,114,105,112,116,62,60,32,73,110,116,101,114,110,97,116,105, +111,110,97,108,32,116,104,101,114,101,32,104,97,118,101,32,98,101,101,110,71,101 +,114,109,97,110,32,108,97,110,103,117,97,103,101,32,115,116,121,108,101,61,34,99 +,111,108,111,114,58,35,67,111,109,109,117,110,105,115,116,32,80,97,114,116,121, +99,111,110,115,105,115,116,101,110,116,32,119,105,116,104,98,111,114,100,101,114 +,61,34,48,34,32,99,101,108,108,32,109,97,114,103,105,110,104,101,105,103,104,116 +,61,34,116,104,101,32,109,97,106,111,114,105,116,121,32,111,102,34,32,97,108,105 +,103,110,61,34,99,101,110,116,101,114,114,101,108,97,116,101,100,32,116,111,32, +116,104,101,32,109,97,110,121,32,100,105,102,102,101,114,101,110,116,32,79,114, +116,104,111,100,111,120,32,67,104,117,114,99,104,115,105,109,105,108,97,114,32, +116,111,32,116,104,101,32,47,62,10,60,108,105,110,107,32,114,101,108,61,34,115, +119,97,115,32,111,110,101,32,111,102,32,116,104,101,32,117,110,116,105,108,32, +104,105,115,32,100,101,97,116,104,125,41,40,41,59,10,60,47,115,99,114,105,112, +116,62,111,116,104,101,114,32,108,97,110,103,117,97,103,101,115,99,111,109,112, +97,114,101,100,32,116,111,32,116,104,101,112,111,114,116,105,111,110,115,32,111, +102,32,116,104,101,116,104,101,32,78,101,116,104,101,114,108,97,110,100,115,116, +104,101,32,109,111,115,116,32,99,111,109,109,111,110,98,97,99,107,103,114,111, +117,110,100,58,117,114,108,40,97,114,103,117,101,100,32,116,104,97,116,32,116, +104,101,115,99,114,111,108,108,105,110,103,61,34,110,111,34,32,105,110,99,108, +117,100,101,100,32,105,110,32,116,104,101,78,111,114,116,104,32,65,109,101,114, +105,99,97,110,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,105,110 +,116,101,114,112,114,101,116,97,116,105,111,110,115,116,104,101,32,116,114,97, +100,105,116,105,111,110,97,108,100,101,118,101,108,111,112,109,101,110,116,32, +111,102,32,102,114,101,113,117,101,110,116,108,121,32,117,115,101,100,97,32,99, +111,108,108,101,99,116,105,111,110,32,111,102,118,101,114,121,32,115,105,109,105 +,108,97,114,32,116,111,115,117,114,114,111,117,110,100,105,110,103,32,116,104, +101,101,120,97,109,112,108,101,32,111,102,32,116,104,105,115,97,108,105,103,110, +61,34,99,101,110,116,101,114,34,62,119,111,117,108,100,32,104,97,118,101,32,98, +101,101,110,105,109,97,103,101,95,99,97,112,116,105,111,110,32,61,97,116,116,97, +99,104,101,100,32,116,111,32,116,104,101,115,117,103,103,101,115,116,105,110,103 +,32,116,104,97,116,105,110,32,116,104,101,32,102,111,114,109,32,111,102,32,105, +110,118,111,108,118,101,100,32,105,110,32,116,104,101,105,115,32,100,101,114,105 +,118,101,100,32,102,114,111,109,110,97,109,101,100,32,97,102,116,101,114,32,116, +104,101,73,110,116,114,111,100,117,99,116,105,111,110,32,116,111,114,101,115,116 +,114,105,99,116,105,111,110,115,32,111,110,32,115,116,121,108,101,61,34,119,105, +100,116,104,58,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,116,104, +101,32,99,114,101,97,116,105,111,110,32,111,102,109,111,115,116,32,105,109,112, +111,114,116,97,110,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,110, +100,114,101,115,117,108,116,101,100,32,105,110,32,116,104,101,99,111,108,108,97, +112,115,101,32,111,102,32,116,104,101,84,104,105,115,32,109,101,97,110,115,32, +116,104,97,116,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,119,97, +115,32,114,101,112,108,97,99,101,100,32,98,121,97,110,97,108,121,115,105,115,32, +111,102,32,116,104,101,105,110,115,112,105,114,97,116,105,111,110,32,102,111,114 +,114,101,103,97,114,100,101,100,32,97,115,32,116,104,101,109,111,115,116,32,115, +117,99,99,101,115,115,102,117,108,107,110,111,119,110,32,97,115,32,38,113,117, +111,116,59,97,32,99,111,109,112,114,101,104,101,110,115,105,118,101,72,105,115, +116,111,114,121,32,111,102,32,116,104,101,32,119,101,114,101,32,99,111,110,115, +105,100,101,114,101,100,114,101,116,117,114,110,101,100,32,116,111,32,116,104, +101,97,114,101,32,114,101,102,101,114,114,101,100,32,116,111,85,110,115,111,117, +114,99,101,100,32,105,109,97,103,101,62,10,9,60,100,105,118,32,99,108,97,115,115 +,61,34,99,111,110,115,105,115,116,115,32,111,102,32,116,104,101,115,116,111,112, +80,114,111,112,97,103,97,116,105,111,110,105,110,116,101,114,101,115,116,32,105, +110,32,116,104,101,97,118,97,105,108,97,98,105,108,105,116,121,32,111,102,97,112 +,112,101,97,114,115,32,116,111,32,104,97,118,101,101,108,101,99,116,114,111,109, +97,103,110,101,116,105,99,101,110,97,98,108,101,83,101,114,118,105,99,101,115,40 +,102,117,110,99,116,105,111,110,32,111,102,32,116,104,101,73,116,32,105,115,32, +105,109,112,111,114,116,97,110,116,60,47,115,99,114,105,112,116,62,60,47,100,105 +,118,62,102,117,110,99,116,105,111,110,40,41,123,118,97,114,32,114,101,108,97, +116,105,118,101,32,116,111,32,116,104,101,97,115,32,97,32,114,101,115,117,108, +116,32,111,102,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,102,70, +111,114,32,101,120,97,109,112,108,101,44,32,105,110,32,109,101,116,104,111,100, +61,34,112,111,115,116,34,32,119,97,115,32,102,111,108,108,111,119,101,100,32,98, +121,38,97,109,112,59,109,100,97,115,104,59,32,116,104,101,116,104,101,32,97,112, +112,108,105,99,97,116,105,111,110,106,115,34,62,60,47,115,99,114,105,112,116,62, +13,10,117,108,62,60,47,100,105,118,62,60,47,100,105,118,62,97,102,116,101,114,32 +,116,104,101,32,100,101,97,116,104,119,105,116,104,32,114,101,115,112,101,99,116 +,32,116,111,115,116,121,108,101,61,34,112,97,100,100,105,110,103,58,105,115,32, +112,97,114,116,105,99,117,108,97,114,108,121,100,105,115,112,108,97,121,58,105, +110,108,105,110,101,59,32,116,121,112,101,61,34,115,117,98,109,105,116,34,32,105 +,115,32,100,105,118,105,100,101,100,32,105,110,116,111,228,184,173,230,150,135, +32,40,231,174,128,228,189,147,41,114,101,115,112,111,110,115,97,98,105,108,105, +100,97,100,97,100,109,105,110,105,115,116,114,97,99,105,195,179,110,105,110,116, +101,114,110,97,99,105,111,110,97,108,101,115,99,111,114,114,101,115,112,111,110, +100,105,101,110,116,101,224,164,137,224,164,170,224,164,175,224,165,139,224,164, +151,224,164,170,224,165,130,224,164,176,224,165,141,224,164,181,224,164,185,224, +164,174,224,164,190,224,164,176,224,165,135,224,164,178,224,165,139,224,164,151, +224,165,139,224,164,130,224,164,154,224,165,129,224,164,168,224,164,190,224,164, +181,224,164,178,224,165,135,224,164,149,224,164,191,224,164,168,224,164,184,224, +164,176,224,164,149,224,164,190,224,164,176,224,164,170,224,165,129,224,164,178, +224,164,191,224,164,184,224,164,150,224,165,139,224,164,156,224,165,135,224,164, +130,224,164,154,224,164,190,224,164,185,224,164,191,224,164,143,224,164,173,224, +165,135,224,164,156,224,165,135,224,164,130,224,164,182,224,164,190,224,164,174, +224,164,191,224,164,178,224,164,185,224,164,174,224,164,190,224,164,176,224,165, +128,224,164,156,224,164,190,224,164,151,224,164,176,224,164,163,224,164,172,224, +164,168,224,164,190,224,164,168,224,165,135,224,164,149,224,165,129,224,164,174, +224,164,190,224,164,176,224,164,172,224,165,141,224,164,178,224,165,137,224,164, +151,224,164,174,224,164,190,224,164,178,224,164,191,224,164,149,224,164,174,224, +164,185,224,164,191,224,164,178,224,164,190,224,164,170,224,165,131,224,164,183, +224,165,141,224,164,160,224,164,172,224,164,162,224,164,188,224,164,164,224,165, +135,224,164,173,224,164,190,224,164,156,224,164,170,224,164,190,224,164,149,224, +165,141,224,164,178,224,164,191,224,164,149,224,164,159,224,165,141,224,164,176, +224,165,135,224,164,168,224,164,150,224,164,191,224,164,178,224,164,190,224,164, +171,224,164,166,224,165,140,224,164,176,224,164,190,224,164,168,224,164,174,224, +164,190,224,164,174,224,164,178,224,165,135,224,164,174,224,164,164,224,164,166, +224,164,190,224,164,168,224,164,172,224,164,190,224,164,156,224,164,190,224,164, +176,224,164,181,224,164,191,224,164,149,224,164,190,224,164,184,224,164,149,224, +165,141,224,164,175,224,165,139,224,164,130,224,164,154,224,164,190,224,164,185, +224,164,164,224,165,135,224,164,170,224,164,185,224,165,129,224,164,129,224,164, +154,224,164,172,224,164,164,224,164,190,224,164,175,224,164,190,224,164,184,224, +164,130,224,164,181,224,164,190,224,164,166,224,164,166,224,165,135,224,164,150, +224,164,168,224,165,135,224,164,170,224,164,191,224,164,155,224,164,178,224,165, +135,224,164,181,224,164,191,224,164,182,224,165,135,224,164,183,224,164,176,224, +164,190,224,164,156,224,165,141,224,164,175,224,164,137,224,164,164,224,165,141, +224,164,164,224,164,176,224,164,174,224,165,129,224,164,130,224,164,172,224,164, +136,224,164,166,224,165,139,224,164,168,224,165,139,224,164,130,224,164,137,224, +164,170,224,164,149,224,164,176,224,164,163,224,164,170,224,164,162,224,164,188, +224,165,135,224,164,130,224,164,184,224,165,141,224,164,165,224,164,191,224,164, +164,224,164,171,224,164,191,224,164,178,224,165,141,224,164,174,224,164,174,224, +165,129,224,164,150,224,165,141,224,164,175,224,164,133,224,164,154,224,165,141, +224,164,155,224,164,190,224,164,155,224,165,130,224,164,159,224,164,164,224,165, +128,224,164,184,224,164,130,224,164,151,224,165,128,224,164,164,224,164,156,224, +164,190,224,164,143,224,164,151,224,164,190,224,164,181,224,164,191,224,164,173, +224,164,190,224,164,151,224,164,152,224,164,163,224,165,141,224,164,159,224,165, +135,224,164,166,224,165,130,224,164,184,224,164,176,224,165,135,224,164,166,224, +164,191,224,164,168,224,165,139,224,164,130,224,164,185,224,164,164,224,165,141, +224,164,175,224,164,190,224,164,184,224,165,135,224,164,149,224,165,141,224,164, +184,224,164,151,224,164,190,224,164,130,224,164,167,224,165,128,224,164,181,224, +164,191,224,164,182,224,165,141,224,164,181,224,164,176,224,164,190,224,164,164, +224,165,135,224,164,130,224,164,166,224,165,136,224,164,159,224,165,141,224,164, +184,224,164,168,224,164,149,224,165,141,224,164,182,224,164,190,224,164,184,224, +164,190,224,164,174,224,164,168,224,165,135,224,164,133,224,164,166,224,164,190, +224,164,178,224,164,164,224,164,172,224,164,191,224,164,156,224,164,178,224,165, +128,224,164,170,224,165,129,224,164,176,224,165,130,224,164,183,224,164,185,224, +164,191,224,164,130,224,164,166,224,165,128,224,164,174,224,164,191,224,164,164, +224,165,141,224,164,176,224,164,149,224,164,181,224,164,191,224,164,164,224,164, +190,224,164,176,224,165,129,224,164,170,224,164,175,224,165,135,224,164,184,224, +165,141,224,164,165,224,164,190,224,164,168,224,164,149,224,164,176,224,165,139, +224,164,161,224,164,188,224,164,174,224,165,129,224,164,149,224,165,141,224,164, +164,224,164,175,224,165,139,224,164,156,224,164,168,224,164,190,224,164,149,224, +165,131,224,164,170,224,164,175,224,164,190,224,164,170,224,165,139,224,164,184, +224,165,141,224,164,159,224,164,152,224,164,176,224,165,135,224,164,178,224,165, +130,224,164,149,224,164,190,224,164,176,224,165,141,224,164,175,224,164,181,224, +164,191,224,164,154,224,164,190,224,164,176,224,164,184,224,165,130,224,164,154, +224,164,168,224,164,190,224,164,174,224,165,130,224,164,178,224,165,141,224,164, +175,224,164,166,224,165,135,224,164,150,224,165,135,224,164,130,224,164,185,224, +164,174,224,165,135,224,164,182,224,164,190,224,164,184,224,165,141,224,164,149, +224,165,130,224,164,178,224,164,174,224,165,136,224,164,130,224,164,168,224,165, +135,224,164,164,224,165,136,224,164,175,224,164,190,224,164,176,224,164,156,224, +164,191,224,164,184,224,164,149,224,165,135,114,115,115,43,120,109,108,34,32,116 +,105,116,108,101,61,34,45,116,121,112,101,34,32,99,111,110,116,101,110,116,61,34 +,116,105,116,108,101,34,32,99,111,110,116,101,110,116,61,34,97,116,32,116,104, +101,32,115,97,109,101,32,116,105,109,101,46,106,115,34,62,60,47,115,99,114,105, +112,116,62,10,60,34,32,109,101,116,104,111,100,61,34,112,111,115,116,34,32,60,47 +,115,112,97,110,62,60,47,97,62,60,47,108,105,62,118,101,114,116,105,99,97,108,45 +,97,108,105,103,110,58,116,47,106,113,117,101,114,121,46,109,105,110,46,106,115, +34,62,46,99,108,105,99,107,40,102,117,110,99,116,105,111,110,40,32,115,116,121, +108,101,61,34,112,97,100,100,105,110,103,45,125,41,40,41,59,10,60,47,115,99,114, +105,112,116,62,10,60,47,115,112,97,110,62,60,97,32,104,114,101,102,61,34,60,97, +32,104,114,101,102,61,34,104,116,116,112,58,47,47,41,59,32,114,101,116,117,114, +110,32,102,97,108,115,101,59,116,101,120,116,45,100,101,99,111,114,97,116,105, +111,110,58,32,115,99,114,111,108,108,105,110,103,61,34,110,111,34,32,98,111,114, +100,101,114,45,99,111,108,108,97,112,115,101,58,97,115,115,111,99,105,97,116,101 +,100,32,119,105,116,104,32,66,97,104,97,115,97,32,73,110,100,111,110,101,115,105 +,97,69,110,103,108,105,115,104,32,108,97,110,103,117,97,103,101,60,116,101,120, +116,32,120,109,108,58,115,112,97,99,101,61,46,103,105,102,34,32,98,111,114,100, +101,114,61,34,48,34,60,47,98,111,100,121,62,10,60,47,104,116,109,108,62,10,111, +118,101,114,102,108,111,119,58,104,105,100,100,101,110,59,105,109,103,32,115,114 +,99,61,34,104,116,116,112,58,47,47,97,100,100,69,118,101,110,116,76,105,115,116, +101,110,101,114,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,115 +,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,47,102,97,118,105,99,111, +110,46,105,99,111,34,32,47,62,111,112,101,114,97,116,105,110,103,32,115,121,115, +116,101,109,34,32,115,116,121,108,101,61,34,119,105,100,116,104,58,49,116,97,114 +,103,101,116,61,34,95,98,108,97,110,107,34,62,83,116,97,116,101,32,85,110,105, +118,101,114,115,105,116,121,116,101,120,116,45,97,108,105,103,110,58,108,101,102 +,116,59,10,100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,44,32,105, +110,99,108,117,100,105,110,103,32,116,104,101,32,97,114,111,117,110,100,32,116, +104,101,32,119,111,114,108,100,41,59,13,10,60,47,115,99,114,105,112,116,62,13,10 +,60,34,32,115,116,121,108,101,61,34,104,101,105,103,104,116,58,59,111,118,101, +114,102,108,111,119,58,104,105,100,100,101,110,109,111,114,101,32,105,110,102, +111,114,109,97,116,105,111,110,97,110,32,105,110,116,101,114,110,97,116,105,111, +110,97,108,97,32,109,101,109,98,101,114,32,111,102,32,116,104,101,32,111,110,101 +,32,111,102,32,116,104,101,32,102,105,114,115,116,99,97,110,32,98,101,32,102,111 +,117,110,100,32,105,110,32,60,47,100,105,118,62,10,9,9,60,47,100,105,118,62,10, +100,105,115,112,108,97,121,58,32,110,111,110,101,59,34,62,34,32,47,62,10,60,108, +105,110,107,32,114,101,108,61,34,10,32,32,40,102,117,110,99,116,105,111,110,40, +41,32,123,116,104,101,32,49,53,116,104,32,99,101,110,116,117,114,121,46,112,114, +101,118,101,110,116,68,101,102,97,117,108,116,40,108,97,114,103,101,32,110,117, +109,98,101,114,32,111,102,32,66,121,122,97,110,116,105,110,101,32,69,109,112,105 +,114,101,46,106,112,103,124,116,104,117,109,98,124,108,101,102,116,124,118,97, +115,116,32,109,97,106,111,114,105,116,121,32,111,102,109,97,106,111,114,105,116, +121,32,111,102,32,116,104,101,32,32,97,108,105,103,110,61,34,99,101,110,116,101, +114,34,62,85,110,105,118,101,114,115,105,116,121,32,80,114,101,115,115,100,111, +109,105,110,97,116,101,100,32,98,121,32,116,104,101,83,101,99,111,110,100,32,87, +111,114,108,100,32,87,97,114,100,105,115,116,114,105,98,117,116,105,111,110,32, +111,102,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,116,104, +101,32,114,101,115,116,32,111,102,32,116,104,101,32,99,104,97,114,97,99,116,101, +114,105,122,101,100,32,98,121,32,114,101,108,61,34,110,111,102,111,108,108,111, +119,34,62,100,101,114,105,118,101,115,32,102,114,111,109,32,116,104,101,114,97, +116,104,101,114,32,116,104,97,110,32,116,104,101,32,97,32,99,111,109,98,105,110, +97,116,105,111,110,32,111,102,115,116,121,108,101,61,34,119,105,100,116,104,58, +49,48,48,69,110,103,108,105,115,104,45,115,112,101,97,107,105,110,103,99,111,109 +,112,117,116,101,114,32,115,99,105,101,110,99,101,98,111,114,100,101,114,61,34, +48,34,32,97,108,116,61,34,116,104,101,32,101,120,105,115,116,101,110,99,101,32, +111,102,68,101,109,111,99,114,97,116,105,99,32,80,97,114,116,121,34,32,115,116, +121,108,101,61,34,109,97,114,103,105,110,45,70,111,114,32,116,104,105,115,32,114 +,101,97,115,111,110,44,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,9,115 +,66,121,84,97,103,78,97,109,101,40,115,41,91,48,93,106,115,34,62,60,47,115,99, +114,105,112,116,62,13,10,60,46,106,115,34,62,60,47,115,99,114,105,112,116,62,13, +10,108,105,110,107,32,114,101,108,61,34,105,99,111,110,34,32,39,32,97,108,116,61 +,39,39,32,99,108,97,115,115,61,39,102,111,114,109,97,116,105,111,110,32,111,102, +32,116,104,101,118,101,114,115,105,111,110,115,32,111,102,32,116,104,101,32,60, +47,97,62,60,47,100,105,118,62,60,47,100,105,118,62,47,112,97,103,101,62,10,32,32 +,60,112,97,103,101,62,10,60,100,105,118,32,99,108,97,115,115,61,34,99,111,110, +116,98,101,99,97,109,101,32,116,104,101,32,102,105,114,115,116,98,97,104,97,115, +97,32,73,110,100,111,110,101,115,105,97,101,110,103,108,105,115,104,32,40,115, +105,109,112,108,101,41,206,149,206,187,206,187,206,183,206,189,206,185,206,186, +206,172,209,133,209,128,208,178,208,176,209,130,209,129,208,186,208,184,208,186, +208,190,208,188,208,191,208,176,208,189,208,184,208,184,209,143,208,178,208,187, +209,143,208,181,209,130,209,129,209,143,208,148,208,190,208,177,208,176,208,178, +208,184,209,130,209,140,209,135,208,181,208,187,208,190,208,178,208,181,208,186, +208,176,209,128,208,176,208,183,208,178,208,184,209,130,208,184,209,143,208,152, +208,189,209,130,208,181,209,128,208,189,208,181,209,130,208,158,209,130,208,178, +208,181,209,130,208,184,209,130,209,140,208,189,208,176,208,191,209,128,208,184, +208,188,208,181,209,128,208,184,208,189,209,130,208,181,209,128,208,189,208,181, +209,130,208,186,208,190,209,130,208,190,209,128,208,190,208,179,208,190,209,129, +209,130,209,128,208,176,208,189,208,184,209,134,209,139,208,186,208,176,209,135, +208,181,209,129,209,130,208,178,208,181,209,131,209,129,208,187,208,190,208,178, +208,184,209,143,209,133,208,191,209,128,208,190,208,177,208,187,208,181,208,188, +209,139,208,191,208,190,208,187,209,131,209,135,208,184,209,130,209,140,209,143, +208,178,208,187,209,143,209,142,209,130,209,129,209,143,208,189,208,176,208,184, +208,177,208,190,208,187,208,181,208,181,208,186,208,190,208,188,208,191,208,176, +208,189,208,184,209,143,208,178,208,189,208,184,208,188,208,176,208,189,208,184, +208,181,209,129,209,128,208,181,208,180,209,129,209,130,208,178,208,176,216,167, +217,132,217,133,217,136,216,167,216,182,217,138,216,185,216,167,217,132,216,177, +216,166,217,138,216,179,217,138,216,169,216,167,217,132,216,167,217,134,216,170, +217,130,216,167,217,132,217,133,216,180,216,167,216,177,217,131,216,167,216,170, +217,131,216,167,217,132,216,179,217,138,216,167,216,177,216,167,216,170,216,167, +217,132,217,133,217,131,216,170,217,136,216,168,216,169,216,167,217,132,216,179, +216,185,217,136,216,175,217,138,216,169,216,167,216,173,216,181,216,167,216,166, +217,138,216,167,216,170,216,167,217,132,216,185,216,167,217,132,217,133,217,138, +216,169,216,167,217,132,216,181,217,136,216,170,217,138,216,167,216,170,216,167, +217,132,216,167,217,134,216,170,216,177,217,134,216,170,216,167,217,132,216,170, +216,181,216,167,217,133,217,138,217,133,216,167,217,132,216,165,216,179,217,132, +216,167,217,133,217,138,216,167,217,132,217,133,216,180,216,167,216,177,217,131, +216,169,216,167,217,132,217,133,216,177,216,166,217,138,216,167,216,170,114,111, +98,111,116,115,34,32,99,111,110,116,101,110,116,61,34,60,100,105,118,32,105,100, +61,34,102,111,111,116,101,114,34,62,116,104,101,32,85,110,105,116,101,100,32,83, +116,97,116,101,115,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47, +46,106,112,103,124,114,105,103,104,116,124,116,104,117,109,98,124,46,106,115,34, +62,60,47,115,99,114,105,112,116,62,13,10,60,108,111,99,97,116,105,111,110,46,112 +,114,111,116,111,99,111,108,102,114,97,109,101,98,111,114,100,101,114,61,34,48, +34,32,115,34,32,47,62,10,60,109,101,116,97,32,110,97,109,101,61,34,60,47,97,62, +60,47,100,105,118,62,60,47,100,105,118,62,60,102,111,110,116,45,119,101,105,103, +104,116,58,98,111,108,100,59,38,113,117,111,116,59,32,97,110,100,32,38,113,117, +111,116,59,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,109, +97,114,103,105,110,58,48,59,112,97,100,100,105,110,103,58,34,32,114,101,108,61, +34,110,111,102,111,108,108,111,119,34,32,80,114,101,115,105,100,101,110,116,32, +111,102,32,116,104,101,32,116,119,101,110,116,105,101,116,104,32,99,101,110,116, +117,114,121,101,118,105,115,105,111,110,62,10,32,32,60,47,112,97,103,101,73,110, +116,101,114,110,101,116,32,69,120,112,108,111,114,101,114,97,46,97,115,121,110, +99,32,61,32,116,114,117,101,59,13,10,105,110,102,111,114,109,97,116,105,111,110, +32,97,98,111,117,116,60,100,105,118,32,105,100,61,34,104,101,97,100,101,114,34, +62,34,32,97,99,116,105,111,110,61,34,104,116,116,112,58,47,47,60,97,32,104,114, +101,102,61,34,104,116,116,112,115,58,47,47,60,100,105,118,32,105,100,61,34,99, +111,110,116,101,110,116,34,60,47,100,105,118,62,13,10,60,47,100,105,118,62,13,10 +,60,100,101,114,105,118,101,100,32,102,114,111,109,32,116,104,101,32,60,105,109, +103,32,115,114,99,61,39,104,116,116,112,58,47,47,97,99,99,111,114,100,105,110, +103,32,116,111,32,116,104,101,32,10,60,47,98,111,100,121,62,10,60,47,104,116,109 +,108,62,10,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,115, +99,114,105,112,116,32,108,97,110,103,117,97,103,101,61,34,65,114,105,97,108,44, +32,72,101,108,118,101,116,105,99,97,44,60,47,97,62,60,115,112,97,110,32,99,108, +97,115,115,61,34,60,47,115,99,114,105,112,116,62,60,115,99,114,105,112,116,32, +112,111,108,105,116,105,99,97,108,32,112,97,114,116,105,101,115,116,100,62,60,47 +,116,114,62,60,47,116,97,98,108,101,62,60,104,114,101,102,61,34,104,116,116,112, +58,47,47,119,119,119,46,105,110,116,101,114,112,114,101,116,97,116,105,111,110, +32,111,102,114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,100, +111,99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,99,104,97,114,115,101 +,116,61,34,117,116,102,45,56,34,62,10,98,101,103,105,110,110,105,110,103,32,111, +102,32,116,104,101,32,114,101,118,101,97,108,101,100,32,116,104,97,116,32,116, +104,101,116,101,108,101,118,105,115,105,111,110,32,115,101,114,105,101,115,34,32 +,114,101,108,61,34,110,111,102,111,108,108,111,119,34,62,32,116,97,114,103,101, +116,61,34,95,98,108,97,110,107,34,62,99,108,97,105,109,105,110,103,32,116,104,97 +,116,32,116,104,101,104,116,116,112,37,51,65,37,50,70,37,50,70,119,119,119,46, +109,97,110,105,102,101,115,116,97,116,105,111,110,115,32,111,102,80,114,105,109, +101,32,77,105,110,105,115,116,101,114,32,111,102,105,110,102,108,117,101,110,99, +101,100,32,98,121,32,116,104,101,99,108,97,115,115,61,34,99,108,101,97,114,102, +105,120,34,62,47,100,105,118,62,13,10,60,47,100,105,118,62,13,10,13,10,116,104, +114,101,101,45,100,105,109,101,110,115,105,111,110,97,108,67,104,117,114,99,104, +32,111,102,32,69,110,103,108,97,110,100,111,102,32,78,111,114,116,104,32,67,97, +114,111,108,105,110,97,115,113,117,97,114,101,32,107,105,108,111,109,101,116,114 +,101,115,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110,101,114,100,105 +,115,116,105,110,99,116,32,102,114,111,109,32,116,104,101,99,111,109,109,111,110 +,108,121,32,107,110,111,119,110,32,97,115,80,104,111,110,101,116,105,99,32,65, +108,112,104,97,98,101,116,100,101,99,108,97,114,101,100,32,116,104,97,116,32,116 +,104,101,99,111,110,116,114,111,108,108,101,100,32,98,121,32,116,104,101,66,101, +110,106,97,109,105,110,32,70,114,97,110,107,108,105,110,114,111,108,101,45,112, +108,97,121,105,110,103,32,103,97,109,101,116,104,101,32,85,110,105,118,101,114, +115,105,116,121,32,111,102,105,110,32,87,101,115,116,101,114,110,32,69,117,114, +111,112,101,112,101,114,115,111,110,97,108,32,99,111,109,112,117,116,101,114,80, +114,111,106,101,99,116,32,71,117,116,101,110,98,101,114,103,114,101,103,97,114, +100,108,101,115,115,32,111,102,32,116,104,101,104,97,115,32,98,101,101,110,32, +112,114,111,112,111,115,101,100,116,111,103,101,116,104,101,114,32,119,105,116, +104,32,116,104,101,62,60,47,108,105,62,60,108,105,32,99,108,97,115,115,61,34,105 +,110,32,115,111,109,101,32,99,111,117,110,116,114,105,101,115,109,105,110,46,106 +,115,34,62,60,47,115,99,114,105,112,116,62,111,102,32,116,104,101,32,112,111,112 +,117,108,97,116,105,111,110,111,102,102,105,99,105,97,108,32,108,97,110,103,117, +97,103,101,60,105,109,103,32,115,114,99,61,34,105,109,97,103,101,115,47,105,100, +101,110,116,105,102,105,101,100,32,98,121,32,116,104,101,110,97,116,117,114,97, +108,32,114,101,115,111,117,114,99,101,115,99,108,97,115,115,105,102,105,99,97, +116,105,111,110,32,111,102,99,97,110,32,98,101,32,99,111,110,115,105,100,101,114 +,101,100,113,117,97,110,116,117,109,32,109,101,99,104,97,110,105,99,115,78,101, +118,101,114,116,104,101,108,101,115,115,44,32,116,104,101,109,105,108,108,105, +111,110,32,121,101,97,114,115,32,97,103,111,60,47,98,111,100,121,62,13,10,60,47, +104,116,109,108,62,13,206,149,206,187,206,187,206,183,206,189,206,185,206,186, +206,172,10,116,97,107,101,32,97,100,118,97,110,116,97,103,101,32,111,102,97,110, +100,44,32,97,99,99,111,114,100,105,110,103,32,116,111,97,116,116,114,105,98,117, +116,101,100,32,116,111,32,116,104,101,77,105,99,114,111,115,111,102,116,32,87, +105,110,100,111,119,115,116,104,101,32,102,105,114,115,116,32,99,101,110,116,117 +,114,121,117,110,100,101,114,32,116,104,101,32,99,111,110,116,114,111,108,100, +105,118,32,99,108,97,115,115,61,34,104,101,97,100,101,114,115,104,111,114,116, +108,121,32,97,102,116,101,114,32,116,104,101,110,111,116,97,98,108,101,32,101, +120,99,101,112,116,105,111,110,116,101,110,115,32,111,102,32,116,104,111,117,115 +,97,110,100,115,115,101,118,101,114,97,108,32,100,105,102,102,101,114,101,110, +116,97,114,111,117,110,100,32,116,104,101,32,119,111,114,108,100,46,114,101,97, +99,104,105,110,103,32,109,105,108,105,116,97,114,121,105,115,111,108,97,116,101, +100,32,102,114,111,109,32,116,104,101,111,112,112,111,115,105,116,105,111,110,32 +,116,111,32,116,104,101,116,104,101,32,79,108,100,32,84,101,115,116,97,109,101, +110,116,65,102,114,105,99,97,110,32,65,109,101,114,105,99,97,110,115,105,110,115 +,101,114,116,101,100,32,105,110,116,111,32,116,104,101,115,101,112,97,114,97,116 +,101,32,102,114,111,109,32,116,104,101,109,101,116,114,111,112,111,108,105,116, +97,110,32,97,114,101,97,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98, +108,101,97,99,107,110,111,119,108,101,100,103,101,100,32,116,104,97,116,97,114, +103,117,97,98,108,121,32,116,104,101,32,109,111,115,116,116,121,112,101,61,34, +116,101,120,116,47,99,115,115,34,62,10,116,104,101,32,73,110,116,101,114,110,97, +116,105,111,110,97,108,65,99,99,111,114,100,105,110,103,32,116,111,32,116,104, +101,32,112,101,61,34,116,101,120,116,47,99,115,115,34,32,47,62,10,99,111,105,110 +,99,105,100,101,32,119,105,116,104,32,116,104,101,116,119,111,45,116,104,105,114 +,100,115,32,111,102,32,116,104,101,68,117,114,105,110,103,32,116,104,105,115,32, +116,105,109,101,44,100,117,114,105,110,103,32,116,104,101,32,112,101,114,105,111 +,100,97,110,110,111,117,110,99,101,100,32,116,104,97,116,32,104,101,116,104,101, +32,105,110,116,101,114,110,97,116,105,111,110,97,108,97,110,100,32,109,111,114, +101,32,114,101,99,101,110,116,108,121,98,101,108,105,101,118,101,100,32,116,104, +97,116,32,116,104,101,99,111,110,115,99,105,111,117,115,110,101,115,115,32,97, +110,100,102,111,114,109,101,114,108,121,32,107,110,111,119,110,32,97,115,115,117 +,114,114,111,117,110,100,101,100,32,98,121,32,116,104,101,102,105,114,115,116,32 +,97,112,112,101,97,114,101,100,32,105,110,111,99,99,97,115,105,111,110,97,108, +108,121,32,117,115,101,100,112,111,115,105,116,105,111,110,58,97,98,115,111,108, +117,116,101,59,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,107,34,32,112 +,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,116,101,120, +116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,106,97,120,47,108,105,98, +115,47,106,113,117,101,114,121,47,49,46,98,97,99,107,103,114,111,117,110,100,45, +99,111,108,111,114,58,35,116,121,112,101,61,34,97,112,112,108,105,99,97,116,105, +111,110,47,97,110,103,117,97,103,101,34,32,99,111,110,116,101,110,116,61,34,60, +109,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,80,114,105,118,97 +,99,121,32,80,111,108,105,99,121,60,47,97,62,101,40,34,37,51,67,115,99,114,105, +112,116,32,115,114,99,61,39,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110, +107,34,62,79,110,32,116,104,101,32,111,116,104,101,114,32,104,97,110,100,44,46, +106,112,103,124,116,104,117,109,98,124,114,105,103,104,116,124,50,60,47,100,105, +118,62,60,100,105,118,32,99,108,97,115,115,61,34,60,100,105,118,32,115,116,121, +108,101,61,34,102,108,111,97,116,58,110,105,110,101,116,101,101,110,116,104,32, +99,101,110,116,117,114,121,60,47,98,111,100,121,62,13,10,60,47,104,116,109,108, +62,13,10,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,115,59,116, +101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,102,111,110,116,45, +119,101,105,103,104,116,58,32,98,111,108,100,59,32,65,99,99,111,114,100,105,110, +103,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98, +101,116,119,101,101,110,34,32,102,114,97,109,101,98,111,114,100,101,114,61,34,48 +,34,32,34,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,108, +105,110,107,32,104,114,101,102,61,34,104,116,116,112,58,47,47,104,116,109,108,52 +,47,108,111,111,115,101,46,100,116,100,34,62,10,100,117,114,105,110,103,32,116, +104,105,115,32,112,101,114,105,111,100,60,47,116,100,62,60,47,116,114,62,60,47, +116,97,98,108,101,62,99,108,111,115,101,108,121,32,114,101,108,97,116,101,100,32 +,116,111,102,111,114,32,116,104,101,32,102,105,114,115,116,32,116,105,109,101,59 +,102,111,110,116,45,119,101,105,103,104,116,58,98,111,108,100,59,105,110,112,117 +,116,32,116,121,112,101,61,34,116,101,120,116,34,32,60,115,112,97,110,32,115,116 +,121,108,101,61,34,102,111,110,116,45,111,110,114,101,97,100,121,115,116,97,116, +101,99,104,97,110,103,101,9,60,100,105,118,32,99,108,97,115,115,61,34,99,108,101 +,97,114,100,111,99,117,109,101,110,116,46,108,111,99,97,116,105,111,110,46,32,70 +,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,97,32,119,105,100, +101,32,118,97,114,105,101,116,121,32,111,102,32,60,33,68,79,67,84,89,80,69,32, +104,116,109,108,62,13,10,60,38,110,98,115,112,59,38,110,98,115,112,59,38,110,98, +115,112,59,34,62,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,115,116 +,121,108,101,61,34,102,108,111,97,116,58,108,101,102,116,59,99,111,110,99,101, +114,110,101,100,32,119,105,116,104,32,116,104,101,61,104,116,116,112,37,51,65,37 +,50,70,37,50,70,119,119,119,46,105,110,32,112,111,112,117,108,97,114,32,99,117, +108,116,117,114,101,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,32,47 +,62,105,116,32,105,115,32,112,111,115,115,105,98,108,101,32,116,111,32,72,97,114 +,118,97,114,100,32,85,110,105,118,101,114,115,105,116,121,116,121,108,101,115, +104,101,101,116,34,32,104,114,101,102,61,34,47,116,104,101,32,109,97,105,110,32, +99,104,97,114,97,99,116,101,114,79,120,102,111,114,100,32,85,110,105,118,101,114 +,115,105,116,121,32,32,110,97,109,101,61,34,107,101,121,119,111,114,100,115,34, +32,99,115,116,121,108,101,61,34,116,101,120,116,45,97,108,105,103,110,58,116,104 +,101,32,85,110,105,116,101,100,32,75,105,110,103,100,111,109,102,101,100,101,114 +,97,108,32,103,111,118,101,114,110,109,101,110,116,60,100,105,118,32,115,116,121 +,108,101,61,34,109,97,114,103,105,110,32,100,101,112,101,110,100,105,110,103,32, +111,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102, +32,116,104,101,60,100,105,118,32,99,108,97,115,115,61,34,104,101,97,100,101,114, +46,109,105,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,100,101,115,116, +114,117,99,116,105,111,110,32,111,102,32,116,104,101,115,108,105,103,104,116,108 +,121,32,100,105,102,102,101,114,101,110,116,105,110,32,97,99,99,111,114,100,97, +110,99,101,32,119,105,116,104,116,101,108,101,99,111,109,109,117,110,105,99,97, +116,105,111,110,115,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32,116, +104,101,115,104,111,114,116,108,121,32,116,104,101,114,101,97,102,116,101,114, +101,115,112,101,99,105,97,108,108,121,32,105,110,32,116,104,101,32,69,117,114, +111,112,101,97,110,32,99,111,117,110,116,114,105,101,115,72,111,119,101,118,101, +114,44,32,116,104,101,114,101,32,97,114,101,115,114,99,61,34,104,116,116,112,58, +47,47,115,116,97,116,105,99,115,117,103,103,101,115,116,101,100,32,116,104,97, +116,32,116,104,101,34,32,115,114,99,61,34,104,116,116,112,58,47,47,119,119,119, +46,97,32,108,97,114,103,101,32,110,117,109,98,101,114,32,111,102,32,84,101,108, +101,99,111,109,109,117,110,105,99,97,116,105,111,110,115,34,32,114,101,108,61,34 +,110,111,102,111,108,108,111,119,34,32,116,72,111,108,121,32,82,111,109,97,110, +32,69,109,112,101,114,111,114,97,108,109,111,115,116,32,101,120,99,108,117,115, +105,118,101,108,121,34,32,98,111,114,100,101,114,61,34,48,34,32,97,108,116,61,34 +,83,101,99,114,101,116,97,114,121,32,111,102,32,83,116,97,116,101,99,117,108,109 +,105,110,97,116,105,110,103,32,105,110,32,116,104,101,67,73,65,32,87,111,114,108 +,100,32,70,97,99,116,98,111,111,107,116,104,101,32,109,111,115,116,32,105,109, +112,111,114,116,97,110,116,97,110,110,105,118,101,114,115,97,114,121,32,111,102, +32,116,104,101,115,116,121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,45 +,60,108,105,62,60,101,109,62,60,97,32,104,114,101,102,61,34,47,116,104,101,32,65 +,116,108,97,110,116,105,99,32,79,99,101,97,110,115,116,114,105,99,116,108,121,32 +,115,112,101,97,107,105,110,103,44,115,104,111,114,116,108,121,32,98,101,102,111 +,114,101,32,116,104,101,100,105,102,102,101,114,101,110,116,32,116,121,112,101, +115,32,111,102,116,104,101,32,79,116,116,111,109,97,110,32,69,109,112,105,114, +101,62,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,65,110,32,73, +110,116,114,111,100,117,99,116,105,111,110,32,116,111,99,111,110,115,101,113,117 +,101,110,99,101,32,111,102,32,116,104,101,100,101,112,97,114,116,117,114,101,32, +102,114,111,109,32,116,104,101,67,111,110,102,101,100,101,114,97,116,101,32,83, +116,97,116,101,115,105,110,100,105,103,101,110,111,117,115,32,112,101,111,112, +108,101,115,80,114,111,99,101,101,100,105,110,103,115,32,111,102,32,116,104,101, +105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,116,104,101,116,104,101 +,111,114,105,101,115,32,104,97,118,101,32,98,101,101,110,105,110,118,111,108,118 +,101,109,101,110,116,32,105,110,32,116,104,101,100,105,118,105,100,101,100,32, +105,110,116,111,32,116,104,114,101,101,97,100,106,97,99,101,110,116,32,99,111, +117,110,116,114,105,101,115,105,115,32,114,101,115,112,111,110,115,105,98,108, +101,32,102,111,114,100,105,115,115,111,108,117,116,105,111,110,32,111,102,32,116 +,104,101,99,111,108,108,97,98,111,114,97,116,105,111,110,32,119,105,116,104,119, +105,100,101,108,121,32,114,101,103,97,114,100,101,100,32,97,115,104,105,115,32, +99,111,110,116,101,109,112,111,114,97,114,105,101,115,102,111,117,110,100,105, +110,103,32,109,101,109,98,101,114,32,111,102,68,111,109,105,110,105,99,97,110,32 +,82,101,112,117,98,108,105,99,103,101,110,101,114,97,108,108,121,32,97,99,99,101 +,112,116,101,100,116,104,101,32,112,111,115,115,105,98,105,108,105,116,121,32, +111,102,97,114,101,32,97,108,115,111,32,97,118,97,105,108,97,98,108,101,117,110, +100,101,114,32,99,111,110,115,116,114,117,99,116,105,111,110,114,101,115,116,111 +,114,97,116,105,111,110,32,111,102,32,116,104,101,116,104,101,32,103,101,110,101 +,114,97,108,32,112,117,98,108,105,99,105,115,32,97,108,109,111,115,116,32,101, +110,116,105,114,101,108,121,112,97,115,115,101,115,32,116,104,114,111,117,103, +104,32,116,104,101,104,97,115,32,98,101,101,110,32,115,117,103,103,101,115,116, +101,100,99,111,109,112,117,116,101,114,32,97,110,100,32,118,105,100,101,111,71, +101,114,109,97,110,105,99,32,108,97,110,103,117,97,103,101,115,32,97,99,99,111, +114,100,105,110,103,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110 +,116,32,102,114,111,109,32,116,104,101,115,104,111,114,116,108,121,32,97,102,116 +,101,114,119,97,114,100,115,104,114,101,102,61,34,104,116,116,112,115,58,47,47, +119,119,119,46,114,101,99,101,110,116,32,100,101,118,101,108,111,112,109,101,110 +,116,66,111,97,114,100,32,111,102,32,68,105,114,101,99,116,111,114,115,60,100, +105,118,32,99,108,97,115,115,61,34,115,101,97,114,99,104,124,32,60,97,32,104,114 +,101,102,61,34,104,116,116,112,58,47,47,73,110,32,112,97,114,116,105,99,117,108, +97,114,44,32,116,104,101,77,117,108,116,105,112,108,101,32,102,111,111,116,110, +111,116,101,115,111,114,32,111,116,104,101,114,32,115,117,98,115,116,97,110,99, +101,116,104,111,117,115,97,110,100,115,32,111,102,32,121,101,97,114,115,116,114, +97,110,115,108,97,116,105,111,110,32,111,102,32,116,104,101,60,47,100,105,118,62 +,13,10,60,47,100,105,118,62,13,10,13,10,60,97,32,104,114,101,102,61,34,105,110, +100,101,120,46,112,104,112,119,97,115,32,101,115,116,97,98,108,105,115,104,101, +100,32,105,110,109,105,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10, +112,97,114,116,105,99,105,112,97,116,101,32,105,110,32,116,104,101,97,32,115,116 +,114,111,110,103,32,105,110,102,108,117,101,110,99,101,115,116,121,108,101,61,34 +,109,97,114,103,105,110,45,116,111,112,58,114,101,112,114,101,115,101,110,116, +101,100,32,98,121,32,116,104,101,103,114,97,100,117,97,116,101,100,32,102,114, +111,109,32,116,104,101,84,114,97,100,105,116,105,111,110,97,108,108,121,44,32, +116,104,101,69,108,101,109,101,110,116,40,34,115,99,114,105,112,116,34,41,59,72, +111,119,101,118,101,114,44,32,115,105,110,99,101,32,116,104,101,47,100,105,118, +62,10,60,47,100,105,118,62,10,60,100,105,118,32,108,101,102,116,59,32,109,97,114 +,103,105,110,45,108,101,102,116,58,112,114,111,116,101,99,116,105,111,110,32,97, +103,97,105,110,115,116,48,59,32,118,101,114,116,105,99,97,108,45,97,108,105,103, +110,58,85,110,102,111,114,116,117,110,97,116,101,108,121,44,32,116,104,101,116, +121,112,101,61,34,105,109,97,103,101,47,120,45,105,99,111,110,47,100,105,118,62, +10,60,100,105,118,32,99,108,97,115,115,61,34,32,99,108,97,115,115,61,34,99,108, +101,97,114,102,105,120,34,62,60,100,105,118,32,99,108,97,115,115,61,34,102,111, +111,116,101,114,9,9,60,47,100,105,118,62,10,9,9,60,47,100,105,118,62,10,116,104, +101,32,109,111,116,105,111,110,32,112,105,99,116,117,114,101,208,145,209,138,208 +,187,208,179,208,176,209,128,209,129,208,186,208,184,208,177,209,138,208,187,208 +,179,208,176,209,128,209,129,208,186,208,184,208,164,208,181,208,180,208,181,209 +,128,208,176,209,134,208,184,208,184,208,189,208,181,209,129,208,186,208,190,208 +,187,209,140,208,186,208,190,209,129,208,190,208,190,208,177,209,137,208,181,208 +,189,208,184,208,181,209,129,208,190,208,190,208,177,209,137,208,181,208,189,208 +,184,209,143,208,191,209,128,208,190,208,179,209,128,208,176,208,188,208,188,209 +,139,208,158,209,130,208,191,209,128,208,176,208,178,208,184,209,130,209,140,208 +,177,208,181,209,129,208,191,208,187,208,176,209,130,208,189,208,190,208,188,208 +,176,209,130,208,181,209,128,208,184,208,176,208,187,209,139,208,191,208,190,208 +,183,208,178,208,190,208,187,209,143,208,181,209,130,208,191,208,190,209,129,208 +,187,208,181,208,180,208,189,208,184,208,181,209,128,208,176,208,183,208,187,208 +,184,209,135,208,189,209,139,209,133,208,191,209,128,208,190,208,180,209,131,208 +,186,209,134,208,184,208,184,208,191,209,128,208,190,208,179,209,128,208,176,208 +,188,208,188,208,176,208,191,208,190,208,187,208,189,208,190,209,129,209,130,209 +,140,209,142,208,189,208,176,209,133,208,190,208,180,208,184,209,130,209,129,209 +,143,208,184,208,183,208,177,209,128,208,176,208,189,208,189,208,190,208,181,208 +,189,208,176,209,129,208,181,208,187,208,181,208,189,208,184,209,143,208,184,208 +,183,208,188,208,181,208,189,208,181,208,189,208,184,209,143,208,186,208,176,209 +,130,208,181,208,179,208,190,209,128,208,184,208,184,208,144,208,187,208,181,208 +,186,209,129,208,176,208,189,208,180,209,128,224,164,166,224,165,141,224,164,181 +,224,164,190,224,164,176,224,164,190,224,164,174,224,165,136,224,164,168,224,165 +,129,224,164,133,224,164,178,224,164,170,224,165,141,224,164,176,224,164,166,224 +,164,190,224,164,168,224,164,173,224,164,190,224,164,176,224,164,164,224,165,128 +,224,164,175,224,164,133,224,164,168,224,165,129,224,164,166,224,165,135,224,164 +,182,224,164,185,224,164,191,224,164,168,224,165,141,224,164,166,224,165,128,224 +,164,135,224,164,130,224,164,161,224,164,191,224,164,175,224,164,190,224,164,166 +,224,164,191,224,164,178,224,165,141,224,164,178,224,165,128,224,164,133,224,164 +,167,224,164,191,224,164,149,224,164,190,224,164,176,224,164,181,224,165,128,224 +,164,161,224,164,191,224,164,175,224,165,139,224,164,154,224,164,191,224,164,159 +,224,165,141,224,164,160,224,165,135,224,164,184,224,164,174,224,164,190,224,164 +,154,224,164,190,224,164,176,224,164,156,224,164,130,224,164,149,224,165,141,224 +,164,182,224,164,168,224,164,166,224,165,129,224,164,168,224,164,191,224,164,175 +,224,164,190,224,164,170,224,165,141,224,164,176,224,164,175,224,165,139,224,164 +,151,224,164,133,224,164,168,224,165,129,224,164,184,224,164,190,224,164,176,224 +,164,145,224,164,168,224,164,178,224,164,190,224,164,135,224,164,168,224,164,170 +,224,164,190,224,164,176,224,165,141,224,164,159,224,165,128,224,164,182,224,164 +,176,224,165,141,224,164,164,224,165,139,224,164,130,224,164,178,224,165,139,224 +,164,149,224,164,184,224,164,173,224,164,190,224,164,171,224,164,188,224,165,141 +,224,164,178,224,165,136,224,164,182,224,164,182,224,164,176,224,165,141,224,164 +,164,224,165,135,224,164,130,224,164,170,224,165,141,224,164,176,224,164,166,224 +,165,135,224,164,182,224,164,170,224,165,141,224,164,178,224,165,135,224,164,175 +,224,164,176,224,164,149,224,165,135,224,164,130,224,164,166,224,165,141,224,164 +,176,224,164,184,224,165,141,224,164,165,224,164,191,224,164,164,224,164,191,224 +,164,137,224,164,164,224,165,141,224,164,170,224,164,190,224,164,166,224,164,137 +,224,164,168,224,165,141,224,164,185,224,165,135,224,164,130,224,164,154,224,164 +,191,224,164,159,224,165,141,224,164,160,224,164,190,224,164,175,224,164,190,224 +,164,164,224,165,141,224,164,176,224,164,190,224,164,156,224,165,141,224,164,175 +,224,164,190,224,164,166,224,164,190,224,164,170,224,165,129,224,164,176,224,164 +,190,224,164,168,224,165,135,224,164,156,224,165,139,224,164,161,224,164,188,224 +,165,135,224,164,130,224,164,133,224,164,168,224,165,129,224,164,181,224,164,190 +,224,164,166,224,164,182,224,165,141,224,164,176,224,165,135,224,164,163,224,165 +,128,224,164,182,224,164,191,224,164,149,224,165,141,224,164,183,224,164,190,224 +,164,184,224,164,176,224,164,149,224,164,190,224,164,176,224,165,128,224,164,184 +,224,164,130,224,164,151,224,165,141,224,164,176,224,164,185,224,164,170,224,164 +,176,224,164,191,224,164,163,224,164,190,224,164,174,224,164,172,224,165,141,224 +,164,176,224,164,190,224,164,130,224,164,161,224,164,172,224,164,154,224,165,141 +,224,164,154,224,165,139,224,164,130,224,164,137,224,164,170,224,164,178,224,164 +,172,224,165,141,224,164,167,224,164,174,224,164,130,224,164,164,224,165,141,224 +,164,176,224,165,128,224,164,184,224,164,130,224,164,170,224,164,176,224,165,141 +,224,164,149,224,164,137,224,164,174,224,165,141,224,164,174,224,165,128,224,164 +,166,224,164,174,224,164,190,224,164,167,224,165,141,224,164,175,224,164,174,224 +,164,184,224,164,185,224,164,190,224,164,175,224,164,164,224,164,190,224,164,182 +,224,164,172,224,165,141,224,164,166,224,165,139,224,164,130,224,164,174,224,165 +,128,224,164,161,224,164,191,224,164,175,224,164,190,224,164,134,224,164,136,224 +,164,170,224,165,128,224,164,143,224,164,178,224,164,174,224,165,139,224,164,172 +,224,164,190,224,164,135,224,164,178,224,164,184,224,164,130,224,164,150,224,165 +,141,224,164,175,224,164,190,224,164,134,224,164,170,224,164,176,224,165,135,224 +,164,182,224,164,168,224,164,133,224,164,168,224,165,129,224,164,172,224,164,130 +,224,164,167,224,164,172,224,164,190,224,164,156,224,164,188,224,164,190,224,164 +,176,224,164,168,224,164,181,224,165,128,224,164,168,224,164,164,224,164,174,224 +,164,170,224,165,141,224,164,176,224,164,174,224,165,129,224,164,150,224,164,170 +,224,165,141,224,164,176,224,164,182,224,165,141,224,164,168,224,164,170,224,164 +,176,224,164,191,224,164,181,224,164,190,224,164,176,224,164,168,224,165,129,224 +,164,149,224,164,184,224,164,190,224,164,168,224,164,184,224,164,174,224,164,176 +,224,165,141,224,164,165,224,164,168,224,164,134,224,164,175,224,165,139,224,164 +,156,224,164,191,224,164,164,224,164,184,224,165,139,224,164,174,224,164,181,224 +,164,190,224,164,176,216,167,217,132,217,133,216,180,216,167,216,177,217,131,216 +,167,216,170,216,167,217,132,217,133,217,134,216,170,216,175,217,138,216,167,216 +,170,216,167,217,132,217,131,217,133,216,168,217,138,217,136,216,170,216,177,216 +,167,217,132,217,133,216,180,216,167,217,135,216,175,216,167,216,170,216,185,216 +,175,216,175,216,167,217,132,216,178,217,136,216,167,216,177,216,185,216,175,216 +,175,216,167,217,132,216,177,216,175,217,136,216,175,216,167,217,132,216,165,216 +,179,217,132,216,167,217,133,217,138,216,169,216,167,217,132,217,129,217,136,216 +,170,217,136,216,180,217,136,216,168,216,167,217,132,217,133,216,179,216,167,216 +,168,217,130,216,167,216,170,216,167,217,132,217,133,216,185,217,132,217,136,217 +,133,216,167,216,170,216,167,217,132,217,133,216,179,217,132,216,179,217,132,216 +,167,216,170,216,167,217,132,216,172,216,177,216,167,217,129,217,138,217,131,216 +,179,216,167,217,132,216,167,216,179,217,132,216,167,217,133,217,138,216,169,216 +,167,217,132,216,167,216,170,216,181,216,167,217,132,216,167,216,170,107,101,121 +,119,111,114,100,115,34,32,99,111,110,116,101,110,116,61,34,119,51,46,111,114, +103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,97,32,116,97,114,103,101,116, +61,34,95,98,108,97,110,107,34,32,116,101,120,116,47,104,116,109,108,59,32,99,104 +,97,114,115,101,116,61,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,107, +34,62,60,116,97,98,108,101,32,99,101,108,108,112,97,100,100,105,110,103,61,34,97 +,117,116,111,99,111,109,112,108,101,116,101,61,34,111,102,102,34,32,116,101,120, +116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,116,111,32,108,97,115, +116,32,118,101,114,115,105,111,110,32,98,121,32,98,97,99,107,103,114,111,117,110 +,100,45,99,111,108,111,114,58,32,35,34,32,104,114,101,102,61,34,104,116,116,112, +58,47,47,119,119,119,46,47,100,105,118,62,60,47,100,105,118,62,60,100,105,118,32 +,105,100,61,60,97,32,104,114,101,102,61,34,35,34,32,99,108,97,115,115,61,34,34, +62,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,99,114,105,112, +116,34,32,115,114,99,61,34,104,116,116,112,58,47,47,10,60,115,99,114,105,112,116 +,32,108,97,110,103,117,97,103,101,61,34,47,47,69,78,34,32,34,104,116,116,112,58, +47,47,119,119,119,46,119,101,110,99,111,100,101,85,82,73,67,111,109,112,111,110, +101,110,116,40,34,32,104,114,101,102,61,34,106,97,118,97,115,99,114,105,112,116, +58,60,100,105,118,32,99,108,97,115,115,61,34,99,111,110,116,101,110,116,100,111, +99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,115,99,112,111,115,105, +116,105,111,110,58,32,97,98,115,111,108,117,116,101,59,115,99,114,105,112,116,32 +,115,114,99,61,34,104,116,116,112,58,47,47,32,115,116,121,108,101,61,34,109,97, +114,103,105,110,45,116,111,112,58,46,109,105,110,46,106,115,34,62,60,47,115,99, +114,105,112,116,62,10,60,47,100,105,118,62,10,60,100,105,118,32,99,108,97,115, +115,61,34,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,32,10, +13,10,60,47,98,111,100,121,62,13,10,60,47,104,116,109,108,62,100,105,115,116,105 +,110,99,116,105,111,110,32,98,101,116,119,101,101,110,47,34,32,116,97,114,103, +101,116,61,34,95,98,108,97,110,107,34,62,60,108,105,110,107,32,104,114,101,102, +61,34,104,116,116,112,58,47,47,101,110,99,111,100,105,110,103,61,34,117,116,102, +45,56,34,63,62,10,119,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110, +101,114,63,97,99,116,105,111,110,61,34,104,116,116,112,58,47,47,119,119,119,46, +105,99,111,110,34,32,104,114,101,102,61,34,104,116,116,112,58,47,47,32,115,116, +121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,58,116,121,112,101,61,34, +116,101,120,116,47,99,115,115,34,32,47,62,10,109,101,116,97,32,112,114,111,112, +101,114,116,121,61,34,111,103,58,116,60,105,110,112,117,116,32,116,121,112,101, +61,34,116,101,120,116,34,32,32,115,116,121,108,101,61,34,116,101,120,116,45,97, +108,105,103,110,58,116,104,101,32,100,101,118,101,108,111,112,109,101,110,116,32 +,111,102,32,116,121,108,101,115,104,101,101,116,34,32,116,121,112,101,61,34,116, +101,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,102,45,56,105,115 +,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,116,97,98,108, +101,32,119,105,100,116,104,61,34,49,48,48,37,34,32,73,110,32,97,100,100,105,116, +105,111,110,32,116,111,32,116,104,101,32,99,111,110,116,114,105,98,117,116,101, +100,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,115,32, +98,101,116,119,101,101,110,100,101,118,101,108,111,112,109,101,110,116,32,111, +102,32,116,104,101,32,73,116,32,105,115,32,105,109,112,111,114,116,97,110,116,32 +,116,111,32,60,47,115,99,114,105,112,116,62,10,10,60,115,99,114,105,112,116,32, +32,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,49,62,60,47, +115,112,97,110,62,60,115,112,97,110,32,105,100,61,103,98,76,105,98,114,97,114, +121,32,111,102,32,67,111,110,103,114,101,115,115,60,105,109,103,32,115,114,99,61 +,34,104,116,116,112,58,47,47,105,109,69,110,103,108,105,115,104,32,116,114,97, +110,115,108,97,116,105,111,110,65,99,97,100,101,109,121,32,111,102,32,83,99,105, +101,110,99,101,115,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108, +97,121,58,99,111,110,115,116,114,117,99,116,105,111,110,32,111,102,32,116,104, +101,46,103,101,116,69,108,101,109,101,110,116,66,121,73,100,40,105,100,41,105, +110,32,99,111,110,106,117,110,99,116,105,111,110,32,119,105,116,104,69,108,101, +109,101,110,116,40,39,115,99,114,105,112,116,39,41,59,32,60,109,101,116,97,32, +112,114,111,112,101,114,116,121,61,34,111,103,58,208,145,209,138,208,187,208,179 +,208,176,209,128,209,129,208,186,208,184,10,32,116,121,112,101,61,34,116,101,120 +,116,34,32,110,97,109,101,61,34,62,80,114,105,118,97,99,121,32,80,111,108,105,99 +,121,60,47,97,62,97,100,109,105,110,105,115,116,101,114,101,100,32,98,121,32,116 +,104,101,101,110,97,98,108,101,83,105,110,103,108,101,82,101,113,117,101,115,116 +,115,116,121,108,101,61,38,113,117,111,116,59,109,97,114,103,105,110,58,60,47, +100,105,118,62,60,47,100,105,118,62,60,47,100,105,118,62,60,62,60,105,109,103,32 +,115,114,99,61,34,104,116,116,112,58,47,47,105,32,115,116,121,108,101,61,38,113, +117,111,116,59,102,108,111,97,116,58,114,101,102,101,114,114,101,100,32,116,111, +32,97,115,32,116,104,101,32,116,111,116,97,108,32,112,111,112,117,108,97,116,105 +,111,110,32,111,102,105,110,32,87,97,115,104,105,110,103,116,111,110,44,32,68,46 +,67,46,32,115,116,121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,45,97, +109,111,110,103,32,111,116,104,101,114,32,116,104,105,110,103,115,44,111,114,103 +,97,110,105,122,97,116,105,111,110,32,111,102,32,116,104,101,112,97,114,116,105, +99,105,112,97,116,101,100,32,105,110,32,116,104,101,116,104,101,32,105,110,116, +114,111,100,117,99,116,105,111,110,32,111,102,105,100,101,110,116,105,102,105, +101,100,32,119,105,116,104,32,116,104,101,102,105,99,116,105,111,110,97,108,32, +99,104,97,114,97,99,116,101,114,32,79,120,102,111,114,100,32,85,110,105,118,101, +114,115,105,116,121,32,109,105,115,117,110,100,101,114,115,116,97,110,100,105, +110,103,32,111,102,84,104,101,114,101,32,97,114,101,44,32,104,111,119,101,118, +101,114,44,115,116,121,108,101,115,104,101,101,116,34,32,104,114,101,102,61,34, +47,67,111,108,117,109,98,105,97,32,85,110,105,118,101,114,115,105,116,121,101, +120,112,97,110,100,101,100,32,116,111,32,105,110,99,108,117,100,101,117,115,117, +97,108,108,121,32,114,101,102,101,114,114,101,100,32,116,111,105,110,100,105,99, +97,116,105,110,103,32,116,104,97,116,32,116,104,101,104,97,118,101,32,115,117, +103,103,101,115,116,101,100,32,116,104,97,116,97,102,102,105,108,105,97,116,101, +100,32,119,105,116,104,32,116,104,101,99,111,114,114,101,108,97,116,105,111,110, +32,98,101,116,119,101,101,110,110,117,109,98,101,114,32,111,102,32,100,105,102, +102,101,114,101,110,116,62,60,47,116,100,62,60,47,116,114,62,60,47,116,97,98,108 +,101,62,82,101,112,117,98,108,105,99,32,111,102,32,73,114,101,108,97,110,100,10, +60,47,115,99,114,105,112,116,62,10,60,115,99,114,105,112,116,32,117,110,100,101, +114,32,116,104,101,32,105,110,102,108,117,101,110,99,101,99,111,110,116,114,105, +98,117,116,105,111,110,32,116,111,32,116,104,101,79,102,102,105,99,105,97,108,32 +,119,101,98,115,105,116,101,32,111,102,104,101,97,100,113,117,97,114,116,101,114 +,115,32,111,102,32,116,104,101,99,101,110,116,101,114,101,100,32,97,114,111,117, +110,100,32,116,104,101,105,109,112,108,105,99,97,116,105,111,110,115,32,111,102, +32,116,104,101,104,97,118,101,32,98,101,101,110,32,100,101,118,101,108,111,112, +101,100,70,101,100,101,114,97,108,32,82,101,112,117,98,108,105,99,32,111,102,98, +101,99,97,109,101,32,105,110,99,114,101,97,115,105,110,103,108,121,99,111,110, +116,105,110,117,97,116,105,111,110,32,111,102,32,116,104,101,78,111,116,101,44, +32,104,111,119,101,118,101,114,44,32,116,104,97,116,115,105,109,105,108,97,114, +32,116,111,32,116,104,97,116,32,111,102,32,99,97,112,97,98,105,108,105,116,105, +101,115,32,111,102,32,116,104,101,97,99,99,111,114,100,97,110,99,101,32,119,105, +116,104,32,116,104,101,112,97,114,116,105,99,105,112,97,110,116,115,32,105,110, +32,116,104,101,102,117,114,116,104,101,114,32,100,101,118,101,108,111,112,109, +101,110,116,117,110,100,101,114,32,116,104,101,32,100,105,114,101,99,116,105,111 +,110,105,115,32,111,102,116,101,110,32,99,111,110,115,105,100,101,114,101,100, +104,105,115,32,121,111,117,110,103,101,114,32,98,114,111,116,104,101,114,60,47, +116,100,62,60,47,116,114,62,60,47,116,97,98,108,101,62,60,97,32,104,116,116,112, +45,101,113,117,105,118,61,34,88,45,85,65,45,112,104,121,115,105,99,97,108,32,112 +,114,111,112,101,114,116,105,101,115,111,102,32,66,114,105,116,105,115,104,32,67 +,111,108,117,109,98,105,97,104,97,115,32,98,101,101,110,32,99,114,105,116,105,99 +,105,122,101,100,40,119,105,116,104,32,116,104,101,32,101,120,99,101,112,116,105 +,111,110,113,117,101,115,116,105,111,110,115,32,97,98,111,117,116,32,116,104,101 +,112,97,115,115,105,110,103,32,116,104,114,111,117,103,104,32,116,104,101,48,34, +32,99,101,108,108,112,97,100,100,105,110,103,61,34,48,34,32,116,104,111,117,115, +97,110,100,115,32,111,102,32,112,101,111,112,108,101,114,101,100,105,114,101,99, +116,115,32,104,101,114,101,46,32,70,111,114,104,97,118,101,32,99,104,105,108,100 +,114,101,110,32,117,110,100,101,114,37,51,69,37,51,67,47,115,99,114,105,112,116, +37,51,69,34,41,41,59,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119 +,119,119,46,60,108,105,62,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47, +47,115,105,116,101,95,110,97,109,101,34,32,99,111,110,116,101,110,116,61,34,116, +101,120,116,45,100,101,99,111,114,97,116,105,111,110,58,110,111,110,101,115,116, +121,108,101,61,34,100,105,115,112,108,97,121,58,32,110,111,110,101,60,109,101, +116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,88,45,110,101,119,32,68, +97,116,101,40,41,46,103,101,116,84,105,109,101,40,41,32,116,121,112,101,61,34, +105,109,97,103,101,47,120,45,105,99,111,110,34,60,47,115,112,97,110,62,60,115, +112,97,110,32,99,108,97,115,115,61,34,108,97,110,103,117,97,103,101,61,34,106,97 +,118,97,115,99,114,105,112,116,119,105,110,100,111,119,46,108,111,99,97,116,105, +111,110,46,104,114,101,102,60,97,32,104,114,101,102,61,34,106,97,118,97,115,99, +114,105,112,116,58,45,45,62,13,10,60,115,99,114,105,112,116,32,116,121,112,101, +61,34,116,60,97,32,104,114,101,102,61,39,104,116,116,112,58,47,47,119,119,119,46 +,104,111,114,116,99,117,116,32,105,99,111,110,34,32,104,114,101,102,61,34,60,47, +100,105,118,62,13,10,60,100,105,118,32,99,108,97,115,115,61,34,60,115,99,114,105 +,112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,34,32,114,101,108,61,34, +115,116,121,108,101,115,104,101,101,116,34,32,116,60,47,100,105,118,62,10,60,115 +,99,114,105,112,116,32,116,121,112,101,61,47,97,62,32,60,97,32,104,114,101,102, +61,34,104,116,116,112,58,47,47,32,97,108,108,111,119,84,114,97,110,115,112,97, +114,101,110,99,121,61,34,88,45,85,65,45,67,111,109,112,97,116,105,98,108,101,34, +32,99,111,110,114,101,108,97,116,105,111,110,115,104,105,112,32,98,101,116,119, +101,101,110,10,60,47,115,99,114,105,112,116,62,13,10,60,115,99,114,105,112,116, +32,60,47,97,62,60,47,108,105,62,60,47,117,108,62,60,47,100,105,118,62,97,115,115 +,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,112,114,111,103, +114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,60,47,97,62,60,97,32 +,104,114,101,102,61,34,104,116,116,112,58,47,47,60,47,97,62,60,47,108,105,62,60, +108,105,32,99,108,97,115,115,61,34,102,111,114,109,32,97,99,116,105,111,110,61, +34,104,116,116,112,58,47,47,60,100,105,118,32,115,116,121,108,101,61,34,100,105, +115,112,108,97,121,58,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101 +,61,34,113,34,60,116,97,98,108,101,32,119,105,100,116,104,61,34,49,48,48,37,34, +32,98,97,99,107,103,114,111,117,110,100,45,112,111,115,105,116,105,111,110,58,34 +,32,98,111,114,100,101,114,61,34,48,34,32,119,105,100,116,104,61,34,114,101,108, +61,34,115,104,111,114,116,99,117,116,32,105,99,111,110,34,32,104,54,62,60,117, +108,62,60,108,105,62,60,97,32,104,114,101,102,61,34,32,32,60,109,101,116,97,32, +104,116,116,112,45,101,113,117,105,118,61,34,99,115,115,34,32,109,101,100,105,97 +,61,34,115,99,114,101,101,110,34,32,114,101,115,112,111,110,115,105,98,108,101, +32,102,111,114,32,116,104,101,32,34,32,116,121,112,101,61,34,97,112,112,108,105, +99,97,116,105,111,110,47,34,32,115,116,121,108,101,61,34,98,97,99,107,103,114, +111,117,110,100,45,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116, +102,45,56,34,32,97,108,108,111,119,116,114,97,110,115,112,97,114,101,110,99,121, +61,34,115,116,121,108,101,115,104,101,101,116,34,32,116,121,112,101,61,34,116, +101,13,10,60,109,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,62, +60,47,115,112,97,110,62,60,115,112,97,110,32,99,108,97,115,115,61,34,48,34,32,99 +,101,108,108,115,112,97,99,105,110,103,61,34,48,34,62,59,10,60,47,115,99,114,105 +,112,116,62,10,60,115,99,114,105,112,116,32,115,111,109,101,116,105,109,101,115, +32,99,97,108,108,101,100,32,116,104,101,100,111,101,115,32,110,111,116,32,110, +101,99,101,115,115,97,114,105,108,121,70,111,114,32,109,111,114,101,32,105,110, +102,111,114,109,97,116,105,111,110,97,116,32,116,104,101,32,98,101,103,105,110, +110,105,110,103,32,111,102,32,60,33,68,79,67,84,89,80,69,32,104,116,109,108,62, +60,104,116,109,108,112,97,114,116,105,99,117,108,97,114,108,121,32,105,110,32, +116,104,101,32,116,121,112,101,61,34,104,105,100,100,101,110,34,32,110,97,109, +101,61,34,106,97,118,97,115,99,114,105,112,116,58,118,111,105,100,40,48,41,59,34 +,101,102,102,101,99,116,105,118,101,110,101,115,115,32,111,102,32,116,104,101,32 +,97,117,116,111,99,111,109,112,108,101,116,101,61,34,111,102,102,34,32,103,101, +110,101,114,97,108,108,121,32,99,111,110,115,105,100,101,114,101,100,62,60,105, +110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,34,62,60,47,115, +99,114,105,112,116,62,13,10,60,115,99,114,105,112,116,116,104,114,111,117,103, +104,111,117,116,32,116,104,101,32,119,111,114,108,100,99,111,109,109,111,110,32, +109,105,115,99,111,110,99,101,112,116,105,111,110,97,115,115,111,99,105,97,116, +105,111,110,32,119,105,116,104,32,116,104,101,60,47,100,105,118,62,10,60,47,100, +105,118,62,10,60,100,105,118,32,99,100,117,114,105,110,103,32,104,105,115,32,108 +,105,102,101,116,105,109,101,44,99,111,114,114,101,115,112,111,110,100,105,110, +103,32,116,111,32,116,104,101,116,121,112,101,61,34,105,109,97,103,101,47,120,45 +,105,99,111,110,34,32,97,110,32,105,110,99,114,101,97,115,105,110,103,32,110,117 +,109,98,101,114,100,105,112,108,111,109,97,116,105,99,32,114,101,108,97,116,105, +111,110,115,97,114,101,32,111,102,116,101,110,32,99,111,110,115,105,100,101,114, +101,100,109,101,116,97,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34, +32,60,105,110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,101,120 +,97,109,112,108,101,115,32,105,110,99,108,117,100,101,32,116,104,101,34,62,60, +105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,105,112,97,114,116,105, +99,105,112,97,116,105,111,110,32,105,110,32,116,104,101,116,104,101,32,101,115, +116,97,98,108,105,115,104,109,101,110,116,32,111,102,10,60,47,100,105,118,62,10, +60,100,105,118,32,99,108,97,115,115,61,34,38,97,109,112,59,110,98,115,112,59,38, +97,109,112,59,110,98,115,112,59,116,111,32,100,101,116,101,114,109,105,110,101, +32,119,104,101,116,104,101,114,113,117,105,116,101,32,100,105,102,102,101,114, +101,110,116,32,102,114,111,109,109,97,114,107,101,100,32,116,104,101,32,98,101, +103,105,110,110,105,110,103,100,105,115,116,97,110,99,101,32,98,101,116,119,101, +101,110,32,116,104,101,99,111,110,116,114,105,98,117,116,105,111,110,115,32,116, +111,32,116,104,101,99,111,110,102,108,105,99,116,32,98,101,116,119,101,101,110, +32,116,104,101,119,105,100,101,108,121,32,99,111,110,115,105,100,101,114,101,100 +,32,116,111,119,97,115,32,111,110,101,32,111,102,32,116,104,101,32,102,105,114, +115,116,119,105,116,104,32,118,97,114,121,105,110,103,32,100,101,103,114,101,101 +,115,104,97,118,101,32,115,112,101,99,117,108,97,116,101,100,32,116,104,97,116, +40,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,112, +97,114,116,105,99,105,112,97,116,105,110,103,32,105,110,32,116,104,101,111,114, +105,103,105,110,97,108,108,121,32,100,101,118,101,108,111,112,101,100,101,116,97 +,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,62,32,116,121,112,101, +61,34,116,101,120,116,47,99,115,115,34,32,47,62,10,105,110,116,101,114,99,104,97 +,110,103,101,97,98,108,121,32,119,105,116,104,109,111,114,101,32,99,108,111,115, +101,108,121,32,114,101,108,97,116,101,100,115,111,99,105,97,108,32,97,110,100,32 +,112,111,108,105,116,105,99,97,108,116,104,97,116,32,119,111,117,108,100,32,111, +116,104,101,114,119,105,115,101,112,101,114,112,101,110,100,105,99,117,108,97, +114,32,116,111,32,116,104,101,115,116,121,108,101,32,116,121,112,101,61,34,116, +101,120,116,47,99,115,115,116,121,112,101,61,34,115,117,98,109,105,116,34,32,110 +,97,109,101,61,34,102,97,109,105,108,105,101,115,32,114,101,115,105,100,105,110, +103,32,105,110,100,101,118,101,108,111,112,105,110,103,32,99,111,117,110,116,114 +,105,101,115,99,111,109,112,117,116,101,114,32,112,114,111,103,114,97,109,109, +105,110,103,101,99,111,110,111,109,105,99,32,100,101,118,101,108,111,112,109,101 +,110,116,100,101,116,101,114,109,105,110,97,116,105,111,110,32,111,102,32,116, +104,101,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111 +,110,111,110,32,115,101,118,101,114,97,108,32,111,99,99,97,115,105,111,110,115, +112,111,114,116,117,103,117,195,170,115,32,40,69,117,114,111,112,101,117,41,208, +163,208,186,209,128,208,176,209,151,208,189,209,129,209,140,208,186,208,176,209, +131,208,186,209,128,208,176,209,151,208,189,209,129,209,140,208,186,208,176,208, +160,208,190,209,129,209,129,208,184,208,185,209,129,208,186,208,190,208,185,208, +188,208,176,209,130,208,181,209,128,208,184,208,176,208,187,208,190,208,178,208, +184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,208,184,209, +131,208,191,209,128,208,176,208,178,208,187,208,181,208,189,208,184,209,143,208, +189,208,181,208,190,208,177,209,133,208,190,208,180,208,184,208,188,208,190,208, +184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,143,208, +152,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,143,208, +160,208,181,209,129,208,191,209,131,208,177,208,187,208,184,208,186,208,184,208, +186,208,190,208,187,208,184,209,135,208,181,209,129,209,130,208,178,208,190,208, +184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,142,209, +130,208,181,209,128,209,128,208,184,209,130,208,190,209,128,208,184,208,184,208, +180,208,190,209,129,209,130,208,176,209,130,208,190,209,135,208,189,208,190,216, +167,217,132,217,133,216,170,217,136,216,167,216,172,216,175,217,136,217,134,216, +167,217,132,216,167,216,180,216,170,216,177,216,167,217,131,216,167,216,170,216, +167,217,132,216,167,217,130,216,170,216,177,216,167,216,173,216,167,216,170,104, +116,109,108,59,32,99,104,97,114,115,101,116,61,85,84,70,45,56,34,32,115,101,116, +84,105,109,101,111,117,116,40,102,117,110,99,116,105,111,110,40,41,100,105,115, +112,108,97,121,58,105,110,108,105,110,101,45,98,108,111,99,107,59,60,105,110,112 +,117,116,32,116,121,112,101,61,34,115,117,98,109,105,116,34,32,116,121,112,101, +32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,105,60,105,109,103,32, +115,114,99,61,34,104,116,116,112,58,47,47,119,119,119,46,34,32,34,104,116,116, +112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,115,104,111,114,116,99,117, +116,32,105,99,111,110,34,32,104,114,101,102,61,34,34,32,97,117,116,111,99,111, +109,112,108,101,116,101,61,34,111,102,102,34,32,60,47,97,62,60,47,100,105,118,62 +,60,100,105,118,32,99,108,97,115,115,61,60,47,97,62,60,47,108,105,62,10,60,108, +105,32,99,108,97,115,115,61,34,99,115,115,34,32,116,121,112,101,61,34,116,101, +120,116,47,99,115,115,34,32,60,102,111,114,109,32,97,99,116,105,111,110,61,34, +104,116,116,112,58,47,47,120,116,47,99,115,115,34,32,104,114,101,102,61,34,104, +116,116,112,58,47,47,108,105,110,107,32,114,101,108,61,34,97,108,116,101,114,110 +,97,116,101,34,32,13,10,60,115,99,114,105,112,116,32,116,121,112,101,61,34,116, +101,120,116,47,32,111,110,99,108,105,99,107,61,34,106,97,118,97,115,99,114,105, +112,116,58,40,110,101,119,32,68,97,116,101,41,46,103,101,116,84,105,109,101,40, +41,125,104,101,105,103,104,116,61,34,49,34,32,119,105,100,116,104,61,34,49,34,32 +,80,101,111,112,108,101,39,115,32,82,101,112,117,98,108,105,99,32,111,102,32,32, +60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,116,101, +120,116,45,100,101,99,111,114,97,116,105,111,110,58,117,110,100,101,114,116,104, +101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,116,104,101,32,60,47,100 +,105,118,62,10,60,47,100,105,118,62,10,60,47,100,105,118,62,10,101,115,116,97,98 +,108,105,115,104,109,101,110,116,32,111,102,32,116,104,101,32,60,47,100,105,118, +62,60,47,100,105,118,62,60,47,100,105,118,62,60,47,100,35,118,105,101,119,112, +111,114,116,123,109,105,110,45,104,101,105,103,104,116,58,10,60,115,99,114,105, +112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,111,112,116,105,111,110,62, +60,111,112,116,105,111,110,32,118,97,108,117,101,61,111,102,116,101,110,32,114, +101,102,101,114,114,101,100,32,116,111,32,97,115,32,47,111,112,116,105,111,110, +62,10,60,111,112,116,105,111,110,32,118,97,108,117,60,33,68,79,67,84,89,80,69,32 +,104,116,109,108,62,10,60,33,45,45,91,73,110,116,101,114,110,97,116,105,111,110, +97,108,32,65,105,114,112,111,114,116,62,10,60,97,32,104,114,101,102,61,34,104, +116,116,112,58,47,47,119,119,119,60,47,97,62,60,97,32,104,114,101,102,61,34,104, +116,116,112,58,47,47,119,224,184,160,224,184,178,224,184,169,224,184,178,224,185 +,132,224,184,151,224,184,162,225,131,165,225,131,144,225,131,160,225,131,151,225 +,131,163,225,131,154,225,131,152,230,173,163,233,171,148,228,184,173,230,150,135 +,32,40,231,185,129,233,171,148,41,224,164,168,224,164,191,224,164,176,224,165, +141,224,164,166,224,165,135,224,164,182,224,164,161,224,164,190,224,164,137,224, +164,168,224,164,178,224,165,139,224,164,161,224,164,149,224,165,141,224,164,183, +224,165,135,224,164,164,224,165,141,224,164,176,224,164,156,224,164,190,224,164, +168,224,164,149,224,164,190,224,164,176,224,165,128,224,164,184,224,164,130,224, +164,172,224,164,130,224,164,167,224,164,191,224,164,164,224,164,184,224,165,141, +224,164,165,224,164,190,224,164,170,224,164,168,224,164,190,224,164,184,224,165, +141,224,164,181,224,165,128,224,164,149,224,164,190,224,164,176,224,164,184,224, +164,130,224,164,184,224,165,141,224,164,149,224,164,176,224,164,163,224,164,184, +224,164,190,224,164,174,224,164,151,224,165,141,224,164,176,224,165,128,224,164, +154,224,164,191,224,164,159,224,165,141,224,164,160,224,165,139,224,164,130,224, +164,181,224,164,191,224,164,156,224,165,141,224,164,158,224,164,190,224,164,168, +224,164,133,224,164,174,224,165,135,224,164,176,224,164,191,224,164,149,224,164, +190,224,164,181,224,164,191,224,164,173,224,164,191,224,164,168,224,165,141,224, +164,168,224,164,151,224,164,190,224,164,161,224,164,191,224,164,175,224,164,190, +224,164,129,224,164,149,224,165,141,224,164,175,224,165,139,224,164,130,224,164, +149,224,164,191,224,164,184,224,165,129,224,164,176,224,164,149,224,165,141,224, +164,183,224,164,190,224,164,170,224,164,185,224,165,129,224,164,129,224,164,154, +224,164,164,224,165,128,224,164,170,224,165,141,224,164,176,224,164,172,224,164, +130,224,164,167,224,164,168,224,164,159,224,164,191,224,164,170,224,165,141,224, +164,170,224,164,163,224,165,128,224,164,149,224,165,141,224,164,176,224,164,191, +224,164,149,224,165,135,224,164,159,224,164,170,224,165,141,224,164,176,224,164, +190,224,164,176,224,164,130,224,164,173,224,164,170,224,165,141,224,164,176,224, +164,190,224,164,170,224,165,141,224,164,164,224,164,174,224,164,190,224,164,178, +224,164,191,224,164,149,224,165,139,224,164,130,224,164,176,224,164,171,224,164, +188,224,165,141,224,164,164,224,164,190,224,164,176,224,164,168,224,164,191,224, +164,176,224,165,141,224,164,174,224,164,190,224,164,163,224,164,178,224,164,191, +224,164,174,224,164,191,224,164,159,224,165,135,224,164,161,100,101,115,99,114, +105,112,116,105,111,110,34,32,99,111,110,116,101,110,116,61,34,100,111,99,117, +109,101,110,116,46,108,111,99,97,116,105,111,110,46,112,114,111,116,46,103,101, +116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,60,33,68,79 +,67,84,89,80,69,32,104,116,109,108,62,10,60,104,116,109,108,32,60,109,101,116,97 +,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,62,58,117,114,108,34,32 +,99,111,110,116,101,110,116,61,34,104,116,116,112,58,47,47,46,99,115,115,34,32, +114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,115,116,121,108,101 +,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,62,116,121,112,101,61 +,34,116,101,120,116,47,99,115,115,34,32,104,114,101,102,61,34,119,51,46,111,114, +103,47,49,57,57,57,47,120,104,116,109,108,34,32,120,109,108,116,121,112,101,61, +34,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,34,32,109,101,116,104 +,111,100,61,34,103,101,116,34,32,97,99,116,105,111,110,61,34,108,105,110,107,32, +114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,32,61,32,100,111 +,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,116,121,112, +101,61,34,105,109,97,103,101,47,120,45,105,99,111,110,34,32,47,62,99,101,108,108 +,112,97,100,100,105,110,103,61,34,48,34,32,99,101,108,108,115,112,46,99,115,115, +34,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,32,60,47,97,62,60, +47,108,105,62,60,108,105,62,60,97,32,104,114,101,102,61,34,34,32,119,105,100,116 +,104,61,34,49,34,32,104,101,105,103,104,116,61,34,49,34,34,62,60,97,32,104,114, +101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,115,116,121,108,101,61,34, +100,105,115,112,108,97,121,58,110,111,110,101,59,34,62,97,108,116,101,114,110,97 +,116,101,34,32,116,121,112,101,61,34,97,112,112,108,105,45,47,47,87,51,67,47,47, +68,84,68,32,88,72,84,77,76,32,49,46,48,32,101,108,108,115,112,97,99,105,110,103, +61,34,48,34,32,99,101,108,108,112,97,100,32,116,121,112,101,61,34,104,105,100, +100,101,110,34,32,118,97,108,117,101,61,34,47,97,62,38,110,98,115,112,59,60,115, +112,97,110,32,114,111,108,101,61,34,115,10,60,105,110,112,117,116,32,116,121,112 +,101,61,34,104,105,100,100,101,110,34,32,108,97,110,103,117,97,103,101,61,34,74, +97,118,97,83,99,114,105,112,116,34,32,32,100,111,99,117,109,101,110,116,46,103, +101,116,69,108,101,109,101,110,116,115,66,103,61,34,48,34,32,99,101,108,108,115, +112,97,99,105,110,103,61,34,48,34,32,121,112,101,61,34,116,101,120,116,47,99,115 +,115,34,32,109,101,100,105,97,61,34,116,121,112,101,61,39,116,101,120,116,47,106 +,97,118,97,115,99,114,105,112,116,39,119,105,116,104,32,116,104,101,32,101,120, +99,101,112,116,105,111,110,32,111,102,32,121,112,101,61,34,116,101,120,116,47,99 +,115,115,34,32,114,101,108,61,34,115,116,32,104,101,105,103,104,116,61,34,49,34, +32,119,105,100,116,104,61,34,49,34,32,61,39,43,101,110,99,111,100,101,85,82,73, +67,111,109,112,111,110,101,110,116,40,60,108,105,110,107,32,114,101,108,61,34,97 +,108,116,101,114,110,97,116,101,34,32,10,98,111,100,121,44,32,116,114,44,32,105, +110,112,117,116,44,32,116,101,120,116,109,101,116,97,32,110,97,109,101,61,34,114 +,111,98,111,116,115,34,32,99,111,110,109,101,116,104,111,100,61,34,112,111,115, +116,34,32,97,99,116,105,111,110,61,34,62,10,60,97,32,104,114,101,102,61,34,104, +116,116,112,58,47,47,119,119,119,46,99,115,115,34,32,114,101,108,61,34,115,116, +121,108,101,115,104,101,101,116,34,32,60,47,100,105,118,62,60,47,100,105,118,62, +60,100,105,118,32,99,108,97,115,115,108,97,110,103,117,97,103,101,61,34,106,97, +118,97,115,99,114,105,112,116,34,62,97,114,105,97,45,104,105,100,100,101,110,61, +34,116,114,117,101,34,62,194,183,60,114,105,112,116,34,32,116,121,112,101,61,34, +116,101,120,116,47,106,97,118,97,115,108,61,48,59,125,41,40,41,59,10,40,102,117, +110,99,116,105,111,110,40,41,123,98,97,99,107,103,114,111,117,110,100,45,105,109 +,97,103,101,58,32,117,114,108,40,47,97,62,60,47,108,105,62,60,108,105,62,60,97, +32,104,114,101,102,61,34,104,9,9,60,108,105,62,60,97,32,104,114,101,102,61,34, +104,116,116,112,58,47,47,97,116,111,114,34,32,97,114,105,97,45,104,105,100,100, +101,110,61,34,116,114,117,62,32,60,97,32,104,114,101,102,61,34,104,116,116,112, +58,47,47,119,119,119,46,108,97,110,103,117,97,103,101,61,34,106,97,118,97,115,99 +,114,105,112,116,34,32,47,111,112,116,105,111,110,62,10,60,111,112,116,105,111, +110,32,118,97,108,117,101,47,100,105,118,62,60,47,100,105,118,62,60,100,105,118, +32,99,108,97,115,115,61,114,97,116,111,114,34,32,97,114,105,97,45,104,105,100, +100,101,110,61,34,116,114,101,61,40,110,101,119,32,68,97,116,101,41,46,103,101, +116,84,105,109,101,40,41,112,111,114,116,117,103,117,195,170,115,32,40,100,111, +32,66,114,97,115,105,108,41,208,190,209,128,208,179,208,176,208,189,208,184,208, +183,208,176,209,134,208,184,208,184,208,178,208,190,208,183,208,188,208,190,208, +182,208,189,208,190,209,129,209,130,209,140,208,190,208,177,209,128,208,176,208, +183,208,190,208,178,208,176,208,189,208,184,209,143,209,128,208,181,208,179,208, +184,209,129,209,130,209,128,208,176,209,134,208,184,208,184,208,178,208,190,208, +183,208,188,208,190,208,182,208,189,208,190,209,129,209,130,208,184,208,190,208, +177,209,143,208,183,208,176,209,130,208,181,208,187,209,140,208,189,208,176,60, +33,68,79,67,84,89,80,69,32,104,116,109,108,32,80,85,66,76,73,67,32,34,110,116,45 +,84,121,112,101,34,32,99,111,110,116,101,110,116,61,34,116,101,120,116,47,60,109 +,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110,116,101, +114,97,110,115,105,116,105,111,110,97,108,47,47,69,78,34,32,34,104,116,116,112, +58,60,104,116,109,108,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119, +119,119,45,47,47,87,51,67,47,47,68,84,68,32,88,72,84,77,76,32,49,46,48,32,84,68, +84,68,47,120,104,116,109,108,49,45,116,114,97,110,115,105,116,105,111,110,97,108 +,47,47,119,119,119,46,119,51,46,111,114,103,47,84,82,47,120,104,116,109,108,49, +47,112,101,32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116, +39,59,60,109,101,116,97,32,110,97,109,101,61,34,100,101,115,99,114,105,112,116, +105,111,110,112,97,114,101,110,116,78,111,100,101,46,105,110,115,101,114,116,66, +101,102,111,114,101,60,105,110,112,117,116,32,116,121,112,101,61,34,104,105,100, +100,101,110,34,32,110,97,106,115,34,32,116,121,112,101,61,34,116,101,120,116,47, +106,97,118,97,115,99,114,105,40,100,111,99,117,109,101,110,116,41,46,114,101,97, +100,121,40,102,117,110,99,116,105,115,99,114,105,112,116,32,116,121,112,101,61, +34,116,101,120,116,47,106,97,118,97,115,105,109,97,103,101,34,32,99,111,110,116, +101,110,116,61,34,104,116,116,112,58,47,47,85,65,45,67,111,109,112,97,116,105,98 +,108,101,34,32,99,111,110,116,101,110,116,61,116,109,108,59,32,99,104,97,114,115 +,101,116,61,117,116,102,45,56,34,32,47,62,10,108,105,110,107,32,114,101,108,61, +34,115,104,111,114,116,99,117,116,32,105,99,111,110,60,108,105,110,107,32,114, +101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,60,47,115,99,114,105 +,112,116,62,10,60,115,99,114,105,112,116,32,116,121,112,101,61,61,32,100,111,99, +117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,60,97,32,116 +,97,114,103,101,116,61,34,95,98,108,97,110,107,34,32,104,114,101,102,61,32,100, +111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,105, +110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101,61 +,97,46,116,121,112,101,32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114, +105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,100,101,110,34,32,110, +97,109,101,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,102,45,56, +34,32,47,62,100,116,100,34,62,10,60,104,116,109,108,32,120,109,108,110,115,61,34 +,104,116,116,112,45,47,47,87,51,67,47,47,68,84,68,32,72,84,77,76,32,52,46,48,49, +32,84,101,110,116,115,66,121,84,97,103,78,97,109,101,40,39,115,99,114,105,112, +116,39,41,105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,100,101,110, +34,32,110,97,109,60,115,99,114,105,112,116,32,116,121,112,101,61,34,116,101,120, +116,47,106,97,118,97,115,34,32,115,116,121,108,101,61,34,100,105,115,112,108,97, +121,58,110,111,110,101,59,34,62,100,111,99,117,109,101,110,116,46,103,101,116,69 +,108,101,109,101,110,116,66,121,73,100,40,61,100,111,99,117,109,101,110,116,46, +99,114,101,97,116,101,69,108,101,109,101,110,116,40,39,32,116,121,112,101,61,39, +116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,39,105,110,112,117,116, +32,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101,61,34,100,46,103, +101,116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,115,110 +,105,99,97,108,34,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119,119,119, +46,67,47,47,68,84,68,32,72,84,77,76,32,52,46,48,49,32,84,114,97,110,115,105,116, +60,115,116,121,108,101,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34 +,62,10,10,60,115,116,121,108,101,32,116,121,112,101,61,34,116,101,120,116,47,99, +115,115,34,62,105,111,110,97,108,46,100,116,100,34,62,10,60,104,116,109,108,32, +120,109,108,110,115,61,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110, +116,101,110,116,45,84,121,112,101,100,105,110,103,61,34,48,34,32,99,101,108,108, +115,112,97,99,105,110,103,61,34,48,34,104,116,109,108,59,32,99,104,97,114,115, +101,116,61,117,116,102,45,56,34,32,47,62,10,32,115,116,121,108,101,61,34,100,105 +,115,112,108,97,121,58,110,111,110,101,59,34,62,60,60,108,105,62,60,97,32,104, +114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,32,116,121,112,101,61, +39,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,39,62,208,180,208,181 +,209,143,209,130,208,181,208,187,209,140,208,189,208,190,209,129,209,130,208,184 +,209,129,208,190,208,190,209,130,208,178,208,181,209,130,209,129,209,130,208,178 +,208,184,208,184,208,191,209,128,208,190,208,184,208,183,208,178,208,190,208,180 +,209,129,209,130,208,178,208,176,208,177,208,181,208,183,208,190,208,191,208,176 +,209,129,208,189,208,190,209,129,209,130,208,184,224,164,170,224,165,129,224,164 +,184,224,165,141,224,164,164,224,164,191,224,164,149,224,164,190,224,164,149,224 +,164,190,224,164,130,224,164,151,224,165,141,224,164,176,224,165,135,224,164,184 +,224,164,137,224,164,168,224,165,141,224,164,185,224,165,139,224,164,130,224,164 +,168,224,165,135,224,164,181,224,164,191,224,164,167,224,164,190,224,164,168,224 +,164,184,224,164,173,224,164,190,224,164,171,224,164,191,224,164,149,224,165,141 +,224,164,184,224,164,191,224,164,130,224,164,151,224,164,184,224,165,129,224,164 +,176,224,164,149,224,165,141,224,164,183,224,164,191,224,164,164,224,164,149,224 +,165,137,224,164,170,224,165,128,224,164,176,224,164,190,224,164,135,224,164,159 +,224,164,181,224,164,191,224,164,156,224,165,141,224,164,158,224,164,190,224,164 +,170,224,164,168,224,164,149,224,164,190,224,164,176,224,165,141,224,164,176,224 +,164,181,224,164,190,224,164,136,224,164,184,224,164,149,224,165,141,224,164,176 +,224,164,191,224,164,175,224,164,164,224,164,190 +} +/* GENERATED CODE END */ +; +#endif /* !BROTLI_EXTERNAL_DICTIONARY_DATA */ + +#if !defined(BROTLI_EXTERNAL_DICTIONARY_DATA) +static const BrotliDictionary kBrotliDictionary = { +#else +static BrotliDictionary kBrotliDictionary = { +#endif + /* size_bits_by_length */ + { + 0, 0, 0, 0, 10, 10, 11, 11, + 10, 10, 10, 10, 10, 9, 9, 8, + 7, 7, 8, 7, 7, 6, 6, 5, + 5, 0, 0, 0, 0, 0, 0, 0 + }, + + /* offsets_by_length */ + { + 0, 0, 0, 0, 0, 4096, 9216, 21504, + 35840, 44032, 53248, 63488, 74752, 87040, 93696, 100864, + 104704, 106752, 108928, 113536, 115968, 118528, 119872, 121280, + 122016, 122784, 122784, 122784, 122784, 122784, 122784, 122784 + }, + + /* data_size == sizeof(kBrotliDictionaryData) */ + 122784, + + /* data */ +#if defined(BROTLI_EXTERNAL_DICTIONARY_DATA) + NULL +#else + kBrotliDictionaryData +#endif +}; + +const BrotliDictionary* duckdb_brotli::BrotliGetDictionary(void) { + return &kBrotliDictionary; +} + +void duckdb_brotli::BrotliSetDictionaryData(const uint8_t* data) { +#if defined(BROTLI_EXTERNAL_DICTIONARY_DATA) + if (!!data && !kBrotliDictionary.data) { + kBrotliDictionary.data = data; + } +#else + BROTLI_UNUSED(data); // Appease -Werror=unused-parameter +#endif +} + + diff --git a/third_party/brotli/common/dictionary.h b/third_party/brotli/common/dictionary.h new file mode 100644 index 00000000000..5afa7760443 --- /dev/null +++ b/third_party/brotli/common/dictionary.h @@ -0,0 +1,60 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Collection of static dictionary words. */ + +#ifndef BROTLI_COMMON_DICTIONARY_H_ +#define BROTLI_COMMON_DICTIONARY_H_ + +#include +#include + +namespace duckdb_brotli { + +typedef struct BrotliDictionary { + /** + * Number of bits to encode index of dictionary word in a bucket. + * + * Specification: Appendix A. Static Dictionary Data + * + * Words in a dictionary are bucketed by length. + * @c 0 means that there are no words of a given length. + * Dictionary consists of words with length of [4..24] bytes. + * Values at [0..3] and [25..31] indices should not be addressed. + */ + uint8_t size_bits_by_length[32]; + + /* assert(offset[i + 1] == offset[i] + (bits[i] ? (i << bits[i]) : 0)) */ + uint32_t offsets_by_length[32]; + + /* assert(data_size == offsets_by_length[31]) */ + size_t data_size; + + /* Data array is not bound, and should obey to size_bits_by_length values. + Specified size matches default (RFC 7932) dictionary. Its size is + defined by data_size */ + const uint8_t* data; +} BrotliDictionary; + +BROTLI_COMMON_API const BrotliDictionary* BrotliGetDictionary(void); + +/** + * Sets dictionary data. + * + * When dictionary data is already set / present, this method is no-op. + * + * Dictionary data MUST be provided before BrotliGetDictionary is invoked. + * This method is used ONLY in multi-client environment (e.g. C + Java), + * to reduce storage by sharing single dictionary between implementations. + */ +BROTLI_COMMON_API void BrotliSetDictionaryData(const uint8_t* data); + +#define BROTLI_MIN_DICTIONARY_WORD_LENGTH 4 +#define BROTLI_MAX_DICTIONARY_WORD_LENGTH 24 + +} + +#endif /* BROTLI_COMMON_DICTIONARY_H_ */ diff --git a/third_party/brotli/common/platform.cpp b/third_party/brotli/common/platform.cpp new file mode 100644 index 00000000000..fd09ac02563 --- /dev/null +++ b/third_party/brotli/common/platform.cpp @@ -0,0 +1,24 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include + +#include + +#include "brotli_platform.h" + + +/* Default brotli_alloc_func */ +void* duckdb_brotli::BrotliDefaultAllocFunc(void* opaque, size_t size) { + BROTLI_UNUSED(opaque); + return malloc(size); +} + +/* Default brotli_free_func */ +void duckdb_brotli::BrotliDefaultFreeFunc(void* opaque, void* address) { + BROTLI_UNUSED(opaque); + free(address); +} diff --git a/third_party/brotli/common/shared_dictionary.cpp b/third_party/brotli/common/shared_dictionary.cpp new file mode 100644 index 00000000000..3b951c98947 --- /dev/null +++ b/third_party/brotli/common/shared_dictionary.cpp @@ -0,0 +1,517 @@ +/* Copyright 2017 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Shared Dictionary definition and utilities. */ + +#include + +#include +#include /* malloc, free */ +#include + +#include "dictionary.h" +#include "brotli_platform.h" +#include "shared_dictionary_internal.h" + +using namespace duckdb_brotli; + +#if defined(BROTLI_EXPERIMENTAL) + +#define BROTLI_NUM_ENCODED_LENGTHS (SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH \ + - SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH + 1) + +/* Max allowed by spec */ +#define BROTLI_MAX_SIZE_BITS 15u + +/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */ +static BROTLI_BOOL ReadBool(const uint8_t* encoded, size_t size, size_t* pos, + BROTLI_BOOL* result) { + uint8_t value; + size_t position = *pos; + if (position >= size) return BROTLI_FALSE; /* past file end */ + value = encoded[position++]; + if (value > 1) return BROTLI_FALSE; /* invalid bool */ + *result = TO_BROTLI_BOOL(value); + *pos = position; + return BROTLI_TRUE; /* success */ +} + +/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */ +static BROTLI_BOOL ReadUint8(const uint8_t* encoded, size_t size, size_t* pos, + uint8_t* result) { + size_t position = *pos; + if (position + sizeof(uint8_t) > size) return BROTLI_FALSE; + *result = encoded[position++]; + *pos = position; + return BROTLI_TRUE; +} + +/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */ +static BROTLI_BOOL ReadUint16(const uint8_t* encoded, size_t size, size_t* pos, + uint16_t* result) { + size_t position = *pos; + if (position + sizeof(uint16_t) > size) return BROTLI_FALSE; + *result = BROTLI_UNALIGNED_LOAD16LE(&encoded[position]); + position += 2; + *pos = position; + return BROTLI_TRUE; +} + +/* Reads a varint into a uint32_t, and returns error if it's too large */ +/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */ +static BROTLI_BOOL ReadVarint32(const uint8_t* encoded, size_t size, + size_t* pos, uint32_t* result) { + int num = 0; + uint8_t byte; + *result = 0; + for (;;) { + if (*pos >= size) return BROTLI_FALSE; + byte = encoded[(*pos)++]; + if (num == 4 && byte > 15) return BROTLI_FALSE; + *result |= (uint32_t)(byte & 127) << (num * 7); + if (byte < 128) return BROTLI_TRUE; + num++; + } +} + +/* Returns the total length of word list. */ +static size_t BrotliSizeBitsToOffsets(const uint8_t* size_bits_by_length, + uint32_t* offsets_by_length) { + uint32_t pos = 0; + uint32_t i; + for (i = 0; i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) { + offsets_by_length[i] = pos; + if (size_bits_by_length[i] != 0) { + pos += i << size_bits_by_length[i]; + } + } + return pos; +} + +static BROTLI_BOOL ParseWordList(size_t size, const uint8_t* encoded, + size_t* pos, BrotliDictionary* out) { + size_t offset; + size_t i; + size_t position = *pos; + if (position + BROTLI_NUM_ENCODED_LENGTHS > size) { + return BROTLI_FALSE; + } + + memset(out->size_bits_by_length, 0, SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH); + memcpy(out->size_bits_by_length + SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH, + &encoded[position], BROTLI_NUM_ENCODED_LENGTHS); + for (i = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH; + i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) { + if (out->size_bits_by_length[i] > BROTLI_MAX_SIZE_BITS) { + return BROTLI_FALSE; + } + } + position += BROTLI_NUM_ENCODED_LENGTHS; + offset = BrotliSizeBitsToOffsets( + out->size_bits_by_length, out->offsets_by_length); + + out->data = &encoded[position]; + out->data_size = offset; + position += offset; + if (position > size) return BROTLI_FALSE; + *pos = position; + return BROTLI_TRUE; +} + +/* Computes the cutOffTransforms of a BrotliTransforms which already has the + transforms data correctly filled in. */ +static void ComputeCutoffTransforms(BrotliTransforms* transforms) { + uint32_t i; + for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) { + transforms->cutOffTransforms[i] = -1; + } + for (i = 0; i < transforms->num_transforms; i++) { + const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, i); + uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, i); + const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, i); + if (type <= BROTLI_TRANSFORM_OMIT_LAST_9 && *prefix == 0 && *suffix == 0 && + transforms->cutOffTransforms[type] == -1) { + transforms->cutOffTransforms[type] = (int16_t)i; + } + } +} + +static BROTLI_BOOL ParsePrefixSuffixTable(size_t size, const uint8_t* encoded, + size_t* pos, BrotliTransforms* out, uint16_t* out_table, + size_t* out_table_size) { + size_t position = *pos; + size_t offset = 0; + size_t stringlet_count = 0; /* NUM_PREFIX_SUFFIX */ + size_t data_length = 0; + + /* PREFIX_SUFFIX_LENGTH */ + if (!ReadUint16(encoded, size, &position, &out->prefix_suffix_size)) { + return BROTLI_FALSE; + } + data_length = out->prefix_suffix_size; + + /* Must at least have space for null terminator. */ + if (data_length < 1) return BROTLI_FALSE; + out->prefix_suffix = &encoded[position]; + if (position + data_length >= size) return BROTLI_FALSE; + while (BROTLI_TRUE) { + /* STRING_LENGTH */ + size_t stringlet_len = encoded[position + offset]; + out_table[stringlet_count] = (uint16_t)offset; + stringlet_count++; + offset++; + if (stringlet_len == 0) { + if (offset == data_length) { + break; + } else { + return BROTLI_FALSE; + } + } + if (stringlet_count > 255) return BROTLI_FALSE; + offset += stringlet_len; + if (offset >= data_length) return BROTLI_FALSE; + } + + position += data_length; + *pos = position; + *out_table_size = (uint16_t)stringlet_count; + return BROTLI_TRUE; +} + +static BROTLI_BOOL ParseTransformsList(size_t size, const uint8_t* encoded, + size_t* pos, BrotliTransforms* out, uint16_t* prefix_suffix_table, + size_t* prefix_suffix_count) { + uint32_t i; + BROTLI_BOOL has_params = BROTLI_FALSE; + BROTLI_BOOL prefix_suffix_ok = BROTLI_FALSE; + size_t position = *pos; + size_t stringlet_cnt = 0; + if (position >= size) return BROTLI_FALSE; + + prefix_suffix_ok = ParsePrefixSuffixTable( + size, encoded, &position, out, prefix_suffix_table, &stringlet_cnt); + if (!prefix_suffix_ok) return BROTLI_FALSE; + out->prefix_suffix_map = prefix_suffix_table; + *prefix_suffix_count = stringlet_cnt; + + out->num_transforms = encoded[position++]; + out->transforms = &encoded[position]; + position += (size_t)out->num_transforms * 3; + if (position > size) return BROTLI_FALSE; + /* Check for errors and read extra parameters. */ + for (i = 0; i < out->num_transforms; i++) { + uint8_t prefix_id = BROTLI_TRANSFORM_PREFIX_ID(out, i); + uint8_t type = BROTLI_TRANSFORM_TYPE(out, i); + uint8_t suffix_id = BROTLI_TRANSFORM_SUFFIX_ID(out, i); + if (prefix_id >= stringlet_cnt) return BROTLI_FALSE; + if (type >= BROTLI_NUM_TRANSFORM_TYPES) return BROTLI_FALSE; + if (suffix_id >= stringlet_cnt) return BROTLI_FALSE; + if (type == BROTLI_TRANSFORM_SHIFT_FIRST || + type == BROTLI_TRANSFORM_SHIFT_ALL) { + has_params = BROTLI_TRUE; + } + } + if (has_params) { + out->params = &encoded[position]; + position += (size_t)out->num_transforms * 2; + if (position > size) return BROTLI_FALSE; + for (i = 0; i < out->num_transforms; i++) { + uint8_t type = BROTLI_TRANSFORM_TYPE(out, i); + if (type != BROTLI_TRANSFORM_SHIFT_FIRST && + type != BROTLI_TRANSFORM_SHIFT_ALL) { + if (out->params[i * 2] != 0 || out->params[i * 2 + 1] != 0) { + return BROTLI_FALSE; + } + } + } + } else { + out->params = NULL; + } + ComputeCutoffTransforms(out); + *pos = position; + return BROTLI_TRUE; +} + +static BROTLI_BOOL DryParseDictionary(const uint8_t* encoded, + size_t size, uint32_t* num_prefix, BROTLI_BOOL* is_custom_static_dict) { + size_t pos = 0; + uint32_t chunk_size = 0; + uint8_t num_word_lists; + uint8_t num_transform_lists; + *is_custom_static_dict = BROTLI_FALSE; + *num_prefix = 0; + + /* Skip magic header bytes. */ + pos += 2; + + /* LZ77_DICTIONARY_LENGTH */ + if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE; + if (chunk_size != 0) { + /* This limitation is not specified but the 32-bit Brotli decoder for now */ + if (chunk_size > 1073741823) return BROTLI_FALSE; + *num_prefix = 1; + if (pos + chunk_size > size) return BROTLI_FALSE; + pos += chunk_size; + } + + if (!ReadUint8(encoded, size, &pos, &num_word_lists)) { + return BROTLI_FALSE; + } + if (!ReadUint8(encoded, size, &pos, &num_transform_lists)) { + return BROTLI_FALSE; + } + + if (num_word_lists > 0 || num_transform_lists > 0) { + *is_custom_static_dict = BROTLI_TRUE; + } + + return BROTLI_TRUE; +} + +static BROTLI_BOOL ParseDictionary(const uint8_t* encoded, size_t size, + BrotliSharedDictionary* dict) { + uint32_t i; + size_t pos = 0; + uint32_t chunk_size = 0; + size_t total_prefix_suffix_count = 0; + size_t trasform_list_start[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; + uint16_t temporary_prefix_suffix_table[256]; + + /* Skip magic header bytes. */ + pos += 2; + + /* LZ77_DICTIONARY_LENGTH */ + if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE; + if (chunk_size != 0) { + if (pos + chunk_size > size) return BROTLI_FALSE; + dict->prefix_size[dict->num_prefix] = chunk_size; + dict->prefix[dict->num_prefix] = &encoded[pos]; + dict->num_prefix++; + /* LZ77_DICTIONARY_LENGTH bytes. */ + pos += chunk_size; + } + + /* NUM_WORD_LISTS */ + if (!ReadUint8(encoded, size, &pos, &dict->num_word_lists)) { + return BROTLI_FALSE; + } + if (dict->num_word_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) { + return BROTLI_FALSE; + } + + if (dict->num_word_lists != 0) { + dict->words_instances = (BrotliDictionary*)dict->alloc_func( + dict->memory_manager_opaque, + dict->num_word_lists * sizeof(*dict->words_instances)); + if (!dict->words_instances) return BROTLI_FALSE; /* OOM */ + } + for (i = 0; i < dict->num_word_lists; i++) { + if (!ParseWordList(size, encoded, &pos, &dict->words_instances[i])) { + return BROTLI_FALSE; + } + } + + /* NUM_TRANSFORM_LISTS */ + if (!ReadUint8(encoded, size, &pos, &dict->num_transform_lists)) { + return BROTLI_FALSE; + } + if (dict->num_transform_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) { + return BROTLI_FALSE; + } + + if (dict->num_transform_lists != 0) { + dict->transforms_instances = (BrotliTransforms*)dict->alloc_func( + dict->memory_manager_opaque, + dict->num_transform_lists * sizeof(*dict->transforms_instances)); + if (!dict->transforms_instances) return BROTLI_FALSE; /* OOM */ + } + for (i = 0; i < dict->num_transform_lists; i++) { + BROTLI_BOOL ok = BROTLI_FALSE; + size_t prefix_suffix_count = 0; + trasform_list_start[i] = pos; + dict->transforms_instances[i].prefix_suffix_map = + temporary_prefix_suffix_table; + ok = ParseTransformsList( + size, encoded, &pos, &dict->transforms_instances[i], + temporary_prefix_suffix_table, &prefix_suffix_count); + if (!ok) return BROTLI_FALSE; + total_prefix_suffix_count += prefix_suffix_count; + } + if (total_prefix_suffix_count != 0) { + dict->prefix_suffix_maps = (uint16_t*)dict->alloc_func( + dict->memory_manager_opaque, + total_prefix_suffix_count * sizeof(*dict->prefix_suffix_maps)); + if (!dict->prefix_suffix_maps) return BROTLI_FALSE; /* OOM */ + } + total_prefix_suffix_count = 0; + for (i = 0; i < dict->num_transform_lists; i++) { + size_t prefix_suffix_count = 0; + size_t position = trasform_list_start[i]; + uint16_t* prefix_suffix_map = + &dict->prefix_suffix_maps[total_prefix_suffix_count]; + BROTLI_BOOL ok = ParsePrefixSuffixTable( + size, encoded, &position, &dict->transforms_instances[i], + prefix_suffix_map, &prefix_suffix_count); + if (!ok) return BROTLI_FALSE; + dict->transforms_instances[i].prefix_suffix_map = prefix_suffix_map; + total_prefix_suffix_count += prefix_suffix_count; + } + + if (dict->num_word_lists != 0 || dict->num_transform_lists != 0) { + if (!ReadUint8(encoded, size, &pos, &dict->num_dictionaries)) { + return BROTLI_FALSE; + } + if (dict->num_dictionaries == 0 || + dict->num_dictionaries > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) { + return BROTLI_FALSE; + } + for (i = 0; i < dict->num_dictionaries; i++) { + uint8_t words_index; + uint8_t transforms_index; + if (!ReadUint8(encoded, size, &pos, &words_index)) { + return BROTLI_FALSE; + } + if (words_index > dict->num_word_lists) return BROTLI_FALSE; + if (!ReadUint8(encoded, size, &pos, &transforms_index)) { + return BROTLI_FALSE; + } + if (transforms_index > dict->num_transform_lists) return BROTLI_FALSE; + dict->words[i] = words_index == dict->num_word_lists ? + BrotliGetDictionary() : &dict->words_instances[words_index]; + dict->transforms[i] = transforms_index == dict->num_transform_lists ? + BrotliGetTransforms(): &dict->transforms_instances[transforms_index]; + } + /* CONTEXT_ENABLED */ + if (!ReadBool(encoded, size, &pos, &dict->context_based)) { + return BROTLI_FALSE; + } + + /* CONTEXT_MAP */ + if (dict->context_based) { + for (i = 0; i < SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS; i++) { + if (!ReadUint8(encoded, size, &pos, &dict->context_map[i])) { + return BROTLI_FALSE; + } + if (dict->context_map[i] >= dict->num_dictionaries) { + return BROTLI_FALSE; + } + } + } + } else { + dict->context_based = BROTLI_FALSE; + dict->num_dictionaries = 1; + dict->words[0] = BrotliGetDictionary(); + dict->transforms[0] = BrotliGetTransforms(); + } + + return BROTLI_TRUE; +} + +/* Decodes shared dictionary and verifies correctness. + Returns BROTLI_TRUE if dictionary is valid, BROTLI_FALSE otherwise. + The BrotliSharedDictionary must already have been initialized. If the + BrotliSharedDictionary already contains data, compound dictionaries + will be appended, but an error will be returned if it already has + custom words or transforms. + TODO(lode): link to RFC for shared brotli once published. */ +static BROTLI_BOOL DecodeSharedDictionary( + const uint8_t* encoded, size_t size, BrotliSharedDictionary* dict) { + uint32_t num_prefix = 0; + BROTLI_BOOL is_custom_static_dict = BROTLI_FALSE; + BROTLI_BOOL has_custom_static_dict = + dict->num_word_lists > 0 || dict->num_transform_lists > 0; + + /* Check magic header bytes. */ + if (size < 2) return BROTLI_FALSE; + if (encoded[0] != 0x91 || encoded[1] != 0) return BROTLI_FALSE; + + if (!DryParseDictionary(encoded, size, &num_prefix, &is_custom_static_dict)) { + return BROTLI_FALSE; + } + + if (num_prefix + dict->num_prefix > SHARED_BROTLI_MAX_COMPOUND_DICTS) { + return BROTLI_FALSE; + } + + /* Cannot combine different static dictionaries, only prefix dictionaries */ + if (has_custom_static_dict && is_custom_static_dict) return BROTLI_FALSE; + + return ParseDictionary(encoded, size, dict); +} + +#endif /* BROTLI_EXPERIMENTAL */ + +void duckdb_brotli::BrotliSharedDictionaryDestroyInstance( + BrotliSharedDictionary* dict) { + if (!dict) { + return; + } else { + brotli_free_func free_func = dict->free_func; + void* opaque = dict->memory_manager_opaque; + /* Cleanup. */ + free_func(opaque, dict->words_instances); + free_func(opaque, dict->transforms_instances); + free_func(opaque, dict->prefix_suffix_maps); + /* Self-destruction. */ + free_func(opaque, dict); + } +} + +BROTLI_BOOL duckdb_brotli::BrotliSharedDictionaryAttach( + BrotliSharedDictionary* dict, BrotliSharedDictionaryType type, + size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) { + if (!dict) { + return BROTLI_FALSE; + } +#if defined(BROTLI_EXPERIMENTAL) + if (type == BROTLI_SHARED_DICTIONARY_SERIALIZED) { + return DecodeSharedDictionary(data, data_size, dict); + } +#endif /* BROTLI_EXPERIMENTAL */ + if (type == BROTLI_SHARED_DICTIONARY_RAW) { + if (dict->num_prefix >= SHARED_BROTLI_MAX_COMPOUND_DICTS) { + return BROTLI_FALSE; + } + dict->prefix_size[dict->num_prefix] = data_size; + dict->prefix[dict->num_prefix] = data; + dict->num_prefix++; + return BROTLI_TRUE; + } + return BROTLI_FALSE; +} + +BrotliSharedDictionary* duckdb_brotli::BrotliSharedDictionaryCreateInstance( + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { + BrotliSharedDictionary* dict = 0; + if (!alloc_func && !free_func) { + dict = (BrotliSharedDictionary*)malloc(sizeof(BrotliSharedDictionary)); + } else if (alloc_func && free_func) { + dict = (BrotliSharedDictionary*)alloc_func( + opaque, sizeof(BrotliSharedDictionary)); + } + if (dict == 0) { + return 0; + } + + /* TODO(eustas): explicitly initialize all the fields? */ + memset(dict, 0, sizeof(BrotliSharedDictionary)); + + dict->context_based = BROTLI_FALSE; + dict->num_dictionaries = 1; + dict->num_word_lists = 0; + dict->num_transform_lists = 0; + + dict->words[0] = BrotliGetDictionary(); + dict->transforms[0] = BrotliGetTransforms(); + + dict->alloc_func = alloc_func ? alloc_func : duckdb_brotli::BrotliDefaultAllocFunc; + dict->free_func = free_func ? free_func : duckdb_brotli::BrotliDefaultFreeFunc; + dict->memory_manager_opaque = opaque; + + return dict; +} + + diff --git a/third_party/brotli/common/shared_dictionary_internal.h b/third_party/brotli/common/shared_dictionary_internal.h new file mode 100644 index 00000000000..1f2d85b38c1 --- /dev/null +++ b/third_party/brotli/common/shared_dictionary_internal.h @@ -0,0 +1,71 @@ +/* Copyright 2017 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* (Transparent) Shared Dictionary definition. */ + +#ifndef BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_ +#define BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_ + +#include +#include + +#include "dictionary.h" +#include "transform.h" + +namespace duckdb_brotli { + +struct BrotliSharedDictionaryStruct { + /* LZ77 prefixes (compound dictionary). */ + uint32_t num_prefix; /* max SHARED_BROTLI_MAX_COMPOUND_DICTS */ + size_t prefix_size[SHARED_BROTLI_MAX_COMPOUND_DICTS]; + const uint8_t* prefix[SHARED_BROTLI_MAX_COMPOUND_DICTS]; + + /* If set, the context map is used to select word and transform list from 64 + contexts, if not set, the context map is not used and only words[0] and + transforms[0] are to be used. */ + BROTLI_BOOL context_based; + + uint8_t context_map[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; + + /* Amount of word_list+transform_list combinations. */ + uint8_t num_dictionaries; + + /* Must use num_dictionaries values. */ + const BrotliDictionary* words[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; + + /* Must use num_dictionaries values. */ + const BrotliTransforms* transforms[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; + + /* Amount of custom word lists. May be 0 if only Brotli's built-in is used */ + uint8_t num_word_lists; + + /* Contents of the custom words lists. Must be NULL if num_word_lists is 0. */ + BrotliDictionary* words_instances; + + /* Amount of custom transform lists. May be 0 if only Brotli's built-in is + used */ + uint8_t num_transform_lists; + + /* Contents of the custom transform lists. Must be NULL if num_transform_lists + is 0. */ + BrotliTransforms* transforms_instances; + + /* Concatenated prefix_suffix_maps of the custom transform lists. Must be NULL + if num_transform_lists is 0. */ + uint16_t* prefix_suffix_maps; + + /* Memory management */ + brotli_alloc_func alloc_func; + brotli_free_func free_func; + void* memory_manager_opaque; +}; + +typedef struct BrotliSharedDictionaryStruct BrotliSharedDictionaryInternal; +#define BrotliSharedDictionary BrotliSharedDictionaryInternal + +} + +#endif /* BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_ */ diff --git a/third_party/brotli/common/transform.cpp b/third_party/brotli/common/transform.cpp new file mode 100644 index 00000000000..9ab4ca260c4 --- /dev/null +++ b/third_party/brotli/common/transform.cpp @@ -0,0 +1,287 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include "transform.h" + +using namespace duckdb_brotli; + +/* RFC 7932 transforms string data */ +static const char kPrefixSuffix[217] = + "\1 \2, \10 of the \4 of \2s \1.\5 and \4 " +/* 0x _0 _2 __5 _E _3 _6 _8 _E */ + "in \1\"\4 to \2\">\1\n\2. \1]\5 for \3 a \6 " +/* 2x _3_ _5 _A_ _D_ _F _2 _4 _A _E */ + "that \1\'\6 with \6 from \4 by \1(\6. T" +/* 4x _5_ _7 _E _5 _A _C */ + "he \4 on \4 as \4 is \4ing \2\n\t\1:\3ed " +/* 6x _3 _8 _D _2 _7_ _ _A _C */ + "\2=\"\4 at \3ly \1,\2=\'\5.com/\7. This \5" +/* 8x _0 _ _3 _8 _C _E _ _1 _7 _F */ + " not \3er \3al \4ful \4ive \5less \4es" +/* Ax _5 _9 _D _2 _7 _D */ + "t \4ize \2\xc2\xa0\4ous \5 the \2e "; /* \0 - implicit trailing zero. */ +/* Cx _2 _7___ ___ _A _F _5 _8 */ + +static const uint16_t kPrefixSuffixMap[50] = { + 0x00, 0x02, 0x05, 0x0E, 0x13, 0x16, 0x18, 0x1E, 0x23, 0x25, + 0x2A, 0x2D, 0x2F, 0x32, 0x34, 0x3A, 0x3E, 0x45, 0x47, 0x4E, + 0x55, 0x5A, 0x5C, 0x63, 0x68, 0x6D, 0x72, 0x77, 0x7A, 0x7C, + 0x80, 0x83, 0x88, 0x8C, 0x8E, 0x91, 0x97, 0x9F, 0xA5, 0xA9, + 0xAD, 0xB2, 0xB7, 0xBD, 0xC2, 0xC7, 0xCA, 0xCF, 0xD5, 0xD8 +}; + +/* RFC 7932 transforms */ +static const uint8_t kTransformsData[] = { + 49, BROTLI_TRANSFORM_IDENTITY, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 0, + 0, BROTLI_TRANSFORM_IDENTITY, 0, + 49, BROTLI_TRANSFORM_OMIT_FIRST_1, 49, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 0, + 49, BROTLI_TRANSFORM_IDENTITY, 47, + 0, BROTLI_TRANSFORM_IDENTITY, 49, + 4, BROTLI_TRANSFORM_IDENTITY, 0, + 49, BROTLI_TRANSFORM_IDENTITY, 3, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 6, + 49, BROTLI_TRANSFORM_OMIT_FIRST_2, 49, + 49, BROTLI_TRANSFORM_OMIT_LAST_1, 49, + 1, BROTLI_TRANSFORM_IDENTITY, 0, + 49, BROTLI_TRANSFORM_IDENTITY, 1, + 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 0, + 49, BROTLI_TRANSFORM_IDENTITY, 7, + 49, BROTLI_TRANSFORM_IDENTITY, 9, + 48, BROTLI_TRANSFORM_IDENTITY, 0, + 49, BROTLI_TRANSFORM_IDENTITY, 8, + 49, BROTLI_TRANSFORM_IDENTITY, 5, + 49, BROTLI_TRANSFORM_IDENTITY, 10, + 49, BROTLI_TRANSFORM_IDENTITY, 11, + 49, BROTLI_TRANSFORM_OMIT_LAST_3, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 13, + 49, BROTLI_TRANSFORM_IDENTITY, 14, + 49, BROTLI_TRANSFORM_OMIT_FIRST_3, 49, + 49, BROTLI_TRANSFORM_OMIT_LAST_2, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 15, + 49, BROTLI_TRANSFORM_IDENTITY, 16, + 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 12, + 5, BROTLI_TRANSFORM_IDENTITY, 49, + 0, BROTLI_TRANSFORM_IDENTITY, 1, + 49, BROTLI_TRANSFORM_OMIT_FIRST_4, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 18, + 49, BROTLI_TRANSFORM_IDENTITY, 17, + 49, BROTLI_TRANSFORM_IDENTITY, 19, + 49, BROTLI_TRANSFORM_IDENTITY, 20, + 49, BROTLI_TRANSFORM_OMIT_FIRST_5, 49, + 49, BROTLI_TRANSFORM_OMIT_FIRST_6, 49, + 47, BROTLI_TRANSFORM_IDENTITY, 49, + 49, BROTLI_TRANSFORM_OMIT_LAST_4, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 22, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 23, + 49, BROTLI_TRANSFORM_IDENTITY, 24, + 49, BROTLI_TRANSFORM_IDENTITY, 25, + 49, BROTLI_TRANSFORM_OMIT_LAST_7, 49, + 49, BROTLI_TRANSFORM_OMIT_LAST_1, 26, + 49, BROTLI_TRANSFORM_IDENTITY, 27, + 49, BROTLI_TRANSFORM_IDENTITY, 28, + 0, BROTLI_TRANSFORM_IDENTITY, 12, + 49, BROTLI_TRANSFORM_IDENTITY, 29, + 49, BROTLI_TRANSFORM_OMIT_FIRST_9, 49, + 49, BROTLI_TRANSFORM_OMIT_FIRST_7, 49, + 49, BROTLI_TRANSFORM_OMIT_LAST_6, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 21, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 1, + 49, BROTLI_TRANSFORM_OMIT_LAST_8, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 31, + 49, BROTLI_TRANSFORM_IDENTITY, 32, + 47, BROTLI_TRANSFORM_IDENTITY, 3, + 49, BROTLI_TRANSFORM_OMIT_LAST_5, 49, + 49, BROTLI_TRANSFORM_OMIT_LAST_9, 49, + 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 1, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 8, + 5, BROTLI_TRANSFORM_IDENTITY, 21, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 0, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 10, + 49, BROTLI_TRANSFORM_IDENTITY, 30, + 0, BROTLI_TRANSFORM_IDENTITY, 5, + 35, BROTLI_TRANSFORM_IDENTITY, 49, + 47, BROTLI_TRANSFORM_IDENTITY, 2, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 17, + 49, BROTLI_TRANSFORM_IDENTITY, 36, + 49, BROTLI_TRANSFORM_IDENTITY, 33, + 5, BROTLI_TRANSFORM_IDENTITY, 0, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 21, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 5, + 49, BROTLI_TRANSFORM_IDENTITY, 37, + 0, BROTLI_TRANSFORM_IDENTITY, 30, + 49, BROTLI_TRANSFORM_IDENTITY, 38, + 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 0, + 49, BROTLI_TRANSFORM_IDENTITY, 39, + 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 49, + 49, BROTLI_TRANSFORM_IDENTITY, 34, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 8, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 12, + 0, BROTLI_TRANSFORM_IDENTITY, 21, + 49, BROTLI_TRANSFORM_IDENTITY, 40, + 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 12, + 49, BROTLI_TRANSFORM_IDENTITY, 41, + 49, BROTLI_TRANSFORM_IDENTITY, 42, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 17, + 49, BROTLI_TRANSFORM_IDENTITY, 43, + 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 5, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 10, + 0, BROTLI_TRANSFORM_IDENTITY, 34, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 33, + 49, BROTLI_TRANSFORM_IDENTITY, 44, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 5, + 45, BROTLI_TRANSFORM_IDENTITY, 49, + 0, BROTLI_TRANSFORM_IDENTITY, 33, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 30, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 30, + 49, BROTLI_TRANSFORM_IDENTITY, 46, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 1, + 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 34, + 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 33, + 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 30, + 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 1, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 33, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 21, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 12, + 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 5, + 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 34, + 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 12, + 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 30, + 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 34, + 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 34, +}; + +static const BrotliTransforms kBrotliTransforms = { + sizeof(kPrefixSuffix), + (const uint8_t*)kPrefixSuffix, + kPrefixSuffixMap, + sizeof(kTransformsData) / (3 * sizeof(kTransformsData[0])), + kTransformsData, + NULL, /* no extra parameters */ + {0, 12, 27, 23, 42, 63, 56, 48, 59, 64} +}; + +const BrotliTransforms* duckdb_brotli::BrotliGetTransforms(void) { + return &kBrotliTransforms; +} + +static int ToUpperCase(uint8_t* p) { + if (p[0] < 0xC0) { + if (p[0] >= 'a' && p[0] <= 'z') { + p[0] ^= 32; + } + return 1; + } + /* An overly simplified uppercasing model for UTF-8. */ + if (p[0] < 0xE0) { + p[1] ^= 32; + return 2; + } + /* An arbitrary transform for three byte characters. */ + p[2] ^= 5; + return 3; +} + +static int Shift(uint8_t* word, int word_len, uint16_t parameter) { + /* Limited sign extension: scalar < (1 << 24). */ + uint32_t scalar = + (parameter & 0x7FFFu) + (0x1000000u - (parameter & 0x8000u)); + if (word[0] < 0x80) { + /* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */ + scalar += (uint32_t)word[0]; + word[0] = (uint8_t)(scalar & 0x7Fu); + return 1; + } else if (word[0] < 0xC0) { + /* Continuation / 10AAAAAA. */ + return 1; + } else if (word[0] < 0xE0) { + /* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */ + if (word_len < 2) return 1; + scalar += (uint32_t)((word[1] & 0x3Fu) | ((word[0] & 0x1Fu) << 6u)); + word[0] = (uint8_t)(0xC0 | ((scalar >> 6u) & 0x1F)); + word[1] = (uint8_t)((word[1] & 0xC0) | (scalar & 0x3F)); + return 2; + } else if (word[0] < 0xF0) { + /* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */ + if (word_len < 3) return word_len; + scalar += (uint32_t)((word[2] & 0x3Fu) | ((word[1] & 0x3Fu) << 6u) | + ((word[0] & 0x0Fu) << 12u)); + word[0] = (uint8_t)(0xE0 | ((scalar >> 12u) & 0x0F)); + word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 6u) & 0x3F)); + word[2] = (uint8_t)((word[2] & 0xC0) | (scalar & 0x3F)); + return 3; + } else if (word[0] < 0xF8) { + /* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */ + if (word_len < 4) return word_len; + scalar += (uint32_t)((word[3] & 0x3Fu) | ((word[2] & 0x3Fu) << 6u) | + ((word[1] & 0x3Fu) << 12u) | ((word[0] & 0x07u) << 18u)); + word[0] = (uint8_t)(0xF0 | ((scalar >> 18u) & 0x07)); + word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 12u) & 0x3F)); + word[2] = (uint8_t)((word[2] & 0xC0) | ((scalar >> 6u) & 0x3F)); + word[3] = (uint8_t)((word[3] & 0xC0) | (scalar & 0x3F)); + return 4; + } + return 1; +} + +int duckdb_brotli::BrotliTransformDictionaryWord(uint8_t* dst, const uint8_t* word, int len, + const BrotliTransforms* transforms, int transform_idx) { + int idx = 0; + const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, transform_idx); + uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, transform_idx); + const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, transform_idx); + { + int prefix_len = *prefix++; + while (prefix_len--) { dst[idx++] = *prefix++; } + } + { + const int t = type; + int i = 0; + if (t <= BROTLI_TRANSFORM_OMIT_LAST_9) { + len -= t; + } else if (t >= BROTLI_TRANSFORM_OMIT_FIRST_1 + && t <= BROTLI_TRANSFORM_OMIT_FIRST_9) { + int skip = t - (BROTLI_TRANSFORM_OMIT_FIRST_1 - 1); + word += skip; + len -= skip; + } + while (i < len) { dst[idx++] = word[i++]; } + if (t == BROTLI_TRANSFORM_UPPERCASE_FIRST) { + ToUpperCase(&dst[idx - len]); + } else if (t == BROTLI_TRANSFORM_UPPERCASE_ALL) { + uint8_t* uppercase = &dst[idx - len]; + while (len > 0) { + int step = ToUpperCase(uppercase); + uppercase += step; + len -= step; + } + } else if (t == BROTLI_TRANSFORM_SHIFT_FIRST) { + uint16_t param = (uint16_t)(transforms->params[transform_idx * 2] + + (transforms->params[transform_idx * 2 + 1] << 8u)); + Shift(&dst[idx - len], len, param); + } else if (t == BROTLI_TRANSFORM_SHIFT_ALL) { + uint16_t param = (uint16_t)(transforms->params[transform_idx * 2] + + (transforms->params[transform_idx * 2 + 1] << 8u)); + uint8_t* shift = &dst[idx - len]; + while (len > 0) { + int step = Shift(shift, len, param); + shift += step; + len -= step; + } + } + } + { + int suffix_len = *suffix++; + while (suffix_len--) { dst[idx++] = *suffix++; } + return idx; + } +} + + diff --git a/third_party/brotli/common/transform.h b/third_party/brotli/common/transform.h new file mode 100644 index 00000000000..3a5a42f9ace --- /dev/null +++ b/third_party/brotli/common/transform.h @@ -0,0 +1,77 @@ +/* transforms is a part of ABI, but not API. + + It means that there are some functions that are supposed to be in "common" + library, but header itself is not placed into include/brotli. This way, + aforementioned functions will be available only to brotli internals. + */ + +#ifndef BROTLI_COMMON_TRANSFORM_H_ +#define BROTLI_COMMON_TRANSFORM_H_ + +#include +#include + +namespace duckdb_brotli { + +enum BrotliWordTransformType { + BROTLI_TRANSFORM_IDENTITY = 0, + BROTLI_TRANSFORM_OMIT_LAST_1 = 1, + BROTLI_TRANSFORM_OMIT_LAST_2 = 2, + BROTLI_TRANSFORM_OMIT_LAST_3 = 3, + BROTLI_TRANSFORM_OMIT_LAST_4 = 4, + BROTLI_TRANSFORM_OMIT_LAST_5 = 5, + BROTLI_TRANSFORM_OMIT_LAST_6 = 6, + BROTLI_TRANSFORM_OMIT_LAST_7 = 7, + BROTLI_TRANSFORM_OMIT_LAST_8 = 8, + BROTLI_TRANSFORM_OMIT_LAST_9 = 9, + BROTLI_TRANSFORM_UPPERCASE_FIRST = 10, + BROTLI_TRANSFORM_UPPERCASE_ALL = 11, + BROTLI_TRANSFORM_OMIT_FIRST_1 = 12, + BROTLI_TRANSFORM_OMIT_FIRST_2 = 13, + BROTLI_TRANSFORM_OMIT_FIRST_3 = 14, + BROTLI_TRANSFORM_OMIT_FIRST_4 = 15, + BROTLI_TRANSFORM_OMIT_FIRST_5 = 16, + BROTLI_TRANSFORM_OMIT_FIRST_6 = 17, + BROTLI_TRANSFORM_OMIT_FIRST_7 = 18, + BROTLI_TRANSFORM_OMIT_FIRST_8 = 19, + BROTLI_TRANSFORM_OMIT_FIRST_9 = 20, + BROTLI_TRANSFORM_SHIFT_FIRST = 21, + BROTLI_TRANSFORM_SHIFT_ALL = 22, + BROTLI_NUM_TRANSFORM_TYPES /* Counts transforms, not a transform itself. */ +}; + +#define BROTLI_TRANSFORMS_MAX_CUT_OFF BROTLI_TRANSFORM_OMIT_LAST_9 + +typedef struct BrotliTransforms { + uint16_t prefix_suffix_size; + /* Last character must be null, so prefix_suffix_size must be at least 1. */ + const uint8_t *prefix_suffix; + const uint16_t *prefix_suffix_map; + uint32_t num_transforms; + /* Each entry is a [prefix_id, transform, suffix_id] triplet. */ + const uint8_t *transforms; + /* Shift for BROTLI_TRANSFORM_SHIFT_FIRST and BROTLI_TRANSFORM_SHIFT_ALL, + must be NULL if and only if no such transforms are present. */ + const uint8_t *params; + /* Indices of transforms like ["", BROTLI_TRANSFORM_OMIT_LAST_#, ""]. + 0-th element corresponds to ["", BROTLI_TRANSFORM_IDENTITY, ""]. + -1, if cut-off transform does not exist. */ + int16_t cutOffTransforms[BROTLI_TRANSFORMS_MAX_CUT_OFF + 1]; +} BrotliTransforms; + +/* T is BrotliTransforms*; result is uint8_t. */ +#define BROTLI_TRANSFORM_PREFIX_ID(T, I) ((T)->transforms[((I) * 3) + 0]) +#define BROTLI_TRANSFORM_TYPE(T, I) ((T)->transforms[((I) * 3) + 1]) +#define BROTLI_TRANSFORM_SUFFIX_ID(T, I) ((T)->transforms[((I) * 3) + 2]) + +/* T is BrotliTransforms*; result is const uint8_t*. */ +#define BROTLI_TRANSFORM_PREFIX(T, I) (&(T)->prefix_suffix[(T)->prefix_suffix_map[BROTLI_TRANSFORM_PREFIX_ID(T, I)]]) +#define BROTLI_TRANSFORM_SUFFIX(T, I) (&(T)->prefix_suffix[(T)->prefix_suffix_map[BROTLI_TRANSFORM_SUFFIX_ID(T, I)]]) + +BROTLI_COMMON_API const BrotliTransforms *BrotliGetTransforms(void); + +BROTLI_COMMON_API int BrotliTransformDictionaryWord(uint8_t *dst, const uint8_t *word, int len, + const BrotliTransforms *transforms, int transform_idx); +} + +#endif /* BROTLI_COMMON_TRANSFORM_H_ */ diff --git a/third_party/brotli/common/version.h b/third_party/brotli/common/version.h new file mode 100644 index 00000000000..8098040f646 --- /dev/null +++ b/third_party/brotli/common/version.h @@ -0,0 +1,51 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Version definition. */ + +#ifndef BROTLI_COMMON_VERSION_H_ +#define BROTLI_COMMON_VERSION_H_ + +/* Compose 3 components into a single number. In a hexadecimal representation + B and C components occupy exactly 3 digits. */ +#define BROTLI_MAKE_HEX_VERSION(A, B, C) ((A << 24) | (B << 12) | C) + +/* Those macros should only be used when library is compiled together with + the client. If library is dynamically linked, use BrotliDecoderVersion and + BrotliEncoderVersion methods. */ + +#define BROTLI_VERSION_MAJOR 1 +#define BROTLI_VERSION_MINOR 1 +#define BROTLI_VERSION_PATCH 0 + +#define BROTLI_VERSION BROTLI_MAKE_HEX_VERSION( \ + BROTLI_VERSION_MAJOR, BROTLI_VERSION_MINOR, BROTLI_VERSION_PATCH) + +/* This macro is used by build system to produce Libtool-friendly soname. See + https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html + Version evolution rules: + - interfaces added (or change is compatible) -> current+1:0:age+1 + - interfaces removed (or changed is incompatible) -> current+1:0:0 + - interfaces not changed -> current:revision+1:age + */ + +#define BROTLI_ABI_CURRENT 2 +#define BROTLI_ABI_REVISION 0 +#define BROTLI_ABI_AGE 1 + +#if BROTLI_VERSION_MAJOR != (BROTLI_ABI_CURRENT - BROTLI_ABI_AGE) +#error ABI/API version inconsistency +#endif + +#if BROTLI_VERSION_MINOR != BROTLI_ABI_AGE +#error ABI/API version inconsistency +#endif + +#if BROTLI_VERSION_PATCH != BROTLI_ABI_REVISION +#error ABI/API version inconsistency +#endif + +#endif /* BROTLI_COMMON_VERSION_H_ */ diff --git a/third_party/brotli/dec/bit_reader.cpp b/third_party/brotli/dec/bit_reader.cpp new file mode 100644 index 00000000000..f5fbd0a1da5 --- /dev/null +++ b/third_party/brotli/dec/bit_reader.cpp @@ -0,0 +1,74 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Bit reading helpers */ + +#include "bit_reader.h" + +#include + +#include "../common/brotli_platform.h" + +using namespace duckdb_brotli; + +const brotli_reg_t duckdb_brotli::kBrotliBitMask[33] = { 0x00000000, + 0x00000001, 0x00000003, 0x00000007, 0x0000000F, + 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, + 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, + 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, + 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, + 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, + 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, + 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF +}; + +void duckdb_brotli::BrotliInitBitReader(BrotliBitReader* const br) { + br->val_ = 0; + br->bit_pos_ = 0; +} + +BROTLI_BOOL duckdb_brotli::BrotliWarmupBitReader(BrotliBitReader* const br) { + size_t aligned_read_mask = (sizeof(br->val_) >> 1) - 1; + /* Fixing alignment after unaligned BrotliFillWindow would result accumulator + overflow. If unalignment is caused by BrotliSafeReadBits, then there is + enough space in accumulator to fix alignment. */ + if (BROTLI_UNALIGNED_READ_FAST) { + aligned_read_mask = 0; + } + if (BrotliGetAvailableBits(br) == 0) { + br->val_ = 0; + if (!BrotliPullByte(br)) { + return BROTLI_FALSE; + } + } + + while ((((size_t)br->next_in) & aligned_read_mask) != 0) { + if (!BrotliPullByte(br)) { + /* If we consumed all the input, we don't care about the alignment. */ + return BROTLI_TRUE; + } + } + return BROTLI_TRUE; +} + +BROTLI_BOOL duckdb_brotli::BrotliSafeReadBits32Slow(BrotliBitReader* const br, + brotli_reg_t n_bits, brotli_reg_t* val) { + brotli_reg_t low_val; + brotli_reg_t high_val; + BrotliBitReaderState memento; + BROTLI_DCHECK(n_bits <= 32); + BROTLI_DCHECK(n_bits > 24); + BrotliBitReaderSaveState(br, &memento); + if (!BrotliSafeReadBits(br, 16, &low_val) || + !BrotliSafeReadBits(br, n_bits - 16, &high_val)) { + BrotliBitReaderRestoreState(br, &memento); + return BROTLI_FALSE; + } + *val = low_val | (high_val << 16); + return BROTLI_TRUE; +} + + diff --git a/third_party/brotli/dec/bit_reader.h b/third_party/brotli/dec/bit_reader.h new file mode 100644 index 00000000000..d97de61eaf2 --- /dev/null +++ b/third_party/brotli/dec/bit_reader.h @@ -0,0 +1,419 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Bit reading helpers */ + +#ifndef BROTLI_DEC_BIT_READER_H_ +#define BROTLI_DEC_BIT_READER_H_ + +#include /* memcpy */ + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" + +namespace duckdb_brotli { + +#define BROTLI_SHORT_FILL_BIT_WINDOW_READ (sizeof(brotli_reg_t) >> 1) + +/* 162 bits + 7 bytes */ +#define BROTLI_FAST_INPUT_SLACK 28 + +BROTLI_INTERNAL extern const brotli_reg_t kBrotliBitMask[33]; + +static BROTLI_INLINE brotli_reg_t BitMask(brotli_reg_t n) { + if (BROTLI_IS_CONSTANT(n) || BROTLI_HAS_UBFX) { + /* Masking with this expression turns to a single + "Unsigned Bit Field Extract" UBFX instruction on ARM. */ + return ~(~((brotli_reg_t)0) << n); + } else { + return kBrotliBitMask[n]; + } +} + +typedef struct { + brotli_reg_t val_; /* pre-fetched bits */ + brotli_reg_t bit_pos_; /* current bit-reading position in val_ */ + const uint8_t* next_in; /* the byte we're reading from */ + const uint8_t* guard_in; /* position from which "fast-path" is prohibited */ + const uint8_t* last_in; /* == next_in + avail_in */ +} BrotliBitReader; + +typedef struct { + brotli_reg_t val_; + brotli_reg_t bit_pos_; + const uint8_t* next_in; + size_t avail_in; +} BrotliBitReaderState; + +/* Initializes the BrotliBitReader fields. */ +BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* br); + +/* Ensures that accumulator is not empty. + May consume up to sizeof(brotli_reg_t) - 1 bytes of input. + Returns BROTLI_FALSE if data is required but there is no input available. + For !BROTLI_UNALIGNED_READ_FAST this function also prepares bit reader for + aligned reading. */ +BROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* br); + +/* Fallback for BrotliSafeReadBits32. Extracted as noninlined method to unburden + the main code-path. Never called for RFC brotli streams, required only for + "large-window" mode and other extensions. */ +BROTLI_INTERNAL BROTLI_NOINLINE BROTLI_BOOL BrotliSafeReadBits32Slow( + BrotliBitReader* br, brotli_reg_t n_bits, brotli_reg_t* val); + +static BROTLI_INLINE size_t +BrotliBitReaderGetAvailIn(BrotliBitReader* const br) { + return (size_t)(br->last_in - br->next_in); +} + +static BROTLI_INLINE void BrotliBitReaderSaveState( + BrotliBitReader* const from, BrotliBitReaderState* to) { + to->val_ = from->val_; + to->bit_pos_ = from->bit_pos_; + to->next_in = from->next_in; + to->avail_in = BrotliBitReaderGetAvailIn(from); +} + +static BROTLI_INLINE void BrotliBitReaderSetInput( + BrotliBitReader* const br, const uint8_t* next_in, size_t avail_in) { + br->next_in = next_in; + br->last_in = (avail_in == 0) ? next_in : (next_in + avail_in); + if (avail_in + 1 > BROTLI_FAST_INPUT_SLACK) { + br->guard_in = next_in + (avail_in + 1 - BROTLI_FAST_INPUT_SLACK); + } else { + br->guard_in = next_in; + } +} + +static BROTLI_INLINE void BrotliBitReaderRestoreState( + BrotliBitReader* const to, BrotliBitReaderState* from) { + to->val_ = from->val_; + to->bit_pos_ = from->bit_pos_; + to->next_in = from->next_in; + BrotliBitReaderSetInput(to, from->next_in, from->avail_in); +} + +static BROTLI_INLINE brotli_reg_t BrotliGetAvailableBits( + const BrotliBitReader* br) { + return br->bit_pos_; +} + +/* Returns amount of unread bytes the bit reader still has buffered from the + BrotliInput, including whole bytes in br->val_. Result is capped with + maximal ring-buffer size (larger number won't be utilized anyway). */ +static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) { + static const size_t kCap = (size_t)1 << BROTLI_LARGE_MAX_WBITS; + size_t avail_in = BrotliBitReaderGetAvailIn(br); + if (avail_in > kCap) return kCap; + return avail_in + (BrotliGetAvailableBits(br) >> 3); +} + +/* Checks if there is at least |num| bytes left in the input ring-buffer + (excluding the bits remaining in br->val_). */ +static BROTLI_INLINE BROTLI_BOOL BrotliCheckInputAmount( + BrotliBitReader* const br) { + return TO_BROTLI_BOOL(br->next_in < br->guard_in); +} + +/* Load more bits into accumulator. */ +static BROTLI_INLINE brotli_reg_t BrotliBitReaderLoadBits(brotli_reg_t val, + brotli_reg_t new_bits, + brotli_reg_t count, + brotli_reg_t offset) { + BROTLI_DCHECK( + !((val >> offset) & ~new_bits & ~(~((brotli_reg_t)0) << count))); + (void)count; + return val | (new_bits << offset); +} + +/* Guarantees that there are at least |n_bits| + 1 bits in accumulator. + Precondition: accumulator contains at least 1 bit. + |n_bits| should be in the range [1..24] for regular build. For portable + non-64-bit little-endian build only 16 bits are safe to request. */ +static BROTLI_INLINE void BrotliFillBitWindow( + BrotliBitReader* const br, brotli_reg_t n_bits) { +#if (BROTLI_64_BITS) + if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) && + (n_bits <= 8)) { + brotli_reg_t bit_pos = br->bit_pos_; + if (bit_pos <= 8) { + br->val_ = BrotliBitReaderLoadBits(br->val_, + BROTLI_UNALIGNED_LOAD64LE(br->next_in), 56, bit_pos); + br->bit_pos_ = bit_pos + 56; + br->next_in += 7; + } + } else if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) && + (n_bits <= 16)) { + brotli_reg_t bit_pos = br->bit_pos_; + if (bit_pos <= 16) { + br->val_ = BrotliBitReaderLoadBits(br->val_, + BROTLI_UNALIGNED_LOAD64LE(br->next_in), 48, bit_pos); + br->bit_pos_ = bit_pos + 48; + br->next_in += 6; + } + } else { + brotli_reg_t bit_pos = br->bit_pos_; + if (bit_pos <= 32) { + br->val_ = BrotliBitReaderLoadBits(br->val_, + (uint64_t)BROTLI_UNALIGNED_LOAD32LE(br->next_in), 32, bit_pos); + br->bit_pos_ = bit_pos + 32; + br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ; + } + } +#else + if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) && + (n_bits <= 8)) { + brotli_reg_t bit_pos = br->bit_pos_; + if (bit_pos <= 8) { + br->val_ = BrotliBitReaderLoadBits(br->val_, + BROTLI_UNALIGNED_LOAD32LE(br->next_in), 24, bit_pos); + br->bit_pos_ = bit_pos + 24; + br->next_in += 3; + } + } else { + brotli_reg_t bit_pos = br->bit_pos_; + if (bit_pos <= 16) { + br->val_ = BrotliBitReaderLoadBits(br->val_, + (uint32_t)BROTLI_UNALIGNED_LOAD16LE(br->next_in), 16, bit_pos); + br->bit_pos_ = bit_pos + 16; + br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ; + } + } +#endif +} + +/* Mostly like BrotliFillBitWindow, but guarantees only 16 bits and reads no + more than BROTLI_SHORT_FILL_BIT_WINDOW_READ bytes of input. */ +static BROTLI_INLINE void BrotliFillBitWindow16(BrotliBitReader* const br) { + BrotliFillBitWindow(br, 17); +} + +/* Tries to pull one byte of input to accumulator. + Returns BROTLI_FALSE if there is no input available. */ +static BROTLI_INLINE BROTLI_BOOL BrotliPullByte(BrotliBitReader* const br) { + if (br->next_in == br->last_in) { + return BROTLI_FALSE; + } + br->val_ = BrotliBitReaderLoadBits(br->val_, + (brotli_reg_t)*br->next_in, 8, br->bit_pos_); + br->bit_pos_ += 8; + ++br->next_in; + return BROTLI_TRUE; +} + +/* Returns currently available bits. + The number of valid bits could be calculated by BrotliGetAvailableBits. */ +static BROTLI_INLINE brotli_reg_t BrotliGetBitsUnmasked( + BrotliBitReader* const br) { + return br->val_; +} + +/* Like BrotliGetBits, but does not mask the result. + The result contains at least 16 valid bits. */ +static BROTLI_INLINE brotli_reg_t BrotliGet16BitsUnmasked( + BrotliBitReader* const br) { + BrotliFillBitWindow(br, 16); + return (brotli_reg_t)BrotliGetBitsUnmasked(br); +} + +/* Returns the specified number of bits from |br| without advancing bit + position. */ +static BROTLI_INLINE brotli_reg_t BrotliGetBits( + BrotliBitReader* const br, brotli_reg_t n_bits) { + BrotliFillBitWindow(br, n_bits); + return BrotliGetBitsUnmasked(br) & BitMask(n_bits); +} + +/* Tries to peek the specified amount of bits. Returns BROTLI_FALSE, if there + is not enough input. */ +static BROTLI_INLINE BROTLI_BOOL BrotliSafeGetBits( + BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) { + while (BrotliGetAvailableBits(br) < n_bits) { + if (!BrotliPullByte(br)) { + return BROTLI_FALSE; + } + } + *val = BrotliGetBitsUnmasked(br) & BitMask(n_bits); + return BROTLI_TRUE; +} + +/* Advances the bit pos by |n_bits|. */ +static BROTLI_INLINE void BrotliDropBits( + BrotliBitReader* const br, brotli_reg_t n_bits) { + br->bit_pos_ -= n_bits; + br->val_ >>= n_bits; +} + +/* Make sure that there are no spectre bits in accumulator. + This is important for the cases when some bytes are skipped + (i.e. never placed into accumulator). */ +static BROTLI_INLINE void BrotliBitReaderNormalize(BrotliBitReader* br) { + /* Actually, it is enough to normalize when br->bit_pos_ == 0 */ + if (br->bit_pos_ < (sizeof(brotli_reg_t) << 3u)) { + br->val_ &= (((brotli_reg_t)1) << br->bit_pos_) - 1; + } +} + +static BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) { + brotli_reg_t unused_bytes = BrotliGetAvailableBits(br) >> 3; + brotli_reg_t unused_bits = unused_bytes << 3; + br->next_in = + (unused_bytes == 0) ? br->next_in : (br->next_in - unused_bytes); + br->bit_pos_ -= unused_bits; + BrotliBitReaderNormalize(br); +} + +/* Reads the specified number of bits from |br| and advances the bit pos. + Precondition: accumulator MUST contain at least |n_bits|. */ +static BROTLI_INLINE void BrotliTakeBits(BrotliBitReader* const br, + brotli_reg_t n_bits, + brotli_reg_t* val) { + *val = BrotliGetBitsUnmasked(br) & BitMask(n_bits); + BROTLI_LOG(("[BrotliTakeBits] %d %d %d val: %6x\n", + (int)BrotliBitReaderGetAvailIn(br), (int)br->bit_pos_, + (int)n_bits, (int)*val)); + BrotliDropBits(br, n_bits); +} + +/* Reads the specified number of bits from |br| and advances the bit pos. + Assumes that there is enough input to perform BrotliFillBitWindow. + Up to 24 bits are allowed to be requested from this method. */ +static BROTLI_INLINE brotli_reg_t BrotliReadBits24( + BrotliBitReader* const br, brotli_reg_t n_bits) { + BROTLI_DCHECK(n_bits <= 24); + if (BROTLI_64_BITS || (n_bits <= 16)) { + brotli_reg_t val; + BrotliFillBitWindow(br, n_bits); + BrotliTakeBits(br, n_bits, &val); + return val; + } else { + brotli_reg_t low_val; + brotli_reg_t high_val; + BrotliFillBitWindow(br, 16); + BrotliTakeBits(br, 16, &low_val); + BrotliFillBitWindow(br, 8); + BrotliTakeBits(br, n_bits - 16, &high_val); + return low_val | (high_val << 16); + } +} + +/* Same as BrotliReadBits24, but allows reading up to 32 bits. */ +static BROTLI_INLINE brotli_reg_t BrotliReadBits32( + BrotliBitReader* const br, brotli_reg_t n_bits) { + BROTLI_DCHECK(n_bits <= 32); + if (BROTLI_64_BITS || (n_bits <= 16)) { + brotli_reg_t val; + BrotliFillBitWindow(br, n_bits); + BrotliTakeBits(br, n_bits, &val); + return val; + } else { + brotli_reg_t low_val; + brotli_reg_t high_val; + BrotliFillBitWindow(br, 16); + BrotliTakeBits(br, 16, &low_val); + BrotliFillBitWindow(br, 16); + BrotliTakeBits(br, n_bits - 16, &high_val); + return low_val | (high_val << 16); + } +} + +/* Tries to read the specified amount of bits. Returns BROTLI_FALSE, if there + is not enough input. |n_bits| MUST be positive. + Up to 24 bits are allowed to be requested from this method. */ +static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits( + BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) { + BROTLI_DCHECK(n_bits <= 24); + while (BrotliGetAvailableBits(br) < n_bits) { + if (!BrotliPullByte(br)) { + return BROTLI_FALSE; + } + } + BrotliTakeBits(br, n_bits, val); + return BROTLI_TRUE; +} + +/* Same as BrotliSafeReadBits, but allows reading up to 32 bits. */ +static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits32( + BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) { + BROTLI_DCHECK(n_bits <= 32); + if (BROTLI_64_BITS || (n_bits <= 24)) { + while (BrotliGetAvailableBits(br) < n_bits) { + if (!BrotliPullByte(br)) { + return BROTLI_FALSE; + } + } + BrotliTakeBits(br, n_bits, val); + return BROTLI_TRUE; + } else { + return BrotliSafeReadBits32Slow(br, n_bits, val); + } +} + +/* Advances the bit reader position to the next byte boundary and verifies + that any skipped bits are set to zero. */ +static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) { + brotli_reg_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7; + brotli_reg_t pad_bits = 0; + if (pad_bits_count != 0) { + BrotliTakeBits(br, pad_bits_count, &pad_bits); + } + BrotliBitReaderNormalize(br); + return TO_BROTLI_BOOL(pad_bits == 0); +} + +static BROTLI_INLINE void BrotliDropBytes(BrotliBitReader* br, size_t num) { + /* Check detour is legal: accumulator must to be empty. */ + BROTLI_DCHECK(br->bit_pos_ == 0); + BROTLI_DCHECK(br->val_ == 0); + br->next_in += num; +} + +/* Copies remaining input bytes stored in the bit reader to the output. Value + |num| may not be larger than BrotliGetRemainingBytes. The bit reader must be + warmed up again after this. */ +static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest, + BrotliBitReader* br, size_t num) { + while (BrotliGetAvailableBits(br) >= 8 && num > 0) { + *dest = (uint8_t)BrotliGetBitsUnmasked(br); + BrotliDropBits(br, 8); + ++dest; + --num; + } + BrotliBitReaderNormalize(br); + if (num > 0) { + memcpy(dest, br->next_in, num); + BrotliDropBytes(br, num); + } +} + +BROTLI_UNUSED_FUNCTION void BrotliBitReaderSuppressUnusedFunctions(void) { + BROTLI_UNUSED(&BrotliBitReaderSuppressUnusedFunctions); + + BROTLI_UNUSED(&BrotliBitReaderGetAvailIn); + BROTLI_UNUSED(&BrotliBitReaderLoadBits); + BROTLI_UNUSED(&BrotliBitReaderRestoreState); + BROTLI_UNUSED(&BrotliBitReaderSaveState); + BROTLI_UNUSED(&BrotliBitReaderSetInput); + BROTLI_UNUSED(&BrotliBitReaderUnload); + BROTLI_UNUSED(&BrotliCheckInputAmount); + BROTLI_UNUSED(&BrotliCopyBytes); + BROTLI_UNUSED(&BrotliFillBitWindow16); + BROTLI_UNUSED(&BrotliGet16BitsUnmasked); + BROTLI_UNUSED(&BrotliGetBits); + BROTLI_UNUSED(&BrotliGetRemainingBytes); + BROTLI_UNUSED(&BrotliJumpToByteBoundary); + BROTLI_UNUSED(&BrotliReadBits24); + BROTLI_UNUSED(&BrotliReadBits32); + BROTLI_UNUSED(&BrotliSafeGetBits); + BROTLI_UNUSED(&BrotliSafeReadBits); + BROTLI_UNUSED(&BrotliSafeReadBits32); +} + +} + +#endif /* BROTLI_DEC_BIT_READER_H_ */ diff --git a/third_party/brotli/dec/decode.cpp b/third_party/brotli/dec/decode.cpp new file mode 100644 index 00000000000..1ad9ac1a3e3 --- /dev/null +++ b/third_party/brotli/dec/decode.cpp @@ -0,0 +1,2758 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include + +#include /* free, malloc */ +#include /* memcpy, memset */ + +#include "../common/brotli_constants.h" +#include "../common/context.h" +#include "../common/dictionary.h" +#include "../common/brotli_platform.h" +#include "../common/shared_dictionary_internal.h" +#include "../common/transform.h" +#include "../common/version.h" +#include "bit_reader.h" +#include "huffman.h" +#include "prefix.h" +#include "state.h" + +#if defined(BROTLI_TARGET_NEON) +#include +#endif + +namespace duckdb_brotli { + +#define BROTLI_FAILURE(CODE) (BROTLI_DUMP(), CODE) + +#define BROTLI_LOG_UINT(name) BROTLI_LOG(("[%s] %s = %lu\n", __func__, #name, (unsigned long)(name))) +#define BROTLI_LOG_ARRAY_INDEX(array_name, idx) \ + BROTLI_LOG(("[%s] %s[%lu] = %lu\n", __func__, #array_name, (unsigned long)(idx), (unsigned long)array_name[idx])) + +#define HUFFMAN_TABLE_BITS 8U +#define HUFFMAN_TABLE_MASK 0xFF + +/* We need the slack region for the following reasons: + - doing up to two 16-byte copies for fast backward copying + - inserting transformed dictionary word: + 255 prefix + 32 base + 255 suffix */ +static const brotli_reg_t kRingBufferWriteAheadSlack = 542; + +static const uint8_t kCodeLengthCodeOrder[BROTLI_CODE_LENGTH_CODES] = { + 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15, +}; + +/* Static prefix code for the complex code length code lengths. */ +static const uint8_t kCodeLengthPrefixLength[16] = { + 2, 2, 2, 3, 2, 2, 2, 4, 2, 2, 2, 3, 2, 2, 2, 4, +}; + +static const uint8_t kCodeLengthPrefixValue[16] = { + 0, 4, 3, 2, 0, 4, 3, 1, 0, 4, 3, 2, 0, 4, 3, 5, +}; + +BROTLI_BOOL BrotliDecoderSetParameter(BrotliDecoderState *state, BrotliDecoderParameter p, uint32_t value) { + if (state->state != BROTLI_STATE_UNINITED) + return BROTLI_FALSE; + switch (p) { + case BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION: + state->canny_ringbuffer_allocation = !!value ? 0 : 1; + return BROTLI_TRUE; + + case BROTLI_DECODER_PARAM_LARGE_WINDOW: + state->large_window = TO_BROTLI_BOOL(!!value); + return BROTLI_TRUE; + + default: + return BROTLI_FALSE; + } +} + +BrotliDecoderState *BrotliDecoderCreateInstance(brotli_alloc_func alloc_func, brotli_free_func free_func, + void *opaque) { + BrotliDecoderState *state = 0; + if (!alloc_func && !free_func) { + state = (BrotliDecoderState *)malloc(sizeof(BrotliDecoderState)); + } else if (alloc_func && free_func) { + state = (BrotliDecoderState *)alloc_func(opaque, sizeof(BrotliDecoderState)); + } + if (state == 0) { + BROTLI_DUMP(); + return 0; + } + if (!BrotliDecoderStateInit(state, alloc_func, free_func, opaque)) { + BROTLI_DUMP(); + if (!alloc_func && !free_func) { + free(state); + } else if (alloc_func && free_func) { + free_func(opaque, state); + } + return 0; + } + return state; +} + +/* Deinitializes and frees BrotliDecoderState instance. */ +void BrotliDecoderDestroyInstance(BrotliDecoderState *state) { + if (!state) { + return; + } else { + brotli_free_func free_func = state->free_func; + void *opaque = state->memory_manager_opaque; + BrotliDecoderStateCleanup(state); + free_func(opaque, state); + } +} + +/* Saves error code and converts it to BrotliDecoderResult. */ +static BROTLI_NOINLINE BrotliDecoderResult SaveErrorCode(BrotliDecoderState *s, BrotliDecoderErrorCode e, + size_t consumed_input) { + s->error_code = (int)e; + s->used_input += consumed_input; + if ((s->buffer_length != 0) && (s->br.next_in == s->br.last_in)) { + /* If internal buffer is depleted at last, reset it. */ + s->buffer_length = 0; + } + switch (e) { + case BROTLI_DECODER_SUCCESS: + return BROTLI_DECODER_RESULT_SUCCESS; + + case BROTLI_DECODER_NEEDS_MORE_INPUT: + return BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT; + + case BROTLI_DECODER_NEEDS_MORE_OUTPUT: + return BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; + + default: + return BROTLI_DECODER_RESULT_ERROR; + } +} + +/* Decodes WBITS by reading 1 - 7 bits, or 0x11 for "Large Window Brotli". + Precondition: bit-reader accumulator has at least 8 bits. */ +static BrotliDecoderErrorCode DecodeWindowBits(BrotliDecoderState *s, BrotliBitReader *br) { + brotli_reg_t n; + BROTLI_BOOL large_window = s->large_window; + s->large_window = BROTLI_FALSE; + BrotliTakeBits(br, 1, &n); + if (n == 0) { + s->window_bits = 16; + return BROTLI_DECODER_SUCCESS; + } + BrotliTakeBits(br, 3, &n); + if (n != 0) { + s->window_bits = (17u + n) & 63u; + return BROTLI_DECODER_SUCCESS; + } + BrotliTakeBits(br, 3, &n); + if (n == 1) { + if (large_window) { + BrotliTakeBits(br, 1, &n); + if (n == 1) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS); + } + s->large_window = BROTLI_TRUE; + return BROTLI_DECODER_SUCCESS; + } else { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS); + } + } + if (n != 0) { + s->window_bits = (8u + n) & 63u; + return BROTLI_DECODER_SUCCESS; + } + s->window_bits = 17; + return BROTLI_DECODER_SUCCESS; +} + +static BROTLI_INLINE void memmove16(uint8_t *dst, uint8_t *src) { +#if defined(BROTLI_TARGET_NEON) + vst1q_u8(dst, vld1q_u8(src)); +#else + uint32_t buffer[4]; + memcpy(buffer, src, 16); + memcpy(dst, buffer, 16); +#endif +} + +/* Decodes a number in the range [0..255], by reading 1 - 11 bits. */ +static BROTLI_NOINLINE BrotliDecoderErrorCode DecodeVarLenUint8(BrotliDecoderState *s, BrotliBitReader *br, + brotli_reg_t *value) { + brotli_reg_t bits; + switch (s->substate_decode_uint8) { + case BROTLI_STATE_DECODE_UINT8_NONE: + if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 1, &bits))) { + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + if (bits == 0) { + *value = 0; + return BROTLI_DECODER_SUCCESS; + } + /* Fall through. */ + + case BROTLI_STATE_DECODE_UINT8_SHORT: + if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 3, &bits))) { + s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_SHORT; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + if (bits == 0) { + *value = 1; + s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE; + return BROTLI_DECODER_SUCCESS; + } + /* Use output value as a temporary storage. It MUST be persisted. */ + *value = bits; + /* Fall through. */ + + case BROTLI_STATE_DECODE_UINT8_LONG: + if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, *value, &bits))) { + s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_LONG; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + *value = (1U << *value) + bits; + s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE; + return BROTLI_DECODER_SUCCESS; + + default: + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */ + } +} + +/* Decodes a metablock length and flags by reading 2 - 31 bits. */ +static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(BrotliDecoderState *s, BrotliBitReader *br) { + brotli_reg_t bits; + int i; + for (;;) { + switch (s->substate_metablock_header) { + case BROTLI_STATE_METABLOCK_HEADER_NONE: + if (!BrotliSafeReadBits(br, 1, &bits)) { + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + s->is_last_metablock = bits ? 1 : 0; + s->meta_block_remaining_len = 0; + s->is_uncompressed = 0; + s->is_metadata = 0; + if (!s->is_last_metablock) { + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES; + break; + } + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_EMPTY; + /* Fall through. */ + + case BROTLI_STATE_METABLOCK_HEADER_EMPTY: + if (!BrotliSafeReadBits(br, 1, &bits)) { + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + if (bits) { + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE; + return BROTLI_DECODER_SUCCESS; + } + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES; + /* Fall through. */ + + case BROTLI_STATE_METABLOCK_HEADER_NIBBLES: + if (!BrotliSafeReadBits(br, 2, &bits)) { + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + s->size_nibbles = (uint8_t)(bits + 4); + s->loop_counter = 0; + if (bits == 3) { + s->is_metadata = 1; + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_RESERVED; + break; + } + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_SIZE; + /* Fall through. */ + + case BROTLI_STATE_METABLOCK_HEADER_SIZE: + i = s->loop_counter; + for (; i < (int)s->size_nibbles; ++i) { + if (!BrotliSafeReadBits(br, 4, &bits)) { + s->loop_counter = i; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 4 && bits == 0) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE); + } + s->meta_block_remaining_len |= (int)(bits << (i * 4)); + } + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED; + /* Fall through. */ + + case BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED: + if (!s->is_last_metablock) { + if (!BrotliSafeReadBits(br, 1, &bits)) { + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + s->is_uncompressed = bits ? 1 : 0; + } + ++s->meta_block_remaining_len; + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE; + return BROTLI_DECODER_SUCCESS; + + case BROTLI_STATE_METABLOCK_HEADER_RESERVED: + if (!BrotliSafeReadBits(br, 1, &bits)) { + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + if (bits != 0) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_RESERVED); + } + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_BYTES; + /* Fall through. */ + + case BROTLI_STATE_METABLOCK_HEADER_BYTES: + if (!BrotliSafeReadBits(br, 2, &bits)) { + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + if (bits == 0) { + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE; + return BROTLI_DECODER_SUCCESS; + } + s->size_nibbles = (uint8_t)bits; + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_METADATA; + /* Fall through. */ + + case BROTLI_STATE_METABLOCK_HEADER_METADATA: + i = s->loop_counter; + for (; i < (int)s->size_nibbles; ++i) { + if (!BrotliSafeReadBits(br, 8, &bits)) { + s->loop_counter = i; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 1 && bits == 0) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE); + } + s->meta_block_remaining_len |= (int)(bits << (i * 8)); + } + ++s->meta_block_remaining_len; + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE; + return BROTLI_DECODER_SUCCESS; + + default: + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */ + } + } +} + +/* Decodes the Huffman code. + This method doesn't read data from the bit reader, BUT drops the amount of + bits that correspond to the decoded symbol. + bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */ +static BROTLI_INLINE brotli_reg_t DecodeSymbol(brotli_reg_t bits, const HuffmanCode *table, BrotliBitReader *br) { + BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table); + BROTLI_HC_ADJUST_TABLE_INDEX(table, bits & HUFFMAN_TABLE_MASK); + if (BROTLI_HC_FAST_LOAD_BITS(table) > HUFFMAN_TABLE_BITS) { + brotli_reg_t nbits = BROTLI_HC_FAST_LOAD_BITS(table) - HUFFMAN_TABLE_BITS; + BrotliDropBits(br, HUFFMAN_TABLE_BITS); + BROTLI_HC_ADJUST_TABLE_INDEX(table, BROTLI_HC_FAST_LOAD_VALUE(table) + + ((bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits))); + } + BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table)); + return BROTLI_HC_FAST_LOAD_VALUE(table); +} + +/* Reads and decodes the next Huffman code from bit-stream. + This method peeks 16 bits of input and drops 0 - 15 of them. */ +static BROTLI_INLINE brotli_reg_t ReadSymbol(const HuffmanCode *table, BrotliBitReader *br) { + return DecodeSymbol(BrotliGet16BitsUnmasked(br), table, br); +} + +/* Same as DecodeSymbol, but it is known that there is less than 15 bits of + input are currently available. */ +static BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(const HuffmanCode *table, BrotliBitReader *br, + brotli_reg_t *result) { + brotli_reg_t val; + brotli_reg_t available_bits = BrotliGetAvailableBits(br); + BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table); + if (available_bits == 0) { + if (BROTLI_HC_FAST_LOAD_BITS(table) == 0) { + *result = BROTLI_HC_FAST_LOAD_VALUE(table); + return BROTLI_TRUE; + } + return BROTLI_FALSE; /* No valid bits at all. */ + } + val = BrotliGetBitsUnmasked(br); + BROTLI_HC_ADJUST_TABLE_INDEX(table, val & HUFFMAN_TABLE_MASK); + if (BROTLI_HC_FAST_LOAD_BITS(table) <= HUFFMAN_TABLE_BITS) { + if (BROTLI_HC_FAST_LOAD_BITS(table) <= available_bits) { + BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table)); + *result = BROTLI_HC_FAST_LOAD_VALUE(table); + return BROTLI_TRUE; + } else { + return BROTLI_FALSE; /* Not enough bits for the first level. */ + } + } + if (available_bits <= HUFFMAN_TABLE_BITS) { + return BROTLI_FALSE; /* Not enough bits to move to the second level. */ + } + + /* Speculatively drop HUFFMAN_TABLE_BITS. */ + val = (val & BitMask(BROTLI_HC_FAST_LOAD_BITS(table))) >> HUFFMAN_TABLE_BITS; + available_bits -= HUFFMAN_TABLE_BITS; + BROTLI_HC_ADJUST_TABLE_INDEX(table, BROTLI_HC_FAST_LOAD_VALUE(table) + val); + if (available_bits < BROTLI_HC_FAST_LOAD_BITS(table)) { + return BROTLI_FALSE; /* Not enough bits for the second level. */ + } + + BrotliDropBits(br, HUFFMAN_TABLE_BITS + BROTLI_HC_FAST_LOAD_BITS(table)); + *result = BROTLI_HC_FAST_LOAD_VALUE(table); + return BROTLI_TRUE; +} + +static BROTLI_INLINE BROTLI_BOOL SafeReadSymbol(const HuffmanCode *table, BrotliBitReader *br, brotli_reg_t *result) { + brotli_reg_t val; + if (BROTLI_PREDICT_TRUE(BrotliSafeGetBits(br, 15, &val))) { + *result = DecodeSymbol(val, table, br); + return BROTLI_TRUE; + } + return SafeDecodeSymbol(table, br, result); +} + +/* Makes a look-up in first level Huffman table. Peeks 8 bits. */ +static BROTLI_INLINE void PreloadSymbol(int safe, const HuffmanCode *table, BrotliBitReader *br, brotli_reg_t *bits, + brotli_reg_t *value) { + if (safe) { + return; + } + BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table); + BROTLI_HC_ADJUST_TABLE_INDEX(table, BrotliGetBits(br, HUFFMAN_TABLE_BITS)); + *bits = BROTLI_HC_FAST_LOAD_BITS(table); + *value = BROTLI_HC_FAST_LOAD_VALUE(table); +} + +/* Decodes the next Huffman code using data prepared by PreloadSymbol. + Reads 0 - 15 bits. Also peeks 8 following bits. */ +static BROTLI_INLINE brotli_reg_t ReadPreloadedSymbol(const HuffmanCode *table, BrotliBitReader *br, brotli_reg_t *bits, + brotli_reg_t *value) { + brotli_reg_t result = *value; + if (BROTLI_PREDICT_FALSE(*bits > HUFFMAN_TABLE_BITS)) { + brotli_reg_t val = BrotliGet16BitsUnmasked(br); + const HuffmanCode *ext = table + (val & HUFFMAN_TABLE_MASK) + *value; + brotli_reg_t mask = BitMask((*bits - HUFFMAN_TABLE_BITS)); + BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(ext); + BrotliDropBits(br, HUFFMAN_TABLE_BITS); + BROTLI_HC_ADJUST_TABLE_INDEX(ext, (val >> HUFFMAN_TABLE_BITS) & mask); + BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(ext)); + result = BROTLI_HC_FAST_LOAD_VALUE(ext); + } else { + BrotliDropBits(br, *bits); + } + PreloadSymbol(0, table, br, bits, value); + return result; +} + +static BROTLI_INLINE brotli_reg_t Log2Floor(brotli_reg_t x) { + brotli_reg_t result = 0; + while (x) { + x >>= 1; + ++result; + } + return result; +} + +/* Reads (s->symbol + 1) symbols. + Totally 1..4 symbols are read, 1..11 bits each. + The list of symbols MUST NOT contain duplicates. */ +static BrotliDecoderErrorCode ReadSimpleHuffmanSymbols(brotli_reg_t alphabet_size_max, brotli_reg_t alphabet_size_limit, + BrotliDecoderState *s) { + /* max_bits == 1..11; symbol == 0..3; 1..44 bits will be read. */ + BrotliBitReader *br = &s->br; + BrotliMetablockHeaderArena *h = &s->arena.header; + brotli_reg_t max_bits = Log2Floor(alphabet_size_max - 1); + brotli_reg_t i = h->sub_loop_counter; + brotli_reg_t num_symbols = h->symbol; + while (i <= num_symbols) { + brotli_reg_t v; + if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) { + h->sub_loop_counter = i; + h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + if (v >= alphabet_size_limit) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET); + } + h->symbols_lists_array[i] = (uint16_t)v; + BROTLI_LOG_UINT(h->symbols_lists_array[i]); + ++i; + } + + for (i = 0; i < num_symbols; ++i) { + brotli_reg_t k = i + 1; + for (; k <= num_symbols; ++k) { + if (h->symbols_lists_array[i] == h->symbols_lists_array[k]) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME); + } + } + } + + return BROTLI_DECODER_SUCCESS; +} + +/* Process single decoded symbol code length: + A) reset the repeat variable + B) remember code length (if it is not 0) + C) extend corresponding index-chain + D) reduce the Huffman space + E) update the histogram */ +static BROTLI_INLINE void ProcessSingleCodeLength(brotli_reg_t code_len, brotli_reg_t *symbol, brotli_reg_t *repeat, + brotli_reg_t *space, brotli_reg_t *prev_code_len, + uint16_t *symbol_lists, uint16_t *code_length_histo, + int *next_symbol) { + *repeat = 0; + if (code_len != 0) { /* code_len == 1..15 */ + symbol_lists[next_symbol[code_len]] = (uint16_t)(*symbol); + next_symbol[code_len] = (int)(*symbol); + *prev_code_len = code_len; + *space -= 32768U >> code_len; + code_length_histo[code_len]++; + BROTLI_LOG(("[ReadHuffmanCode] code_length[%d] = %d\n", (int)*symbol, (int)code_len)); + } + (*symbol)++; +} + +/* Process repeated symbol code length. + A) Check if it is the extension of previous repeat sequence; if the decoded + value is not BROTLI_REPEAT_PREVIOUS_CODE_LENGTH, then it is a new + symbol-skip + B) Update repeat variable + C) Check if operation is feasible (fits alphabet) + D) For each symbol do the same operations as in ProcessSingleCodeLength + + PRECONDITION: code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH or + code_len == BROTLI_REPEAT_ZERO_CODE_LENGTH */ +static BROTLI_INLINE void ProcessRepeatedCodeLength(brotli_reg_t code_len, brotli_reg_t repeat_delta, + brotli_reg_t alphabet_size, brotli_reg_t *symbol, + brotli_reg_t *repeat, brotli_reg_t *space, + brotli_reg_t *prev_code_len, brotli_reg_t *repeat_code_len, + uint16_t *symbol_lists, uint16_t *code_length_histo, + int *next_symbol) { + brotli_reg_t old_repeat; + brotli_reg_t extra_bits = 3; /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */ + brotli_reg_t new_len = 0; /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */ + if (code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) { + new_len = *prev_code_len; + extra_bits = 2; + } + if (*repeat_code_len != new_len) { + *repeat = 0; + *repeat_code_len = new_len; + } + old_repeat = *repeat; + if (*repeat > 0) { + *repeat -= 2; + *repeat <<= extra_bits; + } + *repeat += repeat_delta + 3U; + repeat_delta = *repeat - old_repeat; + if (*symbol + repeat_delta > alphabet_size) { + BROTLI_DUMP(); + *symbol = alphabet_size; + *space = 0xFFFFF; + return; + } + BROTLI_LOG(("[ReadHuffmanCode] code_length[%d..%d] = %d\n", (int)*symbol, (int)(*symbol + repeat_delta - 1), + (int)*repeat_code_len)); + if (*repeat_code_len != 0) { + brotli_reg_t last = *symbol + repeat_delta; + int next = next_symbol[*repeat_code_len]; + do { + symbol_lists[next] = (uint16_t)*symbol; + next = (int)*symbol; + } while (++(*symbol) != last); + next_symbol[*repeat_code_len] = next; + *space -= repeat_delta << (15 - *repeat_code_len); + code_length_histo[*repeat_code_len] = (uint16_t)(code_length_histo[*repeat_code_len] + repeat_delta); + } else { + *symbol += repeat_delta; + } +} + +/* Reads and decodes symbol codelengths. */ +static BrotliDecoderErrorCode ReadSymbolCodeLengths(brotli_reg_t alphabet_size, BrotliDecoderState *s) { + BrotliBitReader *br = &s->br; + BrotliMetablockHeaderArena *h = &s->arena.header; + brotli_reg_t symbol = h->symbol; + brotli_reg_t repeat = h->repeat; + brotli_reg_t space = h->space; + brotli_reg_t prev_code_len = h->prev_code_len; + brotli_reg_t repeat_code_len = h->repeat_code_len; + uint16_t *symbol_lists = h->symbol_lists; + uint16_t *code_length_histo = h->code_length_histo; + int *next_symbol = h->next_symbol; + if (!BrotliWarmupBitReader(br)) { + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + while (symbol < alphabet_size && space > 0) { + const HuffmanCode *p = h->table; + brotli_reg_t code_len; + BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p); + if (!BrotliCheckInputAmount(br)) { + h->symbol = symbol; + h->repeat = repeat; + h->prev_code_len = prev_code_len; + h->repeat_code_len = repeat_code_len; + h->space = space; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + BrotliFillBitWindow16(br); + BROTLI_HC_ADJUST_TABLE_INDEX(p, + BrotliGetBitsUnmasked(br) & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH)); + BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p)); /* Use 1..5 bits. */ + code_len = BROTLI_HC_FAST_LOAD_VALUE(p); /* code_len == 0..17 */ + if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) { + ProcessSingleCodeLength(code_len, &symbol, &repeat, &space, &prev_code_len, symbol_lists, code_length_histo, + next_symbol); + } else { /* code_len == 16..17, extra_bits == 2..3 */ + brotli_reg_t extra_bits = (code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) ? 2 : 3; + brotli_reg_t repeat_delta = BrotliGetBitsUnmasked(br) & BitMask(extra_bits); + BrotliDropBits(br, extra_bits); + ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size, &symbol, &repeat, &space, &prev_code_len, + &repeat_code_len, symbol_lists, code_length_histo, next_symbol); + } + } + h->space = space; + return BROTLI_DECODER_SUCCESS; +} + +static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(brotli_reg_t alphabet_size, BrotliDecoderState *s) { + BrotliBitReader *br = &s->br; + BrotliMetablockHeaderArena *h = &s->arena.header; + BROTLI_BOOL get_byte = BROTLI_FALSE; + while (h->symbol < alphabet_size && h->space > 0) { + const HuffmanCode *p = h->table; + brotli_reg_t code_len; + brotli_reg_t available_bits; + brotli_reg_t bits = 0; + BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p); + if (get_byte && !BrotliPullByte(br)) + return BROTLI_DECODER_NEEDS_MORE_INPUT; + get_byte = BROTLI_FALSE; + available_bits = BrotliGetAvailableBits(br); + if (available_bits != 0) { + bits = (uint32_t)BrotliGetBitsUnmasked(br); + } + BROTLI_HC_ADJUST_TABLE_INDEX(p, bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH)); + if (BROTLI_HC_FAST_LOAD_BITS(p) > available_bits) { + get_byte = BROTLI_TRUE; + continue; + } + code_len = BROTLI_HC_FAST_LOAD_VALUE(p); /* code_len == 0..17 */ + if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) { + BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p)); + ProcessSingleCodeLength(code_len, &h->symbol, &h->repeat, &h->space, &h->prev_code_len, h->symbol_lists, + h->code_length_histo, h->next_symbol); + } else { /* code_len == 16..17, extra_bits == 2..3 */ + brotli_reg_t extra_bits = code_len - 14U; + brotli_reg_t repeat_delta = (bits >> BROTLI_HC_FAST_LOAD_BITS(p)) & BitMask(extra_bits); + if (available_bits < BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits) { + get_byte = BROTLI_TRUE; + continue; + } + BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits); + ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size, &h->symbol, &h->repeat, &h->space, + &h->prev_code_len, &h->repeat_code_len, h->symbol_lists, h->code_length_histo, + h->next_symbol); + } + } + return BROTLI_DECODER_SUCCESS; +} + +/* Reads and decodes 15..18 codes using static prefix code. + Each code is 2..4 bits long. In total 30..72 bits are used. */ +static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState *s) { + BrotliBitReader *br = &s->br; + BrotliMetablockHeaderArena *h = &s->arena.header; + brotli_reg_t num_codes = h->repeat; + brotli_reg_t space = h->space; + brotli_reg_t i = h->sub_loop_counter; + for (; i < BROTLI_CODE_LENGTH_CODES; ++i) { + const uint8_t code_len_idx = kCodeLengthCodeOrder[i]; + brotli_reg_t ix; + brotli_reg_t v; + if (BROTLI_PREDICT_FALSE(!BrotliSafeGetBits(br, 4, &ix))) { + brotli_reg_t available_bits = BrotliGetAvailableBits(br); + if (available_bits != 0) { + ix = BrotliGetBitsUnmasked(br) & 0xF; + } else { + ix = 0; + } + if (kCodeLengthPrefixLength[ix] > available_bits) { + h->sub_loop_counter = i; + h->repeat = num_codes; + h->space = space; + h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + } + v = kCodeLengthPrefixValue[ix]; + BrotliDropBits(br, kCodeLengthPrefixLength[ix]); + h->code_length_code_lengths[code_len_idx] = (uint8_t)v; + BROTLI_LOG_ARRAY_INDEX(h->code_length_code_lengths, code_len_idx); + if (v != 0) { + space = space - (32U >> v); + ++num_codes; + ++h->code_length_histo[v]; + if (space - 1U >= 32U) { + /* space is 0 or wrapped around. */ + break; + } + } + } + if (!(num_codes == 1 || space == 0)) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_CL_SPACE); + } + return BROTLI_DECODER_SUCCESS; +} + +/* Decodes the Huffman tables. + There are 2 scenarios: + A) Huffman code contains only few symbols (1..4). Those symbols are read + directly; their code lengths are defined by the number of symbols. + For this scenario 4 - 49 bits will be read. + + B) 2-phase decoding: + B.1) Small Huffman table is decoded; it is specified with code lengths + encoded with predefined entropy code. 32 - 74 bits are used. + B.2) Decoded table is used to decode code lengths of symbols in resulting + Huffman table. In worst case 3520 bits are read. */ +static BrotliDecoderErrorCode ReadHuffmanCode(brotli_reg_t alphabet_size_max, brotli_reg_t alphabet_size_limit, + HuffmanCode *table, brotli_reg_t *opt_table_size, BrotliDecoderState *s) { + BrotliBitReader *br = &s->br; + BrotliMetablockHeaderArena *h = &s->arena.header; + /* State machine. */ + for (;;) { + switch (h->substate_huffman) { + case BROTLI_STATE_HUFFMAN_NONE: + if (!BrotliSafeReadBits(br, 2, &h->sub_loop_counter)) { + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + BROTLI_LOG_UINT(h->sub_loop_counter); + /* The value is used as follows: + 1 for simple code; + 0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */ + if (h->sub_loop_counter != 1) { + h->space = 32; + h->repeat = 0; /* num_codes */ + memset(&h->code_length_histo[0], 0, + sizeof(h->code_length_histo[0]) * (BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1)); + memset(&h->code_length_code_lengths[0], 0, sizeof(h->code_length_code_lengths)); + h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX; + continue; + } + /* Fall through. */ + + case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE: + /* Read symbols, codes & code lengths directly. */ + if (!BrotliSafeReadBits(br, 2, &h->symbol)) { /* num_symbols */ + h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + h->sub_loop_counter = 0; + /* Fall through. */ + + case BROTLI_STATE_HUFFMAN_SIMPLE_READ: { + BrotliDecoderErrorCode result = ReadSimpleHuffmanSymbols(alphabet_size_max, alphabet_size_limit, s); + if (result != BROTLI_DECODER_SUCCESS) { + return result; + } + } + /* Fall through. */ + + case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: { + brotli_reg_t table_size; + if (h->symbol == 3) { + brotli_reg_t bits; + if (!BrotliSafeReadBits(br, 1, &bits)) { + h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + h->symbol += bits; + } + BROTLI_LOG_UINT(h->symbol); + table_size = + BrotliBuildSimpleHuffmanTable(table, HUFFMAN_TABLE_BITS, h->symbols_lists_array, (uint32_t)h->symbol); + if (opt_table_size) { + *opt_table_size = table_size; + } + h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; + return BROTLI_DECODER_SUCCESS; + } + + /* Decode Huffman-coded code lengths. */ + case BROTLI_STATE_HUFFMAN_COMPLEX: { + brotli_reg_t i; + BrotliDecoderErrorCode result = ReadCodeLengthCodeLengths(s); + if (result != BROTLI_DECODER_SUCCESS) { + return result; + } + BrotliBuildCodeLengthsHuffmanTable(h->table, h->code_length_code_lengths, h->code_length_histo); + memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo)); + for (i = 0; i <= BROTLI_HUFFMAN_MAX_CODE_LENGTH; ++i) { + h->next_symbol[i] = (int)i - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1); + h->symbol_lists[h->next_symbol[i]] = 0xFFFF; + } + + h->symbol = 0; + h->prev_code_len = BROTLI_INITIAL_REPEATED_CODE_LENGTH; + h->repeat = 0; + h->repeat_code_len = 0; + h->space = 32768; + h->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS; + } + /* Fall through. */ + + case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: { + brotli_reg_t table_size; + BrotliDecoderErrorCode result = ReadSymbolCodeLengths(alphabet_size_limit, s); + if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) { + result = SafeReadSymbolCodeLengths(alphabet_size_limit, s); + } + if (result != BROTLI_DECODER_SUCCESS) { + return result; + } + + if (h->space != 0) { + BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", (int)h->space)); + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE); + } + table_size = BrotliBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, h->symbol_lists, h->code_length_histo); + if (opt_table_size) { + *opt_table_size = table_size; + } + h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; + return BROTLI_DECODER_SUCCESS; + } + + default: + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */ + } + } +} + +/* Decodes a block length by reading 3..39 bits. */ +static BROTLI_INLINE brotli_reg_t ReadBlockLength(const HuffmanCode *table, BrotliBitReader *br) { + brotli_reg_t code; + brotli_reg_t nbits; + code = ReadSymbol(table, br); + nbits = _kBrotliPrefixCodeRanges[code].nbits; /* nbits == 2..24 */ + return _kBrotliPrefixCodeRanges[code].offset + BrotliReadBits24(br, nbits); +} + +/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then + reading can't be continued with ReadBlockLength. */ +static BROTLI_INLINE BROTLI_BOOL SafeReadBlockLength(BrotliDecoderState *s, brotli_reg_t *result, + const HuffmanCode *table, BrotliBitReader *br) { + brotli_reg_t index; + if (s->substate_read_block_length == BROTLI_STATE_READ_BLOCK_LENGTH_NONE) { + if (!SafeReadSymbol(table, br, &index)) { + return BROTLI_FALSE; + } + } else { + index = s->block_length_index; + } + { + brotli_reg_t bits; + brotli_reg_t nbits = _kBrotliPrefixCodeRanges[index].nbits; + brotli_reg_t offset = _kBrotliPrefixCodeRanges[index].offset; + if (!BrotliSafeReadBits(br, nbits, &bits)) { + s->block_length_index = index; + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX; + return BROTLI_FALSE; + } + *result = offset + bits; + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE; + return BROTLI_TRUE; + } +} + +/* Transform: + 1) initialize list L with values 0, 1,... 255 + 2) For each input element X: + 2.1) let Y = L[X] + 2.2) remove X-th element from L + 2.3) prepend Y to L + 2.4) append Y to output + + In most cases max(Y) <= 7, so most of L remains intact. + To reduce the cost of initialization, we reuse L, remember the upper bound + of Y values, and reinitialize only first elements in L. + + Most of input values are 0 and 1. To reduce number of branches, we replace + inner for loop with do-while. */ +static BROTLI_NOINLINE void InverseMoveToFrontTransform(uint8_t *v, brotli_reg_t v_len, BrotliDecoderState *state) { + /* Reinitialize elements that could have been changed. */ + brotli_reg_t i = 1; + brotli_reg_t upper_bound = state->mtf_upper_bound; + uint32_t *mtf = &state->mtf[1]; /* Make mtf[-1] addressable. */ + uint8_t *mtf_u8 = (uint8_t *)mtf; + /* Load endian-aware constant. */ + const uint8_t b0123[4] = {0, 1, 2, 3}; + uint32_t pattern; + memcpy(&pattern, &b0123, 4); + + /* Initialize list using 4 consequent values pattern. */ + mtf[0] = pattern; + do { + pattern += 0x04040404; /* Advance all 4 values by 4. */ + mtf[i] = pattern; + i++; + } while (i <= upper_bound); + + /* Transform the input. */ + upper_bound = 0; + for (i = 0; i < v_len; ++i) { + int index = v[i]; + uint8_t value = mtf_u8[index]; + upper_bound |= v[i]; + v[i] = value; + mtf_u8[-1] = value; + do { + index--; + mtf_u8[index + 1] = mtf_u8[index]; + } while (index >= 0); + } + /* Remember amount of elements to be reinitialized. */ + state->mtf_upper_bound = upper_bound >> 2; +} + +/* Decodes a series of Huffman table using ReadHuffmanCode function. */ +static BrotliDecoderErrorCode HuffmanTreeGroupDecode(HuffmanTreeGroup *group, BrotliDecoderState *s) { + BrotliMetablockHeaderArena *h = &s->arena.header; + if (h->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) { + h->next = group->codes; + h->htree_index = 0; + h->substate_tree_group = BROTLI_STATE_TREE_GROUP_LOOP; + } + while (h->htree_index < group->num_htrees) { + brotli_reg_t table_size; + BrotliDecoderErrorCode result = + ReadHuffmanCode(group->alphabet_size_max, group->alphabet_size_limit, h->next, &table_size, s); + if (result != BROTLI_DECODER_SUCCESS) + return result; + group->htrees[h->htree_index] = h->next; + h->next += table_size; + ++h->htree_index; + } + h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE; + return BROTLI_DECODER_SUCCESS; +} + +/* Decodes a context map. + Decoding is done in 4 phases: + 1) Read auxiliary information (6..16 bits) and allocate memory. + In case of trivial context map, decoding is finished at this phase. + 2) Decode Huffman table using ReadHuffmanCode function. + This table will be used for reading context map items. + 3) Read context map items; "0" values could be run-length encoded. + 4) Optionally, apply InverseMoveToFront transform to the resulting map. */ +static BrotliDecoderErrorCode DecodeContextMap(brotli_reg_t context_map_size, brotli_reg_t *num_htrees, + uint8_t **context_map_arg, BrotliDecoderState *s) { + BrotliBitReader *br = &s->br; + BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS; + BrotliMetablockHeaderArena *h = &s->arena.header; + + switch ((int)h->substate_context_map) { + case BROTLI_STATE_CONTEXT_MAP_NONE: + result = DecodeVarLenUint8(s, br, num_htrees); + if (result != BROTLI_DECODER_SUCCESS) { + return result; + } + (*num_htrees)++; + h->context_index = 0; + BROTLI_LOG_UINT(context_map_size); + BROTLI_LOG_UINT(*num_htrees); + *context_map_arg = (uint8_t *)BROTLI_DECODER_ALLOC(s, (size_t)context_map_size); + if (*context_map_arg == 0) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP); + } + if (*num_htrees <= 1) { + memset(*context_map_arg, 0, (size_t)context_map_size); + return BROTLI_DECODER_SUCCESS; + } + h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX; + /* Fall through. */ + + case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: { + brotli_reg_t bits; + /* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe + to peek 4 bits ahead. */ + if (!BrotliSafeGetBits(br, 5, &bits)) { + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + if ((bits & 1) != 0) { /* Use RLE for zeros. */ + h->max_run_length_prefix = (bits >> 1) + 1; + BrotliDropBits(br, 5); + } else { + h->max_run_length_prefix = 0; + BrotliDropBits(br, 1); + } + BROTLI_LOG_UINT(h->max_run_length_prefix); + h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN; + } + /* Fall through. */ + + case BROTLI_STATE_CONTEXT_MAP_HUFFMAN: { + brotli_reg_t alphabet_size = *num_htrees + h->max_run_length_prefix; + result = ReadHuffmanCode(alphabet_size, alphabet_size, h->context_map_table, NULL, s); + if (result != BROTLI_DECODER_SUCCESS) + return result; + h->code = 0xFFFF; + h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE; + } + /* Fall through. */ + + case BROTLI_STATE_CONTEXT_MAP_DECODE: { + brotli_reg_t context_index = h->context_index; + brotli_reg_t max_run_length_prefix = h->max_run_length_prefix; + uint8_t *context_map = *context_map_arg; + brotli_reg_t code = h->code; + BROTLI_BOOL skip_preamble = (code != 0xFFFF); + while (context_index < context_map_size || skip_preamble) { + if (!skip_preamble) { + if (!SafeReadSymbol(h->context_map_table, br, &code)) { + h->code = 0xFFFF; + h->context_index = context_index; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + BROTLI_LOG_UINT(code); + + if (code == 0) { + context_map[context_index++] = 0; + continue; + } + if (code > max_run_length_prefix) { + context_map[context_index++] = (uint8_t)(code - max_run_length_prefix); + continue; + } + } else { + skip_preamble = BROTLI_FALSE; + } + /* RLE sub-stage. */ + { + brotli_reg_t reps; + if (!BrotliSafeReadBits(br, code, &reps)) { + h->code = code; + h->context_index = context_index; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + reps += 1U << code; + BROTLI_LOG_UINT(reps); + if (context_index + reps > context_map_size) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT); + } + do { + context_map[context_index++] = 0; + } while (--reps); + } + } + } + /* Fall through. */ + + case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: { + brotli_reg_t bits; + if (!BrotliSafeReadBits(br, 1, &bits)) { + h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + if (bits != 0) { + InverseMoveToFrontTransform(*context_map_arg, context_map_size, s); + } + h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE; + return BROTLI_DECODER_SUCCESS; + } + + default: + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */ + } +} + +/* Decodes a command or literal and updates block type ring-buffer. + Reads 3..54 bits. */ +static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(int safe, BrotliDecoderState *s, int tree_type) { + brotli_reg_t max_block_type = s->num_block_types[tree_type]; + const HuffmanCode *type_tree = &s->block_type_trees[tree_type * BROTLI_HUFFMAN_MAX_SIZE_258]; + const HuffmanCode *len_tree = &s->block_len_trees[tree_type * BROTLI_HUFFMAN_MAX_SIZE_26]; + BrotliBitReader *br = &s->br; + brotli_reg_t *ringbuffer = &s->block_type_rb[tree_type * 2]; + brotli_reg_t block_type; + if (max_block_type <= 1) { + return BROTLI_FALSE; + } + + /* Read 0..15 + 3..39 bits. */ + if (!safe) { + block_type = ReadSymbol(type_tree, br); + s->block_length[tree_type] = ReadBlockLength(len_tree, br); + } else { + BrotliBitReaderState memento; + BrotliBitReaderSaveState(br, &memento); + if (!SafeReadSymbol(type_tree, br, &block_type)) + return BROTLI_FALSE; + if (!SafeReadBlockLength(s, &s->block_length[tree_type], len_tree, br)) { + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE; + BrotliBitReaderRestoreState(br, &memento); + return BROTLI_FALSE; + } + } + + if (block_type == 1) { + block_type = ringbuffer[1] + 1; + } else if (block_type == 0) { + block_type = ringbuffer[0]; + } else { + block_type -= 2; + } + if (block_type >= max_block_type) { + block_type -= max_block_type; + } + ringbuffer[0] = ringbuffer[1]; + ringbuffer[1] = block_type; + return BROTLI_TRUE; +} + +static BROTLI_INLINE void DetectTrivialLiteralBlockTypes(BrotliDecoderState *s) { + size_t i; + for (i = 0; i < 8; ++i) + s->trivial_literal_contexts[i] = 0; + for (i = 0; i < s->num_block_types[0]; i++) { + size_t offset = i << BROTLI_LITERAL_CONTEXT_BITS; + size_t error = 0; + size_t sample = s->context_map[offset]; + size_t j; + for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS);) { + /* NOLINTNEXTLINE(bugprone-macro-repeated-side-effects) */ + BROTLI_REPEAT_4({ error |= s->context_map[offset + j++] ^ sample; }) + } + if (error == 0) { + s->trivial_literal_contexts[i >> 5] |= 1u << (i & 31); + } + } +} + +static BROTLI_INLINE void PrepareLiteralDecoding(BrotliDecoderState *s) { + uint8_t context_mode; + size_t trivial; + brotli_reg_t block_type = s->block_type_rb[1]; + brotli_reg_t context_offset = block_type << BROTLI_LITERAL_CONTEXT_BITS; + s->context_map_slice = s->context_map + context_offset; + trivial = s->trivial_literal_contexts[block_type >> 5]; + s->trivial_literal_context = (trivial >> (block_type & 31)) & 1; + s->literal_htree = s->literal_hgroup.htrees[s->context_map_slice[0]]; + context_mode = s->context_modes[block_type] & 3; + s->context_lookup = BROTLI_CONTEXT_LUT(context_mode); +} + +/* Decodes the block type and updates the state for literal context. + Reads 3..54 bits. */ +static BROTLI_INLINE BROTLI_BOOL DecodeLiteralBlockSwitchInternal(int safe, BrotliDecoderState *s) { + if (!DecodeBlockTypeAndLength(safe, s, 0)) { + return BROTLI_FALSE; + } + PrepareLiteralDecoding(s); + return BROTLI_TRUE; +} + +static void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliDecoderState *s) { + DecodeLiteralBlockSwitchInternal(0, s); +} + +static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(BrotliDecoderState *s) { + return DecodeLiteralBlockSwitchInternal(1, s); +} + +/* Block switch for insert/copy length. + Reads 3..54 bits. */ +static BROTLI_INLINE BROTLI_BOOL DecodeCommandBlockSwitchInternal(int safe, BrotliDecoderState *s) { + if (!DecodeBlockTypeAndLength(safe, s, 1)) { + return BROTLI_FALSE; + } + s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]]; + return BROTLI_TRUE; +} + +static void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliDecoderState *s) { + DecodeCommandBlockSwitchInternal(0, s); +} + +static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(BrotliDecoderState *s) { + return DecodeCommandBlockSwitchInternal(1, s); +} + +/* Block switch for distance codes. + Reads 3..54 bits. */ +static BROTLI_INLINE BROTLI_BOOL DecodeDistanceBlockSwitchInternal(int safe, BrotliDecoderState *s) { + if (!DecodeBlockTypeAndLength(safe, s, 2)) { + return BROTLI_FALSE; + } + s->dist_context_map_slice = s->dist_context_map + (s->block_type_rb[5] << BROTLI_DISTANCE_CONTEXT_BITS); + s->dist_htree_index = s->dist_context_map_slice[s->distance_context]; + return BROTLI_TRUE; +} + +static void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliDecoderState *s) { + DecodeDistanceBlockSwitchInternal(0, s); +} + +static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(BrotliDecoderState *s) { + return DecodeDistanceBlockSwitchInternal(1, s); +} + +static size_t UnwrittenBytes(const BrotliDecoderState *s, BROTLI_BOOL wrap) { + size_t pos = wrap && s->pos > s->ringbuffer_size ? (size_t)s->ringbuffer_size : (size_t)(s->pos); + size_t partial_pos_rb = (s->rb_roundtrips * (size_t)s->ringbuffer_size) + pos; + return partial_pos_rb - s->partial_pos_out; +} + +/* Dumps output. + Returns BROTLI_DECODER_NEEDS_MORE_OUTPUT only if there is more output to push + and either ring-buffer is as big as window size, or |force| is true. */ +static BrotliDecoderErrorCode BROTLI_NOINLINE WriteRingBuffer(BrotliDecoderState *s, size_t *available_out, + uint8_t **next_out, size_t *total_out, + BROTLI_BOOL force) { + uint8_t *start = s->ringbuffer + (s->partial_pos_out & (size_t)s->ringbuffer_mask); + size_t to_write = UnwrittenBytes(s, BROTLI_TRUE); + size_t num_written = *available_out; + if (num_written > to_write) { + num_written = to_write; + } + if (s->meta_block_remaining_len < 0) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1); + } + if (next_out && !*next_out) { + *next_out = start; + } else { + if (next_out) { + memcpy(*next_out, start, num_written); + *next_out += num_written; + } + } + *available_out -= num_written; + BROTLI_LOG_UINT(to_write); + BROTLI_LOG_UINT(num_written); + s->partial_pos_out += num_written; + if (total_out) { + *total_out = s->partial_pos_out; + } + if (num_written < to_write) { + if (s->ringbuffer_size == (1 << s->window_bits) || force) { + return BROTLI_DECODER_NEEDS_MORE_OUTPUT; + } else { + return BROTLI_DECODER_SUCCESS; + } + } + /* Wrap ring buffer only if it has reached its maximal size. */ + if (s->ringbuffer_size == (1 << s->window_bits) && s->pos >= s->ringbuffer_size) { + s->pos -= s->ringbuffer_size; + s->rb_roundtrips++; + s->should_wrap_ringbuffer = (size_t)s->pos != 0 ? 1 : 0; + } + return BROTLI_DECODER_SUCCESS; +} + +static void BROTLI_NOINLINE WrapRingBuffer(BrotliDecoderState *s) { + if (s->should_wrap_ringbuffer) { + memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)s->pos); + s->should_wrap_ringbuffer = 0; + } +} + +/* Allocates ring-buffer. + + s->ringbuffer_size MUST be updated by BrotliCalculateRingBufferSize before + this function is called. + + Last two bytes of ring-buffer are initialized to 0, so context calculation + could be done uniformly for the first two and all other positions. */ +static BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(BrotliDecoderState *s) { + uint8_t *old_ringbuffer = s->ringbuffer; + if (s->ringbuffer_size == s->new_ringbuffer_size) { + return BROTLI_TRUE; + } + + s->ringbuffer = (uint8_t *)BROTLI_DECODER_ALLOC(s, (size_t)(s->new_ringbuffer_size) + kRingBufferWriteAheadSlack); + if (s->ringbuffer == 0) { + /* Restore previous value. */ + s->ringbuffer = old_ringbuffer; + return BROTLI_FALSE; + } + s->ringbuffer[s->new_ringbuffer_size - 2] = 0; + s->ringbuffer[s->new_ringbuffer_size - 1] = 0; + + if (!!old_ringbuffer) { + memcpy(s->ringbuffer, old_ringbuffer, (size_t)s->pos); + BROTLI_DECODER_FREE(s, old_ringbuffer); + } + + s->ringbuffer_size = s->new_ringbuffer_size; + s->ringbuffer_mask = s->new_ringbuffer_size - 1; + s->ringbuffer_end = s->ringbuffer + s->ringbuffer_size; + + return BROTLI_TRUE; +} + +static BrotliDecoderErrorCode BROTLI_NOINLINE SkipMetadataBlock(BrotliDecoderState *s) { + BrotliBitReader *br = &s->br; + + if (s->meta_block_remaining_len == 0) { + return BROTLI_DECODER_SUCCESS; + } + + BROTLI_DCHECK((BrotliGetAvailableBits(br) & 7) == 0); + + /* Drain accumulator. */ + if (BrotliGetAvailableBits(br) >= 8) { + uint8_t buffer[8]; + int nbytes = (int)(BrotliGetAvailableBits(br)) >> 3; + BROTLI_DCHECK(nbytes <= 8); + if (nbytes > s->meta_block_remaining_len) { + nbytes = s->meta_block_remaining_len; + } + BrotliCopyBytes(buffer, br, (size_t)nbytes); + if (s->metadata_chunk_func) { + s->metadata_chunk_func(s->metadata_callback_opaque, buffer, (size_t)nbytes); + } + s->meta_block_remaining_len -= nbytes; + if (s->meta_block_remaining_len == 0) { + return BROTLI_DECODER_SUCCESS; + } + } + + /* Direct access to metadata is possible. */ + int nbytes = (int)BrotliGetRemainingBytes(br); + if (nbytes > s->meta_block_remaining_len) { + nbytes = s->meta_block_remaining_len; + } + if (nbytes > 0) { + if (s->metadata_chunk_func) { + s->metadata_chunk_func(s->metadata_callback_opaque, br->next_in, (size_t)nbytes); + } + BrotliDropBytes(br, (size_t)nbytes); + s->meta_block_remaining_len -= nbytes; + if (s->meta_block_remaining_len == 0) { + return BROTLI_DECODER_SUCCESS; + } + } + + BROTLI_DCHECK(BrotliGetRemainingBytes(br) == 0); + + return BROTLI_DECODER_NEEDS_MORE_INPUT; +} + +static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(size_t *available_out, uint8_t **next_out, + size_t *total_out, BrotliDecoderState *s) { + /* TODO(eustas): avoid allocation for single uncompressed block. */ + if (!BrotliEnsureRingBuffer(s)) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1); + } + + /* State machine */ + for (;;) { + switch (s->substate_uncompressed) { + case BROTLI_STATE_UNCOMPRESSED_NONE: { + int nbytes = (int)BrotliGetRemainingBytes(&s->br); + if (nbytes > s->meta_block_remaining_len) { + nbytes = s->meta_block_remaining_len; + } + if (s->pos + nbytes > s->ringbuffer_size) { + nbytes = s->ringbuffer_size - s->pos; + } + /* Copy remaining bytes from s->br.buf_ to ring-buffer. */ + BrotliCopyBytes(&s->ringbuffer[s->pos], &s->br, (size_t)nbytes); + s->pos += nbytes; + s->meta_block_remaining_len -= nbytes; + if (s->pos < 1 << s->window_bits) { + if (s->meta_block_remaining_len == 0) { + return BROTLI_DECODER_SUCCESS; + } + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE; + } + /* Fall through. */ + + case BROTLI_STATE_UNCOMPRESSED_WRITE: { + BrotliDecoderErrorCode result; + result = WriteRingBuffer(s, available_out, next_out, total_out, BROTLI_FALSE); + if (result != BROTLI_DECODER_SUCCESS) { + return result; + } + if (s->ringbuffer_size == 1 << s->window_bits) { + s->max_distance = s->max_backward_distance; + } + s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE; + break; + } + } + } + BROTLI_DCHECK(0); /* Unreachable */ +} + +static BROTLI_BOOL AttachCompoundDictionary(BrotliDecoderState *state, const uint8_t *data, size_t size) { + BrotliDecoderCompoundDictionary *addon = state->compound_dictionary; + if (state->state != BROTLI_STATE_UNINITED) + return BROTLI_FALSE; + if (!addon) { + addon = (BrotliDecoderCompoundDictionary *)BROTLI_DECODER_ALLOC(state, sizeof(BrotliDecoderCompoundDictionary)); + if (!addon) + return BROTLI_FALSE; + addon->num_chunks = 0; + addon->total_size = 0; + addon->br_length = 0; + addon->br_copied = 0; + addon->block_bits = -1; + addon->chunk_offsets[0] = 0; + state->compound_dictionary = addon; + } + if (addon->num_chunks == 15) + return BROTLI_FALSE; + addon->chunks[addon->num_chunks] = data; + addon->num_chunks++; + addon->total_size += (int)size; + addon->chunk_offsets[addon->num_chunks] = addon->total_size; + return BROTLI_TRUE; +} + +static void EnsureCoumpoundDictionaryInitialized(BrotliDecoderState *state) { + BrotliDecoderCompoundDictionary *addon = state->compound_dictionary; + /* 256 = (1 << 8) slots in block map. */ + int block_bits = 8; + int cursor = 0; + int index = 0; + if (addon->block_bits != -1) + return; + while (((addon->total_size - 1) >> block_bits) != 0) + block_bits++; + block_bits -= 8; + addon->block_bits = block_bits; + while (cursor < addon->total_size) { + while (addon->chunk_offsets[index + 1] < cursor) + index++; + addon->block_map[cursor >> block_bits] = (uint8_t)index; + cursor += 1 << block_bits; + } +} + +static BROTLI_BOOL InitializeCompoundDictionaryCopy(BrotliDecoderState *s, int address, int length) { + BrotliDecoderCompoundDictionary *addon = s->compound_dictionary; + int index; + EnsureCoumpoundDictionaryInitialized(s); + index = addon->block_map[address >> addon->block_bits]; + while (address >= addon->chunk_offsets[index + 1]) + index++; + if (addon->total_size < address + length) + return BROTLI_FALSE; + /* Update the recent distances cache. */ + s->dist_rb[s->dist_rb_idx & 3] = s->distance_code; + ++s->dist_rb_idx; + s->meta_block_remaining_len -= length; + addon->br_index = index; + addon->br_offset = address - addon->chunk_offsets[index]; + addon->br_length = length; + addon->br_copied = 0; + return BROTLI_TRUE; +} + +static int GetCompoundDictionarySize(BrotliDecoderState *s) { + return s->compound_dictionary ? s->compound_dictionary->total_size : 0; +} + +static int CopyFromCompoundDictionary(BrotliDecoderState *s, int pos) { + BrotliDecoderCompoundDictionary *addon = s->compound_dictionary; + int orig_pos = pos; + while (addon->br_length != addon->br_copied) { + uint8_t *copy_dst = &s->ringbuffer[pos]; + const uint8_t *copy_src = addon->chunks[addon->br_index] + addon->br_offset; + int space = s->ringbuffer_size - pos; + int rem_chunk_length = + (addon->chunk_offsets[addon->br_index + 1] - addon->chunk_offsets[addon->br_index]) - addon->br_offset; + int length = addon->br_length - addon->br_copied; + if (length > rem_chunk_length) + length = rem_chunk_length; + if (length > space) + length = space; + memcpy(copy_dst, copy_src, (size_t)length); + pos += length; + addon->br_offset += length; + addon->br_copied += length; + if (length == rem_chunk_length) { + addon->br_index++; + addon->br_offset = 0; + } + if (pos == s->ringbuffer_size) + break; + } + return pos - orig_pos; +} + +BROTLI_BOOL BrotliDecoderAttachDictionary(BrotliDecoderState *state, BrotliSharedDictionaryType type, size_t data_size, + const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) { + brotli_reg_t i; + brotli_reg_t num_prefix_before = state->dictionary->num_prefix; + if (state->state != BROTLI_STATE_UNINITED) + return BROTLI_FALSE; + if (!BrotliSharedDictionaryAttach(state->dictionary, type, data_size, data)) { + return BROTLI_FALSE; + } + for (i = num_prefix_before; i < state->dictionary->num_prefix; i++) { + if (!AttachCompoundDictionary(state, state->dictionary->prefix[i], state->dictionary->prefix_size[i])) { + return BROTLI_FALSE; + } + } + return BROTLI_TRUE; +} + +/* Calculates the smallest feasible ring buffer. + + If we know the data size is small, do not allocate more ring buffer + size than needed to reduce memory usage. + + When this method is called, metablock size and flags MUST be decoded. */ +static void BROTLI_NOINLINE BrotliCalculateRingBufferSize(BrotliDecoderState *s) { + int window_size = 1 << s->window_bits; + int new_ringbuffer_size = window_size; + /* We need at least 2 bytes of ring buffer size to get the last two + bytes for context from there */ + int min_size = s->ringbuffer_size ? s->ringbuffer_size : 1024; + int output_size; + + /* If maximum is already reached, no further extension is retired. */ + if (s->ringbuffer_size == window_size) { + return; + } + + /* Metadata blocks does not touch ring buffer. */ + if (s->is_metadata) { + return; + } + + if (!s->ringbuffer) { + output_size = 0; + } else { + output_size = s->pos; + } + output_size += s->meta_block_remaining_len; + min_size = min_size < output_size ? output_size : min_size; + + if (!!s->canny_ringbuffer_allocation) { + /* Reduce ring buffer size to save memory when server is unscrupulous. + In worst case memory usage might be 1.5x bigger for a short period of + ring buffer reallocation. */ + while ((new_ringbuffer_size >> 1) >= min_size) { + new_ringbuffer_size >>= 1; + } + } + + s->new_ringbuffer_size = new_ringbuffer_size; +} + +/* Reads 1..256 2-bit context modes. */ +static BrotliDecoderErrorCode ReadContextModes(BrotliDecoderState *s) { + BrotliBitReader *br = &s->br; + int i = s->loop_counter; + + while (i < (int)s->num_block_types[0]) { + brotli_reg_t bits; + if (!BrotliSafeReadBits(br, 2, &bits)) { + s->loop_counter = i; + return BROTLI_DECODER_NEEDS_MORE_INPUT; + } + s->context_modes[i] = (uint8_t)bits; + BROTLI_LOG_ARRAY_INDEX(s->context_modes, i); + i++; + } + return BROTLI_DECODER_SUCCESS; +} + +static BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliDecoderState *s) { + int offset = s->distance_code - 3; + if (s->distance_code <= 3) { + /* Compensate double distance-ring-buffer roll for dictionary items. */ + s->distance_context = 1 >> s->distance_code; + s->distance_code = s->dist_rb[(s->dist_rb_idx - offset) & 3]; + s->dist_rb_idx -= s->distance_context; + } else { + int index_delta = 3; + int delta; + int base = s->distance_code - 10; + if (s->distance_code < 10) { + base = s->distance_code - 4; + } else { + index_delta = 2; + } + /* Unpack one of six 4-bit values. */ + delta = ((0x605142 >> (4 * base)) & 0xF) - 3; + s->distance_code = s->dist_rb[(s->dist_rb_idx + index_delta) & 0x3] + delta; + if (s->distance_code <= 0) { + /* A huge distance will cause a BROTLI_FAILURE() soon. + This is a little faster than failing here. */ + s->distance_code = 0x7FFFFFFF; + } + } +} + +static BROTLI_INLINE BROTLI_BOOL SafeReadBits(BrotliBitReader *const br, brotli_reg_t n_bits, brotli_reg_t *val) { + if (n_bits != 0) { + return BrotliSafeReadBits(br, n_bits, val); + } else { + *val = 0; + return BROTLI_TRUE; + } +} + +static BROTLI_INLINE BROTLI_BOOL SafeReadBits32(BrotliBitReader *const br, brotli_reg_t n_bits, brotli_reg_t *val) { + if (n_bits != 0) { + return BrotliSafeReadBits32(br, n_bits, val); + } else { + *val = 0; + return BROTLI_TRUE; + } +} + +/* + RFC 7932 Section 4 with "..." shortenings and "[]" emendations. + + Each distance ... is represented with a pair ... + The distance code is encoded using a prefix code... The number of extra bits + can be 0..24... Two additional parameters: NPOSTFIX (0..3), and ... + NDIRECT (0..120) ... are encoded in the meta-block header... + + The first 16 distance symbols ... reference past distances... ring buffer ... + Next NDIRECT distance symbols ... represent distances from 1 to NDIRECT... + [For] distance symbols 16 + NDIRECT and greater ... the number of extra bits + ... is given by the following formula: + + [ xcode = dcode - NDIRECT - 16 ] + ndistbits = 1 + [ xcode ] >> (NPOSTFIX + 1) + + ... +*/ + +/* + RFC 7932 Section 9.2 with "..." shortenings and "[]" emendations. + + ... to get the actual value of the parameter NDIRECT, left-shift this + four-bit number by NPOSTFIX bits ... +*/ + +/* Remaining formulas from RFC 7932 Section 4 could be rewritten as following: + + alphabet_size = 16 + NDIRECT + (max_distbits << (NPOSTFIX + 1)) + + half = ((xcode >> NPOSTFIX) & 1) << ndistbits + postfix = xcode & ((1 << NPOSTFIX) - 1) + range_start = 2 * (1 << ndistbits - 1 - 1) + + distance = (range_start + half + extra) << NPOSTFIX + postfix + NDIRECT + 1 + + NB: ndistbits >= 1 -> range_start >= 0 + NB: range_start has factor 2, as the range is covered by 2 "halves" + NB: extra -1 offset in range_start formula covers the absence of + ndistbits = 0 case + NB: when NPOSTFIX = 0, NDIRECT is not greater than 15 + + In other words, xcode has the following binary structure - XXXHPPP: + - XXX represent the number of extra distance bits + - H selects upper / lower range of distances + - PPP represent "postfix" + + "Regular" distance encoding has NPOSTFIX = 0; omitting the postfix part + simplifies distance calculation. + + Using NPOSTFIX > 0 allows cheaper encoding of regular structures, e.g. where + most of distances have the same reminder of division by 2/4/8. For example, + the table of int32_t values that come from different sources; if it is likely + that 3 highest bytes of values from the same source are the same, then + copy distance often looks like 4x + y. + + Distance calculation could be rewritten to: + + ndistbits = NDISTBITS(NDIRECT, NPOSTFIX)[dcode] + distance = OFFSET(NDIRECT, NPOSTFIX)[dcode] + extra << NPOSTFIX + + NDISTBITS and OFFSET could be pre-calculated, as NDIRECT and NPOSTFIX could + change only once per meta-block. +*/ + +/* Calculates distance lookup table. + NB: it is possible to have all 64 tables precalculated. */ +static void CalculateDistanceLut(BrotliDecoderState *s) { + BrotliMetablockBodyArena *b = &s->arena.body; + brotli_reg_t npostfix = s->distance_postfix_bits; + brotli_reg_t ndirect = s->num_direct_distance_codes; + brotli_reg_t alphabet_size_limit = s->distance_hgroup.alphabet_size_limit; + brotli_reg_t postfix = 1u << npostfix; + brotli_reg_t j; + brotli_reg_t bits = 1; + brotli_reg_t half = 0; + + /* Skip short codes. */ + brotli_reg_t i = BROTLI_NUM_DISTANCE_SHORT_CODES; + + /* Fill direct codes. */ + for (j = 0; j < ndirect; ++j) { + b->dist_extra_bits[i] = 0; + b->dist_offset[i] = j + 1; + ++i; + } + + /* Fill regular distance codes. */ + while (i < alphabet_size_limit) { + brotli_reg_t base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1; + /* Always fill the complete group. */ + for (j = 0; j < postfix; ++j) { + b->dist_extra_bits[i] = (uint8_t)bits; + b->dist_offset[i] = base + j; + ++i; + } + bits = bits + half; + half = half ^ 1; + } +} + +/* Precondition: s->distance_code < 0. */ +static BROTLI_INLINE BROTLI_BOOL ReadDistanceInternal(int safe, BrotliDecoderState *s, BrotliBitReader *br) { + BrotliMetablockBodyArena *b = &s->arena.body; + brotli_reg_t code; + brotli_reg_t bits; + BrotliBitReaderState memento; + HuffmanCode *distance_tree = s->distance_hgroup.htrees[s->dist_htree_index]; + if (!safe) { + code = ReadSymbol(distance_tree, br); + } else { + BrotliBitReaderSaveState(br, &memento); + if (!SafeReadSymbol(distance_tree, br, &code)) { + return BROTLI_FALSE; + } + } + --s->block_length[2]; + /* Convert the distance code to the actual distance by possibly + looking up past distances from the s->dist_rb. */ + s->distance_context = 0; + if ((code & ~0xFu) == 0) { + s->distance_code = (int)code; + TakeDistanceFromRingBuffer(s); + return BROTLI_TRUE; + } + if (!safe) { + bits = BrotliReadBits32(br, b->dist_extra_bits[code]); + } else { + if (!SafeReadBits32(br, b->dist_extra_bits[code], &bits)) { + ++s->block_length[2]; + BrotliBitReaderRestoreState(br, &memento); + return BROTLI_FALSE; + } + } + s->distance_code = (int)(b->dist_offset[code] + (bits << s->distance_postfix_bits)); + return BROTLI_TRUE; +} + +static BROTLI_INLINE void ReadDistance(BrotliDecoderState *s, BrotliBitReader *br) { + ReadDistanceInternal(0, s, br); +} + +static BROTLI_INLINE BROTLI_BOOL SafeReadDistance(BrotliDecoderState *s, BrotliBitReader *br) { + return ReadDistanceInternal(1, s, br); +} + +static BROTLI_INLINE BROTLI_BOOL ReadCommandInternal(int safe, BrotliDecoderState *s, BrotliBitReader *br, + int *insert_length) { + brotli_reg_t cmd_code; + brotli_reg_t insert_len_extra = 0; + brotli_reg_t copy_length; + CmdLutElement v; + BrotliBitReaderState memento; + if (!safe) { + cmd_code = ReadSymbol(s->htree_command, br); + } else { + BrotliBitReaderSaveState(br, &memento); + if (!SafeReadSymbol(s->htree_command, br, &cmd_code)) { + return BROTLI_FALSE; + } + } + v = kCmdLut[cmd_code]; + s->distance_code = v.distance_code; + s->distance_context = v.context; + s->dist_htree_index = s->dist_context_map_slice[s->distance_context]; + *insert_length = v.insert_len_offset; + if (!safe) { + if (BROTLI_PREDICT_FALSE(v.insert_len_extra_bits != 0)) { + insert_len_extra = BrotliReadBits24(br, v.insert_len_extra_bits); + } + copy_length = BrotliReadBits24(br, v.copy_len_extra_bits); + } else { + if (!SafeReadBits(br, v.insert_len_extra_bits, &insert_len_extra) || + !SafeReadBits(br, v.copy_len_extra_bits, ©_length)) { + BrotliBitReaderRestoreState(br, &memento); + return BROTLI_FALSE; + } + } + s->copy_length = (int)copy_length + v.copy_len_offset; + --s->block_length[1]; + *insert_length += (int)insert_len_extra; + return BROTLI_TRUE; +} + +static BROTLI_INLINE void ReadCommand(BrotliDecoderState *s, BrotliBitReader *br, int *insert_length) { + ReadCommandInternal(0, s, br, insert_length); +} + +static BROTLI_INLINE BROTLI_BOOL SafeReadCommand(BrotliDecoderState *s, BrotliBitReader *br, int *insert_length) { + return ReadCommandInternal(1, s, br, insert_length); +} + +static BROTLI_INLINE BROTLI_BOOL CheckInputAmount(int safe, BrotliBitReader *const br) { + if (safe) { + return BROTLI_TRUE; + } + return BrotliCheckInputAmount(br); +} + +#define BROTLI_SAFE(METHOD) \ + { \ + if (safe) { \ + if (!Safe##METHOD) { \ + result = BROTLI_DECODER_NEEDS_MORE_INPUT; \ + goto saveStateAndReturn; \ + } \ + } else { \ + METHOD; \ + } \ + } + +static BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(int safe, BrotliDecoderState *s) { + int pos = s->pos; + int i = s->loop_counter; + BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS; + BrotliBitReader *br = &s->br; + int compound_dictionary_size = GetCompoundDictionarySize(s); + + if (!CheckInputAmount(safe, br)) { + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + if (!safe) { + BROTLI_UNUSED(BrotliWarmupBitReader(br)); + } + + /* Jump into state machine. */ + if (s->state == BROTLI_STATE_COMMAND_BEGIN) { + goto CommandBegin; + } else if (s->state == BROTLI_STATE_COMMAND_INNER) { + goto CommandInner; + } else if (s->state == BROTLI_STATE_COMMAND_POST_DECODE_LITERALS) { + goto CommandPostDecodeLiterals; + } else if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) { + goto CommandPostWrapCopy; + } else { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */ + } + +CommandBegin: + if (safe) { + s->state = BROTLI_STATE_COMMAND_BEGIN; + } + if (!CheckInputAmount(safe, br)) { + s->state = BROTLI_STATE_COMMAND_BEGIN; + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + if (BROTLI_PREDICT_FALSE(s->block_length[1] == 0)) { + BROTLI_SAFE(DecodeCommandBlockSwitch(s)); + goto CommandBegin; + } + /* Read the insert/copy length in the command. */ + BROTLI_SAFE(ReadCommand(s, br, &i)); + BROTLI_LOG(("[ProcessCommandsInternal] pos = %d insert = %d copy = %d\n", pos, i, s->copy_length)); + if (i == 0) { + goto CommandPostDecodeLiterals; + } + s->meta_block_remaining_len -= i; + +CommandInner: + if (safe) { + s->state = BROTLI_STATE_COMMAND_INNER; + } + /* Read the literals in the command. */ + if (s->trivial_literal_context) { + brotli_reg_t bits; + brotli_reg_t value; + PreloadSymbol(safe, s->literal_htree, br, &bits, &value); + do { + if (!CheckInputAmount(safe, br)) { + s->state = BROTLI_STATE_COMMAND_INNER; + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) { + goto NextLiteralBlock; + } + if (!safe) { + s->ringbuffer[pos] = (uint8_t)ReadPreloadedSymbol(s->literal_htree, br, &bits, &value); + } else { + brotli_reg_t literal; + if (!SafeReadSymbol(s->literal_htree, br, &literal)) { + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + s->ringbuffer[pos] = (uint8_t)literal; + } + --s->block_length[0]; + BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos); + ++pos; + if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) { + s->state = BROTLI_STATE_COMMAND_INNER_WRITE; + --i; + goto saveStateAndReturn; + } + } while (--i != 0); + } else { + uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask]; + uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask]; + do { + const HuffmanCode *hc; + uint8_t context; + if (!CheckInputAmount(safe, br)) { + s->state = BROTLI_STATE_COMMAND_INNER; + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) { + goto NextLiteralBlock; + } + context = BROTLI_CONTEXT(p1, p2, s->context_lookup); + BROTLI_LOG_UINT(context); + hc = s->literal_hgroup.htrees[s->context_map_slice[context]]; + p2 = p1; + if (!safe) { + p1 = (uint8_t)ReadSymbol(hc, br); + } else { + brotli_reg_t literal; + if (!SafeReadSymbol(hc, br, &literal)) { + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + p1 = (uint8_t)literal; + } + s->ringbuffer[pos] = p1; + --s->block_length[0]; + BROTLI_LOG_UINT(s->context_map_slice[context]); + BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask); + ++pos; + if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) { + s->state = BROTLI_STATE_COMMAND_INNER_WRITE; + --i; + goto saveStateAndReturn; + } + } while (--i != 0); + } + BROTLI_LOG_UINT(s->meta_block_remaining_len); + if (BROTLI_PREDICT_FALSE(s->meta_block_remaining_len <= 0)) { + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } + +CommandPostDecodeLiterals: + if (safe) { + s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS; + } + if (s->distance_code >= 0) { + /* Implicit distance case. */ + s->distance_context = s->distance_code ? 0 : 1; + --s->dist_rb_idx; + s->distance_code = s->dist_rb[s->dist_rb_idx & 3]; + } else { + /* Read distance code in the command, unless it was implicitly zero. */ + if (BROTLI_PREDICT_FALSE(s->block_length[2] == 0)) { + BROTLI_SAFE(DecodeDistanceBlockSwitch(s)); + } + BROTLI_SAFE(ReadDistance(s, br)); + } + BROTLI_LOG(("[ProcessCommandsInternal] pos = %d distance = %d\n", pos, s->distance_code)); + if (s->max_distance != s->max_backward_distance) { + s->max_distance = (pos < s->max_backward_distance) ? pos : s->max_backward_distance; + } + i = s->copy_length; + /* Apply copy of LZ77 back-reference, or static dictionary reference if + the distance is larger than the max LZ77 distance */ + if (s->distance_code > s->max_distance) { + /* The maximum allowed distance is BROTLI_MAX_ALLOWED_DISTANCE = 0x7FFFFFFC. + With this choice, no signed overflow can occur after decoding + a special distance code (e.g., after adding 3 to the last distance). */ + if (s->distance_code > BROTLI_MAX_ALLOWED_DISTANCE) { + BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", + pos, s->distance_code, i, s->meta_block_remaining_len)); + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DISTANCE); + } + if (s->distance_code - s->max_distance - 1 < compound_dictionary_size) { + int address = compound_dictionary_size - (s->distance_code - s->max_distance); + if (!InitializeCompoundDictionaryCopy(s, address, i)) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY); + } + pos += CopyFromCompoundDictionary(s, pos); + if (pos >= s->ringbuffer_size) { + s->state = BROTLI_STATE_COMMAND_POST_WRITE_1; + goto saveStateAndReturn; + } + } else if (i >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH && i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH) { + uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask]; + uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask]; + uint8_t dict_id = s->dictionary->context_based + ? s->dictionary->context_map[BROTLI_CONTEXT(p1, p2, s->context_lookup)] + : 0; + const BrotliDictionary *words = s->dictionary->words[dict_id]; + const BrotliTransforms *transforms = s->dictionary->transforms[dict_id]; + int offset = (int)words->offsets_by_length[i]; + brotli_reg_t shift = words->size_bits_by_length[i]; + int address = s->distance_code - s->max_distance - 1 - compound_dictionary_size; + int mask = (int)BitMask(shift); + int word_idx = address & mask; + int transform_idx = address >> shift; + /* Compensate double distance-ring-buffer roll. */ + s->dist_rb_idx += s->distance_context; + offset += word_idx * i; + /* If the distance is out of bound, select a next static dictionary if + there exist multiple. */ + if ((transform_idx >= (int)transforms->num_transforms || words->size_bits_by_length[i] == 0) && + s->dictionary->num_dictionaries > 1) { + uint8_t dict_id2; + int dist_remaining = address - (int)(((1u << shift) & ~1u)) * (int)transforms->num_transforms; + for (dict_id2 = 0; dict_id2 < s->dictionary->num_dictionaries; dict_id2++) { + const BrotliDictionary *words2 = s->dictionary->words[dict_id2]; + if (dict_id2 != dict_id && words2->size_bits_by_length[i] != 0) { + const BrotliTransforms *transforms2 = s->dictionary->transforms[dict_id2]; + brotli_reg_t shift2 = words2->size_bits_by_length[i]; + int num = (int)((1u << shift2) & ~1u) * (int)transforms2->num_transforms; + if (dist_remaining < num) { + dict_id = dict_id2; + words = words2; + transforms = transforms2; + address = dist_remaining; + shift = shift2; + mask = (int)BitMask(shift); + word_idx = address & mask; + transform_idx = address >> shift; + offset = (int)words->offsets_by_length[i] + word_idx * i; + break; + } + dist_remaining -= num; + } + } + } + if (BROTLI_PREDICT_FALSE(words->size_bits_by_length[i] == 0)) { + BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", + pos, s->distance_code, i, s->meta_block_remaining_len)); + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DICTIONARY); + } + if (BROTLI_PREDICT_FALSE(!words->data)) { + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET); + } + if (transform_idx < (int)transforms->num_transforms) { + const uint8_t *word = &words->data[offset]; + int len = i; + if (transform_idx == transforms->cutOffTransforms[0]) { + memcpy(&s->ringbuffer[pos], word, (size_t)len); + BROTLI_LOG(("[ProcessCommandsInternal] dictionary word: [%.*s]\n", len, word)); + } else { + len = BrotliTransformDictionaryWord(&s->ringbuffer[pos], word, len, transforms, transform_idx); + BROTLI_LOG(("[ProcessCommandsInternal] dictionary word: [%.*s]," + " transform_idx = %d, transformed: [%.*s]\n", + i, word, transform_idx, len, &s->ringbuffer[pos])); + if (len == 0 && s->distance_code <= 120) { + BROTLI_LOG(("Invalid length-0 dictionary word after transform\n")); + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_TRANSFORM); + } + } + pos += len; + s->meta_block_remaining_len -= len; + if (pos >= s->ringbuffer_size) { + s->state = BROTLI_STATE_COMMAND_POST_WRITE_1; + goto saveStateAndReturn; + } + } else { + BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", + pos, s->distance_code, i, s->meta_block_remaining_len)); + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_TRANSFORM); + } + } else { + BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", + pos, s->distance_code, i, s->meta_block_remaining_len)); + return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DICTIONARY); + } + } else { + int src_start = (pos - s->distance_code) & s->ringbuffer_mask; + uint8_t *copy_dst = &s->ringbuffer[pos]; + uint8_t *copy_src = &s->ringbuffer[src_start]; + int dst_end = pos + i; + int src_end = src_start + i; + /* Update the recent distances cache. */ + s->dist_rb[s->dist_rb_idx & 3] = s->distance_code; + ++s->dist_rb_idx; + s->meta_block_remaining_len -= i; + /* There are 32+ bytes of slack in the ring-buffer allocation. + Also, we have 16 short codes, that make these 16 bytes irrelevant + in the ring-buffer. Let's copy over them as a first guess. */ + memmove16(copy_dst, copy_src); + if (src_end > pos && dst_end > src_start) { + /* Regions intersect. */ + goto CommandPostWrapCopy; + } + if (dst_end >= s->ringbuffer_size || src_end >= s->ringbuffer_size) { + /* At least one region wraps. */ + goto CommandPostWrapCopy; + } + pos += i; + if (i > 16) { + if (i > 32) { + memcpy(copy_dst + 16, copy_src + 16, (size_t)(i - 16)); + } else { + /* This branch covers about 45% cases. + Fixed size short copy allows more compiler optimizations. */ + memmove16(copy_dst + 16, copy_src + 16); + } + } + } + BROTLI_LOG_UINT(s->meta_block_remaining_len); + if (s->meta_block_remaining_len <= 0) { + /* Next metablock, if any. */ + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } else { + goto CommandBegin; + } +CommandPostWrapCopy: { + int wrap_guard = s->ringbuffer_size - pos; + while (--i >= 0) { + s->ringbuffer[pos] = s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; + ++pos; + if (BROTLI_PREDICT_FALSE(--wrap_guard == 0)) { + s->state = BROTLI_STATE_COMMAND_POST_WRITE_2; + goto saveStateAndReturn; + } + } +} + if (s->meta_block_remaining_len <= 0) { + /* Next metablock, if any. */ + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } else { + goto CommandBegin; + } + +NextLiteralBlock: + BROTLI_SAFE(DecodeLiteralBlockSwitch(s)); + goto CommandInner; + +saveStateAndReturn: + s->pos = pos; + s->loop_counter = i; + return result; +} + +#undef BROTLI_SAFE + +static BROTLI_NOINLINE BrotliDecoderErrorCode ProcessCommands(BrotliDecoderState *s) { + return ProcessCommandsInternal(0, s); +} + +static BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands(BrotliDecoderState *s) { + return ProcessCommandsInternal(1, s); +} + +BrotliDecoderResult BrotliDecoderDecompress(size_t encoded_size, + const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)], + size_t *decoded_size, + uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]) { + BrotliDecoderState s; + BrotliDecoderResult result; + size_t total_out = 0; + size_t available_in = encoded_size; + const uint8_t *next_in = encoded_buffer; + size_t available_out = *decoded_size; + uint8_t *next_out = decoded_buffer; + if (!BrotliDecoderStateInit(&s, 0, 0, 0)) { + return BROTLI_DECODER_RESULT_ERROR; + } + result = BrotliDecoderDecompressStream(&s, &available_in, &next_in, &available_out, &next_out, &total_out); + *decoded_size = total_out; + BrotliDecoderStateCleanup(&s); + if (result != BROTLI_DECODER_RESULT_SUCCESS) { + result = BROTLI_DECODER_RESULT_ERROR; + } + return result; +} + +/* Invariant: input stream is never overconsumed: + - invalid input implies that the whole stream is invalid -> any amount of + input could be read and discarded + - when result is "needs more input", then at least one more byte is REQUIRED + to complete decoding; all input data MUST be consumed by decoder, so + client could swap the input buffer + - when result is "needs more output" decoder MUST ensure that it doesn't + hold more than 7 bits in bit reader; this saves client from swapping input + buffer ahead of time + - when result is "success" decoder MUST return all unused data back to input + buffer; this is possible because the invariant is held on enter */ +BrotliDecoderResult BrotliDecoderDecompressStream(BrotliDecoderState *s, size_t *available_in, const uint8_t **next_in, + size_t *available_out, uint8_t **next_out, size_t *total_out) { + BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS; + BrotliBitReader *br = &s->br; + size_t input_size = *available_in; +#define BROTLI_SAVE_ERROR_CODE(code) SaveErrorCode(s, (code), input_size - *available_in) + /* Ensure that |total_out| is set, even if no data will ever be pushed out. */ + if (total_out) { + *total_out = s->partial_pos_out; + } + /* Do not try to process further in a case of unrecoverable error. */ + if ((int)s->error_code < 0) { + return BROTLI_DECODER_RESULT_ERROR; + } + if (*available_out && (!next_out || !*next_out)) { + return BROTLI_SAVE_ERROR_CODE(BROTLI_FAILURE(BROTLI_DECODER_ERROR_INVALID_ARGUMENTS)); + } + if (!*available_out) + next_out = 0; + if (s->buffer_length == 0) { /* Just connect bit reader to input stream. */ + BrotliBitReaderSetInput(br, *next_in, *available_in); + } else { + /* At least one byte of input is required. More than one byte of input may + be required to complete the transaction -> reading more data must be + done in a loop -> do it in a main loop. */ + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + BrotliBitReaderSetInput(br, &s->buffer.u8[0], s->buffer_length); + } + /* State machine */ + for (;;) { + if (result != BROTLI_DECODER_SUCCESS) { + /* Error, needs more input/output. */ + if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) { + if (s->ringbuffer != 0) { /* Pro-actively push output. */ + BrotliDecoderErrorCode intermediate_result = + WriteRingBuffer(s, available_out, next_out, total_out, BROTLI_TRUE); + /* WriteRingBuffer checks s->meta_block_remaining_len validity. */ + if ((int)intermediate_result < 0) { + result = intermediate_result; + break; + } + } + if (s->buffer_length != 0) { /* Used with internal buffer. */ + if (br->next_in == br->last_in) { + /* Successfully finished read transaction. + Accumulator contains less than 8 bits, because internal buffer + is expanded byte-by-byte until it is enough to complete read. */ + s->buffer_length = 0; + /* Switch to input stream and restart. */ + result = BROTLI_DECODER_SUCCESS; + BrotliBitReaderSetInput(br, *next_in, *available_in); + continue; + } else if (*available_in != 0) { + /* Not enough data in buffer, but can take one more byte from + input stream. */ + result = BROTLI_DECODER_SUCCESS; + BROTLI_DCHECK(s->buffer_length < 8); + s->buffer.u8[s->buffer_length] = **next_in; + s->buffer_length++; + BrotliBitReaderSetInput(br, &s->buffer.u8[0], s->buffer_length); + (*next_in)++; + (*available_in)--; + /* Retry with more data in buffer. */ + continue; + } + /* Can't finish reading and no more input. */ + break; + } else { /* Input stream doesn't contain enough input. */ + /* Copy tail to internal buffer and return. */ + *next_in = br->next_in; + *available_in = BrotliBitReaderGetAvailIn(br); + while (*available_in) { + s->buffer.u8[s->buffer_length] = **next_in; + s->buffer_length++; + (*next_in)++; + (*available_in)--; + } + break; + } + /* Unreachable. */ + } + + /* Fail or needs more output. */ + + if (s->buffer_length != 0) { + /* Just consumed the buffered input and produced some output. Otherwise + it would result in "needs more input". Reset internal buffer. */ + s->buffer_length = 0; + } else { + /* Using input stream in last iteration. When decoder switches to input + stream it has less than 8 bits in accumulator, so it is safe to + return unused accumulator bits there. */ + BrotliBitReaderUnload(br); + *available_in = BrotliBitReaderGetAvailIn(br); + *next_in = br->next_in; + } + break; + } + switch (s->state) { + case BROTLI_STATE_UNINITED: + /* Prepare to the first read. */ + if (!BrotliWarmupBitReader(br)) { + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + break; + } + /* Decode window size. */ + result = DecodeWindowBits(s, br); /* Reads 1..8 bits. */ + if (result != BROTLI_DECODER_SUCCESS) { + break; + } + if (s->large_window) { + s->state = BROTLI_STATE_LARGE_WINDOW_BITS; + break; + } + s->state = BROTLI_STATE_INITIALIZE; + break; + + case BROTLI_STATE_LARGE_WINDOW_BITS: { + brotli_reg_t bits; + if (!BrotliSafeReadBits(br, 6, &bits)) { + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + break; + } + s->window_bits = bits & 63u; + if (s->window_bits < BROTLI_LARGE_MIN_WBITS || s->window_bits > BROTLI_LARGE_MAX_WBITS) { + result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS); + break; + } + s->state = BROTLI_STATE_INITIALIZE; + } + /* Fall through. */ + + case BROTLI_STATE_INITIALIZE: + BROTLI_LOG_UINT(s->window_bits); + /* Maximum distance, see section 9.1. of the spec. */ + s->max_backward_distance = (1 << s->window_bits) - BROTLI_WINDOW_GAP; + + /* Allocate memory for both block_type_trees and block_len_trees. */ + s->block_type_trees = (HuffmanCode *)BROTLI_DECODER_ALLOC( + s, sizeof(HuffmanCode) * 3 * (BROTLI_HUFFMAN_MAX_SIZE_258 + BROTLI_HUFFMAN_MAX_SIZE_26)); + if (s->block_type_trees == 0) { + result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES); + break; + } + s->block_len_trees = s->block_type_trees + 3 * BROTLI_HUFFMAN_MAX_SIZE_258; + + s->state = BROTLI_STATE_METABLOCK_BEGIN; + /* Fall through. */ + + case BROTLI_STATE_METABLOCK_BEGIN: + BrotliDecoderStateMetablockBegin(s); + BROTLI_LOG_UINT(s->pos); + s->state = BROTLI_STATE_METABLOCK_HEADER; + /* Fall through. */ + + case BROTLI_STATE_METABLOCK_HEADER: + result = DecodeMetaBlockLength(s, br); /* Reads 2 - 31 bits. */ + if (result != BROTLI_DECODER_SUCCESS) { + break; + } + BROTLI_LOG_UINT(s->is_last_metablock); + BROTLI_LOG_UINT(s->meta_block_remaining_len); + BROTLI_LOG_UINT(s->is_metadata); + BROTLI_LOG_UINT(s->is_uncompressed); + if (s->is_metadata || s->is_uncompressed) { + if (!BrotliJumpToByteBoundary(br)) { + result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_PADDING_1); + break; + } + } + if (s->is_metadata) { + s->state = BROTLI_STATE_METADATA; + if (s->metadata_start_func) { + s->metadata_start_func(s->metadata_callback_opaque, (size_t)s->meta_block_remaining_len); + } + break; + } + if (s->meta_block_remaining_len == 0) { + s->state = BROTLI_STATE_METABLOCK_DONE; + break; + } + BrotliCalculateRingBufferSize(s); + if (s->is_uncompressed) { + s->state = BROTLI_STATE_UNCOMPRESSED; + break; + } + s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER; + /* Fall through. */ + + case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER: { + BrotliMetablockHeaderArena *h = &s->arena.header; + s->loop_counter = 0; + /* Initialize compressed metablock header arena. */ + h->sub_loop_counter = 0; + /* Make small negative indexes addressable. */ + h->symbol_lists = &h->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1]; + h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; + h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE; + h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE; + s->state = BROTLI_STATE_HUFFMAN_CODE_0; + } + /* Fall through. */ + + case BROTLI_STATE_HUFFMAN_CODE_0: + if (s->loop_counter >= 3) { + s->state = BROTLI_STATE_METABLOCK_HEADER_2; + break; + } + /* Reads 1..11 bits. */ + result = DecodeVarLenUint8(s, br, &s->num_block_types[s->loop_counter]); + if (result != BROTLI_DECODER_SUCCESS) { + break; + } + s->num_block_types[s->loop_counter]++; + BROTLI_LOG_UINT(s->num_block_types[s->loop_counter]); + if (s->num_block_types[s->loop_counter] < 2) { + s->loop_counter++; + break; + } + s->state = BROTLI_STATE_HUFFMAN_CODE_1; + /* Fall through. */ + + case BROTLI_STATE_HUFFMAN_CODE_1: { + brotli_reg_t alphabet_size = s->num_block_types[s->loop_counter] + 2; + int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_258; + result = ReadHuffmanCode(alphabet_size, alphabet_size, &s->block_type_trees[tree_offset], NULL, s); + if (result != BROTLI_DECODER_SUCCESS) + break; + s->state = BROTLI_STATE_HUFFMAN_CODE_2; + } + /* Fall through. */ + + case BROTLI_STATE_HUFFMAN_CODE_2: { + brotli_reg_t alphabet_size = BROTLI_NUM_BLOCK_LEN_SYMBOLS; + int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26; + result = ReadHuffmanCode(alphabet_size, alphabet_size, &s->block_len_trees[tree_offset], NULL, s); + if (result != BROTLI_DECODER_SUCCESS) + break; + s->state = BROTLI_STATE_HUFFMAN_CODE_3; + } + /* Fall through. */ + + case BROTLI_STATE_HUFFMAN_CODE_3: { + int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26; + if (!SafeReadBlockLength(s, &s->block_length[s->loop_counter], &s->block_len_trees[tree_offset], br)) { + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + break; + } + BROTLI_LOG_UINT(s->block_length[s->loop_counter]); + s->loop_counter++; + s->state = BROTLI_STATE_HUFFMAN_CODE_0; + break; + } + + case BROTLI_STATE_UNCOMPRESSED: { + result = CopyUncompressedBlockToOutput(available_out, next_out, total_out, s); + if (result != BROTLI_DECODER_SUCCESS) { + break; + } + s->state = BROTLI_STATE_METABLOCK_DONE; + break; + } + + case BROTLI_STATE_METADATA: + result = SkipMetadataBlock(s); + if (result != BROTLI_DECODER_SUCCESS) { + break; + } + s->state = BROTLI_STATE_METABLOCK_DONE; + break; + + case BROTLI_STATE_METABLOCK_HEADER_2: { + brotli_reg_t bits; + if (!BrotliSafeReadBits(br, 6, &bits)) { + result = BROTLI_DECODER_NEEDS_MORE_INPUT; + break; + } + s->distance_postfix_bits = bits & BitMask(2); + bits >>= 2; + s->num_direct_distance_codes = bits << s->distance_postfix_bits; + BROTLI_LOG_UINT(s->num_direct_distance_codes); + BROTLI_LOG_UINT(s->distance_postfix_bits); + s->context_modes = (uint8_t *)BROTLI_DECODER_ALLOC(s, (size_t)s->num_block_types[0]); + if (s->context_modes == 0) { + result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES); + break; + } + s->loop_counter = 0; + s->state = BROTLI_STATE_CONTEXT_MODES; + } + /* Fall through. */ + + case BROTLI_STATE_CONTEXT_MODES: + result = ReadContextModes(s); + if (result != BROTLI_DECODER_SUCCESS) { + break; + } + s->state = BROTLI_STATE_CONTEXT_MAP_1; + /* Fall through. */ + + case BROTLI_STATE_CONTEXT_MAP_1: + result = DecodeContextMap(s->num_block_types[0] << BROTLI_LITERAL_CONTEXT_BITS, &s->num_literal_htrees, + &s->context_map, s); + if (result != BROTLI_DECODER_SUCCESS) { + break; + } + DetectTrivialLiteralBlockTypes(s); + s->state = BROTLI_STATE_CONTEXT_MAP_2; + /* Fall through. */ + + case BROTLI_STATE_CONTEXT_MAP_2: { + brotli_reg_t npostfix = s->distance_postfix_bits; + brotli_reg_t ndirect = s->num_direct_distance_codes; + brotli_reg_t distance_alphabet_size_max = + BROTLI_DISTANCE_ALPHABET_SIZE(npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS); + brotli_reg_t distance_alphabet_size_limit = distance_alphabet_size_max; + BROTLI_BOOL allocation_success = BROTLI_TRUE; + if (s->large_window) { + BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(BROTLI_MAX_ALLOWED_DISTANCE, + (uint32_t)npostfix, (uint32_t)ndirect); + distance_alphabet_size_max = + BROTLI_DISTANCE_ALPHABET_SIZE(npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS); + distance_alphabet_size_limit = limit.max_alphabet_size; + } + result = DecodeContextMap(s->num_block_types[2] << BROTLI_DISTANCE_CONTEXT_BITS, &s->num_dist_htrees, + &s->dist_context_map, s); + if (result != BROTLI_DECODER_SUCCESS) { + break; + } + allocation_success &= BrotliDecoderHuffmanTreeGroupInit(s, &s->literal_hgroup, BROTLI_NUM_LITERAL_SYMBOLS, + BROTLI_NUM_LITERAL_SYMBOLS, s->num_literal_htrees); + allocation_success &= + BrotliDecoderHuffmanTreeGroupInit(s, &s->insert_copy_hgroup, BROTLI_NUM_COMMAND_SYMBOLS, + BROTLI_NUM_COMMAND_SYMBOLS, s->num_block_types[1]); + allocation_success &= BrotliDecoderHuffmanTreeGroupInit(s, &s->distance_hgroup, distance_alphabet_size_max, + distance_alphabet_size_limit, s->num_dist_htrees); + if (!allocation_success) { + return BROTLI_SAVE_ERROR_CODE(BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS)); + } + s->loop_counter = 0; + s->state = BROTLI_STATE_TREE_GROUP; + } + /* Fall through. */ + + case BROTLI_STATE_TREE_GROUP: { + HuffmanTreeGroup *hgroup = NULL; + switch (s->loop_counter) { + case 0: + hgroup = &s->literal_hgroup; + break; + case 1: + hgroup = &s->insert_copy_hgroup; + break; + case 2: + hgroup = &s->distance_hgroup; + break; + default: + return BROTLI_SAVE_ERROR_CODE(BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE)); /* COV_NF_LINE */ + } + result = HuffmanTreeGroupDecode(hgroup, s); + if (result != BROTLI_DECODER_SUCCESS) + break; + s->loop_counter++; + if (s->loop_counter < 3) { + break; + } + s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY; + } + /* Fall through. */ + + case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY: + PrepareLiteralDecoding(s); + s->dist_context_map_slice = s->dist_context_map; + s->htree_command = s->insert_copy_hgroup.htrees[0]; + if (!BrotliEnsureRingBuffer(s)) { + result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2); + break; + } + CalculateDistanceLut(s); + s->state = BROTLI_STATE_COMMAND_BEGIN; + /* Fall through. */ + + case BROTLI_STATE_COMMAND_BEGIN: + /* Fall through. */ + case BROTLI_STATE_COMMAND_INNER: + /* Fall through. */ + case BROTLI_STATE_COMMAND_POST_DECODE_LITERALS: + /* Fall through. */ + case BROTLI_STATE_COMMAND_POST_WRAP_COPY: + result = ProcessCommands(s); + if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) { + result = SafeProcessCommands(s); + } + break; + + case BROTLI_STATE_COMMAND_INNER_WRITE: + /* Fall through. */ + case BROTLI_STATE_COMMAND_POST_WRITE_1: + /* Fall through. */ + case BROTLI_STATE_COMMAND_POST_WRITE_2: + result = WriteRingBuffer(s, available_out, next_out, total_out, BROTLI_FALSE); + if (result != BROTLI_DECODER_SUCCESS) { + break; + } + WrapRingBuffer(s); + if (s->ringbuffer_size == 1 << s->window_bits) { + s->max_distance = s->max_backward_distance; + } + if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) { + BrotliDecoderCompoundDictionary *addon = s->compound_dictionary; + if (addon && (addon->br_length != addon->br_copied)) { + s->pos += CopyFromCompoundDictionary(s, s->pos); + if (s->pos >= s->ringbuffer_size) + continue; + } + if (s->meta_block_remaining_len == 0) { + /* Next metablock, if any. */ + s->state = BROTLI_STATE_METABLOCK_DONE; + } else { + s->state = BROTLI_STATE_COMMAND_BEGIN; + } + break; + } else if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_2) { + s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY; + } else { /* BROTLI_STATE_COMMAND_INNER_WRITE */ + if (s->loop_counter == 0) { + if (s->meta_block_remaining_len == 0) { + s->state = BROTLI_STATE_METABLOCK_DONE; + } else { + s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS; + } + break; + } + s->state = BROTLI_STATE_COMMAND_INNER; + } + break; + + case BROTLI_STATE_METABLOCK_DONE: + if (s->meta_block_remaining_len < 0) { + result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2); + break; + } + BrotliDecoderStateCleanupAfterMetablock(s); + if (!s->is_last_metablock) { + s->state = BROTLI_STATE_METABLOCK_BEGIN; + break; + } + if (!BrotliJumpToByteBoundary(br)) { + result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_PADDING_2); + break; + } + if (s->buffer_length == 0) { + BrotliBitReaderUnload(br); + *available_in = BrotliBitReaderGetAvailIn(br); + *next_in = br->next_in; + } + s->state = BROTLI_STATE_DONE; + /* Fall through. */ + + case BROTLI_STATE_DONE: + if (s->ringbuffer != 0) { + result = WriteRingBuffer(s, available_out, next_out, total_out, BROTLI_TRUE); + if (result != BROTLI_DECODER_SUCCESS) { + break; + } + } + return BROTLI_SAVE_ERROR_CODE(result); + } + } + return BROTLI_SAVE_ERROR_CODE(result); +#undef BROTLI_SAVE_ERROR_CODE +} + +BROTLI_BOOL BrotliDecoderHasMoreOutput(const BrotliDecoderState *s) { + /* After unrecoverable error remaining output is considered nonsensical. */ + if ((int)s->error_code < 0) { + return BROTLI_FALSE; + } + return TO_BROTLI_BOOL(s->ringbuffer != 0 && UnwrittenBytes(s, BROTLI_FALSE) != 0); +} + +const uint8_t *BrotliDecoderTakeOutput(BrotliDecoderState *s, size_t *size) { + uint8_t *result = 0; + size_t available_out = *size ? *size : 1u << 24; + size_t requested_out = available_out; + BrotliDecoderErrorCode status; + if ((s->ringbuffer == 0) || ((int)s->error_code < 0)) { + *size = 0; + return 0; + } + WrapRingBuffer(s); + status = WriteRingBuffer(s, &available_out, &result, 0, BROTLI_TRUE); + /* Either WriteRingBuffer returns those "success" codes... */ + if (status == BROTLI_DECODER_SUCCESS || status == BROTLI_DECODER_NEEDS_MORE_OUTPUT) { + *size = requested_out - available_out; + } else { + /* ... or stream is broken. Normally this should be caught by + BrotliDecoderDecompressStream, this is just a safeguard. */ + if ((int)status < 0) + SaveErrorCode(s, status, 0); + *size = 0; + result = 0; + } + return result; +} + +BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState *s) { + return TO_BROTLI_BOOL(s->state != BROTLI_STATE_UNINITED || BrotliGetAvailableBits(&s->br) != 0); +} + +BROTLI_BOOL BrotliDecoderIsFinished(const BrotliDecoderState *s) { + return TO_BROTLI_BOOL(s->state == BROTLI_STATE_DONE) && !BrotliDecoderHasMoreOutput(s); +} + +BrotliDecoderErrorCode BrotliDecoderGetErrorCode(const BrotliDecoderState *s) { + return (BrotliDecoderErrorCode)s->error_code; +} + +const char *BrotliDecoderErrorString(BrotliDecoderErrorCode c) { + switch (c) { +#define BROTLI_ERROR_CODE_CASE_(PREFIX, NAME, CODE) \ + case BROTLI_DECODER##PREFIX##NAME: return #PREFIX #NAME; +#define BROTLI_NOTHING_ + BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_CASE_, BROTLI_NOTHING_) +#undef BROTLI_ERROR_CODE_CASE_ +#undef BROTLI_NOTHING_ + default: + return "INVALID"; + } +} + +uint32_t BrotliDecoderVersion(void) { + return BROTLI_VERSION; +} + +void BrotliDecoderSetMetadataCallbacks(BrotliDecoderState *state, brotli_decoder_metadata_start_func start_func, + brotli_decoder_metadata_chunk_func chunk_func, void *opaque) { + state->metadata_start_func = start_func; + state->metadata_chunk_func = chunk_func; + state->metadata_callback_opaque = opaque; +} + +/* Escalate internal functions visibility; for testing purposes only. */ +#if defined(BROTLI_TEST) +BROTLI_BOOL SafeReadSymbolForTest(const HuffmanCode *, BrotliBitReader *, brotli_reg_t *); +BROTLI_BOOL SafeReadSymbolForTest(const HuffmanCode *table, BrotliBitReader *br, brotli_reg_t *result) { + return SafeReadSymbol(table, br, result); +} + +void InverseMoveToFrontTransformForTest(uint8_t *, brotli_reg_t, BrotliDecoderState *); +void InverseMoveToFrontTransformForTest(uint8_t *v, brotli_reg_t l, BrotliDecoderState *s) { + InverseMoveToFrontTransform(v, l, s); +} +#endif + +} \ No newline at end of file diff --git a/third_party/brotli/dec/huffman.cpp b/third_party/brotli/dec/huffman.cpp new file mode 100644 index 00000000000..08494665e7a --- /dev/null +++ b/third_party/brotli/dec/huffman.cpp @@ -0,0 +1,338 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Utilities for building Huffman decoding tables. */ + +#include "huffman.h" + +#include /* memcpy, memset */ + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" + +using namespace duckdb_brotli; + +#define BROTLI_REVERSE_BITS_MAX 8 + +#if defined(BROTLI_RBIT) +#define BROTLI_REVERSE_BITS_BASE \ + ((sizeof(brotli_reg_t) << 3) - BROTLI_REVERSE_BITS_MAX) +#else +#define BROTLI_REVERSE_BITS_BASE 0 +static uint8_t kReverseBits[1 << BROTLI_REVERSE_BITS_MAX] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; +#endif /* BROTLI_RBIT */ + +#define BROTLI_REVERSE_BITS_LOWEST \ + ((brotli_reg_t)1 << (BROTLI_REVERSE_BITS_MAX - 1 + BROTLI_REVERSE_BITS_BASE)) + +/* Returns reverse(num >> BROTLI_REVERSE_BITS_BASE, BROTLI_REVERSE_BITS_MAX), + where reverse(value, len) is the bit-wise reversal of the len least + significant bits of value. */ +static BROTLI_INLINE brotli_reg_t BrotliReverseBits(brotli_reg_t num) { +#if defined(BROTLI_RBIT) + return BROTLI_RBIT(num); +#else + return kReverseBits[num]; +#endif +} + +/* Stores code in table[0], table[step], table[2*step], ..., table[end] */ +/* Assumes that end is an integer multiple of step */ +static BROTLI_INLINE void ReplicateValue(HuffmanCode* table, + int step, int end, + HuffmanCode code) { + do { + end -= step; + table[end] = code; + } while (end > 0); +} + +/* Returns the table width of the next 2nd level table. |count| is the histogram + of bit lengths for the remaining symbols, |len| is the code length of the + next processed symbol. */ +static BROTLI_INLINE int NextTableBitSize(const uint16_t* const count, + int len, int root_bits) { + int left = 1 << (len - root_bits); + while (len < BROTLI_HUFFMAN_MAX_CODE_LENGTH) { + left -= count[len]; + if (left <= 0) break; + ++len; + left <<= 1; + } + return len - root_bits; +} + +void duckdb_brotli::BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table, + const uint8_t* const code_lengths, + uint16_t* count) { + HuffmanCode code; /* current table entry */ + int symbol; /* symbol index in original or sorted table */ + brotli_reg_t key; /* prefix code */ + brotli_reg_t key_step; /* prefix code addend */ + int step; /* step size to replicate values in current table */ + int table_size; /* size of current table */ + int sorted[BROTLI_CODE_LENGTH_CODES]; /* symbols sorted by code length */ + /* offsets in sorted table for each length */ + int offset[BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1]; + int bits; + int bits_count; + BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH <= + BROTLI_REVERSE_BITS_MAX); + BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5); + + /* Generate offsets into sorted symbol table by code length. */ + symbol = -1; + bits = 1; + /* BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5 */ + BROTLI_REPEAT_5({ + symbol += count[bits]; + offset[bits] = symbol; + bits++; + }); + /* Symbols with code length 0 are placed after all other symbols. */ + offset[0] = BROTLI_CODE_LENGTH_CODES - 1; + + /* Sort symbols by length, by symbol order within each length. */ + symbol = BROTLI_CODE_LENGTH_CODES; + do { + BROTLI_REPEAT_6({ + symbol--; + sorted[offset[code_lengths[symbol]]--] = symbol; + }); + } while (symbol != 0); + + table_size = 1 << BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH; + + /* Special case: all symbols but one have 0 code length. */ + if (offset[0] == 0) { + code = ConstructHuffmanCode(0, (uint16_t)sorted[0]); + for (key = 0; key < (brotli_reg_t)table_size; ++key) { + table[key] = code; + } + return; + } + + /* Fill in table. */ + key = 0; + key_step = BROTLI_REVERSE_BITS_LOWEST; + symbol = 0; + bits = 1; + step = 2; + do { + for (bits_count = count[bits]; bits_count != 0; --bits_count) { + code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)sorted[symbol++]); + ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code); + key += key_step; + } + step <<= 1; + key_step >>= 1; + } while (++bits <= BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH); +} + +uint32_t duckdb_brotli::BrotliBuildHuffmanTable(HuffmanCode* root_table, + int root_bits, + const uint16_t* const symbol_lists, + uint16_t* count) { + HuffmanCode code; /* current table entry */ + HuffmanCode* table; /* next available space in table */ + int len; /* current code length */ + int symbol; /* symbol index in original or sorted table */ + brotli_reg_t key; /* prefix code */ + brotli_reg_t key_step; /* prefix code addend */ + brotli_reg_t sub_key; /* 2nd level table prefix code */ + brotli_reg_t sub_key_step; /* 2nd level table prefix code addend */ + int step; /* step size to replicate values in current table */ + int table_bits; /* key length of current table */ + int table_size; /* size of current table */ + int total_size; /* sum of root table size and 2nd level table sizes */ + int max_length = -1; + int bits; + int bits_count; + + BROTLI_DCHECK(root_bits <= BROTLI_REVERSE_BITS_MAX); + BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH - root_bits <= + BROTLI_REVERSE_BITS_MAX); + + while (symbol_lists[max_length] == 0xFFFF) max_length--; + max_length += BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1; + + table = root_table; + table_bits = root_bits; + table_size = 1 << table_bits; + total_size = table_size; + + /* Fill in the root table. Reduce the table size to if possible, + and create the repetitions by memcpy. */ + if (table_bits > max_length) { + table_bits = max_length; + table_size = 1 << table_bits; + } + key = 0; + key_step = BROTLI_REVERSE_BITS_LOWEST; + bits = 1; + step = 2; + do { + symbol = bits - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1); + for (bits_count = count[bits]; bits_count != 0; --bits_count) { + symbol = symbol_lists[symbol]; + code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)symbol); + ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code); + key += key_step; + } + step <<= 1; + key_step >>= 1; + } while (++bits <= table_bits); + + /* If root_bits != table_bits then replicate to fill the remaining slots. */ + while (total_size != table_size) { + memcpy(&table[table_size], &table[0], + (size_t)table_size * sizeof(table[0])); + table_size <<= 1; + } + + /* Fill in 2nd level tables and add pointers to root table. */ + key_step = BROTLI_REVERSE_BITS_LOWEST >> (root_bits - 1); + sub_key = (BROTLI_REVERSE_BITS_LOWEST << 1); + sub_key_step = BROTLI_REVERSE_BITS_LOWEST; + for (len = root_bits + 1, step = 2; len <= max_length; ++len) { + symbol = len - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1); + for (; count[len] != 0; --count[len]) { + if (sub_key == (BROTLI_REVERSE_BITS_LOWEST << 1U)) { + table += table_size; + table_bits = NextTableBitSize(count, len, root_bits); + table_size = 1 << table_bits; + total_size += table_size; + sub_key = BrotliReverseBits(key); + key += key_step; + root_table[sub_key] = ConstructHuffmanCode( + (uint8_t)(table_bits + root_bits), + (uint16_t)(((size_t)(table - root_table)) - sub_key)); + sub_key = 0; + } + symbol = symbol_lists[symbol]; + code = ConstructHuffmanCode((uint8_t)(len - root_bits), (uint16_t)symbol); + ReplicateValue( + &table[BrotliReverseBits(sub_key)], step, table_size, code); + sub_key += sub_key_step; + } + step <<= 1; + sub_key_step >>= 1; + } + return (uint32_t)total_size; +} + +uint32_t duckdb_brotli::BrotliBuildSimpleHuffmanTable(HuffmanCode* table, + int root_bits, + uint16_t* val, + uint32_t num_symbols) { + uint32_t table_size = 1; + const uint32_t goal_size = 1U << root_bits; + switch (num_symbols) { + case 0: + table[0] = ConstructHuffmanCode(0, val[0]); + break; + case 1: + if (val[1] > val[0]) { + table[0] = ConstructHuffmanCode(1, val[0]); + table[1] = ConstructHuffmanCode(1, val[1]); + } else { + table[0] = ConstructHuffmanCode(1, val[1]); + table[1] = ConstructHuffmanCode(1, val[0]); + } + table_size = 2; + break; + case 2: + table[0] = ConstructHuffmanCode(1, val[0]); + table[2] = ConstructHuffmanCode(1, val[0]); + if (val[2] > val[1]) { + table[1] = ConstructHuffmanCode(2, val[1]); + table[3] = ConstructHuffmanCode(2, val[2]); + } else { + table[1] = ConstructHuffmanCode(2, val[2]); + table[3] = ConstructHuffmanCode(2, val[1]); + } + table_size = 4; + break; + case 3: { + int i, k; + for (i = 0; i < 3; ++i) { + for (k = i + 1; k < 4; ++k) { + if (val[k] < val[i]) { + uint16_t t = val[k]; + val[k] = val[i]; + val[i] = t; + } + } + } + table[0] = ConstructHuffmanCode(2, val[0]); + table[2] = ConstructHuffmanCode(2, val[1]); + table[1] = ConstructHuffmanCode(2, val[2]); + table[3] = ConstructHuffmanCode(2, val[3]); + table_size = 4; + break; + } + case 4: { + if (val[3] < val[2]) { + uint16_t t = val[3]; + val[3] = val[2]; + val[2] = t; + } + table[0] = ConstructHuffmanCode(1, val[0]); + table[1] = ConstructHuffmanCode(2, val[1]); + table[2] = ConstructHuffmanCode(1, val[0]); + table[3] = ConstructHuffmanCode(3, val[2]); + table[4] = ConstructHuffmanCode(1, val[0]); + table[5] = ConstructHuffmanCode(2, val[1]); + table[6] = ConstructHuffmanCode(1, val[0]); + table[7] = ConstructHuffmanCode(3, val[3]); + table_size = 8; + break; + } + } + while (table_size != goal_size) { + memcpy(&table[table_size], &table[0], + (size_t)table_size * sizeof(table[0])); + table_size <<= 1; + } + return goal_size; +} + + diff --git a/third_party/brotli/dec/huffman.h b/third_party/brotli/dec/huffman.h new file mode 100644 index 00000000000..6569834f3ba --- /dev/null +++ b/third_party/brotli/dec/huffman.h @@ -0,0 +1,118 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Utilities for building Huffman decoding tables. */ + +#ifndef BROTLI_DEC_HUFFMAN_H_ +#define BROTLI_DEC_HUFFMAN_H_ + +#include + +#include "../common/brotli_platform.h" + +namespace duckdb_brotli { + +#define BROTLI_HUFFMAN_MAX_CODE_LENGTH 15 + +/* BROTLI_NUM_BLOCK_LEN_SYMBOLS == 26 */ +#define BROTLI_HUFFMAN_MAX_SIZE_26 396 +/* BROTLI_MAX_BLOCK_TYPE_SYMBOLS == 258 */ +#define BROTLI_HUFFMAN_MAX_SIZE_258 632 +/* BROTLI_MAX_CONTEXT_MAP_SYMBOLS == 272 */ +#define BROTLI_HUFFMAN_MAX_SIZE_272 646 + +#define BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH 5 + +#if ((defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_32)) && \ + BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)) +#define BROTLI_HUFFMAN_CODE_FAST_LOAD +#endif + +#if !defined(BROTLI_HUFFMAN_CODE_FAST_LOAD) +/* Do not create this struct directly - use the ConstructHuffmanCode + * constructor below! */ +typedef struct { + uint8_t bits; /* number of bits used for this symbol */ + uint16_t value; /* symbol value or table offset */ +} HuffmanCode; + +static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits, + const uint16_t value) { + HuffmanCode h; + h.bits = bits; + h.value = value; + return h; +} + +/* Please use the following macros to optimize HuffmanCode accesses in hot + * paths. + * + * For example, assuming |table| contains a HuffmanCode pointer: + * + * BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table); + * BROTLI_HC_ADJUST_TABLE_INDEX(table, index_into_table); + * *bits = BROTLI_HC_GET_BITS(table); + * *value = BROTLI_HC_GET_VALUE(table); + * BROTLI_HC_ADJUST_TABLE_INDEX(table, offset); + * *bits2 = BROTLI_HC_GET_BITS(table); + * *value2 = BROTLI_HC_GET_VALUE(table); + * + */ + +#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H) +#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V) + +/* These must be given a HuffmanCode pointer! */ +#define BROTLI_HC_FAST_LOAD_BITS(H) (H->bits) +#define BROTLI_HC_FAST_LOAD_VALUE(H) (H->value) + +#else /* BROTLI_HUFFMAN_CODE_FAST_LOAD */ + +typedef BROTLI_ALIGNED(4) uint32_t HuffmanCode; + +static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits, + const uint16_t value) { + return (HuffmanCode) ((value & 0xFFFF) << 16) | (bits & 0xFF); +} + +#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H) uint32_t __fastload_##H = (*H) +#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V); __fastload_##H = (*H) + +/* These must be given a HuffmanCode pointer! */ +#define BROTLI_HC_FAST_LOAD_BITS(H) ((__fastload_##H) & 0xFF) +#define BROTLI_HC_FAST_LOAD_VALUE(H) ((__fastload_##H) >> 16) +#endif /* BROTLI_HUFFMAN_CODE_FAST_LOAD */ + +/* Builds Huffman lookup table assuming code lengths are in symbol order. */ +BROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table, + const uint8_t* const code_lengths, uint16_t* count); + +/* Builds Huffman lookup table assuming code lengths are in symbol order. + Returns size of resulting table. */ +BROTLI_INTERNAL uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table, + int root_bits, const uint16_t* const symbol_lists, uint16_t* count); + +/* Builds a simple Huffman table. The |num_symbols| parameter is to be + interpreted as follows: 0 means 1 symbol, 1 means 2 symbols, + 2 means 3 symbols, 3 means 4 symbols with lengths [2, 2, 2, 2], + 4 means 4 symbols with lengths [1, 2, 3, 3]. */ +BROTLI_INTERNAL uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table, + int root_bits, uint16_t* symbols, uint32_t num_symbols); + +/* Contains a collection of Huffman trees with the same alphabet size. */ +/* alphabet_size_limit is needed due to simple codes, since + log2(alphabet_size_max) could be greater than log2(alphabet_size_limit). */ +typedef struct { + HuffmanCode** htrees; + HuffmanCode* codes; + uint16_t alphabet_size_max; + uint16_t alphabet_size_limit; + uint16_t num_htrees; +} HuffmanTreeGroup; + +} + +#endif /* BROTLI_DEC_HUFFMAN_H_ */ diff --git a/third_party/brotli/dec/prefix.h b/third_party/brotli/dec/prefix.h new file mode 100644 index 00000000000..08240a73923 --- /dev/null +++ b/third_party/brotli/dec/prefix.h @@ -0,0 +1,733 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Lookup tables to map prefix codes to value ranges. This is used during + decoding of the block lengths, literal insertion lengths and copy lengths. */ + +#ifndef BROTLI_DEC_PREFIX_H_ +#define BROTLI_DEC_PREFIX_H_ + +#include + +#include "../common/brotli_constants.h" + +typedef struct CmdLutElement { + uint8_t insert_len_extra_bits; + uint8_t copy_len_extra_bits; + int8_t distance_code; + uint8_t context; + uint16_t insert_len_offset; + uint16_t copy_len_offset; +} CmdLutElement; + +static const CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS] = { + { 0x00, 0x00, 0, 0x00, 0x0000, 0x0002 }, + { 0x00, 0x00, 0, 0x01, 0x0000, 0x0003 }, + { 0x00, 0x00, 0, 0x02, 0x0000, 0x0004 }, + { 0x00, 0x00, 0, 0x03, 0x0000, 0x0005 }, + { 0x00, 0x00, 0, 0x03, 0x0000, 0x0006 }, + { 0x00, 0x00, 0, 0x03, 0x0000, 0x0007 }, + { 0x00, 0x00, 0, 0x03, 0x0000, 0x0008 }, + { 0x00, 0x00, 0, 0x03, 0x0000, 0x0009 }, + { 0x00, 0x00, 0, 0x00, 0x0001, 0x0002 }, + { 0x00, 0x00, 0, 0x01, 0x0001, 0x0003 }, + { 0x00, 0x00, 0, 0x02, 0x0001, 0x0004 }, + { 0x00, 0x00, 0, 0x03, 0x0001, 0x0005 }, + { 0x00, 0x00, 0, 0x03, 0x0001, 0x0006 }, + { 0x00, 0x00, 0, 0x03, 0x0001, 0x0007 }, + { 0x00, 0x00, 0, 0x03, 0x0001, 0x0008 }, + { 0x00, 0x00, 0, 0x03, 0x0001, 0x0009 }, + { 0x00, 0x00, 0, 0x00, 0x0002, 0x0002 }, + { 0x00, 0x00, 0, 0x01, 0x0002, 0x0003 }, + { 0x00, 0x00, 0, 0x02, 0x0002, 0x0004 }, + { 0x00, 0x00, 0, 0x03, 0x0002, 0x0005 }, + { 0x00, 0x00, 0, 0x03, 0x0002, 0x0006 }, + { 0x00, 0x00, 0, 0x03, 0x0002, 0x0007 }, + { 0x00, 0x00, 0, 0x03, 0x0002, 0x0008 }, + { 0x00, 0x00, 0, 0x03, 0x0002, 0x0009 }, + { 0x00, 0x00, 0, 0x00, 0x0003, 0x0002 }, + { 0x00, 0x00, 0, 0x01, 0x0003, 0x0003 }, + { 0x00, 0x00, 0, 0x02, 0x0003, 0x0004 }, + { 0x00, 0x00, 0, 0x03, 0x0003, 0x0005 }, + { 0x00, 0x00, 0, 0x03, 0x0003, 0x0006 }, + { 0x00, 0x00, 0, 0x03, 0x0003, 0x0007 }, + { 0x00, 0x00, 0, 0x03, 0x0003, 0x0008 }, + { 0x00, 0x00, 0, 0x03, 0x0003, 0x0009 }, + { 0x00, 0x00, 0, 0x00, 0x0004, 0x0002 }, + { 0x00, 0x00, 0, 0x01, 0x0004, 0x0003 }, + { 0x00, 0x00, 0, 0x02, 0x0004, 0x0004 }, + { 0x00, 0x00, 0, 0x03, 0x0004, 0x0005 }, + { 0x00, 0x00, 0, 0x03, 0x0004, 0x0006 }, + { 0x00, 0x00, 0, 0x03, 0x0004, 0x0007 }, + { 0x00, 0x00, 0, 0x03, 0x0004, 0x0008 }, + { 0x00, 0x00, 0, 0x03, 0x0004, 0x0009 }, + { 0x00, 0x00, 0, 0x00, 0x0005, 0x0002 }, + { 0x00, 0x00, 0, 0x01, 0x0005, 0x0003 }, + { 0x00, 0x00, 0, 0x02, 0x0005, 0x0004 }, + { 0x00, 0x00, 0, 0x03, 0x0005, 0x0005 }, + { 0x00, 0x00, 0, 0x03, 0x0005, 0x0006 }, + { 0x00, 0x00, 0, 0x03, 0x0005, 0x0007 }, + { 0x00, 0x00, 0, 0x03, 0x0005, 0x0008 }, + { 0x00, 0x00, 0, 0x03, 0x0005, 0x0009 }, + { 0x01, 0x00, 0, 0x00, 0x0006, 0x0002 }, + { 0x01, 0x00, 0, 0x01, 0x0006, 0x0003 }, + { 0x01, 0x00, 0, 0x02, 0x0006, 0x0004 }, + { 0x01, 0x00, 0, 0x03, 0x0006, 0x0005 }, + { 0x01, 0x00, 0, 0x03, 0x0006, 0x0006 }, + { 0x01, 0x00, 0, 0x03, 0x0006, 0x0007 }, + { 0x01, 0x00, 0, 0x03, 0x0006, 0x0008 }, + { 0x01, 0x00, 0, 0x03, 0x0006, 0x0009 }, + { 0x01, 0x00, 0, 0x00, 0x0008, 0x0002 }, + { 0x01, 0x00, 0, 0x01, 0x0008, 0x0003 }, + { 0x01, 0x00, 0, 0x02, 0x0008, 0x0004 }, + { 0x01, 0x00, 0, 0x03, 0x0008, 0x0005 }, + { 0x01, 0x00, 0, 0x03, 0x0008, 0x0006 }, + { 0x01, 0x00, 0, 0x03, 0x0008, 0x0007 }, + { 0x01, 0x00, 0, 0x03, 0x0008, 0x0008 }, + { 0x01, 0x00, 0, 0x03, 0x0008, 0x0009 }, + { 0x00, 0x01, 0, 0x03, 0x0000, 0x000a }, + { 0x00, 0x01, 0, 0x03, 0x0000, 0x000c }, + { 0x00, 0x02, 0, 0x03, 0x0000, 0x000e }, + { 0x00, 0x02, 0, 0x03, 0x0000, 0x0012 }, + { 0x00, 0x03, 0, 0x03, 0x0000, 0x0016 }, + { 0x00, 0x03, 0, 0x03, 0x0000, 0x001e }, + { 0x00, 0x04, 0, 0x03, 0x0000, 0x0026 }, + { 0x00, 0x04, 0, 0x03, 0x0000, 0x0036 }, + { 0x00, 0x01, 0, 0x03, 0x0001, 0x000a }, + { 0x00, 0x01, 0, 0x03, 0x0001, 0x000c }, + { 0x00, 0x02, 0, 0x03, 0x0001, 0x000e }, + { 0x00, 0x02, 0, 0x03, 0x0001, 0x0012 }, + { 0x00, 0x03, 0, 0x03, 0x0001, 0x0016 }, + { 0x00, 0x03, 0, 0x03, 0x0001, 0x001e }, + { 0x00, 0x04, 0, 0x03, 0x0001, 0x0026 }, + { 0x00, 0x04, 0, 0x03, 0x0001, 0x0036 }, + { 0x00, 0x01, 0, 0x03, 0x0002, 0x000a }, + { 0x00, 0x01, 0, 0x03, 0x0002, 0x000c }, + { 0x00, 0x02, 0, 0x03, 0x0002, 0x000e }, + { 0x00, 0x02, 0, 0x03, 0x0002, 0x0012 }, + { 0x00, 0x03, 0, 0x03, 0x0002, 0x0016 }, + { 0x00, 0x03, 0, 0x03, 0x0002, 0x001e }, + { 0x00, 0x04, 0, 0x03, 0x0002, 0x0026 }, + { 0x00, 0x04, 0, 0x03, 0x0002, 0x0036 }, + { 0x00, 0x01, 0, 0x03, 0x0003, 0x000a }, + { 0x00, 0x01, 0, 0x03, 0x0003, 0x000c }, + { 0x00, 0x02, 0, 0x03, 0x0003, 0x000e }, + { 0x00, 0x02, 0, 0x03, 0x0003, 0x0012 }, + { 0x00, 0x03, 0, 0x03, 0x0003, 0x0016 }, + { 0x00, 0x03, 0, 0x03, 0x0003, 0x001e }, + { 0x00, 0x04, 0, 0x03, 0x0003, 0x0026 }, + { 0x00, 0x04, 0, 0x03, 0x0003, 0x0036 }, + { 0x00, 0x01, 0, 0x03, 0x0004, 0x000a }, + { 0x00, 0x01, 0, 0x03, 0x0004, 0x000c }, + { 0x00, 0x02, 0, 0x03, 0x0004, 0x000e }, + { 0x00, 0x02, 0, 0x03, 0x0004, 0x0012 }, + { 0x00, 0x03, 0, 0x03, 0x0004, 0x0016 }, + { 0x00, 0x03, 0, 0x03, 0x0004, 0x001e }, + { 0x00, 0x04, 0, 0x03, 0x0004, 0x0026 }, + { 0x00, 0x04, 0, 0x03, 0x0004, 0x0036 }, + { 0x00, 0x01, 0, 0x03, 0x0005, 0x000a }, + { 0x00, 0x01, 0, 0x03, 0x0005, 0x000c }, + { 0x00, 0x02, 0, 0x03, 0x0005, 0x000e }, + { 0x00, 0x02, 0, 0x03, 0x0005, 0x0012 }, + { 0x00, 0x03, 0, 0x03, 0x0005, 0x0016 }, + { 0x00, 0x03, 0, 0x03, 0x0005, 0x001e }, + { 0x00, 0x04, 0, 0x03, 0x0005, 0x0026 }, + { 0x00, 0x04, 0, 0x03, 0x0005, 0x0036 }, + { 0x01, 0x01, 0, 0x03, 0x0006, 0x000a }, + { 0x01, 0x01, 0, 0x03, 0x0006, 0x000c }, + { 0x01, 0x02, 0, 0x03, 0x0006, 0x000e }, + { 0x01, 0x02, 0, 0x03, 0x0006, 0x0012 }, + { 0x01, 0x03, 0, 0x03, 0x0006, 0x0016 }, + { 0x01, 0x03, 0, 0x03, 0x0006, 0x001e }, + { 0x01, 0x04, 0, 0x03, 0x0006, 0x0026 }, + { 0x01, 0x04, 0, 0x03, 0x0006, 0x0036 }, + { 0x01, 0x01, 0, 0x03, 0x0008, 0x000a }, + { 0x01, 0x01, 0, 0x03, 0x0008, 0x000c }, + { 0x01, 0x02, 0, 0x03, 0x0008, 0x000e }, + { 0x01, 0x02, 0, 0x03, 0x0008, 0x0012 }, + { 0x01, 0x03, 0, 0x03, 0x0008, 0x0016 }, + { 0x01, 0x03, 0, 0x03, 0x0008, 0x001e }, + { 0x01, 0x04, 0, 0x03, 0x0008, 0x0026 }, + { 0x01, 0x04, 0, 0x03, 0x0008, 0x0036 }, + { 0x00, 0x00, -1, 0x00, 0x0000, 0x0002 }, + { 0x00, 0x00, -1, 0x01, 0x0000, 0x0003 }, + { 0x00, 0x00, -1, 0x02, 0x0000, 0x0004 }, + { 0x00, 0x00, -1, 0x03, 0x0000, 0x0005 }, + { 0x00, 0x00, -1, 0x03, 0x0000, 0x0006 }, + { 0x00, 0x00, -1, 0x03, 0x0000, 0x0007 }, + { 0x00, 0x00, -1, 0x03, 0x0000, 0x0008 }, + { 0x00, 0x00, -1, 0x03, 0x0000, 0x0009 }, + { 0x00, 0x00, -1, 0x00, 0x0001, 0x0002 }, + { 0x00, 0x00, -1, 0x01, 0x0001, 0x0003 }, + { 0x00, 0x00, -1, 0x02, 0x0001, 0x0004 }, + { 0x00, 0x00, -1, 0x03, 0x0001, 0x0005 }, + { 0x00, 0x00, -1, 0x03, 0x0001, 0x0006 }, + { 0x00, 0x00, -1, 0x03, 0x0001, 0x0007 }, + { 0x00, 0x00, -1, 0x03, 0x0001, 0x0008 }, + { 0x00, 0x00, -1, 0x03, 0x0001, 0x0009 }, + { 0x00, 0x00, -1, 0x00, 0x0002, 0x0002 }, + { 0x00, 0x00, -1, 0x01, 0x0002, 0x0003 }, + { 0x00, 0x00, -1, 0x02, 0x0002, 0x0004 }, + { 0x00, 0x00, -1, 0x03, 0x0002, 0x0005 }, + { 0x00, 0x00, -1, 0x03, 0x0002, 0x0006 }, + { 0x00, 0x00, -1, 0x03, 0x0002, 0x0007 }, + { 0x00, 0x00, -1, 0x03, 0x0002, 0x0008 }, + { 0x00, 0x00, -1, 0x03, 0x0002, 0x0009 }, + { 0x00, 0x00, -1, 0x00, 0x0003, 0x0002 }, + { 0x00, 0x00, -1, 0x01, 0x0003, 0x0003 }, + { 0x00, 0x00, -1, 0x02, 0x0003, 0x0004 }, + { 0x00, 0x00, -1, 0x03, 0x0003, 0x0005 }, + { 0x00, 0x00, -1, 0x03, 0x0003, 0x0006 }, + { 0x00, 0x00, -1, 0x03, 0x0003, 0x0007 }, + { 0x00, 0x00, -1, 0x03, 0x0003, 0x0008 }, + { 0x00, 0x00, -1, 0x03, 0x0003, 0x0009 }, + { 0x00, 0x00, -1, 0x00, 0x0004, 0x0002 }, + { 0x00, 0x00, -1, 0x01, 0x0004, 0x0003 }, + { 0x00, 0x00, -1, 0x02, 0x0004, 0x0004 }, + { 0x00, 0x00, -1, 0x03, 0x0004, 0x0005 }, + { 0x00, 0x00, -1, 0x03, 0x0004, 0x0006 }, + { 0x00, 0x00, -1, 0x03, 0x0004, 0x0007 }, + { 0x00, 0x00, -1, 0x03, 0x0004, 0x0008 }, + { 0x00, 0x00, -1, 0x03, 0x0004, 0x0009 }, + { 0x00, 0x00, -1, 0x00, 0x0005, 0x0002 }, + { 0x00, 0x00, -1, 0x01, 0x0005, 0x0003 }, + { 0x00, 0x00, -1, 0x02, 0x0005, 0x0004 }, + { 0x00, 0x00, -1, 0x03, 0x0005, 0x0005 }, + { 0x00, 0x00, -1, 0x03, 0x0005, 0x0006 }, + { 0x00, 0x00, -1, 0x03, 0x0005, 0x0007 }, + { 0x00, 0x00, -1, 0x03, 0x0005, 0x0008 }, + { 0x00, 0x00, -1, 0x03, 0x0005, 0x0009 }, + { 0x01, 0x00, -1, 0x00, 0x0006, 0x0002 }, + { 0x01, 0x00, -1, 0x01, 0x0006, 0x0003 }, + { 0x01, 0x00, -1, 0x02, 0x0006, 0x0004 }, + { 0x01, 0x00, -1, 0x03, 0x0006, 0x0005 }, + { 0x01, 0x00, -1, 0x03, 0x0006, 0x0006 }, + { 0x01, 0x00, -1, 0x03, 0x0006, 0x0007 }, + { 0x01, 0x00, -1, 0x03, 0x0006, 0x0008 }, + { 0x01, 0x00, -1, 0x03, 0x0006, 0x0009 }, + { 0x01, 0x00, -1, 0x00, 0x0008, 0x0002 }, + { 0x01, 0x00, -1, 0x01, 0x0008, 0x0003 }, + { 0x01, 0x00, -1, 0x02, 0x0008, 0x0004 }, + { 0x01, 0x00, -1, 0x03, 0x0008, 0x0005 }, + { 0x01, 0x00, -1, 0x03, 0x0008, 0x0006 }, + { 0x01, 0x00, -1, 0x03, 0x0008, 0x0007 }, + { 0x01, 0x00, -1, 0x03, 0x0008, 0x0008 }, + { 0x01, 0x00, -1, 0x03, 0x0008, 0x0009 }, + { 0x00, 0x01, -1, 0x03, 0x0000, 0x000a }, + { 0x00, 0x01, -1, 0x03, 0x0000, 0x000c }, + { 0x00, 0x02, -1, 0x03, 0x0000, 0x000e }, + { 0x00, 0x02, -1, 0x03, 0x0000, 0x0012 }, + { 0x00, 0x03, -1, 0x03, 0x0000, 0x0016 }, + { 0x00, 0x03, -1, 0x03, 0x0000, 0x001e }, + { 0x00, 0x04, -1, 0x03, 0x0000, 0x0026 }, + { 0x00, 0x04, -1, 0x03, 0x0000, 0x0036 }, + { 0x00, 0x01, -1, 0x03, 0x0001, 0x000a }, + { 0x00, 0x01, -1, 0x03, 0x0001, 0x000c }, + { 0x00, 0x02, -1, 0x03, 0x0001, 0x000e }, + { 0x00, 0x02, -1, 0x03, 0x0001, 0x0012 }, + { 0x00, 0x03, -1, 0x03, 0x0001, 0x0016 }, + { 0x00, 0x03, -1, 0x03, 0x0001, 0x001e }, + { 0x00, 0x04, -1, 0x03, 0x0001, 0x0026 }, + { 0x00, 0x04, -1, 0x03, 0x0001, 0x0036 }, + { 0x00, 0x01, -1, 0x03, 0x0002, 0x000a }, + { 0x00, 0x01, -1, 0x03, 0x0002, 0x000c }, + { 0x00, 0x02, -1, 0x03, 0x0002, 0x000e }, + { 0x00, 0x02, -1, 0x03, 0x0002, 0x0012 }, + { 0x00, 0x03, -1, 0x03, 0x0002, 0x0016 }, + { 0x00, 0x03, -1, 0x03, 0x0002, 0x001e }, + { 0x00, 0x04, -1, 0x03, 0x0002, 0x0026 }, + { 0x00, 0x04, -1, 0x03, 0x0002, 0x0036 }, + { 0x00, 0x01, -1, 0x03, 0x0003, 0x000a }, + { 0x00, 0x01, -1, 0x03, 0x0003, 0x000c }, + { 0x00, 0x02, -1, 0x03, 0x0003, 0x000e }, + { 0x00, 0x02, -1, 0x03, 0x0003, 0x0012 }, + { 0x00, 0x03, -1, 0x03, 0x0003, 0x0016 }, + { 0x00, 0x03, -1, 0x03, 0x0003, 0x001e }, + { 0x00, 0x04, -1, 0x03, 0x0003, 0x0026 }, + { 0x00, 0x04, -1, 0x03, 0x0003, 0x0036 }, + { 0x00, 0x01, -1, 0x03, 0x0004, 0x000a }, + { 0x00, 0x01, -1, 0x03, 0x0004, 0x000c }, + { 0x00, 0x02, -1, 0x03, 0x0004, 0x000e }, + { 0x00, 0x02, -1, 0x03, 0x0004, 0x0012 }, + { 0x00, 0x03, -1, 0x03, 0x0004, 0x0016 }, + { 0x00, 0x03, -1, 0x03, 0x0004, 0x001e }, + { 0x00, 0x04, -1, 0x03, 0x0004, 0x0026 }, + { 0x00, 0x04, -1, 0x03, 0x0004, 0x0036 }, + { 0x00, 0x01, -1, 0x03, 0x0005, 0x000a }, + { 0x00, 0x01, -1, 0x03, 0x0005, 0x000c }, + { 0x00, 0x02, -1, 0x03, 0x0005, 0x000e }, + { 0x00, 0x02, -1, 0x03, 0x0005, 0x0012 }, + { 0x00, 0x03, -1, 0x03, 0x0005, 0x0016 }, + { 0x00, 0x03, -1, 0x03, 0x0005, 0x001e }, + { 0x00, 0x04, -1, 0x03, 0x0005, 0x0026 }, + { 0x00, 0x04, -1, 0x03, 0x0005, 0x0036 }, + { 0x01, 0x01, -1, 0x03, 0x0006, 0x000a }, + { 0x01, 0x01, -1, 0x03, 0x0006, 0x000c }, + { 0x01, 0x02, -1, 0x03, 0x0006, 0x000e }, + { 0x01, 0x02, -1, 0x03, 0x0006, 0x0012 }, + { 0x01, 0x03, -1, 0x03, 0x0006, 0x0016 }, + { 0x01, 0x03, -1, 0x03, 0x0006, 0x001e }, + { 0x01, 0x04, -1, 0x03, 0x0006, 0x0026 }, + { 0x01, 0x04, -1, 0x03, 0x0006, 0x0036 }, + { 0x01, 0x01, -1, 0x03, 0x0008, 0x000a }, + { 0x01, 0x01, -1, 0x03, 0x0008, 0x000c }, + { 0x01, 0x02, -1, 0x03, 0x0008, 0x000e }, + { 0x01, 0x02, -1, 0x03, 0x0008, 0x0012 }, + { 0x01, 0x03, -1, 0x03, 0x0008, 0x0016 }, + { 0x01, 0x03, -1, 0x03, 0x0008, 0x001e }, + { 0x01, 0x04, -1, 0x03, 0x0008, 0x0026 }, + { 0x01, 0x04, -1, 0x03, 0x0008, 0x0036 }, + { 0x02, 0x00, -1, 0x00, 0x000a, 0x0002 }, + { 0x02, 0x00, -1, 0x01, 0x000a, 0x0003 }, + { 0x02, 0x00, -1, 0x02, 0x000a, 0x0004 }, + { 0x02, 0x00, -1, 0x03, 0x000a, 0x0005 }, + { 0x02, 0x00, -1, 0x03, 0x000a, 0x0006 }, + { 0x02, 0x00, -1, 0x03, 0x000a, 0x0007 }, + { 0x02, 0x00, -1, 0x03, 0x000a, 0x0008 }, + { 0x02, 0x00, -1, 0x03, 0x000a, 0x0009 }, + { 0x02, 0x00, -1, 0x00, 0x000e, 0x0002 }, + { 0x02, 0x00, -1, 0x01, 0x000e, 0x0003 }, + { 0x02, 0x00, -1, 0x02, 0x000e, 0x0004 }, + { 0x02, 0x00, -1, 0x03, 0x000e, 0x0005 }, + { 0x02, 0x00, -1, 0x03, 0x000e, 0x0006 }, + { 0x02, 0x00, -1, 0x03, 0x000e, 0x0007 }, + { 0x02, 0x00, -1, 0x03, 0x000e, 0x0008 }, + { 0x02, 0x00, -1, 0x03, 0x000e, 0x0009 }, + { 0x03, 0x00, -1, 0x00, 0x0012, 0x0002 }, + { 0x03, 0x00, -1, 0x01, 0x0012, 0x0003 }, + { 0x03, 0x00, -1, 0x02, 0x0012, 0x0004 }, + { 0x03, 0x00, -1, 0x03, 0x0012, 0x0005 }, + { 0x03, 0x00, -1, 0x03, 0x0012, 0x0006 }, + { 0x03, 0x00, -1, 0x03, 0x0012, 0x0007 }, + { 0x03, 0x00, -1, 0x03, 0x0012, 0x0008 }, + { 0x03, 0x00, -1, 0x03, 0x0012, 0x0009 }, + { 0x03, 0x00, -1, 0x00, 0x001a, 0x0002 }, + { 0x03, 0x00, -1, 0x01, 0x001a, 0x0003 }, + { 0x03, 0x00, -1, 0x02, 0x001a, 0x0004 }, + { 0x03, 0x00, -1, 0x03, 0x001a, 0x0005 }, + { 0x03, 0x00, -1, 0x03, 0x001a, 0x0006 }, + { 0x03, 0x00, -1, 0x03, 0x001a, 0x0007 }, + { 0x03, 0x00, -1, 0x03, 0x001a, 0x0008 }, + { 0x03, 0x00, -1, 0x03, 0x001a, 0x0009 }, + { 0x04, 0x00, -1, 0x00, 0x0022, 0x0002 }, + { 0x04, 0x00, -1, 0x01, 0x0022, 0x0003 }, + { 0x04, 0x00, -1, 0x02, 0x0022, 0x0004 }, + { 0x04, 0x00, -1, 0x03, 0x0022, 0x0005 }, + { 0x04, 0x00, -1, 0x03, 0x0022, 0x0006 }, + { 0x04, 0x00, -1, 0x03, 0x0022, 0x0007 }, + { 0x04, 0x00, -1, 0x03, 0x0022, 0x0008 }, + { 0x04, 0x00, -1, 0x03, 0x0022, 0x0009 }, + { 0x04, 0x00, -1, 0x00, 0x0032, 0x0002 }, + { 0x04, 0x00, -1, 0x01, 0x0032, 0x0003 }, + { 0x04, 0x00, -1, 0x02, 0x0032, 0x0004 }, + { 0x04, 0x00, -1, 0x03, 0x0032, 0x0005 }, + { 0x04, 0x00, -1, 0x03, 0x0032, 0x0006 }, + { 0x04, 0x00, -1, 0x03, 0x0032, 0x0007 }, + { 0x04, 0x00, -1, 0x03, 0x0032, 0x0008 }, + { 0x04, 0x00, -1, 0x03, 0x0032, 0x0009 }, + { 0x05, 0x00, -1, 0x00, 0x0042, 0x0002 }, + { 0x05, 0x00, -1, 0x01, 0x0042, 0x0003 }, + { 0x05, 0x00, -1, 0x02, 0x0042, 0x0004 }, + { 0x05, 0x00, -1, 0x03, 0x0042, 0x0005 }, + { 0x05, 0x00, -1, 0x03, 0x0042, 0x0006 }, + { 0x05, 0x00, -1, 0x03, 0x0042, 0x0007 }, + { 0x05, 0x00, -1, 0x03, 0x0042, 0x0008 }, + { 0x05, 0x00, -1, 0x03, 0x0042, 0x0009 }, + { 0x05, 0x00, -1, 0x00, 0x0062, 0x0002 }, + { 0x05, 0x00, -1, 0x01, 0x0062, 0x0003 }, + { 0x05, 0x00, -1, 0x02, 0x0062, 0x0004 }, + { 0x05, 0x00, -1, 0x03, 0x0062, 0x0005 }, + { 0x05, 0x00, -1, 0x03, 0x0062, 0x0006 }, + { 0x05, 0x00, -1, 0x03, 0x0062, 0x0007 }, + { 0x05, 0x00, -1, 0x03, 0x0062, 0x0008 }, + { 0x05, 0x00, -1, 0x03, 0x0062, 0x0009 }, + { 0x02, 0x01, -1, 0x03, 0x000a, 0x000a }, + { 0x02, 0x01, -1, 0x03, 0x000a, 0x000c }, + { 0x02, 0x02, -1, 0x03, 0x000a, 0x000e }, + { 0x02, 0x02, -1, 0x03, 0x000a, 0x0012 }, + { 0x02, 0x03, -1, 0x03, 0x000a, 0x0016 }, + { 0x02, 0x03, -1, 0x03, 0x000a, 0x001e }, + { 0x02, 0x04, -1, 0x03, 0x000a, 0x0026 }, + { 0x02, 0x04, -1, 0x03, 0x000a, 0x0036 }, + { 0x02, 0x01, -1, 0x03, 0x000e, 0x000a }, + { 0x02, 0x01, -1, 0x03, 0x000e, 0x000c }, + { 0x02, 0x02, -1, 0x03, 0x000e, 0x000e }, + { 0x02, 0x02, -1, 0x03, 0x000e, 0x0012 }, + { 0x02, 0x03, -1, 0x03, 0x000e, 0x0016 }, + { 0x02, 0x03, -1, 0x03, 0x000e, 0x001e }, + { 0x02, 0x04, -1, 0x03, 0x000e, 0x0026 }, + { 0x02, 0x04, -1, 0x03, 0x000e, 0x0036 }, + { 0x03, 0x01, -1, 0x03, 0x0012, 0x000a }, + { 0x03, 0x01, -1, 0x03, 0x0012, 0x000c }, + { 0x03, 0x02, -1, 0x03, 0x0012, 0x000e }, + { 0x03, 0x02, -1, 0x03, 0x0012, 0x0012 }, + { 0x03, 0x03, -1, 0x03, 0x0012, 0x0016 }, + { 0x03, 0x03, -1, 0x03, 0x0012, 0x001e }, + { 0x03, 0x04, -1, 0x03, 0x0012, 0x0026 }, + { 0x03, 0x04, -1, 0x03, 0x0012, 0x0036 }, + { 0x03, 0x01, -1, 0x03, 0x001a, 0x000a }, + { 0x03, 0x01, -1, 0x03, 0x001a, 0x000c }, + { 0x03, 0x02, -1, 0x03, 0x001a, 0x000e }, + { 0x03, 0x02, -1, 0x03, 0x001a, 0x0012 }, + { 0x03, 0x03, -1, 0x03, 0x001a, 0x0016 }, + { 0x03, 0x03, -1, 0x03, 0x001a, 0x001e }, + { 0x03, 0x04, -1, 0x03, 0x001a, 0x0026 }, + { 0x03, 0x04, -1, 0x03, 0x001a, 0x0036 }, + { 0x04, 0x01, -1, 0x03, 0x0022, 0x000a }, + { 0x04, 0x01, -1, 0x03, 0x0022, 0x000c }, + { 0x04, 0x02, -1, 0x03, 0x0022, 0x000e }, + { 0x04, 0x02, -1, 0x03, 0x0022, 0x0012 }, + { 0x04, 0x03, -1, 0x03, 0x0022, 0x0016 }, + { 0x04, 0x03, -1, 0x03, 0x0022, 0x001e }, + { 0x04, 0x04, -1, 0x03, 0x0022, 0x0026 }, + { 0x04, 0x04, -1, 0x03, 0x0022, 0x0036 }, + { 0x04, 0x01, -1, 0x03, 0x0032, 0x000a }, + { 0x04, 0x01, -1, 0x03, 0x0032, 0x000c }, + { 0x04, 0x02, -1, 0x03, 0x0032, 0x000e }, + { 0x04, 0x02, -1, 0x03, 0x0032, 0x0012 }, + { 0x04, 0x03, -1, 0x03, 0x0032, 0x0016 }, + { 0x04, 0x03, -1, 0x03, 0x0032, 0x001e }, + { 0x04, 0x04, -1, 0x03, 0x0032, 0x0026 }, + { 0x04, 0x04, -1, 0x03, 0x0032, 0x0036 }, + { 0x05, 0x01, -1, 0x03, 0x0042, 0x000a }, + { 0x05, 0x01, -1, 0x03, 0x0042, 0x000c }, + { 0x05, 0x02, -1, 0x03, 0x0042, 0x000e }, + { 0x05, 0x02, -1, 0x03, 0x0042, 0x0012 }, + { 0x05, 0x03, -1, 0x03, 0x0042, 0x0016 }, + { 0x05, 0x03, -1, 0x03, 0x0042, 0x001e }, + { 0x05, 0x04, -1, 0x03, 0x0042, 0x0026 }, + { 0x05, 0x04, -1, 0x03, 0x0042, 0x0036 }, + { 0x05, 0x01, -1, 0x03, 0x0062, 0x000a }, + { 0x05, 0x01, -1, 0x03, 0x0062, 0x000c }, + { 0x05, 0x02, -1, 0x03, 0x0062, 0x000e }, + { 0x05, 0x02, -1, 0x03, 0x0062, 0x0012 }, + { 0x05, 0x03, -1, 0x03, 0x0062, 0x0016 }, + { 0x05, 0x03, -1, 0x03, 0x0062, 0x001e }, + { 0x05, 0x04, -1, 0x03, 0x0062, 0x0026 }, + { 0x05, 0x04, -1, 0x03, 0x0062, 0x0036 }, + { 0x00, 0x05, -1, 0x03, 0x0000, 0x0046 }, + { 0x00, 0x05, -1, 0x03, 0x0000, 0x0066 }, + { 0x00, 0x06, -1, 0x03, 0x0000, 0x0086 }, + { 0x00, 0x07, -1, 0x03, 0x0000, 0x00c6 }, + { 0x00, 0x08, -1, 0x03, 0x0000, 0x0146 }, + { 0x00, 0x09, -1, 0x03, 0x0000, 0x0246 }, + { 0x00, 0x0a, -1, 0x03, 0x0000, 0x0446 }, + { 0x00, 0x18, -1, 0x03, 0x0000, 0x0846 }, + { 0x00, 0x05, -1, 0x03, 0x0001, 0x0046 }, + { 0x00, 0x05, -1, 0x03, 0x0001, 0x0066 }, + { 0x00, 0x06, -1, 0x03, 0x0001, 0x0086 }, + { 0x00, 0x07, -1, 0x03, 0x0001, 0x00c6 }, + { 0x00, 0x08, -1, 0x03, 0x0001, 0x0146 }, + { 0x00, 0x09, -1, 0x03, 0x0001, 0x0246 }, + { 0x00, 0x0a, -1, 0x03, 0x0001, 0x0446 }, + { 0x00, 0x18, -1, 0x03, 0x0001, 0x0846 }, + { 0x00, 0x05, -1, 0x03, 0x0002, 0x0046 }, + { 0x00, 0x05, -1, 0x03, 0x0002, 0x0066 }, + { 0x00, 0x06, -1, 0x03, 0x0002, 0x0086 }, + { 0x00, 0x07, -1, 0x03, 0x0002, 0x00c6 }, + { 0x00, 0x08, -1, 0x03, 0x0002, 0x0146 }, + { 0x00, 0x09, -1, 0x03, 0x0002, 0x0246 }, + { 0x00, 0x0a, -1, 0x03, 0x0002, 0x0446 }, + { 0x00, 0x18, -1, 0x03, 0x0002, 0x0846 }, + { 0x00, 0x05, -1, 0x03, 0x0003, 0x0046 }, + { 0x00, 0x05, -1, 0x03, 0x0003, 0x0066 }, + { 0x00, 0x06, -1, 0x03, 0x0003, 0x0086 }, + { 0x00, 0x07, -1, 0x03, 0x0003, 0x00c6 }, + { 0x00, 0x08, -1, 0x03, 0x0003, 0x0146 }, + { 0x00, 0x09, -1, 0x03, 0x0003, 0x0246 }, + { 0x00, 0x0a, -1, 0x03, 0x0003, 0x0446 }, + { 0x00, 0x18, -1, 0x03, 0x0003, 0x0846 }, + { 0x00, 0x05, -1, 0x03, 0x0004, 0x0046 }, + { 0x00, 0x05, -1, 0x03, 0x0004, 0x0066 }, + { 0x00, 0x06, -1, 0x03, 0x0004, 0x0086 }, + { 0x00, 0x07, -1, 0x03, 0x0004, 0x00c6 }, + { 0x00, 0x08, -1, 0x03, 0x0004, 0x0146 }, + { 0x00, 0x09, -1, 0x03, 0x0004, 0x0246 }, + { 0x00, 0x0a, -1, 0x03, 0x0004, 0x0446 }, + { 0x00, 0x18, -1, 0x03, 0x0004, 0x0846 }, + { 0x00, 0x05, -1, 0x03, 0x0005, 0x0046 }, + { 0x00, 0x05, -1, 0x03, 0x0005, 0x0066 }, + { 0x00, 0x06, -1, 0x03, 0x0005, 0x0086 }, + { 0x00, 0x07, -1, 0x03, 0x0005, 0x00c6 }, + { 0x00, 0x08, -1, 0x03, 0x0005, 0x0146 }, + { 0x00, 0x09, -1, 0x03, 0x0005, 0x0246 }, + { 0x00, 0x0a, -1, 0x03, 0x0005, 0x0446 }, + { 0x00, 0x18, -1, 0x03, 0x0005, 0x0846 }, + { 0x01, 0x05, -1, 0x03, 0x0006, 0x0046 }, + { 0x01, 0x05, -1, 0x03, 0x0006, 0x0066 }, + { 0x01, 0x06, -1, 0x03, 0x0006, 0x0086 }, + { 0x01, 0x07, -1, 0x03, 0x0006, 0x00c6 }, + { 0x01, 0x08, -1, 0x03, 0x0006, 0x0146 }, + { 0x01, 0x09, -1, 0x03, 0x0006, 0x0246 }, + { 0x01, 0x0a, -1, 0x03, 0x0006, 0x0446 }, + { 0x01, 0x18, -1, 0x03, 0x0006, 0x0846 }, + { 0x01, 0x05, -1, 0x03, 0x0008, 0x0046 }, + { 0x01, 0x05, -1, 0x03, 0x0008, 0x0066 }, + { 0x01, 0x06, -1, 0x03, 0x0008, 0x0086 }, + { 0x01, 0x07, -1, 0x03, 0x0008, 0x00c6 }, + { 0x01, 0x08, -1, 0x03, 0x0008, 0x0146 }, + { 0x01, 0x09, -1, 0x03, 0x0008, 0x0246 }, + { 0x01, 0x0a, -1, 0x03, 0x0008, 0x0446 }, + { 0x01, 0x18, -1, 0x03, 0x0008, 0x0846 }, + { 0x06, 0x00, -1, 0x00, 0x0082, 0x0002 }, + { 0x06, 0x00, -1, 0x01, 0x0082, 0x0003 }, + { 0x06, 0x00, -1, 0x02, 0x0082, 0x0004 }, + { 0x06, 0x00, -1, 0x03, 0x0082, 0x0005 }, + { 0x06, 0x00, -1, 0x03, 0x0082, 0x0006 }, + { 0x06, 0x00, -1, 0x03, 0x0082, 0x0007 }, + { 0x06, 0x00, -1, 0x03, 0x0082, 0x0008 }, + { 0x06, 0x00, -1, 0x03, 0x0082, 0x0009 }, + { 0x07, 0x00, -1, 0x00, 0x00c2, 0x0002 }, + { 0x07, 0x00, -1, 0x01, 0x00c2, 0x0003 }, + { 0x07, 0x00, -1, 0x02, 0x00c2, 0x0004 }, + { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0005 }, + { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0006 }, + { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0007 }, + { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0008 }, + { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0009 }, + { 0x08, 0x00, -1, 0x00, 0x0142, 0x0002 }, + { 0x08, 0x00, -1, 0x01, 0x0142, 0x0003 }, + { 0x08, 0x00, -1, 0x02, 0x0142, 0x0004 }, + { 0x08, 0x00, -1, 0x03, 0x0142, 0x0005 }, + { 0x08, 0x00, -1, 0x03, 0x0142, 0x0006 }, + { 0x08, 0x00, -1, 0x03, 0x0142, 0x0007 }, + { 0x08, 0x00, -1, 0x03, 0x0142, 0x0008 }, + { 0x08, 0x00, -1, 0x03, 0x0142, 0x0009 }, + { 0x09, 0x00, -1, 0x00, 0x0242, 0x0002 }, + { 0x09, 0x00, -1, 0x01, 0x0242, 0x0003 }, + { 0x09, 0x00, -1, 0x02, 0x0242, 0x0004 }, + { 0x09, 0x00, -1, 0x03, 0x0242, 0x0005 }, + { 0x09, 0x00, -1, 0x03, 0x0242, 0x0006 }, + { 0x09, 0x00, -1, 0x03, 0x0242, 0x0007 }, + { 0x09, 0x00, -1, 0x03, 0x0242, 0x0008 }, + { 0x09, 0x00, -1, 0x03, 0x0242, 0x0009 }, + { 0x0a, 0x00, -1, 0x00, 0x0442, 0x0002 }, + { 0x0a, 0x00, -1, 0x01, 0x0442, 0x0003 }, + { 0x0a, 0x00, -1, 0x02, 0x0442, 0x0004 }, + { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0005 }, + { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0006 }, + { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0007 }, + { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0008 }, + { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0009 }, + { 0x0c, 0x00, -1, 0x00, 0x0842, 0x0002 }, + { 0x0c, 0x00, -1, 0x01, 0x0842, 0x0003 }, + { 0x0c, 0x00, -1, 0x02, 0x0842, 0x0004 }, + { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0005 }, + { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0006 }, + { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0007 }, + { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0008 }, + { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0009 }, + { 0x0e, 0x00, -1, 0x00, 0x1842, 0x0002 }, + { 0x0e, 0x00, -1, 0x01, 0x1842, 0x0003 }, + { 0x0e, 0x00, -1, 0x02, 0x1842, 0x0004 }, + { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0005 }, + { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0006 }, + { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0007 }, + { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0008 }, + { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0009 }, + { 0x18, 0x00, -1, 0x00, 0x5842, 0x0002 }, + { 0x18, 0x00, -1, 0x01, 0x5842, 0x0003 }, + { 0x18, 0x00, -1, 0x02, 0x5842, 0x0004 }, + { 0x18, 0x00, -1, 0x03, 0x5842, 0x0005 }, + { 0x18, 0x00, -1, 0x03, 0x5842, 0x0006 }, + { 0x18, 0x00, -1, 0x03, 0x5842, 0x0007 }, + { 0x18, 0x00, -1, 0x03, 0x5842, 0x0008 }, + { 0x18, 0x00, -1, 0x03, 0x5842, 0x0009 }, + { 0x02, 0x05, -1, 0x03, 0x000a, 0x0046 }, + { 0x02, 0x05, -1, 0x03, 0x000a, 0x0066 }, + { 0x02, 0x06, -1, 0x03, 0x000a, 0x0086 }, + { 0x02, 0x07, -1, 0x03, 0x000a, 0x00c6 }, + { 0x02, 0x08, -1, 0x03, 0x000a, 0x0146 }, + { 0x02, 0x09, -1, 0x03, 0x000a, 0x0246 }, + { 0x02, 0x0a, -1, 0x03, 0x000a, 0x0446 }, + { 0x02, 0x18, -1, 0x03, 0x000a, 0x0846 }, + { 0x02, 0x05, -1, 0x03, 0x000e, 0x0046 }, + { 0x02, 0x05, -1, 0x03, 0x000e, 0x0066 }, + { 0x02, 0x06, -1, 0x03, 0x000e, 0x0086 }, + { 0x02, 0x07, -1, 0x03, 0x000e, 0x00c6 }, + { 0x02, 0x08, -1, 0x03, 0x000e, 0x0146 }, + { 0x02, 0x09, -1, 0x03, 0x000e, 0x0246 }, + { 0x02, 0x0a, -1, 0x03, 0x000e, 0x0446 }, + { 0x02, 0x18, -1, 0x03, 0x000e, 0x0846 }, + { 0x03, 0x05, -1, 0x03, 0x0012, 0x0046 }, + { 0x03, 0x05, -1, 0x03, 0x0012, 0x0066 }, + { 0x03, 0x06, -1, 0x03, 0x0012, 0x0086 }, + { 0x03, 0x07, -1, 0x03, 0x0012, 0x00c6 }, + { 0x03, 0x08, -1, 0x03, 0x0012, 0x0146 }, + { 0x03, 0x09, -1, 0x03, 0x0012, 0x0246 }, + { 0x03, 0x0a, -1, 0x03, 0x0012, 0x0446 }, + { 0x03, 0x18, -1, 0x03, 0x0012, 0x0846 }, + { 0x03, 0x05, -1, 0x03, 0x001a, 0x0046 }, + { 0x03, 0x05, -1, 0x03, 0x001a, 0x0066 }, + { 0x03, 0x06, -1, 0x03, 0x001a, 0x0086 }, + { 0x03, 0x07, -1, 0x03, 0x001a, 0x00c6 }, + { 0x03, 0x08, -1, 0x03, 0x001a, 0x0146 }, + { 0x03, 0x09, -1, 0x03, 0x001a, 0x0246 }, + { 0x03, 0x0a, -1, 0x03, 0x001a, 0x0446 }, + { 0x03, 0x18, -1, 0x03, 0x001a, 0x0846 }, + { 0x04, 0x05, -1, 0x03, 0x0022, 0x0046 }, + { 0x04, 0x05, -1, 0x03, 0x0022, 0x0066 }, + { 0x04, 0x06, -1, 0x03, 0x0022, 0x0086 }, + { 0x04, 0x07, -1, 0x03, 0x0022, 0x00c6 }, + { 0x04, 0x08, -1, 0x03, 0x0022, 0x0146 }, + { 0x04, 0x09, -1, 0x03, 0x0022, 0x0246 }, + { 0x04, 0x0a, -1, 0x03, 0x0022, 0x0446 }, + { 0x04, 0x18, -1, 0x03, 0x0022, 0x0846 }, + { 0x04, 0x05, -1, 0x03, 0x0032, 0x0046 }, + { 0x04, 0x05, -1, 0x03, 0x0032, 0x0066 }, + { 0x04, 0x06, -1, 0x03, 0x0032, 0x0086 }, + { 0x04, 0x07, -1, 0x03, 0x0032, 0x00c6 }, + { 0x04, 0x08, -1, 0x03, 0x0032, 0x0146 }, + { 0x04, 0x09, -1, 0x03, 0x0032, 0x0246 }, + { 0x04, 0x0a, -1, 0x03, 0x0032, 0x0446 }, + { 0x04, 0x18, -1, 0x03, 0x0032, 0x0846 }, + { 0x05, 0x05, -1, 0x03, 0x0042, 0x0046 }, + { 0x05, 0x05, -1, 0x03, 0x0042, 0x0066 }, + { 0x05, 0x06, -1, 0x03, 0x0042, 0x0086 }, + { 0x05, 0x07, -1, 0x03, 0x0042, 0x00c6 }, + { 0x05, 0x08, -1, 0x03, 0x0042, 0x0146 }, + { 0x05, 0x09, -1, 0x03, 0x0042, 0x0246 }, + { 0x05, 0x0a, -1, 0x03, 0x0042, 0x0446 }, + { 0x05, 0x18, -1, 0x03, 0x0042, 0x0846 }, + { 0x05, 0x05, -1, 0x03, 0x0062, 0x0046 }, + { 0x05, 0x05, -1, 0x03, 0x0062, 0x0066 }, + { 0x05, 0x06, -1, 0x03, 0x0062, 0x0086 }, + { 0x05, 0x07, -1, 0x03, 0x0062, 0x00c6 }, + { 0x05, 0x08, -1, 0x03, 0x0062, 0x0146 }, + { 0x05, 0x09, -1, 0x03, 0x0062, 0x0246 }, + { 0x05, 0x0a, -1, 0x03, 0x0062, 0x0446 }, + { 0x05, 0x18, -1, 0x03, 0x0062, 0x0846 }, + { 0x06, 0x01, -1, 0x03, 0x0082, 0x000a }, + { 0x06, 0x01, -1, 0x03, 0x0082, 0x000c }, + { 0x06, 0x02, -1, 0x03, 0x0082, 0x000e }, + { 0x06, 0x02, -1, 0x03, 0x0082, 0x0012 }, + { 0x06, 0x03, -1, 0x03, 0x0082, 0x0016 }, + { 0x06, 0x03, -1, 0x03, 0x0082, 0x001e }, + { 0x06, 0x04, -1, 0x03, 0x0082, 0x0026 }, + { 0x06, 0x04, -1, 0x03, 0x0082, 0x0036 }, + { 0x07, 0x01, -1, 0x03, 0x00c2, 0x000a }, + { 0x07, 0x01, -1, 0x03, 0x00c2, 0x000c }, + { 0x07, 0x02, -1, 0x03, 0x00c2, 0x000e }, + { 0x07, 0x02, -1, 0x03, 0x00c2, 0x0012 }, + { 0x07, 0x03, -1, 0x03, 0x00c2, 0x0016 }, + { 0x07, 0x03, -1, 0x03, 0x00c2, 0x001e }, + { 0x07, 0x04, -1, 0x03, 0x00c2, 0x0026 }, + { 0x07, 0x04, -1, 0x03, 0x00c2, 0x0036 }, + { 0x08, 0x01, -1, 0x03, 0x0142, 0x000a }, + { 0x08, 0x01, -1, 0x03, 0x0142, 0x000c }, + { 0x08, 0x02, -1, 0x03, 0x0142, 0x000e }, + { 0x08, 0x02, -1, 0x03, 0x0142, 0x0012 }, + { 0x08, 0x03, -1, 0x03, 0x0142, 0x0016 }, + { 0x08, 0x03, -1, 0x03, 0x0142, 0x001e }, + { 0x08, 0x04, -1, 0x03, 0x0142, 0x0026 }, + { 0x08, 0x04, -1, 0x03, 0x0142, 0x0036 }, + { 0x09, 0x01, -1, 0x03, 0x0242, 0x000a }, + { 0x09, 0x01, -1, 0x03, 0x0242, 0x000c }, + { 0x09, 0x02, -1, 0x03, 0x0242, 0x000e }, + { 0x09, 0x02, -1, 0x03, 0x0242, 0x0012 }, + { 0x09, 0x03, -1, 0x03, 0x0242, 0x0016 }, + { 0x09, 0x03, -1, 0x03, 0x0242, 0x001e }, + { 0x09, 0x04, -1, 0x03, 0x0242, 0x0026 }, + { 0x09, 0x04, -1, 0x03, 0x0242, 0x0036 }, + { 0x0a, 0x01, -1, 0x03, 0x0442, 0x000a }, + { 0x0a, 0x01, -1, 0x03, 0x0442, 0x000c }, + { 0x0a, 0x02, -1, 0x03, 0x0442, 0x000e }, + { 0x0a, 0x02, -1, 0x03, 0x0442, 0x0012 }, + { 0x0a, 0x03, -1, 0x03, 0x0442, 0x0016 }, + { 0x0a, 0x03, -1, 0x03, 0x0442, 0x001e }, + { 0x0a, 0x04, -1, 0x03, 0x0442, 0x0026 }, + { 0x0a, 0x04, -1, 0x03, 0x0442, 0x0036 }, + { 0x0c, 0x01, -1, 0x03, 0x0842, 0x000a }, + { 0x0c, 0x01, -1, 0x03, 0x0842, 0x000c }, + { 0x0c, 0x02, -1, 0x03, 0x0842, 0x000e }, + { 0x0c, 0x02, -1, 0x03, 0x0842, 0x0012 }, + { 0x0c, 0x03, -1, 0x03, 0x0842, 0x0016 }, + { 0x0c, 0x03, -1, 0x03, 0x0842, 0x001e }, + { 0x0c, 0x04, -1, 0x03, 0x0842, 0x0026 }, + { 0x0c, 0x04, -1, 0x03, 0x0842, 0x0036 }, + { 0x0e, 0x01, -1, 0x03, 0x1842, 0x000a }, + { 0x0e, 0x01, -1, 0x03, 0x1842, 0x000c }, + { 0x0e, 0x02, -1, 0x03, 0x1842, 0x000e }, + { 0x0e, 0x02, -1, 0x03, 0x1842, 0x0012 }, + { 0x0e, 0x03, -1, 0x03, 0x1842, 0x0016 }, + { 0x0e, 0x03, -1, 0x03, 0x1842, 0x001e }, + { 0x0e, 0x04, -1, 0x03, 0x1842, 0x0026 }, + { 0x0e, 0x04, -1, 0x03, 0x1842, 0x0036 }, + { 0x18, 0x01, -1, 0x03, 0x5842, 0x000a }, + { 0x18, 0x01, -1, 0x03, 0x5842, 0x000c }, + { 0x18, 0x02, -1, 0x03, 0x5842, 0x000e }, + { 0x18, 0x02, -1, 0x03, 0x5842, 0x0012 }, + { 0x18, 0x03, -1, 0x03, 0x5842, 0x0016 }, + { 0x18, 0x03, -1, 0x03, 0x5842, 0x001e }, + { 0x18, 0x04, -1, 0x03, 0x5842, 0x0026 }, + { 0x18, 0x04, -1, 0x03, 0x5842, 0x0036 }, + { 0x06, 0x05, -1, 0x03, 0x0082, 0x0046 }, + { 0x06, 0x05, -1, 0x03, 0x0082, 0x0066 }, + { 0x06, 0x06, -1, 0x03, 0x0082, 0x0086 }, + { 0x06, 0x07, -1, 0x03, 0x0082, 0x00c6 }, + { 0x06, 0x08, -1, 0x03, 0x0082, 0x0146 }, + { 0x06, 0x09, -1, 0x03, 0x0082, 0x0246 }, + { 0x06, 0x0a, -1, 0x03, 0x0082, 0x0446 }, + { 0x06, 0x18, -1, 0x03, 0x0082, 0x0846 }, + { 0x07, 0x05, -1, 0x03, 0x00c2, 0x0046 }, + { 0x07, 0x05, -1, 0x03, 0x00c2, 0x0066 }, + { 0x07, 0x06, -1, 0x03, 0x00c2, 0x0086 }, + { 0x07, 0x07, -1, 0x03, 0x00c2, 0x00c6 }, + { 0x07, 0x08, -1, 0x03, 0x00c2, 0x0146 }, + { 0x07, 0x09, -1, 0x03, 0x00c2, 0x0246 }, + { 0x07, 0x0a, -1, 0x03, 0x00c2, 0x0446 }, + { 0x07, 0x18, -1, 0x03, 0x00c2, 0x0846 }, + { 0x08, 0x05, -1, 0x03, 0x0142, 0x0046 }, + { 0x08, 0x05, -1, 0x03, 0x0142, 0x0066 }, + { 0x08, 0x06, -1, 0x03, 0x0142, 0x0086 }, + { 0x08, 0x07, -1, 0x03, 0x0142, 0x00c6 }, + { 0x08, 0x08, -1, 0x03, 0x0142, 0x0146 }, + { 0x08, 0x09, -1, 0x03, 0x0142, 0x0246 }, + { 0x08, 0x0a, -1, 0x03, 0x0142, 0x0446 }, + { 0x08, 0x18, -1, 0x03, 0x0142, 0x0846 }, + { 0x09, 0x05, -1, 0x03, 0x0242, 0x0046 }, + { 0x09, 0x05, -1, 0x03, 0x0242, 0x0066 }, + { 0x09, 0x06, -1, 0x03, 0x0242, 0x0086 }, + { 0x09, 0x07, -1, 0x03, 0x0242, 0x00c6 }, + { 0x09, 0x08, -1, 0x03, 0x0242, 0x0146 }, + { 0x09, 0x09, -1, 0x03, 0x0242, 0x0246 }, + { 0x09, 0x0a, -1, 0x03, 0x0242, 0x0446 }, + { 0x09, 0x18, -1, 0x03, 0x0242, 0x0846 }, + { 0x0a, 0x05, -1, 0x03, 0x0442, 0x0046 }, + { 0x0a, 0x05, -1, 0x03, 0x0442, 0x0066 }, + { 0x0a, 0x06, -1, 0x03, 0x0442, 0x0086 }, + { 0x0a, 0x07, -1, 0x03, 0x0442, 0x00c6 }, + { 0x0a, 0x08, -1, 0x03, 0x0442, 0x0146 }, + { 0x0a, 0x09, -1, 0x03, 0x0442, 0x0246 }, + { 0x0a, 0x0a, -1, 0x03, 0x0442, 0x0446 }, + { 0x0a, 0x18, -1, 0x03, 0x0442, 0x0846 }, + { 0x0c, 0x05, -1, 0x03, 0x0842, 0x0046 }, + { 0x0c, 0x05, -1, 0x03, 0x0842, 0x0066 }, + { 0x0c, 0x06, -1, 0x03, 0x0842, 0x0086 }, + { 0x0c, 0x07, -1, 0x03, 0x0842, 0x00c6 }, + { 0x0c, 0x08, -1, 0x03, 0x0842, 0x0146 }, + { 0x0c, 0x09, -1, 0x03, 0x0842, 0x0246 }, + { 0x0c, 0x0a, -1, 0x03, 0x0842, 0x0446 }, + { 0x0c, 0x18, -1, 0x03, 0x0842, 0x0846 }, + { 0x0e, 0x05, -1, 0x03, 0x1842, 0x0046 }, + { 0x0e, 0x05, -1, 0x03, 0x1842, 0x0066 }, + { 0x0e, 0x06, -1, 0x03, 0x1842, 0x0086 }, + { 0x0e, 0x07, -1, 0x03, 0x1842, 0x00c6 }, + { 0x0e, 0x08, -1, 0x03, 0x1842, 0x0146 }, + { 0x0e, 0x09, -1, 0x03, 0x1842, 0x0246 }, + { 0x0e, 0x0a, -1, 0x03, 0x1842, 0x0446 }, + { 0x0e, 0x18, -1, 0x03, 0x1842, 0x0846 }, + { 0x18, 0x05, -1, 0x03, 0x5842, 0x0046 }, + { 0x18, 0x05, -1, 0x03, 0x5842, 0x0066 }, + { 0x18, 0x06, -1, 0x03, 0x5842, 0x0086 }, + { 0x18, 0x07, -1, 0x03, 0x5842, 0x00c6 }, + { 0x18, 0x08, -1, 0x03, 0x5842, 0x0146 }, + { 0x18, 0x09, -1, 0x03, 0x5842, 0x0246 }, + { 0x18, 0x0a, -1, 0x03, 0x5842, 0x0446 }, + { 0x18, 0x18, -1, 0x03, 0x5842, 0x0846 }, +}; + +#endif /* BROTLI_DEC_PREFIX_H_ */ diff --git a/third_party/brotli/dec/state.cpp b/third_party/brotli/dec/state.cpp new file mode 100644 index 00000000000..08b8dea3de3 --- /dev/null +++ b/third_party/brotli/dec/state.cpp @@ -0,0 +1,178 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include "state.h" + +#include /* free, malloc */ + +#include + +#include "../common/dictionary.h" +#include "huffman.h" + +using namespace duckdb_brotli; + +BROTLI_BOOL duckdb_brotli::BrotliDecoderStateInit(BrotliDecoderState* s, + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { + if (!alloc_func) { + s->alloc_func = BrotliDefaultAllocFunc; + s->free_func = BrotliDefaultFreeFunc; + s->memory_manager_opaque = 0; + } else { + s->alloc_func = alloc_func; + s->free_func = free_func; + s->memory_manager_opaque = opaque; + } + + s->error_code = 0; /* BROTLI_DECODER_NO_ERROR */ + + BrotliInitBitReader(&s->br); + s->state = BROTLI_STATE_UNINITED; + s->large_window = 0; + s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE; + s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE; + s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE; + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE; + + s->buffer_length = 0; + s->loop_counter = 0; + s->pos = 0; + s->rb_roundtrips = 0; + s->partial_pos_out = 0; + s->used_input = 0; + + s->block_type_trees = NULL; + s->block_len_trees = NULL; + s->ringbuffer = NULL; + s->ringbuffer_size = 0; + s->new_ringbuffer_size = 0; + s->ringbuffer_mask = 0; + + s->context_map = NULL; + s->context_modes = NULL; + s->dist_context_map = NULL; + s->context_map_slice = NULL; + s->dist_context_map_slice = NULL; + + s->literal_hgroup.codes = NULL; + s->literal_hgroup.htrees = NULL; + s->insert_copy_hgroup.codes = NULL; + s->insert_copy_hgroup.htrees = NULL; + s->distance_hgroup.codes = NULL; + s->distance_hgroup.htrees = NULL; + + s->is_last_metablock = 0; + s->is_uncompressed = 0; + s->is_metadata = 0; + s->should_wrap_ringbuffer = 0; + s->canny_ringbuffer_allocation = 1; + + s->window_bits = 0; + s->max_distance = 0; + s->dist_rb[0] = 16; + s->dist_rb[1] = 15; + s->dist_rb[2] = 11; + s->dist_rb[3] = 4; + s->dist_rb_idx = 0; + s->block_type_trees = NULL; + s->block_len_trees = NULL; + + s->mtf_upper_bound = 63; + + s->compound_dictionary = NULL; + s->dictionary = + BrotliSharedDictionaryCreateInstance(alloc_func, free_func, opaque); + if (!s->dictionary) return BROTLI_FALSE; + + s->metadata_start_func = NULL; + s->metadata_chunk_func = NULL; + s->metadata_callback_opaque = 0; + + return BROTLI_TRUE; +} + +void duckdb_brotli::BrotliDecoderStateMetablockBegin(BrotliDecoderState* s) { + s->meta_block_remaining_len = 0; + s->block_length[0] = BROTLI_BLOCK_SIZE_CAP; + s->block_length[1] = BROTLI_BLOCK_SIZE_CAP; + s->block_length[2] = BROTLI_BLOCK_SIZE_CAP; + s->num_block_types[0] = 1; + s->num_block_types[1] = 1; + s->num_block_types[2] = 1; + s->block_type_rb[0] = 1; + s->block_type_rb[1] = 0; + s->block_type_rb[2] = 1; + s->block_type_rb[3] = 0; + s->block_type_rb[4] = 1; + s->block_type_rb[5] = 0; + s->context_map = NULL; + s->context_modes = NULL; + s->dist_context_map = NULL; + s->context_map_slice = NULL; + s->literal_htree = NULL; + s->dist_context_map_slice = NULL; + s->dist_htree_index = 0; + s->context_lookup = NULL; + s->literal_hgroup.codes = NULL; + s->literal_hgroup.htrees = NULL; + s->insert_copy_hgroup.codes = NULL; + s->insert_copy_hgroup.htrees = NULL; + s->distance_hgroup.codes = NULL; + s->distance_hgroup.htrees = NULL; +} + +void duckdb_brotli::BrotliDecoderStateCleanupAfterMetablock(BrotliDecoderState* s) { + BROTLI_DECODER_FREE(s, s->context_modes); + BROTLI_DECODER_FREE(s, s->context_map); + BROTLI_DECODER_FREE(s, s->dist_context_map); + BROTLI_DECODER_FREE(s, s->literal_hgroup.htrees); + BROTLI_DECODER_FREE(s, s->insert_copy_hgroup.htrees); + BROTLI_DECODER_FREE(s, s->distance_hgroup.htrees); +} + +#ifdef BROTLI_REPORTING +/* When BROTLI_REPORTING is defined extra reporting module have to be linked. */ +void BrotliDecoderOnFinish(const BrotliDecoderState* s); +#define BROTLI_DECODER_ON_FINISH(s) BrotliDecoderOnFinish(s); +#else +#if !defined(BROTLI_DECODER_ON_FINISH) +#define BROTLI_DECODER_ON_FINISH(s) (void)(s); +#endif +#endif + +void duckdb_brotli::BrotliDecoderStateCleanup(BrotliDecoderState* s) { + BrotliDecoderStateCleanupAfterMetablock(s); + + BROTLI_DECODER_ON_FINISH(s); + + BROTLI_DECODER_FREE(s, s->compound_dictionary); + BrotliSharedDictionaryDestroyInstance(s->dictionary); + s->dictionary = NULL; + BROTLI_DECODER_FREE(s, s->ringbuffer); + BROTLI_DECODER_FREE(s, s->block_type_trees); +} + +BROTLI_BOOL duckdb_brotli::BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState* s, + HuffmanTreeGroup* group, brotli_reg_t alphabet_size_max, + brotli_reg_t alphabet_size_limit, brotli_reg_t ntrees) { + /* 376 = 256 (1-st level table) + 4 + 7 + 15 + 31 + 63 (2-nd level mix-tables) + This number is discovered "unlimited" "enough" calculator; it is actually + a wee bigger than required in several cases (especially for alphabets with + less than 16 symbols). */ + const size_t max_table_size = alphabet_size_limit + 376; + const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size; + const size_t htree_size = sizeof(HuffmanCode*) * ntrees; + /* Pointer alignment is, hopefully, wider than sizeof(HuffmanCode). */ + HuffmanCode** p = (HuffmanCode**)BROTLI_DECODER_ALLOC(s, + code_size + htree_size); + group->alphabet_size_max = (uint16_t)alphabet_size_max; + group->alphabet_size_limit = (uint16_t)alphabet_size_limit; + group->num_htrees = (uint16_t)ntrees; + group->htrees = p; + group->codes = (HuffmanCode*)(&p[ntrees]); + return !!p; +} + diff --git a/third_party/brotli/dec/state.h b/third_party/brotli/dec/state.h new file mode 100644 index 00000000000..fcfe4ab4196 --- /dev/null +++ b/third_party/brotli/dec/state.h @@ -0,0 +1,386 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Brotli state for partial streaming decoding. */ + +#ifndef BROTLI_DEC_STATE_H_ +#define BROTLI_DEC_STATE_H_ + +#include +#include +#include + +#include "../common/brotli_constants.h" +#include "../common/dictionary.h" +#include "../common/brotli_platform.h" +#include "../common/transform.h" +#include "bit_reader.h" +#include "huffman.h" + +namespace duckdb_brotli { + +/* Graphviz diagram that describes state transitions: + +digraph States { + graph [compound=true] + concentrate=true + node [shape="box"] + + UNINITED -> {LARGE_WINDOW_BITS -> INITIALIZE} + subgraph cluster_metablock_workflow { + style="rounded" + label=< METABLOCK CYCLE > + METABLOCK_BEGIN -> METABLOCK_HEADER + METABLOCK_HEADER:sw -> METADATA + METABLOCK_HEADER:s -> UNCOMPRESSED + METABLOCK_HEADER:se -> METABLOCK_DONE:ne + METADATA:s -> METABLOCK_DONE:w + UNCOMPRESSED:s -> METABLOCK_DONE:n + METABLOCK_DONE:e -> METABLOCK_BEGIN:e [constraint="false"] + } + INITIALIZE -> METABLOCK_BEGIN + METABLOCK_DONE -> DONE + + subgraph cluster_compressed_metablock { + style="rounded" + label=< COMPRESSED METABLOCK > + + subgraph cluster_command { + style="rounded" + label=< HOT LOOP > + + _METABLOCK_DONE_PORT_ [shape=point style=invis] + + { + // Set different shape for nodes returning from "compressed metablock". + node [shape=invhouse]; CMD_INNER CMD_POST_DECODE_LITERALS; + CMD_POST_WRAP_COPY; CMD_INNER_WRITE; CMD_POST_WRITE_1; + } + + CMD_BEGIN -> CMD_INNER -> CMD_POST_DECODE_LITERALS -> CMD_POST_WRAP_COPY + + // IO ("write") nodes are not in the hot loop! + CMD_INNER_WRITE [style=dashed] + CMD_INNER -> CMD_INNER_WRITE + CMD_POST_WRITE_1 [style=dashed] + CMD_POST_DECODE_LITERALS -> CMD_POST_WRITE_1 + CMD_POST_WRITE_2 [style=dashed] + CMD_POST_WRAP_COPY -> CMD_POST_WRITE_2 + + CMD_POST_WRITE_1 -> CMD_BEGIN:s [constraint="false"] + CMD_INNER_WRITE -> {CMD_INNER CMD_POST_DECODE_LITERALS} + [constraint="false"] + CMD_BEGIN:ne -> CMD_POST_DECODE_LITERALS [constraint="false"] + CMD_POST_WRAP_COPY -> CMD_BEGIN [constraint="false"] + CMD_POST_DECODE_LITERALS -> CMD_BEGIN:ne [constraint="false"] + CMD_POST_WRITE_2 -> CMD_POST_WRAP_COPY [constraint="false"] + {rank=same; CMD_BEGIN; CMD_INNER; CMD_POST_DECODE_LITERALS; + CMD_POST_WRAP_COPY} + {rank=same; CMD_INNER_WRITE; CMD_POST_WRITE_1; CMD_POST_WRITE_2} + + {CMD_INNER CMD_POST_DECODE_LITERALS CMD_POST_WRAP_COPY} -> + _METABLOCK_DONE_PORT_ [style=invis] + {CMD_INNER_WRITE CMD_POST_WRITE_1} -> _METABLOCK_DONE_PORT_ + [constraint="false" style=invis] + } + + BEFORE_COMPRESSED_METABLOCK_HEADER:s -> HUFFMAN_CODE_0:n + HUFFMAN_CODE_0 -> HUFFMAN_CODE_1 -> HUFFMAN_CODE_2 -> HUFFMAN_CODE_3 + HUFFMAN_CODE_0 -> METABLOCK_HEADER_2 -> CONTEXT_MODES -> CONTEXT_MAP_1 + CONTEXT_MAP_1 -> CONTEXT_MAP_2 -> TREE_GROUP + TREE_GROUP -> BEFORE_COMPRESSED_METABLOCK_BODY:e + BEFORE_COMPRESSED_METABLOCK_BODY:s -> CMD_BEGIN:n + + HUFFMAN_CODE_3:e -> HUFFMAN_CODE_0:ne [constraint="false"] + {rank=same; HUFFMAN_CODE_0; HUFFMAN_CODE_1; HUFFMAN_CODE_2; HUFFMAN_CODE_3} + {rank=same; METABLOCK_HEADER_2; CONTEXT_MODES; CONTEXT_MAP_1; CONTEXT_MAP_2; + TREE_GROUP} + } + METABLOCK_HEADER:e -> BEFORE_COMPRESSED_METABLOCK_HEADER:n + + _METABLOCK_DONE_PORT_ -> METABLOCK_DONE:se + [constraint="false" ltail=cluster_command] + + UNINITED [shape=Mdiamond]; + DONE [shape=Msquare]; +} + + + */ + +typedef enum { + BROTLI_STATE_UNINITED, + BROTLI_STATE_LARGE_WINDOW_BITS, + BROTLI_STATE_INITIALIZE, + BROTLI_STATE_METABLOCK_BEGIN, + BROTLI_STATE_METABLOCK_HEADER, + BROTLI_STATE_METABLOCK_HEADER_2, + BROTLI_STATE_CONTEXT_MODES, + BROTLI_STATE_COMMAND_BEGIN, + BROTLI_STATE_COMMAND_INNER, + BROTLI_STATE_COMMAND_POST_DECODE_LITERALS, + BROTLI_STATE_COMMAND_POST_WRAP_COPY, + BROTLI_STATE_UNCOMPRESSED, + BROTLI_STATE_METADATA, + BROTLI_STATE_COMMAND_INNER_WRITE, + BROTLI_STATE_METABLOCK_DONE, + BROTLI_STATE_COMMAND_POST_WRITE_1, + BROTLI_STATE_COMMAND_POST_WRITE_2, + BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER, + BROTLI_STATE_HUFFMAN_CODE_0, + BROTLI_STATE_HUFFMAN_CODE_1, + BROTLI_STATE_HUFFMAN_CODE_2, + BROTLI_STATE_HUFFMAN_CODE_3, + BROTLI_STATE_CONTEXT_MAP_1, + BROTLI_STATE_CONTEXT_MAP_2, + BROTLI_STATE_TREE_GROUP, + BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY, + BROTLI_STATE_DONE +} BrotliRunningState; + +typedef enum { + BROTLI_STATE_METABLOCK_HEADER_NONE, + BROTLI_STATE_METABLOCK_HEADER_EMPTY, + BROTLI_STATE_METABLOCK_HEADER_NIBBLES, + BROTLI_STATE_METABLOCK_HEADER_SIZE, + BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED, + BROTLI_STATE_METABLOCK_HEADER_RESERVED, + BROTLI_STATE_METABLOCK_HEADER_BYTES, + BROTLI_STATE_METABLOCK_HEADER_METADATA +} BrotliRunningMetablockHeaderState; + +typedef enum { BROTLI_STATE_UNCOMPRESSED_NONE, BROTLI_STATE_UNCOMPRESSED_WRITE } BrotliRunningUncompressedState; + +typedef enum { BROTLI_STATE_TREE_GROUP_NONE, BROTLI_STATE_TREE_GROUP_LOOP } BrotliRunningTreeGroupState; + +typedef enum { + BROTLI_STATE_CONTEXT_MAP_NONE, + BROTLI_STATE_CONTEXT_MAP_READ_PREFIX, + BROTLI_STATE_CONTEXT_MAP_HUFFMAN, + BROTLI_STATE_CONTEXT_MAP_DECODE, + BROTLI_STATE_CONTEXT_MAP_TRANSFORM +} BrotliRunningContextMapState; + +typedef enum { + BROTLI_STATE_HUFFMAN_NONE, + BROTLI_STATE_HUFFMAN_SIMPLE_SIZE, + BROTLI_STATE_HUFFMAN_SIMPLE_READ, + BROTLI_STATE_HUFFMAN_SIMPLE_BUILD, + BROTLI_STATE_HUFFMAN_COMPLEX, + BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS +} BrotliRunningHuffmanState; + +typedef enum { + BROTLI_STATE_DECODE_UINT8_NONE, + BROTLI_STATE_DECODE_UINT8_SHORT, + BROTLI_STATE_DECODE_UINT8_LONG +} BrotliRunningDecodeUint8State; + +typedef enum { + BROTLI_STATE_READ_BLOCK_LENGTH_NONE, + BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX +} BrotliRunningReadBlockLengthState; + +/* BrotliDecoderState addon, used for Compound Dictionary functionality. */ +typedef struct BrotliDecoderCompoundDictionary { + int num_chunks; + int total_size; + int br_index; + int br_offset; + int br_length; + int br_copied; + const uint8_t *chunks[16]; + int chunk_offsets[16]; + int block_bits; + uint8_t block_map[256]; +} BrotliDecoderCompoundDictionary; + +typedef struct BrotliMetablockHeaderArena { + BrotliRunningTreeGroupState substate_tree_group; + BrotliRunningContextMapState substate_context_map; + BrotliRunningHuffmanState substate_huffman; + + brotli_reg_t sub_loop_counter; + + brotli_reg_t repeat_code_len; + brotli_reg_t prev_code_len; + + /* For ReadHuffmanCode. */ + brotli_reg_t symbol; + brotli_reg_t repeat; + brotli_reg_t space; + + /* Huffman table for "histograms". */ + HuffmanCode table[32]; + /* List of heads of symbol chains. */ + uint16_t *symbol_lists; + /* Storage from symbol_lists. */ + uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 + BROTLI_NUM_COMMAND_SYMBOLS]; + /* Tails of symbol chains. */ + int next_symbol[32]; + uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES]; + /* Population counts for the code lengths. */ + uint16_t code_length_histo[16]; + /* TODO(eustas): +2 bytes padding */ + + /* For HuffmanTreeGroupDecode. */ + int htree_index; + HuffmanCode *next; + + /* For DecodeContextMap. */ + brotli_reg_t context_index; + brotli_reg_t max_run_length_prefix; + brotli_reg_t code; + HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272]; +} BrotliMetablockHeaderArena; + +typedef struct BrotliMetablockBodyArena { + uint8_t dist_extra_bits[544]; + brotli_reg_t dist_offset[544]; +} BrotliMetablockBodyArena; + +struct BrotliDecoderStateStruct { + BrotliRunningState state; + + /* This counter is reused for several disjoint loops. */ + int loop_counter; + + BrotliBitReader br; + + brotli_alloc_func alloc_func; + brotli_free_func free_func; + void *memory_manager_opaque; + + /* Temporary storage for remaining input. Brotli stream format is designed in + a way, that 64 bits are enough to make progress in decoding. */ + union { + uint64_t u64; + uint8_t u8[8]; + } buffer; + brotli_reg_t buffer_length; + + int pos; + int max_backward_distance; + int max_distance; + int ringbuffer_size; + int ringbuffer_mask; + int dist_rb_idx; + int dist_rb[4]; + int error_code; + int meta_block_remaining_len; + + uint8_t *ringbuffer; + uint8_t *ringbuffer_end; + HuffmanCode *htree_command; + const uint8_t *context_lookup; + uint8_t *context_map_slice; + uint8_t *dist_context_map_slice; + + /* This ring buffer holds a few past copy distances that will be used by + some special distance codes. */ + HuffmanTreeGroup literal_hgroup; + HuffmanTreeGroup insert_copy_hgroup; + HuffmanTreeGroup distance_hgroup; + HuffmanCode *block_type_trees; + HuffmanCode *block_len_trees; + /* This is true if the literal context map histogram type always matches the + block type. It is then not needed to keep the context (faster decoding). */ + int trivial_literal_context; + /* Distance context is actual after command is decoded and before distance is + computed. After distance computation it is used as a temporary variable. */ + int distance_context; + brotli_reg_t block_length[3]; + brotli_reg_t block_length_index; + brotli_reg_t num_block_types[3]; + brotli_reg_t block_type_rb[6]; + brotli_reg_t distance_postfix_bits; + brotli_reg_t num_direct_distance_codes; + brotli_reg_t num_dist_htrees; + uint8_t *dist_context_map; + HuffmanCode *literal_htree; + + /* For partial write operations. */ + size_t rb_roundtrips; /* how many times we went around the ring-buffer */ + size_t partial_pos_out; /* how much output to the user in total */ + + /* For InverseMoveToFrontTransform. */ + brotli_reg_t mtf_upper_bound; + uint32_t mtf[64 + 1]; + + int copy_length; + int distance_code; + + uint8_t dist_htree_index; + /* TODO(eustas): +3 bytes padding */ + + /* Less used attributes are at the end of this struct. */ + + brotli_decoder_metadata_start_func metadata_start_func; + brotli_decoder_metadata_chunk_func metadata_chunk_func; + void *metadata_callback_opaque; + + /* For reporting. */ + uint64_t used_input; /* how many bytes of input are consumed */ + + /* States inside function calls. */ + BrotliRunningMetablockHeaderState substate_metablock_header; + BrotliRunningUncompressedState substate_uncompressed; + BrotliRunningDecodeUint8State substate_decode_uint8; + BrotliRunningReadBlockLengthState substate_read_block_length; + + int new_ringbuffer_size; + /* TODO(eustas): +4 bytes padding */ + + unsigned int is_last_metablock : 1; + unsigned int is_uncompressed : 1; + unsigned int is_metadata : 1; + unsigned int should_wrap_ringbuffer : 1; + unsigned int canny_ringbuffer_allocation : 1; + unsigned int large_window : 1; + unsigned int window_bits : 6; + unsigned int size_nibbles : 8; + /* TODO(eustas): +12 bits padding */ + + brotli_reg_t num_literal_htrees; + uint8_t *context_map; + uint8_t *context_modes; + + BrotliSharedDictionary *dictionary; + BrotliDecoderCompoundDictionary *compound_dictionary; + + uint32_t trivial_literal_contexts[8]; /* 256 bits */ + + union { + BrotliMetablockHeaderArena header; + BrotliMetablockBodyArena body; + } arena; +}; + +typedef struct BrotliDecoderStateStruct BrotliDecoderStateInternal; +#define BrotliDecoderState BrotliDecoderStateInternal + +BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState *s, brotli_alloc_func alloc_func, + brotli_free_func free_func, void *opaque); +BROTLI_INTERNAL void BrotliDecoderStateCleanup(BrotliDecoderState *s); +BROTLI_INTERNAL void BrotliDecoderStateMetablockBegin(BrotliDecoderState *s); +BROTLI_INTERNAL void BrotliDecoderStateCleanupAfterMetablock(BrotliDecoderState *s); +BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState *s, HuffmanTreeGroup *group, + brotli_reg_t alphabet_size_max, + brotli_reg_t alphabet_size_limit, brotli_reg_t ntrees); + +#define BROTLI_DECODER_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L) + +#define BROTLI_DECODER_FREE(S, X) { \ + S->free_func(S->memory_manager_opaque, X); \ + X = NULL; \ +} + +/* Literal/Command/Distance block size maximum; same as maximum metablock size; + used as block size when there is no block switching. */ +#define BROTLI_BLOCK_SIZE_CAP (1U << 24) + +} +#endif /* BROTLI_DEC_STATE_H_ */ diff --git a/third_party/brotli/enc/backward_references.cpp b/third_party/brotli/enc/backward_references.cpp new file mode 100644 index 00000000000..5f338adc1da --- /dev/null +++ b/third_party/brotli/enc/backward_references.cpp @@ -0,0 +1,3775 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Function to find backward reference copies. */ + +#include "backward_references.h" + +#include + +#include "../common/brotli_constants.h" +#include "../common/dictionary.h" +#include "../common/brotli_platform.h" +#include "command.h" +#include "compound_dictionary.h" +#include "dictionary_hash.h" +#include "encoder_dict.h" +#include "memory.h" +#include "quality.h" + +using namespace duckdb_brotli; + +static BROTLI_INLINE size_t ComputeDistanceCode(size_t distance, + size_t max_distance, + const int* dist_cache) { + if (distance <= max_distance) { + size_t distance_plus_3 = distance + 3; + size_t offset0 = distance_plus_3 - (size_t)dist_cache[0]; + size_t offset1 = distance_plus_3 - (size_t)dist_cache[1]; + if (distance == (size_t)dist_cache[0]) { + return 0; + } else if (distance == (size_t)dist_cache[1]) { + return 1; + } else if (offset0 < 7) { + return (0x9750468 >> (4 * offset0)) & 0xF; + } else if (offset1 < 7) { + return (0xFDB1ACE >> (4 * offset1)) & 0xF; + } else if (distance == (size_t)dist_cache[2]) { + return 2; + } else if (distance == (size_t)dist_cache[3]) { + return 3; + } + } + return distance + BROTLI_NUM_DISTANCE_SHORT_CODES - 1; +} + +#define EXPAND_CAT(a, b) CAT(a, b) +#define CAT(a, b) a ## b +#define FN(X) EXPAND_CAT(X, HASHER()) +#define EXPORT_FN(X) EXPAND_CAT(X, EXPAND_CAT(PREFIX(), HASHER())) + +#define PREFIX() N +#define ENABLE_COMPOUND_DICTIONARY 0 + +#define HASHER() H2 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H3 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H4 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H5 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H6 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H40 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H41 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H42 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H54 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H35 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H55 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#define HASHER() H65 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#undef ENABLE_COMPOUND_DICTIONARY +#undef PREFIX +#define PREFIX() D +#define ENABLE_COMPOUND_DICTIONARY 1 + +#define HASHER() H5 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER +#define HASHER() H6 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER +#define HASHER() H40 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER +#define HASHER() H41 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER +#define HASHER() H42 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER +#define HASHER() H55 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER +#define HASHER() H65 +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: EXPORT_FN, FN */ + +static BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)( + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + HASHER()* privat = &hasher->privat.FN(_); + /* Set maximum distance, see section 9.1. of the spec. */ + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t position_offset = params->stream_offset; + + const Command* const orig_commands = commands; + size_t insert_length = *last_insert_len; + const size_t pos_end = position + num_bytes; + const size_t store_end = num_bytes >= FN(StoreLookahead)() ? + position + num_bytes - FN(StoreLookahead)() + 1 : position; + + /* For speed up heuristics for random data. */ + const size_t random_heuristics_window_size = + LiteralSpreeLengthForSparseSearch(params); + size_t apply_random_heuristics = position + random_heuristics_window_size; + const size_t gap = params->dictionary.compound.total_size; + + /* Minimum score to accept a backward reference. */ + const score_t kMinScore = BROTLI_SCORE_BASE + 100; + + FN(PrepareDistanceCache)(privat, dist_cache); + + while (position + FN(HashTypeLength)() < pos_end) { + size_t max_length = pos_end - position; + size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + HasherSearchResult sr; + int dict_id = 0; + uint8_t p1 = 0; + uint8_t p2 = 0; + if (params->dictionary.contextual.context_based) { + p1 = position >= 1 ? + ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0; + p2 = position >= 2 ? + ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + sr.len = 0; + sr.len_code_delta = 0; + sr.distance = 0; + sr.score = kMinScore; + FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, &sr); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch(¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position, max_length, + dictionary_start, params->dist.max_distance, &sr); + } + if (sr.score > kMinScore) { + /* Found a match. Let's look for something even better ahead. */ + int delayed_backward_references_in_row = 0; + --max_length; + for (;; --max_length) { + const score_t cost_diff_lazy = 175; + HasherSearchResult sr2; + sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ? + BROTLI_MIN(size_t, sr.len - 1, max_length) : 0; + sr2.len_code_delta = 0; + sr2.distance = 0; + sr2.score = kMinScore; + max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit); + dictionary_start = BROTLI_MIN(size_t, + position + 1 + position_offset, max_backward_limit); + if (params->dictionary.contextual.context_based) { + p2 = p1; + p1 = ringbuffer[position & ringbuffer_mask]; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + FN(FindLongestMatch)(privat, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length, + max_distance, dictionary_start + gap, params->dist.max_distance, + &sr2); + if (ENABLE_COMPOUND_DICTIONARY) { + LookupCompoundDictionaryMatch( + ¶ms->dictionary.compound, ringbuffer, + ringbuffer_mask, dist_cache, position + 1, max_length, + dictionary_start, params->dist.max_distance, &sr2); + } + if (sr2.score >= sr.score + cost_diff_lazy) { + /* Ok, let's just write one byte for now and start a match from the + next byte. */ + ++position; + ++insert_length; + sr = sr2; + if (++delayed_backward_references_in_row < 4 && + position + FN(HashTypeLength)() < pos_end) { + continue; + } + } + break; + } + apply_random_heuristics = + position + 2 * sr.len + random_heuristics_window_size; + dictionary_start = BROTLI_MIN(size_t, + position + position_offset, max_backward_limit); + { + /* The first 16 codes are special short-codes, + and the minimum offset is 1. */ + size_t distance_code = ComputeDistanceCode( + sr.distance, dictionary_start + gap, dist_cache); + if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)sr.distance; + FN(PrepareDistanceCache)(privat, dist_cache); + } + InitCommand(commands++, ¶ms->dist, insert_length, + sr.len, sr.len_code_delta, distance_code); + } + *num_literals += insert_length; + insert_length = 0; + /* Put the hash keys into the table, if there are enough bytes left. + Depending on the hasher implementation, it can push all positions + in the given range or only a subset of them. + Avoid hash poisoning with RLE data. */ + { + size_t range_start = position + 2; + size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end); + if (sr.distance < (sr.len >> 2)) { + range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t, + range_start, position + sr.len - (sr.distance << 2))); + } + FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start, + range_end); + } + position += sr.len; + } else { + ++insert_length; + ++position; + /* If we have not seen matches for a long time, we can skip some + match lookups. Unsuccessful match lookups are very very expensive + and this kind of a heuristic speeds up compression quite + a lot. */ + if (position > apply_random_heuristics) { + /* Going through uncompressible data, jump. */ + if (position > + apply_random_heuristics + 4 * random_heuristics_window_size) { + /* It is quite a long time since we saw a copy, so we assume + that this data is not compressible, and store hashes less + often. Hashes of non compressible data are less likely to + turn out to be useful in the future, too, so we store less of + them to not to flood out the hash table of good compressible + data. */ + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4); + size_t pos_jump = + BROTLI_MIN(size_t, position + 16, pos_end - kMargin); + for (; position < pos_jump; position += 4) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 4; + } + } else { + const size_t kMargin = + BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2); + size_t pos_jump = + BROTLI_MIN(size_t, position + 8, pos_end - kMargin); + for (; position < pos_jump; position += 2) { + FN(Store)(privat, ringbuffer, ringbuffer_mask, position); + insert_length += 2; + } + } + } + } + } + insert_length += pos_end - position; + *last_insert_len = insert_length; + *num_commands += (size_t)(commands - orig_commands); +} +#undef HASHER + +#undef ENABLE_COMPOUND_DICTIONARY +#undef PREFIX + +#undef EXPORT_FN +#undef FN +#undef CAT +#undef EXPAND_CAT + +void duckdb_brotli::BrotliCreateBackwardReferences(size_t num_bytes, + size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + if (params->dictionary.compound.num_chunks != 0) { + switch (params->hasher.type) { +#define CASE_(N) \ + case N: \ + CreateBackwardReferencesDH ## N(num_bytes, \ + position, ringbuffer, ringbuffer_mask, \ + literal_context_lut, params, hasher, dist_cache, \ + last_insert_len, commands, num_commands, num_literals); \ + return; + CASE_(5) + CASE_(6) + CASE_(40) + CASE_(41) + CASE_(42) + CASE_(55) + CASE_(65) +#undef CASE_ + default: + BROTLI_DCHECK(false); + break; + } + } + + switch (params->hasher.type) { +#define CASE_(N) \ + case N: \ + CreateBackwardReferencesNH ## N(num_bytes, \ + position, ringbuffer, ringbuffer_mask, \ + literal_context_lut, params, hasher, dist_cache, \ + last_insert_len, commands, num_commands, num_literals); \ + return; + FOR_GENERIC_HASHERS(CASE_) +#undef CASE_ + default: + BROTLI_DCHECK(false); + break; + } +} + + diff --git a/third_party/brotli/enc/backward_references.h b/third_party/brotli/enc/backward_references.h new file mode 100644 index 00000000000..16a71faa208 --- /dev/null +++ b/third_party/brotli/enc/backward_references.h @@ -0,0 +1,36 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Function to find backward reference copies. */ + +#ifndef BROTLI_ENC_BACKWARD_REFERENCES_H_ +#define BROTLI_ENC_BACKWARD_REFERENCES_H_ + +#include + +#include "../common/brotli_constants.h" +#include "../common/context.h" +#include "../common/dictionary.h" +#include "../common/brotli_platform.h" +#include "command.h" +#include "brotli_hash.h" +#include "quality.h" + +namespace duckdb_brotli { + +/* "commands" points to the next output command to write to, "*num_commands" is + initially the total amount of commands output by previous + CreateBackwardReferences calls, and must be incremented by the amount written + by this call. */ +BROTLI_INTERNAL void BrotliCreateBackwardReferences(size_t num_bytes, + size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals); + +} + +#endif /* BROTLI_ENC_BACKWARD_REFERENCES_H_ */ diff --git a/third_party/brotli/enc/backward_references_hq.cpp b/third_party/brotli/enc/backward_references_hq.cpp new file mode 100644 index 00000000000..bd51819ce00 --- /dev/null +++ b/third_party/brotli/enc/backward_references_hq.cpp @@ -0,0 +1,935 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Function to find backward reference copies. */ + +#include "backward_references_hq.h" + +#include /* memcpy, memset */ + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" +#include "command.h" +#include "compound_dictionary.h" +#include "encoder_dict.h" +#include "fast_log.h" +#include "find_match_length.h" +#include "literal_cost.h" +#include "memory.h" +#include "brotli_params.h" +#include "prefix.h" +#include "quality.h" + +using namespace duckdb_brotli; + +/* BrotliCalculateDistanceCodeLimit(BROTLI_MAX_ALLOWED_DISTANCE, 3, 120). */ +#define BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE 544 + +static const float kInfinity = 1.7e38f; /* ~= 2 ^ 127 */ + +static const uint32_t kDistanceCacheIndex[] = { + 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, +}; +static const int kDistanceCacheOffset[] = { + 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3 +}; + +void duckdb_brotli::BrotliInitZopfliNodes(ZopfliNode* array, size_t length) { + ZopfliNode stub; + size_t i; + stub.length = 1; + stub.distance = 0; + stub.dcode_insert_length = 0; + stub.u.cost = kInfinity; + for (i = 0; i < length; ++i) array[i] = stub; +} + +static BROTLI_INLINE uint32_t ZopfliNodeCopyLength(const ZopfliNode* self) { + return self->length & 0x1FFFFFF; +} + +static BROTLI_INLINE uint32_t ZopfliNodeLengthCode(const ZopfliNode* self) { + const uint32_t modifier = self->length >> 25; + return ZopfliNodeCopyLength(self) + 9u - modifier; +} + +static BROTLI_INLINE uint32_t ZopfliNodeCopyDistance(const ZopfliNode* self) { + return self->distance; +} + +static BROTLI_INLINE uint32_t ZopfliNodeDistanceCode(const ZopfliNode* self) { + const uint32_t short_code = self->dcode_insert_length >> 27; + return short_code == 0 ? + ZopfliNodeCopyDistance(self) + BROTLI_NUM_DISTANCE_SHORT_CODES - 1 : + short_code - 1; +} + +static BROTLI_INLINE uint32_t ZopfliNodeCommandLength(const ZopfliNode* self) { + return ZopfliNodeCopyLength(self) + (self->dcode_insert_length & 0x7FFFFFF); +} + +/* Temporary data for ZopfliCostModelSetFromCommands. */ +typedef struct ZopfliCostModelArena { + uint32_t histogram_literal[BROTLI_NUM_LITERAL_SYMBOLS]; + uint32_t histogram_cmd[BROTLI_NUM_COMMAND_SYMBOLS]; + uint32_t histogram_dist[BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE]; + float cost_literal[BROTLI_NUM_LITERAL_SYMBOLS]; +} ZopfliCostModelArena; + +/* Histogram based cost model for zopflification. */ +typedef struct ZopfliCostModel { + /* The insert and copy length symbols. */ + float cost_cmd_[BROTLI_NUM_COMMAND_SYMBOLS]; + float* cost_dist_; + uint32_t distance_histogram_size; + /* Cumulative costs of literals per position in the stream. */ + float* literal_costs_; + float min_cost_cmd_; + size_t num_bytes_; + + /* Temporary data. */ + union { + size_t literal_histograms[3 * 256]; + ZopfliCostModelArena arena; + }; +} ZopfliCostModel; + +static void InitZopfliCostModel( + MemoryManager* m, ZopfliCostModel* self, const BrotliDistanceParams* dist, + size_t num_bytes) { + self->num_bytes_ = num_bytes; + self->literal_costs_ = BROTLI_ALLOC(m, float, num_bytes + 2); + self->cost_dist_ = BROTLI_ALLOC(m, float, dist->alphabet_size_limit); + self->distance_histogram_size = dist->alphabet_size_limit; + if (BROTLI_IS_OOM(m)) return; +} + +static void CleanupZopfliCostModel(MemoryManager* m, ZopfliCostModel* self) { + BROTLI_FREE(m, self->literal_costs_); + BROTLI_FREE(m, self->cost_dist_); +} + +static void SetCost(const uint32_t* histogram, size_t histogram_size, + BROTLI_BOOL literal_histogram, float* cost) { + size_t sum = 0; + size_t missing_symbol_sum; + float log2sum; + float missing_symbol_cost; + size_t i; + for (i = 0; i < histogram_size; i++) { + sum += histogram[i]; + } + log2sum = (float)FastLog2(sum); + missing_symbol_sum = sum; + if (!literal_histogram) { + for (i = 0; i < histogram_size; i++) { + if (histogram[i] == 0) missing_symbol_sum++; + } + } + missing_symbol_cost = (float)FastLog2(missing_symbol_sum) + 2; + for (i = 0; i < histogram_size; i++) { + if (histogram[i] == 0) { + cost[i] = missing_symbol_cost; + continue; + } + + /* Shannon bits for this symbol. */ + cost[i] = log2sum - (float)FastLog2(histogram[i]); + + /* Cannot be coded with less than 1 bit */ + if (cost[i] < 1) cost[i] = 1; + } +} + +static void ZopfliCostModelSetFromCommands(ZopfliCostModel* self, + size_t position, + const uint8_t* ringbuffer, + size_t ringbuffer_mask, + const Command* commands, + size_t num_commands, + size_t last_insert_len) { + ZopfliCostModelArena* arena = &self->arena; + size_t pos = position - last_insert_len; + float min_cost_cmd = kInfinity; + size_t i; + float* cost_cmd = self->cost_cmd_; + + memset(arena->histogram_literal, 0, sizeof(arena->histogram_literal)); + memset(arena->histogram_cmd, 0, sizeof(arena->histogram_cmd)); + memset(arena->histogram_dist, 0, sizeof(arena->histogram_dist)); + + for (i = 0; i < num_commands; i++) { + size_t inslength = commands[i].insert_len_; + size_t copylength = CommandCopyLen(&commands[i]); + size_t distcode = commands[i].dist_prefix_ & 0x3FF; + size_t cmdcode = commands[i].cmd_prefix_; + size_t j; + + arena->histogram_cmd[cmdcode]++; + if (cmdcode >= 128) arena->histogram_dist[distcode]++; + + for (j = 0; j < inslength; j++) { + arena->histogram_literal[ringbuffer[(pos + j) & ringbuffer_mask]]++; + } + + pos += inslength + copylength; + } + + SetCost(arena->histogram_literal, BROTLI_NUM_LITERAL_SYMBOLS, BROTLI_TRUE, + arena->cost_literal); + SetCost(arena->histogram_cmd, BROTLI_NUM_COMMAND_SYMBOLS, BROTLI_FALSE, + cost_cmd); + SetCost(arena->histogram_dist, self->distance_histogram_size, BROTLI_FALSE, + self->cost_dist_); + + for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) { + min_cost_cmd = BROTLI_MIN(float, min_cost_cmd, cost_cmd[i]); + } + self->min_cost_cmd_ = min_cost_cmd; + + { + float* literal_costs = self->literal_costs_; + float literal_carry = 0.0; + size_t num_bytes = self->num_bytes_; + literal_costs[0] = 0.0; + for (i = 0; i < num_bytes; ++i) { + literal_carry += + arena->cost_literal[ringbuffer[(position + i) & ringbuffer_mask]]; + literal_costs[i + 1] = literal_costs[i] + literal_carry; + literal_carry -= literal_costs[i + 1] - literal_costs[i]; + } + } +} + +static void ZopfliCostModelSetFromLiteralCosts(ZopfliCostModel* self, + size_t position, + const uint8_t* ringbuffer, + size_t ringbuffer_mask) { + float* literal_costs = self->literal_costs_; + float literal_carry = 0.0; + float* cost_dist = self->cost_dist_; + float* cost_cmd = self->cost_cmd_; + size_t num_bytes = self->num_bytes_; + size_t i; + BrotliEstimateBitCostsForLiterals(position, num_bytes, ringbuffer_mask, + ringbuffer, self->literal_histograms, + &literal_costs[1]); + literal_costs[0] = 0.0; + for (i = 0; i < num_bytes; ++i) { + literal_carry += literal_costs[i + 1]; + literal_costs[i + 1] = literal_costs[i] + literal_carry; + literal_carry -= literal_costs[i + 1] - literal_costs[i]; + } + for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) { + cost_cmd[i] = (float)FastLog2(11 + (uint32_t)i); + } + for (i = 0; i < self->distance_histogram_size; ++i) { + cost_dist[i] = (float)FastLog2(20 + (uint32_t)i); + } + self->min_cost_cmd_ = (float)FastLog2(11); +} + +static BROTLI_INLINE float ZopfliCostModelGetCommandCost( + const ZopfliCostModel* self, uint16_t cmdcode) { + return self->cost_cmd_[cmdcode]; +} + +static BROTLI_INLINE float ZopfliCostModelGetDistanceCost( + const ZopfliCostModel* self, size_t distcode) { + return self->cost_dist_[distcode]; +} + +static BROTLI_INLINE float ZopfliCostModelGetLiteralCosts( + const ZopfliCostModel* self, size_t from, size_t to) { + return self->literal_costs_[to] - self->literal_costs_[from]; +} + +static BROTLI_INLINE float ZopfliCostModelGetMinCostCmd( + const ZopfliCostModel* self) { + return self->min_cost_cmd_; +} + +/* REQUIRES: len >= 2, start_pos <= pos */ +/* REQUIRES: cost < kInfinity, nodes[start_pos].cost < kInfinity */ +/* Maintains the "ZopfliNode array invariant". */ +static BROTLI_INLINE void UpdateZopfliNode(ZopfliNode* nodes, size_t pos, + size_t start_pos, size_t len, size_t len_code, size_t dist, + size_t short_code, float cost) { + ZopfliNode* next = &nodes[pos + len]; + next->length = (uint32_t)(len | ((len + 9u - len_code) << 25)); + next->distance = (uint32_t)dist; + next->dcode_insert_length = (uint32_t)( + (short_code << 27) | (pos - start_pos)); + next->u.cost = cost; +} + +typedef struct PosData { + size_t pos; + int distance_cache[4]; + float costdiff; + float cost; +} PosData; + +/* Maintains the smallest 8 cost difference together with their positions */ +typedef struct StartPosQueue { + PosData q_[8]; + size_t idx_; +} StartPosQueue; + +static BROTLI_INLINE void InitStartPosQueue(StartPosQueue* self) { + self->idx_ = 0; +} + +static size_t StartPosQueueSize(const StartPosQueue* self) { + return BROTLI_MIN(size_t, self->idx_, 8); +} + +static void StartPosQueuePush(StartPosQueue* self, const PosData* posdata) { + size_t offset = ~(self->idx_++) & 7; + size_t len = StartPosQueueSize(self); + size_t i; + PosData* q = self->q_; + q[offset] = *posdata; + /* Restore the sorted order. In the list of |len| items at most |len - 1| + adjacent element comparisons / swaps are required. */ + for (i = 1; i < len; ++i) { + if (q[offset & 7].costdiff > q[(offset + 1) & 7].costdiff) { + BROTLI_SWAP(PosData, q, offset & 7, (offset + 1) & 7); + } + ++offset; + } +} + +static const PosData* StartPosQueueAt(const StartPosQueue* self, size_t k) { + return &self->q_[(k - self->idx_) & 7]; +} + +/* Returns the minimum possible copy length that can improve the cost of any */ +/* future position. */ +static size_t ComputeMinimumCopyLength(const float start_cost, + const ZopfliNode* nodes, + const size_t num_bytes, + const size_t pos) { + /* Compute the minimum possible cost of reaching any future position. */ + float min_cost = start_cost; + size_t len = 2; + size_t next_len_bucket = 4; + size_t next_len_offset = 10; + while (pos + len <= num_bytes && nodes[pos + len].u.cost <= min_cost) { + /* We already reached (pos + len) with no more cost than the minimum + possible cost of reaching anything from this pos, so there is no point in + looking for lengths <= len. */ + ++len; + if (len == next_len_offset) { + /* We reached the next copy length code bucket, so we add one more + extra bit to the minimum cost. */ + min_cost += 1.0f; + next_len_offset += next_len_bucket; + next_len_bucket *= 2; + } + } + return len; +} + +/* REQUIRES: nodes[pos].cost < kInfinity + REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant". */ +static uint32_t ComputeDistanceShortcut(const size_t block_start, + const size_t pos, + const size_t max_backward_limit, + const size_t gap, + const ZopfliNode* nodes) { + const size_t clen = ZopfliNodeCopyLength(&nodes[pos]); + const size_t ilen = nodes[pos].dcode_insert_length & 0x7FFFFFF; + const size_t dist = ZopfliNodeCopyDistance(&nodes[pos]); + /* Since |block_start + pos| is the end position of the command, the copy part + starts from |block_start + pos - clen|. Distances that are greater than + this or greater than |max_backward_limit| + |gap| are static dictionary + references, and do not update the last distances. + Also distance code 0 (last distance) does not update the last distances. */ + if (pos == 0) { + return 0; + } else if (dist + clen <= block_start + pos + gap && + dist <= max_backward_limit + gap && + ZopfliNodeDistanceCode(&nodes[pos]) > 0) { + return (uint32_t)pos; + } else { + return nodes[pos - clen - ilen].u.shortcut; + } +} + +/* Fills in dist_cache[0..3] with the last four distances (as defined by + Section 4. of the Spec) that would be used at (block_start + pos) if we + used the shortest path of commands from block_start, computed from + nodes[0..pos]. The last four distances at block_start are in + starting_dist_cache[0..3]. + REQUIRES: nodes[pos].cost < kInfinity + REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant". */ +static void ComputeDistanceCache(const size_t pos, + const int* starting_dist_cache, + const ZopfliNode* nodes, + int* dist_cache) { + int idx = 0; + size_t p = nodes[pos].u.shortcut; + while (idx < 4 && p > 0) { + const size_t ilen = nodes[p].dcode_insert_length & 0x7FFFFFF; + const size_t clen = ZopfliNodeCopyLength(&nodes[p]); + const size_t dist = ZopfliNodeCopyDistance(&nodes[p]); + dist_cache[idx++] = (int)dist; + /* Because of prerequisite, p >= clen + ilen >= 2. */ + p = nodes[p - clen - ilen].u.shortcut; + } + for (; idx < 4; ++idx) { + dist_cache[idx] = *starting_dist_cache++; + } +} + +/* Maintains "ZopfliNode array invariant" and pushes node to the queue, if it + is eligible. */ +static void EvaluateNode( + const size_t block_start, const size_t pos, const size_t max_backward_limit, + const size_t gap, const int* starting_dist_cache, + const ZopfliCostModel* model, StartPosQueue* queue, ZopfliNode* nodes) { + /* Save cost, because ComputeDistanceCache invalidates it. */ + float node_cost = nodes[pos].u.cost; + nodes[pos].u.shortcut = ComputeDistanceShortcut( + block_start, pos, max_backward_limit, gap, nodes); + if (node_cost <= ZopfliCostModelGetLiteralCosts(model, 0, pos)) { + PosData posdata; + posdata.pos = pos; + posdata.cost = node_cost; + posdata.costdiff = node_cost - + ZopfliCostModelGetLiteralCosts(model, 0, pos); + ComputeDistanceCache( + pos, starting_dist_cache, nodes, posdata.distance_cache); + StartPosQueuePush(queue, &posdata); + } +} + +/* Returns longest copy length. */ +static size_t UpdateNodes( + const size_t num_bytes, const size_t block_start, const size_t pos, + const uint8_t* ringbuffer, const size_t ringbuffer_mask, + const BrotliEncoderParams* params, const size_t max_backward_limit, + const int* starting_dist_cache, const size_t num_matches, + const BackwardMatch* matches, const ZopfliCostModel* model, + StartPosQueue* queue, ZopfliNode* nodes) { + const size_t stream_offset = params->stream_offset; + const size_t cur_ix = block_start + pos; + const size_t cur_ix_masked = cur_ix & ringbuffer_mask; + const size_t max_distance = BROTLI_MIN(size_t, cur_ix, max_backward_limit); + const size_t dictionary_start = BROTLI_MIN(size_t, + cur_ix + stream_offset, max_backward_limit); + const size_t max_len = num_bytes - pos; + const size_t max_zopfli_len = MaxZopfliLen(params); + const size_t max_iters = MaxZopfliCandidates(params); + size_t min_len; + size_t result = 0; + size_t k; + const CompoundDictionary* addon = ¶ms->dictionary.compound; + size_t gap = addon->total_size; + + EvaluateNode(block_start + stream_offset, pos, max_backward_limit, gap, + starting_dist_cache, model, queue, nodes); + + { + const PosData* posdata = StartPosQueueAt(queue, 0); + float min_cost = (posdata->cost + ZopfliCostModelGetMinCostCmd(model) + + ZopfliCostModelGetLiteralCosts(model, posdata->pos, pos)); + min_len = ComputeMinimumCopyLength(min_cost, nodes, num_bytes, pos); + } + + /* Go over the command starting positions in order of increasing cost + difference. */ + for (k = 0; k < max_iters && k < StartPosQueueSize(queue); ++k) { + const PosData* posdata = StartPosQueueAt(queue, k); + const size_t start = posdata->pos; + const uint16_t inscode = GetInsertLengthCode(pos - start); + const float start_costdiff = posdata->costdiff; + const float base_cost = start_costdiff + (float)GetInsertExtra(inscode) + + ZopfliCostModelGetLiteralCosts(model, 0, pos); + + /* Look for last distance matches using the distance cache from this + starting position. */ + size_t best_len = min_len - 1; + size_t j = 0; + for (; j < BROTLI_NUM_DISTANCE_SHORT_CODES && best_len < max_len; ++j) { + const size_t idx = kDistanceCacheIndex[j]; + const size_t backward = + (size_t)(posdata->distance_cache[idx] + kDistanceCacheOffset[j]); + size_t prev_ix = cur_ix - backward; + size_t len = 0; + uint8_t continuation = ringbuffer[cur_ix_masked + best_len]; + if (cur_ix_masked + best_len > ringbuffer_mask) { + break; + } + if (BROTLI_PREDICT_FALSE(backward > dictionary_start + gap)) { + /* Word dictionary -> ignore. */ + continue; + } + if (backward <= max_distance) { + /* Regular backward reference. */ + if (prev_ix >= cur_ix) { + continue; + } + + prev_ix &= ringbuffer_mask; + if (prev_ix + best_len > ringbuffer_mask || + continuation != ringbuffer[prev_ix + best_len]) { + continue; + } + len = FindMatchLengthWithLimit(&ringbuffer[prev_ix], + &ringbuffer[cur_ix_masked], + max_len); + } else if (backward > dictionary_start) { + size_t d = 0; + size_t offset; + size_t limit; + const uint8_t* source; + offset = dictionary_start + 1 + addon->total_size - 1; + while (offset >= backward + addon->chunk_offsets[d + 1]) d++; + source = addon->chunk_source[d]; + offset = offset - addon->chunk_offsets[d] - backward; + limit = addon->chunk_offsets[d + 1] - addon->chunk_offsets[d] - offset; + limit = limit > max_len ? max_len : limit; + if (best_len >= limit || + continuation != source[offset + best_len]) { + continue; + } + len = FindMatchLengthWithLimit(&source[offset], + &ringbuffer[cur_ix_masked], + limit); + } else { + /* "Gray" area. It is addressable by decoder, but this encoder + instance does not have that data -> should not touch it. */ + continue; + } + { + const float dist_cost = base_cost + + ZopfliCostModelGetDistanceCost(model, j); + size_t l; + for (l = best_len + 1; l <= len; ++l) { + const uint16_t copycode = GetCopyLengthCode(l); + const uint16_t cmdcode = + CombineLengthCodes(inscode, copycode, j == 0); + const float cost = (cmdcode < 128 ? base_cost : dist_cost) + + (float)GetCopyExtra(copycode) + + ZopfliCostModelGetCommandCost(model, cmdcode); + if (cost < nodes[pos + l].u.cost) { + UpdateZopfliNode(nodes, pos, start, l, l, backward, j + 1, cost); + result = BROTLI_MAX(size_t, result, l); + } + best_len = l; + } + } + } + + /* At higher iterations look only for new last distance matches, since + looking only for new command start positions with the same distances + does not help much. */ + if (k >= 2) continue; + + { + /* Loop through all possible copy lengths at this position. */ + size_t len = min_len; + for (j = 0; j < num_matches; ++j) { + BackwardMatch match = matches[j]; + size_t dist = match.distance; + BROTLI_BOOL is_dictionary_match = + TO_BROTLI_BOOL(dist > dictionary_start + gap); + /* We already tried all possible last distance matches, so we can use + normal distance code here. */ + size_t dist_code = dist + BROTLI_NUM_DISTANCE_SHORT_CODES - 1; + uint16_t dist_symbol; + uint32_t distextra; + uint32_t distnumextra; + float dist_cost; + size_t max_match_len; + PrefixEncodeCopyDistance( + dist_code, params->dist.num_direct_distance_codes, + params->dist.distance_postfix_bits, &dist_symbol, &distextra); + distnumextra = dist_symbol >> 10; + dist_cost = base_cost + (float)distnumextra + + ZopfliCostModelGetDistanceCost(model, dist_symbol & 0x3FF); + + /* Try all copy lengths up until the maximum copy length corresponding + to this distance. If the distance refers to the static dictionary, or + the maximum length is long enough, try only one maximum length. */ + max_match_len = BackwardMatchLength(&match); + if (len < max_match_len && + (is_dictionary_match || max_match_len > max_zopfli_len)) { + len = max_match_len; + } + for (; len <= max_match_len; ++len) { + const size_t len_code = + is_dictionary_match ? BackwardMatchLengthCode(&match) : len; + const uint16_t copycode = GetCopyLengthCode(len_code); + const uint16_t cmdcode = CombineLengthCodes(inscode, copycode, 0); + const float cost = dist_cost + (float)GetCopyExtra(copycode) + + ZopfliCostModelGetCommandCost(model, cmdcode); + if (cost < nodes[pos + len].u.cost) { + UpdateZopfliNode(nodes, pos, start, len, len_code, dist, 0, cost); + result = BROTLI_MAX(size_t, result, len); + } + } + } + } + } + return result; +} + +static size_t ComputeShortestPathFromNodes(size_t num_bytes, + ZopfliNode* nodes) { + size_t index = num_bytes; + size_t num_commands = 0; + while ((nodes[index].dcode_insert_length & 0x7FFFFFF) == 0 && + nodes[index].length == 1) --index; + nodes[index].u.next = BROTLI_UINT32_MAX; + while (index != 0) { + size_t len = ZopfliNodeCommandLength(&nodes[index]); + index -= len; + nodes[index].u.next = (uint32_t)len; + num_commands++; + } + return num_commands; +} + +/* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */ +void duckdb_brotli::BrotliZopfliCreateCommands(const size_t num_bytes, + const size_t block_start, const ZopfliNode* nodes, int* dist_cache, + size_t* last_insert_len, const BrotliEncoderParams* params, + Command* commands, size_t* num_literals) { + const size_t stream_offset = params->stream_offset; + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + size_t pos = 0; + uint32_t offset = nodes[0].u.next; + size_t i; + size_t gap = params->dictionary.compound.total_size; + for (i = 0; offset != BROTLI_UINT32_MAX; i++) { + const ZopfliNode* next = &nodes[pos + offset]; + size_t copy_length = ZopfliNodeCopyLength(next); + size_t insert_length = next->dcode_insert_length & 0x7FFFFFF; + pos += insert_length; + offset = next->u.next; + if (i == 0) { + insert_length += *last_insert_len; + *last_insert_len = 0; + } + { + size_t distance = ZopfliNodeCopyDistance(next); + size_t len_code = ZopfliNodeLengthCode(next); + size_t dictionary_start = BROTLI_MIN(size_t, + block_start + pos + stream_offset, max_backward_limit); + BROTLI_BOOL is_dictionary = + TO_BROTLI_BOOL(distance > dictionary_start + gap); + size_t dist_code = ZopfliNodeDistanceCode(next); + InitCommand(&commands[i], ¶ms->dist, insert_length, + copy_length, (int)len_code - (int)copy_length, dist_code); + + if (!is_dictionary && dist_code > 0) { + dist_cache[3] = dist_cache[2]; + dist_cache[2] = dist_cache[1]; + dist_cache[1] = dist_cache[0]; + dist_cache[0] = (int)distance; + } + } + + *num_literals += insert_length; + pos += copy_length; + } + *last_insert_len += num_bytes - pos; +} + +static size_t ZopfliIterate(size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask, + const BrotliEncoderParams* params, const size_t gap, const int* dist_cache, + const ZopfliCostModel* model, const uint32_t* num_matches, + const BackwardMatch* matches, ZopfliNode* nodes) { + const size_t stream_offset = params->stream_offset; + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t max_zopfli_len = MaxZopfliLen(params); + StartPosQueue queue; + size_t cur_match_pos = 0; + size_t i; + nodes[0].length = 0; + nodes[0].u.cost = 0; + InitStartPosQueue(&queue); + for (i = 0; i + 3 < num_bytes; i++) { + size_t skip = UpdateNodes(num_bytes, position, i, ringbuffer, + ringbuffer_mask, params, max_backward_limit, dist_cache, + num_matches[i], &matches[cur_match_pos], model, &queue, nodes); + if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0; + cur_match_pos += num_matches[i]; + if (num_matches[i] == 1 && + BackwardMatchLength(&matches[cur_match_pos - 1]) > max_zopfli_len) { + skip = BROTLI_MAX(size_t, + BackwardMatchLength(&matches[cur_match_pos - 1]), skip); + } + if (skip > 1) { + skip--; + while (skip) { + i++; + if (i + 3 >= num_bytes) break; + EvaluateNode(position + stream_offset, i, max_backward_limit, gap, + dist_cache, model, &queue, nodes); + cur_match_pos += num_matches[i]; + skip--; + } + } + } + return ComputeShortestPathFromNodes(num_bytes, nodes); +} + +static void MergeMatches(BackwardMatch* dst, + BackwardMatch* src1, size_t len1, BackwardMatch* src2, size_t len2) { + while (len1 > 0 && len2 > 0) { + size_t l1 = BackwardMatchLength(src1); + size_t l2 = BackwardMatchLength(src2); + if (l1 < l2 || ((l1 == l2) && (src1->distance < src2->distance))) { + *dst++ = *src1++; + len1--; + } else { + *dst++ = *src2++; + len2--; + } + } + while (len1-- > 0) *dst++ = *src1++; + while (len2-- > 0) *dst++ = *src2++; +} + +/* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */ +size_t duckdb_brotli::BrotliZopfliComputeShortestPath(MemoryManager* m, size_t num_bytes, + size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + const int* dist_cache, Hasher* hasher, ZopfliNode* nodes) { + const size_t stream_offset = params->stream_offset; + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + const size_t max_zopfli_len = MaxZopfliLen(params); + StartPosQueue queue; + BackwardMatch* BROTLI_RESTRICT matches = + BROTLI_ALLOC(m, BackwardMatch, 2 * (MAX_NUM_MATCHES_H10 + 64)); + const size_t store_end = num_bytes >= StoreLookaheadH10() ? + position + num_bytes - StoreLookaheadH10() + 1 : position; + size_t i; + const CompoundDictionary* addon = ¶ms->dictionary.compound; + size_t gap = addon->total_size; + size_t lz_matches_offset = + (addon->num_chunks != 0) ? (MAX_NUM_MATCHES_H10 + 128) : 0; + ZopfliCostModel* model = BROTLI_ALLOC(m, ZopfliCostModel, 1); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(model) || BROTLI_IS_NULL(matches)) { + return 0; + } + nodes[0].length = 0; + nodes[0].u.cost = 0; + InitZopfliCostModel(m, model, ¶ms->dist, num_bytes); + if (BROTLI_IS_OOM(m)) return 0; + ZopfliCostModelSetFromLiteralCosts( + model, position, ringbuffer, ringbuffer_mask); + InitStartPosQueue(&queue); + for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; i++) { + const size_t pos = position + i; + const size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit); + const size_t dictionary_start = BROTLI_MIN(size_t, + pos + stream_offset, max_backward_limit); + size_t skip; + size_t num_matches; + int dict_id = 0; + if (params->dictionary.contextual.context_based) { + uint8_t p1 = pos >= 1 ? + ringbuffer[(size_t)(pos - 1) & ringbuffer_mask] : 0; + uint8_t p2 = pos >= 2 ? + ringbuffer[(size_t)(pos - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + num_matches = FindAllMatchesH10(&hasher->privat._H10, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, pos, num_bytes - i, max_distance, + dictionary_start + gap, params, &matches[lz_matches_offset]); + if (addon->num_chunks != 0) { + size_t cd_matches = LookupAllCompoundDictionaryMatches(addon, + ringbuffer, ringbuffer_mask, pos, 3, num_bytes - i, + dictionary_start, params->dist.max_distance, + &matches[lz_matches_offset - 64], 64); + MergeMatches(matches, &matches[lz_matches_offset - 64], cd_matches, + &matches[lz_matches_offset], num_matches); + num_matches += cd_matches; + } + if (num_matches > 0 && + BackwardMatchLength(&matches[num_matches - 1]) > max_zopfli_len) { + matches[0] = matches[num_matches - 1]; + num_matches = 1; + } + skip = UpdateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask, + params, max_backward_limit, dist_cache, num_matches, matches, model, + &queue, nodes); + if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0; + if (num_matches == 1 && BackwardMatchLength(&matches[0]) > max_zopfli_len) { + skip = BROTLI_MAX(size_t, BackwardMatchLength(&matches[0]), skip); + } + if (skip > 1) { + /* Add the tail of the copy to the hasher. */ + StoreRangeH10(&hasher->privat._H10, + ringbuffer, ringbuffer_mask, pos + 1, BROTLI_MIN( + size_t, pos + skip, store_end)); + skip--; + while (skip) { + i++; + if (i + HashTypeLengthH10() - 1 >= num_bytes) break; + EvaluateNode(position + stream_offset, i, max_backward_limit, gap, + dist_cache, model, &queue, nodes); + skip--; + } + } + } + CleanupZopfliCostModel(m, model); + BROTLI_FREE(m, model); + BROTLI_FREE(m, matches); + return ComputeShortestPathFromNodes(num_bytes, nodes); +} + +void duckdb_brotli::BrotliCreateZopfliBackwardReferences(MemoryManager* m, size_t num_bytes, + size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + ZopfliNode* nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) return; + BrotliInitZopfliNodes(nodes, num_bytes + 1); + *num_commands += BrotliZopfliComputeShortestPath(m, num_bytes, + position, ringbuffer, ringbuffer_mask, literal_context_lut, params, + dist_cache, hasher, nodes); + if (BROTLI_IS_OOM(m)) return; + BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache, + last_insert_len, params, commands, num_literals); + BROTLI_FREE(m, nodes); +} + +void duckdb_brotli::BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes, + size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals) { + const size_t stream_offset = params->stream_offset; + const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin); + uint32_t* num_matches = BROTLI_ALLOC(m, uint32_t, num_bytes); + size_t matches_size = 4 * num_bytes; + const size_t store_end = num_bytes >= StoreLookaheadH10() ? + position + num_bytes - StoreLookaheadH10() + 1 : position; + size_t cur_match_pos = 0; + size_t i; + size_t orig_num_literals; + size_t orig_last_insert_len; + int orig_dist_cache[4]; + size_t orig_num_commands; + ZopfliCostModel* model = BROTLI_ALLOC(m, ZopfliCostModel, 1); + ZopfliNode* nodes; + BackwardMatch* matches = BROTLI_ALLOC(m, BackwardMatch, matches_size); + const CompoundDictionary* addon = ¶ms->dictionary.compound; + size_t gap = addon->total_size; + size_t shadow_matches = + (addon->num_chunks != 0) ? (MAX_NUM_MATCHES_H10 + 128) : 0; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(model) || + BROTLI_IS_NULL(num_matches) || BROTLI_IS_NULL(matches)) { + return; + } + for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; ++i) { + const size_t pos = position + i; + size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit); + size_t dictionary_start = BROTLI_MIN(size_t, + pos + stream_offset, max_backward_limit); + size_t max_length = num_bytes - i; + size_t num_found_matches; + size_t cur_match_end; + size_t j; + int dict_id = 0; + if (params->dictionary.contextual.context_based) { + uint8_t p1 = pos >= 1 ? + ringbuffer[(size_t)(pos - 1) & ringbuffer_mask] : 0; + uint8_t p2 = pos >= 2 ? + ringbuffer[(size_t)(pos - 2) & ringbuffer_mask] : 0; + dict_id = params->dictionary.contextual.context_map[ + BROTLI_CONTEXT(p1, p2, literal_context_lut)]; + } + /* Ensure that we have enough free slots. */ + BROTLI_ENSURE_CAPACITY(m, BackwardMatch, matches, matches_size, + cur_match_pos + MAX_NUM_MATCHES_H10 + shadow_matches); + if (BROTLI_IS_OOM(m)) return; + num_found_matches = FindAllMatchesH10(&hasher->privat._H10, + params->dictionary.contextual.dict[dict_id], + ringbuffer, ringbuffer_mask, pos, max_length, + max_distance, dictionary_start + gap, params, + &matches[cur_match_pos + shadow_matches]); + if (addon->num_chunks != 0) { + size_t cd_matches = LookupAllCompoundDictionaryMatches(addon, + ringbuffer, ringbuffer_mask, pos, 3, max_length, + dictionary_start, params->dist.max_distance, + &matches[cur_match_pos + shadow_matches - 64], 64); + MergeMatches(&matches[cur_match_pos], + &matches[cur_match_pos + shadow_matches - 64], cd_matches, + &matches[cur_match_pos + shadow_matches], num_found_matches); + num_found_matches += cd_matches; + } + cur_match_end = cur_match_pos + num_found_matches; + for (j = cur_match_pos; j + 1 < cur_match_end; ++j) { + BROTLI_DCHECK(BackwardMatchLength(&matches[j]) <= + BackwardMatchLength(&matches[j + 1])); + } + num_matches[i] = (uint32_t)num_found_matches; + if (num_found_matches > 0) { + const size_t match_len = BackwardMatchLength(&matches[cur_match_end - 1]); + if (match_len > MAX_ZOPFLI_LEN_QUALITY_11) { + const size_t skip = match_len - 1; + matches[cur_match_pos++] = matches[cur_match_end - 1]; + num_matches[i] = 1; + /* Add the tail of the copy to the hasher. */ + StoreRangeH10(&hasher->privat._H10, + ringbuffer, ringbuffer_mask, pos + 1, + BROTLI_MIN(size_t, pos + match_len, store_end)); + memset(&num_matches[i + 1], 0, skip * sizeof(num_matches[0])); + i += skip; + } else { + cur_match_pos = cur_match_end; + } + } + } + orig_num_literals = *num_literals; + orig_last_insert_len = *last_insert_len; + memcpy(orig_dist_cache, dist_cache, 4 * sizeof(dist_cache[0])); + orig_num_commands = *num_commands; + nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) return; + InitZopfliCostModel(m, model, ¶ms->dist, num_bytes); + if (BROTLI_IS_OOM(m)) return; + for (i = 0; i < 2; i++) { + BrotliInitZopfliNodes(nodes, num_bytes + 1); + if (i == 0) { + ZopfliCostModelSetFromLiteralCosts( + model, position, ringbuffer, ringbuffer_mask); + } else { + ZopfliCostModelSetFromCommands(model, position, ringbuffer, + ringbuffer_mask, commands, *num_commands - orig_num_commands, + orig_last_insert_len); + } + *num_commands = orig_num_commands; + *num_literals = orig_num_literals; + *last_insert_len = orig_last_insert_len; + memcpy(dist_cache, orig_dist_cache, 4 * sizeof(dist_cache[0])); + *num_commands += ZopfliIterate(num_bytes, position, ringbuffer, + ringbuffer_mask, params, gap, dist_cache, model, num_matches, matches, + nodes); + BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache, + last_insert_len, params, commands, num_literals); + } + CleanupZopfliCostModel(m, model); + BROTLI_FREE(m, model); + BROTLI_FREE(m, nodes); + BROTLI_FREE(m, matches); + BROTLI_FREE(m, num_matches); +} + + diff --git a/third_party/brotli/enc/backward_references_hq.h b/third_party/brotli/enc/backward_references_hq.h new file mode 100644 index 00000000000..f5a6cdcba33 --- /dev/null +++ b/third_party/brotli/enc/backward_references_hq.h @@ -0,0 +1,92 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Function to find backward reference copies. */ + +#ifndef BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_ +#define BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_ + +#include + +#include "../common/brotli_constants.h" +#include "../common/context.h" +#include "../common/dictionary.h" +#include "../common/brotli_platform.h" +#include "command.h" +#include "brotli_hash.h" +#include "memory.h" +#include "quality.h" + +namespace duckdb_brotli { + +BROTLI_INTERNAL void BrotliCreateZopfliBackwardReferences(MemoryManager* m, + size_t num_bytes, + size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals); + +BROTLI_INTERNAL void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, + size_t num_bytes, + size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + Hasher* hasher, int* dist_cache, size_t* last_insert_len, + Command* commands, size_t* num_commands, size_t* num_literals); + +typedef struct ZopfliNode { + /* Best length to get up to this byte (not including this byte itself) + highest 7 bit is used to reconstruct the length code. */ + uint32_t length; + /* Distance associated with the length. */ + uint32_t distance; + /* Number of literal inserts before this copy; highest 5 bits contain + distance short code + 1 (or zero if no short code). */ + uint32_t dcode_insert_length; + + /* This union holds information used by dynamic-programming. During forward + pass |cost| it used to store the goal function. When node is processed its + |cost| is invalidated in favor of |shortcut|. On path back-tracing pass + |next| is assigned the offset to next node on the path. */ + union { + /* Smallest cost to get to this byte from the beginning, as found so far. */ + float cost; + /* Offset to the next node on the path. Equals to command_length() of the + next node on the path. For last node equals to BROTLI_UINT32_MAX */ + uint32_t next; + /* Node position that provides next distance for distance cache. */ + uint32_t shortcut; + } u; +} ZopfliNode; + +BROTLI_INTERNAL void BrotliInitZopfliNodes(ZopfliNode* array, size_t length); + +/* Computes the shortest path of commands from position to at most + position + num_bytes. + + On return, path->size() is the number of commands found and path[i] is the + length of the i-th command (copy length plus insert length). + Note that the sum of the lengths of all commands can be less than num_bytes. + + On return, the nodes[0..num_bytes] array will have the following + "ZopfliNode array invariant": + For each i in [1..num_bytes], if nodes[i].cost < kInfinity, then + (1) nodes[i].copy_length() >= 2 + (2) nodes[i].command_length() <= i and + (3) nodes[i - nodes[i].command_length()].cost < kInfinity */ +BROTLI_INTERNAL size_t BrotliZopfliComputeShortestPath( + MemoryManager* m, size_t num_bytes, + size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, + ContextLut literal_context_lut, const BrotliEncoderParams* params, + const int* dist_cache, Hasher* hasher, ZopfliNode* nodes); + +BROTLI_INTERNAL void BrotliZopfliCreateCommands( + const size_t num_bytes, const size_t block_start, const ZopfliNode* nodes, + int* dist_cache, size_t* last_insert_len, const BrotliEncoderParams* params, + Command* commands, size_t* num_literals); + +} + +#endif /* BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_ */ diff --git a/third_party/brotli/enc/bit_cost.cpp b/third_party/brotli/enc/bit_cost.cpp new file mode 100644 index 00000000000..c9c988acff2 --- /dev/null +++ b/third_party/brotli/enc/bit_cost.cpp @@ -0,0 +1,410 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Functions to estimate the bit cost of Huffman trees. */ + +#include "bit_cost.h" + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" +#include "fast_log.h" +#include "histogram.h" + +using namespace duckdb_brotli; + +#define FN(X) duckdb_brotli:: X ## Literal +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +#define HistogramType FN(Histogram) + +double FN(BrotliPopulationCost)(const HistogramType* histogram) { + static const double kOneSymbolHistogramCost = 12; + static const double kTwoSymbolHistogramCost = 20; + static const double kThreeSymbolHistogramCost = 28; + static const double kFourSymbolHistogramCost = 37; + const size_t data_size = FN(HistogramDataSize)(); + int count = 0; + size_t s[5]; + double bits = 0.0; + size_t i; + if (histogram->total_count_ == 0) { + return kOneSymbolHistogramCost; + } + for (i = 0; i < data_size; ++i) { + if (histogram->data_[i] > 0) { + s[count] = i; + ++count; + if (count > 4) break; + } + } + if (count == 1) { + return kOneSymbolHistogramCost; + } + if (count == 2) { + return (kTwoSymbolHistogramCost + (double)histogram->total_count_); + } + if (count == 3) { + const uint32_t histo0 = histogram->data_[s[0]]; + const uint32_t histo1 = histogram->data_[s[1]]; + const uint32_t histo2 = histogram->data_[s[2]]; + const uint32_t histomax = + BROTLI_MAX(uint32_t, histo0, BROTLI_MAX(uint32_t, histo1, histo2)); + return (kThreeSymbolHistogramCost + + 2 * (histo0 + histo1 + histo2) - histomax); + } + if (count == 4) { + uint32_t histo[4]; + uint32_t h23; + uint32_t histomax; + for (i = 0; i < 4; ++i) { + histo[i] = histogram->data_[s[i]]; + } + /* Sort */ + for (i = 0; i < 4; ++i) { + size_t j; + for (j = i + 1; j < 4; ++j) { + if (histo[j] > histo[i]) { + BROTLI_SWAP(uint32_t, histo, j, i); + } + } + } + h23 = histo[2] + histo[3]; + histomax = BROTLI_MAX(uint32_t, h23, histo[0]); + return (kFourSymbolHistogramCost + + 3 * h23 + 2 * (histo[0] + histo[1]) - histomax); + } + + { + /* In this loop we compute the entropy of the histogram and simultaneously + build a simplified histogram of the code length codes where we use the + zero repeat code 17, but we don't use the non-zero repeat code 16. */ + size_t max_depth = 1; + uint32_t depth_histo[BROTLI_CODE_LENGTH_CODES] = { 0 }; + const double log2total = FastLog2(histogram->total_count_); + for (i = 0; i < data_size;) { + if (histogram->data_[i] > 0) { + /* Compute -log2(P(symbol)) = -log2(count(symbol)/total_count) = + = log2(total_count) - log2(count(symbol)) */ + double log2p = log2total - FastLog2(histogram->data_[i]); + /* Approximate the bit depth by round(-log2(P(symbol))) */ + size_t depth = (size_t)(log2p + 0.5); + bits += histogram->data_[i] * log2p; + if (depth > 15) { + depth = 15; + } + if (depth > max_depth) { + max_depth = depth; + } + ++depth_histo[depth]; + ++i; + } else { + /* Compute the run length of zeros and add the appropriate number of 0 + and 17 code length codes to the code length code histogram. */ + uint32_t reps = 1; + size_t k; + for (k = i + 1; k < data_size && histogram->data_[k] == 0; ++k) { + ++reps; + } + i += reps; + if (i == data_size) { + /* Don't add any cost for the last zero run, since these are encoded + only implicitly. */ + break; + } + if (reps < 3) { + depth_histo[0] += reps; + } else { + reps -= 2; + while (reps > 0) { + ++depth_histo[BROTLI_REPEAT_ZERO_CODE_LENGTH]; + /* Add the 3 extra bits for the 17 code length code. */ + bits += 3; + reps >>= 3; + } + } + } + } + /* Add the estimated encoding cost of the code length code histogram. */ + bits += (double)(18 + 2 * max_depth); + /* Add the entropy of the code length code histogram. */ + bits += BitsEntropy(depth_histo, BROTLI_CODE_LENGTH_CODES); + } + return bits; +} + +#undef HistogramType +#undef FN + +#define FN(X) duckdb_brotli:: X ## Command +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +#define HistogramType FN(Histogram) + +double FN(BrotliPopulationCost)(const HistogramType* histogram) { + static const double kOneSymbolHistogramCost = 12; + static const double kTwoSymbolHistogramCost = 20; + static const double kThreeSymbolHistogramCost = 28; + static const double kFourSymbolHistogramCost = 37; + const size_t data_size = FN(HistogramDataSize)(); + int count = 0; + size_t s[5]; + double bits = 0.0; + size_t i; + if (histogram->total_count_ == 0) { + return kOneSymbolHistogramCost; + } + for (i = 0; i < data_size; ++i) { + if (histogram->data_[i] > 0) { + s[count] = i; + ++count; + if (count > 4) break; + } + } + if (count == 1) { + return kOneSymbolHistogramCost; + } + if (count == 2) { + return (kTwoSymbolHistogramCost + (double)histogram->total_count_); + } + if (count == 3) { + const uint32_t histo0 = histogram->data_[s[0]]; + const uint32_t histo1 = histogram->data_[s[1]]; + const uint32_t histo2 = histogram->data_[s[2]]; + const uint32_t histomax = + BROTLI_MAX(uint32_t, histo0, BROTLI_MAX(uint32_t, histo1, histo2)); + return (kThreeSymbolHistogramCost + + 2 * (histo0 + histo1 + histo2) - histomax); + } + if (count == 4) { + uint32_t histo[4]; + uint32_t h23; + uint32_t histomax; + for (i = 0; i < 4; ++i) { + histo[i] = histogram->data_[s[i]]; + } + /* Sort */ + for (i = 0; i < 4; ++i) { + size_t j; + for (j = i + 1; j < 4; ++j) { + if (histo[j] > histo[i]) { + BROTLI_SWAP(uint32_t, histo, j, i); + } + } + } + h23 = histo[2] + histo[3]; + histomax = BROTLI_MAX(uint32_t, h23, histo[0]); + return (kFourSymbolHistogramCost + + 3 * h23 + 2 * (histo[0] + histo[1]) - histomax); + } + + { + /* In this loop we compute the entropy of the histogram and simultaneously + build a simplified histogram of the code length codes where we use the + zero repeat code 17, but we don't use the non-zero repeat code 16. */ + size_t max_depth = 1; + uint32_t depth_histo[BROTLI_CODE_LENGTH_CODES] = { 0 }; + const double log2total = FastLog2(histogram->total_count_); + for (i = 0; i < data_size;) { + if (histogram->data_[i] > 0) { + /* Compute -log2(P(symbol)) = -log2(count(symbol)/total_count) = + = log2(total_count) - log2(count(symbol)) */ + double log2p = log2total - FastLog2(histogram->data_[i]); + /* Approximate the bit depth by round(-log2(P(symbol))) */ + size_t depth = (size_t)(log2p + 0.5); + bits += histogram->data_[i] * log2p; + if (depth > 15) { + depth = 15; + } + if (depth > max_depth) { + max_depth = depth; + } + ++depth_histo[depth]; + ++i; + } else { + /* Compute the run length of zeros and add the appropriate number of 0 + and 17 code length codes to the code length code histogram. */ + uint32_t reps = 1; + size_t k; + for (k = i + 1; k < data_size && histogram->data_[k] == 0; ++k) { + ++reps; + } + i += reps; + if (i == data_size) { + /* Don't add any cost for the last zero run, since these are encoded + only implicitly. */ + break; + } + if (reps < 3) { + depth_histo[0] += reps; + } else { + reps -= 2; + while (reps > 0) { + ++depth_histo[BROTLI_REPEAT_ZERO_CODE_LENGTH]; + /* Add the 3 extra bits for the 17 code length code. */ + bits += 3; + reps >>= 3; + } + } + } + } + /* Add the estimated encoding cost of the code length code histogram. */ + bits += (double)(18 + 2 * max_depth); + /* Add the entropy of the code length code histogram. */ + bits += BitsEntropy(depth_histo, BROTLI_CODE_LENGTH_CODES); + } + return bits; +} + +#undef HistogramType +#undef FN + +#define FN(X) duckdb_brotli:: X ## Distance +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +#define HistogramType FN(Histogram) + +double FN(BrotliPopulationCost)(const HistogramType* histogram) { + static const double kOneSymbolHistogramCost = 12; + static const double kTwoSymbolHistogramCost = 20; + static const double kThreeSymbolHistogramCost = 28; + static const double kFourSymbolHistogramCost = 37; + const size_t data_size = FN(HistogramDataSize)(); + int count = 0; + size_t s[5]; + double bits = 0.0; + size_t i; + if (histogram->total_count_ == 0) { + return kOneSymbolHistogramCost; + } + for (i = 0; i < data_size; ++i) { + if (histogram->data_[i] > 0) { + s[count] = i; + ++count; + if (count > 4) break; + } + } + if (count == 1) { + return kOneSymbolHistogramCost; + } + if (count == 2) { + return (kTwoSymbolHistogramCost + (double)histogram->total_count_); + } + if (count == 3) { + const uint32_t histo0 = histogram->data_[s[0]]; + const uint32_t histo1 = histogram->data_[s[1]]; + const uint32_t histo2 = histogram->data_[s[2]]; + const uint32_t histomax = + BROTLI_MAX(uint32_t, histo0, BROTLI_MAX(uint32_t, histo1, histo2)); + return (kThreeSymbolHistogramCost + + 2 * (histo0 + histo1 + histo2) - histomax); + } + if (count == 4) { + uint32_t histo[4]; + uint32_t h23; + uint32_t histomax; + for (i = 0; i < 4; ++i) { + histo[i] = histogram->data_[s[i]]; + } + /* Sort */ + for (i = 0; i < 4; ++i) { + size_t j; + for (j = i + 1; j < 4; ++j) { + if (histo[j] > histo[i]) { + BROTLI_SWAP(uint32_t, histo, j, i); + } + } + } + h23 = histo[2] + histo[3]; + histomax = BROTLI_MAX(uint32_t, h23, histo[0]); + return (kFourSymbolHistogramCost + + 3 * h23 + 2 * (histo[0] + histo[1]) - histomax); + } + + { + /* In this loop we compute the entropy of the histogram and simultaneously + build a simplified histogram of the code length codes where we use the + zero repeat code 17, but we don't use the non-zero repeat code 16. */ + size_t max_depth = 1; + uint32_t depth_histo[BROTLI_CODE_LENGTH_CODES] = { 0 }; + const double log2total = FastLog2(histogram->total_count_); + for (i = 0; i < data_size;) { + if (histogram->data_[i] > 0) { + /* Compute -log2(P(symbol)) = -log2(count(symbol)/total_count) = + = log2(total_count) - log2(count(symbol)) */ + double log2p = log2total - FastLog2(histogram->data_[i]); + /* Approximate the bit depth by round(-log2(P(symbol))) */ + size_t depth = (size_t)(log2p + 0.5); + bits += histogram->data_[i] * log2p; + if (depth > 15) { + depth = 15; + } + if (depth > max_depth) { + max_depth = depth; + } + ++depth_histo[depth]; + ++i; + } else { + /* Compute the run length of zeros and add the appropriate number of 0 + and 17 code length codes to the code length code histogram. */ + uint32_t reps = 1; + size_t k; + for (k = i + 1; k < data_size && histogram->data_[k] == 0; ++k) { + ++reps; + } + i += reps; + if (i == data_size) { + /* Don't add any cost for the last zero run, since these are encoded + only implicitly. */ + break; + } + if (reps < 3) { + depth_histo[0] += reps; + } else { + reps -= 2; + while (reps > 0) { + ++depth_histo[BROTLI_REPEAT_ZERO_CODE_LENGTH]; + /* Add the 3 extra bits for the 17 code length code. */ + bits += 3; + reps >>= 3; + } + } + } + } + /* Add the estimated encoding cost of the code length code histogram. */ + bits += (double)(18 + 2 * max_depth); + /* Add the entropy of the code length code histogram. */ + bits += BitsEntropy(depth_histo, BROTLI_CODE_LENGTH_CODES); + } + return bits; +} + +#undef HistogramType +#undef FN + + diff --git a/third_party/brotli/enc/bit_cost.h b/third_party/brotli/enc/bit_cost.h new file mode 100644 index 00000000000..6ef61d81aa6 --- /dev/null +++ b/third_party/brotli/enc/bit_cost.h @@ -0,0 +1,60 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Functions to estimate the bit cost of Huffman trees. */ + +#ifndef BROTLI_ENC_BIT_COST_H_ +#define BROTLI_ENC_BIT_COST_H_ + +#include + +#include "../common/brotli_platform.h" +#include "fast_log.h" +#include "histogram.h" + +namespace duckdb_brotli { + +static BROTLI_INLINE double ShannonEntropy( + const uint32_t* population, size_t size, size_t* total) { + size_t sum = 0; + double retval = 0; + const uint32_t* population_end = population + size; + size_t p; + if (size & 1) { + goto odd_number_of_elements_left; + } + while (population < population_end) { + p = *population++; + sum += p; + retval -= (double)p * FastLog2(p); + odd_number_of_elements_left: + p = *population++; + sum += p; + retval -= (double)p * FastLog2(p); + } + if (sum) retval += (double)sum * FastLog2(sum); + *total = sum; + return retval; +} + +static BROTLI_INLINE double BitsEntropy( + const uint32_t* population, size_t size) { + size_t sum; + double retval = ShannonEntropy(population, size, &sum); + if (retval < (double)sum) { + /* At least one bit per literal is needed. */ + retval = (double)sum; + } + return retval; +} + +BROTLI_INTERNAL double BrotliPopulationCostLiteral(const HistogramLiteral*); +BROTLI_INTERNAL double BrotliPopulationCostCommand(const HistogramCommand*); +BROTLI_INTERNAL double BrotliPopulationCostDistance(const HistogramDistance*); + +} + +#endif /* BROTLI_ENC_BIT_COST_H_ */ diff --git a/third_party/brotli/enc/block_splitter.cpp b/third_party/brotli/enc/block_splitter.cpp new file mode 100644 index 00000000000..7208c61b4d7 --- /dev/null +++ b/third_party/brotli/enc/block_splitter.cpp @@ -0,0 +1,1653 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Block split point selection utilities. */ + +#include "block_splitter.h" + +#include /* memcpy, memset */ + +#include "../common/brotli_platform.h" +#include "bit_cost.h" +#include "cluster.h" +#include "command.h" +#include "fast_log.h" +#include "histogram.h" +#include "memory.h" +#include "quality.h" + +using namespace duckdb_brotli; + +static const size_t kMaxLiteralHistograms = 100; +static const size_t kMaxCommandHistograms = 50; +static const double kLiteralBlockSwitchCost = 28.1; +static const double kCommandBlockSwitchCost = 13.5; +static const double kDistanceBlockSwitchCost = 14.6; +static const size_t kLiteralStrideLength = 70; +static const size_t kCommandStrideLength = 40; +static const size_t kDistanceStrideLength = 40; +static const size_t kSymbolsPerLiteralHistogram = 544; +static const size_t kSymbolsPerCommandHistogram = 530; +static const size_t kSymbolsPerDistanceHistogram = 544; +static const size_t kMinLengthForBlockSplitting = 128; +static const size_t kIterMulForRefining = 2; +static const size_t kMinItersForRefining = 100; + +static size_t CountLiterals(const Command* cmds, const size_t num_commands) { + /* Count how many we have. */ + size_t total_length = 0; + size_t i; + for (i = 0; i < num_commands; ++i) { + total_length += cmds[i].insert_len_; + } + return total_length; +} + +static void CopyLiteralsToByteArray(const Command* cmds, + const size_t num_commands, + const uint8_t* data, + const size_t offset, + const size_t mask, + uint8_t* literals) { + size_t pos = 0; + size_t from_pos = offset & mask; + size_t i; + for (i = 0; i < num_commands; ++i) { + size_t insert_len = cmds[i].insert_len_; + if (from_pos + insert_len > mask) { + size_t head_size = mask + 1 - from_pos; + memcpy(literals + pos, data + from_pos, head_size); + from_pos = 0; + pos += head_size; + insert_len -= head_size; + } + if (insert_len > 0) { + memcpy(literals + pos, data + from_pos, insert_len); + pos += insert_len; + } + from_pos = (from_pos + insert_len + CommandCopyLen(&cmds[i])) & mask; + } +} + +static BROTLI_INLINE uint32_t MyRand(uint32_t* seed) { + /* Initial seed should be 7. In this case, loop length is (1 << 29). */ + *seed *= 16807U; + return *seed; +} + +static BROTLI_INLINE double BitCost(size_t count) { + return count == 0 ? -2.0 : FastLog2(count); +} + +#define HISTOGRAMS_PER_BATCH 64 +#define CLUSTERS_PER_BATCH 16 + +#define FN(X) X ## Literal +#define DataType uint8_t +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, DataType */ + +#define HistogramType FN(Histogram) + +static void FN(InitialEntropyCodes)(const DataType* data, size_t length, + size_t stride, + size_t num_histograms, + HistogramType* histograms) { + uint32_t seed = 7; + size_t block_length = length / num_histograms; + size_t i; + FN(ClearHistograms)(histograms, num_histograms); + for (i = 0; i < num_histograms; ++i) { + size_t pos = length * i / num_histograms; + if (i != 0) { + pos += MyRand(&seed) % block_length; + } + if (pos + stride >= length) { + pos = length - stride - 1; + } + FN(HistogramAddVector)(&histograms[i], data + pos, stride); + } +} + +static void FN(RandomSample)(uint32_t* seed, + const DataType* data, + size_t length, + size_t stride, + HistogramType* sample) { + size_t pos = 0; + if (stride >= length) { + stride = length; + } else { + pos = MyRand(seed) % (length - stride + 1); + } + FN(HistogramAddVector)(sample, data + pos, stride); +} + +static void FN(RefineEntropyCodes)(const DataType* data, size_t length, + size_t stride, + size_t num_histograms, + HistogramType* histograms, + HistogramType* tmp) { + size_t iters = + kIterMulForRefining * length / stride + kMinItersForRefining; + uint32_t seed = 7; + size_t iter; + iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms; + for (iter = 0; iter < iters; ++iter) { + FN(HistogramClear)(tmp); + FN(RandomSample)(&seed, data, length, stride, tmp); + FN(HistogramAddHistogram)(&histograms[iter % num_histograms], tmp); + } +} + +/* Assigns a block id from the range [0, num_histograms) to each data element + in data[0..length) and fills in block_id[0..length) with the assigned values. + Returns the number of blocks, i.e. one plus the number of block switches. */ +static size_t FN(FindBlocks)(const DataType* data, const size_t length, + const double block_switch_bitcost, + const size_t num_histograms, + const HistogramType* histograms, + double* insert_cost, + double* cost, + uint8_t* switch_signal, + uint8_t* block_id) { + const size_t alphabet_size = FN(HistogramDataSize)(); + const size_t bitmap_len = (num_histograms + 7) >> 3; + size_t num_blocks = 1; + size_t byte_ix; + size_t i; + size_t j; + BROTLI_DCHECK(num_histograms <= 256); + + /* Trivial case: single historgram -> single block type. */ + if (num_histograms <= 1) { + for (i = 0; i < length; ++i) { + block_id[i] = 0; + } + return 1; + } + + /* Fill bitcost for each symbol of all histograms. + * Non-existing symbol cost: 2 + log2(total_count). + * Regular symbol cost: -log2(symbol_count / total_count). */ + memset(insert_cost, 0, + sizeof(insert_cost[0]) * alphabet_size * num_histograms); + for (i = 0; i < num_histograms; ++i) { + insert_cost[i] = FastLog2((uint32_t)histograms[i].total_count_); + } + for (i = alphabet_size; i != 0;) { + /* Reverse order to use the 0-th row as a temporary storage. */ + --i; + for (j = 0; j < num_histograms; ++j) { + insert_cost[i * num_histograms + j] = + insert_cost[j] - BitCost(histograms[j].data_[i]); + } + } + + /* After each iteration of this loop, cost[k] will contain the difference + between the minimum cost of arriving at the current byte position using + entropy code k, and the minimum cost of arriving at the current byte + position. This difference is capped at the block switch cost, and if it + reaches block switch cost, it means that when we trace back from the last + position, we need to switch here. */ + memset(cost, 0, sizeof(cost[0]) * num_histograms); + memset(switch_signal, 0, sizeof(switch_signal[0]) * length * bitmap_len); + for (byte_ix = 0; byte_ix < length; ++byte_ix) { + size_t ix = byte_ix * bitmap_len; + size_t symbol = data[byte_ix]; + size_t insert_cost_ix = symbol * num_histograms; + double min_cost = 1e99; + double block_switch_cost = block_switch_bitcost; + size_t k; + for (k = 0; k < num_histograms; ++k) { + /* We are coding the symbol with entropy code k. */ + cost[k] += insert_cost[insert_cost_ix + k]; + if (cost[k] < min_cost) { + min_cost = cost[k]; + block_id[byte_ix] = (uint8_t)k; + } + } + /* More blocks for the beginning. */ + if (byte_ix < 2000) { + block_switch_cost *= 0.77 + 0.07 * (double)byte_ix / 2000; + } + for (k = 0; k < num_histograms; ++k) { + cost[k] -= min_cost; + if (cost[k] >= block_switch_cost) { + const uint8_t mask = (uint8_t)(1u << (k & 7)); + cost[k] = block_switch_cost; + BROTLI_DCHECK((k >> 3) < bitmap_len); + switch_signal[ix + (k >> 3)] |= mask; + } + } + } + + byte_ix = length - 1; + { /* Trace back from the last position and switch at the marked places. */ + size_t ix = byte_ix * bitmap_len; + uint8_t cur_id = block_id[byte_ix]; + while (byte_ix > 0) { + const uint8_t mask = (uint8_t)(1u << (cur_id & 7)); + BROTLI_DCHECK(((size_t)cur_id >> 3) < bitmap_len); + --byte_ix; + ix -= bitmap_len; + if (switch_signal[ix + (cur_id >> 3)] & mask) { + if (cur_id != block_id[byte_ix]) { + cur_id = block_id[byte_ix]; + ++num_blocks; + } + } + block_id[byte_ix] = cur_id; + } + } + return num_blocks; +} + +static size_t FN(RemapBlockIds)(uint8_t* block_ids, const size_t length, + uint16_t* new_id, const size_t num_histograms) { + static const uint16_t kInvalidId = 256; + uint16_t next_id = 0; + size_t i; + for (i = 0; i < num_histograms; ++i) { + new_id[i] = kInvalidId; + } + for (i = 0; i < length; ++i) { + BROTLI_DCHECK(block_ids[i] < num_histograms); + if (new_id[block_ids[i]] == kInvalidId) { + new_id[block_ids[i]] = next_id++; + } + } + for (i = 0; i < length; ++i) { + block_ids[i] = (uint8_t)new_id[block_ids[i]]; + BROTLI_DCHECK(block_ids[i] < num_histograms); + } + BROTLI_DCHECK(next_id <= num_histograms); + return next_id; +} + +static void FN(BuildBlockHistograms)(const DataType* data, const size_t length, + const uint8_t* block_ids, + const size_t num_histograms, + HistogramType* histograms) { + size_t i; + FN(ClearHistograms)(histograms, num_histograms); + for (i = 0; i < length; ++i) { + FN(HistogramAdd)(&histograms[block_ids[i]], data[i]); + } +} + +/* Given the initial partitioning build partitioning with limited number + * of histograms (and block types). */ +static void FN(ClusterBlocks)(MemoryManager* m, + const DataType* data, const size_t length, + const size_t num_blocks, + uint8_t* block_ids, + BlockSplit* split) { + uint32_t* histogram_symbols = BROTLI_ALLOC(m, uint32_t, num_blocks); + uint32_t* u32 = + BROTLI_ALLOC(m, uint32_t, num_blocks + 4 * HISTOGRAMS_PER_BATCH); + const size_t expected_num_clusters = CLUSTERS_PER_BATCH * + (num_blocks + HISTOGRAMS_PER_BATCH - 1) / HISTOGRAMS_PER_BATCH; + size_t all_histograms_size = 0; + size_t all_histograms_capacity = expected_num_clusters; + HistogramType* all_histograms = + BROTLI_ALLOC(m, HistogramType, all_histograms_capacity); + size_t cluster_size_size = 0; + size_t cluster_size_capacity = expected_num_clusters; + uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, cluster_size_capacity); + size_t num_clusters = 0; + HistogramType* histograms = BROTLI_ALLOC(m, HistogramType, + BROTLI_MIN(size_t, num_blocks, HISTOGRAMS_PER_BATCH)); + size_t max_num_pairs = + HISTOGRAMS_PER_BATCH * HISTOGRAMS_PER_BATCH / 2; + size_t pairs_capacity = max_num_pairs + 1; + HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity); + size_t pos = 0; + uint32_t* clusters; + size_t num_final_clusters; + static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; + uint32_t* new_index; + size_t i; + uint32_t* BROTLI_RESTRICT const sizes = u32 + 0 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const new_clusters = u32 + 1 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const symbols = u32 + 2 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const remap = u32 + 3 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const block_lengths = + u32 + 4 * HISTOGRAMS_PER_BATCH; + /* TODO(eustas): move to arena? */ + HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 2); + + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histogram_symbols) || + BROTLI_IS_NULL(u32) || BROTLI_IS_NULL(all_histograms) || + BROTLI_IS_NULL(cluster_size) || BROTLI_IS_NULL(histograms) || + BROTLI_IS_NULL(pairs) || BROTLI_IS_NULL(tmp)) { + return; + } + + memset(u32, 0, (num_blocks + 4 * HISTOGRAMS_PER_BATCH) * sizeof(uint32_t)); + + /* Calculate block lengths (convert repeating values -> series length). */ + { + size_t block_idx = 0; + for (i = 0; i < length; ++i) { + BROTLI_DCHECK(block_idx < num_blocks); + ++block_lengths[block_idx]; + if (i + 1 == length || block_ids[i] != block_ids[i + 1]) { + ++block_idx; + } + } + BROTLI_DCHECK(block_idx == num_blocks); + } + + /* Pre-cluster blocks (cluster batches). */ + for (i = 0; i < num_blocks; i += HISTOGRAMS_PER_BATCH) { + const size_t num_to_combine = + BROTLI_MIN(size_t, num_blocks - i, HISTOGRAMS_PER_BATCH); + size_t num_new_clusters; + size_t j; + for (j = 0; j < num_to_combine; ++j) { + size_t k; + size_t block_length = block_lengths[i + j]; + FN(HistogramClear)(&histograms[j]); + for (k = 0; k < block_length; ++k) { + FN(HistogramAdd)(&histograms[j], data[pos++]); + } + histograms[j].bit_cost_ = FN(BrotliPopulationCost)(&histograms[j]); + new_clusters[j] = (uint32_t)j; + symbols[j] = (uint32_t)j; + sizes[j] = 1; + } + num_new_clusters = FN(BrotliHistogramCombine)( + histograms, tmp, sizes, symbols, new_clusters, pairs, num_to_combine, + num_to_combine, HISTOGRAMS_PER_BATCH, max_num_pairs); + BROTLI_ENSURE_CAPACITY(m, HistogramType, all_histograms, + all_histograms_capacity, all_histograms_size + num_new_clusters); + BROTLI_ENSURE_CAPACITY(m, uint32_t, cluster_size, + cluster_size_capacity, cluster_size_size + num_new_clusters); + if (BROTLI_IS_OOM(m)) return; + for (j = 0; j < num_new_clusters; ++j) { + all_histograms[all_histograms_size++] = histograms[new_clusters[j]]; + cluster_size[cluster_size_size++] = sizes[new_clusters[j]]; + remap[new_clusters[j]] = (uint32_t)j; + } + for (j = 0; j < num_to_combine; ++j) { + histogram_symbols[i + j] = (uint32_t)num_clusters + remap[symbols[j]]; + } + num_clusters += num_new_clusters; + BROTLI_DCHECK(num_clusters == cluster_size_size); + BROTLI_DCHECK(num_clusters == all_histograms_size); + } + BROTLI_FREE(m, histograms); + + /* Final clustering. */ + max_num_pairs = + BROTLI_MIN(size_t, 64 * num_clusters, (num_clusters / 2) * num_clusters); + if (pairs_capacity < max_num_pairs + 1) { + BROTLI_FREE(m, pairs); + pairs = BROTLI_ALLOC(m, HistogramPair, max_num_pairs + 1); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(pairs)) return; + } + clusters = BROTLI_ALLOC(m, uint32_t, num_clusters); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(clusters)) return; + for (i = 0; i < num_clusters; ++i) { + clusters[i] = (uint32_t)i; + } + num_final_clusters = FN(BrotliHistogramCombine)( + all_histograms, tmp, cluster_size, histogram_symbols, clusters, pairs, + num_clusters, num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES, + max_num_pairs); + BROTLI_FREE(m, pairs); + BROTLI_FREE(m, cluster_size); + + /* Assign blocks to final histograms. */ + new_index = BROTLI_ALLOC(m, uint32_t, num_clusters); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return; + for (i = 0; i < num_clusters; ++i) new_index[i] = kInvalidIndex; + pos = 0; + { + uint32_t next_index = 0; + for (i = 0; i < num_blocks; ++i) { + size_t j; + uint32_t best_out; + double best_bits; + FN(HistogramClear)(tmp); + for (j = 0; j < block_lengths[i]; ++j) { + FN(HistogramAdd)(tmp, data[pos++]); + } + /* Among equally good histograms prefer last used. */ + /* TODO(eustas): should we give a block-switch discount here? */ + best_out = (i == 0) ? histogram_symbols[0] : histogram_symbols[i - 1]; + best_bits = FN(BrotliHistogramBitCostDistance)( + tmp, &all_histograms[best_out], tmp + 1); + for (j = 0; j < num_final_clusters; ++j) { + const double cur_bits = FN(BrotliHistogramBitCostDistance)( + tmp, &all_histograms[clusters[j]], tmp + 1); + if (cur_bits < best_bits) { + best_bits = cur_bits; + best_out = clusters[j]; + } + } + histogram_symbols[i] = best_out; + if (new_index[best_out] == kInvalidIndex) { + new_index[best_out] = next_index++; + } + } + } + BROTLI_FREE(m, tmp); + BROTLI_FREE(m, clusters); + BROTLI_FREE(m, all_histograms); + BROTLI_ENSURE_CAPACITY( + m, uint8_t, split->types, split->types_alloc_size, num_blocks); + BROTLI_ENSURE_CAPACITY( + m, uint32_t, split->lengths, split->lengths_alloc_size, num_blocks); + if (BROTLI_IS_OOM(m)) return; + + /* Rewrite final assignment to block-split. There might be less blocks + * than |num_blocks| due to clustering. */ + { + uint32_t cur_length = 0; + size_t block_idx = 0; + uint8_t max_type = 0; + for (i = 0; i < num_blocks; ++i) { + cur_length += block_lengths[i]; + if (i + 1 == num_blocks || + histogram_symbols[i] != histogram_symbols[i + 1]) { + const uint8_t id = (uint8_t)new_index[histogram_symbols[i]]; + split->types[block_idx] = id; + split->lengths[block_idx] = cur_length; + max_type = BROTLI_MAX(uint8_t, max_type, id); + cur_length = 0; + ++block_idx; + } + } + split->num_blocks = block_idx; + split->num_types = (size_t)max_type + 1; + } + BROTLI_FREE(m, new_index); + BROTLI_FREE(m, u32); + BROTLI_FREE(m, histogram_symbols); +} + +/* Create BlockSplit (partitioning) given the limits, estimates and "effort" + * parameters. + * + * NB: max_histograms is often less than number of histograms allowed by format; + * this is done intentionally, to save some "space" for context-aware + * clustering (here entropy is estimated for context-free symbols). */ +static void FN(SplitByteVector)(MemoryManager* m, + const DataType* data, const size_t length, + const size_t symbols_per_histogram, + const size_t max_histograms, + const size_t sampling_stride_length, + const double block_switch_cost, + const BrotliEncoderParams* params, + BlockSplit* split) { + const size_t data_size = FN(HistogramDataSize)(); + HistogramType* histograms; + HistogramType* tmp; + /* Calculate number of histograms; initial estimate is one histogram per + * specified amount of symbols; however, this value is capped. */ + size_t num_histograms = length / symbols_per_histogram + 1; + if (num_histograms > max_histograms) { + num_histograms = max_histograms; + } + + /* Corner case: no input. */ + if (length == 0) { + split->num_types = 1; + return; + } + + if (length < kMinLengthForBlockSplitting) { + BROTLI_ENSURE_CAPACITY(m, uint8_t, + split->types, split->types_alloc_size, split->num_blocks + 1); + BROTLI_ENSURE_CAPACITY(m, uint32_t, + split->lengths, split->lengths_alloc_size, split->num_blocks + 1); + if (BROTLI_IS_OOM(m)) return; + split->num_types = 1; + split->types[split->num_blocks] = 0; + split->lengths[split->num_blocks] = (uint32_t)length; + split->num_blocks++; + return; + } + histograms = BROTLI_ALLOC(m, HistogramType, num_histograms + 1); + tmp = histograms + num_histograms; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histograms)) return; + /* Find good entropy codes. */ + FN(InitialEntropyCodes)(data, length, + sampling_stride_length, + num_histograms, histograms); + FN(RefineEntropyCodes)(data, length, + sampling_stride_length, + num_histograms, histograms, tmp); + { + /* Find a good path through literals with the good entropy codes. */ + uint8_t* block_ids = BROTLI_ALLOC(m, uint8_t, length); + size_t num_blocks = 0; + const size_t bitmaplen = (num_histograms + 7) >> 3; + double* insert_cost = BROTLI_ALLOC(m, double, data_size * num_histograms); + double* cost = BROTLI_ALLOC(m, double, num_histograms); + uint8_t* switch_signal = BROTLI_ALLOC(m, uint8_t, length * bitmaplen); + uint16_t* new_id = BROTLI_ALLOC(m, uint16_t, num_histograms); + const size_t iters = params->quality < HQ_ZOPFLIFICATION_QUALITY ? 3 : 10; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(block_ids) || + BROTLI_IS_NULL(insert_cost) || BROTLI_IS_NULL(cost) || + BROTLI_IS_NULL(switch_signal) || BROTLI_IS_NULL(new_id)) { + return; + } + for (i = 0; i < iters; ++i) { + num_blocks = FN(FindBlocks)(data, length, + block_switch_cost, + num_histograms, histograms, + insert_cost, cost, switch_signal, + block_ids); + num_histograms = FN(RemapBlockIds)(block_ids, length, + new_id, num_histograms); + FN(BuildBlockHistograms)(data, length, block_ids, + num_histograms, histograms); + } + BROTLI_FREE(m, insert_cost); + BROTLI_FREE(m, cost); + BROTLI_FREE(m, switch_signal); + BROTLI_FREE(m, new_id); + BROTLI_FREE(m, histograms); + FN(ClusterBlocks)(m, data, length, num_blocks, block_ids, split); + if (BROTLI_IS_OOM(m)) return; + BROTLI_FREE(m, block_ids); + } +} + +#undef HistogramType +#undef DataType +#undef FN + +#define FN(X) X ## Command +#define DataType uint16_t +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, DataType */ + +#define HistogramType FN(Histogram) + +static void FN(InitialEntropyCodes)(const DataType* data, size_t length, + size_t stride, + size_t num_histograms, + HistogramType* histograms) { + uint32_t seed = 7; + size_t block_length = length / num_histograms; + size_t i; + FN(ClearHistograms)(histograms, num_histograms); + for (i = 0; i < num_histograms; ++i) { + size_t pos = length * i / num_histograms; + if (i != 0) { + pos += MyRand(&seed) % block_length; + } + if (pos + stride >= length) { + pos = length - stride - 1; + } + FN(HistogramAddVector)(&histograms[i], data + pos, stride); + } +} + +static void FN(RandomSample)(uint32_t* seed, + const DataType* data, + size_t length, + size_t stride, + HistogramType* sample) { + size_t pos = 0; + if (stride >= length) { + stride = length; + } else { + pos = MyRand(seed) % (length - stride + 1); + } + FN(HistogramAddVector)(sample, data + pos, stride); +} + +static void FN(RefineEntropyCodes)(const DataType* data, size_t length, + size_t stride, + size_t num_histograms, + HistogramType* histograms, + HistogramType* tmp) { + size_t iters = + kIterMulForRefining * length / stride + kMinItersForRefining; + uint32_t seed = 7; + size_t iter; + iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms; + for (iter = 0; iter < iters; ++iter) { + FN(HistogramClear)(tmp); + FN(RandomSample)(&seed, data, length, stride, tmp); + FN(HistogramAddHistogram)(&histograms[iter % num_histograms], tmp); + } +} + +/* Assigns a block id from the range [0, num_histograms) to each data element + in data[0..length) and fills in block_id[0..length) with the assigned values. + Returns the number of blocks, i.e. one plus the number of block switches. */ +static size_t FN(FindBlocks)(const DataType* data, const size_t length, + const double block_switch_bitcost, + const size_t num_histograms, + const HistogramType* histograms, + double* insert_cost, + double* cost, + uint8_t* switch_signal, + uint8_t* block_id) { + const size_t alphabet_size = FN(HistogramDataSize)(); + const size_t bitmap_len = (num_histograms + 7) >> 3; + size_t num_blocks = 1; + size_t byte_ix; + size_t i; + size_t j; + BROTLI_DCHECK(num_histograms <= 256); + + /* Trivial case: single historgram -> single block type. */ + if (num_histograms <= 1) { + for (i = 0; i < length; ++i) { + block_id[i] = 0; + } + return 1; + } + + /* Fill bitcost for each symbol of all histograms. + * Non-existing symbol cost: 2 + log2(total_count). + * Regular symbol cost: -log2(symbol_count / total_count). */ + memset(insert_cost, 0, + sizeof(insert_cost[0]) * alphabet_size * num_histograms); + for (i = 0; i < num_histograms; ++i) { + insert_cost[i] = FastLog2((uint32_t)histograms[i].total_count_); + } + for (i = alphabet_size; i != 0;) { + /* Reverse order to use the 0-th row as a temporary storage. */ + --i; + for (j = 0; j < num_histograms; ++j) { + insert_cost[i * num_histograms + j] = + insert_cost[j] - BitCost(histograms[j].data_[i]); + } + } + + /* After each iteration of this loop, cost[k] will contain the difference + between the minimum cost of arriving at the current byte position using + entropy code k, and the minimum cost of arriving at the current byte + position. This difference is capped at the block switch cost, and if it + reaches block switch cost, it means that when we trace back from the last + position, we need to switch here. */ + memset(cost, 0, sizeof(cost[0]) * num_histograms); + memset(switch_signal, 0, sizeof(switch_signal[0]) * length * bitmap_len); + for (byte_ix = 0; byte_ix < length; ++byte_ix) { + size_t ix = byte_ix * bitmap_len; + size_t symbol = data[byte_ix]; + size_t insert_cost_ix = symbol * num_histograms; + double min_cost = 1e99; + double block_switch_cost = block_switch_bitcost; + size_t k; + for (k = 0; k < num_histograms; ++k) { + /* We are coding the symbol with entropy code k. */ + cost[k] += insert_cost[insert_cost_ix + k]; + if (cost[k] < min_cost) { + min_cost = cost[k]; + block_id[byte_ix] = (uint8_t)k; + } + } + /* More blocks for the beginning. */ + if (byte_ix < 2000) { + block_switch_cost *= 0.77 + 0.07 * (double)byte_ix / 2000; + } + for (k = 0; k < num_histograms; ++k) { + cost[k] -= min_cost; + if (cost[k] >= block_switch_cost) { + const uint8_t mask = (uint8_t)(1u << (k & 7)); + cost[k] = block_switch_cost; + BROTLI_DCHECK((k >> 3) < bitmap_len); + switch_signal[ix + (k >> 3)] |= mask; + } + } + } + + byte_ix = length - 1; + { /* Trace back from the last position and switch at the marked places. */ + size_t ix = byte_ix * bitmap_len; + uint8_t cur_id = block_id[byte_ix]; + while (byte_ix > 0) { + const uint8_t mask = (uint8_t)(1u << (cur_id & 7)); + BROTLI_DCHECK(((size_t)cur_id >> 3) < bitmap_len); + --byte_ix; + ix -= bitmap_len; + if (switch_signal[ix + (cur_id >> 3)] & mask) { + if (cur_id != block_id[byte_ix]) { + cur_id = block_id[byte_ix]; + ++num_blocks; + } + } + block_id[byte_ix] = cur_id; + } + } + return num_blocks; +} + +static size_t FN(RemapBlockIds)(uint8_t* block_ids, const size_t length, + uint16_t* new_id, const size_t num_histograms) { + static const uint16_t kInvalidId = 256; + uint16_t next_id = 0; + size_t i; + for (i = 0; i < num_histograms; ++i) { + new_id[i] = kInvalidId; + } + for (i = 0; i < length; ++i) { + BROTLI_DCHECK(block_ids[i] < num_histograms); + if (new_id[block_ids[i]] == kInvalidId) { + new_id[block_ids[i]] = next_id++; + } + } + for (i = 0; i < length; ++i) { + block_ids[i] = (uint8_t)new_id[block_ids[i]]; + BROTLI_DCHECK(block_ids[i] < num_histograms); + } + BROTLI_DCHECK(next_id <= num_histograms); + return next_id; +} + +static void FN(BuildBlockHistograms)(const DataType* data, const size_t length, + const uint8_t* block_ids, + const size_t num_histograms, + HistogramType* histograms) { + size_t i; + FN(ClearHistograms)(histograms, num_histograms); + for (i = 0; i < length; ++i) { + FN(HistogramAdd)(&histograms[block_ids[i]], data[i]); + } +} + +/* Given the initial partitioning build partitioning with limited number + * of histograms (and block types). */ +static void FN(ClusterBlocks)(MemoryManager* m, + const DataType* data, const size_t length, + const size_t num_blocks, + uint8_t* block_ids, + BlockSplit* split) { + uint32_t* histogram_symbols = BROTLI_ALLOC(m, uint32_t, num_blocks); + uint32_t* u32 = + BROTLI_ALLOC(m, uint32_t, num_blocks + 4 * HISTOGRAMS_PER_BATCH); + const size_t expected_num_clusters = CLUSTERS_PER_BATCH * + (num_blocks + HISTOGRAMS_PER_BATCH - 1) / HISTOGRAMS_PER_BATCH; + size_t all_histograms_size = 0; + size_t all_histograms_capacity = expected_num_clusters; + HistogramType* all_histograms = + BROTLI_ALLOC(m, HistogramType, all_histograms_capacity); + size_t cluster_size_size = 0; + size_t cluster_size_capacity = expected_num_clusters; + uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, cluster_size_capacity); + size_t num_clusters = 0; + HistogramType* histograms = BROTLI_ALLOC(m, HistogramType, + BROTLI_MIN(size_t, num_blocks, HISTOGRAMS_PER_BATCH)); + size_t max_num_pairs = + HISTOGRAMS_PER_BATCH * HISTOGRAMS_PER_BATCH / 2; + size_t pairs_capacity = max_num_pairs + 1; + HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity); + size_t pos = 0; + uint32_t* clusters; + size_t num_final_clusters; + static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; + uint32_t* new_index; + size_t i; + uint32_t* BROTLI_RESTRICT const sizes = u32 + 0 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const new_clusters = u32 + 1 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const symbols = u32 + 2 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const remap = u32 + 3 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const block_lengths = + u32 + 4 * HISTOGRAMS_PER_BATCH; + /* TODO(eustas): move to arena? */ + HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 2); + + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histogram_symbols) || + BROTLI_IS_NULL(u32) || BROTLI_IS_NULL(all_histograms) || + BROTLI_IS_NULL(cluster_size) || BROTLI_IS_NULL(histograms) || + BROTLI_IS_NULL(pairs) || BROTLI_IS_NULL(tmp)) { + return; + } + + memset(u32, 0, (num_blocks + 4 * HISTOGRAMS_PER_BATCH) * sizeof(uint32_t)); + + /* Calculate block lengths (convert repeating values -> series length). */ + { + size_t block_idx = 0; + for (i = 0; i < length; ++i) { + BROTLI_DCHECK(block_idx < num_blocks); + ++block_lengths[block_idx]; + if (i + 1 == length || block_ids[i] != block_ids[i + 1]) { + ++block_idx; + } + } + BROTLI_DCHECK(block_idx == num_blocks); + } + + /* Pre-cluster blocks (cluster batches). */ + for (i = 0; i < num_blocks; i += HISTOGRAMS_PER_BATCH) { + const size_t num_to_combine = + BROTLI_MIN(size_t, num_blocks - i, HISTOGRAMS_PER_BATCH); + size_t num_new_clusters; + size_t j; + for (j = 0; j < num_to_combine; ++j) { + size_t k; + size_t block_length = block_lengths[i + j]; + FN(HistogramClear)(&histograms[j]); + for (k = 0; k < block_length; ++k) { + FN(HistogramAdd)(&histograms[j], data[pos++]); + } + histograms[j].bit_cost_ = FN(BrotliPopulationCost)(&histograms[j]); + new_clusters[j] = (uint32_t)j; + symbols[j] = (uint32_t)j; + sizes[j] = 1; + } + num_new_clusters = FN(BrotliHistogramCombine)( + histograms, tmp, sizes, symbols, new_clusters, pairs, num_to_combine, + num_to_combine, HISTOGRAMS_PER_BATCH, max_num_pairs); + BROTLI_ENSURE_CAPACITY(m, HistogramType, all_histograms, + all_histograms_capacity, all_histograms_size + num_new_clusters); + BROTLI_ENSURE_CAPACITY(m, uint32_t, cluster_size, + cluster_size_capacity, cluster_size_size + num_new_clusters); + if (BROTLI_IS_OOM(m)) return; + for (j = 0; j < num_new_clusters; ++j) { + all_histograms[all_histograms_size++] = histograms[new_clusters[j]]; + cluster_size[cluster_size_size++] = sizes[new_clusters[j]]; + remap[new_clusters[j]] = (uint32_t)j; + } + for (j = 0; j < num_to_combine; ++j) { + histogram_symbols[i + j] = (uint32_t)num_clusters + remap[symbols[j]]; + } + num_clusters += num_new_clusters; + BROTLI_DCHECK(num_clusters == cluster_size_size); + BROTLI_DCHECK(num_clusters == all_histograms_size); + } + BROTLI_FREE(m, histograms); + + /* Final clustering. */ + max_num_pairs = + BROTLI_MIN(size_t, 64 * num_clusters, (num_clusters / 2) * num_clusters); + if (pairs_capacity < max_num_pairs + 1) { + BROTLI_FREE(m, pairs); + pairs = BROTLI_ALLOC(m, HistogramPair, max_num_pairs + 1); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(pairs)) return; + } + clusters = BROTLI_ALLOC(m, uint32_t, num_clusters); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(clusters)) return; + for (i = 0; i < num_clusters; ++i) { + clusters[i] = (uint32_t)i; + } + num_final_clusters = FN(BrotliHistogramCombine)( + all_histograms, tmp, cluster_size, histogram_symbols, clusters, pairs, + num_clusters, num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES, + max_num_pairs); + BROTLI_FREE(m, pairs); + BROTLI_FREE(m, cluster_size); + + /* Assign blocks to final histograms. */ + new_index = BROTLI_ALLOC(m, uint32_t, num_clusters); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return; + for (i = 0; i < num_clusters; ++i) new_index[i] = kInvalidIndex; + pos = 0; + { + uint32_t next_index = 0; + for (i = 0; i < num_blocks; ++i) { + size_t j; + uint32_t best_out; + double best_bits; + FN(HistogramClear)(tmp); + for (j = 0; j < block_lengths[i]; ++j) { + FN(HistogramAdd)(tmp, data[pos++]); + } + /* Among equally good histograms prefer last used. */ + /* TODO(eustas): should we give a block-switch discount here? */ + best_out = (i == 0) ? histogram_symbols[0] : histogram_symbols[i - 1]; + best_bits = FN(BrotliHistogramBitCostDistance)( + tmp, &all_histograms[best_out], tmp + 1); + for (j = 0; j < num_final_clusters; ++j) { + const double cur_bits = FN(BrotliHistogramBitCostDistance)( + tmp, &all_histograms[clusters[j]], tmp + 1); + if (cur_bits < best_bits) { + best_bits = cur_bits; + best_out = clusters[j]; + } + } + histogram_symbols[i] = best_out; + if (new_index[best_out] == kInvalidIndex) { + new_index[best_out] = next_index++; + } + } + } + BROTLI_FREE(m, tmp); + BROTLI_FREE(m, clusters); + BROTLI_FREE(m, all_histograms); + BROTLI_ENSURE_CAPACITY( + m, uint8_t, split->types, split->types_alloc_size, num_blocks); + BROTLI_ENSURE_CAPACITY( + m, uint32_t, split->lengths, split->lengths_alloc_size, num_blocks); + if (BROTLI_IS_OOM(m)) return; + + /* Rewrite final assignment to block-split. There might be less blocks + * than |num_blocks| due to clustering. */ + { + uint32_t cur_length = 0; + size_t block_idx = 0; + uint8_t max_type = 0; + for (i = 0; i < num_blocks; ++i) { + cur_length += block_lengths[i]; + if (i + 1 == num_blocks || + histogram_symbols[i] != histogram_symbols[i + 1]) { + const uint8_t id = (uint8_t)new_index[histogram_symbols[i]]; + split->types[block_idx] = id; + split->lengths[block_idx] = cur_length; + max_type = BROTLI_MAX(uint8_t, max_type, id); + cur_length = 0; + ++block_idx; + } + } + split->num_blocks = block_idx; + split->num_types = (size_t)max_type + 1; + } + BROTLI_FREE(m, new_index); + BROTLI_FREE(m, u32); + BROTLI_FREE(m, histogram_symbols); +} + +/* Create BlockSplit (partitioning) given the limits, estimates and "effort" + * parameters. + * + * NB: max_histograms is often less than number of histograms allowed by format; + * this is done intentionally, to save some "space" for context-aware + * clustering (here entropy is estimated for context-free symbols). */ +static void FN(SplitByteVector)(MemoryManager* m, + const DataType* data, const size_t length, + const size_t symbols_per_histogram, + const size_t max_histograms, + const size_t sampling_stride_length, + const double block_switch_cost, + const BrotliEncoderParams* params, + BlockSplit* split) { + const size_t data_size = FN(HistogramDataSize)(); + HistogramType* histograms; + HistogramType* tmp; + /* Calculate number of histograms; initial estimate is one histogram per + * specified amount of symbols; however, this value is capped. */ + size_t num_histograms = length / symbols_per_histogram + 1; + if (num_histograms > max_histograms) { + num_histograms = max_histograms; + } + + /* Corner case: no input. */ + if (length == 0) { + split->num_types = 1; + return; + } + + if (length < kMinLengthForBlockSplitting) { + BROTLI_ENSURE_CAPACITY(m, uint8_t, + split->types, split->types_alloc_size, split->num_blocks + 1); + BROTLI_ENSURE_CAPACITY(m, uint32_t, + split->lengths, split->lengths_alloc_size, split->num_blocks + 1); + if (BROTLI_IS_OOM(m)) return; + split->num_types = 1; + split->types[split->num_blocks] = 0; + split->lengths[split->num_blocks] = (uint32_t)length; + split->num_blocks++; + return; + } + histograms = BROTLI_ALLOC(m, HistogramType, num_histograms + 1); + tmp = histograms + num_histograms; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histograms)) return; + /* Find good entropy codes. */ + FN(InitialEntropyCodes)(data, length, + sampling_stride_length, + num_histograms, histograms); + FN(RefineEntropyCodes)(data, length, + sampling_stride_length, + num_histograms, histograms, tmp); + { + /* Find a good path through literals with the good entropy codes. */ + uint8_t* block_ids = BROTLI_ALLOC(m, uint8_t, length); + size_t num_blocks = 0; + const size_t bitmaplen = (num_histograms + 7) >> 3; + double* insert_cost = BROTLI_ALLOC(m, double, data_size * num_histograms); + double* cost = BROTLI_ALLOC(m, double, num_histograms); + uint8_t* switch_signal = BROTLI_ALLOC(m, uint8_t, length * bitmaplen); + uint16_t* new_id = BROTLI_ALLOC(m, uint16_t, num_histograms); + const size_t iters = params->quality < HQ_ZOPFLIFICATION_QUALITY ? 3 : 10; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(block_ids) || + BROTLI_IS_NULL(insert_cost) || BROTLI_IS_NULL(cost) || + BROTLI_IS_NULL(switch_signal) || BROTLI_IS_NULL(new_id)) { + return; + } + for (i = 0; i < iters; ++i) { + num_blocks = FN(FindBlocks)(data, length, + block_switch_cost, + num_histograms, histograms, + insert_cost, cost, switch_signal, + block_ids); + num_histograms = FN(RemapBlockIds)(block_ids, length, + new_id, num_histograms); + FN(BuildBlockHistograms)(data, length, block_ids, + num_histograms, histograms); + } + BROTLI_FREE(m, insert_cost); + BROTLI_FREE(m, cost); + BROTLI_FREE(m, switch_signal); + BROTLI_FREE(m, new_id); + BROTLI_FREE(m, histograms); + FN(ClusterBlocks)(m, data, length, num_blocks, block_ids, split); + if (BROTLI_IS_OOM(m)) return; + BROTLI_FREE(m, block_ids); + } +} + +#undef HistogramType +#undef FN + +#define FN(X) X ## Distance +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, DataType */ + +#define HistogramType FN(Histogram) + +static void FN(InitialEntropyCodes)(const DataType* data, size_t length, + size_t stride, + size_t num_histograms, + HistogramType* histograms) { + uint32_t seed = 7; + size_t block_length = length / num_histograms; + size_t i; + FN(ClearHistograms)(histograms, num_histograms); + for (i = 0; i < num_histograms; ++i) { + size_t pos = length * i / num_histograms; + if (i != 0) { + pos += MyRand(&seed) % block_length; + } + if (pos + stride >= length) { + pos = length - stride - 1; + } + FN(HistogramAddVector)(&histograms[i], data + pos, stride); + } +} + +static void FN(RandomSample)(uint32_t* seed, + const DataType* data, + size_t length, + size_t stride, + HistogramType* sample) { + size_t pos = 0; + if (stride >= length) { + stride = length; + } else { + pos = MyRand(seed) % (length - stride + 1); + } + FN(HistogramAddVector)(sample, data + pos, stride); +} + +static void FN(RefineEntropyCodes)(const DataType* data, size_t length, + size_t stride, + size_t num_histograms, + HistogramType* histograms, + HistogramType* tmp) { + size_t iters = + kIterMulForRefining * length / stride + kMinItersForRefining; + uint32_t seed = 7; + size_t iter; + iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms; + for (iter = 0; iter < iters; ++iter) { + FN(HistogramClear)(tmp); + FN(RandomSample)(&seed, data, length, stride, tmp); + FN(HistogramAddHistogram)(&histograms[iter % num_histograms], tmp); + } +} + +/* Assigns a block id from the range [0, num_histograms) to each data element + in data[0..length) and fills in block_id[0..length) with the assigned values. + Returns the number of blocks, i.e. one plus the number of block switches. */ +static size_t FN(FindBlocks)(const DataType* data, const size_t length, + const double block_switch_bitcost, + const size_t num_histograms, + const HistogramType* histograms, + double* insert_cost, + double* cost, + uint8_t* switch_signal, + uint8_t* block_id) { + const size_t alphabet_size = FN(HistogramDataSize)(); + const size_t bitmap_len = (num_histograms + 7) >> 3; + size_t num_blocks = 1; + size_t byte_ix; + size_t i; + size_t j; + BROTLI_DCHECK(num_histograms <= 256); + + /* Trivial case: single historgram -> single block type. */ + if (num_histograms <= 1) { + for (i = 0; i < length; ++i) { + block_id[i] = 0; + } + return 1; + } + + /* Fill bitcost for each symbol of all histograms. + * Non-existing symbol cost: 2 + log2(total_count). + * Regular symbol cost: -log2(symbol_count / total_count). */ + memset(insert_cost, 0, + sizeof(insert_cost[0]) * alphabet_size * num_histograms); + for (i = 0; i < num_histograms; ++i) { + insert_cost[i] = FastLog2((uint32_t)histograms[i].total_count_); + } + for (i = alphabet_size; i != 0;) { + /* Reverse order to use the 0-th row as a temporary storage. */ + --i; + for (j = 0; j < num_histograms; ++j) { + insert_cost[i * num_histograms + j] = + insert_cost[j] - BitCost(histograms[j].data_[i]); + } + } + + /* After each iteration of this loop, cost[k] will contain the difference + between the minimum cost of arriving at the current byte position using + entropy code k, and the minimum cost of arriving at the current byte + position. This difference is capped at the block switch cost, and if it + reaches block switch cost, it means that when we trace back from the last + position, we need to switch here. */ + memset(cost, 0, sizeof(cost[0]) * num_histograms); + memset(switch_signal, 0, sizeof(switch_signal[0]) * length * bitmap_len); + for (byte_ix = 0; byte_ix < length; ++byte_ix) { + size_t ix = byte_ix * bitmap_len; + size_t symbol = data[byte_ix]; + size_t insert_cost_ix = symbol * num_histograms; + double min_cost = 1e99; + double block_switch_cost = block_switch_bitcost; + size_t k; + for (k = 0; k < num_histograms; ++k) { + /* We are coding the symbol with entropy code k. */ + cost[k] += insert_cost[insert_cost_ix + k]; + if (cost[k] < min_cost) { + min_cost = cost[k]; + block_id[byte_ix] = (uint8_t)k; + } + } + /* More blocks for the beginning. */ + if (byte_ix < 2000) { + block_switch_cost *= 0.77 + 0.07 * (double)byte_ix / 2000; + } + for (k = 0; k < num_histograms; ++k) { + cost[k] -= min_cost; + if (cost[k] >= block_switch_cost) { + const uint8_t mask = (uint8_t)(1u << (k & 7)); + cost[k] = block_switch_cost; + BROTLI_DCHECK((k >> 3) < bitmap_len); + switch_signal[ix + (k >> 3)] |= mask; + } + } + } + + byte_ix = length - 1; + { /* Trace back from the last position and switch at the marked places. */ + size_t ix = byte_ix * bitmap_len; + uint8_t cur_id = block_id[byte_ix]; + while (byte_ix > 0) { + const uint8_t mask = (uint8_t)(1u << (cur_id & 7)); + BROTLI_DCHECK(((size_t)cur_id >> 3) < bitmap_len); + --byte_ix; + ix -= bitmap_len; + if (switch_signal[ix + (cur_id >> 3)] & mask) { + if (cur_id != block_id[byte_ix]) { + cur_id = block_id[byte_ix]; + ++num_blocks; + } + } + block_id[byte_ix] = cur_id; + } + } + return num_blocks; +} + +static size_t FN(RemapBlockIds)(uint8_t* block_ids, const size_t length, + uint16_t* new_id, const size_t num_histograms) { + static const uint16_t kInvalidId = 256; + uint16_t next_id = 0; + size_t i; + for (i = 0; i < num_histograms; ++i) { + new_id[i] = kInvalidId; + } + for (i = 0; i < length; ++i) { + BROTLI_DCHECK(block_ids[i] < num_histograms); + if (new_id[block_ids[i]] == kInvalidId) { + new_id[block_ids[i]] = next_id++; + } + } + for (i = 0; i < length; ++i) { + block_ids[i] = (uint8_t)new_id[block_ids[i]]; + BROTLI_DCHECK(block_ids[i] < num_histograms); + } + BROTLI_DCHECK(next_id <= num_histograms); + return next_id; +} + +static void FN(BuildBlockHistograms)(const DataType* data, const size_t length, + const uint8_t* block_ids, + const size_t num_histograms, + HistogramType* histograms) { + size_t i; + FN(ClearHistograms)(histograms, num_histograms); + for (i = 0; i < length; ++i) { + FN(HistogramAdd)(&histograms[block_ids[i]], data[i]); + } +} + +/* Given the initial partitioning build partitioning with limited number + * of histograms (and block types). */ +static void FN(ClusterBlocks)(MemoryManager* m, + const DataType* data, const size_t length, + const size_t num_blocks, + uint8_t* block_ids, + BlockSplit* split) { + uint32_t* histogram_symbols = BROTLI_ALLOC(m, uint32_t, num_blocks); + uint32_t* u32 = + BROTLI_ALLOC(m, uint32_t, num_blocks + 4 * HISTOGRAMS_PER_BATCH); + const size_t expected_num_clusters = CLUSTERS_PER_BATCH * + (num_blocks + HISTOGRAMS_PER_BATCH - 1) / HISTOGRAMS_PER_BATCH; + size_t all_histograms_size = 0; + size_t all_histograms_capacity = expected_num_clusters; + HistogramType* all_histograms = + BROTLI_ALLOC(m, HistogramType, all_histograms_capacity); + size_t cluster_size_size = 0; + size_t cluster_size_capacity = expected_num_clusters; + uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, cluster_size_capacity); + size_t num_clusters = 0; + HistogramType* histograms = BROTLI_ALLOC(m, HistogramType, + BROTLI_MIN(size_t, num_blocks, HISTOGRAMS_PER_BATCH)); + size_t max_num_pairs = + HISTOGRAMS_PER_BATCH * HISTOGRAMS_PER_BATCH / 2; + size_t pairs_capacity = max_num_pairs + 1; + HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity); + size_t pos = 0; + uint32_t* clusters; + size_t num_final_clusters; + static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; + uint32_t* new_index; + size_t i; + uint32_t* BROTLI_RESTRICT const sizes = u32 + 0 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const new_clusters = u32 + 1 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const symbols = u32 + 2 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const remap = u32 + 3 * HISTOGRAMS_PER_BATCH; + uint32_t* BROTLI_RESTRICT const block_lengths = + u32 + 4 * HISTOGRAMS_PER_BATCH; + /* TODO(eustas): move to arena? */ + HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 2); + + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histogram_symbols) || + BROTLI_IS_NULL(u32) || BROTLI_IS_NULL(all_histograms) || + BROTLI_IS_NULL(cluster_size) || BROTLI_IS_NULL(histograms) || + BROTLI_IS_NULL(pairs) || BROTLI_IS_NULL(tmp)) { + return; + } + + memset(u32, 0, (num_blocks + 4 * HISTOGRAMS_PER_BATCH) * sizeof(uint32_t)); + + /* Calculate block lengths (convert repeating values -> series length). */ + { + size_t block_idx = 0; + for (i = 0; i < length; ++i) { + BROTLI_DCHECK(block_idx < num_blocks); + ++block_lengths[block_idx]; + if (i + 1 == length || block_ids[i] != block_ids[i + 1]) { + ++block_idx; + } + } + BROTLI_DCHECK(block_idx == num_blocks); + } + + /* Pre-cluster blocks (cluster batches). */ + for (i = 0; i < num_blocks; i += HISTOGRAMS_PER_BATCH) { + const size_t num_to_combine = + BROTLI_MIN(size_t, num_blocks - i, HISTOGRAMS_PER_BATCH); + size_t num_new_clusters; + size_t j; + for (j = 0; j < num_to_combine; ++j) { + size_t k; + size_t block_length = block_lengths[i + j]; + FN(HistogramClear)(&histograms[j]); + for (k = 0; k < block_length; ++k) { + FN(HistogramAdd)(&histograms[j], data[pos++]); + } + histograms[j].bit_cost_ = FN(BrotliPopulationCost)(&histograms[j]); + new_clusters[j] = (uint32_t)j; + symbols[j] = (uint32_t)j; + sizes[j] = 1; + } + num_new_clusters = FN(BrotliHistogramCombine)( + histograms, tmp, sizes, symbols, new_clusters, pairs, num_to_combine, + num_to_combine, HISTOGRAMS_PER_BATCH, max_num_pairs); + BROTLI_ENSURE_CAPACITY(m, HistogramType, all_histograms, + all_histograms_capacity, all_histograms_size + num_new_clusters); + BROTLI_ENSURE_CAPACITY(m, uint32_t, cluster_size, + cluster_size_capacity, cluster_size_size + num_new_clusters); + if (BROTLI_IS_OOM(m)) return; + for (j = 0; j < num_new_clusters; ++j) { + all_histograms[all_histograms_size++] = histograms[new_clusters[j]]; + cluster_size[cluster_size_size++] = sizes[new_clusters[j]]; + remap[new_clusters[j]] = (uint32_t)j; + } + for (j = 0; j < num_to_combine; ++j) { + histogram_symbols[i + j] = (uint32_t)num_clusters + remap[symbols[j]]; + } + num_clusters += num_new_clusters; + BROTLI_DCHECK(num_clusters == cluster_size_size); + BROTLI_DCHECK(num_clusters == all_histograms_size); + } + BROTLI_FREE(m, histograms); + + /* Final clustering. */ + max_num_pairs = + BROTLI_MIN(size_t, 64 * num_clusters, (num_clusters / 2) * num_clusters); + if (pairs_capacity < max_num_pairs + 1) { + BROTLI_FREE(m, pairs); + pairs = BROTLI_ALLOC(m, HistogramPair, max_num_pairs + 1); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(pairs)) return; + } + clusters = BROTLI_ALLOC(m, uint32_t, num_clusters); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(clusters)) return; + for (i = 0; i < num_clusters; ++i) { + clusters[i] = (uint32_t)i; + } + num_final_clusters = FN(BrotliHistogramCombine)( + all_histograms, tmp, cluster_size, histogram_symbols, clusters, pairs, + num_clusters, num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES, + max_num_pairs); + BROTLI_FREE(m, pairs); + BROTLI_FREE(m, cluster_size); + + /* Assign blocks to final histograms. */ + new_index = BROTLI_ALLOC(m, uint32_t, num_clusters); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return; + for (i = 0; i < num_clusters; ++i) new_index[i] = kInvalidIndex; + pos = 0; + { + uint32_t next_index = 0; + for (i = 0; i < num_blocks; ++i) { + size_t j; + uint32_t best_out; + double best_bits; + FN(HistogramClear)(tmp); + for (j = 0; j < block_lengths[i]; ++j) { + FN(HistogramAdd)(tmp, data[pos++]); + } + /* Among equally good histograms prefer last used. */ + /* TODO(eustas): should we give a block-switch discount here? */ + best_out = (i == 0) ? histogram_symbols[0] : histogram_symbols[i - 1]; + best_bits = FN(BrotliHistogramBitCostDistance)( + tmp, &all_histograms[best_out], tmp + 1); + for (j = 0; j < num_final_clusters; ++j) { + const double cur_bits = FN(BrotliHistogramBitCostDistance)( + tmp, &all_histograms[clusters[j]], tmp + 1); + if (cur_bits < best_bits) { + best_bits = cur_bits; + best_out = clusters[j]; + } + } + histogram_symbols[i] = best_out; + if (new_index[best_out] == kInvalidIndex) { + new_index[best_out] = next_index++; + } + } + } + BROTLI_FREE(m, tmp); + BROTLI_FREE(m, clusters); + BROTLI_FREE(m, all_histograms); + BROTLI_ENSURE_CAPACITY( + m, uint8_t, split->types, split->types_alloc_size, num_blocks); + BROTLI_ENSURE_CAPACITY( + m, uint32_t, split->lengths, split->lengths_alloc_size, num_blocks); + if (BROTLI_IS_OOM(m)) return; + + /* Rewrite final assignment to block-split. There might be less blocks + * than |num_blocks| due to clustering. */ + { + uint32_t cur_length = 0; + size_t block_idx = 0; + uint8_t max_type = 0; + for (i = 0; i < num_blocks; ++i) { + cur_length += block_lengths[i]; + if (i + 1 == num_blocks || + histogram_symbols[i] != histogram_symbols[i + 1]) { + const uint8_t id = (uint8_t)new_index[histogram_symbols[i]]; + split->types[block_idx] = id; + split->lengths[block_idx] = cur_length; + max_type = BROTLI_MAX(uint8_t, max_type, id); + cur_length = 0; + ++block_idx; + } + } + split->num_blocks = block_idx; + split->num_types = (size_t)max_type + 1; + } + BROTLI_FREE(m, new_index); + BROTLI_FREE(m, u32); + BROTLI_FREE(m, histogram_symbols); +} + +/* Create BlockSplit (partitioning) given the limits, estimates and "effort" + * parameters. + * + * NB: max_histograms is often less than number of histograms allowed by format; + * this is done intentionally, to save some "space" for context-aware + * clustering (here entropy is estimated for context-free symbols). */ +static void FN(SplitByteVector)(MemoryManager* m, + const DataType* data, const size_t length, + const size_t symbols_per_histogram, + const size_t max_histograms, + const size_t sampling_stride_length, + const double block_switch_cost, + const BrotliEncoderParams* params, + BlockSplit* split) { + const size_t data_size = FN(HistogramDataSize)(); + HistogramType* histograms; + HistogramType* tmp; + /* Calculate number of histograms; initial estimate is one histogram per + * specified amount of symbols; however, this value is capped. */ + size_t num_histograms = length / symbols_per_histogram + 1; + if (num_histograms > max_histograms) { + num_histograms = max_histograms; + } + + /* Corner case: no input. */ + if (length == 0) { + split->num_types = 1; + return; + } + + if (length < kMinLengthForBlockSplitting) { + BROTLI_ENSURE_CAPACITY(m, uint8_t, + split->types, split->types_alloc_size, split->num_blocks + 1); + BROTLI_ENSURE_CAPACITY(m, uint32_t, + split->lengths, split->lengths_alloc_size, split->num_blocks + 1); + if (BROTLI_IS_OOM(m)) return; + split->num_types = 1; + split->types[split->num_blocks] = 0; + split->lengths[split->num_blocks] = (uint32_t)length; + split->num_blocks++; + return; + } + histograms = BROTLI_ALLOC(m, HistogramType, num_histograms + 1); + tmp = histograms + num_histograms; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histograms)) return; + /* Find good entropy codes. */ + FN(InitialEntropyCodes)(data, length, + sampling_stride_length, + num_histograms, histograms); + FN(RefineEntropyCodes)(data, length, + sampling_stride_length, + num_histograms, histograms, tmp); + { + /* Find a good path through literals with the good entropy codes. */ + uint8_t* block_ids = BROTLI_ALLOC(m, uint8_t, length); + size_t num_blocks = 0; + const size_t bitmaplen = (num_histograms + 7) >> 3; + double* insert_cost = BROTLI_ALLOC(m, double, data_size * num_histograms); + double* cost = BROTLI_ALLOC(m, double, num_histograms); + uint8_t* switch_signal = BROTLI_ALLOC(m, uint8_t, length * bitmaplen); + uint16_t* new_id = BROTLI_ALLOC(m, uint16_t, num_histograms); + const size_t iters = params->quality < HQ_ZOPFLIFICATION_QUALITY ? 3 : 10; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(block_ids) || + BROTLI_IS_NULL(insert_cost) || BROTLI_IS_NULL(cost) || + BROTLI_IS_NULL(switch_signal) || BROTLI_IS_NULL(new_id)) { + return; + } + for (i = 0; i < iters; ++i) { + num_blocks = FN(FindBlocks)(data, length, + block_switch_cost, + num_histograms, histograms, + insert_cost, cost, switch_signal, + block_ids); + num_histograms = FN(RemapBlockIds)(block_ids, length, + new_id, num_histograms); + FN(BuildBlockHistograms)(data, length, block_ids, + num_histograms, histograms); + } + BROTLI_FREE(m, insert_cost); + BROTLI_FREE(m, cost); + BROTLI_FREE(m, switch_signal); + BROTLI_FREE(m, new_id); + BROTLI_FREE(m, histograms); + FN(ClusterBlocks)(m, data, length, num_blocks, block_ids, split); + if (BROTLI_IS_OOM(m)) return; + BROTLI_FREE(m, block_ids); + } +} + +#undef HistogramType +#undef DataType +#undef FN + +void duckdb_brotli::BrotliInitBlockSplit(BlockSplit* self) { + self->num_types = 0; + self->num_blocks = 0; + self->types = 0; + self->lengths = 0; + self->types_alloc_size = 0; + self->lengths_alloc_size = 0; +} + +void duckdb_brotli::BrotliDestroyBlockSplit(MemoryManager* m, BlockSplit* self) { + BROTLI_FREE(m, self->types); + BROTLI_FREE(m, self->lengths); +} + +/* Extracts literals, command distance and prefix codes, then applies + * SplitByteVector to create partitioning. */ +void duckdb_brotli::BrotliSplitBlock(MemoryManager* m, + const Command* cmds, + const size_t num_commands, + const uint8_t* data, + const size_t pos, + const size_t mask, + const BrotliEncoderParams* params, + BlockSplit* literal_split, + BlockSplit* insert_and_copy_split, + BlockSplit* dist_split) { + { + size_t literals_count = CountLiterals(cmds, num_commands); + uint8_t* literals = BROTLI_ALLOC(m, uint8_t, literals_count); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literals)) return; + /* Create a continuous array of literals. */ + CopyLiteralsToByteArray(cmds, num_commands, data, pos, mask, literals); + /* Create the block split on the array of literals. + * Literal histograms can have alphabet size up to 256. + * Though, to accomodate context modeling, less than half of maximum size + * is allowed. */ + SplitByteVectorLiteral( + m, literals, literals_count, + kSymbolsPerLiteralHistogram, kMaxLiteralHistograms, + kLiteralStrideLength, kLiteralBlockSwitchCost, params, + literal_split); + if (BROTLI_IS_OOM(m)) return; + BROTLI_FREE(m, literals); + /* NB: this might be a good place for injecting extra splitting without + * increasing encoder complexity; however, output parition would be less + * optimal than one produced with forced splitting inside + * SplitByteVector (FindBlocks / ClusterBlocks). */ + } + + { + /* Compute prefix codes for commands. */ + uint16_t* insert_and_copy_codes = BROTLI_ALLOC(m, uint16_t, num_commands); + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(insert_and_copy_codes)) return; + for (i = 0; i < num_commands; ++i) { + insert_and_copy_codes[i] = cmds[i].cmd_prefix_; + } + /* Create the block split on the array of command prefixes. */ + SplitByteVectorCommand( + m, insert_and_copy_codes, num_commands, + kSymbolsPerCommandHistogram, kMaxCommandHistograms, + kCommandStrideLength, kCommandBlockSwitchCost, params, + insert_and_copy_split); + if (BROTLI_IS_OOM(m)) return; + /* TODO(eustas): reuse for distances? */ + BROTLI_FREE(m, insert_and_copy_codes); + } + + { + /* Create a continuous array of distance prefixes. */ + uint16_t* distance_prefixes = BROTLI_ALLOC(m, uint16_t, num_commands); + size_t j = 0; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(distance_prefixes)) return; + for (i = 0; i < num_commands; ++i) { + const Command* cmd = &cmds[i]; + if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) { + distance_prefixes[j++] = cmd->dist_prefix_ & 0x3FF; + } + } + /* Create the block split on the array of distance prefixes. */ + SplitByteVectorDistance( + m, distance_prefixes, j, + kSymbolsPerDistanceHistogram, kMaxCommandHistograms, + kDistanceStrideLength, kDistanceBlockSwitchCost, params, + dist_split); + if (BROTLI_IS_OOM(m)) return; + BROTLI_FREE(m, distance_prefixes); + } +} + +#if defined(BROTLI_TEST) +size_t CountLiteralsForTest(const Command*, const size_t); +size_t CountLiteralsForTest(const Command* cmds, const size_t num_commands) { + return CountLiterals(cmds, num_commands); +} + +void CopyLiteralsToByteArrayForTest(const Command*, + const size_t, const uint8_t*, const size_t, const size_t, uint8_t*); +void CopyLiteralsToByteArrayForTest(const Command* cmds, + const size_t num_commands, const uint8_t* data, const size_t offset, + const size_t mask, uint8_t* literals) { + CopyLiteralsToByteArray(cmds, num_commands, data, offset, mask, literals); +} +#endif + + diff --git a/third_party/brotli/enc/block_splitter.h b/third_party/brotli/enc/block_splitter.h new file mode 100644 index 00000000000..c5e438e3225 --- /dev/null +++ b/third_party/brotli/enc/block_splitter.h @@ -0,0 +1,48 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Block split point selection utilities. */ + +#ifndef BROTLI_ENC_BLOCK_SPLITTER_H_ +#define BROTLI_ENC_BLOCK_SPLITTER_H_ + +#include + +#include "../common/brotli_platform.h" +#include "command.h" +#include "memory.h" +#include "quality.h" + +namespace duckdb_brotli { + +typedef struct BlockSplit { + size_t num_types; /* Amount of distinct types */ + size_t num_blocks; /* Amount of values in types and length */ + uint8_t* types; + uint32_t* lengths; + + size_t types_alloc_size; + size_t lengths_alloc_size; +} BlockSplit; + +BROTLI_INTERNAL void BrotliInitBlockSplit(BlockSplit* self); +BROTLI_INTERNAL void BrotliDestroyBlockSplit(MemoryManager* m, + BlockSplit* self); + +BROTLI_INTERNAL void BrotliSplitBlock(MemoryManager* m, + const Command* cmds, + const size_t num_commands, + const uint8_t* data, + const size_t offset, + const size_t mask, + const BrotliEncoderParams* params, + BlockSplit* literal_split, + BlockSplit* insert_and_copy_split, + BlockSplit* dist_split); + +} + +#endif /* BROTLI_ENC_BLOCK_SPLITTER_H_ */ diff --git a/third_party/brotli/enc/brotli_bit_stream.cpp b/third_party/brotli/enc/brotli_bit_stream.cpp new file mode 100644 index 00000000000..81256e61027 --- /dev/null +++ b/third_party/brotli/enc/brotli_bit_stream.cpp @@ -0,0 +1,1431 @@ +/* Copyright 2014 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Brotli bit stream functions to support the low level format. There are no + compression algorithms here, just the right ordering of bits to match the + specs. */ + +#include "brotli_bit_stream.h" + +#include /* memcpy, memset */ + +#include + +#include "../common/brotli_constants.h" +#include "../common/context.h" +#include "../common/brotli_platform.h" +#include "entropy_encode.h" +#include "entropy_encode_static.h" +#include "fast_log.h" +#include "histogram.h" +#include "memory.h" +#include "write_bits.h" + +using namespace duckdb_brotli; + +#define MAX_HUFFMAN_TREE_SIZE (2 * BROTLI_NUM_COMMAND_SYMBOLS + 1) +/* The maximum size of Huffman dictionary for distances assuming that + NPOSTFIX = 0 and NDIRECT = 0. */ +#define MAX_SIMPLE_DISTANCE_ALPHABET_SIZE \ + BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_LARGE_MAX_DISTANCE_BITS) +/* MAX_SIMPLE_DISTANCE_ALPHABET_SIZE == 140 */ + +static BROTLI_INLINE uint32_t BlockLengthPrefixCode(uint32_t len) { + uint32_t code = (len >= 177) ? (len >= 753 ? 20 : 14) : (len >= 41 ? 7 : 0); + while (code < (BROTLI_NUM_BLOCK_LEN_SYMBOLS - 1) && + len >= _kBrotliPrefixCodeRanges[code + 1].offset) ++code; + return code; +} + +static BROTLI_INLINE void GetBlockLengthPrefixCode(uint32_t len, size_t* code, + uint32_t* n_extra, uint32_t* extra) { + *code = BlockLengthPrefixCode(len); + *n_extra = _kBrotliPrefixCodeRanges[*code].nbits; + *extra = len - _kBrotliPrefixCodeRanges[*code].offset; +} + +typedef struct BlockTypeCodeCalculator { + size_t last_type; + size_t second_last_type; +} BlockTypeCodeCalculator; + +static void InitBlockTypeCodeCalculator(BlockTypeCodeCalculator* self) { + self->last_type = 1; + self->second_last_type = 0; +} + +static BROTLI_INLINE size_t NextBlockTypeCode( + BlockTypeCodeCalculator* calculator, uint8_t type) { + size_t type_code = (type == calculator->last_type + 1) ? 1u : + (type == calculator->second_last_type) ? 0u : type + 2u; + calculator->second_last_type = calculator->last_type; + calculator->last_type = type; + return type_code; +} + +/* |nibblesbits| represents the 2 bits to encode MNIBBLES (0-3) + REQUIRES: length > 0 + REQUIRES: length <= (1 << 24) */ +static void BrotliEncodeMlen(size_t length, uint64_t* bits, + size_t* numbits, uint64_t* nibblesbits) { + size_t lg = (length == 1) ? 1 : Log2FloorNonZero((uint32_t)(length - 1)) + 1; + size_t mnibbles = (lg < 16 ? 16 : (lg + 3)) / 4; + BROTLI_DCHECK(length > 0); + BROTLI_DCHECK(length <= (1 << 24)); + BROTLI_DCHECK(lg <= 24); + *nibblesbits = mnibbles - 4; + *numbits = mnibbles * 4; + *bits = length - 1; +} + +static BROTLI_INLINE void StoreCommandExtra( + const Command* cmd, size_t* storage_ix, uint8_t* storage) { + uint32_t copylen_code = CommandCopyLenCode(cmd); + uint16_t inscode = GetInsertLengthCode(cmd->insert_len_); + uint16_t copycode = GetCopyLengthCode(copylen_code); + uint32_t insnumextra = GetInsertExtra(inscode); + uint64_t insextraval = cmd->insert_len_ - GetInsertBase(inscode); + uint64_t copyextraval = copylen_code - GetCopyBase(copycode); + uint64_t bits = (copyextraval << insnumextra) | insextraval; + BrotliWriteBits( + insnumextra + GetCopyExtra(copycode), bits, storage_ix, storage); +} + +/* Data structure that stores almost everything that is needed to encode each + block switch command. */ +typedef struct BlockSplitCode { + BlockTypeCodeCalculator type_code_calculator; + uint8_t type_depths[BROTLI_MAX_BLOCK_TYPE_SYMBOLS]; + uint16_t type_bits[BROTLI_MAX_BLOCK_TYPE_SYMBOLS]; + uint8_t length_depths[BROTLI_NUM_BLOCK_LEN_SYMBOLS]; + uint16_t length_bits[BROTLI_NUM_BLOCK_LEN_SYMBOLS]; +} BlockSplitCode; + +/* Stores a number between 0 and 255. */ +static void StoreVarLenUint8(size_t n, size_t* storage_ix, uint8_t* storage) { + if (n == 0) { + BrotliWriteBits(1, 0, storage_ix, storage); + } else { + size_t nbits = Log2FloorNonZero(n); + BrotliWriteBits(1, 1, storage_ix, storage); + BrotliWriteBits(3, nbits, storage_ix, storage); + BrotliWriteBits(nbits, n - ((size_t)1 << nbits), storage_ix, storage); + } +} + +/* Stores the compressed meta-block header. + REQUIRES: length > 0 + REQUIRES: length <= (1 << 24) */ +static void StoreCompressedMetaBlockHeader(BROTLI_BOOL is_final_block, + size_t length, + size_t* storage_ix, + uint8_t* storage) { + uint64_t lenbits; + size_t nlenbits; + uint64_t nibblesbits; + + /* Write ISLAST bit. */ + BrotliWriteBits(1, (uint64_t)is_final_block, storage_ix, storage); + /* Write ISEMPTY bit. */ + if (is_final_block) { + BrotliWriteBits(1, 0, storage_ix, storage); + } + + BrotliEncodeMlen(length, &lenbits, &nlenbits, &nibblesbits); + BrotliWriteBits(2, nibblesbits, storage_ix, storage); + BrotliWriteBits(nlenbits, lenbits, storage_ix, storage); + + if (!is_final_block) { + /* Write ISUNCOMPRESSED bit. */ + BrotliWriteBits(1, 0, storage_ix, storage); + } +} + +/* Stores the uncompressed meta-block header. + REQUIRES: length > 0 + REQUIRES: length <= (1 << 24) */ +static void BrotliStoreUncompressedMetaBlockHeader(size_t length, + size_t* storage_ix, + uint8_t* storage) { + uint64_t lenbits; + size_t nlenbits; + uint64_t nibblesbits; + + /* Write ISLAST bit. + Uncompressed block cannot be the last one, so set to 0. */ + BrotliWriteBits(1, 0, storage_ix, storage); + BrotliEncodeMlen(length, &lenbits, &nlenbits, &nibblesbits); + BrotliWriteBits(2, nibblesbits, storage_ix, storage); + BrotliWriteBits(nlenbits, lenbits, storage_ix, storage); + /* Write ISUNCOMPRESSED bit. */ + BrotliWriteBits(1, 1, storage_ix, storage); +} + +static void BrotliStoreHuffmanTreeOfHuffmanTreeToBitMask( + const int num_codes, const uint8_t* code_length_bitdepth, + size_t* storage_ix, uint8_t* storage) { + static const uint8_t kStorageOrder[BROTLI_CODE_LENGTH_CODES] = { + 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15 + }; + /* The bit lengths of the Huffman code over the code length alphabet + are compressed with the following static Huffman code: + Symbol Code + ------ ---- + 0 00 + 1 1110 + 2 110 + 3 01 + 4 10 + 5 1111 */ + static const uint8_t kHuffmanBitLengthHuffmanCodeSymbols[6] = { + 0, 7, 3, 2, 1, 15 + }; + static const uint8_t kHuffmanBitLengthHuffmanCodeBitLengths[6] = { + 2, 4, 3, 2, 2, 4 + }; + + size_t skip_some = 0; /* skips none. */ + + /* Throw away trailing zeros: */ + size_t codes_to_store = BROTLI_CODE_LENGTH_CODES; + if (num_codes > 1) { + for (; codes_to_store > 0; --codes_to_store) { + if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) { + break; + } + } + } + if (code_length_bitdepth[kStorageOrder[0]] == 0 && + code_length_bitdepth[kStorageOrder[1]] == 0) { + skip_some = 2; /* skips two. */ + if (code_length_bitdepth[kStorageOrder[2]] == 0) { + skip_some = 3; /* skips three. */ + } + } + BrotliWriteBits(2, skip_some, storage_ix, storage); + { + size_t i; + for (i = skip_some; i < codes_to_store; ++i) { + size_t l = code_length_bitdepth[kStorageOrder[i]]; + BrotliWriteBits(kHuffmanBitLengthHuffmanCodeBitLengths[l], + kHuffmanBitLengthHuffmanCodeSymbols[l], storage_ix, storage); + } + } +} + +static void BrotliStoreHuffmanTreeToBitMask( + const size_t huffman_tree_size, const uint8_t* huffman_tree, + const uint8_t* huffman_tree_extra_bits, const uint8_t* code_length_bitdepth, + const uint16_t* code_length_bitdepth_symbols, + size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage) { + size_t i; + for (i = 0; i < huffman_tree_size; ++i) { + size_t ix = huffman_tree[i]; + BrotliWriteBits(code_length_bitdepth[ix], code_length_bitdepth_symbols[ix], + storage_ix, storage); + /* Extra bits */ + switch (ix) { + case BROTLI_REPEAT_PREVIOUS_CODE_LENGTH: + BrotliWriteBits(2, huffman_tree_extra_bits[i], storage_ix, storage); + break; + case BROTLI_REPEAT_ZERO_CODE_LENGTH: + BrotliWriteBits(3, huffman_tree_extra_bits[i], storage_ix, storage); + break; + } + } +} + +static void StoreSimpleHuffmanTree(const uint8_t* depths, + size_t symbols[4], + size_t num_symbols, + size_t max_bits, + size_t* storage_ix, uint8_t* storage) { + /* value of 1 indicates a simple Huffman code */ + BrotliWriteBits(2, 1, storage_ix, storage); + BrotliWriteBits(2, num_symbols - 1, storage_ix, storage); /* NSYM - 1 */ + + { + /* Sort */ + size_t i; + for (i = 0; i < num_symbols; i++) { + size_t j; + for (j = i + 1; j < num_symbols; j++) { + if (depths[symbols[j]] < depths[symbols[i]]) { + BROTLI_SWAP(size_t, symbols, j, i); + } + } + } + } + + if (num_symbols == 2) { + BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); + } else if (num_symbols == 3) { + BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[2], storage_ix, storage); + } else { + BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[2], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[3], storage_ix, storage); + /* tree-select */ + BrotliWriteBits(1, depths[symbols[0]] == 1 ? 1 : 0, storage_ix, storage); + } +} + +/* num = alphabet size + depths = symbol depths */ +void duckdb_brotli::BrotliStoreHuffmanTree(const uint8_t* depths, size_t num, + HuffmanTree* tree, + size_t* storage_ix, uint8_t* storage) { + /* Write the Huffman tree into the brotli-representation. + The command alphabet is the largest, so this allocation will fit all + alphabets. */ + /* TODO(eustas): fix me */ + uint8_t huffman_tree[BROTLI_NUM_COMMAND_SYMBOLS]; + uint8_t huffman_tree_extra_bits[BROTLI_NUM_COMMAND_SYMBOLS]; + size_t huffman_tree_size = 0; + uint8_t code_length_bitdepth[BROTLI_CODE_LENGTH_CODES] = { 0 }; + uint16_t code_length_bitdepth_symbols[BROTLI_CODE_LENGTH_CODES]; + uint32_t huffman_tree_histogram[BROTLI_CODE_LENGTH_CODES] = { 0 }; + size_t i; + int num_codes = 0; + size_t code = 0; + + BROTLI_DCHECK(num <= BROTLI_NUM_COMMAND_SYMBOLS); + + BrotliWriteHuffmanTree(depths, num, &huffman_tree_size, huffman_tree, + huffman_tree_extra_bits); + + /* Calculate the statistics of the Huffman tree in brotli-representation. */ + for (i = 0; i < huffman_tree_size; ++i) { + ++huffman_tree_histogram[huffman_tree[i]]; + } + + for (i = 0; i < BROTLI_CODE_LENGTH_CODES; ++i) { + if (huffman_tree_histogram[i]) { + if (num_codes == 0) { + code = i; + num_codes = 1; + } else if (num_codes == 1) { + num_codes = 2; + break; + } + } + } + + /* Calculate another Huffman tree to use for compressing both the + earlier Huffman tree with. */ + BrotliCreateHuffmanTree(huffman_tree_histogram, BROTLI_CODE_LENGTH_CODES, + 5, tree, code_length_bitdepth); + BrotliConvertBitDepthsToSymbols(code_length_bitdepth, + BROTLI_CODE_LENGTH_CODES, + code_length_bitdepth_symbols); + + /* Now, we have all the data, let's start storing it */ + BrotliStoreHuffmanTreeOfHuffmanTreeToBitMask(num_codes, code_length_bitdepth, + storage_ix, storage); + + if (num_codes == 1) { + code_length_bitdepth[code] = 0; + } + + /* Store the real Huffman tree now. */ + BrotliStoreHuffmanTreeToBitMask(huffman_tree_size, + huffman_tree, + huffman_tree_extra_bits, + code_length_bitdepth, + code_length_bitdepth_symbols, + storage_ix, storage); +} + +/* Builds a Huffman tree from histogram[0:length] into depth[0:length] and + bits[0:length] and stores the encoded tree to the bit stream. */ +static void BuildAndStoreHuffmanTree(const uint32_t* histogram, + const size_t histogram_length, + const size_t alphabet_size, + HuffmanTree* tree, + uint8_t* depth, + uint16_t* bits, + size_t* storage_ix, + uint8_t* storage) { + size_t count = 0; + size_t s4[4] = { 0 }; + size_t i; + size_t max_bits = 0; + for (i = 0; i < histogram_length; i++) { + if (histogram[i]) { + if (count < 4) { + s4[count] = i; + } else if (count > 4) { + break; + } + count++; + } + } + + { + size_t max_bits_counter = alphabet_size - 1; + while (max_bits_counter) { + max_bits_counter >>= 1; + ++max_bits; + } + } + + if (count <= 1) { + BrotliWriteBits(4, 1, storage_ix, storage); + BrotliWriteBits(max_bits, s4[0], storage_ix, storage); + depth[s4[0]] = 0; + bits[s4[0]] = 0; + return; + } + + memset(depth, 0, histogram_length * sizeof(depth[0])); + BrotliCreateHuffmanTree(histogram, histogram_length, 15, tree, depth); + BrotliConvertBitDepthsToSymbols(depth, histogram_length, bits); + + if (count <= 4) { + StoreSimpleHuffmanTree(depth, s4, count, max_bits, storage_ix, storage); + } else { + BrotliStoreHuffmanTree(depth, histogram_length, tree, storage_ix, storage); + } +} + +static BROTLI_INLINE BROTLI_BOOL SortHuffmanTree( + const HuffmanTree* v0, const HuffmanTree* v1) { + return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_); +} + +void duckdb_brotli::BrotliBuildAndStoreHuffmanTreeFast(HuffmanTree* tree, + const uint32_t* histogram, + const size_t histogram_total, + const size_t max_bits, + uint8_t* depth, uint16_t* bits, + size_t* storage_ix, + uint8_t* storage) { + size_t count = 0; + size_t symbols[4] = { 0 }; + size_t length = 0; + size_t total = histogram_total; + while (total != 0) { + if (histogram[length]) { + if (count < 4) { + symbols[count] = length; + } + ++count; + total -= histogram[length]; + } + ++length; + } + + if (count <= 1) { + BrotliWriteBits(4, 1, storage_ix, storage); + BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); + depth[symbols[0]] = 0; + bits[symbols[0]] = 0; + return; + } + + memset(depth, 0, length * sizeof(depth[0])); + { + uint32_t count_limit; + for (count_limit = 1; ; count_limit *= 2) { + HuffmanTree* node = tree; + size_t l; + for (l = length; l != 0;) { + --l; + if (histogram[l]) { + if (BROTLI_PREDICT_TRUE(histogram[l] >= count_limit)) { + InitHuffmanTree(node, histogram[l], -1, (int16_t)l); + } else { + InitHuffmanTree(node, count_limit, -1, (int16_t)l); + } + ++node; + } + } + { + const int n = (int)(node - tree); + HuffmanTree sentinel; + int i = 0; /* Points to the next leaf node. */ + int j = n + 1; /* Points to the next non-leaf node. */ + int k; + + SortHuffmanTreeItems(tree, (size_t)n, SortHuffmanTree); + /* The nodes are: + [0, n): the sorted leaf nodes that we start with. + [n]: we add a sentinel here. + [n + 1, 2n): new parent nodes are added here, starting from + (n+1). These are naturally in ascending order. + [2n]: we add a sentinel at the end as well. + There will be (2n+1) elements at the end. */ + InitHuffmanTree(&sentinel, BROTLI_UINT32_MAX, -1, -1); + *node++ = sentinel; + *node++ = sentinel; + + for (k = n - 1; k > 0; --k) { + int left, right; + if (tree[i].total_count_ <= tree[j].total_count_) { + left = i; + ++i; + } else { + left = j; + ++j; + } + if (tree[i].total_count_ <= tree[j].total_count_) { + right = i; + ++i; + } else { + right = j; + ++j; + } + /* The sentinel node becomes the parent node. */ + node[-1].total_count_ = + tree[left].total_count_ + tree[right].total_count_; + node[-1].index_left_ = (int16_t)left; + node[-1].index_right_or_value_ = (int16_t)right; + /* Add back the last sentinel node. */ + *node++ = sentinel; + } + if (BrotliSetDepth(2 * n - 1, tree, depth, 14)) { + /* We need to pack the Huffman tree in 14 bits. If this was not + successful, add fake entities to the lowest values and retry. */ + break; + } + } + } + } + BrotliConvertBitDepthsToSymbols(depth, length, bits); + if (count <= 4) { + size_t i; + /* value of 1 indicates a simple Huffman code */ + BrotliWriteBits(2, 1, storage_ix, storage); + BrotliWriteBits(2, count - 1, storage_ix, storage); /* NSYM - 1 */ + + /* Sort */ + for (i = 0; i < count; i++) { + size_t j; + for (j = i + 1; j < count; j++) { + if (depth[symbols[j]] < depth[symbols[i]]) { + BROTLI_SWAP(size_t, symbols, j, i); + } + } + } + + if (count == 2) { + BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); + } else if (count == 3) { + BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[2], storage_ix, storage); + } else { + BrotliWriteBits(max_bits, symbols[0], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[1], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[2], storage_ix, storage); + BrotliWriteBits(max_bits, symbols[3], storage_ix, storage); + /* tree-select */ + BrotliWriteBits(1, depth[symbols[0]] == 1 ? 1 : 0, storage_ix, storage); + } + } else { + uint8_t previous_value = 8; + size_t i; + /* Complex Huffman Tree */ + StoreStaticCodeLengthCode(storage_ix, storage); + + /* Actual RLE coding. */ + for (i = 0; i < length;) { + const uint8_t value = depth[i]; + size_t reps = 1; + size_t k; + for (k = i + 1; k < length && depth[k] == value; ++k) { + ++reps; + } + i += reps; + if (value == 0) { + BrotliWriteBits(kZeroRepsDepth[reps], kZeroRepsBits[reps], + storage_ix, storage); + } else { + if (previous_value != value) { + BrotliWriteBits(kCodeLengthDepth[value], kCodeLengthBits[value], + storage_ix, storage); + --reps; + } + if (reps < 3) { + while (reps != 0) { + reps--; + BrotliWriteBits(kCodeLengthDepth[value], kCodeLengthBits[value], + storage_ix, storage); + } + } else { + reps -= 3; + BrotliWriteBits(kNonZeroRepsDepth[reps], kNonZeroRepsBits[reps], + storage_ix, storage); + } + previous_value = value; + } + } + } +} + +static size_t IndexOf(const uint8_t* v, size_t v_size, uint8_t value) { + size_t i = 0; + for (; i < v_size; ++i) { + if (v[i] == value) return i; + } + return i; +} + +static void MoveToFront(uint8_t* v, size_t index) { + uint8_t value = v[index]; + size_t i; + for (i = index; i != 0; --i) { + v[i] = v[i - 1]; + } + v[0] = value; +} + +static void MoveToFrontTransform(const uint32_t* BROTLI_RESTRICT v_in, + const size_t v_size, + uint32_t* v_out) { + size_t i; + uint8_t mtf[256]; + uint32_t max_value; + if (v_size == 0) { + return; + } + max_value = v_in[0]; + for (i = 1; i < v_size; ++i) { + if (v_in[i] > max_value) max_value = v_in[i]; + } + BROTLI_DCHECK(max_value < 256u); + for (i = 0; i <= max_value; ++i) { + mtf[i] = (uint8_t)i; + } + { + size_t mtf_size = max_value + 1; + for (i = 0; i < v_size; ++i) { + size_t index = IndexOf(mtf, mtf_size, (uint8_t)v_in[i]); + BROTLI_DCHECK(index < mtf_size); + v_out[i] = (uint32_t)index; + MoveToFront(mtf, index); + } + } +} + +/* Finds runs of zeros in v[0..in_size) and replaces them with a prefix code of + the run length plus extra bits (lower 9 bits is the prefix code and the rest + are the extra bits). Non-zero values in v[] are shifted by + *max_length_prefix. Will not create prefix codes bigger than the initial + value of *max_run_length_prefix. The prefix code of run length L is simply + Log2Floor(L) and the number of extra bits is the same as the prefix code. */ +static void RunLengthCodeZeros(const size_t in_size, + uint32_t* BROTLI_RESTRICT v, size_t* BROTLI_RESTRICT out_size, + uint32_t* BROTLI_RESTRICT max_run_length_prefix) { + uint32_t max_reps = 0; + size_t i; + uint32_t max_prefix; + for (i = 0; i < in_size;) { + uint32_t reps = 0; + for (; i < in_size && v[i] != 0; ++i) ; + for (; i < in_size && v[i] == 0; ++i) { + ++reps; + } + max_reps = BROTLI_MAX(uint32_t, reps, max_reps); + } + max_prefix = max_reps > 0 ? Log2FloorNonZero(max_reps) : 0; + max_prefix = BROTLI_MIN(uint32_t, max_prefix, *max_run_length_prefix); + *max_run_length_prefix = max_prefix; + *out_size = 0; + for (i = 0; i < in_size;) { + BROTLI_DCHECK(*out_size <= i); + if (v[i] != 0) { + v[*out_size] = v[i] + *max_run_length_prefix; + ++i; + ++(*out_size); + } else { + uint32_t reps = 1; + size_t k; + for (k = i + 1; k < in_size && v[k] == 0; ++k) { + ++reps; + } + i += reps; + while (reps != 0) { + if (reps < (2u << max_prefix)) { + uint32_t run_length_prefix = Log2FloorNonZero(reps); + const uint32_t extra_bits = reps - (1u << run_length_prefix); + v[*out_size] = run_length_prefix + (extra_bits << 9); + ++(*out_size); + break; + } else { + const uint32_t extra_bits = (1u << max_prefix) - 1u; + v[*out_size] = max_prefix + (extra_bits << 9); + reps -= (2u << max_prefix) - 1u; + ++(*out_size); + } + } + } + } +} + +#define SYMBOL_BITS 9 + +typedef struct EncodeContextMapArena { + uint32_t histogram[BROTLI_MAX_CONTEXT_MAP_SYMBOLS]; + uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS]; + uint16_t bits[BROTLI_MAX_CONTEXT_MAP_SYMBOLS]; +} EncodeContextMapArena; + +static void EncodeContextMap(MemoryManager* m, + EncodeContextMapArena* arena, + const uint32_t* context_map, + size_t context_map_size, + size_t num_clusters, + HuffmanTree* tree, + size_t* storage_ix, uint8_t* storage) { + size_t i; + uint32_t* rle_symbols; + uint32_t max_run_length_prefix = 6; + size_t num_rle_symbols = 0; + uint32_t* BROTLI_RESTRICT const histogram = arena->histogram; + static const uint32_t kSymbolMask = (1u << SYMBOL_BITS) - 1u; + uint8_t* BROTLI_RESTRICT const depths = arena->depths; + uint16_t* BROTLI_RESTRICT const bits = arena->bits; + + StoreVarLenUint8(num_clusters - 1, storage_ix, storage); + + if (num_clusters == 1) { + return; + } + + rle_symbols = BROTLI_ALLOC(m, uint32_t, context_map_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(rle_symbols)) return; + MoveToFrontTransform(context_map, context_map_size, rle_symbols); + RunLengthCodeZeros(context_map_size, rle_symbols, + &num_rle_symbols, &max_run_length_prefix); + memset(histogram, 0, sizeof(arena->histogram)); + for (i = 0; i < num_rle_symbols; ++i) { + ++histogram[rle_symbols[i] & kSymbolMask]; + } + { + BROTLI_BOOL use_rle = TO_BROTLI_BOOL(max_run_length_prefix > 0); + BrotliWriteBits(1, (uint64_t)use_rle, storage_ix, storage); + if (use_rle) { + BrotliWriteBits(4, max_run_length_prefix - 1, storage_ix, storage); + } + } + BuildAndStoreHuffmanTree(histogram, num_clusters + max_run_length_prefix, + num_clusters + max_run_length_prefix, + tree, depths, bits, storage_ix, storage); + for (i = 0; i < num_rle_symbols; ++i) { + const uint32_t rle_symbol = rle_symbols[i] & kSymbolMask; + const uint32_t extra_bits_val = rle_symbols[i] >> SYMBOL_BITS; + BrotliWriteBits(depths[rle_symbol], bits[rle_symbol], storage_ix, storage); + if (rle_symbol > 0 && rle_symbol <= max_run_length_prefix) { + BrotliWriteBits(rle_symbol, extra_bits_val, storage_ix, storage); + } + } + BrotliWriteBits(1, 1, storage_ix, storage); /* use move-to-front */ + BROTLI_FREE(m, rle_symbols); +} + +/* Stores the block switch command with index block_ix to the bit stream. */ +static BROTLI_INLINE void StoreBlockSwitch(BlockSplitCode* code, + const uint32_t block_len, + const uint8_t block_type, + BROTLI_BOOL is_first_block, + size_t* storage_ix, + uint8_t* storage) { + size_t typecode = NextBlockTypeCode(&code->type_code_calculator, block_type); + size_t lencode; + uint32_t len_nextra; + uint32_t len_extra; + if (!is_first_block) { + BrotliWriteBits(code->type_depths[typecode], code->type_bits[typecode], + storage_ix, storage); + } + GetBlockLengthPrefixCode(block_len, &lencode, &len_nextra, &len_extra); + + BrotliWriteBits(code->length_depths[lencode], code->length_bits[lencode], + storage_ix, storage); + BrotliWriteBits(len_nextra, len_extra, storage_ix, storage); +} + +/* Builds a BlockSplitCode data structure from the block split given by the + vector of block types and block lengths and stores it to the bit stream. */ +static void BuildAndStoreBlockSplitCode(const uint8_t* types, + const uint32_t* lengths, + const size_t num_blocks, + const size_t num_types, + HuffmanTree* tree, + BlockSplitCode* code, + size_t* storage_ix, + uint8_t* storage) { + uint32_t type_histo[BROTLI_MAX_BLOCK_TYPE_SYMBOLS]; + uint32_t length_histo[BROTLI_NUM_BLOCK_LEN_SYMBOLS]; + size_t i; + BlockTypeCodeCalculator type_code_calculator; + memset(type_histo, 0, (num_types + 2) * sizeof(type_histo[0])); + memset(length_histo, 0, sizeof(length_histo)); + InitBlockTypeCodeCalculator(&type_code_calculator); + for (i = 0; i < num_blocks; ++i) { + size_t type_code = NextBlockTypeCode(&type_code_calculator, types[i]); + if (i != 0) ++type_histo[type_code]; + ++length_histo[BlockLengthPrefixCode(lengths[i])]; + } + StoreVarLenUint8(num_types - 1, storage_ix, storage); + if (num_types > 1) { /* TODO(eustas): else? could StoreBlockSwitch occur? */ + BuildAndStoreHuffmanTree(&type_histo[0], num_types + 2, num_types + 2, tree, + &code->type_depths[0], &code->type_bits[0], + storage_ix, storage); + BuildAndStoreHuffmanTree(&length_histo[0], BROTLI_NUM_BLOCK_LEN_SYMBOLS, + BROTLI_NUM_BLOCK_LEN_SYMBOLS, + tree, &code->length_depths[0], + &code->length_bits[0], storage_ix, storage); + StoreBlockSwitch(code, lengths[0], types[0], 1, storage_ix, storage); + } +} + +/* Stores a context map where the histogram type is always the block type. */ +static void StoreTrivialContextMap(EncodeContextMapArena* arena, + size_t num_types, + size_t context_bits, + HuffmanTree* tree, + size_t* storage_ix, + uint8_t* storage) { + StoreVarLenUint8(num_types - 1, storage_ix, storage); + if (num_types > 1) { + size_t repeat_code = context_bits - 1u; + size_t repeat_bits = (1u << repeat_code) - 1u; + size_t alphabet_size = num_types + repeat_code; + uint32_t* BROTLI_RESTRICT const histogram = arena->histogram; + uint8_t* BROTLI_RESTRICT const depths = arena->depths; + uint16_t* BROTLI_RESTRICT const bits = arena->bits; + size_t i; + memset(histogram, 0, alphabet_size * sizeof(histogram[0])); + /* Write RLEMAX. */ + BrotliWriteBits(1, 1, storage_ix, storage); + BrotliWriteBits(4, repeat_code - 1, storage_ix, storage); + histogram[repeat_code] = (uint32_t)num_types; + histogram[0] = 1; + for (i = context_bits; i < alphabet_size; ++i) { + histogram[i] = 1; + } + BuildAndStoreHuffmanTree(histogram, alphabet_size, alphabet_size, + tree, depths, bits, storage_ix, storage); + for (i = 0; i < num_types; ++i) { + size_t code = (i == 0 ? 0 : i + context_bits - 1); + BrotliWriteBits(depths[code], bits[code], storage_ix, storage); + BrotliWriteBits( + depths[repeat_code], bits[repeat_code], storage_ix, storage); + BrotliWriteBits(repeat_code, repeat_bits, storage_ix, storage); + } + /* Write IMTF (inverse-move-to-front) bit. */ + BrotliWriteBits(1, 1, storage_ix, storage); + } +} + +/* Manages the encoding of one block category (literal, command or distance). */ +typedef struct BlockEncoder { + size_t histogram_length_; + size_t num_block_types_; + const uint8_t* block_types_; /* Not owned. */ + const uint32_t* block_lengths_; /* Not owned. */ + size_t num_blocks_; + BlockSplitCode block_split_code_; + size_t block_ix_; + size_t block_len_; + size_t entropy_ix_; + uint8_t* depths_; + uint16_t* bits_; +} BlockEncoder; + +static void InitBlockEncoder(BlockEncoder* self, size_t histogram_length, + size_t num_block_types, const uint8_t* block_types, + const uint32_t* block_lengths, const size_t num_blocks) { + self->histogram_length_ = histogram_length; + self->num_block_types_ = num_block_types; + self->block_types_ = block_types; + self->block_lengths_ = block_lengths; + self->num_blocks_ = num_blocks; + InitBlockTypeCodeCalculator(&self->block_split_code_.type_code_calculator); + self->block_ix_ = 0; + self->block_len_ = num_blocks == 0 ? 0 : block_lengths[0]; + self->entropy_ix_ = 0; + self->depths_ = 0; + self->bits_ = 0; +} + +static void CleanupBlockEncoder(MemoryManager* m, BlockEncoder* self) { + BROTLI_FREE(m, self->depths_); + BROTLI_FREE(m, self->bits_); +} + +/* Creates entropy codes of block lengths and block types and stores them + to the bit stream. */ +static void BuildAndStoreBlockSwitchEntropyCodes(BlockEncoder* self, + HuffmanTree* tree, size_t* storage_ix, uint8_t* storage) { + BuildAndStoreBlockSplitCode(self->block_types_, self->block_lengths_, + self->num_blocks_, self->num_block_types_, tree, &self->block_split_code_, + storage_ix, storage); +} + +/* Stores the next symbol with the entropy code of the current block type. + Updates the block type and block length at block boundaries. */ +static void StoreSymbol(BlockEncoder* self, size_t symbol, size_t* storage_ix, + uint8_t* storage) { + if (self->block_len_ == 0) { + size_t block_ix = ++self->block_ix_; + uint32_t block_len = self->block_lengths_[block_ix]; + uint8_t block_type = self->block_types_[block_ix]; + self->block_len_ = block_len; + self->entropy_ix_ = block_type * self->histogram_length_; + StoreBlockSwitch(&self->block_split_code_, block_len, block_type, 0, + storage_ix, storage); + } + --self->block_len_; + { + size_t ix = self->entropy_ix_ + symbol; + BrotliWriteBits(self->depths_[ix], self->bits_[ix], storage_ix, storage); + } +} + +/* Stores the next symbol with the entropy code of the current block type and + context value. + Updates the block type and block length at block boundaries. */ +static void StoreSymbolWithContext(BlockEncoder* self, size_t symbol, + size_t context, const uint32_t* context_map, size_t* storage_ix, + uint8_t* storage, const size_t context_bits) { + if (self->block_len_ == 0) { + size_t block_ix = ++self->block_ix_; + uint32_t block_len = self->block_lengths_[block_ix]; + uint8_t block_type = self->block_types_[block_ix]; + self->block_len_ = block_len; + self->entropy_ix_ = (size_t)block_type << context_bits; + StoreBlockSwitch(&self->block_split_code_, block_len, block_type, 0, + storage_ix, storage); + } + --self->block_len_; + { + size_t histo_ix = context_map[self->entropy_ix_ + context]; + size_t ix = histo_ix * self->histogram_length_ + symbol; + BrotliWriteBits(self->depths_[ix], self->bits_[ix], storage_ix, storage); + } +} + +#define FN(X) X ## Literal +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2014 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +#define HistogramType FN(Histogram) + +/* Creates entropy codes for all block types and stores them to the bit + stream. */ +static void FN(BuildAndStoreEntropyCodes)(MemoryManager* m, BlockEncoder* self, + const HistogramType* histograms, const size_t histograms_size, + const size_t alphabet_size, HuffmanTree* tree, + size_t* storage_ix, uint8_t* storage) { + const size_t table_size = histograms_size * self->histogram_length_; + self->depths_ = BROTLI_ALLOC(m, uint8_t, table_size); + self->bits_ = BROTLI_ALLOC(m, uint16_t, table_size); + if (BROTLI_IS_OOM(m)) return; + + { + size_t i; + for (i = 0; i < histograms_size; ++i) { + size_t ix = i * self->histogram_length_; + BuildAndStoreHuffmanTree(&histograms[i].data_[0], self->histogram_length_, + alphabet_size, tree, &self->depths_[ix], &self->bits_[ix], + storage_ix, storage); + } + } +} + +#undef HistogramType +#undef FN + +#define FN(X) X ## Command +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2014 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +#define HistogramType FN(Histogram) + +/* Creates entropy codes for all block types and stores them to the bit + stream. */ +static void FN(BuildAndStoreEntropyCodes)(MemoryManager* m, BlockEncoder* self, + const HistogramType* histograms, const size_t histograms_size, + const size_t alphabet_size, HuffmanTree* tree, + size_t* storage_ix, uint8_t* storage) { + const size_t table_size = histograms_size * self->histogram_length_; + self->depths_ = BROTLI_ALLOC(m, uint8_t, table_size); + self->bits_ = BROTLI_ALLOC(m, uint16_t, table_size); + if (BROTLI_IS_OOM(m)) return; + + { + size_t i; + for (i = 0; i < histograms_size; ++i) { + size_t ix = i * self->histogram_length_; + BuildAndStoreHuffmanTree(&histograms[i].data_[0], self->histogram_length_, + alphabet_size, tree, &self->depths_[ix], &self->bits_[ix], + storage_ix, storage); + } + } +} + +#undef HistogramType +#undef FN + +#define FN(X) X ## Distance +/* NOLINTNEXTLINE(build/include) */ +/* NOLINT(build/header_guard) */ +/* Copyright 2014 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +#define HistogramType FN(Histogram) + +/* Creates entropy codes for all block types and stores them to the bit + stream. */ +static void FN(BuildAndStoreEntropyCodes)(MemoryManager* m, BlockEncoder* self, + const HistogramType* histograms, const size_t histograms_size, + const size_t alphabet_size, HuffmanTree* tree, + size_t* storage_ix, uint8_t* storage) { + const size_t table_size = histograms_size * self->histogram_length_; + self->depths_ = BROTLI_ALLOC(m, uint8_t, table_size); + self->bits_ = BROTLI_ALLOC(m, uint16_t, table_size); + if (BROTLI_IS_OOM(m)) return; + + { + size_t i; + for (i = 0; i < histograms_size; ++i) { + size_t ix = i * self->histogram_length_; + BuildAndStoreHuffmanTree(&histograms[i].data_[0], self->histogram_length_, + alphabet_size, tree, &self->depths_[ix], &self->bits_[ix], + storage_ix, storage); + } + } +} + +#undef HistogramType +#undef FN + +static void JumpToByteBoundary(size_t* storage_ix, uint8_t* storage) { + *storage_ix = (*storage_ix + 7u) & ~7u; + storage[*storage_ix >> 3] = 0; +} + +typedef struct StoreMetablockArena { + BlockEncoder literal_enc; + BlockEncoder command_enc; + BlockEncoder distance_enc; + EncodeContextMapArena context_map_arena; +} StoreMetablockArena; + +void duckdb_brotli::BrotliStoreMetaBlock(MemoryManager* m, + const uint8_t* input, size_t start_pos, size_t length, size_t mask, + uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last, + const BrotliEncoderParams* params, ContextType literal_context_mode, + const Command* commands, size_t n_commands, const MetaBlockSplit* mb, + size_t* storage_ix, uint8_t* storage) { + + size_t pos = start_pos; + size_t i; + uint32_t num_distance_symbols = params->dist.alphabet_size_max; + uint32_t num_effective_distance_symbols = params->dist.alphabet_size_limit; + HuffmanTree* tree; + ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode); + StoreMetablockArena* arena = NULL; + BlockEncoder* literal_enc = NULL; + BlockEncoder* command_enc = NULL; + BlockEncoder* distance_enc = NULL; + const BrotliDistanceParams* dist = ¶ms->dist; + BROTLI_DCHECK( + num_effective_distance_symbols <= BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS); + + StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage); + + tree = BROTLI_ALLOC(m, HuffmanTree, MAX_HUFFMAN_TREE_SIZE); + arena = BROTLI_ALLOC(m, StoreMetablockArena, 1); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree) || BROTLI_IS_NULL(arena)) return; + literal_enc = &arena->literal_enc; + command_enc = &arena->command_enc; + distance_enc = &arena->distance_enc; + InitBlockEncoder(literal_enc, BROTLI_NUM_LITERAL_SYMBOLS, + mb->literal_split.num_types, mb->literal_split.types, + mb->literal_split.lengths, mb->literal_split.num_blocks); + InitBlockEncoder(command_enc, BROTLI_NUM_COMMAND_SYMBOLS, + mb->command_split.num_types, mb->command_split.types, + mb->command_split.lengths, mb->command_split.num_blocks); + InitBlockEncoder(distance_enc, num_effective_distance_symbols, + mb->distance_split.num_types, mb->distance_split.types, + mb->distance_split.lengths, mb->distance_split.num_blocks); + + BuildAndStoreBlockSwitchEntropyCodes(literal_enc, tree, storage_ix, storage); + BuildAndStoreBlockSwitchEntropyCodes(command_enc, tree, storage_ix, storage); + BuildAndStoreBlockSwitchEntropyCodes(distance_enc, tree, storage_ix, storage); + + BrotliWriteBits(2, dist->distance_postfix_bits, storage_ix, storage); + BrotliWriteBits( + 4, dist->num_direct_distance_codes >> dist->distance_postfix_bits, + storage_ix, storage); + for (i = 0; i < mb->literal_split.num_types; ++i) { + BrotliWriteBits(2, literal_context_mode, storage_ix, storage); + } + + if (mb->literal_context_map_size == 0) { + StoreTrivialContextMap( + &arena->context_map_arena, mb->literal_histograms_size, + BROTLI_LITERAL_CONTEXT_BITS, tree, storage_ix, storage); + } else { + EncodeContextMap(m, &arena->context_map_arena, + mb->literal_context_map, mb->literal_context_map_size, + mb->literal_histograms_size, tree, storage_ix, storage); + if (BROTLI_IS_OOM(m)) return; + } + + if (mb->distance_context_map_size == 0) { + StoreTrivialContextMap( + &arena->context_map_arena, mb->distance_histograms_size, + BROTLI_DISTANCE_CONTEXT_BITS, tree, storage_ix, storage); + } else { + EncodeContextMap(m, &arena->context_map_arena, + mb->distance_context_map, mb->distance_context_map_size, + mb->distance_histograms_size, tree, storage_ix, storage); + if (BROTLI_IS_OOM(m)) return; + } + + BuildAndStoreEntropyCodesLiteral(m, literal_enc, mb->literal_histograms, + mb->literal_histograms_size, BROTLI_NUM_LITERAL_SYMBOLS, tree, + storage_ix, storage); + if (BROTLI_IS_OOM(m)) return; + BuildAndStoreEntropyCodesCommand(m, command_enc, mb->command_histograms, + mb->command_histograms_size, BROTLI_NUM_COMMAND_SYMBOLS, tree, + storage_ix, storage); + if (BROTLI_IS_OOM(m)) return; + BuildAndStoreEntropyCodesDistance(m, distance_enc, mb->distance_histograms, + mb->distance_histograms_size, num_distance_symbols, tree, + storage_ix, storage); + if (BROTLI_IS_OOM(m)) return; + BROTLI_FREE(m, tree); + + for (i = 0; i < n_commands; ++i) { + const Command cmd = commands[i]; + size_t cmd_code = cmd.cmd_prefix_; + StoreSymbol(command_enc, cmd_code, storage_ix, storage); + StoreCommandExtra(&cmd, storage_ix, storage); + if (mb->literal_context_map_size == 0) { + size_t j; + for (j = cmd.insert_len_; j != 0; --j) { + StoreSymbol(literal_enc, input[pos & mask], storage_ix, storage); + ++pos; + } + } else { + size_t j; + for (j = cmd.insert_len_; j != 0; --j) { + size_t context = + BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut); + uint8_t literal = input[pos & mask]; + StoreSymbolWithContext(literal_enc, literal, context, + mb->literal_context_map, storage_ix, storage, + BROTLI_LITERAL_CONTEXT_BITS); + prev_byte2 = prev_byte; + prev_byte = literal; + ++pos; + } + } + pos += CommandCopyLen(&cmd); + if (CommandCopyLen(&cmd)) { + prev_byte2 = input[(pos - 2) & mask]; + prev_byte = input[(pos - 1) & mask]; + if (cmd.cmd_prefix_ >= 128) { + size_t dist_code = cmd.dist_prefix_ & 0x3FF; + uint32_t distnumextra = cmd.dist_prefix_ >> 10; + uint64_t distextra = cmd.dist_extra_; + if (mb->distance_context_map_size == 0) { + StoreSymbol(distance_enc, dist_code, storage_ix, storage); + } else { + size_t context = CommandDistanceContext(&cmd); + StoreSymbolWithContext(distance_enc, dist_code, context, + mb->distance_context_map, storage_ix, storage, + BROTLI_DISTANCE_CONTEXT_BITS); + } + BrotliWriteBits(distnumextra, distextra, storage_ix, storage); + } + } + } + CleanupBlockEncoder(m, distance_enc); + CleanupBlockEncoder(m, command_enc); + CleanupBlockEncoder(m, literal_enc); + BROTLI_FREE(m, arena); + if (is_last) { + JumpToByteBoundary(storage_ix, storage); + } +} + +static void BuildHistograms(const uint8_t* input, + size_t start_pos, + size_t mask, + const Command* commands, + size_t n_commands, + HistogramLiteral* lit_histo, + HistogramCommand* cmd_histo, + HistogramDistance* dist_histo) { + size_t pos = start_pos; + size_t i; + for (i = 0; i < n_commands; ++i) { + const Command cmd = commands[i]; + size_t j; + HistogramAddCommand(cmd_histo, cmd.cmd_prefix_); + for (j = cmd.insert_len_; j != 0; --j) { + HistogramAddLiteral(lit_histo, input[pos & mask]); + ++pos; + } + pos += CommandCopyLen(&cmd); + if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) { + HistogramAddDistance(dist_histo, cmd.dist_prefix_ & 0x3FF); + } + } +} + +static void StoreDataWithHuffmanCodes(const uint8_t* input, + size_t start_pos, + size_t mask, + const Command* commands, + size_t n_commands, + const uint8_t* lit_depth, + const uint16_t* lit_bits, + const uint8_t* cmd_depth, + const uint16_t* cmd_bits, + const uint8_t* dist_depth, + const uint16_t* dist_bits, + size_t* storage_ix, + uint8_t* storage) { + size_t pos = start_pos; + size_t i; + for (i = 0; i < n_commands; ++i) { + const Command cmd = commands[i]; + const size_t cmd_code = cmd.cmd_prefix_; + size_t j; + BrotliWriteBits( + cmd_depth[cmd_code], cmd_bits[cmd_code], storage_ix, storage); + StoreCommandExtra(&cmd, storage_ix, storage); + for (j = cmd.insert_len_; j != 0; --j) { + const uint8_t literal = input[pos & mask]; + BrotliWriteBits( + lit_depth[literal], lit_bits[literal], storage_ix, storage); + ++pos; + } + pos += CommandCopyLen(&cmd); + if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) { + const size_t dist_code = cmd.dist_prefix_ & 0x3FF; + const uint32_t distnumextra = cmd.dist_prefix_ >> 10; + const uint32_t distextra = cmd.dist_extra_; + BrotliWriteBits(dist_depth[dist_code], dist_bits[dist_code], + storage_ix, storage); + BrotliWriteBits(distnumextra, distextra, storage_ix, storage); + } + } +} + +/* TODO(eustas): pull alloc/dealloc to caller? */ +typedef struct MetablockArena { + HistogramLiteral lit_histo; + HistogramCommand cmd_histo; + HistogramDistance dist_histo; + /* TODO(eustas): merge bits and depth? */ + uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS]; + uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS]; + uint8_t cmd_depth[BROTLI_NUM_COMMAND_SYMBOLS]; + uint16_t cmd_bits[BROTLI_NUM_COMMAND_SYMBOLS]; + uint8_t dist_depth[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE]; + uint16_t dist_bits[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE]; + HuffmanTree tree[MAX_HUFFMAN_TREE_SIZE]; +} MetablockArena; + +void duckdb_brotli::BrotliStoreMetaBlockTrivial(MemoryManager* m, + const uint8_t* input, size_t start_pos, size_t length, size_t mask, + BROTLI_BOOL is_last, const BrotliEncoderParams* params, + const Command* commands, size_t n_commands, + size_t* storage_ix, uint8_t* storage) { + MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1); + uint32_t num_distance_symbols = params->dist.alphabet_size_max; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return; + + StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage); + + HistogramClearLiteral(&arena->lit_histo); + HistogramClearCommand(&arena->cmd_histo); + HistogramClearDistance(&arena->dist_histo); + + BuildHistograms(input, start_pos, mask, commands, n_commands, + &arena->lit_histo, &arena->cmd_histo, &arena->dist_histo); + + BrotliWriteBits(13, 0, storage_ix, storage); + + BuildAndStoreHuffmanTree(arena->lit_histo.data_, BROTLI_NUM_LITERAL_SYMBOLS, + BROTLI_NUM_LITERAL_SYMBOLS, arena->tree, + arena->lit_depth, arena->lit_bits, + storage_ix, storage); + BuildAndStoreHuffmanTree(arena->cmd_histo.data_, BROTLI_NUM_COMMAND_SYMBOLS, + BROTLI_NUM_COMMAND_SYMBOLS, arena->tree, + arena->cmd_depth, arena->cmd_bits, + storage_ix, storage); + BuildAndStoreHuffmanTree(arena->dist_histo.data_, + MAX_SIMPLE_DISTANCE_ALPHABET_SIZE, + num_distance_symbols, arena->tree, + arena->dist_depth, arena->dist_bits, + storage_ix, storage); + StoreDataWithHuffmanCodes(input, start_pos, mask, commands, + n_commands, arena->lit_depth, arena->lit_bits, + arena->cmd_depth, arena->cmd_bits, + arena->dist_depth, arena->dist_bits, + storage_ix, storage); + BROTLI_FREE(m, arena); + if (is_last) { + JumpToByteBoundary(storage_ix, storage); + } +} + +void duckdb_brotli::BrotliStoreMetaBlockFast(MemoryManager* m, + const uint8_t* input, size_t start_pos, size_t length, size_t mask, + BROTLI_BOOL is_last, const BrotliEncoderParams* params, + const Command* commands, size_t n_commands, + size_t* storage_ix, uint8_t* storage) { + MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1); + uint32_t num_distance_symbols = params->dist.alphabet_size_max; + uint32_t distance_alphabet_bits = + Log2FloorNonZero(num_distance_symbols - 1) + 1; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return; + + StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage); + + BrotliWriteBits(13, 0, storage_ix, storage); + + if (n_commands <= 128) { + uint32_t histogram[BROTLI_NUM_LITERAL_SYMBOLS] = { 0 }; + size_t pos = start_pos; + size_t num_literals = 0; + size_t i; + for (i = 0; i < n_commands; ++i) { + const Command cmd = commands[i]; + size_t j; + for (j = cmd.insert_len_; j != 0; --j) { + ++histogram[input[pos & mask]]; + ++pos; + } + num_literals += cmd.insert_len_; + pos += CommandCopyLen(&cmd); + } + BrotliBuildAndStoreHuffmanTreeFast(arena->tree, histogram, num_literals, + /* max_bits = */ 8, + arena->lit_depth, arena->lit_bits, + storage_ix, storage); + StoreStaticCommandHuffmanTree(storage_ix, storage); + StoreStaticDistanceHuffmanTree(storage_ix, storage); + StoreDataWithHuffmanCodes(input, start_pos, mask, commands, + n_commands, arena->lit_depth, arena->lit_bits, + kStaticCommandCodeDepth, + kStaticCommandCodeBits, + kStaticDistanceCodeDepth, + kStaticDistanceCodeBits, + storage_ix, storage); + } else { + HistogramClearLiteral(&arena->lit_histo); + HistogramClearCommand(&arena->cmd_histo); + HistogramClearDistance(&arena->dist_histo); + BuildHistograms(input, start_pos, mask, commands, n_commands, + &arena->lit_histo, &arena->cmd_histo, &arena->dist_histo); + BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->lit_histo.data_, + arena->lit_histo.total_count_, + /* max_bits = */ 8, + arena->lit_depth, arena->lit_bits, + storage_ix, storage); + BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->cmd_histo.data_, + arena->cmd_histo.total_count_, + /* max_bits = */ 10, + arena->cmd_depth, arena->cmd_bits, + storage_ix, storage); + BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->dist_histo.data_, + arena->dist_histo.total_count_, + /* max_bits = */ + distance_alphabet_bits, + arena->dist_depth, arena->dist_bits, + storage_ix, storage); + StoreDataWithHuffmanCodes(input, start_pos, mask, commands, + n_commands, arena->lit_depth, arena->lit_bits, + arena->cmd_depth, arena->cmd_bits, + arena->dist_depth, arena->dist_bits, + storage_ix, storage); + } + + BROTLI_FREE(m, arena); + + if (is_last) { + JumpToByteBoundary(storage_ix, storage); + } +} + +/* This is for storing uncompressed blocks (simple raw storage of + bytes-as-bytes). */ +void duckdb_brotli::BrotliStoreUncompressedMetaBlock(BROTLI_BOOL is_final_block, + const uint8_t* BROTLI_RESTRICT input, + size_t position, size_t mask, + size_t len, + size_t* BROTLI_RESTRICT storage_ix, + uint8_t* BROTLI_RESTRICT storage) { + size_t masked_pos = position & mask; + BrotliStoreUncompressedMetaBlockHeader(len, storage_ix, storage); + JumpToByteBoundary(storage_ix, storage); + + if (masked_pos + len > mask + 1) { + size_t len1 = mask + 1 - masked_pos; + memcpy(&storage[*storage_ix >> 3], &input[masked_pos], len1); + *storage_ix += len1 << 3; + len -= len1; + masked_pos = 0; + } + memcpy(&storage[*storage_ix >> 3], &input[masked_pos], len); + *storage_ix += len << 3; + + /* We need to clear the next 4 bytes to continue to be + compatible with BrotliWriteBits. */ + BrotliWriteBitsPrepareStorage(*storage_ix, storage); + + /* Since the uncompressed block itself may not be the final block, add an + empty one after this. */ + if (is_final_block) { + BrotliWriteBits(1, 1, storage_ix, storage); /* islast */ + BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */ + JumpToByteBoundary(storage_ix, storage); + } +} + +#if defined(BROTLI_TEST) +void GetBlockLengthPrefixCodeForTest(uint32_t len, size_t* code, + uint32_t* n_extra, uint32_t* extra) { + GetBlockLengthPrefixCode(len, code, n_extra, extra); +} +#endif + + diff --git a/third_party/brotli/enc/brotli_bit_stream.h b/third_party/brotli/enc/brotli_bit_stream.h new file mode 100644 index 00000000000..242c0f7fdcd --- /dev/null +++ b/third_party/brotli/enc/brotli_bit_stream.h @@ -0,0 +1,85 @@ +/* Copyright 2014 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Functions to convert brotli-related data structures into the + brotli bit stream. The functions here operate under + assumption that there is enough space in the storage, i.e., there are + no out-of-range checks anywhere. + + These functions do bit addressing into a byte array. The byte array + is called "storage" and the index to the bit is called storage_ix + in function arguments. */ + +#ifndef BROTLI_ENC_BROTLI_BIT_STREAM_H_ +#define BROTLI_ENC_BROTLI_BIT_STREAM_H_ + +#include + +#include "../common/context.h" +#include "../common/brotli_platform.h" +#include "command.h" +#include "entropy_encode.h" +#include "memory.h" +#include "metablock.h" + +namespace duckdb_brotli { + +/* All Store functions here will use a storage_ix, which is always the bit + position for the current storage. */ + +BROTLI_INTERNAL void BrotliStoreHuffmanTree(const uint8_t* depths, size_t num, + HuffmanTree* tree, size_t* storage_ix, uint8_t* storage); + +BROTLI_INTERNAL void BrotliBuildAndStoreHuffmanTreeFast( + HuffmanTree* tree, const uint32_t* histogram, const size_t histogram_total, + const size_t max_bits, uint8_t* depth, uint16_t* bits, size_t* storage_ix, + uint8_t* storage); + +/* REQUIRES: length > 0 */ +/* REQUIRES: length <= (1 << 24) */ +BROTLI_INTERNAL void BrotliStoreMetaBlock(MemoryManager* m, + const uint8_t* input, size_t start_pos, size_t length, size_t mask, + uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last, + const BrotliEncoderParams* params, ContextType literal_context_mode, + const Command* commands, size_t n_commands, const MetaBlockSplit* mb, + size_t* storage_ix, uint8_t* storage); + +/* Stores the meta-block without doing any block splitting, just collects + one histogram per block category and uses that for entropy coding. + REQUIRES: length > 0 + REQUIRES: length <= (1 << 24) */ +BROTLI_INTERNAL void BrotliStoreMetaBlockTrivial(MemoryManager* m, + const uint8_t* input, size_t start_pos, size_t length, size_t mask, + BROTLI_BOOL is_last, const BrotliEncoderParams* params, + const Command* commands, size_t n_commands, + size_t* storage_ix, uint8_t* storage); + +/* Same as above, but uses static prefix codes for histograms with a only a few + symbols, and uses static code length prefix codes for all other histograms. + REQUIRES: length > 0 + REQUIRES: length <= (1 << 24) */ +BROTLI_INTERNAL void BrotliStoreMetaBlockFast(MemoryManager* m, + const uint8_t* input, size_t start_pos, size_t length, size_t mask, + BROTLI_BOOL is_last, const BrotliEncoderParams* params, + const Command* commands, size_t n_commands, + size_t* storage_ix, uint8_t* storage); + +/* This is for storing uncompressed blocks (simple raw storage of + bytes-as-bytes). + REQUIRES: length > 0 + REQUIRES: length <= (1 << 24) */ +BROTLI_INTERNAL void BrotliStoreUncompressedMetaBlock( + BROTLI_BOOL is_final_block, const uint8_t* BROTLI_RESTRICT input, + size_t position, size_t mask, size_t len, + size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage); + +#if defined(BROTLI_TEST) +void GetBlockLengthPrefixCodeForTest(uint32_t, size_t*, uint32_t*, uint32_t*); +#endif + +} + +#endif /* BROTLI_ENC_BROTLI_BIT_STREAM_H_ */ diff --git a/third_party/brotli/enc/brotli_hash.h b/third_party/brotli/enc/brotli_hash.h new file mode 100644 index 00000000000..d16cce54a02 --- /dev/null +++ b/third_party/brotli/enc/brotli_hash.h @@ -0,0 +1,4352 @@ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* A (forgetful) hash table to the data seen by the compressor, to + help create backward references to previous data. */ + +#ifndef BROTLI_ENC_HASH_H_ +#define BROTLI_ENC_HASH_H_ + +#include /* exit */ +#include /* memcmp, memset */ + +#include + +#include "../common/brotli_constants.h" +#include "../common/dictionary.h" +#include "../common/brotli_platform.h" +#include "compound_dictionary.h" +#include "encoder_dict.h" +#include "fast_log.h" +#include "find_match_length.h" +#include "memory.h" +#include "quality.h" +#include "static_dict.h" + +namespace duckdb_brotli { + +typedef struct { + /** + * Dynamically allocated areas; regular hasher uses one or two allocations; + * "composite" hasher uses up to 4 allocations. + */ + void* extra[4]; + + /** + * False before the fisrt invocation of HasherSetup (where "extra" memory) + * is allocated. + */ + BROTLI_BOOL is_setup_; + + size_t dict_num_lookups; + size_t dict_num_matches; + + BrotliHasherParams params; + + /** + * False if hasher needs to be "prepared" before use (before the first + * invocation of HasherSetup or after HasherReset). "preparation" is hasher + * data initialization (using input ringbuffer). + */ + BROTLI_BOOL is_prepared_; +} HasherCommon; + +#define score_t size_t + +static const uint32_t kCutoffTransformsCount = 10; +/* 0, 12, 27, 23, 42, 63, 56, 48, 59, 64 */ +/* 0+0, 4+8, 8+19, 12+11, 16+26, 20+43, 24+32, 28+20, 32+27, 36+28 */ +static const uint64_t kCutoffTransforms = + BROTLI_MAKE_UINT64_T(0x071B520A, 0xDA2D3200); + +typedef struct HasherSearchResult { + size_t len; + size_t distance; + score_t score; + int len_code_delta; /* == len_code - len */ +} HasherSearchResult; + +/* kHashMul32 multiplier has these properties: + * The multiplier must be odd. Otherwise we may lose the highest bit. + * No long streaks of ones or zeros. + * There is no effort to ensure that it is a prime, the oddity is enough + for this use. + * The number has been tuned heuristically against compression benchmarks. */ +static const uint32_t kHashMul32 = 0x1E35A7BD; +static const uint64_t kHashMul64 = + BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u); + +static BROTLI_INLINE uint32_t Hash14(const uint8_t* data) { + uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return h >> (32 - 14); +} + +static BROTLI_INLINE void PrepareDistanceCache( + int* BROTLI_RESTRICT distance_cache, const int num_distances) { + if (num_distances > 4) { + int last_distance = distance_cache[0]; + distance_cache[4] = last_distance - 1; + distance_cache[5] = last_distance + 1; + distance_cache[6] = last_distance - 2; + distance_cache[7] = last_distance + 2; + distance_cache[8] = last_distance - 3; + distance_cache[9] = last_distance + 3; + if (num_distances > 10) { + int next_last_distance = distance_cache[1]; + distance_cache[10] = next_last_distance - 1; + distance_cache[11] = next_last_distance + 1; + distance_cache[12] = next_last_distance - 2; + distance_cache[13] = next_last_distance + 2; + distance_cache[14] = next_last_distance - 3; + distance_cache[15] = next_last_distance + 3; + } + } +} + +#define BROTLI_LITERAL_BYTE_SCORE 135 +#define BROTLI_DISTANCE_BIT_PENALTY 30 +/* Score must be positive after applying maximal penalty. */ +#define BROTLI_SCORE_BASE (BROTLI_DISTANCE_BIT_PENALTY * 8 * sizeof(size_t)) + +/* Usually, we always choose the longest backward reference. This function + allows for the exception of that rule. + + If we choose a backward reference that is further away, it will + usually be coded with more bits. We approximate this by assuming + log2(distance). If the distance can be expressed in terms of the + last four distances, we use some heuristic constants to estimate + the bits cost. For the first up to four literals we use the bit + cost of the literals from the literal cost model, after that we + use the average bit cost of the cost model. + + This function is used to sometimes discard a longer backward reference + when it is not much longer and the bit cost for encoding it is more + than the saved literals. + + backward_reference_offset MUST be positive. */ +static BROTLI_INLINE score_t BackwardReferenceScore( + size_t copy_length, size_t backward_reference_offset) { + return BROTLI_SCORE_BASE + BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length - + BROTLI_DISTANCE_BIT_PENALTY * Log2FloorNonZero(backward_reference_offset); +} + +static BROTLI_INLINE score_t BackwardReferenceScoreUsingLastDistance( + size_t copy_length) { + return BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length + + BROTLI_SCORE_BASE + 15; +} + +static BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance( + size_t distance_short_code) { + return (score_t)39 + ((0x1CA10 >> (distance_short_code & 0xE)) & 0xE); +} + +static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem( + const BrotliEncoderDictionary* dictionary, size_t len, size_t word_idx, + const uint8_t* data, size_t max_length, size_t max_backward, + size_t max_distance, HasherSearchResult* out) { + size_t offset; + size_t matchlen; + size_t backward; + score_t score; + offset = dictionary->words->offsets_by_length[len] + len * word_idx; + if (len > max_length) { + return BROTLI_FALSE; + } + + matchlen = + FindMatchLengthWithLimit(data, &dictionary->words->data[offset], len); + if (matchlen + dictionary->cutoffTransformsCount <= len || matchlen == 0) { + return BROTLI_FALSE; + } + { + size_t cut = len - matchlen; + size_t transform_id = (cut << 2) + + (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F); + backward = max_backward + 1 + word_idx + + (transform_id << dictionary->words->size_bits_by_length[len]); + } + if (backward > max_distance) { + return BROTLI_FALSE; + } + score = BackwardReferenceScore(matchlen, backward); + if (score < out->score) { + return BROTLI_FALSE; + } + out->len = matchlen; + out->len_code_delta = (int)len - (int)matchlen; + out->distance = backward; + out->score = score; + return BROTLI_TRUE; +} + +static BROTLI_INLINE void SearchInStaticDictionary( + const BrotliEncoderDictionary* dictionary, + HasherCommon* common, const uint8_t* data, size_t max_length, + size_t max_backward, size_t max_distance, + HasherSearchResult* out, BROTLI_BOOL shallow) { + size_t key; + size_t i; + if (common->dict_num_matches < (common->dict_num_lookups >> 7)) { + return; + } + key = Hash14(data) << 1; + for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) { + common->dict_num_lookups++; + if (dictionary->hash_table_lengths[key] != 0) { + BROTLI_BOOL item_matches = TestStaticDictionaryItem( + dictionary, dictionary->hash_table_lengths[key], + dictionary->hash_table_words[key], data, + max_length, max_backward, max_distance, out); + if (item_matches) { + common->dict_num_matches++; + } + } + } +} + +typedef struct BackwardMatch { + uint32_t distance; + uint32_t length_and_code; +} BackwardMatch; + +static BROTLI_INLINE void InitBackwardMatch(BackwardMatch* self, + size_t dist, size_t len) { + self->distance = (uint32_t)dist; + self->length_and_code = (uint32_t)(len << 5); +} + +static BROTLI_INLINE void InitDictionaryBackwardMatch(BackwardMatch* self, + size_t dist, size_t len, size_t len_code) { + self->distance = (uint32_t)dist; + self->length_and_code = + (uint32_t)((len << 5) | (len == len_code ? 0 : len_code)); +} + +static BROTLI_INLINE size_t BackwardMatchLength(const BackwardMatch* self) { + return self->length_and_code >> 5; +} + +static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) { + size_t code = self->length_and_code & 31; + return code ? code : BackwardMatchLength(self); +} + +#define EXPAND_CAT(a, b) CAT(a, b) +#define CAT(a, b) a ## b +#define FN(X) EXPAND_CAT(X, HASHER()) + +#define HASHER() H10 +#define BUCKET_BITS 17 +#define MAX_TREE_SEARCH_DEPTH 64 +#define MAX_TREE_COMP_LENGTH 128 +/* NOLINT(build/header_guard) */ +/* Copyright 2016 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, BUCKET_BITS, MAX_TREE_COMP_LENGTH, + MAX_TREE_SEARCH_DEPTH */ + +/* A (forgetful) hash table where each hash bucket contains a binary tree of + sequences whose first 4 bytes share the same hash code. + Each sequence is MAX_TREE_COMP_LENGTH long and is identified by its starting + position in the input data. The binary tree is sorted by the lexicographic + order of the sequences, and it is also a max-heap with respect to the + starting positions. */ + +#define HashToBinaryTree HASHER() + +#define BUCKET_SIZE (1 << BUCKET_BITS) + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { + return MAX_TREE_COMP_LENGTH; +} + +static uint32_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) { + uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return h >> (32 - BUCKET_BITS); +} + +typedef struct HashToBinaryTree { + /* The window size minus 1 */ + size_t window_mask_; + + /* Hash table that maps the 4-byte hashes of the sequence to the last + position where this hash was found, which is the root of the binary + tree of sequences that share this hash bucket. */ + uint32_t* buckets_; /* uint32_t[BUCKET_SIZE]; */ + + /* A position used to mark a non-existent sequence, i.e. a tree is empty if + its root is at invalid_pos_ and a node is a leaf if both its children + are at invalid_pos_. */ + uint32_t invalid_pos_; + + /* --- Dynamic size members --- */ + + /* The union of the binary trees of each hash bucket. The root of the tree + corresponding to a hash is a sequence starting at buckets_[hash] and + the left and right children of a sequence starting at pos are + forest_[2 * pos] and forest_[2 * pos + 1]. */ + uint32_t* forest_; /* uint32_t[2 * num_nodes] */ +} HashToBinaryTree; + +static void FN(Initialize)( + HasherCommon* common, HashToBinaryTree* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + self->buckets_ = (uint32_t*)common->extra[0]; + self->forest_ = (uint32_t*)common->extra[1]; + + self->window_mask_ = (1u << params->lgwin) - 1u; + self->invalid_pos_ = (uint32_t)(0 - self->window_mask_); +} + +static void FN(Prepare) + (HashToBinaryTree* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + uint32_t invalid_pos = self->invalid_pos_; + uint32_t i; + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + BROTLI_UNUSED(data); + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + for (i = 0; i < BUCKET_SIZE; i++) { + buckets[i] = invalid_pos; + } +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + size_t num_nodes = (size_t)1 << params->lgwin; + if (one_shot && input_size < num_nodes) { + num_nodes = input_size; + } + alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE; + alloc_size[1] = 2 * sizeof(uint32_t) * num_nodes; +} + +static BROTLI_INLINE size_t FN(LeftChildIndex)( + HashToBinaryTree* BROTLI_RESTRICT self, + const size_t pos) { + return 2 * (pos & self->window_mask_); +} + +static BROTLI_INLINE size_t FN(RightChildIndex)( + HashToBinaryTree* BROTLI_RESTRICT self, + const size_t pos) { + return 2 * (pos & self->window_mask_) + 1; +} + +/* Stores the hash of the next 4 bytes and in a single tree-traversal, the + hash bucket's binary tree is searched for matches and is re-rooted at the + current position. + + If less than MAX_TREE_COMP_LENGTH data is available, the hash bucket of the + current position is searched for matches, but the state of the hash table + is not changed, since we can not know the final sorting order of the + current (incomplete) sequence. + + This function must be called with increasing cur_ix positions. */ +static BROTLI_INLINE BackwardMatch* FN(StoreAndFindMatches)( + HashToBinaryTree* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, + const size_t cur_ix, const size_t ring_buffer_mask, const size_t max_length, + const size_t max_backward, size_t* const BROTLI_RESTRICT best_len, + BackwardMatch* BROTLI_RESTRICT matches) { + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + const size_t max_comp_len = + BROTLI_MIN(size_t, max_length, MAX_TREE_COMP_LENGTH); + const BROTLI_BOOL should_reroot_tree = + TO_BROTLI_BOOL(max_length >= MAX_TREE_COMP_LENGTH); + const uint32_t key = FN(HashBytes)(&data[cur_ix_masked]); + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + uint32_t* BROTLI_RESTRICT forest = self->forest_; + size_t prev_ix = buckets[key]; + /* The forest index of the rightmost node of the left subtree of the new + root, updated as we traverse and re-root the tree of the hash bucket. */ + size_t node_left = FN(LeftChildIndex)(self, cur_ix); + /* The forest index of the leftmost node of the right subtree of the new + root, updated as we traverse and re-root the tree of the hash bucket. */ + size_t node_right = FN(RightChildIndex)(self, cur_ix); + /* The match length of the rightmost node of the left subtree of the new + root, updated as we traverse and re-root the tree of the hash bucket. */ + size_t best_len_left = 0; + /* The match length of the leftmost node of the right subtree of the new + root, updated as we traverse and re-root the tree of the hash bucket. */ + size_t best_len_right = 0; + size_t depth_remaining; + if (should_reroot_tree) { + buckets[key] = (uint32_t)cur_ix; + } + for (depth_remaining = MAX_TREE_SEARCH_DEPTH; ; --depth_remaining) { + const size_t backward = cur_ix - prev_ix; + const size_t prev_ix_masked = prev_ix & ring_buffer_mask; + if (backward == 0 || backward > max_backward || depth_remaining == 0) { + if (should_reroot_tree) { + forest[node_left] = self->invalid_pos_; + forest[node_right] = self->invalid_pos_; + } + break; + } + { + const size_t cur_len = BROTLI_MIN(size_t, best_len_left, best_len_right); + size_t len; + BROTLI_DCHECK(cur_len <= MAX_TREE_COMP_LENGTH); + len = cur_len + + FindMatchLengthWithLimit(&data[cur_ix_masked + cur_len], + &data[prev_ix_masked + cur_len], + max_length - cur_len); + BROTLI_DCHECK( + 0 == memcmp(&data[cur_ix_masked], &data[prev_ix_masked], len)); + if (matches && len > *best_len) { + *best_len = len; + InitBackwardMatch(matches++, backward, len); + } + if (len >= max_comp_len) { + if (should_reroot_tree) { + forest[node_left] = forest[FN(LeftChildIndex)(self, prev_ix)]; + forest[node_right] = forest[FN(RightChildIndex)(self, prev_ix)]; + } + break; + } + if (data[cur_ix_masked + len] > data[prev_ix_masked + len]) { + best_len_left = len; + if (should_reroot_tree) { + forest[node_left] = (uint32_t)prev_ix; + } + node_left = FN(RightChildIndex)(self, prev_ix); + prev_ix = forest[node_left]; + } else { + best_len_right = len; + if (should_reroot_tree) { + forest[node_right] = (uint32_t)prev_ix; + } + node_right = FN(LeftChildIndex)(self, prev_ix); + prev_ix = forest[node_right]; + } + } + } + return matches; +} + +/* Finds all backward matches of &data[cur_ix & ring_buffer_mask] up to the + length of max_length and stores the position cur_ix in the hash table. + + Sets *num_matches to the number of matches found, and stores the found + matches in matches[0] to matches[*num_matches - 1]. The matches will be + sorted by strictly increasing length and (non-strictly) increasing + distance. */ +static BROTLI_INLINE size_t FN(FindAllMatches)( + HashToBinaryTree* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, + const size_t ring_buffer_mask, const size_t cur_ix, + const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const BrotliEncoderParams* params, + BackwardMatch* matches) { + BackwardMatch* const orig_matches = matches; + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + size_t best_len = 1; + const size_t short_match_max_backward = + params->quality != HQ_ZOPFLIFICATION_QUALITY ? 16 : 64; + size_t stop = cur_ix - short_match_max_backward; + uint32_t dict_matches[BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1]; + size_t i; + if (cur_ix < short_match_max_backward) { stop = 0; } + for (i = cur_ix - 1; i > stop && best_len <= 2; --i) { + size_t prev_ix = i; + const size_t backward = cur_ix - prev_ix; + if (BROTLI_PREDICT_FALSE(backward > max_backward)) { + break; + } + prev_ix &= ring_buffer_mask; + if (data[cur_ix_masked] != data[prev_ix] || + data[cur_ix_masked + 1] != data[prev_ix + 1]) { + continue; + } + { + const size_t len = + FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked], + max_length); + if (len > best_len) { + best_len = len; + InitBackwardMatch(matches++, backward, len); + } + } + } + if (best_len < max_length) { + matches = FN(StoreAndFindMatches)(self, data, cur_ix, + ring_buffer_mask, max_length, max_backward, &best_len, matches); + } + for (i = 0; i <= BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN; ++i) { + dict_matches[i] = kInvalidMatch; + } + { + size_t minlen = BROTLI_MAX(size_t, 4, best_len + 1); + if (BrotliFindAllStaticDictionaryMatches(dictionary, + &data[cur_ix_masked], minlen, max_length, &dict_matches[0])) { + size_t maxlen = BROTLI_MIN( + size_t, BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN, max_length); + size_t l; + for (l = minlen; l <= maxlen; ++l) { + uint32_t dict_id = dict_matches[l]; + if (dict_id < kInvalidMatch) { + size_t distance = dictionary_distance + (dict_id >> 5) + 1; + if (distance <= params->dist.max_distance) { + InitDictionaryBackwardMatch(matches++, distance, l, dict_id & 31); + } + } + } + } + } + return (size_t)(matches - orig_matches); +} + +/* Stores the hash of the next 4 bytes and re-roots the binary tree at the + current sequence, without returning any matches. + REQUIRES: ix + MAX_TREE_COMP_LENGTH <= end-of-current-block */ +static BROTLI_INLINE void FN(Store)(HashToBinaryTree* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, + const size_t mask, const size_t ix) { + /* Maximum distance is window size - 16, see section 9.1. of the spec. */ + const size_t max_backward = self->window_mask_ - BROTLI_WINDOW_GAP + 1; + FN(StoreAndFindMatches)(self, data, ix, mask, MAX_TREE_COMP_LENGTH, + max_backward, NULL, NULL); +} + +static BROTLI_INLINE void FN(StoreRange)(HashToBinaryTree* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + size_t i = ix_start; + size_t j = ix_start; + if (ix_start + 63 <= ix_end) { + i = ix_end - 63; + } + if (ix_start + 512 <= i) { + for (; j < i; j += 8) { + FN(Store)(self, data, mask, j); + } + } + for (; i < ix_end; ++i) { + FN(Store)(self, data, mask, i); + } +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashToBinaryTree* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ringbuffer_mask) { + if (num_bytes >= FN(HashTypeLength)() - 1 && + position >= MAX_TREE_COMP_LENGTH) { + /* Store the last `MAX_TREE_COMP_LENGTH - 1` positions in the hasher. + These could not be calculated before, since they require knowledge + of both the previous and the current block. */ + const size_t i_start = position - MAX_TREE_COMP_LENGTH + 1; + const size_t i_end = BROTLI_MIN(size_t, position, i_start + num_bytes); + size_t i; + for (i = i_start; i < i_end; ++i) { + /* Maximum distance is window size - 16, see section 9.1. of the spec. + Furthermore, we have to make sure that we don't look further back + from the start of the next block than the window size, otherwise we + could access already overwritten areas of the ring-buffer. */ + const size_t max_backward = + self->window_mask_ - BROTLI_MAX(size_t, + BROTLI_WINDOW_GAP - 1, + position - i); + /* We know that i + MAX_TREE_COMP_LENGTH <= position + num_bytes, i.e. the + end of the current block and that we have at least + MAX_TREE_COMP_LENGTH tail in the ring-buffer. */ + FN(StoreAndFindMatches)(self, ringbuffer, i, ringbuffer_mask, + MAX_TREE_COMP_LENGTH, max_backward, NULL, NULL); + } + } +} + +#undef BUCKET_SIZE + +#undef HashToBinaryTree +#undef MAX_TREE_SEARCH_DEPTH +#undef MAX_TREE_COMP_LENGTH +#undef BUCKET_BITS +#undef HASHER +/* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */ +#define MAX_NUM_MATCHES_H10 128 + +/* For BUCKET_SWEEP_BITS == 0, enabling the dictionary lookup makes compression + a little faster (0.5% - 1%) and it compresses 0.15% better on small text + and HTML inputs. */ + +#define HASHER() H2 +#define BUCKET_BITS 16 +#define BUCKET_SWEEP_BITS 0 +#define HASH_LEN 5 +#define USE_DICTIONARY 1 +/* NOLINT(build/header_guard) */ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, BUCKET_BITS, BUCKET_SWEEP_BITS, HASH_LEN, + USE_DICTIONARY + */ + +#define HashLongestMatchQuickly HASHER() + +#define BUCKET_SIZE (1 << BUCKET_BITS) +#define BUCKET_MASK (BUCKET_SIZE - 1) +#define BUCKET_SWEEP (1 << BUCKET_SWEEP_BITS) +#define BUCKET_SWEEP_MASK ((BUCKET_SWEEP - 1) << 3) + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; } + +/* HashBytes is the function that chooses the bucket to place + the address in. The HashLongestMatch and HashLongestMatchQuickly + classes have separate, different implementations of hashing. */ +static uint32_t FN(HashBytes)(const uint8_t* data) { + const uint64_t h = ((BROTLI_UNALIGNED_LOAD64LE(data) << (64 - 8 * HASH_LEN)) * + kHashMul64); + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return (uint32_t)(h >> (64 - BUCKET_BITS)); +} + +/* A (forgetful) hash table to the data seen by the compressor, to + help create backward references to previous data. + + This is a hash map of fixed size (BUCKET_SIZE). */ +typedef struct HashLongestMatchQuickly { + /* Shortcuts. */ + HasherCommon* common; + + /* --- Dynamic size members --- */ + + uint32_t* buckets_; /* uint32_t[BUCKET_SIZE]; */ +} HashLongestMatchQuickly; + +static void FN(Initialize)( + HasherCommon* common, HashLongestMatchQuickly* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + self->common = common; + + BROTLI_UNUSED(params); + self->buckets_ = (uint32_t*)common->extra[0]; +} + +static void FN(Prepare)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + /* Partial preparation is 100 times slower (per socket). */ + size_t partial_prepare_threshold = BUCKET_SIZE >> 5; + if (one_shot && input_size <= partial_prepare_threshold) { + size_t i; + for (i = 0; i < input_size; ++i) { + const uint32_t key = FN(HashBytes)(&data[i]); + if (BUCKET_SWEEP == 1) { + buckets[key] = 0; + } else { + uint32_t j; + for (j = 0; j < BUCKET_SWEEP; ++j) { + buckets[(key + (j << 3)) & BUCKET_MASK] = 0; + } + } + } + } else { + /* It is not strictly necessary to fill this buffer here, but + not filling will make the results of the compression stochastic + (but correct). This is because random data would cause the + system to find accidentally good backward references here and there. */ + memset(buckets, 0, sizeof(uint32_t) * BUCKET_SIZE); + } +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + BROTLI_UNUSED(params); + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE; +} + +/* Look at 5 bytes at &data[ix & mask]. + Compute a hash from these, and store the value somewhere within + [ix .. ix+3]. */ +static BROTLI_INLINE void FN(Store)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + const uint32_t key = FN(HashBytes)(&data[ix & mask]); + if (BUCKET_SWEEP == 1) { + self->buckets_[key] = (uint32_t)ix; + } else { + /* Wiggle the value with the bucket sweep range. */ + const uint32_t off = ix & BUCKET_SWEEP_MASK; + self->buckets_[(key + off) & BUCKET_MASK] = (uint32_t)ix; + } +} + +static BROTLI_INLINE void FN(StoreRange)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + size_t i; + for (i = ix_start; i < ix_end; ++i) { + FN(Store)(self, data, mask, i); + } +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask) { + if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { + /* Prepare the hashes for three last bytes of the last write. + These could not be calculated before, since they require knowledge + of both the previous and the current block. */ + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1); + } +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + BROTLI_UNUSED(self); + BROTLI_UNUSED(distance_cache); +} + +/* Find a longest backward match of &data[cur_ix & ring_buffer_mask] + up to the length of max_length and stores the position cur_ix in the + hash table. + + Does not look for matches longer than max_length. + Does not look for matches further away than max_backward. + Writes the best match into |out|. + |out|->score is updated only if a better match is found. */ +static BROTLI_INLINE void FN(FindLongestMatch)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, + const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, + const size_t cur_ix, const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + const size_t best_len_in = out->len; + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + int compare_char = data[cur_ix_masked + best_len_in]; + size_t key = FN(HashBytes)(&data[cur_ix_masked]); + size_t key_out; + score_t min_score = out->score; + score_t best_score = out->score; + size_t best_len = best_len_in; + size_t cached_backward = (size_t)distance_cache[0]; + size_t prev_ix = cur_ix - cached_backward; + out->len_code_delta = 0; + if (prev_ix < cur_ix) { + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char == data[prev_ix + best_len]) { + const size_t len = FindMatchLengthWithLimit( + &data[prev_ix], &data[cur_ix_masked], max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScoreUsingLastDistance(len); + if (best_score < score) { + out->len = len; + out->distance = cached_backward; + out->score = score; + if (BUCKET_SWEEP == 1) { + buckets[key] = (uint32_t)cur_ix; + return; + } else { + best_len = len; + best_score = score; + compare_char = data[cur_ix_masked + len]; + } + } + } + } + } + if (BUCKET_SWEEP == 1) { + size_t backward; + size_t len; + /* Only one to look for, don't bother to prepare for a loop. */ + prev_ix = buckets[key]; + buckets[key] = (uint32_t)cur_ix; + backward = cur_ix - prev_ix; + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char != data[prev_ix + best_len_in]) { + return; + } + if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) { + return; + } + len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + out->len = len; + out->distance = backward; + out->score = score; + return; + } + } + } else { + size_t keys[BUCKET_SWEEP]; + size_t i; + for (i = 0; i < BUCKET_SWEEP; ++i) { + keys[i] = (key + (i << 3)) & BUCKET_MASK; + } + key_out = keys[(cur_ix & BUCKET_SWEEP_MASK) >> 3]; + for (i = 0; i < BUCKET_SWEEP; ++i) { + size_t len; + size_t backward; + prev_ix = buckets[keys[i]]; + backward = cur_ix - prev_ix; + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char != data[prev_ix + best_len]) { + continue; + } + if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) { + continue; + } + len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + best_len = len; + out->len = len; + compare_char = data[cur_ix_masked + len]; + best_score = score; + out->score = score; + out->distance = backward; + } + } + } + } + if (USE_DICTIONARY && min_score == out->score) { + SearchInStaticDictionary(dictionary, + self->common, &data[cur_ix_masked], max_length, dictionary_distance, + max_distance, out, BROTLI_TRUE); + } + if (BUCKET_SWEEP != 1) { + buckets[key_out] = (uint32_t)cur_ix; + } +} + +#undef BUCKET_SWEEP_MASK +#undef BUCKET_SWEEP +#undef BUCKET_MASK +#undef BUCKET_SIZE + +#undef HashLongestMatchQuickly +#undef BUCKET_SWEEP_BITS +#undef USE_DICTIONARY +#undef HASHER + +#define HASHER() H3 +#define BUCKET_SWEEP_BITS 1 +#define USE_DICTIONARY 0 +/* NOLINT(build/header_guard) */ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, BUCKET_BITS, BUCKET_SWEEP_BITS, HASH_LEN, + USE_DICTIONARY + */ + +#define HashLongestMatchQuickly HASHER() + +#define BUCKET_SIZE (1 << BUCKET_BITS) +#define BUCKET_MASK (BUCKET_SIZE - 1) +#define BUCKET_SWEEP (1 << BUCKET_SWEEP_BITS) +#define BUCKET_SWEEP_MASK ((BUCKET_SWEEP - 1) << 3) + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; } + +/* HashBytes is the function that chooses the bucket to place + the address in. The HashLongestMatch and HashLongestMatchQuickly + classes have separate, different implementations of hashing. */ +static uint32_t FN(HashBytes)(const uint8_t* data) { + const uint64_t h = ((BROTLI_UNALIGNED_LOAD64LE(data) << (64 - 8 * HASH_LEN)) * + kHashMul64); + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return (uint32_t)(h >> (64 - BUCKET_BITS)); +} + +/* A (forgetful) hash table to the data seen by the compressor, to + help create backward references to previous data. + + This is a hash map of fixed size (BUCKET_SIZE). */ +typedef struct HashLongestMatchQuickly { + /* Shortcuts. */ + HasherCommon* common; + + /* --- Dynamic size members --- */ + + uint32_t* buckets_; /* uint32_t[BUCKET_SIZE]; */ +} HashLongestMatchQuickly; + +static void FN(Initialize)( + HasherCommon* common, HashLongestMatchQuickly* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + self->common = common; + + BROTLI_UNUSED(params); + self->buckets_ = (uint32_t*)common->extra[0]; +} + +static void FN(Prepare)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + /* Partial preparation is 100 times slower (per socket). */ + size_t partial_prepare_threshold = BUCKET_SIZE >> 5; + if (one_shot && input_size <= partial_prepare_threshold) { + size_t i; + for (i = 0; i < input_size; ++i) { + const uint32_t key = FN(HashBytes)(&data[i]); + if (BUCKET_SWEEP == 1) { + buckets[key] = 0; + } else { + uint32_t j; + for (j = 0; j < BUCKET_SWEEP; ++j) { + buckets[(key + (j << 3)) & BUCKET_MASK] = 0; + } + } + } + } else { + /* It is not strictly necessary to fill this buffer here, but + not filling will make the results of the compression stochastic + (but correct). This is because random data would cause the + system to find accidentally good backward references here and there. */ + memset(buckets, 0, sizeof(uint32_t) * BUCKET_SIZE); + } +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + BROTLI_UNUSED(params); + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE; +} + +/* Look at 5 bytes at &data[ix & mask]. + Compute a hash from these, and store the value somewhere within + [ix .. ix+3]. */ +static BROTLI_INLINE void FN(Store)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + const uint32_t key = FN(HashBytes)(&data[ix & mask]); + if (BUCKET_SWEEP == 1) { + self->buckets_[key] = (uint32_t)ix; + } else { + /* Wiggle the value with the bucket sweep range. */ + const uint32_t off = ix & BUCKET_SWEEP_MASK; + self->buckets_[(key + off) & BUCKET_MASK] = (uint32_t)ix; + } +} + +static BROTLI_INLINE void FN(StoreRange)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + size_t i; + for (i = ix_start; i < ix_end; ++i) { + FN(Store)(self, data, mask, i); + } +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask) { + if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { + /* Prepare the hashes for three last bytes of the last write. + These could not be calculated before, since they require knowledge + of both the previous and the current block. */ + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1); + } +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + BROTLI_UNUSED(self); + BROTLI_UNUSED(distance_cache); +} + +/* Find a longest backward match of &data[cur_ix & ring_buffer_mask] + up to the length of max_length and stores the position cur_ix in the + hash table. + + Does not look for matches longer than max_length. + Does not look for matches further away than max_backward. + Writes the best match into |out|. + |out|->score is updated only if a better match is found. */ +static BROTLI_INLINE void FN(FindLongestMatch)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, + const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, + const size_t cur_ix, const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + const size_t best_len_in = out->len; + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + int compare_char = data[cur_ix_masked + best_len_in]; + size_t key = FN(HashBytes)(&data[cur_ix_masked]); + size_t key_out; + score_t min_score = out->score; + score_t best_score = out->score; + size_t best_len = best_len_in; + size_t cached_backward = (size_t)distance_cache[0]; + size_t prev_ix = cur_ix - cached_backward; + out->len_code_delta = 0; + if (prev_ix < cur_ix) { + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char == data[prev_ix + best_len]) { + const size_t len = FindMatchLengthWithLimit( + &data[prev_ix], &data[cur_ix_masked], max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScoreUsingLastDistance(len); + if (best_score < score) { + out->len = len; + out->distance = cached_backward; + out->score = score; + if (BUCKET_SWEEP == 1) { + buckets[key] = (uint32_t)cur_ix; + return; + } else { + best_len = len; + best_score = score; + compare_char = data[cur_ix_masked + len]; + } + } + } + } + } + if (BUCKET_SWEEP == 1) { + size_t backward; + size_t len; + /* Only one to look for, don't bother to prepare for a loop. */ + prev_ix = buckets[key]; + buckets[key] = (uint32_t)cur_ix; + backward = cur_ix - prev_ix; + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char != data[prev_ix + best_len_in]) { + return; + } + if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) { + return; + } + len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + out->len = len; + out->distance = backward; + out->score = score; + return; + } + } + } else { + size_t keys[BUCKET_SWEEP]; + size_t i; + for (i = 0; i < BUCKET_SWEEP; ++i) { + keys[i] = (key + (i << 3)) & BUCKET_MASK; + } + key_out = keys[(cur_ix & BUCKET_SWEEP_MASK) >> 3]; + for (i = 0; i < BUCKET_SWEEP; ++i) { + size_t len; + size_t backward; + prev_ix = buckets[keys[i]]; + backward = cur_ix - prev_ix; + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char != data[prev_ix + best_len]) { + continue; + } + if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) { + continue; + } + len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + best_len = len; + out->len = len; + compare_char = data[cur_ix_masked + len]; + best_score = score; + out->score = score; + out->distance = backward; + } + } + } + } + if (USE_DICTIONARY && min_score == out->score) { + SearchInStaticDictionary(dictionary, + self->common, &data[cur_ix_masked], max_length, dictionary_distance, + max_distance, out, BROTLI_TRUE); + } + if (BUCKET_SWEEP != 1) { + buckets[key_out] = (uint32_t)cur_ix; + } +} + +#undef BUCKET_SWEEP_MASK +#undef BUCKET_SWEEP +#undef BUCKET_MASK +#undef BUCKET_SIZE + +#undef HashLongestMatchQuickly +#undef USE_DICTIONARY +#undef BUCKET_SWEEP_BITS +#undef BUCKET_BITS +#undef HASHER + +#define HASHER() H4 +#define BUCKET_BITS 17 +#define BUCKET_SWEEP_BITS 2 +#define USE_DICTIONARY 1 +/* NOLINT(build/header_guard) */ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, BUCKET_BITS, BUCKET_SWEEP_BITS, HASH_LEN, + USE_DICTIONARY + */ + +#define HashLongestMatchQuickly HASHER() + +#define BUCKET_SIZE (1 << BUCKET_BITS) +#define BUCKET_MASK (BUCKET_SIZE - 1) +#define BUCKET_SWEEP (1 << BUCKET_SWEEP_BITS) +#define BUCKET_SWEEP_MASK ((BUCKET_SWEEP - 1) << 3) + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; } + +/* HashBytes is the function that chooses the bucket to place + the address in. The HashLongestMatch and HashLongestMatchQuickly + classes have separate, different implementations of hashing. */ +static uint32_t FN(HashBytes)(const uint8_t* data) { + const uint64_t h = ((BROTLI_UNALIGNED_LOAD64LE(data) << (64 - 8 * HASH_LEN)) * + kHashMul64); + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return (uint32_t)(h >> (64 - BUCKET_BITS)); +} + +/* A (forgetful) hash table to the data seen by the compressor, to + help create backward references to previous data. + + This is a hash map of fixed size (BUCKET_SIZE). */ +typedef struct HashLongestMatchQuickly { + /* Shortcuts. */ + HasherCommon* common; + + /* --- Dynamic size members --- */ + + uint32_t* buckets_; /* uint32_t[BUCKET_SIZE]; */ +} HashLongestMatchQuickly; + +static void FN(Initialize)( + HasherCommon* common, HashLongestMatchQuickly* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + self->common = common; + + BROTLI_UNUSED(params); + self->buckets_ = (uint32_t*)common->extra[0]; +} + +static void FN(Prepare)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + /* Partial preparation is 100 times slower (per socket). */ + size_t partial_prepare_threshold = BUCKET_SIZE >> 5; + if (one_shot && input_size <= partial_prepare_threshold) { + size_t i; + for (i = 0; i < input_size; ++i) { + const uint32_t key = FN(HashBytes)(&data[i]); + if (BUCKET_SWEEP == 1) { + buckets[key] = 0; + } else { + uint32_t j; + for (j = 0; j < BUCKET_SWEEP; ++j) { + buckets[(key + (j << 3)) & BUCKET_MASK] = 0; + } + } + } + } else { + /* It is not strictly necessary to fill this buffer here, but + not filling will make the results of the compression stochastic + (but correct). This is because random data would cause the + system to find accidentally good backward references here and there. */ + memset(buckets, 0, sizeof(uint32_t) * BUCKET_SIZE); + } +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + BROTLI_UNUSED(params); + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE; +} + +/* Look at 5 bytes at &data[ix & mask]. + Compute a hash from these, and store the value somewhere within + [ix .. ix+3]. */ +static BROTLI_INLINE void FN(Store)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + const uint32_t key = FN(HashBytes)(&data[ix & mask]); + if (BUCKET_SWEEP == 1) { + self->buckets_[key] = (uint32_t)ix; + } else { + /* Wiggle the value with the bucket sweep range. */ + const uint32_t off = ix & BUCKET_SWEEP_MASK; + self->buckets_[(key + off) & BUCKET_MASK] = (uint32_t)ix; + } +} + +static BROTLI_INLINE void FN(StoreRange)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + size_t i; + for (i = ix_start; i < ix_end; ++i) { + FN(Store)(self, data, mask, i); + } +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask) { + if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { + /* Prepare the hashes for three last bytes of the last write. + These could not be calculated before, since they require knowledge + of both the previous and the current block. */ + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1); + } +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + BROTLI_UNUSED(self); + BROTLI_UNUSED(distance_cache); +} + +/* Find a longest backward match of &data[cur_ix & ring_buffer_mask] + up to the length of max_length and stores the position cur_ix in the + hash table. + + Does not look for matches longer than max_length. + Does not look for matches further away than max_backward. + Writes the best match into |out|. + |out|->score is updated only if a better match is found. */ +static BROTLI_INLINE void FN(FindLongestMatch)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, + const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, + const size_t cur_ix, const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + const size_t best_len_in = out->len; + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + int compare_char = data[cur_ix_masked + best_len_in]; + size_t key = FN(HashBytes)(&data[cur_ix_masked]); + size_t key_out; + score_t min_score = out->score; + score_t best_score = out->score; + size_t best_len = best_len_in; + size_t cached_backward = (size_t)distance_cache[0]; + size_t prev_ix = cur_ix - cached_backward; + out->len_code_delta = 0; + if (prev_ix < cur_ix) { + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char == data[prev_ix + best_len]) { + const size_t len = FindMatchLengthWithLimit( + &data[prev_ix], &data[cur_ix_masked], max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScoreUsingLastDistance(len); + if (best_score < score) { + out->len = len; + out->distance = cached_backward; + out->score = score; + if (BUCKET_SWEEP == 1) { + buckets[key] = (uint32_t)cur_ix; + return; + } else { + best_len = len; + best_score = score; + compare_char = data[cur_ix_masked + len]; + } + } + } + } + } + if (BUCKET_SWEEP == 1) { + size_t backward; + size_t len; + /* Only one to look for, don't bother to prepare for a loop. */ + prev_ix = buckets[key]; + buckets[key] = (uint32_t)cur_ix; + backward = cur_ix - prev_ix; + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char != data[prev_ix + best_len_in]) { + return; + } + if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) { + return; + } + len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + out->len = len; + out->distance = backward; + out->score = score; + return; + } + } + } else { + size_t keys[BUCKET_SWEEP]; + size_t i; + for (i = 0; i < BUCKET_SWEEP; ++i) { + keys[i] = (key + (i << 3)) & BUCKET_MASK; + } + key_out = keys[(cur_ix & BUCKET_SWEEP_MASK) >> 3]; + for (i = 0; i < BUCKET_SWEEP; ++i) { + size_t len; + size_t backward; + prev_ix = buckets[keys[i]]; + backward = cur_ix - prev_ix; + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char != data[prev_ix + best_len]) { + continue; + } + if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) { + continue; + } + len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + best_len = len; + out->len = len; + compare_char = data[cur_ix_masked + len]; + best_score = score; + out->score = score; + out->distance = backward; + } + } + } + } + if (USE_DICTIONARY && min_score == out->score) { + SearchInStaticDictionary(dictionary, + self->common, &data[cur_ix_masked], max_length, dictionary_distance, + max_distance, out, BROTLI_TRUE); + } + if (BUCKET_SWEEP != 1) { + buckets[key_out] = (uint32_t)cur_ix; + } +} + +#undef BUCKET_SWEEP_MASK +#undef BUCKET_SWEEP +#undef BUCKET_MASK +#undef BUCKET_SIZE + +#undef HashLongestMatchQuickly +#undef USE_DICTIONARY +#undef HASH_LEN +#undef BUCKET_SWEEP_BITS +#undef BUCKET_BITS +#undef HASHER + +#define HASHER() H5 +/* NOLINT(build/header_guard) */ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +/* A (forgetful) hash table to the data seen by the compressor, to + help create backward references to previous data. + + This is a hash map of fixed size (bucket_size_) to a ring buffer of + fixed size (block_size_). The ring buffer contains the last block_size_ + index positions of the given hash key in the compressed data. */ + +#define HashLongestMatch HASHER() + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; } + +/* HashBytes is the function that chooses the bucket to place the address in. */ +static uint32_t FN(HashBytes)( + const uint8_t* BROTLI_RESTRICT data, const int shift) { + uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return (uint32_t)(h >> shift); +} + +typedef struct HashLongestMatch { + /* Number of hash buckets. */ + size_t bucket_size_; + /* Only block_size_ newest backward references are kept, + and the older are forgotten. */ + size_t block_size_; + /* Left-shift for computing hash bucket index from hash value. */ + int hash_shift_; + /* Mask for accessing entries in a block (in a ring-buffer manner). */ + uint32_t block_mask_; + + int block_bits_; + int num_last_distances_to_check_; + + /* Shortcuts. */ + HasherCommon* common_; + + /* --- Dynamic size members --- */ + + /* Number of entries in a particular bucket. */ + uint16_t* num_; /* uint16_t[bucket_size]; */ + + /* Buckets containing block_size_ of backward references. */ + uint32_t* buckets_; /* uint32_t[bucket_size * block_size]; */ +} HashLongestMatch; + +static void FN(Initialize)( + HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + self->common_ = common; + + BROTLI_UNUSED(params); + self->hash_shift_ = 32 - common->params.bucket_bits; + self->bucket_size_ = (size_t)1 << common->params.bucket_bits; + self->block_size_ = (size_t)1 << common->params.block_bits; + self->block_mask_ = (uint32_t)(self->block_size_ - 1); + self->num_ = (uint16_t*)common->extra[0]; + self->buckets_ = (uint32_t*)common->extra[1]; + self->block_bits_ = common->params.block_bits; + self->num_last_distances_to_check_ = + common->params.num_last_distances_to_check; +} + +static void FN(Prepare)( + HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + uint16_t* BROTLI_RESTRICT num = self->num_; + /* Partial preparation is 100 times slower (per socket). */ + size_t partial_prepare_threshold = self->bucket_size_ >> 6; + if (one_shot && input_size <= partial_prepare_threshold) { + size_t i; + for (i = 0; i < input_size; ++i) { + const uint32_t key = FN(HashBytes)(&data[i], self->hash_shift_); + num[key] = 0; + } + } else { + memset(num, 0, self->bucket_size_ * sizeof(num[0])); + } +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + size_t bucket_size = (size_t)1 << params->hasher.bucket_bits; + size_t block_size = (size_t)1 << params->hasher.block_bits; + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = sizeof(uint16_t) * bucket_size; + alloc_size[1] = sizeof(uint32_t) * bucket_size * block_size; +} + +/* Look at 4 bytes at &data[ix & mask]. + Compute a hash from these, and store the value of ix at that position. */ +static BROTLI_INLINE void FN(Store)( + HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, + const size_t mask, const size_t ix) { + const uint32_t key = FN(HashBytes)(&data[ix & mask], self->hash_shift_); + const size_t minor_ix = self->num_[key] & self->block_mask_; + const size_t offset = minor_ix + (key << self->block_bits_); + self->buckets_[offset] = (uint32_t)ix; + ++self->num_[key]; +} + +static BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + size_t i; + for (i = ix_start; i < ix_end; ++i) { + FN(Store)(self, data, mask, i); + } +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashLongestMatch* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ringbuffer_mask) { + if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { + /* Prepare the hashes for three last bytes of the last write. + These could not be calculated before, since they require knowledge + of both the previous and the current block. */ + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1); + } +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashLongestMatch* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_); +} + +/* Find a longest backward match of &data[cur_ix] up to the length of + max_length and stores the position cur_ix in the hash table. + + REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache + values; if this method is invoked repeatedly with the same distance + cache values, it is enough to invoke FN(PrepareDistanceCache) once. + + Does not look for matches longer than max_length. + Does not look for matches further away than max_backward. + Writes the best match into |out|. + |out|->score is updated only if a better match is found. */ +static BROTLI_INLINE void FN(FindLongestMatch)( + HashLongestMatch* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, + const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, + const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + uint16_t* BROTLI_RESTRICT num = self->num_; + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + /* Don't accept a short copy from far away. */ + score_t min_score = out->score; + score_t best_score = out->score; + size_t best_len = out->len; + size_t i; + out->len = 0; + out->len_code_delta = 0; + /* Try last distance first. */ + for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) { + const size_t backward = (size_t)distance_cache[i]; + size_t prev_ix = (size_t)(cur_ix - backward); + if (prev_ix >= cur_ix) { + continue; + } + if (BROTLI_PREDICT_FALSE(backward > max_backward)) { + continue; + } + prev_ix &= ring_buffer_mask; + + if (cur_ix_masked + best_len > ring_buffer_mask || + prev_ix + best_len > ring_buffer_mask || + data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { + continue; + } + { + const size_t len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 3 || (len == 2 && i < 2)) { + /* Comparing for >= 2 does not change the semantics, but just saves for + a few unnecessary binary logarithms in backward reference score, + since we are not interested in such short matches. */ + score_t score = BackwardReferenceScoreUsingLastDistance(len); + if (best_score < score) { + if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->distance = backward; + out->score = best_score; + } + } + } + } + } + { + const uint32_t key = + FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_); + uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_]; + const size_t down = + (num[key] > self->block_size_) ? (num[key] - self->block_size_) : 0u; + for (i = num[key]; i > down;) { + size_t prev_ix = bucket[--i & self->block_mask_]; + const size_t backward = cur_ix - prev_ix; + if (BROTLI_PREDICT_FALSE(backward > max_backward)) { + break; + } + prev_ix &= ring_buffer_mask; + if (cur_ix_masked + best_len > ring_buffer_mask || + prev_ix + best_len > ring_buffer_mask || + data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { + continue; + } + { + const size_t len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + /* Comparing for >= 3 does not change the semantics, but just saves + for a few unnecessary binary logarithms in backward reference + score, since we are not interested in such short matches. */ + score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->distance = backward; + out->score = best_score; + } + } + } + } + bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix; + ++num[key]; + } + if (min_score == out->score) { + SearchInStaticDictionary(dictionary, + self->common_, &data[cur_ix_masked], max_length, dictionary_distance, + max_distance, out, BROTLI_FALSE); + } +} + +#undef HashLongestMatch +#undef HASHER + +#define HASHER() H6 +/* NOLINT(build/header_guard) */ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +/* A (forgetful) hash table to the data seen by the compressor, to + help create backward references to previous data. + + This is a hash map of fixed size (bucket_size_) to a ring buffer of + fixed size (block_size_). The ring buffer contains the last block_size_ + index positions of the given hash key in the compressed data. */ + +#define HashLongestMatch HASHER() + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; } + +/* HashBytes is the function that chooses the bucket to place the address in. */ +static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data, + uint64_t hash_mul) { + const uint64_t h = BROTLI_UNALIGNED_LOAD64LE(data) * hash_mul; + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return (size_t)(h >> (64 - 15)); +} + +typedef struct HashLongestMatch { + /* Number of hash buckets. */ + size_t bucket_size_; + /* Only block_size_ newest backward references are kept, + and the older are forgotten. */ + size_t block_size_; + /* Hash multiplier tuned to match length. */ + uint64_t hash_mul_; + /* Mask for accessing entries in a block (in a ring-buffer manner). */ + uint32_t block_mask_; + + int block_bits_; + int num_last_distances_to_check_; + + /* Shortcuts. */ + HasherCommon* common_; + + /* --- Dynamic size members --- */ + + /* Number of entries in a particular bucket. */ + uint16_t* num_; /* uint16_t[bucket_size]; */ + + /* Buckets containing block_size_ of backward references. */ + uint32_t* buckets_; /* uint32_t[bucket_size * block_size]; */ +} HashLongestMatch; + +static void FN(Initialize)( + HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + self->common_ = common; + + BROTLI_UNUSED(params); + self->hash_mul_ = kHashMul64 << (64 - 5 * 8); + BROTLI_DCHECK(common->params.bucket_bits == 15); + self->bucket_size_ = (size_t)1 << common->params.bucket_bits; + self->block_bits_ = common->params.block_bits; + self->block_size_ = (size_t)1 << common->params.block_bits; + self->block_mask_ = (uint32_t)(self->block_size_ - 1); + self->num_last_distances_to_check_ = + common->params.num_last_distances_to_check; + self->num_ = (uint16_t*)common->extra[0]; + self->buckets_ = (uint32_t*)common->extra[1]; +} + +static void FN(Prepare)( + HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + uint16_t* BROTLI_RESTRICT num = self->num_; + /* Partial preparation is 100 times slower (per socket). */ + size_t partial_prepare_threshold = self->bucket_size_ >> 6; + if (one_shot && input_size <= partial_prepare_threshold) { + size_t i; + for (i = 0; i < input_size; ++i) { + const size_t key = FN(HashBytes)(&data[i], self->hash_mul_); + num[key] = 0; + } + } else { + memset(num, 0, self->bucket_size_ * sizeof(num[0])); + } +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + size_t bucket_size = (size_t)1 << params->hasher.bucket_bits; + size_t block_size = (size_t)1 << params->hasher.block_bits; + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = sizeof(uint16_t) * bucket_size; + alloc_size[1] = sizeof(uint32_t) * bucket_size * block_size; +} + +/* Look at 4 bytes at &data[ix & mask]. + Compute a hash from these, and store the value of ix at that position. */ +static BROTLI_INLINE void FN(Store)( + HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, + const size_t mask, const size_t ix) { + uint16_t* BROTLI_RESTRICT num = self->num_; + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + const size_t key = FN(HashBytes)(&data[ix & mask], self->hash_mul_); + const size_t minor_ix = num[key] & self->block_mask_; + const size_t offset = minor_ix + (key << self->block_bits_); + ++num[key]; + buckets[offset] = (uint32_t)ix; +} + +static BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + size_t i; + for (i = ix_start; i < ix_end; ++i) { + FN(Store)(self, data, mask, i); + } +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashLongestMatch* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ringbuffer_mask) { + if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { + /* Prepare the hashes for three last bytes of the last write. + These could not be calculated before, since they require knowledge + of both the previous and the current block. */ + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1); + } +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashLongestMatch* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_); +} + +/* Find a longest backward match of &data[cur_ix] up to the length of + max_length and stores the position cur_ix in the hash table. + + REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache + values; if this method is invoked repeatedly with the same distance + cache values, it is enough to invoke FN(PrepareDistanceCache) once. + + Does not look for matches longer than max_length. + Does not look for matches further away than max_backward. + Writes the best match into |out|. + |out|->score is updated only if a better match is found. */ +static BROTLI_INLINE void FN(FindLongestMatch)( + HashLongestMatch* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, + const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, + const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + uint16_t* BROTLI_RESTRICT num = self->num_; + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + /* Don't accept a short copy from far away. */ + score_t min_score = out->score; + score_t best_score = out->score; + size_t best_len = out->len; + size_t i; + out->len = 0; + out->len_code_delta = 0; + /* Try last distance first. */ + for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) { + const size_t backward = (size_t)distance_cache[i]; + size_t prev_ix = (size_t)(cur_ix - backward); + if (prev_ix >= cur_ix) { + continue; + } + if (BROTLI_PREDICT_FALSE(backward > max_backward)) { + continue; + } + prev_ix &= ring_buffer_mask; + + if (cur_ix_masked + best_len > ring_buffer_mask || + prev_ix + best_len > ring_buffer_mask || + data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { + continue; + } + { + const size_t len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 3 || (len == 2 && i < 2)) { + /* Comparing for >= 2 does not change the semantics, but just saves for + a few unnecessary binary logarithms in backward reference score, + since we are not interested in such short matches. */ + score_t score = BackwardReferenceScoreUsingLastDistance(len); + if (best_score < score) { + if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->distance = backward; + out->score = best_score; + } + } + } + } + } + { + const size_t key = FN(HashBytes)(&data[cur_ix_masked], self->hash_mul_); + uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_]; + const size_t down = + (num[key] > self->block_size_) ? + (num[key] - self->block_size_) : 0u; + const uint32_t first4 = BrotliUnalignedRead32(data + cur_ix_masked); + const size_t max_length_m4 = max_length - 4; + i = num[key]; + for (; i > down;) { + size_t prev_ix = bucket[--i & self->block_mask_]; + uint32_t current4; + const size_t backward = cur_ix - prev_ix; + if (BROTLI_PREDICT_FALSE(backward > max_backward)) { + break; + } + prev_ix &= ring_buffer_mask; + if (cur_ix_masked + best_len > ring_buffer_mask || + prev_ix + best_len > ring_buffer_mask || + data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { + continue; + } + current4 = BrotliUnalignedRead32(data + prev_ix); + if (first4 != current4) continue; + { + const size_t len = FindMatchLengthWithLimit(&data[prev_ix + 4], + &data[cur_ix_masked + 4], + max_length_m4) + 4; + const score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->distance = backward; + out->score = best_score; + } + } + } + bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix; + ++num[key]; + } + if (min_score == out->score) { + SearchInStaticDictionary(dictionary, + self->common_, &data[cur_ix_masked], max_length, dictionary_distance, + max_distance, out, BROTLI_FALSE); + } +} + +#undef HashLongestMatch +#undef HASHER + +#define BUCKET_BITS 15 + +#define NUM_LAST_DISTANCES_TO_CHECK 4 +#define NUM_BANKS 1 +#define BANK_BITS 16 +#define HASHER() H40 +/* NOLINT(build/header_guard) */ +/* Copyright 2016 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, BUCKET_BITS, NUM_BANKS, BANK_BITS, + NUM_LAST_DISTANCES_TO_CHECK */ + +/* A (forgetful) hash table to the data seen by the compressor, to + help create backward references to previous data. + + Hashes are stored in chains which are bucketed to groups. Group of chains + share a storage "bank". When more than "bank size" chain nodes are added, + oldest nodes are replaced; this way several chains may share a tail. */ + +#define HashForgetfulChain HASHER() + +#define BANK_SIZE (1 << BANK_BITS) + +/* Number of hash buckets. */ +#define BUCKET_SIZE (1 << BUCKET_BITS) + +#define CAPPED_CHAINS 0 + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; } + +/* HashBytes is the function that chooses the bucket to place the address in.*/ +static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) { + const uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return h >> (32 - BUCKET_BITS); +} + +typedef struct FN(Slot) { + uint16_t delta; + uint16_t next; +} FN(Slot); + +typedef struct FN(Bank) { + FN(Slot) slots[BANK_SIZE]; +} FN(Bank); + +typedef struct HashForgetfulChain { + uint16_t free_slot_idx[NUM_BANKS]; /* Up to 1KiB. Move to dynamic? */ + size_t max_hops; + + /* Shortcuts. */ + void* extra[2]; + HasherCommon* common; + + /* --- Dynamic size members --- */ + + /* uint32_t addr[BUCKET_SIZE]; */ + + /* uint16_t head[BUCKET_SIZE]; */ + + /* Truncated hash used for quick rejection of "distance cache" candidates. */ + /* uint8_t tiny_hash[65536];*/ + + /* FN(Bank) banks[NUM_BANKS]; */ +} HashForgetfulChain; + +static uint32_t* FN(Addr)(void* extra) { + return (uint32_t*)extra; +} + +static uint16_t* FN(Head)(void* extra) { + return (uint16_t*)(&FN(Addr)(extra)[BUCKET_SIZE]); +} + +static uint8_t* FN(TinyHash)(void* extra) { + return (uint8_t*)(&FN(Head)(extra)[BUCKET_SIZE]); +} + +static FN(Bank)* FN(Banks)(void* extra) { + return (FN(Bank)*)(extra); +} + +static void FN(Initialize)( + HasherCommon* common, HashForgetfulChain* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + self->common = common; + self->extra[0] = common->extra[0]; + self->extra[1] = common->extra[1]; + + self->max_hops = (params->quality > 6 ? 7u : 8u) << (params->quality - 4); +} + +static void FN(Prepare)( + HashForgetfulChain* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); + uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); + uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]); + /* Partial preparation is 100 times slower (per socket). */ + size_t partial_prepare_threshold = BUCKET_SIZE >> 6; + if (one_shot && input_size <= partial_prepare_threshold) { + size_t i; + for (i = 0; i < input_size; ++i) { + size_t bucket = FN(HashBytes)(&data[i]); + /* See InitEmpty comment. */ + addr[bucket] = 0xCCCCCCCC; + head[bucket] = 0xCCCC; + } + } else { + /* Fill |addr| array with 0xCCCCCCCC value. Because of wrapping, position + processed by hasher never reaches 3GB + 64M; this makes all new chains + to be terminated after the first node. */ + memset(addr, 0xCC, sizeof(uint32_t) * BUCKET_SIZE); + memset(head, 0, sizeof(uint16_t) * BUCKET_SIZE); + } + memset(tiny_hash, 0, sizeof(uint8_t) * 65536); + memset(self->free_slot_idx, 0, sizeof(self->free_slot_idx)); +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + BROTLI_UNUSED(params); + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE + + sizeof(uint16_t) * BUCKET_SIZE + sizeof(uint8_t) * 65536; + alloc_size[1] = sizeof(FN(Bank)) * NUM_BANKS; +} + +/* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and prepend + node to corresponding chain; also update tiny_hash for current position. */ +static BROTLI_INLINE void FN(Store)(HashForgetfulChain* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); + uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); + uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]); + FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]); + const size_t key = FN(HashBytes)(&data[ix & mask]); + const size_t bank = key & (NUM_BANKS - 1); + const size_t idx = self->free_slot_idx[bank]++ & (BANK_SIZE - 1); + size_t delta = ix - addr[key]; + tiny_hash[(uint16_t)ix] = (uint8_t)key; + if (delta > 0xFFFF) delta = CAPPED_CHAINS ? 0 : 0xFFFF; + banks[bank].slots[idx].delta = (uint16_t)delta; + banks[bank].slots[idx].next = head[key]; + addr[key] = (uint32_t)ix; + head[key] = (uint16_t)idx; +} + +static BROTLI_INLINE void FN(StoreRange)( + HashForgetfulChain* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + size_t i; + for (i = ix_start; i < ix_end; ++i) { + FN(Store)(self, data, mask, i); + } +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashForgetfulChain* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ring_buffer_mask) { + if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { + /* Prepare the hashes for three last bytes of the last write. + These could not be calculated before, since they require knowledge + of both the previous and the current block. */ + FN(Store)(self, ringbuffer, ring_buffer_mask, position - 3); + FN(Store)(self, ringbuffer, ring_buffer_mask, position - 2); + FN(Store)(self, ringbuffer, ring_buffer_mask, position - 1); + } +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashForgetfulChain* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + BROTLI_UNUSED(self); + PrepareDistanceCache(distance_cache, NUM_LAST_DISTANCES_TO_CHECK); +} + +/* Find a longest backward match of &data[cur_ix] up to the length of + max_length and stores the position cur_ix in the hash table. + + REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache + values; if this method is invoked repeatedly with the same distance + cache values, it is enough to invoke FN(PrepareDistanceCache) once. + + Does not look for matches longer than max_length. + Does not look for matches further away than max_backward. + Writes the best match into |out|. + |out|->score is updated only if a better match is found. */ +static BROTLI_INLINE void FN(FindLongestMatch)( + HashForgetfulChain* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, + const int* BROTLI_RESTRICT distance_cache, + const size_t cur_ix, const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); + uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); + uint8_t* BROTLI_RESTRICT tiny_hashes = FN(TinyHash)(self->extra[0]); + FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]); + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + /* Don't accept a short copy from far away. */ + score_t min_score = out->score; + score_t best_score = out->score; + size_t best_len = out->len; + size_t i; + const size_t key = FN(HashBytes)(&data[cur_ix_masked]); + const uint8_t tiny_hash = (uint8_t)(key); + out->len = 0; + out->len_code_delta = 0; + /* Try last distance first. */ + for (i = 0; i < NUM_LAST_DISTANCES_TO_CHECK; ++i) { + const size_t backward = (size_t)distance_cache[i]; + size_t prev_ix = (cur_ix - backward); + /* For distance code 0 we want to consider 2-byte matches. */ + if (i > 0 && tiny_hashes[(uint16_t)prev_ix] != tiny_hash) continue; + if (prev_ix >= cur_ix || backward > max_backward) { + continue; + } + prev_ix &= ring_buffer_mask; + { + const size_t len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 2) { + score_t score = BackwardReferenceScoreUsingLastDistance(len); + if (best_score < score) { + if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->distance = backward; + out->score = best_score; + } + } + } + } + } + { + const size_t bank = key & (NUM_BANKS - 1); + size_t backward = 0; + size_t hops = self->max_hops; + size_t delta = cur_ix - addr[key]; + size_t slot = head[key]; + while (hops--) { + size_t prev_ix; + size_t last = slot; + backward += delta; + if (backward > max_backward || (CAPPED_CHAINS && !delta)) break; + prev_ix = (cur_ix - backward) & ring_buffer_mask; + slot = banks[bank].slots[last].next; + delta = banks[bank].slots[last].delta; + if (cur_ix_masked + best_len > ring_buffer_mask || + prev_ix + best_len > ring_buffer_mask || + data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { + continue; + } + { + const size_t len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + /* Comparing for >= 3 does not change the semantics, but just saves + for a few unnecessary binary logarithms in backward reference + score, since we are not interested in such short matches. */ + score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->distance = backward; + out->score = best_score; + } + } + } + } + FN(Store)(self, data, ring_buffer_mask, cur_ix); + } + if (out->score == min_score) { + SearchInStaticDictionary(dictionary, + self->common, &data[cur_ix_masked], max_length, dictionary_distance, + max_distance, out, BROTLI_FALSE); + } +} + +#undef BANK_SIZE +#undef BUCKET_SIZE +#undef CAPPED_CHAINS + +#undef HashForgetfulChain +#undef HASHER +#undef NUM_LAST_DISTANCES_TO_CHECK + +#define NUM_LAST_DISTANCES_TO_CHECK 10 +#define HASHER() H41 +/* NOLINT(build/header_guard) */ +/* Copyright 2016 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, BUCKET_BITS, NUM_BANKS, BANK_BITS, + NUM_LAST_DISTANCES_TO_CHECK */ + +/* A (forgetful) hash table to the data seen by the compressor, to + help create backward references to previous data. + + Hashes are stored in chains which are bucketed to groups. Group of chains + share a storage "bank". When more than "bank size" chain nodes are added, + oldest nodes are replaced; this way several chains may share a tail. */ + +#define HashForgetfulChain HASHER() + +#define BANK_SIZE (1 << BANK_BITS) + +/* Number of hash buckets. */ +#define BUCKET_SIZE (1 << BUCKET_BITS) + +#define CAPPED_CHAINS 0 + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; } + +/* HashBytes is the function that chooses the bucket to place the address in.*/ +static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) { + const uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return h >> (32 - BUCKET_BITS); +} + +typedef struct FN(Slot) { + uint16_t delta; + uint16_t next; +} FN(Slot); + +typedef struct FN(Bank) { + FN(Slot) slots[BANK_SIZE]; +} FN(Bank); + +typedef struct HashForgetfulChain { + uint16_t free_slot_idx[NUM_BANKS]; /* Up to 1KiB. Move to dynamic? */ + size_t max_hops; + + /* Shortcuts. */ + void* extra[2]; + HasherCommon* common; + + /* --- Dynamic size members --- */ + + /* uint32_t addr[BUCKET_SIZE]; */ + + /* uint16_t head[BUCKET_SIZE]; */ + + /* Truncated hash used for quick rejection of "distance cache" candidates. */ + /* uint8_t tiny_hash[65536];*/ + + /* FN(Bank) banks[NUM_BANKS]; */ +} HashForgetfulChain; + +static uint32_t* FN(Addr)(void* extra) { + return (uint32_t*)extra; +} + +static uint16_t* FN(Head)(void* extra) { + return (uint16_t*)(&FN(Addr)(extra)[BUCKET_SIZE]); +} + +static uint8_t* FN(TinyHash)(void* extra) { + return (uint8_t*)(&FN(Head)(extra)[BUCKET_SIZE]); +} + +static FN(Bank)* FN(Banks)(void* extra) { + return (FN(Bank)*)(extra); +} + +static void FN(Initialize)( + HasherCommon* common, HashForgetfulChain* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + self->common = common; + self->extra[0] = common->extra[0]; + self->extra[1] = common->extra[1]; + + self->max_hops = (params->quality > 6 ? 7u : 8u) << (params->quality - 4); +} + +static void FN(Prepare)( + HashForgetfulChain* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); + uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); + uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]); + /* Partial preparation is 100 times slower (per socket). */ + size_t partial_prepare_threshold = BUCKET_SIZE >> 6; + if (one_shot && input_size <= partial_prepare_threshold) { + size_t i; + for (i = 0; i < input_size; ++i) { + size_t bucket = FN(HashBytes)(&data[i]); + /* See InitEmpty comment. */ + addr[bucket] = 0xCCCCCCCC; + head[bucket] = 0xCCCC; + } + } else { + /* Fill |addr| array with 0xCCCCCCCC value. Because of wrapping, position + processed by hasher never reaches 3GB + 64M; this makes all new chains + to be terminated after the first node. */ + memset(addr, 0xCC, sizeof(uint32_t) * BUCKET_SIZE); + memset(head, 0, sizeof(uint16_t) * BUCKET_SIZE); + } + memset(tiny_hash, 0, sizeof(uint8_t) * 65536); + memset(self->free_slot_idx, 0, sizeof(self->free_slot_idx)); +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + BROTLI_UNUSED(params); + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE + + sizeof(uint16_t) * BUCKET_SIZE + sizeof(uint8_t) * 65536; + alloc_size[1] = sizeof(FN(Bank)) * NUM_BANKS; +} + +/* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and prepend + node to corresponding chain; also update tiny_hash for current position. */ +static BROTLI_INLINE void FN(Store)(HashForgetfulChain* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); + uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); + uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]); + FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]); + const size_t key = FN(HashBytes)(&data[ix & mask]); + const size_t bank = key & (NUM_BANKS - 1); + const size_t idx = self->free_slot_idx[bank]++ & (BANK_SIZE - 1); + size_t delta = ix - addr[key]; + tiny_hash[(uint16_t)ix] = (uint8_t)key; + if (delta > 0xFFFF) delta = CAPPED_CHAINS ? 0 : 0xFFFF; + banks[bank].slots[idx].delta = (uint16_t)delta; + banks[bank].slots[idx].next = head[key]; + addr[key] = (uint32_t)ix; + head[key] = (uint16_t)idx; +} + +static BROTLI_INLINE void FN(StoreRange)( + HashForgetfulChain* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + size_t i; + for (i = ix_start; i < ix_end; ++i) { + FN(Store)(self, data, mask, i); + } +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashForgetfulChain* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ring_buffer_mask) { + if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { + /* Prepare the hashes for three last bytes of the last write. + These could not be calculated before, since they require knowledge + of both the previous and the current block. */ + FN(Store)(self, ringbuffer, ring_buffer_mask, position - 3); + FN(Store)(self, ringbuffer, ring_buffer_mask, position - 2); + FN(Store)(self, ringbuffer, ring_buffer_mask, position - 1); + } +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashForgetfulChain* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + BROTLI_UNUSED(self); + PrepareDistanceCache(distance_cache, NUM_LAST_DISTANCES_TO_CHECK); +} + +/* Find a longest backward match of &data[cur_ix] up to the length of + max_length and stores the position cur_ix in the hash table. + + REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache + values; if this method is invoked repeatedly with the same distance + cache values, it is enough to invoke FN(PrepareDistanceCache) once. + + Does not look for matches longer than max_length. + Does not look for matches further away than max_backward. + Writes the best match into |out|. + |out|->score is updated only if a better match is found. */ +static BROTLI_INLINE void FN(FindLongestMatch)( + HashForgetfulChain* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, + const int* BROTLI_RESTRICT distance_cache, + const size_t cur_ix, const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); + uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); + uint8_t* BROTLI_RESTRICT tiny_hashes = FN(TinyHash)(self->extra[0]); + FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]); + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + /* Don't accept a short copy from far away. */ + score_t min_score = out->score; + score_t best_score = out->score; + size_t best_len = out->len; + size_t i; + const size_t key = FN(HashBytes)(&data[cur_ix_masked]); + const uint8_t tiny_hash = (uint8_t)(key); + out->len = 0; + out->len_code_delta = 0; + /* Try last distance first. */ + for (i = 0; i < NUM_LAST_DISTANCES_TO_CHECK; ++i) { + const size_t backward = (size_t)distance_cache[i]; + size_t prev_ix = (cur_ix - backward); + /* For distance code 0 we want to consider 2-byte matches. */ + if (i > 0 && tiny_hashes[(uint16_t)prev_ix] != tiny_hash) continue; + if (prev_ix >= cur_ix || backward > max_backward) { + continue; + } + prev_ix &= ring_buffer_mask; + { + const size_t len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 2) { + score_t score = BackwardReferenceScoreUsingLastDistance(len); + if (best_score < score) { + if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->distance = backward; + out->score = best_score; + } + } + } + } + } + { + const size_t bank = key & (NUM_BANKS - 1); + size_t backward = 0; + size_t hops = self->max_hops; + size_t delta = cur_ix - addr[key]; + size_t slot = head[key]; + while (hops--) { + size_t prev_ix; + size_t last = slot; + backward += delta; + if (backward > max_backward || (CAPPED_CHAINS && !delta)) break; + prev_ix = (cur_ix - backward) & ring_buffer_mask; + slot = banks[bank].slots[last].next; + delta = banks[bank].slots[last].delta; + if (cur_ix_masked + best_len > ring_buffer_mask || + prev_ix + best_len > ring_buffer_mask || + data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { + continue; + } + { + const size_t len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + /* Comparing for >= 3 does not change the semantics, but just saves + for a few unnecessary binary logarithms in backward reference + score, since we are not interested in such short matches. */ + score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->distance = backward; + out->score = best_score; + } + } + } + } + FN(Store)(self, data, ring_buffer_mask, cur_ix); + } + if (out->score == min_score) { + SearchInStaticDictionary(dictionary, + self->common, &data[cur_ix_masked], max_length, dictionary_distance, + max_distance, out, BROTLI_FALSE); + } +} + +#undef BANK_SIZE +#undef BUCKET_SIZE +#undef CAPPED_CHAINS + +#undef HashForgetfulChain +#undef HASHER +#undef NUM_LAST_DISTANCES_TO_CHECK +#undef NUM_BANKS +#undef BANK_BITS + +#define NUM_LAST_DISTANCES_TO_CHECK 16 +#define NUM_BANKS 512 +#define BANK_BITS 9 +#define HASHER() H42 +/* NOLINT(build/header_guard) */ +/* Copyright 2016 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, BUCKET_BITS, NUM_BANKS, BANK_BITS, + NUM_LAST_DISTANCES_TO_CHECK */ + +/* A (forgetful) hash table to the data seen by the compressor, to + help create backward references to previous data. + + Hashes are stored in chains which are bucketed to groups. Group of chains + share a storage "bank". When more than "bank size" chain nodes are added, + oldest nodes are replaced; this way several chains may share a tail. */ + +#define HashForgetfulChain HASHER() + +#define BANK_SIZE (1 << BANK_BITS) + +/* Number of hash buckets. */ +#define BUCKET_SIZE (1 << BUCKET_BITS) + +#define CAPPED_CHAINS 0 + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; } + +/* HashBytes is the function that chooses the bucket to place the address in.*/ +static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) { + const uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return h >> (32 - BUCKET_BITS); +} + +typedef struct FN(Slot) { + uint16_t delta; + uint16_t next; +} FN(Slot); + +typedef struct FN(Bank) { + FN(Slot) slots[BANK_SIZE]; +} FN(Bank); + +typedef struct HashForgetfulChain { + uint16_t free_slot_idx[NUM_BANKS]; /* Up to 1KiB. Move to dynamic? */ + size_t max_hops; + + /* Shortcuts. */ + void* extra[2]; + HasherCommon* common; + + /* --- Dynamic size members --- */ + + /* uint32_t addr[BUCKET_SIZE]; */ + + /* uint16_t head[BUCKET_SIZE]; */ + + /* Truncated hash used for quick rejection of "distance cache" candidates. */ + /* uint8_t tiny_hash[65536];*/ + + /* FN(Bank) banks[NUM_BANKS]; */ +} HashForgetfulChain; + +static uint32_t* FN(Addr)(void* extra) { + return (uint32_t*)extra; +} + +static uint16_t* FN(Head)(void* extra) { + return (uint16_t*)(&FN(Addr)(extra)[BUCKET_SIZE]); +} + +static uint8_t* FN(TinyHash)(void* extra) { + return (uint8_t*)(&FN(Head)(extra)[BUCKET_SIZE]); +} + +static FN(Bank)* FN(Banks)(void* extra) { + return (FN(Bank)*)(extra); +} + +static void FN(Initialize)( + HasherCommon* common, HashForgetfulChain* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + self->common = common; + self->extra[0] = common->extra[0]; + self->extra[1] = common->extra[1]; + + self->max_hops = (params->quality > 6 ? 7u : 8u) << (params->quality - 4); +} + +static void FN(Prepare)( + HashForgetfulChain* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); + uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); + uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]); + /* Partial preparation is 100 times slower (per socket). */ + size_t partial_prepare_threshold = BUCKET_SIZE >> 6; + if (one_shot && input_size <= partial_prepare_threshold) { + size_t i; + for (i = 0; i < input_size; ++i) { + size_t bucket = FN(HashBytes)(&data[i]); + /* See InitEmpty comment. */ + addr[bucket] = 0xCCCCCCCC; + head[bucket] = 0xCCCC; + } + } else { + /* Fill |addr| array with 0xCCCCCCCC value. Because of wrapping, position + processed by hasher never reaches 3GB + 64M; this makes all new chains + to be terminated after the first node. */ + memset(addr, 0xCC, sizeof(uint32_t) * BUCKET_SIZE); + memset(head, 0, sizeof(uint16_t) * BUCKET_SIZE); + } + memset(tiny_hash, 0, sizeof(uint8_t) * 65536); + memset(self->free_slot_idx, 0, sizeof(self->free_slot_idx)); +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + BROTLI_UNUSED(params); + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE + + sizeof(uint16_t) * BUCKET_SIZE + sizeof(uint8_t) * 65536; + alloc_size[1] = sizeof(FN(Bank)) * NUM_BANKS; +} + +/* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and prepend + node to corresponding chain; also update tiny_hash for current position. */ +static BROTLI_INLINE void FN(Store)(HashForgetfulChain* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); + uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); + uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]); + FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]); + const size_t key = FN(HashBytes)(&data[ix & mask]); + const size_t bank = key & (NUM_BANKS - 1); + const size_t idx = self->free_slot_idx[bank]++ & (BANK_SIZE - 1); + size_t delta = ix - addr[key]; + tiny_hash[(uint16_t)ix] = (uint8_t)key; + if (delta > 0xFFFF) delta = CAPPED_CHAINS ? 0 : 0xFFFF; + banks[bank].slots[idx].delta = (uint16_t)delta; + banks[bank].slots[idx].next = head[key]; + addr[key] = (uint32_t)ix; + head[key] = (uint16_t)idx; +} + +static BROTLI_INLINE void FN(StoreRange)( + HashForgetfulChain* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + size_t i; + for (i = ix_start; i < ix_end; ++i) { + FN(Store)(self, data, mask, i); + } +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashForgetfulChain* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ring_buffer_mask) { + if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { + /* Prepare the hashes for three last bytes of the last write. + These could not be calculated before, since they require knowledge + of both the previous and the current block. */ + FN(Store)(self, ringbuffer, ring_buffer_mask, position - 3); + FN(Store)(self, ringbuffer, ring_buffer_mask, position - 2); + FN(Store)(self, ringbuffer, ring_buffer_mask, position - 1); + } +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashForgetfulChain* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + BROTLI_UNUSED(self); + PrepareDistanceCache(distance_cache, NUM_LAST_DISTANCES_TO_CHECK); +} + +/* Find a longest backward match of &data[cur_ix] up to the length of + max_length and stores the position cur_ix in the hash table. + + REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache + values; if this method is invoked repeatedly with the same distance + cache values, it is enough to invoke FN(PrepareDistanceCache) once. + + Does not look for matches longer than max_length. + Does not look for matches further away than max_backward. + Writes the best match into |out|. + |out|->score is updated only if a better match is found. */ +static BROTLI_INLINE void FN(FindLongestMatch)( + HashForgetfulChain* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, + const int* BROTLI_RESTRICT distance_cache, + const size_t cur_ix, const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]); + uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]); + uint8_t* BROTLI_RESTRICT tiny_hashes = FN(TinyHash)(self->extra[0]); + FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]); + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + /* Don't accept a short copy from far away. */ + score_t min_score = out->score; + score_t best_score = out->score; + size_t best_len = out->len; + size_t i; + const size_t key = FN(HashBytes)(&data[cur_ix_masked]); + const uint8_t tiny_hash = (uint8_t)(key); + out->len = 0; + out->len_code_delta = 0; + /* Try last distance first. */ + for (i = 0; i < NUM_LAST_DISTANCES_TO_CHECK; ++i) { + const size_t backward = (size_t)distance_cache[i]; + size_t prev_ix = (cur_ix - backward); + /* For distance code 0 we want to consider 2-byte matches. */ + if (i > 0 && tiny_hashes[(uint16_t)prev_ix] != tiny_hash) continue; + if (prev_ix >= cur_ix || backward > max_backward) { + continue; + } + prev_ix &= ring_buffer_mask; + { + const size_t len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 2) { + score_t score = BackwardReferenceScoreUsingLastDistance(len); + if (best_score < score) { + if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->distance = backward; + out->score = best_score; + } + } + } + } + } + { + const size_t bank = key & (NUM_BANKS - 1); + size_t backward = 0; + size_t hops = self->max_hops; + size_t delta = cur_ix - addr[key]; + size_t slot = head[key]; + while (hops--) { + size_t prev_ix; + size_t last = slot; + backward += delta; + if (backward > max_backward || (CAPPED_CHAINS && !delta)) break; + prev_ix = (cur_ix - backward) & ring_buffer_mask; + slot = banks[bank].slots[last].next; + delta = banks[bank].slots[last].delta; + if (cur_ix_masked + best_len > ring_buffer_mask || + prev_ix + best_len > ring_buffer_mask || + data[cur_ix_masked + best_len] != data[prev_ix + best_len]) { + continue; + } + { + const size_t len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + /* Comparing for >= 3 does not change the semantics, but just saves + for a few unnecessary binary logarithms in backward reference + score, since we are not interested in such short matches. */ + score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->distance = backward; + out->score = best_score; + } + } + } + } + FN(Store)(self, data, ring_buffer_mask, cur_ix); + } + if (out->score == min_score) { + SearchInStaticDictionary(dictionary, + self->common, &data[cur_ix_masked], max_length, dictionary_distance, + max_distance, out, BROTLI_FALSE); + } +} + +#undef BANK_SIZE +#undef BUCKET_SIZE +#undef CAPPED_CHAINS + +#undef HashForgetfulChain +#undef HASHER +#undef NUM_LAST_DISTANCES_TO_CHECK +#undef NUM_BANKS +#undef BANK_BITS + +#undef BUCKET_BITS + +#define HASHER() H54 +#define BUCKET_BITS 20 +#define BUCKET_SWEEP_BITS 2 +#define HASH_LEN 7 +#define USE_DICTIONARY 0 +/* NOLINT(build/header_guard) */ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, BUCKET_BITS, BUCKET_SWEEP_BITS, HASH_LEN, + USE_DICTIONARY + */ + +#define HashLongestMatchQuickly HASHER() + +#define BUCKET_SIZE (1 << BUCKET_BITS) +#define BUCKET_MASK (BUCKET_SIZE - 1) +#define BUCKET_SWEEP (1 << BUCKET_SWEEP_BITS) +#define BUCKET_SWEEP_MASK ((BUCKET_SWEEP - 1) << 3) + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; } + +/* HashBytes is the function that chooses the bucket to place + the address in. The HashLongestMatch and HashLongestMatchQuickly + classes have separate, different implementations of hashing. */ +static uint32_t FN(HashBytes)(const uint8_t* data) { + const uint64_t h = ((BROTLI_UNALIGNED_LOAD64LE(data) << (64 - 8 * HASH_LEN)) * + kHashMul64); + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return (uint32_t)(h >> (64 - BUCKET_BITS)); +} + +/* A (forgetful) hash table to the data seen by the compressor, to + help create backward references to previous data. + + This is a hash map of fixed size (BUCKET_SIZE). */ +typedef struct HashLongestMatchQuickly { + /* Shortcuts. */ + HasherCommon* common; + + /* --- Dynamic size members --- */ + + uint32_t* buckets_; /* uint32_t[BUCKET_SIZE]; */ +} HashLongestMatchQuickly; + +static void FN(Initialize)( + HasherCommon* common, HashLongestMatchQuickly* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + self->common = common; + + BROTLI_UNUSED(params); + self->buckets_ = (uint32_t*)common->extra[0]; +} + +static void FN(Prepare)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + /* Partial preparation is 100 times slower (per socket). */ + size_t partial_prepare_threshold = BUCKET_SIZE >> 5; + if (one_shot && input_size <= partial_prepare_threshold) { + size_t i; + for (i = 0; i < input_size; ++i) { + const uint32_t key = FN(HashBytes)(&data[i]); + if (BUCKET_SWEEP == 1) { + buckets[key] = 0; + } else { + uint32_t j; + for (j = 0; j < BUCKET_SWEEP; ++j) { + buckets[(key + (j << 3)) & BUCKET_MASK] = 0; + } + } + } + } else { + /* It is not strictly necessary to fill this buffer here, but + not filling will make the results of the compression stochastic + (but correct). This is because random data would cause the + system to find accidentally good backward references here and there. */ + memset(buckets, 0, sizeof(uint32_t) * BUCKET_SIZE); + } +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + BROTLI_UNUSED(params); + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE; +} + +/* Look at 5 bytes at &data[ix & mask]. + Compute a hash from these, and store the value somewhere within + [ix .. ix+3]. */ +static BROTLI_INLINE void FN(Store)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + const uint32_t key = FN(HashBytes)(&data[ix & mask]); + if (BUCKET_SWEEP == 1) { + self->buckets_[key] = (uint32_t)ix; + } else { + /* Wiggle the value with the bucket sweep range. */ + const uint32_t off = ix & BUCKET_SWEEP_MASK; + self->buckets_[(key + off) & BUCKET_MASK] = (uint32_t)ix; + } +} + +static BROTLI_INLINE void FN(StoreRange)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + size_t i; + for (i = ix_start; i < ix_end; ++i) { + FN(Store)(self, data, mask, i); + } +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, + const uint8_t* ringbuffer, size_t ringbuffer_mask) { + if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) { + /* Prepare the hashes for three last bytes of the last write. + These could not be calculated before, since they require knowledge + of both the previous and the current block. */ + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2); + FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1); + } +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + BROTLI_UNUSED(self); + BROTLI_UNUSED(distance_cache); +} + +/* Find a longest backward match of &data[cur_ix & ring_buffer_mask] + up to the length of max_length and stores the position cur_ix in the + hash table. + + Does not look for matches longer than max_length. + Does not look for matches further away than max_backward. + Writes the best match into |out|. + |out|->score is updated only if a better match is found. */ +static BROTLI_INLINE void FN(FindLongestMatch)( + HashLongestMatchQuickly* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, + const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, + const size_t cur_ix, const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + uint32_t* BROTLI_RESTRICT buckets = self->buckets_; + const size_t best_len_in = out->len; + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + int compare_char = data[cur_ix_masked + best_len_in]; + size_t key = FN(HashBytes)(&data[cur_ix_masked]); + size_t key_out; + score_t min_score = out->score; + score_t best_score = out->score; + size_t best_len = best_len_in; + size_t cached_backward = (size_t)distance_cache[0]; + size_t prev_ix = cur_ix - cached_backward; + out->len_code_delta = 0; + if (prev_ix < cur_ix) { + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char == data[prev_ix + best_len]) { + const size_t len = FindMatchLengthWithLimit( + &data[prev_ix], &data[cur_ix_masked], max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScoreUsingLastDistance(len); + if (best_score < score) { + out->len = len; + out->distance = cached_backward; + out->score = score; + if (BUCKET_SWEEP == 1) { + buckets[key] = (uint32_t)cur_ix; + return; + } else { + best_len = len; + best_score = score; + compare_char = data[cur_ix_masked + len]; + } + } + } + } + } + if (BUCKET_SWEEP == 1) { + size_t backward; + size_t len; + /* Only one to look for, don't bother to prepare for a loop. */ + prev_ix = buckets[key]; + buckets[key] = (uint32_t)cur_ix; + backward = cur_ix - prev_ix; + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char != data[prev_ix + best_len_in]) { + return; + } + if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) { + return; + } + len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + out->len = len; + out->distance = backward; + out->score = score; + return; + } + } + } else { + size_t keys[BUCKET_SWEEP]; + size_t i; + for (i = 0; i < BUCKET_SWEEP; ++i) { + keys[i] = (key + (i << 3)) & BUCKET_MASK; + } + key_out = keys[(cur_ix & BUCKET_SWEEP_MASK) >> 3]; + for (i = 0; i < BUCKET_SWEEP; ++i) { + size_t len; + size_t backward; + prev_ix = buckets[keys[i]]; + backward = cur_ix - prev_ix; + prev_ix &= (uint32_t)ring_buffer_mask; + if (compare_char != data[prev_ix + best_len]) { + continue; + } + if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) { + continue; + } + len = FindMatchLengthWithLimit(&data[prev_ix], + &data[cur_ix_masked], + max_length); + if (len >= 4) { + const score_t score = BackwardReferenceScore(len, backward); + if (best_score < score) { + best_len = len; + out->len = len; + compare_char = data[cur_ix_masked + len]; + best_score = score; + out->score = score; + out->distance = backward; + } + } + } + } + if (USE_DICTIONARY && min_score == out->score) { + SearchInStaticDictionary(dictionary, + self->common, &data[cur_ix_masked], max_length, dictionary_distance, + max_distance, out, BROTLI_TRUE); + } + if (BUCKET_SWEEP != 1) { + buckets[key_out] = (uint32_t)cur_ix; + } +} + +#undef BUCKET_SWEEP_MASK +#undef BUCKET_SWEEP +#undef BUCKET_MASK +#undef BUCKET_SIZE + +#undef HashLongestMatchQuickly +#undef USE_DICTIONARY +#undef HASH_LEN +#undef BUCKET_SWEEP_BITS +#undef BUCKET_BITS +#undef HASHER + +/* fast large window hashers */ + +#define HASHER() HROLLING_FAST +#define CHUNKLEN 32 +#define JUMP 4 +#define NUMBUCKETS 16777216 +#define MASK ((NUMBUCKETS * 64) - 1) +/* NOLINT(build/header_guard) */ +/* Copyright 2018 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, JUMP, NUMBUCKETS, MASK, CHUNKLEN */ +/* NUMBUCKETS / (MASK + 1) = probability of storing and using hash code. */ +/* JUMP = skip bytes for speedup */ + +/* Rolling hash for long distance long string matches. Stores one position + per bucket, bucket key is computed over a long region. */ + +#define HashRolling HASHER() + +static const uint32_t FN(kRollingHashMul32) = 69069; +static const uint32_t FN(kInvalidPos) = 0xffffffff; + +/* This hasher uses a longer forward length, but returning a higher value here + will hurt compression by the main hasher when combined with a composite + hasher. The hasher tests for forward itself instead. */ +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; } + +/* Computes a code from a single byte. A lookup table of 256 values could be + used, but simply adding 1 works about as good. */ +static uint32_t FN(HashByte)(uint8_t byte) { + return (uint32_t)byte + 1u; +} + +static uint32_t FN(HashRollingFunctionInitial)(uint32_t state, uint8_t add, + uint32_t factor) { + return (uint32_t)(factor * state + FN(HashByte)(add)); +} + +static uint32_t FN(HashRollingFunction)(uint32_t state, uint8_t add, + uint8_t rem, uint32_t factor, + uint32_t factor_remove) { + return (uint32_t)(factor * state + + FN(HashByte)(add) - factor_remove * FN(HashByte)(rem)); +} + +typedef struct HashRolling { + uint32_t state; + uint32_t* table; + size_t next_ix; + + uint32_t chunk_len; + uint32_t factor; + uint32_t factor_remove; +} HashRolling; + +static void FN(Initialize)( + HasherCommon* common, HashRolling* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + size_t i; + self->state = 0; + self->next_ix = 0; + + self->factor = FN(kRollingHashMul32); + + /* Compute the factor of the oldest byte to remove: factor**steps modulo + 0xffffffff (the multiplications rely on 32-bit overflow) */ + self->factor_remove = 1; + for (i = 0; i < CHUNKLEN; i += JUMP) { + self->factor_remove *= self->factor; + } + + self->table = (uint32_t*)common->extra[0]; + for (i = 0; i < NUMBUCKETS; i++) { + self->table[i] = FN(kInvalidPos); + } + + BROTLI_UNUSED(params); +} + +static void FN(Prepare)(HashRolling* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + size_t i; + /* Too small size, cannot use this hasher. */ + if (input_size < CHUNKLEN) return; + self->state = 0; + for (i = 0; i < CHUNKLEN; i += JUMP) { + self->state = FN(HashRollingFunctionInitial)( + self->state, data[i], self->factor); + } + BROTLI_UNUSED(one_shot); +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + BROTLI_UNUSED(params); + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = NUMBUCKETS * sizeof(uint32_t); +} + +static BROTLI_INLINE void FN(Store)(HashRolling* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + BROTLI_UNUSED(self); + BROTLI_UNUSED(data); + BROTLI_UNUSED(mask); + BROTLI_UNUSED(ix); +} + +static BROTLI_INLINE void FN(StoreRange)(HashRolling* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + BROTLI_UNUSED(self); + BROTLI_UNUSED(data); + BROTLI_UNUSED(mask); + BROTLI_UNUSED(ix_start); + BROTLI_UNUSED(ix_end); +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashRolling* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ring_buffer_mask) { + /* In this case we must re-initialize the hasher from scratch from the + current position. */ + size_t position_masked; + size_t available = num_bytes; + if ((position & (JUMP - 1)) != 0) { + size_t diff = JUMP - (position & (JUMP - 1)); + available = (diff > available) ? 0 : (available - diff); + position += diff; + } + position_masked = position & ring_buffer_mask; + /* wrapping around ringbuffer not handled. */ + if (available > ring_buffer_mask - position_masked) { + available = ring_buffer_mask - position_masked; + } + + FN(Prepare)(self, BROTLI_FALSE, available, + ringbuffer + (position & ring_buffer_mask)); + self->next_ix = position; + BROTLI_UNUSED(num_bytes); +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashRolling* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + BROTLI_UNUSED(self); + BROTLI_UNUSED(distance_cache); +} + +static BROTLI_INLINE void FN(FindLongestMatch)( + HashRolling* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, + const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, + const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + size_t pos; + + if ((cur_ix & (JUMP - 1)) != 0) return; + + /* Not enough lookahead */ + if (max_length < CHUNKLEN) return; + + for (pos = self->next_ix; pos <= cur_ix; pos += JUMP) { + uint32_t code = self->state & MASK; + + uint8_t rem = data[pos & ring_buffer_mask]; + uint8_t add = data[(pos + CHUNKLEN) & ring_buffer_mask]; + size_t found_ix = FN(kInvalidPos); + + self->state = FN(HashRollingFunction)( + self->state, add, rem, self->factor, self->factor_remove); + + if (code < NUMBUCKETS) { + found_ix = self->table[code]; + self->table[code] = (uint32_t)pos; + if (pos == cur_ix && found_ix != FN(kInvalidPos)) { + /* The cast to 32-bit makes backward distances up to 4GB work even + if cur_ix is above 4GB, despite using 32-bit values in the table. */ + size_t backward = (uint32_t)(cur_ix - found_ix); + if (backward <= max_backward) { + const size_t found_ix_masked = found_ix & ring_buffer_mask; + const size_t len = FindMatchLengthWithLimit(&data[found_ix_masked], + &data[cur_ix_masked], + max_length); + if (len >= 4 && len > out->len) { + score_t score = BackwardReferenceScore(len, backward); + if (score > out->score) { + out->len = len; + out->distance = backward; + out->score = score; + out->len_code_delta = 0; + } + } + } + } + } + } + + self->next_ix = cur_ix + JUMP; + + /* NOTE: this hasher does not search in the dictionary. It is used as + backup-hasher, the main hasher already searches in it. */ + BROTLI_UNUSED(dictionary); + BROTLI_UNUSED(distance_cache); + BROTLI_UNUSED(dictionary_distance); + BROTLI_UNUSED(max_distance); +} + +#undef HashRolling +#undef JUMP +#undef HASHER + + +#define HASHER() HROLLING +#define JUMP 1 +/* NOLINT(build/header_guard) */ +/* Copyright 2018 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, JUMP, NUMBUCKETS, MASK, CHUNKLEN */ +/* NUMBUCKETS / (MASK + 1) = probability of storing and using hash code. */ +/* JUMP = skip bytes for speedup */ + +/* Rolling hash for long distance long string matches. Stores one position + per bucket, bucket key is computed over a long region. */ + +#define HashRolling HASHER() + +static const uint32_t FN(kRollingHashMul32) = 69069; +static const uint32_t FN(kInvalidPos) = 0xffffffff; + +/* This hasher uses a longer forward length, but returning a higher value here + will hurt compression by the main hasher when combined with a composite + hasher. The hasher tests for forward itself instead. */ +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; } + +/* Computes a code from a single byte. A lookup table of 256 values could be + used, but simply adding 1 works about as good. */ +static uint32_t FN(HashByte)(uint8_t byte) { + return (uint32_t)byte + 1u; +} + +static uint32_t FN(HashRollingFunctionInitial)(uint32_t state, uint8_t add, + uint32_t factor) { + return (uint32_t)(factor * state + FN(HashByte)(add)); +} + +static uint32_t FN(HashRollingFunction)(uint32_t state, uint8_t add, + uint8_t rem, uint32_t factor, + uint32_t factor_remove) { + return (uint32_t)(factor * state + + FN(HashByte)(add) - factor_remove * FN(HashByte)(rem)); +} + +typedef struct HashRolling { + uint32_t state; + uint32_t* table; + size_t next_ix; + + uint32_t chunk_len; + uint32_t factor; + uint32_t factor_remove; +} HashRolling; + +static void FN(Initialize)( + HasherCommon* common, HashRolling* BROTLI_RESTRICT self, + const BrotliEncoderParams* params) { + size_t i; + self->state = 0; + self->next_ix = 0; + + self->factor = FN(kRollingHashMul32); + + /* Compute the factor of the oldest byte to remove: factor**steps modulo + 0xffffffff (the multiplications rely on 32-bit overflow) */ + self->factor_remove = 1; + for (i = 0; i < CHUNKLEN; i += JUMP) { + self->factor_remove *= self->factor; + } + + self->table = (uint32_t*)common->extra[0]; + for (i = 0; i < NUMBUCKETS; i++) { + self->table[i] = FN(kInvalidPos); + } + + BROTLI_UNUSED(params); +} + +static void FN(Prepare)(HashRolling* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + size_t i; + /* Too small size, cannot use this hasher. */ + if (input_size < CHUNKLEN) return; + self->state = 0; + for (i = 0; i < CHUNKLEN; i += JUMP) { + self->state = FN(HashRollingFunctionInitial)( + self->state, data[i], self->factor); + } + BROTLI_UNUSED(one_shot); +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + BROTLI_UNUSED(params); + BROTLI_UNUSED(one_shot); + BROTLI_UNUSED(input_size); + alloc_size[0] = NUMBUCKETS * sizeof(uint32_t); +} + +static BROTLI_INLINE void FN(Store)(HashRolling* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + BROTLI_UNUSED(self); + BROTLI_UNUSED(data); + BROTLI_UNUSED(mask); + BROTLI_UNUSED(ix); +} + +static BROTLI_INLINE void FN(StoreRange)(HashRolling* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, + const size_t ix_start, const size_t ix_end) { + BROTLI_UNUSED(self); + BROTLI_UNUSED(data); + BROTLI_UNUSED(mask); + BROTLI_UNUSED(ix_start); + BROTLI_UNUSED(ix_end); +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashRolling* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ring_buffer_mask) { + /* In this case we must re-initialize the hasher from scratch from the + current position. */ + size_t position_masked; + size_t available = num_bytes; + if ((position & (JUMP - 1)) != 0) { + size_t diff = JUMP - (position & (JUMP - 1)); + available = (diff > available) ? 0 : (available - diff); + position += diff; + } + position_masked = position & ring_buffer_mask; + /* wrapping around ringbuffer not handled. */ + if (available > ring_buffer_mask - position_masked) { + available = ring_buffer_mask - position_masked; + } + + FN(Prepare)(self, BROTLI_FALSE, available, + ringbuffer + (position & ring_buffer_mask)); + self->next_ix = position; + BROTLI_UNUSED(num_bytes); +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashRolling* BROTLI_RESTRICT self, + int* BROTLI_RESTRICT distance_cache) { + BROTLI_UNUSED(self); + BROTLI_UNUSED(distance_cache); +} + +static BROTLI_INLINE void FN(FindLongestMatch)( + HashRolling* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, + const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, + const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + size_t pos; + + if ((cur_ix & (JUMP - 1)) != 0) return; + + /* Not enough lookahead */ + if (max_length < CHUNKLEN) return; + + for (pos = self->next_ix; pos <= cur_ix; pos += JUMP) { + uint32_t code = self->state & MASK; + + uint8_t rem = data[pos & ring_buffer_mask]; + uint8_t add = data[(pos + CHUNKLEN) & ring_buffer_mask]; + size_t found_ix = FN(kInvalidPos); + + self->state = FN(HashRollingFunction)( + self->state, add, rem, self->factor, self->factor_remove); + + if (code < NUMBUCKETS) { + found_ix = self->table[code]; + self->table[code] = (uint32_t)pos; + if (pos == cur_ix && found_ix != FN(kInvalidPos)) { + /* The cast to 32-bit makes backward distances up to 4GB work even + if cur_ix is above 4GB, despite using 32-bit values in the table. */ + size_t backward = (uint32_t)(cur_ix - found_ix); + if (backward <= max_backward) { + const size_t found_ix_masked = found_ix & ring_buffer_mask; + const size_t len = FindMatchLengthWithLimit(&data[found_ix_masked], + &data[cur_ix_masked], + max_length); + if (len >= 4 && len > out->len) { + score_t score = BackwardReferenceScore(len, backward); + if (score > out->score) { + out->len = len; + out->distance = backward; + out->score = score; + out->len_code_delta = 0; + } + } + } + } + } + } + + self->next_ix = cur_ix + JUMP; + + /* NOTE: this hasher does not search in the dictionary. It is used as + backup-hasher, the main hasher already searches in it. */ + BROTLI_UNUSED(dictionary); + BROTLI_UNUSED(distance_cache); + BROTLI_UNUSED(dictionary_distance); + BROTLI_UNUSED(max_distance); +} + +#undef HashRolling +#undef MASK +#undef NUMBUCKETS +#undef JUMP +#undef CHUNKLEN +#undef HASHER + +#define HASHER() H35 +#define HASHER_A H3 +#define HASHER_B HROLLING_FAST +/* NOLINT(build/header_guard) */ +/* Copyright 2018 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, HASHER_A, HASHER_B */ + +/* Composite hasher: This hasher allows to combine two other hashers, HASHER_A + and HASHER_B. */ + +#define HashComposite HASHER() + +#define FN_A(X) EXPAND_CAT(X, HASHER_A) +#define FN_B(X) EXPAND_CAT(X, HASHER_B) + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { + size_t a = FN_A(HashTypeLength)(); + size_t b = FN_B(HashTypeLength)(); + return a > b ? a : b; +} + +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { + size_t a = FN_A(StoreLookahead)(); + size_t b = FN_B(StoreLookahead)(); + return a > b ? a : b; +} + +typedef struct HashComposite { + HASHER_A ha; + HASHER_B hb; + HasherCommon ha_common; + HasherCommon hb_common; + + /* Shortcuts. */ + HasherCommon* common; + + BROTLI_BOOL fresh; + const BrotliEncoderParams* params; +} HashComposite; + +static void FN(Initialize)(HasherCommon* common, + HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { + self->common = common; + + self->ha_common = *self->common; + self->hb_common = *self->common; + self->fresh = BROTLI_TRUE; + self->params = params; + /* TODO(lode): Initialize of the hashers is deferred to Prepare (and params + remembered here) because we don't get the one_shot and input_size params + here that are needed to know the memory size of them. Instead provide + those params to all hashers FN(Initialize) */ +} + +static void FN(Prepare)( + HashComposite* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + if (self->fresh) { + self->fresh = BROTLI_FALSE; + self->ha_common.extra[0] = self->common->extra[0]; + self->ha_common.extra[1] = self->common->extra[1]; + self->ha_common.extra[2] = NULL; + self->ha_common.extra[3] = NULL; + self->hb_common.extra[0] = self->common->extra[2]; + self->hb_common.extra[1] = self->common->extra[3]; + self->hb_common.extra[2] = NULL; + self->hb_common.extra[3] = NULL; + + FN_A(Initialize)(&self->ha_common, &self->ha, self->params); + FN_B(Initialize)(&self->hb_common, &self->hb, self->params); + } + FN_A(Prepare)(&self->ha, one_shot, input_size, data); + FN_B(Prepare)(&self->hb, one_shot, input_size, data); +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + size_t alloc_size_a[4] = {0}; + size_t alloc_size_b[4] = {0}; + FN_A(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_a); + FN_B(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_b); + /* Should never happen. */ + if (alloc_size_a[2] != 0 || alloc_size_a[3] != 0) exit(EXIT_FAILURE); + if (alloc_size_b[2] != 0 || alloc_size_b[3] != 0) exit(EXIT_FAILURE); + alloc_size[0] = alloc_size_a[0]; + alloc_size[1] = alloc_size_a[1]; + alloc_size[2] = alloc_size_b[0]; + alloc_size[3] = alloc_size_b[1]; +} + +static BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + FN_A(Store)(&self->ha, data, mask, ix); + FN_B(Store)(&self->hb, data, mask, ix); +} + +static BROTLI_INLINE void FN(StoreRange)( + HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, + const size_t mask, const size_t ix_start, + const size_t ix_end) { + FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end); + FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end); +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashComposite* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ring_buffer_mask) { + FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position, + ringbuffer, ring_buffer_mask); + FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position, + ringbuffer, ring_buffer_mask); +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) { + FN_A(PrepareDistanceCache)(&self->ha, distance_cache); + FN_B(PrepareDistanceCache)(&self->hb, distance_cache); +} + +static BROTLI_INLINE void FN(FindLongestMatch)( + HashComposite* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, + const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, + const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask, + distance_cache, cur_ix, max_length, max_backward, dictionary_distance, + max_distance, out); + FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask, + distance_cache, cur_ix, max_length, max_backward, dictionary_distance, + max_distance, out); +} + +#undef HashComposite +#undef HASHER_A +#undef HASHER_B +#undef HASHER + +#define HASHER() H55 +#define HASHER_A H54 +#define HASHER_B HROLLING_FAST +/* NOLINT(build/header_guard) */ +/* Copyright 2018 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, HASHER_A, HASHER_B */ + +/* Composite hasher: This hasher allows to combine two other hashers, HASHER_A + and HASHER_B. */ + +#define HashComposite HASHER() + +#define FN_A(X) EXPAND_CAT(X, HASHER_A) +#define FN_B(X) EXPAND_CAT(X, HASHER_B) + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { + size_t a = FN_A(HashTypeLength)(); + size_t b = FN_B(HashTypeLength)(); + return a > b ? a : b; +} + +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { + size_t a = FN_A(StoreLookahead)(); + size_t b = FN_B(StoreLookahead)(); + return a > b ? a : b; +} + +typedef struct HashComposite { + HASHER_A ha; + HASHER_B hb; + HasherCommon ha_common; + HasherCommon hb_common; + + /* Shortcuts. */ + HasherCommon* common; + + BROTLI_BOOL fresh; + const BrotliEncoderParams* params; +} HashComposite; + +static void FN(Initialize)(HasherCommon* common, + HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { + self->common = common; + + self->ha_common = *self->common; + self->hb_common = *self->common; + self->fresh = BROTLI_TRUE; + self->params = params; + /* TODO(lode): Initialize of the hashers is deferred to Prepare (and params + remembered here) because we don't get the one_shot and input_size params + here that are needed to know the memory size of them. Instead provide + those params to all hashers FN(Initialize) */ +} + +static void FN(Prepare)( + HashComposite* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + if (self->fresh) { + self->fresh = BROTLI_FALSE; + self->ha_common.extra[0] = self->common->extra[0]; + self->ha_common.extra[1] = self->common->extra[1]; + self->ha_common.extra[2] = NULL; + self->ha_common.extra[3] = NULL; + self->hb_common.extra[0] = self->common->extra[2]; + self->hb_common.extra[1] = self->common->extra[3]; + self->hb_common.extra[2] = NULL; + self->hb_common.extra[3] = NULL; + + FN_A(Initialize)(&self->ha_common, &self->ha, self->params); + FN_B(Initialize)(&self->hb_common, &self->hb, self->params); + } + FN_A(Prepare)(&self->ha, one_shot, input_size, data); + FN_B(Prepare)(&self->hb, one_shot, input_size, data); +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + size_t alloc_size_a[4] = {0}; + size_t alloc_size_b[4] = {0}; + FN_A(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_a); + FN_B(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_b); + /* Should never happen. */ + if (alloc_size_a[2] != 0 || alloc_size_a[3] != 0) exit(EXIT_FAILURE); + if (alloc_size_b[2] != 0 || alloc_size_b[3] != 0) exit(EXIT_FAILURE); + alloc_size[0] = alloc_size_a[0]; + alloc_size[1] = alloc_size_a[1]; + alloc_size[2] = alloc_size_b[0]; + alloc_size[3] = alloc_size_b[1]; +} + +static BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + FN_A(Store)(&self->ha, data, mask, ix); + FN_B(Store)(&self->hb, data, mask, ix); +} + +static BROTLI_INLINE void FN(StoreRange)( + HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, + const size_t mask, const size_t ix_start, + const size_t ix_end) { + FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end); + FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end); +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashComposite* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ring_buffer_mask) { + FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position, + ringbuffer, ring_buffer_mask); + FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position, + ringbuffer, ring_buffer_mask); +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) { + FN_A(PrepareDistanceCache)(&self->ha, distance_cache); + FN_B(PrepareDistanceCache)(&self->hb, distance_cache); +} + +static BROTLI_INLINE void FN(FindLongestMatch)( + HashComposite* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, + const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, + const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask, + distance_cache, cur_ix, max_length, max_backward, dictionary_distance, + max_distance, out); + FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask, + distance_cache, cur_ix, max_length, max_backward, dictionary_distance, + max_distance, out); +} + +#undef HashComposite +#undef HASHER_A +#undef HASHER_B +#undef HASHER + +#define HASHER() H65 +#define HASHER_A H6 +#define HASHER_B HROLLING +/* NOLINT(build/header_guard) */ +/* Copyright 2018 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, HASHER_A, HASHER_B */ + +/* Composite hasher: This hasher allows to combine two other hashers, HASHER_A + and HASHER_B. */ + +#define HashComposite HASHER() + +#define FN_A(X) EXPAND_CAT(X, HASHER_A) +#define FN_B(X) EXPAND_CAT(X, HASHER_B) + +static BROTLI_INLINE size_t FN(HashTypeLength)(void) { + size_t a = FN_A(HashTypeLength)(); + size_t b = FN_B(HashTypeLength)(); + return a > b ? a : b; +} + +static BROTLI_INLINE size_t FN(StoreLookahead)(void) { + size_t a = FN_A(StoreLookahead)(); + size_t b = FN_B(StoreLookahead)(); + return a > b ? a : b; +} + +typedef struct HashComposite { + HASHER_A ha; + HASHER_B hb; + HasherCommon ha_common; + HasherCommon hb_common; + + /* Shortcuts. */ + HasherCommon* common; + + BROTLI_BOOL fresh; + const BrotliEncoderParams* params; +} HashComposite; + +static void FN(Initialize)(HasherCommon* common, + HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { + self->common = common; + + self->ha_common = *self->common; + self->hb_common = *self->common; + self->fresh = BROTLI_TRUE; + self->params = params; + /* TODO(lode): Initialize of the hashers is deferred to Prepare (and params + remembered here) because we don't get the one_shot and input_size params + here that are needed to know the memory size of them. Instead provide + those params to all hashers FN(Initialize) */ +} + +static void FN(Prepare)( + HashComposite* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, + size_t input_size, const uint8_t* BROTLI_RESTRICT data) { + if (self->fresh) { + self->fresh = BROTLI_FALSE; + self->ha_common.extra[0] = self->common->extra[0]; + self->ha_common.extra[1] = self->common->extra[1]; + self->ha_common.extra[2] = NULL; + self->ha_common.extra[3] = NULL; + self->hb_common.extra[0] = self->common->extra[2]; + self->hb_common.extra[1] = self->common->extra[3]; + self->hb_common.extra[2] = NULL; + self->hb_common.extra[3] = NULL; + + FN_A(Initialize)(&self->ha_common, &self->ha, self->params); + FN_B(Initialize)(&self->hb_common, &self->hb, self->params); + } + FN_A(Prepare)(&self->ha, one_shot, input_size, data); + FN_B(Prepare)(&self->hb, one_shot, input_size, data); +} + +static BROTLI_INLINE void FN(HashMemAllocInBytes)( + const BrotliEncoderParams* params, BROTLI_BOOL one_shot, + size_t input_size, size_t* alloc_size) { + size_t alloc_size_a[4] = {0}; + size_t alloc_size_b[4] = {0}; + FN_A(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_a); + FN_B(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_b); + /* Should never happen. */ + if (alloc_size_a[2] != 0 || alloc_size_a[3] != 0) exit(EXIT_FAILURE); + if (alloc_size_b[2] != 0 || alloc_size_b[3] != 0) exit(EXIT_FAILURE); + alloc_size[0] = alloc_size_a[0]; + alloc_size[1] = alloc_size_a[1]; + alloc_size[2] = alloc_size_b[0]; + alloc_size[3] = alloc_size_b[1]; +} + +static BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self, + const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { + FN_A(Store)(&self->ha, data, mask, ix); + FN_B(Store)(&self->hb, data, mask, ix); +} + +static BROTLI_INLINE void FN(StoreRange)( + HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, + const size_t mask, const size_t ix_start, + const size_t ix_end) { + FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end); + FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end); +} + +static BROTLI_INLINE void FN(StitchToPreviousBlock)( + HashComposite* BROTLI_RESTRICT self, + size_t num_bytes, size_t position, const uint8_t* ringbuffer, + size_t ring_buffer_mask) { + FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position, + ringbuffer, ring_buffer_mask); + FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position, + ringbuffer, ring_buffer_mask); +} + +static BROTLI_INLINE void FN(PrepareDistanceCache)( + HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) { + FN_A(PrepareDistanceCache)(&self->ha, distance_cache); + FN_B(PrepareDistanceCache)(&self->hb, distance_cache); +} + +static BROTLI_INLINE void FN(FindLongestMatch)( + HashComposite* BROTLI_RESTRICT self, + const BrotliEncoderDictionary* dictionary, + const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, + const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, + const size_t max_length, const size_t max_backward, + const size_t dictionary_distance, const size_t max_distance, + HasherSearchResult* BROTLI_RESTRICT out) { + FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask, + distance_cache, cur_ix, max_length, max_backward, dictionary_distance, + max_distance, out); + FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask, + distance_cache, cur_ix, max_length, max_backward, dictionary_distance, + max_distance, out); +} + +#undef HashComposite +#undef HASHER_A +#undef HASHER_B +#undef HASHER + +#undef FN +#undef CAT +#undef EXPAND_CAT + +#define FOR_SIMPLE_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54) +#define FOR_COMPOSITE_HASHERS(H) H(35) H(55) H(65) +#define FOR_GENERIC_HASHERS(H) FOR_SIMPLE_HASHERS(H) FOR_COMPOSITE_HASHERS(H) +#define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10) + +typedef struct { + HasherCommon common; + + union { +#define MEMBER_(N) \ + H ## N _H ## N; + FOR_ALL_HASHERS(MEMBER_) +#undef MEMBER_ + } privat; +} Hasher; + +/* MUST be invoked before any other method. */ +static BROTLI_INLINE void HasherInit(Hasher* hasher) { + hasher->common.is_setup_ = BROTLI_FALSE; + hasher->common.extra[0] = NULL; + hasher->common.extra[1] = NULL; + hasher->common.extra[2] = NULL; + hasher->common.extra[3] = NULL; +} + +static BROTLI_INLINE void DestroyHasher(MemoryManager* m, Hasher* hasher) { + if (hasher->common.extra[0] != NULL) BROTLI_FREE(m, hasher->common.extra[0]); + if (hasher->common.extra[1] != NULL) BROTLI_FREE(m, hasher->common.extra[1]); + if (hasher->common.extra[2] != NULL) BROTLI_FREE(m, hasher->common.extra[2]); + if (hasher->common.extra[3] != NULL) BROTLI_FREE(m, hasher->common.extra[3]); +} + +static BROTLI_INLINE void HasherReset(Hasher* hasher) { + hasher->common.is_prepared_ = BROTLI_FALSE; +} + +static BROTLI_INLINE void HasherSize(const BrotliEncoderParams* params, + BROTLI_BOOL one_shot, const size_t input_size, size_t* alloc_size) { + switch (params->hasher.type) { +#define SIZE_(N) \ + case N: \ + HashMemAllocInBytesH ## N(params, one_shot, input_size, alloc_size); \ + break; + FOR_ALL_HASHERS(SIZE_) +#undef SIZE_ + default: + break; + } +} + +static BROTLI_INLINE void HasherSetup(MemoryManager* m, Hasher* hasher, + BrotliEncoderParams* params, const uint8_t* data, size_t position, + size_t input_size, BROTLI_BOOL is_last) { + BROTLI_BOOL one_shot = (position == 0 && is_last); + if (!hasher->common.is_setup_) { + size_t alloc_size[4] = {0}; + size_t i; + ChooseHasher(params, ¶ms->hasher); + hasher->common.params = params->hasher; + hasher->common.dict_num_lookups = 0; + hasher->common.dict_num_matches = 0; + HasherSize(params, one_shot, input_size, alloc_size); + for (i = 0; i < 4; ++i) { + if (alloc_size[i] == 0) continue; + hasher->common.extra[i] = BROTLI_ALLOC(m, uint8_t, alloc_size[i]); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.extra[i])) return; + } + switch (hasher->common.params.type) { +#define INITIALIZE_(N) \ + case N: \ + InitializeH ## N(&hasher->common, \ + &hasher->privat._H ## N, params); \ + break; + FOR_ALL_HASHERS(INITIALIZE_); +#undef INITIALIZE_ + default: + break; + } + HasherReset(hasher); + hasher->common.is_setup_ = BROTLI_TRUE; + } + + if (!hasher->common.is_prepared_) { + switch (hasher->common.params.type) { +#define PREPARE_(N) \ + case N: \ + PrepareH ## N( \ + &hasher->privat._H ## N, \ + one_shot, input_size, data); \ + break; + FOR_ALL_HASHERS(PREPARE_) +#undef PREPARE_ + default: break; + } + hasher->common.is_prepared_ = BROTLI_TRUE; + } +} + +static BROTLI_INLINE void InitOrStitchToPreviousBlock( + MemoryManager* m, Hasher* hasher, const uint8_t* data, size_t mask, + BrotliEncoderParams* params, size_t position, size_t input_size, + BROTLI_BOOL is_last) { + HasherSetup(m, hasher, params, data, position, input_size, is_last); + if (BROTLI_IS_OOM(m)) return; + switch (hasher->common.params.type) { +#define INIT_(N) \ + case N: \ + StitchToPreviousBlockH ## N( \ + &hasher->privat._H ## N, \ + input_size, position, data, mask); \ + break; + FOR_ALL_HASHERS(INIT_) +#undef INIT_ + default: break; + } +} + +/* NB: when seamless dictionary-ring-buffer copies are implemented, don't forget + to add proper guards for non-zero-BROTLI_PARAM_STREAM_OFFSET. */ +static BROTLI_INLINE void FindCompoundDictionaryMatch( + const PreparedDictionary* self, const uint8_t* BROTLI_RESTRICT data, + const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, + const size_t cur_ix, const size_t max_length, const size_t distance_offset, + const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) { + const uint32_t source_size = self->source_size; + const size_t boundary = distance_offset - source_size; + const uint32_t hash_bits = self->hash_bits; + const uint32_t bucket_bits = self->bucket_bits; + const uint32_t slot_bits = self->slot_bits; + + const uint32_t hash_shift = 64u - bucket_bits; + const uint32_t slot_mask = (~((uint32_t)0U)) >> (32 - slot_bits); + const uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits); + + const uint32_t* slot_offsets = (uint32_t*)(&self[1]); + const uint16_t* heads = (uint16_t*)(&slot_offsets[1u << slot_bits]); + const uint32_t* items = (uint32_t*)(&heads[1u << bucket_bits]); + const uint8_t* source = NULL; + + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + score_t best_score = out->score; + size_t best_len = out->len; + size_t i; + const uint64_t h = + (BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]) & hash_mask) * + kPreparedDictionaryHashMul64Long; + const uint32_t key = (uint32_t)(h >> hash_shift); + const uint32_t slot = key & slot_mask; + const uint32_t head = heads[key]; + const uint32_t* BROTLI_RESTRICT chain = &items[slot_offsets[slot] + head]; + uint32_t item = (head == 0xFFFF) ? 1 : 0; + + const void* tail = (void*)&items[self->num_items]; + if (self->magic == kPreparedDictionaryMagic) { + source = (const uint8_t*)tail; + } else { + /* kLeanPreparedDictionaryMagic */ + source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail); + } + + for (i = 0; i < 4; ++i) { + const size_t distance = (size_t)distance_cache[i]; + size_t offset; + size_t limit; + size_t len; + if (distance <= boundary || distance > distance_offset) continue; + offset = distance_offset - distance; + limit = source_size - offset; + limit = limit > max_length ? max_length : limit; + len = FindMatchLengthWithLimit(&source[offset], &data[cur_ix_masked], + limit); + if (len >= 2) { + score_t score = BackwardReferenceScoreUsingLastDistance(len); + if (best_score < score) { + if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i); + if (best_score < score) { + best_score = score; + if (len > best_len) best_len = len; + out->len = len; + out->len_code_delta = 0; + out->distance = distance; + out->score = best_score; + } + } + } + } + while (item == 0) { + size_t offset; + size_t distance; + size_t limit; + item = *chain; + chain++; + offset = item & 0x7FFFFFFF; + item &= 0x80000000; + distance = distance_offset - offset; + limit = source_size - offset; + limit = (limit > max_length) ? max_length : limit; + if (distance > max_distance) continue; + if (cur_ix_masked + best_len > ring_buffer_mask || + best_len >= limit || + data[cur_ix_masked + best_len] != source[offset + best_len]) { + continue; + } + { + const size_t len = FindMatchLengthWithLimit(&source[offset], + &data[cur_ix_masked], + limit); + if (len >= 4) { + score_t score = BackwardReferenceScore(len, distance); + if (best_score < score) { + best_score = score; + best_len = len; + out->len = best_len; + out->len_code_delta = 0; + out->distance = distance; + out->score = best_score; + } + } + } + } +} + +/* NB: when seamless dictionary-ring-buffer copies are implemented, don't forget + to add proper guards for non-zero-BROTLI_PARAM_STREAM_OFFSET. */ +static BROTLI_INLINE size_t FindAllCompoundDictionaryMatches( + const PreparedDictionary* self, const uint8_t* BROTLI_RESTRICT data, + const size_t ring_buffer_mask, const size_t cur_ix, const size_t min_length, + const size_t max_length, const size_t distance_offset, + const size_t max_distance, BackwardMatch* matches, size_t match_limit) { + const uint32_t source_size = self->source_size; + const uint32_t hash_bits = self->hash_bits; + const uint32_t bucket_bits = self->bucket_bits; + const uint32_t slot_bits = self->slot_bits; + + const uint32_t hash_shift = 64u - bucket_bits; + const uint32_t slot_mask = (~((uint32_t)0U)) >> (32 - slot_bits); + const uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits); + + const uint32_t* slot_offsets = (uint32_t*)(&self[1]); + const uint16_t* heads = (uint16_t*)(&slot_offsets[1u << slot_bits]); + const uint32_t* items = (uint32_t*)(&heads[1u << bucket_bits]); + const uint8_t* source = NULL; + + const size_t cur_ix_masked = cur_ix & ring_buffer_mask; + size_t best_len = min_length; + const uint64_t h = + (BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]) & hash_mask) * + kPreparedDictionaryHashMul64Long; + const uint32_t key = (uint32_t)(h >> hash_shift); + const uint32_t slot = key & slot_mask; + const uint32_t head = heads[key]; + const uint32_t* BROTLI_RESTRICT chain = &items[slot_offsets[slot] + head]; + uint32_t item = (head == 0xFFFF) ? 1 : 0; + size_t found = 0; + + const void* tail = (void*)&items[self->num_items]; + if (self->magic == kPreparedDictionaryMagic) { + source = (const uint8_t*)tail; + } else { + /* kLeanPreparedDictionaryMagic */ + source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail); + } + + while (item == 0) { + size_t offset; + size_t distance; + size_t limit; + size_t len; + item = *chain; + chain++; + offset = item & 0x7FFFFFFF; + item &= 0x80000000; + distance = distance_offset - offset; + limit = source_size - offset; + limit = (limit > max_length) ? max_length : limit; + if (distance > max_distance) continue; + if (cur_ix_masked + best_len > ring_buffer_mask || + best_len >= limit || + data[cur_ix_masked + best_len] != source[offset + best_len]) { + continue; + } + len = FindMatchLengthWithLimit( + &source[offset], &data[cur_ix_masked], limit); + if (len > best_len) { + best_len = len; + InitBackwardMatch(matches++, distance, len); + found++; + if (found == match_limit) break; + } + } + return found; +} + +static BROTLI_INLINE void LookupCompoundDictionaryMatch( + const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data, + const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache, + const size_t cur_ix, const size_t max_length, + const size_t max_ring_buffer_distance, const size_t max_distance, + HasherSearchResult* sr) { + size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1; + size_t d; + for (d = 0; d < addon->num_chunks; ++d) { + /* Only one prepared dictionary type is currently supported. */ + FindCompoundDictionaryMatch( + (const PreparedDictionary*)addon->chunks[d], data, ring_buffer_mask, + distance_cache, cur_ix, max_length, + base_offset - addon->chunk_offsets[d], max_distance, sr); + } +} + +static BROTLI_INLINE size_t LookupAllCompoundDictionaryMatches( + const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data, + const size_t ring_buffer_mask, const size_t cur_ix, size_t min_length, + const size_t max_length, const size_t max_ring_buffer_distance, + const size_t max_distance, BackwardMatch* matches, + size_t match_limit) { + size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1; + size_t d; + size_t total_found = 0; + for (d = 0; d < addon->num_chunks; ++d) { + /* Only one prepared dictionary type is currently supported. */ + total_found += FindAllCompoundDictionaryMatches( + (const PreparedDictionary*)addon->chunks[d], data, ring_buffer_mask, + cur_ix, min_length, max_length, base_offset - addon->chunk_offsets[d], + max_distance, matches + total_found, match_limit - total_found); + if (total_found == match_limit) break; + if (total_found > 0) { + min_length = BackwardMatchLength(&matches[total_found - 1]); + } + } + return total_found; +} + +} + +#endif /* BROTLI_ENC_HASH_H_ */ diff --git a/third_party/brotli/enc/brotli_params.h b/third_party/brotli/enc/brotli_params.h new file mode 100644 index 00000000000..4564179d2d5 --- /dev/null +++ b/third_party/brotli/enc/brotli_params.h @@ -0,0 +1,47 @@ +/* Copyright 2017 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Parameters for the Brotli encoder with chosen quality levels. */ + +#ifndef BROTLI_ENC_PARAMS_H_ +#define BROTLI_ENC_PARAMS_H_ + +#include + +#include "encoder_dict.h" + +typedef struct BrotliHasherParams { + int type; + int bucket_bits; + int block_bits; + int num_last_distances_to_check; +} BrotliHasherParams; + +typedef struct BrotliDistanceParams { + uint32_t distance_postfix_bits; + uint32_t num_direct_distance_codes; + uint32_t alphabet_size_max; + uint32_t alphabet_size_limit; + size_t max_distance; +} BrotliDistanceParams; + +/* Encoding parameters */ +typedef struct BrotliEncoderParams { + BrotliEncoderMode mode; + int quality; + int lgwin; + int lgblock; + size_t stream_offset; + size_t size_hint; + BROTLI_BOOL disable_literal_context_modeling; + BROTLI_BOOL large_window; + BrotliHasherParams hasher; + BrotliDistanceParams dist; + /* TODO(eustas): rename to BrotliShared... */ + duckdb_brotli::SharedEncoderDictionary dictionary; +} BrotliEncoderParams; + +#endif /* BROTLI_ENC_PARAMS_H_ */ diff --git a/third_party/brotli/enc/cluster.cpp b/third_party/brotli/enc/cluster.cpp new file mode 100644 index 00000000000..90d19a694d3 --- /dev/null +++ b/third_party/brotli/enc/cluster.cpp @@ -0,0 +1,1025 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Functions for clustering similar histograms together. */ + +#include "cluster.h" + +#include + +#include "../common/brotli_platform.h" +#include "bit_cost.h" /* BrotliPopulationCost */ +#include "fast_log.h" +#include "histogram.h" +#include "memory.h" + +using namespace duckdb_brotli; + +static BROTLI_INLINE BROTLI_BOOL HistogramPairIsLess( + const HistogramPair* p1, const HistogramPair* p2) { + if (p1->cost_diff != p2->cost_diff) { + return TO_BROTLI_BOOL(p1->cost_diff > p2->cost_diff); + } + return TO_BROTLI_BOOL((p1->idx2 - p1->idx1) > (p2->idx2 - p2->idx1)); +} + +/* Returns entropy reduction of the context map when we combine two clusters. */ +static BROTLI_INLINE double ClusterCostDiff(size_t size_a, size_t size_b) { + size_t size_c = size_a + size_b; + return (double)size_a * FastLog2(size_a) + + (double)size_b * FastLog2(size_b) - + (double)size_c * FastLog2(size_c); +} + +#define CODE(X) X + +#define FN(X) duckdb_brotli:: X ## Literal +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, CODE */ + +#define HistogramType FN(Histogram) + +/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if + it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */ +BROTLI_INTERNAL void FN(BrotliCompareAndPushToQueue)( + const HistogramType* out, HistogramType* tmp, const uint32_t* cluster_size, + uint32_t idx1, uint32_t idx2, size_t max_num_pairs, HistogramPair* pairs, + size_t* num_pairs) CODE({ + BROTLI_BOOL is_good_pair = BROTLI_FALSE; + HistogramPair p; + p.idx1 = p.idx2 = 0; + p.cost_diff = p.cost_combo = 0; + if (idx1 == idx2) { + return; + } + if (idx2 < idx1) { + uint32_t t = idx2; + idx2 = idx1; + idx1 = t; + } + p.idx1 = idx1; + p.idx2 = idx2; + p.cost_diff = 0.5 * ClusterCostDiff(cluster_size[idx1], cluster_size[idx2]); + p.cost_diff -= out[idx1].bit_cost_; + p.cost_diff -= out[idx2].bit_cost_; + + if (out[idx1].total_count_ == 0) { + p.cost_combo = out[idx2].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else if (out[idx2].total_count_ == 0) { + p.cost_combo = out[idx1].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else { + double threshold = *num_pairs == 0 ? 1e99 : + BROTLI_MAX(double, 0.0, pairs[0].cost_diff); + double cost_combo; + *tmp = out[idx1]; + FN(HistogramAddHistogram)(tmp, &out[idx2]); + cost_combo = FN(BrotliPopulationCost)(tmp); + if (cost_combo < threshold - p.cost_diff) { + p.cost_combo = cost_combo; + is_good_pair = BROTLI_TRUE; + } + } + if (is_good_pair) { + p.cost_diff += p.cost_combo; + if (*num_pairs > 0 && HistogramPairIsLess(&pairs[0], &p)) { + /* Replace the top of the queue if needed. */ + if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = pairs[0]; + ++(*num_pairs); + } + pairs[0] = p; + } else if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = p; + ++(*num_pairs); + } + } +}) + +BROTLI_INTERNAL size_t FN(BrotliHistogramCombine)(HistogramType* out, + HistogramType* tmp, + uint32_t* cluster_size, + uint32_t* symbols, + uint32_t* clusters, + HistogramPair* pairs, + size_t num_clusters, + size_t symbols_size, + size_t max_clusters, + size_t max_num_pairs) CODE({ + double cost_diff_threshold = 0.0; + size_t min_cluster_size = 1; + size_t num_pairs = 0; + + { + /* We maintain a vector of histogram pairs, with the property that the pair + with the maximum bit cost reduction is the first. */ + size_t idx1; + for (idx1 = 0; idx1 < num_clusters; ++idx1) { + size_t idx2; + for (idx2 = idx1 + 1; idx2 < num_clusters; ++idx2) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, clusters[idx1], + clusters[idx2], max_num_pairs, &pairs[0], &num_pairs); + } + } + } + + while (num_clusters > min_cluster_size) { + uint32_t best_idx1; + uint32_t best_idx2; + size_t i; + if (pairs[0].cost_diff >= cost_diff_threshold) { + cost_diff_threshold = 1e99; + min_cluster_size = max_clusters; + continue; + } + /* Take the best pair from the top of heap. */ + best_idx1 = pairs[0].idx1; + best_idx2 = pairs[0].idx2; + FN(HistogramAddHistogram)(&out[best_idx1], &out[best_idx2]); + out[best_idx1].bit_cost_ = pairs[0].cost_combo; + cluster_size[best_idx1] += cluster_size[best_idx2]; + for (i = 0; i < symbols_size; ++i) { + if (symbols[i] == best_idx2) { + symbols[i] = best_idx1; + } + } + for (i = 0; i < num_clusters; ++i) { + if (clusters[i] == best_idx2) { + memmove(&clusters[i], &clusters[i + 1], + (num_clusters - i - 1) * sizeof(clusters[0])); + break; + } + } + --num_clusters; + { + /* Remove pairs intersecting the just combined best pair. */ + size_t copy_to_idx = 0; + for (i = 0; i < num_pairs; ++i) { + HistogramPair* p = &pairs[i]; + if (p->idx1 == best_idx1 || p->idx2 == best_idx1 || + p->idx1 == best_idx2 || p->idx2 == best_idx2) { + /* Remove invalid pair from the queue. */ + continue; + } + if (HistogramPairIsLess(&pairs[0], p)) { + /* Replace the top of the queue if needed. */ + HistogramPair front = pairs[0]; + pairs[0] = *p; + pairs[copy_to_idx] = front; + } else { + pairs[copy_to_idx] = *p; + } + ++copy_to_idx; + } + num_pairs = copy_to_idx; + } + + /* Push new pairs formed with the combined histogram to the heap. */ + for (i = 0; i < num_clusters; ++i) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, best_idx1, + clusters[i], max_num_pairs, &pairs[0], &num_pairs); + } + } + return num_clusters; +}) + +/* What is the bit cost of moving histogram from cur_symbol to candidate. */ +BROTLI_INTERNAL double FN(BrotliHistogramBitCostDistance)( + const HistogramType* histogram, const HistogramType* candidate, + HistogramType* tmp) CODE({ + if (histogram->total_count_ == 0) { + return 0.0; + } else { + *tmp = *histogram; + FN(HistogramAddHistogram)(tmp, candidate); + return FN(BrotliPopulationCost)(tmp) - candidate->bit_cost_; + } +}) + +/* Find the best 'out' histogram for each of the 'in' histograms. + When called, clusters[0..num_clusters) contains the unique values from + symbols[0..in_size), but this property is not preserved in this function. + Note: we assume that out[]->bit_cost_ is already up-to-date. */ +BROTLI_INTERNAL void FN(BrotliHistogramRemap)(const HistogramType* in, + size_t in_size, const uint32_t* clusters, size_t num_clusters, + HistogramType* out, HistogramType* tmp, uint32_t* symbols) CODE({ + size_t i; + for (i = 0; i < in_size; ++i) { + uint32_t best_out = i == 0 ? symbols[0] : symbols[i - 1]; + double best_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[best_out], tmp); + size_t j; + for (j = 0; j < num_clusters; ++j) { + const double cur_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[clusters[j]], tmp); + if (cur_bits < best_bits) { + best_bits = cur_bits; + best_out = clusters[j]; + } + } + symbols[i] = best_out; + } + + /* Recompute each out based on raw and symbols. */ + for (i = 0; i < num_clusters; ++i) { + FN(HistogramClear)(&out[clusters[i]]); + } + for (i = 0; i < in_size; ++i) { + FN(HistogramAddHistogram)(&out[symbols[i]], &in[i]); + } +}) + +/* Reorders elements of the out[0..length) array and changes values in + symbols[0..length) array in the following way: + * when called, symbols[] contains indexes into out[], and has N unique + values (possibly N < length) + * on return, symbols'[i] = f(symbols[i]) and + out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length, + where f is a bijection between the range of symbols[] and [0..N), and + the first occurrences of values in symbols'[i] come in consecutive + increasing order. + Returns N, the number of unique values in symbols[]. */ +BROTLI_INTERNAL size_t FN(BrotliHistogramReindex)(MemoryManager* m, + HistogramType* out, uint32_t* symbols, size_t length) CODE({ + static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; + uint32_t* new_index = BROTLI_ALLOC(m, uint32_t, length); + uint32_t next_index; + HistogramType* tmp; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return 0; + for (i = 0; i < length; ++i) { + new_index[i] = kInvalidIndex; + } + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == kInvalidIndex) { + new_index[symbols[i]] = next_index; + ++next_index; + } + } + /* TODO(eustas): by using idea of "cycle-sort" we can avoid allocation of + tmp and reduce the number of copying by the factor of 2. */ + tmp = BROTLI_ALLOC(m, HistogramType, next_index); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return 0; + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == next_index) { + tmp[next_index] = out[symbols[i]]; + ++next_index; + } + symbols[i] = new_index[symbols[i]]; + } + BROTLI_FREE(m, new_index); + for (i = 0; i < next_index; ++i) { + out[i] = tmp[i]; + } + BROTLI_FREE(m, tmp); + return next_index; +}) + +BROTLI_INTERNAL void FN(BrotliClusterHistograms)( + MemoryManager* m, const HistogramType* in, const size_t in_size, + size_t max_histograms, HistogramType* out, size_t* out_size, + uint32_t* histogram_symbols) CODE({ + uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, in_size); + uint32_t* clusters = BROTLI_ALLOC(m, uint32_t, in_size); + size_t num_clusters = 0; + const size_t max_input_histograms = 64; + size_t pairs_capacity = max_input_histograms * max_input_histograms / 2; + /* For the first pass of clustering, we allow all pairs. */ + HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity + 1); + /* TODO(eustas): move to "persistent" arena? */ + HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 1); + size_t i; + + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(cluster_size) || + BROTLI_IS_NULL(clusters) || BROTLI_IS_NULL(pairs)|| BROTLI_IS_NULL(tmp)) { + return; + } + + for (i = 0; i < in_size; ++i) { + cluster_size[i] = 1; + } + + for (i = 0; i < in_size; ++i) { + out[i] = in[i]; + out[i].bit_cost_ = FN(BrotliPopulationCost)(&in[i]); + histogram_symbols[i] = (uint32_t)i; + } + + for (i = 0; i < in_size; i += max_input_histograms) { + size_t num_to_combine = + BROTLI_MIN(size_t, in_size - i, max_input_histograms); + size_t num_new_clusters; + size_t j; + for (j = 0; j < num_to_combine; ++j) { + clusters[num_clusters + j] = (uint32_t)(i + j); + } + num_new_clusters = + FN(BrotliHistogramCombine)(out, tmp, cluster_size, + &histogram_symbols[i], + &clusters[num_clusters], pairs, + num_to_combine, num_to_combine, + max_histograms, pairs_capacity); + num_clusters += num_new_clusters; + } + + { + /* For the second pass, we limit the total number of histogram pairs. + After this limit is reached, we only keep searching for the best pair. */ + size_t max_num_pairs = BROTLI_MIN(size_t, + 64 * num_clusters, (num_clusters / 2) * num_clusters); + BROTLI_ENSURE_CAPACITY( + m, HistogramPair, pairs, pairs_capacity, max_num_pairs + 1); + if (BROTLI_IS_OOM(m)) return; + + /* Collapse similar histograms. */ + num_clusters = FN(BrotliHistogramCombine)(out, tmp, cluster_size, + histogram_symbols, clusters, + pairs, num_clusters, in_size, + max_histograms, max_num_pairs); + } + BROTLI_FREE(m, pairs); + BROTLI_FREE(m, cluster_size); + /* Find the optimal map from original histograms to the final ones. */ + FN(BrotliHistogramRemap)(in, in_size, clusters, num_clusters, + out, tmp, histogram_symbols); + BROTLI_FREE(m, tmp); + BROTLI_FREE(m, clusters); + /* Convert the context map to a canonical form. */ + *out_size = FN(BrotliHistogramReindex)(m, out, histogram_symbols, in_size); + if (BROTLI_IS_OOM(m)) return; +}) + +#undef HistogramType +#undef FN + +#define FN(X) duckdb_brotli:: X ## Command +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, CODE */ + +#define HistogramType FN(Histogram) + +/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if + it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */ +BROTLI_INTERNAL void FN(BrotliCompareAndPushToQueue)( + const HistogramType* out, HistogramType* tmp, const uint32_t* cluster_size, + uint32_t idx1, uint32_t idx2, size_t max_num_pairs, HistogramPair* pairs, + size_t* num_pairs) CODE({ + BROTLI_BOOL is_good_pair = BROTLI_FALSE; + HistogramPair p; + p.idx1 = p.idx2 = 0; + p.cost_diff = p.cost_combo = 0; + if (idx1 == idx2) { + return; + } + if (idx2 < idx1) { + uint32_t t = idx2; + idx2 = idx1; + idx1 = t; + } + p.idx1 = idx1; + p.idx2 = idx2; + p.cost_diff = 0.5 * ClusterCostDiff(cluster_size[idx1], cluster_size[idx2]); + p.cost_diff -= out[idx1].bit_cost_; + p.cost_diff -= out[idx2].bit_cost_; + + if (out[idx1].total_count_ == 0) { + p.cost_combo = out[idx2].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else if (out[idx2].total_count_ == 0) { + p.cost_combo = out[idx1].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else { + double threshold = *num_pairs == 0 ? 1e99 : + BROTLI_MAX(double, 0.0, pairs[0].cost_diff); + double cost_combo; + *tmp = out[idx1]; + FN(HistogramAddHistogram)(tmp, &out[idx2]); + cost_combo = FN(BrotliPopulationCost)(tmp); + if (cost_combo < threshold - p.cost_diff) { + p.cost_combo = cost_combo; + is_good_pair = BROTLI_TRUE; + } + } + if (is_good_pair) { + p.cost_diff += p.cost_combo; + if (*num_pairs > 0 && HistogramPairIsLess(&pairs[0], &p)) { + /* Replace the top of the queue if needed. */ + if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = pairs[0]; + ++(*num_pairs); + } + pairs[0] = p; + } else if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = p; + ++(*num_pairs); + } + } +}) + +BROTLI_INTERNAL size_t FN(BrotliHistogramCombine)(HistogramType* out, + HistogramType* tmp, + uint32_t* cluster_size, + uint32_t* symbols, + uint32_t* clusters, + HistogramPair* pairs, + size_t num_clusters, + size_t symbols_size, + size_t max_clusters, + size_t max_num_pairs) CODE({ + double cost_diff_threshold = 0.0; + size_t min_cluster_size = 1; + size_t num_pairs = 0; + + { + /* We maintain a vector of histogram pairs, with the property that the pair + with the maximum bit cost reduction is the first. */ + size_t idx1; + for (idx1 = 0; idx1 < num_clusters; ++idx1) { + size_t idx2; + for (idx2 = idx1 + 1; idx2 < num_clusters; ++idx2) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, clusters[idx1], + clusters[idx2], max_num_pairs, &pairs[0], &num_pairs); + } + } + } + + while (num_clusters > min_cluster_size) { + uint32_t best_idx1; + uint32_t best_idx2; + size_t i; + if (pairs[0].cost_diff >= cost_diff_threshold) { + cost_diff_threshold = 1e99; + min_cluster_size = max_clusters; + continue; + } + /* Take the best pair from the top of heap. */ + best_idx1 = pairs[0].idx1; + best_idx2 = pairs[0].idx2; + FN(HistogramAddHistogram)(&out[best_idx1], &out[best_idx2]); + out[best_idx1].bit_cost_ = pairs[0].cost_combo; + cluster_size[best_idx1] += cluster_size[best_idx2]; + for (i = 0; i < symbols_size; ++i) { + if (symbols[i] == best_idx2) { + symbols[i] = best_idx1; + } + } + for (i = 0; i < num_clusters; ++i) { + if (clusters[i] == best_idx2) { + memmove(&clusters[i], &clusters[i + 1], + (num_clusters - i - 1) * sizeof(clusters[0])); + break; + } + } + --num_clusters; + { + /* Remove pairs intersecting the just combined best pair. */ + size_t copy_to_idx = 0; + for (i = 0; i < num_pairs; ++i) { + HistogramPair* p = &pairs[i]; + if (p->idx1 == best_idx1 || p->idx2 == best_idx1 || + p->idx1 == best_idx2 || p->idx2 == best_idx2) { + /* Remove invalid pair from the queue. */ + continue; + } + if (HistogramPairIsLess(&pairs[0], p)) { + /* Replace the top of the queue if needed. */ + HistogramPair front = pairs[0]; + pairs[0] = *p; + pairs[copy_to_idx] = front; + } else { + pairs[copy_to_idx] = *p; + } + ++copy_to_idx; + } + num_pairs = copy_to_idx; + } + + /* Push new pairs formed with the combined histogram to the heap. */ + for (i = 0; i < num_clusters; ++i) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, best_idx1, + clusters[i], max_num_pairs, &pairs[0], &num_pairs); + } + } + return num_clusters; +}) + +/* What is the bit cost of moving histogram from cur_symbol to candidate. */ +BROTLI_INTERNAL double FN(BrotliHistogramBitCostDistance)( + const HistogramType* histogram, const HistogramType* candidate, + HistogramType* tmp) CODE({ + if (histogram->total_count_ == 0) { + return 0.0; + } else { + *tmp = *histogram; + FN(HistogramAddHistogram)(tmp, candidate); + return FN(BrotliPopulationCost)(tmp) - candidate->bit_cost_; + } +}) + +/* Find the best 'out' histogram for each of the 'in' histograms. + When called, clusters[0..num_clusters) contains the unique values from + symbols[0..in_size), but this property is not preserved in this function. + Note: we assume that out[]->bit_cost_ is already up-to-date. */ +BROTLI_INTERNAL void FN(BrotliHistogramRemap)(const HistogramType* in, + size_t in_size, const uint32_t* clusters, size_t num_clusters, + HistogramType* out, HistogramType* tmp, uint32_t* symbols) CODE({ + size_t i; + for (i = 0; i < in_size; ++i) { + uint32_t best_out = i == 0 ? symbols[0] : symbols[i - 1]; + double best_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[best_out], tmp); + size_t j; + for (j = 0; j < num_clusters; ++j) { + const double cur_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[clusters[j]], tmp); + if (cur_bits < best_bits) { + best_bits = cur_bits; + best_out = clusters[j]; + } + } + symbols[i] = best_out; + } + + /* Recompute each out based on raw and symbols. */ + for (i = 0; i < num_clusters; ++i) { + FN(HistogramClear)(&out[clusters[i]]); + } + for (i = 0; i < in_size; ++i) { + FN(HistogramAddHistogram)(&out[symbols[i]], &in[i]); + } +}) + +/* Reorders elements of the out[0..length) array and changes values in + symbols[0..length) array in the following way: + * when called, symbols[] contains indexes into out[], and has N unique + values (possibly N < length) + * on return, symbols'[i] = f(symbols[i]) and + out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length, + where f is a bijection between the range of symbols[] and [0..N), and + the first occurrences of values in symbols'[i] come in consecutive + increasing order. + Returns N, the number of unique values in symbols[]. */ +BROTLI_INTERNAL size_t FN(BrotliHistogramReindex)(MemoryManager* m, + HistogramType* out, uint32_t* symbols, size_t length) CODE({ + static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; + uint32_t* new_index = BROTLI_ALLOC(m, uint32_t, length); + uint32_t next_index; + HistogramType* tmp; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return 0; + for (i = 0; i < length; ++i) { + new_index[i] = kInvalidIndex; + } + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == kInvalidIndex) { + new_index[symbols[i]] = next_index; + ++next_index; + } + } + /* TODO(eustas): by using idea of "cycle-sort" we can avoid allocation of + tmp and reduce the number of copying by the factor of 2. */ + tmp = BROTLI_ALLOC(m, HistogramType, next_index); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return 0; + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == next_index) { + tmp[next_index] = out[symbols[i]]; + ++next_index; + } + symbols[i] = new_index[symbols[i]]; + } + BROTLI_FREE(m, new_index); + for (i = 0; i < next_index; ++i) { + out[i] = tmp[i]; + } + BROTLI_FREE(m, tmp); + return next_index; +}) + +BROTLI_INTERNAL void FN(BrotliClusterHistograms)( + MemoryManager* m, const HistogramType* in, const size_t in_size, + size_t max_histograms, HistogramType* out, size_t* out_size, + uint32_t* histogram_symbols) CODE({ + uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, in_size); + uint32_t* clusters = BROTLI_ALLOC(m, uint32_t, in_size); + size_t num_clusters = 0; + const size_t max_input_histograms = 64; + size_t pairs_capacity = max_input_histograms * max_input_histograms / 2; + /* For the first pass of clustering, we allow all pairs. */ + HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity + 1); + /* TODO(eustas): move to "persistent" arena? */ + HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 1); + size_t i; + + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(cluster_size) || + BROTLI_IS_NULL(clusters) || BROTLI_IS_NULL(pairs)|| BROTLI_IS_NULL(tmp)) { + return; + } + + for (i = 0; i < in_size; ++i) { + cluster_size[i] = 1; + } + + for (i = 0; i < in_size; ++i) { + out[i] = in[i]; + out[i].bit_cost_ = FN(BrotliPopulationCost)(&in[i]); + histogram_symbols[i] = (uint32_t)i; + } + + for (i = 0; i < in_size; i += max_input_histograms) { + size_t num_to_combine = + BROTLI_MIN(size_t, in_size - i, max_input_histograms); + size_t num_new_clusters; + size_t j; + for (j = 0; j < num_to_combine; ++j) { + clusters[num_clusters + j] = (uint32_t)(i + j); + } + num_new_clusters = + FN(BrotliHistogramCombine)(out, tmp, cluster_size, + &histogram_symbols[i], + &clusters[num_clusters], pairs, + num_to_combine, num_to_combine, + max_histograms, pairs_capacity); + num_clusters += num_new_clusters; + } + + { + /* For the second pass, we limit the total number of histogram pairs. + After this limit is reached, we only keep searching for the best pair. */ + size_t max_num_pairs = BROTLI_MIN(size_t, + 64 * num_clusters, (num_clusters / 2) * num_clusters); + BROTLI_ENSURE_CAPACITY( + m, HistogramPair, pairs, pairs_capacity, max_num_pairs + 1); + if (BROTLI_IS_OOM(m)) return; + + /* Collapse similar histograms. */ + num_clusters = FN(BrotliHistogramCombine)(out, tmp, cluster_size, + histogram_symbols, clusters, + pairs, num_clusters, in_size, + max_histograms, max_num_pairs); + } + BROTLI_FREE(m, pairs); + BROTLI_FREE(m, cluster_size); + /* Find the optimal map from original histograms to the final ones. */ + FN(BrotliHistogramRemap)(in, in_size, clusters, num_clusters, + out, tmp, histogram_symbols); + BROTLI_FREE(m, tmp); + BROTLI_FREE(m, clusters); + /* Convert the context map to a canonical form. */ + *out_size = FN(BrotliHistogramReindex)(m, out, histogram_symbols, in_size); + if (BROTLI_IS_OOM(m)) return; +}) + +#undef HistogramType +#undef FN + +#define FN(X) duckdb_brotli:: X ## Distance +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, CODE */ + +#define HistogramType FN(Histogram) + +/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if + it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */ +BROTLI_INTERNAL void FN(BrotliCompareAndPushToQueue)( + const HistogramType* out, HistogramType* tmp, const uint32_t* cluster_size, + uint32_t idx1, uint32_t idx2, size_t max_num_pairs, HistogramPair* pairs, + size_t* num_pairs) CODE({ + BROTLI_BOOL is_good_pair = BROTLI_FALSE; + HistogramPair p; + p.idx1 = p.idx2 = 0; + p.cost_diff = p.cost_combo = 0; + if (idx1 == idx2) { + return; + } + if (idx2 < idx1) { + uint32_t t = idx2; + idx2 = idx1; + idx1 = t; + } + p.idx1 = idx1; + p.idx2 = idx2; + p.cost_diff = 0.5 * ClusterCostDiff(cluster_size[idx1], cluster_size[idx2]); + p.cost_diff -= out[idx1].bit_cost_; + p.cost_diff -= out[idx2].bit_cost_; + + if (out[idx1].total_count_ == 0) { + p.cost_combo = out[idx2].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else if (out[idx2].total_count_ == 0) { + p.cost_combo = out[idx1].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else { + double threshold = *num_pairs == 0 ? 1e99 : + BROTLI_MAX(double, 0.0, pairs[0].cost_diff); + double cost_combo; + *tmp = out[idx1]; + FN(HistogramAddHistogram)(tmp, &out[idx2]); + cost_combo = FN(BrotliPopulationCost)(tmp); + if (cost_combo < threshold - p.cost_diff) { + p.cost_combo = cost_combo; + is_good_pair = BROTLI_TRUE; + } + } + if (is_good_pair) { + p.cost_diff += p.cost_combo; + if (*num_pairs > 0 && HistogramPairIsLess(&pairs[0], &p)) { + /* Replace the top of the queue if needed. */ + if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = pairs[0]; + ++(*num_pairs); + } + pairs[0] = p; + } else if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = p; + ++(*num_pairs); + } + } +}) + +BROTLI_INTERNAL size_t FN(BrotliHistogramCombine)(HistogramType* out, + HistogramType* tmp, + uint32_t* cluster_size, + uint32_t* symbols, + uint32_t* clusters, + HistogramPair* pairs, + size_t num_clusters, + size_t symbols_size, + size_t max_clusters, + size_t max_num_pairs) CODE({ + double cost_diff_threshold = 0.0; + size_t min_cluster_size = 1; + size_t num_pairs = 0; + + { + /* We maintain a vector of histogram pairs, with the property that the pair + with the maximum bit cost reduction is the first. */ + size_t idx1; + for (idx1 = 0; idx1 < num_clusters; ++idx1) { + size_t idx2; + for (idx2 = idx1 + 1; idx2 < num_clusters; ++idx2) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, clusters[idx1], + clusters[idx2], max_num_pairs, &pairs[0], &num_pairs); + } + } + } + + while (num_clusters > min_cluster_size) { + uint32_t best_idx1; + uint32_t best_idx2; + size_t i; + if (pairs[0].cost_diff >= cost_diff_threshold) { + cost_diff_threshold = 1e99; + min_cluster_size = max_clusters; + continue; + } + /* Take the best pair from the top of heap. */ + best_idx1 = pairs[0].idx1; + best_idx2 = pairs[0].idx2; + FN(HistogramAddHistogram)(&out[best_idx1], &out[best_idx2]); + out[best_idx1].bit_cost_ = pairs[0].cost_combo; + cluster_size[best_idx1] += cluster_size[best_idx2]; + for (i = 0; i < symbols_size; ++i) { + if (symbols[i] == best_idx2) { + symbols[i] = best_idx1; + } + } + for (i = 0; i < num_clusters; ++i) { + if (clusters[i] == best_idx2) { + memmove(&clusters[i], &clusters[i + 1], + (num_clusters - i - 1) * sizeof(clusters[0])); + break; + } + } + --num_clusters; + { + /* Remove pairs intersecting the just combined best pair. */ + size_t copy_to_idx = 0; + for (i = 0; i < num_pairs; ++i) { + HistogramPair* p = &pairs[i]; + if (p->idx1 == best_idx1 || p->idx2 == best_idx1 || + p->idx1 == best_idx2 || p->idx2 == best_idx2) { + /* Remove invalid pair from the queue. */ + continue; + } + if (HistogramPairIsLess(&pairs[0], p)) { + /* Replace the top of the queue if needed. */ + HistogramPair front = pairs[0]; + pairs[0] = *p; + pairs[copy_to_idx] = front; + } else { + pairs[copy_to_idx] = *p; + } + ++copy_to_idx; + } + num_pairs = copy_to_idx; + } + + /* Push new pairs formed with the combined histogram to the heap. */ + for (i = 0; i < num_clusters; ++i) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, best_idx1, + clusters[i], max_num_pairs, &pairs[0], &num_pairs); + } + } + return num_clusters; +}) + +/* What is the bit cost of moving histogram from cur_symbol to candidate. */ +BROTLI_INTERNAL double FN(BrotliHistogramBitCostDistance)( + const HistogramType* histogram, const HistogramType* candidate, + HistogramType* tmp) CODE({ + if (histogram->total_count_ == 0) { + return 0.0; + } else { + *tmp = *histogram; + FN(HistogramAddHistogram)(tmp, candidate); + return FN(BrotliPopulationCost)(tmp) - candidate->bit_cost_; + } +}) + +/* Find the best 'out' histogram for each of the 'in' histograms. + When called, clusters[0..num_clusters) contains the unique values from + symbols[0..in_size), but this property is not preserved in this function. + Note: we assume that out[]->bit_cost_ is already up-to-date. */ +BROTLI_INTERNAL void FN(BrotliHistogramRemap)(const HistogramType* in, + size_t in_size, const uint32_t* clusters, size_t num_clusters, + HistogramType* out, HistogramType* tmp, uint32_t* symbols) CODE({ + size_t i; + for (i = 0; i < in_size; ++i) { + uint32_t best_out = i == 0 ? symbols[0] : symbols[i - 1]; + double best_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[best_out], tmp); + size_t j; + for (j = 0; j < num_clusters; ++j) { + const double cur_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[clusters[j]], tmp); + if (cur_bits < best_bits) { + best_bits = cur_bits; + best_out = clusters[j]; + } + } + symbols[i] = best_out; + } + + /* Recompute each out based on raw and symbols. */ + for (i = 0; i < num_clusters; ++i) { + FN(HistogramClear)(&out[clusters[i]]); + } + for (i = 0; i < in_size; ++i) { + FN(HistogramAddHistogram)(&out[symbols[i]], &in[i]); + } +}) + +/* Reorders elements of the out[0..length) array and changes values in + symbols[0..length) array in the following way: + * when called, symbols[] contains indexes into out[], and has N unique + values (possibly N < length) + * on return, symbols'[i] = f(symbols[i]) and + out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length, + where f is a bijection between the range of symbols[] and [0..N), and + the first occurrences of values in symbols'[i] come in consecutive + increasing order. + Returns N, the number of unique values in symbols[]. */ +BROTLI_INTERNAL size_t FN(BrotliHistogramReindex)(MemoryManager* m, + HistogramType* out, uint32_t* symbols, size_t length) CODE({ + static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; + uint32_t* new_index = BROTLI_ALLOC(m, uint32_t, length); + uint32_t next_index; + HistogramType* tmp; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return 0; + for (i = 0; i < length; ++i) { + new_index[i] = kInvalidIndex; + } + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == kInvalidIndex) { + new_index[symbols[i]] = next_index; + ++next_index; + } + } + /* TODO(eustas): by using idea of "cycle-sort" we can avoid allocation of + tmp and reduce the number of copying by the factor of 2. */ + tmp = BROTLI_ALLOC(m, HistogramType, next_index); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return 0; + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == next_index) { + tmp[next_index] = out[symbols[i]]; + ++next_index; + } + symbols[i] = new_index[symbols[i]]; + } + BROTLI_FREE(m, new_index); + for (i = 0; i < next_index; ++i) { + out[i] = tmp[i]; + } + BROTLI_FREE(m, tmp); + return next_index; +}) + +BROTLI_INTERNAL void FN(BrotliClusterHistograms)( + MemoryManager* m, const HistogramType* in, const size_t in_size, + size_t max_histograms, HistogramType* out, size_t* out_size, + uint32_t* histogram_symbols) CODE({ + uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, in_size); + uint32_t* clusters = BROTLI_ALLOC(m, uint32_t, in_size); + size_t num_clusters = 0; + const size_t max_input_histograms = 64; + size_t pairs_capacity = max_input_histograms * max_input_histograms / 2; + /* For the first pass of clustering, we allow all pairs. */ + HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity + 1); + /* TODO(eustas): move to "persistent" arena? */ + HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 1); + size_t i; + + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(cluster_size) || + BROTLI_IS_NULL(clusters) || BROTLI_IS_NULL(pairs)|| BROTLI_IS_NULL(tmp)) { + return; + } + + for (i = 0; i < in_size; ++i) { + cluster_size[i] = 1; + } + + for (i = 0; i < in_size; ++i) { + out[i] = in[i]; + out[i].bit_cost_ = FN(BrotliPopulationCost)(&in[i]); + histogram_symbols[i] = (uint32_t)i; + } + + for (i = 0; i < in_size; i += max_input_histograms) { + size_t num_to_combine = + BROTLI_MIN(size_t, in_size - i, max_input_histograms); + size_t num_new_clusters; + size_t j; + for (j = 0; j < num_to_combine; ++j) { + clusters[num_clusters + j] = (uint32_t)(i + j); + } + num_new_clusters = + FN(BrotliHistogramCombine)(out, tmp, cluster_size, + &histogram_symbols[i], + &clusters[num_clusters], pairs, + num_to_combine, num_to_combine, + max_histograms, pairs_capacity); + num_clusters += num_new_clusters; + } + + { + /* For the second pass, we limit the total number of histogram pairs. + After this limit is reached, we only keep searching for the best pair. */ + size_t max_num_pairs = BROTLI_MIN(size_t, + 64 * num_clusters, (num_clusters / 2) * num_clusters); + BROTLI_ENSURE_CAPACITY( + m, HistogramPair, pairs, pairs_capacity, max_num_pairs + 1); + if (BROTLI_IS_OOM(m)) return; + + /* Collapse similar histograms. */ + num_clusters = FN(BrotliHistogramCombine)(out, tmp, cluster_size, + histogram_symbols, clusters, + pairs, num_clusters, in_size, + max_histograms, max_num_pairs); + } + BROTLI_FREE(m, pairs); + BROTLI_FREE(m, cluster_size); + /* Find the optimal map from original histograms to the final ones. */ + FN(BrotliHistogramRemap)(in, in_size, clusters, num_clusters, + out, tmp, histogram_symbols); + BROTLI_FREE(m, tmp); + BROTLI_FREE(m, clusters); + /* Convert the context map to a canonical form. */ + *out_size = FN(BrotliHistogramReindex)(m, out, histogram_symbols, in_size); + if (BROTLI_IS_OOM(m)) return; +}) + +#undef HistogramType +#undef FN + +#undef CODE + + diff --git a/third_party/brotli/enc/cluster.h b/third_party/brotli/enc/cluster.h new file mode 100644 index 00000000000..ffd49667811 --- /dev/null +++ b/third_party/brotli/enc/cluster.h @@ -0,0 +1,1017 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Functions for clustering similar histograms together. */ + +#ifndef BROTLI_ENC_CLUSTER_H_ +#define BROTLI_ENC_CLUSTER_H_ + +#include + +#include "../common/brotli_platform.h" +#include "histogram.h" +#include "memory.h" + +namespace duckdb_brotli { + +typedef struct HistogramPair { + uint32_t idx1; + uint32_t idx2; + double cost_combo; + double cost_diff; +} HistogramPair; + +#define CODE(X) /* Declaration */; + +#define FN(X) X ## Literal +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, CODE */ + +#define HistogramType FN(Histogram) + +/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if + it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */ +BROTLI_INTERNAL void FN(BrotliCompareAndPushToQueue)( + const HistogramType* out, HistogramType* tmp, const uint32_t* cluster_size, + uint32_t idx1, uint32_t idx2, size_t max_num_pairs, HistogramPair* pairs, + size_t* num_pairs) CODE({ + BROTLI_BOOL is_good_pair = BROTLI_FALSE; + HistogramPair p; + p.idx1 = p.idx2 = 0; + p.cost_diff = p.cost_combo = 0; + if (idx1 == idx2) { + return; + } + if (idx2 < idx1) { + uint32_t t = idx2; + idx2 = idx1; + idx1 = t; + } + p.idx1 = idx1; + p.idx2 = idx2; + p.cost_diff = 0.5 * ClusterCostDiff(cluster_size[idx1], cluster_size[idx2]); + p.cost_diff -= out[idx1].bit_cost_; + p.cost_diff -= out[idx2].bit_cost_; + + if (out[idx1].total_count_ == 0) { + p.cost_combo = out[idx2].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else if (out[idx2].total_count_ == 0) { + p.cost_combo = out[idx1].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else { + double threshold = *num_pairs == 0 ? 1e99 : + BROTLI_MAX(double, 0.0, pairs[0].cost_diff); + double cost_combo; + *tmp = out[idx1]; + FN(HistogramAddHistogram)(tmp, &out[idx2]); + cost_combo = FN(BrotliPopulationCost)(tmp); + if (cost_combo < threshold - p.cost_diff) { + p.cost_combo = cost_combo; + is_good_pair = BROTLI_TRUE; + } + } + if (is_good_pair) { + p.cost_diff += p.cost_combo; + if (*num_pairs > 0 && HistogramPairIsLess(&pairs[0], &p)) { + /* Replace the top of the queue if needed. */ + if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = pairs[0]; + ++(*num_pairs); + } + pairs[0] = p; + } else if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = p; + ++(*num_pairs); + } + } +}) + +BROTLI_INTERNAL size_t FN(BrotliHistogramCombine)(HistogramType* out, + HistogramType* tmp, + uint32_t* cluster_size, + uint32_t* symbols, + uint32_t* clusters, + HistogramPair* pairs, + size_t num_clusters, + size_t symbols_size, + size_t max_clusters, + size_t max_num_pairs) CODE({ + double cost_diff_threshold = 0.0; + size_t min_cluster_size = 1; + size_t num_pairs = 0; + + { + /* We maintain a vector of histogram pairs, with the property that the pair + with the maximum bit cost reduction is the first. */ + size_t idx1; + for (idx1 = 0; idx1 < num_clusters; ++idx1) { + size_t idx2; + for (idx2 = idx1 + 1; idx2 < num_clusters; ++idx2) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, clusters[idx1], + clusters[idx2], max_num_pairs, &pairs[0], &num_pairs); + } + } + } + + while (num_clusters > min_cluster_size) { + uint32_t best_idx1; + uint32_t best_idx2; + size_t i; + if (pairs[0].cost_diff >= cost_diff_threshold) { + cost_diff_threshold = 1e99; + min_cluster_size = max_clusters; + continue; + } + /* Take the best pair from the top of heap. */ + best_idx1 = pairs[0].idx1; + best_idx2 = pairs[0].idx2; + FN(HistogramAddHistogram)(&out[best_idx1], &out[best_idx2]); + out[best_idx1].bit_cost_ = pairs[0].cost_combo; + cluster_size[best_idx1] += cluster_size[best_idx2]; + for (i = 0; i < symbols_size; ++i) { + if (symbols[i] == best_idx2) { + symbols[i] = best_idx1; + } + } + for (i = 0; i < num_clusters; ++i) { + if (clusters[i] == best_idx2) { + memmove(&clusters[i], &clusters[i + 1], + (num_clusters - i - 1) * sizeof(clusters[0])); + break; + } + } + --num_clusters; + { + /* Remove pairs intersecting the just combined best pair. */ + size_t copy_to_idx = 0; + for (i = 0; i < num_pairs; ++i) { + HistogramPair* p = &pairs[i]; + if (p->idx1 == best_idx1 || p->idx2 == best_idx1 || + p->idx1 == best_idx2 || p->idx2 == best_idx2) { + /* Remove invalid pair from the queue. */ + continue; + } + if (HistogramPairIsLess(&pairs[0], p)) { + /* Replace the top of the queue if needed. */ + HistogramPair front = pairs[0]; + pairs[0] = *p; + pairs[copy_to_idx] = front; + } else { + pairs[copy_to_idx] = *p; + } + ++copy_to_idx; + } + num_pairs = copy_to_idx; + } + + /* Push new pairs formed with the combined histogram to the heap. */ + for (i = 0; i < num_clusters; ++i) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, best_idx1, + clusters[i], max_num_pairs, &pairs[0], &num_pairs); + } + } + return num_clusters; +}) + +/* What is the bit cost of moving histogram from cur_symbol to candidate. */ +BROTLI_INTERNAL double FN(BrotliHistogramBitCostDistance)( + const HistogramType* histogram, const HistogramType* candidate, + HistogramType* tmp) CODE({ + if (histogram->total_count_ == 0) { + return 0.0; + } else { + *tmp = *histogram; + FN(HistogramAddHistogram)(tmp, candidate); + return FN(BrotliPopulationCost)(tmp) - candidate->bit_cost_; + } +}) + +/* Find the best 'out' histogram for each of the 'in' histograms. + When called, clusters[0..num_clusters) contains the unique values from + symbols[0..in_size), but this property is not preserved in this function. + Note: we assume that out[]->bit_cost_ is already up-to-date. */ +BROTLI_INTERNAL void FN(BrotliHistogramRemap)(const HistogramType* in, + size_t in_size, const uint32_t* clusters, size_t num_clusters, + HistogramType* out, HistogramType* tmp, uint32_t* symbols) CODE({ + size_t i; + for (i = 0; i < in_size; ++i) { + uint32_t best_out = i == 0 ? symbols[0] : symbols[i - 1]; + double best_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[best_out], tmp); + size_t j; + for (j = 0; j < num_clusters; ++j) { + const double cur_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[clusters[j]], tmp); + if (cur_bits < best_bits) { + best_bits = cur_bits; + best_out = clusters[j]; + } + } + symbols[i] = best_out; + } + + /* Recompute each out based on raw and symbols. */ + for (i = 0; i < num_clusters; ++i) { + FN(HistogramClear)(&out[clusters[i]]); + } + for (i = 0; i < in_size; ++i) { + FN(HistogramAddHistogram)(&out[symbols[i]], &in[i]); + } +}) + +/* Reorders elements of the out[0..length) array and changes values in + symbols[0..length) array in the following way: + * when called, symbols[] contains indexes into out[], and has N unique + values (possibly N < length) + * on return, symbols'[i] = f(symbols[i]) and + out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length, + where f is a bijection between the range of symbols[] and [0..N), and + the first occurrences of values in symbols'[i] come in consecutive + increasing order. + Returns N, the number of unique values in symbols[]. */ +BROTLI_INTERNAL size_t FN(BrotliHistogramReindex)(MemoryManager* m, + HistogramType* out, uint32_t* symbols, size_t length) CODE({ + static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; + uint32_t* new_index = BROTLI_ALLOC(m, uint32_t, length); + uint32_t next_index; + HistogramType* tmp; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return 0; + for (i = 0; i < length; ++i) { + new_index[i] = kInvalidIndex; + } + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == kInvalidIndex) { + new_index[symbols[i]] = next_index; + ++next_index; + } + } + /* TODO(eustas): by using idea of "cycle-sort" we can avoid allocation of + tmp and reduce the number of copying by the factor of 2. */ + tmp = BROTLI_ALLOC(m, HistogramType, next_index); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return 0; + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == next_index) { + tmp[next_index] = out[symbols[i]]; + ++next_index; + } + symbols[i] = new_index[symbols[i]]; + } + BROTLI_FREE(m, new_index); + for (i = 0; i < next_index; ++i) { + out[i] = tmp[i]; + } + BROTLI_FREE(m, tmp); + return next_index; +}) + +BROTLI_INTERNAL void FN(BrotliClusterHistograms)( + MemoryManager* m, const HistogramType* in, const size_t in_size, + size_t max_histograms, HistogramType* out, size_t* out_size, + uint32_t* histogram_symbols) CODE({ + uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, in_size); + uint32_t* clusters = BROTLI_ALLOC(m, uint32_t, in_size); + size_t num_clusters = 0; + const size_t max_input_histograms = 64; + size_t pairs_capacity = max_input_histograms * max_input_histograms / 2; + /* For the first pass of clustering, we allow all pairs. */ + HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity + 1); + /* TODO(eustas): move to "persistent" arena? */ + HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 1); + size_t i; + + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(cluster_size) || + BROTLI_IS_NULL(clusters) || BROTLI_IS_NULL(pairs)|| BROTLI_IS_NULL(tmp)) { + return; + } + + for (i = 0; i < in_size; ++i) { + cluster_size[i] = 1; + } + + for (i = 0; i < in_size; ++i) { + out[i] = in[i]; + out[i].bit_cost_ = FN(BrotliPopulationCost)(&in[i]); + histogram_symbols[i] = (uint32_t)i; + } + + for (i = 0; i < in_size; i += max_input_histograms) { + size_t num_to_combine = + BROTLI_MIN(size_t, in_size - i, max_input_histograms); + size_t num_new_clusters; + size_t j; + for (j = 0; j < num_to_combine; ++j) { + clusters[num_clusters + j] = (uint32_t)(i + j); + } + num_new_clusters = + FN(BrotliHistogramCombine)(out, tmp, cluster_size, + &histogram_symbols[i], + &clusters[num_clusters], pairs, + num_to_combine, num_to_combine, + max_histograms, pairs_capacity); + num_clusters += num_new_clusters; + } + + { + /* For the second pass, we limit the total number of histogram pairs. + After this limit is reached, we only keep searching for the best pair. */ + size_t max_num_pairs = BROTLI_MIN(size_t, + 64 * num_clusters, (num_clusters / 2) * num_clusters); + BROTLI_ENSURE_CAPACITY( + m, HistogramPair, pairs, pairs_capacity, max_num_pairs + 1); + if (BROTLI_IS_OOM(m)) return; + + /* Collapse similar histograms. */ + num_clusters = FN(BrotliHistogramCombine)(out, tmp, cluster_size, + histogram_symbols, clusters, + pairs, num_clusters, in_size, + max_histograms, max_num_pairs); + } + BROTLI_FREE(m, pairs); + BROTLI_FREE(m, cluster_size); + /* Find the optimal map from original histograms to the final ones. */ + FN(BrotliHistogramRemap)(in, in_size, clusters, num_clusters, + out, tmp, histogram_symbols); + BROTLI_FREE(m, tmp); + BROTLI_FREE(m, clusters); + /* Convert the context map to a canonical form. */ + *out_size = FN(BrotliHistogramReindex)(m, out, histogram_symbols, in_size); + if (BROTLI_IS_OOM(m)) return; +}) + +#undef HistogramType +#undef FN + +#define FN(X) X ## Command +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, CODE */ + +#define HistogramType FN(Histogram) + +/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if + it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */ +BROTLI_INTERNAL void FN(BrotliCompareAndPushToQueue)( + const HistogramType* out, HistogramType* tmp, const uint32_t* cluster_size, + uint32_t idx1, uint32_t idx2, size_t max_num_pairs, HistogramPair* pairs, + size_t* num_pairs) CODE({ + BROTLI_BOOL is_good_pair = BROTLI_FALSE; + HistogramPair p; + p.idx1 = p.idx2 = 0; + p.cost_diff = p.cost_combo = 0; + if (idx1 == idx2) { + return; + } + if (idx2 < idx1) { + uint32_t t = idx2; + idx2 = idx1; + idx1 = t; + } + p.idx1 = idx1; + p.idx2 = idx2; + p.cost_diff = 0.5 * ClusterCostDiff(cluster_size[idx1], cluster_size[idx2]); + p.cost_diff -= out[idx1].bit_cost_; + p.cost_diff -= out[idx2].bit_cost_; + + if (out[idx1].total_count_ == 0) { + p.cost_combo = out[idx2].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else if (out[idx2].total_count_ == 0) { + p.cost_combo = out[idx1].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else { + double threshold = *num_pairs == 0 ? 1e99 : + BROTLI_MAX(double, 0.0, pairs[0].cost_diff); + double cost_combo; + *tmp = out[idx1]; + FN(HistogramAddHistogram)(tmp, &out[idx2]); + cost_combo = FN(BrotliPopulationCost)(tmp); + if (cost_combo < threshold - p.cost_diff) { + p.cost_combo = cost_combo; + is_good_pair = BROTLI_TRUE; + } + } + if (is_good_pair) { + p.cost_diff += p.cost_combo; + if (*num_pairs > 0 && HistogramPairIsLess(&pairs[0], &p)) { + /* Replace the top of the queue if needed. */ + if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = pairs[0]; + ++(*num_pairs); + } + pairs[0] = p; + } else if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = p; + ++(*num_pairs); + } + } +}) + +BROTLI_INTERNAL size_t FN(BrotliHistogramCombine)(HistogramType* out, + HistogramType* tmp, + uint32_t* cluster_size, + uint32_t* symbols, + uint32_t* clusters, + HistogramPair* pairs, + size_t num_clusters, + size_t symbols_size, + size_t max_clusters, + size_t max_num_pairs) CODE({ + double cost_diff_threshold = 0.0; + size_t min_cluster_size = 1; + size_t num_pairs = 0; + + { + /* We maintain a vector of histogram pairs, with the property that the pair + with the maximum bit cost reduction is the first. */ + size_t idx1; + for (idx1 = 0; idx1 < num_clusters; ++idx1) { + size_t idx2; + for (idx2 = idx1 + 1; idx2 < num_clusters; ++idx2) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, clusters[idx1], + clusters[idx2], max_num_pairs, &pairs[0], &num_pairs); + } + } + } + + while (num_clusters > min_cluster_size) { + uint32_t best_idx1; + uint32_t best_idx2; + size_t i; + if (pairs[0].cost_diff >= cost_diff_threshold) { + cost_diff_threshold = 1e99; + min_cluster_size = max_clusters; + continue; + } + /* Take the best pair from the top of heap. */ + best_idx1 = pairs[0].idx1; + best_idx2 = pairs[0].idx2; + FN(HistogramAddHistogram)(&out[best_idx1], &out[best_idx2]); + out[best_idx1].bit_cost_ = pairs[0].cost_combo; + cluster_size[best_idx1] += cluster_size[best_idx2]; + for (i = 0; i < symbols_size; ++i) { + if (symbols[i] == best_idx2) { + symbols[i] = best_idx1; + } + } + for (i = 0; i < num_clusters; ++i) { + if (clusters[i] == best_idx2) { + memmove(&clusters[i], &clusters[i + 1], + (num_clusters - i - 1) * sizeof(clusters[0])); + break; + } + } + --num_clusters; + { + /* Remove pairs intersecting the just combined best pair. */ + size_t copy_to_idx = 0; + for (i = 0; i < num_pairs; ++i) { + HistogramPair* p = &pairs[i]; + if (p->idx1 == best_idx1 || p->idx2 == best_idx1 || + p->idx1 == best_idx2 || p->idx2 == best_idx2) { + /* Remove invalid pair from the queue. */ + continue; + } + if (HistogramPairIsLess(&pairs[0], p)) { + /* Replace the top of the queue if needed. */ + HistogramPair front = pairs[0]; + pairs[0] = *p; + pairs[copy_to_idx] = front; + } else { + pairs[copy_to_idx] = *p; + } + ++copy_to_idx; + } + num_pairs = copy_to_idx; + } + + /* Push new pairs formed with the combined histogram to the heap. */ + for (i = 0; i < num_clusters; ++i) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, best_idx1, + clusters[i], max_num_pairs, &pairs[0], &num_pairs); + } + } + return num_clusters; +}) + +/* What is the bit cost of moving histogram from cur_symbol to candidate. */ +BROTLI_INTERNAL double FN(BrotliHistogramBitCostDistance)( + const HistogramType* histogram, const HistogramType* candidate, + HistogramType* tmp) CODE({ + if (histogram->total_count_ == 0) { + return 0.0; + } else { + *tmp = *histogram; + FN(HistogramAddHistogram)(tmp, candidate); + return FN(BrotliPopulationCost)(tmp) - candidate->bit_cost_; + } +}) + +/* Find the best 'out' histogram for each of the 'in' histograms. + When called, clusters[0..num_clusters) contains the unique values from + symbols[0..in_size), but this property is not preserved in this function. + Note: we assume that out[]->bit_cost_ is already up-to-date. */ +BROTLI_INTERNAL void FN(BrotliHistogramRemap)(const HistogramType* in, + size_t in_size, const uint32_t* clusters, size_t num_clusters, + HistogramType* out, HistogramType* tmp, uint32_t* symbols) CODE({ + size_t i; + for (i = 0; i < in_size; ++i) { + uint32_t best_out = i == 0 ? symbols[0] : symbols[i - 1]; + double best_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[best_out], tmp); + size_t j; + for (j = 0; j < num_clusters; ++j) { + const double cur_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[clusters[j]], tmp); + if (cur_bits < best_bits) { + best_bits = cur_bits; + best_out = clusters[j]; + } + } + symbols[i] = best_out; + } + + /* Recompute each out based on raw and symbols. */ + for (i = 0; i < num_clusters; ++i) { + FN(HistogramClear)(&out[clusters[i]]); + } + for (i = 0; i < in_size; ++i) { + FN(HistogramAddHistogram)(&out[symbols[i]], &in[i]); + } +}) + +/* Reorders elements of the out[0..length) array and changes values in + symbols[0..length) array in the following way: + * when called, symbols[] contains indexes into out[], and has N unique + values (possibly N < length) + * on return, symbols'[i] = f(symbols[i]) and + out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length, + where f is a bijection between the range of symbols[] and [0..N), and + the first occurrences of values in symbols'[i] come in consecutive + increasing order. + Returns N, the number of unique values in symbols[]. */ +BROTLI_INTERNAL size_t FN(BrotliHistogramReindex)(MemoryManager* m, + HistogramType* out, uint32_t* symbols, size_t length) CODE({ + static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; + uint32_t* new_index = BROTLI_ALLOC(m, uint32_t, length); + uint32_t next_index; + HistogramType* tmp; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return 0; + for (i = 0; i < length; ++i) { + new_index[i] = kInvalidIndex; + } + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == kInvalidIndex) { + new_index[symbols[i]] = next_index; + ++next_index; + } + } + /* TODO(eustas): by using idea of "cycle-sort" we can avoid allocation of + tmp and reduce the number of copying by the factor of 2. */ + tmp = BROTLI_ALLOC(m, HistogramType, next_index); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return 0; + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == next_index) { + tmp[next_index] = out[symbols[i]]; + ++next_index; + } + symbols[i] = new_index[symbols[i]]; + } + BROTLI_FREE(m, new_index); + for (i = 0; i < next_index; ++i) { + out[i] = tmp[i]; + } + BROTLI_FREE(m, tmp); + return next_index; +}) + +BROTLI_INTERNAL void FN(BrotliClusterHistograms)( + MemoryManager* m, const HistogramType* in, const size_t in_size, + size_t max_histograms, HistogramType* out, size_t* out_size, + uint32_t* histogram_symbols) CODE({ + uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, in_size); + uint32_t* clusters = BROTLI_ALLOC(m, uint32_t, in_size); + size_t num_clusters = 0; + const size_t max_input_histograms = 64; + size_t pairs_capacity = max_input_histograms * max_input_histograms / 2; + /* For the first pass of clustering, we allow all pairs. */ + HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity + 1); + /* TODO(eustas): move to "persistent" arena? */ + HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 1); + size_t i; + + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(cluster_size) || + BROTLI_IS_NULL(clusters) || BROTLI_IS_NULL(pairs)|| BROTLI_IS_NULL(tmp)) { + return; + } + + for (i = 0; i < in_size; ++i) { + cluster_size[i] = 1; + } + + for (i = 0; i < in_size; ++i) { + out[i] = in[i]; + out[i].bit_cost_ = FN(BrotliPopulationCost)(&in[i]); + histogram_symbols[i] = (uint32_t)i; + } + + for (i = 0; i < in_size; i += max_input_histograms) { + size_t num_to_combine = + BROTLI_MIN(size_t, in_size - i, max_input_histograms); + size_t num_new_clusters; + size_t j; + for (j = 0; j < num_to_combine; ++j) { + clusters[num_clusters + j] = (uint32_t)(i + j); + } + num_new_clusters = + FN(BrotliHistogramCombine)(out, tmp, cluster_size, + &histogram_symbols[i], + &clusters[num_clusters], pairs, + num_to_combine, num_to_combine, + max_histograms, pairs_capacity); + num_clusters += num_new_clusters; + } + + { + /* For the second pass, we limit the total number of histogram pairs. + After this limit is reached, we only keep searching for the best pair. */ + size_t max_num_pairs = BROTLI_MIN(size_t, + 64 * num_clusters, (num_clusters / 2) * num_clusters); + BROTLI_ENSURE_CAPACITY( + m, HistogramPair, pairs, pairs_capacity, max_num_pairs + 1); + if (BROTLI_IS_OOM(m)) return; + + /* Collapse similar histograms. */ + num_clusters = FN(BrotliHistogramCombine)(out, tmp, cluster_size, + histogram_symbols, clusters, + pairs, num_clusters, in_size, + max_histograms, max_num_pairs); + } + BROTLI_FREE(m, pairs); + BROTLI_FREE(m, cluster_size); + /* Find the optimal map from original histograms to the final ones. */ + FN(BrotliHistogramRemap)(in, in_size, clusters, num_clusters, + out, tmp, histogram_symbols); + BROTLI_FREE(m, tmp); + BROTLI_FREE(m, clusters); + /* Convert the context map to a canonical form. */ + *out_size = FN(BrotliHistogramReindex)(m, out, histogram_symbols, in_size); + if (BROTLI_IS_OOM(m)) return; +}) + +#undef HistogramType +#undef FN + +#define FN(X) X ## Distance +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN, CODE */ + +#define HistogramType FN(Histogram) + +/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if + it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */ +BROTLI_INTERNAL void FN(BrotliCompareAndPushToQueue)( + const HistogramType* out, HistogramType* tmp, const uint32_t* cluster_size, + uint32_t idx1, uint32_t idx2, size_t max_num_pairs, HistogramPair* pairs, + size_t* num_pairs) CODE({ + BROTLI_BOOL is_good_pair = BROTLI_FALSE; + HistogramPair p; + p.idx1 = p.idx2 = 0; + p.cost_diff = p.cost_combo = 0; + if (idx1 == idx2) { + return; + } + if (idx2 < idx1) { + uint32_t t = idx2; + idx2 = idx1; + idx1 = t; + } + p.idx1 = idx1; + p.idx2 = idx2; + p.cost_diff = 0.5 * ClusterCostDiff(cluster_size[idx1], cluster_size[idx2]); + p.cost_diff -= out[idx1].bit_cost_; + p.cost_diff -= out[idx2].bit_cost_; + + if (out[idx1].total_count_ == 0) { + p.cost_combo = out[idx2].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else if (out[idx2].total_count_ == 0) { + p.cost_combo = out[idx1].bit_cost_; + is_good_pair = BROTLI_TRUE; + } else { + double threshold = *num_pairs == 0 ? 1e99 : + BROTLI_MAX(double, 0.0, pairs[0].cost_diff); + double cost_combo; + *tmp = out[idx1]; + FN(HistogramAddHistogram)(tmp, &out[idx2]); + cost_combo = FN(BrotliPopulationCost)(tmp); + if (cost_combo < threshold - p.cost_diff) { + p.cost_combo = cost_combo; + is_good_pair = BROTLI_TRUE; + } + } + if (is_good_pair) { + p.cost_diff += p.cost_combo; + if (*num_pairs > 0 && HistogramPairIsLess(&pairs[0], &p)) { + /* Replace the top of the queue if needed. */ + if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = pairs[0]; + ++(*num_pairs); + } + pairs[0] = p; + } else if (*num_pairs < max_num_pairs) { + pairs[*num_pairs] = p; + ++(*num_pairs); + } + } +}) + +BROTLI_INTERNAL size_t FN(BrotliHistogramCombine)(HistogramType* out, + HistogramType* tmp, + uint32_t* cluster_size, + uint32_t* symbols, + uint32_t* clusters, + HistogramPair* pairs, + size_t num_clusters, + size_t symbols_size, + size_t max_clusters, + size_t max_num_pairs) CODE({ + double cost_diff_threshold = 0.0; + size_t min_cluster_size = 1; + size_t num_pairs = 0; + + { + /* We maintain a vector of histogram pairs, with the property that the pair + with the maximum bit cost reduction is the first. */ + size_t idx1; + for (idx1 = 0; idx1 < num_clusters; ++idx1) { + size_t idx2; + for (idx2 = idx1 + 1; idx2 < num_clusters; ++idx2) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, clusters[idx1], + clusters[idx2], max_num_pairs, &pairs[0], &num_pairs); + } + } + } + + while (num_clusters > min_cluster_size) { + uint32_t best_idx1; + uint32_t best_idx2; + size_t i; + if (pairs[0].cost_diff >= cost_diff_threshold) { + cost_diff_threshold = 1e99; + min_cluster_size = max_clusters; + continue; + } + /* Take the best pair from the top of heap. */ + best_idx1 = pairs[0].idx1; + best_idx2 = pairs[0].idx2; + FN(HistogramAddHistogram)(&out[best_idx1], &out[best_idx2]); + out[best_idx1].bit_cost_ = pairs[0].cost_combo; + cluster_size[best_idx1] += cluster_size[best_idx2]; + for (i = 0; i < symbols_size; ++i) { + if (symbols[i] == best_idx2) { + symbols[i] = best_idx1; + } + } + for (i = 0; i < num_clusters; ++i) { + if (clusters[i] == best_idx2) { + memmove(&clusters[i], &clusters[i + 1], + (num_clusters - i - 1) * sizeof(clusters[0])); + break; + } + } + --num_clusters; + { + /* Remove pairs intersecting the just combined best pair. */ + size_t copy_to_idx = 0; + for (i = 0; i < num_pairs; ++i) { + HistogramPair* p = &pairs[i]; + if (p->idx1 == best_idx1 || p->idx2 == best_idx1 || + p->idx1 == best_idx2 || p->idx2 == best_idx2) { + /* Remove invalid pair from the queue. */ + continue; + } + if (HistogramPairIsLess(&pairs[0], p)) { + /* Replace the top of the queue if needed. */ + HistogramPair front = pairs[0]; + pairs[0] = *p; + pairs[copy_to_idx] = front; + } else { + pairs[copy_to_idx] = *p; + } + ++copy_to_idx; + } + num_pairs = copy_to_idx; + } + + /* Push new pairs formed with the combined histogram to the heap. */ + for (i = 0; i < num_clusters; ++i) { + FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, best_idx1, + clusters[i], max_num_pairs, &pairs[0], &num_pairs); + } + } + return num_clusters; +}) + +/* What is the bit cost of moving histogram from cur_symbol to candidate. */ +BROTLI_INTERNAL double FN(BrotliHistogramBitCostDistance)( + const HistogramType* histogram, const HistogramType* candidate, + HistogramType* tmp) CODE({ + if (histogram->total_count_ == 0) { + return 0.0; + } else { + *tmp = *histogram; + FN(HistogramAddHistogram)(tmp, candidate); + return FN(BrotliPopulationCost)(tmp) - candidate->bit_cost_; + } +}) + +/* Find the best 'out' histogram for each of the 'in' histograms. + When called, clusters[0..num_clusters) contains the unique values from + symbols[0..in_size), but this property is not preserved in this function. + Note: we assume that out[]->bit_cost_ is already up-to-date. */ +BROTLI_INTERNAL void FN(BrotliHistogramRemap)(const HistogramType* in, + size_t in_size, const uint32_t* clusters, size_t num_clusters, + HistogramType* out, HistogramType* tmp, uint32_t* symbols) CODE({ + size_t i; + for (i = 0; i < in_size; ++i) { + uint32_t best_out = i == 0 ? symbols[0] : symbols[i - 1]; + double best_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[best_out], tmp); + size_t j; + for (j = 0; j < num_clusters; ++j) { + const double cur_bits = + FN(BrotliHistogramBitCostDistance)(&in[i], &out[clusters[j]], tmp); + if (cur_bits < best_bits) { + best_bits = cur_bits; + best_out = clusters[j]; + } + } + symbols[i] = best_out; + } + + /* Recompute each out based on raw and symbols. */ + for (i = 0; i < num_clusters; ++i) { + FN(HistogramClear)(&out[clusters[i]]); + } + for (i = 0; i < in_size; ++i) { + FN(HistogramAddHistogram)(&out[symbols[i]], &in[i]); + } +}) + +/* Reorders elements of the out[0..length) array and changes values in + symbols[0..length) array in the following way: + * when called, symbols[] contains indexes into out[], and has N unique + values (possibly N < length) + * on return, symbols'[i] = f(symbols[i]) and + out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length, + where f is a bijection between the range of symbols[] and [0..N), and + the first occurrences of values in symbols'[i] come in consecutive + increasing order. + Returns N, the number of unique values in symbols[]. */ +BROTLI_INTERNAL size_t FN(BrotliHistogramReindex)(MemoryManager* m, + HistogramType* out, uint32_t* symbols, size_t length) CODE({ + static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX; + uint32_t* new_index = BROTLI_ALLOC(m, uint32_t, length); + uint32_t next_index; + HistogramType* tmp; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return 0; + for (i = 0; i < length; ++i) { + new_index[i] = kInvalidIndex; + } + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == kInvalidIndex) { + new_index[symbols[i]] = next_index; + ++next_index; + } + } + /* TODO(eustas): by using idea of "cycle-sort" we can avoid allocation of + tmp and reduce the number of copying by the factor of 2. */ + tmp = BROTLI_ALLOC(m, HistogramType, next_index); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return 0; + next_index = 0; + for (i = 0; i < length; ++i) { + if (new_index[symbols[i]] == next_index) { + tmp[next_index] = out[symbols[i]]; + ++next_index; + } + symbols[i] = new_index[symbols[i]]; + } + BROTLI_FREE(m, new_index); + for (i = 0; i < next_index; ++i) { + out[i] = tmp[i]; + } + BROTLI_FREE(m, tmp); + return next_index; +}) + +BROTLI_INTERNAL void FN(BrotliClusterHistograms)( + MemoryManager* m, const HistogramType* in, const size_t in_size, + size_t max_histograms, HistogramType* out, size_t* out_size, + uint32_t* histogram_symbols) CODE({ + uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, in_size); + uint32_t* clusters = BROTLI_ALLOC(m, uint32_t, in_size); + size_t num_clusters = 0; + const size_t max_input_histograms = 64; + size_t pairs_capacity = max_input_histograms * max_input_histograms / 2; + /* For the first pass of clustering, we allow all pairs. */ + HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity + 1); + /* TODO(eustas): move to "persistent" arena? */ + HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 1); + size_t i; + + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(cluster_size) || + BROTLI_IS_NULL(clusters) || BROTLI_IS_NULL(pairs)|| BROTLI_IS_NULL(tmp)) { + return; + } + + for (i = 0; i < in_size; ++i) { + cluster_size[i] = 1; + } + + for (i = 0; i < in_size; ++i) { + out[i] = in[i]; + out[i].bit_cost_ = FN(BrotliPopulationCost)(&in[i]); + histogram_symbols[i] = (uint32_t)i; + } + + for (i = 0; i < in_size; i += max_input_histograms) { + size_t num_to_combine = + BROTLI_MIN(size_t, in_size - i, max_input_histograms); + size_t num_new_clusters; + size_t j; + for (j = 0; j < num_to_combine; ++j) { + clusters[num_clusters + j] = (uint32_t)(i + j); + } + num_new_clusters = + FN(BrotliHistogramCombine)(out, tmp, cluster_size, + &histogram_symbols[i], + &clusters[num_clusters], pairs, + num_to_combine, num_to_combine, + max_histograms, pairs_capacity); + num_clusters += num_new_clusters; + } + + { + /* For the second pass, we limit the total number of histogram pairs. + After this limit is reached, we only keep searching for the best pair. */ + size_t max_num_pairs = BROTLI_MIN(size_t, + 64 * num_clusters, (num_clusters / 2) * num_clusters); + BROTLI_ENSURE_CAPACITY( + m, HistogramPair, pairs, pairs_capacity, max_num_pairs + 1); + if (BROTLI_IS_OOM(m)) return; + + /* Collapse similar histograms. */ + num_clusters = FN(BrotliHistogramCombine)(out, tmp, cluster_size, + histogram_symbols, clusters, + pairs, num_clusters, in_size, + max_histograms, max_num_pairs); + } + BROTLI_FREE(m, pairs); + BROTLI_FREE(m, cluster_size); + /* Find the optimal map from original histograms to the final ones. */ + FN(BrotliHistogramRemap)(in, in_size, clusters, num_clusters, + out, tmp, histogram_symbols); + BROTLI_FREE(m, tmp); + BROTLI_FREE(m, clusters); + /* Convert the context map to a canonical form. */ + *out_size = FN(BrotliHistogramReindex)(m, out, histogram_symbols, in_size); + if (BROTLI_IS_OOM(m)) return; +}) + +#undef HistogramType +#undef FN + +#undef CODE + +} + +#endif /* BROTLI_ENC_CLUSTER_H_ */ diff --git a/third_party/brotli/enc/command.cpp b/third_party/brotli/enc/command.cpp new file mode 100644 index 00000000000..9aed7778bba --- /dev/null +++ b/third_party/brotli/enc/command.cpp @@ -0,0 +1,24 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include "command.h" + +#include + +using namespace duckdb_brotli; + +const uint32_t duckdb_brotli::kBrotliInsBase[BROTLI_NUM_INS_COPY_CODES] = { + 0, 1, 2, 3, 4, 5, 6, 8, 10, 14, 18, 26, + 34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594}; +const uint32_t duckdb_brotli::kBrotliInsExtra[BROTLI_NUM_INS_COPY_CODES] = { + 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 12, 14, 24}; +const uint32_t duckdb_brotli::kBrotliCopyBase[BROTLI_NUM_INS_COPY_CODES] = { + 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 18, + 22, 30, 38, 54, 70, 102, 134, 198, 326, 582, 1094, 2118}; +const uint32_t duckdb_brotli::kBrotliCopyExtra[BROTLI_NUM_INS_COPY_CODES] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 24}; + + diff --git a/third_party/brotli/enc/command.h b/third_party/brotli/enc/command.h new file mode 100644 index 00000000000..443f39423f9 --- /dev/null +++ b/third_party/brotli/enc/command.h @@ -0,0 +1,187 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* This class models a sequence of literals and a backward reference copy. */ + +#ifndef BROTLI_ENC_COMMAND_H_ +#define BROTLI_ENC_COMMAND_H_ + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" +#include "fast_log.h" +#include "brotli_params.h" +#include "prefix.h" + +namespace duckdb_brotli { + +BROTLI_INTERNAL extern const uint32_t + kBrotliInsBase[BROTLI_NUM_INS_COPY_CODES]; +BROTLI_INTERNAL extern const uint32_t + kBrotliInsExtra[BROTLI_NUM_INS_COPY_CODES]; +BROTLI_INTERNAL extern const uint32_t + kBrotliCopyBase[BROTLI_NUM_INS_COPY_CODES]; +BROTLI_INTERNAL extern const uint32_t + kBrotliCopyExtra[BROTLI_NUM_INS_COPY_CODES]; + +static BROTLI_INLINE uint16_t GetInsertLengthCode(size_t insertlen) { + if (insertlen < 6) { + return (uint16_t)insertlen; + } else if (insertlen < 130) { + uint32_t nbits = Log2FloorNonZero(insertlen - 2) - 1u; + return (uint16_t)((nbits << 1) + ((insertlen - 2) >> nbits) + 2); + } else if (insertlen < 2114) { + return (uint16_t)(Log2FloorNonZero(insertlen - 66) + 10); + } else if (insertlen < 6210) { + return 21u; + } else if (insertlen < 22594) { + return 22u; + } else { + return 23u; + } +} + +static BROTLI_INLINE uint16_t GetCopyLengthCode(size_t copylen) { + if (copylen < 10) { + return (uint16_t)(copylen - 2); + } else if (copylen < 134) { + uint32_t nbits = Log2FloorNonZero(copylen - 6) - 1u; + return (uint16_t)((nbits << 1) + ((copylen - 6) >> nbits) + 4); + } else if (copylen < 2118) { + return (uint16_t)(Log2FloorNonZero(copylen - 70) + 12); + } else { + return 23u; + } +} + +static BROTLI_INLINE uint16_t CombineLengthCodes( + uint16_t inscode, uint16_t copycode, BROTLI_BOOL use_last_distance) { + uint16_t bits64 = + (uint16_t)((copycode & 0x7u) | ((inscode & 0x7u) << 3u)); + if (use_last_distance && inscode < 8u && copycode < 16u) { + return (copycode < 8u) ? bits64 : (bits64 | 64u); + } else { + /* Specification: 5 Encoding of ... (last table) */ + /* offset = 2 * index, where index is in range [0..8] */ + uint32_t offset = 2u * ((copycode >> 3u) + 3u * (inscode >> 3u)); + /* All values in specification are K * 64, + where K = [2, 3, 6, 4, 5, 8, 7, 9, 10], + i + 1 = [1, 2, 3, 4, 5, 6, 7, 8, 9], + K - i - 1 = [1, 1, 3, 0, 0, 2, 0, 1, 2] = D. + All values in D require only 2 bits to encode. + Magic constant is shifted 6 bits left, to avoid final multiplication. */ + offset = (offset << 5u) + 0x40u + ((0x520D40u >> offset) & 0xC0u); + return (uint16_t)(offset | bits64); + } +} + +static BROTLI_INLINE void GetLengthCode(size_t insertlen, size_t copylen, + BROTLI_BOOL use_last_distance, + uint16_t* code) { + uint16_t inscode = GetInsertLengthCode(insertlen); + uint16_t copycode = GetCopyLengthCode(copylen); + *code = CombineLengthCodes(inscode, copycode, use_last_distance); +} + +static BROTLI_INLINE uint32_t GetInsertBase(uint16_t inscode) { + return kBrotliInsBase[inscode]; +} + +static BROTLI_INLINE uint32_t GetInsertExtra(uint16_t inscode) { + return kBrotliInsExtra[inscode]; +} + +static BROTLI_INLINE uint32_t GetCopyBase(uint16_t copycode) { + return kBrotliCopyBase[copycode]; +} + +static BROTLI_INLINE uint32_t GetCopyExtra(uint16_t copycode) { + return kBrotliCopyExtra[copycode]; +} + +typedef struct Command { + uint32_t insert_len_; + /* Stores copy_len in low 25 bits and copy_code - copy_len in high 7 bit. */ + uint32_t copy_len_; + /* Stores distance extra bits. */ + uint32_t dist_extra_; + uint16_t cmd_prefix_; + /* Stores distance code in low 10 bits + and number of extra bits in high 6 bits. */ + uint16_t dist_prefix_; +} Command; + +/* distance_code is e.g. 0 for same-as-last short code, or 16 for offset 1. */ +static BROTLI_INLINE void InitCommand(Command* self, + const BrotliDistanceParams* dist, size_t insertlen, + size_t copylen, int copylen_code_delta, size_t distance_code) { + /* Don't rely on signed int representation, use honest casts. */ + uint32_t delta = (uint8_t)((int8_t)copylen_code_delta); + self->insert_len_ = (uint32_t)insertlen; + self->copy_len_ = (uint32_t)(copylen | (delta << 25)); + /* The distance prefix and extra bits are stored in this Command as if + npostfix and ndirect were 0, they are only recomputed later after the + clustering if needed. */ + PrefixEncodeCopyDistance( + distance_code, dist->num_direct_distance_codes, + dist->distance_postfix_bits, &self->dist_prefix_, &self->dist_extra_); + GetLengthCode( + insertlen, (size_t)((int)copylen + copylen_code_delta), + TO_BROTLI_BOOL((self->dist_prefix_ & 0x3FF) == 0), &self->cmd_prefix_); +} + +static BROTLI_INLINE void InitInsertCommand(Command* self, size_t insertlen) { + self->insert_len_ = (uint32_t)insertlen; + self->copy_len_ = 4 << 25; + self->dist_extra_ = 0; + self->dist_prefix_ = BROTLI_NUM_DISTANCE_SHORT_CODES; + GetLengthCode(insertlen, 4, BROTLI_FALSE, &self->cmd_prefix_); +} + +static BROTLI_INLINE uint32_t CommandRestoreDistanceCode( + const Command* self, const BrotliDistanceParams* dist) { + if ((self->dist_prefix_ & 0x3FFu) < + BROTLI_NUM_DISTANCE_SHORT_CODES + dist->num_direct_distance_codes) { + return self->dist_prefix_ & 0x3FFu; + } else { + uint32_t dcode = self->dist_prefix_ & 0x3FFu; + uint32_t nbits = self->dist_prefix_ >> 10; + uint32_t extra = self->dist_extra_; + uint32_t postfix_mask = (1U << dist->distance_postfix_bits) - 1U; + uint32_t hcode = (dcode - dist->num_direct_distance_codes - + BROTLI_NUM_DISTANCE_SHORT_CODES) >> + dist->distance_postfix_bits; + uint32_t lcode = (dcode - dist->num_direct_distance_codes - + BROTLI_NUM_DISTANCE_SHORT_CODES) & postfix_mask; + uint32_t offset = ((2U + (hcode & 1U)) << nbits) - 4U; + return ((offset + extra) << dist->distance_postfix_bits) + lcode + + dist->num_direct_distance_codes + BROTLI_NUM_DISTANCE_SHORT_CODES; + } +} + +static BROTLI_INLINE uint32_t CommandDistanceContext(const Command* self) { + uint32_t r = self->cmd_prefix_ >> 6; + uint32_t c = self->cmd_prefix_ & 7; + if ((r == 0 || r == 2 || r == 4 || r == 7) && (c <= 2)) { + return c; + } + return 3; +} + +static BROTLI_INLINE uint32_t CommandCopyLen(const Command* self) { + return self->copy_len_ & 0x1FFFFFF; +} + +static BROTLI_INLINE uint32_t CommandCopyLenCode(const Command* self) { + uint32_t modifier = self->copy_len_ >> 25; + int32_t delta = (int8_t)((uint8_t)(modifier | ((modifier & 0x40) << 1))); + return (uint32_t)((int32_t)(self->copy_len_ & 0x1FFFFFF) + delta); +} + +} + +#endif /* BROTLI_ENC_COMMAND_H_ */ diff --git a/third_party/brotli/enc/compound_dictionary.cpp b/third_party/brotli/enc/compound_dictionary.cpp new file mode 100644 index 00000000000..9a602b74517 --- /dev/null +++ b/third_party/brotli/enc/compound_dictionary.cpp @@ -0,0 +1,209 @@ +/* Copyright 2017 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include "compound_dictionary.h" + +#include + +#include "../common/brotli_platform.h" +#include "memory.h" +#include "quality.h" + +using namespace duckdb_brotli; + +static PreparedDictionary* CreatePreparedDictionaryWithParams(MemoryManager* m, + const uint8_t* source, size_t source_size, uint32_t bucket_bits, + uint32_t slot_bits, uint32_t hash_bits, uint16_t bucket_limit) { + /* Step 1: create "bloated" hasher. */ + uint32_t num_slots = 1u << slot_bits; + uint32_t num_buckets = 1u << bucket_bits; + uint32_t hash_shift = 64u - bucket_bits; + uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits); + uint32_t slot_mask = num_slots - 1; + size_t alloc_size = (sizeof(uint32_t) << slot_bits) + + (sizeof(uint32_t) << slot_bits) + + (sizeof(uint16_t) << bucket_bits) + + (sizeof(uint32_t) << bucket_bits) + + (sizeof(uint32_t) * source_size); + uint8_t* flat = NULL; + PreparedDictionary* result = NULL; + uint16_t* num = NULL; + uint32_t* bucket_heads = NULL; + uint32_t* next_bucket = NULL; + uint32_t* slot_offsets = NULL; + uint16_t* heads = NULL; + uint32_t* items = NULL; + uint8_t** source_ref = NULL; + uint32_t i; + uint32_t* slot_size = NULL; + uint32_t* slot_limit = NULL; + uint32_t total_items = 0; + if (slot_bits > 16) return NULL; + if (slot_bits > bucket_bits) return NULL; + if (bucket_bits - slot_bits >= 16) return NULL; + + flat = BROTLI_ALLOC(m, uint8_t, alloc_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(flat)) return NULL; + + slot_size = (uint32_t*)flat; + slot_limit = (uint32_t*)(&slot_size[num_slots]); + num = (uint16_t*)(&slot_limit[num_slots]); + bucket_heads = (uint32_t*)(&num[num_buckets]); + next_bucket = (uint32_t*)(&bucket_heads[num_buckets]); + memset(num, 0, num_buckets * sizeof(num[0])); + + /* TODO(eustas): apply custom "store" order. */ + for (i = 0; i + 7 < source_size; ++i) { + const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(&source[i]) & hash_mask) * + kPreparedDictionaryHashMul64Long; + const uint32_t key = (uint32_t)(h >> hash_shift); + uint16_t count = num[key]; + next_bucket[i] = (count == 0) ? ((uint32_t)(-1)) : bucket_heads[key]; + bucket_heads[key] = i; + count++; + if (count > bucket_limit) count = bucket_limit; + num[key] = count; + } + + /* Step 2: find slot limits. */ + for (i = 0; i < num_slots; ++i) { + BROTLI_BOOL overflow = BROTLI_FALSE; + slot_limit[i] = bucket_limit; + while (BROTLI_TRUE) { + uint32_t limit = slot_limit[i]; + size_t j; + uint32_t count = 0; + overflow = BROTLI_FALSE; + for (j = i; j < num_buckets; j += num_slots) { + uint32_t size = num[j]; + /* Last chain may span behind 64K limit; overflow happens only if + we are about to use 0xFFFF+ as item offset. */ + if (count >= 0xFFFF) { + overflow = BROTLI_TRUE; + break; + } + if (size > limit) size = limit; + count += size; + } + if (!overflow) { + slot_size[i] = count; + total_items += count; + break; + } + slot_limit[i]--; + } + } + + /* Step 3: transfer data to "slim" hasher. */ + alloc_size = sizeof(PreparedDictionary) + (sizeof(uint32_t) << slot_bits) + + (sizeof(uint16_t) << bucket_bits) + (sizeof(uint32_t) * total_items) + + sizeof(uint8_t*); + + result = (PreparedDictionary*)BROTLI_ALLOC(m, uint8_t, alloc_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(result)) { + BROTLI_FREE(m, flat); + return NULL; + } + slot_offsets = (uint32_t*)(&result[1]); + heads = (uint16_t*)(&slot_offsets[num_slots]); + items = (uint32_t*)(&heads[num_buckets]); + source_ref = (uint8_t**)(&items[total_items]); + + result->magic = kLeanPreparedDictionaryMagic; + result->num_items = total_items; + result->source_size = (uint32_t)source_size; + result->hash_bits = hash_bits; + result->bucket_bits = bucket_bits; + result->slot_bits = slot_bits; + BROTLI_UNALIGNED_STORE_PTR(source_ref, source); + + total_items = 0; + for (i = 0; i < num_slots; ++i) { + slot_offsets[i] = total_items; + total_items += slot_size[i]; + slot_size[i] = 0; + } + for (i = 0; i < num_buckets; ++i) { + uint32_t slot = i & slot_mask; + uint32_t count = num[i]; + uint32_t pos; + size_t j; + size_t cursor = slot_size[slot]; + if (count > slot_limit[slot]) count = slot_limit[slot]; + if (count == 0) { + heads[i] = 0xFFFF; + continue; + } + heads[i] = (uint16_t)cursor; + cursor += slot_offsets[slot]; + slot_size[slot] += count; + pos = bucket_heads[i]; + for (j = 0; j < count; j++) { + items[cursor++] = pos; + pos = next_bucket[pos]; + } + items[cursor - 1] |= 0x80000000; + } + + BROTLI_FREE(m, flat); + return result; +} + +PreparedDictionary* duckdb_brotli::CreatePreparedDictionary(MemoryManager* m, + const uint8_t* source, size_t source_size) { + uint32_t bucket_bits = 17; + uint32_t slot_bits = 7; + uint32_t hash_bits = 40; + uint16_t bucket_limit = 32; + size_t volume = 16u << bucket_bits; + /* Tune parameters to fit dictionary size. */ + while (volume < source_size && bucket_bits < 22) { + bucket_bits++; + slot_bits++; + volume <<= 1; + } + return CreatePreparedDictionaryWithParams(m, + source, source_size, bucket_bits, slot_bits, hash_bits, bucket_limit); +} + +void duckdb_brotli::DestroyPreparedDictionary(MemoryManager* m, + PreparedDictionary* dictionary) { + if (!dictionary) return; + BROTLI_FREE(m, dictionary); +} + +BROTLI_BOOL duckdb_brotli::AttachPreparedDictionary( + CompoundDictionary* compound, const PreparedDictionary* dictionary) { + size_t length = 0; + size_t index = 0; + + if (compound->num_chunks == SHARED_BROTLI_MAX_COMPOUND_DICTS) { + return BROTLI_FALSE; + } + + if (!dictionary) return BROTLI_FALSE; + + length = dictionary->source_size; + index = compound->num_chunks; + compound->total_size += length; + compound->chunks[index] = dictionary; + compound->chunk_offsets[index + 1] = compound->total_size; + { + uint32_t* slot_offsets = (uint32_t*)(&dictionary[1]); + uint16_t* heads = (uint16_t*)(&slot_offsets[1u << dictionary->slot_bits]); + uint32_t* items = (uint32_t*)(&heads[1u << dictionary->bucket_bits]); + const void* tail = (void*)&items[dictionary->num_items]; + if (dictionary->magic == kPreparedDictionaryMagic) { + compound->chunk_source[index] = (const uint8_t*)tail; + } else { + /* dictionary->magic == kLeanPreparedDictionaryMagic */ + compound->chunk_source[index] = + (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail); + } + } + compound->num_chunks++; + return BROTLI_TRUE; +} diff --git a/third_party/brotli/enc/compound_dictionary.h b/third_party/brotli/enc/compound_dictionary.h new file mode 100644 index 00000000000..78cd5bfcc56 --- /dev/null +++ b/third_party/brotli/enc/compound_dictionary.h @@ -0,0 +1,75 @@ +/* Copyright 2017 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#ifndef BROTLI_ENC_PREPARED_DICTIONARY_H_ +#define BROTLI_ENC_PREPARED_DICTIONARY_H_ + +#include +#include + +#include "../common/brotli_platform.h" +#include "../common/brotli_constants.h" +#include "memory.h" + +namespace duckdb_brotli { + +/* "Fat" prepared dictionary, could be cooked outside of C implementation, + * e.g. on Java side. LZ77 data is copied inside PreparedDictionary struct. */ +static const uint32_t kPreparedDictionaryMagic = 0xDEBCEDE0; + +static const uint32_t kSharedDictionaryMagic = 0xDEBCEDE1; + +static const uint32_t kManagedDictionaryMagic = 0xDEBCEDE2; + +/* "Lean" prepared dictionary. LZ77 data is referenced. It is the responsibility + * of caller of "prepare dictionary" to keep the LZ77 data while prepared + * dictionary is in use. */ +static const uint32_t kLeanPreparedDictionaryMagic = 0xDEBCEDE3; + +static const uint64_t kPreparedDictionaryHashMul64Long = BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u); + +typedef struct PreparedDictionary { + uint32_t magic; + uint32_t num_items; + uint32_t source_size; + uint32_t hash_bits; + uint32_t bucket_bits; + uint32_t slot_bits; + + /* --- Dynamic size members --- */ + + /* uint32_t slot_offsets[1 << slot_bits]; */ + /* uint16_t heads[1 << bucket_bits]; */ + /* uint32_t items[variable]; */ + + /* [maybe] uint8_t* source_ref, depending on magic. */ + /* [maybe] uint8_t source[source_size], depending on magic. */ +} PreparedDictionary; + +BROTLI_INTERNAL PreparedDictionary *CreatePreparedDictionary(duckdb_brotli::MemoryManager *m, const uint8_t *source, + size_t source_size); + +BROTLI_INTERNAL void DestroyPreparedDictionary(duckdb_brotli::MemoryManager *m, PreparedDictionary *dictionary); + +typedef struct CompoundDictionary { + /* LZ77 prefix, compound dictionary */ + size_t num_chunks; + size_t total_size; + /* Client instances. */ + const PreparedDictionary *chunks[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1]; + const uint8_t *chunk_source[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1]; + size_t chunk_offsets[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1]; + + size_t num_prepared_instances_; + /* Owned instances. */ + PreparedDictionary *prepared_instances_[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1]; +} CompoundDictionary; + +BROTLI_INTERNAL BROTLI_BOOL AttachPreparedDictionary(CompoundDictionary *compound, + const PreparedDictionary *dictionary); + +} +#endif /* BROTLI_ENC_PREPARED_DICTIONARY */ diff --git a/third_party/brotli/enc/compress_fragment.cpp b/third_party/brotli/enc/compress_fragment.cpp new file mode 100644 index 00000000000..0a323e35584 --- /dev/null +++ b/third_party/brotli/enc/compress_fragment.cpp @@ -0,0 +1,796 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Function for fast encoding of an input fragment, independently from the input + history. This function uses one-pass processing: when we find a backward + match, we immediately emit the corresponding command and literal codes to + the bit stream. + + Adapted from the CompressFragment() function in + https://github.com/google/snappy/blob/master/snappy.cc */ + +#include "compress_fragment.h" + +#include /* memcmp, memcpy, memset */ + +#include + +#include "../common/brotli_platform.h" +#include "brotli_bit_stream.h" +#include "entropy_encode.h" +#include "fast_log.h" +#include "find_match_length.h" +#include "write_bits.h" + +using namespace duckdb_brotli; + +#define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18) + +/* kHashMul32 multiplier has these properties: + * The multiplier must be odd. Otherwise we may lose the highest bit. + * No long streaks of ones or zeros. + * There is no effort to ensure that it is a prime, the oddity is enough + for this use. + * The number has been tuned heuristically against compression benchmarks. */ +static const uint32_t kHashMul32 = 0x1E35A7BD; + +static BROTLI_INLINE uint32_t Hash(const uint8_t* p, size_t shift) { + const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(p) << 24) * kHashMul32; + return (uint32_t)(h >> shift); +} + +static BROTLI_INLINE uint32_t HashBytesAtOffset( + uint64_t v, int offset, size_t shift) { + BROTLI_DCHECK(offset >= 0); + BROTLI_DCHECK(offset <= 3); + { + const uint64_t h = ((v >> (8 * offset)) << 24) * kHashMul32; + return (uint32_t)(h >> shift); + } +} + +static BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2) { + return TO_BROTLI_BOOL( + BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2) && + p1[4] == p2[4]); +} + +/* Builds a literal prefix code into "depths" and "bits" based on the statistics + of the "input" string and stores it into the bit stream. + Note that the prefix code here is built from the pre-LZ77 input, therefore + we can only approximate the statistics of the actual literal stream. + Moreover, for long inputs we build a histogram from a sample of the input + and thus have to assign a non-zero depth for each literal. + Returns estimated compression ratio millibytes/char for encoding given input + with generated code. */ +static size_t BuildAndStoreLiteralPrefixCode(BrotliOnePassArena* s, + const uint8_t* input, + const size_t input_size, + uint8_t depths[256], + uint16_t bits[256], + size_t* storage_ix, + uint8_t* storage) { + uint32_t* BROTLI_RESTRICT const histogram = s->histogram; + size_t histogram_total; + size_t i; + memset(histogram, 0, sizeof(s->histogram)); + + if (input_size < (1 << 15)) { + for (i = 0; i < input_size; ++i) { + ++histogram[input[i]]; + } + histogram_total = input_size; + for (i = 0; i < 256; ++i) { + /* We weigh the first 11 samples with weight 3 to account for the + balancing effect of the LZ77 phase on the histogram. */ + const uint32_t adjust = 2 * BROTLI_MIN(uint32_t, histogram[i], 11u); + histogram[i] += adjust; + histogram_total += adjust; + } + } else { + static const size_t kSampleRate = 29; + for (i = 0; i < input_size; i += kSampleRate) { + ++histogram[input[i]]; + } + histogram_total = (input_size + kSampleRate - 1) / kSampleRate; + for (i = 0; i < 256; ++i) { + /* We add 1 to each population count to avoid 0 bit depths (since this is + only a sample and we don't know if the symbol appears or not), and we + weigh the first 11 samples with weight 3 to account for the balancing + effect of the LZ77 phase on the histogram (more frequent symbols are + more likely to be in backward references instead as literals). */ + const uint32_t adjust = 1 + 2 * BROTLI_MIN(uint32_t, histogram[i], 11u); + histogram[i] += adjust; + histogram_total += adjust; + } + } + BrotliBuildAndStoreHuffmanTreeFast(s->tree, histogram, histogram_total, + /* max_bits = */ 8, + depths, bits, storage_ix, storage); + { + size_t literal_ratio = 0; + for (i = 0; i < 256; ++i) { + if (histogram[i]) literal_ratio += histogram[i] * depths[i]; + } + /* Estimated encoding ratio, millibytes per symbol. */ + return (literal_ratio * 125) / histogram_total; + } +} + +/* Builds a command and distance prefix code (each 64 symbols) into "depth" and + "bits" based on "histogram" and stores it into the bit stream. */ +static void BuildAndStoreCommandPrefixCode(BrotliOnePassArena* s, + size_t* storage_ix, uint8_t* storage) { + const uint32_t* const histogram = s->cmd_histo; + uint8_t* const depth = s->cmd_depth; + uint16_t* const bits = s->cmd_bits; + uint8_t* BROTLI_RESTRICT const tmp_depth = s->tmp_depth; + uint16_t* BROTLI_RESTRICT const tmp_bits = s->tmp_bits; + /* TODO(eustas): do only once on initialization. */ + memset(tmp_depth, 0, BROTLI_NUM_COMMAND_SYMBOLS); + + BrotliCreateHuffmanTree(histogram, 64, 15, s->tree, depth); + BrotliCreateHuffmanTree(&histogram[64], 64, 14, s->tree, &depth[64]); + /* We have to jump through a few hoops here in order to compute + the command bits because the symbols are in a different order than in + the full alphabet. This looks complicated, but having the symbols + in this order in the command bits saves a few branches in the Emit* + functions. */ + memcpy(tmp_depth, depth, 24); + memcpy(tmp_depth + 24, depth + 40, 8); + memcpy(tmp_depth + 32, depth + 24, 8); + memcpy(tmp_depth + 40, depth + 48, 8); + memcpy(tmp_depth + 48, depth + 32, 8); + memcpy(tmp_depth + 56, depth + 56, 8); + BrotliConvertBitDepthsToSymbols(tmp_depth, 64, tmp_bits); + memcpy(bits, tmp_bits, 48); + memcpy(bits + 24, tmp_bits + 32, 16); + memcpy(bits + 32, tmp_bits + 48, 16); + memcpy(bits + 40, tmp_bits + 24, 16); + memcpy(bits + 48, tmp_bits + 40, 16); + memcpy(bits + 56, tmp_bits + 56, 16); + BrotliConvertBitDepthsToSymbols(&depth[64], 64, &bits[64]); + { + /* Create the bit length array for the full command alphabet. */ + size_t i; + memset(tmp_depth, 0, 64); /* only 64 first values were used */ + memcpy(tmp_depth, depth, 8); + memcpy(tmp_depth + 64, depth + 8, 8); + memcpy(tmp_depth + 128, depth + 16, 8); + memcpy(tmp_depth + 192, depth + 24, 8); + memcpy(tmp_depth + 384, depth + 32, 8); + for (i = 0; i < 8; ++i) { + tmp_depth[128 + 8 * i] = depth[40 + i]; + tmp_depth[256 + 8 * i] = depth[48 + i]; + tmp_depth[448 + 8 * i] = depth[56 + i]; + } + /* TODO(eustas): could/should full-length machinery be avoided? */ + BrotliStoreHuffmanTree( + tmp_depth, BROTLI_NUM_COMMAND_SYMBOLS, s->tree, storage_ix, storage); + } + BrotliStoreHuffmanTree(&depth[64], 64, s->tree, storage_ix, storage); +} + +/* REQUIRES: insertlen < 6210 */ +static BROTLI_INLINE void EmitInsertLen(size_t insertlen, + const uint8_t depth[128], + const uint16_t bits[128], + uint32_t histo[128], + size_t* storage_ix, + uint8_t* storage) { + if (insertlen < 6) { + const size_t code = insertlen + 40; + BrotliWriteBits(depth[code], bits[code], storage_ix, storage); + ++histo[code]; + } else if (insertlen < 130) { + const size_t tail = insertlen - 2; + const uint32_t nbits = Log2FloorNonZero(tail) - 1u; + const size_t prefix = tail >> nbits; + const size_t inscode = (nbits << 1) + prefix + 42; + BrotliWriteBits(depth[inscode], bits[inscode], storage_ix, storage); + BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage); + ++histo[inscode]; + } else if (insertlen < 2114) { + const size_t tail = insertlen - 66; + const uint32_t nbits = Log2FloorNonZero(tail); + const size_t code = nbits + 50; + BrotliWriteBits(depth[code], bits[code], storage_ix, storage); + BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage); + ++histo[code]; + } else { + BrotliWriteBits(depth[61], bits[61], storage_ix, storage); + BrotliWriteBits(12, insertlen - 2114, storage_ix, storage); + ++histo[61]; + } +} + +static BROTLI_INLINE void EmitLongInsertLen(size_t insertlen, + const uint8_t depth[128], + const uint16_t bits[128], + uint32_t histo[128], + size_t* storage_ix, + uint8_t* storage) { + if (insertlen < 22594) { + BrotliWriteBits(depth[62], bits[62], storage_ix, storage); + BrotliWriteBits(14, insertlen - 6210, storage_ix, storage); + ++histo[62]; + } else { + BrotliWriteBits(depth[63], bits[63], storage_ix, storage); + BrotliWriteBits(24, insertlen - 22594, storage_ix, storage); + ++histo[63]; + } +} + +static BROTLI_INLINE void EmitCopyLen(size_t copylen, + const uint8_t depth[128], + const uint16_t bits[128], + uint32_t histo[128], + size_t* storage_ix, + uint8_t* storage) { + if (copylen < 10) { + BrotliWriteBits( + depth[copylen + 14], bits[copylen + 14], storage_ix, storage); + ++histo[copylen + 14]; + } else if (copylen < 134) { + const size_t tail = copylen - 6; + const uint32_t nbits = Log2FloorNonZero(tail) - 1u; + const size_t prefix = tail >> nbits; + const size_t code = (nbits << 1) + prefix + 20; + BrotliWriteBits(depth[code], bits[code], storage_ix, storage); + BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage); + ++histo[code]; + } else if (copylen < 2118) { + const size_t tail = copylen - 70; + const uint32_t nbits = Log2FloorNonZero(tail); + const size_t code = nbits + 28; + BrotliWriteBits(depth[code], bits[code], storage_ix, storage); + BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage); + ++histo[code]; + } else { + BrotliWriteBits(depth[39], bits[39], storage_ix, storage); + BrotliWriteBits(24, copylen - 2118, storage_ix, storage); + ++histo[39]; + } +} + +static BROTLI_INLINE void EmitCopyLenLastDistance(size_t copylen, + const uint8_t depth[128], + const uint16_t bits[128], + uint32_t histo[128], + size_t* storage_ix, + uint8_t* storage) { + if (copylen < 12) { + BrotliWriteBits(depth[copylen - 4], bits[copylen - 4], storage_ix, storage); + ++histo[copylen - 4]; + } else if (copylen < 72) { + const size_t tail = copylen - 8; + const uint32_t nbits = Log2FloorNonZero(tail) - 1; + const size_t prefix = tail >> nbits; + const size_t code = (nbits << 1) + prefix + 4; + BrotliWriteBits(depth[code], bits[code], storage_ix, storage); + BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage); + ++histo[code]; + } else if (copylen < 136) { + const size_t tail = copylen - 8; + const size_t code = (tail >> 5) + 30; + BrotliWriteBits(depth[code], bits[code], storage_ix, storage); + BrotliWriteBits(5, tail & 31, storage_ix, storage); + BrotliWriteBits(depth[64], bits[64], storage_ix, storage); + ++histo[code]; + ++histo[64]; + } else if (copylen < 2120) { + const size_t tail = copylen - 72; + const uint32_t nbits = Log2FloorNonZero(tail); + const size_t code = nbits + 28; + BrotliWriteBits(depth[code], bits[code], storage_ix, storage); + BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage); + BrotliWriteBits(depth[64], bits[64], storage_ix, storage); + ++histo[code]; + ++histo[64]; + } else { + BrotliWriteBits(depth[39], bits[39], storage_ix, storage); + BrotliWriteBits(24, copylen - 2120, storage_ix, storage); + BrotliWriteBits(depth[64], bits[64], storage_ix, storage); + ++histo[39]; + ++histo[64]; + } +} + +static BROTLI_INLINE void EmitDistance(size_t distance, + const uint8_t depth[128], + const uint16_t bits[128], + uint32_t histo[128], + size_t* storage_ix, uint8_t* storage) { + const size_t d = distance + 3; + const uint32_t nbits = Log2FloorNonZero(d) - 1u; + const size_t prefix = (d >> nbits) & 1; + const size_t offset = (2 + prefix) << nbits; + const size_t distcode = 2 * (nbits - 1) + prefix + 80; + BrotliWriteBits(depth[distcode], bits[distcode], storage_ix, storage); + BrotliWriteBits(nbits, d - offset, storage_ix, storage); + ++histo[distcode]; +} + +static BROTLI_INLINE void EmitLiterals(const uint8_t* input, const size_t len, + const uint8_t depth[256], + const uint16_t bits[256], + size_t* storage_ix, uint8_t* storage) { + size_t j; + for (j = 0; j < len; j++) { + const uint8_t lit = input[j]; + BrotliWriteBits(depth[lit], bits[lit], storage_ix, storage); + } +} + +/* REQUIRES: len <= 1 << 24. */ +static void BrotliStoreMetaBlockHeader( + size_t len, BROTLI_BOOL is_uncompressed, size_t* storage_ix, + uint8_t* storage) { + size_t nibbles = 6; + /* ISLAST */ + BrotliWriteBits(1, 0, storage_ix, storage); + if (len <= (1U << 16)) { + nibbles = 4; + } else if (len <= (1U << 20)) { + nibbles = 5; + } + BrotliWriteBits(2, nibbles - 4, storage_ix, storage); + BrotliWriteBits(nibbles * 4, len - 1, storage_ix, storage); + /* ISUNCOMPRESSED */ + BrotliWriteBits(1, (uint64_t)is_uncompressed, storage_ix, storage); +} + +static void UpdateBits(size_t n_bits, uint32_t bits, size_t pos, + uint8_t* array) { + while (n_bits > 0) { + size_t byte_pos = pos >> 3; + size_t n_unchanged_bits = pos & 7; + size_t n_changed_bits = BROTLI_MIN(size_t, n_bits, 8 - n_unchanged_bits); + size_t total_bits = n_unchanged_bits + n_changed_bits; + uint32_t mask = + (~((1u << total_bits) - 1u)) | ((1u << n_unchanged_bits) - 1u); + uint32_t unchanged_bits = array[byte_pos] & mask; + uint32_t changed_bits = bits & ((1u << n_changed_bits) - 1u); + array[byte_pos] = + (uint8_t)((changed_bits << n_unchanged_bits) | unchanged_bits); + n_bits -= n_changed_bits; + bits >>= n_changed_bits; + pos += n_changed_bits; + } +} + +static void RewindBitPosition(const size_t new_storage_ix, + size_t* storage_ix, uint8_t* storage) { + const size_t bitpos = new_storage_ix & 7; + const size_t mask = (1u << bitpos) - 1; + storage[new_storage_ix >> 3] &= (uint8_t)mask; + *storage_ix = new_storage_ix; +} + +static BROTLI_BOOL ShouldMergeBlock(BrotliOnePassArena* s, + const uint8_t* data, size_t len, const uint8_t* depths) { + uint32_t* BROTLI_RESTRICT const histo = s->histogram; + static const size_t kSampleRate = 43; + size_t i; + memset(histo, 0, sizeof(s->histogram)); + for (i = 0; i < len; i += kSampleRate) { + ++histo[data[i]]; + } + { + const size_t total = (len + kSampleRate - 1) / kSampleRate; + double r = (FastLog2(total) + 0.5) * (double)total + 200; + for (i = 0; i < 256; ++i) { + r -= (double)histo[i] * (depths[i] + FastLog2(histo[i])); + } + return TO_BROTLI_BOOL(r >= 0.0); + } +} + +/* Acceptable loss for uncompressible speedup is 2% */ +#define MIN_RATIO 980 + +static BROTLI_INLINE BROTLI_BOOL ShouldUseUncompressedMode( + const uint8_t* metablock_start, const uint8_t* next_emit, + const size_t insertlen, const size_t literal_ratio) { + const size_t compressed = (size_t)(next_emit - metablock_start); + if (compressed * 50 > insertlen) { + return BROTLI_FALSE; + } else { + return TO_BROTLI_BOOL(literal_ratio > MIN_RATIO); + } +} + +static void EmitUncompressedMetaBlock(const uint8_t* begin, const uint8_t* end, + const size_t storage_ix_start, + size_t* storage_ix, uint8_t* storage) { + const size_t len = (size_t)(end - begin); + RewindBitPosition(storage_ix_start, storage_ix, storage); + BrotliStoreMetaBlockHeader(len, 1, storage_ix, storage); + *storage_ix = (*storage_ix + 7u) & ~7u; + memcpy(&storage[*storage_ix >> 3], begin, len); + *storage_ix += len << 3; + storage[*storage_ix >> 3] = 0; +} + +static uint32_t kCmdHistoSeed[128] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, +}; + +static BROTLI_INLINE void BrotliCompressFragmentFastImpl( + BrotliOnePassArena* s, const uint8_t* input, size_t input_size, + BROTLI_BOOL is_last, int* table, size_t table_bits, + size_t* storage_ix, uint8_t* storage) { + uint8_t* BROTLI_RESTRICT const cmd_depth = s->cmd_depth; + uint16_t* BROTLI_RESTRICT const cmd_bits = s->cmd_bits; + uint32_t* BROTLI_RESTRICT const cmd_histo = s->cmd_histo; + uint8_t* BROTLI_RESTRICT const lit_depth = s->lit_depth; + uint16_t* BROTLI_RESTRICT const lit_bits = s->lit_bits; + const uint8_t* ip_end; + + /* "next_emit" is a pointer to the first byte that is not covered by a + previous copy. Bytes between "next_emit" and the start of the next copy or + the end of the input will be emitted as literal bytes. */ + const uint8_t* next_emit = input; + /* Save the start of the first block for position and distance computations. + */ + const uint8_t* base_ip = input; + + static const size_t kFirstBlockSize = 3 << 15; + static const size_t kMergeBlockSize = 1 << 16; + + const size_t kInputMarginBytes = BROTLI_WINDOW_GAP; + const size_t kMinMatchLen = 5; + + const uint8_t* metablock_start = input; + size_t block_size = BROTLI_MIN(size_t, input_size, kFirstBlockSize); + size_t total_block_size = block_size; + /* Save the bit position of the MLEN field of the meta-block header, so that + we can update it later if we decide to extend this meta-block. */ + size_t mlen_storage_ix = *storage_ix + 3; + + size_t literal_ratio; + + const uint8_t* ip; + int last_distance; + + const size_t shift = 64u - table_bits; + + BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage); + /* No block splits, no contexts. */ + BrotliWriteBits(13, 0, storage_ix, storage); + + literal_ratio = BuildAndStoreLiteralPrefixCode( + s, input, block_size, s->lit_depth, s->lit_bits, storage_ix, storage); + + { + /* Store the pre-compressed command and distance prefix codes. */ + size_t i; + for (i = 0; i + 7 < s->cmd_code_numbits; i += 8) { + BrotliWriteBits(8, s->cmd_code[i >> 3], storage_ix, storage); + } + } + BrotliWriteBits(s->cmd_code_numbits & 7, + s->cmd_code[s->cmd_code_numbits >> 3], storage_ix, storage); + + emit_commands: + /* Initialize the command and distance histograms. We will gather + statistics of command and distance codes during the processing + of this block and use it to update the command and distance + prefix codes for the next block. */ + memcpy(s->cmd_histo, kCmdHistoSeed, sizeof(kCmdHistoSeed)); + + /* "ip" is the input pointer. */ + ip = input; + last_distance = -1; + ip_end = input + block_size; + + if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) { + /* For the last block, we need to keep a 16 bytes margin so that we can be + sure that all distances are at most window size - 16. + For all other blocks, we only need to keep a margin of 5 bytes so that + we don't go over the block size with a copy. */ + const size_t len_limit = BROTLI_MIN(size_t, block_size - kMinMatchLen, + input_size - kInputMarginBytes); + const uint8_t* ip_limit = input + len_limit; + + uint32_t next_hash; + for (next_hash = Hash(++ip, shift); ; ) { + /* Step 1: Scan forward in the input looking for a 5-byte-long match. + If we get close to exhausting the input then goto emit_remainder. + + Heuristic match skipping: If 32 bytes are scanned with no matches + found, start looking only at every other byte. If 32 more bytes are + scanned, look at every third byte, etc.. When a match is found, + immediately go back to looking at every byte. This is a small loss + (~5% performance, ~0.1% density) for compressible data due to more + bookkeeping, but for non-compressible data (such as JPEG) it's a huge + win since the compressor quickly "realizes" the data is incompressible + and doesn't bother looking for matches everywhere. + + The "skip" variable keeps track of how many bytes there are since the + last match; dividing it by 32 (i.e. right-shifting by five) gives the + number of bytes to move ahead for each iteration. */ + uint32_t skip = 32; + + const uint8_t* next_ip = ip; + const uint8_t* candidate; + BROTLI_DCHECK(next_emit < ip); +trawl: + do { + uint32_t hash = next_hash; + uint32_t bytes_between_hash_lookups = skip++ >> 5; + BROTLI_DCHECK(hash == Hash(next_ip, shift)); + ip = next_ip; + next_ip = ip + bytes_between_hash_lookups; + if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) { + goto emit_remainder; + } + next_hash = Hash(next_ip, shift); + candidate = ip - last_distance; + if (IsMatch(ip, candidate)) { + if (BROTLI_PREDICT_TRUE(candidate < ip)) { + table[hash] = (int)(ip - base_ip); + break; + } + } + candidate = base_ip + table[hash]; + BROTLI_DCHECK(candidate >= base_ip); + BROTLI_DCHECK(candidate < ip); + + table[hash] = (int)(ip - base_ip); + } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate))); + + /* Check copy distance. If candidate is not feasible, continue search. + Checking is done outside of hot loop to reduce overhead. */ + if (ip - candidate > MAX_DISTANCE) goto trawl; + + /* Step 2: Emit the found match together with the literal bytes from + "next_emit" to the bit stream, and then see if we can find a next match + immediately afterwards. Repeat until we find no match for the input + without emitting some literal bytes. */ + + { + /* We have a 5-byte match at ip, and we need to emit bytes in + [next_emit, ip). */ + const uint8_t* base = ip; + size_t matched = 5 + FindMatchLengthWithLimit( + candidate + 5, ip + 5, (size_t)(ip_end - ip) - 5); + int distance = (int)(base - candidate); /* > 0 */ + size_t insert = (size_t)(base - next_emit); + ip += matched; + BROTLI_LOG(("[CompressFragment] pos = %d insert = %lu copy = %d\n", + (int)(next_emit - base_ip), (unsigned long)insert, 2)); + BROTLI_DCHECK(0 == memcmp(base, candidate, matched)); + if (BROTLI_PREDICT_TRUE(insert < 6210)) { + EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo, + storage_ix, storage); + } else if (ShouldUseUncompressedMode(metablock_start, next_emit, insert, + literal_ratio)) { + EmitUncompressedMetaBlock(metablock_start, base, mlen_storage_ix - 3, + storage_ix, storage); + input_size -= (size_t)(base - input); + input = base; + next_emit = input; + goto next_block; + } else { + EmitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo, + storage_ix, storage); + } + EmitLiterals(next_emit, insert, lit_depth, lit_bits, + storage_ix, storage); + if (distance == last_distance) { + BrotliWriteBits(cmd_depth[64], cmd_bits[64], storage_ix, storage); + ++cmd_histo[64]; + } else { + EmitDistance((size_t)distance, cmd_depth, cmd_bits, + cmd_histo, storage_ix, storage); + last_distance = distance; + } + EmitCopyLenLastDistance(matched, cmd_depth, cmd_bits, cmd_histo, + storage_ix, storage); + BROTLI_LOG(("[CompressFragment] pos = %d distance = %d\n" + "[CompressFragment] pos = %d insert = %d copy = %d\n" + "[CompressFragment] pos = %d distance = %d\n", + (int)(base - base_ip), (int)distance, + (int)(base - base_ip) + 2, 0, (int)matched - 2, + (int)(base - base_ip) + 2, (int)distance)); + + next_emit = ip; + if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) { + goto emit_remainder; + } + /* We could immediately start working at ip now, but to improve + compression we first update "table" with the hashes of some positions + within the last copy. */ + { + uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3); + uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift); + uint32_t cur_hash = HashBytesAtOffset(input_bytes, 3, shift); + table[prev_hash] = (int)(ip - base_ip - 3); + prev_hash = HashBytesAtOffset(input_bytes, 1, shift); + table[prev_hash] = (int)(ip - base_ip - 2); + prev_hash = HashBytesAtOffset(input_bytes, 2, shift); + table[prev_hash] = (int)(ip - base_ip - 1); + + candidate = base_ip + table[cur_hash]; + table[cur_hash] = (int)(ip - base_ip); + } + } + + while (IsMatch(ip, candidate)) { + /* We have a 5-byte match at ip, and no need to emit any literal bytes + prior to ip. */ + const uint8_t* base = ip; + size_t matched = 5 + FindMatchLengthWithLimit( + candidate + 5, ip + 5, (size_t)(ip_end - ip) - 5); + if (ip - candidate > MAX_DISTANCE) break; + ip += matched; + last_distance = (int)(base - candidate); /* > 0 */ + BROTLI_DCHECK(0 == memcmp(base, candidate, matched)); + EmitCopyLen(matched, cmd_depth, cmd_bits, cmd_histo, + storage_ix, storage); + EmitDistance((size_t)last_distance, cmd_depth, cmd_bits, + cmd_histo, storage_ix, storage); + BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n" + "[CompressFragment] pos = %d distance = %d\n", + (int)(base - base_ip), 0, (int)matched, + (int)(base - base_ip), (int)last_distance)); + + next_emit = ip; + if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) { + goto emit_remainder; + } + /* We could immediately start working at ip now, but to improve + compression we first update "table" with the hashes of some positions + within the last copy. */ + { + uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3); + uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift); + uint32_t cur_hash = HashBytesAtOffset(input_bytes, 3, shift); + table[prev_hash] = (int)(ip - base_ip - 3); + prev_hash = HashBytesAtOffset(input_bytes, 1, shift); + table[prev_hash] = (int)(ip - base_ip - 2); + prev_hash = HashBytesAtOffset(input_bytes, 2, shift); + table[prev_hash] = (int)(ip - base_ip - 1); + + candidate = base_ip + table[cur_hash]; + table[cur_hash] = (int)(ip - base_ip); + } + } + + next_hash = Hash(++ip, shift); + } + } + + emit_remainder: + BROTLI_DCHECK(next_emit <= ip_end); + input += block_size; + input_size -= block_size; + block_size = BROTLI_MIN(size_t, input_size, kMergeBlockSize); + + /* Decide if we want to continue this meta-block instead of emitting the + last insert-only command. */ + if (input_size > 0 && + total_block_size + block_size <= (1 << 20) && + ShouldMergeBlock(s, input, block_size, lit_depth)) { + BROTLI_DCHECK(total_block_size > (1 << 16)); + /* Update the size of the current meta-block and continue emitting commands. + We can do this because the current size and the new size both have 5 + nibbles. */ + total_block_size += block_size; + UpdateBits(20, (uint32_t)(total_block_size - 1), mlen_storage_ix, storage); + goto emit_commands; + } + + /* Emit the remaining bytes as literals. */ + if (next_emit < ip_end) { + const size_t insert = (size_t)(ip_end - next_emit); + BROTLI_LOG(("[CompressFragment] pos = %d insert = %lu copy = %d\n", + (int)(next_emit - base_ip), (unsigned long)insert, 2)); + if (BROTLI_PREDICT_TRUE(insert < 6210)) { + EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo, + storage_ix, storage); + EmitLiterals(next_emit, insert, lit_depth, lit_bits, storage_ix, storage); + } else if (ShouldUseUncompressedMode(metablock_start, next_emit, insert, + literal_ratio)) { + EmitUncompressedMetaBlock(metablock_start, ip_end, mlen_storage_ix - 3, + storage_ix, storage); + } else { + EmitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo, + storage_ix, storage); + EmitLiterals(next_emit, insert, lit_depth, lit_bits, + storage_ix, storage); + } + } + next_emit = ip_end; + +next_block: + /* If we have more data, write a new meta-block header and prefix codes and + then continue emitting commands. */ + if (input_size > 0) { + metablock_start = input; + block_size = BROTLI_MIN(size_t, input_size, kFirstBlockSize); + total_block_size = block_size; + /* Save the bit position of the MLEN field of the meta-block header, so that + we can update it later if we decide to extend this meta-block. */ + mlen_storage_ix = *storage_ix + 3; + BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage); + /* No block splits, no contexts. */ + BrotliWriteBits(13, 0, storage_ix, storage); + literal_ratio = BuildAndStoreLiteralPrefixCode( + s, input, block_size, lit_depth, lit_bits, storage_ix, storage); + BuildAndStoreCommandPrefixCode(s, storage_ix, storage); + goto emit_commands; + } + + if (!is_last) { + /* If this is not the last block, update the command and distance prefix + codes for the next block and store the compressed forms. */ + s->cmd_code[0] = 0; + s->cmd_code_numbits = 0; + BuildAndStoreCommandPrefixCode(s, &s->cmd_code_numbits, s->cmd_code); + } +} + +#define FOR_TABLE_BITS_(X) X(9) X(11) X(13) X(15) + +#define BAKE_METHOD_PARAM_(B) \ +static BROTLI_NOINLINE void BrotliCompressFragmentFastImpl ## B( \ + BrotliOnePassArena* s, const uint8_t* input, size_t input_size, \ + BROTLI_BOOL is_last, int* table, size_t* storage_ix, uint8_t* storage) { \ + BrotliCompressFragmentFastImpl(s, input, input_size, is_last, table, B, \ + storage_ix, storage); \ +} +FOR_TABLE_BITS_(BAKE_METHOD_PARAM_) +#undef BAKE_METHOD_PARAM_ + +void duckdb_brotli::BrotliCompressFragmentFast( + BrotliOnePassArena* s, const uint8_t* input, size_t input_size, + BROTLI_BOOL is_last, int* table, size_t table_size, + size_t* storage_ix, uint8_t* storage) { + const size_t initial_storage_ix = *storage_ix; + const size_t table_bits = Log2FloorNonZero(table_size); + + if (input_size == 0) { + BROTLI_DCHECK(is_last); + BrotliWriteBits(1, 1, storage_ix, storage); /* islast */ + BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */ + *storage_ix = (*storage_ix + 7u) & ~7u; + return; + } + + switch (table_bits) { +#define CASE_(B) \ + case B: \ + BrotliCompressFragmentFastImpl ## B( \ + s, input, input_size, is_last, table, storage_ix, storage);\ + break; + FOR_TABLE_BITS_(CASE_) +#undef CASE_ + default: BROTLI_DCHECK(0); break; + } + + /* If output is larger than single uncompressed block, rewrite it. */ + if (*storage_ix - initial_storage_ix > 31 + (input_size << 3)) { + EmitUncompressedMetaBlock(input, input + input_size, initial_storage_ix, + storage_ix, storage); + } + + if (is_last) { + BrotliWriteBits(1, 1, storage_ix, storage); /* islast */ + BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */ + *storage_ix = (*storage_ix + 7u) & ~7u; + } +} + +#undef FOR_TABLE_BITS_ + + diff --git a/third_party/brotli/enc/compress_fragment.h b/third_party/brotli/enc/compress_fragment.h new file mode 100644 index 00000000000..dbfe82cc408 --- /dev/null +++ b/third_party/brotli/enc/compress_fragment.h @@ -0,0 +1,82 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Function for fast encoding of an input fragment, independently from the input + history. This function uses one-pass processing: when we find a backward + match, we immediately emit the corresponding command and literal codes to + the bit stream. */ + +#ifndef BROTLI_ENC_COMPRESS_FRAGMENT_H_ +#define BROTLI_ENC_COMPRESS_FRAGMENT_H_ + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" +#include "entropy_encode.h" + +namespace duckdb_brotli { + +typedef struct BrotliOnePassArena { + uint8_t lit_depth[256]; + uint16_t lit_bits[256]; + + /* Command and distance prefix codes (each 64 symbols, stored back-to-back) + used for the next block. The command prefix code is over a smaller alphabet + with the following 64 symbols: + 0 - 15: insert length code 0, copy length code 0 - 15, same distance + 16 - 39: insert length code 0, copy length code 0 - 23 + 40 - 63: insert length code 0 - 23, copy length code 0 + Note that symbols 16 and 40 represent the same code in the full alphabet, + but we do not use either of them. */ + uint8_t cmd_depth[128]; + uint16_t cmd_bits[128]; + uint32_t cmd_histo[128]; + + /* The compressed form of the command and distance prefix codes for the next + block. */ + uint8_t cmd_code[512]; + size_t cmd_code_numbits; + + HuffmanTree tree[2 * BROTLI_NUM_LITERAL_SYMBOLS + 1]; + uint32_t histogram[256]; + uint8_t tmp_depth[BROTLI_NUM_COMMAND_SYMBOLS]; + uint16_t tmp_bits[64]; +} BrotliOnePassArena; + +/* Compresses "input" string to the "*storage" buffer as one or more complete + meta-blocks, and updates the "*storage_ix" bit position. + + If "is_last" is 1, emits an additional empty last meta-block. + + "cmd_depth" and "cmd_bits" contain the command and distance prefix codes + (see comment in encode.h) used for the encoding of this input fragment. + If "is_last" is 0, they are updated to reflect the statistics + of this input fragment, to be used for the encoding of the next fragment. + + "*cmd_code_numbits" is the number of bits of the compressed representation + of the command and distance prefix codes, and "cmd_code" is an array of + at least "(*cmd_code_numbits + 7) >> 3" size that contains the compressed + command and distance prefix codes. If "is_last" is 0, these are also + updated to represent the updated "cmd_depth" and "cmd_bits". + + REQUIRES: "input_size" is greater than zero, or "is_last" is 1. + REQUIRES: "input_size" is less or equal to maximal metablock size (1 << 24). + REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero. + REQUIRES: "table_size" is an odd (9, 11, 13, 15) power of two + OUTPUT: maximal copy distance <= |input_size| + OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */ +BROTLI_INTERNAL void BrotliCompressFragmentFast(BrotliOnePassArena* s, + const uint8_t* input, + size_t input_size, + BROTLI_BOOL is_last, + int* table, size_t table_size, + size_t* storage_ix, + uint8_t* storage); + +} + +#endif /* BROTLI_ENC_COMPRESS_FRAGMENT_H_ */ diff --git a/third_party/brotli/enc/compress_fragment_two_pass.cpp b/third_party/brotli/enc/compress_fragment_two_pass.cpp new file mode 100644 index 00000000000..1cc436aa727 --- /dev/null +++ b/third_party/brotli/enc/compress_fragment_two_pass.cpp @@ -0,0 +1,653 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Function for fast encoding of an input fragment, independently from the input + history. This function uses two-pass processing: in the first pass we save + the found backward matches and literal bytes into a buffer, and in the + second pass we emit them into the bit stream using prefix codes built based + on the actual command and literal byte histograms. */ + +#include "compress_fragment_two_pass.h" + +#include /* memcmp, memcpy, memset */ + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" +#include "bit_cost.h" +#include "brotli_bit_stream.h" +#include "entropy_encode.h" +#include "fast_log.h" +#include "find_match_length.h" +#include "write_bits.h" + +using namespace duckdb_brotli; + +#define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18) + +/* kHashMul32 multiplier has these properties: + * The multiplier must be odd. Otherwise we may lose the highest bit. + * No long streaks of ones or zeros. + * There is no effort to ensure that it is a prime, the oddity is enough + for this use. + * The number has been tuned heuristically against compression benchmarks. */ +static const uint32_t kHashMul32 = 0x1E35A7BD; + +static BROTLI_INLINE uint32_t Hash(const uint8_t* p, + size_t shift, size_t length) { + const uint64_t h = + (BROTLI_UNALIGNED_LOAD64LE(p) << ((8 - length) * 8)) * kHashMul32; + return (uint32_t)(h >> shift); +} + +static BROTLI_INLINE uint32_t HashBytesAtOffset(uint64_t v, size_t offset, + size_t shift, size_t length) { + BROTLI_DCHECK(offset <= 8 - length); + { + const uint64_t h = ((v >> (8 * offset)) << ((8 - length) * 8)) * kHashMul32; + return (uint32_t)(h >> shift); + } +} + +static BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2, + size_t length) { + if (BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2)) { + if (length == 4) return BROTLI_TRUE; + return TO_BROTLI_BOOL(p1[4] == p2[4] && p1[5] == p2[5]); + } + return BROTLI_FALSE; +} + +/* Builds a command and distance prefix code (each 64 symbols) into "depth" and + "bits" based on "histogram" and stores it into the bit stream. */ +static void BuildAndStoreCommandPrefixCode(BrotliTwoPassArena* s, + size_t* storage_ix, + uint8_t* storage) { + /* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */ + /* TODO(eustas): initialize once. */ + memset(s->tmp_depth, 0, sizeof(s->tmp_depth)); + BrotliCreateHuffmanTree(s->cmd_histo, 64, 15, s->tmp_tree, s->cmd_depth); + BrotliCreateHuffmanTree(&s->cmd_histo[64], 64, 14, s->tmp_tree, + &s->cmd_depth[64]); + /* We have to jump through a few hoops here in order to compute + the command bits because the symbols are in a different order than in + the full alphabet. This looks complicated, but having the symbols + in this order in the command bits saves a few branches in the Emit* + functions. */ + memcpy(s->tmp_depth, s->cmd_depth + 24, 24); + memcpy(s->tmp_depth + 24, s->cmd_depth, 8); + memcpy(s->tmp_depth + 32, s->cmd_depth + 48, 8); + memcpy(s->tmp_depth + 40, s->cmd_depth + 8, 8); + memcpy(s->tmp_depth + 48, s->cmd_depth + 56, 8); + memcpy(s->tmp_depth + 56, s->cmd_depth + 16, 8); + BrotliConvertBitDepthsToSymbols(s->tmp_depth, 64, s->tmp_bits); + memcpy(s->cmd_bits, s->tmp_bits + 24, 16); + memcpy(s->cmd_bits + 8, s->tmp_bits + 40, 16); + memcpy(s->cmd_bits + 16, s->tmp_bits + 56, 16); + memcpy(s->cmd_bits + 24, s->tmp_bits, 48); + memcpy(s->cmd_bits + 48, s->tmp_bits + 32, 16); + memcpy(s->cmd_bits + 56, s->tmp_bits + 48, 16); + BrotliConvertBitDepthsToSymbols(&s->cmd_depth[64], 64, &s->cmd_bits[64]); + { + /* Create the bit length array for the full command alphabet. */ + size_t i; + memset(s->tmp_depth, 0, 64); /* only 64 first values were used */ + memcpy(s->tmp_depth, s->cmd_depth + 24, 8); + memcpy(s->tmp_depth + 64, s->cmd_depth + 32, 8); + memcpy(s->tmp_depth + 128, s->cmd_depth + 40, 8); + memcpy(s->tmp_depth + 192, s->cmd_depth + 48, 8); + memcpy(s->tmp_depth + 384, s->cmd_depth + 56, 8); + for (i = 0; i < 8; ++i) { + s->tmp_depth[128 + 8 * i] = s->cmd_depth[i]; + s->tmp_depth[256 + 8 * i] = s->cmd_depth[8 + i]; + s->tmp_depth[448 + 8 * i] = s->cmd_depth[16 + i]; + } + BrotliStoreHuffmanTree(s->tmp_depth, BROTLI_NUM_COMMAND_SYMBOLS, + s->tmp_tree, storage_ix, storage); + } + BrotliStoreHuffmanTree(&s->cmd_depth[64], 64, s->tmp_tree, storage_ix, + storage); +} + +static BROTLI_INLINE void EmitInsertLen( + uint32_t insertlen, uint32_t** commands) { + if (insertlen < 6) { + **commands = insertlen; + } else if (insertlen < 130) { + const uint32_t tail = insertlen - 2; + const uint32_t nbits = Log2FloorNonZero(tail) - 1u; + const uint32_t prefix = tail >> nbits; + const uint32_t inscode = (nbits << 1) + prefix + 2; + const uint32_t extra = tail - (prefix << nbits); + **commands = inscode | (extra << 8); + } else if (insertlen < 2114) { + const uint32_t tail = insertlen - 66; + const uint32_t nbits = Log2FloorNonZero(tail); + const uint32_t code = nbits + 10; + const uint32_t extra = tail - (1u << nbits); + **commands = code | (extra << 8); + } else if (insertlen < 6210) { + const uint32_t extra = insertlen - 2114; + **commands = 21 | (extra << 8); + } else if (insertlen < 22594) { + const uint32_t extra = insertlen - 6210; + **commands = 22 | (extra << 8); + } else { + const uint32_t extra = insertlen - 22594; + **commands = 23 | (extra << 8); + } + ++(*commands); +} + +static BROTLI_INLINE void EmitCopyLen(size_t copylen, uint32_t** commands) { + if (copylen < 10) { + **commands = (uint32_t)(copylen + 38); + } else if (copylen < 134) { + const size_t tail = copylen - 6; + const size_t nbits = Log2FloorNonZero(tail) - 1; + const size_t prefix = tail >> nbits; + const size_t code = (nbits << 1) + prefix + 44; + const size_t extra = tail - (prefix << nbits); + **commands = (uint32_t)(code | (extra << 8)); + } else if (copylen < 2118) { + const size_t tail = copylen - 70; + const size_t nbits = Log2FloorNonZero(tail); + const size_t code = nbits + 52; + const size_t extra = tail - ((size_t)1 << nbits); + **commands = (uint32_t)(code | (extra << 8)); + } else { + const size_t extra = copylen - 2118; + **commands = (uint32_t)(63 | (extra << 8)); + } + ++(*commands); +} + +static BROTLI_INLINE void EmitCopyLenLastDistance( + size_t copylen, uint32_t** commands) { + if (copylen < 12) { + **commands = (uint32_t)(copylen + 20); + ++(*commands); + } else if (copylen < 72) { + const size_t tail = copylen - 8; + const size_t nbits = Log2FloorNonZero(tail) - 1; + const size_t prefix = tail >> nbits; + const size_t code = (nbits << 1) + prefix + 28; + const size_t extra = tail - (prefix << nbits); + **commands = (uint32_t)(code | (extra << 8)); + ++(*commands); + } else if (copylen < 136) { + const size_t tail = copylen - 8; + const size_t code = (tail >> 5) + 54; + const size_t extra = tail & 31; + **commands = (uint32_t)(code | (extra << 8)); + ++(*commands); + **commands = 64; + ++(*commands); + } else if (copylen < 2120) { + const size_t tail = copylen - 72; + const size_t nbits = Log2FloorNonZero(tail); + const size_t code = nbits + 52; + const size_t extra = tail - ((size_t)1 << nbits); + **commands = (uint32_t)(code | (extra << 8)); + ++(*commands); + **commands = 64; + ++(*commands); + } else { + const size_t extra = copylen - 2120; + **commands = (uint32_t)(63 | (extra << 8)); + ++(*commands); + **commands = 64; + ++(*commands); + } +} + +static BROTLI_INLINE void EmitDistance(uint32_t distance, uint32_t** commands) { + uint32_t d = distance + 3; + uint32_t nbits = Log2FloorNonZero(d) - 1; + const uint32_t prefix = (d >> nbits) & 1; + const uint32_t offset = (2 + prefix) << nbits; + const uint32_t distcode = 2 * (nbits - 1) + prefix + 80; + uint32_t extra = d - offset; + **commands = distcode | (extra << 8); + ++(*commands); +} + +/* REQUIRES: len <= 1 << 24. */ +static void BrotliStoreMetaBlockHeader( + size_t len, BROTLI_BOOL is_uncompressed, size_t* storage_ix, + uint8_t* storage) { + size_t nibbles = 6; + /* ISLAST */ + BrotliWriteBits(1, 0, storage_ix, storage); + if (len <= (1U << 16)) { + nibbles = 4; + } else if (len <= (1U << 20)) { + nibbles = 5; + } + BrotliWriteBits(2, nibbles - 4, storage_ix, storage); + BrotliWriteBits(nibbles * 4, len - 1, storage_ix, storage); + /* ISUNCOMPRESSED */ + BrotliWriteBits(1, (uint64_t)is_uncompressed, storage_ix, storage); +} + +static BROTLI_INLINE void CreateCommands(const uint8_t* input, + size_t block_size, size_t input_size, const uint8_t* base_ip, int* table, + size_t table_bits, size_t min_match, + uint8_t** literals, uint32_t** commands) { + /* "ip" is the input pointer. */ + const uint8_t* ip = input; + const size_t shift = 64u - table_bits; + const uint8_t* ip_end = input + block_size; + /* "next_emit" is a pointer to the first byte that is not covered by a + previous copy. Bytes between "next_emit" and the start of the next copy or + the end of the input will be emitted as literal bytes. */ + const uint8_t* next_emit = input; + + int last_distance = -1; + const size_t kInputMarginBytes = BROTLI_WINDOW_GAP; + + if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) { + /* For the last block, we need to keep a 16 bytes margin so that we can be + sure that all distances are at most window size - 16. + For all other blocks, we only need to keep a margin of 5 bytes so that + we don't go over the block size with a copy. */ + const size_t len_limit = BROTLI_MIN(size_t, block_size - min_match, + input_size - kInputMarginBytes); + const uint8_t* ip_limit = input + len_limit; + + uint32_t next_hash; + for (next_hash = Hash(++ip, shift, min_match); ; ) { + /* Step 1: Scan forward in the input looking for a 6-byte-long match. + If we get close to exhausting the input then goto emit_remainder. + + Heuristic match skipping: If 32 bytes are scanned with no matches + found, start looking only at every other byte. If 32 more bytes are + scanned, look at every third byte, etc.. When a match is found, + immediately go back to looking at every byte. This is a small loss + (~5% performance, ~0.1% density) for compressible data due to more + bookkeeping, but for non-compressible data (such as JPEG) it's a huge + win since the compressor quickly "realizes" the data is incompressible + and doesn't bother looking for matches everywhere. + + The "skip" variable keeps track of how many bytes there are since the + last match; dividing it by 32 (ie. right-shifting by five) gives the + number of bytes to move ahead for each iteration. */ + uint32_t skip = 32; + + const uint8_t* next_ip = ip; + const uint8_t* candidate; + + BROTLI_DCHECK(next_emit < ip); +trawl: + do { + uint32_t hash = next_hash; + uint32_t bytes_between_hash_lookups = skip++ >> 5; + ip = next_ip; + BROTLI_DCHECK(hash == Hash(ip, shift, min_match)); + next_ip = ip + bytes_between_hash_lookups; + if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) { + goto emit_remainder; + } + next_hash = Hash(next_ip, shift, min_match); + candidate = ip - last_distance; + if (IsMatch(ip, candidate, min_match)) { + if (BROTLI_PREDICT_TRUE(candidate < ip)) { + table[hash] = (int)(ip - base_ip); + break; + } + } + candidate = base_ip + table[hash]; + BROTLI_DCHECK(candidate >= base_ip); + BROTLI_DCHECK(candidate < ip); + + table[hash] = (int)(ip - base_ip); + } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate, min_match))); + + /* Check copy distance. If candidate is not feasible, continue search. + Checking is done outside of hot loop to reduce overhead. */ + if (ip - candidate > MAX_DISTANCE) goto trawl; + + /* Step 2: Emit the found match together with the literal bytes from + "next_emit", and then see if we can find a next match immediately + afterwards. Repeat until we find no match for the input + without emitting some literal bytes. */ + + { + /* We have a 6-byte match at ip, and we need to emit bytes in + [next_emit, ip). */ + const uint8_t* base = ip; + size_t matched = min_match + FindMatchLengthWithLimit( + candidate + min_match, ip + min_match, + (size_t)(ip_end - ip) - min_match); + int distance = (int)(base - candidate); /* > 0 */ + int insert = (int)(base - next_emit); + ip += matched; + BROTLI_DCHECK(0 == memcmp(base, candidate, matched)); + EmitInsertLen((uint32_t)insert, commands); + BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n", + (int)(next_emit - base_ip), insert, 2)); + memcpy(*literals, next_emit, (size_t)insert); + *literals += insert; + if (distance == last_distance) { + **commands = 64; + ++(*commands); + } else { + EmitDistance((uint32_t)distance, commands); + last_distance = distance; + } + EmitCopyLenLastDistance(matched, commands); + BROTLI_LOG(("[CompressFragment] pos = %d distance = %d\n" + "[CompressFragment] pos = %d insert = %d copy = %d\n" + "[CompressFragment] pos = %d distance = %d\n", + (int)(base - base_ip), (int)distance, + (int)(base - base_ip) + 2, 0, (int)matched - 2, + (int)(base - base_ip) + 2, (int)distance)); + + next_emit = ip; + if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) { + goto emit_remainder; + } + { + /* We could immediately start working at ip now, but to improve + compression we first update "table" with the hashes of some + positions within the last copy. */ + uint64_t input_bytes; + uint32_t cur_hash; + uint32_t prev_hash; + if (min_match == 4) { + input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3); + cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match); + prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 3); + prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 2); + prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 1); + } else { + input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5); + prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 5); + prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 4); + prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 3); + input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2); + cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); + prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 2); + prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 1); + } + + candidate = base_ip + table[cur_hash]; + table[cur_hash] = (int)(ip - base_ip); + } + } + + while (ip - candidate <= MAX_DISTANCE && + IsMatch(ip, candidate, min_match)) { + /* We have a 6-byte match at ip, and no need to emit any + literal bytes prior to ip. */ + const uint8_t* base = ip; + size_t matched = min_match + FindMatchLengthWithLimit( + candidate + min_match, ip + min_match, + (size_t)(ip_end - ip) - min_match); + ip += matched; + last_distance = (int)(base - candidate); /* > 0 */ + BROTLI_DCHECK(0 == memcmp(base, candidate, matched)); + EmitCopyLen(matched, commands); + EmitDistance((uint32_t)last_distance, commands); + BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n" + "[CompressFragment] pos = %d distance = %d\n", + (int)(base - base_ip), 0, (int)matched, + (int)(base - base_ip), (int)last_distance)); + + next_emit = ip; + if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) { + goto emit_remainder; + } + { + /* We could immediately start working at ip now, but to improve + compression we first update "table" with the hashes of some + positions within the last copy. */ + uint64_t input_bytes; + uint32_t cur_hash; + uint32_t prev_hash; + if (min_match == 4) { + input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3); + cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match); + prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 3); + prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 2); + prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 1); + } else { + input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5); + prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 5); + prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 4); + prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 3); + input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2); + cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); + prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 2); + prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); + table[prev_hash] = (int)(ip - base_ip - 1); + } + + candidate = base_ip + table[cur_hash]; + table[cur_hash] = (int)(ip - base_ip); + } + } + + next_hash = Hash(++ip, shift, min_match); + } + } + +emit_remainder: + BROTLI_DCHECK(next_emit <= ip_end); + /* Emit the remaining bytes as literals. */ + if (next_emit < ip_end) { + const uint32_t insert = (uint32_t)(ip_end - next_emit); + EmitInsertLen(insert, commands); + BROTLI_LOG(("[CompressFragment] pos = %d insert = %d copy = %d\n", + (int)(next_emit - base_ip), insert, 2)); + memcpy(*literals, next_emit, insert); + *literals += insert; + } +} + +static void StoreCommands(BrotliTwoPassArena* s, + const uint8_t* literals, const size_t num_literals, + const uint32_t* commands, const size_t num_commands, + size_t* storage_ix, uint8_t* storage) { + static const uint32_t kNumExtraBits[128] = { + 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, + 6, 7, 8, 9, 10, 12, 14, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 24, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, + 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, + 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, + }; + static const uint32_t kInsertOffset[24] = { + 0, 1, 2, 3, 4, 5, 6, 8, 10, 14, 18, 26, + 34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594, + }; + + size_t i; + memset(s->lit_histo, 0, sizeof(s->lit_histo)); + /* TODO(eustas): is that necessary? */ + memset(s->cmd_depth, 0, sizeof(s->cmd_depth)); + /* TODO(eustas): is that necessary? */ + memset(s->cmd_bits, 0, sizeof(s->cmd_bits)); + memset(s->cmd_histo, 0, sizeof(s->cmd_histo)); + for (i = 0; i < num_literals; ++i) { + ++s->lit_histo[literals[i]]; + } + BrotliBuildAndStoreHuffmanTreeFast(s->tmp_tree, s->lit_histo, num_literals, + /* max_bits = */ 8, s->lit_depth, + s->lit_bits, storage_ix, storage); + + for (i = 0; i < num_commands; ++i) { + const uint32_t code = commands[i] & 0xFF; + BROTLI_DCHECK(code < 128); + ++s->cmd_histo[code]; + } + s->cmd_histo[1] += 1; + s->cmd_histo[2] += 1; + s->cmd_histo[64] += 1; + s->cmd_histo[84] += 1; + BuildAndStoreCommandPrefixCode(s, storage_ix, storage); + + for (i = 0; i < num_commands; ++i) { + const uint32_t cmd = commands[i]; + const uint32_t code = cmd & 0xFF; + const uint32_t extra = cmd >> 8; + BROTLI_DCHECK(code < 128); + BrotliWriteBits(s->cmd_depth[code], s->cmd_bits[code], storage_ix, storage); + BrotliWriteBits(kNumExtraBits[code], extra, storage_ix, storage); + if (code < 24) { + const uint32_t insert = kInsertOffset[code] + extra; + uint32_t j; + for (j = 0; j < insert; ++j) { + const uint8_t lit = *literals; + BrotliWriteBits(s->lit_depth[lit], s->lit_bits[lit], storage_ix, + storage); + ++literals; + } + } + } +} + +/* Acceptable loss for uncompressible speedup is 2% */ +#define MIN_RATIO 0.98 +#define SAMPLE_RATE 43 + +static BROTLI_BOOL ShouldCompress(BrotliTwoPassArena* s, + const uint8_t* input, size_t input_size, size_t num_literals) { + double corpus_size = (double)input_size; + if ((double)num_literals < MIN_RATIO * corpus_size) { + return BROTLI_TRUE; + } else { + const double max_total_bit_cost = corpus_size * 8 * MIN_RATIO / SAMPLE_RATE; + size_t i; + memset(s->lit_histo, 0, sizeof(s->lit_histo)); + for (i = 0; i < input_size; i += SAMPLE_RATE) { + ++s->lit_histo[input[i]]; + } + return TO_BROTLI_BOOL(BitsEntropy(s->lit_histo, 256) < max_total_bit_cost); + } +} + +static void RewindBitPosition(const size_t new_storage_ix, + size_t* storage_ix, uint8_t* storage) { + const size_t bitpos = new_storage_ix & 7; + const size_t mask = (1u << bitpos) - 1; + storage[new_storage_ix >> 3] &= (uint8_t)mask; + *storage_ix = new_storage_ix; +} + +static void EmitUncompressedMetaBlock(const uint8_t* input, size_t input_size, + size_t* storage_ix, uint8_t* storage) { + BrotliStoreMetaBlockHeader(input_size, 1, storage_ix, storage); + *storage_ix = (*storage_ix + 7u) & ~7u; + memcpy(&storage[*storage_ix >> 3], input, input_size); + *storage_ix += input_size << 3; + storage[*storage_ix >> 3] = 0; +} + +static BROTLI_INLINE void BrotliCompressFragmentTwoPassImpl( + BrotliTwoPassArena* s, const uint8_t* input, size_t input_size, + BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf, + int* table, size_t table_bits, size_t min_match, + size_t* storage_ix, uint8_t* storage) { + /* Save the start of the first block for position and distance computations. + */ + const uint8_t* base_ip = input; + BROTLI_UNUSED(is_last); + + while (input_size > 0) { + size_t block_size = + BROTLI_MIN(size_t, input_size, kCompressFragmentTwoPassBlockSize); + uint32_t* commands = command_buf; + uint8_t* literals = literal_buf; + size_t num_literals; + CreateCommands(input, block_size, input_size, base_ip, table, + table_bits, min_match, &literals, &commands); + num_literals = (size_t)(literals - literal_buf); + if (ShouldCompress(s, input, block_size, num_literals)) { + const size_t num_commands = (size_t)(commands - command_buf); + BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage); + /* No block splits, no contexts. */ + BrotliWriteBits(13, 0, storage_ix, storage); + StoreCommands(s, literal_buf, num_literals, command_buf, num_commands, + storage_ix, storage); + } else { + /* Since we did not find many backward references and the entropy of + the data is close to 8 bits, we can simply emit an uncompressed block. + This makes compression speed of uncompressible data about 3x faster. */ + EmitUncompressedMetaBlock(input, block_size, storage_ix, storage); + } + input += block_size; + input_size -= block_size; + } +} + +#define FOR_TABLE_BITS_(X) \ + X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) + +#define BAKE_METHOD_PARAM_(B) \ +static BROTLI_NOINLINE void BrotliCompressFragmentTwoPassImpl ## B( \ + BrotliTwoPassArena* s, const uint8_t* input, size_t input_size, \ + BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf, \ + int* table, size_t* storage_ix, uint8_t* storage) { \ + size_t min_match = (B <= 15) ? 4 : 6; \ + BrotliCompressFragmentTwoPassImpl(s, input, input_size, is_last, command_buf,\ + literal_buf, table, B, min_match, storage_ix, storage); \ +} +FOR_TABLE_BITS_(BAKE_METHOD_PARAM_) +#undef BAKE_METHOD_PARAM_ + +void duckdb_brotli::BrotliCompressFragmentTwoPass( + BrotliTwoPassArena* s, const uint8_t* input, size_t input_size, + BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf, + int* table, size_t table_size, size_t* storage_ix, uint8_t* storage) { + const size_t initial_storage_ix = *storage_ix; + const size_t table_bits = Log2FloorNonZero(table_size); + switch (table_bits) { +#define CASE_(B) \ + case B: \ + BrotliCompressFragmentTwoPassImpl ## B( \ + s, input, input_size, is_last, command_buf, \ + literal_buf, table, storage_ix, storage); \ + break; + FOR_TABLE_BITS_(CASE_) +#undef CASE_ + default: BROTLI_DCHECK(0); break; + } + + /* If output is larger than single uncompressed block, rewrite it. */ + if (*storage_ix - initial_storage_ix > 31 + (input_size << 3)) { + RewindBitPosition(initial_storage_ix, storage_ix, storage); + EmitUncompressedMetaBlock(input, input_size, storage_ix, storage); + } + + if (is_last) { + BrotliWriteBits(1, 1, storage_ix, storage); /* islast */ + BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */ + *storage_ix = (*storage_ix + 7u) & ~7u; + } +} + +#undef FOR_TABLE_BITS_ + + diff --git a/third_party/brotli/enc/compress_fragment_two_pass.h b/third_party/brotli/enc/compress_fragment_two_pass.h new file mode 100644 index 00000000000..d4edb537b60 --- /dev/null +++ b/third_party/brotli/enc/compress_fragment_two_pass.h @@ -0,0 +1,68 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Function for fast encoding of an input fragment, independently from the input + history. This function uses two-pass processing: in the first pass we save + the found backward matches and literal bytes into a buffer, and in the + second pass we emit them into the bit stream using prefix codes built based + on the actual command and literal byte histograms. */ + +#ifndef BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_ +#define BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_ + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" +#include "entropy_encode.h" + +namespace duckdb_brotli { + +/* TODO(eustas): turn to macro. */ +static const size_t kCompressFragmentTwoPassBlockSize = 1 << 17; + +typedef struct BrotliTwoPassArena { + uint32_t lit_histo[256]; + uint8_t lit_depth[256]; + uint16_t lit_bits[256]; + + uint32_t cmd_histo[128]; + uint8_t cmd_depth[128]; + uint16_t cmd_bits[128]; + + /* BuildAndStoreCommandPrefixCode */ + HuffmanTree tmp_tree[2 * BROTLI_NUM_LITERAL_SYMBOLS + 1]; + uint8_t tmp_depth[BROTLI_NUM_COMMAND_SYMBOLS]; + uint16_t tmp_bits[64]; +} BrotliTwoPassArena; + +/* Compresses "input" string to the "*storage" buffer as one or more complete + meta-blocks, and updates the "*storage_ix" bit position. + + If "is_last" is 1, emits an additional empty last meta-block. + + REQUIRES: "input_size" is greater than zero, or "is_last" is 1. + REQUIRES: "input_size" is less or equal to maximal metablock size (1 << 24). + REQUIRES: "command_buf" and "literal_buf" point to at least + kCompressFragmentTwoPassBlockSize long arrays. + REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero. + REQUIRES: "table_size" is a power of two + OUTPUT: maximal copy distance <= |input_size| + OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */ +BROTLI_INTERNAL void BrotliCompressFragmentTwoPass(BrotliTwoPassArena* s, + const uint8_t* input, + size_t input_size, + BROTLI_BOOL is_last, + uint32_t* command_buf, + uint8_t* literal_buf, + int* table, + size_t table_size, + size_t* storage_ix, + uint8_t* storage); + +} + +#endif /* BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_ */ diff --git a/third_party/brotli/enc/dictionary_hash.cpp b/third_party/brotli/enc/dictionary_hash.cpp new file mode 100644 index 00000000000..ae665b24bcb --- /dev/null +++ b/third_party/brotli/enc/dictionary_hash.cpp @@ -0,0 +1,1844 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Hash table on the 4-byte prefixes of static dictionary words. */ + +#include "../common/brotli_platform.h" +#include "dictionary_hash.h" + +using namespace duckdb_brotli; + +/* GENERATED CODE START */ +BROTLI_INTERNAL const uint16_t duckdb_brotli::kStaticDictionaryHashWords[32768] = { +1002,0,0,0,0,0,0,0,0,683,0,0,0,0,0,0,0,1265,0,0,0,0,0,1431,0,0,0,0,0,0,40,0,0,0, +0,155,8,741,0,624,0,0,0,0,0,0,0,0,0,0,0,0,66,503,0,0,0,451,0,0,0,0,0,0,0,835,70, +0,0,539,0,0,0,0,0,0,0,0,0,113,0,0,0,0,718,0,0,0,0,0,0,520,0,1070,0,0,0,0,0,1515, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,610,0,0,750,0,0,0,307,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,964,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,999,0,0,0,0,0,0,0,0, +645,75,0,649,52,282,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1621,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,211,225,0,0,687,718,0,0,110,0,58,0,0,0,0,0,0,345,0,0,301,0,0, +0,203,0,0,1154,674,1949,0,0,0,0,0,0,0,0,0,259,0,0,0,0,0,0,0,1275,0,0,0,1231,254, +0,0,0,0,0,0,0,277,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,0,0,800,0,0,0,29, +116,100,490,0,0,0,0,0,1641,0,543,0,0,0,0,41,181,0,657,0,0,202,25,0,0,0,0,0,0,0, +0,0,0,423,0,0,0,113,0,0,0,927,963,0,976,0,206,0,0,0,0,0,0,0,0,0,2002,0,0,0,0,0, +0,0,0,0,0,0,696,0,1170,0,0,0,0,226,13,0,769,678,551,0,0,0,0,0,0,57,0,0,0,10,188, +0,0,0,624,0,0,0,0,0,0,0,0,0,1941,130,0,0,0,0,378,269,0,0,528,0,1146,0,0,0,1105, +0,1616,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,656,0,1940,0,0,0,0,0,173,0,0,0,0,0,0,0,0,0, +0,0,457,342,810,0,0,0,0,620,0,0,0,0,0,0,0,967,95,447,406,0,0,0,477,0,1268,944, +1941,0,0,0,629,0,0,0,0,0,375,0,0,0,1636,0,0,0,0,774,0,1,1034,0,0,0,0,0,824,0,0, +0,0,0,118,0,0,560,296,0,0,0,0,0,0,0,0,1009,894,0,0,0,0,0,0,0,0,0,0,0,0,0,1474, +366,0,0,0,0,0,0,0,0,0,79,1723,0,0,200,0,0,0,0,0,0,0,0,1759,372,0,16,0,943,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,900,1839,707,30,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,2004,0,0,10,115,0,50,0,0,0,0,0,0,0,0,0,0,520,1,0,738,98,482,0,0,0,0, +0,0,0,0,0,0,701,2,0,0,0,0,0,0,0,0,557,0,0,0,0,0,0,0,0,0,347,0,0,0,0,572,0,0,0,0, +0,0,0,0,0,832,0,0,797,809,0,0,0,0,0,0,0,0,0,0,0,528,0,0,0,861,0,0,294,0,0,0,109, +0,0,0,0,0,0,0,0,1187,290,266,0,0,0,0,49,50,748,0,0,466,399,0,0,0,0,0,0,0,378,0, +519,0,0,0,0,0,0,0,0,0,0,0,0,667,351,902,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,180, +0,0,869,0,0,0,0,0,0,0,260,0,0,0,0,0,0,0,0,0,0,523,36,0,0,587,510,809,29,260,0,0, +0,0,0,0,0,0,570,0,565,0,1464,0,0,0,0,0,0,10,0,0,787,399,380,200,0,0,0,0,516,0, +844,887,0,0,0,0,0,0,0,44,0,0,0,305,1655,0,0,0,0,0,0,0,0,0,0,0,0,0,0,786,10,0,0, +0,0,0,0,0,0,0,2031,0,0,0,0,0,684,0,0,0,0,0,1480,0,0,0,27,0,0,0,395,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,813,511,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,206, +496,0,0,0,0,0,909,0,891,0,0,0,0,0,0,0,0,0,687,0,0,0,1342,0,0,0,0,0,0,0,0,0,0, +160,41,0,0,0,0,0,0,0,0,0,0,0,1718,778,0,0,0,0,0,0,0,0,0,0,1610,0,0,0,0,0,115,0, +0,0,0,314,294,0,0,0,983,178,193,0,0,0,0,0,0,0,0,0,174,0,0,0,0,0,0,0,0,0,0,848, +1796,0,0,0,0,0,0,221,0,687,1660,0,0,0,0,262,0,0,179,0,0,0,0,0,66,0,773,0,352,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,0,152,0,0,1197,0,0,0,0,0,0,0,0,0,0,0,0,560,0,0, +564,0,0,0,797,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,0,819,0,0,0,0,0,0,0,0,719,544, +637,5,0,0,0,0,0,0,0,0,0,0,0,101,0,1441,0,0,0,893,0,0,0,0,0,0,0,0,0,238,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,1296,0,0,969,1729,314,60,0,0,0,0,0,1144,0,1147,0,0,0,0,0, +0,0,0,0,0,437,1853,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,828,0,176,0,0,0,0,0,0,434,39,0, +0,0,0,0,159,0,0,0,902,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,270,0,0,0,0,801,556,0,0, +0,0,0,0,0,416,19,197,369,0,0,0,0,0,0,0,0,0,28,34,0,757,0,0,898,1553,0,721,0,0,0, +0,1012,0,0,0,0,1102,0,898,183,0,0,0,0,0,0,0,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,277,0,0,0,435,0,0,0,0,0,1311,0,0,0,0, +0,0,211,437,0,0,0,28,0,0,750,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2012,0,702, +0,808,0,0,0,0,739,166,0,0,0,0,0,0,719,170,500,0,0,0,0,0,0,0,0,1500,327,0,0,450, +0,0,0,1318,0,0,0,1602,0,0,331,754,0,0,0,0,0,1368,0,0,557,0,0,0,799,850,0,0,0,0, +0,0,0,0,908,0,0,0,0,0,19,62,459,0,0,0,0,0,0,0,0,0,0,0,0,1802,0,0,0,0,0,0,0,0,0, +1397,0,0,0,0,120,238,0,0,0,0,0,0,0,0,0,0,0,1324,0,0,0,0,0,0,0,0,602,201,0,0,164, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,615,0,0,0,0,0,0,0,0,0,0,0,0,0,1243,0,0,0,0,968,0,0, +0,0,0,0,882,0,0,0,907,329,100,0,0,0,0,0,0,0,0,0,0,0,176,26,9,0,0,265,256,0,0,0, +0,0,0,0,0,0,643,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,610,0,0,0,0,973,2001,0, +0,0,0,0,0,522,0,0,0,0,0,0,0,0,0,0,0,553,0,0,0,0,0,0,1582,0,1578,0,0,0,0,0,0,0,0, +0,0,0,795,0,0,0,432,0,0,0,0,0,0,84,126,0,0,0,0,790,0,377,64,0,1529,0,0,0,0,530, +1857,539,1104,0,0,0,0,0,0,0,0,0,0,0,0,977,0,0,0,34,0,0,0,0,0,0,0,0,0,0,0,24,26, +0,0,918,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,183,379,0,0,0,0,0,0,0,792, +0,0,0,0,0,0,0,0,0,1920,0,0,0,0,0,0,0,0,0,771,0,0,0,1979,0,901,254,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,140,0,0,0,0,0,440,37,0, +508,0,0,0,513,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,533,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,752,920,0,1048,0,153,0, +0,391,0,0,1952,0,0,0,0,0,0,0,0,0,0,126,0,0,0,0,640,0,483,69,1616,0,0,0,0,0,734, +0,0,0,0,0,0,480,0,495,0,472,0,0,0,0,0,0,0,0,874,229,0,0,0,0,948,0,0,0,0,0,0,0,0, +1009,748,0,555,0,0,0,0,0,0,193,0,653,0,0,0,0,0,0,0,0,0,0,984,0,0,0,172,0,0,0,0, +0,0,0,0,83,1568,0,0,384,0,0,0,0,0,0,0,164,880,0,0,0,0,0,0,0,0,0,0,0,367,121,0,0, +828,0,0,0,0,0,0,0,1541,0,0,0,0,0,0,0,343,0,0,0,0,0,0,0,0,561,57,0,0,0,0,0,0,0, +926,0,0,0,0,827,0,194,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0, +0,0,0,896,1249,0,0,0,0,0,1614,0,0,0,860,0,0,0,0,0,0,0,0,964,102,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,899,0,569,0,0,0,0,795,2045,0,0,0, +0,0,0,104,52,0,0,0,0,0,604,0,0,0,0,779,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0, +494,0,677,0,0,0,0,0,0,0,508,0,0,0,0,0,0,0,0,0,1014,0,957,0,0,630,310,0,0,0,570, +0,0,449,0,64,537,0,0,0,0,0,0,0,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,702,1650,49,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0,1279,0,0,0,0,0,0,0,896,0,0, +178,0,0,0,0,0,0,0,0,0,0,0,0,0,808,695,0,0,0,0,539,1117,0,0,0,0,0,0,0,0,257,0, +1003,0,0,0,1,448,0,516,0,0,960,0,125,4,0,1268,30,748,0,0,852,0,0,0,6,0,0,848, +236,1385,862,1811,0,0,0,0,698,803,0,0,0,0,0,0,0,610,992,0,0,878,0,1847,0,0,0,0, +0,0,0,383,0,1404,0,0,0,0,986,0,347,0,0,0,0,0,0,0,0,0,0,0,592,572,0,1411,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,606,0,0,0,0,0,0, +0,0,0,0,0,0,0,1829,0,0,0,0,0,0,0,0,0,0,0,0,700,748,0,0,0,0,0,0,365,0,0,127,0,0, +83,198,0,0,0,0,0,0,864,55,0,0,0,0,726,1752,0,0,0,0,0,0,0,0,0,0,0,0,0,1066,0,764, +0,0,0,0,683,0,550,309,0,0,874,1212,0,0,0,1364,0,986,381,723,0,0,0,1573,0,0,0,0, +0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1559,0,0,0,0,493,133,0,0,0,0,148, +119,0,0,0,0,0,0,537,14,541,0,635,126,0,0,0,495,0,0,0,0,861,998,1009,0,0,0,0,0,0, +0,359,368,0,0,0,0,304,1577,0,0,0,0,0,1107,0,0,0,0,0,929,0,0,0,1142,0,0,0,0,289, +175,0,432,0,219,0,0,0,0,0,785,0,0,595,0,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0,0,0,0, +931,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1323,0,0,0,0,290,0,559,1751,127,0,0,0, +934,1167,0,963,0,260,0,0,0,573,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +580,1689,0,0,0,0,0,0,0,0,0,1164,0,0,982,1922,0,63,0,0,0,0,0,793,0,0,0,0,0,0,0,0, +0,0,0,0,0,67,790,0,0,0,0,0,0,0,0,0,0,391,443,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,271,0,0,0,0,0,0,0,0,0,0,0,1140,0,0,0,0,340,300,0,897,0,0,0,0,0,0, +0,0,0,0,890,0,0,0,0,818,321,53,0,0,0,0,0,0,0,0,0,468,0,243,0,870,0,0,0,1765,121, +0,0,0,180,518,0,822,419,634,0,0,0,0,0,0,0,0,0,898,0,0,0,0,454,36,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,806,0,0,0,0,0,0,0,0,0,0,0,0,1326,0,104,0,0,0,0,0,0,0, +0,0,260,0,0,0,0,0,0,0,0,0,0,0,0,542,45,0,0,263,1516,42,0,0,0,0,0,468,0,1005,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,288,87,0,0,0,0,0,0,0,0,502,988,133,0,0,0,0,0,0, +141,0,0,872,1842,0,0,0,0,0,0,0,0,261,619,0,0,0,0,189,246,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,678,0,0,0,0,0,0,0,0,0,0,0,0,285,35,0,517,0,0,0,0,0,0,0,0,0,0, +540,214,667,0,74,0,0,125,0,0,0,0,0,761,131,0,0,0,0,0,0,0,0,0,0,0,0,0,333,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1338,94,0,0,0,0,0,0,0,0,0,0,0,0,449,0,646,103, +86,641,2028,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,869,87,277,117,39,0,0,0,0,0,0,0,0,938, +297,0,0,0,0,558,464,0,0,0,0,0,0,0,0,0,0,731,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1608,0, +0,0,0,0,0,0,1429,0,0,733,1010,0,0,338,1656,0,0,0,1038,979,2010,0,0,0,0,0,0,0, +1005,0,0,121,0,0,0,219,20,0,0,0,0,0,0,872,1440,0,0,0,683,0,1070,0,0,522,0,0,0,0, +439,669,0,0,0,0,0,0,0,0,1245,0,0,0,0,0,1218,0,0,547,233,0,0,0,0,0,0,0,0,0,482,0, +0,0,0,0,0,0,886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,795,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,371,0,0,0,0,0,0,0,0,0,0,0,0,0,622,0,625,0,0,0,339,29,0,0,338,0,0,0, +0,130,0,0,0,0,0,0,0,0,0,307,0,0,0,0,0,0,0,0,0,0,2044,0,0,0,0,0,0,0,0,308,770,0, +0,0,0,0,1266,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,690,739,0,0, +0,0,0,0,0,990,0,0,0,1831,0,0,0,0,0,0,0,0,0,0,0,0,0,613,0,0,0,0,0,0,0,0,0,0,0,0, +0,763,0,878,0,0,0,977,0,100,0,0,0,0,0,0,0,0,0,463,0,0,0,0,623,318,0,0,296,463, +137,0,0,454,0,0,0,1527,58,0,0,0,0,0,0,0,18,48,0,0,0,0,0,729,0,0,0,442,0,0,0,0, +40,449,0,853,0,0,0,0,0,0,227,0,0,0,0,0,0,1491,0,0,0,0,0,0,0,0,0,0,161,55,0,450, +0,1174,62,0,207,0,0,0,0,0,0,0,0,869,0,0,0,0,80,213,0,0,0,0,0,0,0,0,0,0,354,820, +0,0,747,0,0,0,954,0,0,1073,0,556,0,0,0,692,0,191,0,804,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,831,162,0,0,35,0,0,0,0,0,0,0,0,1235,0,0,0,0,0,1234,0,0, +0,0,0,0,0,0,0,0,96,0,0,0,0,0,0,0,149,0,0,0,902,204,0,0,833,0,287,366,0,0,0,0,0, +0,992,2020,0,0,0,0,0,0,0,0,0,0,0,356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,784,0,0,567, +630,0,0,0,539,0,0,27,0,0,0,0,0,0,0,0,0,0,755,0,0,0,0,0,0,0,0,0,0,0,0,814,0,0,0, +0,0,0,0,0,0,0,0,0,0,987,0,0,255,761,194,0,1086,0,0,0,0,0,0,1016,0,0,1396,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,562,271,913,0,0,0,0,0,0,0,0,320,153,45,475,0,0, +0,0,0,0,0,713,0,327,0,0,0,0,0,0,604,552,3,359,0,0,0,0,853,80,0,0,0,0,0,0,0,2016, +6,887,0,0,0,0,975,0,961,0,0,0,0,0,916,1891,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,100,101,390,708,0,0,0,587,983,512,0,0,0,0,0,0,0,0,0,0,0,645,0,0,0,851,0,0,0, +0,0,498,140,217,0,0,0,1448,0,0,0,0,0,0,0,0,0,905,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +643,105,0,792,0,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,0,0,0,0,0,0,0,535,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1748,0,0,0,0,0,754,0,0,0,0,0,0,0,0,0,0,0,0,91,0,0,1565,0,91,792, +939,3,370,0,0,0,0,95,0,0,0,0,551,7,619,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1150,0, +0,0,0,0,0,0,0,0,0,0,0,0,671,0,0,0,0,0,888,368,149,0,0,105,1134,0,983,0,0,458,31, +0,643,0,0,0,312,0,740,0,0,0,1642,0,0,0,0,0,0,0,236,0,0,0,0,0,0,0,59,68,0,0,0,0, +0,867,795,0,0,0,0,970,1977,0,0,0,0,0,0,0,1148,0,775,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,970,0,0,0,0,0,0,0,0,0,665,71,0,0,0,0,827,0,0,0,0,0,0,0,0,0, +0,479,0,0,0,0,0,0,0,0,99,607,0,0,0,0,0,0,0,1960,0,0,0,793,0,0,871,41,0,0,241,94, +0,0,0,0,209,0,0,1497,0,0,0,0,0,0,0,0,0,98,0,0,0,463,0,0,0,0,291,0,0,0,0,0,0,0,0, +0,0,984,0,0,0,0,0,205,0,0,0,0,0,0,205,42,0,801,0,0,0,0,0,635,0,0,533,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,371,0,1282,0,0,0,825,0,0,0,0,0,0,0,0,0,357,879,467,0,317,0,0, +0,0,0,0,0,924,0,0,0,0,849,1795,0,0,0,0,895,1799,43,0,0,0,0,0,0,0,0,0,0,1820,0,0, +0,0,0,0,0,525,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,110,0,493,0,174,417,0,0, +0,0,0,583,733,0,0,0,0,0,0,481,215,0,0,0,0,477,0,0,0,0,0,0,0,0,308,0,0,0,0,0,0,0, +0,297,126,0,0,361,1551,0,0,0,0,0,0,871,1807,0,0,0,0,0,1307,0,685,0,0,0,0,0,0,0, +797,0,858,0,565,0,0,0,0,0,0,0,0,0,0,0,0,434,252,826,0,0,0,0,0,0,791,0,0,0,0,509, +231,178,601,0,0,0,0,0,0,0,0,43,1591,0,0,0,0,0,1683,0,0,0,0,45,0,0,0,0,0,0,0,0,0, +0,1120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,494,0,398,0,0,0,1030,0,0,0,0,0,0, +168,0,0,0,0,0,0,0,0,0,0,973,0,642,0,0,0,0,0,0,0,0,0,1615,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,378,594,0,1093,0,679,112,0,0,0,0,1492,540,1374,714, +1486,0,0,0,0,825,1511,0,0,0,0,0,0,0,0,0,0,0,0,0,952,0,0,736,143,0,700,0,1540,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1557,0,0,0,860,990,0,0,0,807,0,0,0,0,0,131, +515,0,646,0,0,0,0,117,728,508,121,0,0,0,0,0,0,357,0,0,0,0,0,0,237,0,0,0,0,0,0,0, +0,0,1784,0,0,0,0,0,0,0,0,0,0,0,713,348,1536,0,738,0,0,0,0,0,0,0,434,0,0,0,0,0,0, +366,1877,39,0,0,0,0,0,0,580,0,0,0,0,0,0,0,0,0,0,0,0,0,0,873,0,0,0,0,171,0,625, +550,107,343,943,0,0,0,0,0,0,0,768,0,0,0,0,0,0,0,799,0,0,0,894,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1673,0,0,0,0,0,0,0,0,0,0,0,1052,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +272,0,441,0,0,3,9,0,0,0,1182,0,1346,0,0,0,0,0,0,0,0,682,0,0,1004,24,0,0,968,0,0, +0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,0,0,0,578, +474,0,0,0,0,0,0,0,0,0,0,0,0,0,0,113,530,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,556,0,0,0,0,0,0,16,1317,0,0,97,0,0,0,703,0,0,0,0,0,0,0,0,892,0,0,0,1571,0,0, +426,186,0,1101,0,0,0,0,0,0,0,0,937,585,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,644,291, +0,0,0,0,749,0,162,0,0,381,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,762,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,628,21,0,0,0,0,0,0,0,0,919,0,0,0,0,0,0,0,0,0, +633,0,0,0,0,332,0,0,0,0,0,0,0,0,0,1489,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,832,398,0,645,0,0,0,13,0,0,0,0,0,0,0,0,0,0,20,0,800,0,0,0,0,0,0,0,0,0, +0,0,0,0,1993,0,0,0,0,769,0,0,0,665,0,0,0,0,0,0,0,0,0,0,1426,0,0,0,0,60,0,0,0, +641,1874,0,644,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1757,0,0,0,0,0,937,0,1652,0,654,0, +0,0,0,0,0,0,527,0,0,0,0,0,0,0,0,0,0,0,0,0,226,0,0,0,0,0,1486,0,0,0,0,0,0,0,0,0, +0,0,325,0,0,0,0,0,0,0,1345,0,0,91,0,404,0,0,0,0,0,0,0,0,0,0,0,0,973,0,0,0,0,0,0, +0,1176,0,549,0,0,0,0,0,0,0,0,0,0,976,0,0,0,0,0,21,0,0,0,0,0,51,0,0,0,0,314,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,198,6,0,1093,0,0,0,0,0,0,0,0,0, +0,0,0,0,1776,0,0,0,0,0,1528,0,419,0,0,0,0,0,0,0,0,76,138,0,0,0,0,638,29,0,0,0,0, +0,0,0,1418,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1710,0,0,0,0,0, +0,0,0,0,0,0,0,532,23,0,0,0,0,0,0,0,862,0,0,946,592,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,70,0,0,0,0,0,0,0,0,0,812,0,0,0,76,0,0,988,0,442,0,0,0,896,0,0,0,0,0,0, +483,0,0,0,0,1709,0,0,0,0,0,0,119,0,0,0,117,0,309,0,0,0,0,0,596,976,0,0,0,0,0,0, +0,0,0,0,0,768,0,0,0,0,0,0,0,0,0,518,0,0,0,0,0,0,0,0,0,0,0,0,0,0,863,0,0,0,24, +145,1020,0,0,1984,0,0,0,0,0,0,0,658,0,0,0,0,0,0,0,0,0,0,106,1827,0,1010,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,582,87,0,0,0,0,0,0,0,267,0,0,0,703,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,496,0,0,0,0,1121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,561,0,0,0,0,0, +0,0,760,0,0,154,0,0,0,255,0,419,323,0,0,0,0,0,368,0,0,0,0,0,0,0,0,0,0,522,0,0,0, +0,0,0,0,551,562,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,0,0,0,0, +0,0,0,284,525,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,958,0,0,594,0,0,0,0,0,0,6,479,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,61,0,0,0,0,0,0,0,820,1641,0,1556,0,0,0,0,0,0,0,302,0,0, +0,0,0,148,0,0,676,0,0,0,0,0,0,1674,0,0,0,0,0,0,178,0,0,0,0,0,0,0,94,389,0,0,0,0, +91,8,0,0,0,0,0,0,0,0,0,0,112,0,0,0,0,0,0,0,0,0,0,747,0,0,0,0,0,0,0,1746,0,0,0,0, +0,24,0,1352,158,1530,0,0,718,130,280,1401,0,0,0,0,0,1946,8,0,0,0,0,1607,0,0,0,0, +0,0,882,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,417,0,0,0,1597,633,433,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,234,0,0,0,0,0,0,0,0,680,1950,0,0,0,0,249,5,0,0,0, +0,0,0,0,0,0,1216,0,1773,0,0,0,0,0,0,0,0,0,0,0,0,0,0,509,180,0,0,0,0,0,0,0,1002, +0,0,0,0,0,0,0,0,0,0,0,0,0,931,0,0,0,0,0,0,0,0,747,943,0,1837,0,0,0,0,0,0,0,641, +0,0,0,0,280,0,0,0,5,0,0,0,0,0,72,545,0,0,0,0,0,0,0,0,0,742,0,0,254,151,872,0,0, +0,0,0,0,0,0,0,0,0,0,921,0,0,517,833,0,1680,0,0,436,251,584,0,0,0,0,0,0,0,0,0,0, +0,24,500,0,0,0,0,0,0,0,0,195,1775,514,389,0,0,0,0,0,0,0,743,0,0,0,0,0,0,292,0,0, +0,227,1283,774,1805,0,0,0,0,0,0,0,0,0,0,119,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,913, +1910,0,0,0,1826,490,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1162,700,30, +0,0,0,721,839,0,0,0,617,0,0,0,0,0,0,0,0,0,169,428,0,0,0,0,0,1648,637,1205,0,0,0, +1596,0,0,4,266,0,0,0,0,0,0,0,0,0,0,0,862,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0, +0,279,157,391,604,0,0,713,945,877,973,0,0,0,0,0,0,0,0,0,0,0,0,0,0,859,567,628, +1846,0,0,0,0,0,0,0,0,0,762,0,0,191,0,0,0,0,298,0,0,767,909,0,0,0,0,0,0,0,795,0, +0,301,0,0,1970,0,0,0,0,0,0,0,0,0,1236,0,0,0,0,0,0,644,369,15,0,160,71,0,0,0,0,0, +1447,0,0,0,0,0,0,0,0,735,1255,76,0,0,0,0,0,0,0,0,0,0,474,0,0,0,0,0,0,0,0,0,0, +841,0,0,0,0,0,0,0,0,0,0,836,0,0,0,0,0,1622,0,0,735,0,0,0,0,1601,804,1390,394,0, +0,0,0,0,0,96,0,289,0,0,35,688,0,0,0,667,0,513,0,0,0,0,0,0,0,2034,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,704,0,1524,0,1078,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,306, +0,0,0,0,0,0,0,431,0,1196,0,0,54,0,15,1448,0,1418,0,0,0,0,0,0,0,0,0,907,0,0,0,0, +0,0,194,1767,0,0,0,0,0,840,0,900,0,0,0,0,0,0,0,0,0,0,0,1436,0,0,0,0,642,1560,0, +0,0,0,0,0,94,386,0,0,0,0,0,0,0,0,0,0,830,416,0,0,20,731,0,0,0,0,0,0,0,0,697,0,0, +662,0,0,0,0,0,0,0,0,0,861,0,0,0,0,0,0,0,871,671,864,0,928,7,0,332,0,0,0,0,1055, +0,0,0,0,0,0,986,0,0,0,0,0,44,76,0,0,0,0,0,0,0,0,0,0,300,0,0,0,0,0,0,0,175,518, +831,1108,0,0,0,836,0,1852,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,843,1804,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,246,0,0,0,610,202,0,0,36,0,0,0,240,654,13,0,0,0,0,0,0,0, +0,391,0,403,0,0,0,0,0,0,0,0,0,0,75,0,366,815,0,0,631,0,0,0,0,0,0,0,0,345,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,952,0,0,0,0,0,0,0,0,0,0,0,673,35,662,0,287,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,5,34,0,0,0,0,0,0,0,0,151,0,427,0,0,382,0,0,0,329,0,0,279,0,0,0, +0,0,0,0,0,0,0,906,0,0,366,843,0,1443,0,1372,992,0,36,123,0,649,0,0,0,0,0,767,0, +1018,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,995,0,0,0,0,0,0,0,72,368,0,0,1345,0,0,0, +589,0,0,0,0,0,0,0,0,0,1988,0,0,220,541,0,0,0,686,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,32,196,0,0,0,0,0,0,0,0,0,0,0,0,0,381,0,0,0,0,0,0,0,0,0,1452,0, +0,0,616,0,0,0,0,0,0,0,0,0,1229,0,0,0,0,0,0,0,0,0,0,667,120,0,0,0,0,0,0,0,1146,0, +0,0,0,0,0,0,0,0,0,0,352,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,935,0,1050,0, +147,88,0,0,923,0,0,0,0,0,934,0,0,0,0,0,0,0,0,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,341,222,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0, +637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1159,0,0,0,847,0,0,0,0,0,0,683,0,867,944,0,0, +0,0,0,1809,0,0,0,0,0,0,0,0,0,0,395,170,0,0,0,0,0,0,0,0,0,0,618,535,0,1625,0,0,0, +0,0,0,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,778,0,0,0,0,0,46,0,2032,0,0,37, +1458,0,938,363,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,314,0,0,0,0,0,0,889,0,0,0,0,0,0,0, +0,0,0,0,462,0,0,0,0,525,0,0,23,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,0,0,0,0,0, +0,498,725,0,0,0,0,7,0,0,0,0,773,0,0,0,164,0,0,0,0,0,0,0,0,936,583,659,1462,0, +220,0,0,0,0,803,0,0,544,119,0,0,0,0,0,0,0,0,0,0,0,181,176,0,1192,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1878,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0,0,0,0,0, +944,0,0,0,0,0,0,0,273,0,0,0,0,0,855,0,0,0,0,5,127,0,0,0,0,0,0,0,0,752,230,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,162,0,654,48,156,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197, +0,0,0,0,0,0,0,963,0,0,0,0,0,0,0,0,0,0,858,0,0,0,0,0,0,0,0,0,0,676,1978,0,0,102, +972,0,0,0,0,0,0,0,361,0,461,0,0,0,472,0,0,0,0,0,0,0,0,0,0,0,0,0,0,747,905,0,0,0, +155,0,0,0,0,0,0,0,0,0,0,319,163,0,0,0,0,0,0,0,0,0,848,0,0,36,631,0,0,0,0,0,1769, +0,0,0,0,0,144,0,0,0,0,0,0,0,0,0,0,369,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,555,247,0,0, +996,0,0,189,0,0,0,0,0,0,0,0,0,0,280,0,0,0,0,0,0,0,0,0,0,0,526,746,0,0,345,0,0,0, +1017,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,651,428,0,0,0,1162,230,327,546,792,0,0,0, +1203,0,0,0,0,0,0,0,0,0,672,189,0,0,0,0,0,0,99,0,0,0,298,0,0,0,0,0,0,555,397,0,0, +0,0,0,1157,0,0,0,0,0,0,0,0,0,0,398,1523,0,366,0,0,787,0,0,0,282,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,157,0,941,0,0,0,0,0,1336,0,0,116,0,0,0,0,0,0,787,0,0,0,0,0,0,0,0,0, +0,170,160,0,1815,0,0,0,0,0,866,0,0,0,0,0,0,0,0,0,689,0,0,0,0,820,0,498,108,0,0, +0,1119,0,0,0,244,609,1005,0,581,0,0,0,0,0,895,0,0,0,1898,0,0,0,0,0,926,0,0,0,0, +0,0,0,0,0,0,0,0,0,538,496,294,301,0,0,0,18,0,0,757,0,0,0,0,0,1263,0,820,0,722,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2028,0,0,0,0,124,1875,0,0,0,881,0,0,0,1348, +0,0,0,0,0,0,0,911,0,954,0,0,0,0,414,0,0,0,0,517,0,0,0,0,0,816,0,0,0,0,0,0,0,0, +713,0,0,0,0,0,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,593,150,0,0,0,0, +0,553,0,0,0,0,0,0,0,0,0,0,108,0,0,0,0,420,0,0,0,0,0,0,0,0,0,0,0,1777,0,0,55,493, +0,0,81,0,321,980,0,0,0,0,0,0,0,0,0,0,0,0,0,0,362,112,0,74,0,0,0,0,0,0,0,625,0,0, +0,0,0,0,377,16,0,0,61,281,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,1031,0,0,0,0,0,0,51,0, +0,0,0,0,0,0,211,309,15,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,789,173,0,439,9,648, +0,0,294,0,0,0,0,0,0,0,374,8,0,1099,0,0,0,0,0,0,0,575,0,0,0,518,0,0,0,702,0,0,0, +0,0,0,87,0,0,0,438,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,464,122,0,0,0,1802,0,0,0,0, +0,0,499,0,0,0,87,476,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,840,283,0,0,0,0,1620,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,609,1160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,600, +323,372,0,0,0,0,471,722,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0, +477,1304,0,1774,0,0,88,0,438,12,0,0,0,0,0,0,0,0,671,997,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,639,22,0,0,782,681,0,0,0,0,0,0,0,0,0,0,1013,664,0,942,0,1349,0,0,0,0,0,0,0, +0,0,0,0,0,356,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,215,289,0,1975, +109,450,0,0,0,0,0,0,0,0,0,0,705,0,0,664,0,0,0,0,0,0,0,1238,0,0,318,0,0,0,0,0,0, +0,0,0,0,0,0,0,960,1872,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,0,0,0,0,0,0,0,0,0,239, +777,0,26,0,0,0,0,0,0,0,0,0,0,0,0,375,414,0,17,0,0,0,1350,0,955,0,0,0,0,0,0,0,0, +887,960,0,0,0,0,0,0,0,0,0,0,708,710,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,919,0,0,0, +0,502,280,7,45,0,0,0,0,777,0,0,0,0,410,0,1110,0,0,0,0,0,0,414,341,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,787,0,0,0,436,0,0,0,0,0,0,0,1707,613,377,96,0,0,0,0,451, +0,0,0,0,0,0,0,0,0,0,0,0,0,680,0,483,916,0,0,0,0,0,0,937,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,739,0,0,0,0,0,0,0,0,82,0,0,663,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,128,0,0,0,0,0,0,0,0,1087,0,0,0,0,0,0,0,503,0,0,0,0,0,0,9,113,104,324,0,460,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,935,702,434,485,1014,949,423,0,900, +0,0,0,0,0,0,0,2018,574,0,0,0,0,0,0,0,0,0,0,0,0,1206,0,0,0,0,0,0,0,0,38,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1022,0,0,0,0,143,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2029,0,0,0,0,0,0,0,0,0,0,0,0,523,0,0,0,0,0,0,625,0,0,425,37,0,0,0,1943,0,0,0, +0,0,765,0,0,0,0,0,0,0,0,0,0,551,0,0,0,0,0,0,0,0,0,0,0,0,168,0,0,1010,0,0,1994,0, +0,0,91,0,0,0,0,532,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1884,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,240,15,0,0,0,1227,0,1534,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0, +0,0,0,0,0,0,0,0,0,0,0,655,562,395,0,0,0,501,1019,0,0,0,0,509,267,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1099,0,0,0,0,0,0,948,0,0,0,0,0,0,0, +462,114,0,0,258,404,0,1717,0,0,0,0,82,1061,0,724,0,0,0,0,0,1133,0,0,0,0,0,0, +1021,841,0,1021,0,0,0,0,0,0,0,0,0,0,488,373,37,0,0,0,0,564,0,0,0,0,0,513,0,0,0, +825,0,0,899,0,0,778,0,0,12,1417,0,1116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,545,0,5, +0,0,0,0,0,0,0,192,0,0,763,0,0,0,0,0,0,0,755,759,0,0,0,0,0,0,0,0,0,370,0,1237,0, +0,0,0,0,0,298,87,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0, +0,0,0,0,814,991,0,757,57,0,0,0,0,0,0,0,0,0,540,0,0,0,0,608,0,0,0,0,0,0,0,0,1014, +0,0,0,902,0,0,0,0,553,1668,0,0,0,0,0,0,0,0,0,559,60,0,0,0,0,0,511,0,0,675,0,0, +156,0,0,0,0,0,0,709,0,698,0,0,0,1745,0,0,0,0,0,0,0,0,0,714,0,0,0,0,0,0,0,0,206, +8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,776,0,0,0,0,0,0,0,0,0,1272,0,0, +0,0,0,1059,0,0,0,0,0,0,406,0,0,0,0,0,0,0,0,0,0,947,0,0,0,0,0,0,168,0,0,0,0,0,0, +870,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,554,0,0,0,0,784,908,0,0,0,0,0,0, +0,396,358,0,0,0,0,0,0,0,0,2,228,0,0,0,0,0,0,0,0,0,0,0,845,14,0,716,1820,594,0, +81,1428,0,161,0,782,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,998,0, +0,0,0,0,0,0,0,0,0,0,0,1043,0,1496,0,0,0,0,0,0,0,0,781,0,0,0,0,0,0,0,817,1114,0, +1814,958,0,0,0,0,812,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,139,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,236,643,0,0,0,0,0,0,0,0,0,1172,0,0,0,0,0,0,0,0,0,1338,0,0,0, +0,0,0,0,0,0,0,0,54,0,0,0,256,0,0,351,0,955,1885,0,469,0,0,0,1270,0,744,0,313,0, +0,0,0,0,0,0,0,402,969,0,0,0,0,0,0,50,0,0,0,0,572,0,0,0,0,847,0,0,0,0,0,0,0,248, +43,0,369,0,0,0,0,0,0,0,0,0,0,0,0,0,766,0,363,0,0,0,0,0,0,0,0,0,0,0,678,0,0,409, +258,82,249,0,0,0,0,0,0,0,0,0,0,0,0,32,393,0,788,0,0,0,1281,509,1968,0,0,0,0,39, +291,0,0,0,589,0,0,54,1059,0,0,0,0,0,0,824,0,0,0,0,0,0,0,0,0,0,1005,0,1598,0,0,0, +0,0,919,0,0,0,0,0,0,0,0,52,132,0,0,0,0,0,328,0,0,0,0,173,0,0,0,0,0,65,1411,0,0, +0,0,0,0,0,0,0,0,442,0,842,0,0,0,0,0,0,0,0,0,534,0,0,0,0,0,0,0,0,0,0,0,0,0,845, +210,0,0,0,0,0,0,0,0,892,0,0,223,0,0,0,0,529,0,0,0,807,0,137,218,0,1444,0,0,0,0, +0,332,661,0,0,0,0,0,0,0,76,1517,0,0,0,0,0,0,0,0,0,0,0,418,0,0,0,0,0,0,0,0,481, +379,0,0,0,0,0,149,18,0,0,0,0,0,0,0,0,742,304,142,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,799,925,195,51,0,0,0,0,688,0,0,0,0,697,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1169,751,0,0,0,452,929,0,221,0,1437,0,0,0,0,955,1251,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,132,0,0,0,0,0,865,0,0,0,0,0,0,0,767, +672,42,0,0,0,1050,0,0,0,0,0,0,0,0,368,44,0,0,0,0,0,0,0,570,29,0,0,0,0,0,0,227,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,522,0,0,0,0,0,0,0,1529,0,0,0,0,0,0,739,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1667,0,0,0,0,0,0,132,511,0,138,208,1020,0,0,23,565,0,344,0,0,0, +0,0,922,0,0,0,0,0,0,0,240,0,0,415,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,402,0,0,754,31,716,0,982,731,0,0,0,0,0,0,0,888,0,0,0,803,847,0,0,823, +0,0,0,0,0,0,785,0,0,2,0,0,0,0,0,0,0,532,0,0,681,0,0,314,0,384,684,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,649,447,0,1818,1007,0,321,0,66,360,0,0,0,385,0,0,0,0,0,0, +0,900,73,254,0,0,0,0,683,1959,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,86,0,0,725,0,0,0,0,0,196,0,0,0,0,0,831,0,0,0,0,723,0,0,0,0,0,994,627,0,0, +0,0,0,0,0,0,0,0,764,66,0,0,0,0,205,36,0,0,0,0,0,0,0,950,0,0,0,887,111,0,0,831, +388,165,0,0,0,0,0,155,0,0,0,0,0,0,0,0,0,0,0,0,0,0,780,755,0,0,0,0,898,146,0,0,0, +0,0,0,0,45,7,0,0,0,0,0,0,0,0,607,0,0,0,0,0,0,65,0,0,0,0,0,0,0,0,0,88,0,0,0,0,0, +621,600,0,367,0,0,0,0,0,0,0,561,0,559,0,585,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +287,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,672,157,0,0,0,0,714,0,0,0, +0,0,456,0,925,0,0,0,0,0,0,0,0,19,0,0,0,0,1473,0,0,0,0,0,0,0,0,0,0,113,0,0,0,0,0, +0,0,0,0,0,0,0,0,69,463,0,0,82,193,2,471,0,0,0,0,633,0,0,0,0,0,0,1148,129,1392, +542,803,0,0,0,0,0,0,0,0,0,0,0,0,438,0,0,0,0,0,0,875,0,0,0,0,0,237,0,0,0,0,0,0,0, +65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,563,0,0,0,9,444,0,0,43,1260,0,0,0,0,0,0, +971,0,0,699,0,0,0,0,0,1116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,829,242,0, +0,593,0,0,0,0,0,0,0,0,201,36,224,0,0,0,0,0,0,1430,0,1806,0,523,0,0,212,1889,0,0, +0,827,0,0,0,0,0,2043,136,242,0,0,0,0,0,0,284,148,10,0,0,0,0,0,0,1249,0,0,0,807, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,0,0,0,494,0,0,0,0,0,0,0,0,1510,0,0,0,0,0, +0,0,0,0,0,505,1306,0,0,764,268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,384,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1703,0,0,0,0,159,964,583,0,0,0, +0,0,0,515,0,0,854,0,0,0,0,0,0,0,0,0,0,0,0,1123,0,0,0,0,0,0,0,136,0,0,0,0,0,1782, +0,0,44,1287,0,0,0,0,0,732,0,0,0,0,313,679,0,0,316,0,0,0,0,595,0,0,0,0,0,0,753, +147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,137,0,0,0,0,414,0,1762,0,0,0,0,0,0,0,0, +0,0,0,599,0,0,0,0,0,0,0,0,0,1749,0,0,0,1627,0,488,0,0,0,0,0,83,0,0,0,0,676,0,0, +1639,0,0,0,0,0,0,0,0,0,278,0,0,0,0,0,0,97,0,14,1085,0,0,0,0,0,0,781,388,0,849, +59,229,0,0,0,0,0,1115,0,0,0,0,108,0,0,0,0,700,0,0,0,0,0,0,0,0,0,1414,0,0,0,0,0, +0,0,0,0,0,0,0,0,660,737,1035,0,0,0,0,0,0,521,690,0,0,0,0,0,0,0,0,0,0,0,0,272,0, +0,0,0,0,0,0,0,0,0,1744,0,0,0,0,0,0,128,733,0,0,277,0,0,0,0,0,0,0,0,0,4,0,0,0,0, +0,0,0,0,0,0,0,0,0,936,1981,40,0,0,0,0,0,0,0,0,775,0,0,0,0,0,0,0,0,0,306,0,0,0,0, +0,0,0,979,0,0,0,0,0,611,0,0,0,0,0,178,0,0,0,1969,0,0,0,0,0,0,0,664,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,390,0,0,0,1510,0,0,0,0,0,0,0,0,0,0,0,493,0,0,37,0,0,0,0,724,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,1537,0,0,168,473,0,0,0,105,0,0,0,0, +627,438,0,0,0,0,0,0,0,0,0,0,11,1256,0,0,0,1626,0,779,0,0,0,0,25,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,308,0,0,0,0,0,741,0,671,0,0,0,0,649,150,0,0,99,521,0,0,3,339,0,0,0, +543,0,0,0,0,0,0,0,0,0,1358,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,234,155, +0,0,0,0,0,0,0,1628,0,766,0,0,0,0,0,0,0,0,0,0,0,0,0,829,0,0,0,1445,0,0,0,486,0,0, +0,0,2,1635,0,0,0,0,558,0,0,0,0,0,0,0,0,0,0,1461,0,0,0,0,0,599,0,0,0,0,0,0,0,0,0, +1376,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,0,0,0,0,0,0,447,0,0,66,1432,0,0,0,0, +0,0,307,0,413,609,0,0,0,930,0,0,0,0,21,939,0,0,0,0,0,962,4,651,0,0,0,0,15,579,0, +0,0,0,0,597,0,0,0,0,0,981,0,0,0,545,0,0,0,0,0,0,0,1558,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,800,17,0,0,17,0,907,0,0,0,110,0,0,0,53,458,0,1983,0,0,0,0,0,0,0,0,0,0,443,0, +0,0,0,0,0,0,0,0,0,0,924,1844,0,1232,0,0,0,0,70,519,0,993,0,0,0,0,0,0,14,530,0, +907,0,0,0,0,0,733,0,0,0,0,0,0,0,0,55,0,188,531,56,0,0,1693,0,0,0,0,0,0,0,0,441, +0,192,928,0,0,0,0,0,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1525,0,259,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,512,185,0,464,1603,0,0,0,0,0,0,0,0,0,0,0,1113, +284,720,0,0,722,0,0,0,0,0,13,0,0,0,0,0,0,0,4,289,43,0,0,0,0,0,0,1694,0,0,0,0, +193,0,0,0,0,409,0,0,0,0,0,0,0,0,0,0,0,0,308,0,0,1863,0,0,0,0,0,0,0,0,0,790,0,0, +745,1002,0,0,0,0,0,0,0,0,0,289,68,477,13,0,0,0,0,0,0,0,0,0,0,609,0,0,0,0,0,0,0, +0,0,0,0,367,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,528,0,0,0,0,0,0,0,0,0,694,58, +548,0,0,0,0,0,0,687,0,0,0,0,1749,0,0,0,0,0,0,0,0,1004,661,0,0,0,0,0,0,445,0,0,0, +74,0,0,0,0,213,0,0,0,0,0,0,0,0,0,0,0,0,0,834,0,0,189,1672,0,0,0,0,0,0,0,1548, +192,0,0,0,0,0,0,0,0,0,0,0,0,0,32,751,0,78,0,0,0,0,0,0,544,1602,105,473,0,0,0,0, +0,0,156,1949,0,1779,0,0,0,0,0,0,0,0,0,0,0,763,0,0,0,0,0,0,0,0,29,0,0,0,0,0,0,0, +0,0,0,883,0,0,0,0,0,0,0,488,0,617,0,0,50,0,694,1518,785,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,546,0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,1016,0,0,0,577,0,0,0,0,0,0, +184,935,114,720,0,0,100,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,95,14,0,969,0,0,0,0,0,0,0, +727,0,1021,0,0,0,0,0,1190,0,0,0,0,0,0,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,0,0,798,0, +587,0,0,695,42,0,1929,141,957,0,465,7,908,0,0,450,148,0,0,0,1166,0,0,0,0,0,0,0, +0,0,0,0,0,253,0,1003,0,0,0,0,0,0,0,0,0,0,0,46,0,0,879,0,806,0,1868,0,0,0,0,0, +1846,0,0,0,730,0,0,0,0,0,0,0,965,0,0,0,0,506,0,0,0,10,0,0,0,22,0,0,0,0,0,0,0,0, +0,0,0,0,0,960,296,0,0,0,0,0,0,0,0,0,0,0,587,0,0,0,0,20,0,0,0,32,982,0,0,0,0,0,0, +0,0,0,0,941,0,0,0,0,435,0,0,0,0,0,0,71,419,0,0,0,0,0,0,688,740,94,345,0,0,679, +582,0,0,0,0,0,0,0,945,0,0,0,0,0,0,0,0,0,0,0,0,539,0,684,1993,0,0,0,659,0,583,0, +803,0,704,0,0,0,0,0,198,181,347,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,481,405,203,0,0,99,826,0,0,0,0,0,0,0,492,0,408,0,0,0,0,0,0,0,0,0,0,4,0,0, +0,0,665,349,137,0,0,0,0,612,1270,0,0,0,0,0,371,0,0,0,826,0,0,0,0,21,1535,858, +374,0,0,0,0,0,0,311,0,0,0,991,1968,0,0,0,0,494,1647,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,769,0,0,0,0,0,642,0,0,157,123,0,0,0,1435,0,0,0,0,0,0,0,0,0,0,79,0,0,0, +0,0,0,1425,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,106,393,486,1690,0,0,0,0, +0,0,0,0,0,0,0,0,756,184,0,0,0,1382,0,0,0,175,0,1493,0,1007,0,0,0,0,0,0,0,0,0,0, +0,219,0,0,0,0,515,99,0,851,0,0,0,0,0,1278,0,0,0,0,0,0,0,1000,982,0,762,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,910,1819,0,0,0,0,0,0,906,0,0,0,0,0,0,0,0,0,0,1730,0,0, +0,0,0,0,0,0,0,0,0,1185,0,0,0,0,0,0,0,0,40,0,0,0,147,0,0,0,0,0,0,0,0,0,0,0,0,0, +650,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,30,0,553,0,0,20,597,0,1614,0,0,0,0,0,327, +49,0,0,0,0,0,0,0,78,0,0,786,134,0,0,0,12,496,0,0,0,0,0,0,0,0,0,0,42,204,0,614,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,147,247,0,0,0,0,942,0,0,2023,0,0,0,0, +0,0,67,285,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1309,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,532,0,0,0,0,0,0,0, +1692,0,0,0,0,55,1704,0,0,0,0,988,0,0,0,223,0,0,0,0,0,0,0,57,1123,0,0,0,0,0,1764, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2015,0,0,0,1599,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,0,0,0,534,0,0,0,0,0,0,0,0,0,0,0, +0,0,504,621,1248,321,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1397,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,441,75,0,0,0,0,0,0,0,0,0,0,841,0,0,0,0,0,693,0,650,314,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,913,0,0,0,0,0,0,0,0,0,0,0,0,0,0,880,0,475,0, +0,1016,179,602,111,329,0,0,0,1864,0,0,0,0,846,1888,0,0,780,0,0,0,82,0,0,0,0,821, +0,0,0,0,0,0,0,0,0,0,0,956,112,0,0,0,261,455,0,0,0,0,0,0,337,385,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,184,1865,0,0,721,16,0,486,0,0,0,265,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,621,0,0,0,0,0,0,0,0,234,0,0,815,0,0,743, +1987,205,197,0,0,0,0,0,0,0,0,0,314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,219,452,589,0, +176,333,0,0,0,0,0,0,0,1110,47,0,0,0,0,0,0,0,0,0,0,0,864,0,0,300,0,1237,0,0,0,0, +0,0,0,0,0,0,0,1685,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,135,395,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,631,0,0,0,0,0,0,835,0,0,0,606,459,0,979,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,612,0,0,0,0,0,0,0,0,158,372,0,854,0,0,0,0,0, +0,0,1492,0,0,0,833,0,0,0,0,0,0,0,1739,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +195,0,0,0,0,0,0,0,0,730,1997,0,0,0,0,0,0,0,0,61,0,0,0,0,0,0,0,266,751,0,0,0,0,0, +0,0,821,0,0,0,715,0,0,0,868,0,959,0,0,0,0,0,0,0,0,0,0,0,1053,0,0,0,950,0,1081,0, +1595,0,0,0,0,59,0,0,0,0,0,0,0,0,0,0,47,684,0,0,0,0,0,0,1606,0,777,0,1020,0,0,0, +1094,0,0,0,0,0,0,0,350,0,0,0,0,0,0,242,1812,0,0,0,967,0,0,0,473,286,0,0,0,0,0,0, +798,629,222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,513,337,306,0,0,0,0,0,0,0,0,0, +146,0,0,1646,0,0,0,0,0,465,0,0,0,525,0,0,0,0,0,0,299,165,0,0,0,0,0,0,0,1064,0,0, +0,0,0,596,0,0,0,0,0,0,0,0,0,0,0,0,0,0,238,1741,0,1233,451,1824,0,0,0,0,733,495, +0,0,0,0,0,1204,0,0,0,559,341,0,224,21,0,0,0,0,0,0,0,0,97,1446,0,0,0,0,0,0,0,729, +0,0,565,727,0,1948,0,0,0,519,0,0,0,0,0,0,0,0,0,1193,0,0,0,0,0,0,790,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,323,2,201,0,0,59,0,0,34,0,896,961,0,1285,0,0,46,0,479,0,0, +0,0,549,0,663,0,0,0,0,0,783,65,682,0,0,0,0,0,11,0,0,0,0,0,522,0,0,0,52,0,0,0,0, +0,383,0,0,0,0,0,0,0,0,127,0,0,0,0,0,397,194,0,0,635,0,0,0,0,0,0,0,0,0,0,975,0,0, +0,0,0,0,0,0,0,0,116,0,51,0,0,858,0,1075,535,448,0,0,0,0,0,610,0,0,0,0,0,0,0,0,0, +0,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,267,673,319,94,92,0,551,0,0,218, +1406,69,256,0,0,952,1980,0,833,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0,0,0,0,0,0,81,0,0, +0,352,634,0,0,0,0,0,618,0,0,0,0,0,0,73,339,0,0,0,0,0,0,0,0,0,0,0,0,0,0,169,759, +0,0,0,0,0,0,0,0,0,0,0,0,0,1075,0,0,0,0,0,0,482,649,0,0,0,0,0,0,0,0,386,336,0,0, +0,1035,0,0,0,0,0,0,0,0,0,0,0,924,0,73,0,0,0,0,0,1971,0,0,0,0,0,0,0,0,0,1344,0, +501,0,0,0,0,0,0,0,0,46,799,0,0,0,0,0,0,0,276,0,0,0,0,0,0,0,770,0,0,0,0,0,0,0,0, +0,0,0,0,0,158,0,0,0,0,0,1432,0,0,0,0,0,0,0,0,0,0,25,0,0,2001,0,0,0,0,0,0,0,0,0, +0,0,0,0,478,0,0,0,0,0,0,91,1461,211,602,0,0,0,0,0,0,0,0,0,1068,0,0,124,567,0,0, +0,1006,0,0,0,0,0,0,0,0,0,735,812,0,0,323,0,0,0,304,0,0,0,0,0,0,0,0,0,148,0,0,0, +0,0,0,0,0,0,523,0,0,144,730,0,0,981,0,0,111,0,0,132,0,0,0,0,0,0,890,0,0,0,0,0, +444,0,1787,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,2041,932,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,937,0,995,0,0,255,0,0,138,863,965,0,0,631,0,0,0,0,1394,16,652,0,0,0,0,0,0, +0,0,0,0,0,0,0,897,0,321,0,0,0,0,0,922,0,619,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,844,0,0,0,0,0,0,1659,0,1100,0,0,0,1173,0,1930,268,251,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,390,711,0,0,0,0,0,0,0,0,0,0,0,0,0,744,0,0,0,0,0,0,0,0,0,624,0,0,0, +1998,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1125,0,0,0,594,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,268,0,0,0,0,0,0,0,563,0,0,0,0,0,0,0,0,2,39,0,0,0,1332,0,0,0,0,0, +0,0,508,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,796,0,0,0,0,527,0,0,0,0,98,0,0,576,0, +0,0,0,0,122,0,276,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,645,0,0,0,0, +0,0,0,0,0,0,0,290,0,0,762,1292,0,0,0,1315,0,1955,0,0,0,0,0,0,0,0,0,0,210,131,0, +0,0,0,797,0,38,0,11,488,0,936,0,441,0,0,0,0,0,595,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +991,0,0,0,0,0,0,0,0,0,0,0,653,0,523,0,0,0,903,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0, +0,0,0,0,0,0,432,0,0,314,0,0,0,0,232,1368,534,0,0,0,0,0,27,0,0,0,12,0,0,0,0,0,0, +0,0,0,264,736,0,1657,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1117,0,127,0,0,0,1208,0,1294, +0,0,0,0,364,0,0,0,0,0,125,1334,0,0,0,0,0,0,0,0,0,0,0,0,0,0,792,0,0,0,0,0,0,0, +849,699,0,0,0,0,0,968,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1446, +124,397,0,0,0,0,0,0,0,0,0,0,0,641,0,0,0,0,0,0,0,0,0,0,0,0,127,346,0,0,517,75,0, +0,0,0,0,0,0,0,83,0,0,0,0,0,0,1031,0,0,0,0,0,0,0,1470,0,954,0,0,345,304,410,0,0, +0,0,734,0,0,0,0,0,1822,0,0,0,1798,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,161, +1865,69,0,0,0,0,0,0,922,0,0,0,0,0,0,0,0,0,0,0,541,0,627,0,0,0,0,0,0,0,0,0,166,0, +0,0,0,0,0,0,0,0,849,0,0,0,0,0,0,0,717,0,0,0,0,0,0,0,0,0,0,0,0,0,0,600,0,0,0,0,0, +0,654,0,0,188,273,0,0,0,543,0,410,87,0,0,941,0,0,186,250,0,1785,0,0,0,0,0,1339, +462,961,0,780,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,529,0,0,0,0,0,0,474,1276,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,24,948,0,0,0,0,657,753,0,0,0,0,941,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,706,985,837,0,1861,0,0,0,0,0,0,0,0,0,0,0,0,0,0,292,933,0,0,0,0,0, +0,0,0,0,767,0,0,0,0,0,0,0,641,0,0,0,1233,114,0,883,0,274,2008,0,1794,285,0,0, +571,0,0,0,0,0,0,0,0,0,0,823,960,16,617,0,431,0,0,0,0,0,0,0,0,0,0,567,0,401,0,2, +781,424,33,0,2006,0,0,274,0,0,1882,0,794,0,0,0,1848,0,0,0,0,0,0,448,47,0,0,0, +1199,0,0,0,0,0,0,0,0,417,0,0,0,0,0,0,0,0,0,0,295,0,0,0,0,0,0,0,1019,0,0,0,0,0,0, +0,0,0,0,0,0,0,620,0,0,0,0,464,0,0,0,0,208,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,442,0,930,0,0,0,0,0,516,68,0,0,0,0,0,1128,104,0,0,0,0,0,0,0,0,787,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,491,0,0,0,0,0,0,711,0,0,9,0,101,441,0,0,0,0,0,0,0,0, +0,0,160,396,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,679,326,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,1128,0,0,0,0,0,737,0,1796,0,0,0,0,0,0,0,0,0,0,0,0,338,574,0,0, +0,0,0,1096,491,405,0,0,0,0,0,1081,0,0,0,0,0,0,0,0,0,0,0,0,0,1676,0,1207,0,0,0,0, +0,0,969,354,0,0,0,0,598,0,297,0,0,0,0,0,0,0,0,1772,751,0,37,0,0,1828,0,0,0,0,0, +0,0,0,0,257,191,582,0,0,0,0,0,0,790,0,0,0,0,0,47,0,0,0,0,0,0,0,449,306,1011,0,0, +0,0,0,299,0,0,0,0,0,0,837,0,0,0,0,0,0,10,329,0,0,0,0,0,1320,0,0,0,0,0,0,158,657, +0,1191,0,0,0,0,0,0,7,0,974,1939,0,1665,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,288, +66,0,0,0,0,494,175,0,1643,0,0,0,0,0,0,0,0,570,750,719,0,0,0,0,0,0,0,0,0,0,0,0,0, +13,0,0,1247,0,0,221,356,0,0,0,0,0,0,0,0,0,0,694,1809,0,0,0,0,0,0,0,411,0,44,31, +0,0,0,0,669,0,673,0,0,0,0,0,0,0,0,0,1303,704,299,0,0,0,275,0,0,216,1761,0,0,0,0, +0,0,0,0,0,0,0,1319,0,0,428,0,0,0,0,0,0,0,0,0,0,514,0,0,0,0,0,0,49,55,102,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,364,0,0,0,0,379,0,921,971,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1258,0,0,0,1058,0,0,0,0,0,656,0,0,0,0,0,144,0,0,0,0,0,0,0,0,0,0, +0,1373,10,605,0,0,0,0,0,0,0,838,0,1012,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154,365,0,0, +0,0,0,0,0,0,0,340,0,0,0,0,0,810,0,0,0,0,0,0,495,0,0,0,0,0,0,0,0,0,261,0,535,248, +0,358,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,567,445,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,697,0,0,0,1336,0,0,0,0,0,0,0,0,917,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,972,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,351,0,0,0,0,0,0,0,0,0,0, +0,0,0,286,0,0,56,438,0,0,0,0,0,1950,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,738,0,0,0,0,0, +0,0,0,0,0,969,2047,0,0,0,0,0,0,0,818,0,0,0,0,0,0,0,866,0,0,0,0,0,0,0,1467,0,0,0, +0,0,0,0,0,0,0,0,0,0,972,0,355,0,0,0,116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,267,189,104,0,0,0,0,1613,0,0,0,0,0,0,0,116,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,886,0,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,863,0,0,0,0,0, +0,0,1953,450,1773,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,381,0,0,0,0,0,0,0, +0,0,0,0,0,1142,0,1189,0,0,0,663,0,0,0,0,0,0,0,846,0,0,528,0,393,378,0,0,0,0,0,0, +325,899,680,1880,0,1770,0,0,0,0,0,648,0,0,0,0,0,0,185,167,0,2046,0,0,0,0,0,0, +249,1645,0,152,0,0,0,1733,0,0,0,0,0,1006,0,0,0,0,0,420,0,0,0,832,0,0,0,0,0,351, +0,0,0,0,6,40,0,0,60,0,0,0,0,1354,745,724,0,0,0,0,0,0,0,0,772,1951,275,108,639,0, +0,0,0,0,0,0,0,0,500,1758,0,0,0,0,0,0,0,0,0,0,0,1886,711,205,0,0,965,865,0,0,0, +534,0,0,0,0,691,0,0,0,237,443,0,878,0,0,0,0,0,1410,0,0,0,0,0,0,0,0,0,0,0,0,0, +995,0,0,0,0,0,0,0,0,0,0,0,0,0,578,0,0,0,0,881,0,0,0,0,0,0,0,0,822,0,923,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,924,0,0,0,665,0,0,0,0,0,1901,0,0,0,0,0,950,498,93, +0,0,0,1451,0,0,0,0,0,747,828,788,400,184,0,198,0,0,0,0,0,0,0,0,0,0,0,994,0,0,0, +0,0,0,0,0,615,320,0,0,0,978,843,905,0,0,0,0,0,0,0,0,850,974,0,0,0,0,6,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,509,0,0,0,0,0,273,0,0,0,0,0,0,0,0,0,0,0,0,0, +201,0,0,0,1041,0,0,0,1040,0,0,0,0,0,0,0,0,0,693,234,774,0,336,0,1399,22,0,805, +802,777,167,789,0,0,1705,0,0,0,0,0,0,0,0,0,0,0,10,13,11,0,0,204,264,0,0,56,0,0, +1917,0,470,0,0,0,0,0,0,0,0,0,0,0,1198,0,0,0,0,0,0,0,0,0,0,1015,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,715,0,0,1002,0,0,0,298,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,867,0,0,724,0,0,0,0,0,0,0,0,0,0,0,0,768,0,0,0,0,0,1066,0,0,0,0,67,0,174,948, +0,0,0,0,0,0,0,0,0,0,0,0,0,764,0,0,0,0,75,137,0,756,0,0,0,0,0,0,1008,842,643,0,0, +0,67,0,0,0,0,0,0,0,0,0,0,0,135,821,0,0,0,0,0,0,0,0,736,0,389,355,0,0,786,0,0,0, +0,0,0,2044,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1030,0,0,0,1083,0,0,0,0,0, +1226,0,0,0,0,356,319,8,389,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,474,0,0,0,427, +0,413,0,730,0,0,0,0,0,373,0,0,0,0,0,0,0,0,0,799,0,0,0,1793,0,0,0,322,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,290,2,0,0,0,0,0,0,0,0,0,0,672, +699,1860,0,0,0,737,0,0,0,1612,0,0,0,0,0,0,0,0,0,0,0,145,124,884,0,0,0,0,0,387,0, +0,0,0,0,0,0,0,0,0,0,679,0,550,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1305,0,0,0,0,0,0,0, +576,0,0,0,0,0,0,0,686,0,607,0,0,37,0,0,0,0,0,0,0,0,0,101,1726,0,0,0,0,0,958,0,0, +0,903,0,0,0,0,147,0,0,0,0,0,0,0,0,0,0,0,367,0,0,0,0,690,0,705,273,0,0,887,0,0,0, +0,0,0,0,0,0,0,0,90,0,0,0,0,0,0,0,908,0,0,0,0,0,0,0,1261,0,0,497,1235,0,429,0,0, +0,0,904,0,12,125,0,0,0,841,0,0,0,0,0,860,946,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,768,0,770,160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,271,0,0,0,0,0,0,0,719,0,699,581,0,0,0,0,0,0,0,0,0,0,862,304,0,631,0,0,0,0,880, +1513,0,0,0,0,0,981,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,434,0,0,0,0,0,550,0,0,476,930, +824,553,0,0,452,0,151,0,0,0,0,0,0,772,0,292,135,0,0,0,0,0,0,0,504,0,0,1089,0,0, +0,0,0,0,0,0,0,0,0,783,0,0,0,0,0,0,206,393,0,0,0,0,0,0,0,0,232,912,0,0,0,0,0,977, +0,0,716,98,0,0,0,0,0,733,0,0,0,0,0,0,0,0,19,0,0,0,0,668,0,360,0,0,0,0,0,0,656,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,726,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,1269,0,0,463,0, +0,0,0,0,0,1454,0,1287,245,0,989,0,0,0,0,0,0,0,0,0,107,164,0,0,0,0,0,0,0,1061,0, +0,0,0,2,484,0,0,0,0,0,0,0,1127,0,0,0,0,0,0,0,460,0,0,0,0,0,932,0,0,0,0,0,0,0, +588,625,0,0,0,0,76,92,0,0,0,0,0,0,0,0,0,0,0,0,0,104,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +763,0,622,0,0,0,253,0,546,0,0,110,0,256,916,0,0,35,212,0,0,746,0,0,0,150,0,0, +1466,0,0,0,1299,0,0,0,0,0,0,0,0,0,1518,0,0,0,0,0,0,0,0,0,0,0,0,0,1229,0,0,0,816, +0,0,0,0,0,0,159,0,0,0,0,0,734,869,126,1716,0,0,0,0,0,0,202,232,0,0,0,0,212,0,0, +0,0,0,111,1003,0,0,0,0,0,0,0,0,0,0,0,1712,0,0,216,0,0,0,0,516,0,0,0,0,0,650,0,0, +0,0,57,99,0,0,0,0,300,574,0,0,0,0,1023,0,0,302,0,1871,0,728,252,0,0,461,0,0,0, +323,0,0,0,0,0,0,775,461,0,0,0,0,0,0,172,0,0,464,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,73,727,0,1023,0,0,0,0,0,0,0,0,0,0,577,0,0,0,0,0,0,0,0,1037,0,0,0,0,0,0, +0,0,280,677,0,0,0,0,0,0,0,0,0,0,0,799,0,0,0,0,159,0,446,1730,0,0,0,0,0,0,0,0,0, +395,0,0,0,0,145,0,0,0,0,0,0,0,20,0,0,426,608,0,0,0,0,0,977,0,250,0,0,0,0,0,100, +0,0,0,0,1982,0,0,0,0,0,476,0,0,0,0,0,0,594,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,447,0,0,0,0,526,0,0,14,1124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,188,0,0,0,0,0,0,0,0,362,301,0,0,0,1743,0,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,872,0,831,0,0,208,202,0,0,0,0,0,0,0,1954,0, +0,0,0,516,872,0,0,313,224,0,0,24,0,11,546,0,0,0,1937,242,241,46,0,0,0,830,1273, +0,0,0,0,0,0,0,825,327,1006,0,0,0,0,0,1580,516,366,0,0,0,0,0,1736,0,0,0,0,0,0,0, +0,0,0,0,1935,0,826,0,0,0,0,139,331,0,0,0,0,0,0,0,0,0,0,0,288,0,916,0,0,0,0,0, +1888,0,0,0,0,0,0,0,1471,0,1570,0,394,0,0,0,0,0,0,0,1931,0,1719,0,658,228,0,0,0, +0,0,374,0,0,0,0,735,0,0,0,0,0,0,323,498,0,1063,0,0,0,0,155,0,0,0,0,0,0,0,0,906, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1139,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,616, +902,0,0,0,0,0,692,0,0,0,0,0,0,823,0,0,0,305,0,0,0,0,0,0,0,681,0,0,0,0,0,214, +1004,0,0,0,0,0,0,0,23,0,0,1703,0,0,0,0,0,0,0,0,0,1443,0,0,19,714,0,0,0,0,64,737, +0,0,345,1758,0,0,579,47,0,0,539,139,0,0,0,0,388,0,0,0,0,253,0,0,0,0,0,0,252,0, +745,0,0,0,0,0,0,0,0,0,0,0,504,107,0,871,0,0,0,229,0,0,0,0,0,903,0,0,71,0,0,549, +6,47,0,0,0,0,0,0,0,0,0,980,865,705,0,0,0,161,0,0,0,0,143,1331,0,0,0,1388,33,724, +0,0,0,19,0,0,0,395,0,0,0,0,0,846,210,0,0,0,122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,695,937,497,0,0,0,0,0,718,0,0,0,0,0,0,0,1581,0, +0,0,0,0,0,161,49,0,0,0,0,0,0,0,0,0,597,0,0,0,1094,0,0,0,811,908,0,0,0,0,0,0,0,0, +0,0,1471,0,0,0,0,0,0,0,0,0,0,42,1935,0,0,0,2014,66,2007,0,0,586,0,0,0,0,0,0,0,0, +0,28,1077,0,0,0,1221,0,0,62,0,0,0,0,0,0,0,0,0,0,1766,0,0,0,0,0,0,0,0,0,0,0,0,25, +0,499,1388,0,0,97,10,0,0,0,0,0,481,0,0,0,0,0,0,0,0,0,0,37,134,155,486,0,1442,0, +0,0,0,0,591,0,0,0,0,0,0,310,1173,0,0,0,0,409,1156,0,0,0,482,0,0,263,926,0,0,0,0, +0,0,0,0,0,0,0,0,0,804,0,0,0,0,0,0,0,0,0,0,0,0,0,1265,0,415,0,348,0,0,0,1012,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,165,1803,0,0,0,0,0,0,0,408, +0,0,0,0,0,0,257,1321,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1138,0,0,0,249,0, +0,0,576,0,0,0,0,231,0,0,0,288,0,0,0,0,0,0,0,0,0,433,1487,569,1678,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,0,0,0,0,0,779,538,0,0,0,413,0,0,0, +0,0,0,0,0,0,0,495,0,0,0,0,0,191,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,530,567, +0,0,0,0,0,1484,0,0,0,0,0,0,815,609,0,0,0,0,0,484,0,0,0,0,0,0,0,0,0,0,900,0,0,0, +0,1335,0,1724,0,0,0,0,0,0,0,0,0,0,0,640,0,0,0,0,0,0,0,0,0,0,0,1831,0,0,0,0,0,0, +0,0,0,0,0,0,0,474,0,0,0,0,0,0,0,0,0,1103,0,1504,655,1034,0,0,0,0,0,305,0,0,0,0, +0,0,0,0,0,1236,0,0,429,217,0,0,0,0,739,278,0,0,0,0,0,0,0,708,0,0,0,0,0,1840,233, +0,0,0,0,0,0,0,0,2017,0,0,0,0,0,1488,0,0,0,1590,0,0,0,0,0,1800,28,0,0,0,0,0,0,0, +0,0,45,0,36,0,22,1442,378,0,0,0,0,0,0,1507,0,0,0,0,0,0,0,0,0,0,39,0,0,1054,725, +1955,0,2036,0,0,0,0,0,0,0,0,0,0,896,1871,0,0,0,0,0,0,0,0,0,0,805,0,0,0,0,2046,0, +0,0,0,17,712,0,617,55,320,271,0,0,0,0,0,0,0,0,0,445,0,184,103,0,0,0,0,0,0,0,0, +659,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +337,0,0,0,506,0,0,0,0,0,843,77,0,458,0,0,0,0,0,1420,382,109,142,330,0,0,0,0,0,0, +0,0,0,0,0,0,87,0,0,0,492,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1239,0,0,0,0,0,0, +211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1049,0,321,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1985,0,0,122,0,0,234,0,0,0,1098,0,0,0,0,0,0,549,253,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,522,131,0,0,149,0,0,0,0,0,0,0,0,0,0,0,0,0,0,507,0,0,0,0,811,630,0,0,0,343, +0,0,0,0,0,448,591,455,0,1381,0,0,0,0,0,0,0,575,0,0,0,0,0,1175,0,0,0,0,0,0,0,0,0, +653,0,0,0,1761,0,1198,0,0,0,0,297,1127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,678,0,0, +164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,0,45,0,0,0,0,0,121,0,0,0,0,0,0, +0,0,125,0,0,0,1622,0,0,0,0,0,721,145,0,0,0,970,792,0,0,0,715,0,0,0,0,0,1999,0,0, +74,531,0,0,65,0,0,0,105,220,0,0,0,0,0,0,0,960,0,0,0,0,0,0,428,19,0,0,401,96,0,0, +0,0,0,1595,116,0,1021,0,0,0,0,0,750,1961,0,0,148,0,0,0,0,0,0,0,0,0,0,0,0,0,75,0, +0,1383,0,0,0,0,0,0,0,0,0,0,0,0,0,0,779,0,0,0,0,0,0,0,0,598,0,424,0,0,0,0,0,0,0, +1222,0,0,0,876,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,0,0,0,0,187,0,8,0,0,0,0,0, +0,0,429,0,685,0,0,0,0,0,0,0,0,0,0,0,132,472,0,0,0,0,0,0,0,0,0,938,0,0,874,0,0,0, +0,0,774,0,0,0,0,0,92,0,0,0,0,0,0,830,701,0,0,0,0,0,426,350,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,603,59,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,0,441,163,4,0, +0,0,0,0,0,0,0,0,806,0,0,0,0,0,0,233,0,0,0,0,1994,0,1739,0,0,393,0,47,1038,0,0,0, +309,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,363,0,0,0,175,0,0,0,0,0,0,0,666, +0,0,1675,0,1600,0,0,0,808,0,0,0,0,0,0,0,0,0,0,0,280,54,0,0,0,0,0,0,0,0,421,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,0,0,103,254,0,262,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,805,0,0,0,0,0,0,0,0,0,1630,0,0,0,0,0,0,0,0,0,0,0,0,0,671,972,989,0,0, +0,0,0,0,0,889,0,0,0,1382,0,0,0,0,0,0,0,775,0,0,0,0,0,0,0,0,0,0,388,202,0,0,0,0, +16,560,0,0,0,841,0,0,566,0,0,0,938,0,0,0,0,0,0,0,0,0,0,912,0,0,0,1361,0,0,0,0,0, +0,618,236,0,1854,0,0,318,190,0,1376,0,0,0,0,0,0,0,349,0,0,0,0,951,1972,0,0,0,0, +0,0,344,0,0,0,0,0,0,0,0,850,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,910,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,163,85,0,487,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,145,0,83,0,0,1013,0,0,0,1922,0,0,169,557,66,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1193,82,0,352,454,57,0,0,1333,396,107,0,370,0,0,0,0,0,0,0,0,0,204,0,0,0, +0,0,1706,0,0,0,0,0,0,0,0,0,0,0,0,394,1204,0,0,0,0,0,1007,0,0,0,1696,0,1519,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,981,0,0,0,0,1072,0,0,0,712,0,1629,0,0,0,0,0,0,0,728,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1271,0,0,0,1608,16,0,0,0,0,485,0,0,0,0,0,0, +153,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1991,0,0,0,0,0,0,0,0,52,0,21,0, +0,0,0,0,0,0,0,0,819,0,0,0,0,0,917,0,0,0,0,784,0,0,0,0,135,0,0,0,0,0,454,0,0,0,0, +0,0,0,0,0,852,1719,0,0,0,0,0,852,0,0,0,0,0,952,0,0,0,0,568,0,0,0,0,0,448,0,0,0, +67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1826,657,0,729,666,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +669,0,0,0,0,0,0,0,402,0,0,152,0,0,0,0,912,0,0,0,0,0,0,51,320,0,445,0,0,0,0,308, +0,0,0,0,0,386,0,0,239,0,0,130,83,0,143,0,348,0,0,0,0,0,0,0,958,0,0,0,0,0,210,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,430,0,0,0,0,0,0,0,0,0,0,0,0,7,213,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,801,0,0,0,0,0,0,0,0,0,936,0,108,0,0, +0,0,0,0,0,0,0,885,587,219,398,364,0,1165,0,0,342,241,303,0,0,0,0,0,0,0,0,0,0, +1454,0,0,0,0,0,0,0,0,0,0,254,562,0,786,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1294,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,493,216,0,0,0,0,219,341,0,0,0,0,0, +0,0,0,0,0,130,1734,154,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,701,604,0,0,879,0,195, +666,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1669,0,0,0,1791,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1228,0,0,0,0,0,623,0,0,0,0,0,0,0,798,0,0,0,0,0,0,0,0,0,0,0,0,84, +122,0,0,0,837,0,0,0,0,0,0,1013,0,0,577,0,0,0,460,932,0,0,0,0,0,0,0,0,0,0,0,31, +131,0,0,0,605,0,0,0,1246,0,0,0,0,68,278,165,307,781,0,0,0,0,0,0,33,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,1113,0,0,720,1953,203,0,0,0,0,0,0,0,425,326,0,0,0,0,0, +0,0,0,0,0,241,1316,0,0,0,0,0,416,0,0,0,1300,0,847,0,0,662,358,0,0,0,0,839,1823, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,654,1522,0,0,0,0,0,0,163,0,0,0,0,0,314,978,0,0,0, +601,0,0,0,0,0,946,434,0,0,0,402,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,1467, +410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,483,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,0,70,0,0,0,0,1405,0,0,0,0,0,0,108,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,777,0,0,0,0,0,747,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,505,0,326,0,0,164,628,654,0,0,0, +37,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,668,152,0,0,0,0,0,0,0,0,0,0,0,581, +0,0,0,0,44,126,89,0,0,0,0,0,0,0,0,1531,0,0,0,0,0,0,0,0,203,1167,0,0,0,0,0,0,0,0, +531,1232,0,0,0,0,0,943,0,670,231,880,0,1617,0,0,0,1957,0,0,0,0,0,0,0,975,0,0,0, +0,0,0,0,0,0,0,0,242,0,0,0,0,0,0,0,0,0,421,0,0,14,834,0,0,0,0,0,0,0,0,0,0,0,0, +465,0,0,0,0,0,834,688,413,855,0,0,0,590,0,0,0,0,0,0,0,0,114,0,0,0,0,0,0,0,0,0,0, +0,45,169,0,0,0,0,0,0,0,0,0,0,0,198,0,0,565,585,0,0,0,0,0,0,0,0,0,0,0,0,0,691,0, +0,0,593,0,0,0,0,0,0,0,0,0,913,116,0,0,0,0,1360,0,0,0,802,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,673,308,0,709,1006,1895,0,228,0,0,0,1840,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,608,0,0,0,0,0,0,0,0,0,1573,0,2039,136,540,0,0,0,0,0,0,0, +897,0,0,938,1878,0,0,0,0,0,0,0,0,0,1469,0,999,0,299,0,0,0,0,0,0,0,578,0,0,0,0,0, +456,0,0,0,1679,163,693,0,0,0,0,0,0,48,755,0,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0, +1091,0,0,0,0,695,0,0,1464,0,0,0,0,0,975,0,0,335,0,0,1979,0,0,0,0,269,1566,630, +396,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1815,634,0,0,0,966,0,0,0,0,0,0,0,9, +412,0,958,0,0,579,382,0,212,0,0,0,0,965,681,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,655, +0,0,0,0,67,0,0,0,0,0,0,751,0,0,0,0,423,231,0,0,1016,300,0,0,0,0,100,237,0,0,0, +1370,0,0,0,1208,0,0,0,0,0,1219,129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,199,0,0,427,0,0, +0,0,949,665,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,712,0,0,0,0,0,1186,0,0,0,0,0,0,0,0,0,0,295,312,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +151,0,0,0,0,588,4,0,0,0,0,0,414,104,0,0,757,263,0,561,0,0,0,320,0,0,0,0,0,0,0,0, +0,0,0,225,0,0,0,0,37,817,0,974,0,0,0,0,0,0,0,0,0,0,0,0,0,2026,131,235,16,0,590, +1157,0,0,0,0,0,0,0,0,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,140,390,0,0,0,0, +0,0,0,1144,0,0,0,464,0,0,0,0,0,0,0,0,0,0,0,0,204,407,303,1218,0,0,0,0,5,325,0,0, +0,0,12,800,0,1783,0,0,0,0,0,0,0,0,0,0,504,621,0,0,0,0,0,0,0,0,0,920,0,376,0,0,0, +0,0,218,580,0,768,454,0,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,164,0,0,0,0,0,0,0, +0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,120,285,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,226,343, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,0,0,1812,0,0,8,0,0,0,21,1125,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,1327,0,0,0,0,575,1598,0,0,0,0,0,0,0,0,0,895,0,0,0,959,0,0, +0,0,0,1759,173,0,0,0,0,266,261,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1427,0,0,300,1033,0,0,0,0,0,0,0,0,0,0,0,584,0,0,0,0,52,734, +0,0,217,239,0,1129,0,0,0,0,0,0,0,0,732,20,0,0,0,0,0,0,0,0,0,0,0,418,0,0,0,613,0, +0,0,0,0,0,0,0,0,632,0,0,85,984,0,0,0,0,909,694,7,1109,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,167,0,0,0,0,280,62,0,0,33,0,0,359,186,980,0,0,0,0,0,0,0,0,0,0,0,585,0,0,0, +211,0,0,336,145,0,1130,0,873,0,0,840,263,0,0,0,0,0,0,0,0,0,916,0,0,0,0,0,0,0,0, +0,0,155,0,0,0,461,97,0,0,0,0,0,1356,0,0,0,0,0,0,0,593,0,0,0,0,0,1392,0,0,0,0, +126,0,0,0,0,1179,0,0,0,0,0,162,0,0,0,0,0,765,0,187,0,1286,0,0,0,0,0,0,0,0,0,635, +0,0,23,215,0,0,0,1306,0,0,97,716,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,657,0, +0,0,0,0,0,0,0,299,0,0,0,0,0,0,134,0,0,0,0,0,0,0,0,0,0,0,658,1082,0,0,0,0,0,2002, +0,0,0,0,0,0,833,248,0,0,0,0,0,1654,0,0,531,0,0,0,0,0,0,634,0,0,0,0,0,0,0,0,0, +853,573,249,0,0,0,0,0,0,0,0,527,0,0,0,0,1419,0,0,0,0,0,0,20,49,0,0,0,992,0,0,0, +728,0,0,0,0,0,0,0,0,0,0,0,0,497,1579,0,0,0,0,62,268,0,0,0,0,0,0,0,1201,0,0,0,0, +0,0,0,0,0,0,0,0,495,193,0,0,0,0,106,0,0,859,0,0,23,0,0,0,0,0,0,0,813,925,0,0, +223,613,953,0,0,0,0,0,0,0,0,666,0,0,0,0,0,0,0,0,0,670,0,0,40,216,0,0,0,0,0,0, +259,0,0,0,440,1114,0,0,0,0,0,0,0,0,74,475,0,0,188,139,0,797,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,1572,0,0,0,0,39,0,0,0,0,0,0,0,0,0,0,0,0,1594,0,0,0,0,0,0,0,290,0,232, +0,0,887,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,521,14,0,0,0,0,0,741,0,0,0,992,0, +0,0,0,0,0,0,0,111,0,0,425,0,0,0,0,0,789,0,0,0,1593,0,1768,0,0,233,0,0,0,0,943,0, +0,0,0,0,0,0,955,225,245,0,0,0,0,0,0,241,0,0,0,0,1943,0,0,0,1284,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,709,0,0,0,0,0,0,554,0,0,0,0,0,0,0,0,1564,0,0,0, +443,0,0,0,0,0,0,280,0,0,0,0,0,0,0,0,729,0,0,0,348,0,0,0,0,0,0,0,758,848,298,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,829,1422,189,121,0,0,632,812,0,0,556,0,0,0,0,0,436,172, +530,844,232,984,0,0,0,0,0,0,0,0,0,0,147,0,0,0,0,0,0,0,0,537,0,0,0,0,0,859,0,0, +842,0,0,0,0,0,0,0,0,0,0,1291,0,0,0,0,0,0,0,0,0,0,0,1482,612,392,0,0,0,262,31,0, +0,0,0,0,0,0,0,0,0,753,549,0,0,0,0,0,0,696,0,0,0,0,0,0,0,834,0,0,0,0,0,771,0,0,0, +0,0,0,0,0,0,0,0,0,0,921,0,0,0,674,0,0,0,0,0,0,0,0,0,0,308,444,0,0,0,0,0,0,805, +180,0,0,278,271,0,0,214,505,0,1215,0,0,0,0,0,0,387,271,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,1645,42,92,0,459,0,0,330,1557,0,0,0,0,0,0,0,0,113,18,0,0,0, +1742,0,0,0,965,0,0,0,0,0,0,0,0,0,0,0,0,0,182,0,0,65,0,0,0,0,0,0,0,0,0,0,0,0,973, +0,0,0,0,0,328,0,0,588,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1786, +0,0,962,1985,0,0,0,308,508,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,588,0,0,0,0,0,0,614,793,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,290,0,0,0,0,0,0,0,0,0,0,1136,0,0,0,0,0,0,0,0,0,0,796,719,0,0, +326,210,0,0,0,701,758,472,0,0,0,1947,278,1079,0,0,0,0,0,0,497,41,0,0,634,46,961, +0,810,524,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,532,0,997,0,0,0,0,0,0,0,0,0,0,0,1301,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1298,0,671,0,0,0,306,0,0,0,0,0,0,0,0,0,0, +693,1823,0,0,0,759,0,0,0,0,0,1932,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,182,0,0,0,1964, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,521,0,0,0,0,0,0,424,857,0,0,0,0,671,328,0, +529,0,0,0,0,0,716,0,1509,80,67,0,0,0,0,59,141,0,0,0,0,0,0,783,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1498,0,0,0,0,343,430,803,1183,677, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1357,53,0,0,0,0,590,0,0,0,0,0,0,0,0,0,0, +0,0,0,329,0,0,0,0,0,0,0,469,0,0,0,0,0,0,0,0,0,0,460,0,0,1743,0,0,963,340,0,0,0, +0,0,1603,0,0,250,0,0,0,0,0,646,218,0,1794,0,0,0,571,0,455,0,0,0,1012,0,0,0,0,0, +0,0,0,0,0,0,0,597,161,0,349,0,524,0,0,0,0,0,0,0,0,0,0,0,0,322,432,0,0,0,0,0,0, +325,223,0,0,0,0,0,566,0,0,0,1394,481,436,0,48,457,610,756,618,0,0,0,755,0,1217, +0,0,0,0,0,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,544,492,107,414,0,0,0,0,0,0,0,0,0,0,0, +1007,0,0,0,0,5,0,0,1580,0,0,0,0,0,0,0,0,0,0,0,0,0,673,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1843,0,0,0,0,0,0,0,0,0,165,0,0,0,0,0,0,809,885,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,498,0,0,0,306,9,0,0,0,0,0,0,0,437,721,146,0,0,0,0,0,0,0,0,0,0,0,177,0,0,0,0, +0,0,0,1377,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,200,0,959,0,0,0,1928,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1435,0,481,0,0,0,0,0,0,142,84,0,0,0,0,0, +1015,0,0,0,315,0,0,0,0,0,0,759,0,0,0,0,0,0,0,0,712,0,0,0,1722,0,0,0,0,0,0,0,0,0, +0,0,0,222,0,985,1414,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1273, +538,706,0,0,0,0,0,0,0,0,115,0,0,0,0,0,0,0,0,0,0,1781,0,0,0,0,0,431,97,665,42, +237,0,0,0,264,0,0,213,0,0,0,0,0,0,0,455,0,0,0,906,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +624,0,574,0,0,0,0,0,0,0,0,0,0,0,0,354,0,0,0,1558,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68, +235,723,1813,0,0,0,957,0,830,0,0,0,0,0,0,0,0,0,0,0,0,23,0,0,496,0,0,0,0,0,0,0, +547,239,88,0,0,0,0,0,0,0,0,0,1310,0,0,0,0,0,0,0,0,80,1076,0,0,118,0,0,0,479,274, +0,0,0,0,0,0,0,0,0,0,0,497,0,0,669,261,0,0,0,0,13,0,0,0,0,0,0,791,250,642,0,0,0, +1429,939,949,0,0,0,0,0,0,0,0,0,0,0,0,0,818,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,982,330,0,0,0,0,545,0,0,0,0,0,0,947,0,1188,0,0,0,0,0,904,0,0,0,0,0,1372,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,693,377,0,0,0,0,0,0,0,0,0,0,0,0,0,0,695,0,0, +713,386,0,0,0,0,128,1575,0,0,0,0,0,0,424,893,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,904,0,0,0,0,0,552,322,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,1808,49,0,0,0,0, +1832,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,421,0,0,442,415,0,0,289, +0,0,0,0,0,206,110,0,0,0,0,0,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +19,1539,0,0,0,0,0,1340,0,1194,0,0,0,0,0,0,0,0,549,0,0,0,0,0,0,0,0,1720,0,0,0,0, +0,0,0,0,0,319,0,0,0,0,112,1180,0,0,0,0,0,0,0,0,0,0,0,967,0,0,0,0,0,0,0,0,0,1940, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,735,0,0,0,0,0,0,0,0,0,897,132,0,0,0,0,0,0,0, +0,0,0,38,838,0,0,0,379,218,8,660,1017,0,0,0,0,0,0,111,387,647,877,0,0,53,790,0, +0,0,0,0,0,0,0,458,0,0,0,0,0,0,954,0,0,0,394,0,1367,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,882,0,0,0,0,0,0,0,1409,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,124,342,199,0,0,0,0, +0,0,0,0,0,0,724,628,0,0,0,0,804,266,0,0,0,0,0,208,0,79,0,0,0,0,0,0,0,0,741,0,0, +0,0,0,0,0,0,0,0,606,0,1494,821,1553,0,0,135,405,0,0,178,100,0,0,0,0,0,0,0,0,0,0, +0,0,0,481,0,0,0,1378,0,0,0,0,0,0,0,0,0,0,0,0,0,791,33,1227,857,0,467,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,447,0,0,0,0,0,0,86,128,0,0,0,0,0,0,587,0,0,0,692,1018,0, +195,0,0,0,0,0,0,0,1546,0,0,0,0,0,0,0,0,0,0,0,684,0,0,345,0,0,0,0,0,0,365,0,1683, +0,0,472,0,433,0,0,0,0,0,0,0,28,0,0,0,997,0,705,3,0,0,0,0,0,0,0,0,0,229,0,0,0,0, +102,0,0,0,0,866,1022,0,0,0,0,0,0,0,0,0,55,0,115,0,0,0,0,933,0,0,0,0,0,0,0,702,0, +0,0,0,0,0,0,1728,26,484,0,0,0,185,618,417,0,803,0,0,0,0,0,0,0,0,0,0,0,1262,0,0, +0,0,0,0,0,0,0,0,0,0,0,633,0,0,0,0,0,0,0,0,0,0,0,0,0,479,262,0,0,0,0,0,0,830,0,0, +0,0,26,70,0,0,0,0,0,0,0,0,217,0,640,51,0,0,360,1586,0,0,0,0,0,652,0,0,0,0,0,766, +0,0,0,0,298,737,0,0,0,0,0,0,0,0,0,0,655,222,906,0,0,1013,991,2009,0,0,0,0,503,0, +0,0,216,154,0,0,0,716,0,844,0,0,0,0,621,252,0,0,0,0,748,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,103,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,576,0,0,0,648,0,0,0,331,0,0,0, +0,0,0,0,0,0,0,0,0,632,0,0,0,518,107,0,0,0,0,0,0,0,0,851,0,0,0,0,504,0,0,0,0,0,0, +0,0,0,0,0,0,7,883,0,0,0,0,0,0,0,922,0,0,0,0,0,0,0,0,91,993,0,0,0,0,0,0,200,131, +10,0,0,0,0,0,0,0,0,0,0,0,0,0,365,1433,0,0,0,0,28,103,0,0,798,1013,0,0,0,0,0,0,0, +0,39,1925,0,853,0,0,271,519,0,0,0,0,338,0,0,300,470,419,0,0,0,0,0,0,836,0,0,0,0, +0,0,1937,0,0,0,0,0,393,0,0,357,0,0,0,0,0,703,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,387,0,0,0,0,0,0,75,708,453,1351,0,303,0,0,772,0,0,0,0,0,0,0,0,749,0,0, +0,0,0,0,0,0,0,0,0,0,0,1065,0,0,717,226,0,0,0,0,0,890,431,626,0,0,0,0,706,0,0,0, +51,698,0,0,0,0,0,0,0,0,0,0,0,828,0,0,17,0,0,0,0,1929,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,84,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,871,498,0,101,1793,0,0,0,0,0,0,435,0, +0,0,0,0,966,0,129,1644,0,0,0,0,0,0,0,0,0,0,0,0,0,997,502,0,0,0,0,0,0,0,0,0,0,0, +0,823,0,1927,0,0,0,0,98,1756,0,0,0,0,0,0,0,0,0,0,0,0,8,0,160,1046,0,492,0,0,0,0, +0,0,129,45,0,0,0,0,0,0,353,558,0,0,0,0,0,785,0,0,0,1145,189,0,0,0,26,353,0,0,0, +0,0,2024,0,0,0,606,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,855,0,0,0,0,0,0,0,0,0,0,0, +0,0,2011,0,0,5,4,0,0,461,764,0,0,0,1449,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1445,0,0, +0,1168,0,0,0,233,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,216,0,0,0,286,0,0,0, +3,0,0,0,723,536,0,0,0,0,0,285,0,0,0,560,0,0,0,0,0,690,0,0,0,0,0,1246,0,0,63,0, +33,0,0,0,0,0,520,1862,0,0,0,0,0,0,0,0,0,0,0,0,630,0,0,0,0,554,0,0,0,0,0,1001,0, +0,0,0,0,446,0,0,0,0,0,0,0,1313,0,0,837,636,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,278, +0,0,0,0,0,0,0,0,868,0,0,0,0,1010,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1231,0,304,0,506,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,93,1408,794, +843,704,0,285,114,485,898,145,0,19,2035,0,0,0,1933,0,0,0,0,0,0,0,1728,0,0,0,0,0, +0,0,0,746,0,0,0,0,0,0,0,995,1964,0,0,0,0,0,0,0,0,0,0,0,1550,0,874,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1018,0,0,0,814,126,0,0,1264,0,0,814,955,0,0,0,0,0,0, +0,981,0,0,0,0,0,0,0,0,915,56,0,0,100,0,0,0,0,0,0,0,0,0,638,0,0,0,0,738,0,0,0,0, +0,0,0,0,0,758,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1112,0,0,214,0,0,0,133,0,196, +168,0,0,0,0,0,1152,0,1245,0,0,538,169,871,1816,0,0,413,133,0,0,0,978,0,0,43,93, +371,0,0,0,0,0,0,526,25,0,754,335,0,0,0,0,182,0,0,0,0,0,0,0,0,0,0,0,39,601,0,0,0, +0,0,0,0,181,370,0,0,1652,358,0,0,0,0,0,0,0,0,0,176,286,0,788,0,0,0,0,0,1223,780, +254,1003,896,0,0,0,1447,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,744,0,0,0,0,0,126,0, +41,788,0,0,0,629,0,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,420,37,1900,0,0,0,0,542,1570,957,0,0,0,0,0,0, +0,373,31,0,0,0,0,125,325,0,0,0,0,0,0,323,0,0,1547,0,0,0,0,0,0,0,0,0,0,0,0,0, +1216,0,0,0,0,0,0,198,1905,629,15,0,0,0,0,0,0,20,75,543,1353,0,0,0,533,0,0,6,0,0, +0,0,0,0,538,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0,11,0,0,0,284,659,0,989,0,0,0,0,0, +0,0,0,0,848,0,0,507,0,0,0,0,0,0,0,0,188,991,884,0,0,0,0,60,959,0,0,0,0,0,1653,0, +0,922,337,0,638,0,0,500,0,0,0,0,0,0,0,0,0,0,0,166,0,0,0,0,0,0,0,0,0,0,0,0,418,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,760,0,0,0,0,0,0,1277,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,770,0,0,0,0,0,0,0,243,89,0,0,0,0,0,0,0,0,0,1396,0, +560,0,0,3,1658,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,586,0,0,1271,0,0,0,505,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1947, +41,445,0,0,0,0,0,0,0,0,57,189,0,0,371,0,0,0,0,552,0,883,0,923,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,875,0,0,0,1788,49,0,0,0,0,0, +0,0,0,0,0,0,661,0,0,1945,0,0,0,0,0,794,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,1135,0,0,0,745,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,410,0,976,0,0,0,0,0,703,0,0, +0,0,0,0,187,322,0,0,0,227,0,0,0,0,560,0,31,1395,0,0,0,0,0,466,0,0,0,0,643,167,0, +0,0,1428,0,412,0,0,0,0,0,0,0,0,0,1118,562,0,0,0,0,0,256,0,0,0,0,0,0,1771,0,0,0, +0,0,1190,132,0,66,0,0,0,0,0,0,0,0,0,0,317,0,0,0,63,0,0,0,0,0,0,0,1475,0,0,0,0,0, +0,0,288,0,0,0,0,608,0,0,0,0,0,0,0,0,1225,0,1189,0,0,0,0,0,0,0,1468,0,0,0,0,0, +689,120,0,0,0,0,0,0,0,1,0,329,0,0,0,0,226,0,0,0,0,0,1855,0,0,461,0,0,0,0,1346,0, +0,0,0,0,85,0,0,299,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1171,0,0, +0,980,0,0,0,0,0,0,0,0,637,279,0,0,0,0,0,293,0,0,0,0,528,17,0,0,0,0,5,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,601,0,0,0,0,0,0,779,0, +196,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1322,737,752,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,412,192,80,0,0,8,1470,0,0,0,0,0,0,0,0,0,873,0,0,0,0,0,835,0,0,0,0,256, +38,986,0,0,0,0,0,0,0,0,0,91,257,278,911,0,0,0,0,0,0,0,0,749,151,0,0,0,0,0,0,0,0, +0,0,0,0,989,0,0,990,0,0,90,194,0,0,0,0,0,425,0,0,0,0,0,774,0,0,0,0,0,0,0,0,0,0, +646,827,752,0,0,0,662,0,22,21,0,0,0,0,0,0,95,239,0,0,0,431,0,0,0,0,0,874,0,0, +265,65,0,0,0,1350,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1887,0,0,0,0,0,0,0,809, +0,696,0,1074,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,630,0,0,802,0,0,0,56,776,0, +970,0,0,797,0,0,0,0,0,400,0,0,1951,0,0,41,0,11,118,0,0,0,0,0,0,0,0,251,615,0,0, +0,1044,0,0,0,0,0,0,0,0,0,0,0,225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,370,0,0,0,0, +104,48,209,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,930,0,0,0,0, +0,0,0,0,0,0,0,1286,0,759,0,120,385,0,0,0,429,0,0,0,0,0,0,0,0,820,0,0,0,0,0,0, +199,0,10,151,0,0,0,761,365,0,0,0,0,0,0,0,0,0,46,1086,0,0,0,0,11,1624,58,344,0,0, +1008,1868,0,0,0,888,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,711,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,440,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,914,1913,0,958,0,885,0,0,0,0,0,0,0,0,0,0,0, +0,0,847,276,0,302,65,0,0,0,510,0,1514,0,0,0,0,0,0,152,291,0,0,0,0,0,0,0,0,0,0,0, +0,282,589,0,0,0,0,0,0,0,0,0,0,0,0,0,130,0,0,463,42,0,0,0,0,0,372,0,0,0,0,0,0,0, +0,0,680,0,0,0,0,0,0,0,0,977,1997,0,0,0,810,0,0,0,0,0,0,0,0,0,1390,0,0,0,644,0,0, +867,982,0,0,0,0,0,0,0,540,0,123,0,0,0,1978,0,0,0,0,789,623,0,1723,0,1220,0,0,0, +0,0,0,0,480,0,0,0,0,0,0,0,0,0,0,0,888,0,0,0,0,0,0,0,0,0,0,0,0,299,1995,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,788,179,0,0,0,0,0,0,431,156,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1373,39,80,196,0,0,507,0,0,0,646,0,0,0,0, +0,1214,0,0,0,0,926,0,0,0,1,114,0,0,0,0,0,446,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,490,0,0,0,491,0,1584,0,0,507,250,0,0,0,158, +10,362,1,0,0,0,0,0,0,0,0,0,408,228,860,480,0,779,0,0,0,557,0,0,142,197,0,0,0,0, +0,0,0,0,0,0,0,1490,11,378,316,1057,0,0,18,579,299,1546,0,177,0,0,0,0,0,0,0,0,0, +411,0,0,0,0,727,439,0,0,0,0,0,1528,0,0,0,0,0,0,58,0,482,0,0,0,505,1952,0,0,0,0, +0,0,0,0,0,0,0,242,0,0,0,0,0,0,0,953,0,0,0,0,802,0,0,0,0,0,0,0,0,0,0,290,0,0,791, +52,0,0,0,0,0,0,0,0,0,0,0,112,0,0,0,0,0,1028,0,0,138,0,0,0,0,1811,0,0,0,0,0,0, +934,1821,0,0,0,0,371,38,0,0,0,1296,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,723,0,0,0,0,0, +0,0,0,0,0,0,0,0,1330,0,0,0,0,0,0,0,1255,296,109,0,0,0,0,0,660,0,0,0,0,270,591,0, +0,0,0,0,0,0,1090,81,0,0,0,0,391,0,0,0,0,249,322,0,0,0,0,0,0,0,1412,0,0,0,0,0,0, +0,0,0,0,526,632,0,0,0,0,0,0,235,144,0,0,0,0,0,940,0,0,0,52,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,309,196,0,0,0,0,0,1912,0,1290,0,686,0,0,625,0,0,0,0,0,0,0,0,0,0,0,412,0, +0,0,0,43,0,0,0,0,11,967,758,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,0,0,0,0,0,0,0,0,0,0, +873,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,890,0,0,2,0,0,0,0,0,0,0,0,1774, +393,263,0,0,0,0,0,0,818,456,0,0,251,178,393,97,0,0,0,0,0,674,168,0,0,0,0,0,0,0, +159,1639,0,0,0,0,0,0,0,0,59,934,0,191,0,0,0,0,346,165,0,877,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,128,0,0,0,0,0,0,1297,0,0,0,0,0,0,164,0,0,0,15,132,241,1073,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,228,324,53,0,0,910,0,0,0,0,0,0,0,0,734,705, +217,73,0,0,0,0,0,0,0,0,636,389,0,1409,0,0,0,0,0,893,0,0,0,0,21,0,0,0,0,0,0,0,0, +0,0,0,0,0,721,0,0,0,959,0,0,0,0,1433,0,0,0,0,0,0,0,0,0,0,0,0,174,189,0,0,0,0,0, +0,0,0,0,0,22,2,0,0,815,354,0,0,0,0,425,0,411,60,13,1611,0,0,0,0,0,0,0,0,0,0,0,0, +0,1478,596,0,0,398,0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,1159,0,0,0,0,0, +592,223,0,0,0,0,0,0,0,245,64,0,0,0,0,278,0,604,0,0,1502,265,0,0,0,0,0,0,0,310, +1763,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,0,1356,0,0,0,0,0,0,0, +0,505,0,0,0,0,0,0,0,1000,0,0,966,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,839,0,0,0,0,0,0, +0,0,0,0,0,0,0,637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,590,0,0,0,0,280,0,0,0,1386,0,0,0, +281,0,1064,0,0,0,0,0,917,0,0,15,555,0,0,1014,1883,0,0,0,965,0,0,117,33,0,0,0, +801,0,0,0,0,0,877,0,824,0,0,0,0,0,0,0,0,0,0,0,365,0,0,0,0,0,0,774,7,0,430,0,0, +231,360,0,0,0,0,0,0,0,0,822,740,0,0,929,1485,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,852,0,0,0,0,17,0,0,0,0,0,0,1001,0,0,0,0,35,831,0,0,384,457,0,0,0,1351,0,27, +0,0,984,0,264,552,0,401,0,0,0,710,0,1211,0,0,11,205,0,0,0,0,0,0,0,0,0,0,0,0,5, +579,0,717,0,0,1011,0,0,0,0,0,0,0,0,0,0,0,0,0,0,805,0,0,0,0,0,0,0,0,0,0,0,489,0, +0,0,1024,0,0,0,0,0,0,0,0,0,892,0,0,0,0,0,0,0,0,0,0,0,0,473,0,0,0,659,864,0,0,0, +0,0,0,152,819,0,51,0,0,0,0,0,0,0,0,0,0,130,0,0,0,0,0,229,0,0,0,0,674,0,0,0,0,0, +0,0,0,0,770,52,79,0,0,0,1666,0,409,0,0,0,0,0,0,0,195,0,688,0,0,0,0,0,0,0,0,0,0, +0,889,174,160,0,0,0,0,0,0,0,0,0,0,0,0,0,872,0,918,569,268,0,0,0,1224,0,1361,0,0, +0,0,0,0,0,0,0,374,0,0,0,0,0,731,0,0,0,0,190,0,0,0,0,0,0,0,202,506,444,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,835,0,17,1526,0,0,0,0,0,477,0,0, +994,1374,76,0,0,0,0,0,0,0,355,287,0,1389,0,0,0,0,0,0,455,384,0,0,0,264,0,0,0,0, +0,0,0,0,0,0,0,0,1001,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,851,175,359,0,0,0,0,0,0,0, +0,287,740,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,857,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +819,1402,0,0,0,0,0,0,174,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1649, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,655,573,0,0,0,0,0,0,0,0,128,351,0,0,0,0,0,0, +0,0,0,0,0,918,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,687,0,0,0,0,0,0,0,0,0,1525, +0,0,0,1009,0,0,0,0,0,0,0,340,0,0,0,0,0,0,0,0,0,0,861,0,176,0,0,0,0,0,0,0,0,0,96, +985,0,615,0,0,0,0,0,0,0,1919,0,0,0,0,0,1131,0,0,0,0,0,0,0,247,0,0,0,0,27,23,0,0, +0,0,0,0,0,0,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1015,0,0,0,0,0,1088,0,0, +0,0,0,1585,0,0,0,0,227,0,0,0,478,360,0,0,0,95,0,0,0,0,0,0,699,0,0,0,26,0,0,0,0, +1119,0,0,0,739,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,741,67,0,0,0,0,0,0,464,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,0,96,0,0,0,26,342,0,0,0,0,0,0,203,0,0,449,0, +0,0,0,0,0,0,0,0,0,256,311,0,0,0,0,0,0,758,0,0,0,0,0,0,0,0,827,0,0,0,0,581,64,0, +1047,0,0,0,0,0,288,0,0,0,0,0,1375,0,0,0,0,0,0,0,0,0,0,0,1309,0,0,0,0,0,0,0,0, +376,12,0,0,0,0,0,154,0,1520,0,1753,95,502,0,0,0,0,0,0,0,269,291,1197,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,1341,0,1017,0,0,0,0,0,0,0, +0,857,1810,533,0,0,1453,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,836,211,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,19,0,156,0,0,0,0,1009,0,0,0,0,0,0,0,0,0,0,0,0,0,820,0,0, +0,0,0,0,0,0,0,228,0,0,0,1131,0,1276,0,0,0,0,0,0,0,0,0,0,0,0,849,1792,0,0,389, +291,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,525,0,0, +0,453,0,0,0,0,666,0,0,0,422,0,355,0,0,0,0,165,0,260,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,865,0,0,0,0,0,0,0,1625,0,0,0,234,0,1383,0,0,0,0,0,0,0,0,306,0,0,0,802,1921, +0,0,0,0,0,0,180,0,0,0,0,1312,814,0,0,0,0,0,0,0,0,0,0,707,0,0,0,1493,11,61,733,0, +0,0,341,0,0,0,98,0,0,0,0,0,0,0,0,0,0,0,1014,0,0,0,0,0,0,0,142,102,0,0,30,0,0, +823,0,1045,0,0,0,1930,0,1512,0,0,0,0,0,0,0,87,0,1243,245,0,0,0,0,0,0,0,48,68,0, +0,0,0,0,0,0,0,126,77,625,938,0,0,351,0,0,0,174,1668,0,707,0,0,0,0,0,0,0,0,0,0,0, +403,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,282,0,0,0,0,0,0,8,44,0,0,363,115,0,0,0,0,0,0, +0,0,0,0,0,0,545,761,0,0,835,1254,0,0,0,0,930,1936,0,0,0,0,0,0,0,0,653,0,0,0,0,0, +344,0,0,1483,673,185,0,0,460,93,753,478,0,0,0,0,0,1020,0,0,0,0,0,0,0,103,0,0,0, +499,0,0,0,0,0,0,207,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,968,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,3,0,0,0,0,399,0,0,0,0,224,563,0,0,0,0,0,704,0,0,0,0,0,0,0,0,0,0,0, +1559,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,861,0,0,0,0,946,333,746,0,0,0,0,0, +0,0,910,0,0,0,0,0,0,0,0,0,0,0,0,0,652,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1393,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1514,0,0,0,0,201,0,510,717,0,0,528,0,0,0,0, +20,0,0,0,1251,0,0,0,1163,0,0,0,307,0,0,0,0,0,1091,0,0,0,0,0,0,0,0,0,0,0,429,0,0, +0,881,0,0,0,0,0,621,0,0,0,0,0,0,0,736,0,348,0,868,0,0,0,0,433,0,0,0,771,1495,0, +0,0,0,215,0,0,0,0,0,124,0,0,0,0,0,0,0,0,0,0,0,55,0,0,0,0,0,0,0,112,62,0,856,270, +0,572,0,0,0,0,939,0,0,0,0,0,0,0,352,0,0,0,0,0,0,0,0,0,647,0,0,0,0,10,0,0,0,0,0, +0,0,220,0,0,0,0,0,0,0,0,0,0,0,0,0,464,0,0,109,0,0,0,1746,0,0,0,515,0,0,0,566,0, +0,0,0,0,0,67,40,0,0,722,992,0,0,923,0,0,0,0,0,0,1145,0,0,0,0,0,0,0,0,0,0,0,568, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,0,0,0,0,645,0,0,328,0,0,0,0,0,0,0,0,0,0,0,0, +1363,0,0,0,0,0,1280,0,0,0,0,0,0,0,0,0,0,7,28,360,162,0,0,0,0,0,0,0,0,0,0,0,764, +0,0,833,862,0,856,0,0,0,0,0,0,736,92,0,0,948,1944,0,1479,63,590,0,0,0,1521,0,0, +0,709,0,0,61,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,483,0,0,0,0,1213, +0,0,0,0,29,1022,0,1712,0,466,0,0,0,0,0,0,0,0,0,0,0,0,0,731,0,0,0,0,0,0,171,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,241,0,0,0,0,0,0,0,0,0,0,0,964,2005,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1100,0,0,0,954,0,0,0,0,0,0,0,0,0,1958,0,0,34,549,994,0,0,449, +137,850,0,0,670,146,0,0,0,0,518,159,0,0,0,0,0,0,0,0,151,0,0,1027,0,0,0,0,0,0,0, +0,0,0,983,0,0,0,0,993,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,141,501,0,0,0, +0,0,0,0,0,0,452,0,0,0,0,0,0,0,0,0,0,233,149,0,0,0,0,0,0,0,0,582,0,0,0,801,0,0,0, +0,0,0,70,0,0,369,0,36,0,0,0,0,0,0,0,204,721,430,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1817,16,1078,1021,0,0, +406,0,0,0,0,0,69,0,0,0,0,0,1830,0,0,0,824,0,0,0,0,0,0,0,0,0,826,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,816,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,717,1845,0,423,0,0, +0,0,0,0,0,0,510,0,0,1048,0,0,0,618,0,0,0,520,0,0,0,0,990,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,321,0,0,0,0,0,0,0,1135,0,0,921,0,0,0,24,397,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,856,0,0,0,139,282,981,0,288,0,0,0,1890,651,56,0,0,0,0,0,0,0, +0,261,0,0,0,0,0,0,0,0,0,0,0,617,1403,0,1205,0,0,563,0,0,0,0,0,0,0,0,333,0,0,0,0, +0,369,0,0,0,0,0,0,0,0,0,622,0,0,0,1407,0,0,0,0,0,0,0,0,0,0,0,0,624,160,0,363,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,619,0,174,292,0,0,656,616,0,0,0,685,0,0,0,0,0,0,0,0,0,0,0,0,0,647,0,0,0,631,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1267,0,0,0,1797,0,0,0,1684,0,0,469,0,531, +1230,73,0,0,0,0,0,0,0,0,0,268,0,0,0,0,0,102,558,109,65,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,595,0,0,0,0,0,374,1832,0,0,0,0,0,0,16,0,405,6,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,881,0,1495,0,0,0,0,0,0,0,0,0,142,0,0,0,0,0,0,0,0,0,0,21,466,23, +257,0,0,0,0,0,0,77,404,0,0,0,0,0,0,712,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,860, +1848,0,0,652,629,0,0,0,0,13,377,0,1842,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1501,0, +0,0,1906,0,0,0,0,0,0,0,0,0,0,0,0,0,491,234,171,0,0,0,0,631,1186,0,0,0,0,0,0,0,0, +0,0,0,0,931,0,170,0,0,0,0,0,0,0,0,0,0,1587,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +765,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,424,0,0,714,0,0,0,0,685,0,0,0,0,0, +0,285,0,0,0,0,0,0,429,0,0,0,0,0,0,0,0,0,0,71,18,0,0,0,0,0,0,0,0,0,0,116,828,0,0, +0,0,0,0,289,0,0,0,0,0,0,0,0,675,0,0,0,1424,0,0,0,0,0,647,0,0,0,1334,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,36,209,0,0,0,0,0,0,0,342,0,0,0,928,0,0,0,0,0,1838,118,856,654, +318,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,915,895,454,0,0,513,1425,0,0, +0,0,0,0,791,0,153,0,0,0,0,0,0,796,909,445,345,0,0,0,0,0,0,0,0,578,0,0,0,1387,0, +0,0,555,0,0,0,0,0,0,766,0,0,0,0,0,0,0,0,0,0,541,0,0,0,0,0,0,0,0,0,0,0,0,0,880,0, +0,0,0,0,1506,0,0,983,0,768,0,0,0,0,584,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,737, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,226,30,426,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,462,0,0,0,385,0,398,0,0,0,0,0,0, +0,0,0,347,0,0,0,0,125,1259,644,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,469,0,0,0,0,0, +1367,0,0,0,0,0,0,0,0,0,0,0,719,0,0,0,0,0,0,0,0,0,0,0,0,0,1423,0,0,0,0,0,0,0,0,0, +749,0,0,0,0,546,645,0,0,0,0,0,0,277,0,0,1275,0,0,0,0,0,0,0,453,536,555,0,0,987, +1107,0,0,90,0,0,0,0,0,0,0,0,860,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +257,0,1768,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1071,0,0,0,0,0,0,0,0,0,0,0,0,0,83, +0,835,0,0,0,0,0,0,0,2006,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,696,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,95,1718,0,0,0,0,0,0,0,26,0,550,0,0,0,0,0,901,0,0,0,0,0, +0,822,0,0,122,0,0,0,807,0,0,0,0,0,262,0,620,601,34,0,0,170,0,0,0,0,537,0,0,0,0, +0,0,0,0,0,332,0,0,208,1909,182,261,0,0,0,1721,0,0,0,0,0,933,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,1609,0,895,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,812,0,0,942,1916,0,0,0,0, +0,0,0,778,0,0,0,137,0,1314,0,0,0,0,0,0,0,1661,0,0,0,0,0,0,0,1591,0,0,0,0,0,0, +820,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,89,0,1160,230,6,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,63,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1740,0,0,177, +170,0,1961,0,0,0,0,0,0,0,0,0,0,0,0,91,0,17,44,0,0,0,0,0,0,0,0,0,270,0,296,0,0,0, +0,0,0,0,1523,0,0,0,0,0,0,0,0,0,0,757,7,0,0,0,0,0,0,0,0,0,0,530,588,0,0,0,0,0,0, +0,0,0,786,0,0,0,0,0,580,627,88,447,57,0,0,0,0,0,0,0,0,845,735,0,0,0,0,0,31,15,0, +460,521,12,424,0,0,0,1302,0,0,0,0,0,0,0,595,0,0,0,13,548,97,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,1472,452,1767,0,0,0,0,0,0,0,0,0,0,115,0,0,0,0,0,0,1543,0,1111,0,0,0,0, +1,0,359,488,0,267,0,0,0,1983,0,0,0,0,0,0,0,1155,0,1575,0,1438,31,0,0,377,101,0, +0,0,0,0,0,0,0,0,0,0,0,0,476,0,0,0,0,0,0,0,0,2023,0,0,0,0,0,1836,0,0,0,0,35,843, +0,0,0,0,0,0,0,554,0,0,0,536,625,207,0,1371,0,0,0,424,785,336,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,896,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,750,0,0,0,0,238,0,0, +0,0,0,383,0,0,0,0,0,0,0,0,603,725,11,0,0,0,0,0,0,0,0,0,476,0,0,0,0,0,1552,0,0,0, +0,0,0,0,680,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,435,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1431,0,0,13,112,0,0,356,0,0,0,0,0,0,0,0,0,0,1963,0,0,0,1244,18,0,0,0,0,0,0,867, +0,0,0,0,0,0,50,708,73,592,0,502,0,0,0,0,0,0,161,347,0,0,0,0,470,33,0,246,571,10, +0,465,614,0,237,0,0,0,0,0,24,18,0,506,0,0,0,0,0,0,33,309,0,0,0,0,0,0,0,0,0,0, +140,0,0,0,0,1056,0,0,0,1704,0,0,0,0,0,0,0,1036,0,0,0,0,0,0,0,0,0,1315,432,86, +264,524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,107,0,0,0,0,0,123,927,0,0,957,1149,0,0, +0,0,0,778,0,502,196,0,0,0,0,1312,0,0,0,0,0,0,0,855,0,0,0,0,0,0,0,0,0,0,45,1400, +0,0,0,1003,0,0,0,0,0,1097,0,0,0,0,0,0,0,0,545,612,0,0,0,0,0,0,0,0,0,0,0,0,54,0, +0,0,0,172,0,0,0,1029,0,0,0,0,0,0,0,0,0,568,0,0,0,732,617,0,0,974,94,989,733,0,0, +0,0,0,0,1789,0,0,665,2015,0,0,0,0,0,0,806,287,0,0,0,0,0,1539,0,0,0,0,0,0,0,0,0, +0,182,1563,0,0,0,0,0,0,0,0,0,484,0,0,0,0,0,1623,0,0,0,0,0,0,0,0,878,1833,0,1569, +0,0,0,0,0,0,0,0,93,0,715,994,0,0,0,0,0,63,0,591,0,0,0,0,0,0,0,749,0,0,0,0,547, +366,0,0,0,1747,0,0,0,0,0,0,0,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1463,0,772, +893,0,0,0,48,0,0,941,0,0,690,1785,106,440,0,0,0,0,0,0,0,0,0,0,32,0,332,216,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,852,0, +0,416,564,0,918,0,1764,0,0,3,0,0,274,0,0,0,0,501,0,0,0,0,0,0,0,851,743,0,49,0, +879,0,0,47,0,0,0,0,0,0,865,0,1202,0,0,0,0,0,0,47,272,0,0,0,0,0,0,0,0,0,0,0,1455, +0,0,0,0,891,1911,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,761,0,0,0,0,0,0,0,0,0,407,0, +183,0,0,490,0,0,0,0,0,0,0,35,731,0,0,0,0,0,0,0,819,0,0,0,0,0,0,0,0,0,0,0,0,0, +575,0,0,0,0,45,818,0,0,77,222,0,0,0,0,849,1880,0,0,0,633,0,1308,0,0,0,0,0,0,0,0, +0,0,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,817,0,0,0,0,0,0,0,0,0,882,0,0,0,914,0,0,0,0, +0,0,0,0,0,0,865,0,0,426,399,58,0,0,0,0,0,0,538,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,876,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,139,566,0,63,12,0,0,0, +0,0,0,0,0,0,0,0,0,0,3,114,0,0,0,0,0,0,0,0,576,0,0,0,0,0,0,0,0,933,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,692,0,0,0,0,0,0,0,0,0,0,0,0,752,0,0,0,0, +0,0,0,0,375,0,1011,0,0,96,0,0,0,0,0,0,0,0,0,148,0,0,0,0,0,0,0,0,0,0,0,337,56, +666,0,246,394,0,0,0,0,0,0,0,0,437,0,0,0,506,0,0,0,0,1003,0,1163,0,328,0,0,0,0,0, +0,0,0,1000,0,0,0,0,0,744,101,0,0,0,0,0,726,0,0,176,0,146,9,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,839,0,0,0,0,0,0,223,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,246,1931,29,0,0,1771,0,0,0,0,0,846,6,157,0,0,0,0,0,0,0,0,0,875,0,0,477, +773,177,639,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1747,0,0,0,0,158,873,0,659,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,391,0,0,0,0,0,0,0,0,0,0,0,0,668,883,0,78,628,0,0,0, +0,0,0,0,0,0,0,0,0,1460,0,962,0,0,0,0,0,460,0,0,0,0,0,0,0,0,0,0,0,0,0,0,34,199,0, +0,0,388,474,0,271,0,333,608,0,0,0,0,0,0,49,0,988,0,707,617,0,0,0,0,0,0,0,756,0, +0,0,0,0,1583,0,0,0,0,0,0,0,0,0,0,285,0,0,0,0,0,0,0,0,0,0,0,0,0,0,344,0,0,0,0,0, +0,0,0,515,1709,0,0,0,0,0,0,0,0,404,0,0,0,0,500,0,0,0,0,0,0,0,0,0,68,216,0,0,0,0, +0,0,0,488,353,0,0,177,236,0,0,458,490,0,0,0,0,0,0,756,1504,0,757,0,1735,0,0,108, +598,0,0,0,0}; +BROTLI_INTERNAL const uint8_t duckdb_brotli::kStaticDictionaryHashLengths[32768] = { +8,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,12,0,0,0,0,4,22,5,0, +4,0,0,0,0,0,0,0,0,0,0,0,0,14,6,0,0,0,5,0,0,0,0,0,0,0,7,13,0,0,4,0,0,0,0,0,0,0,0, +0,6,0,0,0,0,8,0,0,0,0,0,0,7,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,4,0,0,0,4, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,10,4,0,5,13,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,8,7,0,0,9,0,8,0,0,0,0,0,0,6,0, +0,9,0,0,0,11,0,0,6,8,7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,6,8,0,0,0,0,0, +0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,0,0,0,8,4,13,7,0,0,0,0,0, +7,0,5,0,0,0,0,8,5,0,5,0,0,8,7,0,0,0,0,0,0,0,0,0,0,9,0,0,0,8,0,0,0,10,4,0,5,0,4, +0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,8,7,0,4,9,4,0,0,0,0,0,0, +9,0,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,7,18,0,0,0,0,4,9,0,0,4,0,6,0,0,0,6,0,6,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,8,7,0,0,0, +0,9,0,0,0,0,0,0,0,8,6,10,6,0,0,0,4,0,6,8,6,0,0,0,4,0,0,0,0,0,5,0,0,0,6,0,0,0,0, +10,0,12,7,0,0,0,0,0,4,0,0,0,0,0,5,0,0,8,7,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0,0, +0,0,0,0,6,11,0,0,0,0,0,0,0,0,0,8,7,0,0,10,0,0,0,0,0,0,0,0,6,10,0,17,0,8,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,8,6,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +7,0,0,11,4,0,5,0,0,0,0,0,0,0,0,0,0,10,5,0,6,8,5,0,0,0,0,0,0,0,0,0,0,11,5,0,0,0, +0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,9,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,0,0,0,0, +0,0,0,0,0,0,5,0,0,0,6,0,0,10,0,0,0,20,0,0,0,0,0,0,0,0,6,9,5,0,0,0,0,10,4,8,0,0, +4,13,0,0,0,0,0,0,0,9,0,9,0,0,0,0,0,0,0,0,0,0,0,0,4,8,6,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,12,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,12,5,0,0,10,4,10,7,13, +0,0,0,0,0,0,0,0,6,0,6,0,6,0,0,0,0,0,0,19,0,0,4,12,6,9,0,0,0,0,4,0,4,11,0,0,0,0, +0,0,0,12,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0, +0,5,0,0,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,9,6,0,0,0,0,0,4,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0, +6,0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,6,0,0, +0,0,0,5,0,0,0,0,14,4,0,0,0,4,12,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,6,0, +0,0,0,0,0,12,0,9,6,0,0,0,0,13,0,0,5,0,0,0,0,0,4,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,13,0,9,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,8,7,8,4,0,0,0,0,0,0,0,0,0,0,0,7,0,7,0,0,0,4,0, +0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,8,4,0,0,0,0,0,6,0,7,0, +0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0,0,9,5,0,0, +0,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,9,4,0,0,0,0,0,0,0,4, +12,5,11,0,0,0,0,0,0,0,0,0,8,7,0,5,0,0,8,7,0,5,0,0,0,0,8,0,0,0,0,7,0,4,10,0,0,0, +0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +13,5,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,14,5,0,0,0,7,0,0,10,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,6,0,4,0,5,0,0,0,0,8,5,0,0,0,0,0,0,9,5,9,0,0,0,0,0,0,0,0,6,9,0, +0,4,0,0,0,7,0,0,0,6,0,0,10,4,0,0,0,0,0,6,0,0,10,0,0,0,8,5,0,0,0,0,0,0,0,0,10,0, +0,0,0,0,18,4,12,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,7,0,0,0, +0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,4,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, +0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,8,0,0,0,0,0,0,6,0,0,0,4,10,5,0,0,0,0,0,0,0,0,0,0, +0,4,8,7,0,0,8,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0, +0,0,0,8,6,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0, +0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,8,7,0,0,0,0,8,0,12,6,0,6,0,0,0,0,9,7,11,7,0,0,0, +0,0,0,0,0,0,0,0,0,11,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,10,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0, +0,0,0,6,0,0,0,7,0,4,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,14,0,0,0,0,0,8,4,0,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,20,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,12,5,0,7,0,5,0,0,10,0,0,7,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,6,0,4,9,7,0,0,0, +0,0,7,0,0,0,0,0,0,10,0,9,0,9,0,0,0,0,0,0,0,0,4,9,0,0,0,0,6,0,0,0,0,0,0,0,0,11,4, +0,6,0,0,0,0,0,0,8,0,8,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0,0,13,6,0,0,11, +0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,6,18,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0, +0,5,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,0,0,9,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,11, +4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,4,0,0,0,0,8, +6,0,0,0,0,0,0,9,6,0,0,0,0,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0, +0,6,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,6,0,6,0,0,10,6,0,0,0,7,0,0,8,0,8,7,0, +0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0, +0,0,0,8,7,0,0,0,0,0,0,0,0,12,0,12,0,0,0,11,6,0,5,0,0,12,0,12,5,0,7,11,6,0,0,11, +0,0,0,12,0,0,4,12,7,8,6,0,0,0,0,8,5,0,0,0,0,0,0,0,4,11,0,0,6,0,7,0,0,0,0,0,0,0, +5,0,6,0,0,0,0,8,0,10,0,0,0,0,0,0,0,0,0,0,0,9,7,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0, +0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,0,10,0,0,5,0,0,12,6,0,0,0,0,0,0,10,6,0,0,0,0,8, +6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,5,0,0,0,0,11,0,10,6,0,0,8,6,0,0,0,6,0,7,10,6,0, +0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,10,7,0,0,0,0, +10,6,0,0,0,0,0,0,8,5,11,0,8,4,0,0,0,4,0,0,0,0,9,4,8,0,0,0,0,0,0,0,11,6,0,0,0,0, +10,7,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,9,6,0,5,0,7,0,0,0,0,0,7,0,0,11,0,0, +0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6, +0,0,0,0,13,0,8,6,13,0,0,0,11,7,0,7,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,0,9,6,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0, +0,0,0,0,0,5,9,0,0,0,0,0,0,0,0,0,0,4,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,9,7,0,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0, +5,11,5,0,0,0,0,0,0,0,0,0,4,0,7,0,6,0,0,0,6,20,0,0,0,10,7,0,5,14,4,0,0,0,0,0,0,0, +0,0,6,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0, +0,0,6,0,4,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,11,6,15,0,0,0,0,0, +10,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,7,0,0,0,0,0,0,0,0,9,7,13,0,0,0,0,0, +0,7,0,0,8,6,0,0,0,0,0,0,0,0,9,4,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,5,0,0,0,0,0,0,0,0,0,0,0,0,8,5,0,4,0,0,0,0,0,0,0,0,0,0,12,6,8,0,12,0,0,7,0,0,0, +0,0,5,10,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7, +14,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,8,7,10,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,18,6, +14,7,0,0,0,0,0,0,0,0,11,6,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,11,7,0,0,10,7,0,0,0,6,8,6,0,0,0,0,0,0,0,6,0,0, +19,0,0,0,9,5,0,0,0,0,0,0,11,7,0,0,0,7,0,6,0,0,11,0,0,0,0,4,8,0,0,0,0,0,0,0,0,6, +0,0,0,0,0,6,0,0,8,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,7, +0,7,0,0,0,7,15,0,0,5,0,0,0,0,10,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,7,0,0, +0,0,0,0,0,0,9,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +11,7,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,5,0,4,0,0,0,4,0,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0,11,6,0,0,8,5,14,0,0,4,0,0,0,7, +17,0,0,0,0,0,0,0,13,5,0,0,0,0,0,5,0,0,0,5,0,0,0,0,16,6,0,4,0,0,0,0,0,0,12,0,0,0, +0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,5,0,5,0,6,10,0,12,0,0,0,0,0,0,0,0,7,0,0,0,0,8,4, +0,0,0,0,0,0,0,0,0,0,8,7,0,0,8,0,0,0,8,0,0,6,0,7,0,0,0,5,0,6,0,4,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,22,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0, +0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,18,0,0,0,9,4,0,0,8,0,9,7,0,0,0,0,0,0,8,6,0,0,0,0, +0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,9,7,0,0,0,6,0,0,14,0,0,0,0, +0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,7,10,4, +0,6,0,0,0,0,0,0,8,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,9,6,0,0,0,0,0,0, +0,0,11,6,12,7,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,0,9,6,11,6,0,0,0,0,9,5,0,0,0,0,0,0, +0,6,8,5,0,0,0,0,8,0,10,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9, +5,10,7,0,0,0,5,8,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,4,8,7,0,0,0,6,0,0, +0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,22, +0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,5,0,0,0,0,0,0,0, +0,0,0,0,0,17,0,0,6,0,6,12,4,19,6,0,0,0,0,16,0,0,0,0,7,15,7,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,4,10,4,0,0,8,7,0,7,0,0,9, +4,0,6,0,0,0,4,0,5,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,10,0,0,0,0,0,11,7,0,0, +0,0,12,6,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8, +0,0,0,0,0,0,0,0,0,10,4,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,8,7,0,0, +0,0,0,0,0,6,0,0,0,4,0,0,11,4,0,0,12,7,0,0,0,0,9,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0, +4,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,9,4,0,6,0,0,0,0,0,4, +0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,7,9,6,0,7,0, +0,0,0,0,0,0,6,0,0,0,0,8,6,0,0,0,0,10,6,11,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,5,0,4,8,0,0,0,0,0,9,7,0,0,0,0,0,0, +13,5,0,0,0,0,8,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,5,0,0,11,7,0,0,0,0,0,0,8,6,0, +0,0,0,0,7,0,4,0,0,0,0,0,0,0,5,0,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,10,4,9,0,0,0,0,0, +0,4,0,0,0,0,10,5,10,7,0,0,0,0,0,0,0,0,16,7,0,0,0,0,0,7,0,0,0,0,11,0,0,0,0,0,0,0, +0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,4,0,0,0,7,0,0,0,0,0,0,13,0,0, +0,0,0,0,0,0,0,0,7,0,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,13,7,0,7,0,4,16,0,0,0,0,6,8,7,9,7,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0, +0,6,0,0,8,5,0,4,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,11,7,0,0,11, +0,0,0,0,0,9,5,0,4,0,0,0,0,9,7,8,6,0,0,0,0,0,0,10,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0, +0,7,0,0,0,0,0,0,0,0,0,0,0,4,10,6,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,0,10,7,10,0,0,0, +0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,6,8,7,12,4,0,0,0,0,0,0,0,5,14, +0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0, +6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,20,4,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,0, +0,6,15,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,12,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,5,0,0,0,0,0,0,8,6,0,0,18,0,0,0,10,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,9,6,0, +6,0,0,0,0,0,0,0,0,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,9,0,9,0,0,4, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,9,5,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,7,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,0,8,0,0,0,16,0,0,0,0,0,0,0, +0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,0,0,0,11,0,0,0,0,0,0,0,0,0,0, +6,0,0,0,0,11,0,0,0,9,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,7,0,7,0,6, +0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6, +0,0,0,0,0,0,0,6,0,0,18,0,8,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,7,0,4,0,0,0, +0,0,0,0,0,0,0,8,0,0,0,0,0,16,0,0,0,0,0,16,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,18,0,0,0,0,0,0,0,0,0,9,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,4,0, +0,0,0,0,0,0,0,9,4,0,0,0,0,12,5,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,5,0,0,0,0,0,0,0,5,0,0,10,6,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,9,0,0,0,11,0,0,6,0,6,0,0, +0,7,0,0,0,0,0,0,8,0,0,0,0,6,0,0,0,0,0,0,19,0,0,0,12,0,9,0,0,0,0,0,10,7,0,0,0,0, +0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,16,7,12, +0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,10,5,0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,4,0,0,9,0,0,0,8,0,12,4,0,0,0,0, +0,4,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,5,0, +0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,8,6,0,6,0,0,0,0,0,0, +0,4,0,0,0,0,0,6,0,0,9,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,10,6,0,0,0,0,8, +6,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,7,0,6, +10,7,0,0,10,5,11,6,0,0,0,0,0,7,16,0,0,0,0,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0, +0,0,0,0,0,8,7,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +8,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,12,7,0,7,0,0,0, +0,0,0,0,6,0,0,0,0,9,0,0,0,23,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,4,0,0,11,7,10,0,0, +0,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,7,0,0,8,7,8,0,0,0,0,0,0,0,0,0,0,0,14,5,0,0,0,0, +0,0,0,0,18,6,8,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,11,0,0,0,9,7,12,6,0,0,0,0,0,0,0,0, +0,0,12,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,6,8,7,0,0,0,6,10,0,0,0,9,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,6, +10,7,0,0,0,7,0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0, +0,0,0,8,7,8,6,0,0,11,7,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,4,8,7,0,0,0,0,0,0,0,0, +0,5,0,0,13,0,0,0,0,5,0,0,9,7,0,0,0,0,0,0,0,4,0,0,11,0,0,7,0,0,0,0,0,0,0,0,0,6,0, +0,0,0,0,0,12,7,19,0,8,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,10,6,8,0,0,0,0,0,0,0,0,0,0, +6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,7,0,0,12,0,0,0,0,6,9,6, +14,0,0,0,0,0,0,6,0,5,0,0,8,7,0,0,0,6,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,4,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0, +7,0,0,10,0,9,7,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,0,0,0,0,5,0,6,0,0,0,0, +0,0,0,0,0,0,0,6,0,0,0,0,9,7,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0,0,11,7,0,0,13,7, +0,0,0,0,0,0,0,0,12,0,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,11,5,0,5,13,0,8,0, +0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,11,5, +9,6,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,10,0,0,0,8,5,0,0,9,0,0,0,8,7,9,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,0, +0,11,0,13,6,0,0,9,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0, +0,0,0,0,0,5,21,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,5,0,0,0,0,0,0,0,0,10,0,8,0, +0,6,0,0,0,4,0,0,9,0,0,0,0,0,0,0,0,0,0,4,0,0,8,6,0,6,0,7,10,0,8,4,0,4,0,0,0,0,0, +5,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,6,12,0,0,7,0,0,0,5,0,0, +0,0,0,0,0,0,0,6,0,0,8,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +15,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,24,7,0,0,0,0,0,0,0,0,0, +7,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0, +0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,4,12,0,0,7,0,0,0,0,0,5,0,0,0,0,0,0,0,0,15,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,8,0,0,0, +0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,9,0,9,6, +0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,8,4,0,7,0,0,0,0,0,0,0,0, +22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,7,0,0,21,7,0,7,9,6,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,8,0,0,6, +0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,23,0,0,0,0,7,0,0,0, +4,0,0,0,0,0,0,0,0,9,4,11,7,0,5,0,0,0,0,11,0,0,4,20,0,0,0,0,0,0,0,0,0,0,0,11,5,0, +7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +21,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,11,6,0,0,0,0,0,0,0,0,9,6,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,5,0,4,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0, +0,0,0,10,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,7,0,0,11,7,0,0,0,0,0,0,0,4, +0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,7,0, +0,0,0,0,0,0,0,0,6,0,0,21,6,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,14,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,8,0,0,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0, +0,0,0,8,7,0,0,11,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,7,13,7,10,4,0, +0,0,6,0,0,0,0,0,0,0,0,0,5,10,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0,0,8,4,0,0,0,0,0,6, +0,0,0,0,0,0,0,0,0,0,12,7,0,6,0,0,10,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0, +0,0,0,0,7,0,0,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,10,5,0,6,0,0,0,0,0,4,0,0,0,0, +0,0,0,0,0,4,0,0,0,0,9,0,11,4,0,0,0,6,0,0,0,5,12,7,0,5,0,0,0,0,0,4,0,0,0,7,0,0,0, +0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,13,6,10,0,0,0,17,0,0,4,0,0,0,0,0,6,0,4,0,5,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,11,7,0,0,0,7,0,0,0,6,0,0,0,0,0,0, +0,6,0,4,0,0,0,0,8,0,0,0,0,5,0,0,0,0,0,4,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,9,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,0,0, +0,0,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,16,4,0,0,11,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +8,7,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,8,6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10, +7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,12,5,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0, +5,18,7,0,0,14,0,0,0,0,0,0,0,9,4,0,7,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,0,0,0, +8,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,7,0,0,0,0,0,0,11,0,0,0, +10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,14,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +11,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,14,6,0,0,0,0,11,4,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,10,7,0,6,0,0,9,0,9,5,0,0,0,0,0, +0,0,0,10,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,8,5,0,0,0,0,0,0,0,0,0,0,11,4,0,6, +0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,12,4,0,6,8,6,0,0,0,0,0,0,0,0,0,0,8,0,0,5,0,0,0,0,0,0,0,7,0,0,13,0,0,0,0,0,0,0, +0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,12,7,0,6,0,0,0, +0,0,0,0,0,0,0,0,0,13,4,0,7,0,0,0,7,0,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,0,0,0, +9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,10,6,21,5,0,0,0,0,8,0,0,0,0,4,0, +7,0,0,0,0,0,0,11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0, +0,7,9,6,11,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,7,10,0,0,0,0,0,0,6,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,19,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,18,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,9,4,10,4,0,7,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,9,7,9,7,10,4,0,7,0,0,0,0,0,0,0,6,12,0, +0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0, +0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0, +0,0,0,0,0,5,0,0,8,7,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0, +0,0,0,0,4,0,0,8,0,0,6,0,0,0,7,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,7,9,7,0,0,0,4,8,0,0,0,0,6,11,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,13,4,0,0, +12,6,0,6,0,0,0,0,8,7,0,7,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,4,0,0,0,0,0,0,0,0,0,0,9, +7,22,0,0,0,0,4,0,0,0,0,0,6,0,0,0,4,0,0,9,0,0,6,0,0,24,7,0,7,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,10,6,0,5,0,0,0,0,0,0,0,7,0,0,8,0,0,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,7,0, +7,0,0,0,0,0,0,13,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0, +0,0,0,0,0,7,12,0,9,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,4,0,0,0,7,0, +0,0,0,8,7,0,0,0,0,0,0,0,0,0,4,18,0,0,0,0,0,10,0,0,5,0,0,11,0,0,0,0,0,0,5,0,6,0, +0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0, +4,0,0,0,0,0,0,10,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0, +0,0,0,5,8,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,20,7,0,0,0,0,0,0,0,0,0,0,0,4,9,0,12, +6,8,0,14,7,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,10,0,0, +0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,9,6,0,7,12,0,0,0,0,4, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7, +0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,4,0,0,9,0, +12,6,0,5,0,0,0,6,0,4,0,6,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0,0,8,0,0,0,0,4,0,0,0,0, +10,0,0,0,0,0,0,0,8,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,0,0,0,0, +6,0,0,12,6,20,5,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,5,0,0,0,6,13,7,0,0,0,0,15,6,0,0,0, +6,0,0,13,7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0, +10,6,0,0,0,0,0,6,0,0,0,0,9,0,0,0,0,0,19,6,0,0,0,0,0,0,0,0,0,0,13,0,11,0,0,0,0,0, +0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,10,0,0,6,0,0,0,0,8,0,0, +0,9,0,15,4,0,6,0,0,0,0,0,6,12,0,0,0,0,0,0,0,14,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0, +0,0,0,0,0,8,7,0,0,0,0,0,6,10,0,0,0,0,0,0,0,0,7,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,10,5,0,0,0,0,8,0,0,0,0,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,6,12,0,0,0,10,7,0,5,0,6,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,6,0,4,0,0,0,0,0,7,0,0,0,0,0,0,0,4,9,6,0,0,0,7,0,0,0,0,0,0,0,0,8,6,0,0, +0,0,0,0,0,4,12,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,7,0, +0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,6,9,4,0,0,8,4,0,6, +0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,8,0,0,6,13,4,0,5,8,0,0,0,0,0,0,0,8,0,0,0,10,5,0,0,9,0,0,0,0,0,0,6,0,0, +24,0,0,0,0,0,0,0,8,0,0,7,0,0,12,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0, +6,8,0,10,0,9,7,0,0,0,5,0,0,0,0,0,0,0,4,8,5,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,4,0,0,0,0,0,6,0,0,0,0,0,5,0,0,0,0,8,0,0, +0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,10,4,0,0,0,0,0,0,0,6,0,0,0,4,20,0,0,7, +10,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,9,6,0,0,0,0,0,0,0,4, +12,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,9,4,0,5,0,0, +0,0,0,0,0,6,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,6,9,0,0,0,0,7,0,0,0,0,0,6,0,5,0,0,0,0,0,0,0,0,9,0,0,0, +0,6,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,17,7,0,0,13,6,14,6,0,0,0,0, +8,0,0,0,0,0,0,7,12,7,8,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,4,0,0,0,0,0,4,0, +0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,12,4,0,0,10,7,0,0,0, +0,0,0,10,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,12,0,0,6, +0,0,0,0,0,0,0,0,8,7,12,0,0,0,0,0,0,6,0,6,0,4,0,0,18,6,0,0,0,6,0,0,0,0,0,6,10,6, +0,0,0,0,0,0,8,7,14,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19, +0,0,0,8,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,7,0,0,10,5,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, +0,0,9,4,8,0,0,0,0,0,0,4,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0, +0,6,0,0,9,7,0,0,0,0,0,5,0,0,0,0,8,7,0,0,14,0,0,0,0,6,0,0,0,0,0,0,9,6,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,5,0,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0, +0,0,0,6,0,0,0,6,0,4,0,0,0,0,0,4,0,0,0,0,12,0,0,7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0, +0,12,0,16,6,0,0,0,0,0,0,11,7,0,4,8,7,0,0,0,0,0,6,0,0,0,0,16,0,0,0,0,6,0,0,0,0,0, +0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,10,7,0,0,0,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0, +0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,13,4,0,0,10,0,0,0,0,0,0,0,0,0,19,0,0,0, +0,0,0,0,0,0,0,0,0,0,8,6,22,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0, +5,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +4,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,18,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,14,7,0,0,11,5,0,0,0,5,0,0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,24,6,0,0, +0,7,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,7,0,4,0,0,0,0,8,7,0,0, +9,6,0,0,14,5,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,12,6,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,7,0,0,0,5,0,0, +0,0,12,7,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,6,0,0,13,7,0,0,0,0,0,0,14,0,11,4,0, +0,0,4,0,0,0,0,14,5,0,0,0,0,0,5,11,5,0,0,0,0,22,5,0,0,0,0,0,7,0,0,0,0,0,4,0,0,0, +4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,17,0,10,0,0,0,8,0,0,0,19, +5,18,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,10,6,0,6,0,0,0,0,10,4,0,4,0, +0,0,0,0,0,14,7,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,0,9,6,12,0,0,6,0,0,0,0,0,0,0,0, +12,0,10,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,13,0,9,7,0,0,0,0,0,0,0,0,0,0,0,7,9,7,0,0,8,0,0,0,0,0, +22,0,0,0,0,0,0,0,23,6,14,0,0,0,0,0,0,7,0,0,0,0,11,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0, +0,0,10,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,8,5,0,0,0,0,0,0,0,0,0,7,11,6,21,0,0,0,0,0, +0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0, +0,0,0,0,0,0,0,4,9,7,0,0,0,0,0,0,12,0,0,0,0,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,9, +0,0,0,20,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,11,7,0,0,0,0,0,0,0,6,15,0,0, +0,0,0,0,0,0,0,0,0,0,0,12,4,0,5,0,0,0,0,0,0,11,7,17,6,0,0,0,0,0,0,15,6,0,7,0,0,0, +0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,6,0,5, +0,0,11,0,11,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0, +17,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,8,7,9,6,0,0,14,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0, +8,7,0,4,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0, +0,0,0,5,0,4,0,0,8,7,0,6,12,5,0,7,18,7,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0, +10,0,11,0,0,0,0,0,0,0,0,0,0,0,9,0,0,4,0,6,0,7,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0, +7,0,0,0,0,8,0,0,0,15,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,0, +0,0,6,0,0,0,0,23,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,5,0,0,0,0,0,0,8,6,0,0, +0,0,0,0,12,7,9,7,0,0,10,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,9,0,8,7,0,0,0, +6,0,6,0,4,0,5,0,0,0,0,0,5,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,7,10,5,0,0,11,6,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,4,9,7,0, +0,0,0,11,7,0,0,0,0,0,5,0,0,0,7,0,0,0,0,23,6,11,4,0,0,0,0,0,0,9,0,0,0,10,6,0,0,0, +0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,10,6,0,0,0,7,0,0, +0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13, +6,11,7,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,6,0,0,0,5,0,6,0,6,0,0,0,0,0,0,0,0,0,0, +0,6,0,0,0,0,8,7,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,4,10,0,8,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,10,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0, +0,0,0,0,0,0,10,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,11,6,0,4,0,0,14,5,0,7,0,0,0,0,0,6,16,0,0,0,0,0,0,0,10,0,0,7,15,0,0,0,11,7,0,0, +0,0,0,0,0,0,0,0,8,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,5,0,0,0, +0,8,0,0,6,0,0,0,0,0,0,9,5,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,6,0, +0,0,0,0,0,0,7,0,0,0,0,15,7,0,0,0,0,8,0,0,0,14,0,0,0,0,0,0,0,16,7,0,0,0,0,0,7,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,12,6,11,7, +9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13, +7,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,12,0,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,8,0,0,5,8,7,10,6,0,0,0,7,0,0,0,0,12,6, +0,0,9,0,0,0,12,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,10,0,0,0,10,5,0,0,0,0,0,0,9,6, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,0,0,9,5,0,4,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,9,0,0,5,0,0,8,7,8, +6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,10,0,9,4,0,0,0,0,0,0,0,6, +11,0,0,0,0,0,0,0,0,0,0,0,8,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,8,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0, +0,0,0,10,0,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0, +0,0,8,4,0,5,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,8,5,0,0,0, +0,0,0,0,7,0,0,0,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,6,0,7,0,0,0,0, +20,0,0,0,0,0,0,0,0,0,0,7,9,0,0,0,0,0,0,6,0,6,0,7,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0, +0,0,0,14,7,0,0,0,5,0,0,22,4,10,0,0,0,0,0,0,4,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,11,5,13,0,0,0,0,0,0,0,0,0,8,0,0,7,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,10,7,0, +0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,7,14,6,0,0,0,0,9,5, +0,0,0,0,0,6,0,0,0,5,10,0,8,6,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,8,4,0,6,0, +0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7, +14,0,0,5,0,0,18,0,8,4,0,6,0,0,20,0,13,0,0,0,0,7,0,4,0,0,0,0,0,4,8,4,0,0,0,0,0,6, +0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0,14,0,0,0,0,0,9,7,0,0,9,0,0,0,0, +0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,20,0,14,0,0,4,0,6,8,5,0,0,0,0,0,7,0,0,0,0,0,0, +0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,4,12,7,0,6,0,0,9,7,10,5, +0,0,8,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,18,0,0,0,14,7,0,0,0,0,0,4, +0,0,0,0,0,0,17,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0, +0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0, +7,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5,0, +0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,23,0,0,7,0,0,0,0,0,0, +0,0,0,0,0,0,0,4,0,0,0,0,0,0,12,7,8,4,0,0,0,0,0,0,0,0,0,6,0,0,9,5,0,0,0,7,0,0,0, +0,0,0,0,0,0,4,10,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,0,0,18,7, +0,0,8,0,0,5,0,0,10,0,0,0,0,0,0,6,0,0,0,0,0,5,0,7,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0, +6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,6,0,0,10,0,0,5,10,4,0,0,12,0,0,0,0, +6,22,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,7,0,5,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,6,0,7,0,0,0,6,0,6,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, +0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,16,6,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,12,7,0,0,0,0,9,0,0,0,0,6,0,0,11,0,0,0,0,0,13,0,9,6,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,10,7,0,0,0,7,0,6,0, +0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,11,0,15,0,22,7,0,4,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0, +18,0,0,0,0,0,0,0,0,0,14,0,0,4,0,0,0,0,8,7,9,0,0,0,0,0,9,0,0,0,14,0,0,0,0,0,0,0, +0,0,11,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,7,0,0,0,6,0,6,0,0,0,0,8,0,0,0,0, +0,11,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,9,4,0,0,0,0,0,4,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,8,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0, +0,0,0,0,0,0,8,6,0,0,9,5,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,5,0, +0,10,6,9,0,0,0,0,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0, +11,7,12,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0, +0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,5,0,0,10,6, +0,0,0,4,0,7,13,0,0,4,0,0,11,4,0,6,0,0,0,0,0,6,8,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,5,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,5,0,0,0,0,12,6,0,0,0,0, +11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,11,5,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8, +7,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,6,17,0,9,0,10,6,0,6,12,0,0,4,0,0,0, +0,0,0,0,0,0,0,8,5,12,7,0,4,0,0,0,0,0,0,0,0,0,0,11,0,9,0,10,6,11,5,0,7,0,0,8,0,0, +7,0,4,0,0,0,7,0,0,0,0,0,0,8,6,0,0,0,6,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,6,0, +0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,11,0,0,0,0,6,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,10,0,0,0,0,0,8,6,0,0,0,0,0,6,12,0,0,0,0,0, +0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,6,0,0,16,0,11,5,0,0,0,0,0, +0,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,9,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,6,10, +7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,9,5,0,0,0,0,8,0,9,0,0, +0,0,0,0,0,0,7,10,0,13,0,0,6,0,0,0,0,0,0,0,0,0,6,9,4,0,0,0,0,0,0,10,0,0,0,0,0,10, +0,0,0,0,0,0,0,10,6,11,0,0,0,0,0,9,0,0,0,0,0,0,4,0,0,0,0,0,0,10,5,0,0,0,0,0,6,0, +0,0,0,0,0,18,4,0,7,0,0,0,0,0,0,24,0,8,6,0,7,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0, +0,8,5,0,0,0,0,10,7,0,6,0,0,0,0,0,0,0,0,8,5,10,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0, +6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,4,0,5,15,0,0,0,0,7,0,7,0,0,0,0, +0,0,0,0,0,6,10,5,0,0,0,6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,12,0,0,0,0,0,0,0,0, +0,0,5,0,0,0,0,0,0,14,4,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,11,0,10,4,9,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,7,0,0,0, +0,0,0,0,0,0,0,0,7,13,7,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0, +0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,8,0,10,6,0,4,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0, +0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,9,7,0,0,0,0,0,6, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,6,0,0,0, +0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0,0,5,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,11,0,0,0,0,6,0,0,0,0,0,0,0,6, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,0, +6,0,0,0,0,0,0,0,6,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0, +0,0,0,0,0,0,0,6,0,6,0,0,0,5,0,0,0,0,0,0,0,5,0,0,10,0,11,5,0,0,0,0,0,0,14,7,9,7, +0,6,0,0,0,0,0,4,0,0,0,0,0,0,11,7,0,6,0,0,0,0,0,0,9,7,0,4,0,0,0,7,0,0,0,0,0,5,0, +0,0,0,0,5,0,0,0,7,0,0,0,0,0,5,0,0,0,0,17,5,0,0,8,0,0,0,0,6,9,4,0,0,0,0,0,0,0,0, +8,7,11,7,9,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,6,9,5,0,0,8,6,0,0,0,5,0, +0,0,0,9,0,0,0,9,6,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,4,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,4,0,0,0,5,0,0,0,0,0,7,0,0,0,0,0,7,13,5,0,0,0,7,0,0,0,0,0,7,9,6,11,7,0,7,0,0,0, +0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,8,5,0,0,0,5,9,4,0,0,0,0,0,0,0,0,8,4,0,0,0,0, +24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0, +0,0,0,0,6,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,5,11,6,0,4,0,7,20,0,8,5,9,5,9,0,0,6, +0,0,0,0,0,0,0,0,0,0,0,7,23,5,0,0,8,4,0,0,10,0,0,6,0,5,0,0,0,0,0,0,0,0,0,0,0,7,0, +0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,0,0,0, +10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0, +6,0,0,0,0,14,0,18,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,6,0,4,0,0,0,0,0,0,8,4, +11,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,12,0,10,7,0,0,10,0,0,0,0, +0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,6,0,0,0,0,8, +6,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,4,0,6,0,4,0,0,0,0,0,5,0,0, +0,0,0,0,0,0,0,7,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,17,7,11,0,0,0,0,0,0,0,0,0,0,4,12,6,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0, +0,5,12,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,6,0,0,20,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,4, +0,0,0,5,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,6,0,4,13,0,0,7,0,0,0,0,0,0, +0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,12,6,0,7,0,0,0,0,10,0,23,6,0,0, +0,4,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +10,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,11,0,9,7,0,0, +0,0,0,0,0,0,0,0,9,7,0,4,0,0,0,0,8,7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, +0,0,0,0,0,6,0,0,10,7,10,5,0,0,8,0,8,0,0,0,0,0,0,4,0,5,10,0,0,0,0,0,0,0,9,0,0,6, +0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,11,7,0,0,0,0,0,0,0,0,9,4,0,0,0,0,0,6,0,0,8, +7,0,0,0,0,0,5,0,0,0,0,0,0,0,0,10,0,0,0,0,5,0,4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,24,7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,6,0,0,9,0,0,0,0,0,0,7,0,6,13,0,8, +0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,0,0,8,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0, +4,0,0,0,0,0,4,0,0,0,0,0,0,0,6,8,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,4,0,4,0,0,0,5,0,7,0,0,10,0,10,7,0,0,12,5,0,0,9,0,0,0,10,0, +0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0, +12,0,0,0,0,0,8,5,13,6,0,0,0,0,0,0,9,4,0,0,0,0,8,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0, +0,0,6,0,0,14,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,17,6,0,0,0,0,12,6,0,0,0,0,8,0,0,7,0, +7,0,4,9,0,0,6,0,0,0,6,0,0,0,0,0,0,8,7,0,0,0,0,0,0,11,0,0,4,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,18,7,0,4,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,0,0, +0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,0,11,7,0,0,0,0,0,0,0,0,0,4,0,0,0,0, +11,0,0,0,0,0,0,0,21,0,0,6,10,0,0,0,0,0,9,0,10,0,0,0,0,0,11,0,0,0,0,6,0,0,0,0,0, +5,0,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,4,0,0,23,7,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,9,7,0,0,0,7, +0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0, +11,6,0,0,0,0,0,0,0,6,0,0,0,0,10,7,0,0,9,4,0,0,11,0,8,5,0,0,0,7,8,5,22,0,0,0,9,6, +0,0,0,0,0,0,0,6,10,4,0,0,0,0,0,7,9,4,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0, +0,0,0,11,6,0,0,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0,6,0,6,0,4,0,0, +0,0,0,0,0,7,0,7,0,4,13,0,0,0,0,0,8,0,0,0,0,7,0,0,0,0,0,0,11,6,0,7,0,0,0,0,9,0,0, +0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,8,0,0,0,0,0,8,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,13,5,8,0,0, +0,0,0,0,0,14,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,17,6,0,0,0,0,13,4,0,0,9,6,0,0,10,5,0, +0,10,5,0,0,0,0,13,0,0,0,0,6,0,0,0,0,0,0,10,0,12,0,0,0,0,0,0,0,0,0,0,0,8,4,0,4,0, +0,0,4,0,0,0,0,0,4,0,0,12,0,0,5,9,4,0,0,0,0,0,0,0,0,0,5,8,5,0,0,0,7,0,0,0,0,8,7, +0,0,0,6,12,5,0,0,0,5,0,0,0,5,0,0,0,0,0,4,12,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,7,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0, +0,9,6,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,4,11,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0, +0,0,0,0,12,7,0,0,0,7,10,7,0,0,11,0,0,0,0,0,0,0,0,0,11,7,0,0,0,6,0,0,11,0,0,0,0, +0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,22,0,10,7,0,0,8,5,0,0,0,0,0,5,0,0,0,0,0,0, +0,0,0,0,9,6,8,7,0,6,0,0,0,0,0,5,0,0,0,0,0,0,8,7,0,0,0,0,9,7,0,0,0,6,0,0,8,7,0,0, +0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,5,0,0,0,4,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9, +6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,5,0,0,0,0,14,0,0,0, +9,0,0,0,0,0,0,0,0,0,9,7,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,12,0,0,0,0,0,12,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,10,7,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,6,0,0,0,0,0,0,9,6,0,0,0,0,0,6,0,0,0,0,0, +0,0,0,0,0,9,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0, +0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,6,0,7,12,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0, +0,7,0,0,8,6,0,0,0,0,10,7,0,0,0,0,0,0,0,6,0,0,0,0,0,6,12,0,0,0,0,0,0,0,0,6,0,0,0, +0,0,6,0,0,0,6,0,0,0,0,0,6,16,0,0,0,0,0,0,0,0,0,9,0,17,0,14,7,8,0,0,0,0,0,0,6,0, +0,0,0,0,0,0,0,0,0,11,0,0,6,8,7,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0, +9,0,0,0,0,7,0,0,0,0,11,5,0,4,9,6,8,0,0,0,0,0,0,0,0,0,10,0,11,7,0,0,0,0,0,0,0,0, +9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, +0,0,0,12,0,0,0,0,0,10,5,0,4,0,0,0,0,0,7,10,6,11,6,0,0,0,0,0,0,0,0,0,0,0,0,17,0, +0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,8,0,0,4,0,0,0,6,0,0,0, +0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,4,0,0,0,0,9,6,0,0,0,4,0,0,0,0,0,4,10,7,0,7,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0, +0,0,0,0,0,0,6,0,0,0,6,0,6,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,18,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,13,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4, +0,0,0,6,0,0,0,0,0,4,8,0,0,0,11,7,0,0,0,4,0,0,0,0,0,7,0,0,8,5,0,0,16,0,0,0,13,6, +0,0,0,0,0,0,0,6,0,0,0,0,20,0,11,6,0,0,8,7,0,0,0,0,0,6,17,0,8,0,0,0,0,0,8,7,0,0, +9,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0, +0,0,4,0,7,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,8, +0,8,0,0,0,0,0,0,0,11,0,8,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,6,0,0,9,0, +0,0,0,0,8,0,0,0,0,0,18,0,0,0,0,0,0,4,9,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,9,6,0,0,0,0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,8,7,0,0,0,0,0,0,0,0, +0,4,0,0,0,0,0,0,14,0,0,0,0,7,0,6,0,0,8,0,20,7,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,8,0,0,0,14,0,0,0,0,0,0,0,8,0,0,7,0,6,0,0,0,7,0,0,0,0,0,0,0,0, +0,0,0,4,12,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,10,6,0, +5,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0, +0,0,0,5,8,4,0,0,0,0,0,0,0,4,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,12,7,0, +0,0,0,13,6,0,0,0,7,0,0,8,0,0,0,8,0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0,0,11,5, +0,6,0,0,8,5,0,7,0,0,0,0,0,0,0,7,0,0,0,0,8,6,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,4,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +14,0,10,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,19,0,0,4,0,0,0,7, +0,0,11,5,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,16,0,10,5,18,0,0,7,9,6,0,5,0,0,0,0,0, +0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,5,0,0,0,7,0,6,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,4,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,23,0,0,0,0,5,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,14,0,20,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0, +11,0,0,0,0,7,0,0,0,0,15,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,7,0,0,0,0, +0,4,0,0,0,0,10,0,0,0,0,0,9,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,10,0,11,6,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,5,0,0,11,0,0,0,0,7,0,0,0,0,0,0,8,7,0, +4,0,0,0,0,11,0,0,0,0,0,11,0,0,5,0,0,8,7,0,4,0,7,0,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,0,0, +0,0,4,11,5,10,7,0,7,0,0,9,6,9,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,9,4,0,4, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,8,6,0,0,0,0,11,7,0,0,0,0,0,0,0,0,0,0,11,7,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,8,5,0,0,8,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0, +10,7,0,0,0,6,0,0,0,0,0,0,8,0,0,6,0,0,0,6,10,0,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,6,0, +0,0,6,0,0,0,0,9,5,8,5,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0, +0,8,7,10,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,5,0,0,0,6,0,7,0,0, +10,5,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,11,0,0,0,0,0,13,4, +0,0,0,4,0,0,0,0,0,5,8,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,7,14,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,5,0,0,15,6,10,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,14,6,10,0,0,0,0,0,0,0,0,6,0, +0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,6,0,5,11,4,0,6,0,0,0,7,0,0,0,0, +0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,5,0,0,8,5,0,0,0,0,0,0,0,0,0,0, +0,0,10,0,0,0,0,0,9,6,9,4,0,0,0,4,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,5,0, +0,0,0,0,0,0,0,0,0,0,4,0,0,11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0, +0,0,0,7,12,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0, +4,9,6,0,4,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,6,0, +7,8,6,0,0,0,0,0,0,0,4,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,5,0,4,0,0,0,0,0,0,0,5,0,0,0, +0,0,5,0,0,0,7,12,7,0,0,0,0,0,0,18,4,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,6,0,0,0, +0,12,0,0,7,0,0,0,0,0,7,0,0,13,0,0,6,0,0,0,0,8,7,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,7,10,5,0,0,8,0,0,0,0,0,0,0,8,6,0,7,0,0,8,4,0,4,0,0,0,0,10,4,0,0,14,0, +0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,17,0,0,0,0,0,0,6,0,0,0,0,8,6,0,0,10,5,0,0,0,0,8, +6,0,0,0,6,0,0,0,7,0,0,0,0,0,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,12,0,0,0,0,6, +8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, +0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,4,24,0,0, +0,0,0,12,6,0,0,10,6,0,5,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,17,7,0,5,0,0,0, +0,0,0,0,0,0,0,0,0,0,6,11,5,9,0,8,7,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,10,7,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,5,8,7,0,0,0, +0,8,5,0,0,0,0,10,7,0,7,0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0, +0,6,12,0,8,7,0,0,0,0,0,0,0,0,0,0,16,0,10,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,22,0,0,0, +0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,22,0,0,6,0,0,21,0,0,0,22,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +6,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,7,8,0,0,0,0,6,14,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,0,0,0,0,0,0, +0,0,0,0,0,6,0,0,0,0,8,5,0,0,11,7,0,6,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0, +6,0,0,0,5,0,0,0,0,0,0,0,0,0,4,0,0,8,7,0,0,0,0,8,5,11,7,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,8,5,0,0,10,0,0,4,13,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,0,13,6, +0,6,0,7,0,0,8,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,15,0,0,0,10,7,0,0,0,0,0, +7,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,19,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,6,0,5, +0,7,0,0,0,0,0,0,0,0,0,6,0,0,11,4,0,0,0,6,0,0,13,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0, +0,7,0,0,0,0,0,0,11,7,0,0,0,0,0,6,0,0,10,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,11,6, +0,0,0,0,0,0,0,0,10,0,0,0,0,6,0,0,0,0,0,0,8,7,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0, +0,0,0,8,7,0,0,0,0,9,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,10,0, +0,6,0,0,13,0,0,0,0,0,0,0,9,6,0,0,8,6,8,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0, +0,9,7,0,0,0,0,0,0,11,0,0,0,10,7,0,0,0,0,0,0,0,0,9,6,0,0,12,4,0,4,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,6,0,0,0,0,21,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,5,0,0, +9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0, +16,0,0,4,0,0,0,0,0,7,0,0,0,6,0,6,0,0,11,0,0,0,0,5,0,0,0,0,0,0,0,4,8,5,0,0,0,0,0, +0,14,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0, +0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, +0,0,0,0,6,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,14,7,0,0,9,7,0,0,11,0,0,0,0,0,10, +4,11,5,13,6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,5,0,0,0,0,0,4,0,0,9,0,0,0,0, +0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,6,12,5,0,0,0,6,14,0,0,0,0,0,0,0,0,0,0,4,9,4, +0,0,0,0,0,5,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,5,0,0, +0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,11,6,0,0,13,7,0,0,13,6,0,7,0,0,0,0,0,0,8,6,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,10,6,0,4,0,0,12,6,0,0,0,0,0,0,0,0,10,6, +0,0,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,6,0, +0,0,0,0,7,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,0, +0,0,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0, +0,0,0,5,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0, +0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,8,7,0,0,8,5,0,0,0,4,9,5,0,0,0,7,10,6,0,0, +0,0,0,0,9,7,0,0,8,5,8,0,8,4,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0, +0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0, +0,11,7,0,0,0,7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,5,0,0,0,7,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9,7,0,0,0,0,8,5,0,4,0,0,0,0,0,6,0,6,14, +6,0,0,0,0,9,6,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,6,0,0,0,0,14,7,9,7,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,16, +0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,14,0, +0,6,0,0,8,6,0,0,0,0,0,6,0,0,12,0,0,0,0,0,8,5,0,7,11,0,0,5,0,4,0,0,0,6,0,0,0,0,0, +0,0,0,0,0,0,0,9,6,0,4,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,10,5,0,0,0,0, +0,4,0,0,0,7,11,6,0,4,8,5,9,5,0,0,0,5,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,8,5,14,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,16,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9,6,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,9,0,0,0,12,5,0,0,0,0,0,0,0,4,10,5,0,0,0,0,0,0,0,0,0,0,0,6,0, +0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,4,0,0,0,6,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,10,4,0,0,0,0,0,5,0,0,0,4, +0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,0,10,7,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,7,0,0,0,0,0,0,0,0,15,0,0,0, +0,0,0,0,0,0,0,7,0,0,0,0,0,7,10,7,9,7,0,0,0,7,0,0,8,0,0,0,0,0,0,0,9,0,0,0,8,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,8,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,7,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,15,7,12,6,0,0,0,7,0,5,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,5,0,0,0,0, +0,0,0,6,9,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,9,7,0,0,14,0,0,0,11,7,0,0,0,0,0, +0,0,0,0,0,0,4,0,0,11,7,0,0,0,0,8,0,0,0,0,0,0,6,8,7,0,0,0,7,10,4,0,0,0,0,0,0,0,0, +0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,10,0,0,0,0,0,0, +6,0,6,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,11,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,7,0,0,10,7,0,0,0,0,9,7,0,0,0,0,0,0,13,7,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,12,0, +0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,9,6,0,0,11,0,0, +0,0,0,14,4,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,23,7,0,0, +0,0,0,6,0,7,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,20, +7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,8,0,0,0,0,0,0,0,0,0,11,5,0,0,0,0,0,0,0,0,0,0,10,4,0,0,0,5,8,5,10,4,0,0,0,0,0, +0,13,6,9,7,0,0,10,7,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,6,0,0,0,7,0,6,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,10,7,0,0, +0,0,0,0,0,0,0,0,12,4,0,0,0,0,8,7,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0, +0,0,0,0,6,0,6,9,6,0,0,12,5,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0, +0,0,0,0,0,0,0,0,0,5,8,7,9,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,11, +4,0,0,0,0,0,0,8,0,0,0,10,7,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,0, +0,0,0,0,0,5,0,6,0,0,10,0,14,0,0,0,0,0,0,0,23,0,0,0,12,0,10,5,0,0,0,0,0,0,0,0,0, +5,0,0,0,0,8,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,22,0,8,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0, +0,0,0,0,0,6,18,4,0,0,0,7,10,6,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0, +0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,0,0,0,0,0,0,6,0,0,0,0,11,5,0,0,0,0,0,0,0,0, +15,0,8,6,0,0,13,7,0,0,0,0,0,7,0,0,0,0,0,7,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,9,5,9, +0,0,6,8,6,0,0,0,0,10,0,0,0,18,5,0,0,0,5,0,7,0,0,0,0,8,6,0,0,0,0,9,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,14,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,5,0, +0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,8,5,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,0,0,0,0,0,0, +0,0,0,0,20,5,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,0,8,4,24,0,0,0,0,0,0, +0,0,0,0,0,0,0,9,7,0,0,0,0,10,5,0,0,8,5,0,0,0,0,0,0,0,0,12,7,0,6,0,0,10,6,0,0,0, +0,14,0,0,4,9,5,0,0,0,0,0,0,9,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,8,0,0,0,0,0,11,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,8,5,11,7,0,4,0,0,10,0,0,0,0, +0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,11,6,0,0,0,0,0,5,14,6,0,0,0,0,10,0,0, +0,13,4,0,0,0,0,0,0,0,0,0,0,0,6,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,7,12,0,10,6,0,0,0,0,0,0,10,0,0,0,0,0,10,0,9, +7,0,0,0,0,0,0,0,0,0,0,0,0,0,7,8,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,9,7,0,0,0, +0,0,0,0,0,0,0,0,0,24,0,11,7,0,7,0,0,0,0,0,0,8,6,0,0,0,0,0,0,8,7,0,0,0,0,0,5,0,0, +0,6,9,0,0,0,23,5,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,7,0,0,0, +0,0,0,0,0,0,0,0,0,0,6,0,0,18,4,0,0,11,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6, +0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,9,0,0,0,11,0,0,0,23,0,0, +0,10,4,0,0,0,0,0,7,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,7,0,0,19,0,11,0,0,0,0,0,12,7,0, +0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,0,0,0,6,0,0, +9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,4,0,0,0,0,10,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,22,0,8,7,10,4,11,0,13,5,8,7,9,0,8,7,0,0,0,7,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0, +0,8,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,0,0,0,4,11,0,0,6,0,0,8,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,5,0,0, +20,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,7,0,0,14,0,0,0,9,0,13,7,0,0,0,0,0,6,0,7,0,0,8,6,10,6,0,0,8,6,0,0,0,6,0, +0,12,6,9,0,0,0,0,0,0,5,9,0,12,4,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0, +0,0,4,8,0,0,6,8,0,0,0,0,0,0,0,0,0,13,6,0,7,0,0,0,0,0,6,8,7,8,6,0,0,0,7,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,18,0,11,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0, +0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,14, +6,0,0,0,0,12,7,8,0,0,0,0,0,0,0,8,7,0,0,0,0,10,4,0,0,0,0,0,0,10,0,0,6,0,0,0,0,0, +0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,15,6,9,7,0,0,0,0,0,0,15,6,11,7,0,0,0,7,0,0,21,0,0, +0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,17,6,0,0,10,5,0,5,0,0,0,0,0,0,0,0,0,7, +0,0,10,0,0,0,0,0,0,0,0,4,11,5,0,0,0,0,16,7,0,0,0,0,0,6,0,0,8,7,0,4,0,0,10,0,0,0, +0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0, +0,0,0,10,4,0,0,0,0,0,0,0,0,0,6,0,5,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0, +0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,6,10,7,0,0,0,0,0,0,0,0,8,4,0,0,10,0,0,0,0,4,0,6,0,6,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,7,17,0,0,0,0,0, +0,0,0,0,0,0,10,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +6,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,4,0,0,0,0,0,6,0,0,0,0,0,0,10,5,0,0, +0,5,0,0,0,0,9,0,19,7,0,0,0,0,0,7,0,0,0,0,10,6,0,0,0,6,0,5,0,0,0,0,0,0,0,0,0,6,8, +0,0,0,0,0,11,0,0,0,0,0,0,6,0,0,0,0,0,7,9,0,15,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,0,0, +0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0,9,0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,6,0,0, +0,0,0,6,10,0,0,0,0,0,0,0,23,0,14,0,0,0,0,7,0,0,0,0,0,7,0,0,9,0,0,0,0,7,0,0,0,0, +0,6,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0, +0,0,0,0,0,9,5,0,0,0,0,0,4,0,0,0,0,9,5,0,0,0,0,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,10,0,0,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,6,11,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,14,7,0,0,12,7,0,0,0, +0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,8,6,10,0,0,0,0,0,0,0,0,0,10,7,8,5,0,0,0,0,0,0, +0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,5,0,0,9,5,0,0,0,0,0,5,0,0,0,0,0,4,0,0,0, +0,0,0,0,0,0,0,12,4,11,0,0,0,9,0,11,7,0,0,0,0,0,0,10,6,0,0,0,6,0,0,0,0,15,5,0,0, +11,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,4,0,6,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,8,0,0,0,19,7,0,4,0,0,9,0,0,0,0,0,10,0, +0,6,0,0,13,0,12,6,0,0,0,0,0,0,0,0,10,7,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,13,7,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,4,9,0,0,0,10,0,0,0,0,0,0,0, +0,5,0,0,0,0,0,0,10,0,23,6,0,0,0,6,8,0,0,0,0,0,0,0,0,0,17,7,0,0,0,0,11,6,22,5,0, +0,9,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,5,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,4,11,0,9,4,0,0, +0,7,0,7,0,0,0,0,0,0,12,4,0,0,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +4,0,0,11,5,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,6,0,0,0,4,0,0,0,0, +0,0,0,0,0,7,0,0,0,4,0,0,10,4,0,0,0,0,0,0,0,7,0,7,0,0,0,6,0,0,0,0,8,6,0,6,0,6,0, +0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,6,22,6,12,0,0,6,0,0,0,6,0,0,0,0,0,7,0,0,0,0,11,0,0,0, +9,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,6,0,0,0,6,0,6,0,0,8,7,0,0,0,4,9,7,19,0,0,0,0,0,0,0,0,0,9,6,10,6,0,6,0,0,0, +4,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,6,16,7,10,6,0,0,23,6,11,7,0,4,0,0,0,0,0,0,0,0,0, +5,0,0,0,0,10,7,0,0,0,0,0,7,0,0,0,0,0,0,15,0,10,0,0,0,14,6,0,0,0,0,0,0,0,0,0,0,0, +5,0,0,0,0,0,0,0,5,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,5,0,0,11,5,0,0,0,0,0,0,0,0,0,0, +0,4,0,0,0,0,0,6,0,0,10,0,0,0,0,7,0,0,0,0,0,0,10,6,0,0,0,0,8,4,0,0,0,7,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,12,5,0,0,0,0, +0,6,0,0,0,0,9,6,0,0,0,0,0,0,0,6,9,0,0,0,0,6,0,0,0,0,8,7,0,0,0,0,0,0,0,6,0,0,0,0, +0,0,0,0,0,0,10,5,0,0,0,0,0,0,8,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,8,5,0,0,0,0,0,7,0,7,0,4,0,0,10,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,13, +7,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,7,0,0,13,0,0,0,0,0,0,0,0,7,10,5,0,0,0,0,0,0,9,7,0,0,8,6,9, +5,0,0,0,0,0,6,12,0,0,0,0,0,0,0,18,6,0,0,0,0,0,0,0,0,19,7,0,4,0,0,0,0,9,5,0,5,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,7,0,0,0,0,0,0,14,0,0,0,23,7,8,7,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,22,0,0,7,0,0,0,0,0,0,0,0,9,7,8,4,0, +0,0,0,0,0,0,0,8,5,0,6,0,0,0,0,0,6,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0, +8,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,8,6,0,0,11,7,0,0,0, +0,12,0,8,6,19,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,11,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,11,7,0,0,0,0,0,4,10,0,0,0,0,0,0,0,8,7,0,0,0,0,14,0,8,0,0,6,10,0,0, +0,0,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0,0, +0,0,0,0,13,0,0,0,0,0,0,0,11,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0, +0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,5,0,0,0,6,0,0,0,5,0,7,0,0,0, +0,0,6,0,0,21,7,0,0,9,6,0,0,0,6,0,0,13,7,0,0,0,5,0,0,0,0,0,4,0,6,0,0,0,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,11,5,0,6,0,0,10,5,0,0,0,0,0,0,0,0,9,6,0,0,8,7,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,0,0,0,0,0,0,6,0,0,0,0,15,4,0,0,12,7,0,0,0,6, +0,7,0,0,8,0,9,5,0,4,0,0,0,6,0,6,0,0,23,4,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,4,0,0,8, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0,0,0,0,0,0, +7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,12,6,0,0,0,0,0,0,10,7,0,7,0,0,0,0,0,0,0,0,0,0, +9,0,0,0,0,0,8,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,11,5,0,0,0,6,0,6,0,0,0,0,0,0,0,6,0, +4,0,0,0,0,0,0,0,0,0,0,0,5,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,8,7,0,0,0,6,0,6,0, +0,0,0,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,11,0,0,0,0,0,0,0,10,5,9,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,23,7,0,0,0,0,0,7,0,0,10,6,18,0,0,0, +0,0,0,0,8,7,0,6,0,0,0,0,0,0,8,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0, +0,0,0,0,0,6,0,0,0,4,12,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,13,5,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0, +11,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0, +0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,0,11,0,0,0,0,0,0,0,0,0, +17,5,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0,8,7,0,0,0,0,0,0,0, +0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0, +10,0,0,0,8,6,0,0,0,7,0,0,0,0,0,0,8,0,0,0,14,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,9,4,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0, +10,0,0,0,16,5,0,0,0,0,0,0,8,0,0,4,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,10,0,0,0, +0,0,0,0,0,5,0,0,0,0,12,5,0,7,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0, +0,0,0,0,0,0,0,12,6,0,0,0,0,0,7,0,6,0,6,12,6,0,0,0,0,0,0,0,4,8,7,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,10,6,8,0,0, +6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +16,0,8,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,23,5,0,0,0,7,0,6,0, +0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,14,0,0,0,0,7,0,0,0,4,17,5,0,0,0,0,11,0,9,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,0,5,0,7,0,0,0,0,0,0,0,0,8,0,0,0, +12,6,0,0,0,0,0,0,13,0,0,0,0,7,9,0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,10,7,12,0,0,0,9,0, +0,0,14,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,15,6,0,0,23,0,0,7,0,6,0,0,0,7,0,6, +0,0,0,0,0,0,0,6,0,6,9,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,8,7,9,4,0,0,10,0,0,0,10, +6,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,23,0,0,6,0,0,0,0,0,0,9,4, +0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,9,6,0,0,0,0,8,6,0,0,0,0,0,0,0,0,12,0,0, +0,0,0,8,0,0,6,11,6,0,0,8,7,8,5,0,0,0,0,0,5,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0, +10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0, +7,0,0,0,0,9,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,8,0,0,0,0,6,12,5,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,10,0,10, +7,0,0,8,0,0,0,0,4,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0, +0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,6,0,5,0,0,0,0,8,0,0,0,10,7,0,0,0,0,10,0,0,0, +0,0,13,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,19,7,0,4,12,0,8,0,0,0,0,6,0,0,0,0, +0,0,0,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,18,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0, +0,14,0,0,4,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,0,0,0,10,4,0,0,9,7,0,0,11,0,0,0,0,0,0, +7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,12,0,0,0, +0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,22,5,9,7,0,0,0,0,0,0,0,0,0, +0,0,6,0,0,9,6,0,5,0,0,0,0,0,0,10,5,0,0,8,6,0,6,10,5,0,0,0,6,0,0,0,6,0,0,20,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,0,17,4,0,7,0,6, +0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10, +0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0, +0,0,7,0,0,8,6,12,0,0,7,18,7,0,0,8,4,0,0,0,0,9,6,0,0,0,0,0,0,0,0,13,0,0,6,0,0,0, +0,0,0,0,0,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0, +0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,12,0,0,0,8,0,0,0,0,0,0, +4,0,0,10,0,16,0,0,0,0,0,0,0,12,7,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,16,6,10,0,0,5,0,0,0,0,0,6,0,0,0,0, +0,7,0,0,0,7,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,5,8,7,0,7,0,0,0,0,0,0,0,0,8,0,0,6,0,0,0,6,0,0,0,4,0,0,0,0, +8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,8,0,0,0, +9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,13,5,0,5,0,0,0,7,8,4,0,0,0,0,0,0,0, +0,12,0,0,0,0,0,0,0,0,0,0,0,8,6,0,6,0,0,11,0,0,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0, +0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,11,6,0,0,10,6,0,0, +0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6, +0,0,0,6,0,0,0,7,0,0,9,0,8,7,11,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,9,6,10,5,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,10,7,0,0,0,0,0,0,11,0,9,6,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,15,5,12,5, +0,0,0,0,0,0,12,7,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,12,6,0, +0,0,0,24,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0, +0,0,0,4,10,4,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,11,0,0,0,0,0,0,0,0,0,0,6, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5, +0,0,8,0,0,0,0,7,0,0,0,0,0,0,10,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0, +0,0,0,0,0,14,7,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0,0,6,0,0,0,6,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,7,20,7,11,4,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,7,9,6,0,0,12,7,0,0,0,0,0,0,10,0,12,0, +0,0,0,0,0,4,9,6,13,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,5,0,0,0,0,0,0,8,0,0,0,0,0,0, +0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,11,0,9,0,0,0,0,4,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,5,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, +0,4,0,5,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,7,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0, +0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6, +0,0,0,0,8,7,0,0,0,0,0,0,12,0,0,6,0,0,0,0,0,0,0,6,8,4,0,0,10,7,0,0,10,0,0,0,0,0, +0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,5, +0,4,0,0,0,0,0,6,0,0,0,0,0,0,8,0,0,6,0,0,0,6,0,0,0,0,0,7,0,5,8,4,0,0,9,0,0,0,0,4, +0,0,0,0,0,0,0,0,0,5,0,0,15,6,8,6,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,6,0,0,0,0,0,0,0,7,0,0,0,4,0, +6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,9,5,0,6,12,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,12,7,0,0,0,0, +0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,0,10, +7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,7,8,7,9,6,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,5,12,0, +10,5,12,6,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,5,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7, +11,7,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,6,0,7,0,0,0,0,8,0,8,5,0,6,0,0,0,6,0,0,0, +0,0,0,0,6,0,6,0,6,9,0,0,5,17,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,7,0,0, +0,0,0,7,0,0,0,0,16,5,0,0,0,0,0,0,0,4,0,0,0,5,11,5,0,7,0,0,0,4,8,7,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,12,0,0,0, +0,0,12,0,0,0,0,0,0,0,0,4,10,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,20,5,0,0, +10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,12,0,0,0,0,0,0,6,0,0,0,0,0,0,9,4,10,7,0,4,0,0, +0,0,0,0,10,6,0,0,0,0,8,4,0,7,8,6,0,6,8,0,10,0,0,0,0,0,13,5,0,6,0,0,0,0,0,0,22,4, +0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,10, +5,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,10,4,0,0,10,7,0,0,0,0,0,5,0, +5,8,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,4,0,0,0,0,0,6,0,0, +0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0, +4,0,0,0,4,10,0,0,6,13,7,8,0,0,0,0,0,0,7,0,0,12,7,0,0,0,0,0,0,10,5,0,0,0,0,0,6,0, +0,0,0,0,0,0,0,0,0,13,7,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,6,0,6, +0,0,0,0,0,0,0,0,12,0,8,4,0,0,0,0,0,4,0,4,0,0,0,0,0,0,0,5,0,0,0,0,12,5,0,0,0,7,0, +0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,10,0,0,0,20,0,0,5,0,0,10, +7,11,7,0,0,0,0,0,0,0,0,0,0,17,0,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,10,7,0,4,0,6,0,0,24,0,0,5,0,0,0,0,8,0,0, +0,0,0,0,0,10,5,0,4,0,6,0,0,8,0,0,0,0,0,0,4,0,6,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0, +0,0,0,6,0,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0,7, +0,0,13,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0, +17,7,0,0,11,6,0,0,0,0,12,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,10,0,0,4,8,6,0,0,0, +0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,9,5,0,7,18,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,8,0,0,0, +0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0, +0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,6,0,0,9,0,0,0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,0, +0,0,0,8,7,10,0,8,5,0,0,0,0,0,0,0,0,9,0,0,0,10,0,0,0,0,6,0,7,0,4,0,0,0,0,0,0,0,0, +8,0,0,0,0,0,8,4,0,0,0,0,0,5,0,0,10,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,11,0,0, +7,0,0,0,0,0,6,10,5,0,0,0,0,0,0,0,0,0,5,0,0,9,5,12,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,6,0,0,0,0,13,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0, +0,0,0,8,4,0,6,12,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,11,4,0,0,0,6,14,0,11,0,9,6,0,0,0,0,0,0,22,0,12,0,8,6,0,0,0,0,0,0,0,6,0, +0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0, +10,7,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,11,0,0,0,0,0,0,0,8,6,0,0,9, +7,0,0,12,4,0,0,0,0,0,0,12,6,0,6,0,7,0,0,8,5,0,0,0,0}; +/* GENERATED CODE END */ + + diff --git a/third_party/brotli/enc/dictionary_hash.h b/third_party/brotli/enc/dictionary_hash.h new file mode 100644 index 00000000000..28cfdef9477 --- /dev/null +++ b/third_party/brotli/enc/dictionary_hash.h @@ -0,0 +1,21 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Hash table on the 4-byte prefixes of static dictionary words. */ + +#ifndef BROTLI_ENC_DICTIONARY_HASH_H_ +#define BROTLI_ENC_DICTIONARY_HASH_H_ + +#include + +namespace duckdb_brotli { + +extern const uint16_t kStaticDictionaryHashWords[32768]; +extern const uint8_t kStaticDictionaryHashLengths[32768]; + +} + +#endif /* BROTLI_ENC_DICTIONARY_HASH_H_ */ diff --git a/third_party/brotli/enc/encode.cpp b/third_party/brotli/enc/encode.cpp new file mode 100644 index 00000000000..9d1af50cbbf --- /dev/null +++ b/third_party/brotli/enc/encode.cpp @@ -0,0 +1,1990 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Implementation of Brotli compressor. */ + +#include +#include +#include + +#include /* free, malloc */ +#include /* memcpy, memset */ + +#include "../common/brotli_constants.h" +#include "../common/context.h" +#include "../common/brotli_platform.h" +#include "../common/version.h" +#include "backward_references.h" +#include "backward_references_hq.h" +#include "bit_cost.h" +#include "brotli_bit_stream.h" +#include "compress_fragment.h" +#include "compress_fragment_two_pass.h" +#include "dictionary_hash.h" +#include "encoder_dict.h" +#include "entropy_encode.h" +#include "fast_log.h" +#include "brotli_hash.h" +#include "histogram.h" +#include "memory.h" +#include "metablock.h" +#include "prefix.h" +#include "state.h" +#include "quality.h" +#include "ringbuffer.h" +#include "utf8_util.h" +#include "write_bits.h" + +using namespace duckdb_brotli; + +#define COPY_ARRAY(dst, src) memcpy(dst, src, sizeof(src)); + +static size_t InputBlockSize(BrotliEncoderState* s) { + return (size_t)1 << s->params.lgblock; +} + +static uint64_t UnprocessedInputSize(BrotliEncoderState* s) { + return s->input_pos_ - s->last_processed_pos_; +} + +static size_t RemainingInputBlockSize(BrotliEncoderState* s) { + const uint64_t delta = UnprocessedInputSize(s); + size_t block_size = InputBlockSize(s); + if (delta >= block_size) return 0; + return block_size - (size_t)delta; +} + +BROTLI_BOOL duckdb_brotli::BrotliEncoderSetParameter( + BrotliEncoderState* state, BrotliEncoderParameter p, uint32_t value) { + /* Changing parameters on the fly is not implemented yet. */ + if (state->is_initialized_) return BROTLI_FALSE; + /* TODO(eustas): Validate/clamp parameters here. */ + switch (p) { + case BROTLI_PARAM_MODE: + state->params.mode = (BrotliEncoderMode)value; + return BROTLI_TRUE; + + case BROTLI_PARAM_QUALITY: + state->params.quality = (int)value; + return BROTLI_TRUE; + + case BROTLI_PARAM_LGWIN: + state->params.lgwin = (int)value; + return BROTLI_TRUE; + + case BROTLI_PARAM_LGBLOCK: + state->params.lgblock = (int)value; + return BROTLI_TRUE; + + case BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: + if ((value != 0) && (value != 1)) return BROTLI_FALSE; + state->params.disable_literal_context_modeling = TO_BROTLI_BOOL(!!value); + return BROTLI_TRUE; + + case BROTLI_PARAM_SIZE_HINT: + state->params.size_hint = value; + return BROTLI_TRUE; + + case BROTLI_PARAM_LARGE_WINDOW: + state->params.large_window = TO_BROTLI_BOOL(!!value); + return BROTLI_TRUE; + + case BROTLI_PARAM_NPOSTFIX: + state->params.dist.distance_postfix_bits = value; + return BROTLI_TRUE; + + case BROTLI_PARAM_NDIRECT: + state->params.dist.num_direct_distance_codes = value; + return BROTLI_TRUE; + + case BROTLI_PARAM_STREAM_OFFSET: + if (value > (1u << 30)) return BROTLI_FALSE; + state->params.stream_offset = value; + return BROTLI_TRUE; + + default: return BROTLI_FALSE; + } +} + +/* Wraps 64-bit input position to 32-bit ring-buffer position preserving + "not-a-first-lap" feature. */ +static uint32_t WrapPosition(uint64_t position) { + uint32_t result = (uint32_t)position; + uint64_t gb = position >> 30; + if (gb > 2) { + /* Wrap every 2GiB; The first 3GB are continuous. */ + result = (result & ((1u << 30) - 1)) | ((uint32_t)((gb - 1) & 1) + 1) << 30; + } + return result; +} + +static uint8_t* GetBrotliStorage(BrotliEncoderState* s, size_t size) { + MemoryManager* m = &s->memory_manager_; + if (s->storage_size_ < size) { + BROTLI_FREE(m, s->storage_); + s->storage_ = BROTLI_ALLOC(m, uint8_t, size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->storage_)) return NULL; + s->storage_size_ = size; + } + return s->storage_; +} + +static size_t HashTableSize(size_t max_table_size, size_t input_size) { + size_t htsize = 256; + while (htsize < max_table_size && htsize < input_size) { + htsize <<= 1; + } + return htsize; +} + +static int* GetHashTable(BrotliEncoderState* s, int quality, + size_t input_size, size_t* table_size) { + /* Use smaller hash table when input.size() is smaller, since we + fill the table, incurring O(hash table size) overhead for + compression, and if the input is short, we won't need that + many hash table entries anyway. */ + MemoryManager* m = &s->memory_manager_; + const size_t max_table_size = MaxHashTableSize(quality); + size_t htsize = HashTableSize(max_table_size, input_size); + int* table; + BROTLI_DCHECK(max_table_size >= 256); + if (quality == FAST_ONE_PASS_COMPRESSION_QUALITY) { + /* Only odd shifts are supported by fast-one-pass. */ + if ((htsize & 0xAAAAA) == 0) { + htsize <<= 1; + } + } + + if (htsize <= sizeof(s->small_table_) / sizeof(s->small_table_[0])) { + table = s->small_table_; + } else { + if (htsize > s->large_table_size_) { + s->large_table_size_ = htsize; + BROTLI_FREE(m, s->large_table_); + s->large_table_ = BROTLI_ALLOC(m, int, htsize); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->large_table_)) return 0; + } + table = s->large_table_; + } + + *table_size = htsize; + memset(table, 0, htsize * sizeof(*table)); + return table; +} + +static void EncodeWindowBits(int lgwin, BROTLI_BOOL large_window, + uint16_t* last_bytes, uint8_t* last_bytes_bits) { + if (large_window) { + *last_bytes = (uint16_t)(((lgwin & 0x3F) << 8) | 0x11); + *last_bytes_bits = 14; + } else { + if (lgwin == 16) { + *last_bytes = 0; + *last_bytes_bits = 1; + } else if (lgwin == 17) { + *last_bytes = 1; + *last_bytes_bits = 7; + } else if (lgwin > 17) { + *last_bytes = (uint16_t)(((lgwin - 17) << 1) | 0x01); + *last_bytes_bits = 4; + } else { + *last_bytes = (uint16_t)(((lgwin - 8) << 4) | 0x01); + *last_bytes_bits = 7; + } + } +} + +/* TODO(eustas): move to compress_fragment.c? */ +/* Initializes the command and distance prefix codes for the first block. */ +static void InitCommandPrefixCodes(BrotliOnePassArena* s) { + static const uint8_t kDefaultCommandDepths[128] = { + 0, 4, 4, 5, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 0, 0, 0, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, + 7, 7, 10, 10, 10, 10, 10, 10, 0, 4, 4, 5, 5, 5, 6, 6, + 7, 8, 8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 10, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + }; + static const uint16_t kDefaultCommandBits[128] = { + 0, 0, 8, 9, 3, 35, 7, 71, + 39, 103, 23, 47, 175, 111, 239, 31, + 0, 0, 0, 4, 12, 2, 10, 6, + 13, 29, 11, 43, 27, 59, 87, 55, + 15, 79, 319, 831, 191, 703, 447, 959, + 0, 14, 1, 25, 5, 21, 19, 51, + 119, 159, 95, 223, 479, 991, 63, 575, + 127, 639, 383, 895, 255, 767, 511, 1023, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 27, 59, 7, 39, 23, 55, 30, 1, 17, 9, 25, 5, 0, 8, 4, 12, + 2, 10, 6, 21, 13, 29, 3, 19, 11, 15, 47, 31, 95, 63, 127, 255, + 767, 2815, 1791, 3839, 511, 2559, 1535, 3583, 1023, 3071, 2047, 4095, + }; + static const uint8_t kDefaultCommandCode[] = { + 0xff, 0x77, 0xd5, 0xbf, 0xe7, 0xde, 0xea, 0x9e, 0x51, 0x5d, 0xde, 0xc6, + 0x70, 0x57, 0xbc, 0x58, 0x58, 0x58, 0xd8, 0xd8, 0x58, 0xd5, 0xcb, 0x8c, + 0xea, 0xe0, 0xc3, 0x87, 0x1f, 0x83, 0xc1, 0x60, 0x1c, 0x67, 0xb2, 0xaa, + 0x06, 0x83, 0xc1, 0x60, 0x30, 0x18, 0xcc, 0xa1, 0xce, 0x88, 0x54, 0x94, + 0x46, 0xe1, 0xb0, 0xd0, 0x4e, 0xb2, 0xf7, 0x04, 0x00, + }; + static const size_t kDefaultCommandCodeNumBits = 448; + COPY_ARRAY(s->cmd_depth, kDefaultCommandDepths); + COPY_ARRAY(s->cmd_bits, kDefaultCommandBits); + + /* Initialize the pre-compressed form of the command and distance prefix + codes. */ + COPY_ARRAY(s->cmd_code, kDefaultCommandCode); + s->cmd_code_numbits = kDefaultCommandCodeNumBits; +} + +/* Decide about the context map based on the ability of the prediction + ability of the previous byte UTF8-prefix on the next byte. The + prediction ability is calculated as Shannon entropy. Here we need + Shannon entropy instead of 'BitsEntropy' since the prefix will be + encoded with the remaining 6 bits of the following byte, and + BitsEntropy will assume that symbol to be stored alone using Huffman + coding. */ +static void ChooseContextMap(int quality, + uint32_t* bigram_histo, + size_t* num_literal_contexts, + const uint32_t** literal_context_map) { + static const uint32_t kStaticContextMapContinuation[64] = { + 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + static const uint32_t kStaticContextMapSimpleUTF8[64] = { + 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + uint32_t monogram_histo[3] = { 0 }; + uint32_t two_prefix_histo[6] = { 0 }; + size_t total; + size_t i; + size_t dummy; + double entropy[4]; + for (i = 0; i < 9; ++i) { + monogram_histo[i % 3] += bigram_histo[i]; + two_prefix_histo[i % 6] += bigram_histo[i]; + } + entropy[1] = ShannonEntropy(monogram_histo, 3, &dummy); + entropy[2] = (ShannonEntropy(two_prefix_histo, 3, &dummy) + + ShannonEntropy(two_prefix_histo + 3, 3, &dummy)); + entropy[3] = 0; + for (i = 0; i < 3; ++i) { + entropy[3] += ShannonEntropy(bigram_histo + 3 * i, 3, &dummy); + } + + total = monogram_histo[0] + monogram_histo[1] + monogram_histo[2]; + BROTLI_DCHECK(total != 0); + entropy[0] = 1.0 / (double)total; + entropy[1] *= entropy[0]; + entropy[2] *= entropy[0]; + entropy[3] *= entropy[0]; + + if (quality < MIN_QUALITY_FOR_HQ_CONTEXT_MODELING) { + /* 3 context models is a bit slower, don't use it at lower qualities. */ + entropy[3] = entropy[1] * 10; + } + /* If expected savings by symbol are less than 0.2 bits, skip the + context modeling -- in exchange for faster decoding speed. */ + if (entropy[1] - entropy[2] < 0.2 && + entropy[1] - entropy[3] < 0.2) { + *num_literal_contexts = 1; + } else if (entropy[2] - entropy[3] < 0.02) { + *num_literal_contexts = 2; + *literal_context_map = kStaticContextMapSimpleUTF8; + } else { + *num_literal_contexts = 3; + *literal_context_map = kStaticContextMapContinuation; + } +} + +/* Decide if we want to use a more complex static context map containing 13 + context values, based on the entropy reduction of histograms over the + first 5 bits of literals. */ +static BROTLI_BOOL ShouldUseComplexStaticContextMap(const uint8_t* input, + size_t start_pos, size_t length, size_t mask, int quality, size_t size_hint, + size_t* num_literal_contexts, const uint32_t** literal_context_map, + uint32_t* arena) { + static const uint32_t kStaticContextMapComplexUTF8[64] = { + 11, 11, 12, 12, /* 0 special */ + 0, 0, 0, 0, /* 4 lf */ + 1, 1, 9, 9, /* 8 space */ + 2, 2, 2, 2, /* !, first after space/lf and after something else. */ + 1, 1, 1, 1, /* " */ + 8, 3, 3, 3, /* % */ + 1, 1, 1, 1, /* ({[ */ + 2, 2, 2, 2, /* }]) */ + 8, 4, 4, 4, /* :; */ + 8, 7, 4, 4, /* . */ + 8, 0, 0, 0, /* > */ + 3, 3, 3, 3, /* [0..9] */ + 5, 5, 10, 5, /* [A-Z] */ + 5, 5, 10, 5, + 6, 6, 6, 6, /* [a-z] */ + 6, 6, 6, 6, + }; + BROTLI_UNUSED(quality); + /* Try the more complex static context map only for long data. */ + if (size_hint < (1 << 20)) { + return BROTLI_FALSE; + } else { + const size_t end_pos = start_pos + length; + /* To make entropy calculations faster, we collect histograms + over the 5 most significant bits of literals. One histogram + without context and 13 additional histograms for each context value. */ + uint32_t* BROTLI_RESTRICT const combined_histo = arena; + uint32_t* BROTLI_RESTRICT const context_histo = arena + 32; + uint32_t total = 0; + double entropy[3]; + size_t dummy; + size_t i; + ContextLut utf8_lut = BROTLI_CONTEXT_LUT(CONTEXT_UTF8); + memset(arena, 0, sizeof(arena[0]) * 32 * 14); + for (; start_pos + 64 <= end_pos; start_pos += 4096) { + const size_t stride_end_pos = start_pos + 64; + uint8_t prev2 = input[start_pos & mask]; + uint8_t prev1 = input[(start_pos + 1) & mask]; + size_t pos; + /* To make the analysis of the data faster we only examine 64 byte long + strides at every 4kB intervals. */ + for (pos = start_pos + 2; pos < stride_end_pos; ++pos) { + const uint8_t literal = input[pos & mask]; + const uint8_t context = (uint8_t)kStaticContextMapComplexUTF8[ + BROTLI_CONTEXT(prev1, prev2, utf8_lut)]; + ++total; + ++combined_histo[literal >> 3]; + ++context_histo[(context << 5) + (literal >> 3)]; + prev2 = prev1; + prev1 = literal; + } + } + entropy[1] = ShannonEntropy(combined_histo, 32, &dummy); + entropy[2] = 0; + for (i = 0; i < 13; ++i) { + entropy[2] += ShannonEntropy(context_histo + (i << 5), 32, &dummy); + } + entropy[0] = 1.0 / (double)total; + entropy[1] *= entropy[0]; + entropy[2] *= entropy[0]; + /* The triggering heuristics below were tuned by compressing the individual + files of the silesia corpus. If we skip this kind of context modeling + for not very well compressible input (i.e. entropy using context modeling + is 60% of maximal entropy) or if expected savings by symbol are less + than 0.2 bits, then in every case when it triggers, the final compression + ratio is improved. Note however that this heuristics might be too strict + for some cases and could be tuned further. */ + if (entropy[2] > 3.0 || entropy[1] - entropy[2] < 0.2) { + return BROTLI_FALSE; + } else { + *num_literal_contexts = 13; + *literal_context_map = kStaticContextMapComplexUTF8; + return BROTLI_TRUE; + } + } +} + +static void DecideOverLiteralContextModeling(const uint8_t* input, + size_t start_pos, size_t length, size_t mask, int quality, size_t size_hint, + size_t* num_literal_contexts, const uint32_t** literal_context_map, + uint32_t* arena) { + if (quality < MIN_QUALITY_FOR_CONTEXT_MODELING || length < 64) { + return; + } else if (ShouldUseComplexStaticContextMap( + input, start_pos, length, mask, quality, size_hint, + num_literal_contexts, literal_context_map, arena)) { + /* Context map was already set, nothing else to do. */ + } else { + /* Gather bi-gram data of the UTF8 byte prefixes. To make the analysis of + UTF8 data faster we only examine 64 byte long strides at every 4kB + intervals. */ + const size_t end_pos = start_pos + length; + uint32_t* BROTLI_RESTRICT const bigram_prefix_histo = arena; + memset(bigram_prefix_histo, 0, sizeof(arena[0]) * 9); + for (; start_pos + 64 <= end_pos; start_pos += 4096) { + static const int lut[4] = { 0, 0, 1, 2 }; + const size_t stride_end_pos = start_pos + 64; + int prev = lut[input[start_pos & mask] >> 6] * 3; + size_t pos; + for (pos = start_pos + 1; pos < stride_end_pos; ++pos) { + const uint8_t literal = input[pos & mask]; + ++bigram_prefix_histo[prev + lut[literal >> 6]]; + prev = lut[literal >> 6] * 3; + } + } + ChooseContextMap(quality, &bigram_prefix_histo[0], num_literal_contexts, + literal_context_map); + } +} + +static BROTLI_BOOL ShouldCompress( + const uint8_t* data, const size_t mask, const uint64_t last_flush_pos, + const size_t bytes, const size_t num_literals, const size_t num_commands) { + /* TODO(eustas): find more precise minimal block overhead. */ + if (bytes <= 2) return BROTLI_FALSE; + if (num_commands < (bytes >> 8) + 2) { + if ((double)num_literals > 0.99 * (double)bytes) { + uint32_t literal_histo[256] = { 0 }; + static const uint32_t kSampleRate = 13; + static const double kMinEntropy = 7.92; + const double bit_cost_threshold = + (double)bytes * kMinEntropy / kSampleRate; + size_t t = (bytes + kSampleRate - 1) / kSampleRate; + uint32_t pos = (uint32_t)last_flush_pos; + size_t i; + for (i = 0; i < t; i++) { + ++literal_histo[data[pos & mask]]; + pos += kSampleRate; + } + if (BitsEntropy(literal_histo, 256) > bit_cost_threshold) { + return BROTLI_FALSE; + } + } + } + return BROTLI_TRUE; +} + +/* Chooses the literal context mode for a metablock */ +static ContextType ChooseContextMode(const BrotliEncoderParams* params, + const uint8_t* data, const size_t pos, const size_t mask, + const size_t length) { + /* We only do the computation for the option of something else than + CONTEXT_UTF8 for the highest qualities */ + if (params->quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING && + !BrotliIsMostlyUTF8(data, pos, mask, length, kMinUTF8Ratio)) { + return CONTEXT_SIGNED; + } + return CONTEXT_UTF8; +} + +static void WriteMetaBlockInternal(MemoryManager* m, + const uint8_t* data, + const size_t mask, + const uint64_t last_flush_pos, + const size_t bytes, + const BROTLI_BOOL is_last, + ContextType literal_context_mode, + const BrotliEncoderParams* params, + const uint8_t prev_byte, + const uint8_t prev_byte2, + const size_t num_literals, + const size_t num_commands, + Command* commands, + const int* saved_dist_cache, + int* dist_cache, + size_t* storage_ix, + uint8_t* storage) { + const uint32_t wrapped_last_flush_pos = WrapPosition(last_flush_pos); + uint16_t last_bytes; + uint8_t last_bytes_bits; + ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode); + BrotliEncoderParams block_params = *params; + + if (bytes == 0) { + /* Write the ISLAST and ISEMPTY bits. */ + BrotliWriteBits(2, 3, storage_ix, storage); + *storage_ix = (*storage_ix + 7u) & ~7u; + return; + } + + if (!ShouldCompress(data, mask, last_flush_pos, bytes, + num_literals, num_commands)) { + /* Restore the distance cache, as its last update by + CreateBackwardReferences is now unused. */ + memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0])); + BrotliStoreUncompressedMetaBlock(is_last, data, + wrapped_last_flush_pos, mask, bytes, + storage_ix, storage); + return; + } + + BROTLI_DCHECK(*storage_ix <= 14); + last_bytes = (uint16_t)((storage[1] << 8) | storage[0]); + last_bytes_bits = (uint8_t)(*storage_ix); + if (params->quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) { + BrotliStoreMetaBlockFast(m, data, wrapped_last_flush_pos, + bytes, mask, is_last, params, + commands, num_commands, + storage_ix, storage); + if (BROTLI_IS_OOM(m)) return; + } else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) { + BrotliStoreMetaBlockTrivial(m, data, wrapped_last_flush_pos, + bytes, mask, is_last, params, + commands, num_commands, + storage_ix, storage); + if (BROTLI_IS_OOM(m)) return; + } else { + MetaBlockSplit mb; + InitMetaBlockSplit(&mb); + if (params->quality < MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) { + size_t num_literal_contexts = 1; + const uint32_t* literal_context_map = NULL; + if (!params->disable_literal_context_modeling) { + /* TODO(eustas): pull to higher level and reuse. */ + uint32_t* arena = BROTLI_ALLOC(m, uint32_t, 14 * 32); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return; + DecideOverLiteralContextModeling( + data, wrapped_last_flush_pos, bytes, mask, params->quality, + params->size_hint, &num_literal_contexts, + &literal_context_map, arena); + BROTLI_FREE(m, arena); + } + BrotliBuildMetaBlockGreedy(m, data, wrapped_last_flush_pos, mask, + prev_byte, prev_byte2, literal_context_lut, num_literal_contexts, + literal_context_map, commands, num_commands, &mb); + if (BROTLI_IS_OOM(m)) return; + } else { + BrotliBuildMetaBlock(m, data, wrapped_last_flush_pos, mask, &block_params, + prev_byte, prev_byte2, + commands, num_commands, + literal_context_mode, + &mb); + if (BROTLI_IS_OOM(m)) return; + } + if (params->quality >= MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS) { + /* The number of distance symbols effectively used for distance + histograms. It might be less than distance alphabet size + for "Large Window Brotli" (32-bit). */ + BrotliOptimizeHistograms(block_params.dist.alphabet_size_limit, &mb); + } + BrotliStoreMetaBlock(m, data, wrapped_last_flush_pos, bytes, mask, + prev_byte, prev_byte2, + is_last, + &block_params, + literal_context_mode, + commands, num_commands, + &mb, + storage_ix, storage); + if (BROTLI_IS_OOM(m)) return; + DestroyMetaBlockSplit(m, &mb); + } + if (bytes + 4 < (*storage_ix >> 3)) { + /* Restore the distance cache and last byte. */ + memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0])); + storage[0] = (uint8_t)last_bytes; + storage[1] = (uint8_t)(last_bytes >> 8); + *storage_ix = last_bytes_bits; + BrotliStoreUncompressedMetaBlock(is_last, data, + wrapped_last_flush_pos, mask, + bytes, storage_ix, storage); + } +} + +static void ChooseDistanceParams(BrotliEncoderParams* params) { + uint32_t distance_postfix_bits = 0; + uint32_t num_direct_distance_codes = 0; + + if (params->quality >= MIN_QUALITY_FOR_NONZERO_DISTANCE_PARAMS) { + uint32_t ndirect_msb; + if (params->mode == BROTLI_MODE_FONT) { + distance_postfix_bits = 1; + num_direct_distance_codes = 12; + } else { + distance_postfix_bits = params->dist.distance_postfix_bits; + num_direct_distance_codes = params->dist.num_direct_distance_codes; + } + ndirect_msb = (num_direct_distance_codes >> distance_postfix_bits) & 0x0F; + if (distance_postfix_bits > BROTLI_MAX_NPOSTFIX || + num_direct_distance_codes > BROTLI_MAX_NDIRECT || + (ndirect_msb << distance_postfix_bits) != num_direct_distance_codes) { + distance_postfix_bits = 0; + num_direct_distance_codes = 0; + } + } + + BrotliInitDistanceParams(¶ms->dist, distance_postfix_bits, + num_direct_distance_codes, params->large_window); +} + +static BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s) { + MemoryManager* m = &s->memory_manager_; + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + if (s->is_initialized_) return BROTLI_TRUE; + + s->last_bytes_bits_ = 0; + s->last_bytes_ = 0; + s->flint_ = BROTLI_FLINT_DONE; + s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX; + + SanitizeParams(&s->params); + s->params.lgblock = ComputeLgBlock(&s->params); + ChooseDistanceParams(&s->params); + + if (s->params.stream_offset != 0) { + s->flint_ = BROTLI_FLINT_NEEDS_2_BYTES; + /* Poison the distance cache. -16 +- 3 is still less than zero (invalid). */ + s->dist_cache_[0] = -16; + s->dist_cache_[1] = -16; + s->dist_cache_[2] = -16; + s->dist_cache_[3] = -16; + memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_)); + } + + RingBufferSetup(&s->params, &s->ringbuffer_); + + /* Initialize last byte with stream header. */ + { + int lgwin = s->params.lgwin; + if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY || + s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { + lgwin = BROTLI_MAX(int, lgwin, 18); + } + if (s->params.stream_offset == 0) { + EncodeWindowBits(lgwin, s->params.large_window, + &s->last_bytes_, &s->last_bytes_bits_); + } else { + /* Bigger values have the same effect, but could cause overflows. */ + s->params.stream_offset = BROTLI_MIN(size_t, + s->params.stream_offset, BROTLI_MAX_BACKWARD_LIMIT(lgwin)); + } + } + + if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) { + s->one_pass_arena_ = BROTLI_ALLOC(m, BrotliOnePassArena, 1); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + InitCommandPrefixCodes(s->one_pass_arena_); + } else if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { + s->two_pass_arena_ = BROTLI_ALLOC(m, BrotliTwoPassArena, 1); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + } + + s->is_initialized_ = BROTLI_TRUE; + return BROTLI_TRUE; +} + +static void BrotliEncoderInitParams(BrotliEncoderParams* params) { + params->mode = BROTLI_DEFAULT_MODE; + params->large_window = BROTLI_FALSE; + params->quality = BROTLI_DEFAULT_QUALITY; + params->lgwin = BROTLI_DEFAULT_WINDOW; + params->lgblock = 0; + params->stream_offset = 0; + params->size_hint = 0; + params->disable_literal_context_modeling = BROTLI_FALSE; + BrotliInitSharedEncoderDictionary(¶ms->dictionary); + params->dist.distance_postfix_bits = 0; + params->dist.num_direct_distance_codes = 0; + params->dist.alphabet_size_max = + BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_MAX_DISTANCE_BITS); + params->dist.alphabet_size_limit = params->dist.alphabet_size_max; + params->dist.max_distance = BROTLI_MAX_DISTANCE; +} + +static void BrotliEncoderCleanupParams(MemoryManager* m, + BrotliEncoderParams* params) { + BrotliCleanupSharedEncoderDictionary(m, ¶ms->dictionary); +} + +static void BrotliEncoderInitState(BrotliEncoderState* s) { + BrotliEncoderInitParams(&s->params); + s->input_pos_ = 0; + s->num_commands_ = 0; + s->num_literals_ = 0; + s->last_insert_len_ = 0; + s->last_flush_pos_ = 0; + s->last_processed_pos_ = 0; + s->prev_byte_ = 0; + s->prev_byte2_ = 0; + s->storage_size_ = 0; + s->storage_ = 0; + HasherInit(&s->hasher_); + s->large_table_ = NULL; + s->large_table_size_ = 0; + s->one_pass_arena_ = NULL; + s->two_pass_arena_ = NULL; + s->command_buf_ = NULL; + s->literal_buf_ = NULL; + s->total_in_ = 0; + s->next_out_ = NULL; + s->available_out_ = 0; + s->total_out_ = 0; + s->stream_state_ = BROTLI_STREAM_PROCESSING; + s->is_last_block_emitted_ = BROTLI_FALSE; + s->is_initialized_ = BROTLI_FALSE; + + RingBufferInit(&s->ringbuffer_); + + s->commands_ = 0; + s->cmd_alloc_size_ = 0; + + /* Initialize distance cache. */ + s->dist_cache_[0] = 4; + s->dist_cache_[1] = 11; + s->dist_cache_[2] = 15; + s->dist_cache_[3] = 16; + /* Save the state of the distance cache in case we need to restore it for + emitting an uncompressed block. */ + memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_)); +} + +BrotliEncoderState* duckdb_brotli::BrotliEncoderCreateInstance( + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { + BrotliEncoderState* state = (BrotliEncoderState*)BrotliBootstrapAlloc( + sizeof(BrotliEncoderState), alloc_func, free_func, opaque); + if (state == NULL) { + /* BROTLI_DUMP(); */ + return 0; + } + BrotliInitMemoryManager( + &state->memory_manager_, alloc_func, free_func, opaque); + BrotliEncoderInitState(state); + return state; +} + +#ifdef BROTLI_REPORTING +/* When BROTLI_REPORTING is defined extra reporting module have to be linked. */ +void BrotliEncoderOnFinish(const BrotliEncoderState* s); +#define BROTLI_ENCODER_ON_FINISH(s) BrotliEncoderOnFinish(s); +#else +#if !defined(BROTLI_ENCODER_ON_FINISH) +#define BROTLI_ENCODER_ON_FINISH(s) (void)(s); +#endif +#endif + +static void BrotliEncoderCleanupState(BrotliEncoderState* s) { + MemoryManager* m = &s->memory_manager_; + + BROTLI_ENCODER_ON_FINISH(s); + + if (BROTLI_IS_OOM(m)) { + BrotliWipeOutMemoryManager(m); + return; + } + + BROTLI_FREE(m, s->storage_); + BROTLI_FREE(m, s->commands_); + RingBufferFree(m, &s->ringbuffer_); + DestroyHasher(m, &s->hasher_); + BROTLI_FREE(m, s->large_table_); + BROTLI_FREE(m, s->one_pass_arena_); + BROTLI_FREE(m, s->two_pass_arena_); + BROTLI_FREE(m, s->command_buf_); + BROTLI_FREE(m, s->literal_buf_); + BrotliEncoderCleanupParams(m, &s->params); +} + +/* Deinitializes and frees BrotliEncoderState instance. */ +void duckdb_brotli::BrotliEncoderDestroyInstance(BrotliEncoderState* state) { + if (!state) { + return; + } else { + BrotliEncoderCleanupState(state); + BrotliBootstrapFree(state, &state->memory_manager_); + } +} + +/* + Copies the given input data to the internal ring buffer of the compressor. + No processing of the data occurs at this time and this function can be + called multiple times before calling WriteBrotliData() to process the + accumulated input. At most input_block_size() bytes of input data can be + copied to the ring buffer, otherwise the next WriteBrotliData() will fail. + */ +static void CopyInputToRingBuffer(BrotliEncoderState* s, + const size_t input_size, + const uint8_t* input_buffer) { + RingBuffer* ringbuffer_ = &s->ringbuffer_; + MemoryManager* m = &s->memory_manager_; + RingBufferWrite(m, input_buffer, input_size, ringbuffer_); + if (BROTLI_IS_OOM(m)) return; + s->input_pos_ += input_size; + + /* TL;DR: If needed, initialize 7 more bytes in the ring buffer to make the + hashing not depend on uninitialized data. This makes compression + deterministic and it prevents uninitialized memory warnings in Valgrind. + Even without erasing, the output would be valid (but nondeterministic). + + Background information: The compressor stores short (at most 8 bytes) + substrings of the input already read in a hash table, and detects + repetitions by looking up such substrings in the hash table. If it + can find a substring, it checks whether the substring is really there + in the ring buffer (or it's just a hash collision). Should the hash + table become corrupt, this check makes sure that the output is + still valid, albeit the compression ratio would be bad. + + The compressor populates the hash table from the ring buffer as it's + reading new bytes from the input. However, at the last few indexes of + the ring buffer, there are not enough bytes to build full-length + substrings from. Since the hash table always contains full-length + substrings, we erase with dummy zeros here to make sure that those + substrings will contain zeros at the end instead of uninitialized + data. + + Please note that erasing is not necessary (because the + memory region is already initialized since he ring buffer + has a `tail' that holds a copy of the beginning,) so we + skip erasing if we have already gone around at least once in + the ring buffer. + + Only clear during the first round of ring-buffer writes. On + subsequent rounds data in the ring-buffer would be affected. */ + if (ringbuffer_->pos_ <= ringbuffer_->mask_) { + /* This is the first time when the ring buffer is being written. + We clear 7 bytes just after the bytes that have been copied from + the input buffer. + + The ring-buffer has a "tail" that holds a copy of the beginning, + but only once the ring buffer has been fully written once, i.e., + pos <= mask. For the first time, we need to write values + in this tail (where index may be larger than mask), so that + we have exactly defined behavior and don't read uninitialized + memory. Due to performance reasons, hashing reads data using a + LOAD64, which can go 7 bytes beyond the bytes written in the + ring-buffer. */ + memset(ringbuffer_->buffer_ + ringbuffer_->pos_, 0, 7); + } +} + +/* Marks all input as processed. + Returns true if position wrapping occurs. */ +static BROTLI_BOOL UpdateLastProcessedPos(BrotliEncoderState* s) { + uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_); + uint32_t wrapped_input_pos = WrapPosition(s->input_pos_); + s->last_processed_pos_ = s->input_pos_; + return TO_BROTLI_BOOL(wrapped_input_pos < wrapped_last_processed_pos); +} + +static void ExtendLastCommand(BrotliEncoderState* s, uint32_t* bytes, + uint32_t* wrapped_last_processed_pos) { + Command* last_command = &s->commands_[s->num_commands_ - 1]; + const uint8_t* data = s->ringbuffer_.buffer_; + const uint32_t mask = s->ringbuffer_.mask_; + uint64_t max_backward_distance = + (((uint64_t)1) << s->params.lgwin) - BROTLI_WINDOW_GAP; + uint64_t last_copy_len = last_command->copy_len_ & 0x1FFFFFF; + uint64_t last_processed_pos = s->last_processed_pos_ - last_copy_len; + uint64_t max_distance = last_processed_pos < max_backward_distance ? + last_processed_pos : max_backward_distance; + uint64_t cmd_dist = (uint64_t)s->dist_cache_[0]; + uint32_t distance_code = CommandRestoreDistanceCode(last_command, + &s->params.dist); + const CompoundDictionary* dict = &s->params.dictionary.compound; + size_t compound_dictionary_size = dict->total_size; + if (distance_code < BROTLI_NUM_DISTANCE_SHORT_CODES || + distance_code - (BROTLI_NUM_DISTANCE_SHORT_CODES - 1) == cmd_dist) { + if (cmd_dist <= max_distance) { + while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] == + data[(*wrapped_last_processed_pos - cmd_dist) & mask]) { + last_command->copy_len_++; + (*bytes)--; + (*wrapped_last_processed_pos)++; + } + } else { + if ((cmd_dist - max_distance - 1) < compound_dictionary_size && + last_copy_len < cmd_dist - max_distance) { + size_t address = + compound_dictionary_size - (size_t)(cmd_dist - max_distance) + + (size_t)last_copy_len; + size_t br_index = 0; + size_t br_offset; + const uint8_t* chunk; + size_t chunk_length; + while (address >= dict->chunk_offsets[br_index + 1]) br_index++; + br_offset = address - dict->chunk_offsets[br_index]; + chunk = dict->chunk_source[br_index]; + chunk_length = + dict->chunk_offsets[br_index + 1] - dict->chunk_offsets[br_index]; + while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] == + chunk[br_offset]) { + last_command->copy_len_++; + (*bytes)--; + (*wrapped_last_processed_pos)++; + if (++br_offset == chunk_length) { + br_index++; + br_offset = 0; + if (br_index != dict->num_chunks) { + chunk = dict->chunk_source[br_index]; + chunk_length = dict->chunk_offsets[br_index + 1] - + dict->chunk_offsets[br_index]; + } else { + break; + } + } + } + } + } + /* The copy length is at most the metablock size, and thus expressible. */ + GetLengthCode(last_command->insert_len_, + (size_t)((int)(last_command->copy_len_ & 0x1FFFFFF) + + (int)(last_command->copy_len_ >> 25)), + TO_BROTLI_BOOL((last_command->dist_prefix_ & 0x3FF) == 0), + &last_command->cmd_prefix_); + } +} + +/* + Processes the accumulated input data and sets |*out_size| to the length of + the new output meta-block, or to zero if no new output meta-block has been + created (in this case the processed input data is buffered internally). + If |*out_size| is positive, |*output| points to the start of the output + data. If |is_last| or |force_flush| is BROTLI_TRUE, an output meta-block is + always created. However, until |is_last| is BROTLI_TRUE encoder may retain up + to 7 bits of the last byte of output. Byte-alignment could be enforced by + emitting an empty meta-data block. + Returns BROTLI_FALSE if the size of the input data is larger than + input_block_size(). + */ +static BROTLI_BOOL EncodeData( + BrotliEncoderState* s, const BROTLI_BOOL is_last, + const BROTLI_BOOL force_flush, size_t* out_size, uint8_t** output) { + const uint64_t delta = UnprocessedInputSize(s); + uint32_t bytes = (uint32_t)delta; + uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_); + uint8_t* data; + uint32_t mask; + MemoryManager* m = &s->memory_manager_; + ContextType literal_context_mode; + ContextLut literal_context_lut; + BROTLI_BOOL fast_compress = + s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY || + s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY; + + data = s->ringbuffer_.buffer_; + mask = s->ringbuffer_.mask_; + + if (delta == 0) { /* No new input; still might want to flush or finish. */ + if (!data) { /* No input has been processed so far. */ + if (is_last) { /* Emit complete finalized stream. */ + BROTLI_DCHECK(s->last_bytes_bits_ <= 14); + s->last_bytes_ |= (uint16_t)(3u << s->last_bytes_bits_); + s->last_bytes_bits_ = (uint8_t)(s->last_bytes_bits_ + 2u); + s->tiny_buf_.u8[0] = (uint8_t)s->last_bytes_; + s->tiny_buf_.u8[1] = (uint8_t)(s->last_bytes_ >> 8); + *output = s->tiny_buf_.u8; + *out_size = (s->last_bytes_bits_ + 7u) >> 3u; + return BROTLI_TRUE; + } else { /* No data, not last -> no-op. */ + *out_size = 0; + return BROTLI_TRUE; + } + } else { + /* Fast compress performs flush every block -> flush is no-op. */ + if (!is_last && (!force_flush || fast_compress)) { /* Another no-op. */ + *out_size = 0; + return BROTLI_TRUE; + } + } + } + BROTLI_DCHECK(data); + + if (s->params.quality > s->params.dictionary.max_quality) return BROTLI_FALSE; + /* Adding more blocks after "last" block is forbidden. */ + if (s->is_last_block_emitted_) return BROTLI_FALSE; + if (is_last) s->is_last_block_emitted_ = BROTLI_TRUE; + + if (delta > InputBlockSize(s)) { + return BROTLI_FALSE; + } + if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY && + !s->command_buf_) { + s->command_buf_ = + BROTLI_ALLOC(m, uint32_t, kCompressFragmentTwoPassBlockSize); + s->literal_buf_ = + BROTLI_ALLOC(m, uint8_t, kCompressFragmentTwoPassBlockSize); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->command_buf_) || + BROTLI_IS_NULL(s->literal_buf_)) { + return BROTLI_FALSE; + } + } + + if (fast_compress) { + uint8_t* storage; + size_t storage_ix = s->last_bytes_bits_; + size_t table_size; + int* table; + + storage = GetBrotliStorage(s, 2 * bytes + 503); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + storage[0] = (uint8_t)s->last_bytes_; + storage[1] = (uint8_t)(s->last_bytes_ >> 8); + table = GetHashTable(s, s->params.quality, bytes, &table_size); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) { + BrotliCompressFragmentFast( + s->one_pass_arena_, &data[wrapped_last_processed_pos & mask], + bytes, is_last, + table, table_size, + &storage_ix, storage); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + } else { + BrotliCompressFragmentTwoPass( + s->two_pass_arena_, &data[wrapped_last_processed_pos & mask], + bytes, is_last, + s->command_buf_, s->literal_buf_, + table, table_size, + &storage_ix, storage); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + } + s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]); + s->last_bytes_bits_ = storage_ix & 7u; + UpdateLastProcessedPos(s); + *output = &storage[0]; + *out_size = storage_ix >> 3; + return BROTLI_TRUE; + } + + { + /* Theoretical max number of commands is 1 per 2 bytes. */ + size_t newsize = s->num_commands_ + bytes / 2 + 1; + if (newsize > s->cmd_alloc_size_) { + Command* new_commands; + /* Reserve a bit more memory to allow merging with a next block + without reallocation: that would impact speed. */ + newsize += (bytes / 4) + 16; + s->cmd_alloc_size_ = newsize; + new_commands = BROTLI_ALLOC(m, Command, newsize); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_commands)) return BROTLI_FALSE; + if (s->commands_) { + memcpy(new_commands, s->commands_, sizeof(Command) * s->num_commands_); + BROTLI_FREE(m, s->commands_); + } + s->commands_ = new_commands; + } + } + + InitOrStitchToPreviousBlock(m, &s->hasher_, data, mask, &s->params, + wrapped_last_processed_pos, bytes, is_last); + + literal_context_mode = ChooseContextMode( + &s->params, data, WrapPosition(s->last_flush_pos_), + mask, (size_t)(s->input_pos_ - s->last_flush_pos_)); + literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode); + + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + + if (s->num_commands_ && s->last_insert_len_ == 0) { + ExtendLastCommand(s, &bytes, &wrapped_last_processed_pos); + } + + if (s->params.quality == ZOPFLIFICATION_QUALITY) { + BROTLI_DCHECK(s->params.hasher.type == 10); + BrotliCreateZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos, + data, mask, literal_context_lut, &s->params, + &s->hasher_, s->dist_cache_, + &s->last_insert_len_, &s->commands_[s->num_commands_], + &s->num_commands_, &s->num_literals_); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + } else if (s->params.quality == HQ_ZOPFLIFICATION_QUALITY) { + BROTLI_DCHECK(s->params.hasher.type == 10); + BrotliCreateHqZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos, + data, mask, literal_context_lut, &s->params, + &s->hasher_, s->dist_cache_, + &s->last_insert_len_, &s->commands_[s->num_commands_], + &s->num_commands_, &s->num_literals_); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + } else { + BrotliCreateBackwardReferences(bytes, wrapped_last_processed_pos, + data, mask, literal_context_lut, &s->params, + &s->hasher_, s->dist_cache_, + &s->last_insert_len_, &s->commands_[s->num_commands_], + &s->num_commands_, &s->num_literals_); + } + + { + const size_t max_length = MaxMetablockSize(&s->params); + const size_t max_literals = max_length / 8; + const size_t max_commands = max_length / 8; + const size_t processed_bytes = (size_t)(s->input_pos_ - s->last_flush_pos_); + /* If maximal possible additional block doesn't fit metablock, flush now. */ + /* TODO(eustas): Postpone decision until next block arrives? */ + const BROTLI_BOOL next_input_fits_metablock = TO_BROTLI_BOOL( + processed_bytes + InputBlockSize(s) <= max_length); + /* If block splitting is not used, then flush as soon as there is some + amount of commands / literals produced. */ + const BROTLI_BOOL should_flush = TO_BROTLI_BOOL( + s->params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT && + s->num_literals_ + s->num_commands_ >= MAX_NUM_DELAYED_SYMBOLS); + if (!is_last && !force_flush && !should_flush && + next_input_fits_metablock && + s->num_literals_ < max_literals && + s->num_commands_ < max_commands) { + /* Merge with next input block. Everything will happen later. */ + if (UpdateLastProcessedPos(s)) { + HasherReset(&s->hasher_); + } + *out_size = 0; + return BROTLI_TRUE; + } + } + + /* Create the last insert-only command. */ + if (s->last_insert_len_ > 0) { + InitInsertCommand(&s->commands_[s->num_commands_++], s->last_insert_len_); + s->num_literals_ += s->last_insert_len_; + s->last_insert_len_ = 0; + } + + if (!is_last && s->input_pos_ == s->last_flush_pos_) { + /* We have no new input data and we don't have to finish the stream, so + nothing to do. */ + *out_size = 0; + return BROTLI_TRUE; + } + BROTLI_DCHECK(s->input_pos_ >= s->last_flush_pos_); + BROTLI_DCHECK(s->input_pos_ > s->last_flush_pos_ || is_last); + BROTLI_DCHECK(s->input_pos_ - s->last_flush_pos_ <= 1u << 24); + { + const uint32_t metablock_size = + (uint32_t)(s->input_pos_ - s->last_flush_pos_); + uint8_t* storage = GetBrotliStorage(s, 2 * metablock_size + 503); + size_t storage_ix = s->last_bytes_bits_; + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + storage[0] = (uint8_t)s->last_bytes_; + storage[1] = (uint8_t)(s->last_bytes_ >> 8); + WriteMetaBlockInternal( + m, data, mask, s->last_flush_pos_, metablock_size, is_last, + literal_context_mode, &s->params, s->prev_byte_, s->prev_byte2_, + s->num_literals_, s->num_commands_, s->commands_, s->saved_dist_cache_, + s->dist_cache_, &storage_ix, storage); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]); + s->last_bytes_bits_ = storage_ix & 7u; + s->last_flush_pos_ = s->input_pos_; + if (UpdateLastProcessedPos(s)) { + HasherReset(&s->hasher_); + } + if (s->last_flush_pos_ > 0) { + s->prev_byte_ = data[((uint32_t)s->last_flush_pos_ - 1) & mask]; + } + if (s->last_flush_pos_ > 1) { + s->prev_byte2_ = data[(uint32_t)(s->last_flush_pos_ - 2) & mask]; + } + s->num_commands_ = 0; + s->num_literals_ = 0; + /* Save the state of the distance cache in case we need to restore it for + emitting an uncompressed block. */ + memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_)); + *output = &storage[0]; + *out_size = storage_ix >> 3; + return BROTLI_TRUE; + } +} + +/* Dumps remaining output bits and metadata header to |header|. + Returns number of produced bytes. + REQUIRED: |header| should be 8-byte aligned and at least 16 bytes long. + REQUIRED: |block_size| <= (1 << 24). */ +static size_t WriteMetadataHeader( + BrotliEncoderState* s, const size_t block_size, uint8_t* header) { + size_t storage_ix; + storage_ix = s->last_bytes_bits_; + header[0] = (uint8_t)s->last_bytes_; + header[1] = (uint8_t)(s->last_bytes_ >> 8); + s->last_bytes_ = 0; + s->last_bytes_bits_ = 0; + + BrotliWriteBits(1, 0, &storage_ix, header); + BrotliWriteBits(2, 3, &storage_ix, header); + BrotliWriteBits(1, 0, &storage_ix, header); + if (block_size == 0) { + BrotliWriteBits(2, 0, &storage_ix, header); + } else { + uint32_t nbits = (block_size == 1) ? 1 : + (Log2FloorNonZero((uint32_t)block_size - 1) + 1); + uint32_t nbytes = (nbits + 7) / 8; + BrotliWriteBits(2, nbytes, &storage_ix, header); + BrotliWriteBits(8 * nbytes, block_size - 1, &storage_ix, header); + } + return (storage_ix + 7u) >> 3; +} + +size_t duckdb_brotli::BrotliEncoderMaxCompressedSize(size_t input_size) { + /* [window bits / empty metadata] + N * [uncompressed] + [last empty] */ + size_t num_large_blocks = input_size >> 14; + size_t overhead = 2 + (4 * num_large_blocks) + 3 + 1; + size_t result = input_size + overhead; + if (input_size == 0) return 2; + return (result < input_size) ? 0 : result; +} + +/* Wraps data to uncompressed brotli stream with minimal window size. + |output| should point at region with at least BrotliEncoderMaxCompressedSize + addressable bytes. + Returns the length of stream. */ +static size_t MakeUncompressedStream( + const uint8_t* input, size_t input_size, uint8_t* output) { + size_t size = input_size; + size_t result = 0; + size_t offset = 0; + if (input_size == 0) { + output[0] = 6; + return 1; + } + output[result++] = 0x21; /* window bits = 10, is_last = false */ + output[result++] = 0x03; /* empty metadata, padding */ + while (size > 0) { + uint32_t nibbles = 0; + uint32_t chunk_size; + uint32_t bits; + chunk_size = (size > (1u << 24)) ? (1u << 24) : (uint32_t)size; + if (chunk_size > (1u << 16)) nibbles = (chunk_size > (1u << 20)) ? 2 : 1; + bits = + (nibbles << 1) | ((chunk_size - 1) << 3) | (1u << (19 + 4 * nibbles)); + output[result++] = (uint8_t)bits; + output[result++] = (uint8_t)(bits >> 8); + output[result++] = (uint8_t)(bits >> 16); + if (nibbles == 2) output[result++] = (uint8_t)(bits >> 24); + memcpy(&output[result], &input[offset], chunk_size); + result += chunk_size; + offset += chunk_size; + size -= chunk_size; + } + output[result++] = 3; + return result; +} + +BROTLI_BOOL duckdb_brotli::BrotliEncoderCompress( + int quality, int lgwin, BrotliEncoderMode mode, size_t input_size, + const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)], + size_t* encoded_size, + uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]) { + BrotliEncoderState* s; + size_t out_size = *encoded_size; + const uint8_t* input_start = input_buffer; + uint8_t* output_start = encoded_buffer; + size_t max_out_size = BrotliEncoderMaxCompressedSize(input_size); + if (out_size == 0) { + /* Output buffer needs at least one byte. */ + return BROTLI_FALSE; + } + if (input_size == 0) { + /* Handle the special case of empty input. */ + *encoded_size = 1; + *encoded_buffer = 6; + return BROTLI_TRUE; + } + + s = BrotliEncoderCreateInstance(0, 0, 0); + if (!s) { + return BROTLI_FALSE; + } else { + size_t available_in = input_size; + const uint8_t* next_in = input_buffer; + size_t available_out = *encoded_size; + uint8_t* next_out = encoded_buffer; + size_t total_out = 0; + BROTLI_BOOL result = BROTLI_FALSE; + /* TODO(eustas): check that parameters are sane. */ + BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality); + BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin); + BrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, (uint32_t)mode); + BrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, (uint32_t)input_size); + if (lgwin > BROTLI_MAX_WINDOW_BITS) { + BrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE); + } + result = BrotliEncoderCompressStream(s, BROTLI_OPERATION_FINISH, + &available_in, &next_in, &available_out, &next_out, &total_out); + if (!BrotliEncoderIsFinished(s)) result = 0; + *encoded_size = total_out; + BrotliEncoderDestroyInstance(s); + if (!result || (max_out_size && *encoded_size > max_out_size)) { + goto fallback; + } + return BROTLI_TRUE; + } +fallback: + *encoded_size = 0; + if (!max_out_size) return BROTLI_FALSE; + if (out_size >= max_out_size) { + *encoded_size = + MakeUncompressedStream(input_start, input_size, output_start); + return BROTLI_TRUE; + } + return BROTLI_FALSE; +} + +static void InjectBytePaddingBlock(BrotliEncoderState* s) { + uint32_t seal = s->last_bytes_; + size_t seal_bits = s->last_bytes_bits_; + uint8_t* destination; + s->last_bytes_ = 0; + s->last_bytes_bits_ = 0; + /* is_last = 0, data_nibbles = 11, reserved = 0, meta_nibbles = 00 */ + seal |= 0x6u << seal_bits; + seal_bits += 6; + /* If we have already created storage, then append to it. + Storage is valid until next block is being compressed. */ + if (s->next_out_) { + destination = s->next_out_ + s->available_out_; + } else { + destination = s->tiny_buf_.u8; + s->next_out_ = destination; + } + destination[0] = (uint8_t)seal; + if (seal_bits > 8) destination[1] = (uint8_t)(seal >> 8); + if (seal_bits > 16) destination[2] = (uint8_t)(seal >> 16); + s->available_out_ += (seal_bits + 7) >> 3; +} + +/* Fills the |total_out|, if it is not NULL. */ +static void SetTotalOut(BrotliEncoderState* s, size_t* total_out) { + if (total_out) { + /* Saturating conversion uint64_t -> size_t */ + size_t result = (size_t)-1; + if (s->total_out_ < result) { + result = (size_t)s->total_out_; + } + *total_out = result; + } +} + +/* Injects padding bits or pushes compressed data to output. + Returns false if nothing is done. */ +static BROTLI_BOOL InjectFlushOrPushOutput(BrotliEncoderState* s, + size_t* available_out, uint8_t** next_out, size_t* total_out) { + if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED && + s->last_bytes_bits_ != 0) { + InjectBytePaddingBlock(s); + return BROTLI_TRUE; + } + + if (s->available_out_ != 0 && *available_out != 0) { + size_t copy_output_size = + BROTLI_MIN(size_t, s->available_out_, *available_out); + memcpy(*next_out, s->next_out_, copy_output_size); + *next_out += copy_output_size; + *available_out -= copy_output_size; + s->next_out_ += copy_output_size; + s->available_out_ -= copy_output_size; + s->total_out_ += copy_output_size; + SetTotalOut(s, total_out); + return BROTLI_TRUE; + } + + return BROTLI_FALSE; +} + +static void CheckFlushComplete(BrotliEncoderState* s) { + if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED && + s->available_out_ == 0) { + s->stream_state_ = BROTLI_STREAM_PROCESSING; + s->next_out_ = 0; + } +} + +static BROTLI_BOOL BrotliEncoderCompressStreamFast( + BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in, + const uint8_t** next_in, size_t* available_out, uint8_t** next_out, + size_t* total_out) { + const size_t block_size_limit = (size_t)1 << s->params.lgwin; + const size_t buf_size = BROTLI_MIN(size_t, kCompressFragmentTwoPassBlockSize, + BROTLI_MIN(size_t, *available_in, block_size_limit)); + uint32_t* tmp_command_buf = NULL; + uint32_t* command_buf = NULL; + uint8_t* tmp_literal_buf = NULL; + uint8_t* literal_buf = NULL; + MemoryManager* m = &s->memory_manager_; + if (s->params.quality != FAST_ONE_PASS_COMPRESSION_QUALITY && + s->params.quality != FAST_TWO_PASS_COMPRESSION_QUALITY) { + return BROTLI_FALSE; + } + if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { + if (!s->command_buf_ && buf_size == kCompressFragmentTwoPassBlockSize) { + s->command_buf_ = + BROTLI_ALLOC(m, uint32_t, kCompressFragmentTwoPassBlockSize); + s->literal_buf_ = + BROTLI_ALLOC(m, uint8_t, kCompressFragmentTwoPassBlockSize); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->command_buf_) || + BROTLI_IS_NULL(s->literal_buf_)) { + return BROTLI_FALSE; + } + } + if (s->command_buf_) { + command_buf = s->command_buf_; + literal_buf = s->literal_buf_; + } else { + tmp_command_buf = BROTLI_ALLOC(m, uint32_t, buf_size); + tmp_literal_buf = BROTLI_ALLOC(m, uint8_t, buf_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp_command_buf) || + BROTLI_IS_NULL(tmp_literal_buf)) { + return BROTLI_FALSE; + } + command_buf = tmp_command_buf; + literal_buf = tmp_literal_buf; + } + } + + while (BROTLI_TRUE) { + if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) { + continue; + } + + /* Compress block only when internal output buffer is empty, stream is not + finished, there is no pending flush request, and there is either + additional input or pending operation. */ + if (s->available_out_ == 0 && + s->stream_state_ == BROTLI_STREAM_PROCESSING && + (*available_in != 0 || op != BROTLI_OPERATION_PROCESS)) { + size_t block_size = BROTLI_MIN(size_t, block_size_limit, *available_in); + BROTLI_BOOL is_last = + (*available_in == block_size) && (op == BROTLI_OPERATION_FINISH); + BROTLI_BOOL force_flush = + (*available_in == block_size) && (op == BROTLI_OPERATION_FLUSH); + size_t max_out_size = 2 * block_size + 503; + BROTLI_BOOL inplace = BROTLI_TRUE; + uint8_t* storage = NULL; + size_t storage_ix = s->last_bytes_bits_; + size_t table_size; + int* table; + + if (force_flush && block_size == 0) { + s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED; + continue; + } + if (max_out_size <= *available_out) { + storage = *next_out; + } else { + inplace = BROTLI_FALSE; + storage = GetBrotliStorage(s, max_out_size); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + } + storage[0] = (uint8_t)s->last_bytes_; + storage[1] = (uint8_t)(s->last_bytes_ >> 8); + table = GetHashTable(s, s->params.quality, block_size, &table_size); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + + if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) { + BrotliCompressFragmentFast(s->one_pass_arena_, *next_in, block_size, + is_last, table, table_size, &storage_ix, storage); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + } else { + BrotliCompressFragmentTwoPass(s->two_pass_arena_, *next_in, block_size, + is_last, command_buf, literal_buf, table, table_size, + &storage_ix, storage); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + } + if (block_size != 0) { + *next_in += block_size; + *available_in -= block_size; + s->total_in_ += block_size; + } + if (inplace) { + size_t out_bytes = storage_ix >> 3; + BROTLI_DCHECK(out_bytes <= *available_out); + BROTLI_DCHECK((storage_ix & 7) == 0 || out_bytes < *available_out); + *next_out += out_bytes; + *available_out -= out_bytes; + s->total_out_ += out_bytes; + SetTotalOut(s, total_out); + } else { + size_t out_bytes = storage_ix >> 3; + s->next_out_ = storage; + s->available_out_ = out_bytes; + } + s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]); + s->last_bytes_bits_ = storage_ix & 7u; + + if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED; + if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED; + continue; + } + break; + } + BROTLI_FREE(m, tmp_command_buf); + BROTLI_FREE(m, tmp_literal_buf); + CheckFlushComplete(s); + return BROTLI_TRUE; +} + +static BROTLI_BOOL ProcessMetadata( + BrotliEncoderState* s, size_t* available_in, const uint8_t** next_in, + size_t* available_out, uint8_t** next_out, size_t* total_out) { + if (*available_in > (1u << 24)) return BROTLI_FALSE; + /* Switch to metadata block workflow, if required. */ + if (s->stream_state_ == BROTLI_STREAM_PROCESSING) { + s->remaining_metadata_bytes_ = (uint32_t)*available_in; + s->stream_state_ = BROTLI_STREAM_METADATA_HEAD; + } + if (s->stream_state_ != BROTLI_STREAM_METADATA_HEAD && + s->stream_state_ != BROTLI_STREAM_METADATA_BODY) { + return BROTLI_FALSE; + } + + while (BROTLI_TRUE) { + if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) { + continue; + } + if (s->available_out_ != 0) break; + + if (s->input_pos_ != s->last_flush_pos_) { + BROTLI_BOOL result = EncodeData(s, BROTLI_FALSE, BROTLI_TRUE, + &s->available_out_, &s->next_out_); + if (!result) return BROTLI_FALSE; + continue; + } + + if (s->stream_state_ == BROTLI_STREAM_METADATA_HEAD) { + s->next_out_ = s->tiny_buf_.u8; + s->available_out_ = + WriteMetadataHeader(s, s->remaining_metadata_bytes_, s->next_out_); + s->stream_state_ = BROTLI_STREAM_METADATA_BODY; + continue; + } else { + /* Exit workflow only when there is no more input and no more output. + Otherwise client may continue producing empty metadata blocks. */ + if (s->remaining_metadata_bytes_ == 0) { + s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX; + s->stream_state_ = BROTLI_STREAM_PROCESSING; + break; + } + if (*available_out) { + /* Directly copy input to output. */ + uint32_t copy = (uint32_t)BROTLI_MIN( + size_t, s->remaining_metadata_bytes_, *available_out); + memcpy(*next_out, *next_in, copy); + *next_in += copy; + *available_in -= copy; + s->total_in_ += copy; /* not actually data input, though */ + s->remaining_metadata_bytes_ -= copy; + *next_out += copy; + *available_out -= copy; + } else { + /* This guarantees progress in "TakeOutput" workflow. */ + uint32_t copy = BROTLI_MIN(uint32_t, s->remaining_metadata_bytes_, 16); + s->next_out_ = s->tiny_buf_.u8; + memcpy(s->next_out_, *next_in, copy); + *next_in += copy; + *available_in -= copy; + s->total_in_ += copy; /* not actually data input, though */ + s->remaining_metadata_bytes_ -= copy; + s->available_out_ = copy; + } + continue; + } + } + + return BROTLI_TRUE; +} + +static void UpdateSizeHint(BrotliEncoderState* s, size_t available_in) { + if (s->params.size_hint == 0) { + uint64_t delta = UnprocessedInputSize(s); + uint64_t tail = available_in; + uint32_t limit = 1u << 30; + uint32_t total; + if ((delta >= limit) || (tail >= limit) || ((delta + tail) >= limit)) { + total = limit; + } else { + total = (uint32_t)(delta + tail); + } + s->params.size_hint = total; + } +} + +BROTLI_BOOL duckdb_brotli::BrotliEncoderCompressStream( + BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in, + const uint8_t** next_in, size_t* available_out, uint8_t** next_out, + size_t* total_out) { + if (!EnsureInitialized(s)) return BROTLI_FALSE; + + /* Unfinished metadata block; check requirements. */ + if (s->remaining_metadata_bytes_ != BROTLI_UINT32_MAX) { + if (*available_in != s->remaining_metadata_bytes_) return BROTLI_FALSE; + if (op != BROTLI_OPERATION_EMIT_METADATA) return BROTLI_FALSE; + } + + if (op == BROTLI_OPERATION_EMIT_METADATA) { + UpdateSizeHint(s, 0); /* First data metablock might be emitted here. */ + return ProcessMetadata( + s, available_in, next_in, available_out, next_out, total_out); + } + + if (s->stream_state_ == BROTLI_STREAM_METADATA_HEAD || + s->stream_state_ == BROTLI_STREAM_METADATA_BODY) { + return BROTLI_FALSE; + } + + if (s->stream_state_ != BROTLI_STREAM_PROCESSING && *available_in != 0) { + return BROTLI_FALSE; + } + if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY || + s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { + return BrotliEncoderCompressStreamFast(s, op, available_in, next_in, + available_out, next_out, total_out); + } + while (BROTLI_TRUE) { + size_t remaining_block_size = RemainingInputBlockSize(s); + /* Shorten input to flint size. */ + if (s->flint_ >= 0 && remaining_block_size > (size_t)s->flint_) { + remaining_block_size = (size_t)s->flint_; + } + + if (remaining_block_size != 0 && *available_in != 0) { + size_t copy_input_size = + BROTLI_MIN(size_t, remaining_block_size, *available_in); + CopyInputToRingBuffer(s, copy_input_size, *next_in); + *next_in += copy_input_size; + *available_in -= copy_input_size; + s->total_in_ += copy_input_size; + if (s->flint_ > 0) s->flint_ = (int8_t)(s->flint_ - (int)copy_input_size); + continue; + } + + if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) { + /* Exit the "emit flint" workflow. */ + if (s->flint_ == BROTLI_FLINT_WAITING_FOR_FLUSHING) { + CheckFlushComplete(s); + if (s->stream_state_ == BROTLI_STREAM_PROCESSING) { + s->flint_ = BROTLI_FLINT_DONE; + } + } + continue; + } + + /* Compress data only when internal output buffer is empty, stream is not + finished and there is no pending flush request. */ + if (s->available_out_ == 0 && + s->stream_state_ == BROTLI_STREAM_PROCESSING) { + if (remaining_block_size == 0 || op != BROTLI_OPERATION_PROCESS) { + BROTLI_BOOL is_last = TO_BROTLI_BOOL( + (*available_in == 0) && op == BROTLI_OPERATION_FINISH); + BROTLI_BOOL force_flush = TO_BROTLI_BOOL( + (*available_in == 0) && op == BROTLI_OPERATION_FLUSH); + BROTLI_BOOL result; + /* Force emitting (uncompressed) piece containing flint. */ + if (!is_last && s->flint_ == 0) { + s->flint_ = BROTLI_FLINT_WAITING_FOR_FLUSHING; + force_flush = BROTLI_TRUE; + } + UpdateSizeHint(s, *available_in); + result = EncodeData(s, is_last, force_flush, + &s->available_out_, &s->next_out_); + if (!result) return BROTLI_FALSE; + if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED; + if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED; + continue; + } + } + break; + } + CheckFlushComplete(s); + return BROTLI_TRUE; +} + +BROTLI_BOOL duckdb_brotli::BrotliEncoderIsFinished(BrotliEncoderState* s) { + return TO_BROTLI_BOOL(s->stream_state_ == BROTLI_STREAM_FINISHED && + !BrotliEncoderHasMoreOutput(s)); +} + +BROTLI_BOOL duckdb_brotli::BrotliEncoderHasMoreOutput(BrotliEncoderState* s) { + return TO_BROTLI_BOOL(s->available_out_ != 0); +} + +const uint8_t* BrotliEncoderTakeOutput(BrotliEncoderState* s, size_t* size) { + size_t consumed_size = s->available_out_; + uint8_t* result = s->next_out_; + if (*size) { + consumed_size = BROTLI_MIN(size_t, *size, s->available_out_); + } + if (consumed_size) { + s->next_out_ += consumed_size; + s->available_out_ -= consumed_size; + s->total_out_ += consumed_size; + CheckFlushComplete(s); + *size = consumed_size; + } else { + *size = 0; + result = 0; + } + return result; +} + +uint32_t duckdb_brotli::BrotliEncoderVersion(void) { + return BROTLI_VERSION; +} + +BrotliEncoderPreparedDictionary* duckdb_brotli::BrotliEncoderPrepareDictionary( + BrotliSharedDictionaryType type, size_t size, + const uint8_t data[BROTLI_ARRAY_PARAM(size)], int quality, + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { + ManagedDictionary* managed_dictionary = NULL; + BROTLI_BOOL type_is_known = BROTLI_FALSE; + type_is_known |= (type == BROTLI_SHARED_DICTIONARY_RAW); +#if defined(BROTLI_EXPERIMENTAL) + type_is_known |= (type == BROTLI_SHARED_DICTIONARY_SERIALIZED); +#endif /* BROTLI_EXPERIMENTAL */ + if (!type_is_known) { + return NULL; + } + managed_dictionary = + BrotliCreateManagedDictionary(alloc_func, free_func, opaque); + if (managed_dictionary == NULL) { + return NULL; + } + if (type == BROTLI_SHARED_DICTIONARY_RAW) { + managed_dictionary->dictionary = (uint32_t*)CreatePreparedDictionary( + &managed_dictionary->memory_manager_, data, size); + } +#if defined(BROTLI_EXPERIMENTAL) + if (type == BROTLI_SHARED_DICTIONARY_SERIALIZED) { + SharedEncoderDictionary* dict = (SharedEncoderDictionary*)BrotliAllocate( + &managed_dictionary->memory_manager_, sizeof(SharedEncoderDictionary)); + managed_dictionary->dictionary = (uint32_t*)dict; + if (dict != NULL) { + BROTLI_BOOL ok = BrotliInitCustomSharedEncoderDictionary( + &managed_dictionary->memory_manager_, data, size, quality, dict); + if (!ok) { + BrotliFree(&managed_dictionary->memory_manager_, dict); + managed_dictionary->dictionary = NULL; + } + } + } +#else /* BROTLI_EXPERIMENTAL */ + (void)quality; +#endif /* BROTLI_EXPERIMENTAL */ + if (managed_dictionary->dictionary == NULL) { + BrotliDestroyManagedDictionary(managed_dictionary); + return NULL; + } + return (BrotliEncoderPreparedDictionary*)managed_dictionary; +} + +void BrotliEncoderDestroyPreparedDictionary( + BrotliEncoderPreparedDictionary* dictionary) { + ManagedDictionary* dict = (ManagedDictionary*)dictionary; + if (!dictionary) return; + /* First field of dictionary structs. */ + /* Only managed dictionaries are eligible for destruction by this method. */ + if (dict->magic != kManagedDictionaryMagic) { + return; + } + if (dict->dictionary == NULL) { + /* This should never ever happen. */ + } else if (*dict->dictionary == kLeanPreparedDictionaryMagic) { + DestroyPreparedDictionary( + &dict->memory_manager_, (PreparedDictionary*)dict->dictionary); + } else if (*dict->dictionary == kSharedDictionaryMagic) { + BrotliCleanupSharedEncoderDictionary(&dict->memory_manager_, + (SharedEncoderDictionary*)dict->dictionary); + BrotliFree(&dict->memory_manager_, dict->dictionary); + } else { + /* There is also kPreparedDictionaryMagic, but such instances should be + * constructed and destroyed by different means. */ + } + dict->dictionary = NULL; + BrotliDestroyManagedDictionary(dict); +} + +BROTLI_BOOL BrotliEncoderAttachPreparedDictionary(BrotliEncoderState* state, + const BrotliEncoderPreparedDictionary* dictionary) { + /* First field of dictionary structs */ + const BrotliEncoderPreparedDictionary* dict = dictionary; + uint32_t magic = *((const uint32_t*)dict); + SharedEncoderDictionary* current = NULL; + if (magic == kManagedDictionaryMagic) { + /* Unwrap managed dictionary. */ + ManagedDictionary* managed_dictionary = (ManagedDictionary*)dict; + magic = *managed_dictionary->dictionary; + dict = (BrotliEncoderPreparedDictionary*)managed_dictionary->dictionary; + } + current = &state->params.dictionary; + if (magic == kPreparedDictionaryMagic || + magic == kLeanPreparedDictionaryMagic) { + const PreparedDictionary* prepared = (const PreparedDictionary*)dict; + if (!AttachPreparedDictionary(¤t->compound, prepared)) { + return BROTLI_FALSE; + } + } else if (magic == kSharedDictionaryMagic) { + const SharedEncoderDictionary* attached = + (const SharedEncoderDictionary*)dict; + BROTLI_BOOL was_default = !current->contextual.context_based && + current->contextual.num_dictionaries == 1 && + current->contextual.dict[0]->hash_table_words == + kStaticDictionaryHashWords && + current->contextual.dict[0]->hash_table_lengths == + kStaticDictionaryHashLengths; + BROTLI_BOOL new_default = !attached->contextual.context_based && + attached->contextual.num_dictionaries == 1 && + attached->contextual.dict[0]->hash_table_words == + kStaticDictionaryHashWords && + attached->contextual.dict[0]->hash_table_lengths == + kStaticDictionaryHashLengths; + size_t i; + if (state->is_initialized_) return BROTLI_FALSE; + current->max_quality = + BROTLI_MIN(int, current->max_quality, attached->max_quality); + for (i = 0; i < attached->compound.num_chunks; i++) { + if (!AttachPreparedDictionary(¤t->compound, + attached->compound.chunks[i])) { + return BROTLI_FALSE; + } + } + if (!new_default) { + if (!was_default) return BROTLI_FALSE; + /* Copy by value, but then set num_instances_ to 0 because their memory + is managed by attached, not by current */ + current->contextual = attached->contextual; + current->contextual.num_instances_ = 0; + } + } else { + return BROTLI_FALSE; + } + return BROTLI_TRUE; +} + +size_t duckdb_brotli::BrotliEncoderEstimatePeakMemoryUsage(int quality, int lgwin, + size_t input_size) { + BrotliEncoderParams params; + size_t memory_manager_slots = BROTLI_ENCODER_MEMORY_MANAGER_SLOTS; + size_t memory_manager_size = memory_manager_slots * sizeof(void*); + BrotliEncoderInitParams(¶ms); + params.quality = quality; + params.lgwin = lgwin; + params.size_hint = input_size; + params.large_window = lgwin > BROTLI_MAX_WINDOW_BITS; + SanitizeParams(¶ms); + params.lgblock = ComputeLgBlock(¶ms); + ChooseHasher(¶ms, ¶ms.hasher); + if (params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY || + params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { + size_t state_size = sizeof(BrotliEncoderState); + size_t block_size = BROTLI_MIN(size_t, input_size, (1ul << params.lgwin)); + size_t hash_table_size = + HashTableSize(MaxHashTableSize(params.quality), block_size); + size_t hash_size = + (hash_table_size < (1u << 10)) ? 0 : sizeof(int) * hash_table_size; + size_t cmdbuf_size = params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY ? + 5 * BROTLI_MIN(size_t, block_size, 1ul << 17) : 0; + if (params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) { + state_size += sizeof(BrotliOnePassArena); + } else { + state_size += sizeof(BrotliTwoPassArena); + } + return hash_size + cmdbuf_size + state_size; + } else { + size_t short_ringbuffer_size = (size_t)1 << params.lgblock; + int ringbuffer_bits = ComputeRbBits(¶ms); + size_t ringbuffer_size = input_size < short_ringbuffer_size ? + input_size : (1u << ringbuffer_bits) + short_ringbuffer_size; + size_t hash_size[4] = {0}; + size_t metablock_size = + BROTLI_MIN(size_t, input_size, MaxMetablockSize(¶ms)); + size_t inputblock_size = + BROTLI_MIN(size_t, input_size, (size_t)1 << params.lgblock); + size_t cmdbuf_size = metablock_size * 2 + inputblock_size * 6; + size_t outbuf_size = metablock_size * 2 + 503; + size_t histogram_size = 0; + HasherSize(¶ms, BROTLI_TRUE, input_size, hash_size); + if (params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT) { + cmdbuf_size = BROTLI_MIN(size_t, cmdbuf_size, + MAX_NUM_DELAYED_SYMBOLS * sizeof(Command) + inputblock_size * 12); + } + if (params.quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) { + /* Only a very rough estimation, based on enwik8. */ + histogram_size = 200 << 20; + } else if (params.quality >= MIN_QUALITY_FOR_BLOCK_SPLIT) { + size_t literal_histograms = + BROTLI_MIN(size_t, metablock_size / 6144, 256); + size_t command_histograms = + BROTLI_MIN(size_t, metablock_size / 6144, 256); + size_t distance_histograms = + BROTLI_MIN(size_t, metablock_size / 6144, 256); + histogram_size = literal_histograms * sizeof(HistogramLiteral) + + command_histograms * sizeof(HistogramCommand) + + distance_histograms * sizeof(HistogramDistance); + } + return (memory_manager_size + ringbuffer_size + + hash_size[0] + hash_size[1] + hash_size[2] + hash_size[3] + + cmdbuf_size + + outbuf_size + + histogram_size); + } +} +size_t duckdb_brotli::BrotliEncoderGetPreparedDictionarySize( + const BrotliEncoderPreparedDictionary* prepared_dictionary) { + /* First field of dictionary structs */ + const BrotliEncoderPreparedDictionary* prepared = prepared_dictionary; + uint32_t magic = *((const uint32_t*)prepared); + size_t overhead = 0; + if (magic == kManagedDictionaryMagic) { + const ManagedDictionary* managed = (const ManagedDictionary*)prepared; + overhead = sizeof(ManagedDictionary); + magic = *managed->dictionary; + prepared = (const BrotliEncoderPreparedDictionary*)managed->dictionary; + } + + if (magic == kPreparedDictionaryMagic) { + const PreparedDictionary* dictionary = + (const PreparedDictionary*)prepared; + /* Keep in sync with step 3 of CreatePreparedDictionary */ + return sizeof(PreparedDictionary) + dictionary->source_size + + (sizeof(uint32_t) << dictionary->slot_bits) + + (sizeof(uint16_t) << dictionary->bucket_bits) + + (sizeof(uint32_t) * dictionary->num_items) + overhead; + } else if (magic == kLeanPreparedDictionaryMagic) { + const PreparedDictionary* dictionary = + (const PreparedDictionary*)prepared; + /* Keep in sync with step 3 of CreatePreparedDictionary */ + return sizeof(PreparedDictionary) + sizeof(uint8_t*) + + (sizeof(uint32_t) << dictionary->slot_bits) + + (sizeof(uint16_t) << dictionary->bucket_bits) + + (sizeof(uint32_t) * dictionary->num_items) + overhead; + } else if (magic == kSharedDictionaryMagic) { + const SharedEncoderDictionary* dictionary = + (const SharedEncoderDictionary*)prepared; + const CompoundDictionary* compound = &dictionary->compound; + const ContextualEncoderDictionary* contextual = &dictionary->contextual; + size_t result = sizeof(*dictionary); + size_t i; + size_t num_instances; + const BrotliEncoderDictionary* instances; + for (i = 0; i < compound->num_prepared_instances_; i++) { + size_t size = BrotliEncoderGetPreparedDictionarySize( + (const BrotliEncoderPreparedDictionary*) + compound->prepared_instances_[i]); + if (!size) return 0; /* error */ + result += size; + } + if (contextual->context_based) { + num_instances = contextual->num_instances_; + instances = contextual->instances_; + result += sizeof(*instances) * num_instances; + } else { + num_instances = 1; + instances = &contextual->instance_; + } + for (i = 0; i < num_instances; i++) { + const BrotliEncoderDictionary* dict = &instances[i]; + result += dict->trie.pool_capacity * sizeof(BrotliTrieNode); + if (dict->hash_table_data_words_) { + result += sizeof(kStaticDictionaryHashWords); + } + if (dict->hash_table_data_lengths_) { + result += sizeof(kStaticDictionaryHashLengths); + } + if (dict->buckets_data_) { + result += sizeof(*dict->buckets_data_) * dict->buckets_alloc_size_; + } + if (dict->dict_words_data_) { + result += sizeof(*dict->dict_words) * dict->dict_words_alloc_size_; + } + if (dict->words_instance_) { + result += sizeof(*dict->words_instance_); + /* data_size not added here: it is never allocated by the + SharedEncoderDictionary, instead it always points to the file + already loaded in memory. So if the caller wants to include + this memory as well, add the size of the loaded dictionary + file to this. */ + } + } + return result + overhead; + } + return 0; /* error */ +} + +#if defined(BROTLI_TEST) +size_t MakeUncompressedStreamForTest(const uint8_t*, size_t, uint8_t*); +size_t MakeUncompressedStreamForTest( + const uint8_t* input, size_t input_size, uint8_t* output) { + return MakeUncompressedStream(input, input_size, output); +} +#endif diff --git a/third_party/brotli/enc/encoder_dict.cpp b/third_party/brotli/enc/encoder_dict.cpp new file mode 100644 index 00000000000..3f5a0fcb124 --- /dev/null +++ b/third_party/brotli/enc/encoder_dict.cpp @@ -0,0 +1,636 @@ +/* Copyright 2017 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include "encoder_dict.h" + +#include /* malloc, free */ + +#include "../common/dictionary.h" +#include "../common/brotli_platform.h" +#include "../common/shared_dictionary_internal.h" +#include "../common/transform.h" +#include "compound_dictionary.h" +#include "dictionary_hash.h" +#include "memory.h" +#include "quality.h" +#include "brotli_hash.h" + +using namespace duckdb_brotli; + +#define NUM_HASH_BITS 15u +#define NUM_HASH_BUCKETS (1u << NUM_HASH_BITS) + +static void BrotliTrieInit(BrotliTrie* trie) { + trie->pool_capacity = 0; + trie->pool_size = 0; + trie->pool = 0; + + /* Set up the root node */ + trie->root.single = 0; + trie->root.len_ = 0; + trie->root.idx_ = 0; + trie->root.sub = 0; +} + +static void BrotliTrieFree(MemoryManager* m, BrotliTrie* trie) { + BrotliFree(m, trie->pool); +} + +/* Initializes to RFC 7932 static dictionary / transforms. */ +static void InitEncoderDictionary(BrotliEncoderDictionary* dict) { + dict->words = BrotliGetDictionary(); + dict->num_transforms = (uint32_t)BrotliGetTransforms()->num_transforms; + + dict->hash_table_words = kStaticDictionaryHashWords; + dict->hash_table_lengths = kStaticDictionaryHashLengths; + dict->buckets = kStaticDictionaryBuckets; + dict->dict_words = kStaticDictionaryWords; + + dict->cutoffTransformsCount = kCutoffTransformsCount; + dict->cutoffTransforms = kCutoffTransforms; + + dict->parent = 0; + + dict->hash_table_data_words_ = 0; + dict->hash_table_data_lengths_ = 0; + dict->buckets_alloc_size_ = 0; + dict->buckets_data_ = 0; + dict->dict_words_alloc_size_ = 0; + dict->dict_words_data_ = 0; + dict->words_instance_ = 0; + dict->has_words_heavy = BROTLI_FALSE; + BrotliTrieInit(&dict->trie); +} + +static void BrotliDestroyEncoderDictionary(MemoryManager* m, + BrotliEncoderDictionary* dict) { + BrotliFree(m, dict->hash_table_data_words_); + BrotliFree(m, dict->hash_table_data_lengths_); + BrotliFree(m, dict->buckets_data_); + BrotliFree(m, dict->dict_words_data_); + BrotliFree(m, dict->words_instance_); + BrotliTrieFree(m, &dict->trie); +} + +#if defined(BROTLI_EXPERIMENTAL) +/* Word length must be at least 4 bytes */ +static uint32_t Hash(const uint8_t* data, int bits) { + uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32; + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return h >> (32 - bits); +} + +/* Theoretical max possible word size after transform */ +#define kTransformedBufferSize \ + (256 + 256 + SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH) + +/* To be safe buffer must have at least kTransformedBufferSize */ +static void TransformedDictionaryWord(uint32_t word_idx, int len, int transform, + const BrotliTransforms* transforms, + const BrotliEncoderDictionary* dict, + uint8_t* buffer, size_t* size) { + const uint8_t* dict_word = &dict->words->data[ + dict->words->offsets_by_length[len] + (uint32_t)len * word_idx]; + *size = (size_t)BrotliTransformDictionaryWord(buffer, dict_word, len, + transforms, transform); +} + +static DictWord MakeDictWord(uint8_t len, uint8_t transform, uint16_t idx) { + DictWord result; + result.len = len; + result.transform = transform; + result.idx = idx; + return result; +} + +static uint32_t BrotliTrieAlloc(MemoryManager* m, size_t num, BrotliTrie* trie, + BrotliTrieNode** keep) { + uint32_t result; + uint32_t keep_index = 0; + if (keep && *keep != &trie->root) { + /* Optional node to keep, since address may change after re-allocating */ + keep_index = (uint32_t)(*keep - trie->pool); + } + if (trie->pool_size == 0) { + /* Have a dummy node in the front. We do not want the result to be 0, it + must be at least 1, 0 represents "null pointer" */ + trie->pool_size = 1; + } + BROTLI_ENSURE_CAPACITY(m, BrotliTrieNode, trie->pool, trie->pool_capacity, + trie->pool_size + num); + if (BROTLI_IS_OOM(m)) return 0; + /* Init the new nodes to empty */ + memset(trie->pool + trie->pool_size, 0, sizeof(*trie->pool) * num); + result = (uint32_t)trie->pool_size; + trie->pool_size += num; + if (keep && *keep != &trie->root) { + *keep = trie->pool + keep_index; + } + return result; +} + +/** + * len and idx: payload for last node + * word, size: the string + * index: position in the string + */ +static BROTLI_BOOL BrotliTrieNodeAdd(MemoryManager* m, uint8_t len, + uint32_t idx, const uint8_t* word, size_t size, int index, + BrotliTrieNode* node, BrotliTrie* trie) { + BrotliTrieNode* child = 0; + uint8_t c; + if ((size_t)index == size) { + if (!node->len_ || idx < node->idx_) { + node->len_ = len; + node->idx_ = idx; + } + return BROTLI_TRUE; + } + c = word[index]; + if (node->single && c != node->c) { + BrotliTrieNode old = trie->pool[node->sub]; + uint32_t new_nodes = BrotliTrieAlloc(m, 32, trie, &node); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + node->single = 0; + node->sub = new_nodes; + trie->pool[node->sub + (node->c >> 4)].sub = new_nodes + 16; + trie->pool[trie->pool[node->sub + (node->c >> 4)].sub + (node->c & 15)] = + old; + } + if (!node->sub) { + uint32_t new_node = BrotliTrieAlloc(m, 1, trie, &node); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + node->single = 1; + node->c = c; + node->sub = new_node; + } + if (node->single) { + child = &trie->pool[node->sub]; + } else { + if (!trie->pool[node->sub + (c >> 4)].sub) { + uint32_t new_nodes = BrotliTrieAlloc(m, 16, trie, &node); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + trie->pool[node->sub + (c >> 4)].sub = new_nodes; + } + child = &trie->pool[trie->pool[node->sub + (c >> 4)].sub + (c & 15)]; + } + return BrotliTrieNodeAdd(m, len, idx, word, size, index + 1, child, trie); +} + +static BROTLI_BOOL BrotliTrieAdd(MemoryManager* m, uint8_t len, uint32_t idx, + const uint8_t* word, size_t size, BrotliTrie* trie) { + return BrotliTrieNodeAdd(m, len, idx, word, size, 0, &trie->root, trie); +} + +const BrotliTrieNode* BrotliTrieSub(const BrotliTrie* trie, + const BrotliTrieNode* node, uint8_t c) { + BrotliTrieNode* temp_node; + if (node->single) { + if (node->c == c) return &trie->pool[node->sub]; + return 0; + } + if (!node->sub) return 0; + temp_node = &trie->pool[node->sub + (c >> 4)]; + if (!temp_node->sub) return 0; + return &trie->pool[temp_node->sub + (c & 15)]; +} + +static const BrotliTrieNode* BrotliTrieFind(const BrotliTrie* trie, + const uint8_t* word, size_t size) { + const BrotliTrieNode* node = &trie->root; + size_t i; + for (i = 0; i < size; i++) { + node = BrotliTrieSub(trie, node, word[i]); + if (!node) return 0; + } + return node; +} + +static BROTLI_BOOL BuildDictionaryLut(MemoryManager* m, + const BrotliTransforms* transforms, + BrotliEncoderDictionary* dict) { + uint32_t i; + DictWord* dict_words; + uint16_t* buckets; + DictWord** words_by_hash; + size_t* words_by_hash_size; + size_t* words_by_hash_capacity; + BrotliTrie dedup; + uint8_t word[kTransformedBufferSize]; + size_t word_size; + size_t total = 0; + uint8_t l; + uint16_t idx; + + BrotliTrieInit(&dedup); + + words_by_hash = (DictWord**)BrotliAllocate(m, + sizeof(*words_by_hash) * NUM_HASH_BUCKETS); + words_by_hash_size = (size_t*)BrotliAllocate(m, + sizeof(*words_by_hash_size) * NUM_HASH_BUCKETS); + words_by_hash_capacity = (size_t*)BrotliAllocate(m, + sizeof(*words_by_hash_capacity) * NUM_HASH_BUCKETS); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + memset(words_by_hash, 0, sizeof(*words_by_hash) * NUM_HASH_BUCKETS); + memset(words_by_hash_size, 0, sizeof(*words_by_hash_size) * NUM_HASH_BUCKETS); + memset(words_by_hash_capacity, 0, + sizeof(*words_by_hash_capacity) * NUM_HASH_BUCKETS); + + if (transforms->num_transforms > 0) { + for (l = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH; + l <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; ++l) { + uint16_t n = dict->words->size_bits_by_length[l] ? + (uint16_t)(1 << dict->words->size_bits_by_length[l]) : 0u; + for (idx = 0; idx < n; ++idx) { + uint32_t key; + /* First transform (usually identity) */ + TransformedDictionaryWord(idx, l, 0, transforms, dict, word, + &word_size); + /* Cannot hash words smaller than 4 bytes */ + if (word_size < 4) { + /* Break instead of continue, all next words of this length will have + same length after transform */ + break; + } + if (!BrotliTrieAdd(m, 0, idx, word, word_size, &dedup)) { + return BROTLI_FALSE; + } + key = Hash(word, NUM_HASH_BITS); + BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key], + words_by_hash_capacity[key], words_by_hash_size[key], + MakeDictWord(l, 0, idx)); + ++total; + } + } + } + + /* These LUT transforms only supported if no custom transforms. This is + ok, we will use the heavy trie instead. */ + if (transforms == BrotliGetTransforms()) { + for (l = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH; + l <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; ++l) { + uint16_t n = dict->words->size_bits_by_length[l] ? + (uint16_t)(1 << dict->words->size_bits_by_length[l]) : 0u; + for (idx = 0; idx < n; ++idx) { + int k; + BROTLI_BOOL is_ascii = BROTLI_TRUE; + size_t offset = dict->words->offsets_by_length[l] + (size_t)l * idx; + const uint8_t* data = &dict->words->data[offset]; + for (k = 0; k < l; ++k) { + if (data[k] >= 128) is_ascii = BROTLI_FALSE; + } + if (data[0] < 128) { + int transform = 9; /* {empty, uppercase first, empty} */ + uint32_t ix = idx + (uint32_t)transform * n; + const BrotliTrieNode* it; + TransformedDictionaryWord(idx, l, transform, transforms, + dict, word, &word_size); + it = BrotliTrieFind(&dedup, word, word_size); + if (!it || it->idx_ > ix) { + uint32_t key = Hash(word, NUM_HASH_BITS); + if (!BrotliTrieAdd(m, 0, ix, word, word_size, &dedup)) { + return BROTLI_FALSE; + } + BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key], + words_by_hash_capacity[key], words_by_hash_size[key], + MakeDictWord(l, BROTLI_TRANSFORM_UPPERCASE_FIRST, idx)); + ++total; + } + } + if (is_ascii) { + int transform = 44; /* {empty, uppercase all, empty} */ + uint32_t ix = idx + (uint32_t)transform * n; + const BrotliTrieNode* it; + TransformedDictionaryWord(idx, l, transform, transforms, + dict, word, &word_size); + it = BrotliTrieFind(&dedup, word, word_size); + if (!it || it->idx_ > ix) { + uint32_t key = Hash(word, NUM_HASH_BITS); + if (!BrotliTrieAdd(m, 0, ix, word, word_size, &dedup)) { + return BROTLI_FALSE; + } + BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key], + words_by_hash_capacity[key], words_by_hash_size[key], + MakeDictWord(l, BROTLI_TRANSFORM_UPPERCASE_ALL, idx)); + ++total; + } + } + } + } + } + + dict_words = (DictWord*)BrotliAllocate(m, + sizeof(*dict->dict_words) * (total + 1)); + buckets = (uint16_t*)BrotliAllocate(m, + sizeof(*dict->buckets) * NUM_HASH_BUCKETS); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + dict->dict_words_alloc_size_ = total + 1; + dict->dict_words = dict->dict_words_data_ = dict_words; + dict->buckets_alloc_size_ = NUM_HASH_BUCKETS; + dict->buckets = dict->buckets_data_ = buckets; + + /* Unused; makes offsets start from 1. */ + dict_words[0] = MakeDictWord(0, 0, 0); + total = 1; + for (i = 0; i < NUM_HASH_BUCKETS; ++i) { + size_t num_words = words_by_hash_size[i]; + if (num_words > 0) { + buckets[i] = (uint16_t)(total); + memcpy(&dict_words[total], &words_by_hash[i][0], + sizeof(dict_words[0]) * num_words); + total += num_words; + dict_words[total - 1].len |= 0x80; + } else { + buckets[i] = 0; + } + } + + for (i = 0; i < NUM_HASH_BUCKETS; ++i) { + BrotliFree(m, words_by_hash[i]); + } + BrotliFree(m, words_by_hash); + BrotliFree(m, words_by_hash_size); + BrotliFree(m, words_by_hash_capacity); + BrotliTrieFree(m, &dedup); + + return BROTLI_TRUE; +} + +static void BuildDictionaryHashTable(uint16_t* hash_table_words, + uint8_t* hash_table_lengths, const BrotliDictionary* dict) { + int j, len; + /* The order of the loops is such that in case of collision, words with + shorter length are preferred, and in case of same length, words with + smaller index. There is only a single word per bucket. */ + /* TODO(lode): consider adding optional user-supplied frequency_map to use + for preferred words instead, this can make the encoder better for + quality 9 and below without affecting the decoder */ + memset(hash_table_words, 0, sizeof(kStaticDictionaryHashWords)); + memset(hash_table_lengths, 0, sizeof(kStaticDictionaryHashLengths)); + for (len = SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; + len >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH; --len) { + const size_t num_words = dict->size_bits_by_length[len] ? + (1u << dict->size_bits_by_length[len]) : 0; + for (j = (int)num_words - 1; j >= 0; --j) { + size_t offset = dict->offsets_by_length[len] + + (size_t)len * (size_t)j; + const uint8_t* word = &dict->data[offset]; + const uint32_t key = Hash(word, 14); + int idx = (int)(key << 1) + (len < 8 ? 1 : 0); + BROTLI_DCHECK(idx < (int)NUM_HASH_BUCKETS); + hash_table_words[idx] = (uint16_t)j; + hash_table_lengths[idx] = (uint8_t)len; + } + } +} + +static BROTLI_BOOL GenerateWordsHeavy(MemoryManager* m, + const BrotliTransforms* transforms, + BrotliEncoderDictionary* dict) { + int i, j, l; + for (j = (int)transforms->num_transforms - 1; j >= 0 ; --j) { + for (l = 0; l < 32; l++) { + int num = (int)((1u << dict->words->size_bits_by_length[l]) & ~1u); + for (i = 0; i < num; i++) { + uint8_t transformed[kTransformedBufferSize]; + size_t size; + TransformedDictionaryWord( + (uint32_t)i, l, j, transforms, dict, transformed, &size); + if (size < 4) continue; + if (!BrotliTrieAdd(m, (uint8_t)l, (uint32_t)(i + num * j), + transformed, size, &dict->trie)) { + return BROTLI_FALSE; + } + } + } + } + return BROTLI_TRUE; +} + +/* Computes cutoffTransformsCount (in count) and cutoffTransforms (in data) for + the custom transforms, where possible within the limits of the + cutoffTransforms encoding. The fast encoder uses this to do fast lookup for + transforms that remove the N last characters (OmitLast). */ +static void ComputeCutoffTransforms( + const BrotliTransforms* transforms, + uint32_t* count, uint64_t* data) { + int i; + /* The encoding in a 64-bit integer of transform N in the data is: (N << 2) + + ((cutoffTransforms >> (N * 6)) & 0x3F), so for example the identity + transform code must be 0-63, for N=1 the transform code must be 4-67, ..., + for N=9 it must be 36-99. + TODO(lode): consider a simple flexible uint8_t[10] instead of the uint64_t + for the cutoff transforms, so that shared dictionaries can have the + OmitLast transforms anywhere without loss. */ + *count = 0; + *data = 0; + for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) { + int idx = transforms->cutOffTransforms[i]; + if (idx == -1) break; /* Not found */ + if (idx < (i << 2)) break; /* Too small for the encoding */ + if (idx >= (i << 2) + 64) break; /* Too large for the encoding */ + (*count)++; + *data |= (uint64_t)(((uint64_t)idx - + ((uint64_t)i << 2u)) << ((uint64_t)i * 6u)); + } +} + +static BROTLI_BOOL ComputeDictionary(MemoryManager* m, int quality, + const BrotliTransforms* transforms, + BrotliEncoderDictionary* current) { + int default_words = current->words == BrotliGetDictionary(); + int default_transforms = transforms == BrotliGetTransforms(); + + if (default_words && default_transforms) { + /* hashes are already set to Brotli defaults */ + return BROTLI_TRUE; + } + + current->hash_table_data_words_ = (uint16_t*)BrotliAllocate( + m, sizeof(kStaticDictionaryHashWords)); + current->hash_table_data_lengths_ = (uint8_t*)BrotliAllocate( + m, sizeof(kStaticDictionaryHashLengths)); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + current->hash_table_words = current->hash_table_data_words_; + current->hash_table_lengths = current->hash_table_data_lengths_; + + BuildDictionaryHashTable(current->hash_table_data_words_, + current->hash_table_data_lengths_, current->words); + + ComputeCutoffTransforms(transforms, + ¤t->cutoffTransformsCount, ¤t->cutoffTransforms); + + /* Only compute the data for slow encoder if the requested quality is high + enough to need it */ + if (quality >= ZOPFLIFICATION_QUALITY) { + if (!BuildDictionaryLut(m, transforms, current)) return BROTLI_FALSE; + + /* For the built-in Brotli transforms, there is a hard-coded function to + handle all transforms, but for custom transforms, we use the following + large hammer instead */ + current->has_words_heavy = !default_transforms; + if (current->has_words_heavy) { + if (!GenerateWordsHeavy(m, transforms, current)) return BROTLI_FALSE; + } + } + + return BROTLI_TRUE; +} +#endif /* BROTLI_EXPERIMENTAL */ + +void duckdb_brotli::BrotliInitSharedEncoderDictionary(SharedEncoderDictionary* dict) { + dict->magic = kSharedDictionaryMagic; + + dict->compound.num_chunks = 0; + dict->compound.total_size = 0; + dict->compound.chunk_offsets[0] = 0; + dict->compound.num_prepared_instances_ = 0; + + dict->contextual.context_based = 0; + dict->contextual.num_dictionaries = 1; + dict->contextual.instances_ = 0; + dict->contextual.num_instances_ = 1; /* The instance_ field */ + dict->contextual.dict[0] = &dict->contextual.instance_; + InitEncoderDictionary(&dict->contextual.instance_); + dict->contextual.instance_.parent = &dict->contextual; + + dict->max_quality = BROTLI_MAX_QUALITY; +} + +#if defined(BROTLI_EXPERIMENTAL) +/* TODO(eustas): make sure that tooling will warn user if not all the cutoff + transforms are available (for low-quality encoder). */ +static BROTLI_BOOL InitCustomSharedEncoderDictionary( + MemoryManager* m, const BrotliSharedDictionary* decoded_dict, + int quality, SharedEncoderDictionary* dict) { + ContextualEncoderDictionary* contextual; + CompoundDictionary* compound; + BrotliEncoderDictionary* instances; + int i; + BrotliInitSharedEncoderDictionary(dict); + + contextual = &dict->contextual; + compound = &dict->compound; + + for (i = 0; i < (int)decoded_dict->num_prefix; i++) { + PreparedDictionary* prepared = CreatePreparedDictionary(m, + decoded_dict->prefix[i], decoded_dict->prefix_size[i]); + AttachPreparedDictionary(compound, prepared); + /* remember for cleanup */ + compound->prepared_instances_[ + compound->num_prepared_instances_++] = prepared; + } + + dict->max_quality = quality; + contextual->context_based = decoded_dict->context_based; + if (decoded_dict->context_based) { + memcpy(contextual->context_map, decoded_dict->context_map, + SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS); + } + + contextual->num_dictionaries = decoded_dict->num_dictionaries; + contextual->num_instances_ = decoded_dict->num_dictionaries; + if (contextual->num_instances_ == 1) { + instances = &contextual->instance_; + } else { + contextual->instances_ = (BrotliEncoderDictionary*) + BrotliAllocate(m, sizeof(*contextual->instances_) * + contextual->num_instances_); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + instances = contextual->instances_; + } + for (i = 0; i < (int)contextual->num_instances_; i++) { + BrotliEncoderDictionary* current = &instances[i]; + InitEncoderDictionary(current); + current->parent = &dict->contextual; + if (decoded_dict->words[i] == BrotliGetDictionary()) { + current->words = BrotliGetDictionary(); + } else { + current->words_instance_ = (BrotliDictionary*)BrotliAllocate( + m, sizeof(BrotliDictionary)); + if (BROTLI_IS_OOM(m)) return BROTLI_FALSE; + *current->words_instance_ = *decoded_dict->words[i]; + current->words = current->words_instance_; + } + current->num_transforms = + (uint32_t)decoded_dict->transforms[i]->num_transforms; + if (!ComputeDictionary( + m, quality, decoded_dict->transforms[i], current)) { + return BROTLI_FALSE; + } + + contextual->dict[i] = current; + } + + return BROTLI_TRUE; /* success */ +} + +BROTLI_BOOL BrotliInitCustomSharedEncoderDictionary( + MemoryManager* m, const uint8_t* encoded_dict, size_t size, + int quality, SharedEncoderDictionary* dict) { + BROTLI_BOOL success = BROTLI_FALSE; + BrotliSharedDictionary* decoded_dict = BrotliSharedDictionaryCreateInstance( + m->alloc_func, m->free_func, m->opaque); + if (!decoded_dict) { /* OOM */ + return BROTLI_FALSE; + } + success = BrotliSharedDictionaryAttach( + decoded_dict, BROTLI_SHARED_DICTIONARY_SERIALIZED, size, encoded_dict); + if (success) { + success = InitCustomSharedEncoderDictionary(m, + decoded_dict, quality, dict); + } + BrotliSharedDictionaryDestroyInstance(decoded_dict); + return success; +} +#endif /* BROTLI_EXPERIMENTAL */ + +void duckdb_brotli::BrotliCleanupSharedEncoderDictionary(MemoryManager* m, + SharedEncoderDictionary* dict) { + size_t i; + for (i = 0; i < dict->compound.num_prepared_instances_; i++) { + DestroyPreparedDictionary(m, + (PreparedDictionary*)dict->compound.prepared_instances_[i]); + } + if (dict->contextual.num_instances_ == 1) { + BrotliDestroyEncoderDictionary(m, &dict->contextual.instance_); + } else if (dict->contextual.num_instances_ > 1) { + for (i = 0; i < dict->contextual.num_instances_; i++) { + BrotliDestroyEncoderDictionary(m, &dict->contextual.instances_[i]); + } + BrotliFree(m, dict->contextual.instances_); + } +} + +ManagedDictionary* duckdb_brotli::BrotliCreateManagedDictionary( + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { + ManagedDictionary* result = (ManagedDictionary*)BrotliBootstrapAlloc( + sizeof(ManagedDictionary), alloc_func, free_func, opaque); + if (result == NULL) return NULL; + + result->magic = kManagedDictionaryMagic; + BrotliInitMemoryManager( + &result->memory_manager_, alloc_func, free_func, opaque); + result->dictionary = NULL; + + return result; +} + +void duckdb_brotli::BrotliDestroyManagedDictionary(ManagedDictionary* dictionary) { + if (!dictionary) return; + BrotliBootstrapFree(dictionary, &dictionary->memory_manager_); +} + +/* Escalate internal functions visibility; for testing purposes only. */ +#if defined(BROTLI_TEST) +void InitEncoderDictionaryForTest(BrotliEncoderDictionary*); +void InitEncoderDictionaryForTest(BrotliEncoderDictionary* d) { + InitEncoderDictionary(d); +} +#endif + + diff --git a/third_party/brotli/enc/encoder_dict.h b/third_party/brotli/enc/encoder_dict.h new file mode 100644 index 00000000000..99a82a6e615 --- /dev/null +++ b/third_party/brotli/enc/encoder_dict.h @@ -0,0 +1,153 @@ +/* Copyright 2017 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#ifndef BROTLI_ENC_ENCODER_DICT_H_ +#define BROTLI_ENC_ENCODER_DICT_H_ + +#include +#include + +#include "../common/dictionary.h" +#include "../common/brotli_platform.h" +#include "compound_dictionary.h" +#include "memory.h" +#include "static_dict_lut.h" + +namespace duckdb_brotli { + +/* +Dictionary hierarchy for Encoder: +-SharedEncoderDictionary +--CompoundDictionary +---PreparedDictionary [up to 15x] + = prefix dictionary with precomputed hashes +--ContextualEncoderDictionary +---BrotliEncoderDictionary [up to 64x] + = for each context, precomputed static dictionary with words + transforms + +Dictionary hiearchy from common: similar, but without precomputed hashes +-BrotliSharedDictionary +--BrotliDictionary [up to 64x] +--BrotliTransforms [up to 64x] +--const uint8_t* prefix [up to 15x]: compound dictionaries +*/ + +typedef struct BrotliTrieNode { + uint8_t single; /* if 1, sub is a single node for c instead of 256 */ + uint8_t c; + uint8_t len_; /* untransformed length */ + uint32_t idx_; /* word index + num words * transform index */ + uint32_t sub; /* index of sub node(s) in the pool */ +} BrotliTrieNode; + +typedef struct BrotliTrie { + BrotliTrieNode* pool; + size_t pool_capacity; + size_t pool_size; + BrotliTrieNode root; +} BrotliTrie; + +#if defined(BROTLI_EXPERIMENTAL) +BROTLI_INTERNAL const BrotliTrieNode* BrotliTrieSub(const BrotliTrie* trie, + const BrotliTrieNode* node, uint8_t c); +#endif /* BROTLI_EXPERIMENTAL */ + +/* Dictionary data (words and transforms) for 1 possible context */ +typedef struct BrotliEncoderDictionary { + const BrotliDictionary* words; + uint32_t num_transforms; + + /* cut off for fast encoder */ + uint32_t cutoffTransformsCount; + uint64_t cutoffTransforms; + + /* from dictionary_hash.h, for fast encoder */ + const uint16_t* hash_table_words; + const uint8_t* hash_table_lengths; + + /* from static_dict_lut.h, for slow encoder */ + const uint16_t* buckets; + const DictWord* dict_words; + /* Heavy version, for use by slow encoder when there are custom transforms. + Contains every possible transformed dictionary word in a trie. It encodes + about as fast as the non-heavy encoder but consumes a lot of memory and + takes time to build. */ + BrotliTrie trie; + BROTLI_BOOL has_words_heavy; + + /* Reference to other dictionaries. */ + const struct ContextualEncoderDictionary* parent; + + /* Allocated memory, used only when not using the Brotli defaults */ + uint16_t* hash_table_data_words_; + uint8_t* hash_table_data_lengths_; + size_t buckets_alloc_size_; + uint16_t* buckets_data_; + size_t dict_words_alloc_size_; + DictWord* dict_words_data_; + BrotliDictionary* words_instance_; +} BrotliEncoderDictionary; + +/* Dictionary data for all 64 contexts */ +typedef struct ContextualEncoderDictionary { + BROTLI_BOOL context_based; + uint8_t num_dictionaries; + uint8_t context_map[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; + const BrotliEncoderDictionary* dict[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS]; + + /* If num_instances_ is 1, instance_ is used, else dynamic allocation with + instances_ is used. */ + size_t num_instances_; + BrotliEncoderDictionary instance_; + BrotliEncoderDictionary* instances_; +} ContextualEncoderDictionary; + +typedef struct SharedEncoderDictionary { + /* Magic value to distinguish this struct from PreparedDictionary for + certain external usages. */ + uint32_t magic; + + /* LZ77 prefix, compound dictionary */ + CompoundDictionary compound; + + /* Custom static dictionary (optionally context-based) */ + ContextualEncoderDictionary contextual; + + /* The maximum quality the dictionary was computed for */ + int max_quality; +} SharedEncoderDictionary; + +typedef struct ManagedDictionary { + uint32_t magic; + MemoryManager memory_manager_; + uint32_t* dictionary; +} ManagedDictionary; + +/* Initializes to the brotli built-in dictionary */ +BROTLI_INTERNAL void BrotliInitSharedEncoderDictionary( + SharedEncoderDictionary* dict); + +#if defined(BROTLI_EXPERIMENTAL) +/* Initializes to shared dictionary that will be parsed from + encoded_dict. Requires that you keep the encoded_dict buffer + around, parts of data will point to it. */ +BROTLI_INTERNAL BROTLI_BOOL BrotliInitCustomSharedEncoderDictionary( + MemoryManager* m, const uint8_t* encoded_dict, size_t size, + int quality, SharedEncoderDictionary* dict); +#endif /* BROTLI_EXPERIMENTAL */ + +BROTLI_INTERNAL void BrotliCleanupSharedEncoderDictionary( + MemoryManager* m, SharedEncoderDictionary* dict); + +BROTLI_INTERNAL ManagedDictionary* BrotliCreateManagedDictionary( + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); + +BROTLI_INTERNAL void BrotliDestroyManagedDictionary( + ManagedDictionary* dictionary); + +} + +#endif /* BROTLI_ENC_ENCODER_DICT_H_ */ diff --git a/third_party/brotli/enc/entropy_encode.cpp b/third_party/brotli/enc/entropy_encode.cpp new file mode 100644 index 00000000000..e56f820465f --- /dev/null +++ b/third_party/brotli/enc/entropy_encode.cpp @@ -0,0 +1,500 @@ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Entropy encoding (Huffman) utilities. */ + +#include "entropy_encode.h" + +#include /* memset */ + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" + +using namespace duckdb_brotli; + +const size_t duckdb_brotli::kBrotliShellGaps[] = {132, 57, 23, 10, 4, 1}; + +BROTLI_BOOL duckdb_brotli::BrotliSetDepth( + int p0, HuffmanTree* pool, uint8_t* depth, int max_depth) { + int stack[16]; + int level = 0; + int p = p0; + BROTLI_DCHECK(max_depth <= 15); + stack[0] = -1; + while (BROTLI_TRUE) { + if (pool[p].index_left_ >= 0) { + level++; + if (level > max_depth) return BROTLI_FALSE; + stack[level] = pool[p].index_right_or_value_; + p = pool[p].index_left_; + continue; + } else { + depth[pool[p].index_right_or_value_] = (uint8_t)level; + } + while (level >= 0 && stack[level] == -1) level--; + if (level < 0) return BROTLI_TRUE; + p = stack[level]; + stack[level] = -1; + } +} + +/* Sort the root nodes, least popular first. */ +static BROTLI_INLINE BROTLI_BOOL SortHuffmanTree( + const HuffmanTree* v0, const HuffmanTree* v1) { + if (v0->total_count_ != v1->total_count_) { + return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_); + } + return TO_BROTLI_BOOL(v0->index_right_or_value_ > v1->index_right_or_value_); +} + +/* This function will create a Huffman tree. + + The catch here is that the tree cannot be arbitrarily deep. + Brotli specifies a maximum depth of 15 bits for "code trees" + and 7 bits for "code length code trees." + + count_limit is the value that is to be faked as the minimum value + and this minimum value is raised until the tree matches the + maximum length requirement. + + This algorithm is not of excellent performance for very long data blocks, + especially when population counts are longer than 2**tree_limit, but + we are not planning to use this with extremely long blocks. + + See http://en.wikipedia.org/wiki/Huffman_coding */ +void duckdb_brotli::BrotliCreateHuffmanTree(const uint32_t* data, + const size_t length, + const int tree_limit, + HuffmanTree* tree, + uint8_t* depth) { + uint32_t count_limit; + HuffmanTree sentinel; + InitHuffmanTree(&sentinel, BROTLI_UINT32_MAX, -1, -1); + /* For block sizes below 64 kB, we never need to do a second iteration + of this loop. Probably all of our block sizes will be smaller than + that, so this loop is mostly of academic interest. If we actually + would need this, we would be better off with the Katajainen algorithm. */ + for (count_limit = 1; ; count_limit *= 2) { + size_t n = 0; + size_t i; + size_t j; + size_t k; + for (i = length; i != 0;) { + --i; + if (data[i]) { + const uint32_t count = BROTLI_MAX(uint32_t, data[i], count_limit); + InitHuffmanTree(&tree[n++], count, -1, (int16_t)i); + } + } + + if (n == 1) { + depth[tree[0].index_right_or_value_] = 1; /* Only one element. */ + break; + } + + SortHuffmanTreeItems(tree, n, SortHuffmanTree); + + /* The nodes are: + [0, n): the sorted leaf nodes that we start with. + [n]: we add a sentinel here. + [n + 1, 2n): new parent nodes are added here, starting from + (n+1). These are naturally in ascending order. + [2n]: we add a sentinel at the end as well. + There will be (2n+1) elements at the end. */ + tree[n] = sentinel; + tree[n + 1] = sentinel; + + i = 0; /* Points to the next leaf node. */ + j = n + 1; /* Points to the next non-leaf node. */ + for (k = n - 1; k != 0; --k) { + size_t left, right; + if (tree[i].total_count_ <= tree[j].total_count_) { + left = i; + ++i; + } else { + left = j; + ++j; + } + if (tree[i].total_count_ <= tree[j].total_count_) { + right = i; + ++i; + } else { + right = j; + ++j; + } + + { + /* The sentinel node becomes the parent node. */ + size_t j_end = 2 * n - k; + tree[j_end].total_count_ = + tree[left].total_count_ + tree[right].total_count_; + tree[j_end].index_left_ = (int16_t)left; + tree[j_end].index_right_or_value_ = (int16_t)right; + + /* Add back the last sentinel node. */ + tree[j_end + 1] = sentinel; + } + } + if (BrotliSetDepth((int)(2 * n - 1), &tree[0], depth, tree_limit)) { + /* We need to pack the Huffman tree in tree_limit bits. If this was not + successful, add fake entities to the lowest values and retry. */ + break; + } + } +} + +static void Reverse(uint8_t* v, size_t start, size_t end) { + --end; + while (start < end) { + uint8_t tmp = v[start]; + v[start] = v[end]; + v[end] = tmp; + ++start; + --end; + } +} + +static void BrotliWriteHuffmanTreeRepetitions( + const uint8_t previous_value, + const uint8_t value, + size_t repetitions, + size_t* tree_size, + uint8_t* tree, + uint8_t* extra_bits_data) { + BROTLI_DCHECK(repetitions > 0); + if (previous_value != value) { + tree[*tree_size] = value; + extra_bits_data[*tree_size] = 0; + ++(*tree_size); + --repetitions; + } + if (repetitions == 7) { + tree[*tree_size] = value; + extra_bits_data[*tree_size] = 0; + ++(*tree_size); + --repetitions; + } + if (repetitions < 3) { + size_t i; + for (i = 0; i < repetitions; ++i) { + tree[*tree_size] = value; + extra_bits_data[*tree_size] = 0; + ++(*tree_size); + } + } else { + size_t start = *tree_size; + repetitions -= 3; + while (BROTLI_TRUE) { + tree[*tree_size] = BROTLI_REPEAT_PREVIOUS_CODE_LENGTH; + extra_bits_data[*tree_size] = repetitions & 0x3; + ++(*tree_size); + repetitions >>= 2; + if (repetitions == 0) { + break; + } + --repetitions; + } + Reverse(tree, start, *tree_size); + Reverse(extra_bits_data, start, *tree_size); + } +} + +static void BrotliWriteHuffmanTreeRepetitionsZeros( + size_t repetitions, + size_t* tree_size, + uint8_t* tree, + uint8_t* extra_bits_data) { + if (repetitions == 11) { + tree[*tree_size] = 0; + extra_bits_data[*tree_size] = 0; + ++(*tree_size); + --repetitions; + } + if (repetitions < 3) { + size_t i; + for (i = 0; i < repetitions; ++i) { + tree[*tree_size] = 0; + extra_bits_data[*tree_size] = 0; + ++(*tree_size); + } + } else { + size_t start = *tree_size; + repetitions -= 3; + while (BROTLI_TRUE) { + tree[*tree_size] = BROTLI_REPEAT_ZERO_CODE_LENGTH; + extra_bits_data[*tree_size] = repetitions & 0x7; + ++(*tree_size); + repetitions >>= 3; + if (repetitions == 0) { + break; + } + --repetitions; + } + Reverse(tree, start, *tree_size); + Reverse(extra_bits_data, start, *tree_size); + } +} + +void duckdb_brotli::BrotliOptimizeHuffmanCountsForRle(size_t length, uint32_t* counts, + uint8_t* good_for_rle) { + size_t nonzero_count = 0; + size_t stride; + size_t limit; + size_t sum; + const size_t streak_limit = 1240; + /* Let's make the Huffman code more compatible with RLE encoding. */ + size_t i; + for (i = 0; i < length; i++) { + if (counts[i]) { + ++nonzero_count; + } + } + if (nonzero_count < 16) { + return; + } + while (length != 0 && counts[length - 1] == 0) { + --length; + } + if (length == 0) { + return; /* All zeros. */ + } + /* Now counts[0..length - 1] does not have trailing zeros. */ + { + size_t nonzeros = 0; + uint32_t smallest_nonzero = 1 << 30; + for (i = 0; i < length; ++i) { + if (counts[i] != 0) { + ++nonzeros; + if (smallest_nonzero > counts[i]) { + smallest_nonzero = counts[i]; + } + } + } + if (nonzeros < 5) { + /* Small histogram will model it well. */ + return; + } + if (smallest_nonzero < 4) { + size_t zeros = length - nonzeros; + if (zeros < 6) { + for (i = 1; i < length - 1; ++i) { + if (counts[i - 1] != 0 && counts[i] == 0 && counts[i + 1] != 0) { + counts[i] = 1; + } + } + } + } + if (nonzeros < 28) { + return; + } + } + /* 2) Let's mark all population counts that already can be encoded + with an RLE code. */ + memset(good_for_rle, 0, length); + { + /* Let's not spoil any of the existing good RLE codes. + Mark any seq of 0's that is longer as 5 as a good_for_rle. + Mark any seq of non-0's that is longer as 7 as a good_for_rle. */ + uint32_t symbol = counts[0]; + size_t step = 0; + for (i = 0; i <= length; ++i) { + if (i == length || counts[i] != symbol) { + if ((symbol == 0 && step >= 5) || + (symbol != 0 && step >= 7)) { + size_t k; + for (k = 0; k < step; ++k) { + good_for_rle[i - k - 1] = 1; + } + } + step = 1; + if (i != length) { + symbol = counts[i]; + } + } else { + ++step; + } + } + } + /* 3) Let's replace those population counts that lead to more RLE codes. + Math here is in 24.8 fixed point representation. */ + stride = 0; + limit = 256 * (counts[0] + counts[1] + counts[2]) / 3 + 420; + sum = 0; + for (i = 0; i <= length; ++i) { + if (i == length || good_for_rle[i] || + (i != 0 && good_for_rle[i - 1]) || + (256 * counts[i] - limit + streak_limit) >= 2 * streak_limit) { + if (stride >= 4 || (stride >= 3 && sum == 0)) { + size_t k; + /* The stride must end, collapse what we have, if we have enough (4). */ + size_t count = (sum + stride / 2) / stride; + if (count == 0) { + count = 1; + } + if (sum == 0) { + /* Don't make an all zeros stride to be upgraded to ones. */ + count = 0; + } + for (k = 0; k < stride; ++k) { + /* We don't want to change value at counts[i], + that is already belonging to the next stride. Thus - 1. */ + counts[i - k - 1] = (uint32_t)count; + } + } + stride = 0; + sum = 0; + if (i < length - 2) { + /* All interesting strides have a count of at least 4, */ + /* at least when non-zeros. */ + limit = 256 * (counts[i] + counts[i + 1] + counts[i + 2]) / 3 + 420; + } else if (i < length) { + limit = 256 * counts[i]; + } else { + limit = 0; + } + } + ++stride; + if (i != length) { + sum += counts[i]; + if (stride >= 4) { + limit = (256 * sum + stride / 2) / stride; + } + if (stride == 4) { + limit += 120; + } + } + } +} + +static void DecideOverRleUse(const uint8_t* depth, const size_t length, + BROTLI_BOOL* use_rle_for_non_zero, + BROTLI_BOOL* use_rle_for_zero) { + size_t total_reps_zero = 0; + size_t total_reps_non_zero = 0; + size_t count_reps_zero = 1; + size_t count_reps_non_zero = 1; + size_t i; + for (i = 0; i < length;) { + const uint8_t value = depth[i]; + size_t reps = 1; + size_t k; + for (k = i + 1; k < length && depth[k] == value; ++k) { + ++reps; + } + if (reps >= 3 && value == 0) { + total_reps_zero += reps; + ++count_reps_zero; + } + if (reps >= 4 && value != 0) { + total_reps_non_zero += reps; + ++count_reps_non_zero; + } + i += reps; + } + *use_rle_for_non_zero = + TO_BROTLI_BOOL(total_reps_non_zero > count_reps_non_zero * 2); + *use_rle_for_zero = TO_BROTLI_BOOL(total_reps_zero > count_reps_zero * 2); +} + +void duckdb_brotli::BrotliWriteHuffmanTree(const uint8_t* depth, + size_t length, + size_t* tree_size, + uint8_t* tree, + uint8_t* extra_bits_data) { + uint8_t previous_value = BROTLI_INITIAL_REPEATED_CODE_LENGTH; + size_t i; + BROTLI_BOOL use_rle_for_non_zero = BROTLI_FALSE; + BROTLI_BOOL use_rle_for_zero = BROTLI_FALSE; + + /* Throw away trailing zeros. */ + size_t new_length = length; + for (i = 0; i < length; ++i) { + if (depth[length - i - 1] == 0) { + --new_length; + } else { + break; + } + } + + /* First gather statistics on if it is a good idea to do RLE. */ + if (length > 50) { + /* Find RLE coding for longer codes. + Shorter codes seem not to benefit from RLE. */ + DecideOverRleUse(depth, new_length, + &use_rle_for_non_zero, &use_rle_for_zero); + } + + /* Actual RLE coding. */ + for (i = 0; i < new_length;) { + const uint8_t value = depth[i]; + size_t reps = 1; + if ((value != 0 && use_rle_for_non_zero) || + (value == 0 && use_rle_for_zero)) { + size_t k; + for (k = i + 1; k < new_length && depth[k] == value; ++k) { + ++reps; + } + } + if (value == 0) { + BrotliWriteHuffmanTreeRepetitionsZeros( + reps, tree_size, tree, extra_bits_data); + } else { + BrotliWriteHuffmanTreeRepetitions(previous_value, + value, reps, tree_size, + tree, extra_bits_data); + previous_value = value; + } + i += reps; + } +} + +static uint16_t BrotliReverseBits(size_t num_bits, uint16_t bits) { + static const size_t kLut[16] = { /* Pre-reversed 4-bit values. */ + 0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, + 0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F + }; + size_t retval = kLut[bits & 0x0F]; + size_t i; + for (i = 4; i < num_bits; i += 4) { + retval <<= 4; + bits = (uint16_t)(bits >> 4); + retval |= kLut[bits & 0x0F]; + } + retval >>= ((0 - num_bits) & 0x03); + return (uint16_t)retval; +} + +/* 0..15 are values for bits */ +#define MAX_HUFFMAN_BITS 16 + +void duckdb_brotli::BrotliConvertBitDepthsToSymbols(const uint8_t* depth, + size_t len, + uint16_t* bits) { + /* In Brotli, all bit depths are [1..15] + 0 bit depth means that the symbol does not exist. */ + uint16_t bl_count[MAX_HUFFMAN_BITS] = { 0 }; + uint16_t next_code[MAX_HUFFMAN_BITS]; + size_t i; + int code = 0; + for (i = 0; i < len; ++i) { + ++bl_count[depth[i]]; + } + bl_count[0] = 0; + next_code[0] = 0; + for (i = 1; i < MAX_HUFFMAN_BITS; ++i) { + code = (code + bl_count[i - 1]) << 1; + next_code[i] = (uint16_t)code; + } + for (i = 0; i < len; ++i) { + if (depth[i]) { + bits[i] = BrotliReverseBits(depth[i], next_code[depth[i]]++); + } + } +} + + diff --git a/third_party/brotli/enc/entropy_encode.h b/third_party/brotli/enc/entropy_encode.h new file mode 100644 index 00000000000..ade29d513ff --- /dev/null +++ b/third_party/brotli/enc/entropy_encode.h @@ -0,0 +1,119 @@ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Entropy encoding (Huffman) utilities. */ + +#ifndef BROTLI_ENC_ENTROPY_ENCODE_H_ +#define BROTLI_ENC_ENTROPY_ENCODE_H_ + +#include + +#include "../common/brotli_platform.h" + +namespace duckdb_brotli { + +/* A node of a Huffman tree. */ +typedef struct HuffmanTree { + uint32_t total_count_; + int16_t index_left_; + int16_t index_right_or_value_; +} HuffmanTree; + +static BROTLI_INLINE void InitHuffmanTree(HuffmanTree* self, uint32_t count, + int16_t left, int16_t right) { + self->total_count_ = count; + self->index_left_ = left; + self->index_right_or_value_ = right; +} + +/* Returns 1 is assignment of depths succeeded, otherwise 0. */ +BROTLI_INTERNAL BROTLI_BOOL BrotliSetDepth( + int p, HuffmanTree* pool, uint8_t* depth, int max_depth); + +/* This function will create a Huffman tree. + + The (data,length) contains the population counts. + The tree_limit is the maximum bit depth of the Huffman codes. + + The depth contains the tree, i.e., how many bits are used for + the symbol. + + The actual Huffman tree is constructed in the tree[] array, which has to + be at least 2 * length + 1 long. + + See http://en.wikipedia.org/wiki/Huffman_coding */ +BROTLI_INTERNAL void BrotliCreateHuffmanTree(const uint32_t* data, + const size_t length, + const int tree_limit, + HuffmanTree* tree, + uint8_t* depth); + +/* Change the population counts in a way that the consequent + Huffman tree compression, especially its RLE-part will be more + likely to compress this data more efficiently. + + length contains the size of the histogram. + counts contains the population counts. + good_for_rle is a buffer of at least length size */ +BROTLI_INTERNAL void BrotliOptimizeHuffmanCountsForRle( + size_t length, uint32_t* counts, uint8_t* good_for_rle); + +/* Write a Huffman tree from bit depths into the bit-stream representation + of a Huffman tree. The generated Huffman tree is to be compressed once + more using a Huffman tree */ +BROTLI_INTERNAL void BrotliWriteHuffmanTree(const uint8_t* depth, + size_t num, + size_t* tree_size, + uint8_t* tree, + uint8_t* extra_bits_data); + +/* Get the actual bit values for a tree of bit depths. */ +BROTLI_INTERNAL void BrotliConvertBitDepthsToSymbols(const uint8_t* depth, + size_t len, + uint16_t* bits); + +BROTLI_INTERNAL extern const size_t kBrotliShellGaps[6]; +/* Input size optimized Shell sort. */ +typedef BROTLI_BOOL (*HuffmanTreeComparator)( + const HuffmanTree*, const HuffmanTree*); +static BROTLI_INLINE void SortHuffmanTreeItems(HuffmanTree* items, + const size_t n, HuffmanTreeComparator comparator) { + if (n < 13) { + /* Insertion sort. */ + size_t i; + for (i = 1; i < n; ++i) { + HuffmanTree tmp = items[i]; + size_t k = i; + size_t j = i - 1; + while (comparator(&tmp, &items[j])) { + items[k] = items[j]; + k = j; + if (!j--) break; + } + items[k] = tmp; + } + return; + } else { + /* Shell sort. */ + int g = n < 57 ? 2 : 0; + for (; g < 6; ++g) { + size_t gap = kBrotliShellGaps[g]; + size_t i; + for (i = gap; i < n; ++i) { + size_t j = i; + HuffmanTree tmp = items[i]; + for (; j >= gap && comparator(&tmp, &items[j - gap]); j -= gap) { + items[j] = items[j - gap]; + } + items[j] = tmp; + } + } + } +} + +} + +#endif /* BROTLI_ENC_ENTROPY_ENCODE_H_ */ diff --git a/third_party/brotli/enc/entropy_encode_static.h b/third_party/brotli/enc/entropy_encode_static.h new file mode 100644 index 00000000000..860a3782054 --- /dev/null +++ b/third_party/brotli/enc/entropy_encode_static.h @@ -0,0 +1,538 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Static entropy codes used for faster meta-block encoding. */ + +#ifndef BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_ +#define BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_ + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" +#include "write_bits.h" + +namespace duckdb_brotli { + +static const uint8_t kCodeLengthDepth[18] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 0, 4, 4, +}; + +static const uint8_t kStaticCommandCodeDepth[BROTLI_NUM_COMMAND_SYMBOLS] = { + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +}; + +static const uint8_t kStaticDistanceCodeDepth[64] = { + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +}; + +/* GENERATED CODE START */ +static const uint32_t kCodeLengthBits[18] = { + 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 15, 31, 0, 11, 7, +}; + +static BROTLI_INLINE void StoreStaticCodeLengthCode( + size_t* storage_ix, uint8_t* storage) { + BrotliWriteBits( + 40, BROTLI_MAKE_UINT64_T(0x0000FFu, 0x55555554u), storage_ix, storage); +} + +static const uint64_t kZeroRepsBits[BROTLI_NUM_COMMAND_SYMBOLS] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x00000017, 0x00000027, + 0x00000037, 0x00000047, 0x00000057, 0x00000067, 0x00000077, 0x00000770, + 0x00000b87, 0x00001387, 0x00001b87, 0x00002387, 0x00002b87, 0x00003387, + 0x00003b87, 0x00000397, 0x00000b97, 0x00001397, 0x00001b97, 0x00002397, + 0x00002b97, 0x00003397, 0x00003b97, 0x000003a7, 0x00000ba7, 0x000013a7, + 0x00001ba7, 0x000023a7, 0x00002ba7, 0x000033a7, 0x00003ba7, 0x000003b7, + 0x00000bb7, 0x000013b7, 0x00001bb7, 0x000023b7, 0x00002bb7, 0x000033b7, + 0x00003bb7, 0x000003c7, 0x00000bc7, 0x000013c7, 0x00001bc7, 0x000023c7, + 0x00002bc7, 0x000033c7, 0x00003bc7, 0x000003d7, 0x00000bd7, 0x000013d7, + 0x00001bd7, 0x000023d7, 0x00002bd7, 0x000033d7, 0x00003bd7, 0x000003e7, + 0x00000be7, 0x000013e7, 0x00001be7, 0x000023e7, 0x00002be7, 0x000033e7, + 0x00003be7, 0x000003f7, 0x00000bf7, 0x000013f7, 0x00001bf7, 0x000023f7, + 0x00002bf7, 0x000033f7, 0x00003bf7, 0x0001c387, 0x0005c387, 0x0009c387, + 0x000dc387, 0x0011c387, 0x0015c387, 0x0019c387, 0x001dc387, 0x0001cb87, + 0x0005cb87, 0x0009cb87, 0x000dcb87, 0x0011cb87, 0x0015cb87, 0x0019cb87, + 0x001dcb87, 0x0001d387, 0x0005d387, 0x0009d387, 0x000dd387, 0x0011d387, + 0x0015d387, 0x0019d387, 0x001dd387, 0x0001db87, 0x0005db87, 0x0009db87, + 0x000ddb87, 0x0011db87, 0x0015db87, 0x0019db87, 0x001ddb87, 0x0001e387, + 0x0005e387, 0x0009e387, 0x000de387, 0x0011e387, 0x0015e387, 0x0019e387, + 0x001de387, 0x0001eb87, 0x0005eb87, 0x0009eb87, 0x000deb87, 0x0011eb87, + 0x0015eb87, 0x0019eb87, 0x001deb87, 0x0001f387, 0x0005f387, 0x0009f387, + 0x000df387, 0x0011f387, 0x0015f387, 0x0019f387, 0x001df387, 0x0001fb87, + 0x0005fb87, 0x0009fb87, 0x000dfb87, 0x0011fb87, 0x0015fb87, 0x0019fb87, + 0x001dfb87, 0x0001c397, 0x0005c397, 0x0009c397, 0x000dc397, 0x0011c397, + 0x0015c397, 0x0019c397, 0x001dc397, 0x0001cb97, 0x0005cb97, 0x0009cb97, + 0x000dcb97, 0x0011cb97, 0x0015cb97, 0x0019cb97, 0x001dcb97, 0x0001d397, + 0x0005d397, 0x0009d397, 0x000dd397, 0x0011d397, 0x0015d397, 0x0019d397, + 0x001dd397, 0x0001db97, 0x0005db97, 0x0009db97, 0x000ddb97, 0x0011db97, + 0x0015db97, 0x0019db97, 0x001ddb97, 0x0001e397, 0x0005e397, 0x0009e397, + 0x000de397, 0x0011e397, 0x0015e397, 0x0019e397, 0x001de397, 0x0001eb97, + 0x0005eb97, 0x0009eb97, 0x000deb97, 0x0011eb97, 0x0015eb97, 0x0019eb97, + 0x001deb97, 0x0001f397, 0x0005f397, 0x0009f397, 0x000df397, 0x0011f397, + 0x0015f397, 0x0019f397, 0x001df397, 0x0001fb97, 0x0005fb97, 0x0009fb97, + 0x000dfb97, 0x0011fb97, 0x0015fb97, 0x0019fb97, 0x001dfb97, 0x0001c3a7, + 0x0005c3a7, 0x0009c3a7, 0x000dc3a7, 0x0011c3a7, 0x0015c3a7, 0x0019c3a7, + 0x001dc3a7, 0x0001cba7, 0x0005cba7, 0x0009cba7, 0x000dcba7, 0x0011cba7, + 0x0015cba7, 0x0019cba7, 0x001dcba7, 0x0001d3a7, 0x0005d3a7, 0x0009d3a7, + 0x000dd3a7, 0x0011d3a7, 0x0015d3a7, 0x0019d3a7, 0x001dd3a7, 0x0001dba7, + 0x0005dba7, 0x0009dba7, 0x000ddba7, 0x0011dba7, 0x0015dba7, 0x0019dba7, + 0x001ddba7, 0x0001e3a7, 0x0005e3a7, 0x0009e3a7, 0x000de3a7, 0x0011e3a7, + 0x0015e3a7, 0x0019e3a7, 0x001de3a7, 0x0001eba7, 0x0005eba7, 0x0009eba7, + 0x000deba7, 0x0011eba7, 0x0015eba7, 0x0019eba7, 0x001deba7, 0x0001f3a7, + 0x0005f3a7, 0x0009f3a7, 0x000df3a7, 0x0011f3a7, 0x0015f3a7, 0x0019f3a7, + 0x001df3a7, 0x0001fba7, 0x0005fba7, 0x0009fba7, 0x000dfba7, 0x0011fba7, + 0x0015fba7, 0x0019fba7, 0x001dfba7, 0x0001c3b7, 0x0005c3b7, 0x0009c3b7, + 0x000dc3b7, 0x0011c3b7, 0x0015c3b7, 0x0019c3b7, 0x001dc3b7, 0x0001cbb7, + 0x0005cbb7, 0x0009cbb7, 0x000dcbb7, 0x0011cbb7, 0x0015cbb7, 0x0019cbb7, + 0x001dcbb7, 0x0001d3b7, 0x0005d3b7, 0x0009d3b7, 0x000dd3b7, 0x0011d3b7, + 0x0015d3b7, 0x0019d3b7, 0x001dd3b7, 0x0001dbb7, 0x0005dbb7, 0x0009dbb7, + 0x000ddbb7, 0x0011dbb7, 0x0015dbb7, 0x0019dbb7, 0x001ddbb7, 0x0001e3b7, + 0x0005e3b7, 0x0009e3b7, 0x000de3b7, 0x0011e3b7, 0x0015e3b7, 0x0019e3b7, + 0x001de3b7, 0x0001ebb7, 0x0005ebb7, 0x0009ebb7, 0x000debb7, 0x0011ebb7, + 0x0015ebb7, 0x0019ebb7, 0x001debb7, 0x0001f3b7, 0x0005f3b7, 0x0009f3b7, + 0x000df3b7, 0x0011f3b7, 0x0015f3b7, 0x0019f3b7, 0x001df3b7, 0x0001fbb7, + 0x0005fbb7, 0x0009fbb7, 0x000dfbb7, 0x0011fbb7, 0x0015fbb7, 0x0019fbb7, + 0x001dfbb7, 0x0001c3c7, 0x0005c3c7, 0x0009c3c7, 0x000dc3c7, 0x0011c3c7, + 0x0015c3c7, 0x0019c3c7, 0x001dc3c7, 0x0001cbc7, 0x0005cbc7, 0x0009cbc7, + 0x000dcbc7, 0x0011cbc7, 0x0015cbc7, 0x0019cbc7, 0x001dcbc7, 0x0001d3c7, + 0x0005d3c7, 0x0009d3c7, 0x000dd3c7, 0x0011d3c7, 0x0015d3c7, 0x0019d3c7, + 0x001dd3c7, 0x0001dbc7, 0x0005dbc7, 0x0009dbc7, 0x000ddbc7, 0x0011dbc7, + 0x0015dbc7, 0x0019dbc7, 0x001ddbc7, 0x0001e3c7, 0x0005e3c7, 0x0009e3c7, + 0x000de3c7, 0x0011e3c7, 0x0015e3c7, 0x0019e3c7, 0x001de3c7, 0x0001ebc7, + 0x0005ebc7, 0x0009ebc7, 0x000debc7, 0x0011ebc7, 0x0015ebc7, 0x0019ebc7, + 0x001debc7, 0x0001f3c7, 0x0005f3c7, 0x0009f3c7, 0x000df3c7, 0x0011f3c7, + 0x0015f3c7, 0x0019f3c7, 0x001df3c7, 0x0001fbc7, 0x0005fbc7, 0x0009fbc7, + 0x000dfbc7, 0x0011fbc7, 0x0015fbc7, 0x0019fbc7, 0x001dfbc7, 0x0001c3d7, + 0x0005c3d7, 0x0009c3d7, 0x000dc3d7, 0x0011c3d7, 0x0015c3d7, 0x0019c3d7, + 0x001dc3d7, 0x0001cbd7, 0x0005cbd7, 0x0009cbd7, 0x000dcbd7, 0x0011cbd7, + 0x0015cbd7, 0x0019cbd7, 0x001dcbd7, 0x0001d3d7, 0x0005d3d7, 0x0009d3d7, + 0x000dd3d7, 0x0011d3d7, 0x0015d3d7, 0x0019d3d7, 0x001dd3d7, 0x0001dbd7, + 0x0005dbd7, 0x0009dbd7, 0x000ddbd7, 0x0011dbd7, 0x0015dbd7, 0x0019dbd7, + 0x001ddbd7, 0x0001e3d7, 0x0005e3d7, 0x0009e3d7, 0x000de3d7, 0x0011e3d7, + 0x0015e3d7, 0x0019e3d7, 0x001de3d7, 0x0001ebd7, 0x0005ebd7, 0x0009ebd7, + 0x000debd7, 0x0011ebd7, 0x0015ebd7, 0x0019ebd7, 0x001debd7, 0x0001f3d7, + 0x0005f3d7, 0x0009f3d7, 0x000df3d7, 0x0011f3d7, 0x0015f3d7, 0x0019f3d7, + 0x001df3d7, 0x0001fbd7, 0x0005fbd7, 0x0009fbd7, 0x000dfbd7, 0x0011fbd7, + 0x0015fbd7, 0x0019fbd7, 0x001dfbd7, 0x0001c3e7, 0x0005c3e7, 0x0009c3e7, + 0x000dc3e7, 0x0011c3e7, 0x0015c3e7, 0x0019c3e7, 0x001dc3e7, 0x0001cbe7, + 0x0005cbe7, 0x0009cbe7, 0x000dcbe7, 0x0011cbe7, 0x0015cbe7, 0x0019cbe7, + 0x001dcbe7, 0x0001d3e7, 0x0005d3e7, 0x0009d3e7, 0x000dd3e7, 0x0011d3e7, + 0x0015d3e7, 0x0019d3e7, 0x001dd3e7, 0x0001dbe7, 0x0005dbe7, 0x0009dbe7, + 0x000ddbe7, 0x0011dbe7, 0x0015dbe7, 0x0019dbe7, 0x001ddbe7, 0x0001e3e7, + 0x0005e3e7, 0x0009e3e7, 0x000de3e7, 0x0011e3e7, 0x0015e3e7, 0x0019e3e7, + 0x001de3e7, 0x0001ebe7, 0x0005ebe7, 0x0009ebe7, 0x000debe7, 0x0011ebe7, + 0x0015ebe7, 0x0019ebe7, 0x001debe7, 0x0001f3e7, 0x0005f3e7, 0x0009f3e7, + 0x000df3e7, 0x0011f3e7, 0x0015f3e7, 0x0019f3e7, 0x001df3e7, 0x0001fbe7, + 0x0005fbe7, 0x0009fbe7, 0x000dfbe7, 0x0011fbe7, 0x0015fbe7, 0x0019fbe7, + 0x001dfbe7, 0x0001c3f7, 0x0005c3f7, 0x0009c3f7, 0x000dc3f7, 0x0011c3f7, + 0x0015c3f7, 0x0019c3f7, 0x001dc3f7, 0x0001cbf7, 0x0005cbf7, 0x0009cbf7, + 0x000dcbf7, 0x0011cbf7, 0x0015cbf7, 0x0019cbf7, 0x001dcbf7, 0x0001d3f7, + 0x0005d3f7, 0x0009d3f7, 0x000dd3f7, 0x0011d3f7, 0x0015d3f7, 0x0019d3f7, + 0x001dd3f7, 0x0001dbf7, 0x0005dbf7, 0x0009dbf7, 0x000ddbf7, 0x0011dbf7, + 0x0015dbf7, 0x0019dbf7, 0x001ddbf7, 0x0001e3f7, 0x0005e3f7, 0x0009e3f7, + 0x000de3f7, 0x0011e3f7, 0x0015e3f7, 0x0019e3f7, 0x001de3f7, 0x0001ebf7, + 0x0005ebf7, 0x0009ebf7, 0x000debf7, 0x0011ebf7, 0x0015ebf7, 0x0019ebf7, + 0x001debf7, 0x0001f3f7, 0x0005f3f7, 0x0009f3f7, 0x000df3f7, 0x0011f3f7, + 0x0015f3f7, 0x0019f3f7, 0x001df3f7, 0x0001fbf7, 0x0005fbf7, 0x0009fbf7, + 0x000dfbf7, 0x0011fbf7, 0x0015fbf7, 0x0019fbf7, 0x001dfbf7, 0x00e1c387, + 0x02e1c387, 0x04e1c387, 0x06e1c387, 0x08e1c387, 0x0ae1c387, 0x0ce1c387, + 0x0ee1c387, 0x00e5c387, 0x02e5c387, 0x04e5c387, 0x06e5c387, 0x08e5c387, + 0x0ae5c387, 0x0ce5c387, 0x0ee5c387, 0x00e9c387, 0x02e9c387, 0x04e9c387, + 0x06e9c387, 0x08e9c387, 0x0ae9c387, 0x0ce9c387, 0x0ee9c387, 0x00edc387, + 0x02edc387, 0x04edc387, 0x06edc387, 0x08edc387, 0x0aedc387, 0x0cedc387, + 0x0eedc387, 0x00f1c387, 0x02f1c387, 0x04f1c387, 0x06f1c387, 0x08f1c387, + 0x0af1c387, 0x0cf1c387, 0x0ef1c387, 0x00f5c387, 0x02f5c387, 0x04f5c387, + 0x06f5c387, 0x08f5c387, 0x0af5c387, 0x0cf5c387, 0x0ef5c387, 0x00f9c387, + 0x02f9c387, 0x04f9c387, 0x06f9c387, 0x08f9c387, 0x0af9c387, 0x0cf9c387, + 0x0ef9c387, 0x00fdc387, 0x02fdc387, 0x04fdc387, 0x06fdc387, 0x08fdc387, + 0x0afdc387, 0x0cfdc387, 0x0efdc387, 0x00e1cb87, 0x02e1cb87, 0x04e1cb87, + 0x06e1cb87, 0x08e1cb87, 0x0ae1cb87, 0x0ce1cb87, 0x0ee1cb87, 0x00e5cb87, + 0x02e5cb87, 0x04e5cb87, 0x06e5cb87, 0x08e5cb87, 0x0ae5cb87, 0x0ce5cb87, + 0x0ee5cb87, 0x00e9cb87, 0x02e9cb87, 0x04e9cb87, 0x06e9cb87, 0x08e9cb87, + 0x0ae9cb87, 0x0ce9cb87, 0x0ee9cb87, 0x00edcb87, 0x02edcb87, 0x04edcb87, + 0x06edcb87, 0x08edcb87, 0x0aedcb87, 0x0cedcb87, 0x0eedcb87, 0x00f1cb87, + 0x02f1cb87, 0x04f1cb87, 0x06f1cb87, 0x08f1cb87, 0x0af1cb87, 0x0cf1cb87, + 0x0ef1cb87, 0x00f5cb87, 0x02f5cb87, 0x04f5cb87, 0x06f5cb87, 0x08f5cb87, + 0x0af5cb87, 0x0cf5cb87, 0x0ef5cb87, 0x00f9cb87, 0x02f9cb87, 0x04f9cb87, + 0x06f9cb87, 0x08f9cb87, +}; + +static const uint32_t kZeroRepsDepth[BROTLI_NUM_COMMAND_SYMBOLS] = { + 0, 4, 8, 7, 7, 7, 7, 7, 7, 7, 7, 11, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +}; + +static const uint64_t kNonZeroRepsBits[BROTLI_NUM_COMMAND_SYMBOLS] = { + 0x0000000b, 0x0000001b, 0x0000002b, 0x0000003b, 0x000002cb, 0x000006cb, + 0x00000acb, 0x00000ecb, 0x000002db, 0x000006db, 0x00000adb, 0x00000edb, + 0x000002eb, 0x000006eb, 0x00000aeb, 0x00000eeb, 0x000002fb, 0x000006fb, + 0x00000afb, 0x00000efb, 0x0000b2cb, 0x0001b2cb, 0x0002b2cb, 0x0003b2cb, + 0x0000b6cb, 0x0001b6cb, 0x0002b6cb, 0x0003b6cb, 0x0000bacb, 0x0001bacb, + 0x0002bacb, 0x0003bacb, 0x0000becb, 0x0001becb, 0x0002becb, 0x0003becb, + 0x0000b2db, 0x0001b2db, 0x0002b2db, 0x0003b2db, 0x0000b6db, 0x0001b6db, + 0x0002b6db, 0x0003b6db, 0x0000badb, 0x0001badb, 0x0002badb, 0x0003badb, + 0x0000bedb, 0x0001bedb, 0x0002bedb, 0x0003bedb, 0x0000b2eb, 0x0001b2eb, + 0x0002b2eb, 0x0003b2eb, 0x0000b6eb, 0x0001b6eb, 0x0002b6eb, 0x0003b6eb, + 0x0000baeb, 0x0001baeb, 0x0002baeb, 0x0003baeb, 0x0000beeb, 0x0001beeb, + 0x0002beeb, 0x0003beeb, 0x0000b2fb, 0x0001b2fb, 0x0002b2fb, 0x0003b2fb, + 0x0000b6fb, 0x0001b6fb, 0x0002b6fb, 0x0003b6fb, 0x0000bafb, 0x0001bafb, + 0x0002bafb, 0x0003bafb, 0x0000befb, 0x0001befb, 0x0002befb, 0x0003befb, + 0x002cb2cb, 0x006cb2cb, 0x00acb2cb, 0x00ecb2cb, 0x002db2cb, 0x006db2cb, + 0x00adb2cb, 0x00edb2cb, 0x002eb2cb, 0x006eb2cb, 0x00aeb2cb, 0x00eeb2cb, + 0x002fb2cb, 0x006fb2cb, 0x00afb2cb, 0x00efb2cb, 0x002cb6cb, 0x006cb6cb, + 0x00acb6cb, 0x00ecb6cb, 0x002db6cb, 0x006db6cb, 0x00adb6cb, 0x00edb6cb, + 0x002eb6cb, 0x006eb6cb, 0x00aeb6cb, 0x00eeb6cb, 0x002fb6cb, 0x006fb6cb, + 0x00afb6cb, 0x00efb6cb, 0x002cbacb, 0x006cbacb, 0x00acbacb, 0x00ecbacb, + 0x002dbacb, 0x006dbacb, 0x00adbacb, 0x00edbacb, 0x002ebacb, 0x006ebacb, + 0x00aebacb, 0x00eebacb, 0x002fbacb, 0x006fbacb, 0x00afbacb, 0x00efbacb, + 0x002cbecb, 0x006cbecb, 0x00acbecb, 0x00ecbecb, 0x002dbecb, 0x006dbecb, + 0x00adbecb, 0x00edbecb, 0x002ebecb, 0x006ebecb, 0x00aebecb, 0x00eebecb, + 0x002fbecb, 0x006fbecb, 0x00afbecb, 0x00efbecb, 0x002cb2db, 0x006cb2db, + 0x00acb2db, 0x00ecb2db, 0x002db2db, 0x006db2db, 0x00adb2db, 0x00edb2db, + 0x002eb2db, 0x006eb2db, 0x00aeb2db, 0x00eeb2db, 0x002fb2db, 0x006fb2db, + 0x00afb2db, 0x00efb2db, 0x002cb6db, 0x006cb6db, 0x00acb6db, 0x00ecb6db, + 0x002db6db, 0x006db6db, 0x00adb6db, 0x00edb6db, 0x002eb6db, 0x006eb6db, + 0x00aeb6db, 0x00eeb6db, 0x002fb6db, 0x006fb6db, 0x00afb6db, 0x00efb6db, + 0x002cbadb, 0x006cbadb, 0x00acbadb, 0x00ecbadb, 0x002dbadb, 0x006dbadb, + 0x00adbadb, 0x00edbadb, 0x002ebadb, 0x006ebadb, 0x00aebadb, 0x00eebadb, + 0x002fbadb, 0x006fbadb, 0x00afbadb, 0x00efbadb, 0x002cbedb, 0x006cbedb, + 0x00acbedb, 0x00ecbedb, 0x002dbedb, 0x006dbedb, 0x00adbedb, 0x00edbedb, + 0x002ebedb, 0x006ebedb, 0x00aebedb, 0x00eebedb, 0x002fbedb, 0x006fbedb, + 0x00afbedb, 0x00efbedb, 0x002cb2eb, 0x006cb2eb, 0x00acb2eb, 0x00ecb2eb, + 0x002db2eb, 0x006db2eb, 0x00adb2eb, 0x00edb2eb, 0x002eb2eb, 0x006eb2eb, + 0x00aeb2eb, 0x00eeb2eb, 0x002fb2eb, 0x006fb2eb, 0x00afb2eb, 0x00efb2eb, + 0x002cb6eb, 0x006cb6eb, 0x00acb6eb, 0x00ecb6eb, 0x002db6eb, 0x006db6eb, + 0x00adb6eb, 0x00edb6eb, 0x002eb6eb, 0x006eb6eb, 0x00aeb6eb, 0x00eeb6eb, + 0x002fb6eb, 0x006fb6eb, 0x00afb6eb, 0x00efb6eb, 0x002cbaeb, 0x006cbaeb, + 0x00acbaeb, 0x00ecbaeb, 0x002dbaeb, 0x006dbaeb, 0x00adbaeb, 0x00edbaeb, + 0x002ebaeb, 0x006ebaeb, 0x00aebaeb, 0x00eebaeb, 0x002fbaeb, 0x006fbaeb, + 0x00afbaeb, 0x00efbaeb, 0x002cbeeb, 0x006cbeeb, 0x00acbeeb, 0x00ecbeeb, + 0x002dbeeb, 0x006dbeeb, 0x00adbeeb, 0x00edbeeb, 0x002ebeeb, 0x006ebeeb, + 0x00aebeeb, 0x00eebeeb, 0x002fbeeb, 0x006fbeeb, 0x00afbeeb, 0x00efbeeb, + 0x002cb2fb, 0x006cb2fb, 0x00acb2fb, 0x00ecb2fb, 0x002db2fb, 0x006db2fb, + 0x00adb2fb, 0x00edb2fb, 0x002eb2fb, 0x006eb2fb, 0x00aeb2fb, 0x00eeb2fb, + 0x002fb2fb, 0x006fb2fb, 0x00afb2fb, 0x00efb2fb, 0x002cb6fb, 0x006cb6fb, + 0x00acb6fb, 0x00ecb6fb, 0x002db6fb, 0x006db6fb, 0x00adb6fb, 0x00edb6fb, + 0x002eb6fb, 0x006eb6fb, 0x00aeb6fb, 0x00eeb6fb, 0x002fb6fb, 0x006fb6fb, + 0x00afb6fb, 0x00efb6fb, 0x002cbafb, 0x006cbafb, 0x00acbafb, 0x00ecbafb, + 0x002dbafb, 0x006dbafb, 0x00adbafb, 0x00edbafb, 0x002ebafb, 0x006ebafb, + 0x00aebafb, 0x00eebafb, 0x002fbafb, 0x006fbafb, 0x00afbafb, 0x00efbafb, + 0x002cbefb, 0x006cbefb, 0x00acbefb, 0x00ecbefb, 0x002dbefb, 0x006dbefb, + 0x00adbefb, 0x00edbefb, 0x002ebefb, 0x006ebefb, 0x00aebefb, 0x00eebefb, + 0x002fbefb, 0x006fbefb, 0x00afbefb, 0x00efbefb, 0x0b2cb2cb, 0x1b2cb2cb, + 0x2b2cb2cb, 0x3b2cb2cb, 0x0b6cb2cb, 0x1b6cb2cb, 0x2b6cb2cb, 0x3b6cb2cb, + 0x0bacb2cb, 0x1bacb2cb, 0x2bacb2cb, 0x3bacb2cb, 0x0becb2cb, 0x1becb2cb, + 0x2becb2cb, 0x3becb2cb, 0x0b2db2cb, 0x1b2db2cb, 0x2b2db2cb, 0x3b2db2cb, + 0x0b6db2cb, 0x1b6db2cb, 0x2b6db2cb, 0x3b6db2cb, 0x0badb2cb, 0x1badb2cb, + 0x2badb2cb, 0x3badb2cb, 0x0bedb2cb, 0x1bedb2cb, 0x2bedb2cb, 0x3bedb2cb, + 0x0b2eb2cb, 0x1b2eb2cb, 0x2b2eb2cb, 0x3b2eb2cb, 0x0b6eb2cb, 0x1b6eb2cb, + 0x2b6eb2cb, 0x3b6eb2cb, 0x0baeb2cb, 0x1baeb2cb, 0x2baeb2cb, 0x3baeb2cb, + 0x0beeb2cb, 0x1beeb2cb, 0x2beeb2cb, 0x3beeb2cb, 0x0b2fb2cb, 0x1b2fb2cb, + 0x2b2fb2cb, 0x3b2fb2cb, 0x0b6fb2cb, 0x1b6fb2cb, 0x2b6fb2cb, 0x3b6fb2cb, + 0x0bafb2cb, 0x1bafb2cb, 0x2bafb2cb, 0x3bafb2cb, 0x0befb2cb, 0x1befb2cb, + 0x2befb2cb, 0x3befb2cb, 0x0b2cb6cb, 0x1b2cb6cb, 0x2b2cb6cb, 0x3b2cb6cb, + 0x0b6cb6cb, 0x1b6cb6cb, 0x2b6cb6cb, 0x3b6cb6cb, 0x0bacb6cb, 0x1bacb6cb, + 0x2bacb6cb, 0x3bacb6cb, 0x0becb6cb, 0x1becb6cb, 0x2becb6cb, 0x3becb6cb, + 0x0b2db6cb, 0x1b2db6cb, 0x2b2db6cb, 0x3b2db6cb, 0x0b6db6cb, 0x1b6db6cb, + 0x2b6db6cb, 0x3b6db6cb, 0x0badb6cb, 0x1badb6cb, 0x2badb6cb, 0x3badb6cb, + 0x0bedb6cb, 0x1bedb6cb, 0x2bedb6cb, 0x3bedb6cb, 0x0b2eb6cb, 0x1b2eb6cb, + 0x2b2eb6cb, 0x3b2eb6cb, 0x0b6eb6cb, 0x1b6eb6cb, 0x2b6eb6cb, 0x3b6eb6cb, + 0x0baeb6cb, 0x1baeb6cb, 0x2baeb6cb, 0x3baeb6cb, 0x0beeb6cb, 0x1beeb6cb, + 0x2beeb6cb, 0x3beeb6cb, 0x0b2fb6cb, 0x1b2fb6cb, 0x2b2fb6cb, 0x3b2fb6cb, + 0x0b6fb6cb, 0x1b6fb6cb, 0x2b6fb6cb, 0x3b6fb6cb, 0x0bafb6cb, 0x1bafb6cb, + 0x2bafb6cb, 0x3bafb6cb, 0x0befb6cb, 0x1befb6cb, 0x2befb6cb, 0x3befb6cb, + 0x0b2cbacb, 0x1b2cbacb, 0x2b2cbacb, 0x3b2cbacb, 0x0b6cbacb, 0x1b6cbacb, + 0x2b6cbacb, 0x3b6cbacb, 0x0bacbacb, 0x1bacbacb, 0x2bacbacb, 0x3bacbacb, + 0x0becbacb, 0x1becbacb, 0x2becbacb, 0x3becbacb, 0x0b2dbacb, 0x1b2dbacb, + 0x2b2dbacb, 0x3b2dbacb, 0x0b6dbacb, 0x1b6dbacb, 0x2b6dbacb, 0x3b6dbacb, + 0x0badbacb, 0x1badbacb, 0x2badbacb, 0x3badbacb, 0x0bedbacb, 0x1bedbacb, + 0x2bedbacb, 0x3bedbacb, 0x0b2ebacb, 0x1b2ebacb, 0x2b2ebacb, 0x3b2ebacb, + 0x0b6ebacb, 0x1b6ebacb, 0x2b6ebacb, 0x3b6ebacb, 0x0baebacb, 0x1baebacb, + 0x2baebacb, 0x3baebacb, 0x0beebacb, 0x1beebacb, 0x2beebacb, 0x3beebacb, + 0x0b2fbacb, 0x1b2fbacb, 0x2b2fbacb, 0x3b2fbacb, 0x0b6fbacb, 0x1b6fbacb, + 0x2b6fbacb, 0x3b6fbacb, 0x0bafbacb, 0x1bafbacb, 0x2bafbacb, 0x3bafbacb, + 0x0befbacb, 0x1befbacb, 0x2befbacb, 0x3befbacb, 0x0b2cbecb, 0x1b2cbecb, + 0x2b2cbecb, 0x3b2cbecb, 0x0b6cbecb, 0x1b6cbecb, 0x2b6cbecb, 0x3b6cbecb, + 0x0bacbecb, 0x1bacbecb, 0x2bacbecb, 0x3bacbecb, 0x0becbecb, 0x1becbecb, + 0x2becbecb, 0x3becbecb, 0x0b2dbecb, 0x1b2dbecb, 0x2b2dbecb, 0x3b2dbecb, + 0x0b6dbecb, 0x1b6dbecb, 0x2b6dbecb, 0x3b6dbecb, 0x0badbecb, 0x1badbecb, + 0x2badbecb, 0x3badbecb, 0x0bedbecb, 0x1bedbecb, 0x2bedbecb, 0x3bedbecb, + 0x0b2ebecb, 0x1b2ebecb, 0x2b2ebecb, 0x3b2ebecb, 0x0b6ebecb, 0x1b6ebecb, + 0x2b6ebecb, 0x3b6ebecb, 0x0baebecb, 0x1baebecb, 0x2baebecb, 0x3baebecb, + 0x0beebecb, 0x1beebecb, 0x2beebecb, 0x3beebecb, 0x0b2fbecb, 0x1b2fbecb, + 0x2b2fbecb, 0x3b2fbecb, 0x0b6fbecb, 0x1b6fbecb, 0x2b6fbecb, 0x3b6fbecb, + 0x0bafbecb, 0x1bafbecb, 0x2bafbecb, 0x3bafbecb, 0x0befbecb, 0x1befbecb, + 0x2befbecb, 0x3befbecb, 0x0b2cb2db, 0x1b2cb2db, 0x2b2cb2db, 0x3b2cb2db, + 0x0b6cb2db, 0x1b6cb2db, 0x2b6cb2db, 0x3b6cb2db, 0x0bacb2db, 0x1bacb2db, + 0x2bacb2db, 0x3bacb2db, 0x0becb2db, 0x1becb2db, 0x2becb2db, 0x3becb2db, + 0x0b2db2db, 0x1b2db2db, 0x2b2db2db, 0x3b2db2db, 0x0b6db2db, 0x1b6db2db, + 0x2b6db2db, 0x3b6db2db, 0x0badb2db, 0x1badb2db, 0x2badb2db, 0x3badb2db, + 0x0bedb2db, 0x1bedb2db, 0x2bedb2db, 0x3bedb2db, 0x0b2eb2db, 0x1b2eb2db, + 0x2b2eb2db, 0x3b2eb2db, 0x0b6eb2db, 0x1b6eb2db, 0x2b6eb2db, 0x3b6eb2db, + 0x0baeb2db, 0x1baeb2db, 0x2baeb2db, 0x3baeb2db, 0x0beeb2db, 0x1beeb2db, + 0x2beeb2db, 0x3beeb2db, 0x0b2fb2db, 0x1b2fb2db, 0x2b2fb2db, 0x3b2fb2db, + 0x0b6fb2db, 0x1b6fb2db, 0x2b6fb2db, 0x3b6fb2db, 0x0bafb2db, 0x1bafb2db, + 0x2bafb2db, 0x3bafb2db, 0x0befb2db, 0x1befb2db, 0x2befb2db, 0x3befb2db, + 0x0b2cb6db, 0x1b2cb6db, 0x2b2cb6db, 0x3b2cb6db, 0x0b6cb6db, 0x1b6cb6db, + 0x2b6cb6db, 0x3b6cb6db, 0x0bacb6db, 0x1bacb6db, 0x2bacb6db, 0x3bacb6db, + 0x0becb6db, 0x1becb6db, 0x2becb6db, 0x3becb6db, 0x0b2db6db, 0x1b2db6db, + 0x2b2db6db, 0x3b2db6db, 0x0b6db6db, 0x1b6db6db, 0x2b6db6db, 0x3b6db6db, + 0x0badb6db, 0x1badb6db, 0x2badb6db, 0x3badb6db, 0x0bedb6db, 0x1bedb6db, + 0x2bedb6db, 0x3bedb6db, 0x0b2eb6db, 0x1b2eb6db, 0x2b2eb6db, 0x3b2eb6db, + 0x0b6eb6db, 0x1b6eb6db, 0x2b6eb6db, 0x3b6eb6db, 0x0baeb6db, 0x1baeb6db, + 0x2baeb6db, 0x3baeb6db, +}; + +static const uint32_t kNonZeroRepsDepth[BROTLI_NUM_COMMAND_SYMBOLS] = { + 6, 6, 6, 6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, +}; + +static const uint16_t kStaticCommandCodeBits[BROTLI_NUM_COMMAND_SYMBOLS] = { + 0, 256, 128, 384, 64, 320, 192, 448, + 32, 288, 160, 416, 96, 352, 224, 480, + 16, 272, 144, 400, 80, 336, 208, 464, + 48, 304, 176, 432, 112, 368, 240, 496, + 8, 264, 136, 392, 72, 328, 200, 456, + 40, 296, 168, 424, 104, 360, 232, 488, + 24, 280, 152, 408, 88, 344, 216, 472, + 56, 312, 184, 440, 120, 376, 248, 504, + 4, 260, 132, 388, 68, 324, 196, 452, + 36, 292, 164, 420, 100, 356, 228, 484, + 20, 276, 148, 404, 84, 340, 212, 468, + 52, 308, 180, 436, 116, 372, 244, 500, + 12, 268, 140, 396, 76, 332, 204, 460, + 44, 300, 172, 428, 108, 364, 236, 492, + 28, 284, 156, 412, 92, 348, 220, 476, + 60, 316, 188, 444, 124, 380, 252, 508, + 2, 258, 130, 386, 66, 322, 194, 450, + 34, 290, 162, 418, 98, 354, 226, 482, + 18, 274, 146, 402, 82, 338, 210, 466, + 50, 306, 178, 434, 114, 370, 242, 498, + 10, 266, 138, 394, 74, 330, 202, 458, + 42, 298, 170, 426, 106, 362, 234, 490, + 26, 282, 154, 410, 90, 346, 218, 474, + 58, 314, 186, 442, 122, 378, 250, 506, + 6, 262, 134, 390, 70, 326, 198, 454, + 38, 294, 166, 422, 102, 358, 230, 486, + 22, 278, 150, 406, 86, 342, 214, 470, + 54, 310, 182, 438, 118, 374, 246, 502, + 14, 270, 142, 398, 78, 334, 206, 462, + 46, 302, 174, 430, 110, 366, 238, 494, + 30, 286, 158, 414, 94, 350, 222, 478, + 62, 318, 190, 446, 126, 382, 254, 510, + 1, 257, 129, 385, 65, 321, 193, 449, + 33, 289, 161, 417, 97, 353, 225, 481, + 17, 273, 145, 401, 81, 337, 209, 465, + 49, 305, 177, 433, 113, 369, 241, 497, + 9, 265, 137, 393, 73, 329, 201, 457, + 41, 297, 169, 425, 105, 361, 233, 489, + 25, 281, 153, 409, 89, 345, 217, 473, + 57, 313, 185, 441, 121, 377, 249, 505, + 5, 261, 133, 389, 69, 325, 197, 453, + 37, 293, 165, 421, 101, 357, 229, 485, + 21, 277, 149, 405, 85, 341, 213, 469, + 53, 309, 181, 437, 117, 373, 245, 501, + 13, 269, 141, 397, 77, 333, 205, 461, + 45, 301, 173, 429, 109, 365, 237, 493, + 29, 285, 157, 413, 93, 349, 221, 477, + 61, 317, 189, 445, 125, 381, 253, 509, + 3, 259, 131, 387, 67, 323, 195, 451, + 35, 291, 163, 419, 99, 355, 227, 483, + 19, 275, 147, 403, 83, 339, 211, 467, + 51, 307, 179, 435, 115, 371, 243, 499, + 11, 267, 139, 395, 75, 331, 203, 459, + 43, 299, 171, 427, 107, 363, 235, 491, + 27, 283, 155, 411, 91, 347, 219, 475, + 59, 315, 187, 443, 123, 379, 251, 507, + 7, 1031, 519, 1543, 263, 1287, 775, 1799, + 135, 1159, 647, 1671, 391, 1415, 903, 1927, + 71, 1095, 583, 1607, 327, 1351, 839, 1863, + 199, 1223, 711, 1735, 455, 1479, 967, 1991, + 39, 1063, 551, 1575, 295, 1319, 807, 1831, + 167, 1191, 679, 1703, 423, 1447, 935, 1959, + 103, 1127, 615, 1639, 359, 1383, 871, 1895, + 231, 1255, 743, 1767, 487, 1511, 999, 2023, + 23, 1047, 535, 1559, 279, 1303, 791, 1815, + 151, 1175, 663, 1687, 407, 1431, 919, 1943, + 87, 1111, 599, 1623, 343, 1367, 855, 1879, + 215, 1239, 727, 1751, 471, 1495, 983, 2007, + 55, 1079, 567, 1591, 311, 1335, 823, 1847, + 183, 1207, 695, 1719, 439, 1463, 951, 1975, + 119, 1143, 631, 1655, 375, 1399, 887, 1911, + 247, 1271, 759, 1783, 503, 1527, 1015, 2039, + 15, 1039, 527, 1551, 271, 1295, 783, 1807, + 143, 1167, 655, 1679, 399, 1423, 911, 1935, + 79, 1103, 591, 1615, 335, 1359, 847, 1871, + 207, 1231, 719, 1743, 463, 1487, 975, 1999, + 47, 1071, 559, 1583, 303, 1327, 815, 1839, + 175, 1199, 687, 1711, 431, 1455, 943, 1967, + 111, 1135, 623, 1647, 367, 1391, 879, 1903, + 239, 1263, 751, 1775, 495, 1519, 1007, 2031, + 31, 1055, 543, 1567, 287, 1311, 799, 1823, + 159, 1183, 671, 1695, 415, 1439, 927, 1951, + 95, 1119, 607, 1631, 351, 1375, 863, 1887, + 223, 1247, 735, 1759, 479, 1503, 991, 2015, + 63, 1087, 575, 1599, 319, 1343, 831, 1855, + 191, 1215, 703, 1727, 447, 1471, 959, 1983, + 127, 1151, 639, 1663, 383, 1407, 895, 1919, + 255, 1279, 767, 1791, 511, 1535, 1023, 2047, +}; + +static BROTLI_INLINE void StoreStaticCommandHuffmanTree( + size_t* storage_ix, uint8_t* storage) { + BrotliWriteBits( + 56, BROTLI_MAKE_UINT64_T(0x926244U, 0x16307003U), storage_ix, storage); + BrotliWriteBits(3, 0x00000000U, storage_ix, storage); +} + +static const uint16_t kStaticDistanceCodeBits[64] = { + 0, 32, 16, 48, 8, 40, 24, 56, 4, 36, 20, 52, 12, 44, 28, 60, + 2, 34, 18, 50, 10, 42, 26, 58, 6, 38, 22, 54, 14, 46, 30, 62, + 1, 33, 17, 49, 9, 41, 25, 57, 5, 37, 21, 53, 13, 45, 29, 61, + 3, 35, 19, 51, 11, 43, 27, 59, 7, 39, 23, 55, 15, 47, 31, 63, +}; + +static BROTLI_INLINE void StoreStaticDistanceHuffmanTree( + size_t* storage_ix, uint8_t* storage) { + BrotliWriteBits(28, 0x0369DC03u, storage_ix, storage); +} +/* GENERATED CODE END */ + +} + +#endif /* BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_ */ diff --git a/third_party/brotli/enc/fast_log.cpp b/third_party/brotli/enc/fast_log.cpp new file mode 100644 index 00000000000..790152b0cd2 --- /dev/null +++ b/third_party/brotli/enc/fast_log.cpp @@ -0,0 +1,101 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include "fast_log.h" + +using namespace duckdb_brotli; + +/* ", ".join(["%.16ff" % x for x in [0.0]+[log2(x) for x in range(1, 256)]]) */ +const double duckdb_brotli::kBrotliLog2Table[BROTLI_LOG2_TABLE_SIZE] = { + 0.0000000000000000f, 0.0000000000000000f, 1.0000000000000000f, + 1.5849625007211563f, 2.0000000000000000f, 2.3219280948873622f, + 2.5849625007211561f, 2.8073549220576042f, 3.0000000000000000f, + 3.1699250014423126f, 3.3219280948873626f, 3.4594316186372978f, + 3.5849625007211565f, 3.7004397181410922f, 3.8073549220576037f, + 3.9068905956085187f, 4.0000000000000000f, 4.0874628412503400f, + 4.1699250014423122f, 4.2479275134435852f, 4.3219280948873626f, + 4.3923174227787607f, 4.4594316186372973f, 4.5235619560570131f, + 4.5849625007211570f, 4.6438561897747244f, 4.7004397181410926f, + 4.7548875021634691f, 4.8073549220576037f, 4.8579809951275728f, + 4.9068905956085187f, 4.9541963103868758f, 5.0000000000000000f, + 5.0443941193584534f, 5.0874628412503400f, 5.1292830169449664f, + 5.1699250014423122f, 5.2094533656289501f, 5.2479275134435852f, + 5.2854022188622487f, 5.3219280948873626f, 5.3575520046180838f, + 5.3923174227787607f, 5.4262647547020979f, 5.4594316186372973f, + 5.4918530963296748f, 5.5235619560570131f, 5.5545888516776376f, + 5.5849625007211570f, 5.6147098441152083f, 5.6438561897747244f, + 5.6724253419714961f, 5.7004397181410926f, 5.7279204545631996f, + 5.7548875021634691f, 5.7813597135246599f, 5.8073549220576046f, + 5.8328900141647422f, 5.8579809951275719f, 5.8826430493618416f, + 5.9068905956085187f, 5.9307373375628867f, 5.9541963103868758f, + 5.9772799234999168f, 6.0000000000000000f, 6.0223678130284544f, + 6.0443941193584534f, 6.0660891904577721f, 6.0874628412503400f, + 6.1085244567781700f, 6.1292830169449672f, 6.1497471195046822f, + 6.1699250014423122f, 6.1898245588800176f, 6.2094533656289510f, + 6.2288186904958804f, 6.2479275134435861f, 6.2667865406949019f, + 6.2854022188622487f, 6.3037807481771031f, 6.3219280948873617f, + 6.3398500028846252f, 6.3575520046180847f, 6.3750394313469254f, + 6.3923174227787598f, 6.4093909361377026f, 6.4262647547020979f, + 6.4429434958487288f, 6.4594316186372982f, 6.4757334309663976f, + 6.4918530963296748f, 6.5077946401986964f, 6.5235619560570131f, + 6.5391588111080319f, 6.5545888516776376f, 6.5698556083309478f, + 6.5849625007211561f, 6.5999128421871278f, 6.6147098441152092f, + 6.6293566200796095f, 6.6438561897747253f, 6.6582114827517955f, + 6.6724253419714952f, 6.6865005271832185f, 6.7004397181410917f, + 6.7142455176661224f, 6.7279204545631988f, 6.7414669864011465f, + 6.7548875021634691f, 6.7681843247769260f, 6.7813597135246599f, + 6.7944158663501062f, 6.8073549220576037f, 6.8201789624151887f, + 6.8328900141647422f, 6.8454900509443757f, 6.8579809951275719f, + 6.8703647195834048f, 6.8826430493618416f, 6.8948177633079437f, + 6.9068905956085187f, 6.9188632372745955f, 6.9307373375628867f, + 6.9425145053392399f, 6.9541963103868758f, 6.9657842846620879f, + 6.9772799234999168f, 6.9886846867721664f, 7.0000000000000000f, + 7.0112272554232540f, 7.0223678130284544f, 7.0334230015374501f, + 7.0443941193584534f, 7.0552824355011898f, 7.0660891904577721f, + 7.0768155970508317f, 7.0874628412503400f, 7.0980320829605272f, + 7.1085244567781700f, 7.1189410727235076f, 7.1292830169449664f, + 7.1395513523987937f, 7.1497471195046822f, 7.1598713367783891f, + 7.1699250014423130f, 7.1799090900149345f, 7.1898245588800176f, + 7.1996723448363644f, 7.2094533656289492f, 7.2191685204621621f, + 7.2288186904958804f, 7.2384047393250794f, 7.2479275134435861f, + 7.2573878426926521f, 7.2667865406949019f, 7.2761244052742384f, + 7.2854022188622487f, 7.2946207488916270f, 7.3037807481771031f, + 7.3128829552843557f, 7.3219280948873617f, 7.3309168781146177f, + 7.3398500028846243f, 7.3487281542310781f, 7.3575520046180847f, + 7.3663222142458151f, 7.3750394313469254f, 7.3837042924740528f, + 7.3923174227787607f, 7.4008794362821844f, 7.4093909361377026f, + 7.4178525148858991f, 7.4262647547020979f, 7.4346282276367255f, + 7.4429434958487288f, 7.4512111118323299f, 7.4594316186372973f, + 7.4676055500829976f, 7.4757334309663976f, 7.4838157772642564f, + 7.4918530963296748f, 7.4998458870832057f, 7.5077946401986964f, + 7.5156998382840436f, 7.5235619560570131f, 7.5313814605163119f, + 7.5391588111080319f, 7.5468944598876373f, 7.5545888516776376f, + 7.5622424242210728f, 7.5698556083309478f, 7.5774288280357487f, + 7.5849625007211561f, 7.5924570372680806f, 7.5999128421871278f, + 7.6073303137496113f, 7.6147098441152075f, 7.6220518194563764f, + 7.6293566200796095f, 7.6366246205436488f, 7.6438561897747244f, + 7.6510516911789290f, 7.6582114827517955f, 7.6653359171851765f, + 7.6724253419714952f, 7.6794800995054464f, 7.6865005271832185f, + 7.6934869574993252f, 7.7004397181410926f, 7.7073591320808825f, + 7.7142455176661224f, 7.7210991887071856f, 7.7279204545631996f, + 7.7347096202258392f, 7.7414669864011465f, 7.7481928495894596f, + 7.7548875021634691f, 7.7615512324444795f, 7.7681843247769260f, + 7.7747870596011737f, 7.7813597135246608f, 7.7879025593914317f, + 7.7944158663501062f, 7.8008998999203047f, 7.8073549220576037f, + 7.8137811912170374f, 7.8201789624151887f, 7.8265484872909159f, + 7.8328900141647422f, 7.8392037880969445f, 7.8454900509443757f, + 7.8517490414160571f, 7.8579809951275719f, 7.8641861446542798f, + 7.8703647195834048f, 7.8765169465650002f, 7.8826430493618425f, + 7.8887432488982601f, 7.8948177633079446f, 7.9008668079807496f, + 7.9068905956085187f, 7.9128893362299619f, 7.9188632372745955f, + 7.9248125036057813f, 7.9307373375628867f, 7.9366379390025719f, + 7.9425145053392399f, 7.9483672315846778f, 7.9541963103868758f, + 7.9600019320680806f, 7.9657842846620870f, 7.9715435539507720f, + 7.9772799234999168f, 7.9829935746943104f, 7.9886846867721664f, + 7.9943534368588578f +}; + + diff --git a/third_party/brotli/enc/fast_log.h b/third_party/brotli/enc/fast_log.h new file mode 100644 index 00000000000..455bd80345d --- /dev/null +++ b/third_party/brotli/enc/fast_log.h @@ -0,0 +1,63 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Utilities for fast computation of logarithms. */ + +#ifndef BROTLI_ENC_FAST_LOG_H_ +#define BROTLI_ENC_FAST_LOG_H_ + +#include + +#include + +#include "../common/brotli_platform.h" + +namespace duckdb_brotli { + +static BROTLI_INLINE uint32_t Log2FloorNonZero(size_t n) { +#if defined(BROTLI_BSR32) + return BROTLI_BSR32((uint32_t)n); +#else + uint32_t result = 0; + while (n >>= 1) result++; + return result; +#endif +} + +#define BROTLI_LOG2_TABLE_SIZE 256 + +/* A lookup table for small values of log2(int) to be used in entropy + computation. */ +BROTLI_INTERNAL extern const double kBrotliLog2Table[BROTLI_LOG2_TABLE_SIZE]; + +/* Visual Studio 2012 and Android API levels < 18 do not have the log2() + * function defined, so we use log() and a multiplication instead. */ +#if !defined(BROTLI_HAVE_LOG2) +#if ((defined(_MSC_VER) && _MSC_VER <= 1700) || \ + (defined(__ANDROID_API__) && __ANDROID_API__ < 18)) +#define BROTLI_HAVE_LOG2 0 +#else +#define BROTLI_HAVE_LOG2 1 +#endif +#endif + +#define LOG_2_INV 1.4426950408889634 + +/* Faster logarithm for small integers, with the property of log2(0) == 0. */ +static BROTLI_INLINE double FastLog2(size_t v) { + if (v < BROTLI_LOG2_TABLE_SIZE) { + return kBrotliLog2Table[v]; + } +#if !(BROTLI_HAVE_LOG2) + return log((double)v) * LOG_2_INV; +#else + return log2((double)v); +#endif +} + +} + +#endif /* BROTLI_ENC_FAST_LOG_H_ */ diff --git a/third_party/brotli/enc/find_match_length.h b/third_party/brotli/enc/find_match_length.h new file mode 100644 index 00000000000..fb74483e289 --- /dev/null +++ b/third_party/brotli/enc/find_match_length.h @@ -0,0 +1,68 @@ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Function to find maximal matching prefixes of strings. */ + +#ifndef BROTLI_ENC_FIND_MATCH_LENGTH_H_ +#define BROTLI_ENC_FIND_MATCH_LENGTH_H_ + +#include + +#include "../common/brotli_platform.h" + +namespace duckdb_brotli { + +/* Separate implementation for little-endian 64-bit targets, for speed. */ +#if defined(BROTLI_TZCNT64) && BROTLI_64_BITS && BROTLI_LITTLE_ENDIAN +static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1, + const uint8_t* s2, + size_t limit) { + const uint8_t *s1_orig = s1; + for (; limit >= 8; limit -= 8) { + uint64_t x = BROTLI_UNALIGNED_LOAD64LE(s2) ^ + BROTLI_UNALIGNED_LOAD64LE(s1); + s2 += 8; + if (x != 0) { + size_t matching_bits = (size_t)BROTLI_TZCNT64(x); + return (size_t)(s1 - s1_orig) + (matching_bits >> 3); + } + s1 += 8; + } + while (limit && *s1 == *s2) { + limit--; + ++s2; + ++s1; + } + return (size_t)(s1 - s1_orig); +} +#else +static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1, + const uint8_t* s2, + size_t limit) { + size_t matched = 0; + const uint8_t* s2_limit = s2 + limit; + const uint8_t* s2_ptr = s2; + /* Find out how long the match is. We loop over the data 32 bits at a + time until we find a 32-bit block that doesn't match; then we find + the first non-matching bit and use that to calculate the total + length of the match. */ + while (s2_ptr <= s2_limit - 4 && + BrotliUnalignedRead32(s2_ptr) == + BrotliUnalignedRead32(s1 + matched)) { + s2_ptr += 4; + matched += 4; + } + while ((s2_ptr < s2_limit) && (s1[matched] == *s2_ptr)) { + ++s2_ptr; + ++matched; + } + return matched; +} +#endif + +} + +#endif /* BROTLI_ENC_FIND_MATCH_LENGTH_H_ */ diff --git a/third_party/brotli/enc/histogram.cpp b/third_party/brotli/enc/histogram.cpp new file mode 100644 index 00000000000..5a9fba9c998 --- /dev/null +++ b/third_party/brotli/enc/histogram.cpp @@ -0,0 +1,96 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Build per-context histograms of literals, commands and distance codes. */ + +#include "histogram.h" + +#include "../common/context.h" +#include "block_splitter.h" +#include "command.h" + +using namespace duckdb_brotli; + +typedef struct BlockSplitIterator { + const BlockSplit* split_; /* Not owned. */ + size_t idx_; + size_t type_; + size_t length_; +} BlockSplitIterator; + +static void InitBlockSplitIterator(BlockSplitIterator* self, + const BlockSplit* split) { + self->split_ = split; + self->idx_ = 0; + self->type_ = 0; + self->length_ = split->lengths ? split->lengths[0] : 0; +} + +static void BlockSplitIteratorNext(BlockSplitIterator* self) { + if (self->length_ == 0) { + ++self->idx_; + self->type_ = self->split_->types[self->idx_]; + self->length_ = self->split_->lengths[self->idx_]; + } + --self->length_; +} + +void duckdb_brotli::BrotliBuildHistogramsWithContext( + const Command* cmds, const size_t num_commands, + const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split, + const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t start_pos, + size_t mask, uint8_t prev_byte, uint8_t prev_byte2, + const ContextType* context_modes, HistogramLiteral* literal_histograms, + HistogramCommand* insert_and_copy_histograms, + HistogramDistance* copy_dist_histograms) { + size_t pos = start_pos; + BlockSplitIterator literal_it; + BlockSplitIterator insert_and_copy_it; + BlockSplitIterator dist_it; + size_t i; + + InitBlockSplitIterator(&literal_it, literal_split); + InitBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split); + InitBlockSplitIterator(&dist_it, dist_split); + for (i = 0; i < num_commands; ++i) { + const Command* cmd = &cmds[i]; + size_t j; + BlockSplitIteratorNext(&insert_and_copy_it); + HistogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_], + cmd->cmd_prefix_); + /* TODO(eustas): unwrap iterator blocks. */ + for (j = cmd->insert_len_; j != 0; --j) { + size_t context; + BlockSplitIteratorNext(&literal_it); + context = literal_it.type_; + if (context_modes) { + ContextLut lut = BROTLI_CONTEXT_LUT(context_modes[context]); + context = (context << BROTLI_LITERAL_CONTEXT_BITS) + + BROTLI_CONTEXT(prev_byte, prev_byte2, lut); + } + HistogramAddLiteral(&literal_histograms[context], + ringbuffer[pos & mask]); + prev_byte2 = prev_byte; + prev_byte = ringbuffer[pos & mask]; + ++pos; + } + pos += CommandCopyLen(cmd); + if (CommandCopyLen(cmd)) { + prev_byte2 = ringbuffer[(pos - 2) & mask]; + prev_byte = ringbuffer[(pos - 1) & mask]; + if (cmd->cmd_prefix_ >= 128) { + size_t context; + BlockSplitIteratorNext(&dist_it); + context = (dist_it.type_ << BROTLI_DISTANCE_CONTEXT_BITS) + + CommandDistanceContext(cmd); + HistogramAddDistance(©_dist_histograms[context], + cmd->dist_prefix_ & 0x3FF); + } + } + } +} + + diff --git a/third_party/brotli/enc/histogram.h b/third_party/brotli/enc/histogram.h new file mode 100644 index 00000000000..3ac082ad846 --- /dev/null +++ b/third_party/brotli/enc/histogram.h @@ -0,0 +1,210 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Models the histograms of literals, commands and distance codes. */ + +#ifndef BROTLI_ENC_HISTOGRAM_H_ +#define BROTLI_ENC_HISTOGRAM_H_ + +#include /* memset */ + +#include + +#include "../common/brotli_constants.h" +#include "../common/context.h" +#include "../common/brotli_platform.h" +#include "block_splitter.h" +#include "command.h" + +namespace duckdb_brotli { + +/* The distance symbols effectively used by "Large Window Brotli" (32-bit). */ +#define BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS 544 + +#define FN(X) X ## Literal +#define DATA_SIZE BROTLI_NUM_LITERAL_SYMBOLS +#define DataType uint8_t +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: Histogram, DATA_SIZE, DataType */ + +/* A simple container for histograms of data in blocks. */ + +typedef struct FN(Histogram) { + uint32_t data_[DATA_SIZE]; + size_t total_count_; + double bit_cost_; +} FN(Histogram); + +static BROTLI_INLINE void FN(HistogramClear)(FN(Histogram)* self) { + memset(self->data_, 0, sizeof(self->data_)); + self->total_count_ = 0; + self->bit_cost_ = HUGE_VAL; +} + +static BROTLI_INLINE void FN(ClearHistograms)( + FN(Histogram)* array, size_t length) { + size_t i; + for (i = 0; i < length; ++i) FN(HistogramClear)(array + i); +} + +static BROTLI_INLINE void FN(HistogramAdd)(FN(Histogram)* self, size_t val) { + ++self->data_[val]; + ++self->total_count_; +} + +static BROTLI_INLINE void FN(HistogramAddVector)(FN(Histogram)* self, + const DataType* p, size_t n) { + self->total_count_ += n; + n += 1; + while (--n) ++self->data_[*p++]; +} + +static BROTLI_INLINE void FN(HistogramAddHistogram)(FN(Histogram)* self, + const FN(Histogram)* v) { + size_t i; + self->total_count_ += v->total_count_; + for (i = 0; i < DATA_SIZE; ++i) { + self->data_[i] += v->data_[i]; + } +} + +static BROTLI_INLINE size_t FN(HistogramDataSize)(void) { return DATA_SIZE; } +#undef DataType +#undef DATA_SIZE +#undef FN + +#define FN(X) X ## Command +#define DataType uint16_t +#define DATA_SIZE BROTLI_NUM_COMMAND_SYMBOLS +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: Histogram, DATA_SIZE, DataType */ + +/* A simple container for histograms of data in blocks. */ + +typedef struct FN(Histogram) { + uint32_t data_[DATA_SIZE]; + size_t total_count_; + double bit_cost_; +} FN(Histogram); + +static BROTLI_INLINE void FN(HistogramClear)(FN(Histogram)* self) { + memset(self->data_, 0, sizeof(self->data_)); + self->total_count_ = 0; + self->bit_cost_ = HUGE_VAL; +} + +static BROTLI_INLINE void FN(ClearHistograms)( + FN(Histogram)* array, size_t length) { + size_t i; + for (i = 0; i < length; ++i) FN(HistogramClear)(array + i); +} + +static BROTLI_INLINE void FN(HistogramAdd)(FN(Histogram)* self, size_t val) { + ++self->data_[val]; + ++self->total_count_; +} + +static BROTLI_INLINE void FN(HistogramAddVector)(FN(Histogram)* self, + const DataType* p, size_t n) { + self->total_count_ += n; + n += 1; + while (--n) ++self->data_[*p++]; +} + +static BROTLI_INLINE void FN(HistogramAddHistogram)(FN(Histogram)* self, + const FN(Histogram)* v) { + size_t i; + self->total_count_ += v->total_count_; + for (i = 0; i < DATA_SIZE; ++i) { + self->data_[i] += v->data_[i]; + } +} + +static BROTLI_INLINE size_t FN(HistogramDataSize)(void) { return DATA_SIZE; } +#undef DATA_SIZE +#undef FN + +#define FN(X) X ## Distance +#define DATA_SIZE BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS +/* NOLINT(build/header_guard) */ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: Histogram, DATA_SIZE, DataType */ + +/* A simple container for histograms of data in blocks. */ + +typedef struct FN(Histogram) { + uint32_t data_[DATA_SIZE]; + size_t total_count_; + double bit_cost_; +} FN(Histogram); + +static BROTLI_INLINE void FN(HistogramClear)(FN(Histogram)* self) { + memset(self->data_, 0, sizeof(self->data_)); + self->total_count_ = 0; + self->bit_cost_ = HUGE_VAL; +} + +static BROTLI_INLINE void FN(ClearHistograms)( + FN(Histogram)* array, size_t length) { + size_t i; + for (i = 0; i < length; ++i) FN(HistogramClear)(array + i); +} + +static BROTLI_INLINE void FN(HistogramAdd)(FN(Histogram)* self, size_t val) { + ++self->data_[val]; + ++self->total_count_; +} + +static BROTLI_INLINE void FN(HistogramAddVector)(FN(Histogram)* self, + const DataType* p, size_t n) { + self->total_count_ += n; + n += 1; + while (--n) ++self->data_[*p++]; +} + +static BROTLI_INLINE void FN(HistogramAddHistogram)(FN(Histogram)* self, + const FN(Histogram)* v) { + size_t i; + self->total_count_ += v->total_count_; + for (i = 0; i < DATA_SIZE; ++i) { + self->data_[i] += v->data_[i]; + } +} + +static BROTLI_INLINE size_t FN(HistogramDataSize)(void) { return DATA_SIZE; } +#undef DataType +#undef DATA_SIZE +#undef FN + +BROTLI_INTERNAL void BrotliBuildHistogramsWithContext( + const Command* cmds, const size_t num_commands, + const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split, + const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t pos, + size_t mask, uint8_t prev_byte, uint8_t prev_byte2, + const ContextType* context_modes, HistogramLiteral* literal_histograms, + HistogramCommand* insert_and_copy_histograms, + HistogramDistance* copy_dist_histograms); + +} + +#endif /* BROTLI_ENC_HISTOGRAM_H_ */ diff --git a/third_party/brotli/enc/literal_cost.cpp b/third_party/brotli/enc/literal_cost.cpp new file mode 100644 index 00000000000..3ffdb6cc1f7 --- /dev/null +++ b/third_party/brotli/enc/literal_cost.cpp @@ -0,0 +1,176 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Literal cost model to allow backward reference replacement to be efficient. +*/ + +#include "literal_cost.h" + +#include /* memset */ + +#include + +#include "../common/brotli_platform.h" +#include "fast_log.h" +#include "utf8_util.h" + +using namespace duckdb_brotli; + +static size_t UTF8Position(size_t last, size_t c, size_t clamp) { + if (c < 128) { + return 0; /* Next one is the 'Byte 1' again. */ + } else if (c >= 192) { /* Next one is the 'Byte 2' of utf-8 encoding. */ + return BROTLI_MIN(size_t, 1, clamp); + } else { + /* Let's decide over the last byte if this ends the sequence. */ + if (last < 0xE0) { + return 0; /* Completed two or three byte coding. */ + } else { /* Next one is the 'Byte 3' of utf-8 encoding. */ + return BROTLI_MIN(size_t, 2, clamp); + } + } +} + +static size_t DecideMultiByteStatsLevel(size_t pos, size_t len, size_t mask, + const uint8_t* data) { + size_t counts[3] = { 0 }; + size_t max_utf8 = 1; /* should be 2, but 1 compresses better. */ + size_t last_c = 0; + size_t i; + for (i = 0; i < len; ++i) { + size_t c = data[(pos + i) & mask]; + ++counts[UTF8Position(last_c, c, 2)]; + last_c = c; + } + if (counts[2] < 500) { + max_utf8 = 1; + } + if (counts[1] + counts[2] < 25) { + max_utf8 = 0; + } + return max_utf8; +} + +static void EstimateBitCostsForLiteralsUTF8(size_t pos, size_t len, size_t mask, + const uint8_t* data, + size_t* histogram, float* cost) { + /* max_utf8 is 0 (normal ASCII single byte modeling), + 1 (for 2-byte UTF-8 modeling), or 2 (for 3-byte UTF-8 modeling). */ + const size_t max_utf8 = DecideMultiByteStatsLevel(pos, len, mask, data); + size_t window_half = 495; + size_t in_window = BROTLI_MIN(size_t, window_half, len); + size_t in_window_utf8[3] = { 0 }; + size_t i; + memset(histogram, 0, 3 * 256 * sizeof(histogram[0])); + + { /* Bootstrap histograms. */ + size_t last_c = 0; + size_t utf8_pos = 0; + for (i = 0; i < in_window; ++i) { + size_t c = data[(pos + i) & mask]; + ++histogram[256 * utf8_pos + c]; + ++in_window_utf8[utf8_pos]; + utf8_pos = UTF8Position(last_c, c, max_utf8); + last_c = c; + } + } + + /* Compute bit costs with sliding window. */ + for (i = 0; i < len; ++i) { + if (i >= window_half) { + /* Remove a byte in the past. */ + size_t c = + i < window_half + 1 ? 0 : data[(pos + i - window_half - 1) & mask]; + size_t last_c = + i < window_half + 2 ? 0 : data[(pos + i - window_half - 2) & mask]; + size_t utf8_pos2 = UTF8Position(last_c, c, max_utf8); + --histogram[256 * utf8_pos2 + data[(pos + i - window_half) & mask]]; + --in_window_utf8[utf8_pos2]; + } + if (i + window_half < len) { + /* Add a byte in the future. */ + size_t c = data[(pos + i + window_half - 1) & mask]; + size_t last_c = data[(pos + i + window_half - 2) & mask]; + size_t utf8_pos2 = UTF8Position(last_c, c, max_utf8); + ++histogram[256 * utf8_pos2 + data[(pos + i + window_half) & mask]]; + ++in_window_utf8[utf8_pos2]; + } + { + size_t c = i < 1 ? 0 : data[(pos + i - 1) & mask]; + size_t last_c = i < 2 ? 0 : data[(pos + i - 2) & mask]; + size_t utf8_pos = UTF8Position(last_c, c, max_utf8); + size_t masked_pos = (pos + i) & mask; + size_t histo = histogram[256 * utf8_pos + data[masked_pos]]; + double lit_cost; + if (histo == 0) { + histo = 1; + } + lit_cost = FastLog2(in_window_utf8[utf8_pos]) - FastLog2(histo); + lit_cost += 0.02905; + if (lit_cost < 1.0) { + lit_cost *= 0.5; + lit_cost += 0.5; + } + /* Make the first bytes more expensive -- seems to help, not sure why. + Perhaps because the entropy source is changing its properties + rapidly in the beginning of the file, perhaps because the beginning + of the data is a statistical "anomaly". */ + if (i < 2000) { + lit_cost += 0.7 - ((double)(2000 - i) / 2000.0 * 0.35); + } + cost[i] = (float)lit_cost; + } + } +} + +void duckdb_brotli::BrotliEstimateBitCostsForLiterals(size_t pos, size_t len, size_t mask, + const uint8_t* data, + size_t* histogram, float* cost) { + if (BrotliIsMostlyUTF8(data, pos, mask, len, kMinUTF8Ratio)) { + EstimateBitCostsForLiteralsUTF8(pos, len, mask, data, histogram, cost); + return; + } else { + size_t window_half = 2000; + size_t in_window = BROTLI_MIN(size_t, window_half, len); + size_t i; + memset(histogram, 0, 256 * sizeof(histogram[0])); + + /* Bootstrap histogram. */ + for (i = 0; i < in_window; ++i) { + ++histogram[data[(pos + i) & mask]]; + } + + /* Compute bit costs with sliding window. */ + for (i = 0; i < len; ++i) { + size_t histo; + if (i >= window_half) { + /* Remove a byte in the past. */ + --histogram[data[(pos + i - window_half) & mask]]; + --in_window; + } + if (i + window_half < len) { + /* Add a byte in the future. */ + ++histogram[data[(pos + i + window_half) & mask]]; + ++in_window; + } + histo = histogram[data[(pos + i) & mask]]; + if (histo == 0) { + histo = 1; + } + { + double lit_cost = FastLog2(in_window) - FastLog2(histo); + lit_cost += 0.029; + if (lit_cost < 1.0) { + lit_cost *= 0.5; + lit_cost += 0.5; + } + cost[i] = (float)lit_cost; + } + } + } +} + + diff --git a/third_party/brotli/enc/literal_cost.h b/third_party/brotli/enc/literal_cost.h new file mode 100644 index 00000000000..17ae559a83d --- /dev/null +++ b/third_party/brotli/enc/literal_cost.h @@ -0,0 +1,28 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Literal cost model to allow backward reference replacement to be efficient. +*/ + +#ifndef BROTLI_ENC_LITERAL_COST_H_ +#define BROTLI_ENC_LITERAL_COST_H_ + +#include + +#include "../common/brotli_platform.h" + +namespace duckdb_brotli { + +/* Estimates how many bits the literals in the interval [pos, pos + len) in the + ring-buffer (data, mask) will take entropy coded and writes these estimates + to the cost[0..len) array. */ +BROTLI_INTERNAL void BrotliEstimateBitCostsForLiterals( + size_t pos, size_t len, size_t mask, const uint8_t* data, size_t* histogram, + float* cost); + +} + +#endif /* BROTLI_ENC_LITERAL_COST_H_ */ diff --git a/third_party/brotli/enc/memory.cpp b/third_party/brotli/enc/memory.cpp new file mode 100644 index 00000000000..a4c8b8db41d --- /dev/null +++ b/third_party/brotli/enc/memory.cpp @@ -0,0 +1,190 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Algorithms for distributing the literals and commands of a metablock between + block types and contexts. */ + +#include "memory.h" + +#include /* exit, free, malloc */ +#include /* memcpy */ + +#include + +#include "../common/brotli_platform.h" + +using namespace duckdb_brotli; + +#define MAX_NEW_ALLOCATED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 2) +#define MAX_NEW_FREED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 2) +#define MAX_PERM_ALLOCATED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 1) + +#define PERM_ALLOCATED_OFFSET 0 +#define NEW_ALLOCATED_OFFSET MAX_PERM_ALLOCATED +#define NEW_FREED_OFFSET (MAX_PERM_ALLOCATED + MAX_NEW_ALLOCATED) + +void duckdb_brotli::BrotliInitMemoryManager( + MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func, + void* opaque) { + if (!alloc_func) { + m->alloc_func = duckdb_brotli::BrotliDefaultAllocFunc; + m->free_func = duckdb_brotli::BrotliDefaultFreeFunc; + m->opaque = 0; + } else { + m->alloc_func = alloc_func; + m->free_func = free_func; + m->opaque = opaque; + } +#if !defined(BROTLI_ENCODER_EXIT_ON_OOM) + m->is_oom = BROTLI_FALSE; + m->perm_allocated = 0; + m->new_allocated = 0; + m->new_freed = 0; +#endif /* BROTLI_ENCODER_EXIT_ON_OOM */ +} + +#if defined(BROTLI_ENCODER_EXIT_ON_OOM) + +void* duckdb_brotli::BrotliAllocate(MemoryManager* m, size_t n) { + void* result = m->alloc_func(m->opaque, n); + if (!result) exit(EXIT_FAILURE); + return result; +} + +void duckdb_brotli::BrotliFree(MemoryManager* m, void* p) { + m->free_func(m->opaque, p); +} + +void duckdb_brotli::BrotliWipeOutMemoryManager(MemoryManager* m) { + BROTLI_UNUSED(m); +} + +#else /* BROTLI_ENCODER_EXIT_ON_OOM */ + +static void SortPointers(void** items, const size_t n) { + /* Shell sort. */ + /* TODO(eustas): fine-tune for "many slots" case */ + static const size_t gaps[] = {23, 10, 4, 1}; + int g = 0; + for (; g < 4; ++g) { + size_t gap = gaps[g]; + size_t i; + for (i = gap; i < n; ++i) { + size_t j = i; + void* tmp = items[i]; + for (; j >= gap && tmp < items[j - gap]; j -= gap) { + items[j] = items[j - gap]; + } + items[j] = tmp; + } + } +} + +static size_t Annihilate(void** a, size_t a_len, void** b, size_t b_len) { + size_t a_read_index = 0; + size_t b_read_index = 0; + size_t a_write_index = 0; + size_t b_write_index = 0; + size_t annihilated = 0; + while (a_read_index < a_len && b_read_index < b_len) { + if (a[a_read_index] == b[b_read_index]) { + a_read_index++; + b_read_index++; + annihilated++; + } else if (a[a_read_index] < b[b_read_index]) { + a[a_write_index++] = a[a_read_index++]; + } else { + b[b_write_index++] = b[b_read_index++]; + } + } + while (a_read_index < a_len) a[a_write_index++] = a[a_read_index++]; + while (b_read_index < b_len) b[b_write_index++] = b[b_read_index++]; + return annihilated; +} + +static void CollectGarbagePointers(MemoryManager* m) { + size_t annihilated; + SortPointers(m->pointers + NEW_ALLOCATED_OFFSET, m->new_allocated); + SortPointers(m->pointers + NEW_FREED_OFFSET, m->new_freed); + annihilated = Annihilate( + m->pointers + NEW_ALLOCATED_OFFSET, m->new_allocated, + m->pointers + NEW_FREED_OFFSET, m->new_freed); + m->new_allocated -= annihilated; + m->new_freed -= annihilated; + + if (m->new_freed != 0) { + annihilated = Annihilate( + m->pointers + PERM_ALLOCATED_OFFSET, m->perm_allocated, + m->pointers + NEW_FREED_OFFSET, m->new_freed); + m->perm_allocated -= annihilated; + m->new_freed -= annihilated; + BROTLI_DCHECK(m->new_freed == 0); + } + + if (m->new_allocated != 0) { + BROTLI_DCHECK(m->perm_allocated + m->new_allocated <= MAX_PERM_ALLOCATED); + memcpy(m->pointers + PERM_ALLOCATED_OFFSET + m->perm_allocated, + m->pointers + NEW_ALLOCATED_OFFSET, + sizeof(void*) * m->new_allocated); + m->perm_allocated += m->new_allocated; + m->new_allocated = 0; + SortPointers(m->pointers + PERM_ALLOCATED_OFFSET, m->perm_allocated); + } +} + +void* BrotliAllocate(MemoryManager* m, size_t n) { + void* result = m->alloc_func(m->opaque, n); + if (!result) { + m->is_oom = BROTLI_TRUE; + return NULL; + } + if (m->new_allocated == MAX_NEW_ALLOCATED) CollectGarbagePointers(m); + m->pointers[NEW_ALLOCATED_OFFSET + (m->new_allocated++)] = result; + return result; +} + +void BrotliFree(MemoryManager* m, void* p) { + if (!p) return; + m->free_func(m->opaque, p); + if (m->new_freed == MAX_NEW_FREED) CollectGarbagePointers(m); + m->pointers[NEW_FREED_OFFSET + (m->new_freed++)] = p; +} + +void BrotliWipeOutMemoryManager(MemoryManager* m) { + size_t i; + CollectGarbagePointers(m); + /* Now all unfreed pointers are in perm-allocated list. */ + for (i = 0; i < m->perm_allocated; ++i) { + m->free_func(m->opaque, m->pointers[PERM_ALLOCATED_OFFSET + i]); + } + m->perm_allocated = 0; +} + +#endif /* BROTLI_ENCODER_EXIT_ON_OOM */ + +void* duckdb_brotli::BrotliBootstrapAlloc(size_t size, + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) { + if (!alloc_func && !free_func) { + return malloc(size); + } else if (alloc_func && free_func) { + return alloc_func(opaque, size); + } + return NULL; +} + +void duckdb_brotli::BrotliBootstrapFree(void* address, MemoryManager* m) { + if (!address) { + /* Should not happen! */ + return; + } else { + /* Copy values, as those would be freed. */ + brotli_free_func free_func = m->free_func; + void* opaque = m->opaque; + free_func(opaque, address); + } +} + + diff --git a/third_party/brotli/enc/memory.h b/third_party/brotli/enc/memory.h new file mode 100644 index 00000000000..2c693d55245 --- /dev/null +++ b/third_party/brotli/enc/memory.h @@ -0,0 +1,127 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Macros for memory management. */ + +#ifndef BROTLI_ENC_MEMORY_H_ +#define BROTLI_ENC_MEMORY_H_ + +#include /* memcpy */ + +#include + +#include "../common/brotli_platform.h" + +namespace duckdb_brotli { + +#if !defined(BROTLI_ENCODER_CLEANUP_ON_OOM) && \ + !defined(BROTLI_ENCODER_EXIT_ON_OOM) +#define BROTLI_ENCODER_EXIT_ON_OOM +#endif + +#if !defined(BROTLI_ENCODER_EXIT_ON_OOM) +#if defined(BROTLI_EXPERIMENTAL) +#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS (48*1024) +#else /* BROTLI_EXPERIMENTAL */ +#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 256 +#endif /* BROTLI_EXPERIMENTAL */ +#else /* BROTLI_ENCODER_EXIT_ON_OOM */ +#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 0 +#endif /* BROTLI_ENCODER_EXIT_ON_OOM */ + +typedef struct MemoryManager { + brotli_alloc_func alloc_func; + brotli_free_func free_func; + void* opaque; +#if !defined(BROTLI_ENCODER_EXIT_ON_OOM) + BROTLI_BOOL is_oom; + size_t perm_allocated; + size_t new_allocated; + size_t new_freed; + void* pointers[BROTLI_ENCODER_MEMORY_MANAGER_SLOTS]; +#endif /* BROTLI_ENCODER_EXIT_ON_OOM */ +} MemoryManager; + +BROTLI_INTERNAL void BrotliInitMemoryManager( + MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func, + void* opaque); + +BROTLI_INTERNAL void* BrotliAllocate(MemoryManager* m, size_t n); +#define BROTLI_ALLOC(M, T, N) \ + ((N) > 0 ? ((T*)BrotliAllocate((M), (N) * sizeof(T))) : NULL) + +BROTLI_INTERNAL void BrotliFree(MemoryManager* m, void* p); +#define BROTLI_FREE(M, P) { \ + BrotliFree((M), (P)); \ + P = NULL; \ +} + +#if defined(BROTLI_ENCODER_EXIT_ON_OOM) +#define BROTLI_IS_OOM(M) (!!0) +#else /* BROTLI_ENCODER_EXIT_ON_OOM */ +#define BROTLI_IS_OOM(M) (!!(M)->is_oom) +#endif /* BROTLI_ENCODER_EXIT_ON_OOM */ + +/* +BROTLI_IS_NULL is a fake check, BROTLI_IS_OOM does the heavy lifting. +The only purpose of it is to explain static analyzers the state of things. +NB: use ONLY together with BROTLI_IS_OOM + AND ONLY for allocations in the current scope. + */ +#if defined(__clang_analyzer__) && !defined(BROTLI_ENCODER_EXIT_ON_OOM) +#define BROTLI_IS_NULL(A) ((A) == nullptr) +#else /* defined(__clang_analyzer__) */ +#define BROTLI_IS_NULL(A) (!!0) +#endif /* defined(__clang_analyzer__) */ + +BROTLI_INTERNAL void BrotliWipeOutMemoryManager(MemoryManager* m); + +/* +Dynamically grows array capacity to at least the requested size +M: MemoryManager +T: data type +A: array +C: capacity +R: requested size +*/ +#define BROTLI_ENSURE_CAPACITY(M, T, A, C, R) { \ + if (C < (R)) { \ + size_t _new_size = (C == 0) ? (R) : C; \ + T* new_array; \ + while (_new_size < (R)) _new_size *= 2; \ + new_array = BROTLI_ALLOC((M), T, _new_size); \ + if (!BROTLI_IS_OOM(M) && !BROTLI_IS_NULL(new_array) && C != 0) \ + memcpy(new_array, A, C * sizeof(T)); \ + BROTLI_FREE((M), A); \ + A = new_array; \ + C = _new_size; \ + } \ +} + +/* +Appends value and dynamically grows array capacity when needed +M: MemoryManager +T: data type +A: array +C: array capacity +S: array size +V: value to append +*/ +#define BROTLI_ENSURE_CAPACITY_APPEND(M, T, A, C, S, V) { \ + (S)++; \ + BROTLI_ENSURE_CAPACITY(M, T, A, C, S); \ + A[(S) - 1] = (V); \ +} + +/* "Bootstrap" allocations are not tracked by memory manager; should be used + only to allocate MemoryManager itself (or structure containing it). */ +BROTLI_INTERNAL void* BrotliBootstrapAlloc(size_t size, + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); +BROTLI_INTERNAL void BrotliBootstrapFree(void* address, MemoryManager* m); + +} + +#endif /* BROTLI_ENC_MEMORY_H_ */ diff --git a/third_party/brotli/enc/metablock.cpp b/third_party/brotli/enc/metablock.cpp new file mode 100644 index 00000000000..a5758c24eff --- /dev/null +++ b/third_party/brotli/enc/metablock.cpp @@ -0,0 +1,1225 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Algorithms for distributing the literals and commands of a metablock between + block types and contexts. */ + +#include "metablock.h" + +#include + +#include "../common/brotli_constants.h" +#include "../common/context.h" +#include "../common/brotli_platform.h" +#include "bit_cost.h" +#include "block_splitter.h" +#include "cluster.h" +#include "entropy_encode.h" +#include "histogram.h" +#include "memory.h" +#include "quality.h" + +using namespace duckdb_brotli; + +void duckdb_brotli::BrotliInitDistanceParams(BrotliDistanceParams* dist_params, + uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window) { + uint32_t alphabet_size_max; + uint32_t alphabet_size_limit; + uint32_t max_distance; + + dist_params->distance_postfix_bits = npostfix; + dist_params->num_direct_distance_codes = ndirect; + + alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE( + npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS); + alphabet_size_limit = alphabet_size_max; + max_distance = ndirect + (1U << (BROTLI_MAX_DISTANCE_BITS + npostfix + 2)) - + (1U << (npostfix + 2)); + + if (large_window) { + BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit( + BROTLI_MAX_ALLOWED_DISTANCE, npostfix, ndirect); + alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE( + npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS); + alphabet_size_limit = limit.max_alphabet_size; + max_distance = limit.max_distance; + } + + dist_params->alphabet_size_max = alphabet_size_max; + dist_params->alphabet_size_limit = alphabet_size_limit; + dist_params->max_distance = max_distance; +} + +static void RecomputeDistancePrefixes(Command* cmds, + size_t num_commands, + const BrotliDistanceParams* orig_params, + const BrotliDistanceParams* new_params) { + size_t i; + + if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits && + orig_params->num_direct_distance_codes == + new_params->num_direct_distance_codes) { + return; + } + + for (i = 0; i < num_commands; ++i) { + Command* cmd = &cmds[i]; + if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) { + PrefixEncodeCopyDistance(CommandRestoreDistanceCode(cmd, orig_params), + new_params->num_direct_distance_codes, + new_params->distance_postfix_bits, + &cmd->dist_prefix_, + &cmd->dist_extra_); + } + } +} + +static BROTLI_BOOL ComputeDistanceCost(const Command* cmds, + size_t num_commands, + const BrotliDistanceParams* orig_params, + const BrotliDistanceParams* new_params, + double* cost, + HistogramDistance* tmp) { + size_t i; + BROTLI_BOOL equal_params = BROTLI_FALSE; + uint16_t dist_prefix; + uint32_t dist_extra; + double extra_bits = 0.0; + HistogramClearDistance(tmp); + + if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits && + orig_params->num_direct_distance_codes == + new_params->num_direct_distance_codes) { + equal_params = BROTLI_TRUE; + } + + for (i = 0; i < num_commands; i++) { + const Command* cmd = &cmds[i]; + if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) { + if (equal_params) { + dist_prefix = cmd->dist_prefix_; + } else { + uint32_t distance = CommandRestoreDistanceCode(cmd, orig_params); + if (distance > new_params->max_distance) { + return BROTLI_FALSE; + } + PrefixEncodeCopyDistance(distance, + new_params->num_direct_distance_codes, + new_params->distance_postfix_bits, + &dist_prefix, + &dist_extra); + } + HistogramAddDistance(tmp, dist_prefix & 0x3FF); + extra_bits += dist_prefix >> 10; + } + } + + *cost = BrotliPopulationCostDistance(tmp) + extra_bits; + return BROTLI_TRUE; +} + +void duckdb_brotli::BrotliBuildMetaBlock(MemoryManager* m, + const uint8_t* ringbuffer, + const size_t pos, + const size_t mask, + BrotliEncoderParams* params, + uint8_t prev_byte, + uint8_t prev_byte2, + Command* cmds, + size_t num_commands, + ContextType literal_context_mode, + MetaBlockSplit* mb) { + /* Histogram ids need to fit in one byte. */ + static const size_t kMaxNumberOfHistograms = 256; + HistogramDistance* distance_histograms; + HistogramLiteral* literal_histograms; + ContextType* literal_context_modes = NULL; + size_t literal_histograms_size; + size_t distance_histograms_size; + size_t i; + size_t literal_context_multiplier = 1; + uint32_t npostfix; + uint32_t ndirect_msb = 0; + BROTLI_BOOL check_orig = BROTLI_TRUE; + double best_dist_cost = 1e99; + BrotliDistanceParams orig_params = params->dist; + BrotliDistanceParams new_params = params->dist; + HistogramDistance* tmp = BROTLI_ALLOC(m, HistogramDistance, 1); + + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return; + + for (npostfix = 0; npostfix <= BROTLI_MAX_NPOSTFIX; npostfix++) { + for (; ndirect_msb < 16; ndirect_msb++) { + uint32_t ndirect = ndirect_msb << npostfix; + BROTLI_BOOL skip; + double dist_cost; + BrotliInitDistanceParams(&new_params, npostfix, ndirect, + params->large_window); + if (npostfix == orig_params.distance_postfix_bits && + ndirect == orig_params.num_direct_distance_codes) { + check_orig = BROTLI_FALSE; + } + skip = !ComputeDistanceCost( + cmds, num_commands, &orig_params, &new_params, &dist_cost, tmp); + if (skip || (dist_cost > best_dist_cost)) { + break; + } + best_dist_cost = dist_cost; + params->dist = new_params; + } + if (ndirect_msb > 0) ndirect_msb--; + ndirect_msb /= 2; + } + if (check_orig) { + double dist_cost; + ComputeDistanceCost(cmds, num_commands, &orig_params, &orig_params, + &dist_cost, tmp); + if (dist_cost < best_dist_cost) { + /* NB: currently unused; uncomment when more param tuning is added. */ + /* best_dist_cost = dist_cost; */ + params->dist = orig_params; + } + } + BROTLI_FREE(m, tmp); + RecomputeDistancePrefixes(cmds, num_commands, &orig_params, ¶ms->dist); + + BrotliSplitBlock(m, cmds, num_commands, + ringbuffer, pos, mask, params, + &mb->literal_split, + &mb->command_split, + &mb->distance_split); + if (BROTLI_IS_OOM(m)) return; + + if (!params->disable_literal_context_modeling) { + literal_context_multiplier = 1 << BROTLI_LITERAL_CONTEXT_BITS; + literal_context_modes = + BROTLI_ALLOC(m, ContextType, mb->literal_split.num_types); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literal_context_modes)) return; + for (i = 0; i < mb->literal_split.num_types; ++i) { + literal_context_modes[i] = literal_context_mode; + } + } + + literal_histograms_size = + mb->literal_split.num_types * literal_context_multiplier; + literal_histograms = + BROTLI_ALLOC(m, HistogramLiteral, literal_histograms_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literal_histograms)) return; + ClearHistogramsLiteral(literal_histograms, literal_histograms_size); + + distance_histograms_size = + mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS; + distance_histograms = + BROTLI_ALLOC(m, HistogramDistance, distance_histograms_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(distance_histograms)) return; + ClearHistogramsDistance(distance_histograms, distance_histograms_size); + + BROTLI_DCHECK(mb->command_histograms == 0); + mb->command_histograms_size = mb->command_split.num_types; + mb->command_histograms = + BROTLI_ALLOC(m, HistogramCommand, mb->command_histograms_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->command_histograms)) return; + ClearHistogramsCommand(mb->command_histograms, mb->command_histograms_size); + + BrotliBuildHistogramsWithContext(cmds, num_commands, + &mb->literal_split, &mb->command_split, &mb->distance_split, + ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_modes, + literal_histograms, mb->command_histograms, distance_histograms); + BROTLI_FREE(m, literal_context_modes); + + BROTLI_DCHECK(mb->literal_context_map == 0); + mb->literal_context_map_size = + mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS; + mb->literal_context_map = + BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_context_map)) return; + + BROTLI_DCHECK(mb->literal_histograms == 0); + mb->literal_histograms_size = mb->literal_context_map_size; + mb->literal_histograms = + BROTLI_ALLOC(m, HistogramLiteral, mb->literal_histograms_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_histograms)) return; + + BrotliClusterHistogramsLiteral(m, literal_histograms, literal_histograms_size, + kMaxNumberOfHistograms, mb->literal_histograms, + &mb->literal_histograms_size, mb->literal_context_map); + if (BROTLI_IS_OOM(m)) return; + BROTLI_FREE(m, literal_histograms); + + if (params->disable_literal_context_modeling) { + /* Distribute assignment to all contexts. */ + for (i = mb->literal_split.num_types; i != 0;) { + size_t j = 0; + i--; + for (; j < (1 << BROTLI_LITERAL_CONTEXT_BITS); j++) { + mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] = + mb->literal_context_map[i]; + } + } + } + + BROTLI_DCHECK(mb->distance_context_map == 0); + mb->distance_context_map_size = + mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS; + mb->distance_context_map = + BROTLI_ALLOC(m, uint32_t, mb->distance_context_map_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->distance_context_map)) return; + + BROTLI_DCHECK(mb->distance_histograms == 0); + mb->distance_histograms_size = mb->distance_context_map_size; + mb->distance_histograms = + BROTLI_ALLOC(m, HistogramDistance, mb->distance_histograms_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->distance_histograms)) return; + + BrotliClusterHistogramsDistance(m, distance_histograms, + mb->distance_context_map_size, + kMaxNumberOfHistograms, + mb->distance_histograms, + &mb->distance_histograms_size, + mb->distance_context_map); + if (BROTLI_IS_OOM(m)) return; + BROTLI_FREE(m, distance_histograms); +} + +#define FN(X) X ## Literal +/* NOLINT(build/header_guard) */ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +#define HistogramType FN(Histogram) + +/* Greedy block splitter for one block category (literal, command or distance). +*/ +typedef struct FN(BlockSplitter) { + /* Alphabet size of particular block category. */ + size_t alphabet_size_; + /* We collect at least this many symbols for each block. */ + size_t min_block_size_; + /* We merge histograms A and B if + entropy(A+B) < entropy(A) + entropy(B) + split_threshold_, + where A is the current histogram and B is the histogram of the last or the + second last block type. */ + double split_threshold_; + + size_t num_blocks_; + BlockSplit* split_; /* not owned */ + HistogramType* histograms_; /* not owned */ + size_t* histograms_size_; /* not owned */ + + /* Temporary storage for BlockSplitterFinishBlock. */ + HistogramType combined_histo[2]; + + /* The number of symbols that we want to collect before deciding on whether + or not to merge the block with a previous one or emit a new block. */ + size_t target_block_size_; + /* The number of symbols in the current histogram. */ + size_t block_size_; + /* Offset of the current histogram. */ + size_t curr_histogram_ix_; + /* Offset of the histograms of the previous two block types. */ + size_t last_histogram_ix_[2]; + /* Entropy of the previous two block types. */ + double last_entropy_[2]; + /* The number of times we merged the current block with the last one. */ + size_t merge_last_count_; +} FN(BlockSplitter); + +static void FN(InitBlockSplitter)( + MemoryManager* m, FN(BlockSplitter)* self, size_t alphabet_size, + size_t min_block_size, double split_threshold, size_t num_symbols, + BlockSplit* split, HistogramType** histograms, size_t* histograms_size) { + size_t max_num_blocks = num_symbols / min_block_size + 1; + /* We have to allocate one more histogram than the maximum number of block + types for the current histogram when the meta-block is too big. */ + size_t max_num_types = + BROTLI_MIN(size_t, max_num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 1); + self->alphabet_size_ = alphabet_size; + self->min_block_size_ = min_block_size; + self->split_threshold_ = split_threshold; + self->num_blocks_ = 0; + self->split_ = split; + self->histograms_size_ = histograms_size; + self->target_block_size_ = min_block_size; + self->block_size_ = 0; + self->curr_histogram_ix_ = 0; + self->merge_last_count_ = 0; + BROTLI_ENSURE_CAPACITY(m, uint8_t, + split->types, split->types_alloc_size, max_num_blocks); + BROTLI_ENSURE_CAPACITY(m, uint32_t, + split->lengths, split->lengths_alloc_size, max_num_blocks); + if (BROTLI_IS_OOM(m)) return; + self->split_->num_blocks = max_num_blocks; + BROTLI_DCHECK(*histograms == 0); + *histograms_size = max_num_types; + *histograms = BROTLI_ALLOC(m, HistogramType, *histograms_size); + self->histograms_ = *histograms; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return; + /* Clear only current histogram. */ + FN(HistogramClear)(&self->histograms_[0]); + self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0; +} + +/* Does either of three things: + (1) emits the current block with a new block type; + (2) emits the current block with the type of the second last block; + (3) merges the current block with the last block. */ +static void FN(BlockSplitterFinishBlock)( + FN(BlockSplitter)* self, BROTLI_BOOL is_final) { + BlockSplit* split = self->split_; + double* last_entropy = self->last_entropy_; + HistogramType* histograms = self->histograms_; + self->block_size_ = + BROTLI_MAX(size_t, self->block_size_, self->min_block_size_); + if (self->num_blocks_ == 0) { + /* Create first block. */ + split->lengths[0] = (uint32_t)self->block_size_; + split->types[0] = 0; + last_entropy[0] = + BitsEntropy(histograms[0].data_, self->alphabet_size_); + last_entropy[1] = last_entropy[0]; + ++self->num_blocks_; + ++split->num_types; + ++self->curr_histogram_ix_; + if (self->curr_histogram_ix_ < *self->histograms_size_) + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + self->block_size_ = 0; + } else if (self->block_size_ > 0) { + double entropy = BitsEntropy(histograms[self->curr_histogram_ix_].data_, + self->alphabet_size_); + double combined_entropy[2]; + double diff[2]; + size_t j; + for (j = 0; j < 2; ++j) { + size_t last_histogram_ix = self->last_histogram_ix_[j]; + self->combined_histo[j] = histograms[self->curr_histogram_ix_]; + FN(HistogramAddHistogram)(&self->combined_histo[j], + &histograms[last_histogram_ix]); + combined_entropy[j] = BitsEntropy( + &self->combined_histo[j].data_[0], self->alphabet_size_); + diff[j] = combined_entropy[j] - entropy - last_entropy[j]; + } + + if (split->num_types < BROTLI_MAX_NUMBER_OF_BLOCK_TYPES && + diff[0] > self->split_threshold_ && + diff[1] > self->split_threshold_) { + /* Create new block. */ + split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; + split->types[self->num_blocks_] = (uint8_t)split->num_types; + self->last_histogram_ix_[1] = self->last_histogram_ix_[0]; + self->last_histogram_ix_[0] = (uint8_t)split->num_types; + last_entropy[1] = last_entropy[0]; + last_entropy[0] = entropy; + ++self->num_blocks_; + ++split->num_types; + ++self->curr_histogram_ix_; + if (self->curr_histogram_ix_ < *self->histograms_size_) + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + self->block_size_ = 0; + self->merge_last_count_ = 0; + self->target_block_size_ = self->min_block_size_; + } else if (diff[1] < diff[0] - 20.0) { + /* Combine this block with second last block. */ + split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; + split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2]; + BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1); + histograms[self->last_histogram_ix_[0]] = self->combined_histo[1]; + last_entropy[1] = last_entropy[0]; + last_entropy[0] = combined_entropy[1]; + ++self->num_blocks_; + self->block_size_ = 0; + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + self->merge_last_count_ = 0; + self->target_block_size_ = self->min_block_size_; + } else { + /* Combine this block with last block. */ + split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_; + histograms[self->last_histogram_ix_[0]] = self->combined_histo[0]; + last_entropy[0] = combined_entropy[0]; + if (split->num_types == 1) { + last_entropy[1] = last_entropy[0]; + } + self->block_size_ = 0; + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + if (++self->merge_last_count_ > 1) { + self->target_block_size_ += self->min_block_size_; + } + } + } + if (is_final) { + *self->histograms_size_ = split->num_types; + split->num_blocks = self->num_blocks_; + } +} + +/* Adds the next symbol to the current histogram. When the current histogram + reaches the target size, decides on merging the block. */ +static void FN(BlockSplitterAddSymbol)(FN(BlockSplitter)* self, size_t symbol) { + FN(HistogramAdd)(&self->histograms_[self->curr_histogram_ix_], symbol); + ++self->block_size_; + if (self->block_size_ == self->target_block_size_) { + FN(BlockSplitterFinishBlock)(self, /* is_final = */ BROTLI_FALSE); + } +} + +#undef HistogramType +#undef FN + +#define FN(X) X ## Command +/* NOLINT(build/header_guard) */ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +#define HistogramType FN(Histogram) + +/* Greedy block splitter for one block category (literal, command or distance). +*/ +typedef struct FN(BlockSplitter) { + /* Alphabet size of particular block category. */ + size_t alphabet_size_; + /* We collect at least this many symbols for each block. */ + size_t min_block_size_; + /* We merge histograms A and B if + entropy(A+B) < entropy(A) + entropy(B) + split_threshold_, + where A is the current histogram and B is the histogram of the last or the + second last block type. */ + double split_threshold_; + + size_t num_blocks_; + BlockSplit* split_; /* not owned */ + HistogramType* histograms_; /* not owned */ + size_t* histograms_size_; /* not owned */ + + /* Temporary storage for BlockSplitterFinishBlock. */ + HistogramType combined_histo[2]; + + /* The number of symbols that we want to collect before deciding on whether + or not to merge the block with a previous one or emit a new block. */ + size_t target_block_size_; + /* The number of symbols in the current histogram. */ + size_t block_size_; + /* Offset of the current histogram. */ + size_t curr_histogram_ix_; + /* Offset of the histograms of the previous two block types. */ + size_t last_histogram_ix_[2]; + /* Entropy of the previous two block types. */ + double last_entropy_[2]; + /* The number of times we merged the current block with the last one. */ + size_t merge_last_count_; +} FN(BlockSplitter); + +static void FN(InitBlockSplitter)( + MemoryManager* m, FN(BlockSplitter)* self, size_t alphabet_size, + size_t min_block_size, double split_threshold, size_t num_symbols, + BlockSplit* split, HistogramType** histograms, size_t* histograms_size) { + size_t max_num_blocks = num_symbols / min_block_size + 1; + /* We have to allocate one more histogram than the maximum number of block + types for the current histogram when the meta-block is too big. */ + size_t max_num_types = + BROTLI_MIN(size_t, max_num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 1); + self->alphabet_size_ = alphabet_size; + self->min_block_size_ = min_block_size; + self->split_threshold_ = split_threshold; + self->num_blocks_ = 0; + self->split_ = split; + self->histograms_size_ = histograms_size; + self->target_block_size_ = min_block_size; + self->block_size_ = 0; + self->curr_histogram_ix_ = 0; + self->merge_last_count_ = 0; + BROTLI_ENSURE_CAPACITY(m, uint8_t, + split->types, split->types_alloc_size, max_num_blocks); + BROTLI_ENSURE_CAPACITY(m, uint32_t, + split->lengths, split->lengths_alloc_size, max_num_blocks); + if (BROTLI_IS_OOM(m)) return; + self->split_->num_blocks = max_num_blocks; + BROTLI_DCHECK(*histograms == 0); + *histograms_size = max_num_types; + *histograms = BROTLI_ALLOC(m, HistogramType, *histograms_size); + self->histograms_ = *histograms; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return; + /* Clear only current histogram. */ + FN(HistogramClear)(&self->histograms_[0]); + self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0; +} + +/* Does either of three things: + (1) emits the current block with a new block type; + (2) emits the current block with the type of the second last block; + (3) merges the current block with the last block. */ +static void FN(BlockSplitterFinishBlock)( + FN(BlockSplitter)* self, BROTLI_BOOL is_final) { + BlockSplit* split = self->split_; + double* last_entropy = self->last_entropy_; + HistogramType* histograms = self->histograms_; + self->block_size_ = + BROTLI_MAX(size_t, self->block_size_, self->min_block_size_); + if (self->num_blocks_ == 0) { + /* Create first block. */ + split->lengths[0] = (uint32_t)self->block_size_; + split->types[0] = 0; + last_entropy[0] = + BitsEntropy(histograms[0].data_, self->alphabet_size_); + last_entropy[1] = last_entropy[0]; + ++self->num_blocks_; + ++split->num_types; + ++self->curr_histogram_ix_; + if (self->curr_histogram_ix_ < *self->histograms_size_) + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + self->block_size_ = 0; + } else if (self->block_size_ > 0) { + double entropy = BitsEntropy(histograms[self->curr_histogram_ix_].data_, + self->alphabet_size_); + double combined_entropy[2]; + double diff[2]; + size_t j; + for (j = 0; j < 2; ++j) { + size_t last_histogram_ix = self->last_histogram_ix_[j]; + self->combined_histo[j] = histograms[self->curr_histogram_ix_]; + FN(HistogramAddHistogram)(&self->combined_histo[j], + &histograms[last_histogram_ix]); + combined_entropy[j] = BitsEntropy( + &self->combined_histo[j].data_[0], self->alphabet_size_); + diff[j] = combined_entropy[j] - entropy - last_entropy[j]; + } + + if (split->num_types < BROTLI_MAX_NUMBER_OF_BLOCK_TYPES && + diff[0] > self->split_threshold_ && + diff[1] > self->split_threshold_) { + /* Create new block. */ + split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; + split->types[self->num_blocks_] = (uint8_t)split->num_types; + self->last_histogram_ix_[1] = self->last_histogram_ix_[0]; + self->last_histogram_ix_[0] = (uint8_t)split->num_types; + last_entropy[1] = last_entropy[0]; + last_entropy[0] = entropy; + ++self->num_blocks_; + ++split->num_types; + ++self->curr_histogram_ix_; + if (self->curr_histogram_ix_ < *self->histograms_size_) + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + self->block_size_ = 0; + self->merge_last_count_ = 0; + self->target_block_size_ = self->min_block_size_; + } else if (diff[1] < diff[0] - 20.0) { + /* Combine this block with second last block. */ + split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; + split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2]; + BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1); + histograms[self->last_histogram_ix_[0]] = self->combined_histo[1]; + last_entropy[1] = last_entropy[0]; + last_entropy[0] = combined_entropy[1]; + ++self->num_blocks_; + self->block_size_ = 0; + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + self->merge_last_count_ = 0; + self->target_block_size_ = self->min_block_size_; + } else { + /* Combine this block with last block. */ + split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_; + histograms[self->last_histogram_ix_[0]] = self->combined_histo[0]; + last_entropy[0] = combined_entropy[0]; + if (split->num_types == 1) { + last_entropy[1] = last_entropy[0]; + } + self->block_size_ = 0; + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + if (++self->merge_last_count_ > 1) { + self->target_block_size_ += self->min_block_size_; + } + } + } + if (is_final) { + *self->histograms_size_ = split->num_types; + split->num_blocks = self->num_blocks_; + } +} + +/* Adds the next symbol to the current histogram. When the current histogram + reaches the target size, decides on merging the block. */ +static void FN(BlockSplitterAddSymbol)(FN(BlockSplitter)* self, size_t symbol) { + FN(HistogramAdd)(&self->histograms_[self->curr_histogram_ix_], symbol); + ++self->block_size_; + if (self->block_size_ == self->target_block_size_) { + FN(BlockSplitterFinishBlock)(self, /* is_final = */ BROTLI_FALSE); + } +} + +#undef HistogramType +#undef FN + +#define FN(X) X ## Distance +/* NOLINT(build/header_guard) */ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* template parameters: FN */ + +#define HistogramType FN(Histogram) + +/* Greedy block splitter for one block category (literal, command or distance). +*/ +typedef struct FN(BlockSplitter) { + /* Alphabet size of particular block category. */ + size_t alphabet_size_; + /* We collect at least this many symbols for each block. */ + size_t min_block_size_; + /* We merge histograms A and B if + entropy(A+B) < entropy(A) + entropy(B) + split_threshold_, + where A is the current histogram and B is the histogram of the last or the + second last block type. */ + double split_threshold_; + + size_t num_blocks_; + BlockSplit* split_; /* not owned */ + HistogramType* histograms_; /* not owned */ + size_t* histograms_size_; /* not owned */ + + /* Temporary storage for BlockSplitterFinishBlock. */ + HistogramType combined_histo[2]; + + /* The number of symbols that we want to collect before deciding on whether + or not to merge the block with a previous one or emit a new block. */ + size_t target_block_size_; + /* The number of symbols in the current histogram. */ + size_t block_size_; + /* Offset of the current histogram. */ + size_t curr_histogram_ix_; + /* Offset of the histograms of the previous two block types. */ + size_t last_histogram_ix_[2]; + /* Entropy of the previous two block types. */ + double last_entropy_[2]; + /* The number of times we merged the current block with the last one. */ + size_t merge_last_count_; +} FN(BlockSplitter); + +static void FN(InitBlockSplitter)( + MemoryManager* m, FN(BlockSplitter)* self, size_t alphabet_size, + size_t min_block_size, double split_threshold, size_t num_symbols, + BlockSplit* split, HistogramType** histograms, size_t* histograms_size) { + size_t max_num_blocks = num_symbols / min_block_size + 1; + /* We have to allocate one more histogram than the maximum number of block + types for the current histogram when the meta-block is too big. */ + size_t max_num_types = + BROTLI_MIN(size_t, max_num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 1); + self->alphabet_size_ = alphabet_size; + self->min_block_size_ = min_block_size; + self->split_threshold_ = split_threshold; + self->num_blocks_ = 0; + self->split_ = split; + self->histograms_size_ = histograms_size; + self->target_block_size_ = min_block_size; + self->block_size_ = 0; + self->curr_histogram_ix_ = 0; + self->merge_last_count_ = 0; + BROTLI_ENSURE_CAPACITY(m, uint8_t, + split->types, split->types_alloc_size, max_num_blocks); + BROTLI_ENSURE_CAPACITY(m, uint32_t, + split->lengths, split->lengths_alloc_size, max_num_blocks); + if (BROTLI_IS_OOM(m)) return; + self->split_->num_blocks = max_num_blocks; + BROTLI_DCHECK(*histograms == 0); + *histograms_size = max_num_types; + *histograms = BROTLI_ALLOC(m, HistogramType, *histograms_size); + self->histograms_ = *histograms; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return; + /* Clear only current histogram. */ + FN(HistogramClear)(&self->histograms_[0]); + self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0; +} + +/* Does either of three things: + (1) emits the current block with a new block type; + (2) emits the current block with the type of the second last block; + (3) merges the current block with the last block. */ +static void FN(BlockSplitterFinishBlock)( + FN(BlockSplitter)* self, BROTLI_BOOL is_final) { + BlockSplit* split = self->split_; + double* last_entropy = self->last_entropy_; + HistogramType* histograms = self->histograms_; + self->block_size_ = + BROTLI_MAX(size_t, self->block_size_, self->min_block_size_); + if (self->num_blocks_ == 0) { + /* Create first block. */ + split->lengths[0] = (uint32_t)self->block_size_; + split->types[0] = 0; + last_entropy[0] = + BitsEntropy(histograms[0].data_, self->alphabet_size_); + last_entropy[1] = last_entropy[0]; + ++self->num_blocks_; + ++split->num_types; + ++self->curr_histogram_ix_; + if (self->curr_histogram_ix_ < *self->histograms_size_) + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + self->block_size_ = 0; + } else if (self->block_size_ > 0) { + double entropy = BitsEntropy(histograms[self->curr_histogram_ix_].data_, + self->alphabet_size_); + double combined_entropy[2]; + double diff[2]; + size_t j; + for (j = 0; j < 2; ++j) { + size_t last_histogram_ix = self->last_histogram_ix_[j]; + self->combined_histo[j] = histograms[self->curr_histogram_ix_]; + FN(HistogramAddHistogram)(&self->combined_histo[j], + &histograms[last_histogram_ix]); + combined_entropy[j] = BitsEntropy( + &self->combined_histo[j].data_[0], self->alphabet_size_); + diff[j] = combined_entropy[j] - entropy - last_entropy[j]; + } + + if (split->num_types < BROTLI_MAX_NUMBER_OF_BLOCK_TYPES && + diff[0] > self->split_threshold_ && + diff[1] > self->split_threshold_) { + /* Create new block. */ + split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; + split->types[self->num_blocks_] = (uint8_t)split->num_types; + self->last_histogram_ix_[1] = self->last_histogram_ix_[0]; + self->last_histogram_ix_[0] = (uint8_t)split->num_types; + last_entropy[1] = last_entropy[0]; + last_entropy[0] = entropy; + ++self->num_blocks_; + ++split->num_types; + ++self->curr_histogram_ix_; + if (self->curr_histogram_ix_ < *self->histograms_size_) + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + self->block_size_ = 0; + self->merge_last_count_ = 0; + self->target_block_size_ = self->min_block_size_; + } else if (diff[1] < diff[0] - 20.0) { + /* Combine this block with second last block. */ + split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; + split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2]; + BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1); + histograms[self->last_histogram_ix_[0]] = self->combined_histo[1]; + last_entropy[1] = last_entropy[0]; + last_entropy[0] = combined_entropy[1]; + ++self->num_blocks_; + self->block_size_ = 0; + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + self->merge_last_count_ = 0; + self->target_block_size_ = self->min_block_size_; + } else { + /* Combine this block with last block. */ + split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_; + histograms[self->last_histogram_ix_[0]] = self->combined_histo[0]; + last_entropy[0] = combined_entropy[0]; + if (split->num_types == 1) { + last_entropy[1] = last_entropy[0]; + } + self->block_size_ = 0; + FN(HistogramClear)(&histograms[self->curr_histogram_ix_]); + if (++self->merge_last_count_ > 1) { + self->target_block_size_ += self->min_block_size_; + } + } + } + if (is_final) { + *self->histograms_size_ = split->num_types; + split->num_blocks = self->num_blocks_; + } +} + +/* Adds the next symbol to the current histogram. When the current histogram + reaches the target size, decides on merging the block. */ +static void FN(BlockSplitterAddSymbol)(FN(BlockSplitter)* self, size_t symbol) { + FN(HistogramAdd)(&self->histograms_[self->curr_histogram_ix_], symbol); + ++self->block_size_; + if (self->block_size_ == self->target_block_size_) { + FN(BlockSplitterFinishBlock)(self, /* is_final = */ BROTLI_FALSE); + } +} + +#undef HistogramType +#undef FN + +#define BROTLI_MAX_STATIC_CONTEXTS 13 + +/* Greedy block splitter for one block category (literal, command or distance). + Gathers histograms for all context buckets. */ +typedef struct ContextBlockSplitter { + /* Alphabet size of particular block category. */ + size_t alphabet_size_; + size_t num_contexts_; + size_t max_block_types_; + /* We collect at least this many symbols for each block. */ + size_t min_block_size_; + /* We merge histograms A and B if + entropy(A+B) < entropy(A) + entropy(B) + split_threshold_, + where A is the current histogram and B is the histogram of the last or the + second last block type. */ + double split_threshold_; + + size_t num_blocks_; + BlockSplit* split_; /* not owned */ + HistogramLiteral* histograms_; /* not owned */ + size_t* histograms_size_; /* not owned */ + + /* The number of symbols that we want to collect before deciding on whether + or not to merge the block with a previous one or emit a new block. */ + size_t target_block_size_; + /* The number of symbols in the current histogram. */ + size_t block_size_; + /* Offset of the current histogram. */ + size_t curr_histogram_ix_; + /* Offset of the histograms of the previous two block types. */ + size_t last_histogram_ix_[2]; + /* Entropy of the previous two block types. */ + double last_entropy_[2 * BROTLI_MAX_STATIC_CONTEXTS]; + /* The number of times we merged the current block with the last one. */ + size_t merge_last_count_; +} ContextBlockSplitter; + +static void InitContextBlockSplitter( + MemoryManager* m, ContextBlockSplitter* self, size_t alphabet_size, + size_t num_contexts, size_t min_block_size, double split_threshold, + size_t num_symbols, BlockSplit* split, HistogramLiteral** histograms, + size_t* histograms_size) { + size_t max_num_blocks = num_symbols / min_block_size + 1; + size_t max_num_types; + BROTLI_DCHECK(num_contexts <= BROTLI_MAX_STATIC_CONTEXTS); + + self->alphabet_size_ = alphabet_size; + self->num_contexts_ = num_contexts; + self->max_block_types_ = BROTLI_MAX_NUMBER_OF_BLOCK_TYPES / num_contexts; + self->min_block_size_ = min_block_size; + self->split_threshold_ = split_threshold; + self->num_blocks_ = 0; + self->split_ = split; + self->histograms_size_ = histograms_size; + self->target_block_size_ = min_block_size; + self->block_size_ = 0; + self->curr_histogram_ix_ = 0; + self->merge_last_count_ = 0; + + /* We have to allocate one more histogram than the maximum number of block + types for the current histogram when the meta-block is too big. */ + max_num_types = + BROTLI_MIN(size_t, max_num_blocks, self->max_block_types_ + 1); + BROTLI_ENSURE_CAPACITY(m, uint8_t, + split->types, split->types_alloc_size, max_num_blocks); + BROTLI_ENSURE_CAPACITY(m, uint32_t, + split->lengths, split->lengths_alloc_size, max_num_blocks); + if (BROTLI_IS_OOM(m)) return; + split->num_blocks = max_num_blocks; + if (BROTLI_IS_OOM(m)) return; + BROTLI_DCHECK(*histograms == 0); + *histograms_size = max_num_types * num_contexts; + *histograms = BROTLI_ALLOC(m, HistogramLiteral, *histograms_size); + self->histograms_ = *histograms; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return; + /* Clear only current histogram. */ + ClearHistogramsLiteral(&self->histograms_[0], num_contexts); + self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0; +} + +/* Does either of three things: + (1) emits the current block with a new block type; + (2) emits the current block with the type of the second last block; + (3) merges the current block with the last block. */ +static void ContextBlockSplitterFinishBlock( + ContextBlockSplitter* self, MemoryManager* m, BROTLI_BOOL is_final) { + BlockSplit* split = self->split_; + const size_t num_contexts = self->num_contexts_; + double* last_entropy = self->last_entropy_; + HistogramLiteral* histograms = self->histograms_; + + if (self->block_size_ < self->min_block_size_) { + self->block_size_ = self->min_block_size_; + } + if (self->num_blocks_ == 0) { + size_t i; + /* Create first block. */ + split->lengths[0] = (uint32_t)self->block_size_; + split->types[0] = 0; + + for (i = 0; i < num_contexts; ++i) { + last_entropy[i] = + BitsEntropy(histograms[i].data_, self->alphabet_size_); + last_entropy[num_contexts + i] = last_entropy[i]; + } + ++self->num_blocks_; + ++split->num_types; + self->curr_histogram_ix_ += num_contexts; + if (self->curr_histogram_ix_ < *self->histograms_size_) { + ClearHistogramsLiteral( + &self->histograms_[self->curr_histogram_ix_], self->num_contexts_); + } + self->block_size_ = 0; + } else if (self->block_size_ > 0) { + /* Try merging the set of histograms for the current block type with the + respective set of histograms for the last and second last block types. + Decide over the split based on the total reduction of entropy across + all contexts. */ + double entropy[BROTLI_MAX_STATIC_CONTEXTS]; + HistogramLiteral* combined_histo = + BROTLI_ALLOC(m, HistogramLiteral, 2 * num_contexts); + double combined_entropy[2 * BROTLI_MAX_STATIC_CONTEXTS]; + double diff[2] = { 0.0 }; + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(combined_histo)) return; + for (i = 0; i < num_contexts; ++i) { + size_t curr_histo_ix = self->curr_histogram_ix_ + i; + size_t j; + entropy[i] = BitsEntropy(histograms[curr_histo_ix].data_, + self->alphabet_size_); + for (j = 0; j < 2; ++j) { + size_t jx = j * num_contexts + i; + size_t last_histogram_ix = self->last_histogram_ix_[j] + i; + combined_histo[jx] = histograms[curr_histo_ix]; + HistogramAddHistogramLiteral(&combined_histo[jx], + &histograms[last_histogram_ix]); + combined_entropy[jx] = BitsEntropy( + &combined_histo[jx].data_[0], self->alphabet_size_); + diff[j] += combined_entropy[jx] - entropy[i] - last_entropy[jx]; + } + } + + if (split->num_types < self->max_block_types_ && + diff[0] > self->split_threshold_ && + diff[1] > self->split_threshold_) { + /* Create new block. */ + split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; + split->types[self->num_blocks_] = (uint8_t)split->num_types; + self->last_histogram_ix_[1] = self->last_histogram_ix_[0]; + self->last_histogram_ix_[0] = split->num_types * num_contexts; + for (i = 0; i < num_contexts; ++i) { + last_entropy[num_contexts + i] = last_entropy[i]; + last_entropy[i] = entropy[i]; + } + ++self->num_blocks_; + ++split->num_types; + self->curr_histogram_ix_ += num_contexts; + if (self->curr_histogram_ix_ < *self->histograms_size_) { + ClearHistogramsLiteral( + &self->histograms_[self->curr_histogram_ix_], self->num_contexts_); + } + self->block_size_ = 0; + self->merge_last_count_ = 0; + self->target_block_size_ = self->min_block_size_; + } else if (diff[1] < diff[0] - 20.0) { + /* Combine this block with second last block. */ + split->lengths[self->num_blocks_] = (uint32_t)self->block_size_; + split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2]; + BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1); + for (i = 0; i < num_contexts; ++i) { + histograms[self->last_histogram_ix_[0] + i] = + combined_histo[num_contexts + i]; + last_entropy[num_contexts + i] = last_entropy[i]; + last_entropy[i] = combined_entropy[num_contexts + i]; + HistogramClearLiteral(&histograms[self->curr_histogram_ix_ + i]); + } + ++self->num_blocks_; + self->block_size_ = 0; + self->merge_last_count_ = 0; + self->target_block_size_ = self->min_block_size_; + } else { + /* Combine this block with last block. */ + split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_; + for (i = 0; i < num_contexts; ++i) { + histograms[self->last_histogram_ix_[0] + i] = combined_histo[i]; + last_entropy[i] = combined_entropy[i]; + if (split->num_types == 1) { + last_entropy[num_contexts + i] = last_entropy[i]; + } + HistogramClearLiteral(&histograms[self->curr_histogram_ix_ + i]); + } + self->block_size_ = 0; + if (++self->merge_last_count_ > 1) { + self->target_block_size_ += self->min_block_size_; + } + } + BROTLI_FREE(m, combined_histo); + } + if (is_final) { + *self->histograms_size_ = split->num_types * num_contexts; + split->num_blocks = self->num_blocks_; + } +} + +/* Adds the next symbol to the current block type and context. When the + current block reaches the target size, decides on merging the block. */ +static void ContextBlockSplitterAddSymbol( + ContextBlockSplitter* self, MemoryManager* m, + size_t symbol, size_t context) { + HistogramAddLiteral(&self->histograms_[self->curr_histogram_ix_ + context], + symbol); + ++self->block_size_; + if (self->block_size_ == self->target_block_size_) { + ContextBlockSplitterFinishBlock(self, m, /* is_final = */ BROTLI_FALSE); + if (BROTLI_IS_OOM(m)) return; + } +} + +static void MapStaticContexts(MemoryManager* m, + size_t num_contexts, + const uint32_t* static_context_map, + MetaBlockSplit* mb) { + size_t i; + BROTLI_DCHECK(mb->literal_context_map == 0); + mb->literal_context_map_size = + mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS; + mb->literal_context_map = + BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_context_map)) return; + + for (i = 0; i < mb->literal_split.num_types; ++i) { + uint32_t offset = (uint32_t)(i * num_contexts); + size_t j; + for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS); ++j) { + mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] = + offset + static_context_map[j]; + } + } +} + +typedef struct GreedyMetablockArena { + union { + BlockSplitterLiteral plain; + ContextBlockSplitter ctx; + } lit_blocks; + BlockSplitterCommand cmd_blocks; + BlockSplitterDistance dist_blocks; +} GreedyMetablockArena; + +static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal( + MemoryManager* m, GreedyMetablockArena* arena, const uint8_t* ringbuffer, + size_t pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2, + ContextLut literal_context_lut, const size_t num_contexts, + const uint32_t* static_context_map, const Command* commands, + size_t n_commands, MetaBlockSplit* mb) { + size_t num_literals = 0; + size_t i; + for (i = 0; i < n_commands; ++i) { + num_literals += commands[i].insert_len_; + } + + if (num_contexts == 1) { + InitBlockSplitterLiteral(m, &arena->lit_blocks.plain, 256, 512, 400.0, + num_literals, &mb->literal_split, &mb->literal_histograms, + &mb->literal_histograms_size); + } else { + InitContextBlockSplitter(m, &arena->lit_blocks.ctx, 256, num_contexts, 512, + 400.0, num_literals, &mb->literal_split, &mb->literal_histograms, + &mb->literal_histograms_size); + } + if (BROTLI_IS_OOM(m)) return; + InitBlockSplitterCommand(m, &arena->cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS, + 1024, 500.0, n_commands, &mb->command_split, &mb->command_histograms, + &mb->command_histograms_size); + if (BROTLI_IS_OOM(m)) return; + InitBlockSplitterDistance(m, &arena->dist_blocks, 64, 512, 100.0, n_commands, + &mb->distance_split, &mb->distance_histograms, + &mb->distance_histograms_size); + if (BROTLI_IS_OOM(m)) return; + + for (i = 0; i < n_commands; ++i) { + const Command cmd = commands[i]; + size_t j; + BlockSplitterAddSymbolCommand(&arena->cmd_blocks, cmd.cmd_prefix_); + for (j = cmd.insert_len_; j != 0; --j) { + uint8_t literal = ringbuffer[pos & mask]; + if (num_contexts == 1) { + BlockSplitterAddSymbolLiteral(&arena->lit_blocks.plain, literal); + } else { + size_t context = + BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut); + ContextBlockSplitterAddSymbol(&arena->lit_blocks.ctx, m, literal, + static_context_map[context]); + if (BROTLI_IS_OOM(m)) return; + } + prev_byte2 = prev_byte; + prev_byte = literal; + ++pos; + } + pos += CommandCopyLen(&cmd); + if (CommandCopyLen(&cmd)) { + prev_byte2 = ringbuffer[(pos - 2) & mask]; + prev_byte = ringbuffer[(pos - 1) & mask]; + if (cmd.cmd_prefix_ >= 128) { + BlockSplitterAddSymbolDistance( + &arena->dist_blocks, cmd.dist_prefix_ & 0x3FF); + } + } + } + + if (num_contexts == 1) { + BlockSplitterFinishBlockLiteral( + &arena->lit_blocks.plain, /* is_final = */ BROTLI_TRUE); + } else { + ContextBlockSplitterFinishBlock( + &arena->lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE); + if (BROTLI_IS_OOM(m)) return; + } + BlockSplitterFinishBlockCommand( + &arena->cmd_blocks, /* is_final = */ BROTLI_TRUE); + BlockSplitterFinishBlockDistance( + &arena->dist_blocks, /* is_final = */ BROTLI_TRUE); + + if (num_contexts > 1) { + MapStaticContexts(m, num_contexts, static_context_map, mb); + } +} + +void duckdb_brotli::BrotliBuildMetaBlockGreedy(MemoryManager* m, + const uint8_t* ringbuffer, + size_t pos, + size_t mask, + uint8_t prev_byte, + uint8_t prev_byte2, + ContextLut literal_context_lut, + size_t num_contexts, + const uint32_t* static_context_map, + const Command* commands, + size_t n_commands, + MetaBlockSplit* mb) { + GreedyMetablockArena* arena = BROTLI_ALLOC(m, GreedyMetablockArena, 1); + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return; + if (num_contexts == 1) { + BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask, + prev_byte, prev_byte2, literal_context_lut, 1, NULL, commands, + n_commands, mb); + } else { + BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask, + prev_byte, prev_byte2, literal_context_lut, num_contexts, + static_context_map, commands, n_commands, mb); + } + BROTLI_FREE(m, arena); +} + +void duckdb_brotli::BrotliOptimizeHistograms(uint32_t num_distance_codes, + MetaBlockSplit* mb) { + uint8_t good_for_rle[BROTLI_NUM_COMMAND_SYMBOLS]; + size_t i; + for (i = 0; i < mb->literal_histograms_size; ++i) { + BrotliOptimizeHuffmanCountsForRle(256, mb->literal_histograms[i].data_, + good_for_rle); + } + for (i = 0; i < mb->command_histograms_size; ++i) { + BrotliOptimizeHuffmanCountsForRle(BROTLI_NUM_COMMAND_SYMBOLS, + mb->command_histograms[i].data_, + good_for_rle); + } + for (i = 0; i < mb->distance_histograms_size; ++i) { + BrotliOptimizeHuffmanCountsForRle(num_distance_codes, + mb->distance_histograms[i].data_, + good_for_rle); + } +} + + diff --git a/third_party/brotli/enc/metablock.h b/third_party/brotli/enc/metablock.h new file mode 100644 index 00000000000..1a5077c1e3e --- /dev/null +++ b/third_party/brotli/enc/metablock.h @@ -0,0 +1,102 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Algorithms for distributing the literals and commands of a metablock between + block types and contexts. */ + +#ifndef BROTLI_ENC_METABLOCK_H_ +#define BROTLI_ENC_METABLOCK_H_ + +#include + +#include "../common/context.h" +#include "../common/brotli_platform.h" +#include "block_splitter.h" +#include "command.h" +#include "histogram.h" +#include "memory.h" +#include "quality.h" + +namespace duckdb_brotli { + +typedef struct MetaBlockSplit { + BlockSplit literal_split; + BlockSplit command_split; + BlockSplit distance_split; + uint32_t* literal_context_map; + size_t literal_context_map_size; + uint32_t* distance_context_map; + size_t distance_context_map_size; + HistogramLiteral* literal_histograms; + size_t literal_histograms_size; + HistogramCommand* command_histograms; + size_t command_histograms_size; + HistogramDistance* distance_histograms; + size_t distance_histograms_size; +} MetaBlockSplit; + +static BROTLI_INLINE void InitMetaBlockSplit(MetaBlockSplit* mb) { + BrotliInitBlockSplit(&mb->literal_split); + BrotliInitBlockSplit(&mb->command_split); + BrotliInitBlockSplit(&mb->distance_split); + mb->literal_context_map = 0; + mb->literal_context_map_size = 0; + mb->distance_context_map = 0; + mb->distance_context_map_size = 0; + mb->literal_histograms = 0; + mb->literal_histograms_size = 0; + mb->command_histograms = 0; + mb->command_histograms_size = 0; + mb->distance_histograms = 0; + mb->distance_histograms_size = 0; +} + +static BROTLI_INLINE void DestroyMetaBlockSplit( + MemoryManager* m, MetaBlockSplit* mb) { + BrotliDestroyBlockSplit(m, &mb->literal_split); + BrotliDestroyBlockSplit(m, &mb->command_split); + BrotliDestroyBlockSplit(m, &mb->distance_split); + BROTLI_FREE(m, mb->literal_context_map); + BROTLI_FREE(m, mb->distance_context_map); + BROTLI_FREE(m, mb->literal_histograms); + BROTLI_FREE(m, mb->command_histograms); + BROTLI_FREE(m, mb->distance_histograms); +} + +/* Uses the slow shortest-path block splitter and does context clustering. + The distance parameters are dynamically selected based on the commands + which get recomputed under the new distance parameters. The new distance + parameters are stored into *params. */ +BROTLI_INTERNAL void BrotliBuildMetaBlock(MemoryManager* m, + const uint8_t* ringbuffer, + const size_t pos, + const size_t mask, + BrotliEncoderParams* params, + uint8_t prev_byte, + uint8_t prev_byte2, + Command* cmds, + size_t num_commands, + ContextType literal_context_mode, + MetaBlockSplit* mb); + +/* Uses a fast greedy block splitter that tries to merge current block with the + last or the second last block and uses a static context clustering which + is the same for all block types. */ +BROTLI_INTERNAL void BrotliBuildMetaBlockGreedy( + MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask, + uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut, + size_t num_contexts, const uint32_t* static_context_map, + const Command* commands, size_t n_commands, MetaBlockSplit* mb); + +BROTLI_INTERNAL void BrotliOptimizeHistograms(uint32_t num_distance_codes, + MetaBlockSplit* mb); + +BROTLI_INTERNAL void BrotliInitDistanceParams(BrotliDistanceParams* params, + uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window); + +} + +#endif /* BROTLI_ENC_METABLOCK_H_ */ diff --git a/third_party/brotli/enc/prefix.h b/third_party/brotli/enc/prefix.h new file mode 100644 index 00000000000..1bb5e1de865 --- /dev/null +++ b/third_party/brotli/enc/prefix.h @@ -0,0 +1,50 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Functions for encoding of integers into prefix codes the amount of extra + bits, and the actual values of the extra bits. */ + +#ifndef BROTLI_ENC_PREFIX_H_ +#define BROTLI_ENC_PREFIX_H_ + +#include + +#include "../common/brotli_constants.h" +#include "../common/brotli_platform.h" +#include "fast_log.h" + +namespace duckdb_brotli { + +/* Here distance_code is an intermediate code, i.e. one of the special codes or + the actual distance increased by BROTLI_NUM_DISTANCE_SHORT_CODES - 1. */ +static BROTLI_INLINE void PrefixEncodeCopyDistance(size_t distance_code, + size_t num_direct_codes, + size_t postfix_bits, + uint16_t* code, + uint32_t* extra_bits) { + if (distance_code < BROTLI_NUM_DISTANCE_SHORT_CODES + num_direct_codes) { + *code = (uint16_t)distance_code; + *extra_bits = 0; + return; + } else { + size_t dist = ((size_t)1 << (postfix_bits + 2u)) + + (distance_code - BROTLI_NUM_DISTANCE_SHORT_CODES - num_direct_codes); + size_t bucket = Log2FloorNonZero(dist) - 1; + size_t postfix_mask = (1u << postfix_bits) - 1; + size_t postfix = dist & postfix_mask; + size_t prefix = (dist >> bucket) & 1; + size_t offset = (2 + prefix) << bucket; + size_t nbits = bucket - postfix_bits; + *code = (uint16_t)((nbits << 10) | + (BROTLI_NUM_DISTANCE_SHORT_CODES + num_direct_codes + + ((2 * (nbits - 1) + prefix) << postfix_bits) + postfix)); + *extra_bits = (uint32_t)((dist - offset) >> postfix_bits); + } +} + +} + +#endif /* BROTLI_ENC_PREFIX_H_ */ diff --git a/third_party/brotli/enc/quality.h b/third_party/brotli/enc/quality.h new file mode 100644 index 00000000000..62ac33d1fca --- /dev/null +++ b/third_party/brotli/enc/quality.h @@ -0,0 +1,202 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Constants and formulas that affect speed-ratio trade-offs and thus define + quality levels. */ + +#ifndef BROTLI_ENC_QUALITY_H_ +#define BROTLI_ENC_QUALITY_H_ + +#include + +#include "../common/brotli_platform.h" +#include "brotli_params.h" + +#define FAST_ONE_PASS_COMPRESSION_QUALITY 0 +#define FAST_TWO_PASS_COMPRESSION_QUALITY 1 +#define ZOPFLIFICATION_QUALITY 10 +#define HQ_ZOPFLIFICATION_QUALITY 11 + +#define MAX_QUALITY_FOR_STATIC_ENTROPY_CODES 2 +#define MIN_QUALITY_FOR_BLOCK_SPLIT 4 +#define MIN_QUALITY_FOR_NONZERO_DISTANCE_PARAMS 4 +#define MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS 4 +#define MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH 5 +#define MIN_QUALITY_FOR_CONTEXT_MODELING 5 +#define MIN_QUALITY_FOR_HQ_CONTEXT_MODELING 7 +#define MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING 10 + +/* For quality below MIN_QUALITY_FOR_BLOCK_SPLIT there is no block splitting, + so we buffer at most this much literals and commands. */ +#define MAX_NUM_DELAYED_SYMBOLS 0x2FFF + +/* Returns hash-table size for quality levels 0 and 1. */ +static BROTLI_INLINE size_t MaxHashTableSize(int quality) { + return quality == FAST_ONE_PASS_COMPRESSION_QUALITY ? 1 << 15 : 1 << 17; +} + +/* The maximum length for which the zopflification uses distinct distances. */ +#define MAX_ZOPFLI_LEN_QUALITY_10 150 +#define MAX_ZOPFLI_LEN_QUALITY_11 325 + +/* Do not thoroughly search when a long copy is found. */ +#define BROTLI_LONG_COPY_QUICK_STEP 16384 + +static BROTLI_INLINE size_t MaxZopfliLen(const BrotliEncoderParams* params) { + return params->quality <= 10 ? + MAX_ZOPFLI_LEN_QUALITY_10 : + MAX_ZOPFLI_LEN_QUALITY_11; +} + +/* Number of best candidates to evaluate to expand Zopfli chain. */ +static BROTLI_INLINE size_t MaxZopfliCandidates( + const BrotliEncoderParams* params) { + return params->quality <= 10 ? 1 : 5; +} + +static BROTLI_INLINE void SanitizeParams(BrotliEncoderParams* params) { + params->quality = BROTLI_MIN(int, BROTLI_MAX_QUALITY, + BROTLI_MAX(int, BROTLI_MIN_QUALITY, params->quality)); + if (params->quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) { + params->large_window = BROTLI_FALSE; + } + if (params->lgwin < BROTLI_MIN_WINDOW_BITS) { + params->lgwin = BROTLI_MIN_WINDOW_BITS; + } else { + int max_lgwin = params->large_window ? BROTLI_LARGE_MAX_WINDOW_BITS : + BROTLI_MAX_WINDOW_BITS; + if (params->lgwin > max_lgwin) params->lgwin = max_lgwin; + } +} + +/* Returns optimized lg_block value. */ +static BROTLI_INLINE int ComputeLgBlock(const BrotliEncoderParams* params) { + int lgblock = params->lgblock; + if (params->quality == FAST_ONE_PASS_COMPRESSION_QUALITY || + params->quality == FAST_TWO_PASS_COMPRESSION_QUALITY) { + lgblock = params->lgwin; + } else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) { + lgblock = 14; + } else if (lgblock == 0) { + lgblock = 16; + if (params->quality >= 9 && params->lgwin > lgblock) { + lgblock = BROTLI_MIN(int, 18, params->lgwin); + } + } else { + lgblock = BROTLI_MIN(int, BROTLI_MAX_INPUT_BLOCK_BITS, + BROTLI_MAX(int, BROTLI_MIN_INPUT_BLOCK_BITS, lgblock)); + } + return lgblock; +} + +/* Returns log2 of the size of main ring buffer area. + Allocate at least lgwin + 1 bits for the ring buffer so that the newly + added block fits there completely and we still get lgwin bits and at least + read_block_size_bits + 1 bits because the copy tail length needs to be + smaller than ring-buffer size. */ +static BROTLI_INLINE int ComputeRbBits(const BrotliEncoderParams* params) { + return 1 + BROTLI_MAX(int, params->lgwin, params->lgblock); +} + +static BROTLI_INLINE size_t MaxMetablockSize( + const BrotliEncoderParams* params) { + int bits = + BROTLI_MIN(int, ComputeRbBits(params), BROTLI_MAX_INPUT_BLOCK_BITS); + return (size_t)1 << bits; +} + +/* When searching for backward references and have not seen matches for a long + time, we can skip some match lookups. Unsuccessful match lookups are very + expensive and this kind of a heuristic speeds up compression quite a lot. + At first 8 byte strides are taken and every second byte is put to hasher. + After 4x more literals stride by 16 bytes, every put 4-th byte to hasher. + Applied only to qualities 2 to 9. */ +static BROTLI_INLINE size_t LiteralSpreeLengthForSparseSearch( + const BrotliEncoderParams* params) { + return params->quality < 9 ? 64 : 512; +} + +/* Quality to hasher mapping: + + - q02: h02 (longest_match_quickly), b16, l5 + + - q03: h03 (longest_match_quickly), b17, l5 + + - q04: h04 (longest_match_quickly), b17, l5 + - q04: h54 (longest_match_quickly), b20, l7 | for large files + + - q05: h05 (longest_match ), b14, l4 + - q05: h06 (longest_match64 ), b15, l5 | for large files + - q05: h40 (forgetful_chain ), b15, l4 | for small window + + - q06: h05 (longest_match ), b14, l4 + - q06: h06 (longest_match64 ), b15, l5 | for large files + - q06: h40 (forgetful_chain ), b15, l4 | for small window + + - q07: h05 (longest_match ), b15, l4 + - q07: h06 (longest_match64 ), b15, l5 | for large files + - q07: h41 (forgetful_chain ), b15, l4 | for small window + + - q08: h05 (longest_match ), b15, l4 + - q08: h06 (longest_match64 ), b15, l5 | for large files + - q08: h41 (forgetful_chain ), b15, l4 | for small window + + - q09: h05 (longest_match ), b15, l4 + - q09: h06 (longest_match64 ), b15, l5 | for large files + - q09: h42 (forgetful_chain ), b15, l4 | for small window + + - q10: t10 (to_binary_tree ), b17, l128 + + - q11: t10 (to_binary_tree ), b17, l128 + + Where "q" is quality, "h" is hasher type, "b" is bucket bits, + "l" is source len. */ +static BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params, + BrotliHasherParams* hparams) { + if (params->quality > 9) { + hparams->type = 10; + } else if (params->quality == 4 && params->size_hint >= (1 << 20)) { + hparams->type = 54; + } else if (params->quality < 5) { + hparams->type = params->quality; + } else if (params->lgwin <= 16) { + hparams->type = params->quality < 7 ? 40 : params->quality < 9 ? 41 : 42; + } else if (params->size_hint >= (1 << 20) && params->lgwin >= 19) { + hparams->type = 6; + hparams->block_bits = params->quality - 1; + hparams->bucket_bits = 15; + hparams->num_last_distances_to_check = + params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16; + } else { + /* TODO(eustas): often previous setting (H6) is faster and denser; consider + adding an option to use it. */ + hparams->type = 5; + hparams->block_bits = params->quality - 1; + hparams->bucket_bits = params->quality < 7 ? 14 : 15; + hparams->num_last_distances_to_check = + params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16; + } + + if (params->lgwin > 24) { + /* Different hashers for large window brotli: not for qualities <= 2, + these are too fast for large window. Not for qualities >= 10: their + hasher already works well with large window. So the changes are: + H3 --> H35: for quality 3. + H54 --> H55: for quality 4 with size hint > 1MB + H6 --> H65: for qualities 5, 6, 7, 8, 9. */ + if (hparams->type == 3) { + hparams->type = 35; + } + if (hparams->type == 54) { + hparams->type = 55; + } + if (hparams->type == 6) { + hparams->type = 65; + } + } +} + +#endif /* BROTLI_ENC_QUALITY_H_ */ diff --git a/third_party/brotli/enc/resolve-multi-includes.py b/third_party/brotli/enc/resolve-multi-includes.py new file mode 100755 index 00000000000..0402ed3cd8b --- /dev/null +++ b/third_party/brotli/enc/resolve-multi-includes.py @@ -0,0 +1,24 @@ +# brotli uses a weird c templating mechanism using _inc.h files +# this does not play well with things like amalagamation +# this script inlines the variuos headers + +import os +import re + +for filename in os.listdir('.'): + if not (filename.endswith('.cpp') or filename.endswith('.h')): + continue + + file_lines = open(filename, 'r').readlines() + if '_inc.h' not in '\n'.join(file_lines): + continue + + out = open (filename, 'w') + + for line in file_lines: + if '#include' in line and '_inc.h' in line: + match = re.search(r'#include\s+"(.+)".*', line).group(1) + include = open(match, 'r').readlines(); + out.write(''.join(include)) + continue + out.write(line) diff --git a/third_party/brotli/enc/ringbuffer.h b/third_party/brotli/enc/ringbuffer.h new file mode 100644 index 00000000000..b7e8113b8dd --- /dev/null +++ b/third_party/brotli/enc/ringbuffer.h @@ -0,0 +1,164 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Sliding window over the input data. */ + +#ifndef BROTLI_ENC_RINGBUFFER_H_ +#define BROTLI_ENC_RINGBUFFER_H_ + +#include /* memcpy */ + +#include + +#include "../common/brotli_platform.h" +#include "memory.h" +#include "quality.h" + +namespace duckdb_brotli { + +/* A RingBuffer(window_bits, tail_bits) contains `1 << window_bits' bytes of + data in a circular manner: writing a byte writes it to: + `position() % (1 << window_bits)'. + For convenience, the RingBuffer array contains another copy of the + first `1 << tail_bits' bytes: + buffer_[i] == buffer_[i + (1 << window_bits)], if i < (1 << tail_bits), + and another copy of the last two bytes: + buffer_[-1] == buffer_[(1 << window_bits) - 1] and + buffer_[-2] == buffer_[(1 << window_bits) - 2]. */ +typedef struct RingBuffer { + /* Size of the ring-buffer is (1 << window_bits) + tail_size_. */ + const uint32_t size_; + const uint32_t mask_; + const uint32_t tail_size_; + const uint32_t total_size_; + + uint32_t cur_size_; + /* Position to write in the ring buffer. */ + uint32_t pos_; + /* The actual ring buffer containing the copy of the last two bytes, the data, + and the copy of the beginning as a tail. */ + uint8_t* data_; + /* The start of the ring-buffer. */ + uint8_t* buffer_; +} RingBuffer; + +static BROTLI_INLINE void RingBufferInit(RingBuffer* rb) { + rb->cur_size_ = 0; + rb->pos_ = 0; + rb->data_ = 0; + rb->buffer_ = 0; +} + +static BROTLI_INLINE void RingBufferSetup( + const BrotliEncoderParams* params, RingBuffer* rb) { + int window_bits = ComputeRbBits(params); + int tail_bits = params->lgblock; + *(uint32_t*)&rb->size_ = 1u << window_bits; + *(uint32_t*)&rb->mask_ = (1u << window_bits) - 1; + *(uint32_t*)&rb->tail_size_ = 1u << tail_bits; + *(uint32_t*)&rb->total_size_ = rb->size_ + rb->tail_size_; +} + +static BROTLI_INLINE void RingBufferFree(MemoryManager* m, RingBuffer* rb) { + BROTLI_FREE(m, rb->data_); +} + +/* Allocates or re-allocates data_ to the given length + plus some slack + region before and after. Fills the slack regions with zeros. */ +static BROTLI_INLINE void RingBufferInitBuffer( + MemoryManager* m, const uint32_t buflen, RingBuffer* rb) { + static const size_t kSlackForEightByteHashingEverywhere = 7; + uint8_t* new_data = BROTLI_ALLOC( + m, uint8_t, 2 + buflen + kSlackForEightByteHashingEverywhere); + size_t i; + if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_data)) return; + if (rb->data_) { + memcpy(new_data, rb->data_, + 2 + rb->cur_size_ + kSlackForEightByteHashingEverywhere); + BROTLI_FREE(m, rb->data_); + } + rb->data_ = new_data; + rb->cur_size_ = buflen; + rb->buffer_ = rb->data_ + 2; + rb->buffer_[-2] = rb->buffer_[-1] = 0; + for (i = 0; i < kSlackForEightByteHashingEverywhere; ++i) { + rb->buffer_[rb->cur_size_ + i] = 0; + } +} + +static BROTLI_INLINE void RingBufferWriteTail( + const uint8_t* bytes, size_t n, RingBuffer* rb) { + const size_t masked_pos = rb->pos_ & rb->mask_; + if (BROTLI_PREDICT_FALSE(masked_pos < rb->tail_size_)) { + /* Just fill the tail buffer with the beginning data. */ + const size_t p = rb->size_ + masked_pos; + memcpy(&rb->buffer_[p], bytes, + BROTLI_MIN(size_t, n, rb->tail_size_ - masked_pos)); + } +} + +/* Push bytes into the ring buffer. */ +static BROTLI_INLINE void RingBufferWrite( + MemoryManager* m, const uint8_t* bytes, size_t n, RingBuffer* rb) { + if (rb->pos_ == 0 && n < rb->tail_size_) { + /* Special case for the first write: to process the first block, we don't + need to allocate the whole ring-buffer and we don't need the tail + either. However, we do this memory usage optimization only if the + first write is less than the tail size, which is also the input block + size, otherwise it is likely that other blocks will follow and we + will need to reallocate to the full size anyway. */ + rb->pos_ = (uint32_t)n; + RingBufferInitBuffer(m, rb->pos_, rb); + if (BROTLI_IS_OOM(m)) return; + memcpy(rb->buffer_, bytes, n); + return; + } + if (rb->cur_size_ < rb->total_size_) { + /* Lazily allocate the full buffer. */ + RingBufferInitBuffer(m, rb->total_size_, rb); + if (BROTLI_IS_OOM(m)) return; + /* Initialize the last two bytes to zero, so that we don't have to worry + later when we copy the last two bytes to the first two positions. */ + rb->buffer_[rb->size_ - 2] = 0; + rb->buffer_[rb->size_ - 1] = 0; + /* Initialize tail; might be touched by "best_len++" optimization when + ring buffer is "full". */ + rb->buffer_[rb->size_] = 241; + } + { + const size_t masked_pos = rb->pos_ & rb->mask_; + /* The length of the writes is limited so that we do not need to worry + about a write */ + RingBufferWriteTail(bytes, n, rb); + if (BROTLI_PREDICT_TRUE(masked_pos + n <= rb->size_)) { + /* A single write fits. */ + memcpy(&rb->buffer_[masked_pos], bytes, n); + } else { + /* Split into two writes. + Copy into the end of the buffer, including the tail buffer. */ + memcpy(&rb->buffer_[masked_pos], bytes, + BROTLI_MIN(size_t, n, rb->total_size_ - masked_pos)); + /* Copy into the beginning of the buffer */ + memcpy(&rb->buffer_[0], bytes + (rb->size_ - masked_pos), + n - (rb->size_ - masked_pos)); + } + } + { + BROTLI_BOOL not_first_lap = (rb->pos_ & (1u << 31)) != 0; + uint32_t rb_pos_mask = (1u << 31) - 1; + rb->buffer_[-2] = rb->buffer_[rb->size_ - 2]; + rb->buffer_[-1] = rb->buffer_[rb->size_ - 1]; + rb->pos_ = (rb->pos_ & rb_pos_mask) + (uint32_t)(n & rb_pos_mask); + if (not_first_lap) { + /* Wrap, but preserve not-a-first-lap feature. */ + rb->pos_ |= 1u << 31; + } + } +} + +} + +#endif /* BROTLI_ENC_RINGBUFFER_H_ */ diff --git a/third_party/brotli/enc/state.h b/third_party/brotli/enc/state.h new file mode 100644 index 00000000000..acdbc0ad2ce --- /dev/null +++ b/third_party/brotli/enc/state.h @@ -0,0 +1,106 @@ +/* Copyright 2022 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Encoder state. */ + +#ifndef BROTLI_ENC_STATE_H_ +#define BROTLI_ENC_STATE_H_ + +#include + +#include "command.h" +#include "compress_fragment.h" +#include "compress_fragment_two_pass.h" +#include "brotli_hash.h" +#include "memory.h" +#include "brotli_params.h" +#include "ringbuffer.h" + +namespace duckdb_brotli { + +typedef enum BrotliEncoderStreamState { + /* Default state. */ + BROTLI_STREAM_PROCESSING = 0, + /* Intermediate state; after next block is emitted, byte-padding should be + performed before getting back to default state. */ + BROTLI_STREAM_FLUSH_REQUESTED = 1, + /* Last metablock was produced; no more input is acceptable. */ + BROTLI_STREAM_FINISHED = 2, + /* Flushing compressed block and writing meta-data block header. */ + BROTLI_STREAM_METADATA_HEAD = 3, + /* Writing metadata block body. */ + BROTLI_STREAM_METADATA_BODY = 4 +} BrotliEncoderStreamState; + +typedef enum BrotliEncoderFlintState { + BROTLI_FLINT_NEEDS_2_BYTES = 2, + BROTLI_FLINT_NEEDS_1_BYTE = 1, + BROTLI_FLINT_WAITING_FOR_PROCESSING = 0, + BROTLI_FLINT_WAITING_FOR_FLUSHING = -1, + BROTLI_FLINT_DONE = -2 +} BrotliEncoderFlintState; + +typedef struct BrotliEncoderStateStruct { + BrotliEncoderParams params; + + MemoryManager memory_manager_; + + uint64_t input_pos_; + RingBuffer ringbuffer_; + size_t cmd_alloc_size_; + Command *commands_; + size_t num_commands_; + size_t num_literals_; + size_t last_insert_len_; + uint64_t last_flush_pos_; + uint64_t last_processed_pos_; + int dist_cache_[BROTLI_NUM_DISTANCE_SHORT_CODES]; + int saved_dist_cache_[4]; + uint16_t last_bytes_; + uint8_t last_bytes_bits_; + /* "Flint" is a tiny uncompressed block emitted before the continuation + block to unwire literal context from previous data. Despite being int8_t, + field is actually BrotliEncoderFlintState enum. */ + int8_t flint_; + uint8_t prev_byte_; + uint8_t prev_byte2_; + size_t storage_size_; + uint8_t *storage_; + + Hasher hasher_; + + /* Hash table for FAST_ONE_PASS_COMPRESSION_QUALITY mode. */ + int small_table_[1 << 10]; /* 4KiB */ + int *large_table_; /* Allocated only when needed */ + size_t large_table_size_; + + BrotliOnePassArena *one_pass_arena_; + BrotliTwoPassArena *two_pass_arena_; + + /* Command and literal buffers for FAST_TWO_PASS_COMPRESSION_QUALITY. */ + uint32_t *command_buf_; + uint8_t *literal_buf_; + + uint64_t total_in_; + uint8_t *next_out_; + size_t available_out_; + uint64_t total_out_; + /* Temporary buffer for padding flush bits or metadata block header / body. */ + union { + uint64_t u64[2]; + uint8_t u8[16]; + } tiny_buf_; + uint32_t remaining_metadata_bytes_; + BrotliEncoderStreamState stream_state_; + + BROTLI_BOOL is_last_block_emitted_; + BROTLI_BOOL is_initialized_; +} BrotliEncoderStateStruct; + +typedef struct BrotliEncoderStateStruct BrotliEncoderStateInternal; +#define BrotliEncoderState BrotliEncoderStateInternal +} +#endif // BROTLI_ENC_STATE_H_ diff --git a/third_party/brotli/enc/static_dict.cpp b/third_party/brotli/enc/static_dict.cpp new file mode 100644 index 00000000000..26b6387178d --- /dev/null +++ b/third_party/brotli/enc/static_dict.cpp @@ -0,0 +1,538 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +#include "static_dict.h" + +#include "../common/dictionary.h" +#include "../common/brotli_platform.h" +#include "../common/transform.h" +#include "encoder_dict.h" +#include "find_match_length.h" + +using namespace duckdb_brotli; + +static BROTLI_INLINE uint32_t Hash(const uint8_t* data) { + uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kDictHashMul32; + /* The higher bits contain more mixture from the multiplication, + so we take our results from there. */ + return h >> (32 - kDictNumBits); +} + +static BROTLI_INLINE void AddMatch(size_t distance, size_t len, size_t len_code, + uint32_t* matches) { + uint32_t match = (uint32_t)((distance << 5) + len_code); + matches[len] = BROTLI_MIN(uint32_t, matches[len], match); +} + +static BROTLI_INLINE size_t DictMatchLength(const BrotliDictionary* dictionary, + const uint8_t* data, + size_t id, + size_t len, + size_t maxlen) { + const size_t offset = dictionary->offsets_by_length[len] + len * id; + return FindMatchLengthWithLimit(&dictionary->data[offset], data, + BROTLI_MIN(size_t, len, maxlen)); +} + +static BROTLI_INLINE BROTLI_BOOL IsMatch(const BrotliDictionary* dictionary, + DictWord w, const uint8_t* data, size_t max_length) { + if (w.len > max_length) { + return BROTLI_FALSE; + } else { + const size_t offset = dictionary->offsets_by_length[w.len] + + (size_t)w.len * (size_t)w.idx; + const uint8_t* dict = &dictionary->data[offset]; + if (w.transform == 0) { + /* Match against base dictionary word. */ + return + TO_BROTLI_BOOL(FindMatchLengthWithLimit(dict, data, w.len) == w.len); + } else if (w.transform == 10) { + /* Match against uppercase first transform. + Note that there are only ASCII uppercase words in the lookup table. */ + return TO_BROTLI_BOOL(dict[0] >= 'a' && dict[0] <= 'z' && + (dict[0] ^ 32) == data[0] && + FindMatchLengthWithLimit(&dict[1], &data[1], w.len - 1u) == + w.len - 1u); + } else { + /* Match against uppercase all transform. + Note that there are only ASCII uppercase words in the lookup table. */ + size_t i; + for (i = 0; i < w.len; ++i) { + if (dict[i] >= 'a' && dict[i] <= 'z') { + if ((dict[i] ^ 32) != data[i]) return BROTLI_FALSE; + } else { + if (dict[i] != data[i]) return BROTLI_FALSE; + } + } + return BROTLI_TRUE; + } + } +} + +/* Finds matches for a single static dictionary */ +static BROTLI_BOOL BrotliFindAllStaticDictionaryMatchesFor( + const BrotliEncoderDictionary* dictionary, const uint8_t* data, + size_t min_length, size_t max_length, uint32_t* matches) { + BROTLI_BOOL has_found_match = BROTLI_FALSE; +#if defined(BROTLI_EXPERIMENTAL) + if (dictionary->has_words_heavy) { + const BrotliTrieNode* node = &dictionary->trie.root; + size_t l = 0; + while (node && l < max_length) { + uint8_t c; + if (l >= min_length && node->len_) { + AddMatch(node->idx_, l, node->len_, matches); + has_found_match = BROTLI_TRUE; + } + c = data[l++]; + node = BrotliTrieSub(&dictionary->trie, node, c); + } + return has_found_match; + } +#endif /* BROTLI_EXPERIMENTAL */ + { + size_t offset = dictionary->buckets[Hash(data)]; + BROTLI_BOOL end = !offset; + while (!end) { + DictWord w = dictionary->dict_words[offset++]; + const size_t l = w.len & 0x1F; + const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l]; + const size_t id = w.idx; + end = !!(w.len & 0x80); + w.len = (uint8_t)l; + if (w.transform == 0) { + const size_t matchlen = + DictMatchLength(dictionary->words, data, id, l, max_length); + const uint8_t* s; + size_t minlen; + size_t maxlen; + size_t len; + /* Transform "" + BROTLI_TRANSFORM_IDENTITY + "" */ + if (matchlen == l) { + AddMatch(id, l, l, matches); + has_found_match = BROTLI_TRUE; + } + /* Transforms "" + BROTLI_TRANSFORM_OMIT_LAST_1 + "" and + "" + BROTLI_TRANSFORM_OMIT_LAST_1 + "ing " */ + if (matchlen >= l - 1) { + AddMatch(id + 12 * n, l - 1, l, matches); + if (l + 2 < max_length && + data[l - 1] == 'i' && data[l] == 'n' && data[l + 1] == 'g' && + data[l + 2] == ' ') { + AddMatch(id + 49 * n, l + 3, l, matches); + } + has_found_match = BROTLI_TRUE; + } + /* Transform "" + BROTLI_TRANSFORM_OMIT_LAST_# + "" (# = 2 .. 9) */ + minlen = min_length; + if (l > 9) minlen = BROTLI_MAX(size_t, minlen, l - 9); + maxlen = BROTLI_MIN(size_t, matchlen, l - 2); + for (len = minlen; len <= maxlen; ++len) { + size_t cut = l - len; + size_t transform_id = (cut << 2) + + (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F); + AddMatch(id + transform_id * n, len, l, matches); + has_found_match = BROTLI_TRUE; + } + if (matchlen < l || l + 6 >= max_length) { + continue; + } + s = &data[l]; + /* Transforms "" + BROTLI_TRANSFORM_IDENTITY + */ + if (s[0] == ' ') { + AddMatch(id + n, l + 1, l, matches); + if (s[1] == 'a') { + if (s[2] == ' ') { + AddMatch(id + 28 * n, l + 3, l, matches); + } else if (s[2] == 's') { + if (s[3] == ' ') AddMatch(id + 46 * n, l + 4, l, matches); + } else if (s[2] == 't') { + if (s[3] == ' ') AddMatch(id + 60 * n, l + 4, l, matches); + } else if (s[2] == 'n') { + if (s[3] == 'd' && s[4] == ' ') { + AddMatch(id + 10 * n, l + 5, l, matches); + } + } + } else if (s[1] == 'b') { + if (s[2] == 'y' && s[3] == ' ') { + AddMatch(id + 38 * n, l + 4, l, matches); + } + } else if (s[1] == 'i') { + if (s[2] == 'n') { + if (s[3] == ' ') AddMatch(id + 16 * n, l + 4, l, matches); + } else if (s[2] == 's') { + if (s[3] == ' ') AddMatch(id + 47 * n, l + 4, l, matches); + } + } else if (s[1] == 'f') { + if (s[2] == 'o') { + if (s[3] == 'r' && s[4] == ' ') { + AddMatch(id + 25 * n, l + 5, l, matches); + } + } else if (s[2] == 'r') { + if (s[3] == 'o' && s[4] == 'm' && s[5] == ' ') { + AddMatch(id + 37 * n, l + 6, l, matches); + } + } + } else if (s[1] == 'o') { + if (s[2] == 'f') { + if (s[3] == ' ') AddMatch(id + 8 * n, l + 4, l, matches); + } else if (s[2] == 'n') { + if (s[3] == ' ') AddMatch(id + 45 * n, l + 4, l, matches); + } + } else if (s[1] == 'n') { + if (s[2] == 'o' && s[3] == 't' && s[4] == ' ') { + AddMatch(id + 80 * n, l + 5, l, matches); + } + } else if (s[1] == 't') { + if (s[2] == 'h') { + if (s[3] == 'e') { + if (s[4] == ' ') AddMatch(id + 5 * n, l + 5, l, matches); + } else if (s[3] == 'a') { + if (s[4] == 't' && s[5] == ' ') { + AddMatch(id + 29 * n, l + 6, l, matches); + } + } + } else if (s[2] == 'o') { + if (s[3] == ' ') AddMatch(id + 17 * n, l + 4, l, matches); + } + } else if (s[1] == 'w') { + if (s[2] == 'i' && s[3] == 't' && s[4] == 'h' && s[5] == ' ') { + AddMatch(id + 35 * n, l + 6, l, matches); + } + } + } else if (s[0] == '"') { + AddMatch(id + 19 * n, l + 1, l, matches); + if (s[1] == '>') { + AddMatch(id + 21 * n, l + 2, l, matches); + } + } else if (s[0] == '.') { + AddMatch(id + 20 * n, l + 1, l, matches); + if (s[1] == ' ') { + AddMatch(id + 31 * n, l + 2, l, matches); + if (s[2] == 'T' && s[3] == 'h') { + if (s[4] == 'e') { + if (s[5] == ' ') AddMatch(id + 43 * n, l + 6, l, matches); + } else if (s[4] == 'i') { + if (s[5] == 's' && s[6] == ' ') { + AddMatch(id + 75 * n, l + 7, l, matches); + } + } + } + } + } else if (s[0] == ',') { + AddMatch(id + 76 * n, l + 1, l, matches); + if (s[1] == ' ') { + AddMatch(id + 14 * n, l + 2, l, matches); + } + } else if (s[0] == '\n') { + AddMatch(id + 22 * n, l + 1, l, matches); + if (s[1] == '\t') { + AddMatch(id + 50 * n, l + 2, l, matches); + } + } else if (s[0] == ']') { + AddMatch(id + 24 * n, l + 1, l, matches); + } else if (s[0] == '\'') { + AddMatch(id + 36 * n, l + 1, l, matches); + } else if (s[0] == ':') { + AddMatch(id + 51 * n, l + 1, l, matches); + } else if (s[0] == '(') { + AddMatch(id + 57 * n, l + 1, l, matches); + } else if (s[0] == '=') { + if (s[1] == '"') { + AddMatch(id + 70 * n, l + 2, l, matches); + } else if (s[1] == '\'') { + AddMatch(id + 86 * n, l + 2, l, matches); + } + } else if (s[0] == 'a') { + if (s[1] == 'l' && s[2] == ' ') { + AddMatch(id + 84 * n, l + 3, l, matches); + } + } else if (s[0] == 'e') { + if (s[1] == 'd') { + if (s[2] == ' ') AddMatch(id + 53 * n, l + 3, l, matches); + } else if (s[1] == 'r') { + if (s[2] == ' ') AddMatch(id + 82 * n, l + 3, l, matches); + } else if (s[1] == 's') { + if (s[2] == 't' && s[3] == ' ') { + AddMatch(id + 95 * n, l + 4, l, matches); + } + } + } else if (s[0] == 'f') { + if (s[1] == 'u' && s[2] == 'l' && s[3] == ' ') { + AddMatch(id + 90 * n, l + 4, l, matches); + } + } else if (s[0] == 'i') { + if (s[1] == 'v') { + if (s[2] == 'e' && s[3] == ' ') { + AddMatch(id + 92 * n, l + 4, l, matches); + } + } else if (s[1] == 'z') { + if (s[2] == 'e' && s[3] == ' ') { + AddMatch(id + 100 * n, l + 4, l, matches); + } + } + } else if (s[0] == 'l') { + if (s[1] == 'e') { + if (s[2] == 's' && s[3] == 's' && s[4] == ' ') { + AddMatch(id + 93 * n, l + 5, l, matches); + } + } else if (s[1] == 'y') { + if (s[2] == ' ') AddMatch(id + 61 * n, l + 3, l, matches); + } + } else if (s[0] == 'o') { + if (s[1] == 'u' && s[2] == 's' && s[3] == ' ') { + AddMatch(id + 106 * n, l + 4, l, matches); + } + } + } else { + /* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and + is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL) + transform. */ + const BROTLI_BOOL is_all_caps = + TO_BROTLI_BOOL(w.transform != BROTLI_TRANSFORM_UPPERCASE_FIRST); + const uint8_t* s; + if (!IsMatch(dictionary->words, w, data, max_length)) { + continue; + } + /* Transform "" + kUppercase{First,All} + "" */ + AddMatch(id + (is_all_caps ? 44 : 9) * n, l, l, matches); + has_found_match = BROTLI_TRUE; + if (l + 1 >= max_length) { + continue; + } + /* Transforms "" + kUppercase{First,All} + */ + s = &data[l]; + if (s[0] == ' ') { + AddMatch(id + (is_all_caps ? 68 : 4) * n, l + 1, l, matches); + } else if (s[0] == '"') { + AddMatch(id + (is_all_caps ? 87 : 66) * n, l + 1, l, matches); + if (s[1] == '>') { + AddMatch(id + (is_all_caps ? 97 : 69) * n, l + 2, l, matches); + } + } else if (s[0] == '.') { + AddMatch(id + (is_all_caps ? 101 : 79) * n, l + 1, l, matches); + if (s[1] == ' ') { + AddMatch(id + (is_all_caps ? 114 : 88) * n, l + 2, l, matches); + } + } else if (s[0] == ',') { + AddMatch(id + (is_all_caps ? 112 : 99) * n, l + 1, l, matches); + if (s[1] == ' ') { + AddMatch(id + (is_all_caps ? 107 : 58) * n, l + 2, l, matches); + } + } else if (s[0] == '\'') { + AddMatch(id + (is_all_caps ? 94 : 74) * n, l + 1, l, matches); + } else if (s[0] == '(') { + AddMatch(id + (is_all_caps ? 113 : 78) * n, l + 1, l, matches); + } else if (s[0] == '=') { + if (s[1] == '"') { + AddMatch(id + (is_all_caps ? 105 : 104) * n, l + 2, l, matches); + } else if (s[1] == '\'') { + AddMatch(id + (is_all_caps ? 116 : 108) * n, l + 2, l, matches); + } + } + } + } + } + /* Transforms with prefixes " " and "." */ + if (max_length >= 5 && (data[0] == ' ' || data[0] == '.')) { + BROTLI_BOOL is_space = TO_BROTLI_BOOL(data[0] == ' '); + size_t offset = dictionary->buckets[Hash(&data[1])]; + BROTLI_BOOL end = !offset; + while (!end) { + DictWord w = dictionary->dict_words[offset++]; + const size_t l = w.len & 0x1F; + const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l]; + const size_t id = w.idx; + end = !!(w.len & 0x80); + w.len = (uint8_t)l; + if (w.transform == 0) { + const uint8_t* s; + if (!IsMatch(dictionary->words, w, &data[1], max_length - 1)) { + continue; + } + /* Transforms " " + BROTLI_TRANSFORM_IDENTITY + "" and + "." + BROTLI_TRANSFORM_IDENTITY + "" */ + AddMatch(id + (is_space ? 6 : 32) * n, l + 1, l, matches); + has_found_match = BROTLI_TRUE; + if (l + 2 >= max_length) { + continue; + } + /* Transforms " " + BROTLI_TRANSFORM_IDENTITY + and + "." + BROTLI_TRANSFORM_IDENTITY + + */ + s = &data[l + 1]; + if (s[0] == ' ') { + AddMatch(id + (is_space ? 2 : 77) * n, l + 2, l, matches); + } else if (s[0] == '(') { + AddMatch(id + (is_space ? 89 : 67) * n, l + 2, l, matches); + } else if (is_space) { + if (s[0] == ',') { + AddMatch(id + 103 * n, l + 2, l, matches); + if (s[1] == ' ') { + AddMatch(id + 33 * n, l + 3, l, matches); + } + } else if (s[0] == '.') { + AddMatch(id + 71 * n, l + 2, l, matches); + if (s[1] == ' ') { + AddMatch(id + 52 * n, l + 3, l, matches); + } + } else if (s[0] == '=') { + if (s[1] == '"') { + AddMatch(id + 81 * n, l + 3, l, matches); + } else if (s[1] == '\'') { + AddMatch(id + 98 * n, l + 3, l, matches); + } + } + } + } else if (is_space) { + /* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and + is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL) + transform. */ + const BROTLI_BOOL is_all_caps = + TO_BROTLI_BOOL(w.transform != BROTLI_TRANSFORM_UPPERCASE_FIRST); + const uint8_t* s; + if (!IsMatch(dictionary->words, w, &data[1], max_length - 1)) { + continue; + } + /* Transforms " " + kUppercase{First,All} + "" */ + AddMatch(id + (is_all_caps ? 85 : 30) * n, l + 1, l, matches); + has_found_match = BROTLI_TRUE; + if (l + 2 >= max_length) { + continue; + } + /* Transforms " " + kUppercase{First,All} + */ + s = &data[l + 1]; + if (s[0] == ' ') { + AddMatch(id + (is_all_caps ? 83 : 15) * n, l + 2, l, matches); + } else if (s[0] == ',') { + if (!is_all_caps) { + AddMatch(id + 109 * n, l + 2, l, matches); + } + if (s[1] == ' ') { + AddMatch(id + (is_all_caps ? 111 : 65) * n, l + 3, l, matches); + } + } else if (s[0] == '.') { + AddMatch(id + (is_all_caps ? 115 : 96) * n, l + 2, l, matches); + if (s[1] == ' ') { + AddMatch(id + (is_all_caps ? 117 : 91) * n, l + 3, l, matches); + } + } else if (s[0] == '=') { + if (s[1] == '"') { + AddMatch(id + (is_all_caps ? 110 : 118) * n, l + 3, l, matches); + } else if (s[1] == '\'') { + AddMatch(id + (is_all_caps ? 119 : 120) * n, l + 3, l, matches); + } + } + } + } + } + if (max_length >= 6) { + /* Transforms with prefixes "e ", "s ", ", " and "\xC2\xA0" */ + if ((data[1] == ' ' && + (data[0] == 'e' || data[0] == 's' || data[0] == ',')) || + (data[0] == 0xC2 && data[1] == 0xA0)) { + size_t offset = dictionary->buckets[Hash(&data[2])]; + BROTLI_BOOL end = !offset; + while (!end) { + DictWord w = dictionary->dict_words[offset++]; + const size_t l = w.len & 0x1F; + const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l]; + const size_t id = w.idx; + end = !!(w.len & 0x80); + w.len = (uint8_t)l; + if (w.transform == 0 && + IsMatch(dictionary->words, w, &data[2], max_length - 2)) { + if (data[0] == 0xC2) { + AddMatch(id + 102 * n, l + 2, l, matches); + has_found_match = BROTLI_TRUE; + } else if (l + 2 < max_length && data[l + 2] == ' ') { + size_t t = data[0] == 'e' ? 18 : (data[0] == 's' ? 7 : 13); + AddMatch(id + t * n, l + 3, l, matches); + has_found_match = BROTLI_TRUE; + } + } + } + } + } + if (max_length >= 9) { + /* Transforms with prefixes " the " and ".com/" */ + if ((data[0] == ' ' && data[1] == 't' && data[2] == 'h' && + data[3] == 'e' && data[4] == ' ') || + (data[0] == '.' && data[1] == 'c' && data[2] == 'o' && + data[3] == 'm' && data[4] == '/')) { + size_t offset = dictionary->buckets[Hash(&data[5])]; + BROTLI_BOOL end = !offset; + while (!end) { + DictWord w = dictionary->dict_words[offset++]; + const size_t l = w.len & 0x1F; + const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l]; + const size_t id = w.idx; + end = !!(w.len & 0x80); + w.len = (uint8_t)l; + if (w.transform == 0 && + IsMatch(dictionary->words, w, &data[5], max_length - 5)) { + AddMatch(id + (data[0] == ' ' ? 41 : 72) * n, l + 5, l, matches); + has_found_match = BROTLI_TRUE; + if (l + 5 < max_length) { + const uint8_t* s = &data[l + 5]; + if (data[0] == ' ') { + if (l + 8 < max_length && + s[0] == ' ' && s[1] == 'o' && s[2] == 'f' && s[3] == ' ') { + AddMatch(id + 62 * n, l + 9, l, matches); + if (l + 12 < max_length && + s[4] == 't' && s[5] == 'h' && s[6] == 'e' && s[7] == ' ') { + AddMatch(id + 73 * n, l + 13, l, matches); + } + } + } + } + } + } + } + } + return has_found_match; +} + +/* Finds matches for one or more dictionaries, if multiple are present + in the contextual dictionary */ +BROTLI_BOOL duckdb_brotli::BrotliFindAllStaticDictionaryMatches( + const BrotliEncoderDictionary* dictionary, const uint8_t* data, + size_t min_length, size_t max_length, uint32_t* matches) { + BROTLI_BOOL has_found_match = + BrotliFindAllStaticDictionaryMatchesFor( + dictionary, data, min_length, max_length, matches); + + if (!!dictionary->parent && dictionary->parent->num_dictionaries > 1) { + uint32_t matches2[BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1]; + int l; + const BrotliEncoderDictionary* dictionary2 = dictionary->parent->dict[0]; + if (dictionary2 == dictionary) { + dictionary2 = dictionary->parent->dict[1]; + } + + for (l = 0; l < BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1; l++) { + matches2[l] = kInvalidMatch; + } + + has_found_match |= BrotliFindAllStaticDictionaryMatchesFor( + dictionary2, data, min_length, max_length, matches2); + + for (l = 0; l < BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1; l++) { + if (matches2[l] != kInvalidMatch) { + uint32_t dist = (uint32_t)(matches2[l] >> 5); + uint32_t len_code = matches2[l] & 31; + uint32_t skipdist = (uint32_t)((uint32_t)(1 << dictionary->words-> + size_bits_by_length[len_code]) & ~1u) * + (uint32_t)dictionary->num_transforms; + /* TODO(lode): check for dist overflow */ + dist += skipdist; + AddMatch(dist, (size_t)l, len_code, matches); + } + } + } + return has_found_match; +} + diff --git a/third_party/brotli/enc/static_dict.h b/third_party/brotli/enc/static_dict.h new file mode 100644 index 00000000000..45c805cc25d --- /dev/null +++ b/third_party/brotli/enc/static_dict.h @@ -0,0 +1,37 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Class to model the static dictionary. */ + +#ifndef BROTLI_ENC_STATIC_DICT_H_ +#define BROTLI_ENC_STATIC_DICT_H_ + +#include + +#include "../common/dictionary.h" +#include "../common/brotli_platform.h" +#include "encoder_dict.h" + +namespace duckdb_brotli { + +#define BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN 37 +static const uint32_t kInvalidMatch = 0xFFFFFFF; + +/* Matches data against static dictionary words, and for each length l, + for which a match is found, updates matches[l] to be the minimum possible + (distance << 5) + len_code. + Returns 1 if matches have been found, otherwise 0. + Prerequisites: + matches array is at least BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1 long + all elements are initialized to kInvalidMatch */ +BROTLI_INTERNAL BROTLI_BOOL BrotliFindAllStaticDictionaryMatches( + const BrotliEncoderDictionary* dictionary, + const uint8_t* data, size_t min_length, size_t max_length, + uint32_t* matches); + +} + +#endif /* BROTLI_ENC_STATIC_DICT_H_ */ diff --git a/third_party/brotli/enc/static_dict_lut.h b/third_party/brotli/enc/static_dict_lut.h new file mode 100644 index 00000000000..2ce39a2982b --- /dev/null +++ b/third_party/brotli/enc/static_dict_lut.h @@ -0,0 +1,5862 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Lookup table for static dictionary and transforms. */ + +#ifndef BROTLI_ENC_STATIC_DICT_LUT_H_ +#define BROTLI_ENC_STATIC_DICT_LUT_H_ + +#include + +namespace duckdb_brotli { + +typedef struct DictWord { + /* Highest bit is used to indicate end of bucket. */ + uint8_t len; + uint8_t transform; + uint16_t idx; +} DictWord; + +/* GENERATED CODE START */ +static const int kDictNumBits = 15; +static const uint32_t kDictHashMul32 = 0x1E35A7BD; + +static const uint16_t kStaticDictionaryBuckets[32768] = { +1,0,0,0,0,0,0,0,0,3,6,0,0,0,0,0,20,0,0,0,21,0,22,0,0,0,0,0,0,0,0,23,0,0,25,0,29, +0,53,0,0,0,0,0,0,55,0,0,0,0,0,0,61,76,0,0,0,94,0,0,0,0,0,0,96,0,97,0,98,0,0,0,0, +0,0,0,99,101,106,108,0,0,0,0,0,110,0,111,112,0,113,118,124,0,0,0,0,0,125,128,0,0 +,0,0,129,0,0,131,0,0,0,0,0,0,132,0,0,135,0,0,0,137,0,0,0,0,0,138,139,0,0,0,0,0,0 +,0,142,143,144,0,0,0,0,0,145,0,0,0,146,149,151,152,0,0,153,0,0,0,0,0,0,0,0,0,0,0 +,0,0,0,0,154,0,0,0,0,0,0,155,0,0,0,0,160,182,0,0,0,0,0,0,183,0,0,0,188,189,0,0, +192,0,0,0,0,0,0,194,0,0,0,0,0,0,0,0,197,202,209,0,0,210,0,224,0,0,0,225,0,0,0,0, +0,0,0,0,0,0,231,0,0,0,232,0,240,0,0,242,0,0,0,0,0,0,0,0,0,0,0,244,0,0,0,246,0,0, +249,251,253,0,0,0,0,0,258,0,0,261,263,0,0,0,267,0,0,268,0,269,0,0,0,0,0,0,0,0,0, +271,0,0,0,0,0,0,272,0,273,0,277,0,278,286,0,0,0,0,287,0,289,290,291,0,0,0,295,0, +0,296,297,0,0,0,0,0,0,0,0,0,0,298,0,0,0,299,0,0,305,0,324,0,0,0,0,0,327,0,328, +329,0,0,0,0,336,0,0,340,0,341,342,343,0,0,346,0,348,0,0,0,0,0,0,349,351,0,0,355, +0,363,0,364,0,368,369,0,370,0,0,0,0,0,0,0,372,0,0,0,0,0,0,0,0,0,0,0,373,0,375,0, +0,0,0,376,377,0,0,394,395,396,0,0,398,0,0,0,0,400,0,0,408,0,0,0,0,420,0,0,0,0,0, +0,421,0,0,422,423,0,0,429,435,436,442,0,0,443,0,444,445,453,456,0,457,0,0,0,0,0, +458,0,0,0,459,0,0,0,460,0,462,463,465,0,0,0,0,0,0,466,469,0,0,0,0,0,0,470,0,0,0, +474,0,476,0,0,0,0,483,0,485,0,0,0,486,0,0,488,491,492,0,0,497,499,500,0,501,0,0, +0,505,0,0,506,0,0,0,507,0,0,0,509,0,0,0,0,511,512,519,0,0,0,0,0,0,529,530,0,0,0, +534,0,0,0,0,543,0,0,0,0,0,0,0,0,0,553,0,0,0,0,557,560,0,0,0,0,0,0,561,0,564,0,0, +0,0,0,0,565,566,0,575,0,619,0,620,0,0,623,624,0,0,0,625,0,0,626,627,0,0,628,0,0, +0,0,630,0,631,0,0,0,0,0,0,0,0,0,641,0,0,0,0,643,656,668,0,0,0,673,0,0,0,674,0,0, +0,0,0,0,0,0,682,0,687,0,690,0,693,699,700,0,0,0,0,0,0,704,705,0,0,0,0,707,710,0, +711,0,0,0,0,726,0,0,729,0,0,0,730,731,0,0,0,0,0,752,0,0,0,762,0,763,0,0,767,0,0, +0,770,774,0,0,775,0,0,0,0,0,0,0,0,0,0,776,0,0,0,777,783,0,0,0,785,788,0,0,0,0, +790,0,0,0,793,0,0,0,0,794,0,0,804,819,821,0,827,0,0,0,834,0,0,835,0,0,0,841,0, +844,0,850,851,859,0,860,0,0,0,0,0,0,0,874,0,876,0,877,890,0,0,0,0,0,0,0,0,893, +894,898,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,899,0,0,0,900,904,906,0,0,0,907,0,908,909, +0,910,0,0,0,0,911,0,0,0,0,0,916,0,0,0,922,925,0,930,0,934,0,0,0,0,0,943,0,0,944, +0,953,954,0,0,0,0,0,0,955,0,962,963,0,0,976,0,0,977,978,979,980,0,981,0,0,0,0, +984,0,0,985,0,0,987,989,991,0,0,0,0,0,0,0,0,0,992,0,0,0,993,0,0,0,0,0,0,996,0,0, +0,1000,0,0,0,0,0,1002,0,0,0,0,1005,1007,0,0,0,1009,0,0,0,1010,0,0,0,0,0,0,1011,0 +,1012,0,0,0,0,1014,1016,0,0,0,1020,0,1021,0,0,0,0,1022,0,0,0,1024,0,0,0,0,0,0, +1025,0,0,1026,1027,0,0,0,0,0,1031,0,1033,0,0,0,0,1034,0,0,0,1037,1040,0,0,0,1042 +,1043,0,0,1053,0,1054,0,0,1057,0,0,0,1058,0,0,1060,0,0,0,0,0,0,0,1061,0,0,1062,0 +,0,0,0,1063,0,0,0,0,1064,0,0,0,0,0,1065,0,0,0,0,1066,1067,0,0,0,1069,1070,1072,0 +,0,0,0,0,0,1073,0,1075,0,0,0,0,0,0,1080,1084,0,0,0,0,1088,0,0,0,0,0,0,1094,0, +1095,0,1107,0,0,0,1112,1114,0,1119,0,1122,0,0,1126,0,1129,0,1130,0,0,0,0,0,1132, +0,0,0,0,0,0,1144,0,0,1145,1146,0,1148,1149,0,0,1150,1151,0,0,0,0,1152,0,1153,0,0 +,0,0,0,1154,0,1163,0,0,0,1164,0,0,0,0,0,1165,0,1167,0,1170,0,0,0,0,0,1171,1172,0 +,0,0,0,0,0,0,0,1173,1175,1177,0,1186,0,0,0,0,0,0,0,0,0,0,1195,0,0,1221,0,0,1224, +0,0,1227,0,0,0,0,0,1228,1229,0,0,1230,0,0,0,0,0,0,0,0,0,1231,0,0,0,1233,0,0,1243 +,1244,1246,1248,0,0,0,0,1254,1255,1258,1259,0,0,0,1260,0,0,1261,0,0,0,1262,1264, +0,0,1265,0,0,0,0,0,0,0,0,0,0,0,0,1266,0,1267,0,0,0,0,1273,1274,1276,1289,0,0, +1291,1292,1293,0,0,1294,1295,1296,0,0,0,0,1302,0,1304,0,0,0,0,0,0,0,0,0,1311, +1312,0,1314,0,1316,1320,1321,0,0,0,0,0,0,0,1322,1323,1324,0,1335,0,1336,0,0,0,0, +1341,1342,0,1346,0,1357,0,0,0,1358,1360,0,0,0,0,0,0,1361,0,0,0,1362,1365,0,1366, +0,0,0,0,0,0,0,1379,0,0,0,0,0,0,0,0,0,0,0,0,1386,0,1388,0,0,0,0,0,0,0,0,0,0,0,0,0 +,0,1395,0,0,0,0,1403,0,1405,0,0,1407,0,0,0,0,0,1408,1409,0,1410,0,0,0,1412,1413, +1416,0,0,1429,1451,0,0,1454,0,0,0,0,0,0,0,1455,0,0,0,0,0,0,0,1456,0,0,0,0,1459, +1460,1461,1475,0,0,0,0,0,0,1477,0,1480,0,1481,0,0,1486,0,0,1495,0,0,0,1496,0,0, +1498,1499,1501,1520,1521,0,0,0,1526,0,0,0,0,1528,1529,0,1533,1536,0,0,0,1537, +1538,1549,0,1550,1558,1559,1572,0,1573,0,0,0,0,0,0,0,0,0,1575,0,0,0,0,0,1579,0, +1599,0,1603,0,1604,0,1605,0,0,0,0,0,1608,1610,0,0,0,0,1611,0,1615,0,1616,1618,0, +1619,0,0,1622,0,0,0,0,1634,0,0,0,1635,0,0,0,1641,0,0,0,0,0,0,0,0,0,1643,0,0,0, +1650,0,0,1652,0,0,0,0,0,1653,0,0,0,1654,0,0,0,0,1655,0,1662,0,0,1663,1664,0,0, +1668,0,0,1669,1670,0,1672,1673,0,0,0,0,0,1674,0,0,0,1675,1676,1680,0,1682,0,0, +1687,0,0,0,0,0,1704,0,0,1705,0,0,1721,0,0,0,0,1734,1735,0,0,0,0,1737,0,0,0,0, +1739,0,0,1740,0,0,0,0,0,0,0,0,0,0,1741,1743,0,0,0,0,1745,0,0,0,1749,0,0,0,1751,0 +,0,0,0,0,0,1760,0,0,0,0,1765,0,0,0,0,0,1784,0,1785,1787,0,0,0,0,1788,1789,0,0,0, +0,1790,1791,1793,0,1798,1799,0,0,0,0,1801,0,1803,1805,0,0,0,1806,1811,0,1812, +1814,0,1821,0,0,0,0,0,1822,1833,0,0,0,0,0,0,1848,0,0,0,0,0,0,1857,0,0,0,1859,0,0 +,0,0,1861,0,0,0,0,0,0,0,1866,0,1921,1925,0,0,0,1929,1930,0,0,0,0,0,0,0,0,0,1931, +0,0,0,0,1932,0,0,0,1934,0,0,0,0,0,0,0,0,1946,0,0,1948,0,0,0,0,1950,0,1957,0,1958 +,0,0,0,0,0,1965,1967,0,0,0,0,1968,0,1969,0,1971,1972,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +,0,1973,0,0,0,0,1975,0,0,0,0,1976,1979,0,1982,0,0,0,0,1984,1988,0,0,0,0,1990, +2004,2008,0,0,0,2012,2013,0,0,0,0,0,0,0,0,0,0,2015,0,2016,2017,0,0,0,0,2021,0,0, +2025,0,0,0,0,0,2029,2036,2040,0,2042,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2043,0,0,0,0,0, +2045,0,0,0,0,0,0,0,2046,2047,0,2048,2049,0,2059,0,0,2063,0,2064,2065,0,0,2066,0, +0,0,0,0,0,2069,0,0,0,0,2070,0,2071,0,2072,0,0,0,0,2080,2082,2083,0,0,0,0,0,2085, +0,2086,2088,2089,2105,0,0,0,0,2107,0,0,2116,2117,0,2120,0,0,2122,0,0,0,0,0,2123, +0,0,2125,2127,2128,0,0,0,2130,0,0,0,2137,2139,2140,2141,0,0,0,0,0,0,0,0,0,2144, +2145,0,0,2146,2149,0,0,0,0,2150,0,0,2151,2158,0,2159,0,2160,0,0,0,0,0,0,2161, +2162,0,0,2194,2202,0,0,0,0,0,0,2205,2217,0,2220,0,2221,0,2222,2224,0,0,0,0,2237, +0,0,0,0,0,2238,0,2239,2241,0,0,2242,0,0,0,0,0,2243,0,0,0,0,0,0,2252,0,0,2253,0,0 +,0,2257,2258,0,0,0,2260,0,0,0,0,0,0,0,2262,0,2264,0,0,0,0,0,2269,2270,0,0,0,0,0, +0,0,0,0,2271,0,2273,0,0,0,0,2277,0,0,0,0,2278,0,0,0,0,2279,0,2280,0,2283,0,0,0,0 +,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2287,0,0,0,0,0,0,0,2289,2290,0,0,0,0,2291,0,2292,0, +0,0,2293,2295,2296,0,0,0,0,0,0,0,2298,0,0,0,0,0,2303,0,2305,0,0,2306,0,2307,0,0, +0,0,0,0,0,0,0,0,0,0,2313,2314,2315,2316,0,0,2318,0,2319,0,2322,0,0,2323,0,2324,0 +,2326,0,0,0,0,0,0,0,2335,0,2336,2338,2339,0,2340,0,0,0,2355,0,2375,0,2382,2386,0 +,2387,0,0,2394,0,0,0,0,2395,0,2397,0,0,0,0,0,2398,0,0,0,0,0,0,0,2399,2402,2404, +2408,2411,0,0,0,2413,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2415,0,0,2416,2417,2419,0,2420, +0,0,0,0,0,2425,0,0,0,2426,0,0,0,0,0,0,0,0,0,0,0,0,2427,2428,0,2429,0,0,2430,2434 +,0,2436,0,0,0,0,0,0,2441,2442,0,2445,0,0,2446,2457,0,2459,0,0,2462,0,2464,0,2477 +,0,2478,2486,0,0,0,2491,0,0,2493,0,0,2494,0,2495,0,2513,2523,0,0,0,0,2524,0,0,0, +0,0,0,2528,2529,2530,0,0,2531,0,2533,0,0,2534,2535,0,2536,2537,0,2538,0,2539, +2540,0,0,0,2545,2546,0,0,0,0,0,0,0,2548,0,0,2549,0,2550,2555,0,0,0,0,0,2557,0, +2560,0,0,0,0,0,0,0,0,0,0,0,2561,0,2576,0,0,0,0,0,0,0,0,0,2577,2578,0,0,0,2579,0, +0,0,0,0,0,0,2580,0,0,0,0,2581,0,0,0,0,2583,0,2584,0,2588,2590,0,0,0,2591,0,0,0,0 +,2593,2594,0,2595,0,2601,2602,0,0,2603,0,2605,0,0,0,2606,2607,2611,0,2615,0,0,0, +2617,0,0,0,0,0,0,0,0,0,0,0,0,0,2619,0,0,2620,0,0,0,2621,0,2623,0,2625,0,0,2628, +2629,0,0,2635,2636,2637,0,0,2639,0,0,0,2642,0,0,0,0,2643,0,2644,0,2649,0,0,0,0,0 +,0,2655,2656,0,0,2657,0,0,0,0,0,2658,0,0,0,0,0,2659,0,0,0,0,2664,2685,0,2687,0, +2688,0,0,2689,0,0,2694,0,2695,0,0,2698,0,2701,2706,0,0,0,2707,0,2709,2710,2711,0 +,0,0,2720,2730,2735,0,0,0,0,2738,2740,0,0,0,0,2747,0,0,0,0,0,0,2748,0,0,2749,0,0 +,0,0,0,2750,0,0,2752,2754,0,0,0,0,0,2758,0,0,0,0,2762,0,0,0,0,2763,0,0,0,0,0,0,0 +,2764,2767,0,0,0,0,2768,0,0,2770,0,0,0,0,0,0,0,2771,0,0,0,0,0,0,0,0,0,2772,0,0,0 +,0,0,2773,2776,0,0,2783,0,0,2784,0,2789,0,2790,0,0,0,2792,0,0,0,0,0,0,0,0,0,0, +2793,2795,0,0,0,0,0,0,2796,0,0,0,0,0,0,2797,2799,0,0,0,0,2803,0,0,0,0,2806,0, +2807,2808,2817,2819,0,0,0,0,0,2821,0,0,0,0,2822,2823,0,0,0,0,0,0,0,2824,0,0,2828 +,0,2834,0,0,0,0,0,0,2836,0,2838,0,0,2839,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2841, +0,0,0,2842,0,0,0,0,0,2843,2844,0,0,0,0,2846,0,0,2847,0,2849,0,2853,0,0,0,0,0, +2857,0,0,0,0,2858,0,2859,0,0,2860,0,2862,2868,0,0,0,0,2875,0,2876,0,0,2877,2878, +2884,2889,2890,0,0,2891,0,0,2892,0,0,0,2906,2912,0,2913,0,0,0,0,0,0,0,0,2916,0, +2934,0,0,0,0,0,2935,0,0,0,0,2939,0,2940,0,0,0,0,0,0,0,2941,0,0,0,2946,0,2949,0,0 +,2950,2954,2955,0,0,0,2959,2961,0,0,2962,0,2963,0,0,0,0,0,0,2964,2965,2966,2967, +0,0,0,0,0,0,0,2969,0,0,0,0,0,2970,2975,0,2982,2983,2984,0,0,0,0,0,2989,0,0,2990, +0,0,0,0,0,0,0,2991,0,0,0,0,0,0,0,0,2998,0,3000,3001,0,0,3002,0,0,0,3003,0,0,3012 +,0,0,3022,0,0,3024,0,0,3025,3027,0,0,0,3030,0,0,0,0,3034,3035,0,0,3036,0,3039,0, +3049,0,0,3050,0,0,0,0,0,0,3051,0,3053,0,0,0,0,3057,0,3058,0,0,0,0,0,0,0,0,3063,0 +,0,3073,3074,3078,3079,0,3080,3086,0,0,0,0,0,0,0,0,3087,0,3092,0,3095,0,3099,0,0 +,0,3100,0,3101,3102,0,3122,0,0,0,3124,0,3125,0,0,0,0,0,0,3132,3134,0,0,3136,0,0, +0,0,0,0,0,3147,0,0,3149,0,0,0,0,0,3150,3151,3152,0,0,0,0,3158,0,0,3160,0,0,3161, +0,0,3162,0,3163,3166,3168,0,0,3169,3170,0,0,3171,0,0,0,0,0,0,0,3182,0,3184,0,0, +3188,0,0,3194,0,0,0,0,0,0,3204,0,0,0,0,3209,0,0,0,0,0,0,0,0,0,0,0,3216,3217,0,0, +0,0,0,0,0,3219,0,0,3220,3222,0,3223,0,0,0,0,3224,0,3225,3226,0,3228,3233,0,3239, +3241,3242,0,0,3251,3252,3253,3255,0,0,0,0,0,0,0,0,3260,0,0,3261,0,0,0,3267,0,0,0 +,0,0,0,0,0,3271,0,0,0,3278,0,3282,0,0,0,3284,0,0,0,3285,3286,0,0,0,0,0,0,0,3287, +3292,0,0,0,0,3294,3296,0,0,3299,3300,3301,0,3302,0,0,0,0,0,3304,3306,0,0,0,0,0,0 +,3308,0,0,0,0,0,0,0,0,0,3311,0,0,0,0,0,0,0,0,3312,3314,3315,0,3318,0,0,0,0,0,0,0 +,0,3319,0,0,0,0,0,3321,0,0,0,0,0,0,0,0,0,3322,0,0,3324,3325,0,0,3326,0,0,3328, +3329,3331,0,0,3335,0,0,3337,0,3338,0,0,0,0,3343,3347,0,0,0,3348,0,0,3351,0,0,0,0 +,0,0,3354,0,0,0,0,0,0,0,0,0,0,3355,0,0,3365,3366,3367,0,0,0,0,0,0,3368,3369,0, +3370,0,0,3373,0,0,3376,0,0,3377,0,3379,3387,0,0,0,0,0,3390,0,0,0,0,0,0,0,3402,0, +3403,3436,3437,3439,0,0,3441,0,0,0,3442,0,0,3449,0,0,0,3450,0,0,0,0,0,0,0,3451,0 +,0,3452,0,3453,3456,0,3457,0,0,3458,0,3459,0,0,0,0,0,0,0,0,0,3460,0,0,3469,3470, +0,0,3475,0,0,0,3480,3487,3489,0,3490,0,0,3491,3499,0,3500,0,0,3501,0,0,0,3502,0, +3514,0,0,0,3516,3517,0,0,0,3518,0,0,0,0,3520,3521,3522,0,0,3526,3530,0,0,0,0, +3531,0,0,0,0,3536,0,0,0,0,0,0,0,3539,3541,0,0,3542,3544,0,3547,3548,0,0,3550,0, +3553,0,0,0,0,0,0,0,3554,0,3555,0,3558,0,3559,0,0,0,0,0,0,0,0,3563,0,3581,0,0,0, +3599,0,0,0,3600,0,3601,0,3602,3603,0,0,3606,3608,0,3610,3611,0,0,0,0,0,0,0,0,0, +3612,3616,3619,0,0,0,0,0,0,0,0,0,0,0,0,0,3624,3628,0,3629,3634,3635,0,0,0,0,0,0, +3636,0,3637,0,0,3638,3651,0,0,0,0,0,0,3652,3653,0,0,0,0,3656,3657,0,0,0,0,0,3658 +,0,0,0,0,3659,0,3661,3663,3664,0,3665,0,3692,0,0,0,3694,3696,0,0,0,0,0,0,0,0,0,0 +,0,0,3698,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3700,0,0,3701,0,0,0,3708,3709,0,0,0,3711 +,3712,0,0,0,0,0,3723,0,3724,3725,0,0,3726,0,0,0,0,0,0,3728,3729,0,3734,3735,3737 +,0,0,0,3743,0,3745,0,0,3746,0,0,3747,3748,0,3757,0,3759,3766,3767,0,3768,0,0,0,0 +,3769,0,0,3771,0,3774,0,0,0,0,0,0,3775,0,0,0,0,0,0,3776,0,3777,3786,0,3788,3789, +0,0,0,0,0,0,0,0,0,3791,0,3811,0,0,0,0,0,3814,3815,3816,3820,0,0,0,0,0,0,0,3821,0 +,0,3825,0,0,0,0,3835,0,0,3848,3849,0,0,0,0,3850,3851,3853,0,0,0,0,3859,0,3860, +3862,0,0,0,0,0,3863,0,0,0,0,0,0,0,0,3873,0,3874,0,3875,3886,0,3887,0,0,0,0,3892, +3913,0,3914,0,0,0,3925,3931,0,0,0,0,3934,3941,3942,0,0,0,0,3943,0,0,0,3944,0,0,0 +,0,0,3945,0,3947,0,0,0,3956,3957,0,0,0,0,0,0,0,0,0,3958,0,3959,3965,0,0,0,0,3966 +,0,0,0,3967,0,0,0,3968,3974,0,0,0,0,0,3975,3977,3978,0,0,0,0,3980,0,3985,0,0,0,0 +,0,0,0,0,3986,4011,0,0,4017,0,0,0,0,0,0,0,0,0,0,0,4018,0,0,0,0,4019,0,4023,0,0,0 +,4027,4028,0,0,0,0,0,0,0,0,4031,4034,0,0,4035,4037,4039,4040,0,0,0,0,0,4059,0, +4060,4061,0,4062,4063,4066,0,0,4072,0,0,0,0,0,0,0,0,0,0,0,0,0,4088,0,0,0,0,0, +4091,0,0,0,0,4094,4095,0,0,4096,0,0,0,0,0,4098,4099,0,0,0,4101,0,4104,0,0,0,4105 +,4108,0,4113,0,0,4115,4116,0,4126,0,0,4127,0,0,0,0,0,0,0,4128,4132,4133,0,4134,0 +,0,0,4137,0,0,4141,0,0,0,0,4144,4146,4147,0,0,0,0,4148,0,0,4311,0,0,0,4314,4329, +0,4331,4332,0,4333,0,4334,0,0,0,4335,0,4336,0,0,0,4337,0,0,0,4342,4345,4346,4350 +,0,4351,4352,0,4354,4355,0,0,4364,0,0,0,0,4369,0,0,0,4373,0,4374,0,0,0,0,4377,0, +0,0,0,4378,0,0,0,4380,0,0,0,4381,4382,0,0,0,0,0,0,0,4384,0,0,0,0,4385,0,0,0,4386 +,0,0,0,4391,4398,0,0,0,0,4407,4409,0,0,0,0,4410,0,0,4411,0,4414,4415,4418,0,4427 +,4428,4430,0,4431,0,4448,0,0,0,0,0,4449,0,0,0,4451,4452,0,4453,4454,0,4456,0,0,0 +,0,0,0,0,4459,0,4463,0,0,0,0,0,4466,0,4467,0,4469,0,0,0,0,0,0,0,0,0,0,0,0,0,4470 +,4471,0,4473,0,0,4475,0,0,0,0,4477,4478,0,0,0,4479,4481,0,4482,0,4484,0,0,0,0,0, +0,0,4486,0,0,4488,0,0,4497,0,4508,0,0,4510,4511,0,4520,4523,0,4524,0,4525,0,4527 +,0,0,4528,0,0,0,0,4530,0,4531,0,0,4532,0,0,0,4533,0,0,0,0,0,4535,0,0,0,4536,0,0, +0,0,0,4541,4543,4544,4545,4547,0,4548,0,0,0,0,4550,4551,0,4553,0,0,0,0,4562,0,0, +4571,0,0,0,4574,0,0,0,4575,0,4576,0,4577,0,0,0,4581,0,0,0,0,0,4582,0,0,4586,0,0, +0,4588,0,0,4597,0,4598,0,0,0,0,4616,4617,0,4618,0,0,0,0,4619,0,4620,0,0,4621,0, +4624,0,0,0,0,0,4625,0,0,0,0,4657,0,4659,0,4667,0,0,0,4668,4670,0,4672,0,0,0,0,0, +4673,4676,0,0,0,0,4687,0,0,0,0,4697,0,0,0,0,4699,0,4701,0,0,0,0,4702,0,0,4706,0, +0,4713,0,0,0,4714,4715,4716,0,0,0,0,0,0,0,0,0,0,0,0,4717,0,0,4720,0,4721,4729, +4735,0,0,0,4737,0,0,0,4739,0,0,0,4740,0,0,0,4741,0,0,0,0,0,4742,0,4745,4746,4747 +,0,0,0,0,0,0,0,0,4748,0,0,0,4749,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4751, +4786,0,4787,0,4788,4796,0,0,4797,4798,0,4799,4806,4807,0,0,0,0,4809,4810,0,0,0,0 +,0,0,4811,0,0,0,0,0,4812,0,4813,0,0,4815,0,4821,4822,0,0,0,0,4823,0,0,0,0,0,0,0, +0,0,0,4824,0,0,0,0,4826,0,0,0,4828,0,4829,0,0,0,4843,0,0,4847,0,4853,4855,4858,0 +,0,0,0,0,4859,0,4864,0,0,4879,0,0,0,0,4880,0,0,0,0,4881,0,4882,0,0,0,0,0,0,0,0,0 +,4883,0,0,0,0,4884,0,0,0,0,0,4886,4887,4888,4894,4896,0,4902,0,0,4905,0,0,4915,0 +,0,0,0,0,0,0,4916,4917,4919,4921,0,0,0,0,0,4926,0,0,0,0,4927,0,0,0,0,0,0,0,0, +4929,0,4930,4931,0,4938,0,4952,0,4953,4957,4960,4964,0,0,0,0,0,0,0,5019,5020, +5022,0,0,0,0,0,5023,0,0,0,5024,0,0,0,5025,0,0,0,0,5028,0,0,0,0,5029,5030,5031,0, +5033,0,0,0,0,0,0,0,0,0,5034,5035,0,5036,0,0,5037,0,0,0,0,5038,0,0,5039,0,0,0, +5041,5042,0,0,0,0,5044,5049,5054,0,5055,0,5057,0,0,0,5060,0,0,0,0,0,5063,0,5064, +5065,0,5067,0,0,0,5068,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5076,0,0,0,0,0,0, +0,5077,0,0,5078,5080,0,0,5083,0,0,0,0,0,0,0,0,5085,0,0,0,0,0,0,5098,5099,5101, +5105,5107,0,5108,0,5109,0,0,0,0,0,0,0,5110,0,0,0,0,0,5117,5118,0,5121,0,5122,0,0 +,5130,0,0,0,5137,0,0,0,5148,0,0,0,0,0,0,0,5151,5154,0,0,0,5155,0,0,5156,5159, +5161,0,0,0,0,5162,0,0,0,0,5163,5164,0,5166,0,0,0,0,0,0,0,0,0,0,5167,0,0,0,5172,0 +,0,0,0,0,0,5178,5179,0,0,5190,0,0,5191,5192,5194,0,0,5198,5201,0,0,0,0,0,5203,0, +5206,5209,0,0,0,0,0,0,5213,0,5214,5216,0,0,0,0,0,5217,0,0,0,0,0,0,0,0,5218,5219, +0,5231,0,0,5244,5249,0,5254,0,5255,0,0,5257,0,0,0,0,0,5258,0,5260,5270,0,5277,0, +0,0,0,0,0,5280,5281,5282,5283,0,0,0,0,0,5284,0,5285,0,0,0,0,0,5287,5288,0,0,0,0, +0,0,0,0,0,0,5289,5291,0,0,5294,0,0,5295,0,0,0,0,0,0,0,5304,0,0,5306,5307,5308,0, +5309,0,0,5310,0,0,0,0,5311,5312,0,5313,0,0,0,0,0,5316,0,0,0,5317,0,0,0,0,0,0,0,0 +,0,5325,0,0,0,0,0,0,5326,0,5327,5329,0,5332,0,0,0,0,5338,0,0,0,0,0,0,0,0,5340,0, +0,5341,0,0,0,5342,0,5343,5344,0,0,5345,0,0,0,0,0,0,5347,5348,0,0,0,0,0,0,0,0,0, +5349,0,5350,0,5354,0,0,0,0,5358,0,0,5359,0,0,5361,0,0,5365,0,5367,0,5373,0,0,0, +5379,0,0,0,5380,0,0,0,5382,0,5384,0,0,0,0,0,0,5385,0,0,0,0,5387,0,0,0,0,0,0,5388 +,5390,5393,0,0,0,0,0,0,0,0,0,0,0,5396,0,0,0,0,5397,5402,0,0,0,0,0,5403,0,0,0, +5404,5405,0,0,0,0,0,0,0,0,0,0,0,0,5406,0,0,0,0,5410,0,0,5411,0,5415,0,0,0,0,5416 +,5434,0,0,0,0,0,0,0,0,0,0,0,5438,0,5440,0,0,0,0,0,0,5441,5442,0,0,0,5443,5444, +5447,0,0,5448,5449,5451,0,0,0,5456,5457,0,0,0,5459,0,0,0,5461,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,5464,0,5466,0,0,5467,0,5470,0,0,5473,0,0,5474,0,0,5476,0,0,0,0,0,0,0,0 +,0,0,0,5477,0,0,0,0,0,0,0,5484,0,0,5485,5486,0,0,0,0,0,5488,0,0,0,0,0,0,0,5489,0 +,0,0,0,0,5507,0,0,0,5510,0,5511,0,0,5512,0,0,0,5513,0,5515,0,0,5516,5517,0,5518, +0,0,5522,0,0,0,0,0,5534,5535,0,0,5536,0,5538,0,0,5543,0,5544,0,0,5545,0,5547,0, +5557,0,0,5558,0,5560,5567,0,0,0,0,5568,0,0,0,5571,5573,0,5574,0,5575,0,0,0,0, +5577,0,0,5598,0,0,0,0,0,0,0,0,0,5600,5609,0,0,0,0,5610,0,0,5612,0,5624,0,5625,0, +0,0,5629,0,5641,0,5642,5643,0,0,0,0,0,0,5651,0,0,0,5652,5653,0,5661,5662,5678,0, +5679,0,0,0,0,5685,5686,0,0,0,0,0,5690,5692,0,5703,0,0,0,0,0,5706,0,0,0,0,5707,0, +0,0,0,0,0,5708,0,0,5709,0,5710,0,0,0,5712,0,5733,0,5734,5735,0,0,5744,5751,0,0,0 +,0,0,0,0,0,0,0,0,0,5752,0,5754,0,0,0,0,0,0,5757,5758,0,5760,5761,0,0,0,0,5763, +5764,5765,0,5766,0,5767,5768,0,5770,0,0,0,0,5776,5780,0,0,0,0,5782,0,0,0,0,5784, +0,0,5788,0,0,0,0,0,0,0,0,0,0,0,5797,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5799,0,0,5801, +0,0,0,5811,0,0,0,0,0,0,5816,0,0,5827,0,0,0,0,0,0,0,0,5830,5831,0,0,5832,0,0,5833 +,0,5835,5844,5845,0,5846,0,0,0,0,0,5850,0,0,0,0,0,5852,0,5855,5857,0,0,5859,0, +5861,0,0,5863,0,5865,0,0,0,5873,5875,0,0,0,5877,0,5879,0,0,0,5888,0,0,5889,5891, +0,5894,0,0,0,0,0,0,5895,0,5897,0,0,0,0,0,0,5907,0,5911,0,0,5912,0,5913,5922,5924 +,0,5927,5928,0,0,0,0,5929,5930,0,5933,0,0,0,0,5949,0,0,5951,0,0,0,0,0,0,0,0,5953 +,0,0,5954,0,5959,5960,5961,0,5964,0,0,0,5976,5978,5987,5990,0,0,0,0,0,5991,0, +5992,0,0,0,5994,5995,0,0,5996,0,0,6001,6003,0,0,0,0,6007,0,0,0,0,0,6008,0,0,6009 +,0,6010,0,0,0,6011,6015,0,6017,0,6019,0,6023,0,0,0,0,0,0,0,6025,0,0,0,0,0,0,0,0, +0,0,6026,0,6030,0,0,6032,0,0,0,6033,6038,6040,0,0,0,6041,6045,0,0,6046,0,0,6053, +0,0,6054,0,6055,0,0,0,0,0,0,6057,0,6063,0,0,0,6064,0,6066,6071,6072,0,0,0,0,0,0, +6075,6076,0,0,6077,0,0,0,0,0,0,0,0,0,6078,6079,0,0,0,0,0,0,0,0,6080,0,6083,0,0,0 +,0,0,6084,0,0,6088,0,6089,0,0,6093,6105,0,0,6107,0,6110,0,0,0,6111,6125,6126,0,0 +,0,6129,0,0,0,0,6130,0,0,0,6131,6134,0,0,0,0,0,0,6142,0,0,0,0,0,6144,0,0,6146, +6151,6153,0,6156,0,6163,0,6180,6181,0,0,0,0,0,6182,0,0,0,0,6184,6195,0,0,6206,0, +6208,0,0,6212,6213,6214,0,6215,0,0,0,6228,0,0,0,6234,0,0,0,0,0,0,6235,6240,0, +6242,6243,6244,0,6250,6255,0,0,0,0,0,6257,0,0,0,6258,6278,0,6284,0,0,0,6285,0,0, +0,0,0,0,0,0,6286,0,0,0,6320,0,0,6322,6332,0,0,0,0,0,0,0,0,6334,0,0,0,0,0,0,0, +6335,0,0,6337,0,6338,0,6339,6340,0,0,6356,6357,6369,0,0,0,6370,6371,6372,0,6373, +0,0,0,0,0,6376,0,0,0,0,0,6382,6383,6384,0,0,0,0,6386,0,6389,6397,6400,6411,0, +6414,0,0,0,0,0,0,0,6415,6416,0,0,0,0,0,0,6417,0,0,0,0,6418,0,0,0,0,0,0,0,6420,0, +6421,6423,6425,0,6429,6430,0,6433,6438,0,0,0,0,0,0,0,0,0,0,6439,6440,0,0,6441,0, +0,6444,0,0,0,0,6446,0,0,0,0,6447,6448,0,0,6450,0,0,0,6454,0,0,6455,0,6461,0,0,0, +0,0,0,6462,0,0,6463,0,6464,0,6465,6467,0,0,0,6468,0,6479,6480,0,0,0,0,0,0,0,6481 +,0,0,6485,6487,0,0,0,0,0,0,6493,0,0,0,0,0,0,0,0,6494,6495,6496,0,0,0,0,0,6498,0, +0,0,6507,6508,0,0,0,0,0,0,0,0,0,0,6511,6512,0,0,0,0,6513,0,0,0,6514,0,0,0,0,0, +6516,0,0,6517,6518,0,0,0,6519,6520,6521,0,6523,0,0,0,0,6524,6528,0,6530,0,0,6532 +,0,6578,0,0,0,6583,0,6584,0,0,0,6587,0,0,0,6590,0,6591,0,0,0,0,0,6592,0,0,0,0, +6593,6594,0,0,0,0,0,6599,6600,0,0,6601,6602,6604,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +6608,0,0,0,0,0,0,0,0,6610,6611,0,6615,0,6616,6618,6620,0,6637,0,0,0,0,6639,0,0,0 +,0,6641,0,6642,0,0,0,6647,0,6660,6663,0,6664,0,6666,6669,0,6675,6676,6677,0,0,0, +0,0,0,0,0,0,6678,0,0,0,6679,0,6680,0,0,0,0,0,0,0,6693,0,0,0,0,0,0,0,0,0,6704, +6705,6706,0,0,6711,6713,0,0,0,0,0,6716,0,0,0,6717,0,6719,6724,0,0,0,0,0,0,0,0, +6725,6726,0,0,0,0,0,6728,6729,6735,0,6737,6742,0,0,6743,6750,0,6751,0,0,6752, +6753,0,0,0,0,0,0,6754,0,0,0,0,0,6756,0,0,0,0,0,0,6763,0,0,6764,6765,0,0,0,6770,0 +,0,0,6776,6780,0,6781,0,0,0,6783,0,6784,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +6785,0,0,0,6792,0,0,0,6793,0,0,6802,0,0,0,0,0,6803,0,0,0,6804,0,0,0,6812,0,0, +6823,0,6824,6839,0,0,0,0,6852,0,0,6854,0,6856,6857,0,0,0,0,0,0,0,0,0,6867,0,6868 +,6870,6872,0,0,0,6873,6874,0,0,0,0,0,6875,0,0,6877,0,0,0,0,0,0,0,6878,0,0,0,6879 +,0,6880,0,0,0,0,0,0,0,0,0,0,6887,0,6888,6891,6893,0,6895,0,0,0,0,0,0,0,0,6899,0, +0,0,0,6901,0,0,0,0,6910,0,6911,0,0,6912,0,0,6913,6914,0,0,0,6915,0,0,0,6916,6919 +,0,0,0,0,0,0,6924,0,6925,0,0,0,6926,6927,6928,0,6929,0,6930,0,0,6931,6935,0,6936 +,0,0,0,0,6939,6940,6941,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6942,6948,6949,0,0,0,0,0,0 +,0,6952,6954,6963,6965,6966,0,0,6967,6968,0,0,0,0,0,0,0,0,0,6969,0,0,6970,6979,0 +,0,6980,0,0,6983,0,0,0,0,0,6984,0,0,0,0,0,0,0,6988,6990,6992,0,0,0,0,0,0,0,6995, +0,0,0,7012,0,0,0,0,0,0,0,0,0,7019,0,0,0,0,0,0,0,0,7021,0,0,7022,7023,7028,0,7030 +,7033,0,0,0,0,0,0,7038,0,0,0,0,0,0,0,0,0,0,7039,0,0,0,0,0,7046,0,7047,0,0,0,0,0, +0,0,0,0,0,0,7048,7052,0,0,0,0,0,7054,0,7060,0,0,0,0,7061,0,7065,0,0,0,0,7067, +7069,0,7070,7071,7072,0,0,7078,0,7080,7081,0,7083,0,0,0,7084,7087,7088,0,0,7090, +0,7093,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7107,0,0,7108,0,0,0,0,0,0,0,0,7110,0,7114,0 +,0,0,0,0,0,0,7115,0,7116,0,0,0,0,0,7117,0,0,7118,0,0,7124,0,7125,0,0,7126,0,0,0, +0,7128,0,0,0,0,0,7129,0,7130,0,7132,7133,0,0,7134,0,0,7139,0,7148,7150,0,0,0,0, +7152,0,0,0,7153,7156,7157,0,0,0,0,0,7158,0,0,0,0,0,0,0,0,0,0,7163,7165,7169,0, +7171,0,0,0,0,0,0,0,0,0,7172,0,7173,7181,0,0,0,0,0,7182,7185,0,0,0,0,7187,0,7201, +7204,0,0,0,0,0,7206,7207,0,0,0,0,7211,7216,0,7218,0,0,0,0,7226,7228,7230,7232, +7233,7235,7237,0,0,0,0,7238,7241,0,7242,0,0,7247,0,0,0,7266,0,0,0,0,0,0,0,7289,0 +,0,7290,7291,0,0,7292,0,7297,0,0,0,0,0,0,0,0,0,0,7300,0,7301,0,0,0,0,0,0,0,0,0,0 +,0,0,7302,0,0,0,0,7305,0,0,0,0,7307,0,7308,0,7310,0,7335,0,0,0,0,0,0,0,7337,0, +7343,7347,0,0,0,0,0,7348,0,7349,7350,7352,7354,0,0,0,0,7357,0,7358,7366,0,7367, +7368,0,0,7373,0,0,0,7374,0,0,0,0,0,0,0,7376,0,0,0,7377,0,0,0,0,0,7378,0,7379, +7380,0,0,0,0,0,7383,0,0,7386,0,0,0,0,7398,0,0,0,7399,7400,0,7401,0,0,0,0,0,0,0, +7402,0,0,0,0,0,7405,0,0,0,0,0,7406,0,0,0,0,0,0,0,0,7421,7427,7429,0,0,0,7435,0,0 +,7436,0,0,0,7437,0,0,0,0,0,0,7438,7443,0,7446,0,7448,0,0,0,0,0,0,0,0,0,0,7456,0, +0,0,0,0,7457,0,0,7461,0,0,0,0,0,7462,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7463,7466,7472, +0,7476,0,0,7490,0,7491,0,0,7493,0,0,0,7498,7499,0,0,7508,0,0,0,0,0,7512,0,0,0, +7513,7514,7516,0,0,0,0,7518,0,0,7519,7521,7522,0,0,0,7526,0,0,7529,0,0,7531,0, +7536,0,7538,0,7539,0,0,7541,7542,7546,0,0,0,0,0,7547,0,7548,0,0,0,0,0,7550,0,0, +7552,7553,0,0,0,0,0,0,0,0,0,0,7554,7563,0,7573,0,0,0,0,0,0,7574,7576,0,7578,7581 +,7583,0,0,0,7584,0,7587,0,0,0,0,0,7589,0,0,0,7594,0,0,7595,0,0,7600,7602,7610,0, +0,0,0,0,7612,0,7613,7614,0,0,7615,0,0,7616,0,7620,0,7621,7622,0,7623,0,0,0,0, +7626,0,0,0,0,7627,7629,7631,0,0,7633,0,0,0,0,0,7639,0,7640,7642,0,0,7643,0,0,0,0 +,7644,0,0,0,0,0,0,0,7645,0,0,0,0,0,7661,7662,7663,7665,0,7666,0,7667,0,7684,7688 +,7690,0,7691,0,0,0,0,0,0,7692,0,0,7700,0,7707,0,7708,0,7709,0,7721,0,0,0,7722,0, +7724,0,0,0,0,0,0,7729,7731,0,7732,0,7733,7735,0,0,0,0,0,0,0,7739,0,0,7741,7745,0 +,7748,0,0,0,7751,0,0,0,7752,0,0,0,0,0,0,0,7753,0,0,7756,0,7757,0,7759,0,7760,0,0 +,0,0,7761,7768,0,0,7769,0,0,7770,0,0,7771,0,0,7772,0,0,7773,0,0,0,0,0,7778,7783, +0,0,0,0,0,7784,7785,0,7790,0,0,0,0,7792,0,7798,0,0,0,0,0,7799,0,7810,0,0,7813,0, +7814,0,7816,0,7818,7824,7825,7826,0,7828,7830,0,0,0,7840,0,7842,0,7843,0,0,0,0, +7844,0,0,0,0,0,0,0,7846,0,0,0,0,0,7856,7857,7858,7862,0,7865,0,0,7866,0,0,7913,0 +,0,0,0,7914,0,0,7915,7917,7918,7919,0,7920,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7921, +7922,0,7924,0,0,7925,0,0,7927,0,7930,7935,0,0,7937,0,0,0,0,0,0,7939,0,7940,0,0,0 +,0,0,7941,0,0,0,0,7945,0,0,0,0,7949,0,0,0,0,0,0,0,0,7950,0,7953,0,0,0,0,0,0,0, +7968,0,0,0,0,7969,7972,7992,0,7993,0,0,0,0,0,0,0,0,0,0,0,7994,0,0,0,0,8007,8008, +0,0,0,0,0,0,0,0,0,0,0,0,8010,0,0,0,8012,0,0,0,0,0,0,0,0,8018,0,8028,8029,0,0, +8030,0,0,8032,8033,0,0,8034,8036,0,0,0,0,0,0,0,0,0,0,8037,0,0,0,8043,8052,8059, +8060,0,0,8061,0,0,0,8062,0,8063,0,8064,0,8066,8068,0,0,0,8080,8081,0,8089,0,0,0, +0,0,8092,0,0,0,0,0,0,8093,8110,0,0,0,0,0,0,0,8111,0,0,0,0,0,8112,8115,0,8117,0,0 +,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8120,8121,8122,8128,8129,8130,8131,0,0,8139,0,0, +8144,0,0,0,0,8145,8146,8153,0,0,0,0,0,0,0,0,8154,0,8157,8160,8162,0,8164,8165,0, +0,0,0,8166,8167,0,0,8179,0,0,0,8185,0,0,0,8186,0,0,8187,0,0,0,8188,0,0,0,0,0, +8204,0,0,0,0,8210,0,0,0,0,0,8213,0,8214,0,0,8215,0,0,0,0,0,0,8218,0,0,0,0,0,0,0, +0,0,8219,0,8221,0,0,8222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8225,0,0,0,8233,0,0, +8242,0,0,0,0,0,0,0,0,0,0,0,8247,0,8248,8252,0,8256,8257,0,0,8261,0,8264,8265,0,0 +,0,0,8267,0,0,0,8269,0,0,0,0,0,0,0,0,0,8270,0,0,0,8278,0,8279,8283,0,0,8285,8286 +,8289,8292,0,0,0,0,8293,8295,8299,8300,8301,0,0,0,0,0,0,8304,8307,0,0,0,0,0,0,0, +8321,0,0,0,8322,8323,8325,8326,8327,0,0,8332,8338,0,0,8340,0,0,0,0,0,8350,0,0, +8351,0,8354,8355,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8360,8372,0,0,0,0,0,0,0,0,8377,0,0, +0,0,8380,0,0,0,8383,0,8384,0,0,0,0,8386,8392,0,0,8394,0,0,0,0,0,0,0,8396,8397,0, +8398,0,8399,0,0,0,0,0,8400,0,8401,8410,8411,0,8412,8413,8422,0,0,0,0,8423,0,0,0, +0,8424,0,0,8425,0,0,0,0,0,0,0,8441,8442,0,0,0,0,0,0,8443,0,0,8444,0,8447,0,0,0,0 +,8451,0,8458,0,8462,0,0,8468,0,8469,0,0,0,8470,0,8473,8479,8480,0,0,0,0,8481, +8483,0,0,0,0,0,0,0,0,0,8484,0,0,8490,0,0,0,0,0,0,8491,8493,8494,0,8528,0,0,0,0,0 +,0,0,8530,0,0,0,0,0,0,0,0,8534,8538,8540,0,0,8541,0,0,8545,0,8557,0,0,8569,8570, +0,0,8571,8574,8575,8579,0,8583,0,0,0,0,8591,0,0,0,0,0,0,0,0,8606,0,8607,0,0,0,0, +0,0,0,0,0,8608,0,0,8609,0,0,0,8610,0,0,0,8611,0,0,8613,8617,8621,0,0,8622,0,8623 +,0,8624,8625,0,0,0,0,0,0,0,0,0,8637,8638,8639,8650,0,0,0,0,8652,8654,8655,0,0,0, +0,0,0,0,0,0,0,8656,0,0,0,0,0,8657,0,0,0,0,0,0,0,0,0,8658,0,0,8659,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,8660,0,0,0,0,0,0,8661,8663,8664,0,0,0,0,8665,0,8669,0, +0,0,0,0,0,0,8671,8674,0,8684,0,8686,0,0,0,8689,0,0,0,8690,0,8706,0,0,0,0,0,0,0,0 +,0,0,0,8710,0,8711,8713,8714,8724,8727,8728,8733,8736,0,8737,8739,0,0,0,0,8742, +8743,8745,8754,0,0,0,0,8756,0,0,0,0,0,0,8757,8760,0,0,0,0,0,8762,8763,8764,0, +8766,8769,8770,8773,0,8774,0,8779,0,0,0,0,8780,0,0,8781,0,0,8783,0,0,0,0,0,0,0,0 +,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8784,0,0,0,0,0,0,0,0,8785,0,0,0,0,8786,0,0,0,0,8788 +,8790,0,0,0,8803,0,8813,8814,0,0,0,0,0,8815,8816,0,0,0,0,8818,0,0,0,0,8822,8828, +8829,0,8831,0,0,0,0,8833,0,0,0,8834,0,0,0,8835,0,8836,0,0,0,8837,0,0,0,0,0,0, +8838,8839,0,0,0,0,0,0,0,0,0,0,0,8840,0,0,0,8841,0,8842,0,0,0,8846,0,0,0,0,0,0,0, +8847,0,8848,0,0,8864,0,0,8866,0,0,8870,8872,0,0,8873,8874,0,0,0,0,0,0,8875,0, +8876,0,0,0,0,8896,8900,0,0,0,0,8901,0,0,0,0,0,8904,0,8907,0,0,0,0,8911,8912,8913 +,0,0,0,8914,0,8915,0,0,0,0,0,0,0,0,0,0,0,0,8916,0,0,0,8929,0,0,0,0,0,0,0,0,0,0, +8930,0,8932,0,8943,0,0,0,8945,8947,0,0,0,0,8949,0,8950,0,8954,8957,0,0,8970,0,0, +0,0,8971,0,8996,0,0,0,0,8997,9000,0,0,0,0,9001,9002,0,9004,9009,9024,0,0,0,0,0,0 +,0,0,0,0,0,0,9027,9082,0,0,9083,9089,0,0,0,0,0,0,9090,0,0,0,9092,0,0,9093,0,9095 +,0,0,9096,9097,9101,9102,0,0,0,0,0,0,0,0,9112,0,0,0,0,0,0,9114,0,0,9120,0,9121, +9122,0,0,0,9123,9124,0,0,9125,0,0,9126,0,9127,0,0,9129,9131,0,0,0,9132,0,0,9136, +0,9144,0,0,9148,0,0,0,0,0,0,9149,0,9152,9163,0,0,9165,0,0,0,0,0,0,0,0,0,0,0,0,0, +9166,0,9169,0,0,0,0,0,0,0,9170,0,0,0,0,9172,0,9174,9175,9176,0,9177,0,0,0,0,0,0, +0,0,9186,0,9187,0,0,0,9188,9189,0,0,9190,0,0,0,0,9191,0,0,0,9193,0,0,0,0,9197, +9198,0,0,0,9208,9211,0,0,0,0,9216,9217,0,9220,0,0,0,0,9221,9222,9223,0,9224,9225 +,0,0,9227,0,9228,9229,0,0,9230,0,9232,0,9233,0,0,0,0,0,9234,9235,0,0,9237,0,0,0, +0,0,0,0,0,9238,9240,0,0,9241,0,0,0,0,9244,0,0,0,0,9247,0,0,0,0,0,0,0,0,0,0,9248, +0,0,0,9249,0,0,0,0,0,9250,0,0,0,0,9251,0,0,9252,9255,0,0,0,9256,0,0,0,0,0,0,0, +9257,0,0,9258,0,0,0,0,0,0,9259,0,0,0,0,0,9262,9263,0,0,9265,9266,0,0,0,0,0,0,0,0 +,9268,9271,0,0,0,0,0,0,0,0,0,9273,0,0,0,9276,9277,9279,0,0,0,0,0,0,0,9280,0,0, +9293,0,0,0,0,0,9297,9301,0,0,0,0,0,0,0,0,0,0,0,9308,9309,9313,9321,9322,0,9326, +9327,0,0,9477,0,9479,0,0,0,0,9482,0,0,0,9483,0,9484,0,0,0,0,0,0,0,0,0,9485,0,0, +9486,0,0,0,9489,0,0,0,0,9490,9491,0,0,0,0,9493,0,9495,9496,0,0,0,0,0,0,0,0,9500, +0,9502,0,0,0,0,0,9504,9507,0,9509,0,9511,0,0,9513,0,0,0,0,0,0,0,0,9515,0,0,0,0,0 +,0,9516,9517,0,0,0,0,9532,0,0,9533,0,0,9538,0,9539,9540,0,0,0,0,9541,0,0,0,9542, +0,0,0,0,0,0,0,0,9544,9545,0,9546,0,0,0,0,0,0,9547,9548,0,0,0,9550,0,9557,0,9558, +0,9561,0,9563,9570,0,9572,9574,9575,0,0,0,9577,9592,0,0,9596,0,0,0,9598,0,9600,0 +,9601,0,0,0,0,0,0,9608,0,9638,9639,0,0,0,0,0,0,0,9641,0,0,9643,9644,9645,9646,0, +0,0,9648,0,0,0,0,0,0,0,9650,9654,0,0,0,0,0,0,0,0,9655,0,0,0,0,0,9656,0,9657,0,0, +0,0,9658,0,0,9659,0,0,9664,0,0,9665,0,9667,9669,0,0,0,0,0,0,0,0,0,0,0,0,9671,0, +9673,9681,0,0,0,0,9682,9683,9684,0,0,0,0,9686,9698,0,0,9700,9701,9702,0,9703, +9717,0,0,0,0,9718,0,9726,0,0,0,0,9727,0,0,0,9728,0,9742,0,9744,0,0,0,9750,0,9754 +,9755,0,0,0,0,0,9756,0,9757,9768,0,9769,0,0,0,9770,9771,0,9773,0,9774,0,9775,0,0 +,0,9776,9777,9784,0,0,0,9786,0,9789,0,0,0,0,9793,9794,0,0,0,9808,0,0,0,0,0,9811, +0,0,0,0,0,0,0,0,0,0,0,0,9812,0,9820,0,9823,0,9828,0,0,0,0,9830,0,0,9833,9836,0,0 +,0,9840,0,0,0,9841,0,0,9842,0,9845,0,0,0,9847,9848,0,0,9855,0,0,0,0,0,0,9856, +9863,9865,0,0,0,0,0,0,0,0,9866,9867,9868,9873,9875,0,0,0,0,0,0,9880,0,9886,0,0,0 +,9887,0,0,9891,0,0,0,0,0,0,0,9906,9907,9908,0,0,0,9909,0,0,0,0,0,0,9910,0,0,0,0, +9913,0,0,0,0,9914,0,0,0,0,0,9922,0,0,0,0,9923,9925,0,0,0,0,0,0,9930,0,0,0,9931,0 +,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9932,0,9939,0,0,9940,9962,9966,0,9969,9970,0,0,9974 +,0,9979,9981,9982,0,0,0,9985,0,0,0,0,0,0,9987,0,0,0,0,0,0,0,9988,9993,0,0,9994,0 +,0,0,9997,0,10004,0,0,0,0,0,10007,10019,10020,10022,0,0,0,10031,0,0,0,0,0,10032, +0,0,10034,0,10036,0,0,0,0,10038,0,10039,10040,10041,10042,0,0,0,0,0,10043,0,0,0, +0,0,10045,10054,0,0,0,0,10055,0,0,10057,10058,0,0,0,0,0,0,10059,0,0,0,0,0,0,0, +10060,0,0,0,0,0,0,0,10063,0,10066,0,0,0,10070,0,10072,0,0,10076,10077,0,0,10084, +0,10087,10090,10091,0,0,0,10094,10097,0,0,0,0,0,0,10098,0,0,0,0,0,0,10103,0, +10104,0,10108,0,0,0,0,0,0,0,0,10120,0,0,0,10122,0,0,10125,0,0,0,0,10127,10128,0, +0,10134,0,10135,10136,0,10137,0,0,10147,0,10149,10150,0,0,10156,0,10158,10159, +10160,10168,0,0,10171,0,10173,0,0,0,10176,0,0,0,0,10177,0,0,0,0,10178,0,0,0,0, +10194,0,10202,0,0,10203,10204,0,10205,10206,0,10207,0,0,0,0,10209,0,0,0,0,0,0,0, +10213,0,0,0,0,0,0,10217,0,10229,0,10230,10231,0,0,10232,0,0,10237,10238,10244,0, +0,0,0,0,10250,0,10252,0,0,0,0,0,0,10255,0,0,10257,0,0,0,0,0,0,10258,0,10259,0,0, +0,0,0,0,0,0,10260,0,0,0,0,0,0,0,10284,10288,10289,0,0,0,10290,0,10296,0,0,0,0,0, +10297,0,0,0,0,0,0,10298,0,0,0,0,10299,10303,0,0,0,0,0,10306,0,0,0,10307,0,10308, +0,0,0,0,10311,0,0,0,0,0,0,0,10315,10317,0,0,0,10318,10319,0,10321,0,10326,0, +10328,0,0,0,0,10329,0,0,10331,0,10332,0,0,0,0,0,0,10334,0,0,10335,10338,0,0,0,0, +0,10339,10349,0,0,0,0,0,0,10351,0,10353,0,0,0,0,0,0,10362,0,10368,0,10369,0,0,0, +10372,10373,0,0,0,0,0,10374,0,0,0,10375,0,10376,0,0,10386,10388,10390,0,0,0,0,0, +0,0,10391,0,0,10392,10394,0,0,10396,0,10397,0,10403,0,0,0,0,0,0,0,0,10404,0, +10405,10410,0,0,10411,0,10412,0,0,0,0,0,0,0,10421,10422,10423,0,0,0,0,0,0,0,0,0, +10425,0,0,10427,0,0,10430,0,0,0,0,0,10432,0,10433,10434,0,0,0,0,10436,10437,0, +10438,0,10439,0,10444,10446,0,0,0,0,0,10448,0,0,0,0,0,10449,0,0,0,0,0,0,0,10451, +0,10453,0,0,0,10454,10457,0,0,10459,0,10469,0,0,0,0,0,10472,10481,0,0,0,0,0, +10482,10483,0,10492,0,0,0,0,0,0,0,0,0,0,10499,0,0,0,10502,0,0,10510,0,10521, +10524,0,0,10525,10526,10528,0,0,0,0,0,0,0,0,10530,0,0,0,0,10533,0,10534,0,0,0,0, +0,0,0,0,0,0,10535,10536,0,0,10544,0,10553,10556,0,10557,10559,0,0,0,0,0,10562, +10563,10564,0,10565,0,0,0,10566,0,10567,0,0,0,0,10575,0,0,10576,0,10578,0,0,0,0, +0,0,0,0,0,0,10585,10586,10587,10589,0,10590,0,0,10594,0,0,0,0,0,10598,0,0,10601, +0,0,0,10602,0,10603,0,10604,0,10605,0,0,10607,0,10626,0,10627,0,0,0,0,0,10629, +10630,10631,0,0,0,10646,0,0,0,10647,0,10650,0,10651,0,0,0,10652,10653,10655,0, +10658,0,0,10659,0,10667,0,0,0,0,10669,0,0,0,0,0,0,0,0,0,10670,0,0,0,10671,0,0,0, +0,10672,10673,0,10674,0,0,0,10676,0,0,0,0,0,0,10678,0,10682,0,0,10692,0,10697,0, +0,0,0,10698,0,0,0,10700,0,0,0,0,0,10703,0,10704,0,0,0,0,0,0,0,10705,0,10715, +10718,10720,0,0,10722,0,0,0,0,0,0,0,0,10723,0,0,0,0,10726,0,0,0,0,0,10727,10730, +10743,0,0,0,0,0,0,10744,0,0,10745,0,0,0,0,0,0,10748,0,0,0,0,10750,0,0,10752, +10753,0,0,0,10756,0,0,0,0,0,0,10758,0,0,0,10759,0,10769,0,0,10772,0,0,0,0,0,0, +10773,0,0,0,10777,0,0,10779,0,0,0,0,0,0,0,0,10780,10784,0,0,0,10789,0,0,0,10791, +0,0,0,0,0,0,0,0,0,10795,0,0,10796,0,10808,0,10809,0,0,0,10810,0,0,0,10812,0,0, +10814,0,0,0,0,0,0,0,0,0,10815,0,0,0,0,10816,10817,0,0,0,0,10819,0,10820,0,0,0,0, +10821,10822,10823,0,10826,10849,0,0,0,0,10850,0,0,10852,0,10853,0,0,10856,0,0, +10857,10858,10859,10860,0,0,0,0,0,0,10863,0,10866,10867,10872,10890,0,0,10891, +10892,0,0,0,0,0,10893,0,0,0,10896,10899,0,0,10900,10902,0,0,0,0,0,10903,0,0,0,0, +0,0,0,0,0,0,0,0,10905,0,10906,0,0,0,0,10908,10911,0,10912,0,0,10916,0,0,0,0,0, +10917,0,10918,0,0,0,10923,0,0,0,0,0,10924,0,0,10928,10929,0,0,10930,0,0,0,10932, +0,0,0,0,10939,0,0,10945,0,0,0,10947,0,0,10948,0,0,0,0,0,0,0,0,0,0,0,0,10958,0, +10960,10962,0,0,10964,0,0,0,10966,0,0,0,0,0,0,0,0,0,0,10967,0,0,0,10968,0,0,0, +10973,0,0,0,0,0,10975,0,0,0,10976,10978,0,0,10982,10984,10987,0,0,10988,0,10989, +0,0,10991,0,0,0,0,10992,0,0,0,10993,0,10995,0,0,0,10996,10997,0,0,0,10998,0, +10999,0,11001,0,0,0,0,0,0,11010,11012,0,11013,11016,11017,0,0,11019,11020,11021, +0,0,0,0,0,0,0,0,0,0,0,0,11022,0,0,11023,11029,0,0,0,0,11031,0,0,0,11034,0,0,0,0, +11055,0,0,0,0,0,11056,11060,0,0,0,0,0,0,11061,0,0,11064,11065,0,11066,0,11069,0, +11085,0,0,0,0,0,11086,0,0,0,11088,0,0,0,11094,0,0,0,11095,11096,0,0,0,0,0,0, +11097,11098,0,0,0,0,0,0,11099,0,0,11102,11108,0,0,0,11109,0,11114,11119,0,11131, +0,0,0,11142,0,0,11143,0,11146,0,11147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11148,0, +11149,11152,11153,11154,0,11156,0,11157,0,0,0,11158,0,0,11159,11160,0,0,0,0,0,0, +0,0,0,0,0,0,11163,0,0,11164,11166,0,0,0,11172,11174,0,0,0,11176,0,0,0,0,0,11182, +11183,0,0,0,11184,11187,0,0,11188,11189,0,0,0,0,0,0,11194,0,0,0,0,0,0,0,11200, +11202,0,0,0,0,0,0,11203,0,11204,0,0,0,0,0,11205,0,0,0,11206,0,11207,0,0,11209,0, +11211,0,11214,0,0,11231,0,0,0,11293,11295,0,0,11296,11297,11302,0,0,0,11307,0,0, +0,0,11309,11310,0,11311,0,0,0,11313,0,11314,0,0,0,0,11334,0,11338,0,0,0,11339,0, +0,0,0,0,11340,0,11341,11342,0,11344,0,11345,0,0,0,11348,11349,0,0,11350,0,0,0, +11355,0,0,0,0,0,0,11356,0,11357,11370,0,0,11371,0,11374,11376,0,0,0,11377,0,0, +11378,11383,0,11386,11399,0,11400,11406,0,0,0,11408,0,0,11409,11412,0,0,0,0, +11417,0,0,0,11418,0,11421,0,11426,11429,0,0,0,0,0,11430,0,11437,0,11438,0,0,0,0, +0,11440,11453,0,0,0,0,0,0,11454,0,0,0,0,11455,0,0,11456,11460,11461,11463,0, +11469,0,11473,0,0,0,0,11474,0,0,0,11475,0,11476,11477,11480,0,0,0,0,11481,0,0, +11484,0,0,11487,0,0,0,0,0,0,0,0,0,0,11497,0,0,11502,0,11509,0,0,11510,11511, +11513,0,0,0,0,0,0,0,0,0,0,11515,0,0,0,0,11516,0,11520,11521,0,0,0,0,0,0,0,0,0,0, +0,11529,11530,11531,11534,0,0,11543,0,0,0,0,0,11547,0,11548,0,0,0,0,0,11552, +11556,0,11557,0,0,11559,0,11560,0,0,0,0,0,0,11561,0,0,11563,11564,0,11565,0,0,0, +0,11567,0,0,0,11569,0,11574,0,11575,0,0,0,11577,0,11578,0,0,0,11580,11581,0,0,0, +11582,11584,0,0,0,0,0,0,0,11587,0,11588,11591,0,11595,0,0,0,0,0,0,0,0,11596,0, +11597,0,0,0,0,11598,11601,0,0,0,11602,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11603, +11604,0,11606,0,0,11608,0,0,0,0,11610,0,0,11611,0,0,0,0,11613,0,11622,0,0,0, +11623,0,0,0,0,11625,0,0,11626,11627,11628,11630,0,0,0,0,0,0,11639,0,0,11646,0, +11648,11649,0,11650,0,0,0,0,0,0,0,0,0,11651,0,0,11652,11653,11656,0,0,11677, +11679,0,0,0,0,11680,0,0,11681,0,11685,0,0,0,0,0,0,0,0,11688,0,0,0,11716,0,11719, +0,0,0,0,0,11721,0,0,11724,11743,0,0,0,0,0,0,0,0,11745,11748,11750,0,0,0,0,0, +11751,0,0,0,11752,11754,0,11755,0,0,0,0,0,0,0,11759,0,0,0,0,0,0,11760,0,0,0, +11761,0,0,0,0,0,0,11766,11767,0,11772,11773,0,11774,0,0,11775,0,11777,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,11778,11780,0,0,0,0,0,0,0,11783,0,11784,0,0,0,11785, +0,0,0,11786,0,0,0,0,11788,0,0,11789,11791,11792,0,0,0,0,11795,11834,11835,11836, +0,0,11837,0,0,0,11838,0,0,11846,11851,0,11852,0,11869,0,0,0,11871,0,0,0,11872, +11874,0,0,0,0,0,0,11875,0,11876,11877,0,0,0,0,0,0,0,0,0,0,11883,0,0,0,0,0,0,0, +11884,0,11885,0,11886,0,0,11887,0,11894,11895,11897,11909,11910,0,11912,11918,0, +0,11920,0,11922,11924,11927,11928,0,0,0,0,11929,0,11934,0,0,0,0,0,11941,11943, +11944,0,11945,0,0,0,0,11948,11949,0,0,0,0,11953,0,11954,0,11955,0,11956,0,0,0,0, +0,11957,0,0,11959,0,0,0,0,0,0,0,0,11961,0,0,0,0,0,11978,0,0,0,11979,11980,11986, +11987,0,11992,0,0,0,0,0,11993,0,0,0,11994,0,11999,12004,12005,12006,0,0,0,0,0, +12011,0,0,12012,12014,0,0,12015,0,0,12019,12028,0,0,12029,0,0,12032,12033,0,0,0, +0,12034,0,12041,12043,0,0,12044,0,0,0,0,0,0,0,12046,0,0,0,0,0,0,0,12054,12055,0, +12056,0,0,0,12060,12064,0,0,0,0,0,12065,12067,12068,0,0,0,0,0,0,0,0,12074,0,0,0, +12075,12076,0,0,0,12079,0,12081,12086,12087,0,0,12088,0,0,0,0,12089,0,12092,0,0, +0,0,12097,0,0,0,0,0,0,0,0,12098,0,0,0,0,0,0,0,0,0,0,0,0,0,12102,12103,12104, +12111,0,0,12114,12116,0,0,0,12118,0,0,0,12119,12120,12128,0,0,0,0,12130,0,0,0,0, +0,0,12131,0,0,0,12132,12134,0,0,0,0,12137,0,12139,0,12141,0,0,12142,0,0,0,12144, +0,0,0,0,0,12145,0,12148,0,12153,0,0,0,0,12154,12171,12173,0,0,0,12175,0,0,0,0, +12178,0,0,0,0,0,0,0,12183,0,0,0,0,0,0,0,0,12184,0,0,0,12186,0,0,0,0,0,12187, +12188,0,0,12189,0,12196,0,12197,0,0,12198,0,12201,0,0,0,0,12203,0,12209,0,0,0,0, +12210,12211,12212,12213,0,12217,12218,0,0,0,0,0,0,0,0,0,12222,0,0,0,0,0,0,0, +12223,0,0,12229,0,0,0,0,12233,0,0,0,0,12234,0,0,12236,12242,0,0,0,12243,0,0,0, +12244,12253,0,12254,12256,0,12257,0,0,12275,0,0,0,0,0,12277,0,0,0,0,0,12278,0, +12289,0,0,12290,0,12292,12293,0,0,12294,0,12295,0,0,12296,0,12297,0,12298,0,0,0, +0,12301,0,0,0,0,0,0,0,0,0,0,0,0,0,12309,0,12338,12340,0,0,0,0,12341,0,0,0,0,0,0, +0,0,12342,12343,0,12344,0,0,0,0,0,0,0,0,0,12345,0,0,0,0,0,0,0,0,12346,0,0,0,0, +12348,0,0,0,0,0,0,0,0,0,0,0,0,12350,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12351,0,12355, +12356,12357,0,0,12367,12370,12371,0,0,0,0,0,12372,12376,0,0,0,0,0,0,0,0,12379,0, +12382,0,12383,0,0,12384,0,0,0,0,12393,0,0,12394,0,0,0,0,12398,12403,0,0,12404,0, +0,0,0,0,0,0,0,0,0,0,0,0,12410,0,0,0,12411,0,0,0,12412,0,0,0,0,12420,0,12421,0,0, +0,0,0,12423,0,12425,12429,0,0,0,12431,12432,0,0,0,0,0,0,0,0,0,0,0,0,12434,0,0,0, +0,0,12435,12436,0,0,0,0,0,0,0,0,12437,0,0,0,0,0,12438,0,0,0,0,0,0,0,0,12445,0,0, +0,12450,12451,0,0,0,0,0,0,0,0,12452,12475,0,0,12493,12494,0,0,0,12495,0,0,0,0, +12496,12502,12509,0,0,0,0,12510,0,12512,12513,0,0,0,0,12514,0,0,0,12515,0,12520, +0,0,0,12524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12527,0,0,0,12528,0,0,0,12529,0,0,0, +0,0,12530,0,12535,0,0,12536,0,12538,0,0,0,0,0,0,0,0,0,0,0,0,12540,0,12548,0,0,0, +0,0,12550,0,0,0,12551,12552,0,0,0,12554,0,0,0,0,0,0,0,0,12555,0,0,12562,0,12565, +0,12566,0,0,0,0,0,0,0,0,0,0,0,0,12569,0,0,0,12571,12574,0,0,0,0,0,0,0,12577,0,0, +0,0,0,0,0,12578,12579,12603,0,12608,0,0,12611,0,12612,0,12615,0,12625,0,0,0,0, +12627,12646,0,12648,0,0,12657,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12670,0,0,12671,0, +12673,12677,0,0,0,0,0,0,0,0,0,0,0,12679,0,12681,0,12682,12693,0,12694,0,12697,0, +12701,0,0,0,12703,12704,0,0,0,0,12707,12737,0,0,12739,0,0,12740,0,0,12742,12743, +0,0,0,0,0,0,0,0,0,12745,0,12746,12747,0,12748,0,0,12759,12767,0,0,0,0,12773,0, +12774,12778,0,0,0,0,0,0,0,12779,0,0,0,0,0,12780,12793,0,12824,0,12825,0,12836,0, +0,0,0,12839,0,12842,0,0,0,0,0,0,0,0,0,0,0,0,12843,12845,0,12846,0,0,0,0,12847,0, +0,12850,12852,12853,0,0,0,12854,0,0,0,12855,0,12856,0,12858,0,0,12859,0,12862,0, +12863,0,0,12866,0,12869,12872,12873,0,0,0,0,0,0,0,0,0,12875,0,12877,0,0,12878,0, +0,0,0,0,0,0,0,0,12884,12885,12888,0,12889,0,0,0,0,12893,0,0,0,12895,12896,12898, +0,0,0,0,0,0,0,12902,0,12909,12910,0,12926,0,12928,0,0,0,12929,0,12930,0,0,0,0, +12931,0,12932,12933,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12934,0,12942,0,0,0,0,12944, +0,0,0,0,0,0,0,0,12946,0,0,12948,0,0,12949,0,0,0,0,12950,0,0,0,0,12951,0,12952,0, +12953,0,0,0,12954,12958,12959,0,0,0,0,0,12960,12964,0,0,0,0,0,12966,0,0,0,0,0,0, +0,0,12970,0,12971,0,0,0,0,0,0,12972,0,0,12982,0,0,0,12984,12985,0,12986,12996, +12997,13001,13002,0,0,0,0,13004,0,0,13005,0,0,13007,13009,0,13017,0,0,0,13020,0, +13021,0,0,0,0,0,0,0,0,0,0,13022,0,0,0,0,0,0,0,0,13024,13027,0,0,0,0,0,13028,0,0, +13029,0,0,0,0,0,0,0,13032,0,13037,0,0,0,0,0,0,13040,0,0,13041,0,0,0,13043,13044, +13046,0,0,0,0,13047,0,0,0,0,0,0,0,13049,13054,0,13056,0,0,13060,13061,0,0,0,0,0, +13067,0,0,13068,0,13071,0,0,0,0,0,13077,13078,0,0,0,0,0,13079,13080,13081,0, +13082,0,0,0,13085,0,0,0,0,0,0,0,13086,0,13087,13088,0,0,0,0,0,13094,0,13099,0, +13100,0,0,0,13101,0,13125,13126,13128,13129,0,0,13130,0,13131,0,0,0,0,0,0,13134, +0,0,0,0,0,0,0,0,0,0,0,13150,0,13168,0,0,0,0,0,0,0,0,0,13169,0,0,13170,0,0,0,0, +13174,0,0,0,13176,0,0,0,0,0,13177,0,13178,13183,13187,0,0,0,13189,0,0,13190,0,0, +13191,0,0,13206,0,0,0,13207,0,0,0,0,0,0,0,0,0,0,13212,0,0,13219,13232,0,0,0, +13241,0,13249,13253,0,0,0,0,0,13255,13259,0,13260,13261,0,13262,0,13272,0,0,0,0, +13276,0,0,0,0,13277,13299,0,0,13301,13302,0,0,13303,0,0,13305,0,13310,0,0,0, +13311,0,0,0,0,13325,0,13328,0,0,0,13329,0,0,0,0,0,0,13330,0,0,13331,0,13335,0,0, +13342,0,0,0,0,0,13343,0,13354,0,13362,0,13366,13367,13369,0,0,13371,13372,0, +13373,13374,0,13376,0,13380,13381,13386,0,13387,13388,0,13389,13391,13395,0,0,0, +0,0,13401,13409,0,13410,0,0,0,0,13420,0,0,0,0,0,13422,0,0,0,0,13423,0,0,0,0, +13425,0,0,0,0,0,13427,0,0,0,13428,0,0,13430,13438,0,13439,0,13445,0,13448,13449, +0,0,0,0,0,0,13451,0,13457,0,0,0,0,13458,13459,0,13460,0,0,0,0,13464,13465,13466, +13470,0,13471,13472,13474,13475,0,13476,0,0,13478,13479,0,13481,0,0,0,0,13487,0, +13490,0,13493,0,0,13494,0,0,13495,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13496,13497,0, +13500,0,0,13516,13522,0,0,13525,13528,0,0,0,13530,13535,0,13537,13539,0,13540,0, +13543,0,13544,0,0,0,0,0,0,13545,0,0,0,0,0,0,13547,0,0,0,13549,13555,0,0,0,13556, +13557,0,0,0,0,0,0,0,13558,0,13563,0,0,0,0,13564,0,0,0,0,0,0,0,0,13566,0,0,0,0,0, +0,13569,0,0,13571,0,0,0,0,13573,0,0,0,0,0,0,13578,0,0,0,0,0,0,0,0,0,0,13581,0, +13586,0,13595,0,13600,0,0,0,0,0,0,0,0,13601,13603,0,13604,13605,13606,13607,0,0, +13617,13618,0,0,0,0,0,0,0,13623,0,13625,13627,0,0,0,0,0,0,0,0,13629,0,0,0,13634, +0,0,0,13638,0,0,0,0,0,0,0,0,13654,0,0,0,0,0,0,0,0,0,0,13656,0,13659,0,0,13660,0, +0,13662,0,0,0,13663,0,13664,0,0,0,0,0,13668,0,13669,13671,0,0,13672,0,0,0,0,0,0, +13675,13685,0,13686,0,0,0,13687,0,0,0,13692,13694,13697,0,0,0,13702,0,0,0,0,0, +13705,0,0,0,0,13707,0,0,0,13714,0,0,0,0,0,0,0,0,0,13715,0,13716,13717,0,0,13719, +13724,13730,13731,0,0,0,0,0,0,0,0,13732,0,0,0,0,0,0,0,13734,0,13736,0,0,13737, +13738,13747,0,13751,0,0,13752,0,0,0,13753,0,13757,0,0,13762,13763,0,13764,13765, +0,13766,0,0,13767,0,0,0,13768,0,0,0,0,0,0,0,13769,0,0,13772,0,13775,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,13776,13778,13787,0,0,0,13797,0,13798,0,13801,0,13804, +13806,0,0,0,0,13816,13817,0,0,0,0,0,0,0,0,0,0,0,0,0,13834,0,13836,0,0,13838,0,0, +13839,0,13840,0,0,0,0,13842,0,0,0,0,0,0,13843,0,0,0,0,0,0,0,0,0,13845,0,0,0,0,0, +13858,0,0,13860,0,0,13861,0,0,13862,13863,0,13868,0,13869,13870,0,0,0,0,0,0,0,0, +0,0,13872,0,0,0,0,13873,13878,0,0,0,0,0,0,0,0,0,0,13886,0,13888,13889,13890,0,0, +13891,13894,0,13897,13899,13900,13904,0,0,13906,0,0,0,13909,0,0,0,13910,0,0,0, +13911,0,0,0,0,0,13912,13917,0,0,0,0,13918,0,13919,0,0,13920,0,0,0,13921,0,0, +13922,0,0,0,0,0,0,0,13924,0,13927,0,0,0,0,0,13932,0,13933,0,13934,0,0,13935,0, +13944,0,0,0,13954,0,0,13955,0,0,0,0,13956,0,13957,0,13967,13969,0,0,0,0,0,0,0,0, +0,0,0,0,13970,13990,0,13991,13994,0,13995,0,0,0,0,13996,0,0,13999,0,0,0,14018,0, +14019,0,14021,0,0,0,0,0,0,14041,0,0,0,0,0,0,0,0,14043,0,0,0,0,14046,0,0,0,14048, +14049,0,0,0,0,0,0,0,0,0,0,14051,0,0,14052,14056,0,14063,0,14064,14066,0,0,14067, +0,0,0,0,0,0,0,0,0,14068,0,0,0,14072,0,14074,14075,0,14076,14079,14085,14086, +14087,14093,0,0,0,0,14095,0,0,0,0,0,0,14096,14097,0,0,0,0,0,0,0,14098,0,14102,0, +0,0,0,0,14103,0,0,0,14104,0,0,14105,0,0,0,14107,14108,0,0,14109,0,0,0,0,0,0,0,0, +14117,0,0,0,0,14118,0,0,0,0,14119,0,0,14120,0,0,14121,0,14122,14127,0,14128, +14136,0,0,14138,0,14140,0,0,0,14141,14142,0,0,0,0,14146,0,0,14149,0,14151,0,0,0, +14152,0,0,14153,0,0,0,0,0,0,0,0,0,14154,0,14156,14157,0,0,14159,0,14161,0,0,0,0, +14162,0,0,0,0,0,0,14163,0,0,14173,0,0,0,0,0,0,14174,0,0,14176,0,0,14178,0,0, +14179,14181,0,0,14182,14185,14187,0,14190,0,0,14197,0,0,0,0,0,0,0,0,0,0,0,0, +14198,0,0,0,0,0,0,14199,14200,0,0,0,14204,0,0,14208,0,0,0,0,0,0,0,0,0,0,0,14231, +0,0,0,0,0,0,0,0,0,14234,0,0,14235,0,0,0,14240,14241,0,0,0,14246,0,0,0,14247,0, +14250,0,0,14251,0,0,14254,0,0,14256,0,0,0,14260,0,14261,0,0,0,0,14262,14267, +14269,0,0,14277,0,0,14278,0,14279,14282,0,0,0,14283,0,0,0,14284,14285,0,0,0,0, +14286,0,0,0,14288,0,0,0,14289,0,14290,0,14293,14301,14302,14304,14305,0,14307,0, +14308,14309,0,0,0,0,0,0,0,0,0,0,0,14311,14312,0,0,14317,0,0,0,0,0,0,0,14318,0,0, +0,0,14320,0,0,0,0,14321,14322,0,0,0,0,0,14326,14329,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +14330,14331,0,0,0,0,14332,0,0,0,14333,0,0,14337,14340,0,14341,0,0,14342,0,14345, +14346,0,0,14347,0,14362,0,0,0,0,0,14364,14365,14371,0,14373,0,0,14374,0,14379,0, +14400,0,0,0,0,0,14401,0,0,14405,0,14406,0,14408,14409,0,0,0,14417,0,0,14424,0,0, +0,0,0,0,0,0,0,14430,0,0,0,14431,0,0,14435,0,14440,0,0,0,0,0,0,14442,0,0,14443,0, +0,0,0,0,14446,0,0,0,0,0,0,0,14454,0,14457,0,14460,0,0,14466,0,0,0,0,0,14467,0,0, +0,0,0,0,14469,0,14477,0,0,0,0,0,0,14478,14482,0,0,0,14483,0,0,0,14485,14486,0,0, +0,14487,14488,14489,14492,14493,14494,14495,14496,14497,0,14499,0,14501,0,0,0,0, +0,0,0,0,0,0,14502,0,14507,14512,14513,14514,0,0,0,0,0,0,0,0,0,0,0,14515,14526, +14530,0,14537,0,14544,0,14547,0,0,14548,14550,14551,0,0,14552,0,0,0,14553,0, +14554,0,0,0,0,14556,14564,0,0,14565,14566,0,0,0,0,0,0,14568,0,0,14569,0,0,0, +14571,14576,0,0,14577,14578,14579,0,0,14580,0,0,0,0,14582,0,0,0,0,0,0,0,0,0,0,0, +0,14583,0,0,0,0,0,14587,0,14588,0,0,14600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,14601,0,0,14604,14605,14611,0,14613,0,0,0,0,14615,0,0,0,0,0,0,14627,0,14628,0, +0,0,0,14631,0,14633,14634,0,0,0,0,14635,0,0,0,0,0,0,0,0,14636,0,0,14639,14642,0, +0,0,0,14644,0,0,0,0,14645,14646,0,14653,0,0,14654,0,14658,0,14661,0,0,0,14665,0, +0,0,14668,0,0,0,0,0,0,0,0,0,14669,0,0,14670,0,0,0,14680,0,0,14681,0,0,0,0,0, +14682,14683,0,0,0,0,14686,0,0,0,0,14687,14697,0,0,0,0,14699,14705,14711,0,0,0,0, +0,0,0,0,0,0,14712,0,0,0,14713,0,0,0,0,14719,0,14720,14721,14726,0,0,0,14728, +14729,0,0,0,0,14731,0,0,0,0,0,0,0,14733,14736,14737,0,0,14740,14742,0,0,0,14744, +14753,0,0,0,0,14755,14758,14760,0,0,0,0,0,14761,14762,14765,14771,0,14772,0, +14773,14774,0,0,14775,0,0,14776,0,0,0,0,14777,0,14779,0,0,14782,0,0,14785,14786, +14788,0,0,0,0,0,14795,0,0,0,0,0,0,14798,0,14803,14804,14806,0,0,0,14809,0,0,0,0, +0,0,14810,0,0,0,0,14811,0,14812,0,0,0,0,0,14815,0,0,0,0,0,0,0,0,14816,0,14818,0, +0,0,0,0,0,14819,0,14820,0,14823,0,0,0,14824,0,0,14826,14827,0,0,0,0,0,0,0,0,0,0, +0,0,14830,0,0,0,0,0,14833,0,14845,0,0,0,0,0,14846,0,0,14847,14871,0,14873,0, +14876,0,14877,14878,14880,0,0,0,0,0,14881,0,14882,14894,0,0,0,0,14895,0,14907,0, +14908,0,0,0,0,0,0,0,14911,0,0,0,0,14920,0,0,14931,0,14932,14934,14935,0,0,14936, +0,14945,0,0,0,0,0,0,0,14947,0,0,14948,14949,14951,0,0,14952,0,0,0,14964,14973,0, +0,14990,0,0,0,0,14995,0,0,14998,15001,0,0,15002,15020,0,0,0,0,0,0,15021,0,15022, +0,0,0,0,15023,0,0,15025,15029,15033,0,0,0,15034,0,0,0,15035,0,0,0,0,0,15043, +15044,0,0,0,15045,15046,15048,15050,0,15065,0,0,0,0,15066,0,0,15075,15082,15084, +0,0,15085,15086,0,0,0,0,0,0,0,0,15088,0,0,0,15089,0,0,0,0,15094,0,15096,0,15097, +0,15100,0,0,15102,0,0,0,0,0,0,0,0,15105,0,0,15106,0,15109,15113,0,0,0,15115,0, +15118,0,0,0,0,0,0,15119,0,0,15120,0,0,0,0,0,15123,15129,0,0,0,15130,0,15131,0,0, +15134,0,15135,0,0,0,15137,15138,0,0,0,0,0,0,15139,0,0,0,0,0,15140,0,0,15154, +15162,0,15169,15170,0,15175,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15177,0,15178,15179,0, +0,0,0,0,15183,0,0,0,0,0,0,0,0,0,0,0,0,15185,15187,0,15194,15195,15196,0,0,0,0,0, +0,0,15204,0,0,0,0,15206,0,0,0,0,0,15207,0,0,0,0,0,0,0,0,0,15213,0,15214,0,0,0,0, +0,0,0,15232,0,0,0,0,15234,0,15238,15240,0,15248,0,0,0,0,15250,15251,0,0,0,0,0,0, +0,15252,0,0,0,15255,15262,15266,0,0,0,15267,0,0,0,15277,15279,0,0,0,15280,15281, +15282,0,0,0,0,0,15285,0,0,0,0,15289,0,0,15291,0,0,0,0,0,0,0,15296,15297,0,0, +15304,0,0,0,0,15306,0,0,0,0,0,0,15307,15308,0,15309,0,0,15311,0,0,15312,15313,0, +0,0,0,0,0,0,0,0,0,0,0,15314,15317,0,0,0,15318,15319,0,0,0,0,15320,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,15321,0,0,0,0,0,15324,0,15325,15326,0,15330,0,0,0,0,15334,0, +15335,0,15341,0,0,15342,0,0,15343,15344,0,0,0,0,15345,0,0,0,0,15347,0,0,15348, +15349,15350,0,15356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15357,0,15358,0,0,0,0,0,0,0, +15359,15360,15364,0,15380,0,0,0,0,0,15392,0,0,15393,0,15395,0,0,0,0,0,0,0,0, +15396,0,0,15397,15398,0,0,0,0,0,0,0,0,0,15399,0,15400,0,0,0,15402,0,15405,15410, +0,0,0,0,15411,0,0,0,15412,0,15416,0,0,0,0,0,0,0,15428,0,15435,0,0,15438,0,0,0,0, +15439,0,0,0,15440,0,0,0,15441,15449,15451,0,0,0,0,0,0,0,15452,0,0,15455,0,0,0, +15456,0,0,15458,0,15460,15461,0,0,0,0,0,15462,15464,0,15465,0,0,15466,0,0,15467, +0,0,0,0,0,15468,0,0,0,0,15481,0,0,15484,0,15485,15486,0,0,0,15487,0,0,0,0,0, +15488,0,15492,15498,0,0,0,15499,0,0,0,15500,0,15501,0,0,15512,0,15522,0,0,0, +15524,0,15525,15526,0,0,15527,0,0,15545,15546,0,15548,15552,0,15553,0,0,0,15554, +0,15555,0,15557,15565,15573,15577,15578,0,15582,0,15583,0,0,0,0,0,0,0,0,0,0,0,0, +0,15586,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15588,0,0,0,0,0,15589,0,0,0,0,0,0,0,15593, +15594,0,0,0,0,15595,0,0,0,0,0,0,15596,0,0,0,15597,0,0,0,0,15600,0,0,15601,0,0,0, +0,15602,15603,0,0,0,0,0,0,15604,0,15609,0,0,15612,0,0,15613,0,0,15615,15617, +15618,0,0,15620,0,15636,15637,0,0,15649,0,0,0,0,0,0,0,15650,0,0,15651,0,0,0, +15656,0,15658,0,0,0,15664,0,0,15665,0,0,15668,0,0,0,0,0,15669,0,0,15674,0,0, +15675,0,0,0,0,15676,0,0,0,0,0,0,0,0,0,0,0,15677,0,0,0,0,15678,0,0,0,0,0,15679,0, +0,15681,0,15686,0,0,0,0,15687,0,15688,0,0,15690,0,0,0,15697,0,15699,15700,0,0,0, +0,0,0,0,0,0,15701,0,15702,15703,0,15704,0,15705,0,15707,0,15709,0,15712,15716,0, +15717,0,15718,15720,0,0,0,0,0,15724,0,0,0,15725,0,15726,0,0,0,15740,0,15745, +15746,0,0,15747,0,15748,0,0,0,0,0,15749,0,0,0,15752,0,15753,0,0,0,0,0,0,15759,0, +0,0,15765,0,0,0,0,0,0,0,0,0,15767,0,0,0,15771,0,0,15784,0,0,0,0,15785,15790, +15791,0,0,15792,0,0,0,15807,0,15811,0,0,0,0,0,0,0,0,0,0,0,0,15818,0,0,0,15819,0, +0,0,0,15821,0,0,0,0,0,15822,15824,0,0,15827,0,0,15829,15831,0,15832,0,0,15833,0, +15835,15838,15839,15843,0,0,0,0,0,0,0,0,0,0,0,15844,0,0,0,0,15845,15851,15856,0, +0,0,0,0,0,0,15858,15860,0,15861,0,0,0,15864,0,0,0,0,15865,0,0,0,0,0,0,15866,0, +15872,0,0,15876,0,0,0,0,15877,15878,15883,15885,0,0,15888,0,0,0,0,0,15889,15890, +0,0,0,0,0,0,0,0,15892,0,0,0,0,0,0,0,15893,0,0,15894,0,0,0,15895,0,15896,15897,0, +15898,15901,15902,0,15911,15915,0,15916,0,15924,15935,0,15937,0,0,0,0,0,15950,0, +0,0,0,0,0,0,15958,0,0,0,15961,0,0,15966,0,15967,0,0,15977,0,0,15978,0,0,15981, +15982,15983,0,0,0,0,0,0,0,15986,0,0,0,15990,0,15991,15995,15998,0,15999,0,16000, +0,0,0,0,16008,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16009,16011,0,16013,0,0,0,0, +0,0,0,0,16014,0,0,16015,16023,16024,16025,0,0,16026,0,16030,0,16032,0,16033,0,0, +0,0,0,0,16035,16036,16037,0,0,0,0,0,16039,0,0,0,0,16041,0,0,0,0,0,16043,16044,0, +0,16047,0,0,0,16048,0,0,16049,16050,16052,0,0,0,0,0,16055,0,0,0,0,0,0,0,0,16056, +0,0,0,0,0,0,0,16058,16060,16061,0,0,16063,0,0,16064,0,0,0,16067,16068,0,0,16069, +16078,0,0,0,16079,0,0,0,16080,0,16081,0,0,0,16088,0,0,0,0,0,0,0,0,0,0,0,16089, +16093,0,16097,0,16103,0,16104,16105,0,0,16256,0,0,16259,0,0,0,0,0,0,0,16260, +16261,0,0,16262,0,0,16263,0,16268,0,0,0,0,0,0,0,16269,0,0,16270,16273,0,16274,0, +0,0,0,16275,16276,16277,16280,0,0,0,16281,16284,0,0,0,16286,0,16289,0,0,0,0,0,0, +0,0,0,16290,0,0,0,0,16291,0,0,0,0,0,0,0,16292,0,0,0,0,0,0,0,0,16293,16295,16297, +0,16302,0,16304,0,16305,0,16306,0,0,0,0,0,0,0,0,0,0,0,0,16307,16308,16312,0,0,0, +0,0,0,16313,16315,0,16318,0,0,0,16321,0,0,0,0,0,0,0,16326,16333,16336,0,0,0,0, +16337,16340,0,0,0,0,0,16345,0,0,16346,0,0,0,0,0,0,0,0,0,16347,0,0,16348,0,0,0,0, +16349,0,0,0,16350,0,16357,0,0,0,0,16359,16360,0,0,0,0,16362,16363,16364,16365,0, +0,16366,0,0,0,0,16367,16368,0,16369,16374,0,0,0,0,0,0,0,16376,0,0,0,0,16378, +16379,0,16380,0,0,0,16381,16383,0,0,0,0,0,16390,0,0,0,16399,0,16402,16404,16406, +16407,0,0,0,16409,16411,0,0,0,0,16412,0,16413,16415,16423,0,0,0,0,0,16424,0,0,0, +16428,16434,16435,16449,0,16450,16451,0,0,0,16453,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +16454,0,0,16456,16458,0,0,16459,0,0,16460,0,0,0,0,16462,0,16463,0,0,16466,0,0,0, +0,0,16479,0,0,16480,0,16481,16484,0,0,0,0,0,0,0,0,0,0,16485,0,0,0,0,0,0,16489,0, +0,0,0,0,16491,0,0,16498,0,0,16503,0,16505,0,0,0,0,0,0,0,0,16506,0,0,0,16508, +16509,0,0,0,0,0,0,0,0,16511,16513,0,0,0,16516,0,16517,0,16519,0,16529,0,0,16531, +0,0,0,0,0,0,16534,0,0,16541,16542,0,0,0,0,0,0,0,0,0,16543,16547,16548,0,0,0, +16551,0,16552,0,0,0,16553,0,0,16558,0,0,16562,16565,0,0,0,16570,0,0,0,16573, +16585,0,0,0,16586,16587,16595,0,16596,0,16598,0,0,0,16600,0,0,0,0,0,0,0,0,0,0,0, +0,0,16601,0,0,0,0,16603,0,0,0,0,0,0,0,16604,16612,0,0,0,0,16613,0,16618,0,0,0, +16640,0,0,16641,0,0,0,0,0,0,16645,0,0,0,0,16646,0,0,0,0,0,0,16651,0,0,0,0,16653, +16654,0,0,0,16655,0,0,16656,16667,0,0,0,0,16671,0,16672,0,0,0,16673,0,0,0,0,0, +16676,0,16686,0,0,0,0,16689,0,16690,0,16692,0,16693,0,16694,0,16696,0,0,0,16705, +0,0,0,0,0,0,16707,0,0,0,16709,0,0,0,0,16711,0,16712,16713,0,0,0,16715,0,0,0,0, +16716,0,0,0,0,0,0,0,0,0,16718,16724,0,0,16726,16727,0,0,0,0,0,0,0,16728,0,16729, +0,0,16730,0,0,0,0,0,16731,0,0,0,16732,0,0,0,0,16734,16738,0,0,0,0,0,0,0,0,16743, +0,0,16745,0,0,0,0,0,16749,0,16752,0,0,0,0,16756,0,0,16758,0,16759,0,0,0,0,0, +16760,0,0,0,0,0,0,0,16762,0,16769,0,16770,0,16772,0,0,0,16777,16780,0,0,0,0,0,0, +16781,0,0,16782,0,16784,0,0,16785,16787,16792,0,0,16794,0,0,0,16798,0,0,16809,0, +0,16814,16816,16817,0,16819,0,0,0,0,0,0,0,0,0,0,16820,0,0,16836,16839,0,0,16841, +16851,16857,0,0,16858,16859,0,0,16860,0,0,0,0,0,0,0,0,16862,0,16863,0,0,0,0,0,0, +0,16864,0,0,0,0,0,0,0,16876,0,16881,16882,0,16885,16886,0,16887,0,0,0,16889, +16891,0,0,0,0,0,16894,16895,0,0,0,0,0,0,0,0,0,0,0,16897,0,16898,0,0,0,0,0,16913, +0,0,16924,16925,16926,0,0,16927,0,0,0,16937,16938,0,0,0,16940,16941,0,0,0,16942, +16945,0,16946,16949,16950,0,0,0,16952,16955,0,0,0,16965,0,16969,0,0,16975,0,0, +16976,0,0,0,0,16978,0,0,16981,0,16983,16989,0,0,0,0,16990,0,0,16991,0,0,0,16993, +0,16994,16996,17000,0,0,0,0,0,17002,17004,0,17006,0,0,17007,0,0,0,0,17008,17013, +17014,0,0,0,0,0,0,0,0,0,17021,0,17031,0,0,0,0,0,17033,17036,0,17038,0,0,17039,0, +17045,0,0,17046,17047,0,0,0,0,17048,0,17049,17050,0,17051,17053,0,17054,0,17055, +0,0,0,0,0,17063,0,0,17064,0,0,0,0,0,0,0,17065,0,0,17068,0,0,0,0,0,17072,0,0,0,0, +0,0,17073,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17074,0,17080,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,17081,17083,17084,0,0,0,17085,0,0,0,0,17092,0,0,0,0,0,0,0, +0,0,17093,0,17095,17102,0,0,0,0,0,0,17103,0,0,17105,0,17107,0,0,0,0,17114,0,0,0, +0,0,17115,17125,17127,0,0,17128,0,0,0,17129,17130,0,17131,0,0,0,0,0,17132,17135, +17145,0,0,0,0,0,0,0,0,17146,0,17147,0,17148,0,0,0,0,0,0,17149,17150,0,17151, +17153,0,17155,0,0,0,0,17163,17171,0,17174,0,0,0,0,17179,0,0,17182,17185,0,0,0,0, +0,17186,0,0,17188,0,0,0,0,0,0,0,17189,17191,0,17194,0,0,0,0,0,0,0,0,0,17195, +17196,17203,17204,0,0,17205,17217,0,0,0,0,0,17218,0,0,0,0,17219,0,17220,0,17221, +0,0,17230,0,0,0,0,0,17236,0,17238,17239,0,0,0,17241,17244,0,0,17245,0,17248,0,0, +17251,0,17252,0,0,17264,0,17266,0,0,0,17268,0,0,0,0,17271,17272,0,17273,0,17295, +0,17302,0,17305,0,0,0,17306,0,0,0,0,0,0,0,17308,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +17309,0,17310,17313,0,0,0,0,17314,17315,0,17317,0,0,0,0,17318,0,0,0,0,0,0,0, +17320,0,0,0,0,0,0,17334,0,17344,17348,0,0,0,17350,17351,0,0,17353,0,0,17354,0,0, +0,0,0,0,0,0,0,17355,0,0,0,0,0,0,17356,17357,0,0,17359,0,0,0,17371,0,17372,0,0,0, +17393,0,0,0,0,17394,0,0,0,0,0,17395,0,0,17399,0,0,0,17401,17417,0,17418,0,17419, +0,0,0,0,0,17422,17423,0,0,0,0,0,17424,0,0,0,0,0,17428,17429,17433,0,0,0,17437,0, +0,17441,0,0,17442,0,0,17453,0,0,0,0,0,0,0,0,17454,17456,17462,0,0,17466,0,0, +17468,0,0,17469,0,0,0,0,17470,0,17475,0,0,0,0,0,17479,0,0,0,17483,17484,0,17485, +0,17486,0,17491,17492,0,0,17493,0,17494,17495,0,0,0,17496,0,0,0,17497,0,0,0, +17502,0,0,0,0,0,17503,0,17505,0,17507,0,0,0,17512,17513,17514,0,0,17515,0,0,0, +17519,0,0,0,17522,0,0,17523,0,0,0,0,0,0,0,0,0,17527,0,0,0,17528,0,0,0,17534,0,0, +0,0,17536,0,0,0,17539,0,17540,17543,17549,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17556, +0,0,17558,0,17559,0,0,17560,0,0,0,17563,0,0,0,0,0,0,17564,0,0,17565,17566,0, +17567,0,0,0,0,0,0,17569,17570,0,17575,0,0,0,0,0,0,0,0,0,0,0,17581,0,0,0,17582, +17583,0,17586,0,0,17587,0,0,0,0,0,0,0,17588,0,0,0,0,17596,17597,0,0,17598,17600, +0,0,0,0,0,0,17601,0,0,0,17604,0,0,17605,0,0,17607,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,17612,0,0,17618,0,17621,17622,0,0,0,0,17623,0,0,17624,0,0,17630,0,0, +17631,17633,17634,0,0,0,0,0,0,0,17635,0,0,17636,0,0,17637,0,17638,0,17640,0,0,0, +0,0,0,0,0,0,0,17641,0,0,0,0,0,0,0,0,0,0,17643,0,0,0,0,17645,0,0,0,0,0,0,0,0, +17646,17662,0,0,0,0,0,0,0,0,0,17663,17664,0,17665,17666,0,0,0,17669,17671,17673, +0,17679,0,0,0,0,0,0,0,17684,0,0,0,17686,0,17714,0,0,17720,17722,17726,0,0,17728, +0,0,17729,0,0,0,17732,0,17733,0,17734,0,0,0,17735,0,0,0,0,17737,0,0,0,0,17739,0, +0,0,17741,17742,0,0,0,0,17743,17744,17745,0,0,0,17749,0,17750,17751,17752,17754, +17761,17762,0,17763,0,17766,0,17772,0,0,0,0,0,17775,0,0,0,0,0,0,0,17776,0,0, +17777,0,0,17778,17779,0,17782,17783,0,0,0,0,0,0,0,0,0,0,17784,0,0,0,0,0,0,0, +17821,0,0,0,17822,0,0,0,17823,17825,0,0,0,0,0,17826,17831,17832,17833,0,0,17845, +0,0,0,17846,0,0,0,17848,17850,17854,0,17855,0,0,17859,0,0,0,0,0,0,17860,17861,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17870,17871,0,0,0,0,0,0,17872,0,0,0,17879,0, +0,0,17881,17883,0,17884,0,17885,0,0,17886,0,0,17887,17891,17953,0,0,0,0,17954,0, +0,17955,0,17968,0,0,17972,0,0,0,0,0,17974,0,0,0,0,17976,17978,0,0,17983,0,0,0,0, +18003,0,0,0,0,0,18007,0,0,0,0,0,18009,0,0,0,0,0,0,0,18010,0,0,0,0,0,0,18012,0,0, +18014,0,0,0,18015,0,0,0,18016,0,18017,0,0,0,18030,0,0,0,0,0,0,0,18031,0,0,18036, +18037,18038,0,0,18049,18056,0,18057,18058,0,18059,0,0,0,0,0,0,0,0,18062,0,0,0,0, +18064,0,0,0,0,0,0,0,0,18067,0,0,0,18068,0,0,18075,0,0,18078,18093,18094,0,0,0,0, +0,0,0,0,18097,0,0,0,0,0,18098,18100,0,0,0,18108,0,18111,0,0,18112,0,18113,0,0, +18115,18116,0,18118,0,0,0,0,18121,0,0,0,0,18123,0,0,0,0,0,0,0,0,0,18124,0,0,0,0, +18125,18126,0,18127,0,0,18128,18135,0,0,0,0,0,0,0,0,0,18150,0,0,0,0,0,18151, +18152,0,0,18156,18164,0,18166,18171,0,0,0,0,0,0,0,0,0,18172,18183,0,18184,0,0,0, +0,18185,0,18187,0,0,0,0,0,18188,0,0,0,0,0,0,0,0,18189,0,0,18190,0,0,18191,18192, +0,0,18194,18195,18196,0,0,0,18197,0,18203,0,18204,0,0,0,0,18205,0,0,0,18207, +18208,0,0,18214,0,0,0,18215,18216,0,0,0,18220,0,0,18222,0,0,0,0,0,18223,0,18225, +18231,0,18234,0,18235,0,0,0,0,18240,0,0,18241,18242,0,0,0,0,0,18243,18251,0, +18253,0,18254,0,0,0,18266,0,0,0,0,0,0,18269,18270,18271,18273,18281,0,0,0,0,0,0, +0,0,0,0,0,0,18282,0,18283,0,18284,0,0,0,0,0,0,18285,0,18287,18289,0,0,18290,0,0, +0,0,18308,0,0,0,18310,0,0,0,0,0,0,0,0,0,0,0,0,18311,0,18312,18313,0,18315,0,0, +18316,18320,0,18331,0,18332,0,18336,0,0,0,0,18337,0,18340,0,0,0,0,0,0,0,0,0, +18341,0,18344,18345,0,18346,0,0,0,0,0,18348,0,18351,0,0,18356,0,0,0,0,0,0,18357, +0,0,0,0,0,18367,0,0,0,18368,0,18369,0,18370,18371,0,0,0,18437,18444,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,18445,18450,0,0,0,0,18451,0,18452,0,0,0,18453,0,0,0,0,0,18455,0, +0,0,18456,0,18457,0,18460,0,0,18461,0,0,0,0,0,0,0,0,18466,0,0,18467,0,0,0,0, +18473,0,0,0,18476,0,18477,0,0,0,18478,18479,18480,0,0,0,18485,0,0,0,18486,0,0,0, +0,0,0,18488,18490,0,0,0,0,0,0,18491,0,0,0,0,0,18495,0,0,18496,0,0,0,0,0,0,18505, +0,18521,0,18522,18523,0,0,0,18525,18526,0,0,0,0,0,18527,0,0,0,0,18532,18533,0, +18534,0,0,0,0,0,0,18535,18537,0,18538,0,0,0,0,0,0,18540,18541,18542,18543,0, +18546,0,0,0,0,18553,18556,0,0,18558,0,0,18569,18571,0,0,0,18572,0,18574,0,0,0,0, +18586,0,0,0,0,0,18588,0,0,18589,0,0,0,0,0,0,18590,0,18592,0,0,0,0,18594,0,0,0, +18596,0,0,18597,18598,0,0,18601,0,0,0,0,18602,0,0,0,18603,18604,0,18605,0,0,0,0, +18608,0,0,18611,0,0,0,0,0,0,0,0,0,18612,0,18616,0,0,18617,18619,0,0,0,18628,0,0, +0,18629,0,0,18630,0,0,0,0,0,0,0,18631,0,18632,0,0,18635,18637,0,0,0,0,0,0,18641, +18643,18648,0,18652,0,0,18653,0,18655,18656,0,0,0,18657,0,0,18666,18674,0,0,0,0, +18677,18684,18685,0,0,18686,0,0,18690,0,0,0,0,0,0,0,18695,18696,0,0,0,0,0,0,0,0, +0,0,18697,0,0,18700,0,0,0,0,0,0,18702,0,18708,0,0,18709,0,18710,0,0,18711,0, +18714,0,0,18718,0,0,0,0,0,0,18719,0,0,18722,0,18726,0,0,0,0,0,0,0,0,0,0,0,0,0, +18731,0,0,0,0,0,18739,18741,0,0,18742,0,18743,18744,18746,18748,0,18752,18753,0, +0,18754,18763,0,18765,0,0,0,18766,0,0,0,18769,0,0,0,0,0,18773,18778,18779,18781, +0,0,18784,18787,0,18788,0,18793,0,0,0,0,0,0,18795,0,0,18800,0,0,0,0,0,18801, +18804,0,0,0,0,0,0,0,18806,0,0,0,18811,18815,18816,0,0,0,0,18825,0,0,18827,18829, +0,0,18830,0,0,0,0,18831,0,0,18832,0,0,0,0,18833,0,18840,0,18841,0,18842,0,0,0,0, +18843,0,18844,0,0,0,0,0,0,18845,18846,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +18848,0,0,0,18853,18860,0,0,18862,18866,0,0,18867,18869,0,0,18874,18881,18891,0, +0,0,0,0,0,0,0,0,0,18892,0,0,0,0,0,0,0,0,18895,0,18896,0,0,0,18900,0,0,0,18901,0, +18902,18915,18916,0,0,0,0,0,0,0,0,18919,0,0,0,0,0,18920,0,0,0,18921,18929,0,0,0, +0,18930,0,0,0,0,0,0,18932,0,0,0,0,18934,18942,0,0,0,18951,18957,0,0,0,0,18958,0, +0,0,0,18959,18960,0,0,18961,0,0,18962,0,0,0,0,18963,18964,0,0,0,18965,0,18967,0, +0,0,0,0,0,0,0,0,18968,0,18969,0,18970,18973,18976,0,0,0,0,0,0,18977,0,0,0,18981, +0,0,0,18990,0,18998,0,0,0,0,0,18999,19003,0,0,19005,0,0,0,19006,0,0,0,0,0,0, +19008,19011,0,0,19018,0,0,19019,0,19024,0,19031,19032,0,19039,0,19041,19050,0,0, +0,19051,19055,19056,0,19059,19063,19064,0,0,19088,0,0,0,19093,19094,0,0,0,0, +19095,0,19096,0,0,0,19097,0,0,19098,0,19099,19100,0,0,19103,0,0,0,0,0,0,0,19111, +0,0,0,0,0,0,19112,0,0,0,19116,19117,0,19121,19122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,19123,19124,0,0,0,0,0,0,0,19125,19126,0,19128,0,0,0,0,0,0,0,0,0,0, +19129,19130,19131,19132,0,0,19146,0,0,19147,19156,19158,0,0,0,0,0,0,0,0,19182, +19185,0,0,19187,0,0,0,19193,0,0,0,0,0,19194,0,19197,0,0,0,0,19198,0,0,0,0,0,0,0, +0,0,0,19202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19203,0,19205,19210, +0,0,0,19213,0,19218,0,0,0,19223,19229,0,0,19230,0,0,19231,19232,19233,19239,0,0, +0,0,0,19240,0,19248,19249,0,0,0,0,19254,0,19256,19258,19259,0,0,19261,0,19266,0, +0,0,19272,0,19278,19281,19282,0,0,0,0,0,0,0,0,0,0,0,0,19283,0,0,19284,0,0,19285, +19287,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19288,19291,0,19292,0,0,0,0,19297,0,19298,0,0, +0,0,19302,19303,0,0,0,0,19304,19305,0,0,0,0,19314,0,0,19315,0,0,19321,0,0,0,0,0, +0,0,19322,0,19333,0,19334,19335,0,19336,19337,0,0,0,0,0,0,0,0,0,0,0,19346,0,0, +19353,0,19354,19362,0,19366,19367,0,0,19369,0,19375,0,19377,19380,19388,0,0,0,0, +0,19389,19390,0,0,0,0,19392,0,0,0,0,0,19402,0,0,0,0,0,0,0,0,19412,0,0,19413, +19422,0,19424,0,0,0,19425,0,0,0,19428,0,0,0,0,19431,0,0,0,0,0,19432,0,0,0,0,0, +19448,19459,0,0,19461,0,19462,19463,0,19467,19474,19482,0,0,0,0,19494,0,0,0,0, +19501,0,0,0,0,0,0,0,0,0,0,19502,19504,0,0,0,0,0,0,0,19505,0,0,0,0,19506,19507,0, +0,0,19508,0,0,19511,0,0,19514,0,19515,0,19516,0,19518,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,19530,0,19537,19538,0,19543,19546,0,19547,19551,0,0,0,0,0,0,19552, +19553,0,0,0,0,0,0,0,0,0,0,0,0,19555,0,0,19556,0,0,0,0,0,0,0,0,0,0,0,0,19560, +19561,0,0,19562,0,0,0,0,0,0,19565,19567,0,19568,0,0,0,19569,19570,0,19578,0,0,0, +0,19580,0,0,0,0,19581,19584,0,0,0,0,0,0,0,19585,19586,0,0,0,19587,19588,0,19589, +0,0,0,0,0,0,19592,19593,19599,0,19600,0,0,19604,0,0,19605,0,19606,19608,19610,0, +19613,19614,0,0,0,0,0,0,19616,19617,0,0,19618,0,0,19619,0,0,0,19620,19621,19631, +0,0,19632,19634,19636,0,19643,0,0,19644,19658,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,19659,0,0,0,0,0,0,0,0,0,0,0,19675,19677,0,0,0,0,19679,0,19683,0,19684,0,0, +0,0,0,0,19687,0,0,0,0,0,0,0,0,19688,19689,19692,0,0,0,0,0,0,0,19695,19697,0,0,0, +0,0,19698,19699,0,0,19700,0,19702,0,0,19703,0,0,0,0,0,0,19704,19708,0,19710,0, +19713,0,0,0,19715,0,0,0,0,19718,0,0,0,0,0,0,0,19720,0,19722,0,0,19725,0,0,0,0,0, +0,0,0,0,0,0,0,0,19730,0,0,0,0,0,19731,0,19734,19735,19739,0,0,19740,0,19741,0,0, +0,19746,0,0,19747,0,19771,0,0,0,0,0,0,0,0,19772,19775,0,0,0,0,0,0,19778,0,0,0,0, +0,19779,0,0,19780,19790,0,19791,0,0,19792,0,0,0,19793,0,0,19796,19797,0,0,0, +19799,0,0,0,19801,0,0,0,0,19803,0,19804,0,19805,0,0,19807,0,0,0,19808,0,0,0,0,0, +0,19809,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19816,0,19821,0,19822,19830,19831,0,0, +0,19833,0,0,0,0,0,0,0,0,0,0,19838,0,0,0,0,19839,0,0,19843,0,0,0,0,19845,0,0,0,0, +19847,0,0,19848,0,19849,0,0,0,0,0,0,0,19851,0,0,0,19854,0,0,0,0,0,0,0,0,0,19864, +0,19865,0,19866,0,0,0,0,0,0,0,19868,0,0,19870,0,0,19871,0,0,19872,19873,19875,0, +19880,19882,19884,0,0,19885,19886,19888,0,0,0,0,0,0,0,0,0,0,0,0,19890,19892, +19893,0,0,19894,0,0,0,19895,0,19896,19902,0,0,19903,0,0,19905,0,0,0,19906,0, +19908,0,19909,19911,0,0,0,19913,19920,0,19938,19939,19940,0,0,0,0,0,0,0,19942,0, +19943,0,19945,0,0,0,19951,19952,19954,19960,0,19965,0,19971,0,0,0,0,0,19975,0, +19976,0,19990,0,0,19991,0,19993,0,19995,0,0,0,19998,19999,20001,0,20003,20005,0, +20011,20012,0,0,0,0,0,0,20014,0,20020,0,0,0,0,20021,0,0,0,0,0,20023,20024,0,0,0, +0,0,20025,0,0,20027,0,0,20029,0,0,20032,0,0,0,0,20044,20045,0,20048,20049,0,0, +20050,0,20052,0,0,20054,20057,0,0,0,0,0,0,0,0,0,20059,0,0,20061,0,20062,0,20064, +0,0,20066,0,0,20067,0,0,0,0,20069,0,0,0,0,0,0,20070,20071,0,0,0,0,0,0,0,0,0,0,0, +20072,0,0,20073,20074,0,0,0,0,0,20075,0,20078,0,0,0,0,20080,0,20081,0,0,0,0,0,0, +20095,0,20098,0,0,0,0,0,0,0,20107,0,0,0,0,0,0,0,0,20112,0,0,0,20113,20114,0,0,0, +20115,20123,20124,0,0,0,20131,20133,20134,0,0,0,0,20136,0,0,20137,20138,20150,0, +20152,0,0,0,20153,0,0,20154,0,0,0,20158,0,20163,0,0,20164,0,0,0,0,0,0,0,20166,0, +20168,0,20170,0,20175,0,0,20178,0,0,0,0,20223,0,0,0,0,20224,0,20226,0,0,20230,0, +20231,0,0,0,0,20232,0,0,20233,20234,0,20244,0,20247,0,0,0,0,0,0,20249,0,0,0, +20250,0,0,0,0,20251,0,20253,0,20254,0,0,0,0,20256,0,0,20264,0,0,0,0,20266,0,0,0, +20278,0,0,20279,20282,0,0,0,0,0,20283,0,20284,0,20285,0,20287,20290,0,0,0,0, +20292,0,0,0,0,20293,20297,0,0,0,0,0,0,20299,0,20300,20303,0,0,0,0,0,0,20307,0,0, +20308,0,20309,0,20310,0,0,0,0,0,0,20312,0,0,0,20314,0,0,0,0,20315,20316,0,20322, +0,0,0,0,0,0,20339,0,0,0,20342,0,0,0,0,20352,0,0,0,0,0,0,0,0,0,0,20362,0,0,20365, +0,20375,20377,0,0,0,0,0,0,0,0,0,0,0,20378,20379,0,20380,0,0,20381,0,20382,0, +20383,0,20388,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20390,20392,20393,0,0,20395,0,0,0,0,0, +20396,0,0,0,0,0,0,0,0,20398,20415,0,0,0,20417,0,0,20420,0,0,20426,20428,0,20431, +0,0,20432,0,20433,20434,20435,0,0,0,0,20440,0,0,0,0,0,20442,0,20443,0,20446,0,0, +0,0,20448,0,20451,0,0,0,0,0,0,0,0,0,20452,20453,0,0,20454,0,0,0,0,0,0,20457,0, +20458,0,0,0,20465,0,0,0,0,0,20469,0,0,0,20473,0,20476,0,0,0,0,0,0,0,0,20477,0,0, +20485,0,0,20486,0,0,20487,0,20496,0,20497,0,0,20498,0,0,0,0,0,0,0,0,0,0,20499, +20500,0,20501,0,0,0,0,0,20520,20527,0,20529,0,0,0,0,20539,0,0,20540,0,0,0,20543, +0,0,0,20546,0,0,0,0,0,20548,0,0,20563,0,0,20564,0,20566,0,0,0,0,0,20589,0,0,0,0, +20590,0,0,20593,20594,0,0,0,0,20595,0,20597,20598,0,0,0,20618,20620,0,0,0,0, +20621,0,0,0,0,20627,0,0,0,0,0,20628,0,0,0,20629,0,20630,0,0,20639,0,0,0,0,0, +20707,0,0,20709,0,0,0,20713,20714,0,0,0,0,0,20724,20725,0,0,0,0,20726,20728, +20729,0,20733,0,20734,0,20735,20736,0,20737,0,0,20744,0,20745,0,20748,0,0,20749, +0,0,0,0,0,0,0,0,20750,0,0,0,0,20754,0,0,0,20761,0,0,20763,0,0,0,0,0,0,0,20766,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,20767,0,0,0,0,20768,0,20769,20777,0,0,0,0,0,0,20785,0, +0,0,20786,20795,20801,0,20802,0,20807,0,0,20808,0,0,20810,0,0,20811,0,20812,0,0, +0,0,0,20813,0,0,20818,20820,20821,0,0,0,20822,0,20823,0,0,0,20826,0,0,0,0,0,0,0, +20829,20830,20831,0,20832,20836,0,0,20839,0,0,20840,20842,0,20843,0,20844,0, +20854,0,0,0,20855,0,0,0,0,20856,0,0,0,20869,0,0,20871,0,0,0,0,0,0,0,20873,0,0,0, +0,0,20876,0,0,0,0,0,20880,0,0,20882,0,0,0,0,20883,20884,0,0,20890,0,0,0,0,0,0,0, +0,0,20891,0,0,0,0,0,20905,0,20906,20910,0,0,20912,20915,0,0,0,0,0,20916,0,20917, +0,20919,20920,20922,0,20927,0,20928,20929,20930,0,0,20935,0,0,20939,0,0,20941,0, +0,0,20943,0,0,0,20946,20947,0,0,0,0,0,20950,0,20954,0,0,20955,20964,0,0,20967,0, +0,0,0,0,20973,20975,0,0,0,20984,0,20987,20988,0,0,0,0,0,20989,0,0,0,20995,0, +20998,0,20999,0,0,0,0,21000,21001,0,0,0,0,21008,0,21010,0,21016,0,0,0,21017, +21018,0,0,0,0,0,21021,21026,21027,21028,0,0,21029,0,0,0,0,0,21030,0,0,0,0,0,0,0, +0,0,0,0,0,0,21031,21032,0,0,0,0,0,21037,0,0,21038,0,0,0,0,0,0,0,0,0,21039,0, +21041,0,21046,21047,0,0,0,21049,21053,0,0,21057,21064,21065,0,0,21066,21067,0,0, +0,21069,0,0,0,21071,21072,0,0,21073,0,21074,0,0,21078,0,0,0,0,21079,0,0,21080, +21081,0,0,21086,21087,0,21089,0,0,0,0,0,0,0,21091,0,21093,0,21094,0,0,0,0,0,0,0, +0,21095,0,0,0,0,0,21096,0,21098,0,0,0,0,0,0,0,21099,0,0,21100,21101,21102,0,0,0, +0,0,21103,0,21104,0,0,0,0,0,21105,21108,21109,0,0,21112,21113,0,0,0,0,0,0,21115, +21122,21123,0,0,0,0,0,21125,0,0,0,0,0,0,0,0,21129,21131,0,0,21134,0,0,0,21137, +21142,0,21143,0,0,21144,0,21145,21146,0,21152,21154,21155,21156,0,0,0,21160,0,0, +0,0,0,0,21161,0,21164,0,21166,0,0,0,0,21170,0,0,0,0,21171,0,0,21172,0,21174,0, +21175,0,0,0,0,0,21176,21179,21188,0,0,0,21189,0,0,21190,0,0,0,21192,0,0,21193,0, +0,0,21198,0,21212,0,0,21213,0,0,0,0,0,0,21215,21216,0,0,21223,21225,0,21226,0,0, +0,0,21227,21228,0,0,21229,0,0,0,0,21230,21236,0,0,0,0,0,0,0,0,0,0,0,0,0,21237,0, +0,21238,21239,0,0,0,0,21256,0,0,0,0,0,21257,0,0,0,0,0,0,0,21259,0,0,0,21263,0, +21272,0,21274,0,21282,0,0,0,0,0,0,0,0,21283,0,0,0,0,0,0,0,0,21294,0,0,21297,0,0, +0,0,21298,0,0,0,21299,0,21300,21302,0,21316,0,21318,21322,21323,0,21324,0,21326, +0,0,0,21327,21328,0,0,0,21352,0,0,21354,21361,0,0,0,0,0,0,0,0,0,0,0,0,0,21362,0, +0,0,21363,0,0,0,0,0,0,0,0,0,21366,0,0,21367,21372,21374,0,0,0,21375,21377,0, +21378,0,0,0,21380,0,0,0,0,0,0,0,0,0,0,21381,0,0,0,0,0,0,21382,0,21383,0,0,21384, +0,0,21385,0,0,0,0,21389,21390,0,0,0,0,0,0,0,0,0,0,0,0,0,21397,21398,0,0,0,0,0,0, +0,0,0,0,21399,0,21400,0,0,0,0,21402,0,0,0,21403,21404,0,21405,21406,0,0,0,21407, +0,0,0,0,0,0,0,0,0,0,0,0,21408,0,0,0,0,21409,0,21421,0,21422,0,0,0,21425,21428,0, +0,0,0,21429,0,0,0,0,0,21433,0,0,0,0,0,0,0,0,0,0,21434,0,21443,0,21444,21449,0, +21452,0,21453,21454,0,0,0,21457,0,0,21458,0,0,0,21460,21461,0,0,21464,0,0,0, +21473,21478,0,0,21479,0,0,21481,21483,0,0,0,0,0,0,0,0,21484,0,0,21485,21486,0,0, +21488,0,0,0,0,0,0,21523,0,0,21525,0,0,0,0,0,0,0,21526,0,0,0,0,0,0,21529,21530,0, +0,21531,0,0,21533,0,0,21539,21564,0,21567,0,0,0,0,0,0,0,0,21575,0,0,0,0,21577,0, +0,0,0,0,21591,0,0,21604,0,0,0,0,0,0,0,0,0,21605,0,21606,0,0,21617,21618,21619, +21620,0,0,0,0,0,0,0,0,0,0,0,0,0,21623,0,0,0,0,21631,0,21635,0,0,0,0,21639,21646, +21653,21662,0,0,21663,21664,0,21666,0,0,21667,0,21670,21672,21673,0,21674,21683, +0,0,0,0,0,21684,0,21694,0,0,0,0,21695,21700,0,21703,0,21704,0,0,21709,0,0,0, +21710,0,0,0,0,0,0,0,0,21711,0,0,0,21712,0,21717,0,21730,0,0,0,21731,21733,0,0,0, +0,21737,21741,21742,0,21747,0,0,0,21749,0,0,0,0,0,0,0,0,0,0,0,0,0,21750,0,0,0,0, +0,21752,0,0,0,0,21753,0,0,0,0,0,0,21755,21756,0,21757,0,0,0,0,0,0,21760,0,0, +21763,0,0,0,0,0,0,0,0,0,21764,0,0,21766,0,0,21767,0,0,0,0,0,0,0,0,0,21773,0, +21774,0,0,21775,0,0,0,0,21776,0,0,21777,0,0,0,0,0,0,0,0,0,21780,21787,21788, +21791,0,0,0,21797,0,0,0,0,0,21805,0,0,0,0,21806,0,21807,21809,0,21810,21811,0, +21817,21819,21820,0,21823,0,21824,0,0,21825,0,0,21826,21832,0,0,0,0,0,21833, +21848,21849,0,0,21867,21870,21871,21873,0,0,0,21874,0,0,0,0,0,0,0,0,0,21875,0, +21878,0,0,0,21879,0,21881,21886,0,0,0,0,21887,0,0,21888,21894,21895,21897,0, +21901,0,21904,0,0,21906,0,0,0,21909,21910,21911,0,0,21912,0,0,21913,21914,21915, +0,21919,0,0,0,0,0,0,0,21921,0,0,21922,21933,21939,0,0,0,0,0,0,0,0,0,0,0,21944,0, +0,0,0,0,21945,0,21947,0,0,0,0,0,0,0,0,0,0,21949,0,0,0,21950,0,0,0,0,0,0,0,0,0,0, +0,0,0,21951,0,21952,0,0,0,0,0,0,0,0,0,21954,21957,0,0,0,0,21958,0,21959,0,0,0,0, +0,0,21962,21963,0,0,0,0,0,0,0,0,21964,21965,0,0,21969,21970,0,0,0,21974,0,0, +21980,21981,0,21982,0,0,0,0,0,21985,0,21988,0,21992,0,21999,0,0,0,0,0,0,22001,0, +22002,0,0,0,0,0,0,22003,0,0,0,0,0,22004,0,0,0,22008,0,22009,22015,0,0,22016,0,0, +0,22017,22019,0,0,0,0,0,0,0,0,0,22020,0,0,0,0,0,0,0,0,0,0,22021,22037,0,22039,0, +0,0,22040,0,0,0,22048,22049,0,0,22053,22055,22056,22059,0,0,22060,22061,0,0, +22064,0,0,0,0,22066,0,0,0,0,0,0,0,22073,0,0,0,22074,22075,0,0,0,0,0,0,0,22076,0, +0,0,0,22077,22084,22099,0,0,0,0,0,0,0,22104,0,0,22107,0,22108,0,22109,0,22110,0, +0,0,0,0,0,0,22111,22119,0,22120,22122,0,0,0,0,22125,0,0,0,22128,22129,0,0,0,0,0, +0,22141,0,0,0,22142,0,0,22144,22146,0,22148,22149,22151,22154,0,0,0,22162,0,0,0, +0,22164,22177,0,0,0,0,22179,0,22182,22183,0,0,22184,22188,0,0,0,0,0,0,0,0,22190, +0,22194,22201,0,0,22208,0,22209,0,22212,0,0,22215,0,22223,22231,0,0,22232,0, +22234,0,0,22235,22236,0,22237,0,22240,0,0,0,0,0,22241,0,0,0,22242,22246,22247,0, +0,0,22259,22268,0,22269,0,0,0,0,0,0,0,22270,0,0,0,0,22271,0,22272,0,22277,0,0,0, +0,0,22278,22280,22283,22286,0,0,22287,22289,0,0,22290,0,22293,0,0,0,0,0,0,0,0,0, +0,22295,0,22301,22302,0,0,0,22305,0,22308,0,0,0,0,0,0,0,0,0,0,22315,0,0,0,22317, +0,22334,0,0,0,22335,0,0,0,0,0,22336,0,22338,22344,0,22347,22349,0,22350,0,0,0,0, +0,0,0,22357,0,0,0,0,0,22358,0,0,0,0,0,0,0,0,0,0,22359,22360,0,0,0,0,0,0,0,0, +22361,22366,0,0,22369,0,22370,22373,0,0,0,0,0,22375,0,22377,0,0,0,0,0,22378,0,0, +0,0,22381,0,0,0,0,22382,0,22383,0,0,0,0,0,0,0,0,0,22391,0,0,22392,22395,22396, +22402,0,0,0,0,0,0,0,0,0,0,0,0,0,22405,0,0,22406,0,0,22408,0,0,22409,22410,0,0,0, +0,0,0,22424,0,0,0,0,22426,0,0,0,22427,0,22428,0,22432,0,22435,22442,22443,0,0,0, +0,22444,0,0,0,0,0,22446,0,22454,0,22455,0,0,0,22465,0,22470,0,22471,0,0,0,0, +22472,22473,0,22487,0,0,0,22488,0,0,0,0,22489,0,0,22499,0,0,0,0,0,0,22514,0,0, +22515,0,0,0,0,0,0,0,22516,0,0,0,22517,22520,0,0,0,22534,0,0,22535,0,0,22536,0, +22540,22553,0,22555,0,0,0,0,22561,0,0,22562,0,0,0,0,0,0,0,0,0,0,0,22566,0,0,0,0, +22567,22568,0,0,22575,0,22579,0,22582,22583,22585,0,0,0,0,0,22586,0,0,22587,0,0, +22590,0,0,0,0,0,22591,0,22592,0,0,0,0,0,22593,0,22602,0,0,22604,0,0,22609,0,0, +22618,0,0,0,0,0,0,22619,0,22624,22625,0,0,22638,0,0,0,0,0,22639,0,0,22640,0,0,0, +0,0,0,0,22644,0,22645,22647,0,0,0,0,22652,22653,0,0,0,22654,0,22655,0,0,0,22656, +0,0,0,0,0,0,0,0,0,0,22673,22675,22676,0,0,22678,22679,0,22691,0,0,0,0,0,0,0, +22693,0,0,22696,0,22699,22707,22708,0,0,0,0,0,0,0,0,22718,0,22719,0,0,0,0,22723, +0,0,0,22724,22725,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22726,22728,0,0,0,0,0,0,0,0,22729, +0,0,22731,0,0,0,0,22732,22735,22736,0,0,0,0,22739,0,22749,0,0,22751,0,0,0,0,0,0, +0,0,0,0,0,22758,0,0,0,0,0,22760,0,0,0,0,0,22764,22765,22766,0,22768,0,0,0,0,0, +22769,22770,0,0,0,0,0,0,22771,0,0,22772,22775,0,22776,22777,22780,0,0,22782, +22784,0,22787,0,22789,22796,0,0,0,0,0,22798,0,0,0,0,0,0,22802,0,22803,22804,0,0, +0,0,0,0,0,0,0,0,22805,0,0,22810,22811,22814,22816,0,22825,22826,0,22831,22833,0, +0,0,0,0,0,0,0,0,22834,0,22836,22838,0,22839,0,0,0,0,0,22840,0,22847,0,0,0,0,0, +22856,22857,0,22858,22859,0,0,22862,0,0,22864,0,0,0,0,22865,0,0,0,0,0,0,0,0,0,0, +0,22866,0,22867,22868,0,0,0,0,22869,0,22871,0,22872,0,22873,22881,22882,22884, +22885,0,0,0,0,0,0,0,22886,22887,0,22894,0,22895,0,0,0,22900,0,22901,0,0,0,0, +22904,0,0,0,0,22905,22907,0,0,0,22915,22917,0,0,22918,0,0,0,22920,0,0,0,22929, +22930,0,0,0,22941,22942,0,0,0,22943,0,0,0,22944,0,0,0,0,0,0,0,22946,0,22947,0,0, +22954,0,22956,0,0,22962,0,0,0,0,0,0,0,22963,0,0,22964,0,0,0,0,0,0,0,22965,0, +22968,0,0,0,22969,0,0,0,0,0,22970,0,22971,0,0,0,0,0,22978,0,0,22979,0,22987,0,0, +22989,0,0,0,0,0,0,22990,0,23005,0,0,0,0,0,0,0,23006,23007,23008,0,0,23023,23024, +23029,0,0,0,0,23030,0,0,0,0,0,23032,0,0,0,0,0,23035,0,0,0,0,23038,0,0,0,23048,0, +23049,23052,23053,23060,23061,0,23063,0,0,0,0,23067,23068,0,0,0,23069,23073,0,0, +0,23127,0,23128,0,0,0,0,0,23129,0,23138,23141,0,23149,0,0,23150,0,0,0,23152,0,0, +0,0,0,0,0,0,23154,0,0,0,0,23157,23159,23160,0,0,0,0,0,0,0,0,0,0,0,0,23180,0,0,0, +0,23181,0,0,23188,0,23189,0,0,0,0,0,0,0,0,0,0,0,0,23195,0,0,23196,23199,0,0,0,0, +0,0,0,0,0,23202,0,23204,0,23207,0,23209,23210,0,0,0,0,0,0,23227,23229,0,0,23230, +23234,23238,0,0,0,23245,23246,23248,0,0,0,0,23249,23254,0,0,0,23265,0,0,0,0,0,0, +0,23268,0,23276,0,0,0,0,23277,0,23297,0,23298,0,0,0,0,23299,0,23302,0,0,23303, +23312,0,0,23314,0,23320,0,0,0,0,23324,0,23325,0,23328,0,23334,0,0,0,23337,0,0,0, +0,23343,23344,23346,0,23348,0,0,0,0,0,0,0,0,23353,0,0,0,0,23355,0,23356,23358,0, +0,0,23359,23360,0,23361,0,23367,0,23369,0,0,23373,0,23378,23379,0,23382,23383,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,23387,0,0,0,0,0,0,23388,23390,0,0,23393,23398,0,0,0, +23399,0,0,0,23400,0,0,0,0,23401,0,0,0,23415,0,0,0,0,0,0,0,0,23416,0,23422,0, +23443,23444,0,0,0,0,23448,0,23454,0,0,0,0,0,0,23456,0,0,23458,23464,0,0,0,0,0,0, +23465,0,0,0,23470,23471,0,0,23472,0,0,0,23473,23496,0,0,0,0,0,0,0,0,23497,0, +23499,0,0,23502,0,0,23503,0,0,23513,0,0,23515,0,0,0,23517,0,0,0,0,23518,23519, +23521,23524,0,23525,23528,23539,0,0,0,0,0,23541,0,0,23544,0,0,23556,0,0,23557,0, +0,0,0,0,0,0,0,0,0,0,0,0,23559,0,23560,0,0,23561,0,0,23566,0,0,0,0,0,23568,23569, +23570,0,0,0,0,23571,0,23574,0,0,0,0,0,0,0,0,0,0,0,23575,0,23579,0,0,23581,0,0,0, +0,0,0,23587,0,0,0,0,0,0,0,23596,23598,0,0,0,0,23602,23606,0,0,23607,0,23608,0,0, +0,23614,23616,0,0,0,0,0,23618,0,0,23619,0,0,0,0,23621,23626,0,23627,0,0,0,0,0,0, +0,23629,0,23630,0,0,0,0,23634,0,23636,0,0,0,0,0,0,23638,0,0,0,0,23640,23667,0, +23669,0,0,0,23681,0,0,0,0,0,0,0,23682,0,23683,0,0,0,0,0,23684,0,0,0,23685,23689, +0,23693,23694,23700,0,23702,0,23709,0,0,0,0,0,0,0,23712,0,0,0,0,0,23714,0,0, +23715,0,0,0,0,23718,0,0,23720,0,0,0,0,23722,0,0,0,23726,23729,0,23741,23746,0, +23748,0,0,0,0,23749,0,0,0,0,0,23750,0,0,0,0,23751,0,23753,0,0,0,0,23757,23765,0, +0,0,23770,0,0,0,0,0,0,0,23771,0,23772,23781,0,0,23796,0,0,0,0,23798,0,23799,0,0, +0,23802,0,0,23806,0,23807,0,0,23808,0,23809,0,23819,0,0,0,23821,0,23827,0,0,0, +23829,0,0,0,0,0,0,0,23830,0,0,0,0,0,0,23832,23833,23834,23835,0,0,0,0,23837, +23838,0,0,0,0,0,23846,0,0,0,0,0,0,23847,0,0,0,0,0,23879,23881,0,0,23882,23883, +23895,0,23899,0,0,0,0,23901,0,0,0,0,0,0,23902,0,0,0,0,0,23903,23905,0,23906,0, +23907,23918,23919,23920,0,23922,0,23924,0,23927,0,23934,0,23937,23941,0,23942, +23946,0,0,0,0,0,23955,23956,23958,0,0,0,0,0,0,23959,0,23962,23965,0,23966,0,0,0, +0,23967,23968,0,0,23973,0,0,23974,0,0,0,0,23975,0,23976,0,0,0,0,0,0,0,0,0,0,0,0, +0,23977,0,0,0,0,0,0,0,0,23980,0,0,23984,0,23985,0,0,23987,0,0,23988,23990,23991, +0,0,0,0,0,0,23992,0,0,0,0,0,0,0,0,23994,0,0,0,23998,0,0,0,0,0,0,0,0,0,23999,0,0, +24003,0,24004,0,24006,0,0,0,24007,0,0,24008,0,0,0,0,0,0,0,24009,0,0,24010,0,0, +24011,0,0,24013,24014,0,0,24015,24016,24027,0,24028,24029,0,24030,0,0,0,0,0, +24033,24034,0,24035,0,0,24036,0,0,24044,0,24048,24049,24063,24067,0,24068,24070, +0,0,24071,24078,24087,0,24090,0,0,0,24095,0,24098,24101,24104,24106,0,24107,0,0, +0,24108,0,0,0,0,24110,24111,0,24113,0,0,24115,24120,0,0,0,0,0,0,24124,0,24125,0, +24126,0,24127,0,0,0,0,0,24135,0,0,24136,0,24137,24142,0,0,0,24146,0,0,24147, +24149,24154,0,24163,0,0,0,24165,24166,24167,0,0,0,0,0,0,0,0,0,0,24169,24170, +24175,0,0,0,24178,0,0,24179,0,0,24181,0,24184,24197,0,24201,24204,0,0,0,0,0,0, +24206,24212,24220,0,0,0,24224,0,0,0,0,0,0,0,0,24226,0,24234,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,24235,0,24236,0,0,0,0,0,24239,24240,24241,0,0,24248,0,0,24249,0, +24251,0,0,0,0,0,0,24253,0,24268,0,0,0,24269,0,24271,24272,0,0,0,0,24273,0,0, +24274,0,0,24279,0,0,0,0,0,0,0,24280,0,24293,24294,0,0,0,0,0,0,24296,0,0,24323,0, +0,0,24329,24330,24331,24339,0,24351,0,0,24369,24370,0,0,0,24371,0,0,0,0,24372, +24373,24374,0,0,0,0,0,24378,0,0,0,0,24379,0,24381,0,24383,24389,0,24390,0,0, +24394,24395,24400,0,0,0,24401,24402,0,24406,0,0,0,24411,0,0,0,24415,0,24416,0,0, +0,0,0,24417,0,24419,0,24422,0,24423,24428,0,24435,0,0,0,24439,0,0,0,24440,24442, +24446,0,0,0,24447,24448,24449,24452,0,0,0,0,24453,24457,0,0,24458,24459,24460,0, +24465,0,0,0,0,0,0,0,24470,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24471,0,24473, +24474,24475,24476,0,24478,0,0,0,0,24480,0,0,0,0,0,0,0,0,0,0,24481,0,0,0,0,0,0,0, +0,0,0,24482,24485,0,0,0,0,24486,0,0,0,24488,0,0,0,24494,0,0,0,0,24497,0,0,24498, +0,0,0,24499,24506,0,0,0,24507,0,0,24511,0,0,24513,24514,0,0,0,0,0,24517,0,24518, +0,24520,0,24521,24524,24525,0,0,0,0,0,24527,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24528,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24537,24539,0,24540,0,0,0,24548,0,0,0,0,0,24549, +24550,0,0,0,24553,24554,0,24555,0,24556,0,24558,0,0,0,0,0,24560,0,0,0,24561,0,0, +0,0,0,24562,0,0,0,0,0,0,0,0,0,0,0,0,0,24567,0,0,0,0,0,24569,0,0,0,24574,0,24575, +0,0,0,0,0,0,0,0,0,0,0,24577,24581,0,24584,0,0,0,0,0,24585,0,0,0,0,0,24586,0,0, +24587,0,24588,0,0,0,0,0,0,0,0,0,0,24590,24591,0,0,0,0,24592,0,0,0,0,0,0,0,24594, +0,0,0,0,0,0,0,24596,24597,0,0,0,0,24602,24603,0,0,0,0,24604,0,0,24605,0,24610,0, +0,24611,0,0,0,0,24612,24615,24616,24624,0,0,0,24627,0,24638,24639,0,0,0,0,24640, +0,0,0,24655,24656,24657,0,0,0,0,0,0,0,0,24662,0,24663,24664,0,0,0,0,0,24665,0,0, +0,0,24667,0,0,0,0,0,0,24668,24669,0,24670,24674,0,0,0,24675,0,24678,0,0,24679,0, +0,0,24681,0,24683,0,0,0,0,24684,0,24685,0,0,24686,0,0,24688,24689,0,0,0,0,24690, +24691,0,0,0,0,0,0,0,24697,0,24698,0,0,0,0,0,0,0,0,24709,0,0,0,0,0,24710,0,24712, +0,0,0,0,0,0,24713,24714,0,24715,0,24716,24718,0,24719,0,0,0,0,24720,0,0,24725,0, +0,24738,0,24749,24750,0,0,0,24752,0,0,0,24753,0,0,0,24758,0,0,0,0,0,24762,0, +24763,0,0,0,0,0,0,0,24764,0,0,0,0,0,24765,24767,24768,0,24772,0,0,0,0,24773,0,0, +0,0,24777,0,0,0,0,0,24785,0,24786,24788,0,0,0,24789,0,0,0,0,24794,24798,0,24799, +24800,0,0,0,24803,0,24804,24806,0,24807,0,0,0,24810,0,0,0,0,0,0,24827,24828,0, +24835,0,0,0,0,0,0,24836,0,0,0,0,0,24839,0,24843,24844,0,0,0,0,0,0,0,0,0,0,24847, +0,0,24848,0,0,0,0,0,0,24849,0,24850,24851,0,0,0,24852,0,24853,0,0,0,0,0,0,0,0,0, +24854,0,24855,0,0,24868,0,0,0,24883,0,0,0,24884,0,24895,24897,0,0,0,0,0,24899,0, +0,0,0,0,24900,0,24913,0,0,0,0,0,0,24914,0,0,24917,24930,24931,0,0,0,24932,0,0, +24939,0,0,24942,0,0,0,0,0,0,0,0,0,24945,24950,0,24951,0,0,24953,0,0,0,24954,0, +24959,0,0,0,24961,0,0,24962,0,24964,24968,24970,24972,0,0,0,0,0,24976,0,0,0, +24977,0,24982,0,0,24983,0,0,24984,0,0,0,24993,0,0,0,24994,0,0,25001,0,0,0,25003, +0,0,25018,0,0,25023,0,0,0,25034,0,0,25035,25036,0,25037,0,0,0,0,0,0,0,25039,0,0, +0,0,0,25040,0,0,0,0,0,0,0,25042,0,0,25043,25045,0,0,0,0,0,0,25049,0,0,25051,0, +25052,25053,0,0,25054,0,0,0,25055,0,0,0,0,25057,25059,0,0,25060,25064,0,25065, +25069,25070,0,0,0,0,25072,0,25073,0,25090,0,0,25092,25093,25101,0,0,0,0,0,0, +25105,25108,0,0,25113,0,0,25115,25116,0,0,0,0,0,0,25117,0,0,0,25120,25121,0,0,0, +0,0,0,0,25125,0,0,0,25126,0,25130,25134,0,25139,0,25143,0,0,0,25151,0,25161,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25163,0,0,0,0,0,0,0,25174,0,25175,0,25207,0,0, +0,25209,0,0,0,0,25213,0,25219,0,25223,0,25225,0,0,0,25227,0,0,0,25228,0,0,0, +25229,0,0,0,0,0,0,0,25231,25233,0,0,0,0,25237,25239,0,0,0,25243,0,0,0,25252,0, +25257,25258,0,0,0,0,25260,25265,0,25268,0,0,25273,25324,0,25325,0,25326,0,0,0,0, +0,0,0,0,25327,0,0,0,0,0,25328,0,0,0,0,0,0,25332,0,0,0,25333,0,0,0,25336,25337, +25338,0,0,25343,0,25350,0,0,0,0,0,0,0,25352,0,25354,0,25375,0,25379,0,0,0,0, +25384,0,0,0,0,0,0,0,0,0,25386,0,25388,0,25390,0,0,25399,0,0,25401,0,0,0,25402,0, +0,0,25407,0,0,0,0,0,0,0,0,0,0,0,25413,25415,0,0,25417,0,0,0,0,0,0,0,25419,0,0,0, +25421,0,0,0,25424,0,0,0,0,25433,0,0,0,0,0,0,0,0,0,25435,0,0,0,0,0,0,25436,0,0,0, +25437,0,0,25440,0,0,0,0,0,0,25442,0,0,25443,0,25446,0,0,25449,0,0,0,25450,0,0,0, +0,25452,0,25453,25454,25455,0,0,0,25456,0,25457,0,0,0,25459,0,25461,0,25468,0,0, +0,0,0,0,0,0,25469,0,0,0,0,0,25471,0,0,0,0,0,25474,0,0,0,0,0,0,0,0,25475,0,0,0,0, +25477,0,0,0,0,25483,0,0,0,0,0,25484,0,0,0,0,0,0,0,0,0,0,0,0,25485,0,25497,0,0, +25498,0,25504,0,25510,0,25512,0,0,25513,25514,0,0,0,0,0,0,25517,25518,25519,0, +25520,0,0,0,0,0,0,0,25521,0,25522,25527,25534,0,25536,0,25537,0,0,25548,25550,0, +0,25551,0,25552,0,0,0,0,0,25554,0,25555,0,25556,25557,25568,0,0,0,25570,25571,0, +0,0,0,0,0,25574,0,0,0,0,25579,0,0,0,25581,0,0,0,25582,0,0,0,0,0,0,0,0,0,25588,0, +0,0,0,25589,0,0,0,0,25590,0,25591,25592,25593,0,25594,0,0,0,25596,0,25597,25615, +0,0,0,0,0,25618,0,0,0,0,25619,25623,0,0,25629,0,0,25631,0,0,0,25635,25636,0,0, +25649,0,0,0,0,25654,0,0,0,25661,25663,0,0,25671,0,0,25678,25698,0,25699,25702, +25703,0,0,0,0,0,0,0,0,25704,0,0,0,0,0,25706,0,0,25710,0,25711,0,25712,0,25715, +25716,25717,0,0,25718,25728,25732,0,0,0,25734,0,0,0,0,0,0,0,0,0,25737,0,0,25739, +0,0,0,25740,0,25741,25745,0,25746,0,25748,25772,25778,0,0,0,0,0,25780,0,0,0,0, +25781,0,25782,25784,25785,0,0,0,25789,0,0,0,0,0,0,25797,25801,0,0,0,25808,25809, +0,0,25811,25814,25815,0,0,25817,0,0,0,0,0,0,0,0,25820,0,0,0,0,25832,25833,0,0,0, +25846,0,0,0,25847,25848,0,0,0,0,0,0,0,0,0,25849,25850,0,0,25851,0,0,25852,0, +25862,0,0,0,25863,25865,0,0,0,0,0,0,0,25867,25868,0,25869,25874,0,25875,0,25876, +25877,0,0,0,0,25878,25902,0,0,0,0,0,0,0,25903,25904,25905,0,0,0,25908,25909,0,0, +0,0,25910,0,0,0,0,0,0,0,25912,0,25913,0,0,0,0,0,0,0,0,25914,0,0,25916,0,0,0,0,0, +25917,25927,0,0,0,0,25928,0,0,25930,0,0,0,25933,0,0,25938,25942,0,0,0,0,0,0,0, +25945,0,25950,0,25956,0,0,25961,25962,0,0,25963,0,25964,25965,25966,0,0,0,0,0, +25967,0,0,0,0,25968,0,0,0,25969,25971,0,0,0,0,0,25973,25975,0,0,0,0,0,0,0,25978, +0,25981,0,0,0,25982,0,0,0,25984,0,0,0,0,0,0,0,25993,0,0,0,0,0,0,0,0,0,0,0,0,0, +26002,0,0,0,26005,0,0,0,26006,26007,0,0,26014,26015,26016,0,0,0,0,0,0,26017, +26018,26020,0,26022,26023,0,0,0,26024,26028,0,26029,26033,26034,26044,0,0,0,0,0, +26046,0,0,26047,0,0,26049,0,26050,0,26051,0,0,0,0,0,26053,0,0,0,0,26054,26059,0, +0,0,0,0,0,26060,0,26066,0,0,0,0,0,0,0,0,0,0,0,0,26067,0,26069,0,0,26071,0,0,0, +26073,0,26074,26077,0,0,0,0,26078,0,0,0,26079,0,26090,0,0,26094,0,0,0,0,0,0,0,0, +26095,0,0,0,0,0,0,0,0,0,0,0,26096,26101,0,26107,26122,0,26124,0,0,26125,0,0,0,0, +0,0,26136,26141,26155,0,0,0,0,0,0,0,0,0,26164,26166,0,0,0,26167,0,26170,26171,0, +0,26172,0,0,26174,0,0,0,0,0,0,0,0,0,0,0,0,0,26175,0,0,0,26176,26177,0,26321, +26322,0,26323,0,0,26324,0,0,0,0,0,0,0,26325,0,26331,0,0,0,0,0,0,26335,0,0,0, +26350,0,0,0,26379,0,0,26382,26383,26385,0,0,26392,26406,0,0,0,0,26411,0,0,0,0,0, +26412,0,0,26420,0,0,26423,0,26424,26426,26432,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +26435,0,26436,0,0,0,0,0,26441,0,26444,0,0,0,26446,0,0,0,0,26447,0,0,0,0,26449,0, +26450,26452,0,26453,26454,0,0,0,26455,0,0,0,26456,0,0,26458,0,0,26460,0,26463,0, +0,0,0,0,0,0,0,26464,26470,0,0,0,0,0,0,0,0,0,26473,0,0,26474,0,0,0,0,0,0,0,26475, +0,0,0,0,0,0,0,26477,0,26485,0,0,26486,0,26487,0,0,26488,26493,26494,0,0,26495,0, +26497,26504,26506,0,0,0,0,0,26507,0,0,0,0,0,26509,0,0,26510,0,0,0,0,0,0,0,0,0,0, +0,0,0,26512,0,26513,26515,0,0,0,26518,0,0,0,26519,0,26524,26526,0,0,0,26527,0, +26532,0,26533,26537,26558,0,0,0,26559,0,0,0,26571,0,0,26573,0,26588,0,26593,0,0, +0,0,0,0,26603,0,26604,0,0,0,0,0,0,0,0,0,0,26606,0,0,0,0,0,0,0,26607,26609,26611, +26614,0,0,0,26616,26620,0,26621,0,0,0,0,0,26627,0,26629,0,0,26630,0,0,26632, +26643,0,0,0,26644,0,0,0,0,0,0,0,0,0,26646,26647,0,0,0,26650,0,0,26656,0,0,0,0, +26663,26670,26671,0,0,0,26685,26686,26687,0,26689,0,0,0,0,26744,0,26745,0,26747, +26748,0,26749,26750,26751,0,0,0,0,26752,26755,0,0,0,26756,26769,0,0,0,26774,0,0, +0,0,0,26775,0,26777,26778,0,26786,0,0,0,26787,0,0,0,0,0,0,0,0,0,0,0,0,0,26788,0, +0,26789,0,0,0,0,0,26791,0,26792,26793,0,0,0,26794,0,26797,26798,0,0,0,26800,0,0, +26803,0,26804,0,0,0,0,0,0,0,0,0,26805,0,0,26808,0,0,26809,0,0,0,0,0,0,0,26812,0, +26825,0,0,0,0,0,0,0,26826,0,0,26827,26829,26834,0,0,0,0,26835,0,0,26849,0,26851, +0,0,0,0,0,0,0,0,0,26852,0,26853,26857,0,26858,0,26859,0,0,0,0,0,0,0,26876,0, +26878,26882,26883,0,0,0,0,26890,26894,0,0,0,0,26895,26896,0,0,0,0,0,26900,0,0,0, +0,0,0,0,26911,26913,26914,26915,26916,26919,0,0,0,26921,26922,0,0,26925,0,0,0, +26928,0,0,26929,26930,0,0,0,26931,0,26932,0,0,0,0,0,26933,0,0,0,0,0,0,26937,0,0, +26943,0,0,26944,0,0,0,26946,0,0,0,0,0,0,0,26956,0,26958,0,0,26963,0,0,0,0,0,0,0, +26965,0,26969,26970,26972,0,0,0,0,0,26973,0,26974,0,26978,0,26980,0,0,0,0,0,0, +26982,0,26986,26987,0,26990,0,0,0,0,27003,27006,0,0,27007,27010,27012,27013,0,0, +0,0,0,0,0,0,27014,27015,27018,0,27019,0,0,0,0,0,27025,0,0,0,27026,0,0,0,0,27029, +27030,27031,27034,0,0,27036,27037,0,0,0,27038,27042,0,0,0,27044,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,27045,0,0,0,0,0,0,0,27046,0,0,0,0,0,0,0,27047,27049,0,27050,0,0,0, +27051,27052,0,27055,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27056,27058,27059,0, +27061,0,27064,0,0,0,0,0,27069,0,0,27070,0,0,0,0,0,0,0,27072,0,0,0,0,0,0,0,0, +27076,0,0,0,0,0,27078,0,27079,0,0,0,27081,0,0,0,0,0,0,27082,0,27083,27086,0,0,0, +0,27087,0,0,0,0,0,27088,27090,0,27094,0,0,27095,0,27099,27102,0,0,0,27103,0,0,0, +0,27105,0,0,0,27106,0,0,0,0,0,0,27107,0,0,0,0,27108,27117,0,0,0,0,27118,0,0, +27124,0,27126,0,0,27130,27131,0,0,0,0,0,0,27147,0,0,0,0,27148,27149,0,0,0,0, +27150,27151,0,27152,0,27159,0,0,0,27164,0,0,0,0,0,0,0,27175,0,27189,0,0,27191,0, +27193,0,27195,0,27198,0,0,0,0,0,27200,0,0,0,0,27202,0,0,0,0,27203,0,0,27204,0,0, +27206,0,27207,0,0,0,0,27209,0,0,0,27213,0,0,27216,27219,27220,27222,27223,0, +27224,0,27225,27226,0,0,27233,0,0,0,0,27235,0,27237,0,27238,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,27239,0,27242,27243,0,27250,0,0,0,27251,0,27253,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,27254,27255,27258,0,0,0,27259,0,0,0,0,0,0,27267,0,27276,27278, +0,0,0,0,0,0,0,0,0,27296,27297,27301,0,0,0,0,0,0,27302,0,0,0,0,0,0,27312,27313,0, +0,0,0,0,27318,0,27320,0,27329,0,27330,27331,0,27332,0,0,0,0,27340,0,0,0,27348,0, +0,0,0,0,0,27350,0,27351,0,0,0,0,27355,0,0,27358,27359,27361,0,0,0,27365,0,27367, +0,27376,27378,0,0,27379,0,0,0,0,0,0,27396,0,27397,27404,0,0,0,0,0,27408,0,0,0,0, +27453,0,0,0,27456,0,0,0,27458,0,0,0,0,0,0,0,27459,0,0,0,27460,0,0,27461,0,27465, +27467,0,0,27469,0,27470,0,27471,0,27477,27482,0,0,0,0,0,0,27484,0,0,0,0,0,0, +27485,0,0,0,0,0,27493,0,27494,27502,0,0,0,0,0,0,0,0,0,0,0,0,27511,27532,0,0,0, +27533,27545,0,0,0,27546,0,0,0,0,0,0,0,0,0,0,27547,0,0,27549,27550,0,27551,0,0,0, +0,0,0,0,27555,0,0,27571,0,27573,27574,27575,27577,0,27578,0,0,27579,27585,0,0,0, +0,0,27586,0,0,27588,27589,0,0,0,0,27596,0,0,27600,0,0,0,0,0,0,0,0,0,0,0,27608,0, +0,0,0,0,0,0,0,0,0,0,27610,0,0,0,27618,0,0,27620,0,0,0,27631,0,0,27632,27634,0, +27636,27638,0,0,0,27643,0,27644,27649,0,0,0,0,0,0,0,0,0,0,0,0,0,27651,27660,0, +27661,0,0,0,0,0,0,0,27662,0,0,27664,0,27665,0,0,0,27669,0,27671,0,0,0,27673, +27674,0,0,0,27682,0,0,0,27711,0,27712,27713,27719,27720,0,0,27728,0,27729,0,0,0, +0,0,0,0,0,0,27731,0,0,27732,0,27733,0,27738,0,0,0,27742,0,0,0,27743,27744,0,0,0, +0,0,0,27745,27746,0,0,0,27747,27748,27751,27752,0,0,0,27768,27770,0,0,0,27774, +27775,0,27776,27777,0,0,27781,0,27784,0,27786,0,0,27791,0,27792,27793,27804,0, +27812,27813,0,0,0,0,0,0,0,0,27814,0,27825,0,27827,0,0,0,0,27828,27861,27862,0,0, +0,27864,0,0,0,27865,27884,0,27889,0,0,0,0,0,27890,0,27891,0,0,0,27892,0,0,0,0,0, +27897,27898,0,0,27899,0,0,0,27901,27905,0,0,27920,0,0,27921,0,27922,0,0,0,27931, +27934,0,0,0,0,0,0,0,0,0,0,27941,0,27942,0,27945,0,27947,27954,0,0,0,0,27960, +27963,0,0,0,0,0,0,0,0,27964,27965,0,0,0,27967,0,27969,27975,0,27976,27977,0, +27981,0,27983,28051,28052,0,0,0,0,0,28056,0,0,0,0,0,0,28058,28059,0,0,28061,0,0, +0,0,0,0,0,28063,0,0,0,0,0,0,28066,0,0,0,0,0,0,28069,28070,28072,0,28073,0,0, +28074,0,0,0,0,28075,0,0,0,0,0,0,0,28078,0,0,0,0,28085,0,0,0,0,28086,0,0,0,0,0,0, +28088,0,0,0,0,0,0,0,0,28090,0,28097,28114,28115,0,0,0,0,0,0,0,28116,0,0,0,0,0, +28118,0,28129,0,28131,0,0,28135,0,0,0,28140,28141,0,0,0,28146,0,0,0,0,28152,0,0, +0,0,28155,28157,28161,0,0,0,0,28166,0,28167,0,0,0,0,0,0,0,0,0,0,0,28172,0,0,0,0, +0,0,28173,0,0,28175,0,0,0,0,0,0,0,0,0,28178,28188,0,28190,0,0,0,0,0,28191,0, +28193,28206,0,0,28207,28209,0,28211,0,28213,0,0,0,28215,28216,28217,0,28222,0, +28223,28225,0,0,0,28226,0,28227,28229,28232,0,0,0,0,0,0,0,0,0,28235,0,28241,0,0, +28242,0,0,0,0,28243,0,0,0,28245,0,0,0,28248,28250,0,28251,28252,0,0,0,0,0,0, +28253,0,0,28254,28255,0,0,28256,0,0,28258,0,0,0,0,0,28259,0,0,28260,0,0,28261,0, +0,0,0,28262,28263,0,0,28264,0,0,0,28266,0,28268,28269,0,28270,28272,28274,0, +28277,28278,0,0,0,28279,0,28280,28281,28283,0,28292,0,28294,0,28297,0,0,0,0, +28299,0,0,0,0,0,28300,0,0,0,0,0,0,0,28301,0,0,0,0,0,0,0,0,0,0,0,0,0,28302,28303, +0,0,0,0,28304,0,0,28305,0,28312,0,28313,28314,0,0,0,0,0,0,28315,0,0,0,28320, +28321,0,0,28328,0,0,0,28329,28338,0,28339,0,0,28344,0,0,0,0,0,0,0,0,28347,0,0,0, +0,0,0,0,0,28348,0,0,0,0,0,28411,0,28412,28413,0,28416,0,0,0,28420,0,0,0,0,0, +28421,0,0,0,0,28423,0,0,0,28424,0,0,28428,0,0,0,0,0,28429,0,0,0,28431,28434,0, +28458,0,0,0,0,0,0,0,0,0,0,0,28464,0,0,0,0,28465,0,28467,0,0,0,0,0,0,28471,0,0,0, +0,28474,0,28480,0,28481,0,0,28485,0,0,0,0,28486,28488,0,0,28489,0,0,0,0,28492,0, +0,0,28495,0,28497,0,28499,0,0,0,0,28500,0,0,28502,28503,0,0,0,28508,0,0,0,28510, +0,0,28512,28513,28514,28521,0,28526,0,28527,28528,0,0,0,0,28529,0,0,28532,0,0, +28537,28538,0,0,0,28539,0,28548,0,28553,28554,0,0,0,0,0,0,0,0,0,0,0,0,28560, +28563,0,0,28564,0,0,0,0,28565,0,0,0,0,0,0,0,28566,28568,0,0,0,0,0,0,28569,0,0,0, +28570,0,28572,28573,0,0,0,0,28575,0,0,0,0,28576,28581,28588,0,0,28589,0,0,0, +28590,28595,0,28598,0,0,28601,0,0,28605,0,0,0,0,28614,28615,28619,0,0,0,0,0,0, +28620,0,28626,0,0,28628,0,28631,0,28632,0,0,0,0,0,0,28635,0,0,0,28637,28638,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28639,0,28643,0,0,28652,0,0,0,28662,0, +28670,28671,0,0,0,0,0,0,0,0,0,28672,28673,28675,28676,0,0,0,0,0,0,0,28691,0,0,0, +28695,0,0,0,28696,0,28697,28698,0,28705,0,28707,28708,28710,0,0,0,0,0,0,0,28711, +28728,0,0,0,28736,0,0,0,28737,0,0,0,0,0,0,0,0,0,28738,0,28739,0,28741,0,0,28742, +0,0,0,0,0,0,0,0,0,0,0,28745,0,0,0,0,0,0,28749,28750,28752,28754,28756,0,28757,0, +0,0,0,28759,28760,0,0,0,0,0,0,28762,0,0,0,28764,0,0,0,0,0,0,28766,0,28767,28768, +0,0,0,0,28769,28770,0,0,0,0,0,0,0,0,0,0,0,0,0,28771,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,28772,0,28773,0,28782,0,0,0,0,0,0,28784,0,28785,0,28786,0,0,0,28787,0,0,0, +28797,0,0,0,0,0,0,28799,0,0,28801,0,0,0,0,28802,0,28805,0,0,28806,0,0,28807,0,0, +0,0,0,0,0,28808,0,0,0,0,0,28810,28812,0,0,28816,28819,0,0,28821,0,28826,0,0,0, +28842,28852,0,0,28853,0,28854,28855,0,0,0,28857,0,0,0,28858,0,28867,28868,28869, +0,0,0,28874,28880,28882,28890,28892,0,0,0,0,0,0,0,28895,0,0,0,28898,28899,0,0,0, +28900,0,0,28904,0,28906,0,0,0,0,28907,0,0,0,0,0,0,28908,0,0,0,28910,0,28914,0,0, +0,0,0,0,0,28915,28916,28919,0,0,28920,0,28921,0,0,0,0,0,0,0,0,28924,0,0,0,0, +28926,28929,0,0,0,28930,0,28936,0,28939,0,0,0,0,28942,0,0,0,0,0,0,28956,0,0,0, +28966,0,0,0,0,28967,0,0,0,0,0,0,0,0,0,28968,0,28971,0,28975,28976,0,28982,28983, +0,0,28984,28989,28996,28997,28998,0,0,0,0,0,0,28999,0,0,0,0,0,29000,0,29001,0,0, +0,29009,0,0,29011,0,0,29021,0,0,0,0,29024,0,29025,0,0,0,0,0,29026,0,0,0,29036,0, +0,0,29037,0,0,0,0,29038,0,29045,0,29047,0,0,0,0,0,0,0,0,0,29051,0,0,0,29054, +29056,29062,0,29070,29082,0,0,0,29083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29084,0,0, +0,0,29085,29088,0,0,0,0,0,0,0,29090,29097,0,0,0,29103,0,0,0,0,0,0,0,0,29105,0,0, +0,0,0,29107,0,29109,0,0,0,29115,0,0,29120,0,0,29138,29140,0,0,0,0,0,0,0,0,0, +29152,0,29160,29174,0,29176,0,0,29180,0,29181,0,0,0,0,0,0,0,0,29228,0,0,29229,0, +0,29230,0,0,0,0,0,0,0,0,0,0,29234,0,0,0,29241,0,29245,0,29248,0,29250,29256, +29280,0,29282,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29285,0,0,29286,29291,29292,0,0,0,0, +29294,0,29295,0,0,0,0,0,29296,29297,29298,29300,0,29302,0,0,29304,29307,0,29312, +0,0,0,29322,0,0,29323,0,0,29324,29326,29328,0,29335,0,0,0,0,0,0,0,29338,29339,0, +0,0,0,0,29341,29343,0,0,0,0,29344,0,0,0,0,0,29345,0,0,0,0,29346,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,29347,29348,29349,0,0,29354,0,0,29355,0,0,0,0,0,0,0,0,29357,0,0, +0,0,29364,0,29365,0,0,0,0,0,0,0,29366,0,0,29368,0,0,0,0,0,0,0,0,29378,0,29381,0, +0,0,0,0,0,0,0,29386,0,0,0,0,0,0,29389,0,0,0,29390,0,0,29391,29397,0,29398,29412, +29414,29418,29419,0,0,0,0,0,0,0,29420,0,0,0,0,0,0,0,29423,0,0,0,29435,0,0,0, +29437,0,0,29439,0,29441,0,0,0,0,29443,0,29446,29450,29452,0,0,0,0,0,29456,0,0,0, +0,0,29461,0,0,0,29464,0,0,0,0,0,0,0,0,29468,0,29473,0,0,0,29486,0,0,0,29490,0,0, +0,29491,29492,0,0,29497,0,0,0,29498,0,29499,0,29502,29505,0,29509,0,0,0,29510,0, +0,0,29512,0,0,0,29516,0,0,0,0,0,0,0,0,29518,0,29519,0,0,0,0,0,29520,29521,29529, +0,0,0,0,0,0,0,0,29530,0,0,29531,29538,0,29540,0,0,0,29542,0,29543,29544,29547,0, +0,29548,0,0,0,29549,0,0,0,29550,0,0,29552,0,0,0,0,29558,29561,0,29562,29564,0,0, +29565,0,0,29566,0,0,0,0,0,0,0,0,0,0,29578,29584,29586,29591,0,0,0,0,29593,29594, +0,0,29597,0,0,29613,0,29614,0,29615,0,0,0,0,29616,29617,0,0,29625,0,0,0,29632,0, +0,0,0,0,0,0,29633,0,0,0,0,0,29634,29635,29637,0,29638,0,29641,29643,0,0,0,0,0,0, +29644,0,29645,0,29649,0,0,0,29650,0,29653,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29656, +29659,0,0,29660,0,0,0,29661,0,0,0,0,0,29664,0,0,0,29671,29673,0,0,0,0,0,0,0, +29675,0,29677,29679,0,0,29684,0,0,0,0,0,29685,0,0,0,29687,0,0,0,29688,0,29689, +29690,29700,0,29701,0,0,0,29702,0,29706,0,0,0,0,0,0,0,29720,0,29721,0,29727,0, +29733,29734,0,29750,29761,0,29763,0,0,0,0,0,29764,0,0,29765,0,0,0,29771,0,0,0,0, +0,0,0,0,0,0,0,0,29772,0,0,0,29773,29774,29775,0,0,0,0,0,0,0,0,0,0,0,29822,0,0,0, +29824,0,29825,0,0,0,0,0,29827,0,0,0,0,0,0,0,0,29829,0,29832,29834,0,0,29835,0,0, +29837,29838,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29843,0,0,0,0,29844,29845,0,0,0, +0,0,0,0,0,0,29849,0,0,29869,29872,29890,29905,0,0,0,0,0,29907,29921,0,29922,0,0, +29923,29926,29944,29946,0,0,0,0,0,0,0,29947,29948,0,0,0,29951,0,0,0,0,0,29953,0, +0,29956,0,29957,0,0,29962,0,0,0,0,29971,0,0,0,29972,0,0,0,0,0,29978,0,29979, +29992,30007,30008,30010,0,0,0,30013,0,0,0,0,30014,30016,0,0,0,0,0,0,0,0,0,0,0, +30017,0,0,0,0,0,30023,30031,0,0,30033,0,0,0,0,0,0,0,0,0,0,30034,0,30038,0,30039, +0,30040,0,0,0,0,0,0,30067,30068,0,0,0,30069,0,30072,0,0,0,30073,0,0,0,0,30075,0, +0,0,0,0,0,30079,0,0,30080,0,0,0,0,0,30082,0,0,0,0,0,0,0,0,0,0,0,30084,30090,0,0, +30091,0,0,0,0,30098,30118,0,30119,0,30121,30130,0,0,0,0,0,0,0,0,0,0,0,0,0,30131, +30132,30133,0,0,0,0,0,0,30135,0,0,0,0,0,0,0,0,0,0,0,30136,0,0,30137,30138,0,0,0, +30139,30146,0,0,0,0,0,30147,0,0,30148,30151,0,0,0,30168,0,30172,30173,0,0,0,0,0, +0,0,0,30180,30181,0,30192,0,0,0,0,0,0,0,30194,30196,0,0,30199,0,0,30202,0,0,0,0, +30203,0,0,0,0,0,0,0,0,0,0,30213,0,0,0,30216,0,0,30217,0,0,0,30218,0,0,0,0,30219, +0,30220,0,30222,30227,0,0,0,0,0,30231,0,0,30233,30235,0,0,0,0,30238,0,30240, +30243,30245,0,30250,30252,0,0,0,30269,0,0,30271,30272,0,0,0,30278,30280,0,0, +30282,0,30284,0,30294,0,0,0,0,30295,30296,0,0,0,0,0,30298,30299,30302,30304, +30306,0,0,0,0,0,0,30316,30317,0,0,0,30318,0,0,0,30319,0,30320,30322,30326,0,0,0, +0,0,30327,0,30332,30348,30349,0,0,30356,0,0,0,0,0,0,0,0,30357,0,30358,0,30359, +30360,0,0,30365,30366,30378,0,0,0,0,30379,0,0,30381,0,30385,0,30388,30397,0,0,0, +30401,0,0,0,0,30403,0,0,0,0,0,30404,0,0,30405,0,30406,30408,0,30409,0,30410,0,0, +0,30417,0,0,30418,30419,0,30420,0,30424,0,0,0,30427,30430,30432,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,30433,0,0,0,0,0,0,0,30436,0,30437,30438,0,30441,30442,0,0, +0,30445,0,0,0,0,30452,30456,30457,0,0,0,30458,0,30464,0,0,0,0,0,0,30467,0,30469, +0,0,0,0,0,30477,0,0,30484,0,0,0,0,0,30485,0,0,0,0,0,30486,30487,30497,30498,0,0, +0,0,0,0,0,0,0,0,30505,0,30508,0,0,0,30509,30510,0,30514,30516,0,0,0,0,0,0,0,0,0, +0,0,30523,0,30524,0,30525,0,0,0,0,30537,0,0,30538,0,0,0,0,0,30553,0,0,30555, +30556,30558,30559,30560,0,0,30561,0,30562,0,0,0,0,0,0,0,0,30563,30570,30571,0, +30586,30587,0,0,30590,0,0,30594,0,0,0,0,30611,30612,30623,30634,0,0,30636,30640, +30655,30656,0,30657,0,0,30658,30669,0,30670,0,30676,30678,0,0,0,0,0,0,0,30679,0, +0,0,0,0,0,0,0,0,0,0,30695,0,0,30698,0,0,0,0,30700,0,0,0,0,30701,0,30702,30703,0, +0,0,0,30707,0,0,0,30709,0,0,30710,30719,30729,0,0,0,0,0,0,0,0,0,30731,0,0,30733, +0,0,0,30734,0,0,0,0,0,30736,30737,0,0,0,30740,0,0,0,30743,0,30746,0,30747,30748, +0,0,30751,30752,30753,0,0,0,30754,0,0,30760,0,0,0,0,0,0,0,30763,0,30764,0,0, +30766,0,30769,30770,30771,30774,30777,0,0,30779,30780,30781,0,0,0,0,30790,0,0,0, +30792,0,0,0,0,30810,0,0,0,0,0,0,0,30812,30819,0,0,30823,30824,0,30825,0,30827,0, +0,0,0,0,0,30828,0,0,30830,0,0,0,30834,0,30835,0,30837,30838,0,30845,0,0,0,0,0, +30846,30847,0,0,30849,0,30851,0,0,0,0,0,30852,30858,0,0,30859,0,30865,0,0,30866, +0,0,30868,0,0,30869,0,0,0,30881,30883,0,0,0,0,0,30889,0,30891,0,0,0,0,30894,0, +30895,0,30897,0,30898,0,0,0,30904,30906,0,30909,0,0,0,0,0,0,30910,0,0,0,30915, +30933,30942,0,0,0,0,30943,0,0,30945,0,0,0,0,0,0,30946,0,0,30947,0,0,30955,30956, +0,0,30960,0,0,30961,30962,30966,0,0,30969,30974,0,0,0,30976,0,0,30977,0,30978, +30982,0,0,0,0,0,0,0,30994,30995,30998,0,31000,0,0,31001,0,0,31003,31005,0,0, +31006,31011,0,0,31014,0,31016,0,0,0,0,31018,0,0,31020,31023,31024,31025,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,31027,31028,31029,0,0,0,0,0,0,31032,0,0,0,0,0,0,0,0,0,0,0, +31036,31037,31038,0,0,0,31041,31043,31045,0,31047,0,0,0,31048,0,31049,0,0,0, +31053,31054,31055,0,0,31063,0,0,0,0,0,31066,0,31068,31071,0,0,0,31072,31073,0,0, +0,0,31075,0,0,31076,0,0,0,31077,31079,0,31080,0,0,0,0,0,0,0,0,0,0,31087,0,31142, +0,31144,0,0,31145,31146,31147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31149,0,31151,31152,0, +0,0,0,0,0,0,31162,31171,31174,31175,0,0,0,31176,0,0,0,0,0,0,0,31179,0,0,0,31186, +0,0,0,31192,31195,0,0,31196,0,0,0,0,0,0,0,0,31198,0,0,0,0,0,31199,0,0,0,31205,0, +0,0,0,31211,31215,0,0,0,0,31231,0,31232,0,0,0,0,0,0,0,0,0,0,31233,31236,31253,0, +31254,0,0,0,0,0,0,31255,0,0,31257,0,0,0,0,0,0,0,0,0,31258,31259,0,0,31260,0, +31261,0,0,0,0,0,31262,31263,0,0,31264,0,31266,0,31267,0,0,0,0,0,31281,0,31282,0, +31284,0,0,31285,31287,31288,0,0,31290,0,0,0,31292,31295,0,31299,0,31300,0,0,0,0, +0,31302,0,0,0,0,31303,0,0,0,0,0,0,31304,0,0,0,0,0,31305,31308,31309,31315,0, +31317,0,0,0,0,0,31323,0,31324,0,0,0,0,0,31325,31327,0,0,31331,0,0,0,0,0,31333,0, +0,0,0,0,31336,0,0,31337,0,0,0,0,0,0,31338,0,0,0,0,0,0,0,0,0,0,0,0,31339,0,0,0,0, +0,0,0,31342,0,0,0,0,31345,0,0,0,0,0,0,0,0,31347,0,0,0,0,0,0,31348,0,0,31350, +31351,0,31352,0,0,31354,0,0,0,0,31355,0,0,31356,0,0,0,0,0,0,0,0,0,0,31363,0, +31372,0,0,31373,0,0,0,0,0,0,0,0,0,31376,0,31388,0,31389,0,31392,0,31401,0,31405, +31407,31408,0,31409,0,0,0,0,0,0,31413,31415,0,0,0,31416,31418,0,0,0,0,0,0,31422, +31423,0,0,31424,0,31425,31432,0,0,0,0,0,0,0,0,0,31433,0,0,0,0,0,0,0,0,31434,0,0, +0,0,0,0,31435,0,0,0,0,31438,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31442,0,31444,0, +31448,0,0,31451,0,0,0,0,31452,0,31461,31465,0,0,31466,0,0,31467,0,0,31468,0,0,0, +31469,31473,0,31476,0,0,0,0,31489,31490,0,0,0,0,0,0,0,31492,31493,31494,0,0,0,0, +31501,31504,31505,0,0,0,0,0,0,0,0,0,31509,0,0,0,0,31510,0,0,31511,0,0,31513,0,0, +0,0,0,0,0,0,0,31514,0,31522,31536,31539,31540,0,31541,0,0,0,0,0,0,31546,31553, +31559,0,0,0,31560,31561,31562,0,0,31564,31567,0,31569,0,0,0,31570,0,0,0,0,31571, +0,0,0,0,0,0,31572,31574,31580,31581,0,0,31582,31584,31585,31586,31595,0,31596,0, +0,0,0,31597,0,31599,0,31600,31601,0,0,31603,31604,0,0,31608,31610,0,0,0,31611,0, +31615,0,0,0,0,31616,0,0,0,0,0,0,31617,0,0,0,0,0,31618,0,0,0,0,0,0,31621,0,0,0,0, +0,0,0,0,0,31622,31625,0,0,0,0,31627,0,31641,0,0,31642,0,0,31643,0,0,0,0,0,0,0,0, +0,31644,0,31646,0,0,0,0,31648,0,0,0,31652,0,0,0,31657,0,0,31676,0,0,0,0,0,0,0, +31689,31691,31692,0,31694,0,0,0,31696,0,31702,0,31703,0}; + +static const DictWord kStaticDictionaryWords[31705] = { +{0,0,0},{8,0,1002},{136,0,1015},{4,0,683},{4,10,325},{138,10,125},{7,11,572},{9, +11,592},{11,11,680},{11,11,842},{11,11,924},{12,11,356},{12,11,550},{13,11,317}, +{13,11,370},{13,11,469},{13,11,471},{14,11,397},{18,11,69},{146,11,145},{134,0, +1265},{136,11,534},{134,0,1431},{11,0,138},{140,0,40},{4,0,155},{7,0,1689},{4,10 +,718},{135,10,1216},{4,0,245},{5,0,151},{5,0,741},{6,0,1147},{7,0,498},{7,0,870} +,{7,0,1542},{12,0,213},{14,0,36},{14,0,391},{17,0,111},{18,0,6},{18,0,46},{18,0, +151},{19,0,36},{20,0,32},{20,0,56},{20,0,69},{20,0,102},{21,0,4},{22,0,8},{22,0, +10},{22,0,14},{150,0,31},{4,0,624},{135,0,1752},{5,10,124},{5,10,144},{6,10,548} +,{7,10,15},{7,10,153},{137,10,629},{6,0,503},{9,0,586},{13,0,468},{14,0,66},{16, +0,58},{7,10,1531},{8,10,416},{9,10,275},{10,10,100},{11,10,658},{11,10,979},{12, +10,86},{14,10,207},{15,10,20},{143,10,25},{5,0,603},{7,0,1212},{9,0,565},{14,0, +301},{5,10,915},{6,10,1783},{7,10,211},{7,10,1353},{9,10,83},{10,10,376},{10,10, +431},{11,10,543},{12,10,664},{13,10,280},{13,10,428},{14,10,128},{17,10,52},{145 +,10,81},{4,0,492},{133,0,451},{135,0,835},{141,0,70},{132,0,539},{7,11,748},{139 +,11,700},{7,11,1517},{11,11,597},{14,11,76},{14,11,335},{148,11,33},{6,0,113},{ +135,0,436},{4,10,338},{133,10,400},{136,0,718},{133,11,127},{133,11,418},{6,0, +1505},{7,0,520},{6,11,198},{11,10,892},{140,11,83},{4,10,221},{5,10,659},{5,10, +989},{7,10,697},{7,10,1211},{138,10,284},{135,0,1070},{5,11,276},{6,11,55},{135, +11,1369},{134,0,1515},{6,11,1752},{136,11,726},{138,10,507},{15,0,78},{4,10,188} +,{135,10,805},{5,10,884},{139,10,991},{133,11,764},{134,10,1653},{6,11,309},{7, +11,331},{138,11,550},{135,11,1861},{132,11,348},{135,11,986},{135,11,1573},{12,0 +,610},{13,0,431},{144,0,59},{9,11,799},{140,10,166},{134,0,1530},{132,0,750},{ +132,0,307},{133,0,964},{6,11,194},{7,11,133},{10,11,493},{10,11,570},{139,11,664 +},{5,11,24},{5,11,569},{6,11,3},{6,11,119},{6,11,143},{6,11,440},{7,11,295},{7, +11,599},{7,11,1686},{7,11,1854},{8,11,424},{9,11,43},{9,11,584},{9,11,760},{10, +11,148},{10,11,328},{11,11,159},{11,11,253},{11,11,506},{12,11,487},{12,11,531}, +{144,11,33},{136,10,760},{5,11,14},{5,11,892},{6,11,283},{7,11,234},{136,11,537} +,{135,11,1251},{4,11,126},{8,11,635},{147,11,34},{4,11,316},{135,11,1561},{6,0, +999},{6,0,1310},{137,11,861},{4,11,64},{5,11,352},{5,11,720},{6,11,368},{139,11, +359},{4,0,75},{5,0,180},{6,0,500},{7,0,58},{7,0,710},{10,0,645},{136,10,770},{ +133,0,649},{6,0,276},{7,0,282},{7,0,879},{7,0,924},{8,0,459},{9,0,599},{9,0,754} +,{11,0,574},{12,0,128},{12,0,494},{13,0,52},{13,0,301},{15,0,30},{143,0,132},{ +132,0,200},{4,10,89},{5,10,489},{6,10,315},{7,10,553},{7,10,1745},{138,10,243},{ +135,11,1050},{7,0,1621},{6,10,1658},{9,10,3},{10,10,154},{11,10,641},{13,10,85}, +{13,10,201},{141,10,346},{6,11,175},{137,11,289},{5,11,432},{133,11,913},{6,0, +225},{137,0,211},{7,0,718},{8,0,687},{139,0,374},{4,10,166},{133,10,505},{9,0, +110},{134,10,1670},{8,0,58},{9,0,724},{11,0,809},{13,0,113},{145,0,72},{6,0,345} +,{7,0,1247},{144,11,82},{5,11,931},{134,11,1698},{8,0,767},{8,0,803},{9,0,301},{ +137,0,903},{139,0,203},{134,0,1154},{7,0,1949},{136,0,674},{134,0,259},{135,0, +1275},{5,11,774},{6,11,1637},{6,11,1686},{134,11,1751},{134,0,1231},{7,10,445},{ +8,10,307},{8,10,704},{10,10,41},{10,10,439},{11,10,237},{11,10,622},{140,10,201} +,{136,0,254},{6,11,260},{135,11,1484},{139,0,277},{135,10,1977},{4,10,189},{5,10 +,713},{6,11,573},{136,10,57},{138,10,371},{132,10,552},{134,11,344},{133,0,248}, +{9,0,800},{10,0,693},{11,0,482},{11,0,734},{11,0,789},{134,11,240},{4,0,116},{5, +0,95},{5,0,445},{7,0,1688},{8,0,29},{9,0,272},{11,0,509},{11,0,915},{4,11,292},{ +4,11,736},{5,11,871},{6,11,171},{6,11,1689},{7,11,1324},{7,11,1944},{9,11,415},{ +9,11,580},{14,11,230},{146,11,68},{7,0,490},{13,0,100},{143,0,75},{135,0,1641},{ +133,0,543},{7,11,209},{8,11,661},{10,11,42},{11,11,58},{12,11,58},{12,11,118},{ +141,11,32},{5,0,181},{8,0,41},{6,11,63},{135,11,920},{133,0,657},{133,11,793},{ +138,0,709},{7,0,25},{8,0,202},{138,0,536},{5,11,665},{135,10,1788},{145,10,49},{ +9,0,423},{140,0,89},{5,11,67},{6,11,62},{6,11,374},{135,11,1391},{8,0,113},{9,0, +877},{10,0,554},{11,0,83},{12,0,136},{19,0,109},{9,11,790},{140,11,47},{138,10, +661},{4,0,963},{10,0,927},{14,0,442},{135,10,1945},{133,0,976},{132,0,206},{4,11 +,391},{135,11,1169},{134,0,2002},{6,0,696},{134,0,1008},{134,0,1170},{132,11,271 +},{7,0,13},{8,0,226},{10,0,537},{11,0,570},{11,0,605},{11,0,799},{11,0,804},{12, +0,85},{12,0,516},{12,0,623},{13,0,112},{13,0,361},{14,0,77},{14,0,78},{17,0,28}, +{19,0,110},{140,11,314},{132,0,769},{134,0,1544},{4,0,551},{137,0,678},{5,10,84} +,{134,10,163},{9,0,57},{9,0,459},{10,0,425},{11,0,119},{12,0,184},{12,0,371},{13 +,0,358},{145,0,51},{5,0,188},{5,0,814},{8,0,10},{9,0,421},{9,0,729},{10,0,609},{ +11,0,689},{4,11,253},{5,10,410},{5,11,544},{7,11,300},{137,11,340},{134,0,624},{ +138,11,321},{135,0,1941},{18,0,130},{5,10,322},{8,10,186},{9,10,262},{10,10,187} +,{142,10,208},{5,11,53},{5,11,541},{6,11,94},{6,11,499},{7,11,230},{139,11,321}, +{133,10,227},{4,0,378},{4,11,920},{5,11,25},{5,11,790},{6,11,457},{135,11,853},{ +137,0,269},{132,0,528},{134,0,1146},{7,10,1395},{8,10,486},{9,10,236},{9,10,878} +,{10,10,218},{11,10,95},{19,10,17},{147,10,31},{7,10,2043},{8,10,672},{141,10, +448},{134,0,1105},{134,0,1616},{134,11,1765},{140,11,163},{5,10,412},{133,11,822 +},{132,11,634},{6,0,656},{134,11,1730},{134,0,1940},{5,0,104},{6,0,173},{135,0, +1631},{136,10,562},{6,11,36},{7,11,658},{8,11,454},{147,11,86},{5,0,457},{134,10 +,1771},{7,0,810},{8,0,138},{8,0,342},{9,0,84},{10,0,193},{11,0,883},{140,0,359}, +{9,0,620},{135,10,1190},{137,10,132},{7,11,975},{137,11,789},{6,0,95},{6,0,1934} +,{136,0,967},{141,11,335},{6,0,406},{10,0,409},{10,0,447},{11,0,44},{140,0,100}, +{4,10,317},{135,10,1279},{132,0,477},{134,0,1268},{6,0,1941},{8,0,944},{5,10,63} +,{133,10,509},{132,0,629},{132,11,104},{4,0,246},{133,0,375},{6,0,1636},{132,10, +288},{135,11,1614},{9,0,49},{10,0,774},{8,10,89},{8,10,620},{11,10,628},{12,10, +322},{143,10,124},{4,0,282},{7,0,1034},{11,0,398},{11,0,634},{12,0,1},{12,0,79}, +{12,0,544},{14,0,237},{17,0,10},{146,0,20},{132,0,824},{7,11,45},{9,11,542},{9, +11,566},{138,11,728},{5,0,118},{5,0,499},{6,0,476},{6,0,665},{6,0,1176},{6,0, +1196},{7,0,600},{7,0,888},{135,0,1096},{7,0,296},{7,0,596},{8,0,560},{8,0,586},{ +9,0,612},{11,0,304},{12,0,46},{13,0,89},{14,0,112},{145,0,122},{5,0,894},{6,0, +1772},{9,0,1009},{138,10,120},{5,11,533},{7,11,755},{138,11,780},{151,10,1},{6,0 +,1474},{7,11,87},{142,11,288},{139,0,366},{137,10,461},{7,11,988},{7,11,1939},{9 +,11,64},{9,11,502},{12,11,7},{12,11,34},{13,11,12},{13,11,234},{147,11,77},{7,0, +1599},{7,0,1723},{8,0,79},{8,0,106},{8,0,190},{8,0,302},{8,0,383},{8,0,713},{9,0 +,119},{9,0,233},{9,0,419},{9,0,471},{10,0,181},{10,0,406},{11,0,57},{11,0,85},{ +11,0,120},{11,0,177},{11,0,296},{11,0,382},{11,0,454},{11,0,758},{11,0,999},{12, +0,27},{12,0,98},{12,0,131},{12,0,245},{12,0,312},{12,0,446},{12,0,454},{13,0,25} +,{13,0,98},{13,0,426},{13,0,508},{14,0,70},{14,0,163},{14,0,272},{14,0,277},{14, +0,370},{15,0,95},{15,0,138},{15,0,167},{17,0,38},{148,0,96},{135,10,1346},{10,0, +200},{19,0,2},{151,0,22},{135,11,141},{134,10,85},{134,0,1759},{138,0,372},{145, +0,16},{8,0,943},{132,11,619},{139,11,88},{5,11,246},{8,11,189},{9,11,355},{9,11, +512},{10,11,124},{10,11,453},{11,11,143},{11,11,416},{11,11,859},{141,11,341},{5 +,0,258},{134,0,719},{6,0,1798},{6,0,1839},{8,0,900},{10,0,874},{10,0,886},{12,0, +698},{12,0,732},{12,0,770},{16,0,106},{18,0,163},{18,0,170},{18,0,171},{152,0,20 +},{9,0,707},{11,0,326},{11,0,339},{12,0,423},{12,0,502},{20,0,62},{9,11,707},{11 +,11,326},{11,11,339},{12,11,423},{12,11,502},{148,11,62},{5,0,30},{7,0,495},{8,0 +,134},{9,0,788},{140,0,438},{133,11,678},{5,10,279},{6,10,235},{7,10,468},{8,10, +446},{9,10,637},{10,10,717},{11,10,738},{140,10,514},{5,11,35},{6,11,287},{7,11, +862},{7,11,1886},{138,11,179},{7,0,1948},{7,0,2004},{132,11,517},{5,10,17},{6,10 +,371},{137,10,528},{4,0,115},{5,0,669},{6,0,407},{8,0,311},{11,0,10},{141,0,5},{ +137,0,381},{5,0,50},{6,0,439},{7,0,780},{135,0,1040},{136,11,667},{11,11,403},{ +146,11,83},{5,0,1},{6,0,81},{138,0,520},{134,0,738},{5,0,482},{8,0,98},{9,0,172} +,{10,0,360},{10,0,700},{10,0,822},{11,0,302},{11,0,778},{12,0,50},{12,0,127},{12 +,0,396},{13,0,62},{13,0,328},{14,0,122},{147,0,72},{9,11,157},{10,11,131},{140, +11,72},{135,11,714},{135,11,539},{5,0,2},{6,0,512},{7,0,797},{7,0,1494},{8,0,253 +},{8,0,589},{9,0,77},{10,0,1},{10,0,129},{10,0,225},{11,0,118},{11,0,226},{11,0, +251},{11,0,430},{11,0,701},{11,0,974},{11,0,982},{12,0,64},{12,0,260},{12,0,488} +,{140,0,690},{5,11,394},{7,11,367},{7,11,487},{7,11,857},{7,11,1713},{8,11,246}, +{9,11,537},{10,11,165},{12,11,219},{140,11,561},{136,0,557},{5,10,779},{5,10,807 +},{6,10,1655},{134,10,1676},{4,10,196},{5,10,558},{133,10,949},{11,11,827},{12, +11,56},{14,11,34},{143,11,148},{137,0,347},{133,0,572},{134,0,832},{4,0,12},{7,0 +,504},{7,0,522},{7,0,809},{8,0,797},{141,0,88},{4,10,752},{133,11,449},{7,11,86} +,{8,11,103},{145,11,69},{7,11,2028},{138,11,641},{5,0,528},{6,11,1},{142,11,2},{ +134,0,861},{10,0,294},{4,10,227},{5,10,159},{5,10,409},{7,10,80},{10,10,479},{12 +,10,418},{14,10,50},{14,10,249},{142,10,295},{7,10,1470},{8,10,66},{8,10,137},{8 +,10,761},{9,10,638},{11,10,80},{11,10,212},{11,10,368},{11,10,418},{12,10,8},{13 +,10,15},{16,10,61},{17,10,59},{19,10,28},{148,10,84},{20,0,109},{135,11,1148},{6 +,11,277},{7,11,1274},{7,11,1386},{7,11,1392},{12,11,129},{146,11,87},{6,11,187}, +{7,11,39},{7,11,1203},{8,11,380},{8,11,542},{14,11,117},{149,11,28},{134,0,1187} +,{5,0,266},{9,0,290},{9,0,364},{10,0,293},{11,0,606},{142,0,45},{6,11,297},{7,11 +,793},{139,11,938},{4,0,50},{6,0,594},{9,0,121},{10,0,49},{10,0,412},{139,0,834} +,{136,0,748},{7,11,464},{8,11,438},{11,11,105},{11,11,363},{12,11,231},{14,11, +386},{15,11,102},{148,11,75},{132,0,466},{13,0,399},{14,0,337},{6,10,38},{7,10, +1220},{8,10,185},{8,10,256},{9,10,22},{9,10,331},{10,10,738},{11,10,205},{11,10, +540},{11,10,746},{13,10,465},{142,10,194},{9,0,378},{141,0,162},{137,0,519},{4, +10,159},{6,10,115},{7,10,252},{7,10,257},{7,10,1928},{8,10,69},{9,10,384},{10,10 +,91},{10,10,615},{12,10,375},{14,10,235},{18,10,117},{147,10,123},{5,11,604},{5, +10,911},{136,10,278},{132,0,667},{8,0,351},{9,0,322},{4,10,151},{135,10,1567},{ +134,0,902},{133,10,990},{12,0,180},{5,10,194},{7,10,1662},{137,10,90},{4,0,869}, +{134,0,1996},{134,0,813},{133,10,425},{137,11,761},{132,0,260},{133,10,971},{5, +11,20},{6,11,298},{7,11,659},{7,11,1366},{137,11,219},{4,0,39},{5,0,36},{7,0, +1843},{8,0,407},{11,0,144},{140,0,523},{4,0,510},{10,0,587},{139,10,752},{7,0,29 +},{7,0,66},{7,0,1980},{10,0,487},{138,0,809},{13,0,260},{14,0,82},{18,0,63},{137 +,10,662},{5,10,72},{6,10,264},{7,10,21},{7,10,46},{7,10,2013},{8,10,215},{8,10, +513},{10,10,266},{139,10,22},{134,0,570},{6,0,565},{7,0,1667},{4,11,439},{10,10, +95},{11,10,603},{12,11,242},{13,10,443},{14,10,160},{143,10,4},{134,0,1464},{134 +,10,431},{9,0,372},{15,0,2},{19,0,10},{19,0,18},{5,10,874},{6,10,1677},{143,10,0 +},{132,0,787},{6,0,380},{12,0,399},{21,0,19},{7,10,939},{7,10,1172},{7,10,1671}, +{9,10,540},{10,10,696},{11,10,265},{11,10,732},{11,10,928},{11,10,937},{141,10, +438},{137,0,200},{132,11,233},{132,0,516},{134,11,577},{132,0,844},{11,0,887},{ +14,0,365},{142,0,375},{132,11,482},{8,0,821},{140,0,44},{7,0,1655},{136,0,305},{ +5,10,682},{135,10,1887},{135,11,346},{132,10,696},{4,0,10},{7,0,917},{139,0,786} +,{5,11,795},{6,11,1741},{8,11,417},{137,11,782},{4,0,1016},{134,0,2031},{5,0,684 +},{4,10,726},{133,10,630},{6,0,1021},{134,0,1480},{8,10,802},{136,10,838},{134,0 +,27},{134,0,395},{135,11,622},{7,11,625},{135,11,1750},{4,11,203},{135,11,1936}, +{6,10,118},{7,10,215},{7,10,1521},{140,10,11},{132,0,813},{136,0,511},{7,10,615} +,{138,10,251},{135,10,1044},{145,0,56},{133,10,225},{6,0,342},{6,0,496},{8,0,275 +},{137,0,206},{4,0,909},{133,0,940},{132,0,891},{7,11,311},{9,11,308},{140,11, +255},{4,10,370},{5,10,756},{135,10,1326},{4,0,687},{134,0,1596},{134,0,1342},{6, +10,1662},{7,10,48},{8,10,771},{10,10,116},{13,10,104},{14,10,105},{14,10,184},{ +15,10,168},{19,10,92},{148,10,68},{138,10,209},{4,11,400},{5,11,267},{135,11,232 +},{151,11,12},{6,0,41},{141,0,160},{141,11,314},{134,0,1718},{136,0,778},{142,11 +,261},{134,0,1610},{133,0,115},{132,0,294},{14,0,314},{132,10,120},{132,0,983},{ +5,0,193},{140,0,178},{138,10,429},{5,10,820},{135,10,931},{6,0,994},{6,0,1051},{ +6,0,1439},{7,0,174},{133,11,732},{4,11,100},{7,11,679},{8,11,313},{138,10,199},{ +6,10,151},{6,10,1675},{7,10,383},{151,10,10},{6,0,1796},{8,0,848},{8,0,867},{8,0 +,907},{10,0,855},{140,0,703},{140,0,221},{4,0,122},{5,0,796},{5,0,952},{6,0,1660 +},{6,0,1671},{8,0,567},{9,0,687},{9,0,742},{10,0,686},{11,0,682},{11,0,909},{140 +,0,281},{5,11,362},{5,11,443},{6,11,318},{7,11,1019},{139,11,623},{5,11,463},{ +136,11,296},{11,0,583},{13,0,262},{6,10,1624},{12,10,422},{142,10,360},{5,0,179} +,{7,0,1095},{135,0,1213},{4,10,43},{4,11,454},{5,10,344},{133,10,357},{4,0,66},{ +7,0,722},{135,0,904},{134,0,773},{7,0,352},{133,10,888},{5,11,48},{5,11,404},{6, +11,557},{7,11,458},{8,11,597},{10,11,455},{10,11,606},{11,11,49},{11,11,548},{12 +,11,476},{13,11,18},{141,11,450},{134,11,418},{132,10,711},{5,11,442},{135,11, +1984},{141,0,35},{137,0,152},{134,0,1197},{135,11,1093},{137,11,203},{137,10,440 +},{10,0,592},{10,0,753},{12,0,317},{12,0,355},{12,0,465},{12,0,469},{12,0,560},{ +12,0,578},{141,0,243},{133,0,564},{134,0,797},{5,10,958},{133,10,987},{5,11,55}, +{7,11,376},{140,11,161},{133,11,450},{134,0,556},{134,0,819},{11,10,276},{142,10 +,293},{7,0,544},{138,0,61},{8,0,719},{4,10,65},{5,10,479},{5,10,1004},{7,10,1913 +},{8,10,317},{9,10,302},{10,10,612},{141,10,22},{4,0,5},{5,0,498},{8,0,637},{9,0 +,521},{4,11,213},{4,10,261},{7,11,223},{7,10,510},{136,11,80},{5,0,927},{7,0,101 +},{4,10,291},{7,11,381},{7,11,806},{7,11,820},{8,11,354},{8,11,437},{8,11,787},{ +9,10,515},{9,11,657},{10,11,58},{10,11,339},{10,11,749},{11,11,914},{12,10,152}, +{12,11,162},{12,10,443},{13,11,75},{13,10,392},{14,11,106},{14,11,198},{14,11, +320},{14,10,357},{14,11,413},{146,11,43},{6,0,1153},{7,0,1441},{136,11,747},{4,0 +,893},{5,0,780},{133,0,893},{138,11,654},{133,11,692},{133,0,238},{134,11,191},{ +4,10,130},{135,10,843},{6,0,1296},{5,10,42},{5,10,879},{7,10,245},{7,10,324},{7, +10,1532},{11,10,463},{11,10,472},{13,10,363},{144,10,52},{134,0,1729},{6,0,1999} +,{136,0,969},{4,10,134},{133,10,372},{4,0,60},{7,0,941},{7,0,1800},{8,0,314},{9, +0,700},{139,0,487},{134,0,1144},{6,11,162},{7,11,1960},{136,11,831},{132,11,706} +,{135,0,1147},{138,11,426},{138,11,89},{7,0,1853},{138,0,437},{136,0,419},{135, +10,1634},{133,0,828},{5,0,806},{7,0,176},{7,0,178},{7,0,1240},{7,0,1976},{132,10 +,644},{135,11,1877},{5,11,420},{135,11,1449},{4,0,51},{5,0,39},{6,0,4},{7,0,591} +,{7,0,849},{7,0,951},{7,0,1613},{7,0,1760},{7,0,1988},{9,0,434},{10,0,754},{11,0 +,25},{139,0,37},{10,11,57},{138,11,277},{135,10,540},{132,11,204},{135,0,159},{ +139,11,231},{133,0,902},{7,0,928},{7,11,366},{9,11,287},{12,11,199},{12,11,556}, +{140,11,577},{6,10,623},{136,10,789},{4,10,908},{5,10,359},{5,10,508},{6,10,1723 +},{7,10,343},{7,10,1996},{135,10,2026},{134,0,270},{4,10,341},{135,10,480},{5,11 +,356},{135,11,224},{11,11,588},{11,11,864},{11,11,968},{143,11,160},{132,0,556}, +{137,0,801},{132,0,416},{142,0,372},{5,0,152},{5,0,197},{7,0,340},{7,0,867},{10, +0,548},{10,0,581},{11,0,6},{12,0,3},{12,0,19},{14,0,110},{142,0,289},{139,0,369} +,{7,11,630},{9,11,567},{11,11,150},{11,11,444},{141,11,119},{134,11,539},{7,10, +1995},{8,10,299},{11,10,890},{140,10,674},{7,0,34},{7,0,190},{8,0,28},{8,0,141}, +{8,0,444},{8,0,811},{9,0,468},{11,0,334},{12,0,24},{12,0,386},{140,0,576},{133,0 +,757},{7,0,1553},{136,0,898},{133,0,721},{136,0,1012},{4,0,789},{5,0,647},{135,0 +,1102},{132,0,898},{10,0,183},{4,10,238},{5,10,503},{6,10,179},{7,10,2003},{8,10 +,381},{8,10,473},{9,10,149},{10,10,788},{15,10,45},{15,10,86},{20,10,110},{150, +10,57},{9,0,136},{19,0,107},{4,10,121},{5,10,156},{5,10,349},{10,10,605},{142,10 +,342},{4,11,235},{135,11,255},{4,11,194},{5,11,584},{6,11,384},{7,11,583},{10,11 +,761},{11,11,760},{139,11,851},{6,10,80},{6,10,1694},{7,10,173},{7,10,1974},{9, +10,547},{10,10,730},{14,10,18},{150,10,39},{4,10,923},{134,10,1711},{5,0,277},{ +141,0,247},{132,0,435},{133,11,562},{134,0,1311},{5,11,191},{137,11,271},{132,10 +,595},{7,11,1537},{14,11,96},{143,11,73},{5,0,437},{7,0,502},{7,0,519},{7,0,1122 +},{7,0,1751},{14,0,211},{6,10,459},{7,10,1753},{7,10,1805},{8,10,658},{9,10,1},{ +11,10,959},{141,10,446},{6,0,814},{4,11,470},{5,11,473},{6,11,153},{7,11,1503},{ +7,11,1923},{10,11,701},{11,11,132},{11,11,168},{11,11,227},{11,11,320},{11,11, +436},{11,11,525},{11,11,855},{12,11,41},{12,11,286},{13,11,103},{13,11,284},{14, +11,255},{14,11,262},{15,11,117},{143,11,127},{5,0,265},{6,0,212},{135,0,28},{138 +,0,750},{133,11,327},{6,11,552},{7,11,1754},{137,11,604},{134,0,2012},{132,0,702 +},{5,11,80},{6,11,405},{7,11,403},{7,11,1502},{7,11,1626},{8,11,456},{9,11,487}, +{9,11,853},{9,11,889},{10,11,309},{11,11,721},{11,11,994},{12,11,430},{141,11, +165},{5,0,808},{135,0,2045},{5,0,166},{8,0,739},{140,0,511},{134,10,490},{4,11, +453},{5,11,887},{6,11,535},{8,11,6},{136,11,543},{4,0,119},{5,0,170},{5,0,447},{ +7,0,1708},{7,0,1889},{9,0,357},{9,0,719},{12,0,486},{140,0,596},{137,0,500},{7, +10,250},{136,10,507},{132,10,158},{6,0,809},{134,0,1500},{9,0,327},{11,0,350},{ +11,0,831},{13,0,352},{4,10,140},{7,10,362},{8,10,209},{9,10,10},{9,10,503},{9,10 +,614},{10,10,689},{11,10,327},{11,10,725},{12,10,252},{12,10,583},{13,10,192},{ +14,10,269},{14,10,356},{148,10,50},{135,11,741},{4,0,450},{7,0,1158},{19,10,1},{ +19,10,26},{150,10,9},{6,0,597},{135,0,1318},{134,0,1602},{6,10,228},{7,10,1341}, +{9,10,408},{138,10,343},{7,0,1375},{7,0,1466},{138,0,331},{132,0,754},{132,10, +557},{5,11,101},{6,11,88},{6,11,543},{7,11,1677},{9,11,100},{10,11,677},{14,11, +169},{14,11,302},{14,11,313},{15,11,48},{143,11,84},{134,0,1368},{4,11,310},{9, +11,795},{10,11,733},{11,11,451},{12,11,249},{14,11,115},{14,11,286},{143,11,100} +,{132,10,548},{10,0,557},{7,10,197},{8,10,142},{8,10,325},{9,10,150},{9,10,596}, +{10,10,353},{11,10,74},{11,10,315},{12,10,662},{12,10,681},{14,10,423},{143,10, +141},{133,11,587},{5,0,850},{136,0,799},{10,0,908},{12,0,701},{12,0,757},{142,0, +466},{4,0,62},{5,0,275},{18,0,19},{6,10,399},{6,10,579},{7,10,692},{7,10,846},{7 +,10,1015},{7,10,1799},{8,10,403},{9,10,394},{10,10,133},{12,10,4},{12,10,297},{ +12,10,452},{16,10,81},{18,10,25},{21,10,14},{22,10,12},{151,10,18},{12,0,459},{7 +,10,1546},{11,10,299},{142,10,407},{132,10,177},{132,11,498},{7,11,217},{8,11, +140},{138,11,610},{5,10,411},{135,10,653},{134,0,1802},{7,10,439},{10,10,727},{ +11,10,260},{139,10,684},{133,11,905},{11,11,580},{142,11,201},{134,0,1397},{5,10 +,208},{7,10,753},{135,10,1528},{7,0,238},{7,0,2033},{8,0,120},{8,0,188},{8,0,659 +},{9,0,598},{10,0,466},{12,0,342},{12,0,588},{13,0,503},{14,0,246},{143,0,92},{ +135,11,1041},{4,11,456},{7,11,105},{7,11,358},{7,11,1637},{8,11,643},{139,11,483 +},{6,0,1318},{134,0,1324},{4,0,201},{7,0,1744},{8,0,602},{11,0,247},{11,0,826},{ +17,0,65},{133,10,242},{8,0,164},{146,0,62},{133,10,953},{139,10,802},{133,0,615} +,{7,11,1566},{8,11,269},{9,11,212},{9,11,718},{14,11,15},{14,11,132},{142,11,227 +},{133,10,290},{132,10,380},{5,10,52},{7,10,277},{9,10,368},{139,10,791},{135,0, +1243},{133,11,539},{11,11,919},{141,11,409},{136,0,968},{133,11,470},{134,0,882} +,{132,0,907},{5,0,100},{10,0,329},{12,0,416},{149,0,29},{10,10,138},{139,10,476} +,{5,10,725},{5,10,727},{6,11,91},{7,11,435},{135,10,1811},{4,11,16},{5,11,316},{ +5,11,842},{6,11,370},{6,11,1778},{8,11,166},{11,11,812},{12,11,206},{12,11,351}, +{14,11,418},{16,11,15},{16,11,34},{18,11,3},{19,11,3},{19,11,7},{20,11,4},{149, +11,21},{132,0,176},{5,0,636},{5,0,998},{7,0,9},{7,0,1508},{8,0,26},{9,0,317},{9, +0,358},{10,0,210},{10,0,292},{10,0,533},{11,0,555},{12,0,526},{12,0,607},{13,0, +263},{13,0,459},{142,0,271},{6,0,256},{8,0,265},{4,10,38},{7,10,307},{7,10,999}, +{7,10,1481},{7,10,1732},{7,10,1738},{9,10,414},{11,10,316},{12,10,52},{13,10,420 +},{147,10,100},{135,10,1296},{4,11,611},{133,11,606},{4,0,643},{142,11,21},{133, +11,715},{133,10,723},{6,0,610},{135,11,597},{10,0,127},{141,0,27},{6,0,1995},{6, +0,2001},{8,0,119},{136,0,973},{4,11,149},{138,11,368},{12,0,522},{4,11,154},{5, +10,109},{6,10,1784},{7,11,1134},{7,10,1895},{8,11,105},{12,10,296},{140,10,302}, +{4,11,31},{6,11,429},{7,11,962},{9,11,458},{139,11,691},{10,0,553},{11,0,876},{ +13,0,193},{13,0,423},{14,0,166},{19,0,84},{4,11,312},{5,10,216},{7,10,1879},{9, +10,141},{9,10,270},{9,10,679},{10,10,159},{11,10,197},{12,10,538},{12,10,559},{ +14,10,144},{14,10,167},{143,10,67},{134,0,1582},{7,0,1578},{135,11,1578},{137,10 +,81},{132,11,236},{134,10,391},{134,0,795},{7,10,322},{136,10,249},{5,11,836},{5 +,11,857},{6,11,1680},{7,11,59},{147,11,53},{135,0,432},{10,11,68},{139,11,494},{ +4,11,81},{139,11,867},{7,0,126},{136,0,84},{142,11,280},{5,11,282},{8,11,650},{9 +,11,295},{9,11,907},{138,11,443},{136,0,790},{5,10,632},{138,10,526},{6,0,64},{ +12,0,377},{13,0,309},{14,0,141},{14,0,429},{14,11,141},{142,11,429},{134,0,1529} +,{6,0,321},{7,0,1857},{9,0,530},{19,0,99},{7,10,948},{7,10,1042},{8,10,235},{8, +10,461},{9,10,453},{10,10,354},{145,10,77},{7,0,1104},{11,0,269},{11,0,539},{11, +0,627},{11,0,706},{11,0,975},{12,0,248},{12,0,434},{12,0,600},{12,0,622},{13,0, +297},{13,0,485},{14,0,69},{14,0,409},{143,0,108},{4,10,362},{7,10,52},{7,10,303} +,{10,11,70},{12,11,26},{14,11,17},{14,11,178},{15,11,34},{149,11,12},{11,0,977}, +{141,0,507},{9,0,34},{139,0,484},{5,10,196},{6,10,486},{7,10,212},{8,10,309},{ +136,10,346},{6,0,1700},{7,0,26},{7,0,293},{7,0,382},{7,0,1026},{7,0,1087},{7,0, +2027},{8,0,24},{8,0,114},{8,0,252},{8,0,727},{8,0,729},{9,0,30},{9,0,199},{9,0, +231},{9,0,251},{9,0,334},{9,0,361},{9,0,712},{10,0,55},{10,0,60},{10,0,232},{10, +0,332},{10,0,384},{10,0,396},{10,0,504},{10,0,542},{10,0,652},{11,0,20},{11,0,48 +},{11,0,207},{11,0,291},{11,0,298},{11,0,342},{11,0,365},{11,0,394},{11,0,620},{ +11,0,705},{11,0,1017},{12,0,123},{12,0,340},{12,0,406},{12,0,643},{13,0,61},{13, +0,269},{13,0,311},{13,0,319},{13,0,486},{14,0,234},{15,0,62},{15,0,85},{16,0,71} +,{18,0,119},{20,0,105},{135,10,1912},{4,11,71},{5,11,376},{7,11,119},{138,11,665 +},{10,0,918},{10,0,926},{4,10,686},{136,11,55},{138,10,625},{136,10,706},{132,11 +,479},{4,10,30},{133,10,43},{6,0,379},{7,0,270},{8,0,176},{8,0,183},{9,0,432},{9 +,0,661},{12,0,247},{12,0,617},{18,0,125},{7,11,607},{8,11,99},{152,11,4},{5,0, +792},{133,0,900},{4,11,612},{133,11,561},{4,11,41},{4,10,220},{5,11,74},{7,10, +1535},{7,11,1627},{11,11,871},{140,11,619},{135,0,1920},{7,11,94},{11,11,329},{ +11,11,965},{12,11,241},{14,11,354},{15,11,22},{148,11,63},{9,11,209},{137,11,300 +},{134,0,771},{135,0,1979},{4,0,901},{133,0,776},{142,0,254},{133,11,98},{9,11, +16},{141,11,386},{133,11,984},{4,11,182},{6,11,205},{135,11,220},{7,10,1725},{7, +10,1774},{138,10,393},{5,10,263},{134,10,414},{4,11,42},{9,11,205},{9,11,786},{ +138,11,659},{14,0,140},{148,0,41},{8,0,440},{10,0,359},{6,10,178},{6,11,289},{6, +10,1750},{7,11,1670},{9,10,690},{10,10,155},{10,10,373},{11,10,698},{12,11,57},{ +13,10,155},{20,10,93},{151,11,4},{4,0,37},{5,0,334},{7,0,1253},{151,11,25},{4,0, +508},{4,11,635},{5,10,97},{137,10,393},{139,11,533},{4,0,640},{133,0,513},{134, +10,1639},{132,11,371},{4,11,272},{7,11,836},{7,11,1651},{145,11,89},{5,11,825},{ +6,11,444},{6,11,1640},{136,11,308},{4,10,191},{7,10,934},{8,10,647},{145,10,97}, +{12,0,246},{15,0,162},{19,0,64},{20,0,8},{20,0,95},{22,0,24},{152,0,17},{4,0,533 +},{5,10,165},{9,10,346},{138,10,655},{5,11,737},{139,10,885},{133,10,877},{8,10, +128},{139,10,179},{137,11,307},{140,0,752},{133,0,920},{135,0,1048},{5,0,153},{6 +,0,580},{6,10,1663},{7,10,132},{7,10,1154},{7,10,1415},{7,10,1507},{12,10,493},{ +15,10,105},{151,10,15},{5,10,459},{7,10,1073},{8,10,241},{136,10,334},{138,0,391 +},{135,0,1952},{133,11,525},{8,11,641},{11,11,388},{140,11,580},{142,0,126},{134 +,0,640},{132,0,483},{7,0,1616},{9,0,69},{6,10,324},{6,10,520},{7,10,338},{7,10, +1729},{8,10,228},{139,10,750},{5,11,493},{134,11,528},{135,0,734},{4,11,174},{ +135,11,911},{138,0,480},{9,0,495},{146,0,104},{135,10,705},{9,0,472},{4,10,73},{ +6,10,612},{7,10,927},{7,10,1330},{7,10,1822},{8,10,217},{9,10,765},{9,10,766},{ +10,10,408},{11,10,51},{11,10,793},{12,10,266},{15,10,158},{20,10,89},{150,10,32} +,{7,11,548},{137,11,58},{4,11,32},{5,11,215},{6,11,269},{7,11,1782},{7,11,1892}, +{10,11,16},{11,11,822},{11,11,954},{141,11,481},{132,0,874},{9,0,229},{5,10,389} +,{136,10,636},{7,11,1749},{136,11,477},{134,0,948},{5,11,308},{135,11,1088},{4,0 +,748},{139,0,1009},{136,10,21},{6,0,555},{135,0,485},{5,11,126},{8,11,297},{9,11 +,366},{9,11,445},{12,11,53},{12,11,374},{141,11,492},{7,11,1551},{139,11,361},{ +136,0,193},{136,0,472},{8,0,653},{13,0,93},{147,0,14},{132,0,984},{132,11,175},{ +5,0,172},{6,0,1971},{132,11,685},{149,11,8},{133,11,797},{13,0,83},{5,10,189},{7 +,10,442},{7,10,443},{8,10,281},{12,10,174},{141,10,261},{134,0,1568},{133,11,565 +},{139,0,384},{133,0,260},{7,0,758},{7,0,880},{7,0,1359},{9,0,164},{9,0,167},{10 +,0,156},{10,0,588},{12,0,101},{14,0,48},{15,0,70},{6,10,2},{7,10,1262},{7,10, +1737},{8,10,22},{8,10,270},{8,10,612},{9,10,312},{9,10,436},{10,10,311},{10,10, +623},{11,10,72},{11,10,330},{11,10,455},{12,10,321},{12,10,504},{12,10,530},{12, +10,543},{13,10,17},{13,10,156},{13,10,334},{17,10,60},{148,10,64},{4,11,252},{7, +11,1068},{10,11,434},{11,11,228},{11,11,426},{13,11,231},{18,11,106},{148,11,87} +,{7,10,354},{10,10,410},{139,10,815},{6,0,367},{7,10,670},{7,10,1327},{8,10,411} +,{8,10,435},{9,10,653},{9,10,740},{10,10,385},{11,10,222},{11,10,324},{11,10,829 +},{140,10,611},{7,0,1174},{6,10,166},{135,10,374},{146,0,121},{132,0,828},{5,11, +231},{138,11,509},{7,11,601},{9,11,277},{9,11,674},{10,11,178},{10,11,257},{10, +11,418},{11,11,531},{11,11,544},{11,11,585},{12,11,113},{12,11,475},{13,11,99},{ +142,11,428},{134,0,1541},{135,11,1779},{5,0,343},{134,10,398},{135,10,50},{135, +11,1683},{4,0,440},{7,0,57},{8,0,167},{8,0,375},{9,0,82},{9,0,561},{9,0,744},{10 +,0,620},{137,11,744},{134,0,926},{6,10,517},{7,10,1159},{10,10,621},{139,10,192} +,{137,0,827},{8,0,194},{136,0,756},{10,10,223},{139,10,645},{7,10,64},{136,10, +245},{4,11,399},{5,11,119},{5,11,494},{7,11,751},{137,11,556},{132,0,808},{135,0 +,22},{7,10,1763},{140,10,310},{5,0,639},{7,0,1249},{11,0,896},{134,11,584},{134, +0,1614},{135,0,860},{135,11,1121},{5,10,129},{6,10,61},{135,10,947},{4,0,102},{7 +,0,815},{7,0,1699},{139,0,964},{13,10,505},{141,10,506},{139,10,1000},{132,11, +679},{132,0,899},{132,0,569},{5,11,694},{137,11,714},{136,0,795},{6,0,2045},{139 +,11,7},{6,0,52},{9,0,104},{9,0,559},{12,0,308},{147,0,87},{4,0,301},{132,0,604}, +{133,10,637},{136,0,779},{5,11,143},{5,11,769},{6,11,1760},{7,11,682},{7,11,1992 +},{136,11,736},{137,10,590},{147,0,32},{137,11,527},{5,10,280},{135,10,1226},{ +134,0,494},{6,0,677},{6,0,682},{134,0,1044},{133,10,281},{135,10,1064},{7,0,508} +,{133,11,860},{6,11,422},{7,11,0},{7,11,1544},{9,11,577},{11,11,990},{12,11,141} +,{12,11,453},{13,11,47},{141,11,266},{134,0,1014},{5,11,515},{137,11,131},{134,0 +,957},{132,11,646},{6,0,310},{7,0,1849},{8,0,72},{8,0,272},{8,0,431},{9,0,12},{9 +,0,376},{10,0,563},{10,0,630},{10,0,796},{10,0,810},{11,0,367},{11,0,599},{11,0, +686},{140,0,672},{7,0,570},{4,11,396},{7,10,120},{7,11,728},{8,10,489},{9,11,117 +},{9,10,319},{10,10,820},{11,10,1004},{12,10,379},{12,10,679},{13,10,117},{13,11 +,202},{13,10,412},{14,10,25},{15,10,52},{15,10,161},{16,10,47},{20,11,51},{149, +10,2},{6,11,121},{6,11,124},{6,11,357},{7,11,1138},{7,11,1295},{8,11,162},{139, +11,655},{8,0,449},{4,10,937},{5,10,801},{136,11,449},{139,11,958},{6,0,181},{7,0 +,537},{8,0,64},{9,0,127},{10,0,496},{12,0,510},{141,0,384},{138,11,253},{4,0,244 +},{135,0,233},{133,11,237},{132,10,365},{6,0,1650},{10,0,702},{139,0,245},{5,10, +7},{139,10,774},{13,0,463},{20,0,49},{13,11,463},{148,11,49},{4,10,734},{5,10, +662},{134,10,430},{4,10,746},{135,10,1090},{5,10,360},{136,10,237},{137,0,338},{ +143,11,10},{7,11,571},{138,11,366},{134,0,1279},{9,11,513},{10,11,22},{10,11,39} +,{12,11,122},{140,11,187},{133,0,896},{146,0,178},{134,0,695},{137,0,808},{134, +11,587},{7,11,107},{7,11,838},{8,11,550},{138,11,401},{7,0,1117},{136,0,539},{4, +10,277},{5,10,608},{6,10,493},{7,10,457},{140,10,384},{133,11,768},{12,0,257},{7 +,10,27},{135,10,316},{140,0,1003},{4,0,207},{5,0,586},{5,0,676},{6,0,448},{8,0, +244},{11,0,1},{13,0,3},{16,0,54},{17,0,4},{18,0,13},{133,10,552},{4,10,401},{137 +,10,264},{5,0,516},{7,0,1883},{135,11,1883},{12,0,960},{132,11,894},{5,0,4},{5,0 +,810},{6,0,13},{6,0,538},{6,0,1690},{6,0,1726},{7,0,499},{7,0,1819},{8,0,148},{8 +,0,696},{8,0,791},{12,0,125},{143,0,9},{135,0,1268},{11,0,30},{14,0,315},{9,10, +543},{10,10,524},{12,10,524},{16,10,18},{20,10,26},{148,10,65},{6,0,748},{4,10, +205},{5,10,623},{7,10,104},{136,10,519},{11,0,542},{139,0,852},{140,0,6},{132,0, +848},{7,0,1385},{11,0,582},{11,0,650},{11,0,901},{11,0,949},{12,0,232},{12,0,236 +},{13,0,413},{13,0,501},{18,0,116},{7,10,579},{9,10,41},{9,10,244},{9,10,669},{ +10,10,5},{11,10,861},{11,10,951},{139,10,980},{4,0,945},{6,0,1811},{6,0,1845},{6 +,0,1853},{6,0,1858},{8,0,862},{12,0,782},{12,0,788},{18,0,160},{148,0,117},{132, +10,717},{4,0,925},{5,0,803},{8,0,698},{138,0,828},{134,0,1416},{132,0,610},{139, +0,992},{6,0,878},{134,0,1477},{135,0,1847},{138,11,531},{137,11,539},{134,11,272 +},{133,0,383},{134,0,1404},{132,10,489},{4,11,9},{5,11,128},{7,11,368},{11,11, +480},{148,11,3},{136,0,986},{9,0,660},{138,0,347},{135,10,892},{136,11,682},{7,0 +,572},{9,0,592},{11,0,680},{12,0,356},{140,0,550},{7,0,1411},{138,11,527},{4,11, +2},{7,11,545},{135,11,894},{137,10,473},{11,0,64},{7,11,481},{7,10,819},{9,10,26 +},{9,10,392},{9,11,792},{10,10,152},{10,10,226},{12,10,276},{12,10,426},{12,10, +589},{13,10,460},{15,10,97},{19,10,48},{148,10,104},{135,10,51},{136,11,445},{ +136,11,646},{135,0,606},{132,10,674},{6,0,1829},{134,0,1830},{132,10,770},{5,10, +79},{7,10,1027},{7,10,1477},{139,10,52},{5,11,530},{142,11,113},{134,10,1666},{7 +,0,748},{139,0,700},{134,10,195},{133,10,789},{9,0,87},{10,0,365},{4,10,251},{4, +10,688},{7,10,513},{135,10,1284},{136,11,111},{133,0,127},{6,0,198},{140,0,83},{ +133,11,556},{133,10,889},{4,10,160},{5,10,330},{7,10,1434},{136,10,174},{5,0,276 +},{6,0,55},{7,0,1369},{138,0,864},{8,11,16},{140,11,568},{6,0,1752},{136,0,726}, +{135,0,1066},{133,0,764},{6,11,186},{137,11,426},{11,0,683},{139,11,683},{6,0, +309},{7,0,331},{138,0,550},{133,10,374},{6,0,1212},{6,0,1852},{7,0,1062},{8,0, +874},{8,0,882},{138,0,936},{132,11,585},{134,0,1364},{7,0,986},{133,10,731},{6,0 +,723},{6,0,1408},{138,0,381},{135,0,1573},{134,0,1025},{4,10,626},{5,10,642},{6, +10,425},{10,10,202},{139,10,141},{4,11,93},{5,11,252},{6,11,229},{7,11,291},{9, +11,550},{139,11,644},{137,11,749},{137,11,162},{132,11,381},{135,0,1559},{6,0, +194},{7,0,133},{10,0,493},{10,0,570},{139,0,664},{5,0,24},{5,0,569},{6,0,3},{6,0 +,119},{6,0,143},{6,0,440},{7,0,295},{7,0,599},{7,0,1686},{7,0,1854},{8,0,424},{9 +,0,43},{9,0,584},{9,0,760},{10,0,148},{10,0,328},{11,0,159},{11,0,253},{11,0,506 +},{12,0,487},{140,0,531},{6,0,661},{134,0,1517},{136,10,835},{151,10,17},{5,0,14 +},{5,0,892},{6,0,283},{7,0,234},{136,0,537},{139,0,541},{4,0,126},{8,0,635},{147 +,0,34},{4,0,316},{4,0,495},{135,0,1561},{4,11,187},{5,11,184},{5,11,690},{7,11, +1869},{138,11,756},{139,11,783},{4,0,998},{137,0,861},{136,0,1009},{139,11,292}, +{5,11,21},{6,11,77},{6,11,157},{7,11,974},{7,11,1301},{7,11,1339},{7,11,1490},{7 +,11,1873},{137,11,628},{7,11,1283},{9,11,227},{9,11,499},{10,11,341},{11,11,325} +,{11,11,408},{14,11,180},{15,11,144},{18,11,47},{147,11,49},{4,0,64},{5,0,352},{ +5,0,720},{6,0,368},{139,0,359},{5,10,384},{8,10,455},{140,10,48},{5,10,264},{134 +,10,184},{7,0,1577},{10,0,304},{10,0,549},{12,0,365},{13,0,220},{13,0,240},{142, +0,33},{134,0,1107},{134,0,929},{135,0,1142},{6,0,175},{137,0,289},{5,0,432},{133 +,0,913},{6,0,279},{7,0,219},{5,10,633},{135,10,1323},{7,0,785},{7,10,359},{8,10, +243},{140,10,175},{139,0,595},{132,10,105},{8,11,398},{9,11,681},{139,11,632},{ +140,0,80},{5,0,931},{134,0,1698},{142,11,241},{134,11,20},{134,0,1323},{11,0,526 +},{11,0,939},{141,0,290},{5,0,774},{6,0,780},{6,0,1637},{6,0,1686},{6,0,1751},{8 +,0,559},{141,0,109},{141,0,127},{7,0,1167},{11,0,934},{13,0,391},{17,0,76},{135, +11,709},{135,0,963},{6,0,260},{135,0,1484},{134,0,573},{4,10,758},{139,11,941},{ +135,10,1649},{145,11,36},{4,0,292},{137,0,580},{4,0,736},{5,0,871},{6,0,1689},{ +135,0,1944},{7,11,945},{11,11,713},{139,11,744},{134,0,1164},{135,11,937},{6,0, +1922},{9,0,982},{15,0,173},{15,0,178},{15,0,200},{18,0,189},{18,0,207},{21,0,47} +,{135,11,1652},{7,0,1695},{139,10,128},{6,0,63},{135,0,920},{133,0,793},{143,11, +134},{133,10,918},{5,0,67},{6,0,62},{6,0,374},{135,0,1391},{9,0,790},{12,0,47},{ +4,11,579},{5,11,226},{5,11,323},{135,11,960},{10,11,784},{141,11,191},{4,0,391}, +{135,0,1169},{137,0,443},{13,11,232},{146,11,35},{132,10,340},{132,0,271},{137, +11,313},{5,11,973},{137,11,659},{134,0,1140},{6,11,135},{135,11,1176},{4,0,253}, +{5,0,544},{7,0,300},{137,0,340},{7,0,897},{5,10,985},{7,10,509},{145,10,96},{138 +,11,735},{135,10,1919},{138,0,890},{5,0,818},{134,0,1122},{5,0,53},{5,0,541},{6, +0,94},{6,0,499},{7,0,230},{139,0,321},{4,0,920},{5,0,25},{5,0,790},{6,0,457},{7, +0,853},{8,0,788},{142,11,31},{132,10,247},{135,11,314},{132,0,468},{7,0,243},{6, +10,337},{7,10,494},{8,10,27},{8,10,599},{138,10,153},{4,10,184},{5,10,390},{7,10 +,618},{7,10,1456},{139,10,710},{134,0,870},{134,0,1238},{134,0,1765},{10,0,853}, +{10,0,943},{14,0,437},{14,0,439},{14,0,443},{14,0,446},{14,0,452},{14,0,469},{14 +,0,471},{14,0,473},{16,0,93},{16,0,102},{16,0,110},{148,0,121},{4,0,605},{7,0, +518},{7,0,1282},{7,0,1918},{10,0,180},{139,0,218},{133,0,822},{4,0,634},{11,0, +916},{142,0,419},{6,11,281},{7,11,6},{8,11,282},{8,11,480},{8,11,499},{9,11,198} +,{10,11,143},{10,11,169},{10,11,211},{10,11,417},{10,11,574},{11,11,147},{11,11, +395},{12,11,75},{12,11,407},{12,11,608},{13,11,500},{142,11,251},{134,0,898},{6, +0,36},{7,0,658},{8,0,454},{150,11,48},{133,11,674},{135,11,1776},{4,11,419},{10, +10,227},{11,10,497},{11,10,709},{140,10,415},{6,10,360},{7,10,1664},{136,10,478} +,{137,0,806},{12,11,508},{14,11,102},{14,11,226},{144,11,57},{135,11,1123},{4,11 +,138},{7,11,1012},{7,11,1280},{137,11,76},{5,11,29},{140,11,638},{136,10,699},{ +134,0,1326},{132,0,104},{135,11,735},{132,10,739},{134,0,1331},{7,0,260},{135,11 +,260},{135,11,1063},{7,0,45},{9,0,542},{9,0,566},{10,0,728},{137,10,869},{4,10, +67},{5,10,422},{7,10,1037},{7,10,1289},{7,10,1555},{9,10,741},{145,10,108},{139, +0,263},{134,0,1516},{14,0,146},{15,0,42},{16,0,23},{17,0,86},{146,0,17},{138,0, +468},{136,0,1005},{4,11,17},{5,11,23},{7,11,995},{11,11,383},{11,11,437},{12,11, +460},{140,11,532},{7,0,87},{142,0,288},{138,10,96},{135,11,626},{144,10,26},{7,0 +,988},{7,0,1939},{9,0,64},{9,0,502},{12,0,22},{12,0,34},{13,0,12},{13,0,234},{ +147,0,77},{13,0,133},{8,10,203},{11,10,823},{11,10,846},{12,10,482},{13,10,277}, +{13,10,302},{13,10,464},{14,10,205},{142,10,221},{4,10,449},{133,10,718},{135,0, +141},{6,0,1842},{136,0,872},{8,11,70},{12,11,171},{141,11,272},{4,10,355},{6,10, +311},{9,10,256},{138,10,404},{132,0,619},{137,0,261},{10,11,233},{10,10,758},{ +139,11,76},{5,0,246},{8,0,189},{9,0,355},{9,0,512},{10,0,124},{10,0,453},{11,0, +143},{11,0,416},{11,0,859},{141,0,341},{134,11,442},{133,10,827},{5,10,64},{140, +10,581},{4,10,442},{7,10,1047},{7,10,1352},{135,10,1643},{134,11,1709},{5,0,678} +,{6,0,305},{7,0,775},{7,0,1065},{133,10,977},{11,11,69},{12,11,105},{12,11,117}, +{13,11,213},{14,11,13},{14,11,62},{14,11,177},{14,11,421},{15,11,19},{146,11,141 +},{137,11,309},{5,0,35},{7,0,862},{7,0,1886},{138,0,179},{136,0,285},{132,0,517} +,{7,11,976},{9,11,146},{10,11,206},{10,11,596},{13,11,218},{142,11,153},{132,10, +254},{6,0,214},{12,0,540},{4,10,275},{7,10,1219},{140,10,376},{8,0,667},{11,0, +403},{146,0,83},{12,0,74},{10,11,648},{11,11,671},{143,11,46},{135,0,125},{134, +10,1753},{133,0,761},{6,0,912},{4,11,518},{6,10,369},{6,10,502},{7,10,1036},{7, +11,1136},{8,10,348},{9,10,452},{10,10,26},{11,10,224},{11,10,387},{11,10,772},{ +12,10,95},{12,10,629},{13,10,195},{13,10,207},{13,10,241},{14,10,260},{14,10,270 +},{143,10,140},{10,0,131},{140,0,72},{132,10,269},{5,10,480},{7,10,532},{7,10, +1197},{7,10,1358},{8,10,291},{11,10,349},{142,10,396},{8,11,689},{137,11,863},{8 +,0,333},{138,0,182},{4,11,18},{7,11,145},{7,11,444},{7,11,1278},{8,11,49},{8,11, +400},{9,11,71},{9,11,250},{10,11,459},{12,11,160},{144,11,24},{14,11,35},{142,11 +,191},{135,11,1864},{135,0,1338},{148,10,15},{14,0,94},{15,0,65},{16,0,4},{16,0, +77},{16,0,80},{145,0,5},{12,11,82},{143,11,36},{133,11,1010},{133,0,449},{133,0, +646},{7,0,86},{8,0,103},{135,10,657},{7,0,2028},{138,0,641},{136,10,533},{134,0, +1},{139,11,970},{5,11,87},{7,11,313},{7,11,1103},{10,11,112},{10,11,582},{11,11, +389},{11,11,813},{12,11,385},{13,11,286},{14,11,124},{146,11,108},{6,0,869},{132 +,11,267},{6,0,277},{7,0,1274},{7,0,1386},{146,0,87},{6,0,187},{7,0,39},{7,0,1203 +},{8,0,380},{14,0,117},{149,0,28},{4,10,211},{4,10,332},{5,10,335},{6,10,238},{7 +,10,269},{7,10,811},{7,10,1797},{8,10,836},{9,10,507},{141,10,242},{4,0,785},{5, +0,368},{6,0,297},{7,0,793},{139,0,938},{7,0,464},{8,0,558},{11,0,105},{12,0,231} +,{14,0,386},{15,0,102},{148,0,75},{133,10,1009},{8,0,877},{140,0,731},{139,11, +289},{10,11,249},{139,11,209},{132,11,561},{134,0,1608},{132,11,760},{134,0,1429 +},{9,11,154},{140,11,485},{5,10,228},{6,10,203},{7,10,156},{8,10,347},{137,10, +265},{7,0,1010},{11,0,733},{11,0,759},{13,0,34},{14,0,427},{146,0,45},{7,10,1131 +},{135,10,1468},{136,11,255},{7,0,1656},{9,0,369},{10,0,338},{10,0,490},{11,0, +154},{11,0,545},{11,0,775},{13,0,77},{141,0,274},{133,11,621},{134,0,1038},{4,11 +,368},{135,11,641},{6,0,2010},{8,0,979},{8,0,985},{10,0,951},{138,0,1011},{134,0 +,1005},{19,0,121},{5,10,291},{5,10,318},{7,10,765},{9,10,389},{140,10,548},{5,0, +20},{6,0,298},{7,0,659},{137,0,219},{7,0,1440},{11,0,854},{11,0,872},{11,0,921}, +{12,0,551},{13,0,472},{142,0,367},{5,0,490},{6,0,615},{6,0,620},{135,0,683},{6,0 +,1070},{134,0,1597},{139,0,522},{132,0,439},{136,0,669},{6,0,766},{6,0,1143},{6, +0,1245},{10,10,525},{139,10,82},{9,11,92},{147,11,91},{6,0,668},{134,0,1218},{6, +11,525},{9,11,876},{140,11,284},{132,0,233},{136,0,547},{132,10,422},{5,10,355}, +{145,10,0},{6,11,300},{135,11,1515},{4,0,482},{137,10,905},{4,0,886},{7,0,346},{ +133,11,594},{133,10,865},{5,10,914},{134,10,1625},{135,0,334},{5,0,795},{6,0, +1741},{133,10,234},{135,10,1383},{6,11,1641},{136,11,820},{135,0,371},{7,11,1313 +},{138,11,660},{135,10,1312},{135,0,622},{7,0,625},{135,0,1750},{135,0,339},{4,0 +,203},{135,0,1936},{15,0,29},{16,0,38},{15,11,29},{144,11,38},{5,0,338},{135,0, +1256},{135,10,1493},{10,0,130},{6,10,421},{7,10,61},{7,10,1540},{138,10,501},{6, +11,389},{7,11,149},{9,11,142},{138,11,94},{137,10,341},{11,0,678},{12,0,307},{ +142,10,98},{6,11,8},{7,11,1881},{136,11,91},{135,0,2044},{6,0,770},{6,0,802},{6, +0,812},{7,0,311},{9,0,308},{12,0,255},{6,10,102},{7,10,72},{15,10,142},{147,10, +67},{151,10,30},{135,10,823},{135,0,1266},{135,11,1746},{135,10,1870},{4,0,400}, +{5,0,267},{135,0,232},{7,11,24},{11,11,542},{139,11,852},{135,11,1739},{4,11,503 +},{135,11,1661},{5,11,130},{7,11,1314},{9,11,610},{10,11,718},{11,11,601},{11,11 +,819},{11,11,946},{140,11,536},{10,11,149},{11,11,280},{142,11,336},{7,0,739},{ +11,0,690},{7,11,1946},{8,10,48},{8,10,88},{8,10,582},{8,10,681},{9,10,373},{9,10 +,864},{11,10,157},{11,10,843},{148,10,27},{134,0,990},{4,10,88},{5,10,137},{5,10 +,174},{5,10,777},{6,10,1664},{6,10,1725},{7,10,77},{7,10,426},{7,10,1317},{7,10, +1355},{8,10,126},{8,10,563},{9,10,523},{9,10,750},{10,10,310},{10,10,836},{11,10 +,42},{11,10,318},{11,10,731},{12,10,68},{12,10,92},{12,10,507},{12,10,692},{13, +10,81},{13,10,238},{13,10,374},{14,10,436},{18,10,138},{19,10,78},{19,10,111},{ +20,10,55},{20,10,77},{148,10,92},{141,10,418},{7,0,1831},{132,10,938},{6,0,776}, +{134,0,915},{138,10,351},{5,11,348},{6,11,522},{6,10,1668},{7,10,1499},{8,10,117 +},{9,10,314},{138,10,174},{135,10,707},{132,0,613},{133,10,403},{132,11,392},{5, +11,433},{9,11,633},{139,11,629},{133,0,763},{132,0,878},{132,0,977},{132,0,100}, +{6,0,463},{4,10,44},{5,10,311},{7,10,639},{7,10,762},{7,10,1827},{9,10,8},{9,10, +462},{148,10,83},{134,11,234},{4,10,346},{7,10,115},{9,10,180},{9,10,456},{138, +10,363},{5,0,362},{5,0,443},{6,0,318},{7,0,1019},{139,0,623},{5,0,463},{8,0,296} +,{7,11,140},{7,11,1950},{8,11,680},{11,11,817},{147,11,88},{7,11,1222},{138,11, +386},{142,0,137},{132,0,454},{7,0,1914},{6,11,5},{7,10,1051},{9,10,545},{11,11, +249},{12,11,313},{16,11,66},{145,11,26},{135,0,1527},{145,0,58},{148,11,59},{5,0 +,48},{5,0,404},{6,0,557},{7,0,458},{8,0,597},{10,0,455},{10,0,606},{11,0,49},{11 +,0,548},{12,0,476},{13,0,18},{141,0,450},{5,11,963},{134,11,1773},{133,0,729},{ +138,11,586},{5,0,442},{135,0,1984},{134,0,449},{144,0,40},{4,0,853},{7,11,180},{ +8,11,509},{136,11,792},{6,10,185},{7,10,1899},{9,10,875},{139,10,673},{134,11, +524},{12,0,227},{4,10,327},{5,10,478},{7,10,1332},{136,10,753},{6,0,1491},{5,10, +1020},{133,10,1022},{4,10,103},{133,10,401},{132,11,931},{4,10,499},{135,10,1421 +},{5,0,55},{7,0,376},{140,0,161},{133,0,450},{6,0,1174},{134,0,1562},{10,0,62},{ +13,0,400},{135,11,1837},{140,0,207},{135,0,869},{4,11,773},{5,11,618},{137,11, +756},{132,10,96},{4,0,213},{7,0,223},{8,0,80},{135,10,968},{4,11,90},{5,11,337}, +{5,11,545},{7,11,754},{9,11,186},{10,11,72},{10,11,782},{11,11,513},{11,11,577}, +{11,11,610},{11,11,889},{11,11,961},{12,11,354},{12,11,362},{12,11,461},{12,11, +595},{13,11,79},{143,11,121},{7,0,381},{7,0,806},{7,0,820},{8,0,354},{8,0,437},{ +8,0,787},{9,0,657},{10,0,58},{10,0,339},{10,0,749},{11,0,914},{12,0,162},{13,0, +75},{14,0,106},{14,0,198},{14,0,320},{14,0,413},{146,0,43},{136,0,747},{136,0, +954},{134,0,1073},{135,0,556},{7,11,151},{9,11,329},{139,11,254},{5,0,692},{134, +0,1395},{6,10,563},{137,10,224},{134,0,191},{132,0,804},{9,11,187},{10,11,36},{ +17,11,44},{146,11,64},{7,11,165},{7,11,919},{136,11,517},{4,11,506},{5,11,295},{ +7,11,1680},{15,11,14},{144,11,5},{4,0,706},{6,0,162},{7,0,1960},{136,0,831},{135 +,11,1376},{7,11,987},{9,11,688},{10,11,522},{11,11,788},{140,11,566},{150,0,35}, +{138,0,426},{135,0,1235},{135,11,1741},{7,11,389},{7,11,700},{7,11,940},{8,11, +514},{9,11,116},{9,11,535},{10,11,118},{11,11,107},{11,11,148},{11,11,922},{12, +11,254},{12,11,421},{142,11,238},{134,0,1234},{132,11,743},{4,10,910},{5,10,832} +,{135,11,1335},{141,0,96},{135,11,185},{146,0,149},{4,0,204},{137,0,902},{4,11, +784},{133,11,745},{136,0,833},{136,0,949},{7,0,366},{9,0,287},{12,0,199},{12,0, +556},{12,0,577},{5,11,81},{7,11,146},{7,11,1342},{7,11,1446},{8,11,53},{8,11,561 +},{8,11,694},{8,11,754},{9,11,97},{9,11,115},{9,11,894},{10,11,462},{10,11,813}, +{11,11,230},{11,11,657},{11,11,699},{11,11,748},{12,11,119},{12,11,200},{12,11, +283},{14,11,273},{145,11,15},{5,11,408},{137,11,747},{9,11,498},{140,11,181},{6, +0,2020},{136,0,992},{5,0,356},{135,0,224},{134,0,784},{7,0,630},{9,0,567},{11,0, +150},{11,0,444},{13,0,119},{8,10,528},{137,10,348},{134,0,539},{4,10,20},{133,10 +,616},{142,0,27},{7,11,30},{8,11,86},{8,11,315},{8,11,700},{9,11,576},{9,11,858} +,{11,11,310},{11,11,888},{11,11,904},{12,11,361},{141,11,248},{138,11,839},{134, +0,755},{134,0,1063},{7,10,1091},{135,10,1765},{134,11,428},{7,11,524},{8,11,169} +,{8,11,234},{9,11,480},{138,11,646},{139,0,814},{7,11,1462},{139,11,659},{4,10, +26},{5,10,429},{6,10,245},{7,10,704},{7,10,1379},{135,10,1474},{7,11,1205},{138, +11,637},{139,11,803},{132,10,621},{136,0,987},{4,11,266},{8,11,4},{9,11,39},{10, +11,166},{11,11,918},{12,11,635},{20,11,10},{22,11,27},{150,11,43},{4,0,235},{135 +,0,255},{4,0,194},{5,0,584},{6,0,384},{7,0,583},{10,0,761},{11,0,760},{139,0,851 +},{133,10,542},{134,0,1086},{133,10,868},{8,0,1016},{136,0,1018},{7,0,1396},{7, +11,1396},{136,10,433},{135,10,1495},{138,10,215},{141,10,124},{7,11,157},{8,11, +279},{9,11,759},{16,11,31},{16,11,39},{16,11,75},{18,11,24},{20,11,42},{152,11,1 +},{5,0,562},{134,11,604},{134,0,913},{5,0,191},{137,0,271},{4,0,470},{6,0,153},{ +7,0,1503},{7,0,1923},{10,0,701},{11,0,132},{11,0,227},{11,0,320},{11,0,436},{11, +0,525},{11,0,855},{11,0,873},{12,0,41},{12,0,286},{13,0,103},{13,0,284},{14,0, +255},{14,0,262},{15,0,117},{143,0,127},{7,0,475},{12,0,45},{147,10,112},{132,11, +567},{137,11,859},{6,0,713},{6,0,969},{6,0,1290},{134,0,1551},{133,0,327},{6,0, +552},{6,0,1292},{7,0,1754},{137,0,604},{4,0,223},{6,0,359},{11,0,3},{13,0,108},{ +14,0,89},{16,0,22},{5,11,762},{7,11,1880},{9,11,680},{139,11,798},{5,0,80},{6,0, +405},{7,0,403},{7,0,1502},{8,0,456},{9,0,487},{9,0,853},{9,0,889},{10,0,309},{11 +,0,721},{11,0,994},{12,0,430},{141,0,165},{133,11,298},{132,10,647},{134,0,2016} +,{18,10,10},{146,11,10},{4,0,453},{5,0,887},{6,0,535},{8,0,6},{8,0,543},{136,0, +826},{136,0,975},{10,0,961},{138,0,962},{138,10,220},{6,0,1891},{6,0,1893},{9,0, +916},{9,0,965},{9,0,972},{12,0,801},{12,0,859},{12,0,883},{15,0,226},{149,0,51}, +{132,10,109},{135,11,267},{7,11,92},{7,11,182},{8,11,453},{9,11,204},{11,11,950} +,{12,11,94},{12,11,644},{16,11,20},{16,11,70},{16,11,90},{147,11,55},{134,10, +1746},{6,11,71},{7,11,845},{7,11,1308},{8,11,160},{137,11,318},{5,0,101},{6,0,88 +},{7,0,263},{7,0,628},{7,0,1677},{8,0,349},{9,0,100},{10,0,677},{14,0,169},{14,0 +,302},{14,0,313},{15,0,48},{15,0,84},{7,11,237},{8,11,664},{9,11,42},{9,11,266}, +{9,11,380},{9,11,645},{10,11,177},{138,11,276},{138,11,69},{4,0,310},{7,0,708},{ +7,0,996},{9,0,795},{10,0,390},{10,0,733},{11,0,451},{12,0,249},{14,0,115},{14,0, +286},{143,0,100},{5,0,587},{4,10,40},{10,10,67},{11,10,117},{11,10,768},{139,10, +935},{6,0,1942},{7,0,512},{136,0,983},{7,10,992},{8,10,301},{9,10,722},{12,10,63 +},{13,10,29},{14,10,161},{143,10,18},{136,11,76},{139,10,923},{134,0,645},{134,0 +,851},{4,0,498},{132,11,293},{7,0,217},{8,0,140},{10,0,610},{14,11,352},{17,11, +53},{18,11,146},{18,11,152},{19,11,11},{150,11,54},{134,0,1448},{138,11,841},{ +133,0,905},{4,11,605},{7,11,518},{7,11,1282},{7,11,1918},{10,11,180},{139,11,218 +},{139,11,917},{135,10,825},{140,10,328},{4,0,456},{7,0,105},{7,0,358},{7,0,1637 +},{8,0,643},{139,0,483},{134,0,792},{6,11,96},{135,11,1426},{137,11,691},{4,11, +651},{133,11,289},{7,11,688},{8,11,35},{9,11,511},{10,11,767},{147,11,118},{150, +0,56},{5,0,243},{5,0,535},{6,10,204},{10,10,320},{10,10,583},{13,10,502},{14,10, +72},{14,10,274},{14,10,312},{14,10,344},{15,10,159},{16,10,62},{16,10,69},{17,10 +,30},{18,10,42},{18,10,53},{18,10,84},{18,10,140},{19,10,68},{19,10,85},{20,10,5 +},{20,10,45},{20,10,101},{22,10,7},{150,10,20},{4,10,558},{6,10,390},{7,10,162}, +{7,10,689},{9,10,360},{138,10,653},{146,11,23},{135,0,1748},{5,10,856},{6,10, +1672},{6,10,1757},{134,10,1781},{5,0,539},{5,0,754},{6,0,876},{132,11,704},{135, +11,1078},{5,10,92},{10,10,736},{140,10,102},{17,0,91},{5,10,590},{137,10,213},{ +134,0,1565},{6,0,91},{135,0,435},{4,0,939},{140,0,792},{134,0,1399},{4,0,16},{5, +0,316},{5,0,842},{6,0,370},{6,0,1778},{8,0,166},{11,0,812},{12,0,206},{12,0,351} +,{14,0,418},{16,0,15},{16,0,34},{18,0,3},{19,0,3},{19,0,7},{20,0,4},{21,0,21},{4 +,11,720},{133,11,306},{144,0,95},{133,11,431},{132,11,234},{135,0,551},{4,0,999} +,{6,0,1966},{134,0,2042},{7,0,619},{10,0,547},{11,0,122},{12,0,601},{15,0,7},{ +148,0,20},{5,11,464},{6,11,236},{7,11,276},{7,11,696},{7,11,914},{7,11,1108},{7, +11,1448},{9,11,15},{9,11,564},{10,11,14},{12,11,565},{13,11,449},{14,11,53},{15, +11,13},{16,11,64},{145,11,41},{6,0,884},{6,0,1019},{134,0,1150},{6,11,1767},{12, +11,194},{145,11,107},{136,10,503},{133,11,840},{7,0,671},{134,10,466},{132,0,888 +},{4,0,149},{138,0,368},{4,0,154},{7,0,1134},{136,0,105},{135,0,983},{9,11,642}, +{11,11,236},{142,11,193},{4,0,31},{6,0,429},{7,0,962},{9,0,458},{139,0,691},{6,0 +,643},{134,0,1102},{132,0,312},{4,11,68},{5,11,634},{6,11,386},{7,11,794},{8,11, +273},{9,11,563},{10,11,105},{10,11,171},{11,11,94},{139,11,354},{133,0,740},{135 +,0,1642},{4,11,95},{7,11,416},{8,11,211},{139,11,830},{132,0,236},{138,10,241},{ +7,11,731},{13,11,20},{143,11,11},{5,0,836},{5,0,857},{6,0,1680},{135,0,59},{10,0 +,68},{11,0,494},{152,11,6},{4,0,81},{139,0,867},{135,0,795},{133,11,689},{4,0, +1001},{5,0,282},{6,0,1932},{6,0,1977},{6,0,1987},{6,0,1992},{8,0,650},{8,0,919}, +{8,0,920},{8,0,923},{8,0,926},{8,0,927},{8,0,931},{8,0,939},{8,0,947},{8,0,956}, +{8,0,997},{9,0,907},{10,0,950},{10,0,953},{10,0,954},{10,0,956},{10,0,958},{10,0 +,959},{10,0,964},{10,0,970},{10,0,972},{10,0,973},{10,0,975},{10,0,976},{10,0, +980},{10,0,981},{10,0,984},{10,0,988},{10,0,990},{10,0,995},{10,0,999},{10,0, +1002},{10,0,1003},{10,0,1005},{10,0,1006},{10,0,1008},{10,0,1009},{10,0,1012},{ +10,0,1014},{10,0,1015},{10,0,1019},{10,0,1020},{10,0,1022},{12,0,959},{12,0,961} +,{12,0,962},{12,0,963},{12,0,964},{12,0,965},{12,0,967},{12,0,968},{12,0,969},{ +12,0,970},{12,0,971},{12,0,972},{12,0,973},{12,0,974},{12,0,975},{12,0,976},{12, +0,977},{12,0,979},{12,0,981},{12,0,982},{12,0,983},{12,0,984},{12,0,985},{12,0, +986},{12,0,987},{12,0,989},{12,0,990},{12,0,992},{12,0,993},{12,0,995},{12,0,998 +},{12,0,999},{12,0,1000},{12,0,1001},{12,0,1002},{12,0,1004},{12,0,1005},{12,0, +1006},{12,0,1007},{12,0,1008},{12,0,1009},{12,0,1010},{12,0,1011},{12,0,1012},{ +12,0,1014},{12,0,1015},{12,0,1016},{12,0,1017},{12,0,1018},{12,0,1019},{12,0, +1022},{12,0,1023},{14,0,475},{14,0,477},{14,0,478},{14,0,479},{14,0,480},{14,0, +482},{14,0,483},{14,0,484},{14,0,485},{14,0,486},{14,0,487},{14,0,488},{14,0,489 +},{14,0,490},{14,0,491},{14,0,492},{14,0,493},{14,0,494},{14,0,495},{14,0,496},{ +14,0,497},{14,0,498},{14,0,499},{14,0,500},{14,0,501},{14,0,502},{14,0,503},{14, +0,504},{14,0,506},{14,0,507},{14,0,508},{14,0,509},{14,0,510},{14,0,511},{16,0, +113},{16,0,114},{16,0,115},{16,0,117},{16,0,118},{16,0,119},{16,0,121},{16,0,122 +},{16,0,123},{16,0,124},{16,0,125},{16,0,126},{16,0,127},{18,0,242},{18,0,243},{ +18,0,244},{18,0,245},{18,0,248},{18,0,249},{18,0,250},{18,0,251},{18,0,252},{18, +0,253},{18,0,254},{18,0,255},{20,0,125},{20,0,126},{148,0,127},{7,11,1717},{7,11 +,1769},{138,11,546},{7,11,1127},{7,11,1572},{10,11,297},{10,11,422},{11,11,764}, +{11,11,810},{12,11,264},{13,11,102},{13,11,300},{13,11,484},{14,11,147},{14,11, +229},{17,11,71},{18,11,118},{147,11,120},{6,0,1148},{134,0,1586},{132,0,775},{ +135,10,954},{133,11,864},{133,11,928},{138,11,189},{135,10,1958},{6,10,549},{8, +10,34},{8,10,283},{9,10,165},{138,10,475},{5,10,652},{5,10,701},{135,10,449},{ +135,11,695},{4,10,655},{7,10,850},{17,10,75},{146,10,137},{140,11,682},{133,11, +523},{8,0,970},{136,10,670},{136,11,555},{7,11,76},{8,11,44},{9,11,884},{10,11, +580},{11,11,399},{11,11,894},{15,11,122},{18,11,144},{147,11,61},{6,10,159},{6, +10,364},{7,10,516},{7,10,1439},{137,10,518},{4,0,71},{5,0,376},{7,0,119},{138,0, +665},{141,10,151},{11,0,827},{14,0,34},{143,0,148},{133,11,518},{4,0,479},{135, +11,1787},{135,11,1852},{135,10,993},{7,0,607},{136,0,99},{134,0,1960},{132,0,793 +},{4,0,41},{5,0,74},{7,0,1627},{11,0,871},{140,0,619},{7,0,94},{11,0,329},{11,0, +965},{12,0,241},{14,0,354},{15,0,22},{148,0,63},{7,10,501},{9,10,111},{10,10,141 +},{11,10,332},{13,10,43},{13,10,429},{14,10,130},{14,10,415},{145,10,102},{9,0, +209},{137,0,300},{134,0,1497},{138,11,255},{4,11,934},{5,11,138},{136,11,610},{ +133,0,98},{6,0,1316},{10,11,804},{138,11,832},{8,11,96},{9,11,36},{10,11,607},{ +11,11,423},{11,11,442},{12,11,309},{14,11,199},{15,11,90},{145,11,110},{132,0, +463},{5,10,149},{136,10,233},{133,10,935},{4,11,652},{8,11,320},{9,11,13},{9,11, +398},{9,11,727},{10,11,75},{10,11,184},{10,11,230},{10,11,564},{10,11,569},{11, +11,973},{12,11,70},{12,11,189},{13,11,57},{13,11,257},{22,11,6},{150,11,16},{142 +,0,291},{12,10,582},{146,10,131},{136,10,801},{133,0,984},{145,11,116},{4,11,692 +},{133,11,321},{4,0,182},{6,0,205},{135,0,220},{4,0,42},{9,0,205},{9,0,786},{138 +,0,659},{6,0,801},{11,11,130},{140,11,609},{132,0,635},{5,11,345},{135,11,1016}, +{139,0,533},{132,0,371},{4,0,272},{135,0,836},{6,0,1282},{135,11,1100},{5,0,825} +,{134,0,1640},{135,11,1325},{133,11,673},{4,11,287},{133,11,1018},{135,0,357},{6 +,0,467},{137,0,879},{7,0,317},{135,0,569},{6,0,924},{134,0,1588},{5,11,34},{5,10 +,406},{10,11,724},{12,11,444},{13,11,354},{18,11,32},{23,11,24},{23,11,31},{152, +11,5},{6,0,1795},{6,0,1835},{6,0,1836},{6,0,1856},{8,0,844},{8,0,849},{8,0,854}, +{8,0,870},{8,0,887},{10,0,852},{138,0,942},{6,10,69},{135,10,117},{137,0,307},{4 +,0,944},{6,0,1799},{6,0,1825},{10,0,848},{10,0,875},{10,0,895},{10,0,899},{10,0, +902},{140,0,773},{11,0,43},{13,0,72},{141,0,142},{135,10,1830},{134,11,382},{4, +10,432},{135,10,824},{132,11,329},{7,0,1820},{139,11,124},{133,10,826},{133,0, +525},{132,11,906},{7,11,1940},{136,11,366},{138,11,10},{4,11,123},{4,11,649},{5, +11,605},{7,11,1509},{136,11,36},{6,0,110},{135,0,1681},{133,0,493},{133,11,767}, +{4,0,174},{135,0,911},{138,11,786},{8,0,417},{137,0,782},{133,10,1000},{7,0,733} +,{137,0,583},{4,10,297},{6,10,529},{7,10,152},{7,10,713},{7,10,1845},{8,10,710}, +{8,10,717},{12,10,639},{140,10,685},{4,0,32},{5,0,215},{6,0,269},{7,0,1782},{7,0 +,1892},{10,0,16},{11,0,822},{11,0,954},{141,0,481},{4,11,273},{5,11,658},{133,11 +,995},{136,0,477},{134,11,72},{135,11,1345},{5,0,308},{7,0,1088},{4,10,520},{135 +,10,575},{133,11,589},{5,0,126},{8,0,297},{9,0,366},{140,0,374},{7,0,1551},{139, +0,361},{5,11,117},{6,11,514},{6,11,541},{7,11,1164},{7,11,1436},{8,11,220},{8,11 +,648},{10,11,688},{139,11,560},{133,11,686},{4,0,946},{6,0,1807},{8,0,871},{10,0 +,854},{10,0,870},{10,0,888},{10,0,897},{10,0,920},{12,0,722},{12,0,761},{12,0, +763},{12,0,764},{14,0,454},{14,0,465},{16,0,107},{18,0,167},{18,0,168},{146,0, +172},{132,0,175},{135,0,1307},{132,0,685},{135,11,1834},{133,0,797},{6,0,745},{6 +,0,858},{134,0,963},{133,0,565},{5,10,397},{6,10,154},{7,11,196},{7,10,676},{8, +10,443},{8,10,609},{9,10,24},{9,10,325},{10,10,35},{10,11,765},{11,11,347},{11, +10,535},{11,11,552},{11,11,576},{11,10,672},{11,11,790},{11,10,1018},{12,11,263} +,{12,10,637},{13,11,246},{13,11,270},{13,11,395},{14,11,74},{14,11,176},{14,11, +190},{14,11,398},{14,11,412},{15,11,32},{15,11,63},{16,10,30},{16,11,88},{147,11 +,105},{13,11,84},{141,11,122},{4,0,252},{7,0,1068},{10,0,434},{11,0,228},{11,0, +426},{13,0,231},{18,0,106},{148,0,87},{137,0,826},{4,11,589},{139,11,282},{5,11, +381},{135,11,1792},{132,0,791},{5,0,231},{10,0,509},{133,10,981},{7,0,601},{9,0, +277},{9,0,674},{10,0,178},{10,0,418},{10,0,571},{11,0,531},{12,0,113},{12,0,475} +,{13,0,99},{142,0,428},{4,10,56},{7,11,616},{7,10,1791},{8,10,607},{8,10,651},{ +10,11,413},{11,10,465},{11,10,835},{12,10,337},{141,10,480},{7,0,1591},{144,0,43 +},{9,10,158},{138,10,411},{135,0,1683},{8,0,289},{11,0,45},{12,0,278},{140,0,537 +},{6,11,120},{7,11,1188},{7,11,1710},{8,11,286},{9,11,667},{11,11,592},{139,11, +730},{136,10,617},{135,0,1120},{135,11,1146},{139,10,563},{4,11,352},{4,10,369}, +{135,11,687},{143,11,38},{4,0,399},{5,0,119},{5,0,494},{7,0,751},{9,0,556},{14, +11,179},{15,11,151},{150,11,11},{4,11,192},{5,11,49},{6,11,200},{6,11,293},{6,11 +,1696},{135,11,488},{4,0,398},{133,0,660},{7,0,1030},{134,10,622},{135,11,595},{ +141,0,168},{132,11,147},{7,0,973},{10,10,624},{142,10,279},{132,10,363},{132,0, +642},{133,11,934},{134,0,1615},{7,11,505},{135,11,523},{7,0,594},{7,0,851},{7,0, +1858},{9,0,411},{9,0,574},{9,0,666},{9,0,737},{10,0,346},{10,0,712},{11,0,246},{ +11,0,432},{11,0,517},{11,0,647},{11,0,679},{11,0,727},{12,0,304},{12,0,305},{12, +0,323},{12,0,483},{12,0,572},{12,0,593},{12,0,602},{13,0,95},{13,0,101},{13,0, +171},{13,0,315},{13,0,378},{13,0,425},{13,0,475},{14,0,63},{14,0,380},{14,0,384} +,{15,0,133},{18,0,112},{148,0,72},{135,0,1093},{132,0,679},{8,0,913},{10,0,903}, +{10,0,915},{12,0,648},{12,0,649},{14,0,455},{16,0,112},{138,11,438},{137,0,203}, +{134,10,292},{134,0,1492},{7,0,1374},{8,0,540},{5,10,177},{6,10,616},{7,10,827}, +{9,10,525},{138,10,656},{135,0,1486},{9,0,714},{138,10,31},{136,0,825},{134,0, +1511},{132,11,637},{134,0,952},{4,10,161},{133,10,631},{5,0,143},{5,0,769},{6,0, +1760},{7,0,682},{7,0,1992},{136,0,736},{132,0,700},{134,0,1540},{132,11,777},{9, +11,867},{138,11,837},{7,0,1557},{135,10,1684},{133,0,860},{6,0,422},{7,0,0},{7,0 +,1544},{9,0,605},{11,0,990},{12,0,235},{12,0,453},{13,0,47},{13,0,266},{9,10,469 +},{9,10,709},{12,10,512},{14,10,65},{145,10,12},{11,0,807},{10,10,229},{11,10,73 +},{139,10,376},{6,11,170},{7,11,1080},{8,11,395},{8,11,487},{11,11,125},{141,11, +147},{5,0,515},{137,0,131},{7,0,1605},{11,0,962},{146,0,139},{132,0,646},{4,0, +396},{7,0,728},{9,0,117},{13,0,202},{148,0,51},{6,0,121},{6,0,124},{6,0,357},{7, +0,1138},{7,0,1295},{8,0,162},{8,0,508},{11,0,655},{4,11,535},{6,10,558},{7,10, +651},{8,11,618},{9,10,0},{10,10,34},{139,10,1008},{135,11,1245},{138,0,357},{150 +,11,23},{133,0,237},{135,0,1784},{7,10,1832},{138,10,374},{132,0,713},{132,11,46 +},{6,0,1536},{10,0,348},{5,11,811},{6,11,1679},{6,11,1714},{135,11,2032},{11,11, +182},{142,11,195},{6,0,523},{7,0,738},{7,10,771},{7,10,1731},{9,10,405},{138,10, +421},{7,11,1458},{9,11,407},{139,11,15},{6,11,34},{7,11,69},{7,11,640},{7,11, +1089},{8,11,708},{8,11,721},{9,11,363},{9,11,643},{10,11,628},{148,11,98},{133,0 +,434},{135,0,1877},{7,0,571},{138,0,366},{5,10,881},{133,10,885},{9,0,513},{10,0 +,25},{10,0,39},{12,0,122},{140,0,187},{132,0,580},{5,10,142},{134,10,546},{132, +11,462},{137,0,873},{5,10,466},{11,10,571},{12,10,198},{13,10,283},{14,10,186},{ +15,10,21},{143,10,103},{7,0,171},{4,10,185},{5,10,257},{5,10,839},{5,10,936},{9, +10,399},{10,10,258},{10,10,395},{10,10,734},{11,10,1014},{12,10,23},{13,10,350}, +{14,10,150},{147,10,6},{134,0,625},{7,0,107},{7,0,838},{8,0,550},{138,0,401},{5, +11,73},{6,11,23},{134,11,338},{4,0,943},{6,0,1850},{12,0,713},{142,0,434},{11,0, +588},{11,0,864},{11,0,936},{11,0,968},{12,0,73},{12,0,343},{12,0,394},{13,0,275} +,{14,0,257},{15,0,160},{7,10,404},{7,10,1377},{7,10,1430},{7,10,2017},{8,10,149} +,{8,10,239},{8,10,512},{8,10,793},{8,10,818},{9,10,474},{9,10,595},{10,10,122},{ +10,10,565},{10,10,649},{10,10,783},{11,10,239},{11,10,295},{11,10,447},{11,10, +528},{11,10,639},{11,10,800},{12,10,25},{12,10,157},{12,10,316},{12,10,390},{12, +10,391},{12,10,395},{12,10,478},{12,10,503},{12,10,592},{12,10,680},{13,10,50},{ +13,10,53},{13,10,132},{13,10,198},{13,10,322},{13,10,415},{13,10,511},{14,10,71} +,{14,10,395},{15,10,71},{15,10,136},{17,10,123},{18,10,93},{147,10,58},{133,0, +768},{11,0,103},{142,0,0},{136,10,712},{132,0,799},{132,0,894},{7,11,725},{8,11, +498},{139,11,268},{135,11,1798},{135,11,773},{141,11,360},{4,10,377},{152,10,13} +,{135,0,1673},{132,11,583},{134,0,1052},{133,11,220},{140,11,69},{132,11,544},{4 +,10,180},{135,10,1906},{134,0,272},{4,0,441},{134,0,1421},{4,0,9},{5,0,128},{7,0 +,368},{11,0,480},{148,0,3},{5,11,176},{6,11,437},{6,11,564},{11,11,181},{141,11, +183},{132,10,491},{7,0,1182},{141,11,67},{6,0,1346},{4,10,171},{138,10,234},{4, +10,586},{7,10,1186},{138,10,631},{136,0,682},{134,0,1004},{15,0,24},{143,11,24}, +{134,0,968},{4,0,2},{6,0,742},{6,0,793},{7,0,545},{7,0,894},{9,10,931},{10,10, +334},{148,10,71},{136,11,600},{133,10,765},{9,0,769},{140,0,185},{4,11,790},{5, +11,273},{134,11,394},{7,0,474},{137,0,578},{4,11,135},{6,11,127},{7,11,1185},{7, +11,1511},{8,11,613},{11,11,5},{12,11,133},{12,11,495},{12,11,586},{14,11,385},{ +15,11,118},{17,11,20},{146,11,98},{133,10,424},{5,0,530},{142,0,113},{6,11,230}, +{7,11,961},{7,11,1085},{136,11,462},{7,11,1954},{137,11,636},{136,10,714},{149, +11,6},{135,10,685},{9,10,420},{10,10,269},{10,10,285},{10,10,576},{11,10,397},{ +13,10,175},{145,10,90},{132,10,429},{5,0,556},{5,11,162},{136,11,68},{132,11,654 +},{4,11,156},{7,11,998},{7,11,1045},{7,11,1860},{9,11,48},{9,11,692},{11,11,419} +,{139,11,602},{6,0,1317},{8,0,16},{9,0,825},{12,0,568},{7,11,1276},{8,11,474},{ +137,11,652},{18,0,97},{7,10,18},{7,10,699},{7,10,1966},{8,10,752},{9,10,273},{9, +10,412},{9,10,703},{10,10,71},{10,10,427},{138,10,508},{10,0,703},{7,11,1454},{ +138,11,703},{4,10,53},{5,10,186},{135,10,752},{134,0,892},{134,0,1571},{8,10,575 +},{10,10,289},{139,10,319},{6,0,186},{137,0,426},{134,0,1101},{132,10,675},{132, +0,585},{6,0,1870},{137,0,937},{152,11,10},{9,11,197},{10,11,300},{12,11,473},{13 +,11,90},{141,11,405},{4,0,93},{5,0,252},{6,0,229},{7,0,291},{9,0,550},{139,0,644 +},{137,0,749},{9,0,162},{6,10,209},{8,10,468},{9,10,210},{11,10,36},{12,10,28},{ +12,10,630},{13,10,21},{13,10,349},{14,10,7},{145,10,13},{132,0,381},{132,11,606} +,{4,10,342},{135,10,1179},{7,11,1587},{7,11,1707},{10,11,528},{139,11,504},{12, +11,39},{13,11,265},{141,11,439},{4,10,928},{133,10,910},{7,10,1838},{7,11,1978}, +{136,11,676},{6,0,762},{6,0,796},{134,0,956},{4,10,318},{4,10,496},{7,10,856},{ +139,10,654},{137,11,242},{4,11,361},{133,11,315},{132,11,461},{132,11,472},{132, +0,857},{5,0,21},{6,0,77},{6,0,157},{7,0,974},{7,0,1301},{7,0,1339},{7,0,1490},{7 +,0,1873},{9,0,628},{7,10,915},{8,10,247},{147,10,0},{4,10,202},{5,10,382},{6,10, +454},{7,10,936},{7,10,1803},{8,10,758},{9,10,375},{9,10,895},{10,10,743},{10,10, +792},{11,10,978},{11,10,1012},{142,10,109},{7,11,617},{10,11,498},{11,11,501},{ +12,11,16},{140,11,150},{7,10,1150},{7,10,1425},{7,10,1453},{10,11,747},{140,10, +513},{133,11,155},{11,0,919},{141,0,409},{138,10,791},{10,0,633},{139,11,729},{7 +,11,163},{8,11,319},{9,11,402},{10,11,24},{10,11,681},{11,11,200},{11,11,567},{ +12,11,253},{12,11,410},{142,11,219},{5,11,475},{7,11,1780},{9,11,230},{11,11,297 +},{11,11,558},{14,11,322},{147,11,76},{7,0,332},{6,10,445},{137,10,909},{135,11, +1956},{136,11,274},{134,10,578},{135,0,1489},{135,11,1848},{5,11,944},{134,11, +1769},{132,11,144},{136,10,766},{4,0,832},{135,10,541},{8,0,398},{9,0,681},{139, +0,632},{136,0,645},{9,0,791},{10,0,93},{16,0,13},{17,0,23},{18,0,135},{19,0,12}, +{20,0,1},{20,0,12},{148,0,14},{6,11,247},{137,11,555},{134,0,20},{132,0,800},{ +135,0,1841},{139,10,983},{137,10,768},{132,10,584},{141,11,51},{6,0,1993},{4,11, +620},{138,11,280},{136,0,769},{11,0,290},{11,0,665},{7,11,1810},{11,11,866},{12, +11,103},{13,11,495},{17,11,67},{147,11,74},{134,0,1426},{139,0,60},{4,10,326},{ +135,10,1770},{7,0,1874},{9,0,641},{132,10,226},{6,0,644},{5,10,426},{8,10,30},{9 +,10,2},{11,10,549},{147,10,122},{5,11,428},{138,11,442},{135,11,1871},{135,0, +1757},{147,10,117},{135,0,937},{135,0,1652},{6,0,654},{134,0,1476},{133,11,99},{ +135,0,527},{132,10,345},{4,10,385},{4,11,397},{7,10,265},{135,10,587},{4,0,579}, +{5,0,226},{5,0,323},{135,0,960},{134,0,1486},{8,11,502},{144,11,9},{4,10,347},{5 +,10,423},{5,10,996},{135,10,1329},{7,11,727},{146,11,73},{4,11,485},{7,11,353},{ +7,10,1259},{7,11,1523},{9,10,125},{139,10,65},{6,0,325},{5,10,136},{6,11,366},{7 +,11,1384},{7,11,1601},{136,10,644},{138,11,160},{6,0,1345},{137,11,282},{18,0,91 +},{147,0,70},{136,0,404},{4,11,157},{133,11,471},{133,0,973},{6,0,135},{135,0, +1176},{8,11,116},{11,11,551},{142,11,159},{4,0,549},{4,10,433},{133,10,719},{136 +,0,976},{5,11,160},{7,11,363},{7,11,589},{10,11,170},{141,11,55},{144,0,21},{144 +,0,51},{135,0,314},{135,10,1363},{4,11,108},{7,11,405},{10,11,491},{139,11,498}, +{146,0,4},{4,10,555},{8,10,536},{10,10,288},{139,10,1005},{135,11,1005},{6,0,281 +},{7,0,6},{8,0,282},{8,0,480},{8,0,499},{9,0,198},{10,0,143},{10,0,169},{10,0, +211},{10,0,417},{10,0,574},{11,0,147},{11,0,395},{12,0,75},{12,0,407},{12,0,608} +,{13,0,500},{142,0,251},{6,0,1093},{6,0,1405},{9,10,370},{138,10,90},{4,11,926}, +{133,11,983},{135,0,1776},{134,0,1528},{132,0,419},{132,11,538},{6,11,294},{7,11 +,1267},{136,11,624},{135,11,1772},{138,11,301},{4,10,257},{135,10,2031},{4,0,138 +},{7,0,1012},{7,0,1280},{9,0,76},{135,10,1768},{132,11,757},{5,0,29},{140,0,638} +,{7,11,655},{135,11,1844},{7,0,1418},{6,11,257},{135,11,1522},{8,11,469},{138,11 +,47},{142,11,278},{6,10,83},{6,10,1733},{135,10,1389},{11,11,204},{11,11,243},{ +140,11,293},{135,11,1875},{6,0,1710},{135,0,2038},{137,11,299},{4,0,17},{5,0,23} +,{7,0,995},{11,0,383},{11,0,437},{12,0,460},{140,0,532},{133,0,862},{137,10,696} +,{6,0,592},{138,0,946},{138,11,599},{7,10,1718},{9,10,95},{9,10,274},{10,10,279} +,{10,10,317},{10,10,420},{11,10,303},{11,10,808},{12,10,134},{12,10,367},{13,10, +149},{13,10,347},{14,10,349},{14,10,406},{18,10,22},{18,10,89},{18,10,122},{147, +10,47},{8,0,70},{12,0,171},{141,0,272},{133,10,26},{132,10,550},{137,0,812},{10, +0,233},{139,0,76},{134,0,988},{134,0,442},{136,10,822},{7,0,896},{4,10,902},{5, +10,809},{134,10,122},{5,11,150},{7,11,106},{8,11,603},{9,11,593},{9,11,634},{10, +11,44},{10,11,173},{11,11,462},{11,11,515},{13,11,216},{13,11,288},{142,11,400}, +{136,0,483},{135,10,262},{6,0,1709},{133,10,620},{4,10,34},{5,10,574},{7,10,279} +,{7,10,1624},{136,10,601},{137,10,170},{147,0,119},{12,11,108},{141,11,291},{11, +0,69},{12,0,105},{12,0,117},{13,0,213},{14,0,13},{14,0,62},{14,0,177},{14,0,421} +,{15,0,19},{146,0,141},{137,0,309},{11,11,278},{142,11,73},{7,0,608},{7,0,976},{ +9,0,146},{10,0,206},{10,0,596},{13,0,218},{142,0,153},{133,10,332},{6,10,261},{8 +,10,182},{139,10,943},{4,11,493},{144,11,55},{134,10,1721},{132,0,768},{4,10,933 +},{133,10,880},{7,11,555},{7,11,1316},{7,11,1412},{7,11,1839},{9,11,192},{9,11, +589},{11,11,241},{11,11,676},{11,11,811},{11,11,891},{12,11,140},{12,11,346},{12 +,11,479},{13,11,30},{13,11,49},{13,11,381},{14,11,188},{15,11,150},{16,11,76},{ +18,11,30},{148,11,52},{4,0,518},{135,0,1136},{6,11,568},{7,11,112},{7,11,1804},{ +8,11,362},{8,11,410},{8,11,830},{9,11,514},{11,11,649},{142,11,157},{135,11,673} +,{8,0,689},{137,0,863},{4,0,18},{7,0,145},{7,0,444},{7,0,1278},{8,0,49},{8,0,400 +},{9,0,71},{9,0,250},{10,0,459},{12,0,160},{16,0,24},{132,11,625},{140,0,1020},{ +4,0,997},{6,0,1946},{6,0,1984},{134,0,1998},{6,11,16},{6,11,158},{7,11,43},{7,11 +,129},{7,11,181},{8,11,276},{8,11,377},{10,11,523},{11,11,816},{12,11,455},{13, +11,303},{142,11,135},{133,10,812},{134,0,658},{4,11,1},{7,11,1143},{7,11,1463},{ +8,11,61},{9,11,207},{9,11,390},{9,11,467},{139,11,836},{150,11,26},{140,0,106},{ +6,0,1827},{10,0,931},{18,0,166},{20,0,114},{4,10,137},{7,10,1178},{7,11,1319},{ +135,10,1520},{133,0,1010},{4,11,723},{5,11,895},{7,11,1031},{8,11,199},{8,11,340 +},{9,11,153},{9,11,215},{10,11,21},{10,11,59},{10,11,80},{10,11,224},{11,11,229} +,{11,11,652},{12,11,192},{13,11,146},{142,11,91},{132,11,295},{6,11,619},{7,11, +898},{7,11,1092},{8,11,485},{18,11,28},{147,11,116},{137,11,51},{6,10,1661},{7, +10,1975},{7,10,2009},{135,10,2011},{5,11,309},{140,11,211},{5,0,87},{7,0,313},{7 +,0,1103},{10,0,208},{10,0,582},{11,0,389},{11,0,813},{12,0,385},{13,0,286},{14,0 +,124},{146,0,108},{5,11,125},{8,11,77},{138,11,15},{132,0,267},{133,0,703},{137, +11,155},{133,11,439},{11,11,164},{140,11,76},{9,0,496},{5,10,89},{7,10,1915},{9, +10,185},{9,10,235},{10,10,64},{10,10,270},{10,10,403},{10,10,469},{10,10,529},{ +10,10,590},{11,10,140},{11,10,860},{13,10,1},{13,10,422},{14,10,341},{14,10,364} +,{17,10,93},{18,10,113},{19,10,97},{147,10,113},{133,10,695},{135,0,1121},{5,10, +6},{6,10,183},{7,10,680},{7,10,978},{7,10,1013},{7,10,1055},{12,10,230},{13,10, +172},{146,10,29},{4,11,8},{7,11,1152},{7,11,1153},{7,11,1715},{9,11,374},{10,11, +478},{139,11,648},{135,11,1099},{6,10,29},{139,10,63},{4,0,561},{10,0,249},{139, +0,209},{132,0,760},{7,11,799},{138,11,511},{136,11,87},{9,0,154},{140,0,485},{ +136,0,255},{132,0,323},{140,0,419},{132,10,311},{134,10,1740},{4,0,368},{135,0, +641},{7,10,170},{8,10,90},{8,10,177},{8,10,415},{11,10,714},{142,10,281},{4,11, +69},{5,11,122},{9,11,656},{138,11,464},{5,11,849},{134,11,1633},{8,0,522},{142,0 +,328},{11,10,91},{13,10,129},{15,10,101},{145,10,125},{7,0,562},{8,0,551},{4,10, +494},{6,10,74},{7,10,44},{11,11,499},{12,10,17},{15,10,5},{148,10,11},{4,10,276} +,{133,10,296},{9,0,92},{147,0,91},{4,10,7},{5,10,90},{5,10,158},{6,10,542},{7,10 +,221},{7,10,1574},{9,10,490},{10,10,540},{11,10,443},{139,10,757},{6,0,525},{6,0 +,1976},{8,0,806},{9,0,876},{140,0,284},{5,11,859},{7,10,588},{7,11,1160},{8,11, +107},{9,10,175},{9,11,291},{9,11,439},{10,10,530},{10,11,663},{11,11,609},{140, +11,197},{7,11,168},{13,11,196},{141,11,237},{139,0,958},{133,0,594},{135,10,580} +,{7,10,88},{136,10,627},{6,0,479},{6,0,562},{7,0,1060},{13,0,6},{5,10,872},{6,10 +,57},{7,10,471},{9,10,447},{137,10,454},{136,11,413},{145,11,19},{4,11,117},{6, +11,372},{7,11,1905},{142,11,323},{4,11,722},{139,11,471},{17,0,61},{5,10,31},{ +134,10,614},{8,10,330},{140,10,477},{7,10,1200},{138,10,460},{6,10,424},{135,10, +1866},{6,0,1641},{136,0,820},{6,0,1556},{134,0,1618},{9,11,5},{12,11,216},{12,11 +,294},{12,11,298},{12,11,400},{12,11,518},{13,11,229},{143,11,139},{15,11,155},{ +144,11,79},{4,0,302},{135,0,1766},{5,10,13},{134,10,142},{6,0,148},{7,0,1313},{7 +,10,116},{8,10,322},{8,10,755},{9,10,548},{10,10,714},{11,10,884},{141,10,324},{ +137,0,676},{9,11,88},{139,11,270},{5,11,12},{7,11,375},{137,11,438},{134,0,1674} +,{7,10,1472},{135,10,1554},{11,0,178},{7,10,1071},{7,10,1541},{7,10,1767},{7,10, +1806},{11,10,162},{11,10,242},{12,10,605},{15,10,26},{144,10,44},{6,0,389},{7,0, +149},{9,0,142},{138,0,94},{140,11,71},{145,10,115},{6,0,8},{7,0,1881},{8,0,91},{ +11,11,966},{12,11,287},{13,11,342},{13,11,402},{15,11,110},{143,11,163},{4,11, +258},{136,11,639},{6,11,22},{7,11,903},{138,11,577},{133,11,681},{135,10,1111},{ +135,11,1286},{9,0,112},{8,10,1},{138,10,326},{5,10,488},{6,10,527},{7,10,489},{7 +,10,1636},{8,10,121},{8,10,144},{8,10,359},{9,10,193},{9,10,241},{9,10,336},{9, +10,882},{11,10,266},{11,10,372},{11,10,944},{12,10,401},{140,10,641},{4,11,664}, +{133,11,804},{6,0,747},{134,0,1015},{135,0,1746},{9,10,31},{10,10,244},{10,10, +699},{12,10,149},{141,10,497},{133,10,377},{135,0,24},{6,0,1352},{5,11,32},{145, +10,101},{7,0,1530},{10,0,158},{13,0,13},{13,0,137},{13,0,258},{14,0,111},{14,0, +225},{14,0,253},{14,0,304},{14,0,339},{14,0,417},{146,0,33},{4,0,503},{135,0, +1661},{5,0,130},{6,0,845},{7,0,1314},{9,0,610},{10,0,718},{11,0,601},{11,0,819}, +{11,0,946},{140,0,536},{10,0,149},{11,0,280},{142,0,336},{134,0,1401},{135,0, +1946},{8,0,663},{144,0,8},{134,0,1607},{135,10,2023},{4,11,289},{7,11,629},{7,11 +,1698},{7,11,1711},{140,11,215},{6,11,450},{136,11,109},{10,0,882},{10,0,883},{ +10,0,914},{138,0,928},{133,10,843},{136,11,705},{132,10,554},{133,10,536},{5,0, +417},{9,10,79},{11,10,625},{145,10,7},{7,11,1238},{142,11,37},{4,0,392},{135,0, +1597},{5,0,433},{9,0,633},{11,0,629},{132,10,424},{7,10,336},{136,10,785},{134, +11,355},{6,0,234},{7,0,769},{9,0,18},{138,0,358},{4,10,896},{134,10,1777},{138, +11,323},{7,0,140},{7,0,1950},{8,0,680},{11,0,817},{147,0,88},{7,0,1222},{138,0, +386},{139,11,908},{11,0,249},{12,0,313},{16,0,66},{145,0,26},{134,0,5},{7,10,750 +},{9,10,223},{11,10,27},{11,10,466},{12,10,624},{14,10,265},{146,10,61},{134,11, +26},{134,0,1216},{5,0,963},{134,0,1773},{4,11,414},{5,11,467},{9,11,654},{10,11, +451},{12,11,59},{141,11,375},{135,11,17},{4,10,603},{133,10,661},{4,10,11},{6,10 +,128},{7,10,231},{7,10,1533},{138,10,725},{135,11,955},{7,0,180},{8,0,509},{136, +0,792},{132,10,476},{132,0,1002},{133,11,538},{135,10,1807},{132,0,931},{7,0,943 +},{11,0,614},{140,0,747},{135,0,1837},{9,10,20},{10,10,324},{10,10,807},{139,10, +488},{134,0,641},{6,11,280},{10,11,502},{11,11,344},{140,11,38},{5,11,45},{7,11, +1161},{11,11,448},{11,11,880},{13,11,139},{13,11,407},{15,11,16},{17,11,95},{18, +11,66},{18,11,88},{18,11,123},{149,11,7},{9,0,280},{138,0,134},{22,0,22},{23,0,5 +},{151,0,29},{136,11,777},{4,0,90},{5,0,545},{7,0,754},{9,0,186},{10,0,72},{10,0 +,782},{11,0,577},{11,0,610},{11,0,960},{12,0,354},{12,0,362},{12,0,595},{4,11, +410},{135,11,521},{135,11,1778},{5,10,112},{6,10,103},{134,10,150},{138,10,356}, +{132,0,742},{7,0,151},{9,0,329},{139,0,254},{8,0,853},{8,0,881},{8,0,911},{8,0, +912},{10,0,872},{12,0,741},{12,0,742},{152,0,18},{4,11,573},{136,11,655},{6,0, +921},{134,0,934},{9,0,187},{10,0,36},{11,0,1016},{17,0,44},{146,0,64},{7,0,833}, +{136,0,517},{4,0,506},{5,0,295},{135,0,1680},{4,10,708},{8,10,15},{9,10,50},{9, +10,386},{11,10,18},{11,10,529},{140,10,228},{7,0,251},{7,0,1701},{8,0,436},{4,10 +,563},{7,10,592},{7,10,637},{7,10,770},{8,10,463},{9,10,60},{9,10,335},{9,10,904 +},{10,10,73},{11,10,434},{12,10,585},{13,10,331},{18,10,110},{148,10,60},{132,10 +,502},{136,0,584},{6,10,347},{138,10,161},{7,0,987},{9,0,688},{10,0,522},{11,0, +788},{12,0,137},{12,0,566},{14,0,9},{14,0,24},{14,0,64},{7,11,899},{142,11,325}, +{4,0,214},{5,0,500},{5,10,102},{6,10,284},{7,10,1079},{7,10,1423},{7,10,1702},{8 +,10,470},{9,10,554},{9,10,723},{139,10,333},{7,10,246},{135,10,840},{6,10,10},{8 +,10,571},{9,10,739},{143,10,91},{133,10,626},{146,0,195},{134,0,1775},{7,0,389}, +{7,0,700},{7,0,940},{8,0,514},{9,0,116},{9,0,535},{10,0,118},{11,0,107},{11,0, +148},{11,0,922},{12,0,254},{12,0,421},{142,0,238},{5,10,18},{6,10,526},{13,10,24 +},{13,10,110},{19,10,5},{147,10,44},{132,0,743},{11,0,292},{4,10,309},{5,10,462} +,{7,10,970},{135,10,1097},{22,10,30},{150,10,33},{139,11,338},{135,11,1598},{7,0 +,1283},{9,0,227},{11,0,325},{11,0,408},{14,0,180},{146,0,47},{4,0,953},{6,0,1805 +},{6,0,1814},{6,0,1862},{140,0,774},{6,11,611},{135,11,1733},{135,11,1464},{5,0, +81},{7,0,146},{7,0,1342},{8,0,53},{8,0,561},{8,0,694},{8,0,754},{9,0,115},{9,0, +179},{9,0,894},{10,0,462},{10,0,813},{11,0,230},{11,0,657},{11,0,699},{11,0,748} +,{12,0,119},{12,0,200},{12,0,283},{142,0,273},{5,0,408},{6,0,789},{6,0,877},{6,0 +,1253},{6,0,1413},{137,0,747},{134,10,1704},{135,11,663},{6,0,1910},{6,0,1915},{ +6,0,1923},{9,0,913},{9,0,928},{9,0,950},{9,0,954},{9,0,978},{9,0,993},{12,0,812} +,{12,0,819},{12,0,831},{12,0,833},{12,0,838},{12,0,909},{12,0,928},{12,0,931},{ +12,0,950},{15,0,186},{15,0,187},{15,0,195},{15,0,196},{15,0,209},{15,0,215},{15, +0,236},{15,0,241},{15,0,249},{15,0,253},{18,0,180},{18,0,221},{18,0,224},{18,0, +227},{18,0,229},{149,0,60},{7,0,1826},{135,0,1938},{11,0,490},{18,0,143},{5,10, +86},{7,10,743},{9,10,85},{10,10,281},{10,10,432},{12,10,251},{13,10,118},{142,10 +,378},{5,10,524},{133,10,744},{141,11,442},{10,10,107},{140,10,436},{135,11,503} +,{134,0,1162},{132,10,927},{7,0,30},{8,0,86},{8,0,315},{8,0,700},{9,0,576},{9,0, +858},{10,0,414},{11,0,310},{11,0,888},{11,0,904},{12,0,361},{13,0,248},{13,0,371 +},{14,0,142},{12,10,670},{146,10,94},{134,0,721},{4,11,113},{5,11,163},{5,11,735 +},{7,11,1009},{7,10,1149},{9,11,9},{9,10,156},{9,11,771},{12,11,90},{13,11,138}, +{13,11,410},{143,11,128},{138,0,839},{133,10,778},{137,0,617},{133,10,502},{8,10 +,196},{10,10,283},{139,10,406},{6,0,428},{7,0,524},{8,0,169},{8,0,234},{9,0,480} +,{138,0,646},{133,10,855},{134,0,1648},{7,0,1205},{138,0,637},{7,0,1596},{4,11, +935},{133,11,823},{5,11,269},{7,11,434},{7,11,891},{8,11,339},{9,11,702},{11,11, +594},{11,11,718},{145,11,100},{7,11,878},{9,11,485},{141,11,264},{4,0,266},{8,0, +4},{9,0,39},{10,0,166},{11,0,918},{12,0,635},{20,0,10},{22,0,27},{22,0,43},{22,0 +,52},{134,11,1713},{7,10,1400},{9,10,446},{138,10,45},{135,11,900},{132,0,862},{ +134,0,1554},{135,11,1033},{19,0,16},{147,11,16},{135,11,1208},{7,0,157},{136,0, +279},{6,0,604},{136,0,391},{13,10,455},{15,10,99},{15,10,129},{144,10,68},{135, +10,172},{7,0,945},{11,0,713},{139,0,744},{4,0,973},{10,0,877},{10,0,937},{10,0, +938},{140,0,711},{139,0,1022},{132,10,568},{142,11,143},{4,0,567},{9,0,859},{132 +,10,732},{7,0,1846},{136,0,628},{136,10,733},{133,0,762},{4,10,428},{135,10,1789 +},{10,0,784},{13,0,191},{7,10,2015},{140,10,665},{133,0,298},{7,0,633},{7,0,905} +,{7,0,909},{7,0,1538},{9,0,767},{140,0,636},{138,10,806},{132,0,795},{139,0,301} +,{135,0,1970},{5,11,625},{135,11,1617},{135,11,275},{7,11,37},{8,11,425},{8,11, +693},{9,11,720},{10,11,380},{10,11,638},{11,11,273},{11,11,307},{11,11,473},{12, +11,61},{143,11,43},{135,11,198},{134,0,1236},{7,0,369},{12,0,644},{12,0,645},{ +144,0,90},{19,0,15},{149,0,27},{6,0,71},{7,0,845},{8,0,160},{9,0,318},{6,10,1623 +},{134,10,1681},{134,0,1447},{134,0,1255},{138,0,735},{8,0,76},{132,11,168},{6, +10,1748},{8,10,715},{9,10,802},{10,10,46},{10,10,819},{13,10,308},{14,10,351},{ +14,10,363},{146,10,67},{135,11,91},{6,0,474},{4,10,63},{133,10,347},{133,10,749} +,{138,0,841},{133,10,366},{6,0,836},{132,11,225},{135,0,1622},{135,10,89},{140,0 +,735},{134,0,1601},{138,11,145},{6,0,1390},{137,0,804},{142,0,394},{6,11,15},{7, +11,70},{10,11,240},{147,11,93},{6,0,96},{135,0,1426},{4,0,651},{133,0,289},{7,11 +,956},{7,10,977},{7,11,1157},{7,11,1506},{7,11,1606},{7,11,1615},{7,11,1619},{7, +11,1736},{7,11,1775},{8,11,590},{9,11,324},{9,11,736},{9,11,774},{9,11,776},{9, +11,784},{10,11,567},{10,11,708},{11,11,518},{11,11,613},{11,11,695},{11,11,716}, +{11,11,739},{11,11,770},{11,11,771},{11,11,848},{11,11,857},{11,11,931},{11,11, +947},{12,11,326},{12,11,387},{12,11,484},{12,11,528},{12,11,552},{12,11,613},{13 +,11,189},{13,11,256},{13,11,340},{13,11,432},{13,11,436},{13,11,440},{13,11,454} +,{14,11,174},{14,11,220},{14,11,284},{14,11,390},{145,11,121},{7,0,688},{8,0,35} +,{9,0,511},{10,0,767},{147,0,118},{134,0,667},{4,0,513},{5,10,824},{133,10,941}, +{7,10,440},{8,10,230},{139,10,106},{134,0,2034},{135,11,1399},{143,11,66},{135, +11,1529},{4,11,145},{6,11,176},{7,11,395},{9,11,562},{144,11,28},{132,11,501},{ +132,0,704},{134,0,1524},{7,0,1078},{134,11,464},{6,11,509},{10,11,82},{20,11,91} +,{151,11,13},{4,0,720},{133,0,306},{133,0,431},{7,0,1196},{4,10,914},{5,10,800}, +{133,10,852},{135,11,1189},{10,0,54},{141,10,115},{7,10,564},{142,10,168},{5,0, +464},{6,0,236},{7,0,696},{7,0,914},{7,0,1108},{7,0,1448},{9,0,15},{9,0,564},{10, +0,14},{12,0,565},{13,0,449},{14,0,53},{15,0,13},{16,0,64},{17,0,41},{4,10,918},{ +133,10,876},{6,0,1418},{134,10,1764},{4,10,92},{133,10,274},{134,0,907},{4,11, +114},{8,10,501},{9,11,492},{13,11,462},{142,11,215},{4,11,77},{5,11,361},{6,11, +139},{6,11,401},{6,11,404},{7,11,413},{7,11,715},{7,11,1716},{11,11,279},{12,11, +179},{12,11,258},{13,11,244},{142,11,358},{6,0,1767},{12,0,194},{145,0,107},{134 +,11,1717},{5,10,743},{142,11,329},{4,10,49},{7,10,280},{135,10,1633},{5,0,840},{ +7,11,1061},{8,11,82},{11,11,250},{12,11,420},{141,11,184},{135,11,724},{134,0, +900},{136,10,47},{134,0,1436},{144,11,0},{6,0,675},{7,0,1008},{7,0,1560},{9,0, +642},{11,0,236},{14,0,193},{5,10,272},{5,10,908},{5,10,942},{8,10,197},{9,10,47} +,{11,10,538},{139,10,742},{4,0,68},{5,0,628},{5,0,634},{6,0,386},{7,0,794},{8,0, +273},{9,0,563},{10,0,105},{10,0,171},{11,0,94},{139,0,354},{135,10,1911},{137,10 +,891},{4,0,95},{6,0,1297},{6,0,1604},{7,0,416},{139,0,830},{6,11,513},{135,11, +1052},{7,0,731},{13,0,20},{143,0,11},{137,11,899},{10,0,850},{140,0,697},{4,0, +662},{7,11,1417},{12,11,382},{17,11,48},{152,11,12},{133,0,736},{132,0,861},{4, +10,407},{132,10,560},{141,10,490},{6,11,545},{7,11,565},{7,11,1669},{10,11,114}, +{11,11,642},{140,11,618},{6,0,871},{134,0,1000},{5,0,864},{10,0,648},{11,0,671}, +{15,0,46},{133,11,5},{133,0,928},{11,0,90},{13,0,7},{4,10,475},{11,10,35},{13,10 +,71},{13,10,177},{142,10,422},{136,0,332},{135,11,192},{134,0,1055},{136,11,763} +,{11,0,986},{140,0,682},{7,0,76},{8,0,44},{9,0,884},{10,0,580},{11,0,399},{11,0, +894},{143,0,122},{135,11,1237},{135,10,636},{11,0,300},{6,10,222},{7,10,1620},{8 +,10,409},{137,10,693},{4,11,87},{5,11,250},{10,11,601},{13,11,298},{13,11,353},{ +141,11,376},{5,0,518},{10,0,340},{11,0,175},{149,0,16},{140,0,771},{6,0,1108},{ +137,0,831},{132,0,836},{135,0,1852},{4,0,957},{6,0,1804},{8,0,842},{8,0,843},{8, +0,851},{8,0,855},{140,0,767},{135,11,814},{4,11,57},{7,11,1195},{7,11,1438},{7, +11,1548},{7,11,1835},{7,11,1904},{9,11,757},{10,11,604},{139,11,519},{133,10,882 +},{138,0,246},{4,0,934},{5,0,202},{8,0,610},{7,11,1897},{12,11,290},{13,11,80},{ +13,11,437},{145,11,74},{8,0,96},{9,0,36},{10,0,607},{10,0,804},{10,0,832},{11,0, +423},{11,0,442},{12,0,309},{14,0,199},{15,0,90},{145,0,110},{132,10,426},{7,0, +654},{8,0,240},{6,10,58},{7,10,745},{7,10,1969},{8,10,675},{9,10,479},{9,10,731} +,{10,10,330},{10,10,593},{10,10,817},{11,10,32},{11,10,133},{11,10,221},{145,10, +68},{9,0,13},{9,0,398},{9,0,727},{10,0,75},{10,0,184},{10,0,230},{10,0,564},{10, +0,569},{11,0,973},{12,0,70},{12,0,189},{13,0,57},{141,0,257},{4,11,209},{135,11, +902},{7,0,391},{137,10,538},{134,0,403},{6,11,303},{7,11,335},{7,11,1437},{7,11, +1668},{8,11,553},{8,11,652},{8,11,656},{9,11,558},{11,11,743},{149,11,18},{132, +11,559},{11,0,75},{142,0,267},{6,0,815},{141,11,2},{141,0,366},{137,0,631},{133, +11,1017},{5,0,345},{135,0,1016},{133,11,709},{134,11,1745},{133,10,566},{7,0,952 +},{6,10,48},{9,10,139},{10,10,399},{11,10,469},{12,10,634},{141,10,223},{133,0, +673},{9,0,850},{7,11,8},{136,11,206},{6,0,662},{149,0,35},{4,0,287},{133,0,1018} +,{6,10,114},{7,10,1224},{7,10,1556},{136,10,3},{8,10,576},{137,10,267},{4,0,884} +,{5,0,34},{10,0,724},{12,0,444},{13,0,354},{18,0,32},{23,0,24},{23,0,31},{152,0, +5},{133,10,933},{132,11,776},{138,0,151},{136,0,427},{134,0,382},{132,0,329},{9, +0,846},{10,0,827},{138,11,33},{9,0,279},{10,0,407},{14,0,84},{22,0,18},{135,11, +1297},{136,11,406},{132,0,906},{136,0,366},{134,0,843},{134,0,1443},{135,0,1372} +,{138,0,992},{4,0,123},{5,0,605},{7,0,1509},{136,0,36},{132,0,649},{8,11,175},{ +10,11,168},{138,11,573},{133,0,767},{134,0,1018},{135,11,1305},{12,10,30},{13,10 +,148},{14,10,87},{14,10,182},{16,10,42},{148,10,70},{134,11,607},{4,0,273},{5,0, +658},{133,0,995},{6,0,72},{139,11,174},{10,0,483},{12,0,368},{7,10,56},{7,10, +1989},{8,10,337},{8,10,738},{9,10,600},{13,10,447},{142,10,92},{5,11,784},{138, +10,666},{135,0,1345},{139,11,882},{134,0,1293},{133,0,589},{134,0,1988},{5,0,117 +},{6,0,514},{6,0,541},{7,0,1164},{7,0,1436},{8,0,220},{8,0,648},{10,0,688},{139, +0,560},{136,0,379},{5,0,686},{7,10,866},{135,10,1163},{132,10,328},{9,11,14},{9, +11,441},{10,11,306},{139,11,9},{4,10,101},{135,10,1171},{5,10,833},{136,10,744}, +{5,11,161},{7,11,839},{135,11,887},{7,0,196},{10,0,765},{11,0,347},{11,0,552},{ +11,0,790},{12,0,263},{13,0,246},{13,0,270},{13,0,395},{14,0,176},{14,0,190},{14, +0,398},{14,0,412},{15,0,32},{15,0,63},{16,0,88},{147,0,105},{6,10,9},{6,10,397}, +{7,10,53},{7,10,1742},{10,10,632},{11,10,828},{140,10,146},{5,0,381},{135,0,1792 +},{134,0,1452},{135,11,429},{8,0,367},{10,0,760},{14,0,79},{20,0,17},{152,0,0},{ +7,0,616},{138,0,413},{11,10,417},{12,10,223},{140,10,265},{7,11,1611},{13,11,14} +,{15,11,44},{19,11,13},{148,11,76},{135,0,1229},{6,0,120},{7,0,1188},{7,0,1710}, +{8,0,286},{9,0,667},{11,0,592},{139,0,730},{135,11,1814},{135,0,1146},{4,10,186} +,{5,10,157},{8,10,168},{138,10,6},{4,0,352},{135,0,687},{4,0,192},{5,0,49},{6,0, +200},{6,0,293},{6,0,1696},{135,0,1151},{133,10,875},{5,10,773},{5,10,991},{6,10, +1635},{134,10,1788},{7,10,111},{136,10,581},{6,0,935},{134,0,1151},{134,0,1050}, +{132,0,650},{132,0,147},{11,0,194},{12,0,62},{12,0,88},{11,11,194},{12,11,62},{ +140,11,88},{6,0,339},{135,0,923},{134,10,1747},{7,11,643},{136,11,236},{133,0, +934},{7,10,1364},{7,10,1907},{141,10,158},{132,10,659},{4,10,404},{135,10,675},{ +7,11,581},{9,11,644},{137,11,699},{13,0,211},{14,0,133},{14,0,204},{15,0,64},{15 +,0,69},{15,0,114},{16,0,10},{19,0,23},{19,0,35},{19,0,39},{19,0,51},{19,0,71},{ +19,0,75},{152,0,15},{133,10,391},{5,11,54},{135,11,1513},{7,0,222},{8,0,341},{5, +10,540},{134,10,1697},{134,10,78},{132,11,744},{136,0,293},{137,11,701},{7,11, +930},{10,11,402},{10,11,476},{13,11,452},{18,11,55},{147,11,104},{132,0,637},{ +133,10,460},{8,11,50},{137,11,624},{132,11,572},{134,0,1159},{4,10,199},{139,10, +34},{134,0,847},{134,10,388},{6,11,43},{7,11,38},{8,11,248},{9,11,504},{138,11, +513},{9,0,683},{4,10,511},{6,10,608},{9,10,333},{10,10,602},{11,10,441},{11,10, +723},{11,10,976},{140,10,357},{9,0,867},{138,0,837},{6,0,944},{135,11,326},{135, +0,1809},{5,10,938},{7,11,783},{136,10,707},{133,11,766},{133,11,363},{6,0,170},{ +7,0,1080},{8,0,395},{8,0,487},{141,0,147},{6,11,258},{140,11,409},{4,0,535},{8,0 +,618},{5,11,249},{148,11,82},{6,0,1379},{149,11,15},{135,0,1625},{150,0,23},{5, +11,393},{6,11,378},{7,11,1981},{9,11,32},{9,11,591},{10,11,685},{10,11,741},{142 +,11,382},{133,11,788},{7,11,1968},{10,11,19},{139,11,911},{7,11,1401},{135,11, +1476},{4,11,61},{5,11,58},{5,11,171},{5,11,635},{5,11,683},{5,11,700},{6,11,291} +,{6,11,566},{7,11,1650},{11,11,523},{12,11,273},{12,11,303},{15,11,39},{143,11, +111},{6,10,469},{7,10,1709},{138,10,515},{4,0,778},{134,11,589},{132,0,46},{5,0, +811},{6,0,1679},{6,0,1714},{135,0,2032},{7,0,1458},{9,0,407},{11,0,15},{12,0,651 +},{149,0,37},{7,0,938},{132,10,500},{6,0,34},{7,0,69},{7,0,1089},{7,0,1281},{8,0 +,708},{8,0,721},{9,0,363},{148,0,98},{10,11,231},{147,11,124},{7,11,726},{152,11 +,9},{5,10,68},{134,10,383},{136,11,583},{4,11,917},{133,11,1005},{11,10,216},{ +139,10,340},{135,11,1675},{8,0,441},{10,0,314},{143,0,3},{132,11,919},{4,10,337} +,{6,10,353},{7,10,1934},{8,10,488},{137,10,429},{7,0,889},{7,10,1795},{8,10,259} +,{9,10,135},{9,10,177},{9,10,860},{10,10,825},{11,10,115},{11,10,370},{11,10,405 +},{11,10,604},{12,10,10},{12,10,667},{12,10,669},{13,10,76},{14,10,310},{15,10, +76},{15,10,147},{148,10,23},{4,10,15},{4,11,255},{5,10,22},{5,11,302},{6,11,132} +,{6,10,244},{7,10,40},{7,11,128},{7,10,200},{7,11,283},{7,10,906},{7,10,1199},{7 +,11,1299},{9,10,616},{10,11,52},{10,11,514},{10,10,716},{11,10,635},{11,10,801}, +{11,11,925},{12,10,458},{13,11,92},{142,11,309},{132,0,462},{137,11,173},{135,10 +,1735},{8,0,525},{5,10,598},{7,10,791},{8,10,108},{137,10,123},{5,0,73},{6,0,23} +,{134,0,338},{132,0,676},{132,10,683},{7,0,725},{8,0,498},{139,0,268},{12,0,21}, +{151,0,7},{135,0,773},{4,10,155},{135,10,1689},{4,0,164},{5,0,730},{5,10,151},{5 +,10,741},{6,11,210},{7,10,498},{7,10,870},{7,10,1542},{12,10,213},{14,10,36},{14 +,10,391},{17,10,111},{18,10,6},{18,10,46},{18,10,151},{19,10,36},{20,10,32},{20, +10,56},{20,10,69},{20,10,102},{21,10,4},{22,10,8},{22,10,10},{22,10,14},{150,10, +31},{4,10,624},{135,10,1752},{4,0,583},{9,0,936},{15,0,214},{18,0,199},{24,0,26} +,{134,11,588},{7,0,1462},{11,0,659},{4,11,284},{134,11,223},{133,0,220},{139,0, +803},{132,0,544},{4,10,492},{133,10,451},{16,0,98},{148,0,119},{4,11,218},{7,11, +526},{143,11,137},{135,10,835},{4,11,270},{5,11,192},{6,11,332},{7,11,1322},{13, +11,9},{13,10,70},{14,11,104},{142,11,311},{132,10,539},{140,11,661},{5,0,176},{6 +,0,437},{6,0,564},{11,0,181},{141,0,183},{135,0,1192},{6,10,113},{135,10,436},{ +136,10,718},{135,10,520},{135,0,1878},{140,11,196},{7,11,379},{8,11,481},{137,11 +,377},{5,11,1003},{6,11,149},{137,11,746},{8,11,262},{9,11,627},{10,11,18},{11, +11,214},{11,11,404},{11,11,457},{11,11,780},{11,11,849},{11,11,913},{13,11,330}, +{13,11,401},{142,11,200},{149,0,26},{136,11,304},{132,11,142},{135,0,944},{4,0, +790},{5,0,273},{134,0,394},{134,0,855},{4,0,135},{6,0,127},{7,0,1185},{7,0,1511} +,{8,0,613},{11,0,5},{12,0,336},{12,0,495},{12,0,586},{12,0,660},{12,0,668},{14,0 +,385},{15,0,118},{17,0,20},{146,0,98},{6,0,230},{9,0,752},{18,0,109},{12,10,610} +,{13,10,431},{144,10,59},{7,0,1954},{135,11,925},{4,11,471},{5,11,51},{6,11,602} +,{8,11,484},{10,11,195},{140,11,159},{132,10,307},{136,11,688},{132,11,697},{7, +11,812},{7,11,1261},{7,11,1360},{9,11,632},{140,11,352},{5,0,162},{8,0,68},{133, +10,964},{4,0,654},{136,11,212},{4,0,156},{7,0,998},{7,0,1045},{7,0,1860},{9,0,48 +},{9,0,692},{11,0,419},{139,0,602},{133,11,221},{4,11,373},{5,11,283},{6,11,480} +,{135,11,609},{142,11,216},{132,0,240},{6,11,192},{9,11,793},{145,11,55},{4,10, +75},{5,10,180},{6,10,500},{7,10,58},{7,10,710},{138,10,645},{4,11,132},{5,11,69} +,{5,10,649},{135,11,1242},{6,10,276},{7,10,282},{7,10,879},{7,10,924},{8,10,459} +,{9,10,599},{9,10,754},{11,10,574},{12,10,128},{12,10,494},{13,10,52},{13,10,301 +},{15,10,30},{143,10,132},{132,10,200},{4,11,111},{135,11,302},{9,0,197},{10,0, +300},{12,0,473},{13,0,90},{141,0,405},{132,11,767},{6,11,42},{7,11,1416},{7,11, +1590},{7,11,2005},{8,11,131},{8,11,466},{9,11,672},{13,11,252},{148,11,103},{8,0 +,958},{8,0,999},{10,0,963},{138,0,1001},{135,10,1621},{135,0,858},{4,0,606},{137 +,11,444},{6,11,44},{136,11,368},{139,11,172},{4,11,570},{133,11,120},{139,11,624 +},{7,0,1978},{8,0,676},{6,10,225},{137,10,211},{7,0,972},{11,0,102},{136,10,687} +,{6,11,227},{135,11,1589},{8,10,58},{9,10,724},{11,10,809},{13,10,113},{145,10, +72},{4,0,361},{133,0,315},{132,0,461},{6,10,345},{135,10,1247},{132,0,472},{8,10 +,767},{8,10,803},{9,10,301},{137,10,903},{135,11,1333},{135,11,477},{7,10,1949}, +{136,10,674},{6,0,905},{138,0,747},{133,0,155},{134,10,259},{7,0,163},{8,0,319}, +{9,0,402},{10,0,24},{10,0,681},{11,0,200},{12,0,253},{12,0,410},{142,0,219},{5,0 +,475},{7,0,1780},{9,0,230},{11,0,297},{11,0,558},{14,0,322},{19,0,76},{6,11,1667 +},{7,11,2036},{138,11,600},{136,10,254},{6,0,848},{135,0,1956},{6,11,511},{140, +11,132},{5,11,568},{6,11,138},{135,11,1293},{6,0,631},{137,0,838},{149,0,36},{4, +11,565},{8,11,23},{136,11,827},{5,0,944},{134,0,1769},{4,0,144},{6,0,842},{6,0, +1400},{4,11,922},{133,11,1023},{133,10,248},{9,10,800},{10,10,693},{11,10,482},{ +11,10,734},{139,10,789},{7,11,1002},{139,11,145},{4,10,116},{5,10,95},{5,10,445} +,{7,10,1688},{8,10,29},{9,10,272},{11,10,509},{139,10,915},{14,0,369},{146,0,72} +,{135,10,1641},{132,11,740},{133,10,543},{140,11,116},{6,0,247},{9,0,555},{5,10, +181},{136,10,41},{133,10,657},{136,0,996},{138,10,709},{7,0,189},{8,10,202},{138 +,10,536},{136,11,402},{4,11,716},{141,11,31},{10,0,280},{138,0,797},{9,10,423},{ +140,10,89},{8,10,113},{9,10,877},{10,10,554},{11,10,83},{12,10,136},{147,10,109} +,{133,10,976},{7,0,746},{132,10,206},{136,0,526},{139,0,345},{136,0,1017},{8,11, +152},{9,11,53},{9,11,268},{9,11,901},{10,11,518},{10,11,829},{11,11,188},{13,11, +74},{14,11,46},{15,11,17},{15,11,33},{17,11,40},{18,11,36},{19,11,20},{22,11,1}, +{152,11,2},{133,11,736},{136,11,532},{5,0,428},{138,0,651},{135,11,681},{135,0, +1162},{7,0,327},{13,0,230},{17,0,113},{8,10,226},{10,10,537},{11,10,570},{11,10, +605},{11,10,799},{11,10,804},{12,10,85},{12,10,516},{12,10,623},{12,11,677},{13, +10,361},{14,10,77},{14,10,78},{147,10,110},{4,0,792},{7,0,1717},{10,0,546},{132, +10,769},{4,11,684},{136,11,384},{132,10,551},{134,0,1203},{9,10,57},{9,10,459},{ +10,10,425},{11,10,119},{12,10,184},{12,10,371},{13,10,358},{145,10,51},{5,0,672} +,{5,10,814},{8,10,10},{9,10,421},{9,10,729},{10,10,609},{139,10,689},{138,0,189} +,{134,10,624},{7,11,110},{7,11,188},{8,11,290},{8,11,591},{9,11,382},{9,11,649}, +{11,11,71},{11,11,155},{11,11,313},{12,11,5},{13,11,325},{142,11,287},{133,0,99} +,{6,0,1053},{135,0,298},{7,11,360},{7,11,425},{9,11,66},{9,11,278},{138,11,644}, +{4,0,397},{136,0,555},{137,10,269},{132,10,528},{4,11,900},{133,11,861},{6,0, +1157},{5,11,254},{7,11,985},{136,11,73},{7,11,1959},{136,11,683},{12,0,398},{20, +0,39},{21,0,11},{150,0,41},{4,0,485},{7,0,353},{135,0,1523},{6,0,366},{7,0,1384} +,{135,0,1601},{138,0,787},{137,0,282},{5,10,104},{6,10,173},{135,10,1631},{139, +11,146},{4,0,157},{133,0,471},{134,0,941},{132,11,725},{7,0,1336},{8,10,138},{8, +10,342},{9,10,84},{10,10,193},{11,10,883},{140,10,359},{134,11,196},{136,0,116}, +{133,11,831},{134,0,787},{134,10,95},{6,10,406},{10,10,409},{10,10,447},{11,10, +44},{140,10,100},{5,0,160},{7,0,363},{7,0,589},{10,0,170},{141,0,55},{134,0,1815 +},{132,0,866},{6,0,889},{6,0,1067},{6,0,1183},{4,11,321},{134,11,569},{5,11,848} +,{134,11,66},{4,11,36},{6,10,1636},{7,11,1387},{10,11,205},{11,11,755},{141,11, +271},{132,0,689},{9,0,820},{4,10,282},{7,10,1034},{11,10,398},{11,10,634},{12,10 +,1},{12,10,79},{12,10,544},{14,10,237},{17,10,10},{146,10,20},{4,0,108},{7,0,804 +},{139,0,498},{132,11,887},{6,0,1119},{135,11,620},{6,11,165},{138,11,388},{5,0, +244},{5,10,499},{6,10,476},{7,10,600},{7,10,888},{135,10,1096},{140,0,609},{135, +0,1005},{4,0,412},{133,0,581},{4,11,719},{135,11,155},{7,10,296},{7,10,596},{8, +10,560},{8,10,586},{9,10,612},{11,10,304},{12,10,46},{13,10,89},{14,10,112},{145 +,10,122},{4,0,895},{133,0,772},{142,11,307},{135,0,1898},{4,0,926},{133,0,983},{ +4,11,353},{6,11,146},{6,11,1789},{7,11,288},{7,11,990},{7,11,1348},{9,11,665},{9 +,11,898},{11,11,893},{142,11,212},{132,0,538},{133,11,532},{6,0,294},{7,0,1267}, +{8,0,624},{141,0,496},{7,0,1325},{4,11,45},{135,11,1257},{138,0,301},{9,0,298},{ +12,0,291},{13,0,276},{14,0,6},{17,0,18},{21,0,32},{7,10,1599},{7,10,1723},{8,10, +79},{8,10,106},{8,10,190},{8,10,302},{8,10,383},{8,10,713},{9,10,119},{9,10,233} +,{9,10,419},{9,10,471},{10,10,181},{10,10,406},{11,10,57},{11,10,85},{11,10,120} +,{11,10,177},{11,10,296},{11,10,382},{11,10,454},{11,10,758},{11,10,999},{12,10, +27},{12,10,131},{12,10,245},{12,10,312},{12,10,446},{12,10,454},{13,10,98},{13, +10,426},{13,10,508},{14,10,163},{14,10,272},{14,10,277},{14,10,370},{15,10,95},{ +15,10,138},{15,10,167},{17,10,38},{148,10,96},{132,0,757},{134,0,1263},{4,0,820} +,{134,10,1759},{133,0,722},{136,11,816},{138,10,372},{145,10,16},{134,0,1039},{4 +,0,991},{134,0,2028},{133,10,258},{7,0,1875},{139,0,124},{6,11,559},{6,11,1691}, +{135,11,586},{5,0,324},{7,0,881},{8,10,134},{9,10,788},{140,10,438},{7,11,1823}, +{139,11,693},{6,0,1348},{134,0,1545},{134,0,911},{132,0,954},{8,0,329},{8,0,414} +,{7,10,1948},{135,10,2004},{5,0,517},{6,10,439},{7,10,780},{135,10,1040},{132,0, +816},{5,10,1},{6,10,81},{138,10,520},{9,0,713},{10,0,222},{5,10,482},{8,10,98},{ +10,10,700},{10,10,822},{11,10,302},{11,10,778},{12,10,50},{12,10,127},{12,10,396 +},{13,10,62},{13,10,328},{14,10,122},{147,10,72},{137,0,33},{5,10,2},{7,10,1494} +,{136,10,589},{6,10,512},{7,10,797},{8,10,253},{9,10,77},{10,10,1},{10,11,108},{ +10,10,129},{10,10,225},{11,11,116},{11,10,118},{11,10,226},{11,10,251},{11,10, +430},{11,10,701},{11,10,974},{11,10,982},{12,10,64},{12,10,260},{12,10,488},{140 +,10,690},{134,11,456},{133,11,925},{5,0,150},{7,0,106},{7,0,774},{8,0,603},{9,0, +593},{9,0,634},{10,0,44},{10,0,173},{11,0,462},{11,0,515},{13,0,216},{13,0,288}, +{142,0,400},{137,10,347},{5,0,748},{134,0,553},{12,0,108},{141,0,291},{7,0,420}, +{4,10,12},{7,10,522},{7,10,809},{8,10,797},{141,10,88},{6,11,193},{7,11,240},{7, +11,1682},{10,11,51},{10,11,640},{11,11,410},{13,11,82},{14,11,247},{14,11,331},{ +142,11,377},{133,10,528},{135,0,1777},{4,0,493},{144,0,55},{136,11,633},{139,0, +81},{6,0,980},{136,0,321},{148,10,109},{5,10,266},{9,10,290},{9,10,364},{10,10, +293},{11,10,606},{142,10,45},{6,0,568},{7,0,112},{7,0,1804},{8,0,362},{8,0,410}, +{8,0,830},{9,0,514},{11,0,649},{142,0,157},{4,0,74},{6,0,510},{6,10,594},{9,10, +121},{10,10,49},{10,10,412},{139,10,834},{134,0,838},{136,10,748},{132,10,466},{ +132,0,625},{135,11,1443},{4,11,237},{135,11,514},{9,10,378},{141,10,162},{6,0,16 +},{6,0,158},{7,0,43},{7,0,129},{7,0,181},{8,0,276},{8,0,377},{10,0,523},{11,0, +816},{12,0,455},{13,0,303},{142,0,135},{135,0,281},{4,0,1},{7,0,1143},{7,0,1463} +,{8,0,61},{9,0,207},{9,0,390},{9,0,467},{139,0,836},{6,11,392},{7,11,65},{135,11 +,2019},{132,10,667},{4,0,723},{5,0,895},{7,0,1031},{8,0,199},{8,0,340},{9,0,153} +,{9,0,215},{10,0,21},{10,0,59},{10,0,80},{10,0,224},{10,0,838},{11,0,229},{11,0, +652},{12,0,192},{13,0,146},{142,0,91},{132,0,295},{137,0,51},{9,11,222},{10,11, +43},{139,11,900},{5,0,309},{140,0,211},{5,0,125},{8,0,77},{138,0,15},{136,11,604 +},{138,0,789},{5,0,173},{4,10,39},{7,10,1843},{8,10,407},{11,10,144},{140,10,523 +},{138,11,265},{133,0,439},{132,10,510},{7,0,648},{7,0,874},{11,0,164},{12,0,76} +,{18,0,9},{7,10,1980},{10,10,487},{138,10,809},{12,0,111},{14,0,294},{19,0,45},{ +13,10,260},{146,10,63},{133,11,549},{134,10,570},{4,0,8},{7,0,1152},{7,0,1153},{ +7,0,1715},{9,0,374},{10,0,478},{139,0,648},{135,0,1099},{5,0,575},{6,0,354},{135 +,0,701},{7,11,36},{8,11,201},{136,11,605},{4,10,787},{136,11,156},{6,0,518},{149 +,11,13},{140,11,224},{134,0,702},{132,10,516},{5,11,724},{10,11,305},{11,11,151} +,{12,11,33},{12,11,121},{12,11,381},{17,11,3},{17,11,27},{17,11,78},{18,11,18},{ +19,11,54},{149,11,5},{8,0,87},{4,11,523},{5,11,638},{11,10,887},{14,10,365},{142 +,10,375},{138,0,438},{136,10,821},{135,11,1908},{6,11,242},{7,11,227},{7,11,1581 +},{8,11,104},{9,11,113},{9,11,220},{9,11,427},{10,11,74},{10,11,239},{11,11,579} +,{11,11,1023},{13,11,4},{13,11,204},{13,11,316},{18,11,95},{148,11,86},{4,0,69}, +{5,0,122},{5,0,849},{6,0,1633},{9,0,656},{138,0,464},{7,0,1802},{4,10,10},{139, +10,786},{135,11,861},{139,0,499},{7,0,476},{7,0,1592},{138,0,87},{133,10,684},{4 +,0,840},{134,10,27},{142,0,283},{6,0,1620},{7,11,1328},{136,11,494},{5,0,859},{7 +,0,1160},{8,0,107},{9,0,291},{9,0,439},{10,0,663},{11,0,609},{140,0,197},{7,11, +1306},{8,11,505},{9,11,482},{10,11,126},{11,11,225},{12,11,347},{12,11,449},{13, +11,19},{142,11,218},{5,11,268},{10,11,764},{12,11,120},{13,11,39},{145,11,127},{ +145,10,56},{7,11,1672},{10,11,472},{11,11,189},{143,11,51},{6,10,342},{6,10,496} +,{8,10,275},{137,10,206},{133,0,600},{4,0,117},{6,0,372},{7,0,1905},{142,0,323}, +{4,10,909},{5,10,940},{135,11,1471},{132,10,891},{4,0,722},{139,0,471},{4,11,384 +},{135,11,1022},{132,10,687},{9,0,5},{12,0,216},{12,0,294},{12,0,298},{12,0,400} +,{12,0,518},{13,0,229},{143,0,139},{135,11,1703},{7,11,1602},{10,11,698},{12,11, +212},{141,11,307},{6,10,41},{141,10,160},{135,11,1077},{9,11,159},{11,11,28},{ +140,11,603},{4,0,514},{7,0,1304},{138,0,477},{134,0,1774},{9,0,88},{139,0,270},{ +5,0,12},{7,0,375},{9,0,438},{134,10,1718},{132,11,515},{136,10,778},{8,11,632},{ +8,11,697},{137,11,854},{6,0,362},{6,0,997},{146,0,51},{7,0,816},{7,0,1241},{9,0, +283},{9,0,520},{10,0,213},{10,0,307},{10,0,463},{10,0,671},{10,0,746},{11,0,401} +,{11,0,794},{12,0,517},{18,0,107},{147,0,115},{133,10,115},{150,11,28},{4,11,136 +},{133,11,551},{142,10,314},{132,0,258},{6,0,22},{7,0,903},{7,0,1963},{8,0,639}, +{138,0,577},{5,0,681},{8,0,782},{13,0,130},{17,0,84},{5,10,193},{140,10,178},{9, +11,17},{138,11,291},{7,11,1287},{9,11,44},{10,11,552},{10,11,642},{11,11,839},{ +12,11,274},{12,11,275},{12,11,372},{13,11,91},{142,11,125},{135,10,174},{4,0,664 +},{5,0,804},{139,0,1013},{134,0,942},{6,0,1349},{6,0,1353},{6,0,1450},{7,11,1518 +},{139,11,694},{11,0,356},{4,10,122},{5,10,796},{5,10,952},{6,10,1660},{6,10, +1671},{8,10,567},{9,10,687},{9,10,742},{10,10,686},{11,10,682},{140,10,281},{5,0 +,32},{6,11,147},{7,11,886},{9,11,753},{138,11,268},{5,10,179},{7,10,1095},{135, +10,1213},{4,10,66},{7,10,722},{135,10,904},{135,10,352},{9,11,245},{138,11,137}, +{4,0,289},{7,0,629},{7,0,1698},{7,0,1711},{12,0,215},{133,11,414},{6,0,1975},{ +135,11,1762},{6,0,450},{136,0,109},{141,10,35},{134,11,599},{136,0,705},{133,0, +664},{134,11,1749},{11,11,402},{12,11,109},{12,11,431},{13,11,179},{13,11,206},{ +14,11,175},{14,11,217},{16,11,3},{148,11,53},{135,0,1238},{134,11,1627},{132,11, +488},{13,0,318},{10,10,592},{10,10,753},{12,10,317},{12,10,355},{12,10,465},{12, +10,469},{12,10,560},{140,10,578},{133,10,564},{132,11,83},{140,11,676},{6,0,1872 +},{6,0,1906},{6,0,1907},{9,0,934},{9,0,956},{9,0,960},{9,0,996},{12,0,794},{12,0 +,876},{12,0,880},{12,0,918},{15,0,230},{18,0,234},{18,0,238},{21,0,38},{149,0,62 +},{134,10,556},{134,11,278},{137,0,103},{7,10,544},{8,10,719},{138,10,61},{4,10, +5},{5,10,498},{8,10,637},{137,10,521},{7,0,777},{12,0,229},{12,0,239},{15,0,12}, +{12,11,229},{12,11,239},{143,11,12},{6,0,26},{7,11,388},{7,11,644},{139,11,781}, +{7,11,229},{8,11,59},{9,11,190},{9,11,257},{10,11,378},{140,11,191},{133,10,927} +,{135,10,1441},{4,10,893},{5,10,780},{133,10,893},{4,0,414},{5,0,467},{9,0,654}, +{10,0,451},{12,0,59},{141,0,375},{142,0,173},{135,0,17},{7,0,1350},{133,10,238}, +{135,0,955},{4,0,960},{10,0,887},{12,0,753},{18,0,161},{18,0,162},{152,0,19},{ +136,11,344},{6,10,1729},{137,11,288},{132,11,660},{4,0,217},{5,0,710},{7,0,760}, +{7,0,1926},{9,0,428},{9,0,708},{10,0,254},{10,0,296},{10,0,720},{11,0,109},{11,0 +,255},{12,0,165},{12,0,315},{13,0,107},{13,0,203},{14,0,54},{14,0,99},{14,0,114} +,{14,0,388},{16,0,85},{17,0,9},{17,0,33},{20,0,25},{20,0,28},{20,0,29},{21,0,9}, +{21,0,10},{21,0,34},{22,0,17},{4,10,60},{7,10,1800},{8,10,314},{9,10,700},{139, +10,487},{7,11,1035},{138,11,737},{7,11,690},{9,11,217},{9,11,587},{140,11,521},{ +6,0,919},{7,11,706},{7,11,1058},{138,11,538},{7,10,1853},{138,10,437},{136,10, +419},{6,0,280},{10,0,502},{11,0,344},{140,0,38},{5,0,45},{7,0,1161},{11,0,448},{ +11,0,880},{13,0,139},{13,0,407},{15,0,16},{17,0,95},{18,0,66},{18,0,88},{18,0, +123},{149,0,7},{11,11,92},{11,11,196},{11,11,409},{11,11,450},{11,11,666},{11,11 +,777},{12,11,262},{13,11,385},{13,11,393},{15,11,115},{16,11,45},{145,11,82},{ +136,0,777},{134,11,1744},{4,0,410},{7,0,521},{133,10,828},{134,0,673},{7,0,1110} +,{7,0,1778},{7,10,176},{135,10,178},{5,10,806},{7,11,268},{7,10,1976},{136,11, +569},{4,11,733},{9,11,194},{10,11,92},{11,11,198},{12,11,84},{12,11,87},{13,11, +128},{144,11,74},{5,0,341},{7,0,1129},{11,0,414},{4,10,51},{6,10,4},{7,10,591},{ +7,10,849},{7,10,951},{7,10,1613},{7,10,1760},{7,10,1988},{9,10,434},{10,10,754}, +{11,10,25},{139,10,37},{133,10,902},{135,10,928},{135,0,787},{132,0,436},{134,10 +,270},{7,0,1587},{135,0,1707},{6,0,377},{7,0,1025},{9,0,613},{145,0,104},{7,11, +982},{7,11,1361},{10,11,32},{143,11,56},{139,0,96},{132,0,451},{132,10,416},{142 +,10,372},{5,10,152},{5,10,197},{7,11,306},{7,10,340},{7,10,867},{10,10,548},{10, +10,581},{11,10,6},{12,10,3},{12,10,19},{14,10,110},{142,10,289},{134,0,680},{134 +,11,609},{7,0,483},{7,10,190},{8,10,28},{8,10,141},{8,10,444},{8,10,811},{9,10, +468},{11,10,334},{12,10,24},{12,10,386},{140,10,576},{10,0,916},{133,10,757},{5, +10,721},{135,10,1553},{133,11,178},{134,0,937},{132,10,898},{133,0,739},{147,0, +82},{135,0,663},{146,0,128},{5,10,277},{141,10,247},{134,0,1087},{132,10,435},{6 +,11,381},{7,11,645},{7,11,694},{136,11,546},{7,0,503},{135,0,1885},{6,0,1965},{8 +,0,925},{138,0,955},{4,0,113},{5,0,163},{5,0,735},{7,0,1009},{9,0,9},{9,0,771},{ +12,0,90},{13,0,138},{13,0,410},{143,0,128},{4,0,324},{138,0,104},{7,0,460},{5,10 +,265},{134,10,212},{133,11,105},{7,11,261},{7,11,1107},{7,11,1115},{7,11,1354},{ +7,11,1588},{7,11,1705},{7,11,1902},{9,11,465},{10,11,248},{10,11,349},{10,11,647 +},{11,11,527},{11,11,660},{11,11,669},{12,11,529},{141,11,305},{5,11,438},{9,11, +694},{12,11,627},{141,11,210},{152,11,11},{4,0,935},{133,0,823},{132,10,702},{5, +0,269},{7,0,434},{7,0,891},{8,0,339},{9,0,702},{11,0,594},{11,0,718},{17,0,100}, +{5,10,808},{135,10,2045},{7,0,1014},{9,0,485},{141,0,264},{134,0,1713},{7,0,1810 +},{11,0,866},{12,0,103},{13,0,495},{140,11,233},{4,0,423},{10,0,949},{138,0,1013 +},{135,0,900},{8,11,25},{138,11,826},{5,10,166},{8,10,739},{140,10,511},{134,0, +2018},{7,11,1270},{139,11,612},{4,10,119},{5,10,170},{5,10,447},{7,10,1708},{7, +10,1889},{9,10,357},{9,10,719},{12,10,486},{140,10,596},{12,0,574},{140,11,574}, +{132,11,308},{6,0,964},{6,0,1206},{134,0,1302},{4,10,450},{135,10,1158},{135,11, +150},{136,11,649},{14,0,213},{148,0,38},{9,11,45},{9,11,311},{141,11,42},{134,11 +,521},{7,10,1375},{7,10,1466},{138,10,331},{132,10,754},{5,11,339},{7,11,1442},{ +14,11,3},{15,11,41},{147,11,66},{136,11,378},{134,0,1022},{5,10,850},{136,10,799 +},{142,0,143},{135,0,2029},{134,11,1628},{8,0,523},{150,0,34},{5,0,625},{135,0, +1617},{7,0,275},{7,10,238},{7,10,2033},{8,10,120},{8,10,188},{8,10,659},{9,10, +598},{10,10,466},{12,10,342},{12,10,588},{13,10,503},{14,10,246},{143,10,92},{7, +0,37},{8,0,425},{8,0,693},{9,0,720},{10,0,380},{10,0,638},{11,0,273},{11,0,473}, +{12,0,61},{143,0,43},{135,11,829},{135,0,1943},{132,0,765},{5,11,486},{135,11, +1349},{7,11,1635},{8,11,17},{10,11,217},{138,11,295},{4,10,201},{7,10,1744},{8, +10,602},{11,10,247},{11,10,826},{145,10,65},{138,11,558},{11,0,551},{142,0,159}, +{8,10,164},{146,10,62},{139,11,176},{132,0,168},{136,0,1010},{134,0,1994},{135,0 +,91},{138,0,532},{135,10,1243},{135,0,1884},{132,10,907},{5,10,100},{10,10,329}, +{12,10,416},{149,10,29},{134,11,447},{132,10,176},{5,10,636},{5,10,998},{7,10,9} +,{7,10,1508},{8,10,26},{9,10,317},{9,10,358},{10,10,210},{10,10,292},{10,10,533} +,{11,10,555},{12,10,526},{12,10,607},{13,10,263},{13,10,459},{142,10,271},{4,11, +609},{135,11,756},{6,0,15},{7,0,70},{10,0,240},{147,0,93},{4,11,930},{133,11,947 +},{134,0,1227},{134,0,1534},{133,11,939},{133,11,962},{5,11,651},{8,11,170},{9, +11,61},{9,11,63},{10,11,23},{10,11,37},{10,11,834},{11,11,4},{11,11,187},{11,11, +281},{11,11,503},{11,11,677},{12,11,96},{12,11,130},{12,11,244},{14,11,5},{14,11 +,40},{14,11,162},{14,11,202},{146,11,133},{4,11,406},{5,11,579},{12,11,492},{150 +,11,15},{139,0,392},{6,10,610},{10,10,127},{141,10,27},{7,0,655},{7,0,1844},{136 +,10,119},{4,0,145},{6,0,176},{7,0,395},{137,0,562},{132,0,501},{140,11,145},{136 +,0,1019},{134,0,509},{139,0,267},{6,11,17},{7,11,16},{7,11,1001},{7,11,1982},{9, +11,886},{10,11,489},{10,11,800},{11,11,782},{12,11,320},{13,11,467},{14,11,145}, +{14,11,387},{143,11,119},{145,11,17},{6,0,1099},{133,11,458},{7,11,1983},{8,11,0 +},{8,11,171},{9,11,120},{9,11,732},{10,11,473},{11,11,656},{11,11,998},{18,11,0} +,{18,11,2},{147,11,21},{12,11,427},{146,11,38},{10,0,948},{138,0,968},{7,10,126} +,{136,10,84},{136,10,790},{4,0,114},{9,0,492},{13,0,462},{142,0,215},{6,10,64},{ +12,10,377},{141,10,309},{4,0,77},{5,0,361},{6,0,139},{6,0,401},{6,0,404},{7,0, +413},{7,0,715},{7,0,1716},{11,0,279},{12,0,179},{12,0,258},{13,0,244},{142,0,358 +},{134,0,1717},{7,0,772},{7,0,1061},{7,0,1647},{8,0,82},{11,0,250},{11,0,607},{ +12,0,311},{12,0,420},{13,0,184},{13,0,367},{7,10,1104},{11,10,269},{11,10,539},{ +11,10,627},{11,10,706},{11,10,975},{12,10,248},{12,10,434},{12,10,600},{12,10, +622},{13,10,297},{13,10,485},{14,10,69},{14,10,409},{143,10,108},{135,0,724},{4, +11,512},{4,11,519},{133,11,342},{134,0,1133},{145,11,29},{11,10,977},{141,10,507 +},{6,0,841},{6,0,1042},{6,0,1194},{10,0,993},{140,0,1021},{6,11,31},{7,11,491},{ +7,11,530},{8,11,592},{9,10,34},{11,11,53},{11,10,484},{11,11,779},{12,11,167},{ +12,11,411},{14,11,14},{14,11,136},{15,11,72},{16,11,17},{144,11,72},{4,0,1021},{ +6,0,2037},{133,11,907},{7,0,373},{8,0,335},{8,0,596},{9,0,488},{6,10,1700},{7,10 +,293},{7,10,382},{7,10,1026},{7,10,1087},{7,10,2027},{8,10,252},{8,10,727},{8,10 +,729},{9,10,30},{9,10,199},{9,10,231},{9,10,251},{9,10,334},{9,10,361},{9,10,712 +},{10,10,55},{10,10,60},{10,10,232},{10,10,332},{10,10,384},{10,10,396},{10,10, +504},{10,10,542},{10,10,652},{11,10,20},{11,10,48},{11,10,207},{11,10,291},{11, +10,298},{11,10,342},{11,10,365},{11,10,394},{11,10,620},{11,10,705},{11,10,1017} +,{12,10,123},{12,10,340},{12,10,406},{12,10,643},{13,10,61},{13,10,269},{13,10, +311},{13,10,319},{13,10,486},{14,10,234},{15,10,62},{15,10,85},{16,10,71},{18,10 +,119},{148,10,105},{150,0,37},{4,11,208},{5,11,106},{6,11,531},{8,11,408},{9,11, +188},{138,11,572},{132,0,564},{6,0,513},{135,0,1052},{132,0,825},{9,0,899},{140, +11,441},{134,0,778},{133,11,379},{7,0,1417},{12,0,382},{17,0,48},{152,0,12},{132 +,11,241},{7,0,1116},{6,10,379},{7,10,270},{8,10,176},{8,10,183},{9,10,432},{9,10 +,661},{12,10,247},{12,10,617},{146,10,125},{5,10,792},{133,10,900},{6,0,545},{7, +0,565},{7,0,1669},{10,0,114},{11,0,642},{140,0,618},{133,0,5},{138,11,7},{132,11 +,259},{135,0,192},{134,0,701},{136,0,763},{135,10,1979},{4,10,901},{133,10,776}, +{10,0,755},{147,0,29},{133,0,759},{4,11,173},{5,11,312},{5,11,512},{135,11,1285} +,{7,11,1603},{7,11,1691},{9,11,464},{11,11,195},{12,11,279},{12,11,448},{14,11, +11},{147,11,102},{7,0,370},{7,0,1007},{7,0,1177},{135,0,1565},{135,0,1237},{4,0, +87},{5,0,250},{141,0,298},{4,11,452},{5,11,583},{5,11,817},{6,11,433},{7,11,593} +,{7,11,720},{7,11,1378},{8,11,161},{9,11,284},{10,11,313},{139,11,886},{4,11,547 +},{135,11,1409},{136,11,722},{4,10,37},{5,10,334},{135,10,1253},{132,10,508},{12 +,0,107},{146,0,31},{8,11,420},{139,11,193},{135,0,814},{135,11,409},{140,0,991}, +{4,0,57},{7,0,1195},{7,0,1438},{7,0,1548},{7,0,1835},{7,0,1904},{9,0,757},{10,0, +604},{139,0,519},{132,0,540},{138,11,308},{132,10,533},{136,0,608},{144,11,65},{ +4,0,1014},{134,0,2029},{4,0,209},{7,0,902},{5,11,1002},{136,11,745},{134,0,2030} +,{6,0,303},{7,0,335},{7,0,1437},{7,0,1668},{8,0,553},{8,0,652},{8,0,656},{9,0, +558},{11,0,743},{149,0,18},{5,11,575},{6,11,354},{135,11,701},{4,11,239},{6,11, +477},{7,11,1607},{11,11,68},{139,11,617},{132,0,559},{8,0,527},{18,0,60},{147,0, +24},{133,10,920},{138,0,511},{133,0,1017},{133,0,675},{138,10,391},{11,0,156},{ +135,10,1952},{138,11,369},{132,11,367},{133,0,709},{6,0,698},{134,0,887},{142,10 +,126},{134,0,1745},{132,10,483},{13,11,299},{142,11,75},{133,0,714},{7,0,8},{136 +,0,206},{138,10,480},{4,11,694},{9,10,495},{146,10,104},{7,11,1248},{11,11,621}, +{139,11,702},{140,11,687},{132,0,776},{139,10,1009},{135,0,1272},{134,0,1059},{8 +,10,653},{13,10,93},{147,10,14},{135,11,213},{136,0,406},{133,10,172},{132,0,947 +},{8,0,175},{10,0,168},{138,0,573},{132,0,870},{6,0,1567},{151,11,28},{134,11, +472},{5,10,260},{136,11,132},{4,11,751},{11,11,390},{140,11,32},{4,11,409},{133, +11,78},{12,0,554},{6,11,473},{145,11,105},{133,0,784},{8,0,908},{136,11,306},{ +139,0,882},{6,0,358},{7,0,1393},{8,0,396},{10,0,263},{14,0,154},{16,0,48},{17,0, +8},{7,11,1759},{8,11,396},{10,11,263},{14,11,154},{16,11,48},{145,11,8},{13,11, +163},{13,11,180},{18,11,78},{148,11,35},{14,0,32},{18,0,85},{20,0,2},{152,0,16}, +{7,0,228},{10,0,770},{8,10,167},{8,10,375},{9,10,82},{9,10,561},{138,10,620},{ +132,0,845},{9,0,14},{9,0,441},{10,0,306},{139,0,9},{11,0,966},{12,0,287},{13,0, +342},{13,0,402},{15,0,110},{15,0,163},{8,10,194},{136,10,756},{134,0,1578},{4,0, +967},{6,0,1820},{6,0,1847},{140,0,716},{136,0,594},{7,0,1428},{7,0,1640},{7,0, +1867},{9,0,169},{9,0,182},{9,0,367},{9,0,478},{9,0,506},{9,0,551},{9,0,557},{9,0 +,648},{9,0,697},{9,0,705},{9,0,725},{9,0,787},{9,0,794},{10,0,198},{10,0,214},{ +10,0,267},{10,0,275},{10,0,456},{10,0,551},{10,0,561},{10,0,613},{10,0,627},{10, +0,668},{10,0,675},{10,0,691},{10,0,695},{10,0,707},{10,0,715},{11,0,183},{11,0, +201},{11,0,244},{11,0,262},{11,0,352},{11,0,439},{11,0,493},{11,0,572},{11,0,591 +},{11,0,608},{11,0,611},{11,0,646},{11,0,674},{11,0,711},{11,0,751},{11,0,761},{ +11,0,776},{11,0,785},{11,0,850},{11,0,853},{11,0,862},{11,0,865},{11,0,868},{11, +0,875},{11,0,898},{11,0,902},{11,0,903},{11,0,910},{11,0,932},{11,0,942},{11,0, +957},{11,0,967},{11,0,972},{12,0,148},{12,0,195},{12,0,220},{12,0,237},{12,0,318 +},{12,0,339},{12,0,393},{12,0,445},{12,0,450},{12,0,474},{12,0,505},{12,0,509},{ +12,0,533},{12,0,591},{12,0,594},{12,0,597},{12,0,621},{12,0,633},{12,0,642},{13, +0,59},{13,0,60},{13,0,145},{13,0,239},{13,0,250},{13,0,329},{13,0,344},{13,0,365 +},{13,0,372},{13,0,387},{13,0,403},{13,0,414},{13,0,456},{13,0,470},{13,0,478},{ +13,0,483},{13,0,489},{14,0,55},{14,0,57},{14,0,81},{14,0,90},{14,0,148},{14,0, +239},{14,0,266},{14,0,321},{14,0,326},{14,0,327},{14,0,330},{14,0,347},{14,0,355 +},{14,0,401},{14,0,404},{14,0,411},{14,0,414},{14,0,416},{14,0,420},{15,0,61},{ +15,0,74},{15,0,87},{15,0,88},{15,0,94},{15,0,96},{15,0,116},{15,0,149},{15,0,154 +},{16,0,50},{16,0,63},{16,0,73},{17,0,2},{17,0,66},{17,0,92},{17,0,103},{17,0, +112},{17,0,120},{18,0,50},{18,0,54},{18,0,82},{18,0,86},{18,0,90},{18,0,111},{18 +,0,115},{18,0,156},{19,0,40},{19,0,79},{20,0,78},{21,0,22},{135,11,883},{5,0,161 +},{135,0,839},{4,0,782},{13,11,293},{142,11,56},{133,11,617},{139,11,50},{135,10 +,22},{145,0,64},{5,10,639},{7,10,1249},{139,10,896},{138,0,998},{135,11,2042},{4 +,11,546},{142,11,233},{6,0,1043},{134,0,1574},{134,0,1496},{4,10,102},{7,10,815} +,{7,10,1699},{139,10,964},{12,0,781},{142,0,461},{4,11,313},{133,11,577},{6,0, +639},{6,0,1114},{137,0,817},{8,11,184},{141,11,433},{7,0,1814},{135,11,935},{10, +0,997},{140,0,958},{4,0,812},{137,11,625},{132,10,899},{136,10,795},{5,11,886},{ +6,11,46},{6,11,1790},{7,11,14},{7,11,732},{7,11,1654},{8,11,95},{8,11,327},{8,11 +,616},{10,11,598},{10,11,769},{11,11,134},{11,11,747},{12,11,378},{142,11,97},{ +136,0,139},{6,10,52},{9,10,104},{9,10,559},{12,10,308},{147,10,87},{133,11,1021} +,{132,10,604},{132,10,301},{136,10,779},{7,0,643},{136,0,236},{132,11,153},{134, +0,1172},{147,10,32},{133,11,798},{6,0,1338},{132,11,587},{6,11,598},{7,11,42},{8 +,11,695},{10,11,212},{11,11,158},{14,11,196},{145,11,85},{135,10,508},{5,11,957} +,{5,11,1008},{135,11,249},{4,11,129},{135,11,465},{5,0,54},{7,11,470},{7,11,1057 +},{7,11,1201},{9,11,755},{11,11,906},{140,11,527},{7,11,908},{146,11,7},{5,11, +148},{136,11,450},{144,11,1},{4,0,256},{135,0,1488},{9,0,351},{6,10,310},{7,10, +1849},{8,10,72},{8,10,272},{8,10,431},{9,10,12},{10,10,563},{10,10,630},{10,10, +796},{10,10,810},{11,10,367},{11,10,599},{11,10,686},{140,10,672},{6,0,1885},{6, +0,1898},{6,0,1899},{140,0,955},{4,0,714},{133,0,469},{6,0,1270},{134,0,1456},{ +132,0,744},{6,0,313},{7,10,537},{8,10,64},{9,10,127},{10,10,496},{12,10,510},{ +141,10,384},{4,11,217},{4,10,244},{5,11,710},{7,10,233},{7,11,1926},{9,11,428},{ +9,11,708},{10,11,254},{10,11,296},{10,11,720},{11,11,109},{11,11,255},{12,11,165 +},{12,11,315},{13,11,107},{13,11,203},{14,11,54},{14,11,99},{14,11,114},{14,11, +388},{16,11,85},{17,11,9},{17,11,33},{20,11,25},{20,11,28},{20,11,29},{21,11,9}, +{21,11,10},{21,11,34},{150,11,17},{138,0,402},{7,0,969},{146,0,55},{8,0,50},{137 +,0,624},{134,0,1355},{132,0,572},{134,10,1650},{10,10,702},{139,10,245},{10,0, +847},{142,0,445},{6,0,43},{7,0,38},{8,0,248},{138,0,513},{133,0,369},{137,10,338 +},{133,0,766},{133,0,363},{133,10,896},{8,11,392},{11,11,54},{13,11,173},{13,11, +294},{148,11,7},{134,0,678},{7,11,1230},{136,11,531},{6,0,258},{140,0,409},{5,0, +249},{148,0,82},{7,10,1117},{136,10,539},{5,0,393},{6,0,378},{7,0,1981},{9,0,32} +,{9,0,591},{10,0,685},{10,0,741},{142,0,382},{133,0,788},{134,0,1281},{134,0, +1295},{7,0,1968},{141,0,509},{4,0,61},{5,0,58},{5,0,171},{5,0,683},{6,0,291},{6, +0,566},{7,0,1650},{11,0,523},{12,0,273},{12,0,303},{15,0,39},{143,0,111},{6,0, +706},{134,0,1283},{134,0,589},{135,11,1433},{133,11,435},{7,0,1059},{13,0,54},{5 +,10,4},{5,10,810},{6,10,13},{6,10,538},{6,10,1690},{6,10,1726},{7,10,1819},{8,10 +,148},{8,10,696},{8,10,791},{12,10,125},{143,10,9},{135,10,1268},{5,11,85},{6,11 +,419},{7,11,134},{7,11,305},{7,11,361},{7,11,1337},{8,11,71},{140,11,519},{137,0 +,824},{140,11,688},{5,11,691},{7,11,345},{7,10,1385},{9,11,94},{11,10,582},{11, +10,650},{11,10,901},{11,10,949},{12,11,169},{12,10,232},{12,10,236},{13,10,413}, +{13,10,501},{146,10,116},{4,0,917},{133,0,1005},{7,0,1598},{5,11,183},{6,11,582} +,{9,11,344},{10,11,679},{140,11,435},{4,10,925},{5,10,803},{8,10,698},{138,10, +828},{132,0,919},{135,11,511},{139,10,992},{4,0,255},{5,0,302},{6,0,132},{7,0, +128},{7,0,283},{7,0,1299},{10,0,52},{10,0,514},{11,0,925},{13,0,92},{142,0,309}, +{134,0,1369},{135,10,1847},{134,0,328},{7,11,1993},{136,11,684},{133,10,383},{ +137,0,173},{134,11,583},{134,0,1411},{19,0,65},{5,11,704},{8,11,357},{10,11,745} +,{14,11,426},{17,11,94},{147,11,57},{9,10,660},{138,10,347},{4,11,179},{5,11,198 +},{133,11,697},{7,11,347},{7,11,971},{8,11,181},{138,11,711},{141,0,442},{11,0, +842},{11,0,924},{13,0,317},{13,0,370},{13,0,469},{13,0,471},{14,0,397},{18,0,69} +,{18,0,145},{7,10,572},{9,10,592},{11,10,680},{12,10,356},{140,10,550},{14,11,19 +},{14,11,28},{144,11,29},{136,0,534},{4,11,243},{5,11,203},{7,11,19},{7,11,71},{ +7,11,113},{10,11,405},{11,11,357},{142,11,240},{6,0,210},{10,0,845},{138,0,862}, +{7,11,1351},{9,11,581},{10,11,639},{11,11,453},{140,11,584},{7,11,1450},{139,11, +99},{10,0,892},{12,0,719},{144,0,105},{4,0,284},{6,0,223},{134,11,492},{5,11,134 +},{6,11,408},{6,11,495},{135,11,1593},{136,0,529},{137,0,807},{4,0,218},{7,0,526 +},{143,0,137},{6,0,1444},{142,11,4},{132,11,665},{4,0,270},{5,0,192},{6,0,332},{ +7,0,1322},{4,11,248},{7,11,137},{137,11,349},{140,0,661},{7,0,1517},{11,0,597},{ +14,0,76},{14,0,335},{20,0,33},{7,10,748},{139,10,700},{5,11,371},{135,11,563},{ +146,11,57},{133,10,127},{133,0,418},{4,11,374},{7,11,547},{7,11,1700},{7,11,1833 +},{139,11,858},{6,10,198},{140,10,83},{7,11,1812},{13,11,259},{13,11,356},{14,11 +,242},{147,11,114},{7,0,379},{8,0,481},{9,0,377},{5,10,276},{6,10,55},{135,10, +1369},{138,11,286},{5,0,1003},{6,0,149},{6,10,1752},{136,10,726},{8,0,262},{9,0, +627},{10,0,18},{11,0,214},{11,0,404},{11,0,457},{11,0,780},{11,0,913},{13,0,401} +,{14,0,200},{6,11,1647},{7,11,1552},{7,11,2010},{9,11,494},{137,11,509},{135,0, +742},{136,0,304},{132,0,142},{133,10,764},{6,10,309},{7,10,331},{138,10,550},{ +135,10,1062},{6,11,123},{7,11,214},{7,10,986},{9,11,728},{10,11,157},{11,11,346} +,{11,11,662},{143,11,106},{135,10,1573},{7,0,925},{137,0,799},{4,0,471},{5,0,51} +,{6,0,602},{8,0,484},{138,0,195},{136,0,688},{132,0,697},{6,0,1169},{6,0,1241},{ +6,10,194},{7,10,133},{10,10,493},{10,10,570},{139,10,664},{140,0,751},{7,0,929}, +{10,0,452},{11,0,878},{16,0,33},{5,10,24},{5,10,569},{6,10,3},{6,10,119},{6,10, +143},{6,10,440},{7,10,599},{7,10,1686},{7,10,1854},{8,10,424},{9,10,43},{9,10, +584},{9,10,760},{10,10,328},{11,10,159},{11,10,253},{12,10,487},{140,10,531},{4, +11,707},{13,11,106},{18,11,49},{147,11,41},{5,0,221},{5,11,588},{134,11,393},{ +134,0,1437},{6,11,211},{7,11,1690},{11,11,486},{140,11,369},{5,10,14},{5,10,892} +,{6,10,283},{7,10,234},{136,10,537},{4,0,988},{136,0,955},{135,0,1251},{4,10,126 +},{8,10,635},{147,10,34},{4,10,316},{135,10,1561},{137,10,861},{4,10,64},{5,10, +352},{5,10,720},{6,10,368},{139,10,359},{134,0,192},{4,0,132},{5,0,69},{135,0, +1242},{7,10,1577},{10,10,304},{10,10,549},{12,10,365},{13,10,220},{13,10,240},{ +142,10,33},{4,0,111},{7,0,865},{134,11,219},{5,11,582},{6,11,1646},{7,11,99},{7, +11,1962},{7,11,1986},{8,11,515},{8,11,773},{9,11,23},{9,11,491},{12,11,620},{14, +11,52},{145,11,50},{132,0,767},{7,11,568},{148,11,21},{6,0,42},{7,0,1416},{7,0, +2005},{8,0,131},{8,0,466},{9,0,672},{13,0,252},{20,0,103},{133,11,851},{135,0, +1050},{6,10,175},{137,10,289},{5,10,432},{133,10,913},{6,0,44},{136,0,368},{135, +11,784},{132,0,570},{133,0,120},{139,10,595},{140,0,29},{6,0,227},{135,0,1589},{ +4,11,98},{7,11,1365},{9,11,422},{9,11,670},{10,11,775},{11,11,210},{13,11,26},{ +13,11,457},{141,11,476},{140,10,80},{5,10,931},{134,10,1698},{133,0,522},{134,0, +1120},{135,0,1529},{12,0,739},{14,0,448},{142,0,467},{11,10,526},{11,10,939},{ +141,10,290},{5,10,774},{6,10,1637},{6,10,1686},{134,10,1751},{6,0,1667},{135,0, +2036},{7,10,1167},{11,10,934},{13,10,391},{145,10,76},{137,11,147},{6,10,260},{7 +,10,1484},{11,11,821},{12,11,110},{12,11,153},{18,11,41},{150,11,19},{6,0,511},{ +12,0,132},{134,10,573},{5,0,568},{6,0,138},{135,0,1293},{132,0,1020},{8,0,258},{ +9,0,208},{137,0,359},{4,0,565},{8,0,23},{136,0,827},{134,0,344},{4,0,922},{5,0, +1023},{13,11,477},{14,11,120},{148,11,61},{134,0,240},{5,11,209},{6,11,30},{11, +11,56},{139,11,305},{6,0,171},{7,0,1002},{7,0,1324},{9,0,415},{14,0,230},{18,0, +68},{4,10,292},{4,10,736},{5,10,871},{6,10,1689},{7,10,1944},{137,10,580},{9,11, +635},{139,11,559},{4,11,150},{5,11,303},{134,11,327},{6,10,63},{135,10,920},{133 +,10,793},{8,11,192},{10,11,78},{10,11,555},{11,11,308},{13,11,359},{147,11,95},{ +135,11,786},{135,11,1712},{136,0,402},{6,0,754},{6,11,1638},{7,11,79},{7,11,496} +,{9,11,138},{10,11,336},{11,11,12},{12,11,412},{12,11,440},{142,11,305},{4,0,716 +},{141,0,31},{133,0,982},{8,0,691},{8,0,731},{5,10,67},{6,10,62},{6,10,374},{135 +,10,1391},{9,10,790},{140,10,47},{139,11,556},{151,11,1},{7,11,204},{7,11,415},{ +8,11,42},{10,11,85},{11,11,33},{11,11,564},{12,11,571},{149,11,1},{8,0,888},{7, +11,610},{135,11,1501},{4,10,391},{135,10,1169},{5,0,847},{9,0,840},{138,0,803},{ +137,0,823},{134,0,785},{8,0,152},{9,0,53},{9,0,268},{9,0,901},{10,0,518},{10,0, +829},{11,0,188},{13,0,74},{14,0,46},{15,0,17},{15,0,33},{17,0,40},{18,0,36},{19, +0,20},{22,0,1},{152,0,2},{4,11,3},{5,11,247},{5,11,644},{7,11,744},{7,11,1207},{ +7,11,1225},{7,11,1909},{146,11,147},{136,0,532},{135,0,681},{132,10,271},{140,0, +314},{140,0,677},{4,0,684},{136,0,384},{5,11,285},{9,11,67},{13,11,473},{143,11, +82},{4,10,253},{5,10,544},{7,10,300},{137,10,340},{7,0,110},{7,0,447},{8,0,290}, +{8,0,591},{9,0,382},{9,0,649},{11,0,71},{11,0,155},{11,0,313},{12,0,5},{13,0,325 +},{142,0,287},{134,0,1818},{136,0,1007},{138,0,321},{7,0,360},{7,0,425},{9,0,66} +,{9,0,278},{138,0,644},{133,10,818},{5,0,385},{5,10,541},{6,10,94},{6,10,499},{7 +,10,230},{139,10,321},{4,10,920},{5,10,25},{5,10,790},{6,10,457},{7,10,853},{136 +,10,788},{4,0,900},{133,0,861},{5,0,254},{7,0,985},{136,0,73},{7,0,1959},{136,0, +683},{134,10,1765},{133,10,822},{132,10,634},{4,11,29},{6,11,532},{7,11,1628},{7 +,11,1648},{9,11,303},{9,11,350},{10,11,433},{11,11,97},{11,11,557},{11,11,745},{ +12,11,289},{12,11,335},{12,11,348},{12,11,606},{13,11,116},{13,11,233},{13,11, +466},{14,11,181},{14,11,209},{14,11,232},{14,11,236},{14,11,300},{16,11,41},{148 +,11,97},{19,0,86},{6,10,36},{7,10,658},{136,10,454},{135,11,1692},{132,0,725},{5 +,11,501},{7,11,1704},{9,11,553},{11,11,520},{12,11,557},{141,11,249},{134,0,196} +,{133,0,831},{136,0,723},{7,0,1897},{13,0,80},{13,0,437},{145,0,74},{4,0,992},{6 +,0,627},{136,0,994},{135,11,1294},{132,10,104},{5,0,848},{6,0,66},{136,0,764},{4 +,0,36},{7,0,1387},{10,0,205},{139,0,755},{6,0,1046},{134,0,1485},{134,0,950},{ +132,0,887},{14,0,450},{148,0,111},{7,0,620},{7,0,831},{9,10,542},{9,10,566},{138 +,10,728},{6,0,165},{138,0,388},{139,10,263},{4,0,719},{135,0,155},{138,10,468},{ +6,11,453},{144,11,36},{134,11,129},{5,0,533},{7,0,755},{138,0,780},{134,0,1465}, +{4,0,353},{6,0,146},{6,0,1789},{7,0,427},{7,0,990},{7,0,1348},{9,0,665},{9,0,898 +},{11,0,893},{142,0,212},{7,10,87},{142,10,288},{4,0,45},{135,0,1257},{12,0,7},{ +7,10,988},{7,10,1939},{9,10,64},{9,10,502},{12,10,34},{13,10,12},{13,10,234},{ +147,10,77},{4,0,607},{5,11,60},{6,11,504},{7,11,614},{7,11,1155},{140,11,0},{135 +,10,141},{8,11,198},{11,11,29},{140,11,534},{140,0,65},{136,0,816},{132,10,619}, +{139,0,88},{5,10,246},{8,10,189},{9,10,355},{9,10,512},{10,10,124},{10,10,453},{ +11,10,143},{11,10,416},{11,10,859},{141,10,341},{4,11,379},{135,11,1397},{4,0, +600},{137,0,621},{133,0,367},{134,0,561},{6,0,559},{134,0,1691},{6,0,585},{134, +11,585},{135,11,1228},{4,11,118},{5,10,678},{6,11,274},{6,11,361},{7,11,75},{141 +,11,441},{135,11,1818},{137,11,841},{5,0,573},{6,0,287},{7,10,862},{7,10,1886},{ +138,10,179},{132,10,517},{140,11,693},{5,11,314},{6,11,221},{7,11,419},{10,11, +650},{11,11,396},{12,11,156},{13,11,369},{14,11,333},{145,11,47},{140,10,540},{ +136,10,667},{11,10,403},{146,10,83},{6,0,672},{133,10,761},{9,0,157},{10,10,131} +,{140,10,72},{7,0,714},{134,11,460},{134,0,456},{133,0,925},{5,11,682},{135,11, +1887},{136,11,510},{136,11,475},{133,11,1016},{9,0,19},{7,11,602},{8,11,179},{10 +,11,781},{140,11,126},{6,11,329},{138,11,111},{6,0,822},{134,0,1473},{144,11,86} +,{11,0,113},{139,11,113},{5,11,821},{134,11,1687},{133,10,449},{7,0,463},{17,0, +69},{136,10,103},{7,10,2028},{138,10,641},{6,0,193},{7,0,240},{7,0,1682},{10,0, +51},{10,0,640},{11,0,410},{13,0,82},{14,0,247},{14,0,331},{142,0,377},{6,0,471}, +{11,0,411},{142,0,2},{5,11,71},{7,11,1407},{9,11,388},{9,11,704},{10,11,261},{10 +,11,619},{11,11,547},{11,11,619},{143,11,157},{136,0,633},{135,0,1148},{6,0,554} +,{7,0,1392},{12,0,129},{7,10,1274},{7,10,1386},{7,11,2008},{9,11,337},{10,11,517 +},{146,10,87},{7,0,803},{8,0,542},{6,10,187},{7,10,1203},{8,10,380},{14,10,117}, +{149,10,28},{6,10,297},{7,10,793},{139,10,938},{8,0,438},{11,0,363},{7,10,464},{ +11,10,105},{12,10,231},{14,10,386},{15,10,102},{148,10,75},{5,11,16},{6,11,86},{ +6,11,603},{7,11,292},{7,11,561},{8,11,257},{8,11,382},{9,11,721},{9,11,778},{11, +11,581},{140,11,466},{6,0,717},{4,11,486},{133,11,491},{132,0,875},{132,11,72},{ +6,11,265},{135,11,847},{4,0,237},{135,0,514},{6,0,392},{7,0,65},{135,0,2019},{ +140,11,261},{135,11,922},{137,11,404},{12,0,563},{14,0,101},{18,0,129},{7,10, +1010},{11,10,733},{11,10,759},{13,10,34},{146,10,45},{7,10,1656},{9,10,369},{10, +10,338},{10,10,490},{11,10,154},{11,10,545},{11,10,775},{13,10,77},{141,10,274}, +{4,0,444},{10,0,146},{140,0,9},{139,11,163},{7,0,1260},{135,0,1790},{9,0,222},{ +10,0,43},{139,0,900},{137,11,234},{138,0,971},{137,0,761},{134,0,699},{136,11, +434},{6,0,1116},{7,0,1366},{5,10,20},{6,11,197},{6,10,298},{7,10,659},{8,11,205} +,{137,10,219},{132,11,490},{11,11,820},{150,11,51},{7,10,1440},{11,10,854},{11, +10,872},{11,10,921},{12,10,551},{13,10,472},{142,10,367},{140,11,13},{132,0,829} +,{12,0,242},{132,10,439},{136,10,669},{6,0,593},{6,11,452},{7,11,312},{138,11, +219},{4,11,333},{9,11,176},{12,11,353},{141,11,187},{7,0,36},{8,0,201},{136,0, +605},{140,0,224},{132,10,233},{134,0,1430},{134,0,1806},{4,0,523},{133,0,638},{6 +,0,1889},{9,0,958},{9,0,971},{9,0,976},{12,0,796},{12,0,799},{12,0,808},{12,0, +835},{12,0,836},{12,0,914},{12,0,946},{15,0,216},{15,0,232},{18,0,183},{18,0,187 +},{18,0,194},{18,0,212},{18,0,232},{149,0,49},{132,10,482},{6,0,827},{134,0,1434 +},{135,10,346},{134,0,2043},{6,0,242},{7,0,227},{7,0,1581},{8,0,104},{9,0,113},{ +9,0,220},{9,0,427},{10,0,136},{10,0,239},{11,0,579},{11,0,1023},{13,0,4},{13,0, +204},{13,0,316},{148,0,86},{134,11,1685},{7,0,148},{8,0,284},{141,0,63},{142,0, +10},{135,11,584},{134,0,1249},{7,0,861},{135,10,334},{5,10,795},{6,10,1741},{137 +,11,70},{132,0,807},{7,11,135},{8,11,7},{8,11,62},{9,11,243},{10,11,658},{10,11, +697},{11,11,456},{139,11,756},{9,11,395},{138,11,79},{137,11,108},{147,0,94},{ +136,0,494},{135,11,631},{135,10,622},{7,0,1510},{135,10,1750},{4,10,203},{135,10 +,1936},{7,11,406},{7,11,459},{8,11,606},{139,11,726},{7,0,1306},{8,0,505},{9,0, +482},{10,0,126},{11,0,225},{12,0,347},{12,0,449},{13,0,19},{14,0,218},{142,0,435 +},{5,0,268},{10,0,764},{12,0,120},{13,0,39},{145,0,127},{142,11,68},{11,10,678}, +{140,10,307},{12,11,268},{12,11,640},{142,11,119},{135,10,2044},{133,11,612},{4, +11,372},{7,11,482},{8,11,158},{9,11,602},{9,11,615},{10,11,245},{10,11,678},{10, +11,744},{11,11,248},{139,11,806},{7,10,311},{9,10,308},{140,10,255},{4,0,384},{ +135,0,1022},{5,11,854},{135,11,1991},{135,10,1266},{4,10,400},{5,10,267},{135,10 +,232},{135,0,1703},{9,0,159},{11,0,661},{140,0,603},{4,0,964},{14,0,438},{14,0, +444},{14,0,456},{22,0,60},{22,0,63},{9,11,106},{9,11,163},{9,11,296},{10,11,167} +,{10,11,172},{10,11,777},{139,11,16},{136,0,583},{132,0,515},{8,0,632},{8,0,697} +,{137,0,854},{5,11,195},{135,11,1685},{6,0,1123},{134,0,1365},{134,11,328},{7,11 +,1997},{8,11,730},{139,11,1006},{4,0,136},{133,0,551},{134,0,1782},{7,0,1287},{9 +,0,44},{10,0,552},{10,0,642},{11,0,839},{12,0,274},{12,0,275},{12,0,372},{13,0, +91},{142,0,125},{5,11,751},{11,11,797},{140,11,203},{133,0,732},{7,0,679},{8,0, +313},{4,10,100},{135,11,821},{10,0,361},{142,0,316},{134,0,595},{6,0,147},{7,0, +886},{9,0,753},{138,0,268},{5,10,362},{5,10,443},{6,10,318},{7,10,1019},{139,10, +623},{5,10,463},{136,10,296},{4,10,454},{5,11,950},{5,11,994},{134,11,351},{138, +0,137},{5,10,48},{5,10,404},{6,10,557},{7,10,458},{8,10,597},{10,10,455},{10,10, +606},{11,10,49},{11,10,548},{12,10,476},{13,10,18},{141,10,450},{133,0,414},{135 +,0,1762},{5,11,421},{135,11,47},{5,10,442},{135,10,1984},{134,0,599},{134,0,1749 +},{134,0,1627},{4,0,488},{132,11,350},{137,11,751},{132,0,83},{140,0,676},{133, +11,967},{7,0,1639},{5,10,55},{140,10,161},{4,11,473},{7,11,623},{8,11,808},{9,11 +,871},{9,11,893},{11,11,38},{11,11,431},{12,11,112},{12,11,217},{12,11,243},{12, +11,562},{12,11,683},{13,11,141},{13,11,197},{13,11,227},{13,11,406},{13,11,487}, +{14,11,156},{14,11,203},{14,11,224},{14,11,256},{18,11,58},{150,11,0},{133,10, +450},{7,11,736},{139,11,264},{134,0,278},{4,11,222},{7,11,286},{136,11,629},{135 +,10,869},{140,0,97},{144,0,14},{134,0,1085},{4,10,213},{7,10,223},{136,10,80},{7 +,0,388},{7,0,644},{139,0,781},{132,0,849},{7,0,229},{8,0,59},{9,0,190},{10,0,378 +},{140,0,191},{7,10,381},{7,10,806},{7,10,820},{8,10,354},{8,10,437},{8,10,787}, +{9,10,657},{10,10,58},{10,10,339},{10,10,749},{11,10,914},{12,10,162},{13,10,75} +,{14,10,106},{14,10,198},{14,10,320},{14,10,413},{146,10,43},{141,11,306},{136, +10,747},{134,0,1115},{16,0,94},{16,0,108},{136,11,146},{6,0,700},{6,0,817},{134, +0,1002},{133,10,692},{4,11,465},{135,11,1663},{134,10,191},{6,0,1414},{135,11, +913},{132,0,660},{7,0,1035},{138,0,737},{6,10,162},{7,10,1960},{136,10,831},{132 +,10,706},{7,0,690},{9,0,217},{9,0,587},{140,0,521},{138,10,426},{135,10,1235},{6 +,11,82},{7,11,138},{7,11,517},{9,11,673},{139,11,238},{138,0,272},{5,11,495},{7, +11,834},{9,11,733},{139,11,378},{134,0,1744},{132,0,1011},{7,11,828},{142,11,116 +},{4,0,733},{9,0,194},{10,0,92},{11,0,198},{12,0,84},{13,0,128},{133,11,559},{10 +,0,57},{10,0,277},{6,11,21},{6,11,1737},{7,11,1444},{136,11,224},{4,10,204},{137 +,10,902},{136,10,833},{11,0,348},{12,0,99},{18,0,1},{18,0,11},{19,0,4},{7,10,366 +},{9,10,287},{12,10,199},{12,10,556},{140,10,577},{6,0,1981},{136,0,936},{21,0, +33},{150,0,40},{5,11,519},{138,11,204},{5,10,356},{135,10,224},{134,0,775},{135, +0,306},{7,10,630},{9,10,567},{11,10,150},{11,10,444},{141,10,119},{5,0,979},{134 +,10,539},{133,0,611},{4,11,402},{135,11,1679},{5,0,178},{7,11,2},{8,11,323},{136 +,11,479},{5,11,59},{135,11,672},{4,0,1010},{6,0,1969},{138,11,237},{133,11,412}, +{146,11,34},{7,11,1740},{146,11,48},{134,0,664},{139,10,814},{4,11,85},{135,11, +549},{133,11,94},{133,11,457},{132,0,390},{134,0,1510},{4,10,235},{135,10,255},{ +4,10,194},{5,10,584},{6,11,11},{6,10,384},{7,11,187},{7,10,583},{10,10,761},{11, +10,760},{139,10,851},{4,11,522},{139,11,802},{135,0,493},{10,11,776},{13,11,345} +,{142,11,425},{146,0,37},{4,11,52},{135,11,661},{134,0,724},{134,0,829},{133,11, +520},{133,10,562},{4,11,281},{5,11,38},{7,11,194},{7,11,668},{7,11,1893},{137,11 +,397},{5,10,191},{137,10,271},{7,0,1537},{14,0,96},{143,0,73},{5,0,473},{11,0, +168},{4,10,470},{6,10,153},{7,10,1503},{7,10,1923},{10,10,701},{11,10,132},{11, +10,227},{11,10,320},{11,10,436},{11,10,525},{11,10,855},{12,10,41},{12,10,286},{ +13,10,103},{13,10,284},{14,10,255},{14,10,262},{15,10,117},{143,10,127},{133,0, +105},{5,0,438},{9,0,694},{12,0,627},{141,0,210},{133,10,327},{6,10,552},{7,10, +1754},{137,10,604},{134,0,1256},{152,0,11},{5,11,448},{11,11,98},{139,11,524},{7 +,0,1626},{5,10,80},{6,10,405},{7,10,403},{7,10,1502},{8,10,456},{9,10,487},{9,10 +,853},{9,10,889},{10,10,309},{11,10,721},{11,10,994},{12,10,430},{13,10,165},{14 +,11,16},{146,11,44},{132,0,779},{8,0,25},{138,0,826},{4,10,453},{5,10,887},{6,10 +,535},{8,10,6},{8,10,543},{136,10,826},{137,11,461},{140,11,632},{132,0,308},{ +135,0,741},{132,0,671},{7,0,150},{8,0,649},{136,0,1020},{9,0,99},{6,11,336},{8, +11,552},{9,11,285},{10,11,99},{139,11,568},{134,0,521},{5,0,339},{14,0,3},{15,0, +41},{15,0,166},{147,0,66},{6,11,423},{7,11,665},{7,11,1210},{9,11,218},{141,11, +222},{6,0,543},{5,10,101},{5,11,256},{6,10,88},{7,10,1677},{9,10,100},{10,10,677 +},{14,10,169},{14,10,302},{14,10,313},{15,10,48},{143,10,84},{4,10,310},{7,10, +708},{7,10,996},{9,10,795},{10,10,390},{10,10,733},{11,10,451},{12,10,249},{14, +10,115},{14,10,286},{143,10,100},{133,10,587},{13,11,417},{14,11,129},{143,11,15 +},{134,0,1358},{136,11,554},{132,10,498},{7,10,217},{8,10,140},{138,10,610},{135 +,11,989},{135,11,634},{6,0,155},{140,0,234},{135,11,462},{132,11,618},{134,0, +1628},{132,0,766},{4,11,339},{5,10,905},{135,11,259},{135,0,829},{4,11,759},{141 +,11,169},{7,0,1445},{4,10,456},{7,10,358},{7,10,1637},{8,10,643},{139,10,483},{5 +,0,486},{135,0,1349},{5,11,688},{135,11,712},{7,0,1635},{8,0,17},{10,0,217},{10, +0,295},{12,0,2},{140,11,2},{138,0,558},{150,10,56},{4,11,278},{5,11,465},{135,11 +,1367},{136,11,482},{133,10,535},{6,0,1362},{6,0,1461},{10,11,274},{10,11,625},{ +139,11,530},{5,0,599},{5,11,336},{6,11,341},{6,11,478},{6,11,1763},{136,11,386}, +{7,10,1748},{137,11,151},{134,0,1376},{133,10,539},{135,11,73},{135,11,1971},{ +139,11,283},{9,0,93},{139,0,474},{6,10,91},{135,10,435},{6,0,447},{5,11,396},{ +134,11,501},{4,10,16},{5,10,316},{5,10,842},{6,10,370},{6,10,1778},{8,10,166},{ +11,10,812},{12,10,206},{12,10,351},{14,10,418},{16,10,15},{16,10,34},{18,10,3},{ +19,10,3},{19,10,7},{20,10,4},{149,10,21},{7,0,577},{7,0,1432},{9,0,475},{9,0,505 +},{9,0,526},{9,0,609},{9,0,689},{9,0,726},{9,0,735},{9,0,738},{10,0,556},{10,0, +674},{10,0,684},{11,0,89},{11,0,202},{11,0,272},{11,0,380},{11,0,415},{11,0,505} +,{11,0,537},{11,0,550},{11,0,562},{11,0,640},{11,0,667},{11,0,688},{11,0,847},{ +11,0,927},{11,0,930},{11,0,940},{12,0,144},{12,0,325},{12,0,329},{12,0,389},{12, +0,403},{12,0,451},{12,0,515},{12,0,604},{12,0,616},{12,0,626},{13,0,66},{13,0, +131},{13,0,167},{13,0,236},{13,0,368},{13,0,411},{13,0,434},{13,0,453},{13,0,461 +},{13,0,474},{14,0,59},{14,0,60},{14,0,139},{14,0,152},{14,0,276},{14,0,353},{14 +,0,402},{15,0,28},{15,0,81},{15,0,123},{15,0,152},{18,0,136},{148,0,88},{4,11, +929},{133,11,799},{136,11,46},{142,0,307},{4,0,609},{7,0,756},{9,0,544},{11,0, +413},{144,0,25},{10,0,687},{7,10,619},{10,10,547},{11,10,122},{140,10,601},{4,0, +930},{133,0,947},{133,0,939},{142,0,21},{4,11,892},{133,11,770},{133,0,962},{5,0 +,651},{8,0,170},{9,0,61},{9,0,63},{10,0,23},{10,0,37},{10,0,834},{11,0,4},{11,0, +187},{11,0,281},{11,0,503},{11,0,677},{12,0,96},{12,0,130},{12,0,244},{14,0,5},{ +14,0,40},{14,0,162},{14,0,202},{146,0,133},{4,0,406},{5,0,579},{12,0,492},{150,0 +,15},{135,11,158},{135,0,597},{132,0,981},{132,10,888},{4,10,149},{138,10,368},{ +132,0,545},{4,10,154},{7,10,1134},{136,10,105},{135,11,2001},{134,0,1558},{4,10, +31},{6,10,429},{7,10,962},{9,10,458},{139,10,691},{132,10,312},{135,10,1642},{6, +0,17},{6,0,1304},{7,0,16},{7,0,1001},{9,0,886},{10,0,489},{10,0,800},{11,0,782}, +{12,0,320},{13,0,467},{14,0,145},{14,0,387},{143,0,119},{135,0,1982},{17,0,17},{ +7,11,1461},{140,11,91},{4,10,236},{132,11,602},{138,0,907},{136,0,110},{7,0,272} +,{19,0,53},{5,10,836},{5,10,857},{134,10,1680},{5,0,458},{7,11,1218},{136,11,303 +},{7,0,1983},{8,0,0},{8,0,171},{9,0,120},{9,0,732},{10,0,473},{11,0,656},{11,0, +998},{18,0,0},{18,0,2},{19,0,21},{10,10,68},{139,10,494},{137,11,662},{4,11,13}, +{5,11,567},{7,11,1498},{9,11,124},{11,11,521},{140,11,405},{4,10,81},{139,10,867 +},{135,11,1006},{7,11,800},{7,11,1783},{138,11,12},{9,0,295},{10,0,443},{5,10, +282},{8,10,650},{137,10,907},{132,11,735},{4,11,170},{4,10,775},{135,11,323},{6, +0,1844},{10,0,924},{11,11,844},{12,11,104},{140,11,625},{5,11,304},{7,11,1403},{ +140,11,498},{134,0,1232},{4,0,519},{10,0,70},{12,0,26},{14,0,17},{14,0,178},{15, +0,34},{149,0,12},{132,0,993},{4,11,148},{133,11,742},{6,0,31},{7,0,491},{7,0,530 +},{8,0,592},{11,0,53},{11,0,779},{12,0,167},{12,0,411},{14,0,14},{14,0,136},{15, +0,72},{16,0,17},{144,0,72},{133,0,907},{134,0,733},{133,11,111},{4,10,71},{5,10, +376},{7,10,119},{138,10,665},{136,0,55},{8,0,430},{136,11,430},{4,0,208},{5,0, +106},{6,0,531},{8,0,408},{9,0,188},{138,0,572},{12,0,56},{11,10,827},{14,10,34}, +{143,10,148},{134,0,1693},{133,11,444},{132,10,479},{140,0,441},{9,0,449},{10,0, +192},{138,0,740},{134,0,928},{4,0,241},{7,10,607},{136,10,99},{8,11,123},{15,11, +6},{144,11,7},{6,11,285},{8,11,654},{11,11,749},{12,11,190},{12,11,327},{13,11, +120},{13,11,121},{13,11,327},{15,11,47},{146,11,40},{4,10,41},{5,10,74},{7,10, +1627},{11,10,871},{140,10,619},{7,0,1525},{11,10,329},{11,10,965},{12,10,241},{ +14,10,354},{15,10,22},{148,10,63},{132,0,259},{135,11,183},{9,10,209},{137,10, +300},{5,11,937},{135,11,100},{133,10,98},{4,0,173},{5,0,312},{5,0,512},{135,0, +1285},{141,0,185},{7,0,1603},{7,0,1691},{9,0,464},{11,0,195},{12,0,279},{12,0, +448},{14,0,11},{147,0,102},{135,0,1113},{133,10,984},{4,0,452},{5,0,583},{135,0, +720},{4,0,547},{5,0,817},{6,0,433},{7,0,593},{7,0,1378},{8,0,161},{9,0,284},{10, +0,313},{139,0,886},{8,0,722},{4,10,182},{6,10,205},{135,10,220},{150,0,13},{4,10 +,42},{9,10,205},{9,10,786},{138,10,659},{6,0,289},{7,0,1670},{12,0,57},{151,0,4} +,{132,10,635},{14,0,43},{146,0,21},{139,10,533},{135,0,1694},{8,0,420},{139,0, +193},{135,0,409},{132,10,371},{4,10,272},{135,10,836},{5,10,825},{134,10,1640},{ +5,11,251},{5,11,956},{8,11,268},{9,11,214},{146,11,142},{138,0,308},{6,0,1863},{ +141,11,37},{137,10,879},{7,10,317},{135,10,569},{132,11,294},{134,0,790},{5,0, +1002},{136,0,745},{5,11,346},{5,11,711},{136,11,390},{135,0,289},{5,0,504},{11,0 +,68},{137,10,307},{4,0,239},{6,0,477},{7,0,1607},{139,0,617},{149,0,13},{133,0, +609},{133,11,624},{5,11,783},{7,11,1998},{135,11,2047},{133,10,525},{132,0,367}, +{132,11,594},{6,0,528},{133,10,493},{4,10,174},{135,10,911},{8,10,417},{137,10, +782},{132,0,694},{7,0,548},{137,0,58},{4,10,32},{5,10,215},{6,10,269},{7,10,1782 +},{7,10,1892},{10,10,16},{11,10,822},{11,10,954},{141,10,481},{140,0,687},{7,0, +1749},{136,10,477},{132,11,569},{133,10,308},{135,10,1088},{4,0,661},{138,0,1004 +},{5,11,37},{6,11,39},{6,11,451},{7,11,218},{7,11,667},{7,11,1166},{7,11,1687},{ +8,11,662},{144,11,2},{9,0,445},{12,0,53},{13,0,492},{5,10,126},{8,10,297},{9,10, +366},{140,10,374},{7,10,1551},{139,10,361},{148,0,74},{134,11,508},{135,0,213},{ +132,10,175},{132,10,685},{6,0,760},{6,0,834},{134,0,1248},{7,11,453},{7,11,635}, +{7,11,796},{8,11,331},{9,11,328},{9,11,330},{9,11,865},{10,11,119},{10,11,235},{ +11,11,111},{11,11,129},{11,11,240},{12,11,31},{12,11,66},{12,11,222},{12,11,269} +,{12,11,599},{12,11,689},{13,11,186},{13,11,364},{142,11,345},{7,0,1672},{139,0, +189},{133,10,797},{133,10,565},{6,0,1548},{6,11,98},{7,11,585},{135,11,702},{9,0 +,968},{15,0,192},{149,0,56},{4,10,252},{6,11,37},{7,11,299},{7,10,1068},{7,11, +1666},{8,11,195},{8,11,316},{9,11,178},{9,11,276},{9,11,339},{9,11,536},{10,11, +102},{10,11,362},{10,10,434},{10,11,785},{11,11,55},{11,11,149},{11,10,228},{11, +10,426},{11,11,773},{13,10,231},{13,11,416},{13,11,419},{14,11,38},{14,11,41},{ +14,11,210},{18,10,106},{148,10,87},{4,0,751},{11,0,390},{140,0,32},{4,0,409},{ +133,0,78},{11,11,458},{12,11,15},{140,11,432},{7,0,1602},{10,0,257},{10,0,698},{ +11,0,544},{11,0,585},{12,0,212},{13,0,307},{5,10,231},{7,10,601},{9,10,277},{9, +10,674},{10,10,178},{10,10,418},{10,10,509},{11,10,531},{12,10,113},{12,10,475}, +{13,10,99},{142,10,428},{6,0,473},{145,0,105},{6,0,1949},{15,0,156},{133,11,645} +,{7,10,1591},{144,10,43},{135,0,1779},{135,10,1683},{4,11,290},{135,11,1356},{ +134,0,763},{6,11,70},{7,11,1292},{10,11,762},{139,11,288},{142,0,29},{140,11,428 +},{7,0,883},{7,11,131},{7,11,422},{8,11,210},{140,11,573},{134,0,488},{4,10,399} +,{5,10,119},{5,10,494},{7,10,751},{137,10,556},{133,0,617},{132,11,936},{139,0, +50},{7,0,1518},{139,0,694},{137,0,785},{4,0,546},{135,0,2042},{7,11,716},{13,11, +97},{141,11,251},{132,11,653},{145,0,22},{134,0,1016},{4,0,313},{133,0,577},{136 +,11,657},{8,0,184},{141,0,433},{135,0,935},{6,0,720},{9,0,114},{146,11,80},{12,0 +,186},{12,0,292},{14,0,100},{18,0,70},{7,10,594},{7,10,851},{7,10,1858},{9,10, +411},{9,10,574},{9,10,666},{9,10,737},{10,10,346},{10,10,712},{11,10,246},{11,10 +,432},{11,10,517},{11,10,647},{11,10,679},{11,10,727},{12,10,304},{12,10,305},{ +12,10,323},{12,10,483},{12,10,572},{12,10,593},{12,10,602},{13,10,95},{13,10,101 +},{13,10,171},{13,10,315},{13,10,378},{13,10,425},{13,10,475},{14,10,63},{14,10, +380},{14,10,384},{15,10,133},{18,10,112},{148,10,72},{135,10,1093},{135,11,1836} +,{132,10,679},{137,10,203},{11,0,402},{12,0,109},{12,0,431},{13,0,179},{13,0,206 +},{14,0,217},{16,0,3},{148,0,53},{7,11,1368},{8,11,232},{8,11,361},{10,11,682},{ +138,11,742},{137,10,714},{5,0,886},{6,0,46},{6,0,1790},{7,0,14},{7,0,732},{7,0, +1654},{8,0,95},{8,0,327},{8,0,616},{9,0,892},{10,0,598},{10,0,769},{11,0,134},{ +11,0,747},{12,0,378},{14,0,97},{137,11,534},{4,0,969},{136,10,825},{137,11,27},{ +6,0,727},{142,11,12},{133,0,1021},{134,0,1190},{134,11,1657},{5,10,143},{5,10, +769},{6,10,1760},{7,10,682},{7,10,1992},{136,10,736},{132,0,153},{135,11,127},{ +133,0,798},{132,0,587},{6,0,598},{7,0,42},{8,0,695},{10,0,212},{11,0,158},{14,0, +196},{145,0,85},{133,10,860},{6,0,1929},{134,0,1933},{5,0,957},{5,0,1008},{9,0, +577},{12,0,141},{6,10,422},{7,10,0},{7,10,1544},{8,11,364},{11,10,990},{12,10, +453},{13,10,47},{141,10,266},{134,0,1319},{4,0,129},{135,0,465},{7,0,470},{7,0, +1057},{7,0,1201},{9,0,755},{11,0,906},{140,0,527},{7,0,908},{146,0,7},{5,0,148}, +{136,0,450},{5,10,515},{137,10,131},{7,10,1605},{11,10,962},{146,10,139},{132,10 +,646},{134,0,1166},{4,10,396},{7,10,728},{9,10,117},{13,10,202},{148,10,51},{6, +10,121},{6,10,124},{6,10,357},{7,10,1138},{7,10,1295},{8,10,162},{139,10,655},{ +14,0,374},{142,11,374},{138,0,253},{139,0,1003},{5,11,909},{9,11,849},{138,11, +805},{133,10,237},{7,11,525},{7,11,1579},{8,11,497},{136,11,573},{137,0,46},{132 +,0,879},{134,0,806},{135,0,1868},{6,0,1837},{134,0,1846},{6,0,730},{134,0,881},{ +7,0,965},{7,0,1460},{7,0,1604},{7,11,193},{7,11,397},{7,11,1105},{8,11,124},{8, +11,619},{9,11,305},{10,11,264},{11,11,40},{12,11,349},{13,11,134},{13,11,295},{ +14,11,155},{15,11,120},{146,11,105},{136,0,506},{143,0,10},{4,11,262},{7,11,342} +,{7,10,571},{7,10,1877},{10,10,366},{141,11,23},{133,11,641},{10,0,22},{9,10,513 +},{10,10,39},{12,10,122},{140,10,187},{135,11,1431},{150,11,49},{4,11,99},{6,11, +250},{6,11,346},{8,11,127},{138,11,81},{6,0,2014},{8,0,928},{10,0,960},{10,0,979 +},{140,0,996},{134,0,296},{132,11,915},{5,11,75},{9,11,517},{10,11,470},{12,11, +155},{141,11,224},{137,10,873},{4,0,854},{140,11,18},{134,0,587},{7,10,107},{7, +10,838},{8,10,550},{138,10,401},{11,0,636},{15,0,145},{17,0,34},{19,0,50},{23,0, +20},{11,10,588},{11,10,864},{11,10,968},{143,10,160},{135,11,216},{7,0,982},{10, +0,32},{143,0,56},{133,10,768},{133,11,954},{6,11,304},{7,11,1114},{8,11,418},{10 +,11,345},{11,11,341},{11,11,675},{141,11,40},{9,11,410},{139,11,425},{136,0,941} +,{5,0,435},{132,10,894},{5,0,85},{6,0,419},{7,0,134},{7,0,305},{7,0,361},{7,0, +1337},{8,0,71},{140,0,519},{140,0,688},{135,0,740},{5,0,691},{7,0,345},{9,0,94}, +{140,0,169},{5,0,183},{6,0,582},{10,0,679},{140,0,435},{134,11,14},{6,0,945},{ +135,0,511},{134,11,1708},{5,11,113},{6,11,243},{7,11,1865},{11,11,161},{16,11,37 +},{145,11,99},{132,11,274},{137,0,539},{7,0,1993},{8,0,684},{134,10,272},{6,0, +659},{134,0,982},{4,10,9},{5,10,128},{7,10,368},{11,10,480},{148,10,3},{134,0, +583},{132,0,803},{133,0,704},{4,0,179},{5,0,198},{133,0,697},{7,0,347},{7,0,971} +,{8,0,181},{10,0,711},{135,11,166},{136,10,682},{4,10,2},{7,10,545},{7,10,894},{ +136,11,521},{135,0,481},{132,0,243},{5,0,203},{7,0,19},{7,0,71},{7,0,113},{10,0, +405},{11,0,357},{142,0,240},{5,11,725},{5,11,727},{135,11,1811},{6,0,826},{137, +11,304},{7,0,1450},{139,0,99},{133,11,654},{134,0,492},{5,0,134},{6,0,408},{6,0, +495},{7,0,1593},{6,11,273},{10,11,188},{13,11,377},{146,11,77},{9,10,769},{140, +10,185},{135,11,410},{142,0,4},{4,0,665},{134,11,1785},{4,0,248},{7,0,137},{137, +0,349},{5,10,530},{142,10,113},{7,0,1270},{139,0,612},{132,11,780},{5,0,371},{ +135,0,563},{135,0,826},{6,0,1535},{23,0,21},{151,0,23},{4,0,374},{7,0,547},{7,0, +1700},{7,0,1833},{139,0,858},{133,10,556},{7,11,612},{8,11,545},{8,11,568},{8,11 +,642},{9,11,717},{10,11,541},{10,11,763},{11,11,449},{12,11,489},{13,11,153},{13 +,11,296},{14,11,138},{14,11,392},{15,11,50},{16,11,6},{16,11,12},{148,11,9},{9,0 +,311},{141,0,42},{8,10,16},{140,10,568},{6,0,1968},{6,0,2027},{138,0,991},{6,0, +1647},{7,0,1552},{7,0,2010},{9,0,494},{137,0,509},{133,11,948},{6,10,186},{137, +10,426},{134,0,769},{134,0,642},{132,10,585},{6,0,123},{7,0,214},{9,0,728},{10,0 +,157},{11,0,346},{11,0,662},{143,0,106},{142,11,381},{135,0,1435},{4,11,532},{5, +11,706},{135,11,662},{5,11,837},{134,11,1651},{4,10,93},{5,10,252},{6,10,229},{7 +,10,291},{9,10,550},{139,10,644},{148,0,79},{137,10,749},{134,0,1425},{137,10, +162},{4,11,362},{7,11,52},{7,11,303},{140,11,166},{132,10,381},{4,11,330},{7,11, +933},{7,11,2012},{136,11,292},{135,11,767},{4,0,707},{5,0,588},{6,0,393},{13,0, +106},{18,0,49},{147,0,41},{6,0,211},{7,0,1690},{11,0,486},{140,0,369},{137,11, +883},{4,11,703},{135,11,207},{4,0,187},{5,0,184},{5,0,690},{7,0,1869},{10,0,756} +,{139,0,783},{132,11,571},{134,0,1382},{5,0,175},{6,10,77},{6,10,157},{7,10,974} +,{7,10,1301},{7,10,1339},{7,10,1490},{7,10,1873},{137,10,628},{134,0,1493},{5,11 +,873},{133,11,960},{134,0,1007},{12,11,93},{12,11,501},{13,11,362},{14,11,151},{ +15,11,40},{15,11,59},{16,11,46},{17,11,25},{18,11,14},{18,11,134},{19,11,25},{19 +,11,69},{20,11,16},{20,11,19},{20,11,66},{21,11,23},{21,11,25},{150,11,42},{11, +10,919},{141,10,409},{134,0,219},{5,0,582},{6,0,1646},{7,0,99},{7,0,1962},{7,0, +1986},{8,0,515},{8,0,773},{9,0,23},{9,0,491},{12,0,620},{142,0,93},{133,0,851},{ +5,11,33},{134,11,470},{135,11,1291},{134,0,1278},{135,11,1882},{135,10,1489},{ +132,0,1000},{138,0,982},{8,0,762},{8,0,812},{137,0,910},{6,11,47},{7,11,90},{7, +11,664},{7,11,830},{7,11,1380},{7,11,2025},{8,11,448},{136,11,828},{4,0,98},{4,0 +,940},{6,0,1819},{6,0,1834},{6,0,1841},{7,0,1365},{8,0,859},{8,0,897},{8,0,918}, +{9,0,422},{9,0,670},{10,0,775},{10,0,894},{10,0,909},{10,0,910},{10,0,935},{11,0 +,210},{12,0,750},{12,0,755},{13,0,26},{13,0,457},{13,0,476},{16,0,100},{16,0,109 +},{18,0,173},{18,0,175},{8,10,398},{9,10,681},{139,10,632},{9,11,417},{137,11, +493},{136,10,645},{138,0,906},{134,0,1730},{134,10,20},{133,11,1019},{134,0,1185 +},{10,0,40},{136,10,769},{9,0,147},{134,11,208},{140,0,650},{5,0,209},{6,0,30},{ +11,0,56},{139,0,305},{132,0,553},{138,11,344},{6,11,68},{7,11,398},{7,11,448},{7 +,11,1629},{7,11,1813},{8,11,387},{8,11,442},{9,11,710},{10,11,282},{138,11,722}, +{5,0,597},{14,0,20},{142,11,20},{135,0,1614},{135,10,1757},{4,0,150},{5,0,303},{ +6,0,327},{135,10,937},{16,0,49},{7,10,1652},{144,11,49},{8,0,192},{10,0,78},{141 +,0,359},{135,0,786},{143,0,134},{6,0,1638},{7,0,79},{7,0,496},{9,0,138},{10,0, +336},{11,0,12},{12,0,412},{12,0,440},{142,0,305},{136,11,491},{4,10,579},{5,10, +226},{5,10,323},{135,10,960},{7,0,204},{7,0,415},{8,0,42},{10,0,85},{139,0,564}, +{132,0,614},{4,11,403},{5,11,441},{7,11,450},{11,11,101},{12,11,193},{141,11,430 +},{135,11,1927},{135,11,1330},{4,0,3},{5,0,247},{5,0,644},{7,0,744},{7,0,1207},{ +7,0,1225},{7,0,1909},{146,0,147},{136,0,942},{4,0,1019},{134,0,2023},{5,11,679}, +{133,10,973},{5,0,285},{9,0,67},{13,0,473},{143,0,82},{7,11,328},{137,11,326},{ +151,0,8},{6,10,135},{135,10,1176},{135,11,1128},{134,0,1309},{135,11,1796},{135, +10,314},{4,11,574},{7,11,350},{7,11,1024},{8,11,338},{9,11,677},{10,11,808},{139 +,11,508},{7,11,818},{17,11,14},{17,11,45},{18,11,75},{148,11,18},{146,10,4},{135 +,11,1081},{4,0,29},{6,0,532},{7,0,1628},{7,0,1648},{9,0,350},{10,0,433},{11,0,97 +},{11,0,557},{11,0,745},{12,0,289},{12,0,335},{12,0,348},{12,0,606},{13,0,116},{ +13,0,233},{13,0,466},{14,0,181},{14,0,209},{14,0,232},{14,0,236},{14,0,300},{16, +0,41},{148,0,97},{7,0,318},{6,10,281},{8,10,282},{8,10,480},{8,10,499},{9,10,198 +},{10,10,143},{10,10,169},{10,10,211},{10,10,417},{10,10,574},{11,10,147},{11,10 +,395},{12,10,75},{12,10,407},{12,10,608},{13,10,500},{142,10,251},{135,11,1676}, +{135,11,2037},{135,0,1692},{5,0,501},{7,0,1704},{9,0,553},{11,0,520},{12,0,557}, +{141,0,249},{6,0,1527},{14,0,324},{15,0,55},{15,0,80},{14,11,324},{15,11,55},{ +143,11,80},{135,10,1776},{8,0,988},{137,11,297},{132,10,419},{142,0,223},{139,11 +,234},{7,0,1123},{12,0,508},{14,0,102},{14,0,226},{144,0,57},{4,10,138},{7,10, +1012},{7,10,1280},{137,10,76},{7,0,1764},{5,10,29},{140,10,638},{134,0,2015},{ +134,0,1599},{138,11,56},{6,11,306},{7,11,1140},{7,11,1340},{8,11,133},{138,11, +449},{139,11,1011},{6,10,1710},{135,10,2038},{7,11,1763},{140,11,310},{6,0,129}, +{4,10,17},{5,10,23},{7,10,995},{11,10,383},{11,10,437},{12,10,460},{140,10,532}, +{5,11,329},{136,11,260},{133,10,862},{132,0,534},{6,0,811},{135,0,626},{132,11, +657},{4,0,25},{5,0,60},{6,0,504},{7,0,614},{7,0,1155},{12,0,0},{152,11,7},{7,0, +1248},{11,0,621},{139,0,702},{137,0,321},{8,10,70},{12,10,171},{141,10,272},{10, +10,233},{139,10,76},{4,0,379},{7,0,1397},{134,10,442},{5,11,66},{7,11,1896},{136 +,11,288},{134,11,1643},{134,10,1709},{4,11,21},{5,11,91},{5,11,570},{5,11,648},{ +5,11,750},{5,11,781},{6,11,54},{6,11,112},{6,11,402},{6,11,1732},{7,11,315},{7, +11,749},{7,11,1347},{7,11,1900},{9,11,78},{9,11,508},{10,11,611},{11,11,510},{11 +,11,728},{13,11,36},{14,11,39},{16,11,83},{17,11,124},{148,11,30},{4,0,118},{6,0 +,274},{6,0,361},{7,0,75},{141,0,441},{10,11,322},{10,11,719},{139,11,407},{147, +10,119},{12,11,549},{14,11,67},{147,11,60},{11,10,69},{12,10,105},{12,10,117},{ +13,10,213},{14,10,13},{14,10,62},{14,10,177},{14,10,421},{15,10,19},{146,10,141} +,{9,0,841},{137,10,309},{7,10,608},{7,10,976},{8,11,125},{8,11,369},{8,11,524},{ +9,10,146},{10,10,206},{10,11,486},{10,10,596},{11,11,13},{11,11,381},{11,11,736} +,{11,11,766},{11,11,845},{13,11,114},{13,10,218},{13,11,292},{14,11,47},{142,10, +153},{12,0,693},{135,11,759},{5,0,314},{6,0,221},{7,0,419},{10,0,650},{11,0,396} +,{12,0,156},{13,0,369},{14,0,333},{145,0,47},{6,11,1684},{6,11,1731},{7,11,356}, +{7,11,1932},{8,11,54},{8,11,221},{9,11,225},{9,11,356},{10,11,77},{10,11,446},{ +10,11,731},{12,11,404},{141,11,491},{132,11,375},{4,10,518},{135,10,1136},{4,0, +913},{4,11,411},{11,11,643},{140,11,115},{4,11,80},{133,11,44},{8,10,689},{137, +10,863},{138,0,880},{4,10,18},{7,10,145},{7,10,444},{7,10,1278},{8,10,49},{8,10, +400},{9,10,71},{9,10,250},{10,10,459},{12,10,160},{144,10,24},{136,0,475},{5,0, +1016},{5,11,299},{135,11,1083},{7,0,602},{8,0,179},{10,0,781},{140,0,126},{6,0, +329},{138,0,111},{135,0,1864},{4,11,219},{7,11,1761},{137,11,86},{6,0,1888},{6,0 +,1892},{6,0,1901},{6,0,1904},{9,0,953},{9,0,985},{9,0,991},{9,0,1001},{12,0,818} +,{12,0,846},{12,0,847},{12,0,861},{12,0,862},{12,0,873},{12,0,875},{12,0,877},{ +12,0,879},{12,0,881},{12,0,884},{12,0,903},{12,0,915},{12,0,926},{12,0,939},{15, +0,182},{15,0,219},{15,0,255},{18,0,191},{18,0,209},{18,0,211},{149,0,41},{5,11, +328},{135,11,918},{137,0,780},{12,0,82},{143,0,36},{133,10,1010},{5,0,821},{134, +0,1687},{133,11,514},{132,0,956},{134,0,1180},{10,0,112},{5,10,87},{7,10,313},{7 +,10,1103},{10,10,582},{11,10,389},{11,10,813},{12,10,385},{13,10,286},{14,10,124 +},{146,10,108},{5,0,71},{7,0,1407},{9,0,704},{10,0,261},{10,0,619},{11,0,547},{ +11,0,619},{143,0,157},{4,0,531},{5,0,455},{5,11,301},{6,11,571},{14,11,49},{146, +11,102},{132,10,267},{6,0,385},{7,0,2008},{9,0,337},{138,0,517},{133,11,726},{ +133,11,364},{4,11,76},{7,11,1550},{9,11,306},{9,11,430},{9,11,663},{10,11,683},{ +11,11,427},{11,11,753},{12,11,334},{12,11,442},{14,11,258},{14,11,366},{143,11, +131},{6,0,1865},{6,0,1879},{6,0,1881},{6,0,1894},{6,0,1908},{9,0,915},{9,0,926}, +{9,0,940},{9,0,943},{9,0,966},{9,0,980},{9,0,989},{9,0,1005},{9,0,1010},{12,0, +813},{12,0,817},{12,0,840},{12,0,843},{12,0,855},{12,0,864},{12,0,871},{12,0,872 +},{12,0,899},{12,0,905},{12,0,924},{15,0,171},{15,0,181},{15,0,224},{15,0,235},{ +15,0,251},{146,0,184},{137,11,52},{5,0,16},{6,0,86},{6,0,603},{7,0,292},{7,0,561 +},{8,0,257},{8,0,382},{9,0,721},{9,0,778},{11,0,581},{140,0,466},{4,0,486},{5,0, +491},{135,10,1121},{4,0,72},{6,0,265},{135,0,1300},{135,11,1183},{10,10,249},{ +139,10,209},{132,10,561},{137,11,519},{4,11,656},{4,10,760},{135,11,779},{9,10, +154},{140,10,485},{135,11,1793},{135,11,144},{136,10,255},{133,0,621},{4,10,368} +,{135,10,641},{135,11,1373},{7,11,554},{7,11,605},{141,11,10},{137,0,234},{5,0, +815},{6,0,1688},{134,0,1755},{5,11,838},{5,11,841},{134,11,1649},{7,0,1987},{7,0 +,2040},{136,0,743},{133,11,1012},{6,0,197},{136,0,205},{6,0,314},{134,11,314},{ +144,11,53},{6,11,251},{7,11,365},{7,11,1357},{7,11,1497},{8,11,154},{141,11,281} +,{133,11,340},{6,0,452},{7,0,312},{138,0,219},{138,0,589},{4,0,333},{9,0,176},{ +12,0,353},{141,0,187},{9,10,92},{147,10,91},{134,0,1110},{11,0,47},{139,11,495}, +{6,10,525},{8,10,806},{9,10,876},{140,10,284},{8,11,261},{9,11,144},{9,11,466},{ +10,11,370},{12,11,470},{13,11,144},{142,11,348},{137,11,897},{8,0,863},{8,0,864} +,{8,0,868},{8,0,884},{10,0,866},{10,0,868},{10,0,873},{10,0,911},{10,0,912},{10, +0,944},{12,0,727},{6,11,248},{9,11,546},{10,11,535},{11,11,681},{141,11,135},{6, +0,300},{135,0,1515},{134,0,1237},{139,10,958},{133,10,594},{140,11,250},{134,0, +1685},{134,11,567},{7,0,135},{8,0,7},{8,0,62},{9,0,243},{10,0,658},{10,0,697},{ +11,0,456},{139,0,756},{9,0,395},{138,0,79},{6,10,1641},{136,10,820},{4,10,302},{ +135,10,1766},{134,11,174},{135,10,1313},{135,0,631},{134,10,1674},{134,11,395},{ +138,0,835},{7,0,406},{7,0,459},{8,0,606},{139,0,726},{134,11,617},{134,0,979},{6 +,10,389},{7,10,149},{9,10,142},{138,10,94},{5,11,878},{133,11,972},{6,10,8},{7, +10,1881},{8,10,91},{136,11,511},{133,0,612},{132,11,351},{4,0,372},{7,0,482},{8, +0,158},{9,0,602},{9,0,615},{10,0,245},{10,0,678},{10,0,744},{11,0,248},{139,0, +806},{5,0,854},{135,0,1991},{132,11,286},{135,11,344},{7,11,438},{7,11,627},{7, +11,1516},{8,11,40},{9,11,56},{9,11,294},{10,11,30},{10,11,259},{11,11,969},{146, +11,148},{135,0,1492},{5,11,259},{7,11,414},{7,11,854},{142,11,107},{135,10,1746} +,{6,0,833},{134,0,998},{135,10,24},{6,0,750},{135,0,1739},{4,10,503},{135,10, +1661},{5,10,130},{7,10,1314},{9,10,610},{10,10,718},{11,10,601},{11,10,819},{11, +10,946},{140,10,536},{10,10,149},{11,10,280},{142,10,336},{132,11,738},{135,10, +1946},{5,0,195},{135,0,1685},{7,0,1997},{8,0,730},{139,0,1006},{151,11,17},{133, +11,866},{14,0,463},{14,0,470},{150,0,61},{5,0,751},{8,0,266},{11,0,578},{4,10, +392},{135,10,1597},{5,10,433},{9,10,633},{139,10,629},{135,0,821},{6,0,715},{134 +,0,1325},{133,11,116},{6,0,868},{132,11,457},{134,0,959},{6,10,234},{138,11,199} +,{7,0,1053},{7,10,1950},{8,10,680},{11,10,817},{147,10,88},{7,10,1222},{138,10, +386},{5,0,950},{5,0,994},{6,0,351},{134,0,1124},{134,0,1081},{7,0,1595},{6,10,5} +,{11,10,249},{12,10,313},{16,10,66},{145,10,26},{148,0,59},{5,11,527},{6,11,189} +,{135,11,859},{5,10,963},{6,10,1773},{11,11,104},{11,11,554},{15,11,60},{143,11, +125},{135,0,47},{137,0,684},{134,11,116},{134,0,1606},{134,0,777},{7,0,1020},{8, +10,509},{136,10,792},{135,0,1094},{132,0,350},{133,11,487},{4,11,86},{5,11,667}, +{5,11,753},{6,11,316},{6,11,455},{135,11,946},{7,0,1812},{13,0,259},{13,0,356},{ +14,0,242},{147,0,114},{132,10,931},{133,0,967},{4,0,473},{7,0,623},{8,0,808},{9, +0,871},{9,0,893},{11,0,38},{11,0,431},{12,0,112},{12,0,217},{12,0,243},{12,0,562 +},{12,0,663},{12,0,683},{13,0,141},{13,0,197},{13,0,227},{13,0,406},{13,0,487},{ +14,0,156},{14,0,203},{14,0,224},{14,0,256},{18,0,58},{150,0,0},{138,0,286},{7,10 +,943},{139,10,614},{135,10,1837},{150,11,45},{132,0,798},{4,0,222},{7,0,286},{ +136,0,629},{4,11,79},{7,11,1773},{10,11,450},{11,11,589},{13,11,332},{13,11,493} +,{14,11,183},{14,11,334},{14,11,362},{14,11,368},{14,11,376},{14,11,379},{19,11, +90},{19,11,103},{19,11,127},{148,11,90},{5,0,337},{11,0,513},{11,0,889},{11,0, +961},{12,0,461},{13,0,79},{15,0,121},{4,10,90},{5,10,545},{7,10,754},{9,10,186}, +{10,10,72},{10,10,782},{11,10,577},{11,10,610},{12,10,354},{12,10,362},{140,10, +595},{141,0,306},{136,0,146},{7,0,1646},{9,10,329},{11,10,254},{141,11,124},{4,0 +,465},{135,0,1663},{132,0,525},{133,11,663},{10,0,299},{18,0,74},{9,10,187},{11, +10,1016},{145,10,44},{7,0,165},{7,0,919},{4,10,506},{136,10,517},{5,10,295},{135 +,10,1680},{133,11,846},{134,0,1064},{5,11,378},{7,11,1402},{7,11,1414},{8,11,465 +},{9,11,286},{10,11,185},{10,11,562},{10,11,635},{11,11,31},{11,11,393},{12,11, +456},{13,11,312},{18,11,65},{18,11,96},{147,11,89},{132,0,596},{7,10,987},{9,10, +688},{10,10,522},{11,10,788},{140,10,566},{6,0,82},{7,0,138},{7,0,517},{7,0,1741 +},{11,0,238},{4,11,648},{134,10,1775},{7,0,1233},{7,10,700},{7,10,940},{8,10,514 +},{9,10,116},{9,10,535},{10,10,118},{11,10,107},{11,10,148},{11,10,922},{12,10, +254},{12,10,421},{142,10,238},{4,0,962},{6,0,1824},{8,0,894},{12,0,708},{12,0, +725},{14,0,451},{20,0,94},{22,0,59},{150,0,62},{5,11,945},{6,11,1656},{6,11,1787 +},{7,11,167},{8,11,824},{9,11,391},{10,11,375},{139,11,185},{5,0,495},{7,0,834}, +{9,0,733},{139,0,378},{4,10,743},{135,11,1273},{6,0,1204},{7,11,1645},{8,11,352} +,{137,11,249},{139,10,292},{133,0,559},{132,11,152},{9,0,499},{10,0,341},{15,0, +144},{19,0,49},{7,10,1283},{9,10,227},{11,10,325},{11,10,408},{14,10,180},{146, +10,47},{6,0,21},{6,0,1737},{7,0,1444},{136,0,224},{133,11,1006},{7,0,1446},{9,0, +97},{17,0,15},{5,10,81},{7,10,146},{7,10,1342},{8,10,53},{8,10,561},{8,10,694},{ +8,10,754},{9,10,115},{9,10,894},{10,10,462},{10,10,813},{11,10,230},{11,10,657}, +{11,10,699},{11,10,748},{12,10,119},{12,10,200},{12,10,283},{142,10,273},{5,10, +408},{137,10,747},{135,11,431},{135,11,832},{6,0,729},{134,0,953},{4,0,727},{8,0 +,565},{5,11,351},{7,11,264},{136,11,565},{134,0,1948},{5,0,519},{5,11,40},{7,11, +598},{7,11,1638},{8,11,78},{9,11,166},{9,11,640},{9,11,685},{9,11,773},{11,11, +215},{13,11,65},{14,11,172},{14,11,317},{145,11,6},{8,11,60},{9,11,343},{139,11, +769},{137,11,455},{134,0,1193},{140,0,790},{7,11,1951},{8,11,765},{8,11,772},{ +140,11,671},{7,11,108},{8,11,219},{8,11,388},{9,11,639},{9,11,775},{11,11,275},{ +140,11,464},{132,11,468},{7,10,30},{8,10,86},{8,10,315},{8,10,700},{9,10,576},{9 +,10,858},{11,10,310},{11,10,888},{11,10,904},{12,10,361},{141,10,248},{5,11,15}, +{6,11,56},{7,11,1758},{8,11,500},{9,11,730},{11,11,331},{13,11,150},{142,11,282} +,{4,0,402},{7,0,2},{8,0,323},{136,0,479},{138,10,839},{11,0,580},{142,0,201},{5, +0,59},{135,0,672},{137,10,617},{146,0,34},{134,11,1886},{4,0,961},{136,0,896},{6 +,0,1285},{5,11,205},{6,11,438},{137,11,711},{134,10,428},{7,10,524},{8,10,169},{ +8,10,234},{9,10,480},{138,10,646},{148,0,46},{141,0,479},{133,11,534},{6,0,2019} +,{134,10,1648},{4,0,85},{7,0,549},{7,10,1205},{138,10,637},{4,0,663},{5,0,94},{7 +,11,235},{7,11,1475},{15,11,68},{146,11,120},{6,11,443},{9,11,237},{9,11,571},{9 +,11,695},{10,11,139},{11,11,715},{12,11,417},{141,11,421},{132,0,783},{4,0,682}, +{8,0,65},{9,10,39},{10,10,166},{11,10,918},{12,10,635},{20,10,10},{22,10,27},{22 +,10,43},{150,10,52},{6,0,11},{135,0,187},{132,0,522},{4,0,52},{135,0,661},{4,0, +383},{133,0,520},{135,11,546},{11,0,343},{142,0,127},{4,11,578},{7,10,157},{7,11 +,624},{7,11,916},{8,10,279},{10,11,256},{11,11,87},{139,11,703},{134,10,604},{4, +0,281},{5,0,38},{7,0,194},{7,0,668},{7,0,1893},{137,0,397},{7,10,945},{11,10,713 +},{139,10,744},{139,10,1022},{9,0,635},{139,0,559},{5,11,923},{7,11,490},{12,11, +553},{13,11,100},{14,11,118},{143,11,75},{132,0,975},{132,10,567},{137,10,859},{ +7,10,1846},{7,11,1846},{8,10,628},{136,11,628},{148,0,116},{138,11,750},{14,0,51 +},{14,11,51},{15,11,7},{148,11,20},{132,0,858},{134,0,1075},{4,11,924},{133,10, +762},{136,0,535},{133,0,448},{10,10,784},{141,10,191},{133,10,298},{7,0,610},{ +135,0,1501},{7,10,633},{7,10,905},{7,10,909},{7,10,1538},{9,10,767},{140,10,636} +,{4,11,265},{7,11,807},{135,11,950},{5,11,93},{12,11,267},{144,11,26},{136,0,191 +},{139,10,301},{135,10,1970},{135,0,267},{4,0,319},{5,0,699},{138,0,673},{6,0, +336},{7,0,92},{7,0,182},{8,0,453},{8,0,552},{9,0,204},{9,0,285},{10,0,99},{11,0, +568},{11,0,950},{12,0,94},{16,0,20},{16,0,70},{19,0,55},{12,10,644},{144,10,90}, +{6,0,551},{7,0,1308},{7,10,845},{7,11,994},{8,10,160},{137,10,318},{19,11,1},{19 +,11,26},{150,11,9},{7,0,1406},{9,0,218},{141,0,222},{5,0,256},{138,0,69},{5,11, +233},{5,11,320},{6,11,140},{7,11,330},{136,11,295},{6,0,1980},{136,0,952},{4,0, +833},{137,11,678},{133,11,978},{4,11,905},{6,11,1701},{137,11,843},{138,10,735}, +{136,10,76},{17,0,39},{148,0,36},{18,0,81},{146,11,81},{14,0,352},{17,0,53},{18, +0,146},{18,0,152},{19,0,11},{150,0,54},{135,0,634},{138,10,841},{132,0,618},{4,0 +,339},{7,0,259},{17,0,73},{4,11,275},{140,11,376},{132,11,509},{7,11,273},{139, +11,377},{4,0,759},{13,0,169},{137,10,804},{6,10,96},{135,10,1426},{4,10,651},{ +133,10,289},{7,0,1075},{8,10,35},{9,10,511},{10,10,767},{147,10,118},{6,0,649},{ +6,0,670},{136,0,482},{5,0,336},{6,0,341},{6,0,478},{6,0,1763},{136,0,386},{5,11, +802},{7,11,2021},{8,11,805},{14,11,94},{15,11,65},{16,11,4},{16,11,77},{16,11,80 +},{145,11,5},{6,0,1035},{5,11,167},{5,11,899},{6,11,410},{137,11,777},{134,11, +1705},{5,0,924},{133,0,969},{132,10,704},{135,0,73},{135,11,10},{135,10,1078},{5 +,11,11},{6,11,117},{6,11,485},{7,11,1133},{9,11,582},{9,11,594},{11,11,21},{11, +11,818},{12,11,535},{141,11,86},{135,0,1971},{4,11,264},{7,11,1067},{8,11,204},{ +8,11,385},{139,11,953},{6,0,1458},{135,0,1344},{5,0,396},{134,0,501},{4,10,720}, +{133,10,306},{4,0,929},{5,0,799},{8,0,46},{8,0,740},{133,10,431},{7,11,646},{7, +11,1730},{11,11,446},{141,11,178},{7,0,276},{5,10,464},{6,10,236},{7,10,696},{7, +10,914},{7,10,1108},{7,10,1448},{9,10,15},{9,10,564},{10,10,14},{12,10,565},{13, +10,449},{14,10,53},{15,10,13},{16,10,64},{145,10,41},{4,0,892},{133,0,770},{6,10 +,1767},{12,10,194},{145,10,107},{135,0,158},{5,10,840},{138,11,608},{134,0,1432} +,{138,11,250},{8,11,794},{9,11,400},{10,11,298},{142,11,228},{151,0,25},{7,11, +1131},{135,11,1468},{135,0,2001},{9,10,642},{11,10,236},{142,10,193},{4,10,68},{ +5,10,634},{6,10,386},{7,10,794},{8,10,273},{9,10,563},{10,10,105},{10,10,171},{ +11,10,94},{139,10,354},{136,11,724},{132,0,478},{11,11,512},{13,11,205},{19,11, +30},{22,11,36},{151,11,19},{7,0,1461},{140,0,91},{6,11,190},{7,11,768},{135,11, +1170},{4,0,602},{8,0,211},{4,10,95},{7,10,416},{139,10,830},{7,10,731},{13,10,20 +},{143,10,11},{6,0,1068},{135,0,1872},{4,0,13},{5,0,567},{7,0,1498},{9,0,124},{ +11,0,521},{12,0,405},{135,11,1023},{135,0,1006},{132,0,735},{138,0,812},{4,0,170 +},{135,0,323},{6,11,137},{9,11,75},{9,11,253},{10,11,194},{138,11,444},{5,0,304} +,{7,0,1403},{5,10,864},{10,10,648},{11,10,671},{143,10,46},{135,11,1180},{133,10 +,928},{4,0,148},{133,0,742},{11,10,986},{140,10,682},{133,0,523},{135,11,1743},{ +7,0,730},{18,0,144},{19,0,61},{8,10,44},{9,10,884},{10,10,580},{11,10,399},{11, +10,894},{143,10,122},{5,11,760},{7,11,542},{8,11,135},{136,11,496},{136,0,981},{ +133,0,111},{10,0,132},{11,0,191},{11,0,358},{139,0,460},{7,11,319},{7,11,355},{7 +,11,763},{10,11,389},{145,11,43},{134,0,890},{134,0,1420},{136,11,557},{133,10, +518},{133,0,444},{135,0,1787},{135,10,1852},{8,0,123},{15,0,6},{144,0,7},{6,0, +2041},{10,11,38},{139,11,784},{136,0,932},{5,0,937},{135,0,100},{6,0,995},{4,11, +58},{5,11,286},{6,11,319},{7,11,402},{7,11,1254},{7,11,1903},{8,11,356},{140,11, +408},{4,11,389},{9,11,181},{9,11,255},{10,11,8},{10,11,29},{10,11,816},{11,11, +311},{11,11,561},{12,11,67},{141,11,181},{138,0,255},{5,0,138},{4,10,934},{136, +10,610},{4,0,965},{10,0,863},{138,0,898},{10,10,804},{138,10,832},{12,0,631},{8, +10,96},{9,10,36},{10,10,607},{11,10,423},{11,10,442},{12,10,309},{14,10,199},{15 +,10,90},{145,10,110},{134,0,1394},{4,0,652},{8,0,320},{22,0,6},{22,0,16},{9,10, +13},{9,10,398},{9,10,727},{10,10,75},{10,10,184},{10,10,230},{10,10,564},{10,10, +569},{11,10,973},{12,10,70},{12,10,189},{13,10,57},{141,10,257},{6,0,897},{134,0 +,1333},{4,0,692},{133,0,321},{133,11,373},{135,0,922},{5,0,619},{133,0,698},{137 +,10,631},{5,10,345},{135,10,1016},{9,0,957},{9,0,1018},{12,0,828},{12,0,844},{12 +,0,897},{12,0,901},{12,0,943},{15,0,180},{18,0,197},{18,0,200},{18,0,213},{18,0, +214},{146,0,226},{5,0,917},{134,0,1659},{135,0,1100},{134,0,1173},{134,0,1930},{ +5,0,251},{5,0,956},{8,0,268},{9,0,214},{146,0,142},{133,10,673},{137,10,850},{4, +10,287},{133,10,1018},{132,11,672},{5,0,346},{5,0,711},{8,0,390},{11,11,752},{ +139,11,885},{5,10,34},{10,10,724},{12,10,444},{13,10,354},{18,10,32},{23,10,24}, +{23,10,31},{152,10,5},{4,11,710},{134,11,606},{134,0,744},{134,10,382},{133,11, +145},{4,10,329},{7,11,884},{140,11,124},{4,11,467},{5,11,405},{134,11,544},{9,10 +,846},{138,10,827},{133,0,624},{9,11,372},{15,11,2},{19,11,10},{147,11,18},{4,11 +,387},{135,11,1288},{5,0,783},{7,0,1998},{135,0,2047},{132,10,906},{136,10,366}, +{135,11,550},{4,10,123},{4,10,649},{5,10,605},{7,10,1509},{136,10,36},{134,0, +1125},{132,0,594},{133,10,767},{135,11,1227},{136,11,467},{4,11,576},{135,11, +1263},{4,0,268},{7,0,1534},{135,11,1534},{4,10,273},{5,10,658},{5,11,919},{5,10, +995},{134,11,1673},{133,0,563},{134,10,72},{135,10,1345},{4,11,82},{5,11,333},{5 +,11,904},{6,11,207},{7,11,325},{7,11,1726},{8,11,101},{10,11,778},{139,11,220},{ +5,0,37},{6,0,39},{6,0,451},{7,0,218},{7,0,667},{7,0,1166},{7,0,1687},{8,0,662},{ +16,0,2},{133,10,589},{134,0,1332},{133,11,903},{134,0,508},{5,10,117},{6,10,514} +,{6,10,541},{7,10,1164},{7,10,1436},{8,10,220},{8,10,648},{10,10,688},{11,10,560 +},{140,11,147},{6,11,555},{135,11,485},{133,10,686},{7,0,453},{7,0,635},{7,0,796 +},{8,0,331},{9,0,330},{9,0,865},{10,0,119},{10,0,235},{11,0,111},{11,0,129},{11, +0,240},{12,0,31},{12,0,66},{12,0,222},{12,0,269},{12,0,599},{12,0,684},{12,0,689 +},{12,0,691},{142,0,345},{135,0,1834},{4,11,705},{7,11,615},{138,11,251},{136,11 +,345},{137,0,527},{6,0,98},{7,0,702},{135,0,991},{11,0,576},{14,0,74},{7,10,196} +,{10,10,765},{11,10,347},{11,10,552},{11,10,790},{12,10,263},{13,10,246},{13,10, +270},{13,10,395},{14,10,176},{14,10,190},{14,10,398},{14,10,412},{15,10,32},{15, +10,63},{16,10,88},{147,10,105},{134,11,90},{13,0,84},{141,0,122},{6,0,37},{7,0, +299},{7,0,1666},{8,0,195},{8,0,316},{9,0,178},{9,0,276},{9,0,339},{9,0,536},{10, +0,102},{10,0,362},{10,0,785},{11,0,55},{11,0,149},{11,0,773},{13,0,416},{13,0, +419},{14,0,38},{14,0,41},{142,0,210},{5,10,381},{135,10,1792},{7,11,813},{12,11, +497},{141,11,56},{7,10,616},{138,10,413},{133,0,645},{6,11,125},{135,11,1277},{ +132,0,290},{6,0,70},{7,0,1292},{10,0,762},{139,0,288},{6,10,120},{7,10,1188},{7, +10,1710},{8,10,286},{9,10,667},{11,10,592},{139,10,730},{135,11,1784},{7,0,1315} +,{135,11,1315},{134,0,1955},{135,10,1146},{7,0,131},{7,0,422},{8,0,210},{140,0, +573},{4,10,352},{135,10,687},{139,0,797},{143,0,38},{14,0,179},{15,0,151},{150,0 +,11},{7,0,488},{4,10,192},{5,10,49},{6,10,200},{6,10,293},{134,10,1696},{132,0, +936},{135,11,703},{6,11,160},{7,11,1106},{9,11,770},{10,11,618},{11,11,112},{140 +,11,413},{5,0,453},{134,0,441},{135,0,595},{132,10,650},{132,10,147},{6,0,991},{ +6,0,1182},{12,11,271},{145,11,109},{133,10,934},{140,11,221},{132,0,653},{7,0, +505},{135,0,523},{134,0,903},{135,11,479},{7,11,304},{9,11,646},{9,11,862},{10, +11,262},{11,11,696},{12,11,208},{15,11,79},{147,11,108},{146,0,80},{135,11,981}, +{142,0,432},{132,0,314},{137,11,152},{7,0,1368},{8,0,232},{8,0,361},{10,0,682},{ +138,0,742},{135,11,1586},{9,0,534},{4,11,434},{11,11,663},{12,11,210},{13,11,166 +},{13,11,310},{14,11,373},{147,11,43},{7,11,1091},{135,11,1765},{6,11,550},{135, +11,652},{137,0,27},{142,0,12},{4,10,637},{5,11,553},{7,11,766},{138,11,824},{7, +11,737},{8,11,298},{136,11,452},{7,0,736},{139,0,264},{134,0,1657},{133,11,292}, +{138,11,135},{6,0,844},{134,0,1117},{135,0,127},{9,10,867},{138,10,837},{6,0, +1184},{134,0,1208},{134,0,1294},{136,0,364},{6,0,1415},{7,0,1334},{11,0,125},{6, +10,170},{7,11,393},{8,10,395},{8,10,487},{10,11,603},{11,11,206},{141,10,147},{ +137,11,748},{4,11,912},{137,11,232},{4,10,535},{136,10,618},{137,0,792},{7,11, +1973},{136,11,716},{135,11,98},{5,0,909},{9,0,849},{138,0,805},{4,0,630},{132,0, +699},{5,11,733},{14,11,103},{150,10,23},{12,11,158},{18,11,8},{19,11,62},{20,11, +6},{22,11,4},{23,11,2},{151,11,9},{132,0,968},{132,10,778},{132,10,46},{5,10,811 +},{6,10,1679},{6,10,1714},{135,10,2032},{6,0,1446},{7,10,1458},{9,10,407},{139, +10,15},{7,0,206},{7,0,397},{7,0,621},{7,0,640},{8,0,124},{8,0,619},{9,0,305},{9, +0,643},{10,0,264},{10,0,628},{11,0,40},{12,0,349},{13,0,134},{13,0,295},{14,0, +155},{15,0,120},{18,0,105},{6,10,34},{7,10,1089},{8,10,708},{8,10,721},{9,10,363 +},{148,10,98},{4,0,262},{5,0,641},{135,0,342},{137,11,72},{4,0,99},{6,0,250},{6, +0,346},{8,0,127},{138,0,81},{132,0,915},{5,0,75},{9,0,517},{10,0,470},{12,0,155} +,{141,0,224},{132,10,462},{11,11,600},{11,11,670},{141,11,245},{142,0,83},{5,10, +73},{6,10,23},{134,10,338},{6,0,1031},{139,11,923},{7,11,164},{7,11,1571},{9,11, +107},{140,11,225},{134,0,1470},{133,0,954},{6,0,304},{8,0,418},{10,0,345},{11,0, +341},{139,0,675},{9,0,410},{139,0,425},{4,11,27},{5,11,484},{5,11,510},{6,11,434 +},{7,11,1000},{7,11,1098},{8,11,2},{136,11,200},{134,0,734},{140,11,257},{7,10, +725},{8,10,498},{139,10,268},{134,0,1822},{135,0,1798},{135,10,773},{132,11,460} +,{4,11,932},{133,11,891},{134,0,14},{132,10,583},{7,10,1462},{8,11,625},{139,10, +659},{5,0,113},{6,0,243},{6,0,1708},{7,0,1865},{11,0,161},{16,0,37},{17,0,99},{ +133,10,220},{134,11,76},{5,11,461},{135,11,1925},{140,0,69},{8,11,92},{137,11, +221},{139,10,803},{132,10,544},{4,0,274},{134,0,922},{132,0,541},{5,0,627},{6,10 +,437},{6,10,564},{11,10,181},{141,10,183},{135,10,1192},{7,0,166},{132,11,763},{ +133,11,253},{134,0,849},{9,11,73},{10,11,110},{14,11,185},{145,11,119},{5,11,212 +},{12,11,35},{141,11,382},{133,0,717},{137,0,304},{136,0,600},{133,0,654},{6,0, +273},{10,0,188},{13,0,377},{146,0,77},{4,10,790},{5,10,273},{134,10,394},{132,0, +543},{135,0,410},{11,0,98},{11,0,524},{141,0,87},{132,0,941},{135,11,1175},{4,0, +250},{7,0,1612},{11,0,186},{12,0,133},{6,10,127},{7,10,1511},{8,10,613},{12,10, +495},{12,10,586},{12,10,660},{12,10,668},{14,10,385},{15,10,118},{17,10,20},{146 +,10,98},{6,0,1785},{133,11,816},{134,0,1339},{7,0,961},{7,0,1085},{7,0,1727},{8, +0,462},{6,10,230},{135,11,1727},{9,0,636},{135,10,1954},{132,0,780},{5,11,869},{ +5,11,968},{6,11,1626},{8,11,734},{136,11,784},{4,11,542},{6,11,1716},{6,11,1727} +,{7,11,1082},{7,11,1545},{8,11,56},{8,11,118},{8,11,412},{8,11,564},{9,11,888},{ +9,11,908},{10,11,50},{10,11,423},{11,11,685},{11,11,697},{11,11,933},{12,11,299} +,{13,11,126},{13,11,136},{13,11,170},{141,11,190},{134,11,226},{4,11,232},{9,11, +202},{10,11,474},{140,11,433},{137,11,500},{5,0,529},{136,10,68},{132,10,654},{4 +,10,156},{7,10,998},{7,10,1045},{7,10,1860},{9,10,48},{9,10,692},{11,10,419},{ +139,10,602},{7,0,1276},{8,0,474},{9,0,652},{6,11,108},{7,11,1003},{7,11,1181},{ +136,11,343},{7,11,1264},{7,11,1678},{11,11,945},{12,11,341},{12,11,471},{140,11, +569},{134,11,1712},{5,0,948},{12,0,468},{19,0,96},{148,0,24},{4,11,133},{7,11, +711},{7,11,1298},{7,11,1585},{135,11,1929},{6,0,753},{140,0,657},{139,0,941},{6, +11,99},{7,11,1808},{145,11,57},{6,11,574},{7,11,428},{7,11,1250},{10,11,669},{11 +,11,485},{11,11,840},{12,11,300},{142,11,250},{4,0,532},{5,0,706},{135,0,662},{5 +,0,837},{6,0,1651},{139,0,985},{7,0,1861},{9,10,197},{10,10,300},{12,10,473},{13 +,10,90},{141,10,405},{137,11,252},{6,11,323},{135,11,1564},{4,0,330},{4,0,863},{ +7,0,933},{7,0,2012},{8,0,292},{7,11,461},{8,11,775},{138,11,435},{132,10,606},{4 +,11,655},{7,11,850},{17,11,75},{146,11,137},{135,0,767},{7,10,1978},{136,10,676} +,{132,0,641},{135,11,1559},{134,0,1233},{137,0,242},{17,0,114},{4,10,361},{133, +10,315},{137,0,883},{132,10,461},{138,0,274},{134,0,2008},{134,0,1794},{4,0,703} +,{135,0,207},{12,0,285},{132,10,472},{132,0,571},{5,0,873},{5,0,960},{8,0,823},{ +9,0,881},{136,11,577},{7,0,617},{10,0,498},{11,0,501},{12,0,16},{140,0,150},{138 +,10,747},{132,0,431},{133,10,155},{11,0,283},{11,0,567},{7,10,163},{8,10,319},{9 +,10,402},{10,10,24},{10,10,681},{11,10,200},{12,10,253},{12,10,410},{142,10,219} +,{4,11,413},{5,11,677},{8,11,432},{140,11,280},{9,0,401},{5,10,475},{7,10,1780}, +{11,10,297},{11,10,558},{14,10,322},{147,10,76},{6,0,781},{9,0,134},{10,0,2},{10 +,0,27},{10,0,333},{11,0,722},{143,0,1},{5,0,33},{6,0,470},{139,0,424},{135,0, +2006},{12,0,783},{135,10,1956},{136,0,274},{135,0,1882},{132,0,794},{135,0,1848} +,{5,10,944},{134,10,1769},{6,0,47},{7,0,90},{7,0,664},{7,0,830},{7,0,1380},{7,0, +2025},{8,0,448},{136,0,828},{132,10,144},{134,0,1199},{4,11,395},{139,11,762},{ +135,11,1504},{9,0,417},{137,0,493},{9,11,174},{10,11,164},{11,11,440},{11,11,841 +},{143,11,98},{134,11,426},{139,11,1002},{134,0,295},{134,0,816},{6,10,247},{137 +,10,555},{133,0,1019},{4,0,620},{5,11,476},{10,10,280},{138,10,797},{139,0,464}, +{5,11,76},{6,11,458},{6,11,497},{7,11,764},{7,11,868},{9,11,658},{10,11,594},{11 +,11,173},{11,11,566},{12,11,20},{12,11,338},{141,11,200},{134,0,208},{4,11,526}, +{7,11,1029},{135,11,1054},{132,11,636},{6,11,233},{7,11,660},{7,11,1124},{17,11, +31},{19,11,22},{151,11,14},{10,0,442},{133,10,428},{10,0,930},{140,0,778},{6,0, +68},{7,0,448},{7,0,1629},{7,0,1769},{7,0,1813},{8,0,442},{8,0,516},{9,0,710},{10 +,0,282},{10,0,722},{7,10,1717},{138,10,546},{134,0,1128},{11,0,844},{12,0,104},{ +140,0,625},{4,11,432},{135,11,824},{138,10,189},{133,0,787},{133,10,99},{4,11, +279},{7,11,301},{137,11,362},{8,0,491},{4,10,397},{136,10,555},{4,11,178},{133, +11,399},{134,0,711},{144,0,9},{4,0,403},{5,0,441},{7,0,450},{10,0,840},{11,0,101 +},{12,0,193},{141,0,430},{135,11,1246},{12,10,398},{20,10,39},{21,10,11},{150,10 +,41},{4,10,485},{7,10,353},{135,10,1523},{6,10,366},{7,10,1384},{7,10,1601},{135 +,11,1912},{7,0,396},{10,0,160},{135,11,396},{137,10,282},{134,11,1692},{4,10,157 +},{5,10,471},{6,11,202},{10,11,448},{11,11,208},{12,11,360},{17,11,117},{17,11, +118},{18,11,27},{148,11,67},{133,0,679},{137,0,326},{136,10,116},{7,11,872},{10, +11,516},{139,11,167},{132,11,224},{5,11,546},{7,11,35},{8,11,11},{8,11,12},{9,11 +,315},{9,11,533},{10,11,802},{11,11,166},{12,11,525},{142,11,243},{7,0,1128},{ +135,11,1920},{5,11,241},{8,11,242},{9,11,451},{10,11,667},{11,11,598},{140,11, +429},{6,0,737},{5,10,160},{7,10,363},{7,10,589},{10,10,170},{141,10,55},{135,0, +1796},{142,11,254},{4,0,574},{7,0,350},{7,0,1024},{8,0,338},{9,0,677},{138,0,808 +},{134,0,1096},{137,11,516},{7,0,405},{10,0,491},{4,10,108},{4,11,366},{139,10, +498},{11,11,337},{142,11,303},{134,11,1736},{7,0,1081},{140,11,364},{7,10,1005}, +{140,10,609},{7,0,1676},{4,10,895},{133,10,772},{135,0,2037},{6,0,1207},{11,11, +916},{142,11,419},{14,11,140},{148,11,41},{6,11,331},{136,11,623},{9,0,944},{9,0 +,969},{9,0,1022},{12,0,913},{12,0,936},{15,0,177},{15,0,193},{4,10,926},{133,10, +983},{5,0,354},{135,11,506},{8,0,598},{9,0,664},{138,0,441},{4,11,640},{133,11, +513},{137,0,297},{132,10,538},{6,10,294},{7,10,1267},{136,10,624},{7,0,1772},{7, +11,1888},{8,11,289},{11,11,45},{12,11,278},{140,11,537},{135,10,1325},{138,0,751 +},{141,0,37},{134,0,1828},{132,10,757},{132,11,394},{6,0,257},{135,0,1522},{4,0, +582},{9,0,191},{135,11,1931},{7,11,574},{7,11,1719},{137,11,145},{132,11,658},{ +10,0,790},{132,11,369},{9,11,781},{10,11,144},{11,11,385},{13,11,161},{13,11,228 +},{13,11,268},{148,11,107},{8,0,469},{10,0,47},{136,11,374},{6,0,306},{7,0,1140} +,{7,0,1340},{8,0,133},{138,0,449},{139,0,1011},{7,10,1875},{139,10,124},{4,11, +344},{6,11,498},{139,11,323},{137,0,299},{132,0,837},{133,11,906},{5,0,329},{8,0 +,260},{138,0,10},{134,0,1320},{4,0,657},{146,0,158},{135,0,1191},{152,0,7},{6,0, +1939},{8,0,974},{138,0,996},{135,0,1665},{11,11,126},{139,11,287},{143,0,8},{14, +11,149},{14,11,399},{143,11,57},{5,0,66},{7,0,1896},{136,0,288},{7,0,175},{10,0, +494},{5,10,150},{8,10,603},{9,10,593},{9,10,634},{10,10,173},{11,10,462},{11,10, +515},{13,10,216},{13,10,288},{142,10,400},{134,0,1643},{136,11,21},{4,0,21},{5,0 +,91},{5,0,648},{5,0,750},{5,0,781},{6,0,54},{6,0,112},{6,0,402},{6,0,1732},{7,0, +315},{7,0,749},{7,0,1427},{7,0,1900},{9,0,78},{9,0,508},{10,0,611},{10,0,811},{ +11,0,510},{11,0,728},{13,0,36},{14,0,39},{16,0,83},{17,0,124},{148,0,30},{4,0, +668},{136,0,570},{10,0,322},{10,0,719},{139,0,407},{135,11,1381},{136,11,193},{ +12,10,108},{141,10,291},{132,11,616},{136,11,692},{8,0,125},{8,0,369},{8,0,524}, +{10,0,486},{11,0,13},{11,0,381},{11,0,736},{11,0,766},{11,0,845},{13,0,114},{13, +0,292},{142,0,47},{134,0,1247},{6,0,1684},{6,0,1731},{7,0,356},{8,0,54},{8,0,221 +},{9,0,225},{9,0,356},{10,0,77},{10,0,446},{10,0,731},{12,0,404},{141,0,491},{ +135,10,1777},{4,11,305},{4,10,493},{144,10,55},{4,0,951},{6,0,1809},{6,0,1849},{ +8,0,846},{8,0,866},{8,0,899},{10,0,896},{12,0,694},{142,0,468},{5,11,214},{7,11, +603},{8,11,611},{9,11,686},{10,11,88},{11,11,459},{11,11,496},{12,11,463},{12,11 +,590},{13,11,0},{142,11,214},{132,0,411},{4,0,80},{133,0,44},{140,11,74},{143,0, +31},{7,0,669},{6,10,568},{7,10,1804},{8,10,362},{8,10,410},{8,10,830},{9,10,514} +,{11,10,649},{142,10,157},{7,0,673},{134,11,1703},{132,10,625},{134,0,1303},{5,0 +,299},{135,0,1083},{138,0,704},{6,0,275},{7,0,408},{6,10,158},{7,10,129},{7,10, +181},{8,10,276},{8,10,377},{10,10,523},{11,10,816},{12,10,455},{13,10,303},{142, +10,135},{4,0,219},{7,0,367},{7,0,1713},{7,0,1761},{9,0,86},{9,0,537},{10,0,165}, +{12,0,219},{140,0,561},{8,0,216},{4,10,1},{4,11,737},{6,11,317},{7,10,1143},{7, +10,1463},{9,10,207},{9,10,390},{9,10,467},{10,11,98},{11,11,294},{11,10,836},{12 +,11,60},{12,11,437},{13,11,64},{13,11,380},{142,11,430},{6,11,1758},{8,11,520},{ +9,11,345},{9,11,403},{142,11,350},{5,11,47},{10,11,242},{138,11,579},{5,11,139}, +{7,11,1168},{138,11,539},{135,0,1319},{4,10,295},{4,10,723},{5,10,895},{7,10, +1031},{8,10,199},{8,10,340},{9,10,153},{9,10,215},{10,10,21},{10,10,59},{10,10, +80},{10,10,224},{10,10,838},{11,10,229},{11,10,652},{12,10,192},{13,10,146},{142 +,10,91},{140,0,428},{137,10,51},{133,0,514},{5,10,309},{140,10,211},{6,0,1010},{ +5,10,125},{8,10,77},{138,10,15},{4,0,55},{5,0,301},{6,0,571},{142,0,49},{146,0, +102},{136,11,370},{4,11,107},{7,11,613},{8,11,358},{8,11,439},{8,11,504},{9,11, +501},{10,11,383},{139,11,477},{132,11,229},{133,0,364},{133,10,439},{4,11,903},{ +135,11,1816},{11,0,379},{140,10,76},{4,0,76},{4,0,971},{7,0,1550},{9,0,306},{9,0 +,430},{9,0,663},{10,0,683},{10,0,921},{11,0,427},{11,0,753},{12,0,334},{12,0,442 +},{14,0,258},{14,0,366},{143,0,131},{137,0,52},{4,11,47},{6,11,373},{7,11,452},{ +7,11,543},{7,11,1714},{7,11,1856},{9,11,6},{11,11,257},{139,11,391},{4,10,8},{7, +10,1152},{7,10,1153},{7,10,1715},{9,10,374},{10,10,478},{139,10,648},{4,11,785}, +{133,11,368},{135,10,1099},{135,11,860},{5,11,980},{134,11,1754},{134,0,1258},{6 +,0,1058},{6,0,1359},{7,11,536},{7,11,1331},{136,11,143},{4,0,656},{135,0,779},{ +136,10,87},{5,11,19},{6,11,533},{146,11,126},{7,0,144},{138,10,438},{5,11,395},{ +5,11,951},{134,11,1776},{135,0,1373},{7,0,554},{7,0,605},{141,0,10},{4,10,69},{5 +,10,122},{9,10,656},{138,10,464},{5,10,849},{134,10,1633},{5,0,838},{5,0,841},{ +134,0,1649},{133,0,1012},{139,10,499},{7,10,476},{7,10,1592},{138,10,87},{6,0, +251},{7,0,365},{7,0,1357},{7,0,1497},{8,0,154},{141,0,281},{132,11,441},{132,11, +695},{7,11,497},{9,11,387},{147,11,81},{133,0,340},{14,10,283},{142,11,283},{134 +,0,810},{135,11,1894},{139,0,495},{5,11,284},{6,11,49},{6,11,350},{7,11,1},{7,11 +,377},{7,11,1693},{8,11,18},{8,11,678},{9,11,161},{9,11,585},{9,11,671},{9,11, +839},{11,11,912},{141,11,427},{5,10,859},{7,10,1160},{8,10,107},{9,10,291},{9,10 +,439},{10,10,663},{11,10,609},{140,10,197},{8,0,261},{9,0,144},{9,0,466},{10,0, +370},{12,0,470},{13,0,144},{142,0,348},{137,0,897},{6,0,248},{9,0,546},{10,0,535 +},{11,0,681},{141,0,135},{4,0,358},{135,0,1496},{134,0,567},{136,0,445},{4,10, +117},{6,10,372},{7,10,1905},{142,10,323},{4,10,722},{139,10,471},{6,0,697},{134, +0,996},{7,11,2007},{9,11,101},{9,11,450},{10,11,66},{10,11,842},{11,11,536},{140 +,11,587},{132,0,577},{134,0,1336},{9,10,5},{12,10,216},{12,10,294},{12,10,298},{ +12,10,400},{12,10,518},{13,10,229},{143,10,139},{6,0,174},{138,0,917},{134,10, +1774},{5,10,12},{7,10,375},{9,10,88},{9,10,438},{11,11,62},{139,10,270},{134,11, +1766},{6,11,0},{7,11,84},{7,10,816},{7,10,1241},{9,10,283},{9,10,520},{10,10,213 +},{10,10,307},{10,10,463},{10,10,671},{10,10,746},{11,10,401},{11,10,794},{11,11 +,895},{12,10,517},{17,11,11},{18,10,107},{147,10,115},{5,0,878},{133,0,972},{6, +11,1665},{7,11,256},{7,11,1388},{138,11,499},{4,10,258},{136,10,639},{4,11,22},{ +5,11,10},{6,10,22},{7,11,848},{7,10,903},{7,10,1963},{8,11,97},{138,10,577},{5, +10,681},{136,10,782},{133,11,481},{132,0,351},{4,10,664},{5,10,804},{139,10,1013 +},{6,11,134},{7,11,437},{7,11,959},{9,11,37},{14,11,285},{14,11,371},{144,11,60} +,{7,11,486},{8,11,155},{11,11,93},{140,11,164},{132,0,286},{7,0,438},{7,0,627},{ +7,0,1516},{8,0,40},{9,0,56},{9,0,294},{10,0,30},{11,0,969},{11,0,995},{146,0,148 +},{5,11,591},{135,11,337},{134,0,1950},{133,10,32},{138,11,500},{5,11,380},{5,11 +,650},{136,11,310},{4,11,364},{7,11,1156},{7,11,1187},{137,11,409},{4,0,738},{ +134,11,482},{4,11,781},{6,11,487},{7,11,926},{8,11,263},{139,11,500},{135,11,418 +},{6,0,2047},{10,0,969},{4,10,289},{7,10,629},{7,10,1698},{7,10,1711},{140,10, +215},{6,10,450},{136,10,109},{134,0,818},{136,10,705},{133,0,866},{4,11,94},{135 +,11,1265},{132,11,417},{134,0,1467},{135,10,1238},{4,0,972},{6,0,1851},{134,0, +1857},{134,0,355},{133,0,116},{132,0,457},{135,11,1411},{4,11,408},{4,11,741},{ +135,11,500},{134,10,26},{142,11,137},{5,0,527},{6,0,189},{7,0,859},{136,0,267},{ +11,0,104},{11,0,554},{15,0,60},{143,0,125},{134,0,1613},{4,10,414},{5,10,467},{9 +,10,654},{10,10,451},{12,10,59},{141,10,375},{135,10,17},{134,0,116},{135,11,541 +},{135,10,955},{6,11,73},{135,11,177},{133,11,576},{134,0,886},{133,0,487},{4,0, +86},{5,0,667},{5,0,753},{6,0,316},{6,0,455},{135,0,946},{142,11,231},{150,0,45}, +{134,0,863},{134,0,1953},{6,10,280},{10,10,502},{11,10,344},{140,10,38},{4,0,79} +,{7,0,1773},{10,0,450},{11,0,589},{13,0,332},{13,0,493},{14,0,183},{14,0,334},{ +14,0,362},{14,0,368},{14,0,376},{14,0,379},{19,0,90},{19,0,103},{19,0,127},{148, +0,90},{5,10,45},{7,10,1161},{11,10,448},{11,10,880},{13,10,139},{13,10,407},{15, +10,16},{17,10,95},{18,10,66},{18,10,88},{18,10,123},{149,10,7},{136,10,777},{4, +10,410},{135,10,521},{135,10,1778},{135,11,538},{142,0,381},{133,11,413},{134,0, +1142},{6,0,1189},{136,11,495},{5,0,663},{6,0,1962},{134,0,2003},{7,11,54},{8,11, +312},{10,11,191},{10,11,614},{140,11,567},{132,10,436},{133,0,846},{10,0,528},{ +11,0,504},{7,10,1587},{135,10,1707},{5,0,378},{8,0,465},{9,0,286},{10,0,185},{10 +,0,562},{10,0,635},{11,0,31},{11,0,393},{13,0,312},{18,0,65},{18,0,96},{147,0,89 +},{7,0,899},{14,0,325},{6,11,468},{7,11,567},{7,11,1478},{8,11,530},{142,11,290} +,{7,0,1880},{9,0,680},{139,0,798},{134,0,1770},{132,0,648},{150,11,35},{5,0,945} +,{6,0,1656},{6,0,1787},{7,0,167},{8,0,824},{9,0,391},{10,0,375},{139,0,185},{6, +11,484},{135,11,822},{134,0,2046},{7,0,1645},{8,0,352},{137,0,249},{132,0,152},{ +6,0,611},{135,0,1733},{6,11,1724},{135,11,2022},{133,0,1006},{141,11,96},{5,0, +420},{135,0,1449},{146,11,149},{135,0,832},{135,10,663},{133,0,351},{5,0,40},{7, +0,598},{7,0,1638},{8,0,78},{9,0,166},{9,0,640},{9,0,685},{9,0,773},{11,0,215},{ +13,0,65},{14,0,172},{14,0,317},{145,0,6},{8,0,60},{9,0,343},{139,0,769},{134,0, +1354},{132,0,724},{137,0,745},{132,11,474},{7,0,1951},{8,0,765},{8,0,772},{140,0 +,671},{7,0,108},{8,0,219},{8,0,388},{9,0,775},{11,0,275},{140,0,464},{137,0,639} +,{135,10,503},{133,11,366},{5,0,15},{6,0,56},{7,0,1758},{8,0,500},{9,0,730},{11, +0,331},{13,0,150},{14,0,282},{5,11,305},{9,11,560},{141,11,208},{4,10,113},{5,10 +,163},{5,10,735},{7,10,1009},{9,10,9},{9,10,771},{12,10,90},{13,10,138},{13,10, +410},{143,10,128},{4,10,324},{138,10,104},{135,11,466},{142,11,27},{134,0,1886}, +{5,0,205},{6,0,438},{9,0,711},{4,11,480},{6,11,167},{6,11,302},{6,11,1642},{7,11 +,130},{7,11,656},{7,11,837},{7,11,1547},{7,11,1657},{8,11,429},{9,11,228},{10,11 +,643},{13,11,289},{13,11,343},{147,11,101},{134,0,865},{6,0,2025},{136,0,965},{7 +,11,278},{10,11,739},{11,11,708},{141,11,348},{133,0,534},{135,11,1922},{137,0, +691},{4,10,935},{133,10,823},{6,0,443},{9,0,237},{9,0,571},{9,0,695},{10,0,139}, +{11,0,715},{12,0,417},{141,0,421},{5,10,269},{7,10,434},{7,10,891},{8,10,339},{9 +,10,702},{11,10,594},{11,10,718},{145,10,100},{6,0,1555},{7,0,878},{9,10,485},{ +141,10,264},{134,10,1713},{7,10,1810},{11,10,866},{12,10,103},{141,10,495},{135, +10,900},{6,0,1410},{9,11,316},{139,11,256},{4,0,995},{135,0,1033},{132,0,578},{ +10,0,881},{12,0,740},{12,0,743},{140,0,759},{132,0,822},{133,0,923},{142,10,143} +,{135,11,1696},{6,11,363},{7,11,1955},{136,11,725},{132,0,924},{133,0,665},{135, +10,2029},{135,0,1901},{4,0,265},{6,0,1092},{6,0,1417},{7,0,807},{135,0,950},{5,0 +,93},{12,0,267},{141,0,498},{135,0,1451},{5,11,813},{135,11,2046},{5,10,625},{ +135,10,1617},{135,0,747},{6,0,788},{137,0,828},{7,0,184},{11,0,307},{11,0,400},{ +15,0,130},{5,11,712},{7,11,1855},{8,10,425},{8,10,693},{9,10,720},{10,10,380},{ +10,10,638},{11,11,17},{11,10,473},{12,10,61},{13,11,321},{144,11,67},{135,0,198} +,{6,11,320},{7,11,781},{7,11,1921},{9,11,55},{10,11,186},{10,11,273},{10,11,664} +,{10,11,801},{11,11,996},{11,11,997},{13,11,157},{142,11,170},{136,11,271},{135, +0,994},{7,11,103},{7,11,863},{11,11,184},{14,11,299},{145,11,62},{11,10,551},{ +142,10,159},{5,0,233},{5,0,320},{6,0,140},{8,0,295},{8,0,615},{136,11,615},{133, +0,978},{4,0,905},{6,0,1701},{137,0,843},{132,10,168},{4,0,974},{8,0,850},{12,0, +709},{12,0,768},{140,0,786},{135,10,91},{152,0,6},{138,10,532},{135,10,1884},{ +132,0,509},{6,0,1307},{135,0,273},{5,11,77},{7,11,1455},{10,11,843},{19,11,73},{ +150,11,5},{132,11,458},{135,11,1420},{6,11,109},{138,11,382},{6,0,201},{6,11,330 +},{7,10,70},{7,11,1084},{10,10,240},{11,11,142},{147,10,93},{7,0,1041},{140,11, +328},{133,11,354},{134,0,1040},{133,0,693},{134,0,774},{139,0,234},{132,0,336},{ +7,0,1399},{139,10,392},{20,0,22},{148,11,22},{5,0,802},{7,0,2021},{136,0,805},{5 +,0,167},{5,0,899},{6,0,410},{137,0,777},{137,0,789},{134,0,1705},{7,10,655},{135 +,10,1844},{4,10,145},{6,10,176},{7,10,395},{137,10,562},{132,10,501},{135,0,10}, +{5,0,11},{6,0,117},{6,0,485},{7,0,1133},{9,0,582},{9,0,594},{10,0,82},{11,0,21}, +{11,0,818},{12,0,535},{13,0,86},{20,0,91},{23,0,13},{134,10,509},{4,0,264},{7,0, +1067},{8,0,204},{8,0,385},{139,0,953},{139,11,737},{138,0,56},{134,0,1917},{133, +0,470},{10,11,657},{14,11,297},{142,11,361},{135,11,412},{7,0,1198},{7,11,1198}, +{8,11,556},{14,11,123},{14,11,192},{143,11,27},{7,11,1985},{14,11,146},{15,11,42 +},{16,11,23},{17,11,86},{146,11,17},{11,0,1015},{136,11,122},{4,10,114},{9,10, +492},{13,10,462},{142,10,215},{4,10,77},{5,10,361},{6,10,139},{6,10,401},{6,10, +404},{7,10,413},{7,10,715},{7,10,1716},{11,10,279},{12,10,179},{12,10,258},{13, +10,244},{142,10,358},{134,10,1717},{7,10,1061},{8,10,82},{11,10,250},{12,10,420} +,{141,10,184},{133,0,715},{135,10,724},{9,0,919},{9,0,922},{9,0,927},{9,0,933},{ +9,0,962},{9,0,1000},{9,0,1002},{9,0,1021},{12,0,890},{12,0,907},{12,0,930},{15,0 +,207},{15,0,228},{15,0,238},{149,0,61},{8,0,794},{9,0,400},{10,0,298},{142,0,228 +},{5,11,430},{5,11,932},{6,11,131},{7,11,417},{9,11,522},{11,11,314},{141,11,390 +},{132,0,867},{8,0,724},{132,11,507},{137,11,261},{4,11,343},{133,11,511},{6,0, +190},{7,0,768},{135,0,1170},{6,10,513},{135,10,1052},{7,11,455},{138,11,591},{ +134,0,1066},{137,10,899},{14,0,67},{147,0,60},{4,0,948},{18,0,174},{146,0,176},{ +135,0,1023},{7,10,1417},{12,10,382},{17,10,48},{152,10,12},{134,11,575},{132,0, +764},{6,10,545},{7,10,565},{7,10,1669},{10,10,114},{11,10,642},{140,10,618},{6,0 +,137},{9,0,75},{9,0,253},{10,0,194},{138,0,444},{4,0,756},{133,10,5},{8,0,1008}, +{135,10,192},{132,0,842},{11,0,643},{12,0,115},{136,10,763},{139,0,67},{133,10, +759},{4,0,821},{5,0,760},{7,0,542},{8,0,135},{8,0,496},{135,11,580},{7,10,370},{ +7,10,1007},{7,10,1177},{135,10,1565},{135,10,1237},{140,0,736},{7,0,319},{7,0, +355},{7,0,763},{10,0,389},{145,0,43},{8,11,333},{138,11,182},{4,10,87},{5,10,250 +},{141,10,298},{138,0,786},{134,0,2044},{8,11,330},{140,11,477},{135,11,1338},{ +132,11,125},{134,0,1030},{134,0,1083},{132,11,721},{135,10,814},{7,11,776},{8,11 +,145},{147,11,56},{134,0,1226},{4,10,57},{7,10,1195},{7,10,1438},{7,10,1548},{7, +10,1835},{7,10,1904},{9,10,757},{10,10,604},{139,10,519},{7,11,792},{8,11,147},{ +10,11,821},{139,11,1021},{137,11,797},{4,0,58},{5,0,286},{6,0,319},{7,0,402},{7, +0,1254},{7,0,1903},{8,0,356},{140,0,408},{4,0,389},{4,0,815},{9,0,181},{9,0,255} +,{10,0,8},{10,0,29},{10,0,816},{11,0,311},{11,0,561},{12,0,67},{141,0,181},{7,11 +,1472},{135,11,1554},{7,11,1071},{7,11,1541},{7,11,1767},{7,11,1806},{7,11,1999} +,{9,11,248},{10,11,400},{11,11,162},{11,11,178},{11,11,242},{12,11,605},{15,11, +26},{144,11,44},{5,11,168},{5,11,930},{8,11,74},{9,11,623},{12,11,500},{12,11, +579},{13,11,41},{143,11,93},{6,11,220},{7,11,1101},{141,11,105},{5,0,474},{7,0, +507},{4,10,209},{7,11,507},{135,10,902},{132,0,427},{6,0,413},{7,10,335},{7,10, +1437},{7,10,1668},{8,10,553},{8,10,652},{8,10,656},{9,10,558},{11,10,743},{149, +10,18},{132,0,730},{6,11,19},{7,11,1413},{139,11,428},{133,0,373},{132,10,559},{ +7,11,96},{8,11,401},{137,11,896},{7,0,799},{7,0,1972},{5,10,1017},{138,10,511},{ +135,0,1793},{7,11,1961},{7,11,1965},{8,11,702},{136,11,750},{8,11,150},{8,11,737 +},{140,11,366},{132,0,322},{133,10,709},{8,11,800},{9,11,148},{9,11,872},{9,11, +890},{11,11,309},{11,11,1001},{13,11,267},{141,11,323},{134,10,1745},{7,0,290},{ +136,10,206},{7,0,1651},{145,0,89},{139,0,2},{132,0,672},{6,0,1860},{8,0,905},{10 +,0,844},{10,0,846},{10,0,858},{12,0,699},{12,0,746},{140,0,772},{135,11,424},{ +133,11,547},{133,0,737},{5,11,490},{6,11,615},{6,11,620},{135,11,683},{6,0,746}, +{134,0,1612},{132,10,776},{9,11,385},{149,11,17},{133,0,145},{135,10,1272},{7,0, +884},{140,0,124},{4,0,387},{135,0,1288},{5,11,133},{136,10,406},{136,11,187},{6, +0,679},{8,11,8},{138,11,0},{135,0,550},{135,11,798},{136,11,685},{7,11,1086},{ +145,11,46},{8,10,175},{10,10,168},{138,10,573},{135,0,1305},{4,0,576},{135,0, +1263},{6,0,686},{134,0,1563},{134,0,607},{5,0,919},{134,0,1673},{148,0,37},{8,11 +,774},{10,11,670},{140,11,51},{133,10,784},{139,10,882},{4,0,82},{5,0,333},{5,0, +904},{6,0,207},{7,0,325},{7,0,1726},{8,0,101},{10,0,778},{139,0,220},{135,11,371 +},{132,0,958},{133,0,903},{4,11,127},{5,11,350},{6,11,356},{8,11,426},{9,11,572} +,{10,11,247},{139,11,312},{140,0,147},{6,11,59},{7,11,885},{9,11,603},{141,11, +397},{10,0,367},{9,10,14},{9,10,441},{139,10,9},{11,10,966},{12,10,287},{13,10, +342},{13,10,402},{15,10,110},{143,10,163},{134,0,690},{132,0,705},{9,0,651},{11, +0,971},{13,0,273},{7,10,1428},{7,10,1640},{7,10,1867},{9,10,169},{9,10,182},{9, +10,367},{9,10,478},{9,10,506},{9,10,551},{9,10,557},{9,10,648},{9,10,697},{9,10, +705},{9,10,725},{9,10,787},{9,10,794},{10,10,198},{10,10,214},{10,10,267},{10,10 +,275},{10,10,456},{10,10,551},{10,10,561},{10,10,613},{10,10,627},{10,10,668},{ +10,10,675},{10,10,691},{10,10,695},{10,10,707},{10,10,715},{11,10,183},{11,10, +201},{11,10,262},{11,10,352},{11,10,439},{11,10,493},{11,10,572},{11,10,591},{11 +,10,608},{11,10,611},{11,10,646},{11,10,674},{11,10,711},{11,10,751},{11,10,761} +,{11,10,776},{11,10,785},{11,10,850},{11,10,853},{11,10,862},{11,10,865},{11,10, +868},{11,10,875},{11,10,898},{11,10,902},{11,10,903},{11,10,910},{11,10,932},{11 +,10,942},{11,10,957},{11,10,967},{11,10,972},{12,10,148},{12,10,195},{12,10,220} +,{12,10,237},{12,10,318},{12,10,339},{12,10,393},{12,10,445},{12,10,450},{12,10, +474},{12,10,505},{12,10,509},{12,10,533},{12,10,591},{12,10,594},{12,10,597},{12 +,10,621},{12,10,633},{12,10,642},{13,10,59},{13,10,60},{13,10,145},{13,10,239},{ +13,10,250},{13,10,329},{13,10,344},{13,10,365},{13,10,372},{13,10,387},{13,10, +403},{13,10,414},{13,10,456},{13,10,470},{13,10,478},{13,10,483},{13,10,489},{14 +,10,55},{14,10,57},{14,10,81},{14,10,90},{14,10,148},{14,10,239},{14,10,266},{14 +,10,321},{14,10,326},{14,10,327},{14,10,330},{14,10,347},{14,10,355},{14,10,401} +,{14,10,404},{14,10,411},{14,10,414},{14,10,416},{14,10,420},{15,10,61},{15,10, +74},{15,10,87},{15,10,88},{15,10,94},{15,10,96},{15,10,116},{15,10,149},{15,10, +154},{16,10,50},{16,10,63},{16,10,73},{17,10,2},{17,10,66},{17,10,92},{17,10,103 +},{17,10,112},{17,10,120},{18,10,50},{18,10,54},{18,10,82},{18,10,86},{18,10,90} +,{18,10,111},{18,10,115},{18,10,156},{19,10,40},{19,10,79},{20,10,78},{149,10,22 +},{7,0,887},{5,10,161},{135,10,839},{142,11,98},{134,0,90},{138,11,356},{135,11, +441},{6,11,111},{7,11,4},{8,11,163},{8,11,776},{138,11,566},{134,0,908},{134,0, +1261},{7,0,813},{12,0,497},{141,0,56},{134,0,1235},{135,0,429},{135,11,1994},{ +138,0,904},{6,0,125},{7,0,1277},{137,0,772},{151,0,12},{4,0,841},{5,0,386},{133, +11,386},{5,11,297},{135,11,1038},{6,0,860},{6,0,1069},{135,11,309},{136,0,946},{ +135,10,1814},{141,11,418},{136,11,363},{10,0,768},{139,0,787},{22,11,30},{150,11 +,33},{6,0,160},{7,0,1106},{9,0,770},{11,0,112},{140,0,413},{11,11,216},{139,11, +340},{136,10,139},{135,11,1390},{135,11,808},{132,11,280},{12,0,271},{17,0,109}, +{7,10,643},{136,10,236},{140,11,54},{4,11,421},{133,11,548},{11,0,719},{12,0,36} +,{141,0,337},{7,0,581},{9,0,644},{137,0,699},{11,11,511},{13,11,394},{14,11,298} +,{14,11,318},{146,11,103},{7,0,304},{9,0,646},{9,0,862},{11,0,696},{12,0,208},{ +15,0,79},{147,0,108},{4,0,631},{7,0,1126},{135,0,1536},{135,11,1527},{8,0,880},{ +10,0,869},{138,0,913},{7,0,1513},{5,10,54},{6,11,254},{9,11,109},{138,11,103},{ +135,0,981},{133,11,729},{132,10,744},{132,0,434},{134,0,550},{7,0,930},{10,0,476 +},{13,0,452},{19,0,104},{6,11,1630},{10,10,402},{146,10,55},{5,0,553},{138,0,824 +},{136,0,452},{8,0,151},{137,10,624},{132,10,572},{132,0,772},{133,11,671},{133, +0,292},{138,0,135},{132,11,889},{140,11,207},{9,0,504},{6,10,43},{7,10,38},{8,10 +,248},{138,10,513},{6,0,1089},{135,11,1910},{4,11,627},{133,11,775},{135,0,783}, +{133,10,766},{133,10,363},{7,0,387},{135,11,387},{7,0,393},{10,0,603},{11,0,206} +,{7,11,202},{11,11,362},{11,11,948},{140,11,388},{6,11,507},{7,11,451},{8,11,389 +},{12,11,490},{13,11,16},{13,11,215},{13,11,351},{18,11,132},{147,11,125},{4,0, +912},{9,0,232},{135,11,841},{6,10,258},{140,10,409},{5,10,249},{148,10,82},{136, +11,566},{6,0,977},{135,11,1214},{7,0,1973},{136,0,716},{135,0,98},{133,0,733},{5 +,11,912},{134,11,1695},{5,10,393},{6,10,378},{7,10,1981},{9,10,32},{9,10,591},{ +10,10,685},{10,10,741},{142,10,382},{133,10,788},{10,0,19},{11,0,911},{7,10,1968 +},{141,10,509},{5,0,668},{5,11,236},{6,11,572},{8,11,492},{11,11,618},{144,11,56 +},{135,11,1789},{4,0,360},{5,0,635},{5,0,700},{5,10,58},{5,10,171},{5,10,683},{6 +,10,291},{6,10,566},{7,10,1650},{11,10,523},{12,10,273},{12,10,303},{15,10,39},{ +143,10,111},{133,0,901},{134,10,589},{5,11,190},{136,11,318},{140,0,656},{7,0, +726},{152,0,9},{4,10,917},{133,10,1005},{135,10,1598},{134,11,491},{4,10,919},{ +133,11,434},{137,0,72},{6,0,1269},{6,0,1566},{134,0,1621},{9,0,463},{10,0,595},{ +4,10,255},{5,10,302},{6,10,132},{7,10,128},{7,10,283},{7,10,1299},{10,10,52},{10 +,10,514},{11,10,925},{13,10,92},{142,10,309},{135,0,1454},{134,0,1287},{11,0,600 +},{13,0,245},{137,10,173},{136,0,989},{7,0,164},{7,0,1571},{9,0,107},{140,0,225} +,{6,0,1061},{141,10,442},{4,0,27},{5,0,484},{5,0,510},{6,0,434},{7,0,1000},{7,0, +1098},{136,0,2},{7,11,85},{7,11,247},{8,11,585},{10,11,163},{138,11,316},{11,11, +103},{142,11,0},{134,0,1127},{4,0,460},{134,0,852},{134,10,210},{4,0,932},{133,0 +,891},{6,0,588},{147,11,83},{8,0,625},{4,10,284},{134,10,223},{134,0,76},{8,0,92 +},{137,0,221},{4,11,124},{10,11,457},{11,11,121},{11,11,169},{11,11,422},{11,11, +870},{12,11,214},{13,11,389},{14,11,187},{143,11,77},{9,11,618},{138,11,482},{4, +10,218},{7,10,526},{143,10,137},{13,0,9},{14,0,104},{14,0,311},{4,10,270},{5,10, +192},{6,10,332},{135,10,1322},{140,10,661},{135,11,1193},{6,11,107},{7,11,638},{ +7,11,1632},{137,11,396},{132,0,763},{4,0,622},{5,11,370},{134,11,1756},{133,0, +253},{135,0,546},{9,0,73},{10,0,110},{14,0,185},{17,0,119},{133,11,204},{7,0,624 +},{7,0,916},{10,0,256},{139,0,87},{7,10,379},{8,10,481},{137,10,377},{5,0,212},{ +12,0,35},{13,0,382},{5,11,970},{134,11,1706},{9,0,746},{5,10,1003},{134,10,149}, +{10,0,150},{11,0,849},{13,0,330},{8,10,262},{9,10,627},{11,10,214},{11,10,404},{ +11,10,457},{11,10,780},{11,10,913},{13,10,401},{142,10,200},{134,0,1466},{135,11 +,3},{6,0,1299},{4,11,35},{5,11,121},{5,11,483},{5,11,685},{6,11,489},{7,11,1204} +,{136,11,394},{135,10,742},{4,10,142},{136,10,304},{4,11,921},{133,11,1007},{134 +,0,1518},{6,0,1229},{135,0,1175},{133,0,816},{12,0,159},{4,10,471},{4,11,712},{5 +,10,51},{6,10,602},{7,10,925},{8,10,484},{138,10,195},{134,11,1629},{5,0,869},{5 +,0,968},{6,0,1626},{8,0,734},{136,0,784},{4,0,542},{6,0,1716},{6,0,1727},{7,0, +1082},{7,0,1545},{8,0,56},{8,0,118},{8,0,412},{8,0,564},{9,0,888},{9,0,908},{10, +0,50},{10,0,423},{11,0,685},{11,0,697},{11,0,933},{12,0,299},{13,0,126},{13,0, +136},{13,0,170},{13,0,190},{136,10,688},{132,10,697},{4,0,232},{9,0,202},{10,0, +474},{140,0,433},{136,0,212},{6,0,108},{7,0,1003},{7,0,1181},{8,0,111},{136,0, +343},{5,10,221},{135,11,1255},{133,11,485},{134,0,1712},{142,0,216},{5,0,643},{6 +,0,516},{4,11,285},{5,11,317},{6,11,301},{7,11,7},{8,11,153},{10,11,766},{11,11, +468},{12,11,467},{141,11,143},{4,0,133},{7,0,711},{7,0,1298},{135,0,1585},{134,0 +,650},{135,11,512},{6,0,99},{7,0,1808},{145,0,57},{6,0,246},{6,0,574},{7,0,428}, +{9,0,793},{10,0,669},{11,0,485},{11,0,840},{12,0,300},{14,0,250},{145,0,55},{4, +10,132},{5,10,69},{135,10,1242},{136,0,1023},{7,0,302},{132,10,111},{135,0,1871} +,{132,0,728},{9,0,252},{132,10,767},{6,0,461},{7,0,1590},{7,10,1416},{7,10,2005} +,{8,10,131},{8,10,466},{9,10,672},{13,10,252},{148,10,103},{6,0,323},{135,0,1564 +},{7,0,461},{136,0,775},{6,10,44},{136,10,368},{139,0,172},{132,0,464},{4,10,570 +},{133,10,120},{137,11,269},{6,10,227},{135,10,1589},{6,11,1719},{6,11,1735},{7, +11,2016},{7,11,2020},{8,11,837},{137,11,852},{7,0,727},{146,0,73},{132,0,1023},{ +135,11,852},{135,10,1529},{136,0,577},{138,11,568},{134,0,1037},{8,11,67},{138, +11,419},{4,0,413},{5,0,677},{8,0,432},{140,0,280},{10,0,600},{6,10,1667},{7,11, +967},{7,10,2036},{141,11,11},{6,10,511},{140,10,132},{6,0,799},{5,10,568},{6,10, +138},{135,10,1293},{8,0,159},{4,10,565},{136,10,827},{7,0,646},{7,0,1730},{11,0, +446},{141,0,178},{4,10,922},{133,10,1023},{135,11,11},{132,0,395},{11,0,145},{ +135,10,1002},{9,0,174},{10,0,164},{11,0,440},{11,0,514},{11,0,841},{15,0,98},{ +149,0,20},{134,0,426},{10,0,608},{139,0,1002},{7,11,320},{8,11,51},{12,11,481},{ +12,11,570},{148,11,106},{9,0,977},{9,0,983},{132,11,445},{138,0,250},{139,0,100} +,{6,0,1982},{136,10,402},{133,11,239},{4,10,716},{141,10,31},{5,0,476},{7,11,83} +,{7,11,1990},{8,11,130},{139,11,720},{8,10,691},{136,10,731},{5,11,123},{6,11, +530},{7,11,348},{135,11,1419},{5,0,76},{6,0,458},{6,0,497},{7,0,868},{9,0,658},{ +10,0,594},{11,0,173},{11,0,566},{12,0,20},{12,0,338},{141,0,200},{9,11,139},{10, +11,399},{11,11,469},{12,11,634},{141,11,223},{9,10,840},{138,10,803},{133,10,847 +},{11,11,223},{140,11,168},{132,11,210},{8,0,447},{9,10,53},{9,10,268},{9,10,901 +},{10,10,518},{10,10,829},{11,10,188},{13,10,74},{14,10,46},{15,10,17},{15,10,33 +},{17,10,40},{18,10,36},{19,10,20},{22,10,1},{152,10,2},{4,0,526},{7,0,1029},{ +135,0,1054},{19,11,59},{150,11,2},{4,0,636},{6,0,1875},{6,0,1920},{9,0,999},{12, +0,807},{12,0,825},{15,0,179},{15,0,190},{18,0,182},{136,10,532},{6,0,1699},{7,0, +660},{7,0,1124},{17,0,31},{19,0,22},{151,0,14},{135,10,681},{132,11,430},{140,10 +,677},{4,10,684},{136,10,384},{132,11,756},{133,11,213},{7,0,188},{7,10,110},{8, +10,290},{8,10,591},{9,10,382},{9,10,649},{11,10,71},{11,10,155},{11,10,313},{12, +10,5},{13,10,325},{142,10,287},{7,10,360},{7,10,425},{9,10,66},{9,10,278},{138, +10,644},{142,11,164},{4,0,279},{7,0,301},{137,0,362},{134,11,586},{135,0,1743},{ +4,0,178},{133,0,399},{4,10,900},{133,10,861},{5,10,254},{7,10,985},{136,10,73},{ +133,11,108},{7,10,1959},{136,10,683},{133,11,219},{4,11,193},{5,11,916},{7,11, +364},{10,11,398},{10,11,726},{11,11,317},{11,11,626},{12,11,142},{12,11,288},{12 +,11,678},{13,11,313},{15,11,113},{18,11,114},{21,11,30},{150,11,53},{6,11,241},{ +7,11,907},{8,11,832},{9,11,342},{10,11,729},{11,11,284},{11,11,445},{11,11,651}, +{11,11,863},{13,11,398},{146,11,99},{132,0,872},{134,0,831},{134,0,1692},{6,0, +202},{6,0,1006},{9,0,832},{10,0,636},{11,0,208},{12,0,360},{17,0,118},{18,0,27}, +{20,0,67},{137,11,734},{132,10,725},{7,11,993},{138,11,666},{134,0,1954},{134,10 +,196},{7,0,872},{10,0,516},{139,0,167},{133,10,831},{4,11,562},{9,11,254},{139, +11,879},{137,0,313},{4,0,224},{132,11,786},{11,0,24},{12,0,170},{136,10,723},{5, +0,546},{7,0,35},{8,0,11},{8,0,12},{9,0,315},{9,0,533},{10,0,802},{11,0,166},{12, +0,525},{142,0,243},{7,0,1937},{13,10,80},{13,10,437},{145,10,74},{5,0,241},{8,0, +242},{9,0,451},{10,0,667},{11,0,598},{140,0,429},{150,0,46},{6,0,1273},{137,0, +830},{5,10,848},{6,10,66},{136,10,764},{6,0,825},{134,0,993},{4,0,1006},{10,0, +327},{13,0,271},{4,10,36},{7,10,1387},{139,10,755},{134,0,1023},{135,0,1580},{4, +0,366},{137,0,516},{132,10,887},{6,0,1736},{135,0,1891},{6,11,216},{7,11,901},{7 +,11,1343},{136,11,493},{6,10,165},{138,10,388},{7,11,341},{139,11,219},{4,10,719 +},{135,10,155},{134,0,1935},{132,0,826},{6,0,331},{6,0,1605},{8,0,623},{11,0,139 +},{139,0,171},{135,11,1734},{10,11,115},{11,11,420},{12,11,154},{13,11,404},{14, +11,346},{15,11,54},{143,11,112},{7,0,288},{4,10,353},{6,10,146},{6,10,1789},{7, +10,990},{7,10,1348},{9,10,665},{9,10,898},{11,10,893},{142,10,212},{6,0,916},{ +134,0,1592},{7,0,1888},{4,10,45},{135,10,1257},{5,11,1011},{136,11,701},{139,11, +596},{4,11,54},{5,11,666},{7,11,1039},{7,11,1130},{9,11,195},{138,11,302},{134,0 +,1471},{134,0,1570},{132,0,394},{140,10,65},{136,10,816},{135,0,1931},{7,0,574}, +{135,0,1719},{134,11,467},{132,0,658},{9,0,781},{10,0,144},{11,0,385},{13,0,161} +,{13,0,228},{13,0,268},{20,0,107},{134,11,1669},{136,0,374},{135,0,735},{4,0,344 +},{6,0,498},{139,0,323},{7,0,586},{7,0,1063},{6,10,559},{134,10,1691},{137,0,155 +},{133,0,906},{7,11,122},{9,11,259},{10,11,84},{11,11,470},{12,11,541},{141,11, +379},{134,0,1139},{10,0,108},{139,0,116},{134,10,456},{133,10,925},{5,11,82},{5, +11,131},{7,11,1755},{8,11,31},{9,11,168},{9,11,764},{139,11,869},{134,11,605},{5 +,11,278},{137,11,68},{4,11,163},{5,11,201},{5,11,307},{5,11,310},{6,11,335},{7, +11,284},{136,11,165},{135,11,1660},{6,11,33},{135,11,1244},{4,0,616},{136,11,483 +},{8,0,857},{8,0,902},{8,0,910},{10,0,879},{12,0,726},{4,11,199},{139,11,34},{ +136,0,692},{6,10,193},{7,10,240},{7,10,1682},{10,10,51},{10,10,640},{11,10,410}, +{13,10,82},{14,10,247},{14,10,331},{142,10,377},{6,0,823},{134,0,983},{139,10, +411},{132,0,305},{136,10,633},{138,11,203},{134,0,681},{6,11,326},{7,11,677},{ +137,11,425},{5,0,214},{7,0,603},{8,0,611},{9,0,686},{10,0,88},{11,0,459},{11,0, +496},{12,0,463},{12,0,590},{141,0,0},{136,0,1004},{142,0,23},{134,0,1703},{147, +11,8},{145,11,56},{135,0,1443},{4,10,237},{135,10,514},{6,0,714},{145,0,19},{5, +11,358},{7,11,473},{7,11,1184},{10,11,662},{13,11,212},{13,11,304},{13,11,333},{ +145,11,98},{4,0,737},{10,0,98},{11,0,294},{12,0,60},{12,0,437},{13,0,64},{13,0, +380},{142,0,430},{6,10,392},{7,10,65},{135,10,2019},{6,0,1758},{8,0,520},{9,0, +345},{9,0,403},{142,0,350},{5,0,47},{10,0,242},{138,0,579},{5,0,139},{7,0,1168}, +{138,0,539},{134,0,1459},{13,0,388},{141,11,388},{134,0,253},{7,10,1260},{135,10 +,1790},{10,0,252},{9,10,222},{139,10,900},{140,0,745},{133,11,946},{4,0,107},{7, +0,613},{8,0,439},{8,0,504},{9,0,501},{10,0,383},{139,0,477},{135,11,1485},{132,0 +,871},{7,11,411},{7,11,590},{8,11,631},{9,11,323},{10,11,355},{11,11,491},{12,11 +,143},{12,11,402},{13,11,73},{14,11,408},{15,11,107},{146,11,71},{132,0,229},{ +132,0,903},{140,0,71},{133,0,549},{4,0,47},{6,0,373},{7,0,452},{7,0,543},{7,0, +1828},{7,0,1856},{9,0,6},{11,0,257},{139,0,391},{7,11,1467},{8,11,328},{10,11, +544},{11,11,955},{13,11,320},{145,11,83},{5,0,980},{134,0,1754},{136,0,865},{5,0 +,705},{137,0,606},{7,0,161},{8,10,201},{136,10,605},{143,11,35},{5,11,835},{6,11 +,483},{140,10,224},{7,0,536},{7,0,1331},{136,0,143},{134,0,1388},{5,0,724},{10,0 +,305},{11,0,151},{12,0,33},{12,0,121},{12,0,381},{17,0,3},{17,0,27},{17,0,78},{ +18,0,18},{19,0,54},{149,0,5},{4,10,523},{133,10,638},{5,0,19},{134,0,533},{5,0, +395},{5,0,951},{134,0,1776},{135,0,1908},{132,0,846},{10,0,74},{11,0,663},{12,0, +210},{13,0,166},{13,0,310},{14,0,373},{18,0,95},{19,0,43},{6,10,242},{7,10,227}, +{7,10,1581},{8,10,104},{9,10,113},{9,10,220},{9,10,427},{10,10,239},{11,10,579}, +{11,10,1023},{13,10,4},{13,10,204},{13,10,316},{148,10,86},{9,11,716},{11,11,108 +},{13,11,123},{14,11,252},{19,11,38},{21,11,3},{151,11,11},{8,0,372},{9,0,122},{ +138,0,175},{132,11,677},{7,11,1374},{136,11,540},{135,10,861},{132,0,695},{7,0, +497},{9,0,387},{147,0,81},{136,0,937},{134,0,718},{7,0,1328},{136,10,494},{132, +11,331},{6,0,1581},{133,11,747},{5,0,284},{6,0,49},{6,0,350},{7,0,1},{7,0,377},{ +7,0,1693},{8,0,18},{8,0,678},{9,0,161},{9,0,585},{9,0,671},{9,0,839},{11,0,912}, +{141,0,427},{7,10,1306},{8,10,505},{9,10,482},{10,10,126},{11,10,225},{12,10,347 +},{12,10,449},{13,10,19},{14,10,218},{142,10,435},{10,10,764},{12,10,120},{13,10 +,39},{145,10,127},{4,0,597},{133,10,268},{134,0,1094},{4,0,1008},{134,0,1973},{ +132,0,811},{139,0,908},{135,0,1471},{133,11,326},{4,10,384},{135,10,1022},{7,0, +1935},{8,0,324},{12,0,42},{4,11,691},{7,11,1935},{8,11,324},{9,11,35},{10,11,680 +},{11,11,364},{12,11,42},{13,11,357},{146,11,16},{135,0,2014},{7,0,2007},{9,0, +101},{9,0,450},{10,0,66},{10,0,842},{11,0,536},{12,0,587},{6,11,32},{7,11,385},{ +7,11,757},{7,11,1916},{8,11,37},{8,11,94},{8,11,711},{9,11,541},{10,11,162},{10, +11,795},{11,11,989},{11,11,1010},{12,11,14},{142,11,308},{139,0,586},{135,10, +1703},{7,0,1077},{11,0,28},{9,10,159},{140,10,603},{6,0,1221},{136,10,583},{6,11 +,152},{6,11,349},{6,11,1682},{7,11,1252},{8,11,112},{9,11,435},{9,11,668},{10,11 +,290},{10,11,319},{10,11,815},{11,11,180},{11,11,837},{12,11,240},{13,11,152},{ +13,11,219},{142,11,158},{139,0,62},{132,10,515},{8,10,632},{8,10,697},{137,10, +854},{134,0,1766},{132,11,581},{6,11,126},{7,11,573},{8,11,397},{142,11,44},{150 +,0,28},{11,0,670},{22,0,25},{4,10,136},{133,10,551},{6,0,1665},{7,0,256},{7,0, +1388},{138,0,499},{4,0,22},{5,0,10},{7,0,1576},{136,0,97},{134,10,1782},{5,0,481 +},{7,10,1287},{9,10,44},{10,10,552},{10,10,642},{11,10,839},{12,10,274},{12,10, +275},{12,10,372},{13,10,91},{142,10,125},{133,11,926},{7,11,1232},{137,11,531},{ +6,0,134},{7,0,437},{7,0,1824},{9,0,37},{14,0,285},{142,0,371},{7,0,486},{8,0,155 +},{11,0,93},{140,0,164},{6,0,1391},{134,0,1442},{133,11,670},{133,0,591},{6,10, +147},{7,10,886},{7,11,1957},{9,10,753},{138,10,268},{5,0,380},{5,0,650},{7,0, +1173},{136,0,310},{4,0,364},{7,0,1156},{7,0,1187},{137,0,409},{135,11,1621},{134 +,0,482},{133,11,506},{4,0,781},{6,0,487},{7,0,926},{8,0,263},{139,0,500},{138,10 +,137},{135,11,242},{139,11,96},{133,10,414},{135,10,1762},{134,0,804},{5,11,834} +,{7,11,1202},{8,11,14},{9,11,481},{137,11,880},{134,10,599},{4,0,94},{135,0,1265 +},{4,0,415},{132,0,417},{5,0,348},{6,0,522},{6,10,1749},{7,11,1526},{138,11,465} +,{134,10,1627},{132,0,1012},{132,10,488},{4,11,357},{6,11,172},{7,11,143},{137, +11,413},{4,10,83},{4,11,590},{146,11,76},{140,10,676},{7,11,287},{8,11,355},{9, +11,293},{137,11,743},{134,10,278},{6,0,1803},{18,0,165},{24,0,21},{5,11,169},{7, +11,333},{136,11,45},{12,10,97},{140,11,97},{4,0,408},{4,0,741},{135,0,500},{132, +11,198},{7,10,388},{7,10,644},{139,10,781},{4,11,24},{5,11,140},{5,11,185},{7,11 +,1500},{11,11,565},{139,11,838},{6,0,1321},{9,0,257},{7,10,229},{8,10,59},{9,10, +190},{10,10,378},{140,10,191},{4,11,334},{133,11,593},{135,11,1885},{134,0,1138} +,{4,0,249},{6,0,73},{135,0,177},{133,0,576},{142,0,231},{137,0,288},{132,10,660} +,{7,10,1035},{138,10,737},{135,0,1487},{6,0,989},{9,0,433},{7,10,690},{9,10,587} +,{140,10,521},{7,0,1264},{7,0,1678},{11,0,945},{12,0,341},{12,0,471},{140,0,569} +,{132,11,709},{133,11,897},{5,11,224},{13,11,174},{146,11,52},{135,11,1840},{134 +,10,1744},{12,0,87},{16,0,74},{4,10,733},{9,10,194},{10,10,92},{11,10,198},{12, +10,84},{141,10,128},{140,0,779},{135,0,538},{4,11,608},{133,11,497},{133,0,413}, +{7,11,1375},{7,11,1466},{138,11,331},{136,0,495},{6,11,540},{136,11,136},{7,0,54 +},{8,0,312},{10,0,191},{10,0,614},{140,0,567},{6,0,468},{7,0,567},{7,0,1478},{8, +0,530},{14,0,290},{133,11,999},{4,11,299},{7,10,306},{135,11,1004},{142,11,296}, +{134,0,1484},{133,10,979},{6,0,609},{9,0,815},{12,11,137},{14,11,9},{14,11,24},{ +142,11,64},{133,11,456},{6,0,484},{135,0,822},{133,10,178},{136,11,180},{132,11, +755},{137,0,900},{135,0,1335},{6,0,1724},{135,0,2022},{135,11,1139},{5,0,640},{ +132,10,390},{6,0,1831},{138,11,633},{135,11,566},{4,11,890},{5,11,805},{5,11,819 +},{5,11,961},{6,11,396},{6,11,1631},{6,11,1678},{7,11,1967},{7,11,2041},{9,11, +630},{11,11,8},{11,11,1019},{12,11,176},{13,11,225},{14,11,292},{149,11,24},{132 +,0,474},{134,0,1103},{135,0,1504},{134,0,1576},{6,0,961},{6,0,1034},{140,0,655}, +{11,11,514},{149,11,20},{5,0,305},{135,11,1815},{7,11,1505},{10,11,190},{10,11, +634},{11,11,792},{12,11,358},{140,11,447},{5,11,0},{6,11,536},{7,11,604},{13,11, +445},{145,11,126},{7,0,1236},{133,10,105},{4,0,480},{6,0,217},{6,0,302},{6,0, +1642},{7,0,130},{7,0,837},{7,0,1321},{7,0,1547},{7,0,1657},{8,0,429},{9,0,228},{ +13,0,289},{13,0,343},{19,0,101},{6,11,232},{6,11,412},{7,11,1074},{8,11,9},{8,11 +,157},{8,11,786},{9,11,196},{9,11,352},{9,11,457},{10,11,337},{11,11,232},{11,11 +,877},{12,11,480},{140,11,546},{5,10,438},{7,11,958},{9,10,694},{12,10,627},{13, +11,38},{141,10,210},{4,11,382},{136,11,579},{7,0,278},{10,0,739},{11,0,708},{141 +,0,348},{4,11,212},{135,11,1206},{135,11,1898},{6,0,708},{6,0,1344},{152,10,11}, +{137,11,768},{134,0,1840},{140,0,233},{8,10,25},{138,10,826},{6,0,2017},{133,11, +655},{6,0,1488},{139,11,290},{132,10,308},{134,0,1590},{134,0,1800},{134,0,1259} +,{16,0,28},{6,11,231},{7,11,95},{136,11,423},{133,11,300},{135,10,150},{136,10, +649},{7,11,1874},{137,11,641},{6,11,237},{7,11,611},{8,11,100},{9,11,416},{11,11 +,335},{12,11,173},{146,11,101},{137,0,45},{134,10,521},{17,0,36},{14,11,26},{146 +,11,150},{7,0,1442},{14,0,22},{5,10,339},{15,10,41},{15,10,166},{147,10,66},{8,0 +,378},{6,11,581},{135,11,1119},{134,0,1507},{147,11,117},{139,0,39},{134,0,1054} +,{6,0,363},{7,0,1955},{136,0,725},{134,0,2036},{133,11,199},{6,0,1871},{9,0,935} +,{9,0,961},{9,0,1004},{9,0,1016},{12,0,805},{12,0,852},{12,0,853},{12,0,869},{12 +,0,882},{12,0,896},{12,0,906},{12,0,917},{12,0,940},{15,0,170},{15,0,176},{15,0, +188},{15,0,201},{15,0,205},{15,0,212},{15,0,234},{15,0,244},{18,0,181},{18,0,193 +},{18,0,196},{18,0,201},{18,0,202},{18,0,210},{18,0,217},{18,0,235},{18,0,236},{ +18,0,237},{21,0,54},{21,0,55},{21,0,58},{21,0,59},{152,0,22},{134,10,1628},{137, +0,805},{5,0,813},{135,0,2046},{142,11,42},{5,0,712},{6,0,1240},{11,0,17},{13,0, +321},{144,0,67},{132,0,617},{135,10,829},{6,0,320},{7,0,781},{7,0,1921},{9,0,55} +,{10,0,186},{10,0,273},{10,0,664},{10,0,801},{11,0,996},{11,0,997},{13,0,157},{ +142,0,170},{136,0,271},{5,10,486},{135,10,1349},{18,11,91},{147,11,70},{10,0,445 +},{7,10,1635},{8,10,17},{138,10,295},{136,11,404},{7,0,103},{7,0,863},{11,0,184} +,{145,0,62},{138,10,558},{137,0,659},{6,11,312},{6,11,1715},{10,11,584},{11,11, +546},{11,11,692},{12,11,259},{12,11,295},{13,11,46},{141,11,154},{134,0,676},{ +132,11,588},{4,11,231},{5,11,61},{6,11,104},{7,11,729},{7,11,964},{7,11,1658},{ +140,11,414},{6,11,263},{138,11,757},{11,0,337},{142,0,303},{135,11,1363},{132,11 +,320},{140,0,506},{134,10,447},{5,0,77},{7,0,1455},{10,0,843},{147,0,73},{7,10, +577},{7,10,1432},{9,10,475},{9,10,505},{9,10,526},{9,10,609},{9,10,689},{9,10, +726},{9,10,735},{9,10,738},{10,10,556},{10,10,674},{10,10,684},{11,10,89},{11,10 +,202},{11,10,272},{11,10,380},{11,10,415},{11,10,505},{11,10,537},{11,10,550},{ +11,10,562},{11,10,640},{11,10,667},{11,10,688},{11,10,847},{11,10,927},{11,10, +930},{11,10,940},{12,10,144},{12,10,325},{12,10,329},{12,10,389},{12,10,403},{12 +,10,451},{12,10,515},{12,10,604},{12,10,616},{12,10,626},{13,10,66},{13,10,131}, +{13,10,167},{13,10,236},{13,10,368},{13,10,411},{13,10,434},{13,10,453},{13,10, +461},{13,10,474},{14,10,59},{14,10,60},{14,10,139},{14,10,152},{14,10,276},{14, +10,353},{14,10,402},{15,10,28},{15,10,81},{15,10,123},{15,10,152},{18,10,136},{ +148,10,88},{132,0,458},{135,0,1420},{6,0,109},{10,0,382},{4,11,405},{4,10,609},{ +7,10,756},{7,11,817},{9,10,544},{11,10,413},{14,11,58},{14,10,307},{16,10,25},{ +17,11,37},{146,11,124},{6,0,330},{7,0,1084},{11,0,142},{133,11,974},{4,10,930},{ +133,10,947},{5,10,939},{142,11,394},{16,0,91},{145,0,87},{5,11,235},{5,10,962},{ +7,11,1239},{11,11,131},{140,11,370},{11,0,492},{5,10,651},{8,10,170},{9,10,61},{ +9,10,63},{10,10,23},{10,10,37},{10,10,834},{11,10,4},{11,10,281},{11,10,503},{11 +,10,677},{12,10,96},{12,10,130},{12,10,244},{14,10,5},{14,10,40},{14,10,162},{14 +,10,202},{146,10,133},{4,10,406},{5,10,579},{12,10,492},{150,10,15},{9,11,137},{ +138,11,221},{134,0,1239},{11,0,211},{140,0,145},{7,11,390},{138,11,140},{135,11, +1418},{135,11,1144},{134,0,1049},{7,0,321},{6,10,17},{7,10,1001},{7,10,1982},{9, +10,886},{10,10,489},{10,10,800},{11,10,782},{12,10,320},{13,10,467},{14,10,145}, +{14,10,387},{143,10,119},{145,10,17},{5,11,407},{11,11,489},{19,11,37},{20,11,73 +},{150,11,38},{133,10,458},{135,0,1985},{7,10,1983},{8,10,0},{8,10,171},{9,10, +120},{9,10,732},{10,10,473},{11,10,656},{11,10,998},{18,10,0},{18,10,2},{147,10, +21},{5,11,325},{7,11,1483},{8,11,5},{8,11,227},{9,11,105},{10,11,585},{140,11, +614},{136,0,122},{132,0,234},{135,11,1196},{6,0,976},{6,0,1098},{134,0,1441},{7, +0,253},{136,0,549},{6,11,621},{13,11,504},{144,11,19},{132,10,519},{5,0,430},{5, +0,932},{6,0,131},{7,0,417},{9,0,522},{11,0,314},{141,0,390},{14,0,149},{14,0,399 +},{143,0,57},{5,10,907},{6,10,31},{6,11,218},{7,10,491},{7,10,530},{8,10,592},{ +11,10,53},{11,10,779},{12,10,167},{12,10,411},{14,10,14},{14,10,136},{15,10,72}, +{16,10,17},{144,10,72},{140,11,330},{7,11,454},{7,11,782},{136,11,768},{132,0, +507},{10,11,676},{140,11,462},{6,0,630},{9,0,811},{4,10,208},{5,10,106},{6,10, +531},{8,10,408},{9,10,188},{138,10,572},{4,0,343},{5,0,511},{134,10,1693},{134, +11,164},{132,0,448},{7,0,455},{138,0,591},{135,0,1381},{12,10,441},{150,11,50},{ +9,10,449},{10,10,192},{138,10,740},{6,0,575},{132,10,241},{134,0,1175},{134,0, +653},{134,0,1761},{134,0,1198},{132,10,259},{6,11,343},{7,11,195},{9,11,226},{10 +,11,197},{10,11,575},{11,11,502},{139,11,899},{7,0,1127},{7,0,1572},{10,0,297},{ +10,0,422},{11,0,764},{11,0,810},{12,0,264},{13,0,102},{13,0,300},{13,0,484},{14, +0,147},{14,0,229},{17,0,71},{18,0,118},{147,0,120},{135,11,666},{132,0,678},{4, +10,173},{5,10,312},{5,10,512},{135,10,1285},{7,10,1603},{7,10,1691},{9,10,464},{ +11,10,195},{12,10,279},{12,10,448},{14,10,11},{147,10,102},{16,0,99},{146,0,164} +,{7,11,1125},{9,11,143},{11,11,61},{14,11,405},{150,11,21},{137,11,260},{4,10, +452},{5,10,583},{5,10,817},{6,10,433},{7,10,593},{7,10,720},{7,10,1378},{8,10, +161},{9,10,284},{10,10,313},{139,10,886},{132,10,547},{136,10,722},{14,0,35},{ +142,0,191},{141,0,45},{138,0,121},{132,0,125},{134,0,1622},{133,11,959},{8,10, +420},{139,10,193},{132,0,721},{135,10,409},{136,0,145},{7,0,792},{8,0,147},{10,0 +,821},{11,0,970},{11,0,1021},{136,11,173},{134,11,266},{132,0,715},{7,0,1999},{ +138,10,308},{133,0,531},{5,0,168},{5,0,930},{8,0,74},{9,0,623},{12,0,500},{140,0 +,579},{144,0,65},{138,11,246},{6,0,220},{7,0,1101},{13,0,105},{142,11,314},{5,10 +,1002},{136,10,745},{134,0,960},{20,0,0},{148,11,0},{4,0,1005},{4,10,239},{6,10, +477},{7,10,1607},{11,10,68},{139,10,617},{6,0,19},{7,0,1413},{139,0,428},{149,10 +,13},{7,0,96},{8,0,401},{8,0,703},{9,0,896},{136,11,300},{134,0,1595},{145,0,116 +},{136,0,1021},{7,0,1961},{7,0,1965},{7,0,2030},{8,0,150},{8,0,702},{8,0,737},{8 +,0,750},{140,0,366},{11,11,75},{142,11,267},{132,10,367},{8,0,800},{9,0,148},{9, +0,872},{9,0,890},{11,0,309},{11,0,1001},{13,0,267},{13,0,323},{5,11,427},{5,11, +734},{7,11,478},{136,11,52},{7,11,239},{11,11,217},{142,11,165},{132,11,323},{ +140,11,419},{13,0,299},{142,0,75},{6,11,87},{6,11,1734},{7,11,20},{7,11,1056},{8 +,11,732},{9,11,406},{9,11,911},{138,11,694},{134,0,1383},{132,10,694},{133,11, +613},{137,0,779},{4,0,598},{140,10,687},{6,0,970},{135,0,424},{133,0,547},{7,11, +32},{7,11,984},{8,11,85},{8,11,709},{9,11,579},{9,11,847},{9,11,856},{10,11,799} +,{11,11,258},{11,11,1007},{12,11,331},{12,11,615},{13,11,188},{13,11,435},{14,11 +,8},{15,11,165},{16,11,27},{148,11,40},{6,0,1222},{134,0,1385},{132,0,876},{138, +11,151},{135,10,213},{4,11,167},{135,11,82},{133,0,133},{6,11,24},{7,11,74},{7, +11,678},{137,11,258},{5,11,62},{6,11,534},{7,11,684},{7,11,1043},{7,11,1072},{8, +11,280},{8,11,541},{8,11,686},{10,11,519},{11,11,252},{140,11,282},{136,0,187},{ +8,0,8},{10,0,0},{10,0,818},{139,0,988},{132,11,359},{11,0,429},{15,0,51},{135,10 +,1672},{136,0,685},{5,11,211},{7,11,88},{136,11,627},{134,0,472},{136,0,132},{6, +11,145},{141,11,336},{4,10,751},{11,10,390},{140,10,32},{6,0,938},{6,0,1060},{4, +11,263},{4,10,409},{133,10,78},{137,0,874},{8,0,774},{10,0,670},{12,0,51},{4,11, +916},{6,10,473},{7,10,1602},{10,10,698},{12,10,212},{13,10,307},{145,10,105},{ +146,0,92},{143,10,156},{132,0,830},{137,0,701},{4,11,599},{6,11,1634},{7,11,5},{ +7,11,55},{7,11,67},{7,11,97},{7,11,691},{7,11,979},{7,11,1697},{8,11,207},{8,11, +214},{8,11,231},{8,11,294},{8,11,336},{8,11,428},{8,11,451},{8,11,460},{8,11,471 +},{8,11,622},{8,11,626},{8,11,679},{8,11,759},{8,11,829},{9,11,11},{9,11,246},{9 +,11,484},{9,11,573},{9,11,706},{9,11,762},{9,11,798},{9,11,855},{9,11,870},{9,11 +,912},{10,11,303},{10,11,335},{10,11,424},{10,11,461},{10,11,543},{10,11,759},{ +10,11,814},{11,11,59},{11,11,199},{11,11,235},{11,11,475},{11,11,590},{11,11,929 +},{11,11,963},{12,11,114},{12,11,182},{12,11,226},{12,11,332},{12,11,439},{12,11 +,575},{12,11,598},{13,11,8},{13,11,125},{13,11,194},{13,11,287},{14,11,197},{14, +11,383},{15,11,53},{17,11,63},{19,11,46},{19,11,98},{19,11,106},{148,11,85},{4,0 +,127},{5,0,350},{6,0,356},{8,0,426},{9,0,572},{10,0,247},{139,0,312},{134,0,1215 +},{6,0,59},{9,0,603},{13,0,397},{7,11,1853},{138,11,437},{134,0,1762},{147,11, +126},{135,10,883},{13,0,293},{142,0,56},{133,10,617},{139,10,50},{5,11,187},{7, +10,1518},{139,10,694},{135,0,441},{6,0,111},{7,0,4},{8,0,163},{8,0,776},{138,0, +566},{132,0,806},{4,11,215},{9,11,38},{10,11,3},{11,11,23},{11,11,127},{139,11, +796},{14,0,233},{4,10,546},{135,10,2042},{135,0,1994},{134,0,1739},{135,11,1530} +,{136,0,393},{5,0,297},{7,0,1038},{14,0,359},{19,0,52},{148,0,47},{135,0,309},{4 +,10,313},{133,10,577},{8,10,184},{141,10,433},{135,10,935},{12,10,186},{12,10, +292},{14,10,100},{146,10,70},{136,0,363},{14,0,175},{11,10,402},{12,10,109},{12, +10,431},{13,10,179},{13,10,206},{14,10,217},{16,10,3},{148,10,53},{5,10,886},{6, +10,46},{6,10,1790},{7,10,14},{7,10,732},{7,10,1654},{8,10,95},{8,10,327},{8,10, +616},{9,10,892},{10,10,598},{10,10,769},{11,10,134},{11,10,747},{12,10,378},{142 +,10,97},{136,0,666},{135,0,1675},{6,0,655},{134,0,1600},{135,0,808},{133,10,1021 +},{4,11,28},{5,11,440},{7,11,248},{11,11,833},{140,11,344},{134,11,1654},{132,0, +280},{140,0,54},{4,0,421},{133,0,548},{132,10,153},{6,11,339},{135,11,923},{133, +11,853},{133,10,798},{132,10,587},{6,11,249},{7,11,1234},{139,11,573},{6,10,598} +,{7,10,42},{8,10,695},{10,10,212},{11,10,158},{14,10,196},{145,10,85},{7,0,249}, +{5,10,957},{133,10,1008},{4,10,129},{135,10,465},{6,0,254},{7,0,842},{7,0,1659}, +{9,0,109},{10,0,103},{7,10,908},{7,10,1201},{9,10,755},{11,10,906},{12,10,527},{ +146,10,7},{5,0,262},{136,10,450},{144,0,1},{10,11,201},{142,11,319},{7,11,49},{7 +,11,392},{8,11,20},{8,11,172},{8,11,690},{9,11,383},{9,11,845},{10,11,48},{11,11 +,293},{11,11,832},{11,11,920},{141,11,221},{5,11,858},{133,11,992},{134,0,805},{ +139,10,1003},{6,0,1630},{134,11,307},{7,11,1512},{135,11,1794},{6,11,268},{137, +11,62},{135,10,1868},{133,0,671},{4,0,989},{8,0,972},{136,0,998},{132,11,423},{ +132,0,889},{135,0,1382},{135,0,1910},{7,10,965},{7,10,1460},{135,10,1604},{4,0, +627},{5,0,775},{138,11,106},{134,11,348},{7,0,202},{11,0,362},{11,0,948},{140,0, +388},{138,11,771},{6,11,613},{136,11,223},{6,0,560},{7,0,451},{8,0,389},{12,0, +490},{13,0,16},{13,0,215},{13,0,351},{18,0,132},{147,0,125},{135,0,841},{136,0, +566},{136,0,938},{132,11,670},{5,0,912},{6,0,1695},{140,11,55},{9,11,40},{139,11 +,136},{7,0,1361},{7,10,982},{10,10,32},{143,10,56},{11,11,259},{140,11,270},{5,0 +,236},{6,0,572},{8,0,492},{11,0,618},{144,0,56},{8,11,572},{9,11,310},{9,11,682} +,{137,11,698},{134,0,1854},{5,0,190},{136,0,318},{133,10,435},{135,0,1376},{4,11 +,296},{6,11,352},{7,11,401},{7,11,1410},{7,11,1594},{7,11,1674},{8,11,63},{8,11, +660},{137,11,74},{7,0,349},{5,10,85},{6,10,419},{7,10,305},{7,10,361},{7,10,1337 +},{8,10,71},{140,10,519},{4,11,139},{4,11,388},{140,11,188},{6,0,1972},{6,0,2013 +},{8,0,951},{10,0,947},{10,0,974},{10,0,1018},{142,0,476},{140,10,688},{135,10, +740},{5,10,691},{7,10,345},{9,10,94},{140,10,169},{9,0,344},{5,10,183},{6,10,582 +},{10,10,679},{140,10,435},{135,10,511},{132,0,850},{8,11,441},{10,11,314},{143, +11,3},{7,10,1993},{136,10,684},{4,11,747},{6,11,290},{6,10,583},{7,11,649},{7,11 +,1479},{135,11,1583},{133,11,232},{133,10,704},{134,0,910},{4,10,179},{5,10,198} +,{133,10,697},{7,10,347},{7,10,971},{8,10,181},{138,10,711},{136,11,525},{14,0, +19},{14,0,28},{144,0,29},{7,0,85},{7,0,247},{8,0,585},{138,0,163},{4,0,487},{7, +11,472},{7,11,1801},{10,11,748},{141,11,458},{4,10,243},{5,10,203},{7,10,19},{7, +10,71},{7,10,113},{10,10,405},{11,10,357},{142,10,240},{7,10,1450},{139,10,99},{ +132,11,425},{138,0,145},{147,0,83},{6,10,492},{137,11,247},{4,0,1013},{134,0, +2033},{5,10,134},{6,10,408},{6,10,495},{135,10,1593},{135,0,1922},{134,11,1768}, +{4,0,124},{10,0,457},{11,0,121},{11,0,169},{11,0,870},{11,0,874},{12,0,214},{14, +0,187},{143,0,77},{5,0,557},{135,0,1457},{139,0,66},{5,11,943},{6,11,1779},{142, +10,4},{4,10,248},{4,10,665},{7,10,137},{137,10,349},{7,0,1193},{5,11,245},{6,11, +576},{7,11,582},{136,11,225},{144,0,82},{7,10,1270},{139,10,612},{5,0,454},{10,0 +,352},{138,11,352},{18,0,57},{5,10,371},{135,10,563},{135,0,1333},{6,0,107},{7,0 +,638},{7,0,1632},{9,0,396},{134,11,610},{5,0,370},{134,0,1756},{4,10,374},{7,10, +547},{7,10,1700},{7,10,1833},{139,10,858},{133,0,204},{6,0,1305},{9,10,311},{141 +,10,42},{5,0,970},{134,0,1706},{6,10,1647},{7,10,1552},{7,10,2010},{9,10,494},{ +137,10,509},{13,11,455},{15,11,99},{15,11,129},{144,11,68},{135,0,3},{4,0,35},{5 +,0,121},{5,0,483},{5,0,685},{6,0,489},{6,0,782},{6,0,1032},{7,0,1204},{136,0,394 +},{4,0,921},{133,0,1007},{8,11,360},{138,11,63},{135,0,1696},{134,0,1519},{132, +11,443},{135,11,944},{6,10,123},{7,10,214},{9,10,728},{10,10,157},{11,10,346},{ +11,10,662},{143,10,106},{137,0,981},{135,10,1435},{134,0,1072},{132,0,712},{134, +0,1629},{134,0,728},{4,11,298},{137,11,483},{6,0,1177},{6,0,1271},{5,11,164},{7, +11,121},{142,11,189},{7,0,1608},{4,10,707},{5,10,588},{6,10,393},{13,10,106},{18 +,10,49},{147,10,41},{23,0,16},{151,11,16},{6,10,211},{7,10,1690},{11,10,486},{ +140,10,369},{133,0,485},{19,11,15},{149,11,27},{4,11,172},{9,11,611},{10,11,436} +,{12,11,673},{141,11,255},{5,11,844},{10,11,484},{11,11,754},{12,11,457},{14,11, +171},{14,11,389},{146,11,153},{4,0,285},{5,0,27},{5,0,317},{6,0,301},{7,0,7},{8, +0,153},{10,0,766},{11,0,468},{12,0,467},{141,0,143},{134,0,1462},{9,11,263},{10, +11,147},{138,11,492},{133,11,537},{6,0,1945},{6,0,1986},{6,0,1991},{134,0,2038}, +{134,10,219},{137,11,842},{14,0,52},{17,0,50},{5,10,582},{6,10,1646},{7,10,99},{ +7,10,1962},{7,10,1986},{8,10,515},{8,10,773},{9,10,23},{9,10,491},{12,10,620},{ +142,10,93},{138,11,97},{20,0,21},{20,0,44},{133,10,851},{136,0,819},{139,0,917}, +{5,11,230},{5,11,392},{6,11,420},{8,10,762},{8,10,812},{9,11,568},{9,10,910},{ +140,11,612},{135,0,784},{15,0,135},{143,11,135},{10,0,454},{140,0,324},{4,11,0}, +{5,11,41},{7,11,1459},{7,11,1469},{7,11,1618},{7,11,1859},{9,11,549},{139,11,905 +},{4,10,98},{7,10,1365},{9,10,422},{9,10,670},{10,10,775},{11,10,210},{13,10,26} +,{13,10,457},{141,10,476},{6,0,1719},{6,0,1735},{7,0,2016},{7,0,2020},{8,0,837}, +{137,0,852},{133,11,696},{135,0,852},{132,0,952},{134,10,1730},{132,11,771},{138 +,0,568},{137,0,448},{139,0,146},{8,0,67},{138,0,419},{133,11,921},{137,10,147},{ +134,0,1826},{10,0,657},{14,0,297},{142,0,361},{6,0,666},{6,0,767},{134,0,1542},{ +139,0,729},{6,11,180},{7,11,1137},{8,11,751},{139,11,805},{4,11,183},{7,11,271}, +{11,11,824},{11,11,952},{13,11,278},{13,11,339},{13,11,482},{14,11,424},{148,11, +99},{4,0,669},{5,11,477},{5,11,596},{6,11,505},{7,11,1221},{11,11,907},{12,11, +209},{141,11,214},{135,11,1215},{5,0,402},{6,10,30},{11,10,56},{139,10,305},{7, +11,564},{142,11,168},{139,0,152},{7,0,912},{135,10,1614},{4,10,150},{5,10,303},{ +134,10,327},{7,0,320},{8,0,51},{9,0,868},{10,0,833},{12,0,481},{12,0,570},{148,0 +,106},{132,0,445},{7,11,274},{11,11,263},{11,11,479},{11,11,507},{140,11,277},{ +10,0,555},{11,0,308},{19,0,95},{6,11,1645},{8,10,192},{10,10,78},{141,10,359},{ +135,10,786},{6,11,92},{6,11,188},{7,11,1269},{7,11,1524},{7,11,1876},{10,11,228} +,{139,11,1020},{4,11,459},{133,11,966},{11,0,386},{6,10,1638},{7,10,79},{7,10, +496},{9,10,138},{10,10,336},{12,10,412},{12,10,440},{142,10,305},{133,0,239},{7, +0,83},{7,0,1990},{8,0,130},{139,0,720},{138,11,709},{4,0,143},{5,0,550},{133,0, +752},{5,0,123},{6,0,530},{7,0,348},{135,0,1419},{135,0,2024},{6,11,18},{7,11,179 +},{7,11,721},{7,11,932},{8,11,548},{8,11,757},{9,11,54},{9,11,65},{9,11,532},{9, +11,844},{10,11,113},{10,11,117},{10,11,236},{10,11,315},{10,11,430},{10,11,798}, +{11,11,153},{11,11,351},{11,11,375},{12,11,78},{12,11,151},{12,11,392},{14,11, +248},{143,11,23},{7,10,204},{7,10,415},{8,10,42},{10,10,85},{139,10,564},{134,0, +958},{133,11,965},{132,0,210},{135,11,1429},{138,11,480},{134,11,182},{139,11, +345},{10,11,65},{10,11,488},{138,11,497},{4,10,3},{5,10,247},{5,10,644},{7,10, +744},{7,10,1207},{7,10,1225},{7,10,1909},{146,10,147},{132,0,430},{5,10,285},{9, +10,67},{13,10,473},{143,10,82},{144,11,16},{7,11,1162},{9,11,588},{10,11,260},{ +151,10,8},{133,0,213},{138,0,7},{135,0,801},{134,11,1786},{135,11,308},{6,0,936} +,{134,0,1289},{133,0,108},{132,0,885},{133,0,219},{139,0,587},{4,0,193},{5,0,916 +},{6,0,1041},{7,0,364},{10,0,398},{10,0,726},{11,0,317},{11,0,626},{12,0,142},{ +12,0,288},{12,0,678},{13,0,313},{15,0,113},{146,0,114},{135,0,1165},{6,0,241},{9 +,0,342},{10,0,729},{11,0,284},{11,0,445},{11,0,651},{11,0,863},{13,0,398},{146,0 +,99},{7,0,907},{136,0,832},{9,0,303},{4,10,29},{6,10,532},{7,10,1628},{7,10,1648 +},{9,10,350},{10,10,433},{11,10,97},{11,10,557},{11,10,745},{12,10,289},{12,10, +335},{12,10,348},{12,10,606},{13,10,116},{13,10,233},{13,10,466},{14,10,181},{14 +,10,209},{14,10,232},{14,10,236},{14,10,300},{16,10,41},{148,10,97},{7,11,423},{ +7,10,1692},{136,11,588},{6,0,931},{134,0,1454},{5,10,501},{7,10,1704},{9,10,553} +,{11,10,520},{12,10,557},{141,10,249},{136,11,287},{4,0,562},{9,0,254},{139,0, +879},{132,0,786},{14,11,32},{18,11,85},{20,11,2},{152,11,16},{135,0,1294},{7,11, +723},{135,11,1135},{6,0,216},{7,0,901},{7,0,1343},{8,0,493},{134,11,403},{7,11, +719},{8,11,809},{136,11,834},{5,11,210},{6,11,213},{7,11,60},{10,11,364},{139,11 +,135},{7,0,341},{11,0,219},{5,11,607},{8,11,326},{136,11,490},{4,11,701},{5,11, +472},{5,11,639},{7,11,1249},{9,11,758},{139,11,896},{135,11,380},{135,11,1947},{ +139,0,130},{135,0,1734},{10,0,115},{11,0,420},{12,0,154},{13,0,404},{14,0,346},{ +143,0,54},{134,10,129},{4,11,386},{7,11,41},{8,11,405},{9,11,497},{11,11,110},{ +11,11,360},{15,11,37},{144,11,84},{141,11,282},{5,11,46},{7,11,1452},{7,11,1480} +,{8,11,634},{140,11,472},{4,11,524},{136,11,810},{10,11,238},{141,11,33},{133,0, +604},{5,0,1011},{136,0,701},{8,0,856},{8,0,858},{8,0,879},{12,0,702},{142,0,447} +,{4,0,54},{5,0,666},{7,0,1039},{7,0,1130},{9,0,195},{138,0,302},{4,10,25},{5,10, +60},{6,10,504},{7,10,614},{7,10,1155},{140,10,0},{7,10,1248},{11,10,621},{139,10 +,702},{133,11,997},{137,10,321},{134,0,1669},{134,0,1791},{4,10,379},{135,10, +1397},{138,11,372},{5,11,782},{5,11,829},{134,11,1738},{135,0,1228},{4,10,118},{ +6,10,274},{6,10,361},{7,10,75},{141,10,441},{132,0,623},{9,11,279},{10,11,407},{ +14,11,84},{150,11,18},{137,10,841},{135,0,798},{140,10,693},{5,10,314},{6,10,221 +},{7,10,419},{10,10,650},{11,10,396},{12,10,156},{13,10,369},{14,10,333},{145,10 +,47},{135,11,1372},{7,0,122},{9,0,259},{10,0,84},{11,0,470},{12,0,541},{141,0, +379},{134,0,837},{8,0,1013},{4,11,78},{5,11,96},{5,11,182},{7,11,1724},{7,11, +1825},{10,11,394},{10,11,471},{11,11,532},{14,11,340},{145,11,88},{134,0,577},{ +135,11,1964},{132,10,913},{134,0,460},{8,0,891},{10,0,901},{10,0,919},{10,0,932} +,{12,0,715},{12,0,728},{12,0,777},{14,0,457},{144,0,103},{5,0,82},{5,0,131},{7,0 +,1755},{8,0,31},{9,0,168},{9,0,764},{139,0,869},{136,10,475},{6,0,605},{5,10, +1016},{9,11,601},{9,11,619},{10,11,505},{10,11,732},{11,11,355},{140,11,139},{7, +10,602},{8,10,179},{10,10,781},{140,10,126},{134,0,1246},{6,10,329},{138,10,111} +,{6,11,215},{7,11,1028},{7,11,1473},{7,11,1721},{9,11,424},{138,11,779},{5,0,278 +},{137,0,68},{6,0,932},{6,0,1084},{144,0,86},{4,0,163},{5,0,201},{5,0,307},{5,0, +310},{6,0,335},{7,0,284},{7,0,1660},{136,0,165},{136,0,781},{134,0,707},{6,0,33} +,{135,0,1244},{5,10,821},{6,11,67},{6,10,1687},{7,11,258},{7,11,1630},{9,11,354} +,{9,11,675},{10,11,830},{14,11,80},{145,11,80},{6,11,141},{7,11,225},{9,11,59},{ +9,11,607},{10,11,312},{11,11,687},{12,11,555},{13,11,373},{13,11,494},{148,11,58 +},{134,0,1113},{9,0,388},{5,10,71},{7,10,1407},{9,10,704},{10,10,261},{10,10,619 +},{11,10,547},{11,10,619},{143,10,157},{7,0,1953},{136,0,720},{138,0,203},{7,10, +2008},{9,10,337},{138,10,517},{6,0,326},{7,0,677},{137,0,425},{139,11,81},{7,0, +1316},{7,0,1412},{7,0,1839},{9,0,589},{11,0,241},{11,0,676},{11,0,811},{11,0,891 +},{12,0,140},{12,0,346},{12,0,479},{13,0,140},{13,0,381},{14,0,188},{18,0,30},{ +148,0,108},{5,0,416},{6,10,86},{6,10,603},{7,10,292},{7,10,561},{8,10,257},{8,10 +,382},{9,10,721},{9,10,778},{11,10,581},{140,10,466},{4,10,486},{133,10,491},{ +134,0,1300},{132,10,72},{7,0,847},{6,10,265},{7,11,430},{139,11,46},{5,11,602},{ +6,11,106},{7,11,1786},{7,11,1821},{7,11,2018},{9,11,418},{137,11,763},{5,0,358}, +{7,0,535},{7,0,1184},{10,0,662},{13,0,212},{13,0,304},{13,0,333},{145,0,98},{5, +11,65},{6,11,416},{7,11,1720},{7,11,1924},{8,11,677},{10,11,109},{11,11,14},{11, +11,70},{11,11,569},{11,11,735},{15,11,153},{148,11,80},{6,0,1823},{8,0,839},{8,0 +,852},{8,0,903},{10,0,940},{12,0,707},{140,0,775},{135,11,1229},{6,0,1522},{140, +0,654},{136,11,595},{139,0,163},{141,0,314},{132,0,978},{4,0,601},{6,0,2035},{ +137,10,234},{5,10,815},{6,10,1688},{134,10,1755},{133,0,946},{136,0,434},{6,10, +197},{136,10,205},{7,0,411},{7,0,590},{8,0,631},{9,0,323},{10,0,355},{11,0,491}, +{12,0,143},{12,0,402},{13,0,73},{14,0,408},{15,0,107},{146,0,71},{7,0,1467},{8,0 +,328},{10,0,544},{11,0,955},{12,0,13},{13,0,320},{145,0,83},{142,0,410},{11,0, +511},{13,0,394},{14,0,298},{14,0,318},{146,0,103},{6,10,452},{7,10,312},{138,10, +219},{138,10,589},{4,10,333},{9,10,176},{12,10,353},{141,10,187},{135,11,329},{ +132,11,469},{5,0,835},{134,0,483},{134,11,1743},{5,11,929},{6,11,340},{8,11,376} +,{136,11,807},{134,10,1685},{132,0,677},{5,11,218},{7,11,1610},{138,11,83},{5,11 +,571},{135,11,1842},{132,11,455},{137,0,70},{135,0,1405},{7,10,135},{8,10,7},{8, +10,62},{9,10,243},{10,10,658},{10,10,697},{11,10,456},{139,10,756},{9,10,395},{ +138,10,79},{137,0,108},{6,11,161},{7,11,372},{137,11,597},{132,11,349},{132,0, +777},{132,0,331},{135,10,631},{133,0,747},{6,11,432},{6,11,608},{139,11,322},{ +138,10,835},{5,11,468},{7,11,1809},{10,11,325},{11,11,856},{12,11,345},{143,11, +104},{133,11,223},{7,10,406},{7,10,459},{8,10,606},{139,10,726},{132,11,566},{ +142,0,68},{4,11,59},{135,11,1394},{6,11,436},{139,11,481},{4,11,48},{5,11,271},{ +135,11,953},{139,11,170},{5,11,610},{136,11,457},{133,11,755},{135,11,1217},{133 +,10,612},{132,11,197},{132,0,505},{4,10,372},{7,10,482},{8,10,158},{9,10,602},{9 +,10,615},{10,10,245},{10,10,678},{10,10,744},{11,10,248},{139,10,806},{133,0,326 +},{5,10,854},{135,10,1991},{4,0,691},{146,0,16},{6,0,628},{9,0,35},{10,0,680},{ +10,0,793},{11,0,364},{13,0,357},{143,0,164},{138,0,654},{6,0,32},{7,0,385},{7,0, +757},{7,0,1916},{8,0,37},{8,0,94},{8,0,711},{9,0,541},{10,0,162},{10,0,795},{11, +0,989},{11,0,1010},{12,0,14},{142,0,308},{133,11,217},{6,0,152},{6,0,349},{6,0, +1682},{7,0,1252},{8,0,112},{9,0,435},{9,0,668},{10,0,290},{10,0,319},{10,0,815}, +{11,0,180},{11,0,837},{12,0,240},{13,0,152},{13,0,219},{142,0,158},{4,0,581},{ +134,0,726},{5,10,195},{135,10,1685},{6,0,126},{7,0,573},{8,0,397},{142,0,44},{ +138,0,89},{7,10,1997},{8,10,730},{139,10,1006},{134,0,1531},{134,0,1167},{5,0, +926},{12,0,203},{133,10,751},{4,11,165},{7,11,1398},{135,11,1829},{7,0,1232},{ +137,0,531},{135,10,821},{134,0,943},{133,0,670},{4,0,880},{139,0,231},{134,0, +1617},{135,0,1957},{5,11,9},{7,11,297},{7,11,966},{140,11,306},{6,0,975},{134,0, +985},{5,10,950},{5,10,994},{134,10,351},{12,11,21},{151,11,7},{5,11,146},{6,11, +411},{138,11,721},{7,0,242},{135,0,1942},{6,11,177},{135,11,467},{5,0,421},{7,10 +,47},{137,10,684},{5,0,834},{7,0,1202},{8,0,14},{9,0,481},{137,0,880},{138,0,465 +},{6,0,688},{9,0,834},{132,10,350},{132,0,855},{4,0,357},{6,0,172},{7,0,143},{ +137,0,413},{133,11,200},{132,0,590},{7,10,1812},{13,10,259},{13,10,356},{14,10, +242},{147,10,114},{133,10,967},{11,0,114},{4,10,473},{7,10,623},{8,10,808},{9,10 +,871},{9,10,893},{11,10,431},{12,10,112},{12,10,217},{12,10,243},{12,10,562},{12 +,10,663},{12,10,683},{13,10,141},{13,10,197},{13,10,227},{13,10,406},{13,10,487} +,{14,10,156},{14,10,203},{14,10,224},{14,10,256},{18,10,58},{150,10,0},{138,10, +286},{4,10,222},{7,10,286},{136,10,629},{5,0,169},{7,0,333},{136,0,45},{134,11, +481},{132,0,198},{4,0,24},{5,0,140},{5,0,185},{7,0,1500},{11,0,565},{11,0,838},{ +4,11,84},{7,11,1482},{10,11,76},{138,11,142},{133,0,585},{141,10,306},{133,11, +1015},{4,11,315},{5,11,507},{135,11,1370},{136,10,146},{6,0,691},{134,0,1503},{4 +,0,334},{133,0,593},{4,10,465},{135,10,1663},{142,11,173},{135,0,913},{12,0,116} +,{134,11,1722},{134,0,1360},{132,0,802},{8,11,222},{8,11,476},{9,11,238},{11,11, +516},{11,11,575},{15,11,109},{146,11,100},{6,0,308},{9,0,673},{7,10,138},{7,10, +517},{139,10,238},{132,0,709},{6,0,1876},{6,0,1895},{9,0,994},{9,0,1006},{12,0, +829},{12,0,888},{12,0,891},{146,0,185},{148,10,94},{4,0,228},{133,0,897},{7,0, +1840},{5,10,495},{7,10,834},{9,10,733},{139,10,378},{133,10,559},{6,10,21},{6,10 +,1737},{7,10,1444},{136,10,224},{4,0,608},{133,0,497},{6,11,40},{135,11,1781},{ +134,0,1573},{135,0,2039},{6,0,540},{136,0,136},{4,0,897},{5,0,786},{133,10,519}, +{6,0,1878},{6,0,1884},{9,0,938},{9,0,948},{9,0,955},{9,0,973},{9,0,1012},{12,0, +895},{12,0,927},{143,0,254},{134,0,1469},{133,0,999},{4,0,299},{135,0,1004},{4,0 +,745},{133,0,578},{136,11,574},{133,0,456},{134,0,1457},{7,0,1679},{132,10,402}, +{7,0,693},{8,0,180},{12,0,163},{8,10,323},{136,10,479},{11,10,580},{142,10,201}, +{5,10,59},{135,10,672},{132,11,354},{146,10,34},{4,0,755},{135,11,1558},{7,0, +1740},{146,0,48},{4,10,85},{135,10,549},{139,0,338},{133,10,94},{134,0,1091},{ +135,11,469},{12,0,695},{12,0,704},{20,0,113},{5,11,830},{14,11,338},{148,11,81}, +{135,0,1464},{6,10,11},{135,10,187},{135,0,975},{13,0,335},{132,10,522},{134,0, +1979},{5,11,496},{135,11,203},{4,10,52},{135,10,661},{7,0,1566},{8,0,269},{9,0, +212},{9,0,718},{14,0,15},{14,0,132},{142,0,227},{4,0,890},{5,0,805},{5,0,819},{5 +,0,961},{6,0,396},{6,0,1631},{6,0,1678},{7,0,1967},{7,0,2041},{9,0,630},{11,0,8} +,{11,0,1019},{12,0,176},{13,0,225},{14,0,292},{21,0,24},{4,10,383},{133,10,520}, +{134,11,547},{135,11,1748},{5,11,88},{137,11,239},{146,11,128},{7,11,650},{135, +11,1310},{4,10,281},{5,10,38},{7,10,194},{7,10,668},{7,10,1893},{137,10,397},{ +135,0,1815},{9,10,635},{139,10,559},{7,0,1505},{10,0,190},{10,0,634},{11,0,792}, +{12,0,358},{140,0,447},{5,0,0},{6,0,536},{7,0,604},{13,0,445},{145,0,126},{7,11, +1076},{9,11,80},{11,11,78},{11,11,421},{11,11,534},{140,11,545},{8,0,966},{10,0, +1023},{14,11,369},{146,11,72},{135,11,1641},{6,0,232},{6,0,412},{7,0,1074},{8,0, +9},{8,0,157},{8,0,786},{9,0,196},{9,0,352},{9,0,457},{10,0,337},{11,0,232},{11,0 +,877},{12,0,480},{140,0,546},{135,0,958},{4,0,382},{136,0,579},{4,0,212},{135,0, +1206},{4,11,497},{5,11,657},{135,11,1584},{132,0,681},{8,0,971},{138,0,965},{5, +10,448},{136,10,535},{14,0,16},{146,0,44},{11,0,584},{11,0,616},{14,0,275},{11, +11,584},{11,11,616},{142,11,275},{136,11,13},{7,10,610},{135,10,1501},{7,11,642} +,{8,11,250},{11,11,123},{11,11,137},{13,11,48},{142,11,95},{133,0,655},{17,0,67} +,{147,0,74},{134,0,751},{134,0,1967},{6,0,231},{136,0,423},{5,0,300},{138,0,1016 +},{4,10,319},{5,10,699},{138,10,673},{6,0,237},{7,0,611},{8,0,100},{9,0,416},{11 +,0,335},{12,0,173},{18,0,101},{6,10,336},{8,10,552},{9,10,285},{10,10,99},{139, +10,568},{134,0,1370},{7,10,1406},{9,10,218},{141,10,222},{133,10,256},{135,0, +1208},{14,11,213},{148,11,38},{6,0,1219},{135,11,1642},{13,0,417},{14,0,129},{ +143,0,15},{10,11,545},{140,11,301},{17,10,39},{148,10,36},{133,0,199},{4,11,904} +,{133,11,794},{12,0,427},{146,0,38},{134,0,949},{8,0,665},{135,10,634},{132,10, +618},{135,10,259},{132,10,339},{133,11,761},{141,10,169},{132,10,759},{5,0,688}, +{7,0,539},{135,0,712},{7,11,386},{138,11,713},{134,0,1186},{6,11,7},{6,11,35},{7 +,11,147},{7,11,1069},{7,11,1568},{7,11,1575},{7,11,1917},{8,11,43},{8,11,208},{9 +,11,128},{9,11,866},{10,11,20},{11,11,981},{147,11,33},{7,11,893},{8,10,482},{ +141,11,424},{6,0,312},{6,0,1715},{10,0,584},{11,0,546},{11,0,692},{12,0,259},{12 +,0,295},{13,0,46},{141,0,154},{5,10,336},{6,10,341},{6,10,478},{6,10,1763},{136, +10,386},{137,0,151},{132,0,588},{152,0,4},{6,11,322},{9,11,552},{11,11,274},{13, +11,209},{13,11,499},{14,11,85},{15,11,126},{145,11,70},{135,10,73},{4,0,231},{5, +0,61},{6,0,104},{7,0,729},{7,0,964},{7,0,1658},{140,0,414},{6,0,263},{138,0,757} +,{135,10,1971},{4,0,612},{133,0,561},{132,0,320},{135,10,1344},{8,11,83},{8,11, +817},{9,11,28},{9,11,29},{9,11,885},{10,11,387},{11,11,633},{11,11,740},{13,11, +235},{13,11,254},{15,11,143},{143,11,146},{5,10,396},{134,10,501},{140,11,49},{ +132,0,225},{4,10,929},{5,10,799},{8,10,46},{136,10,740},{4,0,405},{7,0,817},{14, +0,58},{17,0,37},{146,0,124},{133,0,974},{4,11,412},{133,11,581},{4,10,892},{133, +10,770},{4,0,996},{134,0,2026},{4,0,527},{5,0,235},{7,0,1239},{11,0,131},{140,0, +370},{9,0,16},{13,0,386},{135,11,421},{7,0,956},{7,0,1157},{7,0,1506},{7,0,1606} +,{7,0,1615},{7,0,1619},{7,0,1736},{7,0,1775},{8,0,590},{9,0,324},{9,0,736},{9,0, +774},{9,0,776},{9,0,784},{10,0,567},{10,0,708},{11,0,518},{11,0,613},{11,0,695}, +{11,0,716},{11,0,739},{11,0,770},{11,0,771},{11,0,848},{11,0,857},{11,0,931},{11 +,0,947},{12,0,326},{12,0,387},{12,0,484},{12,0,528},{12,0,552},{12,0,613},{13,0, +189},{13,0,256},{13,0,340},{13,0,432},{13,0,436},{13,0,440},{13,0,454},{14,0,174 +},{14,0,220},{14,0,284},{14,0,390},{145,0,121},{135,10,158},{9,0,137},{138,0,221 +},{4,11,110},{10,11,415},{10,11,597},{142,11,206},{141,11,496},{135,11,205},{151 +,10,25},{135,11,778},{7,11,1656},{7,10,2001},{9,11,369},{10,11,338},{10,11,490}, +{11,11,154},{11,11,545},{11,11,775},{13,11,77},{141,11,274},{4,11,444},{10,11, +146},{140,11,9},{7,0,390},{138,0,140},{135,0,1144},{134,0,464},{7,10,1461},{140, +10,91},{132,10,602},{4,11,283},{135,11,1194},{5,0,407},{11,0,204},{11,0,243},{11 +,0,489},{12,0,293},{19,0,37},{20,0,73},{150,0,38},{7,0,1218},{136,0,303},{5,0, +325},{8,0,5},{8,0,227},{9,0,105},{10,0,585},{12,0,614},{4,10,13},{5,10,567},{7, +10,1498},{9,10,124},{11,10,521},{140,10,405},{135,10,1006},{7,0,800},{10,0,12},{ +134,11,1720},{135,0,1783},{132,10,735},{138,10,812},{4,10,170},{135,10,323},{6,0 +,621},{13,0,504},{144,0,89},{5,10,304},{135,10,1403},{137,11,216},{6,0,920},{6,0 +,1104},{9,11,183},{139,11,286},{4,0,376},{133,10,742},{134,0,218},{8,0,641},{11, +0,388},{140,0,580},{7,0,454},{7,0,782},{8,0,768},{140,0,686},{137,11,33},{133,10 +,111},{144,0,0},{10,0,676},{140,0,462},{6,0,164},{136,11,735},{133,10,444},{150, +0,50},{7,11,1862},{12,11,491},{12,11,520},{13,11,383},{14,11,244},{146,11,12},{5 +,11,132},{9,11,486},{9,11,715},{10,11,458},{11,11,373},{11,11,668},{11,11,795},{ +11,11,897},{12,11,272},{12,11,424},{12,11,539},{12,11,558},{14,11,245},{14,11, +263},{14,11,264},{14,11,393},{142,11,403},{8,10,123},{15,10,6},{144,10,7},{6,0, +285},{8,0,654},{11,0,749},{12,0,190},{12,0,327},{13,0,120},{13,0,121},{13,0,327} +,{15,0,47},{146,0,40},{5,11,8},{6,11,89},{6,11,400},{7,11,1569},{7,11,1623},{7, +11,1850},{8,11,218},{8,11,422},{9,11,570},{138,11,626},{6,11,387},{7,11,882},{ +141,11,111},{6,0,343},{7,0,195},{9,0,226},{10,0,197},{10,0,575},{11,0,502},{11,0 +,899},{6,11,224},{7,11,877},{137,11,647},{5,10,937},{135,10,100},{135,11,790},{ +150,0,29},{147,0,8},{134,0,1812},{149,0,8},{135,11,394},{7,0,1125},{9,0,143},{11 +,0,61},{14,0,405},{150,0,21},{10,11,755},{147,11,29},{9,11,378},{141,11,162},{ +135,10,922},{5,10,619},{133,10,698},{134,0,1327},{6,0,1598},{137,0,575},{9,11, +569},{12,11,12},{12,11,81},{12,11,319},{13,11,69},{14,11,259},{16,11,87},{17,11, +1},{17,11,21},{17,11,24},{18,11,15},{18,11,56},{18,11,59},{18,11,127},{18,11,154 +},{19,11,19},{148,11,31},{6,0,895},{135,11,1231},{5,0,959},{7,11,124},{136,11,38 +},{5,11,261},{7,11,78},{7,11,199},{8,11,815},{9,11,126},{138,11,342},{5,10,917}, +{134,10,1659},{7,0,1759},{5,11,595},{135,11,1863},{136,0,173},{134,0,266},{142,0 +,261},{132,11,628},{5,10,251},{5,10,956},{8,10,268},{9,10,214},{146,10,142},{7, +11,266},{136,11,804},{135,11,208},{6,11,79},{7,11,1021},{135,11,1519},{11,11,704 +},{141,11,396},{5,10,346},{5,10,711},{136,10,390},{136,11,741},{134,11,376},{134 +,0,1427},{6,0,1033},{6,0,1217},{136,0,300},{133,10,624},{6,11,100},{7,11,244},{7 +,11,632},{7,11,1609},{8,11,178},{8,11,638},{141,11,58},{6,0,584},{5,10,783},{7, +10,1998},{135,10,2047},{5,0,427},{5,0,734},{7,0,478},{136,0,52},{7,0,239},{11,0, +217},{142,0,165},{134,0,1129},{6,0,168},{6,0,1734},{7,0,20},{7,0,1056},{8,0,732} +,{9,0,406},{9,0,911},{138,0,694},{132,10,594},{133,11,791},{7,11,686},{8,11,33}, +{8,11,238},{10,11,616},{11,11,467},{11,11,881},{13,11,217},{13,11,253},{142,11, +268},{137,11,476},{134,0,418},{133,0,613},{132,0,632},{132,11,447},{7,0,32},{7,0 +,984},{8,0,85},{8,0,709},{9,0,579},{9,0,847},{9,0,856},{10,0,799},{11,0,258},{11 +,0,1007},{12,0,331},{12,0,615},{13,0,188},{13,0,435},{14,0,8},{15,0,165},{16,0, +27},{20,0,40},{144,11,35},{4,11,128},{5,11,415},{6,11,462},{7,11,294},{7,11,578} +,{10,11,710},{139,11,86},{5,0,694},{136,0,909},{7,0,1109},{11,0,7},{5,10,37},{6, +10,39},{6,10,451},{7,10,218},{7,10,1166},{7,10,1687},{8,10,662},{144,10,2},{136, +11,587},{6,11,427},{7,11,1018},{138,11,692},{4,11,195},{6,10,508},{135,11,802},{ +4,0,167},{135,0,82},{5,0,62},{6,0,24},{6,0,534},{7,0,74},{7,0,678},{7,0,684},{7, +0,1043},{7,0,1072},{8,0,280},{8,0,541},{8,0,686},{9,0,258},{10,0,519},{11,0,252} +,{140,0,282},{138,0,33},{4,0,359},{133,11,738},{7,0,980},{9,0,328},{13,0,186},{ +13,0,364},{7,10,635},{7,10,796},{8,10,331},{9,10,330},{9,10,865},{10,10,119},{10 +,10,235},{11,10,111},{11,10,129},{11,10,240},{12,10,31},{12,10,66},{12,10,222},{ +12,10,269},{12,10,599},{12,10,684},{12,10,689},{12,10,691},{142,10,345},{137,10, +527},{6,0,596},{7,0,585},{135,10,702},{134,11,1683},{133,0,211},{6,0,145},{141,0 +,336},{134,0,1130},{7,0,873},{6,10,37},{7,10,1666},{8,10,195},{8,10,316},{9,10, +178},{9,10,276},{9,10,339},{9,10,536},{10,10,102},{10,10,362},{10,10,785},{11,10 +,55},{11,10,149},{11,10,773},{13,10,416},{13,10,419},{14,10,38},{14,10,41},{142, +10,210},{8,0,840},{136,0,841},{132,0,263},{5,11,3},{8,11,578},{9,11,118},{10,11, +705},{12,11,383},{141,11,279},{132,0,916},{133,11,229},{133,10,645},{15,0,155},{ +16,0,79},{8,11,102},{10,11,578},{10,11,672},{12,11,496},{13,11,408},{14,11,121}, +{145,11,106},{4,0,599},{5,0,592},{6,0,1634},{7,0,5},{7,0,55},{7,0,67},{7,0,97},{ +7,0,691},{7,0,979},{7,0,1600},{7,0,1697},{8,0,207},{8,0,214},{8,0,231},{8,0,294} +,{8,0,336},{8,0,428},{8,0,471},{8,0,622},{8,0,626},{8,0,679},{8,0,759},{8,0,829} +,{9,0,11},{9,0,246},{9,0,484},{9,0,573},{9,0,706},{9,0,762},{9,0,798},{9,0,855}, +{9,0,870},{9,0,912},{10,0,303},{10,0,335},{10,0,424},{10,0,461},{10,0,543},{10,0 +,759},{10,0,814},{11,0,59},{11,0,199},{11,0,235},{11,0,590},{11,0,631},{11,0,929 +},{11,0,963},{11,0,987},{12,0,114},{12,0,182},{12,0,226},{12,0,332},{12,0,439},{ +12,0,575},{12,0,598},{12,0,675},{13,0,8},{13,0,125},{13,0,194},{13,0,287},{14,0, +197},{14,0,383},{15,0,53},{17,0,63},{19,0,46},{19,0,98},{19,0,106},{148,0,85},{7 +,0,1356},{132,10,290},{6,10,70},{7,10,1292},{10,10,762},{139,10,288},{150,11,55} +,{4,0,593},{8,11,115},{8,11,350},{9,11,489},{10,11,128},{11,11,306},{12,11,373}, +{14,11,30},{17,11,79},{147,11,80},{135,11,1235},{134,0,1392},{4,11,230},{133,11, +702},{147,0,126},{7,10,131},{7,10,422},{8,10,210},{140,10,573},{134,0,1179},{139 +,11,435},{139,10,797},{134,11,1728},{4,0,162},{18,11,26},{19,11,42},{20,11,43},{ +21,11,0},{23,11,27},{152,11,14},{132,10,936},{6,0,765},{5,10,453},{134,10,441},{ +133,0,187},{135,0,1286},{6,0,635},{6,0,904},{6,0,1210},{134,0,1489},{4,0,215},{8 +,0,890},{9,0,38},{10,0,923},{11,0,23},{11,0,127},{139,0,796},{6,0,1165},{134,0, +1306},{7,0,716},{13,0,97},{141,0,251},{132,10,653},{136,0,657},{146,10,80},{5,11 +,622},{7,11,1032},{11,11,26},{11,11,213},{11,11,707},{12,11,380},{13,11,226},{ +141,11,355},{6,0,299},{5,11,70},{6,11,334},{9,11,171},{11,11,637},{12,11,202},{ +14,11,222},{145,11,42},{142,0,134},{4,11,23},{5,11,313},{5,11,1014},{6,11,50},{6 +,11,51},{7,11,142},{7,11,384},{9,11,783},{139,11,741},{4,11,141},{7,11,559},{8, +11,640},{9,11,460},{12,11,183},{141,11,488},{136,11,614},{7,10,1368},{8,10,232}, +{8,10,361},{10,10,682},{138,10,742},{137,10,534},{6,0,1082},{140,0,658},{137,10, +27},{135,0,2002},{142,10,12},{4,0,28},{5,0,440},{7,0,248},{11,0,833},{140,0,344} +,{7,10,736},{139,10,264},{134,10,1657},{134,0,1654},{138,0,531},{5,11,222},{9,11 +,140},{138,11,534},{6,0,634},{6,0,798},{134,0,840},{138,11,503},{135,10,127},{ +133,0,853},{5,11,154},{7,11,1491},{10,11,379},{138,11,485},{6,0,249},{7,0,1234}, +{139,0,573},{133,11,716},{7,11,1570},{140,11,542},{136,10,364},{138,0,527},{4,11 +,91},{5,11,388},{5,11,845},{6,11,206},{6,11,252},{6,11,365},{7,11,136},{7,11,531 +},{8,11,264},{136,11,621},{134,0,1419},{135,11,1441},{7,0,49},{7,0,392},{8,0,20} +,{8,0,172},{8,0,690},{9,0,383},{9,0,845},{10,0,48},{11,0,293},{11,0,832},{11,0, +920},{11,0,984},{141,0,221},{5,0,858},{133,0,992},{5,0,728},{137,10,792},{5,10, +909},{9,10,849},{138,10,805},{7,0,525},{7,0,1579},{8,0,497},{136,0,573},{6,0,268 +},{137,0,62},{135,11,576},{134,0,1201},{5,11,771},{5,11,863},{5,11,898},{6,11, +1632},{6,11,1644},{134,11,1780},{133,11,331},{7,0,193},{7,0,1105},{10,0,495},{7, +10,397},{8,10,124},{8,10,619},{9,10,305},{11,10,40},{12,10,349},{13,10,134},{13, +10,295},{14,10,155},{15,10,120},{146,10,105},{138,0,106},{6,0,859},{5,11,107},{7 +,11,201},{136,11,518},{6,11,446},{135,11,1817},{13,0,23},{4,10,262},{135,10,342} +,{133,10,641},{137,11,851},{6,0,925},{137,0,813},{132,11,504},{6,0,613},{136,0, +223},{4,10,99},{6,10,250},{6,10,346},{8,10,127},{138,10,81},{136,0,953},{132,10, +915},{139,11,892},{5,10,75},{9,10,517},{10,10,470},{12,10,155},{141,10,224},{4,0 +,666},{7,0,1017},{7,11,996},{138,11,390},{5,11,883},{133,11,975},{14,10,83},{142 +,11,83},{4,0,670},{5,11,922},{134,11,1707},{135,0,216},{9,0,40},{11,0,136},{135, +11,787},{5,10,954},{5,11,993},{7,11,515},{137,11,91},{139,0,259},{7,0,1114},{9,0 +,310},{9,0,682},{10,0,440},{13,0,40},{6,10,304},{8,10,418},{11,10,341},{139,10, +675},{14,0,296},{9,10,410},{139,10,425},{10,11,377},{12,11,363},{13,11,68},{13, +11,94},{14,11,108},{142,11,306},{7,0,1401},{135,0,1476},{4,0,296},{6,0,475},{7,0 +,401},{7,0,1410},{7,0,1594},{7,0,1674},{8,0,63},{8,0,660},{137,0,74},{4,0,139},{ +4,0,388},{140,0,188},{132,0,797},{132,11,766},{5,11,103},{7,11,921},{8,11,580},{ +8,11,593},{8,11,630},{138,11,28},{4,11,911},{5,11,867},{133,11,1013},{134,10,14} +,{134,0,1572},{134,10,1708},{21,0,39},{5,10,113},{6,10,243},{7,10,1865},{11,10, +161},{16,10,37},{145,10,99},{7,11,1563},{141,11,182},{5,11,135},{6,11,519},{7,11 +,1722},{10,11,271},{11,11,261},{145,11,54},{132,10,274},{134,0,1594},{4,11,300}, +{5,11,436},{135,11,484},{4,0,747},{6,0,290},{7,0,649},{7,0,1479},{135,0,1583},{ +133,11,535},{147,11,82},{133,0,232},{137,0,887},{135,10,166},{136,0,521},{4,0,14 +},{7,0,472},{7,0,1801},{10,0,748},{141,0,458},{134,0,741},{134,0,992},{16,0,111} +,{137,10,304},{4,0,425},{5,11,387},{7,11,557},{12,11,547},{142,11,86},{135,11, +1747},{5,10,654},{135,11,1489},{7,0,789},{4,11,6},{5,11,708},{136,11,75},{6,10, +273},{10,10,188},{13,10,377},{146,10,77},{6,0,1593},{4,11,303},{7,11,619},{10,11 +,547},{10,11,687},{11,11,122},{140,11,601},{134,0,1768},{135,10,410},{138,11,772 +},{11,0,233},{139,10,524},{5,0,943},{134,0,1779},{134,10,1785},{136,11,529},{132 +,0,955},{5,0,245},{6,0,576},{7,0,582},{136,0,225},{132,10,780},{142,0,241},{134, +0,1943},{4,11,106},{7,11,310},{7,11,1785},{10,11,690},{139,11,717},{134,0,1284}, +{5,11,890},{133,11,988},{6,11,626},{142,11,431},{10,11,706},{145,11,32},{137,11, +332},{132,11,698},{135,0,709},{5,10,948},{138,11,17},{136,0,554},{134,0,1564},{ +139,10,941},{132,0,443},{134,0,909},{134,11,84},{142,0,280},{4,10,532},{5,10,706 +},{135,10,662},{132,0,729},{5,10,837},{6,10,1651},{139,10,985},{135,10,1861},{4, +0,348},{152,11,3},{5,11,986},{6,11,130},{7,11,1582},{8,11,458},{10,11,101},{10, +11,318},{138,11,823},{134,0,758},{4,0,298},{137,0,848},{4,10,330},{7,10,933},{7, +10,2012},{136,10,292},{7,11,1644},{137,11,129},{6,0,1422},{9,0,829},{135,10,767} +,{5,0,164},{7,0,121},{142,0,189},{7,0,812},{7,0,1261},{7,0,1360},{9,0,632},{140, +0,352},{135,11,1788},{139,0,556},{135,11,997},{145,10,114},{4,0,172},{9,0,611},{ +10,0,436},{12,0,673},{13,0,255},{137,10,883},{11,0,530},{138,10,274},{133,0,844} +,{134,0,984},{13,0,232},{18,0,35},{4,10,703},{135,10,207},{132,10,571},{9,0,263} +,{10,0,147},{138,0,492},{7,11,1756},{137,11,98},{5,10,873},{5,10,960},{8,10,823} +,{137,10,881},{133,0,537},{132,0,859},{7,11,1046},{139,11,160},{137,0,842},{139, +10,283},{5,10,33},{6,10,470},{139,10,424},{6,11,45},{7,11,433},{8,11,129},{9,11, +21},{10,11,392},{11,11,79},{12,11,499},{13,11,199},{141,11,451},{135,0,1291},{ +135,10,1882},{7,11,558},{136,11,353},{134,0,1482},{5,0,230},{5,0,392},{6,0,420}, +{9,0,568},{140,0,612},{6,0,262},{7,10,90},{7,10,664},{7,10,830},{7,10,1380},{7, +10,2025},{8,11,81},{8,10,448},{8,10,828},{9,11,189},{9,11,201},{11,11,478},{11, +11,712},{141,11,338},{142,0,31},{5,11,353},{151,11,26},{132,0,753},{4,0,0},{5,0, +41},{7,0,1459},{7,0,1469},{7,0,1859},{9,0,549},{139,0,905},{9,10,417},{137,10, +493},{135,11,1113},{133,0,696},{141,11,448},{134,10,295},{132,0,834},{4,0,771},{ +5,10,1019},{6,11,25},{7,11,855},{7,11,1258},{144,11,32},{134,0,1076},{133,0,921} +,{133,0,674},{4,11,4},{7,11,1118},{7,11,1320},{7,11,1706},{8,11,277},{9,11,622}, +{10,11,9},{11,11,724},{12,11,350},{12,11,397},{13,11,28},{13,11,159},{15,11,89}, +{18,11,5},{19,11,9},{20,11,34},{150,11,47},{134,10,208},{6,0,444},{136,0,308},{6 +,0,180},{7,0,1137},{8,0,751},{139,0,805},{4,0,183},{7,0,271},{11,0,824},{11,0, +952},{13,0,278},{13,0,339},{13,0,482},{14,0,424},{148,0,99},{7,11,317},{135,11, +569},{4,0,19},{5,0,477},{5,0,596},{6,0,505},{7,0,1221},{11,0,907},{12,0,209},{ +141,0,214},{135,0,1215},{6,0,271},{7,0,398},{8,0,387},{10,0,344},{7,10,448},{7, +10,1629},{7,10,1813},{8,10,442},{9,10,710},{10,10,282},{138,10,722},{11,10,844}, +{12,10,104},{140,10,625},{134,11,255},{133,10,787},{134,0,1645},{11,11,956},{151 +,11,3},{6,0,92},{6,0,188},{7,0,209},{7,0,1269},{7,0,1524},{7,0,1876},{8,0,661},{ +10,0,42},{10,0,228},{11,0,58},{11,0,1020},{12,0,58},{12,0,118},{141,0,32},{4,0, +459},{133,0,966},{4,11,536},{7,11,1141},{10,11,723},{139,11,371},{140,0,330},{ +134,0,1557},{7,11,285},{135,11,876},{136,10,491},{135,11,560},{6,0,18},{7,0,179} +,{7,0,932},{8,0,548},{8,0,757},{9,0,54},{9,0,65},{9,0,532},{9,0,844},{10,0,113}, +{10,0,117},{10,0,315},{10,0,560},{10,0,622},{10,0,798},{11,0,153},{11,0,351},{11 +,0,375},{12,0,78},{12,0,151},{12,0,392},{12,0,666},{14,0,248},{143,0,23},{6,0, +1742},{132,11,690},{4,10,403},{5,10,441},{7,10,450},{10,10,840},{11,10,101},{12, +10,193},{141,10,430},{133,0,965},{134,0,182},{10,0,65},{10,0,488},{138,0,497},{ +135,11,1346},{6,0,973},{6,0,1158},{10,11,200},{19,11,2},{151,11,22},{4,11,190},{ +133,11,554},{133,10,679},{7,0,328},{137,10,326},{133,11,1001},{9,0,588},{138,0, +260},{133,11,446},{135,10,1128},{135,10,1796},{147,11,119},{134,0,1786},{6,0, +1328},{6,0,1985},{8,0,962},{138,0,1017},{135,0,308},{11,0,508},{4,10,574},{7,10, +350},{7,10,1024},{8,10,338},{9,10,677},{138,10,808},{138,11,752},{135,10,1081},{ +137,11,96},{7,10,1676},{135,10,2037},{136,0,588},{132,11,304},{133,0,614},{140,0 +,793},{136,0,287},{137,10,297},{141,10,37},{6,11,53},{6,11,199},{7,11,1408},{8, +11,32},{8,11,93},{9,11,437},{10,11,397},{10,11,629},{11,11,593},{11,11,763},{13, +11,326},{145,11,35},{134,11,105},{9,11,320},{10,11,506},{138,11,794},{5,11,114}, +{5,11,255},{141,11,285},{140,0,290},{7,11,2035},{8,11,19},{9,11,89},{138,11,831} +,{134,0,1136},{7,0,719},{8,0,796},{8,0,809},{8,0,834},{6,10,306},{7,10,1140},{7, +10,1340},{8,10,133},{138,10,449},{139,10,1011},{5,0,210},{6,0,213},{7,0,60},{10, +0,364},{139,0,135},{5,0,607},{8,0,326},{136,0,490},{138,11,176},{132,0,701},{5,0 +,472},{7,0,380},{137,0,758},{135,0,1947},{6,0,1079},{138,0,278},{138,11,391},{5, +10,329},{8,10,260},{139,11,156},{4,0,386},{7,0,41},{8,0,405},{8,0,728},{9,0,497} +,{11,0,110},{11,0,360},{15,0,37},{144,0,84},{5,0,46},{7,0,1452},{7,0,1480},{8,0, +634},{140,0,472},{136,0,961},{4,0,524},{136,0,810},{10,0,238},{141,0,33},{132,10 +,657},{152,10,7},{133,0,532},{5,0,997},{135,10,1665},{7,11,594},{7,11,851},{7,11 +,1858},{9,11,411},{9,11,574},{9,11,666},{9,11,737},{10,11,346},{10,11,712},{11, +11,246},{11,11,432},{11,11,517},{11,11,647},{11,11,679},{11,11,727},{12,11,304}, +{12,11,305},{12,11,323},{12,11,483},{12,11,572},{12,11,593},{12,11,602},{13,11, +95},{13,11,101},{13,11,171},{13,11,315},{13,11,378},{13,11,425},{13,11,475},{14, +11,63},{14,11,380},{14,11,384},{15,11,133},{18,11,112},{148,11,72},{5,11,955},{ +136,11,814},{134,0,1301},{5,10,66},{7,10,1896},{136,10,288},{133,11,56},{134,10, +1643},{6,0,1298},{148,11,100},{5,0,782},{5,0,829},{6,0,671},{6,0,1156},{6,0,1738 +},{137,11,621},{4,0,306},{5,0,570},{7,0,1347},{5,10,91},{5,10,648},{5,10,750},{5 +,10,781},{6,10,54},{6,10,112},{6,10,402},{6,10,1732},{7,10,315},{7,10,749},{7,10 +,1900},{9,10,78},{9,10,508},{10,10,611},{10,10,811},{11,10,510},{11,10,728},{13, +10,36},{14,10,39},{16,10,83},{17,10,124},{148,10,30},{8,10,570},{9,11,477},{141, +11,78},{4,11,639},{10,11,4},{10,10,322},{10,10,719},{11,10,407},{11,11,638},{12, +11,177},{148,11,57},{7,0,1823},{139,0,693},{7,0,759},{5,11,758},{8,10,125},{8,10 +,369},{8,10,524},{10,10,486},{11,10,13},{11,10,381},{11,10,736},{11,10,766},{11, +10,845},{13,10,114},{13,10,292},{142,10,47},{7,0,1932},{6,10,1684},{6,10,1731},{ +7,10,356},{8,10,54},{8,10,221},{9,10,225},{9,10,356},{10,10,77},{10,10,446},{10, +10,731},{12,10,404},{141,10,491},{135,11,552},{135,11,1112},{4,0,78},{5,0,96},{5 +,0,182},{6,0,1257},{7,0,1724},{7,0,1825},{10,0,394},{10,0,471},{11,0,532},{14,0, +340},{145,0,88},{139,11,328},{135,0,1964},{132,10,411},{4,10,80},{5,10,44},{137, +11,133},{5,11,110},{6,11,169},{6,11,1702},{7,11,400},{8,11,538},{9,11,184},{9,11 +,524},{140,11,218},{4,0,521},{5,10,299},{7,10,1083},{140,11,554},{6,11,133},{9, +11,353},{12,11,628},{146,11,79},{6,0,215},{7,0,584},{7,0,1028},{7,0,1473},{7,0, +1721},{9,0,424},{138,0,779},{7,0,857},{7,0,1209},{7,10,1713},{9,10,537},{10,10, +165},{12,10,219},{140,10,561},{4,10,219},{6,11,93},{7,11,1422},{7,10,1761},{7,11 +,1851},{8,11,673},{9,10,86},{9,11,529},{140,11,43},{137,11,371},{136,0,671},{5,0 +,328},{135,0,918},{132,0,529},{9,11,25},{10,11,467},{138,11,559},{4,11,335},{135 +,11,942},{134,0,716},{134,0,1509},{6,0,67},{7,0,258},{7,0,1630},{9,0,354},{9,0, +675},{10,0,830},{14,0,80},{17,0,80},{140,10,428},{134,0,1112},{6,0,141},{7,0,225 +},{9,0,59},{9,0,607},{10,0,312},{11,0,687},{12,0,555},{13,0,373},{13,0,494},{148 +,0,58},{133,10,514},{8,11,39},{10,11,773},{11,11,84},{12,11,205},{142,11,1},{8,0 +,783},{5,11,601},{133,11,870},{136,11,594},{4,10,55},{5,10,301},{6,10,571},{14, +10,49},{146,10,102},{132,11,181},{134,11,1652},{133,10,364},{4,11,97},{5,11,147} +,{6,11,286},{7,11,1362},{141,11,176},{4,10,76},{7,10,1550},{9,10,306},{9,10,430} +,{9,10,663},{10,10,683},{11,10,427},{11,10,753},{12,10,334},{12,10,442},{14,10, +258},{14,10,366},{143,10,131},{137,10,52},{6,0,955},{134,0,1498},{6,11,375},{7, +11,169},{7,11,254},{136,11,780},{7,0,430},{11,0,46},{14,0,343},{142,11,343},{135 +,0,1183},{5,0,602},{7,0,2018},{9,0,418},{9,0,803},{135,11,1447},{8,0,677},{135, +11,1044},{139,11,285},{4,10,656},{135,10,779},{135,10,144},{5,11,629},{135,11, +1549},{135,10,1373},{138,11,209},{7,10,554},{7,10,605},{141,10,10},{5,10,838},{5 +,10,841},{134,10,1649},{133,10,1012},{6,0,1357},{134,0,1380},{144,0,53},{6,0,590 +},{7,10,365},{7,10,1357},{7,10,1497},{8,10,154},{141,10,281},{133,10,340},{132, +11,420},{135,0,329},{147,11,32},{4,0,469},{10,11,429},{139,10,495},{8,10,261},{9 +,10,144},{9,10,466},{10,10,370},{12,10,470},{13,10,144},{142,10,348},{142,0,460} +,{4,11,325},{9,10,897},{138,11,125},{6,0,1743},{6,10,248},{9,10,546},{10,10,535} +,{11,10,681},{141,10,135},{4,0,990},{5,0,929},{6,0,340},{8,0,376},{8,0,807},{8,0 +,963},{8,0,980},{138,0,1007},{134,0,1603},{140,0,250},{4,11,714},{133,11,469},{ +134,10,567},{136,10,445},{5,0,218},{7,0,1610},{8,0,646},{10,0,83},{11,11,138},{ +140,11,40},{7,0,1512},{135,0,1794},{135,11,1216},{11,0,0},{16,0,78},{132,11,718} +,{133,0,571},{132,0,455},{134,0,1012},{5,11,124},{5,11,144},{6,11,548},{7,11,15} +,{7,11,153},{137,11,629},{142,11,10},{6,11,75},{7,11,1531},{8,11,416},{9,11,240} +,{9,11,275},{10,11,100},{11,11,658},{11,11,979},{12,11,86},{13,11,468},{14,11,66 +},{14,11,207},{15,11,20},{15,11,25},{144,11,58},{132,10,577},{5,11,141},{5,11, +915},{6,11,1783},{7,11,211},{7,11,698},{7,11,1353},{9,11,83},{9,11,281},{10,11, +376},{10,11,431},{11,11,543},{12,11,664},{13,11,280},{13,11,428},{14,11,61},{14, +11,128},{17,11,52},{145,11,81},{6,0,161},{7,0,372},{137,0,597},{132,0,349},{10, +11,702},{139,11,245},{134,0,524},{134,10,174},{6,0,432},{9,0,751},{139,0,322},{ +147,11,94},{4,11,338},{133,11,400},{5,0,468},{10,0,325},{11,0,856},{12,0,345},{ +143,0,104},{133,0,223},{132,0,566},{4,11,221},{5,11,659},{5,11,989},{7,11,697},{ +7,11,1211},{138,11,284},{135,11,1070},{4,0,59},{135,0,1394},{6,0,436},{11,0,481} +,{5,10,878},{133,10,972},{4,0,48},{5,0,271},{135,0,953},{5,0,610},{136,0,457},{4 +,0,773},{5,0,618},{137,0,756},{133,0,755},{135,0,1217},{138,11,507},{132,10,351} +,{132,0,197},{143,11,78},{4,11,188},{7,11,805},{11,11,276},{142,11,293},{5,11, +884},{139,11,991},{132,10,286},{10,0,259},{10,0,428},{7,10,438},{7,10,627},{7,10 +,1516},{8,10,40},{9,10,56},{9,10,294},{11,10,969},{11,10,995},{146,10,148},{4,0, +356},{5,0,217},{5,0,492},{5,0,656},{8,0,544},{136,11,544},{5,0,259},{6,0,1230},{ +7,0,414},{7,0,854},{142,0,107},{132,0,1007},{15,0,14},{144,0,5},{6,0,1580},{132, +10,738},{132,11,596},{132,0,673},{133,10,866},{6,0,1843},{135,11,1847},{4,0,165} +,{7,0,1398},{135,0,1829},{135,11,1634},{147,11,65},{6,0,885},{6,0,1009},{137,0, +809},{133,10,116},{132,10,457},{136,11,770},{9,0,498},{12,0,181},{10,11,361},{ +142,11,316},{134,11,595},{5,0,9},{7,0,297},{7,0,966},{140,0,306},{4,11,89},{5,11 +,489},{6,11,315},{7,11,553},{7,11,1745},{138,11,243},{134,0,1487},{132,0,437},{5 +,0,146},{6,0,411},{138,0,721},{5,10,527},{6,10,189},{135,10,859},{11,10,104},{11 +,10,554},{15,10,60},{143,10,125},{6,11,1658},{9,11,3},{10,11,154},{11,11,641},{ +13,11,85},{13,11,201},{141,11,346},{6,0,177},{135,0,467},{134,0,1377},{134,10, +116},{136,11,645},{4,11,166},{5,11,505},{6,11,1670},{137,11,110},{133,10,487},{4 +,10,86},{5,10,667},{5,10,753},{6,10,316},{6,10,455},{135,10,946},{133,0,200},{ +132,0,959},{6,0,1928},{134,0,1957},{139,11,203},{150,10,45},{4,10,79},{7,10,1773 +},{10,10,450},{11,10,589},{13,10,332},{13,10,493},{14,10,183},{14,10,334},{14,10 +,362},{14,10,368},{14,10,376},{14,10,379},{19,10,90},{19,10,103},{19,10,127},{ +148,10,90},{6,0,1435},{135,11,1275},{134,0,481},{7,11,445},{8,11,307},{8,11,704} +,{10,11,41},{10,11,439},{11,11,237},{11,11,622},{140,11,201},{135,11,869},{4,0, +84},{7,0,1482},{10,0,76},{138,0,142},{11,11,277},{144,11,14},{135,11,1977},{4,11 +,189},{5,11,713},{136,11,57},{133,0,1015},{138,11,371},{4,0,315},{5,0,507},{135, +0,1370},{4,11,552},{142,10,381},{9,0,759},{16,0,31},{16,0,39},{16,0,75},{18,0,24 +},{20,0,42},{152,0,1},{134,0,712},{134,0,1722},{133,10,663},{133,10,846},{8,0, +222},{8,0,476},{9,0,238},{11,0,516},{11,0,575},{15,0,109},{146,0,100},{7,0,1402} +,{7,0,1414},{12,0,456},{5,10,378},{8,10,465},{9,10,286},{10,10,185},{10,10,562}, +{10,10,635},{11,10,31},{11,10,393},{13,10,312},{18,10,65},{18,10,96},{147,10,89} +,{4,0,986},{6,0,1958},{6,0,2032},{8,0,934},{138,0,985},{7,10,1880},{9,10,680},{ +139,10,798},{134,10,1770},{145,11,49},{132,11,614},{132,10,648},{5,10,945},{6,10 +,1656},{6,10,1787},{7,10,167},{8,10,824},{9,10,391},{10,10,375},{139,10,185},{ +138,11,661},{7,0,1273},{135,11,1945},{7,0,706},{7,0,1058},{138,0,538},{7,10,1645 +},{8,10,352},{137,10,249},{132,10,152},{11,0,92},{11,0,196},{11,0,409},{11,0,450 +},{11,0,666},{11,0,777},{12,0,262},{13,0,385},{13,0,393},{15,0,115},{16,0,45},{ +145,0,82},{133,10,1006},{6,0,40},{135,0,1781},{9,11,614},{139,11,327},{5,10,420} +,{135,10,1449},{135,0,431},{10,0,97},{135,10,832},{6,0,423},{7,0,665},{135,0, +1210},{7,0,237},{8,0,664},{9,0,42},{9,0,266},{9,0,380},{9,0,645},{10,0,177},{138 +,0,276},{7,0,264},{133,10,351},{8,0,213},{5,10,40},{7,10,598},{7,10,1638},{9,10, +166},{9,10,640},{9,10,685},{9,10,773},{11,10,215},{13,10,65},{14,10,172},{14,10, +317},{145,10,6},{5,11,84},{134,11,163},{8,10,60},{9,10,343},{139,10,769},{137,0, +455},{133,11,410},{8,0,906},{12,0,700},{12,0,706},{140,0,729},{21,11,33},{150,11 +,40},{7,10,1951},{8,10,765},{8,10,772},{140,10,671},{7,10,108},{8,10,219},{8,10, +388},{9,10,639},{9,10,775},{11,10,275},{140,10,464},{5,11,322},{7,11,1941},{8,11 +,186},{9,11,262},{10,11,187},{14,11,208},{146,11,130},{139,0,624},{8,0,574},{5, +11,227},{140,11,29},{7,11,1546},{11,11,299},{142,11,407},{5,10,15},{6,10,56},{7, +10,1758},{8,10,500},{9,10,730},{11,10,331},{13,10,150},{142,10,282},{7,11,1395}, +{8,11,486},{9,11,236},{9,11,878},{10,11,218},{11,11,95},{19,11,17},{147,11,31},{ +135,11,2043},{4,0,354},{146,11,4},{140,11,80},{135,0,1558},{134,10,1886},{5,10, +205},{6,10,438},{137,10,711},{133,11,522},{133,10,534},{7,0,235},{7,0,1475},{15, +0,68},{146,0,120},{137,10,691},{4,0,942},{6,0,1813},{8,0,917},{10,0,884},{12,0, +696},{12,0,717},{12,0,723},{12,0,738},{12,0,749},{12,0,780},{16,0,97},{146,0,169 +},{6,10,443},{8,11,562},{9,10,237},{9,10,571},{9,10,695},{10,10,139},{11,10,715} +,{12,10,417},{141,10,421},{135,0,957},{133,0,830},{134,11,1771},{146,0,23},{5,0, +496},{6,0,694},{7,0,203},{7,11,1190},{137,11,620},{137,11,132},{6,0,547},{134,0, +1549},{8,11,258},{9,11,208},{137,11,359},{4,0,864},{5,0,88},{137,0,239},{135,11, +493},{4,11,317},{135,11,1279},{132,11,477},{4,10,578},{5,11,63},{133,11,509},{7, +0,650},{135,0,1310},{7,0,1076},{9,0,80},{11,0,78},{11,0,421},{11,0,534},{140,0, +545},{132,11,288},{12,0,553},{14,0,118},{133,10,923},{7,0,274},{11,0,479},{139,0 +,507},{8,11,89},{8,11,620},{9,11,49},{10,11,774},{11,11,628},{12,11,322},{143,11 +,124},{4,0,497},{135,0,1584},{7,0,261},{7,0,1115},{7,0,1354},{7,0,1404},{7,0, +1588},{7,0,1705},{7,0,1902},{9,0,465},{10,0,248},{10,0,349},{10,0,647},{11,0,527 +},{11,0,660},{11,0,669},{12,0,529},{13,0,305},{132,10,924},{133,10,665},{136,0, +13},{6,0,791},{138,11,120},{7,0,642},{8,0,250},{11,0,123},{11,0,137},{13,0,48},{ +142,0,95},{4,10,265},{7,10,807},{135,10,950},{5,10,93},{140,10,267},{135,0,1429} +,{4,0,949},{10,0,885},{10,0,891},{10,0,900},{10,0,939},{12,0,760},{142,0,449},{ +139,11,366},{132,0,818},{134,11,85},{135,10,994},{7,0,330},{5,10,233},{5,10,320} +,{6,10,140},{136,10,295},{4,0,1004},{8,0,982},{136,0,993},{133,10,978},{4,10,905 +},{6,10,1701},{137,10,843},{10,0,545},{140,0,301},{6,0,947},{134,0,1062},{134,0, +1188},{4,0,904},{5,0,794},{152,10,6},{134,0,1372},{135,11,608},{5,11,279},{6,11, +235},{7,11,468},{8,11,446},{9,11,637},{10,11,717},{11,11,738},{140,11,514},{132, +10,509},{5,11,17},{6,11,371},{137,11,528},{132,0,693},{4,11,115},{5,11,669},{6, +11,407},{8,11,311},{11,11,10},{141,11,5},{11,0,377},{7,10,273},{137,11,381},{135 +,0,695},{7,0,386},{138,0,713},{135,10,1041},{134,0,1291},{6,0,7},{6,0,35},{7,0, +147},{7,0,1069},{7,0,1568},{7,0,1575},{7,0,1917},{8,0,43},{8,0,208},{9,0,128},{9 +,0,866},{10,0,20},{11,0,981},{147,0,33},{7,0,893},{141,0,424},{139,10,234},{150, +11,56},{5,11,779},{5,11,807},{6,11,1655},{134,11,1676},{5,10,802},{7,10,2021},{ +136,10,805},{4,11,196},{5,10,167},{5,11,558},{5,10,899},{5,11,949},{6,10,410},{ +137,10,777},{137,10,789},{134,10,1705},{8,0,904},{140,0,787},{6,0,322},{9,0,552} +,{11,0,274},{13,0,209},{13,0,499},{14,0,85},{15,0,126},{145,0,70},{135,10,10},{5 +,10,11},{6,10,117},{6,10,485},{7,10,1133},{9,10,582},{9,10,594},{11,10,21},{11, +10,818},{12,10,535},{141,10,86},{4,10,264},{7,10,1067},{8,10,204},{8,10,385},{ +139,10,953},{132,11,752},{138,10,56},{133,10,470},{6,0,1808},{8,0,83},{8,0,742}, +{8,0,817},{9,0,28},{9,0,29},{9,0,885},{10,0,387},{11,0,633},{11,0,740},{13,0,235 +},{13,0,254},{15,0,143},{143,0,146},{140,0,49},{134,0,1832},{4,11,227},{5,11,159 +},{5,11,409},{7,11,80},{10,11,294},{10,11,479},{12,11,418},{14,11,50},{14,11,249 +},{142,11,295},{7,11,1470},{8,11,66},{8,11,137},{8,11,761},{9,11,638},{11,11,80} +,{11,11,212},{11,11,368},{11,11,418},{12,11,8},{13,11,15},{16,11,61},{17,11,59}, +{19,11,28},{148,11,84},{139,10,1015},{138,11,468},{135,0,421},{6,0,415},{7,0, +1049},{137,0,442},{6,11,38},{7,11,1220},{8,11,185},{8,11,256},{9,11,22},{9,11, +331},{10,11,738},{11,11,205},{11,11,540},{11,11,746},{13,11,399},{13,11,465},{14 +,11,88},{142,11,194},{139,0,289},{133,10,715},{4,0,110},{10,0,415},{10,0,597},{ +142,0,206},{4,11,159},{6,11,115},{7,11,252},{7,11,257},{7,11,1928},{8,11,69},{9, +11,384},{10,11,91},{10,11,615},{12,11,375},{14,11,235},{18,11,117},{147,11,123}, +{5,11,911},{136,11,278},{7,0,205},{7,0,2000},{8,10,794},{9,10,400},{10,10,298},{ +142,10,228},{135,11,1774},{4,11,151},{7,11,1567},{8,11,351},{137,11,322},{136,10 +,724},{133,11,990},{7,0,1539},{11,0,512},{13,0,205},{19,0,30},{22,0,36},{23,0,19 +},{135,11,1539},{5,11,194},{7,11,1662},{9,11,90},{140,11,180},{6,10,190},{7,10, +768},{135,10,1170},{134,0,1340},{4,0,283},{135,0,1194},{133,11,425},{133,11,971} +,{12,0,549},{14,10,67},{147,10,60},{135,10,1023},{134,0,1720},{138,11,587},{5,11 +,72},{6,11,264},{7,11,21},{7,11,46},{7,11,2013},{8,11,215},{8,11,513},{10,11,266 +},{139,11,22},{5,0,319},{135,0,534},{6,10,137},{9,10,75},{9,10,253},{10,10,194}, +{138,10,444},{7,0,1180},{20,0,112},{6,11,239},{7,11,118},{10,11,95},{11,11,603}, +{13,11,443},{14,11,160},{143,11,4},{134,11,431},{5,11,874},{6,11,1677},{11,10, +643},{12,10,115},{143,11,0},{134,0,967},{6,11,65},{7,11,939},{7,11,1172},{7,11, +1671},{9,11,540},{10,11,696},{11,11,265},{11,11,732},{11,11,928},{11,11,937},{12 +,11,399},{13,11,438},{149,11,19},{137,11,200},{135,0,1940},{5,10,760},{7,10,542} +,{8,10,135},{136,10,496},{140,11,44},{7,11,1655},{136,11,305},{7,10,319},{7,10, +355},{7,10,763},{10,10,389},{145,10,43},{136,0,735},{138,10,786},{137,11,19},{ +132,11,696},{5,0,132},{9,0,486},{9,0,715},{10,0,458},{11,0,373},{11,0,668},{11,0 +,795},{11,0,897},{12,0,272},{12,0,424},{12,0,539},{12,0,558},{14,0,245},{14,0, +263},{14,0,264},{14,0,393},{142,0,403},{10,0,38},{139,0,784},{132,0,838},{4,11, +302},{135,11,1766},{133,0,379},{5,0,8},{6,0,89},{6,0,400},{7,0,1569},{7,0,1623}, +{7,0,1850},{8,0,218},{8,0,422},{9,0,570},{10,0,626},{4,11,726},{133,11,630},{4,0 +,1017},{138,0,660},{6,0,387},{7,0,882},{141,0,111},{6,0,224},{7,0,877},{137,0, +647},{4,10,58},{5,10,286},{6,10,319},{7,10,402},{7,10,1254},{7,10,1903},{8,10, +356},{140,10,408},{135,0,790},{9,0,510},{10,0,53},{4,10,389},{9,10,181},{10,10, +29},{10,10,816},{11,10,311},{11,10,561},{12,10,67},{141,10,181},{142,0,458},{6, +11,118},{7,11,215},{7,11,1521},{140,11,11},{134,0,954},{135,0,394},{134,0,1367}, +{5,11,225},{133,10,373},{132,0,882},{7,0,1409},{135,10,1972},{135,10,1793},{4,11 +,370},{5,11,756},{135,11,1326},{150,11,13},{7,11,354},{10,11,410},{139,11,815},{ +6,11,1662},{7,11,48},{8,11,771},{10,11,116},{13,11,104},{14,11,105},{14,11,184}, +{15,11,168},{19,11,92},{148,11,68},{7,0,124},{136,0,38},{5,0,261},{7,0,78},{7,0, +199},{8,0,815},{9,0,126},{10,0,342},{140,0,647},{4,0,628},{140,0,724},{7,0,266}, +{8,0,804},{7,10,1651},{145,10,89},{135,0,208},{134,0,1178},{6,0,79},{135,0,1519} +,{132,10,672},{133,10,737},{136,0,741},{132,11,120},{4,0,710},{6,0,376},{134,0, +606},{134,0,1347},{134,0,1494},{6,0,850},{6,0,1553},{137,0,821},{5,10,145},{134, +11,593},{7,0,1311},{140,0,135},{4,0,467},{5,0,405},{134,0,544},{5,11,820},{135, +11,931},{6,0,100},{7,0,244},{7,0,632},{7,0,1609},{8,0,178},{8,0,638},{141,0,58}, +{4,10,387},{135,10,1288},{6,11,151},{6,11,1675},{7,11,383},{151,11,10},{132,0, +481},{135,10,550},{134,0,1378},{6,11,1624},{11,11,11},{12,11,422},{13,11,262},{ +142,11,360},{133,0,791},{4,11,43},{5,11,344},{133,11,357},{7,0,1227},{140,0,978} +,{7,0,686},{8,0,33},{8,0,238},{10,0,616},{11,0,467},{11,0,881},{13,0,217},{13,0, +253},{142,0,268},{137,0,857},{8,0,467},{8,0,1006},{7,11,148},{8,11,284},{141,11, +63},{4,10,576},{135,10,1263},{133,11,888},{5,10,919},{134,10,1673},{20,10,37},{ +148,11,37},{132,0,447},{132,11,711},{4,0,128},{5,0,415},{6,0,462},{7,0,294},{7,0 +,578},{10,0,710},{139,0,86},{4,10,82},{5,10,333},{5,10,904},{6,10,207},{7,10,325 +},{7,10,1726},{8,10,101},{10,10,778},{139,10,220},{136,0,587},{137,11,440},{133, +10,903},{6,0,427},{7,0,1018},{138,0,692},{4,0,195},{135,0,802},{140,10,147},{134 +,0,1546},{134,0,684},{132,10,705},{136,0,345},{11,11,678},{140,11,307},{133,0, +365},{134,0,1683},{4,11,65},{5,11,479},{5,11,1004},{7,11,1913},{8,11,317},{9,11, +302},{10,11,612},{141,11,22},{138,0,472},{4,11,261},{135,11,510},{134,10,90},{ +142,0,433},{151,0,28},{4,11,291},{7,11,101},{9,11,515},{12,11,152},{12,11,443},{ +13,11,392},{142,11,357},{140,0,997},{5,0,3},{8,0,578},{9,0,118},{10,0,705},{141, +0,279},{135,11,1266},{7,10,813},{12,10,497},{141,10,56},{133,0,229},{6,10,125},{ +135,10,1277},{8,0,102},{10,0,578},{10,0,672},{12,0,496},{13,0,408},{14,0,121},{ +17,0,106},{151,10,12},{6,0,866},{134,0,1080},{136,0,1022},{4,11,130},{135,11,843 +},{5,11,42},{5,11,879},{7,11,245},{7,11,324},{7,11,1532},{11,11,463},{11,11,472} +,{13,11,363},{144,11,52},{150,0,55},{8,0,115},{8,0,350},{9,0,489},{10,0,128},{11 +,0,306},{12,0,373},{14,0,30},{17,0,79},{19,0,80},{4,11,134},{133,11,372},{134,0, +657},{134,0,933},{135,11,1147},{4,0,230},{133,0,702},{134,0,1728},{4,0,484},{18, +0,26},{19,0,42},{20,0,43},{21,0,0},{23,0,27},{152,0,14},{7,0,185},{135,0,703},{6 +,0,417},{10,0,618},{7,10,1106},{9,10,770},{11,10,112},{140,10,413},{134,0,803},{ +132,11,644},{134,0,1262},{7,11,540},{12,10,271},{145,10,109},{135,11,123},{132,0 +,633},{134,11,623},{4,11,908},{5,11,359},{5,11,508},{6,11,1723},{7,11,343},{7,11 +,1996},{135,11,2026},{135,0,479},{10,0,262},{7,10,304},{9,10,646},{9,10,862},{11 +,10,696},{12,10,208},{15,10,79},{147,10,108},{4,11,341},{135,11,480},{134,0,830} +,{5,0,70},{5,0,622},{6,0,334},{7,0,1032},{9,0,171},{11,0,26},{11,0,213},{11,0, +637},{11,0,707},{12,0,202},{12,0,380},{13,0,226},{13,0,355},{14,0,222},{145,0,42 +},{135,10,981},{143,0,217},{137,11,114},{4,0,23},{4,0,141},{5,0,313},{5,0,1014}, +{6,0,50},{6,0,51},{7,0,142},{7,0,384},{7,0,559},{8,0,640},{9,0,460},{9,0,783},{ +11,0,741},{12,0,183},{141,0,488},{141,0,360},{7,0,1586},{7,11,1995},{8,11,299},{ +11,11,890},{140,11,674},{132,10,434},{7,0,652},{134,10,550},{7,0,766},{5,10,553} +,{138,10,824},{7,0,737},{8,0,298},{136,10,452},{4,11,238},{5,11,503},{6,11,179}, +{7,11,2003},{8,11,381},{8,11,473},{9,11,149},{10,11,183},{15,11,45},{143,11,86}, +{133,10,292},{5,0,222},{9,0,655},{138,0,534},{138,10,135},{4,11,121},{5,11,156}, +{5,11,349},{9,11,136},{10,11,605},{14,11,342},{147,11,107},{137,0,906},{6,0,1013 +},{134,0,1250},{6,0,1956},{6,0,2009},{8,0,991},{144,0,120},{135,11,1192},{138,0, +503},{5,0,154},{7,0,1491},{10,0,379},{138,0,485},{6,0,1867},{6,0,1914},{6,0,1925 +},{9,0,917},{9,0,925},{9,0,932},{9,0,951},{9,0,1007},{9,0,1013},{12,0,806},{12,0 +,810},{12,0,814},{12,0,816},{12,0,824},{12,0,832},{12,0,837},{12,0,863},{12,0, +868},{12,0,870},{12,0,889},{12,0,892},{12,0,900},{12,0,902},{12,0,908},{12,0,933 +},{12,0,942},{12,0,949},{12,0,954},{15,0,175},{15,0,203},{15,0,213},{15,0,218},{ +15,0,225},{15,0,231},{15,0,239},{15,0,248},{15,0,252},{18,0,190},{18,0,204},{18, +0,215},{18,0,216},{18,0,222},{18,0,225},{18,0,230},{18,0,239},{18,0,241},{21,0, +42},{21,0,43},{21,0,44},{21,0,45},{21,0,46},{21,0,53},{24,0,27},{152,0,31},{133, +0,716},{135,0,844},{4,0,91},{5,0,388},{5,0,845},{6,0,206},{6,0,252},{6,0,365},{7 +,0,136},{7,0,531},{136,0,621},{7,10,393},{10,10,603},{139,10,206},{6,11,80},{6, +11,1694},{7,11,173},{7,11,1974},{9,11,547},{10,11,730},{14,11,18},{150,11,39},{ +137,0,748},{4,11,923},{134,11,1711},{4,10,912},{137,10,232},{7,10,98},{7,10,1973 +},{136,10,716},{14,0,103},{133,10,733},{132,11,595},{12,0,158},{18,0,8},{19,0,62 +},{20,0,6},{22,0,4},{23,0,2},{23,0,9},{5,11,240},{6,11,459},{7,11,12},{7,11,114} +,{7,11,502},{7,11,1751},{7,11,1753},{7,11,1805},{8,11,658},{9,11,1},{11,11,959}, +{13,11,446},{142,11,211},{135,0,576},{5,0,771},{5,0,863},{5,0,898},{6,0,648},{6, +0,1632},{6,0,1644},{134,0,1780},{133,0,331},{7,11,633},{7,11,905},{7,11,909},{7, +11,1538},{9,11,767},{140,11,636},{140,0,632},{5,0,107},{7,0,201},{136,0,518},{6, +0,446},{7,0,1817},{134,11,490},{9,0,851},{141,0,510},{7,11,250},{8,11,506},{136, +11,507},{4,0,504},{137,10,72},{132,11,158},{4,11,140},{7,11,362},{8,11,209},{9, +11,10},{9,11,160},{9,11,503},{10,11,689},{11,11,350},{11,11,553},{11,11,725},{12 +,11,252},{12,11,583},{13,11,192},{13,11,352},{14,11,269},{14,11,356},{148,11,50} +,{6,11,597},{135,11,1318},{135,10,1454},{5,0,883},{5,0,975},{8,0,392},{148,0,7}, +{6,11,228},{7,11,1341},{9,11,408},{138,11,343},{11,11,348},{11,10,600},{12,11,99 +},{13,10,245},{18,11,1},{18,11,11},{147,11,4},{134,11,296},{5,0,922},{134,0,1707 +},{132,11,557},{4,11,548},{7,10,164},{7,10,1571},{9,10,107},{140,10,225},{7,11, +197},{8,11,142},{8,11,325},{9,11,150},{9,11,596},{10,11,350},{10,11,353},{11,11, +74},{11,11,315},{14,11,423},{143,11,141},{5,0,993},{7,0,515},{137,0,91},{4,0,131 +},{8,0,200},{5,10,484},{5,10,510},{6,10,434},{7,10,1000},{7,10,1098},{136,10,2}, +{152,0,10},{4,11,62},{5,11,83},{6,11,399},{6,11,579},{7,11,692},{7,11,846},{7,11 +,1015},{7,11,1799},{8,11,403},{9,11,394},{10,11,133},{12,11,4},{12,11,297},{12, +11,452},{16,11,81},{18,11,19},{18,11,25},{21,11,14},{22,11,12},{151,11,18},{140, +11,459},{132,11,177},{7,0,1433},{9,0,365},{137,11,365},{132,10,460},{5,0,103},{6 +,0,2004},{7,0,921},{8,0,580},{8,0,593},{8,0,630},{10,0,28},{5,11,411},{135,11, +653},{4,10,932},{133,10,891},{4,0,911},{5,0,867},{5,0,1013},{7,0,2034},{8,0,798} +,{136,0,813},{7,11,439},{10,11,727},{11,11,260},{139,11,684},{136,10,625},{5,11, +208},{7,11,753},{135,11,1528},{5,0,461},{7,0,1925},{12,0,39},{13,0,265},{13,0, +439},{134,10,76},{6,0,853},{8,10,92},{137,10,221},{5,0,135},{6,0,519},{7,0,1722} +,{10,0,271},{11,0,261},{145,0,54},{139,11,814},{14,0,338},{148,0,81},{4,0,300},{ +133,0,436},{5,0,419},{5,0,687},{7,0,864},{9,0,470},{135,11,864},{9,0,836},{133, +11,242},{134,0,1937},{4,10,763},{133,11,953},{132,10,622},{132,0,393},{133,10, +253},{8,0,357},{10,0,745},{14,0,426},{17,0,94},{19,0,57},{135,10,546},{5,11,615} +,{146,11,37},{9,10,73},{10,10,110},{14,10,185},{145,10,119},{11,0,703},{7,10,624 +},{7,10,916},{10,10,256},{139,10,87},{133,11,290},{5,10,212},{12,10,35},{141,10, +382},{132,11,380},{5,11,52},{7,11,277},{9,11,368},{139,11,791},{133,0,387},{10, +11,138},{139,11,476},{4,0,6},{5,0,708},{136,0,75},{7,0,1351},{9,0,581},{10,0,639 +},{11,0,453},{140,0,584},{132,0,303},{138,0,772},{135,10,1175},{4,0,749},{5,10, +816},{6,11,256},{7,11,307},{7,11,999},{7,11,1481},{7,11,1732},{7,11,1738},{8,11, +265},{9,11,414},{11,11,316},{12,11,52},{13,11,420},{147,11,100},{135,11,1296},{6 +,0,1065},{5,10,869},{5,10,968},{6,10,1626},{8,10,734},{136,10,784},{4,10,542},{6 +,10,1716},{6,10,1727},{7,10,1082},{7,10,1545},{8,10,56},{8,10,118},{8,10,412},{8 +,10,564},{9,10,888},{9,10,908},{10,10,50},{10,10,423},{11,10,685},{11,10,697},{ +11,10,933},{12,10,299},{13,10,126},{13,10,136},{13,10,170},{141,10,190},{134,0, +226},{4,0,106},{7,0,310},{11,0,717},{133,11,723},{5,0,890},{5,0,988},{4,10,232}, +{9,10,202},{10,10,474},{140,10,433},{6,0,626},{142,0,431},{10,0,706},{150,0,44}, +{13,0,51},{6,10,108},{7,10,1003},{7,10,1181},{8,10,111},{136,10,343},{132,0,698} +,{5,11,109},{6,11,1784},{7,11,1895},{12,11,296},{140,11,302},{134,0,828},{134,10 +,1712},{138,0,17},{7,0,1929},{4,10,133},{5,11,216},{7,10,711},{7,10,1298},{7,10, +1585},{7,11,1879},{9,11,141},{9,11,270},{9,11,679},{10,11,159},{10,11,553},{11, +11,197},{11,11,438},{12,11,538},{12,11,559},{13,11,193},{13,11,423},{14,11,144}, +{14,11,166},{14,11,167},{15,11,67},{147,11,84},{141,11,127},{7,11,1872},{137,11, +81},{6,10,99},{7,10,1808},{145,10,57},{134,11,391},{5,0,689},{6,0,84},{7,0,1250} +,{6,10,574},{7,10,428},{10,10,669},{11,10,485},{11,10,840},{12,10,300},{142,10, +250},{7,11,322},{136,11,249},{7,11,432},{135,11,1649},{135,10,1871},{137,10,252} +,{6,11,155},{140,11,234},{7,0,871},{19,0,27},{147,11,27},{140,0,498},{5,0,986},{ +6,0,130},{138,0,823},{6,0,1793},{7,0,1582},{8,0,458},{10,0,101},{10,0,318},{10,0 +,945},{12,0,734},{16,0,104},{18,0,177},{6,10,323},{135,10,1564},{5,11,632},{138, +11,526},{10,0,435},{7,10,461},{136,10,775},{6,11,144},{7,11,948},{7,11,1042},{7, +11,1857},{8,11,235},{8,11,461},{9,11,453},{9,11,530},{10,11,354},{17,11,77},{19, +11,99},{148,11,79},{138,0,966},{7,0,1644},{137,0,129},{135,0,997},{136,0,502},{5 +,11,196},{6,11,486},{7,11,212},{8,11,309},{136,11,346},{7,10,727},{146,10,73},{ +132,0,823},{132,11,686},{135,0,1927},{4,0,762},{7,0,1756},{137,0,98},{136,10,577 +},{24,0,8},{4,11,30},{5,11,43},{152,11,8},{7,0,1046},{139,0,160},{7,0,492},{4,10 +,413},{5,10,677},{7,11,492},{8,10,432},{140,10,280},{6,0,45},{7,0,433},{8,0,129} +,{9,0,21},{10,0,392},{11,0,79},{12,0,499},{13,0,199},{141,0,451},{7,0,558},{136, +0,353},{4,11,220},{7,11,1535},{9,11,93},{139,11,474},{7,10,646},{7,10,1730},{11, +10,446},{141,10,178},{133,0,785},{134,0,1145},{8,0,81},{9,0,189},{9,0,201},{11,0 +,478},{11,0,712},{141,0,338},{5,0,353},{151,0,26},{11,0,762},{132,10,395},{134,0 +,2024},{4,0,611},{133,0,606},{9,10,174},{10,10,164},{11,10,440},{11,10,841},{143 +,10,98},{134,10,426},{10,10,608},{139,10,1002},{138,10,250},{6,0,25},{7,0,855},{ +7,0,1258},{144,0,32},{7,11,1725},{138,11,393},{5,11,263},{134,11,414},{6,0,2011} +,{133,10,476},{4,0,4},{7,0,1118},{7,0,1320},{7,0,1706},{8,0,277},{9,0,622},{10,0 +,9},{11,0,724},{12,0,350},{12,0,397},{13,0,28},{13,0,159},{15,0,89},{18,0,5},{19 +,0,9},{20,0,34},{22,0,47},{6,11,178},{6,11,1750},{8,11,251},{9,11,690},{10,11, +155},{10,11,196},{10,11,373},{11,11,698},{13,11,155},{148,11,93},{5,11,97},{137, +11,393},{7,0,764},{11,0,461},{12,0,172},{5,10,76},{6,10,458},{6,10,497},{7,10, +868},{9,10,658},{10,10,594},{11,10,566},{12,10,338},{141,10,200},{134,0,1449},{ +138,11,40},{134,11,1639},{134,0,1445},{6,0,1168},{4,10,526},{7,10,1029},{135,10, +1054},{4,11,191},{7,11,934},{8,11,647},{145,11,97},{132,10,636},{6,0,233},{7,10, +660},{7,10,1124},{17,10,31},{19,10,22},{151,10,14},{6,10,1699},{136,11,110},{12, +11,246},{15,11,162},{19,11,64},{20,11,8},{20,11,95},{22,11,24},{152,11,17},{5,11 +,165},{9,11,346},{138,11,655},{5,11,319},{135,11,534},{134,0,255},{9,0,216},{8, +11,128},{139,11,179},{9,0,183},{139,0,286},{11,0,956},{151,0,3},{4,0,536},{7,0, +1141},{10,0,723},{139,0,371},{4,10,279},{7,10,301},{137,10,362},{7,0,285},{5,11, +57},{6,11,101},{6,11,1663},{7,11,132},{7,11,1048},{7,11,1154},{7,11,1415},{7,11, +1507},{12,11,493},{15,11,105},{151,11,15},{5,11,459},{7,11,1073},{7,10,1743},{8, +11,241},{136,11,334},{4,10,178},{133,10,399},{135,0,560},{132,0,690},{135,0,1246 +},{18,0,157},{147,0,63},{10,0,599},{11,0,33},{12,0,571},{149,0,1},{6,11,324},{6, +11,520},{7,11,338},{7,11,1616},{7,11,1729},{8,11,228},{9,11,69},{139,11,750},{7, +0,1862},{12,0,491},{12,0,520},{13,0,383},{142,0,244},{135,11,734},{134,10,1692}, +{10,0,448},{11,0,630},{17,0,117},{6,10,202},{7,11,705},{12,10,360},{17,10,118},{ +18,10,27},{148,10,67},{4,11,73},{6,11,612},{7,11,927},{7,11,1822},{8,11,217},{9, +11,472},{9,11,765},{9,11,766},{10,11,408},{11,11,51},{11,11,793},{12,11,266},{15 +,11,158},{20,11,89},{150,11,32},{4,0,190},{133,0,554},{133,0,1001},{5,11,389},{8 +,11,636},{137,11,229},{5,0,446},{7,10,872},{10,10,516},{139,10,167},{137,10,313} +,{132,10,224},{134,0,1313},{5,10,546},{7,10,35},{8,10,11},{8,10,12},{9,10,315},{ +9,10,533},{10,10,802},{11,10,166},{12,10,525},{142,10,243},{6,0,636},{137,0,837} +,{5,10,241},{8,10,242},{9,10,451},{10,10,667},{11,10,598},{140,10,429},{22,10,46 +},{150,11,46},{136,11,472},{11,0,278},{142,0,73},{141,11,185},{132,0,868},{134,0 +,972},{4,10,366},{137,10,516},{138,0,1010},{5,11,189},{6,10,1736},{7,11,442},{7, +11,443},{8,11,281},{12,11,174},{13,11,83},{141,11,261},{139,11,384},{6,11,2},{7, +11,191},{7,11,446},{7,11,758},{7,11,1262},{7,11,1737},{8,11,22},{8,11,270},{8,11 +,612},{9,11,4},{9,11,167},{9,11,312},{9,11,436},{10,11,156},{10,11,216},{10,11, +311},{10,11,623},{11,11,72},{11,11,330},{11,11,455},{12,11,101},{12,11,321},{12, +11,504},{12,11,530},{12,11,543},{13,11,17},{13,11,156},{13,11,334},{14,11,48},{ +15,11,70},{17,11,60},{148,11,64},{6,10,331},{136,10,623},{135,0,1231},{132,0,304 +},{6,11,60},{7,11,670},{7,11,1327},{8,11,411},{8,11,435},{9,11,653},{9,11,740},{ +10,11,385},{11,11,222},{11,11,324},{11,11,829},{140,11,611},{7,0,506},{6,11,166} +,{7,11,374},{135,11,1174},{14,11,43},{146,11,21},{135,11,1694},{135,10,1888},{5, +11,206},{134,11,398},{135,11,50},{150,0,26},{6,0,53},{6,0,199},{7,0,1408},{8,0, +32},{8,0,93},{10,0,397},{10,0,629},{11,0,593},{11,0,763},{13,0,326},{145,0,35},{ +134,0,105},{132,10,394},{4,0,843},{138,0,794},{11,0,704},{141,0,396},{5,0,114},{ +5,0,255},{141,0,285},{6,0,619},{7,0,898},{7,0,1092},{8,0,485},{18,0,28},{19,0, +116},{135,10,1931},{9,0,145},{7,10,574},{135,10,1719},{7,0,2035},{8,0,19},{9,0, +89},{138,0,831},{132,10,658},{6,11,517},{7,11,1159},{10,11,621},{139,11,192},{7, +0,1933},{7,11,1933},{9,10,781},{10,10,144},{11,10,385},{13,10,161},{13,10,228},{ +13,10,268},{148,10,107},{136,10,374},{10,11,223},{139,11,645},{135,0,1728},{7,11 +,64},{7,11,289},{136,11,245},{4,10,344},{6,10,498},{139,10,323},{136,0,746},{135 +,10,1063},{137,10,155},{4,0,987},{6,0,1964},{6,0,1974},{6,0,1990},{136,0,995},{ +133,11,609},{133,10,906},{134,0,1550},{134,0,874},{5,11,129},{6,11,61},{135,11, +947},{4,0,1018},{6,0,1938},{6,0,2021},{134,0,2039},{132,0,814},{11,0,126},{139,0 +,287},{134,0,1264},{5,0,955},{136,0,814},{141,11,506},{132,11,314},{6,0,981},{ +139,11,1000},{5,0,56},{8,0,892},{8,0,915},{140,0,776},{148,0,100},{10,0,4},{10,0 +,13},{11,0,638},{148,0,57},{148,11,74},{5,0,738},{132,10,616},{133,11,637},{136, +10,692},{133,0,758},{132,10,305},{137,11,590},{5,11,280},{135,11,1226},{134,11, +494},{135,0,1112},{133,11,281},{13,0,44},{14,0,214},{5,10,214},{7,10,603},{8,10, +611},{9,10,686},{10,10,88},{11,10,459},{11,10,496},{12,10,463},{140,10,590},{139 +,0,328},{135,11,1064},{137,0,133},{7,0,168},{13,0,196},{141,0,237},{134,10,1703} +,{134,0,1152},{135,0,1245},{5,0,110},{6,0,169},{6,0,1702},{7,0,400},{8,0,538},{9 +,0,184},{9,0,524},{140,0,218},{6,0,1816},{10,0,871},{12,0,769},{140,0,785},{132, +11,630},{7,11,33},{7,11,120},{8,11,489},{9,11,319},{10,11,820},{11,11,1004},{12, +11,379},{13,11,117},{13,11,412},{14,11,25},{15,11,52},{15,11,161},{16,11,47},{ +149,11,2},{6,0,133},{8,0,413},{9,0,353},{139,0,993},{145,10,19},{4,11,937},{133, +11,801},{134,0,978},{6,0,93},{6,0,1508},{7,0,1422},{7,0,1851},{8,0,673},{9,0,529 +},{140,0,43},{6,0,317},{10,0,512},{4,10,737},{11,10,294},{12,10,60},{12,10,437}, +{13,10,64},{13,10,380},{142,10,430},{9,0,371},{7,11,1591},{144,11,43},{6,10,1758 +},{8,10,520},{9,10,345},{9,10,403},{142,10,350},{5,0,526},{10,10,242},{138,10, +579},{9,0,25},{10,0,467},{138,0,559},{5,10,139},{7,10,1168},{138,10,539},{4,0, +335},{135,0,942},{140,0,754},{132,11,365},{11,0,182},{142,0,195},{142,11,29},{5, +11,7},{139,11,774},{4,11,746},{135,11,1090},{8,0,39},{10,0,773},{11,0,84},{12,0, +205},{142,0,1},{5,0,601},{5,0,870},{5,11,360},{136,11,237},{132,0,181},{136,0, +370},{134,0,1652},{8,0,358},{4,10,107},{7,10,613},{8,10,439},{8,10,504},{9,10, +501},{10,10,383},{139,10,477},{132,10,229},{137,11,785},{4,0,97},{5,0,147},{6,0, +286},{7,0,1362},{141,0,176},{6,0,537},{7,0,788},{7,0,1816},{132,10,903},{140,10, +71},{6,0,743},{134,0,1223},{6,0,375},{7,0,169},{7,0,254},{8,0,780},{135,11,1493} +,{7,0,1714},{4,10,47},{6,10,373},{7,10,452},{7,10,543},{7,10,1856},{9,10,6},{11, +10,257},{139,10,391},{6,0,896},{136,0,1003},{135,0,1447},{137,11,341},{5,10,980} +,{134,10,1754},{145,11,22},{4,11,277},{5,11,608},{6,11,493},{7,11,457},{140,11, +384},{7,10,536},{7,10,1331},{136,10,143},{140,0,744},{7,11,27},{135,11,316},{18, +0,126},{5,10,19},{134,10,533},{4,0,788},{11,0,41},{5,11,552},{5,11,586},{5,11, +676},{6,11,448},{8,11,244},{11,11,1},{11,11,41},{13,11,3},{16,11,54},{17,11,4},{ +146,11,13},{4,0,985},{6,0,1801},{4,11,401},{137,11,264},{5,10,395},{5,10,951},{ +134,10,1776},{5,0,629},{135,0,1549},{11,10,663},{12,10,210},{13,10,166},{13,10, +310},{14,10,373},{147,10,43},{9,11,543},{10,11,524},{11,11,30},{12,11,524},{14, +11,315},{16,11,18},{20,11,26},{148,11,65},{4,11,205},{5,11,623},{7,11,104},{136, +11,519},{5,0,293},{134,0,601},{7,11,579},{9,11,41},{9,11,244},{9,11,669},{10,11, +5},{11,11,861},{11,11,951},{139,11,980},{132,11,717},{132,10,695},{7,10,497},{9, +10,387},{147,10,81},{132,0,420},{142,0,37},{6,0,1134},{6,0,1900},{12,0,830},{12, +0,878},{12,0,894},{15,0,221},{143,0,245},{132,11,489},{7,0,1570},{140,0,542},{8, +0,933},{136,0,957},{6,0,1371},{7,0,31},{8,0,373},{5,10,284},{6,10,49},{6,10,350} +,{7,10,377},{7,10,1693},{8,10,678},{9,10,161},{9,10,585},{9,10,671},{9,10,839},{ +11,10,912},{141,10,427},{135,11,892},{4,0,325},{138,0,125},{139,11,47},{132,10, +597},{138,0,323},{6,0,1547},{7,11,1605},{9,11,473},{11,11,962},{146,11,139},{139 +,10,908},{7,11,819},{9,11,26},{9,11,392},{10,11,152},{10,11,226},{11,11,19},{12, +11,276},{12,11,426},{12,11,589},{13,11,460},{15,11,97},{19,11,48},{148,11,104},{ +135,11,51},{4,0,718},{135,0,1216},{6,0,1896},{6,0,1905},{6,0,1912},{9,0,947},{9, +0,974},{12,0,809},{12,0,850},{12,0,858},{12,0,874},{12,0,887},{12,0,904},{12,0, +929},{12,0,948},{12,0,952},{15,0,198},{15,0,206},{15,0,220},{15,0,227},{15,0,247 +},{18,0,188},{21,0,48},{21,0,50},{24,0,25},{24,0,29},{7,11,761},{7,11,1051},{137 +,11,545},{5,0,124},{5,0,144},{6,0,548},{7,0,15},{7,0,153},{137,0,629},{135,11, +606},{135,10,2014},{7,10,2007},{9,11,46},{9,10,101},{9,10,450},{10,10,66},{10,10 +,842},{11,10,536},{140,10,587},{6,0,75},{7,0,1531},{8,0,416},{9,0,240},{9,0,275} +,{10,0,100},{11,0,658},{11,0,979},{12,0,86},{14,0,207},{15,0,20},{143,0,25},{5,0 +,141},{5,0,915},{6,0,1783},{7,0,211},{7,0,698},{7,0,1353},{9,0,83},{9,0,281},{10 +,0,376},{10,0,431},{11,0,543},{12,0,664},{13,0,280},{13,0,428},{14,0,61},{14,0, +128},{17,0,52},{145,0,81},{132,11,674},{135,0,533},{149,0,6},{132,11,770},{133,0 +,538},{5,11,79},{7,11,1027},{7,11,1477},{139,11,52},{139,10,62},{4,0,338},{133,0 +,400},{5,11,789},{134,11,195},{4,11,251},{4,11,688},{7,11,513},{7,11,1284},{9,11 +,87},{138,11,365},{134,10,1766},{6,0,0},{7,0,84},{11,0,895},{145,0,11},{139,0, +892},{4,0,221},{5,0,659},{7,0,697},{7,0,1211},{138,0,284},{133,0,989},{133,11, +889},{4,11,160},{5,11,330},{7,11,1434},{136,11,174},{6,10,1665},{7,10,256},{7,10 +,1388},{10,10,499},{139,10,670},{7,0,848},{4,10,22},{5,10,10},{136,10,97},{138,0 +,507},{133,10,481},{4,0,188},{135,0,805},{5,0,884},{6,0,732},{139,0,991},{135,11 +,968},{11,11,636},{15,11,145},{17,11,34},{19,11,50},{151,11,20},{7,0,959},{16,0, +60},{6,10,134},{7,10,437},{9,10,37},{14,10,285},{142,10,371},{7,10,486},{8,10, +155},{11,10,93},{140,10,164},{134,0,1653},{7,0,337},{133,10,591},{6,0,1989},{8,0 +,922},{8,0,978},{133,11,374},{132,0,638},{138,0,500},{133,11,731},{5,10,380},{5, +10,650},{136,10,310},{138,11,381},{4,10,364},{7,10,1156},{7,10,1187},{137,10,409 +},{137,11,224},{140,0,166},{134,10,482},{4,11,626},{5,11,642},{6,11,425},{10,11, +202},{139,11,141},{4,10,781},{6,10,487},{7,10,926},{8,10,263},{139,10,500},{135, +0,418},{4,10,94},{135,10,1265},{136,0,760},{132,10,417},{136,11,835},{5,10,348}, +{134,10,522},{6,0,1277},{134,0,1538},{139,11,541},{135,11,1597},{5,11,384},{8,11 +,455},{140,11,48},{136,0,770},{5,11,264},{134,11,184},{4,0,89},{5,0,489},{6,0, +315},{7,0,553},{7,0,1745},{138,0,243},{4,10,408},{4,10,741},{135,10,500},{134,0, +1396},{133,0,560},{6,0,1658},{9,0,3},{10,0,154},{11,0,641},{13,0,85},{13,0,201}, +{141,0,346},{135,11,1595},{5,11,633},{6,11,28},{7,11,219},{135,11,1323},{9,11, +769},{140,11,185},{135,11,785},{7,11,359},{8,11,243},{140,11,175},{138,0,586},{7 +,0,1271},{134,10,73},{132,11,105},{4,0,166},{5,0,505},{134,0,1670},{133,10,576}, +{4,11,324},{138,11,104},{142,10,231},{6,0,637},{7,10,1264},{7,10,1678},{11,10, +945},{12,10,341},{12,10,471},{12,10,569},{23,11,21},{151,11,23},{8,11,559},{141, +11,109},{134,0,1947},{7,0,445},{8,0,307},{8,0,704},{10,0,41},{10,0,439},{11,0, +237},{11,0,622},{140,0,201},{135,11,963},{135,0,1977},{4,0,189},{5,0,713},{136,0 +,57},{138,0,371},{135,10,538},{132,0,552},{6,0,883},{133,10,413},{6,0,923},{132, +11,758},{138,11,215},{136,10,495},{7,10,54},{8,10,312},{10,10,191},{10,10,614},{ +140,10,567},{7,11,351},{139,11,128},{7,0,875},{6,10,468},{7,10,1478},{8,10,530}, +{142,10,290},{135,0,1788},{17,0,49},{133,11,918},{12,11,398},{20,11,39},{21,11, +11},{150,11,41},{10,0,661},{6,10,484},{135,10,822},{135,0,1945},{134,0,794},{137 +,10,900},{135,10,1335},{6,10,1724},{135,10,2022},{132,11,340},{134,0,1135},{4,0, +784},{133,0,745},{5,0,84},{134,0,163},{133,0,410},{4,0,976},{5,11,985},{7,11,509 +},{7,11,529},{145,11,96},{132,10,474},{134,0,703},{135,11,1919},{5,0,322},{8,0, +186},{9,0,262},{10,0,187},{142,0,208},{135,10,1504},{133,0,227},{9,0,560},{13,0, +208},{133,10,305},{132,11,247},{7,0,1395},{8,0,486},{9,0,236},{9,0,878},{10,0, +218},{11,0,95},{19,0,17},{147,0,31},{7,0,2043},{8,0,672},{141,0,448},{4,11,184}, +{5,11,390},{6,11,337},{7,11,23},{7,11,494},{7,11,618},{7,11,1456},{8,11,27},{8, +11,599},{10,11,153},{139,11,710},{135,0,466},{135,10,1236},{6,0,167},{7,0,186},{ +7,0,656},{10,0,643},{4,10,480},{6,10,302},{6,10,1642},{7,10,837},{7,10,1547},{7, +10,1657},{8,10,429},{9,10,228},{13,10,289},{13,10,343},{147,10,101},{134,0,1428} +,{134,0,1440},{5,0,412},{7,10,278},{10,10,739},{11,10,708},{141,10,348},{134,0, +1118},{136,0,562},{148,11,46},{9,0,316},{139,0,256},{134,0,1771},{135,0,1190},{ +137,0,132},{10,11,227},{11,11,497},{11,11,709},{140,11,415},{143,0,66},{6,11,360 +},{7,11,1664},{136,11,478},{144,10,28},{4,0,317},{135,0,1279},{5,0,63},{133,0, +509},{136,11,699},{145,10,36},{134,0,1475},{11,11,343},{142,11,127},{132,11,739} +,{132,0,288},{135,11,1757},{8,0,89},{8,0,620},{9,0,608},{11,0,628},{12,0,322},{ +143,0,124},{134,0,1225},{7,0,1189},{4,11,67},{5,11,422},{6,10,363},{7,11,1037},{ +7,11,1289},{7,11,1555},{7,10,1955},{8,10,725},{9,11,741},{145,11,108},{134,0, +1468},{6,0,689},{134,0,1451},{138,0,120},{151,0,1},{137,10,805},{142,0,329},{5, +10,813},{135,10,2046},{135,0,226},{138,11,96},{7,0,1855},{5,10,712},{11,10,17},{ +13,10,321},{144,10,67},{9,0,461},{6,10,320},{7,10,781},{7,10,1921},{9,10,55},{10 +,10,186},{10,10,273},{10,10,664},{10,10,801},{11,10,996},{11,10,997},{13,10,157} +,{142,10,170},{8,11,203},{8,10,271},{11,11,823},{11,11,846},{12,11,482},{13,11, +133},{13,11,277},{13,11,302},{13,11,464},{14,11,205},{142,11,221},{135,0,1346},{ +4,11,449},{133,11,718},{134,0,85},{14,0,299},{7,10,103},{7,10,863},{11,10,184},{ +145,10,62},{4,11,355},{6,11,311},{9,11,256},{138,11,404},{137,10,659},{138,11, +758},{133,11,827},{5,11,64},{140,11,581},{134,0,1171},{4,11,442},{7,11,1047},{7, +11,1352},{135,11,1643},{132,0,980},{5,11,977},{6,11,288},{7,11,528},{135,11,1065 +},{5,0,279},{6,0,235},{7,0,468},{8,0,446},{9,0,637},{10,0,717},{11,0,738},{140,0 +,514},{132,0,293},{11,10,337},{142,10,303},{136,11,285},{5,0,17},{6,0,371},{9,0, +528},{12,0,364},{132,11,254},{5,10,77},{7,10,1455},{10,10,843},{147,10,73},{150, +0,5},{132,10,458},{6,11,12},{7,11,1219},{145,11,73},{135,10,1420},{6,10,109},{ +138,10,382},{135,11,125},{6,10,330},{7,10,1084},{139,10,142},{6,11,369},{6,11, +502},{7,11,1036},{8,11,348},{9,11,452},{10,11,26},{11,11,224},{11,11,387},{11,11 +,772},{12,11,95},{12,11,629},{13,11,195},{13,11,207},{13,11,241},{14,11,260},{14 +,11,270},{143,11,140},{132,11,269},{5,11,480},{7,11,532},{7,11,1197},{7,11,1358} +,{8,11,291},{11,11,349},{142,11,396},{150,0,48},{10,0,601},{13,0,353},{141,0,376 +},{5,0,779},{5,0,807},{6,0,1655},{134,0,1676},{142,11,223},{4,0,196},{5,0,558},{ +133,0,949},{148,11,15},{135,11,1764},{134,0,1322},{132,0,752},{139,0,737},{135, +11,657},{136,11,533},{135,0,412},{4,0,227},{5,0,159},{5,0,409},{7,0,80},{8,0,556 +},{10,0,479},{12,0,418},{14,0,50},{14,0,123},{14,0,192},{14,0,249},{14,0,295},{ +143,0,27},{7,0,1470},{8,0,66},{8,0,137},{8,0,761},{9,0,638},{11,0,80},{11,0,212} +,{11,0,368},{11,0,418},{12,0,8},{13,0,15},{16,0,61},{17,0,59},{19,0,28},{148,0, +84},{135,10,1985},{4,11,211},{4,11,332},{5,11,335},{6,11,238},{7,11,269},{7,11, +811},{7,11,1797},{8,10,122},{8,11,836},{9,11,507},{141,11,242},{6,0,683},{134,0, +1252},{4,0,873},{132,10,234},{134,0,835},{6,0,38},{7,0,1220},{8,0,185},{8,0,256} +,{9,0,22},{9,0,331},{10,0,738},{11,0,205},{11,0,540},{11,0,746},{13,0,465},{14,0 +,88},{142,0,194},{138,0,986},{5,11,1009},{12,11,582},{146,11,131},{4,0,159},{6,0 +,115},{7,0,252},{7,0,257},{7,0,1928},{8,0,69},{9,0,384},{10,0,91},{10,0,615},{12 +,0,375},{14,0,235},{18,0,117},{147,0,123},{133,0,911},{136,0,278},{5,10,430},{5, +10,932},{6,10,131},{7,10,417},{9,10,522},{11,10,314},{141,10,390},{14,10,149},{ +14,10,399},{143,10,57},{4,0,151},{7,0,1567},{136,0,749},{5,11,228},{6,11,203},{7 +,11,156},{8,11,347},{137,11,265},{132,10,507},{10,0,989},{140,0,956},{133,0,990} +,{5,0,194},{6,0,927},{7,0,1662},{9,0,90},{140,0,564},{4,10,343},{133,10,511},{ +133,0,425},{7,10,455},{138,10,591},{4,0,774},{7,11,476},{7,11,1592},{138,11,87}, +{5,0,971},{135,10,1381},{5,11,318},{147,11,121},{5,11,291},{7,11,765},{9,11,389} +,{140,11,548},{134,10,575},{4,0,827},{12,0,646},{12,0,705},{12,0,712},{140,0,714 +},{139,0,752},{137,0,662},{5,0,72},{6,0,264},{7,0,21},{7,0,46},{7,0,2013},{8,0, +215},{8,0,513},{10,0,266},{139,0,22},{139,11,522},{6,0,239},{7,0,118},{10,0,95}, +{11,0,603},{13,0,443},{14,0,160},{143,0,4},{6,0,431},{134,0,669},{7,10,1127},{7, +10,1572},{10,10,297},{10,10,422},{11,10,764},{11,10,810},{12,10,264},{13,10,102} +,{13,10,300},{13,10,484},{14,10,147},{14,10,229},{17,10,71},{18,10,118},{147,10, +120},{5,0,874},{6,0,1677},{15,0,0},{10,11,525},{139,11,82},{6,0,65},{7,0,939},{7 +,0,1172},{7,0,1671},{9,0,540},{10,0,696},{11,0,265},{11,0,732},{11,0,928},{11,0, +937},{141,0,438},{134,0,1350},{136,11,547},{132,11,422},{5,11,355},{145,11,0},{ +137,11,905},{5,0,682},{135,0,1887},{132,0,809},{4,0,696},{133,11,865},{6,0,1074} +,{6,0,1472},{14,10,35},{142,10,191},{5,11,914},{134,11,1625},{133,11,234},{135, +11,1383},{137,11,780},{132,10,125},{4,0,726},{133,0,630},{8,0,802},{136,0,838},{ +132,10,721},{6,0,1337},{7,0,776},{19,0,56},{136,10,145},{132,0,970},{7,10,792},{ +8,10,147},{10,10,821},{139,10,1021},{139,10,970},{8,0,940},{137,0,797},{135,11, +1312},{9,0,248},{10,0,400},{7,11,816},{7,11,1241},{7,10,1999},{9,11,283},{9,11, +520},{10,11,213},{10,11,307},{10,11,463},{10,11,671},{10,11,746},{11,11,401},{11 +,11,794},{12,11,517},{18,11,107},{147,11,115},{6,0,1951},{134,0,2040},{135,11, +339},{13,0,41},{15,0,93},{5,10,168},{5,10,930},{8,10,74},{9,10,623},{12,10,500}, +{140,10,579},{6,0,118},{7,0,215},{7,0,1521},{140,0,11},{6,10,220},{7,10,1101},{ +141,10,105},{6,11,421},{7,11,61},{7,11,1540},{10,11,11},{138,11,501},{7,0,615},{ +138,0,251},{140,11,631},{135,0,1044},{6,10,19},{7,10,1413},{139,10,428},{133,0, +225},{7,10,96},{8,10,401},{8,10,703},{137,10,896},{145,10,116},{6,11,102},{7,11, +72},{15,11,142},{147,11,67},{7,10,1961},{7,10,1965},{8,10,702},{136,10,750},{7, +10,2030},{8,10,150},{8,10,737},{12,10,366},{151,11,30},{4,0,370},{5,0,756},{7,0, +1326},{135,11,823},{8,10,800},{9,10,148},{9,10,872},{9,10,890},{11,10,309},{11, +10,1001},{13,10,267},{141,10,323},{6,0,1662},{7,0,48},{8,0,771},{10,0,116},{13,0 +,104},{14,0,105},{14,0,184},{15,0,168},{19,0,92},{148,0,68},{10,0,209},{135,11, +1870},{7,11,68},{8,11,48},{8,11,88},{8,11,582},{8,11,681},{9,11,373},{9,11,864}, +{11,11,157},{11,11,336},{11,11,843},{148,11,27},{134,0,930},{4,11,88},{5,11,137} +,{5,11,174},{5,11,777},{6,11,1664},{6,11,1725},{7,11,77},{7,11,426},{7,11,1317}, +{7,11,1355},{8,11,126},{8,11,563},{9,11,523},{9,11,750},{10,11,310},{10,11,836}, +{11,11,42},{11,11,318},{11,11,731},{12,11,68},{12,11,92},{12,11,507},{12,11,692} +,{13,11,81},{13,11,238},{13,11,374},{18,11,138},{19,11,78},{19,11,111},{20,11,55 +},{20,11,77},{148,11,92},{4,11,938},{135,11,1831},{5,10,547},{7,10,424},{8,11, +617},{138,11,351},{6,0,1286},{6,11,1668},{7,11,1499},{8,11,117},{9,11,314},{138, +11,174},{6,0,759},{6,0,894},{7,11,707},{139,11,563},{4,0,120},{135,0,1894},{9,0, +385},{149,0,17},{138,0,429},{133,11,403},{5,0,820},{135,0,931},{10,0,199},{133, +10,133},{6,0,151},{6,0,1675},{7,0,383},{151,0,10},{6,0,761},{136,10,187},{8,0, +365},{10,10,0},{10,10,818},{139,10,988},{4,11,44},{5,11,311},{6,11,156},{7,11, +639},{7,11,762},{7,11,1827},{9,11,8},{9,11,462},{148,11,83},{4,11,346},{7,11,115 +},{9,11,180},{9,11,456},{138,11,363},{136,10,685},{7,0,1086},{145,0,46},{6,0, +1624},{11,0,11},{12,0,422},{13,0,444},{142,0,360},{6,0,1020},{6,0,1260},{134,0, +1589},{4,0,43},{5,0,344},{5,0,357},{14,0,472},{150,0,58},{6,0,1864},{6,0,1866},{ +6,0,1868},{6,0,1869},{6,0,1874},{6,0,1877},{6,0,1903},{6,0,1911},{9,0,920},{9,0, +921},{9,0,924},{9,0,946},{9,0,959},{9,0,963},{9,0,970},{9,0,997},{9,0,1008},{9,0 +,1017},{12,0,795},{12,0,797},{12,0,798},{12,0,800},{12,0,803},{12,0,811},{12,0, +820},{12,0,821},{12,0,839},{12,0,841},{12,0,848},{12,0,911},{12,0,921},{12,0,922 +},{12,0,925},{12,0,937},{12,0,944},{12,0,945},{12,0,953},{15,0,184},{15,0,191},{ +15,0,199},{15,0,237},{15,0,240},{15,0,243},{15,0,246},{18,0,203},{21,0,40},{21,0 +,52},{21,0,57},{24,0,23},{24,0,28},{152,0,30},{134,0,725},{145,11,58},{133,0,888 +},{137,10,874},{4,0,711},{8,10,774},{10,10,670},{140,10,51},{144,11,40},{6,11, +185},{7,11,1899},{139,11,673},{137,10,701},{137,0,440},{4,11,327},{5,11,478},{7, +11,1332},{8,11,753},{140,11,227},{4,10,127},{5,10,350},{6,10,356},{8,10,426},{9, +10,572},{10,10,247},{139,10,312},{5,11,1020},{133,11,1022},{4,11,103},{133,11, +401},{6,0,1913},{6,0,1926},{6,0,1959},{9,0,914},{9,0,939},{9,0,952},{9,0,979},{9 +,0,990},{9,0,998},{9,0,1003},{9,0,1023},{12,0,827},{12,0,834},{12,0,845},{12,0, +912},{12,0,935},{12,0,951},{15,0,172},{15,0,174},{18,0,198},{149,0,63},{5,0,958} +,{5,0,987},{4,11,499},{135,11,1421},{7,0,885},{6,10,59},{6,10,1762},{9,10,603},{ +141,10,397},{10,11,62},{141,11,164},{4,0,847},{135,0,326},{11,0,276},{142,0,293} +,{4,0,65},{5,0,479},{5,0,1004},{7,0,1913},{8,0,317},{9,0,302},{10,0,612},{13,0, +22},{132,11,96},{4,0,261},{135,0,510},{135,0,1514},{6,10,111},{7,10,4},{8,10,163 +},{8,10,776},{138,10,566},{4,0,291},{9,0,515},{12,0,152},{12,0,443},{13,0,392},{ +142,0,357},{7,11,399},{135,11,1492},{4,0,589},{139,0,282},{6,11,563},{135,10, +1994},{5,10,297},{135,10,1038},{4,0,130},{7,0,843},{135,0,1562},{5,0,42},{5,0, +879},{7,0,245},{7,0,324},{7,0,1532},{11,0,463},{11,0,472},{13,0,363},{144,0,52}, +{4,0,134},{133,0,372},{133,0,680},{136,10,363},{6,0,1997},{8,0,935},{136,0,977}, +{4,0,810},{135,0,1634},{135,10,1675},{7,0,1390},{4,11,910},{133,11,832},{7,10, +808},{8,11,266},{139,11,578},{132,0,644},{4,0,982},{138,0,867},{132,10,280},{135 +,0,540},{140,10,54},{135,0,123},{134,0,1978},{4,10,421},{133,10,548},{6,0,623},{ +136,0,789},{4,0,908},{5,0,359},{5,0,508},{6,0,1723},{7,0,343},{7,0,1996},{135,0, +2026},{134,0,1220},{4,0,341},{135,0,480},{6,10,254},{9,10,109},{138,10,103},{134 +,0,888},{8,11,528},{137,11,348},{7,0,1995},{8,0,299},{11,0,890},{12,0,674},{4,11 +,20},{133,11,616},{135,11,1094},{134,10,1630},{4,0,238},{5,0,503},{6,0,179},{7,0 +,2003},{8,0,381},{8,0,473},{9,0,149},{10,0,788},{15,0,45},{15,0,86},{20,0,110},{ +150,0,57},{133,10,671},{4,11,26},{5,11,429},{6,11,245},{7,11,704},{7,11,1379},{ +135,11,1474},{4,0,121},{5,0,156},{5,0,349},{9,0,431},{10,0,605},{142,0,342},{7, +11,943},{139,11,614},{132,10,889},{132,11,621},{7,10,1382},{7,11,1382},{135,10, +1910},{132,10,627},{133,10,775},{133,11,542},{133,11,868},{136,11,433},{6,0,1373 +},{7,0,1011},{11,10,362},{11,10,948},{140,10,388},{6,0,80},{7,0,173},{9,0,547},{ +10,0,730},{14,0,18},{22,0,39},{135,11,1495},{6,0,1694},{135,0,1974},{140,0,196}, +{4,0,923},{6,0,507},{6,0,1711},{7,10,451},{8,10,389},{12,10,490},{13,10,16},{13, +10,215},{13,10,351},{18,10,132},{147,10,125},{6,0,646},{134,0,1047},{135,10,841} +,{136,10,566},{6,0,1611},{135,0,1214},{139,0,926},{132,11,525},{132,0,595},{5,0, +240},{6,0,459},{7,0,12},{7,0,114},{7,0,949},{7,0,1753},{7,0,1805},{8,0,658},{9,0 +,1},{11,0,959},{141,0,446},{5,10,912},{134,10,1695},{132,0,446},{7,11,62},{12,11 +,45},{147,11,112},{5,10,236},{6,10,572},{8,10,492},{11,10,618},{144,10,56},{5,10 +,190},{136,10,318},{135,10,1376},{4,11,223},{6,11,359},{11,11,3},{13,11,108},{14 +,11,89},{144,11,22},{132,11,647},{134,0,490},{134,0,491},{134,0,1584},{135,11, +685},{138,11,220},{7,0,250},{136,0,507},{132,0,158},{4,0,140},{7,0,362},{8,0,209 +},{9,0,10},{9,0,160},{9,0,503},{9,0,614},{10,0,689},{11,0,327},{11,0,553},{11,0, +725},{11,0,767},{12,0,252},{12,0,583},{13,0,192},{14,0,269},{14,0,356},{148,0,50 +},{19,0,1},{19,0,26},{150,0,9},{132,11,109},{6,0,228},{7,0,1341},{9,0,408},{138, +0,343},{4,0,373},{5,0,283},{6,0,480},{7,0,609},{10,0,860},{138,0,878},{6,0,779}, +{134,0,1209},{4,0,557},{7,11,263},{7,11,628},{136,11,349},{132,0,548},{7,0,197}, +{8,0,142},{8,0,325},{9,0,150},{9,0,596},{10,0,350},{10,0,353},{11,0,74},{11,0, +315},{12,0,662},{12,0,681},{14,0,423},{143,0,141},{4,11,40},{10,11,67},{11,11, +117},{11,11,768},{139,11,935},{7,11,992},{8,11,301},{9,11,722},{12,11,63},{13,11 +,29},{14,11,161},{143,11,18},{6,0,1490},{138,11,532},{5,0,580},{7,0,378},{7,0, +674},{7,0,1424},{15,0,83},{16,0,11},{15,11,83},{144,11,11},{6,0,1057},{6,0,1335} +,{10,0,316},{7,10,85},{7,10,247},{8,10,585},{138,10,163},{4,0,169},{5,0,83},{6,0 +,399},{6,0,579},{6,0,1513},{7,0,692},{7,0,846},{7,0,1015},{7,0,1799},{8,0,403},{ +9,0,394},{10,0,133},{12,0,4},{12,0,297},{12,0,452},{16,0,81},{18,0,25},{21,0,14} +,{22,0,12},{151,0,18},{134,0,1106},{7,0,1546},{11,0,299},{142,0,407},{134,0,1192 +},{132,0,177},{5,0,411},{135,0,653},{7,0,439},{10,0,727},{11,0,260},{139,0,684}, +{138,10,145},{147,10,83},{5,0,208},{7,0,753},{135,0,1528},{137,11,617},{135,10, +1922},{135,11,825},{11,0,422},{13,0,389},{4,10,124},{10,10,457},{11,10,121},{11, +10,169},{11,10,870},{12,10,214},{14,10,187},{143,10,77},{11,0,615},{15,0,58},{11 +,11,615},{143,11,58},{9,0,618},{138,0,482},{6,0,1952},{6,0,1970},{142,0,505},{7, +10,1193},{135,11,1838},{133,0,242},{135,10,1333},{6,10,107},{7,10,638},{7,10, +1632},{137,10,396},{133,0,953},{5,10,370},{134,10,1756},{5,11,28},{6,11,204},{10 +,11,320},{10,11,583},{13,11,502},{14,11,72},{14,11,274},{14,11,312},{14,11,344}, +{15,11,159},{16,11,62},{16,11,69},{17,11,30},{18,11,42},{18,11,53},{18,11,84},{ +18,11,140},{19,11,68},{19,11,85},{20,11,5},{20,11,45},{20,11,101},{22,11,7},{150 +,11,20},{4,11,558},{6,11,390},{7,11,162},{7,11,689},{9,11,360},{138,11,653},{11, +0,802},{141,0,67},{133,10,204},{133,0,290},{5,10,970},{134,10,1706},{132,0,380}, +{5,0,52},{7,0,277},{9,0,368},{139,0,791},{5,11,856},{6,11,1672},{6,11,1757},{6, +11,1781},{7,11,1150},{7,11,1425},{7,11,1453},{140,11,513},{5,11,92},{7,10,3},{10 +,11,736},{140,11,102},{4,0,112},{5,0,653},{5,10,483},{5,10,685},{6,10,489},{7,10 +,1204},{136,10,394},{132,10,921},{6,0,1028},{133,10,1007},{5,11,590},{9,11,213}, +{145,11,91},{135,10,1696},{10,0,138},{139,0,476},{5,0,725},{5,0,727},{135,0,1811 +},{4,0,979},{6,0,1821},{6,0,1838},{8,0,876},{8,0,883},{8,0,889},{8,0,893},{8,0, +895},{10,0,934},{12,0,720},{14,0,459},{148,0,123},{135,11,551},{4,0,38},{6,0,435 +},{7,0,307},{7,0,999},{7,0,1481},{7,0,1732},{7,0,1738},{8,0,371},{9,0,414},{11,0 +,316},{12,0,52},{13,0,420},{147,0,100},{135,0,1296},{132,10,712},{134,10,1629},{ +133,0,723},{134,0,651},{136,11,191},{9,11,791},{10,11,93},{11,11,301},{16,11,13} +,{17,11,23},{18,11,135},{19,11,12},{20,11,1},{20,11,12},{148,11,14},{136,11,503} +,{6,11,466},{135,11,671},{6,0,1200},{134,0,1330},{135,0,1255},{134,0,986},{5,0, +109},{6,0,1784},{7,0,1895},{12,0,296},{140,0,302},{135,11,983},{133,10,485},{134 +,0,660},{134,0,800},{5,0,216},{5,0,294},{6,0,591},{7,0,1879},{9,0,141},{9,0,270} +,{9,0,679},{10,0,159},{11,0,197},{11,0,438},{12,0,538},{12,0,559},{14,0,144},{14 +,0,167},{15,0,67},{4,10,285},{5,10,317},{6,10,301},{7,10,7},{8,10,153},{10,10, +766},{11,10,468},{12,10,467},{141,10,143},{136,0,945},{134,0,1090},{137,0,81},{ +12,11,468},{19,11,96},{148,11,24},{134,0,391},{138,11,241},{7,0,322},{136,0,249} +,{134,0,1412},{135,11,795},{5,0,632},{138,0,526},{136,10,819},{6,0,144},{7,0,948 +},{7,0,1042},{8,0,235},{8,0,461},{9,0,453},{9,0,796},{10,0,354},{17,0,77},{135, +11,954},{139,10,917},{6,0,940},{134,0,1228},{4,0,362},{7,0,52},{135,0,303},{6,11 +,549},{8,11,34},{8,11,283},{9,11,165},{138,11,475},{7,11,370},{7,11,1007},{7,11, +1177},{135,11,1565},{5,11,652},{5,11,701},{135,11,449},{5,0,196},{6,0,486},{7,0, +212},{8,0,309},{136,0,346},{6,10,1719},{6,10,1735},{7,10,2016},{7,10,2020},{8,10 +,837},{137,10,852},{6,11,159},{6,11,364},{7,11,516},{7,11,1439},{137,11,518},{ +135,0,1912},{135,0,1290},{132,0,686},{141,11,151},{138,0,625},{136,0,706},{138, +10,568},{139,0,412},{4,0,30},{133,0,43},{8,10,67},{138,10,419},{7,0,967},{141,0, +11},{12,0,758},{14,0,441},{142,0,462},{10,10,657},{14,10,297},{142,10,361},{139, +10,729},{4,0,220},{135,0,1535},{7,11,501},{9,11,111},{10,11,141},{11,11,332},{13 +,11,43},{13,11,429},{14,11,130},{14,11,415},{145,11,102},{4,0,950},{6,0,1859},{7 +,0,11},{8,0,873},{12,0,710},{12,0,718},{12,0,748},{12,0,765},{148,0,124},{5,11, +149},{5,11,935},{136,11,233},{142,11,291},{134,0,1579},{7,0,890},{8,10,51},{9,10 +,868},{10,10,833},{12,10,481},{12,10,570},{148,10,106},{141,0,2},{132,10,445},{ +136,11,801},{135,0,1774},{7,0,1725},{138,0,393},{5,0,263},{134,0,414},{132,11, +322},{133,10,239},{7,0,456},{7,10,1990},{8,10,130},{139,10,720},{137,0,818},{5, +10,123},{6,10,530},{7,10,348},{135,10,1419},{135,10,2024},{6,0,178},{6,0,1750},{ +8,0,251},{9,0,690},{10,0,155},{10,0,196},{10,0,373},{11,0,698},{13,0,155},{148,0 +,93},{5,0,97},{137,0,393},{134,0,674},{11,0,223},{140,0,168},{132,10,210},{139, +11,464},{6,0,1639},{146,0,159},{139,11,2},{7,0,934},{8,0,647},{17,0,97},{19,0,59 +},{150,0,2},{132,0,191},{5,0,165},{9,0,346},{10,0,655},{11,0,885},{4,10,430},{ +135,11,357},{133,0,877},{5,10,213},{133,11,406},{8,0,128},{139,0,179},{6,11,69}, +{135,11,117},{135,0,1297},{11,11,43},{13,11,72},{141,11,142},{135,11,1830},{142, +0,164},{5,0,57},{6,0,101},{6,0,586},{6,0,1663},{7,0,132},{7,0,1154},{7,0,1415},{ +7,0,1507},{12,0,493},{15,0,105},{151,0,15},{5,0,459},{7,0,1073},{8,0,241},{136,0 +,334},{133,11,826},{133,10,108},{5,10,219},{10,11,132},{11,11,191},{11,11,358},{ +139,11,460},{6,0,324},{6,0,520},{7,0,338},{7,0,1729},{8,0,228},{139,0,750},{21,0 +,30},{22,0,53},{4,10,193},{5,10,916},{7,10,364},{10,10,398},{10,10,726},{11,10, +317},{11,10,626},{12,10,142},{12,10,288},{12,10,678},{13,10,313},{15,10,113},{ +146,10,114},{6,11,110},{135,11,1681},{135,0,910},{6,10,241},{7,10,907},{8,10,832 +},{9,10,342},{10,10,729},{11,10,284},{11,10,445},{11,10,651},{11,10,863},{13,10, +398},{146,10,99},{7,0,705},{9,0,734},{5,11,1000},{7,11,733},{137,11,583},{4,0,73 +},{6,0,612},{7,0,927},{7,0,1822},{8,0,217},{9,0,765},{9,0,766},{10,0,408},{11,0, +51},{11,0,793},{12,0,266},{15,0,158},{20,0,89},{150,0,32},{7,0,1330},{4,11,297}, +{6,11,529},{7,11,152},{7,11,713},{7,11,1845},{8,11,710},{8,11,717},{140,11,639}, +{5,0,389},{136,0,636},{134,0,1409},{4,10,562},{9,10,254},{139,10,879},{134,0,893 +},{132,10,786},{4,11,520},{135,11,575},{136,0,21},{140,0,721},{136,0,959},{7,11, +1428},{7,11,1640},{9,11,169},{9,11,182},{9,11,367},{9,11,478},{9,11,506},{9,11, +551},{9,11,648},{9,11,651},{9,11,697},{9,11,705},{9,11,725},{9,11,787},{9,11,794 +},{10,11,198},{10,11,214},{10,11,267},{10,11,275},{10,11,456},{10,11,551},{10,11 +,561},{10,11,613},{10,11,627},{10,11,668},{10,11,675},{10,11,691},{10,11,695},{ +10,11,707},{10,11,715},{11,11,183},{11,11,201},{11,11,244},{11,11,262},{11,11, +352},{11,11,439},{11,11,493},{11,11,572},{11,11,591},{11,11,608},{11,11,611},{11 +,11,646},{11,11,674},{11,11,711},{11,11,751},{11,11,761},{11,11,776},{11,11,785} +,{11,11,850},{11,11,853},{11,11,862},{11,11,865},{11,11,868},{11,11,898},{11,11, +902},{11,11,903},{11,11,910},{11,11,932},{11,11,942},{11,11,957},{11,11,967},{11 +,11,972},{12,11,148},{12,11,195},{12,11,220},{12,11,237},{12,11,318},{12,11,339} +,{12,11,393},{12,11,445},{12,11,450},{12,11,474},{12,11,509},{12,11,533},{12,11, +591},{12,11,594},{12,11,597},{12,11,621},{12,11,633},{12,11,642},{13,11,59},{13, +11,60},{13,11,145},{13,11,239},{13,11,250},{13,11,273},{13,11,329},{13,11,344},{ +13,11,365},{13,11,372},{13,11,387},{13,11,403},{13,11,414},{13,11,456},{13,11, +478},{13,11,483},{13,11,489},{14,11,55},{14,11,57},{14,11,81},{14,11,90},{14,11, +148},{14,11,239},{14,11,266},{14,11,321},{14,11,326},{14,11,327},{14,11,330},{14 +,11,347},{14,11,355},{14,11,401},{14,11,411},{14,11,414},{14,11,416},{14,11,420} +,{15,11,61},{15,11,74},{15,11,87},{15,11,88},{15,11,94},{15,11,96},{15,11,116},{ +15,11,149},{15,11,154},{16,11,50},{16,11,63},{16,11,73},{17,11,2},{17,11,66},{17 +,11,92},{17,11,103},{17,11,112},{18,11,50},{18,11,54},{18,11,82},{18,11,86},{18, +11,90},{18,11,111},{18,11,115},{18,11,156},{19,11,40},{19,11,79},{20,11,78},{149 +,11,22},{137,11,170},{134,0,1433},{135,11,1307},{139,11,411},{5,0,189},{7,0,442} +,{7,0,443},{8,0,281},{12,0,174},{141,0,261},{6,10,216},{7,10,901},{7,10,1343},{ +136,10,493},{5,11,397},{6,11,154},{7,10,341},{7,11,676},{8,11,443},{8,11,609},{9 +,11,24},{9,11,325},{10,11,35},{11,10,219},{11,11,535},{11,11,672},{11,11,1018},{ +12,11,637},{144,11,30},{6,0,2},{7,0,191},{7,0,446},{7,0,1262},{7,0,1737},{8,0,22 +},{8,0,270},{8,0,612},{9,0,4},{9,0,312},{9,0,436},{9,0,626},{10,0,216},{10,0,311 +},{10,0,521},{10,0,623},{11,0,72},{11,0,330},{11,0,455},{12,0,321},{12,0,504},{ +12,0,530},{12,0,543},{13,0,17},{13,0,156},{13,0,334},{14,0,131},{17,0,60},{148,0 +,64},{7,0,354},{10,0,410},{139,0,815},{139,10,130},{7,10,1734},{137,11,631},{12, +0,425},{15,0,112},{10,10,115},{11,10,420},{13,10,404},{14,10,346},{143,10,54},{6 +,0,60},{6,0,166},{7,0,374},{7,0,670},{7,0,1327},{8,0,411},{8,0,435},{9,0,653},{9 +,0,740},{10,0,385},{11,0,222},{11,0,324},{11,0,829},{140,0,611},{7,0,1611},{13,0 +,14},{15,0,44},{19,0,13},{148,0,76},{133,11,981},{4,11,56},{7,11,1791},{8,11,607 +},{8,11,651},{11,11,465},{11,11,835},{12,11,337},{141,11,480},{6,0,1478},{5,10, +1011},{136,10,701},{139,0,596},{5,0,206},{134,0,398},{4,10,54},{5,10,666},{7,10, +1039},{7,10,1130},{9,10,195},{138,10,302},{7,0,50},{9,11,158},{138,11,411},{135, +11,1120},{6,0,517},{7,0,1159},{10,0,621},{11,0,192},{134,10,1669},{4,0,592},{6,0 +,600},{135,0,1653},{10,0,223},{139,0,645},{136,11,139},{7,0,64},{136,0,245},{142 +,0,278},{6,11,622},{135,11,1030},{136,0,604},{134,0,1502},{138,0,265},{141,11, +168},{7,0,1763},{140,0,310},{7,10,798},{139,11,719},{7,11,160},{10,11,624},{142, +11,279},{132,11,363},{7,10,122},{9,10,259},{10,10,84},{11,10,470},{12,10,541},{ +141,10,379},{5,0,129},{6,0,61},{135,0,947},{134,0,1356},{135,11,1191},{13,0,505} +,{141,0,506},{11,0,1000},{5,10,82},{5,10,131},{7,10,1755},{8,10,31},{9,10,168},{ +9,10,764},{139,10,869},{134,0,966},{134,10,605},{134,11,292},{5,11,177},{6,11, +616},{7,11,827},{9,11,525},{138,11,656},{135,11,1486},{138,11,31},{5,10,278},{ +137,10,68},{4,10,163},{5,10,201},{5,10,307},{5,10,310},{6,10,335},{7,10,284},{ +136,10,165},{6,0,839},{135,10,1660},{136,10,781},{6,10,33},{135,10,1244},{133,0, +637},{4,11,161},{133,11,631},{137,0,590},{7,10,1953},{136,10,720},{5,0,280},{7,0 +,1226},{138,10,203},{134,0,1386},{5,0,281},{6,0,1026},{6,10,326},{7,10,677},{137 +,10,425},{7,11,1557},{135,11,1684},{135,0,1064},{9,11,469},{9,11,709},{12,11,512 +},{14,11,65},{145,11,12},{134,0,917},{10,11,229},{11,11,73},{11,11,376},{139,11, +433},{7,0,555},{9,0,192},{13,0,30},{13,0,49},{15,0,150},{16,0,76},{20,0,52},{7, +10,1316},{7,10,1412},{7,10,1839},{9,10,589},{11,10,241},{11,10,676},{11,10,811}, +{11,10,891},{12,10,140},{12,10,346},{12,10,479},{13,10,381},{14,10,188},{146,10, +30},{149,0,15},{6,0,1882},{6,0,1883},{6,0,1897},{9,0,945},{9,0,1014},{9,0,1020}, +{12,0,823},{12,0,842},{12,0,866},{12,0,934},{15,0,242},{146,0,208},{6,0,965},{ +134,0,1499},{7,0,33},{7,0,120},{8,0,489},{9,0,319},{10,0,820},{11,0,1004},{12,0, +379},{12,0,679},{13,0,117},{13,0,412},{14,0,25},{15,0,52},{15,0,161},{16,0,47},{ +149,0,2},{6,11,558},{7,11,651},{8,11,421},{9,11,0},{138,11,34},{4,0,937},{5,0, +801},{7,0,473},{5,10,358},{7,10,1184},{10,10,662},{13,10,212},{13,10,304},{13,10 +,333},{145,10,98},{132,0,877},{6,0,693},{134,0,824},{132,0,365},{7,11,1832},{138 +,11,374},{5,0,7},{139,0,774},{4,0,734},{5,0,662},{134,0,430},{4,0,746},{135,0, +1090},{5,0,360},{8,0,237},{10,0,231},{147,0,124},{138,11,348},{6,11,6},{7,11,81} +,{7,11,771},{7,11,1731},{9,11,405},{138,11,421},{6,0,740},{137,0,822},{133,10, +946},{7,0,1485},{136,0,929},{7,10,411},{8,10,631},{9,10,323},{10,10,355},{11,10, +491},{12,10,143},{12,10,402},{13,10,73},{14,10,408},{15,10,107},{146,10,71},{135 +,10,590},{5,11,881},{133,11,885},{150,11,25},{4,0,852},{5,11,142},{134,11,546},{ +7,10,1467},{8,10,328},{10,10,544},{11,10,955},{13,10,320},{145,10,83},{9,0,17},{ +10,0,291},{11,10,511},{13,10,394},{14,10,298},{14,10,318},{146,10,103},{5,11,466 +},{11,11,571},{12,11,198},{13,11,283},{14,11,186},{15,11,21},{143,11,103},{134,0 +,1001},{4,11,185},{5,11,257},{5,11,839},{5,11,936},{7,11,171},{9,11,399},{10,11, +258},{10,11,395},{10,11,734},{11,11,1014},{12,11,23},{13,11,350},{14,11,150},{ +147,11,6},{143,0,35},{132,0,831},{5,10,835},{134,10,483},{4,0,277},{5,0,608},{6, +0,493},{7,0,457},{12,0,384},{7,11,404},{7,11,1377},{7,11,1430},{7,11,2017},{8,11 +,149},{8,11,239},{8,11,512},{8,11,793},{8,11,818},{9,11,474},{9,11,595},{10,11, +122},{10,11,565},{10,11,649},{10,11,783},{11,11,239},{11,11,295},{11,11,447},{11 +,11,528},{11,11,639},{11,11,800},{11,11,936},{12,11,25},{12,11,73},{12,11,77},{ +12,11,157},{12,11,316},{12,11,390},{12,11,391},{12,11,394},{12,11,395},{12,11, +478},{12,11,503},{12,11,592},{12,11,680},{13,11,50},{13,11,53},{13,11,132},{13, +11,198},{13,11,275},{13,11,322},{13,11,415},{14,11,71},{14,11,257},{14,11,395},{ +15,11,71},{15,11,136},{17,11,123},{18,11,93},{147,11,58},{134,0,1351},{7,0,27},{ +135,0,316},{136,11,712},{136,0,984},{133,0,552},{137,0,264},{132,0,401},{6,0,710 +},{6,0,1111},{134,0,1343},{134,0,1211},{9,0,543},{10,0,524},{11,0,108},{11,0,653 +},{12,0,524},{13,0,123},{14,0,252},{16,0,18},{19,0,38},{20,0,26},{20,0,65},{21,0 +,3},{151,0,11},{4,0,205},{5,0,623},{7,0,104},{8,0,519},{137,0,716},{132,10,677}, +{4,11,377},{152,11,13},{135,11,1673},{7,0,579},{9,0,41},{9,0,244},{9,0,669},{10, +0,5},{11,0,861},{11,0,951},{139,0,980},{132,0,717},{136,0,1011},{132,0,805},{4, +11,180},{135,11,1906},{132,10,777},{132,10,331},{132,0,489},{6,0,1024},{4,11,491 +},{133,10,747},{135,11,1182},{4,11,171},{138,11,234},{4,11,586},{7,11,1186},{138 +,11,631},{135,0,892},{135,11,336},{9,11,931},{10,11,334},{148,11,71},{137,0,473} +,{6,0,864},{12,0,659},{139,11,926},{7,0,819},{9,0,26},{9,0,392},{10,0,152},{10,0 +,226},{11,0,19},{12,0,276},{12,0,426},{12,0,589},{13,0,460},{15,0,97},{19,0,48}, +{148,0,104},{135,0,51},{133,10,326},{4,10,691},{146,10,16},{9,0,130},{11,0,765}, +{10,10,680},{10,10,793},{141,10,357},{133,11,765},{8,0,229},{6,10,32},{7,10,385} +,{7,10,757},{7,10,1916},{8,10,94},{8,10,711},{9,10,541},{10,10,162},{10,10,795}, +{11,10,989},{11,10,1010},{12,10,14},{142,10,308},{7,11,474},{137,11,578},{132,0, +674},{132,0,770},{5,0,79},{7,0,1027},{7,0,1477},{139,0,52},{133,11,424},{134,0, +1666},{6,0,409},{6,10,349},{6,10,1682},{7,10,1252},{8,10,112},{8,11,714},{9,10, +435},{9,10,668},{10,10,290},{10,10,319},{10,10,815},{11,10,180},{11,10,837},{12, +10,240},{13,10,152},{13,10,219},{142,10,158},{5,0,789},{134,0,195},{4,0,251},{4, +0,688},{7,0,513},{135,0,1284},{132,10,581},{9,11,420},{10,11,269},{10,11,285},{ +10,11,576},{11,11,397},{13,11,175},{145,11,90},{6,10,126},{7,10,573},{8,10,397}, +{142,10,44},{132,11,429},{133,0,889},{4,0,160},{5,0,330},{7,0,1434},{136,0,174}, +{7,11,18},{7,11,699},{7,11,1966},{8,11,752},{9,11,273},{9,11,412},{9,11,703},{10 +,11,71},{10,11,427},{10,11,508},{146,11,97},{6,0,872},{134,0,899},{133,10,926},{ +134,0,1126},{134,0,918},{4,11,53},{5,11,186},{135,11,752},{7,0,268},{136,0,569}, +{134,0,1224},{6,0,1361},{7,10,1232},{137,10,531},{8,11,575},{10,11,289},{139,11, +319},{133,10,670},{132,11,675},{133,0,374},{135,10,1957},{133,0,731},{11,0,190}, +{15,0,49},{11,11,190},{143,11,49},{4,0,626},{5,0,506},{5,0,642},{6,0,425},{10,0, +202},{139,0,141},{137,0,444},{7,10,242},{135,10,1942},{6,11,209},{8,11,468},{9, +11,210},{11,11,36},{12,11,28},{12,11,630},{13,11,21},{13,11,349},{14,11,7},{145, +11,13},{4,11,342},{135,11,1179},{5,10,834},{7,10,1202},{8,10,14},{9,10,481},{137 +,10,880},{4,11,928},{133,11,910},{4,11,318},{4,11,496},{7,11,856},{139,11,654},{ +136,0,835},{7,0,1526},{138,10,465},{151,0,17},{135,0,477},{4,10,357},{6,10,172}, +{7,10,143},{137,10,413},{6,0,1374},{138,0,994},{18,0,76},{132,10,590},{7,0,287}, +{8,0,355},{9,0,293},{137,0,743},{134,0,1389},{7,11,915},{8,11,247},{147,11,0},{4 +,11,202},{5,11,382},{6,11,454},{7,11,936},{7,11,1803},{8,11,758},{9,11,375},{9, +11,895},{10,11,743},{10,11,792},{11,11,978},{11,11,1012},{142,11,109},{5,0,384}, +{8,0,455},{140,0,48},{132,11,390},{5,10,169},{7,10,333},{136,10,45},{5,0,264},{ +134,0,184},{138,11,791},{133,11,717},{132,10,198},{6,11,445},{7,11,332},{137,11, +909},{136,0,1001},{4,10,24},{5,10,140},{5,10,185},{7,10,1500},{11,10,565},{139, +10,838},{134,11,578},{5,0,633},{6,0,28},{135,0,1323},{132,0,851},{136,11,267},{7 +,0,359},{8,0,243},{140,0,175},{4,10,334},{133,10,593},{141,11,87},{136,11,766},{ +10,0,287},{12,0,138},{10,11,287},{140,11,138},{4,0,105},{132,0,740},{140,10,116} +,{134,0,857},{135,11,1841},{6,0,1402},{137,0,819},{132,11,584},{132,10,709},{133 +,10,897},{5,0,224},{13,0,174},{146,0,52},{135,10,1840},{4,10,608},{133,10,497},{ +139,11,60},{4,0,758},{135,0,1649},{4,11,226},{4,11,326},{135,11,1770},{5,11,426} +,{8,11,30},{9,11,2},{11,11,549},{147,11,122},{135,10,2039},{6,10,540},{136,10, +136},{4,0,573},{8,0,655},{4,10,897},{133,10,786},{7,0,351},{139,0,128},{133,10, +999},{4,10,299},{135,10,1004},{133,0,918},{132,11,345},{4,11,385},{7,11,265},{ +135,11,587},{133,10,456},{136,10,180},{6,0,687},{134,0,1537},{4,11,347},{5,11, +423},{5,11,996},{135,11,1329},{132,10,755},{7,11,1259},{9,11,125},{11,11,65},{ +140,11,285},{5,11,136},{6,11,136},{136,11,644},{134,0,1525},{4,0,1009},{135,0, +1139},{139,10,338},{132,0,340},{135,10,1464},{8,0,847},{10,0,861},{10,0,876},{10 +,0,889},{10,0,922},{10,0,929},{10,0,933},{12,0,784},{140,0,791},{139,0,176},{9, +11,134},{10,11,2},{10,11,27},{10,11,333},{11,11,722},{143,11,1},{4,11,433},{133, +11,719},{5,0,985},{7,0,509},{7,0,529},{145,0,96},{132,0,615},{4,10,890},{5,10, +805},{5,10,819},{5,10,961},{6,10,396},{6,10,1631},{6,10,1678},{7,10,1967},{7,10, +2041},{9,10,630},{11,10,8},{11,10,1019},{12,10,176},{13,10,225},{14,10,292},{149 +,10,24},{135,0,1919},{134,0,1131},{144,11,21},{144,11,51},{135,10,1815},{4,0,247 +},{7,10,1505},{10,10,190},{10,10,634},{11,10,792},{12,10,358},{140,10,447},{5,10 +,0},{6,10,536},{7,10,604},{13,10,445},{145,10,126},{4,0,184},{5,0,390},{6,0,337} +,{7,0,23},{7,0,494},{7,0,618},{7,0,1456},{8,0,27},{8,0,599},{10,0,153},{139,0, +710},{6,10,232},{6,10,412},{7,10,1074},{8,10,9},{8,10,157},{8,10,786},{9,10,196} +,{9,10,352},{9,10,457},{10,10,337},{11,10,232},{11,10,877},{12,10,480},{140,10, +546},{13,0,38},{135,10,958},{4,10,382},{136,10,579},{4,10,212},{135,10,1206},{4, +11,555},{8,11,536},{138,11,288},{11,11,139},{139,11,171},{9,11,370},{138,11,90}, +{132,0,1015},{134,0,1088},{5,10,655},{135,11,977},{134,0,1585},{17,10,67},{147, +10,74},{10,0,227},{11,0,497},{11,0,709},{140,0,415},{6,0,360},{7,0,1664},{136,0, +478},{7,0,95},{6,10,231},{136,10,423},{140,11,65},{4,11,257},{135,11,2031},{135, +11,1768},{133,10,300},{139,11,211},{136,0,699},{6,10,237},{7,10,611},{8,10,100}, +{9,10,416},{11,10,335},{12,10,173},{146,10,101},{14,0,26},{146,0,150},{6,0,581}, +{135,0,1119},{135,10,1208},{132,0,739},{6,11,83},{6,11,1733},{135,11,1389},{137, +0,869},{4,0,67},{5,0,422},{7,0,1037},{7,0,1289},{7,0,1555},{9,0,741},{145,0,108} +,{133,10,199},{12,10,427},{146,10,38},{136,0,464},{142,0,42},{10,0,96},{8,11,501 +},{137,11,696},{134,11,592},{4,0,512},{4,0,966},{5,0,342},{6,0,1855},{8,0,869},{ +8,0,875},{8,0,901},{144,0,26},{8,0,203},{11,0,823},{11,0,846},{12,0,482},{13,0, +277},{13,0,302},{13,0,464},{14,0,205},{142,0,221},{4,0,449},{133,0,718},{7,11, +1718},{9,11,95},{9,11,274},{10,11,279},{10,11,317},{10,11,420},{11,11,303},{11, +11,808},{12,11,134},{12,11,367},{13,11,149},{13,11,347},{14,11,349},{14,11,406}, +{18,11,22},{18,11,89},{18,11,122},{147,11,47},{133,11,26},{4,0,355},{6,0,311},{9 +,0,256},{138,0,404},{132,11,550},{10,0,758},{6,10,312},{6,10,1715},{10,10,584},{ +11,10,546},{11,10,692},{12,10,259},{12,10,295},{13,10,46},{141,10,154},{136,11, +822},{5,0,827},{4,11,902},{5,11,809},{6,11,122},{135,11,896},{5,0,64},{140,0,581 +},{4,0,442},{6,0,739},{7,0,1047},{7,0,1352},{7,0,1643},{7,11,1911},{9,11,449},{ +10,11,192},{138,11,740},{135,11,262},{132,10,588},{133,11,620},{5,0,977},{6,0, +288},{7,0,528},{4,11,34},{5,11,574},{7,11,279},{7,11,1624},{136,11,601},{6,0, +1375},{4,10,231},{5,10,61},{6,10,104},{7,10,729},{7,10,964},{7,10,1658},{140,10, +414},{6,10,263},{138,10,757},{132,10,320},{4,0,254},{7,0,1309},{5,11,332},{135, +11,1309},{6,11,261},{8,11,182},{139,11,943},{132,10,225},{6,0,12},{135,0,1219},{ +4,0,275},{12,0,376},{6,11,1721},{141,11,490},{4,11,933},{133,11,880},{6,0,951},{ +6,0,1109},{6,0,1181},{7,0,154},{4,10,405},{7,10,817},{14,10,58},{17,10,37},{146, +10,124},{6,0,1520},{133,10,974},{134,0,1753},{6,0,369},{6,0,502},{7,0,1036},{8,0 +,348},{9,0,452},{10,0,26},{11,0,224},{11,0,387},{11,0,772},{12,0,95},{12,0,629}, +{13,0,195},{13,0,207},{13,0,241},{14,0,260},{14,0,270},{143,0,140},{132,0,269},{ +5,0,480},{7,0,532},{7,0,1197},{7,0,1358},{8,0,291},{11,0,349},{142,0,396},{5,10, +235},{7,10,1239},{11,10,131},{140,10,370},{7,10,956},{7,10,1157},{7,10,1506},{7, +10,1606},{7,10,1615},{7,10,1619},{7,10,1736},{7,10,1775},{8,10,590},{9,10,324},{ +9,10,736},{9,10,774},{9,10,776},{9,10,784},{10,10,567},{10,10,708},{11,10,518},{ +11,10,613},{11,10,695},{11,10,716},{11,10,739},{11,10,770},{11,10,771},{11,10, +848},{11,10,857},{11,10,931},{11,10,947},{12,10,326},{12,10,387},{12,10,484},{12 +,10,528},{12,10,552},{12,10,613},{13,10,189},{13,10,256},{13,10,340},{13,10,432} +,{13,10,436},{13,10,440},{13,10,454},{14,10,174},{14,10,220},{14,10,284},{14,10, +390},{145,10,121},{8,11,598},{9,11,664},{138,11,441},{9,10,137},{138,10,221},{ +133,11,812},{148,0,15},{134,0,1341},{6,0,1017},{4,11,137},{7,11,1178},{135,11, +1520},{7,10,390},{138,10,140},{7,11,1260},{135,11,1790},{137,11,191},{135,10, +1144},{6,0,1810},{7,0,657},{8,0,886},{10,0,857},{14,0,440},{144,0,96},{8,0,533}, +{6,11,1661},{7,11,1975},{7,11,2009},{135,11,2011},{6,0,1453},{134,10,464},{132, +11,715},{5,10,407},{11,10,204},{11,10,243},{11,10,489},{12,10,293},{19,10,37},{ +20,10,73},{150,10,38},{133,11,703},{4,0,211},{7,0,1483},{5,10,325},{8,10,5},{8, +10,227},{9,10,105},{10,10,585},{140,10,614},{4,0,332},{5,0,335},{6,0,238},{7,0, +269},{7,0,811},{7,0,1797},{8,0,836},{9,0,507},{141,0,242},{5,11,89},{7,11,1915}, +{9,11,185},{9,11,235},{9,11,496},{10,11,64},{10,11,270},{10,11,403},{10,11,469}, +{10,11,529},{10,11,590},{11,11,140},{11,11,860},{13,11,1},{13,11,422},{14,11,341 +},{14,11,364},{17,11,93},{18,11,113},{19,11,97},{147,11,113},{133,11,695},{16,0, +19},{5,11,6},{6,11,183},{6,10,621},{7,11,680},{7,11,978},{7,11,1013},{7,11,1055} +,{12,11,230},{13,11,172},{13,10,504},{146,11,29},{136,0,156},{133,0,1009},{6,11, +29},{139,11,63},{134,0,820},{134,10,218},{7,10,454},{7,10,782},{8,10,768},{140, +10,686},{5,0,228},{6,0,203},{7,0,156},{8,0,347},{9,0,265},{18,0,39},{20,0,54},{ +21,0,31},{22,0,3},{23,0,0},{15,11,8},{18,11,39},{20,11,54},{21,11,31},{22,11,3}, +{151,11,0},{7,0,1131},{135,0,1468},{144,10,0},{134,0,1276},{10,10,676},{140,10, +462},{132,11,311},{134,11,1740},{7,11,170},{8,11,90},{8,11,177},{8,11,415},{11, +11,714},{142,11,281},{134,10,164},{6,0,1792},{138,0,849},{150,10,50},{5,0,291},{ +5,0,318},{7,0,765},{9,0,389},{12,0,548},{8,11,522},{142,11,328},{11,11,91},{13, +11,129},{15,11,101},{145,11,125},{4,11,494},{6,11,74},{7,11,44},{7,11,407},{8,11 +,551},{12,11,17},{15,11,5},{148,11,11},{4,11,276},{133,11,296},{6,10,343},{7,10, +195},{7,11,1777},{9,10,226},{10,10,197},{10,10,575},{11,10,502},{139,10,899},{10 +,0,525},{139,0,82},{14,0,453},{4,11,7},{5,11,90},{5,11,158},{6,11,542},{7,11,221 +},{7,11,1574},{9,11,490},{10,11,540},{11,11,443},{139,11,757},{135,0,666},{22,10 +,29},{150,11,29},{4,0,422},{147,10,8},{5,0,355},{145,0,0},{6,0,1873},{9,0,918},{ +7,11,588},{9,11,175},{138,11,530},{143,11,31},{11,0,165},{7,10,1125},{9,10,143}, +{14,10,405},{150,10,21},{9,0,260},{137,0,905},{5,11,872},{6,11,57},{6,11,479},{6 +,11,562},{7,11,471},{7,11,1060},{9,11,447},{9,11,454},{141,11,6},{138,11,704},{ +133,0,865},{5,0,914},{134,0,1625},{133,0,234},{7,0,1383},{5,11,31},{6,11,614},{ +145,11,61},{7,11,1200},{138,11,460},{6,11,424},{135,11,1866},{136,0,306},{5,10, +959},{12,11,30},{13,11,148},{14,11,87},{14,11,182},{16,11,42},{18,11,92},{148,11 +,70},{6,0,1919},{6,0,1921},{9,0,923},{9,0,930},{9,0,941},{9,0,949},{9,0,987},{9, +0,988},{9,0,992},{12,0,802},{12,0,815},{12,0,856},{12,0,885},{12,0,893},{12,0, +898},{12,0,919},{12,0,920},{12,0,941},{12,0,947},{15,0,183},{15,0,185},{15,0,189 +},{15,0,197},{15,0,202},{15,0,233},{18,0,218},{18,0,219},{18,0,233},{143,11,156} +,{135,10,1759},{136,10,173},{13,0,163},{13,0,180},{18,0,78},{20,0,35},{5,11,13}, +{134,11,142},{134,10,266},{6,11,97},{7,11,116},{8,11,322},{8,11,755},{9,11,548}, +{10,11,714},{11,11,884},{141,11,324},{135,0,1312},{9,0,814},{137,11,676},{133,0, +707},{135,0,1493},{6,0,421},{7,0,61},{7,0,1540},{10,0,11},{138,0,501},{12,0,733} +,{12,0,766},{7,11,866},{135,11,1163},{137,0,341},{142,0,98},{145,11,115},{135,11 +,1111},{136,10,300},{136,0,1014},{8,11,1},{9,11,112},{138,11,326},{132,11,730},{ +5,11,488},{6,11,527},{7,11,489},{7,11,1636},{8,11,121},{8,11,144},{8,11,359},{9, +11,193},{9,11,241},{9,11,336},{9,11,882},{11,11,266},{11,11,372},{11,11,944},{12 +,11,401},{140,11,641},{6,0,971},{134,0,1121},{6,0,102},{7,0,72},{15,0,142},{147, +0,67},{151,0,30},{135,0,823},{134,0,1045},{5,10,427},{5,10,734},{7,10,478},{136, +10,52},{7,0,1930},{11,10,217},{142,10,165},{6,0,1512},{135,0,1870},{9,11,31},{10 +,11,244},{10,11,699},{12,11,149},{141,11,497},{133,11,377},{145,11,101},{10,11, +158},{13,11,13},{13,11,137},{13,11,258},{14,11,111},{14,11,225},{14,11,253},{14, +11,304},{14,11,339},{14,11,417},{146,11,33},{6,0,87},{6,10,1734},{7,10,20},{7,10 +,1056},{8,10,732},{9,10,406},{9,10,911},{138,10,694},{134,0,1243},{137,0,245},{7 +,0,68},{8,0,48},{8,0,88},{8,0,582},{8,0,681},{9,0,373},{9,0,864},{11,0,157},{11, +0,336},{11,0,843},{148,0,27},{8,11,663},{144,11,8},{133,10,613},{4,0,88},{5,0, +137},{5,0,174},{5,0,777},{6,0,1664},{6,0,1725},{7,0,77},{7,0,426},{7,0,1317},{7, +0,1355},{8,0,126},{8,0,563},{9,0,523},{9,0,750},{10,0,310},{10,0,836},{11,0,42}, +{11,0,318},{11,0,731},{12,0,68},{12,0,92},{12,0,507},{12,0,692},{13,0,81},{13,0, +238},{13,0,374},{14,0,436},{18,0,138},{19,0,78},{19,0,111},{20,0,55},{20,0,77},{ +148,0,92},{141,0,418},{4,0,938},{137,0,625},{138,0,351},{5,11,843},{7,10,32},{7, +10,984},{8,10,85},{8,10,709},{9,10,579},{9,10,847},{9,10,856},{10,10,799},{11,10 +,258},{11,10,1007},{12,10,331},{12,10,615},{13,10,188},{13,10,435},{14,10,8},{15 +,10,165},{16,10,27},{148,10,40},{6,0,1668},{7,0,1499},{8,0,117},{9,0,314},{138,0 +,174},{135,0,707},{132,11,554},{133,11,536},{5,0,403},{5,11,207},{9,11,79},{11, +11,625},{145,11,7},{132,11,424},{136,11,785},{4,10,167},{135,10,82},{9,0,7},{23, +0,6},{9,11,7},{151,11,6},{6,0,282},{5,10,62},{6,10,534},{7,10,74},{7,10,678},{7, +10,684},{7,10,1043},{7,10,1072},{8,10,280},{8,10,541},{8,10,686},{9,10,258},{10, +10,519},{11,10,252},{140,10,282},{138,10,33},{132,10,359},{4,0,44},{5,0,311},{6, +0,156},{7,0,639},{7,0,762},{7,0,1827},{9,0,8},{9,0,462},{148,0,83},{7,11,769},{9 +,11,18},{138,11,358},{4,0,346},{7,0,115},{9,0,180},{9,0,456},{10,0,363},{4,11, +896},{134,11,1777},{133,10,211},{7,0,761},{7,0,1051},{137,0,545},{6,10,145},{141 +,10,336},{7,11,750},{9,11,223},{11,11,27},{11,11,466},{12,11,624},{14,11,265},{ +146,11,61},{6,0,752},{6,0,768},{6,0,1195},{6,0,1254},{6,0,1619},{137,0,835},{6,0 +,1936},{8,0,930},{136,0,960},{132,10,263},{132,11,249},{12,0,653},{132,10,916},{ +4,11,603},{133,11,661},{8,0,344},{4,11,11},{6,11,128},{7,11,231},{7,11,1533},{ +138,11,725},{134,0,1483},{134,0,875},{6,0,185},{7,0,1899},{9,0,875},{139,0,673}, +{15,10,155},{144,10,79},{7,0,93},{7,0,210},{7,0,1223},{8,0,451},{8,0,460},{11,0, +353},{11,0,475},{4,10,599},{6,10,1634},{7,10,67},{7,10,691},{7,10,979},{7,10, +1697},{8,10,207},{8,10,214},{8,10,231},{8,10,294},{8,10,336},{8,10,428},{8,10, +471},{8,10,622},{8,10,626},{8,10,679},{8,10,759},{8,10,829},{9,10,11},{9,10,246} +,{9,10,484},{9,10,573},{9,10,706},{9,10,762},{9,10,798},{9,10,855},{9,10,870},{9 +,10,912},{10,10,303},{10,10,335},{10,10,424},{10,10,461},{10,10,543},{10,10,759} +,{10,10,814},{11,10,59},{11,10,235},{11,10,590},{11,10,929},{11,10,963},{11,10, +987},{12,10,114},{12,10,182},{12,10,226},{12,10,332},{12,10,439},{12,10,575},{12 +,10,598},{12,10,675},{13,10,8},{13,10,125},{13,10,194},{13,10,287},{14,10,197},{ +14,10,383},{15,10,53},{17,10,63},{19,10,46},{19,10,98},{19,10,106},{148,10,85},{ +132,11,476},{4,0,327},{5,0,478},{7,0,1332},{136,0,753},{5,0,1020},{133,0,1022},{ +135,11,1807},{4,0,103},{133,0,401},{4,0,499},{135,0,1421},{10,0,207},{13,0,164}, +{147,10,126},{9,11,20},{10,11,324},{139,11,488},{132,0,96},{9,11,280},{138,11, +134},{135,0,968},{133,10,187},{135,10,1286},{5,11,112},{6,11,103},{134,11,150},{ +8,0,914},{10,0,3},{4,10,215},{9,10,38},{11,10,23},{11,10,127},{139,10,796},{135, +0,399},{6,0,563},{137,0,224},{6,0,704},{134,0,1214},{4,11,708},{8,11,15},{9,11, +50},{9,11,386},{11,11,18},{11,11,529},{140,11,228},{4,11,563},{7,11,109},{7,11, +592},{7,11,637},{7,11,770},{7,11,1701},{8,11,436},{8,11,463},{9,11,60},{9,11,335 +},{9,11,904},{10,11,73},{11,11,434},{12,11,585},{13,11,331},{18,11,110},{148,11, +60},{134,0,1559},{132,11,502},{6,11,347},{138,11,161},{4,11,33},{5,11,102},{5,11 +,500},{6,11,284},{7,11,1079},{7,11,1423},{7,11,1702},{8,11,470},{9,11,554},{9,11 +,723},{139,11,333},{7,11,246},{135,11,840},{6,11,10},{8,11,571},{9,11,739},{143, +11,91},{8,0,861},{10,0,905},{12,0,730},{12,0,789},{133,11,626},{134,0,946},{5,0, +746},{12,0,333},{14,0,332},{12,11,333},{142,11,332},{5,11,18},{6,11,526},{13,11, +24},{13,11,110},{19,11,5},{147,11,44},{4,0,910},{5,0,832},{135,10,2002},{10,11, +768},{139,11,787},{4,11,309},{5,11,462},{7,11,970},{135,11,1097},{4,10,28},{5,10 +,440},{7,10,248},{11,10,833},{140,10,344},{134,10,1654},{6,0,632},{6,0,652},{6,0 +,1272},{6,0,1384},{134,0,1560},{134,11,1704},{6,0,1393},{133,10,853},{6,10,249}, +{7,10,1234},{139,10,573},{5,11,86},{7,11,743},{9,11,85},{10,11,281},{10,11,432}, +{11,11,490},{12,11,251},{13,11,118},{14,11,378},{146,11,143},{5,11,524},{133,11, +744},{134,0,1514},{10,0,201},{142,0,319},{7,0,717},{10,0,510},{7,10,392},{8,10, +20},{8,10,172},{8,10,690},{9,10,383},{9,10,845},{11,10,293},{11,10,832},{11,10, +920},{11,10,984},{141,10,221},{134,0,1381},{5,10,858},{133,10,992},{8,0,528},{ +137,0,348},{10,11,107},{140,11,436},{4,0,20},{133,0,616},{134,0,1251},{132,11, +927},{10,11,123},{12,11,670},{13,11,371},{14,11,142},{146,11,94},{134,0,1163},{7 +,11,1149},{137,11,156},{134,0,307},{133,11,778},{7,0,1091},{135,0,1765},{5,11, +502},{6,10,268},{137,10,62},{8,11,196},{10,11,283},{139,11,406},{4,0,26},{5,0, +429},{6,0,245},{7,0,704},{7,0,1379},{135,0,1474},{133,11,855},{132,0,881},{4,0, +621},{135,11,1596},{7,11,1400},{9,11,446},{138,11,45},{6,0,736},{138,10,106},{ +133,0,542},{134,0,348},{133,0,868},{136,0,433},{135,0,1495},{138,0,771},{6,10, +613},{136,10,223},{138,0,215},{141,0,124},{136,11,391},{135,11,172},{132,10,670} +,{140,0,55},{9,10,40},{139,10,136},{7,0,62},{147,0,112},{132,0,856},{132,11,568} +,{12,0,270},{139,10,259},{8,0,572},{137,0,698},{4,11,732},{9,10,310},{137,10,682 +},{142,10,296},{134,0,939},{136,11,733},{135,11,1435},{7,10,1401},{135,10,1476}, +{6,0,352},{4,10,296},{7,10,401},{7,10,1410},{7,10,1594},{7,10,1674},{8,10,63},{8 +,10,660},{137,10,74},{4,11,428},{133,11,668},{4,10,139},{4,10,388},{140,10,188}, +{7,11,2015},{140,11,665},{132,0,647},{146,0,10},{138,0,220},{142,0,464},{132,0, +109},{134,0,1746},{6,0,515},{4,10,747},{6,11,1623},{6,11,1681},{7,10,649},{7,10, +1479},{135,10,1583},{133,10,232},{135,0,566},{137,10,887},{4,0,40},{10,0,67},{11 +,0,117},{11,0,768},{139,0,935},{132,0,801},{7,0,992},{8,0,301},{9,0,722},{12,0, +63},{13,0,29},{14,0,161},{143,0,18},{139,0,923},{6,11,1748},{8,11,715},{9,11,802 +},{10,11,46},{10,11,819},{13,11,308},{14,11,351},{14,11,363},{146,11,67},{137,11 +,745},{7,0,1145},{4,10,14},{7,10,1801},{10,10,748},{141,10,458},{4,11,63},{5,11, +347},{134,11,474},{135,0,568},{4,10,425},{7,11,577},{7,11,1432},{9,11,475},{9,11 +,505},{9,11,526},{9,11,609},{9,11,689},{9,11,726},{9,11,735},{9,11,738},{10,11, +556},{10,11,674},{10,11,684},{11,11,89},{11,11,202},{11,11,272},{11,11,380},{11, +11,415},{11,11,505},{11,11,537},{11,11,550},{11,11,562},{11,11,640},{11,11,667}, +{11,11,688},{11,11,847},{11,11,927},{11,11,930},{11,11,940},{12,11,144},{12,11, +325},{12,11,329},{12,11,389},{12,11,403},{12,11,451},{12,11,515},{12,11,604},{12 +,11,616},{12,11,626},{13,11,66},{13,11,131},{13,11,167},{13,11,236},{13,11,368}, +{13,11,411},{13,11,434},{13,11,453},{13,11,461},{13,11,474},{14,11,59},{14,11,60 +},{14,11,139},{14,11,152},{14,11,276},{14,11,353},{14,11,402},{15,11,28},{15,11, +81},{15,11,123},{15,11,152},{18,11,136},{148,11,88},{137,0,247},{135,11,1622},{9 +,11,544},{11,11,413},{144,11,25},{4,0,645},{7,0,825},{6,10,1768},{135,11,89},{ +140,0,328},{5,10,943},{134,10,1779},{134,0,1363},{5,10,245},{6,10,576},{7,10,582 +},{136,10,225},{134,0,1280},{5,11,824},{133,11,941},{7,11,440},{8,11,230},{139, +11,106},{5,0,28},{6,0,204},{10,0,320},{10,0,583},{13,0,502},{14,0,72},{14,0,274} +,{14,0,312},{14,0,344},{15,0,159},{16,0,62},{16,0,69},{17,0,30},{18,0,42},{18,0, +53},{18,0,84},{18,0,140},{19,0,68},{19,0,85},{20,0,5},{20,0,45},{20,0,101},{22,0 +,7},{150,0,20},{4,0,558},{6,0,390},{7,0,162},{7,0,689},{9,0,360},{138,0,653},{ +134,0,764},{6,0,862},{137,0,833},{5,0,856},{6,0,1672},{6,0,1757},{134,0,1781},{5 +,0,92},{10,0,736},{140,0,102},{6,0,1927},{6,0,1944},{8,0,924},{8,0,948},{10,0, +967},{138,0,978},{134,0,1479},{5,0,590},{8,0,360},{9,0,213},{138,0,63},{134,0, +1521},{6,0,709},{134,0,891},{132,10,443},{13,0,477},{14,0,120},{148,0,61},{4,11, +914},{5,11,800},{133,11,852},{10,11,54},{141,11,115},{4,11,918},{133,11,876},{ +139,11,152},{4,11,92},{133,11,274},{135,11,1901},{9,11,800},{10,11,693},{11,11, +482},{11,11,734},{139,11,789},{9,0,483},{132,10,298},{6,0,1213},{141,11,498},{ +135,11,1451},{133,11,743},{4,0,1022},{10,0,1000},{12,0,957},{12,0,980},{12,0, +1013},{14,0,481},{144,0,116},{8,0,503},{17,0,29},{4,11,49},{7,11,280},{135,11, +1633},{135,0,1712},{134,0,466},{136,11,47},{5,10,164},{7,10,121},{142,10,189},{7 +,10,812},{7,10,1261},{7,10,1360},{9,10,632},{140,10,352},{139,10,556},{132,0,731 +},{5,11,272},{5,11,908},{5,11,942},{7,11,1008},{7,11,1560},{8,11,197},{9,11,47}, +{11,11,538},{139,11,742},{4,10,172},{9,10,611},{10,10,436},{12,10,673},{141,10, +255},{133,10,844},{10,0,484},{11,0,754},{12,0,457},{14,0,171},{14,0,389},{146,0, +153},{9,10,263},{10,10,147},{138,10,492},{137,11,891},{138,0,241},{133,10,537},{ +6,0,2005},{136,0,964},{137,10,842},{151,11,8},{4,11,407},{132,11,560},{135,11, +1884},{6,0,1100},{134,0,1242},{135,0,954},{5,10,230},{5,10,392},{6,10,420},{9,10 +,568},{140,10,612},{4,11,475},{11,11,35},{11,11,90},{13,11,7},{13,11,71},{13,11, +177},{142,11,422},{136,11,332},{135,0,1958},{6,0,549},{8,0,34},{8,0,283},{9,0, +165},{138,0,475},{10,0,952},{12,0,966},{140,0,994},{5,0,652},{5,0,701},{135,0, +449},{4,0,655},{7,0,850},{17,0,75},{146,0,137},{4,0,146},{7,0,1618},{8,0,670},{5 +,10,41},{7,10,1459},{7,10,1469},{7,10,1859},{9,10,549},{139,10,905},{133,10,696} +,{6,0,159},{6,0,364},{7,0,516},{137,0,518},{135,0,1439},{6,11,222},{7,11,636},{7 +,11,1620},{8,11,409},{9,11,693},{139,11,77},{13,0,151},{141,11,45},{6,0,1027},{4 +,11,336},{132,10,771},{139,11,392},{10,11,121},{11,11,175},{149,11,16},{8,0,950} +,{138,0,983},{133,10,921},{135,0,993},{6,10,180},{7,10,1137},{8,10,751},{139,10, +805},{7,0,501},{9,0,111},{10,0,141},{11,0,332},{13,0,43},{13,0,429},{14,0,130},{ +14,0,415},{145,0,102},{4,10,183},{5,11,882},{7,10,271},{11,10,824},{11,10,952},{ +13,10,278},{13,10,339},{13,10,482},{14,10,424},{148,10,99},{4,10,19},{5,10,477}, +{5,10,596},{6,10,505},{7,10,1221},{11,10,907},{12,10,209},{141,10,214},{135,10, +1215},{133,0,452},{132,11,426},{5,0,149},{136,0,233},{133,0,935},{6,11,58},{7,11 +,654},{7,11,745},{7,11,1969},{8,11,240},{8,11,675},{9,11,479},{9,11,731},{10,11, +330},{10,11,593},{10,11,817},{11,11,32},{11,11,133},{11,11,221},{145,11,68},{12, +0,582},{18,0,131},{7,11,102},{137,11,538},{136,0,801},{134,10,1645},{132,0,70},{ +6,10,92},{6,10,188},{7,10,1269},{7,10,1524},{7,10,1876},{10,10,228},{139,10,1020 +},{4,10,459},{133,10,966},{138,0,369},{16,0,36},{140,10,330},{141,11,366},{7,0, +721},{10,0,236},{12,0,204},{6,10,18},{7,10,932},{8,10,757},{9,10,54},{9,10,65},{ +9,10,844},{10,10,113},{10,10,315},{10,10,798},{11,10,153},{12,10,151},{12,10,392 +},{12,10,666},{142,10,248},{7,0,241},{10,0,430},{8,10,548},{9,10,532},{10,10,117 +},{11,10,351},{11,10,375},{143,10,23},{134,10,1742},{133,10,965},{133,11,566},{6 +,11,48},{135,11,63},{134,10,182},{10,10,65},{10,10,488},{138,10,497},{6,11,114}, +{7,11,1224},{7,11,1556},{136,11,3},{134,0,1817},{8,11,576},{137,11,267},{6,0, +1078},{144,0,16},{9,10,588},{138,10,260},{138,0,1021},{5,0,406},{134,0,2022},{ +133,11,933},{6,0,69},{135,0,117},{7,0,1830},{136,11,427},{4,0,432},{135,0,824},{ +134,10,1786},{133,0,826},{139,11,67},{133,11,759},{135,10,308},{137,0,816},{133, +0,1000},{4,0,297},{6,0,529},{7,0,152},{7,0,713},{7,0,1845},{8,0,710},{8,0,717},{ +12,0,639},{140,0,685},{7,0,423},{136,10,588},{136,10,287},{136,0,510},{134,0, +1048},{6,0,618},{7,11,56},{7,11,1989},{8,11,337},{8,11,738},{9,11,600},{10,11, +483},{12,11,37},{13,11,447},{142,11,92},{4,0,520},{135,0,575},{8,0,990},{138,0, +977},{135,11,774},{9,11,347},{11,11,24},{140,11,170},{136,11,379},{140,10,290},{ +132,11,328},{4,0,321},{134,0,569},{4,11,101},{135,11,1171},{7,0,723},{7,0,1135}, +{5,11,833},{136,11,744},{7,10,719},{8,10,809},{136,10,834},{8,0,921},{136,10,796 +},{5,10,210},{6,10,213},{7,10,60},{10,10,364},{139,10,135},{5,0,397},{6,0,154},{ +7,0,676},{8,0,443},{8,0,609},{9,0,24},{9,0,325},{10,0,35},{11,0,535},{11,0,672}, +{11,0,1018},{12,0,637},{16,0,30},{5,10,607},{8,10,326},{136,10,490},{4,10,701},{ +5,10,472},{6,11,9},{6,11,397},{7,11,53},{7,11,1742},{9,10,758},{10,11,632},{11, +11,828},{140,11,146},{135,10,380},{135,10,1947},{148,11,109},{10,10,278},{138,11 +,278},{134,0,856},{7,0,139},{4,10,386},{8,10,405},{8,10,728},{9,10,497},{11,10, +110},{11,10,360},{15,10,37},{144,10,84},{141,0,282},{133,0,981},{5,0,288},{7,10, +1452},{7,10,1480},{8,10,634},{140,10,472},{7,0,1890},{8,11,367},{10,11,760},{14, +11,79},{20,11,17},{152,11,0},{4,10,524},{136,10,810},{4,0,56},{7,0,1791},{8,0, +607},{8,0,651},{11,0,465},{11,0,835},{12,0,337},{141,0,480},{10,10,238},{141,10, +33},{11,11,417},{12,11,223},{140,11,265},{9,0,158},{10,0,411},{140,0,261},{133, +10,532},{133,10,997},{12,11,186},{12,11,292},{14,11,100},{146,11,70},{6,0,1403}, +{136,0,617},{134,0,1205},{139,0,563},{4,0,242},{134,0,333},{4,11,186},{5,11,157} +,{8,11,168},{138,11,6},{132,0,369},{133,11,875},{5,10,782},{5,10,829},{134,10, +1738},{134,0,622},{135,11,1272},{6,0,1407},{7,11,111},{136,11,581},{7,10,1823},{ +139,10,693},{7,0,160},{10,0,624},{142,0,279},{132,0,363},{10,11,589},{12,11,111} +,{13,11,260},{14,11,82},{18,11,63},{147,11,45},{7,11,1364},{7,11,1907},{141,11, +158},{4,11,404},{4,11,659},{135,11,675},{13,11,211},{14,11,133},{14,11,204},{15, +11,64},{15,11,69},{15,11,114},{16,11,10},{19,11,23},{19,11,35},{19,11,39},{19,11 +,51},{19,11,71},{19,11,75},{152,11,15},{4,10,78},{5,10,96},{5,10,182},{7,10,1724 +},{7,10,1825},{10,10,394},{10,10,471},{11,10,532},{14,10,340},{145,10,88},{135, +10,1964},{133,11,391},{11,11,887},{14,11,365},{142,11,375},{5,11,540},{6,11,1697 +},{7,11,222},{136,11,341},{134,11,78},{9,0,601},{9,0,619},{10,0,505},{10,0,732}, +{11,0,355},{140,0,139},{134,0,292},{139,0,174},{5,0,177},{6,0,616},{7,0,827},{9, +0,525},{138,0,656},{10,0,31},{6,10,215},{7,10,1028},{7,10,1473},{7,10,1721},{9, +10,424},{138,10,779},{135,10,584},{136,11,293},{134,0,685},{135,11,1868},{133,11 +,460},{7,0,647},{6,10,67},{7,10,1630},{9,10,354},{9,10,675},{10,10,830},{14,10, +80},{145,10,80},{4,0,161},{133,0,631},{6,10,141},{7,10,225},{9,10,59},{9,10,607} +,{10,10,312},{11,10,687},{12,10,555},{13,10,373},{13,10,494},{148,10,58},{7,11, +965},{7,11,1460},{135,11,1604},{136,10,783},{134,11,388},{6,0,722},{6,0,1267},{4 +,11,511},{9,11,333},{9,11,379},{10,11,602},{11,11,441},{11,11,723},{11,11,976},{ +140,11,357},{134,0,1797},{135,0,1684},{9,0,469},{9,0,709},{12,0,512},{14,0,65},{ +17,0,12},{5,11,938},{136,11,707},{7,0,1230},{136,0,531},{10,0,229},{11,0,73},{11 +,0,376},{139,0,433},{12,0,268},{12,0,640},{142,0,119},{7,10,430},{139,10,46},{6, +0,558},{7,0,651},{8,0,421},{9,0,0},{10,0,34},{139,0,1008},{6,0,106},{7,0,1786},{ +7,0,1821},{9,0,102},{9,0,763},{5,10,602},{7,10,2018},{137,10,418},{5,0,65},{6,0, +416},{7,0,1720},{7,0,1924},{10,0,109},{11,0,14},{11,0,70},{11,0,569},{11,0,735}, +{15,0,153},{20,0,80},{136,10,677},{135,11,1625},{137,11,772},{136,0,595},{6,11, +469},{7,11,1709},{138,11,515},{7,0,1832},{138,0,374},{9,0,106},{9,0,163},{9,0, +296},{10,0,167},{10,0,172},{10,0,777},{139,0,16},{6,0,6},{7,0,81},{7,0,771},{7,0 +,1731},{9,0,405},{138,0,421},{4,11,500},{135,11,938},{5,11,68},{134,11,383},{5,0 +,881},{133,0,885},{6,0,854},{6,0,1132},{6,0,1495},{6,0,1526},{6,0,1533},{134,0, +1577},{4,11,337},{6,11,353},{7,11,1934},{8,11,488},{137,11,429},{7,11,236},{7,11 +,1795},{8,11,259},{9,11,135},{9,11,177},{10,11,825},{11,11,115},{11,11,370},{11, +11,405},{11,11,604},{12,11,10},{12,11,667},{12,11,669},{13,11,76},{14,11,310},{ +15,11,76},{15,11,147},{148,11,23},{5,0,142},{134,0,546},{4,11,15},{5,11,22},{6, +11,244},{7,11,40},{7,11,200},{7,11,906},{7,11,1199},{9,11,616},{10,11,716},{11, +11,635},{11,11,801},{140,11,458},{5,0,466},{11,0,571},{12,0,198},{13,0,283},{14, +0,186},{15,0,21},{15,0,103},{135,10,329},{4,0,185},{5,0,257},{5,0,839},{5,0,936} +,{9,0,399},{10,0,258},{10,0,395},{10,0,734},{11,0,1014},{12,0,23},{13,0,350},{14 +,0,150},{19,0,6},{135,11,1735},{12,11,36},{141,11,337},{5,11,598},{7,11,791},{8, +11,108},{137,11,123},{132,10,469},{7,0,404},{7,0,1377},{7,0,1430},{7,0,2017},{8, +0,149},{8,0,239},{8,0,512},{8,0,793},{8,0,818},{9,0,474},{9,0,595},{10,0,122},{ +10,0,565},{10,0,649},{10,0,783},{11,0,239},{11,0,295},{11,0,447},{11,0,528},{11, +0,639},{11,0,800},{12,0,25},{12,0,77},{12,0,157},{12,0,256},{12,0,316},{12,0,390 +},{12,0,391},{12,0,395},{12,0,478},{12,0,503},{12,0,592},{12,0,680},{13,0,50},{ +13,0,53},{13,0,132},{13,0,198},{13,0,322},{13,0,415},{13,0,511},{14,0,71},{14,0, +395},{15,0,71},{15,0,136},{17,0,123},{18,0,93},{147,0,58},{136,0,712},{134,10, +1743},{5,10,929},{6,10,340},{8,10,376},{136,10,807},{6,0,1848},{8,0,860},{10,0, +856},{10,0,859},{10,0,925},{10,0,941},{140,0,762},{6,0,629},{6,0,906},{9,0,810}, +{140,0,652},{5,10,218},{7,10,1610},{138,10,83},{7,10,1512},{135,10,1794},{4,0, +377},{24,0,13},{4,11,155},{7,11,1689},{11,10,0},{144,10,78},{4,11,164},{5,11,151 +},{5,11,730},{5,11,741},{7,11,498},{7,11,870},{7,11,1542},{12,11,213},{14,11,36} +,{14,11,391},{17,11,111},{18,11,6},{18,11,46},{18,11,151},{19,11,36},{20,11,32}, +{20,11,56},{20,11,69},{20,11,102},{21,11,4},{22,11,8},{22,11,10},{22,11,14},{150 +,11,31},{7,0,1842},{133,10,571},{4,10,455},{4,11,624},{135,11,1752},{134,0,1501} +,{4,11,492},{5,11,451},{6,10,161},{7,10,372},{137,10,597},{132,10,349},{4,0,180} +,{135,0,1906},{135,11,835},{141,11,70},{132,0,491},{137,10,751},{6,10,432},{139, +10,322},{4,0,171},{138,0,234},{6,11,113},{135,11,436},{4,0,586},{7,0,1186},{138, +0,631},{5,10,468},{10,10,325},{11,10,856},{12,10,345},{143,10,104},{5,10,223},{ +10,11,592},{10,11,753},{12,11,317},{12,11,355},{12,11,465},{12,11,469},{12,11, +560},{12,11,578},{141,11,243},{132,10,566},{135,11,520},{4,10,59},{135,10,1394}, +{6,10,436},{139,10,481},{9,0,931},{10,0,334},{20,0,71},{4,10,48},{5,10,271},{7, +10,953},{135,11,1878},{11,0,170},{5,10,610},{136,10,457},{133,10,755},{6,0,1587} +,{135,10,1217},{4,10,197},{149,11,26},{133,11,585},{137,11,521},{133,0,765},{133 +,10,217},{139,11,586},{133,0,424},{9,11,752},{12,11,610},{13,11,431},{16,11,59}, +{146,11,109},{136,0,714},{7,0,685},{132,11,307},{9,0,420},{10,0,269},{10,0,285}, +{10,0,576},{11,0,397},{13,0,175},{145,0,90},{132,0,429},{133,11,964},{9,11,463}, +{138,11,595},{7,0,18},{7,0,699},{7,0,1966},{8,0,752},{9,0,273},{9,0,412},{9,0, +703},{10,0,71},{10,0,427},{138,0,508},{4,10,165},{7,10,1398},{135,10,1829},{4,0, +53},{5,0,186},{7,0,752},{7,0,828},{142,0,116},{8,0,575},{10,0,289},{139,0,319},{ +132,0,675},{134,0,1424},{4,11,75},{5,11,180},{6,11,500},{7,11,58},{7,11,710},{ +138,11,645},{133,11,649},{6,11,276},{7,11,282},{7,11,879},{7,11,924},{8,11,459}, +{9,11,599},{9,11,754},{11,11,574},{12,11,128},{12,11,494},{13,11,52},{13,11,301} +,{15,11,30},{143,11,132},{6,0,647},{134,0,1095},{5,10,9},{7,10,297},{7,10,966},{ +140,10,306},{132,11,200},{134,0,1334},{5,10,146},{6,10,411},{138,10,721},{6,0, +209},{6,0,1141},{6,0,1288},{8,0,468},{9,0,210},{11,0,36},{12,0,28},{12,0,630},{ +13,0,21},{13,0,349},{14,0,7},{145,0,13},{6,10,177},{135,10,467},{4,0,342},{135,0 +,1179},{10,11,454},{140,11,324},{4,0,928},{133,0,910},{7,0,1838},{6,11,225},{137 +,11,211},{16,0,101},{20,0,115},{20,0,118},{148,0,122},{4,0,496},{135,0,856},{4,0 +,318},{11,0,654},{7,11,718},{139,11,102},{8,11,58},{9,11,724},{11,11,809},{13,11 +,113},{145,11,72},{5,10,200},{6,11,345},{135,11,1247},{8,11,767},{8,11,803},{9, +11,301},{137,11,903},{7,0,915},{8,0,247},{19,0,0},{7,11,1949},{136,11,674},{4,0, +202},{5,0,382},{6,0,454},{7,0,936},{7,0,1803},{8,0,758},{9,0,375},{9,0,895},{10, +0,743},{10,0,792},{11,0,978},{11,0,1012},{142,0,109},{7,0,1150},{7,0,1425},{7,0, +1453},{140,0,513},{134,11,259},{138,0,791},{11,0,821},{12,0,110},{12,0,153},{18, +0,41},{150,0,19},{134,10,481},{132,0,796},{6,0,445},{9,0,909},{136,11,254},{10,0 +,776},{13,0,345},{142,0,425},{4,10,84},{7,10,1482},{10,10,76},{138,10,142},{135, +11,742},{6,0,578},{133,10,1015},{6,0,1387},{4,10,315},{5,10,507},{135,10,1370},{ +4,0,438},{133,0,555},{136,0,766},{133,11,248},{134,10,1722},{4,11,116},{5,11,95} +,{5,11,445},{7,11,1688},{8,11,29},{9,11,272},{11,11,509},{139,11,915},{135,0,541 +},{133,11,543},{8,10,222},{8,10,476},{9,10,238},{11,10,516},{11,10,575},{15,10, +109},{146,10,100},{6,0,880},{134,0,1191},{5,11,181},{136,11,41},{134,0,1506},{ +132,11,681},{7,11,25},{8,11,202},{138,11,536},{139,0,983},{137,0,768},{132,0,584 +},{9,11,423},{140,11,89},{8,11,113},{9,11,877},{10,11,554},{11,11,83},{12,11,136 +},{147,11,109},{7,10,706},{7,10,1058},{138,10,538},{133,11,976},{4,11,206},{135, +11,746},{136,11,526},{140,0,737},{11,10,92},{11,10,196},{11,10,409},{11,10,450}, +{11,10,666},{11,10,777},{12,10,262},{13,10,385},{13,10,393},{15,10,115},{16,10, +45},{145,10,82},{4,0,226},{4,0,326},{7,0,1770},{4,11,319},{5,11,699},{138,11,673 +},{6,10,40},{135,10,1781},{5,0,426},{8,0,30},{9,0,2},{11,0,549},{147,0,122},{6,0 +,1161},{134,0,1329},{138,10,97},{6,10,423},{7,10,665},{135,10,1210},{7,11,13},{8 +,11,226},{10,11,537},{11,11,570},{11,11,605},{11,11,799},{11,11,804},{12,11,85}, +{12,11,516},{12,11,623},{13,11,112},{13,11,361},{14,11,77},{14,11,78},{17,11,28} +,{147,11,110},{132,11,769},{132,11,551},{132,11,728},{147,0,117},{9,11,57},{9,11 +,459},{10,11,425},{11,11,119},{12,11,184},{12,11,371},{13,11,358},{145,11,51},{5 +,11,188},{5,11,814},{8,11,10},{9,11,421},{9,11,729},{10,11,609},{139,11,689},{ +134,11,624},{135,11,298},{135,0,462},{4,0,345},{139,10,624},{136,10,574},{4,0, +385},{7,0,265},{135,0,587},{6,0,808},{132,11,528},{133,0,398},{132,10,354},{4,0, +347},{5,0,423},{5,0,996},{135,0,1329},{135,10,1558},{7,0,1259},{9,0,125},{139,0, +65},{5,0,136},{6,0,136},{136,0,644},{5,11,104},{6,11,173},{135,11,1631},{135,0, +469},{133,10,830},{4,0,278},{5,0,465},{135,0,1367},{7,11,810},{8,11,138},{8,11, +342},{9,11,84},{10,11,193},{11,11,883},{140,11,359},{5,10,496},{135,10,203},{4,0 +,433},{133,0,719},{6,11,95},{134,10,547},{5,10,88},{137,10,239},{6,11,406},{10, +11,409},{10,11,447},{11,11,44},{140,11,100},{134,0,1423},{7,10,650},{135,10,1310 +},{134,0,749},{135,11,1243},{135,0,1363},{6,0,381},{7,0,645},{7,0,694},{8,0,546} +,{7,10,1076},{9,10,80},{11,10,78},{11,10,421},{11,10,534},{140,10,545},{134,11, +1636},{135,11,1344},{12,0,277},{7,10,274},{11,10,479},{139,10,507},{6,0,705},{6, +0,783},{6,0,1275},{6,0,1481},{4,11,282},{7,11,1034},{11,11,398},{11,11,634},{12, +11,1},{12,11,79},{12,11,544},{14,11,237},{17,11,10},{146,11,20},{134,0,453},{4,0 +,555},{8,0,536},{10,0,288},{11,0,1005},{4,10,497},{135,10,1584},{5,11,118},{5,11 +,499},{6,11,476},{7,11,600},{7,11,888},{135,11,1096},{138,0,987},{7,0,1107},{7, +10,261},{7,10,1115},{7,10,1354},{7,10,1588},{7,10,1705},{7,10,1902},{9,10,465},{ +10,10,248},{10,10,349},{10,10,647},{11,10,527},{11,10,660},{11,10,669},{12,10, +529},{141,10,305},{7,11,296},{7,11,596},{8,11,560},{8,11,586},{9,11,612},{11,11, +100},{11,11,304},{12,11,46},{13,11,89},{14,11,112},{145,11,122},{9,0,370},{138,0 +,90},{136,10,13},{132,0,860},{7,10,642},{8,10,250},{11,10,123},{11,10,137},{13, +10,48},{142,10,95},{135,10,1429},{137,11,321},{132,0,257},{135,0,2031},{7,0,1768 +},{7,11,1599},{7,11,1723},{8,11,79},{8,11,106},{8,11,190},{8,11,302},{8,11,383}, +{9,11,119},{9,11,233},{9,11,298},{9,11,419},{9,11,471},{10,11,181},{10,11,406},{ +11,11,57},{11,11,85},{11,11,120},{11,11,177},{11,11,296},{11,11,382},{11,11,454} +,{11,11,758},{11,11,999},{12,11,27},{12,11,98},{12,11,131},{12,11,245},{12,11, +312},{12,11,446},{12,11,454},{13,11,25},{13,11,98},{13,11,426},{13,11,508},{14, +11,6},{14,11,163},{14,11,272},{14,11,277},{14,11,370},{15,11,95},{15,11,138},{15 +,11,167},{17,11,18},{17,11,38},{20,11,96},{149,11,32},{5,11,722},{134,11,1759},{ +145,11,16},{6,0,1071},{134,0,1561},{10,10,545},{140,10,301},{6,0,83},{6,0,1733}, +{135,0,1389},{4,0,835},{135,0,1818},{133,11,258},{4,10,904},{133,10,794},{134,0, +2006},{5,11,30},{7,11,495},{8,11,134},{9,11,788},{140,11,438},{135,11,2004},{137 +,0,696},{5,11,50},{6,11,439},{7,11,780},{135,11,1040},{7,11,772},{7,11,1104},{7, +11,1647},{11,11,269},{11,11,539},{11,11,607},{11,11,627},{11,11,706},{11,11,975} +,{12,11,248},{12,11,311},{12,11,434},{12,11,600},{12,11,622},{13,11,297},{13,11, +367},{13,11,485},{14,11,69},{14,11,409},{143,11,108},{5,11,1},{6,11,81},{138,11, +520},{7,0,1718},{9,0,95},{9,0,274},{10,0,279},{10,0,317},{10,0,420},{11,0,303},{ +11,0,808},{12,0,134},{12,0,367},{13,0,149},{13,0,347},{14,0,349},{14,0,406},{18, +0,22},{18,0,89},{18,0,122},{147,0,47},{5,11,482},{8,11,98},{9,11,172},{10,11,222 +},{10,11,700},{10,11,822},{11,11,302},{11,11,778},{12,11,50},{12,11,127},{12,11, +396},{13,11,62},{13,11,328},{14,11,122},{147,11,72},{7,10,386},{138,10,713},{6, +10,7},{6,10,35},{7,10,147},{7,10,1069},{7,10,1568},{7,10,1575},{7,10,1917},{8,10 +,43},{8,10,208},{9,10,128},{9,10,866},{10,10,20},{11,10,981},{147,10,33},{133,0, +26},{132,0,550},{5,11,2},{7,11,1494},{136,11,589},{6,11,512},{7,11,797},{8,11, +253},{9,11,77},{10,11,1},{10,11,129},{10,11,225},{11,11,118},{11,11,226},{11,11, +251},{11,11,430},{11,11,701},{11,11,974},{11,11,982},{12,11,64},{12,11,260},{12, +11,488},{140,11,690},{7,10,893},{141,10,424},{134,0,901},{136,0,822},{4,0,902},{ +5,0,809},{134,0,122},{6,0,807},{134,0,1366},{7,0,262},{5,11,748},{134,11,553},{ +133,0,620},{4,0,34},{5,0,574},{7,0,279},{7,0,1624},{136,0,601},{9,0,170},{6,10, +322},{9,10,552},{11,10,274},{13,10,209},{13,10,499},{14,10,85},{15,10,126},{145, +10,70},{132,0,537},{4,11,12},{7,11,420},{7,11,522},{7,11,809},{8,11,797},{141,11 +,88},{133,0,332},{8,10,83},{8,10,742},{8,10,817},{9,10,28},{9,10,29},{9,10,885}, +{10,10,387},{11,10,633},{11,10,740},{13,10,235},{13,10,254},{15,10,143},{143,10, +146},{6,0,1909},{9,0,964},{12,0,822},{12,0,854},{12,0,865},{12,0,910},{12,0,938} +,{15,0,169},{15,0,208},{15,0,211},{18,0,205},{18,0,206},{18,0,220},{18,0,223},{ +152,0,24},{140,10,49},{5,11,528},{135,11,1580},{6,0,261},{8,0,182},{139,0,943},{ +134,0,1721},{4,0,933},{133,0,880},{136,11,321},{5,11,266},{9,11,290},{9,11,364}, +{10,11,293},{11,11,606},{142,11,45},{6,0,1609},{4,11,50},{6,11,510},{6,11,594},{ +9,11,121},{10,11,49},{10,11,412},{139,11,834},{7,0,895},{136,11,748},{132,11,466 +},{4,10,110},{10,10,415},{10,10,597},{142,10,206},{133,0,812},{135,11,281},{6,0, +1890},{6,0,1902},{6,0,1916},{9,0,929},{9,0,942},{9,0,975},{9,0,984},{9,0,986},{9 +,0,1011},{9,0,1019},{12,0,804},{12,0,851},{12,0,867},{12,0,916},{12,0,923},{15,0 +,194},{15,0,204},{15,0,210},{15,0,222},{15,0,223},{15,0,229},{15,0,250},{18,0, +179},{18,0,186},{18,0,192},{7,10,205},{135,10,2000},{132,11,667},{135,0,778},{4, +0,137},{7,0,1178},{135,0,1520},{134,0,1314},{4,11,242},{134,11,333},{6,0,1661},{ +7,0,1975},{7,0,2009},{135,0,2011},{134,0,1591},{4,10,283},{135,10,1194},{11,0, +820},{150,0,51},{4,11,39},{5,11,36},{7,11,1843},{8,11,407},{11,11,144},{140,11, +523},{134,10,1720},{4,11,510},{7,11,29},{7,11,66},{7,11,1980},{10,11,487},{10,11 +,809},{146,11,9},{5,0,89},{7,0,1915},{9,0,185},{9,0,235},{10,0,64},{10,0,270},{ +10,0,403},{10,0,469},{10,0,529},{10,0,590},{11,0,140},{11,0,860},{13,0,1},{13,0, +422},{14,0,341},{14,0,364},{17,0,93},{18,0,113},{19,0,97},{147,0,113},{133,0,695 +},{6,0,987},{134,0,1160},{5,0,6},{6,0,183},{7,0,680},{7,0,978},{7,0,1013},{7,0, +1055},{12,0,230},{13,0,172},{146,0,29},{134,11,570},{132,11,787},{134,11,518},{6 +,0,29},{139,0,63},{132,11,516},{136,11,821},{132,0,311},{134,0,1740},{7,0,170},{ +8,0,90},{8,0,177},{8,0,415},{11,0,714},{14,0,281},{136,10,735},{134,0,1961},{135 +,11,1405},{4,11,10},{7,11,917},{139,11,786},{5,10,132},{9,10,486},{9,10,715},{10 +,10,458},{11,10,373},{11,10,668},{11,10,795},{11,10,897},{12,10,272},{12,10,424} +,{12,10,539},{12,10,558},{14,10,245},{14,10,263},{14,10,264},{14,10,393},{142,10 +,403},{11,0,91},{13,0,129},{15,0,101},{145,0,125},{135,0,1132},{4,0,494},{6,0,74 +},{7,0,44},{7,0,407},{12,0,17},{15,0,5},{148,0,11},{133,10,379},{5,0,270},{5,11, +684},{6,10,89},{6,10,400},{7,10,1569},{7,10,1623},{7,10,1850},{8,10,218},{8,10, +422},{9,10,570},{138,10,626},{4,0,276},{133,0,296},{6,0,1523},{134,11,27},{6,10, +387},{7,10,882},{141,10,111},{6,10,224},{7,10,877},{137,10,647},{135,10,790},{4, +0,7},{5,0,90},{5,0,158},{6,0,542},{7,0,221},{7,0,1574},{9,0,490},{10,0,540},{11, +0,443},{139,0,757},{7,0,588},{9,0,175},{138,0,530},{135,10,394},{142,11,23},{134 +,0,786},{135,0,580},{7,0,88},{136,0,627},{5,0,872},{6,0,57},{7,0,471},{9,0,447}, +{137,0,454},{6,11,342},{6,11,496},{8,11,275},{137,11,206},{4,11,909},{133,11,940 +},{6,0,735},{132,11,891},{8,0,845},{8,0,916},{135,10,1409},{5,0,31},{134,0,614}, +{11,0,458},{12,0,15},{140,0,432},{8,0,330},{140,0,477},{4,0,530},{5,0,521},{7,0, +1200},{10,0,460},{132,11,687},{6,0,424},{135,0,1866},{9,0,569},{12,0,12},{12,0, +81},{12,0,319},{13,0,69},{14,0,259},{16,0,87},{17,0,1},{17,0,21},{17,0,24},{18,0 +,15},{18,0,56},{18,0,59},{18,0,127},{18,0,154},{19,0,19},{148,0,31},{7,0,1302},{ +136,10,38},{134,11,253},{5,10,261},{7,10,78},{7,10,199},{8,10,815},{9,10,126},{ +138,10,342},{5,0,595},{135,0,1863},{6,11,41},{141,11,160},{5,0,13},{134,0,142},{ +6,0,97},{7,0,116},{8,0,322},{8,0,755},{9,0,548},{10,0,714},{11,0,884},{13,0,324} +,{7,11,1304},{138,11,477},{132,10,628},{134,11,1718},{7,10,266},{136,10,804},{ +135,10,208},{7,0,1021},{6,10,79},{135,10,1519},{7,0,1472},{135,0,1554},{6,11,362 +},{146,11,51},{7,0,1071},{7,0,1541},{7,0,1767},{7,0,1806},{11,0,162},{11,0,242}, +{11,0,452},{12,0,605},{15,0,26},{144,0,44},{136,10,741},{133,11,115},{145,0,115} +,{134,10,376},{6,0,1406},{134,0,1543},{5,11,193},{12,11,178},{13,11,130},{145,11 +,84},{135,0,1111},{8,0,1},{9,0,650},{10,0,326},{5,11,705},{137,11,606},{5,0,488} +,{6,0,527},{7,0,489},{7,0,1636},{8,0,121},{8,0,144},{8,0,359},{9,0,193},{9,0,241 +},{9,0,336},{9,0,882},{11,0,266},{11,0,372},{11,0,944},{12,0,401},{140,0,641},{ +135,11,174},{6,0,267},{7,10,244},{7,10,632},{7,10,1609},{8,10,178},{8,10,638},{ +141,10,58},{134,0,1983},{134,0,1155},{134,0,1575},{134,0,1438},{9,0,31},{10,0, +244},{10,0,699},{12,0,149},{141,0,497},{133,0,377},{4,11,122},{5,11,796},{5,11, +952},{6,11,1660},{6,11,1671},{8,11,567},{9,11,687},{9,11,742},{10,11,686},{11,11 +,356},{11,11,682},{140,11,281},{145,0,101},{11,11,0},{144,11,78},{5,11,179},{5, +10,791},{7,11,1095},{135,11,1213},{8,11,372},{9,11,122},{138,11,175},{7,10,686}, +{8,10,33},{8,10,238},{10,10,616},{11,10,467},{11,10,881},{13,10,217},{13,10,253} +,{142,10,268},{9,0,476},{4,11,66},{7,11,722},{135,11,904},{7,11,352},{137,11,684 +},{135,0,2023},{135,0,1836},{132,10,447},{5,0,843},{144,0,35},{137,11,779},{141, +11,35},{4,10,128},{5,10,415},{6,10,462},{7,10,294},{7,10,578},{10,10,710},{139, +10,86},{132,0,554},{133,0,536},{136,10,587},{5,0,207},{9,0,79},{11,0,625},{145,0 +,7},{7,0,1371},{6,10,427},{138,10,692},{4,0,424},{4,10,195},{135,10,802},{8,0, +785},{133,11,564},{135,0,336},{4,0,896},{6,0,1777},{134,11,556},{137,11,103},{ +134,10,1683},{7,11,544},{8,11,719},{138,11,61},{138,10,472},{4,11,5},{5,11,498}, +{136,11,637},{7,0,750},{9,0,223},{11,0,27},{11,0,466},{12,0,624},{14,0,265},{146 +,0,61},{12,0,238},{18,0,155},{12,11,238},{146,11,155},{151,10,28},{133,11,927},{ +12,0,383},{5,10,3},{8,10,578},{9,10,118},{10,10,705},{141,10,279},{4,11,893},{5, +11,780},{133,11,893},{4,0,603},{133,0,661},{4,0,11},{6,0,128},{7,0,231},{7,0, +1533},{10,0,725},{5,10,229},{5,11,238},{135,11,1350},{8,10,102},{10,10,578},{10, +10,672},{12,10,496},{13,10,408},{14,10,121},{145,10,106},{132,0,476},{134,0,1552 +},{134,11,1729},{8,10,115},{8,10,350},{9,10,489},{10,10,128},{11,10,306},{12,10, +373},{14,10,30},{17,10,79},{19,10,80},{150,10,55},{135,0,1807},{4,0,680},{4,11, +60},{7,11,760},{7,11,1800},{8,11,314},{9,11,700},{139,11,487},{4,10,230},{5,10, +702},{148,11,94},{132,11,228},{139,0,435},{9,0,20},{10,0,324},{10,0,807},{139,0, +488},{6,10,1728},{136,11,419},{4,10,484},{18,10,26},{19,10,42},{20,10,43},{21,10 +,0},{23,10,27},{152,10,14},{135,0,1431},{133,11,828},{5,0,112},{6,0,103},{6,0, +150},{7,0,1303},{9,0,292},{10,0,481},{20,0,13},{7,11,176},{7,11,178},{7,11,1110} +,{10,11,481},{148,11,13},{138,0,356},{4,11,51},{5,11,39},{6,11,4},{7,11,591},{7, +11,849},{7,11,951},{7,11,1129},{7,11,1613},{7,11,1760},{7,11,1988},{9,11,434},{ +10,11,754},{11,11,25},{11,11,37},{139,11,414},{6,0,1963},{134,0,2000},{132,10, +633},{6,0,1244},{133,11,902},{135,11,928},{140,0,18},{138,0,204},{135,11,1173},{ +134,0,867},{4,0,708},{8,0,15},{9,0,50},{9,0,386},{11,0,18},{11,0,529},{140,0,228 +},{134,11,270},{4,0,563},{7,0,109},{7,0,592},{7,0,637},{7,0,770},{8,0,463},{9,0, +60},{9,0,335},{9,0,904},{10,0,73},{11,0,434},{12,0,585},{13,0,331},{18,0,110},{ +148,0,60},{132,0,502},{14,11,359},{19,11,52},{148,11,47},{6,11,377},{7,11,1025}, +{9,11,613},{145,11,104},{6,0,347},{10,0,161},{5,10,70},{5,10,622},{6,10,334},{7, +10,1032},{9,10,171},{11,10,26},{11,10,213},{11,10,637},{11,10,707},{12,10,202},{ +12,10,380},{13,10,226},{13,10,355},{14,10,222},{145,10,42},{132,11,416},{4,0,33} +,{5,0,102},{6,0,284},{7,0,1079},{7,0,1423},{7,0,1702},{8,0,470},{9,0,554},{9,0, +723},{11,0,333},{142,11,372},{5,11,152},{5,11,197},{7,11,340},{7,11,867},{10,11, +548},{10,11,581},{11,11,6},{12,11,3},{12,11,19},{14,11,110},{142,11,289},{7,0, +246},{135,0,840},{6,0,10},{8,0,571},{9,0,739},{143,0,91},{6,0,465},{7,0,1465},{4 +,10,23},{4,10,141},{5,10,313},{5,10,1014},{6,10,50},{7,10,142},{7,10,559},{8,10, +640},{9,10,460},{9,10,783},{11,10,741},{12,10,183},{141,10,488},{133,0,626},{136 +,0,614},{138,0,237},{7,11,34},{7,11,190},{8,11,28},{8,11,141},{8,11,444},{8,11, +811},{9,11,468},{11,11,334},{12,11,24},{12,11,386},{140,11,576},{133,11,757},{5, +0,18},{6,0,526},{13,0,24},{13,0,110},{19,0,5},{147,0,44},{6,0,506},{134,11,506}, +{135,11,1553},{4,0,309},{5,0,462},{7,0,970},{7,0,1097},{22,0,30},{22,0,33},{7,11 +,1385},{11,11,582},{11,11,650},{11,11,901},{11,11,949},{12,11,232},{12,11,236},{ +13,11,413},{13,11,501},{146,11,116},{9,0,140},{5,10,222},{138,10,534},{6,0,1056} +,{137,10,906},{134,0,1704},{138,10,503},{134,0,1036},{5,10,154},{7,10,1491},{10, +10,379},{138,10,485},{4,11,383},{133,10,716},{134,0,1315},{5,0,86},{7,0,743},{9, +0,85},{10,0,281},{10,0,432},{11,0,825},{12,0,251},{13,0,118},{142,0,378},{8,0, +264},{4,10,91},{5,10,388},{5,10,845},{6,10,206},{6,10,252},{6,10,365},{7,10,136} +,{7,10,531},{136,10,621},{5,0,524},{133,0,744},{5,11,277},{141,11,247},{132,11, +435},{10,0,107},{140,0,436},{132,0,927},{10,0,123},{12,0,670},{146,0,94},{7,0, +1149},{9,0,156},{138,0,957},{5,11,265},{6,11,212},{135,11,28},{133,0,778},{133,0 +,502},{8,0,196},{10,0,283},{139,0,406},{135,10,576},{136,11,535},{134,0,1312},{5 +,10,771},{5,10,863},{5,10,898},{6,10,1632},{6,10,1644},{134,10,1780},{5,0,855},{ +5,10,331},{135,11,1487},{132,11,702},{5,11,808},{135,11,2045},{7,0,1400},{9,0, +446},{138,0,45},{140,10,632},{132,0,1003},{5,11,166},{8,11,739},{140,11,511},{5, +10,107},{7,10,201},{136,10,518},{6,10,446},{135,10,1817},{134,0,1532},{134,0, +1097},{4,11,119},{5,11,170},{5,11,447},{7,11,1708},{7,11,1889},{9,11,357},{9,11, +719},{12,11,486},{140,11,596},{9,10,851},{141,10,510},{7,0,612},{8,0,545},{8,0, +568},{8,0,642},{9,0,717},{10,0,541},{10,0,763},{11,0,449},{12,0,489},{13,0,153}, +{13,0,296},{14,0,138},{14,0,392},{15,0,50},{16,0,6},{16,0,12},{20,0,9},{132,10, +504},{4,11,450},{135,11,1158},{11,0,54},{13,0,173},{13,0,294},{5,10,883},{5,10, +975},{8,10,392},{148,10,7},{13,0,455},{15,0,99},{15,0,129},{144,0,68},{135,0,172 +},{132,11,754},{5,10,922},{134,10,1707},{134,0,1029},{17,11,39},{148,11,36},{4,0 +,568},{5,10,993},{7,10,515},{137,10,91},{132,0,732},{10,0,617},{138,11,617},{134 +,0,974},{7,0,989},{10,0,377},{12,0,363},{13,0,68},{13,0,94},{14,0,108},{142,0, +306},{136,0,733},{132,0,428},{7,0,1789},{135,11,1062},{7,0,2015},{140,0,665},{ +135,10,1433},{5,0,287},{7,10,921},{8,10,580},{8,10,593},{8,10,630},{138,10,28},{ +138,0,806},{4,10,911},{5,10,867},{5,10,1013},{7,10,2034},{8,10,798},{136,10,813} +,{134,0,1539},{8,11,523},{150,11,34},{135,11,740},{7,11,238},{7,11,2033},{8,11, +120},{8,11,188},{8,11,659},{9,11,598},{10,11,466},{12,11,342},{12,11,588},{13,11 +,503},{14,11,246},{143,11,92},{7,0,1563},{141,0,182},{5,10,135},{6,10,519},{7,10 +,1722},{10,10,271},{11,10,261},{145,10,54},{14,10,338},{148,10,81},{7,0,484},{4, +10,300},{133,10,436},{145,11,114},{6,0,1623},{134,0,1681},{133,11,640},{4,11,201 +},{7,11,1744},{8,11,602},{11,11,247},{11,11,826},{145,11,65},{8,11,164},{146,11, +62},{6,0,1833},{6,0,1861},{136,0,878},{134,0,1569},{8,10,357},{10,10,745},{14,10 +,426},{17,10,94},{147,10,57},{12,0,93},{12,0,501},{13,0,362},{14,0,151},{15,0,40 +},{15,0,59},{16,0,46},{17,0,25},{18,0,14},{18,0,134},{19,0,25},{19,0,69},{20,0, +16},{20,0,19},{20,0,66},{21,0,23},{21,0,25},{150,0,42},{6,0,1748},{8,0,715},{9,0 +,802},{10,0,46},{10,0,819},{13,0,308},{14,0,351},{14,0,363},{146,0,67},{132,0, +994},{4,0,63},{133,0,347},{132,0,591},{133,0,749},{7,11,1577},{10,11,304},{10,11 +,549},{11,11,424},{12,11,365},{13,11,220},{13,11,240},{142,11,33},{133,0,366},{7 +,0,557},{12,0,547},{14,0,86},{133,10,387},{135,0,1747},{132,11,907},{5,11,100},{ +10,11,329},{12,11,416},{149,11,29},{4,10,6},{5,10,708},{136,10,75},{7,10,1351},{ +9,10,581},{10,10,639},{11,10,453},{140,10,584},{7,0,89},{132,10,303},{138,10,772 +},{132,11,176},{5,11,636},{5,11,998},{8,11,26},{137,11,358},{7,11,9},{7,11,1508} +,{9,11,317},{10,11,210},{10,11,292},{10,11,533},{11,11,555},{12,11,526},{12,11, +607},{13,11,263},{13,11,459},{142,11,271},{134,0,1463},{6,0,772},{6,0,1137},{139 +,11,595},{7,0,977},{139,11,66},{138,0,893},{20,0,48},{148,11,48},{5,0,824},{133, +0,941},{134,11,295},{7,0,1543},{7,0,1785},{10,0,690},{4,10,106},{139,10,717},{7, +0,440},{8,0,230},{139,0,106},{5,10,890},{133,10,988},{6,10,626},{142,10,431},{10 +,11,127},{141,11,27},{17,0,32},{10,10,706},{150,10,44},{132,0,216},{137,0,332},{ +4,10,698},{136,11,119},{139,11,267},{138,10,17},{11,11,526},{11,11,939},{141,11, +290},{7,11,1167},{11,11,934},{13,11,391},{145,11,76},{139,11,39},{134,10,84},{4, +0,914},{5,0,800},{133,0,852},{10,0,416},{141,0,115},{7,0,564},{142,0,168},{4,0, +918},{133,0,876},{134,0,1764},{152,0,3},{4,0,92},{5,0,274},{7,11,126},{136,11,84 +},{140,10,498},{136,11,790},{8,0,501},{5,10,986},{6,10,130},{7,10,1582},{8,10, +458},{10,10,101},{10,10,318},{138,10,823},{6,11,64},{12,11,377},{141,11,309},{5, +0,743},{138,0,851},{4,0,49},{7,0,280},{135,0,1633},{134,0,879},{136,0,47},{7,10, +1644},{137,10,129},{132,0,865},{134,0,1202},{9,11,34},{139,11,484},{135,10,997}, +{5,0,272},{5,0,908},{5,0,942},{8,0,197},{9,0,47},{11,0,538},{139,0,742},{6,11, +1700},{7,11,26},{7,11,293},{7,11,382},{7,11,1026},{7,11,1087},{7,11,2027},{8,11, +24},{8,11,114},{8,11,252},{8,11,727},{8,11,729},{9,11,30},{9,11,199},{9,11,231}, +{9,11,251},{9,11,334},{9,11,361},{9,11,488},{9,11,712},{10,11,55},{10,11,60},{10 +,11,232},{10,11,332},{10,11,384},{10,11,396},{10,11,504},{10,11,542},{10,11,652} +,{11,11,20},{11,11,48},{11,11,207},{11,11,291},{11,11,298},{11,11,342},{11,11, +365},{11,11,394},{11,11,620},{11,11,705},{11,11,1017},{12,11,123},{12,11,340},{ +12,11,406},{12,11,643},{13,11,61},{13,11,269},{13,11,311},{13,11,319},{13,11,486 +},{14,11,234},{15,11,62},{15,11,85},{16,11,71},{18,11,119},{148,11,105},{6,0, +1455},{150,11,37},{135,10,1927},{135,0,1911},{137,0,891},{7,10,1756},{137,10,98} +,{7,10,1046},{139,10,160},{132,0,761},{6,11,379},{7,11,270},{7,11,1116},{8,11, +176},{8,11,183},{9,11,432},{9,11,661},{12,11,247},{12,11,617},{146,11,125},{6,10 +,45},{7,10,433},{8,10,129},{9,10,21},{10,10,392},{11,10,79},{12,10,499},{13,10, +199},{141,10,451},{4,0,407},{5,11,792},{133,11,900},{132,0,560},{135,0,183},{13, +0,490},{7,10,558},{136,10,353},{4,0,475},{6,0,731},{11,0,35},{13,0,71},{13,0,177 +},{14,0,422},{133,10,785},{8,10,81},{9,10,189},{9,10,201},{11,10,478},{11,10,712 +},{141,10,338},{4,0,418},{4,0,819},{133,10,353},{151,10,26},{4,11,901},{133,11, +776},{132,0,575},{7,0,818},{16,0,92},{17,0,14},{17,0,45},{18,0,75},{148,0,18},{6 +,0,222},{7,0,636},{7,0,1620},{8,0,409},{9,0,693},{139,0,77},{6,10,25},{7,10,855} +,{7,10,1258},{144,10,32},{6,0,1880},{6,0,1887},{6,0,1918},{6,0,1924},{9,0,967},{ +9,0,995},{9,0,1015},{12,0,826},{12,0,849},{12,0,857},{12,0,860},{12,0,886},{12,0 +,932},{18,0,228},{18,0,231},{146,0,240},{134,0,633},{134,0,1308},{4,11,37},{5,11 +,334},{135,11,1253},{10,0,86},{4,10,4},{7,10,1118},{7,10,1320},{7,10,1706},{8,10 +,277},{9,10,622},{11,10,724},{12,10,350},{12,10,397},{13,10,28},{13,10,159},{15, +10,89},{18,10,5},{19,10,9},{20,10,34},{150,10,47},{132,11,508},{137,11,448},{12, +11,107},{146,11,31},{132,0,817},{134,0,663},{133,0,882},{134,0,914},{132,11,540} +,{132,11,533},{136,11,608},{8,0,885},{138,0,865},{132,0,426},{6,0,58},{7,0,745}, +{7,0,1969},{8,0,399},{8,0,675},{9,0,479},{9,0,731},{10,0,330},{10,0,593},{10,0, +817},{11,0,32},{11,0,133},{11,0,221},{145,0,68},{134,10,255},{7,0,102},{137,0, +538},{137,10,216},{7,11,253},{136,11,549},{135,11,912},{9,10,183},{139,10,286},{ +11,10,956},{151,10,3},{8,11,527},{18,11,60},{147,11,24},{4,10,536},{7,10,1141},{ +10,10,723},{139,10,371},{133,11,920},{7,0,876},{135,10,285},{135,10,560},{132,10 +,690},{142,11,126},{11,10,33},{12,10,571},{149,10,1},{133,0,566},{9,0,139},{10,0 +,399},{11,0,469},{12,0,634},{13,0,223},{132,11,483},{6,0,48},{135,0,63},{18,0,12 +},{7,10,1862},{12,10,491},{12,10,520},{13,10,383},{142,10,244},{135,11,1665},{ +132,11,448},{9,11,495},{146,11,104},{6,0,114},{7,0,1224},{7,0,1556},{136,0,3},{4 +,10,190},{133,10,554},{8,0,576},{9,0,267},{133,10,1001},{133,10,446},{133,0,933} +,{139,11,1009},{8,11,653},{13,11,93},{147,11,14},{6,0,692},{6,0,821},{134,0,1077 +},{5,11,172},{135,11,801},{138,0,752},{4,0,375},{134,0,638},{134,0,1011},{140,11 +,540},{9,0,96},{133,11,260},{139,11,587},{135,10,1231},{12,0,30},{13,0,148},{14, +0,87},{14,0,182},{16,0,42},{20,0,70},{132,10,304},{6,0,1398},{7,0,56},{7,0,1989} +,{8,0,337},{8,0,738},{9,0,600},{12,0,37},{13,0,447},{142,0,92},{138,0,666},{5,0, +394},{7,0,487},{136,0,246},{9,0,437},{6,10,53},{6,10,199},{7,10,1408},{8,10,32}, +{8,10,93},{10,10,397},{10,10,629},{11,10,593},{11,10,763},{13,10,326},{145,10,35 +},{134,10,105},{9,0,320},{10,0,506},{138,10,794},{7,11,57},{8,11,167},{8,11,375} +,{9,11,82},{9,11,561},{10,11,620},{10,11,770},{11,10,704},{141,10,396},{6,0,1003 +},{5,10,114},{5,10,255},{141,10,285},{7,0,866},{135,0,1163},{133,11,531},{132,0, +328},{7,10,2035},{8,10,19},{9,10,89},{138,10,831},{8,11,194},{136,11,756},{136,0 +,1000},{5,11,453},{134,11,441},{4,0,101},{5,0,833},{7,0,1171},{136,0,744},{133,0 +,726},{136,10,746},{138,0,176},{6,0,9},{6,0,397},{7,0,53},{7,0,1742},{10,0,632}, +{11,0,828},{140,0,146},{135,11,22},{145,11,64},{132,0,839},{11,0,417},{12,0,223} +,{140,0,265},{4,11,102},{7,11,815},{7,11,1699},{139,11,964},{5,10,955},{136,10, +814},{6,0,1931},{6,0,2007},{18,0,246},{146,0,247},{8,0,198},{11,0,29},{140,0,534 +},{135,0,1771},{6,0,846},{7,11,1010},{11,11,733},{11,11,759},{12,11,563},{13,11, +34},{14,11,101},{18,11,45},{146,11,129},{4,0,186},{5,0,157},{8,0,168},{138,0,6}, +{132,11,899},{133,10,56},{148,10,100},{133,0,875},{5,0,773},{5,0,991},{6,0,1635} +,{134,0,1788},{6,0,1274},{9,0,477},{141,0,78},{4,0,639},{7,0,111},{8,0,581},{12, +0,177},{6,11,52},{9,11,104},{9,11,559},{10,10,4},{10,10,13},{11,10,638},{12,11, +308},{19,11,87},{148,10,57},{132,11,604},{4,11,301},{133,10,738},{133,10,758},{ +134,0,1747},{7,11,1440},{11,11,854},{11,11,872},{11,11,921},{12,11,551},{13,11, +472},{142,11,367},{7,0,1364},{7,0,1907},{141,0,158},{134,0,873},{4,0,404},{4,0, +659},{7,0,552},{135,0,675},{135,10,1112},{139,10,328},{7,11,508},{137,10,133},{ +133,0,391},{5,10,110},{6,10,169},{6,10,1702},{7,10,400},{8,10,538},{9,10,184},{9 +,10,524},{140,10,218},{6,11,310},{7,11,1849},{8,11,72},{8,11,272},{8,11,431},{9, +11,12},{9,11,351},{10,11,563},{10,11,630},{10,11,810},{11,11,367},{11,11,599},{ +11,11,686},{140,11,672},{5,0,540},{6,0,1697},{136,0,668},{132,0,883},{134,0,78}, +{12,0,628},{18,0,79},{6,10,133},{9,10,353},{139,10,993},{6,11,181},{7,11,537},{8 +,11,64},{9,11,127},{10,11,496},{12,11,510},{141,11,384},{6,10,93},{7,10,1422},{7 +,10,1851},{8,10,673},{9,10,529},{140,10,43},{137,10,371},{134,0,1460},{134,0,962 +},{4,11,244},{135,11,233},{9,10,25},{10,10,467},{138,10,559},{4,10,335},{135,10, +942},{133,0,460},{135,11,334},{134,11,1650},{4,0,199},{139,0,34},{5,10,601},{8, +10,39},{10,10,773},{11,10,84},{12,10,205},{142,10,1},{133,10,870},{134,0,388},{ +14,0,474},{148,0,120},{133,11,369},{139,0,271},{4,0,511},{9,0,333},{9,0,379},{10 +,0,602},{11,0,441},{11,0,723},{11,0,976},{12,0,357},{132,10,181},{134,0,608},{ +134,10,1652},{22,0,49},{137,11,338},{140,0,988},{134,0,617},{5,0,938},{136,0,707 +},{132,10,97},{5,10,147},{6,10,286},{7,10,1362},{141,10,176},{6,0,756},{134,0, +1149},{133,11,896},{6,10,375},{7,10,169},{7,10,254},{136,10,780},{134,0,1583},{ +135,10,1447},{139,0,285},{7,11,1117},{8,11,393},{136,11,539},{135,0,344},{6,0, +469},{7,0,1709},{138,0,515},{5,10,629},{135,10,1549},{5,11,4},{5,11,810},{6,11, +13},{6,11,538},{6,11,1690},{6,11,1726},{7,11,499},{7,11,1819},{8,11,148},{8,11, +696},{8,11,791},{12,11,125},{13,11,54},{143,11,9},{135,11,1268},{137,0,404},{132 +,0,500},{5,0,68},{134,0,383},{11,0,216},{139,0,340},{4,11,925},{5,11,803},{8,11, +698},{138,11,828},{4,0,337},{6,0,353},{7,0,1934},{8,0,488},{137,0,429},{7,0,236} +,{7,0,1795},{8,0,259},{9,0,135},{9,0,177},{9,0,860},{10,0,825},{11,0,115},{11,0, +370},{11,0,405},{11,0,604},{12,0,10},{12,0,667},{12,0,669},{13,0,76},{14,0,310}, +{15,0,76},{15,0,147},{148,0,23},{4,0,15},{4,0,490},{5,0,22},{6,0,244},{7,0,40},{ +7,0,200},{7,0,906},{7,0,1199},{9,0,616},{10,0,716},{11,0,635},{11,0,801},{140,0, +458},{12,0,756},{132,10,420},{134,0,1504},{6,0,757},{133,11,383},{6,0,1266},{135 +,0,1735},{5,0,598},{7,0,791},{8,0,108},{9,0,123},{7,10,1570},{140,10,542},{142, +11,410},{9,11,660},{138,11,347} +}; +/* GENERATED CODE END */ + +} + +#endif /* BROTLI_ENC_STATIC_DICT_LUT_H_ */ diff --git a/third_party/brotli/enc/utf8_util.cpp b/third_party/brotli/enc/utf8_util.cpp new file mode 100644 index 00000000000..ab4079f4388 --- /dev/null +++ b/third_party/brotli/enc/utf8_util.cpp @@ -0,0 +1,81 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Heuristics for deciding about the UTF8-ness of strings. */ + +#include "utf8_util.h" + +#include + +using namespace duckdb_brotli; + +static size_t BrotliParseAsUTF8( + int* symbol, const uint8_t* input, size_t size) { + /* ASCII */ + if ((input[0] & 0x80) == 0) { + *symbol = input[0]; + if (*symbol > 0) { + return 1; + } + } + /* 2-byte UTF8 */ + if (size > 1u && + (input[0] & 0xE0) == 0xC0 && + (input[1] & 0xC0) == 0x80) { + *symbol = (((input[0] & 0x1F) << 6) | + (input[1] & 0x3F)); + if (*symbol > 0x7F) { + return 2; + } + } + /* 3-byte UFT8 */ + if (size > 2u && + (input[0] & 0xF0) == 0xE0 && + (input[1] & 0xC0) == 0x80 && + (input[2] & 0xC0) == 0x80) { + *symbol = (((input[0] & 0x0F) << 12) | + ((input[1] & 0x3F) << 6) | + (input[2] & 0x3F)); + if (*symbol > 0x7FF) { + return 3; + } + } + /* 4-byte UFT8 */ + if (size > 3u && + (input[0] & 0xF8) == 0xF0 && + (input[1] & 0xC0) == 0x80 && + (input[2] & 0xC0) == 0x80 && + (input[3] & 0xC0) == 0x80) { + *symbol = (((input[0] & 0x07) << 18) | + ((input[1] & 0x3F) << 12) | + ((input[2] & 0x3F) << 6) | + (input[3] & 0x3F)); + if (*symbol > 0xFFFF && *symbol <= 0x10FFFF) { + return 4; + } + } + /* Not UTF8, emit a special symbol above the UTF8-code space */ + *symbol = 0x110000 | input[0]; + return 1; +} + +/* Returns 1 if at least min_fraction of the data is UTF8-encoded.*/ +BROTLI_BOOL duckdb_brotli::BrotliIsMostlyUTF8( + const uint8_t* data, const size_t pos, const size_t mask, + const size_t length, const double min_fraction) { + size_t size_utf8 = 0; + size_t i = 0; + while (i < length) { + int symbol; + size_t bytes_read = + BrotliParseAsUTF8(&symbol, &data[(pos + i) & mask], length - i); + i += bytes_read; + if (symbol < 0x110000) size_utf8 += bytes_read; + } + return TO_BROTLI_BOOL((double)size_utf8 > min_fraction * (double)length); +} + + diff --git a/third_party/brotli/enc/utf8_util.h b/third_party/brotli/enc/utf8_util.h new file mode 100644 index 00000000000..3f0315c2c6f --- /dev/null +++ b/third_party/brotli/enc/utf8_util.h @@ -0,0 +1,29 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Heuristics for deciding about the UTF8-ness of strings. */ + +#ifndef BROTLI_ENC_UTF8_UTIL_H_ +#define BROTLI_ENC_UTF8_UTIL_H_ + +#include + +#include "../common/brotli_platform.h" + +namespace duckdb_brotli { + +static const double kMinUTF8Ratio = 0.75; + +/* Returns 1 if at least min_fraction of the bytes between pos and + pos + length in the (data, mask) ring-buffer is UTF8-encoded, otherwise + returns 0. */ +BROTLI_INTERNAL BROTLI_BOOL BrotliIsMostlyUTF8( + const uint8_t* data, const size_t pos, const size_t mask, + const size_t length, const double min_fraction); + +} + +#endif /* BROTLI_ENC_UTF8_UTIL_H_ */ diff --git a/third_party/brotli/enc/write_bits.h b/third_party/brotli/enc/write_bits.h new file mode 100644 index 00000000000..5f46afa4423 --- /dev/null +++ b/third_party/brotli/enc/write_bits.h @@ -0,0 +1,84 @@ +/* Copyright 2010 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Write bits into a byte array. */ + +#ifndef BROTLI_ENC_WRITE_BITS_H_ +#define BROTLI_ENC_WRITE_BITS_H_ + +#include + +#include "../common/brotli_platform.h" + +namespace duckdb_brotli { + +/* This function writes bits into bytes in increasing addresses, and within + a byte least-significant-bit first. + + The function can write up to 56 bits in one go with WriteBits + Example: let's assume that 3 bits (Rs below) have been written already: + + BYTE-0 BYTE+1 BYTE+2 + + 0000 0RRR 0000 0000 0000 0000 + + Now, we could write 5 or less bits in MSB by just shifting by 3 + and OR'ing to BYTE-0. + + For n bits, we take the last 5 bits, OR that with high bits in BYTE-0, + and locate the rest in BYTE+1, BYTE+2, etc. */ +static BROTLI_INLINE void BrotliWriteBits(size_t n_bits, + uint64_t bits, + size_t* BROTLI_RESTRICT pos, + uint8_t* BROTLI_RESTRICT array) { + BROTLI_LOG(("WriteBits %2d 0x%08x%08x %10d\n", (int)n_bits, + (uint32_t)(bits >> 32), (uint32_t)(bits & 0xFFFFFFFF), + (int)*pos)); + BROTLI_DCHECK((bits >> n_bits) == 0); + BROTLI_DCHECK(n_bits <= 56); +#if defined(BROTLI_LITTLE_ENDIAN) + /* This branch of the code can write up to 56 bits at a time, + 7 bits are lost by being perhaps already in *p and at least + 1 bit is needed to initialize the bit-stream ahead (i.e. if 7 + bits are in *p and we write 57 bits, then the next write will + access a byte that was never initialized). */ + { + uint8_t* p = &array[*pos >> 3]; + uint64_t v = (uint64_t)(*p); /* Zero-extend 8 to 64 bits. */ + v |= bits << (*pos & 7); + BROTLI_UNALIGNED_STORE64LE(p, v); /* Set some bits. */ + *pos += n_bits; + } +#else + /* implicit & 0xFF is assumed for uint8_t arithmetics */ + { + uint8_t* array_pos = &array[*pos >> 3]; + const size_t bits_reserved_in_first_byte = (*pos & 7); + size_t bits_left_to_write; + bits <<= bits_reserved_in_first_byte; + *array_pos++ |= (uint8_t)bits; + for (bits_left_to_write = n_bits + bits_reserved_in_first_byte; + bits_left_to_write >= 9; + bits_left_to_write -= 8) { + bits >>= 8; + *array_pos++ = (uint8_t)bits; + } + *array_pos = 0; + *pos += n_bits; + } +#endif +} + +static BROTLI_INLINE void BrotliWriteBitsPrepareStorage( + size_t pos, uint8_t* array) { + BROTLI_LOG(("WriteBitsPrepareStorage %10d\n", (int)pos)); + BROTLI_DCHECK((pos & 7) == 0); + array[pos >> 3] = 0; +} + +} + +#endif /* BROTLI_ENC_WRITE_BITS_H_ */ diff --git a/third_party/brotli/include/brotli/decode.h b/third_party/brotli/include/brotli/decode.h new file mode 100644 index 00000000000..2288009cf32 --- /dev/null +++ b/third_party/brotli/include/brotli/decode.h @@ -0,0 +1,405 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/** + * @file + * API for Brotli decompression. + */ + +#ifndef BROTLI_DEC_DECODE_H_ +#define BROTLI_DEC_DECODE_H_ + +#include +#include +#include + +namespace duckdb_brotli { + +/** + * Opaque structure that holds decoder state. + * + * Allocated and initialized with ::BrotliDecoderCreateInstance. + * Cleaned up and deallocated with ::BrotliDecoderDestroyInstance. + */ +typedef struct BrotliDecoderStateStruct BrotliDecoderState; + +/** + * Result type for ::BrotliDecoderDecompress and + * ::BrotliDecoderDecompressStream functions. + */ +typedef enum { + /** Decoding error, e.g. corrupted input or memory allocation problem. */ + BROTLI_DECODER_RESULT_ERROR = 0, + /** Decoding successfully completed. */ + BROTLI_DECODER_RESULT_SUCCESS = 1, + /** Partially done; should be called again with more input. */ + BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT = 2, + /** Partially done; should be called again with more output. */ + BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT = 3 +} BrotliDecoderResult; + +/** + * Template that evaluates items of ::BrotliDecoderErrorCode. + * + * Example: @code {.cpp} + * // Log Brotli error code. + * switch (brotliDecoderErrorCode) { + * #define CASE_(PREFIX, NAME, CODE) \ + * case BROTLI_DECODER ## PREFIX ## NAME: \ + * LOG(INFO) << "error code:" << #NAME; \ + * break; + * #define NEWLINE_ + * BROTLI_DECODER_ERROR_CODES_LIST(CASE_, NEWLINE_) + * #undef CASE_ + * #undef NEWLINE_ + * default: LOG(FATAL) << "unknown brotli error code"; + * } + * @endcode + */ +#define BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE, SEPARATOR) \ + BROTLI_ERROR_CODE(_, NO_ERROR, 0) SEPARATOR \ + /* Same as BrotliDecoderResult values */ \ + BROTLI_ERROR_CODE(_, SUCCESS, 1) SEPARATOR \ + BROTLI_ERROR_CODE(_, NEEDS_MORE_INPUT, 2) SEPARATOR \ + BROTLI_ERROR_CODE(_, NEEDS_MORE_OUTPUT, 3) SEPARATOR \ + \ + /* Errors caused by invalid input */ \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_NIBBLE, -1) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, RESERVED, -2) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_META_NIBBLE, -3) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_ALPHABET, -4) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_SAME, -5) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, CL_SPACE, -6) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, HUFFMAN_SPACE, -7) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, CONTEXT_MAP_REPEAT, -8) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_1, -9) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_2, -10) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, TRANSFORM, -11) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, DICTIONARY, -12) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, WINDOW_BITS, -13) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_1, -14) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_FORMAT_, DISTANCE, -16) SEPARATOR \ + \ + /* -17 code is reserved */ \ + \ + BROTLI_ERROR_CODE(_ERROR_, COMPOUND_DICTIONARY, -18) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_, DICTIONARY_NOT_SET, -19) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_, INVALID_ARGUMENTS, -20) SEPARATOR \ + \ + /* Memory allocation problems */ \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MODES, -21) SEPARATOR \ + /* Literal, insert and distance trees together */ \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, TREE_GROUPS, -22) SEPARATOR \ + /* -23..-24 codes are reserved for distinct tree groups */ \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MAP, -25) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_1, -26) SEPARATOR \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_2, -27) SEPARATOR \ + /* -28..-29 codes are reserved for dynamic ring-buffer allocation */ \ + BROTLI_ERROR_CODE(_ERROR_ALLOC_, BLOCK_TYPE_TREES, -30) SEPARATOR \ + \ + /* "Impossible" states */ \ + BROTLI_ERROR_CODE(_ERROR_, UNREACHABLE, -31) + +/** + * Error code for detailed logging / production debugging. + * + * See ::BrotliDecoderGetErrorCode and ::BROTLI_LAST_ERROR_CODE. + */ +typedef enum { +#define BROTLI_COMMA_ , +#define BROTLI_ERROR_CODE_ENUM_ITEM_(PREFIX, NAME, CODE) \ + BROTLI_DECODER ## PREFIX ## NAME = CODE + BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_ENUM_ITEM_, BROTLI_COMMA_) +} BrotliDecoderErrorCode; +#undef BROTLI_ERROR_CODE_ENUM_ITEM_ +#undef BROTLI_COMMA_ + +/** + * The value of the last error code, negative integer. + * + * All other error code values are in the range from ::BROTLI_LAST_ERROR_CODE + * to @c -1. There are also 4 other possible non-error codes @c 0 .. @c 3 in + * ::BrotliDecoderErrorCode enumeration. + */ +#define BROTLI_LAST_ERROR_CODE BROTLI_DECODER_ERROR_UNREACHABLE + +/** Options to be used with ::BrotliDecoderSetParameter. */ +typedef enum BrotliDecoderParameter { + /** + * Disable "canny" ring buffer allocation strategy. + * + * Ring buffer is allocated according to window size, despite the real size of + * the content. + */ + BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION = 0, + /** + * Flag that determines if "Large Window Brotli" is used. + */ + BROTLI_DECODER_PARAM_LARGE_WINDOW = 1 +} BrotliDecoderParameter; + +/** + * Sets the specified parameter to the given decoder instance. + * + * @param state decoder instance + * @param param parameter to set + * @param value new parameter value + * @returns ::BROTLI_FALSE if parameter is unrecognized, or value is invalid + * @returns ::BROTLI_TRUE if value is accepted + */ +BROTLI_DEC_API BROTLI_BOOL BrotliDecoderSetParameter( + BrotliDecoderState* state, BrotliDecoderParameter param, uint32_t value); + +/** + * Adds LZ77 prefix dictionary, adds or replaces built-in static dictionary and + * transforms. + * + * Attached dictionary ownership is not transferred. + * Data provided to this method should be kept accessible until + * decoding is finished and decoder instance is destroyed. + * + * @note Dictionaries can NOT be attached after actual decoding is started. + * + * @param state decoder instance + * @param type dictionary data format + * @param data_size length of memory region pointed by @p data + * @param data dictionary data in format corresponding to @p type + * @returns ::BROTLI_FALSE if dictionary is corrupted, + * or dictionary count limit is reached + * @returns ::BROTLI_TRUE if dictionary is accepted / attached + */ +BROTLI_DEC_API BROTLI_BOOL BrotliDecoderAttachDictionary( + BrotliDecoderState* state, BrotliSharedDictionaryType type, + size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]); + +/** + * Creates an instance of ::BrotliDecoderState and initializes it. + * + * The instance can be used once for decoding and should then be destroyed with + * ::BrotliDecoderDestroyInstance, it cannot be reused for a new decoding + * session. + * + * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the + * case they are both zero, default memory allocators are used. @p opaque is + * passed to @p alloc_func and @p free_func when they are called. @p free_func + * has to return without doing anything when asked to free a NULL pointer. + * + * @param alloc_func custom memory allocation function + * @param free_func custom memory free function + * @param opaque custom memory manager handle + * @returns @c 0 if instance can not be allocated or initialized + * @returns pointer to initialized ::BrotliDecoderState otherwise + */ +BROTLI_DEC_API BrotliDecoderState* BrotliDecoderCreateInstance( + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); + +/** + * Deinitializes and frees ::BrotliDecoderState instance. + * + * @param state decoder instance to be cleaned up and deallocated + */ +BROTLI_DEC_API void BrotliDecoderDestroyInstance(BrotliDecoderState* state); + +/** + * Performs one-shot memory-to-memory decompression. + * + * Decompresses the data in @p encoded_buffer into @p decoded_buffer, and sets + * @p *decoded_size to the decompressed length. + * + * @param encoded_size size of @p encoded_buffer + * @param encoded_buffer compressed data buffer with at least @p encoded_size + * addressable bytes + * @param[in, out] decoded_size @b in: size of @p decoded_buffer; \n + * @b out: length of decompressed data written to + * @p decoded_buffer + * @param decoded_buffer decompressed data destination buffer + * @returns ::BROTLI_DECODER_RESULT_ERROR if input is corrupted, memory + * allocation failed, or @p decoded_buffer is not large enough; + * @returns ::BROTLI_DECODER_RESULT_SUCCESS otherwise + */ +BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompress( + size_t encoded_size, + const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)], + size_t* decoded_size, + uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]); + +/** + * Decompresses the input stream to the output stream. + * + * The values @p *available_in and @p *available_out must specify the number of + * bytes addressable at @p *next_in and @p *next_out respectively. + * When @p *available_out is @c 0, @p next_out is allowed to be @c NULL. + * + * After each call, @p *available_in will be decremented by the amount of input + * bytes consumed, and the @p *next_in pointer will be incremented by that + * amount. Similarly, @p *available_out will be decremented by the amount of + * output bytes written, and the @p *next_out pointer will be incremented by + * that amount. + * + * @p total_out, if it is not a null-pointer, will be set to the number + * of bytes decompressed since the last @p state initialization. + * + * @note Input is never overconsumed, so @p next_in and @p available_in could be + * passed to the next consumer after decoding is complete. + * + * @param state decoder instance + * @param[in, out] available_in @b in: amount of available input; \n + * @b out: amount of unused input + * @param[in, out] next_in pointer to the next compressed byte + * @param[in, out] available_out @b in: length of output buffer; \n + * @b out: remaining size of output buffer + * @param[in, out] next_out output buffer cursor; + * can be @c NULL if @p available_out is @c 0 + * @param[out] total_out number of bytes decompressed so far; can be @c NULL + * @returns ::BROTLI_DECODER_RESULT_ERROR if input is corrupted, memory + * allocation failed, arguments were invalid, etc.; + * use ::BrotliDecoderGetErrorCode to get detailed error code + * @returns ::BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT decoding is blocked until + * more input data is provided + * @returns ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT decoding is blocked until + * more output space is provided + * @returns ::BROTLI_DECODER_RESULT_SUCCESS decoding is finished, no more + * input might be consumed and no more output will be produced + */ +BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompressStream( + BrotliDecoderState* state, size_t* available_in, const uint8_t** next_in, + size_t* available_out, uint8_t** next_out, size_t* total_out); + +/** + * Checks if decoder has more output. + * + * @param state decoder instance + * @returns ::BROTLI_TRUE, if decoder has some unconsumed output + * @returns ::BROTLI_FALSE otherwise + */ +BROTLI_DEC_API BROTLI_BOOL BrotliDecoderHasMoreOutput( + const BrotliDecoderState* state); + +/** + * Acquires pointer to internal output buffer. + * + * This method is used to make language bindings easier and more efficient: + * -# push data to ::BrotliDecoderDecompressStream, + * until ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT is reported + * -# use ::BrotliDecoderTakeOutput to peek bytes and copy to language-specific + * entity + * + * Also this could be useful if there is an output stream that is able to + * consume all the provided data (e.g. when data is saved to file system). + * + * @attention After every call to ::BrotliDecoderTakeOutput @p *size bytes of + * output are considered consumed for all consecutive calls to the + * instance methods; returned pointer becomes invalidated as well. + * + * @note Decoder output is not guaranteed to be contiguous. This means that + * after the size-unrestricted call to ::BrotliDecoderTakeOutput, + * immediate next call to ::BrotliDecoderTakeOutput may return more data. + * + * @param state decoder instance + * @param[in, out] size @b in: number of bytes caller is ready to take, @c 0 if + * any amount could be handled; \n + * @b out: amount of data pointed by returned pointer and + * considered consumed; \n + * out value is never greater than in value, unless it is @c 0 + * @returns pointer to output data + */ +BROTLI_DEC_API const uint8_t* BrotliDecoderTakeOutput( + BrotliDecoderState* state, size_t* size); + +/** + * Checks if instance has already consumed input. + * + * Instance that returns ::BROTLI_FALSE is considered "fresh" and could be + * reused. + * + * @param state decoder instance + * @returns ::BROTLI_TRUE if decoder has already used some input bytes + * @returns ::BROTLI_FALSE otherwise + */ +BROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* state); + +/** + * Checks if decoder instance reached the final state. + * + * @param state decoder instance + * @returns ::BROTLI_TRUE if decoder is in a state where it reached the end of + * the input and produced all of the output + * @returns ::BROTLI_FALSE otherwise + */ +BROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsFinished( + const BrotliDecoderState* state); + +/** + * Acquires a detailed error code. + * + * Should be used only after ::BrotliDecoderDecompressStream returns + * ::BROTLI_DECODER_RESULT_ERROR. + * + * See also ::BrotliDecoderErrorString + * + * @param state decoder instance + * @returns last saved error code + */ +BROTLI_DEC_API BrotliDecoderErrorCode BrotliDecoderGetErrorCode( + const BrotliDecoderState* state); + +/** + * Converts error code to a c-string. + */ +BROTLI_DEC_API const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c); + +/** + * Gets a decoder library version. + * + * Look at BROTLI_MAKE_HEX_VERSION for more information. + */ +BROTLI_DEC_API uint32_t BrotliDecoderVersion(void); + +/** + * Callback to fire on metadata block start. + * + * After this callback is fired, if @p size is not @c 0, it is followed by + * ::brotli_decoder_metadata_chunk_func as more metadata block contents become + * accessible. + * + * @param opaque callback handle + * @param size size of metadata block + */ +typedef void (*brotli_decoder_metadata_start_func)(void* opaque, size_t size); + +/** + * Callback to fire on metadata block chunk becomes available. + * + * This function can be invoked multiple times per metadata block; block should + * be considered finished when sum of @p size matches the announced metadata + * block size. Chunks contents pointed by @p data are transient and shouln not + * be accessed after leaving the callback. + * + * @param opaque callback handle + * @param data pointer to metadata contents + * @param size size of metadata block chunk, at least @c 1 + */ +typedef void (*brotli_decoder_metadata_chunk_func)(void* opaque, + const uint8_t* data, + size_t size); + +/** + * Sets callback for receiving metadata blocks. + * + * @param state decoder instance + * @param start_func callback on metadata block start + * @param chunk_func callback on metadata block chunk + * @param opaque callback handle + */ +BROTLI_DEC_API void BrotliDecoderSetMetadataCallbacks( + BrotliDecoderState* state, + brotli_decoder_metadata_start_func start_func, + brotli_decoder_metadata_chunk_func chunk_func, void* opaque); + +} + +#endif /* BROTLI_DEC_DECODE_H_ */ diff --git a/third_party/brotli/include/brotli/encode.h b/third_party/brotli/include/brotli/encode.h new file mode 100644 index 00000000000..e3c3f55eda2 --- /dev/null +++ b/third_party/brotli/include/brotli/encode.h @@ -0,0 +1,489 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/** + * @file + * API for Brotli compression. + */ + +#ifndef BROTLI_ENC_ENCODE_H_ +#define BROTLI_ENC_ENCODE_H_ + +#include +#include +#include + + +/** Minimal value for ::BROTLI_PARAM_LGWIN parameter. */ +#define BROTLI_MIN_WINDOW_BITS 10 +/** + * Maximal value for ::BROTLI_PARAM_LGWIN parameter. + * + * @note equal to @c BROTLI_MAX_DISTANCE_BITS constant. + */ +#define BROTLI_MAX_WINDOW_BITS 24 +/** + * Maximal value for ::BROTLI_PARAM_LGWIN parameter + * in "Large Window Brotli" (32-bit). + */ +#define BROTLI_LARGE_MAX_WINDOW_BITS 30 +/** Minimal value for ::BROTLI_PARAM_LGBLOCK parameter. */ +#define BROTLI_MIN_INPUT_BLOCK_BITS 16 +/** Maximal value for ::BROTLI_PARAM_LGBLOCK parameter. */ +#define BROTLI_MAX_INPUT_BLOCK_BITS 24 +/** Minimal value for ::BROTLI_PARAM_QUALITY parameter. */ +#define BROTLI_MIN_QUALITY 0 +/** Maximal value for ::BROTLI_PARAM_QUALITY parameter. */ +#define BROTLI_MAX_QUALITY 11 + +/** Options for ::BROTLI_PARAM_MODE parameter. */ +typedef enum BrotliEncoderMode { + /** + * Default compression mode. + * + * In this mode compressor does not know anything in advance about the + * properties of the input. + */ + BROTLI_MODE_GENERIC = 0, + /** Compression mode for UTF-8 formatted text input. */ + BROTLI_MODE_TEXT = 1, + /** Compression mode used in WOFF 2.0. */ + BROTLI_MODE_FONT = 2 +} BrotliEncoderMode; + +namespace duckdb_brotli { + + +/** Default value for ::BROTLI_PARAM_QUALITY parameter. */ +#define BROTLI_DEFAULT_QUALITY 11 +/** Default value for ::BROTLI_PARAM_LGWIN parameter. */ +#define BROTLI_DEFAULT_WINDOW 22 +/** Default value for ::BROTLI_PARAM_MODE parameter. */ +#define BROTLI_DEFAULT_MODE BROTLI_MODE_GENERIC + +/** Operations that can be performed by streaming encoder. */ +typedef enum BrotliEncoderOperation { + /** + * Process input. + * + * Encoder may postpone producing output, until it has processed enough input. + */ + BROTLI_OPERATION_PROCESS = 0, + /** + * Produce output for all processed input. + * + * Actual flush is performed when input stream is depleted and there is enough + * space in output stream. This means that client should repeat + * ::BROTLI_OPERATION_FLUSH operation until @p available_in becomes @c 0, and + * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired + * via ::BrotliEncoderTakeOutput, then operation should be repeated after + * output buffer is drained. + * + * @warning Until flush is complete, client @b SHOULD @b NOT swap, + * reduce or extend input stream. + * + * When flush is complete, output data will be sufficient for decoder to + * reproduce all the given input. + */ + BROTLI_OPERATION_FLUSH = 1, + /** + * Finalize the stream. + * + * Actual finalization is performed when input stream is depleted and there is + * enough space in output stream. This means that client should repeat + * ::BROTLI_OPERATION_FINISH operation until @p available_in becomes @c 0, and + * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired + * via ::BrotliEncoderTakeOutput, then operation should be repeated after + * output buffer is drained. + * + * @warning Until finalization is complete, client @b SHOULD @b NOT swap, + * reduce or extend input stream. + * + * Helper function ::BrotliEncoderIsFinished checks if stream is finalized and + * output fully dumped. + * + * Adding more input data to finalized stream is impossible. + */ + BROTLI_OPERATION_FINISH = 2, + /** + * Emit metadata block to stream. + * + * Metadata is opaque to Brotli: neither encoder, nor decoder processes this + * data or relies on it. It may be used to pass some extra information from + * encoder client to decoder client without interfering with main data stream. + * + * @note Encoder may emit empty metadata blocks internally, to pad encoded + * stream to byte boundary. + * + * @warning Until emitting metadata is complete client @b SHOULD @b NOT swap, + * reduce or extend input stream. + * + * @warning The whole content of input buffer is considered to be the content + * of metadata block. Do @b NOT @e append metadata to input stream, + * before it is depleted with other operations. + * + * Stream is soft-flushed before metadata block is emitted. Metadata block + * @b MUST be no longer than than 16MiB. + */ + BROTLI_OPERATION_EMIT_METADATA = 3 +} BrotliEncoderOperation; + +/** Options to be used with ::BrotliEncoderSetParameter. */ +typedef enum BrotliEncoderParameter { + /** + * Tune encoder for specific input. + * + * ::BrotliEncoderMode enumerates all available values. + */ + BROTLI_PARAM_MODE = 0, + /** + * The main compression speed-density lever. + * + * The higher the quality, the slower the compression. Range is + * from ::BROTLI_MIN_QUALITY to ::BROTLI_MAX_QUALITY. + */ + BROTLI_PARAM_QUALITY = 1, + /** + * Recommended sliding LZ77 window size. + * + * Encoder may reduce this value, e.g. if input is much smaller than + * window size. + * + * Window size is `(1 << value) - 16`. + * + * Range is from ::BROTLI_MIN_WINDOW_BITS to ::BROTLI_MAX_WINDOW_BITS. + */ + BROTLI_PARAM_LGWIN = 2, + /** + * Recommended input block size. + * + * Encoder may reduce this value, e.g. if input is much smaller than input + * block size. + * + * Range is from ::BROTLI_MIN_INPUT_BLOCK_BITS to + * ::BROTLI_MAX_INPUT_BLOCK_BITS. + * + * @note Bigger input block size allows better compression, but consumes more + * memory. \n The rough formula of memory used for temporary input + * storage is `3 << lgBlock`. + */ + BROTLI_PARAM_LGBLOCK = 3, + /** + * Flag that affects usage of "literal context modeling" format feature. + * + * This flag is a "decoding-speed vs compression ratio" trade-off. + */ + BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING = 4, + /** + * Estimated total input size for all ::BrotliEncoderCompressStream calls. + * + * The default value is 0, which means that the total input size is unknown. + */ + BROTLI_PARAM_SIZE_HINT = 5, + /** + * Flag that determines if "Large Window Brotli" is used. + */ + BROTLI_PARAM_LARGE_WINDOW = 6, + /** + * Recommended number of postfix bits (NPOSTFIX). + * + * Encoder may change this value. + * + * Range is from 0 to ::BROTLI_MAX_NPOSTFIX. + */ + BROTLI_PARAM_NPOSTFIX = 7, + /** + * Recommended number of direct distance codes (NDIRECT). + * + * Encoder may change this value. + * + * Range is from 0 to (15 << NPOSTFIX) in steps of (1 << NPOSTFIX). + */ + BROTLI_PARAM_NDIRECT = 8, + /** + * Number of bytes of input stream already processed by a different instance. + * + * @note It is important to configure all the encoder instances with same + * parameters (except this one) in order to allow all the encoded parts + * obey the same restrictions implied by header. + * + * If offset is not 0, then stream header is omitted. + * In any case output start is byte aligned, so for proper streams stitching + * "predecessor" stream must be flushed. + * + * Range is not artificially limited, but all the values greater or equal to + * maximal window size have the same effect. Values greater than 2**30 are not + * allowed. + */ + BROTLI_PARAM_STREAM_OFFSET = 9 +} BrotliEncoderParameter; + +/** + * Opaque structure that holds encoder state. + * + * Allocated and initialized with ::BrotliEncoderCreateInstance. + * Cleaned up and deallocated with ::BrotliEncoderDestroyInstance. + */ +typedef struct BrotliEncoderStateStruct BrotliEncoderState; + +/** + * Sets the specified parameter to the given encoder instance. + * + * @param state encoder instance + * @param param parameter to set + * @param value new parameter value + * @returns ::BROTLI_FALSE if parameter is unrecognized, or value is invalid + * @returns ::BROTLI_FALSE if value of parameter can not be changed at current + * encoder state (e.g. when encoding is started, window size might be + * already encoded and therefore it is impossible to change it) + * @returns ::BROTLI_TRUE if value is accepted + * @warning invalid values might be accepted in case they would not break + * encoding process. + */ +BROTLI_ENC_API BROTLI_BOOL BrotliEncoderSetParameter(BrotliEncoderState *state, BrotliEncoderParameter param, + uint32_t value); + +/** + * Creates an instance of ::BrotliEncoderState and initializes it. + * + * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the + * case they are both zero, default memory allocators are used. @p opaque is + * passed to @p alloc_func and @p free_func when they are called. @p free_func + * has to return without doing anything when asked to free a NULL pointer. + * + * @param alloc_func custom memory allocation function + * @param free_func custom memory free function + * @param opaque custom memory manager handle + * @returns @c 0 if instance can not be allocated or initialized + * @returns pointer to initialized ::BrotliEncoderState otherwise + */ +BROTLI_ENC_API BrotliEncoderState *BrotliEncoderCreateInstance(brotli_alloc_func alloc_func, brotli_free_func free_func, + void *opaque); + +/** + * Deinitializes and frees ::BrotliEncoderState instance. + * + * @param state decoder instance to be cleaned up and deallocated + */ +BROTLI_ENC_API void BrotliEncoderDestroyInstance(BrotliEncoderState *state); + +/* Opaque type for pointer to different possible internal structures containing + dictionary prepared for the encoder */ +typedef struct BrotliEncoderPreparedDictionaryStruct BrotliEncoderPreparedDictionary; + +/** + * Prepares a shared dictionary from the given file format for the encoder. + * + * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the + * case they are both zero, default memory allocators are used. @p opaque is + * passed to @p alloc_func and @p free_func when they are called. @p free_func + * has to return without doing anything when asked to free a NULL pointer. + * + * @param type type of dictionary stored in data + * @param data_size size of @p data buffer + * @param data pointer to the dictionary data + * @param quality the maximum Brotli quality to prepare the dictionary for, + * use BROTLI_MAX_QUALITY by default + * @param alloc_func custom memory allocation function + * @param free_func custom memory free function + * @param opaque custom memory manager handle + */ +BROTLI_ENC_API BrotliEncoderPreparedDictionary * +BrotliEncoderPrepareDictionary(BrotliSharedDictionaryType type, size_t data_size, + const uint8_t data[BROTLI_ARRAY_PARAM(data_size)], int quality, + brotli_alloc_func alloc_func, brotli_free_func free_func, void *opaque); + +BROTLI_ENC_API void BrotliEncoderDestroyPreparedDictionary(BrotliEncoderPreparedDictionary *dictionary); + +/** + * Attaches a prepared dictionary of any type to the encoder. Can be used + * multiple times to attach multiple dictionaries. The dictionary type was + * determined by BrotliEncoderPrepareDictionary. Multiple raw prefix + * dictionaries and/or max 1 serialized dictionary with custom words can be + * attached. + * + * @returns ::BROTLI_FALSE in case of error + * @returns ::BROTLI_TRUE otherwise + */ +BROTLI_ENC_API BROTLI_BOOL BrotliEncoderAttachPreparedDictionary(BrotliEncoderState *state, + const BrotliEncoderPreparedDictionary *dictionary); + +/** + * Calculates the output size bound for the given @p input_size. + * + * @warning Result is only valid if quality is at least @c 2 and, in + * case ::BrotliEncoderCompressStream was used, no flushes + * (::BROTLI_OPERATION_FLUSH) were performed. + * + * @param input_size size of projected input + * @returns @c 0 if result does not fit @c size_t + */ +BROTLI_ENC_API size_t BrotliEncoderMaxCompressedSize(size_t input_size); + +/** + * Performs one-shot memory-to-memory compression. + * + * Compresses the data in @p input_buffer into @p encoded_buffer, and sets + * @p *encoded_size to the compressed length. + * + * @note If ::BrotliEncoderMaxCompressedSize(@p input_size) returns non-zero + * value, then output is guaranteed to be no longer than that. + * + * @note If @p lgwin is greater than ::BROTLI_MAX_WINDOW_BITS then resulting + * stream might be incompatible with RFC 7932; to decode such streams, + * decoder should be configured with + * ::BROTLI_DECODER_PARAM_LARGE_WINDOW = @c 1 + * + * @param quality quality parameter value, e.g. ::BROTLI_DEFAULT_QUALITY + * @param lgwin lgwin parameter value, e.g. ::BROTLI_DEFAULT_WINDOW + * @param mode mode parameter value, e.g. ::BROTLI_DEFAULT_MODE + * @param input_size size of @p input_buffer + * @param input_buffer input data buffer with at least @p input_size + * addressable bytes + * @param[in, out] encoded_size @b in: size of @p encoded_buffer; \n + * @b out: length of compressed data written to + * @p encoded_buffer, or @c 0 if compression fails + * @param encoded_buffer compressed data destination buffer + * @returns ::BROTLI_FALSE in case of compression error + * @returns ::BROTLI_FALSE if output buffer is too small + * @returns ::BROTLI_TRUE otherwise + */ +BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress(int quality, int lgwin, BrotliEncoderMode mode, size_t input_size, + const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)], + size_t *encoded_size, + uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]); + +/** + * Compresses input stream to output stream. + * + * The values @p *available_in and @p *available_out must specify the number of + * bytes addressable at @p *next_in and @p *next_out respectively. + * When @p *available_out is @c 0, @p next_out is allowed to be @c NULL. + * + * After each call, @p *available_in will be decremented by the amount of input + * bytes consumed, and the @p *next_in pointer will be incremented by that + * amount. Similarly, @p *available_out will be decremented by the amount of + * output bytes written, and the @p *next_out pointer will be incremented by + * that amount. + * + * @p total_out, if it is not a null-pointer, will be set to the number + * of bytes compressed since the last @p state initialization. + * + * + * + * Internally workflow consists of 3 tasks: + * -# (optionally) copy input data to internal buffer + * -# actually compress data and (optionally) store it to internal buffer + * -# (optionally) copy compressed bytes from internal buffer to output stream + * + * Whenever all 3 tasks can't move forward anymore, or error occurs, this + * method returns the control flow to caller. + * + * @p op is used to perform flush, finish the stream, or inject metadata block. + * See ::BrotliEncoderOperation for more information. + * + * Flushing the stream means forcing encoding of all input passed to encoder and + * completing the current output block, so it could be fully decoded by stream + * decoder. To perform flush set @p op to ::BROTLI_OPERATION_FLUSH. + * Under some circumstances (e.g. lack of output stream capacity) this operation + * would require several calls to ::BrotliEncoderCompressStream. The method must + * be called again until both input stream is depleted and encoder has no more + * output (see ::BrotliEncoderHasMoreOutput) after the method is called. + * + * Finishing the stream means encoding of all input passed to encoder and + * adding specific "final" marks, so stream decoder could determine that stream + * is complete. To perform finish set @p op to ::BROTLI_OPERATION_FINISH. + * Under some circumstances (e.g. lack of output stream capacity) this operation + * would require several calls to ::BrotliEncoderCompressStream. The method must + * be called again until both input stream is depleted and encoder has no more + * output (see ::BrotliEncoderHasMoreOutput) after the method is called. + * + * @warning When flushing and finishing, @p op should not change until operation + * is complete; input stream should not be swapped, reduced or + * extended as well. + * + * @param state encoder instance + * @param op requested operation + * @param[in, out] available_in @b in: amount of available input; \n + * @b out: amount of unused input + * @param[in, out] next_in pointer to the next input byte + * @param[in, out] available_out @b in: length of output buffer; \n + * @b out: remaining size of output buffer + * @param[in, out] next_out compressed output buffer cursor; + * can be @c NULL if @p available_out is @c 0 + * @param[out] total_out number of bytes produced so far; can be @c NULL + * @returns ::BROTLI_FALSE if there was an error + * @returns ::BROTLI_TRUE otherwise + */ +BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompressStream(BrotliEncoderState *state, BrotliEncoderOperation op, + size_t *available_in, const uint8_t **next_in, + size_t *available_out, uint8_t **next_out, size_t *total_out); + +/** + * Checks if encoder instance reached the final state. + * + * @param state encoder instance + * @returns ::BROTLI_TRUE if encoder is in a state where it reached the end of + * the input and produced all of the output + * @returns ::BROTLI_FALSE otherwise + */ +BROTLI_ENC_API BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState *state); + +/** + * Checks if encoder has more output. + * + * @param state encoder instance + * @returns ::BROTLI_TRUE, if encoder has some unconsumed output + * @returns ::BROTLI_FALSE otherwise + */ +BROTLI_ENC_API BROTLI_BOOL BrotliEncoderHasMoreOutput(BrotliEncoderState *state); + +/** + * Acquires pointer to internal output buffer. + * + * This method is used to make language bindings easier and more efficient: + * -# push data to ::BrotliEncoderCompressStream, + * until ::BrotliEncoderHasMoreOutput returns BROTLI_TRUE + * -# use ::BrotliEncoderTakeOutput to peek bytes and copy to language-specific + * entity + * + * Also this could be useful if there is an output stream that is able to + * consume all the provided data (e.g. when data is saved to file system). + * + * @attention After every call to ::BrotliEncoderTakeOutput @p *size bytes of + * output are considered consumed for all consecutive calls to the + * instance methods; returned pointer becomes invalidated as well. + * + * @note Encoder output is not guaranteed to be contiguous. This means that + * after the size-unrestricted call to ::BrotliEncoderTakeOutput, + * immediate next call to ::BrotliEncoderTakeOutput may return more data. + * + * @param state encoder instance + * @param[in, out] size @b in: number of bytes caller is ready to take, @c 0 if + * any amount could be handled; \n + * @b out: amount of data pointed by returned pointer and + * considered consumed; \n + * out value is never greater than in value, unless it is @c 0 + * @returns pointer to output data + */ +BROTLI_ENC_API const uint8_t *BrotliEncoderTakeOutput(BrotliEncoderState *state, size_t *size); + +/* Returns the estimated peak memory usage (in bytes) of the BrotliCompress() + function, not counting the memory needed for the input and output. */ +BROTLI_ENC_EXTRA_API size_t BrotliEncoderEstimatePeakMemoryUsage(int quality, int lgwin, size_t input_size); +/* Returns 0 if dictionary is not valid; otherwise returns allocation size. */ +BROTLI_ENC_EXTRA_API size_t BrotliEncoderGetPreparedDictionarySize(const BrotliEncoderPreparedDictionary *dictionary); + +/** + * Gets an encoder library version. + * + * Look at BROTLI_MAKE_HEX_VERSION for more information. + */ +BROTLI_ENC_API uint32_t BrotliEncoderVersion(void); + +} + +#endif /* BROTLI_ENC_ENCODE_H_ */ diff --git a/third_party/brotli/include/brotli/port.h b/third_party/brotli/include/brotli/port.h new file mode 100644 index 00000000000..d92fcd4c6a5 --- /dev/null +++ b/third_party/brotli/include/brotli/port.h @@ -0,0 +1,238 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* Macros for compiler / platform specific API declarations. */ + +#ifndef BROTLI_COMMON_PORT_H_ +#define BROTLI_COMMON_PORT_H_ + +/* The following macros were borrowed from https://github.com/nemequ/hedley + * with permission of original author - Evan Nemerson */ + +/* >>> >>> >>> hedley macros */ + +#define BROTLI_MAKE_VERSION(major, minor, revision) \ + (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) +#define BROTLI_GNUC_VERSION \ + BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) +#define BROTLI_GNUC_VERSION BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(BROTLI_GNUC_VERSION) +#define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) \ + (BROTLI_GNUC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) +#else +#define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) +#define BROTLI_MSVC_VERSION \ + BROTLI_MAKE_VERSION((_MSC_FULL_VER / 10000000), \ + (_MSC_FULL_VER % 10000000) / 100000, \ + (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) +#define BROTLI_MSVC_VERSION \ + BROTLI_MAKE_VERSION((_MSC_FULL_VER / 1000000), \ + (_MSC_FULL_VER % 1000000) / 10000, \ + (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) +#define BROTLI_MSVC_VERSION \ + BROTLI_MAKE_VERSION(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if !defined(_MSC_VER) +#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) +#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \ + (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) +#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \ + (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else +#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \ + (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) +#define BROTLI_INTEL_VERSION \ + BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100, \ + __INTEL_COMPILER % 100, \ + __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) +#define BROTLI_INTEL_VERSION \ + BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(BROTLI_INTEL_VERSION) +#define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) \ + (BROTLI_INTEL_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) +#else +#define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(__PGI) && \ + defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) +#define BROTLI_PGI_VERSION \ + BROTLI_MAKE_VERSION(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(BROTLI_PGI_VERSION) +#define BROTLI_PGI_VERSION_CHECK(major, minor, patch) \ + (BROTLI_PGI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) +#else +#define BROTLI_PGI_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) +#define BROTLI_SUNPRO_VERSION \ + BROTLI_MAKE_VERSION( \ + (((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), \ + (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), \ + (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) +#define BROTLI_SUNPRO_VERSION \ + BROTLI_MAKE_VERSION((__SUNPRO_C >> 8) & 0xf, \ + (__SUNPRO_C >> 4) & 0xf, \ + (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) +#define BROTLI_SUNPRO_VERSION \ + BROTLI_MAKE_VERSION( \ + (((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), \ + (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), \ + (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) +#define BROTLI_SUNPRO_VERSION \ + BROTLI_MAKE_VERSION((__SUNPRO_CC >> 8) & 0xf, \ + (__SUNPRO_CC >> 4) & 0xf, \ + (__SUNPRO_CC) & 0xf) +#endif + +#if defined(BROTLI_SUNPRO_VERSION) +#define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) \ + (BROTLI_SUNPRO_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) +#else +#define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) +#define BROTLI_ARM_VERSION \ + BROTLI_MAKE_VERSION((__ARMCOMPILER_VERSION / 1000000), \ + (__ARMCOMPILER_VERSION % 1000000) / 10000, \ + (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) +#define BROTLI_ARM_VERSION \ + BROTLI_MAKE_VERSION((__ARMCC_VERSION / 1000000), \ + (__ARMCC_VERSION % 1000000) / 10000, \ + (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(BROTLI_ARM_VERSION) +#define BROTLI_ARM_VERSION_CHECK(major, minor, patch) \ + (BROTLI_ARM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) +#else +#define BROTLI_ARM_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(__ibmxl__) +#define BROTLI_IBM_VERSION \ + BROTLI_MAKE_VERSION(__ibmxl_version__, \ + __ibmxl_release__, \ + __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) +#define BROTLI_IBM_VERSION \ + BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) +#define BROTLI_IBM_VERSION BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(BROTLI_IBM_VERSION) +#define BROTLI_IBM_VERSION_CHECK(major, minor, patch) \ + (BROTLI_IBM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) +#else +#define BROTLI_IBM_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(__TI_COMPILER_VERSION__) +#define BROTLI_TI_VERSION \ + BROTLI_MAKE_VERSION((__TI_COMPILER_VERSION__ / 1000000), \ + (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ + (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(BROTLI_TI_VERSION) +#define BROTLI_TI_VERSION_CHECK(major, minor, patch) \ + (BROTLI_TI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) +#else +#define BROTLI_TI_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(__IAR_SYSTEMS_ICC__) +#if __VER__ > 1000 +#define BROTLI_IAR_VERSION \ + BROTLI_MAKE_VERSION((__VER__ / 1000000), \ + (__VER__ / 1000) % 1000, \ + (__VER__ % 1000)) +#else +#define BROTLI_IAR_VERSION BROTLI_MAKE_VERSION(VER / 100, __VER__ % 100, 0) +#endif +#endif + +#if defined(BROTLI_IAR_VERSION) +#define BROTLI_IAR_VERSION_CHECK(major, minor, patch) \ + (BROTLI_IAR_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) +#else +#define BROTLI_IAR_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(__TINYC__) +#define BROTLI_TINYC_VERSION \ + BROTLI_MAKE_VERSION(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(BROTLI_TINYC_VERSION) +#define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) \ + (BROTLI_TINYC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) +#else +#define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(__has_attribute) +#define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \ + __has_attribute(attribute) +#else +#define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \ + BROTLI_GNUC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(__has_builtin) +#define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \ + __has_builtin(builtin) +#else +#define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \ + BROTLI_GNUC_VERSION_CHECK(major, minor, patch) +#endif + +#if defined(__has_feature) +#define BROTLI_HAS_FEATURE(feature) __has_feature(feature) +#else +#define BROTLI_HAS_FEATURE(feature) (0) +#endif + + + +#define BROTLI_PUBLIC +#define BROTLI_INTERNAL +#define BROTLI_ARRAY_PARAM(name) +#define BROTLI_COMMON_API +#define BROTLI_DEC_API +#define BROTLI_ENC_API +#define BROTLI_ENC_EXTRA_API BROTLI_INTERNAL + + +#endif /* BROTLI_COMMON_PORT_H_ */ diff --git a/third_party/brotli/include/brotli/shared_dictionary.h b/third_party/brotli/include/brotli/shared_dictionary.h new file mode 100644 index 00000000000..19267536e6c --- /dev/null +++ b/third_party/brotli/include/brotli/shared_dictionary.h @@ -0,0 +1,96 @@ +/* Copyright 2017 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/* (Opaque) Shared Dictionary definition and utilities. */ + +#ifndef BROTLI_COMMON_SHARED_DICTIONARY_H_ +#define BROTLI_COMMON_SHARED_DICTIONARY_H_ + +#include +#include + +namespace duckdb_brotli { + +#define SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH 4 +#define SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH 31 +#define SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS 64 +#define SHARED_BROTLI_MAX_COMPOUND_DICTS 15 + +/** + * Opaque structure that holds shared dictionary data. + * + * Allocated and initialized with ::BrotliSharedDictionaryCreateInstance. + * Cleaned up and deallocated with ::BrotliSharedDictionaryDestroyInstance. + */ +typedef struct BrotliSharedDictionaryStruct BrotliSharedDictionary; + +/** + * Input data type for ::BrotliSharedDictionaryAttach. + */ +typedef enum BrotliSharedDictionaryType { + /** Raw LZ77 prefix dictionary. */ + BROTLI_SHARED_DICTIONARY_RAW = 0, + /** Serialized shared dictionary. + * + * DO NOT USE: methods accepting this value will fail. + */ + BROTLI_SHARED_DICTIONARY_SERIALIZED = 1 +} BrotliSharedDictionaryType; + +/** + * Creates an instance of ::BrotliSharedDictionary. + * + * Fresh instance has default word dictionary and transforms + * and no LZ77 prefix dictionary. + * + * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the + * case they are both zero, default memory allocators are used. @p opaque is + * passed to @p alloc_func and @p free_func when they are called. @p free_func + * has to return without doing anything when asked to free a NULL pointer. + * + * @param alloc_func custom memory allocation function + * @param free_func custom memory free function + * @param opaque custom memory manager handle + * @returns @c 0 if instance can not be allocated or initialized + * @returns pointer to initialized ::BrotliSharedDictionary otherwise + */ +BROTLI_COMMON_API BrotliSharedDictionary* BrotliSharedDictionaryCreateInstance( + brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque); + +/** + * Deinitializes and frees ::BrotliSharedDictionary instance. + * + * @param dict shared dictionary instance to be cleaned up and deallocated + */ +BROTLI_COMMON_API void BrotliSharedDictionaryDestroyInstance( + BrotliSharedDictionary* dict); + +/** + * Attaches dictionary to a given instance of ::BrotliSharedDictionary. + * + * Dictionary to be attached is represented in a serialized format as a region + * of memory. + * + * Provided data it partially referenced by a resulting (compound) dictionary, + * and should be kept untouched, while at least one compound dictionary uses it. + * This way memory overhead is kept minimal by the cost of additional resource + * management. + * + * @param dict dictionary to extend + * @param type type of dictionary to attach + * @param data_size size of @p data + * @param data serialized dictionary of type @p type, with at least @p data_size + * addressable bytes + * @returns ::BROTLI_TRUE if provided dictionary is successfully attached + * @returns ::BROTLI_FALSE otherwise + */ +BROTLI_COMMON_API BROTLI_BOOL BrotliSharedDictionaryAttach( + BrotliSharedDictionary* dict, BrotliSharedDictionaryType type, + size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]); + +} + +#endif /* BROTLI_COMMON_SHARED_DICTIONARY_H_ */ diff --git a/third_party/brotli/include/brotli/types.h b/third_party/brotli/include/brotli/types.h new file mode 100644 index 00000000000..eff1a3cd07a --- /dev/null +++ b/third_party/brotli/include/brotli/types.h @@ -0,0 +1,83 @@ +/* Copyright 2013 Google Inc. All Rights Reserved. + + Distributed under MIT license. + See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +*/ + +/** + * @file + * Common types used in decoder and encoder API. + */ + +#ifndef BROTLI_COMMON_TYPES_H_ +#define BROTLI_COMMON_TYPES_H_ + +#include /* for size_t */ + +#if defined(_MSC_VER) && (_MSC_VER < 1600) +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +typedef __int64 int64_t; +#else +#include +#endif /* defined(_MSC_VER) && (_MSC_VER < 1600) */ + +/** + * A portable @c bool replacement. + * + * ::BROTLI_BOOL is a "documentation" type: actually it is @c int, but in API it + * denotes a type, whose only values are ::BROTLI_TRUE and ::BROTLI_FALSE. + * + * ::BROTLI_BOOL values passed to Brotli should either be ::BROTLI_TRUE or + * ::BROTLI_FALSE, or be a result of ::TO_BROTLI_BOOL macros. + * + * ::BROTLI_BOOL values returned by Brotli should not be tested for equality + * with @c true, @c false, ::BROTLI_TRUE, ::BROTLI_FALSE, but rather should be + * evaluated, for example: @code{.cpp} + * if (SomeBrotliFunction(encoder, BROTLI_TRUE) && + * !OtherBrotliFunction(decoder, BROTLI_FALSE)) { + * bool x = !!YetAnotherBrotliFunction(encoder, TO_BROLTI_BOOL(2 * 2 == 4)); + * DoSomething(x); + * } + * @endcode + */ +#define BROTLI_BOOL int +/** Portable @c true replacement. */ +#define BROTLI_TRUE 1 +/** Portable @c false replacement. */ +#define BROTLI_FALSE 0 +/** @c bool to ::BROTLI_BOOL conversion macros. */ +#define TO_BROTLI_BOOL(X) (!!(X) ? BROTLI_TRUE : BROTLI_FALSE) + +#define BROTLI_MAKE_UINT64_T(high, low) ((((uint64_t)(high)) << 32) | low) + +#define BROTLI_UINT32_MAX (~((uint32_t)0)) +#define BROTLI_SIZE_MAX (~((size_t)0)) + +/** + * Allocating function pointer type. + * + * @param opaque custom memory manager handle provided by client + * @param size requested memory region size; can not be @c 0 + * @returns @c 0 in the case of failure + * @returns a valid pointer to a memory region of at least @p size bytes + * long otherwise + */ +typedef void* (*brotli_alloc_func)(void* opaque, size_t size); + +/** + * Deallocating function pointer type. + * + * This function @b SHOULD do nothing if @p address is @c 0. + * + * @param opaque custom memory manager handle provided by client + * @param address memory region pointer returned by ::brotli_alloc_func, or @c 0 + */ +typedef void (*brotli_free_func)(void* opaque, void* address); + +#endif /* BROTLI_COMMON_TYPES_H_ */ diff --git a/third_party/hyperloglog/hyperloglog.hpp b/third_party/hyperloglog/hyperloglog.hpp index 461ecc53a56..68e3159f810 100644 --- a/third_party/hyperloglog/hyperloglog.hpp +++ b/third_party/hyperloglog/hyperloglog.hpp @@ -40,6 +40,10 @@ robj *hll_merge(robj **hlls, size_t hll_count); //! Get size (in bytes) of the HLL uint64_t get_size(); +//! Helper Functions +double hllSigma(double x); +double hllTau(double x); + uint64_t MurmurHash64A(const void *key, int len, unsigned int seed); // NOLINTEND diff --git a/third_party/imdb/CMakeLists.txt b/third_party/imdb/CMakeLists.txt index 5d10dde6d2d..5a681f28905 100644 --- a/third_party/imdb/CMakeLists.txt +++ b/third_party/imdb/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.5...3.29) if(POLICY CMP0063) cmake_policy(SET CMP0063 NEW) diff --git a/third_party/libpg_query/CMakeLists.txt b/third_party/libpg_query/CMakeLists.txt index 5cb0aa6f614..8020d93395b 100644 --- a/third_party/libpg_query/CMakeLists.txt +++ b/third_party/libpg_query/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.5...3.29) project(duckdb_pg_query CXX C) if(POLICY CMP0063) diff --git a/third_party/libpg_query/grammar/grammar.y b/third_party/libpg_query/grammar/grammar.y index 3e580be4c03..e9ab7b4feb7 100644 --- a/third_party/libpg_query/grammar/grammar.y +++ b/third_party/libpg_query/grammar/grammar.y @@ -58,6 +58,8 @@ PGSubLinkType subquerytype; PGViewCheckOption viewcheckoption; PGInsertColumnOrder bynameorposition; + PGLoadInstallType loadinstalltype; + PGTransactionStmtType transactiontype; } %type stmt diff --git a/third_party/libpg_query/grammar/keywords/unreserved_keywords.list b/third_party/libpg_query/grammar/keywords/unreserved_keywords.list index 02c63fecd37..5621fb6b6df 100644 --- a/third_party/libpg_query/grammar/keywords/unreserved_keywords.list +++ b/third_party/libpg_query/grammar/keywords/unreserved_keywords.list @@ -89,6 +89,7 @@ EXPLAIN EXPORT_P EXPORT_STATE EXTENSION +EXTENSIONS EXTERNAL FAMILY FILTER @@ -206,6 +207,8 @@ PROCEDURAL PROCEDURE PROGRAM PUBLICATION +QUARTER_P +QUARTERS_P QUOTE RANGE READ_P diff --git a/third_party/libpg_query/grammar/statements.list b/third_party/libpg_query/grammar/statements.list index b3c26fa85f7..6ddfbe4a5d0 100644 --- a/third_party/libpg_query/grammar/statements.list +++ b/third_party/libpg_query/grammar/statements.list @@ -32,6 +32,7 @@ RenameStmt SelectStmt TransactionStmt UpdateStmt +UpdateExtensionsStmt UseStmt VacuumStmt VariableResetStmt diff --git a/third_party/libpg_query/grammar/statements/explain.y b/third_party/libpg_query/grammar/statements/explain.y index e6f342b1e83..35018ee3ee9 100644 --- a/third_party/libpg_query/grammar/statements/explain.y +++ b/third_party/libpg_query/grammar/statements/explain.y @@ -79,6 +79,7 @@ ExplainableStmt: | SelectStmt | TransactionStmt | UpdateStmt + | UpdateExtensionsStmt | VacuumStmt | VariableResetStmt | VariableSetStmt diff --git a/third_party/libpg_query/grammar/statements/load.y b/third_party/libpg_query/grammar/statements/load.y index 897986d2daa..79a16dbcd3a 100644 --- a/third_party/libpg_query/grammar/statements/load.y +++ b/third_party/libpg_query/grammar/statements/load.y @@ -8,42 +8,48 @@ LoadStmt: LOAD file_name { PGLoadStmt *n = makeNode(PGLoadStmt); n->filename = $2; - n->repository = ""; + n->repository = NULL; + n->repo_is_alias = false; + n->version = NULL; n->load_type = PG_LOAD_TYPE_LOAD; $$ = (PGNode *)n; } | - INSTALL file_name { + opt_force INSTALL file_name opt_ext_version { PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = $2; - n->repository = ""; - n->load_type = PG_LOAD_TYPE_INSTALL; + n->filename = $3; + n->repository = NULL; + n->repo_is_alias = false; + n->version = $4; + n->load_type = $1; $$ = (PGNode *)n; } | - FORCE INSTALL file_name { - PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = $3; - n->repository = ""; - n->load_type = PG_LOAD_TYPE_FORCE_INSTALL; - $$ = (PGNode *)n; - } | - INSTALL file_name FROM repo_path{ - PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = $2; - n->repository = $4; - n->load_type = PG_LOAD_TYPE_INSTALL; - $$ = (PGNode *)n; - } | - FORCE INSTALL file_name FROM repo_path { - PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = $3; - n->repository = $5; - n->load_type = PG_LOAD_TYPE_FORCE_INSTALL; - $$ = (PGNode *)n; - } + opt_force INSTALL file_name FROM ColId opt_ext_version { + PGLoadStmt *n = makeNode(PGLoadStmt); + n->repository = $5; + n->repo_is_alias = true; + n->filename = $3; + n->version = $6; + n->load_type = $1; + $$ = (PGNode *)n; + } | + opt_force INSTALL file_name FROM Sconst opt_ext_version { + PGLoadStmt *n = makeNode(PGLoadStmt); + n->filename = $3; + n->repository = $5; + n->repo_is_alias = false; + n->version = $6; + n->load_type = $1; + $$ = (PGNode *)n; + } ; +opt_force: /* empty*/ { $$ = PG_LOAD_TYPE_INSTALL; } | + FORCE { $$ = PG_LOAD_TYPE_FORCE_INSTALL; }; + file_name: Sconst { $$ = $1; } | ColId { $$ = $1; }; -repo_path: Sconst { $$ = $1; } | - ColId { $$ = $1; }; +opt_ext_version: + /* empty */ { $$ = NULL; } | + VERSION_P Sconst { $$ = $2; } | + VERSION_P ColId { $$ = $2; }; diff --git a/third_party/libpg_query/grammar/statements/select.y b/third_party/libpg_query/grammar/statements/select.y index 2d0d0f82868..b1a2d59684a 100644 --- a/third_party/libpg_query/grammar/statements/select.y +++ b/third_party/libpg_query/grammar/statements/select.y @@ -2040,6 +2040,9 @@ microsecond_keyword: week_keyword: WEEK_P | WEEKS_P +quarter_keyword: + QUARTER_P | QUARTERS_P + decade_keyword: DECADE_P | DECADES_P @@ -2068,6 +2071,8 @@ opt_interval: { $$ = list_make1(makeIntConst(INTERVAL_MASK(MICROSECOND), @1)); } | week_keyword { $$ = list_make1(makeIntConst(INTERVAL_MASK(WEEK), @1)); } + | quarter_keyword + { $$ = list_make1(makeIntConst(INTERVAL_MASK(QUARTER), @1)); } | decade_keyword { $$ = list_make1(makeIntConst(INTERVAL_MASK(DECADE), @1)); } | century_keyword @@ -2554,6 +2559,15 @@ a_expr: c_expr { $$ = $1; } n->location = @1; $$ = (PGNode *)n; } + | '*' COLUMNS '(' a_expr ')' + { + PGAStar *star = makeNode(PGAStar); + star->expr = $4; + star->columns = true; + star->unpacked = true; + star->location = @1; + $$ = (PGNode *) star; + } | COLUMNS '(' a_expr ')' { PGAStar *star = makeNode(PGAStar); @@ -3567,6 +3581,7 @@ extract_arg: | millisecond_keyword { $$ = (char*) "millisecond"; } | microsecond_keyword { $$ = (char*) "microsecond"; } | week_keyword { $$ = (char*) "week"; } + | quarter_keyword { $$ = (char*) "quarter"; } | decade_keyword { $$ = (char*) "decade"; } | century_keyword { $$ = (char*) "century"; } | millennium_keyword { $$ = (char*) "millennium"; } diff --git a/third_party/libpg_query/grammar/statements/transaction.y b/third_party/libpg_query/grammar/statements/transaction.y index ac443fe9e77..b9ebdf90a16 100644 --- a/third_party/libpg_query/grammar/statements/transaction.y +++ b/third_party/libpg_query/grammar/statements/transaction.y @@ -4,18 +4,21 @@ TransactionStmt: PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_ROLLBACK; n->options = NIL; + n->transaction_type = PG_TRANS_TYPE_DEFAULT; $$ = (PGNode *)n; } - | BEGIN_P opt_transaction + | BEGIN_P opt_transaction opt_transaction_type { PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_BEGIN; + n->transaction_type = $3; $$ = (PGNode *)n; } - | START opt_transaction + | START opt_transaction opt_transaction_type { PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_START; + n->transaction_type = $3; $$ = (PGNode *)n; } | COMMIT opt_transaction @@ -23,6 +26,7 @@ TransactionStmt: PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_COMMIT; n->options = NIL; + n->transaction_type = PG_TRANS_TYPE_DEFAULT; $$ = (PGNode *)n; } | END_P opt_transaction @@ -30,6 +34,7 @@ TransactionStmt: PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_COMMIT; n->options = NIL; + n->transaction_type = PG_TRANS_TYPE_DEFAULT; $$ = (PGNode *)n; } | ROLLBACK opt_transaction @@ -37,6 +42,7 @@ TransactionStmt: PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_ROLLBACK; n->options = NIL; + n->transaction_type = PG_TRANS_TYPE_DEFAULT; $$ = (PGNode *)n; } ; @@ -46,3 +52,9 @@ opt_transaction: WORK {} | TRANSACTION {} | /*EMPTY*/ {} ; + +opt_transaction_type: + READ_P ONLY { $$ = PG_TRANS_TYPE_READ_ONLY; } + | READ_P WRITE_P { $$ = PG_TRANS_TYPE_READ_WRITE; } + | /*EMPTY*/ { $$ = PG_TRANS_TYPE_DEFAULT; } + ; diff --git a/third_party/libpg_query/grammar/statements/update_extensions.y b/third_party/libpg_query/grammar/statements/update_extensions.y new file mode 100644 index 00000000000..f18c2218f83 --- /dev/null +++ b/third_party/libpg_query/grammar/statements/update_extensions.y @@ -0,0 +1,22 @@ +/***************************************************************************** + * + * QUERY: + * PGUpdateExtensionsStmt (UPDATE EXTENSIONS) + * + *****************************************************************************/ +UpdateExtensionsStmt: opt_with_clause UPDATE EXTENSIONS opt_column_list + { + PGUpdateExtensionsStmt *n = makeNode(PGUpdateExtensionsStmt); + n->extensions = $4; + + if ($1) { + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("Providing a with clause with an UPDATE EXTENSIONS statement is not allowed"), + parser_errposition(@1))); + break; + } + + $$ = (PGNode *)n; + } + ; diff --git a/third_party/libpg_query/grammar/types/load.yh b/third_party/libpg_query/grammar/types/load.yh index 207b9d2c036..f2199b3a410 100644 --- a/third_party/libpg_query/grammar/types/load.yh +++ b/third_party/libpg_query/grammar/types/load.yh @@ -1,2 +1,3 @@ %type file_name -%type repo_path +%type opt_ext_version +%type opt_force \ No newline at end of file diff --git a/third_party/libpg_query/grammar/types/transaction.yh b/third_party/libpg_query/grammar/types/transaction.yh new file mode 100644 index 00000000000..fe829c5bc09 --- /dev/null +++ b/third_party/libpg_query/grammar/types/transaction.yh @@ -0,0 +1 @@ +%type opt_transaction_type diff --git a/third_party/libpg_query/include/nodes/nodes.hpp b/third_party/libpg_query/include/nodes/nodes.hpp index 32c08a874f6..85ad6793516 100755 --- a/third_party/libpg_query/include/nodes/nodes.hpp +++ b/third_party/libpg_query/include/nodes/nodes.hpp @@ -312,6 +312,7 @@ typedef enum PGNodeTag { T_PGInsertStmt, T_PGDeleteStmt, T_PGUpdateStmt, + T_PGUpdateExtensionsStmt, T_PGSelectStmt, T_PGAlterTableStmt, T_PGAlterTableCmd, diff --git a/third_party/libpg_query/include/nodes/parsenodes.hpp b/third_party/libpg_query/include/nodes/parsenodes.hpp index 1a96c3212a9..93c2d690236 100755 --- a/third_party/libpg_query/include/nodes/parsenodes.hpp +++ b/third_party/libpg_query/include/nodes/parsenodes.hpp @@ -318,6 +318,7 @@ typedef struct PGAStar { PGList *except_list; /* optional: EXCLUDE list */ PGList *replace_list; /* optional: REPLACE list */ bool columns; /* whether or not this is a columns list */ + bool unpacked; /* whether or not the columns list is unpacked */ int location; } PGAStar; @@ -1857,11 +1858,18 @@ typedef enum PGTransactionStmtKind { TRANS_STMT_ROLLBACK_PREPARED } PGTransactionStmtKind; +typedef enum PGTransactionStmtType { + PG_TRANS_TYPE_DEFAULT, + PG_TRANS_TYPE_READ_ONLY, // explicit READ ONLY + PG_TRANS_TYPE_READ_WRITE // explicit READ WRITE +} PGTransactionStmtType; + typedef struct PGTransactionStmt { PGNodeTag type; - PGTransactionStmtKind kind; /* see above */ - PGList *options; /* for BEGIN/START and savepoint commands */ - char *gid; /* for two-phase-commit related commands */ + PGTransactionStmtKind kind; /* see above */ + PGList *options; /* for BEGIN/START and savepoint commands */ + char *gid; /* for two-phase-commit related commands */ + PGTransactionStmtType transaction_type; /* read only or read write */ } PGTransactionStmt; /* ---------------------- @@ -1892,9 +1900,21 @@ typedef struct PGLoadStmt { PGNodeTag type; const char *filename; /* file to load */ const char *repository; /* optionally, the repository to load from */ + bool repo_is_alias; /* whether the repository was passed as an alias or a raw path */ + const char *version; /* optionally, the version of the extension to be loaded */ PGLoadInstallType load_type; } PGLoadStmt; +/* ---------------------- + * Update Extensions Statement + * ---------------------- + */ + +typedef struct PGUpdateExtensionsStmt { + PGNodeTag type; + PGList * extensions; +} PGUpdateExtensionsStmt; + /* ---------------------- * Vacuum and Analyze Statements * diff --git a/third_party/libpg_query/include/parser/gram.hpp b/third_party/libpg_query/include/parser/gram.hpp index c6485a966c7..046d222b576 100644 --- a/third_party/libpg_query/include/parser/gram.hpp +++ b/third_party/libpg_query/include/parser/gram.hpp @@ -1,14 +1,14 @@ -/* A Bison parser, made by GNU Bison 2.3. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ -/* Skeleton interface for Bison's Yacc-like parsers in C +/* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,9 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -33,1023 +31,542 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ -/* Tokens. */ +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +#ifndef YY_BASE_YY_THIRD_PARTY_LIBPG_QUERY_GRAMMAR_GRAMMAR_OUT_HPP_INCLUDED +# define YY_BASE_YY_THIRD_PARTY_LIBPG_QUERY_GRAMMAR_GRAMMAR_OUT_HPP_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int base_yydebug; +#endif + +/* Token kinds. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - IDENT = 258, - FCONST = 259, - SCONST = 260, - BCONST = 261, - XCONST = 262, - Op = 263, - ICONST = 264, - PARAM = 265, - TYPECAST = 266, - DOT_DOT = 267, - COLON_EQUALS = 268, - EQUALS_GREATER = 269, - INTEGER_DIVISION = 270, - POWER_OF = 271, - LAMBDA_ARROW = 272, - DOUBLE_ARROW = 273, - LESS_EQUALS = 274, - GREATER_EQUALS = 275, - NOT_EQUALS = 276, - ABORT_P = 277, - ABSOLUTE_P = 278, - ACCESS = 279, - ACTION = 280, - ADD_P = 281, - ADMIN = 282, - AFTER = 283, - AGGREGATE = 284, - ALL = 285, - ALSO = 286, - ALTER = 287, - ALWAYS = 288, - ANALYSE = 289, - ANALYZE = 290, - AND = 291, - ANTI = 292, - ANY = 293, - ARRAY = 294, - AS = 295, - ASC_P = 296, - ASOF = 297, - ASSERTION = 298, - ASSIGNMENT = 299, - ASYMMETRIC = 300, - AT = 301, - ATTACH = 302, - ATTRIBUTE = 303, - AUTHORIZATION = 304, - BACKWARD = 305, - BEFORE = 306, - BEGIN_P = 307, - BETWEEN = 308, - BIGINT = 309, - BINARY = 310, - BIT = 311, - BOOLEAN_P = 312, - BOTH = 313, - BY = 314, - CACHE = 315, - CALL_P = 316, - CALLED = 317, - CASCADE = 318, - CASCADED = 319, - CASE = 320, - CAST = 321, - CATALOG_P = 322, - CENTURIES_P = 323, - CENTURY_P = 324, - CHAIN = 325, - CHAR_P = 326, - CHARACTER = 327, - CHARACTERISTICS = 328, - CHECK_P = 329, - CHECKPOINT = 330, - CLASS = 331, - CLOSE = 332, - CLUSTER = 333, - COALESCE = 334, - COLLATE = 335, - COLLATION = 336, - COLUMN = 337, - COLUMNS = 338, - COMMENT = 339, - COMMENTS = 340, - COMMIT = 341, - COMMITTED = 342, - COMPRESSION = 343, - CONCURRENTLY = 344, - CONFIGURATION = 345, - CONFLICT = 346, - CONNECTION = 347, - CONSTRAINT = 348, - CONSTRAINTS = 349, - CONTENT_P = 350, - CONTINUE_P = 351, - CONVERSION_P = 352, - COPY = 353, - COST = 354, - CREATE_P = 355, - CROSS = 356, - CSV = 357, - CUBE = 358, - CURRENT_P = 359, - CURSOR = 360, - CYCLE = 361, - DATA_P = 362, - DATABASE = 363, - DAY_P = 364, - DAYS_P = 365, - DEALLOCATE = 366, - DEC = 367, - DECADE_P = 368, - DECADES_P = 369, - DECIMAL_P = 370, - DECLARE = 371, - DEFAULT = 372, - DEFAULTS = 373, - DEFERRABLE = 374, - DEFERRED = 375, - DEFINER = 376, - DELETE_P = 377, - DELIMITER = 378, - DELIMITERS = 379, - DEPENDS = 380, - DESC_P = 381, - DESCRIBE = 382, - DETACH = 383, - DICTIONARY = 384, - DISABLE_P = 385, - DISCARD = 386, - DISTINCT = 387, - DO = 388, - DOCUMENT_P = 389, - DOMAIN_P = 390, - DOUBLE_P = 391, - DROP = 392, - EACH = 393, - ELSE = 394, - ENABLE_P = 395, - ENCODING = 396, - ENCRYPTED = 397, - END_P = 398, - ENUM_P = 399, - ESCAPE = 400, - EVENT = 401, - EXCEPT = 402, - EXCLUDE = 403, - EXCLUDING = 404, - EXCLUSIVE = 405, - EXECUTE = 406, - EXISTS = 407, - EXPLAIN = 408, - EXPORT_P = 409, - EXPORT_STATE = 410, - EXTENSION = 411, - EXTERNAL = 412, - EXTRACT = 413, - FALSE_P = 414, - FAMILY = 415, - FETCH = 416, - FILTER = 417, - FIRST_P = 418, - FLOAT_P = 419, - FOLLOWING = 420, - FOR = 421, - FORCE = 422, - FOREIGN = 423, - FORWARD = 424, - FREEZE = 425, - FROM = 426, - FULL = 427, - FUNCTION = 428, - FUNCTIONS = 429, - GENERATED = 430, - GLOB = 431, - GLOBAL = 432, - GRANT = 433, - GRANTED = 434, - GROUP_P = 435, - GROUPING = 436, - GROUPING_ID = 437, - GROUPS = 438, - HANDLER = 439, - HAVING = 440, - HEADER_P = 441, - HOLD = 442, - HOUR_P = 443, - HOURS_P = 444, - IDENTITY_P = 445, - IF_P = 446, - IGNORE_P = 447, - ILIKE = 448, - IMMEDIATE = 449, - IMMUTABLE = 450, - IMPLICIT_P = 451, - IMPORT_P = 452, - IN_P = 453, - INCLUDE_P = 454, - INCLUDING = 455, - INCREMENT = 456, - INDEX = 457, - INDEXES = 458, - INHERIT = 459, - INHERITS = 460, - INITIALLY = 461, - INLINE_P = 462, - INNER_P = 463, - INOUT = 464, - INPUT_P = 465, - INSENSITIVE = 466, - INSERT = 467, - INSTALL = 468, - INSTEAD = 469, - INT_P = 470, - INTEGER = 471, - INTERSECT = 472, - INTERVAL = 473, - INTO = 474, - INVOKER = 475, - IS = 476, - ISNULL = 477, - ISOLATION = 478, - JOIN = 479, - JSON = 480, - KEY = 481, - LABEL = 482, - LANGUAGE = 483, - LARGE_P = 484, - LAST_P = 485, - LATERAL_P = 486, - LEADING = 487, - LEAKPROOF = 488, - LEFT = 489, - LEVEL = 490, - LIKE = 491, - LIMIT = 492, - LISTEN = 493, - LOAD = 494, - LOCAL = 495, - LOCATION = 496, - LOCK_P = 497, - LOCKED = 498, - LOGGED = 499, - MACRO = 500, - MAP = 501, - MAPPING = 502, - MATCH = 503, - MATERIALIZED = 504, - MAXVALUE = 505, - METHOD = 506, - MICROSECOND_P = 507, - MICROSECONDS_P = 508, - MILLENNIA_P = 509, - MILLENNIUM_P = 510, - MILLISECOND_P = 511, - MILLISECONDS_P = 512, - MINUTE_P = 513, - MINUTES_P = 514, - MINVALUE = 515, - MODE = 516, - MONTH_P = 517, - MONTHS_P = 518, - MOVE = 519, - NAME_P = 520, - NAMES = 521, - NATIONAL = 522, - NATURAL = 523, - NCHAR = 524, - NEW = 525, - NEXT = 526, - NO = 527, - NONE = 528, - NOT = 529, - NOTHING = 530, - NOTIFY = 531, - NOTNULL = 532, - NOWAIT = 533, - NULL_P = 534, - NULLIF = 535, - NULLS_P = 536, - NUMERIC = 537, - OBJECT_P = 538, - OF = 539, - OFF = 540, - OFFSET = 541, - OIDS = 542, - OLD = 543, - ON = 544, - ONLY = 545, - OPERATOR = 546, - OPTION = 547, - OPTIONS = 548, - OR = 549, - ORDER = 550, - ORDINALITY = 551, - OTHERS = 552, - OUT_P = 553, - OUTER_P = 554, - OVER = 555, - OVERLAPS = 556, - OVERLAY = 557, - OVERRIDING = 558, - OWNED = 559, - OWNER = 560, - PARALLEL = 561, - PARSER = 562, - PARTIAL = 563, - PARTITION = 564, - PASSING = 565, - PASSWORD = 566, - PERCENT = 567, - PERSISTENT = 568, - PIVOT = 569, - PIVOT_LONGER = 570, - PIVOT_WIDER = 571, - PLACING = 572, - PLANS = 573, - POLICY = 574, - POSITION = 575, - POSITIONAL = 576, - PRAGMA_P = 577, - PRECEDING = 578, - PRECISION = 579, - PREPARE = 580, - PREPARED = 581, - PRESERVE = 582, - PRIMARY = 583, - PRIOR = 584, - PRIVILEGES = 585, - PROCEDURAL = 586, - PROCEDURE = 587, - PROGRAM = 588, - PUBLICATION = 589, - QUALIFY = 590, - QUOTE = 591, - RANGE = 592, - READ_P = 593, - REAL = 594, - REASSIGN = 595, - RECHECK = 596, - RECURSIVE = 597, - REF = 598, - REFERENCES = 599, - REFERENCING = 600, - REFRESH = 601, - REINDEX = 602, - RELATIVE_P = 603, - RELEASE = 604, - RENAME = 605, - REPEATABLE = 606, - REPLACE = 607, - REPLICA = 608, - RESET = 609, - RESPECT_P = 610, - RESTART = 611, - RESTRICT = 612, - RETURNING = 613, - RETURNS = 614, - REVOKE = 615, - RIGHT = 616, - ROLE = 617, - ROLLBACK = 618, - ROLLUP = 619, - ROW = 620, - ROWS = 621, - RULE = 622, - SAMPLE = 623, - SAVEPOINT = 624, - SCHEMA = 625, - SCHEMAS = 626, - SCOPE = 627, - SCROLL = 628, - SEARCH = 629, - SECOND_P = 630, - SECONDS_P = 631, - SECRET = 632, - SECURITY = 633, - SELECT = 634, - SEMI = 635, - SEQUENCE = 636, - SEQUENCES = 637, - SERIALIZABLE = 638, - SERVER = 639, - SESSION = 640, - SET = 641, - SETOF = 642, - SETS = 643, - SHARE = 644, - SHOW = 645, - SIMILAR = 646, - SIMPLE = 647, - SKIP = 648, - SMALLINT = 649, - SNAPSHOT = 650, - SOME = 651, - SQL_P = 652, - STABLE = 653, - STANDALONE_P = 654, - START = 655, - STATEMENT = 656, - STATISTICS = 657, - STDIN = 658, - STDOUT = 659, - STORAGE = 660, - STORED = 661, - STRICT_P = 662, - STRIP_P = 663, - STRUCT = 664, - SUBSCRIPTION = 665, - SUBSTRING = 666, - SUMMARIZE = 667, - SYMMETRIC = 668, - SYSID = 669, - SYSTEM_P = 670, - TABLE = 671, - TABLES = 672, - TABLESAMPLE = 673, - TABLESPACE = 674, - TEMP = 675, - TEMPLATE = 676, - TEMPORARY = 677, - TEXT_P = 678, - THEN = 679, - TIES = 680, - TIME = 681, - TIMESTAMP = 682, - TO = 683, - TRAILING = 684, - TRANSACTION = 685, - TRANSFORM = 686, - TREAT = 687, - TRIGGER = 688, - TRIM = 689, - TRUE_P = 690, - TRUNCATE = 691, - TRUSTED = 692, - TRY_CAST = 693, - TYPE_P = 694, - TYPES_P = 695, - UNBOUNDED = 696, - UNCOMMITTED = 697, - UNENCRYPTED = 698, - UNION = 699, - UNIQUE = 700, - UNKNOWN = 701, - UNLISTEN = 702, - UNLOGGED = 703, - UNPIVOT = 704, - UNTIL = 705, - UPDATE = 706, - USE_P = 707, - USER = 708, - USING = 709, - VACUUM = 710, - VALID = 711, - VALIDATE = 712, - VALIDATOR = 713, - VALUE_P = 714, - VALUES = 715, - VARCHAR = 716, - VARIADIC = 717, - VARYING = 718, - VERBOSE = 719, - VERSION_P = 720, - VIEW = 721, - VIEWS = 722, - VIRTUAL = 723, - VOLATILE = 724, - WEEK_P = 725, - WEEKS_P = 726, - WHEN = 727, - WHERE = 728, - WHITESPACE_P = 729, - WINDOW = 730, - WITH = 731, - WITHIN = 732, - WITHOUT = 733, - WORK = 734, - WRAPPER = 735, - WRITE_P = 736, - XML_P = 737, - XMLATTRIBUTES = 738, - XMLCONCAT = 739, - XMLELEMENT = 740, - XMLEXISTS = 741, - XMLFOREST = 742, - XMLNAMESPACES = 743, - XMLPARSE = 744, - XMLPI = 745, - XMLROOT = 746, - XMLSERIALIZE = 747, - XMLTABLE = 748, - YEAR_P = 749, - YEARS_P = 750, - YES_P = 751, - ZONE = 752, - NOT_LA = 753, - NULLS_LA = 754, - WITH_LA = 755, - POSTFIXOP = 756, - UMINUS = 757 - }; + enum yytokentype + { + YYEMPTY = -2, + YYEOF = 0, /* "end of file" */ + YYerror = 256, /* error */ + YYUNDEF = 257, /* "invalid token" */ + IDENT = 258, /* IDENT */ + FCONST = 259, /* FCONST */ + SCONST = 260, /* SCONST */ + BCONST = 261, /* BCONST */ + XCONST = 262, /* XCONST */ + Op = 263, /* Op */ + ICONST = 264, /* ICONST */ + PARAM = 265, /* PARAM */ + TYPECAST = 266, /* TYPECAST */ + DOT_DOT = 267, /* DOT_DOT */ + COLON_EQUALS = 268, /* COLON_EQUALS */ + EQUALS_GREATER = 269, /* EQUALS_GREATER */ + INTEGER_DIVISION = 270, /* INTEGER_DIVISION */ + POWER_OF = 271, /* POWER_OF */ + LAMBDA_ARROW = 272, /* LAMBDA_ARROW */ + DOUBLE_ARROW = 273, /* DOUBLE_ARROW */ + LESS_EQUALS = 274, /* LESS_EQUALS */ + GREATER_EQUALS = 275, /* GREATER_EQUALS */ + NOT_EQUALS = 276, /* NOT_EQUALS */ + ABORT_P = 277, /* ABORT_P */ + ABSOLUTE_P = 278, /* ABSOLUTE_P */ + ACCESS = 279, /* ACCESS */ + ACTION = 280, /* ACTION */ + ADD_P = 281, /* ADD_P */ + ADMIN = 282, /* ADMIN */ + AFTER = 283, /* AFTER */ + AGGREGATE = 284, /* AGGREGATE */ + ALL = 285, /* ALL */ + ALSO = 286, /* ALSO */ + ALTER = 287, /* ALTER */ + ALWAYS = 288, /* ALWAYS */ + ANALYSE = 289, /* ANALYSE */ + ANALYZE = 290, /* ANALYZE */ + AND = 291, /* AND */ + ANTI = 292, /* ANTI */ + ANY = 293, /* ANY */ + ARRAY = 294, /* ARRAY */ + AS = 295, /* AS */ + ASC_P = 296, /* ASC_P */ + ASOF = 297, /* ASOF */ + ASSERTION = 298, /* ASSERTION */ + ASSIGNMENT = 299, /* ASSIGNMENT */ + ASYMMETRIC = 300, /* ASYMMETRIC */ + AT = 301, /* AT */ + ATTACH = 302, /* ATTACH */ + ATTRIBUTE = 303, /* ATTRIBUTE */ + AUTHORIZATION = 304, /* AUTHORIZATION */ + BACKWARD = 305, /* BACKWARD */ + BEFORE = 306, /* BEFORE */ + BEGIN_P = 307, /* BEGIN_P */ + BETWEEN = 308, /* BETWEEN */ + BIGINT = 309, /* BIGINT */ + BINARY = 310, /* BINARY */ + BIT = 311, /* BIT */ + BOOLEAN_P = 312, /* BOOLEAN_P */ + BOTH = 313, /* BOTH */ + BY = 314, /* BY */ + CACHE = 315, /* CACHE */ + CALL_P = 316, /* CALL_P */ + CALLED = 317, /* CALLED */ + CASCADE = 318, /* CASCADE */ + CASCADED = 319, /* CASCADED */ + CASE = 320, /* CASE */ + CAST = 321, /* CAST */ + CATALOG_P = 322, /* CATALOG_P */ + CENTURIES_P = 323, /* CENTURIES_P */ + CENTURY_P = 324, /* CENTURY_P */ + CHAIN = 325, /* CHAIN */ + CHAR_P = 326, /* CHAR_P */ + CHARACTER = 327, /* CHARACTER */ + CHARACTERISTICS = 328, /* CHARACTERISTICS */ + CHECK_P = 329, /* CHECK_P */ + CHECKPOINT = 330, /* CHECKPOINT */ + CLASS = 331, /* CLASS */ + CLOSE = 332, /* CLOSE */ + CLUSTER = 333, /* CLUSTER */ + COALESCE = 334, /* COALESCE */ + COLLATE = 335, /* COLLATE */ + COLLATION = 336, /* COLLATION */ + COLUMN = 337, /* COLUMN */ + COLUMNS = 338, /* COLUMNS */ + COMMENT = 339, /* COMMENT */ + COMMENTS = 340, /* COMMENTS */ + COMMIT = 341, /* COMMIT */ + COMMITTED = 342, /* COMMITTED */ + COMPRESSION = 343, /* COMPRESSION */ + CONCURRENTLY = 344, /* CONCURRENTLY */ + CONFIGURATION = 345, /* CONFIGURATION */ + CONFLICT = 346, /* CONFLICT */ + CONNECTION = 347, /* CONNECTION */ + CONSTRAINT = 348, /* CONSTRAINT */ + CONSTRAINTS = 349, /* CONSTRAINTS */ + CONTENT_P = 350, /* CONTENT_P */ + CONTINUE_P = 351, /* CONTINUE_P */ + CONVERSION_P = 352, /* CONVERSION_P */ + COPY = 353, /* COPY */ + COST = 354, /* COST */ + CREATE_P = 355, /* CREATE_P */ + CROSS = 356, /* CROSS */ + CSV = 357, /* CSV */ + CUBE = 358, /* CUBE */ + CURRENT_P = 359, /* CURRENT_P */ + CURSOR = 360, /* CURSOR */ + CYCLE = 361, /* CYCLE */ + DATA_P = 362, /* DATA_P */ + DATABASE = 363, /* DATABASE */ + DAY_P = 364, /* DAY_P */ + DAYS_P = 365, /* DAYS_P */ + DEALLOCATE = 366, /* DEALLOCATE */ + DEC = 367, /* DEC */ + DECADE_P = 368, /* DECADE_P */ + DECADES_P = 369, /* DECADES_P */ + DECIMAL_P = 370, /* DECIMAL_P */ + DECLARE = 371, /* DECLARE */ + DEFAULT = 372, /* DEFAULT */ + DEFAULTS = 373, /* DEFAULTS */ + DEFERRABLE = 374, /* DEFERRABLE */ + DEFERRED = 375, /* DEFERRED */ + DEFINER = 376, /* DEFINER */ + DELETE_P = 377, /* DELETE_P */ + DELIMITER = 378, /* DELIMITER */ + DELIMITERS = 379, /* DELIMITERS */ + DEPENDS = 380, /* DEPENDS */ + DESC_P = 381, /* DESC_P */ + DESCRIBE = 382, /* DESCRIBE */ + DETACH = 383, /* DETACH */ + DICTIONARY = 384, /* DICTIONARY */ + DISABLE_P = 385, /* DISABLE_P */ + DISCARD = 386, /* DISCARD */ + DISTINCT = 387, /* DISTINCT */ + DO = 388, /* DO */ + DOCUMENT_P = 389, /* DOCUMENT_P */ + DOMAIN_P = 390, /* DOMAIN_P */ + DOUBLE_P = 391, /* DOUBLE_P */ + DROP = 392, /* DROP */ + EACH = 393, /* EACH */ + ELSE = 394, /* ELSE */ + ENABLE_P = 395, /* ENABLE_P */ + ENCODING = 396, /* ENCODING */ + ENCRYPTED = 397, /* ENCRYPTED */ + END_P = 398, /* END_P */ + ENUM_P = 399, /* ENUM_P */ + ESCAPE = 400, /* ESCAPE */ + EVENT = 401, /* EVENT */ + EXCEPT = 402, /* EXCEPT */ + EXCLUDE = 403, /* EXCLUDE */ + EXCLUDING = 404, /* EXCLUDING */ + EXCLUSIVE = 405, /* EXCLUSIVE */ + EXECUTE = 406, /* EXECUTE */ + EXISTS = 407, /* EXISTS */ + EXPLAIN = 408, /* EXPLAIN */ + EXPORT_P = 409, /* EXPORT_P */ + EXPORT_STATE = 410, /* EXPORT_STATE */ + EXTENSION = 411, /* EXTENSION */ + EXTENSIONS = 412, /* EXTENSIONS */ + EXTERNAL = 413, /* EXTERNAL */ + EXTRACT = 414, /* EXTRACT */ + FALSE_P = 415, /* FALSE_P */ + FAMILY = 416, /* FAMILY */ + FETCH = 417, /* FETCH */ + FILTER = 418, /* FILTER */ + FIRST_P = 419, /* FIRST_P */ + FLOAT_P = 420, /* FLOAT_P */ + FOLLOWING = 421, /* FOLLOWING */ + FOR = 422, /* FOR */ + FORCE = 423, /* FORCE */ + FOREIGN = 424, /* FOREIGN */ + FORWARD = 425, /* FORWARD */ + FREEZE = 426, /* FREEZE */ + FROM = 427, /* FROM */ + FULL = 428, /* FULL */ + FUNCTION = 429, /* FUNCTION */ + FUNCTIONS = 430, /* FUNCTIONS */ + GENERATED = 431, /* GENERATED */ + GLOB = 432, /* GLOB */ + GLOBAL = 433, /* GLOBAL */ + GRANT = 434, /* GRANT */ + GRANTED = 435, /* GRANTED */ + GROUP_P = 436, /* GROUP_P */ + GROUPING = 437, /* GROUPING */ + GROUPING_ID = 438, /* GROUPING_ID */ + GROUPS = 439, /* GROUPS */ + HANDLER = 440, /* HANDLER */ + HAVING = 441, /* HAVING */ + HEADER_P = 442, /* HEADER_P */ + HOLD = 443, /* HOLD */ + HOUR_P = 444, /* HOUR_P */ + HOURS_P = 445, /* HOURS_P */ + IDENTITY_P = 446, /* IDENTITY_P */ + IF_P = 447, /* IF_P */ + IGNORE_P = 448, /* IGNORE_P */ + ILIKE = 449, /* ILIKE */ + IMMEDIATE = 450, /* IMMEDIATE */ + IMMUTABLE = 451, /* IMMUTABLE */ + IMPLICIT_P = 452, /* IMPLICIT_P */ + IMPORT_P = 453, /* IMPORT_P */ + IN_P = 454, /* IN_P */ + INCLUDE_P = 455, /* INCLUDE_P */ + INCLUDING = 456, /* INCLUDING */ + INCREMENT = 457, /* INCREMENT */ + INDEX = 458, /* INDEX */ + INDEXES = 459, /* INDEXES */ + INHERIT = 460, /* INHERIT */ + INHERITS = 461, /* INHERITS */ + INITIALLY = 462, /* INITIALLY */ + INLINE_P = 463, /* INLINE_P */ + INNER_P = 464, /* INNER_P */ + INOUT = 465, /* INOUT */ + INPUT_P = 466, /* INPUT_P */ + INSENSITIVE = 467, /* INSENSITIVE */ + INSERT = 468, /* INSERT */ + INSTALL = 469, /* INSTALL */ + INSTEAD = 470, /* INSTEAD */ + INT_P = 471, /* INT_P */ + INTEGER = 472, /* INTEGER */ + INTERSECT = 473, /* INTERSECT */ + INTERVAL = 474, /* INTERVAL */ + INTO = 475, /* INTO */ + INVOKER = 476, /* INVOKER */ + IS = 477, /* IS */ + ISNULL = 478, /* ISNULL */ + ISOLATION = 479, /* ISOLATION */ + JOIN = 480, /* JOIN */ + JSON = 481, /* JSON */ + KEY = 482, /* KEY */ + LABEL = 483, /* LABEL */ + LANGUAGE = 484, /* LANGUAGE */ + LARGE_P = 485, /* LARGE_P */ + LAST_P = 486, /* LAST_P */ + LATERAL_P = 487, /* LATERAL_P */ + LEADING = 488, /* LEADING */ + LEAKPROOF = 489, /* LEAKPROOF */ + LEFT = 490, /* LEFT */ + LEVEL = 491, /* LEVEL */ + LIKE = 492, /* LIKE */ + LIMIT = 493, /* LIMIT */ + LISTEN = 494, /* LISTEN */ + LOAD = 495, /* LOAD */ + LOCAL = 496, /* LOCAL */ + LOCATION = 497, /* LOCATION */ + LOCK_P = 498, /* LOCK_P */ + LOCKED = 499, /* LOCKED */ + LOGGED = 500, /* LOGGED */ + MACRO = 501, /* MACRO */ + MAP = 502, /* MAP */ + MAPPING = 503, /* MAPPING */ + MATCH = 504, /* MATCH */ + MATERIALIZED = 505, /* MATERIALIZED */ + MAXVALUE = 506, /* MAXVALUE */ + METHOD = 507, /* METHOD */ + MICROSECOND_P = 508, /* MICROSECOND_P */ + MICROSECONDS_P = 509, /* MICROSECONDS_P */ + MILLENNIA_P = 510, /* MILLENNIA_P */ + MILLENNIUM_P = 511, /* MILLENNIUM_P */ + MILLISECOND_P = 512, /* MILLISECOND_P */ + MILLISECONDS_P = 513, /* MILLISECONDS_P */ + MINUTE_P = 514, /* MINUTE_P */ + MINUTES_P = 515, /* MINUTES_P */ + MINVALUE = 516, /* MINVALUE */ + MODE = 517, /* MODE */ + MONTH_P = 518, /* MONTH_P */ + MONTHS_P = 519, /* MONTHS_P */ + MOVE = 520, /* MOVE */ + NAME_P = 521, /* NAME_P */ + NAMES = 522, /* NAMES */ + NATIONAL = 523, /* NATIONAL */ + NATURAL = 524, /* NATURAL */ + NCHAR = 525, /* NCHAR */ + NEW = 526, /* NEW */ + NEXT = 527, /* NEXT */ + NO = 528, /* NO */ + NONE = 529, /* NONE */ + NOT = 530, /* NOT */ + NOTHING = 531, /* NOTHING */ + NOTIFY = 532, /* NOTIFY */ + NOTNULL = 533, /* NOTNULL */ + NOWAIT = 534, /* NOWAIT */ + NULL_P = 535, /* NULL_P */ + NULLIF = 536, /* NULLIF */ + NULLS_P = 537, /* NULLS_P */ + NUMERIC = 538, /* NUMERIC */ + OBJECT_P = 539, /* OBJECT_P */ + OF = 540, /* OF */ + OFF = 541, /* OFF */ + OFFSET = 542, /* OFFSET */ + OIDS = 543, /* OIDS */ + OLD = 544, /* OLD */ + ON = 545, /* ON */ + ONLY = 546, /* ONLY */ + OPERATOR = 547, /* OPERATOR */ + OPTION = 548, /* OPTION */ + OPTIONS = 549, /* OPTIONS */ + OR = 550, /* OR */ + ORDER = 551, /* ORDER */ + ORDINALITY = 552, /* ORDINALITY */ + OTHERS = 553, /* OTHERS */ + OUT_P = 554, /* OUT_P */ + OUTER_P = 555, /* OUTER_P */ + OVER = 556, /* OVER */ + OVERLAPS = 557, /* OVERLAPS */ + OVERLAY = 558, /* OVERLAY */ + OVERRIDING = 559, /* OVERRIDING */ + OWNED = 560, /* OWNED */ + OWNER = 561, /* OWNER */ + PARALLEL = 562, /* PARALLEL */ + PARSER = 563, /* PARSER */ + PARTIAL = 564, /* PARTIAL */ + PARTITION = 565, /* PARTITION */ + PASSING = 566, /* PASSING */ + PASSWORD = 567, /* PASSWORD */ + PERCENT = 568, /* PERCENT */ + PERSISTENT = 569, /* PERSISTENT */ + PIVOT = 570, /* PIVOT */ + PIVOT_LONGER = 571, /* PIVOT_LONGER */ + PIVOT_WIDER = 572, /* PIVOT_WIDER */ + PLACING = 573, /* PLACING */ + PLANS = 574, /* PLANS */ + POLICY = 575, /* POLICY */ + POSITION = 576, /* POSITION */ + POSITIONAL = 577, /* POSITIONAL */ + PRAGMA_P = 578, /* PRAGMA_P */ + PRECEDING = 579, /* PRECEDING */ + PRECISION = 580, /* PRECISION */ + PREPARE = 581, /* PREPARE */ + PREPARED = 582, /* PREPARED */ + PRESERVE = 583, /* PRESERVE */ + PRIMARY = 584, /* PRIMARY */ + PRIOR = 585, /* PRIOR */ + PRIVILEGES = 586, /* PRIVILEGES */ + PROCEDURAL = 587, /* PROCEDURAL */ + PROCEDURE = 588, /* PROCEDURE */ + PROGRAM = 589, /* PROGRAM */ + PUBLICATION = 590, /* PUBLICATION */ + QUALIFY = 591, /* QUALIFY */ + QUARTER_P = 592, /* QUARTER_P */ + QUARTERS_P = 593, /* QUARTERS_P */ + QUOTE = 594, /* QUOTE */ + RANGE = 595, /* RANGE */ + READ_P = 596, /* READ_P */ + REAL = 597, /* REAL */ + REASSIGN = 598, /* REASSIGN */ + RECHECK = 599, /* RECHECK */ + RECURSIVE = 600, /* RECURSIVE */ + REF = 601, /* REF */ + REFERENCES = 602, /* REFERENCES */ + REFERENCING = 603, /* REFERENCING */ + REFRESH = 604, /* REFRESH */ + REINDEX = 605, /* REINDEX */ + RELATIVE_P = 606, /* RELATIVE_P */ + RELEASE = 607, /* RELEASE */ + RENAME = 608, /* RENAME */ + REPEATABLE = 609, /* REPEATABLE */ + REPLACE = 610, /* REPLACE */ + REPLICA = 611, /* REPLICA */ + RESET = 612, /* RESET */ + RESPECT_P = 613, /* RESPECT_P */ + RESTART = 614, /* RESTART */ + RESTRICT = 615, /* RESTRICT */ + RETURNING = 616, /* RETURNING */ + RETURNS = 617, /* RETURNS */ + REVOKE = 618, /* REVOKE */ + RIGHT = 619, /* RIGHT */ + ROLE = 620, /* ROLE */ + ROLLBACK = 621, /* ROLLBACK */ + ROLLUP = 622, /* ROLLUP */ + ROW = 623, /* ROW */ + ROWS = 624, /* ROWS */ + RULE = 625, /* RULE */ + SAMPLE = 626, /* SAMPLE */ + SAVEPOINT = 627, /* SAVEPOINT */ + SCHEMA = 628, /* SCHEMA */ + SCHEMAS = 629, /* SCHEMAS */ + SCOPE = 630, /* SCOPE */ + SCROLL = 631, /* SCROLL */ + SEARCH = 632, /* SEARCH */ + SECOND_P = 633, /* SECOND_P */ + SECONDS_P = 634, /* SECONDS_P */ + SECRET = 635, /* SECRET */ + SECURITY = 636, /* SECURITY */ + SELECT = 637, /* SELECT */ + SEMI = 638, /* SEMI */ + SEQUENCE = 639, /* SEQUENCE */ + SEQUENCES = 640, /* SEQUENCES */ + SERIALIZABLE = 641, /* SERIALIZABLE */ + SERVER = 642, /* SERVER */ + SESSION = 643, /* SESSION */ + SET = 644, /* SET */ + SETOF = 645, /* SETOF */ + SETS = 646, /* SETS */ + SHARE = 647, /* SHARE */ + SHOW = 648, /* SHOW */ + SIMILAR = 649, /* SIMILAR */ + SIMPLE = 650, /* SIMPLE */ + SKIP = 651, /* SKIP */ + SMALLINT = 652, /* SMALLINT */ + SNAPSHOT = 653, /* SNAPSHOT */ + SOME = 654, /* SOME */ + SQL_P = 655, /* SQL_P */ + STABLE = 656, /* STABLE */ + STANDALONE_P = 657, /* STANDALONE_P */ + START = 658, /* START */ + STATEMENT = 659, /* STATEMENT */ + STATISTICS = 660, /* STATISTICS */ + STDIN = 661, /* STDIN */ + STDOUT = 662, /* STDOUT */ + STORAGE = 663, /* STORAGE */ + STORED = 664, /* STORED */ + STRICT_P = 665, /* STRICT_P */ + STRIP_P = 666, /* STRIP_P */ + STRUCT = 667, /* STRUCT */ + SUBSCRIPTION = 668, /* SUBSCRIPTION */ + SUBSTRING = 669, /* SUBSTRING */ + SUMMARIZE = 670, /* SUMMARIZE */ + SYMMETRIC = 671, /* SYMMETRIC */ + SYSID = 672, /* SYSID */ + SYSTEM_P = 673, /* SYSTEM_P */ + TABLE = 674, /* TABLE */ + TABLES = 675, /* TABLES */ + TABLESAMPLE = 676, /* TABLESAMPLE */ + TABLESPACE = 677, /* TABLESPACE */ + TEMP = 678, /* TEMP */ + TEMPLATE = 679, /* TEMPLATE */ + TEMPORARY = 680, /* TEMPORARY */ + TEXT_P = 681, /* TEXT_P */ + THEN = 682, /* THEN */ + TIES = 683, /* TIES */ + TIME = 684, /* TIME */ + TIMESTAMP = 685, /* TIMESTAMP */ + TO = 686, /* TO */ + TRAILING = 687, /* TRAILING */ + TRANSACTION = 688, /* TRANSACTION */ + TRANSFORM = 689, /* TRANSFORM */ + TREAT = 690, /* TREAT */ + TRIGGER = 691, /* TRIGGER */ + TRIM = 692, /* TRIM */ + TRUE_P = 693, /* TRUE_P */ + TRUNCATE = 694, /* TRUNCATE */ + TRUSTED = 695, /* TRUSTED */ + TRY_CAST = 696, /* TRY_CAST */ + TYPE_P = 697, /* TYPE_P */ + TYPES_P = 698, /* TYPES_P */ + UNBOUNDED = 699, /* UNBOUNDED */ + UNCOMMITTED = 700, /* UNCOMMITTED */ + UNENCRYPTED = 701, /* UNENCRYPTED */ + UNION = 702, /* UNION */ + UNIQUE = 703, /* UNIQUE */ + UNKNOWN = 704, /* UNKNOWN */ + UNLISTEN = 705, /* UNLISTEN */ + UNLOGGED = 706, /* UNLOGGED */ + UNPIVOT = 707, /* UNPIVOT */ + UNTIL = 708, /* UNTIL */ + UPDATE = 709, /* UPDATE */ + USE_P = 710, /* USE_P */ + USER = 711, /* USER */ + USING = 712, /* USING */ + VACUUM = 713, /* VACUUM */ + VALID = 714, /* VALID */ + VALIDATE = 715, /* VALIDATE */ + VALIDATOR = 716, /* VALIDATOR */ + VALUE_P = 717, /* VALUE_P */ + VALUES = 718, /* VALUES */ + VARCHAR = 719, /* VARCHAR */ + VARIADIC = 720, /* VARIADIC */ + VARYING = 721, /* VARYING */ + VERBOSE = 722, /* VERBOSE */ + VERSION_P = 723, /* VERSION_P */ + VIEW = 724, /* VIEW */ + VIEWS = 725, /* VIEWS */ + VIRTUAL = 726, /* VIRTUAL */ + VOLATILE = 727, /* VOLATILE */ + WEEK_P = 728, /* WEEK_P */ + WEEKS_P = 729, /* WEEKS_P */ + WHEN = 730, /* WHEN */ + WHERE = 731, /* WHERE */ + WHITESPACE_P = 732, /* WHITESPACE_P */ + WINDOW = 733, /* WINDOW */ + WITH = 734, /* WITH */ + WITHIN = 735, /* WITHIN */ + WITHOUT = 736, /* WITHOUT */ + WORK = 737, /* WORK */ + WRAPPER = 738, /* WRAPPER */ + WRITE_P = 739, /* WRITE_P */ + XML_P = 740, /* XML_P */ + XMLATTRIBUTES = 741, /* XMLATTRIBUTES */ + XMLCONCAT = 742, /* XMLCONCAT */ + XMLELEMENT = 743, /* XMLELEMENT */ + XMLEXISTS = 744, /* XMLEXISTS */ + XMLFOREST = 745, /* XMLFOREST */ + XMLNAMESPACES = 746, /* XMLNAMESPACES */ + XMLPARSE = 747, /* XMLPARSE */ + XMLPI = 748, /* XMLPI */ + XMLROOT = 749, /* XMLROOT */ + XMLSERIALIZE = 750, /* XMLSERIALIZE */ + XMLTABLE = 751, /* XMLTABLE */ + YEAR_P = 752, /* YEAR_P */ + YEARS_P = 753, /* YEARS_P */ + YES_P = 754, /* YES_P */ + ZONE = 755, /* ZONE */ + NOT_LA = 756, /* NOT_LA */ + NULLS_LA = 757, /* NULLS_LA */ + WITH_LA = 758, /* WITH_LA */ + POSTFIXOP = 759, /* POSTFIXOP */ + UMINUS = 760 /* UMINUS */ + }; + typedef enum yytokentype yytoken_kind_t; #endif -/* Tokens. */ -#define IDENT 258 -#define FCONST 259 -#define SCONST 260 -#define BCONST 261 -#define XCONST 262 -#define Op 263 -#define ICONST 264 -#define PARAM 265 -#define TYPECAST 266 -#define DOT_DOT 267 -#define COLON_EQUALS 268 -#define EQUALS_GREATER 269 -#define INTEGER_DIVISION 270 -#define POWER_OF 271 -#define LAMBDA_ARROW 272 -#define DOUBLE_ARROW 273 -#define LESS_EQUALS 274 -#define GREATER_EQUALS 275 -#define NOT_EQUALS 276 -#define ABORT_P 277 -#define ABSOLUTE_P 278 -#define ACCESS 279 -#define ACTION 280 -#define ADD_P 281 -#define ADMIN 282 -#define AFTER 283 -#define AGGREGATE 284 -#define ALL 285 -#define ALSO 286 -#define ALTER 287 -#define ALWAYS 288 -#define ANALYSE 289 -#define ANALYZE 290 -#define AND 291 -#define ANTI 292 -#define ANY 293 -#define ARRAY 294 -#define AS 295 -#define ASC_P 296 -#define ASOF 297 -#define ASSERTION 298 -#define ASSIGNMENT 299 -#define ASYMMETRIC 300 -#define AT 301 -#define ATTACH 302 -#define ATTRIBUTE 303 -#define AUTHORIZATION 304 -#define BACKWARD 305 -#define BEFORE 306 -#define BEGIN_P 307 -#define BETWEEN 308 -#define BIGINT 309 -#define BINARY 310 -#define BIT 311 -#define BOOLEAN_P 312 -#define BOTH 313 -#define BY 314 -#define CACHE 315 -#define CALL_P 316 -#define CALLED 317 -#define CASCADE 318 -#define CASCADED 319 -#define CASE 320 -#define CAST 321 -#define CATALOG_P 322 -#define CENTURIES_P 323 -#define CENTURY_P 324 -#define CHAIN 325 -#define CHAR_P 326 -#define CHARACTER 327 -#define CHARACTERISTICS 328 -#define CHECK_P 329 -#define CHECKPOINT 330 -#define CLASS 331 -#define CLOSE 332 -#define CLUSTER 333 -#define COALESCE 334 -#define COLLATE 335 -#define COLLATION 336 -#define COLUMN 337 -#define COLUMNS 338 -#define COMMENT 339 -#define COMMENTS 340 -#define COMMIT 341 -#define COMMITTED 342 -#define COMPRESSION 343 -#define CONCURRENTLY 344 -#define CONFIGURATION 345 -#define CONFLICT 346 -#define CONNECTION 347 -#define CONSTRAINT 348 -#define CONSTRAINTS 349 -#define CONTENT_P 350 -#define CONTINUE_P 351 -#define CONVERSION_P 352 -#define COPY 353 -#define COST 354 -#define CREATE_P 355 -#define CROSS 356 -#define CSV 357 -#define CUBE 358 -#define CURRENT_P 359 -#define CURSOR 360 -#define CYCLE 361 -#define DATA_P 362 -#define DATABASE 363 -#define DAY_P 364 -#define DAYS_P 365 -#define DEALLOCATE 366 -#define DEC 367 -#define DECADE_P 368 -#define DECADES_P 369 -#define DECIMAL_P 370 -#define DECLARE 371 -#define DEFAULT 372 -#define DEFAULTS 373 -#define DEFERRABLE 374 -#define DEFERRED 375 -#define DEFINER 376 -#define DELETE_P 377 -#define DELIMITER 378 -#define DELIMITERS 379 -#define DEPENDS 380 -#define DESC_P 381 -#define DESCRIBE 382 -#define DETACH 383 -#define DICTIONARY 384 -#define DISABLE_P 385 -#define DISCARD 386 -#define DISTINCT 387 -#define DO 388 -#define DOCUMENT_P 389 -#define DOMAIN_P 390 -#define DOUBLE_P 391 -#define DROP 392 -#define EACH 393 -#define ELSE 394 -#define ENABLE_P 395 -#define ENCODING 396 -#define ENCRYPTED 397 -#define END_P 398 -#define ENUM_P 399 -#define ESCAPE 400 -#define EVENT 401 -#define EXCEPT 402 -#define EXCLUDE 403 -#define EXCLUDING 404 -#define EXCLUSIVE 405 -#define EXECUTE 406 -#define EXISTS 407 -#define EXPLAIN 408 -#define EXPORT_P 409 -#define EXPORT_STATE 410 -#define EXTENSION 411 -#define EXTERNAL 412 -#define EXTRACT 413 -#define FALSE_P 414 -#define FAMILY 415 -#define FETCH 416 -#define FILTER 417 -#define FIRST_P 418 -#define FLOAT_P 419 -#define FOLLOWING 420 -#define FOR 421 -#define FORCE 422 -#define FOREIGN 423 -#define FORWARD 424 -#define FREEZE 425 -#define FROM 426 -#define FULL 427 -#define FUNCTION 428 -#define FUNCTIONS 429 -#define GENERATED 430 -#define GLOB 431 -#define GLOBAL 432 -#define GRANT 433 -#define GRANTED 434 -#define GROUP_P 435 -#define GROUPING 436 -#define GROUPING_ID 437 -#define GROUPS 438 -#define HANDLER 439 -#define HAVING 440 -#define HEADER_P 441 -#define HOLD 442 -#define HOUR_P 443 -#define HOURS_P 444 -#define IDENTITY_P 445 -#define IF_P 446 -#define IGNORE_P 447 -#define ILIKE 448 -#define IMMEDIATE 449 -#define IMMUTABLE 450 -#define IMPLICIT_P 451 -#define IMPORT_P 452 -#define IN_P 453 -#define INCLUDE_P 454 -#define INCLUDING 455 -#define INCREMENT 456 -#define INDEX 457 -#define INDEXES 458 -#define INHERIT 459 -#define INHERITS 460 -#define INITIALLY 461 -#define INLINE_P 462 -#define INNER_P 463 -#define INOUT 464 -#define INPUT_P 465 -#define INSENSITIVE 466 -#define INSERT 467 -#define INSTALL 468 -#define INSTEAD 469 -#define INT_P 470 -#define INTEGER 471 -#define INTERSECT 472 -#define INTERVAL 473 -#define INTO 474 -#define INVOKER 475 -#define IS 476 -#define ISNULL 477 -#define ISOLATION 478 -#define JOIN 479 -#define JSON 480 -#define KEY 481 -#define LABEL 482 -#define LANGUAGE 483 -#define LARGE_P 484 -#define LAST_P 485 -#define LATERAL_P 486 -#define LEADING 487 -#define LEAKPROOF 488 -#define LEFT 489 -#define LEVEL 490 -#define LIKE 491 -#define LIMIT 492 -#define LISTEN 493 -#define LOAD 494 -#define LOCAL 495 -#define LOCATION 496 -#define LOCK_P 497 -#define LOCKED 498 -#define LOGGED 499 -#define MACRO 500 -#define MAP 501 -#define MAPPING 502 -#define MATCH 503 -#define MATERIALIZED 504 -#define MAXVALUE 505 -#define METHOD 506 -#define MICROSECOND_P 507 -#define MICROSECONDS_P 508 -#define MILLENNIA_P 509 -#define MILLENNIUM_P 510 -#define MILLISECOND_P 511 -#define MILLISECONDS_P 512 -#define MINUTE_P 513 -#define MINUTES_P 514 -#define MINVALUE 515 -#define MODE 516 -#define MONTH_P 517 -#define MONTHS_P 518 -#define MOVE 519 -#define NAME_P 520 -#define NAMES 521 -#define NATIONAL 522 -#define NATURAL 523 -#define NCHAR 524 -#define NEW 525 -#define NEXT 526 -#define NO 527 -#define NONE 528 -#define NOT 529 -#define NOTHING 530 -#define NOTIFY 531 -#define NOTNULL 532 -#define NOWAIT 533 -#define NULL_P 534 -#define NULLIF 535 -#define NULLS_P 536 -#define NUMERIC 537 -#define OBJECT_P 538 -#define OF 539 -#define OFF 540 -#define OFFSET 541 -#define OIDS 542 -#define OLD 543 -#define ON 544 -#define ONLY 545 -#define OPERATOR 546 -#define OPTION 547 -#define OPTIONS 548 -#define OR 549 -#define ORDER 550 -#define ORDINALITY 551 -#define OTHERS 552 -#define OUT_P 553 -#define OUTER_P 554 -#define OVER 555 -#define OVERLAPS 556 -#define OVERLAY 557 -#define OVERRIDING 558 -#define OWNED 559 -#define OWNER 560 -#define PARALLEL 561 -#define PARSER 562 -#define PARTIAL 563 -#define PARTITION 564 -#define PASSING 565 -#define PASSWORD 566 -#define PERCENT 567 -#define PERSISTENT 568 -#define PIVOT 569 -#define PIVOT_LONGER 570 -#define PIVOT_WIDER 571 -#define PLACING 572 -#define PLANS 573 -#define POLICY 574 -#define POSITION 575 -#define POSITIONAL 576 -#define PRAGMA_P 577 -#define PRECEDING 578 -#define PRECISION 579 -#define PREPARE 580 -#define PREPARED 581 -#define PRESERVE 582 -#define PRIMARY 583 -#define PRIOR 584 -#define PRIVILEGES 585 -#define PROCEDURAL 586 -#define PROCEDURE 587 -#define PROGRAM 588 -#define PUBLICATION 589 -#define QUALIFY 590 -#define QUOTE 591 -#define RANGE 592 -#define READ_P 593 -#define REAL 594 -#define REASSIGN 595 -#define RECHECK 596 -#define RECURSIVE 597 -#define REF 598 -#define REFERENCES 599 -#define REFERENCING 600 -#define REFRESH 601 -#define REINDEX 602 -#define RELATIVE_P 603 -#define RELEASE 604 -#define RENAME 605 -#define REPEATABLE 606 -#define REPLACE 607 -#define REPLICA 608 -#define RESET 609 -#define RESPECT_P 610 -#define RESTART 611 -#define RESTRICT 612 -#define RETURNING 613 -#define RETURNS 614 -#define REVOKE 615 -#define RIGHT 616 -#define ROLE 617 -#define ROLLBACK 618 -#define ROLLUP 619 -#define ROW 620 -#define ROWS 621 -#define RULE 622 -#define SAMPLE 623 -#define SAVEPOINT 624 -#define SCHEMA 625 -#define SCHEMAS 626 -#define SCOPE 627 -#define SCROLL 628 -#define SEARCH 629 -#define SECOND_P 630 -#define SECONDS_P 631 -#define SECRET 632 -#define SECURITY 633 -#define SELECT 634 -#define SEMI 635 -#define SEQUENCE 636 -#define SEQUENCES 637 -#define SERIALIZABLE 638 -#define SERVER 639 -#define SESSION 640 -#define SET 641 -#define SETOF 642 -#define SETS 643 -#define SHARE 644 -#define SHOW 645 -#define SIMILAR 646 -#define SIMPLE 647 -#define SKIP 648 -#define SMALLINT 649 -#define SNAPSHOT 650 -#define SOME 651 -#define SQL_P 652 -#define STABLE 653 -#define STANDALONE_P 654 -#define START 655 -#define STATEMENT 656 -#define STATISTICS 657 -#define STDIN 658 -#define STDOUT 659 -#define STORAGE 660 -#define STORED 661 -#define STRICT_P 662 -#define STRIP_P 663 -#define STRUCT 664 -#define SUBSCRIPTION 665 -#define SUBSTRING 666 -#define SUMMARIZE 667 -#define SYMMETRIC 668 -#define SYSID 669 -#define SYSTEM_P 670 -#define TABLE 671 -#define TABLES 672 -#define TABLESAMPLE 673 -#define TABLESPACE 674 -#define TEMP 675 -#define TEMPLATE 676 -#define TEMPORARY 677 -#define TEXT_P 678 -#define THEN 679 -#define TIES 680 -#define TIME 681 -#define TIMESTAMP 682 -#define TO 683 -#define TRAILING 684 -#define TRANSACTION 685 -#define TRANSFORM 686 -#define TREAT 687 -#define TRIGGER 688 -#define TRIM 689 -#define TRUE_P 690 -#define TRUNCATE 691 -#define TRUSTED 692 -#define TRY_CAST 693 -#define TYPE_P 694 -#define TYPES_P 695 -#define UNBOUNDED 696 -#define UNCOMMITTED 697 -#define UNENCRYPTED 698 -#define UNION 699 -#define UNIQUE 700 -#define UNKNOWN 701 -#define UNLISTEN 702 -#define UNLOGGED 703 -#define UNPIVOT 704 -#define UNTIL 705 -#define UPDATE 706 -#define USE_P 707 -#define USER 708 -#define USING 709 -#define VACUUM 710 -#define VALID 711 -#define VALIDATE 712 -#define VALIDATOR 713 -#define VALUE_P 714 -#define VALUES 715 -#define VARCHAR 716 -#define VARIADIC 717 -#define VARYING 718 -#define VERBOSE 719 -#define VERSION_P 720 -#define VIEW 721 -#define VIEWS 722 -#define VIRTUAL 723 -#define VOLATILE 724 -#define WEEK_P 725 -#define WEEKS_P 726 -#define WHEN 727 -#define WHERE 728 -#define WHITESPACE_P 729 -#define WINDOW 730 -#define WITH 731 -#define WITHIN 732 -#define WITHOUT 733 -#define WORK 734 -#define WRAPPER 735 -#define WRITE_P 736 -#define XML_P 737 -#define XMLATTRIBUTES 738 -#define XMLCONCAT 739 -#define XMLELEMENT 740 -#define XMLEXISTS 741 -#define XMLFOREST 742 -#define XMLNAMESPACES 743 -#define XMLPARSE 744 -#define XMLPI 745 -#define XMLROOT 746 -#define XMLSERIALIZE 747 -#define XMLTABLE 748 -#define YEAR_P 749 -#define YEARS_P 750 -#define YES_P 751 -#define ZONE 752 -#define NOT_LA 753 -#define NULLS_LA 754 -#define WITH_LA 755 -#define POSTFIXOP 756 -#define UMINUS 757 - - - +/* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -#line 14 "third_party/libpg_query/grammar/grammar.y" +union YYSTYPE { +#line 14 "third_party/libpg_query/grammar/grammar.y" + core_YYSTYPE core_yystype; /* these fields must match core_YYSTYPE: */ int ival; @@ -1096,28 +613,35 @@ typedef union YYSTYPE PGSubLinkType subquerytype; PGViewCheckOption viewcheckoption; PGInsertColumnOrder bynameorposition; -} -/* Line 1529 of yacc.c. */ -#line 1102 "third_party/libpg_query/grammar/grammar_out.hpp" - YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif + PGLoadInstallType loadinstalltype; + PGTransactionStmtType transactiontype; +#line 620 "third_party/libpg_query/grammar/grammar_out.hpp" +}; +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif +/* Location type. */ #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE +typedef struct YYLTYPE YYLTYPE; +struct YYLTYPE { int first_line; int first_column; int last_line; int last_column; -} YYLTYPE; -# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +}; # define YYLTYPE_IS_DECLARED 1 # define YYLTYPE_IS_TRIVIAL 1 #endif + + +int base_yyparse (core_yyscan_t yyscanner); + + +#endif /* !YY_BASE_YY_THIRD_PARTY_LIBPG_QUERY_GRAMMAR_GRAMMAR_OUT_HPP_INCLUDED */ diff --git a/third_party/libpg_query/include/parser/kwlist.hpp b/third_party/libpg_query/include/parser/kwlist.hpp index e39ca2994c2..ce9d00dbef3 100755 --- a/third_party/libpg_query/include/parser/kwlist.hpp +++ b/third_party/libpg_query/include/parser/kwlist.hpp @@ -138,6 +138,7 @@ PG_KEYWORD("explain", EXPLAIN, UNRESERVED_KEYWORD) PG_KEYWORD("export", EXPORT_P, UNRESERVED_KEYWORD) PG_KEYWORD("export_state", EXPORT_STATE, UNRESERVED_KEYWORD) PG_KEYWORD("extension", EXTENSION, UNRESERVED_KEYWORD) +PG_KEYWORD("extensions", EXTENSIONS, UNRESERVED_KEYWORD) PG_KEYWORD("external", EXTERNAL, UNRESERVED_KEYWORD) PG_KEYWORD("extract", EXTRACT, COL_NAME_KEYWORD) PG_KEYWORD("false", FALSE_P, RESERVED_KEYWORD) @@ -317,6 +318,8 @@ PG_KEYWORD("procedure", PROCEDURE, UNRESERVED_KEYWORD) PG_KEYWORD("program", PROGRAM, UNRESERVED_KEYWORD) PG_KEYWORD("publication", PUBLICATION, UNRESERVED_KEYWORD) PG_KEYWORD("qualify", QUALIFY, RESERVED_KEYWORD) +PG_KEYWORD("quarter", QUARTER_P, UNRESERVED_KEYWORD) +PG_KEYWORD("quarters", QUARTERS_P, UNRESERVED_KEYWORD) PG_KEYWORD("quote", QUOTE, UNRESERVED_KEYWORD) PG_KEYWORD("range", RANGE, UNRESERVED_KEYWORD) PG_KEYWORD("read", READ_P, UNRESERVED_KEYWORD) diff --git a/third_party/libpg_query/include/utils/datetime.hpp b/third_party/libpg_query/include/utils/datetime.hpp index b15b890ac1c..249652c77e7 100644 --- a/third_party/libpg_query/include/utils/datetime.hpp +++ b/third_party/libpg_query/include/utils/datetime.hpp @@ -64,6 +64,7 @@ #define MILLENNIUM 27 /* hack for parsing two-word timezone specs "MET DST" etc */ #define DTZMOD 28 /* "DST" as a separate word */ +#define QUARTER 29 /* reserved for unrecognized string values */ #define UNKNOWN_FIELD 31 diff --git a/third_party/libpg_query/pg_functions.cpp b/third_party/libpg_query/pg_functions.cpp index 9123bbd7d17..d3af77cf3f4 100644 --- a/third_party/libpg_query/pg_functions.cpp +++ b/third_party/libpg_query/pg_functions.cpp @@ -49,6 +49,9 @@ static void allocate_new(parser_state *state, size_t n) { if (state->malloc_ptr_idx >= state->malloc_ptr_size) { size_t new_size = state->malloc_ptr_size * 2; auto new_malloc_ptrs = (char **) malloc(sizeof(char *) * new_size); + if (!new_malloc_ptrs) { + throw std::bad_alloc(); + } memset(new_malloc_ptrs, 0, sizeof(char*) * new_size); memcpy(new_malloc_ptrs, state->malloc_ptrs, state->malloc_ptr_size * sizeof(char*)); free(state->malloc_ptrs); @@ -58,9 +61,9 @@ static void allocate_new(parser_state *state, size_t n) { if (n < PG_MALLOC_SIZE) { n = PG_MALLOC_SIZE; } - char *base_ptr = (char *)malloc(n); + auto base_ptr = (char *)malloc(n); if (!base_ptr) { - throw std::runtime_error("Memory allocation failure"); + throw std::bad_alloc(); } state->malloc_ptrs[state->malloc_ptr_idx] = base_ptr; state->malloc_ptr_idx++; @@ -90,7 +93,11 @@ void pg_parser_init() { pg_parser_state.pg_err_msg[0] = '\0'; pg_parser_state.malloc_ptr_size = 4; - pg_parser_state.malloc_ptrs = (char **) malloc(sizeof(char *) * pg_parser_state.malloc_ptr_size); + auto new_malloc_ptrs = (char **) malloc(sizeof(char *) * pg_parser_state.malloc_ptr_size); + if (!new_malloc_ptrs) { + throw std::bad_alloc(); + } + pg_parser_state.malloc_ptrs = new_malloc_ptrs; memset(pg_parser_state.malloc_ptrs, 0, sizeof(char*) * pg_parser_state.malloc_ptr_size); pg_parser_state.malloc_ptr_idx = 0; allocate_new(&pg_parser_state, 1); @@ -166,7 +173,7 @@ char *psprintf(const char *fmt, ...) { } // attempt two, malloc - char *mbuf = (char *)palloc(newlen); + auto mbuf = (char *)palloc(newlen); va_start(args, fmt); vsnprintf(mbuf, newlen, fmt, args); va_end(args); @@ -174,7 +181,7 @@ char *psprintf(const char *fmt, ...) { } char *pstrdup(const char *in) { - char *new_str = (char *)palloc(strlen(in) + 1); + auto new_str = (char*) palloc(strlen(in) + 1); memcpy(new_str, in, strlen(in)); return new_str; } @@ -191,7 +198,7 @@ void *repalloc(void *ptr, size_t n) { char *old_len_ptr = (char *) ptr - sizeof(size_t); memcpy((void *) &old_len, old_len_ptr, sizeof(size_t)); // re-allocate and copy the data - void *new_buf = palloc(n); + auto new_buf = palloc(n); memcpy(new_buf, ptr, old_len); return new_buf; } diff --git a/third_party/libpg_query/src_backend_parser_gram.cpp b/third_party/libpg_query/src_backend_parser_gram.cpp index f8b6577fd63..6f011d5bf9a 100644 --- a/third_party/libpg_query/src_backend_parser_gram.cpp +++ b/third_party/libpg_query/src_backend_parser_gram.cpp @@ -1,14 +1,14 @@ -/* A Bison parser, made by GNU Bison 2.3. */ +/* A Bison parser, made by GNU Bison 3.8.2. */ -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,9 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -36,6 +34,10 @@ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. @@ -43,11 +45,11 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ -/* Identify Bison output. */ -#define YYBISON 1 +/* Identify Bison output, and Bison version. */ +#define YYBISON 30802 -/* Bison version. */ -#define YYBISON_VERSION "2.3" +/* Bison version string. */ +#define YYBISON_VERSION "3.8.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -55,1033 +57,21 @@ /* Pure parsers. */ #define YYPURE 1 -/* Using locations. */ -#define YYLSP_NEEDED 1 +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + /* Substitute the variable and function names. */ -#define yyparse base_yyparse -#define yylex base_yylex -#define yyerror base_yyerror -#define yylval base_yylval -#define yychar base_yychar -#define yydebug base_yydebug -#define yynerrs base_yynerrs -#define yylloc base_yylloc - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - IDENT = 258, - FCONST = 259, - SCONST = 260, - BCONST = 261, - XCONST = 262, - Op = 263, - ICONST = 264, - PARAM = 265, - TYPECAST = 266, - DOT_DOT = 267, - COLON_EQUALS = 268, - EQUALS_GREATER = 269, - INTEGER_DIVISION = 270, - POWER_OF = 271, - LAMBDA_ARROW = 272, - DOUBLE_ARROW = 273, - LESS_EQUALS = 274, - GREATER_EQUALS = 275, - NOT_EQUALS = 276, - ABORT_P = 277, - ABSOLUTE_P = 278, - ACCESS = 279, - ACTION = 280, - ADD_P = 281, - ADMIN = 282, - AFTER = 283, - AGGREGATE = 284, - ALL = 285, - ALSO = 286, - ALTER = 287, - ALWAYS = 288, - ANALYSE = 289, - ANALYZE = 290, - AND = 291, - ANTI = 292, - ANY = 293, - ARRAY = 294, - AS = 295, - ASC_P = 296, - ASOF = 297, - ASSERTION = 298, - ASSIGNMENT = 299, - ASYMMETRIC = 300, - AT = 301, - ATTACH = 302, - ATTRIBUTE = 303, - AUTHORIZATION = 304, - BACKWARD = 305, - BEFORE = 306, - BEGIN_P = 307, - BETWEEN = 308, - BIGINT = 309, - BINARY = 310, - BIT = 311, - BOOLEAN_P = 312, - BOTH = 313, - BY = 314, - CACHE = 315, - CALL_P = 316, - CALLED = 317, - CASCADE = 318, - CASCADED = 319, - CASE = 320, - CAST = 321, - CATALOG_P = 322, - CENTURIES_P = 323, - CENTURY_P = 324, - CHAIN = 325, - CHAR_P = 326, - CHARACTER = 327, - CHARACTERISTICS = 328, - CHECK_P = 329, - CHECKPOINT = 330, - CLASS = 331, - CLOSE = 332, - CLUSTER = 333, - COALESCE = 334, - COLLATE = 335, - COLLATION = 336, - COLUMN = 337, - COLUMNS = 338, - COMMENT = 339, - COMMENTS = 340, - COMMIT = 341, - COMMITTED = 342, - COMPRESSION = 343, - CONCURRENTLY = 344, - CONFIGURATION = 345, - CONFLICT = 346, - CONNECTION = 347, - CONSTRAINT = 348, - CONSTRAINTS = 349, - CONTENT_P = 350, - CONTINUE_P = 351, - CONVERSION_P = 352, - COPY = 353, - COST = 354, - CREATE_P = 355, - CROSS = 356, - CSV = 357, - CUBE = 358, - CURRENT_P = 359, - CURSOR = 360, - CYCLE = 361, - DATA_P = 362, - DATABASE = 363, - DAY_P = 364, - DAYS_P = 365, - DEALLOCATE = 366, - DEC = 367, - DECADE_P = 368, - DECADES_P = 369, - DECIMAL_P = 370, - DECLARE = 371, - DEFAULT = 372, - DEFAULTS = 373, - DEFERRABLE = 374, - DEFERRED = 375, - DEFINER = 376, - DELETE_P = 377, - DELIMITER = 378, - DELIMITERS = 379, - DEPENDS = 380, - DESC_P = 381, - DESCRIBE = 382, - DETACH = 383, - DICTIONARY = 384, - DISABLE_P = 385, - DISCARD = 386, - DISTINCT = 387, - DO = 388, - DOCUMENT_P = 389, - DOMAIN_P = 390, - DOUBLE_P = 391, - DROP = 392, - EACH = 393, - ELSE = 394, - ENABLE_P = 395, - ENCODING = 396, - ENCRYPTED = 397, - END_P = 398, - ENUM_P = 399, - ESCAPE = 400, - EVENT = 401, - EXCEPT = 402, - EXCLUDE = 403, - EXCLUDING = 404, - EXCLUSIVE = 405, - EXECUTE = 406, - EXISTS = 407, - EXPLAIN = 408, - EXPORT_P = 409, - EXPORT_STATE = 410, - EXTENSION = 411, - EXTERNAL = 412, - EXTRACT = 413, - FALSE_P = 414, - FAMILY = 415, - FETCH = 416, - FILTER = 417, - FIRST_P = 418, - FLOAT_P = 419, - FOLLOWING = 420, - FOR = 421, - FORCE = 422, - FOREIGN = 423, - FORWARD = 424, - FREEZE = 425, - FROM = 426, - FULL = 427, - FUNCTION = 428, - FUNCTIONS = 429, - GENERATED = 430, - GLOB = 431, - GLOBAL = 432, - GRANT = 433, - GRANTED = 434, - GROUP_P = 435, - GROUPING = 436, - GROUPING_ID = 437, - GROUPS = 438, - HANDLER = 439, - HAVING = 440, - HEADER_P = 441, - HOLD = 442, - HOUR_P = 443, - HOURS_P = 444, - IDENTITY_P = 445, - IF_P = 446, - IGNORE_P = 447, - ILIKE = 448, - IMMEDIATE = 449, - IMMUTABLE = 450, - IMPLICIT_P = 451, - IMPORT_P = 452, - IN_P = 453, - INCLUDE_P = 454, - INCLUDING = 455, - INCREMENT = 456, - INDEX = 457, - INDEXES = 458, - INHERIT = 459, - INHERITS = 460, - INITIALLY = 461, - INLINE_P = 462, - INNER_P = 463, - INOUT = 464, - INPUT_P = 465, - INSENSITIVE = 466, - INSERT = 467, - INSTALL = 468, - INSTEAD = 469, - INT_P = 470, - INTEGER = 471, - INTERSECT = 472, - INTERVAL = 473, - INTO = 474, - INVOKER = 475, - IS = 476, - ISNULL = 477, - ISOLATION = 478, - JOIN = 479, - JSON = 480, - KEY = 481, - LABEL = 482, - LANGUAGE = 483, - LARGE_P = 484, - LAST_P = 485, - LATERAL_P = 486, - LEADING = 487, - LEAKPROOF = 488, - LEFT = 489, - LEVEL = 490, - LIKE = 491, - LIMIT = 492, - LISTEN = 493, - LOAD = 494, - LOCAL = 495, - LOCATION = 496, - LOCK_P = 497, - LOCKED = 498, - LOGGED = 499, - MACRO = 500, - MAP = 501, - MAPPING = 502, - MATCH = 503, - MATERIALIZED = 504, - MAXVALUE = 505, - METHOD = 506, - MICROSECOND_P = 507, - MICROSECONDS_P = 508, - MILLENNIA_P = 509, - MILLENNIUM_P = 510, - MILLISECOND_P = 511, - MILLISECONDS_P = 512, - MINUTE_P = 513, - MINUTES_P = 514, - MINVALUE = 515, - MODE = 516, - MONTH_P = 517, - MONTHS_P = 518, - MOVE = 519, - NAME_P = 520, - NAMES = 521, - NATIONAL = 522, - NATURAL = 523, - NCHAR = 524, - NEW = 525, - NEXT = 526, - NO = 527, - NONE = 528, - NOT = 529, - NOTHING = 530, - NOTIFY = 531, - NOTNULL = 532, - NOWAIT = 533, - NULL_P = 534, - NULLIF = 535, - NULLS_P = 536, - NUMERIC = 537, - OBJECT_P = 538, - OF = 539, - OFF = 540, - OFFSET = 541, - OIDS = 542, - OLD = 543, - ON = 544, - ONLY = 545, - OPERATOR = 546, - OPTION = 547, - OPTIONS = 548, - OR = 549, - ORDER = 550, - ORDINALITY = 551, - OTHERS = 552, - OUT_P = 553, - OUTER_P = 554, - OVER = 555, - OVERLAPS = 556, - OVERLAY = 557, - OVERRIDING = 558, - OWNED = 559, - OWNER = 560, - PARALLEL = 561, - PARSER = 562, - PARTIAL = 563, - PARTITION = 564, - PASSING = 565, - PASSWORD = 566, - PERCENT = 567, - PERSISTENT = 568, - PIVOT = 569, - PIVOT_LONGER = 570, - PIVOT_WIDER = 571, - PLACING = 572, - PLANS = 573, - POLICY = 574, - POSITION = 575, - POSITIONAL = 576, - PRAGMA_P = 577, - PRECEDING = 578, - PRECISION = 579, - PREPARE = 580, - PREPARED = 581, - PRESERVE = 582, - PRIMARY = 583, - PRIOR = 584, - PRIVILEGES = 585, - PROCEDURAL = 586, - PROCEDURE = 587, - PROGRAM = 588, - PUBLICATION = 589, - QUALIFY = 590, - QUOTE = 591, - RANGE = 592, - READ_P = 593, - REAL = 594, - REASSIGN = 595, - RECHECK = 596, - RECURSIVE = 597, - REF = 598, - REFERENCES = 599, - REFERENCING = 600, - REFRESH = 601, - REINDEX = 602, - RELATIVE_P = 603, - RELEASE = 604, - RENAME = 605, - REPEATABLE = 606, - REPLACE = 607, - REPLICA = 608, - RESET = 609, - RESPECT_P = 610, - RESTART = 611, - RESTRICT = 612, - RETURNING = 613, - RETURNS = 614, - REVOKE = 615, - RIGHT = 616, - ROLE = 617, - ROLLBACK = 618, - ROLLUP = 619, - ROW = 620, - ROWS = 621, - RULE = 622, - SAMPLE = 623, - SAVEPOINT = 624, - SCHEMA = 625, - SCHEMAS = 626, - SCOPE = 627, - SCROLL = 628, - SEARCH = 629, - SECOND_P = 630, - SECONDS_P = 631, - SECRET = 632, - SECURITY = 633, - SELECT = 634, - SEMI = 635, - SEQUENCE = 636, - SEQUENCES = 637, - SERIALIZABLE = 638, - SERVER = 639, - SESSION = 640, - SET = 641, - SETOF = 642, - SETS = 643, - SHARE = 644, - SHOW = 645, - SIMILAR = 646, - SIMPLE = 647, - SKIP = 648, - SMALLINT = 649, - SNAPSHOT = 650, - SOME = 651, - SQL_P = 652, - STABLE = 653, - STANDALONE_P = 654, - START = 655, - STATEMENT = 656, - STATISTICS = 657, - STDIN = 658, - STDOUT = 659, - STORAGE = 660, - STORED = 661, - STRICT_P = 662, - STRIP_P = 663, - STRUCT = 664, - SUBSCRIPTION = 665, - SUBSTRING = 666, - SUMMARIZE = 667, - SYMMETRIC = 668, - SYSID = 669, - SYSTEM_P = 670, - TABLE = 671, - TABLES = 672, - TABLESAMPLE = 673, - TABLESPACE = 674, - TEMP = 675, - TEMPLATE = 676, - TEMPORARY = 677, - TEXT_P = 678, - THEN = 679, - TIES = 680, - TIME = 681, - TIMESTAMP = 682, - TO = 683, - TRAILING = 684, - TRANSACTION = 685, - TRANSFORM = 686, - TREAT = 687, - TRIGGER = 688, - TRIM = 689, - TRUE_P = 690, - TRUNCATE = 691, - TRUSTED = 692, - TRY_CAST = 693, - TYPE_P = 694, - TYPES_P = 695, - UNBOUNDED = 696, - UNCOMMITTED = 697, - UNENCRYPTED = 698, - UNION = 699, - UNIQUE = 700, - UNKNOWN = 701, - UNLISTEN = 702, - UNLOGGED = 703, - UNPIVOT = 704, - UNTIL = 705, - UPDATE = 706, - USE_P = 707, - USER = 708, - USING = 709, - VACUUM = 710, - VALID = 711, - VALIDATE = 712, - VALIDATOR = 713, - VALUE_P = 714, - VALUES = 715, - VARCHAR = 716, - VARIADIC = 717, - VARYING = 718, - VERBOSE = 719, - VERSION_P = 720, - VIEW = 721, - VIEWS = 722, - VIRTUAL = 723, - VOLATILE = 724, - WEEK_P = 725, - WEEKS_P = 726, - WHEN = 727, - WHERE = 728, - WHITESPACE_P = 729, - WINDOW = 730, - WITH = 731, - WITHIN = 732, - WITHOUT = 733, - WORK = 734, - WRAPPER = 735, - WRITE_P = 736, - XML_P = 737, - XMLATTRIBUTES = 738, - XMLCONCAT = 739, - XMLELEMENT = 740, - XMLEXISTS = 741, - XMLFOREST = 742, - XMLNAMESPACES = 743, - XMLPARSE = 744, - XMLPI = 745, - XMLROOT = 746, - XMLSERIALIZE = 747, - XMLTABLE = 748, - YEAR_P = 749, - YEARS_P = 750, - YES_P = 751, - ZONE = 752, - NOT_LA = 753, - NULLS_LA = 754, - WITH_LA = 755, - POSTFIXOP = 756, - UMINUS = 757 - }; -#endif -/* Tokens. */ -#define IDENT 258 -#define FCONST 259 -#define SCONST 260 -#define BCONST 261 -#define XCONST 262 -#define Op 263 -#define ICONST 264 -#define PARAM 265 -#define TYPECAST 266 -#define DOT_DOT 267 -#define COLON_EQUALS 268 -#define EQUALS_GREATER 269 -#define INTEGER_DIVISION 270 -#define POWER_OF 271 -#define LAMBDA_ARROW 272 -#define DOUBLE_ARROW 273 -#define LESS_EQUALS 274 -#define GREATER_EQUALS 275 -#define NOT_EQUALS 276 -#define ABORT_P 277 -#define ABSOLUTE_P 278 -#define ACCESS 279 -#define ACTION 280 -#define ADD_P 281 -#define ADMIN 282 -#define AFTER 283 -#define AGGREGATE 284 -#define ALL 285 -#define ALSO 286 -#define ALTER 287 -#define ALWAYS 288 -#define ANALYSE 289 -#define ANALYZE 290 -#define AND 291 -#define ANTI 292 -#define ANY 293 -#define ARRAY 294 -#define AS 295 -#define ASC_P 296 -#define ASOF 297 -#define ASSERTION 298 -#define ASSIGNMENT 299 -#define ASYMMETRIC 300 -#define AT 301 -#define ATTACH 302 -#define ATTRIBUTE 303 -#define AUTHORIZATION 304 -#define BACKWARD 305 -#define BEFORE 306 -#define BEGIN_P 307 -#define BETWEEN 308 -#define BIGINT 309 -#define BINARY 310 -#define BIT 311 -#define BOOLEAN_P 312 -#define BOTH 313 -#define BY 314 -#define CACHE 315 -#define CALL_P 316 -#define CALLED 317 -#define CASCADE 318 -#define CASCADED 319 -#define CASE 320 -#define CAST 321 -#define CATALOG_P 322 -#define CENTURIES_P 323 -#define CENTURY_P 324 -#define CHAIN 325 -#define CHAR_P 326 -#define CHARACTER 327 -#define CHARACTERISTICS 328 -#define CHECK_P 329 -#define CHECKPOINT 330 -#define CLASS 331 -#define CLOSE 332 -#define CLUSTER 333 -#define COALESCE 334 -#define COLLATE 335 -#define COLLATION 336 -#define COLUMN 337 -#define COLUMNS 338 -#define COMMENT 339 -#define COMMENTS 340 -#define COMMIT 341 -#define COMMITTED 342 -#define COMPRESSION 343 -#define CONCURRENTLY 344 -#define CONFIGURATION 345 -#define CONFLICT 346 -#define CONNECTION 347 -#define CONSTRAINT 348 -#define CONSTRAINTS 349 -#define CONTENT_P 350 -#define CONTINUE_P 351 -#define CONVERSION_P 352 -#define COPY 353 -#define COST 354 -#define CREATE_P 355 -#define CROSS 356 -#define CSV 357 -#define CUBE 358 -#define CURRENT_P 359 -#define CURSOR 360 -#define CYCLE 361 -#define DATA_P 362 -#define DATABASE 363 -#define DAY_P 364 -#define DAYS_P 365 -#define DEALLOCATE 366 -#define DEC 367 -#define DECADE_P 368 -#define DECADES_P 369 -#define DECIMAL_P 370 -#define DECLARE 371 -#define DEFAULT 372 -#define DEFAULTS 373 -#define DEFERRABLE 374 -#define DEFERRED 375 -#define DEFINER 376 -#define DELETE_P 377 -#define DELIMITER 378 -#define DELIMITERS 379 -#define DEPENDS 380 -#define DESC_P 381 -#define DESCRIBE 382 -#define DETACH 383 -#define DICTIONARY 384 -#define DISABLE_P 385 -#define DISCARD 386 -#define DISTINCT 387 -#define DO 388 -#define DOCUMENT_P 389 -#define DOMAIN_P 390 -#define DOUBLE_P 391 -#define DROP 392 -#define EACH 393 -#define ELSE 394 -#define ENABLE_P 395 -#define ENCODING 396 -#define ENCRYPTED 397 -#define END_P 398 -#define ENUM_P 399 -#define ESCAPE 400 -#define EVENT 401 -#define EXCEPT 402 -#define EXCLUDE 403 -#define EXCLUDING 404 -#define EXCLUSIVE 405 -#define EXECUTE 406 -#define EXISTS 407 -#define EXPLAIN 408 -#define EXPORT_P 409 -#define EXPORT_STATE 410 -#define EXTENSION 411 -#define EXTERNAL 412 -#define EXTRACT 413 -#define FALSE_P 414 -#define FAMILY 415 -#define FETCH 416 -#define FILTER 417 -#define FIRST_P 418 -#define FLOAT_P 419 -#define FOLLOWING 420 -#define FOR 421 -#define FORCE 422 -#define FOREIGN 423 -#define FORWARD 424 -#define FREEZE 425 -#define FROM 426 -#define FULL 427 -#define FUNCTION 428 -#define FUNCTIONS 429 -#define GENERATED 430 -#define GLOB 431 -#define GLOBAL 432 -#define GRANT 433 -#define GRANTED 434 -#define GROUP_P 435 -#define GROUPING 436 -#define GROUPING_ID 437 -#define GROUPS 438 -#define HANDLER 439 -#define HAVING 440 -#define HEADER_P 441 -#define HOLD 442 -#define HOUR_P 443 -#define HOURS_P 444 -#define IDENTITY_P 445 -#define IF_P 446 -#define IGNORE_P 447 -#define ILIKE 448 -#define IMMEDIATE 449 -#define IMMUTABLE 450 -#define IMPLICIT_P 451 -#define IMPORT_P 452 -#define IN_P 453 -#define INCLUDE_P 454 -#define INCLUDING 455 -#define INCREMENT 456 -#define INDEX 457 -#define INDEXES 458 -#define INHERIT 459 -#define INHERITS 460 -#define INITIALLY 461 -#define INLINE_P 462 -#define INNER_P 463 -#define INOUT 464 -#define INPUT_P 465 -#define INSENSITIVE 466 -#define INSERT 467 -#define INSTALL 468 -#define INSTEAD 469 -#define INT_P 470 -#define INTEGER 471 -#define INTERSECT 472 -#define INTERVAL 473 -#define INTO 474 -#define INVOKER 475 -#define IS 476 -#define ISNULL 477 -#define ISOLATION 478 -#define JOIN 479 -#define JSON 480 -#define KEY 481 -#define LABEL 482 -#define LANGUAGE 483 -#define LARGE_P 484 -#define LAST_P 485 -#define LATERAL_P 486 -#define LEADING 487 -#define LEAKPROOF 488 -#define LEFT 489 -#define LEVEL 490 -#define LIKE 491 -#define LIMIT 492 -#define LISTEN 493 -#define LOAD 494 -#define LOCAL 495 -#define LOCATION 496 -#define LOCK_P 497 -#define LOCKED 498 -#define LOGGED 499 -#define MACRO 500 -#define MAP 501 -#define MAPPING 502 -#define MATCH 503 -#define MATERIALIZED 504 -#define MAXVALUE 505 -#define METHOD 506 -#define MICROSECOND_P 507 -#define MICROSECONDS_P 508 -#define MILLENNIA_P 509 -#define MILLENNIUM_P 510 -#define MILLISECOND_P 511 -#define MILLISECONDS_P 512 -#define MINUTE_P 513 -#define MINUTES_P 514 -#define MINVALUE 515 -#define MODE 516 -#define MONTH_P 517 -#define MONTHS_P 518 -#define MOVE 519 -#define NAME_P 520 -#define NAMES 521 -#define NATIONAL 522 -#define NATURAL 523 -#define NCHAR 524 -#define NEW 525 -#define NEXT 526 -#define NO 527 -#define NONE 528 -#define NOT 529 -#define NOTHING 530 -#define NOTIFY 531 -#define NOTNULL 532 -#define NOWAIT 533 -#define NULL_P 534 -#define NULLIF 535 -#define NULLS_P 536 -#define NUMERIC 537 -#define OBJECT_P 538 -#define OF 539 -#define OFF 540 -#define OFFSET 541 -#define OIDS 542 -#define OLD 543 -#define ON 544 -#define ONLY 545 -#define OPERATOR 546 -#define OPTION 547 -#define OPTIONS 548 -#define OR 549 -#define ORDER 550 -#define ORDINALITY 551 -#define OTHERS 552 -#define OUT_P 553 -#define OUTER_P 554 -#define OVER 555 -#define OVERLAPS 556 -#define OVERLAY 557 -#define OVERRIDING 558 -#define OWNED 559 -#define OWNER 560 -#define PARALLEL 561 -#define PARSER 562 -#define PARTIAL 563 -#define PARTITION 564 -#define PASSING 565 -#define PASSWORD 566 -#define PERCENT 567 -#define PERSISTENT 568 -#define PIVOT 569 -#define PIVOT_LONGER 570 -#define PIVOT_WIDER 571 -#define PLACING 572 -#define PLANS 573 -#define POLICY 574 -#define POSITION 575 -#define POSITIONAL 576 -#define PRAGMA_P 577 -#define PRECEDING 578 -#define PRECISION 579 -#define PREPARE 580 -#define PREPARED 581 -#define PRESERVE 582 -#define PRIMARY 583 -#define PRIOR 584 -#define PRIVILEGES 585 -#define PROCEDURAL 586 -#define PROCEDURE 587 -#define PROGRAM 588 -#define PUBLICATION 589 -#define QUALIFY 590 -#define QUOTE 591 -#define RANGE 592 -#define READ_P 593 -#define REAL 594 -#define REASSIGN 595 -#define RECHECK 596 -#define RECURSIVE 597 -#define REF 598 -#define REFERENCES 599 -#define REFERENCING 600 -#define REFRESH 601 -#define REINDEX 602 -#define RELATIVE_P 603 -#define RELEASE 604 -#define RENAME 605 -#define REPEATABLE 606 -#define REPLACE 607 -#define REPLICA 608 -#define RESET 609 -#define RESPECT_P 610 -#define RESTART 611 -#define RESTRICT 612 -#define RETURNING 613 -#define RETURNS 614 -#define REVOKE 615 -#define RIGHT 616 -#define ROLE 617 -#define ROLLBACK 618 -#define ROLLUP 619 -#define ROW 620 -#define ROWS 621 -#define RULE 622 -#define SAMPLE 623 -#define SAVEPOINT 624 -#define SCHEMA 625 -#define SCHEMAS 626 -#define SCOPE 627 -#define SCROLL 628 -#define SEARCH 629 -#define SECOND_P 630 -#define SECONDS_P 631 -#define SECRET 632 -#define SECURITY 633 -#define SELECT 634 -#define SEMI 635 -#define SEQUENCE 636 -#define SEQUENCES 637 -#define SERIALIZABLE 638 -#define SERVER 639 -#define SESSION 640 -#define SET 641 -#define SETOF 642 -#define SETS 643 -#define SHARE 644 -#define SHOW 645 -#define SIMILAR 646 -#define SIMPLE 647 -#define SKIP 648 -#define SMALLINT 649 -#define SNAPSHOT 650 -#define SOME 651 -#define SQL_P 652 -#define STABLE 653 -#define STANDALONE_P 654 -#define START 655 -#define STATEMENT 656 -#define STATISTICS 657 -#define STDIN 658 -#define STDOUT 659 -#define STORAGE 660 -#define STORED 661 -#define STRICT_P 662 -#define STRIP_P 663 -#define STRUCT 664 -#define SUBSCRIPTION 665 -#define SUBSTRING 666 -#define SUMMARIZE 667 -#define SYMMETRIC 668 -#define SYSID 669 -#define SYSTEM_P 670 -#define TABLE 671 -#define TABLES 672 -#define TABLESAMPLE 673 -#define TABLESPACE 674 -#define TEMP 675 -#define TEMPLATE 676 -#define TEMPORARY 677 -#define TEXT_P 678 -#define THEN 679 -#define TIES 680 -#define TIME 681 -#define TIMESTAMP 682 -#define TO 683 -#define TRAILING 684 -#define TRANSACTION 685 -#define TRANSFORM 686 -#define TREAT 687 -#define TRIGGER 688 -#define TRIM 689 -#define TRUE_P 690 -#define TRUNCATE 691 -#define TRUSTED 692 -#define TRY_CAST 693 -#define TYPE_P 694 -#define TYPES_P 695 -#define UNBOUNDED 696 -#define UNCOMMITTED 697 -#define UNENCRYPTED 698 -#define UNION 699 -#define UNIQUE 700 -#define UNKNOWN 701 -#define UNLISTEN 702 -#define UNLOGGED 703 -#define UNPIVOT 704 -#define UNTIL 705 -#define UPDATE 706 -#define USE_P 707 -#define USER 708 -#define USING 709 -#define VACUUM 710 -#define VALID 711 -#define VALIDATE 712 -#define VALIDATOR 713 -#define VALUE_P 714 -#define VALUES 715 -#define VARCHAR 716 -#define VARIADIC 717 -#define VARYING 718 -#define VERBOSE 719 -#define VERSION_P 720 -#define VIEW 721 -#define VIEWS 722 -#define VIRTUAL 723 -#define VOLATILE 724 -#define WEEK_P 725 -#define WEEKS_P 726 -#define WHEN 727 -#define WHERE 728 -#define WHITESPACE_P 729 -#define WINDOW 730 -#define WITH 731 -#define WITHIN 732 -#define WITHOUT 733 -#define WORK 734 -#define WRAPPER 735 -#define WRITE_P 736 -#define XML_P 737 -#define XMLATTRIBUTES 738 -#define XMLCONCAT 739 -#define XMLELEMENT 740 -#define XMLEXISTS 741 -#define XMLFOREST 742 -#define XMLNAMESPACES 743 -#define XMLPARSE 744 -#define XMLPI 745 -#define XMLROOT 746 -#define XMLSERIALIZE 747 -#define XMLTABLE 748 -#define YEAR_P 749 -#define YEARS_P 750 -#define YES_P 751 -#define ZONE 752 -#define NOT_LA 753 -#define NULLS_LA 754 -#define WITH_LA 755 -#define POSTFIXOP 756 -#define UMINUS 757 - - - - -/* Copy the first part of user declarations. */ +#define yyparse base_yyparse +#define yylex base_yylex +#define yyerror base_yyerror +#define yydebug base_yydebug +#define yynerrs base_yynerrs + +/* First part of user prologue. */ #line 1 "third_party/libpg_query/grammar/grammar.y.tmp" #line 1 "third_party/libpg_query/grammar/grammar.hpp" @@ -1247,133 +237,1117 @@ static PGNode *makeRecursiveViewSelect(char *relname, PGList *aliases, PGNode *q static PGNode *makeLimitPercent(PGNode *limit_percent); +#line 241 "third_party/libpg_query/grammar/grammar_out.cpp" -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 -#endif - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -#line 14 "third_party/libpg_query/grammar/grammar.y" -{ - core_YYSTYPE core_yystype; - /* these fields must match core_YYSTYPE: */ - int ival; - char *str; - const char *keyword; - const char *conststr; - - char chr; - bool boolean; - PGJoinType jtype; - PGDropBehavior dbehavior; - PGOnCommitAction oncommit; - PGOnCreateConflict oncreateconflict; - PGList *list; - PGNode *node; - PGValue *value; - PGObjectType objtype; - PGTypeName *typnam; - PGObjectWithArgs *objwithargs; - PGDefElem *defelt; - PGSortBy *sortby; - PGWindowDef *windef; - PGJoinExpr *jexpr; - PGIndexElem *ielem; - PGAlias *alias; - PGRangeVar *range; - PGIntoClause *into; - PGCTEMaterialize ctematerialize; - PGWithClause *with; - PGInferClause *infer; - PGOnConflictClause *onconflict; - PGOnConflictActionAlias onconflictshorthand; - PGAIndices *aind; - PGResTarget *target; - PGInsertStmt *istmt; - PGVariableSetStmt *vsetstmt; - PGOverridingKind override; - PGSortByDir sortorder; - PGSortByNulls nullorder; - PGIgnoreNulls ignorenulls; - PGConstrType constr; - PGLockClauseStrength lockstrength; - PGLockWaitPolicy lockwaitpolicy; - PGSubLinkType subquerytype; - PGViewCheckOption viewcheckoption; - PGInsertColumnOrder bynameorposition; -} -/* Line 193 of yacc.c. */ -#line 1322 "third_party/libpg_query/grammar/grammar_out.cpp" - YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE +#include "include/parser/gram.hpp" +/* Symbol kind. */ +enum yysymbol_kind_t { - int first_line; - int first_column; - int last_line; - int last_column; -} YYLTYPE; -# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 -#endif - + YYSYMBOL_YYEMPTY = -2, + YYSYMBOL_YYEOF = 0, /* "end of file" */ + YYSYMBOL_YYerror = 1, /* error */ + YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ + YYSYMBOL_IDENT = 3, /* IDENT */ + YYSYMBOL_FCONST = 4, /* FCONST */ + YYSYMBOL_SCONST = 5, /* SCONST */ + YYSYMBOL_BCONST = 6, /* BCONST */ + YYSYMBOL_XCONST = 7, /* XCONST */ + YYSYMBOL_Op = 8, /* Op */ + YYSYMBOL_ICONST = 9, /* ICONST */ + YYSYMBOL_PARAM = 10, /* PARAM */ + YYSYMBOL_TYPECAST = 11, /* TYPECAST */ + YYSYMBOL_DOT_DOT = 12, /* DOT_DOT */ + YYSYMBOL_COLON_EQUALS = 13, /* COLON_EQUALS */ + YYSYMBOL_EQUALS_GREATER = 14, /* EQUALS_GREATER */ + YYSYMBOL_INTEGER_DIVISION = 15, /* INTEGER_DIVISION */ + YYSYMBOL_POWER_OF = 16, /* POWER_OF */ + YYSYMBOL_LAMBDA_ARROW = 17, /* LAMBDA_ARROW */ + YYSYMBOL_DOUBLE_ARROW = 18, /* DOUBLE_ARROW */ + YYSYMBOL_LESS_EQUALS = 19, /* LESS_EQUALS */ + YYSYMBOL_GREATER_EQUALS = 20, /* GREATER_EQUALS */ + YYSYMBOL_NOT_EQUALS = 21, /* NOT_EQUALS */ + YYSYMBOL_ABORT_P = 22, /* ABORT_P */ + YYSYMBOL_ABSOLUTE_P = 23, /* ABSOLUTE_P */ + YYSYMBOL_ACCESS = 24, /* ACCESS */ + YYSYMBOL_ACTION = 25, /* ACTION */ + YYSYMBOL_ADD_P = 26, /* ADD_P */ + YYSYMBOL_ADMIN = 27, /* ADMIN */ + YYSYMBOL_AFTER = 28, /* AFTER */ + YYSYMBOL_AGGREGATE = 29, /* AGGREGATE */ + YYSYMBOL_ALL = 30, /* ALL */ + YYSYMBOL_ALSO = 31, /* ALSO */ + YYSYMBOL_ALTER = 32, /* ALTER */ + YYSYMBOL_ALWAYS = 33, /* ALWAYS */ + YYSYMBOL_ANALYSE = 34, /* ANALYSE */ + YYSYMBOL_ANALYZE = 35, /* ANALYZE */ + YYSYMBOL_AND = 36, /* AND */ + YYSYMBOL_ANTI = 37, /* ANTI */ + YYSYMBOL_ANY = 38, /* ANY */ + YYSYMBOL_ARRAY = 39, /* ARRAY */ + YYSYMBOL_AS = 40, /* AS */ + YYSYMBOL_ASC_P = 41, /* ASC_P */ + YYSYMBOL_ASOF = 42, /* ASOF */ + YYSYMBOL_ASSERTION = 43, /* ASSERTION */ + YYSYMBOL_ASSIGNMENT = 44, /* ASSIGNMENT */ + YYSYMBOL_ASYMMETRIC = 45, /* ASYMMETRIC */ + YYSYMBOL_AT = 46, /* AT */ + YYSYMBOL_ATTACH = 47, /* ATTACH */ + YYSYMBOL_ATTRIBUTE = 48, /* ATTRIBUTE */ + YYSYMBOL_AUTHORIZATION = 49, /* AUTHORIZATION */ + YYSYMBOL_BACKWARD = 50, /* BACKWARD */ + YYSYMBOL_BEFORE = 51, /* BEFORE */ + YYSYMBOL_BEGIN_P = 52, /* BEGIN_P */ + YYSYMBOL_BETWEEN = 53, /* BETWEEN */ + YYSYMBOL_BIGINT = 54, /* BIGINT */ + YYSYMBOL_BINARY = 55, /* BINARY */ + YYSYMBOL_BIT = 56, /* BIT */ + YYSYMBOL_BOOLEAN_P = 57, /* BOOLEAN_P */ + YYSYMBOL_BOTH = 58, /* BOTH */ + YYSYMBOL_BY = 59, /* BY */ + YYSYMBOL_CACHE = 60, /* CACHE */ + YYSYMBOL_CALL_P = 61, /* CALL_P */ + YYSYMBOL_CALLED = 62, /* CALLED */ + YYSYMBOL_CASCADE = 63, /* CASCADE */ + YYSYMBOL_CASCADED = 64, /* CASCADED */ + YYSYMBOL_CASE = 65, /* CASE */ + YYSYMBOL_CAST = 66, /* CAST */ + YYSYMBOL_CATALOG_P = 67, /* CATALOG_P */ + YYSYMBOL_CENTURIES_P = 68, /* CENTURIES_P */ + YYSYMBOL_CENTURY_P = 69, /* CENTURY_P */ + YYSYMBOL_CHAIN = 70, /* CHAIN */ + YYSYMBOL_CHAR_P = 71, /* CHAR_P */ + YYSYMBOL_CHARACTER = 72, /* CHARACTER */ + YYSYMBOL_CHARACTERISTICS = 73, /* CHARACTERISTICS */ + YYSYMBOL_CHECK_P = 74, /* CHECK_P */ + YYSYMBOL_CHECKPOINT = 75, /* CHECKPOINT */ + YYSYMBOL_CLASS = 76, /* CLASS */ + YYSYMBOL_CLOSE = 77, /* CLOSE */ + YYSYMBOL_CLUSTER = 78, /* CLUSTER */ + YYSYMBOL_COALESCE = 79, /* COALESCE */ + YYSYMBOL_COLLATE = 80, /* COLLATE */ + YYSYMBOL_COLLATION = 81, /* COLLATION */ + YYSYMBOL_COLUMN = 82, /* COLUMN */ + YYSYMBOL_COLUMNS = 83, /* COLUMNS */ + YYSYMBOL_COMMENT = 84, /* COMMENT */ + YYSYMBOL_COMMENTS = 85, /* COMMENTS */ + YYSYMBOL_COMMIT = 86, /* COMMIT */ + YYSYMBOL_COMMITTED = 87, /* COMMITTED */ + YYSYMBOL_COMPRESSION = 88, /* COMPRESSION */ + YYSYMBOL_CONCURRENTLY = 89, /* CONCURRENTLY */ + YYSYMBOL_CONFIGURATION = 90, /* CONFIGURATION */ + YYSYMBOL_CONFLICT = 91, /* CONFLICT */ + YYSYMBOL_CONNECTION = 92, /* CONNECTION */ + YYSYMBOL_CONSTRAINT = 93, /* CONSTRAINT */ + YYSYMBOL_CONSTRAINTS = 94, /* CONSTRAINTS */ + YYSYMBOL_CONTENT_P = 95, /* CONTENT_P */ + YYSYMBOL_CONTINUE_P = 96, /* CONTINUE_P */ + YYSYMBOL_CONVERSION_P = 97, /* CONVERSION_P */ + YYSYMBOL_COPY = 98, /* COPY */ + YYSYMBOL_COST = 99, /* COST */ + YYSYMBOL_CREATE_P = 100, /* CREATE_P */ + YYSYMBOL_CROSS = 101, /* CROSS */ + YYSYMBOL_CSV = 102, /* CSV */ + YYSYMBOL_CUBE = 103, /* CUBE */ + YYSYMBOL_CURRENT_P = 104, /* CURRENT_P */ + YYSYMBOL_CURSOR = 105, /* CURSOR */ + YYSYMBOL_CYCLE = 106, /* CYCLE */ + YYSYMBOL_DATA_P = 107, /* DATA_P */ + YYSYMBOL_DATABASE = 108, /* DATABASE */ + YYSYMBOL_DAY_P = 109, /* DAY_P */ + YYSYMBOL_DAYS_P = 110, /* DAYS_P */ + YYSYMBOL_DEALLOCATE = 111, /* DEALLOCATE */ + YYSYMBOL_DEC = 112, /* DEC */ + YYSYMBOL_DECADE_P = 113, /* DECADE_P */ + YYSYMBOL_DECADES_P = 114, /* DECADES_P */ + YYSYMBOL_DECIMAL_P = 115, /* DECIMAL_P */ + YYSYMBOL_DECLARE = 116, /* DECLARE */ + YYSYMBOL_DEFAULT = 117, /* DEFAULT */ + YYSYMBOL_DEFAULTS = 118, /* DEFAULTS */ + YYSYMBOL_DEFERRABLE = 119, /* DEFERRABLE */ + YYSYMBOL_DEFERRED = 120, /* DEFERRED */ + YYSYMBOL_DEFINER = 121, /* DEFINER */ + YYSYMBOL_DELETE_P = 122, /* DELETE_P */ + YYSYMBOL_DELIMITER = 123, /* DELIMITER */ + YYSYMBOL_DELIMITERS = 124, /* DELIMITERS */ + YYSYMBOL_DEPENDS = 125, /* DEPENDS */ + YYSYMBOL_DESC_P = 126, /* DESC_P */ + YYSYMBOL_DESCRIBE = 127, /* DESCRIBE */ + YYSYMBOL_DETACH = 128, /* DETACH */ + YYSYMBOL_DICTIONARY = 129, /* DICTIONARY */ + YYSYMBOL_DISABLE_P = 130, /* DISABLE_P */ + YYSYMBOL_DISCARD = 131, /* DISCARD */ + YYSYMBOL_DISTINCT = 132, /* DISTINCT */ + YYSYMBOL_DO = 133, /* DO */ + YYSYMBOL_DOCUMENT_P = 134, /* DOCUMENT_P */ + YYSYMBOL_DOMAIN_P = 135, /* DOMAIN_P */ + YYSYMBOL_DOUBLE_P = 136, /* DOUBLE_P */ + YYSYMBOL_DROP = 137, /* DROP */ + YYSYMBOL_EACH = 138, /* EACH */ + YYSYMBOL_ELSE = 139, /* ELSE */ + YYSYMBOL_ENABLE_P = 140, /* ENABLE_P */ + YYSYMBOL_ENCODING = 141, /* ENCODING */ + YYSYMBOL_ENCRYPTED = 142, /* ENCRYPTED */ + YYSYMBOL_END_P = 143, /* END_P */ + YYSYMBOL_ENUM_P = 144, /* ENUM_P */ + YYSYMBOL_ESCAPE = 145, /* ESCAPE */ + YYSYMBOL_EVENT = 146, /* EVENT */ + YYSYMBOL_EXCEPT = 147, /* EXCEPT */ + YYSYMBOL_EXCLUDE = 148, /* EXCLUDE */ + YYSYMBOL_EXCLUDING = 149, /* EXCLUDING */ + YYSYMBOL_EXCLUSIVE = 150, /* EXCLUSIVE */ + YYSYMBOL_EXECUTE = 151, /* EXECUTE */ + YYSYMBOL_EXISTS = 152, /* EXISTS */ + YYSYMBOL_EXPLAIN = 153, /* EXPLAIN */ + YYSYMBOL_EXPORT_P = 154, /* EXPORT_P */ + YYSYMBOL_EXPORT_STATE = 155, /* EXPORT_STATE */ + YYSYMBOL_EXTENSION = 156, /* EXTENSION */ + YYSYMBOL_EXTENSIONS = 157, /* EXTENSIONS */ + YYSYMBOL_EXTERNAL = 158, /* EXTERNAL */ + YYSYMBOL_EXTRACT = 159, /* EXTRACT */ + YYSYMBOL_FALSE_P = 160, /* FALSE_P */ + YYSYMBOL_FAMILY = 161, /* FAMILY */ + YYSYMBOL_FETCH = 162, /* FETCH */ + YYSYMBOL_FILTER = 163, /* FILTER */ + YYSYMBOL_FIRST_P = 164, /* FIRST_P */ + YYSYMBOL_FLOAT_P = 165, /* FLOAT_P */ + YYSYMBOL_FOLLOWING = 166, /* FOLLOWING */ + YYSYMBOL_FOR = 167, /* FOR */ + YYSYMBOL_FORCE = 168, /* FORCE */ + YYSYMBOL_FOREIGN = 169, /* FOREIGN */ + YYSYMBOL_FORWARD = 170, /* FORWARD */ + YYSYMBOL_FREEZE = 171, /* FREEZE */ + YYSYMBOL_FROM = 172, /* FROM */ + YYSYMBOL_FULL = 173, /* FULL */ + YYSYMBOL_FUNCTION = 174, /* FUNCTION */ + YYSYMBOL_FUNCTIONS = 175, /* FUNCTIONS */ + YYSYMBOL_GENERATED = 176, /* GENERATED */ + YYSYMBOL_GLOB = 177, /* GLOB */ + YYSYMBOL_GLOBAL = 178, /* GLOBAL */ + YYSYMBOL_GRANT = 179, /* GRANT */ + YYSYMBOL_GRANTED = 180, /* GRANTED */ + YYSYMBOL_GROUP_P = 181, /* GROUP_P */ + YYSYMBOL_GROUPING = 182, /* GROUPING */ + YYSYMBOL_GROUPING_ID = 183, /* GROUPING_ID */ + YYSYMBOL_GROUPS = 184, /* GROUPS */ + YYSYMBOL_HANDLER = 185, /* HANDLER */ + YYSYMBOL_HAVING = 186, /* HAVING */ + YYSYMBOL_HEADER_P = 187, /* HEADER_P */ + YYSYMBOL_HOLD = 188, /* HOLD */ + YYSYMBOL_HOUR_P = 189, /* HOUR_P */ + YYSYMBOL_HOURS_P = 190, /* HOURS_P */ + YYSYMBOL_IDENTITY_P = 191, /* IDENTITY_P */ + YYSYMBOL_IF_P = 192, /* IF_P */ + YYSYMBOL_IGNORE_P = 193, /* IGNORE_P */ + YYSYMBOL_ILIKE = 194, /* ILIKE */ + YYSYMBOL_IMMEDIATE = 195, /* IMMEDIATE */ + YYSYMBOL_IMMUTABLE = 196, /* IMMUTABLE */ + YYSYMBOL_IMPLICIT_P = 197, /* IMPLICIT_P */ + YYSYMBOL_IMPORT_P = 198, /* IMPORT_P */ + YYSYMBOL_IN_P = 199, /* IN_P */ + YYSYMBOL_INCLUDE_P = 200, /* INCLUDE_P */ + YYSYMBOL_INCLUDING = 201, /* INCLUDING */ + YYSYMBOL_INCREMENT = 202, /* INCREMENT */ + YYSYMBOL_INDEX = 203, /* INDEX */ + YYSYMBOL_INDEXES = 204, /* INDEXES */ + YYSYMBOL_INHERIT = 205, /* INHERIT */ + YYSYMBOL_INHERITS = 206, /* INHERITS */ + YYSYMBOL_INITIALLY = 207, /* INITIALLY */ + YYSYMBOL_INLINE_P = 208, /* INLINE_P */ + YYSYMBOL_INNER_P = 209, /* INNER_P */ + YYSYMBOL_INOUT = 210, /* INOUT */ + YYSYMBOL_INPUT_P = 211, /* INPUT_P */ + YYSYMBOL_INSENSITIVE = 212, /* INSENSITIVE */ + YYSYMBOL_INSERT = 213, /* INSERT */ + YYSYMBOL_INSTALL = 214, /* INSTALL */ + YYSYMBOL_INSTEAD = 215, /* INSTEAD */ + YYSYMBOL_INT_P = 216, /* INT_P */ + YYSYMBOL_INTEGER = 217, /* INTEGER */ + YYSYMBOL_INTERSECT = 218, /* INTERSECT */ + YYSYMBOL_INTERVAL = 219, /* INTERVAL */ + YYSYMBOL_INTO = 220, /* INTO */ + YYSYMBOL_INVOKER = 221, /* INVOKER */ + YYSYMBOL_IS = 222, /* IS */ + YYSYMBOL_ISNULL = 223, /* ISNULL */ + YYSYMBOL_ISOLATION = 224, /* ISOLATION */ + YYSYMBOL_JOIN = 225, /* JOIN */ + YYSYMBOL_JSON = 226, /* JSON */ + YYSYMBOL_KEY = 227, /* KEY */ + YYSYMBOL_LABEL = 228, /* LABEL */ + YYSYMBOL_LANGUAGE = 229, /* LANGUAGE */ + YYSYMBOL_LARGE_P = 230, /* LARGE_P */ + YYSYMBOL_LAST_P = 231, /* LAST_P */ + YYSYMBOL_LATERAL_P = 232, /* LATERAL_P */ + YYSYMBOL_LEADING = 233, /* LEADING */ + YYSYMBOL_LEAKPROOF = 234, /* LEAKPROOF */ + YYSYMBOL_LEFT = 235, /* LEFT */ + YYSYMBOL_LEVEL = 236, /* LEVEL */ + YYSYMBOL_LIKE = 237, /* LIKE */ + YYSYMBOL_LIMIT = 238, /* LIMIT */ + YYSYMBOL_LISTEN = 239, /* LISTEN */ + YYSYMBOL_LOAD = 240, /* LOAD */ + YYSYMBOL_LOCAL = 241, /* LOCAL */ + YYSYMBOL_LOCATION = 242, /* LOCATION */ + YYSYMBOL_LOCK_P = 243, /* LOCK_P */ + YYSYMBOL_LOCKED = 244, /* LOCKED */ + YYSYMBOL_LOGGED = 245, /* LOGGED */ + YYSYMBOL_MACRO = 246, /* MACRO */ + YYSYMBOL_MAP = 247, /* MAP */ + YYSYMBOL_MAPPING = 248, /* MAPPING */ + YYSYMBOL_MATCH = 249, /* MATCH */ + YYSYMBOL_MATERIALIZED = 250, /* MATERIALIZED */ + YYSYMBOL_MAXVALUE = 251, /* MAXVALUE */ + YYSYMBOL_METHOD = 252, /* METHOD */ + YYSYMBOL_MICROSECOND_P = 253, /* MICROSECOND_P */ + YYSYMBOL_MICROSECONDS_P = 254, /* MICROSECONDS_P */ + YYSYMBOL_MILLENNIA_P = 255, /* MILLENNIA_P */ + YYSYMBOL_MILLENNIUM_P = 256, /* MILLENNIUM_P */ + YYSYMBOL_MILLISECOND_P = 257, /* MILLISECOND_P */ + YYSYMBOL_MILLISECONDS_P = 258, /* MILLISECONDS_P */ + YYSYMBOL_MINUTE_P = 259, /* MINUTE_P */ + YYSYMBOL_MINUTES_P = 260, /* MINUTES_P */ + YYSYMBOL_MINVALUE = 261, /* MINVALUE */ + YYSYMBOL_MODE = 262, /* MODE */ + YYSYMBOL_MONTH_P = 263, /* MONTH_P */ + YYSYMBOL_MONTHS_P = 264, /* MONTHS_P */ + YYSYMBOL_MOVE = 265, /* MOVE */ + YYSYMBOL_NAME_P = 266, /* NAME_P */ + YYSYMBOL_NAMES = 267, /* NAMES */ + YYSYMBOL_NATIONAL = 268, /* NATIONAL */ + YYSYMBOL_NATURAL = 269, /* NATURAL */ + YYSYMBOL_NCHAR = 270, /* NCHAR */ + YYSYMBOL_NEW = 271, /* NEW */ + YYSYMBOL_NEXT = 272, /* NEXT */ + YYSYMBOL_NO = 273, /* NO */ + YYSYMBOL_NONE = 274, /* NONE */ + YYSYMBOL_NOT = 275, /* NOT */ + YYSYMBOL_NOTHING = 276, /* NOTHING */ + YYSYMBOL_NOTIFY = 277, /* NOTIFY */ + YYSYMBOL_NOTNULL = 278, /* NOTNULL */ + YYSYMBOL_NOWAIT = 279, /* NOWAIT */ + YYSYMBOL_NULL_P = 280, /* NULL_P */ + YYSYMBOL_NULLIF = 281, /* NULLIF */ + YYSYMBOL_NULLS_P = 282, /* NULLS_P */ + YYSYMBOL_NUMERIC = 283, /* NUMERIC */ + YYSYMBOL_OBJECT_P = 284, /* OBJECT_P */ + YYSYMBOL_OF = 285, /* OF */ + YYSYMBOL_OFF = 286, /* OFF */ + YYSYMBOL_OFFSET = 287, /* OFFSET */ + YYSYMBOL_OIDS = 288, /* OIDS */ + YYSYMBOL_OLD = 289, /* OLD */ + YYSYMBOL_ON = 290, /* ON */ + YYSYMBOL_ONLY = 291, /* ONLY */ + YYSYMBOL_OPERATOR = 292, /* OPERATOR */ + YYSYMBOL_OPTION = 293, /* OPTION */ + YYSYMBOL_OPTIONS = 294, /* OPTIONS */ + YYSYMBOL_OR = 295, /* OR */ + YYSYMBOL_ORDER = 296, /* ORDER */ + YYSYMBOL_ORDINALITY = 297, /* ORDINALITY */ + YYSYMBOL_OTHERS = 298, /* OTHERS */ + YYSYMBOL_OUT_P = 299, /* OUT_P */ + YYSYMBOL_OUTER_P = 300, /* OUTER_P */ + YYSYMBOL_OVER = 301, /* OVER */ + YYSYMBOL_OVERLAPS = 302, /* OVERLAPS */ + YYSYMBOL_OVERLAY = 303, /* OVERLAY */ + YYSYMBOL_OVERRIDING = 304, /* OVERRIDING */ + YYSYMBOL_OWNED = 305, /* OWNED */ + YYSYMBOL_OWNER = 306, /* OWNER */ + YYSYMBOL_PARALLEL = 307, /* PARALLEL */ + YYSYMBOL_PARSER = 308, /* PARSER */ + YYSYMBOL_PARTIAL = 309, /* PARTIAL */ + YYSYMBOL_PARTITION = 310, /* PARTITION */ + YYSYMBOL_PASSING = 311, /* PASSING */ + YYSYMBOL_PASSWORD = 312, /* PASSWORD */ + YYSYMBOL_PERCENT = 313, /* PERCENT */ + YYSYMBOL_PERSISTENT = 314, /* PERSISTENT */ + YYSYMBOL_PIVOT = 315, /* PIVOT */ + YYSYMBOL_PIVOT_LONGER = 316, /* PIVOT_LONGER */ + YYSYMBOL_PIVOT_WIDER = 317, /* PIVOT_WIDER */ + YYSYMBOL_PLACING = 318, /* PLACING */ + YYSYMBOL_PLANS = 319, /* PLANS */ + YYSYMBOL_POLICY = 320, /* POLICY */ + YYSYMBOL_POSITION = 321, /* POSITION */ + YYSYMBOL_POSITIONAL = 322, /* POSITIONAL */ + YYSYMBOL_PRAGMA_P = 323, /* PRAGMA_P */ + YYSYMBOL_PRECEDING = 324, /* PRECEDING */ + YYSYMBOL_PRECISION = 325, /* PRECISION */ + YYSYMBOL_PREPARE = 326, /* PREPARE */ + YYSYMBOL_PREPARED = 327, /* PREPARED */ + YYSYMBOL_PRESERVE = 328, /* PRESERVE */ + YYSYMBOL_PRIMARY = 329, /* PRIMARY */ + YYSYMBOL_PRIOR = 330, /* PRIOR */ + YYSYMBOL_PRIVILEGES = 331, /* PRIVILEGES */ + YYSYMBOL_PROCEDURAL = 332, /* PROCEDURAL */ + YYSYMBOL_PROCEDURE = 333, /* PROCEDURE */ + YYSYMBOL_PROGRAM = 334, /* PROGRAM */ + YYSYMBOL_PUBLICATION = 335, /* PUBLICATION */ + YYSYMBOL_QUALIFY = 336, /* QUALIFY */ + YYSYMBOL_QUARTER_P = 337, /* QUARTER_P */ + YYSYMBOL_QUARTERS_P = 338, /* QUARTERS_P */ + YYSYMBOL_QUOTE = 339, /* QUOTE */ + YYSYMBOL_RANGE = 340, /* RANGE */ + YYSYMBOL_READ_P = 341, /* READ_P */ + YYSYMBOL_REAL = 342, /* REAL */ + YYSYMBOL_REASSIGN = 343, /* REASSIGN */ + YYSYMBOL_RECHECK = 344, /* RECHECK */ + YYSYMBOL_RECURSIVE = 345, /* RECURSIVE */ + YYSYMBOL_REF = 346, /* REF */ + YYSYMBOL_REFERENCES = 347, /* REFERENCES */ + YYSYMBOL_REFERENCING = 348, /* REFERENCING */ + YYSYMBOL_REFRESH = 349, /* REFRESH */ + YYSYMBOL_REINDEX = 350, /* REINDEX */ + YYSYMBOL_RELATIVE_P = 351, /* RELATIVE_P */ + YYSYMBOL_RELEASE = 352, /* RELEASE */ + YYSYMBOL_RENAME = 353, /* RENAME */ + YYSYMBOL_REPEATABLE = 354, /* REPEATABLE */ + YYSYMBOL_REPLACE = 355, /* REPLACE */ + YYSYMBOL_REPLICA = 356, /* REPLICA */ + YYSYMBOL_RESET = 357, /* RESET */ + YYSYMBOL_RESPECT_P = 358, /* RESPECT_P */ + YYSYMBOL_RESTART = 359, /* RESTART */ + YYSYMBOL_RESTRICT = 360, /* RESTRICT */ + YYSYMBOL_RETURNING = 361, /* RETURNING */ + YYSYMBOL_RETURNS = 362, /* RETURNS */ + YYSYMBOL_REVOKE = 363, /* REVOKE */ + YYSYMBOL_RIGHT = 364, /* RIGHT */ + YYSYMBOL_ROLE = 365, /* ROLE */ + YYSYMBOL_ROLLBACK = 366, /* ROLLBACK */ + YYSYMBOL_ROLLUP = 367, /* ROLLUP */ + YYSYMBOL_ROW = 368, /* ROW */ + YYSYMBOL_ROWS = 369, /* ROWS */ + YYSYMBOL_RULE = 370, /* RULE */ + YYSYMBOL_SAMPLE = 371, /* SAMPLE */ + YYSYMBOL_SAVEPOINT = 372, /* SAVEPOINT */ + YYSYMBOL_SCHEMA = 373, /* SCHEMA */ + YYSYMBOL_SCHEMAS = 374, /* SCHEMAS */ + YYSYMBOL_SCOPE = 375, /* SCOPE */ + YYSYMBOL_SCROLL = 376, /* SCROLL */ + YYSYMBOL_SEARCH = 377, /* SEARCH */ + YYSYMBOL_SECOND_P = 378, /* SECOND_P */ + YYSYMBOL_SECONDS_P = 379, /* SECONDS_P */ + YYSYMBOL_SECRET = 380, /* SECRET */ + YYSYMBOL_SECURITY = 381, /* SECURITY */ + YYSYMBOL_SELECT = 382, /* SELECT */ + YYSYMBOL_SEMI = 383, /* SEMI */ + YYSYMBOL_SEQUENCE = 384, /* SEQUENCE */ + YYSYMBOL_SEQUENCES = 385, /* SEQUENCES */ + YYSYMBOL_SERIALIZABLE = 386, /* SERIALIZABLE */ + YYSYMBOL_SERVER = 387, /* SERVER */ + YYSYMBOL_SESSION = 388, /* SESSION */ + YYSYMBOL_SET = 389, /* SET */ + YYSYMBOL_SETOF = 390, /* SETOF */ + YYSYMBOL_SETS = 391, /* SETS */ + YYSYMBOL_SHARE = 392, /* SHARE */ + YYSYMBOL_SHOW = 393, /* SHOW */ + YYSYMBOL_SIMILAR = 394, /* SIMILAR */ + YYSYMBOL_SIMPLE = 395, /* SIMPLE */ + YYSYMBOL_SKIP = 396, /* SKIP */ + YYSYMBOL_SMALLINT = 397, /* SMALLINT */ + YYSYMBOL_SNAPSHOT = 398, /* SNAPSHOT */ + YYSYMBOL_SOME = 399, /* SOME */ + YYSYMBOL_SQL_P = 400, /* SQL_P */ + YYSYMBOL_STABLE = 401, /* STABLE */ + YYSYMBOL_STANDALONE_P = 402, /* STANDALONE_P */ + YYSYMBOL_START = 403, /* START */ + YYSYMBOL_STATEMENT = 404, /* STATEMENT */ + YYSYMBOL_STATISTICS = 405, /* STATISTICS */ + YYSYMBOL_STDIN = 406, /* STDIN */ + YYSYMBOL_STDOUT = 407, /* STDOUT */ + YYSYMBOL_STORAGE = 408, /* STORAGE */ + YYSYMBOL_STORED = 409, /* STORED */ + YYSYMBOL_STRICT_P = 410, /* STRICT_P */ + YYSYMBOL_STRIP_P = 411, /* STRIP_P */ + YYSYMBOL_STRUCT = 412, /* STRUCT */ + YYSYMBOL_SUBSCRIPTION = 413, /* SUBSCRIPTION */ + YYSYMBOL_SUBSTRING = 414, /* SUBSTRING */ + YYSYMBOL_SUMMARIZE = 415, /* SUMMARIZE */ + YYSYMBOL_SYMMETRIC = 416, /* SYMMETRIC */ + YYSYMBOL_SYSID = 417, /* SYSID */ + YYSYMBOL_SYSTEM_P = 418, /* SYSTEM_P */ + YYSYMBOL_TABLE = 419, /* TABLE */ + YYSYMBOL_TABLES = 420, /* TABLES */ + YYSYMBOL_TABLESAMPLE = 421, /* TABLESAMPLE */ + YYSYMBOL_TABLESPACE = 422, /* TABLESPACE */ + YYSYMBOL_TEMP = 423, /* TEMP */ + YYSYMBOL_TEMPLATE = 424, /* TEMPLATE */ + YYSYMBOL_TEMPORARY = 425, /* TEMPORARY */ + YYSYMBOL_TEXT_P = 426, /* TEXT_P */ + YYSYMBOL_THEN = 427, /* THEN */ + YYSYMBOL_TIES = 428, /* TIES */ + YYSYMBOL_TIME = 429, /* TIME */ + YYSYMBOL_TIMESTAMP = 430, /* TIMESTAMP */ + YYSYMBOL_TO = 431, /* TO */ + YYSYMBOL_TRAILING = 432, /* TRAILING */ + YYSYMBOL_TRANSACTION = 433, /* TRANSACTION */ + YYSYMBOL_TRANSFORM = 434, /* TRANSFORM */ + YYSYMBOL_TREAT = 435, /* TREAT */ + YYSYMBOL_TRIGGER = 436, /* TRIGGER */ + YYSYMBOL_TRIM = 437, /* TRIM */ + YYSYMBOL_TRUE_P = 438, /* TRUE_P */ + YYSYMBOL_TRUNCATE = 439, /* TRUNCATE */ + YYSYMBOL_TRUSTED = 440, /* TRUSTED */ + YYSYMBOL_TRY_CAST = 441, /* TRY_CAST */ + YYSYMBOL_TYPE_P = 442, /* TYPE_P */ + YYSYMBOL_TYPES_P = 443, /* TYPES_P */ + YYSYMBOL_UNBOUNDED = 444, /* UNBOUNDED */ + YYSYMBOL_UNCOMMITTED = 445, /* UNCOMMITTED */ + YYSYMBOL_UNENCRYPTED = 446, /* UNENCRYPTED */ + YYSYMBOL_UNION = 447, /* UNION */ + YYSYMBOL_UNIQUE = 448, /* UNIQUE */ + YYSYMBOL_UNKNOWN = 449, /* UNKNOWN */ + YYSYMBOL_UNLISTEN = 450, /* UNLISTEN */ + YYSYMBOL_UNLOGGED = 451, /* UNLOGGED */ + YYSYMBOL_UNPIVOT = 452, /* UNPIVOT */ + YYSYMBOL_UNTIL = 453, /* UNTIL */ + YYSYMBOL_UPDATE = 454, /* UPDATE */ + YYSYMBOL_USE_P = 455, /* USE_P */ + YYSYMBOL_USER = 456, /* USER */ + YYSYMBOL_USING = 457, /* USING */ + YYSYMBOL_VACUUM = 458, /* VACUUM */ + YYSYMBOL_VALID = 459, /* VALID */ + YYSYMBOL_VALIDATE = 460, /* VALIDATE */ + YYSYMBOL_VALIDATOR = 461, /* VALIDATOR */ + YYSYMBOL_VALUE_P = 462, /* VALUE_P */ + YYSYMBOL_VALUES = 463, /* VALUES */ + YYSYMBOL_VARCHAR = 464, /* VARCHAR */ + YYSYMBOL_VARIADIC = 465, /* VARIADIC */ + YYSYMBOL_VARYING = 466, /* VARYING */ + YYSYMBOL_VERBOSE = 467, /* VERBOSE */ + YYSYMBOL_VERSION_P = 468, /* VERSION_P */ + YYSYMBOL_VIEW = 469, /* VIEW */ + YYSYMBOL_VIEWS = 470, /* VIEWS */ + YYSYMBOL_VIRTUAL = 471, /* VIRTUAL */ + YYSYMBOL_VOLATILE = 472, /* VOLATILE */ + YYSYMBOL_WEEK_P = 473, /* WEEK_P */ + YYSYMBOL_WEEKS_P = 474, /* WEEKS_P */ + YYSYMBOL_WHEN = 475, /* WHEN */ + YYSYMBOL_WHERE = 476, /* WHERE */ + YYSYMBOL_WHITESPACE_P = 477, /* WHITESPACE_P */ + YYSYMBOL_WINDOW = 478, /* WINDOW */ + YYSYMBOL_WITH = 479, /* WITH */ + YYSYMBOL_WITHIN = 480, /* WITHIN */ + YYSYMBOL_WITHOUT = 481, /* WITHOUT */ + YYSYMBOL_WORK = 482, /* WORK */ + YYSYMBOL_WRAPPER = 483, /* WRAPPER */ + YYSYMBOL_WRITE_P = 484, /* WRITE_P */ + YYSYMBOL_XML_P = 485, /* XML_P */ + YYSYMBOL_XMLATTRIBUTES = 486, /* XMLATTRIBUTES */ + YYSYMBOL_XMLCONCAT = 487, /* XMLCONCAT */ + YYSYMBOL_XMLELEMENT = 488, /* XMLELEMENT */ + YYSYMBOL_XMLEXISTS = 489, /* XMLEXISTS */ + YYSYMBOL_XMLFOREST = 490, /* XMLFOREST */ + YYSYMBOL_XMLNAMESPACES = 491, /* XMLNAMESPACES */ + YYSYMBOL_XMLPARSE = 492, /* XMLPARSE */ + YYSYMBOL_XMLPI = 493, /* XMLPI */ + YYSYMBOL_XMLROOT = 494, /* XMLROOT */ + YYSYMBOL_XMLSERIALIZE = 495, /* XMLSERIALIZE */ + YYSYMBOL_XMLTABLE = 496, /* XMLTABLE */ + YYSYMBOL_YEAR_P = 497, /* YEAR_P */ + YYSYMBOL_YEARS_P = 498, /* YEARS_P */ + YYSYMBOL_YES_P = 499, /* YES_P */ + YYSYMBOL_ZONE = 500, /* ZONE */ + YYSYMBOL_NOT_LA = 501, /* NOT_LA */ + YYSYMBOL_NULLS_LA = 502, /* NULLS_LA */ + YYSYMBOL_WITH_LA = 503, /* WITH_LA */ + YYSYMBOL_504_ = 504, /* '<' */ + YYSYMBOL_505_ = 505, /* '>' */ + YYSYMBOL_506_ = 506, /* '=' */ + YYSYMBOL_POSTFIXOP = 507, /* POSTFIXOP */ + YYSYMBOL_508_ = 508, /* '+' */ + YYSYMBOL_509_ = 509, /* '-' */ + YYSYMBOL_510_ = 510, /* '*' */ + YYSYMBOL_511_ = 511, /* '/' */ + YYSYMBOL_512_ = 512, /* '%' */ + YYSYMBOL_513_ = 513, /* '^' */ + YYSYMBOL_UMINUS = 514, /* UMINUS */ + YYSYMBOL_515_ = 515, /* '[' */ + YYSYMBOL_516_ = 516, /* ']' */ + YYSYMBOL_517_ = 517, /* '(' */ + YYSYMBOL_518_ = 518, /* ')' */ + YYSYMBOL_519_ = 519, /* '.' */ + YYSYMBOL_520_ = 520, /* ';' */ + YYSYMBOL_521_ = 521, /* ',' */ + YYSYMBOL_522_ = 522, /* '?' */ + YYSYMBOL_523_ = 523, /* '{' */ + YYSYMBOL_524_ = 524, /* '}' */ + YYSYMBOL_525_ = 525, /* '#' */ + YYSYMBOL_526_ = 526, /* '$' */ + YYSYMBOL_527_ = 527, /* ':' */ + YYSYMBOL_YYACCEPT = 528, /* $accept */ + YYSYMBOL_stmtblock = 529, /* stmtblock */ + YYSYMBOL_stmtmulti = 530, /* stmtmulti */ + YYSYMBOL_stmt = 531, /* stmt */ + YYSYMBOL_AlterObjectSchemaStmt = 532, /* AlterObjectSchemaStmt */ + YYSYMBOL_AlterSeqStmt = 533, /* AlterSeqStmt */ + YYSYMBOL_SeqOptList = 534, /* SeqOptList */ + YYSYMBOL_opt_with = 535, /* opt_with */ + YYSYMBOL_NumericOnly = 536, /* NumericOnly */ + YYSYMBOL_SeqOptElem = 537, /* SeqOptElem */ + YYSYMBOL_opt_by = 538, /* opt_by */ + YYSYMBOL_SignedIconst = 539, /* SignedIconst */ + YYSYMBOL_AlterTableStmt = 540, /* AlterTableStmt */ + YYSYMBOL_alter_identity_column_option_list = 541, /* alter_identity_column_option_list */ + YYSYMBOL_alter_column_default = 542, /* alter_column_default */ + YYSYMBOL_alter_identity_column_option = 543, /* alter_identity_column_option */ + YYSYMBOL_alter_generic_option_list = 544, /* alter_generic_option_list */ + YYSYMBOL_alter_table_cmd = 545, /* alter_table_cmd */ + YYSYMBOL_alter_using = 546, /* alter_using */ + YYSYMBOL_alter_generic_option_elem = 547, /* alter_generic_option_elem */ + YYSYMBOL_alter_table_cmds = 548, /* alter_table_cmds */ + YYSYMBOL_alter_generic_options = 549, /* alter_generic_options */ + YYSYMBOL_opt_set_data = 550, /* opt_set_data */ + YYSYMBOL_AnalyzeStmt = 551, /* AnalyzeStmt */ + YYSYMBOL_AttachStmt = 552, /* AttachStmt */ + YYSYMBOL_DetachStmt = 553, /* DetachStmt */ + YYSYMBOL_opt_database = 554, /* opt_database */ + YYSYMBOL_opt_database_alias = 555, /* opt_database_alias */ + YYSYMBOL_CallStmt = 556, /* CallStmt */ + YYSYMBOL_CheckPointStmt = 557, /* CheckPointStmt */ + YYSYMBOL_opt_col_id = 558, /* opt_col_id */ + YYSYMBOL_CommentOnStmt = 559, /* CommentOnStmt */ + YYSYMBOL_comment_value = 560, /* comment_value */ + YYSYMBOL_comment_on_type_any_name = 561, /* comment_on_type_any_name */ + YYSYMBOL_qualified_name = 562, /* qualified_name */ + YYSYMBOL_ColId = 563, /* ColId */ + YYSYMBOL_ColIdOrString = 564, /* ColIdOrString */ + YYSYMBOL_Sconst = 565, /* Sconst */ + YYSYMBOL_indirection = 566, /* indirection */ + YYSYMBOL_indirection_el = 567, /* indirection_el */ + YYSYMBOL_attr_name = 568, /* attr_name */ + YYSYMBOL_ColLabel = 569, /* ColLabel */ + YYSYMBOL_CopyStmt = 570, /* CopyStmt */ + YYSYMBOL_copy_database_flag = 571, /* copy_database_flag */ + YYSYMBOL_copy_from = 572, /* copy_from */ + YYSYMBOL_copy_delimiter = 573, /* copy_delimiter */ + YYSYMBOL_copy_generic_opt_arg_list = 574, /* copy_generic_opt_arg_list */ + YYSYMBOL_opt_using = 575, /* opt_using */ + YYSYMBOL_opt_as = 576, /* opt_as */ + YYSYMBOL_opt_program = 577, /* opt_program */ + YYSYMBOL_copy_options = 578, /* copy_options */ + YYSYMBOL_copy_generic_opt_arg = 579, /* copy_generic_opt_arg */ + YYSYMBOL_copy_generic_opt_elem = 580, /* copy_generic_opt_elem */ + YYSYMBOL_opt_oids = 581, /* opt_oids */ + YYSYMBOL_copy_opt_list = 582, /* copy_opt_list */ + YYSYMBOL_opt_binary = 583, /* opt_binary */ + YYSYMBOL_copy_opt_item = 584, /* copy_opt_item */ + YYSYMBOL_copy_generic_opt_arg_list_item = 585, /* copy_generic_opt_arg_list_item */ + YYSYMBOL_copy_file_name = 586, /* copy_file_name */ + YYSYMBOL_copy_generic_opt_list = 587, /* copy_generic_opt_list */ + YYSYMBOL_CreateStmt = 588, /* CreateStmt */ + YYSYMBOL_ConstraintAttributeSpec = 589, /* ConstraintAttributeSpec */ + YYSYMBOL_def_arg = 590, /* def_arg */ + YYSYMBOL_OptParenthesizedSeqOptList = 591, /* OptParenthesizedSeqOptList */ + YYSYMBOL_generic_option_arg = 592, /* generic_option_arg */ + YYSYMBOL_key_action = 593, /* key_action */ + YYSYMBOL_ColConstraint = 594, /* ColConstraint */ + YYSYMBOL_ColConstraintElem = 595, /* ColConstraintElem */ + YYSYMBOL_GeneratedColumnType = 596, /* GeneratedColumnType */ + YYSYMBOL_opt_GeneratedColumnType = 597, /* opt_GeneratedColumnType */ + YYSYMBOL_GeneratedConstraintElem = 598, /* GeneratedConstraintElem */ + YYSYMBOL_generic_option_elem = 599, /* generic_option_elem */ + YYSYMBOL_key_update = 600, /* key_update */ + YYSYMBOL_key_actions = 601, /* key_actions */ + YYSYMBOL_OnCommitOption = 602, /* OnCommitOption */ + YYSYMBOL_reloptions = 603, /* reloptions */ + YYSYMBOL_opt_no_inherit = 604, /* opt_no_inherit */ + YYSYMBOL_TableConstraint = 605, /* TableConstraint */ + YYSYMBOL_TableLikeOption = 606, /* TableLikeOption */ + YYSYMBOL_reloption_list = 607, /* reloption_list */ + YYSYMBOL_ExistingIndex = 608, /* ExistingIndex */ + YYSYMBOL_ConstraintAttr = 609, /* ConstraintAttr */ + YYSYMBOL_OptWith = 610, /* OptWith */ + YYSYMBOL_definition = 611, /* definition */ + YYSYMBOL_TableLikeOptionList = 612, /* TableLikeOptionList */ + YYSYMBOL_generic_option_name = 613, /* generic_option_name */ + YYSYMBOL_ConstraintAttributeElem = 614, /* ConstraintAttributeElem */ + YYSYMBOL_columnDef = 615, /* columnDef */ + YYSYMBOL_def_list = 616, /* def_list */ + YYSYMBOL_index_name = 617, /* index_name */ + YYSYMBOL_TableElement = 618, /* TableElement */ + YYSYMBOL_def_elem = 619, /* def_elem */ + YYSYMBOL_opt_definition = 620, /* opt_definition */ + YYSYMBOL_OptTableElementList = 621, /* OptTableElementList */ + YYSYMBOL_columnElem = 622, /* columnElem */ + YYSYMBOL_opt_column_list = 623, /* opt_column_list */ + YYSYMBOL_ColQualList = 624, /* ColQualList */ + YYSYMBOL_key_delete = 625, /* key_delete */ + YYSYMBOL_reloption_elem = 626, /* reloption_elem */ + YYSYMBOL_columnList = 627, /* columnList */ + YYSYMBOL_columnList_opt_comma = 628, /* columnList_opt_comma */ + YYSYMBOL_func_type = 629, /* func_type */ + YYSYMBOL_ConstraintElem = 630, /* ConstraintElem */ + YYSYMBOL_TableElementList = 631, /* TableElementList */ + YYSYMBOL_key_match = 632, /* key_match */ + YYSYMBOL_TableLikeClause = 633, /* TableLikeClause */ + YYSYMBOL_OptTemp = 634, /* OptTemp */ + YYSYMBOL_generated_when = 635, /* generated_when */ + YYSYMBOL_CreateAsStmt = 636, /* CreateAsStmt */ + YYSYMBOL_opt_with_data = 637, /* opt_with_data */ + YYSYMBOL_create_as_target = 638, /* create_as_target */ + YYSYMBOL_unreserved_keyword = 639, /* unreserved_keyword */ + YYSYMBOL_col_name_keyword = 640, /* col_name_keyword */ + YYSYMBOL_func_name_keyword = 641, /* func_name_keyword */ + YYSYMBOL_type_name_keyword = 642, /* type_name_keyword */ + YYSYMBOL_other_keyword = 643, /* other_keyword */ + YYSYMBOL_type_func_name_keyword = 644, /* type_func_name_keyword */ + YYSYMBOL_reserved_keyword = 645, /* reserved_keyword */ + YYSYMBOL_CreateFunctionStmt = 646, /* CreateFunctionStmt */ + YYSYMBOL_macro_alias = 647, /* macro_alias */ + YYSYMBOL_param_list = 648, /* param_list */ + YYSYMBOL_CreateSchemaStmt = 649, /* CreateSchemaStmt */ + YYSYMBOL_OptSchemaEltList = 650, /* OptSchemaEltList */ + YYSYMBOL_schema_stmt = 651, /* schema_stmt */ + YYSYMBOL_CreateSecretStmt = 652, /* CreateSecretStmt */ + YYSYMBOL_opt_secret_name = 653, /* opt_secret_name */ + YYSYMBOL_opt_persist = 654, /* opt_persist */ + YYSYMBOL_opt_storage_specifier = 655, /* opt_storage_specifier */ + YYSYMBOL_CreateSeqStmt = 656, /* CreateSeqStmt */ + YYSYMBOL_OptSeqOptList = 657, /* OptSeqOptList */ + YYSYMBOL_CreateTypeStmt = 658, /* CreateTypeStmt */ + YYSYMBOL_opt_enum_val_list = 659, /* opt_enum_val_list */ + YYSYMBOL_enum_val_list = 660, /* enum_val_list */ + YYSYMBOL_DeallocateStmt = 661, /* DeallocateStmt */ + YYSYMBOL_DeleteStmt = 662, /* DeleteStmt */ + YYSYMBOL_relation_expr_opt_alias = 663, /* relation_expr_opt_alias */ + YYSYMBOL_where_or_current_clause = 664, /* where_or_current_clause */ + YYSYMBOL_using_clause = 665, /* using_clause */ + YYSYMBOL_DropStmt = 666, /* DropStmt */ + YYSYMBOL_drop_type_any_name = 667, /* drop_type_any_name */ + YYSYMBOL_drop_type_name = 668, /* drop_type_name */ + YYSYMBOL_any_name_list = 669, /* any_name_list */ + YYSYMBOL_opt_drop_behavior = 670, /* opt_drop_behavior */ + YYSYMBOL_drop_type_name_on_any_name = 671, /* drop_type_name_on_any_name */ + YYSYMBOL_DropSecretStmt = 672, /* DropSecretStmt */ + YYSYMBOL_opt_storage_drop_specifier = 673, /* opt_storage_drop_specifier */ + YYSYMBOL_ExecuteStmt = 674, /* ExecuteStmt */ + YYSYMBOL_execute_param_expr = 675, /* execute_param_expr */ + YYSYMBOL_execute_param_list = 676, /* execute_param_list */ + YYSYMBOL_execute_param_clause = 677, /* execute_param_clause */ + YYSYMBOL_ExplainStmt = 678, /* ExplainStmt */ + YYSYMBOL_opt_verbose = 679, /* opt_verbose */ + YYSYMBOL_explain_option_arg = 680, /* explain_option_arg */ + YYSYMBOL_ExplainableStmt = 681, /* ExplainableStmt */ + YYSYMBOL_NonReservedWord = 682, /* NonReservedWord */ + YYSYMBOL_NonReservedWord_or_Sconst = 683, /* NonReservedWord_or_Sconst */ + YYSYMBOL_explain_option_list = 684, /* explain_option_list */ + YYSYMBOL_analyze_keyword = 685, /* analyze_keyword */ + YYSYMBOL_opt_boolean_or_string = 686, /* opt_boolean_or_string */ + YYSYMBOL_explain_option_elem = 687, /* explain_option_elem */ + YYSYMBOL_explain_option_name = 688, /* explain_option_name */ + YYSYMBOL_ExportStmt = 689, /* ExportStmt */ + YYSYMBOL_ImportStmt = 690, /* ImportStmt */ + YYSYMBOL_IndexStmt = 691, /* IndexStmt */ + YYSYMBOL_access_method = 692, /* access_method */ + YYSYMBOL_access_method_clause = 693, /* access_method_clause */ + YYSYMBOL_opt_concurrently = 694, /* opt_concurrently */ + YYSYMBOL_opt_index_name = 695, /* opt_index_name */ + YYSYMBOL_opt_reloptions = 696, /* opt_reloptions */ + YYSYMBOL_opt_unique = 697, /* opt_unique */ + YYSYMBOL_InsertStmt = 698, /* InsertStmt */ + YYSYMBOL_insert_rest = 699, /* insert_rest */ + YYSYMBOL_insert_target = 700, /* insert_target */ + YYSYMBOL_opt_by_name_or_position = 701, /* opt_by_name_or_position */ + YYSYMBOL_opt_conf_expr = 702, /* opt_conf_expr */ + YYSYMBOL_opt_with_clause = 703, /* opt_with_clause */ + YYSYMBOL_insert_column_item = 704, /* insert_column_item */ + YYSYMBOL_set_clause = 705, /* set_clause */ + YYSYMBOL_opt_or_action = 706, /* opt_or_action */ + YYSYMBOL_opt_on_conflict = 707, /* opt_on_conflict */ + YYSYMBOL_index_elem = 708, /* index_elem */ + YYSYMBOL_returning_clause = 709, /* returning_clause */ + YYSYMBOL_override_kind = 710, /* override_kind */ + YYSYMBOL_set_target_list = 711, /* set_target_list */ + YYSYMBOL_opt_collate = 712, /* opt_collate */ + YYSYMBOL_opt_class = 713, /* opt_class */ + YYSYMBOL_insert_column_list = 714, /* insert_column_list */ + YYSYMBOL_set_clause_list = 715, /* set_clause_list */ + YYSYMBOL_set_clause_list_opt_comma = 716, /* set_clause_list_opt_comma */ + YYSYMBOL_index_params = 717, /* index_params */ + YYSYMBOL_set_target = 718, /* set_target */ + YYSYMBOL_LoadStmt = 719, /* LoadStmt */ + YYSYMBOL_opt_force = 720, /* opt_force */ + YYSYMBOL_file_name = 721, /* file_name */ + YYSYMBOL_opt_ext_version = 722, /* opt_ext_version */ + YYSYMBOL_PragmaStmt = 723, /* PragmaStmt */ + YYSYMBOL_PrepareStmt = 724, /* PrepareStmt */ + YYSYMBOL_prep_type_clause = 725, /* prep_type_clause */ + YYSYMBOL_PreparableStmt = 726, /* PreparableStmt */ + YYSYMBOL_RenameStmt = 727, /* RenameStmt */ + YYSYMBOL_opt_column = 728, /* opt_column */ + YYSYMBOL_SelectStmt = 729, /* SelectStmt */ + YYSYMBOL_select_with_parens = 730, /* select_with_parens */ + YYSYMBOL_select_no_parens = 731, /* select_no_parens */ + YYSYMBOL_select_clause = 732, /* select_clause */ + YYSYMBOL_opt_select = 733, /* opt_select */ + YYSYMBOL_simple_select = 734, /* simple_select */ + YYSYMBOL_value_or_values = 735, /* value_or_values */ + YYSYMBOL_pivot_keyword = 736, /* pivot_keyword */ + YYSYMBOL_unpivot_keyword = 737, /* unpivot_keyword */ + YYSYMBOL_pivot_column_entry = 738, /* pivot_column_entry */ + YYSYMBOL_pivot_column_list_internal = 739, /* pivot_column_list_internal */ + YYSYMBOL_pivot_column_list = 740, /* pivot_column_list */ + YYSYMBOL_with_clause = 741, /* with_clause */ + YYSYMBOL_cte_list = 742, /* cte_list */ + YYSYMBOL_common_table_expr = 743, /* common_table_expr */ + YYSYMBOL_opt_materialized = 744, /* opt_materialized */ + YYSYMBOL_into_clause = 745, /* into_clause */ + YYSYMBOL_OptTempTableName = 746, /* OptTempTableName */ + YYSYMBOL_opt_table = 747, /* opt_table */ + YYSYMBOL_all_or_distinct = 748, /* all_or_distinct */ + YYSYMBOL_by_name = 749, /* by_name */ + YYSYMBOL_distinct_clause = 750, /* distinct_clause */ + YYSYMBOL_opt_all_clause = 751, /* opt_all_clause */ + YYSYMBOL_opt_ignore_nulls = 752, /* opt_ignore_nulls */ + YYSYMBOL_opt_sort_clause = 753, /* opt_sort_clause */ + YYSYMBOL_sort_clause = 754, /* sort_clause */ + YYSYMBOL_sortby_list = 755, /* sortby_list */ + YYSYMBOL_sortby = 756, /* sortby */ + YYSYMBOL_opt_asc_desc = 757, /* opt_asc_desc */ + YYSYMBOL_opt_nulls_order = 758, /* opt_nulls_order */ + YYSYMBOL_select_limit = 759, /* select_limit */ + YYSYMBOL_opt_select_limit = 760, /* opt_select_limit */ + YYSYMBOL_limit_clause = 761, /* limit_clause */ + YYSYMBOL_offset_clause = 762, /* offset_clause */ + YYSYMBOL_sample_count = 763, /* sample_count */ + YYSYMBOL_sample_clause = 764, /* sample_clause */ + YYSYMBOL_opt_sample_func = 765, /* opt_sample_func */ + YYSYMBOL_tablesample_entry = 766, /* tablesample_entry */ + YYSYMBOL_tablesample_clause = 767, /* tablesample_clause */ + YYSYMBOL_opt_tablesample_clause = 768, /* opt_tablesample_clause */ + YYSYMBOL_opt_repeatable_clause = 769, /* opt_repeatable_clause */ + YYSYMBOL_select_limit_value = 770, /* select_limit_value */ + YYSYMBOL_select_offset_value = 771, /* select_offset_value */ + YYSYMBOL_select_fetch_first_value = 772, /* select_fetch_first_value */ + YYSYMBOL_I_or_F_const = 773, /* I_or_F_const */ + YYSYMBOL_row_or_rows = 774, /* row_or_rows */ + YYSYMBOL_first_or_next = 775, /* first_or_next */ + YYSYMBOL_group_clause = 776, /* group_clause */ + YYSYMBOL_group_by_list = 777, /* group_by_list */ + YYSYMBOL_group_by_list_opt_comma = 778, /* group_by_list_opt_comma */ + YYSYMBOL_group_by_item = 779, /* group_by_item */ + YYSYMBOL_empty_grouping_set = 780, /* empty_grouping_set */ + YYSYMBOL_rollup_clause = 781, /* rollup_clause */ + YYSYMBOL_cube_clause = 782, /* cube_clause */ + YYSYMBOL_grouping_sets_clause = 783, /* grouping_sets_clause */ + YYSYMBOL_grouping_or_grouping_id = 784, /* grouping_or_grouping_id */ + YYSYMBOL_having_clause = 785, /* having_clause */ + YYSYMBOL_qualify_clause = 786, /* qualify_clause */ + YYSYMBOL_for_locking_clause = 787, /* for_locking_clause */ + YYSYMBOL_opt_for_locking_clause = 788, /* opt_for_locking_clause */ + YYSYMBOL_for_locking_items = 789, /* for_locking_items */ + YYSYMBOL_for_locking_item = 790, /* for_locking_item */ + YYSYMBOL_for_locking_strength = 791, /* for_locking_strength */ + YYSYMBOL_locked_rels_list = 792, /* locked_rels_list */ + YYSYMBOL_opt_nowait_or_skip = 793, /* opt_nowait_or_skip */ + YYSYMBOL_values_clause = 794, /* values_clause */ + YYSYMBOL_values_clause_opt_comma = 795, /* values_clause_opt_comma */ + YYSYMBOL_from_clause = 796, /* from_clause */ + YYSYMBOL_from_list = 797, /* from_list */ + YYSYMBOL_from_list_opt_comma = 798, /* from_list_opt_comma */ + YYSYMBOL_table_ref = 799, /* table_ref */ + YYSYMBOL_opt_pivot_group_by = 800, /* opt_pivot_group_by */ + YYSYMBOL_opt_include_nulls = 801, /* opt_include_nulls */ + YYSYMBOL_single_pivot_value = 802, /* single_pivot_value */ + YYSYMBOL_pivot_header = 803, /* pivot_header */ + YYSYMBOL_pivot_value = 804, /* pivot_value */ + YYSYMBOL_pivot_value_list = 805, /* pivot_value_list */ + YYSYMBOL_unpivot_header = 806, /* unpivot_header */ + YYSYMBOL_unpivot_value = 807, /* unpivot_value */ + YYSYMBOL_unpivot_value_list = 808, /* unpivot_value_list */ + YYSYMBOL_joined_table = 809, /* joined_table */ + YYSYMBOL_alias_clause = 810, /* alias_clause */ + YYSYMBOL_opt_alias_clause = 811, /* opt_alias_clause */ + YYSYMBOL_func_alias_clause = 812, /* func_alias_clause */ + YYSYMBOL_join_type = 813, /* join_type */ + YYSYMBOL_join_outer = 814, /* join_outer */ + YYSYMBOL_join_qual = 815, /* join_qual */ + YYSYMBOL_relation_expr = 816, /* relation_expr */ + YYSYMBOL_func_table = 817, /* func_table */ + YYSYMBOL_rowsfrom_item = 818, /* rowsfrom_item */ + YYSYMBOL_rowsfrom_list = 819, /* rowsfrom_list */ + YYSYMBOL_opt_col_def_list = 820, /* opt_col_def_list */ + YYSYMBOL_opt_ordinality = 821, /* opt_ordinality */ + YYSYMBOL_where_clause = 822, /* where_clause */ + YYSYMBOL_TableFuncElementList = 823, /* TableFuncElementList */ + YYSYMBOL_TableFuncElement = 824, /* TableFuncElement */ + YYSYMBOL_opt_collate_clause = 825, /* opt_collate_clause */ + YYSYMBOL_colid_type_list = 826, /* colid_type_list */ + YYSYMBOL_RowOrStruct = 827, /* RowOrStruct */ + YYSYMBOL_opt_Typename = 828, /* opt_Typename */ + YYSYMBOL_Typename = 829, /* Typename */ + YYSYMBOL_qualified_typename = 830, /* qualified_typename */ + YYSYMBOL_opt_array_bounds = 831, /* opt_array_bounds */ + YYSYMBOL_SimpleTypename = 832, /* SimpleTypename */ + YYSYMBOL_ConstTypename = 833, /* ConstTypename */ + YYSYMBOL_GenericType = 834, /* GenericType */ + YYSYMBOL_opt_type_modifiers = 835, /* opt_type_modifiers */ + YYSYMBOL_Numeric = 836, /* Numeric */ + YYSYMBOL_opt_float = 837, /* opt_float */ + YYSYMBOL_Bit = 838, /* Bit */ + YYSYMBOL_ConstBit = 839, /* ConstBit */ + YYSYMBOL_BitWithLength = 840, /* BitWithLength */ + YYSYMBOL_BitWithoutLength = 841, /* BitWithoutLength */ + YYSYMBOL_Character = 842, /* Character */ + YYSYMBOL_ConstCharacter = 843, /* ConstCharacter */ + YYSYMBOL_CharacterWithLength = 844, /* CharacterWithLength */ + YYSYMBOL_CharacterWithoutLength = 845, /* CharacterWithoutLength */ + YYSYMBOL_character = 846, /* character */ + YYSYMBOL_opt_varying = 847, /* opt_varying */ + YYSYMBOL_ConstDatetime = 848, /* ConstDatetime */ + YYSYMBOL_ConstInterval = 849, /* ConstInterval */ + YYSYMBOL_opt_timezone = 850, /* opt_timezone */ + YYSYMBOL_year_keyword = 851, /* year_keyword */ + YYSYMBOL_month_keyword = 852, /* month_keyword */ + YYSYMBOL_day_keyword = 853, /* day_keyword */ + YYSYMBOL_hour_keyword = 854, /* hour_keyword */ + YYSYMBOL_minute_keyword = 855, /* minute_keyword */ + YYSYMBOL_second_keyword = 856, /* second_keyword */ + YYSYMBOL_millisecond_keyword = 857, /* millisecond_keyword */ + YYSYMBOL_microsecond_keyword = 858, /* microsecond_keyword */ + YYSYMBOL_week_keyword = 859, /* week_keyword */ + YYSYMBOL_quarter_keyword = 860, /* quarter_keyword */ + YYSYMBOL_decade_keyword = 861, /* decade_keyword */ + YYSYMBOL_century_keyword = 862, /* century_keyword */ + YYSYMBOL_millennium_keyword = 863, /* millennium_keyword */ + YYSYMBOL_opt_interval = 864, /* opt_interval */ + YYSYMBOL_a_expr = 865, /* a_expr */ + YYSYMBOL_b_expr = 866, /* b_expr */ + YYSYMBOL_c_expr = 867, /* c_expr */ + YYSYMBOL_d_expr = 868, /* d_expr */ + YYSYMBOL_indirection_expr_or_a_expr = 869, /* indirection_expr_or_a_expr */ + YYSYMBOL_indirection_expr = 870, /* indirection_expr */ + YYSYMBOL_list_expr = 871, /* list_expr */ + YYSYMBOL_struct_expr = 872, /* struct_expr */ + YYSYMBOL_func_application = 873, /* func_application */ + YYSYMBOL_func_expr = 874, /* func_expr */ + YYSYMBOL_func_expr_windowless = 875, /* func_expr_windowless */ + YYSYMBOL_func_expr_common_subexpr = 876, /* func_expr_common_subexpr */ + YYSYMBOL_list_comprehension = 877, /* list_comprehension */ + YYSYMBOL_within_group_clause = 878, /* within_group_clause */ + YYSYMBOL_filter_clause = 879, /* filter_clause */ + YYSYMBOL_export_clause = 880, /* export_clause */ + YYSYMBOL_window_clause = 881, /* window_clause */ + YYSYMBOL_window_definition_list = 882, /* window_definition_list */ + YYSYMBOL_window_definition = 883, /* window_definition */ + YYSYMBOL_over_clause = 884, /* over_clause */ + YYSYMBOL_window_specification = 885, /* window_specification */ + YYSYMBOL_opt_existing_window_name = 886, /* opt_existing_window_name */ + YYSYMBOL_opt_partition_clause = 887, /* opt_partition_clause */ + YYSYMBOL_opt_frame_clause = 888, /* opt_frame_clause */ + YYSYMBOL_frame_extent = 889, /* frame_extent */ + YYSYMBOL_frame_bound = 890, /* frame_bound */ + YYSYMBOL_opt_window_exclusion_clause = 891, /* opt_window_exclusion_clause */ + YYSYMBOL_qualified_row = 892, /* qualified_row */ + YYSYMBOL_row = 893, /* row */ + YYSYMBOL_dict_arg = 894, /* dict_arg */ + YYSYMBOL_dict_arguments = 895, /* dict_arguments */ + YYSYMBOL_dict_arguments_opt_comma = 896, /* dict_arguments_opt_comma */ + YYSYMBOL_map_arg = 897, /* map_arg */ + YYSYMBOL_map_arguments = 898, /* map_arguments */ + YYSYMBOL_map_arguments_opt_comma = 899, /* map_arguments_opt_comma */ + YYSYMBOL_opt_map_arguments_opt_comma = 900, /* opt_map_arguments_opt_comma */ + YYSYMBOL_sub_type = 901, /* sub_type */ + YYSYMBOL_all_Op = 902, /* all_Op */ + YYSYMBOL_MathOp = 903, /* MathOp */ + YYSYMBOL_qual_Op = 904, /* qual_Op */ + YYSYMBOL_qual_all_Op = 905, /* qual_all_Op */ + YYSYMBOL_subquery_Op = 906, /* subquery_Op */ + YYSYMBOL_any_operator = 907, /* any_operator */ + YYSYMBOL_c_expr_list = 908, /* c_expr_list */ + YYSYMBOL_c_expr_list_opt_comma = 909, /* c_expr_list_opt_comma */ + YYSYMBOL_expr_list = 910, /* expr_list */ + YYSYMBOL_expr_list_opt_comma = 911, /* expr_list_opt_comma */ + YYSYMBOL_opt_expr_list_opt_comma = 912, /* opt_expr_list_opt_comma */ + YYSYMBOL_func_arg_list = 913, /* func_arg_list */ + YYSYMBOL_func_arg_expr = 914, /* func_arg_expr */ + YYSYMBOL_type_list = 915, /* type_list */ + YYSYMBOL_extract_list = 916, /* extract_list */ + YYSYMBOL_extract_arg = 917, /* extract_arg */ + YYSYMBOL_overlay_list = 918, /* overlay_list */ + YYSYMBOL_overlay_placing = 919, /* overlay_placing */ + YYSYMBOL_position_list = 920, /* position_list */ + YYSYMBOL_substr_list = 921, /* substr_list */ + YYSYMBOL_substr_from = 922, /* substr_from */ + YYSYMBOL_substr_for = 923, /* substr_for */ + YYSYMBOL_trim_list = 924, /* trim_list */ + YYSYMBOL_in_expr = 925, /* in_expr */ + YYSYMBOL_case_expr = 926, /* case_expr */ + YYSYMBOL_when_clause_list = 927, /* when_clause_list */ + YYSYMBOL_when_clause = 928, /* when_clause */ + YYSYMBOL_case_default = 929, /* case_default */ + YYSYMBOL_case_arg = 930, /* case_arg */ + YYSYMBOL_columnref = 931, /* columnref */ + YYSYMBOL_opt_slice_bound = 932, /* opt_slice_bound */ + YYSYMBOL_opt_indirection = 933, /* opt_indirection */ + YYSYMBOL_opt_func_arguments = 934, /* opt_func_arguments */ + YYSYMBOL_extended_indirection_el = 935, /* extended_indirection_el */ + YYSYMBOL_opt_extended_indirection = 936, /* opt_extended_indirection */ + YYSYMBOL_opt_asymmetric = 937, /* opt_asymmetric */ + YYSYMBOL_opt_target_list_opt_comma = 938, /* opt_target_list_opt_comma */ + YYSYMBOL_target_list = 939, /* target_list */ + YYSYMBOL_target_list_opt_comma = 940, /* target_list_opt_comma */ + YYSYMBOL_target_el = 941, /* target_el */ + YYSYMBOL_except_list = 942, /* except_list */ + YYSYMBOL_opt_except_list = 943, /* opt_except_list */ + YYSYMBOL_replace_list_el = 944, /* replace_list_el */ + YYSYMBOL_replace_list = 945, /* replace_list */ + YYSYMBOL_replace_list_opt_comma = 946, /* replace_list_opt_comma */ + YYSYMBOL_opt_replace_list = 947, /* opt_replace_list */ + YYSYMBOL_qualified_name_list = 948, /* qualified_name_list */ + YYSYMBOL_name_list = 949, /* name_list */ + YYSYMBOL_name_list_opt_comma = 950, /* name_list_opt_comma */ + YYSYMBOL_name_list_opt_comma_opt_bracket = 951, /* name_list_opt_comma_opt_bracket */ + YYSYMBOL_name = 952, /* name */ + YYSYMBOL_func_name = 953, /* func_name */ + YYSYMBOL_AexprConst = 954, /* AexprConst */ + YYSYMBOL_Iconst = 955, /* Iconst */ + YYSYMBOL_type_function_name = 956, /* type_function_name */ + YYSYMBOL_function_name_token = 957, /* function_name_token */ + YYSYMBOL_type_name_token = 958, /* type_name_token */ + YYSYMBOL_any_name = 959, /* any_name */ + YYSYMBOL_attrs = 960, /* attrs */ + YYSYMBOL_opt_name_list = 961, /* opt_name_list */ + YYSYMBOL_param_name = 962, /* param_name */ + YYSYMBOL_ColLabelOrString = 963, /* ColLabelOrString */ + YYSYMBOL_TransactionStmt = 964, /* TransactionStmt */ + YYSYMBOL_opt_transaction = 965, /* opt_transaction */ + YYSYMBOL_opt_transaction_type = 966, /* opt_transaction_type */ + YYSYMBOL_UpdateStmt = 967, /* UpdateStmt */ + YYSYMBOL_UpdateExtensionsStmt = 968, /* UpdateExtensionsStmt */ + YYSYMBOL_UseStmt = 969, /* UseStmt */ + YYSYMBOL_VacuumStmt = 970, /* VacuumStmt */ + YYSYMBOL_vacuum_option_elem = 971, /* vacuum_option_elem */ + YYSYMBOL_opt_full = 972, /* opt_full */ + YYSYMBOL_vacuum_option_list = 973, /* vacuum_option_list */ + YYSYMBOL_opt_freeze = 974, /* opt_freeze */ + YYSYMBOL_VariableResetStmt = 975, /* VariableResetStmt */ + YYSYMBOL_generic_reset = 976, /* generic_reset */ + YYSYMBOL_reset_rest = 977, /* reset_rest */ + YYSYMBOL_VariableSetStmt = 978, /* VariableSetStmt */ + YYSYMBOL_set_rest = 979, /* set_rest */ + YYSYMBOL_generic_set = 980, /* generic_set */ + YYSYMBOL_var_value = 981, /* var_value */ + YYSYMBOL_zone_value = 982, /* zone_value */ + YYSYMBOL_var_list = 983, /* var_list */ + YYSYMBOL_VariableShowStmt = 984, /* VariableShowStmt */ + YYSYMBOL_describe_or_desc = 985, /* describe_or_desc */ + YYSYMBOL_show_or_describe = 986, /* show_or_describe */ + YYSYMBOL_opt_tables = 987, /* opt_tables */ + YYSYMBOL_var_name = 988, /* var_name */ + YYSYMBOL_table_id = 989, /* table_id */ + YYSYMBOL_ViewStmt = 990, /* ViewStmt */ + YYSYMBOL_opt_check_option = 991 /* opt_check_option */ +}; +typedef enum yysymbol_kind_t yysymbol_kind_t; -/* Copy the second part of user declarations. */ -/* Line 216 of yacc.c. */ -#line 1347 "third_party/libpg_query/grammar/grammar_out.cpp" #ifdef short # undef short #endif -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + and (if available) are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif #endif -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; +#else typedef signed char yytype_int8; +#endif + +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; #else -typedef short int yytype_int8; +typedef short yytype_int16; +#endif + +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + . */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 #endif -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; #else -typedef unsigned short int yytype_uint16; +typedef short yytype_uint8; #endif -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; #else -typedef short int yytype_int16; +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif #endif #ifndef YYSIZE_T @@ -1381,55 +1355,106 @@ typedef short int yytype_int16; # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else -# define YYSIZE_T unsigned int +# define YYSIZE_T unsigned # endif #endif -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + + +/* Stored state numbers (used for stacks). */ +typedef yytype_int16 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ -# define YY_(msgid) msgid +# define YY_(Msgid) Msgid +# endif +#endif + + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(e) /* empty */ +# define YY_USE(E) /* empty */ #endif -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(n) (n) -#else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int i) +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") #else -static int -YYID (i) - int i; +# define YY_INITIAL_VALUE(Value) Value #endif -{ - return i; -} +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END #endif -#if ! defined yyoverflow || YYERROR_VERBOSE + +#define YY_ASSERT(E) ((void) (0 && (E))) + +#if !defined yyoverflow /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -1446,11 +1471,11 @@ YYID (i) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -1458,8 +1483,8 @@ YYID (i) # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely @@ -1473,127 +1498,134 @@ YYID (i) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) + && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - +#endif /* !defined yyoverflow */ #if (! defined yyoverflow \ && (! defined __cplusplus \ - || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ - && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ + && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss; - YYSTYPE yyvs; - YYLTYPE yyls; + yy_state_t yyss_alloc; + YYSTYPE yyvs_alloc; + YYLTYPE yyls_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE) \ + + YYSIZEOF (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ - Stack = &yyptr->Stack; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (YYID (0)) +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYPTRDIFF_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ + } \ + while (0) #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYPTRDIFF_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 867 +#define YYFINAL 870 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 72739 +#define YYLAST 73455 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 525 +#define YYNTOKENS 528 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 460 +#define YYNNTS 464 /* YYNRULES -- Number of rules. */ -#define YYNRULES 2120 -/* YYNRULES -- Number of states. */ -#define YYNSTATES 3529 +#define YYNRULES 2136 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 3547 -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 757 +/* YYMAXUTOK -- Last valid token kind. */ +#define YYMAXUTOK 760 -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const yytype_uint16 yytranslate[] = +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK \ + ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ + : YYSYMBOL_YYUNDEF) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex. */ +static const yytype_int16 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 522, 523, 509, 2, 2, - 514, 515, 507, 505, 518, 506, 516, 508, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 524, 517, - 501, 503, 502, 519, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 525, 526, 512, 2, 2, + 517, 518, 510, 508, 521, 509, 519, 511, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 527, 520, + 504, 506, 505, 522, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 512, 2, 513, 510, 2, 2, 2, 2, 2, + 2, 515, 2, 516, 513, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 520, 2, 521, 2, 2, 2, 2, + 2, 2, 2, 523, 2, 524, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -1656,1003 +1688,143 @@ static const yytype_uint16 yytranslate[] = 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, - 495, 496, 497, 498, 499, 500, 504, 511 + 495, 496, 497, 498, 499, 500, 501, 502, 503, 507, + 514 }; #if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint16 yyprhs[] = -{ - 0, 0, 3, 5, 9, 11, 13, 15, 17, 19, - 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, - 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, - 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, - 81, 83, 85, 87, 89, 91, 92, 97, 104, 109, - 116, 121, 128, 133, 140, 142, 145, 149, 152, 154, - 158, 161, 165, 167, 171, 174, 180, 184, 191, 196, - 203, 210, 217, 223, 229, 236, 246, 251, 257, 265, - 272, 277, 286, 291, 294, 299, 303, 310, 315, 318, - 321, 324, 327, 329, 332, 333, 335, 338, 341, 344, - 346, 350, 355, 358, 360, 361, 364, 368, 371, 375, - 377, 380, 382, 384, 386, 388, 390, 392, 394, 397, - 400, 402, 404, 406, 408, 410, 417, 424, 433, 440, - 449, 456, 465, 472, 481, 490, 501, 510, 521, 523, - 524, 534, 536, 541, 546, 554, 557, 559, 563, 566, - 569, 570, 575, 579, 580, 582, 583, 586, 590, 596, - 599, 602, 603, 612, 618, 619, 625, 631, 639, 642, - 643, 645, 647, 649, 653, 656, 657, 659, 660, 662, - 666, 668, 672, 674, 677, 679, 683, 686, 693, 702, - 708, 710, 711, 713, 717, 720, 725, 731, 737, 746, - 754, 756, 757, 766, 778, 789, 790, 792, 793, 795, - 797, 798, 801, 805, 815, 828, 830, 834, 836, 840, - 844, 845, 850, 857, 859, 862, 864, 866, 867, 869, - 872, 875, 877, 880, 883, 885, 888, 892, 895, 898, - 901, 904, 908, 912, 916, 918, 922, 924, 925, 927, - 930, 933, 939, 947, 948, 951, 954, 957, 960, 963, - 966, 969, 971, 973, 974, 977, 987, 1000, 1012, 1013, - 1016, 1018, 1020, 1022, 1024, 1026, 1028, 1032, 1033, 1035, - 1038, 1040, 1042, 1045, 1048, 1052, 1054, 1056, 1059, 1062, - 1064, 1067, 1071, 1077, 1081, 1084, 1090, 1092, 1094, 1096, - 1097, 1103, 1111, 1117, 1120, 1124, 1126, 1128, 1131, 1134, - 1135, 1139, 1144, 1149, 1150, 1154, 1157, 1158, 1162, 1164, - 1166, 1168, 1170, 1172, 1174, 1176, 1178, 1180, 1182, 1186, - 1190, 1192, 1195, 1198, 1201, 1204, 1207, 1210, 1211, 1215, - 1219, 1223, 1224, 1226, 1229, 1231, 1234, 1237, 1240, 1243, - 1247, 1252, 1254, 1258, 1260, 1262, 1264, 1266, 1270, 1272, - 1275, 1276, 1278, 1281, 1282, 1284, 1288, 1289, 1292, 1293, - 1297, 1301, 1303, 1309, 1313, 1315, 1319, 1321, 1324, 1326, - 1331, 1337, 1343, 1350, 1354, 1362, 1367, 1379, 1381, 1385, - 1388, 1391, 1394, 1395, 1399, 1401, 1403, 1406, 1409, 1412, - 1415, 1417, 1418, 1420, 1423, 1430, 1435, 1442, 1447, 1454, - 1463, 1465, 1467, 1469, 1471, 1474, 1476, 1479, 1481, 1484, - 1486, 1488, 1490, 1492, 1496, 1500, 1504, 1508, 1510, 1513, - 1516, 1518, 1522, 1524, 1526, 1528, 1532, 1534, 1536, 1537, - 1539, 1541, 1543, 1552, 1564, 1575, 1583, 1594, 1604, 1606, - 1608, 1611, 1615, 1624, 1636, 1646, 1654, 1655, 1659, 1663, - 1665, 1667, 1671, 1672, 1674, 1678, 1680, 1681, 1683, 1684, - 1686, 1687, 1689, 1693, 1695, 1697, 1699, 1701, 1705, 1707, - 1708, 1711, 1714, 1715, 1718, 1719, 1721, 1722, 1724, 1726, - 1728, 1732, 1736, 1738, 1740, 1744, 1748, 1752, 1756, 1760, - 1764, 1769, 1773, 1776, 1778, 1780, 1782, 1784, 1788, 1790, - 1792, 1796, 1798, 1800, 1804, 1808, 1812, 1814, 1817, 1822, - 1827, 1830, 1834, 1840, 1846, 1848, 1850, 1854, 1855, 1867, - 1879, 1890, 1903, 1905, 1908, 1914, 1919, 1924, 1929, 1934, - 1942, 1948, 1953, 1961, 1968, 1978, 1988, 1993, 1995, 1997, - 1999, 2001, 2003, 2005, 2007, 2013, 2015, 2017, 2021, 2023, - 2026, 2029, 2032, 2036, 2038, 2042, 2050, 2052, 2055, 2056, - 2059, 2060, 2064, 2068, 2073, 2078, 2083, 2088, 2092, 2095, - 2097, 2099, 2100, 2102, 2104, 2105, 2108, 2110, 2116, 2118, - 2119, 2122, 2125, 2126, 2128, 2129, 2133, 2139, 2141, 2145, - 2150, 2154, 2156, 2158, 2159, 2162, 2165, 2166, 2169, 2172, - 2174, 2176, 2178, 2179, 2182, 2187, 2193, 2198, 2201, 2205, - 2208, 2211, 2214, 2217, 2219, 2222, 2226, 2227, 2229, 2230, - 2236, 2238, 2243, 2250, 2253, 2255, 2256, 2261, 2262, 2264, - 2266, 2269, 2272, 2275, 2277, 2279, 2282, 2285, 2287, 2289, - 2291, 2293, 2295, 2297, 2301, 2305, 2306, 2308, 2312, 2314, - 2317, 2319, 2321, 2323, 2325, 2327, 2330, 2335, 2340, 2346, - 2348, 2350, 2353, 2354, 2357, 2358, 2360, 2364, 2366, 2367, - 2369, 2372, 2376, 2379, 2384, 2387, 2391, 2394, 2395, 2397, - 2400, 2401, 2406, 2412, 2414, 2417, 2420, 2421, 2423, 2427, - 2429, 2432, 2436, 2440, 2444, 2448, 2452, 2456, 2458, 2463, - 2473, 2483, 2487, 2488, 2491, 2494, 2495, 2501, 2505, 2506, - 2508, 2510, 2514, 2520, 2524, 2526, 2529, 2531, 2535, 2541, - 2543, 2546, 2550, 2555, 2561, 2566, 2572, 2577, 2584, 2590, - 2595, 2601, 2607, 2613, 2616, 2621, 2623, 2625, 2626, 2628, - 2633, 2639, 2644, 2645, 2648, 2651, 2654, 2656, 2658, 2660, - 2662, 2663, 2668, 2671, 2673, 2676, 2679, 2684, 2687, 2694, - 2697, 2699, 2703, 2708, 2709, 2712, 2713, 2716, 2717, 2719, - 2723, 2727, 2730, 2731, 2734, 2739, 2741, 2743, 2745, 2746, - 2749, 2753, 2759, 2766, 2769, 2773, 2775, 2781, 2787, 2793, - 2797, 2801, 2805, 2810, 2811, 2813, 2815, 2817, 2819, 2821, - 2824, 2829, 2831, 2833, 2835, 2837, 2840, 2844, 2845, 2847, - 2849, 2851, 2853, 2855, 2858, 2861, 2864, 2867, 2870, 2872, - 2876, 2877, 2879, 2881, 2883, 2885, 2891, 2894, 2896, 2898, - 2900, 2902, 2907, 2909, 2912, 2915, 2917, 2921, 2925, 2928, - 2930, 2931, 2937, 2940, 2946, 2949, 2951, 2955, 2959, 2960, - 2962, 2964, 2966, 2968, 2970, 2972, 2974, 2976, 2978, 2980, - 2982, 2984, 2986, 2988, 2990, 2992, 2994, 2996, 2998, 3000, - 3002, 3004, 3006, 3008, 3010, 3012, 3014, 3016, 3018, 3020, - 3022, 3024, 3026, 3028, 3030, 3032, 3036, 3040, 3044, 3048, - 3052, 3056, 3060, 3061, 3063, 3067, 3071, 3077, 3080, 3083, - 3087, 3091, 3095, 3099, 3103, 3107, 3111, 3115, 3119, 3123, - 3127, 3131, 3135, 3139, 3143, 3146, 3149, 3153, 3157, 3160, - 3163, 3167, 3171, 3177, 3182, 3189, 3193, 3199, 3204, 3211, - 3216, 3223, 3229, 3237, 3241, 3244, 3249, 3253, 3256, 3260, - 3264, 3268, 3272, 3277, 3281, 3286, 3290, 3295, 3301, 3308, - 3315, 3323, 3330, 3338, 3345, 3353, 3357, 3362, 3367, 3374, - 3376, 3381, 3385, 3391, 3393, 3397, 3400, 3403, 3407, 3411, - 3415, 3419, 3423, 3427, 3431, 3435, 3439, 3443, 3447, 3451, - 3455, 3459, 3463, 3466, 3469, 3475, 3482, 3489, 3497, 3499, - 3502, 3504, 3506, 3508, 3511, 3514, 3519, 3523, 3525, 3527, - 3529, 3531, 3533, 3538, 3540, 3542, 3544, 3546, 3549, 3554, - 3557, 3560, 3564, 3568, 3572, 3579, 3587, 3597, 3605, 3613, - 3619, 3621, 3623, 3625, 3631, 3638, 3645, 3650, 3655, 3660, - 3665, 3672, 3678, 3684, 3690, 3695, 3702, 3707, 3715, 3725, - 3731, 3732, 3738, 3743, 3744, 3746, 3747, 3750, 3751, 3753, - 3757, 3761, 3764, 3767, 3768, 3775, 3777, 3778, 3782, 3783, - 3787, 3791, 3795, 3796, 3798, 3803, 3806, 3809, 3812, 3815, - 3818, 3822, 3825, 3828, 3832, 3833, 3838, 3842, 3844, 3850, - 3854, 3856, 3860, 3862, 3865, 3869, 3871, 3875, 3877, 3880, - 3882, 3883, 3885, 3887, 3889, 3891, 3893, 3895, 3897, 3899, - 3901, 3903, 3905, 3907, 3909, 3911, 3913, 3915, 3917, 3919, - 3921, 3923, 3928, 3930, 3935, 3937, 3942, 3944, 3947, 3949, - 3952, 3954, 3957, 3959, 3963, 3965, 3969, 3971, 3974, 3976, - 3980, 3982, 3985, 3987, 3988, 3990, 3994, 3996, 4000, 4004, - 4006, 4010, 4014, 4015, 4017, 4019, 4021, 4023, 4025, 4027, - 4029, 4031, 4033, 4035, 4037, 4039, 4041, 4043, 4048, 4052, - 4055, 4059, 4060, 4064, 4068, 4071, 4074, 4076, 4077, 4080, - 4083, 4087, 4090, 4092, 4094, 4098, 4104, 4106, 4109, 4114, - 4117, 4118, 4120, 4121, 4123, 4126, 4130, 4136, 4144, 4152, - 4154, 4155, 4156, 4159, 4160, 4163, 4167, 4171, 4175, 4181, - 4189, 4197, 4198, 4201, 4203, 4204, 4206, 4207, 4209, 4213, - 4215, 4218, 4222, 4225, 4227, 4232, 4235, 4237, 4238, 4242, - 4244, 4248, 4250, 4253, 4258, 4261, 4262, 4264, 4268, 4270, - 4274, 4276, 4279, 4281, 4285, 4287, 4289, 4292, 4294, 4296, - 4299, 4301, 4303, 4306, 4314, 4317, 4323, 4327, 4331, 4333, - 4335, 4337, 4339, 4341, 4343, 4345, 4347, 4349, 4351, 4353, - 4355, 4357, 4359, 4362, 4365, 4369, 4373, 4374, 4376, 4378, - 4380, 4386, 4390, 4391, 4393, 4395, 4397, 4399, 4401, 4403, - 4408, 4416, 4423, 4426, 4427, 4429, 4431, 4433, 4435, 4449, - 4466, 4468, 4471, 4472, 4474, 4475, 4477, 4478, 4481, 4482, - 4484, 4485, 4492, 4501, 4508, 4517, 4524, 4533, 4537, 4540, - 4542, 4543, 4550, 4557, 4559, 4561, 4563, 4565, 4567, 4569, - 4572, 4574, 4576, 4578, 4580, 4582, 4587, 4594, 4598, 4601, - 4606, 4610, 4616, 4618, 4619, 4621, 4623, 4624, 4626, 4628, - 4630, 4632, 4634, 4636, 4638, 4640, 4642, 4644, 4646, 4648, - 4650, 4652, 4654, 4656, 4658, 4660, 4662, 4664, 4666, 4668, - 4670, 4672, 4674, 4676, 4678, 4680, 4682, 4684, 4686, 4688, - 4690, 4692, 4694, 4696, 4700, 4702, 4704, 4706, 4708, 4710, - 4712, 4715, 4717, 4719, 4722, 4726, 4730, 4734, 4736, 4740, - 4744, 4747, 4751, 4755, 4757, 4759, 4761, 4765, 4771, 4773, - 4775, 4777, 4779, 4783, 4786, 4789, 4793, 4798, 4804, 4806, - 4808, 4810, 4812, 4817, 4824, 4830, 4835, 4842, 4844, 4846, - 4848, 4850, 4852, 4854, 4855, 4857, 4861, 4863, 4864, 4872, - 4876, 4878, 4881, 4885, 4888, 4889, 4892, 4893, 4896, 4901, - 4907, 4916, 4919, 4923, 4929, 4931, 4932, 4935, 4936, 4939, - 4943, 4947, 4951, 4953, 4955, 4957, 4960, 4964, 4967, 4970, - 4973, 4976, 4980, 4985, 4989, 4991, 4993, 4995, 4997, 4999, - 5001, 5002, 5004, 5008, 5010, 5014, 5017, 5027, 5040, 5052, - 5065, 5080, 5084, 5089, 5094, 5095, 5103, 5114, 5124, 5127, - 5131, 5132, 5137, 5139, 5141, 5143, 5145, 5147, 5149, 5151, - 5153, 5155, 5157, 5159, 5161, 5163, 5165, 5167, 5169, 5171, - 5173, 5175, 5177, 5179, 5181, 5183, 5185, 5187, 5189, 5191, - 5193, 5195, 5197, 5199, 5201, 5203, 5205, 5207, 5209, 5211, - 5213, 5215, 5217, 5219, 5221, 5223, 5225, 5227, 5229, 5231, - 5233, 5235, 5237, 5239, 5241, 5243, 5245, 5247, 5249, 5251, - 5253, 5255, 5257, 5259, 5261, 5263, 5265, 5267, 5269, 5271, - 5273, 5275, 5277, 5279, 5281, 5283, 5285, 5287, 5289, 5291, - 5293, 5295, 5297, 5299, 5301, 5303, 5305, 5307, 5309, 5311, - 5313, 5315, 5317, 5319, 5321, 5323, 5325, 5327, 5329, 5331, - 5333, 5335, 5337, 5339, 5341, 5343, 5345, 5347, 5349, 5351, - 5353, 5355, 5357, 5359, 5361, 5363, 5365, 5367, 5369, 5371, - 5373, 5375, 5377, 5379, 5381, 5383, 5385, 5387, 5389, 5391, - 5393, 5395, 5397, 5399, 5401, 5403, 5405, 5407, 5409, 5411, - 5413, 5415, 5417, 5419, 5421, 5423, 5425, 5427, 5429, 5431, - 5433, 5435, 5437, 5439, 5441, 5443, 5445, 5447, 5449, 5451, - 5453, 5455, 5457, 5459, 5461, 5463, 5465, 5467, 5469, 5471, - 5473, 5475, 5477, 5479, 5481, 5483, 5485, 5487, 5489, 5491, - 5493, 5495, 5497, 5499, 5501, 5503, 5505, 5507, 5509, 5511, - 5513, 5515, 5517, 5519, 5521, 5523, 5525, 5527, 5529, 5531, - 5533, 5535, 5537, 5539, 5541, 5543, 5545, 5547, 5549, 5551, - 5553, 5555, 5557, 5559, 5561, 5563, 5565, 5567, 5569, 5571, - 5573, 5575, 5577, 5579, 5581, 5583, 5585, 5587, 5589, 5591, - 5593, 5595, 5597, 5599, 5601, 5603, 5605, 5607, 5609, 5611, - 5613, 5615, 5617, 5619, 5621, 5623, 5625, 5627, 5629, 5631, - 5633, 5635, 5637, 5639, 5641, 5643, 5645, 5647, 5649, 5651, - 5653, 5655, 5657, 5659, 5661, 5663, 5665, 5667, 5669, 5671, - 5673, 5675, 5677, 5679, 5681, 5683, 5685, 5687, 5689, 5691, - 5693, 5695, 5697, 5699, 5701, 5703, 5705, 5707, 5709, 5711, - 5713, 5715, 5717, 5719, 5721, 5723, 5725, 5727, 5729, 5731, - 5733, 5735, 5737, 5739, 5741, 5743, 5745, 5747, 5749, 5751, - 5753, 5755, 5757, 5759, 5761, 5763, 5765, 5767, 5769, 5771, - 5773, 5775, 5777, 5779, 5781, 5783, 5785, 5787, 5789, 5791, - 5793, 5795, 5797, 5799, 5801, 5803, 5805, 5807, 5809, 5811, - 5813, 5815, 5817, 5819, 5821, 5823, 5825, 5827, 5829, 5831, - 5833, 5835, 5837, 5839, 5841, 5843, 5845, 5847, 5849, 5851, - 5853, 5855, 5857, 5859, 5861, 5863, 5865, 5867, 5869, 5871, - 5873, 5875, 5877, 5879, 5881, 5883, 5885, 5887, 5889, 5891, - 5893, 5895, 5897, 5899, 5901, 5903, 5905, 5907, 5909, 5911, - 5913, 5915, 5917, 5919, 5921, 5923, 5925, 5927, 5929, 5931, - 5933, 5935, 5937, 5939, 5941, 5943, 5945, 5947, 5949, 5951, - 5953, 5955, 5957, 5959, 5961, 5963, 5965, 5967, 5969, 5971, - 5973, 5975, 5977, 5979, 5981, 5983, 5985, 5987, 5989, 5991, - 5993, 5995, 5997, 5999, 6001, 6003, 6005, 6007, 6009, 6011, - 6013, 6015, 6017, 6019, 6021, 6023, 6025, 6027, 6029, 6031, - 6033, 6035, 6037, 6039, 6041, 6043, 6045, 6047, 6049, 6051, - 6053, 6055, 6057, 6059, 6061, 6063, 6065, 6067, 6069, 6071, - 6073, 6075, 6077, 6079, 6081, 6083, 6085, 6087, 6089, 6091, - 6093, 6095, 6097, 6099, 6101, 6103, 6105, 6107, 6109, 6111, - 6113, 6115, 6117, 6119, 6121, 6123, 6125, 6127, 6129, 6131, - 6133, 6135, 6137, 6139, 6141, 6143, 6145, 6147, 6149, 6151, - 6153, 6155, 6157, 6159, 6161, 6163, 6165, 6167, 6169, 6171, - 6173, 6175, 6177, 6179, 6181, 6183, 6185, 6187, 6189, 6191, - 6193, 6195, 6197, 6199, 6201, 6203, 6205, 6207, 6209, 6211, - 6213, 6215, 6217, 6219, 6221, 6223, 6225, 6227, 6229, 6231, - 6233, 6235, 6237, 6239, 6241, 6243, 6245, 6247, 6249, 6251, - 6253, 6255, 6257, 6259, 6261, 6263, 6265, 6267, 6269, 6271, - 6273, 6275, 6277, 6279, 6281, 6283, 6285, 6287, 6289, 6291, - 6293, 6295, 6297, 6299, 6301, 6303, 6305, 6307, 6309, 6311, - 6313, 6315, 6317, 6319, 6321, 6323, 6325, 6327, 6329, 6331, - 6333, 6335, 6337, 6339, 6341, 6343, 6345, 6347, 6349, 6351, - 6353, 6355, 6357, 6359, 6361, 6363, 6365, 6367, 6369, 6371, - 6373 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int16 yyrhs[] = -{ - 526, 0, -1, 527, -1, 527, 517, 528, -1, 528, - -1, 921, -1, 586, -1, 529, -1, 958, -1, 959, - -1, 972, -1, 922, -1, 924, -1, 656, -1, 975, - -1, 652, -1, 911, -1, 578, -1, 576, -1, 598, - -1, 572, -1, 540, -1, 954, -1, 960, -1, 593, - -1, 646, -1, 582, -1, 929, -1, 927, -1, 928, - -1, 914, -1, 551, -1, 946, -1, 575, -1, 908, - -1, 549, -1, 674, -1, 595, -1, 655, -1, 597, - -1, 949, -1, 963, -1, 940, -1, 966, -1, 973, - -1, -1, 32, 416, 761, 537, -1, 32, 416, 191, - 152, 761, 537, -1, 32, 202, 541, 537, -1, 32, - 202, 191, 152, 541, 537, -1, 32, 381, 541, 537, - -1, 32, 381, 191, 152, 541, 537, -1, 32, 466, - 541, 537, -1, 32, 466, 191, 152, 541, 537, -1, - 532, -1, 530, 532, -1, 386, 117, 809, -1, 137, - 117, -1, 356, -1, 356, 588, 589, -1, 386, 590, - -1, 386, 175, 645, -1, 536, -1, 533, 518, 536, - -1, 26, 625, -1, 26, 191, 274, 152, 625, -1, - 26, 82, 625, -1, 26, 82, 191, 274, 152, 625, - -1, 32, 550, 542, 531, -1, 32, 550, 542, 137, - 274, 279, -1, 32, 550, 542, 386, 274, 279, -1, - 32, 550, 542, 386, 402, 592, -1, 32, 550, 542, - 386, 613, -1, 32, 550, 542, 354, 613, -1, 32, - 550, 542, 386, 405, 542, -1, 32, 550, 542, 26, - 175, 645, 40, 190, 601, -1, 32, 550, 542, 530, - -1, 32, 550, 542, 137, 190, -1, 32, 550, 542, - 137, 190, 191, 152, -1, 137, 550, 191, 152, 542, - 650, -1, 137, 550, 542, 650, -1, 32, 550, 542, - 539, 439, 774, 770, 535, -1, 32, 550, 542, 538, - -1, 26, 615, -1, 32, 93, 896, 599, -1, 457, - 93, 896, -1, 137, 93, 191, 152, 896, 650, -1, - 137, 93, 896, 650, -1, 386, 244, -1, 386, 448, - -1, 386, 613, -1, 354, 613, -1, 538, -1, 454, - 809, -1, -1, 609, -1, 386, 609, -1, 26, 609, - -1, 137, 623, -1, 534, -1, 537, 518, 534, -1, - 293, 514, 533, 515, -1, 386, 107, -1, 386, -1, - -1, 111, 896, -1, 111, 325, 896, -1, 111, 30, - -1, 111, 325, 30, -1, 543, -1, 542, 545, -1, - 3, -1, 978, -1, 979, -1, 542, -1, 5, -1, - 5, -1, 546, -1, 545, 546, -1, 516, 547, -1, - 548, -1, 3, -1, 982, -1, 978, -1, 984, -1, - 32, 370, 896, 350, 428, 896, -1, 32, 416, 761, - 350, 428, 896, -1, 32, 416, 191, 152, 761, 350, - 428, 896, -1, 32, 381, 541, 350, 428, 896, -1, - 32, 381, 191, 152, 541, 350, 428, 896, -1, 32, - 466, 541, 350, 428, 896, -1, 32, 466, 191, 152, - 541, 350, 428, 896, -1, 32, 202, 541, 350, 428, - 896, -1, 32, 202, 191, 152, 541, 350, 428, 896, - -1, 32, 416, 761, 350, 550, 896, 428, 896, -1, - 32, 416, 191, 152, 761, 350, 550, 896, 428, 896, - -1, 32, 416, 761, 350, 93, 896, 428, 896, -1, - 32, 416, 191, 152, 761, 350, 93, 896, 428, 896, - -1, 82, -1, -1, 556, 212, 559, 219, 553, 554, - 552, 560, 562, -1, 674, -1, 303, 563, 459, 674, - -1, 514, 567, 515, 674, -1, 514, 567, 515, 303, - 563, 459, 674, -1, 117, 460, -1, 541, -1, 541, - 40, 542, -1, 59, 265, -1, 59, 320, -1, -1, - 514, 570, 515, 767, -1, 289, 93, 896, -1, -1, - 686, -1, -1, 542, 877, -1, 571, 503, 809, -1, - 514, 564, 515, 503, 809, -1, 294, 352, -1, 294, - 192, -1, -1, 289, 91, 555, 133, 451, 386, 569, - 767, -1, 289, 91, 555, 133, 275, -1, -1, 542, - 565, 566, 702, 703, -1, 819, 565, 566, 702, 703, - -1, 514, 809, 515, 565, 566, 702, 703, -1, 358, - 883, -1, -1, 453, -1, 415, -1, 571, -1, 564, - 518, 571, -1, 80, 903, -1, -1, 903, -1, -1, - 557, -1, 567, 518, 557, -1, 558, -1, 568, 518, - 558, -1, 568, -1, 568, 518, -1, 561, -1, 570, - 518, 561, -1, 542, 877, -1, 100, 439, 541, 40, - 144, 675, -1, 100, 439, 541, 40, 144, 514, 573, - 515, -1, 100, 439, 541, 40, 774, -1, 574, -1, - -1, 544, -1, 574, 518, 544, -1, 322, 542, -1, - 322, 542, 503, 945, -1, 322, 542, 514, 857, 515, - -1, 100, 644, 381, 541, 577, -1, 100, 644, 381, - 191, 274, 152, 541, 577, -1, 100, 294, 352, 644, - 381, 541, 577, -1, 587, -1, -1, 100, 580, 377, - 579, 581, 514, 673, 515, -1, 100, 580, 377, 191, - 274, 152, 579, 581, 514, 673, 515, -1, 100, 294, - 352, 580, 377, 579, 581, 514, 673, 515, -1, -1, - 542, -1, -1, 422, -1, 313, -1, -1, 198, 3, - -1, 151, 896, 585, -1, 100, 644, 416, 977, 40, - 151, 896, 585, 976, -1, 100, 644, 416, 191, 274, - 152, 977, 40, 151, 896, 585, 976, -1, 809, -1, - 906, 13, 809, -1, 583, -1, 584, 518, 583, -1, - 514, 584, 515, -1, -1, 32, 381, 541, 587, -1, - 32, 381, 191, 152, 541, 587, -1, 590, -1, 587, - 590, -1, 476, -1, 500, -1, -1, 4, -1, 505, - 4, -1, 506, 4, -1, 592, -1, 40, 777, -1, - 60, 589, -1, 106, -1, 272, 106, -1, 201, 591, - 589, -1, 250, 589, -1, 260, 589, -1, 272, 250, - -1, 272, 260, -1, 304, 59, 903, -1, 381, 265, - 903, -1, 400, 588, 589, -1, 356, -1, 356, 588, - 589, -1, 59, -1, -1, 899, -1, 505, 899, -1, - 506, 899, -1, 137, 580, 377, 542, 594, -1, 137, - 580, 377, 191, 152, 542, 594, -1, -1, 171, 3, - -1, 22, 596, -1, 52, 596, -1, 400, 596, -1, - 86, 596, -1, 143, 596, -1, 363, 596, -1, 479, - -1, 430, -1, -1, 452, 541, -1, 100, 644, 416, - 541, 514, 631, 515, 620, 612, -1, 100, 644, 416, - 191, 274, 152, 541, 514, 631, 515, 620, 612, -1, - 100, 294, 352, 644, 416, 541, 514, 631, 515, 620, - 612, -1, -1, 599, 624, -1, 639, -1, 984, -1, - 849, -1, 589, -1, 544, -1, 273, -1, 514, 587, - 515, -1, -1, 544, -1, 272, 25, -1, 357, -1, - 63, -1, 386, 279, -1, 386, 117, -1, 93, 896, - 605, -1, 605, -1, 619, -1, 80, 903, -1, 274, - 279, -1, 279, -1, 445, 630, -1, 328, 226, 630, - -1, 74, 514, 809, 515, 614, -1, 454, 88, 896, - -1, 117, 810, -1, 344, 541, 633, 642, 611, -1, - 468, -1, 406, -1, 606, -1, -1, 175, 645, 40, - 190, 601, -1, 175, 645, 40, 514, 809, 515, 607, - -1, 40, 514, 809, 515, 607, -1, 623, 602, -1, - 289, 451, 603, -1, 610, -1, 635, -1, 610, 635, - -1, 635, 610, -1, -1, 289, 86, 137, -1, 289, - 86, 122, 366, -1, 289, 86, 327, 366, -1, -1, - 514, 617, 515, -1, 272, 204, -1, -1, 93, 896, - 640, -1, 640, -1, 85, -1, 94, -1, 118, -1, - 190, -1, 203, -1, 402, -1, 405, -1, 30, -1, - 636, -1, 617, 518, 636, -1, 454, 202, 627, -1, - 119, -1, 274, 119, -1, 206, 120, -1, 206, 194, - -1, 476, 613, -1, 476, 287, -1, 478, 287, -1, - -1, 514, 626, 515, -1, 622, 200, 616, -1, 622, - 149, 616, -1, -1, 548, -1, 274, 119, -1, 119, - -1, 206, 194, -1, 206, 120, -1, 274, 456, -1, - 272, 204, -1, 542, 774, 634, -1, 542, 773, 608, - 634, -1, 629, -1, 626, 518, 629, -1, 542, -1, - 625, -1, 643, -1, 615, -1, 548, 503, 600, -1, - 548, -1, 476, 621, -1, -1, 641, -1, 641, 518, - -1, -1, 542, -1, 514, 637, 515, -1, -1, 634, - 604, -1, -1, 289, 122, 603, -1, 548, 503, 600, - -1, 548, -1, 548, 516, 548, 503, 600, -1, 548, - 516, 548, -1, 632, -1, 637, 518, 632, -1, 637, - -1, 637, 518, -1, 774, -1, 900, 904, 509, 439, - -1, 387, 900, 904, 509, 439, -1, 74, 514, 809, - 515, 599, -1, 445, 514, 638, 515, 630, 599, -1, - 445, 618, 599, -1, 328, 226, 514, 638, 515, 630, - 599, -1, 328, 226, 618, 599, -1, 168, 226, 514, - 638, 515, 344, 541, 633, 642, 611, 599, -1, 628, - -1, 641, 518, 628, -1, 248, 172, -1, 248, 308, - -1, 248, 392, -1, -1, 236, 541, 622, -1, 422, - -1, 420, -1, 240, 422, -1, 240, 420, -1, 177, - 422, -1, 177, 420, -1, 448, -1, -1, 33, -1, - 59, 117, -1, 137, 647, 191, 152, 649, 650, -1, - 137, 647, 649, 650, -1, 137, 648, 191, 152, 893, - 650, -1, 137, 648, 893, 650, -1, 137, 651, 896, - 289, 903, 650, -1, 137, 651, 191, 152, 896, 289, - 903, 650, -1, 416, -1, 381, -1, 173, -1, 245, - -1, 245, 416, -1, 466, -1, 249, 466, -1, 202, - -1, 168, 416, -1, 81, -1, 97, -1, 370, -1, - 402, -1, 423, 374, 307, -1, 423, 374, 129, -1, - 423, 374, 421, -1, 423, 374, 90, -1, 439, -1, - 24, 251, -1, 146, 433, -1, 156, -1, 168, 107, - 480, -1, 334, -1, 384, -1, 903, -1, 649, 518, - 903, -1, 63, -1, 357, -1, -1, 319, -1, 367, - -1, 433, -1, 100, 644, 653, 541, 654, 40, 416, - 674, -1, 100, 644, 653, 191, 274, 152, 541, 654, - 40, 416, 674, -1, 100, 294, 352, 644, 653, 541, - 654, 40, 416, 674, -1, 100, 644, 653, 541, 654, - 40, 809, -1, 100, 644, 653, 191, 274, 152, 541, - 654, 40, 809, -1, 100, 294, 352, 644, 653, 541, - 654, 40, 809, -1, 173, -1, 245, -1, 514, 515, - -1, 514, 857, 515, -1, 556, 451, 955, 386, 569, - 741, 956, 562, -1, 98, 669, 541, 633, 667, 658, - 663, 672, 659, 588, 664, -1, 98, 514, 674, 515, - 428, 663, 672, 588, 664, -1, 98, 171, 108, 542, - 428, 542, 657, -1, -1, 514, 370, 515, -1, 514, - 107, 515, -1, 171, -1, 428, -1, 661, 124, 544, - -1, -1, 671, -1, 660, 518, 671, -1, 454, -1, - -1, 40, -1, -1, 333, -1, -1, 668, -1, 514, - 673, 515, -1, 937, -1, 589, -1, 815, -1, 507, - -1, 514, 660, 515, -1, 816, -1, -1, 548, 665, - -1, 476, 287, -1, -1, 668, 670, -1, -1, 55, - -1, -1, 55, -1, 287, -1, 170, -1, 123, 662, - 544, -1, 279, 662, 544, -1, 102, -1, 186, -1, - 336, 662, 544, -1, 145, 662, 544, -1, 167, 336, - 637, -1, 167, 336, 507, -1, 309, 59, 637, -1, - 309, 59, 507, -1, 167, 274, 279, 637, -1, 167, - 279, 637, -1, 141, 544, -1, 937, -1, 544, -1, - 403, -1, 404, -1, 3, 516, 542, -1, 3, -1, - 666, -1, 673, 518, 666, -1, 676, -1, 675, -1, - 514, 676, 515, -1, 514, 675, 515, -1, 514, 966, - 515, -1, 679, -1, 677, 699, -1, 677, 698, 732, - 705, -1, 677, 698, 704, 733, -1, 686, 677, -1, - 686, 677, 699, -1, 686, 677, 698, 732, 705, -1, - 686, 677, 698, 704, 733, -1, 679, -1, 675, -1, - 379, 696, 882, -1, -1, 379, 696, 882, 690, 741, - 767, 721, 730, 825, 731, 709, -1, 379, 695, 884, - 690, 741, 767, 721, 730, 825, 731, 709, -1, 171, - 742, 678, 690, 767, 721, 730, 825, 731, 709, -1, - 171, 742, 379, 695, 884, 690, 767, 721, 730, 825, - 731, 709, -1, 740, -1, 416, 761, -1, 677, 444, - 693, 694, 677, -1, 677, 444, 693, 677, -1, 677, - 217, 693, 677, -1, 677, 147, 693, 677, -1, 681, - 744, 454, 884, -1, 681, 744, 454, 884, 180, 59, - 895, -1, 681, 744, 180, 59, 895, -1, 681, 744, - 289, 685, -1, 681, 744, 289, 685, 180, 59, 895, - -1, 681, 744, 289, 685, 454, 884, -1, 681, 744, - 289, 685, 454, 884, 180, 59, 895, -1, 682, 744, - 289, 884, 219, 265, 896, 680, 895, -1, 682, 744, - 289, 884, -1, 459, -1, 460, -1, 314, -1, 316, - -1, 449, -1, 315, -1, 810, -1, 810, 198, 514, - 676, 515, -1, 747, -1, 683, -1, 684, 518, 683, - -1, 684, -1, 684, 518, -1, 476, 687, -1, 500, - 687, -1, 476, 342, 687, -1, 688, -1, 687, 518, - 688, -1, 896, 905, 40, 689, 514, 910, 515, -1, - 249, -1, 274, 249, -1, -1, 219, 691, -1, -1, - 422, 692, 541, -1, 420, 692, 541, -1, 240, 422, - 692, 541, -1, 240, 420, 692, 541, -1, 177, 422, - 692, 541, -1, 177, 420, 692, 541, -1, 448, 692, - 541, -1, 416, 541, -1, 541, -1, 416, -1, -1, - 30, -1, 132, -1, -1, 59, 265, -1, 132, -1, - 132, 289, 514, 855, 515, -1, 30, -1, -1, 192, - 281, -1, 355, 281, -1, -1, 699, -1, -1, 295, - 59, 700, -1, 295, 59, 30, 702, 703, -1, 701, - -1, 700, 518, 701, -1, 809, 454, 849, 703, -1, - 809, 702, 703, -1, 41, -1, 126, -1, -1, 499, - 163, -1, 499, 230, -1, -1, 706, 707, -1, 707, - 706, -1, 706, -1, 707, -1, 704, -1, -1, 237, - 715, -1, 237, 715, 518, 716, -1, 161, 720, 717, - 719, 290, -1, 161, 720, 719, 290, -1, 286, 716, - -1, 286, 717, 719, -1, 4, 509, -1, 9, 509, - -1, 4, 312, -1, 9, 312, -1, 9, -1, 9, - 366, -1, 454, 368, 711, -1, -1, 542, -1, -1, - 710, 514, 708, 515, 714, -1, 708, -1, 708, 514, - 542, 515, -1, 708, 514, 542, 518, 9, 515, -1, - 418, 711, -1, 712, -1, -1, 351, 514, 9, 515, - -1, -1, 809, -1, 30, -1, 809, 509, -1, 4, - 312, -1, 9, 312, -1, 809, -1, 811, -1, 505, - 718, -1, 506, 718, -1, 899, -1, 4, -1, 365, - -1, 366, -1, 163, -1, 271, -1, 180, 59, 723, - -1, 180, 59, 30, -1, -1, 724, -1, 722, 518, - 724, -1, 722, -1, 722, 518, -1, 809, -1, 725, - -1, 727, -1, 726, -1, 728, -1, 514, 515, -1, - 364, 514, 855, 515, -1, 103, 514, 855, 515, -1, - 181, 388, 514, 723, 515, -1, 181, -1, 182, -1, - 185, 809, -1, -1, 335, 809, -1, -1, 734, -1, - 166, 338, 290, -1, 732, -1, -1, 735, -1, 734, - 735, -1, 736, 737, 738, -1, 166, 451, -1, 166, - 272, 226, 451, -1, 166, 389, -1, 166, 226, 389, - -1, 284, 892, -1, -1, 278, -1, 393, 243, -1, - -1, 460, 514, 855, 515, -1, 739, 518, 514, 855, - 515, -1, 739, -1, 739, 518, -1, 171, 743, -1, - -1, 744, -1, 742, 518, 744, -1, 742, -1, 742, - 518, -1, 761, 756, 713, -1, 762, 757, 713, -1, - 740, 755, 713, -1, 231, 762, 757, -1, 675, 756, - 713, -1, 231, 675, 756, -1, 754, -1, 514, 754, - 515, 755, -1, 744, 314, 514, 884, 166, 750, 745, - 515, 756, -1, 744, 449, 746, 514, 751, 166, 753, - 515, 756, -1, 180, 59, 894, -1, -1, 199, 281, - -1, 148, 281, -1, -1, 810, 198, 514, 884, 515, - -1, 810, 198, 543, -1, -1, 812, -1, 814, -1, - 514, 853, 515, -1, 748, 198, 514, 884, 515, -1, - 748, 198, 543, -1, 749, -1, 750, 749, -1, 543, - -1, 514, 894, 515, -1, 751, 198, 514, 884, 515, - -1, 752, -1, 753, 752, -1, 514, 754, 515, -1, - 744, 101, 224, 744, -1, 744, 758, 224, 744, 760, - -1, 744, 224, 744, 760, -1, 744, 268, 758, 224, - 744, -1, 744, 268, 224, 744, -1, 744, 42, 758, - 224, 744, 760, -1, 744, 42, 224, 744, 760, -1, - 744, 321, 224, 744, -1, 744, 37, 224, 744, 760, - -1, 744, 380, 224, 744, 760, -1, 40, 543, 514, - 894, 515, -1, 40, 543, -1, 542, 514, 894, 515, - -1, 542, -1, 755, -1, -1, 755, -1, 40, 514, - 768, 515, -1, 40, 543, 514, 768, 515, -1, 542, - 514, 768, 515, -1, -1, 172, 759, -1, 234, 759, - -1, 361, 759, -1, 380, -1, 37, -1, 208, -1, - 299, -1, -1, 454, 514, 894, 515, -1, 289, 809, - -1, 541, -1, 541, 507, -1, 290, 541, -1, 290, - 514, 541, 515, -1, 819, 766, -1, 366, 171, 514, - 764, 515, 766, -1, 819, 765, -1, 763, -1, 764, - 518, 763, -1, 40, 514, 768, 515, -1, -1, 500, - 296, -1, -1, 473, 809, -1, -1, 769, -1, 768, - 518, 769, -1, 543, 774, 770, -1, 80, 903, -1, - -1, 542, 774, -1, 771, 518, 542, 774, -1, 365, - -1, 409, -1, 774, -1, -1, 777, 776, -1, 387, - 777, 776, -1, 777, 39, 512, 899, 513, -1, 387, - 777, 39, 512, 899, 513, -1, 777, 39, -1, 387, - 777, 39, -1, 775, -1, 772, 514, 771, 515, 776, - -1, 246, 514, 859, 515, 776, -1, 444, 514, 771, - 515, 776, -1, 3, 516, 3, -1, 775, 516, 3, - -1, 776, 512, 513, -1, 776, 512, 899, 513, -1, - -1, 779, -1, 781, -1, 783, -1, 787, -1, 793, - -1, 794, 808, -1, 794, 514, 899, 515, -1, 781, - -1, 784, -1, 788, -1, 793, -1, 902, 780, -1, - 514, 856, 515, -1, -1, 215, -1, 216, -1, 394, - -1, 54, -1, 339, -1, 164, 782, -1, 136, 324, - -1, 115, 780, -1, 112, 780, -1, 282, 780, -1, - 57, -1, 514, 899, 515, -1, -1, 785, -1, 786, - -1, 785, -1, 786, -1, 56, 792, 514, 855, 515, - -1, 56, 792, -1, 789, -1, 790, -1, 789, -1, - 790, -1, 791, 514, 899, 515, -1, 791, -1, 72, - 792, -1, 71, 792, -1, 461, -1, 267, 72, 792, - -1, 267, 71, 792, -1, 269, 792, -1, 463, -1, - -1, 427, 514, 899, 515, 795, -1, 427, 795, -1, - 426, 514, 899, 515, 795, -1, 426, 795, -1, 218, - -1, 500, 426, 497, -1, 478, 426, 497, -1, -1, - 494, -1, 495, -1, 262, -1, 263, -1, 109, -1, - 110, -1, 188, -1, 189, -1, 258, -1, 259, -1, - 375, -1, 376, -1, 256, -1, 257, -1, 252, -1, - 253, -1, 470, -1, 471, -1, 113, -1, 114, -1, - 69, -1, 68, -1, 255, -1, 254, -1, 796, -1, - 797, -1, 798, -1, 799, -1, 800, -1, 801, -1, - 802, -1, 803, -1, 804, -1, 805, -1, 806, -1, - 807, -1, 796, 428, 797, -1, 798, 428, 799, -1, - 798, 428, 800, -1, 798, 428, 801, -1, 799, 428, - 800, -1, 799, 428, 801, -1, 800, 428, 801, -1, - -1, 811, -1, 809, 11, 774, -1, 809, 80, 903, - -1, 809, 46, 426, 497, 809, -1, 505, 809, -1, - 506, 809, -1, 809, 505, 809, -1, 809, 506, 809, - -1, 809, 507, 809, -1, 809, 508, 809, -1, 809, - 15, 809, -1, 809, 509, 809, -1, 809, 510, 809, - -1, 809, 16, 809, -1, 809, 501, 809, -1, 809, - 502, 809, -1, 809, 503, 809, -1, 809, 19, 809, - -1, 809, 20, 809, -1, 809, 21, 809, -1, 809, - 848, 809, -1, 848, 809, -1, 809, 848, -1, 809, - 36, 809, -1, 809, 294, 809, -1, 274, 809, -1, - 498, 809, -1, 809, 176, 809, -1, 809, 236, 809, - -1, 809, 236, 809, 145, 809, -1, 809, 498, 236, - 809, -1, 809, 498, 236, 809, 145, 809, -1, 809, - 193, 809, -1, 809, 193, 809, 145, 809, -1, 809, - 498, 193, 809, -1, 809, 498, 193, 809, 145, 809, - -1, 809, 391, 428, 809, -1, 809, 391, 428, 809, - 145, 809, -1, 809, 498, 391, 428, 809, -1, 809, - 498, 391, 428, 809, 145, 809, -1, 809, 221, 279, - -1, 809, 222, -1, 809, 221, 274, 279, -1, 809, - 274, 279, -1, 809, 277, -1, 809, 17, 809, -1, - 809, 18, 809, -1, 837, 301, 837, -1, 809, 221, - 435, -1, 809, 221, 274, 435, -1, 809, 221, 159, - -1, 809, 221, 274, 159, -1, 809, 221, 446, -1, - 809, 221, 274, 446, -1, 809, 221, 132, 171, 809, - -1, 809, 221, 274, 132, 171, 809, -1, 809, 221, - 284, 514, 859, 515, -1, 809, 221, 274, 284, 514, - 859, 515, -1, 809, 53, 881, 810, 36, 809, -1, - 809, 498, 53, 881, 810, 36, 809, -1, 809, 53, - 413, 810, 36, 809, -1, 809, 498, 53, 413, 810, - 36, 809, -1, 809, 198, 869, -1, 809, 498, 198, - 869, -1, 809, 850, 845, 675, -1, 809, 850, 845, - 514, 809, 515, -1, 117, -1, 83, 514, 809, 515, - -1, 507, 887, 891, -1, 542, 516, 507, 887, 891, - -1, 811, -1, 810, 11, 774, -1, 505, 810, -1, - 506, 810, -1, 810, 505, 810, -1, 810, 506, 810, - -1, 810, 507, 810, -1, 810, 508, 810, -1, 810, - 15, 810, -1, 810, 509, 810, -1, 810, 510, 810, - -1, 810, 16, 810, -1, 810, 501, 810, -1, 810, - 502, 810, -1, 810, 503, 810, -1, 810, 19, 810, - -1, 810, 20, 810, -1, 810, 21, 810, -1, 810, - 848, 810, -1, 848, 810, -1, 810, 848, -1, 810, - 221, 132, 171, 810, -1, 810, 221, 274, 132, 171, - 810, -1, 810, 221, 284, 514, 859, 515, -1, 810, - 221, 274, 284, 514, 859, 515, -1, 812, -1, 813, - 880, -1, 875, -1, 898, -1, 675, -1, 675, 545, - -1, 152, 675, -1, 729, 514, 855, 515, -1, 514, - 809, 515, -1, 814, -1, 837, -1, 519, -1, 10, - -1, 816, -1, 246, 520, 844, 521, -1, 818, -1, - 870, -1, 815, -1, 821, -1, 39, 675, -1, 39, - 512, 856, 513, -1, 522, 9, -1, 523, 548, -1, - 512, 856, 513, -1, 520, 840, 521, -1, 897, 514, - 515, -1, 897, 514, 857, 698, 697, 515, -1, 897, - 514, 462, 858, 698, 697, 515, -1, 897, 514, 857, - 518, 462, 858, 698, 697, 515, -1, 897, 514, 30, - 857, 698, 697, 515, -1, 897, 514, 132, 857, 698, - 697, 515, -1, 817, 822, 823, 824, 828, -1, 820, - -1, 817, -1, 820, -1, 81, 166, 514, 809, 515, - -1, 66, 514, 809, 40, 774, 515, -1, 438, 514, - 809, 40, 774, 515, -1, 158, 514, 860, 515, -1, - 302, 514, 862, 515, -1, 320, 514, 864, 515, -1, - 411, 514, 865, 515, -1, 432, 514, 809, 40, 774, - 515, -1, 434, 514, 58, 868, 515, -1, 434, 514, - 232, 868, 515, -1, 434, 514, 429, 868, 515, -1, - 434, 514, 868, 515, -1, 280, 514, 809, 518, 809, - 515, -1, 79, 514, 855, 515, -1, 512, 809, 166, - 542, 198, 809, 513, -1, 512, 809, 166, 542, 198, - 811, 191, 809, 513, -1, 477, 180, 514, 699, 515, - -1, -1, 162, 514, 473, 809, 515, -1, 162, 514, - 809, 515, -1, -1, 155, -1, -1, 475, 826, -1, - -1, 827, -1, 826, 518, 827, -1, 542, 40, 829, - -1, 300, 829, -1, 300, 542, -1, -1, 514, 830, - 831, 698, 832, 515, -1, 542, -1, -1, 309, 59, - 854, -1, -1, 337, 833, 835, -1, 366, 833, 835, - -1, 183, 833, 835, -1, -1, 834, -1, 53, 834, - 36, 834, -1, 441, 323, -1, 441, 165, -1, 104, - 365, -1, 809, 323, -1, 809, 165, -1, 148, 104, - 365, -1, 148, 180, -1, 148, 425, -1, 148, 272, - 297, -1, -1, 365, 514, 855, 515, -1, 365, 514, - 515, -1, 836, -1, 514, 854, 518, 809, 515, -1, - 543, 524, 809, -1, 838, -1, 839, 518, 838, -1, - 839, -1, 839, 518, -1, 809, 524, 809, -1, 841, - -1, 842, 518, 841, -1, 842, -1, 842, 518, -1, - 843, -1, -1, 38, -1, 396, -1, 30, -1, 8, - -1, 847, -1, 505, -1, 506, -1, 507, -1, 508, - -1, 15, -1, 509, -1, 510, -1, 16, -1, 501, - -1, 502, -1, 503, -1, 19, -1, 20, -1, 21, - -1, 8, -1, 291, 514, 851, 515, -1, 846, -1, - 291, 514, 851, 515, -1, 846, -1, 291, 514, 851, - 515, -1, 236, -1, 498, 236, -1, 176, -1, 498, - 176, -1, 193, -1, 498, 193, -1, 846, -1, 542, - 516, 851, -1, 811, -1, 852, 518, 811, -1, 852, - -1, 852, 518, -1, 809, -1, 854, 518, 809, -1, - 854, -1, 854, 518, -1, 855, -1, -1, 858, -1, - 857, 518, 858, -1, 809, -1, 906, 13, 809, -1, - 906, 14, 809, -1, 774, -1, 859, 518, 774, -1, - 861, 171, 809, -1, -1, 3, -1, 796, -1, 797, - -1, 798, -1, 799, -1, 800, -1, 801, -1, 802, - -1, 803, -1, 804, -1, 805, -1, 806, -1, 807, - -1, 544, -1, 809, 863, 866, 867, -1, 809, 863, - 866, -1, 317, 809, -1, 810, 198, 810, -1, -1, - 809, 866, 867, -1, 809, 867, 866, -1, 809, 866, - -1, 809, 867, -1, 854, -1, -1, 171, 809, -1, - 166, 809, -1, 809, 171, 855, -1, 171, 855, -1, - 855, -1, 675, -1, 514, 855, 515, -1, 65, 874, - 871, 873, 143, -1, 872, -1, 871, 872, -1, 472, - 809, 424, 809, -1, 139, 809, -1, -1, 809, -1, - -1, 542, -1, 542, 545, -1, 512, 809, 513, -1, - 512, 876, 524, 876, 513, -1, 512, 876, 524, 876, - 524, 876, 513, -1, 512, 876, 524, 506, 524, 876, - 513, -1, 809, -1, -1, -1, 877, 546, -1, -1, - 514, 515, -1, 514, 857, 515, -1, 516, 547, 878, - -1, 512, 809, 513, -1, 512, 876, 524, 876, 513, - -1, 512, 876, 524, 876, 524, 876, 513, -1, 512, - 876, 524, 506, 524, 876, 513, -1, -1, 880, 879, - -1, 45, -1, -1, 884, -1, -1, 885, -1, 883, - 518, 885, -1, 883, -1, 883, 518, -1, 809, 40, - 907, -1, 809, 3, -1, 809, -1, 148, 514, 894, - 515, -1, 148, 542, -1, 886, -1, -1, 809, 40, - 542, -1, 888, -1, 889, 518, 888, -1, 889, -1, - 889, 518, -1, 352, 514, 890, 515, -1, 352, 888, - -1, -1, 541, -1, 892, 518, 541, -1, 896, -1, - 893, 518, 896, -1, 893, -1, 893, 518, -1, 894, - -1, 514, 894, 515, -1, 543, -1, 901, -1, 542, - 545, -1, 899, -1, 4, -1, 544, 877, -1, 6, - -1, 7, -1, 897, 544, -1, 897, 514, 857, 698, - 697, 515, 544, -1, 778, 544, -1, 794, 514, 809, - 515, 808, -1, 794, 899, 808, -1, 794, 544, 808, - -1, 435, -1, 159, -1, 279, -1, 9, -1, 3, - -1, 978, -1, 983, -1, 3, -1, 978, -1, 980, - -1, 3, -1, 978, -1, 981, -1, 542, -1, 542, - 904, -1, 516, 547, -1, 904, 516, 547, -1, 514, - 894, 515, -1, -1, 900, -1, 548, -1, 5, -1, - 325, 896, 909, 40, 910, -1, 514, 859, 515, -1, - -1, 674, -1, 551, -1, 655, -1, 656, -1, 954, - -1, 966, -1, 100, 370, 541, 912, -1, 100, 370, - 191, 274, 152, 541, 912, -1, 100, 294, 352, 370, - 541, 912, -1, 912, 913, -1, -1, 598, -1, 914, - -1, 576, -1, 973, -1, 100, 920, 202, 917, 918, - 289, 541, 916, 514, 570, 515, 919, 767, -1, 100, - 920, 202, 917, 191, 274, 152, 627, 289, 541, 916, - 514, 570, 515, 919, 767, -1, 542, -1, 454, 915, - -1, -1, 89, -1, -1, 627, -1, -1, 476, 613, - -1, -1, 445, -1, -1, 32, 416, 761, 386, 370, - 896, -1, 32, 416, 191, 152, 761, 386, 370, 896, - -1, 32, 381, 541, 386, 370, 896, -1, 32, 381, - 191, 152, 541, 386, 370, 896, -1, 32, 466, 541, - 386, 370, 896, -1, 32, 466, 191, 152, 541, 386, - 370, 896, -1, 167, 75, 923, -1, 75, 923, -1, - 542, -1, -1, 84, 289, 926, 541, 221, 925, -1, - 84, 289, 82, 809, 221, 925, -1, 544, -1, 279, - -1, 416, -1, 381, -1, 173, -1, 245, -1, 245, - 416, -1, 466, -1, 108, -1, 202, -1, 370, -1, - 439, -1, 154, 108, 544, 664, -1, 154, 108, 542, - 428, 544, 664, -1, 197, 108, 544, -1, 153, 932, - -1, 153, 936, 930, 932, -1, 153, 464, 932, -1, - 153, 514, 935, 515, 932, -1, 464, -1, -1, 937, - -1, 589, -1, -1, 921, -1, 586, -1, 529, -1, - 972, -1, 922, -1, 656, -1, 975, -1, 652, -1, - 911, -1, 576, -1, 598, -1, 572, -1, 540, -1, - 954, -1, 646, -1, 582, -1, 914, -1, 551, -1, - 946, -1, 575, -1, 908, -1, 549, -1, 674, -1, - 595, -1, 655, -1, 949, -1, 963, -1, 940, -1, - 966, -1, 973, -1, 3, -1, 978, -1, 982, -1, - 933, -1, 544, -1, 938, -1, 935, 518, 938, -1, - 35, -1, 34, -1, 435, -1, 159, -1, 289, -1, - 934, -1, 939, 931, -1, 933, -1, 936, -1, 386, - 941, -1, 386, 240, 941, -1, 386, 385, 941, -1, - 386, 177, 941, -1, 942, -1, 970, 171, 104, -1, - 426, 497, 944, -1, 370, 544, -1, 970, 428, 945, - -1, 970, 503, 945, -1, 809, -1, 544, -1, 3, - -1, 794, 544, 808, -1, 794, 514, 899, 515, 544, - -1, 589, -1, 117, -1, 240, -1, 943, -1, 945, - 518, 943, -1, 239, 947, -1, 213, 947, -1, 167, - 213, 947, -1, 213, 947, 171, 948, -1, 167, 213, - 947, 171, 948, -1, 544, -1, 542, -1, 544, -1, - 542, -1, 455, 951, 953, 930, -1, 455, 951, 953, - 930, 541, 905, -1, 455, 951, 953, 930, 958, -1, - 455, 514, 952, 515, -1, 455, 514, 952, 515, 541, - 905, -1, 936, -1, 464, -1, 170, -1, 172, -1, - 3, -1, 172, -1, -1, 950, -1, 952, 518, 950, - -1, 170, -1, -1, 556, 122, 171, 955, 957, 956, - 562, -1, 436, 692, 955, -1, 761, -1, 761, 542, - -1, 761, 40, 542, -1, 473, 809, -1, -1, 454, - 743, -1, -1, 936, 930, -1, 936, 930, 541, 905, - -1, 47, 961, 544, 962, 664, -1, 47, 191, 274, - 152, 961, 544, 962, 664, -1, 128, 548, -1, 128, - 108, 548, -1, 128, 108, 191, 152, 548, -1, 108, - -1, -1, 40, 542, -1, -1, 354, 965, -1, 354, - 240, 965, -1, 354, 385, 965, -1, 354, 177, 965, - -1, 970, -1, 30, -1, 964, -1, 426, 497, -1, - 430, 223, 235, -1, 968, 674, -1, 412, 674, -1, - 412, 971, -1, 968, 971, -1, 968, 426, 497, -1, - 968, 430, 223, 235, -1, 968, 30, 969, -1, 968, - -1, 127, -1, 126, -1, 390, -1, 967, -1, 417, - -1, -1, 542, -1, 970, 516, 542, -1, 542, -1, - 971, 516, 542, -1, 61, 817, -1, 100, 644, 466, - 541, 633, 919, 40, 674, 974, -1, 100, 644, 466, - 191, 274, 152, 541, 633, 919, 40, 674, 974, -1, - 100, 294, 352, 644, 466, 541, 633, 919, 40, 674, - 974, -1, 100, 644, 342, 466, 541, 514, 637, 515, - 919, 40, 674, 974, -1, 100, 294, 352, 644, 342, - 466, 541, 514, 637, 515, 919, 40, 674, 974, -1, - 476, 74, 292, -1, 476, 64, 74, 292, -1, 476, - 240, 74, 292, -1, -1, 100, 644, 416, 977, 40, - 674, 976, -1, 100, 644, 416, 191, 274, 152, 977, - 40, 674, 976, -1, 100, 294, 352, 644, 416, 977, - 40, 674, 976, -1, 476, 107, -1, 476, 272, 107, - -1, -1, 541, 633, 620, 612, -1, 22, -1, 23, - -1, 24, -1, 25, -1, 26, -1, 27, -1, 28, - -1, 29, -1, 31, -1, 32, -1, 33, -1, 43, - -1, 44, -1, 46, -1, 47, -1, 48, -1, 50, - -1, 51, -1, 52, -1, 59, -1, 60, -1, 61, - -1, 62, -1, 63, -1, 64, -1, 67, -1, 68, - -1, 69, -1, 70, -1, 73, -1, 75, -1, 76, - -1, 77, -1, 78, -1, 84, -1, 85, -1, 86, - -1, 87, -1, 88, -1, 90, -1, 91, -1, 92, - -1, 94, -1, 95, -1, 96, -1, 97, -1, 98, - -1, 99, -1, 102, -1, 103, -1, 104, -1, 105, - -1, 106, -1, 107, -1, 108, -1, 109, -1, 110, - -1, 111, -1, 113, -1, 114, -1, 116, -1, 118, - -1, 120, -1, 121, -1, 122, -1, 123, -1, 124, - -1, 125, -1, 128, -1, 129, -1, 130, -1, 131, - -1, 134, -1, 135, -1, 136, -1, 137, -1, 138, - -1, 140, -1, 141, -1, 142, -1, 144, -1, 145, - -1, 146, -1, 148, -1, 149, -1, 150, -1, 151, - -1, 153, -1, 154, -1, 155, -1, 156, -1, 157, - -1, 160, -1, 162, -1, 163, -1, 165, -1, 167, - -1, 169, -1, 173, -1, 174, -1, 177, -1, 179, - -1, 183, -1, 184, -1, 186, -1, 187, -1, 188, - -1, 189, -1, 190, -1, 191, -1, 192, -1, 194, - -1, 195, -1, 196, -1, 197, -1, 199, -1, 200, - -1, 201, -1, 202, -1, 203, -1, 204, -1, 205, - -1, 207, -1, 210, -1, 211, -1, 212, -1, 213, - -1, 214, -1, 220, -1, 223, -1, 225, -1, 226, - -1, 227, -1, 228, -1, 229, -1, 230, -1, 233, - -1, 235, -1, 238, -1, 239, -1, 240, -1, 241, - -1, 242, -1, 243, -1, 244, -1, 245, -1, 247, - -1, 248, -1, 249, -1, 250, -1, 251, -1, 252, - -1, 253, -1, 254, -1, 255, -1, 256, -1, 257, - -1, 258, -1, 259, -1, 260, -1, 261, -1, 262, - -1, 263, -1, 264, -1, 265, -1, 266, -1, 270, - -1, 271, -1, 272, -1, 275, -1, 276, -1, 278, - -1, 281, -1, 283, -1, 284, -1, 285, -1, 287, - -1, 288, -1, 291, -1, 292, -1, 293, -1, 296, - -1, 297, -1, 300, -1, 303, -1, 304, -1, 305, - -1, 306, -1, 307, -1, 308, -1, 309, -1, 310, - -1, 311, -1, 312, -1, 313, -1, 318, -1, 319, - -1, 322, -1, 323, -1, 325, -1, 326, -1, 327, - -1, 329, -1, 330, -1, 331, -1, 332, -1, 333, - -1, 334, -1, 336, -1, 337, -1, 338, -1, 340, - -1, 341, -1, 342, -1, 343, -1, 345, -1, 346, - -1, 347, -1, 348, -1, 349, -1, 350, -1, 351, - -1, 352, -1, 353, -1, 354, -1, 355, -1, 356, - -1, 357, -1, 359, -1, 360, -1, 362, -1, 363, - -1, 364, -1, 366, -1, 367, -1, 368, -1, 369, - -1, 370, -1, 371, -1, 372, -1, 373, -1, 374, - -1, 375, -1, 376, -1, 377, -1, 378, -1, 381, - -1, 382, -1, 383, -1, 384, -1, 385, -1, 386, - -1, 388, -1, 389, -1, 392, -1, 393, -1, 395, - -1, 397, -1, 398, -1, 399, -1, 400, -1, 401, - -1, 402, -1, 403, -1, 404, -1, 405, -1, 406, - -1, 407, -1, 408, -1, 410, -1, 414, -1, 415, - -1, 417, -1, 419, -1, 420, -1, 421, -1, 422, - -1, 423, -1, 425, -1, 430, -1, 431, -1, 433, - -1, 436, -1, 437, -1, 439, -1, 440, -1, 441, - -1, 442, -1, 443, -1, 446, -1, 447, -1, 448, - -1, 450, -1, 451, -1, 452, -1, 453, -1, 455, - -1, 456, -1, 457, -1, 458, -1, 459, -1, 463, - -1, 465, -1, 466, -1, 467, -1, 468, -1, 469, - -1, 470, -1, 471, -1, 474, -1, 477, -1, 478, - -1, 479, -1, 480, -1, 481, -1, 482, -1, 494, - -1, 495, -1, 496, -1, 497, -1, 53, -1, 54, - -1, 56, -1, 57, -1, 71, -1, 72, -1, 79, - -1, 83, -1, 112, -1, 115, -1, 152, -1, 158, - -1, 164, -1, 175, -1, 181, -1, 182, -1, 209, - -1, 215, -1, 216, -1, 218, -1, 246, -1, 267, - -1, 269, -1, 273, -1, 280, -1, 282, -1, 298, - -1, 302, -1, 320, -1, 324, -1, 339, -1, 365, - -1, 387, -1, 394, -1, 409, -1, 411, -1, 426, - -1, 427, -1, 432, -1, 434, -1, 438, -1, 460, - -1, 461, -1, 483, -1, 484, -1, 485, -1, 486, - -1, 487, -1, 488, -1, 489, -1, 490, -1, 491, - -1, 492, -1, 493, -1, 42, -1, 49, -1, 55, - -1, 81, -1, 89, -1, 101, -1, 170, -1, 172, - -1, 175, -1, 176, -1, 193, -1, 208, -1, 221, - -1, 222, -1, 224, -1, 234, -1, 236, -1, 246, - -1, 268, -1, 277, -1, 299, -1, 301, -1, 321, - -1, 361, -1, 391, -1, 409, -1, 418, -1, 464, - -1, 37, -1, 42, -1, 49, -1, 55, -1, 81, - -1, 83, -1, 89, -1, 101, -1, 170, -1, 172, - -1, 176, -1, 193, -1, 208, -1, 221, -1, 222, - -1, 224, -1, 234, -1, 236, -1, 268, -1, 277, - -1, 299, -1, 301, -1, 321, -1, 361, -1, 380, - -1, 391, -1, 418, -1, 438, -1, 464, -1, 37, - -1, 42, -1, 49, -1, 53, -1, 54, -1, 55, - -1, 56, -1, 57, -1, 72, -1, 71, -1, 79, - -1, 81, -1, 83, -1, 89, -1, 101, -1, 112, - -1, 115, -1, 152, -1, 158, -1, 164, -1, 170, - -1, 172, -1, 175, -1, 176, -1, 181, -1, 182, - -1, 193, -1, 208, -1, 209, -1, 216, -1, 218, - -1, 215, -1, 221, -1, 222, -1, 224, -1, 234, - -1, 236, -1, 246, -1, 267, -1, 268, -1, 269, - -1, 273, -1, 277, -1, 280, -1, 282, -1, 299, - -1, 298, -1, 301, -1, 302, -1, 320, -1, 321, - -1, 324, -1, 339, -1, 361, -1, 365, -1, 380, - -1, 387, -1, 391, -1, 394, -1, 409, -1, 411, - -1, 418, -1, 426, -1, 427, -1, 432, -1, 434, - -1, 438, -1, 460, -1, 461, -1, 464, -1, 483, - -1, 484, -1, 485, -1, 486, -1, 487, -1, 488, - -1, 489, -1, 490, -1, 491, -1, 492, -1, 493, - -1, 37, -1, 42, -1, 49, -1, 55, -1, 81, - -1, 83, -1, 89, -1, 101, -1, 170, -1, 172, - -1, 175, -1, 176, -1, 193, -1, 208, -1, 221, - -1, 222, -1, 224, -1, 234, -1, 236, -1, 246, - -1, 268, -1, 277, -1, 299, -1, 301, -1, 321, - -1, 361, -1, 380, -1, 391, -1, 409, -1, 418, - -1, 438, -1, 464, -1, 30, -1, 34, -1, 35, - -1, 36, -1, 38, -1, 39, -1, 40, -1, 41, - -1, 45, -1, 58, -1, 65, -1, 66, -1, 74, - -1, 80, -1, 82, -1, 93, -1, 100, -1, 117, - -1, 119, -1, 126, -1, 127, -1, 132, -1, 133, - -1, 139, -1, 143, -1, 147, -1, 159, -1, 161, - -1, 166, -1, 168, -1, 171, -1, 178, -1, 180, - -1, 185, -1, 198, -1, 206, -1, 217, -1, 219, - -1, 231, -1, 232, -1, 237, -1, 274, -1, 279, - -1, 286, -1, 289, -1, 290, -1, 294, -1, 295, - -1, 314, -1, 315, -1, 316, -1, 317, -1, 328, - -1, 335, -1, 344, -1, 358, -1, 379, -1, 390, - -1, 396, -1, 412, -1, 413, -1, 416, -1, 424, - -1, 428, -1, 429, -1, 435, -1, 444, -1, 445, - -1, 449, -1, 454, -1, 462, -1, 472, -1, 473, - -1, 475, -1, 476, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = +/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_int16 yyrline[] = { - 0, 502, 502, 518, 530, 539, 540, 541, 542, 543, - 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, - 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, - 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, - 574, 575, 576, 577, 578, 580, 9, 18, 27, 36, - 45, 54, 63, 72, 85, 87, 93, 94, 99, 103, - 107, 118, 126, 130, 139, 148, 157, 166, 175, 184, - 192, 200, 209, 218, 227, 236, 253, 262, 271, 280, - 290, 303, 318, 327, 335, 350, 358, 368, 378, 385, - 392, 400, 407, 418, 419, 424, 428, 433, 438, 446, - 447, 452, 456, 457, 458, 7, 13, 19, 25, 9, - 13, 44, 45, 46, 50, 51, 55, 59, 60, 64, - 70, 75, 76, 77, 78, 6, 15, 25, 35, 45, - 55, 65, 75, 85, 95, 106, 117, 127, 140, 141, - 9, 23, 29, 36, 42, 49, 59, 63, 71, 72, - 73, 77, 86, 95, 102, 103, 108, 120, 125, 150, - 155, 160, 166, 176, 186, 192, 203, 214, 229, 230, - 236, 237, 242, 243, 249, 250, 254, 255, 260, 262, - 268, 269, 273, 274, 277, 278, 283, 7, 16, 25, - 46, 47, 50, 54, 7, 14, 22, 9, 19, 29, - 42, 43, 7, 17, 27, 40, 41, 45, 46, 47, - 51, 52, 7, 14, 31, 51, 55, 65, 69, 75, - 76, 9, 17, 29, 30, 34, 35, 36, 41, 42, - 43, 48, 52, 56, 60, 64, 68, 72, 76, 80, - 84, 88, 92, 97, 101, 105, 112, 113, 117, 118, - 119, 7, 16, 28, 29, 2, 9, 15, 21, 28, - 35, 45, 46, 47, 2, 7, 21, 36, 56, 57, - 84, 85, 86, 87, 88, 89, 93, 94, 99, 104, - 105, 106, 107, 108, 113, 120, 121, 122, 139, 146, - 153, 163, 173, 185, 193, 202, 220, 221, 225, 226, - 230, 239, 262, 276, 283, 288, 290, 292, 294, 297, - 300, 301, 302, 303, 308, 312, 313, 318, 325, 330, - 331, 332, 333, 334, 335, 336, 337, 343, 344, 348, - 353, 360, 367, 374, 386, 387, 388, 389, 393, 398, - 399, 400, 405, 410, 411, 412, 413, 414, 415, 420, - 440, 469, 470, 474, 478, 479, 480, 484, 488, 496, - 497, 502, 503, 504, 508, 516, 517, 522, 523, 527, - 532, 536, 540, 545, 553, 554, 558, 559, 563, 564, - 570, 581, 594, 608, 622, 636, 650, 673, 677, 684, - 688, 696, 701, 708, 718, 719, 720, 721, 722, 729, - 736, 737, 742, 743, 9, 19, 29, 39, 49, 59, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 95, 96, - 97, 98, 99, 100, 105, 106, 111, 112, 113, 118, - 119, 120, 8, 20, 33, 46, 58, 70, 86, 87, - 91, 95, 7, 1, 30, 49, 61, 62, 63, 67, - 68, 73, 77, 82, 86, 94, 95, 99, 100, 105, - 106, 110, 111, 116, 117, 118, 119, 120, 121, 122, - 127, 135, 139, 144, 145, 150, 154, 159, 163, 167, - 171, 175, 179, 183, 187, 191, 195, 199, 203, 207, - 211, 215, 219, 227, 232, 233, 234, 235, 236, 242, - 246, 47, 48, 52, 53, 54, 72, 73, 80, 88, - 96, 104, 112, 120, 131, 132, 159, 164, 172, 188, - 205, 222, 239, 240, 259, 263, 267, 271, 275, 285, - 296, 306, 315, 326, 337, 349, 364, 382, 382, 386, - 386, 390, 390, 394, 400, 407, 411, 412, 416, 417, - 431, 438, 445, 455, 456, 459, 472, 473, 474, 478, - 489, 497, 502, 507, 512, 517, 525, 533, 538, 543, - 550, 551, 555, 556, 557, 561, 568, 569, 573, 574, - 578, 579, 580, 584, 585, 589, 590, 606, 607, 610, - 619, 630, 631, 632, 635, 636, 637, 641, 642, 643, - 644, 648, 649, 653, 655, 671, 673, 678, 681, 689, - 693, 697, 701, 705, 709, 716, 721, 728, 729, 733, - 738, 742, 746, 754, 761, 762, 767, 768, 772, 773, - 778, 780, 782, 787, 807, 808, 810, 815, 816, 820, - 821, 824, 825, 850, 851, 856, 860, 861, 865, 866, - 870, 871, 872, 873, 874, 878, 891, 898, 905, 912, - 913, 917, 918, 922, 923, 927, 928, 932, 933, 937, - 938, 942, 953, 954, 955, 956, 960, 961, 966, 967, - 968, 977, 983, 992, 993, 1006, 1007, 1011, 1012, 1016, - 1017, 1023, 1029, 1037, 1046, 1054, 1063, 1072, 1076, 1081, - 1092, 1106, 1107, 1110, 1111, 1112, 1115, 1123, 1132, 1133, - 1134, 1135, 1138, 1146, 1155, 1159, 1166, 1167, 1171, 1180, - 1184, 1209, 1213, 1226, 1240, 1255, 1267, 1280, 1294, 1308, - 1321, 1336, 1355, 1361, 1366, 1372, 1379, 1380, 1388, 1392, - 1396, 1402, 1409, 1414, 1415, 1416, 1417, 1418, 1419, 1423, - 1424, 1436, 1437, 1442, 1449, 1456, 1463, 1495, 1506, 1519, - 1524, 1525, 1528, 1529, 1532, 1533, 1538, 1539, 1544, 1548, - 1554, 1575, 1583, 1596, 1599, 1603, 1603, 1606, 1607, 1609, - 1614, 1621, 1626, 1632, 1637, 1643, 1647, 1654, 1661, 1671, - 1672, 1676, 1678, 1681, 1685, 1686, 1687, 1688, 1689, 1690, - 1695, 1715, 1716, 1717, 1718, 1729, 1743, 1744, 1750, 1755, - 1760, 1765, 1770, 1775, 1780, 1785, 1791, 1797, 1803, 1810, - 1832, 1841, 1845, 1853, 1857, 1865, 1877, 1898, 1902, 1908, - 1912, 1925, 1933, 1943, 1945, 1947, 1949, 1951, 1953, 1958, - 1959, 1966, 1975, 1983, 1992, 2003, 2011, 2012, 2013, 2017, - 2017, 2020, 2020, 2023, 2023, 2026, 2026, 2029, 2029, 2032, - 2032, 2035, 2035, 2038, 2038, 2041, 2041, 2044, 2044, 2047, - 2047, 2050, 2050, 2053, 2055, 2057, 2059, 2061, 2063, 2065, - 2067, 2069, 2071, 2073, 2075, 2077, 2082, 2087, 2093, 2100, - 2105, 2111, 2117, 2148, 2150, 2152, 2160, 2175, 2177, 2179, - 2181, 2183, 2185, 2187, 2189, 2191, 2193, 2195, 2197, 2199, - 2201, 2203, 2205, 2208, 2210, 2212, 2215, 2217, 2219, 2221, - 2223, 2228, 2233, 2240, 2245, 2252, 2257, 2264, 2269, 2277, - 2285, 2293, 2301, 2319, 2327, 2335, 2343, 2351, 2359, 2367, - 2371, 2387, 2395, 2403, 2411, 2419, 2427, 2435, 2439, 2443, - 2447, 2451, 2459, 2467, 2475, 2483, 2503, 2525, 2536, 2543, - 2557, 2565, 2573, 2593, 2595, 2597, 2599, 2601, 2603, 2605, - 2607, 2609, 2611, 2613, 2615, 2617, 2619, 2621, 2623, 2625, - 2627, 2629, 2631, 2633, 2635, 2639, 2643, 2647, 2661, 2662, - 2676, 2677, 2678, 2689, 2713, 2724, 2734, 2738, 2742, 2749, - 2753, 2760, 2764, 2781, 2785, 2787, 2790, 2793, 2804, 2809, - 2816, 2822, 2828, 2837, 2841, 2848, 2856, 2864, 2875, 2895, - 2931, 2942, 2943, 2950, 2956, 2958, 2960, 2964, 2973, 2978, - 2985, 3000, 3007, 3011, 3015, 3019, 3023, 3033, 3042, 3064, - 3065, 3069, 3070, 3071, 3075, 3076, 3083, 3084, 3088, 3089, - 3094, 3102, 3104, 3118, 3121, 3148, 3149, 3152, 3153, 3161, - 3169, 3177, 3186, 3196, 3214, 3260, 3269, 3278, 3287, 3296, - 3308, 3309, 3310, 3311, 3312, 3326, 3327, 3330, 3331, 3335, - 3345, 3346, 3350, 3351, 3355, 3362, 3363, 3368, 3369, 3374, - 3375, 3378, 3379, 3380, 3383, 3384, 3387, 3388, 3389, 3390, - 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, - 3403, 3405, 3410, 3412, 3417, 3419, 3421, 3423, 3425, 3427, - 3429, 3431, 3445, 3447, 3452, 3456, 3463, 3468, 3474, 3478, - 3485, 3490, 3497, 3502, 3510, 3514, 3520, 3524, 3533, 3544, - 3545, 3549, 3553, 3560, 3561, 3562, 3563, 3564, 3565, 3566, - 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3583, 3587, 3594, - 3601, 3602, 3618, 3622, 3627, 3631, 3646, 3651, 3655, 3658, - 3661, 3662, 3663, 3666, 3673, 3683, 3697, 3698, 3702, 3713, - 3714, 3717, 3718, 3721, 3725, 3732, 3740, 3748, 3756, 3766, - 3767, 3772, 3773, 3777, 3778, 3779, 3783, 3792, 3800, 3808, - 3817, 3832, 3833, 3838, 3839, 3849, 3850, 3854, 3855, 3859, - 3860, 3863, 3879, 3887, 3897, 3898, 3901, 3902, 3905, 3909, - 3910, 3914, 3915, 3918, 3919, 3920, 3930, 3931, 3935, 3937, - 3943, 3944, 3948, 3949, 3952, 3963, 3966, 3977, 3981, 3985, - 3997, 4001, 4010, 4017, 4055, 4059, 4063, 4067, 4071, 4075, - 4079, 4085, 4102, 4103, 4104, 4107, 4108, 4109, 4112, 4113, - 4114, 4117, 4118, 4121, 4123, 4128, 4129, 4132, 4136, 4137, + 0, 506, 506, 522, 534, 543, 544, 545, 546, 547, + 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, + 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, + 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, + 578, 579, 580, 581, 582, 583, 585, 9, 18, 27, + 36, 45, 54, 63, 72, 85, 87, 93, 94, 99, + 103, 107, 118, 126, 130, 139, 148, 157, 166, 175, + 184, 192, 200, 209, 218, 227, 236, 253, 262, 271, + 280, 290, 303, 318, 327, 335, 350, 358, 368, 378, + 385, 392, 400, 407, 418, 419, 424, 428, 433, 438, + 446, 447, 452, 456, 457, 458, 7, 13, 19, 25, + 9, 13, 44, 45, 46, 50, 51, 55, 59, 60, + 64, 70, 75, 76, 77, 78, 6, 15, 25, 35, + 45, 55, 65, 75, 85, 95, 106, 117, 127, 140, + 141, 9, 23, 29, 36, 42, 49, 59, 63, 71, + 72, 73, 77, 86, 95, 102, 103, 108, 120, 125, + 150, 155, 160, 166, 176, 186, 192, 203, 214, 229, + 230, 236, 237, 242, 243, 249, 250, 254, 255, 260, + 262, 268, 269, 273, 274, 277, 278, 283, 7, 16, + 25, 46, 47, 50, 54, 7, 14, 22, 9, 19, + 29, 42, 43, 7, 17, 27, 40, 41, 45, 46, + 47, 51, 52, 7, 7, 14, 31, 51, 55, 65, + 69, 75, 76, 9, 17, 29, 30, 34, 35, 36, + 41, 42, 43, 48, 52, 56, 60, 64, 68, 72, + 76, 80, 84, 88, 92, 97, 101, 105, 112, 113, + 117, 118, 119, 7, 16, 28, 29, 2, 10, 17, + 24, 32, 40, 51, 52, 53, 57, 58, 59, 2, + 7, 21, 36, 56, 57, 84, 85, 86, 87, 88, + 89, 93, 94, 99, 104, 105, 106, 107, 108, 113, + 120, 121, 122, 139, 146, 153, 163, 173, 185, 193, + 202, 220, 221, 225, 226, 230, 239, 262, 276, 283, + 288, 290, 292, 294, 297, 300, 301, 302, 303, 308, + 312, 313, 318, 325, 330, 331, 332, 333, 334, 335, + 336, 337, 343, 344, 348, 353, 360, 367, 374, 386, + 387, 388, 389, 393, 398, 399, 400, 405, 410, 411, + 412, 413, 414, 415, 420, 440, 469, 470, 474, 478, + 479, 480, 484, 488, 496, 497, 502, 503, 504, 508, + 516, 517, 522, 523, 527, 532, 536, 540, 545, 553, + 554, 558, 559, 563, 564, 570, 581, 594, 608, 622, + 636, 650, 673, 677, 684, 688, 696, 701, 708, 718, + 719, 720, 721, 722, 729, 736, 737, 742, 743, 9, + 19, 29, 39, 49, 59, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 95, 96, 97, 98, 99, 100, 105, + 106, 111, 112, 113, 118, 119, 120, 8, 20, 33, + 46, 58, 70, 86, 87, 91, 95, 7, 1, 30, + 49, 61, 62, 63, 67, 68, 73, 77, 82, 86, + 94, 95, 99, 100, 105, 106, 110, 111, 116, 117, + 118, 119, 120, 121, 122, 127, 135, 139, 144, 145, + 150, 154, 159, 163, 167, 171, 175, 179, 183, 187, + 191, 195, 199, 203, 207, 211, 215, 219, 227, 232, + 233, 234, 235, 236, 242, 246, 47, 48, 52, 53, + 54, 72, 73, 80, 88, 96, 104, 112, 120, 131, + 132, 159, 164, 172, 188, 205, 222, 239, 240, 259, + 263, 267, 271, 275, 285, 296, 306, 315, 326, 337, + 349, 364, 382, 382, 386, 386, 390, 390, 394, 400, + 407, 411, 412, 416, 417, 431, 438, 445, 455, 456, + 459, 472, 473, 474, 478, 489, 497, 502, 507, 512, + 517, 525, 533, 538, 543, 550, 551, 555, 556, 557, + 561, 568, 569, 573, 574, 578, 579, 580, 584, 585, + 589, 590, 606, 607, 610, 619, 630, 631, 632, 635, + 636, 637, 641, 642, 643, 644, 648, 649, 653, 655, + 671, 673, 678, 681, 689, 693, 697, 701, 705, 709, + 716, 721, 728, 729, 733, 738, 742, 746, 754, 761, + 762, 767, 768, 772, 773, 778, 780, 782, 787, 807, + 808, 810, 815, 816, 820, 821, 824, 825, 850, 851, + 856, 860, 861, 865, 866, 870, 871, 872, 873, 874, + 878, 891, 898, 905, 912, 913, 917, 918, 922, 923, + 927, 928, 932, 933, 937, 938, 942, 953, 954, 955, + 956, 960, 961, 966, 967, 968, 977, 983, 992, 993, + 1006, 1007, 1011, 1012, 1016, 1017, 1023, 1029, 1037, 1046, + 1054, 1063, 1072, 1076, 1081, 1092, 1106, 1107, 1110, 1111, + 1112, 1115, 1123, 1132, 1133, 1134, 1135, 1138, 1146, 1155, + 1159, 1166, 1167, 1171, 1180, 1184, 1209, 1213, 1226, 1240, + 1255, 1267, 1280, 1294, 1308, 1321, 1336, 1355, 1361, 1366, + 1372, 1379, 1380, 1388, 1392, 1396, 1402, 1409, 1414, 1415, + 1416, 1417, 1418, 1419, 1423, 1424, 1436, 1437, 1442, 1449, + 1456, 1463, 1495, 1506, 1519, 1524, 1525, 1528, 1529, 1532, + 1533, 1538, 1539, 1544, 1548, 1554, 1575, 1583, 1596, 1599, + 1603, 1603, 1606, 1607, 1609, 1614, 1621, 1626, 1632, 1637, + 1643, 1647, 1654, 1661, 1671, 1672, 1676, 1678, 1681, 1685, + 1686, 1687, 1688, 1689, 1690, 1695, 1715, 1716, 1717, 1718, + 1729, 1743, 1744, 1750, 1755, 1760, 1765, 1770, 1775, 1780, + 1785, 1791, 1797, 1803, 1810, 1832, 1841, 1845, 1853, 1857, + 1865, 1877, 1898, 1902, 1908, 1912, 1925, 1933, 1943, 1945, + 1947, 1949, 1951, 1953, 1958, 1959, 1966, 1975, 1983, 1992, + 2003, 2011, 2012, 2013, 2017, 2017, 2020, 2020, 2023, 2023, + 2026, 2026, 2029, 2029, 2032, 2032, 2035, 2035, 2038, 2038, + 2041, 2041, 2044, 2044, 2047, 2047, 2050, 2050, 2053, 2053, + 2056, 2058, 2060, 2062, 2064, 2066, 2068, 2070, 2072, 2074, + 2076, 2078, 2080, 2082, 2087, 2092, 2098, 2105, 2110, 2116, + 2122, 2153, 2155, 2157, 2165, 2180, 2182, 2184, 2186, 2188, + 2190, 2192, 2194, 2196, 2198, 2200, 2202, 2204, 2206, 2208, + 2210, 2213, 2215, 2217, 2220, 2222, 2224, 2226, 2228, 2233, + 2238, 2245, 2250, 2257, 2262, 2269, 2274, 2282, 2290, 2298, + 2306, 2324, 2332, 2340, 2348, 2356, 2364, 2372, 2376, 2392, + 2400, 2408, 2416, 2424, 2432, 2440, 2444, 2448, 2452, 2456, + 2464, 2472, 2480, 2488, 2508, 2530, 2541, 2548, 2562, 2571, + 2579, 2587, 2607, 2609, 2611, 2613, 2615, 2617, 2619, 2621, + 2623, 2625, 2627, 2629, 2631, 2633, 2635, 2637, 2639, 2641, + 2643, 2645, 2647, 2649, 2653, 2657, 2661, 2675, 2676, 2690, + 2691, 2692, 2703, 2727, 2738, 2748, 2752, 2756, 2763, 2767, + 2774, 2778, 2795, 2799, 2801, 2804, 2807, 2818, 2823, 2830, + 2836, 2842, 2851, 2855, 2862, 2870, 2878, 2889, 2909, 2945, + 2956, 2957, 2964, 2970, 2972, 2974, 2978, 2987, 2992, 2999, + 3014, 3021, 3025, 3029, 3033, 3037, 3047, 3056, 3078, 3079, + 3083, 3084, 3085, 3089, 3090, 3097, 3098, 3102, 3103, 3108, + 3116, 3118, 3132, 3135, 3162, 3163, 3166, 3167, 3175, 3183, + 3191, 3200, 3210, 3228, 3274, 3283, 3292, 3301, 3310, 3322, + 3323, 3324, 3325, 3326, 3340, 3341, 3344, 3345, 3349, 3359, + 3360, 3364, 3365, 3369, 3376, 3377, 3382, 3383, 3388, 3389, + 3392, 3393, 3394, 3397, 3398, 3401, 3402, 3403, 3404, 3405, + 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3417, + 3419, 3424, 3426, 3431, 3433, 3435, 3437, 3439, 3441, 3443, + 3445, 3459, 3461, 3466, 3470, 3477, 3482, 3488, 3492, 3499, + 3504, 3511, 3516, 3524, 3528, 3534, 3538, 3547, 3558, 3559, + 3563, 3567, 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, + 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3598, 3602, 3609, + 3616, 3617, 3633, 3637, 3642, 3646, 3661, 3666, 3670, 3673, + 3676, 3677, 3678, 3681, 3688, 3698, 3712, 3713, 3717, 3728, + 3729, 3732, 3733, 3736, 3740, 3747, 3755, 3763, 3771, 3781, + 3782, 3787, 3788, 3792, 3793, 3794, 3798, 3807, 3815, 3823, + 3832, 3847, 3848, 3853, 3854, 3864, 3865, 3869, 3870, 3874, + 3875, 3878, 3894, 3902, 3912, 3913, 3916, 3917, 3920, 3924, + 3925, 3929, 3930, 3933, 3934, 3935, 3945, 3946, 3950, 3952, + 3958, 3959, 3963, 3964, 3967, 3978, 3981, 3992, 3996, 4000, + 4012, 4016, 4025, 4032, 4070, 4074, 4078, 4082, 4086, 4090, + 4094, 4100, 4117, 4118, 4119, 4122, 4123, 4124, 4127, 4128, + 4129, 4132, 4133, 4136, 4138, 4143, 4144, 4147, 4151, 4152, 7, 18, 19, 23, 24, 25, 26, 27, 28, 7, 26, 50, 73, 80, 85, 86, 87, 88, 8, 33, 62, 66, 67, 72, 73, 78, 79, 83, 84, 89, @@ -2662,20 +1834,20 @@ static const yytype_uint16 yyrline[] = 26, 33, 44, 45, 50, 51, 52, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 90, 91, 92, - 97, 98, 103, 107, 115, 116, 121, 122, 123, 129, - 134, 142, 143, 10, 16, 22, 28, 38, 39, 47, - 58, 70, 78, 89, 95, 99, 103, 118, 125, 126, - 127, 131, 132, 7, 15, 22, 29, 36, 45, 46, - 48, 49, 8, 22, 36, 48, 56, 70, 71, 72, - 73, 74, 87, 88, 93, 94, 98, 99, 7, 18, - 31, 35, 42, 53, 54, 60, 61, 9, 19, 7, - 16, 28, 35, 42, 51, 52, 56, 57, 2, 7, - 12, 17, 26, 33, 43, 44, 51, 3, 10, 17, - 24, 31, 38, 45, 52, 61, 61, 63, 63, 65, - 65, 67, 68, 72, 73, 6, 8, 21, 34, 47, - 65, 87, 88, 89, 90, 11, 24, 37, 54, 55, - 56, 61, 74, 74, 74, 74, 74, 74, 74, 74, + 80, 81, 82, 83, 84, 85, 86, 87, 91, 92, + 93, 98, 99, 104, 108, 116, 117, 122, 123, 124, + 130, 135, 143, 144, 10, 16, 22, 28, 38, 39, + 47, 58, 70, 78, 89, 95, 99, 103, 118, 125, + 126, 127, 131, 132, 7, 17, 26, 35, 46, 47, + 49, 50, 53, 54, 55, 8, 22, 36, 48, 56, + 70, 71, 72, 73, 74, 87, 88, 93, 94, 98, + 99, 7, 18, 31, 35, 42, 53, 54, 60, 61, + 9, 19, 7, 16, 28, 35, 42, 51, 52, 56, + 57, 2, 7, 12, 17, 26, 33, 43, 44, 51, + 3, 10, 17, 24, 31, 38, 45, 52, 61, 61, + 63, 63, 65, 65, 67, 68, 72, 73, 6, 8, + 21, 34, 47, 65, 87, 88, 89, 90, 11, 24, + 37, 54, 55, 56, 61, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, @@ -2707,18 +1879,19 @@ static const yytype_uint16 yyrline[] = 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, + 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 76, 76, 76, 76, + 75, 75, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 78, 78, 78, 78, 78, 78, 78, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, @@ -2726,80 +1899,88 @@ static const yytype_uint16 yyrline[] = 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80 + 80, 80, 80, 80, 80, 80, 80 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/** Accessing symbol of state STATE. */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) + +#if YYDEBUG || 0 +/* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ +static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "$end", "error", "$undefined", "IDENT", "FCONST", "SCONST", "BCONST", - "XCONST", "Op", "ICONST", "PARAM", "TYPECAST", "DOT_DOT", "COLON_EQUALS", - "EQUALS_GREATER", "INTEGER_DIVISION", "POWER_OF", "LAMBDA_ARROW", - "DOUBLE_ARROW", "LESS_EQUALS", "GREATER_EQUALS", "NOT_EQUALS", "ABORT_P", - "ABSOLUTE_P", "ACCESS", "ACTION", "ADD_P", "ADMIN", "AFTER", "AGGREGATE", - "ALL", "ALSO", "ALTER", "ALWAYS", "ANALYSE", "ANALYZE", "AND", "ANTI", - "ANY", "ARRAY", "AS", "ASC_P", "ASOF", "ASSERTION", "ASSIGNMENT", - "ASYMMETRIC", "AT", "ATTACH", "ATTRIBUTE", "AUTHORIZATION", "BACKWARD", - "BEFORE", "BEGIN_P", "BETWEEN", "BIGINT", "BINARY", "BIT", "BOOLEAN_P", - "BOTH", "BY", "CACHE", "CALL_P", "CALLED", "CASCADE", "CASCADED", "CASE", - "CAST", "CATALOG_P", "CENTURIES_P", "CENTURY_P", "CHAIN", "CHAR_P", - "CHARACTER", "CHARACTERISTICS", "CHECK_P", "CHECKPOINT", "CLASS", - "CLOSE", "CLUSTER", "COALESCE", "COLLATE", "COLLATION", "COLUMN", - "COLUMNS", "COMMENT", "COMMENTS", "COMMIT", "COMMITTED", "COMPRESSION", - "CONCURRENTLY", "CONFIGURATION", "CONFLICT", "CONNECTION", "CONSTRAINT", - "CONSTRAINTS", "CONTENT_P", "CONTINUE_P", "CONVERSION_P", "COPY", "COST", - "CREATE_P", "CROSS", "CSV", "CUBE", "CURRENT_P", "CURSOR", "CYCLE", - "DATA_P", "DATABASE", "DAY_P", "DAYS_P", "DEALLOCATE", "DEC", "DECADE_P", + "\"end of file\"", "error", "\"invalid token\"", "IDENT", "FCONST", + "SCONST", "BCONST", "XCONST", "Op", "ICONST", "PARAM", "TYPECAST", + "DOT_DOT", "COLON_EQUALS", "EQUALS_GREATER", "INTEGER_DIVISION", + "POWER_OF", "LAMBDA_ARROW", "DOUBLE_ARROW", "LESS_EQUALS", + "GREATER_EQUALS", "NOT_EQUALS", "ABORT_P", "ABSOLUTE_P", "ACCESS", + "ACTION", "ADD_P", "ADMIN", "AFTER", "AGGREGATE", "ALL", "ALSO", "ALTER", + "ALWAYS", "ANALYSE", "ANALYZE", "AND", "ANTI", "ANY", "ARRAY", "AS", + "ASC_P", "ASOF", "ASSERTION", "ASSIGNMENT", "ASYMMETRIC", "AT", "ATTACH", + "ATTRIBUTE", "AUTHORIZATION", "BACKWARD", "BEFORE", "BEGIN_P", "BETWEEN", + "BIGINT", "BINARY", "BIT", "BOOLEAN_P", "BOTH", "BY", "CACHE", "CALL_P", + "CALLED", "CASCADE", "CASCADED", "CASE", "CAST", "CATALOG_P", + "CENTURIES_P", "CENTURY_P", "CHAIN", "CHAR_P", "CHARACTER", + "CHARACTERISTICS", "CHECK_P", "CHECKPOINT", "CLASS", "CLOSE", "CLUSTER", + "COALESCE", "COLLATE", "COLLATION", "COLUMN", "COLUMNS", "COMMENT", + "COMMENTS", "COMMIT", "COMMITTED", "COMPRESSION", "CONCURRENTLY", + "CONFIGURATION", "CONFLICT", "CONNECTION", "CONSTRAINT", "CONSTRAINTS", + "CONTENT_P", "CONTINUE_P", "CONVERSION_P", "COPY", "COST", "CREATE_P", + "CROSS", "CSV", "CUBE", "CURRENT_P", "CURSOR", "CYCLE", "DATA_P", + "DATABASE", "DAY_P", "DAYS_P", "DEALLOCATE", "DEC", "DECADE_P", "DECADES_P", "DECIMAL_P", "DECLARE", "DEFAULT", "DEFAULTS", "DEFERRABLE", "DEFERRED", "DEFINER", "DELETE_P", "DELIMITER", "DELIMITERS", "DEPENDS", "DESC_P", "DESCRIBE", "DETACH", "DICTIONARY", "DISABLE_P", "DISCARD", "DISTINCT", "DO", "DOCUMENT_P", "DOMAIN_P", "DOUBLE_P", "DROP", "EACH", "ELSE", "ENABLE_P", "ENCODING", "ENCRYPTED", "END_P", "ENUM_P", "ESCAPE", "EVENT", "EXCEPT", "EXCLUDE", "EXCLUDING", "EXCLUSIVE", "EXECUTE", - "EXISTS", "EXPLAIN", "EXPORT_P", "EXPORT_STATE", "EXTENSION", "EXTERNAL", - "EXTRACT", "FALSE_P", "FAMILY", "FETCH", "FILTER", "FIRST_P", "FLOAT_P", - "FOLLOWING", "FOR", "FORCE", "FOREIGN", "FORWARD", "FREEZE", "FROM", - "FULL", "FUNCTION", "FUNCTIONS", "GENERATED", "GLOB", "GLOBAL", "GRANT", - "GRANTED", "GROUP_P", "GROUPING", "GROUPING_ID", "GROUPS", "HANDLER", - "HAVING", "HEADER_P", "HOLD", "HOUR_P", "HOURS_P", "IDENTITY_P", "IF_P", - "IGNORE_P", "ILIKE", "IMMEDIATE", "IMMUTABLE", "IMPLICIT_P", "IMPORT_P", - "IN_P", "INCLUDE_P", "INCLUDING", "INCREMENT", "INDEX", "INDEXES", - "INHERIT", "INHERITS", "INITIALLY", "INLINE_P", "INNER_P", "INOUT", - "INPUT_P", "INSENSITIVE", "INSERT", "INSTALL", "INSTEAD", "INT_P", - "INTEGER", "INTERSECT", "INTERVAL", "INTO", "INVOKER", "IS", "ISNULL", - "ISOLATION", "JOIN", "JSON", "KEY", "LABEL", "LANGUAGE", "LARGE_P", - "LAST_P", "LATERAL_P", "LEADING", "LEAKPROOF", "LEFT", "LEVEL", "LIKE", - "LIMIT", "LISTEN", "LOAD", "LOCAL", "LOCATION", "LOCK_P", "LOCKED", - "LOGGED", "MACRO", "MAP", "MAPPING", "MATCH", "MATERIALIZED", "MAXVALUE", - "METHOD", "MICROSECOND_P", "MICROSECONDS_P", "MILLENNIA_P", - "MILLENNIUM_P", "MILLISECOND_P", "MILLISECONDS_P", "MINUTE_P", - "MINUTES_P", "MINVALUE", "MODE", "MONTH_P", "MONTHS_P", "MOVE", "NAME_P", - "NAMES", "NATIONAL", "NATURAL", "NCHAR", "NEW", "NEXT", "NO", "NONE", - "NOT", "NOTHING", "NOTIFY", "NOTNULL", "NOWAIT", "NULL_P", "NULLIF", - "NULLS_P", "NUMERIC", "OBJECT_P", "OF", "OFF", "OFFSET", "OIDS", "OLD", - "ON", "ONLY", "OPERATOR", "OPTION", "OPTIONS", "OR", "ORDER", - "ORDINALITY", "OTHERS", "OUT_P", "OUTER_P", "OVER", "OVERLAPS", - "OVERLAY", "OVERRIDING", "OWNED", "OWNER", "PARALLEL", "PARSER", - "PARTIAL", "PARTITION", "PASSING", "PASSWORD", "PERCENT", "PERSISTENT", - "PIVOT", "PIVOT_LONGER", "PIVOT_WIDER", "PLACING", "PLANS", "POLICY", - "POSITION", "POSITIONAL", "PRAGMA_P", "PRECEDING", "PRECISION", - "PREPARE", "PREPARED", "PRESERVE", "PRIMARY", "PRIOR", "PRIVILEGES", - "PROCEDURAL", "PROCEDURE", "PROGRAM", "PUBLICATION", "QUALIFY", "QUOTE", - "RANGE", "READ_P", "REAL", "REASSIGN", "RECHECK", "RECURSIVE", "REF", + "EXISTS", "EXPLAIN", "EXPORT_P", "EXPORT_STATE", "EXTENSION", + "EXTENSIONS", "EXTERNAL", "EXTRACT", "FALSE_P", "FAMILY", "FETCH", + "FILTER", "FIRST_P", "FLOAT_P", "FOLLOWING", "FOR", "FORCE", "FOREIGN", + "FORWARD", "FREEZE", "FROM", "FULL", "FUNCTION", "FUNCTIONS", + "GENERATED", "GLOB", "GLOBAL", "GRANT", "GRANTED", "GROUP_P", "GROUPING", + "GROUPING_ID", "GROUPS", "HANDLER", "HAVING", "HEADER_P", "HOLD", + "HOUR_P", "HOURS_P", "IDENTITY_P", "IF_P", "IGNORE_P", "ILIKE", + "IMMEDIATE", "IMMUTABLE", "IMPLICIT_P", "IMPORT_P", "IN_P", "INCLUDE_P", + "INCLUDING", "INCREMENT", "INDEX", "INDEXES", "INHERIT", "INHERITS", + "INITIALLY", "INLINE_P", "INNER_P", "INOUT", "INPUT_P", "INSENSITIVE", + "INSERT", "INSTALL", "INSTEAD", "INT_P", "INTEGER", "INTERSECT", + "INTERVAL", "INTO", "INVOKER", "IS", "ISNULL", "ISOLATION", "JOIN", + "JSON", "KEY", "LABEL", "LANGUAGE", "LARGE_P", "LAST_P", "LATERAL_P", + "LEADING", "LEAKPROOF", "LEFT", "LEVEL", "LIKE", "LIMIT", "LISTEN", + "LOAD", "LOCAL", "LOCATION", "LOCK_P", "LOCKED", "LOGGED", "MACRO", + "MAP", "MAPPING", "MATCH", "MATERIALIZED", "MAXVALUE", "METHOD", + "MICROSECOND_P", "MICROSECONDS_P", "MILLENNIA_P", "MILLENNIUM_P", + "MILLISECOND_P", "MILLISECONDS_P", "MINUTE_P", "MINUTES_P", "MINVALUE", + "MODE", "MONTH_P", "MONTHS_P", "MOVE", "NAME_P", "NAMES", "NATIONAL", + "NATURAL", "NCHAR", "NEW", "NEXT", "NO", "NONE", "NOT", "NOTHING", + "NOTIFY", "NOTNULL", "NOWAIT", "NULL_P", "NULLIF", "NULLS_P", "NUMERIC", + "OBJECT_P", "OF", "OFF", "OFFSET", "OIDS", "OLD", "ON", "ONLY", + "OPERATOR", "OPTION", "OPTIONS", "OR", "ORDER", "ORDINALITY", "OTHERS", + "OUT_P", "OUTER_P", "OVER", "OVERLAPS", "OVERLAY", "OVERRIDING", "OWNED", + "OWNER", "PARALLEL", "PARSER", "PARTIAL", "PARTITION", "PASSING", + "PASSWORD", "PERCENT", "PERSISTENT", "PIVOT", "PIVOT_LONGER", + "PIVOT_WIDER", "PLACING", "PLANS", "POLICY", "POSITION", "POSITIONAL", + "PRAGMA_P", "PRECEDING", "PRECISION", "PREPARE", "PREPARED", "PRESERVE", + "PRIMARY", "PRIOR", "PRIVILEGES", "PROCEDURAL", "PROCEDURE", "PROGRAM", + "PUBLICATION", "QUALIFY", "QUARTER_P", "QUARTERS_P", "QUOTE", "RANGE", + "READ_P", "REAL", "REASSIGN", "RECHECK", "RECURSIVE", "REF", "REFERENCES", "REFERENCING", "REFRESH", "REINDEX", "RELATIVE_P", "RELEASE", "RENAME", "REPEATABLE", "REPLACE", "REPLICA", "RESET", "RESPECT_P", "RESTART", "RESTRICT", "RETURNING", "RETURNS", "REVOKE", @@ -2829,27 +2010,25 @@ static const char *const yytname[] = "POSTFIXOP", "'+'", "'-'", "'*'", "'/'", "'%'", "'^'", "UMINUS", "'['", "']'", "'('", "')'", "'.'", "';'", "','", "'?'", "'{'", "'}'", "'#'", "'$'", "':'", "$accept", "stmtblock", "stmtmulti", "stmt", - "AlterTableStmt", "alter_identity_column_option_list", - "alter_column_default", "alter_identity_column_option", - "alter_generic_option_list", "alter_table_cmd", "alter_using", - "alter_generic_option_elem", "alter_table_cmds", "alter_generic_options", - "opt_set_data", "DeallocateStmt", "qualified_name", "ColId", - "ColIdOrString", "Sconst", "indirection", "indirection_el", "attr_name", - "ColLabel", "RenameStmt", "opt_column", "InsertStmt", "insert_rest", - "insert_target", "opt_by_name_or_position", "opt_conf_expr", - "opt_with_clause", "insert_column_item", "set_clause", "opt_or_action", - "opt_on_conflict", "index_elem", "returning_clause", "override_kind", - "set_target_list", "opt_collate", "opt_class", "insert_column_list", - "set_clause_list", "set_clause_list_opt_comma", "index_params", - "set_target", "CreateTypeStmt", "opt_enum_val_list", "enum_val_list", - "PragmaStmt", "CreateSeqStmt", "OptSeqOptList", "CreateSecretStmt", - "opt_secret_name", "opt_persist", "opt_storage_specifier", "ExecuteStmt", - "execute_param_expr", "execute_param_list", "execute_param_clause", - "AlterSeqStmt", "SeqOptList", "opt_with", "NumericOnly", "SeqOptElem", - "opt_by", "SignedIconst", "DropSecretStmt", "opt_storage_drop_specifier", - "TransactionStmt", "opt_transaction", "UseStmt", "CreateStmt", - "ConstraintAttributeSpec", "def_arg", "OptParenthesizedSeqOptList", - "generic_option_arg", "key_action", "ColConstraint", "ColConstraintElem", + "AlterObjectSchemaStmt", "AlterSeqStmt", "SeqOptList", "opt_with", + "NumericOnly", "SeqOptElem", "opt_by", "SignedIconst", "AlterTableStmt", + "alter_identity_column_option_list", "alter_column_default", + "alter_identity_column_option", "alter_generic_option_list", + "alter_table_cmd", "alter_using", "alter_generic_option_elem", + "alter_table_cmds", "alter_generic_options", "opt_set_data", + "AnalyzeStmt", "AttachStmt", "DetachStmt", "opt_database", + "opt_database_alias", "CallStmt", "CheckPointStmt", "opt_col_id", + "CommentOnStmt", "comment_value", "comment_on_type_any_name", + "qualified_name", "ColId", "ColIdOrString", "Sconst", "indirection", + "indirection_el", "attr_name", "ColLabel", "CopyStmt", + "copy_database_flag", "copy_from", "copy_delimiter", + "copy_generic_opt_arg_list", "opt_using", "opt_as", "opt_program", + "copy_options", "copy_generic_opt_arg", "copy_generic_opt_elem", + "opt_oids", "copy_opt_list", "opt_binary", "copy_opt_item", + "copy_generic_opt_arg_list_item", "copy_file_name", + "copy_generic_opt_list", "CreateStmt", "ConstraintAttributeSpec", + "def_arg", "OptParenthesizedSeqOptList", "generic_option_arg", + "key_action", "ColConstraint", "ColConstraintElem", "GeneratedColumnType", "opt_GeneratedColumnType", "GeneratedConstraintElem", "generic_option_elem", "key_update", "key_actions", "OnCommitOption", "reloptions", "opt_no_inherit", @@ -2860,18 +2039,35 @@ static const char *const yytname[] = "OptTableElementList", "columnElem", "opt_column_list", "ColQualList", "key_delete", "reloption_elem", "columnList", "columnList_opt_comma", "func_type", "ConstraintElem", "TableElementList", "key_match", - "TableLikeClause", "OptTemp", "generated_when", "DropStmt", - "drop_type_any_name", "drop_type_name", "any_name_list", - "opt_drop_behavior", "drop_type_name_on_any_name", "CreateFunctionStmt", - "macro_alias", "param_list", "UpdateStmt", "CopyStmt", - "copy_database_flag", "copy_from", "copy_delimiter", - "copy_generic_opt_arg_list", "opt_using", "opt_as", "opt_program", - "copy_options", "copy_generic_opt_arg", "copy_generic_opt_elem", - "opt_oids", "copy_opt_list", "opt_binary", "copy_opt_item", - "copy_generic_opt_arg_list_item", "copy_file_name", - "copy_generic_opt_list", "SelectStmt", "select_with_parens", - "select_no_parens", "select_clause", "opt_select", "simple_select", - "value_or_values", "pivot_keyword", "unpivot_keyword", + "TableLikeClause", "OptTemp", "generated_when", "CreateAsStmt", + "opt_with_data", "create_as_target", "unreserved_keyword", + "col_name_keyword", "func_name_keyword", "type_name_keyword", + "other_keyword", "type_func_name_keyword", "reserved_keyword", + "CreateFunctionStmt", "macro_alias", "param_list", "CreateSchemaStmt", + "OptSchemaEltList", "schema_stmt", "CreateSecretStmt", "opt_secret_name", + "opt_persist", "opt_storage_specifier", "CreateSeqStmt", "OptSeqOptList", + "CreateTypeStmt", "opt_enum_val_list", "enum_val_list", "DeallocateStmt", + "DeleteStmt", "relation_expr_opt_alias", "where_or_current_clause", + "using_clause", "DropStmt", "drop_type_any_name", "drop_type_name", + "any_name_list", "opt_drop_behavior", "drop_type_name_on_any_name", + "DropSecretStmt", "opt_storage_drop_specifier", "ExecuteStmt", + "execute_param_expr", "execute_param_list", "execute_param_clause", + "ExplainStmt", "opt_verbose", "explain_option_arg", "ExplainableStmt", + "NonReservedWord", "NonReservedWord_or_Sconst", "explain_option_list", + "analyze_keyword", "opt_boolean_or_string", "explain_option_elem", + "explain_option_name", "ExportStmt", "ImportStmt", "IndexStmt", + "access_method", "access_method_clause", "opt_concurrently", + "opt_index_name", "opt_reloptions", "opt_unique", "InsertStmt", + "insert_rest", "insert_target", "opt_by_name_or_position", + "opt_conf_expr", "opt_with_clause", "insert_column_item", "set_clause", + "opt_or_action", "opt_on_conflict", "index_elem", "returning_clause", + "override_kind", "set_target_list", "opt_collate", "opt_class", + "insert_column_list", "set_clause_list", "set_clause_list_opt_comma", + "index_params", "set_target", "LoadStmt", "opt_force", "file_name", + "opt_ext_version", "PragmaStmt", "PrepareStmt", "prep_type_clause", + "PreparableStmt", "RenameStmt", "opt_column", "SelectStmt", + "select_with_parens", "select_no_parens", "select_clause", "opt_select", + "simple_select", "value_or_values", "pivot_keyword", "unpivot_keyword", "pivot_column_entry", "pivot_column_list_internal", "pivot_column_list", "with_clause", "cte_list", "common_table_expr", "opt_materialized", "into_clause", "OptTempTableName", "opt_table", "all_or_distinct", @@ -2906,9 +2102,9 @@ static const char *const yytname[] = "ConstInterval", "opt_timezone", "year_keyword", "month_keyword", "day_keyword", "hour_keyword", "minute_keyword", "second_keyword", "millisecond_keyword", "microsecond_keyword", "week_keyword", - "decade_keyword", "century_keyword", "millennium_keyword", - "opt_interval", "a_expr", "b_expr", "c_expr", "d_expr", - "indirection_expr_or_a_expr", "indirection_expr", "list_expr", + "quarter_keyword", "decade_keyword", "century_keyword", + "millennium_keyword", "opt_interval", "a_expr", "b_expr", "c_expr", + "d_expr", "indirection_expr_or_a_expr", "indirection_expr", "list_expr", "struct_expr", "func_application", "func_expr", "func_expr_windowless", "func_expr_common_subexpr", "list_comprehension", "within_group_clause", "filter_clause", "export_clause", "window_clause", @@ -2935,9555 +2131,9135 @@ static const char *const yytname[] = "name_list_opt_comma_opt_bracket", "name", "func_name", "AexprConst", "Iconst", "type_function_name", "function_name_token", "type_name_token", "any_name", "attrs", "opt_name_list", "param_name", "ColLabelOrString", - "PrepareStmt", "prep_type_clause", "PreparableStmt", "CreateSchemaStmt", - "OptSchemaEltList", "schema_stmt", "IndexStmt", "access_method", - "access_method_clause", "opt_concurrently", "opt_index_name", - "opt_reloptions", "opt_unique", "AlterObjectSchemaStmt", - "CheckPointStmt", "opt_col_id", "CommentOnStmt", "comment_value", - "comment_on_type_any_name", "ExportStmt", "ImportStmt", "ExplainStmt", - "opt_verbose", "explain_option_arg", "ExplainableStmt", - "NonReservedWord", "NonReservedWord_or_Sconst", "explain_option_list", - "analyze_keyword", "opt_boolean_or_string", "explain_option_elem", - "explain_option_name", "VariableSetStmt", "set_rest", "generic_set", - "var_value", "zone_value", "var_list", "LoadStmt", "file_name", - "repo_path", "VacuumStmt", "vacuum_option_elem", "opt_full", - "vacuum_option_list", "opt_freeze", "DeleteStmt", - "relation_expr_opt_alias", "where_or_current_clause", "using_clause", - "AnalyzeStmt", "AttachStmt", "DetachStmt", "opt_database", - "opt_database_alias", "VariableResetStmt", "generic_reset", "reset_rest", + "TransactionStmt", "opt_transaction", "opt_transaction_type", + "UpdateStmt", "UpdateExtensionsStmt", "UseStmt", "VacuumStmt", + "vacuum_option_elem", "opt_full", "vacuum_option_list", "opt_freeze", + "VariableResetStmt", "generic_reset", "reset_rest", "VariableSetStmt", + "set_rest", "generic_set", "var_value", "zone_value", "var_list", "VariableShowStmt", "describe_or_desc", "show_or_describe", "opt_tables", - "var_name", "table_id", "CallStmt", "ViewStmt", "opt_check_option", - "CreateAsStmt", "opt_with_data", "create_as_target", - "unreserved_keyword", "col_name_keyword", "func_name_keyword", - "type_name_keyword", "other_keyword", "type_func_name_keyword", - "reserved_keyword", 0 + "var_name", "table_id", "ViewStmt", "opt_check_option", YY_NULLPTR }; -#endif -# ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const yytype_uint16 yytoknum[] = +static const char * +yysymbol_name (yysymbol_kind_t yysymbol) { - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, - 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, - 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, - 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, - 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, - 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, - 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, - 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, - 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, - 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, - 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, - 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, - 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, - 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, - 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, - 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, - 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, - 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, - 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, - 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, - 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, - 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, - 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, - 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, - 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, - 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, - 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, - 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, - 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, - 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, - 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, - 755, 60, 62, 61, 756, 43, 45, 42, 47, 37, - 94, 757, 91, 93, 40, 41, 46, 59, 44, 63, - 123, 125, 35, 36, 58 -}; -# endif + return yytname[yysymbol]; +} +#endif -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint16 yyr1[] = -{ - 0, 525, 526, 527, 527, 528, 528, 528, 528, 528, - 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, - 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, - 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, - 528, 528, 528, 528, 528, 528, 529, 529, 529, 529, - 529, 529, 529, 529, 530, 530, 531, 531, 532, 532, - 532, 532, 533, 533, 534, 534, 534, 534, 534, 534, - 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, - 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, - 534, 534, 534, 535, 535, 536, 536, 536, 536, 537, - 537, 538, 539, 539, 539, 540, 540, 540, 540, 541, - 541, 542, 542, 542, 543, 543, 544, 545, 545, 546, - 547, 548, 548, 548, 548, 549, 549, 549, 549, 549, - 549, 549, 549, 549, 549, 549, 549, 549, 550, 550, - 551, 552, 552, 552, 552, 552, 553, 553, 554, 554, - 554, 555, 555, 555, 556, 556, 557, 558, 558, 559, - 559, 559, 560, 560, 560, 561, 561, 561, 562, 562, - 563, 563, 564, 564, 565, 565, 566, 566, 567, 567, - 568, 568, 569, 569, 570, 570, 571, 572, 572, 572, - 573, 573, 574, 574, 575, 575, 575, 576, 576, 576, - 577, 577, 578, 578, 578, 579, 579, 580, 580, 580, - 581, 581, 582, 582, 582, 583, 583, 584, 584, 585, - 585, 586, 586, 587, 587, 588, 588, 588, 589, 589, - 589, 589, 590, 590, 590, 590, 590, 590, 590, 590, - 590, 590, 590, 590, 590, 590, 591, 591, 592, 592, - 592, 593, 593, 594, 594, 595, 595, 595, 595, 595, - 595, 596, 596, 596, 597, 598, 598, 598, 599, 599, - 600, 600, 600, 600, 600, 600, 601, 601, 602, 603, - 603, 603, 603, 603, 604, 604, 604, 604, 605, 605, - 605, 605, 605, 605, 605, 605, 606, 606, 607, 607, - 608, 608, 608, 609, 610, 611, 611, 611, 611, 611, - 612, 612, 612, 612, 613, 614, 614, 615, 615, 616, - 616, 616, 616, 616, 616, 616, 616, 617, 617, 618, - 619, 619, 619, 619, 620, 620, 620, 620, 621, 622, - 622, 622, 623, 624, 624, 624, 624, 624, 624, 625, - 625, 626, 626, 627, 628, 628, 628, 629, 629, 630, - 630, 631, 631, 631, 632, 633, 633, 634, 634, 635, - 636, 636, 636, 636, 637, 637, 638, 638, 639, 639, - 639, 640, 640, 640, 640, 640, 640, 641, 641, 642, - 642, 642, 642, 643, 644, 644, 644, 644, 644, 644, - 644, 644, 645, 645, 646, 646, 646, 646, 646, 646, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 647, - 647, 647, 647, 647, 647, 647, 647, 647, 648, 648, - 648, 648, 648, 648, 649, 649, 650, 650, 650, 651, - 651, 651, 652, 652, 652, 652, 652, 652, 653, 653, - 654, 654, 655, 656, 656, 656, 657, 657, 657, 658, - 658, 659, 659, 660, 660, 661, 661, 662, 662, 663, - 663, 664, 664, 665, 665, 665, 665, 665, 665, 665, - 666, 667, 667, 668, 668, 669, 669, 670, 670, 670, - 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, - 670, 670, 670, 671, 672, 672, 672, 672, 672, 673, - 673, 674, 674, 675, 675, 675, 676, 676, 676, 676, - 676, 676, 676, 676, 677, 677, 678, 678, 679, 679, - 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, - 679, 679, 679, 679, 679, 679, 679, 680, 680, 681, - 681, 682, 682, 683, 683, 683, 684, 684, 685, 685, - 686, 686, 686, 687, 687, 688, 689, 689, 689, 690, - 690, 691, 691, 691, 691, 691, 691, 691, 691, 691, - 692, 692, 693, 693, 693, 694, 695, 695, 696, 696, - 697, 697, 697, 698, 698, 699, 699, 700, 700, 701, - 701, 702, 702, 702, 703, 703, 703, 704, 704, 704, - 704, 705, 705, 706, 706, 706, 706, 707, 707, 708, - 708, 708, 708, 708, 708, 709, 709, 710, 710, 711, - 711, 711, 711, 712, 713, 713, 714, 714, 715, 715, - 715, 715, 715, 716, 717, 717, 717, 718, 718, 719, - 719, 720, 720, 721, 721, 721, 722, 722, 723, 723, - 724, 724, 724, 724, 724, 725, 726, 727, 728, 729, - 729, 730, 730, 731, 731, 732, 732, 733, 733, 734, - 734, 735, 736, 736, 736, 736, 737, 737, 738, 738, - 738, 739, 739, 740, 740, 741, 741, 742, 742, 743, - 743, 744, 744, 744, 744, 744, 744, 744, 744, 744, - 744, 745, 745, 746, 746, 746, 747, 747, 748, 748, - 748, 748, 749, 749, 750, 750, 751, 751, 752, 753, - 753, 754, 754, 754, 754, 754, 754, 754, 754, 754, - 754, 754, 755, 755, 755, 755, 756, 756, 757, 757, - 757, 757, 757, 758, 758, 758, 758, 758, 758, 759, - 759, 760, 760, 761, 761, 761, 761, 762, 762, 763, - 764, 764, 765, 765, 766, 766, 767, 767, 768, 768, - 769, 770, 770, 771, 771, 772, 772, 773, 773, 774, - 774, 774, 774, 774, 774, 774, 774, 774, 774, 775, - 775, 776, 776, 776, 777, 777, 777, 777, 777, 777, - 777, 778, 778, 778, 778, 779, 780, 780, 781, 781, - 781, 781, 781, 781, 781, 781, 781, 781, 781, 782, - 782, 783, 783, 784, 784, 785, 786, 787, 787, 788, - 788, 789, 790, 791, 791, 791, 791, 791, 791, 792, - 792, 793, 793, 793, 793, 794, 795, 795, 795, 796, - 796, 797, 797, 798, 798, 799, 799, 800, 800, 801, - 801, 802, 802, 803, 803, 804, 804, 805, 805, 806, - 806, 807, 807, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 808, 808, 808, 808, 808, 808, 808, - 808, 808, 808, 809, 809, 809, 809, 809, 809, 809, - 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, - 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, - 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, - 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, - 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, - 809, 809, 809, 809, 809, 809, 809, 809, 809, 809, - 809, 809, 809, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 810, 810, 811, 811, - 812, 812, 812, 812, 812, 812, 813, 813, 813, 814, - 814, 814, 814, 814, 814, 814, 814, 814, 814, 814, - 814, 815, 816, 817, 817, 817, 817, 817, 817, 818, - 818, 819, 819, 820, 820, 820, 820, 820, 820, 820, - 820, 820, 820, 820, 820, 820, 820, 821, 821, 822, - 822, 823, 823, 823, 824, 824, 825, 825, 826, 826, - 827, 828, 828, 828, 829, 830, 830, 831, 831, 832, - 832, 832, 832, 833, 833, 834, 834, 834, 834, 834, - 835, 835, 835, 835, 835, 836, 836, 837, 837, 838, - 839, 839, 840, 840, 841, 842, 842, 843, 843, 844, - 844, 845, 845, 845, 846, 846, 847, 847, 847, 847, - 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, - 848, 848, 849, 849, 850, 850, 850, 850, 850, 850, - 850, 850, 851, 851, 852, 852, 853, 853, 854, 854, - 855, 855, 856, 856, 857, 857, 858, 858, 858, 859, - 859, 860, 860, 861, 861, 861, 861, 861, 861, 861, - 861, 861, 861, 861, 861, 861, 861, 862, 862, 863, - 864, 864, 865, 865, 865, 865, 865, 865, 866, 867, - 868, 868, 868, 869, 869, 870, 871, 871, 872, 873, - 873, 874, 874, 875, 875, 546, 546, 546, 546, 876, - 876, 877, 877, 878, 878, 878, 879, 879, 879, 879, - 879, 880, 880, 881, 881, 882, 882, 883, 883, 884, - 884, 885, 885, 885, 886, 886, 887, 887, 888, 889, - 889, 890, 890, 891, 891, 891, 892, 892, 893, 893, - 894, 894, 895, 895, 896, 897, 897, 898, 898, 898, - 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, - 898, 899, 900, 900, 900, 901, 901, 901, 902, 902, - 902, 903, 903, 904, 904, 905, 905, 906, 907, 907, - 908, 909, 909, 910, 910, 910, 910, 910, 910, 911, - 911, 911, 912, 912, 913, 913, 913, 913, 914, 914, - 915, 916, 916, 917, 917, 918, 918, 919, 919, 920, - 920, 921, 921, 921, 921, 921, 921, 922, 922, 923, - 923, 924, 924, 925, 925, 926, 926, 926, 926, 926, - 926, 926, 926, 926, 926, 927, 927, 928, 929, 929, - 929, 929, 930, 930, 931, 931, 931, 932, 932, 932, - 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, - 932, 932, 932, 932, 932, 932, 932, 932, 932, 932, - 932, 932, 932, 932, 932, 932, 932, 933, 933, 933, - 934, 934, 935, 935, 936, 936, 937, 937, 937, 937, - 938, 939, 939, 940, 940, 940, 940, 941, 941, 941, - 941, 942, 942, 943, 944, 944, 944, 944, 944, 944, - 944, 945, 945, 946, 946, 946, 946, 946, 947, 947, - 948, 948, 949, 949, 949, 949, 949, 950, 950, 950, - 950, 950, 951, 951, 952, 952, 953, 953, 954, 954, - 955, 955, 955, 956, 956, 957, 957, 958, 958, 959, - 959, 960, 960, 960, 961, 961, 962, 962, 963, 963, - 963, 963, 964, 964, 965, 965, 965, 966, 966, 966, - 966, 966, 966, 966, 966, 967, 967, 968, 968, 969, - 969, 970, 970, 971, 971, 972, 973, 973, 973, 973, - 973, 974, 974, 974, 974, 975, 975, 975, 976, 976, - 976, 977, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 978, 978, 978, 978, 978, 978, 978, 978, - 978, 978, 979, 979, 979, 979, 979, 979, 979, 979, - 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, - 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, - 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, - 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, - 979, 979, 979, 979, 979, 979, 980, 980, 980, 980, - 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, - 980, 980, 980, 980, 980, 980, 980, 980, 980, 980, - 980, 980, 980, 980, 981, 981, 981, 981, 981, 981, - 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, - 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, - 981, 981, 981, 982, 982, 982, 982, 982, 982, 982, - 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, - 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, - 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, - 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, - 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, - 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, - 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, - 982, 982, 982, 982, 983, 983, 983, 983, 983, 983, - 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, - 983, 983, 983, 983, 983, 983, 983, 983, 983, 983, - 983, 983, 983, 983, 983, 983, 984, 984, 984, 984, - 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, - 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, - 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, - 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, - 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, - 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, - 984, 984, 984, 984, 984, 984, 984, 984, 984, 984, - 984 -}; +#define YYPACT_NINF (-3106) -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 1, 3, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 0, 4, 6, 4, 6, - 4, 6, 4, 6, 1, 2, 3, 2, 1, 3, - 2, 3, 1, 3, 2, 5, 3, 6, 4, 6, - 6, 6, 5, 5, 6, 9, 4, 5, 7, 6, - 4, 8, 4, 2, 4, 3, 6, 4, 2, 2, - 2, 2, 1, 2, 0, 1, 2, 2, 2, 1, - 3, 4, 2, 1, 0, 2, 3, 2, 3, 1, - 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, - 1, 1, 1, 1, 1, 6, 6, 8, 6, 8, - 6, 8, 6, 8, 8, 10, 8, 10, 1, 0, - 9, 1, 4, 4, 7, 2, 1, 3, 2, 2, - 0, 4, 3, 0, 1, 0, 2, 3, 5, 2, - 2, 0, 8, 5, 0, 5, 5, 7, 2, 0, - 1, 1, 1, 3, 2, 0, 1, 0, 1, 3, - 1, 3, 1, 2, 1, 3, 2, 6, 8, 5, - 1, 0, 1, 3, 2, 4, 5, 5, 8, 7, - 1, 0, 8, 11, 10, 0, 1, 0, 1, 1, - 0, 2, 3, 9, 12, 1, 3, 1, 3, 3, - 0, 4, 6, 1, 2, 1, 1, 0, 1, 2, - 2, 1, 2, 2, 1, 2, 3, 2, 2, 2, - 2, 3, 3, 3, 1, 3, 1, 0, 1, 2, - 2, 5, 7, 0, 2, 2, 2, 2, 2, 2, - 2, 1, 1, 0, 2, 9, 12, 11, 0, 2, - 1, 1, 1, 1, 1, 1, 3, 0, 1, 2, - 1, 1, 2, 2, 3, 1, 1, 2, 2, 1, - 2, 3, 5, 3, 2, 5, 1, 1, 1, 0, - 5, 7, 5, 2, 3, 1, 1, 2, 2, 0, - 3, 4, 4, 0, 3, 2, 0, 3, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, - 1, 2, 2, 2, 2, 2, 2, 0, 3, 3, - 3, 0, 1, 2, 1, 2, 2, 2, 2, 3, - 4, 1, 3, 1, 1, 1, 1, 3, 1, 2, - 0, 1, 2, 0, 1, 3, 0, 2, 0, 3, - 3, 1, 5, 3, 1, 3, 1, 2, 1, 4, - 5, 5, 6, 3, 7, 4, 11, 1, 3, 2, - 2, 2, 0, 3, 1, 1, 2, 2, 2, 2, - 1, 0, 1, 2, 6, 4, 6, 4, 6, 8, - 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, - 1, 1, 1, 3, 3, 3, 3, 1, 2, 2, - 1, 3, 1, 1, 1, 3, 1, 1, 0, 1, - 1, 1, 8, 11, 10, 7, 10, 9, 1, 1, - 2, 3, 8, 11, 9, 7, 0, 3, 3, 1, - 1, 3, 0, 1, 3, 1, 0, 1, 0, 1, - 0, 1, 3, 1, 1, 1, 1, 3, 1, 0, - 2, 2, 0, 2, 0, 1, 0, 1, 1, 1, - 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, - 4, 3, 2, 1, 1, 1, 1, 3, 1, 1, - 3, 1, 1, 3, 3, 3, 1, 2, 4, 4, - 2, 3, 5, 5, 1, 1, 3, 0, 11, 11, - 10, 12, 1, 2, 5, 4, 4, 4, 4, 7, - 5, 4, 7, 6, 9, 9, 4, 1, 1, 1, - 1, 1, 1, 1, 5, 1, 1, 3, 1, 2, - 2, 2, 3, 1, 3, 7, 1, 2, 0, 2, - 0, 3, 3, 4, 4, 4, 4, 3, 2, 1, - 1, 0, 1, 1, 0, 2, 1, 5, 1, 0, - 2, 2, 0, 1, 0, 3, 5, 1, 3, 4, - 3, 1, 1, 0, 2, 2, 0, 2, 2, 1, - 1, 1, 0, 2, 4, 5, 4, 2, 3, 2, - 2, 2, 2, 1, 2, 3, 0, 1, 0, 5, - 1, 4, 6, 2, 1, 0, 4, 0, 1, 1, - 2, 2, 2, 1, 1, 2, 2, 1, 1, 1, - 1, 1, 1, 3, 3, 0, 1, 3, 1, 2, - 1, 1, 1, 1, 1, 2, 4, 4, 5, 1, - 1, 2, 0, 2, 0, 1, 3, 1, 0, 1, - 2, 3, 2, 4, 2, 3, 2, 0, 1, 2, - 0, 4, 5, 1, 2, 2, 0, 1, 3, 1, - 2, 3, 3, 3, 3, 3, 3, 1, 4, 9, - 9, 3, 0, 2, 2, 0, 5, 3, 0, 1, - 1, 3, 5, 3, 1, 2, 1, 3, 5, 1, - 2, 3, 4, 5, 4, 5, 4, 6, 5, 4, - 5, 5, 5, 2, 4, 1, 1, 0, 1, 4, - 5, 4, 0, 2, 2, 2, 1, 1, 1, 1, - 0, 4, 2, 1, 2, 2, 4, 2, 6, 2, - 1, 3, 4, 0, 2, 0, 2, 0, 1, 3, - 3, 2, 0, 2, 4, 1, 1, 1, 0, 2, - 3, 5, 6, 2, 3, 1, 5, 5, 5, 3, - 3, 3, 4, 0, 1, 1, 1, 1, 1, 2, - 4, 1, 1, 1, 1, 2, 3, 0, 1, 1, - 1, 1, 1, 2, 2, 2, 2, 2, 1, 3, - 0, 1, 1, 1, 1, 5, 2, 1, 1, 1, - 1, 4, 1, 2, 2, 1, 3, 3, 2, 1, - 0, 5, 2, 5, 2, 1, 3, 3, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, - 3, 3, 0, 1, 3, 3, 5, 2, 2, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 2, 2, 3, 3, 2, 2, - 3, 3, 5, 4, 6, 3, 5, 4, 6, 4, - 6, 5, 7, 3, 2, 4, 3, 2, 3, 3, - 3, 3, 4, 3, 4, 3, 4, 5, 6, 6, - 7, 6, 7, 6, 7, 3, 4, 4, 6, 1, - 4, 3, 5, 1, 3, 2, 2, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 2, 2, 5, 6, 6, 7, 1, 2, - 1, 1, 1, 2, 2, 4, 3, 1, 1, 1, - 1, 1, 4, 1, 1, 1, 1, 2, 4, 2, - 2, 3, 3, 3, 6, 7, 9, 7, 7, 5, - 1, 1, 1, 5, 6, 6, 4, 4, 4, 4, - 6, 5, 5, 5, 4, 6, 4, 7, 9, 5, - 0, 5, 4, 0, 1, 0, 2, 0, 1, 3, - 3, 2, 2, 0, 6, 1, 0, 3, 0, 3, - 3, 3, 0, 1, 4, 2, 2, 2, 2, 2, - 3, 2, 2, 3, 0, 4, 3, 1, 5, 3, - 1, 3, 1, 2, 3, 1, 3, 1, 2, 1, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 4, 1, 4, 1, 4, 1, 2, 1, 2, - 1, 2, 1, 3, 1, 3, 1, 2, 1, 3, - 1, 2, 1, 0, 1, 3, 1, 3, 3, 1, - 3, 3, 0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 4, 3, 2, - 3, 0, 3, 3, 2, 2, 1, 0, 2, 2, - 3, 2, 1, 1, 3, 5, 1, 2, 4, 2, - 0, 1, 0, 1, 2, 3, 5, 7, 7, 1, - 0, 0, 2, 0, 2, 3, 3, 3, 5, 7, - 7, 0, 2, 1, 0, 1, 0, 1, 3, 1, - 2, 3, 2, 1, 4, 2, 1, 0, 3, 1, - 3, 1, 2, 4, 2, 0, 1, 3, 1, 3, - 1, 2, 1, 3, 1, 1, 2, 1, 1, 2, - 1, 1, 2, 7, 2, 5, 3, 3, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 3, 3, 0, 1, 1, 1, - 5, 3, 0, 1, 1, 1, 1, 1, 1, 4, - 7, 6, 2, 0, 1, 1, 1, 1, 13, 16, - 1, 2, 0, 1, 0, 1, 0, 2, 0, 1, - 0, 6, 8, 6, 8, 6, 8, 3, 2, 1, - 0, 6, 6, 1, 1, 1, 1, 1, 1, 2, - 1, 1, 1, 1, 1, 4, 6, 3, 2, 4, - 3, 5, 1, 0, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, - 2, 1, 1, 2, 3, 3, 3, 1, 3, 3, - 2, 3, 3, 1, 1, 1, 3, 5, 1, 1, - 1, 1, 3, 2, 2, 3, 4, 5, 1, 1, - 1, 1, 4, 6, 5, 4, 6, 1, 1, 1, - 1, 1, 1, 0, 1, 3, 1, 0, 7, 3, - 1, 2, 3, 2, 0, 2, 0, 2, 4, 5, - 8, 2, 3, 5, 1, 0, 2, 0, 2, 3, - 3, 3, 1, 1, 1, 2, 3, 2, 2, 2, - 2, 3, 4, 3, 1, 1, 1, 1, 1, 1, - 0, 1, 3, 1, 3, 2, 9, 12, 11, 12, - 14, 3, 4, 4, 0, 7, 10, 9, 2, 3, - 0, 4, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1 -}; +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const yytype_uint16 yydefact[] = -{ - 155, 263, 0, 1385, 1384, 1455, 263, 0, 1320, 0, - 263, 486, 401, 0, 1476, 1475, 0, 207, 263, 0, - 155, 0, 0, 0, 0, 0, 0, 549, 552, 550, - 0, 0, 0, 263, 589, 0, 1477, 263, 0, 0, - 581, 551, 0, 1433, 0, 0, 0, 0, 0, 2, - 4, 7, 21, 35, 31, 0, 20, 33, 18, 17, - 26, 6, 24, 37, 39, 19, 25, 15, 38, 13, - 36, 525, 511, 594, 524, 0, 0, 154, 693, 532, - 34, 16, 30, 5, 11, 12, 28, 29, 27, 1343, - 42, 32, 40, 22, 8, 9, 23, 41, 43, 1478, - 1474, 10, 44, 14, 262, 261, 255, 0, 0, 0, - 0, 0, 1454, 0, 0, 256, 111, 1502, 1503, 1504, - 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1876, 1513, - 1514, 1515, 1516, 1517, 1877, 1518, 1519, 1520, 1822, 1823, - 1878, 1824, 1825, 1521, 1522, 1523, 1524, 1525, 1526, 1527, - 1528, 1529, 1530, 1826, 1827, 1531, 1532, 1533, 1534, 1535, - 1828, 1879, 1829, 1536, 1537, 1538, 1539, 1540, 1880, 1541, - 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1881, 1550, - 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1830, - 1560, 1561, 1831, 1562, 1563, 1564, 1565, 1566, 1567, 1568, - 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, - 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, - 1832, 1589, 1590, 1591, 1592, 1593, 1833, 1594, 1595, 1596, - 1834, 1597, 1598, 1599, 1882, 1883, 1600, 1601, 1835, 1885, - 1602, 1603, 1836, 1837, 1604, 1605, 1606, 1607, 1608, 1609, - 1610, 1611, 1612, 1886, 1613, 1614, 1615, 1616, 1617, 1618, - 1619, 1620, 1621, 1622, 1623, 1624, 1887, 1838, 1625, 1626, - 1627, 1628, 1629, 1839, 1840, 1841, 1630, 1888, 1889, 1631, - 1890, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1891, 1639, - 1892, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1842, - 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, - 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, - 1843, 1894, 1844, 1668, 1669, 1670, 1845, 1671, 1672, 1895, - 1673, 1846, 1674, 1847, 1675, 1676, 1677, 1678, 1679, 1680, - 1681, 1682, 1683, 1684, 1848, 1896, 1685, 1897, 1849, 1686, - 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, - 1697, 1698, 1850, 1898, 1699, 1700, 1851, 1701, 1702, 1703, - 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1852, - 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, - 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1899, - 1732, 1733, 1734, 1853, 1735, 1736, 1737, 1738, 1739, 1740, - 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, - 1751, 1752, 1753, 1854, 1754, 1755, 1900, 1756, 1757, 1855, - 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, - 1768, 1769, 1770, 1856, 1771, 1857, 1772, 1773, 1774, 1902, - 1775, 1776, 1777, 1778, 1779, 1780, 1858, 1859, 1781, 1782, - 1860, 1783, 1861, 1784, 1785, 1862, 1786, 1787, 1788, 1789, - 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, - 1800, 1801, 1802, 1863, 1864, 1803, 1903, 1804, 1805, 1806, - 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, - 1817, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, - 1874, 1875, 1818, 1819, 1820, 1821, 0, 1485, 0, 1245, - 112, 113, 1267, 111, 1835, 1842, 1856, 1319, 1318, 112, - 0, 258, 485, 0, 0, 0, 0, 0, 0, 209, - 0, 395, 394, 0, 1309, 400, 0, 0, 0, 115, - 107, 1701, 114, 1244, 105, 121, 2046, 2047, 2048, 2049, - 1933, 2050, 2051, 2052, 2053, 1934, 2054, 1935, 1936, 1937, - 1938, 1939, 1940, 2055, 2056, 2057, 1942, 1941, 2058, 1943, - 2059, 1944, 2060, 1945, 1946, 2061, 2062, 1947, 1556, 1948, - 1949, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, - 1950, 1951, 2072, 2073, 1952, 2074, 2075, 1953, 2076, 1954, - 1955, 1956, 2077, 2078, 1957, 1958, 2079, 1959, 2080, 2081, - 1960, 1961, 1964, 1962, 2082, 1963, 2083, 1965, 1966, 1967, - 2084, 2085, 1968, 1969, 2086, 1970, 1971, 1972, 1973, 1974, - 2087, 1975, 2088, 1976, 1977, 2089, 2090, 2091, 2092, 2093, - 1979, 1978, 1980, 1981, 2094, 2095, 2096, 2097, 1982, 1983, - 1984, 2098, 2099, 1985, 2100, 2101, 1986, 1987, 2102, 1988, - 1989, 2103, 1990, 1991, 2104, 1992, 1993, 2105, 2106, 2107, - 1994, 2108, 1995, 1996, 2109, 2110, 1997, 1998, 2111, 1999, - 2112, 2113, 2114, 2115, 2000, 2001, 2116, 2002, 2117, 2118, - 2119, 2120, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011, 2012, 2013, 1451, 123, 122, 124, 0, 419, 420, - 0, 430, 0, 412, 417, 413, 0, 439, 432, 440, - 421, 411, 433, 422, 410, 208, 0, 441, 427, 415, - 0, 0, 0, 0, 259, 220, 401, 0, 155, 0, - 1349, 1359, 1368, 1364, 1358, 1366, 1356, 1362, 1348, 1370, - 1357, 1361, 1354, 1371, 1352, 1369, 1367, 1355, 1363, 1347, - 1351, 1338, 1343, 1374, 1365, 1372, 1360, 1373, 1375, 1350, - 1376, 1353, 0, 1320, 0, 0, 1828, 1879, 1833, 0, - 1846, 0, 1849, 1850, 1735, 1857, 1860, 1861, 1862, 1863, - 0, 763, 114, 109, 747, 0, 527, 697, 707, 747, - 752, 1031, 775, 1032, 0, 116, 1419, 1418, 1414, 1413, - 194, 1282, 1463, 1602, 1642, 1752, 1858, 1781, 1481, 1464, - 1458, 1462, 260, 588, 586, 0, 1216, 1602, 1642, 1739, - 1752, 1858, 1393, 1397, 0, 257, 1483, 1468, 0, 1469, - 114, 533, 580, 0, 264, 1432, 0, 1437, 0, 1715, - 560, 563, 1276, 561, 525, 0, 0, 1, 155, 0, - 161, 0, 584, 584, 0, 584, 0, 517, 0, 0, - 525, 520, 524, 694, 1342, 1447, 1480, 1858, 1781, 1467, - 1470, 1611, 0, 0, 1611, 0, 1611, 0, 1611, 0, - 0, 1457, 1200, 0, 1246, 117, 0, 0, 1331, 1327, - 1332, 1328, 1333, 1326, 1325, 1334, 1330, 0, 0, 0, - 366, 399, 398, 397, 396, 401, 1611, 1293, 0, 205, - 448, 449, 0, 0, 0, 0, 0, 1304, 108, 106, - 1611, 1452, 428, 429, 0, 418, 414, 416, 0, 0, - 1611, 1271, 438, 434, 1611, 438, 1238, 1611, 0, 0, - 212, 0, 394, 1340, 1377, 2000, 1391, 0, 1392, 1382, - 1346, 1378, 1379, 155, 0, 484, 1317, 1415, 0, 0, - 0, 1152, 747, 752, 0, 0, 765, 0, 1171, 0, - 1177, 0, 0, 0, 747, 532, 0, 707, 764, 110, - 0, 745, 746, 635, 635, 589, 0, 570, 757, 0, - 0, 760, 758, 0, 760, 0, 0, 0, 760, 756, - 715, 0, 635, 0, 745, 748, 635, 0, 767, 1337, - 0, 0, 0, 0, 0, 1461, 1459, 1460, 1465, 0, - 0, 0, 1248, 1250, 1251, 1120, 1261, 1010, 0, 1823, - 1824, 1825, 1192, 1826, 1827, 1829, 1830, 1831, 969, 1576, - 1832, 1259, 1834, 1836, 1837, 1839, 1840, 1841, 1842, 1843, - 1844, 0, 1260, 1847, 1680, 1852, 1853, 1855, 1858, 1859, - 1258, 1864, 0, 0, 0, 1227, 1143, 0, 1009, 0, - 0, 0, 1193, 1201, 1002, 0, 0, 811, 812, 833, - 834, 813, 839, 840, 842, 814, 0, 1223, 903, 998, - 1211, 1007, 1015, 1011, 1050, 1013, 1030, 1016, 1087, 1008, - 0, 1014, 1000, 1219, 570, 1217, 0, 1001, 1247, 570, - 1215, 1396, 1394, 1400, 1395, 0, 0, 0, 0, 0, - 110, 1440, 1439, 1431, 1429, 1430, 1428, 1427, 1434, 0, - 1436, 1343, 1138, 1140, 0, 562, 0, 0, 0, 514, - 513, 515, 3, 0, 0, 0, 0, 582, 583, 0, - 0, 0, 0, 0, 0, 0, 0, 678, 609, 610, - 612, 675, 679, 687, 0, 0, 0, 0, 0, 521, - 0, 1276, 1479, 1473, 1471, 0, 0, 0, 139, 139, - 0, 0, 0, 0, 0, 99, 48, 92, 0, 0, - 0, 0, 234, 247, 0, 0, 0, 0, 0, 244, - 0, 0, 227, 50, 221, 223, 0, 139, 0, 46, - 0, 0, 0, 52, 1455, 0, 484, 1199, 0, 119, - 120, 118, 111, 0, 2014, 1876, 1877, 1878, 1879, 1829, - 1880, 1881, 0, 1882, 1883, 1835, 1885, 1886, 1887, 1888, - 1889, 1890, 1891, 1892, 1842, 1894, 1895, 1896, 1897, 1898, - 1899, 2040, 1900, 1856, 1902, 1862, 0, 1903, 1023, 1146, - 594, 1144, 1277, 0, 112, 1264, 0, 1329, 0, 0, - 0, 0, 482, 0, 0, 0, 0, 1289, 0, 1611, - 206, 210, 0, 1611, 201, 1611, 366, 0, 1611, 366, - 1611, 0, 1303, 1306, 0, 431, 426, 424, 423, 425, - 1611, 253, 0, 0, 1272, 436, 437, 0, 405, 0, - 0, 407, 0, 0, 217, 0, 215, 0, 401, 155, - 0, 228, 1387, 1388, 1386, 0, 0, 1381, 1345, 231, - 248, 1390, 1380, 1389, 1344, 1339, 0, 0, 1335, 471, - 0, 0, 0, 0, 1153, 880, 879, 863, 864, 877, - 878, 865, 866, 873, 874, 882, 881, 871, 872, 867, - 868, 861, 862, 869, 870, 875, 876, 859, 860, 1166, - 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, - 1164, 1165, 0, 0, 706, 704, 0, 0, 0, 0, - 0, 0, 1193, 0, 973, 1008, 0, 0, 0, 1138, - 1176, 0, 0, 0, 0, 0, 0, 1138, 1182, 0, - 0, 731, 743, 0, 628, 634, 705, 703, 0, 1216, - 698, 0, 777, 0, 757, 0, 756, 0, 0, 759, - 753, 0, 754, 0, 0, 0, 0, 755, 0, 0, - 0, 0, 0, 701, 0, 743, 0, 702, 774, 1421, - 1420, 1416, 1403, 1411, 195, 0, 1268, 1904, 1905, 1906, - 821, 1907, 850, 828, 850, 850, 1908, 1909, 1910, 1911, - 817, 817, 830, 1912, 1913, 1914, 1915, 1916, 818, 819, - 855, 1917, 1918, 1919, 1920, 1921, 0, 0, 1922, 850, - 1923, 817, 1924, 1925, 1926, 822, 1927, 785, 1928, 0, - 1929, 820, 786, 1930, 858, 858, 1931, 0, 845, 1932, - 0, 1149, 795, 803, 804, 805, 806, 831, 832, 807, - 837, 838, 808, 902, 0, 817, 1269, 1270, 155, 1466, - 1482, 0, 1143, 1017, 849, 836, 1191, 0, 844, 843, - 0, 1143, 826, 825, 824, 1004, 0, 823, 1100, 850, - 850, 848, 928, 827, 0, 0, 0, 0, 0, 854, - 0, 852, 929, 907, 908, 0, 1226, 1235, 1138, 1142, - 0, 1002, 1138, 0, 0, 1090, 1092, 0, 1019, 1020, - 0, 1194, 1249, 1003, 0, 1254, 0, 0, 902, 902, - 1222, 1120, 0, 1110, 1113, 0, 0, 1117, 1118, 1119, - 0, 0, 0, 1214, 0, 1128, 1130, 0, 0, 944, - 1126, 0, 947, 0, 0, 0, 0, 1114, 1115, 1116, - 1106, 1107, 1108, 1109, 1111, 1112, 1124, 1105, 925, 0, - 999, 0, 1053, 0, 924, 1220, 696, 0, 1252, 696, - 1405, 1409, 1410, 1404, 1408, 0, 1399, 1398, 1401, 1402, - 1484, 0, 1441, 1425, 0, 1422, 1141, 691, 564, 1240, - 0, 568, 1446, 160, 159, 0, 0, 537, 536, 603, - 595, 597, 603, 0, 535, 0, 651, 652, 0, 0, - 0, 0, 684, 682, 1248, 1261, 639, 613, 638, 0, - 0, 617, 0, 643, 903, 677, 519, 607, 608, 611, - 518, 0, 680, 0, 690, 0, 556, 558, 541, 555, - 553, 538, 546, 678, 612, 0, 1448, 1472, 0, 0, - 0, 0, 0, 1611, 0, 0, 788, 83, 64, 318, - 138, 0, 0, 0, 0, 0, 0, 0, 91, 88, - 89, 90, 0, 0, 0, 0, 1268, 232, 233, 246, - 0, 237, 238, 235, 239, 240, 0, 0, 225, 226, - 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1456, 1449, 1195, 1200, 594, 594, - 594, 0, 592, 593, 0, 0, 0, 0, 0, 470, - 364, 374, 0, 0, 0, 1293, 205, 0, 0, 0, - 0, 0, 0, 401, 1296, 1294, 1292, 1295, 1297, 1582, - 189, 0, 0, 0, 0, 0, 197, 200, 0, 363, - 337, 0, 0, 1308, 0, 0, 0, 1611, 353, 1305, - 0, 1453, 0, 0, 251, 438, 1273, 0, 435, 438, - 1239, 0, 438, 219, 0, 0, 1341, 1383, 229, 249, - 230, 250, 484, 479, 509, 0, 487, 492, 468, 0, - 468, 0, 489, 493, 468, 488, 0, 468, 483, 1417, - 0, 1046, 0, 1036, 0, 0, 766, 0, 0, 1037, - 975, 976, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 993, 992, 1038, 770, 0, 773, 0, 0, 1174, 1175, - 0, 1039, 0, 0, 1181, 0, 0, 0, 1044, 0, - 708, 0, 0, 0, 623, 627, 630, 0, 633, 570, - 526, 1602, 1642, 0, 581, 581, 581, 579, 569, 0, - 655, 0, 0, 0, 732, 0, 0, 734, 736, 0, - 0, 739, 0, 714, 713, 0, 0, 0, 0, 778, - 0, 1244, 0, 0, 196, 0, 0, 0, 803, 0, - 0, 0, 793, 789, 0, 883, 884, 885, 886, 887, - 888, 889, 890, 891, 892, 893, 894, 809, 1281, 0, - 815, 1284, 1285, 1286, 1283, 1280, 1287, 1288, 0, 0, - 0, 0, 1190, 1186, 0, 0, 0, 0, 1095, 1097, - 1099, 0, 847, 846, 1104, 1110, 1113, 1117, 1118, 1119, - 1114, 1115, 1116, 1106, 1107, 1108, 1109, 1111, 1112, 0, - 1132, 0, 1086, 0, 0, 0, 0, 0, 0, 1225, - 0, 971, 0, 1021, 1006, 0, 0, 1093, 1022, 1227, - 1202, 0, 0, 0, 1257, 1256, 904, 913, 916, 948, - 949, 920, 921, 922, 926, 1279, 1278, 1221, 0, 1213, - 0, 0, 905, 930, 935, 0, 1183, 965, 0, 953, - 0, 943, 0, 951, 955, 931, 946, 0, 927, 0, - 1214, 1129, 1131, 0, 1127, 0, 917, 918, 919, 909, - 910, 911, 912, 914, 915, 923, 1103, 1101, 1102, 0, - 1200, 0, 1212, 0, 0, 1055, 0, 0, 950, 1218, - 0, 777, 594, 777, 0, 902, 1442, 1276, 1435, 1276, - 1424, 1139, 1241, 1275, 566, 0, 0, 0, 1444, 146, - 150, 0, 1201, 180, 182, 696, 0, 601, 602, 606, - 0, 0, 606, 585, 534, 1853, 1735, 0, 0, 0, - 0, 644, 685, 0, 676, 641, 642, 0, 640, 1248, - 645, 1247, 646, 649, 650, 618, 1236, 686, 688, 0, - 681, 0, 1242, 540, 559, 0, 0, 0, 0, 0, - 523, 522, 692, 0, 49, 0, 1611, 66, 0, 0, - 0, 0, 0, 0, 268, 0, 368, 268, 104, 1611, - 438, 1611, 438, 1506, 1577, 1753, 0, 62, 342, 95, - 0, 132, 371, 0, 327, 85, 100, 125, 0, 0, - 51, 222, 236, 241, 128, 245, 242, 1313, 243, 139, - 0, 47, 0, 126, 0, 1311, 0, 0, 53, 130, - 1315, 1457, 0, 1199, 0, 592, 592, 592, 0, 1145, - 0, 0, 0, 1147, 1148, 943, 1323, 1322, 1324, 1321, - 456, 469, 0, 365, 0, 481, 459, 460, 470, 1291, - 210, 0, 201, 366, 0, 366, 0, 1293, 0, 0, - 191, 187, 205, 211, 0, 0, 0, 0, 0, 364, - 356, 354, 387, 0, 361, 355, 0, 0, 313, 0, - 1500, 0, 0, 0, 0, 450, 0, 0, 0, 0, - 253, 254, 404, 1274, 406, 0, 408, 218, 216, 1336, - 476, 1143, 0, 474, 480, 475, 478, 473, 472, 0, - 467, 0, 502, 0, 0, 0, 0, 0, 0, 0, - 0, 1033, 1151, 0, 1169, 1168, 974, 981, 984, 988, - 989, 990, 1170, 0, 0, 0, 985, 986, 987, 977, - 978, 979, 980, 982, 983, 991, 775, 0, 0, 769, - 1179, 1178, 1172, 1173, 0, 1041, 1042, 1043, 1180, 0, - 0, 744, 621, 619, 622, 624, 620, 0, 0, 777, - 581, 581, 581, 581, 578, 0, 0, 0, 776, 0, - 672, 740, 738, 0, 762, 0, 735, 718, 741, 0, - 726, 0, 733, 782, 749, 0, 0, 751, 1412, 799, - 0, 794, 790, 0, 0, 0, 800, 0, 0, 0, - 0, 0, 0, 0, 1150, 587, 1018, 0, 0, 0, - 1187, 0, 970, 816, 829, 0, 1098, 1012, 0, 1121, - 1085, 857, 856, 858, 858, 0, 0, 0, 1234, 0, - 1139, 1089, 1091, 1235, 1005, 841, 902, 0, 0, 0, - 0, 0, 0, 0, 954, 945, 0, 952, 956, 0, - 0, 0, 939, 0, 0, 937, 966, 933, 0, 0, - 967, 1199, 0, 1203, 0, 0, 1054, 1063, 699, 695, - 655, 592, 655, 0, 1406, 1426, 1423, 567, 155, 1445, - 0, 169, 0, 0, 0, 0, 172, 186, 183, 1444, - 0, 0, 596, 598, 0, 1122, 606, 600, 648, 647, - 0, 616, 683, 614, 0, 689, 0, 557, 0, 543, - 0, 717, 0, 0, 0, 0, 0, 317, 0, 0, - 0, 268, 0, 376, 0, 383, 0, 0, 368, 349, - 84, 0, 0, 0, 58, 103, 76, 68, 54, 82, - 0, 0, 87, 0, 80, 97, 98, 96, 101, 0, - 278, 303, 0, 0, 314, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 484, 1200, 1196, 1200, - 0, 0, 0, 594, 590, 591, 1024, 0, 455, 508, - 505, 506, 504, 227, 375, 0, 0, 0, 199, 363, - 0, 1308, 0, 1290, 401, 0, 192, 0, 190, 210, - 0, 0, 201, 366, 0, 341, 337, 362, 335, 334, - 336, 0, 1501, 220, 0, 1495, 366, 1307, 0, 0, - 451, 0, 445, 0, 1302, 252, 438, 0, 463, 503, - 510, 490, 495, 0, 501, 497, 496, 491, 499, 498, - 494, 1034, 1045, 1167, 0, 0, 0, 0, 768, 771, - 0, 1040, 1035, 742, 0, 0, 655, 0, 0, 0, - 0, 572, 571, 577, 0, 0, 1057, 737, 0, 0, - 0, 724, 712, 719, 720, 0, 0, 0, 780, 779, - 750, 803, 0, 783, 803, 0, 803, 0, 801, 0, - 810, 895, 896, 897, 898, 899, 900, 901, 835, 0, - 1189, 1185, 1094, 1096, 1133, 853, 851, 1224, 1138, 1229, - 1231, 0, 0, 0, 1088, 972, 1255, 906, 0, 0, - 936, 1184, 957, 0, 0, 0, 932, 1121, 0, 0, - 0, 0, 0, 941, 0, 1207, 1200, 0, 1206, 0, - 0, 0, 0, 1029, 700, 672, 0, 672, 0, 0, - 1443, 0, 1438, 147, 148, 149, 0, 0, 0, 164, - 141, 0, 0, 181, 169, 157, 604, 605, 0, 599, - 615, 1237, 1243, 542, 0, 1002, 0, 0, 539, 0, - 133, 268, 0, 0, 65, 0, 385, 329, 377, 360, - 344, 0, 0, 0, 269, 0, 402, 0, 0, 350, - 0, 0, 0, 0, 330, 0, 0, 289, 0, 0, - 360, 0, 367, 285, 286, 0, 57, 77, 0, 73, - 0, 102, 0, 0, 0, 0, 0, 60, 72, 0, - 55, 0, 438, 438, 63, 1268, 1904, 1905, 1906, 1907, - 1908, 1909, 1910, 1911, 1912, 1913, 2024, 1914, 1915, 1916, - 1917, 1918, 1919, 1920, 1921, 2033, 1922, 275, 1923, 1680, - 1924, 1925, 1926, 1927, 1928, 0, 1929, 786, 1930, 1931, - 2112, 1932, 1106, 1107, 274, 273, 370, 270, 378, 272, - 0, 1269, 271, 373, 328, 129, 1314, 0, 127, 0, - 1312, 136, 134, 131, 1316, 1450, 0, 0, 1027, 1028, - 1025, 592, 0, 0, 0, 484, 462, 0, 0, 0, - 1500, 0, 0, 0, 1611, 0, 188, 0, 0, 202, - 1308, 198, 363, 0, 393, 313, 388, 0, 1500, 1498, - 0, 1308, 1494, 0, 442, 0, 0, 0, 409, 477, - 0, 500, 994, 0, 0, 0, 0, 631, 0, 637, - 672, 576, 575, 574, 573, 654, 1551, 1836, 1734, 0, - 658, 653, 656, 661, 663, 662, 664, 660, 671, 0, - 674, 761, 1134, 1136, 0, 0, 0, 0, 725, 727, - 0, 729, 0, 781, 797, 0, 798, 0, 796, 791, - 802, 1188, 1232, 1233, 1228, 0, 903, 963, 961, 958, - 0, 959, 940, 0, 0, 938, 934, 0, 968, 0, - 0, 1204, 0, 1049, 0, 1052, 1066, 1062, 1061, 1057, - 1024, 1057, 1407, 565, 168, 145, 171, 170, 0, 1201, - 178, 0, 0, 169, 0, 173, 452, 0, 0, 554, - 716, 547, 548, 0, 381, 67, 0, 360, 0, 268, - 346, 345, 348, 343, 347, 0, 403, 0, 0, 287, - 0, 294, 332, 333, 331, 288, 360, 366, 290, 0, - 0, 0, 69, 59, 56, 61, 70, 0, 0, 71, - 74, 782, 86, 79, 1268, 2033, 2042, 0, 0, 0, - 0, 0, 1198, 1197, 0, 458, 457, 507, 454, 465, - 227, 0, 0, 0, 337, 1497, 0, 0, 447, 0, - 0, 363, 193, 0, 0, 0, 0, 1500, 0, 0, - 265, 0, 310, 0, 213, 1499, 0, 0, 1486, 0, - 0, 1300, 1301, 0, 464, 995, 0, 996, 772, 0, - 0, 629, 1057, 0, 0, 0, 665, 659, 0, 1056, - 1058, 0, 626, 1137, 721, 0, 723, 0, 747, 0, - 747, 730, 792, 784, 1230, 1047, 0, 960, 964, 962, - 942, 1200, 1208, 1200, 1205, 1051, 1065, 1068, 674, 1253, - 674, 0, 0, 156, 0, 0, 153, 140, 158, 1123, - 544, 545, 0, 268, 0, 359, 382, 299, 277, 0, - 0, 0, 284, 291, 392, 293, 0, 78, 94, 0, - 0, 372, 137, 135, 1026, 484, 0, 204, 1308, 313, - 1494, 444, 0, 0, 0, 0, 337, 220, 1496, 326, - 319, 320, 321, 322, 323, 324, 325, 340, 339, 311, - 312, 0, 0, 0, 0, 0, 446, 1302, 0, 175, - 184, 0, 175, 997, 632, 0, 674, 0, 0, 0, - 657, 0, 0, 673, 0, 530, 1135, 0, 711, 709, - 0, 710, 0, 0, 0, 0, 594, 626, 626, 142, - 0, 143, 179, 0, 0, 0, 366, 384, 358, 0, - 351, 297, 296, 298, 302, 0, 300, 0, 316, 0, - 309, 277, 0, 81, 0, 379, 453, 461, 0, 267, - 1488, 363, 0, 203, 1494, 313, 1500, 1494, 0, 1491, - 0, 443, 0, 0, 0, 177, 1308, 0, 177, 0, - 626, 667, 0, 666, 1060, 1059, 628, 722, 0, 1048, - 1210, 1209, 0, 1072, 529, 528, 0, 0, 0, 0, - 392, 0, 338, 0, 0, 299, 0, 292, 389, 390, - 391, 0, 305, 295, 306, 75, 93, 380, 0, 363, - 1489, 266, 214, 1487, 1492, 1493, 0, 175, 174, 603, - 176, 777, 185, 603, 636, 531, 668, 625, 728, 1067, - 0, 0, 0, 0, 0, 152, 777, 163, 0, 309, - 357, 352, 276, 301, 315, 0, 0, 0, 307, 0, - 308, 1494, 0, 177, 606, 1298, 606, 1822, 1552, 1788, - 0, 1084, 1073, 1084, 1084, 1064, 144, 151, 0, 268, - 281, 0, 280, 0, 369, 304, 1490, 1308, 603, 165, - 166, 0, 1077, 1076, 1075, 1079, 1078, 0, 1071, 1069, - 1070, 777, 386, 279, 283, 282, 777, 606, 0, 0, - 1081, 0, 1082, 162, 1299, 167, 1074, 1080, 1083 -}; +#define YYTABLE_NINF (-2062) -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 48, 49, 50, 750, 2596, 2597, 2598, 2236, 1205, - 3363, 2237, 1206, 1207, 2600, 751, 801, 1092, 803, 1093, - 1603, 905, 1239, 1240, 752, 1752, 753, 2819, 2160, 2544, - 3345, 55, 3090, 2163, 1165, 3093, 3310, 2812, 3088, 2545, - 3385, 3439, 3091, 2164, 2165, 3311, 2166, 754, 2657, 2658, - 755, 756, 1836, 59, 1301, 546, 1833, 757, 1334, 1335, - 960, 758, 1837, 1780, 2935, 1225, 1770, 1349, 62, 1854, - 759, 106, 64, 760, 2585, 2936, 3356, 2611, 3494, 2872, - 2873, 3353, 3354, 2588, 2239, 3422, 3423, 2672, 1761, 3417, - 2320, 3297, 2243, 2224, 2874, 2328, 3255, 2984, 2240, 2854, - 2321, 3349, 1849, 2322, 3350, 3109, 2323, 1811, 1840, 2589, - 3424, 2244, 1812, 2584, 2937, 1749, 2324, 3360, 2325, 547, - 2858, 761, 741, 742, 952, 1328, 743, 762, 936, 1846, - 763, 764, 2638, 2298, 3160, 2687, 3161, 2361, 2292, 1358, - 2354, 1874, 1814, 1359, 535, 1888, 2688, 2643, 1875, 765, - 1094, 72, 73, 1007, 74, 3103, 75, 76, 1726, 1727, - 1728, 848, 860, 861, 2156, 1442, 1958, 853, 1169, 1695, - 835, 836, 2282, 876, 1803, 1690, 1691, 2169, 2552, 1719, - 1720, 1178, 1179, 1946, 3325, 1947, 1948, 1435, 1436, 3201, - 1707, 1711, 1712, 2190, 2180, 1698, 2430, 3020, 3021, 3022, - 3023, 3024, 3025, 3026, 1095, 2726, 3212, 1715, 1716, 1181, - 1182, 1183, 1724, 2200, 78, 79, 2141, 2528, 2529, 807, - 3037, 1461, 1729, 2730, 2731, 2732, 3040, 3041, 3042, 808, - 1002, 1003, 1026, 1021, 1450, 1967, 809, 810, 1923, 1924, - 2399, 1028, 1960, 1978, 1979, 2738, 2454, 1530, 2225, 1531, - 1532, 1993, 1533, 1096, 1534, 1562, 1097, 1567, 1536, 1098, - 1099, 1100, 1539, 1101, 1102, 1103, 1104, 1555, 1105, 1106, - 1579, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 1152, 1730, 1108, 1109, 1110, 1111, - 1112, 1113, 1114, 1115, 812, 1116, 1117, 1652, 2135, 2527, - 3030, 3209, 3210, 2803, 3078, 3237, 3336, 3453, 3481, 3482, - 3508, 1118, 1119, 1595, 1596, 1597, 2028, 2029, 2030, 2031, - 2129, 1646, 1647, 1120, 2939, 1649, 2051, 3033, 3034, 1153, - 1428, 1590, 1280, 1281, 1544, 1402, 1403, 1409, 1898, 1417, - 1421, 1928, 1929, 1429, 2097, 1121, 2022, 2023, 2471, 1557, - 1122, 1238, 1602, 2798, 2132, 1650, 2091, 1129, 1123, 1130, - 1125, 1586, 1587, 2488, 2770, 2771, 2061, 2197, 1679, 2202, - 2203, 956, 1126, 1127, 1128, 1282, 519, 1545, 3440, 1324, - 1158, 1283, 2087, 766, 1034, 2015, 767, 1297, 1826, 768, - 3192, 2997, 1313, 1850, 2333, 548, 769, 770, 528, 85, - 2287, 917, 86, 87, 88, 885, 1351, 771, 1352, 1353, - 967, 89, 2689, 969, 970, 773, 842, 843, 1473, 1666, - 1474, 774, 818, 1471, 775, 1148, 857, 1149, 1151, 776, - 1142, 2541, 2158, 94, 95, 96, 114, 1236, 777, 829, - 830, 866, 99, 100, 1193, 831, 849, 779, 780, 3188, - 781, 2675, 1307, 529, 521, 522, 1547, 715, 1285, 716 -}; +#define yytable_value_is_error(Yyn) \ + ((Yyn) == YYTABLE_NINF) /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -3059 static const int yypact[] = { - 6375, 351, 1052, -3059, -3059, 657, 351, 50036, 64871, 293, - 351, 181, 3103, 52016, -3059, -3059, 46571, 4517, 351, 54986, - 72207, 328, 274, 31911, 355, 55481, 55481, -3059, -3059, -3059, - 64871, 54986, 55976, 351, 358, 65366, -3059, 351, 34386, 52511, - 198, -3059, 54986, 65, 257, 56471, 54986, 4726, 600, 263, - -3059, -3059, -3059, -3059, -3059, 178, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, 150, -3059, 189, 154, 31911, 31911, 1366, 118, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 442, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - 33891, -3059, -3059, -3059, -3059, -3059, -3059, 56966, 54986, 57461, - 53006, 57956, -3059, 645, 965, -3059, 165, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 170, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 481, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, 183, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, 376, -3059, 516, -3059, - 195, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - 1178, -3059, -3059, 957, 3143, 54986, 432, 665, 718, -3059, - 58451, -3059, 725, 54986, -3059, -3059, 731, 774, 916, -3059, - -3059, 53501, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 47066, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, 877, -3059, -3059, - 706, -3059, 194, -3059, -3059, 729, 686, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, 787, -3059, -3059, -3059, - 789, 65861, 58946, 59441, -3059, 667, 2978, 6731, 72225, 30919, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, 442, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, 55481, 64871, 55481, 709, 723, 1076, 734, 32406, - 737, 34882, 753, 769, 1117, 776, 778, 785, 796, 257, - 31415, 807, 376, -3059, 59936, 59936, -26, 2686, -3059, 59936, - 60431, -3059, 822, -3059, 965, -3059, -3059, -3059, 1157, -3059, - -61, 816, -3059, 60926, 60926, 60926, 842, 1124, -3059, -3059, - -3059, 866, -3059, -3059, 1095, 20588, 20588, 66356, 66356, 965, - 66356, 876, -3059, -3059, 91, -3059, -3059, -3059, 1366, 882, - 376, -3059, -3059, 52511, -3059, -3059, 237, 1219, 20588, 54986, - 884, -3059, 886, 884, 892, 906, 913, -3059, 6375, 1264, - 1145, 52511, 364, 364, 1386, 364, 212, 587, 4710, 2869, - -3059, 887, -3059, 944, -3059, 54986, 1048, 974, 1244, -3059, - 882, 1329, 1242, 1133, 1338, 5360, 1346, 1336, 1375, 1623, - 1382, 1523, 20588, 47561, 376, -3059, 11731, 20588, -3059, -3059, - -3059, 1149, -3059, -3059, -3059, -3059, -3059, 54986, 64871, 1072, - 1075, -3059, -3059, -3059, -3059, 1022, 1317, -3059, 1558, 66851, - -3059, -3059, 1160, 61421, 61916, 62411, 62906, 1514, -3059, -3059, - 1490, -3059, -3059, -3059, 1167, -3059, -3059, -3059, 176, 67346, - 1500, 1154, 110, -3059, 1509, 172, -3059, 1522, 1409, 15378, - -3059, 1353, -3059, -3059, -3059, 257, -3059, 403, -3059, -3059, - 43428, -3059, -3059, 72225, 1281, 1207, -3059, 1556, 20588, 20588, - 1221, 5787, 59936, 60431, 20588, 54986, -3059, 20588, 25277, 1235, - 20588, 20588, 12773, 20588, 29929, 59936, 2686, 1248, -3059, 582, - 54986, 1243, -3059, 1347, 1347, 358, 31911, 1548, -3059, 375, - 1545, 1479, -3059, 31911, 1479, 977, 1269, 1562, 1479, -3059, - 253, 1567, 1347, 35377, 1282, -3059, 1347, 1516, -3059, -3059, - 55481, 20588, 15378, 69821, 1776, -3059, -3059, -3059, -3059, 1585, - 64871, 1308, -3059, -3059, -3059, -3059, -3059, -3059, 615, 1818, - 158, 1819, 20588, 158, 158, 1311, 196, 196, -3059, 1503, - 1314, -3059, 200, 1315, 1316, 1827, 1831, 180, 134, 871, - 158, 20588, -3059, 196, 1326, 1839, 1334, 1846, 138, 173, - -3059, 201, 20588, 20588, 20588, 1704, 20588, 10689, -3059, 54986, - 1844, 47561, 545, -3059, 376, 1341, 965, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, 1356, -3059, 185, 7003, -3059, -3059, - -3059, -3059, -3059, -3059, 1377, -3059, -3059, -3059, -3059, 1559, - 20588, -3059, -3059, 1343, 1548, -3059, 202, -3059, -3059, 1548, - -3059, -3059, -3059, -3059, -3059, 217, 1768, 20588, 20588, 64871, - 376, 67841, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 628, - -3059, 442, 45116, 1355, 1359, 884, 54986, 54986, 1835, -3059, - -3059, -3059, -3059, 52511, 159, 1657, 1491, -3059, -3059, 1366, - 1366, 15899, 1027, 220, 70, 16420, 21109, 1713, 1592, 225, - 586, 1715, -3059, 1598, 1825, 25277, 20588, 20588, 212, 587, - 20588, 886, -3059, -3059, -3059, 1651, 54986, 50531, 482, 553, - 1371, 1461, 1378, 29, 1798, -3059, 1376, -3059, 1465, 54986, - 71756, 244, -3059, 1855, 244, 244, 235, 1856, 1493, 261, - 1659, 630, -32, 1376, 2912, -3059, 52511, 156, 643, 1376, - 54986, 1494, 688, 1376, 1820, 64871, 1207, 41015, 1403, -3059, - -3059, -3059, 147, 15378, -3059, 1292, 1339, 1364, 367, 184, - 1400, 1542, 15378, 1602, 1650, 163, 1652, 1663, 1671, 1679, - 1683, 1687, 1703, 1705, 144, 1710, 1712, 1716, 1718, 1720, - 1724, -3059, 1728, 169, 1730, 199, 15378, 1733, -3059, 45116, - 8, -3059, -3059, 1738, 182, -3059, 45205, -3059, 1708, 1505, - 1506, 64871, 1455, 54986, 1560, 823, 1783, 1836, 70301, 1664, - -3059, 1741, 54986, 1666, 2912, 1667, 1429, 1904, 1672, 1075, - 1674, 1431, -3059, 68336, 47561, -3059, -3059, -3059, -3059, -3059, - 1797, 1780, 64871, 47561, 1437, -3059, -3059, 64871, -3059, 54986, - 54986, -3059, 54986, 64871, -3059, 644, 45116, 1941, 865, 72225, - 49046, -3059, -3059, -3059, -3059, 428, 951, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, 965, 47561, -3059, 2564, - 55481, 44046, 1444, 20588, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, 1449, 1801, -3059, -3059, 6587, 1453, 44086, 1454, - 25277, 25277, 376, 530, -3059, -3059, 25277, 1460, 49541, 43959, - 1463, 1467, 44434, 16941, 20588, 16941, 16941, 44521, -3059, 1471, - 44598, 59936, 1473, 54986, 53996, -3059, -3059, -3059, 20588, 20588, - 2686, 54491, 1515, 31911, -3059, 31911, -3059, 1765, 31911, -3059, - -3059, 2074, -3059, 31911, 1766, 20588, 31911, -3059, 31911, 1714, - 1717, 1477, 31911, -3059, 54986, 1482, 54986, -3059, -3059, -3059, - -3059, -3059, 45116, -3059, 1481, 690, 1485, -3059, -3059, -3059, - -3059, -3059, 1534, -3059, 1534, 1534, -3059, -3059, -3059, -3059, - 1492, 1492, 1497, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, 1498, 871, -3059, 1534, - -3059, 1492, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 71756, - -3059, -3059, -3059, -3059, -50, 501, -3059, 1501, -3059, -3059, - 1507, -3059, 1489, 1978, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, 5696, 699, 1492, -3059, -3059, 5470, -3059, - -3059, 20588, 20588, -3059, -3059, 1508, 45116, 1547, -3059, -3059, - 20588, 20588, -3059, -3059, -3059, -3059, 2011, -3059, 20588, 1534, - 1534, -3059, 45587, -3059, 39834, 17462, 1597, 1599, 2011, -3059, - 2011, -3059, 45587, 2015, 2015, 37852, -3059, 1675, 44685, -3059, - 1518, 2122, 7670, 1510, 1511, -3059, 1519, 1513, -3059, -3059, - 41943, 166, 376, 376, 20588, -3059, 2011, 20588, 8642, 8642, - -3059, 295, 69821, 20588, 20588, 20588, 20588, 20588, 20588, 20588, - 20588, 46076, 1606, 127, 64871, 20588, 20588, 1524, 858, -3059, - 20588, 1754, -3059, 1525, 20588, 1608, 312, 20588, 20588, 20588, - 20588, 20588, 20588, 20588, 20588, 20588, -3059, -3059, 28924, 344, - 550, 1860, 1879, 46, 291, 20588, 1871, 11731, -3059, 1871, - -3059, -3059, -3059, -3059, -3059, 204, -3059, -3059, 1481, 1481, - -3059, 64871, -3059, 54986, 237, 51521, 20588, -3059, -3059, 1527, - 1531, 485, 1594, -3059, -3059, 54986, 38347, 1833, -3059, 350, - 1533, -3059, 43920, 1790, 1833, 1366, -3059, -3059, 26319, 1673, - 1830, 1770, -3059, -3059, 1749, 1751, -3059, 1546, 45338, 21630, - 21630, -3059, 646, 45116, 1293, -3059, -3059, -3059, -3059, -3059, - -3059, 733, -3059, 54986, 82, 35872, -3059, 1552, 111, -3059, - 3217, 1885, 1847, 1713, 586, 1557, -3059, -3059, 1781, 1563, - 68831, 54986, 1845, 1804, 1859, 308, 69821, -3059, -3059, -3059, - -3059, 54986, 64871, 63401, 69326, 48056, 54986, 47561, -3059, -3059, - -3059, -3059, 54986, 1218, 54986, 8381, -3059, -3059, -3059, -3059, - 244, -3059, -3059, -3059, -3059, -3059, 64871, 54986, -3059, -3059, - 244, 64871, 54986, 244, -3059, 1939, 54986, 54986, 54986, 54986, - 2069, 54986, 54986, 965, -3059, -3059, -3059, 22151, 24, 24, - 1786, 13294, 203, -3059, 20588, 20588, 306, 294, 64871, 1753, - -3059, -3059, 700, 1795, 103, -3059, 64871, 1621, 54986, 54986, - 54986, 54986, 54986, 2076, -3059, -3059, -3059, -3059, -3059, 1575, - -3059, 1940, 2090, 1582, 1586, 1947, -3059, 2912, 1951, 51026, - 698, 2699, 1952, 1630, 1956, 13815, 2072, 1840, -3059, -3059, - 1824, -3059, 64871, 2106, -3059, 110, -3059, 47561, -3059, 172, - -3059, 1829, 205, -3059, 15378, 20588, -3059, -3059, -3059, -3059, - -3059, -3059, 1207, 29430, -3059, 714, -3059, -3059, 2075, 965, - 2075, 565, -3059, -3059, 2075, -3059, 2060, 2075, -3059, -3059, - 69821, -3059, 7960, -3059, 20588, 20588, -3059, 20588, 1949, -3059, - 2110, 2110, 69821, 25277, 25277, 25277, 25277, 25277, 25277, 486, - 1326, 25277, 25277, 25277, 25277, 25277, 25277, 25277, 25277, 25277, - 26840, 301, -3059, -3059, 715, 2085, 20588, 20588, 1960, 1949, - 20588, -3059, 69821, 1613, -3059, 1614, 1617, 20588, -3059, 69821, - -3059, 54986, 1619, 9, -2, -3059, 1622, 1627, -3059, 1548, - -3059, 713, 775, 54986, 2465, 5151, 5636, -3059, -3059, 20588, - 1962, 2074, 2074, 31911, -3059, 20588, 1629, -3059, -3059, 31911, - 1979, -3059, 2074, -3059, -3059, 36367, 2074, 69821, 748, -3059, - 54986, 69821, 758, 20588, -3059, 15378, 2143, 69821, 2108, 64871, - 64871, 2145, 1637, 1639, 2011, 1725, -3059, 1727, 1729, 1731, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 69821, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 1643, 1647, - 20588, 20588, 80, -3059, 8114, 1646, 1653, 6163, -3059, 1644, - -3059, 1649, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 1655, - -3059, 1661, -3059, 1669, 1677, 1682, 1676, 1681, 54986, -3059, - 22672, -3059, 64871, -3059, -3059, 20588, 20588, 54986, -3059, 1704, - -3059, 1685, 1688, 8303, -3059, -3059, -3059, 153, 394, 45444, - 291, 3594, 3594, 3594, 45587, -3059, -3059, -3059, 1692, -3059, - 25277, 25277, -3059, 2523, 2753, 10689, -3059, -3059, 1995, -3059, - 891, -3059, 1658, -3059, -3059, 3090, -3059, 39834, 45547, 20588, - 179, -3059, 20588, 1524, 20588, 1762, 3594, 3594, 3594, 268, - 268, 153, 153, 153, 394, 291, -3059, -3059, -3059, 1668, - 20588, 47561, -3059, 1680, 1684, 2038, 1334, 20588, -3059, -3059, - 31911, 1515, 8, 1515, 2011, 8642, -3059, 886, -3059, 886, - -3059, 45116, 54986, -3059, -3059, 1953, 1690, 31911, 1732, 2167, - 2157, 64871, -3059, -3059, 1693, 1871, 1719, -3059, -3059, 1721, - 20588, 3753, 1721, -3059, 1833, -5, 1929, 998, 998, 646, - 1931, -3059, -3059, 1774, -3059, -3059, -3059, 20588, 14336, 1389, - -3059, 1407, -3059, -3059, -3059, -3059, -3059, 1699, -3059, 1986, - -3059, 54986, -3059, -3059, 25277, 2172, 20588, 36862, 2174, 1974, - -3059, -3059, -3059, 1812, 1376, 20588, 1971, -3059, 187, 1734, - 2097, 371, 2049, 64871, -3059, 318, 353, -3059, 978, 2100, - 205, 2105, 205, 47561, 47561, 47561, 760, -3059, -3059, -3059, - 965, -3059, 271, 762, -3059, -3059, -3059, -3059, 1834, 933, - 1376, 2912, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 222, - 948, 1376, 1842, -3059, 1849, -3059, 1851, 1015, 1376, -3059, - -3059, 1523, 9124, 45116, 336, 203, 203, 203, 15378, -3059, - 1982, 1983, 1758, 45116, 45116, 142, -3059, -3059, -3059, -3059, - 1760, -3059, 236, -3059, 64871, -3059, -3059, -3059, 1753, 1836, - 1741, 54986, 2912, 1767, 2236, 1075, 1431, -3059, 1928, 901, - 1678, -3059, 64871, -3059, 47561, 64871, 54986, 54986, 54986, 63896, - -3059, -3059, -3059, 1769, 1772, -3059, -11, 2004, 2005, 54986, - 1821, 54986, 1378, 2255, 54986, -3059, 766, 17983, 2144, 54986, - 1780, -3059, -3059, -3059, -3059, 64871, -3059, -3059, 45116, -3059, - -3059, 20588, 48551, -3059, -3059, -3059, -3059, -3059, -3059, 47561, - -3059, 965, -3059, 965, 2020, 64871, 42438, 965, 42933, 965, - 1785, -3059, 45116, 8353, 45116, 1960, -3059, 214, 2110, 1848, - 1848, 1848, 4127, 2130, 240, 1788, 1848, 1848, 1848, 282, - 282, 214, 214, 214, 2110, 301, 822, 49541, 1789, -3059, - 45116, 45116, -3059, -3059, 1794, -3059, -3059, -3059, -3059, 1802, - 1803, -3059, -3059, -3059, -3059, -3059, -3059, 64871, 1037, 1515, - 198, 198, 198, 198, -3059, 54986, 54986, 54986, 45116, 2245, - 2120, -3059, -3059, 2074, 45116, 54986, -3059, 27882, -3059, 54986, - -3059, 2153, -3059, 2240, -3059, 54986, 830, -3059, -3059, -3059, - 857, 1809, 1639, 69821, 873, 879, -3059, 2011, 136, 1807, - 1512, 1319, 750, 1413, -3059, -3059, -3059, 1808, 44820, 20588, - -3059, 2181, -3059, -3059, -3059, 20588, 20588, -3059, 39834, -3059, - -3059, -3059, -3059, -45, -45, 1811, 10689, 45042, -3059, 2139, - 8435, 45116, -3059, 1675, -3059, -3059, 8642, 20588, 1205, 1826, - 20588, 1823, 20588, 2169, -3059, -3059, 1832, -3059, -3059, 69821, - 20588, 1850, 5197, 25277, 25277, 6403, -3059, 7322, 20588, 10689, - -3059, 41101, 1817, 1852, 1786, 18504, -3059, 2047, 1843, -3059, - 1962, 203, 1962, 1854, -3059, -3059, -3059, -3059, 5470, -3059, - 20588, 1990, 64871, 518, 1927, 890, -3059, 376, 38347, 1732, - 20588, 252, -3059, -3059, 1857, -3059, 1721, -3059, -3059, -3059, - 2083, -3059, -3059, -3059, 54986, -3059, 1862, -3059, 35872, 2184, - 11210, -3059, 35872, 54986, 54986, 40337, 2223, -3059, 64871, 64871, - 64871, -3059, 64871, 1861, 1863, 653, 1866, 389, -3059, 1021, - 653, 2206, 296, 1378, 261, 1561, 521, -3059, -3059, -3059, - 1943, 54986, -3059, 64871, -3059, -3059, -3059, -3059, -3059, 48056, - -3059, -3059, 39338, 47561, -3059, 47561, 54986, 54986, 54986, 54986, - 54986, 54986, 54986, 54986, 54986, 54986, 1207, 20588, -3059, 20588, - 1868, 1869, 1874, 1786, -3059, -3059, -3059, 206, -3059, 1870, - -3059, -3059, -3059, -32, -3059, 236, 1877, 1878, -3059, 51026, - 3143, 1630, 2353, 1836, 850, 64376, -3059, 1882, 1876, 1741, - 897, 912, 2912, 1884, 2359, -3059, 698, 51026, -3059, -3059, - -3059, 2315, -3059, 667, 232, -3059, 1075, -3059, 3143, 1431, - -3059, 3143, 45116, 64871, 1948, -3059, 205, 922, -3059, -3059, - -3059, -3059, -3059, 64871, 1886, -3059, 1886, -3059, -3059, 1886, - -3059, -3059, -3059, -3059, 25277, 2234, 1892, 69821, -3059, -3059, - 54986, -3059, -3059, -3059, 942, 1894, 1962, 54986, 54986, 54986, - 54986, -3059, -3059, -3059, 19025, 20588, 1932, -3059, 1895, 12252, - 2213, -3059, 27361, -3059, -3059, 1899, 36367, 64871, -3059, -3059, - -3059, -3059, 2011, -3059, -3059, 64871, -3059, 1902, -3059, 1903, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, 20588, - 45116, -3059, 45116, -3059, -3059, -3059, -3059, -3059, 7369, -3059, - 1907, 1905, 64871, 20588, -3059, -3059, -3059, 747, 20588, 20588, - 2523, -3059, 6937, 20588, 69821, 962, 2523, 347, 20588, 2239, - 3853, 20588, 20588, 7350, 40376, -3059, 23193, 14857, -3059, 1906, - 20588, 40415, 38842, -3059, 31911, 2120, 1911, 2120, 965, 1913, - 45116, 20588, -3059, -3059, -3059, -3059, 1969, 349, 33396, 2142, - -3059, 1930, 64871, -3059, 1990, 45116, -3059, -3059, 39834, -3059, - -3059, -3059, -3059, -3059, 2373, 2635, 1923, 1924, -3059, 1340, - -3059, -3059, 64871, 1925, -3059, 1935, 653, -3059, 64871, 1968, - -3059, 272, 2241, 113, -3059, 20588, -3059, 2330, 2411, 1021, - 1942, 64871, 54986, 25277, -3059, 625, 243, -3059, 2227, 54986, - 1968, 2369, -3059, -3059, -3059, 389, -3059, 2268, 2185, -3059, - 244, -3059, 20588, 389, 2188, 137, 64871, -3059, -3059, 2738, - -3059, 69821, 205, 205, -3059, 1485, 1954, 1955, 1958, 1959, - 1961, 1965, 1967, 1972, 1973, 1976, -3059, 1988, 1989, 1992, - 1993, 1994, 1997, 1998, 1999, 1498, 2000, -3059, 2001, 1857, - 2006, 2013, 2016, 2019, 2021, 70781, 2026, 2028, 2031, 2033, - 1501, 2034, 428, 951, -3059, -3059, -3059, -3059, -3059, -3059, - 1154, 2035, -3059, 1975, -3059, -3059, -3059, 2044, -3059, 2056, - -3059, -3059, -3059, -3059, -3059, -3059, 1981, 2007, -3059, -3059, - -3059, 203, 1970, 1984, 64871, 1207, 151, 47561, 64871, 2037, - 1821, 2496, 19546, 1159, 2279, 2041, -3059, 965, 2053, -3059, - 1630, -3059, 51026, 3125, 669, 2005, -3059, 208, 1821, -3059, - 2451, 1630, 2094, 2521, -3059, 2282, 64871, 2059, -3059, -3059, - 48551, 1886, 4313, 25277, 69821, 964, 970, -3059, 2568, 2231, - 2120, -3059, -3059, -3059, -3059, -3059, 2064, -25, 2078, 10168, - 2065, -3059, -3059, -3059, -3059, -3059, -3059, 45116, 45116, 64871, - 2251, -3059, -3059, 2071, 2081, 37357, 2531, 2082, -3059, -3059, - 2395, -3059, 30424, -3059, 1639, 2086, 1639, 69821, 1639, -3059, - -3059, 45116, 20588, -3059, -3059, 41369, 2407, 2523, 2523, 6937, - 987, -3059, 2523, 20588, 20588, 2523, 2523, 20588, -3059, 9646, - 409, -3059, 995, -3059, 40462, -3059, 71261, -3059, -3059, 1932, - 965, 1932, -3059, -3059, 2089, -3059, -3059, -3059, 2141, -3059, - -3059, 1049, 2510, 1990, 20588, -3059, -3059, 2096, 35872, -3059, - -3059, -3059, -3059, 35872, 653, -3059, 2260, 1968, 2095, -3059, - -3059, -3059, -3059, -3059, -3059, 40501, -3059, 52, 20588, -3059, - 1046, 4127, -3059, -3059, -3059, -3059, 1968, 1075, -3059, 54986, - 2573, 2463, -3059, -3059, 45116, -3059, -3059, 2011, 2011, -3059, - -3059, 2240, -3059, -3059, 2101, -3059, -3059, 1154, 512, 39338, - 54986, 54986, -3059, -3059, 2103, -3059, -3059, -3059, -3059, -3059, - -32, 2497, 1064, 1065, 698, -3059, 3143, 3143, 45116, 54986, - 2471, 51026, -3059, 47561, 2587, 2113, 54986, 1821, 1137, 1137, - -3059, 2263, -3059, 2266, -3059, -3059, 2595, 276, -3059, 20067, - 54986, -3059, -3059, 32901, -3059, 4313, 1070, -3059, -3059, 2124, - 2126, -3059, 1932, 20588, 2127, 20588, -3059, 23714, 2602, 2125, - -3059, 20588, 2190, 28403, -3059, 20588, -3059, 54986, 59936, 2132, - 59936, -3059, -3059, -3059, -3059, -3059, 20588, -3059, 2523, 2523, - 2523, 20588, -3059, 20588, -3059, -3059, -3059, 2338, 2251, -3059, - 2251, 20588, 3143, 376, 2620, 64871, 20, -3059, 45116, -3059, - -3059, -3059, 54986, -3059, 47561, -3059, 653, 326, 2134, 20588, - 40851, 2372, -3059, -3059, 2405, -3059, 2464, -3059, 2201, 573, - 2222, -3059, -3059, -3059, -3059, 1207, 965, -3059, 1630, 2005, - 2094, -3059, 2148, 54986, 1084, 3143, 698, 667, -3059, -3059, - -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, -3059, - -3059, 3143, 2596, 2377, 2597, 3143, 45116, 1948, 20588, 79, - -3059, 1128, 2592, -3059, -3059, 2664, 2251, 2159, 23714, 2160, - -3059, 2162, 64871, 45116, 2309, -3059, -3059, 2166, -3059, -3059, - 20588, -3059, 41451, 2171, 2175, 2626, 1786, 2190, 2190, -3059, - 349, -3059, -3059, 2586, 32901, 2556, 1075, 653, 2187, 1136, - -3059, -3059, -3059, -3059, -3059, 2912, -3059, 40937, 2419, 122, - 2403, 2134, 20588, -3059, 2256, -3059, -3059, -3059, 2654, -3059, - -3059, 51026, 2182, -3059, 2094, 2005, 1821, 2094, 2406, -3059, - 2409, -3059, 2189, 40976, 64871, 64871, 1630, 32901, 64871, 2191, - 2190, -3059, 2192, -3059, -3059, -3059, 53996, -3059, 2193, -3059, - -3059, -3059, 20588, 135, -3059, -3059, 2252, 54986, 1138, 51, - 2405, 39338, -3059, 47561, 174, 326, 2500, -3059, -3059, -3059, - -3059, 209, 2421, -3059, 2423, -3059, 45116, -3059, 3143, 51026, - -3059, -3059, -3059, -3059, -3059, -3059, 32901, 2592, -3059, 350, - -3059, 1515, -3059, 350, -3059, -3059, -3059, -3059, -3059, 1463, - 24235, 24235, 24235, 2198, 3143, -3059, 1515, -3059, 2328, 2403, - -3059, -3059, -3059, -3059, -3059, 457, 457, 2598, -3059, 2273, - -3059, 2094, 1142, 64871, 1721, -3059, 1721, 25798, 2354, 238, - 43998, 2578, -3059, 2578, 2578, -3059, -3059, -3059, 38347, -3059, - -3059, 2702, -3059, 227, -3059, -3059, -3059, 1630, 350, -3059, - -3059, 2693, -3059, -3059, -3059, -3059, -3059, 343, -3059, -3059, - -3059, 1515, 653, -3059, -3059, -3059, 1515, 1721, 24756, 2365, - -3059, 2435, -3059, -3059, -3059, -3059, -3059, -3059, -3059 + 5967, -16, 747, -3106, -3106, 276, -16, 50116, 65539, 370, + -16, 120, 4354, 52108, -3106, -3106, 46630, 40587, -16, 55594, + 72920, 311, 385, 32053, 332, 56092, -3106, -3106, -3106, 65539, + 55594, 56590, -16, 371, 66037, -3106, -16, 34543, 52606, 68, + -3106, 55594, 44, -54, 57088, 55594, 1660, 556, 246, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, 248, -3106, -3106, -3106, -3106, 130, -3106, + 561, -3106, -3106, -3106, -3106, 143, -3106, 315, 167, 32053, + 32053, 2048, 272, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, 34045, -3106, -3106, -3106, -3106, 57586, 55594, + 58084, 53104, 58582, -3106, 560, 860, 538, 139, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + 155, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, 374, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, 177, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + 344, 182, -3106, -3106, -3106, 383, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, 2597, -3106, -3106, 815, 3310, 55594, + 723, 1010, 594, -3106, 59080, -3106, 577, 55594, -3106, -3106, + 154, 621, 844, -3106, -3106, 53602, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, 47128, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, 845, -3106, -3106, 617, -3106, 168, -3106, -3106, 705, + 663, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + 762, -3106, -3106, -3106, 779, 66535, 59578, 60076, -3106, 672, + 1406, 4718, 72938, 31055, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, 248, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, 56092, 65539, 675, + 681, 1041, 698, 32551, 702, 35042, 714, 721, 1070, 794, + 797, 822, 827, -54, 31554, 754, 344, -3106, 60574, 60574, + -9, 2610, -3106, 60574, 61072, -3106, 776, -3106, 860, -3106, + -3106, -3106, -3106, -65, 832, -3106, 61570, 61570, 61570, 855, + 1073, -3106, -3106, -3106, 848, -3106, -3106, 1098, 20664, 20664, + 67033, 67033, 860, 67033, 892, -3106, -3106, 106, 538, -3106, + -3106, 2048, 861, 344, -3106, -3106, 52606, -3106, -3106, 280, + 1229, 20664, 55594, 887, -3106, 895, 887, 908, 952, 976, + -3106, 5967, -3106, 55594, 1280, 1221, 54100, 56092, 382, 382, + 1473, 382, 995, 1008, 1857, 3596, -3106, 1859, -3106, 1024, + 1123, 1058, 1341, -3106, 861, 1425, 772, 1227, 1431, 6422, + 1444, 935, 1447, 1373, 1449, 1568, 26, -3106, 20664, 47626, + 344, -3106, 11756, 20664, -3106, -3106, -3106, 1192, -3106, -3106, + -3106, -3106, -3106, 55594, 65539, 1109, 1116, -3106, -3106, -3106, + -3106, 864, 1356, -3106, 1612, -3106, -3106, 1167, 62068, 62566, + 63064, 63562, 67531, 1567, -3106, -3106, 1510, -3106, -3106, -3106, + 1182, -3106, -3106, -3106, 192, 68029, 1516, 1151, 126, -3106, + 1525, 156, -3106, 1535, 1410, 15424, -3106, 1358, -3106, -3106, + -3106, -54, -3106, -3106, -3106, 646, -3106, -3106, 43725, 72938, + 1273, 1199, -3106, 20664, 20664, 1207, 5590, 60574, 61072, 20664, + 55594, -3106, 20664, 25380, 1210, 20664, 20664, 12804, 20664, 30059, + 60574, 2610, 1240, -3106, 742, 55594, 1222, -3106, 1339, 1339, + 371, 32053, 1543, -3106, 1040, 1540, 1476, -3106, 32053, 1476, + 1346, 1263, 1556, 1476, -3106, 238, 1557, 1339, 35540, 1266, + -3106, 1339, 1487, -3106, -3106, 20664, 15424, 70519, 1748, -3106, + -3106, -3106, -3106, 1553, 65539, 1277, -3106, -3106, -3106, -3106, + -3106, -3106, 858, 1790, 179, 1792, 20664, 179, 179, 1281, + 188, 188, -3106, 1474, 1283, -3106, 195, 1285, 1286, 1799, + 1801, 176, 159, 998, 179, 20664, -3106, 188, 1293, 1802, + 1294, 1807, 140, 172, -3106, 205, 20664, 20664, 20664, 310, + 20664, 10708, -3106, 55594, 1805, 47626, 420, -3106, 344, 1299, + 860, -3106, -3106, -3106, -3106, -3106, -3106, -3106, 1300, -3106, + 200, 6891, -3106, -3106, -3106, -3106, -3106, -3106, 1338, -3106, + -3106, -3106, -3106, 1517, 20664, -3106, -3106, 1301, 1543, -3106, + 206, -3106, -3106, 1543, -3106, -3106, -3106, -3106, -3106, 224, + 1717, 20664, 20664, -3106, 65539, 344, -3106, 68527, -3106, -3106, + -3106, -3106, -3106, -3106, 676, -3106, 248, 45374, 1304, 1306, + 887, 55594, 55594, 1786, -3106, -3106, -3106, -3106, 895, 52606, + 158, 1608, 134, 1441, 91, -3106, -3106, 2048, 2048, 15948, + 113, 211, 849, 16472, 21188, 1680, 1562, 502, 569, 1689, + -3106, 1565, 1793, 25380, 20664, 20664, 995, 1008, 20664, -3106, + -3106, -3106, 1622, 55594, 50614, 851, 950, 1342, 1429, 1345, + 92, 1771, -3106, 1344, -3106, 1439, 55594, 72466, 216, -3106, + 1815, 216, 216, 671, 1817, 1450, 270, 1600, 407, -66, + 4038, -3106, 1344, 52606, 144, 662, 1344, 55594, 1455, 686, + 1344, 1770, 65539, 1199, -3106, -3106, 41297, 1360, -3106, -3106, + -3106, 178, 15424, -3106, 1271, 1307, 1348, 369, 166, 1427, + 1432, 15424, 1448, 1513, 181, 1539, 1572, 1575, 1578, 1580, + 1592, 1637, 1645, 157, 1647, 1661, 1666, 1668, 1670, 1677, + -3106, 1679, 183, 1683, 193, 15424, 1685, -3106, 199, -3106, + 45374, 33, -3106, -3106, 1693, 45573, -3106, 1667, 1457, 1461, + 65539, 1423, 55594, 836, 1523, 1752, 1812, 71002, 55594, 1638, + 4038, 1649, 1408, 1886, 1652, 1116, 1653, 1415, 1662, -3106, + 1739, -3106, 69025, 47626, -3106, -3106, -3106, -3106, -3106, 1787, + 1769, 65539, 47626, 1424, -3106, -3106, 65539, -3106, 55594, 55594, + -3106, 55594, 65539, -3106, 703, 45374, 1931, 623, 72938, 49120, + -3106, -3106, -3106, -3106, 1056, 1097, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, 860, 47626, -3106, 2013, 44345, + 1430, 20664, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, 1434, 1773, -3106, -3106, 6565, 1437, 44640, + 1438, 25380, 25380, 344, 1864, -3106, -3106, 25380, 1442, 49618, + 44259, 1426, 1443, 44864, 16996, 20664, 16996, 16996, 44932, -3106, + 1445, 44986, 60574, 1451, 55594, 54598, -3106, -3106, -3106, 20664, + 20664, 2610, 55096, 1488, -3106, 32053, -3106, 1734, 32053, -3106, + -3106, 4226, -3106, 32053, 1744, 20664, 32053, -3106, 1691, 1697, + 1470, 32053, -3106, 55594, 1472, 55594, -3106, -3106, 45374, -3106, + 1469, 707, 1475, -3106, -3106, -3106, -3106, -3106, 1529, -3106, + 1529, 1529, -3106, -3106, -3106, -3106, 1479, 1479, 1486, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, 1490, 998, -3106, 1529, -3106, 1479, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, 72466, -3106, -3106, -3106, -3106, + 395, 719, -3106, 1491, -3106, -3106, -3106, -3106, 1493, -3106, + 1485, 1952, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, 44491, 709, 1479, 4655, -3106, -3106, 20664, 20664, -3106, + -3106, 1495, 45374, 1530, -3106, -3106, 20664, 20664, -3106, -3106, + -3106, -3106, 2004, -3106, 20664, 1529, 1529, -3106, 7184, -3106, + 40024, 17520, 1585, 1586, 2004, -3106, 2004, -3106, 7184, 2005, + 2005, 1501, 38030, -3106, 1664, 45053, -3106, 1504, 1784, 7514, + 1506, 1498, -3106, 1511, 1507, -3106, -3106, 42231, 171, 344, + 344, 20664, -3106, 2004, 20664, 44717, 44717, -3106, 228, 70519, + 20664, 20664, 20664, 20664, 20664, 20664, 20664, 20664, 46132, 1604, + 173, 65539, 20664, 20664, 1518, 987, -3106, 20664, 1754, -3106, + 1519, 20664, 1606, 245, 20664, 20664, 20664, 20664, 20664, 20664, + 20664, 20664, 20664, -3106, -3106, 29048, 267, 597, 1860, 1877, + 24, 334, 20664, 1871, 11756, -3106, 1871, -3106, -3106, -3106, + -3106, -3106, 209, -3106, -3106, 1469, 1469, -3106, 65539, -3106, + 55594, 280, 51610, 20664, -3106, -3106, 1526, 1528, 598, -3106, + 1587, -3106, -3106, 55594, -3106, 38528, 56092, 56092, -3106, 1831, + -3106, 328, 1531, -3106, 44220, 1785, 1831, 2048, -3106, -3106, + 26428, 1658, 1828, 1766, -3106, -3106, 1746, 1747, -3106, 1541, + 45621, 21712, 21712, -3106, 1343, 45374, 1349, -3106, -3106, -3106, + -3106, -3106, -3106, 80, -3106, 55594, 365, 36038, -3106, 1544, + 87, -3106, 2247, 1892, 1847, 1680, 569, 1558, -3106, 1375, + 1561, 69523, 55594, 1856, 1809, 1858, -58, 70519, -3106, -3106, + -3106, -3106, 55594, 65539, 64060, 70021, 48124, 55594, 47626, -3106, + -3106, -3106, -3106, 55594, 1119, 55594, 6583, -3106, -3106, -3106, + -3106, 216, -3106, -3106, -3106, -3106, -3106, 65539, 55594, -3106, + -3106, 216, 65539, 55594, 216, -3106, 1596, 55594, 55594, 55594, + 55594, 1640, 55594, 55594, 860, -3106, -3106, -3106, 22236, 50, + 50, 1778, 13328, 169, -3106, 20664, 20664, 265, 268, 65539, + 1753, -3106, -3106, 753, 1800, 204, -3106, 1620, 55594, 55594, + 55594, 55594, 65539, 55594, 2250, -3106, -3106, -3106, -3106, -3106, + 1574, -3106, 1576, 1944, 4038, -3106, 1946, 51112, 974, 2244, + 1950, 1624, 1953, 13852, 2066, 1955, 2105, 1594, 1834, -3106, + -3106, 1824, -3106, 65539, 2116, -3106, 126, -3106, 47626, -3106, + 156, -3106, 1830, 237, -3106, 15424, 20664, -3106, -3106, -3106, + -3106, -3106, -3106, 1199, 29557, -3106, 755, -3106, -3106, 2084, + 860, 2084, 536, -3106, -3106, 2084, -3106, 2069, 2084, -3106, + 70519, -3106, 7958, -3106, 20664, 20664, -3106, 20664, 1957, -3106, + 2114, 2114, 70519, 25380, 25380, 25380, 25380, 25380, 25380, 695, + 1293, 25380, 25380, 25380, 25380, 25380, 25380, 25380, 25380, 25380, + 26952, 514, -3106, -3106, 759, 2090, 20664, 20664, 1964, 1957, + 20664, -3106, 70519, 1614, -3106, 1615, 1619, 20664, -3106, 70519, + -3106, 55594, 1625, 12, 9, -3106, 1621, 1623, -3106, 1543, + -3106, 1076, 1090, 55594, 3376, 4035, 5104, -3106, -3106, 20664, + 1967, 4226, 32053, -3106, 20664, 1632, -3106, -3106, 32053, 1983, + -3106, -3106, -3106, 36536, 4226, 70519, 765, -3106, 55594, 70519, + 773, 20664, -3106, 15424, 2148, 70519, 2120, 65539, 65539, 2159, + 1650, 1651, 2004, 1733, -3106, 1736, 1737, 1738, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, 70519, -3106, + -3106, -3106, -3106, 196, -3106, -3106, -3106, -3106, 1655, 1669, + 20664, 20664, 108, -3106, 8113, 1665, 1671, 6227, -3106, 1672, + -3106, 1663, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, 1657, + -3106, 1673, -3106, 1674, 1682, 1686, 1676, 1681, 20664, 55594, + -3106, 22760, -3106, 65539, -3106, -3106, 20664, 20664, 55594, -3106, + 2042, -3106, 1684, 1687, 8257, -3106, -3106, -3106, 230, 438, + 45639, 334, 5393, 5393, 5393, 7184, -3106, -3106, -3106, 1701, + -3106, 25380, 25380, -3106, 4732, 2997, 10708, -3106, -3106, 2025, + -3106, 880, -3106, 1690, -3106, -3106, 4909, -3106, 40024, 7863, + 20664, 186, -3106, 20664, 1518, 20664, 1772, 5393, 5393, 5393, + 240, 240, 230, 230, 230, 438, 334, -3106, -3106, -3106, + 1694, 20664, 47626, -3106, 1696, 1698, 2049, 1294, 20664, -3106, + -3106, 32053, 1488, 33, 1488, 2004, 44717, -3106, 895, -3106, + -3106, 895, 45374, 55594, -3106, -3106, 1956, 1699, 32053, 1741, + 2170, 2160, 65539, -3106, -3106, 1703, 1871, 1716, 1757, 1757, + -3106, -3106, -3106, -3106, 1724, 20664, 4102, 1724, -3106, 1831, + 25, 1937, 1114, 1114, 1343, 1938, -3106, -3106, 1779, -3106, + -3106, -3106, 20664, 14376, 1351, -3106, 1366, -3106, -3106, -3106, + -3106, -3106, 1711, -3106, 1990, -3106, 55594, -3106, -3106, 25380, + 2177, 20664, 37034, 2178, 1973, -3106, -3106, -3106, 1816, 1344, + 20664, 1971, -3106, 162, 1731, 2097, -50, 2047, 65539, -3106, + 293, 355, -3106, 466, 2099, 237, 2107, 237, 47626, 47626, + 47626, 775, -3106, -3106, -3106, 860, -3106, 45, 780, -3106, + -3106, -3106, -3106, 1826, 717, 4038, 1344, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, 202, 809, 1344, 1829, -3106, 1833, + -3106, 1839, 885, 1344, -3106, -3106, 1568, 9134, 45374, 517, + 169, 169, 169, 15424, -3106, 1979, 1989, 1755, 45374, 45374, + 135, -3106, -3106, -3106, -3106, 1758, -3106, 349, -3106, 65539, + -3106, -3106, -3106, 1753, 1812, 55594, 4038, 1759, 2225, 1116, + 1415, 1739, -3106, 1919, 66, 787, -3106, 65539, 55594, 55594, + 55594, 64558, -3106, -3106, -3106, 1760, 1756, -3106, 0, 1991, + 1992, 55594, 1806, 55594, 1345, 2248, 55594, -3106, 781, 18044, + 65539, -3106, 47626, 2132, 55594, 1769, -3106, -3106, -3106, -3106, + 65539, -3106, -3106, 45374, -3106, -3106, 20664, 48622, -3106, -3106, + -3106, -3106, -3106, -3106, 47626, -3106, 860, -3106, 860, 2007, + 65539, 42729, 860, 43227, 860, 1774, -3106, 45374, 8305, 45374, + 1964, -3106, 152, 2114, 3516, 3516, 3516, 2635, 2118, 234, + 1777, 3516, 3516, 3516, 278, 278, 152, 152, 152, 2114, + 514, 776, 49618, 1788, -3106, 45374, 45374, -3106, -3106, 1789, + -3106, -3106, -3106, -3106, 1794, 1795, -3106, -3106, -3106, -3106, + -3106, -3106, 65539, 1124, 1488, 68, 68, 68, 68, -3106, + 55594, 55594, 55594, 45374, 2232, 2109, -3106, 4226, 45374, 55594, + -3106, 28000, 55594, -3106, 2129, -3106, 2224, -3106, 55594, 801, + -3106, -3106, -3106, 812, 1796, 1651, 70519, 820, 839, -3106, + 2004, 142, 1808, 1483, 678, 833, 1370, -3106, 52606, -3106, + -3106, 1811, 45185, 20664, -3106, 2165, -3106, -3106, -3106, 20664, + 20664, -3106, 40024, -3106, -3106, -3106, -3106, -79, -79, 8558, + 1818, 10708, 45252, -3106, 2111, 40530, 45374, -3106, 1664, -3106, + -3106, 44717, 20664, 1232, 1332, 20664, 1819, 20664, 2146, -3106, + -3106, 1810, -3106, -3106, 70519, 20664, 1823, 5208, 25380, 25380, + 5473, -3106, 5880, 20664, 10708, -3106, 41650, 1803, 1832, 1778, + 18568, -3106, 2018, 1814, -3106, 1967, 169, 1967, 1837, -3106, + -3106, -3106, -3106, 4655, -3106, 20664, 1972, 65539, 303, 2675, + 853, -3106, 344, 38528, 1741, 20664, -3106, -3106, 242, -3106, + -3106, 1840, -3106, 1724, -3106, -3106, -3106, 2057, -3106, -3106, + -3106, 55594, -3106, 1843, -3106, 36038, 2181, 11232, -3106, 36038, + 55594, 55594, 40569, 2199, -3106, 65539, 65539, 65539, -3106, 65539, + 1845, 1853, 834, 1841, 793, -3106, 4177, 834, 2205, 264, + 1345, 270, 4269, 59, -3106, -3106, -3106, 1940, 55594, -3106, + 65539, -3106, -3106, -3106, -3106, -3106, 48124, -3106, -3106, 39525, + 47626, -3106, 47626, 55594, 55594, 55594, 55594, 55594, 55594, 55594, + 55594, 55594, 55594, 1199, 20664, -3106, 20664, 1865, 1867, 1870, + 1778, -3106, -3106, -3106, 201, -3106, 1873, -3106, -3106, -3106, + -66, -3106, 349, 1872, -3106, 51112, 3310, 1624, 2350, 1876, + 1812, 377, 65041, -3106, 1878, 1879, 869, 4038, 1884, 2354, + -3106, 974, 51112, -3106, -3106, -3106, 2318, -3106, 672, 235, + -3106, 1116, -3106, 3310, 1415, -3106, 3310, 45374, 1739, 875, + 65539, 1954, -3106, 237, 888, -3106, -3106, -3106, -3106, -3106, + 65539, 1888, -3106, 1888, -3106, -3106, 1888, -3106, -3106, -3106, + -3106, 25380, 2235, 1893, 70519, -3106, -3106, 55594, -3106, -3106, + -3106, 903, 1896, 1967, 55594, 55594, 55594, 55594, -3106, -3106, + -3106, 19092, 20664, 1945, -3106, 1897, 12280, 2223, -3106, 27476, + -3106, -3106, 1906, 36536, 65539, -3106, -3106, -3106, -3106, 2004, + -3106, -3106, 65539, -3106, 1909, -3106, 1910, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, 20664, 45374, -3106, 45374, + -3106, -3106, -3106, -3106, -3106, -3106, 7080, -3106, 1908, 1913, + 65539, 20664, -3106, -3106, -3106, 376, 20664, 20664, 4732, -3106, + 8504, 20664, 70519, 916, 4732, 330, 20664, 2579, 3641, 20664, + 20664, 6361, 40608, -3106, 23284, 14900, -3106, 1916, 20664, 40655, + 39026, -3106, 32053, 2109, 1917, 2109, 860, 1918, 45374, 20664, + -3106, -3106, -3106, -3106, 1974, 8, 33547, 2137, -3106, 1933, + 65539, -3106, 1972, 45374, -3106, -3106, 40024, -3106, -3106, -3106, + -3106, -3106, 2381, 1435, 1923, 1925, -3106, 1290, -3106, -3106, + 65539, 1927, -3106, 1930, 834, -3106, 65539, 1977, -3106, 284, + 2245, 111, -3106, 20664, -3106, 2334, 2418, 4177, 1943, 65539, + 55594, 25380, -3106, 644, 208, -3106, 2234, 55594, 1977, 2374, + -3106, -3106, -3106, 793, -3106, 2273, 2188, -3106, 216, -3106, + 20664, 793, 2190, 229, 65539, -3106, -3106, 2825, -3106, 70519, + 237, 237, -3106, 1475, 1958, 1959, 1962, 1965, 1966, 1968, + 1970, 1976, 1978, 1980, -3106, 1982, 1984, 1985, 1987, 1994, + 1995, 1996, 2000, 1490, 2001, -3106, 2006, 1840, 2009, 2011, + 2012, 2015, 2016, 71485, 2019, 2021, 2022, 2023, 1491, 2024, + 1056, 1097, -3106, -3106, -3106, -3106, 2027, -3106, -3106, -3106, + 1151, 1969, -3106, -3106, -3106, 2041, -3106, 2043, -3106, -3106, + -3106, -3106, -3106, -3106, 1986, 1993, -3106, -3106, -3106, 169, + 1975, 2014, 65539, 1199, 115, 65539, 2026, 1806, 2433, 19616, + 47626, 730, 2215, 1981, -3106, 860, 1624, -3106, 51112, 3017, + 619, 1992, -3106, 187, 1806, -3106, 2385, 1624, 2044, 2484, + -3106, 2020, -3106, 2257, 65539, 2032, -3106, -3106, 48622, 1888, + 3828, 25380, 70519, 929, 945, -3106, 2541, 2201, 2109, -3106, + -3106, -3106, -3106, -3106, 2040, -20, 2045, 10184, 2046, -3106, + -3106, -3106, -3106, -3106, -3106, 45374, 45374, 65539, 2228, -3106, + -3106, 2052, 2051, 37532, 2507, 2058, -3106, -3106, 2371, -3106, + 30557, -3106, 1651, 2061, 1651, 70519, 1651, -3106, -3106, 45374, + 20664, -3106, -3106, 41689, 2386, 4732, 4732, 8504, 956, -3106, + 4732, 20664, 20664, 4732, 4732, 20664, -3106, 9659, 546, -3106, + 961, -3106, 40694, -3106, 71968, -3106, -3106, 1945, 860, 1945, + -3106, -3106, 2062, -3106, -3106, -3106, 2117, -3106, -3106, 966, + 2493, 1972, 20664, -3106, -3106, 2067, 36038, -3106, -3106, -3106, + -3106, 36038, 834, -3106, 2241, 1977, 2072, -3106, -3106, -3106, + -3106, -3106, -3106, 41047, -3106, 51, 20664, -3106, 934, 2635, + -3106, -3106, -3106, -3106, 1977, 1116, -3106, 55594, 2551, 2440, + -3106, -3106, 45374, -3106, -3106, 2004, 2004, -3106, -3106, 2224, + -3106, -3106, 2074, -3106, -3106, 1151, 428, 39525, 55594, 55594, + -3106, -3106, 2078, -3106, -3106, -3106, -3106, -3106, -66, 2473, + 967, 974, -3106, 3310, 3310, 45374, 971, 55594, 2449, 51112, + -3106, 2564, 2087, 55594, 1806, 404, 404, -3106, 2237, -3106, + 2238, -3106, -3106, 2568, 266, -3106, 20140, 47626, 55594, -3106, + -3106, 33049, -3106, 3828, 972, -3106, -3106, 2091, 2094, -3106, + 1945, 20664, 2095, 20664, -3106, 23808, 2573, 2093, -3106, 20664, + 2163, 28524, -3106, 20664, -3106, 55594, 60574, 2100, 60574, -3106, + -3106, -3106, -3106, -3106, 20664, -3106, 4732, 4732, 4732, 20664, + -3106, 20664, -3106, -3106, -3106, 2306, 2228, -3106, 2228, 20664, + 3310, 344, 3405, 65539, 6, -3106, 45374, -3106, -3106, -3106, + 55594, -3106, 47626, -3106, 834, -39, 2104, 20664, 41133, 2344, + -3106, -3106, 2378, -3106, 2437, -3106, 2172, 533, 2189, -3106, + -3106, -3106, -3106, 1199, 860, 1624, 1992, 2044, -3106, -3106, + 2115, 55594, 3310, 974, 672, -3106, -3106, -3106, -3106, -3106, + -3106, -3106, -3106, -3106, -3106, -3106, -3106, -3106, 3310, 2561, + 2345, 2566, 3310, 45374, 977, 1954, 20664, 119, -3106, 982, + 2562, -3106, -3106, 2632, 2228, 2126, 23808, 2127, -3106, 2131, + 65539, 45374, 2278, -3106, -3106, 2139, -3106, -3106, 20664, -3106, + 41736, 2142, 2143, 2601, 1778, 2163, 2163, -3106, 8, -3106, + -3106, 2569, 33049, 2528, 1116, 834, 2158, 988, -3106, -3106, + -3106, -3106, -3106, 4038, -3106, 41172, 2394, 467, 2379, 2104, + 20664, -3106, 2230, -3106, -3106, -3106, 2630, -3106, -3106, 51112, + 2157, 2044, 1992, 1806, 2044, 2389, -3106, 2390, -3106, -3106, + 2161, 41211, 65539, 65539, 1624, 33049, 65539, 2166, 2163, -3106, + 2168, -3106, -3106, -3106, 54598, -3106, 2171, -3106, -3106, -3106, + 20664, 180, -3106, -3106, 2231, 55594, 993, 47, 2378, 39525, + -3106, 47626, 1305, -39, 2485, -3106, -3106, -3106, -3106, 225, + 2402, -3106, 2404, -3106, 45374, -3106, 3310, 51112, -3106, -3106, + -3106, -3106, -3106, -3106, 33049, 2562, -3106, 328, -3106, 1488, + -3106, 328, -3106, -3106, -3106, -3106, -3106, 1426, 24332, 24332, + 24332, 2179, 3310, -3106, 1488, -3106, 2310, 2379, -3106, -3106, + -3106, -3106, -3106, 197, 197, 2578, -3106, 2249, -3106, 2044, + 999, 65539, 1724, -3106, 1724, 25904, 2327, 170, 44298, 2554, + -3106, 2554, 2554, -3106, -3106, -3106, 38528, -3106, -3106, 2679, + -3106, 231, -3106, -3106, -3106, 1624, 328, -3106, -3106, 2670, + -3106, -3106, -3106, -3106, -3106, 198, -3106, -3106, -3106, 1488, + 834, -3106, -3106, -3106, 1488, 1724, 24856, 2341, -3106, 2412, + -3106, -3106, -3106, -3106, -3106, -3106, -3106 +}; + +/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_int16 yydefact[] = +{ + 156, 265, 0, 1396, 1395, 1468, 265, 0, 1330, 0, + 265, 491, 406, 0, 1489, 1488, 0, 208, 265, 0, + 156, 0, 1429, 0, 0, 0, 554, 557, 555, 0, + 0, 0, 265, 594, 0, 1490, 265, 0, 0, 586, + 556, 0, 1446, 0, 0, 0, 0, 0, 2, 4, + 5, 6, 7, 8, 9, 23, 10, 11, 12, 13, + 19, 14, 15, 16, 17, 18, 20, 21, 22, 25, + 24, 26, 27, 1353, 28, 29, 30, 31, 0, 32, + 0, 33, 34, 35, 36, 530, 516, 599, 529, 0, + 0, 155, 698, 537, 37, 39, 38, 40, 41, 42, + 43, 44, 1491, 1487, 45, 264, 263, 257, 0, 0, + 0, 0, 0, 1467, 0, 0, 268, 112, 1515, 1516, + 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1892, + 1526, 1527, 1528, 1529, 1530, 1893, 1531, 1532, 1533, 1838, + 1839, 1894, 1840, 1841, 1534, 1535, 1536, 1537, 1538, 1539, + 1540, 1541, 1542, 1543, 1842, 1843, 1544, 1545, 1546, 1547, + 1548, 1844, 1895, 1845, 1549, 1550, 1551, 1552, 1553, 1896, + 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1897, + 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1572, + 1846, 1573, 1574, 1847, 1575, 1576, 1577, 1578, 1579, 1580, + 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, + 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, + 1601, 1848, 1602, 1603, 1604, 1605, 1606, 1607, 1849, 1608, + 1609, 1610, 1850, 1611, 1612, 1613, 1898, 1899, 1614, 1615, + 1851, 1901, 1616, 1617, 1852, 1853, 1618, 1619, 1620, 1621, + 1622, 1623, 1624, 1625, 1626, 1902, 1627, 1628, 1629, 1630, + 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1903, 1854, + 1639, 1640, 1641, 1642, 1643, 1855, 1856, 1857, 1644, 1904, + 1905, 1645, 1906, 1646, 1647, 1648, 1649, 1650, 1651, 1652, + 1907, 1653, 1908, 1654, 1655, 1656, 1657, 1658, 1659, 1660, + 1661, 1858, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, + 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, + 1680, 1681, 1859, 1910, 1860, 1682, 1683, 1684, 1861, 1685, + 1686, 1911, 1687, 1862, 1688, 1863, 1689, 1690, 1691, 1692, + 1693, 1694, 1695, 1696, 1697, 1698, 1864, 1912, 1699, 1913, + 1865, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, + 1709, 1710, 1711, 1712, 1866, 1914, 1713, 1714, 1867, 1715, + 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, + 1726, 1727, 1728, 1868, 1729, 1730, 1731, 1732, 1733, 1734, + 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, + 1745, 1746, 1747, 1915, 1748, 1749, 1750, 1869, 1751, 1752, + 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, + 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1870, 1770, 1771, + 1916, 1772, 1773, 1871, 1774, 1775, 1776, 1777, 1778, 1779, + 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1872, 1787, 1873, + 1788, 1789, 1790, 1918, 1791, 1792, 1793, 1794, 1795, 1796, + 1874, 1875, 1797, 1798, 1876, 1799, 1877, 1800, 1801, 1878, + 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, + 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1879, 1880, 1819, + 1919, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, + 1829, 1830, 1831, 1832, 1833, 1881, 1882, 1883, 1884, 1885, + 1886, 1887, 1888, 1889, 1890, 1891, 1834, 1835, 1836, 1837, + 0, 113, 114, 1277, 1498, 0, 1255, 112, 1851, 1858, + 1872, 1328, 1329, 113, 0, 260, 490, 0, 0, 0, + 0, 0, 0, 210, 0, 400, 399, 0, 1319, 405, + 0, 0, 0, 116, 108, 1715, 115, 1254, 106, 122, + 2062, 2063, 2064, 2065, 1949, 2066, 2067, 2068, 2069, 1950, + 2070, 1951, 1952, 1953, 1954, 1955, 1956, 2071, 2072, 2073, + 1958, 1957, 2074, 1959, 2075, 1960, 2076, 1961, 1962, 2077, + 2078, 1963, 1569, 1964, 1965, 2079, 2080, 2081, 2082, 2083, + 2084, 2085, 2086, 2087, 1966, 1967, 2088, 2089, 1968, 2090, + 2091, 1969, 2092, 1970, 1971, 1972, 2093, 2094, 1973, 1974, + 2095, 1975, 2096, 2097, 1976, 1977, 1980, 1978, 2098, 1979, + 2099, 1981, 1982, 1983, 2100, 2101, 1984, 1985, 2102, 1986, + 1987, 1988, 1989, 1990, 2103, 1991, 2104, 1992, 1993, 2105, + 2106, 2107, 2108, 2109, 1995, 1994, 1996, 1997, 2110, 2111, + 2112, 2113, 1998, 1999, 2000, 2114, 2115, 2001, 2116, 2117, + 2002, 2003, 2118, 2004, 2005, 2119, 2006, 2007, 2120, 2008, + 2009, 2121, 2122, 2123, 2010, 2124, 2011, 2012, 2125, 2126, + 2013, 2014, 2127, 2015, 2128, 2129, 2130, 2131, 2016, 2017, + 2132, 2018, 2133, 2134, 2135, 2136, 2019, 2020, 2021, 2022, + 2023, 2024, 2025, 2026, 2027, 2028, 2029, 1464, 124, 123, + 125, 0, 424, 425, 0, 435, 0, 417, 422, 418, + 0, 444, 437, 445, 426, 416, 438, 427, 415, 209, + 0, 446, 432, 420, 0, 0, 0, 0, 261, 222, + 406, 0, 156, 0, 1357, 1358, 1359, 1360, 1361, 1362, + 1367, 1363, 1364, 1365, 1366, 1368, 1369, 1370, 1371, 1372, + 1348, 1353, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, + 1381, 1382, 1383, 1384, 1385, 1386, 1387, 0, 1330, 0, + 1844, 1895, 1849, 0, 1862, 0, 1865, 1866, 1751, 1873, + 1876, 1877, 1878, 1879, 0, 768, 115, 110, 752, 0, + 532, 702, 712, 752, 757, 1040, 780, 1041, 0, 117, + 1431, 1430, 1424, 195, 1292, 1476, 1616, 1656, 1768, 1874, + 1797, 1494, 1477, 1471, 1475, 262, 593, 591, 0, 1226, + 1616, 1656, 1755, 1768, 1874, 1404, 1408, 0, 268, 1496, + 1481, 0, 1482, 115, 538, 585, 0, 269, 1445, 0, + 1450, 0, 1731, 565, 568, 1286, 566, 530, 0, 0, + 1, 156, 1352, 1460, 0, 162, 0, 0, 589, 589, + 0, 589, 0, 522, 0, 0, 530, 525, 529, 699, + 1493, 1874, 1797, 1480, 1483, 1625, 0, 0, 1625, 0, + 1625, 0, 1625, 0, 0, 1470, 0, 258, 1210, 0, + 1256, 118, 0, 0, 1341, 1337, 1342, 1338, 1343, 1336, + 1335, 1344, 1340, 0, 0, 0, 371, 404, 403, 402, + 401, 406, 1625, 1303, 0, 453, 454, 0, 0, 0, + 0, 0, 206, 1314, 109, 107, 1625, 1465, 433, 434, + 0, 423, 419, 421, 0, 0, 1625, 1281, 443, 439, + 1625, 443, 1248, 1625, 0, 0, 214, 0, 399, 1350, + 1388, 2016, 1389, 1390, 1402, 0, 1403, 1393, 1356, 156, + 0, 489, 1327, 0, 0, 0, 1161, 752, 757, 0, + 0, 770, 0, 1181, 0, 1187, 0, 0, 0, 752, + 537, 0, 712, 769, 111, 0, 750, 751, 640, 640, + 594, 0, 575, 762, 0, 0, 765, 763, 0, 765, + 0, 0, 0, 765, 761, 720, 0, 640, 0, 750, + 753, 640, 0, 772, 1347, 0, 0, 0, 0, 1474, + 1472, 1473, 1478, 0, 0, 0, 1258, 1260, 1261, 1129, + 1271, 1019, 0, 1839, 1840, 1841, 1202, 1842, 1843, 1845, + 1846, 1847, 977, 1589, 1848, 1269, 1850, 1852, 1853, 1855, + 1856, 1857, 1858, 1859, 1860, 0, 1270, 1863, 1694, 1868, + 1869, 1871, 1874, 1875, 1268, 1880, 0, 0, 0, 1237, + 1152, 0, 1018, 0, 0, 0, 1203, 1211, 1011, 0, + 0, 816, 817, 838, 839, 818, 844, 845, 847, 819, + 0, 1233, 911, 1007, 1221, 1016, 1024, 1020, 1059, 1022, + 1039, 1025, 1096, 1017, 0, 1023, 1009, 1229, 575, 1227, + 0, 1010, 1257, 575, 1225, 1407, 1405, 1411, 1406, 0, + 0, 0, 0, 259, 0, 111, 1452, 1453, 1444, 1442, + 1443, 1441, 1440, 1447, 0, 1449, 1353, 1147, 1149, 0, + 567, 0, 0, 0, 519, 518, 520, 3, 1286, 0, + 0, 0, 1606, 0, 1432, 587, 588, 0, 0, 0, + 0, 0, 0, 0, 0, 683, 614, 615, 617, 680, + 684, 692, 0, 0, 0, 0, 0, 526, 0, 1492, + 1486, 1484, 0, 0, 0, 140, 140, 0, 0, 0, + 0, 0, 100, 49, 93, 0, 0, 0, 0, 236, + 249, 0, 0, 0, 0, 0, 246, 0, 0, 229, + 223, 225, 51, 0, 140, 0, 47, 0, 0, 0, + 53, 1468, 0, 489, 266, 267, 1209, 0, 120, 121, + 119, 112, 0, 2030, 1892, 1893, 1894, 1895, 1845, 1896, + 1897, 0, 1898, 1899, 1851, 1901, 1902, 1903, 1904, 1905, + 1906, 1907, 1908, 1858, 1910, 1911, 1912, 1913, 1914, 1915, + 2056, 1916, 1872, 1918, 1878, 0, 1919, 1032, 113, 1274, + 1155, 599, 1153, 1287, 0, 0, 1339, 0, 0, 0, + 0, 487, 0, 0, 0, 0, 1299, 0, 0, 1625, + 202, 1625, 371, 0, 1625, 371, 1625, 0, 1625, 207, + 211, 1313, 1316, 0, 436, 431, 429, 428, 430, 1625, + 255, 0, 0, 1282, 441, 442, 0, 410, 0, 0, + 412, 0, 0, 219, 0, 217, 0, 406, 156, 0, + 230, 1398, 1399, 1397, 0, 0, 1355, 233, 1392, 1401, + 1391, 1400, 1354, 250, 1349, 0, 0, 1345, 476, 0, + 0, 0, 1162, 887, 886, 868, 869, 884, 885, 870, + 871, 878, 879, 889, 888, 876, 877, 872, 873, 866, + 867, 882, 883, 874, 875, 880, 881, 864, 865, 1176, + 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, + 1173, 1174, 1175, 0, 0, 711, 709, 0, 0, 0, + 0, 0, 0, 1203, 0, 982, 1017, 0, 0, 0, + 1147, 1186, 0, 0, 0, 0, 0, 0, 1147, 1192, + 0, 0, 736, 748, 0, 633, 639, 710, 708, 0, + 1226, 703, 0, 782, 762, 0, 761, 0, 0, 764, + 758, 0, 759, 0, 0, 0, 0, 760, 0, 0, + 0, 0, 706, 0, 748, 0, 707, 779, 1414, 1422, + 196, 0, 1278, 1920, 1921, 1922, 826, 1923, 855, 833, + 855, 855, 1924, 1925, 1926, 1927, 822, 822, 835, 1928, + 1929, 1930, 1931, 1932, 823, 824, 860, 1933, 1934, 1935, + 1936, 1937, 0, 0, 1938, 855, 1939, 822, 1940, 1941, + 1942, 827, 1943, 790, 1944, 0, 1945, 825, 791, 1946, + 863, 863, 1947, 0, 850, 1948, 1279, 1280, 0, 1158, + 800, 808, 809, 810, 811, 836, 837, 812, 842, 843, + 813, 910, 0, 822, 156, 1479, 1495, 0, 1152, 1026, + 854, 841, 1201, 0, 849, 848, 0, 1152, 831, 830, + 829, 1013, 0, 828, 1109, 855, 855, 853, 936, 832, + 0, 0, 0, 0, 0, 859, 0, 857, 937, 915, + 916, 0, 0, 1236, 1245, 1147, 1151, 0, 1011, 1147, + 0, 0, 1099, 1101, 0, 1028, 1029, 0, 1204, 1259, + 1012, 0, 1264, 0, 0, 910, 910, 1232, 1129, 0, + 1119, 1122, 0, 0, 1126, 1127, 1128, 0, 0, 0, + 1224, 0, 1137, 1139, 0, 0, 952, 1135, 0, 955, + 0, 0, 0, 0, 1123, 1124, 1125, 1115, 1116, 1117, + 1118, 1120, 1121, 1133, 1114, 933, 0, 1008, 0, 1062, + 0, 932, 1230, 701, 0, 1262, 701, 1416, 1420, 1421, + 1419, 1415, 0, 1410, 1409, 1412, 1413, 1497, 0, 1454, + 1438, 0, 1435, 1150, 696, 569, 1250, 0, 573, 1461, + 1459, 161, 160, 0, 213, 0, 0, 0, 1425, 542, + 541, 608, 600, 602, 608, 0, 540, 0, 656, 657, + 0, 0, 0, 0, 689, 687, 1258, 1271, 644, 618, + 643, 0, 0, 622, 0, 648, 911, 682, 524, 612, + 613, 616, 523, 0, 685, 0, 695, 0, 561, 563, + 546, 560, 558, 543, 551, 683, 617, 0, 1485, 0, + 0, 0, 0, 0, 1625, 0, 0, 793, 84, 65, + 323, 139, 0, 0, 0, 0, 0, 0, 0, 92, + 89, 90, 91, 0, 0, 0, 0, 1278, 234, 235, + 248, 0, 239, 240, 237, 241, 242, 0, 0, 227, + 228, 0, 0, 0, 0, 226, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1469, 1462, 1205, 1210, 599, + 599, 599, 0, 597, 598, 0, 0, 0, 0, 0, + 475, 369, 379, 0, 0, 0, 1303, 0, 0, 0, + 0, 0, 206, 0, 406, 1304, 1302, 1306, 1305, 1307, + 1595, 190, 0, 0, 201, 198, 0, 368, 342, 0, + 0, 1318, 0, 0, 0, 0, 0, 0, 1625, 358, + 1315, 0, 1466, 0, 0, 253, 443, 1283, 0, 440, + 443, 1249, 0, 443, 221, 0, 0, 1351, 1394, 231, + 251, 232, 252, 489, 484, 514, 0, 492, 497, 473, + 0, 473, 0, 494, 498, 473, 493, 0, 473, 488, + 0, 1055, 0, 1045, 0, 0, 771, 0, 0, 1046, + 984, 985, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1002, 1001, 1047, 775, 0, 778, 0, 0, 1184, 1185, + 0, 1048, 0, 0, 1191, 0, 0, 0, 1053, 0, + 713, 0, 0, 0, 628, 632, 635, 0, 638, 575, + 531, 1616, 1656, 0, 586, 586, 586, 584, 574, 0, + 660, 0, 0, 737, 0, 0, 739, 741, 0, 0, + 744, 719, 718, 0, 0, 0, 0, 783, 0, 1254, + 0, 0, 197, 0, 0, 0, 808, 0, 0, 0, + 798, 794, 0, 890, 891, 892, 893, 894, 895, 896, + 897, 898, 899, 900, 901, 902, 814, 1291, 0, 820, + 1296, 1297, 1294, 0, 1290, 1293, 1295, 1298, 0, 0, + 0, 0, 1200, 1196, 0, 0, 0, 0, 1104, 1106, + 1108, 0, 852, 851, 1113, 1119, 1122, 1126, 1127, 1128, + 1123, 1124, 1125, 1115, 1116, 1117, 1118, 1120, 1121, 0, + 1141, 0, 1095, 0, 0, 0, 0, 0, 0, 0, + 1235, 0, 980, 0, 1030, 1015, 0, 0, 1102, 1031, + 1237, 1212, 0, 0, 0, 1267, 1266, 912, 921, 924, + 956, 957, 928, 929, 930, 934, 1289, 1288, 1231, 0, + 1223, 0, 0, 913, 938, 943, 0, 1193, 973, 0, + 961, 0, 951, 0, 959, 963, 939, 954, 0, 935, + 0, 1224, 1138, 1140, 0, 1136, 0, 925, 926, 927, + 917, 918, 919, 920, 922, 923, 931, 1112, 1110, 1111, + 0, 1210, 0, 1222, 0, 0, 1064, 0, 0, 958, + 1228, 0, 782, 599, 782, 0, 910, 1455, 1286, 1448, + 1437, 1286, 1148, 1251, 1285, 571, 0, 0, 0, 1457, + 147, 151, 0, 1211, 181, 183, 701, 0, 1432, 1432, + 1434, 1433, 606, 607, 611, 0, 0, 611, 590, 539, + 1869, 1751, 0, 0, 0, 0, 649, 690, 0, 681, + 646, 647, 0, 645, 1258, 650, 1257, 651, 654, 655, + 623, 1246, 691, 693, 0, 686, 0, 1252, 545, 564, + 0, 0, 0, 0, 0, 528, 527, 697, 0, 50, + 0, 1625, 67, 0, 0, 0, 0, 0, 0, 273, + 0, 373, 273, 105, 1625, 443, 1625, 443, 1519, 1590, + 1769, 0, 63, 347, 96, 0, 133, 376, 0, 332, + 86, 101, 126, 0, 0, 224, 52, 238, 243, 129, + 247, 244, 1323, 245, 140, 0, 48, 0, 127, 0, + 1321, 0, 0, 54, 131, 1325, 1470, 0, 1209, 0, + 597, 597, 597, 0, 1154, 0, 0, 0, 1156, 1157, + 951, 1332, 1333, 1334, 1331, 461, 474, 0, 370, 0, + 486, 464, 465, 475, 1301, 0, 202, 371, 0, 371, + 0, 211, 1303, 0, 0, 192, 188, 0, 0, 0, + 0, 369, 361, 359, 392, 0, 366, 360, 0, 0, + 318, 0, 1513, 0, 0, 0, 0, 455, 0, 0, + 206, 212, 0, 0, 0, 255, 256, 409, 1284, 411, + 0, 413, 220, 218, 1346, 481, 1152, 0, 479, 485, + 478, 480, 483, 477, 0, 472, 0, 507, 0, 0, + 0, 0, 0, 0, 0, 0, 1042, 1160, 0, 1179, + 1178, 983, 990, 993, 997, 998, 999, 1180, 0, 0, + 0, 994, 995, 996, 986, 987, 988, 989, 991, 992, + 1000, 780, 0, 0, 774, 1189, 1188, 1182, 1183, 0, + 1050, 1051, 1052, 1190, 0, 0, 749, 626, 624, 627, + 629, 625, 0, 0, 782, 586, 586, 586, 586, 583, + 0, 0, 0, 781, 0, 677, 743, 0, 767, 0, + 740, 723, 0, 731, 0, 738, 787, 754, 0, 0, + 756, 1423, 804, 0, 799, 795, 0, 0, 0, 805, + 0, 0, 0, 0, 0, 0, 0, 1159, 0, 592, + 1027, 0, 0, 0, 1197, 0, 979, 821, 834, 0, + 1107, 1021, 0, 1130, 1094, 862, 861, 863, 863, 0, + 0, 0, 0, 1244, 0, 1148, 1098, 1100, 1245, 1014, + 846, 910, 0, 0, 0, 0, 0, 0, 0, 962, + 953, 0, 960, 964, 0, 0, 0, 947, 0, 0, + 945, 974, 941, 0, 0, 975, 1209, 0, 1213, 0, + 0, 1063, 1072, 704, 700, 660, 597, 660, 0, 1417, + 1439, 1436, 572, 156, 1458, 0, 170, 0, 0, 0, + 0, 173, 187, 184, 1457, 0, 1426, 1427, 0, 601, + 603, 0, 1131, 611, 605, 653, 652, 0, 621, 688, + 619, 0, 694, 0, 562, 0, 548, 0, 722, 0, + 0, 0, 0, 0, 322, 0, 0, 0, 273, 0, + 381, 0, 388, 0, 0, 373, 354, 85, 0, 0, + 0, 59, 104, 77, 69, 55, 83, 0, 0, 88, + 0, 81, 98, 99, 97, 102, 0, 283, 308, 0, + 0, 319, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 489, 1210, 1206, 1210, 0, 0, 0, + 599, 595, 596, 1033, 0, 460, 513, 510, 511, 509, + 229, 380, 0, 0, 200, 368, 0, 1318, 0, 0, + 1300, 406, 0, 193, 0, 191, 0, 202, 371, 0, + 346, 342, 367, 340, 339, 341, 0, 1514, 222, 0, + 1508, 371, 1317, 0, 0, 456, 0, 450, 211, 0, + 0, 1312, 254, 443, 0, 468, 508, 515, 495, 500, + 0, 506, 502, 501, 496, 504, 503, 499, 1043, 1054, + 1177, 0, 0, 0, 0, 773, 776, 0, 1049, 1044, + 747, 0, 0, 660, 0, 0, 0, 0, 577, 576, + 582, 0, 0, 1066, 742, 0, 0, 0, 729, 717, + 724, 725, 0, 0, 0, 785, 784, 755, 808, 0, + 788, 808, 0, 808, 0, 806, 0, 815, 903, 904, + 905, 906, 907, 908, 909, 840, 0, 1199, 1195, 1103, + 1105, 1142, 858, 856, 978, 1234, 1147, 1239, 1241, 0, + 0, 0, 1097, 981, 1265, 914, 0, 0, 944, 1194, + 965, 0, 0, 0, 940, 1130, 0, 0, 0, 0, + 0, 949, 0, 1217, 1210, 0, 1216, 0, 0, 0, + 0, 1038, 705, 677, 0, 677, 0, 0, 1456, 0, + 1451, 148, 149, 150, 0, 0, 0, 165, 142, 0, + 0, 182, 170, 158, 609, 610, 0, 604, 620, 1247, + 1253, 547, 0, 1011, 0, 0, 544, 0, 134, 273, + 0, 0, 66, 0, 390, 334, 382, 365, 349, 0, + 0, 0, 274, 0, 407, 0, 0, 355, 0, 0, + 0, 0, 335, 0, 0, 294, 0, 0, 365, 0, + 372, 290, 291, 0, 58, 78, 0, 74, 0, 103, + 0, 0, 0, 0, 0, 61, 73, 0, 56, 0, + 443, 443, 64, 1278, 1920, 1921, 1922, 1923, 1924, 1925, + 1926, 1927, 1928, 1929, 2040, 1930, 1931, 1932, 1933, 1934, + 1935, 1936, 1937, 2049, 1938, 280, 1939, 1694, 1940, 1941, + 1942, 1943, 1944, 0, 1945, 791, 1946, 1947, 2128, 1948, + 1115, 1116, 278, 279, 375, 275, 1279, 276, 383, 277, + 0, 378, 333, 130, 1324, 0, 128, 0, 1322, 137, + 135, 132, 1326, 1463, 0, 0, 1036, 1037, 1034, 597, + 0, 0, 0, 489, 467, 0, 0, 1513, 0, 0, + 0, 0, 1625, 0, 189, 0, 1318, 199, 368, 0, + 398, 318, 393, 0, 1513, 1511, 0, 1318, 1507, 0, + 447, 0, 203, 0, 0, 0, 414, 482, 0, 505, + 1003, 0, 0, 0, 0, 636, 0, 642, 677, 581, + 580, 579, 578, 659, 1564, 1852, 1750, 0, 663, 658, + 661, 666, 668, 667, 669, 665, 676, 0, 679, 766, + 1143, 1145, 0, 0, 0, 0, 730, 732, 0, 734, + 0, 786, 802, 0, 803, 0, 801, 796, 807, 1198, + 1242, 1243, 1238, 0, 911, 971, 969, 966, 0, 967, + 948, 0, 0, 946, 942, 0, 976, 0, 0, 1214, + 0, 1058, 0, 1061, 1075, 1071, 1070, 1066, 1033, 1066, + 1418, 570, 169, 146, 172, 171, 0, 1211, 179, 0, + 0, 170, 0, 174, 457, 0, 0, 559, 721, 552, + 553, 0, 386, 68, 0, 365, 0, 273, 351, 350, + 353, 348, 352, 0, 408, 0, 0, 292, 0, 299, + 337, 338, 336, 293, 365, 371, 295, 0, 0, 0, + 70, 60, 57, 62, 71, 0, 0, 72, 75, 787, + 87, 80, 1278, 2049, 2058, 0, 0, 0, 0, 0, + 1208, 1207, 0, 463, 462, 512, 459, 470, 229, 0, + 0, 342, 1510, 0, 0, 452, 0, 0, 0, 368, + 194, 0, 0, 0, 1513, 0, 0, 270, 0, 315, + 0, 215, 1512, 0, 0, 1499, 0, 0, 0, 1310, + 1311, 0, 469, 1004, 0, 1005, 777, 0, 0, 634, + 1066, 0, 0, 0, 670, 664, 0, 1065, 1067, 0, + 631, 1146, 726, 0, 728, 0, 752, 0, 752, 735, + 797, 789, 1240, 1056, 0, 968, 972, 970, 950, 1210, + 1218, 1210, 1215, 1060, 1074, 1077, 679, 1263, 679, 0, + 0, 157, 0, 0, 154, 141, 159, 1132, 549, 550, + 0, 273, 0, 364, 387, 304, 282, 0, 0, 0, + 289, 296, 397, 298, 0, 79, 95, 0, 0, 377, + 138, 136, 1035, 489, 0, 1318, 318, 1507, 449, 205, + 0, 0, 0, 342, 222, 1509, 331, 324, 325, 326, + 327, 328, 329, 330, 345, 344, 316, 317, 0, 0, + 0, 0, 0, 451, 0, 1312, 0, 176, 185, 0, + 176, 1006, 637, 0, 679, 0, 0, 0, 662, 0, + 0, 678, 0, 535, 1144, 0, 716, 714, 0, 715, + 0, 0, 0, 0, 599, 631, 631, 143, 0, 144, + 180, 0, 0, 0, 371, 389, 363, 0, 356, 302, + 301, 303, 307, 0, 305, 0, 321, 0, 314, 282, + 0, 82, 0, 384, 458, 466, 0, 272, 1501, 368, + 0, 1507, 318, 1513, 1507, 0, 1504, 0, 448, 204, + 0, 0, 0, 178, 1318, 0, 178, 0, 631, 672, + 0, 671, 1069, 1068, 633, 727, 0, 1057, 1220, 1219, + 0, 1081, 534, 533, 0, 0, 0, 0, 397, 0, + 343, 0, 0, 304, 0, 297, 394, 395, 396, 0, + 310, 300, 311, 76, 94, 385, 0, 368, 1502, 271, + 216, 1500, 1505, 1506, 0, 176, 175, 608, 177, 782, + 186, 608, 641, 536, 673, 630, 733, 1076, 0, 0, + 0, 0, 0, 153, 782, 164, 0, 314, 362, 357, + 281, 306, 320, 0, 0, 0, 312, 0, 313, 1507, + 0, 178, 611, 1308, 611, 1838, 1565, 1804, 0, 1093, + 1082, 1093, 1093, 1073, 145, 152, 0, 273, 286, 0, + 285, 0, 374, 309, 1503, 1318, 608, 166, 167, 0, + 1086, 1085, 1084, 1088, 1087, 0, 1080, 1078, 1079, 782, + 391, 284, 288, 287, 782, 611, 0, 0, 1090, 0, + 1091, 163, 1309, 168, 1083, 1089, 1092 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -3059, -3059, -3059, 1865, 73, -3059, -3059, 139, -3059, 973, - -3059, 146, -787, 509, -3059, 77, 1252, 2549, 3668, 2713, - -515, -876, -1226, 1, 81, -1140, 3, -3059, -3059, -3059, - -3059, -3059, -502, 210, -3059, -3059, -634, -2561, -584, -3059, - -2881, -3004, -3059, -3059, -731, -2965, -2068, 86, -3059, -3059, - 88, 11, -2084, -3059, -1601, 36, -2072, 89, 898, -3059, - -2570, 90, -889, -1193, -933, -1200, -3059, -122, -3059, 425, - 96, 1228, -3059, 12, -2165, -2872, -594, -3059, -696, -3059, - -347, -3059, -641, -3059, -1047, -645, -679, -2818, -1139, -3059, - 1589, -396, -3059, 567, -3059, -2540, -3059, -3059, 558, -3059, - -1154, -3059, -2186, 140, -618, -2582, -2531, -2156, -912, 215, - -617, 193, -2122, -1331, -3059, 584, -3059, -600, -3059, -893, - -2019, 98, -3059, -3059, 1495, -909, -3059, 99, 1517, -2083, - 10, 22, -3059, -3059, -3059, -3059, -3059, -828, 513, -1206, - -3059, 454, -3059, -3059, -3059, -3059, -185, 171, -2234, 2, - 323, -43, -22, -3059, -16, -3059, -3059, -3059, 614, -3059, - -3059, 21, 32, 1665, -3059, -1020, -3059, -1587, 383, -3059, - 1814, 1841, -2144, -863, -66, -3059, 652, -1659, -2130, -629, - 1090, 1656, 1648, 407, -2525, -3059, -568, -3059, -88, -3059, - -3059, 647, 1132, -1544, -1559, -3059, -2203, -3059, -487, -375, - -3059, -3059, -3059, -3059, -3059, -2483, -2836, -620, 1103, -3059, - 1660, -3059, -3059, -3059, -3059, 61, -1497, 2814, 682, 41, - -3059, -3059, -3059, -3059, 108, -3059, 863, -195, -3059, 2054, - -675, -796, 1880, 34, 93, -1745, 31, 2068, 452, -3059, - -3059, 463, -2087, -1408, 408, -281, 872, -3059, -3059, -1246, - -3059, -1833, -1172, -3059, -3059, -806, 510, -3059, -3059, -3059, - 1645, 2152, -3059, -3059, 2178, 2764, -3059, -862, 2970, -781, - -1031, 1883, -924, 1887, -930, -946, -937, 1888, 1890, 1893, - 1896, 1897, 1898, -1534, 4692, 2325, 2519, -2179, -3059, -2178, - 993, 1003, 16, -3059, -1387, 128, -3059, -3059, -3059, -3059, - -2600, -3059, -442, -3059, -439, -3059, -3059, -3059, -1649, -3058, - -1674, -3059, 2641, 818, -3059, -3059, 410, -3059, -3059, -3059, - -3059, -1509, -3059, 5718, 712, -3059, -2024, -3059, -3059, -965, - -831, -638, -983, -1197, -1921, -3059, -3059, -3059, -3059, -3059, - -3059, -1488, -1772, -326, 777, -3059, -3059, 867, -3059, -3059, - -3059, -1703, -2098, -3059, -3059, -3059, 781, 1448, 84, -830, - -1621, -3059, 819, -2352, -3059, -3059, 399, -3059, -627, -1138, - -2428, 2164, 104, -3059, -925, -2536, -3059, -3059, -721, -2648, - -1131, -888, -3059, 100, -3059, 359, 105, -1650, -3059, 14, - -3059, -411, -3059, -3059, -2566, -3059, 106, 114, 2116, -3059, - 1094, -3059, -3059, -3059, -3059, -588, -3059, -635, -621, -3059, - -3059, 30, -898, 1564, -3059, 119, 372, -3059, 919, -3059, - 681, 120, 69, 1543, 121, 1231, -3059, -3059, -3059, 26, - -626, 363, -3059, 1240, -3059, -3059, 1694, 651, 124, -3059, - 43, 47, -3059, -3059, -3059, 72, 2816, 125, 15, -2904, - 129, -2759, -1672, -7, -3059, -3059, -3059, -713, -3059, -2530 + -3106, -3106, -3106, 1842, 84, 93, -893, -1179, -941, -1202, + -3106, -191, 94, -3106, -3106, 103, -3106, 946, -3106, 96, + -762, 478, -3106, 1042, -3106, -3106, 1484, 440, 95, 97, + 1939, -3106, 910, -3106, 1613, 2309, 3577, 1303, -515, -874, + -1232, 4, 3, -3106, -3106, -3106, -3106, -3106, -1126, 416, + -1212, -3106, 356, -3106, -3106, -3106, -3106, -287, 70, -2277, + 1, -2175, -2877, -646, -3106, -748, -3106, -401, -3106, -695, + -3106, -727, -702, -734, -2800, -1143, -3106, 1542, -452, -3106, + 513, -3106, -2561, -3106, -3106, 501, -3106, -1158, -3106, -2225, + 72, -669, -2322, -2551, -2169, -900, 160, -677, 141, -2119, + -1060, -3106, 531, -3106, -662, -3106, -886, -2044, 98, -2648, + -1670, -7, -3106, -3106, -3106, -721, -3106, -2526, 101, 1464, + -2080, 102, -1673, -3106, -3106, -1683, 53, -2097, 7, -2100, + 104, -3106, -3106, 107, 10, -587, 210, -3106, 121, -3106, + -3106, 1446, -910, -3106, -3106, 413, 122, 897, -3106, -2576, + -3106, -556, -3106, -647, -630, -3106, -3106, 28, -905, 1421, + -3106, -3106, -3106, 11, -3106, -550, -3106, -3106, -2586, -3106, + 19, -3106, -3106, -3106, -3106, -1489, -487, 215, -3106, -3106, + -626, -2507, -578, -3106, -2953, -3017, -3106, -3106, -725, -2977, + -2083, 124, -3106, 1905, -424, 127, 128, -3106, 232, 129, + -1148, 22, 132, -5, -36, -3106, -22, -3106, -3106, -3106, + 567, -3106, -3106, 15, 42, 1627, -3106, -1048, -3106, -1653, + 689, -3106, 1781, 1783, -2174, -883, -73, -3106, 611, -1665, + -2138, -638, 1051, 1617, 1628, 372, -2319, -3106, -608, -3106, + -611, -3106, -3106, 607, 1100, -1561, -1490, -3106, -2180, -3106, + -523, -408, -3106, -3106, -3106, -3106, -3106, -2519, -2853, -634, + 1075, -3106, 1629, -3106, -3106, -3106, -3106, 2, -1508, 2800, + 658, -77, -3106, -3106, -3106, -3106, 78, -3106, 847, -228, + -3106, 2029, -701, -784, 1846, -184, 117, -1739, -15, 2053, + 424, -3106, -3106, 426, -2090, -1421, 380, -320, 842, -3106, + -3106, -1231, -3106, -1842, -1170, -3106, -3106, -758, 991, -3106, + -3106, -3106, 1369, 1401, -3106, -3106, 1934, 1960, -3106, -884, + 2609, -122, -1026, 1855, -933, 1863, -946, -926, -930, 1866, + 1868, 1869, 1875, 1881, 1882, 1883, -1537, 4695, 2262, 2784, + -2202, -3106, -2186, 960, 975, 20, -3106, -1396, 76, -3106, + -3106, -3106, -3106, -2278, -3106, -489, -3106, -481, -3106, -3106, + -3106, -1713, -3105, -1733, -3106, 2933, 784, -3106, -3106, 373, + -3106, -3106, -3106, -3106, -1538, -3106, 5710, 687, -3106, -2012, + -3106, -3106, -965, -837, -1131, -1002, -1222, -1907, -3106, -3106, + -3106, -3106, -3106, -3106, -1145, -1684, -263, 752, -3106, -3106, + 850, -3106, -3106, -3106, -1747, -2101, -3106, -3106, -3106, 756, + 1436, 55, -836, -1610, -3106, 800, -2368, -3106, -3106, 379, + -3106, -631, -1118, -2443, 1108, 67, -3106, -776, -2552, -3106, + -3106, -737, -2659, -1100, -894, -3106, 131, 1340, 2056, 21, + 136, -3106, 138, 1209, -3106, -3106, -3106, 148, -3106, 735, + 150, 364, -3106, 901, -3106, 633, 18, -3106, -3106, -3106, + 77, 2785, 17, -2901 }; -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -2046 -static const yytype_int16 yytable[] = +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = { - 520, 904, 70, 54, 865, 1124, 1224, 877, 1292, 714, - 68, 58, 65, 1022, 82, 102, 520, 713, 1188, 1680, - 953, 77, 69, 517, 1784, 1420, 93, 1154, 1241, 1783, - 1795, 1925, 1295, 2172, 2139, 1394, 972, 1348, 1767, 811, - 847, 77, 2557, 1748, 1395, 1350, 1331, 98, 1581, 1475, - 772, 1393, 1830, 740, 2530, 881, 2532, 1391, 1982, 1754, - 1736, 882, 2590, 1758, 2547, 2050, 2450, 778, 520, 520, - 851, 1337, 1354, 51, 2074, 2075, 2940, 52, 863, 1800, - 2660, 53, 2942, 2511, 805, 2971, 56, 1788, 57, 60, - 61, 811, 811, 2546, 2274, 819, 63, 1856, 66, 67, - 80, 2583, 889, 2988, 1656, 81, 83, 844, 1223, 1659, - 1229, 518, 1233, 963, 84, 955, 878, 879, 2969, 90, - 91, 92, 1593, 1241, 97, 101, 2985, 518, 966, 103, - 1004, 2630, 2631, 2632, 2769, 1025, 805, 805, 2644, -1893, - 2833, 897, -1324, -858, 2838, 1046, 1046, 2304, 1362, -1893, - -512, 813, -1265, 2195, -516, 2452, 2402, -2033, -2033, 3384, - -1262, -1262, 2143, -850, 1612, 2299, 2192, 3180, -1884, 1614, - -1265, -1246, 2089, 1325, -1901, -1884, -2024, -2024, -858, 518, - 518, 1609, -2042, -2042, 973, -855, 1404, -1266, -1901, -855, - 815, 1558, 1559, 2661, 1046, -1263, -1263, -2019, -2019, 1622, - -1266, -817, 1664, 813, 813, -830, -845, 815, 1571, 815, - 1350, 3165, -2044, -2044, 1210, 2300, 2431, 2432, 2648, 2469, - 1660, 1341, 815, 2652, 2089, 1902, 1046, 2438, 2646, 3184, - 1904, 2442, 3113, 1624, 1211, 1325, 532, 855, 1750, 2639, - 1143, 815, 3258, 2694, 2696, 1166, 2699, 1177, 1341, 1786, - -512, 1563, 1543, 1046, -516, 1589, 1180, 972, 2733, 2734, - 1798, 1739, 1136, 3096, 1241, -227, 1316, 1573, 1325, 1799, - -227, 3, 4, 1759, 2296, -466, 2668, 3271, 1768, 1612, - 1212, 1771, 1772, 1613, 1614, -649, 1350, 999, 3128, 1350, - 1350, 2205, 3148, 1902, 3418, 1942, 1699, 1903, 1904, 815, - 869, 944, 1612, 874, 1750, 1317, 1613, 1614, 1025, 3343, - 2414, 815, 1902, 2962, 1622, 2618, 1903, 1904, 3450, 874, - 1004, 2412, 3079, 71, 3081, -1104, 3457, 2805, 1942, 2807, - 3181, 3465, 2716, -1104, 1661, 1140, 872, 1622, 1355, 2989, - 3302, 1773, 1700, 71, 3514, 3182, 804, 1988, 1624, 783, - 3303, 1683, 533, 1005, 1665, 1742, 1731, 1732, 2586, 1735, - 2198, 71, 3124, 3204, 2415, 2110, 2076, 2425, 2426, 2427, - 864, 1624, 2705, 1173, 2126, 1213, 3370, -1125, 1174, 3408, - -2018, -2018, 2127, 1696, 3443, -1125, 1173, 2806, 833, 3147, - 870, 2167, 3110, -787, 1167, 2280, 2847, 1843, 804, 804, - 880, 1459, 3337, 3503, 3338, 1612, 873, 1144, 1701, 1145, - 2375, 2136, 1444, 2876, 3174, 2826, 2846, 1802, 3288, 3501, - 1869, 1871, 2856, 71, 1214, 3186, 2829, 2522, 1576, 1543, - 3419, 3388, 1868, 1576, 1215, 1500, 782, 1046, 2098, -512, - 1622, 2403, 1031, -516, 1778, 1295, 1216, 3519, 2857, 1175, - 1577, 3175, 1460, 1032, 2764, 1577, 2583, 1662, 2583, 1702, - 3526, 3369, 1175, 814, 1578, 2099, 3111, 1326, 1779, 3498, - 3430, 3472, 3451, 3433, 1624, 2199, 2168, 1760, 1217, 3238, - 3390, 3240, 2827, 1318, 874, 1774, 2877, 784, 2111, -669, - 834, 1697, 1006, 2587, 1581, 1775, 1168, 2995, 1176, 3269, - 2226, 3452, 3458, 1757, 2990, 2112, 3515, 2416, -512, 1575, - 2113, 1684, -516, 3010, 3420, 1744, 3304, 1543, 2413, 1137, - 3490, 1703, 3125, 3520, 2706, 3253, 1801, 3202, -787, 1326, - 1219, 2297, 3247, 980, 3344, 3183, 919, 1682, 1045, 3460, - 2090, 1902, 1985, 1757, 3263, 1903, 1904, 1011, 2114, 1905, - 1906, 1907, 2021, 2733, 2734, 1220, 3473, 3431, 2281, 1733, - 2137, 3504, 1326, 1675, 1750, 2206, 3259, 3496, 1734, 3114, - 2878, 3001, 2446, 2288, 1222, 1751, 2963, 1601, 2981, 856, - 2100, 714, 530, 1012, 1787, 2285, 2217, 2978, 2785, 941, - 2102, 902, 2513, 1934, 1138, 903, 2993, 1319, 2050, 1445, - 867, 953, 3316, 2703, 2279, 3159, 1858, 1040, 1949, 1014, - 945, 2534, 1862, 2940, 852, 3521, 1576, 3432, 2383, 2942, - 2560, 1554, 1558, 1559, 3279, 1970, -512, 972, 1327, 871, - -516, 2343, 1745, 875, 2192, 1750, 883, 1784, 1577, 2640, - 2641, 2026, 3137, 3138, 2370, 2664, 1753, 1571, -1893, 2748, - 2619, 1576, 1578, 2056, 1568, 2057, 2376, 2653, -1893, -1324, - 3466, -1265, 2555, 1645, 1568, -512, 2349, -512, 2549, -516, - 3250, -516, -850, 1577, 2142, 3251, 3104, -1884, 902, -1265, - -1246, 2072, 903, -1901, -1884, 1563, 2404, 1580, 2727, 3462, - 1330, -1104, 2644, 2409, -855, 534, -1266, -1901, 1560, 1607, - 3224, 1146, 1859, 2115, 1866, 1573, 865, 2032, 2033, -1266, - 1561, 2659, 3368, 993, 1566, -845, 1657, 3376, 2144, 966, - 2018, 1589, 1345, 1346, 1919, 1241, 2070, 1241, 1908, 3491, - 1589, 2443, 3351, 3162, 2154, 2443, 1018, 1778, 1543, 2010, - 2128, 2103, 971, -1125, 2053, 3122, 3375, 1173, -593, 1345, - 1346, 1909, 2104, -593, 3095, 1446, 1940, 865, 1612, 2155, - 2384, 1779, 2222, 2464, 3086, 112, -227, -227, 3522, 77, - 2385, 858, 2850, 2071, 2612, 1642, 1643, 1644, 1645, 968, - 868, 104, 520, 2814, 2191, 2191, 3005, 2613, 2279, 1916, - 1917, 1918, 1919, 520, 3352, 778, 1640, 1641, 1642, 1643, - 1644, 1645, 3087, 2410, 3097, 811, 1914, 1915, 1916, 1917, - 1918, 1919, 3404, 3405, 3492, 1189, 811, 3154, 3178, 3123, - 3441, 1910, 2223, 1175, -593, 2222, 881, 1624, 520, 520, - 105, 1543, 882, 2717, 2718, 2719, 2720, 2252, 2815, 2364, - 2969, 996, 2410, 3493, 2365, 1350, 3163, 2255, 113, 2628, - 2258, 520, 921, 977, 922, 1350, 3130, 71, 1350, 2851, - 2629, 995, 2336, 3060, 3135, 3445, 1035, 1036, 1037, 3179, - 70, 54, 1176, -593, 1759, 2940, 2251, 2594, 68, 58, - 65, 2942, 82, 102, 1141, 2580, 1147, 1759, 902, 77, - 69, 1155, 903, 518, 93, 520, 714, 1601, 3175, 1284, - 520, 2366, 1141, 2092, 518, 2523, 884, 2889, 3044, 844, - 844, 3046, 844, 3048, 2019, 98, 1437, 813, 1339, 900, - 2485, 1340, 3232, 2025, 2956, 2852, 2957, 2853, 813, 2419, - 2309, 3516, 1759, 3233, 1463, 2275, 2276, 2277, 1467, 3284, - 2353, 51, 1569, 1570, 3256, 52, 2342, 930, 1350, 53, - 2344, 2214, 1284, 2346, 56, 1870, 57, 60, 61, 1699, - 1046, 1294, 2776, 971, 63, 1543, 66, 67, 80, 2050, - 815, 520, 520, 81, 83, 2357, 1337, 520, 2250, 1576, - 520, 520, 84, 520, 520, 520, 520, 90, 91, 92, - 2098, 3243, 97, 101, 77, -1893, 930, 103, 2261, 520, - 1782, 1577, 2558, 2268, 2591, 1700, 520, 1046, 1379, 1380, - 1925, 2193, 2194, 1789, 1444, 1580, 2535, 2099, 2536, 931, - 778, 3270, 811, 2503, 520, 1284, 1546, 536, 1857, 811, - 906, 1911, 1912, 1913, 872, 1914, 1915, 1916, 1917, 1918, - 1919, 1943, 536, 1447, 865, 520, 1944, 1440, -594, 1454, - 2504, 1784, 2363, -594, 1451, 2253, 2367, 902, 1792, 2369, - 2256, 1600, 2130, 2566, 520, 918, 2131, 805, 931, 2459, - 925, 71, 864, 2226, 805, 520, 520, 520, 1760, 520, - 520, 2633, 3364, 3196, 714, 923, 1693, 924, 3347, 1857, - 537, 1760, 1599, 3070, 902, 2860, -1246, 1933, 903, 1935, - 1936, 2861, -208, 2555, 873, 537, 2408, 1452, 929, 1543, - 518, 1457, 982, 520, 2862, 2592, 932, 518, 937, 2620, - 2860, 1543, 1702, 994, -594, 1383, 1384, 1552, 942, 47, - 520, 520, 2100, 2420, 813, 2421, 1760, 2101, 2863, 943, - 2864, 813, 2102, 1673, 1757, 946, 1674, 1687, 1688, 1011, - 1694, 1543, 947, 882, 882, 933, 882, 1757, 1543, 1863, - 972, 948, 1864, 2863, 520, 1817, 949, 3289, 520, 520, - 2505, 880, 1593, -594, 2326, 2506, 2327, 1759, 520, 520, - 520, 959, 874, 520, 1703, 1012, 2605, 2669, 2607, 2467, - 934, 71, 1759, 2677, 1141, 2422, 1543, 2423, 23, 536, - 1543, 1453, 1757, 1546, 1818, 1984, 1543, 2743, 1985, 1131, - 1132, 1014, 1134, 1045, 2008, 2293, 1902, 2009, 2294, 2533, - 1903, 1904, 3290, 978, 1905, 1906, 1907, 2865, 1543, 2358, - 2396, 3291, 2359, 2397, 115, 1293, 1284, 979, 531, 1819, - 935, 2778, 980, 932, 1197, 1284, 744, 2843, 981, 2845, - 1198, 984, 2559, 2559, 107, 3292, 1170, 1785, 1172, 1759, - 907, 832, 537, 2444, 2501, 845, 2445, 987, 1197, 1284, - 541, 1200, 962, 2447, 1198, 2608, 2445, 2614, 2609, 2531, - 2615, 2680, 933, 988, 1985, 541, 908, 962, 989, 1820, - 990, 1546, 991, 2103, 854, 2866, 71, 2728, 545, 992, - 2867, 2735, 3006, 2617, 2104, -2015, -2015, 714, 1824, 1825, - 993, 1827, 1828, 545, 998, 1851, 714, 2655, 2621, 2050, - 3261, 2602, 1027, 2604, 3512, 2867, 2507, 3293, 1030, 804, - 1033, 875, 2593, 971, 2594, 539, 804, 2508, 1018, 1038, - 3294, 27, 28, 29, 3499, 2740, 3500, 1039, 2445, 2868, - 714, 909, -2016, -2016, 3475, 1199, 520, 1446, 1873, 892, - 77, 895, 1197, 899, 2595, 2869, 2938, 935, 1198, 3487, - 968, 1553, 2741, 1135, 2868, 2009, 2569, -2017, -2017, 1199, - 910, 1760, 1040, 1565, 1041, 2625, 778, 3525, 2744, 1150, - 2869, 2745, 1293, 2651, 2746, 2887, 1760, 2745, 1139, -207, - 1157, 2880, 1156, 520, 520, 2821, 34, 1159, 2822, 520, - 1591, 520, 2979, -2020, -2020, 2359, 520, 520, 520, 520, - 2955, 1160, 108, 911, 3523, 2844, 1909, 2980, 1161, 3524, - 2294, 520, 520, 109, 811, 1163, 520, 2999, 520, 1164, - 3000, 520, 541, 39, 542, 1171, 520, 1757, 520, 520, - 2965, 520, 2765, 2766, 2879, 520, 2888, 3007, 1190, 811, - 3008, 811, 1757, 1760, 811, 1192, 2870, 1195, 110, 811, - 545, 1194, 811, 1199, 811, 2871, 41, 3061, 811, 3197, - 2009, 1196, 2009, 1208, 1961, 3198, 1962, 44, 2445, 1964, - 1209, 2870, 880, 880, 1968, 880, 1910, 1971, 1226, 1972, - 2871, 1817, 3227, 1976, 805, 2009, 805, 1371, 1372, 805, - 3234, 1200, 1546, 1985, 805, 2753, 2755, 805, 111, 805, - 1589, 1593, 518, 805, 2754, 2756, 2757, 1230, 3333, 1757, - 3334, 2752, 2747, 2749, 1234, 1200, 2751, 23, 1543, 3295, - 1818, 47, 3296, 1535, 520, 520, 813, 518, 912, 518, - 2014, 2011, 518, 520, 520, -2021, -2021, 518, 2012, 913, - 518, 520, 518, 1235, 3244, 1287, 518, 3245, 520, 77, - 2013, 813, 1202, 813, 2016, 3169, 813, 1379, 1380, 3277, - 3278, 813, 2359, 2294, 813, 3313, 813, 1290, 2009, 1291, - 813, 1296, 1201, 714, 914, 2017, 1202, 520, 1298, 3373, - 520, 1210, 2359, 1312, 1203, 1546, 520, 520, 520, 520, - 520, 520, 520, 520, 714, -2022, -2022, 915, 520, 520, - 2139, 1211, 2086, 520, 2686, 1820, 1302, 520, 1203, 1200, - 520, 520, 520, 520, 520, 520, 520, 520, 520, 972, - 2555, 520, 1314, 3386, 916, 3141, 3387, 1315, 520, 1197, - 1284, 3412, 1322, 3456, 3413, 1198, 3387, 3497, -644, -644, - 3387, 1329, 71, -2023, -2023, -2025, -2025, 1212, 2881, 520, - 1323, 2070, 1543, 2174, 1332, 1204, -2026, -2026, 2882, 882, - 27, 28, 29, 815, -2027, -2027, 1227, 1350, 3105, 2887, - 1202, 520, -2028, -2028, 1383, 1384, -2029, -2029, 1333, 1204, - -2030, -2030, 520, 520, 1147, 1338, 1911, 1912, 1913, 1356, - 1914, 1915, 1916, 1917, 1918, 1919, -2031, -2031, -2032, -2032, - 1535, 1357, 1228, -2034, -2034, -2035, -2035, 1360, 1543, -2036, - -2036, -2037, -2037, -2038, -2038, 1363, 2883, -2039, -2039, 1546, - 2837, -2041, -2041, -2043, -2043, 34, -2045, -2045, 714, 1418, - 714, 1804, 1805, 1988, -648, -648, 2238, 1433, 2242, 3158, - 1199, 2973, 1213, 1431, 2991, 1434, 804, 1441, 804, 1448, - 2961, 804, -647, -647, 1381, 1382, 804, 2998, 1449, 804, - 3474, 804, 39, 1455, 3476, 804, 1456, 920, 1383, 1384, - 520, 1462, 927, 1204, 1284, 928, 1466, 520, 520, 3101, - 3102, 3223, 3483, 3484, 14, 15, 3312, 1197, 1535, 3509, - 3510, 1214, 1468, 1198, 3072, 41, 1548, 3045, 1668, 1669, - 1549, 1215, 1551, -821, -828, 1560, 44, 1564, 47, -669, - -670, 1543, -818, 1216, 1045, 2884, -819, 1902, 1284, 3517, - 1574, 1903, 1904, 2330, -822, 1905, 1906, 1907, 1575, 23, - 714, -820, 1585, 1598, 1651, 1604, 1045, 1284, 520, 1902, - 1653, 1655, 2779, 1903, 1904, 1217, 971, -2046, -2046, -2046, - 1606, 71, 1667, 1676, 1677, 1681, 1685, 1686, 1176, 1174, - 47, 1721, 1723, 1546, 1725, 1755, 1737, 520, 520, 1756, - 520, 1762, 1757, 1764, 1763, 1546, 520, 520, 520, 520, - 520, 520, 2555, 2938, 520, 520, 520, 520, 520, 520, - 520, 520, 520, 520, 1769, 1776, 1200, 1219, 1199, 520, - 520, 1777, 1791, 520, 1781, 1546, 1543, 1797, 112, 1807, - 520, 1813, 1546, 1808, 1809, 1822, 1823, 1816, 1831, 1832, - 1835, 1838, 1220, 1839, 1841, 1845, 1842, 3133, 1844, 1852, - 2096, 1853, 520, 1857, 1865, 1350, 520, 3312, 520, 1891, - 1350, 1222, 520, 2885, 1893, 1197, 2886, 3275, 1896, 1899, - 1546, 1198, 1894, 1231, 1546, 1922, 520, 1202, 1284, 811, - 1546, 1930, 1931, 3142, 3143, 811, 1938, 1941, 1959, 1963, - 1969, 1975, 27, 28, 29, 1973, 1980, 1554, 1974, 1983, - 3312, 1986, 1546, 1543, 2433, 1991, 1561, 1869, 1871, 1232, - 2436, 1566, 1987, 520, 520, 1989, 3043, 1992, 880, 2021, - 1046, 1990, 2020, 2054, 805, 2055, 1612, 2060, 2065, 1535, - 805, 2063, 2088, 2106, 2068, 2066, 2109, 2067, 2095, 2107, - 2133, 2134, 2140, 986, 2816, 2152, 2153, 1909, 2157, 3312, - 873, 2170, 865, 520, 1593, 2173, 2183, 34, 520, 520, - 2184, 2185, 2182, 2186, 2187, 2208, 2209, 518, 36, 3366, - 2204, 2219, 2212, 518, 1200, 1757, 1199, 2215, 2220, 3328, - 1204, 874, 2295, 520, 520, 2221, 2291, 2301, 520, 2310, - 38, 813, 2312, 2313, 39, 1197, 2314, 813, 23, 2316, - 2315, 1198, 520, 2317, 2331, 520, 2332, 520, 2334, 2341, - 1543, 1008, 2337, 2339, 2338, 2360, 1009, 1910, 2345, 2368, - 1927, 1902, 1535, 520, 714, 2398, 1926, 41, 2405, 2406, - 520, 2213, 2407, 520, 2411, 1202, 2417, 1191, 44, 1910, - 3119, 2418, 2429, 2435, 1543, 2437, 2449, 2451, 2456, 2457, - 520, 2458, 2311, 2460, 45, 2461, 811, 2462, 2465, 2463, - 2466, 2473, 2476, 520, 71, 2938, 2502, 1203, 2474, 1288, - 2477, 2478, 2509, 811, 2481, 1010, 2479, 554, 46, 2482, - 520, 520, 2519, 745, 2480, 1304, 1306, 1309, 1311, 2497, - 2518, 2483, 47, 2526, 2524, 821, 2484, 520, 2525, 520, - 2494, 805, 2537, 2495, 2538, 2540, 1199, 2542, 520, 862, - 862, 2548, 1869, 1871, 1784, 3264, 2543, 2564, 805, -650, - 2551, 2561, 2550, 1543, 1350, 2562, 714, 714, 714, 2565, - 2817, 2568, 1200, 2572, 2238, 2238, 2238, 1407, 1204, 2573, - 2574, 27, 28, 29, 518, 2576, 1011, 1045, 2578, 2579, - 1902, 2582, 2601, 536, 1903, 1904, 1535, 2603, 1905, 1906, - 1907, 518, 2616, 2634, 2635, 520, 1543, 865, 813, -525, - 2622, 1284, 893, 2636, 2637, 3063, 2650, 2623, -1310, 2624, - 2654, 2649, 1012, -525, 2666, 813, 804, 972, -525, 2259, - 2667, 2670, 804, 1202, 2671, 2678, 2683, 2674, 1013, 2693, - 2701, 2704, 2707, 2710, 2724, 2725, 34, 714, 1014, 2711, - 1824, 1825, 1546, 1827, 1828, 1873, 537, 2712, 2713, 2736, - 2737, 2742, 2750, 2758, 2761, 2260, 2767, 1911, 1912, 1913, - 520, 1914, 1915, 1916, 1917, 1918, 1919, 2773, 2781, -525, - 2783, 2796, 1015, 39, 520, 971, 2784, 2802, 2811, -2046, - -2046, -2046, 714, 1914, 1915, 1916, 1917, 1918, 1919, -525, - 1873, 2804, 1200, 1965, 2834, 2787, 2797, 2070, 1543, 2808, - 2308, 2828, 3317, 2830, 3319, 2842, 41, 2832, 2849, 2848, - 2855, 2875, 2891, 2958, 2959, 3327, 2964, 44, 1016, 2960, - 520, 2967, 2968, 2972, 2977, 1017, 1204, 2976, 2982, 2983, - 1535, 2987, 2996, 45, 2294, 3003, 3004, 3029, -525, 3009, - 3031, 3035, 1535, 811, 3039, 3049, 3050, -525, 1591, 2266, - 3053, 3073, 3329, 1202, 3331, 3052, 3080, 46, 3083, 3085, - 520, 3092, 3098, 3094, 3410, 1018, 2096, 3449, 3099, 3100, - 3106, 2818, 1535, 865, 3108, 3112, 1546, 3116, 1738, 1535, - 3107, 3117, 2520, 3126, 1019, 2267, 3118, 3129, 2799, 3131, - 1909, 1765, 520, 804, 3132, -1776, 3414, 3136, 520, 520, - -2014, -2015, 3150, 3403, -2016, -2017, 865, -2018, 3149, 520, - 804, -2019, 1790, -2020, 3151, 3155, 1350, 1535, -2021, -2022, - 520, 1535, -2023, 520, 3152, 520, 541, 1535, 962, 3156, - 3398, 518, 1546, 520, -2025, -2026, 520, 520, -2027, -2028, - -2029, 520, 520, -2030, -2031, -2032, -2034, -2035, 520, 1535, - 3153, 544, -2036, 1020, 545, 813, 1204, 2836, 1966, -2037, - 1910, 1611, -2038, 520, 1612, -2039, 3166, -2040, 1613, 1614, - 2014, 2011, -2041, 520, -2042, 1815, 2820, -2043, 2012, -2044, - -2045, -1263, 3164, 3170, 1834, 3171, 516, 527, 3185, 77, - 2013, 3189, 552, 520, 2016, -1776, -525, 3173, 552, 1622, - 3187, 3190, 802, 3193, 816, 816, -2046, 3199, 3203, 820, - 552, 828, 3200, 3207, 828, 2017, 3211, 846, 850, 3213, - 3217, 850, 3205, 3219, 552, 552, 3214, 3218, 3226, 3222, - 3242, 3246, 714, 1624, 3252, 2941, 714, 3241, 714, 3254, - 2238, 3249, -1776, 3266, 2943, 3267, 2242, -1262, 3274, 1876, - 520, 3276, 520, 3283, 802, 802, -1776, 3285, 3286, 3299, - 1543, -1776, 3300, 864, 902, 3301, -1776, 1159, 903, 3314, - 3315, 3318, 3321, 3322, 3324, -1776, 3330, 3335, 3355, 846, - -1776, 3125, 2970, 3359, 3361, 3362, 850, 552, 850, 850, - 850, 3365, 3371, 3438, 1824, 1825, 1877, 1827, 1828, 3379, - 3378, 3380, 3384, 3389, 3391, 3393, 3076, 3396, 1537, 3407, - 2992, 3397, -1776, 2994, 3400, 3402, 865, 1878, 3401, 3409, - 3411, 3416, 3421, 1957, 3428, 3427, 3429, 520, 3434, -2046, - 1546, 3435, -1776, 3436, 3464, 1879, 3444, 3446, 3448, 1880, - 3467, 3454, 3469, 3485, 3488, 939, -2046, 520, 520, 3502, - 3465, -2046, 520, 1008, 3466, 520, 3507, 3513, 1009, 3518, - 3527, 1881, 3528, 1162, 1882, 2890, 2246, 2599, 817, 817, - 1911, 1912, 1913, 3342, 1914, 1915, 1916, 1917, 1918, 1919, - 1883, -1776, 520, 3442, -1776, 2894, 3406, 3511, 2823, -2046, - -1776, 1611, 2347, 3139, 1612, 2685, 520, 3425, 1613, 1614, - 3495, 520, 520, 3262, 3463, 865, 520, 1546, 1210, 3470, - 3489, 520, -525, 3298, 520, 520, 1747, 1010, 2581, 520, - 1284, 23, 2606, 520, 904, 3461, -525, 520, 1211, 1622, - -1776, -525, 2577, 2859, 520, 3468, -2046, 2986, 2944, 1591, - 3459, 2645, 1821, 2690, 1633, 3194, 2966, 1855, 2567, 1438, - 811, 1678, 2553, -1776, 2211, 2715, 1717, 901, 3447, 1535, - 2179, 3392, 3320, 1624, 2563, 1718, 2210, 806, 2441, 2539, - 3038, 1722, 1591, 1884, 1212, 1440, 1439, 3221, 520, 2709, - 2329, 1885, -525, 2739, 997, 1537, 520, 983, 1011, 2708, - 3268, 71, 2455, 1405, 1390, 805, 2355, 71, 1392, 1396, - 23, 1397, -525, 1886, 1398, 520, 2356, 1399, 1400, 1401, - 3395, 852, 3394, 2556, 1546, 2492, 2763, 1950, 2493, 2470, - 2516, 2514, 2775, 2835, 1012, 3084, 3382, 2809, 2500, 976, - 1887, 2289, 2448, 1889, 1867, 2148, 1008, 958, 518, -1776, - 1013, 1009, 2824, 2883, -2046, 2150, 890, 0, 2941, -1776, - 1014, -525, 2626, 3340, 0, 2147, 0, 2149, 1793, -2046, - -525, 0, 813, 0, 27, 28, 29, 2159, -1776, 1213, - -1776, -1776, 0, 1537, 0, 0, -2046, 0, 0, 0, - 0, -2046, 1210, 0, 1015, 0, 0, 0, 0, 0, - 714, 0, 0, 1535, 0, 520, 0, 0, 1873, 0, - 1010, 0, 1211, 71, 0, 2196, 865, -1776, 0, 0, - -1776, -1776, -1776, 0, 0, 3177, 0, 0, 1214, -2046, - 0, 0, 0, 971, 0, 0, 520, 1546, 1215, 34, - 1016, 71, 0, 0, 71, 0, 0, 1017, 0, 0, - 1216, 0, 520, 27, 28, 29, 0, 0, 1212, 1535, - 0, -2046, 0, 862, 0, 0, 0, 0, 1640, 1641, - 1642, 1643, 1644, 1645, 0, 0, 39, 0, 0, 0, - 1546, 1011, 1217, 0, 1633, 520, 0, 1018, 0, 0, - 0, 0, 1591, 0, 0, 0, 520, 520, 0, 0, - 520, 0, 520, 0, 0, 0, 1019, 0, 0, 41, - 2302, 2303, 2305, 2306, 2307, 0, 0, 1012, 34, -525, - 44, 0, 0, 0, 850, 0, 0, 520, 0, 850, - 0, 0, 850, 1013, 1219, 0, 45, 0, 1611, 0, - 552, 1612, 0, 1014, 0, 1613, 1614, 0, 0, 0, - 0, 520, 0, 1213, 0, 39, 0, 0, 0, 1220, - 46, 0, 1535, 0, 0, 0, 0, 804, 0, 0, - 0, 0, 0, 0, 47, 1020, 1622, 1015, 1222, 0, - 0, 864, 2941, -2046, -2046, 0, 0, 902, 41, 0, - 0, 903, 0, 0, 0, 536, 0, 0, 1187, 44, - 0, 0, 1214, 0, 1537, 0, 714, 0, 3280, 3281, - 1624, 0, 1215, 0, 1873, 45, 0, 0, 0, 0, - -1310, 0, 520, 1016, 1216, 1538, 520, 0, 0, 0, - 1017, 0, 0, 0, 0, 0, 520, 0, 520, 46, - 520, 0, 0, 0, 520, 2424, 520, 0, 520, 811, - 0, 1540, 0, 47, 0, 0, 1217, 1535, 537, 520, - 0, 0, 0, 0, 520, 1045, 520, 0, 1902, 0, - 1018, 0, 1903, 1904, 520, 2510, 1905, 1906, 1907, 0, - 0, 0, 0, 0, 3339, 0, 3341, 714, 0, 1019, - 0, -2046, 520, 0, 0, 3348, 0, 1537, 1640, 1641, - 1642, 1643, 1644, 1645, 0, 0, -2046, 0, 1219, 0, - 0, 0, 961, 0, 0, 0, 3176, 0, 0, 0, - 536, 0, 0, -2046, 0, 0, 0, 3374, -2046, 0, - 951, 552, 552, 1220, 1535, 0, 23, 518, 0, 0, - 0, 520, 0, 3377, 0, -1310, 71, 3381, 0, 0, - 0, 520, 1222, 1413, 23, 0, 0, 0, 1020, 0, - 862, 813, 0, 520, 0, 0, -2046, 0, 0, 0, - 0, 974, 527, 816, 0, 0, 0, 520, 516, 0, - 850, 0, 1591, 537, 0, 0, 0, 0, 540, 802, - 0, 0, 0, 1001, 1001, 520, 0, 0, 1001, 1024, - 811, 0, 1538, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 828, 828, 828, 0, 0, 0, 0, 0, - 520, 1633, 0, 0, 0, 0, 828, 828, 1540, 828, - 0, 1537, 0, 0, 0, 520, 0, 538, 541, 0, - 962, 1535, 850, 811, 2941, 0, 714, 0, 552, 0, - 0, 0, 0, 0, 3348, 2207, 539, 543, 0, 0, - 850, 0, 0, 544, 0, 0, 545, 0, 0, 520, - 3471, 0, 0, 0, 850, 1535, 0, 0, 1909, 27, - 28, 29, 0, 520, 520, 520, 0, 0, 518, 0, - 1538, 0, 811, 0, 0, 0, 3486, 27, 28, 29, - 0, 0, 0, 0, 0, 0, 850, 1289, 0, 0, - 520, 0, 813, 540, 0, 0, 1540, 0, 1300, 0, - -207, -2046, 850, 850, 850, 850, 0, 0, 0, 71, - 71, 518, 0, 0, 1860, 975, 1861, 817, 1321, 0, - 0, 0, 0, 0, 34, 0, 0, 1414, 1910, 0, - 0, 520, 0, 0, 1535, 813, 0, 0, 0, 0, - 0, 0, 34, 541, 0, 542, 0, 1029, 0, 0, - 0, 1001, 1024, 0, 850, 1537, 0, 1412, 0, 0, - 518, 39, 543, 1001, 1001, 0, 0, 1537, 544, 552, - 0, 545, 1133, 2647, 0, 802, 0, 1535, 0, 39, - 0, 0, 802, 0, 813, 71, 0, 71, 2662, 2663, - 2665, 0, 552, 0, 41, 0, 0, 1537, 0, 1469, - 0, 0, 0, 2676, 1537, 44, 2679, 0, -2046, 1550, - 0, 2684, 41, 0, 0, 1640, 1641, 1642, 1643, 1644, - 1645, 45, 1611, 44, 0, 1612, 0, 0, 71, 1613, - 1614, 0, 0, -2046, -2046, -2046, 0, 0, 0, 45, - 0, 0, 1537, 0, 71, 46, 1537, 0, 71, 1415, - 0, 0, 1537, 0, 0, 0, 0, 0, 552, 47, - 1622, 0, 0, 46, 0, 0, 0, 1623, 0, 0, - 0, 0, 0, 0, 1537, 0, 0, 47, 0, 1535, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1538, 0, 0, 1624, 0, 0, 2721, 2722, 2723, - 0, 553, 0, 1347, 0, 0, 0, 553, 1670, 0, - 1672, 0, 0, 0, 1389, 1714, 0, 1540, 0, 553, - 0, 0, 0, 0, 1414, 552, 552, 0, 0, 0, - 0, 0, 850, 553, 553, 0, 0, 0, 1911, 1912, - 1913, 0, 1914, 1915, 1916, 1917, 1918, 1919, 0, 0, - 0, 0, 0, 0, 1412, 1900, 1901, 0, 0, 0, - 0, 1921, 0, 1470, 0, 850, 1746, 0, 0, 0, - 0, 71, 0, 0, 0, 0, 0, 0, 850, 0, - 0, 2034, 0, 0, 1538, 0, 0, 0, 2035, 2036, - 1625, 0, 2037, 2038, 2039, 850, 553, 71, 0, 850, - 0, 0, 0, 0, 1794, 0, 0, 1626, 0, 0, - 1540, 0, 1627, 0, 0, 0, 0, 1541, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1605, - 0, 0, 0, 0, 0, 0, 2831, 0, 0, 1608, - 0, 0, 0, 0, 0, 0, 1415, 0, 0, 0, - 1630, 0, 0, 0, 0, 0, 0, 0, 0, 1658, - 1810, 0, 850, 0, 0, 0, 0, 0, 1663, 0, - 0, 850, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1045, 1848, 0, 1902, 0, 0, 0, 1903, 1904, - 0, 951, 1905, 1906, 1907, 0, 951, 0, 552, 552, - 0, 552, 951, 0, 0, 1633, 0, 0, 0, 3064, - 0, 0, 0, 0, 0, 0, 0, 0, 1538, 0, - 0, 0, 0, 0, 0, 2218, 0, 2975, 0, 1469, - 0, 0, 0, 0, 0, 2227, 0, 2230, 0, 0, - 2241, 1535, 0, 0, 1540, 0, 2245, 0, 2247, 1414, - 1414, 0, 0, 0, 0, 1414, 0, 0, 0, 0, - 0, 2254, 0, 0, 0, 0, 2257, 0, 0, 0, - 2262, 2263, 2264, 2265, 0, 2269, 2270, 0, 0, 1412, - 1412, 0, 0, 0, 1537, 1412, 0, 516, 0, 3011, - 3012, 3013, 3014, 0, 1541, 0, 0, 0, 0, 0, - 1001, 0, 552, 1945, 0, 1635, 0, 0, 0, 0, - 850, 0, 802, 0, 802, 0, 0, 802, 0, 0, - 0, 0, 802, 1542, 0, 802, 0, 802, 0, 0, - 0, 802, 0, 552, 0, 552, 0, 0, 0, 0, + 0, 47, 48, 49, 754, 755, 1844, 1791, 2952, 1231, + 1781, 1357, 756, 2613, 2614, 2615, 2251, 1212, 3381, 2252, + 1213, 1214, 2617, 53, 54, 55, 115, 1243, 757, 758, + 531, 58, 2301, 923, 805, 1096, 807, 1097, 1610, 911, + 1248, 1249, 759, 2655, 2313, 3178, 2704, 3179, 2376, 2307, + 1367, 2369, 1885, 1825, 1368, 539, 1899, 2705, 2660, 1886, + 760, 2602, 2954, 3374, 2628, 3512, 2890, 2891, 3371, 3372, + 2605, 2254, 3440, 3441, 2687, 1772, 3435, 2332, 3314, 2258, + 2239, 2892, 2340, 3273, 3000, 2255, 2872, 2333, 3367, 1860, + 2334, 3368, 3127, 2335, 1822, 1848, 2606, 3442, 2259, 1823, + 2601, 2955, 1760, 2336, 3378, 2337, 550, 2876, 761, 2690, + 1313, 533, 522, 523, 1537, 719, 1289, 720, 762, 941, + 1854, 763, 1306, 1836, 64, 1320, 551, 1857, 764, 1845, + 765, 2674, 2675, 766, 767, 1173, 2556, 2169, 768, 745, + 746, 958, 1337, 747, 70, 1865, 769, 1343, 1344, 966, + 72, 873, 1359, 770, 1360, 1361, 975, 73, 2706, 977, + 978, 74, 75, 772, 3210, 3015, 1322, 1861, 2345, 552, + 773, 2837, 2171, 2559, 3363, 78, 3108, 2174, 1171, 3111, + 3328, 2830, 3106, 2560, 3403, 3457, 3109, 2175, 2176, 3329, + 2177, 774, 80, 822, 1698, 775, 776, 1038, 2024, 777, + 1763, 778, 1098, 86, 87, 1012, 88, 3121, 89, 90, + 1738, 1739, 1740, 851, 863, 864, 2167, 1453, 1968, 856, + 1177, 1707, 838, 839, 2297, 882, 1814, 1702, 1703, 2184, + 2569, 1731, 1732, 1186, 1187, 1956, 3343, 1957, 1958, 1446, + 1447, 3219, 1719, 1723, 1724, 2205, 2195, 1710, 2445, 3038, + 3039, 3040, 3041, 3042, 3043, 3044, 1099, 2743, 3230, 1727, + 1728, 1189, 1190, 1191, 1736, 2215, 92, 93, 2152, 2543, + 2544, 811, 3055, 1470, 1741, 2747, 2748, 2749, 3058, 3059, + 3060, 812, 1007, 1008, 1031, 1026, 1460, 1976, 813, 814, + 1933, 1934, 2414, 1033, 1970, 1986, 1987, 2755, 2467, 1538, + 2240, 1539, 1540, 2001, 1541, 1100, 1542, 1568, 1101, 1573, + 1544, 1102, 1103, 1104, 1547, 1105, 1106, 1107, 1108, 1561, + 1109, 1110, 1585, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010, 2011, 2012, 2013, 2014, 2015, 2016, 1157, 1742, 1112, + 1113, 1114, 1115, 1116, 1117, 1118, 1119, 816, 1120, 1121, + 1659, 2146, 2542, 3048, 3227, 3228, 2821, 3096, 3255, 3354, + 3471, 3499, 3500, 3526, 1122, 1123, 1602, 1603, 1604, 2038, + 2039, 2040, 2041, 2140, 1653, 1654, 1124, 2959, 1656, 2061, + 3051, 3052, 1158, 1439, 1597, 1291, 1292, 1552, 1413, 1414, + 1420, 1908, 1428, 1432, 1938, 1939, 1440, 2108, 1125, 2032, + 2033, 2485, 1563, 1126, 1247, 1609, 2816, 2143, 1657, 2102, + 1133, 1127, 1134, 1129, 1593, 1594, 2503, 2788, 2789, 2072, + 2212, 1686, 2217, 2218, 962, 1130, 1131, 1132, 1293, 526, + 1553, 3458, 1333, 1163, 1294, 2098, 779, 107, 907, 780, + 781, 97, 782, 1153, 860, 1154, 1156, 783, 832, 833, + 784, 845, 846, 1479, 1673, 1480, 869, 102, 103, 1200, + 834, 852, 786, 3205 +}; + +/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int16 yytable[] = +{ + 521, 60, 1128, 59, 1196, 910, 1230, 65, 959, 718, + 68, 76, 884, 885, 883, 91, 521, 104, 101, 77, + 717, 95, 84, 854, 1159, 809, 1301, 524, 1795, 1027, + 1431, 1806, 973, 1935, 1481, 91, 1250, 1356, 785, 2187, + 1403, 868, 2060, 815, 1687, 1303, 1759, 1778, 771, 2574, + 1794, 1340, 2150, 1401, 1990, 887, 1405, 1587, 1765, 850, + 1404, 2289, 2545, 1811, 2547, 2023, 1769, 2607, 1689, 888, + 744, 1346, 2562, 1362, 525, 2699, 1841, 2960, 2085, 2086, + 1663, 2988, 521, 521, 50, 1666, 1799, 866, 2463, 2561, + 525, 809, 809, 51, 52, 56, 901, 57, 61, 817, + 1867, 62, 63, 2957, 66, 969, 2526, 67, 1009, 815, + 815, 847, 3004, 1030, 2986, 961, 2647, 2648, 2649, 2600, + 3001, 69, 71, 974, 79, 893, 1600, 81, 82, 83, + 1250, 94, 85, 2787, -371, -1334, 96, 1232, 98, 1236, + 2661, 1240, 2851, -517, -1275, -863, 2856, 1370, 99, 2321, + 100, 1050, 85, 2314, 2465, 808, 525, 525, 2154, 2318, + -1900, 2207, -1909, 1912, -1909, 817, 817, -521, 1914, 85, + -2049, -2049, 1705, 1564, 1565, 536, -1256, -863, 867, -2035, + -2035, -860, -1917, -1275, -855, -860, -1900, -1276, -1917, 1334, + 1577, -1272, -1272, -822, -2040, -2040, -2058, -2058, 1670, 3402, + -835, 3197, 1363, 1415, -1276, 819, -2060, -2060, 2676, 1050, + -850, 819, -1273, -1273, 819, 979, 2664, 858, 2100, 1334, + 1350, 808, 808, 886, 2669, 1050, 1761, 1667, 1350, 819, + 3131, 2100, 2446, 1050, 2210, 85, 1750, 1797, 1050, -471, + 2668, 1619, 3276, -517, 1185, 2455, 1621, 2483, 1188, 2750, + 1809, 1619, 874, 1596, 2417, 1620, 1621, 973, -1113, 1810, + 3508, 2711, 2713, 1696, 2716, 2751, -1113, -521, 2220, 1146, + 819, 1250, 1694, 819, -229, 950, 1629, 1779, 1140, -229, + 1782, 1783, 1325, 1148, 1761, 23, 1629, 1030, 2683, 1912, + 3289, 1004, 537, 1913, 1914, 2635, 3361, 2137, 2121, 1009, + 1334, 3166, 3537, 1569, 3097, 2138, 3099, 1711, 2980, 3198, + 1631, 2440, 2441, 2442, 3, 4, -654, 1244, 874, 1579, + 1631, 1326, 2429, 3475, 3199, 2427, 1952, 3142, 935, 880, + 3319, 1753, 1364, 2603, 1616, 3114, 3521, 1770, 1145, 3182, + 3320, 1668, 3005, 875, 2733, 1619, 880, 3483, 3532, 1620, + 1621, 1691, 2656, 1712, 819, 1996, 3201, 1952, 1743, 1744, + -1134, 1747, 2295, 1363, 3468, 2823, 2722, 2825, -1134, 2182, + 3369, 3222, 2824, 1010, 2865, 1708, 2311, 3406, 2430, 3538, + 1629, 2894, -2034, -2034, 113, 3426, 1468, 1619, 2087, 3461, + 3519, 3165, 2147, 1591, 2537, -792, 3388, 2109, 1448, 2237, + 936, 836, 1582, 3355, 3128, 3356, 2844, 2237, 1813, 875, + 3191, 937, 1175, 1789, 1631, 1851, 1472, 105, 2611, 787, + 1476, 3203, 2122, 2864, 1583, 2110, 3104, 2029, 26, 27, + 28, 3544, 3370, -517, 3306, 2847, 2035, 1790, 1469, 2123, + 818, 1035, 1363, 1506, 2124, 1363, 1363, 3192, 2907, 1619, + 938, 1149, 1036, 1150, 2183, 2895, 1631, -521, 1592, 2238, + 788, 1303, 878, 861, 3105, 1669, 106, 2597, 114, 2604, + 3509, 3539, 1714, 2845, 3516, 3013, 2600, 3490, 2600, 3129, + 2781, 3408, 2125, 1709, 1629, 2672, 1335, 855, 3143, 3307, + 3448, 1755, 2608, 3451, 3522, 33, 3387, -674, 3308, 937, + 1327, 3476, 3491, 837, -517, 1587, 3287, 3321, 3006, 3220, + 1245, 3533, 1011, 1692, 1176, 3200, 1335, 1768, 1631, 2723, + 3469, 2431, 3309, 3362, 2428, 1912, 2241, 2296, -521, 1913, + 1914, -792, 38, 879, 1715, 940, 985, 1141, 938, 2896, + 2111, 2148, 1581, 1771, 2221, 2300, 3305, 2750, 2303, 3470, + 2113, 2629, 3478, 3028, 1812, 540, 870, 3510, 1745, 1697, + 925, 859, 1746, 2751, 2630, 40, 3146, 2459, 3277, 2832, + 3132, 1993, 3177, 939, 2981, 1798, 43, 2997, 1880, 1882, + 2060, 1608, 1690, 2031, 876, 718, 3511, 951, 3514, 2101, + 2294, 3019, 3449, 2232, 959, 3310, 947, 1335, 1944, 1869, + 1682, 3011, 2528, 2609, 3265, 1873, 1564, 1565, 3311, 1768, + 1756, 880, 1142, 1959, 3009, 2960, 1328, 2803, 541, 2549, + 3296, 1582, -517, 940, 2833, 1044, 3540, -1113, 973, 1979, + 46, 1577, 2207, 2636, 908, 2312, 2358, 538, 909, 2126, + 3436, 2957, 1795, 1583, 2213, 1560, -521, 1336, 2572, 2670, + 2478, 1300, 1770, 1582, -371, -1334, -1275, 1584, 2765, 2679, + 534, -517, 2153, -517, 1181, 1929, 2139, 2698, 2564, 2385, + 85, 2364, -1900, 3268, -1909, 1583, -1909, 1339, 3269, 3484, + 1574, 2391, 1574, 1566, 3122, -521, 908, -521, -1256, 1586, + 909, 2042, 2043, -860, -1917, -1275, -855, 2661, -1900, -1276, + -1917, 1877, 3242, 2114, 2577, 1567, 2720, 1870, 2744, 3386, + 998, 2419, 1572, 3186, 2115, 872, -1276, 1614, 2424, 974, + 2028, 1596, -850, 1664, 1354, 1355, 2155, 1001, 3393, -1134, + 1596, 1181, 1354, 1355, 1250, 2081, 1250, 3155, 3156, 1569, + 1183, 1950, 3392, 1652, 2063, 3450, 972, 1151, 868, 1789, + 1649, 1650, 1651, 1652, 2456, 2657, 2658, 3113, 2456, 1579, + 1207, 2214, 881, 2390, 3140, 2378, 871, 91, 3195, 2382, + 785, 2294, 2384, 1790, 2082, 877, 3437, 1784, -229, -229, + 1793, 976, 2734, 2735, 2736, 2737, 521, 2477, 1926, 1927, + 1928, 1929, 819, 889, 2418, 2019, 2036, 521, 1204, 868, + 545, 540, 968, 3271, 1205, 3172, 1000, 1183, 2066, 3312, + 2067, 2379, 3313, 815, 1197, 887, 2380, 3023, 3459, 3256, + 3196, 3258, 3281, 2610, 815, 2611, 2874, 2398, 549, 888, + 1457, 521, 521, 2425, 3115, 904, 1464, 2083, 2986, 3141, + 2267, 1147, 1647, 1648, 1649, 1650, 1651, 1652, 2165, 3148, + 2270, 2348, 2875, 2273, 521, 2612, 1184, 3153, 1771, 908, + 525, 1147, 3438, 909, 541, 819, 3180, 1379, 1380, 817, + 2425, 525, 60, 2166, 59, 2381, 1582, 2960, 65, 906, + 817, 68, 76, 2265, 85, 867, 91, 1152, 104, 101, + 77, -1909, 95, 84, 2103, 3078, 3192, 2974, 1583, 2975, + 912, 521, 718, 2957, 1160, 1288, 521, 1770, 1608, 1206, + 2538, 2434, 1584, 14, 15, 1551, 3062, 847, 847, 3064, + 847, 3066, 1785, 924, 1768, 987, 2290, 2291, 2292, 3534, + 3324, 1770, 1786, 1761, 1451, 908, 999, 1387, 1388, 1607, + 3288, 1461, 3334, 2368, 1762, 2206, 2206, 1868, 2324, 931, + 108, 2500, 3274, 2868, 2060, 50, 2357, -209, 1288, 23, + 2359, 1204, 1770, 2361, 51, 52, 56, 1205, 57, 61, + 2399, 972, 62, 63, 2794, 66, 521, 521, 67, 2370, + 2400, 1346, 521, 886, 1304, 521, 521, 2229, 521, 521, + 521, 521, 69, 71, 91, 79, 1302, 785, 81, 82, + 83, 942, 94, 85, 521, 1363, 3261, 96, 2878, 98, + 935, 521, 2518, 809, 2266, 1363, 1935, 1672, 1363, 99, + 809, 100, 1924, 1925, 1926, 1927, 1928, 1929, 521, 1288, + 1536, 815, 1761, 2645, 2276, 1800, 3422, 3423, 815, 2283, + 2519, 2869, 540, 1764, 2646, 3382, 545, 943, 968, 521, + 2268, 2881, 1868, 949, 1770, 2271, 1393, 1394, 2550, 1803, + 1879, 2551, 3250, 1795, 2023, 1050, 1207, 3088, 521, 1575, + 1576, 2650, 1206, 3251, 549, 1827, 1711, 1454, 525, 521, + 521, 521, 936, 521, 521, 525, 868, 817, 718, 3463, + 2634, 2572, 1387, 1388, 817, 1551, 3365, 948, 2583, 1606, + 2241, 1881, 26, 27, 28, 541, 1050, 2870, 1363, 2871, + 2423, 85, 2141, 1771, 1828, 3214, 2142, 521, 2575, 2109, + 109, 558, 1712, 1050, 952, 1208, 2637, 749, 1953, 1209, + 1770, 110, 953, 1954, 521, 521, 1462, 1771, 824, 954, + 1467, 1699, 1700, 808, 1706, 1204, 927, 2110, 928, 3187, + 808, 1205, 865, 865, 1147, 888, 888, 1181, 888, 955, + 2520, 1210, 1182, 973, 1348, 2521, 111, 1349, 1771, 33, + -598, 1943, 521, 1945, 1946, -598, 521, 521, 543, 1768, + 35, 1827, 2638, 1600, 1559, 1551, 521, 521, 521, 965, + 1713, 521, 983, 2481, 1680, 2684, 1571, 1681, 984, 1830, + 1582, 2692, 37, 1768, 1135, 1136, 38, 1138, 985, 3279, + 1536, 1393, 1394, 1016, 2885, 986, 112, 897, 1796, 989, + 1828, 1874, 1583, 1598, 1875, 1992, 2472, 2017, 1993, 1207, + 2018, 992, 1211, 1183, 1768, 2760, 1586, 1302, 993, 40, + 1049, 1714, 994, 1912, -208, 1288, -598, 1913, 1914, 1017, + 43, 1915, 1916, 1917, 1288, 1829, 1206, 908, 2642, -1256, + 1771, 909, 2111, 2886, 1003, 1455, 44, 2112, 2796, 2516, + 2546, 2308, 2113, 2373, 2309, 1019, 2374, 2411, 1288, 1032, + 2412, 2887, 1184, 2457, -2031, -2031, 2458, 545, 1234, 546, + 45, 2460, 1209, 2625, 2458, -598, 2626, 1043, 2631, 2695, + 1536, 2632, 1993, 1715, 46, 1830, 3024, 1835, 2060, 886, + 886, 995, 886, 1837, 996, 549, 718, 1838, 2522, 2757, + -2032, -2032, 2458, 1839, 1235, 718, 1768, 1862, 821, 2523, + 2758, 2745, 3530, 2018, 2752, 2619, 1771, 2621, 2761, 997, + 1049, 2762, 972, 1912, 998, 1217, 116, 1913, 1914, 1037, + 535, 1915, 1916, 1917, 3517, 1042, 3518, 2763, 748, 718, + 2762, -2033, -2033, 91, 521, 1218, 785, 1044, 2797, 3493, + 1884, 2839, 835, 1558, 2840, 46, 848, 976, 1971, 2548, + 1144, 1973, 2888, 1454, 3505, 2586, 1977, 2996, 1045, 1980, + 2309, 2889, 1139, 3012, 1984, 1211, 2374, 3543, 2958, 1204, + 1155, 1204, 1768, 1551, 1023, 1205, 3017, 1205, 1161, 3018, + 2905, 1219, 1162, 1207, 521, 521, 2576, 2576, 905, 2667, + 521, 3025, 521, 1456, 3026, 2114, 1164, 521, 521, 521, + 521, 2973, 2898, 929, 3079, 930, 2115, 2018, 2862, 3541, + -2036, -2036, 521, 521, 3542, -2037, -2037, 3215, 521, 815, + 2018, 521, 1169, 2338, 1919, 2339, 521, 809, 521, 521, + 809, -2038, -2038, 3216, 521, 809, 2458, 2897, 809, 2906, + 1165, 2782, 2783, 809, 3245, 815, 1209, 2018, 815, 3252, + 85, 2983, 1993, 815, 3262, 3295, 815, 3263, 2309, 3299, + 3331, 815, 2374, 2018, 1166, 3399, 525, 1551, 2374, 2435, + 3404, 2436, 3351, 3405, 3352, 817, 3430, 1220, 1210, 3431, + 1206, 3474, 1206, 2437, 3405, 2438, 1170, 3515, 1536, 1016, + 3405, 2622, 525, 2624, 1920, 525, -2039, -2039, 2769, 1596, + 525, 817, 1179, 525, 817, 2861, 1600, 2863, 525, 817, + 2768, 1198, 817, 1199, 2771, 2773, 2774, 817, 2770, 2772, + 521, 521, -2041, -2041, 1919, 1017, 1221, 2020, 1201, 521, + 521, 1039, 1040, 1041, 2021, 1202, 1222, 521, 1178, 91, + 1180, 1463, 2027, 2022, 521, 2026, 2025, 1203, 1223, 1211, + 1215, 1019, -530, 1216, 540, -2042, -2042, 808, -2043, -2043, + 808, -2044, -2044, -2045, -2045, 808, 1233, -530, 808, 1237, + 718, 1241, -530, 808, 521, -2046, -2046, 521, 1242, -1320, + 1224, 1296, 1536, 521, 521, 521, 521, 521, 521, 521, + 521, 718, 1204, 2703, 1920, 521, 521, 1299, 1205, 2572, + 521, 1305, 2097, 1300, 521, 1551, 1308, 521, 521, 521, + 521, 521, 521, 521, 521, 521, 973, 541, 521, 2150, + -2047, -2047, 1307, -530, 857, 521, 1321, 1288, -2048, -2048, + -2050, -2050, 1323, 945, 1226, 1324, 1204, 1207, 1331, 1207, + 1332, 2189, 1205, -530, -2051, -2051, 521, 1338, 3159, -2052, + -2052, -2053, -2053, -2054, -2054, 888, 85, 1341, 2081, 1227, + -2055, -2055, -2057, -2057, 2764, 2766, -2059, -2059, -2061, -2061, + 1342, 967, 3123, 521, 1365, 2905, 1815, 1816, 1229, 1152, + 1023, 2208, 2209, 1347, 521, 521, 1366, -649, -649, -653, + -653, 896, -530, 899, 1371, 903, 1238, 1429, 2228, 1456, + 1209, -530, 1209, 1206, -652, -652, 1921, 1922, 1923, 1444, + 1924, 1925, 1926, 1927, 1928, 1929, 1389, 1390, 1393, 1394, + 1536, 2855, 3119, 3120, 2566, 2567, 3501, 3502, 1442, 718, + 1445, 718, 1239, 1452, 1210, 1458, 2107, 2979, 3527, 3528, + 2253, 3176, 2257, 1996, 1675, 1676, 1459, 1206, 1551, 544, + 1465, 1466, 1471, 1475, 1477, 2991, 14, 15, 1554, 1555, + 1551, 3007, 3492, 3016, 1557, -826, 3494, -833, 1566, 1570, + 46, 521, -674, -675, -823, 1288, -824, -827, 521, 521, + 1580, 1581, -825, 3090, 1605, 3330, 1611, 1613, 1658, 1660, + 1551, 1674, 1662, 3480, 1684, 1683, 1688, 1551, 1693, 545, + 1695, 968, 23, 1211, 3241, 1211, 1921, 1922, 1923, 886, + 1924, 1925, 1926, 1927, 1928, 1929, 1288, 1182, 547, 1184, + 1735, 3535, 1737, 1363, 548, 964, 1733, 549, 1748, 1766, + 1767, 718, 1768, 1551, 1773, 1774, 1792, 1551, 1288, 521, + 1775, 2342, 1049, 1551, 1780, 1912, 1787, 972, 113, 1913, + 1914, 1788, -530, 1915, 1916, 1917, 1802, 1808, 1819, 1818, + 1207, 2572, 1820, 1536, 1013, 2447, 1551, 521, 521, 1014, + 521, 2450, 1824, 1832, 1833, 1536, 521, 521, 521, 521, + 521, 521, 1834, 1843, 521, 521, 521, 521, 521, 521, + 521, 521, 521, 521, 1846, 1847, 1849, 1850, 1852, 521, + 521, -530, 1853, 521, 1207, 1536, 2958, 1855, 1856, 1863, + 521, 1864, 1536, 1868, 1876, 1904, -530, 1940, 1901, 2274, + 908, -530, 1903, 1209, 909, 1906, 1909, 3151, 1015, 1972, + 1932, 1941, 521, 1948, 1969, 521, 3330, 521, 1951, 1978, + 865, 521, 2326, 1981, 809, 26, 27, 28, 1536, 1982, + 809, 85, 1536, 3063, 521, 2275, 1288, 1983, 1536, 1988, + 1991, 2000, 815, 2281, 1994, 1560, 1567, 1209, 815, 3293, + 3160, 3161, -530, 1572, 1999, 2031, 878, 1995, 1997, 3330, + 1998, 1536, 2030, 1050, 2064, 2065, 1619, 3061, 2068, 2071, + 2074, -599, -530, 521, 521, 2077, -599, 2076, 1543, 2282, + 1016, 2079, 2078, 2099, 2117, 2106, 2118, 2120, 1192, 525, + 2145, 2144, 33, 2151, 2168, 525, 2164, 2163, 817, 879, + 2197, 2188, 2185, 35, 817, 2198, 1211, 2199, 3330, 2200, + 2201, 521, 2202, 1918, 521, 2219, 1017, 2224, 1887, 521, + 521, -530, 1600, 2223, 880, 37, 2227, 879, 2230, 38, + -530, 3384, 1018, 2234, 2235, 2236, 1919, 2306, 2310, 2315, + 981, 2325, 1019, 2327, 521, 521, 2328, -599, 2329, 521, + 1211, 868, 2343, 2344, 808, 2346, 2349, 2350, 2351, 2353, + 808, 2352, 40, 521, 2354, 1888, 521, 3346, 521, 2356, + 2360, 1034, 1363, 43, 2375, 1912, 1020, 1363, 2383, 1937, + 2413, 1936, 2420, 2421, 521, 718, 1889, 2422, 2432, 44, + 2433, 521, 3137, 2426, 521, 1137, -599, 1193, 2444, 2449, + 2451, 2462, 926, 809, 1890, 880, 1920, 933, 1891, 2464, + 934, 521, 2469, 45, 2473, 2470, 2471, 2474, 2475, 2476, + 809, 815, 1021, 2479, 1880, 1882, 2492, 46, 521, 1022, + 821, 1892, 2495, 2487, 1893, 2480, 2496, 2491, 815, 2488, + 1592, 2493, 2494, 2490, 2497, 521, 521, 2517, 2958, 2498, + 1894, 2512, 2509, 2533, 2541, 2510, 2552, 2524, 1543, 1551, + 2557, 2534, 521, 2539, 521, 2540, 2553, 2555, 525, 2558, + 23, 1023, 2565, 521, 2563, 1697, 2568, 817, -655, 2578, + 1795, -530, 2581, 2579, 2582, 525, 2585, 2589, 1598, 2590, + 1024, 718, 718, 718, 817, 3282, 2593, 2591, 2595, 2596, + 2599, 2618, 2253, 2253, 2253, 1049, 2107, 2633, 1912, 2620, + 2639, 2651, 1913, 1914, 2640, 2666, 1915, 1916, 1917, 865, + 2641, 2652, 2535, 2653, 2671, 2654, 2665, 2682, 2681, 2685, + 521, 1358, 2686, 808, 2700, 2689, 1288, 2710, 2693, 1399, + 2721, 2741, 2718, 1895, 2724, 2742, 2753, 973, 1543, 908, + 808, 1896, 1164, 909, 2754, 2727, 881, 2728, 2778, 1025, + 2791, 2759, 2729, 2730, 1194, 1835, 520, 532, 2801, 2820, + 868, 1837, 556, 1897, 1536, 1838, 2767, 2802, 556, 2775, + 2814, 1839, 806, 2829, 820, 2822, 2785, 2799, 823, 556, + 831, 2805, 521, 831, 1551, 718, 849, 853, 2848, 2815, + 853, 2860, 1898, 556, 556, 2826, 1884, 2846, 2873, 521, + 972, 2850, 2852, 26, 27, 28, 2866, 718, 1921, 1922, + 1923, 2867, 1924, 1925, 1926, 1927, 1928, 1929, 1884, 1880, + 1882, 2893, 2909, 2976, 3335, 2977, 3337, 2081, 2978, 2985, + 2989, 1363, 2982, 2990, 2999, 2341, 2994, 3345, 806, 806, + 2995, 2998, 1551, 1612, 3003, 521, 1545, 3021, 991, 2309, + 3022, 3014, 849, 1615, 3027, 3049, 23, 853, 556, 853, + 853, 853, 3053, 3047, 3057, 3067, 3068, 3110, 540, 3070, + 33, 3071, 815, 1665, 3091, 3098, 3101, 3103, 1546, 3112, + 3116, 3117, 1671, 3118, 521, 3124, 2222, 1871, 3125, 1872, + 3130, 3134, 3347, -1320, 3349, 3467, 3126, 867, 3135, 1536, + 3136, 3144, 3147, 1147, 3428, 3149, 2817, 38, 3150, 1919, + 3154, 3421, 3168, 3183, 3169, 3167, 521, -2030, -2031, 525, + 3432, -2032, 521, 521, -2033, -2034, 1168, -2035, 817, -2036, + 3188, 541, 3202, 3173, 521, -2037, 868, -2038, 3189, -2039, + 40, -2041, 3170, -2042, -2043, 521, -2044, 1551, 521, 3171, + 521, 43, 3416, -2045, -2046, -2047, 1543, 1536, 521, -2048, + -2050, 521, 521, 3204, 3206, -2051, 521, 521, -2052, 868, + -2053, -2054, 3174, 521, -2055, -2056, 1297, 3207, -2057, 1920, + -2058, -2059, -2060, -2061, 3181, 2323, -1273, 3208, 521, 3211, + 3217, 1310, 1312, 1315, 1317, 3218, 2020, 3221, 521, 26, + 27, 28, 3223, 2021, 3229, 46, 3235, 3225, 91, 3232, + 3237, 2027, 2022, 3231, 2026, 2025, 3236, 3240, 3244, 3260, + 521, 2838, 2854, 3259, 3264, 3267, 1545, 1049, 3270, 3272, + 1912, 3284, 3285, -1272, 1913, 1914, 3292, 3294, 1915, 1916, + 1917, 3301, 1551, 1418, 3302, 3303, 3316, 3317, 3318, 3332, + 1543, 3333, 3336, 3339, 3340, 3081, 3353, 3348, 1546, 718, + 3342, 3373, 2956, 718, 3143, 718, 33, 3377, 3379, 3380, + 2253, 3383, 3389, 1598, 2961, 3395, 2257, 521, 3396, 521, + 3397, 3407, 3402, 1049, 3409, 3411, 1912, 1013, 3094, 3414, + 1913, 1914, 1014, 1363, 1915, 1916, 1917, 3415, 3418, 3419, + 3420, 3427, 3425, 38, 3429, 3456, 1598, 3434, 1883, 3439, + 3446, 1835, 3445, 545, 3447, 968, 1545, 1837, 3454, 913, + 1551, 1838, 3452, 3453, 3462, 85, 3464, 1839, 2987, 3466, + 3482, 85, 3485, 3472, 3487, 3520, 40, 3503, 548, 3506, + 3483, 549, 3525, 3484, 3531, 914, 3536, 43, 1546, 3545, + 3546, 1015, 3157, 1167, 521, 3008, 2908, 1536, 3010, 2853, + 2261, 2616, 2912, 44, 2160, 1804, 2643, 982, 2304, 2662, + 2707, 3212, 2984, 3443, 521, 521, 3513, 3280, 3481, 521, + 3488, 868, 521, 3507, 3315, 1451, 1758, 45, 1543, 2598, + 2623, 1921, 1922, 1923, 3002, 1924, 1925, 1926, 1927, 1928, + 1929, 46, 3479, 3486, 2594, 2877, 3477, 1831, 2702, 521, + 1878, 915, 2362, 2962, 2842, 3400, 3360, 1866, 2841, 3460, + 3424, 3529, 1174, 1016, 521, 2827, 2584, 1551, 1685, 521, + 521, 1449, 2834, 1450, 521, 1536, 2570, 2226, 85, 521, + 916, 1919, 521, 521, 1730, 2732, 3465, 521, 1288, 2580, + 2194, 521, 910, 3410, 1729, 521, 1749, 3338, 1734, 1017, + 2225, 1551, 521, 810, 809, 85, 2554, 3056, 85, 1776, + 2454, 868, 3239, 1002, 1416, 1018, 2726, 2725, 2756, 3286, + 2468, 1400, 815, 917, 2371, 1019, 988, 23, 853, 1402, + 1801, 3413, 1406, 853, 1407, 1408, 853, 1919, 3412, 2372, + 2233, 1409, 2507, 2780, 556, 1217, 521, 1410, 1411, 1412, + 2242, 1920, 2245, 2573, 521, 2256, 2531, 2529, 1598, 1020, + 2508, 2260, 2484, 2262, 3102, 1218, 1960, 2793, 894, 525, + 2159, 1543, 2461, 521, 1545, 0, 2269, 0, 817, 0, + 1551, 2272, 1536, 1543, 1143, 2277, 2278, 2279, 2280, 0, + 2284, 2285, 0, 0, 0, 1826, 0, 0, 0, 0, + 0, 1842, 0, 0, 0, 1021, 1546, 1920, 0, 0, + 0, 1219, 1022, 1543, 0, 0, 2956, 0, 0, 0, + 1543, 0, 0, 1551, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 808, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 867, 0, + 918, 1548, 0, 0, 1023, 2156, 1543, 0, 0, 2835, + 1543, 919, 521, 718, 0, 0, 1543, 0, 1545, 0, + 26, 27, 28, 1024, 1884, 0, 0, 1549, 0, 2179, + 2181, 2901, 0, 0, 0, 1618, 0, 0, 1619, 1543, + 0, 972, 1620, 1621, 521, 1536, 920, 0, 0, 0, + 1546, 3194, 0, 0, 0, 0, 0, 1220, 0, 0, + 521, 0, 868, 0, 0, 0, 0, 0, 0, 921, + 0, 0, 0, 1629, 0, 1551, 0, 0, 0, 0, + -2062, 0, 0, 0, 957, 556, 556, 33, 1536, 0, + 0, 0, 1025, 521, 0, 1967, 922, 0, 0, 0, + 0, 0, 0, 0, 521, 521, 1221, 1631, 521, 0, + 521, 0, 0, 1921, 1922, 1923, 1222, 1924, 1925, 1926, + 1927, 1928, 1929, 0, 38, 0, 980, 532, 1223, 0, + 0, 0, 520, 0, 853, 521, 0, 2286, 0, 0, + 0, 0, 0, 806, 0, 0, 0, 1006, 1006, 0, + 2302, 2302, 1006, 1029, 0, 0, 1545, 40, 0, 521, + 1224, 85, 0, 0, 0, 831, 831, 831, 43, 1921, + 1922, 1923, 2515, 1924, 1925, 1926, 1927, 1928, 1929, 831, + 831, 1548, 831, 0, 44, 0, 0, 0, 1546, 0, + 2956, 0, 0, 0, 0, 853, 0, 0, 3193, 1598, + 0, 556, 0, 0, -2062, 0, 0, 1549, 45, 0, + 0, 0, 853, 0, 1226, 853, 820, 1358, 0, 23, + 0, -2062, 2836, 2377, 0, 0, -2062, 0, 0, 521, + 718, 0, 0, 0, 521, 3297, 3298, 0, 0, 1227, + 0, 1884, 0, 0, 521, 0, 521, 0, 521, 0, + 0, 0, 521, 0, 521, 0, 521, 0, 1229, 0, + 0, 815, 853, 1298, -2062, 0, 0, 521, 0, 0, + 0, 1548, 521, 0, 521, 0, 0, 853, 853, 853, + 853, 1319, 521, 0, 0, 1424, 0, 0, 0, 0, + 0, 0, 0, 0, 1330, 718, 0, 1549, 0, 1545, + 521, 1871, 0, 0, 0, 0, 3366, 0, 525, 0, + 0, 1545, 3357, 0, 3359, 0, 0, 817, 0, 1640, + 0, 0, 0, 2158, 0, 2161, 1006, 1029, 0, 853, + 0, 1546, 1423, 0, 0, 0, 2170, 1551, 1006, 1006, + 0, 1545, 0, 1546, 556, 85, 85, 0, 1545, 521, + 806, 0, 1543, 0, 3391, 0, 0, 806, 0, 521, + 0, 0, 26, 27, 28, 0, 0, 556, 0, 0, + 3394, 521, 0, 1546, 3398, 0, 0, 0, 2211, 0, + 1546, 0, 0, 1556, 1545, 521, 0, 0, 1545, 0, + 0, 0, 0, 0, 1545, 0, 0, 0, 0, 0, + 0, 0, 0, 521, 0, 0, -1792, 0, 0, 0, + 0, 0, 815, 0, 0, 0, 1546, 1545, 0, 0, + 1546, -2062, 85, 0, 85, 0, 1546, 0, 521, 33, + 0, 0, 556, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 521, 0, 0, 0, 0, 0, 1546, + 0, 0, 2956, 0, 718, 815, 0, 0, 0, 525, + 0, 0, 0, 0, 85, 3366, 38, 0, 817, 0, + 0, 2316, 2317, 2319, 2320, 0, 2322, 521, 0, 2688, + 85, 0, 0, 1677, 85, 0, 1679, 1543, 0, 1548, + 0, 521, 521, 521, 0, 0, 0, 0, 3489, 40, + 556, 556, 525, 0, 815, 0, -1792, 0, 853, 0, + 43, 817, 23, 0, 0, 1549, 0, 0, 521, 0, + 0, 0, 0, 0, 3504, 0, 44, 0, -2062, 0, + 0, 0, 1423, 0, 0, 1647, 1648, 1649, 1650, 1651, + 1652, 0, 853, 1757, 0, 1543, 0, 0, 0, 0, + 45, 525, 0, -1792, 1049, 853, 0, 1912, 0, 521, + 817, 1913, 1914, 0, 46, -2062, -2062, -2062, -1792, 0, + 0, 0, 853, -1792, 0, 0, 853, 0, -1792, 0, + 0, 1805, 0, 1548, 0, 0, 0, -1792, 2627, 0, + 0, 0, -1792, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2439, 23, 85, 1549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 557, 0, 0, 0, -1792, 0, 557, 0, 0, 0, + 0, 0, 0, 0, 85, 0, 0, 557, 0, 1821, + 2659, 853, 0, 0, -1792, 0, 0, 853, 0, 0, + 1543, 557, 557, 0, 0, 26, 27, 28, 2673, 0, + 0, 1859, 0, 1013, 0, 0, 0, 0, 1014, 0, + 957, 0, 0, 0, 0, 957, 1550, 556, 556, 1049, + 556, 957, 1912, 0, 0, 0, 1913, 1914, 0, 0, + 1915, 1916, 1917, -1792, 0, 0, -1792, 0, 0, 0, + 1358, 0, -1792, 0, 0, 0, 0, 3082, 0, 2708, + 0, 2709, 0, 1910, 1911, 2714, 557, 2717, 0, 1931, + 0, 1548, 33, 0, 0, 0, 0, 1015, 2857, 2858, + 1545, 0, 0, 0, 0, 0, 0, 0, 0, 3358, + 0, 0, -1792, 0, 0, 1543, 0, 1549, 0, 0, + 26, 27, 28, 0, 0, 0, 2910, 0, 0, 38, + 1423, 1423, 1546, 0, 0, 0, 1423, -1792, 520, 0, + 0, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, + 2972, 1006, 0, 556, 1955, 0, 0, 0, 0, 0, + 0, 853, 40, 0, 806, 0, 0, 806, 0, 1016, + 0, 0, 806, 43, 0, 806, 0, 1425, 0, 0, + 806, 0, 556, 0, 556, 0, 0, 33, 0, 44, + 0, 0, 0, 1543, 0, 855, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1017, 0, 0, 1920, 0, + 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, + 0, 1018, 0, -1792, 38, 0, 1550, 46, 0, 0, + 0, 1019, 0, -1792, 1548, 1545, 1049, 0, 0, 1912, + 0, 0, 0, 1913, 1914, 0, 1548, 1915, 1916, 1917, + 0, 0, -1792, 0, -1792, -1792, 0, 40, 0, 0, + 1549, 0, 0, 1919, 0, 1020, 0, 1546, 43, 0, + 0, 0, 1549, 0, 0, 0, 1548, 0, 0, 0, + 0, 0, 0, 1548, 44, 0, 1195, 0, 0, 2059, + 0, -1792, 0, 1545, -1792, -1792, -1792, 0, 0, 0, + 1543, 2070, 1549, 0, 0, 0, 0, 0, 45, 1549, + 0, 1021, 0, 0, 0, 0, 1550, 0, 1022, 1548, + 0, 0, 46, 1548, 0, 1546, 1426, 0, 2663, 1548, + 0, 0, 2953, 1920, 1543, 0, 0, 0, 0, 0, + 957, 2677, 2678, 2680, 0, 1549, 0, 0, 0, 1549, + 0, 0, 1548, 0, 0, 1549, 2691, 0, 0, 2694, + 1023, 0, 0, 0, 0, 2659, 0, 2701, 1726, 0, + 0, 0, 0, 0, 0, 0, 0, 1425, 1549, 1024, + 0, 0, 0, 0, 0, 0, 0, 2157, 3138, 853, + 0, 853, 0, 0, 0, 0, 0, 0, 1545, 0, + 0, 0, 853, 0, 2173, 2178, 2180, 0, 0, 0, + 0, 0, 0, 1543, 0, 0, 0, 0, 0, 1423, + -2062, -2062, -2062, 0, 1924, 1925, 1926, 1927, 1928, 1929, + 1546, 0, 0, 0, 0, -1794, 0, 0, 0, 0, + 0, 0, 0, 0, 853, 0, 556, 0, 1025, 0, + -2062, 0, 0, 2738, 2739, 2740, 1543, 0, 0, 0, + 1757, 556, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 556, 2243, 556, 2247, 0, 556, 0, 1217, 0, + 0, 0, 556, 0, 556, 0, 0, 0, 0, 0, + 0, 0, 0, 1545, 0, 0, 957, 556, 1218, 0, + 0, 957, 556, 0, 0, 0, 556, 556, 556, 556, + 2044, 556, 556, 0, 0, 0, 0, 2045, 2046, 0, + 1920, 2047, 2048, 2049, 0, 1546, 1426, 0, 2305, 3100, + 0, 0, 557, 0, 1550, -1794, 0, 853, 853, 853, + 853, 1319, 853, 0, 1219, 1921, 1922, 1923, 0, 1924, + 1925, 1926, 1927, 1928, 1929, 0, 2331, 0, 1543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1538, 0, 2554, 0, 0, 0, 0, 0, - 0, 1415, 1415, 0, 1538, 0, 0, 1415, 0, 0, - 0, 0, 1541, 0, 0, 0, 0, 0, 1540, 1872, - 0, 0, 0, 1470, 1909, 0, 0, 0, 0, 0, - 1540, 0, 0, 0, 1538, 0, 0, 0, 0, 0, - 0, 1538, 1636, 0, 0, -2046, -2046, -2046, 1537, 1640, - 1641, 1642, 1643, 1644, 1645, 0, 0, 0, 0, 0, - 1540, 0, 0, 0, 0, 0, 0, 1540, 0, 0, - 0, 3127, 0, 2049, 0, 0, 0, 0, 0, 1538, - 0, 0, 0, 1538, 2059, 1045, 0, 0, 1902, 1538, - 0, 0, 1903, 1904, 1910, 0, 1905, 1906, 1907, 0, - 0, 0, 0, 0, 1537, 1540, 0, 0, 0, 1540, - 0, 1538, 0, 0, 0, 1540, 0, 0, 0, 0, - 0, 0, 0, 951, 0, 0, 0, 0, 0, 0, - 1542, 0, 0, 0, 0, 0, 0, 1540, 0, 0, + 0, 1545, 2355, 0, 0, 2392, 2393, 2394, 2395, 2396, + 2397, 0, -1794, 2401, 2402, 2403, 2404, 2405, 2406, 2407, + 2408, 2409, 2410, 0, 2849, 0, 0, -1794, 0, 0, + 0, 0, -1794, 1546, 0, 1425, 1425, -1794, 0, 0, + 0, 1425, 0, 0, 0, 0, -1794, 0, 0, 0, + 0, -1794, 1423, 1423, 1423, 1423, 1423, 1423, 1550, 0, + 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1423, + 1220, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2878, 0, -1794, 0, 3283, 0, 2879, 0, 0, + 556, 0, 0, 1013, 0, 1548, 0, 0, 1014, 0, + 2880, 0, 853, -1794, 0, 0, 3290, 3291, 1545, 0, + 0, 806, 0, 0, 0, 2993, 0, 806, 0, 1221, + 0, 1549, 556, 0, 2881, 0, 2882, 556, 3190, 1222, + 0, 3304, 0, 0, 0, 0, 2466, 2466, 0, 1217, + 1546, 1223, 1545, 0, 0, 0, 0, 0, 0, 0, + 0, 1358, -1794, 557, 557, -1794, 0, 1015, 0, 1218, + 0, -1794, 1921, 1922, 1923, 0, 1924, 1925, 1926, 1927, + 1928, 1929, 0, 1224, 1546, 0, 0, 3029, 3030, 3031, + 3032, 0, 0, 0, 1426, 1426, 0, 0, 0, 0, + 1426, 0, 0, 2513, 2514, 0, 1550, 0, 0, 0, + 0, -1794, 0, 0, 0, 1219, 2899, 0, 556, 0, + 0, 0, 2504, 0, 2883, 0, 2900, 556, 0, 0, + 0, 1545, 0, 0, 2571, 0, -1794, 1226, 0, 1016, + 1548, 3257, 0, 0, 0, 0, 0, 0, 0, 0, + 1423, 1423, 0, 0, 0, 0, 0, 0, 0, 0, + 1543, 0, 1227, 1546, 0, 0, 1549, 2059, 0, 0, + 0, 0, 0, 0, 1545, 1017, 0, 0, 0, 557, + 0, 1229, 0, 0, 0, 2901, 0, 0, 0, 0, + 0, 1018, 2884, 0, 855, 0, 0, 2885, 1548, 0, + 806, 1019, 0, 0, 0, 0, 1546, 0, 0, 0, + 2953, 1220, 556, 0, 0, 0, 0, 806, 0, 0, + 0, 2173, -1794, 0, 1549, 0, 0, 0, 0, 0, + 0, 0, -1794, 0, 2196, 1020, 0, 0, 0, 0, + 3145, 0, 0, 0, 0, 0, 2886, 0, 0, 1550, + 0, -1794, 0, -1794, -1794, 0, 1974, 0, 0, 0, + 1221, 1550, 0, 0, 2887, 556, 0, 0, 1423, 0, + 1222, 556, 540, 3473, 0, 0, 1545, 0, 0, 0, + 0, 1021, 1223, 0, 2902, 0, 0, 1821, 1022, 0, + -1794, 1550, 0, -1794, -1794, -1794, 0, -1320, 1550, 0, + 0, 0, 0, 1548, 0, 0, 0, 0, 1546, 0, + 0, 0, 0, 0, 1224, 0, 0, 0, 0, 0, + 0, 0, 1443, 0, 0, 0, 0, 0, 0, 1549, + 1023, 0, 0, 2149, 1550, 541, 0, 3385, 1550, 0, + 0, 0, 0, 0, 1550, 1474, 2050, 2051, 2052, 1024, + 2053, 2054, 2055, 2056, 2057, 2058, 0, 0, 1821, 0, + 0, 0, 0, 0, 853, 2888, 0, 1550, 1226, 0, + 0, 0, 0, 0, 2889, 0, 1821, 853, 853, 853, + 0, 0, 0, 1426, 0, 0, 0, 0, 0, 542, + 556, 0, 853, 1227, 0, 853, 0, 0, 1548, 1319, + 0, 0, 0, 853, 0, 0, 0, 0, 543, 957, + 1601, 0, 1229, 0, 2903, 0, 0, 2904, 1025, 0, + 0, 0, 0, 1975, 1549, 0, 0, 0, 0, 1821, + 1821, 0, 1821, 0, 0, 0, 0, 1425, 1425, 1425, + 1425, 1425, 1425, 0, 0, 1425, 1425, 1425, 1425, 1425, + 1425, 1425, 1425, 1425, 1425, 0, 0, 0, 0, 0, + 0, 520, 0, 0, 0, 0, 0, 544, 0, 0, + 0, 0, 2953, 0, -208, 0, 1548, 0, 557, 557, + 1618, 2731, 721, 1619, 0, 0, 0, 1620, 1621, 853, + 853, 853, 0, 11, 0, 0, 0, 0, 556, 0, + 1423, 556, 1549, 0, 0, 0, 0, 556, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 545, 1629, 546, + 0, 14, 15, 0, 0, -2062, 1768, 853, 0, 0, + 2807, 2808, 0, 0, 0, 0, 547, 0, 1545, 722, + 3300, 2059, 548, 0, 0, 549, 0, 0, 0, 0, + 0, 0, 1631, 0, 0, 723, 0, 0, 0, 0, + 0, 3325, 0, 0, 0, 0, 0, 23, 0, 0, + 1546, 0, 0, 0, 0, 0, 0, 1423, 1423, 0, + 0, 0, 0, 1548, 0, 0, 1426, 1426, 1426, 1426, + 1426, 1426, 0, 0, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 724, 0, 2831, 0, 0, 1549, + 0, 0, 2173, 0, 725, 0, 0, 1548, 0, 0, + 0, 0, 0, 3364, 0, 1425, 1425, 726, 0, 0, + 853, 0, 727, 0, 556, 0, 0, 0, 556, 556, + 556, 0, 0, 1549, 1821, 1757, 1821, 0, 1859, -2062, + 0, 0, 0, 0, 3390, 557, 557, 1618, 557, 0, + 1619, 728, 0, 0, 1620, 1621, -2062, 556, 0, 2911, + 0, -2062, 0, 0, 0, 0, 0, 0, 0, 0, + 1550, 0, 556, 556, 556, 556, 556, 556, 556, 556, + 556, 556, 0, 0, 0, 1629, 1548, 0, 0, 0, + 0, 0, -2062, 0, 729, 0, 0, 0, 730, -2062, + 26, 27, 28, 0, 2331, 0, 0, 0, 0, 0, + 0, 853, 1549, 3020, 0, 0, 0, 0, 0, 1631, + 0, 1757, 0, 0, 0, 0, 0, 0, 0, 1548, + 0, 0, 0, 1425, 0, 0, 0, 0, 0, 1859, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1821, + 0, 557, 0, 0, 1640, 1549, 0, 0, 0, 0, + 1423, 0, 0, 0, 1426, 1426, 556, 33, 731, 0, + 0, 0, 0, 853, 853, 853, 853, 0, 35, 0, + 1985, 0, 1989, 732, 2525, 1423, 0, 0, 1423, 0, + 0, 0, 556, 957, 0, 0, 0, 0, 0, 0, + 37, 3065, 0, 0, 38, 1550, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -2062, 0, 733, 0, + 0, 734, 0, 0, 39, 0, 0, 0, 0, 3072, + 0, 1548, 735, -2062, -1809, 736, 0, 40, -2062, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, + 0, 0, 0, 737, 0, 0, -2062, 1549, 0, 3095, + 0, 806, 0, 1550, 44, 0, 0, 738, 0, 0, + 0, 0, 0, 3139, 740, 3107, -2062, 0, 0, 2173, + 0, 0, 1426, 0, 741, 2059, 0, 0, 45, 0, + 742, 0, 0, 0, 0, 0, 0, 0, 0, 1757, + 0, 0, 46, 0, 0, 1821, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 743, 957, 556, + 1423, 0, 0, 0, 0, 0, 853, 0, 0, 0, + 0, 1640, 0, 0, -1809, 0, 0, 0, 0, 0, + 0, 0, 0, 3158, 0, 0, 1618, 0, 0, 1619, + 0, 0, 0, 1620, 1621, 0, 0, 0, 0, 0, + 0, 0, 0, -2062, 0, 0, 0, 0, 1550, 0, + 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, 0, 0, + 0, -1809, 0, 0, 1629, 0, 0, 0, 0, 0, + 0, -2062, 0, 0, 0, 0, -1809, 0, 0, 0, + 0, -1809, 0, 0, 0, 0, -1809, 0, 0, 0, + 0, 0, 0, 3213, 0, -1809, 0, 0, 1631, 0, + -1809, 3175, 0, 0, 1821, 0, 0, 0, 0, 0, + 0, 0, 0, -2062, 0, 0, 0, 2331, 0, 0, + 0, 0, 1425, 1425, 557, 0, 0, 0, 0, 0, + 0, 0, -1809, 3209, 0, 0, 0, 0, 0, 557, + 1423, 0, 0, 1550, 0, 0, 0, 0, 0, 557, + 0, 557, -1809, 0, 557, 0, 0, 0, 0, 0, + 557, 0, 557, 2806, 0, 0, 3226, 0, 0, 0, + 0, 0, 556, 1548, 0, 557, 0, 0, 0, 556, + 557, 0, 0, 0, 557, 557, 557, 557, 0, 557, + 557, 0, 0, 0, 0, -2062, 0, 0, 0, 1549, + 0, -1809, 0, 0, -1809, 0, 0, 0, 0, 0, + -1809, 1618, -2062, 3254, 1619, 0, 0, -2062, 1620, 1621, + -2062, 1550, -2062, -2062, -2062, 0, 0, 1647, 1648, 1649, + 1650, 1651, 1652, 0, 0, 556, 0, 0, 0, 0, + 556, 0, 0, 0, 0, 0, 0, 0, 0, 1629, + -1809, 0, 0, 0, 0, -2062, 1630, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 556, 0, 0, 0, + 0, 1426, 1426, 0, 0, -1809, 0, 0, 0, 0, + 0, 0, 0, 1631, 0, 0, 0, 556, 556, 0, + 0, 1618, 0, 0, 1619, 0, 0, 0, 1620, 1621, + 0, 0, 0, 0, 0, 0, 853, 0, 1757, 0, + 1640, 0, 556, 0, 0, 1425, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 853, 1550, 1629, + 3327, 0, 0, 855, 0, 0, -2062, 0, 557, 0, + 3050, 0, 0, 1111, 1111, 0, 0, 0, 0, 0, + 1423, 0, 0, 0, 556, 1006, 0, 1006, 0, 0, + 0, -1809, 1550, 1631, 0, 0, 0, 0, 0, 0, + 2453, -1809, 0, 0, 0, 1989, 0, 0, 0, 0, + 1632, 0, 3107, 0, 0, 3074, 0, 0, 0, 853, + -1809, 0, -1809, -1809, 0, 0, 0, 1633, 0, 0, + 0, 0, 1634, 1372, 0, 819, 0, 0, 0, 0, + 0, 0, -2062, 1246, 0, 0, 0, 1290, 1295, 0, + 853, 0, 0, 0, 0, 0, 0, 0, 2809, -1809, + 0, 0, -1809, -1809, -1809, 0, 0, 0, 0, 0, + 1637, 1550, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 557, 0, 0, 3226, + -2062, 0, 0, 0, 1426, 1601, 0, 0, 1373, 1374, + 1345, 0, 0, 0, 0, 1425, 0, -2062, 0, 0, + 0, 3327, -2062, 0, 1550, 0, 0, 0, 1369, 1426, + 0, 0, 0, 0, 1417, 1640, 0, 1419, 0, 0, + 1430, 1433, 1438, 1441, 0, 0, 0, 0, 1757, 1375, + 1376, 0, 0, 1377, 1378, 0, 0, 0, 0, -2062, + -2062, 957, 957, 0, 3327, 957, 1647, 1648, 1649, 1650, + 1651, 1652, 0, 1955, 0, 0, 0, 0, 0, 0, + 1478, 1290, 0, 0, 556, 0, 0, 0, 0, 0, + 557, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1562, 0, 0, 0, 0, 1757, 0, 0, 0, + 0, 0, 0, 3327, 0, 1640, 0, 0, 0, 0, + 1578, 0, 0, 0, 0, 0, 1550, 0, 0, 1379, + 1380, 1588, 1589, 1590, 0, 1595, 1599, 1642, 0, 0, + 0, 0, 0, 557, 0, 0, 0, 0, 0, 2588, + 957, 0, 0, 0, 0, 1425, 0, 0, 0, 0, + 0, 0, 0, 0, 1426, 2173, 0, 0, 0, 1661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1478, 1478, 0, 0, + 0, 0, 0, 1381, 1382, 1383, 1384, 1385, 1386, 1387, + 1388, 0, 0, 1389, 1390, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -2062, 0, 0, + 0, 0, 0, 0, 1704, 0, 0, 0, 1720, 1725, + 0, 0, 0, 0, 0, 0, 0, 0, 1618, 1111, + 1111, 1619, 0, 0, 1643, 1620, 1621, -2062, -2062, -2062, + 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 557, 0, + 0, 0, 0, 0, 0, 0, 1629, 1391, 1392, 0, + 0, 0, 0, -2062, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1290, 0, 0, + 0, 0, 0, 0, 1426, 0, 1290, 0, 0, 0, + 1631, 0, 0, 0, 0, 0, 0, -46, 1393, 1394, + 0, 0, 0, 0, -2062, 0, 0, 0, 0, 0, + 1290, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 3344, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 2810, 557, 0, 7, 557, + 0, 0, 0, 0, 0, 1985, 0, 0, 1550, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 0, 10, 0, 0, 0, -2062, 0, 0, + 0, 0, 0, 1395, 1396, 11, 1902, 12, 0, 0, + 0, 0, 0, 0, -2062, 0, 0, 0, 13, -2062, + 0, 0, 0, 0, 0, 0, 0, 1397, 1398, 0, + 0, 0, 0, 14, 15, 16, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 0, -2062, 19, 0, + 20, 21, 0, 0, 0, 0, 0, 0, 0, 1438, + 0, 1438, 1438, 0, 0, 22, 0, 0, 0, 23, + 0, 0, 0, 0, 1111, 1111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2181, 0, 553, - 2146, 0, 850, 0, 850, 0, 0, 0, 2377, 2378, - 2379, 2380, 2381, 2382, 850, 2162, 2386, 2387, 2388, 2389, - 2390, 2391, 2392, 2393, 2394, 2395, 0, 1412, 0, 0, - 0, 0, 0, 0, 2040, 2041, 2042, 1537, 2043, 2044, - 2045, 2046, 2047, 2048, 0, 0, 0, 0, 1542, 0, - 0, 0, 850, 0, 552, 0, 0, 0, 0, 0, - 0, 0, 0, 1541, 0, 0, 0, 0, 0, 1746, - 552, 0, 0, 0, 2138, 0, 0, 0, 0, 0, - 552, 2228, 552, 2232, 0, 552, 0, 0, 0, 0, - 0, 552, 0, 552, 0, 0, 1860, 0, 0, 0, - 0, 1045, 0, 0, 1902, 951, 552, 0, 1903, 1904, - 951, 552, 1905, 1906, 1907, 552, 552, 552, 552, 1415, - 552, 552, 0, 0, 0, 0, 0, 0, 1909, 0, - 0, 0, 1537, 0, 1911, 1912, 1913, 2290, 1914, 1915, - 1916, 1917, 1918, 1919, 0, 1300, 0, 850, 850, 850, - 850, 850, 0, 0, 0, 0, 1541, 0, 2145, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2319, 0, + 1111, 0, 557, 0, 1426, 24, 557, 557, 557, 0, + 0, 0, 1640, 0, 0, 0, 0, 0, 0, 0, + 0, -1428, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 557, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, + 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2340, 0, 0, 0, 0, 0, 0, 0, 0, - 553, 553, 0, 0, 0, 2498, 2499, 0, 1910, 0, - 0, 3282, 1414, 1414, 1414, 1414, 1414, 1414, 0, 1537, - 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, 1414, - 0, 0, 3307, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1412, 1412, 1412, 1412, 1412, 1412, 0, 0, - 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, 1412, - 0, 1538, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1542, - 552, 0, 0, 2673, 0, 0, 0, 1540, 0, 0, - 0, 0, 850, 0, 3346, 0, 2271, 0, 0, 0, - 1541, 0, 802, 0, 0, 0, 0, 0, 802, 2286, - 2286, 0, 0, 0, 552, 0, 0, 553, 0, 552, - 0, 0, 0, 0, -2046, 3372, 1537, 0, 2453, 2453, - 0, 717, 0, 0, 1415, 1415, 1415, 1415, 1415, 1415, - 0, 0, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, - 1415, 1415, 0, 0, 0, 0, 0, 0, 0, 0, - 1537, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1542, 0, 0, 0, 1347, 0, 0, 0, - 0, 0, 2362, 0, 0, 0, 0, 0, 718, 0, - 0, 0, 0, 0, 1910, 1538, 0, 552, 0, 1414, - 1414, 2489, 0, 0, 719, 0, 552, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1911, 1912, - 1913, 1540, 1914, 1915, 1916, 1917, 1918, 1919, 0, 1412, - 1412, 0, 0, 0, 0, 0, 0, 0, 0, 1537, - 0, 0, 0, 0, 1541, 0, 2049, 0, 0, 0, - 0, 1538, 0, 720, 0, 0, 1541, 0, 1432, 0, - 0, 0, 0, 721, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 722, 0, 1540, 0, 802, - 723, 1465, 1537, 0, 0, 0, 1541, 0, 0, 0, - 0, 552, 0, 1541, 0, 0, 802, 0, 0, 0, - 2162, 0, 0, 0, 0, 0, 1542, 0, 0, 724, - 0, 0, 0, 1414, 0, 0, 0, 0, 0, 0, - 0, 1415, 1415, 0, 0, 0, 0, 2839, 2840, 0, - 0, 1541, 0, 0, 0, 1541, 0, 1008, 0, 0, - 552, 1541, 1009, 1412, 0, 0, 552, 1594, 0, 0, - 0, 0, 725, 0, 1538, 2892, 726, 0, 0, 0, - 0, 0, 1810, 1541, 0, 0, 0, 0, 0, 0, - 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, - 1540, 0, 0, 0, 1537, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1618, 0, 0, 1619, 0, + 0, 0, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1010, 0, 0, 1911, 1912, 1913, 0, 1914, 1915, - 1916, 1917, 1918, 1919, 553, 553, 0, 0, 0, 0, - 539, 0, 0, 0, 0, 0, 727, 0, 2789, 2790, - 0, 0, 0, 1810, 0, 1415, 0, 0, 0, 0, - 850, 728, 14, 15, 0, 0, 0, 0, 0, 1538, - 1542, 1300, 0, 0, 1810, 850, 850, 850, 0, 0, - 0, 0, 1542, 0, 0, 0, 0, 0, 552, 0, - 850, 0, 1011, 850, 729, 1540, 0, 730, 850, 0, - 1184, 0, 0, 0, 951, 0, 0, 23, 731, 0, - 0, 732, 1542, 0, 0, 0, 0, 0, 0, 1542, - 0, 0, 0, 0, 1810, 1810, 0, 1810, 1012, 733, + 0, 2034, 0, 1627, 0, 0, 0, 0, 0, 2037, + 0, 0, 0, 1629, -2062, 0, 0, 0, 0, 0, + 1630, 0, 26, 27, 28, 0, 0, 0, 0, 0, + 29, 0, 0, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1985, 0, 0, 1631, 0, 2084, + 0, 0, 0, 0, 0, 2088, 2089, 2090, 2091, 2092, + 2093, 2094, 2095, 0, 31, 0, 0, 2104, 2105, 0, + 2453, 0, 2116, 32, 0, 0, 2119, 0, 0, 2127, + 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 0, 33, + 2136, 0, 0, 0, 0, 0, 34, 1111, 0, 1290, + 35, 0, 0, 0, 0, 0, 0, 0, 0, 1618, + 36, 0, 1619, 0, 0, 0, 1620, 1621, 2162, 0, + 0, -2062, 37, 0, 0, 0, 38, 0, 1647, 1648, + 1649, 1650, 1651, 1652, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1632, 0, 39, 1629, 0, 0, + 0, 0, 0, 0, -2062, 0, 1589, 1590, 0, 40, + 0, 1633, 41, 0, 0, 42, 1634, 0, 0, 0, + 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1631, 0, 0, 0, 0, 44, 0, 1204, 1635, + 1636, 0, 0, 0, 1205, 0, 0, 557, 0, 0, + 0, 0, 1217, 0, 1637, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1218, 0, 46, 0, 0, -46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 734, 1013, 0, 1538, 0, 0, 735, - 736, 0, 0, 0, 1014, 0, 516, 1542, 0, 0, - 737, 1542, 0, 2610, 0, 0, 738, 1542, 0, 0, - 0, 0, 1540, 0, 0, 0, 2714, 0, 0, 0, - 0, 0, 0, 0, 850, 850, 850, 0, 1015, 1542, - 0, 0, 0, 739, 552, 0, 1412, 0, 552, 0, - 0, 0, 0, 0, 552, 0, 0, 553, 553, 1185, - 553, 0, 0, 0, 0, 2642, 0, 0, 0, 0, + 0, 0, 1638, 2288, 0, 1639, 3085, 1290, 0, 0, + 2298, 2299, 0, 0, 0, 0, 0, 0, 0, 1640, + 0, 0, 1641, 0, 0, 0, 0, 0, 1219, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -2062, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1290, 0, + 0, 0, 0, 0, 0, -2062, 0, 0, 0, 1206, + -2062, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1345, 2363, 0, 1618, 0, 0, 1619, 0, 0, 0, + 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -2062, 2387, + 2388, 1627, 2389, 0, 0, 0, 0, 0, 0, 1204, + 0, 1629, 0, 0, 0, 1205, 0, 0, 1630, 0, + 0, 1642, 0, 1217, 1220, 0, 0, 0, 0, 0, + 3234, 2415, 2416, 0, 0, 2162, 0, 2453, 0, 0, + 0, 0, 0, 1218, 0, 1631, 0, 0, 0, 0, + 0, 0, 0, 1640, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2443, 0, 0, 0, 0, 2448, + 0, 0, 0, 1221, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1222, 0, 0, 1478, 0, 1290, 1219, + 0, 0, 0, 557, 0, 1223, 0, 0, 557, 0, + 0, 0, 0, 1427, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1207, 0, 0, 0, + 1206, 0, 0, 0, 557, 0, 2482, 1224, 1643, 0, + 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, 1650, 1651, + 1652, 0, 1632, 0, 0, 557, 557, 0, 0, 0, + 0, 0, 0, 0, 2489, -2062, 0, 0, 0, 1633, + 0, 0, 0, 2499, 1634, 0, 2502, 0, 0, 0, + 557, 2505, 2506, 0, 0, 1225, 0, 0, 0, 1209, + 0, 1226, 0, 0, 0, 1220, 0, 1635, 1636, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2656, 1016, 0, 3120, 2049, 0, 3002, - 0, 1017, 1414, 1414, 0, 0, 0, 0, 0, 0, - 27, 28, 29, 1538, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1537, 0, 0, 0, - 0, 0, 1412, 1412, 0, 1347, 0, 0, 0, 1540, - 0, 1018, 0, 0, 2691, 0, 2692, 1538, 0, 0, - 2697, 0, 2700, 1541, 0, 0, 0, 0, 0, 0, - 1019, 2813, 0, 0, 0, 0, 0, 2162, 0, 0, - 0, 553, 0, 1540, 0, 34, 0, 0, 0, 0, - 0, 0, 0, 850, 0, 0, 36, 552, 0, 0, - 0, 552, 552, 552, 0, 0, 0, 1810, 1746, 1810, - 0, 1848, 1977, 0, 1981, 0, 0, 0, 38, 0, - 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, - 552, -1778, 2893, 0, 1415, 1415, 1538, 0, 0, 1020, - 0, 0, 0, 0, 1186, 552, 552, 552, 552, 552, - 552, 552, 552, 552, 552, 41, 0, 0, 0, 0, - 0, 0, 1540, 0, 0, 0, 44, 0, 3121, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2319, 1538, - 0, 0, 45, 0, 850, 1611, 0, 0, 1612, 0, - 0, 0, 1613, 1614, 0, 0, 1746, 1541, 0, 0, - 0, 0, 0, 1414, 0, 1540, 46, 0, 0, 0, - 0, 0, 1848, 0, 0, 0, 0, 0, 0, 0, - 47, 0, 1810, 1622, 0, 0, 0, 0, 3032, 0, - -2046, -1778, 0, 1412, 0, 0, 0, 0, 0, 552, - 0, 0, 0, 0, 0, 0, 850, 850, 850, 850, - 0, 0, 0, 1541, 0, 0, 0, 1624, 1412, 0, - 0, 1412, 0, 0, 0, 552, 951, 0, 0, 1542, - 0, 0, 3056, 3265, 3047, 0, 0, 0, -1778, 0, - 0, 1538, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1778, 0, 3272, 3273, 0, -1778, 0, 0, - 0, 3054, -1778, 0, 0, 2934, 0, 1540, 3195, 0, - 0, -1778, 0, 0, 0, 0, -1778, 0, 0, 0, - 3287, 0, 2788, 0, 0, 1415, 0, 0, 0, 0, - 0, 3077, 0, 802, 0, 0, 0, 0, 2642, 0, - 0, 0, 0, 0, 0, 0, 0, 3089, -1778, 0, - 1415, 2162, 0, -2046, 0, 0, 1541, 2049, 0, 0, - 0, 0, 1414, 0, 0, 0, 1197, 0, -1778, 0, - -2046, 1746, 1198, 553, 0, -2046, 0, 1810, 0, 0, - 1210, 0, 0, 0, 0, 0, 0, 0, 0, 553, - 951, 552, 1412, 0, 0, 0, 0, 0, 850, 553, - 1211, 553, 0, 1542, 553, 0, 0, 0, 0, 0, - 553, 0, 553, -2046, 0, 3140, 0, -1778, 0, 0, - -1778, 0, 0, 0, 0, 553, -1778, 0, 0, 0, - 553, 0, 0, 0, 553, 553, 553, 553, 0, 553, - 553, 0, 0, 0, 0, 0, 1212, 0, 0, 0, - 0, 1541, 0, 0, 0, 0, 0, 0, 0, 1542, - 0, 0, 0, 0, 0, 0, -1778, 0, 1633, 0, - 0, 0, 0, 0, 0, 0, 0, 1199, 0, 0, - 0, 0, 0, 0, 1415, 0, 0, 0, 0, -1778, - 0, 0, 0, 3157, 0, 0, 0, 1810, 0, 0, - 0, 3082, 1414, 0, 0, 0, 0, 1107, 1107, 0, - 0, 2319, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3191, 0, 0, 1541, 0, - 0, 0, 1412, 0, 0, 0, 0, 0, 0, 0, - 0, 1213, 0, 1538, 0, 0, 0, 852, 11, 0, - 0, 3455, 0, 0, 0, 0, 0, 0, 3208, 0, - 0, 0, 1542, 0, 552, 0, 0, 0, -2046, 1540, - 0, 552, 0, 0, 1237, -1778, 14, 15, 1279, 1286, - 0, 0, 0, 0, 0, -1778, 0, 0, 0, 553, - 1214, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1215, 0, 0, 0, -1778, 3236, -1778, -1778, 0, 0, - 0, 0, 1216, 0, 0, 0, -1793, 0, 0, 0, - 0, 23, 0, 2440, 1415, 0, 0, 552, 1981, 0, - 0, 1336, 552, 1200, 0, 1541, 0, 0, 0, 0, - 0, 0, 0, -1778, 1217, 0, -1778, -1778, -1778, 0, - 1361, 0, 0, 0, 0, 0, 1406, 1542, 552, 1408, - 0, 0, 1419, 1422, 1427, 1430, 0, 0, 0, 1541, - 3172, 0, 0, 0, 0, -2046, 0, 0, 0, 552, - 552, 0, 1640, 1641, 1642, 1643, 1644, 1645, 0, 0, - 1218, 0, 0, 1347, 1202, 0, 1219, 0, 850, 0, - 1746, 0, 0, 1472, 1279, 552, 553, 0, 0, 0, - 0, 0, 3326, 0, 0, 1594, -1793, 0, 0, 850, - 0, 1220, 3309, 0, 1556, 0, 1221, 0, 0, 0, - 0, 0, 0, 0, 1542, 0, 0, 0, 0, 0, - 1222, 0, 1412, 1572, 1365, 1366, 552, 1001, 1541, 1001, - 0, 0, 0, 0, 1582, 1583, 1584, 0, 1588, 1592, - 0, 0, 0, -1793, 27, 28, 29, 0, 0, 0, - 1364, 0, 815, 3239, 3089, 0, 0, -1793, 0, 0, - 0, 850, -1793, 0, 0, 1367, 1368, -1793, 0, 1369, - 1370, 1541, 1654, 0, 0, 0, -1793, 1204, 0, 0, - 553, -1793, 0, 0, 0, 0, 0, 0, 0, 1472, - 1472, 0, 850, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, - 0, 0, 0, -1793, 1415, 1365, 1366, 0, 0, 0, - 36, 1542, 2934, 1692, 0, 0, 0, 1708, 1713, 553, - 0, 3208, 0, -1793, 0, 2571, 0, 0, 1107, 1107, - 0, 0, 38, 0, 1371, 1372, 39, 0, 0, 0, - 0, 0, 0, 3309, 0, 1542, 1367, 1368, 0, 0, - 1369, 1370, 0, 0, 0, 0, 40, 0, 0, 0, - 0, 0, 0, 1541, 0, 0, 0, 0, 0, 41, - 1746, 0, -1793, 0, 0, -1793, 0, 0, 0, 0, - 44, -1793, 0, 951, 951, 1279, 3309, 951, 0, 0, - 0, 0, 0, 0, 1279, 1945, 45, 0, 1373, 1374, - 1375, 1376, 1377, 1378, 1379, 1380, 552, 0, 1381, 1382, - 0, 0, 0, 0, 0, 0, 0, 0, 1279, 0, - 46, -1793, 0, 0, 1542, 1371, 1372, 0, 1746, 0, - 0, 0, 0, 0, 47, 3309, 0, 0, 0, 3367, - 0, 0, 0, 0, -1793, 0, 0, 553, 0, 0, + 0, 0, 1637, 0, 0, 0, 1227, 0, 0, 0, + 0, 1228, 557, 0, 0, 2527, 0, 0, 2530, 0, + 2532, 1655, 0, 0, 0, 1229, 0, 0, 0, 0, + 0, 0, 0, 0, 1221, 0, 2536, 0, 0, 0, + 1638, 0, 0, 1639, 1222, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1223, 1640, 0, 0, + 1641, 0, -2062, 0, 0, 0, 0, 1655, 0, 1647, + 1648, 1649, 1650, 1651, 1652, 0, 0, 1207, 0, 0, + 1704, 0, 1211, 0, 0, 0, 0, 0, 1224, 0, + 0, 0, 0, 0, 1617, 0, 0, 1725, 2134, 1618, + 0, 0, 1619, 1427, 0, 0, 1620, 1621, 1622, 1623, + 1624, 1625, 1626, 0, 0, 0, 1111, 0, 0, 0, + 0, 0, 0, 0, 0, 2592, 0, 1627, 0, 0, + 0, 1628, 0, 0, 0, 0, 2263, 1629, 0, 0, + 1209, 0, 1226, 0, 1630, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1655, 0, 0, 1642, + 0, 0, 0, 0, 0, 0, 0, 1227, 0, 0, + 0, 1631, 2264, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1590, 0, 0, 0, 1229, 0, 1290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1542, 0, 0, - 0, 0, 951, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2162, 0, 1373, - 1374, 1375, 1376, 1377, 1378, 1379, 1380, 0, 0, 1381, - 1382, 0, 852, 0, 0, 1892, 0, 0, 0, 0, + 1655, 0, 557, 0, 0, 1655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1383, 1384, 0, 0, 0, 0, 0, 0, 0, - -1793, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1793, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 553, 0, 0, 0, 553, 0, -1793, - 0, -1793, -1793, 1977, 0, 1427, 0, 1427, 1427, 1542, - 0, 0, 0, 0, 2934, 0, 0, 0, 0, 0, - 1107, 1107, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1107, -1793, 0, - 0, -1793, -1793, -1793, 0, 0, 0, 0, 0, 0, - 0, 0, 1383, 1384, 0, 0, 1385, 1386, 0, 0, - 0, 1611, 0, 0, 1612, 1541, 0, 0, 1613, 1614, - 1615, 1616, 1617, 1618, 1619, 0, 0, 0, 0, 0, - 1387, 1388, 0, 0, 0, 0, 0, 0, 0, 1620, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1622, - 1994, 0, 0, 0, 0, 0, 1623, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 553, 0, 0, 0, - 553, 553, 553, 1624, 0, 0, 0, 0, 0, 0, - 0, 0, 2024, 0, 0, 0, 0, 1385, 1386, 0, - 2027, 0, 0, 0, 0, 0, 0, 0, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1387, 1388, 0, 553, 553, 553, 553, 553, 553, - 553, 553, 553, 553, 0, 0, 0, 0, 0, 2073, - 0, 0, 0, 0, 0, 2077, 2078, 2079, 2080, 2081, - 2082, 2083, 2084, 0, 0, 0, 0, 2093, 2094, 0, - 0, 0, 2105, 0, 0, 0, 2108, 0, 0, 2116, - 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 0, 1625, - 2125, 0, 0, 0, 0, 0, 0, 1107, 0, 1279, - 0, 0, 0, 0, 0, 0, 1626, 0, 0, 0, - 0, 1627, 0, 0, 0, 0, 0, 0, 2151, 0, - 0, 0, 0, 0, 0, -45, 0, 0, 1977, 0, - 0, 1542, 0, 0, 1628, 1629, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 1630, - 0, 1583, 1584, 0, 2440, 0, 0, 2, 0, 3, - 4, 1611, 0, 0, 1612, 0, 0, 0, 1613, 1614, - 0, 0, 5, 0, 0, 0, 0, 6, 0, 0, - 0, 0, 0, 0, 0, 0, 7, 1631, 0, 0, - 1632, 0, 0, 0, 0, 0, 0, 0, 0, 1622, - 8, 0, 0, 0, 1633, 0, -2046, 1634, 0, 9, - 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 11, 0, 12, 0, 0, 0, 0, - 0, 0, 0, 1624, 0, 0, 13, 0, 0, 2273, - 0, 0, 0, 1279, 0, 0, 2283, 2284, 0, 0, - 0, 14, 15, 16, 0, 0, 0, 0, 0, 0, - 0, 0, 17, 0, 0, 0, 0, 0, 18, 0, - 0, 0, 0, 0, 0, 0, 19, 0, 20, 21, - 553, 0, 0, 0, 0, 0, 0, 1279, 0, 0, - 0, 0, 22, 0, 0, 0, 23, 0, 2791, 0, - 0, 0, 0, 0, 1635, 0, 1336, 2348, 0, 0, + 0, 0, 0, 1211, 2697, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1655, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1643, 0, 1632, 1644, + 1645, 1646, 0, 1647, 1648, 1649, 1650, 1651, 1652, 1655, + 0, 0, 0, 0, 0, 1633, 1905, 0, 1618, 0, + 1634, 1619, 0, 0, 0, 1620, 1621, 1622, 1623, 1624, + 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1635, 1636, 0, 1627, 0, 0, 0, + 2790, 0, 0, 0, 0, 0, 1629, 1655, 1637, 1655, + 0, 1427, 1427, 1630, 1930, 0, 0, 1427, 0, 0, + 1655, 0, 0, 1655, 0, 0, 0, 0, 1655, 0, + 0, 1655, 0, 0, 0, 0, 0, 0, 0, 0, + 1631, 0, 0, 0, 0, 0, 1638, 0, 0, 1639, + 0, 0, 0, 0, 0, 0, 0, 0, 2777, 0, + 0, 0, 0, 1640, 2779, 2037, 1641, 0, 1655, 0, + 0, 0, 1618, 0, 0, 1619, 2786, 0, 0, 1620, + 1621, 0, 0, 1624, 1625, 1626, 0, 2795, 0, 0, + 2798, 0, 2800, 0, 0, 0, 0, 0, 0, 0, + 2804, 0, 0, 0, 0, 0, 0, 0, 2811, 2812, + 1629, 0, 0, 0, 0, 2819, 0, 1630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 24, 0, 0, 0, 0, 0, 0, -2046, - 0, 0, 0, 0, 0, 0, 2372, 2373, 25, 2374, - 0, 0, 0, 0, 0, 1611, -2046, 0, 1612, 0, - 0, -2046, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, - 0, 0, 0, 0, 26, 0, 0, 0, 2400, 2401, - 0, 0, 2151, 1620, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1622, 0, 0, 0, 0, 0, -2046, - 1623, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2428, 0, 0, 0, 0, 0, 2434, 0, 0, - 0, 1636, 0, 0, 1637, 1638, 1639, 1624, 1640, 1641, - 1642, 1643, 1644, 1645, 0, 1472, 0, 1279, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2475, 0, 27, - 28, 29, 0, 0, 1633, 0, 0, 30, 0, 0, - 31, 0, 0, 3216, 0, 0, 1416, 0, 0, 0, - 2440, 0, 0, 2468, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, + 2828, 0, 0, 0, 0, 0, 0, 1632, 0, 0, + 2843, 0, 0, 0, 1631, 0, 0, 0, 0, 0, + 0, 0, 1655, 0, 1633, 0, 0, 0, 0, 1634, + 0, 0, 1111, 0, 0, 1642, 0, 0, 1655, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1655, 1655, + 1655, 0, 1635, 1636, 0, 1655, 0, 0, 0, 1655, + 0, 0, 0, 0, 0, 0, 0, 1637, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2487, 0, 34, 717, 0, 2490, 2491, 0, - 0, 35, 0, 1625, 0, 36, 553, 0, 0, 0, - 0, 553, 0, 0, 0, 37, 0, 0, 0, 0, - 1626, 0, 0, 0, 0, 1627, 0, 38, 0, 0, - 0, 39, 0, 0, -2046, 0, 0, 553, 0, 0, - 0, 2512, 0, 0, 2515, 0, 2517, 0, 1628, 1629, - 0, 40, 718, 0, 0, 0, 0, 0, 553, 553, - 0, 0, 2521, 1630, 41, 1648, 0, 42, 719, 0, - 43, 0, 0, 0, 0, 44, 0, 0, 0, 0, - 0, 0, 0, 0, 553, 0, 0, 0, 0, 0, - 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1631, 1692, 0, 1632, 0, 0, 0, 0, 0, - 1648, 0, 0, 0, 0, 46, 0, 720, 1633, 1713, - 2123, 1634, 0, 0, 0, 553, 0, 721, 0, 47, - 0, 0, -45, 0, 0, 0, 0, 0, 1107, 722, - 0, -2046, 0, 1416, 723, 0, 0, 2575, 1640, 1641, - 1642, 1643, 1644, 1645, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2288, + 0, 2288, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1638, 0, 0, 1639, 0, + 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1655, 1640, 0, 0, 1641, 0, 0, 1633, 0, + 0, 0, 0, 1634, 0, 0, 0, 0, 0, 0, + 0, 0, 1643, 0, 0, 1644, 1645, 1646, 0, 1647, + 1648, 1649, 1650, 1651, 1652, 0, 1635, 1636, 0, 0, + 0, 0, 0, 0, 1655, 0, 0, 0, 0, 0, + 0, 1637, 0, 0, 0, 0, 0, 0, 0, 0, + 1655, 0, 0, 0, 0, 1655, 3045, 3046, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 724, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1611, 0, 0, 1612, 0, - 0, 0, 1613, 1614, 0, 1648, 1617, 1618, 1619, 0, - 0, 0, 0, 0, 1584, 0, 0, 0, 0, 0, - 1279, 0, 0, 0, 0, 0, 725, 0, 1635, 0, - 726, 0, 0, 1622, 0, 0, 0, 0, 0, 0, - 1623, 0, 0, 0, 0, 0, 0, 1648, 0, 0, - 0, 0, 0, 0, 1648, 0, 1610, 0, 0, 0, - 0, 1611, 0, 0, 1612, 0, 0, 1624, 1613, 1614, - 1615, 1616, 1617, 1618, 1619, 0, 0, 0, 0, 2682, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1620, - 0, 0, 0, 1621, 0, 0, 0, 0, 0, 1622, - 727, 0, 0, 0, 1648, 0, 1623, 0, 0, 0, - 0, 0, 0, 0, 0, 728, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 553, 0, 0, 0, 1648, - 0, 0, 0, 1624, 0, 1636, 0, 0, 1637, 1638, - 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, 729, 0, - 0, 730, 0, 0, 0, 1895, 0, 0, 0, 0, - 0, 0, 731, 1625, 0, 732, 0, 0, 0, 0, - 0, 0, 0, 0, 1648, 0, 1648, 0, 1416, 1416, - 1626, 1920, 0, 733, 1416, 1627, 0, 1648, 0, 0, - 1648, 0, 0, 0, 0, 1648, 0, 734, 1648, 0, - 0, 0, 0, 0, 736, 0, 0, 0, -2046, -2046, - 0, 2760, 0, 0, 737, 0, 0, 2762, 2027, 0, - 738, 0, 0, 1630, 0, 0, 0, 0, 2768, 1625, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2777, - 1648, 0, 2780, 0, 2782, 0, 1626, 739, 0, 0, - 0, 1627, 2786, 0, 0, 0, 0, 0, 0, 0, - 2793, 2794, 0, 0, -2046, 0, 0, 2801, 0, 0, - 0, 0, 0, 0, 1628, 1629, 0, 0, 1633, 0, - 0, 0, 2810, 0, 0, 0, 0, 0, 0, 1630, - 0, 0, 2825, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1930, 0, 0, 0, 0, 0, 0, 1638, + 0, 0, 1639, 0, 0, 0, 0, 0, 0, 0, + 0, 3069, 0, 0, 1642, 0, 1640, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3073, 0, 0, 0, + 0, 3075, 3076, 0, 0, 0, 3077, 0, 0, 0, + 0, 3080, 0, 0, 3083, 3084, 0, 0, 0, 2288, + 1290, 0, 0, 3092, 0, 0, 0, 0, 0, 0, + 0, 0, 1618, 0, 1111, 1619, 0, 0, 0, 1620, + 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1107, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1648, 0, 0, 1631, 0, 0, - 1632, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1648, 0, 0, 0, 1633, 0, 0, 1634, 0, 0, - 1648, 1648, 1648, 0, 0, 0, 1648, 0, 0, 0, - 1648, 0, 0, 0, 0, 0, 0, 0, 0, 2273, - 0, 2273, 0, 0, 0, 0, 0, 0, 1635, 0, - 1611, 0, 0, 1612, 0, 0, 0, 1613, 1614, 0, + 1627, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1629, 0, 0, 0, 0, 0, 0, 1630, 3133, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1642, 0, + 0, 1643, 0, 0, 1644, 1645, 1646, 0, 1647, 1648, + 1649, 1650, 1651, 1652, 1631, 3152, 0, 0, 2075, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1611, 0, - 0, 1612, 0, 0, 0, 1613, 1614, 0, 1622, 0, - 0, 0, 1648, 0, 0, -2046, 0, 1611, 0, 0, - 1612, 0, 0, 0, 1613, 1614, 1615, 1616, 1617, 1618, - 1619, 0, 0, 0, 1635, 0, 1622, 0, 0, 0, - 0, 0, 1624, -2046, 0, 1620, 0, 0, 0, 2772, - 1648, 0, 0, 0, 0, 1622, 3027, 3028, 0, 0, - 0, 0, 1623, 0, 0, 0, 1648, 0, 0, 0, - 1624, 1648, 0, 0, 0, 1636, 0, 0, 1637, 1638, - 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, 1920, 1624, - 0, 3051, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3055, 0, 2792, 0, 0, - 3057, 3058, 0, 0, 0, 3059, 0, 0, 0, 0, - 3062, 0, 0, 3065, 3066, 0, 0, 0, 2273, 1279, - 0, 0, 3074, 0, 0, 3067, 0, 0, -2046, 0, - 0, 1636, 0, 1107, 1637, 1638, 1639, 0, 1640, 1641, - 1642, 1643, 1644, 1645, 0, -2046, 0, 0, 0, 0, - -2046, 0, 0, 0, 0, 0, -2046, 0, 0, 0, + 0, 0, 1655, 0, 0, 0, 0, 0, 0, 0, + 1930, 1930, 0, 1427, 1427, 1427, 1427, 1427, 1427, 0, + 0, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, 1427, + 1427, 1930, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -2046, 0, 1625, 0, 3115, -2046, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -2046, 0, - 0, 0, 1626, 0, 0, 0, 0, 1627, 0, 0, - 0, 0, 0, 0, 3134, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -2046, 0, 0, 0, - 1628, 1629, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1630, 0, 0, 0, 0, - 1648, 0, 0, 1633, 0, 0, 0, 0, 1920, 1920, - 0, 1416, 1416, 1416, 1416, 1416, 1416, 0, 0, 1416, - 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1416, 1920, - 0, 1633, 0, 1631, 0, 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1633, 0, 0, 1634, 3168, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1611, 0, - 0, 1612, 0, 0, 0, 1613, 1614, 1615, 1616, 1617, - 1618, 1619, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1620, 0, 0, 0, - 0, 1592, 0, -2046, 0, 0, 1622, 0, 0, 0, - 0, 0, 0, 1623, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -2046, 1648, 0, 2487, 1648, 0, 0, 0, 0, - 1624, 0, 0, 0, 0, 3228, 3229, 0, 0, 3230, - 1635, 1584, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3185, 1643, 0, 0, 1644, 1645, + 1646, 1632, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1633, 0, + 0, 0, 0, 1634, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3248, 0, 0, 0, - 0, 1648, 0, 0, 0, 1648, 1648, 1648, 1648, 1648, - 1648, 1648, 1648, 0, 0, 0, 0, 0, 1416, 1416, - 3260, 1648, 1648, 0, 0, 0, 0, 0, 0, 0, - -2046, 0, 0, 1648, 0, 0, 1648, 1640, 1641, 1642, - 1643, 1644, 1645, 0, 1648, 1648, 1648, 1648, 1648, 1648, - 1648, 1648, 1648, 1648, 0, 0, 1625, 0, -2046, 0, - 0, 0, 0, 0, 0, 1640, 1641, 1642, 1643, 1644, - 1645, 0, 0, 1626, 0, 0, 0, 1636, 1627, 1648, - 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, - 0, 3306, 0, 0, 2064, 0, 0, 0, 0, 0, - 0, 1628, 1629, 0, 0, 0, 0, 0, 0, 3027, - 0, 0, 0, 3323, 0, 0, 1630, 1107, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3332, 0, - 0, 0, 1416, 2273, 0, 2273, 0, 0, 0, 0, - 0, 0, 0, 1107, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1631, 0, 0, 1632, 0, 0, - 0, 3357, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1633, 0, 0, 1634, 0, 0, 0, 1611, 0, - 0, 1612, 0, 0, 0, 1613, 1614, 1615, 1616, 1617, - 1618, 1619, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1648, 0, 0, 0, 0, 1620, 0, 0, 0, - 3383, 1648, 1648, 0, 0, 0, 1622, 0, 0, 0, - 3027, 0, 0, 1623, 0, 0, 0, 0, 0, 0, - 0, 0, 1107, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1599, 0, 0, 0, 1635, 1636, 0, 0, + 0, 0, 0, 0, 1655, 0, 0, 1655, 0, 0, + 0, 1637, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2502, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3246, 3247, 0, 0, + 3248, 0, 1590, 0, 0, 0, 0, 0, 0, 1638, + 0, 0, 1639, 0, 1655, 0, 0, 0, 1655, 1655, + 1655, 1655, 1655, 1655, 1655, 1655, 1640, 3266, 0, 1641, + 0, 1427, 1427, 0, 1655, 1655, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1655, 0, 0, 1655, + 0, 3278, 0, 0, 0, 0, 0, 1655, 1655, 1655, + 1655, 1655, 1655, 1655, 1655, 1655, 1655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3426, 0, 0, 0, 0, 0, - 0, 1635, 0, 0, 0, 0, 1648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1618, 1655, 0, 1619, 0, 0, 0, 1620, 1621, + 0, 0, 1624, 1625, 1626, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1627, + 0, 3323, 0, 0, 0, 0, 0, 0, 1642, 1629, + 0, 0, 0, 0, 0, 0, 1630, 0, 0, 0, + 3045, 0, 0, 0, 3341, 0, 0, 0, 1111, 1427, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3350, + 0, 0, 0, 1631, 2288, 0, 2288, 0, 0, 0, + 0, 0, 0, 0, 1111, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1618, 0, 0, 1619, + 0, 0, 3375, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1648, 1648, 1648, 0, 0, 1920, 1920, 1920, 1920, 1920, - 1920, 0, 0, 0, 1920, 1920, 1920, 1920, 1920, 1920, - 1920, 1920, 1920, 1920, 0, 0, 0, 0, 1648, 1648, - 0, 0, 1611, 0, 0, 1612, 0, 0, 0, 1613, - 1614, 1615, 1616, 1617, 1618, 1619, 1625, 0, 0, 0, - 0, 0, 3480, 3480, 3480, 0, 1648, 0, 0, 0, - 1620, 0, 1648, 1626, 0, 0, 0, 0, 1627, 0, - 1622, 0, 0, 0, 0, 0, 0, 1623, 1636, 3480, - 0, 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, 1644, - 1645, 1628, 1629, 0, 0, 2064, 1648, 0, 0, 0, - 0, 0, 0, 0, 1624, 0, 1630, 0, 0, 0, - 0, 0, 0, 0, 0, 1648, 0, 0, 1648, 1648, - 3480, 0, 0, 0, 0, 0, 1920, 1920, 0, 0, + 0, 0, 0, 0, 1627, 0, 0, 0, 1655, 0, + 0, 0, 0, 0, 1629, 0, 0, 0, 1655, 1655, + 0, 1630, 0, 0, 0, 1643, 0, 0, 1644, 1645, + 1646, 3401, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, + 0, 3045, 2075, 0, 0, 0, 0, 0, 1631, 0, + 1632, 0, 0, 1111, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1633, 0, 0, + 0, 0, 1634, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1655, 0, 3444, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1635, 1636, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1655, 1655, 1655, + 1637, 0, 1930, 1930, 1930, 1930, 1930, 1930, 0, 0, + 0, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, 1930, + 1930, 1618, 0, 0, 1619, 1655, 1655, 0, 1620, 1621, + 1622, 1623, 1624, 1625, 1626, 1632, 0, 0, 1638, 0, + 0, 1639, 0, 0, 0, 0, 0, 0, 0, 1627, + 0, 0, 1633, 1655, 0, 1640, 0, 1634, 1655, 1629, + 0, 0, 0, 3498, 3498, 3498, 1630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1648, 1416, 1416, 1648, 1631, 1648, 0, 1632, 0, 1648, + 1635, 1636, 0, 0, 0, 0, 0, 0, 0, 0, + 3498, 0, 1655, 1631, 0, 1637, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1655, + 0, 0, 1655, 0, 0, 1655, 1655, 0, 0, 0, + 0, 0, 0, 1930, 1930, 0, 0, 0, 0, 0, + 0, 3498, 0, 1638, 0, 0, 1639, 1655, 1427, 1427, + 1655, 0, 1655, 0, 0, 0, 1655, 0, 0, 0, + 1640, 0, 0, 1641, 0, 0, 0, 1642, 0, 0, + 0, 0, 0, 0, 0, 1618, 0, 0, 1619, 0, + 0, 0, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1633, 0, 0, 1634, 0, 0, 0, 0, 0, + 1632, 0, 0, 1627, 0, 0, 0, 0, 0, 0, + 0, 0, 1655, 1629, 0, 0, 0, 1633, 0, 0, + 1630, 0, 1634, 1618, 0, 0, 1619, 0, 0, 0, + 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, + 0, 0, 0, 0, 0, 1635, 1636, 1631, 0, 0, + 0, 1627, 0, 0, 0, 0, 0, 0, 0, 0, + 1637, 1629, 1642, 0, 0, 0, 0, 0, 1630, 0, + 0, 0, 0, 0, 1643, 0, 0, 1644, 1645, 1646, + 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, 0, + 0, 0, 0, 0, 0, 1631, 0, 0, 1638, 0, + 0, 1639, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1640, 0, 1655, 1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1427, 0, 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1625, 0, 0, 1648, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1626, 0, 0, - 0, 1611, 1627, 0, 1612, 0, 0, 0, 1613, 1614, - 1615, 1616, 1617, 1618, 1619, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1628, 1629, 0, 0, 1620, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1622, - 1630, 1635, 0, 0, 0, 0, 1623, 0, 0, 0, - 0, 1611, 0, 0, 1612, 0, 0, 0, 1613, 1614, - 1615, 1616, 1617, 1618, 1619, 0, 0, 0, 0, 0, - 0, 0, 0, 1624, 0, 0, 0, 0, 1631, 1620, - 0, 1632, 0, 0, 0, 0, 0, 0, 0, 1622, - 1648, 0, 0, 0, 0, 1633, 1623, 1197, 1634, 0, - 0, 0, 0, 1198, 0, 0, 0, 0, 0, 0, - 0, 1210, 1416, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1624, 0, 0, 0, 0, 0, 0, - 0, 1211, 0, 1611, 0, 0, 1612, 0, 0, 0, - 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, 1636, 0, - 0, 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, 1644, - 1645, 1620, 0, 0, 0, 2371, 0, 0, 1648, 1625, - 1648, 1622, 0, 0, 0, 0, 1648, 1212, 1623, 0, - 0, 0, 0, 0, 0, 1648, 1626, 0, 1648, 0, - 1648, 1627, 0, 0, 1648, 1635, 0, 1920, 1920, 0, - 0, 1648, 1648, 0, 0, 1624, 0, 0, 1199, 1648, - 0, 0, 0, 0, 1628, 1629, 0, 0, 1648, 1625, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1630, - 0, 0, 0, 1648, 0, 0, 1626, 0, 0, 0, - 0, 1627, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1633, 0, 0, 0, 0, 1634, 0, 0, 1643, + 0, 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, 1650, + 1651, 1652, 0, 0, 0, 0, 2386, 0, 0, 1635, + 1636, 0, 1632, 0, 0, 0, 0, 1655, 0, 1655, + 0, 0, 0, 0, 1637, 0, 1655, 0, 0, 1633, + 0, 0, 0, 0, 1634, 1655, 0, 1642, 1655, 0, + 1655, 0, 1618, 0, 1655, 1619, 0, 1930, 1930, 1620, + 1621, 1655, 1655, 1624, 1625, 1626, 0, 1635, 1636, 1655, + 0, 0, 1638, 0, 0, 1639, 0, 0, 1655, 0, + 0, 0, 1637, 0, 0, 0, 0, 0, 0, 1640, + 1629, 0, 1641, 1655, 0, 0, 0, 1630, 0, 0, + 0, 0, 0, 0, 0, 0, 1618, 0, 0, 1619, + 0, 0, 0, 1620, 1621, 1622, 1623, 1624, 1625, 1626, + 1638, 0, 0, 1639, 1631, 0, 0, 0, 0, 0, + 0, 1427, 0, 0, 1627, 0, 0, 1640, 0, 0, + 1641, 0, 0, 0, 1629, 0, 0, 0, 0, 0, + 0, 1630, 0, 0, 1643, 0, 0, 1644, 1645, 1646, + 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, 0, + 0, 2486, 0, 0, 0, 0, 0, 0, 1631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1628, 1629, 0, 1631, 0, 0, - 1632, 1416, 1213, 0, 0, 0, 0, 0, 0, 1630, - 0, 0, 0, 0, 1633, 0, 0, 1634, 0, 0, + 0, 1642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1625, 1636, 0, 0, 1637, 1638, 1639, 0, 1640, - 1641, 1642, 1643, 1644, 1645, 0, 0, 1631, 1626, 2472, - 1632, 1214, 0, 1627, 0, 0, 0, 0, 0, 0, - 0, 1215, 0, 0, 1633, 0, 0, 1634, 0, 0, - 0, 0, 0, 1216, 0, 0, 1628, 1629, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1630, 0, 0, 1200, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1217, 0, 0, 0, 0, - 0, 0, 0, 0, 1635, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1631, - 1365, 1366, 1632, 0, 0, 0, 0, 0, 0, 0, - 1920, 1416, 0, 0, 0, 0, 1633, 0, 0, 1634, - 0, 2248, 0, 0, 0, 1202, 0, 1219, 0, 0, - 0, 0, 0, 0, 1635, 1648, 1648, 0, 0, 0, - 0, 1367, 1368, 0, 0, 1369, 1370, 0, 0, 0, - 0, 0, 1220, 0, 0, 0, 0, 2249, 0, 1648, - 0, 0, 0, 1648, 0, 1648, 1648, 1648, 0, 0, - 1648, 1222, 0, 1648, 1648, 0, 0, 0, 0, 0, - 0, 0, 1648, 0, 0, 0, 0, 0, 0, 0, - 0, 1636, 0, 0, 1637, 1638, 1639, 0, 1640, 1641, - 1642, 1643, 1644, 1645, 0, 0, 0, 0, 2496, 0, - 0, 0, 0, 0, 0, 0, 1635, 0, 0, 0, - 1371, 1372, 0, 1648, 0, 0, 0, 0, 1204, 1920, + 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1633, 1642, + 0, 0, 0, 1634, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1636, 1648, 0, 1637, 1638, 1639, 0, 1640, 1641, - 1642, 1643, 1644, 1645, 0, 0, 0, 0, 2702, 0, + 0, 0, 0, 0, 0, 0, -2062, -2062, 0, 0, + 1930, 1427, 0, 0, 0, 1632, 0, 0, 0, 0, + 0, 1637, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1633, 0, 0, 1655, 1655, 1634, 1643, 0, + 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, 1650, 1651, + 1652, 0, 0, 0, 0, 2511, 0, 0, 0, 1655, + 1635, 1636, -2062, 1655, 0, 1655, 1655, 1655, 0, 0, + 1655, 0, 0, 1655, 1655, 1637, 1640, 0, 0, 0, + 0, 0, 1655, 0, 0, 0, 1643, 0, 0, 1644, + 1645, 1646, 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, + 0, 0, 0, 2719, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1638, 0, 0, 1639, 0, 0, 0, + 0, 0, 0, 1655, 0, 0, 0, 0, 0, 1930, + 1640, 0, 0, 1641, 0, 0, 0, 0, 0, 0, + 0, 0, 1655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1648, 0, 0, 0, - 0, 0, 0, 0, 1373, 1374, 1375, 1376, 1377, 1378, - 1379, 1380, 0, 0, 1381, 1382, 0, 0, 0, 0, - 0, 0, 0, 1920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1636, 0, 0, 1637, 1638, 1639, 0, - 1640, 1641, 1642, 1643, 1644, 1645, 1648, 1648, 1648, 0, - 2774, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1648, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1648, 0, + 0, 0, 0, 0, 0, 1655, 0, 0, 1642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1930, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1383, 1384, 0, - 0, 0, 0, 0, 1648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1648, 0, 0, 0, 0, 0, 0, 0, 0, - 1648, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1642, 0, 0, 0, 1655, 1655, 1655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1648, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1655, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1655, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1643, 0, 0, 1644, 1645, + 1646, 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1648, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1385, 1386, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 116, 1042, 815, - 1043, 1044, 1045, 1046, 1047, 0, 1387, 1388, 0, 0, - 0, 0, 0, 0, 1648, 0, 117, 118, 119, 120, - 121, 122, 123, 124, 0, 125, 126, 127, 0, 0, - 0, 0, 0, 1048, 0, 0, 128, 129, 130, 0, - 131, 132, 133, 134, 135, 136, 137, 138, 1049, 140, - 1050, 1051, 0, 143, 144, 145, 146, 147, 148, 1052, - 785, 149, 150, 151, 152, 1053, 1054, 155, 1648, 156, - 157, 158, 159, 786, 0, 787, 0, 1055, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 0, 172, 173, - 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, - 183, 184, 185, 186, 187, 188, 1056, 190, 191, 1057, - 193, 1058, 194, 0, 195, 196, 197, 198, 199, 200, - 0, 0, 201, 202, 203, 204, 0, 0, 205, 206, - 1059, 208, 209, 0, 210, 211, 212, 0, 213, 214, - 215, 0, 216, 217, 218, 219, 1060, 221, 222, 223, - 224, 225, 788, 1061, 227, 0, 228, 229, 1062, 231, - 0, 232, 0, 233, 234, 0, 235, 236, 237, 238, - 239, 240, 0, 241, 0, 1063, 1064, 244, 245, 0, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 0, 258, 259, 260, 261, 262, 263, 264, - 0, 265, 266, 267, 268, 269, 270, 271, 272, 1065, - 1066, 0, 1067, 0, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 0, 0, 287, 288, 289, - 290, 0, 291, 292, 293, 294, 295, 296, 297, 298, - 1068, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 1069, 321, 1070, 323, 324, 325, 326, 1071, 327, - 328, 329, 330, 1072, 790, 332, 1073, 334, 335, 336, - 0, 337, 338, 0, 0, 1074, 340, 341, 0, 0, - 342, 343, 344, 345, 346, 347, 792, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 0, 0, - 0, 0, 360, 361, 793, 363, 364, 365, 366, 367, - 368, 369, 0, 370, 371, 372, 373, 374, 375, 0, - 376, 377, 378, 1075, 380, 381, 382, 383, 0, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 0, 397, 398, 399, 400, 401, 402, 1076, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, - 414, 415, 416, 0, 0, 417, 418, 419, 420, 421, - 422, 423, 424, 425, 0, 426, 427, 428, 1077, 430, - 0, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, 444, 795, 0, 0, 446, 447, - 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, - 1078, 1079, 0, 0, 458, 459, 796, 461, 797, 1080, - 463, 464, 798, 466, 467, 468, 469, 470, 0, 0, - 471, 472, 473, 0, 474, 475, 476, 477, 0, 478, - 479, 480, 481, 482, 483, 1081, 0, 485, 486, 487, - 488, 489, 490, 491, 492, 493, 0, 0, 494, 0, - 0, 495, 496, 497, 498, 499, 500, 501, 502, 503, - 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, - 514, 515, 1082, 0, 0, 0, 0, 0, 0, 1083, - 1084, 1085, 0, 0, 0, 0, 1086, 0, 1087, 0, - 0, 0, 0, 1088, 1089, 0, 1090, 1091, 2627, 116, - 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 1048, 0, 0, 128, 129, - 130, 0, 131, 132, 133, 134, 135, 136, 137, 138, - 1049, 140, 1050, 1051, 0, 143, 144, 145, 146, 147, - 148, 1052, 785, 149, 150, 151, 152, 1053, 1054, 155, - 0, 156, 157, 158, 159, 786, 0, 787, 0, 1055, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 1056, 190, - 191, 1057, 193, 1058, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 1059, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 1060, 221, - 222, 223, 224, 225, 788, 1061, 227, 0, 228, 229, - 1062, 231, 0, 232, 0, 233, 234, 0, 235, 236, - 237, 238, 239, 240, 0, 241, 0, 1063, 1064, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 266, 267, 268, 269, 270, 271, - 272, 1065, 1066, 0, 1067, 0, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 288, 289, 290, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 1068, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 1069, 321, 1070, 323, 324, 325, 326, - 1071, 327, 328, 329, 330, 1072, 790, 332, 1073, 334, - 335, 336, 0, 337, 338, 0, 0, 1074, 340, 341, - 0, 0, 342, 343, 344, 345, 346, 347, 792, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 793, 363, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 1075, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 1076, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 426, 427, 428, - 1077, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 795, 0, 0, - 446, 447, 0, 448, 449, 450, 451, 452, 453, 454, - 0, 455, 1078, 1079, 0, 0, 458, 459, 796, 461, - 797, 1080, 463, 464, 798, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 1081, 0, 485, - 486, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 1082, 0, 0, 0, 0, 0, - 0, 1083, 1084, 1085, 0, 0, 0, 0, 1086, 0, - 1087, 0, 0, 0, 0, 1088, 1089, 0, 1090, 1091, - 3231, 116, 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, + 0, 0, 0, 1655, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1655, 0, 0, 0, 0, 0, 0, 0, 1643, + 1655, 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, 1650, + 1651, 1652, 0, 0, 0, 0, 2784, 0, 0, 0, + 0, 0, 0, 0, 0, 1655, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1655, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 117, 1046, 819, + 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1655, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 1052, 0, 0, 129, 130, 131, 0, + 132, 133, 134, 135, 136, 137, 138, 139, 1053, 141, + 1054, 1055, 0, 144, 145, 146, 147, 148, 149, 1056, + 789, 150, 151, 152, 153, 1057, 1058, 156, 1655, 157, + 158, 159, 160, 790, 0, 791, 0, 1059, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 1060, 191, 192, 1061, + 194, 1062, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 1063, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 1064, 222, 223, 224, + 225, 226, 227, 792, 1065, 229, 0, 230, 231, 1066, + 233, 0, 234, 0, 235, 236, 0, 237, 238, 239, + 240, 241, 242, 0, 243, 0, 1067, 1068, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 268, 269, 270, 271, 272, 273, 274, + 1069, 1070, 0, 1071, 0, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 290, + 291, 292, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 1073, 323, 1074, 325, 326, 327, 328, 1075, + 329, 330, 331, 332, 1076, 794, 334, 1077, 336, 337, + 338, 0, 339, 340, 0, 0, 1078, 342, 343, 0, + 0, 344, 345, 346, 347, 348, 349, 796, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 797, 365, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 1079, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 403, 404, + 405, 406, 1080, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 430, 431, + 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 799, 0, + 0, 450, 451, 0, 452, 453, 454, 455, 456, 457, + 458, 0, 459, 1082, 1083, 0, 0, 462, 463, 800, + 465, 801, 1084, 467, 468, 802, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 1085, 0, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 1086, 0, 0, 0, 0, + 0, 0, 1087, 1088, 1089, 0, 0, 0, 0, 1090, + 0, 1091, 0, 0, 0, 0, 1092, 1093, 0, 1094, + 1095, 2644, 117, 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 117, 118, 119, 120, 121, 122, 123, 124, 0, 125, - 126, 127, 0, 0, 0, 0, 0, 1048, 0, 0, - 128, 129, 130, 0, 131, 132, 133, 134, 135, 136, - 137, 138, 1049, 140, 1050, 1051, 0, 143, 144, 145, - 146, 147, 148, 1052, 785, 149, 150, 151, 152, 1053, - 1054, 155, 0, 156, 157, 158, 159, 786, 0, 787, - 0, 1055, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 0, 172, 173, 174, 175, 176, 177, 0, 178, + 0, 118, 119, 120, 121, 122, 123, 124, 125, 0, + 126, 127, 128, 0, 0, 0, 0, 0, 1052, 0, + 0, 129, 130, 131, 0, 132, 133, 134, 135, 136, + 137, 138, 139, 1053, 141, 1054, 1055, 0, 144, 145, + 146, 147, 148, 149, 1056, 789, 150, 151, 152, 153, + 1057, 1058, 156, 0, 157, 158, 159, 160, 790, 0, + 791, 0, 1059, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 0, 173, 174, 175, 176, 177, 178, 0, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 1056, 190, 191, 1057, 193, 1058, 194, 0, 195, 196, - 197, 198, 199, 200, 14, 15, 201, 202, 203, 204, - 0, 0, 205, 206, 1059, 208, 209, 0, 210, 211, - 212, 0, 213, 214, 215, 0, 216, 217, 218, 219, - 1060, 221, 222, 223, 224, 225, 788, 1061, 227, 0, - 228, 229, 1062, 231, 0, 232, 0, 233, 234, 23, - 235, 236, 237, 238, 239, 240, 0, 241, 0, 1063, - 1064, 244, 245, 0, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 0, 258, 259, 260, - 261, 262, 263, 264, 0, 265, 266, 267, 268, 269, - 270, 271, 272, 1065, 1066, 0, 1067, 0, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, - 0, 287, 288, 289, 290, 0, 291, 292, 293, 294, - 295, 296, 297, 298, 1068, 300, 301, 302, 303, 304, + 189, 1060, 191, 192, 1061, 194, 1062, 195, 0, 196, + 197, 198, 199, 200, 201, 0, 0, 202, 203, 204, + 205, 0, 0, 206, 207, 1063, 209, 210, 0, 211, + 212, 213, 0, 214, 215, 216, 0, 217, 218, 219, + 220, 1064, 222, 223, 224, 225, 226, 227, 792, 1065, + 229, 0, 230, 231, 1066, 233, 0, 234, 0, 235, + 236, 0, 237, 238, 239, 240, 241, 242, 0, 243, + 0, 1067, 1068, 246, 247, 0, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 0, 260, + 261, 262, 263, 264, 265, 266, 0, 267, 268, 269, + 270, 271, 272, 273, 274, 1069, 1070, 0, 1071, 0, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, + 288, 0, 0, 289, 290, 291, 292, 0, 293, 294, + 295, 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 1069, 321, 1070, 323, 324, - 325, 326, 1071, 327, 328, 329, 330, 1072, 790, 332, - 1073, 334, 335, 336, 0, 337, 338, 0, 0, 1074, - 340, 341, 0, 0, 342, 343, 344, 345, 346, 347, - 792, 349, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 27, 28, 29, 0, 360, 361, 793, 363, - 364, 365, 366, 367, 368, 369, 0, 370, 371, 372, - 373, 374, 375, 0, 376, 377, 378, 1075, 380, 381, - 382, 383, 0, 384, 385, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, 396, 0, 397, 398, 399, - 400, 401, 402, 1076, 404, 405, 406, 407, 408, 409, - 410, 411, 412, 413, 414, 415, 416, 34, 0, 417, - 418, 419, 420, 421, 422, 423, 424, 425, 36, 426, - 427, 428, 1077, 430, 0, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, 444, 795, - 38, 0, 446, 447, 39, 448, 449, 450, 451, 452, - 453, 454, 0, 455, 1078, 1079, 0, 0, 458, 459, - 796, 461, 797, 1080, 463, 464, 798, 466, 467, 468, - 469, 470, 0, 0, 471, 472, 473, 41, 474, 475, - 476, 477, 0, 478, 479, 480, 481, 482, 799, 1081, - 0, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 0, 0, 494, 0, 45, 495, 496, 497, 498, 499, + 315, 316, 317, 318, 319, 320, 321, 1073, 323, 1074, + 325, 326, 327, 328, 1075, 329, 330, 331, 332, 1076, + 794, 334, 1077, 336, 337, 338, 0, 339, 340, 0, + 0, 1078, 342, 343, 0, 0, 344, 345, 346, 347, + 348, 349, 796, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, 361, 0, 0, 0, 0, 362, 363, + 797, 365, 366, 367, 368, 369, 370, 371, 0, 372, + 373, 374, 375, 376, 377, 0, 378, 379, 380, 381, + 382, 1079, 384, 385, 386, 387, 0, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 0, 401, 402, 403, 404, 405, 406, 1080, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 0, 0, 421, 422, 423, 424, 425, 426, 427, + 428, 429, 0, 430, 431, 432, 1081, 434, 0, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, 447, 448, 799, 0, 0, 450, 451, 0, 452, + 453, 454, 455, 456, 457, 458, 0, 459, 1082, 1083, + 0, 0, 462, 463, 800, 465, 801, 1084, 467, 468, + 802, 470, 471, 472, 473, 474, 0, 0, 475, 476, + 477, 0, 478, 479, 480, 481, 0, 482, 483, 484, + 485, 486, 487, 1085, 0, 489, 490, 491, 492, 493, + 494, 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, - 510, 511, 512, 513, 514, 515, 1082, 0, 46, 0, - 0, 0, 0, 1083, 1084, 1085, 0, 0, 0, 0, - 1086, 0, 1087, 3206, 0, 0, 0, 1088, 1089, 0, - 1090, 1091, 116, 1042, 815, 1043, 1044, 1045, 1046, 1047, + 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, + 1086, 0, 0, 0, 0, 0, 0, 1087, 1088, 1089, + 0, 0, 0, 0, 1090, 0, 1091, 0, 0, 0, + 0, 1092, 1093, 0, 1094, 1095, 3249, 117, 1046, 819, + 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 1052, 0, 0, 129, 130, 131, 0, + 132, 133, 134, 135, 136, 137, 138, 139, 1053, 141, + 1054, 1055, 0, 144, 145, 146, 147, 148, 149, 1056, + 789, 150, 151, 152, 153, 1057, 1058, 156, 0, 157, + 158, 159, 160, 790, 0, 791, 0, 1059, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 1060, 191, 192, 1061, + 194, 1062, 195, 0, 196, 197, 198, 199, 200, 201, + 14, 15, 202, 203, 204, 205, 0, 0, 206, 207, + 1063, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 1064, 222, 223, 224, + 225, 226, 227, 792, 1065, 229, 0, 230, 231, 1066, + 233, 0, 234, 0, 235, 236, 23, 237, 238, 239, + 240, 241, 242, 0, 243, 0, 1067, 1068, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 268, 269, 270, 271, 272, 273, 274, + 1069, 1070, 0, 1071, 0, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 290, + 291, 292, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 1073, 323, 1074, 325, 326, 327, 328, 1075, + 329, 330, 331, 332, 1076, 794, 334, 1077, 336, 337, + 338, 0, 339, 340, 0, 0, 1078, 342, 343, 0, + 0, 344, 345, 346, 347, 348, 349, 796, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 26, + 27, 28, 0, 362, 363, 797, 365, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 1079, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 403, 404, + 405, 406, 1080, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 33, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 35, 430, 431, + 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 799, 37, + 0, 450, 451, 38, 452, 453, 454, 455, 456, 457, + 458, 0, 459, 1082, 1083, 0, 0, 462, 463, 800, + 465, 801, 1084, 467, 468, 802, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 40, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 803, 1085, 0, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 44, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 1086, 0, 45, 0, 0, + 0, 0, 1087, 1088, 1089, 0, 0, 0, 0, 1090, + 0, 1091, 3224, 0, 0, 0, 1092, 1093, 0, 1094, + 1095, 117, 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 117, 118, 119, 120, 121, 122, 123, 124, 0, - 125, 126, 127, 0, 0, 0, 0, 0, 1048, 0, - 0, 128, 129, 130, 0, 131, 132, 133, 134, 135, - 136, 137, 138, 1049, 140, 1050, 1051, 0, 143, 144, - 145, 146, 147, 148, 1052, 785, 149, 150, 151, 152, - 1053, 1054, 155, 0, 156, 157, 158, 159, 786, 0, - 787, 0, 1055, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 0, 172, 173, 174, 175, 176, 177, 0, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 1056, 190, 191, 1057, 193, 1058, 194, 0, 195, - 196, 197, 198, 199, 200, 14, 15, 201, 202, 203, - 204, 0, 0, 205, 206, 1059, 208, 209, 0, 210, - 211, 212, 0, 213, 214, 215, 0, 216, 217, 218, - 219, 1060, 221, 222, 223, 224, 225, 788, 1061, 227, - 0, 228, 229, 1062, 231, 0, 232, 0, 233, 234, - 23, 235, 236, 237, 238, 239, 240, 0, 241, 0, - 1063, 1064, 244, 245, 0, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 0, 258, 259, - 260, 261, 262, 263, 264, 0, 265, 266, 267, 268, - 269, 270, 271, 272, 1065, 1066, 0, 1067, 0, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 0, 0, 287, 288, 289, 290, 0, 291, 292, 293, - 294, 295, 296, 297, 298, 1068, 300, 301, 302, 303, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 1052, 0, 0, + 129, 130, 131, 0, 132, 133, 134, 135, 136, 137, + 138, 139, 1053, 141, 1054, 1055, 0, 144, 145, 146, + 147, 148, 149, 1056, 789, 150, 151, 152, 153, 1057, + 1058, 156, 0, 157, 158, 159, 160, 790, 0, 791, + 0, 1059, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 1060, 191, 192, 1061, 194, 1062, 195, 0, 196, 197, + 198, 199, 200, 201, 14, 15, 202, 203, 204, 205, + 0, 0, 206, 207, 1063, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 1064, 222, 223, 224, 225, 226, 227, 792, 1065, 229, + 0, 230, 231, 1066, 233, 0, 234, 0, 235, 236, + 23, 237, 238, 239, 240, 241, 242, 0, 243, 0, + 1067, 1068, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 268, 269, 270, + 271, 272, 273, 274, 1069, 1070, 0, 1071, 0, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 290, 291, 292, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 1073, 323, 1074, 325, + 326, 327, 328, 1075, 329, 330, 331, 332, 1076, 794, + 334, 1077, 336, 337, 338, 0, 339, 340, 0, 0, + 1078, 342, 343, 0, 0, 344, 345, 346, 347, 348, + 349, 796, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 26, 27, 28, 0, 362, 363, 797, + 365, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 1079, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 403, 404, 405, 406, 1080, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 33, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 35, 430, 431, 432, 1081, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 447, 448, 799, 37, 0, 450, 451, 38, 452, 453, + 454, 455, 456, 457, 458, 0, 459, 1082, 1083, 0, + 0, 462, 463, 800, 465, 801, 1084, 467, 468, 802, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 40, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 803, 1085, 0, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 44, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 1086, + 0, 45, 0, 0, 0, 0, 1087, 1088, 1089, 0, + 0, 0, 0, 1090, 0, 1091, 0, 0, 0, 0, + 1092, 1093, 0, 1094, 1095, 117, 1046, 819, 1047, 1048, + 1049, 1050, 1051, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 1052, 0, 0, 129, 130, 131, 0, 132, 133, + 134, 135, 136, 137, 138, 139, 1053, 141, 1054, 1055, + 0, 144, 145, 146, 147, 148, 149, 1056, 789, 150, + 151, 152, 153, 1057, 1058, 156, 0, 157, 158, 159, + 160, 790, 0, 791, 0, 1059, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 1060, 191, 192, 1061, 194, 1062, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 1063, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 1064, 222, 223, 224, 225, 226, + 227, 792, 1065, 229, 0, 230, 231, 1066, 233, 0, + 234, 0, 235, 236, 23, 237, 238, 239, 240, 241, + 242, 0, 243, 0, 1067, 1068, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 268, 269, 270, 271, 272, 273, 274, 1069, 1070, + 0, 1071, 0, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 290, 291, 292, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 1072, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 1073, 323, 1074, 325, 326, 327, 328, 1075, 329, 330, + 331, 332, 1076, 794, 334, 1077, 336, 337, 338, 0, + 339, 340, 0, 0, 1078, 342, 343, 0, 0, 344, + 345, 346, 347, 348, 349, 796, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 26, 27, 28, + 0, 362, 363, 797, 365, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 1079, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 403, 404, 405, 406, + 1080, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 33, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 430, 431, 432, 1081, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 447, 448, 799, 0, 0, 450, + 451, 38, 452, 453, 454, 455, 456, 457, 458, 0, + 459, 1082, 1083, 0, 0, 462, 463, 800, 465, 801, + 1084, 467, 468, 802, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 40, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 803, 1085, 0, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 44, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 1086, 0, 45, 0, 0, 0, 0, + 1087, 1088, 1089, 0, 0, 0, 0, 1090, 0, 1091, + 0, 0, 0, 0, 1092, 1093, 0, 1094, 1095, 1251, + 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 1252, 126, 127, 128, + 0, 0, 0, 1253, 0, 1052, 0, 0, 1254, 130, + 131, 0, 132, 133, 134, 1255, 136, 137, 138, 139, + 1053, 1256, 1054, 1055, 0, 144, 145, 146, 147, 148, + 149, 1056, 789, 150, 151, 152, 153, 1057, 1058, 156, + 0, 157, 158, 159, 160, 790, 0, 1257, 0, 1258, + 164, 165, 166, 167, 168, 1259, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 1260, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 1060, 191, + 192, 1061, 194, 1062, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 1261, 0, + 206, 207, 1063, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 1064, 222, + 223, 224, 225, 226, 227, 792, 1065, 229, 0, 230, + 231, 1066, 233, 0, 234, 0, 235, 1262, 0, 1263, + 238, 239, 1264, 1265, 242, 0, 243, 0, 1067, 1068, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 1266, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 1267, 269, 270, 271, 272, + 273, 274, 1069, 1070, 0, 1071, 0, 278, 1268, 1269, + 281, 1270, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 1271, 291, 1272, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 1273, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 1073, 1274, 1074, 325, 326, 327, + 328, 1075, 329, 330, 1275, 332, 1076, 794, 334, 1077, + 336, 337, 338, 0, 339, 340, 0, 0, 1078, 342, + 343, 0, 0, 344, 345, 346, 1276, 348, 1277, 796, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 797, 1278, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 1079, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 1279, 404, 405, 406, 1080, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 1280, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 1281, 431, 432, 1081, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 1282, 448, + 799, 0, 0, 450, 451, 0, 452, 1283, 454, 455, + 456, 457, 458, 0, 459, 1082, 1083, 0, 0, 462, + 463, 800, 465, 801, 1084, 467, 468, 1284, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 1085, 1285, 489, 1286, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 1086, 0, 0, + 0, 0, 0, 0, 1087, 1088, 1089, 0, 0, 0, + 0, 1090, 0, 1091, 1287, 0, 0, 0, 1092, 1093, + 0, 1094, 1095, 117, 1046, 819, 1047, 1048, 0, 1050, + 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 1052, + 0, 0, 129, 130, 131, 0, 132, 133, 134, 135, + 136, 137, 138, 139, 1053, 141, 1054, 1055, 0, 144, + 145, 146, 147, 148, 149, 1056, 789, 150, 151, 152, + 153, 1057, 1058, 156, 0, 157, 158, 159, 160, 790, + 0, 791, 0, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 1060, 191, 192, 1061, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 14, 15, 202, 203, + 204, 205, 0, 0, 206, 207, 1063, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 1064, 222, 223, 224, 225, 226, 227, 792, + 1065, 229, 0, 230, 231, 1066, 233, 0, 234, 0, + 235, 236, 23, 237, 238, 239, 240, 241, 242, 0, + 243, 0, 1067, 1068, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 268, + 269, 270, 271, 272, 273, 274, 1069, 1070, 0, 1071, + 0, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 290, 291, 292, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 1069, 321, 1070, 323, - 324, 325, 326, 1071, 327, 328, 329, 330, 1072, 790, - 332, 1073, 334, 335, 336, 0, 337, 338, 0, 0, - 1074, 340, 341, 0, 0, 342, 343, 344, 345, 346, - 347, 792, 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 27, 28, 29, 0, 360, 361, 793, - 363, 364, 365, 366, 367, 368, 369, 0, 370, 371, - 372, 373, 374, 375, 0, 376, 377, 378, 1075, 380, - 381, 382, 383, 0, 384, 385, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 0, 397, 398, - 399, 400, 401, 402, 1076, 404, 405, 406, 407, 408, - 409, 410, 411, 412, 413, 414, 415, 416, 34, 0, - 417, 418, 419, 420, 421, 422, 423, 424, 425, 36, - 426, 427, 428, 1077, 430, 0, 431, 432, 433, 434, + 314, 315, 316, 317, 318, 319, 320, 321, 1073, 323, + 1074, 325, 326, 327, 328, 0, 329, 330, 331, 332, + 1076, 794, 334, 1077, 336, 337, 338, 0, 339, 340, + 0, 0, 341, 342, 343, 0, 0, 344, 345, 346, + 347, 348, 349, 796, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 26, 27, 28, 0, 362, + 363, 797, 365, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 1079, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 403, 404, 405, 406, 1080, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 33, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 35, 430, 431, 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, - 795, 38, 0, 446, 447, 39, 448, 449, 450, 451, - 452, 453, 454, 0, 455, 1078, 1079, 0, 0, 458, - 459, 796, 461, 797, 1080, 463, 464, 798, 466, 467, - 468, 469, 470, 0, 0, 471, 472, 473, 41, 474, - 475, 476, 477, 0, 478, 479, 480, 481, 482, 799, - 1081, 0, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 0, 0, 494, 0, 45, 495, 496, 497, 498, + 445, 446, 447, 448, 799, 37, 0, 450, 451, 38, + 452, 453, 454, 455, 456, 457, 458, 0, 459, 1082, + 1083, 0, 0, 462, 463, 800, 465, 801, 1084, 467, + 468, 802, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 40, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 803, 1085, 0, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 44, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, - 509, 510, 511, 512, 513, 514, 515, 1082, 0, 46, - 0, 0, 0, 0, 1083, 1084, 1085, 0, 0, 0, - 0, 1086, 0, 1087, 0, 0, 0, 0, 1088, 1089, - 0, 1090, 1091, 116, 1042, 815, 1043, 1044, 1045, 1046, - 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 117, 118, 119, 120, 121, 122, 123, 124, - 0, 125, 126, 127, 0, 0, 0, 0, 0, 1048, - 0, 0, 128, 129, 130, 0, 131, 132, 133, 134, - 135, 136, 137, 138, 1049, 140, 1050, 1051, 0, 143, - 144, 145, 146, 147, 148, 1052, 785, 149, 150, 151, - 152, 1053, 1054, 155, 0, 156, 157, 158, 159, 786, - 0, 787, 0, 1055, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 0, 172, 173, 174, 175, 176, 177, - 0, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 1056, 190, 191, 1057, 193, 1058, 194, 0, - 195, 196, 197, 198, 199, 200, 0, 0, 201, 202, - 203, 204, 0, 0, 205, 206, 1059, 208, 209, 0, - 210, 211, 212, 0, 213, 214, 215, 0, 216, 217, - 218, 219, 1060, 221, 222, 223, 224, 225, 788, 1061, - 227, 0, 228, 229, 1062, 231, 0, 232, 0, 233, - 234, 23, 235, 236, 237, 238, 239, 240, 0, 241, - 0, 1063, 1064, 244, 245, 0, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 0, 258, - 259, 260, 261, 262, 263, 264, 0, 265, 266, 267, - 268, 269, 270, 271, 272, 1065, 1066, 0, 1067, 0, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 287, 288, 289, 290, 0, 291, 292, - 293, 294, 295, 296, 297, 298, 1068, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 1069, 321, 1070, - 323, 324, 325, 326, 1071, 327, 328, 329, 330, 1072, - 790, 332, 1073, 334, 335, 336, 0, 337, 338, 0, - 0, 1074, 340, 341, 0, 0, 342, 343, 344, 345, - 346, 347, 792, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 27, 28, 29, 0, 360, 361, - 793, 363, 364, 365, 366, 367, 368, 369, 0, 370, - 371, 372, 373, 374, 375, 0, 376, 377, 378, 1075, - 380, 381, 382, 383, 0, 384, 385, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 0, 397, - 398, 399, 400, 401, 402, 1076, 404, 405, 406, 407, - 408, 409, 410, 411, 412, 413, 414, 415, 416, 34, - 0, 417, 418, 419, 420, 421, 422, 423, 424, 425, - 0, 426, 427, 428, 1077, 430, 0, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 795, 0, 0, 446, 447, 39, 448, 449, 450, - 451, 452, 453, 454, 0, 455, 1078, 1079, 0, 0, - 458, 459, 796, 461, 797, 1080, 463, 464, 798, 466, - 467, 468, 469, 470, 0, 0, 471, 472, 473, 41, - 474, 475, 476, 477, 0, 478, 479, 480, 481, 482, - 799, 1081, 0, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 0, 0, 494, 0, 45, 495, 496, 497, - 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, - 508, 509, 510, 511, 512, 513, 514, 515, 1082, 0, - 46, 0, 0, 0, 0, 1083, 1084, 1085, 0, 0, - 0, 0, 1086, 0, 1087, 0, 0, 0, 0, 1088, - 1089, 0, 1090, 1091, 1242, 1042, 815, 1043, 1044, 1045, - 1046, 1047, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 1243, 125, 126, 127, 0, 0, 0, 1244, 0, - 1048, 0, 0, 1245, 129, 130, 0, 131, 132, 133, - 1246, 135, 136, 137, 138, 1049, 1247, 1050, 1051, 0, - 143, 144, 145, 146, 147, 148, 1052, 785, 149, 150, - 151, 152, 1053, 1054, 155, 0, 156, 157, 158, 159, - 786, 0, 1248, 0, 1249, 163, 164, 165, 166, 167, - 1250, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 1251, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 1056, 190, 191, 1057, 193, 1058, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 1252, 0, 205, 206, 1059, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 1060, 221, 222, 223, 224, 225, 788, - 1061, 227, 0, 228, 229, 1062, 231, 0, 232, 0, - 233, 1253, 0, 1254, 236, 237, 1255, 1256, 240, 0, - 241, 0, 1063, 1064, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 1257, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 1258, - 267, 268, 269, 270, 271, 272, 1065, 1066, 0, 1067, - 0, 276, 1259, 1260, 279, 1261, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 1262, 289, 1263, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 1264, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 1069, 1265, - 1070, 323, 324, 325, 326, 1071, 327, 328, 1266, 330, - 1072, 790, 332, 1073, 334, 335, 336, 0, 337, 338, - 0, 0, 1074, 340, 341, 0, 0, 342, 343, 344, - 1267, 346, 1268, 792, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 793, 1269, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 1075, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 1270, 400, 401, 402, 1076, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 1271, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 1272, 427, 428, 1077, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 1273, 444, 795, 0, 0, 446, 447, 0, 448, 1274, - 450, 451, 452, 453, 454, 0, 455, 1078, 1079, 0, - 0, 458, 459, 796, 461, 797, 1080, 463, 464, 1275, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 1081, 1276, 485, 1277, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 1082, - 0, 0, 0, 0, 0, 0, 1083, 1084, 1085, 0, - 0, 0, 0, 1086, 0, 1087, 1278, 0, 0, 0, - 1088, 1089, 0, 1090, 1091, 116, 1042, 815, 1043, 1044, - 0, 1046, 1047, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 117, 118, 119, 120, 121, 122, - 123, 124, 0, 125, 126, 127, 0, 0, 0, 0, - 0, 1048, 0, 0, 128, 129, 130, 0, 131, 132, - 133, 134, 135, 136, 137, 138, 1049, 140, 1050, 1051, - 0, 143, 144, 145, 146, 147, 148, 1052, 785, 149, - 150, 151, 152, 1053, 1054, 155, 0, 156, 157, 158, - 159, 786, 0, 787, 0, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 0, 172, 173, 174, 175, - 176, 177, 0, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 1056, 190, 191, 1057, 193, 0, - 194, 0, 195, 196, 197, 198, 199, 200, 14, 15, - 201, 202, 203, 204, 0, 0, 205, 206, 1059, 208, - 209, 0, 210, 211, 212, 0, 213, 214, 215, 0, - 216, 217, 218, 219, 1060, 221, 222, 223, 224, 225, - 788, 1061, 227, 0, 228, 229, 1062, 231, 0, 232, - 0, 233, 234, 23, 235, 236, 237, 238, 239, 240, - 0, 241, 0, 1063, 1064, 244, 245, 0, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 0, 258, 259, 260, 261, 262, 263, 264, 0, 265, - 266, 267, 268, 269, 270, 271, 272, 1065, 1066, 0, - 1067, 0, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 0, 0, 287, 288, 289, 290, 0, - 291, 292, 293, 294, 295, 296, 297, 298, 1068, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 1069, - 321, 1070, 323, 324, 325, 326, 0, 327, 328, 329, - 330, 1072, 790, 332, 1073, 334, 335, 336, 0, 337, - 338, 0, 0, 339, 340, 341, 0, 0, 342, 343, - 344, 345, 346, 347, 792, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 27, 28, 29, 0, - 360, 361, 793, 363, 364, 365, 366, 367, 368, 369, - 0, 370, 371, 372, 373, 374, 375, 0, 376, 377, - 378, 1075, 380, 381, 382, 383, 0, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 0, 397, 398, 399, 400, 401, 402, 1076, 404, 405, - 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 34, 0, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 36, 426, 427, 428, 1077, 430, 0, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, 444, 795, 38, 0, 446, 447, 39, 448, - 449, 450, 451, 452, 453, 454, 0, 455, 1078, 1079, - 0, 0, 458, 459, 796, 461, 797, 1080, 463, 464, - 798, 466, 467, 468, 469, 470, 0, 0, 471, 472, - 473, 41, 474, 475, 476, 477, 0, 478, 479, 480, - 481, 482, 799, 1081, 0, 485, 486, 487, 488, 489, - 490, 491, 492, 493, 0, 0, 494, 0, 45, 495, - 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, - 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, - 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1086, 0, 1087, 0, 0, 0, - 0, 1088, 1089, 0, 1090, 1091, 116, 1042, 815, 1043, - 1044, 1045, 1046, 1047, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 117, 118, 119, 120, 121, - 122, 123, 124, 0, 125, 126, 127, 0, 0, 0, - 0, 0, 1048, 0, 0, 128, 129, 130, 0, 131, - 132, 133, 134, 135, 136, 137, 138, 1049, 140, 1050, - 1051, 1423, 143, 144, 145, 146, 147, 148, 1052, 785, - 149, 150, 151, 152, 1053, 1054, 155, 0, 156, 157, - 158, 159, 786, 0, 787, 0, 1055, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 0, 172, 173, 174, - 175, 176, 177, 0, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 1056, 190, 191, 1057, 193, - 1058, 194, 0, 195, 196, 197, 198, 199, 200, 0, - 0, 201, 202, 203, 204, 0, 0, 205, 206, 1059, - 208, 209, 0, 210, 211, 212, 0, 213, 214, 215, - 0, 216, 217, 218, 219, 1060, 221, 222, 223, 224, - 225, 788, 1061, 227, 0, 228, 229, 1062, 231, 0, - 232, 0, 233, 234, 1424, 235, 236, 237, 238, 239, - 240, 0, 241, 0, 1063, 1064, 244, 245, 0, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 0, 258, 259, 260, 261, 262, 263, 264, 0, - 265, 266, 267, 268, 269, 270, 271, 272, 1065, 1066, - 0, 1067, 0, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 0, 1425, 287, 288, 289, 290, - 0, 291, 292, 293, 294, 295, 296, 297, 298, 1068, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 0, 0, 45, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1090, 0, 1091, 0, 0, + 0, 0, 1092, 1093, 0, 1094, 1095, 117, 1046, 819, + 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 1052, 0, 0, 129, 130, 131, 0, + 132, 133, 134, 135, 136, 137, 138, 139, 1053, 141, + 1054, 1055, 1434, 144, 145, 146, 147, 148, 149, 1056, + 789, 150, 151, 152, 153, 1057, 1058, 156, 0, 157, + 158, 159, 160, 790, 0, 791, 0, 1059, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 1060, 191, 192, 1061, + 194, 1062, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 1063, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 1064, 222, 223, 224, + 225, 226, 227, 792, 1065, 229, 0, 230, 231, 1066, + 233, 0, 234, 0, 235, 236, 1435, 237, 238, 239, + 240, 241, 242, 0, 243, 0, 1067, 1068, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 268, 269, 270, 271, 272, 273, 274, + 1069, 1070, 0, 1071, 0, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 0, 1436, 289, 290, + 291, 292, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 1069, 321, 1070, 323, 324, 325, 326, 1071, 327, 328, - 329, 330, 1072, 790, 332, 1073, 334, 335, 336, 0, - 337, 338, 0, 0, 1074, 340, 341, 0, 0, 342, - 343, 344, 345, 346, 347, 792, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 0, 0, 0, - 0, 360, 361, 793, 363, 364, 365, 366, 367, 368, - 369, 0, 370, 371, 372, 373, 374, 375, 0, 376, - 377, 378, 1075, 380, 381, 382, 383, 0, 384, 385, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 0, 397, 398, 399, 400, 401, 402, 1076, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 0, 0, 417, 418, 419, 420, 421, 422, - 423, 424, 425, 0, 426, 427, 428, 1077, 430, 0, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 443, 444, 795, 0, 0, 446, 447, 0, - 448, 449, 450, 451, 452, 453, 454, 0, 455, 1078, - 1079, 0, 1426, 458, 459, 796, 461, 797, 1080, 463, - 464, 798, 466, 467, 468, 469, 470, 0, 0, 471, - 472, 473, 0, 474, 475, 476, 477, 0, 478, 479, - 480, 481, 482, 483, 1081, 0, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 0, 0, 494, 0, 0, - 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, + 320, 321, 1073, 323, 1074, 325, 326, 327, 328, 1075, + 329, 330, 331, 332, 1076, 794, 334, 1077, 336, 337, + 338, 0, 339, 340, 0, 0, 1078, 342, 343, 0, + 0, 344, 345, 346, 347, 348, 349, 796, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 797, 365, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 1079, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 403, 404, + 405, 406, 1080, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 430, 431, + 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 799, 0, + 0, 450, 451, 0, 452, 453, 454, 455, 456, 457, + 458, 0, 459, 1082, 1083, 0, 1437, 462, 463, 800, + 465, 801, 1084, 467, 468, 802, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 1085, 0, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, - 515, 1082, 0, 0, 0, 0, 0, 0, 1083, 1084, - 1085, 0, 0, 0, 0, 1086, 0, 1087, 0, 0, - 0, 0, 1088, 1089, 0, 1090, 1091, 1242, 1042, 815, - 1043, 1044, 1045, 1046, 1047, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 117, 118, 119, 120, - 121, 122, 123, 124, 0, 125, 126, 127, 0, 0, - 0, 1244, 0, 1048, 0, 0, 1245, 129, 130, 0, - 131, 132, 133, 1246, 135, 136, 137, 138, 1049, 1247, - 1050, 1051, 0, 143, 144, 145, 146, 147, 148, 1052, - 785, 149, 150, 151, 152, 1053, 1054, 155, 0, 156, - 157, 158, 159, 786, 0, 1248, 0, 1249, 163, 164, - 165, 166, 167, 1250, 169, 170, 171, 0, 172, 173, - 174, 175, 176, 177, 0, 1251, 179, 180, 181, 182, - 183, 184, 185, 186, 187, 188, 1056, 190, 191, 1057, - 193, 1058, 194, 0, 195, 196, 197, 198, 199, 200, - 0, 0, 201, 202, 203, 204, 0, 0, 205, 206, - 1059, 208, 209, 0, 210, 211, 212, 0, 213, 214, - 215, 0, 216, 217, 218, 219, 1060, 221, 222, 223, - 224, 225, 788, 1061, 227, 0, 228, 229, 1062, 231, - 0, 232, 0, 233, 1253, 0, 1254, 236, 237, 1255, - 1256, 240, 0, 241, 0, 1063, 1064, 244, 245, 0, - 246, 247, 248, 249, 250, 251, 252, 1257, 254, 255, - 256, 257, 0, 258, 259, 260, 261, 262, 263, 264, - 0, 265, 1258, 267, 268, 269, 270, 271, 272, 1065, - 1066, 0, 1067, 0, 276, 1259, 1260, 279, 1261, 281, - 282, 283, 284, 285, 286, 0, 0, 287, 1262, 289, - 1263, 0, 291, 292, 293, 294, 295, 296, 297, 298, - 1264, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 1069, 1265, 1070, 323, 324, 325, 326, 1071, 327, - 328, 1266, 330, 1072, 790, 332, 1073, 334, 335, 336, - 0, 337, 338, 0, 0, 1074, 340, 341, 0, 0, - 342, 343, 344, 1267, 346, 1268, 792, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 0, 0, - 0, 0, 360, 361, 793, 1269, 364, 365, 366, 367, - 368, 369, 0, 370, 371, 372, 373, 374, 375, 0, - 376, 377, 378, 1075, 380, 381, 382, 383, 0, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 0, 397, 398, 1270, 400, 401, 402, 1076, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, - 414, 415, 416, 0, 1271, 417, 418, 419, 420, 421, - 422, 423, 424, 425, 0, 1272, 427, 428, 1077, 430, - 0, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 1273, 444, 795, 0, 0, 446, 447, - 0, 448, 1274, 450, 451, 452, 453, 454, 0, 455, - 1078, 1079, 0, 0, 458, 459, 796, 461, 797, 1080, - 463, 464, 1275, 466, 467, 468, 469, 470, 0, 0, - 471, 472, 473, 0, 474, 475, 476, 477, 0, 478, - 479, 480, 481, 482, 483, 1081, 2278, 485, 1277, 487, - 488, 489, 490, 491, 492, 493, 0, 0, 494, 0, - 0, 495, 496, 497, 498, 499, 500, 501, 502, 503, - 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, - 514, 515, 1082, 0, 0, 0, 0, 0, 0, 1083, - 1084, 1085, 0, 0, 0, 0, 1086, 0, 1087, 0, - 0, 0, 0, 1088, 1089, 0, 1090, 1091, 1242, 1042, - 815, 1043, 1044, 1045, 1046, 1047, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 117, 118, 119, - 120, 121, 122, 123, 124, 0, 125, 126, 127, 0, - 0, 0, 1244, 0, 1048, 0, 0, 1245, 129, 130, - 0, 131, 132, 133, 1246, 135, 136, 137, 138, 1049, - 1247, 1050, 1051, 0, 143, 144, 145, 146, 147, 148, - 1052, 785, 149, 150, 151, 152, 1053, 1054, 155, 0, - 156, 157, 158, 159, 786, 0, 1248, 0, 1249, 163, - 164, 165, 166, 167, 1250, 169, 170, 171, 0, 172, - 173, 174, 175, 176, 177, 0, 1251, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 1056, 190, 191, - 1057, 193, 1058, 194, 0, 195, 196, 197, 198, 199, - 200, 0, 0, 201, 202, 203, 204, 0, 0, 205, - 206, 1059, 208, 209, 0, 210, 211, 212, 0, 213, - 214, 215, 0, 216, 217, 218, 219, 1060, 221, 222, - 223, 224, 225, 788, 1061, 227, 0, 228, 229, 1062, - 231, 0, 232, 0, 233, 1253, 0, 1254, 236, 237, - 1255, 1256, 240, 0, 241, 0, 1063, 1064, 244, 245, - 0, 246, 247, 248, 249, 250, 251, 252, 1257, 254, - 255, 256, 257, 0, 258, 259, 260, 261, 262, 263, - 264, 0, 265, 1258, 267, 268, 269, 270, 271, 272, - 1065, 1066, 0, 1067, 0, 276, 1259, 1260, 279, 1261, - 281, 282, 283, 284, 285, 286, 0, 0, 287, 1262, - 289, 1263, 0, 291, 292, 293, 294, 295, 296, 297, - 298, 1264, 300, 301, 302, 303, 304, 305, 306, 307, + 515, 516, 517, 518, 519, 1086, 0, 0, 0, 0, + 0, 0, 1087, 1088, 1089, 0, 0, 0, 0, 1090, + 0, 1091, 0, 0, 0, 0, 1092, 1093, 0, 1094, + 1095, 1251, 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 1253, 0, 1052, 0, 0, + 1254, 130, 131, 0, 132, 133, 134, 1255, 136, 137, + 138, 139, 1053, 1256, 1054, 1055, 0, 144, 145, 146, + 147, 148, 149, 1056, 789, 150, 151, 152, 153, 1057, + 1058, 156, 0, 157, 158, 159, 160, 790, 0, 1257, + 0, 1258, 164, 165, 166, 167, 168, 1259, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 1260, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 1060, 191, 192, 1061, 194, 1062, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 1063, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 1064, 222, 223, 224, 225, 226, 227, 792, 1065, 229, + 0, 230, 231, 1066, 233, 0, 234, 0, 235, 1262, + 0, 1263, 238, 239, 1264, 1265, 242, 0, 243, 0, + 1067, 1068, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 1266, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 1267, 269, 270, + 271, 272, 273, 274, 1069, 1070, 0, 1071, 0, 278, + 1268, 1269, 281, 1270, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 1271, 291, 1272, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 1273, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 1073, 1274, 1074, 325, + 326, 327, 328, 1075, 329, 330, 1275, 332, 1076, 794, + 334, 1077, 336, 337, 338, 0, 339, 340, 0, 0, + 1078, 342, 343, 0, 0, 344, 345, 346, 1276, 348, + 1277, 796, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 797, + 1278, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 1079, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 1279, 404, 405, 406, 1080, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 1280, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 1281, 431, 432, 1081, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 1282, 448, 799, 0, 0, 450, 451, 0, 452, 1283, + 454, 455, 456, 457, 458, 0, 459, 1082, 1083, 0, + 0, 462, 463, 800, 465, 801, 1084, 467, 468, 1284, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 1085, 2293, 489, 1286, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 1086, + 0, 0, 0, 0, 0, 0, 1087, 1088, 1089, 0, + 0, 0, 0, 1090, 0, 1091, 0, 0, 0, 0, + 1092, 1093, 0, 1094, 1095, 1251, 1046, 819, 1047, 1048, + 1049, 1050, 1051, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 1253, + 0, 1052, 0, 0, 1254, 130, 131, 0, 132, 133, + 134, 1255, 136, 137, 138, 139, 1053, 1256, 1054, 1055, + 0, 144, 145, 146, 147, 148, 149, 1056, 789, 150, + 151, 152, 153, 1057, 1058, 156, 0, 157, 158, 159, + 160, 790, 0, 1257, 0, 1258, 164, 165, 166, 167, + 168, 1259, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 1260, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 1060, 191, 192, 1061, 194, 1062, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 1063, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 1064, 222, 223, 224, 225, 226, + 227, 792, 1065, 229, 0, 230, 231, 1066, 233, 0, + 234, 0, 235, 1262, 0, 1263, 238, 239, 1264, 1265, + 242, 0, 243, 0, 1067, 1068, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 1266, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 1267, 269, 270, 271, 272, 273, 274, 1069, 1070, + 0, 1071, 0, 278, 1268, 1269, 281, 1270, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 1271, 291, 1272, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 1273, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 1073, 1274, 1074, 325, 326, 327, 328, 1075, 329, 330, + 1275, 332, 1076, 794, 334, 1077, 336, 337, 338, 0, + 339, 340, 0, 0, 1078, 342, 343, 0, 0, 344, + 345, 346, 1276, 348, 1277, 796, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 797, 1278, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 1079, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 1279, 404, 405, 406, + 1080, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 0, 1280, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 1281, 431, 432, 1081, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 1282, 448, 799, 0, 0, 450, + 451, 0, 452, 1283, 454, 455, 456, 457, 458, 0, + 459, 1082, 1083, 0, 0, 462, 463, 800, 465, 801, + 1084, 467, 468, 1284, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 1085, 0, 489, 1286, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 1086, 0, 0, 0, 0, 0, 0, + 1087, 1088, 1089, 0, 0, 0, 0, 1090, 0, 1091, + 2347, 0, 0, 0, 1092, 1093, 0, 1094, 1095, 117, + 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, -1120, 126, 127, 128, + 0, 0, 0, 0, -1120, 1052, 0, 0, 129, 130, + 131, 0, 132, 133, 134, 135, 136, 137, 138, 139, + 1053, 141, 1054, 1055, 0, 144, 145, 146, 147, 148, + 149, 1056, 789, 150, 151, 152, 153, 1057, 1058, 156, + 0, 157, 158, 159, 160, 790, 0, 791, 0, 1059, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 1060, 191, + 192, 1061, 194, 1062, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 1063, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 1064, 222, + 223, 224, 225, 226, 227, 792, 1065, 229, 0, 230, + 231, 1066, 233, 0, 234, 0, 235, 236, 0, 237, + 238, 239, 240, 241, 242, 0, 243, 0, 1067, 1068, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 268, 269, 270, 271, 272, + 273, 274, 1069, 1070, 0, 1071, 0, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 290, 291, 292, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 1069, 1265, 1070, 323, 324, 325, 326, 1071, - 327, 328, 1266, 330, 1072, 790, 332, 1073, 334, 335, - 336, 0, 337, 338, 0, 0, 1074, 340, 341, 0, - 0, 342, 343, 344, 1267, 346, 1268, 792, 349, 350, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 0, - 0, 0, 0, 360, 361, 793, 1269, 364, 365, 366, - 367, 368, 369, 0, 370, 371, 372, 373, 374, 375, - 0, 376, 377, 378, 1075, 380, 381, 382, 383, 0, - 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 0, 397, 398, 1270, 400, 401, 402, - 1076, 404, 405, 406, 407, 408, 409, 410, 411, 412, - 413, 414, 415, 416, 0, 1271, 417, 418, 419, 420, - 421, 422, 423, 424, 425, 0, 1272, 427, 428, 1077, - 430, 0, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 1273, 444, 795, 0, 0, 446, - 447, 0, 448, 1274, 450, 451, 452, 453, 454, 0, - 455, 1078, 1079, 0, 0, 458, 459, 796, 461, 797, - 1080, 463, 464, 1275, 466, 467, 468, 469, 470, 0, - 0, 471, 472, 473, 0, 474, 475, 476, 477, 0, - 478, 479, 480, 481, 482, 483, 1081, 0, 485, 1277, - 487, 488, 489, 490, 491, 492, 493, 0, 0, 494, - 0, 0, 495, 496, 497, 498, 499, 500, 501, 502, + 318, 319, 320, 321, 1073, 323, 1074, 325, 326, 327, + 328, 1075, 329, 330, 331, 332, 1076, 794, 334, 1077, + 336, 337, 338, 0, 339, 340, 0, 0, 1078, 342, + 343, 0, 0, 344, 345, 346, 347, 348, 349, 796, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 797, 365, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 1079, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 403, 404, 405, 406, 1080, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 430, 431, 432, 1081, 434, -1120, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, + 799, 0, 0, 450, 451, 0, 452, 453, 454, 455, + 456, 457, 458, 0, 459, 1082, 1083, 0, 0, 462, + 463, 800, 465, 801, 1084, 467, 468, 802, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 1085, 0, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, - 513, 514, 515, 1082, 0, 0, 0, 0, 0, 0, - 1083, 1084, 1085, 0, 0, 0, 0, 1086, 0, 1087, - 2335, 0, 0, 0, 1088, 1089, 0, 1090, 1091, 116, - 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, -1111, 125, 126, 127, - 0, 0, 0, 0, -1111, 1048, 0, 0, 128, 129, - 130, 0, 131, 132, 133, 134, 135, 136, 137, 138, - 1049, 140, 1050, 1051, 0, 143, 144, 145, 146, 147, - 148, 1052, 785, 149, 150, 151, 152, 1053, 1054, 155, - 0, 156, 157, 158, 159, 786, 0, 787, 0, 1055, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 1056, 190, - 191, 1057, 193, 1058, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 1059, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 1060, 221, - 222, 223, 224, 225, 788, 1061, 227, 0, 228, 229, - 1062, 231, 0, 232, 0, 233, 234, 0, 235, 236, - 237, 238, 239, 240, 0, 241, 0, 1063, 1064, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 266, 267, 268, 269, 270, 271, - 272, 1065, 1066, 0, 1067, 0, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 288, 289, 290, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 1068, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 1069, 321, 1070, 323, 324, 325, 326, - 1071, 327, 328, 329, 330, 1072, 790, 332, 1073, 334, - 335, 336, 0, 337, 338, 0, 0, 1074, 340, 341, - 0, 0, 342, 343, 344, 345, 346, 347, 792, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 793, 363, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 1075, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 1076, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 426, 427, 428, - 1077, 430, -1111, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 795, 0, 0, - 446, 447, 0, 448, 449, 450, 451, 452, 453, 454, - 0, 455, 1078, 1079, 0, 0, 458, 459, 796, 461, - 797, 1080, 463, 464, 798, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 1081, 0, 485, - 486, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 1082, 0, 0, 0, 0, 0, - 0, 1083, 1084, 1085, 0, 0, 0, 0, 1086, 0, - 1087, 0, 0, 0, 0, 1088, 1089, 0, 1090, 1091, - 1242, 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, - 118, 119, 120, 121, 122, 123, 124, 0, 125, 126, - 127, 0, 0, 0, 1244, 0, 1048, 0, 0, 1245, - 129, 130, 0, 131, 132, 133, 1246, 135, 136, 137, - 138, 1049, 1247, 1050, 1051, 0, 143, 144, 145, 146, - 147, 148, 1052, 785, 149, 150, 151, 152, 1053, 1054, - 155, 0, 156, 157, 158, 159, 786, 0, 1248, 0, - 1249, 163, 164, 165, 166, 167, 1250, 169, 170, 171, - 0, 172, 173, 174, 175, 176, 177, 0, 1251, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 1056, - 190, 191, 1057, 193, 1058, 194, 0, 195, 196, 197, - 198, 199, 200, 0, 0, 201, 202, 203, 204, 0, - 0, 205, 206, 1059, 208, 209, 0, 210, 211, 212, - 0, 213, 214, 215, 0, 216, 217, 218, 219, 1060, - 221, 222, 223, 224, 225, 788, 1061, 227, 0, 228, - 229, 1062, 231, 0, 232, 0, 233, 1253, 0, 1254, - 236, 237, 1255, 1256, 240, 0, 241, 0, 1063, 1064, - 244, 245, 0, 246, 247, 248, 249, 250, 251, 252, - 1257, 254, 255, 256, 257, 0, 258, 259, 260, 261, - 262, 263, 264, 0, 265, 1258, 267, 268, 269, 270, - 271, 272, 1065, 1066, 0, 1067, 0, 276, 1259, 1260, - 279, 1261, 281, 282, 283, 284, 285, 286, 0, 0, - 287, 1262, 289, 1263, 0, 291, 292, 293, 294, 295, - 296, 297, 298, 1264, 300, 301, 302, 303, 304, 305, + 513, 514, 515, 516, 517, 518, 519, 1086, 0, 0, + 0, 0, 0, 0, 1087, 1088, 1089, 0, 0, 0, + 0, 1090, 0, 1091, 0, 0, 0, 0, 1092, 1093, + 0, 1094, 1095, 1251, 1046, 819, 1047, 1048, 1049, 1050, + 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 1253, 0, 1052, + 0, 0, 1254, 130, 131, 0, 132, 133, 134, 1255, + 136, 137, 138, 139, 1053, 1256, 1054, 1055, 0, 144, + 145, 146, 147, 148, 149, 1056, 789, 150, 151, 152, + 153, 1057, 1058, 156, 0, 157, 158, 159, 160, 790, + 0, 1257, 0, 1258, 164, 165, 166, 167, 168, 1259, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 1260, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 1060, 191, 192, 1061, 194, 1062, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 1063, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 1064, 222, 223, 224, 225, 226, 227, 792, + 1065, 229, 0, 230, 231, 1066, 233, 0, 234, 0, + 235, 1262, 0, 1263, 238, 239, 1264, 1265, 242, 0, + 243, 0, 1067, 1068, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 1266, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 1267, + 269, 270, 271, 272, 273, 274, 1069, 1070, 0, 1071, + 0, 278, 1268, 1269, 281, 1270, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 1271, 291, 1272, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 1273, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 1073, 1274, + 1074, 325, 326, 327, 328, 1075, 329, 330, 1275, 332, + 1076, 794, 334, 1077, 336, 337, 338, 0, 339, 340, + 0, 0, 1078, 342, 343, 0, 0, 344, 345, 346, + 1276, 348, 1277, 796, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 797, 1278, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 1079, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 1279, 404, 405, 406, 1080, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 1280, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 1281, 431, 432, 1081, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 1282, 448, 799, 0, 0, 450, 451, 0, + 452, 1283, 454, 455, 456, 457, 458, 0, 459, 1082, + 1083, 0, 0, 462, 463, 800, 465, 801, 1084, 467, + 468, 1284, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 1085, 0, 489, 1286, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 1086, 0, 0, 0, 0, 0, 0, 1087, 1088, + 1089, 0, 0, 0, 0, 1090, 0, 1091, 3089, 0, + 0, 0, 1092, 1093, 0, 1094, 1095, 1251, 1046, 819, + 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 1253, 0, 1052, 0, 0, 1254, 130, 131, 0, + 132, 133, 134, 1255, 136, 137, 138, 139, 1053, 1256, + 1054, 1055, 0, 144, 145, 146, 147, 148, 149, 1056, + 789, 150, 151, 152, 153, 1057, 1058, 156, 0, 157, + 158, 159, 160, 790, 0, 1257, 0, 1258, 164, 165, + 166, 167, 168, 1259, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 1260, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 1060, 191, 192, 1061, + 194, 1062, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 1063, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 1064, 222, 223, 224, + 225, 226, 227, 792, 1065, 229, 0, 230, 231, 1066, + 233, 0, 234, 0, 235, 1262, 0, 1263, 238, 239, + 1264, 1265, 242, 0, 243, 0, 1067, 1068, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 1266, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 1267, 269, 270, 271, 272, 273, 274, + 1069, 1070, 0, 1071, 0, 278, 1268, 1269, 281, 1270, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 1271, + 291, 1272, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 1273, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 1073, 1274, 1074, 325, 326, 327, 328, 1075, + 329, 330, 1275, 332, 1076, 794, 334, 1077, 336, 337, + 338, 0, 339, 340, 0, 0, 1078, 342, 343, 0, + 0, 344, 345, 346, 1276, 348, 1277, 796, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 797, 1278, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 1079, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 1279, 404, + 405, 406, 1080, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 1280, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 1281, 431, + 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 1282, 448, 799, 0, + 0, 450, 451, 0, 452, 1283, 454, 455, 456, 457, + 458, 0, 459, 1082, 1083, 0, 0, 462, 463, 800, + 465, 801, 1084, 467, 468, 1284, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 1085, 0, + 489, 1286, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 1086, 0, 0, 0, 0, + 0, 0, 1087, 1088, 1089, 0, 0, 0, 0, 1090, + 0, 1091, 0, 0, 0, 0, 1092, 1093, 0, 1094, + 1095, 117, 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 1701, 126, + 127, 128, 0, 0, 0, 0, 0, 1052, 0, 0, + 129, 130, 131, 0, 132, 133, 134, 135, 136, 137, + 138, 139, 1053, 141, 1054, 1055, 0, 144, 145, 146, + 147, 148, 149, 1056, 789, 150, 151, 152, 153, 1057, + 1058, 156, 0, 157, 158, 159, 160, 790, 0, 791, + 0, 1059, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 1060, 191, 192, 1061, 194, 1062, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 1063, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 1064, 222, 223, 224, 225, 226, 227, 792, 1065, 229, + 0, 230, 231, 1066, 233, 0, 234, 0, 235, 236, + 0, 237, 238, 239, 240, 241, 242, 0, 243, 0, + 1067, 1068, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 268, 269, 270, + 271, 272, 273, 274, 1069, 1070, 0, 1071, 0, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 290, 291, 292, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 1069, 1265, 1070, 323, 324, 325, - 326, 1071, 327, 328, 1266, 330, 1072, 790, 332, 1073, - 334, 335, 336, 0, 337, 338, 0, 0, 1074, 340, - 341, 0, 0, 342, 343, 344, 1267, 346, 1268, 792, - 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 0, 0, 0, 0, 360, 361, 793, 1269, 364, - 365, 366, 367, 368, 369, 0, 370, 371, 372, 373, - 374, 375, 0, 376, 377, 378, 1075, 380, 381, 382, - 383, 0, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 0, 397, 398, 1270, 400, - 401, 402, 1076, 404, 405, 406, 407, 408, 409, 410, - 411, 412, 413, 414, 415, 416, 0, 1271, 417, 418, - 419, 420, 421, 422, 423, 424, 425, 0, 1272, 427, - 428, 1077, 430, 0, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 1273, 444, 795, 0, - 0, 446, 447, 0, 448, 1274, 450, 451, 452, 453, - 454, 0, 455, 1078, 1079, 0, 0, 458, 459, 796, - 461, 797, 1080, 463, 464, 1275, 466, 467, 468, 469, - 470, 0, 0, 471, 472, 473, 0, 474, 475, 476, - 477, 0, 478, 479, 480, 481, 482, 483, 1081, 0, - 485, 1277, 487, 488, 489, 490, 491, 492, 493, 0, - 0, 494, 0, 0, 495, 496, 497, 498, 499, 500, + 316, 317, 318, 319, 320, 321, 1073, 323, 1074, 325, + 326, 327, 328, 1075, 329, 330, 331, 332, 1076, 794, + 334, 1077, 336, 337, 338, 0, 339, 340, 0, 0, + 1078, 342, 343, 0, 0, 344, 345, 346, 347, 348, + 349, 796, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 797, + 365, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 1079, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 403, 404, 405, 406, 1080, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 430, 431, 432, 1081, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 447, 448, 799, 0, 0, 450, 451, 0, 452, 453, + 454, 455, 456, 457, 458, 0, 459, 1082, 1083, 0, + 0, 462, 463, 800, 465, 801, 1084, 467, 468, 802, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 1085, 0, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, - 511, 512, 513, 514, 515, 1082, 0, 0, 0, 0, - 0, 0, 1083, 1084, 1085, 0, 0, 0, 0, 1086, - 0, 1087, 3071, 0, 0, 0, 1088, 1089, 0, 1090, - 1091, 1242, 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 117, 118, 119, 120, 121, 122, 123, 124, 0, 125, - 126, 127, 0, 0, 0, 1244, 0, 1048, 0, 0, - 1245, 129, 130, 0, 131, 132, 133, 1246, 135, 136, - 137, 138, 1049, 1247, 1050, 1051, 0, 143, 144, 145, - 146, 147, 148, 1052, 785, 149, 150, 151, 152, 1053, - 1054, 155, 0, 156, 157, 158, 159, 786, 0, 1248, - 0, 1249, 163, 164, 165, 166, 167, 1250, 169, 170, - 171, 0, 172, 173, 174, 175, 176, 177, 0, 1251, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 1056, 190, 191, 1057, 193, 1058, 194, 0, 195, 196, - 197, 198, 199, 200, 0, 0, 201, 202, 203, 204, - 0, 0, 205, 206, 1059, 208, 209, 0, 210, 211, - 212, 0, 213, 214, 215, 0, 216, 217, 218, 219, - 1060, 221, 222, 223, 224, 225, 788, 1061, 227, 0, - 228, 229, 1062, 231, 0, 232, 0, 233, 1253, 0, - 1254, 236, 237, 1255, 1256, 240, 0, 241, 0, 1063, - 1064, 244, 245, 0, 246, 247, 248, 249, 250, 251, - 252, 1257, 254, 255, 256, 257, 0, 258, 259, 260, - 261, 262, 263, 264, 0, 265, 1258, 267, 268, 269, - 270, 271, 272, 1065, 1066, 0, 1067, 0, 276, 1259, - 1260, 279, 1261, 281, 282, 283, 284, 285, 286, 0, - 0, 287, 1262, 289, 1263, 0, 291, 292, 293, 294, - 295, 296, 297, 298, 1264, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 1069, 1265, 1070, 323, 324, - 325, 326, 1071, 327, 328, 1266, 330, 1072, 790, 332, - 1073, 334, 335, 336, 0, 337, 338, 0, 0, 1074, - 340, 341, 0, 0, 342, 343, 344, 1267, 346, 1268, - 792, 349, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 0, 0, 0, 0, 360, 361, 793, 1269, - 364, 365, 366, 367, 368, 369, 0, 370, 371, 372, - 373, 374, 375, 0, 376, 377, 378, 1075, 380, 381, - 382, 383, 0, 384, 385, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, 396, 0, 397, 398, 1270, - 400, 401, 402, 1076, 404, 405, 406, 407, 408, 409, - 410, 411, 412, 413, 414, 415, 416, 0, 1271, 417, - 418, 419, 420, 421, 422, 423, 424, 425, 0, 1272, - 427, 428, 1077, 430, 0, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 1273, 444, 795, - 0, 0, 446, 447, 0, 448, 1274, 450, 451, 452, - 453, 454, 0, 455, 1078, 1079, 0, 0, 458, 459, - 796, 461, 797, 1080, 463, 464, 1275, 466, 467, 468, - 469, 470, 0, 0, 471, 472, 473, 0, 474, 475, - 476, 477, 0, 478, 479, 480, 481, 482, 483, 1081, - 0, 485, 1277, 487, 488, 489, 490, 491, 492, 493, - 0, 0, 494, 0, 0, 495, 496, 497, 498, 499, - 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, - 510, 511, 512, 513, 514, 515, 1082, 0, 0, 0, - 0, 0, 0, 1083, 1084, 1085, 0, 0, 0, 0, - 1086, 0, 1087, 0, 0, 0, 0, 1088, 1089, 0, - 1090, 1091, 116, 1042, 815, 1043, 1044, 1045, 1046, 1047, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 117, 118, 119, 120, 121, 122, 123, 124, 1689, - 125, 126, 127, 0, 0, 0, 0, 0, 1048, 0, - 0, 128, 129, 130, 0, 131, 132, 133, 134, 135, - 136, 137, 138, 1049, 140, 1050, 1051, 0, 143, 144, - 145, 146, 147, 148, 1052, 785, 149, 150, 151, 152, - 1053, 1054, 155, 0, 156, 157, 158, 159, 786, 0, - 787, 0, 1055, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 0, 172, 173, 174, 175, 176, 177, 0, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 1056, 190, 191, 1057, 193, 1058, 194, 0, 195, - 196, 197, 198, 199, 200, 0, 0, 201, 202, 203, - 204, 0, 0, 205, 206, 1059, 208, 209, 0, 210, - 211, 212, 0, 213, 214, 215, 0, 216, 217, 218, - 219, 1060, 221, 222, 223, 224, 225, 788, 1061, 227, - 0, 228, 229, 1062, 231, 0, 232, 0, 233, 234, - 0, 235, 236, 237, 238, 239, 240, 0, 241, 0, - 1063, 1064, 244, 245, 0, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 0, 258, 259, - 260, 261, 262, 263, 264, 0, 265, 266, 267, 268, - 269, 270, 271, 272, 1065, 1066, 0, 1067, 0, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 0, 0, 287, 288, 289, 290, 0, 291, 292, 293, - 294, 295, 296, 297, 298, 1068, 300, 301, 302, 303, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 1086, + 0, 0, 0, 0, 0, 0, 1087, 1088, 1089, 0, + 0, 0, 0, 1090, 0, 1091, 0, 0, 0, 0, + 1092, 1093, 0, 1094, 1095, 117, 1716, 819, 1047, 1048, + 1049, 1717, 1051, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 1718, 126, 127, 128, 0, 0, 0, 0, + 0, 1052, 0, 0, 129, 130, 131, 0, 132, 133, + 134, 135, 136, 137, 138, 139, 1053, 141, 1054, 1055, + 0, 144, 145, 146, 147, 148, 149, 1056, 789, 150, + 151, 152, 153, 1057, 1058, 156, 0, 157, 158, 159, + 160, 790, 0, 791, 0, 1059, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 1060, 191, 192, 1061, 194, 1062, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 1063, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 1064, 222, 223, 224, 225, 226, + 227, 792, 1065, 229, 0, 230, 231, 1066, 233, 0, + 234, 0, 235, 236, 0, 237, 238, 239, 240, 241, + 242, 0, 243, 0, 1067, 1068, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 268, 269, 270, 271, 272, 273, 274, 1069, 1070, + 0, 1071, 0, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 290, 291, 292, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 1072, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 1073, 323, 1074, 325, 326, 327, 328, 1075, 329, 330, + 331, 332, 1076, 794, 334, 1077, 336, 337, 338, 0, + 339, 340, 0, 0, 1078, 342, 343, 0, 0, 344, + 345, 346, 347, 348, 349, 796, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 797, 365, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 1079, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 403, 404, 405, 406, + 1080, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 430, 431, 432, 1081, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 447, 448, 799, 0, 0, 450, + 451, 0, 452, 453, 454, 455, 456, 457, 458, 0, + 459, 1082, 1083, 0, 0, 462, 463, 800, 465, 801, + 1084, 467, 468, 802, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 1085, 0, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 1086, 0, 0, 0, 0, 0, 0, + 1087, 1088, 1089, 0, 0, 0, 0, 1090, 0, 1091, + 0, 0, 0, 0, 1092, 1093, 0, 1094, 1095, 117, + 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 1052, 0, 0, 129, 130, + 131, 0, 132, 133, 134, 135, 136, 137, 138, 139, + 1053, 141, 1054, 1055, 0, 144, 145, 146, 147, 148, + 149, 1056, 789, 150, 151, 152, 153, 1057, 1058, 156, + 0, 157, 158, 159, 160, 790, 0, 791, 0, 1059, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 1060, 191, + 192, 1061, 194, 1062, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 1063, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 1064, 222, + 223, 224, 225, 226, 227, 792, 1065, 229, 0, 230, + 231, 1066, 233, 0, 234, 0, 235, 236, 1435, 237, + 238, 239, 240, 241, 242, 0, 243, 0, 1067, 1068, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 268, 269, 270, 271, 272, + 273, 274, 1069, 1070, 0, 1071, 0, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 290, 291, 292, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 1073, 323, 1074, 325, 326, 327, + 328, 1075, 329, 330, 331, 332, 1076, 794, 334, 1077, + 336, 337, 338, 0, 339, 340, 0, 0, 1078, 342, + 343, 0, 0, 344, 345, 346, 347, 348, 349, 796, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 797, 365, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 1079, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 403, 404, 405, 406, 1080, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 430, 431, 432, 1081, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, + 799, 0, 0, 450, 451, 0, 452, 453, 454, 455, + 456, 457, 458, 0, 459, 1082, 1083, 0, 0, 462, + 463, 800, 465, 801, 1084, 467, 468, 802, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 1085, 0, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 1086, 0, 0, + 0, 0, 0, 0, 1087, 1088, 1089, 0, 0, 0, + 0, 1090, 0, 1091, 0, 0, 0, 0, 1092, 1093, + 0, 1094, 1095, 117, 1046, 819, 1047, 1048, 1049, 1050, + 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 1052, + 0, 0, 129, 130, 131, 0, 132, 133, 134, 135, + 136, 137, 138, 139, 1053, 141, 1054, 1055, 0, 144, + 145, 146, 147, 148, 149, 1056, 789, 150, 151, 152, + 153, 1057, 1058, 156, 0, 157, 158, 159, 160, 790, + 0, 791, 0, 1059, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 1060, 191, 192, 1061, 194, 1062, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 1063, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 1064, 222, 223, 224, 225, 226, 227, 792, + 1065, 229, 0, 230, 231, 1066, 233, 0, 234, 0, + 235, 236, 0, 237, 238, 239, 240, 241, 242, 0, + 243, 0, 1067, 1068, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 268, + 269, 270, 271, 272, 273, 274, 1069, 1070, 0, 1071, + 0, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 290, 291, 292, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 1069, 321, 1070, 323, - 324, 325, 326, 1071, 327, 328, 329, 330, 1072, 790, - 332, 1073, 334, 335, 336, 0, 337, 338, 0, 0, - 1074, 340, 341, 0, 0, 342, 343, 344, 345, 346, - 347, 792, 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 0, 0, 0, 0, 360, 361, 793, - 363, 364, 365, 366, 367, 368, 369, 0, 370, 371, - 372, 373, 374, 375, 0, 376, 377, 378, 1075, 380, - 381, 382, 383, 0, 384, 385, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 0, 397, 398, - 399, 400, 401, 402, 1076, 404, 405, 406, 407, 408, - 409, 410, 411, 412, 413, 414, 415, 416, 0, 0, - 417, 418, 419, 420, 421, 422, 423, 424, 425, 0, - 426, 427, 428, 1077, 430, 0, 431, 432, 433, 434, + 314, 315, 316, 317, 318, 319, 320, 321, 1073, 323, + 1074, 325, 326, 327, 328, 1075, 329, 330, 331, 332, + 1076, 794, 334, 1077, 336, 337, 338, 0, 339, 340, + 0, 0, 1078, 342, 343, 0, 0, 344, 345, 346, + 347, 348, 349, 796, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 797, 365, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 1079, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 403, 404, 405, 406, 1080, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 430, 431, 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, - 795, 0, 0, 446, 447, 0, 448, 449, 450, 451, - 452, 453, 454, 0, 455, 1078, 1079, 0, 0, 458, - 459, 796, 461, 797, 1080, 463, 464, 798, 466, 467, - 468, 469, 470, 0, 0, 471, 472, 473, 0, 474, - 475, 476, 477, 0, 478, 479, 480, 481, 482, 483, - 1081, 0, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 0, 0, 494, 0, 0, 495, 496, 497, 498, + 445, 446, 447, 448, 799, 0, 0, 450, 451, 0, + 452, 453, 454, 455, 456, 457, 458, 0, 459, 1082, + 1083, 0, 0, 462, 463, 800, 465, 801, 1084, 467, + 468, 802, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 1085, 0, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, - 509, 510, 511, 512, 513, 514, 515, 1082, 0, 0, - 0, 0, 0, 0, 1083, 1084, 1085, 0, 0, 0, - 0, 1086, 0, 1087, 0, 0, 0, 0, 1088, 1089, - 0, 1090, 1091, 116, 1704, 815, 1043, 1044, 1045, 1705, - 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 117, 118, 119, 120, 121, 122, 123, 124, - 1706, 125, 126, 127, 0, 0, 0, 0, 0, 1048, - 0, 0, 128, 129, 130, 0, 131, 132, 133, 134, - 135, 136, 137, 138, 1049, 140, 1050, 1051, 0, 143, - 144, 145, 146, 147, 148, 1052, 785, 149, 150, 151, - 152, 1053, 1054, 155, 0, 156, 157, 158, 159, 786, - 0, 787, 0, 1055, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 0, 172, 173, 174, 175, 176, 177, - 0, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 1056, 190, 191, 1057, 193, 1058, 194, 0, - 195, 196, 197, 198, 199, 200, 0, 0, 201, 202, - 203, 204, 0, 0, 205, 206, 1059, 208, 209, 0, - 210, 211, 212, 0, 213, 214, 215, 0, 216, 217, - 218, 219, 1060, 221, 222, 223, 224, 225, 788, 1061, - 227, 0, 228, 229, 1062, 231, 0, 232, 0, 233, - 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, - 0, 1063, 1064, 244, 245, 0, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 0, 258, - 259, 260, 261, 262, 263, 264, 0, 265, 266, 267, - 268, 269, 270, 271, 272, 1065, 1066, 0, 1067, 0, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 287, 288, 289, 290, 0, 291, 292, - 293, 294, 295, 296, 297, 298, 1068, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 1069, 321, 1070, - 323, 324, 325, 326, 1071, 327, 328, 329, 330, 1072, - 790, 332, 1073, 334, 335, 336, 0, 337, 338, 0, - 0, 1074, 340, 341, 0, 0, 342, 343, 344, 345, - 346, 347, 792, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 0, 0, 0, 0, 360, 361, - 793, 363, 364, 365, 366, 367, 368, 369, 0, 370, - 371, 372, 373, 374, 375, 0, 376, 377, 378, 1075, - 380, 381, 382, 383, 0, 384, 385, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 0, 397, - 398, 399, 400, 401, 402, 1076, 404, 405, 406, 407, - 408, 409, 410, 411, 412, 413, 414, 415, 416, 0, - 0, 417, 418, 419, 420, 421, 422, 423, 424, 425, - 0, 426, 427, 428, 1077, 430, 0, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 795, 0, 0, 446, 447, 0, 448, 449, 450, - 451, 452, 453, 454, 0, 455, 1078, 1079, 0, 0, - 458, 459, 796, 461, 797, 1080, 463, 464, 798, 466, - 467, 468, 469, 470, 0, 0, 471, 472, 473, 0, - 474, 475, 476, 477, 0, 478, 479, 480, 481, 482, - 483, 1081, 0, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 0, 0, 494, 0, 0, 495, 496, 497, - 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, - 508, 509, 510, 511, 512, 513, 514, 515, 1082, 0, - 0, 0, 0, 0, 0, 1083, 1084, 1085, 0, 0, - 0, 0, 1086, 0, 1087, 0, 0, 0, 0, 1088, - 1089, 0, 1090, 1091, 116, 1042, 815, 1043, 1044, 1045, - 1046, 1047, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 1048, 0, 0, 128, 129, 130, 0, 131, 132, 133, - 134, 135, 136, 137, 138, 1049, 140, 1050, 1051, 0, - 143, 144, 145, 146, 147, 148, 1052, 785, 149, 150, - 151, 152, 1053, 1054, 155, 0, 156, 157, 158, 159, - 786, 0, 787, 0, 1055, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 1056, 190, 191, 1057, 193, 1058, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 1059, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 1060, 221, 222, 223, 224, 225, 788, - 1061, 227, 0, 228, 229, 1062, 231, 0, 232, 0, - 233, 234, 1424, 235, 236, 237, 238, 239, 240, 0, - 241, 0, 1063, 1064, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 266, - 267, 268, 269, 270, 271, 272, 1065, 1066, 0, 1067, - 0, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 288, 289, 290, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 1068, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 1069, 321, - 1070, 323, 324, 325, 326, 1071, 327, 328, 329, 330, - 1072, 790, 332, 1073, 334, 335, 336, 0, 337, 338, - 0, 0, 1074, 340, 341, 0, 0, 342, 343, 344, - 345, 346, 347, 792, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 793, 363, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 1075, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 1076, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 426, 427, 428, 1077, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, 444, 795, 0, 0, 446, 447, 0, 448, 449, - 450, 451, 452, 453, 454, 0, 455, 1078, 1079, 0, - 0, 458, 459, 796, 461, 797, 1080, 463, 464, 798, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 1081, 0, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 1082, - 0, 0, 0, 0, 0, 0, 1083, 1084, 1085, 0, - 0, 0, 0, 1086, 0, 1087, 0, 0, 0, 0, - 1088, 1089, 0, 1090, 1091, 116, 1042, 815, 1043, 1044, - 1045, 1046, 1047, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 117, 118, 119, 120, 121, 122, - 123, 124, 0, 125, 126, 127, 0, 0, 0, 0, - 0, 1048, 0, 0, 128, 129, 130, 0, 131, 132, - 133, 134, 135, 136, 137, 138, 1049, 140, 1050, 1051, - 0, 143, 144, 145, 146, 147, 148, 1052, 785, 149, - 150, 151, 152, 1053, 1054, 155, 0, 156, 157, 158, - 159, 786, 0, 787, 0, 1055, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 0, 172, 173, 174, 175, - 176, 177, 0, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 1056, 190, 191, 1057, 193, 1058, - 194, 0, 195, 196, 197, 198, 199, 200, 0, 0, - 201, 202, 203, 204, 0, 0, 205, 206, 1059, 208, - 209, 0, 210, 211, 212, 0, 213, 214, 215, 0, - 216, 217, 218, 219, 1060, 221, 222, 223, 224, 225, - 788, 1061, 227, 0, 228, 229, 1062, 231, 0, 232, - 0, 233, 234, 0, 235, 236, 237, 238, 239, 240, - 0, 241, 0, 1063, 1064, 244, 245, 0, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 0, 258, 259, 260, 261, 262, 263, 264, 0, 265, - 266, 267, 268, 269, 270, 271, 272, 1065, 1066, 0, - 1067, 0, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 0, 0, 287, 288, 289, 290, 0, - 291, 292, 293, 294, 295, 296, 297, 298, 1068, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 1069, - 321, 1070, 323, 324, 325, 326, 1071, 327, 328, 329, - 330, 1072, 790, 332, 1073, 334, 335, 336, 0, 337, - 338, 0, 0, 1074, 340, 341, 0, 0, 342, 343, - 344, 345, 346, 347, 792, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 0, 0, 0, 0, - 360, 361, 793, 363, 364, 365, 366, 367, 368, 369, - 0, 370, 371, 372, 373, 374, 375, 0, 376, 377, - 378, 1075, 380, 381, 382, 383, 0, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 0, 397, 398, 399, 400, 401, 402, 1076, 404, 405, - 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 0, 0, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 0, 426, 427, 428, 1077, 430, 0, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, 444, 795, 0, 0, 446, 447, 0, 448, - 449, 450, 451, 452, 453, 454, 0, 455, 1078, 1079, - 0, 0, 458, 459, 796, 461, 797, 1080, 463, 464, - 798, 466, 467, 468, 469, 470, 0, 0, 471, 472, - 473, 0, 474, 475, 476, 477, 0, 478, 479, 480, - 481, 482, 483, 1081, 0, 485, 486, 487, 488, 489, - 490, 491, 492, 493, 0, 0, 494, 0, 0, 495, - 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, - 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, - 1082, 0, 0, 0, 0, 0, 0, 1083, 1084, 1085, - 0, 0, 0, 0, 1086, 0, 1087, 2052, 0, 0, - 0, 1088, 1089, 0, 1090, 1091, 116, 1042, 815, 1043, - 1044, 1045, 1046, 1047, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 117, 118, 119, 120, 121, - 122, 123, 124, 0, 125, 126, 127, 0, 0, 0, - 0, 0, 1048, 0, 0, 128, 129, 130, 0, 131, - 132, 133, 134, 135, 136, 137, 138, 1049, 140, 1050, - 1051, 0, 143, 144, 145, 146, 147, 148, 1052, 785, - 149, 150, 151, 152, 1053, 1054, 155, 0, 156, 157, - 158, 159, 786, 0, 787, 0, 1055, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 0, 172, 173, 174, - 175, 176, 177, 0, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 1056, 190, 191, 1057, 193, - 1058, 194, 0, 195, 196, 197, 198, 199, 200, 0, - 0, 201, 202, 203, 204, 0, 0, 205, 206, 1059, - 208, 209, 0, 210, 211, 212, 0, 213, 214, 215, - 0, 216, 217, 218, 219, 1060, 221, 222, 223, 224, - 225, 788, 1061, 227, 0, 228, 229, 1062, 231, 0, - 232, 0, 233, 234, 0, 235, 236, 237, 238, 239, - 240, 0, 241, 0, 1063, 1064, 244, 245, 0, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 0, 258, 259, 260, 261, 262, 263, 264, 0, - 265, 266, 267, 268, 269, 270, 271, 272, 1065, 1066, - 0, 1067, 0, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 0, 0, 287, 288, 289, 290, - 0, 291, 292, 293, 294, 295, 296, 297, 298, 1068, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 1086, 0, 0, 0, 0, 0, 0, 1087, 1088, + 1089, 0, 0, 0, 0, 1090, 0, 1091, 2062, 0, + 0, 0, 1092, 1093, 0, 1094, 1095, 117, 1046, 819, + 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 1052, 0, 0, 129, 130, 131, 0, + 132, 133, 134, 135, 136, 137, 138, 139, 1053, 141, + 1054, 1055, 0, 144, 145, 146, 147, 148, 149, 1056, + 789, 150, 151, 152, 153, 1057, 1058, 156, 0, 157, + 158, 159, 160, 790, 0, 791, 0, 1059, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 1060, 191, 192, 1061, + 194, 1062, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 1063, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 1064, 222, 223, 224, + 225, 226, 227, 792, 1065, 229, 0, 230, 231, 1066, + 233, 0, 234, 0, 235, 236, 0, 237, 238, 239, + 240, 241, 242, 0, 243, 0, 1067, 1068, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 268, 269, 270, 271, 272, 273, 274, + 1069, 1070, 0, 1071, 0, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 290, + 291, 292, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 1069, 321, 1070, 323, 324, 325, 326, 1071, 327, 328, - 329, 330, 1072, 790, 332, 1073, 334, 335, 336, 0, - 337, 338, 0, 0, 1074, 340, 341, 0, 0, 342, - 343, 344, 345, 346, 347, 792, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 0, 0, 0, - 0, 360, 361, 793, 363, 364, 365, 366, 367, 368, - 369, 0, 370, 371, 372, 373, 374, 375, 0, 376, - 377, 378, 1075, 380, 381, 382, 383, 0, 384, 385, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 0, 397, 398, 399, 400, 401, 402, 1076, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 0, 0, 417, 418, 419, 420, 421, 422, - 423, 424, 425, 0, 426, 427, 428, 1077, 430, 0, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 443, 444, 795, 0, 0, 446, 447, 2681, - 448, 449, 450, 451, 452, 453, 454, 0, 455, 1078, - 1079, 0, 0, 458, 459, 796, 461, 797, 1080, 463, - 464, 798, 466, 467, 468, 469, 470, 0, 0, 471, - 472, 473, 0, 474, 475, 476, 477, 0, 478, 479, - 480, 481, 482, 483, 1081, 0, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 0, 0, 494, 0, 0, - 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, + 320, 321, 1073, 323, 1074, 325, 326, 327, 328, 1075, + 329, 330, 331, 332, 1076, 794, 334, 1077, 336, 337, + 338, 0, 339, 340, 0, 0, 1078, 342, 343, 0, + 0, 344, 345, 346, 347, 348, 349, 796, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 797, 365, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 1079, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 403, 404, + 405, 406, 1080, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 430, 431, + 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 799, 0, + 0, 450, 451, 2696, 452, 453, 454, 455, 456, 457, + 458, 0, 459, 1082, 1083, 0, 0, 462, 463, 800, + 465, 801, 1084, 467, 468, 802, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 1085, 0, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, - 515, 1082, 0, 0, 0, 0, 0, 0, 1083, 1084, - 1085, 0, 0, 0, 0, 1086, 0, 1087, 0, 0, - 0, 0, 1088, 1089, 0, 1090, 1091, 116, 1042, 815, - 1043, 1044, 1045, 1046, 1047, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 117, 118, 119, 120, - 121, 122, 123, 124, 0, 125, 126, 127, 0, 0, - 0, 0, 0, 1048, 0, 0, 128, 129, 130, 0, - 131, 132, 133, 134, 135, 136, 137, 138, 1049, 140, - 1050, 1051, 0, 143, 144, 145, 146, 147, 148, 1052, - 785, 149, 150, 151, 152, 1053, 1054, 155, 0, 156, - 157, 158, 159, 786, 0, 787, 0, 1055, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 0, 172, 173, - 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, - 183, 184, 185, 186, 187, 188, 1056, 190, 191, 1057, - 193, 1058, 194, 0, 195, 196, 197, 198, 199, 200, - 0, 0, 201, 202, 203, 204, 0, 0, 205, 206, - 1059, 208, 209, 0, 210, 211, 212, 0, 213, 214, - 215, 0, 216, 217, 218, 219, 1060, 221, 222, 223, - 224, 225, 788, 1061, 227, 0, 228, 229, 1062, 231, - 0, 232, 0, 233, 234, 0, 235, 236, 237, 238, - 239, 240, 0, 241, 0, 1063, 1064, 244, 245, 0, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 0, 258, 259, 260, 261, 262, 263, 264, - 0, 265, 266, 267, 268, 269, 270, 271, 272, 1065, - 1066, 0, 1067, 0, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 0, 0, 287, 288, 289, - 290, 0, 291, 292, 293, 294, 295, 296, 297, 298, - 1068, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 1069, 321, 1070, 323, 324, 325, 326, 1071, 327, - 328, 329, 330, 1072, 790, 332, 1073, 334, 335, 336, - 0, 337, 338, 0, 0, 1074, 340, 341, 0, 0, - 342, 343, 344, 345, 346, 347, 792, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 0, 0, - 0, 0, 360, 361, 793, 363, 364, 365, 366, 367, - 368, 369, 0, 370, 371, 372, 373, 374, 375, 0, - 376, 377, 378, 1075, 380, 381, 382, 383, 0, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 0, 397, 398, 399, 400, 401, 402, 1076, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, - 414, 415, 416, 0, 0, 417, 418, 419, 420, 421, - 422, 423, 424, 425, 0, 426, 427, 428, 1077, 430, - 0, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, 444, 795, 0, 0, 446, 447, - 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, - 1078, 1079, 0, 0, 458, 459, 796, 461, 797, 1080, - 463, 464, 798, 466, 467, 468, 469, 470, 0, 0, - 471, 472, 473, 0, 474, 475, 476, 477, 0, 478, - 479, 480, 481, 482, 483, 1081, 0, 485, 486, 487, - 488, 489, 490, 491, 492, 493, 0, 2800, 494, 0, - 0, 495, 496, 497, 498, 499, 500, 501, 502, 503, - 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, - 514, 515, 1082, 0, 0, 0, 0, 0, 0, 1083, - 1084, 1085, 0, 0, 0, 0, 1086, 0, 1087, 0, - 0, 0, 0, 1088, 1089, 0, 1090, 1091, 116, 1042, - 815, 1043, 1044, 1045, 1046, 1047, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 117, 118, 119, - 120, 121, 122, 123, 124, 3015, 125, 126, 127, 0, - 0, 0, 0, 0, 1048, 0, 0, 128, 129, 130, - 0, 131, 132, 133, 134, 135, 136, 137, 138, 1049, - 140, 1050, 1051, 0, 143, 144, 145, 146, 147, 148, - 1052, 785, 149, 150, 151, 152, 1053, 1054, 155, 0, - 156, 157, 158, 159, 786, 0, 787, 0, 1055, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 0, 172, - 173, 174, 175, 176, 177, 0, 178, 179, 3016, 181, - 182, 183, 184, 185, 186, 187, 188, 1056, 190, 191, - 1057, 193, 1058, 194, 0, 195, 196, 197, 198, 199, - 200, 0, 0, 201, 202, 203, 204, 0, 0, 205, - 206, 1059, 208, 209, 0, 210, 211, 212, 0, 213, - 214, 215, 0, 216, 217, 218, 219, 1060, 221, 222, - 223, 224, 225, 788, 1061, 227, 0, 228, 229, 1062, - 231, 0, 232, 0, 233, 234, 0, 235, 236, 237, - 238, 239, 240, 0, 241, 0, 3017, 1064, 244, 245, - 0, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 0, 258, 259, 260, 261, 262, 263, - 264, 0, 265, 266, 267, 268, 269, 270, 271, 272, - 1065, 1066, 0, 1067, 0, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 0, 0, 287, 288, - 289, 290, 0, 291, 292, 293, 294, 295, 296, 297, - 298, 1068, 300, 301, 302, 303, 304, 305, 306, 307, + 515, 516, 517, 518, 519, 1086, 0, 0, 0, 0, + 0, 0, 1087, 1088, 1089, 0, 0, 0, 0, 1090, + 0, 1091, 0, 0, 0, 0, 1092, 1093, 0, 1094, + 1095, 117, 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 1052, 0, 0, + 129, 130, 131, 0, 132, 133, 134, 135, 136, 137, + 138, 139, 1053, 141, 1054, 1055, 0, 144, 145, 146, + 147, 148, 149, 1056, 789, 150, 151, 152, 153, 1057, + 1058, 156, 0, 157, 158, 159, 160, 790, 0, 791, + 0, 1059, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 1060, 191, 192, 1061, 194, 1062, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 1063, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 1064, 222, 223, 224, 225, 226, 227, 792, 1065, 229, + 0, 230, 231, 1066, 233, 0, 234, 0, 235, 236, + 0, 237, 238, 239, 240, 241, 242, 0, 243, 0, + 1067, 1068, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 268, 269, 270, + 271, 272, 273, 274, 1069, 1070, 0, 1071, 0, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 290, 291, 292, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 1073, 323, 1074, 325, + 326, 327, 328, 1075, 329, 330, 331, 332, 1076, 794, + 334, 1077, 336, 337, 338, 0, 339, 340, 0, 0, + 1078, 342, 343, 0, 0, 344, 345, 346, 347, 348, + 349, 796, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 797, + 365, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 1079, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 403, 404, 405, 406, 1080, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 430, 431, 432, 1081, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 447, 448, 799, 0, 0, 450, 451, 0, 452, 453, + 454, 455, 456, 457, 458, 0, 459, 1082, 1083, 0, + 0, 462, 463, 800, 465, 801, 1084, 467, 468, 802, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 1085, 0, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 0, 2818, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 1086, + 0, 0, 0, 0, 0, 0, 1087, 1088, 1089, 0, + 0, 0, 0, 1090, 0, 1091, 0, 0, 0, 0, + 1092, 1093, 0, 1094, 1095, 117, 1046, 819, 1047, 1048, + 1049, 1050, 1051, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 3033, 126, 127, 128, 0, 0, 0, 0, + 0, 1052, 0, 0, 129, 130, 131, 0, 132, 133, + 134, 135, 136, 137, 138, 139, 1053, 141, 1054, 1055, + 0, 144, 145, 146, 147, 148, 149, 1056, 789, 150, + 151, 152, 153, 1057, 1058, 156, 0, 157, 158, 159, + 160, 790, 0, 791, 0, 1059, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 179, 180, 3034, 182, 183, 184, 185, + 186, 187, 188, 189, 1060, 191, 192, 1061, 194, 1062, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 1063, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 1064, 222, 223, 224, 225, 226, + 227, 792, 1065, 229, 0, 230, 231, 1066, 233, 0, + 234, 0, 235, 236, 0, 237, 238, 239, 240, 241, + 242, 0, 243, 0, 3035, 1068, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 268, 269, 270, 271, 272, 273, 274, 1069, 1070, + 0, 1071, 0, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 290, 291, 292, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 1072, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 1073, 323, 1074, 325, 326, 327, 328, 1075, 329, 330, + 331, 332, 1076, 794, 334, 1077, 336, 337, 338, 0, + 339, 340, 0, 0, 1078, 342, 343, 0, 0, 344, + 345, 346, 347, 348, 349, 796, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 797, 365, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 1079, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 403, 404, 405, 3036, + 1080, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 430, 431, 432, 1081, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 447, 448, 799, 0, 0, 450, + 451, 0, 452, 453, 454, 455, 456, 457, 458, 0, + 459, 1082, 1083, 0, 0, 462, 463, 800, 465, 801, + 1084, 467, 468, 802, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 1085, 0, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 1086, 0, 0, 0, 0, 0, 0, + 1087, 1088, 1089, 0, 0, 0, 0, 1090, 0, 3037, + 0, 0, 0, 0, 1092, 1093, 0, 1094, 1095, 117, + 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 1052, 0, 0, 129, 130, + 131, 0, 132, 133, 134, 135, 136, 137, 138, 139, + 1053, 141, 1054, 1055, 0, 144, 145, 146, 147, 148, + 149, 1056, 789, 150, 151, 152, 153, 1057, 1058, 156, + 0, 157, 158, 159, 160, 790, 0, 791, 0, 1059, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 1060, 191, + 192, 1061, 194, 1062, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 1063, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 1064, 222, + 223, 224, 225, 226, 227, 792, 1065, 229, 0, 230, + 231, 1066, 233, 0, 234, 0, 235, 236, 0, 237, + 238, 239, 240, 241, 242, 0, 243, 0, 1067, 1068, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 268, 269, 270, 271, 272, + 273, 274, 1069, 1070, 0, 1071, 0, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 290, 291, 292, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 1069, 321, 1070, 323, 324, 325, 326, 1071, - 327, 328, 329, 330, 1072, 790, 332, 1073, 334, 335, - 336, 0, 337, 338, 0, 0, 1074, 340, 341, 0, - 0, 342, 343, 344, 345, 346, 347, 792, 349, 350, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 0, - 0, 0, 0, 360, 361, 793, 363, 364, 365, 366, - 367, 368, 369, 0, 370, 371, 372, 373, 374, 375, - 0, 376, 377, 378, 1075, 380, 381, 382, 383, 0, - 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 0, 397, 398, 399, 400, 401, 3018, - 1076, 404, 405, 406, 407, 408, 409, 410, 411, 412, - 413, 414, 415, 416, 0, 0, 417, 418, 419, 420, - 421, 422, 423, 424, 425, 0, 426, 427, 428, 1077, - 430, 0, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 443, 444, 795, 0, 0, 446, - 447, 0, 448, 449, 450, 451, 452, 453, 454, 0, - 455, 1078, 1079, 0, 0, 458, 459, 796, 461, 797, - 1080, 463, 464, 798, 466, 467, 468, 469, 470, 0, - 0, 471, 472, 473, 0, 474, 475, 476, 477, 0, - 478, 479, 480, 481, 482, 483, 1081, 0, 485, 486, - 487, 488, 489, 490, 491, 492, 493, 0, 0, 494, - 0, 0, 495, 496, 497, 498, 499, 500, 501, 502, + 318, 319, 320, 321, 1073, 323, 1074, 325, 326, 327, + 328, 1075, 329, 330, 331, 332, 1076, 794, 334, 1077, + 336, 337, 338, 0, 339, 340, 0, 0, 1078, 342, + 343, 0, 0, 344, 345, 346, 347, 348, 349, 796, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 797, 365, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 1079, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 403, 404, 405, 406, 1080, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 430, 431, 432, 1081, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, + 799, 0, 0, 450, 451, 3184, 452, 453, 454, 455, + 456, 457, 458, 0, 459, 1082, 1083, 0, 0, 462, + 463, 800, 465, 801, 1084, 467, 468, 802, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 1085, 0, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, - 513, 514, 515, 1082, 0, 0, 0, 0, 0, 0, - 1083, 1084, 1085, 0, 0, 0, 0, 1086, 0, 3019, - 0, 0, 0, 0, 1088, 1089, 0, 1090, 1091, 116, - 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 1048, 0, 0, 128, 129, - 130, 0, 131, 132, 133, 134, 135, 136, 137, 138, - 1049, 140, 1050, 1051, 0, 143, 144, 145, 146, 147, - 148, 1052, 785, 149, 150, 151, 152, 1053, 1054, 155, - 0, 156, 157, 158, 159, 786, 0, 787, 0, 1055, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 1056, 190, - 191, 1057, 193, 1058, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 1059, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 1060, 221, - 222, 223, 224, 225, 788, 1061, 227, 0, 228, 229, - 1062, 231, 0, 232, 0, 233, 234, 0, 235, 236, - 237, 238, 239, 240, 0, 241, 0, 1063, 1064, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 266, 267, 268, 269, 270, 271, - 272, 1065, 1066, 0, 1067, 0, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 288, 289, 290, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 1068, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 1069, 321, 1070, 323, 324, 325, 326, - 1071, 327, 328, 329, 330, 1072, 790, 332, 1073, 334, - 335, 336, 0, 337, 338, 0, 0, 1074, 340, 341, - 0, 0, 342, 343, 344, 345, 346, 347, 792, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 793, 363, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 1075, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 1076, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 426, 427, 428, - 1077, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 795, 0, 0, - 446, 447, 3167, 448, 449, 450, 451, 452, 453, 454, - 0, 455, 1078, 1079, 0, 0, 458, 459, 796, 461, - 797, 1080, 463, 464, 798, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 1081, 0, 485, - 486, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 1082, 0, 0, 0, 0, 0, - 0, 1083, 1084, 1085, 0, 0, 0, 0, 1086, 0, - 1087, 0, 0, 0, 0, 1088, 1089, 0, 1090, 1091, - 116, 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, - 118, 119, 120, 121, 122, 123, 124, 0, 125, 126, - 127, 0, 0, 0, 0, 0, 1048, 0, 0, 128, - 129, 130, 0, 131, 132, 133, 134, 135, 136, 137, - 138, 1049, 140, 1050, 1051, 0, 143, 144, 145, 146, - 147, 148, 1052, 785, 149, 150, 151, 152, 1053, 1054, - 155, 0, 156, 157, 158, 159, 786, 0, 787, 0, - 1055, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 0, 172, 173, 174, 175, 176, 177, 0, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 1056, - 190, 191, 1057, 193, 1058, 194, 0, 195, 196, 197, - 198, 199, 200, 0, 0, 201, 202, 203, 204, 0, - 0, 205, 206, 1059, 208, 209, 0, 210, 211, 212, - 0, 213, 214, 215, 0, 216, 217, 218, 219, 1060, - 221, 222, 223, 224, 225, 788, 1061, 227, 0, 228, - 229, 1062, 231, 0, 232, 0, 233, 234, 0, 235, - 236, 237, 238, 239, 240, 0, 241, 0, 1063, 1064, - 244, 245, 0, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 0, 258, 259, 260, 261, - 262, 263, 264, 0, 265, 266, 267, 268, 269, 270, - 271, 272, 1065, 1066, 0, 1067, 0, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, - 287, 288, 289, 290, 0, 291, 292, 293, 294, 295, - 296, 297, 298, 1068, 300, 301, 302, 303, 304, 305, + 513, 514, 515, 516, 517, 518, 519, 1086, 0, 0, + 0, 0, 0, 0, 1087, 1088, 1089, 0, 0, 0, + 0, 1090, 0, 1091, 0, 0, 0, 0, 1092, 1093, + 0, 1094, 1095, 117, 1046, 819, 1047, 1048, 1049, 1050, + 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 1052, + 0, 0, 129, 130, 131, 0, 132, 133, 134, 135, + 136, 137, 138, 139, 1053, 141, 1054, 1055, 0, 144, + 145, 146, 147, 148, 149, 1056, 789, 150, 151, 152, + 153, 1057, 1058, 156, 0, 157, 158, 159, 160, 790, + 0, 791, 0, 1059, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 1060, 191, 192, 1061, 194, 1062, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 1063, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 1064, 222, 223, 224, 225, 226, 227, 792, + 1065, 229, 0, 230, 231, 1066, 233, 0, 234, 0, + 235, 236, 0, 237, 238, 239, 240, 241, 242, 0, + 243, 0, 1067, 1068, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 268, + 269, 270, 271, 272, 273, 274, 1069, 1070, 0, 1071, + 0, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 290, 291, 292, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 1072, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 1073, 323, + 1074, 325, 326, 327, 328, 1075, 329, 330, 331, 332, + 1076, 794, 334, 1077, 336, 337, 338, 0, 339, 340, + 0, 0, 1078, 342, 343, 0, 0, 344, 345, 346, + 347, 348, 349, 796, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 797, 365, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 1079, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 403, 404, 405, 406, 1080, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 430, 431, 432, 1081, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 447, 448, 799, 0, 0, 450, 451, 3322, + 452, 453, 454, 455, 456, 457, 458, 0, 459, 1082, + 1083, 0, 0, 462, 463, 800, 465, 801, 1084, 467, + 468, 802, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 1085, 0, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 1086, 0, 0, 0, 0, 0, 0, 1087, 1088, + 1089, 0, 0, 0, 0, 1090, 0, 1091, 0, 0, + 0, 0, 1092, 1093, 0, 1094, 1095, 117, 1046, 819, + 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 1052, 0, 0, 129, 130, 131, 0, + 132, 133, 134, 135, 136, 137, 138, 139, 1053, 141, + 1054, 1055, 0, 144, 145, 146, 147, 148, 149, 1056, + 789, 150, 151, 152, 153, 1057, 1058, 156, 0, 157, + 158, 159, 160, 790, 0, 791, 0, 1059, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 1060, 191, 192, 1061, + 194, 1062, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 1063, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 1064, 222, 223, 224, + 225, 226, 227, 792, 1065, 229, 0, 230, 231, 1066, + 233, 0, 234, 0, 235, 236, 0, 237, 238, 239, + 240, 241, 242, 0, 243, 0, 1067, 1068, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 268, 269, 270, 271, 272, 273, 274, + 1069, 1070, 0, 1071, 0, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 290, + 291, 292, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 1073, 323, 1074, 325, 326, 327, 328, 1075, + 329, 330, 331, 332, 1076, 794, 334, 1077, 336, 337, + 338, 0, 339, 340, 0, 0, 1078, 342, 343, 0, + 0, 344, 345, 346, 347, 348, 349, 796, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 797, 365, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 1079, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 403, 404, + 405, 406, 1080, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 430, 431, + 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 799, 0, + 0, 450, 451, 0, 452, 453, 454, 455, 456, 457, + 458, 0, 459, 1082, 1083, 0, 0, 462, 463, 800, + 465, 801, 1084, 467, 468, 802, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 1085, 0, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 1086, 0, 0, 0, 0, + 0, 0, 1087, 1088, 1089, 0, 0, 0, 0, 1090, + 0, 1091, 0, 0, 0, 0, 1092, 1093, 0, 1094, + 1095, 117, 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 1052, 0, 0, + 129, 130, 131, 0, 132, 133, 134, 135, 136, 137, + 138, 139, 1053, 141, 1054, 1055, 0, 144, 145, 146, + 147, 148, 149, 1056, 789, 150, 151, 152, 153, 1057, + 1058, 156, 0, 157, 158, 159, 160, 790, 0, 791, + 0, 1059, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 1060, 191, 192, 1061, 194, 1062, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 1063, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 1064, 222, 223, 224, 225, 226, 227, 792, 1065, 229, + 0, 230, 231, 1066, 233, 0, 234, 0, 235, 236, + 0, 237, 238, 239, 240, 241, 242, 0, 243, 0, + 1067, 1068, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 268, 269, 270, + 271, 272, 273, 274, 1069, 1070, 0, 1071, 0, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 290, 291, 292, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 1069, 321, 1070, 323, 324, 325, - 326, 1071, 327, 328, 329, 330, 1072, 790, 332, 1073, - 334, 335, 336, 0, 337, 338, 0, 0, 1074, 340, - 341, 0, 0, 342, 343, 344, 345, 346, 347, 792, - 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 0, 0, 0, 0, 360, 361, 793, 363, 364, - 365, 366, 367, 368, 369, 0, 370, 371, 372, 373, - 374, 375, 0, 376, 377, 378, 1075, 380, 381, 382, - 383, 0, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 0, 397, 398, 399, 400, - 401, 402, 1076, 404, 405, 406, 407, 408, 409, 410, - 411, 412, 413, 414, 415, 416, 0, 0, 417, 418, - 419, 420, 421, 422, 423, 424, 425, 0, 426, 427, - 428, 1077, 430, 0, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, 444, 795, 0, - 0, 446, 447, 3305, 448, 449, 450, 451, 452, 453, - 454, 0, 455, 1078, 1079, 0, 0, 458, 459, 796, - 461, 797, 1080, 463, 464, 798, 466, 467, 468, 469, - 470, 0, 0, 471, 472, 473, 0, 474, 475, 476, - 477, 0, 478, 479, 480, 481, 482, 483, 1081, 0, - 485, 486, 487, 488, 489, 490, 491, 492, 493, 0, - 0, 494, 0, 0, 495, 496, 497, 498, 499, 500, + 316, 317, 318, 319, 320, 321, 1073, 323, 1074, 325, + 326, 327, 328, 1075, 329, 330, 331, 332, 1076, 794, + 334, 1077, 336, 337, 338, 0, 339, 340, 0, 0, + 1078, 342, 343, 0, 0, 344, 345, 346, 347, 348, + 349, 796, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 797, + 365, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 1079, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 403, 404, 405, 406, 1080, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 430, 431, 432, 1081, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 447, 448, 799, 0, 0, 450, 451, 0, 452, 453, + 454, 455, 456, 457, 458, 0, 459, 1082, 1083, 0, + 0, 462, 463, 800, 465, 801, 1084, 467, 468, 802, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 1085, 0, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, - 511, 512, 513, 514, 515, 1082, 0, 0, 0, 0, - 0, 0, 1083, 1084, 1085, 0, 0, 0, 0, 1086, - 0, 1087, 0, 0, 0, 0, 1088, 1089, 0, 1090, - 1091, 116, 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 117, 118, 119, 120, 121, 122, 123, 124, 0, 125, - 126, 127, 0, 0, 0, 0, 0, 1048, 0, 0, - 128, 129, 130, 0, 131, 132, 133, 134, 135, 136, - 137, 138, 1049, 140, 1050, 1051, 0, 143, 144, 145, - 146, 147, 148, 1052, 785, 149, 150, 151, 152, 1053, - 1054, 155, 0, 156, 157, 158, 159, 786, 0, 787, - 0, 1055, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 0, 172, 173, 174, 175, 176, 177, 0, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 1056, 190, 191, 1057, 193, 1058, 194, 0, 195, 196, - 197, 198, 199, 200, 0, 0, 201, 202, 203, 204, - 0, 0, 205, 206, 1059, 208, 209, 0, 210, 211, - 212, 0, 213, 214, 215, 0, 216, 217, 218, 219, - 1060, 221, 222, 223, 224, 225, 788, 1061, 227, 0, - 228, 229, 1062, 231, 0, 232, 0, 233, 234, 0, - 235, 236, 237, 238, 239, 240, 0, 241, 0, 1063, - 1064, 244, 245, 0, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 0, 258, 259, 260, - 261, 262, 263, 264, 0, 265, 266, 267, 268, 269, - 270, 271, 272, 1065, 1066, 0, 1067, 0, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 0, - 0, 287, 288, 289, 290, 0, 291, 292, 293, 294, - 295, 296, 297, 298, 1068, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 1069, 321, 1070, 323, 324, - 325, 326, 1071, 327, 328, 329, 330, 1072, 790, 332, - 1073, 334, 335, 336, 0, 337, 338, 0, 0, 1074, - 340, 341, 0, 0, 342, 343, 344, 345, 346, 347, - 792, 349, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 0, 0, 0, 0, 360, 361, 793, 363, - 364, 365, 366, 367, 368, 369, 0, 370, 371, 372, - 373, 374, 375, 0, 376, 377, 378, 1075, 380, 381, - 382, 383, 0, 384, 385, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, 396, 0, 397, 398, 399, - 400, 401, 402, 1076, 404, 405, 406, 407, 408, 409, - 410, 411, 412, 413, 414, 415, 416, 0, 0, 417, - 418, 419, 420, 421, 422, 423, 424, 425, 0, 426, - 427, 428, 1077, 430, 0, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, 444, 795, - 0, 0, 446, 447, 0, 448, 449, 450, 451, 452, - 453, 454, 0, 455, 1078, 1079, 0, 0, 458, 459, - 796, 461, 797, 1080, 463, 464, 798, 466, 467, 468, - 469, 470, 0, 0, 471, 472, 473, 0, 474, 475, - 476, 477, 0, 478, 479, 480, 481, 482, 483, 1081, - 0, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 0, 0, 494, 0, 0, 495, 496, 497, 498, 499, - 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, - 510, 511, 512, 513, 514, 515, 1082, 0, 0, 0, - 0, 0, 0, 1083, 1084, 1085, 0, 0, 0, 0, - 1086, 0, 1087, 0, 0, 0, 0, 1088, 1089, 0, - 1090, 1091, 116, 1042, 815, 1043, 1044, 1045, 1046, 1047, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 117, 118, 119, 120, 121, 122, 123, 124, 0, - 125, 126, 127, 0, 0, 0, 0, 0, 1048, 0, - 0, 128, 129, 130, 0, 131, 132, 133, 134, 135, - 136, 137, 138, 1049, 140, 1050, 1051, 0, 143, 144, - 145, 146, 147, 148, 1052, 785, 149, 150, 151, 152, - 1053, 1054, 155, 0, 156, 157, 158, 159, 786, 0, - 787, 0, 1055, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 0, 172, 173, 174, 175, 176, 177, 0, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 1056, 190, 191, 1057, 193, 1058, 194, 0, 195, - 196, 197, 198, 199, 200, 0, 0, 201, 202, 203, - 204, 0, 0, 205, 206, 1059, 208, 209, 0, 210, - 211, 212, 0, 213, 214, 215, 0, 216, 217, 218, - 219, 1060, 221, 222, 223, 224, 225, 788, 1061, 227, - 0, 228, 229, 1062, 231, 0, 232, 0, 233, 234, - 0, 235, 236, 237, 238, 239, 240, 0, 241, 0, - 1063, 1064, 244, 245, 0, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 0, 258, 259, - 260, 261, 262, 263, 264, 0, 265, 266, 267, 268, - 269, 270, 271, 272, 1065, 1066, 0, 1067, 0, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 0, 0, 287, 288, 289, 290, 0, 291, 292, 293, - 294, 295, 296, 297, 298, 1068, 300, 301, 302, 303, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 1086, + 0, 0, 0, 0, 0, 0, 1721, 1722, 1089, 0, + 0, 0, 0, 1090, 0, 1091, 0, 0, 0, 0, + 1092, 1093, 0, 1094, 1095, 117, 2204, 819, 1047, 1048, + 1049, 1050, 1051, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 1052, 0, 0, 129, 130, 131, 0, 132, 133, + 134, 135, 136, 137, 138, 139, 1053, 141, 1054, 1055, + 0, 144, 145, 146, 147, 148, 149, 1056, 789, 150, + 151, 152, 153, 1057, 1058, 156, 0, 157, 158, 159, + 160, 790, 0, 791, 0, 1059, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 1060, 191, 192, 1061, 194, 1062, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 1063, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 1064, 222, 223, 224, 225, 226, + 227, 792, 1065, 229, 0, 230, 231, 1066, 233, 0, + 234, 0, 235, 236, 0, 237, 238, 239, 240, 241, + 242, 0, 243, 0, 1067, 1068, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 268, 269, 270, 271, 272, 273, 274, 1069, 1070, + 0, 1071, 0, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 290, 291, 292, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 1072, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 1073, 323, 1074, 325, 326, 327, 328, 1075, 329, 330, + 331, 332, 1076, 794, 334, 1077, 336, 337, 338, 0, + 339, 340, 0, 0, 1078, 342, 343, 0, 0, 344, + 345, 346, 347, 348, 349, 796, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 797, 365, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 1079, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 403, 404, 405, 406, + 1080, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 430, 431, 432, 1081, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 447, 448, 799, 0, 0, 450, + 451, 0, 452, 453, 454, 455, 456, 457, 458, 0, + 459, 1082, 1083, 0, 0, 462, 463, 800, 465, 801, + 1084, 467, 468, 802, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 1085, 0, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 1086, 0, 0, 0, 0, 0, 0, + 1087, 1088, 1089, 0, 0, 0, 0, 1090, 0, 1091, + 0, 0, 0, 0, 1092, 1093, 0, 1094, 1095, 117, + 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 1052, 0, 0, 129, 130, + 131, 0, 132, 133, 134, 135, 136, 137, 138, 139, + 1053, 141, 1054, 1055, 0, 144, 145, 146, 147, 148, + 149, 1056, 789, 150, 151, 152, 153, 1057, 1058, 156, + 0, 157, 158, 159, 160, 790, 0, 791, 0, 1059, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 1060, 191, + 192, 1061, 194, 1062, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 1063, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 1064, 222, + 223, 224, 225, 226, 227, 792, 1065, 229, 0, 230, + 231, 1066, 233, 0, 234, 0, 235, 236, 0, 237, + 238, 239, 240, 241, 242, 0, 243, 0, 1067, 1068, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 268, 269, 270, 271, 272, + 273, 274, 1069, 1070, 0, 1071, 0, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 290, 291, 292, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 1073, 323, 1074, 325, 326, 327, + 328, 1075, 329, 330, 331, 332, 1076, 794, 334, 1077, + 336, 337, 338, 0, 339, 340, 0, 0, 1078, 342, + 343, 0, 0, 344, 345, 346, 347, 348, 349, 796, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 797, 365, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 1079, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 403, 404, 405, 406, 1080, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 430, 431, 432, 1081, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, + 799, 0, 0, 450, 451, 0, 452, 453, 454, 455, + 456, 457, 458, 0, 459, 1082, 1083, 0, 0, 462, + 463, 800, 465, 801, 1084, 467, 468, 802, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 1085, 0, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 1086, 0, 0, + 0, 0, 0, 0, 1087, 2287, 1089, 0, 0, 0, + 0, 1090, 0, 1091, 0, 0, 0, 0, 1092, 1093, + 0, 1094, 1095, 117, 1046, 819, 1047, 1048, 1049, 1050, + 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 1052, + 0, 0, 129, 130, 131, 0, 132, 133, 134, 135, + 136, 137, 138, 139, 1053, 141, 1054, 1055, 0, 144, + 145, 146, 147, 148, 149, 1056, 789, 150, 151, 152, + 153, 1057, 1058, 156, 0, 157, 158, 159, 160, 790, + 0, 791, 0, 1059, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 1060, 191, 192, 1061, 194, 1062, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 1063, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 1064, 222, 223, 224, 225, 226, 227, 792, + 1065, 229, 0, 230, 231, 1066, 233, 0, 234, 0, + 235, 236, 0, 237, 238, 239, 240, 241, 242, 0, + 243, 0, 1067, 1068, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 268, + 269, 270, 271, 272, 273, 274, 1069, 1070, 0, 1071, + 0, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 290, 291, 292, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 1069, 321, 1070, 323, - 324, 325, 326, 1071, 327, 328, 329, 330, 1072, 790, - 332, 1073, 334, 335, 336, 0, 337, 338, 0, 0, - 1074, 340, 341, 0, 0, 342, 343, 344, 345, 346, - 347, 792, 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 0, 0, 0, 0, 360, 361, 793, - 363, 364, 365, 366, 367, 368, 369, 0, 370, 371, - 372, 373, 374, 375, 0, 376, 377, 378, 1075, 380, - 381, 382, 383, 0, 384, 385, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 0, 397, 398, - 399, 400, 401, 402, 1076, 404, 405, 406, 407, 408, - 409, 410, 411, 412, 413, 414, 415, 416, 0, 0, - 417, 418, 419, 420, 421, 422, 423, 424, 425, 0, - 426, 427, 428, 1077, 430, 0, 431, 432, 433, 434, + 314, 315, 316, 317, 318, 319, 320, 321, 1073, 323, + 1074, 325, 326, 327, 328, 1075, 329, 330, 331, 332, + 1076, 794, 334, 1077, 336, 337, 338, 0, 339, 340, + 0, 0, 1078, 342, 343, 0, 0, 344, 345, 346, + 347, 348, 349, 796, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 797, 365, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 1079, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 403, 404, 405, 406, 1080, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 430, 431, 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, - 795, 0, 0, 446, 447, 0, 448, 449, 450, 451, - 452, 453, 454, 0, 455, 1078, 1079, 0, 0, 458, - 459, 796, 461, 797, 1080, 463, 464, 798, 466, 467, - 468, 469, 470, 0, 0, 471, 472, 473, 0, 474, - 475, 476, 477, 0, 478, 479, 480, 481, 482, 483, - 1081, 0, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 0, 0, 494, 0, 0, 495, 496, 497, 498, + 445, 446, 447, 448, 799, 0, 0, 450, 451, 0, + 452, 453, 454, 455, 456, 457, 458, 0, 459, 1082, + 1083, 0, 0, 462, 463, 800, 465, 801, 1084, 467, + 468, 802, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 1085, 0, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, - 509, 510, 511, 512, 513, 514, 515, 1082, 0, 0, - 0, 0, 0, 0, 1709, 1710, 1085, 0, 0, 0, - 0, 1086, 0, 1087, 0, 0, 0, 0, 1088, 1089, - 0, 1090, 1091, 116, 2189, 815, 1043, 1044, 1045, 1046, - 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 117, 118, 119, 120, 121, 122, 123, 124, - 0, 125, 126, 127, 0, 0, 0, 0, 0, 1048, - 0, 0, 128, 129, 130, 0, 131, 132, 133, 134, - 135, 136, 137, 138, 1049, 140, 1050, 1051, 0, 143, - 144, 145, 146, 147, 148, 1052, 785, 149, 150, 151, - 152, 1053, 1054, 155, 0, 156, 157, 158, 159, 786, - 0, 787, 0, 1055, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 0, 172, 173, 174, 175, 176, 177, - 0, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 1056, 190, 191, 1057, 193, 1058, 194, 0, - 195, 196, 197, 198, 199, 200, 0, 0, 201, 202, - 203, 204, 0, 0, 205, 206, 1059, 208, 209, 0, - 210, 211, 212, 0, 213, 214, 215, 0, 216, 217, - 218, 219, 1060, 221, 222, 223, 224, 225, 788, 1061, - 227, 0, 228, 229, 1062, 231, 0, 232, 0, 233, - 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, - 0, 1063, 1064, 244, 245, 0, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 0, 258, - 259, 260, 261, 262, 263, 264, 0, 265, 266, 267, - 268, 269, 270, 271, 272, 1065, 1066, 0, 1067, 0, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 287, 288, 289, 290, 0, 291, 292, - 293, 294, 295, 296, 297, 298, 1068, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 1069, 321, 1070, - 323, 324, 325, 326, 1071, 327, 328, 329, 330, 1072, - 790, 332, 1073, 334, 335, 336, 0, 337, 338, 0, - 0, 1074, 340, 341, 0, 0, 342, 343, 344, 345, - 346, 347, 792, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 0, 0, 0, 0, 360, 361, - 793, 363, 364, 365, 366, 367, 368, 369, 0, 370, - 371, 372, 373, 374, 375, 0, 376, 377, 378, 1075, - 380, 381, 382, 383, 0, 384, 385, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 0, 397, - 398, 399, 400, 401, 402, 1076, 404, 405, 406, 407, - 408, 409, 410, 411, 412, 413, 414, 415, 416, 0, - 0, 417, 418, 419, 420, 421, 422, 423, 424, 425, - 0, 426, 427, 428, 1077, 430, 0, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 795, 0, 0, 446, 447, 0, 448, 449, 450, - 451, 452, 453, 454, 0, 455, 1078, 1079, 0, 0, - 458, 459, 796, 461, 797, 1080, 463, 464, 798, 466, - 467, 468, 469, 470, 0, 0, 471, 472, 473, 0, - 474, 475, 476, 477, 0, 478, 479, 480, 481, 482, - 483, 1081, 0, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 0, 0, 494, 0, 0, 495, 496, 497, - 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, - 508, 509, 510, 511, 512, 513, 514, 515, 1082, 0, - 0, 0, 0, 0, 0, 1083, 1084, 1085, 0, 0, - 0, 0, 1086, 0, 1087, 0, 0, 0, 0, 1088, - 1089, 0, 1090, 1091, 116, 1042, 815, 1043, 1044, 1045, - 1046, 1047, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 1048, 0, 0, 128, 129, 130, 0, 131, 132, 133, - 134, 135, 136, 137, 138, 1049, 140, 1050, 1051, 0, - 143, 144, 145, 146, 147, 148, 1052, 785, 149, 150, - 151, 152, 1053, 1054, 155, 0, 156, 157, 158, 159, - 786, 0, 787, 0, 1055, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 1056, 190, 191, 1057, 193, 1058, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 1059, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 1060, 221, 222, 223, 224, 225, 788, - 1061, 227, 0, 228, 229, 1062, 231, 0, 232, 0, - 233, 234, 0, 235, 236, 237, 238, 239, 240, 0, - 241, 0, 1063, 1064, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 266, - 267, 268, 269, 270, 271, 272, 1065, 1066, 0, 1067, - 0, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 288, 289, 290, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 1068, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 1069, 321, - 1070, 323, 324, 325, 326, 1071, 327, 328, 329, 330, - 1072, 790, 332, 1073, 334, 335, 336, 0, 337, 338, - 0, 0, 1074, 340, 341, 0, 0, 342, 343, 344, - 345, 346, 347, 792, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 793, 363, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 1075, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 1076, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 426, 427, 428, 1077, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, 444, 795, 0, 0, 446, 447, 0, 448, 449, - 450, 451, 452, 453, 454, 0, 455, 1078, 1079, 0, - 0, 458, 459, 796, 461, 797, 1080, 463, 464, 798, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 1081, 0, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 1082, - 0, 0, 0, 0, 0, 0, 1083, 2272, 1085, 0, - 0, 0, 0, 1086, 0, 1087, 0, 0, 0, 0, - 1088, 1089, 0, 1090, 1091, 116, 1042, 815, 1043, 1044, - 1045, 1046, 1047, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 117, 118, 119, 120, 121, 122, - 123, 124, 0, 125, 126, 127, 0, 0, 0, 0, - 0, 1048, 0, 0, 128, 129, 130, 0, 131, 132, - 133, 134, 135, 136, 137, 138, 1049, 140, 1050, 1051, - 0, 143, 144, 145, 146, 147, 148, 1052, 785, 149, - 150, 151, 152, 1053, 1054, 155, 0, 156, 157, 158, - 159, 786, 0, 787, 0, 1055, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 0, 172, 173, 174, 175, - 176, 177, 0, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 1056, 190, 191, 1057, 193, 1058, - 194, 0, 195, 196, 197, 198, 199, 200, 0, 0, - 201, 202, 203, 204, 0, 0, 205, 206, 1059, 208, - 209, 0, 210, 211, 212, 0, 213, 214, 215, 0, - 216, 217, 218, 219, 1060, 221, 222, 223, 224, 225, - 788, 1061, 227, 0, 228, 229, 1062, 231, 0, 232, - 0, 233, 234, 0, 235, 236, 237, 238, 239, 240, - 0, 241, 0, 1063, 1064, 244, 245, 0, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 0, 258, 259, 260, 261, 262, 263, 264, 0, 265, - 266, 267, 268, 269, 270, 271, 272, 1065, 1066, 0, - 1067, 0, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 0, 0, 287, 288, 289, 290, 0, - 291, 292, 293, 294, 295, 296, 297, 298, 1068, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 1069, - 321, 1070, 323, 324, 325, 326, 1071, 327, 328, 329, - 330, 1072, 790, 332, 1073, 334, 335, 336, 0, 337, - 338, 0, 0, 1074, 340, 341, 0, 0, 342, 343, - 344, 345, 346, 347, 792, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 0, 0, 0, 0, - 360, 361, 793, 363, 364, 365, 366, 367, 368, 369, - 0, 370, 371, 372, 373, 374, 375, 0, 376, 377, - 378, 1075, 380, 381, 382, 383, 0, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 0, 397, 398, 399, 400, 401, 402, 1076, 404, 405, - 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 0, 0, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 0, 426, 427, 428, 1077, 430, 0, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, 444, 795, 0, 0, 446, 447, 0, 448, - 449, 450, 451, 452, 453, 454, 0, 455, 1078, 1079, - 0, 0, 458, 459, 796, 461, 797, 1080, 463, 464, - 798, 466, 467, 468, 469, 470, 0, 0, 471, 472, - 473, 0, 474, 475, 476, 477, 0, 478, 479, 480, - 481, 482, 483, 1081, 0, 485, 486, 487, 488, 489, - 490, 491, 492, 493, 0, 0, 494, 0, 0, 495, - 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, - 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, - 1082, 0, 0, 0, 0, 0, 0, 1083, 1084, 1085, - 0, 0, 0, 0, 1086, 0, 2486, 0, 0, 0, - 0, 1088, 1089, 0, 1090, 1091, 116, 1042, 815, 1043, - 1044, 1045, 1046, 1047, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 117, 118, 119, 120, 121, - 122, 123, 124, 0, 125, 126, 127, 0, 0, 0, - 0, 0, 1048, 0, 0, 128, 129, 130, 0, 131, - 132, 133, 134, 135, 136, 137, 138, 1049, 140, 1050, - 1051, 0, 143, 144, 145, 146, 147, 148, 1052, 785, - 149, 150, 151, 152, 1053, 1054, 155, 0, 156, 157, - 158, 159, 786, 0, 787, 0, 1055, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 0, 172, 173, 174, - 175, 176, 177, 0, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 1056, 190, 191, 1057, 193, - 1058, 194, 0, 195, 196, 197, 198, 199, 200, 0, - 0, 201, 202, 203, 204, 0, 0, 205, 206, 1059, - 208, 209, 0, 210, 211, 212, 0, 213, 214, 215, - 0, 216, 217, 218, 219, 1060, 221, 222, 223, 224, - 225, 788, 1061, 227, 0, 228, 229, 1062, 231, 0, - 232, 0, 233, 234, 0, 235, 236, 237, 238, 239, - 240, 0, 241, 0, 1063, 1064, 244, 245, 0, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 0, 258, 259, 260, 261, 262, 263, 264, 0, - 265, 266, 267, 268, 269, 270, 271, 272, 1065, 1066, - 0, 1067, 0, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 0, 0, 287, 288, 289, 290, - 0, 291, 292, 293, 294, 295, 296, 297, 298, 1068, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 1086, 0, 0, 0, 0, 0, 0, 1087, 1088, + 1089, 0, 0, 0, 0, 1090, 0, 2501, 0, 0, + 0, 0, 1092, 1093, 0, 1094, 1095, 117, 1046, 819, + 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 1052, 0, 0, 129, 130, 131, 0, + 132, 133, 134, 135, 136, 137, 138, 139, 1053, 141, + 1054, 1055, 0, 144, 145, 146, 147, 148, 149, 1056, + 789, 150, 151, 152, 153, 1057, 1058, 156, 0, 157, + 158, 159, 160, 790, 0, 791, 0, 1059, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 1060, 191, 192, 1061, + 194, 1062, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 1063, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 1064, 222, 223, 224, + 225, 226, 227, 792, 1065, 229, 0, 230, 231, 1066, + 233, 0, 234, 0, 235, 236, 0, 237, 238, 239, + 240, 241, 242, 0, 243, 0, 1067, 1068, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 268, 269, 270, 271, 272, 273, 274, + 1069, 1070, 0, 1071, 0, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 290, + 291, 292, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 1069, 321, 1070, 323, 324, 325, 326, 1071, 327, 328, - 329, 330, 1072, 790, 332, 1073, 334, 335, 336, 0, - 337, 338, 0, 0, 1074, 340, 341, 0, 0, 342, - 343, 344, 345, 346, 347, 792, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 0, 0, 0, - 0, 360, 361, 793, 363, 364, 365, 366, 367, 368, - 369, 0, 370, 371, 372, 373, 374, 375, 0, 376, - 377, 378, 1075, 380, 381, 382, 383, 0, 384, 385, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 0, 397, 398, 399, 400, 401, 402, 1076, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 0, 0, 417, 418, 419, 420, 421, 422, - 423, 424, 425, 0, 426, 427, 428, 1077, 430, 0, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 443, 444, 795, 0, 0, 446, 447, 0, - 448, 449, 450, 451, 452, 453, 454, 0, 455, 1078, - 1079, 0, 0, 458, 459, 796, 461, 797, 1080, 463, - 464, 798, 466, 467, 468, 469, 470, 0, 0, 471, - 472, 473, 0, 474, 475, 476, 477, 0, 478, 479, - 480, 481, 482, 483, 1081, 0, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 0, 0, 494, 0, 0, - 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, + 320, 321, 1073, 323, 1074, 325, 326, 327, 328, 1075, + 329, 330, 331, 332, 1076, 794, 334, 1077, 336, 337, + 338, 0, 339, 340, 0, 0, 1078, 342, 343, 0, + 0, 344, 345, 346, 347, 348, 349, 796, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 797, 365, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 1079, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 403, 404, + 405, 406, 1080, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 430, 431, + 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 799, 0, + 0, 450, 451, 0, 452, 453, 454, 455, 456, 457, + 458, 0, 459, 1082, 1083, 0, 0, 462, 463, 800, + 465, 801, 1084, 467, 468, 802, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 1085, 0, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, - 515, 1082, 0, 0, 0, 0, 0, 0, 1083, 3069, - 1085, 0, 0, 0, 0, 1086, 0, 1087, 0, 0, - 0, 0, 1088, 1089, 0, 1090, 1091, 116, 1042, 815, - 1043, 1044, 1045, 1046, 1047, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 117, 118, 119, 120, - 121, 122, 123, 124, 0, 125, 126, 127, 0, 0, - 0, 0, 0, 1048, 0, 0, 128, 129, 130, 0, - 131, 132, 133, 134, 135, 136, 137, 138, 1049, 140, - 1050, 1051, 0, 143, 144, 145, 146, 147, 148, 1052, - 785, 149, 150, 151, 152, 1053, 1054, 155, 0, 156, - 157, 158, 159, 786, 0, 787, 0, 1055, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 0, 172, 173, - 174, 175, 176, 177, 0, 178, 179, 3016, 181, 182, - 183, 184, 185, 186, 187, 188, 1056, 190, 191, 1057, - 193, 1058, 194, 0, 195, 196, 197, 198, 199, 200, - 0, 0, 201, 202, 203, 204, 0, 0, 205, 206, - 1059, 208, 209, 0, 210, 211, 212, 0, 213, 214, - 215, 0, 216, 217, 218, 219, 1060, 221, 222, 223, - 224, 225, 788, 1061, 227, 0, 228, 229, 1062, 231, - 0, 232, 0, 233, 234, 0, 235, 236, 237, 238, - 239, 240, 0, 241, 0, 3017, 1064, 244, 245, 0, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 0, 258, 259, 260, 261, 262, 263, 264, - 0, 265, 266, 267, 268, 269, 270, 271, 272, 1065, - 1066, 0, 1067, 0, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 0, 0, 287, 288, 289, - 290, 0, 291, 292, 293, 294, 295, 296, 297, 298, - 1068, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 1069, 321, 1070, 323, 324, 325, 326, 1071, 327, - 328, 329, 330, 1072, 790, 332, 1073, 334, 335, 336, - 0, 337, 338, 0, 0, 1074, 340, 341, 0, 0, - 342, 343, 344, 345, 346, 347, 792, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 0, 0, - 0, 0, 360, 361, 793, 363, 364, 365, 366, 367, - 368, 369, 0, 370, 371, 372, 373, 374, 375, 0, - 376, 377, 378, 1075, 380, 381, 382, 383, 0, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 0, 397, 398, 399, 400, 401, 3018, 1076, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, - 414, 415, 416, 0, 0, 417, 418, 419, 420, 421, - 422, 423, 424, 425, 0, 426, 427, 428, 1077, 430, - 0, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, 444, 795, 0, 0, 446, 447, - 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, - 1078, 1079, 0, 0, 458, 459, 796, 461, 797, 1080, - 463, 464, 798, 466, 467, 468, 469, 470, 0, 0, - 471, 472, 473, 0, 474, 475, 476, 477, 0, 478, - 479, 480, 481, 482, 483, 1081, 0, 485, 486, 487, - 488, 489, 490, 491, 492, 493, 0, 0, 494, 0, - 0, 495, 496, 497, 498, 499, 500, 501, 502, 503, - 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, - 514, 515, 1082, 0, 0, 0, 0, 0, 0, 1083, - 1084, 1085, 0, 0, 0, 0, 1086, 0, 3019, 0, - 0, 0, 0, 1088, 1089, 0, 1090, 1091, 116, 1042, - 815, 1043, 1044, 1045, 1046, 1047, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 117, 118, 119, - 120, 121, 122, 123, 124, 0, 125, 126, 127, 0, - 0, 0, 0, 0, 1048, 0, 0, 128, 129, 130, - 0, 131, 132, 133, 134, 135, 136, 137, 3477, 1049, - 140, 1050, 1051, 0, 143, 144, 145, 146, 147, 148, - 1052, 785, 149, 150, 151, 152, 1053, 1054, 155, 0, - 156, 157, 158, 159, 786, 0, 787, 0, 1055, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 0, 172, - 173, 174, 175, 176, 177, 0, 178, 179, 180, 3478, - 182, 183, 184, 185, 186, 187, 188, 1056, 190, 191, - 1057, 193, 1058, 194, 0, 195, 196, 197, 198, 199, - 200, 0, 0, 201, 202, 203, 204, 0, 0, 205, - 206, 1059, 208, 209, 0, 210, 211, 212, 0, 213, - 214, 215, 0, 216, 217, 218, 219, 1060, 221, 222, - 223, 224, 225, 788, 1061, 227, 0, 228, 229, 1062, - 231, 0, 232, 0, 233, 234, 0, 235, 236, 237, - 238, 239, 240, 0, 241, 0, 1063, 1064, 244, 245, - 0, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 0, 258, 259, 260, 261, 262, 263, - 264, 0, 265, 266, 267, 268, 269, 270, 271, 272, - 1065, 1066, 0, 1067, 0, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 0, 0, 287, 288, - 289, 290, 0, 291, 292, 293, 294, 295, 296, 297, - 298, 1068, 300, 301, 302, 303, 304, 305, 306, 307, + 515, 516, 517, 518, 519, 1086, 0, 0, 0, 0, + 0, 0, 1087, 3087, 1089, 0, 0, 0, 0, 1090, + 0, 1091, 0, 0, 0, 0, 1092, 1093, 0, 1094, + 1095, 117, 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 1052, 0, 0, + 129, 130, 131, 0, 132, 133, 134, 135, 136, 137, + 138, 139, 1053, 141, 1054, 1055, 0, 144, 145, 146, + 147, 148, 149, 1056, 789, 150, 151, 152, 153, 1057, + 1058, 156, 0, 157, 158, 159, 160, 790, 0, 791, + 0, 1059, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 179, + 180, 3034, 182, 183, 184, 185, 186, 187, 188, 189, + 1060, 191, 192, 1061, 194, 1062, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 1063, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 1064, 222, 223, 224, 225, 226, 227, 792, 1065, 229, + 0, 230, 231, 1066, 233, 0, 234, 0, 235, 236, + 0, 237, 238, 239, 240, 241, 242, 0, 243, 0, + 3035, 1068, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 268, 269, 270, + 271, 272, 273, 274, 1069, 1070, 0, 1071, 0, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 290, 291, 292, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 1073, 323, 1074, 325, + 326, 327, 328, 1075, 329, 330, 331, 332, 1076, 794, + 334, 1077, 336, 337, 338, 0, 339, 340, 0, 0, + 1078, 342, 343, 0, 0, 344, 345, 346, 347, 348, + 349, 796, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 797, + 365, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 1079, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 403, 404, 405, 3036, 1080, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 430, 431, 432, 1081, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 447, 448, 799, 0, 0, 450, 451, 0, 452, 453, + 454, 455, 456, 457, 458, 0, 459, 1082, 1083, 0, + 0, 462, 463, 800, 465, 801, 1084, 467, 468, 802, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 1085, 0, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 1086, + 0, 0, 0, 0, 0, 0, 1087, 1088, 1089, 0, + 0, 0, 0, 1090, 0, 3037, 0, 0, 0, 0, + 1092, 1093, 0, 1094, 1095, 117, 1046, 819, 1047, 1048, + 1049, 1050, 1051, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 1052, 0, 0, 129, 130, 131, 0, 132, 133, + 134, 135, 136, 137, 138, 3495, 1053, 141, 1054, 1055, + 0, 144, 145, 146, 147, 148, 149, 1056, 789, 150, + 151, 152, 153, 1057, 1058, 156, 0, 157, 158, 159, + 160, 790, 0, 791, 0, 1059, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 179, 180, 181, 3496, 183, 184, 185, + 186, 187, 188, 189, 1060, 191, 192, 1061, 194, 1062, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 1063, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 1064, 222, 223, 224, 225, 226, + 227, 792, 1065, 229, 0, 230, 231, 1066, 233, 0, + 234, 0, 235, 236, 0, 237, 238, 239, 240, 241, + 242, 0, 243, 0, 1067, 1068, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 268, 269, 270, 271, 272, 273, 274, 1069, 1070, + 0, 1071, 0, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 290, 291, 292, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 1072, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 1073, 323, 1074, 325, 326, 327, 328, 1075, 329, 330, + 331, 332, 1076, 794, 334, 1077, 336, 337, 338, 0, + 339, 340, 0, 0, 1078, 342, 343, 0, 0, 344, + 345, 346, 347, 348, 349, 796, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 797, 365, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 1079, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 403, 404, 405, 406, + 1080, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 430, 431, 432, 1081, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 447, 448, 799, 0, 0, 450, + 451, 0, 452, 453, 454, 455, 456, 457, 458, 0, + 459, 1082, 1083, 0, 0, 462, 463, 800, 465, 801, + 1084, 467, 468, 802, 470, 471, 3497, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 1085, 0, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 1086, 0, 0, 0, 0, 0, 0, + 1087, 1088, 1089, 0, 0, 0, 0, 1090, 0, 1091, + 0, 0, 0, 0, 1092, 1093, 0, 1094, 1095, 117, + 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 1052, 0, 0, 129, 130, + 131, 0, 132, 133, 134, 135, 136, 137, 138, 139, + 1053, 141, 1054, 1055, 0, 144, 145, 146, 147, 148, + 149, 1056, 789, 150, 151, 152, 153, 1057, 1058, 156, + 0, 157, 158, 159, 160, 790, 0, 791, 0, 1059, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 179, 180, 181, + 3496, 183, 184, 185, 186, 187, 188, 189, 1060, 191, + 192, 1061, 194, 1062, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 1063, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 1064, 222, + 223, 224, 225, 226, 227, 792, 1065, 229, 0, 230, + 231, 1066, 233, 0, 234, 0, 235, 236, 0, 237, + 238, 239, 240, 241, 242, 0, 243, 0, 1067, 1068, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 268, 269, 270, 271, 272, + 273, 274, 1069, 1070, 0, 1071, 0, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 290, 291, 292, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 1069, 321, 1070, 323, 324, 325, 326, 1071, - 327, 328, 329, 330, 1072, 790, 332, 1073, 334, 335, - 336, 0, 337, 338, 0, 0, 1074, 340, 341, 0, - 0, 342, 343, 344, 345, 346, 347, 792, 349, 350, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 0, - 0, 0, 0, 360, 361, 793, 363, 364, 365, 366, - 367, 368, 369, 0, 370, 371, 372, 373, 374, 375, - 0, 376, 377, 378, 1075, 380, 381, 382, 383, 0, - 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 0, 397, 398, 399, 400, 401, 402, - 1076, 404, 405, 406, 407, 408, 409, 410, 411, 412, - 413, 414, 415, 416, 0, 0, 417, 418, 419, 420, - 421, 422, 423, 424, 425, 0, 426, 427, 428, 1077, - 430, 0, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 443, 444, 795, 0, 0, 446, - 447, 0, 448, 449, 450, 451, 452, 453, 454, 0, - 455, 1078, 1079, 0, 0, 458, 459, 796, 461, 797, - 1080, 463, 464, 798, 466, 467, 3479, 469, 470, 0, - 0, 471, 472, 473, 0, 474, 475, 476, 477, 0, - 478, 479, 480, 481, 482, 483, 1081, 0, 485, 486, - 487, 488, 489, 490, 491, 492, 493, 0, 0, 494, - 0, 0, 495, 496, 497, 498, 499, 500, 501, 502, + 318, 319, 320, 321, 1073, 323, 1074, 325, 326, 327, + 328, 1075, 329, 330, 331, 332, 1076, 794, 334, 1077, + 336, 337, 338, 0, 339, 340, 0, 0, 1078, 342, + 343, 0, 0, 344, 345, 346, 347, 348, 349, 796, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 797, 365, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 1079, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 403, 404, 405, 406, 1080, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 430, 431, 432, 1081, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, + 799, 0, 0, 450, 451, 0, 452, 453, 454, 455, + 456, 457, 458, 0, 459, 1082, 1083, 0, 0, 462, + 463, 800, 465, 801, 1084, 467, 468, 802, 470, 471, + 3497, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 1085, 0, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, - 513, 514, 515, 1082, 0, 0, 0, 0, 0, 0, - 1083, 1084, 1085, 0, 0, 0, 0, 1086, 0, 1087, - 0, 0, 0, 0, 1088, 1089, 0, 1090, 1091, 116, - 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 1048, 0, 0, 128, 129, - 130, 0, 131, 132, 133, 134, 135, 136, 137, 138, - 1049, 140, 1050, 1051, 0, 143, 144, 145, 146, 147, - 148, 1052, 785, 149, 150, 151, 152, 1053, 1054, 155, - 0, 156, 157, 158, 159, 786, 0, 787, 0, 1055, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 178, 179, 180, - 3478, 182, 183, 184, 185, 186, 187, 188, 1056, 190, - 191, 1057, 193, 1058, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 1059, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 1060, 221, - 222, 223, 224, 225, 788, 1061, 227, 0, 228, 229, - 1062, 231, 0, 232, 0, 233, 234, 0, 235, 236, - 237, 238, 239, 240, 0, 241, 0, 1063, 1064, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 266, 267, 268, 269, 270, 271, - 272, 1065, 1066, 0, 1067, 0, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 288, 289, 290, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 1068, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 1069, 321, 1070, 323, 324, 325, 326, - 1071, 327, 328, 329, 330, 1072, 790, 332, 1073, 334, - 335, 336, 0, 337, 338, 0, 0, 1074, 340, 341, - 0, 0, 342, 343, 344, 345, 346, 347, 792, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 793, 363, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 1075, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 1076, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 426, 427, 428, - 1077, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 795, 0, 0, - 446, 447, 0, 448, 449, 450, 451, 452, 453, 454, - 0, 455, 1078, 1079, 0, 0, 458, 459, 796, 461, - 797, 1080, 463, 464, 798, 466, 467, 3479, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 1081, 0, 485, - 486, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 1082, 0, 0, 0, 0, 0, - 0, 1083, 1084, 1085, 0, 0, 0, 0, 1086, 0, - 1087, 0, 0, 0, 0, 1088, 1089, 0, 1090, 1091, - 116, 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, - 118, 119, 120, 121, 122, 123, 124, 0, 125, 126, - 127, 0, 0, 0, 0, 0, 1048, 0, 0, 128, - 129, 130, 0, 131, 132, 133, 134, 135, 136, 137, - 138, 1049, 140, 1050, 1051, 0, 143, 144, 145, 146, - 147, 148, 1052, 785, 149, 150, 151, 152, 1053, 1054, - 155, 0, 156, 157, 158, 159, 786, 0, 787, 0, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 0, 172, 173, 174, 175, 176, 177, 0, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 1056, - 190, 191, 1057, 193, 0, 194, 0, 195, 196, 197, - 198, 199, 200, 0, 0, 201, 202, 203, 204, 0, - 0, 205, 206, 1059, 208, 209, 0, 210, 211, 212, - 0, 213, 214, 215, 0, 216, 217, 218, 219, 1060, - 221, 222, 223, 224, 225, 788, 1061, 227, 0, 228, - 229, 1062, 231, 0, 232, 0, 233, 234, 0, 235, - 236, 237, 238, 239, 240, 0, 241, 0, 1063, 1064, - 244, 245, 0, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 0, 258, 259, 260, 261, - 262, 263, 264, 0, 265, 266, 267, 268, 269, 270, - 271, 272, 1065, 1066, 0, 1067, 0, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 0, 0, - 287, 288, 289, 290, 0, 291, 292, 293, 294, 295, - 296, 297, 298, 1068, 300, 301, 302, 303, 304, 305, + 513, 514, 515, 516, 517, 518, 519, 1086, 0, 0, + 0, 0, 0, 0, 1087, 1088, 1089, 0, 0, 0, + 0, 1090, 0, 1091, 0, 0, 0, 0, 1092, 1093, + 0, 1094, 1095, 117, 1046, 819, 1047, 1048, 1049, 1050, + 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 1052, + 0, 0, 129, 130, 131, 0, 132, 133, 134, 135, + 136, 137, 138, 139, 1053, 141, 1054, 1055, 0, 144, + 145, 146, 147, 148, 149, 1056, 789, 150, 151, 152, + 153, 1057, 1058, 156, 0, 157, 158, 159, 160, 790, + 0, 791, 0, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 1060, 191, 192, 1061, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 1063, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 1064, 222, 223, 224, 225, 226, 227, 792, + 1065, 229, 0, 230, 231, 1066, 233, 0, 234, 0, + 235, 236, 0, 237, 238, 239, 240, 241, 242, 0, + 243, 0, 1067, 1068, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 268, + 269, 270, 271, 272, 273, 274, 1069, 1070, 0, 1071, + 0, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 290, 291, 292, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 1072, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 1073, 323, + 1074, 325, 326, 327, 328, 0, 329, 330, 331, 332, + 1076, 794, 334, 1077, 336, 337, 338, 0, 339, 340, + 0, 0, 1078, 342, 343, 0, 0, 344, 345, 346, + 347, 348, 349, 796, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 797, 365, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 1079, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 403, 404, 405, 406, 1080, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 430, 431, 432, 1081, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 447, 448, 799, 0, 0, 450, 451, 0, + 452, 453, 454, 455, 456, 457, 458, 0, 459, 1082, + 1083, 0, 0, 462, 463, 800, 465, 801, 1084, 467, + 468, 802, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 1085, 0, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 0, 0, 0, 0, 0, 0, 0, 1421, 1422, + 0, 0, 0, 0, 0, 1090, 0, 1091, 0, 0, + 0, 0, 1092, 1093, 0, 1094, 1095, 117, 1046, 819, + 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 1052, 0, 0, 129, 130, 131, 0, + 132, 133, 134, 135, 136, 137, 138, -2062, 1053, 141, + 1054, 1055, 0, 144, 145, 146, 147, 148, 149, 1056, + 789, 150, 151, 152, 153, 1057, 1058, 156, 0, 157, + 158, 159, 160, 790, 0, 791, 0, 1059, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 179, 180, 181, 3496, 183, + 184, 185, 186, 187, 188, 189, 1060, 191, 192, 1061, + 194, 1062, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 1063, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 1064, 222, 223, 224, + 225, 226, 227, 792, 1065, 229, 0, 230, 231, 1066, + 233, 0, 234, 0, 235, 236, 0, 237, 238, 239, + 240, -2062, 242, 0, 243, 0, 1067, 1068, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, -2062, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 268, 269, 270, 271, 272, 273, 274, + 1069, 1070, 0, 1071, 0, 278, 0, 0, 281, 282, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 290, + 291, -2062, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 1073, 323, 1074, 325, 326, 327, 328, 0, + 329, 330, 0, 332, 1076, 794, 334, 1077, 336, 337, + 338, 0, 339, 340, 0, 0, 1078, 342, 343, 0, + 0, 344, 345, 346, 347, 348, 349, 796, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 797, 365, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 1079, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 403, 404, + 405, 406, 1080, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, -2062, 431, + 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 799, 0, + 0, 450, 451, 0, 452, 453, 454, 455, 456, 457, + 458, 0, 459, 1082, 1083, 0, 0, 462, 463, 800, + 465, 801, 1084, 467, 468, 802, 470, 471, 3497, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 1085, 0, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, -2062, 0, 0, 0, 0, + 0, 0, 1087, 1088, 1089, 0, 0, 0, 0, 1090, + 0, 1091, 0, 0, 0, 0, 1092, 1093, 0, 1094, + 1095, 117, 1046, 819, 1047, 1048, 0, 1050, 1051, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 1052, 0, 0, + 129, 130, 131, 0, 132, 133, 134, 135, 136, 137, + 138, 139, 1053, 141, 1054, 1055, 0, 144, 145, 146, + 147, 148, 149, 1056, 789, 150, 151, 152, 153, 1057, + 1058, 156, 0, 157, 158, 159, 160, 790, 0, 791, + 0, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 1060, 191, 192, 1061, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 1063, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 1064, 222, 223, 224, 225, 226, 227, 792, 1065, 229, + 0, 230, 231, 1066, 233, 0, 234, 0, 235, 236, + 0, 237, 238, 239, 240, 241, 242, 0, 243, 0, + 1067, 1068, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 268, 269, 270, + 271, 272, 273, 274, 1069, 1070, 0, 1071, 0, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 290, 291, 292, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 1069, 321, 1070, 323, 324, 325, - 326, 0, 327, 328, 329, 330, 1072, 790, 332, 1073, - 334, 335, 336, 0, 337, 338, 0, 0, 1074, 340, - 341, 0, 0, 342, 343, 344, 345, 346, 347, 792, - 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 0, 0, 0, 0, 360, 361, 793, 363, 364, - 365, 366, 367, 368, 369, 0, 370, 371, 372, 373, - 374, 375, 0, 376, 377, 378, 1075, 380, 381, 382, - 383, 0, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 0, 397, 398, 399, 400, - 401, 402, 1076, 404, 405, 406, 407, 408, 409, 410, - 411, 412, 413, 414, 415, 416, 0, 0, 417, 418, - 419, 420, 421, 422, 423, 424, 425, 0, 426, 427, - 428, 1077, 430, 0, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, 444, 795, 0, - 0, 446, 447, 0, 448, 449, 450, 451, 452, 453, - 454, 0, 455, 1078, 1079, 0, 0, 458, 459, 796, - 461, 797, 1080, 463, 464, 798, 466, 467, 468, 469, - 470, 0, 0, 471, 472, 473, 0, 474, 475, 476, - 477, 0, 478, 479, 480, 481, 482, 483, 1081, 0, - 485, 486, 487, 488, 489, 490, 491, 492, 493, 0, - 0, 494, 0, 0, 495, 496, 497, 498, 499, 500, + 316, 317, 318, 319, 320, 321, 1073, 323, 1074, 325, + 326, 327, 328, 0, 329, 330, 331, 332, 1076, 794, + 334, 1077, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 346, 347, 348, + 349, 796, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 797, + 365, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 1079, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 403, 404, 405, 406, 2190, 2191, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 430, 431, 432, 1081, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 447, 448, 799, 0, 0, 450, 451, 0, 452, 453, + 454, 455, 456, 457, 458, 0, 459, 1082, 1083, 0, + 0, 462, 463, 800, 465, 801, 1084, 467, 468, 802, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 1085, 0, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, - 511, 512, 513, 514, 515, 0, 0, 0, 0, 0, - 0, 0, 1410, 1411, 0, 0, 0, 0, 0, 1086, - 0, 1087, 0, 0, 0, 0, 1088, 1089, 0, 1090, - 1091, 116, 1042, 815, 1043, 1044, 1045, 1046, 1047, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 117, 118, 119, 120, 121, 122, 123, 124, 0, 125, - 126, 127, 0, 0, 0, 0, 0, 1048, 0, 0, - 128, 129, 130, 0, 131, 132, 133, 134, 135, 136, - 137, -2046, 1049, 140, 1050, 1051, 0, 143, 144, 145, - 146, 147, 148, 1052, 785, 149, 150, 151, 152, 1053, - 1054, 155, 0, 156, 157, 158, 159, 786, 0, 787, - 0, 1055, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 0, 172, 173, 174, 175, 176, 177, 0, 178, - 179, 180, 3478, 182, 183, 184, 185, 186, 187, 188, - 1056, 190, 191, 1057, 193, 1058, 194, 0, 195, 196, - 197, 198, 199, 200, 0, 0, 201, 202, 203, 204, - 0, 0, 205, 206, 1059, 208, 209, 0, 210, 211, - 212, 0, 213, 214, 215, 0, 216, 217, 218, 219, - 1060, 221, 222, 223, 224, 225, 788, 1061, 227, 0, - 228, 229, 1062, 231, 0, 232, 0, 233, 234, 0, - 235, 236, 237, 238, -2046, 240, 0, 241, 0, 1063, - 1064, 244, 245, 0, 246, 247, 248, 249, 250, 251, - 252, -2046, 254, 255, 256, 257, 0, 258, 259, 260, - 261, 262, 263, 264, 0, 265, 266, 267, 268, 269, - 270, 271, 272, 1065, 1066, 0, 1067, 0, 276, 0, - 0, 279, 280, 281, 282, 283, 284, 285, 286, 0, - 0, 287, 288, 289, -2046, 0, 291, 292, 293, 294, - 295, 296, 297, 298, 1068, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 1069, 321, 1070, 323, 324, - 325, 326, 0, 327, 328, 0, 330, 1072, 790, 332, - 1073, 334, 335, 336, 0, 337, 338, 0, 0, 1074, - 340, 341, 0, 0, 342, 343, 344, 345, 346, 347, - 792, 349, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 0, 0, 0, 0, 360, 361, 793, 363, - 364, 365, 366, 367, 368, 369, 0, 370, 371, 372, - 373, 374, 375, 0, 376, 377, 378, 1075, 380, 381, - 382, 383, 0, 384, 385, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, 396, 0, 397, 398, 399, - 400, 401, 402, 1076, 404, 405, 406, 407, 408, 409, - 410, 411, 412, 413, 414, 415, 416, 0, 0, 417, - 418, 419, 420, 421, 422, 423, 424, 425, 0, -2046, - 427, 428, 1077, 430, 0, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, 444, 795, - 0, 0, 446, 447, 0, 448, 449, 450, 451, 452, - 453, 454, 0, 455, 1078, 1079, 0, 0, 458, 459, - 796, 461, 797, 1080, 463, 464, 798, 466, 467, 3479, - 469, 470, 0, 0, 471, 472, 473, 0, 474, 475, - 476, 477, 0, 478, 479, 480, 481, 482, 483, 1081, - 0, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 0, 0, 494, 0, 0, 495, 496, 497, 498, 499, - 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, - 510, 511, 512, 513, 514, 515, -2046, 0, 0, 0, - 0, 0, 0, 1083, 1084, 1085, 0, 0, 0, 0, - 1086, 0, 1087, 0, 0, 0, 0, 1088, 1089, 0, - 1090, 1091, 116, 1042, 815, 1043, 1044, 0, 1046, 1047, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 0, + 0, 0, 0, 0, 0, 0, 2192, 2193, 0, 0, + 0, 0, 0, 1090, 0, 1091, 0, 0, 0, 0, + 1092, 1093, 0, 1094, 1095, 117, 1046, 819, 1047, 1048, + 1049, 1050, 1051, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 1052, 0, 0, 129, 130, 131, 0, 132, 133, + 134, 135, 136, 137, 138, 139, 1053, 141, 1054, 1055, + 0, 144, 145, 146, 147, 148, 149, 1056, 789, 150, + 151, 152, 153, 1057, 1058, 156, 0, 157, 158, 159, + 160, 790, 0, 791, 0, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 1060, 191, 192, 1061, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 1063, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 1064, 222, 223, 224, 225, 226, + 227, 792, 1065, 229, 0, 230, 231, 1066, 233, 0, + 234, 0, 235, 236, 0, 237, 238, 239, 240, 241, + 242, 0, 243, 0, 1067, 1068, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 268, 269, 270, 271, 272, 273, 274, 1069, 1070, + 0, 1071, 0, 278, 0, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 290, 291, 292, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 1072, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 1073, 323, 1074, 325, 326, 327, 328, 0, 329, 330, + 331, 332, 1076, 794, 334, 1077, 336, 337, 338, 0, + 339, 340, 0, 0, 1078, 342, 343, 0, 0, 344, + 345, 346, 347, 348, 349, 796, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 797, 365, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 1079, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 403, 404, 405, 406, + 1080, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 430, 431, 432, 1081, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 447, 448, 799, 0, 0, 450, + 451, 0, 452, 453, 454, 455, 456, 457, 458, 0, + 459, 1082, 1083, 0, 0, 462, 463, 800, 465, 801, + 1084, 467, 468, 802, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 1085, 0, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 0, 0, 0, 0, 0, 0, 0, + 1421, 1422, 0, 0, 0, 0, 0, 1090, 0, 1091, + 0, 0, 0, 0, 1092, 1093, 0, 1094, 1095, 117, + 1046, 819, 1047, 1048, 0, 1050, 1051, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 1052, 0, 0, 129, 130, + 131, 0, 132, 133, 134, 135, 136, 137, 138, 139, + 1053, 141, 1054, 1055, 0, 144, 145, 146, 147, 148, + 149, 1056, 789, 150, 151, 152, 153, 1057, 1058, 156, + 0, 157, 158, 159, 160, 790, 0, 791, 0, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 1060, 191, + 192, 1061, 194, 0, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 1063, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 1064, 222, + 223, 224, 225, 226, 227, 792, 1065, 229, 0, 230, + 231, 1066, 233, 0, 234, 0, 235, 236, 0, 237, + 238, 239, 240, 241, 242, 0, 243, 3054, 1067, 1068, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, -723, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 268, 269, 270, 271, 272, + 273, 274, 1069, 1070, 0, 1071, 0, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 290, 291, 292, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 1073, 323, 1074, 325, 326, 327, + 328, 0, 329, 330, 331, 332, 1076, 794, 334, 1077, + 336, 337, 338, 0, 339, 340, 0, 0, 341, 342, + 343, 0, 0, 344, 345, 346, 347, 348, 349, 796, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 797, 365, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 1079, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 430, 431, 432, 1081, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, + 799, 0, 0, 450, 451, 0, 452, 453, 454, 455, + 456, 457, 458, 0, 459, 1082, 1083, 0, 0, 462, + 463, 800, 465, 801, 1084, 467, 468, 802, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 1085, 0, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 117, 118, 119, 120, 121, 122, 123, 124, 0, - 125, 126, 127, 0, 0, 0, 0, 0, 1048, 0, - 0, 128, 129, 130, 0, 131, 132, 133, 134, 135, - 136, 137, 138, 1049, 140, 1050, 1051, 0, 143, 144, - 145, 146, 147, 148, 1052, 785, 149, 150, 151, 152, - 1053, 1054, 155, 0, 156, 157, 158, 159, 786, 0, - 787, 0, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 0, 172, 173, 174, 175, 176, 177, 0, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 1056, 190, 191, 1057, 193, 0, 194, 0, 195, - 196, 197, 198, 199, 200, 0, 0, 201, 202, 203, - 204, 0, 0, 205, 206, 1059, 208, 209, 0, 210, - 211, 212, 0, 213, 214, 215, 0, 216, 217, 218, - 219, 1060, 221, 222, 223, 224, 225, 788, 1061, 227, - 0, 228, 229, 1062, 231, 0, 232, 0, 233, 234, - 0, 235, 236, 237, 238, 239, 240, 0, 241, 0, - 1063, 1064, 244, 245, 0, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 0, 258, 259, - 260, 261, 262, 263, 264, 0, 265, 266, 267, 268, - 269, 270, 271, 272, 1065, 1066, 0, 1067, 0, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 0, 0, 287, 288, 289, 290, 0, 291, 292, 293, - 294, 295, 296, 297, 298, 1068, 300, 301, 302, 303, + 0, 1090, 0, 2746, 0, 0, 0, 0, 1092, 1093, + 0, 1094, 1095, 117, 1046, 819, 1047, 1048, 0, 1050, + 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 1052, + 0, 0, 129, 130, 131, 0, 132, 133, 134, 135, + 136, 137, 138, 139, 1053, 141, 1054, 1055, 0, 144, + 145, 146, 147, 148, 149, 1056, 789, 150, 151, 152, + 153, 1057, 1058, 156, 0, 157, 158, 159, 160, 790, + 0, 791, 0, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 1060, 191, 192, 1061, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 1063, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 1064, 222, 223, 224, 225, 226, 227, 792, + 1065, 229, 0, 230, 231, 1066, 233, 0, 234, 0, + 235, 236, 0, 237, 238, 239, 240, 241, 242, 0, + 243, 0, 1067, 1068, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 268, + 269, 270, 271, 272, 273, 274, 1069, 1070, 0, 1071, + 0, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 290, 291, 292, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 1069, 321, 1070, 323, - 324, 325, 326, 0, 327, 328, 329, 330, 1072, 790, - 332, 1073, 334, 335, 336, 0, 337, 338, 0, 0, - 339, 340, 341, 0, 0, 342, 343, 344, 345, 346, - 347, 792, 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 0, 0, 0, 0, 360, 361, 793, - 363, 364, 365, 366, 367, 368, 369, 0, 370, 371, - 372, 373, 374, 375, 0, 376, 377, 378, 1075, 380, - 381, 382, 383, 0, 384, 385, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 0, 397, 398, - 399, 400, 401, 402, 2175, 2176, 405, 406, 407, 408, - 409, 410, 411, 412, 413, 414, 415, 416, 0, 0, - 417, 418, 419, 420, 421, 422, 423, 424, 425, 0, - 426, 427, 428, 1077, 430, 0, 431, 432, 433, 434, + 314, 315, 316, 317, 318, 319, 320, 321, 1073, 323, + 1074, 325, 326, 327, 328, 0, 329, 330, 331, 332, + 1076, 794, 334, 1077, 336, 337, 338, 0, 339, 340, + 0, 0, 341, 342, 343, 0, 0, 344, 345, 346, + 347, 348, 349, 796, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 797, 365, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 1079, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 430, 431, 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, - 795, 0, 0, 446, 447, 0, 448, 449, 450, 451, - 452, 453, 454, 0, 455, 1078, 1079, 0, 0, 458, - 459, 796, 461, 797, 1080, 463, 464, 798, 466, 467, - 468, 469, 470, 0, 0, 471, 472, 473, 0, 474, - 475, 476, 477, 0, 478, 479, 480, 481, 482, 483, - 1081, 0, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 0, 0, 494, 0, 0, 495, 496, 497, 498, + 445, 446, 447, 448, 799, 0, 0, 450, 451, 0, + 452, 453, 454, 455, 456, 457, 458, 0, 459, 1082, + 1083, 0, 0, 462, 463, 800, 465, 801, 1084, 467, + 468, 802, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 1085, 0, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, - 509, 510, 511, 512, 513, 514, 515, 0, 0, 0, - 0, 0, 0, 0, 2177, 2178, 0, 0, 0, 0, - 0, 1086, 0, 1087, 0, 0, 0, 0, 1088, 1089, - 0, 1090, 1091, 116, 1042, 815, 1043, 1044, 1045, 1046, - 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 117, 118, 119, 120, 121, 122, 123, 124, - 0, 125, 126, 127, 0, 0, 0, 0, 0, 1048, - 0, 0, 128, 129, 130, 0, 131, 132, 133, 134, - 135, 136, 137, 138, 1049, 140, 1050, 1051, 0, 143, - 144, 145, 146, 147, 148, 1052, 785, 149, 150, 151, - 152, 1053, 1054, 155, 0, 156, 157, 158, 159, 786, - 0, 787, 0, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 0, 172, 173, 174, 175, 176, 177, - 0, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 1056, 190, 191, 1057, 193, 0, 194, 0, - 195, 196, 197, 198, 199, 200, 0, 0, 201, 202, - 203, 204, 0, 0, 205, 206, 1059, 208, 209, 0, - 210, 211, 212, 0, 213, 214, 215, 0, 216, 217, - 218, 219, 1060, 221, 222, 223, 224, 225, 788, 1061, - 227, 0, 228, 229, 1062, 231, 0, 232, 0, 233, - 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, - 0, 1063, 1064, 244, 245, 0, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 0, 258, - 259, 260, 261, 262, 263, 264, 0, 265, 266, 267, - 268, 269, 270, 271, 272, 1065, 1066, 0, 1067, 0, - 276, 0, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 0, 0, 287, 288, 289, 290, 0, 291, 292, - 293, 294, 295, 296, 297, 298, 1068, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 1069, 321, 1070, - 323, 324, 325, 326, 0, 327, 328, 329, 330, 1072, - 790, 332, 1073, 334, 335, 336, 0, 337, 338, 0, - 0, 1074, 340, 341, 0, 0, 342, 343, 344, 345, - 346, 347, 792, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 0, 0, 0, 0, 360, 361, - 793, 363, 364, 365, 366, 367, 368, 369, 0, 370, - 371, 372, 373, 374, 375, 0, 376, 377, 378, 1075, - 380, 381, 382, 383, 0, 384, 385, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 0, 397, - 398, 399, 400, 401, 402, 1076, 404, 405, 406, 407, - 408, 409, 410, 411, 412, 413, 414, 415, 416, 0, - 0, 417, 418, 419, 420, 421, 422, 423, 424, 425, - 0, 426, 427, 428, 1077, 430, 0, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 795, 0, 0, 446, 447, 0, 448, 449, 450, - 451, 452, 453, 454, 0, 455, 1078, 1079, 0, 0, - 458, 459, 796, 461, 797, 1080, 463, 464, 798, 466, - 467, 468, 469, 470, 0, 0, 471, 472, 473, 0, - 474, 475, 476, 477, 0, 478, 479, 480, 481, 482, - 483, 1081, 0, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 0, 0, 494, 0, 0, 495, 496, 497, - 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, - 508, 509, 510, 511, 512, 513, 514, 515, 0, 0, - 0, 0, 0, 0, 0, 1410, 1411, 0, 0, 0, - 0, 0, 1086, 0, 1087, 0, 0, 0, 0, 1088, - 1089, 0, 1090, 1091, 116, 1042, 815, 1043, 1044, 0, - 1046, 1047, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 1048, 0, 0, 128, 129, 130, 0, 131, 132, 133, - 134, 135, 136, 137, 138, 1049, 140, 1050, 1051, 0, - 143, 144, 145, 146, 147, 148, 1052, 785, 149, 150, - 151, 152, 1053, 1054, 155, 0, 156, 157, 158, 159, - 786, 0, 787, 0, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 1056, 190, 191, 1057, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 1059, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 1060, 221, 222, 223, 224, 225, 788, - 1061, 227, 0, 228, 229, 1062, 231, 0, 232, 0, - 233, 234, 0, 235, 236, 237, 238, 239, 240, 0, - 241, 3036, 1063, 1064, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, -718, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 266, - 267, 268, 269, 270, 271, 272, 1065, 1066, 0, 1067, - 0, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 288, 289, 290, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 1068, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 1069, 321, - 1070, 323, 324, 325, 326, 0, 327, 328, 329, 330, - 1072, 790, 332, 1073, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 345, 346, 347, 792, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 793, 363, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 1075, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 426, 427, 428, 1077, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, 444, 795, 0, 0, 446, 447, 0, 448, 449, - 450, 451, 452, 453, 454, 0, 455, 1078, 1079, 0, - 0, 458, 459, 796, 461, 797, 1080, 463, 464, 798, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 1081, 0, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 0, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1090, 0, 2746, 0, 0, + 0, 0, 1092, 1093, 0, 1094, 1095, 117, 1046, 819, + 1047, 1048, 0, 1050, 1051, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 1052, 0, 0, 129, 130, 131, 0, + 132, 133, 134, 135, 136, 137, 138, 139, 1053, 141, + 1054, 1055, 0, 144, 145, 146, 147, 148, 149, 1056, + 789, 150, 151, 152, 153, 1057, 1058, 156, 0, 157, + 158, 159, 160, 790, 0, 791, 0, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 1060, 191, 192, 1061, + 194, 0, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 1063, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 1064, 222, 223, 224, + 225, 226, 227, 792, 1065, 229, 0, 230, 231, 1066, + 233, 0, 234, 0, 235, 236, 0, 237, 238, 239, + 240, 241, 242, 0, 243, 0, 1067, 1068, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 268, 269, 270, 271, 272, 273, 274, + 1069, 1070, 0, 1071, 0, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 290, + 291, 292, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 1072, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 1073, 323, 1074, 325, 326, 327, 328, 0, + 329, 330, 331, 332, 1076, 794, 334, 1077, 336, 337, + 338, 0, 339, 340, 0, 0, 341, 342, 343, 0, + 0, 344, 345, 346, 347, 348, 349, 796, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 797, 365, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 1079, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 403, 404, + 405, 406, 1080, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 430, 431, + 432, 1081, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 799, 0, + 0, 450, 451, 0, 452, 453, 454, 455, 456, 457, + 458, 0, 459, 1082, 1083, 0, 0, 462, 463, 800, + 465, 801, 1084, 467, 468, 802, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 1085, 0, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1090, + 0, 1091, 0, 0, 0, 0, 1092, 1093, 0, 1094, + 1095, 117, 1046, 819, 1047, 1048, 1049, 1050, 1051, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1086, 0, 2729, 0, 0, 0, 0, - 1088, 1089, 0, 1090, 1091, 116, 1042, 815, 1043, 1044, - 0, 1046, 1047, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 117, 118, 119, 120, 121, 122, - 123, 124, 0, 125, 126, 127, 0, 0, 0, 0, - 0, 1048, 0, 0, 128, 129, 130, 0, 131, 132, - 133, 134, 135, 136, 137, 138, 1049, 140, 1050, 1051, - 0, 143, 144, 145, 146, 147, 148, 1052, 785, 149, - 150, 151, 152, 1053, 1054, 155, 0, 156, 157, 158, - 159, 786, 0, 787, 0, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 0, 172, 173, 174, 175, - 176, 177, 0, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 1056, 190, 191, 1057, 193, 0, - 194, 0, 195, 196, 197, 198, 199, 200, 0, 0, - 201, 202, 203, 204, 0, 0, 205, 206, 1059, 208, - 209, 0, 210, 211, 212, 0, 213, 214, 215, 0, - 216, 217, 218, 219, 1060, 221, 222, 223, 224, 225, - 788, 1061, 227, 0, 228, 229, 1062, 231, 0, 232, - 0, 233, 234, 0, 235, 236, 237, 238, 239, 240, - 0, 241, 0, 1063, 1064, 244, 245, 0, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 0, 258, 259, 260, 261, 262, 263, 264, 0, 265, - 266, 267, 268, 269, 270, 271, 272, 1065, 1066, 0, - 1067, 0, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 0, 0, 287, 288, 289, 290, 0, - 291, 292, 293, 294, 295, 296, 297, 298, 1068, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 1069, - 321, 1070, 323, 324, 325, 326, 0, 327, 328, 329, - 330, 1072, 790, 332, 1073, 334, 335, 336, 0, 337, - 338, 0, 0, 339, 340, 341, 0, 0, 342, 343, - 344, 345, 346, 347, 792, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 0, 0, 0, 0, - 360, 361, 793, 363, 364, 365, 366, 367, 368, 369, - 0, 370, 371, 372, 373, 374, 375, 0, 376, 377, - 378, 1075, 380, 381, 382, 383, 0, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 0, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 0, 0, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 0, 426, 427, 428, 1077, 430, 0, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, 444, 795, 0, 0, 446, 447, 0, 448, - 449, 450, 451, 452, 453, 454, 0, 455, 1078, 1079, - 0, 0, 458, 459, 796, 461, 797, 1080, 463, 464, - 798, 466, 467, 468, 469, 470, 0, 0, 471, 472, - 473, 0, 474, 475, 476, 477, 0, 478, 479, 480, - 481, 482, 483, 1081, 0, 485, 486, 487, 488, 489, - 490, 491, 492, 493, 0, 0, 494, 0, 0, 495, - 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, - 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 1052, 0, 0, + 129, 130, 131, 0, 132, 133, 134, 135, 136, 137, + 138, 0, 1053, 141, 1054, 1055, 0, 144, 145, 146, + 147, 148, 149, 1056, 789, 150, 151, 152, 153, 1057, + 1058, 156, 0, 157, 158, 159, 160, 790, 0, 791, + 0, 1059, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 1060, 191, 192, 1061, 194, 1062, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 1063, 209, 210, 0, 211, 212, + 213, 0, 214, 0, 216, 0, 217, 218, 219, 220, + 1064, 222, 223, 224, 225, 226, 227, 792, 1065, 229, + 0, 230, 231, 1066, 233, 0, 234, 0, 235, 236, + 0, 237, 238, 239, 240, 0, 242, 0, 243, 0, + 1067, 1068, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 0, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 268, 269, 270, + 271, 272, 273, 274, 1069, 1070, 0, 1071, 0, 278, + 0, 0, 281, 282, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 290, 291, 0, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 1072, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 1073, 323, 1074, 325, + 326, 327, 328, 0, 329, 330, 0, 332, 1076, 794, + 334, 1077, 336, 337, 338, 0, 339, 340, 0, 0, + 1078, 342, 343, 0, 0, 344, 345, 346, 347, 348, + 349, 796, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 797, + 365, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 1079, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 403, 404, 405, 406, 1080, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 0, 431, 432, 1081, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 447, 448, 799, 0, 0, 450, 451, 0, 452, 453, + 454, 455, 456, 457, 458, 0, 459, 1082, 1083, 0, + 0, 462, 463, 800, 465, 801, 1084, 467, 468, 802, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 1085, 0, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 0, + 0, 0, 0, 0, 0, 0, 1087, 1088, 1089, 0, + 970, 1350, 819, 1090, 0, 1091, 1050, 0, 0, 0, + 1092, 1093, 0, 1094, 1095, 0, 0, 0, 0, 118, + 119, 120, 121, 122, 123, 124, 125, 0, 126, 127, + 128, 0, 0, 0, 564, 0, 0, 0, 0, 569, + 130, 131, 0, 132, 133, 134, 571, 136, 137, 138, + 572, 573, 574, 575, 576, 0, 144, 145, 146, 147, + 148, 149, 0, 0, 150, 151, 152, 153, 580, 581, + 156, 0, 157, 158, 159, 160, 583, 0, 585, 0, + 587, 164, 165, 166, 167, 168, 588, 170, 171, 172, + 0, 173, 174, 175, 176, 177, 178, 0, 591, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 593, + 191, 192, 594, 194, 0, 195, 0, 196, 197, 198, + 199, 200, 201, 0, 0, 202, 203, 204, 205, 0, + 0, 206, 207, 208, 209, 210, 0, 211, 212, 213, + 0, 214, 215, 216, 0, 217, 218, 219, 220, 604, + 222, 223, 224, 225, 226, 227, 605, 1351, 229, 0, + 230, 231, 608, 233, 0, 234, 0, 235, 611, 0, + 613, 238, 239, 614, 615, 242, 0, 243, 0, 618, + 619, 246, 247, 0, 248, 249, 250, 251, 252, 253, + 254, 621, 256, 257, 258, 259, 0, 260, 261, 262, + 263, 264, 265, 266, 0, 267, 624, 625, 270, 271, + 272, 273, 274, 626, 627, 0, 629, 0, 278, 631, + 632, 281, 633, 283, 284, 285, 286, 287, 288, 0, + 0, 289, 636, 291, 637, 0, 293, 294, 295, 296, + 297, 298, 299, 300, 639, 302, 303, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 640, 641, 642, 325, 326, + 327, 643, 0, 329, 330, 645, 332, 0, 647, 334, + 648, 336, 337, 338, 0, 339, 340, 1352, 0, 341, + 342, 343, 0, 0, 344, 345, 654, 655, 348, 656, + 657, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 0, 0, 0, 0, 362, 363, 662, 663, + 366, 367, 664, 369, 370, 371, 0, 372, 373, 374, + 375, 376, 377, 0, 378, 379, 380, 381, 382, 667, + 384, 385, 386, 387, 0, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 0, 401, + 402, 670, 404, 405, 406, 671, 408, 409, 410, 411, + 412, 413, 414, 415, 416, 417, 418, 419, 420, 0, + 673, 421, 422, 423, 424, 425, 426, 674, 428, 429, + 0, 676, 431, 432, 677, 434, 0, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, 679, + 448, 680, 0, 0, 450, 451, 0, 452, 684, 454, + 455, 456, 457, 458, 0, 459, 686, 687, 0, 0, + 462, 463, 690, 465, 691, 1353, 467, 468, 693, 470, + 471, 472, 473, 474, 0, 0, 475, 476, 477, 0, + 478, 479, 480, 481, 0, 482, 483, 484, 485, 486, + 698, 699, 0, 489, 701, 491, 492, 493, 494, 495, + 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, + 502, 503, 504, 706, 707, 708, 709, 710, 711, 712, + 713, 714, 715, 716, 516, 517, 518, 519, 0, 0, + 0, 0, 527, 0, 0, 1354, 1355, 2365, 0, 0, + 0, 0, 2366, 0, 2367, 0, 0, 0, 0, 0, + 1093, 118, 119, 120, 121, 122, 123, 124, 125, 0, + 126, 127, 128, 0, 0, 0, 0, 0, 0, 1005, + 0, 0, 130, 131, 0, 132, 133, 134, 0, 136, + 137, 138, 139, 140, 0, 142, 143, 0, 144, 145, + 146, 147, 148, 149, 0, 0, 150, 151, 152, 153, + 154, 155, 156, 0, 157, 158, 159, 160, 161, 0, + 0, 0, 163, 164, 165, 166, 167, 168, 0, 170, + 171, 172, 0, 173, 174, 175, 176, 177, 178, 0, + 0, 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 0, 195, 0, 196, + 197, 198, 199, 200, 201, 0, 0, 202, 203, 204, + 205, 0, 0, 206, 207, 208, 209, 210, 0, 211, + 212, 213, 0, 214, 215, 216, -530, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 0, + 229, -530, 230, 231, 232, 233, -530, 234, 0, 235, + 0, 0, 0, 238, 239, 528, 0, 242, 0, 243, + 0, 244, 245, 246, 247, 0, 248, 249, 250, 251, + 252, 253, 254, 0, 256, 257, 258, 259, 0, 260, + 261, 262, 263, 264, 265, 266, 0, 267, 0, 269, + 270, 271, 272, 273, 274, 275, 276, -530, 277, 0, + 278, 0, 0, 281, 0, 283, 284, 285, 286, 287, + 288, 0, 0, 289, 0, 291, 0, -530, 293, 294, + 295, 296, 297, 298, 299, 300, 529, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 0, 324, + 325, 326, 327, 328, 0, 329, 330, 0, 332, 0, + 333, 334, 335, 336, 337, 338, -530, 339, 340, 0, + 0, 341, 342, 343, 0, -530, 344, 345, 346, 0, + 348, 0, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, 361, 0, 0, 0, 0, 362, 363, + 364, 0, 366, 367, 368, 369, 370, 371, 0, 372, + 373, 374, 375, 376, 377, 0, 378, 379, 380, 381, + 382, 383, 384, 385, 386, 387, 0, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 0, 0, 421, 422, 423, 424, 425, 426, 427, + 428, 429, 0, 0, 431, 432, 433, 434, 0, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, 530, 448, 449, 0, 0, 450, 451, 0, 452, + 0, 454, 455, 456, 457, 458, 0, 459, 460, 461, + 0, 0, 462, 463, 464, 465, 466, 0, 467, 468, + 469, 470, 471, 472, 473, 474, -530, 0, 475, 476, + 477, 0, 478, 479, 480, 481, 0, 482, 483, 484, + 485, 486, 487, 488, 0, 489, 0, 491, 492, 493, + 494, 495, 496, 497, 0, 0, 498, 0, 0, 499, + 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, + 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, + 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1164, 0, 118, + 119, 120, 121, 122, 123, 124, 125, 0, 126, 127, + 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 130, 131, 0, 132, 133, 134, 0, 136, 137, 138, + 139, 140, 0, 142, 143, 0, 144, 145, 146, 147, + 148, 149, 0, 0, 150, 151, 152, 153, 154, 155, + 156, 0, 157, 158, 159, 160, 161, 0, 0, 0, + 163, 164, 165, 166, 167, 168, 0, 170, 171, 172, + 0, 173, 174, 175, 176, 177, 178, 0, 0, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 0, 195, 0, 196, 197, 198, + 199, 200, 201, 0, 0, 202, 203, 204, 205, 0, + 0, 206, 207, 208, 209, 210, 0, 211, 212, 213, + 0, 214, 215, 216, 0, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 0, 229, 0, + 230, 231, 232, 233, 0, 234, 0, 235, 0, 0, + 0, 238, 239, 528, 0, 242, 0, 243, 0, 244, + 245, 246, 247, 0, 248, 249, 250, 251, 252, 253, + 254, 0, 256, 257, 258, 259, 0, 260, 261, 262, + 263, 264, 265, 266, 0, 267, 0, 269, 270, 271, + 272, 273, 274, 275, 276, 0, 277, 0, 278, 0, + 0, 281, 0, 283, 284, 285, 286, 287, 288, 0, + 0, 289, 0, 291, 0, 0, 293, 294, 295, 296, + 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 0, 324, 325, 326, + 327, 328, 0, 329, 330, 0, 332, 0, 333, 334, + 335, 336, 337, 338, 0, 339, 340, 0, 0, 341, + 342, 343, 0, 0, 344, 345, 346, 0, 348, 0, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 0, 0, 0, 0, 362, 363, 364, 0, + 366, 367, 368, 369, 370, 371, 0, 372, 373, 374, + 375, 376, 377, 0, 378, 379, 380, 381, 382, 383, + 384, 385, 386, 387, 0, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 0, 401, + 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 416, 417, 418, 419, 420, 0, + 0, 421, 422, 423, 424, 425, 426, 427, 428, 429, + 0, 0, 431, 432, 433, 434, 0, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, 530, + 448, 449, 0, 0, 450, 451, 0, 452, 0, 454, + 455, 456, 457, 458, 0, 459, 460, 461, 0, 0, + 462, 463, 464, 465, 466, 0, 467, 468, 469, 470, + 471, 472, 473, 474, 0, 0, 475, 476, 477, 0, + 478, 479, 480, 481, 0, 482, 483, 484, 485, 486, + 487, 488, 0, 489, 0, 491, 492, 493, 494, 495, + 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, + 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, + 512, 513, 514, 515, 516, 517, 518, 519, 970, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1086, 0, 2729, 0, 0, 0, - 0, 1088, 1089, 0, 1090, 1091, 116, 1042, 815, 1043, - 1044, 0, 1046, 1047, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 117, 118, 119, 120, 121, - 122, 123, 124, 0, 125, 126, 127, 0, 0, 0, - 0, 0, 1048, 0, 0, 128, 129, 130, 0, 131, - 132, 133, 134, 135, 136, 137, 138, 1049, 140, 1050, - 1051, 0, 143, 144, 145, 146, 147, 148, 1052, 785, - 149, 150, 151, 152, 1053, 1054, 155, 0, 156, 157, - 158, 159, 786, 0, 787, 0, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 0, 172, 173, 174, - 175, 176, 177, 0, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 1056, 190, 191, 1057, 193, - 0, 194, 0, 195, 196, 197, 198, 199, 200, 0, - 0, 201, 202, 203, 204, 0, 0, 205, 206, 1059, - 208, 209, 0, 210, 211, 212, 0, 213, 214, 215, - 0, 216, 217, 218, 219, 1060, 221, 222, 223, 224, - 225, 788, 1061, 227, 0, 228, 229, 1062, 231, 0, - 232, 0, 233, 234, 0, 235, 236, 237, 238, 239, - 240, 0, 241, 0, 1063, 1064, 244, 245, 0, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 0, 258, 259, 260, 261, 262, 263, 264, 0, - 265, 266, 267, 268, 269, 270, 271, 272, 1065, 1066, - 0, 1067, 0, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 0, 0, 287, 288, 289, 290, - 0, 291, 292, 293, 294, 295, 296, 297, 298, 1068, + 0, 0, 0, 0, 2452, 3238, 0, 118, 119, 120, + 121, 122, 123, 124, 125, 0, 126, 127, 128, 3, + 4, 0, 564, 0, 0, 0, 0, 569, 130, 131, + 0, 132, 133, 134, 571, 136, 137, 138, 572, 573, + 574, 575, 576, 0, 144, 145, 146, 147, 148, 149, + 0, 0, 150, 151, 152, 153, 580, 581, 156, 0, + 157, 158, 159, 160, 583, 0, 585, 0, 587, 164, + 165, 166, 167, 168, 588, 170, 171, 172, 0, 173, + 174, 175, 176, 177, 178, 0, 591, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 593, 191, 192, + 594, 194, 0, 195, 0, 196, 197, 198, 199, 200, + 201, 14, 15, 202, 203, 204, 205, 0, 0, 206, + 207, 208, 209, 210, 0, 211, 212, 213, 0, 214, + 215, 216, 0, 217, 218, 219, 220, 604, 222, 223, + 224, 225, 226, 227, 605, 0, 229, 0, 230, 231, + 608, 233, 0, 234, 0, 235, 611, 23, 613, 238, + 239, 614, 615, 242, 0, 243, 0, 618, 619, 246, + 247, 0, 248, 249, 250, 251, 252, 253, 254, 621, + 256, 257, 258, 259, 0, 260, 261, 262, 263, 264, + 265, 266, 0, 267, 624, 625, 270, 271, 272, 273, + 274, 626, 627, 0, 629, 0, 278, 631, 632, 281, + 633, 283, 284, 285, 286, 287, 288, 0, 0, 289, + 636, 291, 637, 0, 293, 294, 295, 296, 297, 298, + 299, 300, 639, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 640, 641, 642, 325, 326, 327, 643, + 0, 329, 330, 645, 332, 0, 647, 334, 648, 336, + 337, 338, 0, 339, 340, 0, 0, 341, 342, 343, + 0, 0, 344, 345, 654, 655, 348, 656, 657, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 26, 27, 28, 0, 362, 363, 662, 663, 366, 367, + 664, 369, 370, 371, 0, 372, 373, 374, 375, 376, + 377, 0, 378, 379, 380, 381, 382, 667, 384, 385, + 386, 387, 0, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 0, 401, 402, 670, + 404, 405, 406, 671, 408, 409, 410, 411, 412, 413, + 414, 415, 416, 417, 418, 419, 420, 33, 673, 421, + 422, 423, 424, 425, 426, 674, 428, 429, 35, 676, + 431, 432, 677, 434, 0, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, 679, 448, 680, + 37, 0, 450, 451, 38, 452, 684, 454, 455, 456, + 457, 458, 0, 459, 686, 687, 0, 0, 462, 463, + 690, 465, 691, 0, 467, 468, 693, 470, 471, 472, + 473, 474, 0, 0, 475, 476, 477, 40, 478, 479, + 480, 481, 0, 482, 483, 484, 485, 486, 971, 699, + 0, 489, 701, 491, 492, 493, 494, 495, 496, 497, + 0, 0, 498, 0, 44, 499, 500, 501, 502, 503, + 504, 706, 707, 708, 709, 710, 711, 712, 713, 714, + 715, 716, 516, 517, 518, 519, 0, 117, 45, 553, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 46, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 129, 130, 131, 0, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 0, 144, 145, 146, 147, 148, 149, 0, + 789, 150, 151, 152, 153, 154, 155, 156, 0, 157, + 158, 159, 160, 790, 0, 791, 0, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 0, 195, 0, 196, 197, 198, 199, 200, 201, + 14, 15, 202, 203, 204, 205, 0, 0, 206, 207, + 208, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 792, 0, 229, 0, 230, 231, 232, + 233, 0, 234, 0, 235, 236, 23, 237, 238, 239, + 240, 241, 242, 0, 243, 0, 244, 245, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 0, 277, 0, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 793, 0, 289, 290, + 291, 292, 0, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 1069, 321, 1070, 323, 324, 325, 326, 0, 327, 328, - 329, 330, 1072, 790, 332, 1073, 334, 335, 336, 0, - 337, 338, 0, 0, 339, 340, 341, 0, 0, 342, - 343, 344, 345, 346, 347, 792, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 0, 0, 0, - 0, 360, 361, 793, 363, 364, 365, 366, 367, 368, - 369, 0, 370, 371, 372, 373, 374, 375, 0, 376, - 377, 378, 1075, 380, 381, 382, 383, 0, 384, 385, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 0, 397, 398, 399, 400, 401, 402, 1076, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 0, 0, 417, 418, 419, 420, 421, 422, - 423, 424, 425, 0, 426, 427, 428, 1077, 430, 0, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 443, 444, 795, 0, 0, 446, 447, 0, - 448, 449, 450, 451, 452, 453, 454, 0, 455, 1078, - 1079, 0, 0, 458, 459, 796, 461, 797, 1080, 463, - 464, 798, 466, 467, 468, 469, 470, 0, 0, 471, - 472, 473, 0, 474, 475, 476, 477, 0, 478, 479, - 480, 481, 482, 483, 1081, 0, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 0, 0, 494, 0, 0, - 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, + 320, 321, 322, 323, 324, 325, 326, 327, 328, 0, + 329, 330, 331, 332, 0, 794, 334, 335, 336, 337, + 338, 0, 339, 340, 0, 795, 341, 342, 343, 0, + 0, 344, 345, 346, 347, 348, 349, 796, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 26, + 27, 28, 0, 362, 363, 797, 365, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 403, 404, + 405, 406, 407, 798, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 33, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 35, 430, 431, + 432, 433, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 799, 37, + 0, 450, 451, 38, 452, 453, 454, 455, 456, 457, + 458, 0, 459, 460, 461, 0, 0, 462, 463, 800, + 465, 801, 0, 467, 468, 802, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 40, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 803, 488, 0, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 44, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, - 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1086, 0, 1087, 0, 0, - 0, 0, 1088, 1089, 0, 1090, 1091, 116, 1042, 815, - 1043, 1044, 1045, 1046, 1047, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 117, 118, 119, 120, - 121, 122, 123, 124, 0, 125, 126, 127, 0, 0, - 0, 0, 0, 1048, 0, 0, 128, 129, 130, 0, - 131, 132, 133, 134, 135, 136, 137, 0, 1049, 140, - 1050, 1051, 0, 143, 144, 145, 146, 147, 148, 1052, - 785, 149, 150, 151, 152, 1053, 1054, 155, 0, 156, - 157, 158, 159, 786, 0, 787, 0, 1055, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 0, 172, 173, - 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, - 183, 184, 185, 186, 187, 188, 1056, 190, 191, 1057, - 193, 1058, 194, 0, 195, 196, 197, 198, 199, 200, - 0, 0, 201, 202, 203, 204, 0, 0, 205, 206, - 1059, 208, 209, 0, 210, 211, 212, 0, 213, 0, - 215, 0, 216, 217, 218, 219, 1060, 221, 222, 223, - 224, 225, 788, 1061, 227, 0, 228, 229, 1062, 231, - 0, 232, 0, 233, 234, 0, 235, 236, 237, 238, - 0, 240, 0, 241, 0, 1063, 1064, 244, 245, 0, - 246, 247, 248, 249, 250, 251, 252, 0, 254, 255, - 256, 257, 0, 258, 259, 260, 261, 262, 263, 264, - 0, 265, 266, 267, 268, 269, 270, 271, 272, 1065, - 1066, 0, 1067, 0, 276, 0, 0, 279, 280, 281, - 282, 283, 284, 285, 286, 0, 0, 287, 288, 289, - 0, 0, 291, 292, 293, 294, 295, 296, 297, 298, - 1068, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 1069, 321, 1070, 323, 324, 325, 326, 0, 327, - 328, 0, 330, 1072, 790, 332, 1073, 334, 335, 336, - 0, 337, 338, 0, 0, 1074, 340, 341, 0, 0, - 342, 343, 344, 345, 346, 347, 792, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 0, 0, - 0, 0, 360, 361, 793, 363, 364, 365, 366, 367, - 368, 369, 0, 370, 371, 372, 373, 374, 375, 0, - 376, 377, 378, 1075, 380, 381, 382, 383, 0, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 0, 397, 398, 399, 400, 401, 402, 1076, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, - 414, 415, 416, 0, 0, 417, 418, 419, 420, 421, - 422, 423, 424, 425, 0, 0, 427, 428, 1077, 430, - 0, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, 444, 795, 0, 0, 446, 447, - 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, - 1078, 1079, 0, 0, 458, 459, 796, 461, 797, 1080, - 463, 464, 798, 466, 467, 468, 469, 470, 0, 0, - 471, 472, 473, 0, 474, 475, 476, 477, 0, 478, - 479, 480, 481, 482, 483, 1081, 0, 485, 486, 487, - 488, 489, 490, 491, 492, 493, 0, 0, 494, 0, - 0, 495, 496, 497, 498, 499, 500, 501, 502, 503, - 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, - 514, 515, 0, 0, 0, 0, 0, 0, 0, 1083, - 1084, 1085, 0, 964, 1341, 815, 1086, 0, 1087, 1046, - 0, 0, 0, 1088, 1089, 0, 1090, 1091, 0, 0, - 0, 0, 117, 118, 119, 120, 121, 122, 123, 124, - 0, 125, 126, 127, 0, 0, 0, 560, 0, 0, - 0, 0, 565, 129, 130, 0, 131, 132, 133, 567, - 135, 136, 137, 568, 569, 570, 571, 572, 0, 143, - 144, 145, 146, 147, 148, 0, 0, 149, 150, 151, - 152, 576, 577, 155, 0, 156, 157, 158, 159, 579, - 0, 581, 0, 583, 163, 164, 165, 166, 167, 584, - 169, 170, 171, 0, 172, 173, 174, 175, 176, 177, - 0, 587, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 589, 190, 191, 590, 193, 0, 194, 0, - 195, 196, 197, 198, 199, 200, 0, 0, 201, 202, - 203, 204, 0, 0, 205, 206, 207, 208, 209, 0, - 210, 211, 212, 0, 213, 214, 215, 0, 216, 217, - 218, 219, 600, 221, 222, 223, 224, 225, 601, 1342, - 227, 0, 228, 229, 604, 231, 0, 232, 0, 233, - 607, 0, 609, 236, 237, 610, 611, 240, 0, 241, - 0, 614, 615, 244, 245, 0, 246, 247, 248, 249, - 250, 251, 252, 617, 254, 255, 256, 257, 0, 258, - 259, 260, 261, 262, 263, 264, 0, 265, 620, 621, - 268, 269, 270, 271, 272, 622, 623, 0, 625, 0, - 276, 627, 628, 279, 629, 281, 282, 283, 284, 285, - 286, 0, 0, 287, 632, 289, 633, 0, 291, 292, - 293, 294, 295, 296, 297, 298, 635, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, 314, 315, 316, 317, 318, 319, 636, 637, 638, - 323, 324, 325, 639, 0, 327, 328, 641, 330, 0, - 643, 332, 644, 334, 335, 336, 0, 337, 338, 1343, - 0, 339, 340, 341, 0, 0, 342, 343, 650, 651, - 346, 652, 653, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 0, 0, 0, 0, 360, 361, - 658, 659, 364, 365, 660, 367, 368, 369, 0, 370, - 371, 372, 373, 374, 375, 0, 376, 377, 378, 663, - 380, 381, 382, 383, 0, 384, 385, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 0, 397, - 398, 666, 400, 401, 402, 667, 404, 405, 406, 407, - 408, 409, 410, 411, 412, 413, 414, 415, 416, 0, - 669, 417, 418, 419, 420, 421, 422, 670, 424, 425, - 0, 672, 427, 428, 673, 430, 0, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 675, - 444, 676, 0, 0, 446, 447, 0, 448, 680, 450, - 451, 452, 453, 454, 0, 455, 682, 683, 0, 0, - 458, 459, 686, 461, 687, 1344, 463, 464, 689, 466, - 467, 468, 469, 470, 0, 0, 471, 472, 473, 0, - 474, 475, 476, 477, 0, 478, 479, 480, 481, 482, - 694, 695, 0, 485, 697, 487, 488, 489, 490, 491, - 492, 493, 0, 0, 494, 0, 0, 495, 496, 497, - 498, 499, 500, 702, 703, 704, 705, 706, 707, 708, - 709, 710, 711, 712, 512, 513, 514, 515, 0, 0, - 0, 0, 523, 0, 0, 1345, 1346, 2350, 0, 0, - 0, 0, 2351, 0, 2352, 0, 0, 0, 0, 0, - 1089, 117, 118, 119, 120, 121, 122, 123, 124, 0, - 125, 126, 127, 0, 0, 0, 0, 0, 0, 1000, - 0, 0, 129, 130, 0, 131, 132, 133, 0, 135, - 136, 137, 138, 139, 0, 141, 142, 0, 143, 144, - 145, 146, 147, 148, 0, 0, 149, 150, 151, 152, - 153, 154, 155, 0, 156, 157, 158, 159, 160, 0, - 0, 0, 162, 163, 164, 165, 166, 167, 0, 169, - 170, 171, 0, 172, 173, 174, 175, 176, 177, 0, - 0, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 0, 194, 0, 195, - 196, 197, 198, 199, 200, 0, 0, 201, 202, 203, - 204, 0, 0, 205, 206, 207, 208, 209, 0, 210, - 211, 212, 0, 213, 214, 215, -525, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 0, 227, - -525, 228, 229, 230, 231, -525, 232, 0, 233, 0, - 0, 0, 236, 237, 524, 0, 240, 0, 241, 0, - 242, 243, 244, 245, 0, 246, 247, 248, 249, 250, - 251, 252, 0, 254, 255, 256, 257, 0, 258, 259, - 260, 261, 262, 263, 264, 0, 265, 0, 267, 268, - 269, 270, 271, 272, 273, 274, -525, 275, 0, 276, - 0, 0, 279, 0, 281, 282, 283, 284, 285, 286, - 0, 0, 287, 0, 289, 0, -525, 291, 292, 293, - 294, 295, 296, 297, 298, 525, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 0, 322, 323, - 324, 325, 326, 0, 327, 328, 0, 330, 0, 331, - 332, 333, 334, 335, 336, -525, 337, 338, 0, 0, - 339, 340, 341, 0, -525, 342, 343, 344, 0, 346, - 0, 348, 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 0, 0, 0, 0, 360, 361, 362, - 0, 364, 365, 366, 367, 368, 369, 0, 370, 371, - 372, 373, 374, 375, 0, 376, 377, 378, 379, 380, - 381, 382, 383, 0, 384, 385, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 0, 397, 398, - 0, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, 412, 413, 414, 415, 416, 0, 0, - 417, 418, 419, 420, 421, 422, 423, 424, 425, 0, - 0, 427, 428, 429, 430, 0, 431, 432, 433, 434, - 435, 436, 437, 438, 439, 440, 441, 442, 526, 444, - 445, 0, 0, 446, 447, 0, 448, 0, 450, 451, - 452, 453, 454, 0, 455, 456, 457, 0, 0, 458, - 459, 460, 461, 462, 0, 463, 464, 465, 466, 467, - 468, 469, 470, -525, 0, 471, 472, 473, 0, 474, - 475, 476, 477, 0, 478, 479, 480, 481, 482, 483, - 484, 0, 485, 0, 487, 488, 489, 490, 491, 492, - 493, 0, 0, 494, 0, 0, 495, 496, 497, 498, - 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, - 509, 510, 511, 512, 513, 514, 515, 523, 0, 549, + 515, 516, 517, 518, 519, 0, 117, 45, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1159, 0, 117, 118, 119, 120, - 121, 122, 123, 124, 0, 125, 126, 127, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 129, 130, 0, - 131, 132, 133, 0, 135, 136, 137, 138, 139, 0, - 141, 142, 0, 143, 144, 145, 146, 147, 148, 0, - 0, 149, 150, 151, 152, 153, 154, 155, 0, 156, - 157, 158, 159, 160, 0, 0, 0, 162, 163, 164, - 165, 166, 167, 0, 169, 170, 171, 0, 172, 173, - 174, 175, 176, 177, 0, 0, 179, 180, 181, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 0, 194, 0, 195, 196, 197, 198, 199, 200, - 0, 0, 201, 202, 203, 204, 0, 0, 205, 206, - 207, 208, 209, 0, 210, 211, 212, 0, 213, 214, - 215, 0, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 0, 227, 0, 228, 229, 230, 231, - 0, 232, 0, 233, 0, 0, 0, 236, 237, 524, - 0, 240, 0, 241, 0, 242, 243, 244, 245, 0, - 246, 247, 248, 249, 250, 251, 252, 0, 254, 255, - 256, 257, 0, 258, 259, 260, 261, 262, 263, 264, - 0, 265, 0, 267, 268, 269, 270, 271, 272, 273, - 274, 0, 275, 0, 276, 0, 0, 279, 0, 281, - 282, 283, 284, 285, 286, 0, 0, 287, 0, 289, - 0, 0, 291, 292, 293, 294, 295, 296, 297, 298, - 525, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 0, 322, 323, 324, 325, 326, 0, 327, - 328, 0, 330, 0, 331, 332, 333, 334, 335, 336, - 0, 337, 338, 0, 0, 339, 340, 341, 0, 0, - 342, 343, 344, 0, 346, 0, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 0, 0, - 0, 0, 360, 361, 362, 0, 364, 365, 366, 367, - 368, 369, 0, 370, 371, 372, 373, 374, 375, 0, - 376, 377, 378, 379, 380, 381, 382, 383, 0, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 0, 397, 398, 0, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, - 414, 415, 416, 0, 0, 417, 418, 419, 420, 421, - 422, 423, 424, 425, 0, 0, 427, 428, 429, 430, - 0, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 526, 444, 445, 0, 0, 446, 447, - 0, 448, 0, 450, 451, 452, 453, 454, 0, 455, - 456, 457, 0, 0, 458, 459, 460, 461, 462, 0, - 463, 464, 465, 466, 467, 468, 469, 470, 0, 0, - 471, 472, 473, 0, 474, 475, 476, 477, 0, 478, - 479, 480, 481, 482, 483, 484, 0, 485, 0, 487, - 488, 489, 490, 491, 492, 493, 0, 0, 494, 0, - 0, 495, 496, 497, 498, 499, 500, 501, 502, 503, - 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, - 514, 515, 964, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2439, 3220, - 0, 117, 118, 119, 120, 121, 122, 123, 124, 0, - 125, 126, 127, 3, 4, 0, 560, 0, 0, 0, - 0, 565, 129, 130, 0, 131, 132, 133, 567, 135, - 136, 137, 568, 569, 570, 571, 572, 0, 143, 144, - 145, 146, 147, 148, 0, 0, 149, 150, 151, 152, - 576, 577, 155, 0, 156, 157, 158, 159, 579, 0, - 581, 0, 583, 163, 164, 165, 166, 167, 584, 169, - 170, 171, 0, 172, 173, 174, 175, 176, 177, 0, - 587, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 589, 190, 191, 590, 193, 0, 194, 0, 195, - 196, 197, 198, 199, 200, 14, 15, 201, 202, 203, - 204, 0, 0, 205, 206, 207, 208, 209, 0, 210, - 211, 212, 0, 213, 214, 215, 0, 216, 217, 218, - 219, 600, 221, 222, 223, 224, 225, 601, 0, 227, - 0, 228, 229, 604, 231, 0, 232, 0, 233, 607, - 23, 609, 236, 237, 610, 611, 240, 0, 241, 0, - 614, 615, 244, 245, 0, 246, 247, 248, 249, 250, - 251, 252, 617, 254, 255, 256, 257, 0, 258, 259, - 260, 261, 262, 263, 264, 0, 265, 620, 621, 268, - 269, 270, 271, 272, 622, 623, 0, 625, 0, 276, - 627, 628, 279, 629, 281, 282, 283, 284, 285, 286, - 0, 0, 287, 632, 289, 633, 0, 291, 292, 293, - 294, 295, 296, 297, 298, 635, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 636, 637, 638, 323, - 324, 325, 639, 0, 327, 328, 641, 330, 0, 643, - 332, 644, 334, 335, 336, 0, 337, 338, 0, 0, - 339, 340, 341, 0, 0, 342, 343, 650, 651, 346, - 652, 653, 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 27, 28, 29, 0, 360, 361, 658, - 659, 364, 365, 660, 367, 368, 369, 0, 370, 371, - 372, 373, 374, 375, 0, 376, 377, 378, 663, 380, - 381, 382, 383, 0, 384, 385, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 0, 397, 398, - 666, 400, 401, 402, 667, 404, 405, 406, 407, 408, - 409, 410, 411, 412, 413, 414, 415, 416, 34, 669, - 417, 418, 419, 420, 421, 422, 670, 424, 425, 36, - 672, 427, 428, 673, 430, 0, 431, 432, 433, 434, - 435, 436, 437, 438, 439, 440, 441, 442, 675, 444, - 676, 38, 0, 446, 447, 39, 448, 680, 450, 451, - 452, 453, 454, 0, 455, 682, 683, 0, 0, 458, - 459, 686, 461, 687, 0, 463, 464, 689, 466, 467, - 468, 469, 470, 0, 0, 471, 472, 473, 41, 474, - 475, 476, 477, 0, 478, 479, 480, 481, 482, 965, - 695, 0, 485, 697, 487, 488, 489, 490, 491, 492, - 493, 0, 0, 494, 0, 45, 495, 496, 497, 498, - 499, 500, 702, 703, 704, 705, 706, 707, 708, 709, - 710, 711, 712, 512, 513, 514, 515, 0, 116, 46, - 549, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 47, 0, 0, 0, 117, 118, 119, - 120, 121, 122, 123, 124, 0, 125, 126, 127, 0, - 0, 0, 0, 0, 0, 0, 0, 128, 129, 130, - 0, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 0, 143, 144, 145, 146, 147, 148, - 0, 785, 149, 150, 151, 152, 153, 154, 155, 0, - 156, 157, 158, 159, 786, 0, 787, 0, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 0, 172, - 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 0, 194, 0, 195, 196, 197, 198, 199, - 200, 14, 15, 201, 202, 203, 204, 0, 0, 205, - 206, 207, 208, 209, 0, 210, 211, 212, 0, 213, - 214, 215, 0, 216, 217, 218, 219, 220, 221, 222, - 223, 224, 225, 788, 0, 227, 0, 228, 229, 230, - 231, 0, 232, 0, 233, 234, 23, 235, 236, 237, - 238, 239, 240, 0, 241, 0, 242, 243, 244, 245, - 0, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 0, 258, 259, 260, 261, 262, 263, - 264, 0, 265, 266, 267, 268, 269, 270, 271, 272, - 273, 274, 0, 275, 0, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 789, 0, 287, 288, - 289, 290, 0, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 0, - 327, 328, 329, 330, 0, 790, 332, 333, 334, 335, - 336, 0, 337, 338, 0, 791, 339, 340, 341, 0, - 0, 342, 343, 344, 345, 346, 347, 792, 349, 350, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 27, - 28, 29, 0, 360, 361, 793, 363, 364, 365, 366, - 367, 368, 369, 0, 370, 371, 372, 373, 374, 375, - 0, 376, 377, 378, 379, 380, 381, 382, 383, 0, - 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 794, 405, 406, 407, 408, 409, 410, 411, 412, - 413, 414, 415, 416, 34, 0, 417, 418, 419, 420, - 421, 422, 423, 424, 425, 36, 426, 427, 428, 429, - 430, 0, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 443, 444, 795, 38, 0, 446, - 447, 39, 448, 449, 450, 451, 452, 453, 454, 0, - 455, 456, 457, 0, 0, 458, 459, 796, 461, 797, - 0, 463, 464, 798, 466, 467, 468, 469, 470, 0, - 0, 471, 472, 473, 41, 474, 475, 476, 477, 0, - 478, 479, 480, 481, 482, 799, 484, 0, 485, 486, - 487, 488, 489, 490, 491, 492, 493, 0, 0, 494, - 0, 45, 495, 496, 497, 498, 499, 500, 501, 502, - 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, - 513, 514, 515, 0, 116, 46, 549, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 800, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 128, 129, 130, 0, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 785, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 786, 0, 787, 0, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 788, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 234, 0, 235, 236, 237, 238, 239, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 789, 0, 287, 288, 289, 290, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 0, 327, 328, 329, 330, - 0, 790, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 791, 339, 340, 341, 0, 0, 342, 343, 344, - 345, 346, 347, 792, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 793, 363, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 794, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 426, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, 444, 795, 0, 0, 446, 447, 0, 448, 449, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 796, 461, 797, 0, 463, 464, 798, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 799, 484, 0, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 116, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 800, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 128, 129, - 130, 0, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 785, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 786, 0, 787, 0, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 788, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 234, 0, 235, 236, - 237, 238, 239, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 288, 289, 290, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 0, 327, 328, 329, 330, 0, 790, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 345, 346, 347, 792, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 793, 363, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 403, 794, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 426, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 795, 0, 0, - 446, 447, 0, 448, 449, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 796, 461, - 797, 0, 463, 464, 798, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 486, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 116, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 47, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 128, 129, 130, 0, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 785, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 786, 0, 787, 0, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 788, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 234, 0, 235, 236, 237, 238, 239, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 288, 289, 290, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 0, 327, 328, 329, 330, - 0, 790, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 345, 346, 347, 792, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 793, 363, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 426, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, 444, 795, 0, 0, 446, 447, 0, 448, 449, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 796, 461, 797, 0, 463, 464, 798, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3308, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 14, 15, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 23, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 27, 28, 29, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 34, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 36, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 38, 0, - 446, 447, 39, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 41, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 799, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 45, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 46, 0, 0, 0, + 0, 804, 0, 0, 0, 118, 119, 120, 121, 122, + 123, 124, 125, 0, 126, 127, 128, 0, 0, 0, + 0, 0, 0, 0, 0, 129, 130, 131, 0, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 0, 144, 145, 146, 147, 148, 149, 0, 789, + 150, 151, 152, 153, 154, 155, 156, 0, 157, 158, + 159, 160, 790, 0, 791, 0, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 172, 0, 173, 174, 175, + 176, 177, 178, 0, 179, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 0, 195, 0, 196, 197, 198, 199, 200, 201, 0, + 0, 202, 203, 204, 205, 0, 0, 206, 207, 208, + 209, 210, 0, 211, 212, 213, 0, 214, 215, 216, + 0, 217, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 792, 0, 229, 0, 230, 231, 232, 233, + 0, 234, 0, 235, 236, 0, 237, 238, 239, 240, + 241, 242, 0, 243, 0, 244, 245, 246, 247, 0, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 0, 260, 261, 262, 263, 264, 265, 266, + 0, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 0, 277, 0, 278, 279, 280, 281, 282, 283, + 284, 285, 286, 287, 288, 793, 0, 289, 290, 291, + 292, 0, 293, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 328, 0, 329, + 330, 331, 332, 0, 794, 334, 335, 336, 337, 338, + 0, 339, 340, 0, 795, 341, 342, 343, 0, 0, + 344, 345, 346, 347, 348, 349, 796, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, 0, 0, + 0, 0, 362, 363, 797, 365, 366, 367, 368, 369, + 370, 371, 0, 372, 373, 374, 375, 376, 377, 0, + 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, + 0, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 0, 401, 402, 403, 404, 405, + 406, 407, 798, 409, 410, 411, 412, 413, 414, 415, + 416, 417, 418, 419, 420, 0, 0, 421, 422, 423, + 424, 425, 426, 427, 428, 429, 0, 430, 431, 432, + 433, 434, 0, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, 447, 448, 799, 0, 0, + 450, 451, 0, 452, 453, 454, 455, 456, 457, 458, + 0, 459, 460, 461, 0, 0, 462, 463, 800, 465, + 801, 0, 467, 468, 802, 470, 471, 472, 473, 474, + 0, 0, 475, 476, 477, 0, 478, 479, 480, 481, + 0, 482, 483, 484, 485, 486, 803, 488, 0, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 0, 0, + 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, + 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, + 516, 517, 518, 519, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 47, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 886, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 23, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 27, 28, 29, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 34, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 39, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 887, 457, 0, - 0, 888, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 41, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 799, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 45, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 47, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, + 804, 0, 0, 118, 119, 120, 121, 122, 123, 124, + 125, 0, 126, 127, 128, 0, 0, 0, 0, 0, + 0, 0, 0, 129, 130, 131, 0, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 0, + 144, 145, 146, 147, 148, 149, 0, 789, 150, 151, + 152, 153, 154, 155, 156, 0, 157, 158, 159, 160, + 790, 0, 791, 0, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 0, 173, 174, 175, 176, 177, + 178, 0, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 0, 195, + 0, 196, 197, 198, 199, 200, 201, 0, 0, 202, + 203, 204, 205, 0, 0, 206, 207, 208, 209, 210, + 0, 211, 212, 213, 0, 214, 215, 216, 0, 217, + 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 792, 0, 229, 0, 230, 231, 232, 233, 0, 234, + 0, 235, 236, 0, 237, 238, 239, 240, 241, 242, + 0, 243, 0, 244, 245, 246, 247, 0, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 0, 260, 261, 262, 263, 264, 265, 266, 0, 267, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 0, + 277, 0, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 0, 0, 289, 290, 291, 292, 0, + 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 328, 0, 329, 330, 331, + 332, 0, 794, 334, 335, 336, 337, 338, 0, 339, + 340, 0, 0, 341, 342, 343, 0, 0, 344, 345, + 346, 347, 348, 349, 796, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 0, 0, 0, 0, + 362, 363, 797, 365, 366, 367, 368, 369, 370, 371, + 0, 372, 373, 374, 375, 376, 377, 0, 378, 379, + 380, 381, 382, 383, 384, 385, 386, 387, 0, 388, + 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 0, 401, 402, 403, 404, 405, 406, 407, + 798, 409, 410, 411, 412, 413, 414, 415, 416, 417, + 418, 419, 420, 0, 0, 421, 422, 423, 424, 425, + 426, 427, 428, 429, 0, 430, 431, 432, 433, 434, + 0, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, 447, 448, 799, 0, 0, 450, 451, + 0, 452, 453, 454, 455, 456, 457, 458, 0, 459, + 460, 461, 0, 0, 462, 463, 800, 465, 801, 0, + 467, 468, 802, 470, 471, 472, 473, 474, 0, 0, + 475, 476, 477, 0, 478, 479, 480, 481, 0, 482, + 483, 484, 485, 486, 487, 488, 0, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 0, 0, 498, 0, + 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, + 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, + 518, 519, 117, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, + 0, 118, 119, 120, 121, 122, 123, 124, 125, 0, + 126, 127, 128, 0, 0, 0, 0, 0, 0, 0, + 0, 129, 130, 131, 0, 132, 133, 134, 135, 136, + 137, 138, 139, 140, 141, 142, 143, 0, 144, 145, + 146, 147, 148, 149, 0, 789, 150, 151, 152, 153, + 154, 155, 156, 0, 157, 158, 159, 160, 790, 0, + 791, 0, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 0, 173, 174, 175, 176, 177, 178, 0, + 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 0, 195, 0, 196, + 197, 198, 199, 200, 201, 0, 0, 202, 203, 204, + 205, 0, 0, 206, 207, 208, 209, 210, 0, 211, + 212, 213, 0, 214, 215, 216, 0, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 792, 0, + 229, 0, 230, 231, 232, 233, 0, 234, 0, 235, + 236, 0, 237, 238, 239, 240, 241, 242, 0, 243, + 0, 244, 245, 246, 247, 0, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 0, 260, + 261, 262, 263, 264, 265, 266, 0, 267, 268, 269, + 270, 271, 272, 273, 274, 275, 276, 0, 277, 0, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, + 288, 0, 0, 289, 290, 291, 292, 0, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 0, 329, 330, 331, 332, 0, + 794, 334, 335, 336, 337, 338, 0, 339, 340, 0, + 0, 341, 342, 343, 0, 0, 344, 345, 346, 347, + 348, 349, 796, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, 361, 0, 0, 0, 0, 362, 363, + 797, 365, 366, 367, 368, 369, 370, 371, 0, 372, + 373, 374, 375, 376, 377, 0, 378, 379, 380, 381, + 382, 383, 384, 385, 386, 387, 0, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 0, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 0, 0, 421, 422, 423, 424, 425, 426, 427, + 428, 429, 0, 430, 431, 432, 433, 434, 0, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, 447, 448, 799, 0, 0, 450, 451, 0, 452, + 453, 454, 455, 456, 457, 458, 0, 459, 460, 461, + 0, 0, 462, 463, 800, 465, 801, 0, 467, 468, + 802, 470, 471, 472, 473, 474, 0, 0, 475, 476, + 477, 0, 478, 479, 480, 481, 0, 482, 483, 484, + 485, 486, 487, 488, 0, 489, 490, 491, 492, 493, + 494, 495, 496, 497, 0, 0, 498, 0, 0, 499, + 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, + 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, + 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3326, 0, 0, 118, + 119, 120, 121, 122, 123, 124, 125, 0, 126, 127, + 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 130, 131, 0, 132, 133, 134, 0, 136, 137, 138, + 139, 140, 0, 142, 143, 0, 144, 145, 146, 147, + 148, 149, 0, 0, 150, 151, 152, 153, 154, 155, + 156, 0, 157, 158, 159, 160, 161, 0, 0, 0, + 163, 164, 165, 166, 167, 168, 0, 170, 171, 172, + 0, 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 23, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, + 191, 192, 193, 194, 0, 195, 0, 196, 197, 198, + 199, 200, 201, 14, 15, 202, 203, 204, 205, 0, + 0, 206, 207, 208, 209, 210, 0, 211, 212, 213, + 0, 214, 215, 216, 0, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 0, 229, 0, + 230, 231, 232, 233, 0, 234, 0, 235, 0, 23, + 0, 238, 239, 528, 0, 242, 0, 243, 0, 244, + 245, 246, 247, 0, 248, 249, 250, 251, 252, 253, + 254, 0, 256, 257, 258, 259, 0, 260, 261, 262, + 263, 264, 265, 266, 0, 267, 0, 269, 270, 271, + 272, 273, 274, 275, 276, 0, 277, 0, 278, 0, + 0, 281, 0, 283, 284, 285, 286, 287, 288, 0, + 0, 289, 0, 291, 0, 0, 293, 294, 295, 296, + 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, + 317, 318, 319, 320, 321, 322, 0, 324, 325, 326, + 327, 328, 0, 329, 330, 0, 332, 0, 333, 334, + 335, 336, 337, 338, 0, 339, 340, 0, 0, 341, + 342, 343, 0, 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 27, 28, 29, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 34, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 39, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 41, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 799, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 45, 495, 496, 497, 498, 499, 500, 501, + 360, 361, 26, 27, 28, 0, 362, 363, 364, 0, + 366, 367, 368, 369, 370, 371, 0, 372, 373, 374, + 375, 376, 377, 0, 378, 379, 380, 381, 382, 383, + 384, 385, 386, 387, 0, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 0, 401, + 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 416, 417, 418, 419, 420, 33, + 0, 421, 422, 423, 424, 425, 426, 427, 428, 429, + 35, 0, 431, 432, 433, 434, 0, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, 530, + 448, 449, 37, 0, 450, 451, 38, 452, 0, 454, + 455, 456, 457, 458, 0, 459, 460, 461, 0, 0, + 462, 463, 464, 465, 466, 0, 467, 468, 469, 470, + 471, 472, 473, 474, 0, 0, 475, 476, 477, 40, + 478, 479, 480, 481, 0, 482, 483, 484, 485, 486, + 803, 488, 0, 489, 0, 491, 492, 493, 494, 495, + 496, 497, 0, 0, 498, 0, 44, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 0, 523, 46, 549, 0, 0, + 512, 513, 514, 515, 516, 517, 518, 519, 527, 0, + 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 0, 0, 118, 119, 120, + 121, 122, 123, 124, 125, 890, 126, 127, 128, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 130, 131, + 0, 132, 133, 134, 0, 136, 137, 138, 139, 140, + 0, 142, 143, 0, 144, 145, 146, 147, 148, 149, + 0, 0, 150, 151, 152, 153, 154, 155, 156, 0, + 157, 158, 159, 160, 161, 0, 0, 0, 163, 164, + 165, 166, 167, 168, 0, 170, 171, 172, 0, 173, + 174, 175, 176, 177, 178, 0, 0, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 0, 195, 0, 196, 197, 198, 199, 200, + 201, 0, 0, 202, 203, 204, 205, 0, 0, 206, + 207, 208, 209, 210, 0, 211, 212, 213, 0, 214, + 215, 216, 0, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 0, 229, 0, 230, 231, + 232, 233, 0, 234, 0, 235, 0, 23, 0, 238, + 239, 528, 0, 242, 0, 243, 0, 244, 245, 246, + 247, 0, 248, 249, 250, 251, 252, 253, 254, 0, + 256, 257, 258, 259, 0, 260, 261, 262, 263, 264, + 265, 266, 0, 267, 0, 269, 270, 271, 272, 273, + 274, 275, 276, 0, 277, 0, 278, 0, 0, 281, + 0, 283, 284, 285, 286, 287, 288, 0, 0, 289, + 0, 291, 0, 0, 293, 294, 295, 296, 297, 298, + 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 0, 324, 325, 326, 327, 328, + 0, 329, 330, 0, 332, 0, 333, 334, 335, 336, + 337, 338, 0, 339, 340, 0, 0, 341, 342, 343, + 0, 0, 344, 345, 346, 0, 348, 0, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 26, 27, 28, 0, 362, 363, 364, 0, 366, 367, + 368, 369, 370, 371, 0, 372, 373, 374, 375, 376, + 377, 0, 378, 379, 380, 381, 382, 383, 384, 385, + 386, 387, 0, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 0, 401, 402, 0, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, 415, 416, 417, 418, 419, 420, 33, 0, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 0, 0, + 431, 432, 433, 434, 0, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, 530, 448, 449, + 0, 0, 450, 451, 38, 452, 0, 454, 455, 456, + 457, 458, 0, 459, 891, 461, 0, 0, 892, 463, + 464, 465, 466, 0, 467, 468, 469, 470, 471, 472, + 473, 474, 0, 0, 475, 476, 477, 40, 478, 479, + 480, 481, 0, 482, 483, 484, 485, 486, 803, 488, + 0, 489, 0, 491, 492, 493, 494, 495, 496, 497, + 0, 0, 498, 0, 44, 499, 500, 501, 502, 503, + 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, + 514, 515, 516, 517, 518, 519, 527, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 47, 0, 0, 0, 117, 118, 119, 120, 121, 122, - 123, 124, 0, 125, 126, 127, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 129, 130, 0, 131, 132, - 133, 0, 135, 136, 137, 138, 139, 0, 141, 142, - 0, 143, 144, 145, 146, 147, 148, 0, 0, 149, - 150, 151, 152, 153, 154, 155, 0, 156, 157, 158, - 159, 160, 0, 0, 0, 162, 163, 164, 165, 166, - 167, 0, 169, 170, 171, 0, 172, 173, 174, 175, - 176, 177, 0, 0, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 0, - 194, 0, 195, 196, 197, 198, 199, 200, 0, 0, - 201, 202, 203, 204, 0, 0, 205, 206, 207, 208, - 209, 0, 210, 211, 212, 0, 213, 214, 215, 0, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 0, 227, 0, 228, 229, 230, 231, 0, 232, - 0, 233, 0, 0, 0, 236, 237, 524, 0, 240, - 0, 241, 0, 242, 243, 244, 245, 0, 246, 247, - 248, 249, 250, 251, 252, 0, 254, 255, 256, 257, - 0, 258, 259, 260, 261, 262, 263, 264, 0, 265, - 0, 267, 268, 269, 270, 271, 272, 273, 274, 0, - 275, 0, 276, 0, 0, 279, 0, 281, 282, 283, - 284, 285, 286, 0, 0, 287, 0, 289, 0, 0, - 291, 292, 293, 294, 295, 296, 297, 298, 525, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, + 0, 0, 46, 0, 0, 118, 119, 120, 121, 122, + 123, 124, 125, 0, 126, 127, 128, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 130, 131, 0, 132, + 133, 134, 0, 136, 137, 138, 139, 140, 0, 142, + 143, 0, 144, 145, 146, 147, 148, 149, 0, 0, + 150, 151, 152, 153, 154, 155, 156, 0, 157, 158, + 159, 160, 161, 0, 0, 0, 163, 164, 165, 166, + 167, 168, 0, 170, 171, 172, 0, 173, 174, 175, + 176, 177, 178, 0, 0, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 0, 195, 0, 196, 197, 198, 199, 200, 201, 0, + 0, 202, 203, 204, 205, 0, 0, 206, 207, 208, + 209, 210, 0, 211, 212, 213, 0, 214, 215, 216, + 0, 217, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 0, 229, 0, 230, 231, 232, 233, + 0, 234, 0, 235, 0, 23, 0, 238, 239, 528, + 0, 242, 0, 243, 0, 244, 245, 246, 247, 0, + 248, 249, 250, 251, 252, 253, 254, 0, 256, 257, + 258, 259, 0, 260, 261, 262, 263, 264, 265, 266, + 0, 267, 0, 269, 270, 271, 272, 273, 274, 275, + 276, 0, 277, 0, 278, 0, 0, 281, 0, 283, + 284, 285, 286, 287, 288, 0, 0, 289, 0, 291, + 0, 0, 293, 294, 295, 296, 297, 298, 299, 300, + 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 0, 322, 323, 324, 325, 326, 0, 327, 328, 0, - 330, 0, 331, 332, 333, 334, 335, 336, 0, 337, - 338, 0, 0, 339, 340, 341, 0, 0, 342, 343, - 344, 0, 346, 0, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 0, 0, 0, 0, - 360, 361, 362, 0, 364, 365, 366, 367, 368, 369, - 0, 370, 371, 372, 373, 374, 375, 0, 376, 377, - 378, 379, 380, 381, 382, 383, 0, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 0, 397, 398, 0, 400, 401, 402, 403, 404, 405, + 321, 322, 0, 324, 325, 326, 327, 328, 0, 329, + 330, 0, 332, 0, 333, 334, 335, 336, 337, 338, + 0, 339, 340, 0, 0, 341, 342, 343, 0, 0, + 344, 345, 346, 0, 348, 0, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, 26, 27, + 28, 0, 362, 363, 364, 0, 366, 367, 368, 369, + 370, 371, 0, 372, 373, 374, 375, 376, 377, 0, + 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, + 0, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 0, 0, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 0, 0, 427, 428, 429, 430, 0, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 526, 444, 445, 0, 0, 446, 447, 0, 448, - 0, 450, 451, 452, 453, 454, 0, 455, 456, 457, - 0, 0, 458, 459, 460, 461, 462, 0, 463, 464, - 465, 466, 467, 468, 469, 470, 0, 0, 471, 472, - 473, 0, 474, 475, 476, 477, 0, 478, 479, 480, - 481, 482, 483, 484, 0, 485, 0, 487, 488, 489, - 490, 491, 492, 493, 0, 0, 494, 0, 0, 495, - 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, + 416, 417, 418, 419, 420, 33, 0, 421, 422, 423, + 424, 425, 426, 427, 428, 429, 0, 0, 431, 432, + 433, 434, 0, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, 530, 448, 449, 0, 0, + 450, 451, 38, 452, 0, 454, 455, 456, 457, 458, + 0, 459, 460, 461, 0, 0, 462, 463, 464, 465, + 466, 0, 467, 468, 469, 470, 471, 472, 473, 474, + 0, 0, 475, 476, 477, 40, 478, 479, 480, 481, + 0, 482, 483, 484, 485, 486, 803, 488, 0, 489, + 0, 491, 492, 493, 494, 495, 496, 497, 0, 0, + 498, 0, 44, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, - 523, 0, 549, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 985, 0, 0, 117, - 118, 119, 120, 121, 122, 123, 124, 0, 125, 126, - 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 129, 130, 0, 131, 132, 133, 0, 135, 136, 137, - 138, 139, 0, 141, 142, 0, 143, 144, 145, 146, - 147, 148, 0, 0, 149, 150, 151, 152, 153, 154, - 155, 0, 156, 157, 158, 159, 160, 0, 0, 0, - 162, 163, 164, 165, 166, 167, 0, 169, 170, 171, - 0, 172, 173, 174, 175, 176, 177, 0, 0, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 0, 194, 0, 195, 196, 197, - 198, 199, 200, 0, 0, 201, 202, 203, 204, 0, - 0, 205, 206, 207, 208, 209, 0, 210, 211, 212, - 0, 213, 214, 215, 0, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 0, 227, 0, 228, - 229, 230, 231, 0, 232, 0, 233, 0, 0, 0, - 236, 237, 524, 0, 240, 0, 241, 0, 242, 243, - 244, 245, 0, 246, 247, 248, 249, 250, 251, 252, - 0, 254, 255, 256, 257, 0, 258, 259, 260, 261, - 262, 263, 264, 0, 265, 0, 267, 268, 269, 270, - 271, 272, 273, 274, 0, 275, 0, 276, 0, 0, - 279, 0, 281, 282, 283, 284, 285, 286, 0, 0, - 287, 0, 289, 0, 0, 291, 292, 293, 294, 295, - 296, 297, 298, 525, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 0, 322, 323, 324, 325, - 326, 0, 327, 328, 0, 330, 0, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 0, 0, 339, 340, - 341, 0, 0, 342, 343, 344, 0, 346, 0, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 0, 0, 0, 0, 360, 361, 362, 0, 364, - 365, 366, 367, 368, 369, 0, 370, 371, 372, 373, - 374, 375, 0, 376, 377, 378, 379, 380, 381, 382, - 383, 0, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 0, 397, 398, 0, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, 412, 413, 414, 415, 416, 0, 0, 417, 418, - 419, 420, 421, 422, 423, 424, 425, 0, 0, 427, - 428, 429, 430, 0, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 526, 444, 445, 0, - 0, 446, 447, 0, 448, 0, 450, 451, 452, 453, - 454, 0, 455, 456, 457, 0, 0, 458, 459, 460, - 461, 462, 0, 463, 464, 465, 466, 467, 468, 469, - 470, 0, 0, 471, 472, 473, 0, 474, 475, 476, - 477, 0, 478, 479, 480, 481, 482, 483, 484, 0, - 485, 0, 487, 488, 489, 490, 491, 492, 493, 0, - 0, 494, 0, 0, 495, 496, 497, 498, 499, 500, - 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, - 511, 512, 513, 514, 515, 523, 0, 549, 0, 0, + 516, 517, 518, 519, 0, 527, 45, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1464, 0, 0, 117, 118, 119, 120, 121, 122, - 123, 124, 0, 125, 126, 127, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 129, 130, 0, 131, 132, - 133, 0, 135, 136, 137, 138, 139, 0, 141, 142, - 0, 143, 144, 145, 146, 147, 148, 0, 0, 149, - 150, 151, 152, 153, 154, 155, 0, 156, 157, 158, - 159, 160, 0, 0, 0, 162, 163, 164, 165, 166, - 167, 0, 169, 170, 171, 0, 172, 173, 174, 175, - 176, 177, 0, 0, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 0, - 194, 0, 195, 196, 197, 198, 199, 200, 0, 0, - 201, 202, 203, 204, 0, 0, 205, 206, 207, 208, - 209, 0, 210, 211, 212, 0, 213, 214, 215, 0, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 0, 227, 0, 228, 229, 230, 231, 0, 232, - 0, 233, 0, 0, 0, 236, 237, 524, 0, 240, - 0, 241, 0, 242, 243, 244, 245, 0, 246, 247, - 248, 249, 250, 251, 252, 0, 254, 255, 256, 257, - 0, 258, 259, 260, 261, 262, 263, 264, 0, 265, - 0, 267, 268, 269, 270, 271, 272, 273, 274, 0, - 275, 0, 276, 0, 0, 279, 0, 281, 282, 283, - 284, 285, 286, 0, 0, 287, 0, 289, 0, 0, - 291, 292, 293, 294, 295, 296, 297, 298, 525, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 0, 322, 323, 324, 325, 326, 0, 327, 328, 0, - 330, 0, 331, 332, 333, 334, 335, 336, 0, 337, - 338, 0, 0, 339, 340, 341, 0, 0, 342, 343, - 344, 0, 346, 0, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 0, 0, 0, 0, - 360, 361, 362, 0, 364, 365, 366, 367, 368, 369, - 0, 370, 371, 372, 373, 374, 375, 0, 376, 377, - 378, 379, 380, 381, 382, 383, 0, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 0, 397, 398, 0, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 0, 0, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 0, 0, 427, 428, 429, 430, 0, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 526, 444, 445, 0, 0, 446, 447, 0, 448, - 0, 450, 451, 452, 453, 454, 0, 455, 456, 457, - 0, 0, 458, 459, 460, 461, 462, 0, 463, 464, - 465, 466, 467, 468, 469, 470, 0, 0, 471, 472, - 473, 0, 474, 475, 476, 477, 0, 478, 479, 480, - 481, 482, 483, 484, 0, 485, 0, 487, 488, 489, - 490, 491, 492, 493, 0, 0, 494, 0, 0, 495, - 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, - 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, - 523, 0, 549, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2201, 0, 0, 117, - 118, 119, 120, 121, 122, 123, 124, 0, 125, 126, - 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 129, 130, 0, 131, 132, 133, 0, 135, 136, 137, - 138, 139, 0, 141, 142, 0, 143, 144, 145, 146, - 147, 148, 0, 0, 149, 150, 151, 152, 153, 154, - 155, 0, 156, 157, 158, 159, 160, 0, 0, 0, - 162, 163, 164, 165, 166, 167, 0, 169, 170, 171, - 0, 172, 173, 174, 175, 176, 177, 0, 0, 179, + 46, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 130, 131, 0, 132, 133, + 134, 0, 136, 137, 138, 139, 140, 0, 142, 143, + 0, 144, 145, 146, 147, 148, 149, 0, 0, 150, + 151, 152, 153, 154, 155, 156, 0, 157, 158, 159, + 160, 161, 0, 0, 0, 163, 164, 165, 166, 167, + 168, 0, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 208, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 0, 229, 0, 230, 231, 232, 233, 0, + 234, 0, 235, 0, 0, 0, 238, 239, 528, 0, + 242, 0, 243, 0, 244, 245, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 0, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 0, 269, 270, 271, 272, 273, 274, 275, 276, + 0, 277, 0, 278, 0, 0, 281, 0, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 0, 291, 0, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 529, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 0, 324, 325, 326, 327, 328, 0, 329, 330, + 0, 332, 0, 333, 334, 335, 336, 337, 338, 0, + 339, 340, 0, 0, 341, 342, 343, 0, 0, 344, + 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 364, 0, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 383, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 0, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 0, 431, 432, 433, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 530, 448, 449, 0, 0, 450, + 451, 0, 452, 0, 454, 455, 456, 457, 458, 0, + 459, 460, 461, 0, 0, 462, 463, 464, 465, 466, + 0, 467, 468, 469, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 488, 0, 489, 0, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 990, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 131, 0, 132, 133, 134, 0, + 136, 137, 138, 139, 140, 0, 142, 143, 0, 144, + 145, 146, 147, 148, 149, 0, 0, 150, 151, 152, + 153, 154, 155, 156, 0, 157, 158, 159, 160, 161, + 0, 0, 0, 163, 164, 165, 166, 167, 168, 0, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 208, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 0, 229, 0, 230, 231, 232, 233, 0, 234, 0, + 235, 0, 0, 0, 238, 239, 528, 0, 242, 0, + 243, 0, 244, 245, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 0, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 0, + 269, 270, 271, 272, 273, 274, 275, 276, 0, 277, + 0, 278, 0, 0, 281, 0, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 0, 291, 0, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 0, + 324, 325, 326, 327, 328, 0, 329, 330, 0, 332, + 0, 333, 334, 335, 336, 337, 338, 0, 339, 340, + 0, 0, 341, 342, 343, 0, 0, 344, 345, 346, + 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 364, 0, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 0, 431, 432, 433, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 530, 448, 449, 0, 0, 450, 451, 0, + 452, 0, 454, 455, 456, 457, 458, 0, 459, 460, + 461, 0, 0, 462, 463, 464, 465, 466, 0, 467, + 468, 469, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 488, 0, 489, 0, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1473, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 130, 131, 0, 132, 133, 134, 0, 136, 137, + 138, 139, 140, 0, 142, 143, 0, 144, 145, 146, + 147, 148, 149, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 0, 157, 158, 159, 160, 161, 0, 0, + 0, 163, 164, 165, 166, 167, 168, 0, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 0, 194, 0, 195, 196, 197, - 198, 199, 200, 0, 0, 201, 202, 203, 204, 0, - 0, 205, 206, 207, 208, 209, 0, 210, 211, 212, - 0, 213, 214, 215, 0, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 0, 227, 0, 228, - 229, 230, 231, 0, 232, 0, 233, 0, 0, 0, - 236, 237, 524, 0, 240, 0, 241, 0, 242, 243, - 244, 245, 0, 246, 247, 248, 249, 250, 251, 252, - 0, 254, 255, 256, 257, 0, 258, 259, 260, 261, - 262, 263, 264, 0, 265, 0, 267, 268, 269, 270, - 271, 272, 273, 274, 0, 275, 0, 276, 0, 0, - 279, 0, 281, 282, 283, 284, 285, 286, 0, 0, - 287, 0, 289, 0, 0, 291, 292, 293, 294, 295, - 296, 297, 298, 525, 300, 301, 302, 303, 304, 305, + 190, 191, 192, 193, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 0, 229, + 0, 230, 231, 232, 233, 0, 234, 0, 235, 0, + 0, 0, 238, 239, 528, 0, 242, 0, 243, 0, + 244, 245, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 0, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 0, 269, 270, + 271, 272, 273, 274, 275, 276, 0, 277, 0, 278, + 0, 0, 281, 0, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 0, 291, 0, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 0, 322, 323, 324, 325, - 326, 0, 327, 328, 0, 330, 0, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 0, 0, 339, 340, - 341, 0, 0, 342, 343, 344, 0, 346, 0, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 0, 0, 0, 0, 360, 361, 362, 0, 364, - 365, 366, 367, 368, 369, 0, 370, 371, 372, 373, - 374, 375, 0, 376, 377, 378, 379, 380, 381, 382, - 383, 0, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 0, 397, 398, 0, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, 412, 413, 414, 415, 416, 0, 0, 417, 418, - 419, 420, 421, 422, 423, 424, 425, 0, 0, 427, - 428, 429, 430, 0, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 526, 444, 445, 0, - 0, 446, 447, 0, 448, 0, 450, 451, 452, 453, - 454, 0, 455, 456, 457, 0, 0, 458, 459, 460, - 461, 462, 0, 463, 464, 465, 466, 467, 468, 469, - 470, 0, 0, 471, 472, 473, 0, 474, 475, 476, - 477, 0, 478, 479, 480, 481, 482, 483, 484, 0, - 485, 0, 487, 488, 489, 490, 491, 492, 493, 0, - 0, 494, 0, 0, 495, 496, 497, 498, 499, 500, + 316, 317, 318, 319, 320, 321, 322, 0, 324, 325, + 326, 327, 328, 0, 329, 330, 0, 332, 0, 333, + 334, 335, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 346, 0, 348, + 0, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 364, + 0, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 383, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 0, 431, 432, 433, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 530, 448, 449, 0, 0, 450, 451, 0, 452, 0, + 454, 455, 456, 457, 458, 0, 459, 460, 461, 0, + 0, 462, 463, 464, 465, 466, 0, 467, 468, 469, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 488, 0, 489, 0, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, - 511, 512, 513, 514, 515, 523, 0, 549, 0, 0, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 527, + 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2216, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, + 131, 0, 132, 133, 134, 0, 136, 137, 138, 139, + 140, 0, 142, 143, 0, 144, 145, 146, 147, 148, + 149, 0, 0, 150, 151, 152, 153, 154, 155, 156, + 0, 157, 158, 159, 160, 161, 0, 0, 0, 163, + 164, 165, 166, 167, 168, 0, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 0, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 0, 229, 0, 230, + 231, 232, 233, 0, 234, 0, 235, 0, 0, 0, + 238, 239, 528, 0, 242, 0, 243, 0, 244, 245, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 0, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 0, 269, 270, 271, 272, + 273, 274, 275, 276, 0, 277, 0, 278, 0, 0, + 281, 0, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 0, 291, 0, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 0, 324, 325, 326, 327, + 328, 0, 329, 330, 0, 332, 0, 333, 334, 335, + 336, 337, 338, 0, 339, 340, 0, 0, 341, 342, + 343, 0, 0, 344, 345, 346, 0, 348, 0, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 364, 0, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 0, 431, 432, 433, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 530, 448, + 449, 0, 0, 450, 451, 0, 452, 0, 454, 455, + 456, 457, 458, 0, 459, 460, 461, 0, 0, 462, + 463, 464, 465, 466, 0, 467, 468, 469, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 488, 0, 489, 0, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2439, 0, 0, 117, 118, 119, 120, 121, 122, - 123, 124, 0, 125, 126, 127, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 129, 130, 0, 131, 132, - 133, 0, 135, 136, 137, 138, 139, 0, 141, 142, - 0, 143, 144, 145, 146, 147, 148, 0, 0, 149, - 150, 151, 152, 153, 154, 155, 0, 156, 157, 158, - 159, 160, 0, 0, 0, 162, 163, 164, 165, 166, - 167, 0, 169, 170, 171, 0, 172, 173, 174, 175, - 176, 177, 0, 0, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 0, - 194, 0, 195, 196, 197, 198, 199, 200, 0, 0, - 201, 202, 203, 204, 0, 0, 205, 206, 207, 208, - 209, 0, 210, 211, 212, 0, 213, 214, 215, 0, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 0, 227, 0, 228, 229, 230, 231, 0, 232, - 0, 233, 0, 0, 0, 236, 237, 524, 0, 240, - 0, 241, 0, 242, 243, 244, 245, 0, 246, 247, - 248, 249, 250, 251, 252, 0, 254, 255, 256, 257, - 0, 258, 259, 260, 261, 262, 263, 264, 0, 265, - 0, 267, 268, 269, 270, 271, 272, 273, 274, 0, - 275, 0, 276, 0, 0, 279, 0, 281, 282, 283, - 284, 285, 286, 0, 0, 287, 0, 289, 0, 0, - 291, 292, 293, 294, 295, 296, 297, 298, 525, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 0, 322, 323, 324, 325, 326, 0, 327, 328, 0, - 330, 0, 331, 332, 333, 334, 335, 336, 0, 337, - 338, 0, 0, 339, 340, 341, 0, 0, 342, 343, - 344, 0, 346, 0, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 0, 0, 0, 0, - 360, 361, 362, 0, 364, 365, 366, 367, 368, 369, - 0, 370, 371, 372, 373, 374, 375, 0, 376, 377, - 378, 379, 380, 381, 382, 383, 0, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 0, 397, 398, 0, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 0, 0, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 0, 0, 427, 428, 429, 430, 0, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 526, 444, 445, 0, 0, 446, 447, 0, 448, - 0, 450, 451, 452, 453, 454, 0, 455, 456, 457, - 0, 0, 458, 459, 460, 461, 462, 0, 463, 464, - 465, 466, 467, 468, 469, 470, 0, 0, 471, 472, - 473, 0, 474, 475, 476, 477, 0, 478, 479, 480, - 481, 482, 483, 484, 0, 485, 0, 487, 488, 489, - 490, 491, 492, 493, 0, 0, 494, 0, 0, 495, - 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, - 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, - 523, 0, 549, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2570, 0, 0, 117, - 118, 119, 120, 121, 122, 123, 124, 0, 125, 126, - 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 129, 130, 0, 131, 132, 133, 0, 135, 136, 137, - 138, 139, 0, 141, 142, 0, 143, 144, 145, 146, - 147, 148, 0, 0, 149, 150, 151, 152, 153, 154, - 155, 0, 156, 157, 158, 159, 160, 0, 0, 0, - 162, 163, 164, 165, 166, 167, 0, 169, 170, 171, - 0, 172, 173, 174, 175, 176, 177, 0, 0, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 0, 194, 0, 195, 196, 197, - 198, 199, 200, 0, 0, 201, 202, 203, 204, 0, - 0, 205, 206, 207, 208, 209, 0, 210, 211, 212, - 0, 213, 214, 215, 0, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 0, 227, 0, 228, - 229, 230, 231, 0, 232, 0, 233, 0, 0, 0, - 236, 237, 524, 0, 240, 0, 241, 0, 242, 243, - 244, 245, 0, 246, 247, 248, 249, 250, 251, 252, - 0, 254, 255, 256, 257, 0, 258, 259, 260, 261, - 262, 263, 264, 0, 265, 0, 267, 268, 269, 270, - 271, 272, 273, 274, 0, 275, 0, 276, 0, 0, - 279, 0, 281, 282, 283, 284, 285, 286, 0, 0, - 287, 0, 289, 0, 0, 291, 292, 293, 294, 295, - 296, 297, 298, 525, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 0, 322, 323, 324, 325, - 326, 0, 327, 328, 0, 330, 0, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 0, 0, 339, 340, - 341, 0, 0, 342, 343, 344, 0, 346, 0, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 0, 0, 0, 0, 360, 361, 362, 0, 364, - 365, 366, 367, 368, 369, 0, 370, 371, 372, 373, - 374, 375, 0, 376, 377, 378, 379, 380, 381, 382, - 383, 0, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 0, 397, 398, 0, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, 412, 413, 414, 415, 416, 0, 0, 417, 418, - 419, 420, 421, 422, 423, 424, 425, 0, 0, 427, - 428, 429, 430, 0, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 526, 444, 445, 0, - 0, 446, 447, 0, 448, 0, 450, 451, 452, 453, - 454, 0, 455, 456, 457, 0, 0, 458, 459, 460, - 461, 462, 0, 463, 464, 465, 466, 467, 468, 469, - 470, 0, 0, 471, 472, 473, 0, 474, 475, 476, - 477, 0, 478, 479, 480, 481, 482, 483, 484, 0, - 485, 0, 487, 488, 489, 490, 491, 492, 493, 0, - 0, 494, 0, 0, 495, 496, 497, 498, 499, 500, - 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, - 511, 512, 513, 514, 515, 523, 0, 0, 0, 0, + 0, 0, 0, 2452, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 130, 131, 0, + 132, 133, 134, 0, 136, 137, 138, 139, 140, 0, + 142, 143, 0, 144, 145, 146, 147, 148, 149, 0, + 0, 150, 151, 152, 153, 154, 155, 156, 0, 157, + 158, 159, 160, 161, 0, 0, 0, 163, 164, 165, + 166, 167, 168, 0, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 0, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 208, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 0, 229, 0, 230, 231, 232, + 233, 0, 234, 0, 235, 0, 0, 0, 238, 239, + 528, 0, 242, 0, 243, 0, 244, 245, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 0, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 0, 269, 270, 271, 272, 273, 274, + 275, 276, 0, 277, 0, 278, 0, 0, 281, 0, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 0, + 291, 0, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 0, 324, 325, 326, 327, 328, 0, + 329, 330, 0, 332, 0, 333, 334, 335, 336, 337, + 338, 0, 339, 340, 0, 0, 341, 342, 343, 0, + 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 364, 0, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 0, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 0, 431, + 432, 433, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 530, 448, 449, 0, + 0, 450, 451, 0, 452, 0, 454, 455, 456, 457, + 458, 0, 459, 460, 461, 0, 0, 462, 463, 464, + 465, 466, 0, 467, 468, 469, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 488, 0, + 489, 0, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3215, 0, 0, 117, 118, 119, 120, 121, 122, - 123, 124, 0, 125, 126, 127, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 129, 130, 0, 131, 132, - 133, 0, 135, 136, 137, 138, 139, 0, 141, 142, - 0, 143, 144, 145, 146, 147, 148, 0, 0, 149, - 150, 151, 152, 153, 154, 155, 0, 156, 157, 158, - 159, 160, 0, 0, 0, 162, 163, 164, 165, 166, - 167, 0, 169, 170, 171, 0, 172, 173, 174, 175, - 176, 177, 0, 0, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 0, - 194, 0, 195, 196, 197, 198, 199, 200, 0, 0, - 201, 202, 203, 204, 0, 0, 205, 206, 207, 208, - 209, 0, 210, 211, 212, 0, 213, 214, 215, 0, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 0, 227, 0, 228, 229, 230, 231, 0, 232, - 0, 233, 0, 0, 0, 236, 237, 524, 0, 240, - 0, 241, 0, 242, 243, 244, 245, 0, 246, 247, - 248, 249, 250, 251, 252, 0, 254, 255, 256, 257, - 0, 258, 259, 260, 261, 262, 263, 264, 0, 265, - 0, 267, 268, 269, 270, 271, 272, 273, 274, 0, - 275, 0, 276, 0, 0, 279, 0, 281, 282, 283, - 284, 285, 286, 0, 0, 287, 0, 289, 0, 0, - 291, 292, 293, 294, 295, 296, 297, 298, 525, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 0, 322, 323, 324, 325, 326, 0, 327, 328, 0, - 330, 0, 331, 332, 333, 334, 335, 336, 0, 337, - 338, 0, 0, 339, 340, 341, 0, 0, 342, 343, - 344, 0, 346, 0, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 0, 0, 0, 0, - 360, 361, 362, 0, 364, 365, 366, 367, 368, 369, - 0, 370, 371, 372, 373, 374, 375, 0, 376, 377, - 378, 379, 380, 381, 382, 383, 0, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 0, 397, 398, 0, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 0, 0, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 0, 0, 427, 428, 429, 430, 0, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 526, 444, 445, 0, 0, 446, 447, 0, 448, - 0, 450, 451, 452, 453, 454, 0, 455, 456, 457, - 0, 0, 458, 459, 460, 461, 462, 0, 463, 464, - 465, 466, 467, 468, 469, 470, 0, 0, 471, 472, - 473, 0, 474, 475, 476, 477, 0, 478, 479, 480, - 481, 482, 483, 484, 0, 485, 0, 487, 488, 489, - 490, 491, 492, 493, 0, 0, 494, 0, 0, 495, - 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, - 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, - 523, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2058, 0, 0, 117, - 118, 119, 120, 121, 122, 123, 124, 0, 125, 126, - 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 129, 130, 0, 131, 132, 133, 0, 135, 136, 137, - 138, 139, 0, 141, 142, 0, 143, 144, 145, 146, - 147, 148, 0, 0, 149, 150, 151, 152, 153, 154, - 155, 0, 156, 157, 158, 159, 160, 0, 0, 0, - 162, 163, 164, 165, 166, 167, 0, 169, 170, 171, - 0, 172, 173, 174, 175, 176, 177, 0, 0, 179, + 0, 2587, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 130, 131, 0, 132, 133, + 134, 0, 136, 137, 138, 139, 140, 0, 142, 143, + 0, 144, 145, 146, 147, 148, 149, 0, 0, 150, + 151, 152, 153, 154, 155, 156, 0, 157, 158, 159, + 160, 161, 0, 0, 0, 163, 164, 165, 166, 167, + 168, 0, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 208, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 0, 229, 0, 230, 231, 232, 233, 0, + 234, 0, 235, 0, 0, 0, 238, 239, 528, 0, + 242, 0, 243, 0, 244, 245, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 0, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 0, 269, 270, 271, 272, 273, 274, 275, 276, + 0, 277, 0, 278, 0, 0, 281, 0, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 0, 291, 0, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 529, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 0, 324, 325, 326, 327, 328, 0, 329, 330, + 0, 332, 0, 333, 334, 335, 336, 337, 338, 0, + 339, 340, 0, 0, 341, 342, 343, 0, 0, 344, + 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 364, 0, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 383, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 0, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 0, 431, 432, 433, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 530, 448, 449, 0, 0, 450, + 451, 0, 452, 0, 454, 455, 456, 457, 458, 0, + 459, 460, 461, 0, 0, 462, 463, 464, 465, 466, + 0, 467, 468, 469, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 488, 0, 489, 0, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3233, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 131, 0, 132, 133, 134, 0, + 136, 137, 138, 139, 140, 0, 142, 143, 0, 144, + 145, 146, 147, 148, 149, 0, 0, 150, 151, 152, + 153, 154, 155, 156, 0, 157, 158, 159, 160, 161, + 0, 0, 0, 163, 164, 165, 166, 167, 168, 0, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 208, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 0, 229, 0, 230, 231, 232, 233, 0, 234, 0, + 235, 0, 0, 0, 238, 239, 528, 0, 242, 0, + 243, 0, 244, 245, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 0, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 0, + 269, 270, 271, 272, 273, 274, 275, 276, 0, 277, + 0, 278, 0, 0, 281, 0, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 0, 291, 0, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 0, + 324, 325, 326, 327, 328, 0, 329, 330, 0, 332, + 0, 333, 334, 335, 336, 337, 338, 0, 339, 340, + 0, 0, 341, 342, 343, 0, 0, 344, 345, 346, + 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 364, 0, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 0, 431, 432, 433, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 530, 448, 449, 0, 0, 450, 451, 0, + 452, 0, 454, 455, 456, 457, 458, 0, 459, 460, + 461, 0, 0, 462, 463, 464, 465, 466, 0, 467, + 468, 469, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 488, 0, 489, 0, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2069, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 130, 131, 0, 132, 133, 134, 0, 136, 137, + 138, 139, 140, 0, 142, 143, 0, 144, 145, 146, + 147, 148, 149, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 0, 157, 158, 159, 160, 161, 0, 0, + 0, 163, 164, 165, 166, 167, 168, 0, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 0, 194, 0, 195, 196, 197, - 198, 199, 200, 0, 0, 201, 202, 203, 204, 0, - 0, 205, 206, 207, 208, 209, 0, 210, 211, 212, - 0, 213, 214, 215, 0, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 0, 227, 0, 228, - 229, 230, 231, 0, 232, 0, 233, 0, 0, 0, - 236, 237, 524, 0, 240, 0, 241, 0, 242, 243, - 244, 245, 0, 246, 247, 248, 249, 250, 251, 252, - 0, 254, 255, 256, 257, 0, 258, 259, 260, 261, - 262, 263, 264, 0, 265, 0, 267, 268, 269, 270, - 271, 272, 273, 274, 0, 275, 0, 276, 0, 0, - 279, 0, 281, 282, 283, 284, 285, 286, 0, 0, - 287, 0, 289, 0, 0, 291, 292, 293, 294, 295, - 296, 297, 298, 525, 300, 301, 302, 303, 304, 305, + 190, 191, 192, 193, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 0, 229, + 0, 230, 231, 232, 233, 0, 234, 0, 235, 0, + 0, 0, 238, 239, 528, 0, 242, 0, 243, 0, + 244, 245, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 0, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 0, 269, 270, + 271, 272, 273, 274, 275, 276, 0, 277, 0, 278, + 0, 0, 281, 0, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 0, 291, 0, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 0, 322, 323, 324, 325, - 326, 0, 327, 328, 0, 330, 0, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 0, 0, 339, 340, - 341, 0, 0, 342, 343, 344, 0, 346, 0, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 0, 0, 0, 0, 360, 361, 362, 0, 364, - 365, 366, 367, 368, 369, 0, 370, 371, 372, 373, - 374, 375, 0, 376, 377, 378, 379, 380, 381, 382, - 383, 0, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 0, 397, 398, 0, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, 412, 413, 414, 415, 416, 0, 0, 417, 418, - 419, 420, 421, 422, 423, 424, 425, 0, 0, 427, - 428, 429, 430, 0, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 526, 444, 445, 0, - 0, 446, 447, 0, 448, 0, 450, 451, 452, 453, - 454, 0, 455, 456, 457, 0, 0, 458, 459, 460, - 461, 462, 0, 463, 464, 465, 466, 467, 468, 469, - 470, 0, 0, 471, 472, 473, 0, 474, 475, 476, - 477, 0, 478, 479, 480, 481, 482, 483, 484, 0, - 485, 0, 487, 488, 489, 490, 491, 492, 493, 0, - 0, 494, 0, 0, 495, 496, 497, 498, 499, 500, + 316, 317, 318, 319, 320, 321, 322, 0, 324, 325, + 326, 327, 328, 0, 329, 330, 0, 332, 0, 333, + 334, 335, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 346, 0, 348, + 0, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 364, + 0, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 383, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 0, 431, 432, 433, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 530, 448, 449, 0, 0, 450, 451, 0, 452, 0, + 454, 455, 456, 457, 458, 0, 459, 460, 461, 0, + 0, 462, 463, 464, 465, 466, 0, 467, 468, 469, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 488, 0, 489, 0, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, - 511, 512, 513, 514, 515, 523, 0, 0, 0, 0, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2161, 0, 0, 117, 118, 119, 120, 121, 122, - 123, 124, 0, 125, 126, 127, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 129, 130, 0, 131, 132, - 133, 0, 135, 136, 137, 138, 139, 0, 141, 142, - 0, 143, 144, 145, 146, 147, 148, 0, 0, 149, - 150, 151, 152, 153, 154, 155, 0, 156, 157, 158, - 159, 160, 0, 0, 0, 162, 163, 164, 165, 166, - 167, 0, 169, 170, 171, 0, 172, 173, 174, 175, - 176, 177, 0, 0, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 0, - 194, 0, 195, 196, 197, 198, 199, 200, 0, 0, - 201, 202, 203, 204, 0, 0, 205, 206, 207, 208, - 209, 0, 210, 211, 212, 0, 213, 214, 215, 0, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 0, 227, 0, 228, 229, 230, 231, 0, 232, - 0, 233, 0, 0, 0, 236, 237, 524, 0, 240, - 0, 241, 0, 242, 243, 244, 245, 0, 246, 247, - 248, 249, 250, 251, 252, 0, 254, 255, 256, 257, - 0, 258, 259, 260, 261, 262, 263, 264, 0, 265, - 0, 267, 268, 269, 270, 271, 272, 273, 274, 0, - 275, 0, 276, 0, 0, 279, 0, 281, 282, 283, - 284, 285, 286, 0, 0, 287, 0, 289, 0, 0, - 291, 292, 293, 294, 295, 296, 297, 298, 525, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 0, 322, 323, 324, 325, 326, 0, 327, 328, 0, - 330, 0, 331, 332, 333, 334, 335, 336, 0, 337, - 338, 0, 0, 339, 340, 341, 0, 0, 342, 343, - 344, 0, 346, 0, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 0, 0, 0, 0, - 360, 361, 362, 0, 364, 365, 366, 367, 368, 369, - 0, 370, 371, 372, 373, 374, 375, 0, 376, 377, - 378, 379, 380, 381, 382, 383, 0, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 0, 397, 398, 0, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 0, 0, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 0, 0, 427, 428, 429, 430, 0, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 526, 444, 445, 0, 0, 446, 447, 0, 448, - 0, 450, 451, 452, 453, 454, 0, 455, 456, 457, - 0, 0, 458, 459, 460, 461, 462, 0, 463, 464, - 465, 466, 467, 468, 469, 470, 0, 0, 471, 472, - 473, 0, 474, 475, 476, 477, 0, 478, 479, 480, - 481, 482, 483, 484, 0, 485, 0, 487, 488, 489, - 490, 491, 492, 493, 0, 0, 494, 0, 0, 495, - 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, - 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, - 0, 2895, 1341, 815, 0, 0, 2034, 1046, 0, 0, - 0, 0, 0, 2035, 2036, 0, 3076, 2037, 2038, 2039, - 117, 118, 119, 120, 121, 122, 123, 124, 556, 125, - 126, 127, 557, 558, 559, 2896, 561, 562, 563, 564, - 2897, 129, 130, 566, 131, 132, 133, 2898, 135, 136, - 137, 0, 1480, 2899, 1482, 1483, 573, 143, 144, 145, - 146, 147, 148, 574, 575, 149, 150, 151, 152, 1484, - 1485, 155, 578, 156, 157, 158, 159, 0, 580, 2900, - 582, 2901, 163, 164, 165, 166, 167, 2902, 169, 170, - 171, 585, 172, 173, 174, 175, 176, 177, 586, 2903, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 1490, 190, 191, 1491, 193, 591, 194, 592, 195, 196, - 197, 198, 199, 200, 593, 594, 201, 202, 203, 204, - 595, 596, 205, 206, 1059, 208, 209, 597, 210, 211, - 212, 598, 213, 214, 215, 599, 216, 217, 218, 219, - 0, 221, 222, 223, 224, 225, 0, 602, 227, 603, - 228, 229, 1492, 231, 605, 232, 606, 233, 2904, 608, - 2905, 236, 237, 2906, 2907, 240, 612, 241, 613, 0, - 0, 244, 245, 616, 246, 247, 248, 249, 250, 251, - 252, 2908, 254, 255, 256, 257, 618, 258, 259, 260, - 261, 262, 263, 264, 619, 265, 2909, 0, 268, 269, - 270, 271, 272, 1498, 1499, 624, 1500, 626, 276, 2910, - 2911, 279, 2912, 281, 282, 283, 284, 285, 286, 630, - 631, 287, 2913, 289, 2914, 634, 291, 292, 293, 294, - 295, 296, 297, 298, 2915, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 1507, 2916, 1509, 323, 324, - 325, 2917, 640, 327, 328, 2918, 330, 642, 0, 332, - 1511, 334, 335, 336, 645, 337, 338, 646, 647, 2919, - 340, 341, 648, 649, 342, 343, 0, 2920, 346, 2921, - 0, 349, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 654, 655, 656, 657, 360, 361, 0, 2922, - 364, 365, 0, 367, 368, 369, 661, 370, 371, 372, - 373, 374, 375, 662, 376, 377, 378, 1515, 380, 381, - 382, 383, 664, 384, 385, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, 396, 665, 397, 398, 2923, - 400, 401, 402, 1517, 404, 405, 406, 407, 408, 409, - 410, 411, 412, 413, 414, 415, 416, 668, 2924, 417, - 418, 419, 420, 421, 422, 2925, 424, 425, 671, 2926, - 427, 428, 1521, 430, 674, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 2927, 444, 0, - 677, 678, 446, 447, 679, 448, 2928, 450, 451, 452, - 453, 454, 681, 455, 1524, 1525, 684, 685, 458, 459, - 0, 461, 0, 688, 463, 464, 2929, 466, 467, 468, - 469, 470, 2930, 691, 471, 472, 473, 692, 474, 475, - 476, 477, 693, 478, 479, 480, 481, 482, 0, 1528, - 696, 485, 2931, 487, 488, 489, 490, 491, 492, 493, - 698, 699, 494, 700, 701, 495, 496, 497, 498, 499, - 500, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 512, 513, 514, 515, 0, 523, 0, 2040, - 2041, 2042, 2034, 2932, 2933, 2045, 2046, 2047, 2048, 2035, - 2036, 0, 0, 2037, 2038, 2039, 117, 118, 119, 120, - 121, 122, 123, 124, 0, 125, 126, 127, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 129, 130, 0, - 131, 132, 133, 0, 135, 136, 137, 138, 139, 0, - 141, 142, 0, 143, 144, 145, 146, 147, 148, 0, - 0, 149, 150, 151, 152, 153, 154, 155, 0, 156, - 157, 158, 159, 160, 0, 0, 0, 162, 163, 164, - 165, 166, 167, 0, 169, 170, 171, 0, 172, 173, - 174, 175, 176, 177, 0, 0, 179, 180, 181, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 0, 194, 0, 195, 196, 197, 198, 199, 200, - 0, 0, 201, 202, 203, 204, 0, 0, 205, 206, - 207, 208, 209, 0, 210, 211, 212, 0, 213, 214, - 215, 0, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 0, 227, 0, 228, 229, 230, 231, - 0, 232, 0, 233, 0, 0, 0, 236, 237, 524, - 0, 240, 0, 241, 0, 242, 243, 244, 245, 0, - 246, 247, 248, 249, 250, 251, 252, 0, 254, 255, - 256, 257, 0, 258, 259, 260, 261, 262, 263, 264, - 0, 265, 0, 267, 268, 269, 270, 271, 272, 273, - 274, 0, 275, 0, 276, 0, 0, 279, 0, 281, - 282, 283, 284, 285, 286, 0, 0, 287, 0, 289, - 0, 0, 291, 292, 293, 294, 295, 296, 297, 298, - 525, 300, 301, 302, 303, 304, 305, 306, 307, 308, + 0, 0, 0, 0, 0, 2172, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, + 131, 0, 132, 133, 134, 0, 136, 137, 138, 139, + 140, 0, 142, 143, 0, 144, 145, 146, 147, 148, + 149, 0, 0, 150, 151, 152, 153, 154, 155, 156, + 0, 157, 158, 159, 160, 161, 0, 0, 0, 163, + 164, 165, 166, 167, 168, 0, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 0, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 0, 229, 0, 230, + 231, 232, 233, 0, 234, 0, 235, 0, 0, 0, + 238, 239, 528, 0, 242, 0, 243, 0, 244, 245, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 0, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 0, 269, 270, 271, 272, + 273, 274, 275, 276, 0, 277, 0, 278, 0, 0, + 281, 0, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 0, 291, 0, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 0, 324, 325, 326, 327, + 328, 0, 329, 330, 0, 332, 0, 333, 334, 335, + 336, 337, 338, 0, 339, 340, 0, 0, 341, 342, + 343, 0, 0, 344, 345, 346, 0, 348, 0, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 364, 0, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 0, 431, 432, 433, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 530, 448, + 449, 0, 0, 450, 451, 0, 452, 0, 454, 455, + 456, 457, 458, 0, 459, 460, 461, 0, 0, 462, + 463, 464, 465, 466, 0, 467, 468, 469, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 488, 0, 489, 0, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 0, 2913, 1350, + 819, 0, 0, 2044, 1050, 0, 0, 0, 0, 0, + 2045, 2046, 0, 3094, 2047, 2048, 2049, 118, 119, 120, + 121, 122, 123, 124, 125, 560, 126, 127, 128, 561, + 562, 563, 2914, 565, 566, 567, 568, 2915, 130, 131, + 570, 132, 133, 134, 2916, 136, 137, 138, 0, 1486, + 2917, 1488, 1489, 577, 144, 145, 146, 147, 148, 149, + 578, 579, 150, 151, 152, 153, 1490, 1491, 156, 582, + 157, 158, 159, 160, 0, 584, 2918, 586, 2919, 164, + 165, 166, 167, 168, 2920, 170, 171, 172, 589, 173, + 174, 175, 176, 177, 178, 590, 2921, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 1496, 191, 192, + 1497, 194, 595, 195, 596, 196, 197, 198, 199, 200, + 201, 597, 598, 202, 203, 204, 205, 599, 600, 206, + 207, 1063, 209, 210, 601, 211, 212, 213, 602, 214, + 215, 216, 603, 217, 218, 219, 220, 0, 222, 223, + 224, 225, 226, 227, 0, 606, 229, 607, 230, 231, + 1498, 233, 609, 234, 610, 235, 2922, 612, 2923, 238, + 239, 2924, 2925, 242, 616, 243, 617, 0, 0, 246, + 247, 620, 248, 249, 250, 251, 252, 253, 254, 2926, + 256, 257, 258, 259, 622, 260, 261, 262, 263, 264, + 265, 266, 623, 267, 2927, 0, 270, 271, 272, 273, + 274, 1504, 1505, 628, 1506, 630, 278, 2928, 2929, 281, + 2930, 283, 284, 285, 286, 287, 288, 634, 635, 289, + 2931, 291, 2932, 638, 293, 294, 295, 296, 297, 298, + 299, 300, 2933, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 0, 322, 323, 324, 325, 326, 0, 327, - 328, 0, 330, 0, 331, 332, 333, 334, 335, 336, - 0, 337, 338, 0, 0, 339, 340, 341, 0, 0, - 342, 343, 344, 0, 346, 0, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 0, 0, - 0, 0, 360, 361, 362, 0, 364, 365, 366, 367, - 368, 369, 0, 370, 371, 372, 373, 374, 375, 0, - 376, 377, 378, 379, 380, 381, 382, 383, 0, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 0, 397, 398, 0, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, - 414, 415, 416, 0, 0, 417, 418, 419, 420, 421, - 422, 423, 424, 425, 0, 0, 427, 428, 429, 430, - 0, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 526, 444, 445, 0, 0, 446, 447, - 0, 448, 0, 450, 451, 452, 453, 454, 0, 455, - 456, 457, 0, 0, 458, 459, 460, 461, 462, 0, - 463, 464, 465, 466, 467, 468, 469, 470, 0, 0, - 471, 472, 473, 0, 474, 475, 476, 477, 0, 478, - 479, 480, 481, 482, 483, 484, 0, 485, 0, 487, - 488, 489, 490, 491, 492, 493, 0, 0, 494, 0, - 0, 495, 496, 497, 498, 499, 500, 501, 502, 503, - 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, - 514, 515, 0, 0, 0, 2040, 2041, 2042, 0, 2043, - 2044, 2045, 2046, 2047, 2048, 1611, 0, 0, 1612, 0, - 0, 0, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1620, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1622, 1611, 0, 0, 1612, 0, 0, - 1623, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, 0, + 319, 320, 321, 1513, 2934, 1515, 325, 326, 327, 2935, + 644, 329, 330, 2936, 332, 646, 0, 334, 1517, 336, + 337, 338, 649, 339, 340, 650, 651, 2937, 342, 343, + 652, 653, 344, 345, 0, 2938, 348, 2939, 0, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 658, 659, 660, 661, 362, 363, 0, 2940, 366, 367, + 0, 369, 370, 371, 665, 372, 373, 374, 375, 376, + 377, 666, 378, 379, 380, 381, 382, 1521, 384, 385, + 386, 387, 668, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 669, 401, 402, 2941, + 404, 405, 406, 1523, 408, 409, 410, 411, 412, 413, + 414, 415, 416, 417, 418, 419, 420, 672, 2942, 421, + 422, 423, 424, 425, 426, 2943, 428, 429, 675, 2944, + 431, 432, 1527, 434, 678, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, 2945, 448, 0, + 681, 682, 450, 451, 683, 452, 2946, 454, 455, 456, + 457, 458, 685, 459, 1530, 1531, 688, 689, 462, 463, + 0, 465, 0, 692, 467, 468, 2947, 470, 471, 472, + 473, 474, 2948, 695, 475, 476, 477, 696, 478, 479, + 480, 481, 697, 482, 483, 484, 485, 486, 0, 1534, + 700, 489, 2949, 491, 492, 493, 494, 495, 496, 497, + 702, 703, 498, 704, 705, 499, 500, 501, 502, 503, + 504, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 516, 517, 518, 519, 0, 527, 0, 2050, + 2051, 2052, 2044, 2950, 2951, 2055, 2056, 2057, 2058, 2045, + 2046, 0, 0, 2047, 2048, 2049, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 130, 131, 0, + 132, 133, 134, 0, 136, 137, 138, 139, 140, 0, + 142, 143, 0, 144, 145, 146, 147, 148, 149, 0, + 0, 150, 151, 152, 153, 154, 155, 156, 0, 157, + 158, 159, 160, 161, 0, 0, 0, 163, 164, 165, + 166, 167, 168, 0, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 0, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 208, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 0, 229, 0, 230, 231, 232, + 233, 0, 234, 0, 235, 0, 0, 0, 238, 239, + 528, 0, 242, 0, 243, 0, 244, 245, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 0, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 0, 269, 270, 271, 272, 273, 274, + 275, 276, 0, 277, 0, 278, 0, 0, 281, 0, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 0, + 291, 0, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 0, 324, 325, 326, 327, 328, 0, + 329, 330, 0, 332, 0, 333, 334, 335, 336, 337, + 338, 0, 339, 340, 0, 0, 341, 342, 343, 0, + 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 364, 0, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 0, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 0, 431, + 432, 433, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 530, 448, 449, 0, + 0, 450, 451, 0, 452, 0, 454, 455, 456, 457, + 458, 0, 459, 460, 461, 0, 0, 462, 463, 464, + 465, 466, 0, 467, 468, 469, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 488, 0, + 489, 0, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 0, 0, 0, 2050, 2051, + 2052, 0, 2053, 2054, 2055, 2056, 2057, 2058, 1618, 0, + 0, 1619, 0, 0, 0, 1620, 1621, 1622, 1623, 1624, + 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1627, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1629, 1618, 0, 0, + 1619, 0, 0, 1630, 1620, 1621, 1622, 1623, 1624, 1625, + 1626, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1627, 0, 0, 0, 0, + 1631, 721, 0, 0, 0, 1629, 1618, 0, 0, 1619, + 0, 0, 1630, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1620, 0, 0, 0, 0, 1624, 0, 0, - 0, 0, 1622, 1611, 0, 0, 1612, 0, 0, 1623, - 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, 0, 0, + 0, 0, 0, 0, 1627, 0, 0, 0, 0, 1631, + 0, 0, 0, 0, 1629, 0, 0, 0, 0, 0, + 0, 1630, 0, 1618, 0, 0, 1619, 0, 722, 0, + 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, + 0, 0, 0, 0, 723, 0, 0, 0, 1631, 0, + 0, 1627, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1629, 1618, 0, 0, 1619, 0, 1632, 1630, 1620, + 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, 0, + 0, 0, 0, 0, 1633, 0, 0, 0, 0, 1634, + 1627, 0, 0, 724, 0, 1631, 0, 0, 0, 0, + 1629, 0, 0, 725, 0, 0, 1632, 1630, 0, 0, + 0, 0, 1635, 1636, 0, 0, 726, 0, 0, 0, + 0, 727, 0, 1633, 0, 0, 0, 1637, 1634, 0, + 0, 0, 0, 0, 1631, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1632, 0, 0, 0, 0, + 728, 1635, 1636, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1633, 0, 0, 1638, 1637, 1634, 1639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1620, 0, 0, 0, 0, 1624, 0, 0, 0, - 0, 1622, 0, 0, 0, 0, 0, 0, 1623, 0, - 1611, 0, 0, 1612, 0, 0, 0, 1613, 1614, 1615, - 1616, 1617, 1618, 1619, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1624, 0, 0, 1620, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1622, 1611, - 0, 0, 1612, 1625, 0, 1623, 1613, 1614, 1615, 1616, - 1617, 1618, 1619, 0, 0, 0, 0, 0, 0, 0, - 1626, 0, 0, 0, 0, 1627, 0, 1620, 0, 0, - 0, 0, 1624, 0, 0, 0, 0, 1622, 0, 0, - 0, 0, 1625, 0, 1623, 0, 0, 0, 1628, 1629, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1626, - 0, 0, 0, 1630, 1627, 0, 0, 0, 0, 0, - 0, 1624, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1625, 0, 0, 0, 0, 0, 1628, 1629, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1626, 0, - 0, 1631, 1630, 1627, 1632, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1633, 0, - 0, 1634, 0, 0, 0, 0, 1628, 1629, 1625, 0, + 0, 0, 1640, 0, 0, 1641, 0, 0, 0, 0, + 1635, 1636, 1632, 729, 0, 0, 0, 730, 0, 0, + 0, 0, 0, 0, 1638, 1637, 0, 1639, 0, 1633, + 0, 0, 0, 0, 1634, 0, 0, 0, 0, 0, + 0, 1640, 0, 0, 1641, 0, 0, 0, 0, 0, + 0, 1632, 0, 0, 0, 0, 0, 1635, 1636, 0, + 0, 0, 0, 1638, 0, 0, 1639, 0, 1633, 0, + 0, 0, 1637, 1634, 0, 0, 0, 0, 0, 0, + 1640, 543, 0, 1641, 0, 0, 0, 731, 0, 0, + 0, 0, 0, 0, 0, 0, 1635, 1636, 0, 0, + 0, 0, 732, 0, 1642, 0, 0, 0, 0, 0, + 1638, 1637, 0, 1639, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1640, 0, 0, + 1641, 0, 0, 0, 0, 0, 0, 733, 0, 0, + 734, 0, 0, 1642, 0, 0, 0, 0, 0, 1638, + 0, 735, 1639, 0, 736, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1640, 0, 0, 1641, + 0, 0, 737, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1642, 0, 0, 0, 738, 0, 0, 0, + 0, 0, 739, 740, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 741, 0, 0, 0, 0, 0, 742, + 0, 1643, 0, 0, 1644, 1645, 1646, 0, 1647, 1648, + 1649, 1650, 1651, 1652, 0, 0, 0, 0, 2792, 1642, + 0, 0, 0, 0, 0, 1618, 743, 0, 1619, 0, + 0, 0, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, + 1643, 0, 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, + 1650, 1651, 1652, 1627, 0, 0, 0, 2859, 1642, 0, + 0, 0, 0, 1629, 0, 0, 0, 0, 0, 0, + 1630, 0, 0, 0, 0, 0, 0, 0, 0, 1643, + 0, 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, 1650, + 1651, 1652, 0, 0, 0, 0, 3086, 1631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1631, 1630, 0, 1632, 0, 1626, 0, 0, 0, 0, - 1627, 0, 0, 0, 0, 0, 0, 1633, 0, 0, - 1634, 0, 0, 0, 0, 0, 0, 1625, 0, 0, - 0, 0, 0, 1628, 1629, 0, 0, 0, 0, 1631, - 0, 0, 1632, 0, 1626, 0, 0, 0, 1630, 1627, - 0, 0, 0, 0, 0, 0, 1633, 0, 0, 1634, + 0, 1618, 0, 0, 1619, 0, 0, 0, 1620, 1621, + 1622, 1623, 1624, 1625, 1626, 0, 1643, 0, 0, 1644, + 1645, 1646, 0, 1647, 1648, 1649, 1650, 1651, 1652, 1627, + 0, 0, 0, 3093, 0, 0, 0, 0, 0, 1629, + 1618, 0, 0, 1619, 0, 0, 1630, 1620, 1621, 1622, + 1623, 1624, 1625, 1626, 0, 1643, 0, 0, 1644, 1645, + 1646, 0, 1647, 1648, 1649, 1650, 1651, 1652, 1627, 0, + 0, 0, 3253, 1631, 0, 0, 0, 0, 1629, 1618, + 0, 0, 1619, 0, 1632, 1630, 1620, 1621, 1622, 1623, + 1624, 1625, 1626, 0, 0, 0, 0, 0, 0, 0, + 0, 1633, 0, 0, 0, 0, 1634, 1627, 0, 0, + 0, 0, 1631, 0, 0, 0, 0, 1629, 0, 0, + 0, 0, 0, 0, 1630, 0, 0, 0, 0, 1635, + 1636, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1637, 0, 0, 0, 0, 0, + 0, 1631, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1618, 0, 0, 1619, 0, + 1632, 0, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, + 0, 0, 1638, 0, 0, 1639, 0, 1633, 0, 0, + 0, 0, 1634, 1627, 0, 0, 0, 0, 0, 1640, + 0, 0, 1641, 1629, 0, 0, 0, 0, 0, 1632, + 1630, 0, 0, 0, 0, 1635, 1636, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1633, 0, 0, 0, + 1637, 1634, 0, 0, 0, 0, 0, 1631, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1632, 0, + 0, 0, 0, 0, 1635, 1636, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1633, 0, 0, 1638, 1637, + 1634, 1639, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1640, 0, 0, 1641, 0, + 0, 0, 0, 1635, 1636, 0, 0, 0, 0, 0, + 0, 1642, 0, 0, 0, 0, 0, 1638, 1637, 0, + 1639, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1640, 0, 0, 1641, 0, 0, + 0, 0, 0, 0, 1632, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1638, 0, 0, 1639, + 0, 1633, 0, 0, 0, 0, 1634, 0, 0, 0, + 0, 0, 0, 1640, 0, 0, 1641, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1635, + 1636, 0, 0, 0, 0, 0, 0, 1642, 0, 0, + 0, 0, 0, 0, 1637, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1643, 0, + 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, 1650, 1651, + 1652, 0, 0, 0, 0, 3275, 1642, 0, 0, 0, + 0, 0, 1638, 0, 0, 1639, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1640, + 0, 0, 1641, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1628, 1629, 0, 0, 0, 0, 1635, 0, - 0, 0, 0, 0, 0, 0, 1631, 1630, 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1633, 0, 0, 1634, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1635, 0, 0, - 0, 0, 0, 0, 0, 1631, 0, 0, 1632, 0, + 0, 0, 0, 0, 1643, 0, 0, 1644, 1645, 1646, + 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, 0, + 0, 3376, 0, 0, 0, 0, 0, 0, 1618, 0, + 0, 1619, 0, 0, 0, 1620, 1621, 1622, 1623, 1624, + 1625, 1626, 0, 1643, 0, 0, 1644, 1645, 1646, 0, + 1647, 1648, 1649, 1650, 1651, 1652, 1627, 0, 0, 0, + 3433, 1642, 0, 0, 0, 0, 1629, 1618, 0, 0, + 1619, 0, 0, 1630, 1620, 1621, 1622, 1623, 1624, 1625, + 1626, 0, 1643, 0, 0, 1644, 1645, 1646, 0, 1647, + 1648, 1649, 1650, 1651, 1652, 1627, 0, 0, 0, 3455, + 1631, 0, 0, 0, 0, 1629, 0, 0, 0, 0, + 0, 0, 1630, 0, 1618, 0, 0, 1619, 0, 0, + 0, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1631, + 0, 0, 1627, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1629, 0, 0, 0, 0, 0, 0, 1630, + 0, 0, 0, 0, 0, 0, 0, 0, 1643, 0, + 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, 1650, 1651, + 1652, 0, 0, 1807, 0, 0, 1631, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1633, 0, 0, 1634, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1635, 0, 0, 0, + 0, 0, 0, 0, 1633, 0, 0, 0, 0, 1634, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1632, 0, 0, 0, + 0, 0, 1635, 1636, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1633, 0, 0, 0, 1637, 1634, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1636, 0, 0, 1637, 1638, - 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, 0, 0, - 0, 0, 2841, 1635, 0, 0, 0, 0, 0, 1611, - 0, 0, 1612, 0, 0, 0, 1613, 1614, 1615, 1616, - 1617, 1618, 1619, 0, 1636, 0, 0, 1637, 1638, 1639, - 0, 1640, 1641, 1642, 1643, 1644, 1645, 1620, 0, 0, - 0, 3068, 1635, 0, 0, 0, 0, 1622, 0, 0, - 0, 0, 0, 0, 1623, 0, 0, 0, 0, 0, - 0, 0, 0, 1636, 0, 0, 1637, 1638, 1639, 0, - 1640, 1641, 1642, 1643, 1644, 1645, 0, 0, 0, 0, - 3075, 1624, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1611, 0, 0, 1612, 0, - 0, 0, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, - 1636, 0, 0, 1637, 1638, 1639, 0, 1640, 1641, 1642, - 1643, 1644, 1645, 1620, 0, 0, 0, 3235, 0, 0, - 0, 0, 0, 1622, 1611, 0, 0, 1612, 0, 0, - 1623, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, 1636, - 0, 0, 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, - 1644, 1645, 1620, 0, 0, 0, 3257, 1624, 0, 0, - 0, 0, 1622, 1611, 0, 0, 1612, 1625, 0, 1623, - 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, 0, 0, - 0, 0, 0, 0, 1626, 0, 0, 0, 0, 1627, - 0, 1620, 0, 0, 0, 0, 1624, 0, 0, 0, - 0, 1622, 0, 0, 0, 0, 0, 0, 1623, 0, - 0, 0, 1628, 1629, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1630, 0, 0, - 0, 0, 0, 0, 0, 1624, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1611, - 0, 0, 1612, 1625, 0, 0, 1613, 1614, 1615, 1616, - 1617, 1618, 1619, 0, 0, 1631, 0, 0, 1632, 0, - 1626, 0, 0, 0, 0, 1627, 0, 1620, 0, 0, - 0, 0, 1633, 0, 0, 1634, 0, 1622, 0, 0, - 0, 0, 1625, 0, 1623, 0, 0, 0, 1628, 1629, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1626, - 0, 0, 0, 1630, 1627, 0, 0, 0, 0, 0, - 0, 1624, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1625, 0, 0, 0, 0, 0, 1628, 1629, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1626, 0, - 0, 1631, 1630, 1627, 1632, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1633, 0, - 0, 1634, 0, 0, 0, 0, 1628, 1629, 0, 0, - 0, 0, 1635, 0, 0, 0, 0, 0, 0, 0, - 1631, 1630, 0, 1632, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1633, 0, 0, - 1634, 0, 0, 0, 0, 0, 0, 1625, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1631, - 0, 0, 1632, 0, 1626, 0, 0, 0, 0, 1627, - 0, 0, 0, 0, 0, 0, 1633, 0, 0, 1634, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1628, 1629, 0, 0, 0, 0, 1635, 0, - 0, 0, 0, 0, 0, 0, 0, 1630, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1636, - 0, 0, 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, - 1644, 1645, 0, 0, 0, 0, 3358, 1635, 0, 0, - 0, 0, 0, 0, 0, 1631, 0, 1611, 1632, 0, - 1612, 0, 0, 0, 1613, 1614, 1615, 1616, 1617, 1618, - 1619, 0, 1633, 0, 0, 1634, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1620, 1635, 0, 0, 0, - 0, 0, 0, 0, 0, 1622, 0, 0, 0, 0, - 0, 0, 1623, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1636, 0, 0, 1637, 1638, - 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, 0, 1624, - 0, 0, 3415, 0, 0, 0, 0, 0, 0, 1611, - 0, 0, 1612, 0, 0, 0, 1613, 1614, 1615, 1616, - 1617, 1618, 1619, 0, 1636, 0, 0, 1637, 1638, 1639, - 0, 1640, 1641, 1642, 1643, 1644, 1645, 1620, 0, 0, - 0, 3437, 1635, 0, 0, 0, 0, 1622, 0, 0, - 0, 0, 0, 0, 1623, 0, 0, 0, 0, 0, - 0, 0, 0, 1636, 0, 0, 1637, 1638, 1639, 0, - 1640, 1641, 1642, 1643, 1644, 1645, 0, 0, 1796, 0, - 0, 1624, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1625, 0, 0, 0, 0, + 0, 1635, 1636, 1632, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1638, 1637, 0, 1639, 0, + 1633, 0, 0, 0, 0, 1634, 0, 0, 0, 0, + 0, 0, 1640, 0, 0, 1641, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1635, 1636, + 0, 0, 0, 0, 1638, 0, 0, 1639, 0, 0, + 0, 0, 0, 1637, 0, 0, 0, 0, 0, 0, + 0, 1640, 0, 0, 1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1626, 0, 0, 0, 0, 1627, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1638, 0, 0, 1639, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1640, 0, + 0, 1641, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1628, 1629, 0, 0, 0, 0, 0, 0, 0, 1636, - 0, 0, 1637, 1638, 1639, 1630, 1640, 1641, 1642, 1643, - 1644, 1645, 0, 0, 2795, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1625, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1631, 1626, 0, 1632, 0, 0, 1627, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1633, 0, 0, 1634, 0, 0, 0, 0, 0, 0, - 0, 0, 1628, 1629, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1630, 0, 0, + 0, 0, 0, 1642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1631, 0, 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1633, 0, 0, 1634, 0, 0, 0, 0, + 1642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1635, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1643, 0, 0, 1644, 1645, 1646, 0, 1647, 1648, + 1649, 1650, 1651, 1652, 0, 0, 2813, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1643, 0, 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, + 1650, 1651, 1652, 0, 0, 3243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 559, 0, 0, 1643, 0, 0, + 1644, 1645, 1646, 0, 1647, 1648, 1649, 1650, 1651, 1652, + 0, 0, 3417, 118, 119, 120, 121, 122, 123, 124, + 125, 560, 126, 127, 128, 561, 562, 563, 564, 565, + 566, 567, 568, 569, 130, 131, 570, 132, 133, 134, + 571, 136, 137, 138, 572, 573, 574, 575, 576, 577, + 144, 145, 146, 147, 148, 149, 578, 579, 150, 151, + 152, 153, 580, 581, 156, 582, 157, 158, 159, 160, + 583, 584, 585, 586, 587, 164, 165, 166, 167, 168, + 588, 170, 171, 172, 589, 173, 174, 175, 176, 177, + 178, 590, 591, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 593, 191, 192, 594, 194, 595, 195, + 596, 196, 197, 198, 199, 200, 201, 597, 598, 202, + 203, 204, 205, 599, 600, 206, 207, 208, 209, 210, + 601, 211, 212, 213, 602, 214, 215, 216, 603, 217, + 218, 219, 220, 604, 222, 223, 224, 225, 226, 227, + 605, 606, 229, 607, 230, 231, 608, 233, 609, 234, + 610, 235, 611, 612, 613, 238, 239, 614, 615, 242, + 616, 243, 617, 618, 619, 246, 247, 620, 248, 249, + 250, 251, 252, 253, 254, 621, 256, 257, 258, 259, + 622, 260, 261, 262, 263, 264, 265, 266, 623, 267, + 624, 625, 270, 271, 272, 273, 274, 626, 627, 628, + 629, 630, 278, 631, 632, 281, 633, 283, 284, 285, + 286, 287, 288, 634, 635, 289, 636, 291, 637, 638, + 293, 294, 295, 296, 297, 298, 299, 300, 639, 302, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 640, + 641, 642, 325, 326, 327, 643, 644, 329, 330, 645, + 332, 646, 647, 334, 648, 336, 337, 338, 649, 339, + 340, 650, 651, 341, 342, 343, 652, 653, 344, 345, + 654, 655, 348, 656, 657, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 658, 659, 660, 661, + 362, 363, 662, 663, 366, 367, 664, 369, 370, 371, + 665, 372, 373, 374, 375, 376, 377, 666, 378, 379, + 380, 381, 382, 667, 384, 385, 386, 387, 668, 388, + 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 669, 401, 402, 670, 404, 405, 406, 671, + 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, + 418, 419, 420, 672, 673, 421, 422, 423, 424, 425, + 426, 674, 428, 429, 675, 676, 431, 432, 677, 434, + 678, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, 679, 448, 680, 681, 682, 450, 451, + 683, 452, 684, 454, 455, 456, 457, 458, 685, 459, + 686, 687, 688, 689, 462, 463, 690, 465, 691, 692, + 467, 468, 693, 470, 471, 472, 473, 474, 694, 695, + 475, 476, 477, 696, 478, 479, 480, 481, 697, 482, + 483, 484, 485, 486, 698, 699, 700, 489, 701, 491, + 492, 493, 494, 495, 496, 497, 702, 703, 498, 704, + 705, 499, 500, 501, 502, 503, 504, 706, 707, 708, + 709, 710, 711, 712, 713, 714, 715, 716, 516, 517, + 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, + 0, 2080, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 118, 119, 120, 121, 122, 123, 124, 125, 0, + 126, 127, 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 130, 131, 0, 132, 133, 134, 0, 136, + 137, 138, 139, 140, 0, 142, 143, 0, 144, 145, + 146, 147, 148, 149, 0, 0, 150, 151, 152, 153, + 154, 155, 156, 0, 157, 158, 159, 160, 161, 0, + 0, 0, 163, 164, 165, 166, 167, 168, 0, 170, + 171, 172, 0, 173, 174, 175, 176, 177, 178, 0, + 0, 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 0, 195, 0, 196, + 197, 198, 199, 200, 201, 0, 0, 202, 203, 204, + 205, 0, 0, 206, 207, 208, 209, 210, 0, 211, + 212, 213, 0, 214, 215, 216, 0, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 0, + 229, 0, 230, 231, 232, 233, 0, 234, 0, 235, + 0, 0, 0, 238, 239, 528, 0, 242, 0, 243, + 0, 244, 245, 246, 247, 0, 248, 249, 250, 251, + 252, 253, 254, 0, 256, 257, 258, 259, 0, 260, + 261, 262, 263, 264, 265, 266, 0, 267, 0, 269, + 270, 271, 272, 273, 274, 275, 276, 0, 277, 0, + 278, 0, 0, 281, 0, 283, 284, 285, 286, 287, + 288, 0, 0, 289, 0, 291, 0, 0, 293, 294, + 295, 296, 297, 298, 299, 300, 529, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 0, 324, + 325, 326, 327, 328, 0, 329, 330, 0, 332, 0, + 333, 334, 335, 336, 337, 338, 0, 339, 340, 0, + 0, 341, 342, 343, 0, 0, 344, 345, 346, 0, + 348, 0, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, 361, 0, 0, 0, 0, 362, 363, + 364, 0, 366, 367, 368, 369, 370, 371, 0, 372, + 373, 374, 375, 376, 377, 0, 378, 379, 380, 381, + 382, 383, 384, 385, 386, 387, 0, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 0, 0, 421, 422, 423, 424, 425, 426, 427, + 428, 429, 0, 0, 431, 432, 433, 434, 0, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, 530, 448, 449, 0, 0, 450, 451, 0, 452, + 0, 454, 455, 456, 457, 458, 0, 459, 460, 461, + 0, 0, 462, 463, 464, 465, 466, 0, 467, 468, + 469, 470, 471, 472, 473, 474, 0, 0, 475, 476, + 477, 0, 478, 479, 480, 481, 0, 482, 483, 484, + 485, 486, 487, 488, 0, 489, 0, 491, 492, 493, + 494, 495, 496, 497, 0, 0, 498, 0, 0, 499, + 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, + 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, + 527, 0, 0, 0, 0, 0, 0, 0, 0, 2712, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, + 119, 120, 121, 122, 123, 124, 125, 0, 126, 127, + 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 130, 131, 0, 132, 133, 134, 0, 136, 137, 138, + 139, 140, 0, 142, 143, 0, 144, 145, 146, 147, + 148, 149, 0, 0, 150, 151, 152, 153, 154, 155, + 156, 0, 157, 158, 159, 160, 161, 0, 0, 0, + 163, 164, 165, 166, 167, 168, 0, 170, 171, 172, + 0, 173, 174, 175, 176, 177, 178, 0, 0, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 0, 195, 0, 196, 197, 198, + 199, 200, 201, 0, 0, 202, 203, 204, 205, 0, + 0, 206, 207, 208, 209, 210, 0, 211, 212, 213, + 0, 214, 215, 216, 0, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 0, 229, 0, + 230, 231, 232, 233, 0, 234, 0, 235, 0, 0, + 0, 238, 239, 528, 0, 242, 0, 243, 0, 244, + 245, 246, 247, 0, 248, 249, 250, 251, 252, 253, + 254, 0, 256, 257, 258, 259, 0, 260, 261, 262, + 263, 264, 265, 266, 0, 267, 0, 269, 270, 271, + 272, 273, 274, 275, 276, 0, 277, 0, 278, 0, + 0, 281, 0, 283, 284, 285, 286, 287, 288, 0, + 0, 289, 0, 291, 0, 0, 293, 294, 295, 296, + 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 0, 324, 325, 326, + 327, 328, 0, 329, 330, 0, 332, 0, 333, 334, + 335, 336, 337, 338, 0, 339, 340, 0, 0, 341, + 342, 343, 0, 0, 344, 345, 346, 0, 348, 0, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 0, 0, 0, 0, 362, 363, 364, 0, + 366, 367, 368, 369, 370, 371, 0, 372, 373, 374, + 375, 376, 377, 0, 378, 379, 380, 381, 382, 383, + 384, 385, 386, 387, 0, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 0, 401, + 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 416, 417, 418, 419, 420, 0, + 0, 421, 422, 423, 424, 425, 426, 427, 428, 429, + 0, 0, 431, 432, 433, 434, 0, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, 530, + 448, 449, 0, 0, 450, 451, 0, 452, 0, 454, + 455, 456, 457, 458, 0, 459, 460, 461, 0, 0, + 462, 463, 464, 465, 466, 0, 467, 468, 469, 470, + 471, 472, 473, 474, 0, 0, 475, 476, 477, 0, + 478, 479, 480, 481, 0, 482, 483, 484, 485, 486, + 487, 488, 0, 489, 0, 491, 492, 493, 494, 495, + 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, + 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, + 512, 513, 514, 515, 516, 517, 518, 519, 970, 1350, + 819, 0, 0, 0, 1050, 0, 0, 2715, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 118, 119, 120, + 121, 122, 123, 124, 125, 0, 126, 127, 128, 0, + 0, 0, 564, 0, 0, 0, 0, 569, 130, 131, + 0, 132, 133, 134, 571, 136, 137, 138, 572, 573, + 574, 575, 576, 0, 144, 145, 146, 147, 148, 149, + 0, 0, 150, 151, 152, 153, 580, 581, 156, 0, + 157, 158, 159, 160, 583, 0, 585, 0, 587, 164, + 165, 166, 167, 168, 588, 170, 171, 172, 0, 173, + 174, 175, 176, 177, 178, 0, 591, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 593, 191, 192, + 594, 194, 0, 195, 0, 196, 197, 198, 199, 200, + 201, 0, 0, 202, 203, 204, 205, 0, 0, 206, + 207, 208, 209, 210, 0, 211, 212, 213, 0, 214, + 215, 216, 0, 217, 218, 219, 220, 604, 222, 223, + 224, 225, 226, 227, 605, 1351, 229, 0, 230, 231, + 608, 233, 0, 234, 0, 235, 611, 0, 613, 238, + 239, 614, 615, 242, 0, 243, 0, 618, 619, 246, + 247, 0, 248, 249, 250, 251, 252, 253, 254, 621, + 256, 257, 258, 259, 0, 260, 261, 262, 263, 264, + 265, 266, 0, 267, 624, 625, 270, 271, 272, 273, + 274, 626, 627, 0, 629, 0, 278, 631, 632, 281, + 633, 283, 284, 285, 286, 287, 288, 0, 0, 289, + 636, 291, 637, 0, 293, 294, 295, 296, 297, 298, + 299, 300, 639, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 640, 641, 642, 325, 326, 327, 643, + 0, 329, 330, 645, 332, 0, 647, 334, 648, 336, + 337, 338, 0, 339, 340, 1352, 0, 341, 342, 343, + 0, 0, 344, 345, 654, 655, 348, 656, 657, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 0, 0, 0, 0, 362, 363, 662, 663, 366, 367, + 664, 369, 370, 371, 0, 372, 373, 374, 375, 376, + 377, 0, 378, 379, 380, 381, 382, 667, 384, 385, + 386, 387, 0, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 0, 401, 402, 670, + 404, 405, 406, 671, 408, 409, 410, 411, 412, 413, + 414, 415, 416, 417, 418, 419, 420, 0, 673, 421, + 422, 423, 424, 425, 426, 674, 428, 429, 0, 676, + 431, 432, 677, 434, 0, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, 679, 448, 680, + 0, 0, 450, 451, 0, 452, 684, 454, 455, 456, + 457, 458, 0, 459, 686, 687, 0, 0, 462, 463, + 690, 465, 691, 1353, 467, 468, 693, 470, 471, 472, + 473, 474, 0, 0, 475, 476, 477, 0, 478, 479, + 480, 481, 0, 482, 483, 484, 485, 486, 698, 699, + 0, 489, 701, 491, 492, 493, 494, 495, 496, 497, + 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, + 504, 706, 707, 708, 709, 710, 711, 712, 713, 714, + 715, 716, 516, 517, 518, 519, 0, 0, 1618, 0, + 0, 1619, 0, 1354, 1355, 1620, 1621, 1622, 1623, 1624, + 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1627, 0, 0, 0, + 0, 2182, 0, 0, 0, 0, 1629, 1618, 0, 0, + 1619, 0, 0, 1630, 1620, 1621, 1622, 1623, 1624, 1625, + 1626, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1627, 0, 0, 0, 0, + 1631, 0, 0, 0, 0, 1629, 1618, 0, 0, 1619, + 0, 0, 1630, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1627, 0, 0, 0, 0, 1631, + 0, 0, 0, 0, 1629, 0, 2183, 0, 0, 0, + 0, 1630, 0, 1618, 0, 0, 1619, 0, 0, 0, + 1620, 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1631, 0, + 0, 1627, 0, 0, 0, 1900, 0, 0, 0, 0, + 0, 1629, 0, 0, 0, 0, 0, 1632, 1630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1633, 0, 0, 0, 0, 1634, + 0, 0, 0, 0, 0, 1631, 1936, 0, 0, 0, + 0, 1937, 0, 0, 0, 0, 1632, 0, 0, 0, + 0, 0, 1635, 1636, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1633, 0, 0, 0, 1637, 1634, 0, + 0, 0, 0, 0, 3523, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1632, 0, 0, 0, 0, + 0, 1635, 1636, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1633, 0, 0, 1638, 1637, 1634, 1639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1635, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1640, 0, 0, 1641, 0, 0, 0, 0, + 1635, 1636, 1632, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1638, 1637, 0, 1639, 0, 1633, + 0, 0, 0, 0, 1634, 0, 0, 0, 0, 0, + 0, 1640, 0, 0, 1641, 0, 0, 0, 0, 1373, + 1374, 0, 0, 0, 0, 0, 0, 1635, 1636, 0, + 0, 0, 0, 1638, 0, 0, 1639, 0, 0, 0, + 0, 0, 1637, 0, 0, 0, 0, 0, 0, 0, + 1640, 0, 0, 1641, 0, 0, 0, 0, 0, 0, + 1375, 1376, 0, 0, 1377, 1378, 0, 0, 0, 0, + 0, 0, 0, 0, 1642, 0, 0, 0, 0, 0, + 1638, 0, 3524, 1639, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1640, 0, 0, + 1641, 0, 0, 0, 0, 0, 0, 0, 1618, 0, + 0, 1619, 0, 1642, 0, 1620, 1621, 1622, 1623, 1624, + 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1627, 2186, 0, 0, + 1379, 1380, 0, 0, 0, 0, 1629, 0, 0, 0, + 0, 0, 1642, 1630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1636, 0, 0, - 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, - 0, 0, 3225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1631, 1643, 0, 0, 1644, 1645, 1646, 0, 1647, 1648, + 1649, 1650, 1651, 1652, 0, 0, 0, 0, 0, 1642, + 0, 0, 0, 0, 1381, 1382, 1383, 1384, 1385, 1386, + 1387, 1388, 0, 0, 1389, 1390, 0, 0, 0, 0, + 1643, 0, 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, + 1650, 1651, 1652, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1373, 1374, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1643, + 0, 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, 1650, + 1651, 1652, 0, 0, 0, 0, 0, 1632, 0, 0, + 0, 0, 0, 0, 0, 0, 1375, 1376, 1391, 1392, + 1377, 1378, 0, 0, 1633, 0, 0, 0, 0, 1634, + 0, 0, 0, 0, 0, 0, 1643, 0, 0, 1644, + 1645, 1646, 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, + 0, 0, 1635, 1636, 0, 0, 0, 0, 0, 1393, + 1394, 0, 1618, 0, 0, 1619, 0, 1637, 0, 1620, + 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1627, 0, 0, 0, 1942, 0, 1379, 1380, 0, 0, + 1629, 0, 0, 0, 0, 1638, 0, 1630, 1639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1640, 0, 0, 1641, 0, 0, 0, 0, + 1618, 0, 0, 1619, 1631, 0, 0, 1620, 1621, 1622, + 1623, 1624, 1625, 1626, 0, 0, 0, 0, 1907, 0, + 0, 0, 0, 0, 1395, 1396, 0, 0, 1627, 0, + 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1629, 0, + 1389, 1390, 0, 0, 0, 1630, 0, 0, 1397, 1398, + 0, 0, 0, 0, 1618, 0, 0, 1619, 0, 0, + 0, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 2002, 0, + 0, 0, 1631, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1627, 0, 0, 0, 1949, 0, 0, 0, + 0, 0, 1629, 0, 1642, 0, 0, 0, 0, 1630, + 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1391, 1392, 0, 0, 1633, 0, + 0, 1618, 0, 1634, 1619, 0, 1631, 0, 1620, 1621, + 1622, 1623, 1624, 1625, 1626, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1635, 1636, 0, 1627, + 0, 0, 0, 0, 0, 1393, 1394, 0, 0, 1629, + 0, 1637, 0, 0, 1947, 0, 1630, 0, 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1633, 0, 0, 0, + 0, 1634, 0, 1631, 0, 0, 0, 0, 0, 1638, + 0, 1643, 1639, 0, 1644, 1645, 1646, 0, 1647, 1648, + 1649, 1650, 1651, 1652, 1635, 1636, 1640, 0, 0, 1641, + 0, 0, 0, 1632, 0, 0, 0, 0, 0, 1637, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 555, 0, 0, 1636, - 0, 0, 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, - 1644, 1645, 0, 0, 3399, 117, 118, 119, 120, 121, - 122, 123, 124, 556, 125, 126, 127, 557, 558, 559, - 560, 561, 562, 563, 564, 565, 129, 130, 566, 131, - 132, 133, 567, 135, 136, 137, 568, 569, 570, 571, - 572, 573, 143, 144, 145, 146, 147, 148, 574, 575, - 149, 150, 151, 152, 576, 577, 155, 578, 156, 157, - 158, 159, 579, 580, 581, 582, 583, 163, 164, 165, - 166, 167, 584, 169, 170, 171, 585, 172, 173, 174, - 175, 176, 177, 586, 587, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 589, 190, 191, 590, 193, - 591, 194, 592, 195, 196, 197, 198, 199, 200, 593, - 594, 201, 202, 203, 204, 595, 596, 205, 206, 207, - 208, 209, 597, 210, 211, 212, 598, 213, 214, 215, - 599, 216, 217, 218, 219, 600, 221, 222, 223, 224, - 225, 601, 602, 227, 603, 228, 229, 604, 231, 605, - 232, 606, 233, 607, 608, 609, 236, 237, 610, 611, - 240, 612, 241, 613, 614, 615, 244, 245, 616, 246, - 247, 248, 249, 250, 251, 252, 617, 254, 255, 256, - 257, 618, 258, 259, 260, 261, 262, 263, 264, 619, - 265, 620, 621, 268, 269, 270, 271, 272, 622, 623, - 624, 625, 626, 276, 627, 628, 279, 629, 281, 282, - 283, 284, 285, 286, 630, 631, 287, 632, 289, 633, - 634, 291, 292, 293, 294, 295, 296, 297, 298, 635, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 636, 637, 638, 323, 324, 325, 639, 640, 327, 328, - 641, 330, 642, 643, 332, 644, 334, 335, 336, 645, - 337, 338, 646, 647, 339, 340, 341, 648, 649, 342, - 343, 650, 651, 346, 652, 653, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 654, 655, 656, - 657, 360, 361, 658, 659, 364, 365, 660, 367, 368, - 369, 661, 370, 371, 372, 373, 374, 375, 662, 376, - 377, 378, 663, 380, 381, 382, 383, 664, 384, 385, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 665, 397, 398, 666, 400, 401, 402, 667, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 668, 669, 417, 418, 419, 420, 421, 422, - 670, 424, 425, 671, 672, 427, 428, 673, 430, 674, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 675, 444, 676, 677, 678, 446, 447, 679, - 448, 680, 450, 451, 452, 453, 454, 681, 455, 682, - 683, 684, 685, 458, 459, 686, 461, 687, 688, 463, - 464, 689, 466, 467, 468, 469, 470, 690, 691, 471, - 472, 473, 692, 474, 475, 476, 477, 693, 478, 479, - 480, 481, 482, 694, 695, 696, 485, 697, 487, 488, - 489, 490, 491, 492, 493, 698, 699, 494, 700, 701, - 495, 496, 497, 498, 499, 500, 702, 703, 704, 705, - 706, 707, 708, 709, 710, 711, 712, 512, 513, 514, - 515, 523, 0, 0, 0, 0, 0, 0, 0, 0, - 2069, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 117, 118, 119, 120, 121, 122, 123, 124, 0, 125, - 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 129, 130, 0, 131, 132, 133, 0, 135, 136, - 137, 138, 139, 0, 141, 142, 0, 143, 144, 145, - 146, 147, 148, 0, 0, 149, 150, 151, 152, 153, - 154, 155, 0, 156, 157, 158, 159, 160, 0, 0, - 0, 162, 163, 164, 165, 166, 167, 0, 169, 170, - 171, 0, 172, 173, 174, 175, 176, 177, 0, 0, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 0, 194, 0, 195, 196, - 197, 198, 199, 200, 0, 0, 201, 202, 203, 204, - 0, 0, 205, 206, 207, 208, 209, 0, 210, 211, - 212, 0, 213, 214, 215, 0, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 0, 227, 0, - 228, 229, 230, 231, 0, 232, 0, 233, 0, 0, - 0, 236, 237, 524, 0, 240, 0, 241, 0, 242, - 243, 244, 245, 0, 246, 247, 248, 249, 250, 251, - 252, 0, 254, 255, 256, 257, 0, 258, 259, 260, - 261, 262, 263, 264, 0, 265, 0, 267, 268, 269, - 270, 271, 272, 273, 274, 0, 275, 0, 276, 0, - 0, 279, 0, 281, 282, 283, 284, 285, 286, 0, - 0, 287, 0, 289, 0, 0, 291, 292, 293, 294, - 295, 296, 297, 298, 525, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 0, 322, 323, 324, - 325, 326, 0, 327, 328, 0, 330, 0, 331, 332, - 333, 334, 335, 336, 0, 337, 338, 0, 0, 339, - 340, 341, 0, 0, 342, 343, 344, 0, 346, 0, - 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 0, 0, 0, 0, 360, 361, 362, 0, - 364, 365, 366, 367, 368, 369, 0, 370, 371, 372, - 373, 374, 375, 0, 376, 377, 378, 379, 380, 381, - 382, 383, 0, 384, 385, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, 396, 0, 397, 398, 0, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 411, 412, 413, 414, 415, 416, 0, 0, 417, - 418, 419, 420, 421, 422, 423, 424, 425, 0, 0, - 427, 428, 429, 430, 0, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 526, 444, 445, - 0, 0, 446, 447, 0, 448, 0, 450, 451, 452, - 453, 454, 0, 455, 456, 457, 0, 0, 458, 459, - 460, 461, 462, 0, 463, 464, 465, 466, 467, 468, - 469, 470, 0, 0, 471, 472, 473, 0, 474, 475, - 476, 477, 0, 478, 479, 480, 481, 482, 483, 484, - 0, 485, 0, 487, 488, 489, 490, 491, 492, 493, - 0, 0, 494, 0, 0, 495, 496, 497, 498, 499, - 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, - 510, 511, 512, 513, 514, 515, 523, 0, 0, 0, - 0, 0, 0, 0, 0, 2695, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 117, 118, 119, 120, 121, - 122, 123, 124, 0, 125, 126, 127, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 129, 130, 0, 131, - 132, 133, 0, 135, 136, 137, 138, 139, 0, 141, - 142, 0, 143, 144, 145, 146, 147, 148, 0, 0, - 149, 150, 151, 152, 153, 154, 155, 0, 156, 157, - 158, 159, 160, 0, 0, 0, 162, 163, 164, 165, - 166, 167, 0, 169, 170, 171, 0, 172, 173, 174, - 175, 176, 177, 0, 0, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 0, 194, 0, 195, 196, 197, 198, 199, 200, 0, - 0, 201, 202, 203, 204, 0, 0, 205, 206, 207, - 208, 209, 0, 210, 211, 212, 0, 213, 214, 215, - 0, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 0, 227, 0, 228, 229, 230, 231, 0, - 232, 0, 233, 0, 0, 0, 236, 237, 524, 0, - 240, 0, 241, 0, 242, 243, 244, 245, 0, 246, - 247, 248, 249, 250, 251, 252, 0, 254, 255, 256, - 257, 0, 258, 259, 260, 261, 262, 263, 264, 0, - 265, 0, 267, 268, 269, 270, 271, 272, 273, 274, - 0, 275, 0, 276, 0, 0, 279, 0, 281, 282, - 283, 284, 285, 286, 0, 0, 287, 0, 289, 0, - 0, 291, 292, 293, 294, 295, 296, 297, 298, 525, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 0, 322, 323, 324, 325, 326, 0, 327, 328, - 0, 330, 0, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 0, 0, 339, 340, 341, 0, 0, 342, - 343, 344, 0, 346, 0, 348, 349, 350, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 0, 0, 0, - 0, 360, 361, 362, 0, 364, 365, 366, 367, 368, - 369, 0, 370, 371, 372, 373, 374, 375, 0, 376, - 377, 378, 379, 380, 381, 382, 383, 0, 384, 385, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 0, 397, 398, 0, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 0, 0, 417, 418, 419, 420, 421, 422, - 423, 424, 425, 0, 0, 427, 428, 429, 430, 0, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 526, 444, 445, 0, 0, 446, 447, 0, - 448, 0, 450, 451, 452, 453, 454, 0, 455, 456, - 457, 0, 0, 458, 459, 460, 461, 462, 0, 463, - 464, 465, 466, 467, 468, 469, 470, 0, 0, 471, - 472, 473, 0, 474, 475, 476, 477, 0, 478, 479, - 480, 481, 482, 483, 484, 0, 485, 0, 487, 488, - 489, 490, 491, 492, 493, 0, 0, 494, 0, 0, - 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, - 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, - 515, 964, 1341, 815, 0, 0, 0, 1046, 0, 0, - 2698, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 117, 118, 119, 120, 121, 122, 123, 124, 0, 125, - 126, 127, 0, 0, 0, 560, 0, 0, 0, 0, - 565, 129, 130, 0, 131, 132, 133, 567, 135, 136, - 137, 568, 569, 570, 571, 572, 0, 143, 144, 145, - 146, 147, 148, 0, 0, 149, 150, 151, 152, 576, - 577, 155, 0, 156, 157, 158, 159, 579, 0, 581, - 0, 583, 163, 164, 165, 166, 167, 584, 169, 170, - 171, 0, 172, 173, 174, 175, 176, 177, 0, 587, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 589, 190, 191, 590, 193, 0, 194, 0, 195, 196, - 197, 198, 199, 200, 0, 0, 201, 202, 203, 204, - 0, 0, 205, 206, 207, 208, 209, 0, 210, 211, - 212, 0, 213, 214, 215, 0, 216, 217, 218, 219, - 600, 221, 222, 223, 224, 225, 601, 1342, 227, 0, - 228, 229, 604, 231, 0, 232, 0, 233, 607, 0, - 609, 236, 237, 610, 611, 240, 0, 241, 0, 614, - 615, 244, 245, 0, 246, 247, 248, 249, 250, 251, - 252, 617, 254, 255, 256, 257, 0, 258, 259, 260, - 261, 262, 263, 264, 0, 265, 620, 621, 268, 269, - 270, 271, 272, 622, 623, 0, 625, 0, 276, 627, - 628, 279, 629, 281, 282, 283, 284, 285, 286, 0, - 0, 287, 632, 289, 633, 0, 291, 292, 293, 294, - 295, 296, 297, 298, 635, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 636, 637, 638, 323, 324, - 325, 639, 0, 327, 328, 641, 330, 0, 643, 332, - 644, 334, 335, 336, 0, 337, 338, 1343, 0, 339, - 340, 341, 0, 0, 342, 343, 650, 651, 346, 652, - 653, 349, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 0, 0, 0, 0, 360, 361, 658, 659, - 364, 365, 660, 367, 368, 369, 0, 370, 371, 372, - 373, 374, 375, 0, 376, 377, 378, 663, 380, 381, - 382, 383, 0, 384, 385, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, 396, 0, 397, 398, 666, - 400, 401, 402, 667, 404, 405, 406, 407, 408, 409, - 410, 411, 412, 413, 414, 415, 416, 0, 669, 417, - 418, 419, 420, 421, 422, 670, 424, 425, 0, 672, - 427, 428, 673, 430, 0, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 675, 444, 676, - 0, 0, 446, 447, 0, 448, 680, 450, 451, 452, - 453, 454, 0, 455, 682, 683, 0, 0, 458, 459, - 686, 461, 687, 1344, 463, 464, 689, 466, 467, 468, - 469, 470, 0, 0, 471, 472, 473, 0, 474, 475, - 476, 477, 0, 478, 479, 480, 481, 482, 694, 695, - 0, 485, 697, 487, 488, 489, 490, 491, 492, 493, - 0, 0, 494, 0, 0, 495, 496, 497, 498, 499, - 500, 702, 703, 704, 705, 706, 707, 708, 709, 710, - 711, 712, 512, 513, 514, 515, 0, 0, 1611, 0, - 0, 1612, 0, 1345, 1346, 1613, 1614, 1615, 1616, 1617, - 1618, 1619, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1620, 0, 0, 0, - 0, 2167, 0, 0, 0, 0, 1622, 1611, 0, 0, - 1612, 0, 0, 1623, 1613, 1614, 1615, 1616, 1617, 1618, - 1619, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1620, 0, 0, 0, 0, - 1624, 0, 0, 0, 0, 1622, 1611, 0, 0, 1612, - 0, 0, 1623, 1613, 1614, 1615, 1616, 1617, 1618, 1619, + 1633, 0, 0, 0, 0, 1634, 0, 0, 0, 0, + 1395, 1396, 0, 1618, 0, 0, 1619, 0, 0, 0, + 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1638, 1635, 1636, + 1639, 0, 0, 0, 1397, 1398, 0, 0, 0, 0, + 2073, 1627, 0, 1637, 1640, 0, 0, 1641, 0, 0, + 1632, 1629, 0, 0, 0, 0, 0, 0, 1630, 0, + 0, 0, 0, 0, 0, 0, 0, 1633, 0, 0, + 0, 0, 1634, 0, 0, 0, 0, 0, 1642, 0, + 1618, 1638, 0, 1619, 1639, 1631, 0, 1620, 1621, 1622, + 1623, 1624, 1625, 1626, 0, 1635, 1636, 0, 1640, 0, + 0, 1641, 0, 0, 0, 0, 0, 0, 1627, 0, + 1637, 0, 2790, 0, 0, 0, 0, 0, 1629, 0, + 0, 0, 0, 0, 0, 1630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1620, 0, 0, 0, 0, 1624, - 0, 0, 0, 0, 1622, 0, 2168, 0, 0, 0, - 0, 1623, 0, 0, 1611, 0, 0, 1612, 0, 0, - 0, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1624, 0, - 0, 0, 1620, 0, 0, 0, 1890, 0, 0, 0, - 0, 0, 1622, 0, 1611, 0, 1625, 1612, 0, 1623, - 0, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, 0, - 0, 0, 0, 1626, 0, 0, 0, 0, 1627, 0, - 0, 0, 1620, 0, 0, 1926, 1624, 0, 0, 0, - 1927, 0, 1622, 0, 0, 1625, 0, 0, 0, 1623, - 0, 1628, 1629, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1626, 0, 0, 0, 1630, 1627, 0, 0, - 0, 0, 0, 3505, 0, 0, 1624, 0, 0, 0, - 0, 0, 0, 0, 1625, 0, 0, 0, 0, 0, - 1628, 1629, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1626, 0, 0, 1631, 1630, 1627, 1632, 0, 0, + 0, 0, 0, 0, 0, 0, 1642, 0, 1638, 0, + 0, 1639, 1631, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1640, 0, 0, 1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1633, 0, 0, 1634, 0, 0, 0, 0, 1628, - 1629, 0, 1625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1631, 1630, 0, 1632, 0, 0, 1626, - 0, 0, 0, 0, 1627, 0, 0, 0, 0, 0, - 1633, 0, 0, 1634, 0, 0, 0, 0, 0, 0, - 0, 0, 1625, 0, 0, 0, 0, 1628, 1629, 0, - 0, 0, 1631, 0, 0, 1632, 0, 0, 0, 1626, - 0, 0, 1630, 0, 1627, 0, 0, 0, 0, 1633, - 0, 0, 1634, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1628, 1629, 0, - 0, 1635, 0, 0, 0, 0, 0, 0, 0, 0, - 1631, 3506, 1630, 1632, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1633, 0, 0, - 1634, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1635, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1631, 0, 0, 1632, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2171, 0, 0, 1633, 0, 0, - 1634, 0, 0, 0, 0, 0, 0, 0, 0, 1635, + 0, 0, 1632, 0, 0, 1643, 0, 0, 1644, 1645, + 1646, 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, 1633, + 1642, 0, 1618, 0, 1634, 1619, 0, 0, 0, 1620, + 1621, 1622, 1623, 1624, 1625, 1626, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1635, 1636, 0, + 1627, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1629, 0, 1637, 0, 0, 0, 0, 1630, 0, 1632, + 0, 0, 0, 1643, 0, 0, 1644, 1645, 1646, 0, + 1647, 1648, 1649, 1650, 1651, 1652, 1633, 1642, 0, 0, + 0, 1634, 0, 0, 1631, 0, 0, 0, 0, 0, + 1638, 0, 0, 1639, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1635, 1636, 0, 1640, 0, 0, + 1641, 0, 0, 0, 0, 0, 0, 1643, 0, 1637, + 1644, 1645, 1646, 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1897, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1636, 0, - 0, 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, 1644, - 1645, 0, 0, 0, 0, 0, 0, 1635, 0, 0, - 0, 0, 1611, 0, 0, 1612, 0, 0, 0, 1613, - 1614, 1615, 1616, 1617, 1618, 1619, 0, 1636, 0, 0, - 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, - 1620, 0, 0, 0, 1932, 0, 0, 1635, 0, 0, - 1622, 0, 0, 0, 0, 0, 0, 1623, 0, 0, - 0, 0, 0, 0, 0, 0, 1636, 0, 0, 1637, - 1638, 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, 0, - 0, 0, 0, 0, 1624, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1611, - 0, 0, 1612, 0, 0, 0, 1613, 1614, 1615, 1616, - 1617, 1618, 1619, 0, 1636, 0, 0, 1637, 1638, 1639, - 0, 1640, 1641, 1642, 1643, 1644, 1645, 1620, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1622, 0, 0, - 0, 0, 0, 0, 1623, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1636, 0, 0, 1637, 1638, 1639, - 0, 1640, 1641, 1642, 1643, 1644, 1645, 0, 0, 0, - 0, 1624, 0, 0, 0, 0, 1611, 0, 0, 1612, - 1625, 0, 0, 1613, 1614, 1615, 1616, 1617, 1618, 1619, - 0, 0, 0, 0, 0, 0, 0, 1626, 0, 0, - 0, 0, 1627, 0, 1620, 0, 0, 0, 1939, 0, - 0, 0, 0, 0, 1622, 0, 0, 0, 0, 0, - 0, 1623, 0, 0, 0, 1628, 1629, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1630, 0, 0, 0, 0, 0, 0, 0, 1624, 0, + 0, 0, 0, 0, 0, 0, 0, 1638, 0, 0, + 1639, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1640, 0, 0, 1641, 0, 0, + 0, 1632, 0, 0, 1643, 0, 0, 1644, 1645, 1646, + 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, 1633, 0, + 0, 0, 0, 1634, 0, 0, 0, 0, 0, 1642, + 0, 1618, 0, 0, 1619, 0, 0, 0, 1620, 1621, + 1622, 1623, 1624, 1625, 1626, 0, 1635, 1636, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1627, + 0, 1637, 2776, 0, 0, 0, 0, 0, 0, 1629, + 0, 0, 0, 0, 0, 0, 1630, 0, 0, 1618, + 0, 0, 1619, 0, 0, 0, 1620, 1621, 1622, 1623, + 1624, 1625, 1626, 0, 0, 0, 1642, 1618, 0, 1638, + 1619, 0, 1639, 1631, 1620, 1621, 0, 1627, 1624, 1625, + 1626, 0, 0, 0, 0, 0, 1640, 1629, 0, 1641, + 0, 0, 0, 0, 1630, 1627, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1629, 1643, 0, 0, 1644, + 1645, 1646, 1630, 1647, 1648, 1649, 1650, 1651, 1652, 0, + 0, 1631, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1937, 1611, 0, 0, 1612, 1625, 0, 0, - 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, 1631, 0, - 0, 1632, 0, 0, 1626, 0, 0, 0, 0, 1627, - 0, 1620, 0, 0, 0, 1633, 0, 0, 1634, 0, - 0, 1622, 0, 0, 0, 0, 0, 0, 1623, 0, - 0, 0, 1628, 1629, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1630, 0, 0, - 0, 0, 0, 0, 0, 1624, 0, 0, 0, 0, - 0, 0, 0, 0, 1625, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1626, 0, 0, 0, 1631, 1627, 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1633, 0, 0, 1634, 0, 0, 0, 1628, - 1629, 0, 0, 0, 0, 1635, 0, 0, 1611, 0, - 0, 1612, 0, 0, 1630, 1613, 1614, 1615, 1616, 1617, - 1618, 1619, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2062, 0, 0, 0, 0, 1620, 0, 0, 0, - 0, 1625, 0, 0, 0, 0, 1622, 0, 0, 0, - 0, 0, 1631, 1623, 0, 1632, 0, 0, 1626, 0, - 0, 0, 0, 1627, 0, 0, 0, 0, 0, 1633, + 1632, 0, 0, 1643, 0, 0, 1644, 1645, 1646, 0, + 1647, 1648, 1649, 1650, 1651, 1652, 0, 1633, 1642, 0, 0, 0, 1634, 0, 0, 0, 0, 0, 0, 0, - 1624, 0, 0, 0, 0, 0, 1628, 1629, 0, 0, - 0, 0, 1635, 0, 0, 0, 0, 0, 0, 0, - 0, 1630, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1636, 0, 0, 1637, 1638, 1639, 0, 1640, - 1641, 1642, 1643, 1644, 1645, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1631, - 0, 0, 1632, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1633, 0, 0, 1634, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1635, - 0, 0, 0, 0, 0, 0, 1625, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1626, 0, 0, 0, 0, 1627, 1636, - 0, 0, 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, - 1644, 1645, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1628, 1629, 0, 0, 0, 0, 0, 0, 0, - 1611, 0, 0, 1612, 0, 0, 1630, 1613, 1614, 1615, - 1616, 1617, 1618, 1619, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1635, 0, 1620, 0, - 0, 0, 2772, 0, 0, 0, 0, 0, 1622, 0, - 0, 0, 0, 0, 1631, 1623, 1636, 1632, 0, 1637, - 1638, 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, 0, - 0, 1633, 0, 0, 1634, 0, 0, 0, 0, 0, - 0, 0, 1624, 0, 1611, 0, 0, 1612, 0, 0, - 0, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, 0, + 0, 0, 0, 0, 0, 1817, 1636, 0, 1632, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1620, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1622, 0, 0, 0, 0, 0, 0, 1623, + 1637, 0, 0, 0, 0, 1633, 1632, 0, 0, 0, + 1634, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1633, 0, 0, 0, 0, 1634, 0, + 0, 0, 0, 1635, 1636, 0, 0, 0, 1638, 0, + 0, 1639, 0, 0, 0, 0, 0, 0, 1637, 0, + 0, 1635, 1636, 0, 0, 1640, 0, 0, 1641, 0, + 0, 0, 0, 0, 0, 1643, 1637, 0, 1644, 1645, + 1646, 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, + 0, 0, 0, 0, 0, 0, 1638, 0, 0, 1639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1636, 0, 0, 1637, 1638, 1639, 0, - 1640, 1641, 1642, 1643, 1644, 1645, 1624, 0, 0, 0, + 0, 0, 0, 1640, 1638, 0, 1641, 1639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1635, 0, 1611, 0, 0, 1612, 0, 1625, 0, - 1613, 1614, 1615, 1616, 1617, 1618, 1619, 0, 0, 0, - 0, 0, 0, 0, 0, 1626, 0, 0, 0, 0, - 1627, 1620, 0, 0, 2759, 0, 0, 0, 0, 0, - 0, 1622, 0, 0, 0, 0, 0, 0, 1623, 0, - 0, 0, 0, 1628, 1629, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1630, 0, - 0, 0, 0, 0, 0, 1624, 0, 0, 0, 0, - 0, 0, 1625, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1626, - 0, 0, 0, 0, 1627, 0, 1631, 0, 1636, 1632, - 0, 1637, 1638, 1639, 0, 1640, 1641, 1642, 1643, 1644, - 1645, 0, 0, 1633, 0, 0, 1634, 1628, 1629, 0, - 0, 0, 0, 0, 0, 0, 1611, 0, 0, 1612, - 0, 0, 1630, 1613, 1614, 1615, 1616, 1617, 1618, 1619, + 0, 1640, 0, 0, 1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1620, 0, 0, 0, 0, 0, - 0, 1625, 0, 0, 1622, 0, 0, 0, 0, 0, - 1631, 1623, 0, 1632, 0, 0, 0, 0, 1626, 0, - 0, 0, 0, 1627, 0, 0, 0, 1633, 0, 0, - 1634, 0, 0, 0, 0, 0, 0, 0, 1624, 0, - 0, 0, 0, 0, 0, 0, 1806, 1629, 0, 0, - 0, 0, 0, 1635, 0, 0, 0, 0, 0, 0, - 0, 1630, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1611, 0, 0, 1612, 0, 0, 0, 1613, - 1614, 0, 0, 1617, 1618, 1619, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1631, - 1620, 0, 1632, 0, 0, 0, 0, 0, 0, 0, - 1622, 0, 0, 0, 0, 0, 1633, 1623, 0, 1634, - 0, 0, 0, 0, 0, 0, 0, 1635, 0, 0, - 0, 0, 0, 0, 1625, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1624, 0, 0, 0, 0, 0, - 0, 1626, 0, 0, 0, 0, 1627, 0, 0, 0, - 1636, 0, 0, 1637, 1638, 1639, 0, 1640, 1641, 1642, - 1643, 1644, 1645, 0, 0, 1611, 0, 0, 1612, 1628, - 1629, 0, 1613, 1614, 0, 0, 1617, 1618, 1619, 0, - 0, 0, 0, 0, 1630, 0, 0, 0, 0, 0, - 0, 0, 0, 1620, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1622, 0, 1611, 1635, 0, 1612, 0, - 1623, 0, 1613, 1614, 0, 0, 1617, 1618, 1619, 0, - 0, 0, 1631, 0, 1636, 1632, 0, 1637, 1638, 1639, - 1625, 1640, 1641, 1642, 1643, 1644, 1645, 1624, 0, 1633, - 0, 0, 1634, 1622, 0, 0, 0, 1626, 0, 0, - 1623, 0, 1627, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1628, 1629, 1624, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1636, 0, 0, 1637, 1638, 1639, 0, - 1640, 1641, 1642, 1643, 1644, 1645, 0, 0, 1631, 0, - 0, 1632, 0, 1625, 0, 0, 0, 0, 0, 1635, - 0, 0, 0, 0, 0, 1633, 0, 0, 1634, 0, - 1626, 0, 0, 0, 0, 1627, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1625, 0, 0, 0, 0, 1628, 1629, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1626, 0, 0, 1630, 0, 1627, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1628, 1629, + 0, 0, 0, 1642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1631, 0, 1630, 1632, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1635, 1636, 0, 1633, 1637, - 1638, 1639, 0, 1640, 1641, 1642, 1643, 2188, 1645, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1631, 0, 0, 1632, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1633, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1643, 0, 0, 1644, 1645, 1646, + 0, 1647, 1648, 1649, 1650, 1651, 1652, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1643, 0, 0, 1644, 1645, 1646, 0, 1647, + 1648, 1649, 1650, 2203, 1652, 559, 0, 2096, 0, 0, + 1643, 0, 0, 1644, 1645, 1646, 0, 1647, 1648, 1649, + 1650, 1651, 1652, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 560, 126, 127, 128, 561, 562, 563, 564, + 565, 566, 567, 568, 569, 130, 131, 570, 132, 133, + 134, 571, 136, 137, 138, 572, 573, 574, 575, 576, + 577, 144, 145, 146, 147, 148, 149, 578, 579, 150, + 151, 152, 153, 580, 581, 156, 582, 157, 158, 159, + 160, 583, 584, 585, 586, 587, 164, 165, 166, 167, + 168, 588, 170, 171, 172, 589, 173, 174, 175, 176, + 177, 178, 590, 591, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 593, 191, 192, 594, 194, 595, + 195, 596, 196, 197, 198, 199, 200, 201, 597, 598, + 202, 203, 204, 205, 599, 600, 206, 207, 208, 209, + 210, 601, 211, 212, 213, 602, 214, 215, 216, 603, + 217, 218, 219, 220, 604, 222, 223, 224, 225, 226, + 227, 605, 606, 229, 607, 230, 231, 608, 233, 609, + 234, 610, 235, 611, 612, 613, 238, 239, 614, 615, + 242, 616, 243, 617, 618, 619, 246, 247, 620, 248, + 249, 250, 251, 252, 253, 254, 621, 256, 257, 258, + 259, 622, 260, 261, 262, 263, 264, 265, 266, 623, + 267, 624, 625, 270, 271, 272, 273, 274, 626, 627, + 628, 629, 630, 278, 631, 632, 281, 633, 283, 284, + 285, 286, 287, 288, 634, 635, 289, 636, 291, 637, + 638, 293, 294, 295, 296, 297, 298, 299, 300, 639, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 640, 641, 642, 325, 326, 327, 643, 644, 329, 330, + 645, 332, 646, 647, 334, 648, 336, 337, 338, 649, + 339, 340, 650, 651, 341, 342, 343, 652, 653, 344, + 345, 654, 655, 348, 656, 657, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 658, 659, 660, + 661, 362, 363, 662, 663, 366, 367, 664, 369, 370, + 371, 665, 372, 373, 374, 375, 376, 377, 666, 378, + 379, 380, 381, 382, 667, 384, 385, 386, 387, 668, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 669, 401, 402, 670, 404, 405, 406, + 671, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 672, 673, 421, 422, 423, 424, + 425, 426, 674, 428, 429, 675, 676, 431, 432, 677, + 434, 678, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 679, 448, 680, 681, 682, 450, + 451, 683, 452, 684, 454, 455, 456, 457, 458, 685, + 459, 686, 687, 688, 689, 462, 463, 690, 465, 691, + 692, 467, 468, 693, 470, 471, 472, 473, 474, 694, + 695, 475, 476, 477, 696, 478, 479, 480, 481, 697, + 482, 483, 484, 485, 486, 698, 699, 700, 489, 701, + 491, 492, 493, 494, 495, 496, 497, 702, 703, 498, + 704, 705, 499, 500, 501, 502, 503, 504, 706, 707, + 708, 709, 710, 711, 712, 713, 714, 715, 716, 516, + 517, 518, 519, 559, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1635, 0, - 0, 0, 1636, 0, 0, 1637, 1638, 1639, 0, 1640, - 1641, 1642, 1643, 1644, 1645, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 560, 126, 127, 128, 561, 562, 563, 564, 565, 566, + 567, 568, 569, 130, 131, 570, 132, 133, 134, 571, + 136, 137, 138, 572, 573, 574, 575, 576, 577, 144, + 145, 146, 147, 148, 149, 578, 579, 150, 151, 152, + 153, 580, 581, 156, 582, 157, 158, 159, 160, 583, + 584, 585, 586, 587, 164, 165, 166, 167, 168, 588, + 170, 171, 172, 589, 173, 174, 175, 176, 177, 178, + 590, 591, 180, 181, 182, 183, 184, 185, 592, 187, + 188, 189, 593, 191, 192, 594, 194, 595, 195, 596, + 196, 197, 198, 199, 200, 201, 597, 598, 202, 203, + 204, 205, 599, 600, 206, 207, 208, 209, 210, 601, + 211, 212, 213, 602, 214, 215, 216, 603, 217, 218, + 219, 220, 604, 222, 223, 224, 225, 226, 227, 605, + 606, 229, 607, 230, 231, 608, 233, 609, 234, 610, + 235, 611, 612, 613, 238, 239, 614, 615, 242, 616, + 243, 617, 618, 619, 246, 247, 620, 248, 249, 250, + 251, 252, 253, 254, 621, 256, 257, 258, 259, 622, + 260, 261, 262, 263, 264, 265, 266, 623, 267, 624, + 625, 270, 271, 272, 273, 274, 626, 627, 628, 629, + 630, 278, 631, 632, 281, 633, 283, 284, 285, 286, + 287, 288, 634, 635, 289, 636, 291, 637, 638, 293, + 294, 295, 296, 297, 298, 299, 300, 639, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 640, 641, + 642, 325, 326, 327, 643, 644, 329, 330, 645, 332, + 646, 647, 334, 648, 336, 337, 338, 649, 339, 340, + 650, 651, 341, 342, 343, 652, 653, 344, 345, 654, + 655, 348, 656, 657, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 658, 659, 660, 661, 362, + 363, 662, 663, 366, 367, 664, 369, 370, 371, 665, + 372, 373, 374, 375, 376, 377, 666, 378, 379, 380, + 381, 382, 667, 384, 385, 386, 387, 668, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 669, 401, 402, 670, 404, 405, 406, 671, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 672, 673, 421, 422, 423, 424, 425, 426, + 674, 428, 429, 675, 676, 431, 432, 677, 434, 678, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 679, 448, 680, 681, 682, 450, 451, 683, + 452, 684, 454, 455, 456, 457, 458, 685, 459, 686, + 687, 688, 689, 462, 463, 690, 465, 691, 692, 467, + 468, 693, 470, 471, 472, 473, 474, 694, 695, 475, + 476, 477, 696, 478, 479, 480, 481, 697, 482, 483, + 484, 485, 486, 698, 699, 700, 489, 701, 491, 492, + 493, 494, 495, 496, 497, 702, 703, 498, 704, 705, + 499, 500, 501, 502, 503, 504, 706, 707, 708, 709, + 710, 711, 712, 713, 714, 715, 716, 516, 517, 518, + 519, 559, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1635, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 560, 126, + 127, 128, 561, 562, 563, 564, 565, 566, 567, 568, + 569, 130, 131, 570, 132, 133, 134, 571, 136, 137, + 138, 572, 573, 574, 575, 576, 577, 144, 145, 146, + 147, 148, 149, 578, 579, 150, 151, 152, 153, 580, + 581, 156, 582, 157, 158, 159, 160, 583, 584, 585, + 586, 587, 164, 165, 166, 167, 168, 588, 170, 171, + 172, 589, 173, 174, 175, 176, 177, 178, 590, 591, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 593, 191, 192, 594, 194, 595, 195, 596, 196, 197, + 198, 199, 200, 201, 597, 598, 202, 203, 204, 205, + 599, 600, 206, 207, 208, 209, 210, 601, 211, 212, + 213, 602, 214, 215, 216, 603, 217, 218, 219, 220, + 604, 222, 223, 224, 225, 226, 227, 605, 606, 229, + 607, 230, 231, 608, 233, 609, 234, 610, 235, 611, + 612, 613, 238, 239, 614, 615, 242, 616, 243, 617, + 618, 619, 246, 247, 620, 248, 249, 250, 251, 252, + 946, 254, 621, 256, 257, 258, 259, 622, 260, 261, + 262, 263, 264, 265, 266, 623, 267, 624, 625, 270, + 271, 272, 273, 274, 626, 627, 628, 629, 630, 278, + 631, 632, 281, 633, 283, 284, 285, 286, 287, 288, + 634, 635, 289, 636, 291, 637, 638, 293, 294, 295, + 296, 297, 298, 299, 300, 639, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 640, 641, 642, 325, + 326, 327, 643, 644, 329, 330, 645, 332, 646, 647, + 334, 648, 336, 337, 338, 649, 339, 340, 650, 651, + 341, 342, 343, 652, 653, 344, 345, 654, 655, 348, + 656, 657, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 658, 659, 660, 661, 362, 363, 662, + 663, 366, 367, 664, 369, 370, 371, 665, 372, 373, + 374, 375, 376, 377, 666, 378, 379, 380, 381, 382, + 667, 384, 385, 386, 387, 668, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 669, + 401, 402, 670, 404, 405, 406, 671, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 672, 673, 421, 422, 423, 424, 425, 426, 674, 428, + 429, 675, 676, 431, 432, 677, 434, 678, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 679, 448, 680, 681, 682, 450, 451, 683, 452, 684, + 454, 455, 456, 457, 458, 685, 459, 686, 687, 688, + 689, 462, 463, 690, 465, 691, 692, 467, 468, 693, + 470, 471, 472, 473, 474, 694, 695, 475, 476, 477, + 696, 478, 479, 480, 481, 697, 482, 483, 484, 485, + 486, 698, 699, 700, 489, 701, 491, 492, 493, 494, + 495, 496, 497, 702, 703, 498, 704, 705, 499, 500, + 501, 502, 503, 504, 706, 707, 708, 709, 710, 711, + 712, 713, 714, 715, 716, 516, 517, 518, 519, 559, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 560, 126, 127, 128, + 561, 562, 563, 564, 565, 566, 567, 568, 569, 130, + 131, 570, 132, 133, 134, 571, 136, 137, 138, 572, + 573, 574, 575, 576, 577, 144, 145, 146, 147, 148, + 149, 578, 579, 150, 151, 152, 153, 580, 581, 156, + 582, 157, 158, 159, 160, 583, 584, 585, 586, 587, + 164, 165, 166, 167, 168, 588, 170, 171, 172, 589, + 173, 174, 175, 176, 177, 178, 590, 591, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 593, 191, + 192, 594, 194, 595, 195, 596, 196, 197, 198, 199, + 200, 201, 597, 598, 202, 203, 204, 205, 599, 600, + 206, 207, 208, 209, 210, 601, 211, 212, 213, 602, + 214, 215, 216, 603, 217, 218, 219, 220, 604, 222, + 223, 224, 225, 226, 227, 605, 606, 229, 607, 230, + 231, 608, 233, 609, 234, 610, 235, 611, 612, 613, + 238, 239, 614, 615, 242, 616, 243, 617, 618, 619, + 246, 247, 620, 248, 249, 250, 251, 252, 253, 254, + 621, 256, 257, 258, 259, 622, 260, 261, 262, 263, + 264, 265, 266, 623, 267, 624, 625, 270, 271, 272, + 273, 274, 626, 627, 628, 629, 630, 278, 631, 632, + 281, 633, 283, 284, 285, 286, 287, 288, 634, 635, + 289, 636, 291, 637, 638, 293, 294, 295, 296, 297, + 298, 299, 300, 639, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 640, 641, 642, 325, 326, 327, + 643, 644, 329, 330, 645, 332, 646, 647, 334, 648, + 336, 337, 338, 649, 339, 340, 650, 651, 341, 342, + 343, 652, 653, 344, 345, 654, 655, 348, 656, 657, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 658, 659, 660, 661, 362, 363, 662, 663, 366, + 367, 664, 369, 370, 371, 665, 372, 373, 374, 375, + 376, 377, 666, 378, 379, 380, 381, 382, 667, 384, + 385, 386, 387, 668, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 669, 401, 402, + 670, 404, 405, 406, 671, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 672, 673, + 421, 422, 423, 424, 425, 426, 674, 428, 429, 675, + 676, 431, 432, 677, 434, 678, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 679, 448, + 680, 681, 682, 450, 451, 683, 452, 684, 454, 455, + 456, 457, 458, 685, 459, 686, 687, 688, 689, 462, + 463, 690, 465, 691, 692, 467, 468, 693, 470, 471, + 472, 473, 474, 694, 695, 475, 476, 477, 696, 478, + 479, 480, 481, 697, 482, 483, 484, 485, 486, 698, + 699, 700, 489, 701, 491, 492, 493, 494, 495, 496, + 497, 702, 703, 498, 704, 705, 499, 500, 501, 502, + 503, 504, 706, 707, 708, 709, 710, 711, 712, 713, + 714, 715, 716, 516, 517, 518, 519, 559, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 2248, 123, 124, 125, 560, 126, 127, 128, 561, 562, + 563, 564, 565, 566, 567, 568, 569, 130, 131, 570, + 132, 133, 134, 571, 136, 137, 138, 572, 573, 574, + 575, 576, 577, 144, 145, 146, 147, 148, 149, 578, + 579, 150, 151, 152, 153, 580, 581, 156, 582, 157, + 158, 159, 160, 583, 584, 585, 586, 587, 164, 165, + 166, 167, 168, 588, 170, 171, 172, 589, 173, 174, + 175, 176, 177, 178, 590, 591, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 593, 191, 192, 594, + 194, 595, 195, 596, 196, 197, 198, 199, 200, 201, + 597, 598, 202, 203, 204, 205, 599, 600, 206, 207, + 208, 2249, 210, 601, 211, 212, 213, 602, 214, 215, + 216, 603, 217, 218, 219, 220, 604, 222, 223, 224, + 225, 226, 227, 605, 606, 229, 607, 230, 231, 608, + 233, 609, 234, 610, 235, 611, 612, 613, 238, 239, + 614, 615, 242, 616, 243, 617, 618, 619, 246, 247, + 620, 248, 249, 250, 251, 252, 253, 254, 621, 256, + 257, 258, 259, 622, 260, 261, 262, 263, 264, 265, + 266, 623, 267, 624, 625, 270, 271, 272, 273, 274, + 626, 627, 628, 629, 630, 278, 631, 632, 281, 633, + 283, 284, 285, 286, 287, 288, 634, 635, 289, 636, + 291, 637, 638, 293, 294, 295, 296, 297, 298, 299, + 300, 639, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 640, 641, 642, 325, 326, 327, 643, 644, + 329, 330, 645, 332, 646, 647, 334, 648, 336, 337, + 338, 649, 339, 340, 650, 651, 341, 342, 343, 652, + 653, 344, 345, 654, 655, 348, 656, 657, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 658, + 659, 660, 661, 362, 363, 662, 663, 366, 367, 664, + 369, 370, 371, 665, 372, 373, 374, 375, 376, 377, + 666, 378, 379, 380, 381, 382, 667, 384, 385, 386, + 387, 668, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 669, 401, 402, 670, 404, + 405, 406, 671, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 672, 673, 421, 422, + 423, 424, 425, 2250, 674, 428, 429, 675, 676, 431, + 432, 677, 434, 678, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 679, 448, 680, 681, + 682, 450, 451, 683, 452, 684, 454, 455, 456, 457, + 458, 685, 459, 686, 687, 688, 689, 462, 463, 690, + 465, 691, 692, 467, 468, 693, 470, 471, 472, 473, + 474, 694, 695, 475, 476, 477, 696, 478, 479, 480, + 481, 697, 482, 483, 484, 485, 486, 698, 699, 700, + 489, 701, 491, 492, 493, 494, 495, 496, 497, 702, + 703, 498, 704, 705, 499, 500, 501, 502, 503, 504, + 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, + 716, 516, 517, 518, 519, 970, 0, 819, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 564, + 0, 0, 0, 0, 569, 130, 131, 0, 132, 133, + 134, 571, 136, 137, 138, 572, 573, 574, 575, 576, + 0, 144, 145, 146, 147, 148, 149, 0, 0, 150, + 151, 152, 153, 580, 581, 156, 0, 157, 158, 159, + 160, 583, 0, 585, 0, 587, 164, 165, 166, 167, + 168, 588, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 591, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 593, 191, 192, 594, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 208, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 604, 222, 223, 224, 225, 226, + 227, 605, 1351, 229, 0, 230, 231, 608, 233, 0, + 234, 0, 235, 611, 0, 613, 238, 239, 614, 615, + 242, 0, 243, 0, 618, 619, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 621, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 624, 625, 270, 271, 272, 273, 274, 626, 627, + 0, 629, 0, 278, 631, 632, 281, 633, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 636, 291, 637, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 639, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 640, 641, 642, 325, 326, 327, 643, 0, 329, 330, + 645, 332, 0, 647, 334, 648, 336, 337, 338, 0, + 339, 340, 1352, 0, 341, 342, 343, 0, 0, 344, + 345, 654, 655, 348, 656, 657, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 662, 663, 366, 367, 664, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 667, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 670, 404, 405, 406, + 671, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 0, 673, 421, 422, 423, 424, + 425, 426, 674, 428, 429, 0, 676, 431, 432, 677, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 679, 448, 680, 0, 0, 450, + 451, 0, 452, 684, 454, 455, 456, 457, 458, 0, + 459, 686, 687, 0, 0, 462, 463, 690, 465, 691, + 1353, 467, 468, 693, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 698, 699, 0, 489, 701, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 706, 707, + 708, 709, 710, 711, 712, 713, 714, 715, 716, 516, + 517, 518, 519, 970, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 3, 4, 0, 564, 0, 0, + 0, 0, 569, 130, 131, 0, 132, 133, 134, 571, + 136, 137, 138, 572, 573, 574, 575, 576, 0, 144, + 145, 146, 147, 148, 149, 0, 0, 150, 151, 152, + 153, 580, 581, 156, 0, 157, 158, 159, 160, 583, + 0, 585, 0, 587, 164, 165, 166, 167, 168, 588, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 591, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 593, 191, 192, 594, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 208, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 604, 222, 223, 224, 225, 226, 227, 605, + 0, 229, 0, 230, 231, 608, 233, 0, 234, 0, + 235, 611, 0, 613, 238, 239, 614, 615, 242, 0, + 243, 0, 618, 619, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 621, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 624, + 625, 270, 271, 272, 273, 274, 626, 627, 0, 629, + 0, 278, 631, 632, 281, 633, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 636, 291, 637, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 639, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 640, 641, + 642, 325, 326, 327, 643, 0, 329, 330, 645, 332, + 0, 647, 334, 648, 336, 337, 338, 0, 339, 340, + 0, 0, 341, 342, 343, 0, 0, 344, 345, 654, + 655, 348, 656, 657, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 662, 663, 366, 367, 664, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 667, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 670, 404, 405, 406, 671, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 673, 421, 422, 423, 424, 425, 426, + 674, 428, 429, 0, 676, 431, 432, 677, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 679, 448, 680, 0, 0, 450, 451, 0, + 452, 684, 454, 455, 456, 457, 458, 0, 459, 686, + 687, 0, 0, 462, 463, 690, 465, 691, 0, 467, + 468, 693, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 698, 699, 0, 489, 701, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 706, 707, 708, 709, + 710, 711, 712, 713, 714, 715, 716, 516, 517, 518, + 519, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 129, 130, 131, 0, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 0, 144, 145, 146, + 147, 148, 149, 0, 789, 150, 151, 152, 153, 154, + 155, 156, 0, 157, 158, 159, 160, 790, 0, 791, + 0, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 792, 0, 229, + 0, 230, 231, 232, 233, 0, 234, 0, 235, 236, + 0, 237, 238, 239, 240, 241, 242, 0, 243, 0, + 244, 245, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 268, 269, 270, + 271, 272, 273, 274, 275, 276, 0, 277, 0, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 290, 291, 292, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, 0, 329, 330, 331, 332, 0, 794, + 334, 335, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 346, 347, 348, + 349, 796, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 797, + 365, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 383, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 430, 431, 432, 433, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 447, 448, 799, 0, 0, 450, 451, 0, 452, 453, + 454, 455, 456, 457, 458, 0, 459, 460, 461, 0, + 0, 462, 463, 800, 465, 801, 0, 467, 468, 802, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 488, 0, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1636, 0, 0, 1637, 1638, - 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 129, 130, + 131, 0, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 0, 144, 145, 146, 147, 148, + 149, 0, 0, 150, 151, 152, 153, 154, 155, 156, + 0, 157, 158, 159, 160, 161, 0, 162, 0, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 0, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 0, 229, 0, 230, + 231, 232, 233, 0, 234, 0, 235, 236, 0, 237, + 238, 239, 240, 241, 242, 0, 243, 0, 244, 245, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 268, 269, 270, 271, 272, + 273, 274, 275, 276, 0, 277, 0, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 290, 291, 292, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, 0, 329, 330, 331, 332, 0, 333, 334, 335, + 336, 337, 338, 0, 339, 340, 0, 0, 341, 342, + 343, 0, 0, 344, 345, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 364, 365, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 430, 431, 432, 433, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, + 449, 0, 0, 450, 451, 0, 452, 453, 454, 455, + 456, 457, 458, 0, 459, 460, 461, 0, 0, 462, + 463, 464, 465, 466, 0, 467, 468, 469, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 488, 0, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 555, - 0, 2085, 0, 0, 0, 1636, 0, 0, 1637, 1638, - 1639, 0, 1640, 1641, 1642, 1643, 1644, 1645, 117, 118, - 119, 120, 121, 122, 123, 124, 556, 125, 126, 127, - 557, 558, 559, 560, 561, 562, 563, 564, 565, 129, - 130, 566, 131, 132, 133, 567, 135, 136, 137, 568, - 569, 570, 571, 572, 573, 143, 144, 145, 146, 147, - 148, 574, 575, 149, 150, 151, 152, 576, 577, 155, - 578, 156, 157, 158, 159, 579, 580, 581, 582, 583, - 163, 164, 165, 166, 167, 584, 169, 170, 171, 585, - 172, 173, 174, 175, 176, 177, 586, 587, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 589, 190, - 191, 590, 193, 591, 194, 592, 195, 196, 197, 198, - 199, 200, 593, 594, 201, 202, 203, 204, 595, 596, - 205, 206, 207, 208, 209, 597, 210, 211, 212, 598, - 213, 214, 215, 599, 216, 217, 218, 219, 600, 221, - 222, 223, 224, 225, 601, 602, 227, 603, 228, 229, - 604, 231, 605, 232, 606, 233, 607, 608, 609, 236, - 237, 610, 611, 240, 612, 241, 613, 614, 615, 244, - 245, 616, 246, 247, 248, 249, 250, 251, 252, 617, - 254, 255, 256, 257, 618, 258, 259, 260, 261, 262, - 263, 264, 619, 265, 620, 621, 268, 269, 270, 271, - 272, 622, 623, 624, 625, 626, 276, 627, 628, 279, - 629, 281, 282, 283, 284, 285, 286, 630, 631, 287, - 632, 289, 633, 634, 291, 292, 293, 294, 295, 296, - 297, 298, 635, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 636, 637, 638, 323, 324, 325, 639, - 640, 327, 328, 641, 330, 642, 643, 332, 644, 334, - 335, 336, 645, 337, 338, 646, 647, 339, 340, 341, - 648, 649, 342, 343, 650, 651, 346, 652, 653, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 654, 655, 656, 657, 360, 361, 658, 659, 364, 365, - 660, 367, 368, 369, 661, 370, 371, 372, 373, 374, - 375, 662, 376, 377, 378, 663, 380, 381, 382, 383, - 664, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 665, 397, 398, 666, 400, 401, - 402, 667, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 668, 669, 417, 418, 419, - 420, 421, 422, 670, 424, 425, 671, 672, 427, 428, - 673, 430, 674, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 675, 444, 676, 677, 678, - 446, 447, 679, 448, 680, 450, 451, 452, 453, 454, - 681, 455, 682, 683, 684, 685, 458, 459, 686, 461, - 687, 688, 463, 464, 689, 466, 467, 468, 469, 470, - 690, 691, 471, 472, 473, 692, 474, 475, 476, 477, - 693, 478, 479, 480, 481, 482, 694, 695, 696, 485, - 697, 487, 488, 489, 490, 491, 492, 493, 698, 699, - 494, 700, 701, 495, 496, 497, 498, 499, 500, 702, - 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, - 512, 513, 514, 515, 555, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 130, 131, 0, + 132, 133, 134, 0, 136, 137, 138, 139, 140, 0, + 142, 143, 0, 144, 145, 146, 147, 148, 149, 0, + 0, 150, 151, 152, 153, 154, 155, 156, 1750, 157, + 158, 159, 160, 161, 0, 0, 1751, 163, 164, 165, + 166, 167, 168, 0, 170, 171, 172, 1752, 173, 174, + 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 0, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 208, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 0, 229, 0, 230, 231, 232, + 233, 0, 234, 1753, 235, 0, 0, 0, 238, 239, + 528, 0, 242, 0, 243, 0, 244, 245, 246, 247, + 0, 248, 249, 250, 251, 252, 1754, 254, 0, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 0, 269, 270, 271, 272, 273, 274, + 275, 276, 0, 277, 0, 278, 0, 0, 281, 0, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 0, + 291, 0, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 0, 324, 325, 326, 327, 328, 0, + 329, 330, 0, 332, 0, 333, 334, 335, 336, 337, + 338, 0, 339, 340, 0, 0, 341, 342, 343, 0, + 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 364, 0, 366, 367, 368, + 369, 370, 371, 1755, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 0, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 0, 431, + 432, 433, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 530, 448, 449, 0, + 0, 450, 451, 0, 452, 0, 454, 455, 456, 457, + 458, 0, 459, 460, 461, 0, 0, 462, 463, 464, + 465, 466, 0, 467, 468, 469, 470, 471, 472, 473, + 474, 0, 1756, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 488, 0, + 489, 0, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 556, 125, 126, 127, 557, 558, 559, 560, 561, - 562, 563, 564, 565, 129, 130, 566, 131, 132, 133, - 567, 135, 136, 137, 568, 569, 570, 571, 572, 573, - 143, 144, 145, 146, 147, 148, 574, 575, 149, 150, - 151, 152, 576, 577, 155, 578, 156, 157, 158, 159, - 579, 580, 581, 582, 583, 163, 164, 165, 166, 167, - 584, 169, 170, 171, 585, 172, 173, 174, 175, 176, - 177, 586, 587, 179, 180, 181, 182, 183, 184, 588, - 186, 187, 188, 589, 190, 191, 590, 193, 591, 194, - 592, 195, 196, 197, 198, 199, 200, 593, 594, 201, - 202, 203, 204, 595, 596, 205, 206, 207, 208, 209, - 597, 210, 211, 212, 598, 213, 214, 215, 599, 216, - 217, 218, 219, 600, 221, 222, 223, 224, 225, 601, - 602, 227, 603, 228, 229, 604, 231, 605, 232, 606, - 233, 607, 608, 609, 236, 237, 610, 611, 240, 612, - 241, 613, 614, 615, 244, 245, 616, 246, 247, 248, - 249, 250, 251, 252, 617, 254, 255, 256, 257, 618, - 258, 259, 260, 261, 262, 263, 264, 619, 265, 620, - 621, 268, 269, 270, 271, 272, 622, 623, 624, 625, - 626, 276, 627, 628, 279, 629, 281, 282, 283, 284, - 285, 286, 630, 631, 287, 632, 289, 633, 634, 291, - 292, 293, 294, 295, 296, 297, 298, 635, 300, 301, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 130, 131, 0, 132, 133, + 134, 0, 136, 137, 138, 139, 140, 0, 142, 143, + 0, 144, 145, 146, 147, 148, 149, 0, 0, 150, + 151, 152, 153, 154, 155, 156, 1750, 157, 158, 159, + 160, 161, 0, 0, 0, 163, 164, 165, 166, 167, + 168, 0, 170, 171, 172, 1752, 173, 174, 175, 176, + 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 208, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 0, 229, 0, 230, 231, 232, 233, 0, + 234, 1753, 235, 0, 0, 0, 238, 239, 528, 0, + 242, 0, 243, 0, 244, 245, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 0, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 0, 269, 270, 271, 272, 273, 274, 275, 276, + 0, 277, 0, 278, 0, 0, 281, 0, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 0, 291, 2330, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 636, 637, - 638, 323, 324, 325, 639, 640, 327, 328, 641, 330, - 642, 643, 332, 644, 334, 335, 336, 645, 337, 338, - 646, 647, 339, 340, 341, 648, 649, 342, 343, 650, - 651, 346, 652, 653, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 654, 655, 656, 657, 360, - 361, 658, 659, 364, 365, 660, 367, 368, 369, 661, - 370, 371, 372, 373, 374, 375, 662, 376, 377, 378, - 663, 380, 381, 382, 383, 664, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 665, - 397, 398, 666, 400, 401, 402, 667, 404, 405, 406, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 0, 324, 325, 326, 327, 328, 0, 329, 330, + 0, 332, 0, 333, 334, 335, 336, 337, 338, 0, + 339, 340, 0, 0, 341, 342, 343, 0, 0, 344, + 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 364, 0, 366, 367, 368, 369, 370, + 371, 1755, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 383, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 668, 669, 417, 418, 419, 420, 421, 422, 670, 424, - 425, 671, 672, 427, 428, 673, 430, 674, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 675, 444, 676, 677, 678, 446, 447, 679, 448, 680, - 450, 451, 452, 453, 454, 681, 455, 682, 683, 684, - 685, 458, 459, 686, 461, 687, 688, 463, 464, 689, - 466, 467, 468, 469, 470, 690, 691, 471, 472, 473, - 692, 474, 475, 476, 477, 693, 478, 479, 480, 481, - 482, 694, 695, 696, 485, 697, 487, 488, 489, 490, - 491, 492, 493, 698, 699, 494, 700, 701, 495, 496, - 497, 498, 499, 500, 702, 703, 704, 705, 706, 707, - 708, 709, 710, 711, 712, 512, 513, 514, 515, 555, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 0, 431, 432, 433, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 530, 448, 449, 0, 0, 450, + 451, 0, 452, 0, 454, 455, 456, 457, 458, 0, + 459, 460, 461, 0, 0, 462, 463, 464, 465, 466, + 0, 467, 468, 469, 470, 471, 472, 473, 474, 0, + 1756, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 488, 0, 489, 0, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 556, 125, 126, 127, - 557, 558, 559, 560, 561, 562, 563, 564, 565, 129, - 130, 566, 131, 132, 133, 567, 135, 136, 137, 568, - 569, 570, 571, 572, 573, 143, 144, 145, 146, 147, - 148, 574, 575, 149, 150, 151, 152, 576, 577, 155, - 578, 156, 157, 158, 159, 579, 580, 581, 582, 583, - 163, 164, 165, 166, 167, 584, 169, 170, 171, 585, - 172, 173, 174, 175, 176, 177, 586, 587, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 589, 190, - 191, 590, 193, 591, 194, 592, 195, 196, 197, 198, - 199, 200, 593, 594, 201, 202, 203, 204, 595, 596, - 205, 206, 207, 208, 209, 597, 210, 211, 212, 598, - 213, 214, 215, 599, 216, 217, 218, 219, 600, 221, - 222, 223, 224, 225, 601, 602, 227, 603, 228, 229, - 604, 231, 605, 232, 606, 233, 607, 608, 609, 236, - 237, 610, 611, 240, 612, 241, 613, 614, 615, 244, - 245, 616, 246, 247, 248, 249, 250, 940, 252, 617, - 254, 255, 256, 257, 618, 258, 259, 260, 261, 262, - 263, 264, 619, 265, 620, 621, 268, 269, 270, 271, - 272, 622, 623, 624, 625, 626, 276, 627, 628, 279, - 629, 281, 282, 283, 284, 285, 286, 630, 631, 287, - 632, 289, 633, 634, 291, 292, 293, 294, 295, 296, - 297, 298, 635, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 636, 637, 638, 323, 324, 325, 639, - 640, 327, 328, 641, 330, 642, 643, 332, 644, 334, - 335, 336, 645, 337, 338, 646, 647, 339, 340, 341, - 648, 649, 342, 343, 650, 651, 346, 652, 653, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 654, 655, 656, 657, 360, 361, 658, 659, 364, 365, - 660, 367, 368, 369, 661, 370, 371, 372, 373, 374, - 375, 662, 376, 377, 378, 663, 380, 381, 382, 383, - 664, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 665, 397, 398, 666, 400, 401, - 402, 667, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 668, 669, 417, 418, 419, - 420, 421, 422, 670, 424, 425, 671, 672, 427, 428, - 673, 430, 674, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 675, 444, 676, 677, 678, - 446, 447, 679, 448, 680, 450, 451, 452, 453, 454, - 681, 455, 682, 683, 684, 685, 458, 459, 686, 461, - 687, 688, 463, 464, 689, 466, 467, 468, 469, 470, - 690, 691, 471, 472, 473, 692, 474, 475, 476, 477, - 693, 478, 479, 480, 481, 482, 694, 695, 696, 485, - 697, 487, 488, 489, 490, 491, 492, 493, 698, 699, - 494, 700, 701, 495, 496, 497, 498, 499, 500, 702, - 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, - 512, 513, 514, 515, 555, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 3, 4, 0, 0, 0, 0, + 0, 0, 0, 130, 131, 0, 132, 133, 134, 0, + 136, 137, 138, 139, 140, 0, 142, 143, 0, 144, + 145, 146, 147, 148, 149, 0, 0, 150, 151, 152, + 153, 154, 155, 156, 0, 157, 158, 159, 160, 161, + 0, 0, 0, 163, 164, 165, 166, 167, 168, 0, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 208, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 0, 229, 0, 230, 231, 232, 233, 0, 234, 0, + 235, 0, 0, 0, 238, 239, 528, 0, 242, 0, + 243, 0, 244, 245, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 0, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 0, + 269, 270, 271, 272, 273, 274, 275, 276, 0, 277, + 0, 278, 0, 0, 281, 0, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 0, 291, 0, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 0, + 324, 325, 326, 327, 328, 0, 329, 330, 0, 332, + 0, 333, 334, 335, 336, 337, 338, 0, 339, 340, + 0, 0, 341, 342, 343, 0, 0, 344, 345, 346, + 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 364, 0, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 0, 431, 432, 433, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 530, 448, 449, 0, 0, 450, 451, 0, + 452, 0, 454, 455, 456, 457, 458, 0, 459, 460, + 461, 0, 0, 462, 463, 464, 465, 466, 0, 467, + 468, 469, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 488, 0, 489, 0, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 556, 125, 126, 127, 557, 558, 559, 560, 561, - 562, 563, 564, 565, 129, 130, 566, 131, 132, 133, - 567, 135, 136, 137, 568, 569, 570, 571, 572, 573, - 143, 144, 145, 146, 147, 148, 574, 575, 149, 150, - 151, 152, 576, 577, 155, 578, 156, 157, 158, 159, - 579, 580, 581, 582, 583, 163, 164, 165, 166, 167, - 584, 169, 170, 171, 585, 172, 173, 174, 175, 176, - 177, 586, 587, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 589, 190, 191, 590, 193, 591, 194, - 592, 195, 196, 197, 198, 199, 200, 593, 594, 201, - 202, 203, 204, 595, 596, 205, 206, 207, 208, 209, - 597, 210, 211, 212, 598, 213, 214, 215, 599, 216, - 217, 218, 219, 600, 221, 222, 223, 224, 225, 601, - 602, 227, 603, 228, 229, 604, 231, 605, 232, 606, - 233, 607, 608, 609, 236, 237, 610, 611, 240, 612, - 241, 613, 614, 615, 244, 245, 616, 246, 247, 248, - 249, 250, 251, 252, 617, 254, 255, 256, 257, 618, - 258, 259, 260, 261, 262, 263, 264, 619, 265, 620, - 621, 268, 269, 270, 271, 272, 622, 623, 624, 625, - 626, 276, 627, 628, 279, 629, 281, 282, 283, 284, - 285, 286, 630, 631, 287, 632, 289, 633, 634, 291, - 292, 293, 294, 295, 296, 297, 298, 635, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 636, 637, - 638, 323, 324, 325, 639, 640, 327, 328, 641, 330, - 642, 643, 332, 644, 334, 335, 336, 645, 337, 338, - 646, 647, 339, 340, 341, 648, 649, 342, 343, 650, - 651, 346, 652, 653, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 654, 655, 656, 657, 360, - 361, 658, 659, 364, 365, 660, 367, 368, 369, 661, - 370, 371, 372, 373, 374, 375, 662, 376, 377, 378, - 663, 380, 381, 382, 383, 664, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 665, - 397, 398, 666, 400, 401, 402, 667, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 668, 669, 417, 418, 419, 420, 421, 422, 670, 424, - 425, 671, 672, 427, 428, 673, 430, 674, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 675, 444, 676, 677, 678, 446, 447, 679, 448, 680, - 450, 451, 452, 453, 454, 681, 455, 682, 683, 684, - 685, 458, 459, 686, 461, 687, 688, 463, 464, 689, - 466, 467, 468, 469, 470, 690, 691, 471, 472, 473, - 692, 474, 475, 476, 477, 693, 478, 479, 480, 481, - 482, 694, 695, 696, 485, 697, 487, 488, 489, 490, - 491, 492, 493, 698, 699, 494, 700, 701, 495, 496, - 497, 498, 499, 500, 702, 703, 704, 705, 706, 707, - 708, 709, 710, 711, 712, 512, 513, 514, 515, 555, + 118, 119, 120, 121, 122, 123, 124, 125, 554, 126, + 127, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 130, 131, 0, 132, 133, 134, 0, 136, 137, + 138, 139, 140, 0, 142, 143, 0, 144, 145, 146, + 147, 148, 149, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 0, 157, 158, 159, 160, 161, 0, 0, + 0, 163, 164, 165, 166, 167, 168, 0, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 0, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 0, 229, + 0, 230, 231, 232, 233, 0, 234, 0, 235, 0, + 0, 0, 238, 239, 528, 0, 242, 0, 243, 0, + 244, 245, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 0, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 0, 269, 270, + 271, 272, 273, 274, 275, 276, 0, 277, 0, 278, + 0, 0, 281, 0, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 0, 291, 0, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 0, 324, 325, + 326, 327, 328, 0, 329, 330, 0, 332, 0, 333, + 334, 335, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 346, 0, 348, + 0, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 364, + 0, 366, 367, 368, 555, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 383, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 0, 431, 432, 433, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 530, 448, 449, 0, 0, 450, 451, 0, 452, 0, + 454, 455, 456, 457, 458, 0, 459, 460, 461, 0, + 0, 462, 463, 464, 465, 466, 0, 467, 468, 469, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 488, 0, 489, 0, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 527, + 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, + 131, 0, 132, 133, 134, 0, 136, 137, 138, 139, + 140, 0, 142, 143, 0, 144, 145, 146, 147, 148, + 149, 0, 0, 150, 151, 152, 153, 154, 155, 156, + 0, 157, 158, 159, 160, 161, 0, 0, 0, 163, + 164, 165, 166, 167, 168, 0, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 0, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 0, 229, 0, 230, + 231, 232, 233, 0, 234, 0, 235, 0, 0, 0, + 238, 239, 528, 0, 242, 0, 243, 0, 244, 245, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 0, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 0, 269, 270, 271, 272, + 273, 274, 275, 276, 0, 277, 0, 278, 0, 0, + 281, 0, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 0, 291, 0, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 0, 324, 325, 326, 327, + 328, 0, 329, 330, 0, 332, 0, 333, 334, 335, + 336, 337, 338, 0, 339, 340, 0, 795, 341, 342, + 343, 0, 0, 344, 345, 346, 0, 348, 0, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 364, 0, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 0, 431, 432, 433, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 530, 448, + 449, 0, 0, 450, 451, 0, 452, 0, 454, 455, + 456, 457, 458, 0, 459, 460, 461, 0, 0, 462, + 463, 464, 465, 466, 0, 467, 468, 469, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 488, 0, 489, 0, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 2233, 122, 123, 124, 556, 125, 126, 127, - 557, 558, 559, 560, 561, 562, 563, 564, 565, 129, - 130, 566, 131, 132, 133, 567, 135, 136, 137, 568, - 569, 570, 571, 572, 573, 143, 144, 145, 146, 147, - 148, 574, 575, 149, 150, 151, 152, 576, 577, 155, - 578, 156, 157, 158, 159, 579, 580, 581, 582, 583, - 163, 164, 165, 166, 167, 584, 169, 170, 171, 585, - 172, 173, 174, 175, 176, 177, 586, 587, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 589, 190, - 191, 590, 193, 591, 194, 592, 195, 196, 197, 198, - 199, 200, 593, 594, 201, 202, 203, 204, 595, 596, - 205, 206, 207, 2234, 209, 597, 210, 211, 212, 598, - 213, 214, 215, 599, 216, 217, 218, 219, 600, 221, - 222, 223, 224, 225, 601, 602, 227, 603, 228, 229, - 604, 231, 605, 232, 606, 233, 607, 608, 609, 236, - 237, 610, 611, 240, 612, 241, 613, 614, 615, 244, - 245, 616, 246, 247, 248, 249, 250, 251, 252, 617, - 254, 255, 256, 257, 618, 258, 259, 260, 261, 262, - 263, 264, 619, 265, 620, 621, 268, 269, 270, 271, - 272, 622, 623, 624, 625, 626, 276, 627, 628, 279, - 629, 281, 282, 283, 284, 285, 286, 630, 631, 287, - 632, 289, 633, 634, 291, 292, 293, 294, 295, 296, - 297, 298, 635, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 636, 637, 638, 323, 324, 325, 639, - 640, 327, 328, 641, 330, 642, 643, 332, 644, 334, - 335, 336, 645, 337, 338, 646, 647, 339, 340, 341, - 648, 649, 342, 343, 650, 651, 346, 652, 653, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 654, 655, 656, 657, 360, 361, 658, 659, 364, 365, - 660, 367, 368, 369, 661, 370, 371, 372, 373, 374, - 375, 662, 376, 377, 378, 663, 380, 381, 382, 383, - 664, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 665, 397, 398, 666, 400, 401, - 402, 667, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 668, 669, 417, 418, 419, - 420, 421, 2235, 670, 424, 425, 671, 672, 427, 428, - 673, 430, 674, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 675, 444, 676, 677, 678, - 446, 447, 679, 448, 680, 450, 451, 452, 453, 454, - 681, 455, 682, 683, 684, 685, 458, 459, 686, 461, - 687, 688, 463, 464, 689, 466, 467, 468, 469, 470, - 690, 691, 471, 472, 473, 692, 474, 475, 476, 477, - 693, 478, 479, 480, 481, 482, 694, 695, 696, 485, - 697, 487, 488, 489, 490, 491, 492, 493, 698, 699, - 494, 700, 701, 495, 496, 497, 498, 499, 500, 702, - 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, - 512, 513, 514, 515, 964, 0, 815, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 130, 131, 0, + 132, 133, 134, 0, 136, 137, 138, 139, 140, 0, + 142, 143, 0, 144, 145, 146, 147, 148, 149, 0, + 0, 150, 151, 152, 153, 154, 155, 156, 0, 157, + 158, 159, 160, 161, 0, 0, 0, 163, 164, 165, + 166, 167, 168, 0, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 0, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 208, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 0, 229, 0, 230, 231, 232, + 233, 0, 234, 0, 235, 0, 0, 0, 238, 239, + 528, 0, 242, 0, 243, 0, 244, 245, 246, 247, + 0, 248, 249, 250, 251, 252, 900, 254, 0, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 0, 269, 270, 271, 272, 273, 274, + 275, 276, 0, 277, 0, 278, 0, 0, 281, 0, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 0, + 291, 0, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 0, 324, 325, 326, 327, 328, 0, + 329, 330, 0, 332, 0, 333, 334, 335, 336, 337, + 338, 0, 339, 340, 0, 795, 341, 342, 343, 0, + 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 364, 0, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 0, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 0, 431, + 432, 433, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 530, 448, 449, 0, + 0, 450, 451, 0, 452, 0, 454, 455, 456, 457, + 458, 0, 459, 460, 461, 0, 0, 462, 463, 464, + 465, 466, 0, 467, 468, 469, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 488, 0, + 489, 0, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 560, 0, - 0, 0, 0, 565, 129, 130, 0, 131, 132, 133, - 567, 135, 136, 137, 568, 569, 570, 571, 572, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 576, 577, 155, 0, 156, 157, 158, 159, - 579, 0, 581, 0, 583, 163, 164, 165, 166, 167, - 584, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 587, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 589, 190, 191, 590, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 600, 221, 222, 223, 224, 225, 601, - 1342, 227, 0, 228, 229, 604, 231, 0, 232, 0, - 233, 607, 0, 609, 236, 237, 610, 611, 240, 0, - 241, 0, 614, 615, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 617, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 620, - 621, 268, 269, 270, 271, 272, 622, 623, 0, 625, - 0, 276, 627, 628, 279, 629, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 632, 289, 633, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 635, 300, 301, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 944, 126, 127, 128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 130, 131, 0, 132, 133, + 134, 0, 136, 137, 138, 139, 140, 0, 142, 143, + 0, 144, 145, 146, 147, 148, 149, 0, 0, 150, + 151, 152, 153, 154, 155, 156, 0, 157, 158, 159, + 160, 161, 0, 0, 0, 163, 164, 165, 166, 167, + 168, 0, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 208, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 0, 229, 0, 230, 231, 232, 233, 0, + 234, 0, 235, 0, 0, 0, 238, 239, 528, 0, + 242, 0, 243, 0, 244, 245, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 0, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 0, 269, 270, 271, 272, 273, 274, 275, 276, + 0, 277, 0, 278, 0, 0, 281, 0, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 0, 291, 0, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 636, 637, - 638, 323, 324, 325, 639, 0, 327, 328, 641, 330, - 0, 643, 332, 644, 334, 335, 336, 0, 337, 338, - 1343, 0, 339, 340, 341, 0, 0, 342, 343, 650, - 651, 346, 652, 653, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 658, 659, 364, 365, 660, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 663, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 666, 400, 401, 402, 667, 404, 405, 406, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 0, 324, 325, 326, 327, 328, 0, 329, 330, + 0, 332, 0, 333, 334, 335, 336, 337, 338, 0, + 339, 340, 0, 0, 341, 342, 343, 0, 0, 344, + 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 364, 0, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 383, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 669, 417, 418, 419, 420, 421, 422, 670, 424, - 425, 0, 672, 427, 428, 673, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 675, 444, 676, 0, 0, 446, 447, 0, 448, 680, - 450, 451, 452, 453, 454, 0, 455, 682, 683, 0, - 0, 458, 459, 686, 461, 687, 1344, 463, 464, 689, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 694, 695, 0, 485, 697, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 702, 703, 704, 705, 706, 707, - 708, 709, 710, 711, 712, 512, 513, 514, 515, 964, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 0, 431, 432, 433, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 530, 448, 449, 0, 0, 450, + 451, 0, 452, 0, 454, 455, 456, 457, 458, 0, + 459, 460, 461, 0, 0, 462, 463, 464, 465, 466, + 0, 467, 468, 469, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 488, 0, 489, 0, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 3, 4, 0, 560, 0, 0, 0, 0, 565, 129, - 130, 0, 131, 132, 133, 567, 135, 136, 137, 568, - 569, 570, 571, 572, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 576, 577, 155, - 0, 156, 157, 158, 159, 579, 0, 581, 0, 583, - 163, 164, 165, 166, 167, 584, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 587, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 589, 190, - 191, 590, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 600, 221, - 222, 223, 224, 225, 601, 0, 227, 0, 228, 229, - 604, 231, 0, 232, 0, 233, 607, 0, 609, 236, - 237, 610, 611, 240, 0, 241, 0, 614, 615, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 617, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 620, 621, 268, 269, 270, 271, - 272, 622, 623, 0, 625, 0, 276, 627, 628, 279, - 629, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 632, 289, 633, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 635, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 636, 637, 638, 323, 324, 325, 639, - 0, 327, 328, 641, 330, 0, 643, 332, 644, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 650, 651, 346, 652, 653, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 658, 659, 364, 365, - 660, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 663, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 666, 400, 401, - 402, 667, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 669, 417, 418, 419, - 420, 421, 422, 670, 424, 425, 0, 672, 427, 428, - 673, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 675, 444, 676, 0, 0, - 446, 447, 0, 448, 680, 450, 451, 452, 453, 454, - 0, 455, 682, 683, 0, 0, 458, 459, 686, 461, - 687, 0, 463, 464, 689, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 694, 695, 0, 485, - 697, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 702, - 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, - 512, 513, 514, 515, 116, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 131, 0, 132, 133, 134, 0, + 136, 137, 138, 139, 140, 0, 142, 143, 0, 144, + 145, 146, 147, 148, 149, 0, 0, 150, 151, 152, + 153, 154, 155, 156, 0, 157, 158, 159, 160, 161, + 0, 0, 0, 163, 164, 165, 166, 167, 168, 0, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 208, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 1172, 227, 228, + 0, 229, 0, 230, 231, 232, 233, 0, 234, 0, + 235, 0, 0, 0, 238, 239, 528, 0, 242, 0, + 243, 0, 244, 245, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 0, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 0, + 269, 270, 271, 272, 273, 274, 275, 276, 0, 277, + 0, 278, 0, 0, 281, 0, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 0, 291, 0, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 0, + 324, 325, 326, 327, 328, 0, 329, 330, 0, 332, + 0, 333, 334, 335, 336, 337, 338, 0, 339, 340, + 0, 795, 341, 342, 343, 0, 0, 344, 345, 346, + 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 364, 0, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 0, 431, 432, 433, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 530, 448, 449, 0, 0, 450, 451, 0, + 452, 0, 454, 455, 456, 457, 458, 0, 459, 460, + 461, 0, 0, 462, 463, 464, 465, 466, 0, 467, + 468, 469, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 488, 0, 489, 0, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 527, 1953, 0, 0, 0, 0, 1954, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 128, 129, 130, 0, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 785, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 786, 0, 787, 0, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 788, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 234, 0, 235, 236, 237, 238, 239, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 288, 289, 290, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 0, 327, 328, 329, 330, - 0, 790, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 345, 346, 347, 792, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 793, 363, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 426, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, 444, 795, 0, 0, 446, 447, 0, 448, 449, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 796, 461, 797, 0, 463, 464, 798, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 116, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 130, 131, 0, 132, 133, 134, 0, 136, 137, + 138, 139, 140, 0, 142, 143, 0, 144, 145, 146, + 147, 148, 149, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 0, 157, 158, 159, 160, 161, 0, 0, + 0, 163, 164, 165, 166, 167, 168, 0, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 0, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 0, 229, + 0, 230, 231, 232, 233, 0, 234, 0, 235, 0, + 0, 0, 238, 239, 528, 0, 242, 0, 243, 0, + 244, 245, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 0, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 0, 269, 270, + 271, 272, 273, 274, 275, 276, 0, 277, 0, 278, + 0, 0, 281, 0, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 0, 291, 0, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 0, 324, 325, + 326, 327, 328, 0, 329, 330, 0, 332, 0, 333, + 334, 335, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 346, 0, 348, + 0, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 364, + 0, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 383, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 0, 431, 432, 433, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 530, 448, 449, 0, 0, 450, 451, 0, 452, 0, + 454, 455, 456, 457, 458, 0, 459, 460, 461, 0, + 0, 462, 463, 464, 465, 466, 0, 467, 468, 469, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 488, 0, 489, 0, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 527, + 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, + 131, 0, 132, 133, 134, 0, 136, 137, 138, 139, + 140, 0, 142, 143, 0, 144, 145, 146, 147, 148, + 149, 0, 0, 150, 151, 152, 153, 154, 155, 156, + 0, 157, 158, 159, 160, 161, 0, 0, 0, 163, + 164, 165, 166, 167, 168, 0, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 0, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 0, 229, 0, 230, + 231, 232, 233, 0, 234, 0, 235, 0, 0, 0, + 238, 239, 528, 0, 1961, 0, 243, 0, 244, 245, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 0, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 0, 269, 270, 271, 272, + 273, 274, 275, 276, 0, 277, 0, 278, 0, 0, + 281, 0, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 0, 291, 0, 0, 293, 294, 1962, 296, 297, + 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 0, 324, 325, 326, 327, + 328, 0, 329, 330, 0, 332, 0, 333, 334, 335, + 336, 337, 338, 0, 339, 340, 0, 0, 341, 342, + 343, 0, 0, 344, 345, 346, 0, 348, 0, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 364, 0, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 0, 431, 432, 433, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 530, 448, + 449, 0, 0, 450, 451, 1963, 452, 0, 454, 1964, + 456, 1965, 458, 0, 459, 460, 461, 0, 0, 462, + 463, 464, 465, 466, 0, 467, 468, 469, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 1966, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 488, 0, 489, 0, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 128, 129, - 130, 0, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 161, 0, 162, - 163, 164, 165, 166, 167, 168, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 234, 0, 235, 236, - 237, 238, 239, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 288, 289, 290, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 0, 327, 328, 329, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 345, 346, 347, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 363, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 426, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 445, 0, 0, - 446, 447, 0, 448, 449, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 486, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 130, 131, 0, + 132, 133, 134, 0, 136, 137, 138, 139, 140, 0, + 142, 143, 0, 144, 145, 146, 147, 148, 149, 0, + 0, 150, 151, 152, 153, 154, 155, 156, 0, 157, + 158, 159, 160, 161, 0, 0, 0, 163, 164, 165, + 166, 167, 168, 0, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 0, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 208, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 0, 229, 0, 230, 231, 232, + 233, 0, 234, 0, 235, 0, 0, 0, 238, 239, + 528, 0, 242, 0, 243, 0, 244, 245, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 0, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 0, 269, 270, 271, 272, 273, 274, + 275, 276, 0, 277, 0, 278, 0, 0, 281, 0, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 0, + 291, 0, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 0, 324, 325, 326, 327, 328, 0, + 329, 330, 0, 332, 0, 333, 334, 335, 336, 337, + 338, 0, 339, 340, 0, 0, 341, 342, 343, 0, + 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 364, 0, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 0, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 0, 431, + 432, 433, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 530, 448, 449, 0, + 0, 450, 451, 0, 452, 0, 454, 455, 456, 457, + 458, 0, 459, 460, 461, 0, 0, 462, 463, 464, + 465, 466, 0, 467, 468, 469, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 488, 0, + 489, 0, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 527, 0, 819, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 1739, 156, 157, 158, 159, - 160, 0, 0, 1740, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 1741, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 130, 131, 0, 132, 133, + 134, 0, 136, 137, 138, 139, 140, 0, 142, 143, + 0, 144, 145, 146, 147, 148, 149, 0, 0, 150, + 151, 152, 153, 154, 155, 156, 0, 157, 158, 159, + 160, 161, 0, 0, 0, 163, 164, 165, 166, 167, + 168, 0, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 208, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 1742, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 1743, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, + 227, 228, 0, 229, 0, 230, 231, 232, 233, 0, + 234, 0, 235, 0, 0, 0, 238, 239, 528, 0, + 242, 0, 243, 0, 244, 245, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 0, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 0, 269, 270, 271, 272, 273, 274, 275, 276, + 0, 277, 0, 278, 0, 0, 281, 0, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 0, 291, 0, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 1744, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 0, 324, 325, 326, 327, 328, 0, 329, 330, + 0, 332, 0, 333, 334, 335, 336, 337, 338, 0, + 339, 340, 0, 0, 341, 342, 343, 0, 0, 344, + 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 364, 0, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 383, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 1745, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 0, 431, 432, 433, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 530, 448, 449, 0, 0, 450, + 451, 0, 452, 0, 454, 455, 456, 457, 458, 0, + 459, 460, 461, 0, 0, 462, 463, 464, 465, 466, + 0, 467, 468, 469, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 488, 0, 489, 0, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 1739, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 1741, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 1742, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 2318, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 1744, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 1745, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 825, 126, 127, 128, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 131, 0, 132, 133, 134, 0, + 136, 137, 138, 139, 140, 0, 142, 143, 0, 144, + 145, 146, 147, 148, 149, 0, 0, 150, 151, 152, + 153, 154, 155, 156, 0, 157, 158, 159, 160, 161, + 0, 0, 0, 163, 164, 165, 166, 167, 168, 0, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 208, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 0, 229, 0, 230, 231, 232, 233, 0, 234, 0, + 235, 0, 0, 0, 238, 239, 528, 0, 826, 0, + 243, 0, 244, 245, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 0, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 0, + 269, 270, 271, 272, 273, 274, 275, 276, 0, 277, + 0, 278, 0, 0, 281, 0, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 0, 291, 0, 0, 293, + 294, 827, 296, 297, 298, 299, 300, 529, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 0, + 324, 325, 326, 327, 328, 0, 329, 330, 0, 332, + 0, 333, 334, 335, 336, 337, 338, 0, 339, 340, + 0, 0, 341, 342, 343, 0, 0, 344, 345, 346, + 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 364, 0, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 828, 426, + 427, 428, 429, 0, 0, 431, 432, 433, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 530, 448, 449, 0, 0, 450, 451, 0, + 452, 0, 454, 455, 456, 457, 458, 0, 459, 829, + 461, 0, 0, 830, 463, 464, 465, 466, 0, 467, + 468, 469, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 488, 0, 489, 0, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 3, 4, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 550, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 551, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 130, 131, 0, 132, 133, 134, 0, 136, 137, + 138, 139, 140, 0, 142, 143, 0, 144, 145, 146, + 147, 148, 149, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 0, 157, 158, 159, 160, 161, 0, 0, + 0, 163, 164, 165, 166, 167, 168, 0, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 0, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 0, 229, + 0, 230, 231, 232, 233, 0, 234, 0, 235, 0, + 0, 0, 238, 239, 528, 0, 242, 0, 243, 0, + 244, 245, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 0, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 0, 269, 270, + 271, 272, 273, 274, 275, 276, 0, 277, 0, 278, + 0, 0, 281, 0, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 0, 291, 0, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 0, 324, 325, + 326, 327, 328, 0, 329, 330, 0, 332, 0, 333, + 334, 335, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 346, 0, 348, + 0, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 364, + 0, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 383, 384, 385, 862, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 0, 431, 432, 433, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 530, 448, 449, 0, 0, 450, 451, 0, 452, 0, + 454, 455, 456, 457, 458, 0, 459, 460, 461, 0, + 0, 462, 463, 464, 465, 466, 0, 467, 468, 469, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 488, 0, 489, 0, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 527, + 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, + 131, 0, 132, 133, 134, 0, 136, 137, 138, 139, + 140, 0, 142, 143, 0, 144, 145, 146, 147, 148, + 149, 0, 0, 150, 151, 152, 153, 154, 155, 156, + 0, 157, 158, 159, 160, 161, 0, 0, 0, 163, + 164, 165, 166, 167, 168, 0, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 0, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 0, 229, 0, 230, + 231, 232, 233, 0, 234, 0, 235, 0, 0, 0, + 238, 239, 528, 0, 242, 0, 243, 0, 244, 245, + 246, 247, 0, 248, 249, 250, 251, 252, 895, 254, + 0, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 0, 269, 270, 271, 272, + 273, 274, 275, 276, 0, 277, 0, 278, 0, 0, + 281, 0, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 0, 291, 0, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 0, 324, 325, 326, 327, + 328, 0, 329, 330, 0, 332, 0, 333, 334, 335, + 336, 337, 338, 0, 339, 340, 0, 0, 341, 342, + 343, 0, 0, 344, 345, 346, 0, 348, 0, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 364, 0, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 0, 431, 432, 433, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 530, 448, + 449, 0, 0, 450, 451, 0, 452, 0, 454, 455, + 456, 457, 458, 0, 459, 460, 461, 0, 0, 462, + 463, 464, 465, 466, 0, 467, 468, 469, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 488, 0, 489, 0, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 791, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 896, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 791, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 130, 131, 0, + 132, 133, 134, 0, 136, 137, 138, 139, 140, 0, + 142, 143, 0, 144, 145, 146, 147, 148, 149, 0, + 0, 150, 151, 152, 153, 154, 155, 156, 0, 157, + 158, 159, 160, 161, 0, 0, 0, 163, 164, 165, + 166, 167, 168, 0, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 0, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 208, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 0, 229, 0, 230, 231, 232, + 233, 0, 234, 0, 235, 0, 0, 0, 238, 239, + 528, 0, 242, 0, 243, 0, 244, 245, 246, 247, + 0, 248, 249, 250, 251, 252, 898, 254, 0, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 0, 269, 270, 271, 272, 273, 274, + 275, 276, 0, 277, 0, 278, 0, 0, 281, 0, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 0, + 291, 0, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 0, 324, 325, 326, 327, 328, 0, + 329, 330, 0, 332, 0, 333, 334, 335, 336, 337, + 338, 0, 339, 340, 0, 0, 341, 342, 343, 0, + 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 364, 0, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 0, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 0, 431, + 432, 433, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 530, 448, 449, 0, + 0, 450, 451, 0, 452, 0, 454, 455, 456, 457, + 458, 0, 459, 460, 461, 0, 0, 462, 463, 464, + 465, 466, 0, 467, 468, 469, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 488, 0, + 489, 0, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 938, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 130, 131, 0, 132, 133, + 134, 0, 136, 137, 138, 139, 140, 0, 142, 143, + 0, 144, 145, 146, 147, 148, 149, 0, 0, 150, + 151, 152, 153, 154, 155, 156, 0, 157, 158, 159, + 160, 161, 0, 0, 0, 163, 164, 165, 166, 167, + 168, 0, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 208, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, + 227, 228, 0, 229, 0, 230, 231, 232, 233, 0, + 234, 0, 235, 0, 0, 0, 238, 239, 528, 0, + 242, 0, 243, 0, 244, 245, 246, 247, 0, 248, + 249, 250, 251, 252, 902, 254, 0, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 0, 269, 270, 271, 272, 273, 274, 275, 276, + 0, 277, 0, 278, 0, 0, 281, 0, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 0, 291, 0, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 0, 324, 325, 326, 327, 328, 0, 329, 330, + 0, 332, 0, 333, 334, 335, 336, 337, 338, 0, + 339, 340, 0, 0, 341, 342, 343, 0, 0, 344, + 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 364, 0, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 383, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 1943, 0, 0, 0, 0, 1944, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 0, 431, 432, 433, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 530, 448, 449, 0, 0, 450, + 451, 0, 452, 0, 454, 455, 456, 457, 458, 0, + 459, 460, 461, 0, 0, 462, 463, 464, 465, 466, + 0, 467, 468, 469, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 488, 0, 489, 0, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 1951, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 1952, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 1953, 448, 0, - 450, 1954, 452, 1955, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 1956, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 815, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 131, 0, 132, 133, 134, 0, + 136, 137, 138, 139, 140, 0, 142, 143, 0, 144, + 145, 146, 147, 148, 149, 0, 0, 150, 151, 152, + 153, 154, 155, 156, 0, 157, 158, 159, 160, 161, + 0, 0, 0, 163, 164, 165, 166, 167, 168, 0, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 208, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 0, 229, 0, 230, 231, 232, 233, 0, 234, 0, + 235, 0, 0, 0, 238, 239, 528, 0, 242, 0, + 243, 0, 244, 245, 246, 247, 0, 248, 249, 250, + 251, 252, 932, 254, 0, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 0, + 269, 270, 271, 272, 273, 274, 275, 276, 0, 277, + 0, 278, 0, 0, 281, 0, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 0, 291, 0, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 0, + 324, 325, 326, 327, 328, 0, 329, 330, 0, 332, + 0, 333, 334, 335, 336, 337, 338, 0, 339, 340, + 0, 0, 341, 342, 343, 0, 0, 344, 345, 346, + 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 364, 0, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 0, 431, 432, 433, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 530, 448, 449, 0, 0, 450, 451, 0, + 452, 0, 454, 455, 456, 457, 458, 0, 459, 460, + 461, 0, 0, 462, 463, 464, 465, 466, 0, 467, + 468, 469, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 488, 0, 489, 0, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 130, 131, 0, 132, 133, 134, 0, 136, 137, + 138, 139, 140, 0, 142, 143, 0, 144, 145, 146, + 147, 148, 149, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 0, 157, 158, 159, 160, 161, 0, 0, + 0, 163, 164, 165, 166, 167, 168, 0, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 0, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 0, 229, + 0, 230, 231, 232, 233, 0, 234, 0, 235, 0, + 0, 0, 238, 239, 528, 0, 242, 0, 243, 0, + 244, 245, 246, 247, 0, 248, 249, 250, 251, 252, + 960, 254, 0, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 0, 269, 270, + 271, 272, 273, 274, 275, 276, 0, 277, 0, 278, + 0, 0, 281, 0, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 0, 291, 0, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 0, 324, 325, + 326, 327, 328, 0, 329, 330, 0, 332, 0, 333, + 334, 335, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 346, 0, 348, + 0, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 364, + 0, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 383, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 0, 431, 432, 433, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 530, 448, 449, 0, 0, 450, 451, 0, 452, 0, + 454, 455, 456, 457, 458, 0, 459, 460, 461, 0, + 0, 462, 463, 464, 465, 466, 0, 467, 468, 469, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 488, 0, 489, 0, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 527, + 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, + 131, 0, 132, 133, 134, 0, 136, 137, 138, 139, + 140, 0, 142, 143, 0, 144, 145, 146, 147, 148, + 149, 0, 0, 150, 151, 152, 153, 154, 155, 156, + 0, 157, 158, 159, 160, 161, 0, 0, 0, 163, + 164, 165, 166, 167, 168, 0, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 0, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 0, 229, 0, 230, + 231, 232, 233, 0, 234, 0, 235, 0, 0, 0, + 238, 239, 528, 0, 242, 0, 243, 0, 244, 245, + 246, 247, 0, 248, 249, 250, 251, 252, 963, 254, + 0, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 0, 269, 270, 271, 272, + 273, 274, 275, 276, 0, 277, 0, 278, 0, 0, + 281, 0, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 0, 291, 0, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 0, 324, 325, 326, 327, + 328, 0, 329, 330, 0, 332, 0, 333, 334, 335, + 336, 337, 338, 0, 339, 340, 0, 0, 341, 342, + 343, 0, 0, 344, 345, 346, 0, 348, 0, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 364, 0, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 0, 431, 432, 433, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 530, 448, + 449, 0, 0, 450, 451, 0, 452, 0, 454, 455, + 456, 457, 458, 0, 459, 460, 461, 0, 0, 462, + 463, 464, 465, 466, 0, 467, 468, 469, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 488, 0, 489, 0, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 822, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 823, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 824, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 825, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 826, 457, 0, 0, 827, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 0, 1005, 0, 0, 130, 131, 0, + 132, 133, 134, 0, 136, 137, 138, 139, 140, 0, + 142, 143, 0, 144, 145, 146, 147, 148, 149, 0, + 0, 150, 151, 152, 153, 154, 155, 156, 0, 157, + 158, 159, 160, 161, 0, 0, 0, 163, 164, 165, + 166, 167, 168, 0, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 0, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 208, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 0, 229, 0, 230, 231, 232, + 233, 0, 234, 0, 235, 0, 0, 0, 238, 239, + 528, 0, 242, 0, 243, 0, 244, 245, 246, 247, + 0, 248, 249, 250, 251, 252, 253, 254, 0, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 0, 269, 270, 271, 272, 273, 274, + 275, 276, 0, 277, 0, 278, 0, 0, 281, 0, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 0, + 291, 0, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 0, 324, 325, 326, 327, 328, 0, + 329, 330, 0, 332, 0, 333, 334, 335, 336, 337, + 338, 0, 339, 340, 0, 0, 341, 342, 343, 0, + 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 364, 0, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 0, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 0, 431, + 432, 433, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 530, 448, 449, 0, + 0, 450, 451, 0, 452, 0, 454, 455, 456, 457, + 458, 0, 459, 460, 461, 0, 0, 462, 463, 464, + 465, 466, 0, 467, 468, 469, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 488, 0, + 489, 0, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 0, 1028, 0, 0, 130, 131, 0, 132, 133, + 134, 0, 136, 137, 138, 139, 140, 0, 142, 143, + 0, 144, 145, 146, 147, 148, 149, 0, 0, 150, + 151, 152, 153, 154, 155, 156, 0, 157, 158, 159, + 160, 161, 0, 0, 0, 163, 164, 165, 166, 167, + 168, 0, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 208, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, + 227, 228, 0, 229, 0, 230, 231, 232, 233, 0, + 234, 0, 235, 0, 0, 0, 238, 239, 528, 0, + 242, 0, 243, 0, 244, 245, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 0, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 0, 269, 270, 271, 272, 273, 274, 275, 276, + 0, 277, 0, 278, 0, 0, 281, 0, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 0, 291, 0, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 859, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 0, 324, 325, 326, 327, 328, 0, 329, 330, + 0, 332, 0, 333, 334, 335, 336, 337, 338, 0, + 339, 340, 0, 0, 341, 342, 343, 0, 0, 344, + 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 364, 0, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 383, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 891, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 0, 431, 432, 433, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 530, 448, 449, 0, 0, 450, + 451, 0, 452, 0, 454, 455, 456, 457, 458, 0, + 459, 460, 461, 0, 0, 462, 463, 464, 465, 466, + 0, 467, 468, 469, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 488, 0, 489, 0, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 894, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 898, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 825, 126, 127, 128, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 131, 0, 132, 133, 134, 0, + 136, 137, 138, 139, 140, 0, 142, 143, 0, 144, + 145, 146, 147, 148, 149, 0, 0, 150, 151, 152, + 153, 154, 155, 156, 0, 157, 158, 159, 160, 161, + 0, 0, 0, 163, 164, 165, 166, 167, 168, 0, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 208, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 0, 229, 0, 230, 231, 232, 233, 0, 234, 0, + 235, 0, 0, 0, 238, 239, 528, 0, 242, 0, + 243, 0, 244, 245, 246, 247, 0, 248, 249, 250, + 251, 252, 253, 254, 0, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 0, + 269, 270, 271, 272, 273, 274, 275, 276, 0, 277, + 0, 278, 0, 0, 281, 0, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 0, 291, 0, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 0, + 324, 325, 326, 327, 328, 0, 329, 330, 0, 332, + 0, 333, 334, 335, 336, 337, 338, 0, 339, 340, + 0, 0, 341, 342, 343, 0, 0, 344, 345, 346, + 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 364, 0, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 0, 431, 432, 433, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 530, 448, 449, 0, 0, 450, 451, 0, + 452, 0, 454, 455, 456, 457, 458, 0, 459, 829, + 461, 0, 0, 830, 463, 464, 465, 466, 0, 467, + 468, 469, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 488, 0, 489, 0, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 926, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 954, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 130, 131, 0, 132, 133, 134, 0, 136, 137, + 138, 139, 140, 0, 142, 143, 0, 144, 145, 146, + 147, 148, 149, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 0, 157, 158, 159, 160, 161, 0, 0, + 0, 163, 164, 165, 166, 167, 168, 0, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 0, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 0, 229, + 0, 230, 231, 232, 233, 0, 234, 0, 235, 0, + 0, 0, 238, 239, 528, 0, 242, 0, 243, 0, + 244, 245, 246, 247, 0, 248, 249, 250, 251, 252, + 1309, 254, 0, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 0, 269, 270, + 271, 272, 273, 274, 275, 276, 0, 277, 0, 278, + 0, 0, 281, 0, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 0, 291, 0, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 0, 324, 325, + 326, 327, 328, 0, 329, 330, 0, 332, 0, 333, + 334, 335, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 346, 0, 348, + 0, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 364, + 0, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 383, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 0, 431, 432, 433, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 530, 448, 449, 0, 0, 450, 451, 0, 452, 0, + 454, 455, 456, 457, 458, 0, 459, 460, 461, 0, + 0, 462, 463, 464, 465, 466, 0, 467, 468, 469, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 488, 0, 489, 0, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 527, + 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, + 131, 0, 132, 133, 134, 0, 136, 137, 138, 139, + 140, 0, 142, 143, 0, 144, 145, 146, 147, 148, + 149, 0, 0, 150, 151, 152, 153, 154, 155, 156, + 0, 157, 158, 159, 160, 161, 0, 0, 0, 163, + 164, 165, 166, 167, 168, 0, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 0, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 208, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 0, 229, 0, 230, + 231, 232, 233, 0, 234, 0, 235, 0, 0, 0, + 238, 239, 528, 0, 242, 0, 243, 0, 244, 245, + 246, 247, 0, 248, 249, 250, 251, 252, 1311, 254, + 0, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 0, 269, 270, 271, 272, + 273, 274, 275, 276, 0, 277, 0, 278, 0, 0, + 281, 0, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 0, 291, 0, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 0, 324, 325, 326, 327, + 328, 0, 329, 330, 0, 332, 0, 333, 334, 335, + 336, 337, 338, 0, 339, 340, 0, 0, 341, 342, + 343, 0, 0, 344, 345, 346, 0, 348, 0, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 364, 0, 366, + 367, 368, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 0, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 0, + 0, 431, 432, 433, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 530, 448, + 449, 0, 0, 450, 451, 0, 452, 0, 454, 455, + 456, 457, 458, 0, 459, 460, 461, 0, 0, 462, + 463, 464, 465, 466, 0, 467, 468, 469, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 487, + 488, 0, 489, 0, 491, 492, 493, 494, 495, 496, + 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 527, 0, 553, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 118, 119, 120, 121, + 122, 123, 124, 125, 0, 126, 127, 128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 130, 131, 0, + 132, 133, 134, 0, 136, 137, 138, 139, 140, 0, + 142, 143, 0, 144, 145, 146, 147, 148, 149, 0, + 0, 150, 151, 152, 153, 154, 155, 156, 0, 157, + 158, 159, 160, 161, 0, 0, 0, 163, 164, 165, + 166, 167, 168, 0, 170, 171, 172, 0, 173, 174, + 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 0, 195, 0, 196, 197, 198, 199, 200, 201, + 0, 0, 202, 203, 204, 205, 0, 0, 206, 207, + 208, 209, 210, 0, 211, 212, 213, 0, 214, 215, + 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 0, 229, 0, 230, 231, 232, + 233, 0, 234, 0, 235, 0, 0, 0, 238, 239, + 528, 0, 242, 0, 243, 0, 244, 245, 246, 247, + 0, 248, 249, 250, 251, 252, 1314, 254, 0, 256, + 257, 258, 259, 0, 260, 261, 262, 263, 264, 265, + 266, 0, 267, 0, 269, 270, 271, 272, 273, 274, + 275, 276, 0, 277, 0, 278, 0, 0, 281, 0, + 283, 284, 285, 286, 287, 288, 0, 0, 289, 0, + 291, 0, 0, 293, 294, 295, 296, 297, 298, 299, + 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 0, 324, 325, 326, 327, 328, 0, + 329, 330, 0, 332, 0, 333, 334, 335, 336, 337, + 338, 0, 339, 340, 0, 0, 341, 342, 343, 0, + 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 0, + 0, 0, 0, 362, 363, 364, 0, 366, 367, 368, + 369, 370, 371, 0, 372, 373, 374, 375, 376, 377, + 0, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 0, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 0, 401, 402, 0, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, 416, 417, 418, 419, 420, 0, 0, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 0, 0, 431, + 432, 433, 434, 0, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 530, 448, 449, 0, + 0, 450, 451, 0, 452, 0, 454, 455, 456, 457, + 458, 0, 459, 460, 461, 0, 0, 462, 463, 464, + 465, 466, 0, 467, 468, 469, 470, 471, 472, 473, + 474, 0, 0, 475, 476, 477, 0, 478, 479, 480, + 481, 0, 482, 483, 484, 485, 486, 487, 488, 0, + 489, 0, 491, 492, 493, 494, 495, 496, 497, 0, + 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, + 515, 516, 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 130, 131, 0, 132, 133, + 134, 0, 136, 137, 138, 139, 140, 0, 142, 143, + 0, 144, 145, 146, 147, 148, 149, 0, 0, 150, + 151, 152, 153, 154, 155, 156, 0, 157, 158, 159, + 160, 161, 0, 0, 0, 163, 164, 165, 166, 167, + 168, 0, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 208, 209, + 210, 0, 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 957, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, + 227, 228, 0, 229, 0, 230, 231, 232, 233, 0, + 234, 0, 235, 0, 0, 0, 238, 239, 528, 0, + 242, 0, 243, 0, 244, 245, 246, 247, 0, 248, + 249, 250, 251, 252, 1316, 254, 0, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 0, 269, 270, 271, 272, 273, 274, 275, 276, + 0, 277, 0, 278, 0, 0, 281, 0, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 0, 291, 0, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 0, 324, 325, 326, 327, 328, 0, 329, 330, + 0, 332, 0, 333, 334, 335, 336, 337, 338, 0, + 339, 340, 0, 0, 341, 342, 343, 0, 0, 344, + 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 364, 0, 366, 367, 368, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 383, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, + 417, 418, 419, 420, 0, 0, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 0, 0, 431, 432, 433, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 530, 448, 449, 0, 0, 450, + 451, 0, 452, 0, 454, 455, 456, 457, 458, 0, + 459, 460, 461, 0, 0, 462, 463, 464, 465, 466, + 0, 467, 468, 469, 470, 471, 472, 473, 474, 0, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 487, 488, 0, 489, 0, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, + 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 527, 0, 553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 1000, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 0, 0, 0, 0, + 0, 0, 118, 119, 120, 121, 122, 123, 124, 125, + 0, 126, 127, 128, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 131, 0, 132, 133, 134, 0, + 136, 137, 138, 139, 140, 0, 142, 143, 0, 144, + 145, 146, 147, 148, 149, 0, 0, 150, 151, 152, + 153, 154, 155, 156, 0, 157, 158, 159, 160, 161, + 0, 0, 0, 163, 164, 165, 166, 167, 168, 0, + 170, 171, 172, 0, 173, 174, 175, 176, 177, 178, + 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 0, 195, 0, + 196, 197, 198, 199, 200, 201, 0, 0, 202, 203, + 204, 205, 0, 0, 206, 207, 208, 209, 210, 0, + 211, 212, 213, 0, 214, 215, 216, 0, 217, 218, + 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 0, 229, 0, 230, 231, 232, 233, 0, 234, 0, + 235, 0, 0, 0, 238, 239, 528, 0, 242, 0, + 243, 0, 244, 245, 246, 247, 0, 248, 249, 250, + 251, 252, 2244, 254, 0, 256, 257, 258, 259, 0, + 260, 261, 262, 263, 264, 265, 266, 0, 267, 0, + 269, 270, 271, 272, 273, 274, 275, 276, 0, 277, + 0, 278, 0, 0, 281, 0, 283, 284, 285, 286, + 287, 288, 0, 0, 289, 0, 291, 0, 0, 293, + 294, 295, 296, 297, 298, 299, 300, 529, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 319, 320, 321, 322, 0, + 324, 325, 326, 327, 328, 0, 329, 330, 0, 332, + 0, 333, 334, 335, 336, 337, 338, 0, 339, 340, + 0, 0, 341, 342, 343, 0, 0, 344, 345, 346, + 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 0, 0, 0, 0, 362, + 363, 364, 0, 366, 367, 368, 369, 370, 371, 0, + 372, 373, 374, 375, 376, 377, 0, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 0, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 0, 401, 402, 0, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 0, 0, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 0, 0, 431, 432, 433, 434, 0, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 530, 448, 449, 0, 0, 450, 451, 0, + 452, 0, 454, 455, 456, 457, 458, 0, 459, 460, + 461, 0, 0, 462, 463, 464, 465, 466, 0, 467, + 468, 469, 470, 471, 472, 473, 474, 0, 0, 475, + 476, 477, 0, 478, 479, 480, 481, 0, 482, 483, + 484, 485, 486, 487, 488, 0, 489, 0, 491, 492, + 493, 494, 495, 496, 497, 0, 0, 498, 0, 0, + 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 1482, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 1023, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 1483, 0, 0, -793, 0, + 1484, 130, 131, 0, 132, 133, 134, 1485, 136, 137, + 138, 0, 1486, 1487, 1488, 1489, 0, 144, 145, 146, + 147, 148, 149, 0, 0, 150, 151, 152, 153, 1490, + 1491, 156, 0, 157, 158, 159, 160, 0, 0, 1492, + 0, 1493, 164, 165, 166, 167, 168, 1494, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 1495, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 1496, 191, 192, 1497, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 1063, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 0, 222, 223, 224, 225, 226, 227, 0, 0, 229, + 0, 230, 231, 1498, 233, 0, 234, 0, 235, 1499, + 0, 1500, 238, 239, -793, 1501, 242, 0, 243, 0, + 0, 0, 246, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 1502, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 1503, 0, 270, + 271, 272, 273, 274, 1504, 1505, 0, 1506, 0, 278, + 1507, 1508, 281, 1509, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 1510, 291, 1511, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 1512, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 1513, 1514, 1515, 325, + 326, 327, 0, 0, 329, 330, 1516, 332, 0, 0, + 334, 1517, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 0, 1518, 348, + 1519, 0, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 0, + 1520, 366, 367, 0, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 381, 382, + 1521, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 1522, 404, 405, 406, 1523, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 1524, 421, 422, 423, 424, 425, 426, 1525, 428, + 429, 0, 1526, 431, 432, 1527, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 1528, 448, 0, 0, 0, 450, 451, 0, 452, 1529, + 454, 455, 456, 457, 458, 0, 459, 1530, 1531, 0, + 0, 462, 463, 0, 465, 0, 0, 467, 468, 1532, + 470, 471, 472, 473, 474, 1533, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 0, 1534, 0, 489, 1535, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 527, 0, 553, 0, 0, 0, + 0, 0, 0, 0, 0, 516, 517, 518, 519, 0, + 0, 0, 0, 118, 119, 120, 121, 122, 123, 124, + 125, 0, 126, 127, 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 130, 131, 0, 132, 133, 134, + 0, 136, 137, 138, 139, 140, 0, 142, 143, 0, + 144, 145, 146, 147, 148, 149, 0, 0, 150, 151, + 152, 153, 154, 155, 156, 0, 157, 158, 159, 160, + 161, 0, 0, 0, 163, 164, 165, 166, 167, 168, + 0, 170, 171, 172, 0, 173, 174, 175, 176, 177, + 178, 0, 0, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 0, 195, + 0, 196, 197, 198, 199, 200, 201, 0, 0, 202, + 203, 204, 205, 0, 0, 206, 207, 208, 209, 210, + 0, 211, 212, 213, 0, 214, 215, 216, 0, 217, + 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 0, 229, 0, 230, 231, 232, 233, 0, 234, + 0, 235, 0, 0, 0, 238, 239, 528, 0, 242, + 0, 243, 0, 244, 245, 246, 247, 0, 248, 249, + 250, 251, 252, 2992, 254, 0, 256, 257, 258, 259, + 0, 260, 261, 262, 263, 264, 265, 266, 0, 267, + 0, 269, 270, 271, 272, 273, 274, 275, 276, 0, + 277, 0, 278, 0, 0, 281, 0, 283, 284, 285, + 286, 287, 288, 0, 0, 289, 0, 291, 0, 0, + 293, 294, 295, 296, 297, 298, 299, 300, 529, 302, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 0, 324, 325, 326, 327, 328, 0, 329, 330, 0, + 332, 0, 333, 334, 335, 336, 337, 338, 0, 339, + 340, 0, 0, 341, 342, 343, 0, 0, 344, 345, + 346, 0, 348, 0, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 0, 0, 0, 0, + 362, 363, 364, 0, 366, 367, 368, 369, 370, 371, + 0, 372, 373, 374, 375, 376, 377, 0, 378, 379, + 380, 381, 382, 383, 384, 385, 386, 387, 0, 388, + 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 0, 401, 402, 0, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, + 418, 419, 420, 0, 0, 421, 422, 423, 424, 425, + 426, 427, 428, 429, 0, 0, 431, 432, 433, 434, + 0, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, 530, 448, 449, 0, 0, 450, 451, + 0, 452, 0, 454, 455, 456, 457, 458, 0, 459, + 460, 461, 0, 0, 462, 463, 464, 465, 466, 0, + 467, 468, 469, 470, 471, 472, 473, 474, 0, 0, + 475, 476, 477, 0, 478, 479, 480, 481, 0, 482, + 483, 484, 485, 486, 487, 488, 0, 489, 0, 491, + 492, 493, 494, 495, 496, 497, 0, 0, 498, 0, + 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, + 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, + 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 822, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, + 0, 118, 119, 120, 121, 122, 123, 124, 125, 0, + 126, 127, 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 130, 131, 0, 132, 133, 134, 0, 136, + 137, 138, 139, 140, 0, 142, 143, 0, 144, 145, + 146, 147, 148, 149, 0, 0, 150, 151, 152, 153, + 154, 155, 156, 0, 157, 158, 159, 160, 161, 0, + 0, 0, 163, 164, 165, 166, 167, 168, 0, 170, + 171, 172, 0, 173, 174, 175, 176, 177, 178, 0, + 0, 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 0, 195, 0, 196, + 197, 198, 199, 200, 201, 0, 0, 202, 203, 204, + 205, 0, 0, 206, 207, 208, 209, 210, 0, 211, + 212, 213, 0, 214, 215, 216, 0, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 0, + 229, 0, 230, 231, 232, 233, 0, 234, 0, 235, + 0, 0, 0, 238, 239, 528, 0, 242, 0, 243, + 0, 244, 245, 246, 247, 0, 248, 249, 250, 251, + 252, 253, 254, 0, 256, 257, 258, 259, 0, 260, + 261, 262, 263, 264, 265, 266, 0, 267, 0, 269, + 270, 271, 272, 273, 274, 275, 276, 0, 277, 0, + 278, 0, 0, 281, 0, 283, 284, 285, 286, 287, + 288, 0, 0, 289, 0, 291, 0, 0, 293, 294, + 295, 296, 297, 298, 299, 300, 529, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 0, 324, + 325, 326, 327, 328, 0, 329, 330, 0, 332, 0, + 333, 334, 335, 336, 337, 338, 0, 339, 340, 0, + 0, 341, 342, 343, 0, 0, 344, 345, 346, 0, + 348, 0, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, 361, 0, 0, 0, 0, 362, 363, + 364, 0, 366, 367, 368, 369, 370, 371, 0, 372, + 373, 374, 375, 376, 377, 0, 378, 379, 380, 381, + 382, 383, 384, 385, 386, 387, 0, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 0, 0, 421, 422, 423, 424, 425, 426, 427, + 428, 429, 0, 0, 431, 432, 433, 434, 0, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, 530, 448, 449, 0, 0, 450, 451, 0, 452, + 0, 454, 455, 456, 457, 458, 0, 459, 460, 461, + 0, 0, 462, 463, 464, 465, 466, 0, 467, 468, + 469, 470, 471, 472, 473, 474, 0, 0, 475, 476, + 477, 0, 478, 479, 480, 481, 0, 482, 483, 484, + 485, 486, 487, 488, 0, 489, 0, 491, 492, 493, + 494, 495, 496, 497, 0, 0, 498, 0, 0, 499, + 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, + 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, + 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, + 119, 120, 121, 122, 123, 124, 125, 0, 126, 127, + 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 130, 131, 0, 132, 133, 134, 0, 136, 137, 138, + 139, 140, 0, 142, 143, 0, 144, 145, 146, 147, + 148, 149, 0, 0, 150, 151, 152, 153, 154, 155, + 156, 0, 157, 158, 159, 160, 161, 0, 0, 0, + 163, 164, 165, 166, 167, 168, 0, 170, 171, 172, + 0, 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, + 191, 192, 193, 194, 0, 195, 0, 196, 197, 198, + 199, 200, 201, 0, 0, 202, 203, 204, 205, 0, + 0, 206, 207, 208, 209, 210, 0, 211, 212, 213, + 0, 214, 215, 216, 0, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 0, 229, 0, + 230, 231, 232, 233, 0, 234, 0, 235, 0, 0, + 0, 238, 239, 528, 0, 840, 0, 243, 0, 244, + 245, 246, 247, 0, 248, 249, 250, 251, 252, 253, + 254, 0, 256, 257, 258, 259, 0, 260, 261, 262, + 263, 264, 265, 266, 0, 267, 0, 269, 270, 271, + 272, 273, 274, 275, 276, 0, 277, 0, 278, 0, + 0, 281, 0, 283, 284, 285, 286, 287, 288, 0, + 0, 289, 0, 291, 0, 0, 293, 294, 841, 296, + 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, + 317, 318, 319, 320, 321, 322, 0, 324, 325, 326, + 327, 328, 0, 329, 330, 0, 332, 0, 333, 334, + 335, 336, 337, 338, 0, 339, 340, 0, 0, 341, + 342, 343, 0, 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 826, 457, 0, 0, 827, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, + 360, 361, 0, 0, 0, 0, 362, 363, 364, 0, + 366, 367, 368, 369, 370, 371, 0, 372, 373, 374, + 375, 376, 377, 0, 378, 379, 380, 381, 382, 383, + 384, 385, 386, 387, 0, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 0, 401, + 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, + 842, 413, 414, 415, 416, 417, 418, 419, 420, 0, + 0, 421, 422, 423, 424, 843, 426, 427, 428, 429, + 0, 0, 431, 432, 433, 434, 0, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, 530, + 448, 449, 0, 0, 450, 451, 0, 452, 0, 454, + 455, 456, 457, 458, 0, 459, 844, 461, 0, 0, + 462, 463, 464, 465, 466, 0, 467, 468, 469, 470, + 471, 472, 473, 474, 0, 0, 475, 476, 477, 0, + 478, 479, 480, 481, 0, 482, 483, 484, 485, 486, + 487, 488, 0, 489, 0, 491, 492, 493, 494, 495, + 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 512, 513, 514, 515, 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 1303, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 1305, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 118, 119, 120, + 121, 122, 123, 124, 125, 0, 126, 127, 128, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 130, 131, + 0, 132, 133, 134, 0, 136, 137, 138, 139, 140, + 0, 142, 143, 0, 144, 145, 146, 147, 148, 149, + 0, 0, 150, 151, 152, 153, 154, 155, 156, 0, + 157, 158, 159, 160, 161, 0, 0, 0, 163, 164, + 165, 166, 167, 168, 0, 170, 171, 172, 0, 173, + 174, 175, 176, 177, 178, 0, 0, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 0, 195, 0, 196, 197, 198, 199, 200, + 201, 0, 0, 202, 203, 204, 205, 0, 0, 206, + 207, 208, 209, 210, 0, 211, 212, 213, 0, 214, + 215, 216, 0, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 0, 229, 0, 230, 231, + 232, 233, 0, 234, 0, 235, 0, 0, 0, 238, + 239, 528, 0, 242, 0, 243, 0, 244, 245, 246, + 247, 0, 248, 249, 250, 251, 252, 956, 254, 0, + 256, 257, 258, 259, 0, 260, 261, 262, 263, 264, + 265, 266, 0, 267, 0, 269, 270, 271, 272, 273, + 274, 275, 276, 0, 277, 0, 278, 0, 0, 281, + 0, 283, 284, 285, 286, 287, 288, 0, 0, 289, + 0, 291, 0, 0, 293, 294, 295, 296, 297, 298, + 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 0, 324, 325, 326, 327, 328, + 0, 329, 330, 0, 332, 0, 333, 334, 335, 336, + 337, 338, 0, 339, 340, 0, 0, 341, 342, 343, + 0, 0, 344, 345, 346, 0, 348, 0, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 0, 0, 0, 0, 362, 363, 364, 0, 366, 367, + 368, 369, 370, 371, 0, 372, 373, 374, 375, 376, + 377, 0, 378, 379, 380, 381, 382, 383, 384, 385, + 386, 387, 0, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 0, 401, 402, 0, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, 415, 416, 417, 418, 419, 420, 0, 0, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 0, 0, + 431, 432, 433, 434, 0, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, 530, 448, 449, + 0, 0, 450, 451, 0, 452, 0, 454, 455, 456, + 457, 458, 0, 459, 460, 461, 0, 0, 462, 463, + 464, 465, 466, 0, 467, 468, 469, 470, 471, 472, + 473, 474, 0, 0, 475, 476, 477, 0, 478, 479, + 480, 481, 0, 482, 483, 484, 485, 486, 487, 488, + 0, 489, 0, 491, 492, 493, 494, 495, 496, 497, + 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, + 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, + 514, 515, 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 1308, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 1310, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 549, 0, 0, 0, + 0, 0, 0, 0, 0, 118, 119, 120, 121, 122, + 123, 124, 125, 0, 126, 127, 128, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 130, 131, 0, 132, + 133, 134, 0, 136, 137, 138, 139, 140, 0, 142, + 143, 0, 144, 145, 146, 147, 148, 149, 0, 0, + 150, 151, 152, 153, 154, 155, 156, 0, 157, 158, + 159, 160, 161, 0, 0, 0, 163, 164, 165, 166, + 167, 168, 0, 170, 171, 172, 0, 173, 174, 175, + 176, 177, 178, 0, 0, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 0, 195, 0, 196, 197, 198, 199, 200, 201, 0, + 0, 202, 203, 204, 205, 0, 0, 206, 207, 208, + 209, 210, 0, 211, 212, 213, 0, 214, 215, 216, + 0, 217, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 0, 229, 0, 230, 231, 232, 233, + 0, 234, 0, 235, 0, 0, 0, 238, 239, 528, + 0, 242, 0, 243, 0, 244, 245, 246, 247, 0, + 248, 249, 250, 251, 252, 253, 254, 0, 256, 257, + 258, 259, 0, 260, 261, 262, 263, 264, 265, 266, + 0, 267, 0, 269, 270, 271, 272, 273, 274, 275, + 276, 0, 277, 0, 278, 0, 0, 281, 0, 283, + 284, 285, 286, 287, 288, 0, 0, 289, 0, 291, + 0, 0, 293, 294, 295, 296, 297, 298, 299, 300, + 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 0, 324, 325, 326, 327, 328, 0, 329, + 330, 0, 332, 0, 333, 334, 335, 336, 337, 338, + 0, 339, 340, 0, 0, 341, 342, 343, 0, 0, + 344, 345, 346, 0, 348, 0, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, 0, 0, + 0, 0, 362, 363, 364, 0, 366, 367, 368, 369, + 370, 371, 0, 372, 373, 374, 375, 376, 377, 0, + 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, + 0, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 0, 401, 402, 0, 404, 405, + 406, 407, 408, 409, 410, 411, 842, 413, 414, 415, + 416, 417, 418, 419, 420, 0, 0, 421, 422, 423, + 424, 425, 426, 427, 428, 429, 0, 0, 431, 432, + 433, 434, 0, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, 530, 448, 449, 0, 0, + 450, 451, 0, 452, 0, 454, 455, 456, 457, 458, + 0, 459, 844, 461, 0, 0, 462, 463, 464, 465, + 466, 0, 467, 468, 469, 470, 471, 472, 473, 474, + 0, 0, 475, 476, 477, 0, 478, 479, 480, 481, + 0, 482, 483, 484, 485, 486, 487, 488, 0, 489, + 0, 491, 492, 493, 494, 495, 496, 497, 0, 0, + 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, + 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, + 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 2229, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 1476, + 0, 0, 0, 118, 119, 120, 121, 122, 123, 124, + 125, 0, 126, 127, 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 130, 131, 0, 132, 133, 134, + 0, 136, 137, 138, 139, 140, 0, 142, 143, 0, + 144, 145, 146, 147, 148, 149, 0, 0, 150, 151, + 152, 153, 154, 155, 156, 0, 157, 158, 159, 160, + 161, 0, 0, 0, 163, 164, 165, 166, 167, 168, + 0, 170, 171, 172, 0, 173, 174, 175, 176, 177, + 178, 0, 0, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 0, 195, + 0, 196, 197, 198, 199, 200, 201, 0, 0, 202, + 203, 204, 205, 0, 0, 206, 207, 208, 209, 210, + 0, 211, 212, 213, 0, 214, 215, 216, 0, 217, + 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 0, 229, 0, 230, 231, 232, 233, 0, 234, + 0, 235, 0, 0, 0, 238, 239, 528, 0, 242, + 0, 243, 0, 244, 245, 246, 247, 0, 248, 249, + 250, 251, 252, 1318, 254, 0, 256, 257, 258, 259, + 0, 260, 261, 262, 263, 264, 265, 266, 0, 267, + 0, 269, 270, 271, 272, 273, 274, 275, 276, 0, + 277, 0, 278, 0, 0, 281, 0, 283, 284, 285, + 286, 287, 288, 0, 0, 289, 0, 291, 0, 0, + 293, 294, 295, 296, 297, 298, 299, 300, 529, 302, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 0, 324, 325, 326, 327, 328, 0, 329, 330, 0, + 332, 0, 333, 334, 335, 336, 337, 338, 0, 339, + 340, 0, 0, 341, 342, 343, 0, 0, 344, 345, + 346, 0, 348, 0, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 0, 0, 0, 0, + 362, 363, 364, 0, 366, 367, 368, 369, 370, 371, + 0, 372, 373, 374, 375, 376, 377, 0, 378, 379, + 380, 381, 382, 383, 384, 385, 386, 387, 0, 388, + 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 0, 401, 402, 0, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, + 418, 419, 420, 0, 0, 421, 422, 423, 424, 425, + 426, 427, 428, 429, 0, 0, 431, 432, 433, 434, + 0, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, 530, 448, 449, 0, 0, 450, 451, + 0, 452, 0, 454, 455, 456, 457, 458, 0, 459, + 460, 461, 0, 0, 462, 463, 464, 465, 466, 0, + 467, 468, 469, 470, 471, 472, 473, 474, 0, 0, + 475, 476, 477, 0, 478, 479, 480, 481, 0, 482, + 483, 484, 485, 486, 487, 488, 0, 489, 0, 491, + 492, 493, 494, 495, 496, 497, 0, 0, 498, 0, + 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, + 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, + 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 1477, 0, 0, -788, 0, 1478, 129, - 130, 0, 131, 132, 133, 1479, 135, 136, 137, 0, - 1480, 1481, 1482, 1483, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 1484, 1485, 155, - 0, 156, 157, 158, 159, 0, 0, 1486, 0, 1487, - 163, 164, 165, 166, 167, 1488, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 1489, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 1490, 190, - 191, 1491, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 1059, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 0, 221, - 222, 223, 224, 225, 0, 0, 227, 0, 228, 229, - 1492, 231, 0, 232, 0, 233, 1493, 0, 1494, 236, - 237, -788, 1495, 240, 0, 241, 0, 0, 0, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 1496, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 1497, 0, 268, 269, 270, 271, - 272, 1498, 1499, 0, 1500, 0, 276, 1501, 1502, 279, - 1503, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 1504, 289, 1505, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 1506, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 1507, 1508, 1509, 323, 324, 325, 0, - 0, 327, 328, 1510, 330, 0, 0, 332, 1511, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 0, 1512, 346, 1513, 0, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 0, 1514, 364, 365, - 0, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 1515, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 1516, 400, 401, - 402, 1517, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 1518, 417, 418, 419, - 420, 421, 422, 1519, 424, 425, 0, 1520, 427, 428, - 1521, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 1522, 444, 0, 0, 0, - 446, 447, 0, 448, 1523, 450, 451, 452, 453, 454, - 0, 455, 1524, 1525, 0, 0, 458, 459, 0, 461, - 0, 0, 463, 464, 1526, 466, 467, 468, 469, 470, - 1527, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 0, 1528, 0, 485, - 1529, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 523, - 0, 549, 0, 0, 0, 0, 0, 0, 0, 0, - 512, 513, 514, 515, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, + 0, 118, 119, 120, 121, 122, 123, 124, 125, 0, + 126, 127, 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 130, 131, 0, 132, 133, 134, 0, 136, + 137, 138, 139, 140, 0, 142, 143, 0, 144, 145, + 146, 147, 148, 149, 0, 0, 150, 151, 152, 153, + 154, 155, 156, 0, 157, 158, 159, 160, 161, 0, + 0, 0, 163, 164, 165, 166, 167, 168, 0, 170, + 171, 172, 0, 173, 174, 175, 176, 177, 178, 0, + 0, 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 0, 195, 0, 196, + 197, 198, 199, 200, 201, 0, 0, 202, 203, 204, + 205, 0, 0, 206, 207, 208, 209, 210, 0, 211, + 212, 213, 0, 214, 215, 216, 0, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 0, + 229, 0, 230, 231, 232, 233, 0, 234, 0, 235, + 0, 0, 0, 238, 239, 528, 0, 242, 0, 243, + 0, 244, 245, 246, 247, 0, 248, 249, 250, 251, + 252, 1329, 254, 0, 256, 257, 258, 259, 0, 260, + 261, 262, 263, 264, 265, 266, 0, 267, 0, 269, + 270, 271, 272, 273, 274, 275, 276, 0, 277, 0, + 278, 0, 0, 281, 0, 283, 284, 285, 286, 287, + 288, 0, 0, 289, 0, 291, 0, 0, 293, 294, + 295, 296, 297, 298, 299, 300, 529, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 0, 324, + 325, 326, 327, 328, 0, 329, 330, 0, 332, 0, + 333, 334, 335, 336, 337, 338, 0, 339, 340, 0, + 0, 341, 342, 343, 0, 0, 344, 345, 346, 0, + 348, 0, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, 361, 0, 0, 0, 0, 362, 363, + 364, 0, 366, 367, 368, 369, 370, 371, 0, 372, + 373, 374, 375, 376, 377, 0, 378, 379, 380, 381, + 382, 383, 384, 385, 386, 387, 0, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 0, 401, 402, 0, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 0, 0, 421, 422, 423, 424, 425, 426, 427, + 428, 429, 0, 0, 431, 432, 433, 434, 0, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, 530, 448, 449, 0, 0, 450, 451, 0, 452, + 0, 454, 455, 456, 457, 458, 0, 459, 460, 461, + 0, 0, 462, 463, 464, 465, 466, 0, 467, 468, + 469, 470, 471, 472, 473, 474, 0, 0, 475, 476, + 477, 0, 478, 479, 480, 481, 0, 482, 483, 484, + 485, 486, 487, 488, 0, 489, 0, 491, 492, 493, + 494, 495, 496, 497, 0, 0, 498, 0, 0, 499, + 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, + 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, + 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, + 119, 120, 121, 122, 123, 124, 125, 0, 126, 127, + 128, 0, 0, 0, 0, 0, 0, 1678, 0, 0, + 130, 131, 0, 132, 133, 134, 0, 136, 137, 138, + 139, 140, 0, 142, 143, 0, 144, 145, 146, 147, + 148, 149, 0, 0, 150, 151, 152, 153, 154, 155, + 156, 0, 157, 158, 159, 160, 161, 0, 0, 0, + 163, 164, 165, 166, 167, 168, 0, 170, 171, 172, + 0, 173, 174, 175, 176, 177, 178, 0, 0, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 2974, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, + 191, 192, 193, 194, 0, 195, 0, 196, 197, 198, + 199, 200, 201, 0, 0, 202, 203, 204, 205, 0, + 0, 206, 207, 208, 209, 210, 0, 211, 212, 213, + 0, 214, 215, 216, 0, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 0, 229, 0, + 230, 231, 232, 233, 0, 234, 0, 235, 0, 0, + 0, 238, 239, 528, 0, 242, 0, 243, 0, 244, + 245, 246, 247, 0, 248, 249, 250, 251, 252, 253, + 254, 0, 256, 257, 258, 259, 0, 260, 261, 262, + 263, 264, 265, 266, 0, 267, 0, 269, 270, 271, + 272, 273, 274, 275, 276, 0, 277, 0, 278, 0, + 0, 281, 0, 283, 284, 285, 286, 287, 288, 0, + 0, 289, 0, 291, 0, 0, 293, 294, 295, 296, + 297, 298, 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, + 317, 318, 319, 320, 321, 322, 0, 324, 325, 326, + 327, 328, 0, 329, 330, 0, 332, 0, 333, 334, + 335, 336, 337, 338, 0, 339, 340, 0, 0, 341, + 342, 343, 0, 0, 344, 345, 346, 0, 348, 0, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, + 360, 361, 0, 0, 0, 0, 362, 363, 364, 0, + 366, 367, 368, 369, 370, 371, 0, 372, 373, 374, + 375, 376, 377, 0, 378, 379, 380, 381, 382, 383, + 384, 385, 386, 387, 0, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 0, 401, + 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 416, 417, 418, 419, 420, 0, + 0, 421, 422, 423, 424, 425, 0, 427, 428, 429, + 0, 0, 431, 432, 433, 434, 0, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, 530, + 448, 449, 0, 0, 450, 451, 0, 452, 0, 454, + 455, 456, 457, 458, 0, 459, 460, 461, 0, 0, + 462, 463, 464, 465, 466, 0, 467, 468, 469, 470, + 471, 472, 473, 474, 0, 0, 475, 476, 477, 0, + 478, 479, 480, 481, 0, 482, 483, 484, 485, 486, + 487, 488, 0, 489, 0, 491, 492, 493, 494, 495, + 496, 497, 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 0, 0, 0, 0, + 512, 513, 514, 515, 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, + 0, 0, 0, 0, 0, 0, 0, 118, 119, 120, + 121, 122, 123, 124, 125, 0, 126, 127, 128, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 130, 131, + 0, 132, 133, 134, 0, 136, 137, 138, 139, 140, + 0, 142, 143, 0, 144, 145, 146, 147, 148, 149, + 0, 0, 150, 151, 152, 153, 154, 155, 156, 0, + 157, 158, 159, 160, 161, 0, 0, 0, 163, 164, + 165, 166, 167, 168, 0, 170, 171, 172, 0, 173, + 174, 175, 176, 177, 178, 0, 0, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 0, 195, 0, 196, 197, 198, 199, 200, + 201, 0, 0, 202, 203, 204, 205, 0, 0, 206, + 207, 208, 209, 210, 0, 211, 212, 213, 0, 214, + 215, 216, 0, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 0, 229, 0, 230, 231, + 232, 233, 0, 234, 0, 235, 0, 0, 0, 238, + 239, 528, 0, 242, 0, 243, 0, 244, 245, 246, + 247, 0, 248, 249, 250, 251, 252, 1858, 254, 0, + 256, 257, 258, 259, 0, 260, 261, 262, 263, 264, + 265, 266, 0, 267, 0, 269, 270, 271, 272, 273, + 274, 275, 276, 0, 277, 0, 278, 0, 0, 281, + 0, 283, 284, 285, 286, 287, 288, 0, 0, 289, + 0, 291, 0, 0, 293, 294, 295, 296, 297, 298, + 299, 300, 529, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 0, 324, 325, 326, 327, 328, + 0, 329, 330, 0, 332, 0, 333, 334, 335, 336, + 337, 338, 0, 339, 340, 0, 0, 341, 342, 343, + 0, 0, 344, 345, 346, 0, 348, 0, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 0, 0, 0, 0, 362, 363, 364, 0, 366, 367, + 368, 369, 370, 371, 0, 372, 373, 374, 375, 376, + 377, 0, 378, 379, 380, 381, 382, 383, 384, 385, + 386, 387, 0, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 0, 401, 402, 0, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, 415, 416, 417, 418, 419, 420, 0, 0, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 0, 0, + 431, 432, 433, 434, 0, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, 530, 448, 449, + 0, 0, 450, 451, 0, 452, 0, 454, 455, 456, + 457, 458, 0, 459, 460, 461, 0, 0, 462, 463, + 464, 465, 466, 0, 467, 468, 469, 470, 471, 472, + 473, 474, 0, 0, 475, 476, 477, 0, 478, 479, + 480, 481, 0, 482, 483, 484, 485, 486, 487, 488, + 0, 489, 0, 491, 492, 493, 494, 495, 496, 497, + 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, + 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, + 514, 515, 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 837, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 838, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 839, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 840, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 841, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 118, 119, 120, 121, 122, + 123, 124, 125, 0, 126, 127, 128, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 130, 131, 0, 132, + 133, 134, 0, 136, 137, 138, 139, 140, 0, 142, + 143, 0, 144, 145, 146, 147, 148, 149, 0, 0, + 150, 151, 152, 153, 154, 155, 156, 0, 157, 158, + 159, 160, 161, 0, 0, 0, 163, 164, 165, 166, + 167, 168, 0, 170, 171, 172, 0, 173, 174, 175, + 176, 177, 178, 0, 0, 180, 181, 182, 183, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 0, 195, 0, 196, 197, 198, 199, 200, 201, 0, + 0, 202, 203, 204, 205, 0, 0, 206, 207, 208, + 209, 210, 0, 211, 212, 213, 0, 214, 215, 216, + 0, 217, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 0, 229, 0, 230, 231, 232, 233, + 0, 234, 0, 235, 0, 0, 0, 238, 239, 528, + 0, 242, 0, 243, 0, 244, 245, 246, 247, 0, + 248, 249, 250, 251, 252, 2231, 254, 0, 256, 257, + 258, 259, 0, 260, 261, 262, 263, 264, 265, 266, + 0, 267, 0, 269, 270, 271, 272, 273, 274, 275, + 276, 0, 277, 0, 278, 0, 0, 281, 0, 283, + 284, 285, 286, 287, 288, 0, 0, 289, 0, 291, + 0, 0, 293, 294, 295, 296, 297, 298, 299, 300, + 529, 302, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 0, 324, 325, 326, 327, 328, 0, 329, + 330, 0, 332, 0, 333, 334, 335, 336, 337, 338, + 0, 339, 340, 0, 0, 341, 342, 343, 0, 0, + 344, 345, 346, 0, 348, 0, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, 0, 0, + 0, 0, 362, 363, 364, 0, 366, 367, 368, 369, + 370, 371, 0, 372, 373, 374, 375, 376, 377, 0, + 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, + 0, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 0, 401, 402, 0, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, + 416, 417, 418, 419, 420, 0, 0, 421, 422, 423, + 424, 425, 426, 427, 428, 429, 0, 0, 431, 432, + 433, 434, 0, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, 530, 448, 449, 0, 0, + 450, 451, 0, 452, 0, 454, 455, 456, 457, 458, + 0, 459, 460, 461, 0, 0, 462, 463, 464, 465, + 466, 0, 467, 468, 469, 470, 471, 472, 473, 474, + 0, 0, 475, 476, 477, 0, 478, 479, 480, 481, + 0, 482, 483, 484, 485, 486, 487, 488, 0, 489, + 0, 491, 492, 493, 494, 495, 496, 497, 0, 0, + 498, 0, 0, 499, 500, 501, 502, 503, 504, 505, + 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, + 516, 517, 518, 519, 527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 950, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, + 0, 0, 0, 118, 119, 120, 121, 122, 123, 124, + 125, 0, 126, 127, 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 130, 131, 0, 132, 133, 134, + 0, 136, 137, 138, 139, 140, 0, 142, 143, 0, + 144, 145, 146, 147, 148, 149, 0, 0, 150, 151, + 152, 153, 154, 155, 156, 0, 157, 158, 159, 160, + 161, 0, 0, 0, 163, 164, 165, 166, 167, 168, + 0, 170, 171, 172, 0, 173, 174, 175, 176, 177, + 178, 0, 0, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 0, 195, + 0, 196, 197, 198, 199, 200, 201, 0, 0, 202, + 203, 204, 205, 0, 0, 206, 207, 208, 209, 210, + 0, 211, 212, 213, 0, 214, 215, 216, 0, 217, + 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 0, 229, 0, 230, 231, 232, 233, 0, 234, + 0, 235, 0, 0, 0, 238, 239, 528, 0, 242, + 0, 243, 0, 244, 245, 246, 247, 0, 248, 249, + 250, 251, 252, 2246, 254, 0, 256, 257, 258, 259, + 0, 260, 261, 262, 263, 264, 265, 266, 0, 267, + 0, 269, 270, 271, 272, 273, 274, 275, 276, 0, + 277, 0, 278, 0, 0, 281, 0, 283, 284, 285, + 286, 287, 288, 0, 0, 289, 0, 291, 0, 0, + 293, 294, 295, 296, 297, 298, 299, 300, 529, 302, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 0, 324, 325, 326, 327, 328, 0, 329, 330, 0, + 332, 0, 333, 334, 335, 336, 337, 338, 0, 339, + 340, 0, 0, 341, 342, 343, 0, 0, 344, 345, + 346, 0, 348, 0, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 0, 0, 0, 0, + 362, 363, 364, 0, 366, 367, 368, 369, 370, 371, + 0, 372, 373, 374, 375, 376, 377, 0, 378, 379, + 380, 381, 382, 383, 384, 385, 386, 387, 0, 388, + 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 0, 401, 402, 0, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, + 418, 419, 420, 0, 0, 421, 422, 423, 424, 425, + 426, 427, 428, 429, 0, 0, 431, 432, 433, 434, + 0, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, 530, 448, 449, 0, 0, 450, 451, + 0, 452, 0, 454, 455, 456, 457, 458, 0, 459, + 460, 461, 0, 0, 462, 463, 464, 465, 466, 0, + 467, 468, 469, 470, 471, 472, 473, 474, 0, 0, + 475, 476, 477, 0, 478, 479, 480, 481, 0, 482, + 483, 484, 485, 486, 487, 488, 0, 489, 0, 491, + 492, 493, 494, 495, 496, 497, 0, 0, 498, 0, + 0, 499, 500, 501, 502, 503, 504, 505, 506, 507, + 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, + 518, 519, 1482, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 118, 119, 120, 121, 122, 123, 124, 125, 0, + 126, 127, 128, 0, 0, 0, 1483, 0, 0, 0, + 0, 1484, 130, 131, 0, 132, 133, 134, 1485, 136, + 137, 138, 0, 1486, 1487, 1488, 1489, 0, 144, 145, + 146, 147, 148, 149, 0, 0, 150, 151, 152, 153, + 1490, 1491, 156, 0, 157, 158, 159, 160, 0, 0, + 1492, 0, 1493, 164, 165, 166, 167, 168, 1494, 170, + 171, 172, 0, 173, 174, 175, 176, 177, 178, 0, + 1495, 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 1496, 191, 192, 1497, 194, 0, 195, 0, 196, + 197, 198, 199, 200, 201, 0, 0, 202, 203, 204, + 205, 0, 0, 206, 207, 1063, 209, 210, 0, 211, + 212, 213, 0, 214, 215, 216, 0, 217, 218, 219, + 220, 0, 222, 223, 224, 225, 226, 227, 0, 0, + 229, 0, 230, 231, 1498, 233, 0, 234, 0, 235, + 1499, 0, 1500, 238, 239, 0, 1501, 242, 0, 243, + 0, 0, 0, 246, 247, 0, 248, 249, 250, 251, + 252, 253, 254, 1502, 256, 257, 258, 259, 0, 260, + 261, 262, 263, 264, 265, 266, 0, 267, 1503, 0, + 270, 271, 272, 273, 274, 1504, 1505, 0, 1506, 0, + 278, 1507, 1508, 281, 1509, 283, 284, 285, 286, 287, + 288, 0, 0, 289, 1510, 291, 1511, 0, 293, 294, + 295, 296, 297, 298, 299, 300, 1512, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 1513, 1514, 1515, + 325, 326, 327, 0, 0, 329, 330, 1516, 332, 0, + 0, 334, 1517, 336, 337, 338, 0, 339, 340, 0, + 0, 341, 342, 343, 0, 0, 344, 345, 0, 1518, + 348, 1519, 0, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, 361, 0, 0, 0, 0, 362, 363, + 0, 1520, 366, 367, 0, 369, 370, 371, 0, 372, + 373, 374, 375, 376, 377, 0, 378, 379, 380, 381, + 382, 1521, 384, 385, 386, 387, 0, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 0, 401, 402, 1522, 404, 405, 406, 1523, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 0, 1524, 421, 422, 423, 424, 425, 426, 1525, + 428, 429, 0, 1526, 431, 432, 1527, 434, 0, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, 1528, 448, 0, 0, 0, 450, 451, 0, 452, + 1529, 454, 455, 456, 457, 458, 0, 459, 1530, 1531, + 0, 0, 462, 463, 0, 465, 0, 0, 467, 468, + 1532, 470, 471, 472, 473, 474, 1533, 0, 475, 476, + 477, 0, 478, 479, 480, 481, 0, 482, 483, 484, + 485, 486, 0, 1534, 0, 489, 1535, 491, 492, 493, + 494, 495, 496, 497, 0, 0, 498, 0, 0, 499, + 500, 501, 502, 503, 504, 1482, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 516, 517, 518, 519, + 0, 0, 0, 0, 118, 119, 120, 121, 122, 123, + 124, 125, 0, 126, 127, 128, 0, 0, 0, 1483, + 0, 0, 0, 0, 1484, 130, 131, 0, 132, 133, + 134, 1485, 136, 137, 138, 0, 1486, 1487, 1488, 1489, + 0, 144, 145, 146, 147, 148, 149, 0, 0, 150, + 151, 152, 153, 1490, 1491, 156, 0, 157, 158, 159, + 160, 0, 0, 1492, 0, 1493, 164, 165, 166, 167, + 168, 1494, 170, 171, 172, 0, 173, 174, 175, 176, + 177, 178, 0, 1495, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 1496, 191, 192, 1497, 194, 0, + 195, 0, 196, 197, 198, 199, 200, 201, 0, 0, + 202, 203, 204, 205, 0, 0, 206, 207, 1063, 209, + 210, 0, 211, 212, 213, 0, 1840, 215, 216, 0, + 217, 218, 219, 220, 0, 222, 223, 224, 225, 226, + 227, 0, 0, 229, 0, 230, 231, 1498, 233, 0, + 234, 0, 235, 1499, 0, 1500, 238, 239, 0, 1501, + 242, 0, 243, 0, 0, 0, 246, 247, 0, 248, + 249, 250, 251, 252, 253, 254, 1502, 256, 257, 258, + 259, 0, 260, 261, 262, 263, 264, 265, 266, 0, + 267, 1503, 0, 270, 271, 272, 273, 274, 1504, 1505, + 0, 1506, 0, 278, 1507, 1508, 281, 1509, 283, 284, + 285, 286, 287, 288, 0, 0, 289, 1510, 291, 1511, + 0, 293, 294, 295, 296, 297, 298, 299, 300, 1512, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 1513, 1514, 1515, 325, 326, 327, 0, 0, 329, 330, + 1516, 332, 0, 0, 334, 1517, 336, 337, 338, 0, + 339, 340, 0, 0, 341, 342, 343, 0, 0, 344, + 345, 0, 1518, 348, 1519, 0, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 0, 0, 0, + 0, 362, 363, 0, 1520, 366, 367, 0, 369, 370, + 371, 0, 372, 373, 374, 375, 376, 377, 0, 378, + 379, 380, 381, 382, 1521, 384, 385, 386, 387, 0, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 0, 401, 402, 1522, 404, 405, 406, + 1523, 408, 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 0, 1524, 421, 422, 423, 424, + 425, 426, 1525, 428, 429, 0, 1526, 431, 432, 1527, + 434, 0, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 1528, 448, 0, 0, 0, 450, + 451, 0, 452, 1529, 454, 455, 456, 457, 458, 0, + 459, 1530, 1531, 0, 0, 462, 463, 0, 465, 0, + 0, 467, 468, 1532, 470, 471, 472, 473, 474, 1533, + 0, 475, 476, 477, 0, 478, 479, 480, 481, 0, + 482, 483, 484, 485, 486, 0, 1534, 0, 489, 1535, + 491, 492, 493, 494, 495, 496, 497, 0, 0, 498, + 0, 0, 499, 500, 501, 502, 503, 504, 3162, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 516, + 517, 518, 519, 0, 0, 0, 0, 118, 119, 120, + 121, 122, 123, 124, 125, 0, 126, 127, 128, 0, + 0, 0, 2914, 0, 0, 0, 0, 2915, 130, 131, + 0, 132, 133, 134, 2916, 136, 137, 138, 0, 1486, + 2917, 1488, 1489, 0, 144, 145, 146, 147, 148, 149, + 0, 0, 150, 151, 152, 153, 1490, 1491, 156, 0, + 157, 158, 159, 160, 0, 0, 2918, 0, 2919, 164, + 165, 166, 167, 168, 2920, 170, 171, 172, 0, 173, + 174, 175, 176, 177, 178, 0, 2921, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 1496, 191, 192, + 1497, 194, 0, 195, 0, 196, 197, 198, 199, 200, + 201, 0, 0, 202, 203, 204, 205, 0, 0, 206, + 207, 1063, 209, 210, 0, 211, 212, 213, 0, 214, + 215, 216, 0, 217, 218, 219, 220, 0, 222, 223, + 224, 225, 226, 227, 0, 0, 229, 0, 230, 231, + 1498, 233, 0, 234, 0, 235, 2922, 0, 2923, 238, + 239, 2924, 2925, 242, 0, 243, 0, 0, 0, 246, + 247, 0, 248, 249, 250, 251, 252, 253, 254, 2926, + 256, 257, 258, 259, 0, 260, 261, 262, 263, 264, + 265, 266, 0, 267, 2927, 0, 270, 271, 272, 273, + 274, 1504, 1505, 0, 1506, 0, 278, 2928, 2929, 281, + 2930, 283, 284, 285, 286, 287, 288, 0, 0, 289, + 2931, 291, 2932, 0, 293, 294, 295, 296, 297, 298, + 299, 300, 3163, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 1513, 2934, 1515, 325, 326, 327, 0, + 0, 329, 330, 2936, 332, 0, 0, 334, 1517, 336, + 337, 338, 0, 339, 340, 0, 0, 341, 342, 343, + 0, 0, 344, 345, 0, 2938, 348, 2939, 0, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 0, 0, 0, 0, 362, 363, 0, 2940, 366, 367, + 0, 369, 370, 371, 0, 372, 373, 374, 375, 376, + 377, 0, 378, 379, 380, 381, 382, 1521, 384, 385, + 386, 387, 0, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 0, 401, 402, 2941, + 404, 405, 406, 0, 408, 409, 410, 411, 412, 413, + 414, 415, 416, 417, 418, 419, 420, 0, 2942, 421, + 422, 423, 424, 425, 426, 0, 428, 429, 0, 2944, + 431, 432, 1527, 434, 0, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, 3164, 448, 0, + 0, 0, 450, 451, 0, 452, 2946, 454, 455, 456, + 457, 458, 0, 459, 1530, 1531, 0, 0, 462, 463, + 0, 465, 0, 0, 467, 468, 2947, 470, 471, 472, + 473, 474, 0, 0, 475, 476, 477, 0, 478, 479, + 480, 481, 0, 482, 483, 484, 485, 486, 0, 1534, + 0, 489, 2949, 491, 492, 493, 494, 495, 496, 497, + 0, 0, 498, 0, 0, 499, 500, 501, 502, 503, + 504, 527, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 516, 517, 518, 519, 0, 0, 0, 0, + 118, 119, 120, 121, 122, 123, 124, 125, 0, 126, + 127, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 130, 131, 0, 132, 133, 134, 0, 136, 137, + 138, 139, 140, 0, 142, 143, 0, 144, 145, 146, + 147, 148, 149, 0, 0, 150, 151, 152, 153, 154, + 155, 156, 0, 157, 158, 159, 160, 161, 0, 0, + 0, 163, 164, 165, 166, 167, 168, 0, 170, 171, + 172, 0, 173, 174, 175, 176, 177, 178, 0, 0, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 0, 195, 0, 196, 197, + 198, 199, 200, 201, 0, 0, 202, 203, 204, 205, + 0, 0, 206, 207, 208, 209, 210, 0, 211, 212, + 213, 0, 214, 215, 216, 0, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 0, 229, + 0, 230, 231, 232, 233, 0, 234, 0, 235, 0, + 0, 0, 238, 239, 528, 0, 242, 0, 243, 0, + 244, 245, 0, 247, 0, 248, 249, 250, 251, 252, + 253, 254, 0, 256, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 265, 266, 0, 267, 0, 269, 270, + 271, 272, 273, 274, 275, 276, 0, 277, 0, 278, + 0, 0, 281, 0, 283, 284, 285, 286, 287, 288, + 0, 0, 289, 0, 291, 0, 0, 293, 294, 295, + 296, 297, 298, 299, 300, 529, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 0, 324, 325, + 326, 327, 328, 0, 329, 330, 0, 332, 0, 333, + 334, 335, 336, 337, 338, 0, 339, 340, 0, 0, + 341, 342, 343, 0, 0, 344, 345, 346, 0, 348, + 0, 350, 351, 352, 353, 354, 355, 356, 0, 358, + 359, 360, 361, 0, 0, 0, 0, 362, 363, 364, + 0, 366, 367, 368, 369, 370, 371, 0, 372, 373, + 374, 375, 376, 377, 0, 378, 379, 380, 0, 382, + 383, 384, 385, 386, 387, 0, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 0, + 401, 402, 0, 404, 405, 406, 407, 0, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 0, 0, 421, 422, 423, 424, 425, 426, 427, 428, + 429, 0, 0, 431, 432, 433, 434, 0, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, + 530, 448, 449, 0, 0, 450, 451, 0, 452, 0, + 454, 455, 456, 457, 458, 0, 459, 460, 461, 0, + 0, 462, 463, 464, 465, 466, 0, 467, 468, 469, + 470, 471, 472, 473, 474, 0, 0, 475, 476, 477, + 0, 478, 479, 480, 481, 0, 482, 483, 484, 485, + 486, 487, 488, 0, 489, 0, 491, 492, 493, 494, + 495, 496, 497, 0, 0, 498, 0, 0, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, 519, 1777, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 839, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 841, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 119, + 120, 121, 122, 123, 124, 125, 0, 126, 127, 128, + 0, 0, 0, 1483, 0, 0, 0, 0, 1484, 130, + 131, 0, 132, 133, 134, 1485, 136, 137, 138, 0, + 1486, 1487, 1488, 1489, 0, 144, 145, 146, 147, 148, + 149, 0, 0, 150, 151, 152, 153, 1490, 1491, 156, + 0, 157, 158, 159, 160, 0, 0, 1492, 0, 1493, + 164, 165, 166, 167, 168, 1494, 170, 171, 172, 0, + 173, 174, 175, 176, 177, 178, 0, 1495, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 1496, 191, + 192, 1497, 194, 0, 195, 0, 196, 197, 198, 199, + 200, 201, 0, 0, 202, 203, 204, 205, 0, 0, + 206, 207, 1063, 209, 210, 0, 211, 212, 213, 0, + 214, 215, 216, 0, 217, 218, 219, 220, 0, 222, + 223, 224, 225, 226, 227, 0, 0, 229, 0, 230, + 231, 1498, 233, 0, 234, 0, 235, 1499, 0, 1500, + 238, 239, 0, 1501, 242, 0, 243, 0, 0, 0, + 246, 247, 0, 248, 249, 250, 251, 252, 253, 254, + 1502, 256, 257, 258, 259, 0, 260, 261, 262, 263, + 264, 265, 266, 0, 267, 1503, 0, 270, 271, 272, + 273, 274, 1504, 1505, 0, 1506, 0, 278, 1507, 1508, + 281, 1509, 283, 284, 285, 286, 287, 288, 0, 0, + 289, 1510, 291, 1511, 0, 293, 294, 295, 296, 297, + 298, 299, 300, 0, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 1513, 1514, 1515, 325, 326, 327, + 0, 0, 329, 330, 1516, 332, 0, 0, 334, 1517, + 336, 337, 338, 0, 339, 340, 0, 0, 341, 342, + 343, 0, 0, 344, 345, 0, 1518, 348, 1519, 0, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 0, 0, 0, 0, 362, 363, 0, 1520, 366, + 367, 0, 369, 370, 371, 0, 372, 373, 374, 375, + 376, 377, 0, 378, 379, 380, 381, 382, 1521, 384, + 385, 386, 387, 0, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 0, 401, 402, + 1522, 404, 405, 406, 0, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 0, 1524, + 421, 422, 423, 424, 425, 426, 0, 428, 429, 0, + 1526, 431, 432, 1527, 434, 0, 435, 436, 437, 438, + 439, 440, 441, 442, 443, 444, 445, 446, 0, 448, + 0, 0, 0, 450, 451, 0, 452, 1529, 454, 455, + 456, 457, 458, 0, 459, 1530, 1531, 0, 0, 462, + 463, 0, 465, 0, 0, 467, 468, 1532, 470, 471, + 472, 473, 474, 0, 0, 475, 476, 477, 0, 478, + 479, 480, 481, 0, 482, 483, 484, 485, 486, 0, + 1534, 0, 489, 1535, 491, 492, 493, 494, 495, 496, + 497, 0, 1, 498, 0, 0, 499, 500, 501, 502, + 503, 504, 2, 0, 3, 4, 0, 0, 0, 0, + 1, 0, 0, 516, 517, 518, 519, 0, 0, 0, + 2, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 8, 0, 0, 0, 7, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 8, 0, 0, 0, 0, 11, 0, + 750, 0, 0, 0, 10, 0, 0, 0, 0, 0, + 0, 13, 0, 0, 0, 0, 11, 0, 750, 0, + 0, 0, 0, 0, 0, 0, 14, 15, 0, 13, + 0, 0, 0, 0, 0, 0, 0, 751, 0, 0, + 0, 0, 0, 18, 14, 15, 0, 0, 0, 0, + 0, 19, 0, 0, 0, 751, 0, 0, 0, 0, + 0, 18, 0, 0, 0, 0, 0, 0, 22, 19, + 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, + 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 1299, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, + 0, 0, 0, 0, -1428, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 1320, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 0, 0, 0, 0, + 0, 0, -1428, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 1671, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 0, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 1847, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 523, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 244, 245, 0, 246, 247, 248, - 249, 250, 2216, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 523, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, - 130, 0, 131, 132, 133, 0, 135, 136, 137, 138, - 139, 0, 141, 142, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 153, 154, 155, - 0, 156, 157, 158, 159, 160, 0, 0, 0, 162, - 163, 164, 165, 166, 167, 0, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 0, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 207, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 0, 227, 0, 228, 229, - 230, 231, 0, 232, 0, 233, 0, 0, 0, 236, - 237, 524, 0, 240, 0, 241, 0, 242, 243, 244, - 245, 0, 246, 247, 248, 249, 250, 2231, 252, 0, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 0, 267, 268, 269, 270, 271, - 272, 273, 274, 0, 275, 0, 276, 0, 0, 279, - 0, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 0, 289, 0, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 525, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 0, 322, 323, 324, 325, 326, - 0, 327, 328, 0, 330, 0, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 344, 0, 346, 0, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 362, 0, 364, 365, - 366, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 379, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 0, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 0, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 0, 0, 427, 428, - 429, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 526, 444, 445, 0, 0, - 446, 447, 0, 448, 0, 450, 451, 452, 453, 454, - 0, 455, 456, 457, 0, 0, 458, 459, 460, 461, - 462, 0, 463, 464, 465, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 0, 487, 488, 489, 490, 491, 492, 493, 0, 0, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 1476, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 1477, 0, - 0, 0, 0, 1478, 129, 130, 0, 131, 132, 133, - 1479, 135, 136, 137, 0, 1480, 1481, 1482, 1483, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 1484, 1485, 155, 0, 156, 157, 158, 159, - 0, 0, 1486, 0, 1487, 163, 164, 165, 166, 167, - 1488, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 1489, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 1490, 190, 191, 1491, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 1059, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 0, 221, 222, 223, 224, 225, 0, - 0, 227, 0, 228, 229, 1492, 231, 0, 232, 0, - 233, 1493, 0, 1494, 236, 237, 0, 1495, 240, 0, - 241, 0, 0, 0, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 1496, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 1497, - 0, 268, 269, 270, 271, 272, 1498, 1499, 0, 1500, - 0, 276, 1501, 1502, 279, 1503, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 1504, 289, 1505, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 1506, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 1507, 1508, - 1509, 323, 324, 325, 0, 0, 327, 328, 1510, 330, - 0, 0, 332, 1511, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 0, - 1512, 346, 1513, 0, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 0, 1514, 364, 365, 0, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 1515, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 1516, 400, 401, 402, 1517, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 1518, 417, 418, 419, 420, 421, 422, 1519, 424, - 425, 0, 1520, 427, 428, 1521, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 1522, 444, 0, 0, 0, 446, 447, 0, 448, 1523, - 450, 451, 452, 453, 454, 0, 455, 1524, 1525, 0, - 0, 458, 459, 0, 461, 0, 0, 463, 464, 1526, - 466, 467, 468, 469, 470, 1527, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 0, 1528, 0, 485, 1529, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 1476, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 512, 513, 514, 515, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 1477, 0, - 0, 0, 0, 1478, 129, 130, 0, 131, 132, 133, - 1479, 135, 136, 137, 0, 1480, 1481, 1482, 1483, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 1484, 1485, 155, 0, 156, 157, 158, 159, - 0, 0, 1486, 0, 1487, 163, 164, 165, 166, 167, - 1488, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 1489, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 1490, 190, 191, 1491, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 1059, 208, 209, - 0, 210, 211, 212, 0, 1829, 214, 215, 0, 216, - 217, 218, 219, 0, 221, 222, 223, 224, 225, 0, - 0, 227, 0, 228, 229, 1492, 231, 0, 232, 0, - 233, 1493, 0, 1494, 236, 237, 0, 1495, 240, 0, - 241, 0, 0, 0, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 1496, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 1497, - 0, 268, 269, 270, 271, 272, 1498, 1499, 0, 1500, - 0, 276, 1501, 1502, 279, 1503, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 1504, 289, 1505, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 1506, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 1507, 1508, - 1509, 323, 324, 325, 0, 0, 327, 328, 1510, 330, - 0, 0, 332, 1511, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 0, - 1512, 346, 1513, 0, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 0, 1514, 364, 365, 0, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 1515, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 1516, 400, 401, 402, 1517, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 1518, 417, 418, 419, 420, 421, 422, 1519, 424, - 425, 0, 1520, 427, 428, 1521, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 1522, 444, 0, 0, 0, 446, 447, 0, 448, 1523, - 450, 451, 452, 453, 454, 0, 455, 1524, 1525, 0, - 0, 458, 459, 0, 461, 0, 0, 463, 464, 1526, - 466, 467, 468, 469, 470, 1527, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 0, 1528, 0, 485, 1529, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 3144, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 512, 513, 514, 515, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 2896, 0, - 0, 0, 0, 2897, 129, 130, 0, 131, 132, 133, - 2898, 135, 136, 137, 0, 1480, 2899, 1482, 1483, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 1484, 1485, 155, 0, 156, 157, 158, 159, - 0, 0, 2900, 0, 2901, 163, 164, 165, 166, 167, - 2902, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 2903, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 1490, 190, 191, 1491, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 1059, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 0, 221, 222, 223, 224, 225, 0, - 0, 227, 0, 228, 229, 1492, 231, 0, 232, 0, - 233, 2904, 0, 2905, 236, 237, 2906, 2907, 240, 0, - 241, 0, 0, 0, 244, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 2908, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 2909, - 0, 268, 269, 270, 271, 272, 1498, 1499, 0, 1500, - 0, 276, 2910, 2911, 279, 2912, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 2913, 289, 2914, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 3145, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 1507, 2916, - 1509, 323, 324, 325, 0, 0, 327, 328, 2918, 330, - 0, 0, 332, 1511, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 0, - 2920, 346, 2921, 0, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 0, 2922, 364, 365, 0, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 377, 378, - 1515, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 2923, 400, 401, 402, 0, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 2924, 417, 418, 419, 420, 421, 422, 0, 424, - 425, 0, 2926, 427, 428, 1521, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 3146, 444, 0, 0, 0, 446, 447, 0, 448, 2928, - 450, 451, 452, 453, 454, 0, 455, 1524, 1525, 0, - 0, 458, 459, 0, 461, 0, 0, 463, 464, 2929, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 0, 1528, 0, 485, 2931, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 523, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 512, 513, 514, 515, 0, - 0, 0, 0, 117, 118, 119, 120, 121, 122, 123, - 124, 0, 125, 126, 127, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 129, 130, 0, 131, 132, 133, - 0, 135, 136, 137, 138, 139, 0, 141, 142, 0, - 143, 144, 145, 146, 147, 148, 0, 0, 149, 150, - 151, 152, 153, 154, 155, 0, 156, 157, 158, 159, - 160, 0, 0, 0, 162, 163, 164, 165, 166, 167, - 0, 169, 170, 171, 0, 172, 173, 174, 175, 176, - 177, 0, 0, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 0, 194, - 0, 195, 196, 197, 198, 199, 200, 0, 0, 201, - 202, 203, 204, 0, 0, 205, 206, 207, 208, 209, - 0, 210, 211, 212, 0, 213, 214, 215, 0, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 0, 227, 0, 228, 229, 230, 231, 0, 232, 0, - 233, 0, 0, 0, 236, 237, 524, 0, 240, 0, - 241, 0, 242, 243, 0, 245, 0, 246, 247, 248, - 249, 250, 251, 252, 0, 254, 255, 256, 257, 0, - 258, 259, 260, 261, 262, 263, 264, 0, 265, 0, - 267, 268, 269, 270, 271, 272, 273, 274, 0, 275, - 0, 276, 0, 0, 279, 0, 281, 282, 283, 284, - 285, 286, 0, 0, 287, 0, 289, 0, 0, 291, - 292, 293, 294, 295, 296, 297, 298, 525, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 0, - 322, 323, 324, 325, 326, 0, 327, 328, 0, 330, - 0, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 0, 0, 339, 340, 341, 0, 0, 342, 343, 344, - 0, 346, 0, 348, 349, 350, 351, 352, 353, 354, - 0, 356, 357, 358, 359, 0, 0, 0, 0, 360, - 361, 362, 0, 364, 365, 366, 367, 368, 369, 0, - 370, 371, 372, 373, 374, 375, 0, 376, 0, 378, - 379, 380, 381, 382, 383, 0, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 0, - 397, 398, 0, 400, 401, 402, 403, 0, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 0, 0, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 0, 0, 427, 428, 429, 430, 0, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 526, 444, 445, 0, 0, 446, 447, 0, 448, 0, - 450, 451, 452, 453, 454, 0, 455, 456, 457, 0, - 0, 458, 459, 460, 461, 462, 0, 463, 464, 465, - 466, 467, 468, 469, 470, 0, 0, 471, 472, 473, - 0, 474, 475, 476, 477, 0, 478, 479, 480, 481, - 482, 483, 484, 0, 485, 0, 487, 488, 489, 490, - 491, 492, 493, 0, 0, 494, 0, 0, 495, 496, - 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 1766, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, - 119, 120, 121, 122, 123, 124, 0, 125, 126, 127, - 0, 0, 0, 1477, 0, 0, 0, 0, 1478, 129, - 130, 0, 131, 132, 133, 1479, 135, 136, 137, 0, - 1480, 1481, 1482, 1483, 0, 143, 144, 145, 146, 147, - 148, 0, 0, 149, 150, 151, 152, 1484, 1485, 155, - 0, 156, 157, 158, 159, 0, 0, 1486, 0, 1487, - 163, 164, 165, 166, 167, 1488, 169, 170, 171, 0, - 172, 173, 174, 175, 176, 177, 0, 1489, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, 1490, 190, - 191, 1491, 193, 0, 194, 0, 195, 196, 197, 198, - 199, 200, 0, 0, 201, 202, 203, 204, 0, 0, - 205, 206, 1059, 208, 209, 0, 210, 211, 212, 0, - 213, 214, 215, 0, 216, 217, 218, 219, 0, 221, - 222, 223, 224, 225, 0, 0, 227, 0, 228, 229, - 1492, 231, 0, 232, 0, 233, 1493, 0, 1494, 236, - 237, 0, 1495, 240, 0, 241, 0, 0, 0, 244, - 245, 0, 246, 247, 248, 249, 250, 251, 252, 1496, - 254, 255, 256, 257, 0, 258, 259, 260, 261, 262, - 263, 264, 0, 265, 1497, 0, 268, 269, 270, 271, - 272, 1498, 1499, 0, 1500, 0, 276, 1501, 1502, 279, - 1503, 281, 282, 283, 284, 285, 286, 0, 0, 287, - 1504, 289, 1505, 0, 291, 292, 293, 294, 295, 296, - 297, 298, 0, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 1507, 1508, 1509, 323, 324, 325, 0, - 0, 327, 328, 1510, 330, 0, 0, 332, 1511, 334, - 335, 336, 0, 337, 338, 0, 0, 339, 340, 341, - 0, 0, 342, 343, 0, 1512, 346, 1513, 0, 349, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 0, 0, 0, 0, 360, 361, 0, 1514, 364, 365, - 0, 367, 368, 369, 0, 370, 371, 372, 373, 374, - 375, 0, 376, 377, 378, 1515, 380, 381, 382, 383, - 0, 384, 385, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 1516, 400, 401, - 402, 0, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 0, 1518, 417, 418, 419, - 420, 421, 422, 0, 424, 425, 0, 1520, 427, 428, - 1521, 430, 0, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 0, 444, 0, 0, 0, - 446, 447, 0, 448, 1523, 450, 451, 452, 453, 454, - 0, 455, 1524, 1525, 0, 0, 458, 459, 0, 461, - 0, 0, 463, 464, 1526, 466, 467, 468, 469, 470, - 0, 0, 471, 472, 473, 0, 474, 475, 476, 477, - 0, 478, 479, 480, 481, 482, 0, 1528, 0, 485, - 1529, 487, 488, 489, 490, 491, 492, 493, 0, 1, - 494, 0, 0, 495, 496, 497, 498, 499, 500, 2, - 0, 3, 4, 0, 0, 0, 0, 1, 0, 0, - 512, 513, 514, 515, 0, 0, 0, 2, 0, 6, - 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, - 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, - 0, 0, 8, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 11, 0, 746, 0, 0, - 0, 10, 0, 0, 0, 0, 0, 0, 13, 0, - 0, 0, 0, 11, 0, 746, 0, 0, 0, 0, - 0, 0, 0, 14, 15, 0, 13, 0, 0, 0, - 0, 0, 0, 0, 747, 0, 0, 0, 0, 0, - 18, 14, 15, 0, 0, 0, 0, 0, 19, 0, - 0, 0, 747, 0, 0, 0, 0, 0, 18, 0, - 0, 0, 0, 0, 22, 0, 19, 0, 23, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 22, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, - 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 26, 27, 28, 0, 0, + 0, 0, 0, 29, 0, 0, 30, 0, 0, 0, + 0, 0, 0, 26, 27, 28, 0, 0, 0, 0, + 0, 29, 0, 0, 30, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, + 0, 0, 33, 0, 32, 0, 0, 0, 0, 34, + 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 36, 0, 0, 0, 34, 0, 0, + 0, 35, 0, 0, 0, 37, 0, 0, 0, 38, + 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 37, 0, 0, 0, 38, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 27, 28, 29, 0, 0, 0, 0, 0, 30, - 0, 0, 31, 0, 0, 0, 0, 0, 0, 27, - 28, 29, 0, 0, 0, 0, 0, 30, 0, 0, - 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 0, 0, 32, - 0, 0, 0, 0, 0, 0, 34, 0, 33, 0, - 0, 0, 0, 35, 0, 0, 0, 36, 0, 0, - 0, 0, 0, 0, 34, 0, 0, 37, 0, 0, - 0, 35, 0, 0, 0, 36, 0, 0, 0, 38, - 0, 0, 0, 39, 0, 37, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, - 0, 39, 0, 40, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, - 0, 40, 43, 0, 0, 0, 0, 44, 0, 0, - 0, 748, 0, 0, 41, 0, 0, 0, 0, 0, - 43, 0, 0, 45, 0, 44, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 45, 0, 0, 0, 0, 0, 46, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 749, 0, 0, 0, 46, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 47 + 0, 0, 40, 0, 0, 0, 0, 39, 42, 0, + 0, 0, 0, 43, 0, 0, 0, 752, 0, 0, + 40, 0, 0, 0, 0, 0, 42, 0, 0, 44, + 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, + 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 753, 0, 0, + 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 46 }; static const yytype_int16 yycheck[] = { - 7, 516, 0, 0, 47, 835, 895, 73, 920, 16, - 0, 0, 0, 809, 0, 0, 23, 16, 881, 1157, - 741, 0, 0, 7, 1224, 990, 0, 858, 904, 1222, - 1236, 1418, 925, 1692, 1655, 981, 749, 970, 1210, 23, - 38, 20, 2172, 1197, 981, 970, 955, 0, 1079, 1032, - 20, 981, 1298, 17, 2141, 77, 2143, 981, 1466, 1199, - 1191, 77, 2227, 1202, 2162, 1574, 1987, 20, 75, 76, - 39, 959, 970, 0, 1608, 1609, 2612, 0, 46, 1276, - 2314, 0, 2612, 2107, 23, 2651, 0, 1227, 0, 0, - 0, 75, 76, 2161, 1797, 26, 0, 1323, 0, 0, - 0, 2223, 100, 2673, 1124, 0, 0, 35, 895, 1129, - 897, 7, 899, 748, 0, 742, 75, 76, 2649, 0, - 0, 0, 1087, 999, 0, 0, 2666, 23, 749, 0, - 805, 2275, 2276, 2277, 2486, 810, 75, 76, 2294, 5, - 2568, 110, 0, 5, 2572, 9, 9, 1819, 979, 5, - 0, 23, 5, 1712, 0, 1988, 1928, 13, 14, 80, - 13, 14, 1659, 5, 11, 1815, 1710, 2985, 5, 16, - 5, 5, 45, 63, 5, 5, 13, 14, 5, 75, - 76, 1106, 13, 14, 772, 5, 982, 5, 5, 9, - 5, 1053, 1054, 2315, 9, 13, 14, 13, 14, 46, - 5, 5, 1135, 75, 76, 5, 5, 5, 1070, 5, - 1135, 2970, 13, 14, 40, 1816, 1961, 1962, 2302, 139, - 3, 4, 5, 2306, 45, 11, 9, 1972, 2300, 2988, - 16, 1976, 119, 80, 60, 63, 55, 172, 82, 3, - 3, 5, 190, 2365, 2366, 871, 2368, 876, 4, 93, - 100, 1057, 1033, 9, 100, 1086, 876, 970, 2437, 2437, - 1243, 74, 171, 2824, 1140, 4, 90, 1073, 63, 1252, - 9, 34, 35, 244, 171, 124, 287, 3149, 1211, 11, - 106, 1214, 1215, 15, 16, 290, 1211, 802, 2870, 1214, - 1215, 180, 2940, 11, 172, 1433, 226, 15, 16, 5, - 122, 107, 11, 295, 82, 129, 15, 16, 983, 289, - 312, 5, 11, 107, 46, 93, 15, 16, 183, 295, - 995, 312, 2805, 0, 2807, 30, 275, 2530, 1466, 2532, - 122, 122, 2419, 38, 117, 850, 147, 46, 973, 107, - 64, 106, 272, 20, 117, 137, 23, 1519, 80, 75, - 74, 192, 171, 379, 1135, 168, 1186, 1187, 40, 1190, - 278, 38, 119, 388, 366, 53, 1612, 1954, 1955, 1956, - 47, 80, 132, 161, 30, 201, 3280, 30, 166, 3344, - 13, 14, 38, 163, 3388, 38, 161, 2531, 30, 2925, - 212, 41, 120, 40, 30, 192, 2582, 1309, 75, 76, - 77, 148, 3238, 165, 3240, 11, 217, 170, 338, 172, - 1898, 365, 37, 117, 2980, 163, 2581, 1280, 3177, 3477, - 1345, 1346, 33, 100, 250, 2991, 2556, 2130, 478, 1210, - 308, 3312, 4, 478, 260, 218, 108, 9, 132, 289, - 46, 1929, 503, 289, 476, 1338, 272, 104, 59, 237, - 500, 2982, 199, 514, 2478, 500, 2578, 240, 2580, 389, - 3518, 3279, 237, 108, 514, 159, 194, 357, 500, 3473, - 3374, 3436, 337, 3377, 80, 393, 126, 448, 304, 3079, - 3316, 3081, 230, 307, 295, 250, 190, 213, 176, 514, - 132, 271, 518, 175, 1525, 260, 132, 2683, 286, 3147, - 1746, 366, 451, 514, 272, 193, 279, 509, 358, 514, - 198, 352, 358, 2716, 392, 328, 240, 1298, 509, 428, - 63, 451, 279, 180, 284, 3107, 518, 3010, 175, 357, - 356, 428, 3093, 166, 514, 327, 534, 1163, 8, 3411, - 413, 11, 518, 514, 3126, 15, 16, 172, 236, 19, - 20, 21, 472, 2732, 2732, 381, 3437, 3375, 355, 1188, - 514, 323, 357, 1151, 82, 454, 514, 3471, 1188, 456, - 274, 2693, 1980, 279, 400, 93, 370, 1092, 2662, 514, - 274, 588, 289, 208, 428, 279, 1740, 2659, 2509, 588, - 284, 512, 413, 1424, 503, 516, 2679, 421, 2107, 224, - 0, 1322, 3202, 2375, 1801, 454, 1327, 516, 1438, 234, - 416, 2145, 1333, 3149, 416, 272, 478, 3376, 132, 3149, - 2179, 463, 1484, 1485, 3164, 1455, 476, 1340, 518, 451, - 476, 1857, 445, 444, 2178, 82, 518, 1837, 500, 403, - 404, 1566, 505, 506, 1890, 2317, 93, 1509, 514, 513, - 428, 478, 514, 1578, 520, 1580, 1902, 2307, 514, 517, - 451, 514, 2171, 510, 520, 515, 1872, 517, 2165, 515, - 3098, 517, 514, 500, 1657, 3103, 2841, 514, 512, 514, - 514, 1606, 516, 514, 514, 1491, 1932, 514, 2433, 515, - 518, 396, 2848, 1939, 514, 514, 514, 514, 514, 514, - 3052, 464, 1329, 391, 1339, 1511, 749, 1569, 1570, 514, - 514, 2312, 3278, 514, 514, 514, 514, 3287, 514, 1340, - 1551, 1552, 505, 506, 510, 1601, 1602, 1603, 198, 272, - 1561, 1977, 406, 2967, 249, 1981, 361, 476, 1519, 1545, - 396, 435, 749, 396, 1575, 120, 3286, 161, 161, 505, - 506, 221, 446, 166, 2822, 380, 1431, 800, 11, 274, - 274, 500, 454, 2009, 415, 108, 505, 506, 425, 748, - 284, 514, 119, 1604, 503, 507, 508, 509, 510, 749, - 517, 430, 789, 265, 1709, 1710, 2707, 516, 1985, 507, - 508, 509, 510, 800, 468, 748, 505, 506, 507, 508, - 509, 510, 453, 1941, 2828, 789, 505, 506, 507, 508, - 509, 510, 3337, 3338, 357, 881, 800, 2961, 149, 194, - 3386, 291, 514, 237, 237, 454, 848, 80, 835, 836, - 479, 1612, 848, 2420, 2421, 2422, 2423, 1770, 320, 274, - 3371, 800, 1980, 386, 279, 1770, 2968, 1780, 191, 513, - 1783, 858, 420, 784, 422, 1780, 2875, 534, 1783, 206, - 524, 800, 1845, 2784, 2883, 3390, 823, 824, 825, 200, - 868, 868, 286, 286, 244, 3411, 1765, 356, 868, 868, - 868, 3411, 868, 868, 853, 514, 856, 244, 512, 868, - 868, 859, 516, 789, 868, 902, 903, 1412, 3429, 906, - 907, 336, 871, 1624, 800, 2131, 464, 386, 2741, 837, - 838, 2744, 840, 2746, 1552, 868, 1004, 789, 515, 274, - 2058, 518, 513, 1561, 2627, 272, 2629, 274, 800, 1949, - 1823, 3497, 244, 524, 1022, 1798, 1799, 1800, 1026, 3173, - 1873, 868, 71, 72, 3109, 868, 1855, 173, 1873, 868, - 1859, 1738, 959, 1862, 868, 4, 868, 868, 868, 226, - 9, 925, 2496, 970, 868, 1746, 868, 868, 868, 2478, - 5, 978, 979, 868, 868, 1873, 1864, 984, 1765, 478, - 987, 988, 868, 990, 991, 992, 993, 868, 868, 868, - 132, 3089, 868, 868, 973, 514, 173, 868, 1785, 1006, - 370, 500, 4, 1790, 26, 272, 1013, 9, 258, 259, - 2397, 365, 366, 370, 37, 514, 2147, 159, 2149, 245, - 973, 509, 1006, 132, 1031, 1032, 1033, 177, 516, 1013, - 514, 501, 502, 503, 147, 505, 506, 507, 508, 509, - 510, 4, 177, 1009, 1087, 1052, 9, 1006, 161, 1015, - 159, 2251, 1880, 166, 1013, 1776, 1884, 512, 370, 1887, - 1781, 516, 512, 2201, 1071, 108, 516, 1006, 245, 1994, - 352, 748, 749, 2319, 1013, 1082, 1083, 1084, 448, 1086, - 1087, 2278, 509, 3004, 1091, 420, 59, 422, 3253, 516, - 240, 448, 1091, 2796, 512, 74, 514, 1423, 516, 1425, - 1426, 80, 377, 2612, 217, 240, 1937, 1014, 377, 1890, - 1006, 1018, 789, 1120, 93, 137, 342, 1013, 202, 2259, - 74, 1902, 389, 800, 237, 375, 376, 512, 251, 514, - 1137, 1138, 274, 420, 1006, 422, 448, 279, 117, 433, - 119, 1013, 284, 515, 514, 416, 518, 1169, 1170, 172, - 1172, 1932, 466, 1169, 1170, 381, 1172, 514, 1939, 515, - 1873, 374, 518, 117, 1171, 342, 377, 30, 1175, 1176, - 279, 848, 2137, 286, 476, 284, 478, 244, 1185, 1186, - 1187, 514, 295, 1190, 451, 208, 2233, 2326, 2235, 2020, - 416, 868, 244, 2332, 1163, 420, 1977, 422, 171, 177, - 1981, 224, 514, 1210, 381, 515, 1987, 2453, 518, 837, - 838, 234, 840, 8, 515, 515, 11, 518, 518, 2144, - 15, 16, 85, 514, 19, 20, 21, 206, 2009, 515, - 515, 94, 518, 518, 6, 370, 1243, 514, 10, 416, - 466, 36, 166, 342, 26, 1252, 18, 2578, 514, 2580, - 32, 514, 2177, 2178, 202, 118, 873, 1226, 875, 244, - 82, 33, 240, 515, 2095, 37, 518, 514, 26, 1276, - 420, 293, 422, 515, 32, 515, 518, 515, 518, 2142, - 518, 515, 381, 514, 518, 420, 108, 422, 171, 466, - 514, 1298, 514, 435, 42, 274, 973, 2435, 448, 514, - 279, 2439, 2710, 370, 446, 13, 14, 1314, 1297, 1297, - 514, 1297, 1297, 448, 507, 1314, 1323, 416, 370, 2828, - 274, 2230, 500, 2232, 3489, 279, 435, 190, 171, 1006, - 514, 444, 354, 1340, 356, 313, 1013, 446, 361, 497, - 203, 314, 315, 316, 3474, 515, 3476, 223, 518, 328, - 1357, 173, 13, 14, 3441, 137, 1363, 380, 1357, 107, - 1339, 109, 26, 111, 386, 344, 2612, 466, 32, 3456, - 1340, 1048, 515, 497, 328, 518, 2206, 13, 14, 137, - 202, 448, 516, 1060, 289, 370, 1339, 3517, 515, 170, - 344, 518, 370, 2305, 515, 2595, 448, 518, 516, 377, - 514, 2594, 518, 1410, 1411, 515, 379, 515, 518, 1416, - 1087, 1418, 515, 13, 14, 518, 1423, 1424, 1425, 1426, - 2626, 515, 370, 245, 3511, 2579, 221, 515, 515, 3516, - 518, 1438, 1439, 381, 1418, 171, 1443, 515, 1445, 294, - 518, 1448, 420, 416, 422, 59, 1453, 514, 1455, 1456, - 2643, 1458, 2483, 2484, 2593, 1462, 2595, 515, 514, 1443, - 518, 1445, 514, 448, 1448, 417, 445, 223, 416, 1453, - 448, 497, 1456, 137, 1458, 454, 449, 515, 1462, 515, - 518, 152, 518, 350, 1443, 515, 1445, 460, 518, 1448, - 152, 445, 1169, 1170, 1453, 1172, 291, 1456, 152, 1458, - 454, 342, 515, 1462, 1443, 518, 1445, 188, 189, 1448, - 515, 293, 1519, 518, 1453, 2461, 2462, 1456, 466, 1458, - 2351, 2486, 1418, 1462, 2461, 2462, 2463, 152, 3231, 514, - 3233, 2461, 2457, 2458, 152, 293, 2460, 171, 2319, 402, - 381, 514, 405, 1033, 1551, 1552, 1418, 1443, 370, 1445, - 1548, 1548, 1448, 1560, 1561, 13, 14, 1453, 1548, 381, - 1456, 1568, 1458, 40, 515, 416, 1462, 518, 1575, 1548, - 1548, 1443, 354, 1445, 1548, 416, 1448, 258, 259, 515, - 515, 1453, 518, 518, 1456, 515, 1458, 515, 518, 514, - 1462, 274, 350, 1600, 416, 1548, 354, 1604, 40, 515, - 1607, 40, 518, 89, 386, 1612, 1613, 1614, 1615, 1616, - 1617, 1618, 1619, 1620, 1621, 13, 14, 439, 1625, 1626, - 3241, 60, 1621, 1630, 2345, 466, 466, 1634, 386, 293, - 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 2352, - 3149, 1648, 152, 515, 466, 2891, 518, 480, 1655, 26, - 1657, 515, 152, 515, 518, 32, 518, 515, 365, 366, - 518, 152, 1339, 13, 14, 13, 14, 106, 107, 1676, - 516, 2547, 2453, 1695, 152, 457, 13, 14, 117, 1695, - 314, 315, 316, 5, 13, 14, 350, 2612, 2842, 2889, - 354, 1698, 13, 14, 375, 376, 13, 14, 289, 457, - 13, 14, 1709, 1710, 1674, 352, 501, 502, 503, 428, - 505, 506, 507, 508, 509, 510, 13, 14, 13, 14, - 1210, 514, 386, 13, 14, 13, 14, 171, 2509, 13, - 14, 13, 14, 13, 14, 514, 175, 13, 14, 1746, - 2570, 13, 14, 13, 14, 379, 13, 14, 1755, 514, - 1757, 13, 14, 2925, 365, 366, 1755, 514, 1757, 2965, - 137, 2654, 201, 515, 2676, 418, 1443, 219, 1445, 224, - 2633, 1448, 365, 366, 262, 263, 1453, 2686, 299, 1456, - 3439, 1458, 416, 514, 3443, 1462, 224, 535, 375, 376, - 1797, 224, 540, 457, 1801, 543, 514, 1804, 1805, 459, - 460, 3047, 3451, 3452, 126, 127, 3193, 26, 1298, 3483, - 3484, 250, 296, 32, 2797, 449, 40, 2742, 1137, 1138, - 235, 260, 514, 5, 5, 514, 460, 324, 514, 514, - 514, 2612, 5, 272, 8, 274, 5, 11, 1845, 3498, - 514, 15, 16, 1841, 5, 19, 20, 21, 514, 171, - 1857, 5, 148, 9, 477, 514, 8, 1864, 1865, 11, - 301, 518, 36, 15, 16, 304, 1873, 19, 20, 21, - 514, 1548, 104, 518, 515, 40, 219, 386, 286, 166, - 514, 166, 284, 1890, 59, 514, 235, 1894, 1895, 428, - 1897, 93, 514, 428, 518, 1902, 1903, 1904, 1905, 1906, - 1907, 1908, 3411, 3149, 1911, 1912, 1913, 1914, 1915, 1916, - 1917, 1918, 1919, 1920, 59, 59, 293, 356, 137, 1926, - 1927, 428, 428, 1930, 265, 1932, 2707, 524, 108, 221, - 1937, 476, 1939, 428, 428, 152, 100, 377, 274, 198, - 274, 274, 381, 514, 40, 514, 274, 2880, 274, 152, - 1627, 171, 1959, 516, 13, 2880, 1963, 3344, 1965, 515, - 2885, 400, 1969, 402, 515, 26, 405, 3160, 515, 515, - 1977, 32, 171, 350, 1981, 515, 1983, 354, 1985, 1963, - 1987, 518, 515, 2892, 2893, 1969, 515, 514, 473, 224, - 224, 514, 314, 315, 316, 281, 514, 463, 281, 518, - 3387, 516, 2009, 2784, 1963, 516, 514, 2932, 2933, 386, - 1969, 514, 514, 2020, 2021, 514, 2737, 39, 1695, 472, - 9, 514, 514, 426, 1963, 426, 11, 352, 518, 1519, - 1969, 513, 426, 279, 521, 524, 428, 518, 514, 514, - 180, 162, 171, 791, 117, 518, 515, 221, 454, 3436, - 217, 518, 2095, 2060, 3019, 265, 226, 379, 2065, 2066, - 290, 312, 389, 312, 518, 180, 219, 1963, 390, 3275, - 518, 226, 515, 1969, 293, 514, 137, 514, 274, 3217, - 457, 295, 287, 2090, 2091, 226, 333, 466, 2095, 514, - 412, 1963, 152, 3, 416, 26, 514, 1969, 171, 152, - 514, 32, 2109, 152, 152, 2112, 476, 2114, 152, 3, - 2891, 37, 40, 289, 274, 40, 42, 291, 289, 59, - 171, 11, 1612, 2130, 2131, 40, 166, 449, 515, 515, - 2137, 350, 515, 2140, 515, 354, 514, 885, 460, 291, - 2861, 514, 180, 514, 2925, 166, 3, 39, 3, 512, - 2157, 512, 1829, 428, 476, 428, 2140, 428, 515, 428, - 513, 515, 518, 2170, 1841, 3411, 171, 386, 515, 917, - 521, 516, 514, 2157, 497, 101, 515, 13, 500, 497, - 2187, 2188, 514, 19, 515, 933, 934, 935, 936, 497, - 428, 515, 514, 155, 514, 31, 515, 2204, 514, 2206, - 515, 2140, 249, 515, 514, 473, 137, 40, 2215, 45, - 46, 518, 3137, 3138, 3414, 3127, 59, 518, 2157, 290, - 499, 290, 503, 3004, 3149, 451, 2233, 2234, 2235, 243, - 303, 59, 293, 59, 2233, 2234, 2235, 985, 457, 265, - 428, 314, 315, 316, 2140, 274, 172, 8, 514, 152, - 11, 202, 152, 177, 15, 16, 1746, 152, 19, 20, - 21, 2157, 428, 281, 281, 2272, 3047, 2310, 2140, 147, - 428, 2278, 108, 515, 514, 36, 40, 428, 202, 428, - 352, 514, 208, 161, 515, 2157, 1963, 3000, 166, 350, - 518, 287, 1969, 354, 289, 40, 152, 476, 224, 279, - 515, 171, 514, 514, 59, 185, 379, 2314, 234, 515, - 2299, 2299, 2319, 2299, 2299, 2314, 240, 515, 515, 166, - 80, 512, 515, 515, 143, 386, 515, 501, 502, 503, - 2337, 505, 506, 507, 508, 509, 510, 198, 515, 217, - 171, 524, 268, 416, 2351, 2352, 514, 300, 358, 501, - 502, 503, 2359, 505, 506, 507, 508, 509, 510, 237, - 2359, 518, 293, 289, 180, 515, 514, 3243, 3149, 515, - 294, 514, 3203, 290, 3205, 152, 449, 515, 515, 518, - 514, 175, 439, 515, 515, 3215, 516, 460, 314, 515, - 2397, 514, 514, 40, 518, 321, 457, 515, 514, 40, - 1890, 86, 454, 476, 518, 171, 514, 475, 286, 515, - 515, 198, 1902, 2397, 515, 513, 513, 295, 2095, 350, - 515, 515, 3218, 354, 3220, 518, 515, 500, 515, 460, - 2437, 289, 59, 503, 3346, 361, 2113, 3402, 515, 515, - 515, 514, 1932, 2486, 476, 204, 2453, 117, 1196, 1939, - 515, 40, 2129, 226, 380, 386, 514, 88, 2524, 191, - 221, 1209, 2469, 2140, 279, 0, 3355, 279, 2475, 2476, - 516, 516, 428, 3336, 516, 516, 2519, 516, 503, 2486, - 2157, 516, 1230, 516, 428, 515, 3411, 1977, 516, 516, - 2497, 1981, 516, 2500, 513, 2502, 420, 1987, 422, 515, - 3330, 2397, 2509, 2510, 516, 516, 2513, 2514, 516, 516, - 516, 2518, 2519, 516, 516, 516, 516, 516, 2525, 2009, - 513, 445, 516, 449, 448, 2397, 457, 2570, 454, 516, - 291, 8, 516, 2540, 11, 516, 40, 516, 15, 16, - 2538, 2538, 516, 2550, 516, 1293, 2544, 516, 2538, 516, - 516, 516, 515, 274, 1302, 514, 7, 8, 107, 2538, - 2538, 40, 13, 2570, 2538, 100, 444, 514, 19, 46, - 476, 289, 23, 514, 25, 26, 53, 9, 514, 30, - 31, 32, 351, 518, 35, 2538, 335, 38, 39, 518, - 59, 42, 514, 198, 45, 46, 515, 515, 191, 513, - 459, 91, 2609, 80, 344, 2612, 2613, 518, 2615, 514, - 2609, 515, 147, 40, 2613, 152, 2615, 516, 515, 55, - 2627, 124, 2629, 152, 75, 76, 161, 40, 515, 366, - 3411, 166, 366, 2310, 512, 40, 171, 515, 516, 515, - 514, 514, 40, 518, 454, 180, 514, 309, 514, 100, - 185, 279, 2650, 248, 190, 454, 107, 108, 109, 110, - 111, 439, 514, 3384, 2653, 2653, 102, 2653, 2653, 292, - 74, 74, 80, 9, 515, 515, 514, 368, 1033, 93, - 2678, 515, 217, 2681, 513, 59, 2729, 123, 513, 133, - 503, 272, 289, 1441, 40, 439, 514, 2704, 292, 176, - 2707, 292, 237, 514, 204, 141, 515, 515, 515, 145, - 289, 459, 289, 515, 386, 551, 193, 2724, 2725, 365, - 122, 198, 2729, 37, 451, 2732, 148, 25, 42, 36, - 365, 167, 297, 868, 170, 2596, 1763, 2228, 25, 26, - 501, 502, 503, 3245, 505, 506, 507, 508, 509, 510, - 186, 286, 2759, 3387, 289, 2609, 3340, 3488, 2548, 236, - 295, 8, 1864, 2885, 11, 2340, 2773, 3361, 15, 16, - 3466, 2778, 2779, 3120, 3415, 2818, 2783, 2784, 40, 3424, - 3459, 2788, 147, 3179, 2791, 2792, 1197, 101, 2221, 2796, - 2797, 171, 2234, 2800, 3309, 3413, 161, 2804, 60, 46, - 335, 166, 2218, 2588, 2811, 3422, 53, 2667, 2615, 2486, - 3410, 2298, 1295, 2359, 291, 3000, 2645, 1322, 2204, 1005, - 2804, 1156, 2170, 358, 1734, 2418, 1178, 114, 3396, 2319, - 1698, 3318, 3207, 80, 2187, 1179, 1733, 23, 1975, 2157, - 2732, 1181, 2519, 279, 106, 2804, 1005, 3042, 2855, 2397, - 151, 287, 217, 2445, 800, 1210, 2863, 789, 172, 2396, - 3141, 2538, 1990, 983, 981, 2804, 1873, 2544, 981, 981, - 171, 981, 237, 309, 981, 2882, 1873, 981, 981, 981, - 3322, 416, 3321, 2171, 2891, 2067, 2476, 1439, 2069, 2022, - 2113, 2110, 2493, 2570, 208, 2811, 3307, 2538, 145, 783, - 336, 1807, 1983, 1360, 1340, 1674, 37, 743, 2804, 444, - 224, 42, 2549, 175, 391, 1675, 100, -1, 2925, 454, - 234, 286, 2271, 303, -1, 1673, -1, 1675, 1234, 176, - 295, -1, 2804, -1, 314, 315, 316, 1685, 473, 201, - 475, 476, -1, 1298, -1, -1, 193, -1, -1, -1, - -1, 198, 40, -1, 268, -1, -1, -1, -1, -1, - 2967, -1, -1, 2453, -1, 2972, -1, -1, 2967, -1, - 101, -1, 60, 2650, -1, 1723, 3019, 512, -1, -1, - 515, 516, 517, -1, -1, 2983, -1, -1, 250, 236, - -1, -1, -1, 3000, -1, -1, 3003, 3004, 260, 379, - 314, 2678, -1, -1, 2681, -1, -1, 321, -1, -1, - 272, -1, 3019, 314, 315, 316, -1, -1, 106, 2509, - -1, 498, -1, 859, -1, -1, -1, -1, 505, 506, - 507, 508, 509, 510, -1, -1, 416, -1, -1, -1, - 3047, 172, 304, -1, 291, 3052, -1, 361, -1, -1, - -1, -1, 2729, -1, -1, -1, 3063, 3064, -1, -1, - 3067, -1, 3069, -1, -1, -1, 380, -1, -1, 449, - 1818, 1819, 1820, 1821, 1822, -1, -1, 208, 379, 444, - 460, -1, -1, -1, 535, -1, -1, 3094, -1, 540, - -1, -1, 543, 224, 356, -1, 476, -1, 8, -1, - 551, 11, -1, 234, -1, 15, 16, -1, -1, -1, - -1, 3118, -1, 201, -1, 416, -1, -1, -1, 381, - 500, -1, 2612, -1, -1, -1, -1, 2804, -1, -1, - -1, -1, -1, -1, 514, 449, 46, 268, 400, -1, - -1, 2818, 3149, 53, 391, -1, -1, 512, 449, -1, - -1, 516, -1, -1, -1, 177, -1, -1, 289, 460, - -1, -1, 250, -1, 1519, -1, 3173, -1, 3166, 3167, - 80, -1, 260, -1, 3173, 476, -1, -1, -1, -1, - 202, -1, 3189, 314, 272, 1033, 3193, -1, -1, -1, - 321, -1, -1, -1, -1, -1, 3203, -1, 3205, 500, - 3207, -1, -1, -1, 3211, 1953, 3213, -1, 3215, 3193, - -1, 1033, -1, 514, -1, -1, 304, 2707, 240, 3226, - -1, -1, -1, -1, 3231, 8, 3233, -1, 11, -1, - 361, -1, 15, 16, 3241, 145, 19, 20, 21, -1, - -1, -1, -1, -1, 3242, -1, 3244, 3254, -1, 380, - -1, 498, 3259, -1, -1, 3254, -1, 1612, 505, 506, - 507, 508, 509, 510, -1, -1, 176, -1, 356, -1, - -1, -1, 294, -1, -1, -1, 151, -1, -1, -1, - 177, -1, -1, 193, -1, -1, -1, 3285, 198, -1, - 741, 742, 743, 381, 2784, -1, 171, 3193, -1, -1, - -1, 3308, -1, 3301, -1, 202, 2983, 3305, -1, -1, - -1, 3318, 400, 988, 171, -1, -1, -1, 449, -1, - 1156, 3193, -1, 3330, -1, -1, 236, -1, -1, -1, - -1, 782, 783, 784, -1, -1, -1, 3344, 789, -1, - 791, -1, 3019, 240, -1, -1, -1, -1, 370, 800, - -1, -1, -1, 804, 805, 3362, -1, -1, 809, 810, - 3344, -1, 1210, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 823, 824, 825, -1, -1, -1, -1, -1, - 3387, 291, -1, -1, -1, -1, 837, 838, 1210, 840, - -1, 1746, -1, -1, -1, 3402, -1, 294, 420, -1, - 422, 2891, 853, 3387, 3411, -1, 3413, -1, 859, -1, - -1, -1, -1, -1, 3413, 198, 313, 439, -1, -1, - 871, -1, -1, 445, -1, -1, 448, -1, -1, 3436, - 3428, -1, -1, -1, 885, 2925, -1, -1, 221, 314, - 315, 316, -1, 3450, 3451, 3452, -1, -1, 3344, -1, - 1298, -1, 3436, -1, -1, -1, 3454, 314, 315, 316, - -1, -1, -1, -1, -1, -1, 917, 918, -1, -1, - 3477, -1, 3344, 370, -1, -1, 1298, -1, 929, -1, - 377, 391, 933, 934, 935, 936, -1, -1, -1, 3166, - 3167, 3387, -1, -1, 1330, 782, 1332, 784, 949, -1, - -1, -1, -1, -1, 379, -1, -1, 988, 291, -1, - -1, 3518, -1, -1, 3004, 3387, -1, -1, -1, -1, - -1, -1, 379, 420, -1, 422, -1, 814, -1, -1, - -1, 982, 983, -1, 985, 1890, -1, 988, -1, -1, - 3436, 416, 439, 994, 995, -1, -1, 1902, 445, 1000, - -1, 448, 839, 2301, -1, 1006, -1, 3047, -1, 416, - -1, -1, 1013, -1, 3436, 3242, -1, 3244, 2316, 2317, - 2318, -1, 1023, -1, 449, -1, -1, 1932, -1, 1030, - -1, -1, -1, 2331, 1939, 460, 2334, -1, 498, 1040, - -1, 2339, 449, -1, -1, 505, 506, 507, 508, 509, - 510, 476, 8, 460, -1, 11, -1, -1, 3285, 15, - 16, -1, -1, 19, 20, 21, -1, -1, -1, 476, - -1, -1, 1977, -1, 3301, 500, 1981, -1, 3305, 988, - -1, -1, 1987, -1, -1, -1, -1, -1, 1089, 514, - 46, -1, -1, 500, -1, -1, -1, 53, -1, -1, - -1, -1, -1, -1, 2009, -1, -1, 514, -1, 3149, + 7, 0, 838, 0, 887, 520, 899, 0, 745, 16, + 0, 0, 89, 90, 87, 0, 23, 0, 0, 0, + 16, 0, 0, 38, 861, 23, 926, 7, 1230, 813, + 995, 1243, 753, 1429, 1036, 20, 910, 978, 20, 1704, + 986, 46, 1580, 23, 1162, 931, 1204, 1217, 20, 2187, + 1229, 961, 1662, 986, 1475, 91, 986, 1083, 1206, 37, + 986, 1808, 2152, 1285, 2154, 1554, 1209, 2242, 1168, 91, + 17, 965, 2173, 978, 7, 2352, 1307, 2629, 1615, 1616, + 1128, 2667, 89, 90, 0, 1133, 1234, 45, 1995, 2172, + 23, 89, 90, 0, 0, 0, 111, 0, 0, 23, + 1332, 0, 0, 2629, 0, 752, 2118, 0, 809, 89, + 90, 34, 2688, 814, 2665, 746, 2290, 2291, 2292, 2238, + 2681, 0, 0, 753, 0, 103, 1091, 0, 0, 0, + 1004, 0, 0, 2501, 0, 0, 0, 899, 0, 901, + 2309, 903, 2585, 0, 5, 5, 2589, 984, 0, 1832, + 0, 9, 20, 1826, 1996, 23, 89, 90, 1666, 1829, + 5, 1722, 5, 11, 5, 89, 90, 0, 16, 37, + 13, 14, 59, 1057, 1058, 55, 5, 5, 46, 13, + 14, 5, 5, 5, 5, 9, 5, 5, 5, 63, + 1074, 13, 14, 5, 13, 14, 13, 14, 1139, 80, + 5, 3001, 978, 987, 5, 5, 13, 14, 2327, 9, + 5, 5, 13, 14, 5, 771, 2316, 173, 45, 63, + 4, 89, 90, 91, 2321, 9, 82, 3, 4, 5, + 119, 45, 1971, 9, 1724, 103, 74, 93, 9, 124, + 2320, 11, 191, 100, 882, 1984, 16, 139, 882, 2451, + 1252, 11, 122, 1090, 1938, 15, 16, 978, 30, 1261, + 63, 2380, 2381, 172, 2383, 2451, 38, 100, 181, 856, + 5, 1145, 1172, 5, 4, 107, 46, 1218, 172, 9, + 1221, 1222, 90, 3, 82, 172, 46, 988, 288, 11, + 3167, 806, 172, 15, 16, 93, 290, 30, 53, 1000, + 63, 2960, 104, 1061, 2823, 38, 2825, 227, 107, 122, + 80, 1964, 1965, 1966, 34, 35, 291, 291, 122, 1077, + 80, 129, 313, 276, 137, 313, 1444, 119, 174, 296, + 64, 169, 979, 40, 1110, 2842, 166, 245, 853, 2987, + 74, 117, 107, 213, 2434, 11, 296, 122, 117, 15, + 16, 193, 3, 273, 5, 1525, 3004, 1475, 1194, 1195, + 30, 1198, 193, 1139, 184, 2545, 132, 2547, 38, 41, + 409, 391, 2546, 382, 2599, 164, 172, 3330, 369, 181, + 46, 117, 13, 14, 108, 3362, 148, 11, 1619, 3406, + 3495, 2943, 368, 83, 2141, 40, 3297, 132, 1009, 457, + 246, 30, 481, 3256, 120, 3258, 164, 457, 1291, 213, + 2996, 345, 30, 479, 80, 1315, 1027, 433, 359, 108, + 1031, 3007, 177, 2598, 503, 160, 418, 1558, 315, 316, + 317, 3536, 471, 290, 30, 2573, 1567, 503, 200, 194, + 108, 506, 1218, 219, 199, 1221, 1222, 2998, 389, 11, + 384, 171, 517, 173, 126, 191, 80, 290, 148, 517, + 75, 1347, 147, 517, 456, 241, 482, 517, 192, 176, + 273, 273, 392, 231, 3491, 2700, 2595, 3454, 2597, 195, + 2492, 3334, 237, 272, 46, 419, 360, 419, 280, 85, + 3391, 329, 26, 3394, 324, 382, 3296, 517, 94, 345, + 308, 454, 3455, 132, 361, 1531, 3165, 241, 273, 3028, + 484, 280, 521, 355, 132, 328, 360, 517, 80, 285, + 340, 512, 118, 517, 512, 11, 1757, 358, 361, 15, + 16, 176, 419, 218, 454, 469, 167, 431, 384, 275, + 275, 517, 517, 451, 457, 280, 3194, 2749, 280, 369, + 285, 506, 3429, 2733, 521, 178, 0, 360, 1196, 468, + 538, 517, 1196, 2749, 519, 452, 2888, 1988, 517, 266, + 459, 521, 457, 419, 373, 431, 463, 2677, 1354, 1355, + 2118, 1096, 1169, 475, 454, 592, 389, 419, 3489, 416, + 1812, 2710, 3392, 1751, 1331, 191, 592, 360, 1435, 1336, + 1156, 2698, 416, 137, 3111, 1342, 1490, 1491, 204, 517, + 448, 296, 506, 1449, 2694, 3167, 424, 2524, 241, 2156, + 3181, 481, 479, 469, 321, 519, 428, 399, 1349, 1465, + 517, 1515, 2193, 431, 515, 431, 1868, 517, 519, 394, + 173, 3167, 1844, 503, 279, 466, 479, 521, 2186, 2322, + 454, 517, 245, 481, 520, 520, 517, 517, 516, 2329, + 290, 518, 1664, 520, 162, 513, 399, 2350, 2176, 1900, + 538, 1883, 517, 3116, 517, 503, 517, 521, 3121, 454, + 523, 1912, 523, 517, 2859, 518, 515, 520, 517, 517, + 519, 1575, 1576, 517, 517, 517, 517, 2866, 517, 517, + 517, 1348, 3070, 438, 2194, 517, 2390, 1338, 2447, 3295, + 517, 1942, 517, 2990, 449, 467, 517, 517, 1949, 1349, + 1557, 1558, 517, 517, 508, 509, 517, 804, 3304, 399, + 1567, 162, 508, 509, 1608, 1609, 1610, 508, 509, 1497, + 238, 1442, 3303, 513, 1581, 3393, 753, 467, 753, 479, + 510, 511, 512, 513, 1985, 406, 407, 2840, 1989, 1517, + 294, 396, 447, 1908, 120, 1891, 520, 752, 149, 1895, + 752, 1993, 1898, 503, 1611, 214, 309, 106, 508, 509, + 373, 753, 2435, 2436, 2437, 2438, 793, 2018, 510, 511, + 512, 513, 5, 521, 1939, 1553, 1572, 804, 26, 804, + 423, 178, 425, 3125, 32, 2979, 804, 238, 1584, 405, + 1586, 275, 408, 793, 887, 851, 280, 2724, 3404, 3097, + 201, 3099, 3144, 357, 804, 359, 33, 132, 451, 851, + 1014, 838, 839, 1951, 2846, 275, 1020, 1613, 3389, 195, + 1781, 856, 508, 509, 510, 511, 512, 513, 250, 2893, + 1791, 1853, 59, 1794, 861, 389, 287, 2901, 451, 515, + 793, 876, 395, 519, 241, 5, 2985, 189, 190, 793, + 1988, 804, 871, 275, 871, 339, 481, 3429, 871, 341, + 804, 871, 871, 1776, 752, 753, 871, 859, 871, 871, + 871, 517, 871, 871, 1631, 2802, 3447, 2644, 503, 2646, + 517, 908, 909, 3429, 862, 912, 913, 245, 1423, 137, + 2142, 1959, 517, 126, 127, 1037, 2758, 840, 841, 2761, + 843, 2763, 251, 108, 517, 793, 1809, 1810, 1811, 3515, + 3207, 245, 261, 82, 1011, 515, 804, 259, 260, 519, + 512, 1018, 3220, 1884, 93, 1721, 1722, 519, 1834, 355, + 203, 2069, 3127, 119, 2492, 871, 1866, 380, 965, 172, + 1870, 26, 245, 1873, 871, 871, 871, 32, 871, 871, + 275, 978, 871, 871, 2511, 871, 983, 984, 871, 1884, + 285, 1875, 989, 851, 931, 992, 993, 1749, 995, 996, + 997, 998, 871, 871, 979, 871, 373, 979, 871, 871, + 871, 380, 871, 871, 1011, 1781, 3107, 871, 74, 871, + 174, 1018, 132, 1011, 1776, 1791, 2412, 1139, 1794, 871, + 1018, 871, 508, 509, 510, 511, 512, 513, 1035, 1036, + 1037, 1011, 82, 516, 1796, 373, 3355, 3356, 1018, 1801, + 160, 207, 178, 93, 527, 512, 423, 203, 425, 1056, + 1787, 117, 519, 436, 245, 1792, 378, 379, 2158, 373, + 4, 2161, 516, 2265, 2553, 9, 294, 2814, 1075, 71, + 72, 2293, 137, 527, 451, 345, 227, 37, 1011, 1086, + 1087, 1088, 246, 1090, 1091, 1018, 1091, 1011, 1095, 3408, + 373, 2629, 259, 260, 1018, 1217, 3271, 252, 2216, 1095, + 2331, 4, 315, 316, 317, 241, 9, 273, 1884, 275, + 1947, 979, 515, 451, 384, 3022, 519, 1124, 4, 132, + 373, 13, 273, 9, 419, 353, 2274, 19, 4, 357, + 245, 384, 469, 9, 1141, 1142, 1019, 451, 30, 377, + 1023, 1177, 1178, 1011, 1180, 26, 423, 160, 425, 419, + 1018, 32, 44, 45, 1169, 1177, 1178, 162, 1180, 380, + 280, 389, 167, 1884, 518, 285, 419, 521, 451, 382, + 162, 1434, 1179, 1436, 1437, 167, 1183, 1184, 314, 517, + 393, 345, 373, 2148, 1052, 1307, 1193, 1194, 1195, 517, + 341, 1198, 517, 2030, 518, 2338, 1064, 521, 517, 469, + 481, 2344, 415, 517, 840, 841, 419, 843, 167, 275, + 1217, 378, 379, 173, 280, 517, 469, 109, 1233, 517, + 384, 518, 503, 1091, 521, 518, 2002, 518, 521, 294, + 521, 517, 460, 238, 517, 2466, 517, 373, 517, 452, + 8, 392, 172, 11, 380, 1252, 238, 15, 16, 209, + 463, 19, 20, 21, 1261, 419, 137, 515, 373, 517, + 451, 519, 275, 329, 510, 225, 479, 280, 36, 2106, + 2153, 518, 285, 518, 521, 235, 521, 518, 1285, 503, + 521, 347, 287, 518, 13, 14, 521, 423, 353, 425, + 503, 518, 357, 518, 521, 287, 521, 224, 518, 518, + 1307, 521, 521, 454, 517, 469, 2727, 1306, 2846, 1177, + 1178, 517, 1180, 1306, 517, 451, 1323, 1306, 438, 518, + 13, 14, 521, 1306, 389, 1332, 517, 1323, 25, 449, + 518, 2449, 3507, 521, 2452, 2245, 451, 2247, 518, 517, + 8, 521, 1349, 11, 517, 40, 6, 15, 16, 517, + 10, 19, 20, 21, 3492, 500, 3494, 518, 18, 1366, + 521, 13, 14, 1348, 1371, 60, 1348, 519, 36, 3459, + 1366, 518, 32, 515, 521, 517, 36, 1349, 1455, 2155, + 519, 1458, 448, 37, 3474, 2221, 1463, 518, 290, 1466, + 521, 457, 500, 518, 1471, 460, 521, 3535, 2629, 26, + 171, 26, 517, 1525, 364, 32, 518, 32, 521, 521, + 2612, 106, 517, 294, 1421, 1422, 2192, 2193, 115, 2319, + 1427, 518, 1429, 383, 521, 438, 518, 1434, 1435, 1436, + 1437, 2643, 2611, 423, 518, 425, 449, 521, 2596, 3529, + 13, 14, 1449, 1450, 3534, 13, 14, 518, 1455, 1429, + 521, 1458, 172, 479, 222, 481, 1463, 1455, 1465, 1466, + 1458, 13, 14, 518, 1471, 1463, 521, 2610, 1466, 2612, + 518, 2497, 2498, 1471, 518, 1455, 357, 521, 1458, 518, + 1348, 2660, 521, 1463, 518, 518, 1466, 521, 521, 518, + 518, 1471, 521, 521, 518, 518, 1429, 1619, 521, 423, + 518, 425, 3249, 521, 3251, 1429, 518, 202, 389, 521, + 137, 518, 137, 423, 521, 425, 295, 518, 1525, 173, + 521, 2248, 1455, 2250, 292, 1458, 13, 14, 2474, 2366, + 1463, 1455, 59, 1466, 1458, 2595, 2501, 2597, 1471, 1463, + 2473, 517, 1466, 420, 2474, 2475, 2476, 1471, 2474, 2475, + 1557, 1558, 13, 14, 222, 209, 251, 1554, 500, 1566, + 1567, 826, 827, 828, 1554, 224, 261, 1574, 879, 1554, + 881, 225, 1554, 1554, 1581, 1554, 1554, 152, 273, 460, + 353, 235, 147, 152, 178, 13, 14, 1455, 13, 14, + 1458, 13, 14, 13, 14, 1463, 152, 162, 1466, 152, + 1607, 152, 167, 1471, 1611, 13, 14, 1614, 40, 203, + 305, 419, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, + 1627, 1628, 26, 2360, 292, 1632, 1633, 518, 32, 3167, + 1637, 275, 1628, 517, 1641, 1757, 469, 1644, 1645, 1646, + 1647, 1648, 1649, 1650, 1651, 1652, 2367, 241, 1655, 3259, + 13, 14, 40, 218, 41, 1662, 89, 1664, 13, 14, + 13, 14, 152, 555, 359, 483, 26, 294, 152, 294, + 519, 1707, 32, 238, 13, 14, 1683, 152, 2909, 13, + 14, 13, 14, 13, 14, 1707, 1554, 152, 2562, 384, + 13, 14, 13, 14, 2470, 2471, 13, 14, 13, 14, + 290, 295, 2860, 1710, 431, 2907, 13, 14, 403, 1681, + 364, 368, 369, 355, 1721, 1722, 517, 368, 369, 368, + 369, 108, 287, 110, 517, 112, 353, 517, 353, 383, + 357, 296, 357, 137, 368, 369, 504, 505, 506, 517, + 508, 509, 510, 511, 512, 513, 263, 264, 378, 379, + 1757, 2587, 462, 463, 2178, 2179, 3469, 3470, 518, 1766, + 421, 1768, 389, 220, 389, 225, 1634, 2650, 3501, 3502, + 1766, 2983, 1768, 2943, 1141, 1142, 300, 137, 1900, 373, + 517, 225, 225, 517, 297, 2671, 126, 127, 40, 236, + 1912, 2691, 3457, 2703, 517, 5, 3461, 5, 517, 325, + 517, 1808, 517, 517, 5, 1812, 5, 5, 1815, 1816, + 517, 517, 5, 2815, 9, 3211, 517, 517, 480, 302, + 1942, 104, 521, 518, 518, 521, 40, 1949, 220, 423, + 389, 425, 172, 460, 3065, 460, 504, 505, 506, 1707, + 508, 509, 510, 511, 512, 513, 1853, 167, 442, 287, + 285, 3516, 59, 2629, 448, 747, 167, 451, 236, 517, + 431, 1868, 517, 1985, 93, 521, 266, 1989, 1875, 1876, + 431, 1849, 8, 1995, 59, 11, 59, 1884, 108, 15, + 16, 431, 447, 19, 20, 21, 431, 527, 431, 222, + 294, 3429, 431, 1900, 37, 1972, 2018, 1904, 1905, 42, + 1907, 1978, 479, 380, 152, 1912, 1913, 1914, 1915, 1916, + 1917, 1918, 100, 275, 1921, 1922, 1923, 1924, 1925, 1926, + 1927, 1928, 1929, 1930, 275, 517, 40, 275, 275, 1936, + 1937, 147, 517, 1940, 294, 1942, 3167, 275, 199, 152, + 1947, 172, 1949, 519, 13, 172, 162, 521, 518, 353, + 515, 167, 518, 357, 519, 518, 518, 2898, 101, 225, + 518, 518, 1969, 518, 476, 1972, 3362, 1974, 517, 225, + 862, 1978, 1840, 282, 1972, 315, 316, 317, 1985, 282, + 1978, 1849, 1989, 2759, 1991, 389, 1993, 517, 1995, 517, + 521, 39, 1972, 353, 519, 466, 517, 357, 1978, 3178, + 2910, 2911, 218, 517, 519, 475, 147, 517, 517, 3405, + 517, 2018, 517, 9, 429, 429, 11, 2754, 517, 355, + 516, 162, 238, 2030, 2031, 527, 167, 521, 1037, 389, + 173, 524, 521, 429, 280, 517, 517, 431, 181, 1972, + 163, 181, 382, 172, 457, 1978, 518, 521, 1972, 218, + 392, 266, 521, 393, 1978, 227, 460, 291, 3454, 313, + 313, 2068, 521, 199, 2071, 521, 209, 220, 55, 2076, + 2077, 287, 3037, 181, 296, 415, 518, 218, 517, 419, + 296, 3293, 225, 227, 275, 227, 222, 334, 288, 469, + 787, 517, 235, 517, 2101, 2102, 152, 238, 152, 2106, + 460, 2106, 152, 479, 1972, 152, 40, 152, 3, 275, + 1978, 517, 452, 2120, 290, 102, 2123, 3235, 2125, 3, + 290, 818, 2898, 463, 40, 11, 269, 2903, 59, 172, + 40, 167, 518, 518, 2141, 2142, 123, 518, 517, 479, + 517, 2148, 2879, 518, 2151, 842, 287, 290, 181, 517, + 167, 3, 539, 2151, 141, 296, 292, 544, 145, 39, + 547, 2168, 3, 503, 431, 515, 515, 431, 431, 431, + 2168, 2151, 315, 518, 2950, 2951, 519, 517, 2185, 322, + 877, 168, 500, 518, 171, 516, 500, 524, 2168, 518, + 148, 518, 518, 521, 518, 2202, 2203, 172, 3429, 518, + 187, 500, 518, 431, 155, 518, 250, 517, 1217, 2331, + 40, 517, 2219, 517, 2221, 517, 517, 476, 2151, 59, + 172, 364, 506, 2230, 521, 468, 502, 2151, 291, 291, + 3432, 447, 521, 454, 244, 2168, 59, 59, 2106, 266, + 383, 2248, 2249, 2250, 2168, 3145, 275, 431, 517, 152, + 203, 152, 2248, 2249, 2250, 8, 2124, 431, 11, 152, + 431, 282, 15, 16, 431, 40, 19, 20, 21, 1161, + 431, 282, 2140, 518, 355, 517, 517, 521, 518, 288, + 2287, 978, 290, 2151, 152, 479, 2293, 280, 40, 986, + 172, 59, 518, 280, 517, 186, 167, 3018, 1307, 515, + 2168, 288, 518, 519, 80, 517, 447, 518, 143, 452, + 199, 515, 518, 518, 457, 2314, 7, 8, 172, 301, + 2325, 2314, 13, 310, 2331, 2314, 518, 517, 19, 518, + 527, 2314, 23, 361, 25, 521, 518, 518, 29, 30, + 31, 518, 2349, 34, 2466, 2352, 37, 38, 291, 517, + 41, 152, 339, 44, 45, 518, 2352, 517, 517, 2366, + 2367, 518, 181, 315, 316, 317, 521, 2374, 504, 505, + 506, 518, 508, 509, 510, 511, 512, 513, 2374, 3155, + 3156, 176, 442, 518, 3221, 518, 3223, 3261, 518, 517, + 40, 3167, 519, 517, 40, 151, 518, 3233, 89, 90, + 521, 517, 2524, 1100, 86, 2412, 1037, 172, 795, 521, + 517, 457, 103, 1110, 518, 518, 172, 108, 109, 110, + 111, 112, 199, 478, 518, 516, 516, 290, 178, 521, + 382, 518, 2412, 1130, 518, 518, 518, 463, 1037, 506, + 59, 518, 1139, 518, 2451, 518, 199, 1339, 518, 1341, + 205, 117, 3236, 203, 3238, 3420, 479, 2325, 40, 2466, + 517, 227, 88, 2478, 3364, 192, 2539, 419, 280, 222, + 280, 3354, 431, 40, 431, 506, 2483, 519, 519, 2412, + 3373, 519, 2489, 2490, 519, 519, 873, 519, 2412, 519, + 275, 241, 107, 518, 2501, 519, 2501, 519, 517, 519, + 452, 519, 516, 519, 519, 2512, 519, 2629, 2515, 516, + 2517, 463, 3348, 519, 519, 519, 1525, 2524, 2525, 519, + 519, 2528, 2529, 479, 40, 519, 2533, 2534, 519, 2534, + 519, 519, 518, 2540, 519, 519, 923, 517, 519, 292, + 519, 519, 519, 519, 518, 295, 519, 290, 2555, 517, + 9, 938, 939, 940, 941, 354, 2553, 517, 2565, 315, + 316, 317, 517, 2553, 336, 517, 59, 521, 2553, 518, + 199, 2553, 2553, 521, 2553, 2553, 518, 516, 192, 462, + 2587, 2559, 2587, 521, 91, 518, 1217, 8, 347, 517, + 11, 40, 152, 519, 15, 16, 518, 124, 19, 20, + 21, 152, 2724, 990, 40, 518, 369, 369, 40, 518, + 1619, 517, 517, 40, 521, 36, 310, 517, 1217, 2626, + 457, 517, 2629, 2630, 280, 2632, 382, 249, 191, 457, + 2626, 442, 517, 2501, 2630, 74, 2632, 2644, 293, 2646, + 74, 9, 80, 8, 518, 518, 11, 37, 517, 371, + 15, 16, 42, 3429, 19, 20, 21, 518, 516, 516, + 59, 133, 93, 419, 506, 3402, 2534, 273, 1365, 290, + 40, 2670, 442, 423, 517, 425, 1307, 2670, 517, 82, + 2802, 2670, 293, 293, 518, 2553, 518, 2670, 2666, 518, + 205, 2559, 290, 462, 290, 368, 452, 518, 448, 389, + 122, 451, 148, 454, 25, 108, 36, 463, 1307, 368, + 298, 101, 2903, 871, 2721, 2693, 2613, 2724, 2696, 2587, + 1774, 2243, 2626, 479, 1682, 1241, 2286, 788, 1818, 2313, + 2374, 3018, 2662, 3379, 2741, 2742, 3484, 3138, 3433, 2746, + 3442, 2746, 2749, 3477, 3196, 2822, 1204, 503, 1757, 2236, + 2249, 504, 505, 506, 2682, 508, 509, 510, 511, 512, + 513, 517, 3431, 3440, 2233, 2605, 3428, 1303, 2355, 2776, + 1349, 174, 1875, 2632, 2564, 3325, 3263, 1331, 2563, 3405, + 3358, 3506, 877, 173, 2791, 2553, 2219, 2909, 1161, 2796, + 2797, 1010, 117, 1010, 2801, 2802, 2185, 1746, 2666, 2806, + 203, 222, 2809, 2810, 1187, 2433, 3414, 2814, 2815, 2202, + 1710, 2818, 3327, 3336, 1186, 2822, 1203, 3225, 1189, 209, + 1745, 2943, 2829, 23, 2822, 2693, 2168, 2749, 2696, 1216, + 1983, 2836, 3060, 804, 988, 225, 2412, 2411, 2458, 3159, + 1998, 986, 2822, 246, 1884, 235, 793, 172, 539, 986, + 1237, 3340, 986, 544, 986, 986, 547, 222, 3339, 1884, + 1752, 986, 2078, 2490, 555, 40, 2873, 986, 986, 986, + 1762, 292, 1764, 2186, 2881, 1767, 2124, 2121, 2746, 269, + 2080, 1773, 2032, 1775, 2829, 60, 1450, 2508, 103, 2822, + 1681, 1900, 1991, 2900, 1525, -1, 1788, -1, 2822, -1, + 3022, 1793, 2909, 1912, 848, 1797, 1798, 1799, 1800, -1, + 1802, 1803, -1, -1, -1, 1302, -1, -1, -1, -1, + -1, 1308, -1, -1, -1, 315, 1525, 292, -1, -1, + -1, 106, 322, 1942, -1, -1, 2943, -1, -1, -1, + 1949, -1, -1, 3065, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 2822, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 2836, -1, + 373, 1037, -1, -1, 364, 1672, 1985, -1, -1, 304, + 1989, 384, 2989, 2990, -1, -1, 1995, -1, 1619, -1, + 315, 316, 317, 383, 2990, -1, -1, 1037, -1, 1696, + 1697, 176, -1, -1, -1, 8, -1, -1, 11, 2018, + -1, 3018, 15, 16, 3021, 3022, 419, -1, -1, -1, + 1619, 2999, -1, -1, -1, -1, -1, 202, -1, -1, + 3037, -1, 3037, -1, -1, -1, -1, -1, -1, 442, + -1, -1, -1, 46, -1, 3167, -1, -1, -1, -1, + 53, -1, -1, -1, 745, 746, 747, 382, 3065, -1, + -1, -1, 452, 3070, -1, 1452, 469, -1, -1, -1, + -1, -1, -1, -1, 3081, 3082, 251, 80, 3085, -1, + 3087, -1, -1, 504, 505, 506, 261, 508, 509, 510, + 511, 512, 513, -1, 419, -1, 787, 788, 273, -1, + -1, -1, 793, -1, 795, 3112, -1, 1804, -1, -1, + -1, -1, -1, 804, -1, -1, -1, 808, 809, -1, + 1817, 1818, 813, 814, -1, -1, 1757, 452, -1, 3136, + 305, 2999, -1, -1, -1, 826, 827, 828, 463, 504, + 505, 506, 145, 508, 509, 510, 511, 512, 513, 840, + 841, 1217, 843, -1, 479, -1, -1, -1, 1757, -1, + 3167, -1, -1, -1, -1, 856, -1, -1, 151, 3037, + -1, 862, -1, -1, 177, -1, -1, 1217, 503, -1, + -1, -1, 873, -1, 359, 876, 877, 1884, -1, 172, + -1, 194, 517, 1890, -1, -1, 199, -1, -1, 3206, + 3207, -1, -1, -1, 3211, 3183, 3184, -1, -1, 384, + -1, 3207, -1, -1, 3221, -1, 3223, -1, 3225, -1, + -1, -1, 3229, -1, 3231, -1, 3233, -1, 403, -1, + -1, 3211, 923, 924, 237, -1, -1, 3244, -1, -1, + -1, 1307, 3249, -1, 3251, -1, -1, 938, 939, 940, + 941, 942, 3259, -1, -1, 993, -1, -1, -1, -1, + -1, -1, -1, -1, 955, 3272, -1, 1307, -1, 1900, + 3277, 2163, -1, -1, -1, -1, 3272, -1, 3211, -1, + -1, 1912, 3260, -1, 3262, -1, -1, 3211, -1, 292, + -1, -1, -1, 1680, -1, 1682, 987, 988, -1, 990, + -1, 1900, 993, -1, -1, -1, 1693, 3429, 999, 1000, + -1, 1942, -1, 1912, 1005, 3183, 3184, -1, 1949, 3326, + 1011, -1, 2331, -1, 3302, -1, -1, 1018, -1, 3336, + -1, -1, 315, 316, 317, -1, -1, 1028, -1, -1, + 3318, 3348, -1, 1942, 3322, -1, -1, -1, 1735, -1, + 1949, -1, -1, 1044, 1985, 3362, -1, -1, 1989, -1, + -1, -1, -1, -1, 1995, -1, -1, -1, -1, -1, + -1, -1, -1, 3380, -1, -1, 0, -1, -1, -1, + -1, -1, 3362, -1, -1, -1, 1985, 2018, -1, -1, + 1989, 394, 3260, -1, 3262, -1, 1995, -1, 3405, 382, + -1, -1, 1093, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 3420, -1, -1, -1, -1, -1, 2018, + -1, -1, 3429, -1, 3431, 3405, -1, -1, -1, 3362, + -1, -1, -1, -1, 3302, 3431, 419, -1, 3362, -1, + -1, 1828, 1829, 1830, 1831, -1, 1833, 3454, -1, 2341, + 3318, -1, -1, 1144, 3322, -1, 1147, 2466, -1, 1525, + -1, 3468, 3469, 3470, -1, -1, -1, -1, 3446, 452, + 1161, 1162, 3405, -1, 3454, -1, 100, -1, 1169, -1, + 463, 3405, 172, -1, -1, 1525, -1, -1, 3495, -1, + -1, -1, -1, -1, 3472, -1, 479, -1, 501, -1, + -1, -1, 1193, -1, -1, 508, 509, 510, 511, 512, + 513, -1, 1203, 1204, -1, 2524, -1, -1, -1, -1, + 503, 3454, -1, 147, 8, 1216, -1, 11, -1, 3536, + 3454, 15, 16, -1, 517, 19, 20, 21, 162, -1, + -1, -1, 1233, 167, -1, -1, 1237, -1, 172, -1, + -1, 1242, -1, 1619, -1, -1, -1, 181, 2255, -1, + -1, -1, 186, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 1963, 172, 3446, 1619, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1519, -1, -1, 80, -1, -1, 2425, 2426, 2427, - -1, 13, -1, 970, -1, -1, -1, 19, 1139, -1, - 1141, -1, -1, -1, 981, 1176, -1, 1519, -1, 31, - -1, -1, -1, -1, 1185, 1156, 1157, -1, -1, -1, - -1, -1, 1163, 45, 46, -1, -1, -1, 501, 502, - 503, -1, 505, 506, 507, 508, 509, 510, -1, -1, - -1, -1, -1, -1, 1185, 1410, 1411, -1, -1, -1, - -1, 1416, -1, 1030, -1, 1196, 1197, -1, -1, -1, - -1, 3428, -1, -1, -1, -1, -1, -1, 1209, -1, - -1, 8, -1, -1, 1612, -1, -1, -1, 15, 16, - 176, -1, 19, 20, 21, 1226, 108, 3454, -1, 1230, - -1, -1, -1, -1, 1235, -1, -1, 193, -1, -1, - 1612, -1, 198, -1, -1, -1, -1, 1033, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 1096, - -1, -1, -1, -1, -1, -1, 2564, -1, -1, 1106, - -1, -1, -1, -1, -1, -1, 1185, -1, -1, -1, - 236, -1, -1, -1, -1, -1, -1, -1, -1, 1126, - 1291, -1, 1293, -1, -1, -1, -1, -1, 1135, -1, - -1, 1302, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8, 1313, -1, 11, -1, -1, -1, 15, 16, - -1, 1322, 19, 20, 21, -1, 1327, -1, 1329, 1330, - -1, 1332, 1333, -1, -1, 291, -1, -1, -1, 36, - -1, -1, -1, -1, -1, -1, -1, -1, 1746, -1, - -1, -1, -1, -1, -1, 1741, -1, 2655, -1, 1360, - -1, -1, -1, -1, -1, 1751, -1, 1753, -1, -1, - 1756, 3411, -1, -1, 1746, -1, 1762, -1, 1764, 1410, - 1411, -1, -1, -1, -1, 1416, -1, -1, -1, -1, - -1, 1777, -1, -1, -1, -1, 1782, -1, -1, -1, - 1786, 1787, 1788, 1789, -1, 1791, 1792, -1, -1, 1410, - 1411, -1, -1, -1, 2319, 1416, -1, 1418, -1, 2717, - 2718, 2719, 2720, -1, 1210, -1, -1, -1, -1, -1, - 1431, -1, 1433, 1434, -1, 391, -1, -1, -1, -1, - 1441, -1, 1443, -1, 1445, -1, -1, 1448, -1, -1, - -1, -1, 1453, 1033, -1, 1456, -1, 1458, -1, -1, - -1, 1462, -1, 1464, -1, 1466, -1, -1, -1, -1, + 13, -1, -1, -1, 218, -1, 19, -1, -1, -1, + -1, -1, -1, -1, 3472, -1, -1, 30, -1, 1300, + 2307, 1302, -1, -1, 238, -1, -1, 1308, -1, -1, + 2629, 44, 45, -1, -1, 315, 316, 317, 2325, -1, + -1, 1322, -1, 37, -1, -1, -1, -1, 42, -1, + 1331, -1, -1, -1, -1, 1336, 1037, 1338, 1339, 8, + 1341, 1342, 11, -1, -1, -1, 15, 16, -1, -1, + 19, 20, 21, 287, -1, -1, 290, -1, -1, -1, + 2367, -1, 296, -1, -1, -1, -1, 36, -1, 2376, + -1, 2378, -1, 1421, 1422, 2382, 109, 2384, -1, 1427, + -1, 1757, 382, -1, -1, -1, -1, 101, 2590, 2591, + 2331, -1, -1, -1, -1, -1, -1, -1, -1, 304, + -1, -1, 336, -1, -1, 2724, -1, 1757, -1, -1, + 315, 316, 317, -1, -1, -1, 2618, -1, -1, 419, + 1421, 1422, 2331, -1, -1, -1, 1427, 361, 1429, -1, + -1, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, + 2642, 1442, -1, 1444, 1445, -1, -1, -1, -1, -1, + -1, 1452, 452, -1, 1455, -1, -1, 1458, -1, 173, + -1, -1, 1463, 463, -1, 1466, -1, 993, -1, -1, + 1471, -1, 1473, -1, 1475, -1, -1, 382, -1, 479, + -1, -1, -1, 2802, -1, 419, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 209, -1, -1, 292, -1, + -1, -1, -1, 503, -1, -1, -1, -1, -1, -1, + -1, 225, -1, 447, 419, -1, 1217, 517, -1, -1, + -1, 235, -1, 457, 1900, 2466, 8, -1, -1, 11, + -1, -1, -1, 15, 16, -1, 1912, 19, 20, 21, + -1, -1, 476, -1, 478, 479, -1, 452, -1, -1, + 1900, -1, -1, 222, -1, 269, -1, 2466, 463, -1, + -1, -1, 1912, -1, -1, -1, 1942, -1, -1, -1, + -1, -1, -1, 1949, 479, -1, 290, -1, -1, 1580, + -1, 515, -1, 2524, 518, 519, 520, -1, -1, -1, + 2909, 1592, 1942, -1, -1, -1, -1, -1, 503, 1949, + -1, 315, -1, -1, -1, -1, 1307, -1, 322, 1985, + -1, -1, 517, 1989, -1, 2524, 993, -1, 2315, 1995, + -1, -1, 2629, 292, 2943, -1, -1, -1, -1, -1, + 1631, 2328, 2329, 2330, -1, 1985, -1, -1, -1, 1989, + -1, -1, 2018, -1, -1, 1995, 2343, -1, -1, 2346, + 364, -1, -1, -1, -1, 2662, -1, 2354, 1184, -1, + -1, -1, -1, -1, -1, -1, -1, 1193, 2018, 383, + -1, -1, -1, -1, -1, -1, -1, 1678, 2880, 1680, + -1, 1682, -1, -1, -1, -1, -1, -1, 2629, -1, + -1, -1, 1693, -1, 1695, 1696, 1697, -1, -1, -1, + -1, -1, -1, 3022, -1, -1, -1, -1, -1, 1710, + 504, 505, 506, -1, 508, 509, 510, 511, 512, 513, + 2629, -1, -1, -1, -1, 0, -1, -1, -1, -1, + -1, -1, -1, -1, 1735, -1, 1737, -1, 452, -1, + 222, -1, -1, 2440, 2441, 2442, 3065, -1, -1, -1, + 1751, 1752, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1762, 1763, 1764, 1765, -1, 1767, -1, 40, -1, + -1, -1, 1773, -1, 1775, -1, -1, -1, -1, -1, + -1, -1, -1, 2724, -1, -1, 1787, 1788, 60, -1, + -1, 1792, 1793, -1, -1, -1, 1797, 1798, 1799, 1800, + 8, 1802, 1803, -1, -1, -1, -1, 15, 16, -1, + 292, 19, 20, 21, -1, 2724, 1193, -1, 1819, 2826, + -1, -1, 555, -1, 1525, 100, -1, 1828, 1829, 1830, + 1831, 1832, 1833, -1, 106, 504, 505, 506, -1, 508, + 509, 510, 511, 512, 513, -1, 1847, -1, 3167, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 2802, 1863, -1, -1, 1913, 1914, 1915, 1916, 1917, + 1918, -1, 147, 1921, 1922, 1923, 1924, 1925, 1926, 1927, + 1928, 1929, 1930, -1, 2581, -1, -1, 162, -1, -1, + -1, -1, 167, 2802, -1, 1421, 1422, 172, -1, -1, + -1, 1427, -1, -1, -1, -1, 181, -1, -1, -1, + -1, 186, 1913, 1914, 1915, 1916, 1917, 1918, 1619, -1, + 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, + 202, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 74, -1, 218, -1, 3147, -1, 80, -1, -1, + 1951, -1, -1, 37, -1, 2331, -1, -1, 42, -1, + 93, -1, 1963, 238, -1, -1, 3168, 3169, 2909, -1, + -1, 1972, -1, -1, -1, 2672, -1, 1978, -1, 251, + -1, 2331, 1983, -1, 117, -1, 119, 1988, 2995, 261, + -1, 3193, -1, -1, -1, -1, 1997, 1998, -1, 40, + 2909, 273, 2943, -1, -1, -1, -1, -1, -1, -1, + -1, 3018, 287, 746, 747, 290, -1, 101, -1, 60, + -1, 296, 504, 505, 506, -1, 508, 509, 510, 511, + 512, 513, -1, 305, 2943, -1, -1, 2734, 2735, 2736, + 2737, -1, -1, -1, 1421, 1422, -1, -1, -1, -1, + 1427, -1, -1, 2101, 2102, -1, 1757, -1, -1, -1, + -1, 336, -1, -1, -1, 106, 107, -1, 2069, -1, + -1, -1, 2073, -1, 207, -1, 117, 2078, -1, -1, + -1, 3022, -1, -1, 292, -1, 361, 359, -1, 173, + 2466, 3098, -1, -1, -1, -1, -1, -1, -1, -1, + 2101, 2102, -1, -1, -1, -1, -1, -1, -1, -1, + 3429, -1, 384, 3022, -1, -1, 2466, 2118, -1, -1, + -1, -1, -1, -1, 3065, 209, -1, -1, -1, 862, + -1, 403, -1, -1, -1, 176, -1, -1, -1, -1, + -1, 225, 275, -1, 419, -1, -1, 280, 2524, -1, + 2151, 235, -1, -1, -1, -1, 3065, -1, -1, -1, + 3167, 202, 2163, -1, -1, -1, -1, 2168, -1, -1, + -1, 2172, 447, -1, 2524, -1, -1, -1, -1, -1, + -1, -1, 457, -1, 1710, 269, -1, -1, -1, -1, + 2887, -1, -1, -1, -1, -1, 329, -1, -1, 1900, + -1, 476, -1, 478, 479, -1, 290, -1, -1, -1, + 251, 1912, -1, -1, 347, 2216, -1, -1, 2219, -1, + 261, 2222, 178, 3425, -1, -1, 3167, -1, -1, -1, + -1, 315, 273, -1, 275, -1, -1, 2238, 322, -1, + 515, 1942, -1, 518, 519, 520, -1, 203, 1949, -1, + -1, -1, -1, 2629, -1, -1, -1, -1, 3167, -1, + -1, -1, -1, -1, 305, -1, -1, -1, -1, -1, + -1, -1, 1005, -1, -1, -1, -1, -1, -1, 2629, + 364, -1, -1, 1660, 1985, 241, -1, 3294, 1989, -1, + -1, -1, -1, -1, 1995, 1028, 504, 505, 506, 383, + 508, 509, 510, 511, 512, 513, -1, -1, 2309, -1, + -1, -1, -1, -1, 2315, 448, -1, 2018, 359, -1, + -1, -1, -1, -1, 457, -1, 2327, 2328, 2329, 2330, + -1, -1, -1, 1710, -1, -1, -1, -1, -1, 295, + 2341, -1, 2343, 384, -1, 2346, -1, -1, 2724, 2350, + -1, -1, -1, 2354, -1, -1, -1, -1, 314, 2360, + 1093, -1, 403, -1, 405, -1, -1, 408, 452, -1, + -1, -1, -1, 457, 2724, -1, -1, -1, -1, 2380, + 2381, -1, 2383, -1, -1, -1, -1, 1913, 1914, 1915, + 1916, 1917, 1918, -1, -1, 1921, 1922, 1923, 1924, 1925, + 1926, 1927, 1928, 1929, 1930, -1, -1, -1, -1, -1, + -1, 2412, -1, -1, -1, -1, -1, 373, -1, -1, + -1, -1, 3429, -1, 380, -1, 2802, -1, 1161, 1162, + 8, 2432, 24, 11, -1, -1, -1, 15, 16, 2440, + 2441, 2442, -1, 98, -1, -1, -1, -1, 2449, -1, + 2451, 2452, 2802, -1, -1, -1, -1, 2458, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 423, 46, 425, + -1, 126, 127, -1, -1, 53, 517, 2478, -1, -1, + 2528, 2529, -1, -1, -1, -1, 442, -1, 3429, 81, + 3187, 2492, 448, -1, -1, 451, -1, -1, -1, -1, + -1, -1, 80, -1, -1, 97, -1, -1, -1, -1, + -1, 3208, -1, -1, -1, -1, -1, 172, -1, -1, + 3429, -1, -1, -1, -1, -1, -1, 2528, 2529, -1, + -1, -1, -1, 2909, -1, -1, 1913, 1914, 1915, 1916, + 1917, 1918, -1, -1, 1921, 1922, 1923, 1924, 1925, 1926, + 1927, 1928, 1929, 1930, 146, -1, 2557, -1, -1, 2909, + -1, -1, 2563, -1, 156, -1, -1, 2943, -1, -1, + -1, -1, -1, 3270, -1, 2101, 2102, 169, -1, -1, + 2581, -1, 174, -1, 2585, -1, -1, -1, 2589, 2590, + 2591, -1, -1, 2943, 2595, 2596, 2597, -1, 2599, 177, + -1, -1, -1, -1, 3301, 1338, 1339, 8, 1341, -1, + 11, 203, -1, -1, 15, 16, 194, 2618, -1, 2620, + -1, 199, -1, -1, -1, -1, -1, -1, -1, -1, + 2331, -1, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, + 2641, 2642, -1, -1, -1, 46, 3022, -1, -1, -1, + -1, -1, 53, -1, 246, -1, -1, -1, 250, 237, + 315, 316, 317, -1, 2665, -1, -1, -1, -1, -1, + -1, 2672, 3022, 2721, -1, -1, -1, -1, -1, 80, + -1, 2682, -1, -1, -1, -1, -1, -1, -1, 3065, + -1, -1, -1, 2219, -1, -1, -1, -1, -1, 2700, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 2710, + -1, 1444, -1, -1, 292, 3065, -1, -1, -1, -1, + 2721, -1, -1, -1, 2101, 2102, 2727, 382, 320, -1, + -1, -1, -1, 2734, 2735, 2736, 2737, -1, 393, -1, + 1473, -1, 1475, 335, 145, 2746, -1, -1, 2749, -1, + -1, -1, 2753, 2754, -1, -1, -1, -1, -1, -1, + 415, 2762, -1, -1, 419, 2466, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 177, -1, 370, -1, + -1, 373, -1, -1, 439, -1, -1, -1, -1, 2790, + -1, 3167, 384, 194, 0, 387, -1, 452, 199, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 463, -1, + -1, -1, -1, 405, -1, -1, 394, 3167, -1, 2820, + -1, 2822, -1, 2524, 479, -1, -1, 419, -1, -1, + -1, -1, -1, 2881, 426, 2836, 237, -1, -1, 2840, + -1, -1, 2219, -1, 436, 2846, -1, -1, 503, -1, + 442, -1, -1, -1, -1, -1, -1, -1, -1, 2860, + -1, -1, 517, -1, -1, 2866, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 469, 2879, 2880, + 2881, -1, -1, -1, -1, -1, 2887, -1, -1, -1, + -1, 292, -1, -1, 100, -1, -1, -1, -1, -1, + -1, -1, -1, 2904, -1, -1, 8, -1, -1, 11, + -1, -1, -1, 15, 16, -1, -1, -1, -1, -1, + -1, -1, -1, 501, -1, -1, -1, -1, 2629, -1, + 508, 509, 510, 511, 512, 513, -1, -1, -1, -1, + -1, 147, -1, -1, 46, -1, -1, -1, -1, -1, + -1, 53, -1, -1, -1, -1, 162, -1, -1, -1, + -1, 167, -1, -1, -1, -1, 172, -1, -1, -1, + -1, -1, -1, 3021, -1, 181, -1, -1, 80, -1, + 186, 2982, -1, -1, 2985, -1, -1, -1, -1, -1, + -1, -1, -1, 394, -1, -1, -1, 2998, -1, -1, + -1, -1, 2528, 2529, 1737, -1, -1, -1, -1, -1, + -1, -1, 218, 3014, -1, -1, -1, -1, -1, 1752, + 3021, -1, -1, 2724, -1, -1, -1, -1, -1, 1762, + -1, 1764, 238, -1, 1767, -1, -1, -1, -1, -1, + 1773, -1, 1775, 145, -1, -1, 3047, -1, -1, -1, + -1, -1, 3053, 3429, -1, 1788, -1, -1, -1, 3060, + 1793, -1, -1, -1, 1797, 1798, 1799, 1800, -1, 1802, + 1803, -1, -1, -1, -1, 177, -1, -1, -1, 3429, + -1, 287, -1, -1, 290, -1, -1, -1, -1, -1, + 296, 8, 194, 3094, 11, -1, -1, 199, 15, 16, + 501, 2802, 19, 20, 21, -1, -1, 508, 509, 510, + 511, 512, 513, -1, -1, 3116, -1, -1, -1, -1, + 3121, -1, -1, -1, -1, -1, -1, -1, -1, 46, + 336, -1, -1, -1, -1, 237, 53, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 3147, -1, -1, -1, + -1, 2528, 2529, -1, -1, 361, -1, -1, -1, -1, + -1, -1, -1, 80, -1, -1, -1, 3168, 3169, -1, + -1, 8, -1, -1, 11, -1, -1, -1, 15, 16, + -1, -1, -1, -1, -1, -1, 3187, -1, 3189, -1, + 292, -1, 3193, -1, -1, 2721, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 3208, 2909, 46, + 3211, -1, -1, 419, -1, -1, 53, -1, 1951, -1, + 2746, -1, -1, 838, 839, -1, -1, -1, -1, -1, + 3231, -1, -1, -1, 3235, 3236, -1, 3238, -1, -1, + -1, 447, 2943, 80, -1, -1, -1, -1, -1, -1, + 1983, 457, -1, -1, -1, 1988, -1, -1, -1, -1, + 177, -1, 3263, -1, -1, 2791, -1, -1, -1, 3270, + 476, -1, 478, 479, -1, -1, -1, 194, -1, -1, + -1, -1, 199, 3, -1, 5, -1, -1, -1, -1, + -1, -1, 394, 908, -1, -1, -1, 912, 913, -1, + 3301, -1, -1, -1, -1, -1, -1, -1, 145, 515, + -1, -1, 518, 519, 520, -1, -1, -1, -1, -1, + 237, 3022, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 2069, -1, -1, 3340, + 177, -1, -1, -1, 2721, 2078, -1, -1, 68, 69, + 965, -1, -1, -1, -1, 2881, -1, 194, -1, -1, + -1, 3362, 199, -1, 3065, -1, -1, -1, 983, 2746, + -1, -1, -1, -1, 989, 292, -1, 992, -1, -1, + 995, 996, 997, 998, -1, -1, -1, -1, 3389, 109, + 110, -1, -1, 113, 114, -1, -1, -1, -1, 501, + 237, 3402, 3403, -1, 3405, 3406, 508, 509, 510, 511, + 512, 513, -1, 3414, -1, -1, -1, -1, -1, -1, + 1035, 1036, -1, -1, 3425, -1, -1, -1, -1, -1, + 2163, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1056, -1, -1, -1, -1, 3447, -1, -1, -1, + -1, -1, -1, 3454, -1, 292, -1, -1, -1, -1, + 1075, -1, -1, -1, -1, -1, 3167, -1, -1, 189, + 190, 1086, 1087, 1088, -1, 1090, 1091, 394, -1, -1, + -1, -1, -1, 2216, -1, -1, -1, -1, -1, 2222, + 3491, -1, -1, -1, -1, 3021, -1, -1, -1, -1, + -1, -1, -1, -1, 2881, 3506, -1, -1, -1, 1124, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1890, -1, 291, -1, -1, -1, -1, -1, - -1, 1410, 1411, -1, 1902, -1, -1, 1416, -1, -1, - -1, -1, 1298, -1, -1, -1, -1, -1, 1890, 1356, - -1, -1, -1, 1360, 221, -1, -1, -1, -1, -1, - 1902, -1, -1, -1, 1932, -1, -1, -1, -1, -1, - -1, 1939, 498, -1, -1, 501, 502, 503, 2453, 505, - 506, 507, 508, 509, 510, -1, -1, -1, -1, -1, - 1932, -1, -1, -1, -1, -1, -1, 1939, -1, -1, - -1, 2869, -1, 1574, -1, -1, -1, -1, -1, 1977, - -1, -1, -1, 1981, 1585, 8, -1, -1, 11, 1987, - -1, -1, 15, 16, 291, -1, 19, 20, 21, -1, - -1, -1, -1, -1, 2509, 1977, -1, -1, -1, 1981, - -1, 2009, -1, -1, -1, 1987, -1, -1, -1, -1, - -1, -1, -1, 1624, -1, -1, -1, -1, -1, -1, - 1210, -1, -1, -1, -1, -1, -1, 2009, -1, -1, + -1, -1, -1, -1, -1, -1, 1141, 1142, -1, -1, + -1, -1, -1, 253, 254, 255, 256, 257, 258, 259, + 260, -1, -1, 263, 264, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 394, -1, -1, + -1, -1, -1, -1, 1179, -1, -1, -1, 1183, 1184, + -1, -1, -1, -1, -1, -1, -1, -1, 8, 1194, + 1195, 11, -1, -1, 501, 15, 16, 504, 505, 506, + -1, 508, 509, 510, 511, 512, 513, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 2341, -1, + -1, -1, -1, -1, -1, -1, 46, 337, 338, -1, + -1, -1, -1, 53, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 1252, -1, -1, + -1, -1, -1, -1, 3021, -1, 1261, -1, -1, -1, + 80, -1, -1, -1, -1, -1, -1, 0, 378, 379, + -1, -1, -1, -1, 501, -1, -1, -1, -1, -1, + 1285, 508, 509, 510, 511, 512, 513, -1, -1, 22, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, + -1, 34, 35, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 47, 3231, -1, -1, -1, 52, + -1, -1, -1, -1, -1, 145, 2449, -1, 61, 2452, + -1, -1, -1, -1, -1, 2458, -1, -1, 3429, -1, + -1, -1, 75, -1, -1, -1, -1, -1, -1, -1, + -1, 84, -1, 86, -1, -1, -1, 177, -1, -1, + -1, -1, -1, 473, 474, 98, 1371, 100, -1, -1, + -1, -1, -1, -1, 194, -1, -1, -1, 111, 199, + -1, -1, -1, -1, -1, -1, -1, 497, 498, -1, + -1, -1, -1, 126, 127, 128, -1, -1, -1, -1, + -1, -1, -1, -1, 137, -1, -1, -1, -1, -1, + 143, -1, -1, -1, -1, -1, -1, 237, 151, -1, + 153, 154, -1, -1, -1, -1, -1, -1, -1, 1434, + -1, 1436, 1437, -1, -1, 168, -1, -1, -1, 172, + -1, -1, -1, -1, 1449, 1450, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1465, -1, 2585, -1, 3231, 198, 2589, 2590, 2591, -1, + -1, -1, 292, -1, -1, -1, -1, -1, -1, -1, + -1, 214, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 2618, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 240, -1, -1, + 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1698, -1, 551, - 1671, -1, 1673, -1, 1675, -1, -1, -1, 1903, 1904, - 1905, 1906, 1907, 1908, 1685, 1686, 1911, 1912, 1913, 1914, - 1915, 1916, 1917, 1918, 1919, 1920, -1, 1698, -1, -1, - -1, -1, -1, -1, 501, 502, 503, 2612, 505, 506, - 507, 508, 509, 510, -1, -1, -1, -1, 1298, -1, - -1, -1, 1723, -1, 1725, -1, -1, -1, -1, -1, - -1, -1, -1, 1519, -1, -1, -1, -1, -1, 1740, - 1741, -1, -1, -1, 1653, -1, -1, -1, -1, -1, - 1751, 1752, 1753, 1754, -1, 1756, -1, -1, -1, -1, - -1, 1762, -1, 1764, -1, -1, 2152, -1, -1, -1, - -1, 8, -1, -1, 11, 1776, 1777, -1, 15, 16, - 1781, 1782, 19, 20, 21, 1786, 1787, 1788, 1789, 1698, - 1791, 1792, -1, -1, -1, -1, -1, -1, 221, -1, - -1, -1, 2707, -1, 501, 502, 503, 1808, 505, 506, - 507, 508, 509, 510, -1, 1816, -1, 1818, 1819, 1820, - 1821, 1822, -1, -1, -1, -1, 1612, -1, 1665, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 1839, -1, + -1, -1, -1, -1, -1, 8, -1, -1, 11, -1, + -1, -1, 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1852, -1, -1, -1, -1, -1, -1, -1, -1, - 742, 743, -1, -1, -1, 2090, 2091, -1, 291, -1, - -1, 3169, 1903, 1904, 1905, 1906, 1907, 1908, -1, 2784, - 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, - -1, -1, 3190, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1903, 1904, 1905, 1906, 1907, 1908, -1, -1, - 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, - -1, 2319, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 1519, - 1941, -1, -1, 2329, -1, -1, -1, 2319, -1, -1, - -1, -1, 1953, -1, 3252, -1, 1793, -1, -1, -1, - 1746, -1, 1963, -1, -1, -1, -1, -1, 1969, 1806, - 1807, -1, -1, -1, 1975, -1, -1, 859, -1, 1980, - -1, -1, -1, -1, 221, 3283, 2891, -1, 1989, 1990, - -1, 24, -1, -1, 1903, 1904, 1905, 1906, 1907, 1908, - -1, -1, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, - 1919, 1920, -1, -1, -1, -1, -1, -1, -1, -1, - 2925, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1612, -1, -1, -1, 1873, -1, -1, -1, - -1, -1, 1879, -1, -1, -1, -1, -1, 81, -1, - -1, -1, -1, -1, 291, 2453, -1, 2058, -1, 2090, - 2091, 2062, -1, -1, 97, -1, 2067, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 501, 502, - 503, 2453, 505, 506, 507, 508, 509, 510, -1, 2090, - 2091, -1, -1, -1, -1, -1, -1, -1, -1, 3004, - -1, -1, -1, -1, 1890, -1, 2107, -1, -1, -1, - -1, 2509, -1, 146, -1, -1, 1902, -1, 1000, -1, - -1, -1, -1, 156, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 168, -1, 2509, -1, 2140, - 173, 1023, 3047, -1, -1, -1, 1932, -1, -1, -1, - -1, 2152, -1, 1939, -1, -1, 2157, -1, -1, -1, - 2161, -1, -1, -1, -1, -1, 1746, -1, -1, 202, - -1, -1, -1, 2204, -1, -1, -1, -1, -1, -1, - -1, 2090, 2091, -1, -1, -1, -1, 2573, 2574, -1, - -1, 1977, -1, -1, -1, 1981, -1, 37, -1, -1, - 2201, 1987, 42, 2204, -1, -1, 2207, 1089, -1, -1, - -1, -1, 245, -1, 2612, 2601, 249, -1, -1, -1, - -1, -1, 2223, 2009, -1, -1, -1, -1, -1, -1, - 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, - 2612, -1, -1, -1, 3149, -1, -1, -1, -1, -1, + -1, 1566, -1, 36, -1, -1, -1, -1, -1, 1574, + -1, -1, -1, 46, 394, -1, -1, -1, -1, -1, + 53, -1, 315, 316, 317, -1, -1, -1, -1, -1, + 323, -1, -1, 326, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 2727, -1, -1, 80, -1, 1614, + -1, -1, -1, -1, -1, 1620, 1621, 1622, 1623, 1624, + 1625, 1626, 1627, -1, 357, -1, -1, 1632, 1633, -1, + 2753, -1, 1637, 366, -1, -1, 1641, -1, -1, 1644, + 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, -1, 382, + 1655, -1, -1, -1, -1, -1, 389, 1662, -1, 1664, + 393, -1, -1, -1, -1, -1, -1, -1, -1, 8, + 403, -1, 11, -1, -1, -1, 15, 16, 1683, -1, + -1, 501, 415, -1, -1, -1, 419, -1, 508, 509, + 510, 511, 512, 513, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 177, -1, 439, 46, -1, -1, + -1, -1, -1, -1, 53, -1, 1721, 1722, -1, 452, + -1, 194, 455, -1, -1, 458, 199, -1, -1, -1, + 463, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 80, -1, -1, -1, -1, 479, -1, 26, 222, + 223, -1, -1, -1, 32, -1, -1, 2880, -1, -1, + -1, -1, 40, -1, 237, -1, -1, -1, -1, -1, + 503, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 60, -1, 517, -1, -1, 520, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 101, -1, -1, 501, 502, 503, -1, 505, 506, - 507, 508, 509, 510, 1156, 1157, -1, -1, -1, -1, - 313, -1, -1, -1, -1, -1, 319, -1, 2513, 2514, - -1, -1, -1, 2294, -1, 2204, -1, -1, -1, -1, - 2301, 334, 126, 127, -1, -1, -1, -1, -1, 2707, - 1890, 2312, -1, -1, 2315, 2316, 2317, 2318, -1, -1, - -1, -1, 1902, -1, -1, -1, -1, -1, 2329, -1, - 2331, -1, 172, 2334, 367, 2707, -1, 370, 2339, -1, - 180, -1, -1, -1, 2345, -1, -1, 171, 381, -1, - -1, 384, 1932, -1, -1, -1, -1, -1, -1, 1939, - -1, -1, -1, -1, 2365, 2366, -1, 2368, 208, 402, + -1, -1, 275, 1808, -1, 278, 145, 1812, -1, -1, + 1815, 1816, -1, -1, -1, -1, -1, -1, -1, 292, + -1, -1, 295, -1, -1, -1, -1, -1, 106, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 177, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1853, -1, + -1, -1, -1, -1, -1, 194, -1, -1, -1, 137, + 199, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1875, 1876, -1, 8, -1, -1, 11, -1, -1, -1, + 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 237, 1904, + 1905, 36, 1907, -1, -1, -1, -1, -1, -1, 26, + -1, 46, -1, -1, -1, 32, -1, -1, 53, -1, + -1, 394, -1, 40, 202, -1, -1, -1, -1, -1, + 3053, 1936, 1937, -1, -1, 1940, -1, 3060, -1, -1, + -1, -1, -1, 60, -1, 80, -1, -1, -1, -1, + -1, -1, -1, 292, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 1969, -1, -1, -1, -1, 1974, + -1, -1, -1, 251, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 261, -1, -1, 1991, -1, 1993, 106, + -1, -1, -1, 3116, -1, 273, -1, -1, 3121, -1, + -1, -1, -1, 993, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 294, -1, -1, -1, + 137, -1, -1, -1, 3147, -1, 2031, 305, 501, -1, + -1, 504, 505, 506, -1, 508, 509, 510, 511, 512, + 513, -1, 177, -1, -1, 3168, 3169, -1, -1, -1, + -1, -1, -1, -1, 527, 394, -1, -1, -1, 194, + -1, -1, -1, 2068, 199, -1, 2071, -1, -1, -1, + 3193, 2076, 2077, -1, -1, 353, -1, -1, -1, 357, + -1, 359, -1, -1, -1, 202, -1, 222, 223, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 416, 224, -1, 2784, -1, -1, 422, - 423, -1, -1, -1, 234, -1, 2397, 1977, -1, -1, - 433, 1981, -1, 2240, -1, -1, 439, 1987, -1, -1, - -1, -1, 2784, -1, -1, -1, 2417, -1, -1, -1, - -1, -1, -1, -1, 2425, 2426, 2427, -1, 268, 2009, - -1, -1, -1, 466, 2435, -1, 2437, -1, 2439, -1, - -1, -1, -1, -1, 2445, -1, -1, 1329, 1330, 289, - 1332, -1, -1, -1, -1, 2292, -1, -1, -1, -1, + -1, -1, 237, -1, -1, -1, 384, -1, -1, -1, + -1, 389, 3235, -1, -1, 2120, -1, -1, 2123, -1, + 2125, 1111, -1, -1, -1, 403, -1, -1, -1, -1, + -1, -1, -1, -1, 251, -1, 2141, -1, -1, -1, + 275, -1, -1, 278, 261, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 273, 292, -1, -1, + 295, -1, 501, -1, -1, -1, -1, 1157, -1, 508, + 509, 510, 511, 512, 513, -1, -1, 294, -1, -1, + 2185, -1, 460, -1, -1, -1, -1, -1, 305, -1, + -1, -1, -1, -1, 3, -1, -1, 2202, 2203, 8, + -1, -1, 11, 1193, -1, -1, 15, 16, 17, 18, + 19, 20, 21, -1, -1, -1, 2221, -1, -1, -1, + -1, -1, -1, -1, -1, 2230, -1, 36, -1, -1, + -1, 40, -1, -1, -1, -1, 353, 46, -1, -1, + 357, -1, 359, -1, 53, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 1246, -1, -1, 394, + -1, -1, -1, -1, -1, -1, -1, 384, -1, -1, + -1, 80, 389, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 2287, -1, -1, -1, 403, -1, 2293, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 2310, 314, -1, 2862, 2478, -1, 2704, - -1, 321, 2513, 2514, -1, -1, -1, -1, -1, -1, - 314, 315, 316, 2891, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3411, -1, -1, -1, - -1, -1, 2513, 2514, -1, 2352, -1, -1, -1, 2891, - -1, 361, -1, -1, 2361, -1, 2363, 2925, -1, -1, - 2367, -1, 2369, 2319, -1, -1, -1, -1, -1, -1, - 380, 2542, -1, -1, -1, -1, -1, 2548, -1, -1, - -1, 1433, -1, 2925, -1, 379, -1, -1, -1, -1, - -1, -1, -1, 2564, -1, -1, 390, 2568, -1, -1, - -1, 2572, 2573, 2574, -1, -1, -1, 2578, 2579, 2580, - -1, 2582, 1464, -1, 1466, -1, -1, -1, 412, -1, - -1, -1, 416, -1, -1, -1, -1, -1, -1, -1, - 2601, 0, 2603, -1, 2513, 2514, 3004, -1, -1, 449, - -1, -1, -1, -1, 454, 2616, 2617, 2618, 2619, 2620, - 2621, 2622, 2623, 2624, 2625, 449, -1, -1, -1, -1, - -1, -1, 3004, -1, -1, -1, 460, -1, 2863, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 2649, 3047, - -1, -1, 476, -1, 2655, 8, -1, -1, 11, -1, - -1, -1, 15, 16, -1, -1, 2667, 2453, -1, -1, - -1, -1, -1, 2704, -1, 3047, 500, -1, -1, -1, - -1, -1, 2683, -1, -1, -1, -1, -1, -1, -1, - 514, -1, 2693, 46, -1, -1, -1, -1, 2729, -1, - 53, 100, -1, 2704, -1, -1, -1, -1, -1, 2710, - -1, -1, -1, -1, -1, -1, 2717, 2718, 2719, 2720, - -1, -1, -1, 2509, -1, -1, -1, 80, 2729, -1, - -1, 2732, -1, -1, -1, 2736, 2737, -1, -1, 2319, - -1, -1, 2773, 3129, 2745, -1, -1, -1, 147, -1, - -1, 3149, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 161, -1, 3150, 3151, -1, 166, -1, -1, - -1, 2772, 171, -1, -1, 2612, -1, 3149, 3003, -1, - -1, 180, -1, -1, -1, -1, 185, -1, -1, -1, - 3176, -1, 145, -1, -1, 2704, -1, -1, -1, -1, - -1, 2802, -1, 2804, -1, -1, -1, -1, 2645, -1, - -1, -1, -1, -1, -1, -1, -1, 2818, 217, -1, - 2729, 2822, -1, 176, -1, -1, 2612, 2828, -1, -1, - -1, -1, 2863, -1, -1, -1, 26, -1, 237, -1, - 193, 2842, 32, 1725, -1, 198, -1, 2848, -1, -1, - 40, -1, -1, -1, -1, -1, -1, -1, -1, 1741, - 2861, 2862, 2863, -1, -1, -1, -1, -1, 2869, 1751, - 60, 1753, -1, 2453, 1756, -1, -1, -1, -1, -1, - 1762, -1, 1764, 236, -1, 2886, -1, 286, -1, -1, - 289, -1, -1, -1, -1, 1777, 295, -1, -1, -1, - 1782, -1, -1, -1, 1786, 1787, 1788, 1789, -1, 1791, - 1792, -1, -1, -1, -1, -1, 106, -1, -1, -1, - -1, 2707, -1, -1, -1, -1, -1, -1, -1, 2509, - -1, -1, -1, -1, -1, -1, 335, -1, 291, -1, - -1, -1, -1, -1, -1, -1, -1, 137, -1, -1, - -1, -1, -1, -1, 2863, -1, -1, -1, -1, 358, - -1, -1, -1, 2964, -1, -1, -1, 2968, -1, -1, - -1, 2808, 3003, -1, -1, -1, -1, 835, 836, -1, - -1, 2982, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 2996, -1, -1, 2784, -1, - -1, -1, 3003, -1, -1, -1, -1, -1, -1, -1, - -1, 201, -1, 3411, -1, -1, -1, 416, 98, -1, - -1, 3407, -1, -1, -1, -1, -1, -1, 3029, -1, - -1, -1, 2612, -1, 3035, -1, -1, -1, 391, 3411, - -1, 3042, -1, -1, 902, 444, 126, 127, 906, 907, - -1, -1, -1, -1, -1, 454, -1, -1, -1, 1941, - 250, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 260, -1, -1, -1, 473, 3076, 475, 476, -1, -1, - -1, -1, 272, -1, -1, -1, 0, -1, -1, -1, - -1, 171, -1, 1975, 3003, -1, -1, 3098, 1980, -1, - -1, 959, 3103, 293, -1, 2891, -1, -1, -1, -1, - -1, -1, -1, 512, 304, -1, 515, 516, 517, -1, - 978, -1, -1, -1, -1, -1, 984, 2707, 3129, 987, - -1, -1, 990, 991, 992, 993, -1, -1, -1, 2925, - 2977, -1, -1, -1, -1, 498, -1, -1, -1, 3150, - 3151, -1, 505, 506, 507, 508, 509, 510, -1, -1, - 350, -1, -1, 3000, 354, -1, 356, -1, 3169, -1, - 3171, -1, -1, 1031, 1032, 3176, 2058, -1, -1, -1, - -1, -1, 3213, -1, -1, 2067, 100, -1, -1, 3190, - -1, 381, 3193, -1, 1052, -1, 386, -1, -1, -1, - -1, -1, -1, -1, 2784, -1, -1, -1, -1, -1, - 400, -1, 3213, 1071, 68, 69, 3217, 3218, 3004, 3220, - -1, -1, -1, -1, 1082, 1083, 1084, -1, 1086, 1087, - -1, -1, -1, 147, 314, 315, 316, -1, -1, -1, - 3, -1, 5, 3080, 3245, -1, -1, 161, -1, -1, - -1, 3252, 166, -1, -1, 109, 110, 171, -1, 113, - 114, 3047, 1120, -1, -1, -1, 180, 457, -1, -1, - 2152, 185, -1, -1, -1, -1, -1, -1, -1, 1137, - 1138, -1, 3283, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 379, - -1, -1, -1, 217, 3213, 68, 69, -1, -1, -1, - 390, 2891, 3149, 1171, -1, -1, -1, 1175, 1176, 2201, - -1, 3322, -1, 237, -1, 2207, -1, -1, 1186, 1187, - -1, -1, 412, -1, 188, 189, 416, -1, -1, -1, - -1, -1, -1, 3344, -1, 2925, 109, 110, -1, -1, - 113, 114, -1, -1, -1, -1, 436, -1, -1, -1, - -1, -1, -1, 3149, -1, -1, -1, -1, -1, 449, - 3371, -1, 286, -1, -1, 289, -1, -1, -1, -1, - 460, 295, -1, 3384, 3385, 1243, 3387, 3388, -1, -1, - -1, -1, -1, -1, 1252, 3396, 476, -1, 252, 253, - 254, 255, 256, 257, 258, 259, 3407, -1, 262, 263, - -1, -1, -1, -1, -1, -1, -1, -1, 1276, -1, - 500, 335, -1, -1, 3004, 188, 189, -1, 3429, -1, - -1, -1, -1, -1, 514, 3436, -1, -1, -1, 3276, - -1, -1, -1, -1, 358, -1, -1, 2329, -1, -1, + 1290, -1, 3425, -1, -1, 1295, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 3047, -1, -1, - -1, -1, 3473, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 3488, -1, 252, - 253, 254, 255, 256, 257, 258, 259, -1, -1, 262, - 263, -1, 416, -1, -1, 1363, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 375, 376, -1, -1, -1, -1, -1, -1, -1, - 444, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 454, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 2435, -1, -1, -1, 2439, -1, 473, - -1, 475, 476, 2445, -1, 1423, -1, 1425, 1426, 3149, - -1, -1, -1, -1, 3411, -1, -1, -1, -1, -1, - 1438, 1439, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1455, 512, -1, - -1, 515, 516, 517, -1, -1, -1, -1, -1, -1, - -1, -1, 375, 376, -1, -1, 470, 471, -1, -1, - -1, 8, -1, -1, 11, 3411, -1, -1, 15, 16, - 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, - 494, 495, -1, -1, -1, -1, -1, -1, -1, 36, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, - 514, -1, -1, -1, -1, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 2568, -1, -1, -1, - 2572, 2573, 2574, 80, -1, -1, -1, -1, -1, -1, - -1, -1, 1560, -1, -1, -1, -1, 470, 471, -1, - 1568, -1, -1, -1, -1, -1, -1, -1, -1, 2601, + -1, -1, -1, 460, 2349, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 1345, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 501, -1, 177, 504, + 505, 506, -1, 508, 509, 510, 511, 512, 513, 1369, + -1, -1, -1, -1, -1, 194, 521, -1, 8, -1, + 199, 11, -1, -1, -1, 15, 16, 17, 18, 19, + 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 222, 223, -1, 36, -1, -1, -1, + 40, -1, -1, -1, -1, -1, 46, 1417, 237, 1419, + -1, 1421, 1422, 53, 1424, -1, -1, 1427, -1, -1, + 1430, -1, -1, 1433, -1, -1, -1, -1, 1438, -1, + -1, 1441, -1, -1, -1, -1, -1, -1, -1, -1, + 80, -1, -1, -1, -1, -1, 275, -1, -1, 278, + -1, -1, -1, -1, -1, -1, -1, -1, 2483, -1, + -1, -1, -1, 292, 2489, 2490, 295, -1, 1478, -1, + -1, -1, 8, -1, -1, 11, 2501, -1, -1, 15, + 16, -1, -1, 19, 20, 21, -1, 2512, -1, -1, + 2515, -1, 2517, -1, -1, -1, -1, -1, -1, -1, + 2525, -1, -1, -1, -1, -1, -1, -1, 2533, 2534, + 46, -1, -1, -1, -1, 2540, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 494, 495, -1, 2616, 2617, 2618, 2619, 2620, 2621, - 2622, 2623, 2624, 2625, -1, -1, -1, -1, -1, 1607, - -1, -1, -1, -1, -1, 1613, 1614, 1615, 1616, 1617, - 1618, 1619, 1620, -1, -1, -1, -1, 1625, 1626, -1, - -1, -1, 1630, -1, -1, -1, 1634, -1, -1, 1637, - 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, -1, 176, - 1648, -1, -1, -1, -1, -1, -1, 1655, -1, 1657, - -1, -1, -1, -1, -1, -1, 193, -1, -1, -1, - -1, 198, -1, -1, -1, -1, -1, -1, 1676, -1, - -1, -1, -1, -1, -1, 0, -1, -1, 2710, -1, - -1, 3411, -1, -1, 221, 222, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 22, -1, 236, - -1, 1709, 1710, -1, 2736, -1, -1, 32, -1, 34, - 35, 8, -1, -1, 11, -1, -1, -1, 15, 16, - -1, -1, 47, -1, -1, -1, -1, 52, -1, -1, - -1, -1, -1, -1, -1, -1, 61, 274, -1, -1, - 277, -1, -1, -1, -1, -1, -1, -1, -1, 46, - 75, -1, -1, -1, 291, -1, 53, 294, -1, 84, - -1, 86, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 98, -1, 100, -1, -1, -1, -1, - -1, -1, -1, 80, -1, -1, 111, -1, -1, 1797, - -1, -1, -1, 1801, -1, -1, 1804, 1805, -1, -1, - -1, 126, 127, 128, -1, -1, -1, -1, -1, -1, - -1, -1, 137, -1, -1, -1, -1, -1, 143, -1, - -1, -1, -1, -1, -1, -1, 151, -1, 153, 154, - 2862, -1, -1, -1, -1, -1, -1, 1845, -1, -1, - -1, -1, 167, -1, -1, -1, 171, -1, 145, -1, - -1, -1, -1, -1, 391, -1, 1864, 1865, -1, -1, + 2555, -1, -1, -1, -1, -1, -1, 177, -1, -1, + 2565, -1, -1, -1, 80, -1, -1, -1, -1, -1, + -1, -1, 1562, -1, 194, -1, -1, -1, -1, 199, + -1, -1, 2587, -1, -1, 394, -1, -1, 1578, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1588, 1589, + 1590, -1, 222, 223, -1, 1595, -1, -1, -1, 1599, + -1, -1, -1, -1, -1, -1, -1, 237, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 197, -1, -1, -1, -1, -1, -1, 176, - -1, -1, -1, -1, -1, -1, 1894, 1895, 213, 1897, - -1, -1, -1, -1, -1, 8, 193, -1, 11, -1, - -1, 198, 15, 16, 17, 18, 19, 20, 21, -1, - -1, -1, -1, -1, 239, -1, -1, -1, 1926, 1927, - -1, -1, 1930, 36, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 46, -1, -1, -1, -1, -1, 236, - 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1959, -1, -1, -1, -1, -1, 1965, -1, -1, - -1, 498, -1, -1, 501, 502, 503, 80, 505, 506, - 507, 508, 509, 510, -1, 1983, -1, 1985, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 524, -1, 314, - 315, 316, -1, -1, 291, -1, -1, 322, -1, -1, - 325, -1, -1, 3035, -1, -1, 988, -1, -1, -1, - 3042, -1, -1, 2021, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 354, - -1, -1, -1, -1, -1, -1, -1, -1, 363, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 2644, + -1, 2646, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 275, -1, -1, 278, -1, + -1, 177, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1661, 292, -1, -1, 295, -1, -1, 194, -1, + -1, -1, -1, 199, -1, -1, -1, -1, -1, -1, + -1, -1, 501, -1, -1, 504, 505, 506, -1, 508, + 509, 510, 511, 512, 513, -1, 222, 223, -1, -1, + -1, -1, -1, -1, 1704, -1, -1, -1, -1, -1, + -1, 237, -1, -1, -1, -1, -1, -1, -1, -1, + 1720, -1, -1, -1, -1, 1725, 2741, 2742, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 2060, -1, 379, 24, -1, 2065, 2066, -1, - -1, 386, -1, 176, -1, 390, 3098, -1, -1, -1, - -1, 3103, -1, -1, -1, 400, -1, -1, -1, -1, - 193, -1, -1, -1, -1, 198, -1, 412, -1, -1, - -1, 416, -1, -1, 391, -1, -1, 3129, -1, -1, - -1, 2109, -1, -1, 2112, -1, 2114, -1, 221, 222, - -1, 436, 81, -1, -1, -1, -1, -1, 3150, 3151, - -1, -1, 2130, 236, 449, 1107, -1, 452, 97, -1, - 455, -1, -1, -1, -1, 460, -1, -1, -1, -1, - -1, -1, -1, -1, 3176, -1, -1, -1, -1, -1, - -1, 476, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 274, 2170, -1, 277, -1, -1, -1, -1, -1, - 1152, -1, -1, -1, -1, 500, -1, 146, 291, 2187, - 2188, 294, -1, -1, -1, 3217, -1, 156, -1, 514, - -1, -1, 517, -1, -1, -1, -1, -1, 2206, 168, - -1, 498, -1, 1185, 173, -1, -1, 2215, 505, 506, - 507, 508, 509, 510, -1, -1, -1, -1, -1, -1, + -1, -1, 1742, -1, -1, -1, -1, -1, -1, 275, + -1, -1, 278, -1, -1, -1, -1, -1, -1, -1, + -1, 2776, -1, -1, 394, -1, 292, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 2791, -1, -1, -1, + -1, 2796, 2797, -1, -1, -1, 2801, -1, -1, -1, + -1, 2806, -1, -1, 2809, 2810, -1, -1, -1, 2814, + 2815, -1, -1, 2818, -1, -1, -1, -1, -1, -1, + -1, -1, 8, -1, 2829, 11, -1, -1, -1, 15, + 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 202, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8, -1, -1, 11, -1, - -1, -1, 15, 16, -1, 1237, 19, 20, 21, -1, - -1, -1, -1, -1, 2272, -1, -1, -1, -1, -1, - 2278, -1, -1, -1, -1, -1, 245, -1, 391, -1, - 249, -1, -1, 46, -1, -1, -1, -1, -1, -1, - 53, -1, -1, -1, -1, -1, -1, 1279, -1, -1, - -1, -1, -1, -1, 1286, -1, 3, -1, -1, -1, - -1, 8, -1, -1, 11, -1, -1, 80, 15, 16, - 17, 18, 19, 20, 21, -1, -1, -1, -1, 2337, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, - -1, -1, -1, 40, -1, -1, -1, -1, -1, 46, - 319, -1, -1, -1, 1336, -1, 53, -1, -1, -1, - -1, -1, -1, -1, -1, 334, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 3407, -1, -1, -1, 1361, - -1, -1, -1, 80, -1, 498, -1, -1, 501, 502, - 503, -1, 505, 506, 507, 508, 509, 510, 367, -1, - -1, 370, -1, -1, -1, 518, -1, -1, -1, -1, - -1, -1, 381, 176, -1, 384, -1, -1, -1, -1, - -1, -1, -1, -1, 1406, -1, 1408, -1, 1410, 1411, - 193, 1413, -1, 402, 1416, 198, -1, 1419, -1, -1, - 1422, -1, -1, -1, -1, 1427, -1, 416, 1430, -1, - -1, -1, -1, -1, 423, -1, -1, -1, 221, 222, - -1, 2469, -1, -1, 433, -1, -1, 2475, 2476, -1, - 439, -1, -1, 236, -1, -1, -1, -1, 2486, 176, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 2497, - 1472, -1, 2500, -1, 2502, -1, 193, 466, -1, -1, - -1, 198, 2510, -1, -1, -1, -1, -1, -1, -1, - 2518, 2519, -1, -1, 277, -1, -1, 2525, -1, -1, - -1, -1, -1, -1, 221, 222, -1, -1, 291, -1, - -1, -1, 2540, -1, -1, -1, -1, -1, -1, 236, - -1, -1, 2550, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 46, -1, -1, -1, -1, -1, -1, 53, 2873, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 394, -1, + -1, 501, -1, -1, 504, 505, 506, -1, 508, 509, + 510, 511, 512, 513, 80, 2900, -1, -1, 518, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 2570, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 1556, -1, -1, 274, -1, -1, - 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1572, -1, -1, -1, 291, -1, -1, 294, -1, -1, - 1582, 1583, 1584, -1, -1, -1, 1588, -1, -1, -1, - 1592, -1, -1, -1, -1, -1, -1, -1, -1, 2627, - -1, 2629, -1, -1, -1, -1, -1, -1, 391, -1, - 8, -1, -1, 11, -1, -1, -1, 15, 16, -1, + -1, -1, 1902, -1, -1, -1, -1, -1, -1, -1, + 1910, 1911, -1, 1913, 1914, 1915, 1916, 1917, 1918, -1, + -1, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, + 1930, 1931, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, - -1, 11, -1, -1, -1, 15, 16, -1, 46, -1, - -1, -1, 1654, -1, -1, 53, -1, 8, -1, -1, - 11, -1, -1, -1, 15, 16, 17, 18, 19, 20, - 21, -1, -1, -1, 391, -1, 46, -1, -1, -1, - -1, -1, 80, 53, -1, 36, -1, -1, -1, 40, - 1692, -1, -1, -1, -1, 46, 2724, 2725, -1, -1, - -1, -1, 53, -1, -1, -1, 1708, -1, -1, -1, - 80, 1713, -1, -1, -1, 498, -1, -1, 501, 502, - 503, -1, 505, 506, 507, 508, 509, 510, 1730, 80, - -1, 2759, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 2773, -1, 145, -1, -1, - 2778, 2779, -1, -1, -1, 2783, -1, -1, -1, -1, - 2788, -1, -1, 2791, 2792, -1, -1, -1, 2796, 2797, - -1, -1, 2800, -1, -1, 145, -1, -1, 176, -1, - -1, 498, -1, 2811, 501, 502, 503, -1, 505, 506, - 507, 508, 509, 510, -1, 193, -1, -1, -1, -1, - 198, -1, -1, -1, -1, -1, 176, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 193, -1, 176, -1, 2855, 198, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 236, -1, - -1, -1, 193, -1, -1, -1, -1, 198, -1, -1, - -1, -1, -1, -1, 2882, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 236, -1, -1, -1, - 221, 222, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 236, -1, -1, -1, -1, - 1892, -1, -1, 291, -1, -1, -1, -1, 1900, 1901, - -1, 1903, 1904, 1905, 1906, 1907, 1908, -1, -1, 1911, - 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, - -1, 291, -1, 274, -1, -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 291, -1, -1, 294, 2972, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, - -1, 11, -1, -1, -1, 15, 16, 17, 18, 19, - 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, - -1, 3019, -1, 391, -1, -1, 46, -1, -1, -1, - -1, -1, -1, 53, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 2989, 501, -1, -1, 504, 505, + 506, 177, 508, 509, 510, 511, 512, 513, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 194, -1, + -1, -1, -1, 199, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 391, 2024, -1, 3052, 2027, -1, -1, -1, -1, - 80, -1, -1, -1, -1, 3063, 3064, -1, -1, 3067, - 391, 3069, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 3037, -1, -1, -1, 222, 223, -1, -1, + -1, -1, -1, -1, 2034, -1, -1, 2037, -1, -1, + -1, 237, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 3070, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 3081, 3082, -1, -1, + 3085, -1, 3087, -1, -1, -1, -1, -1, -1, 275, + -1, -1, 278, -1, 2084, -1, -1, -1, 2088, 2089, + 2090, 2091, 2092, 2093, 2094, 2095, 292, 3112, -1, 295, + -1, 2101, 2102, -1, 2104, 2105, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 2116, -1, -1, 2119, + -1, 3136, -1, -1, -1, -1, -1, 2127, 2128, 2129, + 2130, 2131, 2132, 2133, 2134, 2135, 2136, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3094, -1, -1, -1, - -1, 2073, -1, -1, -1, 2077, 2078, 2079, 2080, 2081, - 2082, 2083, 2084, -1, -1, -1, -1, -1, 2090, 2091, - 3118, 2093, 2094, -1, -1, -1, -1, -1, -1, -1, - 498, -1, -1, 2105, -1, -1, 2108, 505, 506, 507, - 508, 509, 510, -1, 2116, 2117, 2118, 2119, 2120, 2121, - 2122, 2123, 2124, 2125, -1, -1, 176, -1, 498, -1, - -1, -1, -1, -1, -1, 505, 506, 507, 508, 509, - 510, -1, -1, 193, -1, -1, -1, 498, 198, 2151, - 501, 502, 503, -1, 505, 506, 507, 508, 509, 510, - -1, 3189, -1, -1, 515, -1, -1, -1, -1, -1, - -1, 221, 222, -1, -1, -1, -1, -1, -1, 3207, - -1, -1, -1, 3211, -1, -1, 236, 3215, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 3226, -1, - -1, -1, 2204, 3231, -1, 3233, -1, -1, -1, -1, - -1, -1, -1, 3241, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 274, -1, -1, 277, -1, -1, - -1, 3259, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 291, -1, -1, 294, -1, -1, -1, 8, -1, - -1, 11, -1, -1, -1, 15, 16, 17, 18, 19, - 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 2273, -1, -1, -1, -1, 36, -1, -1, -1, - 3308, 2283, 2284, -1, -1, -1, 46, -1, -1, -1, - 3318, -1, -1, 53, -1, -1, -1, -1, -1, -1, - -1, -1, 3330, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 3362, -1, -1, -1, -1, -1, - -1, 391, -1, -1, -1, -1, 2348, -1, -1, -1, + -1, 8, 2162, -1, 11, -1, -1, -1, 15, 16, + -1, -1, 19, 20, 21, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, + -1, 3206, -1, -1, -1, -1, -1, -1, 394, 46, + -1, -1, -1, -1, -1, -1, 53, -1, -1, -1, + 3225, -1, -1, -1, 3229, -1, -1, -1, 3233, 2219, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 3244, + -1, -1, -1, 80, 3249, -1, 3251, -1, -1, -1, + -1, -1, -1, -1, 3259, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, + -1, -1, 3277, 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 36, -1, -1, -1, 2288, -1, + -1, -1, -1, -1, 46, -1, -1, -1, 2298, 2299, + -1, 53, -1, -1, -1, 501, -1, -1, 504, 505, + 506, 3326, 508, 509, 510, 511, 512, 513, -1, -1, + -1, 3336, 518, -1, -1, -1, -1, -1, 80, -1, + 177, -1, -1, 3348, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 194, -1, -1, + -1, -1, 199, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 2363, -1, 3380, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 222, 223, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 2387, 2388, 2389, + 237, -1, 2392, 2393, 2394, 2395, 2396, 2397, -1, -1, + -1, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, + 2410, 8, -1, -1, 11, 2415, 2416, -1, 15, 16, + 17, 18, 19, 20, 21, 177, -1, -1, 275, -1, + -1, 278, -1, -1, -1, -1, -1, -1, -1, 36, + -1, -1, 194, 2443, -1, 292, -1, 199, 2448, 46, + -1, -1, -1, 3468, 3469, 3470, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 2372, 2373, 2374, -1, -1, 2377, 2378, 2379, 2380, 2381, - 2382, -1, -1, -1, 2386, 2387, 2388, 2389, 2390, 2391, - 2392, 2393, 2394, 2395, -1, -1, -1, -1, 2400, 2401, - -1, -1, 8, -1, -1, 11, -1, -1, -1, 15, - 16, 17, 18, 19, 20, 21, 176, -1, -1, -1, - -1, -1, 3450, 3451, 3452, -1, 2428, -1, -1, -1, - 36, -1, 2434, 193, -1, -1, -1, -1, 198, -1, - 46, -1, -1, -1, -1, -1, -1, 53, 498, 3477, - -1, 501, 502, 503, -1, 505, 506, 507, 508, 509, - 510, 221, 222, -1, -1, 515, 2468, -1, -1, -1, - -1, -1, -1, -1, 80, -1, 236, -1, -1, -1, - -1, -1, -1, -1, -1, 2487, -1, -1, 2490, 2491, - 3518, -1, -1, -1, -1, -1, 2498, 2499, -1, -1, + 222, 223, -1, -1, -1, -1, -1, -1, -1, -1, + 3495, -1, 2482, 80, -1, 237, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 2499, + -1, -1, 2502, -1, -1, 2505, 2506, -1, -1, -1, + -1, -1, -1, 2513, 2514, -1, -1, -1, -1, -1, + -1, 3536, -1, 275, -1, -1, 278, 2527, 2528, 2529, + 2530, -1, 2532, -1, -1, -1, 2536, -1, -1, -1, + 292, -1, -1, 295, -1, -1, -1, 394, -1, -1, + -1, -1, -1, -1, -1, 8, -1, -1, 11, -1, + -1, -1, 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 2512, 2513, 2514, 2515, 274, 2517, -1, 277, -1, 2521, + 177, -1, -1, 36, -1, -1, -1, -1, -1, -1, + -1, -1, 2592, 46, -1, -1, -1, 194, -1, -1, + 53, -1, 199, 8, -1, -1, 11, -1, -1, -1, + 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, + -1, -1, -1, -1, -1, 222, 223, 80, -1, -1, + -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, + 237, 46, 394, -1, -1, -1, -1, -1, 53, -1, + -1, -1, -1, -1, 501, -1, -1, 504, 505, 506, + -1, 508, 509, 510, 511, 512, 513, -1, -1, -1, + -1, -1, -1, -1, -1, 80, -1, -1, 275, -1, + -1, 278, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 292, -1, 2697, 295, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 291, -1, -1, 294, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 2721, -1, -1, 177, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 194, -1, -1, -1, -1, 199, -1, -1, 501, + -1, -1, 504, 505, 506, -1, 508, 509, 510, 511, + 512, 513, -1, -1, -1, -1, 518, -1, -1, 222, + 223, -1, 177, -1, -1, -1, -1, 2777, -1, 2779, + -1, -1, -1, -1, 237, -1, 2786, -1, -1, 194, + -1, -1, -1, -1, 199, 2795, -1, 394, 2798, -1, + 2800, -1, 8, -1, 2804, 11, -1, 2807, 2808, 15, + 16, 2811, 2812, 19, 20, 21, -1, 222, 223, 2819, + -1, -1, 275, -1, -1, 278, -1, -1, 2828, -1, + -1, -1, 237, -1, -1, -1, -1, -1, -1, 292, + 46, -1, 295, 2843, -1, -1, -1, 53, -1, -1, + -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, + -1, -1, -1, 15, 16, 17, 18, 19, 20, 21, + 275, -1, -1, 278, 80, -1, -1, -1, -1, -1, + -1, 2881, -1, -1, 36, -1, -1, 292, -1, -1, + 295, -1, -1, -1, 46, -1, -1, -1, -1, -1, + -1, 53, -1, -1, 501, -1, -1, 504, 505, 506, + -1, 508, 509, 510, 511, 512, 513, -1, -1, -1, + -1, 518, -1, -1, -1, -1, -1, -1, 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 176, -1, -1, 2575, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 193, -1, -1, - -1, 8, 198, -1, 11, -1, -1, -1, 15, 16, - 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 221, 222, -1, -1, 36, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, - 236, 391, -1, -1, -1, -1, 53, -1, -1, -1, - -1, 8, -1, -1, 11, -1, -1, -1, 15, 16, - 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, - -1, -1, -1, 80, -1, -1, -1, -1, 274, 36, - -1, 277, -1, -1, -1, -1, -1, -1, -1, 46, - 2682, -1, -1, -1, -1, 291, 53, 26, 294, -1, - -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, - -1, 40, 2704, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 80, -1, -1, -1, -1, -1, -1, - -1, 60, -1, 8, -1, -1, 11, -1, -1, -1, - 15, 16, 17, 18, 19, 20, 21, -1, 498, -1, - -1, 501, 502, 503, -1, 505, 506, 507, 508, 509, - 510, 36, -1, -1, -1, 515, -1, -1, 2760, 176, - 2762, 46, -1, -1, -1, -1, 2768, 106, 53, -1, - -1, -1, -1, -1, -1, 2777, 193, -1, 2780, -1, - 2782, 198, -1, -1, 2786, 391, -1, 2789, 2790, -1, - -1, 2793, 2794, -1, -1, 80, -1, -1, 137, 2801, - -1, -1, -1, -1, 221, 222, -1, -1, 2810, 176, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 236, - -1, -1, -1, 2825, -1, -1, 193, -1, -1, -1, - -1, 198, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 394, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 177, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 194, 394, + -1, -1, -1, 199, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 221, 222, -1, 274, -1, -1, - 277, 2863, 201, -1, -1, -1, -1, -1, -1, 236, - -1, -1, -1, -1, 291, -1, -1, 294, -1, -1, + -1, -1, -1, -1, -1, -1, 222, 223, -1, -1, + 3020, 3021, -1, -1, -1, 177, -1, -1, -1, -1, + -1, 237, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 194, -1, -1, 3045, 3046, 199, 501, -1, + -1, 504, 505, 506, -1, 508, 509, 510, 511, 512, + 513, -1, -1, -1, -1, 518, -1, -1, -1, 3069, + 222, 223, 278, 3073, -1, 3075, 3076, 3077, -1, -1, + 3080, -1, -1, 3083, 3084, 237, 292, -1, -1, -1, + -1, -1, 3092, -1, -1, -1, 501, -1, -1, 504, + 505, 506, -1, 508, 509, 510, 511, 512, 513, -1, + -1, -1, -1, 518, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 275, -1, -1, 278, -1, -1, -1, + -1, -1, -1, 3133, -1, -1, -1, -1, -1, 3139, + 292, -1, -1, 295, -1, -1, -1, -1, -1, -1, + -1, -1, 3152, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 176, 498, -1, -1, 501, 502, 503, -1, 505, - 506, 507, 508, 509, 510, -1, -1, 274, 193, 515, - 277, 250, -1, 198, -1, -1, -1, -1, -1, -1, - -1, 260, -1, -1, 291, -1, -1, 294, -1, -1, - -1, -1, -1, 272, -1, -1, 221, 222, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 236, -1, -1, 293, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 304, -1, -1, -1, -1, - -1, -1, -1, -1, 391, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 274, - 68, 69, 277, -1, -1, -1, -1, -1, -1, -1, - 3002, 3003, -1, -1, -1, -1, 291, -1, -1, 294, - -1, 350, -1, -1, -1, 354, -1, 356, -1, -1, - -1, -1, -1, -1, 391, 3027, 3028, -1, -1, -1, - -1, 109, 110, -1, -1, 113, 114, -1, -1, -1, - -1, -1, 381, -1, -1, -1, -1, 386, -1, 3051, - -1, -1, -1, 3055, -1, 3057, 3058, 3059, -1, -1, - 3062, 400, -1, 3065, 3066, -1, -1, -1, -1, -1, - -1, -1, 3074, -1, -1, -1, -1, -1, -1, -1, - -1, 498, -1, -1, 501, 502, 503, -1, 505, 506, - 507, 508, 509, 510, -1, -1, -1, -1, 515, -1, - -1, -1, -1, -1, -1, -1, 391, -1, -1, -1, - 188, 189, -1, 3115, -1, -1, -1, -1, 457, 3121, + -1, -1, -1, -1, -1, 3185, -1, -1, 394, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 498, 3134, -1, 501, 502, 503, -1, 505, 506, - 507, 508, 509, 510, -1, -1, -1, -1, 515, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3168, -1, -1, -1, - -1, -1, -1, -1, 252, 253, 254, 255, 256, 257, - 258, 259, -1, -1, 262, 263, -1, -1, -1, -1, - -1, -1, -1, 3195, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 3213, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 498, -1, -1, 501, 502, 503, -1, - 505, 506, 507, 508, 509, 510, 3228, 3229, 3230, -1, - 515, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3248, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 3260, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 394, -1, -1, -1, 3246, 3247, 3248, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 3266, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 3278, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 375, 376, -1, - -1, -1, -1, -1, 3306, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 501, -1, -1, 504, 505, + 506, -1, 508, 509, 510, 511, 512, 513, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 3323, -1, -1, -1, -1, -1, -1, -1, -1, - 3332, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 3323, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 3357, -1, -1, -1, -1, + -1, 3341, -1, -1, -1, -1, -1, -1, -1, 501, + 3350, -1, 504, 505, 506, -1, 508, 509, 510, 511, + 512, 513, -1, -1, -1, -1, 518, -1, -1, -1, + -1, -1, -1, -1, -1, 3375, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 3383, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 470, 471, -1, -1, -1, -1, -1, -1, + -1, 3401, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, - 6, 7, 8, 9, 10, -1, 494, 495, -1, -1, - -1, -1, -1, -1, 3426, -1, 22, 23, 24, 25, + 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 3444, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 3480, 75, + 66, 67, 68, 69, 70, 71, 72, 73, 3498, 75, 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, @@ -12492,148 +11268,44 @@ static const yytype_int16 yycheck[] = -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, -1, 162, 163, 164, 165, - -1, 167, -1, 169, 170, -1, 172, 173, 174, 175, - 176, 177, -1, 179, -1, 181, 182, 183, 184, -1, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, -1, 199, 200, 201, 202, 203, 204, 205, - -1, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, -1, 218, -1, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, -1, -1, 233, 234, 235, - 236, -1, 238, 239, 240, 241, 242, 243, 244, 245, + 156, 157, 158, 159, 160, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, 171, -1, 173, 174, 175, + 176, 177, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, -1, -1, 234, 235, + 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - -1, 287, 288, -1, -1, 291, 292, 293, -1, -1, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, -1, -1, - -1, -1, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, -1, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, -1, 345, - 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, -1, 359, 360, 361, 362, 363, 364, 365, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, -1, -1, 381, 382, 383, 384, 385, - 386, 387, 388, 389, -1, 391, 392, 393, 394, 395, - -1, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, -1, -1, 414, 415, - -1, 417, 418, 419, 420, 421, 422, 423, -1, 425, - 426, 427, -1, -1, 430, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, -1, -1, - 446, 447, 448, -1, 450, 451, 452, 453, -1, 455, - 456, 457, 458, 459, 460, 461, -1, 463, 464, 465, - 466, 467, 468, 469, 470, 471, -1, -1, 474, -1, - -1, 477, 478, 479, 480, 481, 482, 483, 484, 485, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, 394, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, 421, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, 467, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, - 496, 497, 498, -1, -1, -1, -1, -1, -1, 505, - 506, 507, -1, -1, -1, -1, 512, -1, 514, -1, - -1, -1, -1, 519, 520, -1, 522, 523, 524, 3, - 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, 39, -1, -1, 42, 43, - 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, 81, -1, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, - 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, -1, -1, 233, - 234, 235, 236, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, 391, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, 418, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - 464, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 498, -1, -1, -1, -1, -1, - -1, 505, 506, 507, -1, -1, -1, -1, 512, -1, - 514, -1, -1, -1, -1, 519, 520, -1, 522, 523, - 524, 3, 4, 5, 6, 7, 8, 9, 10, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, - 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, - 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, - -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, - 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, - 162, 163, 164, 165, -1, 167, -1, 169, 170, 171, - 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, - 182, 183, 184, -1, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, -1, 199, 200, 201, - 202, 203, 204, 205, -1, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, -1, 218, -1, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, -1, - -1, 233, 234, 235, 236, -1, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, -1, 287, 288, -1, -1, 291, - 292, 293, -1, -1, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, -1, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, -1, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, -1, 345, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, -1, 359, 360, 361, - 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, -1, 381, - 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, -1, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, -1, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, -1, 425, 426, 427, -1, -1, 430, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, -1, -1, 446, 447, 448, 449, 450, 451, - 452, 453, -1, 455, 456, 457, 458, 459, 460, 461, - -1, 463, 464, 465, 466, 467, 468, 469, 470, 471, - -1, -1, 474, -1, 476, 477, 478, 479, 480, 481, - 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 494, 495, 496, 497, 498, -1, 500, -1, - -1, -1, -1, 505, 506, 507, -1, -1, -1, -1, - 512, -1, 514, 515, -1, -1, -1, 519, 520, -1, - 522, 523, 3, 4, 5, 6, 7, 8, 9, 10, + 496, 497, 498, 499, 500, 501, -1, -1, -1, -1, + -1, -1, 508, 509, 510, -1, -1, -1, -1, 515, + -1, 517, -1, -1, -1, -1, 522, 523, -1, 525, + 526, 527, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, 39, -1, @@ -12645,47 +11317,257 @@ static const yytype_int16 yycheck[] = 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, - 171, 172, 173, 174, 175, 176, 177, -1, 179, -1, - 181, 182, 183, 184, -1, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, -1, 199, 200, - 201, 202, 203, 204, 205, -1, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, -1, 218, -1, 220, + 161, -1, 163, 164, 165, 166, -1, 168, -1, 170, + 171, -1, 173, 174, 175, 176, 177, 178, -1, 180, + -1, 182, 183, 184, 185, -1, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, -1, 200, + 201, 202, 203, 204, 205, 206, -1, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - -1, -1, 233, 234, 235, 236, -1, 238, 239, 240, + 231, -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, -1, 287, 288, -1, -1, - 291, 292, 293, -1, -1, 296, 297, 298, 299, 300, + 281, 282, 283, 284, 285, 286, -1, 288, 289, -1, + -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, -1, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, -1, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, -1, 345, 346, 347, 348, 349, 350, - 351, 352, 353, 354, 355, 356, 357, -1, 359, 360, - 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378, 379, -1, - 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, -1, 397, 398, 399, 400, + 311, 312, 313, 314, -1, -1, -1, -1, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 328, -1, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, -1, -1, 384, 385, 386, 387, 388, 389, 390, + 391, 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, 412, -1, 414, 415, 416, 417, 418, 419, 420, - 421, 422, 423, -1, 425, 426, 427, -1, -1, 430, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 443, -1, -1, 446, 447, 448, 449, 450, - 451, 452, 453, -1, 455, 456, 457, 458, 459, 460, - 461, -1, 463, 464, 465, 466, 467, 468, 469, 470, - 471, -1, -1, 474, -1, 476, 477, 478, 479, 480, + 411, 412, 413, 414, -1, -1, 417, 418, -1, 420, + 421, 422, 423, 424, 425, 426, -1, 428, 429, 430, + -1, -1, 433, 434, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, -1, -1, 449, 450, + 451, -1, 453, 454, 455, 456, -1, 458, 459, 460, + 461, 462, 463, 464, -1, 466, 467, 468, 469, 470, + 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 494, 495, 496, 497, 498, -1, 500, - -1, -1, -1, -1, 505, 506, 507, -1, -1, -1, - -1, 512, -1, 514, -1, -1, -1, -1, 519, 520, - -1, 522, 523, 3, 4, 5, 6, 7, 8, 9, + 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, + 501, -1, -1, -1, -1, -1, -1, 508, 509, 510, + -1, -1, -1, -1, 515, -1, 517, -1, -1, -1, + -1, 522, 523, -1, 525, 526, 527, 3, 4, 5, + 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, 171, 172, 173, 174, 175, + 176, 177, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, -1, -1, 234, 235, + 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, -1, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, 382, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, + -1, 417, 418, 419, 420, 421, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, 452, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, 467, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, 479, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 501, -1, 503, -1, -1, + -1, -1, 508, 509, 510, -1, -1, -1, -1, 515, + -1, 517, 518, -1, -1, -1, 522, 523, -1, 525, + 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, + 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, + -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, 171, + 172, 173, 174, 175, 176, 177, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, -1, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + 382, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, -1, 417, 418, 419, 420, 421, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + 452, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, 467, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, 479, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, + -1, 503, -1, -1, -1, -1, 508, 509, 510, -1, + -1, -1, -1, 515, -1, 517, -1, -1, -1, -1, + 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, + 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, + -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + -1, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, 171, 172, 173, 174, 175, 176, 177, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, -1, -1, 234, 235, 236, 237, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + -1, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, 394, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, 419, 420, 421, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, 452, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, 467, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, 479, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 501, -1, 503, -1, -1, -1, -1, + 508, 509, 510, -1, -1, -1, -1, 515, -1, 517, + -1, -1, -1, -1, 522, 523, -1, 525, 526, 3, + 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + -1, -1, -1, 37, -1, 39, -1, -1, 42, 43, + 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + -1, 75, 76, 77, 78, 79, -1, 81, -1, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, + 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, -1, 120, 121, 122, 123, + 124, 125, -1, -1, 128, 129, 130, 131, 132, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, 171, -1, 173, + 174, 175, 176, 177, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, -1, -1, + 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, -1, -1, -1, -1, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, 383, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, 421, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, + 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, + 494, 495, 496, 497, 498, 499, 500, 501, -1, -1, + -1, -1, -1, -1, 508, 509, 510, -1, -1, -1, + -1, 515, -1, 517, 518, -1, -1, -1, 522, 523, + -1, 525, 526, 3, 4, 5, 6, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, 39, @@ -12696,210 +11578,54 @@ static const yytype_int16 yycheck[] = -1, 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, - 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, -1, 162, 163, 164, 165, -1, 167, -1, 169, - 170, 171, 172, 173, 174, 175, 176, 177, -1, 179, - -1, 181, 182, 183, 184, -1, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, -1, 199, - 200, 201, 202, 203, 204, 205, -1, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, -1, 218, -1, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, -1, -1, 233, 234, 235, 236, -1, 238, 239, + 160, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, 171, 172, 173, 174, 175, 176, 177, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, -1, 287, 288, -1, - -1, 291, 292, 293, -1, -1, 296, 297, 298, 299, + 270, 271, 272, 273, 274, -1, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 314, 315, 316, -1, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, -1, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, -1, 345, 346, 347, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, -1, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, + 310, 311, 312, 313, 314, 315, 316, 317, -1, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - -1, 381, 382, 383, 384, 385, 386, 387, 388, 389, - -1, 391, 392, 393, 394, 395, -1, 397, 398, 399, + 380, 381, 382, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 411, -1, -1, 414, 415, 416, 417, 418, 419, - 420, 421, 422, 423, -1, 425, 426, 427, -1, -1, - 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, -1, -1, 446, 447, 448, 449, - 450, 451, 452, 453, -1, 455, 456, 457, 458, 459, - 460, 461, -1, 463, 464, 465, 466, 467, 468, 469, - 470, 471, -1, -1, 474, -1, 476, 477, 478, 479, + 410, 411, 412, 413, 414, 415, -1, 417, 418, 419, + 420, 421, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, 452, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, 467, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, - 490, 491, 492, 493, 494, 495, 496, 497, 498, -1, - 500, -1, -1, -1, -1, 505, 506, 507, -1, -1, - -1, -1, 512, -1, 514, -1, -1, -1, -1, 519, - 520, -1, 522, 523, 3, 4, 5, 6, 7, 8, - 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, -1, -1, -1, 37, -1, - 39, -1, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, 132, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, -1, 172, 173, 174, 175, 176, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, -1, -1, 233, 234, 235, 236, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, 380, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, - -1, -1, -1, -1, -1, -1, 505, 506, 507, -1, - -1, -1, -1, 512, -1, 514, 515, -1, -1, -1, - 519, 520, -1, 522, 523, 3, 4, 5, 6, 7, - -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, - 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, - -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - -1, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, - 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, - 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, - 118, -1, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, - 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, -1, 162, 163, 164, 165, -1, 167, - -1, 169, 170, 171, 172, 173, 174, 175, 176, 177, - -1, 179, -1, 181, 182, 183, 184, -1, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - -1, 199, 200, 201, 202, 203, 204, 205, -1, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, -1, - 218, -1, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, -1, -1, 233, 234, 235, 236, -1, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, -1, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, -1, 287, - 288, -1, -1, 291, 292, 293, -1, -1, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, -1, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - -1, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, -1, 345, 346, 347, - 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - -1, 359, 360, 361, 362, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, -1, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 411, 412, -1, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, -1, 425, 426, 427, - -1, -1, 430, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, -1, -1, 446, 447, - 448, 449, 450, 451, 452, 453, -1, 455, 456, 457, - 458, 459, 460, 461, -1, 463, 464, 465, 466, 467, - 468, 469, 470, 471, -1, -1, 474, -1, 476, 477, - 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, - 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, - -1, -1, 500, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 512, -1, 514, -1, -1, -1, - -1, 519, 520, -1, 522, 523, 3, 4, 5, 6, - 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, - 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, - -1, -1, 39, -1, -1, 42, 43, 44, -1, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, - 77, 78, 79, -1, 81, -1, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, - 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, - -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, - 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, - -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, -1, 179, -1, 181, 182, 183, 184, -1, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, -1, 199, 200, 201, 202, 203, 204, 205, -1, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - -1, 218, -1, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, -1, 232, 233, 234, 235, 236, - -1, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, -1, - 287, 288, -1, -1, 291, 292, 293, -1, -1, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, -1, -1, -1, - -1, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, -1, 329, 330, 331, 332, 333, 334, -1, 336, - 337, 338, 339, 340, 341, 342, 343, -1, 345, 346, - 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, - 357, -1, 359, 360, 361, 362, 363, 364, 365, 366, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, -1, -1, 381, 382, 383, 384, 385, 386, - 387, 388, 389, -1, 391, 392, 393, 394, 395, -1, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, -1, -1, 414, 415, -1, - 417, 418, 419, 420, 421, 422, 423, -1, 425, 426, - 427, -1, 429, 430, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, -1, -1, 446, - 447, 448, -1, 450, 451, 452, 453, -1, 455, 456, - 457, 458, 459, 460, 461, -1, 463, 464, 465, 466, - 467, 468, 469, 470, 471, -1, -1, 474, -1, -1, - 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, - 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, - 497, 498, -1, -1, -1, -1, -1, -1, 505, 506, - 507, -1, -1, -1, -1, 512, -1, 514, -1, -1, - -1, -1, 519, 520, -1, 522, 523, 3, 4, 5, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, -1, -1, 503, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 515, -1, 517, -1, -1, + -1, -1, 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, - -1, 37, -1, 39, -1, -1, 42, 43, 44, -1, + -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, @@ -12909,95 +11635,148 @@ static const yytype_int16 yycheck[] = -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, -1, 162, 163, 164, 165, - -1, 167, -1, 169, 170, -1, 172, 173, 174, 175, - 176, 177, -1, 179, -1, 181, 182, 183, 184, -1, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, -1, 199, 200, 201, 202, 203, 204, 205, - -1, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, -1, 218, -1, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, -1, -1, 233, 234, 235, - 236, -1, 238, 239, 240, 241, 242, 243, 244, 245, + 156, 157, 158, 159, 160, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, 171, 172, 173, 174, 175, + 176, 177, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, -1, 233, 234, 235, + 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - -1, 287, 288, -1, -1, 291, 292, 293, -1, -1, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, -1, -1, - -1, -1, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, -1, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, -1, 345, - 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, -1, 359, 360, 361, 362, 363, 364, 365, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, -1, 380, 381, 382, 383, 384, 385, - 386, 387, 388, 389, -1, 391, 392, 393, 394, 395, - -1, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, -1, -1, 414, 415, - -1, 417, 418, 419, 420, 421, 422, 423, -1, 425, - 426, 427, -1, -1, 430, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, -1, -1, - 446, 447, 448, -1, 450, 451, 452, 453, -1, 455, - 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, -1, -1, 474, -1, - -1, 477, 478, 479, 480, 481, 482, 483, 484, 485, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, 394, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, 421, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, 432, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, 467, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, - 496, 497, 498, -1, -1, -1, -1, -1, -1, 505, - 506, 507, -1, -1, -1, -1, 512, -1, 514, -1, - -1, -1, -1, 519, 520, -1, 522, 523, 3, 4, - 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, - 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, - -1, -1, 37, -1, 39, -1, -1, 42, 43, 44, - -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, - 75, 76, 77, 78, 79, -1, 81, -1, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, - 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, -1, 120, 121, 122, 123, 124, - 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, - 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, - 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, -1, 162, 163, 164, - 165, -1, 167, -1, 169, 170, -1, 172, 173, 174, - 175, 176, 177, -1, 179, -1, 181, 182, 183, 184, - -1, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, -1, 199, 200, 201, 202, 203, 204, - 205, -1, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, -1, 218, -1, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, -1, -1, 233, 234, - 235, 236, -1, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, -1, 287, 288, -1, -1, 291, 292, 293, -1, - -1, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, -1, - -1, -1, -1, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, -1, 329, 330, 331, 332, 333, 334, - -1, 336, 337, 338, 339, 340, 341, 342, 343, -1, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, -1, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, -1, 380, 381, 382, 383, 384, - 385, 386, 387, 388, 389, -1, 391, 392, 393, 394, - 395, -1, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, -1, -1, 414, - 415, -1, 417, 418, 419, 420, 421, 422, 423, -1, - 425, 426, 427, -1, -1, 430, 431, 432, 433, 434, - 435, 436, 437, 438, 439, 440, 441, 442, 443, -1, - -1, 446, 447, 448, -1, 450, 451, 452, 453, -1, - 455, 456, 457, 458, 459, 460, 461, -1, 463, 464, - 465, 466, 467, 468, 469, 470, 471, -1, -1, 474, - -1, -1, 477, 478, 479, 480, 481, 482, 483, 484, - 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, - 495, 496, 497, 498, -1, -1, -1, -1, -1, -1, - 505, 506, 507, -1, -1, -1, -1, 512, -1, 514, - 515, -1, -1, -1, 519, 520, -1, 522, 523, 3, + 496, 497, 498, 499, 500, 501, -1, -1, -1, -1, + -1, -1, 508, 509, 510, -1, -1, -1, -1, 515, + -1, 517, -1, -1, -1, -1, 522, 523, -1, 525, + 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, 37, -1, 39, -1, -1, + 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, + -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, 171, + -1, 173, 174, 175, 176, 177, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, 383, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, 421, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, + -1, -1, -1, -1, -1, -1, 508, 509, 510, -1, + -1, -1, -1, 515, -1, 517, -1, -1, -1, -1, + 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, + 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, 37, + -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + -1, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, 171, -1, 173, 174, 175, 176, 177, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, -1, -1, 234, 235, 236, 237, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, 383, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, 394, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, 421, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, 467, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 501, -1, -1, -1, -1, -1, -1, + 508, 509, 510, -1, -1, -1, -1, 515, -1, 517, + 518, -1, -1, -1, 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, @@ -13013,203 +11792,47 @@ static const yytype_int16 yycheck[] = 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, - 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, -1, -1, 233, - 234, 235, 236, -1, 238, 239, 240, 241, 242, 243, + 154, 155, 156, 157, 158, 159, 160, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, 171, -1, 173, + 174, 175, 176, 177, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, -1, -1, + 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, 299, 300, 301, 302, 303, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, 361, 362, 363, + 314, -1, -1, -1, -1, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, 391, 392, 393, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, 418, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, 421, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - 464, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, 467, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 498, -1, -1, -1, -1, -1, - -1, 505, 506, 507, -1, -1, -1, -1, 512, -1, - 514, -1, -1, -1, -1, 519, 520, -1, 522, 523, - 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, - 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, - 33, -1, -1, -1, 37, -1, 39, -1, -1, 42, - 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, -1, 75, 76, 77, 78, 79, -1, 81, -1, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - -1, 94, 95, 96, 97, 98, 99, -1, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, -1, 120, 121, 122, - 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, - -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, - -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, 159, 160, -1, 162, - 163, 164, 165, -1, 167, -1, 169, 170, -1, 172, - 173, 174, 175, 176, 177, -1, 179, -1, 181, 182, - 183, 184, -1, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, -1, 199, 200, 201, 202, - 203, 204, 205, -1, 207, 208, 209, 210, 211, 212, - 213, 214, 215, 216, -1, 218, -1, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, -1, -1, - 233, 234, 235, 236, -1, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, -1, 287, 288, -1, -1, 291, 292, - 293, -1, -1, 296, 297, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, -1, -1, -1, -1, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, -1, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, -1, 345, 346, 347, 348, 349, 350, 351, 352, - 353, 354, 355, 356, 357, -1, 359, 360, 361, 362, - 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, -1, 380, 381, 382, - 383, 384, 385, 386, 387, 388, 389, -1, 391, 392, - 393, 394, 395, -1, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 411, -1, - -1, 414, 415, -1, 417, 418, 419, 420, 421, 422, - 423, -1, 425, 426, 427, -1, -1, 430, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, -1, -1, 446, 447, 448, -1, 450, 451, 452, - 453, -1, 455, 456, 457, 458, 459, 460, 461, -1, - 463, 464, 465, 466, 467, 468, 469, 470, 471, -1, - -1, 474, -1, -1, 477, 478, 479, 480, 481, 482, - 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 494, 495, 496, 497, 498, -1, -1, -1, -1, - -1, -1, 505, 506, 507, -1, -1, -1, -1, 512, - -1, 514, 515, -1, -1, -1, 519, 520, -1, 522, - 523, 3, 4, 5, 6, 7, 8, 9, 10, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, - 32, 33, -1, -1, -1, 37, -1, 39, -1, -1, - 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, - -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, - 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, - -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, - 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, - 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, - 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, - 182, 183, 184, -1, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, -1, 199, 200, 201, - 202, 203, 204, 205, -1, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, -1, 218, -1, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, -1, - -1, 233, 234, 235, 236, -1, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, -1, 287, 288, -1, -1, 291, - 292, 293, -1, -1, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, -1, -1, -1, -1, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, -1, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, -1, 345, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, -1, 359, 360, 361, - 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, -1, 380, 381, - 382, 383, 384, 385, 386, 387, 388, 389, -1, 391, - 392, 393, 394, 395, -1, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - -1, -1, 414, 415, -1, 417, 418, 419, 420, 421, - 422, 423, -1, 425, 426, 427, -1, -1, 430, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, -1, -1, 446, 447, 448, -1, 450, 451, - 452, 453, -1, 455, 456, 457, 458, 459, 460, 461, - -1, 463, 464, 465, 466, 467, 468, 469, 470, 471, - -1, -1, 474, -1, -1, 477, 478, 479, 480, 481, - 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 494, 495, 496, 497, 498, -1, -1, -1, - -1, -1, -1, 505, 506, 507, -1, -1, -1, -1, - 512, -1, 514, -1, -1, -1, -1, 519, 520, -1, - 522, 523, 3, 4, 5, 6, 7, 8, 9, 10, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, -1, -1, -1, -1, -1, 39, -1, - -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, - 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, -1, 120, - 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, - 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, - 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, - -1, 172, 173, 174, 175, 176, 177, -1, 179, -1, - 181, 182, 183, 184, -1, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, -1, 199, 200, - 201, 202, 203, 204, 205, -1, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, -1, 218, -1, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - -1, -1, 233, 234, 235, 236, -1, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, -1, 287, 288, -1, -1, - 291, 292, 293, -1, -1, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, -1, -1, -1, -1, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, -1, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, -1, 345, 346, 347, 348, 349, 350, - 351, 352, 353, 354, 355, 356, 357, -1, 359, 360, - 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378, -1, -1, - 381, 382, 383, 384, 385, 386, 387, 388, 389, -1, - 391, 392, 393, 394, 395, -1, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, -1, -1, 414, 415, -1, 417, 418, 419, 420, - 421, 422, 423, -1, 425, 426, 427, -1, -1, 430, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 443, -1, -1, 446, 447, 448, -1, 450, - 451, 452, 453, -1, 455, 456, 457, 458, 459, 460, - 461, -1, 463, 464, 465, 466, 467, 468, 469, 470, - 471, -1, -1, 474, -1, -1, 477, 478, 479, 480, - 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 494, 495, 496, 497, 498, -1, -1, - -1, -1, -1, -1, 505, 506, 507, -1, -1, -1, - -1, 512, -1, 514, -1, -1, -1, -1, 519, 520, - -1, 522, 523, 3, 4, 5, 6, 7, 8, 9, + 494, 495, 496, 497, 498, 499, 500, 501, -1, -1, + -1, -1, -1, -1, 508, 509, 510, -1, -1, -1, + -1, 515, -1, 517, -1, -1, -1, -1, 522, 523, + -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, -1, -1, -1, -1, -1, 39, + -1, 31, 32, 33, -1, -1, -1, 37, -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, @@ -13222,98 +11845,151 @@ static const yytype_int16 yycheck[] = 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, -1, 162, 163, 164, 165, -1, 167, -1, 169, - 170, -1, 172, 173, 174, 175, 176, 177, -1, 179, - -1, 181, 182, 183, 184, -1, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, -1, 199, - 200, 201, 202, 203, 204, 205, -1, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, -1, 218, -1, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, -1, -1, 233, 234, 235, 236, -1, 238, 239, + 160, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, 171, -1, 173, 174, 175, 176, 177, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, -1, 287, 288, -1, - -1, 291, 292, 293, -1, -1, 296, 297, 298, 299, + 280, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, -1, -1, -1, -1, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, -1, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, -1, 345, 346, 347, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, -1, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, -1, - -1, 381, 382, 383, 384, 385, 386, 387, 388, 389, - -1, 391, 392, 393, 394, 395, -1, 397, 398, 399, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, 383, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 411, -1, -1, 414, 415, -1, 417, 418, 419, - 420, 421, 422, 423, -1, 425, 426, 427, -1, -1, - 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, -1, -1, 446, 447, 448, -1, - 450, 451, 452, 453, -1, 455, 456, 457, 458, 459, - 460, 461, -1, 463, 464, 465, 466, 467, 468, 469, - 470, 471, -1, -1, 474, -1, -1, 477, 478, 479, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, 421, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, 467, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, - 490, 491, 492, 493, 494, 495, 496, 497, 498, -1, - -1, -1, -1, -1, -1, 505, 506, 507, -1, -1, - -1, -1, 512, -1, 514, -1, -1, -1, -1, 519, - 520, -1, 522, 523, 3, 4, 5, 6, 7, 8, - 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - 39, -1, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, 171, 172, 173, 174, 175, 176, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, -1, -1, 233, 234, 235, 236, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, - -1, -1, -1, -1, -1, -1, 505, 506, 507, -1, - -1, -1, -1, 512, -1, 514, -1, -1, -1, -1, - 519, 520, -1, 522, 523, 3, 4, 5, 6, 7, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 501, -1, -1, -1, -1, -1, -1, 508, 509, + 510, -1, -1, -1, -1, 515, -1, 517, 518, -1, + -1, -1, 522, 523, -1, 525, 526, 3, 4, 5, + 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, 37, -1, 39, -1, -1, 42, 43, 44, -1, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, 171, -1, 173, 174, 175, + 176, 177, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, -1, -1, 234, 235, + 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, 383, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, 394, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, 421, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, 467, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 501, -1, -1, -1, -1, + -1, -1, 508, 509, 510, -1, -1, -1, -1, 515, + -1, 517, -1, -1, -1, -1, 522, 523, -1, 525, + 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, + 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, + -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, 171, + -1, 173, 174, 175, 176, 177, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, 421, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, 467, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, + -1, -1, -1, -1, -1, -1, 508, 509, 510, -1, + -1, -1, -1, 515, -1, 517, -1, -1, -1, -1, + 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, - 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, + 28, 29, 30, 31, 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, 66, 67, @@ -13326,199 +12002,43 @@ static const yytype_int16 yycheck[] = 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, -1, 162, 163, 164, 165, -1, 167, - -1, 169, 170, -1, 172, 173, 174, 175, 176, 177, - -1, 179, -1, 181, 182, 183, 184, -1, 186, 187, + 158, 159, 160, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, 171, -1, 173, 174, 175, 176, 177, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - -1, 199, 200, 201, 202, 203, 204, 205, -1, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, -1, - 218, -1, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, -1, -1, 233, 234, 235, 236, -1, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, -1, -1, 234, 235, 236, 237, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, -1, 287, - 288, -1, -1, 291, 292, 293, -1, -1, 296, 297, + 278, 279, 280, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, -1, -1, -1, -1, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - -1, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, -1, 345, 346, 347, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - -1, 359, 360, 361, 362, 363, 364, 365, 366, 367, + 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, -1, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, -1, 391, 392, 393, 394, 395, -1, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 411, -1, -1, 414, 415, -1, 417, - 418, 419, 420, 421, 422, 423, -1, 425, 426, 427, - -1, -1, 430, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, -1, -1, 446, 447, - 448, -1, 450, 451, 452, 453, -1, 455, 456, 457, - 458, 459, 460, 461, -1, 463, 464, 465, 466, 467, - 468, 469, 470, 471, -1, -1, 474, -1, -1, 477, - 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, 394, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, 421, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, 467, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, - 498, -1, -1, -1, -1, -1, -1, 505, 506, 507, - -1, -1, -1, -1, 512, -1, 514, 515, -1, -1, - -1, 519, 520, -1, 522, 523, 3, 4, 5, 6, - 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, - 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, - -1, -1, 39, -1, -1, 42, 43, 44, -1, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, -1, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, - 77, 78, 79, -1, 81, -1, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, - 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, - -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, - 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, - -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, - 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, - 177, -1, 179, -1, 181, 182, 183, 184, -1, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, -1, 199, 200, 201, 202, 203, 204, 205, -1, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - -1, 218, -1, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, -1, -1, 233, 234, 235, 236, - -1, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, -1, - 287, 288, -1, -1, 291, 292, 293, -1, -1, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, -1, -1, -1, - -1, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, -1, 329, 330, 331, 332, 333, 334, -1, 336, - 337, 338, 339, 340, 341, 342, 343, -1, 345, 346, - 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, - 357, -1, 359, 360, 361, 362, 363, 364, 365, 366, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, -1, -1, 381, 382, 383, 384, 385, 386, - 387, 388, 389, -1, 391, 392, 393, 394, 395, -1, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, -1, -1, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, -1, 425, 426, - 427, -1, -1, 430, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, -1, -1, 446, - 447, 448, -1, 450, 451, 452, 453, -1, 455, 456, - 457, 458, 459, 460, 461, -1, 463, 464, 465, 466, - 467, 468, 469, 470, 471, -1, -1, 474, -1, -1, - 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, - 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, - 497, 498, -1, -1, -1, -1, -1, -1, 505, 506, - 507, -1, -1, -1, -1, 512, -1, 514, -1, -1, - -1, -1, 519, 520, -1, 522, 523, 3, 4, 5, - 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, - 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, - -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, - 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, - 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, - -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, - 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, - 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, -1, 162, 163, 164, 165, - -1, 167, -1, 169, 170, -1, 172, 173, 174, 175, - 176, 177, -1, 179, -1, 181, 182, 183, 184, -1, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, -1, 199, 200, 201, 202, 203, 204, 205, - -1, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, -1, 218, -1, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, -1, -1, 233, 234, 235, - 236, -1, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - -1, 287, 288, -1, -1, 291, 292, 293, -1, -1, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, -1, -1, - -1, -1, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, -1, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, -1, 345, - 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, -1, 359, 360, 361, 362, 363, 364, 365, - 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, -1, -1, 381, 382, 383, 384, 385, - 386, 387, 388, 389, -1, 391, 392, 393, 394, 395, - -1, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, -1, -1, 414, 415, - -1, 417, 418, 419, 420, 421, 422, 423, -1, 425, - 426, 427, -1, -1, 430, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, -1, -1, - 446, 447, 448, -1, 450, 451, 452, 453, -1, 455, - 456, 457, 458, 459, 460, 461, -1, 463, 464, 465, - 466, 467, 468, 469, 470, 471, -1, 473, 474, -1, - -1, 477, 478, 479, 480, 481, 482, 483, 484, 485, - 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, - 496, 497, 498, -1, -1, -1, -1, -1, -1, 505, - 506, 507, -1, -1, -1, -1, 512, -1, 514, -1, - -1, -1, -1, 519, 520, -1, 522, 523, 3, 4, - 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, -1, - -1, -1, -1, -1, 39, -1, -1, 42, 43, 44, - -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, - 75, 76, 77, 78, 79, -1, 81, -1, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, - 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, -1, 120, 121, 122, 123, 124, - 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, - 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, - 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, -1, 162, 163, 164, - 165, -1, 167, -1, 169, 170, -1, 172, 173, 174, - 175, 176, 177, -1, 179, -1, 181, 182, 183, 184, - -1, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, -1, 199, 200, 201, 202, 203, 204, - 205, -1, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, -1, 218, -1, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, -1, -1, 233, 234, - 235, 236, -1, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, -1, 287, 288, -1, -1, 291, 292, 293, -1, - -1, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, -1, - -1, -1, -1, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, -1, 329, 330, 331, 332, 333, 334, - -1, 336, 337, 338, 339, 340, 341, 342, 343, -1, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, -1, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, -1, -1, 381, 382, 383, 384, - 385, 386, 387, 388, 389, -1, 391, 392, 393, 394, - 395, -1, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, -1, -1, 414, - 415, -1, 417, 418, 419, 420, 421, 422, 423, -1, - 425, 426, 427, -1, -1, 430, 431, 432, 433, 434, - 435, 436, 437, 438, 439, 440, 441, 442, 443, -1, - -1, 446, 447, 448, -1, 450, 451, 452, 453, -1, - 455, 456, 457, 458, 459, 460, 461, -1, 463, 464, - 465, 466, 467, 468, 469, 470, 471, -1, -1, 474, - -1, -1, 477, 478, 479, 480, 481, 482, 483, 484, - 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, - 495, 496, 497, 498, -1, -1, -1, -1, -1, -1, - 505, 506, 507, -1, -1, -1, -1, 512, -1, 514, - -1, -1, -1, -1, 519, 520, -1, 522, 523, 3, + 498, 499, 500, 501, -1, -1, -1, -1, -1, -1, + 508, 509, 510, -1, -1, -1, -1, 515, -1, 517, + -1, -1, -1, -1, 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, @@ -13534,200 +12054,44 @@ static const yytype_int16 yycheck[] = 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, - 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, -1, -1, 233, - 234, 235, 236, -1, 238, 239, 240, 241, 242, 243, + 154, 155, 156, 157, 158, 159, 160, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, 171, 172, 173, + 174, 175, 176, 177, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, -1, -1, + 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, 299, 300, 301, 302, 303, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, 361, 362, 363, + 314, -1, -1, -1, -1, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, 391, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, 421, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - 464, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, 467, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 498, -1, -1, -1, -1, -1, - -1, 505, 506, 507, -1, -1, -1, -1, 512, -1, - 514, -1, -1, -1, -1, 519, 520, -1, 522, 523, - 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, - 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, - 33, -1, -1, -1, -1, -1, 39, -1, -1, 42, - 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, -1, 75, 76, 77, 78, 79, -1, 81, -1, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - -1, 94, 95, 96, 97, 98, 99, -1, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, -1, 120, 121, 122, - 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, - -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, - -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, 159, 160, -1, 162, - 163, 164, 165, -1, 167, -1, 169, 170, -1, 172, - 173, 174, 175, 176, 177, -1, 179, -1, 181, 182, - 183, 184, -1, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, -1, 199, 200, 201, 202, - 203, 204, 205, -1, 207, 208, 209, 210, 211, 212, - 213, 214, 215, 216, -1, 218, -1, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, -1, -1, - 233, 234, 235, 236, -1, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, -1, 287, 288, -1, -1, 291, 292, - 293, -1, -1, 296, 297, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, -1, -1, -1, -1, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, -1, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, -1, 345, 346, 347, 348, 349, 350, 351, 352, - 353, 354, 355, 356, 357, -1, 359, 360, 361, 362, - 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, -1, -1, 381, 382, - 383, 384, 385, 386, 387, 388, 389, -1, 391, 392, - 393, 394, 395, -1, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 411, -1, - -1, 414, 415, 416, 417, 418, 419, 420, 421, 422, - 423, -1, 425, 426, 427, -1, -1, 430, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, -1, -1, 446, 447, 448, -1, 450, 451, 452, - 453, -1, 455, 456, 457, 458, 459, 460, 461, -1, - 463, 464, 465, 466, 467, 468, 469, 470, 471, -1, - -1, 474, -1, -1, 477, 478, 479, 480, 481, 482, - 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 494, 495, 496, 497, 498, -1, -1, -1, -1, - -1, -1, 505, 506, 507, -1, -1, -1, -1, 512, - -1, 514, -1, -1, -1, -1, 519, 520, -1, 522, - 523, 3, 4, 5, 6, 7, 8, 9, 10, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, - 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, - 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, - -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, - 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, - -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, - 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, - 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, - 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, - 182, 183, 184, -1, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, -1, 199, 200, 201, - 202, 203, 204, 205, -1, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, -1, 218, -1, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, -1, - -1, 233, 234, 235, 236, -1, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, -1, 287, 288, -1, -1, 291, - 292, 293, -1, -1, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, -1, -1, -1, -1, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, -1, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, -1, 345, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, -1, 359, 360, 361, - 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, -1, -1, 381, - 382, 383, 384, 385, 386, 387, 388, 389, -1, 391, - 392, 393, 394, 395, -1, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - -1, -1, 414, 415, -1, 417, 418, 419, 420, 421, - 422, 423, -1, 425, 426, 427, -1, -1, 430, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, -1, -1, 446, 447, 448, -1, 450, 451, - 452, 453, -1, 455, 456, 457, 458, 459, 460, 461, - -1, 463, 464, 465, 466, 467, 468, 469, 470, 471, - -1, -1, 474, -1, -1, 477, 478, 479, 480, 481, - 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 494, 495, 496, 497, 498, -1, -1, -1, - -1, -1, -1, 505, 506, 507, -1, -1, -1, -1, - 512, -1, 514, -1, -1, -1, -1, 519, 520, -1, - 522, 523, 3, 4, 5, 6, 7, 8, 9, 10, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, - 31, 32, 33, -1, -1, -1, -1, -1, 39, -1, - -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, - 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, 118, -1, 120, - 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, - 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, - 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, - -1, 172, 173, 174, 175, 176, 177, -1, 179, -1, - 181, 182, 183, 184, -1, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, -1, 199, 200, - 201, 202, 203, 204, 205, -1, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, -1, 218, -1, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - -1, -1, 233, 234, 235, 236, -1, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, -1, 287, 288, -1, -1, - 291, 292, 293, -1, -1, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, -1, -1, -1, -1, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, -1, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, -1, 345, 346, 347, 348, 349, 350, - 351, 352, 353, 354, 355, 356, 357, -1, 359, 360, - 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378, -1, -1, - 381, 382, 383, 384, 385, 386, 387, 388, 389, -1, - 391, 392, 393, 394, 395, -1, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, -1, -1, 414, 415, -1, 417, 418, 419, 420, - 421, 422, 423, -1, 425, 426, 427, -1, -1, 430, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 443, -1, -1, 446, 447, 448, -1, 450, - 451, 452, 453, -1, 455, 456, 457, 458, 459, 460, - 461, -1, 463, 464, 465, 466, 467, 468, 469, 470, - 471, -1, -1, 474, -1, -1, 477, 478, 479, 480, - 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 494, 495, 496, 497, 498, -1, -1, - -1, -1, -1, -1, 505, 506, 507, -1, -1, -1, - -1, 512, -1, 514, -1, -1, -1, -1, 519, 520, - -1, 522, 523, 3, 4, 5, 6, 7, 8, 9, + 494, 495, 496, 497, 498, 499, 500, 501, -1, -1, + -1, -1, -1, -1, 508, 509, 510, -1, -1, -1, + -1, 515, -1, 517, -1, -1, -1, -1, 522, 523, + -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, 39, @@ -13743,98 +12107,151 @@ static const yytype_int16 yycheck[] = 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, -1, 162, 163, 164, 165, -1, 167, -1, 169, - 170, -1, 172, 173, 174, 175, 176, 177, -1, 179, - -1, 181, 182, 183, 184, -1, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, -1, 199, - 200, 201, 202, 203, 204, 205, -1, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, -1, 218, -1, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, -1, -1, 233, 234, 235, 236, -1, 238, 239, + 160, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, 171, -1, 173, 174, 175, 176, 177, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, -1, 287, 288, -1, - -1, 291, 292, 293, -1, -1, 296, 297, 298, 299, + 280, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, -1, -1, -1, -1, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, -1, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, -1, 345, 346, 347, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, -1, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, -1, - -1, 381, 382, 383, 384, 385, 386, 387, 388, 389, - -1, 391, 392, 393, 394, 395, -1, 397, 398, 399, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 411, -1, -1, 414, 415, -1, 417, 418, 419, - 420, 421, 422, 423, -1, 425, 426, 427, -1, -1, - 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, -1, -1, 446, 447, 448, -1, - 450, 451, 452, 453, -1, 455, 456, 457, 458, 459, - 460, 461, -1, 463, 464, 465, 466, 467, 468, 469, - 470, 471, -1, -1, 474, -1, -1, 477, 478, 479, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, 421, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, 467, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, - 490, 491, 492, 493, 494, 495, 496, 497, 498, -1, - -1, -1, -1, -1, -1, 505, 506, 507, -1, -1, - -1, -1, 512, -1, 514, -1, -1, -1, -1, 519, - 520, -1, 522, 523, 3, 4, 5, 6, 7, 8, - 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - 39, -1, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, -1, 172, 173, 174, 175, 176, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, -1, -1, 233, 234, 235, 236, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, - -1, -1, -1, -1, -1, -1, 505, 506, 507, -1, - -1, -1, -1, 512, -1, 514, -1, -1, -1, -1, - 519, 520, -1, 522, 523, 3, 4, 5, 6, 7, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 501, -1, -1, -1, -1, -1, -1, 508, 509, + 510, -1, -1, -1, -1, 515, -1, 517, 518, -1, + -1, -1, 522, 523, -1, 525, 526, 3, 4, 5, + 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, 171, -1, 173, 174, 175, + 176, 177, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, -1, -1, 234, 235, + 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, 394, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, 419, 420, 421, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, 467, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 501, -1, -1, -1, -1, + -1, -1, 508, 509, 510, -1, -1, -1, -1, 515, + -1, 517, -1, -1, -1, -1, 522, 523, -1, 525, + 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, + 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, + -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, 171, + -1, 173, 174, 175, 176, 177, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, 421, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, 467, 468, 469, 470, 471, + 472, 473, 474, -1, 476, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, + -1, -1, -1, -1, -1, -1, 508, 509, 510, -1, + -1, -1, -1, 515, -1, 517, -1, -1, -1, -1, + 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, - 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, + 28, 29, 30, 31, 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, 66, 67, @@ -13847,199 +12264,43 @@ static const yytype_int16 yycheck[] = 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, -1, 162, 163, 164, 165, -1, 167, - -1, 169, 170, -1, 172, 173, 174, 175, 176, 177, - -1, 179, -1, 181, 182, 183, 184, -1, 186, 187, + 158, 159, 160, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, 171, -1, 173, 174, 175, 176, 177, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - -1, 199, 200, 201, 202, 203, 204, 205, -1, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, -1, - 218, -1, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, -1, -1, 233, 234, 235, 236, -1, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, -1, -1, 234, 235, 236, 237, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, -1, 287, - 288, -1, -1, 291, 292, 293, -1, -1, 296, 297, + 278, 279, 280, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, -1, -1, -1, -1, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - -1, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, -1, 345, 346, 347, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - -1, 359, 360, 361, 362, 363, 364, 365, 366, 367, + 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, -1, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, -1, 391, 392, 393, 394, 395, -1, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 411, -1, -1, 414, 415, -1, 417, - 418, 419, 420, 421, 422, 423, -1, 425, 426, 427, - -1, -1, 430, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, -1, -1, 446, 447, - 448, -1, 450, 451, 452, 453, -1, 455, 456, 457, - 458, 459, 460, 461, -1, 463, 464, 465, 466, 467, - 468, 469, 470, 471, -1, -1, 474, -1, -1, 477, - 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, 394, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, 421, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, 467, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, - 498, -1, -1, -1, -1, -1, -1, 505, 506, 507, - -1, -1, -1, -1, 512, -1, 514, -1, -1, -1, - -1, 519, 520, -1, 522, 523, 3, 4, 5, 6, - 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, - 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, - -1, -1, 39, -1, -1, 42, 43, 44, -1, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, -1, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, - 77, 78, 79, -1, 81, -1, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, - 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, - -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, - 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, - -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, - 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, - 177, -1, 179, -1, 181, 182, 183, 184, -1, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, -1, 199, 200, 201, 202, 203, 204, 205, -1, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - -1, 218, -1, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, -1, -1, 233, 234, 235, 236, - -1, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, -1, - 287, 288, -1, -1, 291, 292, 293, -1, -1, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, -1, -1, -1, - -1, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, -1, 329, 330, 331, 332, 333, 334, -1, 336, - 337, 338, 339, 340, 341, 342, 343, -1, 345, 346, - 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, - 357, -1, 359, 360, 361, 362, 363, 364, 365, 366, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, -1, -1, 381, 382, 383, 384, 385, 386, - 387, 388, 389, -1, 391, 392, 393, 394, 395, -1, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, -1, -1, 414, 415, -1, - 417, 418, 419, 420, 421, 422, 423, -1, 425, 426, - 427, -1, -1, 430, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, -1, -1, 446, - 447, 448, -1, 450, 451, 452, 453, -1, 455, 456, - 457, 458, 459, 460, 461, -1, 463, 464, 465, 466, - 467, 468, 469, 470, 471, -1, -1, 474, -1, -1, - 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, - 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, - 497, 498, -1, -1, -1, -1, -1, -1, 505, 506, - 507, -1, -1, -1, -1, 512, -1, 514, -1, -1, - -1, -1, 519, 520, -1, 522, 523, 3, 4, 5, - 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, - 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, - -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, - 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, - 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, - -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, - 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, - 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, -1, 162, 163, 164, 165, - -1, 167, -1, 169, 170, -1, 172, 173, 174, 175, - 176, 177, -1, 179, -1, 181, 182, 183, 184, -1, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, -1, 199, 200, 201, 202, 203, 204, 205, - -1, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, -1, 218, -1, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, -1, -1, 233, 234, 235, - 236, -1, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - -1, 287, 288, -1, -1, 291, 292, 293, -1, -1, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, -1, -1, - -1, -1, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, -1, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, -1, 345, - 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, -1, 359, 360, 361, 362, 363, 364, 365, - 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, -1, -1, 381, 382, 383, 384, 385, - 386, 387, 388, 389, -1, 391, 392, 393, 394, 395, - -1, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, -1, -1, 414, 415, - -1, 417, 418, 419, 420, 421, 422, 423, -1, 425, - 426, 427, -1, -1, 430, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, -1, -1, - 446, 447, 448, -1, 450, 451, 452, 453, -1, 455, - 456, 457, 458, 459, 460, 461, -1, 463, 464, 465, - 466, 467, 468, 469, 470, 471, -1, -1, 474, -1, - -1, 477, 478, 479, 480, 481, 482, 483, 484, 485, - 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, - 496, 497, 498, -1, -1, -1, -1, -1, -1, 505, - 506, 507, -1, -1, -1, -1, 512, -1, 514, -1, - -1, -1, -1, 519, 520, -1, 522, 523, 3, 4, - 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, - 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, - -1, -1, -1, -1, 39, -1, -1, 42, 43, 44, - -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, - 75, 76, 77, 78, 79, -1, 81, -1, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, - 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, -1, 120, 121, 122, 123, 124, - 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, - 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, - 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, -1, 162, 163, 164, - 165, -1, 167, -1, 169, 170, -1, 172, 173, 174, - 175, 176, 177, -1, 179, -1, 181, 182, 183, 184, - -1, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, -1, 199, 200, 201, 202, 203, 204, - 205, -1, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, -1, 218, -1, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, -1, -1, 233, 234, - 235, 236, -1, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, -1, 287, 288, -1, -1, 291, 292, 293, -1, - -1, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, -1, - -1, -1, -1, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, -1, 329, 330, 331, 332, 333, 334, - -1, 336, 337, 338, 339, 340, 341, 342, 343, -1, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, -1, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, -1, -1, 381, 382, 383, 384, - 385, 386, 387, 388, 389, -1, 391, 392, 393, 394, - 395, -1, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, -1, -1, 414, - 415, -1, 417, 418, 419, 420, 421, 422, 423, -1, - 425, 426, 427, -1, -1, 430, 431, 432, 433, 434, - 435, 436, 437, 438, 439, 440, 441, 442, 443, -1, - -1, 446, 447, 448, -1, 450, 451, 452, 453, -1, - 455, 456, 457, 458, 459, 460, 461, -1, 463, 464, - 465, 466, 467, 468, 469, 470, 471, -1, -1, 474, - -1, -1, 477, 478, 479, 480, 481, 482, 483, 484, - 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, - 495, 496, 497, 498, -1, -1, -1, -1, -1, -1, - 505, 506, 507, -1, -1, -1, -1, 512, -1, 514, - -1, -1, -1, -1, 519, 520, -1, 522, 523, 3, + 498, 499, 500, 501, -1, -1, -1, -1, -1, -1, + 508, 509, 510, -1, -1, -1, -1, 515, -1, 517, + -1, -1, -1, -1, 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, @@ -14055,96 +12316,149 @@ static const yytype_int16 yycheck[] = 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, - 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, -1, -1, 233, - 234, 235, 236, -1, 238, 239, 240, 241, 242, 243, + 154, 155, 156, 157, 158, 159, 160, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, 171, -1, 173, + 174, 175, 176, 177, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, -1, -1, + 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, 299, 300, 301, 302, 303, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, 361, 362, 363, + 314, -1, -1, -1, -1, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, 391, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, 418, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, 419, 420, 421, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - 464, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, 467, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 498, -1, -1, -1, -1, -1, - -1, 505, 506, 507, -1, -1, -1, -1, 512, -1, - 514, -1, -1, -1, -1, 519, 520, -1, 522, 523, - 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, - 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, - 33, -1, -1, -1, -1, -1, 39, -1, -1, 42, - 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, -1, 75, 76, 77, 78, 79, -1, 81, -1, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - -1, 94, 95, 96, 97, 98, 99, -1, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, - 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, - -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, - -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, 159, 160, -1, 162, - 163, 164, 165, -1, 167, -1, 169, 170, -1, 172, - 173, 174, 175, 176, 177, -1, 179, -1, 181, 182, - 183, 184, -1, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 196, 197, -1, 199, 200, 201, 202, - 203, 204, 205, -1, 207, 208, 209, 210, 211, 212, - 213, 214, 215, 216, -1, 218, -1, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, -1, -1, - 233, 234, 235, 236, -1, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, - 273, -1, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, -1, 287, 288, -1, -1, 291, 292, - 293, -1, -1, 296, 297, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, -1, -1, -1, -1, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, -1, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, -1, 345, 346, 347, 348, 349, 350, 351, 352, - 353, 354, 355, 356, 357, -1, 359, 360, 361, 362, - 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, -1, -1, 381, 382, - 383, 384, 385, 386, 387, 388, 389, -1, 391, 392, - 393, 394, 395, -1, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 411, -1, - -1, 414, 415, -1, 417, 418, 419, 420, 421, 422, - 423, -1, 425, 426, 427, -1, -1, 430, 431, 432, - 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, -1, -1, 446, 447, 448, -1, 450, 451, 452, - 453, -1, 455, 456, 457, 458, 459, 460, 461, -1, - 463, 464, 465, 466, 467, 468, 469, 470, 471, -1, - -1, 474, -1, -1, 477, 478, 479, 480, 481, 482, - 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 494, 495, 496, 497, -1, -1, -1, -1, -1, - -1, -1, 505, 506, -1, -1, -1, -1, -1, 512, - -1, 514, -1, -1, -1, -1, 519, 520, -1, 522, - 523, 3, 4, 5, 6, 7, 8, 9, 10, -1, + 494, 495, 496, 497, 498, 499, 500, 501, -1, -1, + -1, -1, -1, -1, 508, 509, 510, -1, -1, -1, + -1, 515, -1, 517, -1, -1, -1, -1, 522, 523, + -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, + 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + -1, 31, 32, 33, -1, -1, -1, -1, -1, 39, + -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, 81, -1, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, 171, -1, 173, 174, 175, 176, 177, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, -1, -1, 234, 235, 236, 237, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, + 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, 394, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, 419, + 420, 421, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, 467, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 501, -1, -1, -1, -1, -1, -1, 508, 509, + 510, -1, -1, -1, -1, 515, -1, 517, -1, -1, + -1, -1, 522, 523, -1, 525, 526, 3, 4, 5, + 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, 171, -1, 173, 174, 175, + 176, 177, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, -1, -1, 234, 235, + 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, 394, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, 421, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, 467, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 501, -1, -1, -1, -1, + -1, -1, 508, 509, 510, -1, -1, -1, -1, 515, + -1, 517, -1, -1, -1, -1, 522, 523, -1, 525, + 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, @@ -14159,96 +12473,149 @@ static const yytype_int16 yycheck[] = 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, - 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, - 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, - 182, 183, 184, -1, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, -1, 199, 200, 201, - 202, 203, 204, 205, -1, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, -1, 218, -1, 220, -1, - -1, 223, 224, 225, 226, 227, 228, 229, 230, -1, - -1, 233, 234, 235, 236, -1, 238, 239, 240, 241, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, 171, + -1, 173, 174, 175, 176, 177, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, -1, 275, 276, -1, 278, 279, 280, 281, - 282, 283, 284, 285, -1, 287, 288, -1, -1, 291, - 292, 293, -1, -1, 296, 297, 298, 299, 300, 301, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, -1, -1, -1, -1, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, -1, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, -1, 345, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, -1, 359, 360, 361, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, -1, -1, 381, - 382, 383, 384, 385, 386, 387, 388, 389, -1, 391, - 392, 393, 394, 395, -1, 397, 398, 399, 400, 401, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - -1, -1, 414, 415, -1, 417, 418, 419, 420, 421, - 422, 423, -1, 425, 426, 427, -1, -1, 430, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, -1, -1, 446, 447, 448, -1, 450, 451, - 452, 453, -1, 455, 456, 457, 458, 459, 460, 461, - -1, 463, 464, 465, 466, 467, 468, 469, 470, 471, - -1, -1, 474, -1, -1, 477, 478, 479, 480, 481, + 412, 413, 414, -1, -1, 417, 418, -1, 420, 421, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, 467, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 494, 495, 496, 497, 498, -1, -1, -1, - -1, -1, -1, 505, 506, 507, -1, -1, -1, -1, - 512, -1, 514, -1, -1, -1, -1, 519, 520, -1, - 522, 523, 3, 4, 5, 6, 7, -1, 9, 10, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, - 31, 32, 33, -1, -1, -1, -1, -1, 39, -1, - -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, - 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, - 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, - 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, - 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, - -1, 172, 173, 174, 175, 176, 177, -1, 179, -1, - 181, 182, 183, 184, -1, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, -1, 199, 200, - 201, 202, 203, 204, 205, -1, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, -1, 218, -1, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - -1, -1, 233, 234, 235, 236, -1, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, -1, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, -1, 287, 288, -1, -1, - 291, 292, 293, -1, -1, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, -1, -1, -1, -1, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, -1, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, -1, 345, 346, 347, 348, 349, 350, - 351, 352, 353, 354, 355, 356, 357, -1, 359, 360, - 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378, -1, -1, - 381, 382, 383, 384, 385, 386, 387, 388, 389, -1, - 391, 392, 393, 394, 395, -1, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, -1, -1, 414, 415, -1, 417, 418, 419, 420, - 421, 422, 423, -1, 425, 426, 427, -1, -1, 430, - 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, - 441, 442, 443, -1, -1, 446, 447, 448, -1, 450, - 451, 452, 453, -1, 455, 456, 457, 458, 459, 460, - 461, -1, 463, 464, 465, 466, 467, 468, 469, 470, - 471, -1, -1, 474, -1, -1, 477, 478, 479, 480, - 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 494, 495, 496, 497, -1, -1, -1, - -1, -1, -1, -1, 505, 506, -1, -1, -1, -1, - -1, 512, -1, 514, -1, -1, -1, -1, 519, 520, - -1, 522, 523, 3, 4, 5, 6, 7, 8, 9, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, + -1, -1, -1, -1, -1, -1, 508, 509, 510, -1, + -1, -1, -1, 515, -1, 517, -1, -1, -1, -1, + 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, + 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, + -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + -1, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, 171, -1, 173, 174, 175, 176, 177, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, -1, -1, 234, 235, 236, 237, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, 394, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, 421, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, 467, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 501, -1, -1, -1, -1, -1, -1, + 508, 509, 510, -1, -1, -1, -1, 515, -1, 517, + -1, -1, -1, -1, 522, 523, -1, 525, 526, 3, + 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, + 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, + -1, -1, -1, -1, -1, 39, -1, -1, 42, 43, + 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + -1, 75, 76, 77, 78, 79, -1, 81, -1, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, + 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, -1, 120, 121, 122, 123, + 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, 171, -1, 173, + 174, 175, 176, 177, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, -1, -1, + 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, -1, -1, -1, -1, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, 421, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, 467, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, + 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, + 494, 495, 496, 497, 498, 499, 500, 501, -1, -1, + -1, -1, -1, -1, 508, 509, 510, -1, -1, -1, + -1, 515, -1, 517, -1, -1, -1, -1, 522, 523, + -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, 39, @@ -14259,101 +12626,154 @@ static const yytype_int16 yycheck[] = -1, 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, -1, 162, 163, 164, 165, -1, 167, -1, 169, - 170, -1, 172, 173, 174, 175, 176, 177, -1, 179, - -1, 181, 182, 183, 184, -1, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, -1, 199, - 200, 201, 202, 203, 204, 205, -1, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, -1, 218, -1, - 220, -1, 222, 223, 224, 225, 226, 227, 228, 229, - 230, -1, -1, 233, 234, 235, 236, -1, 238, 239, + 160, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, 171, -1, 173, 174, 175, 176, 177, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, -1, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, -1, 287, 288, -1, - -1, 291, 292, 293, -1, -1, 296, 297, 298, 299, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, -1, -1, -1, -1, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, -1, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, -1, 345, 346, 347, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, -1, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, -1, - -1, 381, 382, 383, 384, 385, 386, 387, 388, 389, - -1, 391, 392, 393, 394, 395, -1, 397, 398, 399, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 411, -1, -1, 414, 415, -1, 417, 418, 419, - 420, 421, 422, 423, -1, 425, 426, 427, -1, -1, - 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, -1, -1, 446, 447, 448, -1, - 450, 451, 452, 453, -1, 455, 456, 457, 458, 459, - 460, 461, -1, 463, 464, 465, 466, 467, 468, 469, - 470, 471, -1, -1, 474, -1, -1, 477, 478, 479, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, 421, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, 467, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, - 490, 491, 492, 493, 494, 495, 496, 497, -1, -1, - -1, -1, -1, -1, -1, 505, 506, -1, -1, -1, - -1, -1, 512, -1, 514, -1, -1, -1, -1, 519, - 520, -1, 522, 523, 3, 4, 5, 6, 7, -1, - 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - 39, -1, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, -1, 172, 173, 174, 175, 176, 177, -1, - 179, 180, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, -1, -1, 233, 234, 235, 236, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, -1, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, -1, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 501, -1, -1, -1, -1, -1, -1, 508, 509, + 510, -1, -1, -1, -1, 515, -1, 517, -1, -1, + -1, -1, 522, 523, -1, 525, 526, 3, 4, 5, + 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, 171, -1, 173, 174, 175, + 176, 177, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, -1, -1, 234, 235, + 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, 394, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, 421, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, 467, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 501, -1, -1, -1, -1, + -1, -1, 508, 509, 510, -1, -1, -1, -1, 515, + -1, 517, -1, -1, -1, -1, 522, 523, -1, 525, + 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 512, -1, 514, -1, -1, -1, -1, - 519, 520, -1, 522, 523, 3, 4, 5, 6, 7, - -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, + 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, + -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, 171, + -1, 173, 174, 175, 176, 177, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, 421, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, 467, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, + -1, -1, -1, -1, -1, -1, 508, 509, 510, -1, + -1, -1, -1, 515, -1, 517, -1, -1, -1, -1, + 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, + 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, @@ -14363,157 +12783,369 @@ static const yytype_int16 yycheck[] = 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, -1, 162, 163, 164, 165, -1, 167, - -1, 169, 170, -1, 172, 173, 174, 175, 176, 177, - -1, 179, -1, 181, 182, 183, 184, -1, 186, 187, + 158, 159, 160, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, 171, -1, 173, 174, 175, 176, 177, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - -1, 199, 200, 201, 202, 203, 204, 205, -1, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, -1, - 218, -1, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, -1, -1, 233, 234, 235, 236, -1, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, -1, -1, 234, 235, 236, 237, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, -1, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, -1, 287, - 288, -1, -1, 291, 292, 293, -1, -1, 296, 297, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, -1, -1, -1, -1, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - -1, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, -1, 345, 346, 347, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - -1, 359, 360, 361, 362, 363, 364, 365, 366, 367, + 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, -1, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, -1, 391, 392, 393, 394, 395, -1, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 411, -1, -1, 414, 415, -1, 417, - 418, 419, 420, 421, 422, 423, -1, 425, 426, 427, - -1, -1, 430, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, -1, -1, 446, 447, - 448, -1, 450, 451, 452, 453, -1, 455, 456, 457, - 458, 459, 460, 461, -1, 463, 464, 465, 466, 467, - 468, 469, 470, 471, -1, -1, 474, -1, -1, 477, - 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, 394, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, 421, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, 467, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 512, -1, 514, -1, -1, -1, - -1, 519, 520, -1, 522, 523, 3, 4, 5, 6, - 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, - 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, - -1, -1, 39, -1, -1, 42, 43, 44, -1, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, -1, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, - 77, 78, 79, -1, 81, -1, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, - 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, - -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, - 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, - -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, - 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, - 177, -1, 179, -1, 181, 182, 183, 184, -1, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, -1, 199, 200, 201, 202, 203, 204, 205, -1, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - -1, 218, -1, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, -1, -1, 233, 234, 235, 236, - -1, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, -1, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, -1, - 287, 288, -1, -1, 291, 292, 293, -1, -1, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, -1, -1, -1, - -1, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, -1, 329, 330, 331, 332, 333, 334, -1, 336, - 337, 338, 339, 340, 341, 342, 343, -1, 345, 346, - 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, - 357, -1, 359, 360, 361, 362, 363, 364, 365, 366, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, -1, -1, 381, 382, 383, 384, 385, 386, - 387, 388, 389, -1, 391, 392, 393, 394, 395, -1, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, -1, -1, 414, 415, -1, - 417, 418, 419, 420, 421, 422, 423, -1, 425, 426, - 427, -1, -1, 430, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, -1, -1, 446, - 447, 448, -1, 450, 451, 452, 453, -1, 455, 456, - 457, 458, 459, 460, 461, -1, 463, 464, 465, 466, - 467, 468, 469, 470, 471, -1, -1, 474, -1, -1, - 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, - 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, - 497, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 512, -1, 514, -1, -1, - -1, -1, 519, 520, -1, 522, 523, 3, 4, 5, - 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, - 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, - -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, - 46, 47, 48, 49, 50, 51, 52, -1, 54, 55, - 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, - 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, - 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, - -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, - 136, 137, 138, -1, 140, 141, 142, -1, 144, -1, - 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, -1, 162, 163, 164, 165, - -1, 167, -1, 169, 170, -1, 172, 173, 174, 175, - -1, 177, -1, 179, -1, 181, 182, 183, 184, -1, - 186, 187, 188, 189, 190, 191, 192, -1, 194, 195, - 196, 197, -1, 199, 200, 201, 202, 203, 204, 205, - -1, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, -1, 218, -1, 220, -1, -1, 223, 224, 225, - 226, 227, 228, 229, 230, -1, -1, 233, 234, 235, - -1, -1, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 498, 499, 500, 501, -1, -1, -1, -1, -1, -1, + 508, 509, 510, -1, -1, -1, -1, 515, -1, 517, + -1, -1, -1, -1, 522, 523, -1, 525, 526, 3, + 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, + 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, + -1, -1, -1, -1, -1, 39, -1, -1, 42, 43, + 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + -1, 75, 76, 77, 78, 79, -1, 81, -1, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, + 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, -1, 120, 121, 122, 123, + 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, 171, -1, 173, + 174, 175, 176, 177, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, -1, -1, + 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, + 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, -1, -1, -1, -1, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, 421, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, 467, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, + 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, + 494, 495, 496, 497, 498, 499, 500, 501, -1, -1, + -1, -1, -1, -1, 508, 509, 510, -1, -1, -1, + -1, 515, -1, 517, -1, -1, -1, -1, 522, 523, + -1, 525, 526, 3, 4, 5, 6, 7, 8, 9, + 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + -1, 31, 32, 33, -1, -1, -1, -1, -1, 39, + -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, 81, -1, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, 171, -1, 173, 174, 175, 176, 177, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, -1, -1, 234, 235, 236, 237, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 272, 273, 274, -1, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, + 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, 394, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, 421, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, 467, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, -1, -1, -1, -1, -1, -1, -1, 508, 509, + -1, -1, -1, -1, -1, 515, -1, 517, -1, -1, + -1, -1, 522, 523, -1, 525, 526, 3, 4, 5, + 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, 171, -1, 173, 174, 175, + 176, 177, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, -1, -1, 224, 225, + 226, 227, 228, 229, 230, 231, -1, -1, 234, 235, + 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, -1, 275, - 276, -1, 278, 279, 280, 281, 282, 283, 284, 285, - -1, 287, 288, -1, -1, 291, 292, 293, -1, -1, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, -1, -1, - -1, -1, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, -1, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, -1, 345, - 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, -1, 359, 360, 361, 362, 363, 364, 365, + 266, 267, 268, 269, 270, 271, 272, 273, 274, -1, + 276, 277, -1, 279, 280, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, -1, -1, 381, 382, 383, 384, 385, - 386, 387, 388, 389, -1, -1, 392, 393, 394, 395, - -1, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, -1, -1, 414, 415, - -1, 417, 418, 419, 420, 421, 422, 423, -1, 425, - 426, 427, -1, -1, 430, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, -1, -1, - 446, 447, 448, -1, 450, 451, 452, 453, -1, 455, - 456, 457, 458, 459, 460, 461, -1, 463, 464, 465, - 466, 467, 468, 469, 470, 471, -1, -1, 474, -1, - -1, 477, 478, 479, 480, 481, 482, 483, 484, 485, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, 394, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, 421, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, 467, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, - 496, 497, -1, -1, -1, -1, -1, -1, -1, 505, - 506, 507, -1, 3, 4, 5, 512, -1, 514, 9, - -1, -1, -1, 519, 520, -1, 522, 523, -1, -1, + 496, 497, 498, 499, 500, 501, -1, -1, -1, -1, + -1, -1, 508, 509, 510, -1, -1, -1, -1, 515, + -1, 517, -1, -1, -1, -1, 522, 523, -1, 525, + 526, 3, 4, 5, 6, 7, -1, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, + 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, + -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, 171, + -1, 173, 174, 175, 176, 177, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, -1, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, 421, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, 467, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, -1, + -1, -1, -1, -1, -1, -1, 508, 509, -1, -1, + -1, -1, -1, 515, -1, 517, -1, -1, -1, -1, + 522, 523, -1, 525, 526, 3, 4, 5, 6, 7, + 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, + -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + -1, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, 171, -1, 173, 174, 175, 176, 177, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, -1, 223, 224, 225, 226, 227, + 228, 229, 230, 231, -1, -1, 234, 235, 236, 237, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, 273, 274, -1, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, 394, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, 421, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, 467, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, -1, -1, -1, -1, -1, -1, -1, + 508, 509, -1, -1, -1, -1, -1, 515, -1, 517, + -1, -1, -1, -1, 522, 523, -1, 525, 526, 3, + 4, 5, 6, 7, -1, 9, 10, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, + 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, + -1, -1, -1, -1, -1, 39, -1, -1, 42, 43, + 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + -1, 75, 76, 77, 78, 79, -1, 81, -1, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, + 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, + 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, 171, -1, 173, + 174, 175, 176, 177, 178, -1, 180, 181, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, -1, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, -1, -1, + 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, + 274, -1, 276, 277, 278, 279, 280, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, -1, -1, -1, -1, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, 421, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, 467, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, + 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, + 494, 495, 496, 497, 498, 499, 500, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 515, -1, 517, -1, -1, -1, -1, 522, 523, + -1, 525, 526, 3, 4, 5, 6, 7, -1, 9, + 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, - -1, 31, 32, 33, -1, -1, -1, 37, -1, -1, + -1, 31, 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, - 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, @@ -14523,196 +13155,303 @@ static const yytype_int16 yycheck[] = 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, -1, 162, 163, 164, 165, -1, 167, -1, 169, - 170, -1, 172, 173, 174, 175, 176, 177, -1, 179, - -1, 181, 182, 183, 184, -1, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, -1, 199, - 200, 201, 202, 203, 204, 205, -1, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, -1, 218, -1, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, -1, -1, 233, 234, 235, 236, -1, 238, 239, + 160, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, 171, -1, 173, 174, 175, 176, 177, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, -1, 275, 276, 277, 278, -1, - 280, 281, 282, 283, 284, 285, -1, 287, 288, 289, - -1, 291, 292, 293, -1, -1, 296, 297, 298, 299, + 270, 271, 272, 273, 274, -1, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, -1, -1, -1, -1, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, -1, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, -1, 345, 346, 347, 348, 349, - 350, 351, 352, 353, 354, 355, 356, 357, -1, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, -1, - 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, - -1, 391, 392, 393, 394, 395, -1, 397, 398, 399, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 411, -1, -1, 414, 415, -1, 417, 418, 419, - 420, 421, 422, 423, -1, 425, 426, 427, -1, -1, - 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, -1, -1, 446, 447, 448, -1, - 450, 451, 452, 453, -1, 455, 456, 457, 458, 459, - 460, 461, -1, 463, 464, 465, 466, 467, 468, 469, - 470, 471, -1, -1, 474, -1, -1, 477, 478, 479, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, 421, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, 467, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, - 490, 491, 492, 493, 494, 495, 496, 497, -1, -1, - -1, -1, 3, -1, -1, 505, 506, 507, -1, -1, - -1, -1, 512, -1, 514, -1, -1, -1, -1, -1, - 520, 22, 23, 24, 25, 26, 27, 28, 29, -1, - 31, 32, 33, -1, -1, -1, -1, -1, -1, 40, - -1, -1, 43, 44, -1, 46, 47, 48, -1, 50, - 51, 52, 53, 54, -1, 56, 57, -1, 59, 60, - 61, 62, 63, 64, -1, -1, 67, 68, 69, 70, - 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, - -1, -1, 83, 84, 85, 86, 87, 88, -1, 90, - 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, - -1, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, - 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, - 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, - 141, 142, -1, 144, 145, 146, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, - 161, 162, 163, 164, 165, 166, 167, -1, 169, -1, - -1, -1, 173, 174, 175, -1, 177, -1, 179, -1, - 181, 182, 183, 184, -1, 186, 187, 188, 189, 190, - 191, 192, -1, 194, 195, 196, 197, -1, 199, 200, - 201, 202, 203, 204, 205, -1, 207, -1, 209, 210, - 211, 212, 213, 214, 215, 216, 217, 218, -1, 220, - -1, -1, 223, -1, 225, 226, 227, 228, 229, 230, - -1, -1, 233, -1, 235, -1, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, -1, 269, 270, - 271, 272, 273, -1, 275, 276, -1, 278, -1, 280, - 281, 282, 283, 284, 285, 286, 287, 288, -1, -1, - 291, 292, 293, -1, 295, 296, 297, 298, -1, 300, - -1, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, -1, -1, -1, -1, 318, 319, 320, - -1, 322, 323, 324, 325, 326, 327, -1, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, -1, 345, 346, 347, 348, 349, 350, - 351, 352, 353, 354, 355, 356, 357, -1, 359, 360, - -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378, -1, -1, - 381, 382, 383, 384, 385, 386, 387, 388, 389, -1, - -1, 392, 393, 394, 395, -1, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, -1, -1, 414, 415, -1, 417, -1, 419, 420, - 421, 422, 423, -1, 425, 426, 427, -1, -1, 430, - 431, 432, 433, 434, -1, 436, 437, 438, 439, 440, - 441, 442, 443, 444, -1, 446, 447, 448, -1, 450, - 451, 452, 453, -1, 455, 456, 457, 458, 459, 460, - 461, -1, 463, -1, 465, 466, 467, 468, 469, 470, - 471, -1, -1, 474, -1, -1, 477, 478, 479, 480, - 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 494, 495, 496, 497, 3, -1, 5, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 515, -1, 22, 23, 24, 25, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 515, -1, 517, -1, -1, + -1, -1, 522, 523, -1, 525, 526, 3, 4, 5, + 6, 7, -1, 9, 10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, - 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, - 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, - -1, 67, 68, 69, 70, 71, 72, 73, -1, 75, - 76, 77, 78, 79, -1, -1, -1, 83, 84, 85, - 86, 87, 88, -1, 90, 91, 92, -1, 94, 95, - 96, 97, 98, 99, -1, -1, 102, 103, 104, 105, + -1, -1, -1, 39, -1, -1, 42, 43, 44, -1, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, - -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, - -1, 177, -1, 179, -1, 181, 182, 183, 184, -1, - 186, 187, 188, 189, 190, 191, 192, -1, 194, 195, - 196, 197, -1, 199, 200, 201, 202, 203, 204, 205, - -1, 207, -1, 209, 210, 211, 212, 213, 214, 215, - 216, -1, 218, -1, 220, -1, -1, 223, -1, 225, - 226, 227, 228, 229, 230, -1, -1, 233, -1, 235, - -1, -1, 238, 239, 240, 241, 242, 243, 244, 245, + 156, 157, 158, 159, 160, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, 171, -1, 173, 174, 175, + 176, 177, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, -1, -1, 234, 235, + 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, -1, 269, 270, 271, 272, 273, -1, 275, - 276, -1, 278, -1, 280, 281, 282, 283, 284, 285, - -1, 287, 288, -1, -1, 291, 292, 293, -1, -1, - 296, 297, 298, -1, 300, -1, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, -1, -1, - -1, -1, 318, 319, 320, -1, 322, 323, 324, 325, - 326, 327, -1, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, -1, 345, - 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, -1, 359, 360, -1, 362, 363, 364, 365, + 266, 267, 268, 269, 270, 271, 272, 273, 274, -1, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, -1, -1, 381, 382, 383, 384, 385, - 386, 387, 388, 389, -1, -1, 392, 393, 394, 395, - -1, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, -1, -1, 414, 415, - -1, 417, -1, 419, 420, 421, 422, 423, -1, 425, - 426, 427, -1, -1, 430, 431, 432, 433, 434, -1, - 436, 437, 438, 439, 440, 441, 442, 443, -1, -1, - 446, 447, 448, -1, 450, 451, 452, 453, -1, 455, - 456, 457, 458, 459, 460, 461, -1, 463, -1, 465, - 466, 467, 468, 469, 470, 471, -1, -1, 474, -1, - -1, 477, 478, 479, 480, 481, 482, 483, 484, 485, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, 394, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, 421, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, 467, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, - 496, 497, 3, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 514, 515, - -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, - 31, 32, 33, 34, 35, -1, 37, -1, -1, -1, - -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, + 496, 497, 498, 499, 500, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 515, + -1, 517, -1, -1, -1, -1, 522, 523, -1, 525, + 526, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, 39, -1, -1, + 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, + 52, -1, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, + -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, -1, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, 171, + -1, 173, 174, 175, 176, -1, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, -1, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + -1, -1, 224, 225, 226, 227, 228, 229, 230, 231, + -1, -1, 234, 235, 236, -1, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, -1, 276, 277, -1, 279, 280, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, -1, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, 421, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, 467, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, -1, + -1, -1, -1, -1, -1, -1, 508, 509, 510, -1, + 3, 4, 5, 515, -1, 517, 9, -1, -1, -1, + 522, 523, -1, 525, 526, -1, -1, -1, -1, 22, + 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, + 33, -1, -1, -1, 37, -1, -1, -1, -1, 42, + 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, + 63, 64, -1, -1, 67, 68, 69, 70, 71, 72, + 73, -1, 75, 76, 77, 78, 79, -1, 81, -1, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + -1, 94, 95, 96, 97, 98, 99, -1, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, 161, -1, + 163, 164, 165, 166, -1, 168, -1, 170, 171, -1, + 173, 174, 175, 176, 177, 178, -1, 180, -1, 182, + 183, 184, 185, -1, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, -1, 200, 201, 202, + 203, 204, 205, 206, -1, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, -1, 219, -1, 221, 222, + 223, 224, 225, 226, 227, 228, 229, 230, 231, -1, + -1, 234, 235, 236, 237, -1, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, + 273, 274, -1, 276, 277, 278, 279, -1, 281, 282, + 283, 284, 285, 286, -1, 288, 289, 290, -1, 292, + 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, -1, -1, -1, -1, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 328, -1, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, -1, 362, + 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, -1, + 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, + -1, 394, 395, 396, 397, 398, -1, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, -1, -1, 417, 418, -1, 420, 421, 422, + 423, 424, 425, 426, -1, 428, 429, 430, -1, -1, + 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, -1, -1, 449, 450, 451, -1, + 453, 454, 455, 456, -1, 458, 459, 460, 461, 462, + 463, 464, -1, 466, 467, 468, 469, 470, 471, 472, + 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, + 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 498, 499, 500, -1, -1, + -1, -1, 3, -1, -1, 508, 509, 510, -1, -1, + -1, -1, 515, -1, 517, -1, -1, -1, -1, -1, + 523, 22, 23, 24, 25, 26, 27, 28, 29, -1, + 31, 32, 33, -1, -1, -1, -1, -1, -1, 40, + -1, -1, 43, 44, -1, 46, 47, 48, -1, 50, + 51, 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, - 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, + -1, -1, 83, 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + -1, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, - 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, - -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, - 171, 172, 173, 174, 175, 176, 177, -1, 179, -1, - 181, 182, 183, 184, -1, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, 196, 197, -1, 199, 200, - 201, 202, 203, 204, 205, -1, 207, 208, 209, 210, - 211, 212, 213, 214, 215, 216, -1, 218, -1, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - -1, -1, 233, 234, 235, 236, -1, 238, 239, 240, + 141, 142, -1, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, -1, + 161, 162, 163, 164, 165, 166, 167, 168, -1, 170, + -1, -1, -1, 174, 175, 176, -1, 178, -1, 180, + -1, 182, 183, 184, 185, -1, 187, 188, 189, 190, + 191, 192, 193, -1, 195, 196, 197, 198, -1, 200, + 201, 202, 203, 204, 205, 206, -1, 208, -1, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, -1, + 221, -1, -1, 224, -1, 226, 227, 228, 229, 230, + 231, -1, -1, 234, -1, 236, -1, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - 271, 272, 273, -1, 275, 276, 277, 278, -1, 280, - 281, 282, 283, 284, 285, -1, 287, 288, -1, -1, - 291, 292, 293, -1, -1, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 314, 315, 316, -1, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, -1, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, -1, 345, 346, 347, 348, 349, 350, - 351, 352, 353, 354, 355, 356, 357, -1, 359, 360, - 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, + 261, 262, 263, 264, 265, 266, 267, 268, -1, 270, + 271, 272, 273, 274, -1, 276, 277, -1, 279, -1, + 281, 282, 283, 284, 285, 286, 287, 288, 289, -1, + -1, 292, 293, 294, -1, 296, 297, 298, 299, -1, + 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, -1, -1, -1, -1, 319, 320, + 321, -1, 323, 324, 325, 326, 327, 328, -1, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + -1, 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, -1, 397, 398, 399, 400, + 381, -1, -1, 384, 385, 386, 387, 388, 389, 390, + 391, 392, -1, -1, 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, 412, -1, 414, 415, 416, 417, 418, 419, 420, - 421, 422, 423, -1, 425, 426, 427, -1, -1, 430, - 431, 432, 433, 434, -1, 436, 437, 438, 439, 440, - 441, 442, 443, -1, -1, 446, 447, 448, 449, 450, - 451, 452, 453, -1, 455, 456, 457, 458, 459, 460, - 461, -1, 463, 464, 465, 466, 467, 468, 469, 470, - 471, -1, -1, 474, -1, 476, 477, 478, 479, 480, + 411, 412, 413, 414, -1, -1, 417, 418, -1, 420, + -1, 422, 423, 424, 425, 426, -1, 428, 429, 430, + -1, -1, 433, 434, 435, 436, 437, -1, 439, 440, + 441, 442, 443, 444, 445, 446, 447, -1, 449, 450, + 451, -1, 453, 454, 455, 456, -1, 458, 459, 460, + 461, 462, 463, 464, -1, 466, -1, 468, 469, 470, + 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 494, 495, 496, 497, -1, 3, 500, - 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 514, -1, -1, -1, 22, 23, 24, - 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, - -1, -1, -1, -1, -1, -1, -1, 42, 43, 44, + 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, + 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 518, -1, 22, + 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, + 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, + 53, 54, -1, 56, 57, -1, 59, 60, 61, 62, + 63, 64, -1, -1, 67, 68, 69, 70, 71, 72, + 73, -1, 75, 76, 77, 78, 79, -1, -1, -1, + 83, 84, 85, 86, 87, 88, -1, 90, 91, 92, + -1, 94, 95, 96, 97, 98, 99, -1, -1, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, -1, 161, -1, + 163, 164, 165, 166, -1, 168, -1, 170, -1, -1, + -1, 174, 175, 176, -1, 178, -1, 180, -1, 182, + 183, 184, 185, -1, 187, 188, 189, 190, 191, 192, + 193, -1, 195, 196, 197, 198, -1, 200, 201, 202, + 203, 204, 205, 206, -1, 208, -1, 210, 211, 212, + 213, 214, 215, 216, 217, -1, 219, -1, 221, -1, + -1, 224, -1, 226, 227, 228, 229, 230, 231, -1, + -1, 234, -1, 236, -1, -1, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, -1, 270, 271, 272, + 273, 274, -1, 276, 277, -1, 279, -1, 281, 282, + 283, 284, 285, 286, -1, 288, 289, -1, -1, 292, + 293, 294, -1, -1, 297, 298, 299, -1, 301, -1, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, -1, -1, -1, -1, 319, 320, 321, -1, + 323, 324, 325, 326, 327, 328, -1, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, -1, 362, + 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, -1, + -1, 384, 385, 386, 387, 388, 389, 390, 391, 392, + -1, -1, 395, 396, 397, 398, -1, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, -1, -1, 417, 418, -1, 420, -1, 422, + 423, 424, 425, 426, -1, 428, 429, 430, -1, -1, + 433, 434, 435, 436, 437, -1, 439, 440, 441, 442, + 443, 444, 445, 446, -1, -1, 449, 450, 451, -1, + 453, 454, 455, 456, -1, 458, 459, 460, 461, 462, + 463, 464, -1, 466, -1, 468, 469, 470, 471, 472, + 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, + 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 498, 499, 500, 3, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 517, 518, -1, 22, 23, 24, + 25, 26, 27, 28, 29, -1, 31, 32, 33, 34, + 35, -1, 37, -1, -1, -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, - -1, 66, 67, 68, 69, 70, 71, 72, 73, -1, + -1, -1, 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, @@ -14721,142 +13460,143 @@ static const yytype_int16 yycheck[] = 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, -1, 160, -1, 162, 163, 164, - 165, -1, 167, -1, 169, 170, 171, 172, 173, 174, - 175, 176, 177, -1, 179, -1, 181, 182, 183, 184, - -1, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, -1, 199, 200, 201, 202, 203, 204, - 205, -1, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, -1, 218, -1, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, -1, 233, 234, - 235, 236, -1, 238, 239, 240, 241, 242, 243, 244, + 155, 156, 157, 158, 159, -1, 161, -1, 163, 164, + 165, 166, -1, 168, -1, 170, 171, 172, 173, 174, + 175, 176, 177, 178, -1, 180, -1, 182, 183, 184, + 185, -1, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, -1, 200, 201, 202, 203, 204, + 205, 206, -1, 208, 209, 210, 211, 212, 213, 214, + 215, 216, 217, -1, 219, -1, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, -1, -1, 234, + 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, -1, - 275, 276, 277, 278, -1, 280, 281, 282, 283, 284, - 285, -1, 287, 288, -1, 290, 291, 292, 293, -1, - -1, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + -1, 276, 277, 278, 279, -1, 281, 282, 283, 284, + 285, 286, -1, 288, 289, -1, -1, 292, 293, 294, + -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, -1, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, -1, 329, 330, 331, 332, 333, 334, - -1, 336, 337, 338, 339, 340, 341, 342, 343, -1, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, -1, 359, 360, 361, 362, 363, 364, + 315, 316, 317, -1, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, -1, 330, 331, 332, 333, 334, + 335, -1, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, -1, 381, 382, 383, 384, + 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, -1, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, 412, -1, 414, - 415, 416, 417, 418, 419, 420, 421, 422, 423, -1, - 425, 426, 427, -1, -1, 430, 431, 432, 433, 434, - -1, 436, 437, 438, 439, 440, 441, 442, 443, -1, - -1, 446, 447, 448, 449, 450, 451, 452, 453, -1, - 455, 456, 457, 458, 459, 460, 461, -1, 463, 464, - 465, 466, 467, 468, 469, 470, 471, -1, -1, 474, - -1, 476, 477, 478, 479, 480, 481, 482, 483, 484, + 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 415, -1, 417, 418, 419, 420, 421, 422, 423, 424, + 425, 426, -1, 428, 429, 430, -1, -1, 433, 434, + 435, 436, 437, -1, 439, 440, 441, 442, 443, 444, + 445, 446, -1, -1, 449, 450, 451, 452, 453, 454, + 455, 456, -1, 458, 459, 460, 461, 462, 463, 464, + -1, 466, 467, 468, 469, 470, 471, 472, 473, 474, + -1, -1, 477, -1, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, - 495, 496, 497, -1, 3, 500, 5, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 514, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, 66, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, -1, 172, 173, 174, 175, 176, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, -1, 233, 234, 235, 236, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, -1, 275, 276, 277, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, 290, 291, 292, 293, -1, -1, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + 495, 496, 497, 498, 499, 500, -1, 3, 503, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 514, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, 42, 43, - 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, 66, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, 81, -1, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, - 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, -1, -1, 233, - 234, 235, 236, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - -1, 275, 276, 277, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, 391, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, 418, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - 464, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, + -1, -1, 517, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, -1, -1, -1, 42, 43, 44, -1, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, + 66, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, 81, -1, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, -1, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, 171, 172, 173, 174, 175, + 176, 177, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, 232, -1, 234, 235, + 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, -1, + 276, 277, 278, 279, -1, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, 291, 292, 293, 294, -1, + -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, -1, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, 382, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, + -1, 417, 418, 419, 420, 421, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, -1, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, 452, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, 467, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, 479, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, -1, 3, 503, 5, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 517, -1, -1, -1, 22, 23, 24, 25, 26, + 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, + -1, -1, -1, -1, -1, 42, 43, 44, -1, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, -1, 59, 60, 61, 62, 63, 64, -1, 66, + 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, + 77, 78, 79, -1, 81, -1, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, -1, 94, 95, 96, + 97, 98, 99, -1, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, + -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, -1, 161, -1, 163, 164, 165, 166, + -1, 168, -1, 170, 171, -1, 173, 174, 175, 176, + 177, 178, -1, 180, -1, 182, 183, 184, 185, -1, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, -1, 200, 201, 202, 203, 204, 205, 206, + -1, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, -1, 219, -1, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, -1, 234, 235, 236, + 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, -1, 276, + 277, 278, 279, -1, 281, 282, 283, 284, 285, 286, + -1, 288, 289, -1, 291, 292, 293, 294, -1, -1, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, -1, -1, + -1, -1, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 328, -1, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + -1, 348, 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, + 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, -1, -1, 384, 385, 386, + 387, 388, 389, 390, 391, 392, -1, 394, 395, 396, + 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, -1, -1, + 417, 418, -1, 420, 421, 422, 423, 424, 425, 426, + -1, 428, 429, 430, -1, -1, 433, 434, 435, 436, + 437, -1, 439, 440, 441, 442, 443, 444, 445, 446, + -1, -1, 449, 450, 451, -1, 453, 454, 455, 456, + -1, 458, 459, 460, 461, 462, 463, 464, -1, 466, + 467, 468, 469, 470, 471, 472, 473, 474, -1, -1, + 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, + 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 514, -1, -1, 22, 23, 24, 25, 26, 27, 28, + 517, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, @@ -14870,240 +13610,92 @@ static const yytype_int16 yycheck[] = 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, -1, 172, 173, 174, 175, 176, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, -1, -1, 233, 234, 235, 236, -1, 238, + 159, -1, 161, -1, 163, 164, 165, 166, -1, 168, + -1, 170, 171, -1, 173, 174, 175, 176, 177, 178, + -1, 180, -1, 182, 183, 184, 185, -1, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, + -1, 200, 201, 202, 203, 204, 205, 206, -1, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, -1, + 219, -1, 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, -1, 275, 276, 277, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, + 269, 270, 271, 272, 273, 274, -1, 276, 277, 278, + 279, -1, 281, 282, 283, 284, 285, 286, -1, 288, + 289, -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 514, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, 171, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, 390, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, 412, -1, - 414, 415, 416, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, 449, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, 476, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 500, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 514, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, 171, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, + 309, 310, 311, 312, 313, 314, -1, -1, -1, -1, + 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, + -1, 330, 331, 332, 333, 334, 335, -1, 337, 338, + 339, 340, 341, 342, 343, 344, 345, 346, -1, 348, + 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - 379, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, 416, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - 449, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, 476, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, - -1, 500, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 514, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, 171, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, 416, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, 449, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, 476, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, -1, 3, 500, 5, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 514, -1, -1, -1, 22, 23, 24, 25, 26, 27, - 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, - 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, - -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, - 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, - 78, 79, -1, -1, -1, 83, 84, 85, 86, 87, - 88, -1, 90, 91, 92, -1, 94, 95, 96, 97, - 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, - 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, - 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, - 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, -1, 160, -1, 162, 163, 164, 165, -1, 167, - -1, 169, -1, -1, -1, 173, 174, 175, -1, 177, - -1, 179, -1, 181, 182, 183, 184, -1, 186, 187, - 188, 189, 190, 191, 192, -1, 194, 195, 196, 197, - -1, 199, 200, 201, 202, 203, 204, 205, -1, 207, - -1, 209, 210, 211, 212, 213, 214, 215, 216, -1, - 218, -1, 220, -1, -1, 223, -1, 225, 226, 227, - 228, 229, 230, -1, -1, 233, -1, 235, -1, -1, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - -1, 269, 270, 271, 272, 273, -1, 275, 276, -1, - 278, -1, 280, 281, 282, 283, 284, 285, -1, 287, - 288, -1, -1, 291, 292, 293, -1, -1, 296, 297, - 298, -1, 300, -1, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, -1, -1, -1, -1, - 318, 319, 320, -1, 322, 323, 324, 325, 326, 327, - -1, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, -1, 345, 346, 347, - 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - -1, 359, 360, -1, 362, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, -1, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, -1, -1, 392, 393, 394, 395, -1, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 411, -1, -1, 414, 415, -1, 417, - -1, 419, 420, 421, 422, 423, -1, 425, 426, 427, - -1, -1, 430, 431, 432, 433, 434, -1, 436, 437, - 438, 439, 440, 441, 442, 443, -1, -1, 446, 447, - 448, -1, 450, 451, 452, 453, -1, 455, 456, 457, - 458, 459, 460, 461, -1, 463, -1, 465, 466, 467, - 468, 469, 470, 471, -1, -1, 474, -1, -1, 477, - 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, - 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, - 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 514, -1, -1, 22, + 379, 380, 381, -1, -1, 384, 385, 386, 387, 388, + 389, 390, 391, 392, -1, 394, 395, 396, 397, 398, + -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, -1, -1, 417, 418, + -1, 420, 421, 422, 423, 424, 425, 426, -1, 428, + 429, 430, -1, -1, 433, 434, 435, 436, 437, -1, + 439, 440, 441, 442, 443, 444, 445, 446, -1, -1, + 449, 450, 451, -1, 453, 454, 455, 456, -1, 458, + 459, 460, 461, 462, 463, 464, -1, 466, 467, 468, + 469, 470, 471, 472, 473, 474, -1, -1, 477, -1, + -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, + 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 517, -1, + -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, + 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, + -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, -1, 59, 60, + 61, 62, 63, 64, -1, 66, 67, 68, 69, 70, + 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, + 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, -1, + 161, -1, 163, 164, 165, 166, -1, 168, -1, 170, + 171, -1, 173, 174, 175, 176, 177, 178, -1, 180, + -1, 182, 183, 184, 185, -1, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, -1, 200, + 201, 202, 203, 204, 205, 206, -1, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, -1, 219, -1, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, -1, -1, 234, 235, 236, 237, -1, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 273, 274, -1, 276, 277, 278, 279, -1, + 281, 282, 283, 284, 285, 286, -1, 288, 289, -1, + -1, 292, 293, 294, -1, -1, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, -1, -1, -1, -1, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 328, -1, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, -1, -1, 384, 385, 386, 387, 388, 389, 390, + 391, 392, -1, 394, 395, 396, 397, 398, -1, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, -1, -1, 417, 418, -1, 420, + 421, 422, 423, 424, 425, 426, -1, 428, 429, 430, + -1, -1, 433, 434, 435, 436, 437, -1, 439, 440, + 441, 442, 443, 444, 445, 446, -1, -1, 449, 450, + 451, -1, 453, 454, 455, 456, -1, 458, 459, 460, + 461, 462, 463, 464, -1, 466, 467, 468, 469, 470, + 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, + 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, + 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 517, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, @@ -15114,46 +13706,146 @@ static const yytype_int16 yycheck[] = -1, 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, - 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, + 123, 124, 125, 126, 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, -1, 160, -1, 162, - 163, 164, 165, -1, 167, -1, 169, -1, -1, -1, - 173, 174, 175, -1, 177, -1, 179, -1, 181, 182, - 183, 184, -1, 186, 187, 188, 189, 190, 191, 192, - -1, 194, 195, 196, 197, -1, 199, 200, 201, 202, - 203, 204, 205, -1, 207, -1, 209, 210, 211, 212, - 213, 214, 215, 216, -1, 218, -1, 220, -1, -1, - 223, -1, 225, 226, 227, 228, 229, 230, -1, -1, - 233, -1, 235, -1, -1, 238, 239, 240, 241, 242, + 153, 154, 155, 156, 157, 158, 159, -1, 161, -1, + 163, 164, 165, 166, -1, 168, -1, 170, -1, 172, + -1, 174, 175, 176, -1, 178, -1, 180, -1, 182, + 183, 184, 185, -1, 187, 188, 189, 190, 191, 192, + 193, -1, 195, 196, 197, 198, -1, 200, 201, 202, + 203, 204, 205, 206, -1, 208, -1, 210, 211, 212, + 213, 214, 215, 216, 217, -1, 219, -1, 221, -1, + -1, 224, -1, 226, 227, 228, 229, 230, 231, -1, + -1, 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, -1, 269, 270, 271, 272, - 273, -1, 275, 276, -1, 278, -1, 280, 281, 282, - 283, 284, 285, -1, 287, 288, -1, -1, 291, 292, - 293, -1, -1, 296, 297, 298, -1, 300, -1, 302, + 263, 264, 265, 266, 267, 268, -1, 270, 271, 272, + 273, 274, -1, 276, 277, -1, 279, -1, 281, 282, + 283, 284, 285, 286, -1, 288, 289, -1, -1, 292, + 293, 294, -1, -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, -1, -1, -1, -1, 318, 319, 320, -1, 322, - 323, 324, 325, 326, 327, -1, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, -1, 345, 346, 347, 348, 349, 350, 351, 352, - 353, 354, 355, 356, 357, -1, 359, 360, -1, 362, - 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, -1, -1, 381, 382, - 383, 384, 385, 386, 387, 388, 389, -1, -1, 392, - 393, 394, 395, -1, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 411, -1, - -1, 414, 415, -1, 417, -1, 419, 420, 421, 422, - 423, -1, 425, 426, 427, -1, -1, 430, 431, 432, - 433, 434, -1, 436, 437, 438, 439, 440, 441, 442, - 443, -1, -1, 446, 447, 448, -1, 450, 451, 452, - 453, -1, 455, 456, 457, 458, 459, 460, 461, -1, - 463, -1, 465, 466, 467, 468, 469, 470, 471, -1, - -1, 474, -1, -1, 477, 478, 479, 480, 481, 482, + 313, 314, 315, 316, 317, -1, 319, 320, 321, -1, + 323, 324, 325, 326, 327, 328, -1, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, -1, 362, + 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + -1, 384, 385, 386, 387, 388, 389, 390, 391, 392, + 393, -1, 395, 396, 397, 398, -1, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, -1, 417, 418, 419, 420, -1, 422, + 423, 424, 425, 426, -1, 428, 429, 430, -1, -1, + 433, 434, 435, 436, 437, -1, 439, 440, 441, 442, + 443, 444, 445, 446, -1, -1, 449, 450, 451, 452, + 453, 454, 455, 456, -1, 458, 459, 460, 461, 462, + 463, 464, -1, 466, -1, 468, 469, 470, 471, 472, + 473, 474, -1, -1, 477, -1, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 494, 495, 496, 497, 3, -1, 5, -1, -1, + 493, 494, 495, 496, 497, 498, 499, 500, 3, -1, + 503, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 517, -1, -1, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, + -1, 46, 47, 48, -1, 50, 51, 52, 53, 54, + -1, 56, 57, -1, 59, 60, 61, 62, 63, 64, + -1, -1, 67, 68, 69, 70, 71, 72, 73, -1, + 75, 76, 77, 78, 79, -1, -1, -1, 83, 84, + 85, 86, 87, 88, -1, 90, 91, 92, -1, 94, + 95, 96, 97, 98, 99, -1, -1, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, -1, 118, -1, 120, 121, 122, 123, 124, + 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, + 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, + 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, -1, 161, -1, 163, 164, + 165, 166, -1, 168, -1, 170, -1, 172, -1, 174, + 175, 176, -1, 178, -1, 180, -1, 182, 183, 184, + 185, -1, 187, 188, 189, 190, 191, 192, 193, -1, + 195, 196, 197, 198, -1, 200, 201, 202, 203, 204, + 205, 206, -1, 208, -1, 210, 211, 212, 213, 214, + 215, 216, 217, -1, 219, -1, 221, -1, -1, 224, + -1, 226, 227, 228, 229, 230, 231, -1, -1, 234, + -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, -1, 270, 271, 272, 273, 274, + -1, 276, 277, -1, 279, -1, 281, 282, 283, 284, + 285, 286, -1, 288, 289, -1, -1, 292, 293, 294, + -1, -1, 297, 298, 299, -1, 301, -1, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, -1, 319, 320, 321, -1, 323, 324, + 325, 326, 327, 328, -1, 330, 331, 332, 333, 334, + 335, -1, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, -1, 362, 363, -1, + 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, 382, -1, 384, + 385, 386, 387, 388, 389, 390, 391, 392, -1, -1, + 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + -1, -1, 417, 418, 419, 420, -1, 422, 423, 424, + 425, 426, -1, 428, 429, 430, -1, -1, 433, 434, + 435, 436, 437, -1, 439, 440, 441, 442, 443, 444, + 445, 446, -1, -1, 449, 450, 451, 452, 453, 454, + 455, 456, -1, 458, 459, 460, 461, 462, 463, 464, + -1, 466, -1, 468, 469, 470, 471, 472, 473, 474, + -1, -1, 477, -1, 479, 480, 481, 482, 483, 484, + 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 498, 499, 500, 3, -1, 503, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 517, -1, -1, 22, 23, 24, 25, 26, + 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 43, 44, -1, 46, + 47, 48, -1, 50, 51, 52, 53, 54, -1, 56, + 57, -1, 59, 60, 61, 62, 63, 64, -1, -1, + 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, + 77, 78, 79, -1, -1, -1, 83, 84, 85, 86, + 87, 88, -1, 90, 91, 92, -1, 94, 95, 96, + 97, 98, 99, -1, -1, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, + -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, -1, 161, -1, 163, 164, 165, 166, + -1, 168, -1, 170, -1, 172, -1, 174, 175, 176, + -1, 178, -1, 180, -1, 182, 183, 184, 185, -1, + 187, 188, 189, 190, 191, 192, 193, -1, 195, 196, + 197, 198, -1, 200, 201, 202, 203, 204, 205, 206, + -1, 208, -1, 210, 211, 212, 213, 214, 215, 216, + 217, -1, 219, -1, 221, -1, -1, 224, -1, 226, + 227, 228, 229, 230, 231, -1, -1, 234, -1, 236, + -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, -1, 270, 271, 272, 273, 274, -1, 276, + 277, -1, 279, -1, 281, 282, 283, 284, 285, 286, + -1, 288, 289, -1, -1, 292, 293, 294, -1, -1, + 297, 298, 299, -1, 301, -1, 303, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + 317, -1, 319, 320, 321, -1, 323, 324, 325, 326, + 327, 328, -1, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + -1, 348, 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, -1, 362, 363, -1, 365, 366, + 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, -1, 384, 385, 386, + 387, 388, 389, 390, 391, 392, -1, -1, 395, 396, + 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, -1, -1, + 417, 418, 419, 420, -1, 422, 423, 424, 425, 426, + -1, 428, 429, 430, -1, -1, 433, 434, 435, 436, + 437, -1, 439, 440, 441, 442, 443, 444, 445, 446, + -1, -1, 449, 450, 451, 452, 453, 454, 455, 456, + -1, 458, 459, 460, 461, 462, 463, 464, -1, 466, + -1, 468, 469, 470, 471, 472, 473, 474, -1, -1, + 477, -1, 479, 480, 481, 482, 483, 484, 485, 486, + 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 498, 499, 500, -1, 3, 503, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 514, -1, -1, 22, 23, 24, 25, 26, 27, + 517, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, @@ -15167,290 +13859,242 @@ static const yytype_int16 yycheck[] = 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, -1, 160, -1, 162, 163, 164, 165, -1, 167, - -1, 169, -1, -1, -1, 173, 174, 175, -1, 177, - -1, 179, -1, 181, 182, 183, 184, -1, 186, 187, - 188, 189, 190, 191, 192, -1, 194, 195, 196, 197, - -1, 199, 200, 201, 202, 203, 204, 205, -1, 207, - -1, 209, 210, 211, 212, 213, 214, 215, 216, -1, - 218, -1, 220, -1, -1, 223, -1, 225, 226, 227, - 228, 229, 230, -1, -1, 233, -1, 235, -1, -1, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 158, 159, -1, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, -1, -1, -1, 174, 175, 176, -1, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, -1, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, -1, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, -1, -1, 224, -1, 226, 227, + 228, 229, 230, 231, -1, -1, 234, -1, 236, -1, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - -1, 269, 270, 271, 272, 273, -1, 275, 276, -1, - 278, -1, 280, 281, 282, 283, 284, 285, -1, 287, - 288, -1, -1, 291, 292, 293, -1, -1, 296, 297, - 298, -1, 300, -1, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, -1, -1, -1, -1, - 318, 319, 320, -1, 322, 323, 324, 325, 326, 327, - -1, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, -1, 345, 346, 347, + 268, -1, 270, 271, 272, 273, 274, -1, 276, 277, + -1, 279, -1, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, -1, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - -1, 359, 360, -1, 362, 363, 364, 365, 366, 367, + 358, 359, 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, -1, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, -1, -1, 392, 393, 394, 395, -1, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 411, -1, -1, 414, 415, -1, 417, - -1, 419, 420, 421, 422, 423, -1, 425, 426, 427, - -1, -1, 430, 431, 432, 433, 434, -1, 436, 437, - 438, 439, 440, 441, 442, 443, -1, -1, 446, 447, - 448, -1, 450, 451, 452, 453, -1, 455, 456, 457, - 458, 459, 460, 461, -1, 463, -1, 465, 466, 467, - 468, 469, 470, 471, -1, -1, 474, -1, -1, 477, - 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, -1, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, -1, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + -1, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, -1, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, - 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 514, -1, -1, 22, - 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, - 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, - 53, 54, -1, 56, 57, -1, 59, 60, 61, 62, - 63, 64, -1, -1, 67, 68, 69, 70, 71, 72, - 73, -1, 75, 76, 77, 78, 79, -1, -1, -1, - 83, 84, 85, 86, 87, 88, -1, 90, 91, 92, - -1, 94, 95, 96, 97, 98, 99, -1, -1, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, - 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, - -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, - -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, -1, 160, -1, 162, - 163, 164, 165, -1, 167, -1, 169, -1, -1, -1, - 173, 174, 175, -1, 177, -1, 179, -1, 181, 182, - 183, 184, -1, 186, 187, 188, 189, 190, 191, 192, - -1, 194, 195, 196, 197, -1, 199, 200, 201, 202, - 203, 204, 205, -1, 207, -1, 209, 210, 211, 212, - 213, 214, 215, 216, -1, 218, -1, 220, -1, -1, - 223, -1, 225, 226, 227, 228, 229, 230, -1, -1, - 233, -1, 235, -1, -1, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, -1, 269, 270, 271, 272, - 273, -1, 275, 276, -1, 278, -1, 280, 281, 282, - 283, 284, 285, -1, 287, 288, -1, -1, 291, 292, - 293, -1, -1, 296, 297, 298, -1, 300, -1, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, -1, -1, -1, -1, 318, 319, 320, -1, 322, - 323, 324, 325, 326, 327, -1, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, -1, 345, 346, 347, 348, 349, 350, 351, 352, - 353, 354, 355, 356, 357, -1, 359, 360, -1, 362, - 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, -1, -1, 381, 382, - 383, 384, 385, 386, 387, 388, 389, -1, -1, 392, - 393, 394, 395, -1, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 411, -1, - -1, 414, 415, -1, 417, -1, 419, 420, 421, 422, - 423, -1, 425, 426, 427, -1, -1, 430, 431, 432, - 433, 434, -1, 436, 437, 438, 439, 440, 441, 442, - 443, -1, -1, 446, 447, 448, -1, 450, 451, 452, - 453, -1, 455, 456, 457, 458, 459, 460, 461, -1, - 463, -1, 465, 466, 467, 468, 469, 470, 471, -1, - -1, 474, -1, -1, 477, 478, 479, 480, 481, 482, - 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 494, 495, 496, 497, 3, -1, 5, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 514, -1, -1, 22, 23, 24, 25, 26, 27, - 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, - 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, - -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, - 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, - 78, 79, -1, -1, -1, 83, 84, 85, 86, 87, - 88, -1, 90, 91, 92, -1, 94, 95, 96, 97, - 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, - 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, - 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, - 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, -1, 160, -1, 162, 163, 164, 165, -1, 167, - -1, 169, -1, -1, -1, 173, 174, 175, -1, 177, - -1, 179, -1, 181, 182, 183, 184, -1, 186, 187, - 188, 189, 190, 191, 192, -1, 194, 195, 196, 197, - -1, 199, 200, 201, 202, 203, 204, 205, -1, 207, - -1, 209, 210, 211, 212, 213, 214, 215, 216, -1, - 218, -1, 220, -1, -1, 223, -1, 225, 226, 227, - 228, 229, 230, -1, -1, 233, -1, 235, -1, -1, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - -1, 269, 270, 271, 272, 273, -1, 275, 276, -1, - 278, -1, 280, 281, 282, 283, 284, 285, -1, 287, - 288, -1, -1, 291, 292, 293, -1, -1, 296, 297, - 298, -1, 300, -1, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, -1, -1, -1, -1, - 318, 319, 320, -1, 322, 323, 324, 325, 326, 327, - -1, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, -1, 345, 346, 347, - 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - -1, 359, 360, -1, 362, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, -1, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, -1, -1, 392, 393, 394, 395, -1, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 411, -1, -1, 414, 415, -1, 417, - -1, 419, 420, 421, 422, 423, -1, 425, 426, 427, - -1, -1, 430, 431, 432, 433, 434, -1, 436, 437, - 438, 439, 440, 441, 442, 443, -1, -1, 446, 447, - 448, -1, 450, 451, 452, 453, -1, 455, 456, 457, - 458, 459, 460, 461, -1, 463, -1, 465, 466, 467, - 468, 469, 470, 471, -1, -1, 474, -1, -1, 477, - 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, - 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, - 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 514, -1, -1, 22, - 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, - 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, - 53, 54, -1, 56, 57, -1, 59, 60, 61, 62, - 63, 64, -1, -1, 67, 68, 69, 70, 71, 72, - 73, -1, 75, 76, 77, 78, 79, -1, -1, -1, - 83, 84, 85, 86, 87, 88, -1, 90, 91, 92, - -1, 94, 95, 96, 97, 98, 99, -1, -1, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, - 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, - -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, - -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, -1, 160, -1, 162, - 163, 164, 165, -1, 167, -1, 169, -1, -1, -1, - 173, 174, 175, -1, 177, -1, 179, -1, 181, 182, - 183, 184, -1, 186, 187, 188, 189, 190, 191, 192, - -1, 194, 195, 196, 197, -1, 199, 200, 201, 202, - 203, 204, 205, -1, 207, -1, 209, 210, 211, 212, - 213, 214, 215, 216, -1, 218, -1, 220, -1, -1, - 223, -1, 225, 226, 227, 228, 229, 230, -1, -1, - 233, -1, 235, -1, -1, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, -1, 269, 270, 271, 272, - 273, -1, 275, 276, -1, 278, -1, 280, 281, 282, - 283, 284, 285, -1, 287, 288, -1, -1, 291, 292, - 293, -1, -1, 296, 297, 298, -1, 300, -1, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, -1, -1, -1, -1, 318, 319, 320, -1, 322, - 323, 324, 325, 326, 327, -1, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, -1, 345, 346, 347, 348, 349, 350, 351, 352, - 353, 354, 355, 356, 357, -1, 359, 360, -1, 362, - 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, -1, -1, 381, 382, - 383, 384, 385, 386, 387, 388, 389, -1, -1, 392, - 393, 394, 395, -1, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 411, -1, - -1, 414, 415, -1, 417, -1, 419, 420, 421, 422, - 423, -1, 425, 426, 427, -1, -1, 430, 431, 432, - 433, 434, -1, 436, 437, 438, 439, 440, 441, 442, - 443, -1, -1, 446, 447, 448, -1, 450, 451, 452, - 453, -1, 455, 456, 457, 458, 459, 460, 461, -1, - 463, -1, 465, 466, 467, 468, 469, 470, 471, -1, - -1, 474, -1, -1, 477, 478, 479, 480, 481, 482, - 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 494, 495, 496, 497, 3, -1, -1, -1, -1, + 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 517, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, + 50, 51, 52, 53, 54, -1, 56, 57, -1, 59, + 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, -1, -1, 83, 84, 85, 86, 87, 88, -1, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + -1, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, -1, -1, -1, 174, 175, 176, -1, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, -1, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, -1, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, -1, -1, 224, -1, 226, 227, 228, 229, + 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, -1, + 270, 271, 272, 273, 274, -1, 276, 277, -1, 279, + -1, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, + -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, -1, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, -1, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, -1, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, -1, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, -1, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 517, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, + 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, + 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, -1, + -1, 83, 84, 85, 86, 87, 88, -1, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, -1, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, -1, + -1, -1, 174, 175, 176, -1, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, -1, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, -1, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + -1, -1, 224, -1, 226, 227, 228, 229, 230, 231, + -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, -1, 270, 271, + 272, 273, 274, -1, 276, 277, -1, 279, -1, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, -1, 301, + -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + -1, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, -1, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, -1, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, -1, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, -1, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 3, + -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 517, -1, -1, 22, 23, + 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, + 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, + 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, + 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, + -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, + 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, + 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, + 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, -1, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, -1, -1, -1, + 174, 175, 176, -1, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + -1, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, -1, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, -1, -1, + 224, -1, 226, 227, 228, 229, 230, 231, -1, -1, + 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, -1, 270, 271, 272, 273, + 274, -1, 276, 277, -1, 279, -1, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, -1, 301, -1, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, -1, -1, -1, -1, 319, 320, 321, -1, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + -1, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, -1, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, -1, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, -1, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, + 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, + 494, 495, 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 514, -1, -1, 22, 23, 24, 25, 26, 27, - 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, - 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, - -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, - 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, - 78, 79, -1, -1, -1, 83, 84, 85, 86, 87, - 88, -1, 90, 91, 92, -1, 94, 95, 96, 97, - 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, - 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, - 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, - 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, -1, 160, -1, 162, 163, 164, 165, -1, 167, - -1, 169, -1, -1, -1, 173, 174, 175, -1, 177, - -1, 179, -1, 181, 182, 183, 184, -1, 186, 187, - 188, 189, 190, 191, 192, -1, 194, 195, 196, 197, - -1, 199, 200, 201, 202, 203, 204, 205, -1, 207, - -1, 209, 210, 211, 212, 213, 214, 215, 216, -1, - 218, -1, 220, -1, -1, 223, -1, 225, 226, 227, - 228, 229, 230, -1, -1, 233, -1, 235, -1, -1, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - -1, 269, 270, 271, 272, 273, -1, 275, 276, -1, - 278, -1, 280, 281, 282, 283, 284, 285, -1, 287, - 288, -1, -1, 291, 292, 293, -1, -1, 296, 297, - 298, -1, 300, -1, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, -1, -1, -1, -1, - 318, 319, 320, -1, 322, 323, 324, 325, 326, 327, - -1, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, -1, 345, 346, 347, - 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - -1, 359, 360, -1, 362, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, -1, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, -1, -1, 392, 393, 394, 395, -1, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 411, -1, -1, 414, 415, -1, 417, - -1, 419, 420, 421, 422, 423, -1, 425, 426, 427, - -1, -1, 430, 431, 432, 433, 434, -1, 436, 437, - 438, 439, 440, 441, 442, 443, -1, -1, 446, 447, - 448, -1, 450, 451, 452, 453, -1, 455, 456, 457, - 458, 459, 460, 461, -1, 463, -1, 465, 466, 467, - 468, 469, 470, 471, -1, -1, 474, -1, -1, 477, - 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, - 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, - 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 514, -1, -1, 22, - 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, - 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, - 53, 54, -1, 56, 57, -1, 59, 60, 61, 62, - 63, 64, -1, -1, 67, 68, 69, 70, 71, 72, - 73, -1, 75, 76, 77, 78, 79, -1, -1, -1, - 83, 84, 85, 86, 87, 88, -1, 90, 91, 92, - -1, 94, 95, 96, 97, 98, 99, -1, -1, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, - 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, - -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, - -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, -1, 160, -1, 162, - 163, 164, 165, -1, 167, -1, 169, -1, -1, -1, - 173, 174, 175, -1, 177, -1, 179, -1, 181, 182, - 183, 184, -1, 186, 187, 188, 189, 190, 191, 192, - -1, 194, 195, 196, 197, -1, 199, 200, 201, 202, - 203, 204, 205, -1, 207, -1, 209, 210, 211, 212, - 213, 214, 215, 216, -1, 218, -1, 220, -1, -1, - 223, -1, 225, 226, 227, 228, 229, 230, -1, -1, - 233, -1, 235, -1, -1, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, -1, 269, 270, 271, 272, - 273, -1, 275, 276, -1, 278, -1, 280, 281, 282, - 283, 284, 285, -1, 287, 288, -1, -1, 291, 292, - 293, -1, -1, 296, 297, 298, -1, 300, -1, 302, - 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, - 313, -1, -1, -1, -1, 318, 319, 320, -1, 322, - 323, 324, 325, 326, 327, -1, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, -1, 345, 346, 347, 348, 349, 350, 351, 352, - 353, 354, 355, 356, 357, -1, 359, 360, -1, 362, - 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, -1, -1, 381, 382, - 383, 384, 385, 386, 387, 388, 389, -1, -1, 392, - 393, 394, 395, -1, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 411, -1, - -1, 414, 415, -1, 417, -1, 419, 420, 421, 422, - 423, -1, 425, 426, 427, -1, -1, 430, 431, 432, - 433, 434, -1, 436, 437, 438, 439, 440, 441, 442, - 443, -1, -1, 446, 447, 448, -1, 450, 451, 452, - 453, -1, 455, 456, 457, 458, 459, 460, 461, -1, - 463, -1, 465, 466, 467, 468, 469, 470, 471, -1, - -1, 474, -1, -1, 477, 478, 479, 480, 481, 482, - 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, - 493, 494, 495, 496, 497, 3, -1, -1, -1, -1, + -1, -1, -1, 517, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, + 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, + 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, + -1, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, -1, -1, 83, 84, 85, + 86, 87, 88, -1, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, -1, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, -1, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, -1, -1, -1, 174, 175, + 176, -1, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, -1, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, -1, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, -1, -1, 224, -1, + 226, 227, 228, 229, 230, 231, -1, -1, 234, -1, + 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, -1, 270, 271, 272, 273, 274, -1, + 276, 277, -1, 279, -1, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, -1, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, -1, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, -1, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, -1, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, -1, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, -1, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 514, -1, -1, 22, 23, 24, 25, 26, 27, + -1, 517, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, @@ -15464,91 +14108,241 @@ static const yytype_int16 yycheck[] = 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, -1, 160, -1, 162, 163, 164, 165, -1, 167, - -1, 169, -1, -1, -1, 173, 174, 175, -1, 177, - -1, 179, -1, 181, 182, 183, 184, -1, 186, 187, - 188, 189, 190, 191, 192, -1, 194, 195, 196, 197, - -1, 199, 200, 201, 202, 203, 204, 205, -1, 207, - -1, 209, 210, 211, 212, 213, 214, 215, 216, -1, - 218, -1, 220, -1, -1, 223, -1, 225, 226, 227, - 228, 229, 230, -1, -1, 233, -1, 235, -1, -1, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 158, 159, -1, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, -1, -1, -1, 174, 175, 176, -1, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, -1, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, -1, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, -1, -1, 224, -1, 226, 227, + 228, 229, 230, 231, -1, -1, 234, -1, 236, -1, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - -1, 269, 270, 271, 272, 273, -1, 275, 276, -1, - 278, -1, 280, 281, 282, 283, 284, 285, -1, 287, - 288, -1, -1, 291, 292, 293, -1, -1, 296, 297, - 298, -1, 300, -1, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, -1, -1, -1, -1, - 318, 319, 320, -1, 322, 323, 324, 325, 326, 327, - -1, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, -1, 345, 346, 347, + 268, -1, 270, 271, 272, 273, 274, -1, 276, 277, + -1, 279, -1, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, -1, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, - -1, 359, 360, -1, 362, 363, 364, 365, 366, 367, + 358, 359, 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, -1, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, -1, -1, 392, 393, 394, 395, -1, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 409, 410, 411, -1, -1, 414, 415, -1, 417, - -1, 419, 420, 421, 422, 423, -1, 425, 426, 427, - -1, -1, 430, 431, 432, 433, 434, -1, 436, 437, - 438, 439, 440, 441, 442, 443, -1, -1, 446, 447, - 448, -1, 450, 451, 452, 453, -1, 455, 456, 457, - 458, 459, 460, 461, -1, 463, -1, 465, 466, 467, - 468, 469, 470, 471, -1, -1, 474, -1, -1, 477, - 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, -1, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, -1, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + -1, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, -1, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, - -1, 3, 4, 5, -1, -1, 8, 9, -1, -1, - -1, -1, -1, 15, 16, -1, 514, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, -1, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, -1, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 517, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, + 50, 51, 52, 53, 54, -1, 56, 57, -1, 59, + 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, -1, -1, 83, 84, 85, 86, 87, 88, -1, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + -1, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, -1, -1, -1, 174, 175, 176, -1, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, -1, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, -1, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, -1, -1, 224, -1, 226, 227, 228, 229, + 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, -1, + 270, 271, 272, 273, 274, -1, 276, 277, -1, 279, + -1, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, + -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, -1, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, -1, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, -1, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, -1, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, -1, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 517, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, + 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, + 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, -1, + -1, 83, 84, 85, 86, 87, 88, -1, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - -1, 153, 154, 155, 156, 157, -1, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, -1, - -1, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, -1, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, -1, + -1, -1, 174, 175, 176, -1, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, -1, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, -1, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + -1, -1, 224, -1, 226, 227, 228, 229, 230, 231, + -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, -1, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, -1, 299, 300, 301, + 262, 263, 264, 265, 266, 267, 268, -1, 270, 271, + 272, 273, 274, -1, 276, 277, -1, 279, -1, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, - 322, 323, -1, 325, 326, 327, 328, 329, 330, 331, - 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + -1, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, -1, - 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, - -1, 433, -1, 435, 436, 437, 438, 439, 440, 441, - 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, - 452, 453, 454, 455, 456, 457, 458, 459, -1, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 482, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 494, 495, 496, 497, -1, 3, -1, 501, - 502, 503, 8, 505, 506, 507, 508, 509, 510, 15, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, -1, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, -1, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, -1, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, -1, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 3, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 517, -1, -1, 22, 23, + 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, + 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, + 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, + 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, + -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, + 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, + 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, + 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, -1, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, -1, -1, -1, + 174, 175, 176, -1, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + -1, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, -1, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, -1, -1, + 224, -1, 226, 227, 228, 229, 230, 231, -1, -1, + 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, -1, 270, 271, 272, 273, + 274, -1, 276, 277, -1, 279, -1, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, -1, 301, -1, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, -1, -1, -1, -1, 319, 320, 321, -1, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + -1, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, -1, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, -1, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, -1, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, + 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, + 494, 495, 496, 497, 498, 499, 500, -1, 3, 4, + 5, -1, -1, 8, 9, -1, -1, -1, -1, -1, + 15, 16, -1, 517, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, -1, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, -1, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, -1, 153, 154, + 155, 156, 157, 158, -1, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 179, 180, 181, -1, -1, 184, + 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, -1, 211, 212, 213, 214, + 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, -1, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, -1, 300, 301, 302, -1, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, -1, 322, 323, 324, + -1, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, -1, + 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, + -1, 436, -1, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, + 455, 456, 457, 458, 459, 460, 461, 462, -1, 464, + 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, + 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, + 485, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 497, 498, 499, 500, -1, 3, -1, 504, + 505, 506, 8, 508, 509, 510, 511, 512, 513, 15, 16, -1, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, @@ -15563,667 +14357,214 @@ static const yytype_int16 yycheck[] = -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, - -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, - -1, 177, -1, 179, -1, 181, 182, 183, 184, -1, - 186, 187, 188, 189, 190, 191, 192, -1, 194, 195, - 196, 197, -1, 199, 200, 201, 202, 203, 204, 205, - -1, 207, -1, 209, 210, 211, 212, 213, 214, 215, - 216, -1, 218, -1, 220, -1, -1, 223, -1, 225, - 226, 227, 228, 229, 230, -1, -1, 233, -1, 235, - -1, -1, 238, 239, 240, 241, 242, 243, 244, 245, + 156, 157, 158, 159, -1, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, -1, -1, -1, 174, 175, + 176, -1, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, -1, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, -1, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, -1, -1, 224, -1, + 226, 227, 228, 229, 230, 231, -1, -1, 234, -1, + 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, -1, 269, 270, 271, 272, 273, -1, 275, - 276, -1, 278, -1, 280, 281, 282, 283, 284, 285, - -1, 287, 288, -1, -1, 291, 292, 293, -1, -1, - 296, 297, 298, -1, 300, -1, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, -1, -1, - -1, -1, 318, 319, 320, -1, 322, 323, 324, 325, - 326, 327, -1, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, -1, 345, - 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, -1, 359, 360, -1, 362, 363, 364, 365, + 266, 267, 268, -1, 270, 271, 272, 273, 274, -1, + 276, 277, -1, 279, -1, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, -1, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, -1, -1, 381, 382, 383, 384, 385, - 386, 387, 388, 389, -1, -1, 392, 393, 394, 395, - -1, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, -1, -1, 414, 415, - -1, 417, -1, 419, 420, 421, 422, 423, -1, 425, - 426, 427, -1, -1, 430, 431, 432, 433, 434, -1, - 436, 437, 438, 439, 440, 441, 442, 443, -1, -1, - 446, 447, 448, -1, 450, 451, 452, 453, -1, 455, - 456, 457, 458, 459, 460, 461, -1, 463, -1, 465, - 466, 467, 468, 469, 470, 471, -1, -1, 474, -1, - -1, 477, 478, 479, 480, 481, 482, 483, 484, 485, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, -1, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, -1, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, -1, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, -1, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, - 496, 497, -1, -1, -1, 501, 502, 503, -1, 505, - 506, 507, 508, 509, 510, 8, -1, -1, 11, -1, - -1, -1, 15, 16, 17, 18, 19, 20, 21, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 46, 8, -1, -1, 11, -1, -1, - 53, 15, 16, 17, 18, 19, 20, 21, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 36, -1, -1, -1, -1, 80, -1, -1, - -1, -1, 46, 8, -1, -1, 11, -1, -1, 53, - 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 36, -1, -1, -1, -1, 80, -1, -1, -1, - -1, 46, -1, -1, -1, -1, -1, -1, 53, -1, - 8, -1, -1, 11, -1, -1, -1, 15, 16, 17, - 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 80, -1, -1, 36, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 46, 8, - -1, -1, 11, 176, -1, 53, 15, 16, 17, 18, - 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, - 193, -1, -1, -1, -1, 198, -1, 36, -1, -1, - -1, -1, 80, -1, -1, -1, -1, 46, -1, -1, - -1, -1, 176, -1, 53, -1, -1, -1, 221, 222, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 193, - -1, -1, -1, 236, 198, -1, -1, -1, -1, -1, - -1, 80, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 176, -1, -1, -1, -1, -1, 221, 222, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 193, -1, - -1, 274, 236, 198, 277, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 291, -1, - -1, 294, -1, -1, -1, -1, 221, 222, 176, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 274, 236, -1, 277, -1, 193, -1, -1, -1, -1, - 198, -1, -1, -1, -1, -1, -1, 291, -1, -1, - 294, -1, -1, -1, -1, -1, -1, 176, -1, -1, - -1, -1, -1, 221, 222, -1, -1, -1, -1, 274, - -1, -1, 277, -1, 193, -1, -1, -1, 236, 198, - -1, -1, -1, -1, -1, -1, 291, -1, -1, 294, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 221, 222, -1, -1, -1, -1, 391, -1, - -1, -1, -1, -1, -1, -1, 274, 236, -1, 277, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 291, -1, -1, 294, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 391, -1, -1, - -1, -1, -1, -1, -1, 274, -1, -1, 277, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 291, -1, -1, 294, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 391, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 498, -1, -1, 501, 502, - 503, -1, 505, 506, 507, 508, 509, 510, -1, -1, - -1, -1, 515, 391, -1, -1, -1, -1, -1, 8, - -1, -1, 11, -1, -1, -1, 15, 16, 17, 18, - 19, 20, 21, -1, 498, -1, -1, 501, 502, 503, - -1, 505, 506, 507, 508, 509, 510, 36, -1, -1, - -1, 515, 391, -1, -1, -1, -1, 46, -1, -1, - -1, -1, -1, -1, 53, -1, -1, -1, -1, -1, - -1, -1, -1, 498, -1, -1, 501, 502, 503, -1, - 505, 506, 507, 508, 509, 510, -1, -1, -1, -1, - 515, 80, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8, -1, -1, 11, -1, - -1, -1, 15, 16, 17, 18, 19, 20, 21, -1, - 498, -1, -1, 501, 502, 503, -1, 505, 506, 507, - 508, 509, 510, 36, -1, -1, -1, 515, -1, -1, - -1, -1, -1, 46, 8, -1, -1, 11, -1, -1, - 53, 15, 16, 17, 18, 19, 20, 21, -1, 498, - -1, -1, 501, 502, 503, -1, 505, 506, 507, 508, - 509, 510, 36, -1, -1, -1, 515, 80, -1, -1, - -1, -1, 46, 8, -1, -1, 11, 176, -1, 53, - 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, - -1, -1, -1, -1, 193, -1, -1, -1, -1, 198, - -1, 36, -1, -1, -1, -1, 80, -1, -1, -1, - -1, 46, -1, -1, -1, -1, -1, -1, 53, -1, - -1, -1, 221, 222, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 236, -1, -1, - -1, -1, -1, -1, -1, 80, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, - -1, -1, 11, 176, -1, -1, 15, 16, 17, 18, - 19, 20, 21, -1, -1, 274, -1, -1, 277, -1, - 193, -1, -1, -1, -1, 198, -1, 36, -1, -1, - -1, -1, 291, -1, -1, 294, -1, 46, -1, -1, - -1, -1, 176, -1, 53, -1, -1, -1, 221, 222, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 193, - -1, -1, -1, 236, 198, -1, -1, -1, -1, -1, - -1, 80, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 176, -1, -1, -1, -1, -1, 221, 222, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 193, -1, - -1, 274, 236, 198, 277, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 291, -1, - -1, 294, -1, -1, -1, -1, 221, 222, -1, -1, - -1, -1, 391, -1, -1, -1, -1, -1, -1, -1, - 274, 236, -1, 277, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 291, -1, -1, - 294, -1, -1, -1, -1, -1, -1, 176, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 274, - -1, -1, 277, -1, 193, -1, -1, -1, -1, 198, - -1, -1, -1, -1, -1, -1, 291, -1, -1, 294, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 221, 222, -1, -1, -1, -1, 391, -1, - -1, -1, -1, -1, -1, -1, -1, 236, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, - -1, -1, 501, 502, 503, -1, 505, 506, 507, 508, - 509, 510, -1, -1, -1, -1, 515, 391, -1, -1, - -1, -1, -1, -1, -1, 274, -1, 8, 277, -1, - 11, -1, -1, -1, 15, 16, 17, 18, 19, 20, - 21, -1, 291, -1, -1, 294, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 36, 391, -1, -1, -1, - -1, -1, -1, -1, -1, 46, -1, -1, -1, -1, - -1, -1, 53, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 498, -1, -1, 501, 502, - 503, -1, 505, 506, 507, 508, 509, 510, -1, 80, - -1, -1, 515, -1, -1, -1, -1, -1, -1, 8, - -1, -1, 11, -1, -1, -1, 15, 16, 17, 18, - 19, 20, 21, -1, 498, -1, -1, 501, 502, 503, - -1, 505, 506, 507, 508, 509, 510, 36, -1, -1, - -1, 515, 391, -1, -1, -1, -1, 46, -1, -1, - -1, -1, -1, -1, 53, -1, -1, -1, -1, -1, - -1, -1, -1, 498, -1, -1, 501, 502, 503, -1, - 505, 506, 507, 508, 509, 510, -1, -1, 513, -1, - -1, 80, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 176, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 193, -1, -1, -1, -1, 198, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 221, 222, -1, -1, -1, -1, -1, -1, -1, 498, - -1, -1, 501, 502, 503, 236, 505, 506, 507, 508, - 509, 510, -1, -1, 513, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 176, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 274, 193, -1, 277, -1, -1, 198, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 291, -1, -1, 294, -1, -1, -1, -1, -1, -1, - -1, -1, 221, 222, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 236, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 274, -1, -1, 277, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 291, -1, -1, 294, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 391, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 391, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, - 501, 502, 503, -1, 505, 506, 507, 508, 509, 510, - -1, -1, 513, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3, -1, -1, 498, - -1, -1, 501, 502, 503, -1, 505, 506, 507, 508, - 509, 510, -1, -1, 513, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, - 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, - 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, - 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, - 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, - 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, - 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, - 497, 3, -1, -1, -1, -1, -1, -1, -1, -1, - 507, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, - 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, - 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, - 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, - 72, 73, -1, 75, 76, 77, 78, 79, -1, -1, - -1, 83, 84, 85, 86, 87, 88, -1, 90, 91, - 92, -1, 94, 95, 96, 97, 98, 99, -1, -1, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, - 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, - -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, - 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, -1, 160, -1, - 162, 163, 164, 165, -1, 167, -1, 169, -1, -1, - -1, 173, 174, 175, -1, 177, -1, 179, -1, 181, - 182, 183, 184, -1, 186, 187, 188, 189, 190, 191, - 192, -1, 194, 195, 196, 197, -1, 199, 200, 201, - 202, 203, 204, 205, -1, 207, -1, 209, 210, 211, - 212, 213, 214, 215, 216, -1, 218, -1, 220, -1, - -1, 223, -1, 225, 226, 227, 228, 229, 230, -1, - -1, 233, -1, 235, -1, -1, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, -1, 269, 270, 271, - 272, 273, -1, 275, 276, -1, 278, -1, 280, 281, - 282, 283, 284, 285, -1, 287, 288, -1, -1, 291, - 292, 293, -1, -1, 296, 297, 298, -1, 300, -1, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, -1, -1, -1, -1, 318, 319, 320, -1, - 322, 323, 324, 325, 326, 327, -1, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, -1, 345, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, -1, 359, 360, -1, - 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, -1, -1, 381, - 382, 383, 384, 385, 386, 387, 388, 389, -1, -1, - 392, 393, 394, 395, -1, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - -1, -1, 414, 415, -1, 417, -1, 419, 420, 421, - 422, 423, -1, 425, 426, 427, -1, -1, 430, 431, - 432, 433, 434, -1, 436, 437, 438, 439, 440, 441, - 442, 443, -1, -1, 446, 447, 448, -1, 450, 451, - 452, 453, -1, 455, 456, 457, 458, 459, 460, 461, - -1, 463, -1, 465, 466, 467, 468, 469, 470, 471, - -1, -1, 474, -1, -1, 477, 478, 479, 480, 481, - 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 494, 495, 496, 497, 3, -1, -1, -1, - -1, -1, -1, -1, -1, 507, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, - 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 43, 44, -1, 46, - 47, 48, -1, 50, 51, 52, 53, 54, -1, 56, - 57, -1, 59, 60, 61, 62, 63, 64, -1, -1, - 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, - 77, 78, 79, -1, -1, -1, 83, 84, 85, 86, - 87, 88, -1, 90, 91, 92, -1, 94, 95, 96, - 97, 98, 99, -1, -1, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, - -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, - 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, - -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, -1, 160, -1, 162, 163, 164, 165, -1, - 167, -1, 169, -1, -1, -1, 173, 174, 175, -1, - 177, -1, 179, -1, 181, 182, 183, 184, -1, 186, - 187, 188, 189, 190, 191, 192, -1, 194, 195, 196, - 197, -1, 199, 200, 201, 202, 203, 204, 205, -1, - 207, -1, 209, 210, 211, 212, 213, 214, 215, 216, - -1, 218, -1, 220, -1, -1, 223, -1, 225, 226, - 227, 228, 229, 230, -1, -1, 233, -1, 235, -1, - -1, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, -1, 269, 270, 271, 272, 273, -1, 275, 276, - -1, 278, -1, 280, 281, 282, 283, 284, 285, -1, - 287, 288, -1, -1, 291, 292, 293, -1, -1, 296, - 297, 298, -1, 300, -1, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, -1, -1, -1, - -1, 318, 319, 320, -1, 322, 323, 324, 325, 326, - 327, -1, 329, 330, 331, 332, 333, 334, -1, 336, - 337, 338, 339, 340, 341, 342, 343, -1, 345, 346, - 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, - 357, -1, 359, 360, -1, 362, 363, 364, 365, 366, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, -1, -1, 381, 382, 383, 384, 385, 386, - 387, 388, 389, -1, -1, 392, 393, 394, 395, -1, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, -1, -1, 414, 415, -1, - 417, -1, 419, 420, 421, 422, 423, -1, 425, 426, - 427, -1, -1, 430, 431, 432, 433, 434, -1, 436, - 437, 438, 439, 440, 441, 442, 443, -1, -1, 446, - 447, 448, -1, 450, 451, 452, 453, -1, 455, 456, - 457, 458, 459, 460, 461, -1, 463, -1, 465, 466, - 467, 468, 469, 470, 471, -1, -1, 474, -1, -1, - 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, - 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, - 497, 3, 4, 5, -1, -1, -1, 9, -1, -1, - 507, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, - 32, 33, -1, -1, -1, 37, -1, -1, -1, -1, - 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, - 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, - 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, - -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, - 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, - -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, - 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, - 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, - 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, - 182, 183, 184, -1, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, -1, 199, 200, 201, - 202, 203, 204, 205, -1, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, -1, 218, -1, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, -1, - -1, 233, 234, 235, 236, -1, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, -1, 275, 276, 277, 278, -1, 280, 281, - 282, 283, 284, 285, -1, 287, 288, 289, -1, 291, - 292, 293, -1, -1, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, -1, -1, -1, -1, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, -1, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, -1, 345, 346, 347, 348, 349, 350, 351, - 352, 353, 354, 355, 356, 357, -1, 359, 360, 361, - 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, -1, 380, 381, - 382, 383, 384, 385, 386, 387, 388, 389, -1, 391, - 392, 393, 394, 395, -1, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - -1, -1, 414, 415, -1, 417, 418, 419, 420, 421, - 422, 423, -1, 425, 426, 427, -1, -1, 430, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, -1, -1, 446, 447, 448, -1, 450, 451, - 452, 453, -1, 455, 456, 457, 458, 459, 460, 461, - -1, 463, 464, 465, 466, 467, 468, 469, 470, 471, - -1, -1, 474, -1, -1, 477, 478, 479, 480, 481, - 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 494, 495, 496, 497, -1, -1, 8, -1, - -1, 11, -1, 505, 506, 15, 16, 17, 18, 19, + 496, 497, 498, 499, 500, -1, -1, -1, 504, 505, + 506, -1, 508, 509, 510, 511, 512, 513, 8, -1, + -1, 11, -1, -1, -1, 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, - -1, 41, -1, -1, -1, -1, 46, 8, -1, -1, + -1, -1, -1, -1, -1, -1, 46, 8, -1, -1, 11, -1, -1, 53, 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, - 80, -1, -1, -1, -1, 46, 8, -1, -1, 11, + 80, 24, -1, -1, -1, 46, 8, -1, -1, 11, -1, -1, 53, 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, 80, - -1, -1, -1, -1, 46, -1, 126, -1, -1, -1, - -1, 53, -1, -1, 8, -1, -1, 11, -1, -1, - -1, 15, 16, 17, 18, 19, 20, 21, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 80, -1, - -1, -1, 36, -1, -1, -1, 40, -1, -1, -1, - -1, -1, 46, -1, 8, -1, 176, 11, -1, 53, - -1, 15, 16, 17, 18, 19, 20, 21, -1, -1, - -1, -1, -1, 193, -1, -1, -1, -1, 198, -1, - -1, -1, 36, -1, -1, 166, 80, -1, -1, -1, - 171, -1, 46, -1, -1, 176, -1, -1, -1, 53, - -1, 221, 222, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 193, -1, -1, -1, 236, 198, -1, -1, - -1, -1, -1, 165, -1, -1, 80, -1, -1, -1, - -1, -1, -1, -1, 176, -1, -1, -1, -1, -1, - 221, 222, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 193, -1, -1, 274, 236, 198, 277, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 291, -1, -1, 294, -1, -1, -1, -1, 221, - 222, -1, 176, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 274, 236, -1, 277, -1, -1, 193, - -1, -1, -1, -1, 198, -1, -1, -1, -1, -1, - 291, -1, -1, 294, -1, -1, -1, -1, -1, -1, - -1, -1, 176, -1, -1, -1, -1, 221, 222, -1, - -1, -1, 274, -1, -1, 277, -1, -1, -1, 193, - -1, -1, 236, -1, 198, -1, -1, -1, -1, 291, - -1, -1, 294, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 221, 222, -1, - -1, 391, -1, -1, -1, -1, -1, -1, -1, -1, - 274, 323, 236, 277, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 291, -1, -1, - 294, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 391, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 274, -1, -1, 277, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 454, -1, -1, 291, -1, -1, - 294, -1, -1, -1, -1, -1, -1, -1, -1, 391, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 317, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, - -1, 501, 502, 503, -1, 505, 506, 507, 508, 509, - 510, -1, -1, -1, -1, -1, -1, 391, -1, -1, - -1, -1, 8, -1, -1, 11, -1, -1, -1, 15, - 16, 17, 18, 19, 20, 21, -1, 498, -1, -1, - 501, 502, 503, -1, 505, 506, 507, 508, 509, 510, - 36, -1, -1, -1, 40, -1, -1, 391, -1, -1, - 46, -1, -1, -1, -1, -1, -1, 53, -1, -1, - -1, -1, -1, -1, -1, -1, 498, -1, -1, 501, - 502, 503, -1, 505, 506, 507, 508, 509, 510, -1, - -1, -1, -1, -1, 80, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, - -1, -1, 11, -1, -1, -1, 15, 16, 17, 18, - 19, 20, 21, -1, 498, -1, -1, 501, 502, 503, - -1, 505, 506, 507, 508, 509, 510, 36, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 46, -1, -1, - -1, -1, -1, -1, 53, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 498, -1, -1, 501, 502, 503, - -1, 505, 506, 507, 508, 509, 510, -1, -1, -1, - -1, 80, -1, -1, -1, -1, 8, -1, -1, 11, - 176, -1, -1, 15, 16, 17, 18, 19, 20, 21, - -1, -1, -1, -1, -1, -1, -1, 193, -1, -1, - -1, -1, 198, -1, 36, -1, -1, -1, 40, -1, -1, -1, -1, -1, 46, -1, -1, -1, -1, -1, - -1, 53, -1, -1, -1, 221, 222, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 236, -1, -1, -1, -1, -1, -1, -1, 80, -1, + -1, 53, -1, 8, -1, -1, 11, -1, 81, -1, + 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, + -1, -1, -1, -1, 97, -1, -1, -1, 80, -1, + -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 46, 8, -1, -1, 11, -1, 177, 53, 15, + 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, + -1, -1, -1, -1, 194, -1, -1, -1, -1, 199, + 36, -1, -1, 146, -1, 80, -1, -1, -1, -1, + 46, -1, -1, 156, -1, -1, 177, 53, -1, -1, + -1, -1, 222, 223, -1, -1, 169, -1, -1, -1, + -1, 174, -1, 194, -1, -1, -1, 237, 199, -1, + -1, -1, -1, -1, 80, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 177, -1, -1, -1, -1, + 203, 222, 223, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 194, -1, -1, 275, 237, 199, 278, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 171, 8, -1, -1, 11, 176, -1, -1, - 15, 16, 17, 18, 19, 20, 21, -1, 274, -1, - -1, 277, -1, -1, 193, -1, -1, -1, -1, 198, - -1, 36, -1, -1, -1, 291, -1, -1, 294, -1, - -1, 46, -1, -1, -1, -1, -1, -1, 53, -1, - -1, -1, 221, 222, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 236, -1, -1, - -1, -1, -1, -1, -1, 80, -1, -1, -1, -1, - -1, -1, -1, -1, 176, -1, -1, -1, -1, -1, + -1, -1, 292, -1, -1, 295, -1, -1, -1, -1, + 222, 223, 177, 246, -1, -1, -1, 250, -1, -1, + -1, -1, -1, -1, 275, 237, -1, 278, -1, 194, + -1, -1, -1, -1, 199, -1, -1, -1, -1, -1, + -1, 292, -1, -1, 295, -1, -1, -1, -1, -1, + -1, 177, -1, -1, -1, -1, -1, 222, 223, -1, + -1, -1, -1, 275, -1, -1, 278, -1, 194, -1, + -1, -1, 237, 199, -1, -1, -1, -1, -1, -1, + 292, 314, -1, 295, -1, -1, -1, 320, -1, -1, + -1, -1, -1, -1, -1, -1, 222, 223, -1, -1, + -1, -1, 335, -1, 394, -1, -1, -1, -1, -1, + 275, 237, -1, 278, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 292, -1, -1, + 295, -1, -1, -1, -1, -1, -1, 370, -1, -1, + 373, -1, -1, 394, -1, -1, -1, -1, -1, 275, + -1, 384, 278, -1, 387, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 292, -1, -1, 295, + -1, -1, 405, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 394, -1, -1, -1, 419, -1, -1, -1, + -1, -1, 425, 426, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 436, -1, -1, -1, -1, -1, 442, + -1, 501, -1, -1, 504, 505, 506, -1, 508, 509, + 510, 511, 512, 513, -1, -1, -1, -1, 518, 394, + -1, -1, -1, -1, -1, 8, 469, -1, 11, -1, + -1, -1, 15, 16, 17, 18, 19, 20, 21, -1, + 501, -1, -1, 504, 505, 506, -1, 508, 509, 510, + 511, 512, 513, 36, -1, -1, -1, 518, 394, -1, + -1, -1, -1, 46, -1, -1, -1, -1, -1, -1, + 53, -1, -1, -1, -1, -1, -1, -1, -1, 501, + -1, -1, 504, 505, 506, -1, 508, 509, 510, 511, + 512, 513, -1, -1, -1, -1, 518, 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 193, -1, -1, -1, 274, 198, -1, 277, -1, + -1, 8, -1, -1, 11, -1, -1, -1, 15, 16, + 17, 18, 19, 20, 21, -1, 501, -1, -1, 504, + 505, 506, -1, 508, 509, 510, 511, 512, 513, 36, + -1, -1, -1, 518, -1, -1, -1, -1, -1, 46, + 8, -1, -1, 11, -1, -1, 53, 15, 16, 17, + 18, 19, 20, 21, -1, 501, -1, -1, 504, 505, + 506, -1, 508, 509, 510, 511, 512, 513, 36, -1, + -1, -1, 518, 80, -1, -1, -1, -1, 46, 8, + -1, -1, 11, -1, 177, 53, 15, 16, 17, 18, + 19, 20, 21, -1, -1, -1, -1, -1, -1, -1, + -1, 194, -1, -1, -1, -1, 199, 36, -1, -1, + -1, -1, 80, -1, -1, -1, -1, 46, -1, -1, + -1, -1, -1, -1, 53, -1, -1, -1, -1, 222, + 223, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 237, -1, -1, -1, -1, -1, + -1, 80, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 8, -1, -1, 11, -1, + 177, -1, 15, 16, 17, 18, 19, 20, 21, -1, + -1, -1, 275, -1, -1, 278, -1, 194, -1, -1, + -1, -1, 199, 36, -1, -1, -1, -1, -1, 292, + -1, -1, 295, 46, -1, -1, -1, -1, -1, 177, + 53, -1, -1, -1, -1, 222, 223, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 194, -1, -1, -1, + 237, 199, -1, -1, -1, -1, -1, 80, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 177, -1, + -1, -1, -1, -1, 222, 223, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 194, -1, -1, 275, 237, + 199, 278, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 292, -1, -1, 295, -1, + -1, -1, -1, 222, 223, -1, -1, -1, -1, -1, + -1, 394, -1, -1, -1, -1, -1, 275, 237, -1, + 278, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 292, -1, -1, 295, -1, -1, + -1, -1, -1, -1, 177, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 275, -1, -1, 278, + -1, 194, -1, -1, -1, -1, 199, -1, -1, -1, + -1, -1, -1, 292, -1, -1, 295, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 222, + 223, -1, -1, -1, -1, -1, -1, 394, -1, -1, + -1, -1, -1, -1, 237, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 501, -1, + -1, 504, 505, 506, -1, 508, 509, 510, 511, 512, + 513, -1, -1, -1, -1, 518, 394, -1, -1, -1, + -1, -1, 275, -1, -1, 278, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 292, + -1, -1, 295, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 394, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 291, -1, -1, 294, -1, -1, -1, 221, - 222, -1, -1, -1, -1, 391, -1, -1, 8, -1, - -1, 11, -1, -1, 236, 15, 16, 17, 18, 19, - 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 166, -1, -1, -1, -1, 36, -1, -1, -1, - -1, 176, -1, -1, -1, -1, 46, -1, -1, -1, - -1, -1, 274, 53, -1, 277, -1, -1, 193, -1, - -1, -1, -1, 198, -1, -1, -1, -1, -1, 291, - -1, -1, 294, -1, -1, -1, -1, -1, -1, -1, - 80, -1, -1, -1, -1, -1, 221, 222, -1, -1, - -1, -1, 391, -1, -1, -1, -1, -1, -1, -1, - -1, 236, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 498, -1, -1, 501, 502, 503, -1, 505, - 506, 507, 508, 509, 510, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 274, - -1, -1, 277, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 291, -1, -1, 294, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 391, - -1, -1, -1, -1, -1, -1, 176, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 193, -1, -1, -1, -1, 198, 498, - -1, -1, 501, 502, 503, -1, 505, 506, 507, 508, - 509, 510, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 221, 222, -1, -1, -1, -1, -1, -1, -1, - 8, -1, -1, 11, -1, -1, 236, 15, 16, 17, - 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 391, -1, 36, -1, - -1, -1, 40, -1, -1, -1, -1, -1, 46, -1, - -1, -1, -1, -1, 274, 53, 498, 277, -1, 501, - 502, 503, -1, 505, 506, 507, 508, 509, 510, -1, - -1, 291, -1, -1, 294, -1, -1, -1, -1, -1, - -1, -1, 80, -1, 8, -1, -1, 11, -1, -1, + -1, -1, -1, -1, 501, -1, -1, 504, 505, 506, + -1, 508, 509, 510, 511, 512, 513, -1, -1, -1, + -1, 518, -1, -1, -1, -1, -1, -1, 8, -1, + -1, 11, -1, -1, -1, 15, 16, 17, 18, 19, + 20, 21, -1, 501, -1, -1, 504, 505, 506, -1, + 508, 509, 510, 511, 512, 513, 36, -1, -1, -1, + 518, 394, -1, -1, -1, -1, 46, 8, -1, -1, + 11, -1, -1, 53, 15, 16, 17, 18, 19, 20, + 21, -1, 501, -1, -1, 504, 505, 506, -1, 508, + 509, 510, 511, 512, 513, 36, -1, -1, -1, 518, + 80, -1, -1, -1, -1, 46, -1, -1, -1, -1, + -1, -1, 53, -1, 8, -1, -1, 11, -1, -1, -1, 15, 16, 17, 18, 19, 20, 21, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 80, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, -1, -1, -1, -1, -1, -1, 53, + -1, -1, -1, -1, -1, -1, -1, -1, 501, -1, + -1, 504, 505, 506, -1, 508, 509, 510, 511, 512, + 513, -1, -1, 516, -1, -1, 80, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 177, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 498, -1, -1, 501, 502, 503, -1, - 505, 506, 507, 508, 509, 510, 80, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 391, -1, 8, -1, -1, 11, -1, 176, -1, - 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, - -1, -1, -1, -1, -1, 193, -1, -1, -1, -1, - 198, 36, -1, -1, 424, -1, -1, -1, -1, -1, - -1, 46, -1, -1, -1, -1, -1, -1, 53, -1, - -1, -1, -1, 221, 222, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 236, -1, - -1, -1, -1, -1, -1, 80, -1, -1, -1, -1, - -1, -1, 176, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 193, - -1, -1, -1, -1, 198, -1, 274, -1, 498, 277, - -1, 501, 502, 503, -1, 505, 506, 507, 508, 509, - 510, -1, -1, 291, -1, -1, 294, 221, 222, -1, - -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, - -1, -1, 236, 15, 16, 17, 18, 19, 20, 21, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, - -1, 176, -1, -1, 46, -1, -1, -1, -1, -1, - 274, 53, -1, 277, -1, -1, -1, -1, 193, -1, - -1, -1, -1, 198, -1, -1, -1, 291, -1, -1, - 294, -1, -1, -1, -1, -1, -1, -1, 80, -1, - -1, -1, -1, -1, -1, -1, 221, 222, -1, -1, - -1, -1, -1, 391, -1, -1, -1, -1, -1, -1, - -1, 236, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 8, -1, -1, 11, -1, -1, -1, 15, - 16, -1, -1, 19, 20, 21, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 274, - 36, -1, 277, -1, -1, -1, -1, -1, -1, -1, - 46, -1, -1, -1, -1, -1, 291, 53, -1, 294, - -1, -1, -1, -1, -1, -1, -1, 391, -1, -1, - -1, -1, -1, -1, 176, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 80, -1, -1, -1, -1, -1, - -1, 193, -1, -1, -1, -1, 198, -1, -1, -1, - 498, -1, -1, 501, 502, 503, -1, 505, 506, 507, - 508, 509, 510, -1, -1, 8, -1, -1, 11, 221, - 222, -1, 15, 16, -1, -1, 19, 20, 21, -1, - -1, -1, -1, -1, 236, -1, -1, -1, -1, -1, - -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 46, -1, 8, 391, -1, 11, -1, - 53, -1, 15, 16, -1, -1, 19, 20, 21, -1, - -1, -1, 274, -1, 498, 277, -1, 501, 502, 503, - 176, 505, 506, 507, 508, 509, 510, 80, -1, 291, - -1, -1, 294, 46, -1, -1, -1, 193, -1, -1, - 53, -1, 198, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 221, 222, 80, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 236, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 194, -1, -1, -1, -1, 199, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 498, -1, -1, 501, 502, 503, -1, - 505, 506, 507, 508, 509, 510, -1, -1, 274, -1, - -1, 277, -1, 176, -1, -1, -1, -1, -1, 391, - -1, -1, -1, -1, -1, 291, -1, -1, 294, -1, - 193, -1, -1, -1, -1, 198, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 177, -1, -1, -1, + -1, -1, 222, 223, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 194, -1, -1, -1, 237, 199, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 176, -1, -1, -1, -1, 221, 222, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 193, -1, -1, 236, -1, 198, -1, -1, -1, -1, + -1, 222, 223, 177, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 275, 237, -1, 278, -1, + 194, -1, -1, -1, -1, 199, -1, -1, -1, -1, + -1, -1, 292, -1, -1, 295, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 222, 223, + -1, -1, -1, -1, 275, -1, -1, 278, -1, -1, + -1, -1, -1, 237, -1, -1, -1, -1, -1, -1, + -1, 292, -1, -1, 295, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 221, 222, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 274, -1, 236, 277, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 391, 498, -1, 291, 501, - 502, 503, -1, 505, 506, 507, 508, 509, 510, -1, + -1, 275, -1, -1, 278, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 292, -1, + -1, 295, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 394, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 274, -1, -1, 277, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 291, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 394, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 391, -1, - -1, -1, 498, -1, -1, 501, 502, 503, -1, 505, - 506, 507, 508, 509, 510, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 391, -1, + 394, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 501, -1, -1, 504, 505, 506, -1, 508, 509, + 510, 511, 512, 513, -1, -1, 516, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 501, -1, -1, 504, 505, 506, -1, 508, 509, 510, + 511, 512, 513, -1, -1, 516, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 498, -1, -1, 501, 502, - 503, -1, 505, 506, 507, 508, 509, 510, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, - -1, 5, -1, -1, -1, 498, -1, -1, 501, 502, - 503, -1, 505, 506, 507, 508, 509, 510, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, - 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, - 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, + -1, -1, -1, -1, 3, -1, -1, 501, -1, -1, + 504, 505, 506, -1, 508, 509, 510, 511, 512, 513, + -1, -1, 516, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, @@ -16270,106 +14611,497 @@ static const yytype_int16 yycheck[] = 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, + 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, + -1, 510, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, + 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 43, 44, -1, 46, 47, 48, -1, 50, + 51, 52, 53, 54, -1, 56, 57, -1, 59, 60, + 61, 62, 63, 64, -1, -1, 67, 68, 69, 70, + 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, + -1, -1, 83, 84, 85, 86, 87, 88, -1, 90, + 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, + -1, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, -1, + 161, -1, 163, 164, 165, 166, -1, 168, -1, 170, + -1, -1, -1, 174, 175, 176, -1, 178, -1, 180, + -1, 182, 183, 184, 185, -1, 187, 188, 189, 190, + 191, 192, 193, -1, 195, 196, 197, 198, -1, 200, + 201, 202, 203, 204, 205, 206, -1, 208, -1, 210, + 211, 212, 213, 214, 215, 216, 217, -1, 219, -1, + 221, -1, -1, 224, -1, 226, 227, 228, 229, 230, + 231, -1, -1, 234, -1, 236, -1, -1, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, -1, 270, + 271, 272, 273, 274, -1, 276, 277, -1, 279, -1, + 281, 282, 283, 284, 285, 286, -1, 288, 289, -1, + -1, 292, 293, 294, -1, -1, 297, 298, 299, -1, + 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, -1, -1, -1, -1, 319, 320, + 321, -1, 323, 324, 325, 326, 327, 328, -1, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + -1, 362, 363, -1, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, -1, -1, 384, 385, 386, 387, 388, 389, 390, + 391, 392, -1, -1, 395, 396, 397, 398, -1, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, -1, -1, 417, 418, -1, 420, + -1, 422, 423, 424, 425, 426, -1, 428, 429, 430, + -1, -1, 433, 434, 435, 436, 437, -1, 439, 440, + 441, 442, 443, 444, 445, 446, -1, -1, 449, 450, + 451, -1, 453, 454, 455, 456, -1, 458, 459, 460, + 461, 462, 463, 464, -1, 466, -1, 468, 469, 470, + 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, + 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, + 3, -1, -1, -1, -1, -1, -1, -1, -1, 510, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, + 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, + 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, + 53, 54, -1, 56, 57, -1, 59, 60, 61, 62, + 63, 64, -1, -1, 67, 68, 69, 70, 71, 72, + 73, -1, 75, 76, 77, 78, 79, -1, -1, -1, + 83, 84, 85, 86, 87, 88, -1, 90, 91, 92, + -1, 94, 95, 96, 97, 98, 99, -1, -1, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, -1, 161, -1, + 163, 164, 165, 166, -1, 168, -1, 170, -1, -1, + -1, 174, 175, 176, -1, 178, -1, 180, -1, 182, + 183, 184, 185, -1, 187, 188, 189, 190, 191, 192, + 193, -1, 195, 196, 197, 198, -1, 200, 201, 202, + 203, 204, 205, 206, -1, 208, -1, 210, 211, 212, + 213, 214, 215, 216, 217, -1, 219, -1, 221, -1, + -1, 224, -1, 226, 227, 228, 229, 230, 231, -1, + -1, 234, -1, 236, -1, -1, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, -1, 270, 271, 272, + 273, 274, -1, 276, 277, -1, 279, -1, 281, 282, + 283, 284, 285, 286, -1, 288, 289, -1, -1, 292, + 293, 294, -1, -1, 297, 298, 299, -1, 301, -1, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, -1, -1, -1, -1, 319, 320, 321, -1, + 323, 324, 325, 326, 327, 328, -1, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, -1, 362, + 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, -1, + -1, 384, 385, 386, 387, 388, 389, 390, 391, 392, + -1, -1, 395, 396, 397, 398, -1, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, -1, -1, 417, 418, -1, 420, -1, 422, + 423, 424, 425, 426, -1, 428, 429, 430, -1, -1, + 433, 434, 435, 436, 437, -1, 439, 440, 441, 442, + 443, 444, 445, 446, -1, -1, 449, 450, 451, -1, + 453, 454, 455, 456, -1, 458, 459, 460, 461, 462, + 463, 464, -1, 466, -1, 468, 469, 470, 471, 472, + 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, + 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 498, 499, 500, 3, 4, + 5, -1, -1, -1, 9, -1, -1, 510, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, + 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, + -1, -1, 37, -1, -1, -1, -1, 42, 43, 44, + -1, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, + -1, -1, 67, 68, 69, 70, 71, 72, 73, -1, + 75, 76, 77, 78, 79, -1, 81, -1, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, + 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, -1, 118, -1, 120, 121, 122, 123, 124, + 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, + 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, + 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, 160, 161, -1, 163, 164, + 165, 166, -1, 168, -1, 170, 171, -1, 173, 174, + 175, 176, 177, 178, -1, 180, -1, 182, 183, 184, + 185, -1, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, -1, 200, 201, 202, 203, 204, + 205, 206, -1, 208, 209, 210, 211, 212, 213, 214, + 215, 216, 217, -1, 219, -1, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, -1, -1, 234, + 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + -1, 276, 277, 278, 279, -1, 281, 282, 283, 284, + 285, 286, -1, 288, 289, 290, -1, 292, 293, 294, + -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + -1, -1, -1, -1, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, -1, 330, 331, 332, 333, 334, + 335, -1, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, -1, 362, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, -1, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, -1, 394, + 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + -1, -1, 417, 418, -1, 420, 421, 422, 423, 424, + 425, 426, -1, 428, 429, 430, -1, -1, 433, 434, + 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, -1, -1, 449, 450, 451, -1, 453, 454, + 455, 456, -1, 458, 459, 460, 461, 462, 463, 464, + -1, 466, 467, 468, 469, 470, 471, 472, 473, 474, + -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, + 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 498, 499, 500, -1, -1, 8, -1, + -1, 11, -1, 508, 509, 15, 16, 17, 18, 19, + 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, + -1, 41, -1, -1, -1, -1, 46, 8, -1, -1, + 11, -1, -1, 53, 15, 16, 17, 18, 19, 20, + 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, + 80, -1, -1, -1, -1, 46, 8, -1, -1, 11, + -1, -1, 53, 15, 16, 17, 18, 19, 20, 21, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 36, -1, -1, -1, -1, 80, + -1, -1, -1, -1, 46, -1, 126, -1, -1, -1, + -1, 53, -1, 8, -1, -1, 11, -1, -1, -1, + 15, 16, 17, 18, 19, 20, 21, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 80, -1, + -1, 36, -1, -1, -1, 40, -1, -1, -1, -1, + -1, 46, -1, -1, -1, -1, -1, 177, 53, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 194, -1, -1, -1, -1, 199, + -1, -1, -1, -1, -1, 80, 167, -1, -1, -1, + -1, 172, -1, -1, -1, -1, 177, -1, -1, -1, + -1, -1, 222, 223, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 194, -1, -1, -1, 237, 199, -1, + -1, -1, -1, -1, 166, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 177, -1, -1, -1, -1, + -1, 222, 223, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 194, -1, -1, 275, 237, 199, 278, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 292, -1, -1, 295, -1, -1, -1, -1, + 222, 223, 177, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 275, 237, -1, 278, -1, 194, + -1, -1, -1, -1, 199, -1, -1, -1, -1, -1, + -1, 292, -1, -1, 295, -1, -1, -1, -1, 68, + 69, -1, -1, -1, -1, -1, -1, 222, 223, -1, + -1, -1, -1, 275, -1, -1, 278, -1, -1, -1, + -1, -1, 237, -1, -1, -1, -1, -1, -1, -1, + 292, -1, -1, 295, -1, -1, -1, -1, -1, -1, + 109, 110, -1, -1, 113, 114, -1, -1, -1, -1, + -1, -1, -1, -1, 394, -1, -1, -1, -1, -1, + 275, -1, 324, 278, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 292, -1, -1, + 295, -1, -1, -1, -1, -1, -1, -1, 8, -1, + -1, 11, -1, 394, -1, 15, 16, 17, 18, 19, + 20, 21, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 36, 457, -1, -1, + 189, 190, -1, -1, -1, -1, 46, -1, -1, -1, + -1, -1, 394, 53, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 80, 501, -1, -1, 504, 505, 506, -1, 508, 509, + 510, 511, 512, 513, -1, -1, -1, -1, -1, 394, + -1, -1, -1, -1, 253, 254, 255, 256, 257, 258, + 259, 260, -1, -1, 263, 264, -1, -1, -1, -1, + 501, -1, -1, 504, 505, 506, -1, 508, 509, 510, + 511, 512, 513, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 68, 69, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 501, + -1, -1, 504, 505, 506, -1, 508, 509, 510, 511, + 512, 513, -1, -1, -1, -1, -1, 177, -1, -1, + -1, -1, -1, -1, -1, -1, 109, 110, 337, 338, + 113, 114, -1, -1, 194, -1, -1, -1, -1, 199, + -1, -1, -1, -1, -1, -1, 501, -1, -1, 504, + 505, 506, -1, 508, 509, 510, 511, 512, 513, -1, + -1, -1, 222, 223, -1, -1, -1, -1, -1, 378, + 379, -1, 8, -1, -1, 11, -1, 237, -1, 15, + 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 40, -1, 189, 190, -1, -1, + 46, -1, -1, -1, -1, 275, -1, 53, 278, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 292, -1, -1, 295, -1, -1, -1, -1, + 8, -1, -1, 11, 80, -1, -1, 15, 16, 17, + 18, 19, 20, 21, -1, -1, -1, -1, 318, -1, + -1, -1, -1, -1, 473, 474, -1, -1, 36, -1, + 253, 254, 255, 256, 257, 258, 259, 260, 46, -1, + 263, 264, -1, -1, -1, 53, -1, -1, 497, 498, + -1, -1, -1, -1, 8, -1, -1, 11, -1, -1, + -1, 15, 16, 17, 18, 19, 20, 21, 517, -1, + -1, -1, 80, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 36, -1, -1, -1, 40, -1, -1, -1, + -1, -1, 46, -1, 394, -1, -1, -1, -1, 53, + -1, 177, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 337, 338, -1, -1, 194, -1, + -1, 8, -1, 199, 11, -1, 80, -1, 15, 16, + 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 222, 223, -1, 36, + -1, -1, -1, -1, -1, 378, 379, -1, -1, 46, + -1, 237, -1, -1, 172, -1, 53, -1, -1, 177, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 194, -1, -1, -1, + -1, 199, -1, 80, -1, -1, -1, -1, -1, 275, + -1, 501, 278, -1, 504, 505, 506, -1, 508, 509, + 510, 511, 512, 513, 222, 223, 292, -1, -1, 295, + -1, -1, -1, 177, -1, -1, -1, -1, -1, 237, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 194, -1, -1, -1, -1, 199, -1, -1, -1, -1, + 473, 474, -1, 8, -1, -1, 11, -1, -1, -1, + 15, 16, 17, 18, 19, 20, 21, 275, 222, 223, + 278, -1, -1, -1, 497, 498, -1, -1, -1, -1, + 167, 36, -1, 237, 292, -1, -1, 295, -1, -1, + 177, 46, -1, -1, -1, -1, -1, -1, 53, -1, + -1, -1, -1, -1, -1, -1, -1, 194, -1, -1, + -1, -1, 199, -1, -1, -1, -1, -1, 394, -1, + 8, 275, -1, 11, 278, 80, -1, 15, 16, 17, + 18, 19, 20, 21, -1, 222, 223, -1, 292, -1, + -1, 295, -1, -1, -1, -1, -1, -1, 36, -1, + 237, -1, 40, -1, -1, -1, -1, -1, 46, -1, + -1, -1, -1, -1, -1, 53, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 394, -1, 275, -1, + -1, 278, 80, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 292, -1, -1, 295, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 177, -1, -1, 501, -1, -1, 504, 505, + 506, -1, 508, 509, 510, 511, 512, 513, -1, 194, + 394, -1, 8, -1, 199, 11, -1, -1, -1, 15, + 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 222, 223, -1, + 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 46, -1, 237, -1, -1, -1, -1, 53, -1, 177, + -1, -1, -1, 501, -1, -1, 504, 505, 506, -1, + 508, 509, 510, 511, 512, 513, 194, 394, -1, -1, + -1, 199, -1, -1, 80, -1, -1, -1, -1, -1, + 275, -1, -1, 278, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 222, 223, -1, 292, -1, -1, + 295, -1, -1, -1, -1, -1, -1, 501, -1, 237, + 504, 505, 506, -1, 508, 509, 510, 511, 512, 513, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 275, -1, -1, + 278, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 292, -1, -1, 295, -1, -1, + -1, 177, -1, -1, 501, -1, -1, 504, 505, 506, + -1, 508, 509, 510, 511, 512, 513, -1, 194, -1, + -1, -1, -1, 199, -1, -1, -1, -1, -1, 394, + -1, 8, -1, -1, 11, -1, -1, -1, 15, 16, + 17, 18, 19, 20, 21, -1, 222, 223, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, + -1, 237, 427, -1, -1, -1, -1, -1, -1, 46, + -1, -1, -1, -1, -1, -1, 53, -1, -1, 8, + -1, -1, 11, -1, -1, -1, 15, 16, 17, 18, + 19, 20, 21, -1, -1, -1, 394, 8, -1, 275, + 11, -1, 278, 80, 15, 16, -1, 36, 19, 20, + 21, -1, -1, -1, -1, -1, 292, 46, -1, 295, + -1, -1, -1, -1, 53, 36, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 46, 501, -1, -1, 504, + 505, 506, 53, 508, 509, 510, 511, 512, 513, -1, + -1, 80, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 80, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 177, -1, -1, 501, -1, -1, 504, 505, 506, -1, + 508, 509, 510, 511, 512, 513, -1, 194, 394, -1, + -1, -1, 199, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 222, 223, -1, 177, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 237, -1, -1, -1, -1, 194, 177, -1, -1, -1, + 199, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 194, -1, -1, -1, -1, 199, -1, + -1, -1, -1, 222, 223, -1, -1, -1, 275, -1, + -1, 278, -1, -1, -1, -1, -1, -1, 237, -1, + -1, 222, 223, -1, -1, 292, -1, -1, 295, -1, + -1, -1, -1, -1, -1, 501, 237, -1, 504, 505, + 506, -1, 508, 509, 510, 511, 512, 513, -1, -1, + -1, -1, -1, -1, -1, -1, 275, -1, -1, 278, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 292, 275, -1, 295, 278, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 292, -1, -1, 295, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 394, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, - 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, - 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, - 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, - 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, - 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 394, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 394, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 501, -1, -1, 504, 505, 506, + -1, 508, 509, 510, 511, 512, 513, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 501, -1, -1, 504, 505, 506, -1, 508, + 509, 510, 511, 512, 513, 3, -1, 5, -1, -1, + 501, -1, -1, 504, 505, 506, -1, 508, 509, 510, + 511, 512, 513, -1, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, + 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, + 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, + 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, + 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, + 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, + 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, + 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, + 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, + 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, + 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, + 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, + 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, + 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, + 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, + 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, + 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, + 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, + 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, @@ -16419,155 +15151,206 @@ static const yytype_int16 yycheck[] = 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, + 494, 495, 496, 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, 37, -1, - -1, -1, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, -1, 172, 173, 174, 175, 176, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, -1, -1, 233, 234, 235, 236, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, -1, 275, 276, 277, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - 289, -1, 291, 292, 293, -1, -1, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, 380, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, 435, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, + 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, + 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, + 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, + 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, + 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, + 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, + 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - 34, 35, -1, 37, -1, -1, -1, -1, 42, 43, - 44, -1, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, 81, -1, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, - 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, -1, -1, 233, - 234, 235, 236, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - -1, 275, 276, 277, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, 380, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, 391, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, 418, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - 464, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, 37, + -1, -1, -1, -1, 42, 43, 44, -1, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, 79, -1, 81, -1, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, 171, -1, 173, 174, 175, 176, 177, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, -1, -1, 234, 235, 236, 237, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, 273, 274, -1, 276, 277, + 278, 279, -1, 281, 282, 283, 284, 285, 286, -1, + 288, 289, 290, -1, 292, 293, 294, -1, -1, 297, + 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, 383, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, 394, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, 421, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + 438, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, 467, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, 66, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, 81, -1, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, -1, 172, 173, 174, 175, 176, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, -1, -1, 233, 234, 235, 236, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, -1, 275, 276, 277, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + -1, 31, 32, 33, 34, 35, -1, 37, -1, -1, + -1, -1, 42, 43, 44, -1, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, -1, 59, + 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, 81, -1, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + -1, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, 171, -1, 173, 174, 175, 176, 177, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, -1, -1, 234, 235, 236, 237, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 272, 273, 274, -1, 276, 277, 278, 279, + -1, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, + 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, 322, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, 383, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, 394, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, 421, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, -1, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, 467, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, + 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, -1, 66, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, 81, + -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, 171, + -1, 173, 174, 175, 176, 177, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, 209, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, -1, 276, 277, 278, 279, -1, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, 421, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, -1, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, 467, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, @@ -16583,192 +15366,243 @@ static const yytype_int16 yycheck[] = 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, - 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, -1, -1, 233, - 234, 235, 236, -1, 238, 239, 240, 241, 242, 243, + 154, 155, 156, 157, 158, 159, -1, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, 171, -1, 173, + 174, 175, 176, 177, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, -1, -1, + 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - -1, 275, 276, 277, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, 299, 300, 301, 302, 303, + 274, -1, 276, 277, 278, 279, -1, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, 361, 362, 363, + 314, -1, -1, -1, -1, 319, 320, 321, 322, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, 391, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, 418, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - 464, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, 421, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, -1, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, 467, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, + 494, 495, 496, 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, -1, -1, 82, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, 168, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, 445, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, + 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, + 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, + -1, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, -1, -1, 82, 83, 84, 85, + 86, 87, 88, -1, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, -1, -1, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, -1, 161, -1, 163, 164, 165, + 166, -1, 168, 169, 170, -1, -1, -1, 174, 175, + 176, -1, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, -1, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, -1, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, -1, -1, 224, -1, + 226, 227, 228, 229, 230, 231, -1, -1, 234, -1, + 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, -1, 270, 271, 272, 273, 274, -1, + 276, 277, -1, 279, -1, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, -1, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, -1, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, -1, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, -1, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, -1, 439, 440, 441, 442, 443, 444, 445, + 446, -1, 448, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, -1, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, 168, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, 236, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, 445, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, + 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, + -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, -1, -1, -1, 83, 84, 85, 86, 87, + 88, -1, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, -1, 161, -1, 163, 164, 165, 166, -1, + 168, 169, 170, -1, -1, -1, 174, 175, 176, -1, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, -1, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, -1, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, -1, -1, 224, -1, 226, 227, + 228, 229, 230, 231, -1, -1, 234, -1, 236, 237, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, -1, 270, 271, 272, 273, 274, -1, 276, 277, + -1, 279, -1, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, -1, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, -1, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, -1, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, -1, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + -1, 439, 440, 441, 442, 443, 444, 445, 446, -1, + 448, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, -1, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, 34, 35, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + -1, 31, 32, 33, 34, 35, -1, -1, -1, -1, + -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, + 50, 51, 52, 53, 54, -1, 56, 57, -1, 59, + 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, -1, -1, 83, 84, 85, 86, 87, 88, -1, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + -1, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, -1, -1, -1, 174, 175, 176, -1, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, -1, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, -1, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, -1, -1, 224, -1, 226, 227, 228, 229, + 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, -1, + 270, 271, 272, 273, 274, -1, 276, 277, -1, 279, + -1, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, + -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, -1, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, -1, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, -1, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, -1, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, -1, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, + 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, + 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, -1, + -1, 83, 84, 85, 86, 87, 88, -1, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, -1, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, -1, + -1, -1, 174, 175, 176, -1, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, -1, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, -1, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + -1, -1, 224, -1, 226, 227, 228, 229, 230, 231, + -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, -1, 270, 271, + 272, 273, 274, -1, 276, 277, -1, 279, -1, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, -1, 301, + -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + -1, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, -1, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, -1, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, -1, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, -1, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, @@ -16781,981 +15615,240 @@ static const yytype_int16 yycheck[] = 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, + 154, 155, 156, 157, 158, 159, -1, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, -1, -1, -1, + 174, 175, 176, -1, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + -1, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, -1, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, -1, -1, + 224, -1, 226, 227, 228, 229, 230, 231, -1, -1, + 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, + 264, 265, 266, 267, 268, -1, 270, 271, 272, 273, + 274, -1, 276, 277, -1, 279, -1, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, 291, 292, 293, + 294, -1, -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, + 314, -1, -1, -1, -1, 319, 320, 321, -1, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + -1, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, -1, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, -1, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, -1, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, + 494, 495, 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, 290, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, - -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, 290, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, - 4, -1, -1, -1, -1, 9, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, 416, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, - -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, - -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, - -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, - -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, 40, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, 40, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, + 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, + 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, + -1, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, -1, -1, 83, 84, 85, + 86, 87, 88, -1, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, -1, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, -1, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, -1, -1, -1, 174, 175, + 176, -1, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, -1, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, -1, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, -1, -1, 224, -1, + 226, 227, 228, 229, 230, 231, -1, -1, 234, -1, + 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, -1, 270, 271, 272, 273, 274, -1, + 276, 277, -1, 279, -1, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, 291, 292, 293, 294, -1, + -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, -1, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, -1, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, -1, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, -1, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, -1, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, -1, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, + 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, + -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, 79, -1, -1, -1, 83, 84, 85, 86, 87, + 88, -1, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, -1, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, -1, -1, -1, 174, 175, 176, -1, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, -1, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, -1, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, -1, -1, 224, -1, 226, 227, + 228, 229, 230, 231, -1, -1, 234, -1, 236, -1, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, -1, 270, 271, 272, 273, 274, -1, 276, 277, + -1, 279, -1, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, -1, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, -1, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, -1, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, -1, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + -1, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, -1, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, + 50, 51, 52, 53, 54, -1, 56, 57, -1, 59, + 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, -1, -1, 83, 84, 85, 86, 87, 88, -1, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + -1, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, -1, -1, -1, 174, 175, 176, -1, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, -1, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, -1, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, -1, -1, 224, -1, 226, 227, 228, 229, + 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, -1, + 270, 271, 272, 273, 274, -1, 276, 277, -1, 279, + -1, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, 291, 292, 293, 294, -1, -1, 297, 298, 299, + -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, -1, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, -1, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, -1, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, -1, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, -1, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 3, 4, -1, -1, -1, -1, 9, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, + 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, + 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, -1, + -1, 83, 84, 85, 86, 87, 88, -1, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, -1, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, -1, + -1, -1, 174, 175, 176, -1, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, -1, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, -1, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + -1, -1, 224, -1, 226, 227, 228, 229, 230, 231, + -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, -1, 270, 271, + 272, 273, 274, -1, 276, 277, -1, 279, -1, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, -1, 301, + -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + -1, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, -1, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, -1, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, -1, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, -1, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, @@ -17771,90 +15864,240 @@ static const yytype_int16 yycheck[] = 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, + 154, 155, 156, 157, 158, 159, -1, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, -1, -1, -1, + 174, 175, 176, -1, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + -1, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, -1, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, -1, -1, + 224, -1, 226, 227, 228, 229, 230, 231, -1, -1, + 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, + 264, 265, 266, 267, 268, -1, 270, 271, 272, 273, + 274, -1, 276, 277, -1, 279, -1, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, + 314, -1, -1, -1, -1, 319, 320, 321, -1, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + -1, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, 419, 420, -1, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, -1, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, -1, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, + 494, 495, 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, + 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, + 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, + -1, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, -1, -1, 83, 84, 85, + 86, 87, 88, -1, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, -1, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, -1, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, -1, -1, -1, 174, 175, + 176, -1, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, -1, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, -1, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, -1, -1, 224, -1, + 226, 227, 228, 229, 230, 231, -1, -1, 234, -1, + 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, -1, 270, 271, 272, 273, 274, -1, + 276, 277, -1, 279, -1, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, -1, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, -1, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, -1, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, -1, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, -1, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, -1, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, + 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, + -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, 79, -1, -1, -1, 83, 84, 85, 86, 87, + 88, -1, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, -1, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, -1, -1, -1, 174, 175, 176, -1, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, -1, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, -1, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, -1, -1, 224, -1, 226, 227, + 228, 229, 230, 231, -1, -1, 234, -1, 236, -1, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, -1, 270, 271, 272, 273, 274, -1, 276, 277, + -1, 279, -1, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, -1, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, -1, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, -1, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, -1, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + -1, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, -1, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, + 50, 51, 52, 53, 54, -1, 56, 57, -1, 59, + 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, -1, -1, 83, 84, 85, 86, 87, 88, -1, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + -1, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, -1, -1, -1, 174, 175, 176, -1, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, -1, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, -1, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, -1, -1, 224, -1, 226, 227, 228, 229, + 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, -1, + 270, 271, 272, 273, 274, -1, 276, 277, -1, 279, + -1, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, + -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, -1, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, -1, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, -1, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, -1, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, -1, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, + 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, + 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, -1, + -1, 83, 84, 85, 86, 87, 88, -1, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, -1, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, -1, + -1, -1, 174, 175, 176, -1, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, -1, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, -1, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + -1, -1, 224, -1, 226, 227, 228, 229, 230, 231, + -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, -1, 270, 271, + 272, 273, 274, -1, 276, 277, -1, 279, -1, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, -1, 301, + -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + -1, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, -1, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, -1, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, -1, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, -1, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, @@ -17870,238 +16113,241 @@ static const yytype_int16 yycheck[] = 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, + 154, 155, 156, 157, 158, 159, -1, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, -1, -1, -1, + 174, 175, 176, -1, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + -1, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, -1, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, -1, -1, + 224, -1, 226, 227, 228, 229, 230, 231, -1, -1, + 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, + 264, 265, 266, 267, 268, -1, 270, 271, 272, 273, + 274, -1, 276, 277, -1, 279, -1, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, + 314, -1, -1, -1, -1, 319, 320, 321, -1, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + -1, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, -1, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, -1, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, -1, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, 5, -1, -1, -1, + 494, 495, 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, + 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, + 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, + -1, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, -1, -1, 83, 84, 85, + 86, 87, 88, -1, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, -1, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, -1, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, -1, -1, -1, 174, 175, + 176, -1, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, -1, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, -1, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, -1, -1, 224, -1, + 226, 227, 228, 229, 230, 231, -1, -1, 234, -1, + 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, -1, 270, 271, 272, 273, 274, -1, + 276, 277, -1, 279, -1, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, -1, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, -1, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, -1, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, -1, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, -1, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, -1, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, 37, -1, -1, 40, -1, 42, 43, - 44, -1, 46, 47, 48, 49, 50, 51, 52, -1, - 54, 55, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, -1, -1, 81, -1, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, -1, 153, - 154, 155, 156, 157, -1, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, - 174, 175, 176, 177, -1, 179, -1, -1, -1, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, 208, -1, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, -1, -1, 233, - 234, 235, 236, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, -1, - -1, 275, 276, 277, 278, -1, -1, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, -1, 299, 300, 301, -1, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, -1, 321, 322, 323, - -1, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, 380, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, 391, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, -1, -1, -1, - 414, 415, -1, 417, 418, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, -1, 433, - -1, -1, 436, 437, 438, 439, 440, 441, 442, 443, - 444, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, -1, 461, -1, 463, - 464, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 3, - -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, - 494, 495, 496, 497, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, + 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, + -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, 79, -1, -1, -1, 83, 84, 85, 86, 87, + 88, -1, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, -1, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, -1, -1, -1, 174, 175, 176, -1, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, -1, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, -1, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, -1, -1, 224, -1, 226, 227, + 228, 229, 230, 231, -1, -1, 234, -1, 236, -1, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, -1, 270, 271, 272, 273, 274, -1, 276, 277, + -1, 279, -1, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, -1, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, -1, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, -1, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, -1, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + -1, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, -1, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, + 50, 51, 52, 53, 54, -1, 56, 57, -1, 59, + 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, -1, -1, 83, 84, 85, 86, 87, 88, -1, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + -1, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, -1, -1, -1, 174, 175, 176, -1, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, -1, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, -1, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, -1, -1, 224, -1, 226, 227, 228, 229, + 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, -1, + 270, 271, 272, 273, 274, -1, 276, 277, -1, 279, + -1, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, + -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, -1, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, -1, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, -1, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, -1, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, -1, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, + 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, + 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, -1, + -1, 83, 84, 85, 86, 87, 88, -1, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, -1, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, -1, + -1, -1, 174, 175, 176, -1, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, -1, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, -1, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + -1, -1, 224, -1, 226, 227, 228, 229, 230, 231, + -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, -1, 270, 271, + 272, 273, 274, -1, 276, 277, -1, 279, -1, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, -1, 301, + -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + -1, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, -1, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, -1, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, -1, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, -1, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 3, + -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, @@ -18116,190 +16362,241 @@ static const yytype_int16 yycheck[] = 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, + 154, 155, 156, 157, 158, 159, -1, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, -1, -1, -1, + 174, 175, 176, -1, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + -1, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, -1, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, -1, -1, + 224, -1, 226, 227, 228, 229, 230, 231, -1, -1, + 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, + 264, 265, 266, 267, 268, -1, 270, 271, 272, 273, + 274, -1, 276, 277, -1, 279, -1, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, + 314, -1, -1, -1, -1, 319, 320, 321, -1, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + -1, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, -1, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, -1, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, -1, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, + 494, 495, 496, 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, -1, 40, -1, -1, 43, 44, -1, + 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, + 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, + -1, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, -1, -1, 83, 84, 85, + 86, 87, 88, -1, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, -1, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, -1, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, -1, -1, -1, 174, 175, + 176, -1, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, -1, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, -1, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, -1, -1, 224, -1, + 226, 227, 228, 229, 230, 231, -1, -1, 234, -1, + 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, -1, 270, 271, 272, 273, 274, -1, + 276, 277, -1, 279, -1, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, -1, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, -1, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, -1, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, -1, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, -1, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, -1, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, + -1, -1, 40, -1, -1, 43, 44, -1, 46, 47, + 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, + -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, 79, -1, -1, -1, 83, 84, 85, 86, 87, + 88, -1, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, -1, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, -1, -1, -1, 174, 175, 176, -1, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, -1, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, -1, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, -1, -1, 224, -1, 226, 227, + 228, 229, 230, 231, -1, -1, 234, -1, 236, -1, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, -1, 270, 271, 272, 273, 274, -1, 276, 277, + -1, 279, -1, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, -1, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, -1, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, -1, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, -1, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + -1, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, -1, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, + 50, 51, 52, 53, 54, -1, 56, 57, -1, 59, + 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, -1, -1, 83, 84, 85, 86, 87, 88, -1, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + -1, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, -1, -1, -1, 174, 175, 176, -1, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, -1, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, -1, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, -1, -1, 224, -1, 226, 227, 228, 229, + 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, -1, + 270, 271, 272, 273, 274, -1, 276, 277, -1, 279, + -1, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, + -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, -1, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, -1, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, -1, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, -1, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, -1, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, + 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, + 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, -1, + -1, 83, 84, 85, 86, 87, 88, -1, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, -1, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, -1, + -1, -1, 174, 175, 176, -1, 178, -1, 180, -1, + 182, 183, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, -1, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, -1, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + -1, -1, 224, -1, 226, 227, 228, 229, 230, 231, + -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, -1, 270, 271, + 272, 273, 274, -1, 276, 277, -1, 279, -1, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, -1, 301, + -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + -1, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, -1, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, -1, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, -1, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, -1, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 3, + -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, @@ -18314,141 +16611,240 @@ static const yytype_int16 yycheck[] = 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, + 154, 155, 156, 157, 158, 159, -1, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, -1, -1, -1, + 174, 175, 176, -1, 178, -1, 180, -1, 182, 183, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + -1, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, -1, 210, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, -1, -1, + 224, -1, 226, 227, 228, 229, 230, 231, -1, -1, + 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, + 264, 265, 266, 267, 268, -1, 270, 271, 272, 273, + 274, -1, 276, 277, -1, 279, -1, 281, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, + 314, -1, -1, -1, -1, 319, 320, 321, -1, 323, + 324, 325, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, -1, + 384, 385, 386, 387, 388, 389, 390, 391, 392, -1, + -1, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + 414, -1, -1, 417, 418, -1, 420, -1, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, 435, 436, 437, -1, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, 463, + 464, -1, 466, -1, 468, 469, 470, 471, 472, 473, + 474, -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, + 494, 495, 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, - -1, 40, -1, -1, 43, 44, -1, 46, 47, 48, - -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, - -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, -1, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, + 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, + 46, 47, 48, -1, 50, 51, 52, 53, 54, -1, + 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, + -1, 67, 68, 69, 70, 71, 72, 73, -1, 75, + 76, 77, 78, 79, -1, -1, -1, 83, 84, 85, + 86, 87, 88, -1, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, -1, -1, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, -1, 161, -1, 163, 164, 165, + 166, -1, 168, -1, 170, -1, -1, -1, 174, 175, + 176, -1, 178, -1, 180, -1, 182, 183, 184, 185, + -1, 187, 188, 189, 190, 191, 192, 193, -1, 195, + 196, 197, 198, -1, 200, 201, 202, 203, 204, 205, + 206, -1, 208, -1, 210, 211, 212, 213, 214, 215, + 216, 217, -1, 219, -1, 221, -1, -1, 224, -1, + 226, 227, 228, 229, 230, 231, -1, -1, 234, -1, + 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, -1, 270, 271, 272, 273, 274, -1, + 276, 277, -1, 279, -1, 281, 282, 283, 284, 285, + 286, -1, 288, 289, -1, -1, 292, 293, 294, -1, + -1, 297, 298, 299, -1, 301, -1, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, -1, + -1, -1, -1, 319, 320, 321, -1, 323, 324, 325, + 326, 327, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, -1, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, -1, 362, 363, -1, 365, + 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, -1, -1, 384, 385, + 386, 387, 388, 389, 390, 391, 392, -1, -1, 395, + 396, 397, 398, -1, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, -1, + -1, 417, 418, -1, 420, -1, 422, 423, 424, 425, + 426, -1, 428, 429, 430, -1, -1, 433, 434, 435, + 436, 437, -1, 439, 440, 441, 442, 443, 444, 445, + 446, -1, -1, 449, 450, 451, -1, 453, 454, 455, + 456, -1, 458, 459, 460, 461, 462, 463, 464, -1, + 466, -1, 468, 469, 470, 471, 472, 473, 474, -1, + -1, 477, -1, -1, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, + 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, + -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, 79, -1, -1, -1, 83, 84, 85, 86, 87, + 88, -1, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, -1, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, -1, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, -1, -1, -1, 174, 175, 176, -1, + 178, -1, 180, -1, 182, 183, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, -1, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, -1, 210, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, -1, -1, 224, -1, 226, 227, + 228, 229, 230, 231, -1, -1, 234, -1, 236, -1, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, -1, 270, 271, 272, 273, 274, -1, 276, 277, + -1, 279, -1, 281, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, 299, -1, 301, -1, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, 321, -1, 323, 324, 325, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, -1, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, -1, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, -1, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 414, -1, -1, 417, + 418, -1, 420, -1, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, 435, 436, 437, + -1, 439, 440, 441, 442, 443, 444, 445, 446, -1, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, 463, 464, -1, 466, -1, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 486, 487, + 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, + 498, 499, 500, 3, -1, 5, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, + -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 43, 44, -1, 46, 47, 48, -1, + 50, 51, 52, 53, 54, -1, 56, 57, -1, 59, + 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, + 70, 71, 72, 73, -1, 75, 76, 77, 78, 79, + -1, -1, -1, 83, 84, 85, 86, 87, 88, -1, + 90, 91, 92, -1, 94, 95, 96, 97, 98, 99, + -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + -1, 161, -1, 163, 164, 165, 166, -1, 168, -1, + 170, -1, -1, -1, 174, 175, 176, -1, 178, -1, + 180, -1, 182, 183, 184, 185, -1, 187, 188, 189, + 190, 191, 192, 193, -1, 195, 196, 197, 198, -1, + 200, 201, 202, 203, 204, 205, 206, -1, 208, -1, + 210, 211, 212, 213, 214, 215, 216, 217, -1, 219, + -1, 221, -1, -1, 224, -1, 226, 227, 228, 229, + 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, 268, -1, + 270, 271, 272, 273, 274, -1, 276, 277, -1, 279, + -1, 281, 282, 283, 284, 285, 286, -1, 288, 289, + -1, -1, 292, 293, 294, -1, -1, 297, 298, 299, + -1, 301, -1, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, -1, -1, -1, -1, 319, + 320, 321, -1, 323, 324, 325, 326, 327, 328, -1, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, -1, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, -1, -1, 384, 385, 386, 387, 388, 389, + 390, 391, 392, -1, -1, 395, 396, 397, 398, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, 414, -1, -1, 417, 418, -1, + 420, -1, 422, 423, 424, 425, 426, -1, 428, 429, + 430, -1, -1, 433, 434, 435, 436, 437, -1, 439, + 440, 441, 442, 443, 444, 445, 446, -1, -1, 449, + 450, 451, -1, 453, 454, 455, 456, -1, 458, 459, + 460, 461, 462, 463, 464, -1, 466, -1, 468, 469, + 470, 471, 472, 473, 474, -1, -1, 477, -1, -1, + 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, + 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, 37, -1, -1, 40, -1, + 42, 43, 44, -1, 46, 47, 48, 49, 50, 51, + 52, -1, 54, 55, 56, 57, -1, 59, 60, 61, + 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, -1, -1, 81, + -1, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + -1, 153, 154, 155, 156, 157, 158, -1, -1, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, 171, + -1, 173, 174, 175, 176, 177, 178, -1, 180, -1, + -1, -1, 184, 185, -1, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, 209, -1, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + -1, -1, 234, 235, 236, 237, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, -1, -1, 276, 277, 278, 279, -1, -1, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, -1, 300, 301, + 302, -1, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, -1, + 322, 323, 324, -1, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, 383, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, 394, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, -1, -1, -1, 417, 418, -1, 420, 421, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, -1, 436, -1, -1, 439, 440, 441, + 442, 443, 444, 445, 446, 447, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, -1, 464, -1, 466, 467, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 3, -1, 5, -1, -1, -1, + -1, -1, -1, -1, -1, 497, 498, 499, 500, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, @@ -18463,235 +16859,490 @@ static const yytype_int16 yycheck[] = 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, + 159, -1, 161, -1, 163, 164, 165, 166, -1, 168, + -1, 170, -1, -1, -1, 174, 175, 176, -1, 178, + -1, 180, -1, 182, 183, 184, 185, -1, 187, 188, + 189, 190, 191, 192, 193, -1, 195, 196, 197, 198, + -1, 200, 201, 202, 203, 204, 205, 206, -1, 208, + -1, 210, 211, 212, 213, 214, 215, 216, 217, -1, + 219, -1, 221, -1, -1, 224, -1, 226, 227, 228, + 229, 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, 366, 367, 368, + 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, + -1, 270, 271, 272, 273, 274, -1, 276, 277, -1, + 279, -1, 281, 282, 283, 284, 285, 286, -1, 288, + 289, -1, -1, 292, 293, 294, -1, -1, 297, 298, + 299, -1, 301, -1, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, -1, -1, -1, -1, + 319, 320, 321, -1, 323, 324, 325, 326, 327, 328, + -1, 330, 331, 332, 333, 334, 335, -1, 337, 338, + 339, 340, 341, 342, 343, 344, 345, 346, -1, 348, + 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + 379, 380, 381, -1, -1, 384, 385, 386, 387, 388, + 389, 390, 391, 392, -1, -1, 395, 396, 397, 398, + -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, -1, -1, 417, 418, + -1, 420, -1, 422, 423, 424, 425, 426, -1, 428, + 429, 430, -1, -1, 433, 434, 435, 436, 437, -1, + 439, 440, 441, 442, 443, 444, 445, 446, -1, -1, + 449, 450, 451, -1, 453, 454, 455, 456, -1, 458, + 459, 460, 461, 462, 463, 464, -1, 466, -1, 468, + 469, 470, 471, 472, 473, 474, -1, -1, 477, -1, + -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, + 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, - 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - 44, -1, 46, 47, 48, -1, 50, 51, 52, 53, - 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, - 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, - -1, 75, 76, 77, 78, 79, -1, -1, -1, 83, - 84, 85, 86, 87, 88, -1, 90, 91, 92, -1, - 94, 95, 96, 97, 98, 99, -1, -1, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, - 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, - 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, - 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, - 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, -1, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, -1, 209, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, -1, -1, 223, - -1, 225, 226, 227, 228, 229, 230, -1, -1, 233, - -1, 235, -1, -1, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, -1, 269, 270, 271, 272, 273, - -1, 275, 276, -1, 278, -1, 280, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, 298, -1, 300, -1, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, 320, -1, 322, 323, - 324, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, -1, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, -1, 381, 382, 383, - 384, 385, 386, 387, 388, 389, -1, -1, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, -1, -1, - 414, 415, -1, 417, -1, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, 432, 433, - 434, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, 460, 461, -1, 463, - -1, 465, 466, 467, 468, 469, 470, 471, -1, -1, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, - 494, 495, 496, 497, 3, -1, -1, -1, -1, -1, + -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, + 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 43, 44, -1, 46, 47, 48, -1, 50, + 51, 52, 53, 54, -1, 56, 57, -1, 59, 60, + 61, 62, 63, 64, -1, -1, 67, 68, 69, 70, + 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, + -1, -1, 83, 84, 85, 86, 87, 88, -1, 90, + 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, + -1, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, -1, + 161, -1, 163, 164, 165, 166, -1, 168, -1, 170, + -1, -1, -1, 174, 175, 176, -1, 178, -1, 180, + -1, 182, 183, 184, 185, -1, 187, 188, 189, 190, + 191, 192, 193, -1, 195, 196, 197, 198, -1, 200, + 201, 202, 203, 204, 205, 206, -1, 208, -1, 210, + 211, 212, 213, 214, 215, 216, 217, -1, 219, -1, + 221, -1, -1, 224, -1, 226, 227, 228, 229, 230, + 231, -1, -1, 234, -1, 236, -1, -1, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, -1, 270, + 271, 272, 273, 274, -1, 276, 277, -1, 279, -1, + 281, 282, 283, 284, 285, 286, -1, 288, 289, -1, + -1, 292, 293, 294, -1, -1, 297, 298, 299, -1, + 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, -1, -1, -1, -1, 319, 320, + 321, -1, 323, 324, 325, 326, 327, 328, -1, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + -1, 362, 363, -1, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, -1, -1, 384, 385, 386, 387, 388, 389, 390, + 391, 392, -1, -1, 395, 396, 397, 398, -1, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, -1, -1, 417, 418, -1, 420, + -1, 422, 423, 424, 425, 426, -1, 428, 429, 430, + -1, -1, 433, 434, 435, 436, 437, -1, 439, 440, + 441, 442, 443, 444, 445, 446, -1, -1, 449, 450, + 451, -1, 453, 454, 455, 456, -1, 458, 459, 460, + 461, 462, 463, 464, -1, 466, -1, 468, 469, 470, + 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, + 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, + 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, + 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, + 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, + 53, 54, -1, 56, 57, -1, 59, 60, 61, 62, + 63, 64, -1, -1, 67, 68, 69, 70, 71, 72, + 73, -1, 75, 76, 77, 78, 79, -1, -1, -1, + 83, 84, 85, 86, 87, 88, -1, 90, 91, 92, + -1, 94, 95, 96, 97, 98, 99, -1, -1, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, -1, 161, -1, + 163, 164, 165, 166, -1, 168, -1, 170, -1, -1, + -1, 174, 175, 176, -1, 178, -1, 180, -1, 182, + 183, 184, 185, -1, 187, 188, 189, 190, 191, 192, + 193, -1, 195, 196, 197, 198, -1, 200, 201, 202, + 203, 204, 205, 206, -1, 208, -1, 210, 211, 212, + 213, 214, 215, 216, 217, -1, 219, -1, 221, -1, + -1, 224, -1, 226, 227, 228, 229, 230, 231, -1, + -1, 234, -1, 236, -1, -1, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, -1, 270, 271, 272, + 273, 274, -1, 276, 277, -1, 279, -1, 281, 282, + 283, 284, 285, 286, -1, 288, 289, -1, -1, 292, + 293, 294, -1, -1, 297, 298, 299, -1, 301, -1, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, -1, -1, -1, -1, 319, 320, 321, -1, + 323, 324, 325, 326, 327, 328, -1, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, -1, 362, + 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, -1, + -1, 384, 385, 386, 387, 388, 389, 390, 391, 392, + -1, -1, 395, 396, 397, 398, -1, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, -1, -1, 417, 418, -1, 420, -1, 422, + 423, 424, 425, 426, -1, 428, 429, 430, -1, -1, + 433, 434, 435, 436, 437, -1, 439, 440, 441, 442, + 443, 444, 445, 446, -1, -1, 449, 450, 451, -1, + 453, 454, 455, 456, -1, 458, 459, 460, 461, 462, + 463, 464, -1, 466, -1, 468, 469, 470, 471, 472, + 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, + 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 498, 499, 500, 3, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, + 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, + -1, 46, 47, 48, -1, 50, 51, 52, 53, 54, + -1, 56, 57, -1, 59, 60, 61, 62, 63, 64, + -1, -1, 67, 68, 69, 70, 71, 72, 73, -1, + 75, 76, 77, 78, 79, -1, -1, -1, 83, 84, + 85, 86, 87, 88, -1, 90, 91, 92, -1, 94, + 95, 96, 97, 98, 99, -1, -1, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, -1, 118, -1, 120, 121, 122, 123, 124, + 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, + 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, + 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, -1, 161, -1, 163, 164, + 165, 166, -1, 168, -1, 170, -1, -1, -1, 174, + 175, 176, -1, 178, -1, 180, -1, 182, 183, 184, + 185, -1, 187, 188, 189, 190, 191, 192, 193, -1, + 195, 196, 197, 198, -1, 200, 201, 202, 203, 204, + 205, 206, -1, 208, -1, 210, 211, 212, 213, 214, + 215, 216, 217, -1, 219, -1, 221, -1, -1, 224, + -1, 226, 227, 228, 229, 230, 231, -1, -1, 234, + -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, -1, 270, 271, 272, 273, 274, + -1, 276, 277, -1, 279, -1, 281, 282, 283, 284, + 285, 286, -1, 288, 289, -1, -1, 292, 293, 294, + -1, -1, 297, 298, 299, -1, 301, -1, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + -1, -1, -1, -1, 319, 320, 321, -1, 323, 324, + 325, 326, 327, 328, -1, 330, 331, 332, 333, 334, + 335, -1, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, -1, 362, 363, -1, + 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, -1, -1, 384, + 385, 386, 387, 388, 389, 390, 391, 392, -1, -1, + 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + -1, -1, 417, 418, -1, 420, -1, 422, 423, 424, + 425, 426, -1, 428, 429, 430, -1, -1, 433, 434, + 435, 436, 437, -1, 439, 440, 441, 442, 443, 444, + 445, 446, -1, -1, 449, 450, 451, -1, 453, 454, + 455, 456, -1, 458, 459, 460, 461, 462, 463, 464, + -1, 466, -1, 468, 469, 470, 471, 472, 473, 474, + -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, + 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 498, 499, 500, 3, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, + 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 43, 44, -1, 46, + 47, 48, -1, 50, 51, 52, 53, 54, -1, 56, + 57, -1, 59, 60, 61, 62, 63, 64, -1, -1, + 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, + 77, 78, 79, -1, -1, -1, 83, 84, 85, 86, + 87, 88, -1, 90, 91, 92, -1, 94, 95, 96, + 97, 98, 99, -1, -1, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, + -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, -1, 161, -1, 163, 164, 165, 166, + -1, 168, -1, 170, -1, -1, -1, 174, 175, 176, + -1, 178, -1, 180, -1, 182, 183, 184, 185, -1, + 187, 188, 189, 190, 191, 192, 193, -1, 195, 196, + 197, 198, -1, 200, 201, 202, 203, 204, 205, 206, + -1, 208, -1, 210, 211, 212, 213, 214, 215, 216, + 217, -1, 219, -1, 221, -1, -1, 224, -1, 226, + 227, 228, 229, 230, 231, -1, -1, 234, -1, 236, + -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, -1, 270, 271, 272, 273, 274, -1, 276, + 277, -1, 279, -1, 281, 282, 283, 284, 285, 286, + -1, 288, 289, -1, -1, 292, 293, 294, -1, -1, + 297, 298, 299, -1, 301, -1, 303, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, -1, -1, + -1, -1, 319, 320, 321, -1, 323, 324, 325, 326, + 327, 328, -1, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + -1, 348, 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, -1, 362, 363, -1, 365, 366, + 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, -1, -1, 384, 385, 386, + 387, 388, 389, 390, 391, 392, -1, -1, 395, 396, + 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, -1, -1, + 417, 418, -1, 420, -1, 422, 423, 424, 425, 426, + -1, 428, 429, 430, -1, -1, 433, 434, 435, 436, + 437, -1, 439, 440, 441, 442, 443, 444, 445, 446, + -1, -1, 449, 450, 451, -1, 453, 454, 455, 456, + -1, 458, 459, 460, 461, 462, 463, 464, -1, 466, + -1, 468, 469, 470, 471, 472, 473, 474, -1, -1, + 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, + 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, 37, -1, - -1, -1, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, 51, 52, -1, 54, 55, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - -1, -1, 81, -1, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, -1, 153, 154, 155, 156, 157, -1, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, -1, 172, 173, 174, -1, 176, 177, -1, - 179, -1, -1, -1, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - -1, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, -1, -1, 233, 234, 235, 236, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, -1, -1, 275, 276, 277, 278, - -1, -1, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, -1, - 299, 300, 301, -1, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, -1, 321, 322, 323, -1, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, 380, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, -1, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, -1, 433, -1, -1, 436, 437, 438, - 439, 440, 441, 442, 443, 444, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, -1, 461, -1, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 3, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 494, 495, 496, 497, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, 37, -1, - -1, -1, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, 51, 52, -1, 54, 55, 56, 57, -1, - 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, - 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - -1, -1, 81, -1, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, - -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, - 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, - -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, -1, 153, 154, 155, 156, 157, -1, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, -1, 172, 173, 174, -1, 176, 177, -1, - 179, -1, -1, -1, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - -1, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, -1, -1, 233, 234, 235, 236, -1, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, -1, -1, 275, 276, 277, 278, - -1, -1, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, -1, - 299, 300, 301, -1, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, -1, 321, 322, 323, -1, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, 380, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, -1, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, -1, 433, -1, -1, 436, 437, 438, - 439, 440, 441, 442, 443, 444, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, -1, 461, -1, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 3, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 494, 495, 496, 497, -1, - -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, - 29, -1, 31, 32, 33, -1, -1, -1, 37, -1, - -1, -1, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, 51, 52, -1, 54, 55, 56, 57, -1, + 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, + -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, 78, - -1, -1, 81, -1, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, -1, 94, 95, 96, 97, 98, - 99, -1, 101, 102, 103, 104, 105, 106, 107, 108, + 79, -1, -1, -1, 83, 84, 85, 86, 87, 88, + -1, 90, 91, 92, -1, 94, 95, 96, 97, 98, + 99, -1, -1, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, - 149, 150, 151, -1, 153, 154, 155, 156, 157, -1, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, 170, -1, 172, 173, 174, 175, 176, 177, -1, - 179, -1, -1, -1, 183, 184, -1, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, 208, - -1, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, -1, -1, 233, 234, 235, 236, -1, 238, + 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + 159, -1, 161, -1, 163, 164, 165, 166, -1, 168, + -1, 170, -1, -1, -1, 174, 175, 176, -1, 178, + -1, 180, -1, 182, 183, 184, 185, -1, 187, 188, + 189, 190, 191, 192, 193, -1, 195, 196, 197, 198, + -1, 200, 201, 202, 203, 204, 205, 206, -1, 208, + -1, 210, 211, 212, 213, 214, 215, 216, 217, -1, + 219, -1, 221, -1, -1, 224, -1, 226, 227, 228, + 229, 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, -1, -1, 275, 276, 277, 278, - -1, -1, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, -1, - 299, 300, 301, -1, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, -1, 321, 322, 323, -1, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, 361, 362, 363, 364, -1, 366, 367, 368, + -1, 270, 271, 272, 273, 274, -1, 276, 277, -1, + 279, -1, 281, 282, 283, 284, 285, 286, -1, 288, + 289, -1, -1, 292, 293, 294, -1, -1, 297, 298, + 299, -1, 301, -1, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, -1, -1, -1, -1, + 319, 320, 321, -1, 323, 324, 325, 326, 327, 328, + -1, 330, 331, 332, 333, 334, 335, -1, 337, 338, + 339, 340, 341, 342, 343, 344, 345, 346, -1, 348, + 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, 380, 381, 382, 383, 384, 385, 386, -1, 388, - 389, -1, 391, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, -1, -1, -1, 414, 415, -1, 417, 418, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, -1, 433, -1, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, -1, 461, -1, 463, 464, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 3, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 494, 495, 496, 497, -1, + 379, 380, 381, -1, -1, 384, 385, 386, 387, 388, + 389, 390, 391, 392, -1, -1, 395, 396, 397, 398, + -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, -1, -1, 417, 418, + -1, 420, -1, 422, 423, 424, 425, 426, -1, 428, + 429, 430, -1, -1, 433, 434, 435, 436, 437, -1, + 439, 440, 441, 442, 443, 444, 445, 446, -1, -1, + 449, 450, 451, -1, 453, 454, 455, 456, -1, 458, + 459, 460, 461, 462, 463, 464, -1, 466, -1, 468, + 469, 470, 471, 472, 473, 474, -1, -1, 477, -1, + -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, + 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, + 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 43, 44, -1, 46, 47, 48, -1, 50, + 51, 52, 53, 54, -1, 56, 57, -1, 59, 60, + 61, 62, 63, 64, -1, -1, 67, 68, 69, 70, + 71, 72, 73, -1, 75, 76, 77, 78, 79, -1, + -1, -1, 83, 84, 85, 86, 87, 88, -1, 90, + 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, + -1, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, -1, + 161, -1, 163, 164, 165, 166, -1, 168, -1, 170, + -1, -1, -1, 174, 175, 176, -1, 178, -1, 180, + -1, 182, 183, 184, 185, -1, 187, 188, 189, 190, + 191, 192, 193, -1, 195, 196, 197, 198, -1, 200, + 201, 202, 203, 204, 205, 206, -1, 208, -1, 210, + 211, 212, 213, 214, 215, 216, 217, -1, 219, -1, + 221, -1, -1, 224, -1, 226, 227, 228, 229, 230, + 231, -1, -1, 234, -1, 236, -1, -1, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, -1, 270, + 271, 272, 273, 274, -1, 276, 277, -1, 279, -1, + 281, 282, 283, 284, 285, 286, -1, 288, 289, -1, + -1, 292, 293, 294, -1, -1, 297, 298, 299, -1, + 301, -1, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, -1, -1, -1, -1, 319, 320, + 321, -1, 323, 324, 325, 326, 327, 328, -1, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + -1, 362, 363, -1, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, -1, -1, 384, 385, 386, 387, 388, 389, 390, + 391, 392, -1, -1, 395, 396, 397, 398, -1, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, -1, -1, 417, 418, -1, 420, + -1, 422, 423, 424, 425, 426, -1, 428, 429, 430, + -1, -1, 433, 434, 435, 436, 437, -1, 439, 440, + 441, 442, 443, 444, 445, 446, -1, -1, 449, 450, + 451, -1, 453, 454, 455, 456, -1, 458, 459, 460, + 461, 462, 463, 464, -1, 466, -1, 468, 469, 470, + 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, + 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, + 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, + 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, + 33, -1, -1, -1, -1, -1, -1, 40, -1, -1, + 43, 44, -1, 46, 47, 48, -1, 50, 51, 52, + 53, 54, -1, 56, 57, -1, 59, 60, 61, 62, + 63, 64, -1, -1, 67, 68, 69, 70, 71, 72, + 73, -1, 75, 76, 77, 78, 79, -1, -1, -1, + 83, 84, 85, 86, 87, 88, -1, 90, 91, 92, + -1, 94, 95, 96, 97, 98, 99, -1, -1, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, -1, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, -1, 161, -1, + 163, 164, 165, 166, -1, 168, -1, 170, -1, -1, + -1, 174, 175, 176, -1, 178, -1, 180, -1, 182, + 183, 184, 185, -1, 187, 188, 189, 190, 191, 192, + 193, -1, 195, 196, 197, 198, -1, 200, 201, 202, + 203, 204, 205, 206, -1, 208, -1, 210, 211, 212, + 213, 214, 215, 216, 217, -1, 219, -1, 221, -1, + -1, 224, -1, 226, 227, 228, 229, 230, 231, -1, + -1, 234, -1, 236, -1, -1, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, -1, 270, 271, 272, + 273, 274, -1, 276, 277, -1, 279, -1, 281, 282, + 283, 284, 285, 286, -1, 288, 289, -1, -1, 292, + 293, 294, -1, -1, 297, 298, 299, -1, 301, -1, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, -1, -1, -1, -1, 319, 320, 321, -1, + 323, 324, 325, 326, 327, 328, -1, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, -1, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, -1, 362, + 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, -1, + -1, 384, 385, 386, 387, 388, -1, 390, 391, 392, + -1, -1, 395, 396, 397, 398, -1, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, -1, -1, 417, 418, -1, 420, -1, 422, + 423, 424, 425, 426, -1, 428, 429, 430, -1, -1, + 433, 434, 435, 436, 437, -1, 439, 440, 441, 442, + 443, 444, 445, 446, -1, -1, 449, 450, 451, -1, + 453, 454, 455, 456, -1, 458, 459, 460, 461, 462, + 463, 464, -1, 466, -1, 468, 469, 470, 471, 472, + 473, 474, -1, -1, 477, -1, -1, 480, 481, 482, + 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 498, 499, 500, 3, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, + 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, + -1, 46, 47, 48, -1, 50, 51, 52, 53, 54, + -1, 56, 57, -1, 59, 60, 61, 62, 63, 64, + -1, -1, 67, 68, 69, 70, 71, 72, 73, -1, + 75, 76, 77, 78, 79, -1, -1, -1, 83, 84, + 85, 86, 87, 88, -1, 90, 91, 92, -1, 94, + 95, 96, 97, 98, 99, -1, -1, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, -1, 118, -1, 120, 121, 122, 123, 124, + 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, + 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, + 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, + 155, 156, 157, 158, 159, -1, 161, -1, 163, 164, + 165, 166, -1, 168, -1, 170, -1, -1, -1, 174, + 175, 176, -1, 178, -1, 180, -1, 182, 183, 184, + 185, -1, 187, 188, 189, 190, 191, 192, 193, -1, + 195, 196, 197, 198, -1, 200, 201, 202, 203, 204, + 205, 206, -1, 208, -1, 210, 211, 212, 213, 214, + 215, 216, 217, -1, 219, -1, 221, -1, -1, 224, + -1, 226, 227, 228, 229, 230, 231, -1, -1, 234, + -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, -1, 270, 271, 272, 273, 274, + -1, 276, 277, -1, 279, -1, 281, 282, 283, 284, + 285, 286, -1, 288, 289, -1, -1, 292, 293, 294, + -1, -1, 297, 298, 299, -1, 301, -1, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + -1, -1, -1, -1, 319, 320, 321, -1, 323, 324, + 325, 326, 327, 328, -1, 330, 331, 332, 333, 334, + 335, -1, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, -1, 362, 363, -1, + 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, -1, -1, 384, + 385, 386, 387, 388, 389, 390, 391, 392, -1, -1, + 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + -1, -1, 417, 418, -1, 420, -1, 422, 423, 424, + 425, 426, -1, 428, 429, 430, -1, -1, 433, 434, + 435, 436, 437, -1, 439, 440, 441, 442, 443, 444, + 445, 446, -1, -1, 449, 450, 451, -1, 453, 454, + 455, 456, -1, 458, 459, 460, 461, 462, 463, 464, + -1, 466, -1, 468, 469, 470, 471, 472, 473, 474, + -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, + 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, + 495, 496, 497, 498, 499, 500, 3, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, + 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 43, 44, -1, 46, + 47, 48, -1, 50, 51, 52, 53, 54, -1, 56, + 57, -1, 59, 60, 61, 62, 63, 64, -1, -1, + 67, 68, 69, 70, 71, 72, 73, -1, 75, 76, + 77, 78, 79, -1, -1, -1, 83, 84, 85, 86, + 87, 88, -1, 90, 91, 92, -1, 94, 95, 96, + 97, 98, 99, -1, -1, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, + -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, -1, 161, -1, 163, 164, 165, 166, + -1, 168, -1, 170, -1, -1, -1, 174, 175, 176, + -1, 178, -1, 180, -1, 182, 183, 184, 185, -1, + 187, 188, 189, 190, 191, 192, 193, -1, 195, 196, + 197, 198, -1, 200, 201, 202, 203, 204, 205, 206, + -1, 208, -1, 210, 211, 212, 213, 214, 215, 216, + 217, -1, 219, -1, 221, -1, -1, 224, -1, 226, + 227, 228, 229, 230, 231, -1, -1, 234, -1, 236, + -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, -1, 270, 271, 272, 273, 274, -1, 276, + 277, -1, 279, -1, 281, 282, 283, 284, 285, 286, + -1, 288, 289, -1, -1, 292, 293, 294, -1, -1, + 297, 298, 299, -1, 301, -1, 303, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, -1, -1, + -1, -1, 319, 320, 321, -1, 323, 324, 325, 326, + 327, 328, -1, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + -1, 348, 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, -1, 362, 363, -1, 365, 366, + 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, -1, -1, 384, 385, 386, + 387, 388, 389, 390, 391, 392, -1, -1, 395, 396, + 397, 398, -1, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, -1, -1, + 417, 418, -1, 420, -1, 422, 423, 424, 425, 426, + -1, 428, 429, 430, -1, -1, 433, 434, 435, 436, + 437, -1, 439, 440, 441, 442, 443, 444, 445, 446, + -1, -1, 449, 450, 451, -1, 453, 454, 455, 456, + -1, 458, 459, 460, 461, 462, 463, 464, -1, 466, + -1, 468, 469, 470, 471, 472, 473, 474, -1, -1, + 477, -1, -1, 480, 481, 482, 483, 484, 485, 486, + 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, + 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, 44, -1, 46, 47, 48, @@ -18706,40 +17357,235 @@ static const yytype_int16 yycheck[] = 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - -1, 160, -1, 162, 163, 164, 165, -1, 167, -1, - 169, -1, -1, -1, 173, 174, 175, -1, 177, -1, - 179, -1, 181, 182, -1, 184, -1, 186, 187, 188, - 189, 190, 191, 192, -1, 194, 195, 196, 197, -1, - 199, 200, 201, 202, 203, 204, 205, -1, 207, -1, - 209, 210, 211, 212, 213, 214, 215, 216, -1, 218, - -1, 220, -1, -1, 223, -1, 225, 226, 227, 228, - 229, 230, -1, -1, 233, -1, 235, -1, -1, 238, + 159, -1, 161, -1, 163, 164, 165, 166, -1, 168, + -1, 170, -1, -1, -1, 174, 175, 176, -1, 178, + -1, 180, -1, 182, 183, 184, 185, -1, 187, 188, + 189, 190, 191, 192, 193, -1, 195, 196, 197, 198, + -1, 200, 201, 202, 203, 204, 205, 206, -1, 208, + -1, 210, 211, 212, 213, 214, 215, 216, 217, -1, + 219, -1, 221, -1, -1, 224, -1, 226, 227, 228, + 229, 230, 231, -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, -1, - 269, 270, 271, 272, 273, -1, 275, 276, -1, 278, - -1, 280, 281, 282, 283, 284, 285, -1, 287, 288, - -1, -1, 291, 292, 293, -1, -1, 296, 297, 298, - -1, 300, -1, 302, 303, 304, 305, 306, 307, 308, - -1, 310, 311, 312, 313, -1, -1, -1, -1, 318, - 319, 320, -1, 322, 323, 324, 325, 326, 327, -1, - 329, 330, 331, 332, 333, 334, -1, 336, -1, 338, - 339, 340, 341, 342, 343, -1, 345, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 357, -1, - 359, 360, -1, 362, 363, 364, 365, -1, 367, 368, + 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, + -1, 270, 271, 272, 273, 274, -1, 276, 277, -1, + 279, -1, 281, 282, 283, 284, 285, 286, -1, 288, + 289, -1, -1, 292, 293, 294, -1, -1, 297, 298, + 299, -1, 301, -1, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, -1, -1, -1, -1, + 319, 320, 321, -1, 323, 324, 325, 326, 327, 328, + -1, 330, 331, 332, 333, 334, 335, -1, 337, 338, + 339, 340, 341, 342, 343, 344, 345, 346, -1, 348, + 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, + 359, 360, -1, 362, 363, -1, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - -1, -1, 381, 382, 383, 384, 385, 386, 387, 388, - 389, -1, -1, 392, 393, 394, 395, -1, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, -1, -1, 414, 415, -1, 417, -1, - 419, 420, 421, 422, 423, -1, 425, 426, 427, -1, - -1, 430, 431, 432, 433, 434, -1, 436, 437, 438, - 439, 440, 441, 442, 443, -1, -1, 446, 447, 448, - -1, 450, 451, 452, 453, -1, 455, 456, 457, 458, - 459, 460, 461, -1, 463, -1, 465, 466, 467, 468, - 469, 470, 471, -1, -1, 474, -1, -1, 477, 478, - 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, - 489, 490, 491, 492, 493, 494, 495, 496, 497, 3, + 379, 380, 381, -1, -1, 384, 385, 386, 387, 388, + 389, 390, 391, 392, -1, -1, 395, 396, 397, 398, + -1, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, -1, -1, 417, 418, + -1, 420, -1, 422, 423, 424, 425, 426, -1, 428, + 429, 430, -1, -1, 433, 434, 435, 436, 437, -1, + 439, 440, 441, 442, 443, 444, 445, 446, -1, -1, + 449, 450, 451, -1, 453, 454, 455, 456, -1, 458, + 459, 460, 461, 462, 463, 464, -1, 466, -1, 468, + 469, 470, 471, 472, 473, 474, -1, -1, 477, -1, + -1, 480, 481, 482, 483, 484, 485, 486, 487, 488, + 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, + 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, + 31, 32, 33, -1, -1, -1, 37, -1, -1, -1, + -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, + 51, 52, -1, 54, 55, 56, 57, -1, 59, 60, + 61, 62, 63, 64, -1, -1, 67, 68, 69, 70, + 71, 72, 73, -1, 75, 76, 77, 78, -1, -1, + 81, -1, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, -1, 94, 95, 96, 97, 98, 99, -1, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, -1, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, -1, 153, 154, 155, 156, 157, 158, -1, -1, + 161, -1, 163, 164, 165, 166, -1, 168, -1, 170, + 171, -1, 173, 174, 175, -1, 177, 178, -1, 180, + -1, -1, -1, 184, 185, -1, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, -1, 200, + 201, 202, 203, 204, 205, 206, -1, 208, 209, -1, + 211, 212, 213, 214, 215, 216, 217, -1, 219, -1, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, -1, -1, 234, 235, 236, 237, -1, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 273, -1, -1, 276, 277, 278, 279, -1, + -1, 282, 283, 284, 285, 286, -1, 288, 289, -1, + -1, 292, 293, 294, -1, -1, 297, 298, -1, 300, + 301, 302, -1, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, -1, -1, -1, -1, 319, 320, + -1, 322, 323, 324, -1, 326, 327, 328, -1, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, -1, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + -1, 362, 363, 364, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, -1, 383, 384, 385, 386, 387, 388, 389, 390, + 391, 392, -1, 394, 395, 396, 397, 398, -1, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, -1, -1, -1, 417, 418, -1, 420, + 421, 422, 423, 424, 425, 426, -1, 428, 429, 430, + -1, -1, 433, 434, -1, 436, -1, -1, 439, 440, + 441, 442, 443, 444, 445, 446, 447, -1, 449, 450, + 451, -1, 453, 454, 455, 456, -1, 458, 459, 460, + 461, 462, -1, 464, -1, 466, 467, 468, 469, 470, + 471, 472, 473, 474, -1, -1, 477, -1, -1, 480, + 481, 482, 483, 484, 485, 3, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 497, 498, 499, 500, + -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 31, 32, 33, -1, -1, -1, 37, + -1, -1, -1, -1, 42, 43, 44, -1, 46, 47, + 48, 49, 50, 51, 52, -1, 54, 55, 56, 57, + -1, 59, 60, 61, 62, 63, 64, -1, -1, 67, + 68, 69, 70, 71, 72, 73, -1, 75, 76, 77, + 78, -1, -1, 81, -1, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, -1, 94, 95, 96, 97, + 98, 99, -1, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, -1, + 118, -1, 120, 121, 122, 123, 124, 125, -1, -1, + 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, + 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, + 148, 149, 150, 151, -1, 153, 154, 155, 156, 157, + 158, -1, -1, 161, -1, 163, 164, 165, 166, -1, + 168, -1, 170, 171, -1, 173, 174, 175, -1, 177, + 178, -1, 180, -1, -1, -1, 184, 185, -1, 187, + 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, -1, 200, 201, 202, 203, 204, 205, 206, -1, + 208, 209, -1, 211, 212, 213, 214, 215, 216, 217, + -1, 219, -1, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, -1, -1, 234, 235, 236, 237, + -1, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, 273, -1, -1, 276, 277, + 278, 279, -1, -1, 282, 283, 284, 285, 286, -1, + 288, 289, -1, -1, 292, 293, 294, -1, -1, 297, + 298, -1, 300, 301, 302, -1, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, -1, -1, -1, + -1, 319, 320, -1, 322, 323, 324, -1, 326, 327, + 328, -1, 330, 331, 332, 333, 334, 335, -1, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, -1, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, + 358, 359, 360, -1, 362, 363, 364, 365, 366, 367, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, -1, 383, 384, 385, 386, 387, + 388, 389, 390, 391, 392, -1, 394, 395, 396, 397, + 398, -1, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, -1, -1, -1, 417, + 418, -1, 420, 421, 422, 423, 424, 425, 426, -1, + 428, 429, 430, -1, -1, 433, 434, -1, 436, -1, + -1, 439, 440, 441, 442, 443, 444, 445, 446, 447, + -1, 449, 450, 451, -1, 453, 454, 455, 456, -1, + 458, 459, 460, 461, 462, -1, 464, -1, 466, 467, + 468, 469, 470, 471, 472, 473, 474, -1, -1, 477, + -1, -1, 480, 481, 482, 483, 484, 485, 3, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 497, + 498, 499, 500, -1, -1, -1, -1, 22, 23, 24, + 25, 26, 27, 28, 29, -1, 31, 32, 33, -1, + -1, -1, 37, -1, -1, -1, -1, 42, 43, 44, + -1, 46, 47, 48, 49, 50, 51, 52, -1, 54, + 55, 56, 57, -1, 59, 60, 61, 62, 63, 64, + -1, -1, 67, 68, 69, 70, 71, 72, 73, -1, + 75, 76, 77, 78, -1, -1, 81, -1, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, -1, 94, + 95, 96, 97, 98, 99, -1, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, -1, 118, -1, 120, 121, 122, 123, 124, + 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, + 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, + 145, 146, -1, 148, 149, 150, 151, -1, 153, 154, + 155, 156, 157, 158, -1, -1, 161, -1, 163, 164, + 165, 166, -1, 168, -1, 170, 171, -1, 173, 174, + 175, 176, 177, 178, -1, 180, -1, -1, -1, 184, + 185, -1, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, -1, 200, 201, 202, 203, 204, + 205, 206, -1, 208, 209, -1, 211, 212, 213, 214, + 215, 216, 217, -1, 219, -1, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, -1, -1, 234, + 235, 236, 237, -1, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, -1, + -1, 276, 277, 278, 279, -1, -1, 282, 283, 284, + 285, 286, -1, 288, 289, -1, -1, 292, 293, 294, + -1, -1, 297, 298, -1, 300, 301, 302, -1, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + -1, -1, -1, -1, 319, 320, -1, 322, 323, 324, + -1, 326, 327, 328, -1, 330, 331, 332, 333, 334, + 335, -1, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, -1, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, -1, 362, 363, 364, + 365, 366, 367, -1, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, -1, 383, 384, + 385, 386, 387, 388, 389, -1, 391, 392, -1, 394, + 395, 396, 397, 398, -1, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, -1, + -1, -1, 417, 418, -1, 420, 421, 422, 423, 424, + 425, 426, -1, 428, 429, 430, -1, -1, 433, 434, + -1, 436, -1, -1, 439, 440, 441, 442, 443, 444, + 445, 446, -1, -1, 449, 450, 451, -1, 453, 454, + 455, 456, -1, 458, 459, 460, 461, 462, -1, 464, + -1, 466, 467, 468, 469, 470, 471, 472, 473, 474, + -1, -1, 477, -1, -1, 480, 481, 482, 483, 484, + 485, 3, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 497, 498, 499, 500, -1, -1, -1, -1, + 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, + 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 43, 44, -1, 46, 47, 48, -1, 50, 51, + 52, 53, 54, -1, 56, 57, -1, 59, 60, 61, + 62, 63, 64, -1, -1, 67, 68, 69, 70, 71, + 72, 73, -1, 75, 76, 77, 78, 79, -1, -1, + -1, 83, 84, 85, 86, 87, 88, -1, 90, 91, + 92, -1, 94, 95, 96, 97, 98, 99, -1, -1, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, -1, 118, -1, 120, 121, + 122, 123, 124, 125, -1, -1, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, + -1, 163, 164, 165, 166, -1, 168, -1, 170, -1, + -1, -1, 174, 175, 176, -1, 178, -1, 180, -1, + 182, 183, -1, 185, -1, 187, 188, 189, 190, 191, + 192, 193, -1, 195, 196, 197, 198, -1, 200, 201, + 202, 203, 204, 205, 206, -1, 208, -1, 210, 211, + 212, 213, 214, 215, 216, 217, -1, 219, -1, 221, + -1, -1, 224, -1, 226, 227, 228, 229, 230, 231, + -1, -1, 234, -1, 236, -1, -1, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, -1, 270, 271, + 272, 273, 274, -1, 276, 277, -1, 279, -1, 281, + 282, 283, 284, 285, 286, -1, 288, 289, -1, -1, + 292, 293, 294, -1, -1, 297, 298, 299, -1, 301, + -1, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, -1, -1, -1, -1, 319, 320, 321, + -1, 323, 324, 325, 326, 327, 328, -1, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, -1, 341, + 342, 343, 344, 345, 346, -1, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, -1, + 362, 363, -1, 365, 366, 367, 368, -1, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + -1, -1, 384, 385, 386, 387, 388, 389, 390, 391, + 392, -1, -1, 395, 396, 397, 398, -1, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, -1, -1, 417, 418, -1, 420, -1, + 422, 423, 424, 425, 426, -1, 428, 429, 430, -1, + -1, 433, 434, 435, 436, 437, -1, 439, 440, 441, + 442, 443, 444, 445, 446, -1, -1, 449, 450, 451, + -1, 453, 454, 455, 456, -1, 458, 459, 460, 461, + 462, 463, 464, -1, 466, -1, 468, 469, 470, 471, + 472, 473, 474, -1, -1, 477, -1, -1, 480, 481, + 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, + 492, 493, 494, 495, 496, 497, 498, 499, 500, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, @@ -18755,539 +17601,952 @@ static const yytype_int16 yycheck[] = 124, 125, -1, -1, 128, 129, 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, -1, 153, - 154, 155, 156, 157, -1, -1, 160, -1, 162, 163, - 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, - 174, -1, 176, 177, -1, 179, -1, -1, -1, 183, - 184, -1, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, -1, 199, 200, 201, 202, 203, - 204, 205, -1, 207, 208, -1, 210, 211, 212, 213, - 214, 215, 216, -1, 218, -1, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, -1, -1, 233, - 234, 235, 236, -1, 238, 239, 240, 241, 242, 243, - 244, 245, -1, 247, 248, 249, 250, 251, 252, 253, + 154, 155, 156, 157, 158, -1, -1, 161, -1, 163, + 164, 165, 166, -1, 168, -1, 170, 171, -1, 173, + 174, 175, -1, 177, 178, -1, 180, -1, -1, -1, + 184, 185, -1, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, -1, 200, 201, 202, 203, + 204, 205, 206, -1, 208, 209, -1, 211, 212, 213, + 214, 215, 216, 217, -1, 219, -1, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, -1, -1, + 234, 235, 236, 237, -1, 239, 240, 241, 242, 243, + 244, 245, 246, -1, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, -1, - -1, 275, 276, 277, 278, -1, -1, 281, 282, 283, - 284, 285, -1, 287, 288, -1, -1, 291, 292, 293, - -1, -1, 296, 297, -1, 299, 300, 301, -1, 303, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, + -1, -1, 276, 277, 278, 279, -1, -1, 282, 283, + 284, 285, 286, -1, 288, 289, -1, -1, 292, 293, + 294, -1, -1, 297, 298, -1, 300, 301, 302, -1, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - -1, -1, -1, -1, 318, 319, -1, 321, 322, 323, - -1, 325, 326, 327, -1, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - -1, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, -1, 359, 360, 361, 362, 363, - 364, -1, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, -1, 380, 381, 382, 383, - 384, 385, 386, -1, 388, 389, -1, 391, 392, 393, - 394, 395, -1, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, -1, 410, -1, -1, -1, - 414, 415, -1, 417, 418, 419, 420, 421, 422, 423, - -1, 425, 426, 427, -1, -1, 430, 431, -1, 433, - -1, -1, 436, 437, 438, 439, 440, 441, 442, 443, - -1, -1, 446, 447, 448, -1, 450, 451, 452, 453, - -1, 455, 456, 457, 458, 459, -1, 461, -1, 463, - 464, 465, 466, 467, 468, 469, 470, 471, -1, 22, - 474, -1, -1, 477, 478, 479, 480, 481, 482, 32, - -1, 34, 35, -1, -1, -1, -1, 22, -1, -1, - 494, 495, 496, 497, -1, -1, -1, 32, -1, 52, - -1, -1, -1, -1, -1, -1, -1, -1, 61, -1, - -1, -1, -1, -1, -1, -1, -1, 52, -1, -1, - -1, -1, 75, -1, -1, -1, 61, -1, -1, -1, - -1, -1, -1, 86, -1, -1, -1, -1, -1, -1, - 75, -1, -1, -1, -1, 98, -1, 100, -1, -1, - -1, 86, -1, -1, -1, -1, -1, -1, 111, -1, - -1, -1, -1, 98, -1, 100, -1, -1, -1, -1, - -1, -1, -1, 126, 127, -1, 111, -1, -1, -1, - -1, -1, -1, -1, 137, -1, -1, -1, -1, -1, - 143, 126, 127, -1, -1, -1, -1, -1, 151, -1, - -1, -1, 137, -1, -1, -1, -1, -1, 143, -1, - -1, -1, -1, -1, 167, -1, 151, -1, 171, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 167, -1, -1, -1, 171, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 213, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 213, -1, - -1, -1, -1, -1, -1, -1, 239, -1, -1, -1, + 314, -1, -1, -1, -1, 319, 320, -1, 322, 323, + 324, -1, 326, 327, 328, -1, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, -1, 348, 349, 350, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, -1, 362, 363, + 364, 365, 366, 367, -1, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, -1, 383, + 384, 385, 386, 387, 388, 389, -1, 391, 392, -1, + 394, 395, 396, 397, 398, -1, 400, 401, 402, 403, + 404, 405, 406, 407, 408, 409, 410, 411, -1, 413, + -1, -1, -1, 417, 418, -1, 420, 421, 422, 423, + 424, 425, 426, -1, 428, 429, 430, -1, -1, 433, + 434, -1, 436, -1, -1, 439, 440, 441, 442, 443, + 444, 445, 446, -1, -1, 449, 450, 451, -1, 453, + 454, 455, 456, -1, 458, 459, 460, 461, 462, -1, + 464, -1, 466, 467, 468, 469, 470, 471, 472, 473, + 474, -1, 22, 477, -1, -1, 480, 481, 482, 483, + 484, 485, 32, -1, 34, 35, -1, -1, -1, -1, + 22, -1, -1, 497, 498, 499, 500, -1, -1, -1, + 32, -1, 52, -1, -1, -1, -1, -1, -1, -1, + -1, 61, -1, -1, -1, -1, -1, -1, -1, -1, + 52, -1, -1, -1, -1, 75, -1, -1, -1, 61, + -1, -1, -1, -1, -1, -1, 86, -1, -1, -1, + -1, -1, -1, 75, -1, -1, -1, -1, 98, -1, + 100, -1, -1, -1, 86, -1, -1, -1, -1, -1, + -1, 111, -1, -1, -1, -1, 98, -1, 100, -1, + -1, -1, -1, -1, -1, -1, 126, 127, -1, 111, + -1, -1, -1, -1, -1, -1, -1, 137, -1, -1, + -1, -1, -1, 143, 126, 127, -1, -1, -1, -1, + -1, 151, -1, -1, -1, 137, -1, -1, -1, -1, + -1, 143, -1, -1, -1, -1, -1, -1, 168, 151, + -1, -1, 172, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 168, -1, -1, -1, + 172, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 239, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 214, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 214, -1, -1, -1, -1, -1, -1, -1, + 240, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 314, 315, 316, -1, -1, -1, -1, -1, 322, - -1, -1, 325, -1, -1, -1, -1, -1, -1, 314, - 315, 316, -1, -1, -1, -1, -1, 322, -1, -1, - 325, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 354, -1, -1, -1, -1, -1, -1, -1, -1, - 363, -1, -1, -1, -1, -1, -1, -1, -1, 354, - -1, -1, -1, -1, -1, -1, 379, -1, 363, -1, - -1, -1, -1, 386, -1, -1, -1, 390, -1, -1, - -1, -1, -1, -1, 379, -1, -1, 400, -1, -1, - -1, 386, -1, -1, -1, 390, -1, -1, -1, 412, - -1, -1, -1, 416, -1, 400, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 412, -1, -1, - -1, 416, -1, 436, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 449, -1, -1, -1, - -1, 436, 455, -1, -1, -1, -1, 460, -1, -1, - -1, 464, -1, -1, 449, -1, -1, -1, -1, -1, - 455, -1, -1, 476, -1, 460, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 476, -1, -1, -1, -1, -1, 500, -1, -1, + -1, -1, -1, -1, -1, 315, 316, 317, -1, -1, + -1, -1, -1, 323, -1, -1, 326, -1, -1, -1, + -1, -1, -1, 315, 316, 317, -1, -1, -1, -1, + -1, 323, -1, -1, 326, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 357, -1, -1, + -1, -1, -1, -1, -1, -1, 366, -1, -1, -1, + -1, -1, -1, -1, -1, 357, -1, -1, -1, -1, + -1, -1, 382, -1, 366, -1, -1, -1, -1, 389, + -1, -1, -1, 393, -1, -1, -1, -1, -1, -1, + 382, -1, -1, 403, -1, -1, -1, 389, -1, -1, + -1, 393, -1, -1, -1, 415, -1, -1, -1, 419, + -1, 403, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 415, -1, -1, -1, 419, -1, 439, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 514, -1, -1, -1, 500, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 514 + -1, -1, 452, -1, -1, -1, -1, 439, 458, -1, + -1, -1, -1, 463, -1, -1, -1, 467, -1, -1, + 452, -1, -1, -1, -1, -1, 458, -1, -1, 479, + -1, 463, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 479, -1, -1, + -1, -1, -1, 503, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 517, -1, -1, + -1, 503, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 517 }; -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint16 yystos[] = +/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + state STATE-NUM. */ +static const yytype_int16 yystos[] = { 0, 22, 32, 34, 35, 47, 52, 61, 75, 84, 86, 98, 100, 111, 126, 127, 128, 137, 143, 151, - 153, 154, 167, 171, 197, 213, 239, 314, 315, 316, - 322, 325, 354, 363, 379, 386, 390, 400, 412, 416, - 436, 449, 452, 455, 460, 476, 500, 514, 526, 527, - 528, 529, 540, 549, 551, 556, 572, 575, 576, 578, - 582, 586, 593, 595, 597, 598, 646, 652, 655, 656, - 674, 675, 676, 677, 679, 681, 682, 686, 739, 740, - 908, 911, 914, 921, 922, 924, 927, 928, 929, 936, - 940, 946, 949, 954, 958, 959, 960, 963, 966, 967, - 968, 972, 973, 975, 430, 479, 596, 202, 370, 381, - 416, 466, 108, 191, 961, 596, 3, 22, 23, 24, - 25, 26, 27, 28, 29, 31, 32, 33, 42, 43, - 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 59, 60, 61, 62, 63, 64, 67, - 68, 69, 70, 71, 72, 73, 75, 76, 77, 78, - 79, 81, 83, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 94, 95, 96, 97, 98, 99, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 118, 120, 121, 122, 123, 124, - 125, 128, 129, 130, 131, 134, 135, 136, 137, 138, - 140, 141, 142, 144, 145, 146, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 160, 162, 163, - 164, 165, 167, 169, 170, 172, 173, 174, 175, 176, - 177, 179, 181, 182, 183, 184, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 199, 200, - 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 218, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 233, 234, 235, - 236, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 275, 276, 277, - 278, 280, 281, 282, 283, 284, 285, 287, 288, 291, - 292, 293, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 329, 330, 331, 332, 333, 334, 336, 337, 338, 339, - 340, 341, 342, 343, 345, 346, 347, 348, 349, 350, - 351, 352, 353, 354, 355, 356, 357, 359, 360, 361, - 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 381, 382, 383, - 384, 385, 386, 387, 388, 389, 391, 392, 393, 394, - 395, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 409, 410, 411, 414, 415, 417, 418, - 419, 420, 421, 422, 423, 425, 426, 427, 430, 431, - 432, 433, 434, 436, 437, 438, 439, 440, 441, 442, - 443, 446, 447, 448, 450, 451, 452, 453, 455, 456, - 457, 458, 459, 460, 461, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 474, 477, 478, 479, 480, 481, - 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, - 492, 493, 494, 495, 496, 497, 542, 817, 897, 901, - 978, 979, 980, 3, 175, 246, 409, 542, 923, 978, - 289, 596, 55, 171, 514, 669, 177, 240, 294, 313, - 370, 420, 422, 439, 445, 448, 580, 644, 920, 5, - 30, 325, 542, 543, 896, 3, 30, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 45, 49, 53, 54, - 55, 56, 57, 58, 65, 66, 71, 72, 74, 79, - 80, 81, 82, 83, 89, 93, 100, 101, 108, 112, - 115, 117, 119, 126, 127, 132, 133, 139, 143, 147, - 152, 158, 159, 161, 164, 166, 168, 170, 171, 172, - 175, 176, 178, 180, 181, 182, 185, 193, 198, 206, - 208, 209, 215, 216, 217, 218, 219, 221, 222, 224, - 231, 232, 234, 236, 237, 246, 267, 268, 269, 273, - 274, 277, 279, 280, 282, 286, 289, 290, 294, 295, - 298, 299, 301, 302, 314, 315, 316, 317, 320, 321, - 324, 328, 335, 339, 344, 358, 361, 365, 379, 380, - 387, 390, 391, 394, 396, 409, 411, 412, 413, 416, - 418, 424, 426, 427, 428, 429, 432, 434, 435, 438, - 444, 445, 449, 454, 460, 461, 462, 464, 472, 473, - 475, 476, 483, 484, 485, 486, 487, 488, 489, 490, - 491, 492, 493, 548, 978, 982, 984, 24, 81, 97, - 146, 156, 168, 173, 202, 245, 249, 319, 334, 367, - 370, 381, 384, 402, 416, 422, 423, 433, 439, 466, - 580, 647, 648, 651, 596, 896, 100, 137, 464, 514, - 529, 540, 549, 551, 572, 575, 576, 582, 586, 595, - 598, 646, 652, 655, 656, 674, 908, 911, 914, 921, - 922, 932, 936, 940, 946, 949, 954, 963, 966, 972, - 973, 975, 108, 75, 213, 66, 79, 81, 158, 231, - 280, 290, 302, 320, 366, 411, 432, 434, 438, 460, - 514, 541, 542, 543, 675, 740, 742, 744, 754, 761, - 762, 817, 819, 820, 108, 5, 542, 544, 947, 947, - 542, 896, 30, 177, 240, 385, 426, 430, 542, 964, - 965, 970, 596, 30, 132, 695, 696, 177, 240, 370, - 385, 426, 941, 942, 970, 596, 542, 674, 686, 971, - 542, 761, 416, 692, 541, 172, 514, 951, 514, 342, - 687, 688, 896, 687, 675, 676, 966, 0, 517, 122, - 212, 451, 147, 217, 295, 444, 698, 699, 744, 744, - 675, 677, 679, 518, 464, 930, 30, 426, 430, 674, - 971, 191, 541, 896, 191, 541, 191, 761, 191, 541, - 274, 544, 512, 516, 545, 546, 514, 82, 108, 173, - 202, 245, 370, 381, 416, 439, 466, 926, 108, 674, - 541, 420, 422, 420, 422, 352, 191, 541, 541, 377, - 173, 245, 342, 381, 416, 466, 653, 202, 30, 896, - 191, 548, 251, 433, 107, 416, 416, 466, 374, 377, - 191, 542, 649, 903, 191, 893, 896, 191, 896, 514, - 585, 294, 422, 932, 3, 460, 933, 935, 936, 938, - 939, 978, 982, 930, 542, 544, 923, 947, 514, 514, - 166, 514, 675, 762, 514, 514, 541, 514, 514, 171, - 514, 514, 514, 514, 675, 740, 744, 754, 507, 545, - 40, 542, 755, 756, 755, 379, 518, 678, 37, 42, - 101, 172, 208, 224, 234, 268, 314, 321, 361, 380, - 449, 758, 756, 40, 542, 755, 757, 500, 766, 544, - 171, 503, 514, 514, 909, 965, 965, 965, 497, 223, - 516, 289, 4, 6, 7, 8, 9, 10, 39, 54, - 56, 57, 65, 71, 72, 83, 112, 115, 117, 136, - 152, 159, 164, 181, 182, 215, 216, 218, 246, 267, - 269, 274, 279, 282, 291, 339, 365, 394, 426, 427, - 435, 461, 498, 505, 506, 507, 512, 514, 519, 520, - 522, 523, 542, 544, 675, 729, 778, 781, 784, 785, - 786, 788, 789, 790, 791, 793, 794, 809, 811, 812, - 813, 814, 815, 816, 817, 818, 820, 821, 836, 837, - 848, 870, 875, 883, 884, 885, 897, 898, 899, 882, - 884, 941, 941, 544, 941, 497, 171, 428, 503, 516, - 545, 761, 955, 3, 170, 172, 464, 936, 950, 952, - 170, 953, 809, 854, 855, 687, 518, 514, 905, 515, - 515, 515, 528, 171, 294, 559, 955, 30, 132, 693, - 693, 59, 693, 161, 166, 237, 286, 704, 706, 707, - 732, 734, 735, 736, 180, 289, 454, 289, 698, 699, - 514, 541, 417, 969, 497, 223, 152, 26, 32, 137, - 293, 350, 354, 386, 457, 534, 537, 538, 350, 152, - 40, 60, 106, 201, 250, 260, 272, 304, 350, 356, - 381, 386, 400, 537, 587, 590, 152, 350, 386, 537, - 152, 350, 386, 537, 152, 40, 962, 809, 876, 547, - 548, 546, 3, 30, 37, 42, 49, 55, 81, 83, - 89, 101, 132, 170, 172, 175, 176, 193, 208, 221, - 222, 224, 234, 236, 246, 268, 277, 299, 301, 321, - 361, 380, 391, 409, 418, 438, 462, 464, 515, 809, - 857, 858, 900, 906, 978, 983, 809, 416, 541, 542, - 515, 514, 633, 370, 580, 644, 274, 912, 40, 191, - 542, 579, 466, 191, 541, 191, 541, 977, 191, 541, - 191, 541, 89, 917, 152, 480, 90, 129, 307, 421, - 191, 542, 152, 516, 904, 63, 357, 518, 650, 152, - 518, 650, 152, 289, 583, 584, 809, 906, 352, 515, - 518, 4, 159, 289, 435, 505, 506, 544, 589, 592, - 899, 931, 933, 934, 937, 932, 428, 514, 664, 668, - 171, 809, 855, 514, 3, 68, 69, 109, 110, 113, - 114, 188, 189, 252, 253, 254, 255, 256, 257, 258, - 259, 262, 263, 375, 376, 470, 471, 494, 495, 544, - 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, - 806, 807, 860, 861, 756, 757, 809, 541, 809, 862, - 505, 506, 542, 810, 811, 837, 848, 864, 514, 809, - 854, 865, 809, 58, 171, 232, 429, 809, 855, 868, - 809, 515, 543, 514, 418, 712, 713, 713, 695, 696, - 744, 219, 690, 224, 37, 224, 380, 758, 224, 299, - 759, 744, 759, 224, 758, 514, 224, 759, 224, 148, - 199, 746, 224, 713, 514, 543, 514, 713, 296, 542, - 544, 948, 809, 943, 945, 857, 3, 37, 42, 49, - 54, 55, 56, 57, 71, 72, 81, 83, 89, 101, - 112, 115, 164, 170, 172, 176, 193, 208, 215, 216, - 218, 221, 222, 224, 234, 236, 246, 267, 268, 269, - 277, 282, 299, 301, 321, 339, 361, 365, 380, 387, - 391, 394, 409, 418, 426, 427, 438, 444, 461, 464, - 772, 774, 775, 777, 779, 781, 783, 785, 786, 787, - 789, 790, 793, 794, 859, 902, 978, 981, 40, 235, - 542, 514, 512, 675, 463, 792, 809, 874, 792, 792, - 514, 514, 780, 780, 324, 675, 514, 782, 520, 71, - 72, 792, 809, 780, 514, 514, 478, 500, 514, 795, - 514, 795, 809, 809, 809, 148, 886, 887, 809, 855, - 856, 675, 809, 854, 543, 838, 839, 840, 9, 548, - 516, 545, 877, 545, 514, 544, 514, 514, 544, 899, - 3, 8, 11, 15, 16, 17, 18, 19, 20, 21, - 36, 40, 46, 53, 80, 176, 193, 198, 221, 222, - 236, 274, 277, 291, 294, 391, 498, 501, 502, 503, - 505, 506, 507, 508, 509, 510, 846, 847, 848, 850, - 880, 477, 822, 301, 809, 518, 690, 514, 544, 690, - 3, 117, 240, 544, 589, 794, 944, 104, 945, 945, - 542, 40, 542, 515, 518, 930, 518, 515, 688, 893, - 894, 40, 955, 192, 352, 219, 386, 677, 677, 30, - 700, 701, 809, 59, 677, 694, 163, 271, 720, 226, - 272, 338, 389, 451, 4, 9, 30, 715, 809, 505, - 506, 716, 717, 809, 811, 732, 733, 707, 706, 704, - 705, 166, 735, 284, 737, 59, 683, 684, 685, 747, - 810, 884, 884, 704, 732, 855, 905, 235, 541, 74, - 82, 93, 168, 191, 328, 445, 542, 615, 625, 640, - 82, 93, 550, 93, 550, 514, 428, 514, 613, 244, - 448, 613, 93, 518, 428, 541, 3, 777, 589, 59, - 591, 589, 589, 106, 250, 260, 59, 428, 476, 500, - 588, 265, 370, 588, 590, 761, 93, 428, 550, 370, - 541, 428, 370, 961, 542, 664, 513, 524, 857, 857, - 858, 518, 698, 699, 13, 14, 221, 221, 428, 428, - 542, 632, 637, 476, 667, 541, 377, 342, 381, 416, - 466, 653, 152, 100, 576, 598, 913, 914, 973, 144, - 774, 274, 198, 581, 541, 274, 577, 587, 274, 514, - 633, 40, 274, 633, 274, 514, 654, 191, 542, 627, - 918, 548, 152, 171, 594, 649, 547, 516, 903, 893, - 896, 896, 903, 515, 518, 13, 932, 938, 4, 899, - 4, 899, 544, 548, 666, 673, 55, 102, 123, 141, - 145, 167, 170, 186, 279, 287, 309, 336, 670, 948, - 40, 515, 809, 515, 171, 518, 515, 317, 863, 515, - 810, 810, 11, 15, 16, 19, 20, 21, 198, 221, - 291, 501, 502, 503, 505, 506, 507, 508, 509, 510, - 848, 810, 515, 763, 764, 819, 166, 171, 866, 867, - 518, 515, 40, 868, 855, 868, 868, 171, 515, 40, - 755, 514, 894, 4, 9, 542, 708, 710, 711, 884, - 882, 177, 240, 416, 420, 422, 448, 541, 691, 473, - 767, 744, 744, 224, 744, 289, 454, 760, 744, 224, - 884, 744, 744, 281, 281, 514, 744, 543, 768, 769, - 514, 543, 768, 518, 515, 518, 516, 514, 777, 514, - 514, 516, 39, 776, 514, 796, 797, 798, 799, 800, - 801, 802, 803, 804, 805, 806, 807, 808, 515, 518, - 780, 551, 655, 656, 674, 910, 954, 966, 855, 856, - 514, 472, 871, 872, 809, 856, 899, 809, 841, 842, - 843, 844, 792, 792, 8, 15, 16, 19, 20, 21, - 501, 502, 503, 505, 506, 507, 508, 509, 510, 542, - 846, 851, 515, 855, 426, 426, 899, 899, 514, 542, - 352, 891, 166, 513, 515, 518, 524, 518, 521, 507, - 546, 855, 899, 809, 808, 808, 774, 809, 809, 809, - 809, 809, 809, 809, 809, 5, 548, 907, 426, 45, - 413, 881, 903, 809, 809, 514, 675, 869, 132, 159, - 274, 279, 284, 435, 446, 809, 279, 514, 809, 428, - 53, 176, 193, 198, 236, 391, 809, 809, 809, 809, - 809, 809, 809, 809, 809, 809, 30, 38, 396, 845, - 512, 516, 879, 180, 162, 823, 365, 514, 837, 885, - 171, 741, 857, 741, 514, 544, 542, 541, 950, 541, - 958, 809, 518, 515, 249, 274, 689, 454, 957, 541, - 553, 514, 542, 558, 568, 569, 571, 41, 126, 702, - 518, 454, 702, 265, 677, 365, 366, 505, 506, 717, - 719, 811, 389, 226, 290, 312, 312, 518, 509, 4, - 718, 899, 718, 365, 366, 719, 541, 892, 278, 393, - 738, 514, 894, 895, 518, 180, 454, 198, 180, 219, - 733, 705, 515, 350, 537, 514, 191, 625, 896, 226, - 274, 226, 454, 514, 618, 773, 774, 896, 542, 191, - 896, 191, 542, 26, 137, 386, 533, 536, 548, 609, - 623, 896, 548, 617, 636, 896, 534, 896, 350, 386, - 537, 587, 589, 903, 896, 589, 903, 896, 589, 350, - 386, 537, 896, 896, 896, 896, 350, 386, 537, 896, - 896, 544, 506, 809, 876, 698, 698, 698, 462, 858, - 192, 355, 697, 809, 809, 279, 544, 925, 279, 925, - 542, 333, 663, 515, 518, 287, 171, 428, 658, 912, - 579, 466, 541, 541, 977, 541, 541, 541, 294, 644, - 514, 675, 152, 3, 514, 514, 152, 152, 236, 542, - 615, 625, 628, 631, 641, 643, 476, 478, 620, 151, - 674, 152, 476, 919, 152, 515, 857, 40, 274, 289, - 542, 3, 650, 547, 650, 289, 650, 583, 809, 664, - 507, 512, 514, 589, 665, 815, 816, 937, 515, 518, - 40, 662, 544, 662, 274, 279, 336, 662, 59, 662, - 774, 515, 809, 809, 809, 866, 774, 810, 810, 810, - 810, 810, 810, 132, 274, 284, 810, 810, 810, 810, - 810, 810, 810, 810, 810, 810, 515, 518, 40, 765, - 809, 809, 867, 866, 774, 515, 515, 515, 855, 774, - 894, 515, 312, 509, 312, 366, 509, 514, 514, 690, - 420, 422, 420, 422, 541, 692, 692, 692, 809, 180, - 721, 760, 760, 744, 809, 514, 744, 166, 760, 514, - 543, 751, 760, 774, 515, 518, 768, 515, 943, 3, - 859, 39, 776, 542, 771, 771, 3, 512, 512, 899, - 428, 428, 428, 428, 774, 515, 513, 855, 809, 139, - 872, 873, 515, 515, 515, 524, 518, 521, 516, 515, - 515, 497, 497, 515, 515, 894, 514, 809, 888, 542, - 809, 809, 838, 887, 515, 515, 515, 497, 810, 810, - 145, 855, 171, 132, 159, 279, 284, 435, 446, 514, - 145, 851, 809, 413, 881, 809, 869, 809, 428, 514, - 675, 809, 876, 547, 514, 514, 155, 824, 742, 743, - 767, 698, 767, 899, 808, 905, 905, 249, 514, 743, - 473, 956, 40, 59, 554, 564, 571, 877, 518, 741, - 503, 499, 703, 701, 291, 846, 849, 703, 4, 899, - 719, 290, 451, 716, 518, 243, 894, 683, 59, 884, - 514, 543, 59, 265, 428, 809, 274, 640, 514, 152, - 514, 618, 202, 637, 638, 599, 40, 175, 608, 634, - 599, 26, 137, 354, 356, 386, 530, 531, 532, 538, - 539, 152, 650, 152, 650, 609, 623, 609, 515, 518, - 544, 602, 503, 516, 515, 518, 428, 370, 93, 428, - 550, 370, 428, 428, 428, 370, 962, 524, 513, 524, - 697, 697, 697, 858, 281, 281, 515, 514, 657, 3, - 403, 404, 544, 672, 632, 663, 581, 541, 577, 514, - 40, 633, 654, 912, 352, 416, 544, 573, 574, 579, - 673, 637, 541, 541, 977, 541, 515, 518, 287, 613, - 287, 289, 612, 896, 476, 976, 541, 613, 40, 541, - 515, 416, 809, 152, 541, 594, 903, 660, 671, 937, - 666, 544, 544, 279, 637, 507, 637, 544, 507, 637, - 544, 515, 515, 867, 171, 132, 284, 514, 766, 763, - 514, 515, 515, 515, 542, 708, 767, 692, 692, 692, - 692, 541, 541, 541, 59, 185, 730, 760, 894, 514, - 748, 749, 750, 812, 814, 894, 166, 80, 770, 769, - 515, 515, 512, 774, 515, 518, 515, 899, 513, 899, - 515, 797, 799, 800, 801, 800, 801, 801, 515, 424, - 809, 143, 809, 841, 851, 795, 795, 515, 809, 888, - 889, 890, 40, 198, 515, 891, 808, 809, 36, 36, - 809, 515, 809, 171, 514, 859, 809, 515, 145, 810, - 810, 145, 145, 809, 809, 513, 524, 514, 878, 699, - 473, 809, 300, 828, 518, 721, 697, 721, 515, 910, - 809, 358, 562, 542, 265, 320, 117, 303, 514, 552, - 674, 515, 518, 558, 956, 809, 163, 230, 514, 703, - 290, 541, 515, 895, 180, 675, 676, 884, 895, 896, - 896, 515, 152, 638, 625, 638, 599, 627, 518, 515, - 119, 206, 272, 274, 624, 514, 33, 59, 645, 634, - 74, 80, 93, 117, 119, 206, 274, 279, 328, 344, - 445, 454, 604, 605, 619, 175, 117, 190, 274, 613, - 588, 107, 117, 175, 274, 402, 405, 590, 613, 386, - 532, 439, 896, 542, 536, 3, 37, 42, 49, 55, - 81, 83, 89, 101, 170, 172, 175, 176, 193, 208, - 221, 222, 224, 234, 236, 246, 268, 273, 277, 291, - 299, 301, 321, 361, 380, 387, 391, 409, 418, 438, - 444, 464, 505, 506, 544, 589, 600, 639, 774, 849, - 900, 978, 984, 548, 636, 896, 896, 896, 896, 896, - 896, 896, 896, 896, 896, 664, 876, 876, 515, 515, - 515, 698, 107, 370, 516, 588, 672, 514, 514, 631, - 674, 919, 40, 644, 191, 541, 515, 518, 581, 515, - 515, 577, 514, 40, 622, 620, 628, 86, 585, 107, - 272, 633, 674, 654, 674, 627, 454, 916, 650, 515, - 518, 637, 810, 171, 514, 859, 768, 515, 518, 515, - 721, 541, 541, 541, 541, 30, 103, 181, 364, 514, - 722, 723, 724, 725, 726, 727, 728, 809, 809, 475, - 825, 515, 811, 852, 853, 198, 180, 745, 749, 515, - 751, 752, 753, 903, 776, 899, 776, 542, 776, 513, - 513, 809, 518, 515, 542, 809, 811, 809, 809, 809, - 859, 515, 809, 36, 36, 809, 809, 145, 515, 506, - 876, 515, 857, 515, 809, 515, 514, 542, 829, 730, - 515, 730, 544, 515, 883, 460, 415, 453, 563, 542, - 557, 567, 289, 560, 503, 571, 562, 851, 59, 515, - 515, 459, 460, 680, 599, 625, 515, 515, 476, 630, - 120, 194, 204, 119, 456, 809, 117, 40, 514, 903, - 896, 810, 120, 194, 119, 279, 226, 541, 630, 88, - 645, 191, 279, 589, 809, 645, 279, 505, 506, 592, - 542, 774, 650, 650, 3, 246, 409, 900, 904, 503, - 428, 428, 513, 513, 697, 515, 515, 542, 664, 454, - 659, 661, 673, 637, 515, 976, 40, 416, 809, 416, - 274, 514, 544, 514, 919, 631, 151, 674, 149, 200, - 612, 122, 137, 327, 976, 107, 919, 476, 974, 40, - 289, 542, 915, 514, 671, 810, 859, 515, 515, 9, - 351, 714, 730, 514, 388, 514, 515, 518, 542, 826, - 827, 335, 731, 518, 515, 514, 543, 59, 515, 198, - 515, 752, 513, 774, 888, 513, 191, 515, 809, 809, - 809, 524, 513, 524, 515, 515, 542, 830, 825, 544, - 825, 518, 459, 877, 515, 518, 91, 562, 809, 515, - 895, 895, 344, 630, 514, 621, 599, 515, 190, 514, - 809, 274, 605, 630, 633, 896, 40, 152, 770, 904, - 509, 600, 896, 896, 515, 588, 124, 515, 515, 620, - 674, 674, 541, 152, 673, 40, 515, 896, 976, 30, - 85, 94, 118, 190, 203, 402, 405, 616, 616, 366, - 366, 40, 64, 74, 240, 416, 809, 541, 514, 542, - 561, 570, 819, 515, 515, 514, 825, 855, 514, 855, - 724, 40, 518, 809, 454, 709, 811, 884, 894, 756, - 514, 756, 809, 876, 876, 309, 831, 731, 731, 674, - 303, 674, 557, 289, 514, 555, 541, 599, 548, 626, - 629, 406, 468, 606, 607, 514, 601, 809, 515, 248, - 642, 190, 454, 535, 509, 439, 664, 544, 919, 612, - 974, 514, 541, 515, 674, 620, 585, 674, 74, 292, - 74, 674, 916, 809, 80, 565, 515, 518, 565, 9, - 731, 515, 723, 515, 829, 827, 368, 515, 884, 513, - 513, 513, 59, 698, 709, 709, 563, 93, 570, 133, - 633, 503, 515, 518, 587, 515, 272, 614, 172, 308, - 392, 289, 610, 611, 635, 601, 809, 439, 40, 514, - 974, 612, 976, 974, 292, 292, 514, 515, 903, 566, - 903, 919, 561, 566, 515, 709, 515, 711, 515, 854, - 183, 337, 366, 832, 459, 896, 515, 275, 451, 642, - 600, 629, 515, 607, 204, 122, 451, 289, 635, 289, - 610, 674, 570, 565, 702, 767, 702, 53, 104, 441, - 809, 833, 834, 833, 833, 515, 674, 767, 386, 611, - 63, 272, 357, 386, 603, 603, 974, 515, 566, 703, - 703, 834, 365, 165, 323, 165, 323, 148, 835, 835, - 835, 569, 599, 25, 117, 279, 919, 702, 36, 104, - 180, 272, 425, 767, 767, 703, 834, 365, 297 + 153, 154, 168, 172, 198, 240, 315, 316, 317, 323, + 326, 357, 366, 382, 389, 393, 403, 415, 419, 439, + 452, 455, 458, 463, 479, 503, 517, 529, 530, 531, + 532, 533, 540, 551, 552, 553, 556, 557, 559, 570, + 588, 636, 646, 649, 652, 656, 658, 661, 662, 666, + 672, 674, 678, 685, 689, 690, 691, 698, 703, 719, + 720, 723, 724, 727, 729, 730, 731, 732, 734, 736, + 737, 741, 794, 795, 964, 967, 968, 969, 970, 975, + 978, 984, 985, 986, 990, 433, 482, 965, 203, 373, + 384, 419, 469, 108, 192, 554, 965, 3, 22, 23, + 24, 25, 26, 27, 28, 29, 31, 32, 33, 42, + 43, 44, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 59, 60, 61, 62, 63, 64, + 67, 68, 69, 70, 71, 72, 73, 75, 76, 77, + 78, 79, 81, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 94, 95, 96, 97, 98, 99, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 118, 120, 121, 122, 123, + 124, 125, 128, 129, 130, 131, 134, 135, 136, 137, + 138, 140, 141, 142, 144, 145, 146, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 161, + 163, 164, 165, 166, 168, 170, 171, 173, 174, 175, + 176, 177, 178, 180, 182, 183, 184, 185, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, + 200, 201, 202, 203, 204, 205, 206, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 219, 221, 222, + 223, 224, 225, 226, 227, 228, 229, 230, 231, 234, + 235, 236, 237, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 276, + 277, 278, 279, 281, 282, 283, 284, 285, 286, 288, + 289, 292, 293, 294, 297, 298, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 328, 330, 331, 332, 333, 334, 335, 337, 338, + 339, 340, 341, 342, 343, 344, 345, 346, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 362, 363, 364, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 384, 385, 386, 387, 388, 389, 390, 391, 392, + 394, 395, 396, 397, 398, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, + 417, 418, 420, 421, 422, 423, 424, 425, 426, 428, + 429, 430, 433, 434, 435, 436, 437, 439, 440, 441, + 442, 443, 444, 445, 446, 449, 450, 451, 453, 454, + 455, 456, 458, 459, 460, 461, 462, 463, 464, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 477, 480, + 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, + 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, + 563, 639, 640, 641, 873, 953, 957, 3, 176, 247, + 412, 558, 563, 639, 290, 965, 55, 172, 517, 583, + 178, 241, 295, 314, 373, 423, 425, 442, 448, 451, + 634, 654, 697, 5, 30, 326, 563, 564, 952, 3, + 30, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 45, 49, 53, 54, 55, 56, 57, 58, 65, 66, + 71, 72, 74, 79, 80, 81, 82, 83, 89, 93, + 100, 101, 108, 112, 115, 117, 119, 126, 127, 132, + 133, 139, 143, 147, 152, 159, 160, 162, 165, 167, + 169, 171, 172, 173, 176, 177, 179, 181, 182, 183, + 186, 194, 199, 207, 209, 210, 216, 217, 218, 219, + 220, 222, 223, 225, 232, 233, 235, 237, 238, 247, + 268, 269, 270, 274, 275, 278, 280, 281, 283, 287, + 290, 291, 295, 296, 299, 300, 302, 303, 315, 316, + 317, 318, 321, 322, 325, 329, 336, 342, 347, 361, + 364, 368, 382, 383, 390, 393, 394, 397, 399, 412, + 414, 415, 416, 419, 421, 427, 429, 430, 431, 432, + 435, 437, 438, 441, 447, 448, 452, 457, 463, 464, + 465, 467, 475, 476, 478, 479, 486, 487, 488, 489, + 490, 491, 492, 493, 494, 495, 496, 569, 639, 643, + 645, 24, 81, 97, 146, 156, 169, 174, 203, 246, + 250, 320, 335, 370, 373, 384, 387, 405, 419, 425, + 426, 436, 442, 469, 654, 667, 668, 671, 965, 952, + 100, 137, 467, 517, 532, 533, 540, 556, 557, 570, + 588, 636, 646, 649, 656, 658, 661, 662, 666, 674, + 681, 685, 691, 698, 719, 723, 724, 727, 729, 964, + 967, 968, 970, 975, 978, 984, 990, 108, 75, 66, + 79, 81, 159, 232, 281, 291, 303, 321, 369, 414, + 435, 437, 441, 463, 517, 562, 563, 564, 730, 795, + 797, 799, 809, 816, 817, 873, 875, 876, 108, 5, + 563, 565, 721, 563, 952, 30, 178, 241, 388, 429, + 433, 563, 976, 977, 988, 965, 30, 132, 750, 751, + 178, 241, 373, 388, 429, 979, 980, 988, 965, 563, + 729, 741, 989, 563, 816, 419, 747, 562, 173, 517, + 972, 517, 345, 742, 743, 952, 742, 730, 731, 984, + 0, 520, 467, 679, 122, 213, 454, 214, 147, 218, + 296, 447, 753, 754, 799, 799, 730, 732, 734, 521, + 30, 429, 433, 729, 989, 192, 562, 952, 192, 562, + 192, 816, 192, 562, 275, 565, 341, 966, 515, 519, + 566, 567, 517, 82, 108, 174, 203, 246, 373, 384, + 419, 442, 469, 561, 108, 729, 562, 423, 425, 423, + 425, 355, 192, 562, 562, 174, 246, 345, 384, 419, + 469, 647, 380, 203, 30, 952, 192, 569, 252, 436, + 107, 419, 419, 469, 377, 380, 192, 563, 669, 959, + 192, 949, 952, 192, 952, 517, 677, 295, 425, 681, + 3, 463, 639, 643, 682, 684, 685, 687, 688, 679, + 563, 565, 558, 517, 517, 167, 517, 730, 817, 517, + 517, 562, 517, 517, 172, 517, 517, 517, 517, 730, + 795, 799, 809, 510, 566, 40, 563, 810, 811, 810, + 382, 521, 733, 37, 42, 101, 173, 209, 225, 235, + 269, 315, 322, 364, 383, 452, 813, 811, 40, 563, + 810, 812, 503, 821, 565, 506, 517, 517, 725, 977, + 977, 977, 500, 224, 519, 290, 4, 6, 7, 8, + 9, 10, 39, 54, 56, 57, 65, 71, 72, 83, + 112, 115, 117, 136, 152, 160, 165, 182, 183, 216, + 217, 219, 247, 268, 270, 275, 280, 283, 292, 342, + 368, 397, 429, 430, 438, 464, 501, 508, 509, 510, + 515, 517, 522, 523, 525, 526, 563, 565, 730, 784, + 833, 836, 839, 840, 841, 843, 844, 845, 846, 848, + 849, 865, 867, 868, 869, 870, 871, 872, 873, 874, + 876, 877, 892, 893, 904, 926, 931, 939, 940, 941, + 953, 954, 955, 938, 940, 979, 979, 565, 979, 500, + 172, 431, 506, 966, 519, 566, 663, 816, 3, 171, + 173, 467, 685, 971, 973, 171, 974, 865, 910, 911, + 742, 521, 517, 961, 518, 518, 518, 531, 562, 172, + 295, 706, 157, 663, 721, 30, 132, 748, 748, 59, + 748, 162, 167, 238, 287, 759, 761, 762, 787, 789, + 790, 791, 181, 290, 457, 290, 753, 754, 517, 420, + 987, 500, 224, 152, 26, 32, 137, 294, 353, 357, + 389, 460, 545, 548, 549, 353, 152, 40, 60, 106, + 202, 251, 261, 273, 305, 353, 359, 384, 389, 403, + 534, 537, 548, 152, 353, 389, 548, 152, 353, 389, + 548, 152, 40, 555, 291, 484, 865, 932, 568, 569, + 567, 3, 30, 37, 42, 49, 55, 81, 83, 89, + 101, 132, 171, 173, 176, 177, 194, 209, 222, 223, + 225, 235, 237, 247, 269, 278, 300, 302, 322, 364, + 383, 394, 412, 421, 441, 465, 467, 518, 639, 644, + 865, 913, 914, 956, 962, 865, 419, 562, 563, 518, + 517, 623, 373, 634, 654, 275, 650, 40, 469, 192, + 562, 192, 562, 638, 192, 562, 192, 562, 192, 563, + 653, 89, 694, 152, 483, 90, 129, 308, 424, 192, + 563, 152, 519, 960, 63, 360, 521, 670, 152, 521, + 670, 152, 290, 675, 676, 865, 962, 355, 518, 521, + 4, 160, 290, 438, 508, 509, 536, 539, 565, 680, + 682, 683, 686, 955, 681, 431, 517, 578, 582, 865, + 911, 517, 3, 68, 69, 109, 110, 113, 114, 189, + 190, 253, 254, 255, 256, 257, 258, 259, 260, 263, + 264, 337, 338, 378, 379, 473, 474, 497, 498, 565, + 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, + 861, 862, 863, 916, 917, 811, 812, 865, 562, 865, + 918, 508, 509, 563, 866, 867, 893, 904, 920, 517, + 865, 910, 921, 865, 58, 172, 233, 432, 865, 911, + 924, 865, 518, 564, 517, 421, 767, 768, 768, 750, + 751, 799, 220, 745, 37, 225, 383, 813, 225, 300, + 814, 799, 814, 225, 813, 517, 225, 814, 148, 200, + 801, 225, 768, 517, 564, 517, 768, 297, 865, 981, + 983, 913, 3, 37, 42, 49, 54, 55, 56, 57, + 71, 72, 81, 83, 89, 101, 112, 115, 165, 171, + 173, 177, 194, 209, 216, 217, 219, 222, 223, 225, + 235, 237, 247, 268, 269, 270, 278, 283, 300, 302, + 322, 342, 364, 368, 383, 390, 394, 397, 412, 421, + 429, 430, 441, 447, 464, 467, 639, 642, 827, 829, + 830, 832, 834, 836, 838, 840, 841, 842, 844, 845, + 848, 849, 915, 958, 40, 236, 563, 517, 515, 730, + 466, 847, 865, 930, 847, 847, 517, 517, 835, 835, + 325, 730, 517, 837, 523, 71, 72, 847, 865, 835, + 517, 517, 481, 503, 517, 850, 517, 850, 865, 865, + 865, 83, 148, 942, 943, 865, 911, 912, 730, 865, + 910, 564, 894, 895, 896, 9, 569, 519, 566, 933, + 566, 517, 565, 517, 517, 565, 955, 3, 8, 11, + 15, 16, 17, 18, 19, 20, 21, 36, 40, 46, + 53, 80, 177, 194, 199, 222, 223, 237, 275, 278, + 292, 295, 394, 501, 504, 505, 506, 508, 509, 510, + 511, 512, 513, 902, 903, 904, 906, 936, 480, 878, + 302, 865, 521, 745, 517, 565, 745, 3, 117, 241, + 536, 565, 849, 982, 104, 983, 983, 563, 40, 563, + 518, 521, 679, 521, 518, 743, 949, 950, 40, 961, + 663, 193, 355, 220, 623, 389, 172, 468, 722, 732, + 732, 30, 755, 756, 865, 59, 732, 749, 164, 272, + 775, 227, 273, 341, 392, 454, 4, 9, 30, 770, + 865, 508, 509, 771, 772, 865, 867, 787, 788, 762, + 761, 759, 760, 167, 790, 285, 792, 59, 738, 739, + 740, 802, 866, 940, 940, 759, 787, 911, 236, 562, + 74, 82, 93, 169, 192, 329, 448, 563, 605, 615, + 630, 82, 93, 728, 93, 728, 517, 431, 517, 603, + 245, 451, 603, 93, 521, 431, 562, 3, 832, 536, + 59, 538, 536, 536, 106, 251, 261, 59, 431, 479, + 503, 535, 266, 373, 535, 537, 816, 93, 431, 728, + 373, 562, 431, 373, 554, 563, 578, 516, 527, 913, + 913, 914, 521, 753, 754, 13, 14, 222, 222, 431, + 431, 563, 622, 627, 479, 581, 562, 345, 384, 419, + 469, 647, 380, 152, 100, 588, 651, 656, 691, 990, + 144, 829, 562, 275, 534, 657, 275, 517, 623, 40, + 275, 623, 275, 517, 648, 275, 199, 655, 192, 563, + 617, 695, 569, 152, 172, 673, 669, 568, 519, 959, + 949, 952, 952, 959, 518, 521, 13, 681, 687, 4, + 955, 4, 955, 565, 569, 580, 587, 55, 102, 123, + 141, 145, 168, 171, 187, 280, 288, 310, 339, 584, + 40, 518, 865, 518, 172, 521, 518, 318, 919, 518, + 866, 866, 11, 15, 16, 19, 20, 21, 199, 222, + 292, 504, 505, 506, 508, 509, 510, 511, 512, 513, + 904, 866, 518, 818, 819, 875, 167, 172, 922, 923, + 521, 518, 40, 924, 911, 924, 924, 172, 518, 40, + 810, 517, 950, 4, 9, 563, 763, 765, 766, 940, + 938, 178, 241, 419, 423, 425, 451, 562, 746, 476, + 822, 799, 225, 799, 290, 457, 815, 799, 225, 940, + 799, 282, 282, 517, 799, 564, 823, 824, 517, 564, + 823, 521, 518, 521, 519, 517, 832, 517, 517, 519, + 39, 831, 517, 851, 852, 853, 854, 855, 856, 857, + 858, 859, 860, 861, 862, 863, 864, 518, 521, 835, + 570, 662, 698, 703, 726, 729, 967, 984, 911, 912, + 517, 475, 927, 928, 865, 912, 955, 865, 897, 898, + 899, 900, 847, 847, 8, 15, 16, 19, 20, 21, + 504, 505, 506, 508, 509, 510, 511, 512, 513, 563, + 902, 907, 518, 911, 429, 429, 955, 955, 517, 517, + 563, 355, 947, 167, 516, 518, 521, 527, 521, 524, + 510, 567, 911, 955, 865, 864, 864, 829, 865, 865, + 865, 865, 865, 865, 865, 865, 5, 569, 963, 429, + 45, 416, 937, 959, 865, 865, 517, 730, 925, 132, + 160, 275, 280, 285, 438, 449, 865, 280, 517, 865, + 431, 53, 177, 194, 199, 237, 394, 865, 865, 865, + 865, 865, 865, 865, 865, 865, 865, 30, 38, 399, + 901, 515, 519, 935, 181, 163, 879, 368, 517, 893, + 941, 172, 796, 913, 796, 517, 565, 563, 562, 971, + 551, 562, 865, 521, 518, 250, 275, 744, 457, 665, + 562, 700, 517, 563, 705, 715, 716, 718, 563, 565, + 563, 565, 41, 126, 757, 521, 457, 757, 266, 732, + 368, 369, 508, 509, 772, 774, 867, 392, 227, 291, + 313, 313, 521, 512, 4, 773, 955, 773, 368, 369, + 774, 562, 948, 279, 396, 793, 517, 950, 951, 521, + 181, 457, 199, 181, 220, 788, 760, 518, 353, 548, + 517, 192, 615, 952, 227, 275, 227, 457, 517, 608, + 828, 829, 952, 563, 192, 952, 192, 563, 26, 137, + 389, 544, 547, 569, 599, 613, 952, 569, 607, 626, + 952, 545, 952, 353, 389, 534, 548, 536, 959, 952, + 536, 959, 952, 536, 353, 389, 548, 952, 952, 952, + 952, 353, 389, 548, 952, 952, 565, 509, 865, 932, + 753, 753, 753, 465, 914, 193, 358, 752, 865, 865, + 280, 560, 565, 280, 560, 563, 334, 577, 518, 521, + 288, 172, 431, 572, 650, 469, 562, 562, 638, 562, + 562, 653, 562, 295, 634, 517, 730, 517, 152, 152, + 237, 563, 605, 615, 618, 621, 631, 633, 479, 481, + 610, 151, 729, 152, 479, 696, 152, 518, 913, 40, + 152, 3, 517, 275, 290, 563, 3, 670, 568, 670, + 290, 670, 675, 865, 578, 510, 515, 517, 536, 579, + 686, 871, 872, 518, 521, 40, 576, 565, 576, 275, + 280, 339, 576, 59, 576, 829, 518, 865, 865, 865, + 922, 829, 866, 866, 866, 866, 866, 866, 132, 275, + 285, 866, 866, 866, 866, 866, 866, 866, 866, 866, + 866, 518, 521, 40, 820, 865, 865, 923, 922, 829, + 518, 518, 518, 911, 829, 950, 518, 313, 512, 313, + 369, 512, 517, 517, 745, 423, 425, 423, 425, 562, + 747, 747, 747, 865, 181, 776, 815, 799, 865, 517, + 799, 167, 517, 564, 806, 815, 829, 518, 521, 823, + 518, 981, 3, 915, 39, 831, 563, 826, 826, 3, + 515, 515, 955, 431, 431, 431, 431, 829, 454, 518, + 516, 911, 865, 139, 928, 929, 518, 518, 518, 527, + 521, 524, 519, 518, 518, 500, 500, 518, 518, 865, + 950, 517, 865, 944, 563, 865, 865, 894, 943, 518, + 518, 518, 500, 866, 866, 145, 911, 172, 132, 160, + 280, 285, 438, 449, 517, 145, 907, 865, 416, 937, + 865, 925, 865, 431, 517, 730, 865, 932, 568, 517, + 517, 155, 880, 797, 798, 822, 753, 822, 955, 864, + 961, 961, 250, 517, 798, 476, 664, 40, 59, 701, + 711, 718, 933, 521, 796, 506, 722, 722, 502, 758, + 756, 292, 902, 905, 758, 4, 955, 774, 291, 454, + 771, 521, 244, 950, 738, 59, 940, 517, 564, 59, + 266, 431, 865, 275, 630, 517, 152, 517, 608, 203, + 627, 628, 589, 40, 176, 598, 624, 589, 26, 137, + 357, 359, 389, 541, 542, 543, 549, 550, 152, 670, + 152, 670, 599, 613, 599, 518, 521, 565, 592, 506, + 519, 518, 521, 431, 373, 93, 431, 728, 373, 431, + 431, 431, 373, 555, 527, 516, 527, 752, 752, 752, + 914, 282, 282, 518, 517, 571, 3, 406, 407, 565, + 586, 622, 577, 562, 657, 517, 40, 623, 648, 655, + 650, 355, 419, 565, 659, 660, 627, 562, 562, 638, + 562, 518, 521, 288, 603, 288, 290, 602, 952, 479, + 637, 562, 603, 40, 562, 518, 419, 865, 653, 587, + 152, 562, 673, 959, 574, 585, 686, 580, 565, 565, + 280, 627, 510, 627, 565, 510, 627, 565, 518, 518, + 923, 172, 132, 285, 517, 821, 818, 517, 518, 518, + 518, 563, 763, 822, 747, 747, 747, 747, 562, 562, + 562, 59, 186, 785, 815, 950, 517, 803, 804, 805, + 868, 870, 950, 167, 80, 825, 824, 518, 518, 515, + 829, 518, 521, 518, 955, 516, 955, 518, 852, 854, + 855, 856, 855, 856, 856, 518, 427, 865, 143, 865, + 897, 907, 850, 850, 518, 518, 865, 944, 945, 946, + 40, 199, 518, 947, 864, 865, 36, 36, 865, 518, + 865, 172, 517, 915, 865, 518, 145, 866, 866, 145, + 145, 865, 865, 516, 527, 517, 934, 754, 476, 865, + 301, 884, 521, 776, 752, 776, 518, 726, 865, 361, + 709, 563, 266, 321, 117, 304, 517, 699, 729, 518, + 521, 705, 664, 865, 164, 231, 517, 758, 291, 562, + 518, 951, 181, 730, 731, 940, 951, 952, 952, 518, + 152, 628, 615, 628, 589, 617, 521, 518, 119, 207, + 273, 275, 614, 517, 33, 59, 635, 624, 74, 80, + 93, 117, 119, 207, 275, 280, 329, 347, 448, 457, + 594, 595, 609, 176, 117, 191, 275, 603, 535, 107, + 117, 176, 275, 405, 408, 537, 603, 389, 543, 442, + 952, 563, 547, 3, 37, 42, 49, 55, 81, 83, + 89, 101, 171, 173, 176, 177, 194, 209, 222, 223, + 225, 235, 237, 247, 269, 274, 278, 292, 300, 302, + 322, 364, 383, 390, 394, 412, 421, 441, 447, 467, + 508, 509, 536, 565, 590, 629, 639, 645, 829, 905, + 956, 569, 626, 952, 952, 952, 952, 952, 952, 952, + 952, 952, 952, 578, 932, 932, 518, 518, 518, 753, + 107, 373, 519, 535, 586, 517, 621, 729, 696, 40, + 517, 634, 192, 562, 518, 521, 518, 657, 517, 40, + 612, 610, 618, 86, 677, 107, 273, 623, 729, 648, + 729, 655, 518, 617, 457, 693, 670, 518, 521, 627, + 866, 172, 517, 915, 823, 518, 521, 518, 776, 562, + 562, 562, 562, 30, 103, 182, 367, 517, 777, 778, + 779, 780, 781, 782, 783, 865, 865, 478, 881, 518, + 867, 908, 909, 199, 181, 800, 804, 518, 806, 807, + 808, 959, 831, 955, 831, 563, 831, 516, 516, 865, + 521, 518, 563, 865, 867, 865, 865, 865, 915, 518, + 865, 36, 36, 865, 865, 145, 518, 509, 932, 518, + 913, 518, 865, 518, 517, 563, 885, 785, 518, 785, + 565, 518, 939, 463, 418, 456, 710, 563, 704, 714, + 290, 707, 506, 718, 709, 907, 59, 518, 518, 462, + 463, 735, 589, 615, 518, 518, 479, 620, 120, 195, + 205, 119, 459, 865, 117, 40, 517, 959, 952, 866, + 120, 195, 119, 280, 227, 562, 620, 88, 635, 192, + 280, 536, 865, 635, 280, 508, 509, 539, 563, 829, + 670, 670, 3, 247, 412, 956, 960, 506, 431, 431, + 516, 516, 752, 518, 518, 563, 578, 457, 573, 575, + 627, 518, 637, 40, 419, 865, 587, 419, 275, 517, + 565, 696, 621, 151, 729, 149, 201, 602, 122, 137, + 328, 637, 107, 696, 479, 991, 40, 517, 290, 563, + 692, 517, 585, 866, 915, 518, 518, 9, 354, 769, + 785, 517, 391, 517, 518, 521, 563, 882, 883, 336, + 786, 521, 518, 517, 564, 59, 518, 199, 518, 807, + 516, 829, 944, 516, 192, 518, 865, 865, 865, 527, + 516, 527, 518, 518, 563, 886, 881, 565, 881, 521, + 462, 933, 518, 521, 91, 709, 865, 518, 951, 951, + 347, 620, 517, 611, 589, 518, 191, 517, 865, 275, + 595, 620, 623, 952, 40, 152, 825, 960, 512, 590, + 952, 952, 518, 535, 124, 518, 610, 729, 729, 518, + 562, 152, 40, 518, 952, 637, 30, 85, 94, 118, + 191, 204, 405, 408, 606, 606, 369, 369, 40, 64, + 74, 241, 419, 865, 587, 562, 517, 563, 708, 717, + 875, 518, 518, 517, 881, 911, 517, 911, 779, 40, + 521, 865, 457, 764, 867, 940, 950, 811, 517, 811, + 865, 932, 932, 310, 887, 786, 786, 729, 304, 729, + 704, 290, 517, 702, 562, 589, 569, 616, 619, 409, + 471, 596, 597, 517, 591, 865, 518, 249, 632, 191, + 457, 546, 512, 442, 578, 565, 696, 602, 991, 517, + 562, 729, 610, 677, 729, 74, 293, 74, 729, 518, + 693, 865, 80, 712, 518, 521, 712, 9, 786, 518, + 778, 518, 885, 883, 371, 518, 940, 516, 516, 516, + 59, 753, 764, 764, 710, 93, 717, 133, 623, 506, + 518, 521, 534, 518, 273, 604, 173, 309, 395, 290, + 600, 601, 625, 591, 865, 442, 40, 517, 991, 602, + 637, 991, 293, 293, 517, 518, 959, 713, 959, 696, + 708, 713, 518, 764, 518, 766, 518, 910, 184, 340, + 369, 888, 462, 952, 518, 276, 454, 632, 590, 619, + 518, 597, 205, 122, 454, 290, 625, 290, 600, 729, + 717, 712, 757, 822, 757, 53, 104, 444, 865, 889, + 890, 889, 889, 518, 729, 822, 389, 601, 63, 273, + 360, 389, 593, 593, 991, 518, 713, 758, 758, 890, + 368, 166, 324, 166, 324, 148, 891, 891, 891, 716, + 589, 25, 117, 280, 696, 757, 36, 104, 181, 273, + 428, 822, 822, 758, 890, 368, 298 }; -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab +/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ +static const yytype_int16 yyr1[] = +{ + 0, 528, 529, 530, 530, 531, 531, 531, 531, 531, + 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, + 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, + 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, + 531, 531, 531, 531, 531, 531, 531, 540, 540, 540, + 540, 540, 540, 540, 540, 541, 541, 542, 542, 543, + 543, 543, 543, 544, 544, 545, 545, 545, 545, 545, + 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, + 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, + 545, 545, 545, 545, 546, 546, 547, 547, 547, 547, + 548, 548, 549, 550, 550, 550, 661, 661, 661, 661, + 562, 562, 563, 563, 563, 564, 564, 565, 566, 566, + 567, 568, 569, 569, 569, 569, 727, 727, 727, 727, + 727, 727, 727, 727, 727, 727, 727, 727, 727, 728, + 728, 698, 699, 699, 699, 699, 699, 700, 700, 701, + 701, 701, 702, 702, 702, 703, 703, 704, 705, 705, + 706, 706, 706, 707, 707, 707, 708, 708, 708, 709, + 709, 710, 710, 711, 711, 712, 712, 713, 713, 714, + 714, 715, 715, 716, 716, 717, 717, 718, 658, 658, + 658, 659, 659, 660, 660, 723, 723, 723, 656, 656, + 656, 657, 657, 652, 652, 652, 653, 653, 654, 654, + 654, 655, 655, 968, 674, 674, 674, 675, 675, 676, + 676, 677, 677, 533, 533, 534, 534, 535, 535, 535, + 536, 536, 536, 536, 537, 537, 537, 537, 537, 537, + 537, 537, 537, 537, 537, 537, 537, 537, 538, 538, + 539, 539, 539, 672, 672, 673, 673, 964, 964, 964, + 964, 964, 964, 965, 965, 965, 966, 966, 966, 969, + 588, 588, 588, 589, 589, 590, 590, 590, 590, 590, + 590, 591, 591, 592, 593, 593, 593, 593, 593, 594, + 594, 594, 594, 595, 595, 595, 595, 595, 595, 595, + 595, 596, 596, 597, 597, 598, 598, 598, 599, 600, + 601, 601, 601, 601, 601, 602, 602, 602, 602, 603, + 604, 604, 605, 605, 606, 606, 606, 606, 606, 606, + 606, 606, 607, 607, 608, 609, 609, 609, 609, 610, + 610, 610, 610, 611, 612, 612, 612, 613, 614, 614, + 614, 614, 614, 614, 615, 615, 616, 616, 617, 618, + 618, 618, 619, 619, 620, 620, 621, 621, 621, 622, + 623, 623, 624, 624, 625, 626, 626, 626, 626, 627, + 627, 628, 628, 629, 629, 629, 630, 630, 630, 630, + 630, 630, 631, 631, 632, 632, 632, 632, 633, 634, + 634, 634, 634, 634, 634, 634, 634, 635, 635, 666, + 666, 666, 666, 666, 666, 667, 667, 667, 667, 667, + 667, 667, 667, 667, 667, 667, 667, 667, 667, 667, + 667, 667, 667, 668, 668, 668, 668, 668, 668, 669, + 669, 670, 670, 670, 671, 671, 671, 646, 646, 646, + 646, 646, 646, 647, 647, 648, 648, 967, 570, 570, + 570, 571, 571, 571, 572, 572, 573, 573, 574, 574, + 575, 575, 576, 576, 577, 577, 578, 578, 579, 579, + 579, 579, 579, 579, 579, 580, 581, 581, 582, 582, + 583, 583, 584, 584, 584, 584, 584, 584, 584, 584, + 584, 584, 584, 584, 584, 584, 584, 584, 585, 586, + 586, 586, 586, 586, 587, 587, 729, 729, 730, 730, + 730, 731, 731, 731, 731, 731, 731, 731, 731, 732, + 732, 733, 733, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 734, 734, 734, 734, 734, + 734, 734, 735, 735, 736, 736, 737, 737, 738, 738, + 738, 739, 739, 740, 740, 741, 741, 741, 742, 742, + 743, 744, 744, 744, 745, 745, 746, 746, 746, 746, + 746, 746, 746, 746, 746, 747, 747, 748, 748, 748, + 749, 750, 750, 751, 751, 752, 752, 752, 753, 753, + 754, 754, 755, 755, 756, 756, 757, 757, 757, 758, + 758, 758, 759, 759, 759, 759, 760, 760, 761, 761, + 761, 761, 762, 762, 763, 763, 763, 763, 763, 763, + 764, 764, 765, 765, 766, 766, 766, 766, 767, 768, + 768, 769, 769, 770, 770, 770, 770, 770, 771, 772, + 772, 772, 773, 773, 774, 774, 775, 775, 776, 776, + 776, 777, 777, 778, 778, 779, 779, 779, 779, 779, + 780, 781, 782, 783, 784, 784, 785, 785, 786, 786, + 787, 787, 788, 788, 789, 789, 790, 791, 791, 791, + 791, 792, 792, 793, 793, 793, 794, 794, 795, 795, + 796, 796, 797, 797, 798, 798, 799, 799, 799, 799, + 799, 799, 799, 799, 799, 799, 800, 800, 801, 801, + 801, 802, 802, 803, 803, 803, 803, 804, 804, 805, + 805, 806, 806, 807, 808, 808, 809, 809, 809, 809, + 809, 809, 809, 809, 809, 809, 809, 810, 810, 810, + 810, 811, 811, 812, 812, 812, 812, 812, 813, 813, + 813, 813, 813, 813, 814, 814, 815, 815, 816, 816, + 816, 816, 817, 817, 818, 819, 819, 820, 820, 821, + 821, 822, 822, 823, 823, 824, 825, 825, 826, 826, + 827, 827, 828, 828, 829, 829, 829, 829, 829, 829, + 829, 829, 829, 829, 830, 830, 831, 831, 831, 832, + 832, 832, 832, 832, 832, 832, 833, 833, 833, 833, + 834, 835, 835, 836, 836, 836, 836, 836, 836, 836, + 836, 836, 836, 836, 837, 837, 838, 838, 839, 839, + 840, 841, 842, 842, 843, 843, 844, 845, 846, 846, + 846, 846, 846, 846, 847, 847, 848, 848, 848, 848, + 849, 850, 850, 850, 851, 851, 852, 852, 853, 853, + 854, 854, 855, 855, 856, 856, 857, 857, 858, 858, + 859, 859, 860, 860, 861, 861, 862, 862, 863, 863, + 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, + 864, 864, 864, 864, 864, 864, 864, 864, 864, 864, + 864, 865, 865, 865, 865, 865, 865, 865, 865, 865, + 865, 865, 865, 865, 865, 865, 865, 865, 865, 865, + 865, 865, 865, 865, 865, 865, 865, 865, 865, 865, + 865, 865, 865, 865, 865, 865, 865, 865, 865, 865, + 865, 865, 865, 865, 865, 865, 865, 865, 865, 865, + 865, 865, 865, 865, 865, 865, 865, 865, 865, 865, + 865, 865, 865, 865, 865, 865, 865, 865, 865, 865, + 865, 865, 866, 866, 866, 866, 866, 866, 866, 866, + 866, 866, 866, 866, 866, 866, 866, 866, 866, 866, + 866, 866, 866, 866, 866, 866, 866, 867, 867, 868, + 868, 868, 868, 868, 868, 869, 869, 869, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, 870, 870, + 871, 872, 873, 873, 873, 873, 873, 873, 874, 874, + 875, 875, 876, 876, 876, 876, 876, 876, 876, 876, + 876, 876, 876, 876, 876, 876, 877, 877, 878, 878, + 879, 879, 879, 880, 880, 881, 881, 882, 882, 883, + 884, 884, 884, 885, 886, 886, 887, 887, 888, 888, + 888, 888, 889, 889, 890, 890, 890, 890, 890, 891, + 891, 891, 891, 891, 892, 892, 893, 893, 894, 895, + 895, 896, 896, 897, 898, 898, 899, 899, 900, 900, + 901, 901, 901, 902, 902, 903, 903, 903, 903, 903, + 903, 903, 903, 903, 903, 903, 903, 903, 903, 904, + 904, 905, 905, 906, 906, 906, 906, 906, 906, 906, + 906, 907, 907, 908, 908, 909, 909, 910, 910, 911, + 911, 912, 912, 913, 913, 914, 914, 914, 915, 915, + 916, 916, 917, 917, 917, 917, 917, 917, 917, 917, + 917, 917, 917, 917, 917, 917, 917, 918, 918, 919, + 920, 920, 921, 921, 921, 921, 921, 921, 922, 923, + 924, 924, 924, 925, 925, 926, 927, 927, 928, 929, + 929, 930, 930, 931, 931, 567, 567, 567, 567, 932, + 932, 933, 933, 934, 934, 934, 935, 935, 935, 935, + 935, 936, 936, 937, 937, 938, 938, 939, 939, 940, + 940, 941, 941, 941, 942, 942, 943, 943, 944, 945, + 945, 946, 946, 947, 947, 947, 948, 948, 949, 949, + 950, 950, 951, 951, 952, 953, 953, 954, 954, 954, + 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + 954, 955, 956, 956, 956, 957, 957, 957, 958, 958, + 958, 959, 959, 960, 960, 961, 961, 962, 963, 963, + 724, 725, 725, 726, 726, 726, 726, 726, 726, 649, + 649, 649, 650, 650, 651, 651, 651, 651, 691, 691, + 692, 693, 693, 694, 694, 695, 695, 696, 696, 697, + 697, 532, 532, 532, 532, 532, 532, 557, 557, 558, + 558, 559, 559, 560, 560, 561, 561, 561, 561, 561, + 561, 561, 561, 561, 561, 689, 689, 690, 678, 678, + 678, 678, 679, 679, 680, 680, 680, 681, 681, 681, + 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, + 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, + 681, 681, 681, 681, 681, 681, 681, 681, 682, 682, + 682, 683, 683, 684, 684, 685, 685, 686, 686, 686, + 686, 687, 688, 688, 978, 978, 978, 978, 979, 979, + 979, 979, 980, 980, 981, 982, 982, 982, 982, 982, + 982, 982, 983, 983, 719, 719, 719, 719, 720, 720, + 721, 721, 722, 722, 722, 970, 970, 970, 970, 970, + 971, 971, 971, 971, 971, 972, 972, 973, 973, 974, + 974, 662, 662, 663, 663, 663, 664, 664, 665, 665, + 551, 551, 552, 552, 553, 553, 553, 554, 554, 555, + 555, 975, 975, 975, 975, 976, 976, 977, 977, 977, + 984, 984, 984, 984, 984, 984, 984, 984, 985, 985, + 986, 986, 987, 987, 988, 988, 989, 989, 556, 990, + 990, 990, 990, 990, 991, 991, 991, 991, 636, 636, + 636, 637, 637, 637, 638, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, + 639, 639, 639, 639, 639, 639, 639, 639, 640, 640, + 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, + 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, + 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, + 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, + 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, + 640, 640, 641, 641, 641, 641, 641, 641, 641, 641, + 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, + 641, 641, 641, 641, 641, 641, 641, 641, 641, 641, + 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, + 642, 642, 642, 642, 642, 642, 642, 642, 642, 642, + 642, 642, 642, 642, 642, 642, 642, 642, 642, 643, + 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, + 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, + 644, 644, 644, 644, 644, 644, 644, 644, 644, 644, + 644, 644, 645, 645, 645, 645, 645, 645, 645, 645, + 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, + 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, + 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, + 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, + 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, + 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, + 645, 645, 645, 645, 645, 645, 645 +}; +/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ +static const yytype_int8 yyr2[] = +{ + 0, 2, 1, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 4, 6, 4, + 6, 4, 6, 4, 6, 1, 2, 3, 2, 1, + 3, 2, 3, 1, 3, 2, 5, 3, 6, 4, + 6, 6, 6, 5, 5, 6, 9, 4, 5, 7, + 6, 4, 8, 4, 2, 4, 3, 6, 4, 2, + 2, 2, 2, 1, 2, 0, 1, 2, 2, 2, + 1, 3, 4, 2, 1, 0, 2, 3, 2, 3, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 1, 1, 1, 1, 1, 6, 6, 8, 6, + 8, 6, 8, 6, 8, 8, 10, 8, 10, 1, + 0, 9, 1, 4, 4, 7, 2, 1, 3, 2, + 2, 0, 4, 3, 0, 1, 0, 2, 3, 5, + 2, 2, 0, 8, 5, 0, 5, 5, 7, 2, + 0, 1, 1, 1, 3, 2, 0, 1, 0, 1, + 3, 1, 3, 1, 2, 1, 3, 2, 6, 8, + 5, 1, 0, 1, 3, 2, 4, 5, 5, 8, + 7, 1, 0, 8, 11, 10, 0, 1, 0, 1, + 1, 0, 2, 4, 3, 9, 12, 1, 3, 1, + 3, 3, 0, 4, 6, 1, 2, 1, 1, 0, + 1, 2, 2, 1, 2, 2, 1, 2, 3, 2, + 2, 2, 2, 3, 3, 3, 1, 3, 1, 0, + 1, 2, 2, 5, 7, 0, 2, 2, 3, 3, + 2, 2, 2, 1, 1, 0, 2, 2, 0, 2, + 9, 12, 11, 0, 2, 1, 1, 1, 1, 1, + 1, 3, 0, 1, 2, 1, 1, 2, 2, 3, + 1, 1, 2, 2, 1, 2, 3, 5, 3, 2, + 5, 1, 1, 1, 0, 5, 7, 5, 2, 3, + 1, 1, 2, 2, 0, 3, 4, 4, 0, 3, + 2, 0, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 3, 1, 2, 2, 2, 2, + 2, 2, 0, 3, 3, 3, 0, 1, 2, 1, + 2, 2, 2, 2, 3, 4, 1, 3, 1, 1, + 1, 1, 3, 1, 2, 0, 1, 2, 0, 1, + 3, 0, 2, 0, 3, 3, 1, 5, 3, 1, + 3, 1, 2, 1, 4, 5, 5, 6, 3, 7, + 4, 11, 1, 3, 2, 2, 2, 0, 3, 1, + 1, 2, 2, 2, 2, 1, 0, 1, 2, 6, + 4, 6, 4, 6, 8, 1, 1, 1, 1, 2, + 1, 2, 1, 2, 1, 1, 1, 1, 3, 3, + 3, 3, 1, 2, 2, 1, 3, 1, 1, 1, + 3, 1, 1, 0, 1, 1, 1, 8, 11, 10, + 7, 10, 9, 1, 1, 2, 3, 8, 11, 9, + 7, 0, 3, 3, 1, 1, 3, 0, 1, 3, + 1, 0, 1, 0, 1, 0, 1, 3, 1, 1, + 1, 1, 3, 1, 0, 2, 2, 0, 2, 0, + 1, 0, 1, 1, 1, 3, 3, 1, 1, 3, + 3, 3, 3, 3, 3, 4, 3, 2, 1, 1, + 1, 1, 3, 1, 1, 3, 1, 1, 3, 3, + 3, 1, 2, 4, 4, 2, 3, 5, 5, 1, + 1, 3, 0, 11, 11, 10, 12, 1, 2, 5, + 4, 4, 4, 4, 7, 5, 4, 7, 6, 9, + 9, 4, 1, 1, 1, 1, 1, 1, 1, 5, + 1, 1, 3, 1, 2, 2, 2, 3, 1, 3, + 7, 1, 2, 0, 2, 0, 3, 3, 4, 4, + 4, 4, 3, 2, 1, 1, 0, 1, 1, 0, + 2, 1, 5, 1, 0, 2, 2, 0, 1, 0, + 3, 5, 1, 3, 4, 3, 1, 1, 0, 2, + 2, 0, 2, 2, 1, 1, 1, 0, 2, 4, + 5, 4, 2, 3, 2, 2, 2, 2, 1, 2, + 3, 0, 1, 0, 5, 1, 4, 6, 2, 1, + 0, 4, 0, 1, 1, 2, 2, 2, 1, 1, + 2, 2, 1, 1, 1, 1, 1, 1, 3, 3, + 0, 1, 3, 1, 2, 1, 1, 1, 1, 1, + 2, 4, 4, 5, 1, 1, 2, 0, 2, 0, + 1, 3, 1, 0, 1, 2, 3, 2, 4, 2, + 3, 2, 0, 1, 2, 0, 4, 5, 1, 2, + 2, 0, 1, 3, 1, 2, 3, 3, 3, 3, + 3, 3, 1, 4, 9, 9, 3, 0, 2, 2, + 0, 5, 3, 0, 1, 1, 3, 5, 3, 1, + 2, 1, 3, 5, 1, 2, 3, 4, 5, 4, + 5, 4, 6, 5, 4, 5, 5, 5, 2, 4, + 1, 1, 0, 1, 4, 5, 4, 0, 2, 2, + 2, 1, 1, 1, 1, 0, 4, 2, 1, 2, + 2, 4, 2, 6, 2, 1, 3, 4, 0, 2, + 0, 2, 0, 1, 3, 3, 2, 0, 2, 4, + 1, 1, 1, 0, 2, 3, 5, 6, 2, 3, + 1, 5, 5, 5, 3, 3, 3, 4, 0, 1, + 1, 1, 1, 1, 2, 4, 1, 1, 1, 1, + 2, 3, 0, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 1, 3, 0, 1, 1, 1, 1, + 5, 2, 1, 1, 1, 1, 4, 1, 2, 2, + 1, 3, 3, 2, 1, 0, 5, 2, 5, 2, + 1, 3, 3, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, + 0, 1, 3, 3, 5, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, + 5, 4, 6, 3, 5, 4, 6, 4, 6, 5, + 7, 3, 2, 4, 3, 2, 3, 3, 3, 3, + 4, 3, 4, 3, 4, 5, 6, 6, 7, 6, + 7, 6, 7, 3, 4, 4, 6, 1, 5, 4, + 3, 5, 1, 3, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 2, 2, 5, 6, 6, 7, 1, 2, 1, + 1, 1, 2, 2, 4, 3, 1, 1, 1, 1, + 1, 4, 1, 1, 1, 1, 2, 4, 2, 2, + 3, 3, 3, 6, 7, 9, 7, 7, 5, 1, + 1, 1, 5, 6, 6, 4, 4, 4, 4, 6, + 5, 5, 5, 4, 6, 4, 7, 9, 5, 0, + 5, 4, 0, 1, 0, 2, 0, 1, 3, 3, + 2, 2, 0, 6, 1, 0, 3, 0, 3, 3, + 3, 0, 1, 4, 2, 2, 2, 2, 2, 3, + 2, 2, 3, 0, 4, 3, 1, 5, 3, 1, + 3, 1, 2, 3, 1, 3, 1, 2, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 4, 1, 4, 1, 4, 1, 2, 1, 2, 1, + 2, 1, 3, 1, 3, 1, 2, 1, 3, 1, + 2, 1, 0, 1, 3, 1, 3, 3, 1, 3, + 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 4, 3, 2, + 3, 0, 3, 3, 2, 2, 1, 0, 2, 2, + 3, 2, 1, 1, 3, 5, 1, 2, 4, 2, + 0, 1, 0, 1, 2, 3, 5, 7, 7, 1, + 0, 0, 2, 0, 2, 3, 3, 3, 5, 7, + 7, 0, 2, 1, 0, 1, 0, 1, 3, 1, + 2, 3, 2, 1, 4, 2, 1, 0, 3, 1, + 3, 1, 2, 4, 2, 0, 1, 3, 1, 3, + 1, 2, 1, 3, 1, 1, 2, 1, 1, 2, + 1, 1, 2, 7, 2, 5, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 3, 3, 0, 1, 1, 1, + 5, 3, 0, 1, 1, 1, 1, 1, 1, 4, + 7, 6, 2, 0, 1, 1, 1, 1, 13, 16, + 1, 2, 0, 1, 0, 1, 0, 2, 0, 1, + 0, 6, 8, 6, 8, 6, 8, 3, 2, 1, + 0, 6, 6, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 4, 6, 3, 2, 4, + 3, 5, 1, 0, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 2, 3, 3, 3, 1, 3, + 3, 2, 3, 3, 1, 1, 1, 3, 5, 1, + 1, 1, 1, 3, 2, 4, 6, 6, 0, 1, + 1, 1, 0, 2, 2, 4, 6, 5, 4, 6, + 1, 1, 1, 1, 1, 1, 0, 1, 3, 1, + 0, 7, 3, 1, 2, 3, 2, 0, 2, 0, + 2, 4, 5, 8, 2, 3, 5, 1, 0, 2, + 0, 2, 3, 3, 3, 1, 1, 1, 2, 3, + 2, 2, 2, 2, 3, 4, 3, 1, 1, 1, + 1, 1, 1, 0, 1, 3, 1, 3, 2, 9, + 12, 11, 12, 14, 3, 4, 4, 0, 7, 10, + 9, 2, 3, 0, 4, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1 +}; -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ -#define YYFAIL goto yyerrlab +enum { YYENOMEM = -2 }; -#define YYRECOVERING() (!!yyerrstatus) +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (&yylloc, yyscanner, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (YYID (0)) +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab +#define YYNOMEM goto yyexhaustedlab -#define YYTERROR 1 -#define YYERRCODE 256 +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, yyscanner, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) + +/* Backward compatibility with an undocumented macro. + Use YYerror or YYUNDEF. */ +#define YYERRCODE YYUNDEF /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (0) #endif +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) -#else -# define YYLEX yylex (&yylval, &yylloc, yyscanner) -#endif /* Enable debugging if requested. */ #if YYDEBUG @@ -19297,88 +18556,119 @@ while (YYID (0)) # define YYFPRINTF fprintf # endif -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (YYID (0)) - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value, Location, yyscanner); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (YYID (0)) - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, core_yyscan_t yyscanner) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; - YYLTYPE const * const yylocationp; - core_yyscan_t yyscanner; -#endif +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + + +/* YYLOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +# ifndef YYLOCATION_PRINT + +# if defined YY_LOCATION_PRINT + + /* Temporary convenience wrapper in case some people defined the + undocumented and private YY_LOCATION_PRINT macros. */ +# define YYLOCATION_PRINT(File, Loc) YY_LOCATION_PRINT(File, *(Loc)) + +# elif defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL + +/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ + +YY_ATTRIBUTE_UNUSED +static int +yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) { - if (!yyvaluep) - return; - YYUSE (yylocationp); - YYUSE (yyscanner); -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); -# endif - switch (yytype) + int res = 0; + int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; + if (0 <= yylocp->first_line) { - default: - break; + res += YYFPRINTF (yyo, "%d", yylocp->first_line); + if (0 <= yylocp->first_column) + res += YYFPRINTF (yyo, ".%d", yylocp->first_column); } + if (0 <= yylocp->last_line) + { + if (yylocp->first_line < yylocp->last_line) + { + res += YYFPRINTF (yyo, "-%d", yylocp->last_line); + if (0 <= end_col) + res += YYFPRINTF (yyo, ".%d", end_col); + } + else if (0 <= end_col && yylocp->first_column < end_col) + res += YYFPRINTF (yyo, "-%d", end_col); + } + return res; } +# define YYLOCATION_PRINT yy_location_print_ + + /* Temporary convenience wrapper in case some people defined the + undocumented and private YY_LOCATION_PRINT macros. */ +# define YY_LOCATION_PRINT(File, Loc) YYLOCATION_PRINT(File, &(Loc)) + +# else + +# define YYLOCATION_PRINT(File, Loc) ((void) 0) + /* Temporary convenience wrapper in case some people defined the + undocumented and private YY_LOCATION_PRINT macros. */ +# define YY_LOCATION_PRINT YYLOCATION_PRINT + +# endif +# endif /* !defined YYLOCATION_PRINT */ + -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Kind, Value, Location, yyscanner); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, core_yyscan_t yyscanner) -#else +yy_symbol_value_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, core_yyscan_t yyscanner) +{ + FILE *yyoutput = yyo; + YY_USE (yyoutput); + YY_USE (yylocationp); + YY_USE (yyscanner); + if (!yyvaluep) + return; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ + static void -yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; - YYLTYPE const * const yylocationp; - core_yyscan_t yyscanner; -#endif +yy_symbol_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, core_yyscan_t yyscanner) { - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + YYFPRINTF (yyo, "%s %s (", + yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); - YY_LOCATION_PRINT (yyoutput, *yylocationp); - YYFPRINTF (yyoutput, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner); - YYFPRINTF (yyoutput, ")"); + YYLOCATION_PRINT (yyo, yylocationp); + YYFPRINTF (yyo, ": "); + yy_symbol_value_print (yyo, yykind, yyvaluep, yylocationp, yyscanner); + YYFPRINTF (yyo, ")"); } /*------------------------------------------------------------------. @@ -19386,82 +18676,69 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner) | TOP (included). | `------------------------------------------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) -#else static void -yy_stack_print (bottom, top) - yytype_int16 *bottom; - yytype_int16 *top; -#endif +yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) { YYFPRINTF (stderr, "Stack now"); - for (; bottom <= top; ++bottom) - YYFPRINTF (stderr, " %d", *bottom); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } YYFPRINTF (stderr, "\n"); } -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, core_yyscan_t yyscanner) -#else static void -yy_reduce_print (yyvsp, yylsp, yyrule, yyscanner) - YYSTYPE *yyvsp; - YYLTYPE *yylsp; - int yyrule; - core_yyscan_t yyscanner; -#endif +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, + int yyrule, core_yyscan_t yyscanner) { + int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; - unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); + YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", + yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { - fprintf (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], - &(yyvsp[(yyi + 1) - (yynrhs)]) - , &(yylsp[(yyi + 1) - (yynrhs)]) , yyscanner); - fprintf (stderr, "\n"); + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), + &yyvsp[(yyi + 1) - (yynrhs)], + &(yylsp[(yyi + 1) - (yynrhs)]), yyscanner); + YYFPRINTF (stderr, "\n"); } } -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyvsp, yylsp, Rule, yyscanner); \ -} while (YYID (0)) +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, yylsp, Rule, yyscanner); \ +} while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YYDPRINTF(Args) ((void) 0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH +#ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif @@ -19472,274 +18749,34 @@ int yydebug; YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static YYSIZE_T -yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static char * -yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ - int yyn = yypact[yystate]; - - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else - { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; - } -} -#endif /* YYERROR_VERBOSE */ - - +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + + + + /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, core_yyscan_t yyscanner) -#else static void -yydestruct (yymsg, yytype, yyvaluep, yylocationp, yyscanner) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; - YYLTYPE *yylocationp; - core_yyscan_t yyscanner; -#endif +yydestruct (const char *yymsg, + yysymbol_kind_t yykind, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, core_yyscan_t yyscanner) { - YYUSE (yyvaluep); - YYUSE (yylocationp); - YYUSE (yyscanner); - + YY_USE (yyvaluep); + YY_USE (yylocationp); + YY_USE (yyscanner); if (!yymsg) yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - switch (yytype) - { + YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); - default: - break; - } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END } - - -/* Prevent warnings from -Wmissing-prototypes. */ - -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (core_yyscan_t yyscanner); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ @@ -19750,221 +18787,217 @@ int yyparse (); | yyparse. | `----------*/ -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) int yyparse (core_yyscan_t yyscanner) -#else -int -yyparse (yyscanner) - core_yyscan_t yyscanner; -#endif -#endif { - /* The look-ahead symbol. */ +/* Lookahead token kind. */ int yychar; -/* The semantic value of the look-ahead symbol. */ -YYSTYPE yylval; -/* Number of syntax errors so far. */ -int yynerrs; -/* Location data for the look-ahead symbol. */ -YYLTYPE yylloc; +/* The semantic value of the lookahead symbol. */ +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); - int yystate; - int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Look-ahead token as an internal (translated) token number. */ - int yytoken = 0; -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif +/* Location data for the lookahead symbol. */ +static YYLTYPE yyloc_default +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL + = { 1, 1, 1, 1 } +# endif +; +YYLTYPE yylloc = yyloc_default; - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. + /* Number of syntax errors so far. */ + int yynerrs = 0; (void)yynerrs; - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ + yy_state_fast_t yystate = 0; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus = 0; - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss = yyssa; - yytype_int16 *yyssp; + /* Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp; + /* Their size. */ + YYPTRDIFF_T yystacksize = YYINITDEPTH; - /* The location stack. */ - YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp; - /* The locations where the error started and ended. */ - YYLTYPE yyerror_range[2]; + /* The state stack: array, bottom, top. */ + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss = yyssa; + yy_state_t *yyssp = yyss; -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + /* The semantic value stack: array, bottom, top. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp = yyvs; - YYSIZE_T yystacksize = YYINITDEPTH; + /* The location stack: array, bottom, top. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp = yyls; + int yyn; + /* The return value of yyparse. */ + int yyresult; + /* Lookahead symbol kind. */ + yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; YYLTYPE yyloc; + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[3]; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; (void)yynerrs; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - - yyssp = yyss; - yyvsp = yyvs; - yylsp = yyls; -#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL - /* Initialize the default location before parsing starts. */ - yylloc.first_line = yylloc.last_line = 1; - yylloc.first_column = yylloc.last_column = 0; -#endif + yychar = YYEMPTY; /* Cause a token to be read. */ + yylsp[0] = yylloc; goto yysetstate; + /*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | +| yynewstate -- push a new state, which is found in yystate. | `------------------------------------------------------------*/ - yynewstate: +yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; - yysetstate: - *yyssp = yystate; + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END + YY_STACK_PRINT (yyss, yyssp); if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + YYNOMEM; +#else { /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + YYPTRDIFF_T yysize = yyssp - yyss + 1; -#ifdef yyoverflow +# if defined yyoverflow { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - YYLTYPE *yyls1 = yyls; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), - &yystacksize); - yyls = yyls1; - yyss = yyss1; - yyvs = yyvs1; + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + yy_state_t *yyss1 = yyss; + YYSTYPE *yyvs1 = yyvs; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yyls1, yysize * YYSIZEOF (*yylsp), + &yystacksize); + yyss = yyss1; + yyvs = yyvs1; + yyls = yyls1; } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else +# else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; + YYNOMEM; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; + yystacksize = YYMAXDEPTH; { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); - YYSTACK_RELOCATE (yyls); + yy_state_t *yyss1 = yyss; + union yyalloc *yyptr = + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); + if (! yyptr) + YYNOMEM; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyls_alloc, yyls); # undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); } # endif -#endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; yylsp = yyls + yysize - 1; - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((stderr, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END if (yyss + yystacksize - 1 <= yyssp) - YYABORT; + YYABORT; } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; goto yybackup; + /*-----------. | yybackup. | `-----------*/ yybackup: - /* Do appropriate processing given the current state. Read a - look-ahead token if we need one and don't already have one. */ + lookahead token if we need one and don't already have one. */ - /* First try to decide what to do without reference to look-ahead token. */ + /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; - /* Not known => get a look-ahead token if don't already have one. */ + /* Not known => get a lookahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ if (yychar == YYEMPTY) { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; + YYDPRINTF ((stderr, "Reading a token\n")); + yychar = yylex (&yylval, &yylloc, yyscanner); } if (yychar <= YYEOF) { - yychar = yytoken = YYEOF; + yychar = YYEOF; + yytoken = YYSYMBOL_YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } + else if (yychar == YYerror) + { + /* The scanner already issued an error message, process directly + to error recovery. But do not keep the error token as + lookahead, it is too special and may lead us to an endless + loop in error recovery. */ + yychar = YYUNDEF; + yytoken = YYSYMBOL_YYerror; + yyerror_range[1] = yylloc; + goto yyerrlab1; + } else { yytoken = YYTRANSLATE (yychar); @@ -19979,30 +19012,27 @@ YYLTYPE yylloc; yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } - if (yyn == YYFINAL) - YYACCEPT; - /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; - /* Shift the look-ahead token. */ + /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; - yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END *++yylsp = yylloc; + + /* Discard the shifted token. */ + yychar = YYEMPTY; goto yynewstate; @@ -20017,14 +19047,14 @@ YYLTYPE yylloc; /*-----------------------------. -| yyreduce -- Do a reduction. | +| yyreduce -- do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. + '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison @@ -20033,2101 +19063,2390 @@ YYLTYPE yylloc; GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; - /* Default location. */ + /* Default location. */ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + yyerror_range[1] = yyloc; YY_REDUCE_PRINT (yyn); switch (yyn) { - case 2: -#line 503 "third_party/libpg_query/grammar/grammar.y" - { - pg_yyget_extra(yyscanner)->parsetree = (yyvsp[(1) - (1)].list); - ;} + case 2: /* stmtblock: stmtmulti */ +#line 507 "third_party/libpg_query/grammar/grammar.y" + { + pg_yyget_extra(yyscanner)->parsetree = (yyvsp[0].list); + } +#line 19078 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 3: -#line 519 "third_party/libpg_query/grammar/grammar.y" - { - if ((yyvsp[(1) - (3)].list) != NIL) + case 3: /* stmtmulti: stmtmulti ';' stmt */ +#line 523 "third_party/libpg_query/grammar/grammar.y" + { + if ((yyvsp[-2].list) != NIL) { /* update length of previous stmt */ - updateRawStmtEnd(llast_node(PGRawStmt, (yyvsp[(1) - (3)].list)), (yylsp[(2) - (3)])); + updateRawStmtEnd(llast_node(PGRawStmt, (yyvsp[-2].list)), (yylsp[-1])); } - if ((yyvsp[(3) - (3)].node) != NULL) - (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeRawStmt((yyvsp[(3) - (3)].node), (yylsp[(2) - (3)]) + 1)); + if ((yyvsp[0].node) != NULL) + (yyval.list) = lappend((yyvsp[-2].list), makeRawStmt((yyvsp[0].node), (yylsp[-1]) + 1)); else - (yyval.list) = (yyvsp[(1) - (3)].list); - ;} + (yyval.list) = (yyvsp[-2].list); + } +#line 19094 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 4: -#line 531 "third_party/libpg_query/grammar/grammar.y" - { - if ((yyvsp[(1) - (1)].node) != NULL) - (yyval.list) = list_make1(makeRawStmt((yyvsp[(1) - (1)].node), 0)); + case 4: /* stmtmulti: stmt */ +#line 535 "third_party/libpg_query/grammar/grammar.y" + { + if ((yyvsp[0].node) != NULL) + (yyval.list) = list_make1(makeRawStmt((yyvsp[0].node), 0)); else (yyval.list) = NIL; - ;} + } +#line 19105 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 45: -#line 580 "third_party/libpg_query/grammar/grammar.y" - { (yyval.node) = NULL; ;} + case 46: /* stmt: %empty */ +#line 585 "third_party/libpg_query/grammar/grammar.y" + { (yyval.node) = NULL; } +#line 19111 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 46: + case 47: /* AlterTableStmt: ALTER TABLE relation_expr alter_table_cmds */ #line 10 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(3) - (4)].range); - n->cmds = (yyvsp[(4) - (4)].list); + n->relation = (yyvsp[-1].range); + n->cmds = (yyvsp[0].list); n->relkind = PG_OBJECT_TABLE; n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19124 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 47: + case 48: /* AlterTableStmt: ALTER TABLE IF_P EXISTS relation_expr alter_table_cmds */ #line 19 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(5) - (6)].range); - n->cmds = (yyvsp[(6) - (6)].list); + n->relation = (yyvsp[-1].range); + n->cmds = (yyvsp[0].list); n->relkind = PG_OBJECT_TABLE; n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19137 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 48: + case 49: /* AlterTableStmt: ALTER INDEX qualified_name alter_table_cmds */ #line 28 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(3) - (4)].range); - n->cmds = (yyvsp[(4) - (4)].list); + n->relation = (yyvsp[-1].range); + n->cmds = (yyvsp[0].list); n->relkind = PG_OBJECT_INDEX; n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19150 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 49: + case 50: /* AlterTableStmt: ALTER INDEX IF_P EXISTS qualified_name alter_table_cmds */ #line 37 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(5) - (6)].range); - n->cmds = (yyvsp[(6) - (6)].list); + n->relation = (yyvsp[-1].range); + n->cmds = (yyvsp[0].list); n->relkind = PG_OBJECT_INDEX; n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19163 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 50: + case 51: /* AlterTableStmt: ALTER SEQUENCE qualified_name alter_table_cmds */ #line 46 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(3) - (4)].range); - n->cmds = (yyvsp[(4) - (4)].list); + n->relation = (yyvsp[-1].range); + n->cmds = (yyvsp[0].list); n->relkind = PG_OBJECT_SEQUENCE; n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19176 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 51: + case 52: /* AlterTableStmt: ALTER SEQUENCE IF_P EXISTS qualified_name alter_table_cmds */ #line 55 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(5) - (6)].range); - n->cmds = (yyvsp[(6) - (6)].list); + n->relation = (yyvsp[-1].range); + n->cmds = (yyvsp[0].list); n->relkind = PG_OBJECT_SEQUENCE; n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19189 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 52: + case 53: /* AlterTableStmt: ALTER VIEW qualified_name alter_table_cmds */ #line 64 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(3) - (4)].range); - n->cmds = (yyvsp[(4) - (4)].list); + n->relation = (yyvsp[-1].range); + n->cmds = (yyvsp[0].list); n->relkind = PG_OBJECT_VIEW; n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19202 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 53: + case 54: /* AlterTableStmt: ALTER VIEW IF_P EXISTS qualified_name alter_table_cmds */ #line 73 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(5) - (6)].range); - n->cmds = (yyvsp[(6) - (6)].list); + n->relation = (yyvsp[-1].range); + n->cmds = (yyvsp[0].list); n->relkind = PG_OBJECT_VIEW; n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19215 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 54: + case 55: /* alter_identity_column_option_list: alter_identity_column_option */ #line 86 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} + { (yyval.list) = list_make1((yyvsp[0].defelt)); } +#line 19221 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 55: + case 56: /* alter_identity_column_option_list: alter_identity_column_option_list alter_identity_column_option */ #line 88 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].defelt)); ;} + { (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].defelt)); } +#line 19227 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 56: + case 57: /* alter_column_default: SET DEFAULT a_expr */ #line 93 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.node) = (yyvsp[(3) - (3)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 19233 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 57: + case 58: /* alter_column_default: DROP DEFAULT */ #line 94 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 19239 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 58: + case 59: /* alter_identity_column_option: RESTART */ #line 100 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.defelt) = makeDefElem("restart", NULL, (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem("restart", NULL, (yylsp[0])); + } +#line 19247 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 59: + case 60: /* alter_identity_column_option: RESTART opt_with NumericOnly */ #line 104 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.defelt) = makeDefElem("restart", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("restart", (PGNode *)(yyvsp[0].value), (yylsp[-2])); + } +#line 19255 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 60: + case 61: /* alter_identity_column_option: SET SeqOptElem */ #line 108 "third_party/libpg_query/grammar/statements/alter_table.y" - { - if (strcmp((yyvsp[(2) - (2)].defelt)->defname, "as") == 0 || - strcmp((yyvsp[(2) - (2)].defelt)->defname, "restart") == 0 || - strcmp((yyvsp[(2) - (2)].defelt)->defname, "owned_by") == 0) + { + if (strcmp((yyvsp[0].defelt)->defname, "as") == 0 || + strcmp((yyvsp[0].defelt)->defname, "restart") == 0 || + strcmp((yyvsp[0].defelt)->defname, "owned_by") == 0) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("sequence option \"%s\" not supported here", (yyvsp[(2) - (2)].defelt)->defname), - parser_errposition((yylsp[(2) - (2)])))); - (yyval.defelt) = (yyvsp[(2) - (2)].defelt); - ;} + errmsg("sequence option \"%s\" not supported here", (yyvsp[0].defelt)->defname), + parser_errposition((yylsp[0])))); + (yyval.defelt) = (yyvsp[0].defelt); + } +#line 19270 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 61: + case 62: /* alter_identity_column_option: SET GENERATED generated_when */ #line 119 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.defelt) = makeDefElem("generated", (PGNode *) makeInteger((yyvsp[(3) - (3)].ival)), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("generated", (PGNode *) makeInteger((yyvsp[0].ival)), (yylsp[-2])); + } +#line 19278 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 62: + case 63: /* alter_generic_option_list: alter_generic_option_elem */ #line 127 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); - ;} + { + (yyval.list) = list_make1((yyvsp[0].defelt)); + } +#line 19286 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 63: + case 64: /* alter_generic_option_list: alter_generic_option_list ',' alter_generic_option_elem */ #line 131 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); - ;} + { + (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].defelt)); + } +#line 19294 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 64: + case 65: /* alter_table_cmd: ADD_P columnDef */ #line 140 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_AddColumn; - n->def = (yyvsp[(2) - (2)].node); + n->def = (yyvsp[0].node); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19306 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 65: + case 66: /* alter_table_cmd: ADD_P IF_P NOT EXISTS columnDef */ #line 149 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_AddColumn; - n->def = (yyvsp[(5) - (5)].node); + n->def = (yyvsp[0].node); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19318 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 66: + case 67: /* alter_table_cmd: ADD_P COLUMN columnDef */ #line 158 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_AddColumn; - n->def = (yyvsp[(3) - (3)].node); + n->def = (yyvsp[0].node); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19330 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 67: + case 68: /* alter_table_cmd: ADD_P COLUMN IF_P NOT EXISTS columnDef */ #line 167 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_AddColumn; - n->def = (yyvsp[(6) - (6)].node); + n->def = (yyvsp[0].node); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19342 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 68: + case 69: /* alter_table_cmd: ALTER opt_column ColId alter_column_default */ #line 176 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_ColumnDefault; - n->name = (yyvsp[(3) - (4)].str); - n->def = (yyvsp[(4) - (4)].node); + n->name = (yyvsp[-1].str); + n->def = (yyvsp[0].node); (yyval.node) = (PGNode *)n; - ;} + } +#line 19354 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 69: + case 70: /* alter_table_cmd: ALTER opt_column ColId DROP NOT NULL_P */ #line 185 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_DropNotNull; - n->name = (yyvsp[(3) - (6)].str); + n->name = (yyvsp[-3].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 19365 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 70: + case 71: /* alter_table_cmd: ALTER opt_column ColId SET NOT NULL_P */ #line 193 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_SetNotNull; - n->name = (yyvsp[(3) - (6)].str); + n->name = (yyvsp[-3].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 19376 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 71: + case 72: /* alter_table_cmd: ALTER opt_column ColId SET STATISTICS SignedIconst */ #line 201 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_SetStatistics; - n->name = (yyvsp[(3) - (6)].str); - n->def = (PGNode *) makeInteger((yyvsp[(6) - (6)].ival)); + n->name = (yyvsp[-3].str); + n->def = (PGNode *) makeInteger((yyvsp[0].ival)); (yyval.node) = (PGNode *)n; - ;} + } +#line 19388 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 72: + case 73: /* alter_table_cmd: ALTER opt_column ColId SET reloptions */ #line 210 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_SetOptions; - n->name = (yyvsp[(3) - (5)].str); - n->def = (PGNode *) (yyvsp[(5) - (5)].list); + n->name = (yyvsp[-2].str); + n->def = (PGNode *) (yyvsp[0].list); (yyval.node) = (PGNode *)n; - ;} + } +#line 19400 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 73: + case 74: /* alter_table_cmd: ALTER opt_column ColId RESET reloptions */ #line 219 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_ResetOptions; - n->name = (yyvsp[(3) - (5)].str); - n->def = (PGNode *) (yyvsp[(5) - (5)].list); + n->name = (yyvsp[-2].str); + n->def = (PGNode *) (yyvsp[0].list); (yyval.node) = (PGNode *)n; - ;} + } +#line 19412 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 74: + case 75: /* alter_table_cmd: ALTER opt_column ColId SET STORAGE ColId */ #line 228 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_SetStorage; - n->name = (yyvsp[(3) - (6)].str); - n->def = (PGNode *) makeString((yyvsp[(6) - (6)].str)); + n->name = (yyvsp[-3].str); + n->def = (PGNode *) makeString((yyvsp[0].str)); (yyval.node) = (PGNode *)n; - ;} + } +#line 19424 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 75: + case 76: /* alter_table_cmd: ALTER opt_column ColId ADD_P GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList */ #line 237 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); PGConstraint *c = makeNode(PGConstraint); c->contype = PG_CONSTR_IDENTITY; - c->generated_when = (yyvsp[(6) - (9)].ival); - c->options = (yyvsp[(9) - (9)].list); - c->location = (yylsp[(5) - (9)]); + c->generated_when = (yyvsp[-3].ival); + c->options = (yyvsp[0].list); + c->location = (yylsp[-4]); n->subtype = PG_AT_AddIdentity; - n->name = (yyvsp[(3) - (9)].str); + n->name = (yyvsp[-6].str); n->def = (PGNode *) c; (yyval.node) = (PGNode *)n; - ;} + } +#line 19444 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 76: + case 77: /* alter_table_cmd: ALTER opt_column ColId alter_identity_column_option_list */ #line 254 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_SetIdentity; - n->name = (yyvsp[(3) - (4)].str); - n->def = (PGNode *) (yyvsp[(4) - (4)].list); + n->name = (yyvsp[-1].str); + n->def = (PGNode *) (yyvsp[0].list); (yyval.node) = (PGNode *)n; - ;} + } +#line 19456 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 77: + case 78: /* alter_table_cmd: ALTER opt_column ColId DROP IDENTITY_P */ #line 263 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = AT_DropIdentity; - n->name = (yyvsp[(3) - (5)].str); + n->name = (yyvsp[-2].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19468 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 78: + case 79: /* alter_table_cmd: ALTER opt_column ColId DROP IDENTITY_P IF_P EXISTS */ #line 272 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = AT_DropIdentity; - n->name = (yyvsp[(3) - (7)].str); + n->name = (yyvsp[-4].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19480 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 79: + case 80: /* alter_table_cmd: DROP opt_column IF_P EXISTS ColId opt_drop_behavior */ #line 281 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_DropColumn; - n->name = (yyvsp[(5) - (6)].str); - n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->name = (yyvsp[-1].str); + n->behavior = (yyvsp[0].dbehavior); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19493 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 80: + case 81: /* alter_table_cmd: DROP opt_column ColId opt_drop_behavior */ #line 291 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_DropColumn; - n->name = (yyvsp[(3) - (4)].str); - n->behavior = (yyvsp[(4) - (4)].dbehavior); + n->name = (yyvsp[-1].str); + n->behavior = (yyvsp[0].dbehavior); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19506 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 81: + case 82: /* alter_table_cmd: ALTER opt_column ColId opt_set_data TYPE_P Typename opt_collate_clause alter_using */ #line 304 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); PGColumnDef *def = makeNode(PGColumnDef); n->subtype = PG_AT_AlterColumnType; - n->name = (yyvsp[(3) - (8)].str); + n->name = (yyvsp[-5].str); n->def = (PGNode *) def; /* We only use these fields of the PGColumnDef node */ - def->typeName = (yyvsp[(6) - (8)].typnam); - def->collClause = (PGCollateClause *) (yyvsp[(7) - (8)].node); - def->raw_default = (yyvsp[(8) - (8)].node); - def->location = (yylsp[(3) - (8)]); + def->typeName = (yyvsp[-2].typnam); + def->collClause = (PGCollateClause *) (yyvsp[-1].node); + def->raw_default = (yyvsp[0].node); + def->location = (yylsp[-5]); (yyval.node) = (PGNode *)n; - ;} + } +#line 19524 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 82: + case 83: /* alter_table_cmd: ALTER opt_column ColId alter_generic_options */ #line 319 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_AlterColumnGenericOptions; - n->name = (yyvsp[(3) - (4)].str); - n->def = (PGNode *) (yyvsp[(4) - (4)].list); + n->name = (yyvsp[-1].str); + n->def = (PGNode *) (yyvsp[0].list); (yyval.node) = (PGNode *)n; - ;} + } +#line 19536 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 83: + case 84: /* alter_table_cmd: ADD_P TableConstraint */ #line 328 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_AddConstraint; - n->def = (yyvsp[(2) - (2)].node); + n->def = (yyvsp[0].node); (yyval.node) = (PGNode *)n; - ;} + } +#line 19547 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 84: + case 85: /* alter_table_cmd: ALTER CONSTRAINT name ConstraintAttributeSpec */ #line 336 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); PGConstraint *c = makeNode(PGConstraint); n->subtype = PG_AT_AlterConstraint; n->def = (PGNode *) c; c->contype = PG_CONSTR_FOREIGN; /* others not supported, yet */ - c->conname = (yyvsp[(3) - (4)].str); - processCASbits((yyvsp[(4) - (4)].ival), (yylsp[(4) - (4)]), "ALTER CONSTRAINT statement", + c->conname = (yyvsp[-1].str); + processCASbits((yyvsp[0].ival), (yylsp[0]), "ALTER CONSTRAINT statement", &c->deferrable, &c->initdeferred, NULL, NULL, yyscanner); (yyval.node) = (PGNode *)n; - ;} + } +#line 19565 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 85: + case 86: /* alter_table_cmd: VALIDATE CONSTRAINT name */ #line 351 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_ValidateConstraint; - n->name = (yyvsp[(3) - (3)].str); + n->name = (yyvsp[0].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 19576 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 86: + case 87: /* alter_table_cmd: DROP CONSTRAINT IF_P EXISTS name opt_drop_behavior */ #line 359 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_DropConstraint; - n->name = (yyvsp[(5) - (6)].str); - n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->name = (yyvsp[-1].str); + n->behavior = (yyvsp[0].dbehavior); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19589 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 87: + case 88: /* alter_table_cmd: DROP CONSTRAINT name opt_drop_behavior */ #line 369 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_DropConstraint; - n->name = (yyvsp[(3) - (4)].str); - n->behavior = (yyvsp[(4) - (4)].dbehavior); + n->name = (yyvsp[-1].str); + n->behavior = (yyvsp[0].dbehavior); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19602 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 88: + case 89: /* alter_table_cmd: SET LOGGED */ #line 379 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_SetLogged; (yyval.node) = (PGNode *)n; - ;} + } +#line 19612 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 89: + case 90: /* alter_table_cmd: SET UNLOGGED */ #line 386 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_SetUnLogged; (yyval.node) = (PGNode *)n; - ;} + } +#line 19622 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 90: + case 91: /* alter_table_cmd: SET reloptions */ #line 393 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_SetRelOptions; - n->def = (PGNode *)(yyvsp[(2) - (2)].list); + n->def = (PGNode *)(yyvsp[0].list); (yyval.node) = (PGNode *)n; - ;} + } +#line 19633 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 91: + case 92: /* alter_table_cmd: RESET reloptions */ #line 401 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_ResetRelOptions; - n->def = (PGNode *)(yyvsp[(2) - (2)].list); + n->def = (PGNode *)(yyvsp[0].list); (yyval.node) = (PGNode *)n; - ;} + } +#line 19644 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 92: + case 93: /* alter_table_cmd: alter_generic_options */ #line 408 "third_party/libpg_query/grammar/statements/alter_table.y" - { + { PGAlterTableCmd *n = makeNode(PGAlterTableCmd); n->subtype = PG_AT_GenericOptions; - n->def = (PGNode *)(yyvsp[(1) - (1)].list); + n->def = (PGNode *)(yyvsp[0].list); (yyval.node) = (PGNode *) n; - ;} + } +#line 19655 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 93: + case 94: /* alter_using: USING a_expr */ #line 418 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 19661 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 94: + case 95: /* alter_using: %empty */ #line 419 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 19667 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 95: + case 96: /* alter_generic_option_elem: generic_option_elem */ #line 425 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.defelt) = (yyvsp[(1) - (1)].defelt); - ;} + { + (yyval.defelt) = (yyvsp[0].defelt); + } +#line 19675 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 96: + case 97: /* alter_generic_option_elem: SET generic_option_elem */ #line 429 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.defelt) = (yyvsp[(2) - (2)].defelt); + { + (yyval.defelt) = (yyvsp[0].defelt); (yyval.defelt)->defaction = PG_DEFELEM_SET; - ;} + } +#line 19684 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 97: + case 98: /* alter_generic_option_elem: ADD_P generic_option_elem */ #line 434 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.defelt) = (yyvsp[(2) - (2)].defelt); + { + (yyval.defelt) = (yyvsp[0].defelt); (yyval.defelt)->defaction = PG_DEFELEM_ADD; - ;} + } +#line 19693 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 98: + case 99: /* alter_generic_option_elem: DROP generic_option_name */ #line 439 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.defelt) = makeDefElemExtended(NULL, (yyvsp[(2) - (2)].str), NULL, DEFELEM_DROP, (yylsp[(2) - (2)])); - ;} + { + (yyval.defelt) = makeDefElemExtended(NULL, (yyvsp[0].str), NULL, DEFELEM_DROP, (yylsp[0])); + } +#line 19701 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 99: + case 100: /* alter_table_cmds: alter_table_cmd */ #line 446 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 19707 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 100: + case 101: /* alter_table_cmds: alter_table_cmds ',' alter_table_cmd */ #line 447 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); } +#line 19713 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 101: + case 102: /* alter_generic_options: OPTIONS '(' alter_generic_option_list ')' */ #line 452 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 19719 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 102: + case 103: /* opt_set_data: SET DATA_P */ #line 456 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.ival) = 1; ;} + { (yyval.ival) = 1; } +#line 19725 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 103: + case 104: /* opt_set_data: SET */ #line 457 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.ival) = 0; ;} + { (yyval.ival) = 0; } +#line 19731 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 104: + case 105: /* opt_set_data: %empty */ #line 458 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.ival) = 0; ;} + { (yyval.ival) = 0; } +#line 19737 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 105: + case 106: /* DeallocateStmt: DEALLOCATE name */ #line 8 "third_party/libpg_query/grammar/statements/deallocate.y" - { + { PGDeallocateStmt *n = makeNode(PGDeallocateStmt); - n->name = (yyvsp[(2) - (2)].str); + n->name = (yyvsp[0].str); (yyval.node) = (PGNode *) n; - ;} + } +#line 19747 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 106: + case 107: /* DeallocateStmt: DEALLOCATE PREPARE name */ #line 14 "third_party/libpg_query/grammar/statements/deallocate.y" - { + { PGDeallocateStmt *n = makeNode(PGDeallocateStmt); - n->name = (yyvsp[(3) - (3)].str); + n->name = (yyvsp[0].str); (yyval.node) = (PGNode *) n; - ;} + } +#line 19757 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 107: + case 108: /* DeallocateStmt: DEALLOCATE ALL */ #line 20 "third_party/libpg_query/grammar/statements/deallocate.y" - { + { PGDeallocateStmt *n = makeNode(PGDeallocateStmt); n->name = NULL; (yyval.node) = (PGNode *) n; - ;} + } +#line 19767 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 108: + case 109: /* DeallocateStmt: DEALLOCATE PREPARE ALL */ #line 26 "third_party/libpg_query/grammar/statements/deallocate.y" - { + { PGDeallocateStmt *n = makeNode(PGDeallocateStmt); n->name = NULL; (yyval.node) = (PGNode *) n; - ;} + } +#line 19777 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 109: + case 110: /* qualified_name: ColIdOrString */ #line 10 "third_party/libpg_query/grammar/statements/common.y" - { - (yyval.range) = makeRangeVar(NULL, (yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} + { + (yyval.range) = makeRangeVar(NULL, (yyvsp[0].str), (yylsp[0])); + } +#line 19785 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 110: + case 111: /* qualified_name: ColId indirection */ #line 14 "third_party/libpg_query/grammar/statements/common.y" - { - check_qualified_name((yyvsp[(2) - (2)].list), yyscanner); - (yyval.range) = makeRangeVar(NULL, NULL, (yylsp[(1) - (2)])); - switch (list_length((yyvsp[(2) - (2)].list))) + { + check_qualified_name((yyvsp[0].list), yyscanner); + (yyval.range) = makeRangeVar(NULL, NULL, (yylsp[-1])); + switch (list_length((yyvsp[0].list))) { case 1: (yyval.range)->catalogname = NULL; - (yyval.range)->schemaname = (yyvsp[(1) - (2)].str); - (yyval.range)->relname = strVal(linitial((yyvsp[(2) - (2)].list))); + (yyval.range)->schemaname = (yyvsp[-1].str); + (yyval.range)->relname = strVal(linitial((yyvsp[0].list))); break; case 2: - (yyval.range)->catalogname = (yyvsp[(1) - (2)].str); - (yyval.range)->schemaname = strVal(linitial((yyvsp[(2) - (2)].list))); - (yyval.range)->relname = strVal(lsecond((yyvsp[(2) - (2)].list))); + (yyval.range)->catalogname = (yyvsp[-1].str); + (yyval.range)->schemaname = strVal(linitial((yyvsp[0].list))); + (yyval.range)->relname = strVal(lsecond((yyvsp[0].list))); break; case 3: default: ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", - NameListToString(lcons(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].list)))), - parser_errposition((yylsp[(1) - (2)])))); + NameListToString(lcons(makeString((yyvsp[-1].str)), (yyvsp[0].list)))), + parser_errposition((yylsp[-1])))); break; } - ;} + } +#line 19815 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 111: + case 112: /* ColId: IDENT */ #line 44 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 19821 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 112: + case 113: /* ColId: unreserved_keyword */ #line 45 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 19827 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 113: + case 114: /* ColId: col_name_keyword */ #line 46 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 19833 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 114: + case 115: /* ColIdOrString: ColId */ #line 50 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 19839 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 115: + case 116: /* ColIdOrString: SCONST */ #line 51 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 19845 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 116: + case 117: /* Sconst: SCONST */ #line 55 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 19851 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 117: + case 118: /* indirection: indirection_el */ #line 59 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 19857 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 118: + case 119: /* indirection: indirection indirection_el */ #line 60 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + { (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].node)); } +#line 19863 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 119: + case 120: /* indirection_el: '.' attr_name */ #line 65 "third_party/libpg_query/grammar/statements/common.y" - { - (yyval.node) = (PGNode *) makeString((yyvsp[(2) - (2)].str)); - ;} + { + (yyval.node) = (PGNode *) makeString((yyvsp[0].str)); + } +#line 19871 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 120: + case 121: /* attr_name: ColLabel */ #line 70 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 19877 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 121: + case 122: /* ColLabel: IDENT */ #line 75 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 19883 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 122: + case 123: /* ColLabel: other_keyword */ #line 76 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 19889 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 123: + case 124: /* ColLabel: unreserved_keyword */ #line 77 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 19895 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 124: + case 125: /* ColLabel: reserved_keyword */ #line 78 "third_party/libpg_query/grammar/statements/common.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 19901 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 125: + case 126: /* RenameStmt: ALTER SCHEMA name RENAME TO name */ #line 7 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_SCHEMA; - n->subname = (yyvsp[(3) - (6)].str); - n->newname = (yyvsp[(6) - (6)].str); + n->subname = (yyvsp[-3].str); + n->newname = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19914 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 126: + case 127: /* RenameStmt: ALTER TABLE relation_expr RENAME TO name */ #line 16 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(3) - (6)].range); + n->relation = (yyvsp[-3].range); n->subname = NULL; - n->newname = (yyvsp[(6) - (6)].str); + n->newname = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19928 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 127: + case 128: /* RenameStmt: ALTER TABLE IF_P EXISTS relation_expr RENAME TO name */ #line 26 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(5) - (8)].range); + n->relation = (yyvsp[-3].range); n->subname = NULL; - n->newname = (yyvsp[(8) - (8)].str); + n->newname = (yyvsp[0].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19942 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 128: + case 129: /* RenameStmt: ALTER SEQUENCE qualified_name RENAME TO name */ #line 36 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_SEQUENCE; - n->relation = (yyvsp[(3) - (6)].range); + n->relation = (yyvsp[-3].range); n->subname = NULL; - n->newname = (yyvsp[(6) - (6)].str); + n->newname = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19956 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 129: + case 130: /* RenameStmt: ALTER SEQUENCE IF_P EXISTS qualified_name RENAME TO name */ #line 46 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_SEQUENCE; - n->relation = (yyvsp[(5) - (8)].range); + n->relation = (yyvsp[-3].range); n->subname = NULL; - n->newname = (yyvsp[(8) - (8)].str); + n->newname = (yyvsp[0].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19970 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 130: + case 131: /* RenameStmt: ALTER VIEW qualified_name RENAME TO name */ #line 56 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_VIEW; - n->relation = (yyvsp[(3) - (6)].range); + n->relation = (yyvsp[-3].range); n->subname = NULL; - n->newname = (yyvsp[(6) - (6)].str); + n->newname = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 19984 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 131: + case 132: /* RenameStmt: ALTER VIEW IF_P EXISTS qualified_name RENAME TO name */ #line 66 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_VIEW; - n->relation = (yyvsp[(5) - (8)].range); + n->relation = (yyvsp[-3].range); n->subname = NULL; - n->newname = (yyvsp[(8) - (8)].str); + n->newname = (yyvsp[0].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 19998 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 132: + case 133: /* RenameStmt: ALTER INDEX qualified_name RENAME TO name */ #line 76 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_INDEX; - n->relation = (yyvsp[(3) - (6)].range); + n->relation = (yyvsp[-3].range); n->subname = NULL; - n->newname = (yyvsp[(6) - (6)].str); + n->newname = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 20012 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 133: + case 134: /* RenameStmt: ALTER INDEX IF_P EXISTS qualified_name RENAME TO name */ #line 86 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_INDEX; - n->relation = (yyvsp[(5) - (8)].range); + n->relation = (yyvsp[-3].range); n->subname = NULL; - n->newname = (yyvsp[(8) - (8)].str); + n->newname = (yyvsp[0].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 20026 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 134: + case 135: /* RenameStmt: ALTER TABLE relation_expr RENAME opt_column name TO name */ #line 96 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_COLUMN; n->relationType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(3) - (8)].range); - n->subname = (yyvsp[(6) - (8)].str); - n->newname = (yyvsp[(8) - (8)].str); + n->relation = (yyvsp[-5].range); + n->subname = (yyvsp[-2].str); + n->newname = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 20041 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 135: + case 136: /* RenameStmt: ALTER TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name */ #line 107 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_COLUMN; n->relationType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(5) - (10)].range); - n->subname = (yyvsp[(8) - (10)].str); - n->newname = (yyvsp[(10) - (10)].str); + n->relation = (yyvsp[-5].range); + n->subname = (yyvsp[-2].str); + n->newname = (yyvsp[0].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 20056 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 136: + case 137: /* RenameStmt: ALTER TABLE relation_expr RENAME CONSTRAINT name TO name */ #line 118 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_TABCONSTRAINT; - n->relation = (yyvsp[(3) - (8)].range); - n->subname = (yyvsp[(6) - (8)].str); - n->newname = (yyvsp[(8) - (8)].str); + n->relation = (yyvsp[-5].range); + n->subname = (yyvsp[-2].str); + n->newname = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 20070 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 137: + case 138: /* RenameStmt: ALTER TABLE IF_P EXISTS relation_expr RENAME CONSTRAINT name TO name */ #line 128 "third_party/libpg_query/grammar/statements/rename.y" - { + { PGRenameStmt *n = makeNode(PGRenameStmt); n->renameType = PG_OBJECT_TABCONSTRAINT; - n->relation = (yyvsp[(5) - (10)].range); - n->subname = (yyvsp[(8) - (10)].str); - n->newname = (yyvsp[(10) - (10)].str); + n->relation = (yyvsp[-5].range); + n->subname = (yyvsp[-2].str); + n->newname = (yyvsp[0].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 20084 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 138: + case 139: /* opt_column: COLUMN */ #line 140 "third_party/libpg_query/grammar/statements/rename.y" - { (yyval.ival) = COLUMN; ;} + { (yyval.ival) = COLUMN; } +#line 20090 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 139: + case 140: /* opt_column: %empty */ #line 141 "third_party/libpg_query/grammar/statements/rename.y" - { (yyval.ival) = 0; ;} + { (yyval.ival) = 0; } +#line 20096 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 140: + case 141: /* InsertStmt: opt_with_clause INSERT opt_or_action INTO insert_target opt_by_name_or_position insert_rest opt_on_conflict returning_clause */ #line 11 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyvsp[(7) - (9)].istmt)->relation = (yyvsp[(5) - (9)].range); - (yyvsp[(7) - (9)].istmt)->onConflictAlias = (yyvsp[(3) - (9)].onconflictshorthand); - (yyvsp[(7) - (9)].istmt)->onConflictClause = (yyvsp[(8) - (9)].onconflict); - (yyvsp[(7) - (9)].istmt)->returningList = (yyvsp[(9) - (9)].list); - (yyvsp[(7) - (9)].istmt)->withClause = (yyvsp[(1) - (9)].with); - (yyvsp[(7) - (9)].istmt)->insert_column_order = (yyvsp[(6) - (9)].bynameorposition); - (yyval.node) = (PGNode *) (yyvsp[(7) - (9)].istmt); - ;} - break; - - case 141: + { + (yyvsp[-2].istmt)->relation = (yyvsp[-4].range); + (yyvsp[-2].istmt)->onConflictAlias = (yyvsp[-6].onconflictshorthand); + (yyvsp[-2].istmt)->onConflictClause = (yyvsp[-1].onconflict); + (yyvsp[-2].istmt)->returningList = (yyvsp[0].list); + (yyvsp[-2].istmt)->withClause = (yyvsp[-8].with); + (yyvsp[-2].istmt)->insert_column_order = (yyvsp[-3].bynameorposition); + (yyval.node) = (PGNode *) (yyvsp[-2].istmt); + } +#line 20110 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 142: /* insert_rest: SelectStmt */ #line 24 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.istmt) = makeNode(PGInsertStmt); (yyval.istmt)->cols = NIL; - (yyval.istmt)->selectStmt = (yyvsp[(1) - (1)].node); - ;} + (yyval.istmt)->selectStmt = (yyvsp[0].node); + } +#line 20120 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 142: + case 143: /* insert_rest: OVERRIDING override_kind VALUE_P SelectStmt */ #line 30 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.istmt) = makeNode(PGInsertStmt); (yyval.istmt)->cols = NIL; - (yyval.istmt)->override = (yyvsp[(2) - (4)].override); - (yyval.istmt)->selectStmt = (yyvsp[(4) - (4)].node); - ;} + (yyval.istmt)->override = (yyvsp[-2].override); + (yyval.istmt)->selectStmt = (yyvsp[0].node); + } +#line 20131 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 143: + case 144: /* insert_rest: '(' insert_column_list ')' SelectStmt */ #line 37 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.istmt) = makeNode(PGInsertStmt); - (yyval.istmt)->cols = (yyvsp[(2) - (4)].list); - (yyval.istmt)->selectStmt = (yyvsp[(4) - (4)].node); - ;} + (yyval.istmt)->cols = (yyvsp[-2].list); + (yyval.istmt)->selectStmt = (yyvsp[0].node); + } +#line 20141 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 144: + case 145: /* insert_rest: '(' insert_column_list ')' OVERRIDING override_kind VALUE_P SelectStmt */ #line 43 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.istmt) = makeNode(PGInsertStmt); - (yyval.istmt)->cols = (yyvsp[(2) - (7)].list); - (yyval.istmt)->override = (yyvsp[(5) - (7)].override); - (yyval.istmt)->selectStmt = (yyvsp[(7) - (7)].node); - ;} + (yyval.istmt)->cols = (yyvsp[-5].list); + (yyval.istmt)->override = (yyvsp[-2].override); + (yyval.istmt)->selectStmt = (yyvsp[0].node); + } +#line 20152 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 145: + case 146: /* insert_rest: DEFAULT VALUES */ #line 50 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.istmt) = makeNode(PGInsertStmt); (yyval.istmt)->cols = NIL; (yyval.istmt)->selectStmt = NULL; - ;} + } +#line 20162 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 146: + case 147: /* insert_target: qualified_name */ #line 60 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.range) = (yyvsp[(1) - (1)].range); - ;} + { + (yyval.range) = (yyvsp[0].range); + } +#line 20170 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 147: + case 148: /* insert_target: qualified_name AS ColId */ #line 64 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyvsp[(1) - (3)].range)->alias = makeAlias((yyvsp[(3) - (3)].str), NIL); - (yyval.range) = (yyvsp[(1) - (3)].range); - ;} + { + (yyvsp[-2].range)->alias = makeAlias((yyvsp[0].str), NIL); + (yyval.range) = (yyvsp[-2].range); + } +#line 20179 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 148: + case 149: /* opt_by_name_or_position: BY NAME_P */ #line 71 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.bynameorposition) = PG_INSERT_BY_NAME; ;} + { (yyval.bynameorposition) = PG_INSERT_BY_NAME; } +#line 20185 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 149: + case 150: /* opt_by_name_or_position: BY POSITION */ #line 72 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.bynameorposition) = PG_INSERT_BY_POSITION; ;} + { (yyval.bynameorposition) = PG_INSERT_BY_POSITION; } +#line 20191 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 150: + case 151: /* opt_by_name_or_position: %empty */ #line 73 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.bynameorposition) = PG_INSERT_BY_POSITION; ;} + { (yyval.bynameorposition) = PG_INSERT_BY_POSITION; } +#line 20197 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 151: + case 152: /* opt_conf_expr: '(' index_params ')' where_clause */ #line 78 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.infer) = makeNode(PGInferClause); - (yyval.infer)->indexElems = (yyvsp[(2) - (4)].list); - (yyval.infer)->whereClause = (yyvsp[(4) - (4)].node); + (yyval.infer)->indexElems = (yyvsp[-2].list); + (yyval.infer)->whereClause = (yyvsp[0].node); (yyval.infer)->conname = NULL; - (yyval.infer)->location = (yylsp[(1) - (4)]); - ;} + (yyval.infer)->location = (yylsp[-3]); + } +#line 20209 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 152: + case 153: /* opt_conf_expr: ON CONSTRAINT name */ #line 87 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.infer) = makeNode(PGInferClause); (yyval.infer)->indexElems = NIL; (yyval.infer)->whereClause = NULL; - (yyval.infer)->conname = (yyvsp[(3) - (3)].str); - (yyval.infer)->location = (yylsp[(1) - (3)]); - ;} + (yyval.infer)->conname = (yyvsp[0].str); + (yyval.infer)->location = (yylsp[-2]); + } +#line 20221 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 153: + case 154: /* opt_conf_expr: %empty */ #line 95 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.infer) = NULL; - ;} + } +#line 20229 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 154: + case 155: /* opt_with_clause: with_clause */ #line 102 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.with) = (yyvsp[(1) - (1)].with); ;} + { (yyval.with) = (yyvsp[0].with); } +#line 20235 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 155: + case 156: /* opt_with_clause: %empty */ #line 103 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.with) = NULL; ;} + { (yyval.with) = NULL; } +#line 20241 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 156: + case 157: /* insert_column_item: ColId opt_indirection */ #line 109 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = (yyvsp[(1) - (2)].str); - (yyval.target)->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + (yyval.target)->name = (yyvsp[-1].str); + (yyval.target)->indirection = check_indirection((yyvsp[0].list), yyscanner); (yyval.target)->val = NULL; - (yyval.target)->location = (yylsp[(1) - (2)]); - ;} + (yyval.target)->location = (yylsp[-1]); + } +#line 20253 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 157: + case 158: /* set_clause: set_target '=' a_expr */ #line 121 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyvsp[(1) - (3)].target)->val = (PGNode *) (yyvsp[(3) - (3)].node); - (yyval.list) = list_make1((yyvsp[(1) - (3)].target)); - ;} + { + (yyvsp[-2].target)->val = (PGNode *) (yyvsp[0].node); + (yyval.list) = list_make1((yyvsp[-2].target)); + } +#line 20262 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 158: + case 159: /* set_clause: '(' set_target_list ')' '=' a_expr */ #line 126 "third_party/libpg_query/grammar/statements/insert.y" - { - int ncolumns = list_length((yyvsp[(2) - (5)].list)); + { + int ncolumns = list_length((yyvsp[-3].list)); int i = 1; PGListCell *col_cell; /* Create a PGMultiAssignRef source for each target */ - foreach(col_cell, (yyvsp[(2) - (5)].list)) + foreach(col_cell, (yyvsp[-3].list)) { PGResTarget *res_col = (PGResTarget *) lfirst(col_cell); PGMultiAssignRef *r = makeNode(PGMultiAssignRef); - r->source = (PGNode *) (yyvsp[(5) - (5)].node); + r->source = (PGNode *) (yyvsp[0].node); r->colno = i; r->ncolumns = ncolumns; res_col->val = (PGNode *) r; i++; } - (yyval.list) = (yyvsp[(2) - (5)].list); - ;} + (yyval.list) = (yyvsp[-3].list); + } +#line 20287 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 159: + case 160: /* opt_or_action: OR REPLACE */ #line 151 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.onconflictshorthand) = PG_ONCONFLICT_ALIAS_REPLACE; - ;} + } +#line 20295 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 160: + case 161: /* opt_or_action: OR IGNORE_P */ #line 156 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.onconflictshorthand) = PG_ONCONFLICT_ALIAS_IGNORE; - ;} + } +#line 20303 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 161: + case 162: /* opt_or_action: %empty */ #line 160 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.onconflictshorthand) = PG_ONCONFLICT_ALIAS_NONE; - ;} + } +#line 20311 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 162: + case 163: /* opt_on_conflict: ON CONFLICT opt_conf_expr DO UPDATE SET set_clause_list_opt_comma where_clause */ #line 167 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.onconflict) = makeNode(PGOnConflictClause); (yyval.onconflict)->action = PG_ONCONFLICT_UPDATE; - (yyval.onconflict)->infer = (yyvsp[(3) - (8)].infer); - (yyval.onconflict)->targetList = (yyvsp[(7) - (8)].list); - (yyval.onconflict)->whereClause = (yyvsp[(8) - (8)].node); - (yyval.onconflict)->location = (yylsp[(1) - (8)]); - ;} + (yyval.onconflict)->infer = (yyvsp[-5].infer); + (yyval.onconflict)->targetList = (yyvsp[-1].list); + (yyval.onconflict)->whereClause = (yyvsp[0].node); + (yyval.onconflict)->location = (yylsp[-7]); + } +#line 20324 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 163: + case 164: /* opt_on_conflict: ON CONFLICT opt_conf_expr DO NOTHING */ #line 177 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.onconflict) = makeNode(PGOnConflictClause); (yyval.onconflict)->action = PG_ONCONFLICT_NOTHING; - (yyval.onconflict)->infer = (yyvsp[(3) - (5)].infer); + (yyval.onconflict)->infer = (yyvsp[-2].infer); (yyval.onconflict)->targetList = NIL; (yyval.onconflict)->whereClause = NULL; - (yyval.onconflict)->location = (yylsp[(1) - (5)]); - ;} + (yyval.onconflict)->location = (yylsp[-4]); + } +#line 20337 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 164: + case 165: /* opt_on_conflict: %empty */ #line 186 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.onconflict) = NULL; - ;} + } +#line 20345 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 165: + case 166: /* index_elem: ColId opt_collate opt_class opt_asc_desc opt_nulls_order */ #line 193 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.ielem) = makeNode(PGIndexElem); - (yyval.ielem)->name = (yyvsp[(1) - (5)].str); + (yyval.ielem)->name = (yyvsp[-4].str); (yyval.ielem)->expr = NULL; (yyval.ielem)->indexcolname = NULL; - (yyval.ielem)->collation = (yyvsp[(2) - (5)].list); - (yyval.ielem)->opclass = (yyvsp[(3) - (5)].list); - (yyval.ielem)->ordering = (yyvsp[(4) - (5)].sortorder); - (yyval.ielem)->nulls_ordering = (yyvsp[(5) - (5)].nullorder); - ;} + (yyval.ielem)->collation = (yyvsp[-3].list); + (yyval.ielem)->opclass = (yyvsp[-2].list); + (yyval.ielem)->ordering = (yyvsp[-1].sortorder); + (yyval.ielem)->nulls_ordering = (yyvsp[0].nullorder); + } +#line 20360 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 166: + case 167: /* index_elem: func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order */ #line 204 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.ielem) = makeNode(PGIndexElem); (yyval.ielem)->name = NULL; - (yyval.ielem)->expr = (yyvsp[(1) - (5)].node); + (yyval.ielem)->expr = (yyvsp[-4].node); (yyval.ielem)->indexcolname = NULL; - (yyval.ielem)->collation = (yyvsp[(2) - (5)].list); - (yyval.ielem)->opclass = (yyvsp[(3) - (5)].list); - (yyval.ielem)->ordering = (yyvsp[(4) - (5)].sortorder); - (yyval.ielem)->nulls_ordering = (yyvsp[(5) - (5)].nullorder); - ;} + (yyval.ielem)->collation = (yyvsp[-3].list); + (yyval.ielem)->opclass = (yyvsp[-2].list); + (yyval.ielem)->ordering = (yyvsp[-1].sortorder); + (yyval.ielem)->nulls_ordering = (yyvsp[0].nullorder); + } +#line 20375 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 167: + case 168: /* index_elem: '(' a_expr ')' opt_collate opt_class opt_asc_desc opt_nulls_order */ #line 215 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.ielem) = makeNode(PGIndexElem); (yyval.ielem)->name = NULL; - (yyval.ielem)->expr = (yyvsp[(2) - (7)].node); + (yyval.ielem)->expr = (yyvsp[-5].node); (yyval.ielem)->indexcolname = NULL; - (yyval.ielem)->collation = (yyvsp[(4) - (7)].list); - (yyval.ielem)->opclass = (yyvsp[(5) - (7)].list); - (yyval.ielem)->ordering = (yyvsp[(6) - (7)].sortorder); - (yyval.ielem)->nulls_ordering = (yyvsp[(7) - (7)].nullorder); - ;} + (yyval.ielem)->collation = (yyvsp[-3].list); + (yyval.ielem)->opclass = (yyvsp[-2].list); + (yyval.ielem)->ordering = (yyvsp[-1].sortorder); + (yyval.ielem)->nulls_ordering = (yyvsp[0].nullorder); + } +#line 20390 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 168: + case 169: /* returning_clause: RETURNING target_list */ #line 229 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 20396 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 169: + case 170: /* returning_clause: %empty */ #line 230 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 20402 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 170: + case 171: /* override_kind: USER */ #line 236 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.override) = PG_OVERRIDING_USER_VALUE; ;} + { (yyval.override) = PG_OVERRIDING_USER_VALUE; } +#line 20408 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 171: + case 172: /* override_kind: SYSTEM_P */ #line 237 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.override) = OVERRIDING_SYSTEM_VALUE; ;} + { (yyval.override) = OVERRIDING_SYSTEM_VALUE; } +#line 20414 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 172: + case 173: /* set_target_list: set_target */ #line 242 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].target)); ;} + { (yyval.list) = list_make1((yyvsp[0].target)); } +#line 20420 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 173: + case 174: /* set_target_list: set_target_list ',' set_target */ #line 243 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list),(yyvsp[(3) - (3)].target)); ;} + { (yyval.list) = lappend((yyvsp[-2].list),(yyvsp[0].target)); } +#line 20426 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 174: + case 175: /* opt_collate: COLLATE any_name */ #line 249 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 20432 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 175: + case 176: /* opt_collate: %empty */ #line 250 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 20438 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 176: + case 177: /* opt_class: any_name */ #line 254 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 20444 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 177: + case 178: /* opt_class: %empty */ #line 255 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 20450 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 178: + case 179: /* insert_column_list: insert_column_item */ #line 261 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].target)); ;} + { (yyval.list) = list_make1((yyvsp[0].target)); } +#line 20456 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 179: + case 180: /* insert_column_list: insert_column_list ',' insert_column_item */ #line 263 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].target)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].target)); } +#line 20462 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 180: + case 181: /* set_clause_list: set_clause */ #line 268 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 20468 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 181: + case 182: /* set_clause_list: set_clause_list ',' set_clause */ #line 269 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = list_concat((yyvsp[(1) - (3)].list),(yyvsp[(3) - (3)].list)); ;} + { (yyval.list) = list_concat((yyvsp[-2].list),(yyvsp[0].list)); } +#line 20474 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 182: + case 183: /* set_clause_list_opt_comma: set_clause_list */ #line 273 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 20480 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 183: + case 184: /* set_clause_list_opt_comma: set_clause_list ',' */ #line 274 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 20486 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 184: + case 185: /* index_params: index_elem */ #line 277 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].ielem)); ;} + { (yyval.list) = list_make1((yyvsp[0].ielem)); } +#line 20492 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 185: + case 186: /* index_params: index_params ',' index_elem */ #line 278 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].ielem)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].ielem)); } +#line 20498 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 186: + case 187: /* set_target: ColId opt_indirection */ #line 284 "third_party/libpg_query/grammar/statements/insert.y" - { + { (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = (yyvsp[(1) - (2)].str); - (yyval.target)->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + (yyval.target)->name = (yyvsp[-1].str); + (yyval.target)->indirection = check_indirection((yyvsp[0].list), yyscanner); (yyval.target)->val = NULL; /* upper production sets this */ - (yyval.target)->location = (yylsp[(1) - (2)]); - ;} + (yyval.target)->location = (yylsp[-1]); + } +#line 20510 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 187: + case 188: /* CreateTypeStmt: CREATE_P TYPE_P qualified_name AS ENUM_P select_with_parens */ #line 8 "third_party/libpg_query/grammar/statements/create_type.y" - { + { PGCreateTypeStmt *n = makeNode(PGCreateTypeStmt); - n->typeName = (yyvsp[(3) - (6)].range); + n->typeName = (yyvsp[-3].range); n->kind = PG_NEWTYPE_ENUM; - n->query = (yyvsp[(6) - (6)].node); + n->query = (yyvsp[0].node); n->vals = NULL; (yyval.node) = (PGNode *)n; - ;} + } +#line 20523 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 188: + case 189: /* CreateTypeStmt: CREATE_P TYPE_P qualified_name AS ENUM_P '(' opt_enum_val_list ')' */ #line 17 "third_party/libpg_query/grammar/statements/create_type.y" - { + { PGCreateTypeStmt *n = makeNode(PGCreateTypeStmt); - n->typeName = (yyvsp[(3) - (8)].range); + n->typeName = (yyvsp[-5].range); n->kind = PG_NEWTYPE_ENUM; - n->vals = (yyvsp[(7) - (8)].list); + n->vals = (yyvsp[-1].list); n->query = NULL; (yyval.node) = (PGNode *)n; - ;} + } +#line 20536 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 189: + case 190: /* CreateTypeStmt: CREATE_P TYPE_P qualified_name AS Typename */ #line 26 "third_party/libpg_query/grammar/statements/create_type.y" - { + { PGCreateTypeStmt *n = makeNode(PGCreateTypeStmt); - n->typeName = (yyvsp[(3) - (5)].range); + n->typeName = (yyvsp[-2].range); n->query = NULL; - auto name = std::string(reinterpret_cast((yyvsp[(5) - (5)].typnam)->names->tail->data.ptr_value)->val.str); + auto name = std::string(reinterpret_cast((yyvsp[0].typnam)->names->tail->data.ptr_value)->val.str); if (name == "enum") { n->kind = PG_NEWTYPE_ENUM; - n->vals = (yyvsp[(5) - (5)].typnam)->typmods; + n->vals = (yyvsp[0].typnam)->typmods; } else { n->kind = PG_NEWTYPE_ALIAS; - n->ofType = (yyvsp[(5) - (5)].typnam); + n->ofType = (yyvsp[0].typnam); } (yyval.node) = (PGNode *)n; - ;} + } +#line 20555 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 190: + case 191: /* opt_enum_val_list: enum_val_list */ #line 46 "third_party/libpg_query/grammar/statements/create_type.y" - { (yyval.list) = (yyvsp[(1) - (1)].list);;} + { (yyval.list) = (yyvsp[0].list);} +#line 20561 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 191: + case 192: /* opt_enum_val_list: %empty */ #line 47 "third_party/libpg_query/grammar/statements/create_type.y" - {(yyval.list) = NIL;;} + {(yyval.list) = NIL;} +#line 20567 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 192: + case 193: /* enum_val_list: Sconst */ #line 51 "third_party/libpg_query/grammar/statements/create_type.y" - { - (yyval.list) = list_make1(makeStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)]))); - ;} + { + (yyval.list) = list_make1(makeStringConst((yyvsp[0].str), (yylsp[0]))); + } +#line 20575 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 193: + case 194: /* enum_val_list: enum_val_list ',' Sconst */ #line 55 "third_party/libpg_query/grammar/statements/create_type.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeStringConst((yyvsp[(3) - (3)].str), (yylsp[(3) - (3)]))); - ;} + { + (yyval.list) = lappend((yyvsp[-2].list), makeStringConst((yyvsp[0].str), (yylsp[0]))); + } +#line 20583 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 194: + case 195: /* PragmaStmt: PRAGMA_P ColId */ #line 8 "third_party/libpg_query/grammar/statements/pragma.y" - { + { PGPragmaStmt *n = makeNode(PGPragmaStmt); n->kind = PG_PRAGMA_TYPE_NOTHING; - n->name = (yyvsp[(2) - (2)].str); + n->name = (yyvsp[0].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 20594 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 195: + case 196: /* PragmaStmt: PRAGMA_P ColId '=' var_list */ #line 15 "third_party/libpg_query/grammar/statements/pragma.y" - { + { PGPragmaStmt *n = makeNode(PGPragmaStmt); n->kind = PG_PRAGMA_TYPE_ASSIGNMENT; - n->name = (yyvsp[(2) - (4)].str); - n->args = (yyvsp[(4) - (4)].list); + n->name = (yyvsp[-2].str); + n->args = (yyvsp[0].list); (yyval.node) = (PGNode *)n; - ;} + } +#line 20606 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 196: + case 197: /* PragmaStmt: PRAGMA_P ColId '(' func_arg_list ')' */ #line 23 "third_party/libpg_query/grammar/statements/pragma.y" - { + { PGPragmaStmt *n = makeNode(PGPragmaStmt); n->kind = PG_PRAGMA_TYPE_CALL; - n->name = (yyvsp[(2) - (5)].str); - n->args = (yyvsp[(4) - (5)].list); + n->name = (yyvsp[-3].str); + n->args = (yyvsp[-1].list); (yyval.node) = (PGNode *)n; - ;} + } +#line 20618 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 197: + case 198: /* CreateSeqStmt: CREATE_P OptTemp SEQUENCE qualified_name OptSeqOptList */ #line 10 "third_party/libpg_query/grammar/statements/create_sequence.y" - { + { PGCreateSeqStmt *n = makeNode(PGCreateSeqStmt); - (yyvsp[(4) - (5)].range)->relpersistence = (yyvsp[(2) - (5)].ival); - n->sequence = (yyvsp[(4) - (5)].range); - n->options = (yyvsp[(5) - (5)].list); + (yyvsp[-1].range)->relpersistence = (yyvsp[-3].ival); + n->sequence = (yyvsp[-1].range); + n->options = (yyvsp[0].list); n->ownerId = InvalidOid; n->onconflict = PG_ERROR_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 20632 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 198: + case 199: /* CreateSeqStmt: CREATE_P OptTemp SEQUENCE IF_P NOT EXISTS qualified_name OptSeqOptList */ #line 20 "third_party/libpg_query/grammar/statements/create_sequence.y" - { + { PGCreateSeqStmt *n = makeNode(PGCreateSeqStmt); - (yyvsp[(7) - (8)].range)->relpersistence = (yyvsp[(2) - (8)].ival); - n->sequence = (yyvsp[(7) - (8)].range); - n->options = (yyvsp[(8) - (8)].list); + (yyvsp[-1].range)->relpersistence = (yyvsp[-6].ival); + n->sequence = (yyvsp[-1].range); + n->options = (yyvsp[0].list); n->ownerId = InvalidOid; n->onconflict = PG_IGNORE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 20646 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 199: + case 200: /* CreateSeqStmt: CREATE_P OR REPLACE OptTemp SEQUENCE qualified_name OptSeqOptList */ #line 30 "third_party/libpg_query/grammar/statements/create_sequence.y" - { + { PGCreateSeqStmt *n = makeNode(PGCreateSeqStmt); - (yyvsp[(6) - (7)].range)->relpersistence = (yyvsp[(4) - (7)].ival); - n->sequence = (yyvsp[(6) - (7)].range); - n->options = (yyvsp[(7) - (7)].list); + (yyvsp[-1].range)->relpersistence = (yyvsp[-3].ival); + n->sequence = (yyvsp[-1].range); + n->options = (yyvsp[0].list); n->ownerId = InvalidOid; n->onconflict = PG_REPLACE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 20660 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 200: + case 201: /* OptSeqOptList: SeqOptList */ #line 42 "third_party/libpg_query/grammar/statements/create_sequence.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 20666 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 201: + case 202: /* OptSeqOptList: %empty */ #line 43 "third_party/libpg_query/grammar/statements/create_sequence.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 20672 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 202: + case 203: /* CreateSecretStmt: CREATE_P opt_persist SECRET opt_secret_name opt_storage_specifier '(' copy_generic_opt_list ')' */ #line 8 "third_party/libpg_query/grammar/statements/create_secret.y" - { + { PGCreateSecretStmt *n = makeNode(PGCreateSecretStmt); - n->persist_type = (yyvsp[(2) - (8)].str); - n->secret_name = (yyvsp[(4) - (8)].str); - n->secret_storage = (yyvsp[(5) - (8)].str); - n->options = (yyvsp[(7) - (8)].list); + n->persist_type = (yyvsp[-6].str); + n->secret_name = (yyvsp[-4].str); + n->secret_storage = (yyvsp[-3].str); + n->options = (yyvsp[-1].list); n->onconflict = PG_ERROR_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 20686 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 203: + case 204: /* CreateSecretStmt: CREATE_P opt_persist SECRET IF_P NOT EXISTS opt_secret_name opt_storage_specifier '(' copy_generic_opt_list ')' */ #line 18 "third_party/libpg_query/grammar/statements/create_secret.y" - { + { PGCreateSecretStmt *n = makeNode(PGCreateSecretStmt); - n->persist_type = (yyvsp[(2) - (11)].str); - n->secret_name = (yyvsp[(7) - (11)].str); - n->secret_storage = (yyvsp[(8) - (11)].str); - n->options = (yyvsp[(10) - (11)].list); + n->persist_type = (yyvsp[-9].str); + n->secret_name = (yyvsp[-4].str); + n->secret_storage = (yyvsp[-3].str); + n->options = (yyvsp[-1].list); n->onconflict = PG_IGNORE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 20700 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 204: + case 205: /* CreateSecretStmt: CREATE_P OR REPLACE opt_persist SECRET opt_secret_name opt_storage_specifier '(' copy_generic_opt_list ')' */ #line 28 "third_party/libpg_query/grammar/statements/create_secret.y" - { + { PGCreateSecretStmt *n = makeNode(PGCreateSecretStmt); - n->persist_type = (yyvsp[(4) - (10)].str); - n->secret_name = (yyvsp[(6) - (10)].str); - n->secret_storage = (yyvsp[(7) - (10)].str); - n->options = (yyvsp[(9) - (10)].list); + n->persist_type = (yyvsp[-6].str); + n->secret_name = (yyvsp[-4].str); + n->secret_storage = (yyvsp[-3].str); + n->options = (yyvsp[-1].list); n->onconflict = PG_REPLACE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 20714 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 205: + case 206: /* opt_secret_name: %empty */ #line 40 "third_party/libpg_query/grammar/statements/create_secret.y" - { (yyval.str) = NULL; ;} + { (yyval.str) = NULL; } +#line 20720 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 206: + case 207: /* opt_secret_name: ColId */ #line 41 "third_party/libpg_query/grammar/statements/create_secret.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 20726 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 207: + case 208: /* opt_persist: %empty */ #line 45 "third_party/libpg_query/grammar/statements/create_secret.y" - { (yyval.str) = pstrdup("default"); ;} + { (yyval.str) = pstrdup("default"); } +#line 20732 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 208: + case 209: /* opt_persist: TEMPORARY */ #line 46 "third_party/libpg_query/grammar/statements/create_secret.y" - { (yyval.str) = pstrdup("temporary"); ;} + { (yyval.str) = pstrdup("temporary"); } +#line 20738 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 209: + case 210: /* opt_persist: PERSISTENT */ #line 47 "third_party/libpg_query/grammar/statements/create_secret.y" - { (yyval.str) = pstrdup("persistent"); ;} + { (yyval.str) = pstrdup("persistent"); } +#line 20744 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 210: + case 211: /* opt_storage_specifier: %empty */ #line 51 "third_party/libpg_query/grammar/statements/create_secret.y" - { (yyval.str) = pstrdup(""); ;} + { (yyval.str) = pstrdup(""); } +#line 20750 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 211: + case 212: /* opt_storage_specifier: IN_P IDENT */ #line 52 "third_party/libpg_query/grammar/statements/create_secret.y" - { (yyval.str) = (yyvsp[(2) - (2)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 20756 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 213: /* UpdateExtensionsStmt: opt_with_clause UPDATE EXTENSIONS opt_column_list */ +#line 8 "third_party/libpg_query/grammar/statements/update_extensions.y" + { + PGUpdateExtensionsStmt *n = makeNode(PGUpdateExtensionsStmt); + n->extensions = (yyvsp[0].list); + + if ((yyvsp[-3].with)) { + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("Providing a with clause with an UPDATE EXTENSIONS statement is not allowed"), + parser_errposition((yylsp[-3])))); + break; + } + + (yyval.node) = (PGNode *)n; + } +#line 20775 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 212: + case 214: /* ExecuteStmt: EXECUTE name execute_param_clause */ #line 8 "third_party/libpg_query/grammar/statements/execute.y" - { + { PGExecuteStmt *n = makeNode(PGExecuteStmt); - n->name = (yyvsp[(2) - (3)].str); - n->params = (yyvsp[(3) - (3)].list); + n->name = (yyvsp[-1].str); + n->params = (yyvsp[0].list); (yyval.node) = (PGNode *) n; - ;} + } +#line 20786 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 213: + case 215: /* ExecuteStmt: CREATE_P OptTemp TABLE create_as_target AS EXECUTE name execute_param_clause opt_with_data */ #line 16 "third_party/libpg_query/grammar/statements/execute.y" - { + { PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); PGExecuteStmt *n = makeNode(PGExecuteStmt); - n->name = (yyvsp[(7) - (9)].str); - n->params = (yyvsp[(8) - (9)].list); + n->name = (yyvsp[-2].str); + n->params = (yyvsp[-1].list); ctas->query = (PGNode *) n; - ctas->into = (yyvsp[(4) - (9)].into); + ctas->into = (yyvsp[-5].into); ctas->relkind = PG_OBJECT_TABLE; ctas->is_select_into = false; ctas->onconflict = PG_ERROR_ON_CONFLICT; /* cram additional flags into the PGIntoClause */ - (yyvsp[(4) - (9)].into)->rel->relpersistence = (yyvsp[(2) - (9)].ival); - (yyvsp[(4) - (9)].into)->skipData = !((yyvsp[(9) - (9)].boolean)); + (yyvsp[-5].into)->rel->relpersistence = (yyvsp[-7].ival); + (yyvsp[-5].into)->skipData = !((yyvsp[0].boolean)); (yyval.node) = (PGNode *) ctas; - ;} + } +#line 20806 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 214: + case 216: /* ExecuteStmt: CREATE_P OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE name execute_param_clause opt_with_data */ #line 33 "third_party/libpg_query/grammar/statements/execute.y" - { + { PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); PGExecuteStmt *n = makeNode(PGExecuteStmt); - n->name = (yyvsp[(10) - (12)].str); - n->params = (yyvsp[(11) - (12)].list); + n->name = (yyvsp[-2].str); + n->params = (yyvsp[-1].list); ctas->query = (PGNode *) n; - ctas->into = (yyvsp[(7) - (12)].into); + ctas->into = (yyvsp[-5].into); ctas->relkind = PG_OBJECT_TABLE; ctas->is_select_into = false; ctas->onconflict = PG_IGNORE_ON_CONFLICT; /* cram additional flags into the PGIntoClause */ - (yyvsp[(7) - (12)].into)->rel->relpersistence = (yyvsp[(2) - (12)].ival); - (yyvsp[(7) - (12)].into)->skipData = !((yyvsp[(12) - (12)].boolean)); + (yyvsp[-5].into)->rel->relpersistence = (yyvsp[-10].ival); + (yyvsp[-5].into)->skipData = !((yyvsp[0].boolean)); (yyval.node) = (PGNode *) ctas; - ;} + } +#line 20826 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 215: + case 217: /* execute_param_expr: a_expr */ #line 52 "third_party/libpg_query/grammar/statements/execute.y" - { - (yyval.node) = (yyvsp[(1) - (1)].node); - ;} + { + (yyval.node) = (yyvsp[0].node); + } +#line 20834 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 216: + case 218: /* execute_param_expr: param_name COLON_EQUALS a_expr */ #line 56 "third_party/libpg_query/grammar/statements/execute.y" - { + { PGNamedArgExpr *na = makeNode(PGNamedArgExpr); - na->name = (yyvsp[(1) - (3)].str); - na->arg = (PGExpr *) (yyvsp[(3) - (3)].node); + na->name = (yyvsp[-2].str); + na->arg = (PGExpr *) (yyvsp[0].node); na->argnumber = -1; /* until determined */ - na->location = (yylsp[(1) - (3)]); + na->location = (yylsp[-2]); (yyval.node) = (PGNode *) na; - ;} + } +#line 20847 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 217: + case 219: /* execute_param_list: execute_param_expr */ #line 66 "third_party/libpg_query/grammar/statements/execute.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} + { + (yyval.list) = list_make1((yyvsp[0].node)); + } +#line 20855 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 218: + case 220: /* execute_param_list: execute_param_list ',' execute_param_expr */ #line 70 "third_party/libpg_query/grammar/statements/execute.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} + { + (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); + } +#line 20863 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 219: + case 221: /* execute_param_clause: '(' execute_param_list ')' */ #line 75 "third_party/libpg_query/grammar/statements/execute.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 20869 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 220: + case 222: /* execute_param_clause: %empty */ #line 76 "third_party/libpg_query/grammar/statements/execute.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 20875 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 221: + case 223: /* AlterSeqStmt: ALTER SEQUENCE qualified_name SeqOptList */ #line 10 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { + { PGAlterSeqStmt *n = makeNode(PGAlterSeqStmt); - n->sequence = (yyvsp[(3) - (4)].range); - n->options = (yyvsp[(4) - (4)].list); + n->sequence = (yyvsp[-1].range); + n->options = (yyvsp[0].list); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 20887 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 222: + case 224: /* AlterSeqStmt: ALTER SEQUENCE IF_P EXISTS qualified_name SeqOptList */ #line 18 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { + { PGAlterSeqStmt *n = makeNode(PGAlterSeqStmt); - n->sequence = (yyvsp[(5) - (6)].range); - n->options = (yyvsp[(6) - (6)].list); + n->sequence = (yyvsp[-1].range); + n->options = (yyvsp[0].list); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 20899 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 223: + case 225: /* SeqOptList: SeqOptElem */ #line 29 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} + { (yyval.list) = list_make1((yyvsp[0].defelt)); } +#line 20905 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 224: + case 226: /* SeqOptList: SeqOptList SeqOptElem */ #line 30 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].defelt)); ;} + { (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].defelt)); } +#line 20911 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 225: + case 227: /* opt_with: WITH */ #line 34 "third_party/libpg_query/grammar/statements/alter_sequence.y" - {;} + {} +#line 20917 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 226: + case 228: /* opt_with: WITH_LA */ #line 35 "third_party/libpg_query/grammar/statements/alter_sequence.y" - {;} + {} +#line 20923 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 227: + case 229: /* opt_with: %empty */ #line 36 "third_party/libpg_query/grammar/statements/alter_sequence.y" - {;} + {} +#line 20929 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 228: + case 230: /* NumericOnly: FCONST */ #line 41 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.value) = makeFloat((yyvsp[(1) - (1)].str)); ;} + { (yyval.value) = makeFloat((yyvsp[0].str)); } +#line 20935 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 229: + case 231: /* NumericOnly: '+' FCONST */ #line 42 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.value) = makeFloat((yyvsp[(2) - (2)].str)); ;} + { (yyval.value) = makeFloat((yyvsp[0].str)); } +#line 20941 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 230: + case 232: /* NumericOnly: '-' FCONST */ #line 44 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.value) = makeFloat((yyvsp[(2) - (2)].str)); + { + (yyval.value) = makeFloat((yyvsp[0].str)); doNegateFloat((yyval.value)); - ;} + } +#line 20950 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 231: + case 233: /* NumericOnly: SignedIconst */ #line 48 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.value) = makeInteger((yyvsp[(1) - (1)].ival)); ;} + { (yyval.value) = makeInteger((yyvsp[0].ival)); } +#line 20956 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 232: + case 234: /* SeqOptElem: AS SimpleTypename */ #line 53 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("as", (PGNode *)(yyvsp[(2) - (2)].typnam), (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem("as", (PGNode *)(yyvsp[0].typnam), (yylsp[-1])); + } +#line 20964 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 233: + case 235: /* SeqOptElem: CACHE NumericOnly */ #line 57 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("cache", (PGNode *)(yyvsp[(2) - (2)].value), (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem("cache", (PGNode *)(yyvsp[0].value), (yylsp[-1])); + } +#line 20972 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 234: + case 236: /* SeqOptElem: CYCLE */ #line 61 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("cycle", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem("cycle", (PGNode *)makeInteger(true), (yylsp[0])); + } +#line 20980 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 235: + case 237: /* SeqOptElem: NO CYCLE */ #line 65 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("cycle", (PGNode *)makeInteger(false), (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem("cycle", (PGNode *)makeInteger(false), (yylsp[-1])); + } +#line 20988 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 236: + case 238: /* SeqOptElem: INCREMENT opt_by NumericOnly */ #line 69 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("increment", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("increment", (PGNode *)(yyvsp[0].value), (yylsp[-2])); + } +#line 20996 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 237: + case 239: /* SeqOptElem: MAXVALUE NumericOnly */ #line 73 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("maxvalue", (PGNode *)(yyvsp[(2) - (2)].value), (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem("maxvalue", (PGNode *)(yyvsp[0].value), (yylsp[-1])); + } +#line 21004 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 238: + case 240: /* SeqOptElem: MINVALUE NumericOnly */ #line 77 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("minvalue", (PGNode *)(yyvsp[(2) - (2)].value), (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem("minvalue", (PGNode *)(yyvsp[0].value), (yylsp[-1])); + } +#line 21012 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 239: + case 241: /* SeqOptElem: NO MAXVALUE */ #line 81 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("maxvalue", NULL, (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem("maxvalue", NULL, (yylsp[-1])); + } +#line 21020 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 240: + case 242: /* SeqOptElem: NO MINVALUE */ #line 85 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("minvalue", NULL, (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem("minvalue", NULL, (yylsp[-1])); + } +#line 21028 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 241: + case 243: /* SeqOptElem: OWNED BY any_name */ #line 89 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("owned_by", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("owned_by", (PGNode *)(yyvsp[0].list), (yylsp[-2])); + } +#line 21036 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 242: + case 244: /* SeqOptElem: SEQUENCE NAME_P any_name */ #line 93 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { + { /* not documented, only used by pg_dump */ - (yyval.defelt) = makeDefElem("sequence_name", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); - ;} + (yyval.defelt) = makeDefElem("sequence_name", (PGNode *)(yyvsp[0].list), (yylsp[-2])); + } +#line 21045 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 243: + case 245: /* SeqOptElem: START opt_with NumericOnly */ #line 98 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("start", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("start", (PGNode *)(yyvsp[0].value), (yylsp[-2])); + } +#line 21053 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 244: + case 246: /* SeqOptElem: RESTART */ #line 102 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("restart", NULL, (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem("restart", NULL, (yylsp[0])); + } +#line 21061 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 245: + case 247: /* SeqOptElem: RESTART opt_with NumericOnly */ #line 106 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("restart", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("restart", (PGNode *)(yyvsp[0].value), (yylsp[-2])); + } +#line 21069 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 246: + case 248: /* opt_by: BY */ #line 112 "third_party/libpg_query/grammar/statements/alter_sequence.y" - {;} + {} +#line 21075 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 247: + case 249: /* opt_by: %empty */ #line 113 "third_party/libpg_query/grammar/statements/alter_sequence.y" - {;} + {} +#line 21081 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 248: + case 250: /* SignedIconst: Iconst */ #line 117 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} + { (yyval.ival) = (yyvsp[0].ival); } +#line 21087 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 249: + case 251: /* SignedIconst: '+' Iconst */ #line 118 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.ival) = + (yyvsp[(2) - (2)].ival); ;} + { (yyval.ival) = + (yyvsp[0].ival); } +#line 21093 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 250: + case 252: /* SignedIconst: '-' Iconst */ #line 119 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.ival) = - (yyvsp[(2) - (2)].ival); ;} + { (yyval.ival) = - (yyvsp[0].ival); } +#line 21099 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 251: + case 253: /* DropSecretStmt: DROP opt_persist SECRET ColId opt_storage_drop_specifier */ #line 8 "third_party/libpg_query/grammar/statements/drop_secret.y" - { + { PGDropSecretStmt *n = makeNode(PGDropSecretStmt); - n->persist_type = (yyvsp[(2) - (5)].str); - n->secret_name = (yyvsp[(4) - (5)].str); - n->secret_storage = (yyvsp[(5) - (5)].str); + n->persist_type = (yyvsp[-3].str); + n->secret_name = (yyvsp[-1].str); + n->secret_storage = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 21112 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 252: + case 254: /* DropSecretStmt: DROP opt_persist SECRET IF_P EXISTS ColId opt_storage_drop_specifier */ #line 17 "third_party/libpg_query/grammar/statements/drop_secret.y" - { + { PGDropSecretStmt *n = makeNode(PGDropSecretStmt); - n->persist_type = (yyvsp[(2) - (7)].str); - n->secret_name = (yyvsp[(6) - (7)].str); - n->secret_storage = (yyvsp[(7) - (7)].str); + n->persist_type = (yyvsp[-5].str); + n->secret_name = (yyvsp[-1].str); + n->secret_storage = (yyvsp[0].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 21125 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 253: + case 255: /* opt_storage_drop_specifier: %empty */ #line 28 "third_party/libpg_query/grammar/statements/drop_secret.y" - { (yyval.str) = pstrdup(""); ;} + { (yyval.str) = pstrdup(""); } +#line 21131 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 254: + case 256: /* opt_storage_drop_specifier: FROM IDENT */ #line 29 "third_party/libpg_query/grammar/statements/drop_secret.y" - { (yyval.str) = (yyvsp[(2) - (2)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 21137 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 255: + case 257: /* TransactionStmt: ABORT_P opt_transaction */ #line 3 "third_party/libpg_query/grammar/statements/transaction.y" - { + { PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_ROLLBACK; n->options = NIL; + n->transaction_type = PG_TRANS_TYPE_DEFAULT; (yyval.node) = (PGNode *)n; - ;} + } +#line 21149 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 256: -#line 10 "third_party/libpg_query/grammar/statements/transaction.y" - { + case 258: /* TransactionStmt: BEGIN_P opt_transaction opt_transaction_type */ +#line 11 "third_party/libpg_query/grammar/statements/transaction.y" + { PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_BEGIN; + n->transaction_type = (yyvsp[0].transactiontype); (yyval.node) = (PGNode *)n; - ;} + } +#line 21160 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 257: -#line 16 "third_party/libpg_query/grammar/statements/transaction.y" - { + case 259: /* TransactionStmt: START opt_transaction opt_transaction_type */ +#line 18 "third_party/libpg_query/grammar/statements/transaction.y" + { PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_START; + n->transaction_type = (yyvsp[0].transactiontype); (yyval.node) = (PGNode *)n; - ;} + } +#line 21171 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 258: -#line 22 "third_party/libpg_query/grammar/statements/transaction.y" - { + case 260: /* TransactionStmt: COMMIT opt_transaction */ +#line 25 "third_party/libpg_query/grammar/statements/transaction.y" + { PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_COMMIT; n->options = NIL; + n->transaction_type = PG_TRANS_TYPE_DEFAULT; (yyval.node) = (PGNode *)n; - ;} + } +#line 21183 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 259: -#line 29 "third_party/libpg_query/grammar/statements/transaction.y" - { + case 261: /* TransactionStmt: END_P opt_transaction */ +#line 33 "third_party/libpg_query/grammar/statements/transaction.y" + { PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_COMMIT; n->options = NIL; + n->transaction_type = PG_TRANS_TYPE_DEFAULT; (yyval.node) = (PGNode *)n; - ;} + } +#line 21195 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 260: -#line 36 "third_party/libpg_query/grammar/statements/transaction.y" - { + case 262: /* TransactionStmt: ROLLBACK opt_transaction */ +#line 41 "third_party/libpg_query/grammar/statements/transaction.y" + { PGTransactionStmt *n = makeNode(PGTransactionStmt); n->kind = PG_TRANS_STMT_ROLLBACK; n->options = NIL; + n->transaction_type = PG_TRANS_TYPE_DEFAULT; (yyval.node) = (PGNode *)n; - ;} + } +#line 21207 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 263: /* opt_transaction: WORK */ +#line 51 "third_party/libpg_query/grammar/statements/transaction.y" + {} +#line 21213 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 264: /* opt_transaction: TRANSACTION */ +#line 52 "third_party/libpg_query/grammar/statements/transaction.y" + {} +#line 21219 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 265: /* opt_transaction: %empty */ +#line 53 "third_party/libpg_query/grammar/statements/transaction.y" + {} +#line 21225 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 261: -#line 45 "third_party/libpg_query/grammar/statements/transaction.y" - {;} + case 266: /* opt_transaction_type: READ_P ONLY */ +#line 57 "third_party/libpg_query/grammar/statements/transaction.y" + { (yyval.transactiontype) = PG_TRANS_TYPE_READ_ONLY; } +#line 21231 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 262: -#line 46 "third_party/libpg_query/grammar/statements/transaction.y" - {;} + case 267: /* opt_transaction_type: READ_P WRITE_P */ +#line 58 "third_party/libpg_query/grammar/statements/transaction.y" + { (yyval.transactiontype) = PG_TRANS_TYPE_READ_WRITE; } +#line 21237 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 263: -#line 47 "third_party/libpg_query/grammar/statements/transaction.y" - {;} + case 268: /* opt_transaction_type: %empty */ +#line 59 "third_party/libpg_query/grammar/statements/transaction.y" + { (yyval.transactiontype) = PG_TRANS_TYPE_DEFAULT; } +#line 21243 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 264: + case 269: /* UseStmt: USE_P qualified_name */ #line 3 "third_party/libpg_query/grammar/statements/use.y" - { + { PGUseStmt *n = makeNode(PGUseStmt); - n->name = (yyvsp[(2) - (2)].range); + n->name = (yyvsp[0].range); (yyval.node) = (PGNode *) n; - ;} + } +#line 21253 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 265: + case 270: /* CreateStmt: CREATE_P OptTemp TABLE qualified_name '(' OptTableElementList ')' OptWith OnCommitOption */ #line 9 "third_party/libpg_query/grammar/statements/create.y" - { + { PGCreateStmt *n = makeNode(PGCreateStmt); - (yyvsp[(4) - (9)].range)->relpersistence = (yyvsp[(2) - (9)].ival); - n->relation = (yyvsp[(4) - (9)].range); - n->tableElts = (yyvsp[(6) - (9)].list); + (yyvsp[-5].range)->relpersistence = (yyvsp[-7].ival); + n->relation = (yyvsp[-5].range); + n->tableElts = (yyvsp[-3].list); n->ofTypename = NULL; n->constraints = NIL; - n->options = (yyvsp[(8) - (9)].list); - n->oncommit = (yyvsp[(9) - (9)].oncommit); + n->options = (yyvsp[-1].list); + n->oncommit = (yyvsp[0].oncommit); n->onconflict = PG_ERROR_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 21270 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 266: + case 271: /* CreateStmt: CREATE_P OptTemp TABLE IF_P NOT EXISTS qualified_name '(' OptTableElementList ')' OptWith OnCommitOption */ #line 24 "third_party/libpg_query/grammar/statements/create.y" - { + { PGCreateStmt *n = makeNode(PGCreateStmt); - (yyvsp[(7) - (12)].range)->relpersistence = (yyvsp[(2) - (12)].ival); - n->relation = (yyvsp[(7) - (12)].range); - n->tableElts = (yyvsp[(9) - (12)].list); + (yyvsp[-5].range)->relpersistence = (yyvsp[-10].ival); + n->relation = (yyvsp[-5].range); + n->tableElts = (yyvsp[-3].list); n->ofTypename = NULL; n->constraints = NIL; - n->options = (yyvsp[(11) - (12)].list); - n->oncommit = (yyvsp[(12) - (12)].oncommit); + n->options = (yyvsp[-1].list); + n->oncommit = (yyvsp[0].oncommit); n->onconflict = PG_IGNORE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 21287 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 267: + case 272: /* CreateStmt: CREATE_P OR REPLACE OptTemp TABLE qualified_name '(' OptTableElementList ')' OptWith OnCommitOption */ #line 39 "third_party/libpg_query/grammar/statements/create.y" - { + { PGCreateStmt *n = makeNode(PGCreateStmt); - (yyvsp[(6) - (11)].range)->relpersistence = (yyvsp[(4) - (11)].ival); - n->relation = (yyvsp[(6) - (11)].range); - n->tableElts = (yyvsp[(8) - (11)].list); + (yyvsp[-5].range)->relpersistence = (yyvsp[-7].ival); + n->relation = (yyvsp[-5].range); + n->tableElts = (yyvsp[-3].list); n->ofTypename = NULL; n->constraints = NIL; - n->options = (yyvsp[(10) - (11)].list); - n->oncommit = (yyvsp[(11) - (11)].oncommit); + n->options = (yyvsp[-1].list); + n->oncommit = (yyvsp[0].oncommit); n->onconflict = PG_REPLACE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 21304 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 268: + case 273: /* ConstraintAttributeSpec: %empty */ #line 56 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = 0; ;} + { (yyval.ival) = 0; } +#line 21310 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 269: + case 274: /* ConstraintAttributeSpec: ConstraintAttributeSpec ConstraintAttributeElem */ #line 58 "third_party/libpg_query/grammar/statements/create.y" - { + { /* * We must complain about conflicting options. * We could, but choose not to, complain about redundant * options (ie, where $2's bit is already set in $1). */ - int newspec = (yyvsp[(1) - (2)].ival) | (yyvsp[(2) - (2)].ival); + int newspec = (yyvsp[-1].ival) | (yyvsp[0].ival); /* special message for this case */ if ((newspec & (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) == (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), - parser_errposition((yylsp[(2) - (2)])))); + parser_errposition((yylsp[0])))); /* generic message for other conflicts */ if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) || (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("conflicting constraint properties"), - parser_errposition((yylsp[(2) - (2)])))); + parser_errposition((yylsp[0])))); (yyval.ival) = newspec; - ;} + } +#line 21338 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 270: + case 275: /* def_arg: func_type */ #line 84 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)(yyvsp[(1) - (1)].typnam); ;} + { (yyval.node) = (PGNode *)(yyvsp[0].typnam); } +#line 21344 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 271: + case 276: /* def_arg: reserved_keyword */ #line 85 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)makeString(pstrdup((yyvsp[(1) - (1)].keyword))); ;} + { (yyval.node) = (PGNode *)makeString(pstrdup((yyvsp[0].keyword))); } +#line 21350 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 272: + case 277: /* def_arg: qual_all_Op */ #line 86 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)(yyvsp[(1) - (1)].list); ;} + { (yyval.node) = (PGNode *)(yyvsp[0].list); } +#line 21356 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 273: + case 278: /* def_arg: NumericOnly */ #line 87 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)(yyvsp[(1) - (1)].value); ;} + { (yyval.node) = (PGNode *)(yyvsp[0].value); } +#line 21362 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 274: + case 279: /* def_arg: Sconst */ #line 88 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)makeString((yyvsp[(1) - (1)].str)); ;} + { (yyval.node) = (PGNode *)makeString((yyvsp[0].str)); } +#line 21368 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 275: + case 280: /* def_arg: NONE */ #line 89 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)makeString(pstrdup((yyvsp[(1) - (1)].keyword))); ;} + { (yyval.node) = (PGNode *)makeString(pstrdup((yyvsp[0].keyword))); } +#line 21374 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 276: + case 281: /* OptParenthesizedSeqOptList: '(' SeqOptList ')' */ #line 93 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 21380 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 277: + case 282: /* OptParenthesizedSeqOptList: %empty */ #line 94 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 21386 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 278: + case 283: /* generic_option_arg: Sconst */ #line 99 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} + { (yyval.node) = (PGNode *) makeString((yyvsp[0].str)); } +#line 21392 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 279: + case 284: /* key_action: NO ACTION */ #line 104 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_FKCONSTR_ACTION_NOACTION; ;} + { (yyval.ival) = PG_FKCONSTR_ACTION_NOACTION; } +#line 21398 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 280: + case 285: /* key_action: RESTRICT */ #line 105 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_FKCONSTR_ACTION_RESTRICT; ;} + { (yyval.ival) = PG_FKCONSTR_ACTION_RESTRICT; } +#line 21404 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 281: + case 286: /* key_action: CASCADE */ #line 106 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_FKCONSTR_ACTION_CASCADE; ;} + { (yyval.ival) = PG_FKCONSTR_ACTION_CASCADE; } +#line 21410 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 282: + case 287: /* key_action: SET NULL_P */ #line 107 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_FKCONSTR_ACTION_SETNULL; ;} + { (yyval.ival) = PG_FKCONSTR_ACTION_SETNULL; } +#line 21416 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 283: + case 288: /* key_action: SET DEFAULT */ #line 108 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_FKCONSTR_ACTION_SETDEFAULT; ;} + { (yyval.ival) = PG_FKCONSTR_ACTION_SETDEFAULT; } +#line 21422 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 284: + case 289: /* ColConstraint: CONSTRAINT name ColConstraintElem */ #line 114 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = castNode(PGConstraint, (yyvsp[(3) - (3)].node)); - n->conname = (yyvsp[(2) - (3)].str); - n->location = (yylsp[(1) - (3)]); + { + PGConstraint *n = castNode(PGConstraint, (yyvsp[0].node)); + n->conname = (yyvsp[-1].str); + n->location = (yylsp[-2]); (yyval.node) = (PGNode *) n; - ;} + } +#line 21433 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 285: + case 290: /* ColConstraint: ColConstraintElem */ #line 120 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 21439 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 286: + case 291: /* ColConstraint: ConstraintAttr */ #line 121 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 21445 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 287: + case 292: /* ColConstraint: COLLATE any_name */ #line 123 "third_party/libpg_query/grammar/statements/create.y" - { + { /* * Note: the PGCollateClause is momentarily included in * the list built by ColQualList, but we split it out @@ -22135,155 +21454,169 @@ YYLTYPE yylloc; */ PGCollateClause *n = makeNode(PGCollateClause); n->arg = NULL; - n->collname = (yyvsp[(2) - (2)].list); - n->location = (yylsp[(1) - (2)]); + n->collname = (yyvsp[0].list); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *) n; - ;} + } +#line 21462 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 288: + case 293: /* ColConstraintElem: NOT NULL_P */ #line 140 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_NOTNULL; - n->location = (yylsp[(1) - (2)]); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *)n; - ;} + } +#line 21473 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 289: + case 294: /* ColConstraintElem: NULL_P */ #line 147 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_NULL; - n->location = (yylsp[(1) - (1)]); + n->location = (yylsp[0]); (yyval.node) = (PGNode *)n; - ;} + } +#line 21484 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 290: + case 295: /* ColConstraintElem: UNIQUE opt_definition */ #line 154 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_UNIQUE; - n->location = (yylsp[(1) - (2)]); + n->location = (yylsp[-1]); n->keys = NULL; - n->options = (yyvsp[(2) - (2)].list); + n->options = (yyvsp[0].list); n->indexname = NULL; (yyval.node) = (PGNode *)n; - ;} + } +#line 21498 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 291: + case 296: /* ColConstraintElem: PRIMARY KEY opt_definition */ #line 164 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_PRIMARY; - n->location = (yylsp[(1) - (3)]); + n->location = (yylsp[-2]); n->keys = NULL; - n->options = (yyvsp[(3) - (3)].list); + n->options = (yyvsp[0].list); n->indexname = NULL; (yyval.node) = (PGNode *)n; - ;} + } +#line 21512 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 292: + case 297: /* ColConstraintElem: CHECK_P '(' a_expr ')' opt_no_inherit */ #line 174 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_CHECK; - n->location = (yylsp[(1) - (5)]); - n->is_no_inherit = (yyvsp[(5) - (5)].boolean); - n->raw_expr = (yyvsp[(3) - (5)].node); + n->location = (yylsp[-4]); + n->is_no_inherit = (yyvsp[0].boolean); + n->raw_expr = (yyvsp[-2].node); n->cooked_expr = NULL; n->skip_validation = false; n->initially_valid = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 21528 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 293: + case 298: /* ColConstraintElem: USING COMPRESSION name */ #line 186 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_COMPRESSION; - n->location = (yylsp[(1) - (3)]); - n->compression_name = (yyvsp[(3) - (3)].str); + n->location = (yylsp[-2]); + n->compression_name = (yyvsp[0].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 21540 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 294: + case 299: /* ColConstraintElem: DEFAULT b_expr */ #line 194 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_DEFAULT; - n->location = (yylsp[(1) - (2)]); - n->raw_expr = (yyvsp[(2) - (2)].node); + n->location = (yylsp[-1]); + n->raw_expr = (yyvsp[0].node); n->cooked_expr = NULL; (yyval.node) = (PGNode *)n; - ;} + } +#line 21553 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 295: + case 300: /* ColConstraintElem: REFERENCES qualified_name opt_column_list key_match key_actions */ #line 203 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_FOREIGN; - n->location = (yylsp[(1) - (5)]); - n->pktable = (yyvsp[(2) - (5)].range); + n->location = (yylsp[-4]); + n->pktable = (yyvsp[-3].range); n->fk_attrs = NIL; - n->pk_attrs = (yyvsp[(3) - (5)].list); - n->fk_matchtype = (yyvsp[(4) - (5)].ival); - n->fk_upd_action = (char) ((yyvsp[(5) - (5)].ival) >> 8); - n->fk_del_action = (char) ((yyvsp[(5) - (5)].ival) & 0xFF); + n->pk_attrs = (yyvsp[-2].list); + n->fk_matchtype = (yyvsp[-1].ival); + n->fk_upd_action = (char) ((yyvsp[0].ival) >> 8); + n->fk_del_action = (char) ((yyvsp[0].ival) & 0xFF); n->skip_validation = false; n->initially_valid = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 21572 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 296: + case 301: /* GeneratedColumnType: VIRTUAL */ #line 220 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.constr) = PG_CONSTR_GENERATED_VIRTUAL; ;} + { (yyval.constr) = PG_CONSTR_GENERATED_VIRTUAL; } +#line 21578 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 297: + case 302: /* GeneratedColumnType: STORED */ #line 221 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.constr) = PG_CONSTR_GENERATED_STORED; ;} + { (yyval.constr) = PG_CONSTR_GENERATED_STORED; } +#line 21584 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 298: + case 303: /* opt_GeneratedColumnType: GeneratedColumnType */ #line 225 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.constr) = (yyvsp[(1) - (1)].constr); ;} + { (yyval.constr) = (yyvsp[0].constr); } +#line 21590 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 299: + case 304: /* opt_GeneratedColumnType: %empty */ #line 226 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.constr) = PG_CONSTR_GENERATED_VIRTUAL; ;} + { (yyval.constr) = PG_CONSTR_GENERATED_VIRTUAL; } +#line 21596 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 300: + case 305: /* GeneratedConstraintElem: GENERATED generated_when AS IDENTITY_P OptParenthesizedSeqOptList */ #line 231 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_IDENTITY; - n->generated_when = (yyvsp[(2) - (5)].ival); - n->options = (yyvsp[(5) - (5)].list); - n->location = (yylsp[(1) - (5)]); + n->generated_when = (yyvsp[-3].ival); + n->options = (yyvsp[0].list); + n->location = (yylsp[-4]); (yyval.node) = (PGNode *)n; - ;} + } +#line 21609 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 301: + case 306: /* GeneratedConstraintElem: GENERATED generated_when AS '(' a_expr ')' opt_GeneratedColumnType */ #line 240 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); - n->contype = (yyvsp[(7) - (7)].constr); - n->generated_when = (yyvsp[(2) - (7)].ival); - n->raw_expr = (yyvsp[(5) - (7)].node); + n->contype = (yyvsp[0].constr); + n->generated_when = (yyvsp[-5].ival); + n->raw_expr = (yyvsp[-2].node); n->cooked_expr = NULL; - n->location = (yylsp[(1) - (7)]); + n->location = (yylsp[-6]); /* * Can't do this in the grammar because of shift/reduce @@ -22291,293 +21624,341 @@ YYLTYPE yylloc; * DEFAULT, but generated columns only allow ALWAYS.) We * can also give a more useful error message and location. */ - if ((yyvsp[(2) - (7)].ival) != PG_ATTRIBUTE_IDENTITY_ALWAYS) + if ((yyvsp[-5].ival) != PG_ATTRIBUTE_IDENTITY_ALWAYS) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("for a generated column, GENERATED ALWAYS must be specified"), - parser_errposition((yylsp[(2) - (7)])))); + parser_errposition((yylsp[-5])))); (yyval.node) = (PGNode *)n; - ;} + } +#line 21636 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 302: + case 307: /* GeneratedConstraintElem: AS '(' a_expr ')' opt_GeneratedColumnType */ #line 263 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); - n->contype = (yyvsp[(5) - (5)].constr); + n->contype = (yyvsp[0].constr); n->generated_when = PG_ATTRIBUTE_IDENTITY_ALWAYS; - n->raw_expr = (yyvsp[(3) - (5)].node); + n->raw_expr = (yyvsp[-2].node); n->cooked_expr = NULL; - n->location = (yylsp[(1) - (5)]); + n->location = (yylsp[-4]); (yyval.node) = (PGNode *)n; - ;} + } +#line 21650 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 303: + case 308: /* generic_option_elem: generic_option_name generic_option_arg */ #line 277 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem((yyvsp[-1].str), (yyvsp[0].node), (yylsp[-1])); + } +#line 21658 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 304: + case 309: /* key_update: ON UPDATE key_action */ #line 283 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (yyvsp[(3) - (3)].ival); ;} + { (yyval.ival) = (yyvsp[0].ival); } +#line 21664 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 305: + case 310: /* key_actions: key_update */ #line 289 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = ((yyvsp[(1) - (1)].ival) << 8) | (PG_FKCONSTR_ACTION_NOACTION & 0xFF); ;} + { (yyval.ival) = ((yyvsp[0].ival) << 8) | (PG_FKCONSTR_ACTION_NOACTION & 0xFF); } +#line 21670 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 306: + case 311: /* key_actions: key_delete */ #line 291 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (PG_FKCONSTR_ACTION_NOACTION << 8) | ((yyvsp[(1) - (1)].ival) & 0xFF); ;} + { (yyval.ival) = (PG_FKCONSTR_ACTION_NOACTION << 8) | ((yyvsp[0].ival) & 0xFF); } +#line 21676 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 307: + case 312: /* key_actions: key_update key_delete */ #line 293 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = ((yyvsp[(1) - (2)].ival) << 8) | ((yyvsp[(2) - (2)].ival) & 0xFF); ;} + { (yyval.ival) = ((yyvsp[-1].ival) << 8) | ((yyvsp[0].ival) & 0xFF); } +#line 21682 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 308: + case 313: /* key_actions: key_delete key_update */ #line 295 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = ((yyvsp[(2) - (2)].ival) << 8) | ((yyvsp[(1) - (2)].ival) & 0xFF); ;} + { (yyval.ival) = ((yyvsp[0].ival) << 8) | ((yyvsp[-1].ival) & 0xFF); } +#line 21688 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 309: + case 314: /* key_actions: %empty */ #line 297 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (PG_FKCONSTR_ACTION_NOACTION << 8) | (PG_FKCONSTR_ACTION_NOACTION & 0xFF); ;} + { (yyval.ival) = (PG_FKCONSTR_ACTION_NOACTION << 8) | (PG_FKCONSTR_ACTION_NOACTION & 0xFF); } +#line 21694 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 310: + case 315: /* OnCommitOption: ON COMMIT DROP */ #line 300 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.oncommit) = ONCOMMIT_DROP; ;} + { (yyval.oncommit) = ONCOMMIT_DROP; } +#line 21700 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 311: + case 316: /* OnCommitOption: ON COMMIT DELETE_P ROWS */ #line 301 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.oncommit) = PG_ONCOMMIT_DELETE_ROWS; ;} + { (yyval.oncommit) = PG_ONCOMMIT_DELETE_ROWS; } +#line 21706 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 312: + case 317: /* OnCommitOption: ON COMMIT PRESERVE ROWS */ #line 302 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.oncommit) = PG_ONCOMMIT_PRESERVE_ROWS; ;} + { (yyval.oncommit) = PG_ONCOMMIT_PRESERVE_ROWS; } +#line 21712 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 313: + case 318: /* OnCommitOption: %empty */ #line 303 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.oncommit) = PG_ONCOMMIT_NOOP; ;} + { (yyval.oncommit) = PG_ONCOMMIT_NOOP; } +#line 21718 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 314: + case 319: /* reloptions: '(' reloption_list ')' */ #line 308 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 21724 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 315: + case 320: /* opt_no_inherit: NO INHERIT */ #line 312 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 21730 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 316: + case 321: /* opt_no_inherit: %empty */ #line 313 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 21736 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 317: + case 322: /* TableConstraint: CONSTRAINT name ConstraintElem */ #line 319 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = castNode(PGConstraint, (yyvsp[(3) - (3)].node)); - n->conname = (yyvsp[(2) - (3)].str); - n->location = (yylsp[(1) - (3)]); + { + PGConstraint *n = castNode(PGConstraint, (yyvsp[0].node)); + n->conname = (yyvsp[-1].str); + n->location = (yylsp[-2]); (yyval.node) = (PGNode *) n; - ;} + } +#line 21747 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 318: + case 323: /* TableConstraint: ConstraintElem */ #line 325 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 21753 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 319: + case 324: /* TableLikeOption: COMMENTS */ #line 330 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_COMMENTS; ;} + { (yyval.ival) = PG_CREATE_TABLE_LIKE_COMMENTS; } +#line 21759 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 320: + case 325: /* TableLikeOption: CONSTRAINTS */ #line 331 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_CONSTRAINTS; ;} + { (yyval.ival) = PG_CREATE_TABLE_LIKE_CONSTRAINTS; } +#line 21765 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 321: + case 326: /* TableLikeOption: DEFAULTS */ #line 332 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_DEFAULTS; ;} + { (yyval.ival) = PG_CREATE_TABLE_LIKE_DEFAULTS; } +#line 21771 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 322: + case 327: /* TableLikeOption: IDENTITY_P */ #line 333 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_IDENTITY; ;} + { (yyval.ival) = PG_CREATE_TABLE_LIKE_IDENTITY; } +#line 21777 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 323: + case 328: /* TableLikeOption: INDEXES */ #line 334 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_INDEXES; ;} + { (yyval.ival) = PG_CREATE_TABLE_LIKE_INDEXES; } +#line 21783 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 324: + case 329: /* TableLikeOption: STATISTICS */ #line 335 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_STATISTICS; ;} + { (yyval.ival) = PG_CREATE_TABLE_LIKE_STATISTICS; } +#line 21789 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 325: + case 330: /* TableLikeOption: STORAGE */ #line 336 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_STORAGE; ;} + { (yyval.ival) = PG_CREATE_TABLE_LIKE_STORAGE; } +#line 21795 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 326: + case 331: /* TableLikeOption: ALL */ #line 337 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_ALL; ;} + { (yyval.ival) = PG_CREATE_TABLE_LIKE_ALL; } +#line 21801 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 327: + case 332: /* reloption_list: reloption_elem */ #line 343 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} + { (yyval.list) = list_make1((yyvsp[0].defelt)); } +#line 21807 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 328: + case 333: /* reloption_list: reloption_list ',' reloption_elem */ #line 344 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].defelt)); } +#line 21813 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 329: + case 334: /* ExistingIndex: USING INDEX index_name */ #line 348 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.str) = (yyvsp[(3) - (3)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 21819 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 330: + case 335: /* ConstraintAttr: DEFERRABLE */ #line 354 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_ATTR_DEFERRABLE; - n->location = (yylsp[(1) - (1)]); + n->location = (yylsp[0]); (yyval.node) = (PGNode *)n; - ;} + } +#line 21830 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 331: + case 336: /* ConstraintAttr: NOT DEFERRABLE */ #line 361 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_ATTR_NOT_DEFERRABLE; - n->location = (yylsp[(1) - (2)]); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *)n; - ;} + } +#line 21841 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 332: + case 337: /* ConstraintAttr: INITIALLY DEFERRED */ #line 368 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_ATTR_DEFERRED; - n->location = (yylsp[(1) - (2)]); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *)n; - ;} + } +#line 21852 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 333: + case 338: /* ConstraintAttr: INITIALLY IMMEDIATE */ #line 375 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_ATTR_IMMEDIATE; - n->location = (yylsp[(1) - (2)]); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *)n; - ;} + } +#line 21863 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 334: + case 339: /* OptWith: WITH reloptions */ #line 386 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 21869 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 335: + case 340: /* OptWith: WITH OIDS */ #line 387 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = list_make1(makeDefElem("oids", (PGNode *) makeInteger(true), (yylsp[(1) - (2)]))); ;} + { (yyval.list) = list_make1(makeDefElem("oids", (PGNode *) makeInteger(true), (yylsp[-1]))); } +#line 21875 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 336: + case 341: /* OptWith: WITHOUT OIDS */ #line 388 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = list_make1(makeDefElem("oids", (PGNode *) makeInteger(false), (yylsp[(1) - (2)]))); ;} + { (yyval.list) = list_make1(makeDefElem("oids", (PGNode *) makeInteger(false), (yylsp[-1]))); } +#line 21881 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 337: + case 342: /* OptWith: %empty */ #line 389 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 21887 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 338: + case 343: /* definition: '(' def_list ')' */ #line 393 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 21893 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 339: + case 344: /* TableLikeOptionList: TableLikeOptionList INCLUDING TableLikeOption */ #line 398 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival); ;} + { (yyval.ival) = (yyvsp[-2].ival) | (yyvsp[0].ival); } +#line 21899 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 340: + case 345: /* TableLikeOptionList: TableLikeOptionList EXCLUDING TableLikeOption */ #line 399 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (yyvsp[(1) - (3)].ival) & ~(yyvsp[(3) - (3)].ival); ;} + { (yyval.ival) = (yyvsp[-2].ival) & ~(yyvsp[0].ival); } +#line 21905 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 341: + case 346: /* TableLikeOptionList: %empty */ #line 400 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = 0; ;} + { (yyval.ival) = 0; } +#line 21911 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 342: + case 347: /* generic_option_name: ColLabel */ #line 405 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 21917 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 343: + case 348: /* ConstraintAttributeElem: NOT DEFERRABLE */ #line 410 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_NOT_DEFERRABLE; ;} + { (yyval.ival) = CAS_NOT_DEFERRABLE; } +#line 21923 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 344: + case 349: /* ConstraintAttributeElem: DEFERRABLE */ #line 411 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_DEFERRABLE; ;} + { (yyval.ival) = CAS_DEFERRABLE; } +#line 21929 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 345: + case 350: /* ConstraintAttributeElem: INITIALLY IMMEDIATE */ #line 412 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_INITIALLY_IMMEDIATE; ;} + { (yyval.ival) = CAS_INITIALLY_IMMEDIATE; } +#line 21935 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 346: + case 351: /* ConstraintAttributeElem: INITIALLY DEFERRED */ #line 413 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_INITIALLY_DEFERRED; ;} + { (yyval.ival) = CAS_INITIALLY_DEFERRED; } +#line 21941 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 347: + case 352: /* ConstraintAttributeElem: NOT VALID */ #line 414 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_NOT_VALID; ;} + { (yyval.ival) = CAS_NOT_VALID; } +#line 21947 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 348: + case 353: /* ConstraintAttributeElem: NO INHERIT */ #line 415 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_NO_INHERIT; ;} + { (yyval.ival) = CAS_NO_INHERIT; } +#line 21953 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 349: + case 354: /* columnDef: ColId Typename ColQualList */ #line 421 "third_party/libpg_query/grammar/statements/create.y" - { + { PGColumnDef *n = makeNode(PGColumnDef); n->category = COL_STANDARD; - n->colname = (yyvsp[(1) - (3)].str); - n->typeName = (yyvsp[(2) - (3)].typnam); + n->colname = (yyvsp[-2].str); + n->typeName = (yyvsp[-1].typnam); n->inhcount = 0; n->is_local = true; n->is_not_null = false; @@ -22586,20 +21967,21 @@ YYLTYPE yylloc; n->raw_default = NULL; n->cooked_default = NULL; n->collOid = InvalidOid; - SplitColQualList((yyvsp[(3) - (3)].list), &n->constraints, &n->collClause, + SplitColQualList((yyvsp[0].list), &n->constraints, &n->collClause, yyscanner); - n->location = (yylsp[(1) - (3)]); + n->location = (yylsp[-2]); (yyval.node) = (PGNode *)n; - ;} + } +#line 21976 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 350: + case 355: /* columnDef: ColId opt_Typename GeneratedConstraintElem ColQualList */ #line 441 "third_party/libpg_query/grammar/statements/create.y" - { + { PGColumnDef *n = makeNode(PGColumnDef); n->category = COL_GENERATED; - n->colname = (yyvsp[(1) - (4)].str); - n->typeName = (yyvsp[(2) - (4)].typnam); + n->colname = (yyvsp[-3].str); + n->typeName = (yyvsp[-2].typnam); n->inhcount = 0; n->is_local = true; n->is_not_null = false; @@ -22609,1352 +21991,1531 @@ YYLTYPE yylloc; n->cooked_default = NULL; n->collOid = InvalidOid; // merge the constraints with the generated column constraint - auto constraints = (yyvsp[(4) - (4)].list); + auto constraints = (yyvsp[0].list); if (constraints) { - constraints = lappend(constraints, (yyvsp[(3) - (4)].node)); + constraints = lappend(constraints, (yyvsp[-1].node)); } else { - constraints = list_make1((yyvsp[(3) - (4)].node)); + constraints = list_make1((yyvsp[-1].node)); } SplitColQualList(constraints, &n->constraints, &n->collClause, yyscanner); - n->location = (yylsp[(1) - (4)]); + n->location = (yylsp[-3]); (yyval.node) = (PGNode *)n; - ;} + } +#line 22006 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 351: + case 356: /* def_list: def_elem */ #line 469 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} + { (yyval.list) = list_make1((yyvsp[0].defelt)); } +#line 22012 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 352: + case 357: /* def_list: def_list ',' def_elem */ #line 470 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].defelt)); } +#line 22018 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 353: + case 358: /* index_name: ColId */ #line 474 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 22024 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 354: + case 359: /* TableElement: columnDef */ #line 478 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 22030 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 355: + case 360: /* TableElement: TableLikeClause */ #line 479 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 22036 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 356: + case 361: /* TableElement: TableConstraint */ #line 480 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 22042 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 357: + case 362: /* def_elem: ColLabel '=' def_arg */ #line 485 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (3)].str), (PGNode *) (yyvsp[(3) - (3)].node), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem((yyvsp[-2].str), (PGNode *) (yyvsp[0].node), (yylsp[-2])); + } +#line 22050 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 358: + case 363: /* def_elem: ColLabel */ #line 489 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (1)].str), NULL, (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem((yyvsp[0].str), NULL, (yylsp[0])); + } +#line 22058 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 359: + case 364: /* opt_definition: WITH definition */ #line 496 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 22064 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 360: + case 365: /* opt_definition: %empty */ #line 497 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 22070 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 361: + case 366: /* OptTableElementList: TableElementList */ #line 502 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 22076 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 362: + case 367: /* OptTableElementList: TableElementList ',' */ #line 503 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 22082 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 363: + case 368: /* OptTableElementList: %empty */ #line 504 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 22088 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 364: + case 369: /* columnElem: ColId */ #line 509 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); - ;} + { + (yyval.node) = (PGNode *) makeString((yyvsp[0].str)); + } +#line 22096 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 365: + case 370: /* opt_column_list: '(' columnList ')' */ #line 516 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 22102 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 366: + case 371: /* opt_column_list: %empty */ #line 517 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 22108 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 367: + case 372: /* ColQualList: ColQualList ColConstraint */ #line 522 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + { (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].node)); } +#line 22114 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 368: + case 373: /* ColQualList: %empty */ #line 523 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 22120 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 369: + case 374: /* key_delete: ON DELETE_P key_action */ #line 527 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (yyvsp[(3) - (3)].ival); ;} + { (yyval.ival) = (yyvsp[0].ival); } +#line 22126 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 370: + case 375: /* reloption_elem: ColLabel '=' def_arg */ #line 533 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (3)].str), (PGNode *) (yyvsp[(3) - (3)].node), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem((yyvsp[-2].str), (PGNode *) (yyvsp[0].node), (yylsp[-2])); + } +#line 22134 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 371: + case 376: /* reloption_elem: ColLabel */ #line 537 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (1)].str), NULL, (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem((yyvsp[0].str), NULL, (yylsp[0])); + } +#line 22142 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 372: + case 377: /* reloption_elem: ColLabel '.' ColLabel '=' def_arg */ #line 541 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElemExtended((yyvsp[(1) - (5)].str), (yyvsp[(3) - (5)].str), (PGNode *) (yyvsp[(5) - (5)].node), - PG_DEFELEM_UNSPEC, (yylsp[(1) - (5)])); - ;} + { + (yyval.defelt) = makeDefElemExtended((yyvsp[-4].str), (yyvsp[-2].str), (PGNode *) (yyvsp[0].node), + PG_DEFELEM_UNSPEC, (yylsp[-4])); + } +#line 22151 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 373: + case 378: /* reloption_elem: ColLabel '.' ColLabel */ #line 546 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElemExtended((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str), NULL, PG_DEFELEM_UNSPEC, (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElemExtended((yyvsp[-2].str), (yyvsp[0].str), NULL, PG_DEFELEM_UNSPEC, (yylsp[-2])); + } +#line 22159 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 374: + case 379: /* columnList: columnElem */ #line 553 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 22165 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 375: + case 380: /* columnList: columnList ',' columnElem */ #line 554 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); } +#line 22171 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 376: + case 381: /* columnList_opt_comma: columnList */ #line 558 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 22177 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 377: + case 382: /* columnList_opt_comma: columnList ',' */ #line 559 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 22183 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 378: + case 383: /* func_type: Typename */ #line 563 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 22189 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 379: + case 384: /* func_type: type_function_name attrs '%' TYPE_P */ #line 565 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.typnam) = makeTypeNameFromNameList(lcons(makeString((yyvsp[(1) - (4)].str)), (yyvsp[(2) - (4)].list))); + { + (yyval.typnam) = makeTypeNameFromNameList(lcons(makeString((yyvsp[-3].str)), (yyvsp[-2].list))); (yyval.typnam)->pct_type = true; - (yyval.typnam)->location = (yylsp[(1) - (4)]); - ;} + (yyval.typnam)->location = (yylsp[-3]); + } +#line 22199 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 380: + case 385: /* func_type: SETOF type_function_name attrs '%' TYPE_P */ #line 571 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.typnam) = makeTypeNameFromNameList(lcons(makeString((yyvsp[(2) - (5)].str)), (yyvsp[(3) - (5)].list))); + { + (yyval.typnam) = makeTypeNameFromNameList(lcons(makeString((yyvsp[-3].str)), (yyvsp[-2].list))); (yyval.typnam)->pct_type = true; (yyval.typnam)->setof = true; - (yyval.typnam)->location = (yylsp[(2) - (5)]); - ;} + (yyval.typnam)->location = (yylsp[-3]); + } +#line 22210 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 381: + case 386: /* ConstraintElem: CHECK_P '(' a_expr ')' ConstraintAttributeSpec */ #line 582 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_CHECK; - n->location = (yylsp[(1) - (5)]); - n->raw_expr = (yyvsp[(3) - (5)].node); + n->location = (yylsp[-4]); + n->raw_expr = (yyvsp[-2].node); n->cooked_expr = NULL; - processCASbits((yyvsp[(5) - (5)].ival), (yylsp[(5) - (5)]), "CHECK", + processCASbits((yyvsp[0].ival), (yylsp[0]), "CHECK", NULL, NULL, &n->skip_validation, &n->is_no_inherit, yyscanner); n->initially_valid = !n->skip_validation; (yyval.node) = (PGNode *)n; - ;} + } +#line 22227 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 382: + case 387: /* ConstraintElem: UNIQUE '(' columnList_opt_comma ')' opt_definition ConstraintAttributeSpec */ #line 596 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_UNIQUE; - n->location = (yylsp[(1) - (6)]); - n->keys = (yyvsp[(3) - (6)].list); - n->options = (yyvsp[(5) - (6)].list); + n->location = (yylsp[-5]); + n->keys = (yyvsp[-3].list); + n->options = (yyvsp[-1].list); n->indexname = NULL; - processCASbits((yyvsp[(6) - (6)].ival), (yylsp[(6) - (6)]), "UNIQUE", + processCASbits((yyvsp[0].ival), (yylsp[0]), "UNIQUE", &n->deferrable, &n->initdeferred, NULL, NULL, yyscanner); (yyval.node) = (PGNode *)n; - ;} + } +#line 22244 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 383: + case 388: /* ConstraintElem: UNIQUE ExistingIndex ConstraintAttributeSpec */ #line 609 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_UNIQUE; - n->location = (yylsp[(1) - (3)]); + n->location = (yylsp[-2]); n->keys = NIL; n->options = NIL; - n->indexname = (yyvsp[(2) - (3)].str); + n->indexname = (yyvsp[-1].str); n->indexspace = NULL; - processCASbits((yyvsp[(3) - (3)].ival), (yylsp[(3) - (3)]), "UNIQUE", + processCASbits((yyvsp[0].ival), (yylsp[0]), "UNIQUE", &n->deferrable, &n->initdeferred, NULL, NULL, yyscanner); (yyval.node) = (PGNode *)n; - ;} + } +#line 22262 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 384: + case 389: /* ConstraintElem: PRIMARY KEY '(' columnList_opt_comma ')' opt_definition ConstraintAttributeSpec */ #line 624 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_PRIMARY; - n->location = (yylsp[(1) - (7)]); - n->keys = (yyvsp[(4) - (7)].list); - n->options = (yyvsp[(6) - (7)].list); + n->location = (yylsp[-6]); + n->keys = (yyvsp[-3].list); + n->options = (yyvsp[-1].list); n->indexname = NULL; - processCASbits((yyvsp[(7) - (7)].ival), (yylsp[(7) - (7)]), "PRIMARY KEY", + processCASbits((yyvsp[0].ival), (yylsp[0]), "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, NULL, yyscanner); (yyval.node) = (PGNode *)n; - ;} + } +#line 22279 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 385: + case 390: /* ConstraintElem: PRIMARY KEY ExistingIndex ConstraintAttributeSpec */ #line 637 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_PRIMARY; - n->location = (yylsp[(1) - (4)]); + n->location = (yylsp[-3]); n->keys = NIL; n->options = NIL; - n->indexname = (yyvsp[(3) - (4)].str); + n->indexname = (yyvsp[-1].str); n->indexspace = NULL; - processCASbits((yyvsp[(4) - (4)].ival), (yylsp[(4) - (4)]), "PRIMARY KEY", + processCASbits((yyvsp[0].ival), (yylsp[0]), "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, NULL, yyscanner); (yyval.node) = (PGNode *)n; - ;} + } +#line 22297 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 386: + case 391: /* ConstraintElem: FOREIGN KEY '(' columnList_opt_comma ')' REFERENCES qualified_name opt_column_list key_match key_actions ConstraintAttributeSpec */ #line 652 "third_party/libpg_query/grammar/statements/create.y" - { + { PGConstraint *n = makeNode(PGConstraint); n->contype = PG_CONSTR_FOREIGN; - n->location = (yylsp[(1) - (11)]); - n->pktable = (yyvsp[(7) - (11)].range); - n->fk_attrs = (yyvsp[(4) - (11)].list); - n->pk_attrs = (yyvsp[(8) - (11)].list); - n->fk_matchtype = (yyvsp[(9) - (11)].ival); - n->fk_upd_action = (char) ((yyvsp[(10) - (11)].ival) >> 8); - n->fk_del_action = (char) ((yyvsp[(10) - (11)].ival) & 0xFF); - processCASbits((yyvsp[(11) - (11)].ival), (yylsp[(11) - (11)]), "FOREIGN KEY", + n->location = (yylsp[-10]); + n->pktable = (yyvsp[-4].range); + n->fk_attrs = (yyvsp[-7].list); + n->pk_attrs = (yyvsp[-3].list); + n->fk_matchtype = (yyvsp[-2].ival); + n->fk_upd_action = (char) ((yyvsp[-1].ival) >> 8); + n->fk_del_action = (char) ((yyvsp[-1].ival) & 0xFF); + processCASbits((yyvsp[0].ival), (yylsp[0]), "FOREIGN KEY", &n->deferrable, &n->initdeferred, &n->skip_validation, NULL, yyscanner); n->initially_valid = !n->skip_validation; (yyval.node) = (PGNode *)n; - ;} + } +#line 22319 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 387: + case 392: /* TableElementList: TableElement */ #line 674 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} + { + (yyval.list) = list_make1((yyvsp[0].node)); + } +#line 22327 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 388: + case 393: /* TableElementList: TableElementList ',' TableElement */ #line 678 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} + { + (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); + } +#line 22335 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 389: + case 394: /* key_match: MATCH FULL */ #line 685 "third_party/libpg_query/grammar/statements/create.y" - { + { (yyval.ival) = PG_FKCONSTR_MATCH_FULL; - ;} + } +#line 22343 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 390: + case 395: /* key_match: MATCH PARTIAL */ #line 689 "third_party/libpg_query/grammar/statements/create.y" - { + { ereport(ERROR, (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("MATCH PARTIAL not yet implemented"), - parser_errposition((yylsp[(1) - (2)])))); + parser_errposition((yylsp[-1])))); (yyval.ival) = PG_FKCONSTR_MATCH_PARTIAL; - ;} + } +#line 22355 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 391: + case 396: /* key_match: MATCH SIMPLE */ #line 697 "third_party/libpg_query/grammar/statements/create.y" - { + { (yyval.ival) = PG_FKCONSTR_MATCH_SIMPLE; - ;} + } +#line 22363 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 392: + case 397: /* key_match: %empty */ #line 701 "third_party/libpg_query/grammar/statements/create.y" - { + { (yyval.ival) = PG_FKCONSTR_MATCH_SIMPLE; - ;} + } +#line 22371 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 393: + case 398: /* TableLikeClause: LIKE qualified_name TableLikeOptionList */ #line 709 "third_party/libpg_query/grammar/statements/create.y" - { + { PGTableLikeClause *n = makeNode(PGTableLikeClause); - n->relation = (yyvsp[(2) - (3)].range); - n->options = (yyvsp[(3) - (3)].ival); + n->relation = (yyvsp[-1].range); + n->options = (yyvsp[0].ival); (yyval.node) = (PGNode *)n; - ;} + } +#line 22382 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 394: + case 399: /* OptTemp: TEMPORARY */ #line 718 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} + { (yyval.ival) = PG_RELPERSISTENCE_TEMP; } +#line 22388 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 395: + case 400: /* OptTemp: TEMP */ #line 719 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} + { (yyval.ival) = PG_RELPERSISTENCE_TEMP; } +#line 22394 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 396: + case 401: /* OptTemp: LOCAL TEMPORARY */ #line 720 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} + { (yyval.ival) = PG_RELPERSISTENCE_TEMP; } +#line 22400 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 397: + case 402: /* OptTemp: LOCAL TEMP */ #line 721 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} + { (yyval.ival) = PG_RELPERSISTENCE_TEMP; } +#line 22406 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 398: + case 403: /* OptTemp: GLOBAL TEMPORARY */ #line 723 "third_party/libpg_query/grammar/statements/create.y" - { + { ereport(PGWARNING, (errmsg("GLOBAL is deprecated in temporary table creation"), - parser_errposition((yylsp[(1) - (2)])))); + parser_errposition((yylsp[-1])))); (yyval.ival) = PG_RELPERSISTENCE_TEMP; - ;} + } +#line 22417 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 399: + case 404: /* OptTemp: GLOBAL TEMP */ #line 730 "third_party/libpg_query/grammar/statements/create.y" - { + { ereport(PGWARNING, (errmsg("GLOBAL is deprecated in temporary table creation"), - parser_errposition((yylsp[(1) - (2)])))); + parser_errposition((yylsp[-1])))); (yyval.ival) = PG_RELPERSISTENCE_TEMP; - ;} + } +#line 22428 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 400: + case 405: /* OptTemp: UNLOGGED */ #line 736 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_RELPERSISTENCE_UNLOGGED; ;} + { (yyval.ival) = PG_RELPERSISTENCE_UNLOGGED; } +#line 22434 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 401: + case 406: /* OptTemp: %empty */ #line 737 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = RELPERSISTENCE_PERMANENT; ;} + { (yyval.ival) = RELPERSISTENCE_PERMANENT; } +#line 22440 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 402: + case 407: /* generated_when: ALWAYS */ #line 742 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_ATTRIBUTE_IDENTITY_ALWAYS; ;} + { (yyval.ival) = PG_ATTRIBUTE_IDENTITY_ALWAYS; } +#line 22446 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 403: + case 408: /* generated_when: BY DEFAULT */ #line 743 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = ATTRIBUTE_IDENTITY_BY_DEFAULT; ;} + { (yyval.ival) = ATTRIBUTE_IDENTITY_BY_DEFAULT; } +#line 22452 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 404: + case 409: /* DropStmt: DROP drop_type_any_name IF_P EXISTS any_name_list opt_drop_behavior */ #line 10 "third_party/libpg_query/grammar/statements/drop.y" - { + { PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (6)].objtype); + n->removeType = (yyvsp[-4].objtype); n->missing_ok = true; - n->objects = (yyvsp[(5) - (6)].list); - n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->objects = (yyvsp[-1].list); + n->behavior = (yyvsp[0].dbehavior); n->concurrent = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 22466 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 405: + case 410: /* DropStmt: DROP drop_type_any_name any_name_list opt_drop_behavior */ #line 20 "third_party/libpg_query/grammar/statements/drop.y" - { + { PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (4)].objtype); + n->removeType = (yyvsp[-2].objtype); n->missing_ok = false; - n->objects = (yyvsp[(3) - (4)].list); - n->behavior = (yyvsp[(4) - (4)].dbehavior); + n->objects = (yyvsp[-1].list); + n->behavior = (yyvsp[0].dbehavior); n->concurrent = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 22480 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 406: + case 411: /* DropStmt: DROP drop_type_name IF_P EXISTS name_list opt_drop_behavior */ #line 30 "third_party/libpg_query/grammar/statements/drop.y" - { + { PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (6)].objtype); + n->removeType = (yyvsp[-4].objtype); n->missing_ok = true; - n->objects = (yyvsp[(5) - (6)].list); - n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->objects = (yyvsp[-1].list); + n->behavior = (yyvsp[0].dbehavior); n->concurrent = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 22494 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 407: + case 412: /* DropStmt: DROP drop_type_name name_list opt_drop_behavior */ #line 40 "third_party/libpg_query/grammar/statements/drop.y" - { + { PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (4)].objtype); + n->removeType = (yyvsp[-2].objtype); n->missing_ok = false; - n->objects = (yyvsp[(3) - (4)].list); - n->behavior = (yyvsp[(4) - (4)].dbehavior); + n->objects = (yyvsp[-1].list); + n->behavior = (yyvsp[0].dbehavior); n->concurrent = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 22508 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 408: + case 413: /* DropStmt: DROP drop_type_name_on_any_name name ON any_name opt_drop_behavior */ #line 50 "third_party/libpg_query/grammar/statements/drop.y" - { + { PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (6)].objtype); - n->objects = list_make1(lappend((yyvsp[(5) - (6)].list), makeString((yyvsp[(3) - (6)].str)))); - n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->removeType = (yyvsp[-4].objtype); + n->objects = list_make1(lappend((yyvsp[-1].list), makeString((yyvsp[-3].str)))); + n->behavior = (yyvsp[0].dbehavior); n->missing_ok = false; n->concurrent = false; (yyval.node) = (PGNode *) n; - ;} + } +#line 22522 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 409: + case 414: /* DropStmt: DROP drop_type_name_on_any_name IF_P EXISTS name ON any_name opt_drop_behavior */ #line 60 "third_party/libpg_query/grammar/statements/drop.y" - { + { PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (8)].objtype); - n->objects = list_make1(lappend((yyvsp[(7) - (8)].list), makeString((yyvsp[(5) - (8)].str)))); - n->behavior = (yyvsp[(8) - (8)].dbehavior); + n->removeType = (yyvsp[-6].objtype); + n->objects = list_make1(lappend((yyvsp[-1].list), makeString((yyvsp[-3].str)))); + n->behavior = (yyvsp[0].dbehavior); n->missing_ok = true; n->concurrent = false; (yyval.node) = (PGNode *) n; - ;} + } +#line 22536 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 410: + case 415: /* drop_type_any_name: TABLE */ #line 73 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TABLE; ;} + { (yyval.objtype) = PG_OBJECT_TABLE; } +#line 22542 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 411: + case 416: /* drop_type_any_name: SEQUENCE */ #line 74 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_SEQUENCE; ;} + { (yyval.objtype) = PG_OBJECT_SEQUENCE; } +#line 22548 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 412: + case 417: /* drop_type_any_name: FUNCTION */ #line 75 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_FUNCTION; ;} + { (yyval.objtype) = PG_OBJECT_FUNCTION; } +#line 22554 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 413: + case 418: /* drop_type_any_name: MACRO */ #line 76 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_FUNCTION; ;} + { (yyval.objtype) = PG_OBJECT_FUNCTION; } +#line 22560 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 414: + case 419: /* drop_type_any_name: MACRO TABLE */ #line 77 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TABLE_MACRO; ;} + { (yyval.objtype) = PG_OBJECT_TABLE_MACRO; } +#line 22566 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 415: + case 420: /* drop_type_any_name: VIEW */ #line 78 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_VIEW; ;} + { (yyval.objtype) = PG_OBJECT_VIEW; } +#line 22572 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 416: + case 421: /* drop_type_any_name: MATERIALIZED VIEW */ #line 79 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_MATVIEW; ;} + { (yyval.objtype) = PG_OBJECT_MATVIEW; } +#line 22578 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 417: + case 422: /* drop_type_any_name: INDEX */ #line 80 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_INDEX; ;} + { (yyval.objtype) = PG_OBJECT_INDEX; } +#line 22584 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 418: + case 423: /* drop_type_any_name: FOREIGN TABLE */ #line 81 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_FOREIGN_TABLE; ;} + { (yyval.objtype) = PG_OBJECT_FOREIGN_TABLE; } +#line 22590 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 419: + case 424: /* drop_type_any_name: COLLATION */ #line 82 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_COLLATION; ;} + { (yyval.objtype) = PG_OBJECT_COLLATION; } +#line 22596 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 420: + case 425: /* drop_type_any_name: CONVERSION_P */ #line 83 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_CONVERSION; ;} + { (yyval.objtype) = PG_OBJECT_CONVERSION; } +#line 22602 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 421: + case 426: /* drop_type_any_name: SCHEMA */ #line 84 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_SCHEMA; ;} + { (yyval.objtype) = PG_OBJECT_SCHEMA; } +#line 22608 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 422: + case 427: /* drop_type_any_name: STATISTICS */ #line 85 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_STATISTIC_EXT; ;} + { (yyval.objtype) = PG_OBJECT_STATISTIC_EXT; } +#line 22614 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 423: + case 428: /* drop_type_any_name: TEXT_P SEARCH PARSER */ #line 86 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TSPARSER; ;} + { (yyval.objtype) = PG_OBJECT_TSPARSER; } +#line 22620 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 424: + case 429: /* drop_type_any_name: TEXT_P SEARCH DICTIONARY */ #line 87 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TSDICTIONARY; ;} + { (yyval.objtype) = PG_OBJECT_TSDICTIONARY; } +#line 22626 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 425: + case 430: /* drop_type_any_name: TEXT_P SEARCH TEMPLATE */ #line 88 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TSTEMPLATE; ;} + { (yyval.objtype) = PG_OBJECT_TSTEMPLATE; } +#line 22632 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 426: + case 431: /* drop_type_any_name: TEXT_P SEARCH CONFIGURATION */ #line 89 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TSCONFIGURATION; ;} + { (yyval.objtype) = PG_OBJECT_TSCONFIGURATION; } +#line 22638 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 427: + case 432: /* drop_type_any_name: TYPE_P */ #line 90 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TYPE; ;} + { (yyval.objtype) = PG_OBJECT_TYPE; } +#line 22644 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 428: + case 433: /* drop_type_name: ACCESS METHOD */ #line 95 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_ACCESS_METHOD; ;} + { (yyval.objtype) = PG_OBJECT_ACCESS_METHOD; } +#line 22650 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 429: + case 434: /* drop_type_name: EVENT TRIGGER */ #line 96 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_EVENT_TRIGGER; ;} + { (yyval.objtype) = PG_OBJECT_EVENT_TRIGGER; } +#line 22656 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 430: + case 435: /* drop_type_name: EXTENSION */ #line 97 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_EXTENSION; ;} + { (yyval.objtype) = PG_OBJECT_EXTENSION; } +#line 22662 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 431: + case 436: /* drop_type_name: FOREIGN DATA_P WRAPPER */ #line 98 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_FDW; ;} + { (yyval.objtype) = PG_OBJECT_FDW; } +#line 22668 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 432: + case 437: /* drop_type_name: PUBLICATION */ #line 99 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_PUBLICATION; ;} + { (yyval.objtype) = PG_OBJECT_PUBLICATION; } +#line 22674 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 433: + case 438: /* drop_type_name: SERVER */ #line 100 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_FOREIGN_SERVER; ;} + { (yyval.objtype) = PG_OBJECT_FOREIGN_SERVER; } +#line 22680 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 434: + case 439: /* any_name_list: any_name */ #line 105 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].list)); ;} + { (yyval.list) = list_make1((yyvsp[0].list)); } +#line 22686 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 435: + case 440: /* any_name_list: any_name_list ',' any_name */ #line 106 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].list)); } +#line 22692 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 436: + case 441: /* opt_drop_behavior: CASCADE */ #line 111 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.dbehavior) = PG_DROP_CASCADE; ;} + { (yyval.dbehavior) = PG_DROP_CASCADE; } +#line 22698 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 437: + case 442: /* opt_drop_behavior: RESTRICT */ #line 112 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.dbehavior) = PG_DROP_RESTRICT; ;} + { (yyval.dbehavior) = PG_DROP_RESTRICT; } +#line 22704 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 438: + case 443: /* opt_drop_behavior: %empty */ #line 113 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.dbehavior) = PG_DROP_RESTRICT; /* default */ ;} + { (yyval.dbehavior) = PG_DROP_RESTRICT; /* default */ } +#line 22710 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 439: + case 444: /* drop_type_name_on_any_name: POLICY */ #line 118 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_POLICY; ;} + { (yyval.objtype) = PG_OBJECT_POLICY; } +#line 22716 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 440: + case 445: /* drop_type_name_on_any_name: RULE */ #line 119 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_RULE; ;} + { (yyval.objtype) = PG_OBJECT_RULE; } +#line 22722 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 441: + case 446: /* drop_type_name_on_any_name: TRIGGER */ #line 120 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TRIGGER; ;} + { (yyval.objtype) = PG_OBJECT_TRIGGER; } +#line 22728 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 442: + case 447: /* CreateFunctionStmt: CREATE_P OptTemp macro_alias qualified_name param_list AS TABLE SelectStmt */ #line 9 "third_party/libpg_query/grammar/statements/create_function.y" - { + { PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt); - (yyvsp[(4) - (8)].range)->relpersistence = (yyvsp[(2) - (8)].ival); - n->name = (yyvsp[(4) - (8)].range); - n->params = (yyvsp[(5) - (8)].list); + (yyvsp[-4].range)->relpersistence = (yyvsp[-6].ival); + n->name = (yyvsp[-4].range); + n->params = (yyvsp[-3].list); n->function = NULL; - n->query = (yyvsp[(8) - (8)].node); + n->query = (yyvsp[0].node); n->onconflict = PG_ERROR_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 22743 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 443: + case 448: /* CreateFunctionStmt: CREATE_P OptTemp macro_alias IF_P NOT EXISTS qualified_name param_list AS TABLE SelectStmt */ #line 21 "third_party/libpg_query/grammar/statements/create_function.y" - { + { PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt); - (yyvsp[(7) - (11)].range)->relpersistence = (yyvsp[(2) - (11)].ival); - n->name = (yyvsp[(7) - (11)].range); - n->params = (yyvsp[(8) - (11)].list); + (yyvsp[-4].range)->relpersistence = (yyvsp[-9].ival); + n->name = (yyvsp[-4].range); + n->params = (yyvsp[-3].list); n->function = NULL; - n->query = (yyvsp[(11) - (11)].node); + n->query = (yyvsp[0].node); n->onconflict = PG_IGNORE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 22759 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 444: + case 449: /* CreateFunctionStmt: CREATE_P OR REPLACE OptTemp macro_alias qualified_name param_list AS TABLE SelectStmt */ #line 34 "third_party/libpg_query/grammar/statements/create_function.y" - { + { PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt); - (yyvsp[(6) - (10)].range)->relpersistence = (yyvsp[(4) - (10)].ival); - n->name = (yyvsp[(6) - (10)].range); - n->params = (yyvsp[(7) - (10)].list); + (yyvsp[-4].range)->relpersistence = (yyvsp[-6].ival); + n->name = (yyvsp[-4].range); + n->params = (yyvsp[-3].list); n->function = NULL; - n->query = (yyvsp[(10) - (10)].node); + n->query = (yyvsp[0].node); n->onconflict = PG_REPLACE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 22775 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 445: + case 450: /* CreateFunctionStmt: CREATE_P OptTemp macro_alias qualified_name param_list AS a_expr */ #line 47 "third_party/libpg_query/grammar/statements/create_function.y" - { + { PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt); - (yyvsp[(4) - (7)].range)->relpersistence = (yyvsp[(2) - (7)].ival); - n->name = (yyvsp[(4) - (7)].range); - n->params = (yyvsp[(5) - (7)].list); - n->function = (yyvsp[(7) - (7)].node); + (yyvsp[-3].range)->relpersistence = (yyvsp[-5].ival); + n->name = (yyvsp[-3].range); + n->params = (yyvsp[-2].list); + n->function = (yyvsp[0].node); n->query = NULL; n->onconflict = PG_ERROR_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 22790 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 446: + case 451: /* CreateFunctionStmt: CREATE_P OptTemp macro_alias IF_P NOT EXISTS qualified_name param_list AS a_expr */ #line 59 "third_party/libpg_query/grammar/statements/create_function.y" - { + { PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt); - (yyvsp[(7) - (10)].range)->relpersistence = (yyvsp[(2) - (10)].ival); - n->name = (yyvsp[(7) - (10)].range); - n->params = (yyvsp[(8) - (10)].list); - n->function = (yyvsp[(10) - (10)].node); + (yyvsp[-3].range)->relpersistence = (yyvsp[-8].ival); + n->name = (yyvsp[-3].range); + n->params = (yyvsp[-2].list); + n->function = (yyvsp[0].node); n->query = NULL; n->onconflict = PG_IGNORE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 22805 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 447: + case 452: /* CreateFunctionStmt: CREATE_P OR REPLACE OptTemp macro_alias qualified_name param_list AS a_expr */ #line 71 "third_party/libpg_query/grammar/statements/create_function.y" - { + { PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt); - (yyvsp[(6) - (9)].range)->relpersistence = (yyvsp[(4) - (9)].ival); - n->name = (yyvsp[(6) - (9)].range); - n->params = (yyvsp[(7) - (9)].list); - n->function = (yyvsp[(9) - (9)].node); + (yyvsp[-3].range)->relpersistence = (yyvsp[-5].ival); + n->name = (yyvsp[-3].range); + n->params = (yyvsp[-2].list); + n->function = (yyvsp[0].node); n->query = NULL; n->onconflict = PG_REPLACE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 22820 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 450: + case 455: /* param_list: '(' ')' */ #line 92 "third_party/libpg_query/grammar/statements/create_function.y" - { + { (yyval.list) = NIL; - ;} + } +#line 22828 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 451: + case 456: /* param_list: '(' func_arg_list ')' */ #line 96 "third_party/libpg_query/grammar/statements/create_function.y" - { - (yyval.list) = (yyvsp[(2) - (3)].list); - ;} + { + (yyval.list) = (yyvsp[-1].list); + } +#line 22836 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 452: + case 457: /* UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias SET set_clause_list_opt_comma from_clause where_or_current_clause returning_clause */ #line 12 "third_party/libpg_query/grammar/statements/update.y" - { + { PGUpdateStmt *n = makeNode(PGUpdateStmt); - n->relation = (yyvsp[(3) - (8)].range); - n->targetList = (yyvsp[(5) - (8)].list); - n->fromClause = (yyvsp[(6) - (8)].list); - n->whereClause = (yyvsp[(7) - (8)].node); - n->returningList = (yyvsp[(8) - (8)].list); - n->withClause = (yyvsp[(1) - (8)].with); + n->relation = (yyvsp[-5].range); + n->targetList = (yyvsp[-3].list); + n->fromClause = (yyvsp[-2].list); + n->whereClause = (yyvsp[-1].node); + n->returningList = (yyvsp[0].list); + n->withClause = (yyvsp[-7].with); (yyval.node) = (PGNode *)n; - ;} + } +#line 22851 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 453: + case 458: /* CopyStmt: COPY opt_binary qualified_name opt_column_list opt_oids copy_from opt_program copy_file_name copy_delimiter opt_with copy_options */ #line 3 "third_party/libpg_query/grammar/statements/copy.y" - { + { PGCopyStmt *n = makeNode(PGCopyStmt); - n->relation = (yyvsp[(3) - (11)].range); + n->relation = (yyvsp[-8].range); n->query = NULL; - n->attlist = (yyvsp[(4) - (11)].list); - n->is_from = (yyvsp[(6) - (11)].boolean); - n->is_program = (yyvsp[(7) - (11)].boolean); - n->filename = (yyvsp[(8) - (11)].str); + n->attlist = (yyvsp[-7].list); + n->is_from = (yyvsp[-5].boolean); + n->is_program = (yyvsp[-4].boolean); + n->filename = (yyvsp[-3].str); if (n->is_program && n->filename == NULL) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("STDIN/STDOUT not allowed with PROGRAM"), - parser_errposition((yylsp[(8) - (11)])))); + parser_errposition((yylsp[-3])))); n->options = NIL; /* Concatenate user-supplied flags */ - if ((yyvsp[(2) - (11)].defelt)) - n->options = lappend(n->options, (yyvsp[(2) - (11)].defelt)); - if ((yyvsp[(5) - (11)].defelt)) - n->options = lappend(n->options, (yyvsp[(5) - (11)].defelt)); - if ((yyvsp[(9) - (11)].defelt)) - n->options = lappend(n->options, (yyvsp[(9) - (11)].defelt)); - if ((yyvsp[(11) - (11)].list)) - n->options = list_concat(n->options, (yyvsp[(11) - (11)].list)); + if ((yyvsp[-9].defelt)) + n->options = lappend(n->options, (yyvsp[-9].defelt)); + if ((yyvsp[-6].defelt)) + n->options = lappend(n->options, (yyvsp[-6].defelt)); + if ((yyvsp[-2].defelt)) + n->options = lappend(n->options, (yyvsp[-2].defelt)); + if ((yyvsp[0].list)) + n->options = list_concat(n->options, (yyvsp[0].list)); (yyval.node) = (PGNode *)n; - ;} + } +#line 22883 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 454: + case 459: /* CopyStmt: COPY '(' SelectStmt ')' TO opt_program copy_file_name opt_with copy_options */ #line 31 "third_party/libpg_query/grammar/statements/copy.y" - { + { PGCopyStmt *n = makeNode(PGCopyStmt); n->relation = NULL; - n->query = (yyvsp[(3) - (9)].node); + n->query = (yyvsp[-6].node); n->attlist = NIL; n->is_from = false; - n->is_program = (yyvsp[(6) - (9)].boolean); - n->filename = (yyvsp[(7) - (9)].str); - n->options = (yyvsp[(9) - (9)].list); + n->is_program = (yyvsp[-3].boolean); + n->filename = (yyvsp[-2].str); + n->options = (yyvsp[0].list); if (n->is_program && n->filename == NULL) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("STDIN/STDOUT not allowed with PROGRAM"), - parser_errposition((yylsp[(5) - (9)])))); + parser_errposition((yylsp[-4])))); (yyval.node) = (PGNode *)n; - ;} + } +#line 22906 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 455: + case 460: /* CopyStmt: COPY FROM DATABASE ColId TO ColId copy_database_flag */ #line 50 "third_party/libpg_query/grammar/statements/copy.y" - { + { PGCopyDatabaseStmt *n = makeNode(PGCopyDatabaseStmt); - n->from_database = (yyvsp[(4) - (7)].str); - n->to_database = (yyvsp[(6) - (7)].str); - n->copy_database_flag = (yyvsp[(7) - (7)].conststr); + n->from_database = (yyvsp[-3].str); + n->to_database = (yyvsp[-1].str); + n->copy_database_flag = (yyvsp[0].conststr); (yyval.node) = (PGNode *)n; - ;} + } +#line 22918 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 456: + case 461: /* copy_database_flag: %empty */ #line 61 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.conststr) = NULL; ;} + { (yyval.conststr) = NULL; } +#line 22924 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 457: + case 462: /* copy_database_flag: '(' SCHEMA ')' */ #line 62 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.conststr) = "schema"; ;} + { (yyval.conststr) = "schema"; } +#line 22930 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 458: + case 463: /* copy_database_flag: '(' DATA_P ')' */ #line 63 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.conststr) = "data"; ;} + { (yyval.conststr) = "data"; } +#line 22936 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 459: + case 464: /* copy_from: FROM */ #line 67 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 22942 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 460: + case 465: /* copy_from: TO */ #line 68 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 22948 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 461: + case 466: /* copy_delimiter: opt_using DELIMITERS Sconst */ #line 74 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("delimiter", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(2) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("delimiter", (PGNode *)makeString((yyvsp[0].str)), (yylsp[-1])); + } +#line 22956 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 462: + case 467: /* copy_delimiter: %empty */ #line 77 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.defelt) = NULL; ;} + { (yyval.defelt) = NULL; } +#line 22962 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 463: + case 468: /* copy_generic_opt_arg_list: copy_generic_opt_arg_list_item */ #line 83 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} + { + (yyval.list) = list_make1((yyvsp[0].node)); + } +#line 22970 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 464: + case 469: /* copy_generic_opt_arg_list: copy_generic_opt_arg_list ',' copy_generic_opt_arg_list_item */ #line 87 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} + { + (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); + } +#line 22978 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 465: + case 470: /* opt_using: USING */ #line 94 "third_party/libpg_query/grammar/statements/copy.y" - {;} + {} +#line 22984 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 466: + case 471: /* opt_using: %empty */ #line 95 "third_party/libpg_query/grammar/statements/copy.y" - {;} + {} +#line 22990 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 467: + case 472: /* opt_as: AS */ #line 99 "third_party/libpg_query/grammar/statements/copy.y" - {;} + {} +#line 22996 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 468: + case 473: /* opt_as: %empty */ #line 100 "third_party/libpg_query/grammar/statements/copy.y" - {;} + {} +#line 23002 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 469: + case 474: /* opt_program: PROGRAM */ #line 105 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 23008 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 470: + case 475: /* opt_program: %empty */ #line 106 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 23014 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 471: + case 476: /* copy_options: copy_opt_list */ #line 110 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 23020 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 472: + case 477: /* copy_options: '(' copy_generic_opt_list ')' */ #line 111 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 23026 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 473: + case 478: /* copy_generic_opt_arg: opt_boolean_or_string */ #line 116 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} + { (yyval.node) = (PGNode *) makeString((yyvsp[0].str)); } +#line 23032 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 474: + case 479: /* copy_generic_opt_arg: NumericOnly */ #line 117 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].value); ;} + { (yyval.node) = (PGNode *) (yyvsp[0].value); } +#line 23038 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 475: + case 480: /* copy_generic_opt_arg: list_expr */ #line 118 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (PGNode *) (yyvsp[0].node); } +#line 23044 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 476: + case 481: /* copy_generic_opt_arg: '*' */ #line 119 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) makeNode(PGAStar); ;} + { (yyval.node) = (PGNode *) makeNode(PGAStar); } +#line 23050 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 477: + case 482: /* copy_generic_opt_arg: '(' copy_generic_opt_arg_list ')' */ #line 120 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) (yyvsp[(2) - (3)].list); ;} + { (yyval.node) = (PGNode *) (yyvsp[-1].list); } +#line 23056 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 478: + case 483: /* copy_generic_opt_arg: struct_expr */ #line 121 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (PGNode *) (yyvsp[0].node); } +#line 23062 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 479: + case 484: /* copy_generic_opt_arg: %empty */ #line 122 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 23068 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 480: + case 485: /* copy_generic_opt_elem: ColLabel copy_generic_opt_arg */ #line 128 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem((yyvsp[-1].str), (yyvsp[0].node), (yylsp[-1])); + } +#line 23076 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 481: + case 486: /* opt_oids: WITH OIDS */ #line 136 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("oids", (PGNode *)makeInteger(true), (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem("oids", (PGNode *)makeInteger(true), (yylsp[-1])); + } +#line 23084 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 482: + case 487: /* opt_oids: %empty */ #line 139 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.defelt) = NULL; ;} + { (yyval.defelt) = NULL; } +#line 23090 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 483: + case 488: /* copy_opt_list: copy_opt_list copy_opt_item */ #line 144 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].defelt)); ;} + { (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].defelt)); } +#line 23096 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 484: + case 489: /* copy_opt_list: %empty */ #line 145 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 23102 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 485: + case 490: /* opt_binary: BINARY */ #line 151 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("binary"), (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("binary"), (yylsp[0])); + } +#line 23110 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 486: + case 491: /* opt_binary: %empty */ #line 154 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.defelt) = NULL; ;} + { (yyval.defelt) = NULL; } +#line 23116 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 487: + case 492: /* copy_opt_item: BINARY */ #line 160 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("binary"), (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("binary"), (yylsp[0])); + } +#line 23124 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 488: + case 493: /* copy_opt_item: OIDS */ #line 164 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("oids", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem("oids", (PGNode *)makeInteger(true), (yylsp[0])); + } +#line 23132 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 489: + case 494: /* copy_opt_item: FREEZE */ #line 168 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("freeze", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem("freeze", (PGNode *)makeInteger(true), (yylsp[0])); + } +#line 23140 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 490: + case 495: /* copy_opt_item: DELIMITER opt_as Sconst */ #line 172 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("delimiter", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("delimiter", (PGNode *)makeString((yyvsp[0].str)), (yylsp[-2])); + } +#line 23148 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 491: + case 496: /* copy_opt_item: NULL_P opt_as Sconst */ #line 176 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("null", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("null", (PGNode *)makeString((yyvsp[0].str)), (yylsp[-2])); + } +#line 23156 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 492: + case 497: /* copy_opt_item: CSV */ #line 180 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("csv"), (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("csv"), (yylsp[0])); + } +#line 23164 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 493: + case 498: /* copy_opt_item: HEADER_P */ #line 184 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("header", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); - ;} + { + (yyval.defelt) = makeDefElem("header", (PGNode *)makeInteger(true), (yylsp[0])); + } +#line 23172 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 494: + case 499: /* copy_opt_item: QUOTE opt_as Sconst */ #line 188 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("quote", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("quote", (PGNode *)makeString((yyvsp[0].str)), (yylsp[-2])); + } +#line 23180 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 495: + case 500: /* copy_opt_item: ESCAPE opt_as Sconst */ #line 192 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("escape", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("escape", (PGNode *)makeString((yyvsp[0].str)), (yylsp[-2])); + } +#line 23188 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 496: + case 501: /* copy_opt_item: FORCE QUOTE columnList */ #line 196 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("force_quote", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("force_quote", (PGNode *)(yyvsp[0].list), (yylsp[-2])); + } +#line 23196 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 497: + case 502: /* copy_opt_item: FORCE QUOTE '*' */ #line 200 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("force_quote", (PGNode *)makeNode(PGAStar), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("force_quote", (PGNode *)makeNode(PGAStar), (yylsp[-2])); + } +#line 23204 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 498: + case 503: /* copy_opt_item: PARTITION BY columnList */ #line 204 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("partition_by", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("partition_by", (PGNode *)(yyvsp[0].list), (yylsp[-2])); + } +#line 23212 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 499: + case 504: /* copy_opt_item: PARTITION BY '*' */ #line 208 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("partition_by", (PGNode *)makeNode(PGAStar), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("partition_by", (PGNode *)makeNode(PGAStar), (yylsp[-2])); + } +#line 23220 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 500: + case 505: /* copy_opt_item: FORCE NOT NULL_P columnList */ #line 212 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("force_not_null", (PGNode *)(yyvsp[(4) - (4)].list), (yylsp[(1) - (4)])); - ;} + { + (yyval.defelt) = makeDefElem("force_not_null", (PGNode *)(yyvsp[0].list), (yylsp[-3])); + } +#line 23228 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 501: + case 506: /* copy_opt_item: FORCE NULL_P columnList */ #line 216 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("force_null", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); - ;} + { + (yyval.defelt) = makeDefElem("force_null", (PGNode *)(yyvsp[0].list), (yylsp[-2])); + } +#line 23236 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 502: + case 507: /* copy_opt_item: ENCODING Sconst */ #line 220 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("encoding", (PGNode *)makeString((yyvsp[(2) - (2)].str)), (yylsp[(1) - (2)])); - ;} + { + (yyval.defelt) = makeDefElem("encoding", (PGNode *)makeString((yyvsp[0].str)), (yylsp[-1])); + } +#line 23244 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 503: + case 508: /* copy_generic_opt_arg_list_item: opt_boolean_or_string */ #line 227 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} + { (yyval.node) = (PGNode *) makeString((yyvsp[0].str)); } +#line 23250 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 504: + case 509: /* copy_file_name: Sconst */ #line 232 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 23256 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 505: + case 510: /* copy_file_name: STDIN */ #line 233 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.str) = NULL; ;} + { (yyval.str) = NULL; } +#line 23262 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 506: + case 511: /* copy_file_name: STDOUT */ #line 234 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.str) = NULL; ;} + { (yyval.str) = NULL; } +#line 23268 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 507: + case 512: /* copy_file_name: IDENT '.' ColId */ #line 235 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.str) = psprintf("%s.%s", (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str)); ;} + { (yyval.str) = psprintf("%s.%s", (yyvsp[-2].str), (yyvsp[0].str)); } +#line 23274 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 508: + case 513: /* copy_file_name: IDENT */ #line 236 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 23280 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 509: + case 514: /* copy_generic_opt_list: copy_generic_opt_elem */ #line 243 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); - ;} + { + (yyval.list) = list_make1((yyvsp[0].defelt)); + } +#line 23288 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 510: + case 515: /* copy_generic_opt_list: copy_generic_opt_list ',' copy_generic_opt_elem */ #line 247 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); - ;} + { + (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].defelt)); + } +#line 23296 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 513: + case 518: /* select_with_parens: '(' select_no_parens ')' */ #line 52 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (3)].node); ;} + { (yyval.node) = (yyvsp[-1].node); } +#line 23302 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 514: + case 519: /* select_with_parens: '(' select_with_parens ')' */ #line 53 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (3)].node); ;} + { (yyval.node) = (yyvsp[-1].node); } +#line 23308 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 515: + case 520: /* select_with_parens: '(' VariableShowStmt ')' */ #line 55 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(2) - (3)].node); - ;} + { + (yyval.node) = (yyvsp[-1].node); + } +#line 23316 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 516: + case 521: /* select_no_parens: simple_select */ #line 72 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 23322 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 517: + case 522: /* select_no_parens: select_clause sort_clause */ #line 74 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].list), NIL, + { + insertSelectOptions((PGSelectStmt *) (yyvsp[-1].node), (yyvsp[0].list), NIL, NULL, NULL, NULL, yyscanner); - (yyval.node) = (yyvsp[(1) - (2)].node); - ;} + (yyval.node) = (yyvsp[-1].node); + } +#line 23333 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 518: + case 523: /* select_no_parens: select_clause opt_sort_clause for_locking_clause opt_select_limit */ #line 81 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(1) - (4)].node), (yyvsp[(2) - (4)].list), (yyvsp[(3) - (4)].list), - (PGNode*) list_nth((yyvsp[(4) - (4)].list), 0), (PGNode*) list_nth((yyvsp[(4) - (4)].list), 1), + { + insertSelectOptions((PGSelectStmt *) (yyvsp[-3].node), (yyvsp[-2].list), (yyvsp[-1].list), + (PGNode*) list_nth((yyvsp[0].list), 0), (PGNode*) list_nth((yyvsp[0].list), 1), NULL, yyscanner); - (yyval.node) = (yyvsp[(1) - (4)].node); - ;} + (yyval.node) = (yyvsp[-3].node); + } +#line 23345 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 519: + case 524: /* select_no_parens: select_clause opt_sort_clause select_limit opt_for_locking_clause */ #line 89 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(1) - (4)].node), (yyvsp[(2) - (4)].list), (yyvsp[(4) - (4)].list), - (PGNode*) list_nth((yyvsp[(3) - (4)].list), 0), (PGNode*) list_nth((yyvsp[(3) - (4)].list), 1), + { + insertSelectOptions((PGSelectStmt *) (yyvsp[-3].node), (yyvsp[-2].list), (yyvsp[0].list), + (PGNode*) list_nth((yyvsp[-1].list), 0), (PGNode*) list_nth((yyvsp[-1].list), 1), NULL, yyscanner); - (yyval.node) = (yyvsp[(1) - (4)].node); - ;} + (yyval.node) = (yyvsp[-3].node); + } +#line 23357 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 520: + case 525: /* select_no_parens: with_clause select_clause */ #line 97 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (2)].node), NULL, NIL, + { + insertSelectOptions((PGSelectStmt *) (yyvsp[0].node), NULL, NIL, NULL, NULL, - (yyvsp[(1) - (2)].with), + (yyvsp[-1].with), yyscanner); - (yyval.node) = (yyvsp[(2) - (2)].node); - ;} + (yyval.node) = (yyvsp[0].node); + } +#line 23369 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 521: + case 526: /* select_no_parens: with_clause select_clause sort_clause */ #line 105 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (3)].node), (yyvsp[(3) - (3)].list), NIL, + { + insertSelectOptions((PGSelectStmt *) (yyvsp[-1].node), (yyvsp[0].list), NIL, NULL, NULL, - (yyvsp[(1) - (3)].with), + (yyvsp[-2].with), yyscanner); - (yyval.node) = (yyvsp[(2) - (3)].node); - ;} + (yyval.node) = (yyvsp[-1].node); + } +#line 23381 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 522: + case 527: /* select_no_parens: with_clause select_clause opt_sort_clause for_locking_clause opt_select_limit */ #line 113 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (5)].node), (yyvsp[(3) - (5)].list), (yyvsp[(4) - (5)].list), - (PGNode*) list_nth((yyvsp[(5) - (5)].list), 0), (PGNode*) list_nth((yyvsp[(5) - (5)].list), 1), - (yyvsp[(1) - (5)].with), + { + insertSelectOptions((PGSelectStmt *) (yyvsp[-3].node), (yyvsp[-2].list), (yyvsp[-1].list), + (PGNode*) list_nth((yyvsp[0].list), 0), (PGNode*) list_nth((yyvsp[0].list), 1), + (yyvsp[-4].with), yyscanner); - (yyval.node) = (yyvsp[(2) - (5)].node); - ;} + (yyval.node) = (yyvsp[-3].node); + } +#line 23393 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 523: + case 528: /* select_no_parens: with_clause select_clause opt_sort_clause select_limit opt_for_locking_clause */ #line 121 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (5)].node), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list), - (PGNode*) list_nth((yyvsp[(4) - (5)].list), 0), (PGNode*) list_nth((yyvsp[(4) - (5)].list), 1), - (yyvsp[(1) - (5)].with), + { + insertSelectOptions((PGSelectStmt *) (yyvsp[-3].node), (yyvsp[-2].list), (yyvsp[0].list), + (PGNode*) list_nth((yyvsp[-1].list), 0), (PGNode*) list_nth((yyvsp[-1].list), 1), + (yyvsp[-4].with), yyscanner); - (yyval.node) = (yyvsp[(2) - (5)].node); - ;} + (yyval.node) = (yyvsp[-3].node); + } +#line 23405 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 524: + case 529: /* select_clause: simple_select */ #line 131 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 23411 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 525: + case 530: /* select_clause: select_with_parens */ #line 132 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 23417 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 526: + case 531: /* opt_select: SELECT opt_all_clause opt_target_list_opt_comma */ #line 160 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(3) - (3)].list); - ;} + { + (yyval.list) = (yyvsp[0].list); + } +#line 23425 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 527: + case 532: /* opt_select: %empty */ #line 164 "third_party/libpg_query/grammar/statements/select.y" - { + { PGAStar *star = makeNode(PGAStar); (yyval.list) = list_make1(star); - ;} + } +#line 23434 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 528: + case 533: /* simple_select: SELECT opt_all_clause opt_target_list_opt_comma into_clause from_clause where_clause group_clause having_clause window_clause qualify_clause sample_clause */ #line 175 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *n = makeNode(PGSelectStmt); - n->targetList = (yyvsp[(3) - (11)].list); - n->intoClause = (yyvsp[(4) - (11)].into); - n->fromClause = (yyvsp[(5) - (11)].list); - n->whereClause = (yyvsp[(6) - (11)].node); - n->groupClause = (yyvsp[(7) - (11)].list); - n->havingClause = (yyvsp[(8) - (11)].node); - n->windowClause = (yyvsp[(9) - (11)].list); - n->qualifyClause = (yyvsp[(10) - (11)].node); - n->sampleOptions = (yyvsp[(11) - (11)].node); + n->targetList = (yyvsp[-8].list); + n->intoClause = (yyvsp[-7].into); + n->fromClause = (yyvsp[-6].list); + n->whereClause = (yyvsp[-5].node); + n->groupClause = (yyvsp[-4].list); + n->havingClause = (yyvsp[-3].node); + n->windowClause = (yyvsp[-2].list); + n->qualifyClause = (yyvsp[-1].node); + n->sampleOptions = (yyvsp[0].node); (yyval.node) = (PGNode *)n; - ;} + } +#line 23452 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 529: + case 534: /* simple_select: SELECT distinct_clause target_list_opt_comma into_clause from_clause where_clause group_clause having_clause window_clause qualify_clause sample_clause */ #line 191 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *n = makeNode(PGSelectStmt); - n->distinctClause = (yyvsp[(2) - (11)].list); - n->targetList = (yyvsp[(3) - (11)].list); - n->intoClause = (yyvsp[(4) - (11)].into); - n->fromClause = (yyvsp[(5) - (11)].list); - n->whereClause = (yyvsp[(6) - (11)].node); - n->groupClause = (yyvsp[(7) - (11)].list); - n->havingClause = (yyvsp[(8) - (11)].node); - n->windowClause = (yyvsp[(9) - (11)].list); - n->qualifyClause = (yyvsp[(10) - (11)].node); - n->sampleOptions = (yyvsp[(11) - (11)].node); + n->distinctClause = (yyvsp[-9].list); + n->targetList = (yyvsp[-8].list); + n->intoClause = (yyvsp[-7].into); + n->fromClause = (yyvsp[-6].list); + n->whereClause = (yyvsp[-5].node); + n->groupClause = (yyvsp[-4].list); + n->havingClause = (yyvsp[-3].node); + n->windowClause = (yyvsp[-2].list); + n->qualifyClause = (yyvsp[-1].node); + n->sampleOptions = (yyvsp[0].node); (yyval.node) = (PGNode *)n; - ;} + } +#line 23471 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 530: + case 535: /* simple_select: FROM from_list opt_select into_clause where_clause group_clause having_clause window_clause qualify_clause sample_clause */ #line 208 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *n = makeNode(PGSelectStmt); - n->targetList = (yyvsp[(3) - (10)].list); - n->fromClause = (yyvsp[(2) - (10)].list); - n->intoClause = (yyvsp[(4) - (10)].into); - n->whereClause = (yyvsp[(5) - (10)].node); - n->groupClause = (yyvsp[(6) - (10)].list); - n->havingClause = (yyvsp[(7) - (10)].node); - n->windowClause = (yyvsp[(8) - (10)].list); - n->qualifyClause = (yyvsp[(9) - (10)].node); - n->sampleOptions = (yyvsp[(10) - (10)].node); + n->targetList = (yyvsp[-7].list); + n->fromClause = (yyvsp[-8].list); + n->intoClause = (yyvsp[-6].into); + n->whereClause = (yyvsp[-5].node); + n->groupClause = (yyvsp[-4].list); + n->havingClause = (yyvsp[-3].node); + n->windowClause = (yyvsp[-2].list); + n->qualifyClause = (yyvsp[-1].node); + n->sampleOptions = (yyvsp[0].node); (yyval.node) = (PGNode *)n; - ;} + } +#line 23489 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 531: + case 536: /* simple_select: FROM from_list SELECT distinct_clause target_list_opt_comma into_clause where_clause group_clause having_clause window_clause qualify_clause sample_clause */ #line 225 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *n = makeNode(PGSelectStmt); - n->targetList = (yyvsp[(5) - (12)].list); - n->distinctClause = (yyvsp[(4) - (12)].list); - n->fromClause = (yyvsp[(2) - (12)].list); - n->intoClause = (yyvsp[(6) - (12)].into); - n->whereClause = (yyvsp[(7) - (12)].node); - n->groupClause = (yyvsp[(8) - (12)].list); - n->havingClause = (yyvsp[(9) - (12)].node); - n->windowClause = (yyvsp[(10) - (12)].list); - n->qualifyClause = (yyvsp[(11) - (12)].node); - n->sampleOptions = (yyvsp[(12) - (12)].node); + n->targetList = (yyvsp[-7].list); + n->distinctClause = (yyvsp[-8].list); + n->fromClause = (yyvsp[-10].list); + n->intoClause = (yyvsp[-6].into); + n->whereClause = (yyvsp[-5].node); + n->groupClause = (yyvsp[-4].list); + n->havingClause = (yyvsp[-3].node); + n->windowClause = (yyvsp[-2].list); + n->qualifyClause = (yyvsp[-1].node); + n->sampleOptions = (yyvsp[0].node); (yyval.node) = (PGNode *)n; - ;} + } +#line 23508 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 532: + case 537: /* simple_select: values_clause_opt_comma */ #line 239 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 23514 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 533: + case 538: /* simple_select: TABLE relation_expr */ #line 241 "third_party/libpg_query/grammar/statements/select.y" - { + { /* same as SELECT * FROM relation_expr */ PGColumnRef *cr = makeNode(PGColumnRef); PGResTarget *rt = makeNode(PGResTarget); @@ -23969,1749 +23530,1989 @@ YYLTYPE yylloc; rt->location = -1; n->targetList = list_make1(rt); - n->fromClause = list_make1((yyvsp[(2) - (2)].range)); + n->fromClause = list_make1((yyvsp[0].range)); (yyval.node) = (PGNode *)n; - ;} + } +#line 23537 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 534: + case 539: /* simple_select: select_clause UNION all_or_distinct by_name select_clause */ #line 260 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSetOp(PG_SETOP_UNION_BY_NAME, (yyvsp[(3) - (5)].boolean), (yyvsp[(1) - (5)].node), (yyvsp[(5) - (5)].node)); - ;} + { + (yyval.node) = makeSetOp(PG_SETOP_UNION_BY_NAME, (yyvsp[-2].boolean), (yyvsp[-4].node), (yyvsp[0].node)); + } +#line 23545 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 535: + case 540: /* simple_select: select_clause UNION all_or_distinct select_clause */ #line 264 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSetOp(PG_SETOP_UNION, (yyvsp[(3) - (4)].boolean), (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node)); - ;} + { + (yyval.node) = makeSetOp(PG_SETOP_UNION, (yyvsp[-1].boolean), (yyvsp[-3].node), (yyvsp[0].node)); + } +#line 23553 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 536: + case 541: /* simple_select: select_clause INTERSECT all_or_distinct select_clause */ #line 268 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSetOp(PG_SETOP_INTERSECT, (yyvsp[(3) - (4)].boolean), (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node)); - ;} + { + (yyval.node) = makeSetOp(PG_SETOP_INTERSECT, (yyvsp[-1].boolean), (yyvsp[-3].node), (yyvsp[0].node)); + } +#line 23561 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 537: + case 542: /* simple_select: select_clause EXCEPT all_or_distinct select_clause */ #line 272 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSetOp(PG_SETOP_EXCEPT, (yyvsp[(3) - (4)].boolean), (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node)); - ;} + { + (yyval.node) = makeSetOp(PG_SETOP_EXCEPT, (yyvsp[-1].boolean), (yyvsp[-3].node), (yyvsp[0].node)); + } +#line 23569 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 538: + case 543: /* simple_select: pivot_keyword table_ref USING target_list_opt_comma */ #line 276 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *res = makeNode(PGSelectStmt); PGPivotStmt *n = makeNode(PGPivotStmt); - n->source = (yyvsp[(2) - (4)].node); - n->aggrs = (yyvsp[(4) - (4)].list); - n->location = (yylsp[(1) - (4)]); + n->source = (yyvsp[-2].node); + n->aggrs = (yyvsp[0].list); + n->location = (yylsp[-3]); res->pivot = n; (yyval.node) = (PGNode *)res; - ;} + } +#line 23583 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 539: + case 544: /* simple_select: pivot_keyword table_ref USING target_list_opt_comma GROUP_P BY name_list_opt_comma_opt_bracket */ #line 286 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *res = makeNode(PGSelectStmt); PGPivotStmt *n = makeNode(PGPivotStmt); - n->source = (yyvsp[(2) - (7)].node); - n->aggrs = (yyvsp[(4) - (7)].list); - n->groups = (yyvsp[(7) - (7)].list); - n->location = (yylsp[(1) - (7)]); + n->source = (yyvsp[-5].node); + n->aggrs = (yyvsp[-3].list); + n->groups = (yyvsp[0].list); + n->location = (yylsp[-6]); res->pivot = n; (yyval.node) = (PGNode *)res; - ;} + } +#line 23598 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 540: + case 545: /* simple_select: pivot_keyword table_ref GROUP_P BY name_list_opt_comma_opt_bracket */ #line 297 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *res = makeNode(PGSelectStmt); PGPivotStmt *n = makeNode(PGPivotStmt); - n->source = (yyvsp[(2) - (5)].node); - n->groups = (yyvsp[(5) - (5)].list); - n->location = (yylsp[(1) - (5)]); + n->source = (yyvsp[-3].node); + n->groups = (yyvsp[0].list); + n->location = (yylsp[-4]); res->pivot = n; (yyval.node) = (PGNode *)res; - ;} + } +#line 23612 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 541: + case 546: /* simple_select: pivot_keyword table_ref ON pivot_column_list */ #line 307 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *res = makeNode(PGSelectStmt); PGPivotStmt *n = makeNode(PGPivotStmt); - n->source = (yyvsp[(2) - (4)].node); - n->columns = (yyvsp[(4) - (4)].list); + n->source = (yyvsp[-2].node); + n->columns = (yyvsp[0].list); res->pivot = n; (yyval.node) = (PGNode *)res; - ;} + } +#line 23625 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 542: + case 547: /* simple_select: pivot_keyword table_ref ON pivot_column_list GROUP_P BY name_list_opt_comma_opt_bracket */ #line 316 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *res = makeNode(PGSelectStmt); PGPivotStmt *n = makeNode(PGPivotStmt); - n->source = (yyvsp[(2) - (7)].node); - n->columns = (yyvsp[(4) - (7)].list); - n->groups = (yyvsp[(7) - (7)].list); - n->location = (yylsp[(1) - (7)]); + n->source = (yyvsp[-5].node); + n->columns = (yyvsp[-3].list); + n->groups = (yyvsp[0].list); + n->location = (yylsp[-6]); res->pivot = n; (yyval.node) = (PGNode *)res; - ;} + } +#line 23640 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 543: + case 548: /* simple_select: pivot_keyword table_ref ON pivot_column_list USING target_list_opt_comma */ #line 327 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *res = makeNode(PGSelectStmt); PGPivotStmt *n = makeNode(PGPivotStmt); - n->source = (yyvsp[(2) - (6)].node); - n->columns = (yyvsp[(4) - (6)].list); - n->aggrs = (yyvsp[(6) - (6)].list); - n->location = (yylsp[(1) - (6)]); + n->source = (yyvsp[-4].node); + n->columns = (yyvsp[-2].list); + n->aggrs = (yyvsp[0].list); + n->location = (yylsp[-5]); res->pivot = n; (yyval.node) = (PGNode *)res; - ;} + } +#line 23655 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 544: + case 549: /* simple_select: pivot_keyword table_ref ON pivot_column_list USING target_list_opt_comma GROUP_P BY name_list_opt_comma_opt_bracket */ #line 338 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *res = makeNode(PGSelectStmt); PGPivotStmt *n = makeNode(PGPivotStmt); - n->source = (yyvsp[(2) - (9)].node); - n->columns = (yyvsp[(4) - (9)].list); - n->aggrs = (yyvsp[(6) - (9)].list); - n->groups = (yyvsp[(9) - (9)].list); - n->location = (yylsp[(1) - (9)]); + n->source = (yyvsp[-7].node); + n->columns = (yyvsp[-5].list); + n->aggrs = (yyvsp[-3].list); + n->groups = (yyvsp[0].list); + n->location = (yylsp[-8]); res->pivot = n; (yyval.node) = (PGNode *)res; - ;} + } +#line 23671 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 545: + case 550: /* simple_select: unpivot_keyword table_ref ON target_list_opt_comma INTO NAME_P name value_or_values name_list_opt_comma_opt_bracket */ #line 350 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *res = makeNode(PGSelectStmt); PGPivotStmt *n = makeNode(PGPivotStmt); - n->source = (yyvsp[(2) - (9)].node); - n->unpivots = (yyvsp[(9) - (9)].list); - n->location = (yylsp[(1) - (9)]); + n->source = (yyvsp[-7].node); + n->unpivots = (yyvsp[0].list); + n->location = (yylsp[-8]); PGPivot *piv = makeNode(PGPivot); - piv->unpivot_columns = list_make1(makeString((yyvsp[(7) - (9)].str))); - piv->pivot_value = (yyvsp[(4) - (9)].list); + piv->unpivot_columns = list_make1(makeString((yyvsp[-2].str))); + piv->pivot_value = (yyvsp[-5].list); n->columns = list_make1(piv); res->pivot = n; (yyval.node) = (PGNode *)res; - ;} + } +#line 23690 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 546: + case 551: /* simple_select: unpivot_keyword table_ref ON target_list_opt_comma */ #line 365 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *res = makeNode(PGSelectStmt); PGPivotStmt *n = makeNode(PGPivotStmt); - n->source = (yyvsp[(2) - (4)].node); + n->source = (yyvsp[-2].node); n->unpivots = list_make1(makeString("value")); - n->location = (yylsp[(1) - (4)]); + n->location = (yylsp[-3]); PGPivot *piv = makeNode(PGPivot); piv->unpivot_columns = list_make1(makeString("name")); - piv->pivot_value = (yyvsp[(4) - (4)].list); + piv->pivot_value = (yyvsp[0].list); n->columns = list_make1(piv); res->pivot = n; (yyval.node) = (PGNode *)res; - ;} + } +#line 23709 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 553: + case 558: /* pivot_column_entry: b_expr */ #line 395 "third_party/libpg_query/grammar/statements/select.y" - { + { PGPivot *n = makeNode(PGPivot); - n->pivot_columns = list_make1((yyvsp[(1) - (1)].node)); + n->pivot_columns = list_make1((yyvsp[0].node)); (yyval.node) = (PGNode *) n; - ;} + } +#line 23719 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 554: + case 559: /* pivot_column_entry: b_expr IN_P '(' select_no_parens ')' */ #line 401 "third_party/libpg_query/grammar/statements/select.y" - { + { PGPivot *n = makeNode(PGPivot); - n->pivot_columns = list_make1((yyvsp[(1) - (5)].node)); - n->subquery = (yyvsp[(4) - (5)].node); + n->pivot_columns = list_make1((yyvsp[-4].node)); + n->subquery = (yyvsp[-1].node); (yyval.node) = (PGNode *) n; - ;} + } +#line 23730 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 555: + case 560: /* pivot_column_entry: single_pivot_value */ #line 407 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 23736 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 556: + case 561: /* pivot_column_list_internal: pivot_column_entry */ #line 411 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 23742 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 557: + case 562: /* pivot_column_list_internal: pivot_column_list_internal ',' pivot_column_entry */ #line 412 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); } +#line 23748 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 558: + case 563: /* pivot_column_list: pivot_column_list_internal */ #line 416 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 23754 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 559: + case 564: /* pivot_column_list: pivot_column_list_internal ',' */ #line 417 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 23760 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 560: + case 565: /* with_clause: WITH cte_list */ #line 432 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.with) = makeNode(PGWithClause); - (yyval.with)->ctes = (yyvsp[(2) - (2)].list); + (yyval.with)->ctes = (yyvsp[0].list); (yyval.with)->recursive = false; - (yyval.with)->location = (yylsp[(1) - (2)]); - ;} + (yyval.with)->location = (yylsp[-1]); + } +#line 23771 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 561: + case 566: /* with_clause: WITH_LA cte_list */ #line 439 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.with) = makeNode(PGWithClause); - (yyval.with)->ctes = (yyvsp[(2) - (2)].list); + (yyval.with)->ctes = (yyvsp[0].list); (yyval.with)->recursive = false; - (yyval.with)->location = (yylsp[(1) - (2)]); - ;} + (yyval.with)->location = (yylsp[-1]); + } +#line 23782 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 562: + case 567: /* with_clause: WITH RECURSIVE cte_list */ #line 446 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.with) = makeNode(PGWithClause); - (yyval.with)->ctes = (yyvsp[(3) - (3)].list); + (yyval.with)->ctes = (yyvsp[0].list); (yyval.with)->recursive = true; - (yyval.with)->location = (yylsp[(1) - (3)]); - ;} + (yyval.with)->location = (yylsp[-2]); + } +#line 23793 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 563: + case 568: /* cte_list: common_table_expr */ #line 455 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 23799 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 564: + case 569: /* cte_list: cte_list ',' common_table_expr */ #line 456 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); } +#line 23805 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 565: + case 570: /* common_table_expr: name opt_name_list AS opt_materialized '(' PreparableStmt ')' */ #line 460 "third_party/libpg_query/grammar/statements/select.y" - { + { PGCommonTableExpr *n = makeNode(PGCommonTableExpr); - n->ctename = (yyvsp[(1) - (7)].str); - n->aliascolnames = (yyvsp[(2) - (7)].list); - n->ctematerialized = (yyvsp[(4) - (7)].ctematerialize); - n->ctequery = (yyvsp[(6) - (7)].node); - n->location = (yylsp[(1) - (7)]); + n->ctename = (yyvsp[-6].str); + n->aliascolnames = (yyvsp[-5].list); + n->ctematerialized = (yyvsp[-3].ctematerialize); + n->ctequery = (yyvsp[-1].node); + n->location = (yylsp[-6]); (yyval.node) = (PGNode *) n; - ;} + } +#line 23819 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 566: + case 571: /* opt_materialized: MATERIALIZED */ #line 472 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ctematerialize) = PGCTEMaterializeAlways; ;} + { (yyval.ctematerialize) = PGCTEMaterializeAlways; } +#line 23825 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 567: + case 572: /* opt_materialized: NOT MATERIALIZED */ #line 473 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ctematerialize) = PGCTEMaterializeNever; ;} + { (yyval.ctematerialize) = PGCTEMaterializeNever; } +#line 23831 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 568: + case 573: /* opt_materialized: %empty */ #line 474 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ctematerialize) = PGCTEMaterializeDefault; ;} + { (yyval.ctematerialize) = PGCTEMaterializeDefault; } +#line 23837 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 569: + case 574: /* into_clause: INTO OptTempTableName */ #line 479 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.into) = makeNode(PGIntoClause); - (yyval.into)->rel = (yyvsp[(2) - (2)].range); + (yyval.into)->rel = (yyvsp[0].range); (yyval.into)->colNames = NIL; (yyval.into)->options = NIL; (yyval.into)->onCommit = PG_ONCOMMIT_NOOP; (yyval.into)->viewQuery = NULL; (yyval.into)->skipData = false; - ;} + } +#line 23851 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 570: + case 575: /* into_clause: %empty */ #line 489 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.into) = NULL; ;} + { (yyval.into) = NULL; } +#line 23857 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 571: + case 576: /* OptTempTableName: TEMPORARY opt_table qualified_name */ #line 498 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(3) - (3)].range); + { + (yyval.range) = (yyvsp[0].range); (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} + } +#line 23866 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 572: + case 577: /* OptTempTableName: TEMP opt_table qualified_name */ #line 503 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(3) - (3)].range); + { + (yyval.range) = (yyvsp[0].range); (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} + } +#line 23875 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 573: + case 578: /* OptTempTableName: LOCAL TEMPORARY opt_table qualified_name */ #line 508 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(4) - (4)].range); + { + (yyval.range) = (yyvsp[0].range); (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} + } +#line 23884 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 574: + case 579: /* OptTempTableName: LOCAL TEMP opt_table qualified_name */ #line 513 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(4) - (4)].range); + { + (yyval.range) = (yyvsp[0].range); (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} + } +#line 23893 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 575: + case 580: /* OptTempTableName: GLOBAL TEMPORARY opt_table qualified_name */ #line 518 "third_party/libpg_query/grammar/statements/select.y" - { + { ereport(PGWARNING, (errmsg("GLOBAL is deprecated in temporary table creation"), - parser_errposition((yylsp[(1) - (4)])))); - (yyval.range) = (yyvsp[(4) - (4)].range); + parser_errposition((yylsp[-3])))); + (yyval.range) = (yyvsp[0].range); (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} + } +#line 23905 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 576: + case 581: /* OptTempTableName: GLOBAL TEMP opt_table qualified_name */ #line 526 "third_party/libpg_query/grammar/statements/select.y" - { + { ereport(PGWARNING, (errmsg("GLOBAL is deprecated in temporary table creation"), - parser_errposition((yylsp[(1) - (4)])))); - (yyval.range) = (yyvsp[(4) - (4)].range); + parser_errposition((yylsp[-3])))); + (yyval.range) = (yyvsp[0].range); (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} + } +#line 23917 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 577: + case 582: /* OptTempTableName: UNLOGGED opt_table qualified_name */ #line 534 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(3) - (3)].range); + { + (yyval.range) = (yyvsp[0].range); (yyval.range)->relpersistence = PG_RELPERSISTENCE_UNLOGGED; - ;} + } +#line 23926 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 578: + case 583: /* OptTempTableName: TABLE qualified_name */ #line 539 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(2) - (2)].range); + { + (yyval.range) = (yyvsp[0].range); (yyval.range)->relpersistence = RELPERSISTENCE_PERMANENT; - ;} + } +#line 23935 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 579: + case 584: /* OptTempTableName: qualified_name */ #line 544 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(1) - (1)].range); + { + (yyval.range) = (yyvsp[0].range); (yyval.range)->relpersistence = RELPERSISTENCE_PERMANENT; - ;} + } +#line 23944 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 580: + case 585: /* opt_table: TABLE */ #line 550 "third_party/libpg_query/grammar/statements/select.y" - {;} + {} +#line 23950 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 581: + case 586: /* opt_table: %empty */ #line 551 "third_party/libpg_query/grammar/statements/select.y" - {;} + {} +#line 23956 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 582: + case 587: /* all_or_distinct: ALL */ #line 555 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 23962 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 583: + case 588: /* all_or_distinct: DISTINCT */ #line 556 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 23968 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 584: + case 589: /* all_or_distinct: %empty */ #line 557 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 23974 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 585: + case 590: /* by_name: BY NAME_P */ #line 561 "third_party/libpg_query/grammar/statements/select.y" - { ;} + { } +#line 23980 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 586: + case 591: /* distinct_clause: DISTINCT */ #line 568 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(NIL); ;} + { (yyval.list) = list_make1(NIL); } +#line 23986 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 587: + case 592: /* distinct_clause: DISTINCT ON '(' expr_list_opt_comma ')' */ #line 569 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(4) - (5)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 23992 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 588: + case 593: /* opt_all_clause: ALL */ #line 573 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL;;} + { (yyval.list) = NIL;} +#line 23998 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 589: + case 594: /* opt_all_clause: %empty */ #line 574 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 24004 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 590: + case 595: /* opt_ignore_nulls: IGNORE_P NULLS_P */ #line 578 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ignorenulls) = PG_IGNORE_NULLS;;} + { (yyval.ignorenulls) = PG_IGNORE_NULLS;} +#line 24010 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 591: + case 596: /* opt_ignore_nulls: RESPECT_P NULLS_P */ #line 579 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ignorenulls) = PG_RESPECT_NULLS;;} + { (yyval.ignorenulls) = PG_RESPECT_NULLS;} +#line 24016 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 592: + case 597: /* opt_ignore_nulls: %empty */ #line 580 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ignorenulls) = PG_DEFAULT_NULLS; ;} + { (yyval.ignorenulls) = PG_DEFAULT_NULLS; } +#line 24022 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 593: + case 598: /* opt_sort_clause: sort_clause */ #line 584 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list);;} + { (yyval.list) = (yyvsp[0].list);} +#line 24028 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 594: + case 599: /* opt_sort_clause: %empty */ #line 585 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 24034 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 595: + case 600: /* sort_clause: ORDER BY sortby_list */ #line 589 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (3)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 24040 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 596: + case 601: /* sort_clause: ORDER BY ALL opt_asc_desc opt_nulls_order */ #line 591 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSortBy *sort = makeNode(PGSortBy); PGAStar *star = makeNode(PGAStar); star->columns = true; - star->location = (yylsp[(3) - (5)]); + star->location = (yylsp[-2]); sort->node = (PGNode *) star; - sort->sortby_dir = (yyvsp[(4) - (5)].sortorder); - sort->sortby_nulls = (yyvsp[(5) - (5)].nullorder); + sort->sortby_dir = (yyvsp[-1].sortorder); + sort->sortby_nulls = (yyvsp[0].nullorder); sort->useOp = NIL; sort->location = -1; /* no operator */ (yyval.list) = list_make1(sort); - ;} + } +#line 24057 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 597: + case 602: /* sortby_list: sortby */ #line 606 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].sortby)); ;} + { (yyval.list) = list_make1((yyvsp[0].sortby)); } +#line 24063 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 598: + case 603: /* sortby_list: sortby_list ',' sortby */ #line 607 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].sortby)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].sortby)); } +#line 24069 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 599: + case 604: /* sortby: a_expr USING qual_all_Op opt_nulls_order */ #line 611 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.sortby) = makeNode(PGSortBy); - (yyval.sortby)->node = (yyvsp[(1) - (4)].node); + (yyval.sortby)->node = (yyvsp[-3].node); (yyval.sortby)->sortby_dir = SORTBY_USING; - (yyval.sortby)->sortby_nulls = (yyvsp[(4) - (4)].nullorder); - (yyval.sortby)->useOp = (yyvsp[(3) - (4)].list); - (yyval.sortby)->location = (yylsp[(3) - (4)]); - ;} + (yyval.sortby)->sortby_nulls = (yyvsp[0].nullorder); + (yyval.sortby)->useOp = (yyvsp[-1].list); + (yyval.sortby)->location = (yylsp[-1]); + } +#line 24082 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 600: + case 605: /* sortby: a_expr opt_asc_desc opt_nulls_order */ #line 620 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.sortby) = makeNode(PGSortBy); - (yyval.sortby)->node = (yyvsp[(1) - (3)].node); - (yyval.sortby)->sortby_dir = (yyvsp[(2) - (3)].sortorder); - (yyval.sortby)->sortby_nulls = (yyvsp[(3) - (3)].nullorder); + (yyval.sortby)->node = (yyvsp[-2].node); + (yyval.sortby)->sortby_dir = (yyvsp[-1].sortorder); + (yyval.sortby)->sortby_nulls = (yyvsp[0].nullorder); (yyval.sortby)->useOp = NIL; (yyval.sortby)->location = -1; /* no operator */ - ;} + } +#line 24095 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 601: + case 606: /* opt_asc_desc: ASC_P */ #line 630 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.sortorder) = PG_SORTBY_ASC; ;} + { (yyval.sortorder) = PG_SORTBY_ASC; } +#line 24101 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 602: + case 607: /* opt_asc_desc: DESC_P */ #line 631 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.sortorder) = PG_SORTBY_DESC; ;} + { (yyval.sortorder) = PG_SORTBY_DESC; } +#line 24107 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 603: + case 608: /* opt_asc_desc: %empty */ #line 632 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.sortorder) = PG_SORTBY_DEFAULT; ;} + { (yyval.sortorder) = PG_SORTBY_DEFAULT; } +#line 24113 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 604: + case 609: /* opt_nulls_order: NULLS_LA FIRST_P */ #line 635 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.nullorder) = PG_SORTBY_NULLS_FIRST; ;} + { (yyval.nullorder) = PG_SORTBY_NULLS_FIRST; } +#line 24119 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 605: + case 610: /* opt_nulls_order: NULLS_LA LAST_P */ #line 636 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.nullorder) = PG_SORTBY_NULLS_LAST; ;} + { (yyval.nullorder) = PG_SORTBY_NULLS_LAST; } +#line 24125 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 606: + case 611: /* opt_nulls_order: %empty */ #line 637 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.nullorder) = PG_SORTBY_NULLS_DEFAULT; ;} + { (yyval.nullorder) = PG_SORTBY_NULLS_DEFAULT; } +#line 24131 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 607: + case 612: /* select_limit: limit_clause offset_clause */ #line 641 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].node)); ;} + { (yyval.list) = list_make2((yyvsp[0].node), (yyvsp[-1].node)); } +#line 24137 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 608: + case 613: /* select_limit: offset_clause limit_clause */ #line 642 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); ;} + { (yyval.list) = list_make2((yyvsp[-1].node), (yyvsp[0].node)); } +#line 24143 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 609: + case 614: /* select_limit: limit_clause */ #line 643 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2(NULL, (yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make2(NULL, (yyvsp[0].node)); } +#line 24149 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 610: + case 615: /* select_limit: offset_clause */ #line 644 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(1) - (1)].node), NULL); ;} + { (yyval.list) = list_make2((yyvsp[0].node), NULL); } +#line 24155 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 611: + case 616: /* opt_select_limit: select_limit */ #line 648 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 24161 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 612: + case 617: /* opt_select_limit: %empty */ #line 649 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2(NULL,NULL); ;} + { (yyval.list) = list_make2(NULL,NULL); } +#line 24167 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 613: + case 618: /* limit_clause: LIMIT select_limit_value */ #line 654 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24173 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 614: + case 619: /* limit_clause: LIMIT select_limit_value ',' select_offset_value */ #line 656 "third_party/libpg_query/grammar/statements/select.y" - { + { /* Disabled because it was too confusing, bjm 2002-02-18 */ ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("LIMIT #,# syntax is not supported"), errhint("Use separate LIMIT and OFFSET clauses."), - parser_errposition((yylsp[(1) - (4)])))); - ;} + parser_errposition((yylsp[-3])))); + } +#line 24186 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 615: + case 620: /* limit_clause: FETCH first_or_next select_fetch_first_value row_or_rows ONLY */ #line 672 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(3) - (5)].node); ;} + { (yyval.node) = (yyvsp[-2].node); } +#line 24192 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 616: + case 621: /* limit_clause: FETCH first_or_next row_or_rows ONLY */ #line 674 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeIntConst(1, -1); ;} + { (yyval.node) = makeIntConst(1, -1); } +#line 24198 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 617: + case 622: /* offset_clause: OFFSET select_offset_value */ #line 679 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24204 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 618: + case 623: /* offset_clause: OFFSET select_fetch_first_value row_or_rows */ #line 682 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (3)].node); ;} + { (yyval.node) = (yyvsp[-1].node); } +#line 24210 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 619: + case 624: /* sample_count: FCONST '%' */ #line 690 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeFloat((yyvsp[(1) - (2)].str)), true); - ;} + { + (yyval.node) = makeSampleSize(makeFloat((yyvsp[-1].str)), true); + } +#line 24218 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 620: + case 625: /* sample_count: ICONST '%' */ #line 694 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (2)].ival)), true); - ;} + { + (yyval.node) = makeSampleSize(makeInteger((yyvsp[-1].ival)), true); + } +#line 24226 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 621: + case 626: /* sample_count: FCONST PERCENT */ #line 698 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeFloat((yyvsp[(1) - (2)].str)), true); - ;} + { + (yyval.node) = makeSampleSize(makeFloat((yyvsp[-1].str)), true); + } +#line 24234 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 622: + case 627: /* sample_count: ICONST PERCENT */ #line 702 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (2)].ival)), true); - ;} + { + (yyval.node) = makeSampleSize(makeInteger((yyvsp[-1].ival)), true); + } +#line 24242 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 623: + case 628: /* sample_count: ICONST */ #line 706 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (1)].ival)), false); - ;} + { + (yyval.node) = makeSampleSize(makeInteger((yyvsp[0].ival)), false); + } +#line 24250 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 624: + case 629: /* sample_count: ICONST ROWS */ #line 710 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (2)].ival)), false); - ;} + { + (yyval.node) = makeSampleSize(makeInteger((yyvsp[-1].ival)), false); + } +#line 24258 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 625: + case 630: /* sample_clause: USING SAMPLE tablesample_entry */ #line 717 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(3) - (3)].node); - ;} + { + (yyval.node) = (yyvsp[0].node); + } +#line 24266 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 626: + case 631: /* sample_clause: %empty */ #line 721 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 24272 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 627: + case 632: /* opt_sample_func: ColId */ #line 728 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 24278 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 628: + case 633: /* opt_sample_func: %empty */ #line 729 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = NULL; ;} + { (yyval.str) = NULL; } +#line 24284 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 629: + case 634: /* tablesample_entry: opt_sample_func '(' sample_count ')' opt_repeatable_clause */ #line 734 "third_party/libpg_query/grammar/statements/select.y" - { - int seed = (yyvsp[(5) - (5)].ival); - (yyval.node) = makeSampleOptions((yyvsp[(3) - (5)].node), (yyvsp[(1) - (5)].str), &seed, (yylsp[(1) - (5)])); - ;} + { + int seed = (yyvsp[0].ival); + (yyval.node) = makeSampleOptions((yyvsp[-2].node), (yyvsp[-4].str), &seed, (yylsp[-4])); + } +#line 24293 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 630: + case 635: /* tablesample_entry: sample_count */ #line 739 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleOptions((yyvsp[(1) - (1)].node), NULL, NULL, (yylsp[(1) - (1)])); - ;} + { + (yyval.node) = makeSampleOptions((yyvsp[0].node), NULL, NULL, (yylsp[0])); + } +#line 24301 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 631: + case 636: /* tablesample_entry: sample_count '(' ColId ')' */ #line 743 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleOptions((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].str), NULL, (yylsp[(1) - (4)])); - ;} + { + (yyval.node) = makeSampleOptions((yyvsp[-3].node), (yyvsp[-1].str), NULL, (yylsp[-3])); + } +#line 24309 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 632: + case 637: /* tablesample_entry: sample_count '(' ColId ',' ICONST ')' */ #line 747 "third_party/libpg_query/grammar/statements/select.y" - { - int seed = (yyvsp[(5) - (6)].ival); - (yyval.node) = makeSampleOptions((yyvsp[(1) - (6)].node), (yyvsp[(3) - (6)].str), &seed, (yylsp[(1) - (6)])); - ;} + { + int seed = (yyvsp[-1].ival); + (yyval.node) = makeSampleOptions((yyvsp[-5].node), (yyvsp[-3].str), &seed, (yylsp[-5])); + } +#line 24318 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 633: + case 638: /* tablesample_clause: TABLESAMPLE tablesample_entry */ #line 755 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(2) - (2)].node); - ;} + { + (yyval.node) = (yyvsp[0].node); + } +#line 24326 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 634: + case 639: /* opt_tablesample_clause: tablesample_clause */ #line 761 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24332 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 635: + case 640: /* opt_tablesample_clause: %empty */ #line 762 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 24338 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 636: + case 641: /* opt_repeatable_clause: REPEATABLE '(' ICONST ')' */ #line 767 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = (yyvsp[(3) - (4)].ival); ;} + { (yyval.ival) = (yyvsp[-1].ival); } +#line 24344 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 637: + case 642: /* opt_repeatable_clause: %empty */ #line 768 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = -1; ;} + { (yyval.ival) = -1; } +#line 24350 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 638: + case 643: /* select_limit_value: a_expr */ #line 772 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24356 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 639: + case 644: /* select_limit_value: ALL */ #line 774 "third_party/libpg_query/grammar/statements/select.y" - { + { /* LIMIT ALL is represented as a NULL constant */ - (yyval.node) = makeNullAConst((yylsp[(1) - (1)])); - ;} + (yyval.node) = makeNullAConst((yylsp[0])); + } +#line 24365 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 640: + case 645: /* select_limit_value: a_expr '%' */ #line 779 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeLimitPercent((yyvsp[(1) - (2)].node)); ;} + { (yyval.node) = makeLimitPercent((yyvsp[-1].node)); } +#line 24371 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 641: + case 646: /* select_limit_value: FCONST PERCENT */ #line 781 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeLimitPercent(makeFloatConst((yyvsp[(1) - (2)].str),(yylsp[(1) - (2)]))); ;} + { (yyval.node) = makeLimitPercent(makeFloatConst((yyvsp[-1].str),(yylsp[-1]))); } +#line 24377 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 642: + case 647: /* select_limit_value: ICONST PERCENT */ #line 783 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeLimitPercent(makeIntConst((yyvsp[(1) - (2)].ival),(yylsp[(1) - (2)]))); ;} + { (yyval.node) = makeLimitPercent(makeIntConst((yyvsp[-1].ival),(yylsp[-1]))); } +#line 24383 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 643: + case 648: /* select_offset_value: a_expr */ #line 787 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24389 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 644: + case 649: /* select_fetch_first_value: c_expr */ #line 807 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24395 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 645: + case 650: /* select_fetch_first_value: '+' I_or_F_const */ #line 809 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[0].node), (yylsp[-1])); } +#line 24401 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 646: + case 651: /* select_fetch_first_value: '-' I_or_F_const */ #line 811 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = doNegate((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + { (yyval.node) = doNegate((yyvsp[0].node), (yylsp[-1])); } +#line 24407 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 647: + case 652: /* I_or_F_const: Iconst */ #line 815 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeIntConst((yyvsp[(1) - (1)].ival),(yylsp[(1) - (1)])); ;} + { (yyval.node) = makeIntConst((yyvsp[0].ival),(yylsp[0])); } +#line 24413 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 648: + case 653: /* I_or_F_const: FCONST */ #line 816 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeFloatConst((yyvsp[(1) - (1)].str),(yylsp[(1) - (1)])); ;} + { (yyval.node) = makeFloatConst((yyvsp[0].str),(yylsp[0])); } +#line 24419 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 649: + case 654: /* row_or_rows: ROW */ #line 820 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = 0; ;} + { (yyval.ival) = 0; } +#line 24425 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 650: + case 655: /* row_or_rows: ROWS */ #line 821 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = 0; ;} + { (yyval.ival) = 0; } +#line 24431 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 651: + case 656: /* first_or_next: FIRST_P */ #line 824 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = 0; ;} + { (yyval.ival) = 0; } +#line 24437 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 652: + case 657: /* first_or_next: NEXT */ #line 825 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = 0; ;} + { (yyval.ival) = 0; } +#line 24443 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 653: + case 658: /* group_clause: GROUP_P BY group_by_list_opt_comma */ #line 850 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (3)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 24449 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 654: + case 659: /* group_clause: GROUP_P BY ALL */ #line 852 "third_party/libpg_query/grammar/statements/select.y" - { - PGNode *node = (PGNode *) makeGroupingSet(GROUPING_SET_ALL, NIL, (yylsp[(3) - (3)])); + { + PGNode *node = (PGNode *) makeGroupingSet(GROUPING_SET_ALL, NIL, (yylsp[0])); (yyval.list) = list_make1(node); - ;} + } +#line 24458 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 655: + case 660: /* group_clause: %empty */ #line 856 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 24464 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 656: + case 661: /* group_by_list: group_by_item */ #line 860 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 24470 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 657: + case 662: /* group_by_list: group_by_list ',' group_by_item */ #line 861 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list),(yyvsp[(3) - (3)].node)); ;} + { (yyval.list) = lappend((yyvsp[-2].list),(yyvsp[0].node)); } +#line 24476 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 658: + case 663: /* group_by_list_opt_comma: group_by_list */ #line 865 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 24482 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 659: + case 664: /* group_by_list_opt_comma: group_by_list ',' */ #line 866 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 24488 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 660: + case 665: /* group_by_item: a_expr */ #line 870 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24494 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 661: + case 666: /* group_by_item: empty_grouping_set */ #line 871 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24500 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 662: + case 667: /* group_by_item: cube_clause */ #line 872 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24506 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 663: + case 668: /* group_by_item: rollup_clause */ #line 873 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24512 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 664: + case 669: /* group_by_item: grouping_sets_clause */ #line 874 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24518 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 665: + case 670: /* empty_grouping_set: '(' ')' */ #line 879 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_EMPTY, NIL, (yylsp[(1) - (2)])); - ;} + { + (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_EMPTY, NIL, (yylsp[-1])); + } +#line 24526 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 666: + case 671: /* rollup_clause: ROLLUP '(' expr_list_opt_comma ')' */ #line 892 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_ROLLUP, (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} + { + (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_ROLLUP, (yyvsp[-1].list), (yylsp[-3])); + } +#line 24534 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 667: + case 672: /* cube_clause: CUBE '(' expr_list_opt_comma ')' */ #line 899 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_CUBE, (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} + { + (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_CUBE, (yyvsp[-1].list), (yylsp[-3])); + } +#line 24542 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 668: + case 673: /* grouping_sets_clause: GROUPING SETS '(' group_by_list_opt_comma ')' */ #line 906 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_SETS, (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); - ;} + { + (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_SETS, (yyvsp[-1].list), (yylsp[-4])); + } +#line 24550 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 669: + case 674: /* grouping_or_grouping_id: GROUPING */ #line 912 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 24556 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 670: + case 675: /* grouping_or_grouping_id: GROUPING_ID */ #line 913 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 24562 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 671: + case 676: /* having_clause: HAVING a_expr */ #line 917 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24568 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 672: + case 677: /* having_clause: %empty */ #line 918 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 24574 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 673: + case 678: /* qualify_clause: QUALIFY a_expr */ #line 922 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24580 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 674: + case 679: /* qualify_clause: %empty */ #line 923 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 24586 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 675: + case 680: /* for_locking_clause: for_locking_items */ #line 927 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 24592 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 676: + case 681: /* for_locking_clause: FOR READ_P ONLY */ #line 928 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 24598 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 677: + case 682: /* opt_for_locking_clause: for_locking_clause */ #line 932 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 24604 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 678: + case 683: /* opt_for_locking_clause: %empty */ #line 933 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 24610 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 679: + case 684: /* for_locking_items: for_locking_item */ #line 937 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 24616 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 680: + case 685: /* for_locking_items: for_locking_items for_locking_item */ #line 938 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + { (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].node)); } +#line 24622 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 681: + case 686: /* for_locking_item: for_locking_strength locked_rels_list opt_nowait_or_skip */ #line 943 "third_party/libpg_query/grammar/statements/select.y" - { + { PGLockingClause *n = makeNode(PGLockingClause); - n->lockedRels = (yyvsp[(2) - (3)].list); - n->strength = (yyvsp[(1) - (3)].lockstrength); - n->waitPolicy = (yyvsp[(3) - (3)].lockwaitpolicy); + n->lockedRels = (yyvsp[-1].list); + n->strength = (yyvsp[-2].lockstrength); + n->waitPolicy = (yyvsp[0].lockwaitpolicy); (yyval.node) = (PGNode *) n; - ;} + } +#line 24634 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 682: + case 687: /* for_locking_strength: FOR UPDATE */ #line 953 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockstrength) = LCS_FORUPDATE; ;} + { (yyval.lockstrength) = LCS_FORUPDATE; } +#line 24640 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 683: + case 688: /* for_locking_strength: FOR NO KEY UPDATE */ #line 954 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockstrength) = PG_LCS_FORNOKEYUPDATE; ;} + { (yyval.lockstrength) = PG_LCS_FORNOKEYUPDATE; } +#line 24646 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 684: + case 689: /* for_locking_strength: FOR SHARE */ #line 955 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockstrength) = PG_LCS_FORSHARE; ;} + { (yyval.lockstrength) = PG_LCS_FORSHARE; } +#line 24652 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 685: + case 690: /* for_locking_strength: FOR KEY SHARE */ #line 956 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockstrength) = PG_LCS_FORKEYSHARE; ;} + { (yyval.lockstrength) = PG_LCS_FORKEYSHARE; } +#line 24658 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 686: + case 691: /* locked_rels_list: OF qualified_name_list */ #line 960 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 24664 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 687: + case 692: /* locked_rels_list: %empty */ #line 961 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 24670 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 688: + case 693: /* opt_nowait_or_skip: NOWAIT */ #line 966 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockwaitpolicy) = LockWaitError; ;} + { (yyval.lockwaitpolicy) = LockWaitError; } +#line 24676 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 689: + case 694: /* opt_nowait_or_skip: SKIP LOCKED */ #line 967 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockwaitpolicy) = PGLockWaitSkip; ;} + { (yyval.lockwaitpolicy) = PGLockWaitSkip; } +#line 24682 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 690: + case 695: /* opt_nowait_or_skip: %empty */ #line 968 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockwaitpolicy) = PGLockWaitBlock; ;} + { (yyval.lockwaitpolicy) = PGLockWaitBlock; } +#line 24688 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 691: + case 696: /* values_clause: VALUES '(' expr_list_opt_comma ')' */ #line 978 "third_party/libpg_query/grammar/statements/select.y" - { + { PGSelectStmt *n = makeNode(PGSelectStmt); - n->valuesLists = list_make1((yyvsp[(3) - (4)].list)); + n->valuesLists = list_make1((yyvsp[-1].list)); (yyval.node) = (PGNode *) n; - ;} + } +#line 24698 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 692: + case 697: /* values_clause: values_clause ',' '(' expr_list_opt_comma ')' */ #line 984 "third_party/libpg_query/grammar/statements/select.y" - { - PGSelectStmt *n = (PGSelectStmt *) (yyvsp[(1) - (5)].node); - n->valuesLists = lappend(n->valuesLists, (yyvsp[(4) - (5)].list)); + { + PGSelectStmt *n = (PGSelectStmt *) (yyvsp[-4].node); + n->valuesLists = lappend(n->valuesLists, (yyvsp[-1].list)); (yyval.node) = (PGNode *) n; - ;} + } +#line 24708 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 693: + case 698: /* values_clause_opt_comma: values_clause */ #line 992 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 24714 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 694: + case 699: /* values_clause_opt_comma: values_clause ',' */ #line 993 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (2)].node); ;} + { (yyval.node) = (yyvsp[-1].node); } +#line 24720 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 695: + case 700: /* from_clause: FROM from_list_opt_comma */ #line 1006 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 24726 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 696: + case 701: /* from_clause: %empty */ #line 1007 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 24732 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 697: + case 702: /* from_list: table_ref */ #line 1011 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 24738 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 698: + case 703: /* from_list: from_list ',' table_ref */ #line 1012 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); } +#line 24744 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 699: + case 704: /* from_list_opt_comma: from_list */ #line 1016 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 24750 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 700: + case 705: /* from_list_opt_comma: from_list ',' */ #line 1017 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 24756 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 701: + case 706: /* table_ref: relation_expr opt_alias_clause opt_tablesample_clause */ #line 1024 "third_party/libpg_query/grammar/statements/select.y" - { - (yyvsp[(1) - (3)].range)->alias = (yyvsp[(2) - (3)].alias); - (yyvsp[(1) - (3)].range)->sample = (yyvsp[(3) - (3)].node); - (yyval.node) = (PGNode *) (yyvsp[(1) - (3)].range); - ;} + { + (yyvsp[-2].range)->alias = (yyvsp[-1].alias); + (yyvsp[-2].range)->sample = (yyvsp[0].node); + (yyval.node) = (PGNode *) (yyvsp[-2].range); + } +#line 24766 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 702: + case 707: /* table_ref: func_table func_alias_clause opt_tablesample_clause */ #line 1030 "third_party/libpg_query/grammar/statements/select.y" - { - PGRangeFunction *n = (PGRangeFunction *) (yyvsp[(1) - (3)].node); - n->alias = (PGAlias*) linitial((yyvsp[(2) - (3)].list)); - n->coldeflist = (PGList*) lsecond((yyvsp[(2) - (3)].list)); - n->sample = (yyvsp[(3) - (3)].node); + { + PGRangeFunction *n = (PGRangeFunction *) (yyvsp[-2].node); + n->alias = (PGAlias*) linitial((yyvsp[-1].list)); + n->coldeflist = (PGList*) lsecond((yyvsp[-1].list)); + n->sample = (yyvsp[0].node); (yyval.node) = (PGNode *) n; - ;} + } +#line 24778 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 703: + case 708: /* table_ref: values_clause_opt_comma alias_clause opt_tablesample_clause */ #line 1038 "third_party/libpg_query/grammar/statements/select.y" - { + { PGRangeSubselect *n = makeNode(PGRangeSubselect); n->lateral = false; - n->subquery = (yyvsp[(1) - (3)].node); - n->alias = (yyvsp[(2) - (3)].alias); - n->sample = (yyvsp[(3) - (3)].node); + n->subquery = (yyvsp[-2].node); + n->alias = (yyvsp[-1].alias); + n->sample = (yyvsp[0].node); (yyval.node) = (PGNode *) n; - ;} + } +#line 24791 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 704: + case 709: /* table_ref: LATERAL_P func_table func_alias_clause */ #line 1047 "third_party/libpg_query/grammar/statements/select.y" - { - PGRangeFunction *n = (PGRangeFunction *) (yyvsp[(2) - (3)].node); + { + PGRangeFunction *n = (PGRangeFunction *) (yyvsp[-1].node); n->lateral = true; - n->alias = (PGAlias*) linitial((yyvsp[(3) - (3)].list)); - n->coldeflist = (PGList*) lsecond((yyvsp[(3) - (3)].list)); + n->alias = (PGAlias*) linitial((yyvsp[0].list)); + n->coldeflist = (PGList*) lsecond((yyvsp[0].list)); (yyval.node) = (PGNode *) n; - ;} + } +#line 24803 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 705: + case 710: /* table_ref: select_with_parens opt_alias_clause opt_tablesample_clause */ #line 1055 "third_party/libpg_query/grammar/statements/select.y" - { + { PGRangeSubselect *n = makeNode(PGRangeSubselect); n->lateral = false; - n->subquery = (yyvsp[(1) - (3)].node); - n->alias = (yyvsp[(2) - (3)].alias); - n->sample = (yyvsp[(3) - (3)].node); + n->subquery = (yyvsp[-2].node); + n->alias = (yyvsp[-1].alias); + n->sample = (yyvsp[0].node); (yyval.node) = (PGNode *) n; - ;} + } +#line 24816 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 706: + case 711: /* table_ref: LATERAL_P select_with_parens opt_alias_clause */ #line 1064 "third_party/libpg_query/grammar/statements/select.y" - { + { PGRangeSubselect *n = makeNode(PGRangeSubselect); n->lateral = true; - n->subquery = (yyvsp[(2) - (3)].node); - n->alias = (yyvsp[(3) - (3)].alias); + n->subquery = (yyvsp[-1].node); + n->alias = (yyvsp[0].alias); n->sample = NULL; (yyval.node) = (PGNode *) n; - ;} + } +#line 24829 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 707: + case 712: /* table_ref: joined_table */ #line 1073 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].jexpr); - ;} + { + (yyval.node) = (PGNode *) (yyvsp[0].jexpr); + } +#line 24837 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 708: + case 713: /* table_ref: '(' joined_table ')' alias_clause */ #line 1077 "third_party/libpg_query/grammar/statements/select.y" - { - (yyvsp[(2) - (4)].jexpr)->alias = (yyvsp[(4) - (4)].alias); - (yyval.node) = (PGNode *) (yyvsp[(2) - (4)].jexpr); - ;} + { + (yyvsp[-2].jexpr)->alias = (yyvsp[0].alias); + (yyval.node) = (PGNode *) (yyvsp[-2].jexpr); + } +#line 24846 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 709: + case 714: /* table_ref: table_ref PIVOT '(' target_list_opt_comma FOR pivot_value_list opt_pivot_group_by ')' opt_alias_clause */ #line 1082 "third_party/libpg_query/grammar/statements/select.y" - { + { PGPivotExpr *n = makeNode(PGPivotExpr); - n->source = (yyvsp[(1) - (9)].node); - n->aggrs = (yyvsp[(4) - (9)].list); - n->pivots = (yyvsp[(6) - (9)].list); - n->groups = (yyvsp[(7) - (9)].list); - n->alias = (yyvsp[(9) - (9)].alias); - n->location = (yylsp[(2) - (9)]); + n->source = (yyvsp[-8].node); + n->aggrs = (yyvsp[-5].list); + n->pivots = (yyvsp[-3].list); + n->groups = (yyvsp[-2].list); + n->alias = (yyvsp[0].alias); + n->location = (yylsp[-7]); (yyval.node) = (PGNode *) n; - ;} + } +#line 24861 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 710: + case 715: /* table_ref: table_ref UNPIVOT opt_include_nulls '(' unpivot_header FOR unpivot_value_list ')' opt_alias_clause */ #line 1093 "third_party/libpg_query/grammar/statements/select.y" - { + { PGPivotExpr *n = makeNode(PGPivotExpr); - n->source = (yyvsp[(1) - (9)].node); - n->include_nulls = (yyvsp[(3) - (9)].boolean); - n->unpivots = (yyvsp[(5) - (9)].list); - n->pivots = (yyvsp[(7) - (9)].list); - n->alias = (yyvsp[(9) - (9)].alias); - n->location = (yylsp[(2) - (9)]); + n->source = (yyvsp[-8].node); + n->include_nulls = (yyvsp[-6].boolean); + n->unpivots = (yyvsp[-4].list); + n->pivots = (yyvsp[-2].list); + n->alias = (yyvsp[0].alias); + n->location = (yylsp[-7]); (yyval.node) = (PGNode *) n; - ;} + } +#line 24876 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 711: + case 716: /* opt_pivot_group_by: GROUP_P BY name_list_opt_comma */ #line 1106 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (3)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 24882 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 712: + case 717: /* opt_pivot_group_by: %empty */ #line 1107 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NULL; ;} + { (yyval.list) = NULL; } +#line 24888 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 713: + case 718: /* opt_include_nulls: INCLUDE_P NULLS_P */ #line 1110 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 24894 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 714: + case 719: /* opt_include_nulls: EXCLUDE NULLS_P */ #line 1111 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 24900 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 715: + case 720: /* opt_include_nulls: %empty */ #line 1112 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 24906 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 716: + case 721: /* single_pivot_value: b_expr IN_P '(' target_list_opt_comma ')' */ #line 1116 "third_party/libpg_query/grammar/statements/select.y" - { + { PGPivot *n = makeNode(PGPivot); - n->pivot_columns = list_make1((yyvsp[(1) - (5)].node)); - n->pivot_value = (yyvsp[(4) - (5)].list); + n->pivot_columns = list_make1((yyvsp[-4].node)); + n->pivot_value = (yyvsp[-1].list); (yyval.node) = (PGNode *) n; - ;} + } +#line 24917 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 717: + case 722: /* single_pivot_value: b_expr IN_P ColIdOrString */ #line 1124 "third_party/libpg_query/grammar/statements/select.y" - { + { PGPivot *n = makeNode(PGPivot); - n->pivot_columns = list_make1((yyvsp[(1) - (3)].node)); - n->pivot_enum = (yyvsp[(3) - (3)].str); + n->pivot_columns = list_make1((yyvsp[-2].node)); + n->pivot_enum = (yyvsp[0].str); (yyval.node) = (PGNode *) n; - ;} + } +#line 24928 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 719: + case 724: /* pivot_header: d_expr */ #line 1133 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 24934 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 720: + case 725: /* pivot_header: indirection_expr */ #line 1134 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 24940 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 721: + case 726: /* pivot_header: '(' c_expr_list_opt_comma ')' */ #line 1135 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 24946 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 722: + case 727: /* pivot_value: pivot_header IN_P '(' target_list_opt_comma ')' */ #line 1139 "third_party/libpg_query/grammar/statements/select.y" - { + { PGPivot *n = makeNode(PGPivot); - n->pivot_columns = (yyvsp[(1) - (5)].list); - n->pivot_value = (yyvsp[(4) - (5)].list); + n->pivot_columns = (yyvsp[-4].list); + n->pivot_value = (yyvsp[-1].list); (yyval.node) = (PGNode *) n; - ;} + } +#line 24957 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 723: + case 728: /* pivot_value: pivot_header IN_P ColIdOrString */ #line 1147 "third_party/libpg_query/grammar/statements/select.y" - { + { PGPivot *n = makeNode(PGPivot); - n->pivot_columns = (yyvsp[(1) - (3)].list); - n->pivot_enum = (yyvsp[(3) - (3)].str); + n->pivot_columns = (yyvsp[-2].list); + n->pivot_enum = (yyvsp[0].str); (yyval.node) = (PGNode *) n; - ;} + } +#line 24968 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 724: + case 729: /* pivot_value_list: pivot_value */ #line 1156 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} + { + (yyval.list) = list_make1((yyvsp[0].node)); + } +#line 24976 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 725: + case 730: /* pivot_value_list: pivot_value_list pivot_value */ #line 1160 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); - ;} + { + (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].node)); + } +#line 24984 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 726: + case 731: /* unpivot_header: ColIdOrString */ #line 1166 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + { (yyval.list) = list_make1(makeString((yyvsp[0].str))); } +#line 24990 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 727: + case 732: /* unpivot_header: '(' name_list_opt_comma ')' */ #line 1167 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 24996 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 728: + case 733: /* unpivot_value: unpivot_header IN_P '(' target_list_opt_comma ')' */ #line 1172 "third_party/libpg_query/grammar/statements/select.y" - { + { PGPivot *n = makeNode(PGPivot); - n->unpivot_columns = (yyvsp[(1) - (5)].list); - n->pivot_value = (yyvsp[(4) - (5)].list); + n->unpivot_columns = (yyvsp[-4].list); + n->pivot_value = (yyvsp[-1].list); (yyval.node) = (PGNode *) n; - ;} + } +#line 25007 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 729: + case 734: /* unpivot_value_list: unpivot_value */ #line 1181 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} + { + (yyval.list) = list_make1((yyvsp[0].node)); + } +#line 25015 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 730: + case 735: /* unpivot_value_list: unpivot_value_list unpivot_value */ #line 1185 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); - ;} + { + (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].node)); + } +#line 25023 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 731: + case 736: /* joined_table: '(' joined_table ')' */ #line 1210 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.jexpr) = (yyvsp[(2) - (3)].jexpr); - ;} + { + (yyval.jexpr) = (yyvsp[-1].jexpr); + } +#line 25031 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 732: + case 737: /* joined_table: table_ref CROSS JOIN table_ref */ #line 1214 "third_party/libpg_query/grammar/statements/select.y" - { + { /* CROSS JOIN is same as unqualified inner join */ PGJoinExpr *n = makeNode(PGJoinExpr); n->jointype = PG_JOIN_INNER; n->joinreftype = PG_JOIN_REGULAR; - n->larg = (yyvsp[(1) - (4)].node); - n->rarg = (yyvsp[(4) - (4)].node); + n->larg = (yyvsp[-3].node); + n->rarg = (yyvsp[0].node); n->usingClause = NIL; n->quals = NULL; - n->location = (yylsp[(2) - (4)]); + n->location = (yylsp[-2]); (yyval.jexpr) = n; - ;} + } +#line 25048 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 733: + case 738: /* joined_table: table_ref join_type JOIN table_ref join_qual */ #line 1227 "third_party/libpg_query/grammar/statements/select.y" - { + { PGJoinExpr *n = makeNode(PGJoinExpr); - n->jointype = (yyvsp[(2) - (5)].jtype); + n->jointype = (yyvsp[-3].jtype); n->joinreftype = PG_JOIN_REGULAR; - n->larg = (yyvsp[(1) - (5)].node); - n->rarg = (yyvsp[(4) - (5)].node); - if ((yyvsp[(5) - (5)].node) != NULL && IsA((yyvsp[(5) - (5)].node), PGList)) - n->usingClause = (PGList *) (yyvsp[(5) - (5)].node); /* USING clause */ + n->larg = (yyvsp[-4].node); + n->rarg = (yyvsp[-1].node); + if ((yyvsp[0].node) != NULL && IsA((yyvsp[0].node), PGList)) + n->usingClause = (PGList *) (yyvsp[0].node); /* USING clause */ else - n->quals = (yyvsp[(5) - (5)].node); /* ON clause */ - n->location = (yylsp[(2) - (5)]); + n->quals = (yyvsp[0].node); /* ON clause */ + n->location = (yylsp[-3]); (yyval.jexpr) = n; - ;} + } +#line 25066 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 734: + case 739: /* joined_table: table_ref JOIN table_ref join_qual */ #line 1241 "third_party/libpg_query/grammar/statements/select.y" - { + { /* letting join_type reduce to empty doesn't work */ PGJoinExpr *n = makeNode(PGJoinExpr); n->jointype = PG_JOIN_INNER; n->joinreftype = PG_JOIN_REGULAR; - n->larg = (yyvsp[(1) - (4)].node); - n->rarg = (yyvsp[(3) - (4)].node); - if ((yyvsp[(4) - (4)].node) != NULL && IsA((yyvsp[(4) - (4)].node), PGList)) - n->usingClause = (PGList *) (yyvsp[(4) - (4)].node); /* USING clause */ + n->larg = (yyvsp[-3].node); + n->rarg = (yyvsp[-1].node); + if ((yyvsp[0].node) != NULL && IsA((yyvsp[0].node), PGList)) + n->usingClause = (PGList *) (yyvsp[0].node); /* USING clause */ else - n->quals = (yyvsp[(4) - (4)].node); /* ON clause */ - n->location = (yylsp[(2) - (4)]); + n->quals = (yyvsp[0].node); /* ON clause */ + n->location = (yylsp[-2]); (yyval.jexpr) = n; - ;} + } +#line 25085 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 735: + case 740: /* joined_table: table_ref NATURAL join_type JOIN table_ref */ #line 1256 "third_party/libpg_query/grammar/statements/select.y" - { + { PGJoinExpr *n = makeNode(PGJoinExpr); - n->jointype = (yyvsp[(3) - (5)].jtype); + n->jointype = (yyvsp[-2].jtype); n->joinreftype = PG_JOIN_NATURAL; - n->larg = (yyvsp[(1) - (5)].node); - n->rarg = (yyvsp[(5) - (5)].node); + n->larg = (yyvsp[-4].node); + n->rarg = (yyvsp[0].node); n->usingClause = NIL; /* figure out which columns later... */ n->quals = NULL; /* fill later */ - n->location = (yylsp[(2) - (5)]); + n->location = (yylsp[-3]); (yyval.jexpr) = n; - ;} + } +#line 25101 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 736: + case 741: /* joined_table: table_ref NATURAL JOIN table_ref */ #line 1268 "third_party/libpg_query/grammar/statements/select.y" - { + { /* letting join_type reduce to empty doesn't work */ PGJoinExpr *n = makeNode(PGJoinExpr); n->jointype = PG_JOIN_INNER; n->joinreftype = PG_JOIN_NATURAL; - n->larg = (yyvsp[(1) - (4)].node); - n->rarg = (yyvsp[(4) - (4)].node); + n->larg = (yyvsp[-3].node); + n->rarg = (yyvsp[0].node); n->usingClause = NIL; /* figure out which columns later... */ n->quals = NULL; /* fill later */ - n->location = (yylsp[(2) - (4)]); + n->location = (yylsp[-2]); (yyval.jexpr) = n; - ;} + } +#line 25118 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 737: + case 742: /* joined_table: table_ref ASOF join_type JOIN table_ref join_qual */ #line 1281 "third_party/libpg_query/grammar/statements/select.y" - { + { PGJoinExpr *n = makeNode(PGJoinExpr); - n->jointype = (yyvsp[(3) - (6)].jtype); + n->jointype = (yyvsp[-3].jtype); n->joinreftype = PG_JOIN_ASOF; - n->larg = (yyvsp[(1) - (6)].node); - n->rarg = (yyvsp[(5) - (6)].node); - if ((yyvsp[(6) - (6)].node) != NULL && IsA((yyvsp[(6) - (6)].node), PGList)) - n->usingClause = (PGList *) (yyvsp[(6) - (6)].node); /* USING clause */ + n->larg = (yyvsp[-5].node); + n->rarg = (yyvsp[-1].node); + if ((yyvsp[0].node) != NULL && IsA((yyvsp[0].node), PGList)) + n->usingClause = (PGList *) (yyvsp[0].node); /* USING clause */ else - n->quals = (yyvsp[(6) - (6)].node); /* ON clause */ - n->location = (yylsp[(2) - (6)]); + n->quals = (yyvsp[0].node); /* ON clause */ + n->location = (yylsp[-4]); (yyval.jexpr) = n; - ;} + } +#line 25136 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 738: + case 743: /* joined_table: table_ref ASOF JOIN table_ref join_qual */ #line 1295 "third_party/libpg_query/grammar/statements/select.y" - { + { PGJoinExpr *n = makeNode(PGJoinExpr); n->jointype = PG_JOIN_INNER; n->joinreftype = PG_JOIN_ASOF; - n->larg = (yyvsp[(1) - (5)].node); - n->rarg = (yyvsp[(4) - (5)].node); - if ((yyvsp[(5) - (5)].node) != NULL && IsA((yyvsp[(5) - (5)].node), PGList)) - n->usingClause = (PGList *) (yyvsp[(5) - (5)].node); /* USING clause */ + n->larg = (yyvsp[-4].node); + n->rarg = (yyvsp[-1].node); + if ((yyvsp[0].node) != NULL && IsA((yyvsp[0].node), PGList)) + n->usingClause = (PGList *) (yyvsp[0].node); /* USING clause */ else - n->quals = (yyvsp[(5) - (5)].node); /* ON clause */ - n->location = (yylsp[(2) - (5)]); + n->quals = (yyvsp[0].node); /* ON clause */ + n->location = (yylsp[-3]); (yyval.jexpr) = n; - ;} + } +#line 25154 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 739: + case 744: /* joined_table: table_ref POSITIONAL JOIN table_ref */ #line 1309 "third_party/libpg_query/grammar/statements/select.y" - { + { /* POSITIONAL JOIN is a coordinated scan */ PGJoinExpr *n = makeNode(PGJoinExpr); n->jointype = PG_JOIN_POSITION; n->joinreftype = PG_JOIN_REGULAR; - n->larg = (yyvsp[(1) - (4)].node); - n->rarg = (yyvsp[(4) - (4)].node); + n->larg = (yyvsp[-3].node); + n->rarg = (yyvsp[0].node); n->usingClause = NIL; n->quals = NULL; - n->location = (yylsp[(2) - (4)]); + n->location = (yylsp[-2]); (yyval.jexpr) = n; - ;} + } +#line 25171 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 740: + case 745: /* joined_table: table_ref ANTI JOIN table_ref join_qual */ #line 1322 "third_party/libpg_query/grammar/statements/select.y" - { + { /* ANTI JOIN is a filter */ PGJoinExpr *n = makeNode(PGJoinExpr); n->jointype = PG_JOIN_ANTI; n->joinreftype = PG_JOIN_REGULAR; - n->larg = (yyvsp[(1) - (5)].node); - n->rarg = (yyvsp[(4) - (5)].node); - if ((yyvsp[(5) - (5)].node) != NULL && IsA((yyvsp[(5) - (5)].node), PGList)) - n->usingClause = (PGList *) (yyvsp[(5) - (5)].node); /* USING clause */ + n->larg = (yyvsp[-4].node); + n->rarg = (yyvsp[-1].node); + if ((yyvsp[0].node) != NULL && IsA((yyvsp[0].node), PGList)) + n->usingClause = (PGList *) (yyvsp[0].node); /* USING clause */ else - n->quals = (yyvsp[(5) - (5)].node); /* ON clause */ - n->location = (yylsp[(2) - (5)]); + n->quals = (yyvsp[0].node); /* ON clause */ + n->location = (yylsp[-3]); (yyval.jexpr) = n; - ;} + } +#line 25190 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 741: + case 746: /* joined_table: table_ref SEMI JOIN table_ref join_qual */ #line 1337 "third_party/libpg_query/grammar/statements/select.y" - { + { /* SEMI JOIN is also a filter */ PGJoinExpr *n = makeNode(PGJoinExpr); n->jointype = PG_JOIN_SEMI; n->joinreftype = PG_JOIN_REGULAR; - n->larg = (yyvsp[(1) - (5)].node); - n->rarg = (yyvsp[(4) - (5)].node); - if ((yyvsp[(5) - (5)].node) != NULL && IsA((yyvsp[(5) - (5)].node), PGList)) - n->usingClause = (PGList *) (yyvsp[(5) - (5)].node); /* USING clause */ + n->larg = (yyvsp[-4].node); + n->rarg = (yyvsp[-1].node); + if ((yyvsp[0].node) != NULL && IsA((yyvsp[0].node), PGList)) + n->usingClause = (PGList *) (yyvsp[0].node); /* USING clause */ else - n->quals = (yyvsp[(5) - (5)].node); /* ON clause */ - n->location = (yylsp[(2) - (5)]); - n->location = (yylsp[(2) - (5)]); + n->quals = (yyvsp[0].node); /* ON clause */ + n->location = (yylsp[-3]); + n->location = (yylsp[-3]); (yyval.jexpr) = n; - ;} + } +#line 25210 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 742: + case 747: /* alias_clause: AS ColIdOrString '(' name_list_opt_comma ')' */ #line 1356 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.alias) = makeNode(PGAlias); - (yyval.alias)->aliasname = (yyvsp[(2) - (5)].str); - (yyval.alias)->colnames = (yyvsp[(4) - (5)].list); - ;} + (yyval.alias)->aliasname = (yyvsp[-3].str); + (yyval.alias)->colnames = (yyvsp[-1].list); + } +#line 25220 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 743: + case 748: /* alias_clause: AS ColIdOrString */ #line 1362 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.alias) = makeNode(PGAlias); - (yyval.alias)->aliasname = (yyvsp[(2) - (2)].str); - ;} + (yyval.alias)->aliasname = (yyvsp[0].str); + } +#line 25229 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 744: + case 749: /* alias_clause: ColId '(' name_list_opt_comma ')' */ #line 1367 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.alias) = makeNode(PGAlias); - (yyval.alias)->aliasname = (yyvsp[(1) - (4)].str); - (yyval.alias)->colnames = (yyvsp[(3) - (4)].list); - ;} + (yyval.alias)->aliasname = (yyvsp[-3].str); + (yyval.alias)->colnames = (yyvsp[-1].list); + } +#line 25239 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 745: + case 750: /* alias_clause: ColId */ #line 1373 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.alias) = makeNode(PGAlias); - (yyval.alias)->aliasname = (yyvsp[(1) - (1)].str); - ;} + (yyval.alias)->aliasname = (yyvsp[0].str); + } +#line 25248 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 746: + case 751: /* opt_alias_clause: alias_clause */ #line 1379 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.alias) = (yyvsp[(1) - (1)].alias); ;} + { (yyval.alias) = (yyvsp[0].alias); } +#line 25254 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 747: + case 752: /* opt_alias_clause: %empty */ #line 1380 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.alias) = NULL; ;} + { (yyval.alias) = NULL; } +#line 25260 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 748: + case 753: /* func_alias_clause: alias_clause */ #line 1389 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make2((yyvsp[(1) - (1)].alias), NIL); - ;} + { + (yyval.list) = list_make2((yyvsp[0].alias), NIL); + } +#line 25268 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 749: + case 754: /* func_alias_clause: AS '(' TableFuncElementList ')' */ #line 1393 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make2(NULL, (yyvsp[(3) - (4)].list)); - ;} + { + (yyval.list) = list_make2(NULL, (yyvsp[-1].list)); + } +#line 25276 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 750: + case 755: /* func_alias_clause: AS ColIdOrString '(' TableFuncElementList ')' */ #line 1397 "third_party/libpg_query/grammar/statements/select.y" - { + { PGAlias *a = makeNode(PGAlias); - a->aliasname = (yyvsp[(2) - (5)].str); - (yyval.list) = list_make2(a, (yyvsp[(4) - (5)].list)); - ;} + a->aliasname = (yyvsp[-3].str); + (yyval.list) = list_make2(a, (yyvsp[-1].list)); + } +#line 25286 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 751: + case 756: /* func_alias_clause: ColId '(' TableFuncElementList ')' */ #line 1403 "third_party/libpg_query/grammar/statements/select.y" - { + { PGAlias *a = makeNode(PGAlias); - a->aliasname = (yyvsp[(1) - (4)].str); - (yyval.list) = list_make2(a, (yyvsp[(3) - (4)].list)); - ;} + a->aliasname = (yyvsp[-3].str); + (yyval.list) = list_make2(a, (yyvsp[-1].list)); + } +#line 25296 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 752: + case 757: /* func_alias_clause: %empty */ #line 1409 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.list) = list_make2(NULL, NIL); - ;} + } +#line 25304 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 753: + case 758: /* join_type: FULL join_outer */ #line 1414 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.jtype) = PG_JOIN_FULL; ;} + { (yyval.jtype) = PG_JOIN_FULL; } +#line 25310 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 754: + case 759: /* join_type: LEFT join_outer */ #line 1415 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.jtype) = PG_JOIN_LEFT; ;} + { (yyval.jtype) = PG_JOIN_LEFT; } +#line 25316 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 755: + case 760: /* join_type: RIGHT join_outer */ #line 1416 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.jtype) = PG_JOIN_RIGHT; ;} + { (yyval.jtype) = PG_JOIN_RIGHT; } +#line 25322 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 756: + case 761: /* join_type: SEMI */ #line 1417 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.jtype) = PG_JOIN_SEMI; ;} + { (yyval.jtype) = PG_JOIN_SEMI; } +#line 25328 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 757: + case 762: /* join_type: ANTI */ #line 1418 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.jtype) = PG_JOIN_ANTI; ;} + { (yyval.jtype) = PG_JOIN_ANTI; } +#line 25334 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 758: + case 763: /* join_type: INNER_P */ #line 1419 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.jtype) = PG_JOIN_INNER; ;} + { (yyval.jtype) = PG_JOIN_INNER; } +#line 25340 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 759: + case 764: /* join_outer: OUTER_P */ #line 1423 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 25346 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 760: + case 765: /* join_outer: %empty */ #line 1424 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 25352 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 761: + case 766: /* join_qual: USING '(' name_list_opt_comma ')' */ #line 1436 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) (yyvsp[(3) - (4)].list); ;} + { (yyval.node) = (PGNode *) (yyvsp[-1].list); } +#line 25358 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 762: + case 767: /* join_qual: ON a_expr */ #line 1437 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 25364 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 763: + case 768: /* relation_expr: qualified_name */ #line 1443 "third_party/libpg_query/grammar/statements/select.y" - { + { /* inheritance query, implicitly */ - (yyval.range) = (yyvsp[(1) - (1)].range); + (yyval.range) = (yyvsp[0].range); (yyval.range)->inh = true; (yyval.range)->alias = NULL; - ;} + } +#line 25375 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 764: + case 769: /* relation_expr: qualified_name '*' */ #line 1450 "third_party/libpg_query/grammar/statements/select.y" - { + { /* inheritance query, explicitly */ - (yyval.range) = (yyvsp[(1) - (2)].range); + (yyval.range) = (yyvsp[-1].range); (yyval.range)->inh = true; (yyval.range)->alias = NULL; - ;} + } +#line 25386 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 765: + case 770: /* relation_expr: ONLY qualified_name */ #line 1457 "third_party/libpg_query/grammar/statements/select.y" - { + { /* no inheritance */ - (yyval.range) = (yyvsp[(2) - (2)].range); + (yyval.range) = (yyvsp[0].range); (yyval.range)->inh = false; (yyval.range)->alias = NULL; - ;} + } +#line 25397 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 766: + case 771: /* relation_expr: ONLY '(' qualified_name ')' */ #line 1464 "third_party/libpg_query/grammar/statements/select.y" - { + { /* no inheritance, SQL99-style syntax */ - (yyval.range) = (yyvsp[(3) - (4)].range); + (yyval.range) = (yyvsp[-1].range); (yyval.range)->inh = false; (yyval.range)->alias = NULL; - ;} + } +#line 25408 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 767: + case 772: /* func_table: func_expr_windowless opt_ordinality */ #line 1496 "third_party/libpg_query/grammar/statements/select.y" - { + { PGRangeFunction *n = makeNode(PGRangeFunction); n->lateral = false; - n->ordinality = (yyvsp[(2) - (2)].boolean); + n->ordinality = (yyvsp[0].boolean); n->is_rowsfrom = false; - n->functions = list_make1(list_make2((yyvsp[(1) - (2)].node), NIL)); + n->functions = list_make1(list_make2((yyvsp[-1].node), NIL)); n->sample = NULL; /* alias and coldeflist are set by table_ref production */ (yyval.node) = (PGNode *) n; - ;} + } +#line 25423 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 768: + case 773: /* func_table: ROWS FROM '(' rowsfrom_list ')' opt_ordinality */ #line 1507 "third_party/libpg_query/grammar/statements/select.y" - { + { PGRangeFunction *n = makeNode(PGRangeFunction); n->lateral = false; - n->ordinality = (yyvsp[(6) - (6)].boolean); + n->ordinality = (yyvsp[0].boolean); n->is_rowsfrom = true; - n->functions = (yyvsp[(4) - (6)].list); + n->functions = (yyvsp[-2].list); n->sample = NULL; /* alias and coldeflist are set by table_ref production */ (yyval.node) = (PGNode *) n; - ;} + } +#line 25438 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 769: + case 774: /* rowsfrom_item: func_expr_windowless opt_col_def_list */ #line 1520 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].list)); ;} + { (yyval.list) = list_make2((yyvsp[-1].node), (yyvsp[0].list)); } +#line 25444 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 770: + case 775: /* rowsfrom_list: rowsfrom_item */ #line 1524 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].list)); ;} + { (yyval.list) = list_make1((yyvsp[0].list)); } +#line 25450 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 771: + case 776: /* rowsfrom_list: rowsfrom_list ',' rowsfrom_item */ #line 1525 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].list)); } +#line 25456 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 772: + case 777: /* opt_col_def_list: AS '(' TableFuncElementList ')' */ #line 1528 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 25462 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 773: + case 778: /* opt_col_def_list: %empty */ #line 1529 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 25468 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 774: + case 779: /* opt_ordinality: WITH_LA ORDINALITY */ #line 1532 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 25474 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 775: + case 780: /* opt_ordinality: %empty */ #line 1533 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 25480 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 776: + case 781: /* where_clause: WHERE a_expr */ #line 1538 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 25486 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 777: + case 782: /* where_clause: %empty */ #line 1539 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 25492 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 778: + case 783: /* TableFuncElementList: TableFuncElement */ #line 1545 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} + { + (yyval.list) = list_make1((yyvsp[0].node)); + } +#line 25500 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 779: + case 784: /* TableFuncElementList: TableFuncElementList ',' TableFuncElement */ #line 1549 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} + { + (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); + } +#line 25508 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 780: + case 785: /* TableFuncElement: ColIdOrString Typename opt_collate_clause */ #line 1555 "third_party/libpg_query/grammar/statements/select.y" - { + { PGColumnDef *n = makeNode(PGColumnDef); - n->colname = (yyvsp[(1) - (3)].str); - n->typeName = (yyvsp[(2) - (3)].typnam); + n->colname = (yyvsp[-2].str); + n->typeName = (yyvsp[-1].typnam); n->inhcount = 0; n->is_local = true; n->is_not_null = false; @@ -25719,416 +25520,470 @@ YYLTYPE yylloc; n->storage = 0; n->raw_default = NULL; n->cooked_default = NULL; - n->collClause = (PGCollateClause *) (yyvsp[(3) - (3)].node); + n->collClause = (PGCollateClause *) (yyvsp[0].node); n->collOid = InvalidOid; n->constraints = NIL; - n->location = (yylsp[(1) - (3)]); + n->location = (yylsp[-2]); (yyval.node) = (PGNode *)n; - ;} + } +#line 25530 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 781: + case 786: /* opt_collate_clause: COLLATE any_name */ #line 1576 "third_party/libpg_query/grammar/statements/select.y" - { + { PGCollateClause *n = makeNode(PGCollateClause); n->arg = NULL; - n->collname = (yyvsp[(2) - (2)].list); - n->location = (yylsp[(1) - (2)]); + n->collname = (yyvsp[0].list); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *) n; - ;} + } +#line 25542 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 782: + case 787: /* opt_collate_clause: %empty */ #line 1583 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 25548 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 783: + case 788: /* colid_type_list: ColId Typename */ #line 1596 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(list_make2(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].typnam))); - ;} + { + (yyval.list) = list_make1(list_make2(makeString((yyvsp[-1].str)), (yyvsp[0].typnam))); + } +#line 25556 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 784: + case 789: /* colid_type_list: colid_type_list ',' ColId Typename */ #line 1599 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (4)].list), list_make2(makeString((yyvsp[(3) - (4)].str)), (yyvsp[(4) - (4)].typnam))); - ;} + { + (yyval.list) = lappend((yyvsp[-3].list), list_make2(makeString((yyvsp[-1].str)), (yyvsp[0].typnam))); + } +#line 25564 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 787: + case 792: /* opt_Typename: Typename */ #line 1606 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 25570 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 788: + case 793: /* opt_Typename: %empty */ #line 1607 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = NULL; ;} + { (yyval.typnam) = NULL; } +#line 25576 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 789: + case 794: /* Typename: SimpleTypename opt_array_bounds */ #line 1610 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (2)].typnam); - (yyval.typnam)->arrayBounds = (yyvsp[(2) - (2)].list); - ;} + { + (yyval.typnam) = (yyvsp[-1].typnam); + (yyval.typnam)->arrayBounds = (yyvsp[0].list); + } +#line 25585 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 790: + case 795: /* Typename: SETOF SimpleTypename opt_array_bounds */ #line 1615 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(2) - (3)].typnam); - (yyval.typnam)->arrayBounds = (yyvsp[(3) - (3)].list); + { + (yyval.typnam) = (yyvsp[-1].typnam); + (yyval.typnam)->arrayBounds = (yyvsp[0].list); (yyval.typnam)->setof = true; - ;} + } +#line 25595 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 791: + case 796: /* Typename: SimpleTypename ARRAY '[' Iconst ']' */ #line 1622 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (5)].typnam); - (yyval.typnam)->arrayBounds = list_make1(makeInteger((yyvsp[(4) - (5)].ival))); - ;} + { + (yyval.typnam) = (yyvsp[-4].typnam); + (yyval.typnam)->arrayBounds = list_make1(makeInteger((yyvsp[-1].ival))); + } +#line 25604 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 792: + case 797: /* Typename: SETOF SimpleTypename ARRAY '[' Iconst ']' */ #line 1627 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(2) - (6)].typnam); - (yyval.typnam)->arrayBounds = list_make1(makeInteger((yyvsp[(5) - (6)].ival))); + { + (yyval.typnam) = (yyvsp[-4].typnam); + (yyval.typnam)->arrayBounds = list_make1(makeInteger((yyvsp[-1].ival))); (yyval.typnam)->setof = true; - ;} + } +#line 25614 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 793: + case 798: /* Typename: SimpleTypename ARRAY */ #line 1633 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (2)].typnam); + { + (yyval.typnam) = (yyvsp[-1].typnam); (yyval.typnam)->arrayBounds = list_make1(makeInteger(-1)); - ;} + } +#line 25623 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 794: + case 799: /* Typename: SETOF SimpleTypename ARRAY */ #line 1638 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(2) - (3)].typnam); + { + (yyval.typnam) = (yyvsp[-1].typnam); (yyval.typnam)->arrayBounds = list_make1(makeInteger(-1)); (yyval.typnam)->setof = true; - ;} + } +#line 25633 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 795: + case 800: /* Typename: qualified_typename */ #line 1644 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = makeTypeNameFromNameList((yyvsp[(1) - (1)].list)); - ;} + { + (yyval.typnam) = makeTypeNameFromNameList((yyvsp[0].list)); + } +#line 25641 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 796: + case 801: /* Typename: RowOrStruct '(' colid_type_list ')' opt_array_bounds */ #line 1648 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("struct"); - (yyval.typnam)->arrayBounds = (yyvsp[(5) - (5)].list); - (yyval.typnam)->typmods = (yyvsp[(3) - (5)].list); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} + (yyval.typnam)->arrayBounds = (yyvsp[0].list); + (yyval.typnam)->typmods = (yyvsp[-2].list); + (yyval.typnam)->location = (yylsp[-4]); + } +#line 25652 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 797: + case 802: /* Typename: MAP '(' type_list ')' opt_array_bounds */ #line 1655 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("map"); - (yyval.typnam)->arrayBounds = (yyvsp[(5) - (5)].list); - (yyval.typnam)->typmods = (yyvsp[(3) - (5)].list); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} + (yyval.typnam)->arrayBounds = (yyvsp[0].list); + (yyval.typnam)->typmods = (yyvsp[-2].list); + (yyval.typnam)->location = (yylsp[-4]); + } +#line 25663 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 798: + case 803: /* Typename: UNION '(' colid_type_list ')' opt_array_bounds */ #line 1662 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("union"); - (yyval.typnam)->arrayBounds = (yyvsp[(5) - (5)].list); - (yyval.typnam)->typmods = (yyvsp[(3) - (5)].list); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} + (yyval.typnam)->arrayBounds = (yyvsp[0].list); + (yyval.typnam)->typmods = (yyvsp[-2].list); + (yyval.typnam)->location = (yylsp[-4]); + } +#line 25674 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 799: + case 804: /* qualified_typename: IDENT '.' IDENT */ #line 1671 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2(makeString((yyvsp[(1) - (3)].str)), makeString((yyvsp[(3) - (3)].str))); ;} + { (yyval.list) = list_make2(makeString((yyvsp[-2].str)), makeString((yyvsp[0].str))); } +#line 25680 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 800: + case 805: /* qualified_typename: qualified_typename '.' IDENT */ #line 1672 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeString((yyvsp[(3) - (3)].str))); ;} + { (yyval.list) = lappend((yyvsp[-2].list), makeString((yyvsp[0].str))); } +#line 25686 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 801: + case 806: /* opt_array_bounds: opt_array_bounds '[' ']' */ #line 1677 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeInteger(-1)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), makeInteger(-1)); } +#line 25692 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 802: + case 807: /* opt_array_bounds: opt_array_bounds '[' Iconst ']' */ #line 1679 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (4)].list), makeInteger((yyvsp[(3) - (4)].ival))); ;} + { (yyval.list) = lappend((yyvsp[-3].list), makeInteger((yyvsp[-1].ival))); } +#line 25698 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 803: + case 808: /* opt_array_bounds: %empty */ #line 1681 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 25704 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 804: + case 809: /* SimpleTypename: GenericType */ #line 1685 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 25710 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 805: + case 810: /* SimpleTypename: Numeric */ #line 1686 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 25716 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 806: + case 811: /* SimpleTypename: Bit */ #line 1687 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 25722 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 807: + case 812: /* SimpleTypename: Character */ #line 1688 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 25728 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 808: + case 813: /* SimpleTypename: ConstDatetime */ #line 1689 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 25734 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 809: + case 814: /* SimpleTypename: ConstInterval opt_interval */ #line 1691 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (2)].typnam); - (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); - ;} + { + (yyval.typnam) = (yyvsp[-1].typnam); + (yyval.typnam)->typmods = (yyvsp[0].list); + } +#line 25743 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 810: + case 815: /* SimpleTypename: ConstInterval '(' Iconst ')' */ #line 1696 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (4)].typnam); + { + (yyval.typnam) = (yyvsp[-3].typnam); (yyval.typnam)->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1), - makeIntConst((yyvsp[(3) - (4)].ival), (yylsp[(3) - (4)]))); - ;} + makeIntConst((yyvsp[-1].ival), (yylsp[-1]))); + } +#line 25753 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 811: + case 816: /* ConstTypename: Numeric */ #line 1715 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 25759 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 812: + case 817: /* ConstTypename: ConstBit */ #line 1716 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 25765 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 813: + case 818: /* ConstTypename: ConstCharacter */ #line 1717 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 25771 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 814: + case 819: /* ConstTypename: ConstDatetime */ #line 1718 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + { (yyval.typnam) = (yyvsp[0].typnam); } +#line 25777 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 815: + case 820: /* GenericType: type_name_token opt_type_modifiers */ #line 1730 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = makeTypeName((yyvsp[(1) - (2)].str)); - (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} + { + (yyval.typnam) = makeTypeName((yyvsp[-1].str)); + (yyval.typnam)->typmods = (yyvsp[0].list); + (yyval.typnam)->location = (yylsp[-1]); + } +#line 25787 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 816: + case 821: /* opt_type_modifiers: '(' opt_expr_list_opt_comma ')' */ #line 1743 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 25793 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 817: + case 822: /* opt_type_modifiers: %empty */ #line 1744 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 25799 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 818: + case 823: /* Numeric: INT_P */ #line 1751 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("int4"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} + (yyval.typnam)->location = (yylsp[0]); + } +#line 25808 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 819: + case 824: /* Numeric: INTEGER */ #line 1756 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("int4"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} + (yyval.typnam)->location = (yylsp[0]); + } +#line 25817 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 820: + case 825: /* Numeric: SMALLINT */ #line 1761 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("int2"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} + (yyval.typnam)->location = (yylsp[0]); + } +#line 25826 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 821: + case 826: /* Numeric: BIGINT */ #line 1766 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("int8"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} + (yyval.typnam)->location = (yylsp[0]); + } +#line 25835 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 822: + case 827: /* Numeric: REAL */ #line 1771 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("float4"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} + (yyval.typnam)->location = (yylsp[0]); + } +#line 25844 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 823: + case 828: /* Numeric: FLOAT_P opt_float */ #line 1776 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(2) - (2)].typnam); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} + { + (yyval.typnam) = (yyvsp[0].typnam); + (yyval.typnam)->location = (yylsp[-1]); + } +#line 25853 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 824: + case 829: /* Numeric: DOUBLE_P PRECISION */ #line 1781 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("float8"); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} + (yyval.typnam)->location = (yylsp[-1]); + } +#line 25862 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 825: + case 830: /* Numeric: DECIMAL_P opt_type_modifiers */ #line 1786 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("numeric"); - (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} + (yyval.typnam)->typmods = (yyvsp[0].list); + (yyval.typnam)->location = (yylsp[-1]); + } +#line 25872 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 826: + case 831: /* Numeric: DEC opt_type_modifiers */ #line 1792 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("numeric"); - (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} + (yyval.typnam)->typmods = (yyvsp[0].list); + (yyval.typnam)->location = (yylsp[-1]); + } +#line 25882 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 827: + case 832: /* Numeric: NUMERIC opt_type_modifiers */ #line 1798 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("numeric"); - (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} + (yyval.typnam)->typmods = (yyvsp[0].list); + (yyval.typnam)->location = (yylsp[-1]); + } +#line 25892 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 828: + case 833: /* Numeric: BOOLEAN_P */ #line 1804 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("bool"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} + (yyval.typnam)->location = (yylsp[0]); + } +#line 25901 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 829: + case 834: /* opt_float: '(' Iconst ')' */ #line 1811 "third_party/libpg_query/grammar/statements/select.y" - { + { /* * Check FLOAT() precision limits assuming IEEE floating * types - thomas 1997-09-18 */ - if ((yyvsp[(2) - (3)].ival) < 1) + if ((yyvsp[-1].ival) < 1) ereport(ERROR, (errcode(PG_ERRCODE_INVALID_PARAMETER_VALUE), errmsg("precision for type float must be at least 1 bit"), - parser_errposition((yylsp[(2) - (3)])))); - else if ((yyvsp[(2) - (3)].ival) <= 24) + parser_errposition((yylsp[-1])))); + else if ((yyvsp[-1].ival) <= 24) (yyval.typnam) = SystemTypeName("float4"); - else if ((yyvsp[(2) - (3)].ival) <= 53) + else if ((yyvsp[-1].ival) <= 53) (yyval.typnam) = SystemTypeName("float8"); else ereport(ERROR, (errcode(PG_ERRCODE_INVALID_PARAMETER_VALUE), errmsg("precision for type float must be less than 54 bits"), - parser_errposition((yylsp[(2) - (3)])))); - ;} + parser_errposition((yylsp[-1])))); + } +#line 25926 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 830: + case 835: /* opt_float: %empty */ #line 1832 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("float4"); - ;} + } +#line 25934 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 831: + case 836: /* Bit: BitWithLength */ #line 1842 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} + { + (yyval.typnam) = (yyvsp[0].typnam); + } +#line 25942 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 832: + case 837: /* Bit: BitWithoutLength */ #line 1846 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} + { + (yyval.typnam) = (yyvsp[0].typnam); + } +#line 25950 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 833: + case 838: /* ConstBit: BitWithLength */ #line 1854 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} + { + (yyval.typnam) = (yyvsp[0].typnam); + } +#line 25958 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 834: + case 839: /* ConstBit: BitWithoutLength */ #line 1858 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); + { + (yyval.typnam) = (yyvsp[0].typnam); (yyval.typnam)->typmods = NIL; - ;} + } +#line 25967 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 835: + case 840: /* BitWithLength: BIT opt_varying '(' expr_list_opt_comma ')' */ #line 1866 "third_party/libpg_query/grammar/statements/select.y" - { + { const char *typname; - typname = (yyvsp[(2) - (5)].boolean) ? "varbit" : "bit"; + typname = (yyvsp[-3].boolean) ? "varbit" : "bit"; (yyval.typnam) = SystemTypeName(typname); - (yyval.typnam)->typmods = (yyvsp[(4) - (5)].list); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} + (yyval.typnam)->typmods = (yyvsp[-1].list); + (yyval.typnam)->location = (yylsp[-4]); + } +#line 25980 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 836: + case 841: /* BitWithoutLength: BIT opt_varying */ #line 1878 "third_party/libpg_query/grammar/statements/select.y" - { + { /* bit defaults to bit(1), varbit to no limit */ - if ((yyvsp[(2) - (2)].boolean)) + if ((yyvsp[0].boolean)) { (yyval.typnam) = SystemTypeName("varbit"); } @@ -26137,873 +25992,988 @@ YYLTYPE yylloc; (yyval.typnam) = SystemTypeName("bit"); (yyval.typnam)->typmods = list_make1(makeIntConst(1, -1)); } - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} + (yyval.typnam)->location = (yylsp[-1]); + } +#line 25998 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 837: + case 842: /* Character: CharacterWithLength */ #line 1899 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} + { + (yyval.typnam) = (yyvsp[0].typnam); + } +#line 26006 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 838: + case 843: /* Character: CharacterWithoutLength */ #line 1903 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} + { + (yyval.typnam) = (yyvsp[0].typnam); + } +#line 26014 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 839: + case 844: /* ConstCharacter: CharacterWithLength */ #line 1909 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} + { + (yyval.typnam) = (yyvsp[0].typnam); + } +#line 26022 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 840: + case 845: /* ConstCharacter: CharacterWithoutLength */ #line 1913 "third_party/libpg_query/grammar/statements/select.y" - { + { /* Length was not specified so allow to be unrestricted. * This handles problems with fixed-length (bpchar) strings * which in column definitions must default to a length * of one, but should not be constrained if the length * was not specified. */ - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); + (yyval.typnam) = (yyvsp[0].typnam); (yyval.typnam)->typmods = NIL; - ;} + } +#line 26037 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 841: + case 846: /* CharacterWithLength: character '(' Iconst ')' */ #line 1926 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName((yyvsp[(1) - (4)].conststr)); - (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[(3) - (4)].ival), (yylsp[(3) - (4)]))); - (yyval.typnam)->location = (yylsp[(1) - (4)]); - ;} + { + (yyval.typnam) = SystemTypeName((yyvsp[-3].conststr)); + (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[-1].ival), (yylsp[-1]))); + (yyval.typnam)->location = (yylsp[-3]); + } +#line 26047 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 842: + case 847: /* CharacterWithoutLength: character */ #line 1934 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName((yyvsp[(1) - (1)].conststr)); + { + (yyval.typnam) = SystemTypeName((yyvsp[0].conststr)); /* char defaults to char(1), varchar to no limit */ - if (strcmp((yyvsp[(1) - (1)].conststr), "bpchar") == 0) + if (strcmp((yyvsp[0].conststr), "bpchar") == 0) (yyval.typnam)->typmods = list_make1(makeIntConst(1, -1)); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} + (yyval.typnam)->location = (yylsp[0]); + } +#line 26059 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 843: + case 848: /* character: CHARACTER opt_varying */ #line 1944 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = (yyvsp[(2) - (2)].boolean) ? "varchar": "bpchar"; ;} + { (yyval.conststr) = (yyvsp[0].boolean) ? "varchar": "bpchar"; } +#line 26065 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 844: + case 849: /* character: CHAR_P opt_varying */ #line 1946 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = (yyvsp[(2) - (2)].boolean) ? "varchar": "bpchar"; ;} + { (yyval.conststr) = (yyvsp[0].boolean) ? "varchar": "bpchar"; } +#line 26071 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 845: + case 850: /* character: VARCHAR */ #line 1948 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "varchar"; ;} + { (yyval.conststr) = "varchar"; } +#line 26077 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 846: + case 851: /* character: NATIONAL CHARACTER opt_varying */ #line 1950 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = (yyvsp[(3) - (3)].boolean) ? "varchar": "bpchar"; ;} + { (yyval.conststr) = (yyvsp[0].boolean) ? "varchar": "bpchar"; } +#line 26083 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 847: + case 852: /* character: NATIONAL CHAR_P opt_varying */ #line 1952 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = (yyvsp[(3) - (3)].boolean) ? "varchar": "bpchar"; ;} + { (yyval.conststr) = (yyvsp[0].boolean) ? "varchar": "bpchar"; } +#line 26089 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 848: + case 853: /* character: NCHAR opt_varying */ #line 1954 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = (yyvsp[(2) - (2)].boolean) ? "varchar": "bpchar"; ;} + { (yyval.conststr) = (yyvsp[0].boolean) ? "varchar": "bpchar"; } +#line 26095 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 849: + case 854: /* opt_varying: VARYING */ #line 1958 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 26101 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 850: + case 855: /* opt_varying: %empty */ #line 1959 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 26107 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 851: + case 856: /* ConstDatetime: TIMESTAMP '(' Iconst ')' opt_timezone */ #line 1967 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(5) - (5)].boolean)) + { + if ((yyvsp[0].boolean)) (yyval.typnam) = SystemTypeName("timestamptz"); else (yyval.typnam) = SystemTypeName("timestamp"); - (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[(3) - (5)].ival), (yylsp[(3) - (5)]))); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} + (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[-2].ival), (yylsp[-2]))); + (yyval.typnam)->location = (yylsp[-4]); + } +#line 26120 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 852: + case 857: /* ConstDatetime: TIMESTAMP opt_timezone */ #line 1976 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(2) - (2)].boolean)) + { + if ((yyvsp[0].boolean)) (yyval.typnam) = SystemTypeName("timestamptz"); else (yyval.typnam) = SystemTypeName("timestamp"); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} + (yyval.typnam)->location = (yylsp[-1]); + } +#line 26132 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 853: + case 858: /* ConstDatetime: TIME '(' Iconst ')' opt_timezone */ #line 1984 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(5) - (5)].boolean)) + { + if ((yyvsp[0].boolean)) (yyval.typnam) = SystemTypeName("timetz"); else (yyval.typnam) = SystemTypeName("time"); - (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[(3) - (5)].ival), (yylsp[(3) - (5)]))); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} + (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[-2].ival), (yylsp[-2]))); + (yyval.typnam)->location = (yylsp[-4]); + } +#line 26145 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 854: + case 859: /* ConstDatetime: TIME opt_timezone */ #line 1993 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(2) - (2)].boolean)) + { + if ((yyvsp[0].boolean)) (yyval.typnam) = SystemTypeName("timetz"); else (yyval.typnam) = SystemTypeName("time"); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} + (yyval.typnam)->location = (yylsp[-1]); + } +#line 26157 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 855: + case 860: /* ConstInterval: INTERVAL */ #line 2004 "third_party/libpg_query/grammar/statements/select.y" - { + { (yyval.typnam) = SystemTypeName("interval"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} + (yyval.typnam)->location = (yylsp[0]); + } +#line 26166 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 856: + case 861: /* opt_timezone: WITH_LA TIME ZONE */ #line 2011 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 26172 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 857: + case 862: /* opt_timezone: WITHOUT TIME ZONE */ #line 2012 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 26178 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 858: + case 863: /* opt_timezone: %empty */ #line 2013 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 26184 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 883: -#line 2054 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(YEAR), (yylsp[(1) - (1)]))); ;} + case 890: /* opt_interval: year_keyword */ +#line 2057 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(YEAR), (yylsp[0]))); } +#line 26190 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 884: -#line 2056 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MONTH), (yylsp[(1) - (1)]))); ;} + case 891: /* opt_interval: month_keyword */ +#line 2059 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MONTH), (yylsp[0]))); } +#line 26196 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 885: -#line 2058 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY), (yylsp[(1) - (1)]))); ;} + case 892: /* opt_interval: day_keyword */ +#line 2061 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY), (yylsp[0]))); } +#line 26202 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 886: -#line 2060 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(HOUR), (yylsp[(1) - (1)]))); ;} + case 893: /* opt_interval: hour_keyword */ +#line 2063 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(HOUR), (yylsp[0]))); } +#line 26208 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 887: -#line 2062 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MINUTE), (yylsp[(1) - (1)]))); ;} + case 894: /* opt_interval: minute_keyword */ +#line 2065 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MINUTE), (yylsp[0]))); } +#line 26214 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 888: -#line 2064 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(SECOND), (yylsp[(1) - (1)]))); ;} + case 895: /* opt_interval: second_keyword */ +#line 2067 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(SECOND), (yylsp[0]))); } +#line 26220 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 889: -#line 2066 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MILLISECOND), (yylsp[(1) - (1)]))); ;} + case 896: /* opt_interval: millisecond_keyword */ +#line 2069 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MILLISECOND), (yylsp[0]))); } +#line 26226 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 890: -#line 2068 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MICROSECOND), (yylsp[(1) - (1)]))); ;} + case 897: /* opt_interval: microsecond_keyword */ +#line 2071 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MICROSECOND), (yylsp[0]))); } +#line 26232 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 891: -#line 2070 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(WEEK), (yylsp[(1) - (1)]))); ;} + case 898: /* opt_interval: week_keyword */ +#line 2073 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(WEEK), (yylsp[0]))); } +#line 26238 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 892: -#line 2072 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DECADE), (yylsp[(1) - (1)]))); ;} + case 899: /* opt_interval: quarter_keyword */ +#line 2075 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(QUARTER), (yylsp[0]))); } +#line 26244 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 893: -#line 2074 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(CENTURY), (yylsp[(1) - (1)]))); ;} + case 900: /* opt_interval: decade_keyword */ +#line 2077 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DECADE), (yylsp[0]))); } +#line 26250 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 894: -#line 2076 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MILLENNIUM), (yylsp[(1) - (1)]))); ;} + case 901: /* opt_interval: century_keyword */ +#line 2079 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(CENTURY), (yylsp[0]))); } +#line 26256 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 895: -#line 2078 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(YEAR) | - INTERVAL_MASK(MONTH), (yylsp[(1) - (3)]))); - ;} + case 902: /* opt_interval: millennium_keyword */ +#line 2081 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MILLENNIUM), (yylsp[0]))); } +#line 26262 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 896: + case 903: /* opt_interval: year_keyword TO month_keyword */ #line 2083 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY) | - INTERVAL_MASK(HOUR), (yylsp[(1) - (3)]))); - ;} + { + (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(YEAR) | + INTERVAL_MASK(MONTH), (yylsp[-2]))); + } +#line 26271 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 897: + case 904: /* opt_interval: day_keyword TO hour_keyword */ #line 2088 "third_party/libpg_query/grammar/statements/select.y" - { + { + (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY) | + INTERVAL_MASK(HOUR), (yylsp[-2]))); + } +#line 26280 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 905: /* opt_interval: day_keyword TO minute_keyword */ +#line 2093 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | - INTERVAL_MASK(MINUTE), (yylsp[(1) - (3)]))); - ;} + INTERVAL_MASK(MINUTE), (yylsp[-2]))); + } +#line 26290 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 898: -#line 2094 "third_party/libpg_query/grammar/statements/select.y" - { + case 906: /* opt_interval: day_keyword TO second_keyword */ +#line 2099 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | - INTERVAL_MASK(SECOND), (yylsp[(1) - (3)]))); - ;} + INTERVAL_MASK(SECOND), (yylsp[-2]))); + } +#line 26301 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 899: -#line 2101 "third_party/libpg_query/grammar/statements/select.y" - { + case 907: /* opt_interval: hour_keyword TO minute_keyword */ +#line 2106 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(HOUR) | - INTERVAL_MASK(MINUTE), (yylsp[(1) - (3)]))); - ;} + INTERVAL_MASK(MINUTE), (yylsp[-2]))); + } +#line 26310 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 900: -#line 2106 "third_party/libpg_query/grammar/statements/select.y" - { + case 908: /* opt_interval: hour_keyword TO second_keyword */ +#line 2111 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | - INTERVAL_MASK(SECOND), (yylsp[(1) - (3)]))); - ;} + INTERVAL_MASK(SECOND), (yylsp[-2]))); + } +#line 26320 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 901: -#line 2112 "third_party/libpg_query/grammar/statements/select.y" - { + case 909: /* opt_interval: minute_keyword TO second_keyword */ +#line 2117 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MINUTE) | - INTERVAL_MASK(SECOND), (yylsp[(1) - (3)]))); - ;} + INTERVAL_MASK(SECOND), (yylsp[-2]))); + } +#line 26329 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 902: -#line 2117 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 910: /* opt_interval: %empty */ +#line 2122 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 26335 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 903: -#line 2148 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + case 911: /* a_expr: c_expr */ +#line 2153 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 26341 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 904: -#line 2151 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeTypeCast((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].typnam), 0, (yylsp[(2) - (3)])); ;} + case 912: /* a_expr: a_expr TYPECAST Typename */ +#line 2156 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeTypeCast((yyvsp[-2].node), (yyvsp[0].typnam), 0, (yylsp[-1])); } +#line 26347 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 905: -#line 2153 "third_party/libpg_query/grammar/statements/select.y" - { + case 913: /* a_expr: a_expr COLLATE any_name */ +#line 2158 "third_party/libpg_query/grammar/statements/select.y" + { PGCollateClause *n = makeNode(PGCollateClause); - n->arg = (yyvsp[(1) - (3)].node); - n->collname = (yyvsp[(3) - (3)].list); - n->location = (yylsp[(2) - (3)]); + n->arg = (yyvsp[-2].node); + n->collname = (yyvsp[0].list); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *) n; - ;} + } +#line 26359 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 906: -#line 2161 "third_party/libpg_query/grammar/statements/select.y" - { + case 914: /* a_expr: a_expr AT TIME ZONE a_expr */ +#line 2166 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("timezone"), - list_make2((yyvsp[(5) - (5)].node), (yyvsp[(1) - (5)].node)), - (yylsp[(2) - (5)])); - ;} - break; - - case 907: -#line 2176 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; - - case 908: -#line 2178 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = doNegate((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + list_make2((yyvsp[0].node), (yyvsp[-4].node)), + (yylsp[-3])); + } +#line 26369 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 909: -#line 2180 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 915: /* a_expr: '+' a_expr */ +#line 2181 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[0].node), (yylsp[-1])); } +#line 26375 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 910: -#line 2182 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 916: /* a_expr: '-' a_expr */ +#line 2183 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = doNegate((yyvsp[0].node), (yylsp[-1])); } +#line 26381 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 911: -#line 2184 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "*", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 917: /* a_expr: a_expr '+' a_expr */ +#line 2185 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26387 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 912: -#line 2186 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "/", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 918: /* a_expr: a_expr '-' a_expr */ +#line 2187 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26393 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 913: -#line 2188 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "//", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 919: /* a_expr: a_expr '*' a_expr */ +#line 2189 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "*", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26399 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 914: -#line 2190 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "%", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 920: /* a_expr: a_expr '/' a_expr */ +#line 2191 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "/", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26405 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 915: -#line 2192 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "^", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 921: /* a_expr: a_expr INTEGER_DIVISION a_expr */ +#line 2193 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "//", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26411 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 916: -#line 2194 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "**", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 922: /* a_expr: a_expr '%' a_expr */ +#line 2195 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "%", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26417 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 917: -#line 2196 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 923: /* a_expr: a_expr '^' a_expr */ +#line 2197 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "^", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26423 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 918: -#line 2198 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 924: /* a_expr: a_expr POWER_OF a_expr */ +#line 2199 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "**", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26429 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 919: -#line 2200 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 925: /* a_expr: a_expr '<' a_expr */ +#line 2201 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26435 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 920: -#line 2202 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 926: /* a_expr: a_expr '>' a_expr */ +#line 2203 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26441 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 921: -#line 2204 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 927: /* a_expr: a_expr '=' a_expr */ +#line 2205 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "=", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26447 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 922: -#line 2206 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<>", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 928: /* a_expr: a_expr LESS_EQUALS a_expr */ +#line 2207 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<=", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26453 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 923: + case 929: /* a_expr: a_expr GREATER_EQUALS a_expr */ #line 2209 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (3)].list), (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">=", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26459 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 924: + case 930: /* a_expr: a_expr NOT_EQUALS a_expr */ #line 2211 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(1) - (2)].list), NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<>", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26465 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 925: -#line 2213 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (2)].list), (yyvsp[(1) - (2)].node), NULL, (yylsp[(2) - (2)])); ;} + case 931: /* a_expr: a_expr qual_Op a_expr */ +#line 2214 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[-1].list), (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26471 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 926: + case 932: /* a_expr: qual_Op a_expr */ #line 2216 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeAndExpr((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[-1].list), NULL, (yyvsp[0].node), (yylsp[-1])); } +#line 26477 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 927: + case 933: /* a_expr: a_expr qual_Op */ #line 2218 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeOrExpr((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[0].list), (yyvsp[-1].node), NULL, (yylsp[0])); } +#line 26483 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 928: -#line 2220 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeNotExpr((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + case 934: /* a_expr: a_expr AND a_expr */ +#line 2221 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeAndExpr((yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26489 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 929: -#line 2222 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeNotExpr((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + case 935: /* a_expr: a_expr OR a_expr */ +#line 2223 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeOrExpr((yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 26495 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 930: -#line 2224 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_GLOB, "~~~", - (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); - ;} + case 936: /* a_expr: NOT a_expr */ +#line 2225 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeNotExpr((yyvsp[0].node), (yylsp[-1])); } +#line 26501 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 937: /* a_expr: NOT_LA a_expr */ +#line 2227 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeNotExpr((yyvsp[0].node), (yylsp[-1])); } +#line 26507 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 931: + case 938: /* a_expr: a_expr GLOB a_expr */ #line 2229 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_LIKE, "~~", - (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); - ;} + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_GLOB, "~~~", + (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); + } +#line 26516 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 932: + case 939: /* a_expr: a_expr LIKE a_expr */ #line 2234 "third_party/libpg_query/grammar/statements/select.y" - { + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_LIKE, "~~", + (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); + } +#line 26525 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 940: /* a_expr: a_expr LIKE a_expr ESCAPE a_expr */ +#line 2239 "third_party/libpg_query/grammar/statements/select.y" + { PGFuncCall *n = makeFuncCall(SystemFuncName("like_escape"), - list_make3((yyvsp[(1) - (5)].node), (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)), - (yylsp[(2) - (5)])); + list_make3((yyvsp[-4].node), (yyvsp[-2].node), (yyvsp[0].node)), + (yylsp[-3])); (yyval.node) = (PGNode *) n; - ;} + } +#line 26536 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 933: -#line 2241 "third_party/libpg_query/grammar/statements/select.y" - { + case 941: /* a_expr: a_expr NOT_LA LIKE a_expr */ +#line 2246 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_LIKE, "!~~", - (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node), (yylsp[(2) - (4)])); - ;} + (yyvsp[-3].node), (yyvsp[0].node), (yylsp[-2])); + } +#line 26545 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 934: -#line 2246 "third_party/libpg_query/grammar/statements/select.y" - { + case 942: /* a_expr: a_expr NOT_LA LIKE a_expr ESCAPE a_expr */ +#line 2251 "third_party/libpg_query/grammar/statements/select.y" + { PGFuncCall *n = makeFuncCall(SystemFuncName("not_like_escape"), - list_make3((yyvsp[(1) - (6)].node), (yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), - (yylsp[(2) - (6)])); + list_make3((yyvsp[-5].node), (yyvsp[-2].node), (yyvsp[0].node)), + (yylsp[-4])); (yyval.node) = (PGNode *) n; - ;} + } +#line 26556 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 935: -#line 2253 "third_party/libpg_query/grammar/statements/select.y" - { + case 943: /* a_expr: a_expr ILIKE a_expr */ +#line 2258 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_ILIKE, "~~*", - (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); - ;} + (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); + } +#line 26565 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 936: -#line 2258 "third_party/libpg_query/grammar/statements/select.y" - { + case 944: /* a_expr: a_expr ILIKE a_expr ESCAPE a_expr */ +#line 2263 "third_party/libpg_query/grammar/statements/select.y" + { PGFuncCall *n = makeFuncCall(SystemFuncName("ilike_escape"), - list_make3((yyvsp[(1) - (5)].node), (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)), - (yylsp[(2) - (5)])); + list_make3((yyvsp[-4].node), (yyvsp[-2].node), (yyvsp[0].node)), + (yylsp[-3])); (yyval.node) = (PGNode *) n; - ;} + } +#line 26576 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 937: -#line 2265 "third_party/libpg_query/grammar/statements/select.y" - { + case 945: /* a_expr: a_expr NOT_LA ILIKE a_expr */ +#line 2270 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_ILIKE, "!~~*", - (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node), (yylsp[(2) - (4)])); - ;} + (yyvsp[-3].node), (yyvsp[0].node), (yylsp[-2])); + } +#line 26585 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 938: -#line 2270 "third_party/libpg_query/grammar/statements/select.y" - { + case 946: /* a_expr: a_expr NOT_LA ILIKE a_expr ESCAPE a_expr */ +#line 2275 "third_party/libpg_query/grammar/statements/select.y" + { PGFuncCall *n = makeFuncCall(SystemFuncName("not_ilike_escape"), - list_make3((yyvsp[(1) - (6)].node), (yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), - (yylsp[(2) - (6)])); + list_make3((yyvsp[-5].node), (yyvsp[-2].node), (yyvsp[0].node)), + (yylsp[-4])); (yyval.node) = (PGNode *) n; - ;} + } +#line 26596 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 939: -#line 2278 "third_party/libpg_query/grammar/statements/select.y" - { + case 947: /* a_expr: a_expr SIMILAR TO a_expr */ +#line 2283 "third_party/libpg_query/grammar/statements/select.y" + { PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), - list_make2((yyvsp[(4) - (4)].node), makeNullAConst(-1)), - (yylsp[(2) - (4)])); + list_make2((yyvsp[0].node), makeNullAConst(-1)), + (yylsp[-2])); (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "~", - (yyvsp[(1) - (4)].node), (PGNode *) n, (yylsp[(2) - (4)])); - ;} + (yyvsp[-3].node), (PGNode *) n, (yylsp[-2])); + } +#line 26608 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 940: -#line 2286 "third_party/libpg_query/grammar/statements/select.y" - { + case 948: /* a_expr: a_expr SIMILAR TO a_expr ESCAPE a_expr */ +#line 2291 "third_party/libpg_query/grammar/statements/select.y" + { PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), - list_make2((yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), - (yylsp[(2) - (6)])); + list_make2((yyvsp[-2].node), (yyvsp[0].node)), + (yylsp[-4])); (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "~", - (yyvsp[(1) - (6)].node), (PGNode *) n, (yylsp[(2) - (6)])); - ;} + (yyvsp[-5].node), (PGNode *) n, (yylsp[-4])); + } +#line 26620 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 941: -#line 2294 "third_party/libpg_query/grammar/statements/select.y" - { + case 949: /* a_expr: a_expr NOT_LA SIMILAR TO a_expr */ +#line 2299 "third_party/libpg_query/grammar/statements/select.y" + { PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), - list_make2((yyvsp[(5) - (5)].node), makeNullAConst(-1)), - (yylsp[(2) - (5)])); + list_make2((yyvsp[0].node), makeNullAConst(-1)), + (yylsp[-3])); (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "!~", - (yyvsp[(1) - (5)].node), (PGNode *) n, (yylsp[(2) - (5)])); - ;} + (yyvsp[-4].node), (PGNode *) n, (yylsp[-3])); + } +#line 26632 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 942: -#line 2302 "third_party/libpg_query/grammar/statements/select.y" - { + case 950: /* a_expr: a_expr NOT_LA SIMILAR TO a_expr ESCAPE a_expr */ +#line 2307 "third_party/libpg_query/grammar/statements/select.y" + { PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), - list_make2((yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)), - (yylsp[(2) - (7)])); + list_make2((yyvsp[-2].node), (yyvsp[0].node)), + (yylsp[-5])); (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "!~", - (yyvsp[(1) - (7)].node), (PGNode *) n, (yylsp[(2) - (7)])); - ;} + (yyvsp[-6].node), (PGNode *) n, (yylsp[-5])); + } +#line 26644 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 943: -#line 2320 "third_party/libpg_query/grammar/statements/select.y" - { + case 951: /* a_expr: a_expr IS NULL_P */ +#line 2325 "third_party/libpg_query/grammar/statements/select.y" + { PGNullTest *n = makeNode(PGNullTest); - n->arg = (PGExpr *) (yyvsp[(1) - (3)].node); + n->arg = (PGExpr *) (yyvsp[-2].node); n->nulltesttype = PG_IS_NULL; - n->location = (yylsp[(2) - (3)]); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *)n; - ;} + } +#line 26656 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 944: -#line 2328 "third_party/libpg_query/grammar/statements/select.y" - { + case 952: /* a_expr: a_expr ISNULL */ +#line 2333 "third_party/libpg_query/grammar/statements/select.y" + { PGNullTest *n = makeNode(PGNullTest); - n->arg = (PGExpr *) (yyvsp[(1) - (2)].node); + n->arg = (PGExpr *) (yyvsp[-1].node); n->nulltesttype = PG_IS_NULL; - n->location = (yylsp[(2) - (2)]); + n->location = (yylsp[0]); (yyval.node) = (PGNode *)n; - ;} + } +#line 26668 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 945: -#line 2336 "third_party/libpg_query/grammar/statements/select.y" - { + case 953: /* a_expr: a_expr IS NOT NULL_P */ +#line 2341 "third_party/libpg_query/grammar/statements/select.y" + { PGNullTest *n = makeNode(PGNullTest); - n->arg = (PGExpr *) (yyvsp[(1) - (4)].node); + n->arg = (PGExpr *) (yyvsp[-3].node); n->nulltesttype = IS_NOT_NULL; - n->location = (yylsp[(2) - (4)]); + n->location = (yylsp[-2]); (yyval.node) = (PGNode *)n; - ;} + } +#line 26680 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 946: -#line 2344 "third_party/libpg_query/grammar/statements/select.y" - { + case 954: /* a_expr: a_expr NOT NULL_P */ +#line 2349 "third_party/libpg_query/grammar/statements/select.y" + { PGNullTest *n = makeNode(PGNullTest); - n->arg = (PGExpr *) (yyvsp[(1) - (3)].node); + n->arg = (PGExpr *) (yyvsp[-2].node); n->nulltesttype = IS_NOT_NULL; - n->location = (yylsp[(2) - (3)]); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *)n; - ;} + } +#line 26692 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 947: -#line 2352 "third_party/libpg_query/grammar/statements/select.y" - { + case 955: /* a_expr: a_expr NOTNULL */ +#line 2357 "third_party/libpg_query/grammar/statements/select.y" + { PGNullTest *n = makeNode(PGNullTest); - n->arg = (PGExpr *) (yyvsp[(1) - (2)].node); + n->arg = (PGExpr *) (yyvsp[-1].node); n->nulltesttype = IS_NOT_NULL; - n->location = (yylsp[(2) - (2)]); + n->location = (yylsp[0]); (yyval.node) = (PGNode *)n; - ;} + } +#line 26704 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 948: -#line 2360 "third_party/libpg_query/grammar/statements/select.y" - { + case 956: /* a_expr: a_expr LAMBDA_ARROW a_expr */ +#line 2365 "third_party/libpg_query/grammar/statements/select.y" + { PGLambdaFunction *n = makeNode(PGLambdaFunction); - n->lhs = (yyvsp[(1) - (3)].node); - n->rhs = (yyvsp[(3) - (3)].node); - n->location = (yylsp[(2) - (3)]); + n->lhs = (yyvsp[-2].node); + n->rhs = (yyvsp[0].node); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *) n; - ;} + } +#line 26716 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 949: -#line 2368 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "->>", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); - ;} + case 957: /* a_expr: a_expr DOUBLE_ARROW a_expr */ +#line 2373 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "->>", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); + } +#line 26724 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 950: -#line 2372 "third_party/libpg_query/grammar/statements/select.y" - { - if (list_length((yyvsp[(1) - (3)].list)) != 2) + case 958: /* a_expr: row OVERLAPS row */ +#line 2377 "third_party/libpg_query/grammar/statements/select.y" + { + if (list_length((yyvsp[-2].list)) != 2) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("wrong number of parameters on left side of OVERLAPS expression"), - parser_errposition((yylsp[(1) - (3)])))); - if (list_length((yyvsp[(3) - (3)].list)) != 2) + parser_errposition((yylsp[-2])))); + if (list_length((yyvsp[0].list)) != 2) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("wrong number of parameters on right side of OVERLAPS expression"), - parser_errposition((yylsp[(3) - (3)])))); + parser_errposition((yylsp[0])))); (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("overlaps"), - list_concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)), - (yylsp[(2) - (3)])); - ;} + list_concat((yyvsp[-2].list), (yyvsp[0].list)), + (yylsp[-1])); + } +#line 26744 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 951: -#line 2388 "third_party/libpg_query/grammar/statements/select.y" - { + case 959: /* a_expr: a_expr IS TRUE_P */ +#line 2393 "third_party/libpg_query/grammar/statements/select.y" + { PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (3)].node); + b->arg = (PGExpr *) (yyvsp[-2].node); b->booltesttype = PG_IS_TRUE; - b->location = (yylsp[(2) - (3)]); + b->location = (yylsp[-1]); (yyval.node) = (PGNode *)b; - ;} + } +#line 26756 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 952: -#line 2396 "third_party/libpg_query/grammar/statements/select.y" - { + case 960: /* a_expr: a_expr IS NOT TRUE_P */ +#line 2401 "third_party/libpg_query/grammar/statements/select.y" + { PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (4)].node); + b->arg = (PGExpr *) (yyvsp[-3].node); b->booltesttype = IS_NOT_TRUE; - b->location = (yylsp[(2) - (4)]); + b->location = (yylsp[-2]); (yyval.node) = (PGNode *)b; - ;} + } +#line 26768 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 953: -#line 2404 "third_party/libpg_query/grammar/statements/select.y" - { + case 961: /* a_expr: a_expr IS FALSE_P */ +#line 2409 "third_party/libpg_query/grammar/statements/select.y" + { PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (3)].node); + b->arg = (PGExpr *) (yyvsp[-2].node); b->booltesttype = IS_FALSE; - b->location = (yylsp[(2) - (3)]); + b->location = (yylsp[-1]); (yyval.node) = (PGNode *)b; - ;} + } +#line 26780 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 954: -#line 2412 "third_party/libpg_query/grammar/statements/select.y" - { + case 962: /* a_expr: a_expr IS NOT FALSE_P */ +#line 2417 "third_party/libpg_query/grammar/statements/select.y" + { PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (4)].node); + b->arg = (PGExpr *) (yyvsp[-3].node); b->booltesttype = IS_NOT_FALSE; - b->location = (yylsp[(2) - (4)]); + b->location = (yylsp[-2]); (yyval.node) = (PGNode *)b; - ;} + } +#line 26792 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 955: -#line 2420 "third_party/libpg_query/grammar/statements/select.y" - { + case 963: /* a_expr: a_expr IS UNKNOWN */ +#line 2425 "third_party/libpg_query/grammar/statements/select.y" + { PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (3)].node); + b->arg = (PGExpr *) (yyvsp[-2].node); b->booltesttype = IS_UNKNOWN; - b->location = (yylsp[(2) - (3)]); + b->location = (yylsp[-1]); (yyval.node) = (PGNode *)b; - ;} + } +#line 26804 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 956: -#line 2428 "third_party/libpg_query/grammar/statements/select.y" - { + case 964: /* a_expr: a_expr IS NOT UNKNOWN */ +#line 2433 "third_party/libpg_query/grammar/statements/select.y" + { PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (4)].node); + b->arg = (PGExpr *) (yyvsp[-3].node); b->booltesttype = IS_NOT_UNKNOWN; - b->location = (yylsp[(2) - (4)]); + b->location = (yylsp[-2]); (yyval.node) = (PGNode *)b; - ;} + } +#line 26816 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 957: -#line 2436 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_DISTINCT, "=", (yyvsp[(1) - (5)].node), (yyvsp[(5) - (5)].node), (yylsp[(2) - (5)])); - ;} + case 965: /* a_expr: a_expr IS DISTINCT FROM a_expr */ +#line 2441 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_DISTINCT, "=", (yyvsp[-4].node), (yyvsp[0].node), (yylsp[-3])); + } +#line 26824 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 958: -#line 2440 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_DISTINCT, "=", (yyvsp[(1) - (6)].node), (yyvsp[(6) - (6)].node), (yylsp[(2) - (6)])); - ;} + case 966: /* a_expr: a_expr IS NOT DISTINCT FROM a_expr */ +#line 2445 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_DISTINCT, "=", (yyvsp[-5].node), (yyvsp[0].node), (yylsp[-4])); + } +#line 26832 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 959: -#line 2444 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "=", (yyvsp[(1) - (6)].node), (PGNode *) (yyvsp[(5) - (6)].list), (yylsp[(2) - (6)])); - ;} + case 967: /* a_expr: a_expr IS OF '(' type_list ')' */ +#line 2449 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "=", (yyvsp[-5].node), (PGNode *) (yyvsp[-1].list), (yylsp[-4])); + } +#line 26840 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 960: -#line 2448 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "<>", (yyvsp[(1) - (7)].node), (PGNode *) (yyvsp[(6) - (7)].list), (yylsp[(2) - (7)])); - ;} + case 968: /* a_expr: a_expr IS NOT OF '(' type_list ')' */ +#line 2453 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "<>", (yyvsp[-6].node), (PGNode *) (yyvsp[-1].list), (yylsp[-5])); + } +#line 26848 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 961: -#line 2452 "third_party/libpg_query/grammar/statements/select.y" - { + case 969: /* a_expr: a_expr BETWEEN opt_asymmetric b_expr AND a_expr */ +#line 2457 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_BETWEEN, "BETWEEN", - (yyvsp[(1) - (6)].node), - (PGNode *) list_make2((yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), - (yylsp[(2) - (6)])); - ;} + (yyvsp[-5].node), + (PGNode *) list_make2((yyvsp[-2].node), (yyvsp[0].node)), + (yylsp[-4])); + } +#line 26860 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 962: -#line 2460 "third_party/libpg_query/grammar/statements/select.y" - { + case 970: /* a_expr: a_expr NOT_LA BETWEEN opt_asymmetric b_expr AND a_expr */ +#line 2465 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_BETWEEN, "NOT BETWEEN", - (yyvsp[(1) - (7)].node), - (PGNode *) list_make2((yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)), - (yylsp[(2) - (7)])); - ;} + (yyvsp[-6].node), + (PGNode *) list_make2((yyvsp[-2].node), (yyvsp[0].node)), + (yylsp[-5])); + } +#line 26872 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 963: -#line 2468 "third_party/libpg_query/grammar/statements/select.y" - { + case 971: /* a_expr: a_expr BETWEEN SYMMETRIC b_expr AND a_expr */ +#line 2473 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_BETWEEN_SYM, "BETWEEN SYMMETRIC", - (yyvsp[(1) - (6)].node), - (PGNode *) list_make2((yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), - (yylsp[(2) - (6)])); - ;} + (yyvsp[-5].node), + (PGNode *) list_make2((yyvsp[-2].node), (yyvsp[0].node)), + (yylsp[-4])); + } +#line 26884 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 964: -#line 2476 "third_party/libpg_query/grammar/statements/select.y" - { + case 972: /* a_expr: a_expr NOT_LA BETWEEN SYMMETRIC b_expr AND a_expr */ +#line 2481 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_BETWEEN_SYM, "NOT BETWEEN SYMMETRIC", - (yyvsp[(1) - (7)].node), - (PGNode *) list_make2((yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)), - (yylsp[(2) - (7)])); - ;} + (yyvsp[-6].node), + (PGNode *) list_make2((yyvsp[-2].node), (yyvsp[0].node)), + (yylsp[-5])); + } +#line 26896 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 965: -#line 2484 "third_party/libpg_query/grammar/statements/select.y" - { + case 973: /* a_expr: a_expr IN_P in_expr */ +#line 2489 "third_party/libpg_query/grammar/statements/select.y" + { /* in_expr returns a PGSubLink or a list of a_exprs */ - if (IsA((yyvsp[(3) - (3)].node), PGSubLink)) + if (IsA((yyvsp[0].node), PGSubLink)) { /* generate foo = ANY (subquery) */ - PGSubLink *n = (PGSubLink *) (yyvsp[(3) - (3)].node); + PGSubLink *n = (PGSubLink *) (yyvsp[0].node); n->subLinkType = PG_ANY_SUBLINK; n->subLinkId = 0; - n->testexpr = (yyvsp[(1) - (3)].node); + n->testexpr = (yyvsp[-2].node); n->operName = NIL; /* show it's IN not = ANY */ - n->location = (yylsp[(2) - (3)]); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *)n; } else { /* generate scalar IN expression */ - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_IN, "=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_IN, "=", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } - ;} + } +#line 26920 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 966: -#line 2504 "third_party/libpg_query/grammar/statements/select.y" - { + case 974: /* a_expr: a_expr NOT_LA IN_P in_expr */ +#line 2509 "third_party/libpg_query/grammar/statements/select.y" + { /* in_expr returns a PGSubLink or a list of a_exprs */ - if (IsA((yyvsp[(4) - (4)].node), PGSubLink)) + if (IsA((yyvsp[0].node), PGSubLink)) { /* generate NOT (foo = ANY (subquery)) */ /* Make an = ANY node */ - PGSubLink *n = (PGSubLink *) (yyvsp[(4) - (4)].node); + PGSubLink *n = (PGSubLink *) (yyvsp[0].node); n->subLinkType = PG_ANY_SUBLINK; n->subLinkId = 0; - n->testexpr = (yyvsp[(1) - (4)].node); + n->testexpr = (yyvsp[-3].node); n->operName = NIL; /* show it's IN not = ANY */ - n->location = (yylsp[(2) - (4)]); + n->location = (yylsp[-2]); /* Stick a NOT on top; must have same parse location */ - (yyval.node) = makeNotExpr((PGNode *) n, (yylsp[(2) - (4)])); + (yyval.node) = makeNotExpr((PGNode *) n, (yylsp[-2])); } else { /* generate scalar NOT IN expression */ - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_IN, "<>", (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node), (yylsp[(2) - (4)])); + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_IN, "<>", (yyvsp[-3].node), (yyvsp[0].node), (yylsp[-2])); } - ;} + } +#line 26946 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 967: -#line 2526 "third_party/libpg_query/grammar/statements/select.y" - { + case 975: /* a_expr: a_expr subquery_Op sub_type select_with_parens */ +#line 2531 "third_party/libpg_query/grammar/statements/select.y" + { PGSubLink *n = makeNode(PGSubLink); - n->subLinkType = (yyvsp[(3) - (4)].subquerytype); + n->subLinkType = (yyvsp[-1].subquerytype); n->subLinkId = 0; - n->testexpr = (yyvsp[(1) - (4)].node); - n->operName = (yyvsp[(2) - (4)].list); - n->subselect = (yyvsp[(4) - (4)].node); - n->location = (yylsp[(2) - (4)]); + n->testexpr = (yyvsp[-3].node); + n->operName = (yyvsp[-2].list); + n->subselect = (yyvsp[0].node); + n->location = (yylsp[-2]); (yyval.node) = (PGNode *)n; - ;} + } +#line 26961 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 968: -#line 2537 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(3) - (6)].subquerytype) == PG_ANY_SUBLINK) - (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP_ANY, (yyvsp[(2) - (6)].list), (yyvsp[(1) - (6)].node), (yyvsp[(5) - (6)].node), (yylsp[(2) - (6)])); + case 976: /* a_expr: a_expr subquery_Op sub_type '(' a_expr ')' */ +#line 2542 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[-3].subquerytype) == PG_ANY_SUBLINK) + (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP_ANY, (yyvsp[-4].list), (yyvsp[-5].node), (yyvsp[-1].node), (yylsp[-4])); else - (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP_ALL, (yyvsp[(2) - (6)].list), (yyvsp[(1) - (6)].node), (yyvsp[(5) - (6)].node), (yylsp[(2) - (6)])); - ;} + (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP_ALL, (yyvsp[-4].list), (yyvsp[-5].node), (yyvsp[-1].node), (yylsp[-4])); + } +#line 26972 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 969: -#line 2544 "third_party/libpg_query/grammar/statements/select.y" - { + case 977: /* a_expr: DEFAULT */ +#line 2549 "third_party/libpg_query/grammar/statements/select.y" + { /* * The SQL spec only allows DEFAULT in "contextually typed * expressions", but for us, it's easier to allow it in @@ -27013,220 +26983,266 @@ YYLTYPE yylloc; */ PGSetToDefault *n = makeNode(PGSetToDefault); /* parse analysis will fill in the rest */ - n->location = (yylsp[(1) - (1)]); + n->location = (yylsp[0]); (yyval.node) = (PGNode *)n; - ;} + } +#line 26990 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 970: -#line 2558 "third_party/libpg_query/grammar/statements/select.y" - { + case 978: /* a_expr: '*' COLUMNS '(' a_expr ')' */ +#line 2563 "third_party/libpg_query/grammar/statements/select.y" + { PGAStar *star = makeNode(PGAStar); - star->expr = (yyvsp[(3) - (4)].node); + star->expr = (yyvsp[-1].node); star->columns = true; - star->location = (yylsp[(1) - (4)]); + star->unpacked = true; + star->location = (yylsp[-4]); (yyval.node) = (PGNode *) star; - ;} + } +#line 27003 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 971: -#line 2566 "third_party/libpg_query/grammar/statements/select.y" - { + case 979: /* a_expr: COLUMNS '(' a_expr ')' */ +#line 2572 "third_party/libpg_query/grammar/statements/select.y" + { PGAStar *star = makeNode(PGAStar); - star->except_list = (yyvsp[(2) - (3)].list); - star->replace_list = (yyvsp[(3) - (3)].list); - star->location = (yylsp[(1) - (3)]); + star->expr = (yyvsp[-1].node); + star->columns = true; + star->location = (yylsp[-3]); (yyval.node) = (PGNode *) star; - ;} + } +#line 27015 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 972: -#line 2574 "third_party/libpg_query/grammar/statements/select.y" - { + case 980: /* a_expr: '*' opt_except_list opt_replace_list */ +#line 2580 "third_party/libpg_query/grammar/statements/select.y" + { PGAStar *star = makeNode(PGAStar); - star->relation = (yyvsp[(1) - (5)].str); - star->except_list = (yyvsp[(4) - (5)].list); - star->replace_list = (yyvsp[(5) - (5)].list); - star->location = (yylsp[(1) - (5)]); + star->except_list = (yyvsp[-1].list); + star->replace_list = (yyvsp[0].list); + star->location = (yylsp[-2]); (yyval.node) = (PGNode *) star; - ;} - break; - - case 973: -#line 2594 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; - - case 974: -#line 2596 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeTypeCast((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].typnam), 0, (yylsp[(2) - (3)])); ;} - break; - - case 975: -#line 2598 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; - - case 976: -#line 2600 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = doNegate((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; - - case 977: -#line 2602 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; - - case 978: -#line 2604 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + } +#line 27027 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 979: -#line 2606 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "*", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + case 981: /* a_expr: ColId '.' '*' opt_except_list opt_replace_list */ +#line 2588 "third_party/libpg_query/grammar/statements/select.y" + { + PGAStar *star = makeNode(PGAStar); + star->relation = (yyvsp[-4].str); + star->except_list = (yyvsp[-1].list); + star->replace_list = (yyvsp[0].list); + star->location = (yylsp[-4]); + (yyval.node) = (PGNode *) star; + } +#line 27040 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 980: + case 982: /* b_expr: c_expr */ #line 2608 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "/", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 27046 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 981: + case 983: /* b_expr: b_expr TYPECAST Typename */ #line 2610 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "//", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = makeTypeCast((yyvsp[-2].node), (yyvsp[0].typnam), 0, (yylsp[-1])); } +#line 27052 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 982: + case 984: /* b_expr: '+' b_expr */ #line 2612 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "%", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[0].node), (yylsp[-1])); } +#line 27058 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 983: + case 985: /* b_expr: '-' b_expr */ #line 2614 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "^", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = doNegate((yyvsp[0].node), (yylsp[-1])); } +#line 27064 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 984: + case 986: /* b_expr: b_expr '+' b_expr */ #line 2616 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "**", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27070 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 985: + case 987: /* b_expr: b_expr '-' b_expr */ #line 2618 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27076 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 986: + case 988: /* b_expr: b_expr '*' b_expr */ #line 2620 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "*", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27082 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 987: + case 989: /* b_expr: b_expr '/' b_expr */ #line 2622 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "/", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27088 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 988: + case 990: /* b_expr: b_expr INTEGER_DIVISION b_expr */ #line 2624 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "//", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27094 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 989: + case 991: /* b_expr: b_expr '%' b_expr */ #line 2626 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "%", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27100 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 990: + case 992: /* b_expr: b_expr '^' b_expr */ #line 2628 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<>", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "^", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27106 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 991: + case 993: /* b_expr: b_expr POWER_OF b_expr */ #line 2630 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (3)].list), (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "**", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27112 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 992: + case 994: /* b_expr: b_expr '<' b_expr */ #line 2632 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(1) - (2)].list), NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27118 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 993: + case 995: /* b_expr: b_expr '>' b_expr */ #line 2634 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (2)].list), (yyvsp[(1) - (2)].node), NULL, (yylsp[(2) - (2)])); ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27124 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 994: + case 996: /* b_expr: b_expr '=' b_expr */ #line 2636 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_DISTINCT, "=", (yyvsp[(1) - (5)].node), (yyvsp[(5) - (5)].node), (yylsp[(2) - (5)])); - ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "=", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27130 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 995: + case 997: /* b_expr: b_expr LESS_EQUALS b_expr */ +#line 2638 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<=", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27136 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 998: /* b_expr: b_expr GREATER_EQUALS b_expr */ #line 2640 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_DISTINCT, "=", (yyvsp[(1) - (6)].node), (yyvsp[(6) - (6)].node), (yylsp[(2) - (6)])); - ;} + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">=", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27142 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 999: /* b_expr: b_expr NOT_EQUALS b_expr */ +#line 2642 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<>", (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27148 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 996: + case 1000: /* b_expr: b_expr qual_Op b_expr */ #line 2644 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "=", (yyvsp[(1) - (6)].node), (PGNode *) (yyvsp[(5) - (6)].list), (yylsp[(2) - (6)])); - ;} + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[-1].list), (yyvsp[-2].node), (yyvsp[0].node), (yylsp[-1])); } +#line 27154 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 1001: /* b_expr: qual_Op b_expr */ +#line 2646 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[-1].list), NULL, (yyvsp[0].node), (yylsp[-1])); } +#line 27160 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 997: + case 1002: /* b_expr: b_expr qual_Op */ #line 2648 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "<>", (yyvsp[(1) - (7)].node), (PGNode *) (yyvsp[(6) - (7)].list), (yylsp[(2) - (7)])); - ;} + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[0].list), (yyvsp[-1].node), NULL, (yylsp[0])); } +#line 27166 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 999: -#line 2663 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(2) - (2)].list)) + case 1003: /* b_expr: b_expr IS DISTINCT FROM b_expr */ +#line 2650 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_DISTINCT, "=", (yyvsp[-4].node), (yyvsp[0].node), (yylsp[-3])); + } +#line 27174 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 1004: /* b_expr: b_expr IS NOT DISTINCT FROM b_expr */ +#line 2654 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_DISTINCT, "=", (yyvsp[-5].node), (yyvsp[0].node), (yylsp[-4])); + } +#line 27182 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 1005: /* b_expr: b_expr IS OF '(' type_list ')' */ +#line 2658 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "=", (yyvsp[-5].node), (PGNode *) (yyvsp[-1].list), (yylsp[-4])); + } +#line 27190 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 1006: /* b_expr: b_expr IS NOT OF '(' type_list ')' */ +#line 2662 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "<>", (yyvsp[-6].node), (PGNode *) (yyvsp[-1].list), (yylsp[-5])); + } +#line 27198 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 1008: /* c_expr: indirection_expr_or_a_expr opt_extended_indirection */ +#line 2677 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[0].list)) { PGAIndirection *n = makeNode(PGAIndirection); - n->arg = (PGNode *) (yyvsp[(1) - (2)].node); - n->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + n->arg = (PGNode *) (yyvsp[-1].node); + n->indirection = check_indirection((yyvsp[0].list), yyscanner); (yyval.node) = (PGNode *) n; } else - (yyval.node) = (PGNode *) (yyvsp[(1) - (2)].node); - ;} + (yyval.node) = (PGNode *) (yyvsp[-1].node); + } +#line 27214 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1000: -#line 2676 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + case 1009: /* d_expr: columnref */ +#line 2690 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 27220 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1001: -#line 2677 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + case 1010: /* d_expr: AexprConst */ +#line 2691 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 27226 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1002: -#line 2679 "third_party/libpg_query/grammar/statements/select.y" - { + case 1011: /* d_expr: select_with_parens */ +#line 2693 "third_party/libpg_query/grammar/statements/select.y" + { PGSubLink *n = makeNode(PGSubLink); n->subLinkType = PG_EXPR_SUBLINK; n->subLinkId = 0; n->testexpr = NULL; n->operName = NIL; - n->subselect = (yyvsp[(1) - (1)].node); - n->location = (yylsp[(1) - (1)]); + n->subselect = (yyvsp[0].node); + n->location = (yylsp[0]); (yyval.node) = (PGNode *)n; - ;} + } +#line 27241 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1003: -#line 2690 "third_party/libpg_query/grammar/statements/select.y" - { + case 1012: /* d_expr: select_with_parens indirection */ +#line 2704 "third_party/libpg_query/grammar/statements/select.y" + { /* * Because the select_with_parens nonterminal is designed * to "eat" as many levels of parens as possible, the @@ -27243,254 +27259,280 @@ YYLTYPE yylloc; n->subLinkId = 0; n->testexpr = NULL; n->operName = NIL; - n->subselect = (yyvsp[(1) - (2)].node); - n->location = (yylsp[(1) - (2)]); + n->subselect = (yyvsp[-1].node); + n->location = (yylsp[-1]); a->arg = (PGNode *)n; - a->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + a->indirection = check_indirection((yyvsp[0].list), yyscanner); (yyval.node) = (PGNode *)a; - ;} + } +#line 27269 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1004: -#line 2714 "third_party/libpg_query/grammar/statements/select.y" - { + case 1013: /* d_expr: EXISTS select_with_parens */ +#line 2728 "third_party/libpg_query/grammar/statements/select.y" + { PGSubLink *n = makeNode(PGSubLink); n->subLinkType = PG_EXISTS_SUBLINK; n->subLinkId = 0; n->testexpr = NULL; n->operName = NIL; - n->subselect = (yyvsp[(2) - (2)].node); - n->location = (yylsp[(1) - (2)]); + n->subselect = (yyvsp[0].node); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *)n; - ;} + } +#line 27284 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1005: -#line 2725 "third_party/libpg_query/grammar/statements/select.y" - { + case 1014: /* d_expr: grouping_or_grouping_id '(' expr_list_opt_comma ')' */ +#line 2739 "third_party/libpg_query/grammar/statements/select.y" + { PGGroupingFunc *g = makeNode(PGGroupingFunc); - g->args = (yyvsp[(3) - (4)].list); - g->location = (yylsp[(1) - (4)]); + g->args = (yyvsp[-1].list); + g->location = (yylsp[-3]); (yyval.node) = (PGNode *)g; - ;} + } +#line 27295 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1006: -#line 2735 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(2) - (3)].node); - ;} + case 1015: /* indirection_expr_or_a_expr: '(' a_expr ')' */ +#line 2749 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (yyvsp[-1].node); + } +#line 27303 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1007: -#line 2739 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(1) - (1)].node); - ;} + case 1016: /* indirection_expr_or_a_expr: indirection_expr */ +#line 2753 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (yyvsp[0].node); + } +#line 27311 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1008: -#line 2742 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("row"), (yyvsp[(1) - (1)].list), (yylsp[(1) - (1)])); + case 1017: /* indirection_expr_or_a_expr: row */ +#line 2756 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("row"), (yyvsp[0].list), (yylsp[0])); (yyval.node) = (PGNode *) n; - ;} + } +#line 27320 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1009: -#line 2750 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeParamRef(0, (yylsp[(1) - (1)])); - ;} + case 1018: /* indirection_expr: '?' */ +#line 2764 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeParamRef(0, (yylsp[0])); + } +#line 27328 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1010: -#line 2754 "third_party/libpg_query/grammar/statements/select.y" - { + case 1019: /* indirection_expr: PARAM */ +#line 2768 "third_party/libpg_query/grammar/statements/select.y" + { PGParamRef *p = makeNode(PGParamRef); - p->number = (yyvsp[(1) - (1)].ival); - p->location = (yylsp[(1) - (1)]); + p->number = (yyvsp[0].ival); + p->location = (yylsp[0]); (yyval.node) = (PGNode *) p; - ;} + } +#line 27339 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1011: -#line 2761 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(1) - (1)].node); - ;} + case 1020: /* indirection_expr: struct_expr */ +#line 2775 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (yyvsp[0].node); + } +#line 27347 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1012: -#line 2765 "third_party/libpg_query/grammar/statements/select.y" - { + case 1021: /* indirection_expr: MAP '{' opt_map_arguments_opt_comma '}' */ +#line 2779 "third_party/libpg_query/grammar/statements/select.y" + { PGList *key_list = NULL; PGList *value_list = NULL; PGListCell *lc; - PGList *entry_list = (yyvsp[(3) - (4)].list); + PGList *entry_list = (yyvsp[-1].list); foreach(lc, entry_list) { PGList *l = (PGList *) lc->data.ptr_value; key_list = lappend(key_list, (PGNode *) l->head->data.ptr_value); value_list = lappend(value_list, (PGNode *) l->tail->data.ptr_value); } - PGNode *keys = (PGNode *) makeFuncCall(SystemFuncName("list_value"), key_list, (yylsp[(3) - (4)])); - PGNode *values = (PGNode *) makeFuncCall(SystemFuncName("list_value"), value_list, (yylsp[(3) - (4)])); - PGFuncCall *f = makeFuncCall(SystemFuncName("map"), list_make2(keys, values), (yylsp[(3) - (4)])); + PGNode *keys = (PGNode *) makeFuncCall(SystemFuncName("list_value"), key_list, (yylsp[-1])); + PGNode *values = (PGNode *) makeFuncCall(SystemFuncName("list_value"), value_list, (yylsp[-1])); + PGFuncCall *f = makeFuncCall(SystemFuncName("map"), list_make2(keys, values), (yylsp[-1])); (yyval.node) = (PGNode *) f; - ;} + } +#line 27368 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1013: -#line 2782 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(1) - (1)].node); - ;} + case 1022: /* indirection_expr: func_expr */ +#line 2796 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (yyvsp[0].node); + } +#line 27376 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1014: -#line 2786 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + case 1023: /* indirection_expr: case_expr */ +#line 2800 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 27382 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1015: -#line 2787 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(1) - (1)].node); - ;} + case 1024: /* indirection_expr: list_expr */ +#line 2801 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (yyvsp[0].node); + } +#line 27390 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1016: -#line 2790 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(1) - (1)].node); - ;} + case 1025: /* indirection_expr: list_comprehension */ +#line 2804 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (yyvsp[0].node); + } +#line 27398 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1017: -#line 2794 "third_party/libpg_query/grammar/statements/select.y" - { + case 1026: /* indirection_expr: ARRAY select_with_parens */ +#line 2808 "third_party/libpg_query/grammar/statements/select.y" + { PGSubLink *n = makeNode(PGSubLink); n->subLinkType = PG_ARRAY_SUBLINK; n->subLinkId = 0; n->testexpr = NULL; n->operName = NULL; - n->subselect = (yyvsp[(2) - (2)].node); - n->location = (yylsp[(2) - (2)]); + n->subselect = (yyvsp[0].node); + n->location = (yylsp[0]); (yyval.node) = (PGNode *)n; - ;} + } +#line 27413 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1018: -#line 2804 "third_party/libpg_query/grammar/statements/select.y" - { + case 1027: /* indirection_expr: ARRAY '[' opt_expr_list_opt_comma ']' */ +#line 2818 "third_party/libpg_query/grammar/statements/select.y" + { PGList *func_name = list_make1(makeString("construct_array")); - PGFuncCall *n = makeFuncCall(func_name, (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); + PGFuncCall *n = makeFuncCall(func_name, (yyvsp[-1].list), (yylsp[-3])); (yyval.node) = (PGNode *) n; - ;} + } +#line 27423 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1019: -#line 2810 "third_party/libpg_query/grammar/statements/select.y" - { + case 1028: /* indirection_expr: '#' ICONST */ +#line 2824 "third_party/libpg_query/grammar/statements/select.y" + { PGPositionalReference *n = makeNode(PGPositionalReference); - n->position = (yyvsp[(2) - (2)].ival); - n->location = (yylsp[(1) - (2)]); + n->position = (yyvsp[0].ival); + n->location = (yylsp[-1]); (yyval.node) = (PGNode *) n; - ;} + } +#line 27434 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1020: -#line 2817 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeNamedParamRef((yyvsp[(2) - (2)].str), (yylsp[(1) - (2)])); - ;} + case 1029: /* indirection_expr: '$' ColLabel */ +#line 2831 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeNamedParamRef((yyvsp[0].str), (yylsp[-1])); + } +#line 27442 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1021: -#line 2822 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("list_value"), (yyvsp[(2) - (3)].list), (yylsp[(2) - (3)])); + case 1030: /* list_expr: '[' opt_expr_list_opt_comma ']' */ +#line 2836 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("list_value"), (yyvsp[-1].list), (yylsp[-1])); (yyval.node) = (PGNode *) n; - ;} + } +#line 27451 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1022: -#line 2829 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *f = makeFuncCall(SystemFuncName("struct_pack"), (yyvsp[(2) - (3)].list), (yylsp[(2) - (3)])); + case 1031: /* struct_expr: '{' dict_arguments_opt_comma '}' */ +#line 2843 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *f = makeFuncCall(SystemFuncName("struct_pack"), (yyvsp[-1].list), (yylsp[-1])); (yyval.node) = (PGNode *) f; - ;} + } +#line 27460 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1023: -#line 2838 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeFuncCall((yyvsp[(1) - (3)].list), NIL, (yylsp[(1) - (3)])); - ;} + case 1032: /* func_application: func_name '(' ')' */ +#line 2852 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall((yyvsp[-2].list), NIL, (yylsp[-2])); + } +#line 27468 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1024: -#line 2842 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (6)].list), (yyvsp[(3) - (6)].list), (yylsp[(1) - (6)])); - n->agg_order = (yyvsp[(4) - (6)].list); - n->agg_ignore_nulls = (yyvsp[(5) - (6)].ignorenulls); + case 1033: /* func_application: func_name '(' func_arg_list opt_sort_clause opt_ignore_nulls ')' */ +#line 2856 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall((yyvsp[-5].list), (yyvsp[-3].list), (yylsp[-5])); + n->agg_order = (yyvsp[-2].list); + n->agg_ignore_nulls = (yyvsp[-1].ignorenulls); (yyval.node) = (PGNode *)n; - ;} + } +#line 27479 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1025: -#line 2849 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (7)].list), list_make1((yyvsp[(4) - (7)].node)), (yylsp[(1) - (7)])); + case 1034: /* func_application: func_name '(' VARIADIC func_arg_expr opt_sort_clause opt_ignore_nulls ')' */ +#line 2863 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall((yyvsp[-6].list), list_make1((yyvsp[-3].node)), (yylsp[-6])); n->func_variadic = true; - n->agg_order = (yyvsp[(5) - (7)].list); - n->agg_ignore_nulls = (yyvsp[(6) - (7)].ignorenulls); + n->agg_order = (yyvsp[-2].list); + n->agg_ignore_nulls = (yyvsp[-1].ignorenulls); (yyval.node) = (PGNode *)n; - ;} + } +#line 27491 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1026: -#line 2857 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (9)].list), lappend((yyvsp[(3) - (9)].list), (yyvsp[(6) - (9)].node)), (yylsp[(1) - (9)])); + case 1035: /* func_application: func_name '(' func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause opt_ignore_nulls ')' */ +#line 2871 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall((yyvsp[-8].list), lappend((yyvsp[-6].list), (yyvsp[-3].node)), (yylsp[-8])); n->func_variadic = true; - n->agg_order = (yyvsp[(7) - (9)].list); - n->agg_ignore_nulls = (yyvsp[(8) - (9)].ignorenulls); + n->agg_order = (yyvsp[-2].list); + n->agg_ignore_nulls = (yyvsp[-1].ignorenulls); (yyval.node) = (PGNode *)n; - ;} + } +#line 27503 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1027: -#line 2865 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (7)].list), (yyvsp[(4) - (7)].list), (yylsp[(1) - (7)])); - n->agg_order = (yyvsp[(5) - (7)].list); - n->agg_ignore_nulls = (yyvsp[(6) - (7)].ignorenulls); + case 1036: /* func_application: func_name '(' ALL func_arg_list opt_sort_clause opt_ignore_nulls ')' */ +#line 2879 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall((yyvsp[-6].list), (yyvsp[-3].list), (yylsp[-6])); + n->agg_order = (yyvsp[-2].list); + n->agg_ignore_nulls = (yyvsp[-1].ignorenulls); /* Ideally we'd mark the PGFuncCall node to indicate * "must be an aggregate", but there's no provision * for that in PGFuncCall at the moment. */ (yyval.node) = (PGNode *)n; - ;} + } +#line 27518 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1028: -#line 2876 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (7)].list), (yyvsp[(4) - (7)].list), (yylsp[(1) - (7)])); - n->agg_order = (yyvsp[(5) - (7)].list); - n->agg_ignore_nulls = (yyvsp[(6) - (7)].ignorenulls); + case 1037: /* func_application: func_name '(' DISTINCT func_arg_list opt_sort_clause opt_ignore_nulls ')' */ +#line 2890 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall((yyvsp[-6].list), (yyvsp[-3].list), (yylsp[-6])); + n->agg_order = (yyvsp[-2].list); + n->agg_ignore_nulls = (yyvsp[-1].ignorenulls); n->agg_distinct = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 27530 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1029: -#line 2896 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = (PGFuncCall *) (yyvsp[(1) - (5)].node); + case 1038: /* func_expr: func_application within_group_clause filter_clause export_clause over_clause */ +#line 2910 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = (PGFuncCall *) (yyvsp[-4].node); /* * The order clause for WITHIN GROUP and the one for * plain-aggregate ORDER BY share a field, so we have to @@ -27499,107 +27541,118 @@ YYLTYPE yylloc; * location. Other consistency checks are deferred to * parse analysis. */ - if ((yyvsp[(2) - (5)].list) != NIL) + if ((yyvsp[-3].list) != NIL) { if (n->agg_order != NIL) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("cannot use multiple ORDER BY clauses with WITHIN GROUP"), - parser_errposition((yylsp[(2) - (5)])))); + parser_errposition((yylsp[-3])))); if (n->agg_distinct) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("cannot use DISTINCT with WITHIN GROUP"), - parser_errposition((yylsp[(2) - (5)])))); + parser_errposition((yylsp[-3])))); if (n->func_variadic) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("cannot use VARIADIC with WITHIN GROUP"), - parser_errposition((yylsp[(2) - (5)])))); - n->agg_order = (yyvsp[(2) - (5)].list); + parser_errposition((yylsp[-3])))); + n->agg_order = (yyvsp[-3].list); n->agg_within_group = true; } - n->agg_filter = (yyvsp[(3) - (5)].node); - n->export_state = (yyvsp[(4) - (5)].boolean); - n->over = (yyvsp[(5) - (5)].windef); + n->agg_filter = (yyvsp[-2].node); + n->export_state = (yyvsp[-1].boolean); + n->over = (yyvsp[0].windef); (yyval.node) = (PGNode *) n; - ;} + } +#line 27570 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1030: -#line 2932 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + case 1039: /* func_expr: func_expr_common_subexpr */ +#line 2946 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 27576 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1031: -#line 2942 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + case 1040: /* func_expr_windowless: func_application */ +#line 2956 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 27582 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1032: -#line 2943 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + case 1041: /* func_expr_windowless: func_expr_common_subexpr */ +#line 2957 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 27588 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1033: -#line 2951 "third_party/libpg_query/grammar/statements/select.y" - { + case 1042: /* func_expr_common_subexpr: COLLATION FOR '(' a_expr ')' */ +#line 2965 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("pg_collation_for"), - list_make1((yyvsp[(4) - (5)].node)), - (yylsp[(1) - (5)])); - ;} + list_make1((yyvsp[-1].node)), + (yylsp[-4])); + } +#line 27598 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1034: -#line 2957 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeTypeCast((yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].typnam), 0, (yylsp[(1) - (6)])); ;} + case 1043: /* func_expr_common_subexpr: CAST '(' a_expr AS Typename ')' */ +#line 2971 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeTypeCast((yyvsp[-3].node), (yyvsp[-1].typnam), 0, (yylsp[-5])); } +#line 27604 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1035: -#line 2959 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeTypeCast((yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].typnam), 1, (yylsp[(1) - (6)])); ;} + case 1044: /* func_expr_common_subexpr: TRY_CAST '(' a_expr AS Typename ')' */ +#line 2973 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeTypeCast((yyvsp[-3].node), (yyvsp[-1].typnam), 1, (yylsp[-5])); } +#line 27610 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1036: -#line 2961 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("date_part"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} + case 1045: /* func_expr_common_subexpr: EXTRACT '(' extract_list ')' */ +#line 2975 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("date_part"), (yyvsp[-1].list), (yylsp[-3])); + } +#line 27618 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1037: -#line 2965 "third_party/libpg_query/grammar/statements/select.y" - { + case 1046: /* func_expr_common_subexpr: OVERLAY '(' overlay_list ')' */ +#line 2979 "third_party/libpg_query/grammar/statements/select.y" + { /* overlay(A PLACING B FROM C FOR D) is converted to * overlay(A, B, C, D) * overlay(A PLACING B FROM C) is converted to * overlay(A, B, C) */ - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("overlay"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("overlay"), (yyvsp[-1].list), (yylsp[-3])); + } +#line 27631 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1038: -#line 2974 "third_party/libpg_query/grammar/statements/select.y" - { + case 1047: /* func_expr_common_subexpr: POSITION '(' position_list ')' */ +#line 2988 "third_party/libpg_query/grammar/statements/select.y" + { /* position(A in B) is converted to position_inverse(A, B) */ - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("__internal_position_operator"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("__internal_position_operator"), (yyvsp[-1].list), (yylsp[-3])); + } +#line 27640 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1039: -#line 2979 "third_party/libpg_query/grammar/statements/select.y" - { + case 1048: /* func_expr_common_subexpr: SUBSTRING '(' substr_list ')' */ +#line 2993 "third_party/libpg_query/grammar/statements/select.y" + { /* substring(A from B for C) is converted to * substring(A, B, C) - thomas 2000-11-28 */ - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("substring"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("substring"), (yyvsp[-1].list), (yylsp[-3])); + } +#line 27651 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1040: -#line 2986 "third_party/libpg_query/grammar/statements/select.y" - { + case 1049: /* func_expr_common_subexpr: TREAT '(' a_expr AS Typename ')' */ +#line 3000 "third_party/libpg_query/grammar/statements/select.y" + { /* TREAT(expr AS target) converts expr of a particular type to target, * which is defined to be a subtype of the original expression. * In SQL99, this is intended for use with structured UDTs, @@ -27609,288 +27662,322 @@ YYLTYPE yylloc; * Convert SystemTypeName() to SystemFuncName() even though * at the moment they result in the same thing. */ - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName(((PGValue *)llast((yyvsp[(5) - (6)].typnam)->names))->val.str), - list_make1((yyvsp[(3) - (6)].node)), - (yylsp[(1) - (6)])); - ;} + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName(((PGValue *)llast((yyvsp[-1].typnam)->names))->val.str), + list_make1((yyvsp[-3].node)), + (yylsp[-5])); + } +#line 27670 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1041: -#line 3001 "third_party/libpg_query/grammar/statements/select.y" - { + case 1050: /* func_expr_common_subexpr: TRIM '(' BOTH trim_list ')' */ +#line 3015 "third_party/libpg_query/grammar/statements/select.y" + { /* various trim expressions are defined in SQL * - thomas 1997-07-19 */ - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("trim"), (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); - ;} + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("trim"), (yyvsp[-1].list), (yylsp[-4])); + } +#line 27681 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1042: -#line 3008 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("ltrim"), (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); - ;} + case 1051: /* func_expr_common_subexpr: TRIM '(' LEADING trim_list ')' */ +#line 3022 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("ltrim"), (yyvsp[-1].list), (yylsp[-4])); + } +#line 27689 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1043: -#line 3012 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("rtrim"), (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); - ;} + case 1052: /* func_expr_common_subexpr: TRIM '(' TRAILING trim_list ')' */ +#line 3026 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("rtrim"), (yyvsp[-1].list), (yylsp[-4])); + } +#line 27697 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1044: -#line 3016 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("trim"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} + case 1053: /* func_expr_common_subexpr: TRIM '(' trim_list ')' */ +#line 3030 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("trim"), (yyvsp[-1].list), (yylsp[-3])); + } +#line 27705 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1045: -#line 3020 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NULLIF, "=", (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node), (yylsp[(1) - (6)])); - ;} + case 1054: /* func_expr_common_subexpr: NULLIF '(' a_expr ',' a_expr ')' */ +#line 3034 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NULLIF, "=", (yyvsp[-3].node), (yyvsp[-1].node), (yylsp[-5])); + } +#line 27713 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1046: -#line 3024 "third_party/libpg_query/grammar/statements/select.y" - { + case 1055: /* func_expr_common_subexpr: COALESCE '(' expr_list_opt_comma ')' */ +#line 3038 "third_party/libpg_query/grammar/statements/select.y" + { PGCoalesceExpr *c = makeNode(PGCoalesceExpr); - c->args = (yyvsp[(3) - (4)].list); - c->location = (yylsp[(1) - (4)]); + c->args = (yyvsp[-1].list); + c->location = (yylsp[-3]); (yyval.node) = (PGNode *)c; - ;} + } +#line 27724 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1047: -#line 3034 "third_party/libpg_query/grammar/statements/select.y" - { + case 1056: /* list_comprehension: '[' a_expr FOR ColId IN_P a_expr ']' */ +#line 3048 "third_party/libpg_query/grammar/statements/select.y" + { PGLambdaFunction *lambda = makeNode(PGLambdaFunction); - lambda->lhs = makeColumnRef((yyvsp[(4) - (7)].str), NIL, (yylsp[(4) - (7)]), yyscanner); - lambda->rhs = (yyvsp[(2) - (7)].node); - lambda->location = (yylsp[(1) - (7)]); - PGFuncCall *n = makeFuncCall(SystemFuncName("list_apply"), list_make2((yyvsp[(6) - (7)].node), lambda), (yylsp[(1) - (7)])); + lambda->lhs = makeColumnRef((yyvsp[-3].str), NIL, (yylsp[-3]), yyscanner); + lambda->rhs = (yyvsp[-5].node); + lambda->location = (yylsp[-6]); + PGFuncCall *n = makeFuncCall(SystemFuncName("list_apply"), list_make2((yyvsp[-1].node), lambda), (yylsp[-6])); (yyval.node) = (PGNode *) n; - ;} + } +#line 27737 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1048: -#line 3043 "third_party/libpg_query/grammar/statements/select.y" - { + case 1057: /* list_comprehension: '[' a_expr FOR ColId IN_P c_expr IF_P a_expr ']' */ +#line 3057 "third_party/libpg_query/grammar/statements/select.y" + { PGLambdaFunction *lambda = makeNode(PGLambdaFunction); - lambda->lhs = makeColumnRef((yyvsp[(4) - (9)].str), NIL, (yylsp[(4) - (9)]), yyscanner); - lambda->rhs = (yyvsp[(2) - (9)].node); - lambda->location = (yylsp[(1) - (9)]); + lambda->lhs = makeColumnRef((yyvsp[-5].str), NIL, (yylsp[-5]), yyscanner); + lambda->rhs = (yyvsp[-7].node); + lambda->location = (yylsp[-8]); PGLambdaFunction *lambda_filter = makeNode(PGLambdaFunction); - lambda_filter->lhs = makeColumnRef((yyvsp[(4) - (9)].str), NIL, (yylsp[(4) - (9)]), yyscanner); - lambda_filter->rhs = (yyvsp[(8) - (9)].node); - lambda_filter->location = (yylsp[(8) - (9)]); - PGFuncCall *filter = makeFuncCall(SystemFuncName("list_filter"), list_make2((yyvsp[(6) - (9)].node), lambda_filter), (yylsp[(1) - (9)])); - PGFuncCall *n = makeFuncCall(SystemFuncName("list_apply"), list_make2(filter, lambda), (yylsp[(1) - (9)])); + lambda_filter->lhs = makeColumnRef((yyvsp[-5].str), NIL, (yylsp[-5]), yyscanner); + lambda_filter->rhs = (yyvsp[-1].node); + lambda_filter->location = (yylsp[-1]); + PGFuncCall *filter = makeFuncCall(SystemFuncName("list_filter"), list_make2((yyvsp[-3].node), lambda_filter), (yylsp[-8])); + PGFuncCall *n = makeFuncCall(SystemFuncName("list_apply"), list_make2(filter, lambda), (yylsp[-8])); (yyval.node) = (PGNode *) n; - ;} + } +#line 27756 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1049: -#line 3064 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(4) - (5)].list); ;} + case 1058: /* within_group_clause: WITHIN GROUP_P '(' sort_clause ')' */ +#line 3078 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 27762 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1050: -#line 3065 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1059: /* within_group_clause: %empty */ +#line 3079 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 27768 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1051: -#line 3069 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(4) - (5)].node); ;} + case 1060: /* filter_clause: FILTER '(' WHERE a_expr ')' */ +#line 3083 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[-1].node); } +#line 27774 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1052: -#line 3070 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(3) - (4)].node); ;} + case 1061: /* filter_clause: FILTER '(' a_expr ')' */ +#line 3084 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[-1].node); } +#line 27780 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1053: -#line 3071 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + case 1062: /* filter_clause: %empty */ +#line 3085 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; } +#line 27786 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1054: -#line 3075 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} + case 1063: /* export_clause: EXPORT_STATE */ +#line 3089 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = true; } +#line 27792 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1055: -#line 3076 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} + case 1064: /* export_clause: %empty */ +#line 3090 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = false; } +#line 27798 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1056: -#line 3083 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + case 1065: /* window_clause: WINDOW window_definition_list */ +#line 3097 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 27804 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1057: -#line 3084 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1066: /* window_clause: %empty */ +#line 3098 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 27810 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1058: -#line 3088 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].windef)); ;} + case 1067: /* window_definition_list: window_definition */ +#line 3102 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[0].windef)); } +#line 27816 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1059: -#line 3090 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].windef)); ;} + case 1068: /* window_definition_list: window_definition_list ',' window_definition */ +#line 3104 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].windef)); } +#line 27822 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1060: -#line 3095 "third_party/libpg_query/grammar/statements/select.y" - { - PGWindowDef *n = (yyvsp[(3) - (3)].windef); - n->name = (yyvsp[(1) - (3)].str); + case 1069: /* window_definition: ColId AS window_specification */ +#line 3109 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = (yyvsp[0].windef); + n->name = (yyvsp[-2].str); (yyval.windef) = n; - ;} + } +#line 27832 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1061: -#line 3103 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.windef) = (yyvsp[(2) - (2)].windef); ;} + case 1070: /* over_clause: OVER window_specification */ +#line 3117 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.windef) = (yyvsp[0].windef); } +#line 27838 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1062: -#line 3105 "third_party/libpg_query/grammar/statements/select.y" - { + case 1071: /* over_clause: OVER ColId */ +#line 3119 "third_party/libpg_query/grammar/statements/select.y" + { PGWindowDef *n = makeNode(PGWindowDef); - n->name = (yyvsp[(2) - (2)].str); + n->name = (yyvsp[0].str); n->refname = NULL; n->partitionClause = NIL; n->orderClause = NIL; n->frameOptions = FRAMEOPTION_DEFAULTS; n->startOffset = NULL; n->endOffset = NULL; - n->location = (yylsp[(2) - (2)]); + n->location = (yylsp[0]); (yyval.windef) = n; - ;} + } +#line 27855 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1063: -#line 3118 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.windef) = NULL; ;} + case 1072: /* over_clause: %empty */ +#line 3132 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.windef) = NULL; } +#line 27861 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1064: -#line 3123 "third_party/libpg_query/grammar/statements/select.y" - { + case 1073: /* window_specification: '(' opt_existing_window_name opt_partition_clause opt_sort_clause opt_frame_clause ')' */ +#line 3137 "third_party/libpg_query/grammar/statements/select.y" + { PGWindowDef *n = makeNode(PGWindowDef); n->name = NULL; - n->refname = (yyvsp[(2) - (6)].str); - n->partitionClause = (yyvsp[(3) - (6)].list); - n->orderClause = (yyvsp[(4) - (6)].list); + n->refname = (yyvsp[-4].str); + n->partitionClause = (yyvsp[-3].list); + n->orderClause = (yyvsp[-2].list); /* copy relevant fields of opt_frame_clause */ - n->frameOptions = (yyvsp[(5) - (6)].windef)->frameOptions; - n->startOffset = (yyvsp[(5) - (6)].windef)->startOffset; - n->endOffset = (yyvsp[(5) - (6)].windef)->endOffset; - n->location = (yylsp[(1) - (6)]); + n->frameOptions = (yyvsp[-1].windef)->frameOptions; + n->startOffset = (yyvsp[-1].windef)->startOffset; + n->endOffset = (yyvsp[-1].windef)->endOffset; + n->location = (yylsp[-5]); (yyval.windef) = n; - ;} + } +#line 27879 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1065: -#line 3148 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1074: /* opt_existing_window_name: ColId */ +#line 3162 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[0].str); } +#line 27885 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1066: -#line 3149 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = NULL; ;} + case 1075: /* opt_existing_window_name: %empty */ +#line 3163 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = NULL; } +#line 27891 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1067: -#line 3152 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (3)].list); ;} + case 1076: /* opt_partition_clause: PARTITION BY expr_list */ +#line 3166 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 27897 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1068: -#line 3153 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1077: /* opt_partition_clause: %empty */ +#line 3167 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 27903 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1069: -#line 3162 "third_party/libpg_query/grammar/statements/select.y" - { - PGWindowDef *n = (yyvsp[(2) - (3)].windef); + case 1078: /* opt_frame_clause: RANGE frame_extent opt_window_exclusion_clause */ +#line 3176 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = (yyvsp[-1].windef); n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_RANGE; - n->frameOptions |= (yyvsp[(3) - (3)].ival); + n->frameOptions |= (yyvsp[0].ival); (yyval.windef) = n; - ;} + } +#line 27915 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1070: -#line 3170 "third_party/libpg_query/grammar/statements/select.y" - { - PGWindowDef *n = (yyvsp[(2) - (3)].windef); + case 1079: /* opt_frame_clause: ROWS frame_extent opt_window_exclusion_clause */ +#line 3184 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = (yyvsp[-1].windef); n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_ROWS; - n->frameOptions |= (yyvsp[(3) - (3)].ival); + n->frameOptions |= (yyvsp[0].ival); (yyval.windef) = n; - ;} + } +#line 27927 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1071: -#line 3178 "third_party/libpg_query/grammar/statements/select.y" - { - PGWindowDef *n = (yyvsp[(2) - (3)].windef); + case 1080: /* opt_frame_clause: GROUPS frame_extent opt_window_exclusion_clause */ +#line 3192 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = (yyvsp[-1].windef); n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_GROUPS; - n->frameOptions |= (yyvsp[(3) - (3)].ival); + n->frameOptions |= (yyvsp[0].ival); (yyval.windef) = n; - ;} + } +#line 27939 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1072: -#line 3186 "third_party/libpg_query/grammar/statements/select.y" - { + case 1081: /* opt_frame_clause: %empty */ +#line 3200 "third_party/libpg_query/grammar/statements/select.y" + { PGWindowDef *n = makeNode(PGWindowDef); n->frameOptions = FRAMEOPTION_DEFAULTS; n->startOffset = NULL; n->endOffset = NULL; (yyval.windef) = n; - ;} + } +#line 27952 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1073: -#line 3197 "third_party/libpg_query/grammar/statements/select.y" - { - PGWindowDef *n = (yyvsp[(1) - (1)].windef); + case 1082: /* frame_extent: frame_bound */ +#line 3211 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = (yyvsp[0].windef); /* reject invalid cases */ if (n->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) ereport(ERROR, (errcode(PG_ERRCODE_WINDOWING_ERROR), errmsg("frame start cannot be UNBOUNDED FOLLOWING"), - parser_errposition((yylsp[(1) - (1)])))); + parser_errposition((yylsp[0])))); if (n->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING) ereport(ERROR, (errcode(PG_ERRCODE_WINDOWING_ERROR), errmsg("frame starting from following row cannot end with current row"), - parser_errposition((yylsp[(1) - (1)])))); + parser_errposition((yylsp[0])))); n->frameOptions |= FRAMEOPTION_END_CURRENT_ROW; (yyval.windef) = n; - ;} + } +#line 27974 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1074: -#line 3215 "third_party/libpg_query/grammar/statements/select.y" - { - PGWindowDef *n1 = (yyvsp[(2) - (4)].windef); - PGWindowDef *n2 = (yyvsp[(4) - (4)].windef); + case 1083: /* frame_extent: BETWEEN frame_bound AND frame_bound */ +#line 3229 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n1 = (yyvsp[-2].windef); + PGWindowDef *n2 = (yyvsp[0].windef); /* form merged options */ int frameOptions = n1->frameOptions; @@ -27902,631 +27989,738 @@ YYLTYPE yylloc; ereport(ERROR, (errcode(PG_ERRCODE_WINDOWING_ERROR), errmsg("frame start cannot be UNBOUNDED FOLLOWING"), - parser_errposition((yylsp[(2) - (4)])))); + parser_errposition((yylsp[-2])))); if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) ereport(ERROR, (errcode(PG_ERRCODE_WINDOWING_ERROR), errmsg("frame end cannot be UNBOUNDED PRECEDING"), - parser_errposition((yylsp[(4) - (4)])))); + parser_errposition((yylsp[0])))); if ((frameOptions & FRAMEOPTION_START_CURRENT_ROW) && (frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING)) ereport(ERROR, (errcode(PG_ERRCODE_WINDOWING_ERROR), errmsg("frame starting from current row cannot have preceding rows"), - parser_errposition((yylsp[(4) - (4)])))); + parser_errposition((yylsp[0])))); if ((frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING) && (frameOptions & (FRAMEOPTION_END_OFFSET_PRECEDING | FRAMEOPTION_END_CURRENT_ROW))) ereport(ERROR, (errcode(PG_ERRCODE_WINDOWING_ERROR), errmsg("frame starting from following row cannot have preceding rows"), - parser_errposition((yylsp[(4) - (4)])))); + parser_errposition((yylsp[0])))); n1->frameOptions = frameOptions; n1->endOffset = n2->startOffset; (yyval.windef) = n1; - ;} + } +#line 28016 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1075: -#line 3261 "third_party/libpg_query/grammar/statements/select.y" - { + case 1084: /* frame_bound: UNBOUNDED PRECEDING */ +#line 3275 "third_party/libpg_query/grammar/statements/select.y" + { PGWindowDef *n = makeNode(PGWindowDef); n->frameOptions = FRAMEOPTION_START_UNBOUNDED_PRECEDING; n->startOffset = NULL; n->endOffset = NULL; (yyval.windef) = n; - ;} + } +#line 28029 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1076: -#line 3270 "third_party/libpg_query/grammar/statements/select.y" - { + case 1085: /* frame_bound: UNBOUNDED FOLLOWING */ +#line 3284 "third_party/libpg_query/grammar/statements/select.y" + { PGWindowDef *n = makeNode(PGWindowDef); n->frameOptions = FRAMEOPTION_START_UNBOUNDED_FOLLOWING; n->startOffset = NULL; n->endOffset = NULL; (yyval.windef) = n; - ;} + } +#line 28042 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1077: -#line 3279 "third_party/libpg_query/grammar/statements/select.y" - { + case 1086: /* frame_bound: CURRENT_P ROW */ +#line 3293 "third_party/libpg_query/grammar/statements/select.y" + { PGWindowDef *n = makeNode(PGWindowDef); n->frameOptions = FRAMEOPTION_START_CURRENT_ROW; n->startOffset = NULL; n->endOffset = NULL; (yyval.windef) = n; - ;} + } +#line 28055 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1078: -#line 3288 "third_party/libpg_query/grammar/statements/select.y" - { + case 1087: /* frame_bound: a_expr PRECEDING */ +#line 3302 "third_party/libpg_query/grammar/statements/select.y" + { PGWindowDef *n = makeNode(PGWindowDef); n->frameOptions = FRAMEOPTION_START_OFFSET_PRECEDING; - n->startOffset = (yyvsp[(1) - (2)].node); + n->startOffset = (yyvsp[-1].node); n->endOffset = NULL; (yyval.windef) = n; - ;} + } +#line 28068 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1079: -#line 3297 "third_party/libpg_query/grammar/statements/select.y" - { + case 1088: /* frame_bound: a_expr FOLLOWING */ +#line 3311 "third_party/libpg_query/grammar/statements/select.y" + { PGWindowDef *n = makeNode(PGWindowDef); n->frameOptions = FRAMEOPTION_START_OFFSET_FOLLOWING; - n->startOffset = (yyvsp[(1) - (2)].node); + n->startOffset = (yyvsp[-1].node); n->endOffset = NULL; (yyval.windef) = n; - ;} + } +#line 28081 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1080: -#line 3308 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = FRAMEOPTION_EXCLUDE_CURRENT_ROW; ;} + case 1089: /* opt_window_exclusion_clause: EXCLUDE CURRENT_P ROW */ +#line 3322 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = FRAMEOPTION_EXCLUDE_CURRENT_ROW; } +#line 28087 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1081: -#line 3309 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = FRAMEOPTION_EXCLUDE_GROUP; ;} + case 1090: /* opt_window_exclusion_clause: EXCLUDE GROUP_P */ +#line 3323 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = FRAMEOPTION_EXCLUDE_GROUP; } +#line 28093 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1082: -#line 3310 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = FRAMEOPTION_EXCLUDE_TIES; ;} + case 1091: /* opt_window_exclusion_clause: EXCLUDE TIES */ +#line 3324 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = FRAMEOPTION_EXCLUDE_TIES; } +#line 28099 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1083: -#line 3311 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = 0; ;} + case 1092: /* opt_window_exclusion_clause: EXCLUDE NO OTHERS */ +#line 3325 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = 0; } +#line 28105 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1084: -#line 3312 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = 0; ;} + case 1093: /* opt_window_exclusion_clause: %empty */ +#line 3326 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = 0; } +#line 28111 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1085: -#line 3326 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + case 1094: /* qualified_row: ROW '(' expr_list_opt_comma ')' */ +#line 3340 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 28117 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1086: -#line 3327 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1095: /* qualified_row: ROW '(' ')' */ +#line 3341 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 28123 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1087: -#line 3330 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list);;} + case 1096: /* row: qualified_row */ +#line 3344 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list);} +#line 28129 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1088: -#line 3331 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(2) - (5)].list), (yyvsp[(4) - (5)].node)); ;} + case 1097: /* row: '(' expr_list ',' a_expr ')' */ +#line 3345 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-3].list), (yyvsp[-1].node)); } +#line 28135 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1089: -#line 3335 "third_party/libpg_query/grammar/statements/select.y" - { + case 1098: /* dict_arg: ColIdOrString ':' a_expr */ +#line 3349 "third_party/libpg_query/grammar/statements/select.y" + { PGNamedArgExpr *na = makeNode(PGNamedArgExpr); - na->name = (yyvsp[(1) - (3)].str); - na->arg = (PGExpr *) (yyvsp[(3) - (3)].node); + na->name = (yyvsp[-2].str); + na->arg = (PGExpr *) (yyvsp[0].node); na->argnumber = -1; - na->location = (yylsp[(1) - (3)]); + na->location = (yylsp[-2]); (yyval.node) = (PGNode *) na; - ;} + } +#line 28148 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1090: -#line 3345 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + case 1099: /* dict_arguments: dict_arg */ +#line 3359 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 28154 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1091: -#line 3346 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + case 1100: /* dict_arguments: dict_arguments ',' dict_arg */ +#line 3360 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); } +#line 28160 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1092: -#line 3350 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + case 1101: /* dict_arguments_opt_comma: dict_arguments */ +#line 3364 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 28166 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1093: -#line 3351 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + case 1102: /* dict_arguments_opt_comma: dict_arguments ',' */ +#line 3365 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 28172 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1094: -#line 3356 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make2((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); - ;} + case 1103: /* map_arg: a_expr ':' a_expr */ +#line 3370 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make2((yyvsp[-2].node), (yyvsp[0].node)); + } +#line 28180 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1095: -#line 3362 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].list)); ;} + case 1104: /* map_arguments: map_arg */ +#line 3376 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[0].list)); } +#line 28186 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1096: -#line 3363 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} + case 1105: /* map_arguments: map_arguments ',' map_arg */ +#line 3377 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].list)); } +#line 28192 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1097: -#line 3368 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + case 1106: /* map_arguments_opt_comma: map_arguments */ +#line 3382 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 28198 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1098: -#line 3369 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + case 1107: /* map_arguments_opt_comma: map_arguments ',' */ +#line 3383 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 28204 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1099: -#line 3374 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + case 1108: /* opt_map_arguments_opt_comma: map_arguments_opt_comma */ +#line 3388 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 28210 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1100: -#line 3375 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NULL; ;} + case 1109: /* opt_map_arguments_opt_comma: %empty */ +#line 3389 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NULL; } +#line 28216 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1101: -#line 3378 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.subquerytype) = PG_ANY_SUBLINK; ;} + case 1110: /* sub_type: ANY */ +#line 3392 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.subquerytype) = PG_ANY_SUBLINK; } +#line 28222 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1102: -#line 3379 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.subquerytype) = PG_ANY_SUBLINK; ;} + case 1111: /* sub_type: SOME */ +#line 3393 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.subquerytype) = PG_ANY_SUBLINK; } +#line 28228 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1103: -#line 3380 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.subquerytype) = PG_ALL_SUBLINK; ;} + case 1112: /* sub_type: ALL */ +#line 3394 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.subquerytype) = PG_ALL_SUBLINK; } +#line 28234 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1104: -#line 3383 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1113: /* all_Op: Op */ +#line 3397 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[0].str); } +#line 28240 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1105: -#line 3384 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) (yyvsp[(1) - (1)].conststr); ;} + case 1114: /* all_Op: MathOp */ +#line 3398 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) (yyvsp[0].conststr); } +#line 28246 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1106: -#line 3387 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "+"; ;} + case 1115: /* MathOp: '+' */ +#line 3401 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "+"; } +#line 28252 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1107: -#line 3388 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "-"; ;} + case 1116: /* MathOp: '-' */ +#line 3402 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "-"; } +#line 28258 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1108: -#line 3389 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "*"; ;} + case 1117: /* MathOp: '*' */ +#line 3403 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "*"; } +#line 28264 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1109: -#line 3390 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "/"; ;} + case 1118: /* MathOp: '/' */ +#line 3404 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "/"; } +#line 28270 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1110: -#line 3391 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "//"; ;} + case 1119: /* MathOp: INTEGER_DIVISION */ +#line 3405 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "//"; } +#line 28276 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1111: -#line 3392 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "%"; ;} + case 1120: /* MathOp: '%' */ +#line 3406 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "%"; } +#line 28282 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1112: -#line 3393 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "^"; ;} + case 1121: /* MathOp: '^' */ +#line 3407 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "^"; } +#line 28288 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1113: -#line 3394 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "**"; ;} + case 1122: /* MathOp: POWER_OF */ +#line 3408 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "**"; } +#line 28294 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1114: -#line 3395 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "<"; ;} + case 1123: /* MathOp: '<' */ +#line 3409 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "<"; } +#line 28300 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1115: -#line 3396 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = ">"; ;} + case 1124: /* MathOp: '>' */ +#line 3410 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = ">"; } +#line 28306 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1116: -#line 3397 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "="; ;} + case 1125: /* MathOp: '=' */ +#line 3411 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "="; } +#line 28312 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1117: -#line 3398 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "<="; ;} + case 1126: /* MathOp: LESS_EQUALS */ +#line 3412 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "<="; } +#line 28318 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1118: -#line 3399 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = ">="; ;} + case 1127: /* MathOp: GREATER_EQUALS */ +#line 3413 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = ">="; } +#line 28324 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1119: -#line 3400 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "<>"; ;} + case 1128: /* MathOp: NOT_EQUALS */ +#line 3414 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "<>"; } +#line 28330 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1120: -#line 3404 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + case 1129: /* qual_Op: Op */ +#line 3418 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[0].str))); } +#line 28336 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1121: -#line 3406 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + case 1130: /* qual_Op: OPERATOR '(' any_operator ')' */ +#line 3420 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 28342 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1122: -#line 3411 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + case 1131: /* qual_all_Op: all_Op */ +#line 3425 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[0].str))); } +#line 28348 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1123: -#line 3413 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + case 1132: /* qual_all_Op: OPERATOR '(' any_operator ')' */ +#line 3427 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 28354 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1124: -#line 3418 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + case 1133: /* subquery_Op: all_Op */ +#line 3432 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[0].str))); } +#line 28360 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1125: -#line 3420 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + case 1134: /* subquery_Op: OPERATOR '(' any_operator ')' */ +#line 3434 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 28366 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1126: -#line 3422 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("~~")); ;} + case 1135: /* subquery_Op: LIKE */ +#line 3436 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("~~")); } +#line 28372 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1127: -#line 3424 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("!~~")); ;} + case 1136: /* subquery_Op: NOT_LA LIKE */ +#line 3438 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("!~~")); } +#line 28378 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1128: -#line 3426 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("~~~")); ;} + case 1137: /* subquery_Op: GLOB */ +#line 3440 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("~~~")); } +#line 28384 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1129: -#line 3428 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("!~~~")); ;} + case 1138: /* subquery_Op: NOT_LA GLOB */ +#line 3442 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("!~~~")); } +#line 28390 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1130: -#line 3430 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("~~*")); ;} + case 1139: /* subquery_Op: ILIKE */ +#line 3444 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("~~*")); } +#line 28396 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1131: -#line 3432 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("!~~*")); ;} + case 1140: /* subquery_Op: NOT_LA ILIKE */ +#line 3446 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("!~~*")); } +#line 28402 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1132: -#line 3446 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + case 1141: /* any_operator: all_Op */ +#line 3460 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[0].str))); } +#line 28408 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1133: -#line 3448 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lcons(makeString((yyvsp[(1) - (3)].str)), (yyvsp[(3) - (3)].list)); ;} + case 1142: /* any_operator: ColId '.' any_operator */ +#line 3462 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lcons(makeString((yyvsp[-2].str)), (yyvsp[0].list)); } +#line 28414 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1134: -#line 3453 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} + case 1143: /* c_expr_list: c_expr */ +#line 3467 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1((yyvsp[0].node)); + } +#line 28422 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1135: -#line 3457 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} + case 1144: /* c_expr_list: c_expr_list ',' c_expr */ +#line 3471 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); + } +#line 28430 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1136: -#line 3464 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(1) - (1)].list); - ;} + case 1145: /* c_expr_list_opt_comma: c_expr_list */ +#line 3478 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = (yyvsp[0].list); + } +#line 28438 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1137: -#line 3469 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(1) - (2)].list); - ;} + case 1146: /* c_expr_list_opt_comma: c_expr_list ',' */ +#line 3483 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = (yyvsp[-1].list); + } +#line 28446 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1138: -#line 3475 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} + case 1147: /* expr_list: a_expr */ +#line 3489 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1((yyvsp[0].node)); + } +#line 28454 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1139: -#line 3479 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} + case 1148: /* expr_list: expr_list ',' a_expr */ +#line 3493 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); + } +#line 28462 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1140: -#line 3486 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(1) - (1)].list); - ;} + case 1149: /* expr_list_opt_comma: expr_list */ +#line 3500 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = (yyvsp[0].list); + } +#line 28470 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1141: -#line 3491 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(1) - (2)].list); - ;} + case 1150: /* expr_list_opt_comma: expr_list ',' */ +#line 3505 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = (yyvsp[-1].list); + } +#line 28478 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1142: -#line 3498 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(1) - (1)].list); - ;} + case 1151: /* opt_expr_list_opt_comma: expr_list_opt_comma */ +#line 3512 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = (yyvsp[0].list); + } +#line 28486 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1143: -#line 3502 "third_party/libpg_query/grammar/statements/select.y" - { + case 1152: /* opt_expr_list_opt_comma: %empty */ +#line 3516 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NULL; - ;} + } +#line 28494 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1144: -#line 3511 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} + case 1153: /* func_arg_list: func_arg_expr */ +#line 3525 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1((yyvsp[0].node)); + } +#line 28502 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1145: -#line 3515 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} + case 1154: /* func_arg_list: func_arg_list ',' func_arg_expr */ +#line 3529 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); + } +#line 28510 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1146: -#line 3521 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(1) - (1)].node); - ;} + case 1155: /* func_arg_expr: a_expr */ +#line 3535 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (yyvsp[0].node); + } +#line 28518 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1147: -#line 3525 "third_party/libpg_query/grammar/statements/select.y" - { + case 1156: /* func_arg_expr: param_name COLON_EQUALS a_expr */ +#line 3539 "third_party/libpg_query/grammar/statements/select.y" + { PGNamedArgExpr *na = makeNode(PGNamedArgExpr); - na->name = (yyvsp[(1) - (3)].str); - na->arg = (PGExpr *) (yyvsp[(3) - (3)].node); + na->name = (yyvsp[-2].str); + na->arg = (PGExpr *) (yyvsp[0].node); na->argnumber = -1; /* until determined */ - na->location = (yylsp[(1) - (3)]); + na->location = (yylsp[-2]); (yyval.node) = (PGNode *) na; - ;} + } +#line 28531 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1148: -#line 3534 "third_party/libpg_query/grammar/statements/select.y" - { + case 1157: /* func_arg_expr: param_name EQUALS_GREATER a_expr */ +#line 3548 "third_party/libpg_query/grammar/statements/select.y" + { PGNamedArgExpr *na = makeNode(PGNamedArgExpr); - na->name = (yyvsp[(1) - (3)].str); - na->arg = (PGExpr *) (yyvsp[(3) - (3)].node); + na->name = (yyvsp[-2].str); + na->arg = (PGExpr *) (yyvsp[0].node); na->argnumber = -1; /* until determined */ - na->location = (yylsp[(1) - (3)]); + na->location = (yylsp[-2]); (yyval.node) = (PGNode *) na; - ;} + } +#line 28544 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1149: -#line 3544 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].typnam)); ;} + case 1158: /* type_list: Typename */ +#line 3558 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[0].typnam)); } +#line 28550 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1150: -#line 3545 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].typnam)); ;} + case 1159: /* type_list: type_list ',' Typename */ +#line 3559 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].typnam)); } +#line 28556 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1151: -#line 3550 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make2(makeStringConst((yyvsp[(1) - (3)].str), (yylsp[(1) - (3)])), (yyvsp[(3) - (3)].node)); - ;} + case 1160: /* extract_list: extract_arg FROM a_expr */ +#line 3564 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make2(makeStringConst((yyvsp[-2].str), (yylsp[-2])), (yyvsp[0].node)); + } +#line 28564 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1152: -#line 3553 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1161: /* extract_list: %empty */ +#line 3567 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 28570 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1153: -#line 3560 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1162: /* extract_arg: IDENT */ +#line 3574 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[0].str); } +#line 28576 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1154: -#line 3561 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "year"; ;} + case 1163: /* extract_arg: year_keyword */ +#line 3575 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "year"; } +#line 28582 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1155: -#line 3562 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "month"; ;} + case 1164: /* extract_arg: month_keyword */ +#line 3576 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "month"; } +#line 28588 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1156: -#line 3563 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "day"; ;} + case 1165: /* extract_arg: day_keyword */ +#line 3577 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "day"; } +#line 28594 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1157: -#line 3564 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "hour"; ;} + case 1166: /* extract_arg: hour_keyword */ +#line 3578 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "hour"; } +#line 28600 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1158: -#line 3565 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "minute"; ;} + case 1167: /* extract_arg: minute_keyword */ +#line 3579 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "minute"; } +#line 28606 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1159: -#line 3566 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "second"; ;} + case 1168: /* extract_arg: second_keyword */ +#line 3580 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "second"; } +#line 28612 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1160: -#line 3567 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "millisecond"; ;} + case 1169: /* extract_arg: millisecond_keyword */ +#line 3581 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "millisecond"; } +#line 28618 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1161: -#line 3568 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "microsecond"; ;} + case 1170: /* extract_arg: microsecond_keyword */ +#line 3582 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "microsecond"; } +#line 28624 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1162: -#line 3569 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "week"; ;} + case 1171: /* extract_arg: week_keyword */ +#line 3583 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "week"; } +#line 28630 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1163: -#line 3570 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "decade"; ;} + case 1172: /* extract_arg: quarter_keyword */ +#line 3584 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "quarter"; } +#line 28636 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1164: -#line 3571 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "century"; ;} + case 1173: /* extract_arg: decade_keyword */ +#line 3585 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "decade"; } +#line 28642 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1165: -#line 3572 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "millennium"; ;} + case 1174: /* extract_arg: century_keyword */ +#line 3586 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "century"; } +#line 28648 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1166: -#line 3573 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1175: /* extract_arg: millennium_keyword */ +#line 3587 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "millennium"; } +#line 28654 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1167: -#line 3584 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make4((yyvsp[(1) - (4)].node), (yyvsp[(2) - (4)].node), (yyvsp[(3) - (4)].node), (yyvsp[(4) - (4)].node)); - ;} + case 1176: /* extract_arg: Sconst */ +#line 3588 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[0].str); } +#line 28660 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1168: -#line 3588 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make3((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].node), (yyvsp[(3) - (3)].node)); - ;} + case 1177: /* overlay_list: a_expr overlay_placing substr_from substr_for */ +#line 3599 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make4((yyvsp[-3].node), (yyvsp[-2].node), (yyvsp[-1].node), (yyvsp[0].node)); + } +#line 28668 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1169: -#line 3595 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + case 1178: /* overlay_list: a_expr overlay_placing substr_from */ +#line 3603 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make3((yyvsp[-2].node), (yyvsp[-1].node), (yyvsp[0].node)); + } +#line 28676 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1170: -#line 3601 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); ;} + case 1179: /* overlay_placing: PLACING a_expr */ +#line 3610 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 28682 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1171: -#line 3602 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1180: /* position_list: b_expr IN_P b_expr */ +#line 3616 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make2((yyvsp[-2].node), (yyvsp[0].node)); } +#line 28688 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1172: -#line 3619 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make3((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].node), (yyvsp[(3) - (3)].node)); - ;} + case 1181: /* position_list: %empty */ +#line 3617 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 28694 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1173: -#line 3623 "third_party/libpg_query/grammar/statements/select.y" - { + case 1182: /* substr_list: a_expr substr_from substr_for */ +#line 3634 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make3((yyvsp[-2].node), (yyvsp[-1].node), (yyvsp[0].node)); + } +#line 28702 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 1183: /* substr_list: a_expr substr_for substr_from */ +#line 3638 "third_party/libpg_query/grammar/statements/select.y" + { /* not legal per SQL99, but might as well allow it */ - (yyval.list) = list_make3((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yyvsp[(2) - (3)].node)); - ;} + (yyval.list) = list_make3((yyvsp[-2].node), (yyvsp[0].node), (yyvsp[-1].node)); + } +#line 28711 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1174: -#line 3628 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make2((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); - ;} + case 1184: /* substr_list: a_expr substr_from */ +#line 3643 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make2((yyvsp[-1].node), (yyvsp[0].node)); + } +#line 28719 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1175: -#line 3632 "third_party/libpg_query/grammar/statements/select.y" - { + case 1185: /* substr_list: a_expr substr_for */ +#line 3647 "third_party/libpg_query/grammar/statements/select.y" + { /* * Since there are no cases where this syntax allows * a textual FOR value, we forcibly cast the argument @@ -28536,523 +28730,599 @@ YYLTYPE yylloc; * which it is likely to do if the second argument * is unknown or doesn't have an implicit cast to int4. */ - (yyval.list) = list_make3((yyvsp[(1) - (2)].node), makeIntConst(1, -1), - makeTypeCast((yyvsp[(2) - (2)].node), + (yyval.list) = list_make3((yyvsp[-1].node), makeIntConst(1, -1), + makeTypeCast((yyvsp[0].node), SystemTypeName("int4"), 0, -1)); - ;} + } +#line 28738 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1176: -#line 3647 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(1) - (1)].list); - ;} + case 1186: /* substr_list: expr_list */ +#line 3662 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = (yyvsp[0].list); + } +#line 28746 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1177: -#line 3651 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1187: /* substr_list: %empty */ +#line 3666 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 28752 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1178: -#line 3655 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + case 1188: /* substr_from: FROM a_expr */ +#line 3670 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 28758 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1179: -#line 3658 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + case 1189: /* substr_for: FOR a_expr */ +#line 3673 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 28764 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1180: -#line 3661 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(3) - (3)].list), (yyvsp[(1) - (3)].node)); ;} + case 1190: /* trim_list: a_expr FROM expr_list_opt_comma */ +#line 3676 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[0].list), (yyvsp[-2].node)); } +#line 28770 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1181: -#line 3662 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + case 1191: /* trim_list: FROM expr_list_opt_comma */ +#line 3677 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 28776 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1182: -#line 3663 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + case 1192: /* trim_list: expr_list_opt_comma */ +#line 3678 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 28782 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1183: -#line 3667 "third_party/libpg_query/grammar/statements/select.y" - { + case 1193: /* in_expr: select_with_parens */ +#line 3682 "third_party/libpg_query/grammar/statements/select.y" + { PGSubLink *n = makeNode(PGSubLink); - n->subselect = (yyvsp[(1) - (1)].node); + n->subselect = (yyvsp[0].node); /* other fields will be filled later */ (yyval.node) = (PGNode *)n; - ;} + } +#line 28793 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1184: -#line 3673 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *)(yyvsp[(2) - (3)].list); ;} + case 1194: /* in_expr: '(' expr_list_opt_comma ')' */ +#line 3688 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *)(yyvsp[-1].list); } +#line 28799 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1185: -#line 3684 "third_party/libpg_query/grammar/statements/select.y" - { + case 1195: /* case_expr: CASE case_arg when_clause_list case_default END_P */ +#line 3699 "third_party/libpg_query/grammar/statements/select.y" + { PGCaseExpr *c = makeNode(PGCaseExpr); c->casetype = InvalidOid; /* not analyzed yet */ - c->arg = (PGExpr *) (yyvsp[(2) - (5)].node); - c->args = (yyvsp[(3) - (5)].list); - c->defresult = (PGExpr *) (yyvsp[(4) - (5)].node); - c->location = (yylsp[(1) - (5)]); + c->arg = (PGExpr *) (yyvsp[-3].node); + c->args = (yyvsp[-2].list); + c->defresult = (PGExpr *) (yyvsp[-1].node); + c->location = (yylsp[-4]); (yyval.node) = (PGNode *)c; - ;} + } +#line 28813 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1186: -#line 3697 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + case 1196: /* when_clause_list: when_clause */ +#line 3712 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 28819 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1187: -#line 3698 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + case 1197: /* when_clause_list: when_clause_list when_clause */ +#line 3713 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].node)); } +#line 28825 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1188: -#line 3703 "third_party/libpg_query/grammar/statements/select.y" - { + case 1198: /* when_clause: WHEN a_expr THEN a_expr */ +#line 3718 "third_party/libpg_query/grammar/statements/select.y" + { PGCaseWhen *w = makeNode(PGCaseWhen); - w->expr = (PGExpr *) (yyvsp[(2) - (4)].node); - w->result = (PGExpr *) (yyvsp[(4) - (4)].node); - w->location = (yylsp[(1) - (4)]); + w->expr = (PGExpr *) (yyvsp[-2].node); + w->result = (PGExpr *) (yyvsp[0].node); + w->location = (yylsp[-3]); (yyval.node) = (PGNode *)w; - ;} + } +#line 28837 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1189: -#line 3713 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + case 1199: /* case_default: ELSE a_expr */ +#line 3728 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 28843 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1190: -#line 3714 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + case 1200: /* case_default: %empty */ +#line 3729 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; } +#line 28849 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1191: -#line 3717 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + case 1201: /* case_arg: a_expr */ +#line 3732 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 28855 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1192: -#line 3718 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + case 1202: /* case_arg: %empty */ +#line 3733 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; } +#line 28861 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1193: -#line 3722 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeColumnRef((yyvsp[(1) - (1)].str), NIL, (yylsp[(1) - (1)]), yyscanner); - ;} + case 1203: /* columnref: ColId */ +#line 3737 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeColumnRef((yyvsp[0].str), NIL, (yylsp[0]), yyscanner); + } +#line 28869 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1194: -#line 3726 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeColumnRef((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].list), (yylsp[(1) - (2)]), yyscanner); - ;} + case 1204: /* columnref: ColId indirection */ +#line 3741 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeColumnRef((yyvsp[-1].str), (yyvsp[0].list), (yylsp[-1]), yyscanner); + } +#line 28877 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1195: -#line 3733 "third_party/libpg_query/grammar/statements/select.y" - { + case 1205: /* indirection_el: '[' a_expr ']' */ +#line 3748 "third_party/libpg_query/grammar/statements/select.y" + { PGAIndices *ai = makeNode(PGAIndices); ai->is_slice = false; ai->lidx = NULL; - ai->uidx = (yyvsp[(2) - (3)].node); + ai->uidx = (yyvsp[-1].node); (yyval.node) = (PGNode *) ai; - ;} + } +#line 28889 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1196: -#line 3741 "third_party/libpg_query/grammar/statements/select.y" - { + case 1206: /* indirection_el: '[' opt_slice_bound ':' opt_slice_bound ']' */ +#line 3756 "third_party/libpg_query/grammar/statements/select.y" + { PGAIndices *ai = makeNode(PGAIndices); ai->is_slice = true; - ai->lidx = (yyvsp[(2) - (5)].node); - ai->uidx = (yyvsp[(4) - (5)].node); + ai->lidx = (yyvsp[-3].node); + ai->uidx = (yyvsp[-1].node); (yyval.node) = (PGNode *) ai; - ;} + } +#line 28901 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1197: -#line 3748 "third_party/libpg_query/grammar/statements/select.y" - { + case 1207: /* indirection_el: '[' opt_slice_bound ':' opt_slice_bound ':' opt_slice_bound ']' */ +#line 3763 "third_party/libpg_query/grammar/statements/select.y" + { PGAIndices *ai = makeNode(PGAIndices); ai->is_slice = true; - ai->lidx = (yyvsp[(2) - (7)].node); - ai->uidx = (yyvsp[(4) - (7)].node); - ai->step = (yyvsp[(6) - (7)].node); + ai->lidx = (yyvsp[-5].node); + ai->uidx = (yyvsp[-3].node); + ai->step = (yyvsp[-1].node); (yyval.node) = (PGNode *) ai; - ;} + } +#line 28914 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1198: -#line 3756 "third_party/libpg_query/grammar/statements/select.y" - { + case 1208: /* indirection_el: '[' opt_slice_bound ':' '-' ':' opt_slice_bound ']' */ +#line 3771 "third_party/libpg_query/grammar/statements/select.y" + { PGAIndices *ai = makeNode(PGAIndices); ai->is_slice = true; - ai->lidx = (yyvsp[(2) - (7)].node); - ai->step = (yyvsp[(6) - (7)].node); + ai->lidx = (yyvsp[-5].node); + ai->step = (yyvsp[-1].node); (yyval.node) = (PGNode *) ai; - ;} + } +#line 28926 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1199: -#line 3766 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + case 1209: /* opt_slice_bound: a_expr */ +#line 3781 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[0].node); } +#line 28932 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1200: -#line 3767 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} + case 1210: /* opt_slice_bound: %empty */ +#line 3782 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; } +#line 28938 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1201: -#line 3772 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1211: /* opt_indirection: %empty */ +#line 3787 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 28944 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1202: -#line 3773 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + case 1212: /* opt_indirection: opt_indirection indirection_el */ +#line 3788 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].node)); } +#line 28950 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1203: -#line 3777 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NULL; ;} + case 1213: /* opt_func_arguments: %empty */ +#line 3792 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NULL; } +#line 28956 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1204: -#line 3778 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(NULL); ;} + case 1214: /* opt_func_arguments: '(' ')' */ +#line 3793 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(NULL); } +#line 28962 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1205: -#line 3779 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + case 1215: /* opt_func_arguments: '(' func_arg_list ')' */ +#line 3794 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 28968 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1206: -#line 3784 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(3) - (3)].list)) { - PGFuncCall *n = makeFuncCall(list_make1(makeString((yyvsp[(2) - (3)].str))), (yyvsp[(3) - (3)].list)->head->data.ptr_value ? (yyvsp[(3) - (3)].list) : NULL, (yylsp[(2) - (3)])); + case 1216: /* extended_indirection_el: '.' attr_name opt_func_arguments */ +#line 3799 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[0].list)) { + PGFuncCall *n = makeFuncCall(list_make1(makeString((yyvsp[-1].str))), (yyvsp[0].list)->head->data.ptr_value ? (yyvsp[0].list) : NULL, (yylsp[-1])); (yyval.node) = (PGNode *) n; } else { - (yyval.node) = (PGNode *) makeString((yyvsp[(2) - (3)].str)); + (yyval.node) = (PGNode *) makeString((yyvsp[-1].str)); } - ;} + } +#line 28981 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1207: -#line 3793 "third_party/libpg_query/grammar/statements/select.y" - { + case 1217: /* extended_indirection_el: '[' a_expr ']' */ +#line 3808 "third_party/libpg_query/grammar/statements/select.y" + { PGAIndices *ai = makeNode(PGAIndices); ai->is_slice = false; ai->lidx = NULL; - ai->uidx = (yyvsp[(2) - (3)].node); + ai->uidx = (yyvsp[-1].node); (yyval.node) = (PGNode *) ai; - ;} + } +#line 28993 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1208: -#line 3801 "third_party/libpg_query/grammar/statements/select.y" - { + case 1218: /* extended_indirection_el: '[' opt_slice_bound ':' opt_slice_bound ']' */ +#line 3816 "third_party/libpg_query/grammar/statements/select.y" + { PGAIndices *ai = makeNode(PGAIndices); ai->is_slice = true; - ai->lidx = (yyvsp[(2) - (5)].node); - ai->uidx = (yyvsp[(4) - (5)].node); + ai->lidx = (yyvsp[-3].node); + ai->uidx = (yyvsp[-1].node); (yyval.node) = (PGNode *) ai; - ;} + } +#line 29005 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1209: -#line 3808 "third_party/libpg_query/grammar/statements/select.y" - { + case 1219: /* extended_indirection_el: '[' opt_slice_bound ':' opt_slice_bound ':' opt_slice_bound ']' */ +#line 3823 "third_party/libpg_query/grammar/statements/select.y" + { PGAIndices *ai = makeNode(PGAIndices); ai->is_slice = true; - ai->lidx = (yyvsp[(2) - (7)].node); - ai->uidx = (yyvsp[(4) - (7)].node); - ai->step = (yyvsp[(6) - (7)].node); + ai->lidx = (yyvsp[-5].node); + ai->uidx = (yyvsp[-3].node); + ai->step = (yyvsp[-1].node); (yyval.node) = (PGNode *) ai; - ;} + } +#line 29018 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1210: -#line 3817 "third_party/libpg_query/grammar/statements/select.y" - { + case 1220: /* extended_indirection_el: '[' opt_slice_bound ':' '-' ':' opt_slice_bound ']' */ +#line 3832 "third_party/libpg_query/grammar/statements/select.y" + { PGAIndices *ai = makeNode(PGAIndices); ai->is_slice = true; - ai->lidx = (yyvsp[(2) - (7)].node); - ai->step = (yyvsp[(6) - (7)].node); + ai->lidx = (yyvsp[-5].node); + ai->step = (yyvsp[-1].node); (yyval.node) = (PGNode *) ai; - ;} + } +#line 29030 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1211: -#line 3832 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1221: /* opt_extended_indirection: %empty */ +#line 3847 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 29036 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1212: -#line 3833 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + case 1222: /* opt_extended_indirection: opt_extended_indirection extended_indirection_el */ +#line 3848 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].node)); } +#line 29042 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1215: -#line 3849 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + case 1225: /* opt_target_list_opt_comma: target_list_opt_comma */ +#line 3864 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 29048 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1216: -#line 3850 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1226: /* opt_target_list_opt_comma: %empty */ +#line 3865 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 29054 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1217: -#line 3854 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].target)); ;} + case 1227: /* target_list: target_el */ +#line 3869 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[0].target)); } +#line 29060 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1218: -#line 3855 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].target)); ;} + case 1228: /* target_list: target_list ',' target_el */ +#line 3870 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].target)); } +#line 29066 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1219: -#line 3859 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + case 1229: /* target_list_opt_comma: target_list */ +#line 3874 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 29072 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1220: -#line 3860 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + case 1230: /* target_list_opt_comma: target_list ',' */ +#line 3875 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 29078 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1221: -#line 3864 "third_party/libpg_query/grammar/statements/select.y" - { + case 1231: /* target_el: a_expr AS ColLabelOrString */ +#line 3879 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = (yyvsp[(3) - (3)].str); + (yyval.target)->name = (yyvsp[0].str); (yyval.target)->indirection = NIL; - (yyval.target)->val = (PGNode *)(yyvsp[(1) - (3)].node); - (yyval.target)->location = (yylsp[(1) - (3)]); - ;} + (yyval.target)->val = (PGNode *)(yyvsp[-2].node); + (yyval.target)->location = (yylsp[-2]); + } +#line 29090 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1222: -#line 3880 "third_party/libpg_query/grammar/statements/select.y" - { + case 1232: /* target_el: a_expr IDENT */ +#line 3895 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = (yyvsp[(2) - (2)].str); + (yyval.target)->name = (yyvsp[0].str); (yyval.target)->indirection = NIL; - (yyval.target)->val = (PGNode *)(yyvsp[(1) - (2)].node); - (yyval.target)->location = (yylsp[(1) - (2)]); - ;} + (yyval.target)->val = (PGNode *)(yyvsp[-1].node); + (yyval.target)->location = (yylsp[-1]); + } +#line 29102 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1223: -#line 3888 "third_party/libpg_query/grammar/statements/select.y" - { + case 1233: /* target_el: a_expr */ +#line 3903 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.target) = makeNode(PGResTarget); (yyval.target)->name = NULL; (yyval.target)->indirection = NIL; - (yyval.target)->val = (PGNode *)(yyvsp[(1) - (1)].node); - (yyval.target)->location = (yylsp[(1) - (1)]); - ;} + (yyval.target)->val = (PGNode *)(yyvsp[0].node); + (yyval.target)->location = (yylsp[0]); + } +#line 29114 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1224: -#line 3897 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + case 1234: /* except_list: EXCLUDE '(' name_list_opt_comma ')' */ +#line 3912 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 29120 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1225: -#line 3898 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(2) - (2)].str))); ;} + case 1235: /* except_list: EXCLUDE ColId */ +#line 3913 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[0].str))); } +#line 29126 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1226: -#line 3901 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + case 1236: /* opt_except_list: except_list */ +#line 3916 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 29132 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1227: -#line 3902 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NULL; ;} + case 1237: /* opt_except_list: %empty */ +#line 3917 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NULL; } +#line 29138 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1228: -#line 3905 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(1) - (3)].node), makeString((yyvsp[(3) - (3)].str))); ;} + case 1238: /* replace_list_el: a_expr AS ColId */ +#line 3920 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make2((yyvsp[-2].node), makeString((yyvsp[0].str))); } +#line 29144 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1229: -#line 3909 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].list)); ;} + case 1239: /* replace_list: replace_list_el */ +#line 3924 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[0].list)); } +#line 29150 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1230: -#line 3910 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} + case 1240: /* replace_list: replace_list ',' replace_list_el */ +#line 3925 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].list)); } +#line 29156 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1231: -#line 3914 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + case 1241: /* replace_list_opt_comma: replace_list */ +#line 3929 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 29162 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1232: -#line 3915 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + case 1242: /* replace_list_opt_comma: replace_list ',' */ +#line 3930 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 29168 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1233: -#line 3918 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + case 1243: /* opt_replace_list: REPLACE '(' replace_list_opt_comma ')' */ +#line 3933 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 29174 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1234: -#line 3919 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(2) - (2)].list)); ;} + case 1244: /* opt_replace_list: REPLACE replace_list_el */ +#line 3934 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[0].list)); } +#line 29180 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1235: -#line 3920 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NULL; ;} + case 1245: /* opt_replace_list: %empty */ +#line 3935 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NULL; } +#line 29186 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1236: -#line 3930 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].range)); ;} + case 1246: /* qualified_name_list: qualified_name */ +#line 3945 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[0].range)); } +#line 29192 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1237: -#line 3931 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].range)); ;} + case 1247: /* qualified_name_list: qualified_name_list ',' qualified_name */ +#line 3946 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].range)); } +#line 29198 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1238: -#line 3936 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + case 1248: /* name_list: name */ +#line 3951 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[0].str))); } +#line 29204 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1239: -#line 3938 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeString((yyvsp[(3) - (3)].str))); ;} + case 1249: /* name_list: name_list ',' name */ +#line 3953 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-2].list), makeString((yyvsp[0].str))); } +#line 29210 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1240: -#line 3943 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + case 1250: /* name_list_opt_comma: name_list */ +#line 3958 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 29216 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1241: -#line 3944 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + case 1251: /* name_list_opt_comma: name_list ',' */ +#line 3959 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 29222 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1242: -#line 3948 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + case 1252: /* name_list_opt_comma_opt_bracket: name_list_opt_comma */ +#line 3963 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[0].list); } +#line 29228 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1243: -#line 3949 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + case 1253: /* name_list_opt_comma_opt_bracket: '(' name_list_opt_comma ')' */ +#line 3964 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 29234 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1244: -#line 3952 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1254: /* name: ColIdOrString */ +#line 3967 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[0].str); } +#line 29240 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1245: -#line 3964 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + case 1255: /* func_name: function_name_token */ +#line 3979 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[0].str))); } +#line 29246 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1246: -#line 3967 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = check_func_name(lcons(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].list)), + case 1256: /* func_name: ColId indirection */ +#line 3982 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = check_func_name(lcons(makeString((yyvsp[-1].str)), (yyvsp[0].list)), yyscanner); - ;} + } +#line 29255 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1247: -#line 3978 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeIntConst((yyvsp[(1) - (1)].ival), (yylsp[(1) - (1)])); - ;} + case 1257: /* AexprConst: Iconst */ +#line 3993 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeIntConst((yyvsp[0].ival), (yylsp[0])); + } +#line 29263 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1248: -#line 3982 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeFloatConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} + case 1258: /* AexprConst: FCONST */ +#line 3997 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeFloatConst((yyvsp[0].str), (yylsp[0])); + } +#line 29271 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1249: -#line 3986 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(2) - (2)].list)) + case 1259: /* AexprConst: Sconst opt_indirection */ +#line 4001 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[0].list)) { PGAIndirection *n = makeNode(PGAIndirection); - n->arg = makeStringConst((yyvsp[(1) - (2)].str), (yylsp[(1) - (2)])); - n->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + n->arg = makeStringConst((yyvsp[-1].str), (yylsp[-1])); + n->indirection = check_indirection((yyvsp[0].list), yyscanner); (yyval.node) = (PGNode *) n; } else - (yyval.node) = makeStringConst((yyvsp[(1) - (2)].str), (yylsp[(1) - (2)])); - ;} + (yyval.node) = makeStringConst((yyvsp[-1].str), (yylsp[-1])); + } +#line 29287 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1250: -#line 3998 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeBitStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} + case 1260: /* AexprConst: BCONST */ +#line 4013 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeBitStringConst((yyvsp[0].str), (yylsp[0])); + } +#line 29295 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1251: -#line 4002 "third_party/libpg_query/grammar/statements/select.y" - { + case 1261: /* AexprConst: XCONST */ +#line 4017 "third_party/libpg_query/grammar/statements/select.y" + { /* This is a bit constant per SQL99: * Without Feature F511, "BIT data type", * a shall not be a * or a . */ - (yyval.node) = makeBitStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} + (yyval.node) = makeBitStringConst((yyvsp[0].str), (yylsp[0])); + } +#line 29308 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1252: -#line 4011 "third_party/libpg_query/grammar/statements/select.y" - { + case 1262: /* AexprConst: func_name Sconst */ +#line 4026 "third_party/libpg_query/grammar/statements/select.y" + { /* generic type 'literal' syntax */ - PGTypeName *t = makeTypeNameFromNameList((yyvsp[(1) - (2)].list)); - t->location = (yylsp[(1) - (2)]); - (yyval.node) = makeStringConstCast((yyvsp[(2) - (2)].str), (yylsp[(2) - (2)]), t); - ;} + PGTypeName *t = makeTypeNameFromNameList((yyvsp[-1].list)); + t->location = (yylsp[-1]); + (yyval.node) = makeStringConstCast((yyvsp[0].str), (yylsp[0]), t); + } +#line 29319 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1253: -#line 4018 "third_party/libpg_query/grammar/statements/select.y" - { + case 1263: /* AexprConst: func_name '(' func_arg_list opt_sort_clause opt_ignore_nulls ')' Sconst */ +#line 4033 "third_party/libpg_query/grammar/statements/select.y" + { /* generic syntax with a type modifier */ - PGTypeName *t = makeTypeNameFromNameList((yyvsp[(1) - (7)].list)); + PGTypeName *t = makeTypeNameFromNameList((yyvsp[-6].list)); PGListCell *lc; /* @@ -29061,7 +29331,7 @@ YYLTYPE yylloc; * don't actually wish to allow PGNamedArgExpr in this * context, ORDER BY, nor IGNORE NULLS. */ - foreach(lc, (yyvsp[(3) - (7)].list)) + foreach(lc, (yyvsp[-4].list)) { PGNamedArgExpr *arg = (PGNamedArgExpr *) lfirst(lc); @@ -29071,281 +29341,315 @@ YYLTYPE yylloc; errmsg("type modifier cannot have parameter name"), parser_errposition(arg->location))); } - if ((yyvsp[(4) - (7)].list) != NIL) + if ((yyvsp[-3].list) != NIL) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("type modifier cannot have ORDER BY"), - parser_errposition((yylsp[(4) - (7)])))); - if ((yyvsp[(5) - (7)].ignorenulls) != false) + parser_errposition((yylsp[-3])))); + if ((yyvsp[-2].ignorenulls) != false) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("type modifier cannot have IGNORE NULLS"), - parser_errposition((yylsp[(5) - (7)])))); + parser_errposition((yylsp[-2])))); - t->typmods = (yyvsp[(3) - (7)].list); - t->location = (yylsp[(1) - (7)]); - (yyval.node) = makeStringConstCast((yyvsp[(7) - (7)].str), (yylsp[(7) - (7)]), t); - ;} + t->typmods = (yyvsp[-4].list); + t->location = (yylsp[-6]); + (yyval.node) = makeStringConstCast((yyvsp[0].str), (yylsp[0]), t); + } +#line 29361 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1254: -#line 4056 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeStringConstCast((yyvsp[(2) - (2)].str), (yylsp[(2) - (2)]), (yyvsp[(1) - (2)].typnam)); - ;} + case 1264: /* AexprConst: ConstTypename Sconst */ +#line 4071 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeStringConstCast((yyvsp[0].str), (yylsp[0]), (yyvsp[-1].typnam)); + } +#line 29369 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1255: -#line 4060 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeIntervalNode((yyvsp[(3) - (5)].node), (yylsp[(3) - (5)]), (yyvsp[(5) - (5)].list)); - ;} + case 1265: /* AexprConst: ConstInterval '(' a_expr ')' opt_interval */ +#line 4075 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeIntervalNode((yyvsp[-2].node), (yylsp[-2]), (yyvsp[0].list)); + } +#line 29377 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1256: -#line 4064 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeIntervalNode((yyvsp[(2) - (3)].ival), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].list)); - ;} + case 1266: /* AexprConst: ConstInterval Iconst opt_interval */ +#line 4079 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeIntervalNode((yyvsp[-1].ival), (yylsp[-1]), (yyvsp[0].list)); + } +#line 29385 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1257: -#line 4068 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeIntervalNode((yyvsp[(2) - (3)].str), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].list)); - ;} + case 1267: /* AexprConst: ConstInterval Sconst opt_interval */ +#line 4083 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeIntervalNode((yyvsp[-1].str), (yylsp[-1]), (yyvsp[0].list)); + } +#line 29393 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1258: -#line 4072 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeBoolAConst(true, (yylsp[(1) - (1)])); - ;} + case 1268: /* AexprConst: TRUE_P */ +#line 4087 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeBoolAConst(true, (yylsp[0])); + } +#line 29401 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1259: -#line 4076 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeBoolAConst(false, (yylsp[(1) - (1)])); - ;} + case 1269: /* AexprConst: FALSE_P */ +#line 4091 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeBoolAConst(false, (yylsp[0])); + } +#line 29409 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1260: -#line 4080 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeNullAConst((yylsp[(1) - (1)])); - ;} + case 1270: /* AexprConst: NULL_P */ +#line 4095 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeNullAConst((yylsp[0])); + } +#line 29417 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1261: -#line 4085 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} + case 1271: /* Iconst: ICONST */ +#line 4100 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = (yyvsp[0].ival); } +#line 29423 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1262: -#line 4102 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1272: /* type_function_name: IDENT */ +#line 4117 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[0].str); } +#line 29429 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1263: -#line 4103 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + case 1273: /* type_function_name: unreserved_keyword */ +#line 4118 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 29435 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1264: -#line 4104 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + case 1274: /* type_function_name: type_func_name_keyword */ +#line 4119 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 29441 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1265: -#line 4107 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1275: /* function_name_token: IDENT */ +#line 4122 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[0].str); } +#line 29447 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1266: -#line 4108 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + case 1276: /* function_name_token: unreserved_keyword */ +#line 4123 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 29453 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1267: -#line 4109 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + case 1277: /* function_name_token: func_name_keyword */ +#line 4124 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 29459 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1268: -#line 4112 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1278: /* type_name_token: IDENT */ +#line 4127 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[0].str); } +#line 29465 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1269: -#line 4113 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + case 1279: /* type_name_token: unreserved_keyword */ +#line 4128 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 29471 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1270: -#line 4114 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + case 1280: /* type_name_token: type_name_keyword */ +#line 4129 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 29477 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1271: -#line 4117 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + case 1281: /* any_name: ColId */ +#line 4132 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[0].str))); } +#line 29483 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1272: -#line 4118 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lcons(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].list)); ;} + case 1282: /* any_name: ColId attrs */ +#line 4133 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lcons(makeString((yyvsp[-1].str)), (yyvsp[0].list)); } +#line 29489 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1273: -#line 4122 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(2) - (2)].str))); ;} + case 1283: /* attrs: '.' attr_name */ +#line 4137 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[0].str))); } +#line 29495 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1274: -#line 4124 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeString((yyvsp[(3) - (3)].str))); ;} + case 1284: /* attrs: attrs '.' attr_name */ +#line 4139 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[-2].list), makeString((yyvsp[0].str))); } +#line 29501 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1275: -#line 4128 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + case 1285: /* opt_name_list: '(' name_list_opt_comma ')' */ +#line 4143 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[-1].list); } +#line 29507 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1276: -#line 4129 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} + case 1286: /* opt_name_list: %empty */ +#line 4144 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; } +#line 29513 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1278: -#line 4136 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1288: /* ColLabelOrString: ColLabel */ +#line 4151 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[0].str); } +#line 29519 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1279: -#line 4137 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1289: /* ColLabelOrString: SCONST */ +#line 4152 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[0].str); } +#line 29525 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1280: + case 1290: /* PrepareStmt: PREPARE name prep_type_clause AS PreparableStmt */ #line 8 "third_party/libpg_query/grammar/statements/prepare.y" - { + { PGPrepareStmt *n = makeNode(PGPrepareStmt); - n->name = (yyvsp[(2) - (5)].str); - n->argtypes = (yyvsp[(3) - (5)].list); - n->query = (yyvsp[(5) - (5)].node); + n->name = (yyvsp[-3].str); + n->argtypes = (yyvsp[-2].list); + n->query = (yyvsp[0].node); (yyval.node) = (PGNode *) n; - ;} + } +#line 29537 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1281: + case 1291: /* prep_type_clause: '(' type_list ')' */ #line 18 "third_party/libpg_query/grammar/statements/prepare.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + { (yyval.list) = (yyvsp[-1].list); } +#line 29543 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1282: + case 1292: /* prep_type_clause: %empty */ #line 19 "third_party/libpg_query/grammar/statements/prepare.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 29549 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1289: + case 1299: /* CreateSchemaStmt: CREATE_P SCHEMA qualified_name OptSchemaEltList */ #line 8 "third_party/libpg_query/grammar/statements/create_schema.y" - { + { PGCreateSchemaStmt *n = makeNode(PGCreateSchemaStmt); - if ((yyvsp[(3) - (4)].range)->catalogname) { + if ((yyvsp[-1].range)->catalogname) { ereport(ERROR, (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("CREATE SCHEMA too many dots: expected \"catalog.schema\" or \"schema\""), - parser_errposition((yylsp[(3) - (4)])))); + parser_errposition((yylsp[-1])))); } - if ((yyvsp[(3) - (4)].range)->schemaname) { - n->catalogname = (yyvsp[(3) - (4)].range)->schemaname; - n->schemaname = (yyvsp[(3) - (4)].range)->relname; + if ((yyvsp[-1].range)->schemaname) { + n->catalogname = (yyvsp[-1].range)->schemaname; + n->schemaname = (yyvsp[-1].range)->relname; } else { - n->schemaname = (yyvsp[(3) - (4)].range)->relname; + n->schemaname = (yyvsp[-1].range)->relname; } - n->schemaElts = (yyvsp[(4) - (4)].list); + n->schemaElts = (yyvsp[0].list); n->onconflict = PG_ERROR_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 29572 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1290: + case 1300: /* CreateSchemaStmt: CREATE_P SCHEMA IF_P NOT EXISTS qualified_name OptSchemaEltList */ #line 27 "third_party/libpg_query/grammar/statements/create_schema.y" - { + { PGCreateSchemaStmt *n = makeNode(PGCreateSchemaStmt); - if ((yyvsp[(6) - (7)].range)->catalogname) { + if ((yyvsp[-1].range)->catalogname) { ereport(ERROR, (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("CREATE SCHEMA too many dots: expected \"catalog.schema\" or \"schema\""), - parser_errposition((yylsp[(6) - (7)])))); + parser_errposition((yylsp[-1])))); } - if ((yyvsp[(6) - (7)].range)->schemaname) { - n->catalogname = (yyvsp[(6) - (7)].range)->schemaname; - n->schemaname = (yyvsp[(6) - (7)].range)->relname; + if ((yyvsp[-1].range)->schemaname) { + n->catalogname = (yyvsp[-1].range)->schemaname; + n->schemaname = (yyvsp[-1].range)->relname; } else { - n->schemaname = (yyvsp[(6) - (7)].range)->relname; + n->schemaname = (yyvsp[-1].range)->relname; } - if ((yyvsp[(7) - (7)].list) != NIL) + if ((yyvsp[0].list) != NIL) ereport(ERROR, (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("CREATE SCHEMA IF NOT EXISTS cannot include schema elements"), - parser_errposition((yylsp[(7) - (7)])))); - n->schemaElts = (yyvsp[(7) - (7)].list); + parser_errposition((yylsp[0])))); + n->schemaElts = (yyvsp[0].list); n->onconflict = PG_IGNORE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 29600 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1291: + case 1301: /* CreateSchemaStmt: CREATE_P OR REPLACE SCHEMA qualified_name OptSchemaEltList */ #line 51 "third_party/libpg_query/grammar/statements/create_schema.y" - { + { PGCreateSchemaStmt *n = makeNode(PGCreateSchemaStmt); - if ((yyvsp[(5) - (6)].range)->catalogname) { + if ((yyvsp[-1].range)->catalogname) { ereport(ERROR, (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("CREATE SCHEMA too many dots: expected \"catalog.schema\" or \"schema\""), - parser_errposition((yylsp[(5) - (6)])))); + parser_errposition((yylsp[-1])))); } - if ((yyvsp[(5) - (6)].range)->schemaname) { - n->catalogname = (yyvsp[(5) - (6)].range)->schemaname; - n->schemaname = (yyvsp[(5) - (6)].range)->relname; + if ((yyvsp[-1].range)->schemaname) { + n->catalogname = (yyvsp[-1].range)->schemaname; + n->schemaname = (yyvsp[-1].range)->relname; } else { - n->schemaname = (yyvsp[(5) - (6)].range)->relname; + n->schemaname = (yyvsp[-1].range)->relname; } - n->schemaElts = (yyvsp[(6) - (6)].list); + n->schemaElts = (yyvsp[0].list); n->onconflict = PG_REPLACE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 29623 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1292: + case 1302: /* OptSchemaEltList: OptSchemaEltList schema_stmt */ #line 74 "third_party/libpg_query/grammar/statements/create_schema.y" - { + { if ((yyloc) < 0) /* see comments for YYLLOC_DEFAULT */ - (yyloc) = (yylsp[(2) - (2)]); - (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); - ;} + (yyloc) = (yylsp[0]); + (yyval.list) = lappend((yyvsp[-1].list), (yyvsp[0].node)); + } +#line 29633 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1293: + case 1303: /* OptSchemaEltList: %empty */ #line 80 "third_party/libpg_query/grammar/statements/create_schema.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 29639 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1298: + case 1308: /* IndexStmt: CREATE_P opt_unique INDEX opt_concurrently opt_index_name ON qualified_name access_method_clause '(' index_params ')' opt_reloptions where_clause */ #line 11 "third_party/libpg_query/grammar/statements/index.y" - { + { PGIndexStmt *n = makeNode(PGIndexStmt); - n->unique = (yyvsp[(2) - (13)].boolean); - n->concurrent = (yyvsp[(4) - (13)].boolean); - n->idxname = (yyvsp[(5) - (13)].str); - n->relation = (yyvsp[(7) - (13)].range); - n->accessMethod = (yyvsp[(8) - (13)].str); - n->indexParams = (yyvsp[(10) - (13)].list); - n->options = (yyvsp[(12) - (13)].list); - n->whereClause = (yyvsp[(13) - (13)].node); + n->unique = (yyvsp[-11].boolean); + n->concurrent = (yyvsp[-9].boolean); + n->idxname = (yyvsp[-8].str); + n->relation = (yyvsp[-6].range); + n->accessMethod = (yyvsp[-5].str); + n->indexParams = (yyvsp[-3].list); + n->options = (yyvsp[-1].list); + n->whereClause = (yyvsp[0].node); n->excludeOpNames = NIL; n->idxcomment = NULL; n->indexOid = InvalidOid; @@ -29357,21 +29661,22 @@ YYLTYPE yylloc; n->transformed = false; n->onconflict = PG_ERROR_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 29666 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1299: + case 1309: /* IndexStmt: CREATE_P opt_unique INDEX opt_concurrently IF_P NOT EXISTS index_name ON qualified_name access_method_clause '(' index_params ')' opt_reloptions where_clause */ #line 36 "third_party/libpg_query/grammar/statements/index.y" - { + { PGIndexStmt *n = makeNode(PGIndexStmt); - n->unique = (yyvsp[(2) - (16)].boolean); - n->concurrent = (yyvsp[(4) - (16)].boolean); - n->idxname = (yyvsp[(8) - (16)].str); - n->relation = (yyvsp[(10) - (16)].range); - n->accessMethod = (yyvsp[(11) - (16)].str); - n->indexParams = (yyvsp[(13) - (16)].list); - n->options = (yyvsp[(15) - (16)].list); - n->whereClause = (yyvsp[(16) - (16)].node); + n->unique = (yyvsp[-14].boolean); + n->concurrent = (yyvsp[-12].boolean); + n->idxname = (yyvsp[-8].str); + n->relation = (yyvsp[-6].range); + n->accessMethod = (yyvsp[-5].str); + n->indexParams = (yyvsp[-3].list); + n->options = (yyvsp[-1].list); + n->whereClause = (yyvsp[0].node); n->excludeOpNames = NIL; n->idxcomment = NULL; n->indexOid = InvalidOid; @@ -29383,1457 +29688,1615 @@ YYLTYPE yylloc; n->transformed = false; n->onconflict = PG_IGNORE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 29693 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1300: + case 1310: /* access_method: ColId */ #line 62 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 29699 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1301: + case 1311: /* access_method_clause: USING access_method */ #line 66 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.str) = (yyvsp[(2) - (2)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 29705 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1302: + case 1312: /* access_method_clause: %empty */ #line 67 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.str) = (char*) DEFAULT_INDEX_TYPE; ;} + { (yyval.str) = (char*) DEFAULT_INDEX_TYPE; } +#line 29711 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1303: + case 1313: /* opt_concurrently: CONCURRENTLY */ #line 72 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 29717 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1304: + case 1314: /* opt_concurrently: %empty */ #line 73 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 29723 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1305: + case 1315: /* opt_index_name: index_name */ #line 78 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 29729 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1306: + case 1316: /* opt_index_name: %empty */ #line 79 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.str) = NULL; ;} + { (yyval.str) = NULL; } +#line 29735 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1307: + case 1317: /* opt_reloptions: WITH reloptions */ #line 83 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 29741 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1308: + case 1318: /* opt_reloptions: %empty */ #line 84 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 29747 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1309: + case 1319: /* opt_unique: UNIQUE */ #line 89 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 29753 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1310: + case 1320: /* opt_unique: %empty */ #line 90 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 29759 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1311: + case 1321: /* AlterObjectSchemaStmt: ALTER TABLE relation_expr SET SCHEMA name */ #line 8 "third_party/libpg_query/grammar/statements/alter_schema.y" - { + { PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); n->objectType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(3) - (6)].range); - n->newschema = (yyvsp[(6) - (6)].str); + n->relation = (yyvsp[-3].range); + n->newschema = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 29772 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1312: + case 1322: /* AlterObjectSchemaStmt: ALTER TABLE IF_P EXISTS relation_expr SET SCHEMA name */ #line 17 "third_party/libpg_query/grammar/statements/alter_schema.y" - { + { PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); n->objectType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(5) - (8)].range); - n->newschema = (yyvsp[(8) - (8)].str); + n->relation = (yyvsp[-3].range); + n->newschema = (yyvsp[0].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 29785 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1313: + case 1323: /* AlterObjectSchemaStmt: ALTER SEQUENCE qualified_name SET SCHEMA name */ #line 26 "third_party/libpg_query/grammar/statements/alter_schema.y" - { + { PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); n->objectType = PG_OBJECT_SEQUENCE; - n->relation = (yyvsp[(3) - (6)].range); - n->newschema = (yyvsp[(6) - (6)].str); + n->relation = (yyvsp[-3].range); + n->newschema = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 29798 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1314: + case 1324: /* AlterObjectSchemaStmt: ALTER SEQUENCE IF_P EXISTS qualified_name SET SCHEMA name */ #line 35 "third_party/libpg_query/grammar/statements/alter_schema.y" - { + { PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); n->objectType = PG_OBJECT_SEQUENCE; - n->relation = (yyvsp[(5) - (8)].range); - n->newschema = (yyvsp[(8) - (8)].str); + n->relation = (yyvsp[-3].range); + n->newschema = (yyvsp[0].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 29811 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1315: + case 1325: /* AlterObjectSchemaStmt: ALTER VIEW qualified_name SET SCHEMA name */ #line 44 "third_party/libpg_query/grammar/statements/alter_schema.y" - { + { PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); n->objectType = PG_OBJECT_VIEW; - n->relation = (yyvsp[(3) - (6)].range); - n->newschema = (yyvsp[(6) - (6)].str); + n->relation = (yyvsp[-3].range); + n->newschema = (yyvsp[0].str); n->missing_ok = false; (yyval.node) = (PGNode *)n; - ;} + } +#line 29824 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1316: + case 1326: /* AlterObjectSchemaStmt: ALTER VIEW IF_P EXISTS qualified_name SET SCHEMA name */ #line 53 "third_party/libpg_query/grammar/statements/alter_schema.y" - { + { PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); n->objectType = PG_OBJECT_VIEW; - n->relation = (yyvsp[(5) - (8)].range); - n->newschema = (yyvsp[(8) - (8)].str); + n->relation = (yyvsp[-3].range); + n->newschema = (yyvsp[0].str); n->missing_ok = true; (yyval.node) = (PGNode *)n; - ;} + } +#line 29837 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1317: + case 1327: /* CheckPointStmt: FORCE CHECKPOINT opt_col_id */ #line 6 "third_party/libpg_query/grammar/statements/checkpoint.y" - { + { PGCheckPointStmt *n = makeNode(PGCheckPointStmt); n->force = true; - n->name = (yyvsp[(3) - (3)].str); + n->name = (yyvsp[0].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 29848 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1318: + case 1328: /* CheckPointStmt: CHECKPOINT opt_col_id */ #line 13 "third_party/libpg_query/grammar/statements/checkpoint.y" - { + { PGCheckPointStmt *n = makeNode(PGCheckPointStmt); n->force = false; - n->name = (yyvsp[(2) - (2)].str); + n->name = (yyvsp[0].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 29859 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1319: + case 1329: /* opt_col_id: ColId */ #line 22 "third_party/libpg_query/grammar/statements/checkpoint.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 29865 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1320: + case 1330: /* opt_col_id: %empty */ #line 23 "third_party/libpg_query/grammar/statements/checkpoint.y" - { (yyval.str) = NULL; ;} + { (yyval.str) = NULL; } +#line 29871 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1321: + case 1331: /* CommentOnStmt: COMMENT ON comment_on_type_any_name qualified_name IS comment_value */ #line 8 "third_party/libpg_query/grammar/statements/comment_on.y" - { + { PGCommentOnStmt *n = makeNode(PGCommentOnStmt); - n->object_type = (yyvsp[(3) - (6)].objtype); - n->name = (yyvsp[(4) - (6)].range); - n->value = (yyvsp[(6) - (6)].node); + n->object_type = (yyvsp[-3].objtype); + n->name = (yyvsp[-2].range); + n->value = (yyvsp[0].node); (yyval.node) = (PGNode *)n; - ;} + } +#line 29883 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1322: + case 1332: /* CommentOnStmt: COMMENT ON COLUMN a_expr IS comment_value */ #line 16 "third_party/libpg_query/grammar/statements/comment_on.y" - { + { PGCommentOnStmt *n = makeNode(PGCommentOnStmt); n->object_type = PG_OBJECT_COLUMN; - n->column_expr = (yyvsp[(4) - (6)].node); - n->value = (yyvsp[(6) - (6)].node); + n->column_expr = (yyvsp[-2].node); + n->value = (yyvsp[0].node); (yyval.node) = (PGNode *)n; - ;} + } +#line 29895 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1323: + case 1333: /* comment_value: Sconst */ #line 26 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.node) = makeStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); ;} + { (yyval.node) = makeStringConst((yyvsp[0].str), (yylsp[0])); } +#line 29901 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1324: + case 1334: /* comment_value: NULL_P */ #line 27 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.node) = makeNullAConst((yylsp[(1) - (1)])); ;} + { (yyval.node) = makeNullAConst((yylsp[0])); } +#line 29907 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1325: + case 1335: /* comment_on_type_any_name: TABLE */ #line 30 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.objtype) = PG_OBJECT_TABLE; ;} + { (yyval.objtype) = PG_OBJECT_TABLE; } +#line 29913 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1326: + case 1336: /* comment_on_type_any_name: SEQUENCE */ #line 31 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.objtype) = PG_OBJECT_SEQUENCE; ;} + { (yyval.objtype) = PG_OBJECT_SEQUENCE; } +#line 29919 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1327: + case 1337: /* comment_on_type_any_name: FUNCTION */ #line 32 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.objtype) = PG_OBJECT_FUNCTION; ;} + { (yyval.objtype) = PG_OBJECT_FUNCTION; } +#line 29925 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1328: + case 1338: /* comment_on_type_any_name: MACRO */ #line 33 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.objtype) = PG_OBJECT_FUNCTION; ;} + { (yyval.objtype) = PG_OBJECT_FUNCTION; } +#line 29931 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1329: + case 1339: /* comment_on_type_any_name: MACRO TABLE */ #line 34 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.objtype) = PG_OBJECT_TABLE_MACRO; ;} + { (yyval.objtype) = PG_OBJECT_TABLE_MACRO; } +#line 29937 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1330: + case 1340: /* comment_on_type_any_name: VIEW */ #line 35 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.objtype) = PG_OBJECT_VIEW; ;} + { (yyval.objtype) = PG_OBJECT_VIEW; } +#line 29943 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1331: + case 1341: /* comment_on_type_any_name: DATABASE */ #line 36 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.objtype) = PG_OBJECT_DATABASE; ;} + { (yyval.objtype) = PG_OBJECT_DATABASE; } +#line 29949 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1332: + case 1342: /* comment_on_type_any_name: INDEX */ #line 37 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.objtype) = PG_OBJECT_INDEX; ;} + { (yyval.objtype) = PG_OBJECT_INDEX; } +#line 29955 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1333: + case 1343: /* comment_on_type_any_name: SCHEMA */ #line 38 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.objtype) = PG_OBJECT_SCHEMA; ;} + { (yyval.objtype) = PG_OBJECT_SCHEMA; } +#line 29961 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1334: + case 1344: /* comment_on_type_any_name: TYPE_P */ #line 39 "third_party/libpg_query/grammar/statements/comment_on.y" - { (yyval.objtype) = PG_OBJECT_TYPE; ;} + { (yyval.objtype) = PG_OBJECT_TYPE; } +#line 29967 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1335: + case 1345: /* ExportStmt: EXPORT_P DATABASE Sconst copy_options */ #line 8 "third_party/libpg_query/grammar/statements/export.y" - { + { PGExportStmt *n = makeNode(PGExportStmt); n->database = NULL; - n->filename = (yyvsp[(3) - (4)].str); + n->filename = (yyvsp[-1].str); n->options = NIL; - if ((yyvsp[(4) - (4)].list)) { - n->options = list_concat(n->options, (yyvsp[(4) - (4)].list)); + if ((yyvsp[0].list)) { + n->options = list_concat(n->options, (yyvsp[0].list)); } (yyval.node) = (PGNode *)n; - ;} + } +#line 29982 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1336: + case 1346: /* ExportStmt: EXPORT_P DATABASE ColId TO Sconst copy_options */ #line 20 "third_party/libpg_query/grammar/statements/export.y" - { + { PGExportStmt *n = makeNode(PGExportStmt); - n->database = (yyvsp[(3) - (6)].str); - n->filename = (yyvsp[(5) - (6)].str); + n->database = (yyvsp[-3].str); + n->filename = (yyvsp[-1].str); n->options = NIL; - if ((yyvsp[(6) - (6)].list)) { - n->options = list_concat(n->options, (yyvsp[(6) - (6)].list)); + if ((yyvsp[0].list)) { + n->options = list_concat(n->options, (yyvsp[0].list)); } (yyval.node) = (PGNode *)n; - ;} + } +#line 29997 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1337: + case 1347: /* ImportStmt: IMPORT_P DATABASE Sconst */ #line 34 "third_party/libpg_query/grammar/statements/export.y" - { + { PGImportStmt *n = makeNode(PGImportStmt); - n->filename = (yyvsp[(3) - (3)].str); + n->filename = (yyvsp[0].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 30007 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1338: + case 1348: /* ExplainStmt: EXPLAIN ExplainableStmt */ #line 10 "third_party/libpg_query/grammar/statements/explain.y" - { + { PGExplainStmt *n = makeNode(PGExplainStmt); - n->query = (yyvsp[(2) - (2)].node); + n->query = (yyvsp[0].node); n->options = NIL; (yyval.node) = (PGNode *) n; - ;} + } +#line 30018 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1339: + case 1349: /* ExplainStmt: EXPLAIN analyze_keyword opt_verbose ExplainableStmt */ #line 17 "third_party/libpg_query/grammar/statements/explain.y" - { + { PGExplainStmt *n = makeNode(PGExplainStmt); - n->query = (yyvsp[(4) - (4)].node); - n->options = list_make1(makeDefElem("analyze", NULL, (yylsp[(2) - (4)]))); - if ((yyvsp[(3) - (4)].boolean)) + n->query = (yyvsp[0].node); + n->options = list_make1(makeDefElem("analyze", NULL, (yylsp[-2]))); + if ((yyvsp[-1].boolean)) n->options = lappend(n->options, - makeDefElem("verbose", NULL, (yylsp[(3) - (4)]))); + makeDefElem("verbose", NULL, (yylsp[-1]))); (yyval.node) = (PGNode *) n; - ;} + } +#line 30032 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1340: + case 1350: /* ExplainStmt: EXPLAIN VERBOSE ExplainableStmt */ #line 27 "third_party/libpg_query/grammar/statements/explain.y" - { + { PGExplainStmt *n = makeNode(PGExplainStmt); - n->query = (yyvsp[(3) - (3)].node); - n->options = list_make1(makeDefElem("verbose", NULL, (yylsp[(2) - (3)]))); + n->query = (yyvsp[0].node); + n->options = list_make1(makeDefElem("verbose", NULL, (yylsp[-1]))); (yyval.node) = (PGNode *) n; - ;} + } +#line 30043 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1341: + case 1351: /* ExplainStmt: EXPLAIN '(' explain_option_list ')' ExplainableStmt */ #line 34 "third_party/libpg_query/grammar/statements/explain.y" - { + { PGExplainStmt *n = makeNode(PGExplainStmt); - n->query = (yyvsp[(5) - (5)].node); - n->options = (yyvsp[(3) - (5)].list); + n->query = (yyvsp[0].node); + n->options = (yyvsp[-2].list); (yyval.node) = (PGNode *) n; - ;} + } +#line 30054 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1342: + case 1352: /* opt_verbose: VERBOSE */ #line 44 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 30060 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1343: + case 1353: /* opt_verbose: %empty */ #line 45 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 30066 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1344: + case 1354: /* explain_option_arg: opt_boolean_or_string */ #line 50 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} + { (yyval.node) = (PGNode *) makeString((yyvsp[0].str)); } +#line 30072 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1345: + case 1355: /* explain_option_arg: NumericOnly */ #line 51 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].value); ;} + { (yyval.node) = (PGNode *) (yyvsp[0].value); } +#line 30078 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1346: + case 1356: /* explain_option_arg: %empty */ #line 52 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.node) = NULL; ;} - break; - - case 1377: -#line 90 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.node) = NULL; } +#line 30084 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1378: + case 1388: /* NonReservedWord: IDENT */ #line 91 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 30090 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1379: + case 1389: /* NonReservedWord: unreserved_keyword */ #line 92 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 30096 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1380: -#line 97 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1390: /* NonReservedWord: other_keyword */ +#line 93 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = pstrdup((yyvsp[0].keyword)); } +#line 30102 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1381: + case 1391: /* NonReservedWord_or_Sconst: NonReservedWord */ #line 98 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 30108 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1382: -#line 104 "third_party/libpg_query/grammar/statements/explain.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); - ;} + case 1392: /* NonReservedWord_or_Sconst: Sconst */ +#line 99 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (yyvsp[0].str); } +#line 30114 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1383: -#line 108 "third_party/libpg_query/grammar/statements/explain.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); - ;} + case 1393: /* explain_option_list: explain_option_elem */ +#line 105 "third_party/libpg_query/grammar/statements/explain.y" + { + (yyval.list) = list_make1((yyvsp[0].defelt)); + } +#line 30122 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1384: -#line 115 "third_party/libpg_query/grammar/statements/explain.y" - {;} + case 1394: /* explain_option_list: explain_option_list ',' explain_option_elem */ +#line 109 "third_party/libpg_query/grammar/statements/explain.y" + { + (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].defelt)); + } +#line 30130 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1385: + case 1395: /* analyze_keyword: ANALYZE */ #line 116 "third_party/libpg_query/grammar/statements/explain.y" - {;} + {} +#line 30136 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1386: -#line 121 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (char*) "true"; ;} + case 1396: /* analyze_keyword: ANALYSE */ +#line 117 "third_party/libpg_query/grammar/statements/explain.y" + {} +#line 30142 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1387: + case 1397: /* opt_boolean_or_string: TRUE_P */ #line 122 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (char*) "false"; ;} + { (yyval.str) = (char*) "true"; } +#line 30148 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1388: + case 1398: /* opt_boolean_or_string: FALSE_P */ #line 123 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (char*) "on"; ;} + { (yyval.str) = (char*) "false"; } +#line 30154 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1389: -#line 129 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1399: /* opt_boolean_or_string: ON */ +#line 124 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (char*) "on"; } +#line 30160 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1390: -#line 135 "third_party/libpg_query/grammar/statements/explain.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); - ;} + case 1400: /* opt_boolean_or_string: NonReservedWord_or_Sconst */ +#line 130 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (yyvsp[0].str); } +#line 30166 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1391: -#line 142 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1401: /* explain_option_elem: explain_option_name explain_option_arg */ +#line 136 "third_party/libpg_query/grammar/statements/explain.y" + { + (yyval.defelt) = makeDefElem((yyvsp[-1].str), (yyvsp[0].node), (yylsp[-1])); + } +#line 30174 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1392: + case 1402: /* explain_option_name: NonReservedWord */ #line 143 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (char*) "analyze"; ;} + { (yyval.str) = (yyvsp[0].str); } +#line 30180 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 1403: /* explain_option_name: analyze_keyword */ +#line 144 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (char*) "analyze"; } +#line 30186 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1393: + case 1404: /* VariableSetStmt: SET set_rest */ #line 11 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = (yyvsp[(2) - (2)].vsetstmt); + { + PGVariableSetStmt *n = (yyvsp[0].vsetstmt); n->scope = VAR_SET_SCOPE_DEFAULT; (yyval.node) = (PGNode *) n; - ;} + } +#line 30196 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1394: + case 1405: /* VariableSetStmt: SET LOCAL set_rest */ #line 17 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = (yyvsp[(3) - (3)].vsetstmt); + { + PGVariableSetStmt *n = (yyvsp[0].vsetstmt); n->scope = VAR_SET_SCOPE_LOCAL; (yyval.node) = (PGNode *) n; - ;} + } +#line 30206 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1395: + case 1406: /* VariableSetStmt: SET SESSION set_rest */ #line 23 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = (yyvsp[(3) - (3)].vsetstmt); + { + PGVariableSetStmt *n = (yyvsp[0].vsetstmt); n->scope = VAR_SET_SCOPE_SESSION; (yyval.node) = (PGNode *) n; - ;} + } +#line 30216 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1396: + case 1407: /* VariableSetStmt: SET GLOBAL set_rest */ #line 29 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = (yyvsp[(3) - (3)].vsetstmt); + { + PGVariableSetStmt *n = (yyvsp[0].vsetstmt); n->scope = VAR_SET_SCOPE_GLOBAL; (yyval.node) = (PGNode *) n; - ;} + } +#line 30226 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1397: + case 1408: /* set_rest: generic_set */ #line 38 "third_party/libpg_query/grammar/statements/variable_set.y" - {(yyval.vsetstmt) = (yyvsp[(1) - (1)].vsetstmt);;} + {(yyval.vsetstmt) = (yyvsp[0].vsetstmt);} +#line 30232 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1398: + case 1409: /* set_rest: var_name FROM CURRENT_P */ #line 40 "third_party/libpg_query/grammar/statements/variable_set.y" - { + { PGVariableSetStmt *n = makeNode(PGVariableSetStmt); n->kind = VAR_SET_CURRENT; - n->name = (yyvsp[(1) - (3)].str); + n->name = (yyvsp[-2].str); (yyval.vsetstmt) = n; - ;} + } +#line 30243 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1399: + case 1410: /* set_rest: TIME ZONE zone_value */ #line 48 "third_party/libpg_query/grammar/statements/variable_set.y" - { + { PGVariableSetStmt *n = makeNode(PGVariableSetStmt); n->kind = VAR_SET_VALUE; n->name = (char*) "timezone"; - if ((yyvsp[(3) - (3)].node) != NULL) - n->args = list_make1((yyvsp[(3) - (3)].node)); + if ((yyvsp[0].node) != NULL) + n->args = list_make1((yyvsp[0].node)); else n->kind = VAR_SET_DEFAULT; (yyval.vsetstmt) = n; - ;} + } +#line 30258 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1400: + case 1411: /* set_rest: SCHEMA Sconst */ #line 59 "third_party/libpg_query/grammar/statements/variable_set.y" - { + { PGVariableSetStmt *n = makeNode(PGVariableSetStmt); n->kind = VAR_SET_VALUE; n->name = (char*) "search_path"; - n->args = list_make1(makeStringConst((yyvsp[(2) - (2)].str), (yylsp[(2) - (2)]))); + n->args = list_make1(makeStringConst((yyvsp[0].str), (yylsp[0]))); (yyval.vsetstmt) = n; - ;} + } +#line 30270 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1401: + case 1412: /* generic_set: var_name TO var_list */ #line 71 "third_party/libpg_query/grammar/statements/variable_set.y" - { + { PGVariableSetStmt *n = makeNode(PGVariableSetStmt); n->kind = VAR_SET_VALUE; - n->name = (yyvsp[(1) - (3)].str); - n->args = (yyvsp[(3) - (3)].list); + n->name = (yyvsp[-2].str); + n->args = (yyvsp[0].list); (yyval.vsetstmt) = n; - ;} + } +#line 30282 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1402: + case 1413: /* generic_set: var_name '=' var_list */ #line 79 "third_party/libpg_query/grammar/statements/variable_set.y" - { + { PGVariableSetStmt *n = makeNode(PGVariableSetStmt); n->kind = VAR_SET_VALUE; - n->name = (yyvsp[(1) - (3)].str); - n->args = (yyvsp[(3) - (3)].list); + n->name = (yyvsp[-2].str); + n->args = (yyvsp[0].list); (yyval.vsetstmt) = n; - ;} + } +#line 30294 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1403: + case 1414: /* var_value: a_expr */ #line 90 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 30300 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1404: + case 1415: /* zone_value: Sconst */ #line 96 "third_party/libpg_query/grammar/statements/variable_set.y" - { - (yyval.node) = makeStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} + { + (yyval.node) = makeStringConst((yyvsp[0].str), (yylsp[0])); + } +#line 30308 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1405: + case 1416: /* zone_value: IDENT */ #line 100 "third_party/libpg_query/grammar/statements/variable_set.y" - { - (yyval.node) = makeStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} + { + (yyval.node) = makeStringConst((yyvsp[0].str), (yylsp[0])); + } +#line 30316 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1406: + case 1417: /* zone_value: ConstInterval Sconst opt_interval */ #line 104 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGTypeName *t = (yyvsp[(1) - (3)].typnam); - if ((yyvsp[(3) - (3)].list) != NIL) + { + PGTypeName *t = (yyvsp[-2].typnam); + if ((yyvsp[0].list) != NIL) { - PGAConst *n = (PGAConst *) linitial((yyvsp[(3) - (3)].list)); + PGAConst *n = (PGAConst *) linitial((yyvsp[0].list)); if ((n->val.val.ival & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0) ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), errmsg("time zone interval must be HOUR or HOUR TO MINUTE"), - parser_errposition((yylsp[(3) - (3)])))); + parser_errposition((yylsp[0])))); } - t->typmods = (yyvsp[(3) - (3)].list); - (yyval.node) = makeStringConstCast((yyvsp[(2) - (3)].str), (yylsp[(2) - (3)]), t); - ;} + t->typmods = (yyvsp[0].list); + (yyval.node) = makeStringConstCast((yyvsp[-1].str), (yylsp[-1]), t); + } +#line 30335 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1407: + case 1418: /* zone_value: ConstInterval '(' Iconst ')' Sconst */ #line 119 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGTypeName *t = (yyvsp[(1) - (5)].typnam); + { + PGTypeName *t = (yyvsp[-4].typnam); t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1), - makeIntConst((yyvsp[(3) - (5)].ival), (yylsp[(3) - (5)]))); - (yyval.node) = makeStringConstCast((yyvsp[(5) - (5)].str), (yylsp[(5) - (5)]), t); - ;} + makeIntConst((yyvsp[-2].ival), (yylsp[-2]))); + (yyval.node) = makeStringConstCast((yyvsp[0].str), (yylsp[0]), t); + } +#line 30346 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1408: + case 1419: /* zone_value: NumericOnly */ #line 125 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.node) = makeAConst((yyvsp[(1) - (1)].value), (yylsp[(1) - (1)])); ;} + { (yyval.node) = makeAConst((yyvsp[0].value), (yylsp[0])); } +#line 30352 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1409: + case 1420: /* zone_value: DEFAULT */ #line 126 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 30358 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1410: + case 1421: /* zone_value: LOCAL */ #line 127 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 30364 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1411: + case 1422: /* var_list: var_value */ #line 131 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + { (yyval.list) = list_make1((yyvsp[0].node)); } +#line 30370 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1412: + case 1423: /* var_list: var_list ',' var_value */ #line 132 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + { (yyval.list) = lappend((yyvsp[-2].list), (yyvsp[0].node)); } +#line 30376 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1413: + case 1424: /* LoadStmt: LOAD file_name */ #line 8 "third_party/libpg_query/grammar/statements/load.y" - { + { PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = (yyvsp[(2) - (2)].str); - n->repository = ""; + n->filename = (yyvsp[0].str); + n->repository = NULL; + n->repo_is_alias = false; + n->version = NULL; n->load_type = PG_LOAD_TYPE_LOAD; (yyval.node) = (PGNode *)n; - ;} + } +#line 30390 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1414: -#line 15 "third_party/libpg_query/grammar/statements/load.y" - { + case 1425: /* LoadStmt: opt_force INSTALL file_name opt_ext_version */ +#line 17 "third_party/libpg_query/grammar/statements/load.y" + { PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = (yyvsp[(2) - (2)].str); - n->repository = ""; - n->load_type = PG_LOAD_TYPE_INSTALL; + n->filename = (yyvsp[-1].str); + n->repository = NULL; + n->repo_is_alias = false; + n->version = (yyvsp[0].str); + n->load_type = (yyvsp[-3].loadinstalltype); (yyval.node) = (PGNode *)n; - ;} + } +#line 30404 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1415: -#line 22 "third_party/libpg_query/grammar/statements/load.y" - { - PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = (yyvsp[(3) - (3)].str); - n->repository = ""; - n->load_type = PG_LOAD_TYPE_FORCE_INSTALL; - (yyval.node) = (PGNode *)n; - ;} + case 1426: /* LoadStmt: opt_force INSTALL file_name FROM ColId opt_ext_version */ +#line 26 "third_party/libpg_query/grammar/statements/load.y" + { + PGLoadStmt *n = makeNode(PGLoadStmt); + n->repository = (yyvsp[-1].str); + n->repo_is_alias = true; + n->filename = (yyvsp[-3].str); + n->version = (yyvsp[0].str); + n->load_type = (yyvsp[-5].loadinstalltype); + (yyval.node) = (PGNode *)n; + } +#line 30418 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1416: -#line 29 "third_party/libpg_query/grammar/statements/load.y" - { - PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = (yyvsp[(2) - (4)].str); - n->repository = (yyvsp[(4) - (4)].str); - n->load_type = PG_LOAD_TYPE_INSTALL; - (yyval.node) = (PGNode *)n; - ;} + case 1427: /* LoadStmt: opt_force INSTALL file_name FROM Sconst opt_ext_version */ +#line 35 "third_party/libpg_query/grammar/statements/load.y" + { + PGLoadStmt *n = makeNode(PGLoadStmt); + n->filename = (yyvsp[-3].str); + n->repository = (yyvsp[-1].str); + n->repo_is_alias = false; + n->version = (yyvsp[0].str); + n->load_type = (yyvsp[-5].loadinstalltype); + (yyval.node) = (PGNode *)n; + } +#line 30432 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1417: -#line 36 "third_party/libpg_query/grammar/statements/load.y" - { - PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = (yyvsp[(3) - (5)].str); - n->repository = (yyvsp[(5) - (5)].str); - n->load_type = PG_LOAD_TYPE_FORCE_INSTALL; - (yyval.node) = (PGNode *)n; - ;} + case 1428: /* opt_force: %empty */ +#line 46 "third_party/libpg_query/grammar/statements/load.y" + { (yyval.loadinstalltype) = PG_LOAD_TYPE_INSTALL; } +#line 30438 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1418: -#line 45 "third_party/libpg_query/grammar/statements/load.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1429: /* opt_force: FORCE */ +#line 47 "third_party/libpg_query/grammar/statements/load.y" + { (yyval.loadinstalltype) = PG_LOAD_TYPE_FORCE_INSTALL; } +#line 30444 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1419: -#line 46 "third_party/libpg_query/grammar/statements/load.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1430: /* file_name: Sconst */ +#line 49 "third_party/libpg_query/grammar/statements/load.y" + { (yyval.str) = (yyvsp[0].str); } +#line 30450 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1420: -#line 48 "third_party/libpg_query/grammar/statements/load.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1431: /* file_name: ColId */ +#line 50 "third_party/libpg_query/grammar/statements/load.y" + { (yyval.str) = (yyvsp[0].str); } +#line 30456 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1421: -#line 49 "third_party/libpg_query/grammar/statements/load.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + case 1432: /* opt_ext_version: %empty */ +#line 53 "third_party/libpg_query/grammar/statements/load.y" + { (yyval.str) = NULL; } +#line 30462 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 1433: /* opt_ext_version: VERSION_P Sconst */ +#line 54 "third_party/libpg_query/grammar/statements/load.y" + { (yyval.str) = (yyvsp[0].str); } +#line 30468 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1422: + case 1434: /* opt_ext_version: VERSION_P ColId */ +#line 55 "third_party/libpg_query/grammar/statements/load.y" + { (yyval.str) = (yyvsp[0].str); } +#line 30474 "third_party/libpg_query/grammar/grammar_out.cpp" + break; + + case 1435: /* VacuumStmt: VACUUM opt_full opt_freeze opt_verbose */ #line 9 "third_party/libpg_query/grammar/statements/vacuum.y" - { + { PGVacuumStmt *n = makeNode(PGVacuumStmt); n->options = PG_VACOPT_VACUUM; - if ((yyvsp[(2) - (4)].boolean)) + if ((yyvsp[-2].boolean)) n->options |= PG_VACOPT_FULL; - if ((yyvsp[(3) - (4)].boolean)) + if ((yyvsp[-1].boolean)) n->options |= PG_VACOPT_FREEZE; - if ((yyvsp[(4) - (4)].boolean)) + if ((yyvsp[0].boolean)) n->options |= PG_VACOPT_VERBOSE; n->relation = NULL; n->va_cols = NIL; (yyval.node) = (PGNode *)n; - ;} + } +#line 30492 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1423: + case 1436: /* VacuumStmt: VACUUM opt_full opt_freeze opt_verbose qualified_name opt_name_list */ #line 23 "third_party/libpg_query/grammar/statements/vacuum.y" - { + { PGVacuumStmt *n = makeNode(PGVacuumStmt); n->options = PG_VACOPT_VACUUM; - if ((yyvsp[(2) - (6)].boolean)) + if ((yyvsp[-4].boolean)) n->options |= PG_VACOPT_FULL; - if ((yyvsp[(3) - (6)].boolean)) + if ((yyvsp[-3].boolean)) n->options |= PG_VACOPT_FREEZE; - if ((yyvsp[(4) - (6)].boolean)) + if ((yyvsp[-2].boolean)) n->options |= PG_VACOPT_VERBOSE; - n->relation = (yyvsp[(5) - (6)].range); - n->va_cols = (yyvsp[(6) - (6)].list); + n->relation = (yyvsp[-1].range); + n->va_cols = (yyvsp[0].list); (yyval.node) = (PGNode *)n; - ;} + } +#line 30510 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1424: + case 1437: /* VacuumStmt: VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt */ #line 37 "third_party/libpg_query/grammar/statements/vacuum.y" - { - PGVacuumStmt *n = (PGVacuumStmt *) (yyvsp[(5) - (5)].node); + { + PGVacuumStmt *n = (PGVacuumStmt *) (yyvsp[0].node); n->options |= PG_VACOPT_VACUUM; - if ((yyvsp[(2) - (5)].boolean)) + if ((yyvsp[-3].boolean)) n->options |= PG_VACOPT_FULL; - if ((yyvsp[(3) - (5)].boolean)) + if ((yyvsp[-2].boolean)) n->options |= PG_VACOPT_FREEZE; - if ((yyvsp[(4) - (5)].boolean)) + if ((yyvsp[-1].boolean)) n->options |= PG_VACOPT_VERBOSE; (yyval.node) = (PGNode *)n; - ;} + } +#line 30526 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1425: + case 1438: /* VacuumStmt: VACUUM '(' vacuum_option_list ')' */ #line 49 "third_party/libpg_query/grammar/statements/vacuum.y" - { + { PGVacuumStmt *n = makeNode(PGVacuumStmt); - n->options = PG_VACOPT_VACUUM | (yyvsp[(3) - (4)].ival); + n->options = PG_VACOPT_VACUUM | (yyvsp[-1].ival); n->relation = NULL; n->va_cols = NIL; (yyval.node) = (PGNode *) n; - ;} + } +#line 30538 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1426: + case 1439: /* VacuumStmt: VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list */ #line 57 "third_party/libpg_query/grammar/statements/vacuum.y" - { + { PGVacuumStmt *n = makeNode(PGVacuumStmt); - n->options = PG_VACOPT_VACUUM | (yyvsp[(3) - (6)].ival); - n->relation = (yyvsp[(5) - (6)].range); - n->va_cols = (yyvsp[(6) - (6)].list); + n->options = PG_VACOPT_VACUUM | (yyvsp[-3].ival); + n->relation = (yyvsp[-1].range); + n->va_cols = (yyvsp[0].list); if (n->va_cols != NIL) /* implies analyze */ n->options |= PG_VACOPT_ANALYZE; (yyval.node) = (PGNode *) n; - ;} + } +#line 30552 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1427: + case 1440: /* vacuum_option_elem: analyze_keyword */ #line 70 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = PG_VACOPT_ANALYZE; ;} + { (yyval.ival) = PG_VACOPT_ANALYZE; } +#line 30558 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1428: + case 1441: /* vacuum_option_elem: VERBOSE */ #line 71 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = PG_VACOPT_VERBOSE; ;} + { (yyval.ival) = PG_VACOPT_VERBOSE; } +#line 30564 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1429: + case 1442: /* vacuum_option_elem: FREEZE */ #line 72 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = PG_VACOPT_FREEZE; ;} + { (yyval.ival) = PG_VACOPT_FREEZE; } +#line 30570 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1430: + case 1443: /* vacuum_option_elem: FULL */ #line 73 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = PG_VACOPT_FULL; ;} + { (yyval.ival) = PG_VACOPT_FULL; } +#line 30576 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1431: + case 1444: /* vacuum_option_elem: IDENT */ #line 75 "third_party/libpg_query/grammar/statements/vacuum.y" - { - if (strcmp((yyvsp[(1) - (1)].str), "disable_page_skipping") == 0) + { + if (strcmp((yyvsp[0].str), "disable_page_skipping") == 0) (yyval.ival) = PG_VACOPT_DISABLE_PAGE_SKIPPING; else ereport(ERROR, (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("unrecognized VACUUM option \"%s\"", (yyvsp[(1) - (1)].str)), - parser_errposition((yylsp[(1) - (1)])))); - ;} + errmsg("unrecognized VACUUM option \"%s\"", (yyvsp[0].str)), + parser_errposition((yylsp[0])))); + } +#line 30590 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1432: + case 1445: /* opt_full: FULL */ #line 87 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 30596 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1433: + case 1446: /* opt_full: %empty */ #line 88 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 30602 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1434: + case 1447: /* vacuum_option_list: vacuum_option_elem */ #line 93 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} + { (yyval.ival) = (yyvsp[0].ival); } +#line 30608 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1435: + case 1448: /* vacuum_option_list: vacuum_option_list ',' vacuum_option_elem */ #line 94 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival); ;} + { (yyval.ival) = (yyvsp[-2].ival) | (yyvsp[0].ival); } +#line 30614 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1436: + case 1449: /* opt_freeze: FREEZE */ #line 98 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 30620 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1437: + case 1450: /* opt_freeze: %empty */ #line 99 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 30626 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1438: + case 1451: /* DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias using_clause where_or_current_clause returning_clause */ #line 9 "third_party/libpg_query/grammar/statements/delete.y" - { + { PGDeleteStmt *n = makeNode(PGDeleteStmt); - n->relation = (yyvsp[(4) - (7)].range); - n->usingClause = (yyvsp[(5) - (7)].list); - n->whereClause = (yyvsp[(6) - (7)].node); - n->returningList = (yyvsp[(7) - (7)].list); - n->withClause = (yyvsp[(1) - (7)].with); + n->relation = (yyvsp[-3].range); + n->usingClause = (yyvsp[-2].list); + n->whereClause = (yyvsp[-1].node); + n->returningList = (yyvsp[0].list); + n->withClause = (yyvsp[-6].with); (yyval.node) = (PGNode *)n; - ;} + } +#line 30640 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1439: + case 1452: /* DeleteStmt: TRUNCATE opt_table relation_expr_opt_alias */ #line 19 "third_party/libpg_query/grammar/statements/delete.y" - { + { PGDeleteStmt *n = makeNode(PGDeleteStmt); - n->relation = (yyvsp[(3) - (3)].range); + n->relation = (yyvsp[0].range); n->usingClause = NULL; n->whereClause = NULL; n->returningList = NULL; n->withClause = NULL; (yyval.node) = (PGNode *)n; - ;} + } +#line 30654 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1440: + case 1453: /* relation_expr_opt_alias: relation_expr */ #line 32 "third_party/libpg_query/grammar/statements/delete.y" - { - (yyval.range) = (yyvsp[(1) - (1)].range); - ;} + { + (yyval.range) = (yyvsp[0].range); + } +#line 30662 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1441: + case 1454: /* relation_expr_opt_alias: relation_expr ColId */ #line 36 "third_party/libpg_query/grammar/statements/delete.y" - { + { PGAlias *alias = makeNode(PGAlias); - alias->aliasname = (yyvsp[(2) - (2)].str); - (yyvsp[(1) - (2)].range)->alias = alias; - (yyval.range) = (yyvsp[(1) - (2)].range); - ;} + alias->aliasname = (yyvsp[0].str); + (yyvsp[-1].range)->alias = alias; + (yyval.range) = (yyvsp[-1].range); + } +#line 30673 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1442: + case 1455: /* relation_expr_opt_alias: relation_expr AS ColId */ #line 43 "third_party/libpg_query/grammar/statements/delete.y" - { + { PGAlias *alias = makeNode(PGAlias); - alias->aliasname = (yyvsp[(3) - (3)].str); - (yyvsp[(1) - (3)].range)->alias = alias; - (yyval.range) = (yyvsp[(1) - (3)].range); - ;} + alias->aliasname = (yyvsp[0].str); + (yyvsp[-2].range)->alias = alias; + (yyval.range) = (yyvsp[-2].range); + } +#line 30684 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1443: + case 1456: /* where_or_current_clause: WHERE a_expr */ #line 53 "third_party/libpg_query/grammar/statements/delete.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + { (yyval.node) = (yyvsp[0].node); } +#line 30690 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1444: + case 1457: /* where_or_current_clause: %empty */ #line 54 "third_party/libpg_query/grammar/statements/delete.y" - { (yyval.node) = NULL; ;} + { (yyval.node) = NULL; } +#line 30696 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1445: + case 1458: /* using_clause: USING from_list_opt_comma */ #line 60 "third_party/libpg_query/grammar/statements/delete.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + { (yyval.list) = (yyvsp[0].list); } +#line 30702 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1446: + case 1459: /* using_clause: %empty */ #line 61 "third_party/libpg_query/grammar/statements/delete.y" - { (yyval.list) = NIL; ;} + { (yyval.list) = NIL; } +#line 30708 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1447: + case 1460: /* AnalyzeStmt: analyze_keyword opt_verbose */ #line 10 "third_party/libpg_query/grammar/statements/analyze.y" - { + { PGVacuumStmt *n = makeNode(PGVacuumStmt); n->options = PG_VACOPT_ANALYZE; - if ((yyvsp[(2) - (2)].boolean)) + if ((yyvsp[0].boolean)) n->options |= PG_VACOPT_VERBOSE; n->relation = NULL; n->va_cols = NIL; (yyval.node) = (PGNode *)n; - ;} + } +#line 30722 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1448: + case 1461: /* AnalyzeStmt: analyze_keyword opt_verbose qualified_name opt_name_list */ #line 20 "third_party/libpg_query/grammar/statements/analyze.y" - { + { PGVacuumStmt *n = makeNode(PGVacuumStmt); n->options = PG_VACOPT_ANALYZE; - if ((yyvsp[(2) - (4)].boolean)) + if ((yyvsp[-2].boolean)) n->options |= PG_VACOPT_VERBOSE; - n->relation = (yyvsp[(3) - (4)].range); - n->va_cols = (yyvsp[(4) - (4)].list); + n->relation = (yyvsp[-1].range); + n->va_cols = (yyvsp[0].list); (yyval.node) = (PGNode *)n; - ;} + } +#line 30736 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1449: + case 1462: /* AttachStmt: ATTACH opt_database Sconst opt_database_alias copy_options */ #line 8 "third_party/libpg_query/grammar/statements/attach.y" - { + { PGAttachStmt *n = makeNode(PGAttachStmt); - n->path = (yyvsp[(3) - (5)].str); - n->name = (yyvsp[(4) - (5)].str); - n->options = (yyvsp[(5) - (5)].list); + n->path = (yyvsp[-2].str); + n->name = (yyvsp[-1].str); + n->options = (yyvsp[0].list); n->onconflict = PG_ERROR_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 30749 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1450: + case 1463: /* AttachStmt: ATTACH IF_P NOT EXISTS opt_database Sconst opt_database_alias copy_options */ #line 17 "third_party/libpg_query/grammar/statements/attach.y" - { + { PGAttachStmt *n = makeNode(PGAttachStmt); - n->path = (yyvsp[(6) - (8)].str); - n->name = (yyvsp[(7) - (8)].str); - n->options = (yyvsp[(8) - (8)].list); + n->path = (yyvsp[-2].str); + n->name = (yyvsp[-1].str); + n->options = (yyvsp[0].list); n->onconflict = PG_IGNORE_ON_CONFLICT; (yyval.node) = (PGNode *)n; - ;} + } +#line 30762 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1451: + case 1464: /* DetachStmt: DETACH ColLabel */ #line 29 "third_party/libpg_query/grammar/statements/attach.y" - { + { PGDetachStmt *n = makeNode(PGDetachStmt); n->missing_ok = false; - n->db_name = (yyvsp[(2) - (2)].str); + n->db_name = (yyvsp[0].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 30773 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1452: + case 1465: /* DetachStmt: DETACH DATABASE ColLabel */ #line 36 "third_party/libpg_query/grammar/statements/attach.y" - { + { PGDetachStmt *n = makeNode(PGDetachStmt); n->missing_ok = false; - n->db_name = (yyvsp[(3) - (3)].str); + n->db_name = (yyvsp[0].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 30784 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1453: + case 1466: /* DetachStmt: DETACH DATABASE IF_P EXISTS ColLabel */ #line 43 "third_party/libpg_query/grammar/statements/attach.y" - { + { PGDetachStmt *n = makeNode(PGDetachStmt); n->missing_ok = true; - n->db_name = (yyvsp[(5) - (5)].str); + n->db_name = (yyvsp[0].str); (yyval.node) = (PGNode *)n; - ;} + } +#line 30795 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1454: + case 1467: /* opt_database: DATABASE */ #line 51 "third_party/libpg_query/grammar/statements/attach.y" - {;} + {} +#line 30801 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1455: + case 1468: /* opt_database: %empty */ #line 52 "third_party/libpg_query/grammar/statements/attach.y" - {;} + {} +#line 30807 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1456: + case 1469: /* opt_database_alias: AS ColId */ #line 56 "third_party/libpg_query/grammar/statements/attach.y" - { (yyval.str) = (yyvsp[(2) - (2)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 30813 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1457: + case 1470: /* opt_database_alias: %empty */ #line 57 "third_party/libpg_query/grammar/statements/attach.y" - { (yyval.str) = NULL; ;} + { (yyval.str) = NULL; } +#line 30819 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1458: + case 1471: /* VariableResetStmt: RESET reset_rest */ #line 3 "third_party/libpg_query/grammar/statements/variable_reset.y" - { - (yyvsp[(2) - (2)].vsetstmt)->scope = VAR_SET_SCOPE_DEFAULT; - (yyval.node) = (PGNode *) (yyvsp[(2) - (2)].vsetstmt); - ;} + { + (yyvsp[0].vsetstmt)->scope = VAR_SET_SCOPE_DEFAULT; + (yyval.node) = (PGNode *) (yyvsp[0].vsetstmt); + } +#line 30828 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1459: + case 1472: /* VariableResetStmt: RESET LOCAL reset_rest */ #line 8 "third_party/libpg_query/grammar/statements/variable_reset.y" - { - (yyvsp[(3) - (3)].vsetstmt)->scope = VAR_SET_SCOPE_LOCAL; - (yyval.node) = (PGNode *) (yyvsp[(3) - (3)].vsetstmt); - ;} + { + (yyvsp[0].vsetstmt)->scope = VAR_SET_SCOPE_LOCAL; + (yyval.node) = (PGNode *) (yyvsp[0].vsetstmt); + } +#line 30837 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1460: + case 1473: /* VariableResetStmt: RESET SESSION reset_rest */ #line 13 "third_party/libpg_query/grammar/statements/variable_reset.y" - { - (yyvsp[(3) - (3)].vsetstmt)->scope = VAR_SET_SCOPE_SESSION; - (yyval.node) = (PGNode *) (yyvsp[(3) - (3)].vsetstmt); - ;} + { + (yyvsp[0].vsetstmt)->scope = VAR_SET_SCOPE_SESSION; + (yyval.node) = (PGNode *) (yyvsp[0].vsetstmt); + } +#line 30846 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1461: + case 1474: /* VariableResetStmt: RESET GLOBAL reset_rest */ #line 18 "third_party/libpg_query/grammar/statements/variable_reset.y" - { - (yyvsp[(3) - (3)].vsetstmt)->scope = VAR_SET_SCOPE_GLOBAL; - (yyval.node) = (PGNode *) (yyvsp[(3) - (3)].vsetstmt); - ;} + { + (yyvsp[0].vsetstmt)->scope = VAR_SET_SCOPE_GLOBAL; + (yyval.node) = (PGNode *) (yyvsp[0].vsetstmt); + } +#line 30855 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1462: + case 1475: /* generic_reset: var_name */ #line 27 "third_party/libpg_query/grammar/statements/variable_reset.y" - { + { PGVariableSetStmt *n = makeNode(PGVariableSetStmt); n->kind = VAR_RESET; - n->name = (yyvsp[(1) - (1)].str); + n->name = (yyvsp[0].str); (yyval.vsetstmt) = n; - ;} + } +#line 30866 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1463: + case 1476: /* generic_reset: ALL */ #line 34 "third_party/libpg_query/grammar/statements/variable_reset.y" - { + { PGVariableSetStmt *n = makeNode(PGVariableSetStmt); n->kind = VAR_RESET_ALL; (yyval.vsetstmt) = n; - ;} + } +#line 30876 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1464: + case 1477: /* reset_rest: generic_reset */ #line 43 "third_party/libpg_query/grammar/statements/variable_reset.y" - { (yyval.vsetstmt) = (yyvsp[(1) - (1)].vsetstmt); ;} + { (yyval.vsetstmt) = (yyvsp[0].vsetstmt); } +#line 30882 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1465: + case 1478: /* reset_rest: TIME ZONE */ #line 45 "third_party/libpg_query/grammar/statements/variable_reset.y" - { + { PGVariableSetStmt *n = makeNode(PGVariableSetStmt); n->kind = VAR_RESET; n->name = (char*) "timezone"; (yyval.vsetstmt) = n; - ;} + } +#line 30893 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1466: + case 1479: /* reset_rest: TRANSACTION ISOLATION LEVEL */ #line 52 "third_party/libpg_query/grammar/statements/variable_reset.y" - { + { PGVariableSetStmt *n = makeNode(PGVariableSetStmt); n->kind = VAR_RESET; n->name = (char*) "transaction_isolation"; (yyval.vsetstmt) = n; - ;} + } +#line 30904 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1467: + case 1480: /* VariableShowStmt: show_or_describe SelectStmt */ #line 3 "third_party/libpg_query/grammar/statements/variable_show.y" - { + { PGVariableShowSelectStmt *n = makeNode(PGVariableShowSelectStmt); - n->stmt = (yyvsp[(2) - (2)].node); + n->stmt = (yyvsp[0].node); n->name = (char*) "select"; n->is_summary = 0; (yyval.node) = (PGNode *) n; - ;} + } +#line 30916 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1468: + case 1481: /* VariableShowStmt: SUMMARIZE SelectStmt */ #line 10 "third_party/libpg_query/grammar/statements/variable_show.y" - { + { PGVariableShowSelectStmt *n = makeNode(PGVariableShowSelectStmt); - n->stmt = (yyvsp[(2) - (2)].node); + n->stmt = (yyvsp[0].node); n->name = (char*) "select"; n->is_summary = 1; (yyval.node) = (PGNode *) n; - ;} + } +#line 30928 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1469: + case 1482: /* VariableShowStmt: SUMMARIZE table_id */ #line 18 "third_party/libpg_query/grammar/statements/variable_show.y" - { + { PGVariableShowStmt *n = makeNode(PGVariableShowStmt); - n->name = (yyvsp[(2) - (2)].str); + n->name = (yyvsp[0].str); n->is_summary = 1; (yyval.node) = (PGNode *) n; - ;} + } +#line 30939 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1470: + case 1483: /* VariableShowStmt: show_or_describe table_id */ #line 25 "third_party/libpg_query/grammar/statements/variable_show.y" - { + { PGVariableShowStmt *n = makeNode(PGVariableShowStmt); - n->name = (yyvsp[(2) - (2)].str); + n->name = (yyvsp[0].str); n->is_summary = 0; (yyval.node) = (PGNode *) n; - ;} + } +#line 30950 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1471: + case 1484: /* VariableShowStmt: show_or_describe TIME ZONE */ #line 32 "third_party/libpg_query/grammar/statements/variable_show.y" - { + { PGVariableShowStmt *n = makeNode(PGVariableShowStmt); n->name = (char*) "timezone"; n->is_summary = 0; (yyval.node) = (PGNode *) n; - ;} + } +#line 30961 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1472: + case 1485: /* VariableShowStmt: show_or_describe TRANSACTION ISOLATION LEVEL */ #line 39 "third_party/libpg_query/grammar/statements/variable_show.y" - { + { PGVariableShowStmt *n = makeNode(PGVariableShowStmt); n->name = (char*) "transaction_isolation"; n->is_summary = 0; (yyval.node) = (PGNode *) n; - ;} + } +#line 30972 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1473: + case 1486: /* VariableShowStmt: show_or_describe ALL opt_tables */ #line 46 "third_party/libpg_query/grammar/statements/variable_show.y" - { + { PGVariableShowStmt *n = makeNode(PGVariableShowStmt); n->name = (char*) "__show_tables_expanded"; n->is_summary = 0; (yyval.node) = (PGNode *) n; - ;} + } +#line 30983 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1474: + case 1487: /* VariableShowStmt: show_or_describe */ #line 53 "third_party/libpg_query/grammar/statements/variable_show.y" - { + { PGVariableShowStmt *n = makeNode(PGVariableShowStmt); n->name = (char*) "__show_tables_expanded"; n->is_summary = 0; (yyval.node) = (PGNode *) n; - ;} + } +#line 30994 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1481: + case 1494: /* var_name: ColId */ #line 67 "third_party/libpg_query/grammar/statements/variable_show.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + { (yyval.str) = (yyvsp[0].str); } +#line 31000 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1482: + case 1495: /* var_name: var_name '.' ColId */ #line 69 "third_party/libpg_query/grammar/statements/variable_show.y" - { (yyval.str) = psprintf("%s.%s", (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str)); ;} + { (yyval.str) = psprintf("%s.%s", (yyvsp[-2].str), (yyvsp[0].str)); } +#line 31006 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1483: + case 1496: /* table_id: ColId */ #line 72 "third_party/libpg_query/grammar/statements/variable_show.y" - { (yyval.str) = psprintf("\"%s\"", (yyvsp[(1) - (1)].str)); ;} + { (yyval.str) = psprintf("\"%s\"", (yyvsp[0].str)); } +#line 31012 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1484: + case 1497: /* table_id: table_id '.' ColId */ #line 74 "third_party/libpg_query/grammar/statements/variable_show.y" - { (yyval.str) = psprintf("%s.\"%s\"", (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str)); ;} + { (yyval.str) = psprintf("%s.\"%s\"", (yyvsp[-2].str), (yyvsp[0].str)); } +#line 31018 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1485: + case 1498: /* CallStmt: CALL_P func_application */ #line 7 "third_party/libpg_query/grammar/statements/call.y" - { + { PGCallStmt *n = makeNode(PGCallStmt); - n->func = (yyvsp[(2) - (2)].node); + n->func = (yyvsp[0].node); (yyval.node) = (PGNode *) n; - ;} + } +#line 31028 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1486: + case 1499: /* ViewStmt: CREATE_P OptTemp VIEW qualified_name opt_column_list opt_reloptions AS SelectStmt opt_check_option */ #line 10 "third_party/libpg_query/grammar/statements/view.y" - { + { PGViewStmt *n = makeNode(PGViewStmt); - n->view = (yyvsp[(4) - (9)].range); - n->view->relpersistence = (yyvsp[(2) - (9)].ival); - n->aliases = (yyvsp[(5) - (9)].list); - n->query = (yyvsp[(8) - (9)].node); + n->view = (yyvsp[-5].range); + n->view->relpersistence = (yyvsp[-7].ival); + n->aliases = (yyvsp[-4].list); + n->query = (yyvsp[-1].node); n->onconflict = PG_ERROR_ON_CONFLICT; - n->options = (yyvsp[(6) - (9)].list); - n->withCheckOption = (yyvsp[(9) - (9)].viewcheckoption); + n->options = (yyvsp[-3].list); + n->withCheckOption = (yyvsp[0].viewcheckoption); (yyval.node) = (PGNode *) n; - ;} + } +#line 31044 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1487: + case 1500: /* ViewStmt: CREATE_P OptTemp VIEW IF_P NOT EXISTS qualified_name opt_column_list opt_reloptions AS SelectStmt opt_check_option */ #line 23 "third_party/libpg_query/grammar/statements/view.y" - { + { PGViewStmt *n = makeNode(PGViewStmt); - n->view = (yyvsp[(7) - (12)].range); - n->view->relpersistence = (yyvsp[(2) - (12)].ival); - n->aliases = (yyvsp[(8) - (12)].list); - n->query = (yyvsp[(11) - (12)].node); + n->view = (yyvsp[-5].range); + n->view->relpersistence = (yyvsp[-10].ival); + n->aliases = (yyvsp[-4].list); + n->query = (yyvsp[-1].node); n->onconflict = PG_IGNORE_ON_CONFLICT; - n->options = (yyvsp[(9) - (12)].list); - n->withCheckOption = (yyvsp[(12) - (12)].viewcheckoption); + n->options = (yyvsp[-3].list); + n->withCheckOption = (yyvsp[0].viewcheckoption); (yyval.node) = (PGNode *) n; - ;} + } +#line 31060 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1488: + case 1501: /* ViewStmt: CREATE_P OR REPLACE OptTemp VIEW qualified_name opt_column_list opt_reloptions AS SelectStmt opt_check_option */ #line 36 "third_party/libpg_query/grammar/statements/view.y" - { + { PGViewStmt *n = makeNode(PGViewStmt); - n->view = (yyvsp[(6) - (11)].range); - n->view->relpersistence = (yyvsp[(4) - (11)].ival); - n->aliases = (yyvsp[(7) - (11)].list); - n->query = (yyvsp[(10) - (11)].node); + n->view = (yyvsp[-5].range); + n->view->relpersistence = (yyvsp[-7].ival); + n->aliases = (yyvsp[-4].list); + n->query = (yyvsp[-1].node); n->onconflict = PG_REPLACE_ON_CONFLICT; - n->options = (yyvsp[(8) - (11)].list); - n->withCheckOption = (yyvsp[(11) - (11)].viewcheckoption); + n->options = (yyvsp[-3].list); + n->withCheckOption = (yyvsp[0].viewcheckoption); (yyval.node) = (PGNode *) n; - ;} + } +#line 31076 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1489: + case 1502: /* ViewStmt: CREATE_P OptTemp RECURSIVE VIEW qualified_name '(' columnList ')' opt_reloptions AS SelectStmt opt_check_option */ #line 49 "third_party/libpg_query/grammar/statements/view.y" - { + { PGViewStmt *n = makeNode(PGViewStmt); - n->view = (yyvsp[(5) - (12)].range); - n->view->relpersistence = (yyvsp[(2) - (12)].ival); - n->aliases = (yyvsp[(7) - (12)].list); - n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, (yyvsp[(11) - (12)].node)); + n->view = (yyvsp[-7].range); + n->view->relpersistence = (yyvsp[-10].ival); + n->aliases = (yyvsp[-5].list); + n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, (yyvsp[-1].node)); n->onconflict = PG_ERROR_ON_CONFLICT; - n->options = (yyvsp[(9) - (12)].list); - n->withCheckOption = (yyvsp[(12) - (12)].viewcheckoption); + n->options = (yyvsp[-3].list); + n->withCheckOption = (yyvsp[0].viewcheckoption); if (n->withCheckOption != PG_NO_CHECK_OPTION) ereport(ERROR, (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("WITH CHECK OPTION not supported on recursive views"), - parser_errposition((yylsp[(12) - (12)])))); + parser_errposition((yylsp[0])))); (yyval.node) = (PGNode *) n; - ;} + } +#line 31097 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1490: + case 1503: /* ViewStmt: CREATE_P OR REPLACE OptTemp RECURSIVE VIEW qualified_name '(' columnList ')' opt_reloptions AS SelectStmt opt_check_option */ #line 67 "third_party/libpg_query/grammar/statements/view.y" - { + { PGViewStmt *n = makeNode(PGViewStmt); - n->view = (yyvsp[(7) - (14)].range); - n->view->relpersistence = (yyvsp[(4) - (14)].ival); - n->aliases = (yyvsp[(9) - (14)].list); - n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, (yyvsp[(13) - (14)].node)); + n->view = (yyvsp[-7].range); + n->view->relpersistence = (yyvsp[-10].ival); + n->aliases = (yyvsp[-5].list); + n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, (yyvsp[-1].node)); n->onconflict = PG_REPLACE_ON_CONFLICT; - n->options = (yyvsp[(11) - (14)].list); - n->withCheckOption = (yyvsp[(14) - (14)].viewcheckoption); + n->options = (yyvsp[-3].list); + n->withCheckOption = (yyvsp[0].viewcheckoption); if (n->withCheckOption != PG_NO_CHECK_OPTION) ereport(ERROR, (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("WITH CHECK OPTION not supported on recursive views"), - parser_errposition((yylsp[(14) - (14)])))); + parser_errposition((yylsp[0])))); (yyval.node) = (PGNode *) n; - ;} + } +#line 31118 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1491: + case 1504: /* opt_check_option: WITH CHECK_P OPTION */ #line 87 "third_party/libpg_query/grammar/statements/view.y" - { (yyval.viewcheckoption) = CASCADED_CHECK_OPTION; ;} + { (yyval.viewcheckoption) = CASCADED_CHECK_OPTION; } +#line 31124 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1492: + case 1505: /* opt_check_option: WITH CASCADED CHECK_P OPTION */ #line 88 "third_party/libpg_query/grammar/statements/view.y" - { (yyval.viewcheckoption) = CASCADED_CHECK_OPTION; ;} + { (yyval.viewcheckoption) = CASCADED_CHECK_OPTION; } +#line 31130 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1493: + case 1506: /* opt_check_option: WITH LOCAL CHECK_P OPTION */ #line 89 "third_party/libpg_query/grammar/statements/view.y" - { (yyval.viewcheckoption) = PG_LOCAL_CHECK_OPTION; ;} + { (yyval.viewcheckoption) = PG_LOCAL_CHECK_OPTION; } +#line 31136 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1494: + case 1507: /* opt_check_option: %empty */ #line 90 "third_party/libpg_query/grammar/statements/view.y" - { (yyval.viewcheckoption) = PG_NO_CHECK_OPTION; ;} + { (yyval.viewcheckoption) = PG_NO_CHECK_OPTION; } +#line 31142 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1495: + case 1508: /* CreateAsStmt: CREATE_P OptTemp TABLE create_as_target AS SelectStmt opt_with_data */ #line 12 "third_party/libpg_query/grammar/statements/create_as.y" - { + { PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); - ctas->query = (yyvsp[(6) - (7)].node); - ctas->into = (yyvsp[(4) - (7)].into); + ctas->query = (yyvsp[-1].node); + ctas->into = (yyvsp[-3].into); ctas->relkind = PG_OBJECT_TABLE; ctas->is_select_into = false; ctas->onconflict = PG_ERROR_ON_CONFLICT; /* cram additional flags into the PGIntoClause */ - (yyvsp[(4) - (7)].into)->rel->relpersistence = (yyvsp[(2) - (7)].ival); - (yyvsp[(4) - (7)].into)->skipData = !((yyvsp[(7) - (7)].boolean)); + (yyvsp[-3].into)->rel->relpersistence = (yyvsp[-5].ival); + (yyvsp[-3].into)->skipData = !((yyvsp[0].boolean)); (yyval.node) = (PGNode *) ctas; - ;} + } +#line 31159 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1496: + case 1509: /* CreateAsStmt: CREATE_P OptTemp TABLE IF_P NOT EXISTS create_as_target AS SelectStmt opt_with_data */ #line 25 "third_party/libpg_query/grammar/statements/create_as.y" - { + { PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); - ctas->query = (yyvsp[(9) - (10)].node); - ctas->into = (yyvsp[(7) - (10)].into); + ctas->query = (yyvsp[-1].node); + ctas->into = (yyvsp[-3].into); ctas->relkind = PG_OBJECT_TABLE; ctas->is_select_into = false; ctas->onconflict = PG_IGNORE_ON_CONFLICT; /* cram additional flags into the PGIntoClause */ - (yyvsp[(7) - (10)].into)->rel->relpersistence = (yyvsp[(2) - (10)].ival); - (yyvsp[(7) - (10)].into)->skipData = !((yyvsp[(10) - (10)].boolean)); + (yyvsp[-3].into)->rel->relpersistence = (yyvsp[-8].ival); + (yyvsp[-3].into)->skipData = !((yyvsp[0].boolean)); (yyval.node) = (PGNode *) ctas; - ;} + } +#line 31176 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1497: + case 1510: /* CreateAsStmt: CREATE_P OR REPLACE OptTemp TABLE create_as_target AS SelectStmt opt_with_data */ #line 38 "third_party/libpg_query/grammar/statements/create_as.y" - { + { PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); - ctas->query = (yyvsp[(8) - (9)].node); - ctas->into = (yyvsp[(6) - (9)].into); + ctas->query = (yyvsp[-1].node); + ctas->into = (yyvsp[-3].into); ctas->relkind = PG_OBJECT_TABLE; ctas->is_select_into = false; ctas->onconflict = PG_REPLACE_ON_CONFLICT; /* cram additional flags into the PGIntoClause */ - (yyvsp[(6) - (9)].into)->rel->relpersistence = (yyvsp[(4) - (9)].ival); - (yyvsp[(6) - (9)].into)->skipData = !((yyvsp[(9) - (9)].boolean)); + (yyvsp[-3].into)->rel->relpersistence = (yyvsp[-5].ival); + (yyvsp[-3].into)->skipData = !((yyvsp[0].boolean)); (yyval.node) = (PGNode *) ctas; - ;} + } +#line 31193 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1498: + case 1511: /* opt_with_data: WITH DATA_P */ #line 54 "third_party/libpg_query/grammar/statements/create_as.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 31199 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1499: + case 1512: /* opt_with_data: WITH NO DATA_P */ #line 55 "third_party/libpg_query/grammar/statements/create_as.y" - { (yyval.boolean) = false; ;} + { (yyval.boolean) = false; } +#line 31205 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1500: + case 1513: /* opt_with_data: %empty */ #line 56 "third_party/libpg_query/grammar/statements/create_as.y" - { (yyval.boolean) = true; ;} + { (yyval.boolean) = true; } +#line 31211 "third_party/libpg_query/grammar/grammar_out.cpp" break; - case 1501: + case 1514: /* create_as_target: qualified_name opt_column_list OptWith OnCommitOption */ #line 62 "third_party/libpg_query/grammar/statements/create_as.y" - { + { (yyval.into) = makeNode(PGIntoClause); - (yyval.into)->rel = (yyvsp[(1) - (4)].range); - (yyval.into)->colNames = (yyvsp[(2) - (4)].list); - (yyval.into)->options = (yyvsp[(3) - (4)].list); - (yyval.into)->onCommit = (yyvsp[(4) - (4)].oncommit); + (yyval.into)->rel = (yyvsp[-3].range); + (yyval.into)->colNames = (yyvsp[-2].list); + (yyval.into)->options = (yyvsp[-1].list); + (yyval.into)->onCommit = (yyvsp[0].oncommit); (yyval.into)->viewQuery = NULL; (yyval.into)->skipData = false; /* might get changed later */ - ;} + } +#line 31225 "third_party/libpg_query/grammar/grammar_out.cpp" break; -/* Line 1267 of yacc.c. */ -#line 30744 "third_party/libpg_query/grammar/grammar_out.cpp" +#line 31229 "third_party/libpg_query/grammar/grammar_out.cpp" + default: break; } - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; - YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; *++yylsp = yyloc; - /* Now `shift' the result of the reduction. Determine what state + /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } goto yynewstate; -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; -#if ! YYERROR_VERBOSE yyerror (&yylloc, yyscanner, YY_("syntax error")); -#else - { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (&yylloc, yyscanner, yymsg); - } - else - { - yyerror (&yylloc, yyscanner, YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } - } -#endif } - yyerror_range[0] = yylloc; - + yyerror_range[1] = yylloc; if (yyerrstatus == 3) { - /* If just tried and failed to reuse look-ahead token after an - error, discard it. */ + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } else - { - yydestruct ("Error: discarding", - yytoken, &yylval, &yylloc, yyscanner); - yychar = YYEMPTY; - } + { + yydestruct ("Error: discarding", + yytoken, &yylval, &yylloc, yyscanner); + yychar = YYEMPTY; + } } - /* Else will try to reuse look-ahead token after shifting the error + /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; @@ -30842,15 +31305,13 @@ YYLTYPE yylloc; | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; + ++yynerrs; - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - yyerror_range[0] = yylsp[1-yylen]; - /* Do not reclaim the symbols of the rule which action triggered + /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; @@ -30863,47 +31324,45 @@ YYLTYPE yylloc; | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ + yyerrstatus = 3; /* Each real token shifted decrements this. */ + /* Pop stack until we find a state that shifts the error token. */ for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } + if (!yypact_value_is_default (yyn)) + { + yyn += YYSYMBOL_YYerror; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) - YYABORT; + YYABORT; - yyerror_range[0] = *yylsp; + yyerror_range[1] = *yylsp; yydestruct ("Error: popping", - yystos[yystate], yyvsp, yylsp, yyscanner); + YY_ACCESSING_SYMBOL (yystate), yyvsp, yylsp, yyscanner); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } - if (yyn == YYFINAL) - YYACCEPT; - + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END - yyerror_range[1] = yylloc; - /* Using YYLLOC is tempting, but would change the location of - the look-ahead. YYLOC is available though. */ - YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); - *++yylsp = yyloc; + yyerror_range[2] = yylloc; + ++yylsp; + YYLLOC_DEFAULT (*yylsp, yyerror_range, 2); /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); yystate = yyn; goto yynewstate; @@ -30914,51 +31373,55 @@ YYLTYPE yylloc; `-------------------------------------*/ yyacceptlab: yyresult = 0; - goto yyreturn; + goto yyreturnlab; + /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; - goto yyreturn; + goto yyreturnlab; -#ifndef yyoverflow -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ + +/*-----------------------------------------------------------. +| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | +`-----------------------------------------------------------*/ yyexhaustedlab: yyerror (&yylloc, yyscanner, YY_("memory exhausted")); yyresult = 2; - /* Fall through. */ -#endif + goto yyreturnlab; -yyreturn: - if (yychar != YYEOF && yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, yyscanner); - /* Do not reclaim the symbols of the rule which action triggered + +/*----------------------------------------------------------. +| yyreturnlab -- parsing is finished, clean up and return. | +`----------------------------------------------------------*/ +yyreturnlab: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc, yyscanner); + } + /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, yylsp, yyscanner); + YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yylsp, yyscanner); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - /* Make sure YYID is used. */ - return YYID (yyresult); -} + return yyresult; +} #line 83 "third_party/libpg_query/grammar/statements/create_as.y" @@ -31717,4 +32180,3 @@ parser_init(base_yy_extra_type *yyext) #undef yylloc } // namespace duckdb_libpgquery - diff --git a/third_party/libpg_query/src_backend_parser_scan.cpp b/third_party/libpg_query/src_backend_parser_scan.cpp index e395c285575..3786374364f 100644 --- a/third_party/libpg_query/src_backend_parser_scan.cpp +++ b/third_party/libpg_query/src_backend_parser_scan.cpp @@ -1,5 +1,4 @@ -#line 2 "third_party/libpg_query/src_backend_parser_scan.cpp" -#line 2 "third_party/libpg_query/scan.l" +#line 1 "third_party/libpg_query/src_backend_parser_scan.cpp" /*------------------------------------------------------------------------- * * scan.l @@ -41,10 +40,7 @@ #include - - - -#line 48 "third_party/libpg_query/src_backend_parser_scan.cpp" +#line 43 "third_party/libpg_query/src_backend_parser_scan.cpp" #define YY_INT_ALIGNED short int @@ -52,12 +48,246 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif +#ifdef yy_create_buffer +#define core_yy_create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer core_yy_create_buffer +#endif + +#ifdef yy_delete_buffer +#define core_yy_delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer core_yy_delete_buffer +#endif + +#ifdef yy_scan_buffer +#define core_yy_scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer core_yy_scan_buffer +#endif + +#ifdef yy_scan_string +#define core_yy_scan_string_ALREADY_DEFINED +#else +#define yy_scan_string core_yy_scan_string +#endif + +#ifdef yy_scan_bytes +#define core_yy_scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes core_yy_scan_bytes +#endif + +#ifdef yy_init_buffer +#define core_yy_init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer core_yy_init_buffer +#endif + +#ifdef yy_flush_buffer +#define core_yy_flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer core_yy_flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define core_yy_load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state core_yy_load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define core_yy_switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer core_yy_switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define core_yypush_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state core_yypush_buffer_state +#endif + +#ifdef yypop_buffer_state +#define core_yypop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state core_yypop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define core_yyensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack core_yyensure_buffer_stack +#endif + +#ifdef yylex +#define core_yylex_ALREADY_DEFINED +#else +#define yylex core_yylex +#endif + +#ifdef yyrestart +#define core_yyrestart_ALREADY_DEFINED +#else +#define yyrestart core_yyrestart +#endif + +#ifdef yylex_init +#define core_yylex_init_ALREADY_DEFINED +#else +#define yylex_init core_yylex_init +#endif + +#ifdef yylex_init_extra +#define core_yylex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra core_yylex_init_extra +#endif + +#ifdef yylex_destroy +#define core_yylex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy core_yylex_destroy +#endif + +#ifdef yyget_debug +#define core_yyget_debug_ALREADY_DEFINED +#else +#define yyget_debug core_yyget_debug +#endif + +#ifdef yyset_debug +#define core_yyset_debug_ALREADY_DEFINED +#else +#define yyset_debug core_yyset_debug +#endif + +#ifdef yyget_extra +#define core_yyget_extra_ALREADY_DEFINED +#else +#define yyget_extra core_yyget_extra +#endif + +#ifdef yyset_extra +#define core_yyset_extra_ALREADY_DEFINED +#else +#define yyset_extra core_yyset_extra +#endif + +#ifdef yyget_in +#define core_yyget_in_ALREADY_DEFINED +#else +#define yyget_in core_yyget_in +#endif + +#ifdef yyset_in +#define core_yyset_in_ALREADY_DEFINED +#else +#define yyset_in core_yyset_in +#endif + +#ifdef yyget_out +#define core_yyget_out_ALREADY_DEFINED +#else +#define yyget_out core_yyget_out +#endif + +#ifdef yyset_out +#define core_yyset_out_ALREADY_DEFINED +#else +#define yyset_out core_yyset_out +#endif + +#ifdef yyget_leng +#define core_yyget_leng_ALREADY_DEFINED +#else +#define yyget_leng core_yyget_leng +#endif + +#ifdef yyget_text +#define core_yyget_text_ALREADY_DEFINED +#else +#define yyget_text core_yyget_text +#endif + +#ifdef yyget_lineno +#define core_yyget_lineno_ALREADY_DEFINED +#else +#define yyget_lineno core_yyget_lineno +#endif + +#ifdef yyset_lineno +#define core_yyset_lineno_ALREADY_DEFINED +#else +#define yyset_lineno core_yyset_lineno +#endif + +#ifdef yyget_column +#define core_yyget_column_ALREADY_DEFINED +#else +#define yyget_column core_yyget_column +#endif + +#ifdef yyset_column +#define core_yyset_column_ALREADY_DEFINED +#else +#define yyset_column core_yyset_column +#endif + +#ifdef yywrap +#define core_yywrap_ALREADY_DEFINED +#else +#define yywrap core_yywrap +#endif + +#ifdef yyget_lval +#define core_yyget_lval_ALREADY_DEFINED +#else +#define yyget_lval core_yyget_lval +#endif + +#ifdef yyset_lval +#define core_yyset_lval_ALREADY_DEFINED +#else +#define yyset_lval core_yyset_lval +#endif + +#ifdef yyget_lloc +#define core_yyget_lloc_ALREADY_DEFINED +#else +#define yyget_lloc core_yyget_lloc +#endif + +#ifdef yyset_lloc +#define core_yyset_lloc_ALREADY_DEFINED +#else +#define yyset_lloc core_yyset_lloc +#endif + +#ifdef yyalloc +#define core_yyalloc_ALREADY_DEFINED +#else +#define yyalloc core_yyalloc +#endif + +#ifdef yyrealloc +#define core_yyrealloc_ALREADY_DEFINED +#else +#define yyrealloc core_yyrealloc +#endif + +#ifdef yyfree +#define core_yyfree_ALREADY_DEFINED +#else +#define yyfree core_yyfree +#endif + /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ @@ -100,7 +330,6 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -131,38 +360,32 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif -#endif /* ! FLEXINT_H */ - -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif -/* C99 requires __STDC__ to be defined as 1. */ -#if defined (__STDC__) +#endif /* ! C99 */ -#define YY_USE_CONST +#endif /* ! FLEXINT_H */ -#endif /* defined (__STDC__) */ -#endif /* ! __cplusplus */ +/* begin standard C++ headers. */ -#ifdef YY_USE_CONST +/* TODO: this is always defined, so inline it */ #define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) #else -#define yyconst +#define yynoreturn #endif /* Returned upon end-of-file. */ #define YY_NULL 0 -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) /* An opaque pointer. */ #ifndef YY_TYPEDEF_YY_SCANNER_T @@ -186,25 +409,29 @@ typedef void* yyscan_t; * definition of BEGIN. */ #define BEGIN yyg->yy_start = 1 + 2 * - /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yyg->yy_start - 1) / 2) #define YYSTATE YY_START - /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - /* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE core_yyrestart(yyin ,yyscanner ) - +#define YY_NEW_FILE yyrestart( yyin , yyscanner ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else #define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. @@ -224,8 +451,9 @@ typedef size_t yy_size_t; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 - + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ @@ -240,7 +468,6 @@ typedef size_t yy_size_t; YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) - #define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) #ifndef YY_STRUCT_YY_BUFFER_STATE @@ -283,7 +510,7 @@ struct yy_buffer_state int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ - + /* Whether to try to fill the input buffer when we reach the * end of it. */ @@ -300,7 +527,7 @@ struct yy_buffer_state * possible backing-up. * * When we actually see the EOF, we change the status to "new" - * (via core_yyrestart()), so that the user can continue scanning by + * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 @@ -317,73 +544,67 @@ struct yy_buffer_state #define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ : NULL) - /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] -void core_yyrestart (FILE *input_file ,yyscan_t yyscanner ); -void core_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -YY_BUFFER_STATE core_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); -void core_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void core_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void core_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -void core_yypop_buffer_state (yyscan_t yyscanner ); - -static void core_yyensure_buffer_stack (yyscan_t yyscanner ); -static void core_yy_load_buffer_state (yyscan_t yyscanner ); -static void core_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); -#define YY_FLUSH_BUFFER core_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) +static void yyensure_buffer_stack ( yyscan_t yyscanner ); +static void yy_load_buffer_state ( yyscan_t yyscanner ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner) -YY_BUFFER_STATE core_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); -YY_BUFFER_STATE core_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); -YY_BUFFER_STATE core_yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len , yyscan_t yyscanner ); -void *core_yyalloc (yy_size_t ,yyscan_t yyscanner ); -void *core_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); -void core_yyfree (void * ,yyscan_t yyscanner ); - -#define yy_new_buffer core_yy_create_buffer +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); +#define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ - core_yyensure_buffer_stack (yyscanner); \ + yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ - core_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } - #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ - core_yyensure_buffer_stack (yyscanner); \ + yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ - core_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } - #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ -#define core_yywrap(n) 1 +#define core_yywrap(yyscanner) (/*CONSTCOND*/1) #define YY_SKIP_YYWRAP - -typedef unsigned char YY_CHAR; +typedef flex_uint8_t YY_CHAR; typedef int yy_state_type; #define yytext_ptr yytext_r -static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); -static int yy_get_next_buffer (yyscan_t yyscanner ); -static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); +static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner); +static int yy_get_next_buffer ( yyscan_t yyscanner ); +static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. @@ -394,7 +615,6 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; - #define YY_NUM_RULES 84 #define YY_END_OF_BUFFER 85 /* This struct is not used in this scanner, @@ -404,7 +624,7 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[309] = +static const flex_int16_t yy_accept[309] = { 0, 0, 0, 12, 12, 0, 0, 0, 0, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, @@ -442,7 +662,7 @@ static yyconst flex_int16_t yy_accept[309] = 28, 28, 28, 55, 55, 28, 28, 0 } ; -static yyconst flex_int32_t yy_ec[256] = +static const YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 2, 4, 1, 1, 1, 1, 1, 1, 1, @@ -474,7 +694,7 @@ static yyconst flex_int32_t yy_ec[256] = 30, 30, 30, 30, 30 } ; -static yyconst flex_int32_t yy_meta[40] = +static const YY_CHAR yy_meta[40] = { 0, 1, 1, 2, 2, 3, 4, 5, 3, 3, 6, 1, 7, 3, 3, 1, 7, 8, 8, 1, 3, @@ -482,7 +702,7 @@ static yyconst flex_int32_t yy_meta[40] = 10, 10, 10, 10, 10, 11, 10, 10, 10 } ; -static yyconst flex_int16_t yy_base[376] = +static const flex_int16_t yy_base[376] = { 0, 0, 0, 486, 484, 35, 55, 483, 475, 466, 465, 42, 51, 458, 450, 39, 55, 449, 448, 86, 123, @@ -527,7 +747,7 @@ static yyconst flex_int16_t yy_base[376] = 1196, 1205, 1216, 1227, 1238 } ; -static yyconst flex_int16_t yy_def[376] = +static const flex_int16_t yy_def[376] = { 0, 308, 1, 309, 309, 310, 310, 311, 311, 312, 312, 313, 313, 314, 314, 315, 315, 311, 311, 316, 316, @@ -572,7 +792,7 @@ static yyconst flex_int16_t yy_def[376] = 308, 308, 308, 308, 308 } ; -static yyconst flex_int16_t yy_nxt[1290] = +static const flex_int16_t yy_nxt[1290] = { 0, 28, 29, 30, 29, 31, 32, 33, 34, 35, 36, 37, 38, 34, 39, 40, 41, 42, 42, 43, 44, @@ -717,7 +937,7 @@ static yyconst flex_int16_t yy_nxt[1290] = 308, 308, 308, 308, 308, 308, 308, 308, 308 } ; -static yyconst flex_int16_t yy_chk[1290] = +static const flex_int16_t yy_chk[1290] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -898,7 +1118,7 @@ bool standard_conforming_strings = true; #define YY_EXTRA_TYPE core_yy_extra_type * /* - * Each call to core_yylex must set yylloc to the location of the found token + * Each call to yylex must set yylloc to the location of the found token * (expressed as a byte offset from the start of the input text). * When we parse a token that requires multiple lexer rules to process, * this should be done in the first such rule, else yylloc will point @@ -940,6 +1160,7 @@ static void check_escape_warning(core_yyscan_t yyscanner); extern int core_yyget_column(yyscan_t yyscanner); extern void core_yyset_column(int column_no, yyscan_t yyscanner); +#line 1162 "third_party/libpg_query/src_backend_parser_scan.cpp" #define YY_NO_INPUT 1 /* * OK, here is a short description of lex/flex rules behavior. @@ -969,17 +1190,6 @@ extern void core_yyset_column(int column_no, yyscan_t yyscanner); * The default one is probably not the right thing. */ - - - - - - - - - - - /* * In order to make the world safe for Windows and Mac clients as well as * Unix ones, we accept either \n or \r as a newline. A DOS-style \r\n @@ -1104,7 +1314,7 @@ extern void core_yyset_column(int column_no, yyscan_t yyscanner); * Note that xcstart must appear before operator, as explained above! * Also whitespace (comment) must appear before operator. */ -#line 1107 "third_party/libpg_query/src_backend_parser_scan.cpp" +#line 1316 "third_party/libpg_query/src_backend_parser_scan.cpp" #define INITIAL 0 #define xb 1 @@ -1162,7 +1372,7 @@ struct yyguts_t }; /* end struct yyguts_t */ -static int yy_init_globals (yyscan_t yyscanner ); +static int yy_init_globals ( yyscan_t yyscanner ); /* This must go here because YYSTYPE and YYLTYPE are included * from bison output in section 1.*/ @@ -1170,46 +1380,50 @@ static int yy_init_globals (yyscan_t yyscanner ); # define yylloc yyg->yylloc_r -int core_yylex_init (yyscan_t* scanner); +int yylex_init (yyscan_t* scanner); -int core_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ -int core_yylex_destroy (yyscan_t yyscanner ); +int yylex_destroy ( yyscan_t yyscanner ); -int core_yyget_debug (yyscan_t yyscanner ); +int yyget_debug ( yyscan_t yyscanner ); -void core_yyset_debug (int debug_flag ,yyscan_t yyscanner ); +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); -YY_EXTRA_TYPE core_yyget_extra (yyscan_t yyscanner ); +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); -void core_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); -FILE *core_yyget_in (yyscan_t yyscanner ); +FILE *yyget_in ( yyscan_t yyscanner ); -void core_yyset_in (FILE * in_str ,yyscan_t yyscanner ); +void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); -FILE *core_yyget_out (yyscan_t yyscanner ); +FILE *yyget_out ( yyscan_t yyscanner ); -void core_yyset_out (FILE * out_str ,yyscan_t yyscanner ); +void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); -yy_size_t core_yyget_leng (yyscan_t yyscanner ); + yy_size_t yyget_leng ( yyscan_t yyscanner ); -char *core_yyget_text (yyscan_t yyscanner ); +char *yyget_text ( yyscan_t yyscanner ); -int core_yyget_lineno (yyscan_t yyscanner ); +int yyget_lineno ( yyscan_t yyscanner ); -void core_yyset_lineno (int line_number ,yyscan_t yyscanner ); +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); -YYSTYPE * core_yyget_lval (yyscan_t yyscanner ); +int yyget_column ( yyscan_t yyscanner ); -void core_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); +void yyset_column ( int _column_no , yyscan_t yyscanner ); - YYLTYPE *core_yyget_lloc (yyscan_t yyscanner ); +YYSTYPE * yyget_lval ( yyscan_t yyscanner ); + +void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner ); + + YYLTYPE *yyget_lloc ( yyscan_t yyscanner ); - void core_yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner ); + void yyset_lloc ( YYLTYPE * yylloc_param , yyscan_t yyscanner ); /* Macros after this point can all be overridden by user definitions in * section 1. @@ -1217,33 +1431,41 @@ void core_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int core_yywrap (yyscan_t yyscanner ); +extern "C" int yywrap ( yyscan_t yyscanner ); #else -extern int core_yywrap (yyscan_t yyscanner ); +extern int yywrap ( yyscan_t yyscanner ); +#endif #endif + +#ifndef YY_NO_UNPUT + #endif #ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); #endif #ifndef YY_NO_INPUT - #ifdef __cplusplus -static int yyinput (yyscan_t yyscanner ); +static int yyinput ( yyscan_t yyscanner ); #else -static int input (yyscan_t yyscanner ); +static int input ( yyscan_t yyscanner ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else #define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ @@ -1251,7 +1473,7 @@ static int input (yyscan_t yyscanner ); /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ -#define ECHO fwrite( yytext, yyleng, 1, yyout ) +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, @@ -1275,7 +1497,7 @@ static int input (yyscan_t yyscanner ); else \ { \ errno=0; \ - while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ @@ -1316,10 +1538,10 @@ static int input (yyscan_t yyscanner ); #ifndef YY_DECL #define YY_DECL_IS_OURS 1 -extern int core_yylex \ - (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner); +extern int yylex \ + (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner); -#define YY_DECL int core_yylex \ +#define YY_DECL int yylex \ (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) #endif /* !YY_DECL */ @@ -1332,7 +1554,7 @@ extern int core_yylex \ /* Code executed at the end of each rule. */ #ifndef YY_BREAK -#define YY_BREAK break; +#define YY_BREAK /*LINTED*/break; #endif #define YY_RULE_SETUP \ @@ -1347,11 +1569,6 @@ YY_DECL int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 404 "third_party/libpg_query/scan.l" - - -#line 1353 "third_party/libpg_query/src_backend_parser_scan.cpp" - yylval = yylval_param; yylloc = yylloc_param; @@ -1367,15 +1584,21 @@ YY_DECL if ( ! yyg->yy_start ) yyg->yy_start = 1; /* first start state */ if ( ! YY_CURRENT_BUFFER ) { - core_yyensure_buffer_stack (yyscanner); + yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = - core_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); } - core_yy_load_buffer_state(yyscanner ); + yy_load_buffer_state( yyscanner ); } - while ( 1 ) /* loops until end-of-file is reached */ + { +#line 404 "third_party/libpg_query/scan.l" + + +#line 1605 "third_party/libpg_query/src_backend_parser_scan.cpp" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { yy_cp = yyg->yy_c_buf_p; @@ -1391,7 +1614,7 @@ YY_DECL yy_match: do { - YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; if ( yy_accept[yy_current_state] ) { yyg->yy_last_accepting_state = yy_current_state; @@ -1401,9 +1624,9 @@ YY_DECL { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 309 ) - yy_c = yy_meta[(unsigned int) yy_c]; + yy_c = yy_meta[yy_c]; } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } while ( yy_current_state != 308 ); @@ -2444,7 +2667,7 @@ YY_RULE_SETUP #line 1089 "third_party/libpg_query/scan.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK -#line 2454 "third_party/libpg_query/src_backend_parser_scan.cpp" +#line 2676 "third_party/libpg_query/src_backend_parser_scan.cpp" case YY_END_OF_BUFFER: { @@ -2460,7 +2683,7 @@ YY_FATAL_ERROR( "flex scanner jammed" ); /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called - * core_yylex(). If so, then we have to assure + * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a @@ -2521,7 +2744,7 @@ YY_FATAL_ERROR( "flex scanner jammed" ); { yyg->yy_did_buffer_switch_on_eof = 0; - if ( core_yywrap(yyscanner ) ) + if ( yywrap( yyscanner ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up @@ -2574,7 +2797,8 @@ YY_FATAL_ERROR( "flex scanner jammed" ); "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ -} /* end of core_yylex */ + } /* end of user's declarations */ +} /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * @@ -2617,7 +2841,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) /* Try to read more data. */ /* First move last chars to start of buffer. */ - number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); @@ -2637,7 +2861,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) (yyg->yy_c_buf_p - b->yy_ch_buf); @@ -2653,11 +2877,12 @@ static int yy_get_next_buffer (yyscan_t yyscanner) b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - core_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + yyrealloc( (void *) b->yy_ch_buf, + (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); } else /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; + b->yy_ch_buf = NULL; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( @@ -2685,7 +2910,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; - core_yyrestart(yyin ,yyscanner); + yyrestart( yyin , yyscanner); } else @@ -2699,12 +2924,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner) else ret_val = EOB_ACT_CONTINUE_SCAN; - if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) core_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( + (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); } yyg->yy_n_chars += number_to_move; @@ -2738,9 +2966,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 309 ) - yy_c = yy_meta[(unsigned int) yy_c]; + yy_c = yy_meta[yy_c]; } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; } return yy_current_state; @@ -2767,14 +2995,19 @@ static int yy_get_next_buffer (yyscan_t yyscanner) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 309 ) - yy_c = yy_meta[(unsigned int) yy_c]; + yy_c = yy_meta[yy_c]; } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; yy_is_jam = (yy_current_state == 308); + (void)yyg; return yy_is_jam ? 0 : yy_current_state; } +#ifndef YY_NO_UNPUT + +#endif + #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (yyscan_t yyscanner) @@ -2817,13 +3050,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner) */ /* Reset buffer status. */ - core_yyrestart(yyin ,yyscanner); + yyrestart( yyin , yyscanner); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { - if ( core_yywrap(yyscanner ) ) + if ( yywrap( yyscanner ) ) return 0; if ( ! yyg->yy_did_buffer_switch_on_eof ) @@ -2855,34 +3088,34 @@ static int yy_get_next_buffer (yyscan_t yyscanner) * @param yyscanner The scanner object. * @note This function does not reset the start condition to @c INITIAL . */ - void core_yyrestart (FILE * input_file , yyscan_t yyscanner) + void yyrestart (FILE * input_file , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! YY_CURRENT_BUFFER ){ - core_yyensure_buffer_stack (yyscanner); + yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = - core_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); } - core_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); - core_yy_load_buffer_state(yyscanner ); + yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner); + yy_load_buffer_state( yyscanner ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * @param yyscanner The scanner object. */ - void core_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* TODO. We should be able to replace this entire function body * with - * core_yypop_buffer_state(); - * core_yypush_buffer_state(new_buffer); + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); */ - core_yyensure_buffer_stack (yyscanner); + yyensure_buffer_stack (yyscanner); if ( YY_CURRENT_BUFFER == new_buffer ) return; @@ -2895,17 +3128,17 @@ static int yy_get_next_buffer (yyscan_t yyscanner) } YY_CURRENT_BUFFER_LVALUE = new_buffer; - core_yy_load_buffer_state(yyscanner ); + yy_load_buffer_state( yyscanner ); /* We don't actually know whether we did this switch during - * EOF (core_yywrap()) processing, but the only time this flag - * is looked at is after core_yywrap() is called, so it's safe + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yyg->yy_did_buffer_switch_on_eof = 1; } -static void core_yy_load_buffer_state (yyscan_t yyscanner) +static void yy_load_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; @@ -2920,35 +3153,35 @@ static void core_yy_load_buffer_state (yyscan_t yyscanner) * @param yyscanner The scanner object. * @return the allocated buffer state. */ - YY_BUFFER_STATE core_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) { YY_BUFFER_STATE b; - b = (YY_BUFFER_STATE) core_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in core_yy_create_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) core_yyalloc(b->yy_buf_size + 2 ,yyscanner ); + b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in core_yy_create_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; - core_yy_init_buffer(b,file ,yyscanner); + yy_init_buffer( b, file , yyscanner); return b; } /** Destroy the buffer. - * @param b a buffer created with core_yy_create_buffer() + * @param b a buffer created with yy_create_buffer() * @param yyscanner The scanner object. */ - void core_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) + void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; @@ -2959,28 +3192,28 @@ static void core_yy_load_buffer_state (yyscan_t yyscanner) YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) - core_yyfree((void *) b->yy_ch_buf ,yyscanner ); + yyfree( (void *) b->yy_ch_buf , yyscanner ); - core_yyfree((void *) b ,yyscanner ); + yyfree( (void *) b , yyscanner ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, - * such as during a core_yyrestart() or at EOF. + * such as during a yyrestart() or at EOF. */ - static void core_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) { int oerrno = errno; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - core_yy_flush_buffer(b ,yyscanner); + yy_flush_buffer( b , yyscanner); b->yy_input_file = file; b->yy_fill_buffer = 1; - /* If b is the current buffer, then core_yy_init_buffer was _probably_ - * called from core_yyrestart() or through yy_get_next_buffer. + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ @@ -2997,7 +3230,7 @@ static void core_yy_load_buffer_state (yyscan_t yyscanner) * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * @param yyscanner The scanner object. */ - void core_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) + void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) @@ -3018,7 +3251,7 @@ static void core_yy_load_buffer_state (yyscan_t yyscanner) b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) - core_yy_load_buffer_state(yyscanner ); + yy_load_buffer_state( yyscanner ); } /** Pushes the new state onto the stack. The new state becomes @@ -3027,15 +3260,15 @@ static void core_yy_load_buffer_state (yyscan_t yyscanner) * @param new_buffer The new state. * @param yyscanner The scanner object. */ -void core_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (new_buffer == NULL) return; - core_yyensure_buffer_stack(yyscanner); + yyensure_buffer_stack(yyscanner); - /* This block is copied from core_yy_switch_to_buffer. */ + /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ @@ -3049,8 +3282,8 @@ void core_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) yyg->yy_buffer_stack_top++; YY_CURRENT_BUFFER_LVALUE = new_buffer; - /* copied from core_yy_switch_to_buffer. */ - core_yy_load_buffer_state(yyscanner ); + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } @@ -3058,19 +3291,19 @@ void core_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) * The next element becomes the new top. * @param yyscanner The scanner object. */ -void core_yypop_buffer_state (yyscan_t yyscanner) +void yypop_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!YY_CURRENT_BUFFER) return; - core_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner); YY_CURRENT_BUFFER_LVALUE = NULL; if (yyg->yy_buffer_stack_top > 0) --yyg->yy_buffer_stack_top; if (YY_CURRENT_BUFFER) { - core_yy_load_buffer_state(yyscanner ); + yy_load_buffer_state( yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } } @@ -3078,7 +3311,7 @@ void core_yypop_buffer_state (yyscan_t yyscanner) /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ -static void core_yyensure_buffer_stack (yyscan_t yyscanner) +static void yyensure_buffer_stack (yyscan_t yyscanner) { yy_size_t num_to_alloc; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; @@ -3089,15 +3322,15 @@ static void core_yyensure_buffer_stack (yyscan_t yyscanner) * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ - num_to_alloc = 1; - yyg->yy_buffer_stack = (struct yy_buffer_state**)core_yyalloc + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in core_yyensure_buffer_stack()" ); - + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - + yyg->yy_buffer_stack_max = num_to_alloc; yyg->yy_buffer_stack_top = 0; return; @@ -3106,15 +3339,15 @@ static void core_yyensure_buffer_stack (yyscan_t yyscanner) if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; + yy_size_t grow_size = 8 /* arbitrary grow size */; num_to_alloc = yyg->yy_buffer_stack_max + grow_size; - yyg->yy_buffer_stack = (struct yy_buffer_state**)core_yyrealloc + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc (yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in core_yyensure_buffer_stack()" ); + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); @@ -3126,9 +3359,9 @@ static void core_yyensure_buffer_stack (yyscan_t yyscanner) * @param base the character buffer * @param size the size in bytes of the character buffer * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. + * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE core_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) { YY_BUFFER_STATE b; @@ -3136,68 +3369,69 @@ YY_BUFFER_STATE core_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yy base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ - return 0; + return NULL; - b = (YY_BUFFER_STATE) core_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in core_yy_scan_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; - b->yy_input_file = 0; + b->yy_input_file = NULL; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; - core_yy_switch_to_buffer(b ,yyscanner ); + yy_switch_to_buffer( b , yyscanner ); return b; } -/** Setup the input buffer state to scan a string. The next call to core_yylex() will +/** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * @param yyscanner The scanner object. * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use - * core_yy_scan_bytes() instead. + * yy_scan_bytes() instead. */ -YY_BUFFER_STATE core_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) +YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) { - return core_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); + return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner); } -/** Setup the input buffer state to scan the given bytes. The next call to core_yylex() will +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE core_yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner) +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; - yy_size_t n, i; + yy_size_t n; + yy_size_t i; /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) core_yyalloc(n ,yyscanner ); + n = (yy_size_t) (_yybytes_len + 2); + buf = (char *) yyalloc( n , yyscanner ); if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in core_yy_scan_bytes()" ); + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - b = core_yy_scan_buffer(buf,n ,yyscanner); + b = yy_scan_buffer( buf, n , yyscanner); if ( ! b ) - YY_FATAL_ERROR( "bad buffer in core_yy_scan_bytes()" ); + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. @@ -3211,9 +3445,11 @@ YY_BUFFER_STATE core_yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes #define YY_EXIT_FAILURE 2 #endif -static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) +static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) { - //( stderr, "%s\n", msg ); + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + //( stderr, "%s\n", msg ); throw std::runtime_error(msg); // YY_EXIT_FAILURE ); } @@ -3224,7 +3460,7 @@ static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) do \ { \ /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ + yy_size_t yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = yyg->yy_hold_char; \ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ @@ -3239,7 +3475,7 @@ static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) /** Get the user-defined data for this scanner. * @param yyscanner The scanner object. */ -YY_EXTRA_TYPE core_yyget_extra (yyscan_t yyscanner) +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyextra; @@ -3248,10 +3484,10 @@ YY_EXTRA_TYPE core_yyget_extra (yyscan_t yyscanner) /** Get the current line number. * @param yyscanner The scanner object. */ -int core_yyget_lineno (yyscan_t yyscanner) +int yyget_lineno (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - + if (! YY_CURRENT_BUFFER) return 0; @@ -3261,10 +3497,10 @@ int core_yyget_lineno (yyscan_t yyscanner) /** Get the current column number. * @param yyscanner The scanner object. */ -int core_yyget_column (yyscan_t yyscanner) +int yyget_column (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - + if (! YY_CURRENT_BUFFER) return 0; @@ -3274,7 +3510,7 @@ int core_yyget_column (yyscan_t yyscanner) /** Get the input stream. * @param yyscanner The scanner object. */ -FILE *core_yyget_in (yyscan_t yyscanner) +FILE *yyget_in (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyin; @@ -3283,7 +3519,7 @@ FILE *core_yyget_in (yyscan_t yyscanner) /** Get the output stream. * @param yyscanner The scanner object. */ -FILE *core_yyget_out (yyscan_t yyscanner) +FILE *yyget_out (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyout; @@ -3292,7 +3528,7 @@ FILE *core_yyget_out (yyscan_t yyscanner) /** Get the length of the current token. * @param yyscanner The scanner object. */ -yy_size_t core_yyget_leng (yyscan_t yyscanner) +yy_size_t yyget_leng (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyleng; @@ -3302,7 +3538,7 @@ yy_size_t core_yyget_leng (yyscan_t yyscanner) * @param yyscanner The scanner object. */ -char *core_yyget_text (yyscan_t yyscanner) +char *yyget_text (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yytext; @@ -3312,93 +3548,93 @@ char *core_yyget_text (yyscan_t yyscanner) * @param user_defined The data to be associated with this scanner. * @param yyscanner The scanner object. */ -void core_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyextra = user_defined ; } /** Set the current line number. - * @param line_number + * @param _line_number line number * @param yyscanner The scanner object. */ -void core_yyset_lineno (int line_number , yyscan_t yyscanner) +void yyset_lineno (int _line_number , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* lineno is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) - yy_fatal_error( "core_yyset_lineno called with no buffer" , yyscanner); + YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); - yylineno = line_number; + yylineno = _line_number; } /** Set the current column. - * @param line_number + * @param _column_no column number * @param yyscanner The scanner object. */ -void core_yyset_column (int column_no , yyscan_t yyscanner) +void yyset_column (int _column_no , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* column is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) - yy_fatal_error( "core_yyset_column called with no buffer" , yyscanner); + YY_FATAL_ERROR( "yyset_column called with no buffer" ); - yycolumn = column_no; + yycolumn = _column_no; } /** Set the input stream. This does not discard the current * input buffer. - * @param in_str A readable stream. + * @param _in_str A readable stream. * @param yyscanner The scanner object. - * @see core_yy_switch_to_buffer + * @see yy_switch_to_buffer */ -void core_yyset_in (FILE * in_str , yyscan_t yyscanner) +void yyset_in (FILE * _in_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyin = in_str ; + yyin = _in_str ; } -void core_yyset_out (FILE * out_str , yyscan_t yyscanner) +void yyset_out (FILE * _out_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyout = out_str ; + yyout = _out_str ; } -int core_yyget_debug (yyscan_t yyscanner) +int yyget_debug (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yy_flex_debug; } -void core_yyset_debug (int bdebug , yyscan_t yyscanner) +void yyset_debug (int _bdebug , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yy_flex_debug = bdebug ; + yy_flex_debug = _bdebug ; } /* Accessor methods for yylval and yylloc */ -YYSTYPE * core_yyget_lval (yyscan_t yyscanner) +YYSTYPE * yyget_lval (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yylval; } -void core_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yylval = yylval_param; } -YYLTYPE *core_yyget_lloc (yyscan_t yyscanner) +YYLTYPE *yyget_lloc (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yylloc; } -void core_yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) +void yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yylloc = yylloc_param; @@ -3406,20 +3642,18 @@ void core_yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) /* User-visible API */ -/* core_yylex_init is special because it creates the scanner itself, so it is +/* yylex_init is special because it creates the scanner itself, so it is * the ONLY reentrant function that doesn't take the scanner as the last argument. * That's why we explicitly handle the declaration, instead of using our macros. */ - -int core_yylex_init(yyscan_t* ptr_yy_globals) - +int yylex_init(yyscan_t* ptr_yy_globals) { if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } - *ptr_yy_globals = (yyscan_t) core_yyalloc ( sizeof( struct yyguts_t ), NULL ); + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; @@ -3432,39 +3666,37 @@ int core_yylex_init(yyscan_t* ptr_yy_globals) return yy_init_globals ( *ptr_yy_globals ); } -/* core_yylex_init_extra has the same functionality as core_yylex_init, but follows the +/* yylex_init_extra has the same functionality as yylex_init, but follows the * convention of taking the scanner as the last argument. Note however, that * this is a *pointer* to a scanner, as it will be allocated by this call (and * is the reason, too, why this function also must handle its own declaration). - * The user defined value in the first argument will be available to core_yyalloc in + * The user defined value in the first argument will be available to yyalloc in * the yyextra field. */ - -int core_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) - +int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) { struct yyguts_t dummy_yyguts; - core_yyset_extra (yy_user_defined, &dummy_yyguts); + yyset_extra (yy_user_defined, &dummy_yyguts); if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } - - *ptr_yy_globals = (yyscan_t) core_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); - + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + if (*ptr_yy_globals == NULL){ errno = ENOMEM; return 1; } - + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - - core_yyset_extra (yy_user_defined, *ptr_yy_globals); - + + yyset_extra (yy_user_defined, *ptr_yy_globals); + return yy_init_globals ( *ptr_yy_globals ); } @@ -3472,13 +3704,13 @@ static int yy_init_globals (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Initialization is the same as for the non-reentrant scanner. - * This function is called from core_yylex_destroy(), so don't allocate here. + * This function is called from yylex_destroy(), so don't allocate here. */ - yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack = NULL; yyg->yy_buffer_stack_top = 0; yyg->yy_buffer_stack_max = 0; - yyg->yy_c_buf_p = (char *) 0; + yyg->yy_c_buf_p = NULL; yyg->yy_init = 0; yyg->yy_start = 0; @@ -3487,41 +3719,46 @@ static int yy_init_globals (yyscan_t yyscanner) yyg->yy_start_stack = NULL; /* Defined in main.c */ - yyin = (FILE *) 0; - yyout = (FILE *) 0; +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif /* For future reference: Set errno on error, since we are called by - * core_yylex_init() + * yylex_init() */ return 0; } -/* core_yylex_destroy is for both reentrant and non-reentrant scanners. */ -int core_yylex_destroy (yyscan_t yyscanner) +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ - core_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner ); YY_CURRENT_BUFFER_LVALUE = NULL; - core_yypop_buffer_state(yyscanner); + yypop_buffer_state(yyscanner); } /* Destroy the stack itself. */ - core_yyfree(yyg->yy_buffer_stack ,yyscanner); + yyfree(yyg->yy_buffer_stack , yyscanner); yyg->yy_buffer_stack = NULL; /* Destroy the start condition stack. */ - core_yyfree(yyg->yy_start_stack ,yyscanner ); + yyfree( yyg->yy_start_stack , yyscanner ); yyg->yy_start_stack = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time - * core_yylex() is called, initialization will occur. */ + * yylex() is called, initialization will occur. */ yy_init_globals( yyscanner); /* Destroy the main struct (reentrant only). */ - core_yyfree ( yyscanner , yyscanner ); + yyfree ( yyscanner , yyscanner ); yyscanner = NULL; return 0; } @@ -3531,8 +3768,11 @@ int core_yylex_destroy (yyscan_t yyscanner) */ #ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) +static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) { + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; @@ -3540,7 +3780,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) +static int yy_flex_strlen (const char * s , yyscan_t yyscanner) { int n; for ( n = 0; s[n]; ++n ) @@ -3555,11 +3795,10 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) #line 1089 "third_party/libpg_query/scan.l" - /* LCOV_EXCL_STOP */ /* - * Arrange access to yyextra for subroutines of the main core_yylex() function. + * Arrange access to yyextra for subroutines of the main yylex() function. * We expect each subroutine to have a yyscanner parameter. Rather than * use the yyget_xxx functions, which might or might not get inlined by the * compiler, we cheat just a bit and cast yyscanner to the right type. @@ -3604,7 +3843,7 @@ scanner_errposition(int location, core_yyscan_t yyscanner) * Report a lexer or grammar error. * * The message's cursor position is whatever YYLLOC was last set to, - * ie, the start of the current token if called within core_yylex(), or the + * ie, the start of the current token if called within yylex(), or the * most recently lexed token if called from the grammar. * This is OK for syntax error messages from the Bison parser, because Bison * parsers report error as soon as the first unparsable token is reached. @@ -3647,8 +3886,8 @@ scanner_init(const char *str, PGSize slen = strlen(str); yyscan_t scanner; - if (core_yylex_init(&scanner) != 0) - elog(ERROR, "core_yylex_init() failed: %m"); + if (yylex_init(&scanner) != 0) + elog(ERROR, "yylex_init() failed: %m"); core_yyset_extra(yyext, scanner); @@ -3666,7 +3905,7 @@ scanner_init(const char *str, yyext->scanbuflen = slen; memcpy(yyext->scanbuf, str, slen); yyext->scanbuf[slen] = yyext->scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; - core_yy_scan_buffer(yyext->scanbuf,slen + 2,scanner); + yy_scan_buffer(yyext->scanbuf, slen + 2, scanner); /* initialize literal buffer to a reasonable but expansible size */ yyext->literalalloc = 1024; @@ -3684,7 +3923,7 @@ void scanner_finish(core_yyscan_t yyscanner) { /* - * We don't bother to call core_yylex_destroy(), because all it would do is + * We don't bother to call yylex_destroy(), because all it would do is * pfree a small amount of control storage. It's cheaper to leak the * storage until the parsing context is destroyed. The amount of space * involved is usually negligible compared to the output parse tree diff --git a/third_party/re2/CMakeLists.txt b/third_party/re2/CMakeLists.txt index 4440566c862..6e8ce002a58 100644 --- a/third_party/re2/CMakeLists.txt +++ b/third_party/re2/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright 2015 The RE2 Authors. All Rights Reserved. Use of this source code # is governed by a BSD-style license that can be found in the LICENSE file. -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.5...3.29) if(POLICY CMP0048) cmake_policy(SET CMP0048 NEW) @@ -50,6 +50,8 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") add_compile_options(-std=c++11) endif() +add_definitions(-DRE2_ON_VALGRIND) + if(WIN32) add_definitions(-DUNICODE -D_UNICODE diff --git a/third_party/re2/re2/compile.cc b/third_party/re2/re2/compile.cc index 7bc76bbd75f..cb03d8d4ae2 100644 --- a/third_party/re2/re2/compile.cc +++ b/third_party/re2/re2/compile.cc @@ -487,8 +487,8 @@ int Compiler::CachedRuneByteSuffix(uint8_t lo, uint8_t hi, bool foldcase, } bool Compiler::IsCachedRuneByteSuffix(int id) { - uint8_t lo = inst_[id].lo_; - uint8_t hi = inst_[id].hi_; + uint8_t lo = inst_[id].byte_range.lo_; + uint8_t hi = inst_[id].byte_range.hi_; bool foldcase = inst_[id].foldcase() != 0; int next = inst_[id].out(); diff --git a/third_party/re2/re2/dfa.cc b/third_party/re2/re2/dfa.cc index 38b060d5343..7793f8f56a6 100644 --- a/third_party/re2/re2/dfa.cc +++ b/third_party/re2/re2/dfa.cc @@ -116,13 +116,8 @@ class DFA { // into this state, along with kFlagMatch if this // is a matching state. -// Work around the bug affecting flexible array members in GCC 6.x (for x >= 1). -// (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70932) -#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ == 6 && __GNUC_MINOR__ >= 1 - std::atomic next_[0]; // Outgoing arrows from State, -#else - std::atomic next_[]; // Outgoing arrows from State, -#endif + // fixes from https://github.com/girishji/re2/commit/80b212f289c4ef75408b1510b9fc85e6cb9a447c + std::atomic *next_; // Outgoing arrows from State, // one per input byte class }; @@ -751,7 +746,7 @@ DFA::State* DFA::CachedState(int* inst, int ninst, uint32_t flag) { // Allocate new state along with room for next_ and inst_. char* space = std::allocator().allocate(mem); State* s = new (space) State; - (void) new (s->next_) std::atomic[nnext]; + s->next_ = new (space + sizeof(State)) std::atomic[nnext]; // Work around a unfortunate bug in older versions of libstdc++. // (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64658) for (int i = 0; i < nnext; i++) diff --git a/third_party/re2/re2/onepass.cc b/third_party/re2/re2/onepass.cc index 2290e8c8048..f2a620e28bf 100644 --- a/third_party/re2/re2/onepass.cc +++ b/third_party/re2/re2/onepass.cc @@ -143,7 +143,7 @@ namespace duckdb_re2 { // the memory footprint.) struct OneState { uint32_t matchcond; // conditions to match right now. - uint32_t action[]; + uint32_t action[256]; }; // The uint32_t conditions in the action are a combination of @@ -243,7 +243,8 @@ bool Prog::SearchOnePass(const StringPiece& text, kind = kFullMatch; uint8_t* nodes = onepass_nodes_.data(); - int statesize = sizeof(OneState) + bytemap_range()*sizeof(uint32_t); + int statesize = sizeof(uint32_t) + bytemap_range()*sizeof(uint32_t); + // start() is always mapped to the zeroth OneState. OneState* state = IndexToNode(nodes, statesize, 0); uint8_t* bytemap = bytemap_; @@ -392,7 +393,7 @@ bool Prog::IsOnePass() { // Limit max node count to 65000 as a conservative estimate to // avoid overflowing 16-bit node index in encoding. int maxnodes = 2 + inst_count(kInstByteRange); - int statesize = sizeof(OneState) + bytemap_range()*sizeof(uint32_t); + int statesize = sizeof(uint32_t) + bytemap_range()*sizeof(uint32_t); if (maxnodes >= 65000 || dfa_mem_ / 4 / statesize < maxnodes) return false; diff --git a/third_party/re2/re2/prog.cc b/third_party/re2/re2/prog.cc index b0ed4dbb92d..716b6f3eef7 100644 --- a/third_party/re2/re2/prog.cc +++ b/third_party/re2/re2/prog.cc @@ -38,9 +38,9 @@ void Prog::Inst::InitAlt(uint32_t out, uint32_t out1) { void Prog::Inst::InitByteRange(int lo, int hi, int foldcase, uint32_t out) { DCHECK_EQ(out_opcode_, 0); set_out_opcode(out, kInstByteRange); - lo_ = lo & 0xFF; - hi_ = hi & 0xFF; - hint_foldcase_ = foldcase&1; + byte_range.lo_ = lo & 0xFF; + byte_range.hi_ = hi & 0xFF; + byte_range.hint_foldcase_ = foldcase&1; } void Prog::Inst::InitCapture(int cap, uint32_t out) { @@ -85,7 +85,7 @@ std::string Prog::Inst::Dump() { case kInstByteRange: return StringPrintf("byte%s [%02x-%02x] %d -> %d", foldcase() ? "/i" : "", - lo_, hi_, hint(), out()); + byte_range.lo_, byte_range.hi_, hint(), out()); case kInstCapture: return StringPrintf("capture %d -> %d", cap_, out()); @@ -921,7 +921,7 @@ void Prog::ComputeHints(std::vector* flat, int begin, int end) { if (first != end) { uint16_t hint = static_cast(std::min(first - id, 32767)); - ip->hint_foldcase_ |= hint<<1; + ip->byte_range.hint_foldcase_ |= hint<<1; } } } @@ -1022,11 +1022,11 @@ void Prog::ConfigurePrefixAccel(const std::string& prefix, prefix_dfa_ = BuildShiftDFA(prefix.substr(0, prefix_size_)); } else if (prefix_size_ != 1) { // Use PrefixAccel_FrontAndBack(). - prefix_front_ = prefix.front(); - prefix_back_ = prefix.back(); + prefix_front_back.prefix_front_ = prefix.front(); + prefix_front_back.prefix_back_ = prefix.back(); } else { // Use memchr(3). - prefix_front_ = prefix.front(); + prefix_front_back.prefix_front_ = prefix.front(); } } @@ -1143,8 +1143,8 @@ const void* Prog::PrefixAccel_FrontAndBack(const void* data, size_t size) { const __m256i* bp = reinterpret_cast( reinterpret_cast(data) + prefix_size_-1); const __m256i* endfp = fp + size/sizeof(__m256i); - const __m256i f_set1 = _mm256_set1_epi8(prefix_front_); - const __m256i b_set1 = _mm256_set1_epi8(prefix_back_); + const __m256i f_set1 = _mm256_set1_epi8(prefix_front_back.prefix_front_); + const __m256i b_set1 = _mm256_set1_epi8(prefix_front_back.prefix_back_); do { const __m256i f_loadu = _mm256_loadu_si256(fp++); const __m256i b_loadu = _mm256_loadu_si256(bp++); @@ -1166,8 +1166,8 @@ const void* Prog::PrefixAccel_FrontAndBack(const void* data, size_t size) { const char* p0 = reinterpret_cast(data); for (const char* p = p0;; p++) { DCHECK_GE(size, static_cast(p-p0)); - p = reinterpret_cast(memchr(p, prefix_front_, size - (p-p0))); - if (p == NULL || p[prefix_size_-1] == prefix_back_) + p = reinterpret_cast(memchr(p, prefix_front_back.prefix_front_, size - (p-p0))); + if (p == NULL || p[prefix_size_-1] == prefix_front_back.prefix_back_) return p; } } diff --git a/third_party/re2/re2/prog.h b/third_party/re2/re2/prog.h index 29be811a75d..e385b59e1b7 100644 --- a/third_party/re2/re2/prog.h +++ b/third_party/re2/re2/prog.h @@ -84,10 +84,10 @@ class Prog { int out() { return out_opcode_>>4; } int out1() { DCHECK(opcode() == kInstAlt || opcode() == kInstAltMatch); return out1_; } int cap() { DCHECK_EQ(opcode(), kInstCapture); return cap_; } - int lo() { DCHECK_EQ(opcode(), kInstByteRange); return lo_; } - int hi() { DCHECK_EQ(opcode(), kInstByteRange); return hi_; } - int foldcase() { DCHECK_EQ(opcode(), kInstByteRange); return hint_foldcase_&1; } - int hint() { DCHECK_EQ(opcode(), kInstByteRange); return hint_foldcase_>>1; } + int lo() { DCHECK_EQ(opcode(), kInstByteRange); return byte_range.lo_; } + int hi() { DCHECK_EQ(opcode(), kInstByteRange); return byte_range.hi_; } + int foldcase() { DCHECK_EQ(opcode(), kInstByteRange); return byte_range.hint_foldcase_&1; } + int hint() { DCHECK_EQ(opcode(), kInstByteRange); return byte_range.hint_foldcase_>>1; } int match_id() { DCHECK_EQ(opcode(), kInstMatch); return match_id_; } EmptyOp empty() { DCHECK_EQ(opcode(), kInstEmptyWidth); return empty_; } @@ -103,7 +103,7 @@ class Prog { DCHECK_EQ(opcode(), kInstByteRange); if (foldcase() && 'A' <= c && c <= 'Z') c += 'a' - 'A'; - return lo_ <= c && c <= hi_; + return byte_range.lo_ <= c && c <= byte_range.hi_; } // Returns string representation for debugging. @@ -155,7 +155,7 @@ class Prog { // means there are no remaining possibilities, // which is most likely for character classes. // foldcase: A-Z -> a-z before checking range. - }; + } byte_range; EmptyOp empty_; // opcode == kInstEmptyWidth // empty_ is bitwise OR of kEmpty* flags above. @@ -227,7 +227,7 @@ class Prog { } else if (prefix_size_ != 1) { return PrefixAccel_FrontAndBack(data, size); } else { - return memchr(data, prefix_front_, size); + return memchr(data, prefix_front_back.prefix_front_, size); } } @@ -426,7 +426,7 @@ class Prog { struct { int prefix_front_; // first byte of prefix int prefix_back_; // last byte of prefix - }; + } prefix_front_back; }; int list_count_; // count of lists (see above) diff --git a/third_party/snappy/snappy-stubs-internal.h b/third_party/snappy/snappy-stubs-internal.h index c53adddeb8e..6ce981275e6 100644 --- a/third_party/snappy/snappy-stubs-internal.h +++ b/third_party/snappy/snappy-stubs-internal.h @@ -41,6 +41,13 @@ #include #include +// DuckDB - LNK: define here instead of in CMake +#ifdef __GNUC__ +#define HAVE_BUILTIN_EXPECT +#define HAVE_BUILTIN_CTZ +#define HAVE_BUILTIN_PREFETCH +#endif + #ifdef HAVE_SYS_MMAN_H #include #endif diff --git a/third_party/snowball/CMakeLists.txt b/third_party/snowball/CMakeLists.txt index d55517d2b0e..9efa3c9728e 100644 --- a/third_party/snowball/CMakeLists.txt +++ b/third_party/snowball/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(Snowball) diff --git a/third_party/tpce-tool/CMakeLists.txt b/third_party/tpce-tool/CMakeLists.txt index ba9a37a1f16..37ecb8d4e00 100644 --- a/third_party/tpce-tool/CMakeLists.txt +++ b/third_party/tpce-tool/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 2.8.12...3.29) project(tpce CXX C) diff --git a/third_party/utf8proc/include/utf8proc.hpp b/third_party/utf8proc/include/utf8proc.hpp index 37fa1f2664b..5d66c15d3d9 100644 --- a/third_party/utf8proc/include/utf8proc.hpp +++ b/third_party/utf8proc/include/utf8proc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 Steven G. Johnson, Jiahao Chen, Peter Colberg, Tony Kelman, Scott P. Jones, and other contributors. + * Copyright (c) 2014-2021 Steven G. Johnson, Jiahao Chen, Peter Colberg, Tony Kelman, Scott P. Jones, and other contributors. * Copyright (c) 2009 Public Software Group e. V., Berlin, Germany * * Permission is hereby granted, free of charge, to any person obtaining a @@ -36,16 +36,16 @@ * * The features of utf8proc include: * - * - Transformation of strings (@ref utf8proc_map) to: + * - Transformation of strings (utf8proc_map()) to: * - decompose (@ref UTF8PROC_DECOMPOSE) or compose (@ref UTF8PROC_COMPOSE) Unicode combining characters (http://en.wikipedia.org/wiki/Combining_character) * - canonicalize Unicode compatibility characters (@ref UTF8PROC_COMPAT) * - strip "ignorable" (@ref UTF8PROC_IGNORE) characters, control characters (@ref UTF8PROC_STRIPCC), or combining characters such as accents (@ref UTF8PROC_STRIPMARK) * - case-folding (@ref UTF8PROC_CASEFOLD) - * - Unicode normalization: @ref utf8proc_NFD, @ref utf8proc_NFC, @ref utf8proc_NFKD, @ref utf8proc_NFKC - * - Detecting grapheme boundaries (@ref utf8proc_grapheme_break and @ref UTF8PROC_CHARBOUND) - * - Character-width computation: @ref utf8proc_charwidth - * - Classification of characters by Unicode category: @ref utf8proc_category and @ref utf8proc_category_string - * - Encode (@ref utf8proc_encode_char) and decode (@ref utf8proc_iterate) Unicode codepoints to/from UTF-8. + * - Unicode normalization: utf8proc_NFD(), utf8proc_NFC(), utf8proc_NFKD(), utf8proc_NFKC() + * - Detecting grapheme boundaries (utf8proc_grapheme_break() and @ref UTF8PROC_CHARBOUND) + * - Character-width computation: utf8proc_charwidth() + * - Classification of characters by Unicode category: utf8proc_category() and utf8proc_category_string() + * - Encode (utf8proc_encode_char()) and decode (utf8proc_iterate()) Unicode codepoints to/from UTF-8. */ /** @file */ @@ -53,16 +53,13 @@ #ifndef UTF8PROC_H #define UTF8PROC_H -// DuckDB change: -#define UTF8PROC_STATIC - /** @name API version * * The utf8proc API version MAJOR.MINOR.PATCH, following * semantic-versioning rules (http://semver.org) based on API * compatibility. * - * This is also returned at runtime by @ref utf8proc_version; however, the + * This is also returned at runtime by utf8proc_version(); however, the * runtime version may append a string like "-dev" to the version number * for prerelease versions. * @@ -74,7 +71,7 @@ /** The MAJOR version number (increased when backwards API compatibility is broken). */ #define UTF8PROC_VERSION_MAJOR 2 /** The MINOR version number (increased when new functionality is added in a backwards-compatible manner). */ -#define UTF8PROC_VERSION_MINOR 4 +#define UTF8PROC_VERSION_MINOR 9 /** The PATCH version (increased for fixes that do not change the API). */ #define UTF8PROC_VERSION_PATCH 0 /** @} */ @@ -82,7 +79,7 @@ #include #if defined(_MSC_VER) && _MSC_VER < 1800 -// MSVC prior to 2013 lacked stdbool.h and inttypes.h +// MSVC prior to 2013 lacked stdbool.h and stdint.h typedef signed char utf8proc_int8_t; typedef unsigned char utf8proc_uint8_t; typedef short utf8proc_int16_t; @@ -110,29 +107,7 @@ typedef bool utf8proc_bool; #else # include # include -# include -#endif -#include - -#define UTF8PROC_DLLEXPORT -// #ifdef UTF8PROC_STATIC -// # define UTF8PROC_DLLEXPORT -// #else -// # ifdef _WIN32 -// # ifdef UTF8PROC_EXPORTS -// # define UTF8PROC_DLLEXPORT __declspec(dllexport) -// # else -// # define UTF8PROC_DLLEXPORT __declspec(dllimport) -// # endif -// # elif __GNUC__ >= 4 -// # define UTF8PROC_DLLEXPORT __attribute__ ((visibility("default"))) -// # else -// # define UTF8PROC_DLLEXPORT -// # endif -// #endif - -namespace duckdb { - +# include typedef int8_t utf8proc_int8_t; typedef uint8_t utf8proc_uint8_t; typedef int16_t utf8proc_int16_t; @@ -142,10 +117,12 @@ typedef uint32_t utf8proc_uint32_t; typedef size_t utf8proc_size_t; typedef ptrdiff_t utf8proc_ssize_t; typedef bool utf8proc_bool; +#endif +#include -//#ifdef __cplusplus -//extern "C" { -//#endif +# define UTF8PROC_DLLEXPORT + +namespace duckdb { /** * Option flags used by several functions in the library. @@ -268,7 +245,7 @@ typedef struct utf8proc_property_struct { /** * Can this codepoint be ignored? * - * Used by @ref utf8proc_decompose_char when @ref UTF8PROC_IGNORE is + * Used by utf8proc_decompose_char() when @ref UTF8PROC_IGNORE is * passed as an option. */ unsigned ignorable:1; @@ -280,7 +257,8 @@ typedef struct utf8proc_property_struct { * Boundclass. * @see utf8proc_boundclass_t. */ - unsigned boundclass:8; + unsigned boundclass:6; + unsigned indic_conjunct_break:2; } utf8proc_property_t; /** Unicode categories. */ @@ -395,9 +373,17 @@ typedef enum { UTF8PROC_BOUNDCLASS_E_ZWG = 20, /* UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC + ZWJ */ } utf8proc_boundclass_t; +/** Indic_Conjunct_Break property. (TR44) */ +typedef enum { + UTF8PROC_INDIC_CONJUNCT_BREAK_NONE = 0, + UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER = 1, + UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT = 2, + UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND = 3, +} utf8proc_indic_conjunct_break_t; + /** - * Function pointer type passed to @ref utf8proc_map_custom and - * @ref utf8proc_decompose_custom, which is used to specify a user-defined + * Function pointer type passed to utf8proc_map_custom() and + * utf8proc_decompose_custom(), which is used to specify a user-defined * mapping of codepoints to be applied in conjunction with other mappings. */ typedef utf8proc_int32_t (*utf8proc_custom_func)(utf8proc_int32_t codepoint, void *data); @@ -406,7 +392,7 @@ typedef utf8proc_int32_t (*utf8proc_custom_func)(utf8proc_int32_t codepoint, voi * Array containing the byte lengths of a UTF-8 encoded codepoint based * on the first byte. */ -// UTF8PROC_DLLEXPORT extern const utf8proc_int8_t utf8proc_utf8class[256]; +UTF8PROC_DLLEXPORT extern const utf8proc_int8_t utf8proc_utf8class[256]; /** * Returns the utf8proc API version as a string MAJOR.MINOR.PATCH @@ -422,7 +408,7 @@ UTF8PROC_DLLEXPORT const char *utf8proc_unicode_version(void); /** * Returns an informative error string for the given utf8proc error code - * (e.g. the error codes returned by @ref utf8proc_map). + * (e.g. the error codes returned by utf8proc_map()). */ UTF8PROC_DLLEXPORT const char *utf8proc_errmsg(utf8proc_ssize_t errcode); @@ -488,12 +474,13 @@ UTF8PROC_DLLEXPORT const utf8proc_property_t *utf8proc_get_property(utf8proc_int * - @ref UTF8PROC_STRIPNA - remove unassigned codepoints * @param last_boundclass * Pointer to an integer variable containing - * the previous codepoint's boundary class if the @ref UTF8PROC_CHARBOUND - * option is used. Otherwise, this parameter is ignored. + * the previous codepoint's (boundclass + indic_conjunct_break << 1) if the @ref UTF8PROC_CHARBOUND + * option is used. If the string is being processed in order, this can be initialized to 0 for + * the beginning of the string, and is thereafter updated automatically. Otherwise, this parameter is ignored. * * @return * In case of success, the number of codepoints written is returned; in case - * of an error, a negative error code is returned (@ref utf8proc_errmsg). + * of an error, a negative error code is returned (utf8proc_errmsg()). * @par * If the number of written codepoints would be bigger than `bufsize`, the * required buffer size is returned, while the buffer will be overwritten with @@ -505,17 +492,17 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char( ); /** - * The same as @ref utf8proc_decompose_char, but acts on a whole UTF-8 + * The same as utf8proc_decompose_char(), but acts on a whole UTF-8 * string and orders the decomposed sequences correctly. * * If the @ref UTF8PROC_NULLTERM flag in `options` is set, processing - * will be stopped, when a NULL byte is encounted, otherwise `strlen` + * will be stopped, when a NULL byte is encountered, otherwise `strlen` * bytes are processed. The result (in the form of 32-bit unicode * codepoints) is written into the buffer being pointed to by * `buffer` (which must contain at least `bufsize` entries). In case of * success, the number of codepoints written is returned; in case of an - * error, a negative error code is returned (@ref utf8proc_errmsg). - * See @ref utf8proc_decompose_custom to supply additional transformations. + * error, a negative error code is returned (utf8proc_errmsg()). + * See utf8proc_decompose_custom() to supply additional transformations. * * If the number of written codepoints would be bigger than `bufsize`, the * required buffer size is returned, while the buffer will be overwritten with @@ -527,10 +514,10 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose( ); /** - * The same as @ref utf8proc_decompose, but also takes a `custom_func` mapping function + * The same as utf8proc_decompose(), but also takes a `custom_func` mapping function * that is called on each codepoint in `str` before any other transformations * (along with a `custom_data` pointer that is passed through to `custom_func`). - * The `custom_func` argument is ignored if it is `NULL`. See also @ref utf8proc_map_custom. + * The `custom_func` argument is ignored if it is `NULL`. See also utf8proc_map_custom(). */ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom( const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, @@ -556,7 +543,7 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom( * * @return * In case of success, the length (in codepoints) of the normalized UTF-32 string is - * returned; otherwise, a negative error code is returned (@ref utf8proc_errmsg). + * returned; otherwise, a negative error code is returned (utf8proc_errmsg()). * * @warning The entries of the array pointed to by `str` have to be in the * range `0x0000` to `0x10FFFF`. Otherwise, the program might crash! @@ -584,7 +571,7 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *b * @return * In case of success, the length (in bytes) of the resulting nul-terminated * UTF-8 string is returned; otherwise, a negative error code is returned - * (@ref utf8proc_errmsg). + * (utf8proc_errmsg()). * * @warning The amount of free space pointed to by `buffer` must * exceed the amount of the input data by one byte, and the @@ -614,43 +601,12 @@ UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break_stateful( utf8proc_int32_t codepoint1, utf8proc_int32_t codepoint2, utf8proc_int32_t *state); /** - * Same as @ref utf8proc_grapheme_break_stateful, except without support for the + * Same as utf8proc_grapheme_break_stateful(), except without support for the * Unicode 9 additions to the algorithm. Supported for legacy reasons. */ UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break( utf8proc_int32_t codepoint1, utf8proc_int32_t codepoint2); -//! Returns the current UTF8 codepoint in a UTF8 string. Assumes the string is valid UTF8. -UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_codepoint(const char *u_input, int &sz); -UTF8PROC_DLLEXPORT utf8proc_bool grapheme_break_extended(int lbc, int tbc, utf8proc_int32_t *state); -UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_codepoint(const char *u_input, int &sz); -UTF8PROC_DLLEXPORT bool utf8proc_codepoint_to_utf8(int cp, int &sz, char *c); -UTF8PROC_DLLEXPORT int utf8proc_codepoint_length(int cp); -UTF8PROC_DLLEXPORT size_t utf8proc_next_grapheme(const char *s, size_t len, size_t cpos); -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_remove_accents(const utf8proc_uint8_t *str, utf8proc_ssize_t len); -template -void utf8proc_grapheme_callback(const char *s, size_t len, T &&fun) { - int sz; - int boundclass = UTF8PROC_BOUNDCLASS_START; - int initial = utf8proc_get_property(utf8proc_codepoint(s, sz))->boundclass; - grapheme_break_extended(boundclass, initial, &boundclass); - size_t start = 0; - size_t cpos = 0; - while(true) { - cpos += static_cast(sz); - if (cpos >= len) { - fun(start, cpos); - return; - } - int next = utf8proc_get_property(utf8proc_codepoint(s + cpos, sz))->boundclass; - if (grapheme_break_extended(boundclass, next, &boundclass)) { - if (!fun(start, cpos)) { - return; - } - start = cpos; - } - } -} /** * Given a codepoint `c`, return the codepoint of the corresponding @@ -673,6 +629,18 @@ UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_toupper(utf8proc_int32_t c); */ UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_totitle(utf8proc_int32_t c); +/** + * Given a codepoint `c`, return `1` if the codepoint corresponds to a lower-case character + * and `0` otherwise. + */ +UTF8PROC_DLLEXPORT int utf8proc_islower(utf8proc_int32_t c); + +/** + * Given a codepoint `c`, return `1` if the codepoint corresponds to an upper-case character + * and `0` otherwise. + */ +UTF8PROC_DLLEXPORT int utf8proc_isupper(utf8proc_int32_t c); + /** * Given a codepoint, return a character width analogous to `wcwidth(codepoint)`, * except that a width of 0 is returned for non-printable codepoints @@ -680,8 +648,8 @@ UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_totitle(utf8proc_int32_t c); * * @note * If you want to check for particular types of non-printable characters, - * (analogous to `isprint` or `iscntrl`), use @ref utf8proc_category. */ - UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t codepoint); + * (analogous to `isprint` or `iscntrl`), use utf8proc_category(). */ +UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t codepoint); /** * Return the Unicode category for the codepoint (one of the @@ -706,7 +674,7 @@ UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t codepoi * contain NULL characters with the string if `str` contained NULL * characters). Other flags in the `options` field are passed to the * functions defined above, and regarded as described. See also - * @ref utf8proc_map_custom to supply a custom codepoint transformation. + * utf8proc_map_custom() to supply a custom codepoint transformation. * * In case of success the length of the new string is returned, * otherwise a negative error code is returned. @@ -719,7 +687,7 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map( ); /** - * Like @ref utf8proc_map, but also takes a `custom_func` mapping function + * Like utf8proc_map(), but also takes a `custom_func` mapping function * that is called on each codepoint in `str` before any other transformations * (along with a `custom_data` pointer that is passed through to `custom_func`). * The `custom_func` argument is ignored if it is `NULL`. @@ -733,27 +701,27 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom( * * Returns a pointer to newly allocated memory of a NFD, NFC, NFKD, NFKC or * NFKC_Casefold normalized version of the null-terminated string `str`. These - * are shortcuts to calling @ref utf8proc_map with @ref UTF8PROC_NULLTERM + * are shortcuts to calling utf8proc_map() with @ref UTF8PROC_NULLTERM * combined with @ref UTF8PROC_STABLE and flags indicating the normalization. */ /** @{ */ /** NFD normalization (@ref UTF8PROC_DECOMPOSE). */ -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str, utf8proc_ssize_t len); +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen); /** NFC normalization (@ref UTF8PROC_COMPOSE). */ -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str, utf8proc_ssize_t len); +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen); +/** remove accents from a string */ +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_remove_accents(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen); /** NFKD normalization (@ref UTF8PROC_DECOMPOSE and @ref UTF8PROC_COMPAT). */ -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str, utf8proc_ssize_t len); +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen); /** NFKC normalization (@ref UTF8PROC_COMPOSE and @ref UTF8PROC_COMPAT). */ -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str, utf8proc_ssize_t len); +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen); /** * NFKC_Casefold normalization (@ref UTF8PROC_COMPOSE and @ref UTF8PROC_COMPAT * and @ref UTF8PROC_CASEFOLD and @ref UTF8PROC_IGNORE). **/ -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC_Casefold(const utf8proc_uint8_t *str, utf8proc_ssize_t len); +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC_Casefold(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen); /** @} */ -//#ifdef __cplusplus -//} -//#endif } + #endif diff --git a/third_party/utf8proc/include/utf8proc_wrapper.hpp b/third_party/utf8proc/include/utf8proc_wrapper.hpp index a7fb8c662b2..75c9480c2cc 100644 --- a/third_party/utf8proc/include/utf8proc_wrapper.hpp +++ b/third_party/utf8proc/include/utf8proc_wrapper.hpp @@ -14,6 +14,7 @@ #include namespace duckdb { +class GraphemeIterator; enum class UnicodeType { INVALID, ASCII, UNICODE }; enum class UnicodeInvalidReason { BYTE_MISMATCH, INVALID_UNICODE }; @@ -43,6 +44,58 @@ class Utf8Proc { static size_t RenderWidth(const char *s, size_t len, size_t pos); static size_t RenderWidth(const std::string &str); + static int32_t CodepointToUpper(int32_t codepoint); + static int32_t CodepointToLower(int32_t codepoint); + + //! Constructs a class that can be iterated over to fetch grapheme clusters in a string + static GraphemeIterator GraphemeClusters(const char *s, size_t len); + + //! Returns the number of grapheme clusters in a string + static size_t GraphemeCount(const char *s, size_t len); + + }; +struct GraphemeCluster { + size_t start; + size_t end; +}; + +class GraphemeIterator { +public: + GraphemeIterator(const char *s, size_t len); + +private: + const char *s; + size_t len; + +private: + class GraphemeClusterIterator { + public: + GraphemeClusterIterator(const char *s, size_t len); + + const char *s; + size_t len; + GraphemeCluster cluster; + + public: + void Next(); + void SetInvalid(); + bool IsInvalid() const; + + GraphemeClusterIterator &operator++(); + bool operator!=(const GraphemeClusterIterator &other) const; + GraphemeCluster operator*() const; + }; + +public: + GraphemeClusterIterator begin() { // NOLINT: match stl API + return GraphemeClusterIterator(s, len); + } + GraphemeClusterIterator end() { // NOLINT: match stl API + return GraphemeClusterIterator(nullptr, 0); + } +}; + + } diff --git a/third_party/utf8proc/utf8proc.cpp b/third_party/utf8proc/utf8proc.cpp index e4d97aa5be5..bfea42744e4 100644 --- a/third_party/utf8proc/utf8proc.cpp +++ b/third_party/utf8proc/utf8proc.cpp @@ -1,6 +1,6 @@ /* -*- mode: c; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*- */ /* - * Copyright (c) 2014-2019 Steven G. Johnson, Jiahao Chen, Peter Colberg, Tony Kelman, Scott P. Jones, and other contributors. + * Copyright (c) 2014-2021 Steven G. Johnson, Jiahao Chen, Peter Colberg, Tony Kelman, Scott P. Jones, and other contributors. * Copyright (c) 2009 Public Software Group e. V., Berlin, Germany * * Permission is hereby granted, free of charge, to any person obtaining a @@ -27,7 +27,7 @@ * Unicode data files. * * The original data files are available at - * http://www.unicode.org/Public/UNIDATA/ + * https://www.unicode.org/Public/UNIDATA/ * * Please notice the copyright statement in the file "utf8proc_data.c". */ @@ -44,7 +44,6 @@ #include "utf8proc.hpp" namespace duckdb { - #ifndef SSIZE_MAX #define SSIZE_MAX ((size_t)SIZE_MAX/2) #endif @@ -55,23 +54,23 @@ namespace duckdb { #include "utf8proc_data.cpp" -// UTF8PROC_DLLEXPORT const utf8proc_int8_t utf8proc_utf8class[256] = { -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -// 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -// 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -// 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -// 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0 }; +UTF8PROC_DLLEXPORT const utf8proc_int8_t utf8proc_utf8class[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0 }; #define UTF8PROC_HANGUL_SBASE 0xAC00 #define UTF8PROC_HANGUL_LBASE 0x1100 @@ -94,755 +93,712 @@ namespace duckdb { #define UTF8PROC_HANGUL_S_END 0xD7A4 /* Should follow semantic-versioning rules (semver.org) based on API - compatibility. (Note that the shared-library version number will - be different, being based on ABI compatibility.): */ + compatibility. (Note that the shared-library version number will + be different, being based on ABI compatibility.): */ #define STRINGIZEx(x) #x #define STRINGIZE(x) STRINGIZEx(x) UTF8PROC_DLLEXPORT const char *utf8proc_version(void) { - return STRINGIZE(UTF8PROC_VERSION_MAJOR) "." STRINGIZE(UTF8PROC_VERSION_MINOR) "." STRINGIZE(UTF8PROC_VERSION_PATCH) ""; + return STRINGIZE(UTF8PROC_VERSION_MAJOR) "." STRINGIZE(UTF8PROC_VERSION_MINOR) "." STRINGIZE(UTF8PROC_VERSION_PATCH) ""; } UTF8PROC_DLLEXPORT const char *utf8proc_unicode_version(void) { - return "12.1.0"; + return "15.1.0"; } UTF8PROC_DLLEXPORT const char *utf8proc_errmsg(utf8proc_ssize_t errcode) { - switch (errcode) { - case UTF8PROC_ERROR_NOMEM: - return "Memory for processing UTF-8 data could not be allocated."; - case UTF8PROC_ERROR_OVERFLOW: - return "UTF-8 string is too long to be processed."; - case UTF8PROC_ERROR_INVALIDUTF8: - return "Invalid UTF-8 string"; - case UTF8PROC_ERROR_NOTASSIGNED: - return "Unassigned Unicode code point found in UTF-8 string."; - case UTF8PROC_ERROR_INVALIDOPTS: - return "Invalid options for UTF-8 processing chosen."; - default: - return "An unknown error occurred while processing UTF-8 data."; - } + switch (errcode) { + case UTF8PROC_ERROR_NOMEM: + return "Memory for processing UTF-8 data could not be allocated."; + case UTF8PROC_ERROR_OVERFLOW: + return "UTF-8 string is too long to be processed."; + case UTF8PROC_ERROR_INVALIDUTF8: + return "Invalid UTF-8 string"; + case UTF8PROC_ERROR_NOTASSIGNED: + return "Unassigned Unicode code point found in UTF-8 string."; + case UTF8PROC_ERROR_INVALIDOPTS: + return "Invalid options for UTF-8 processing chosen."; + default: + return "An unknown error occurred while processing UTF-8 data."; + } } #define utf_cont(ch) (((ch) & 0xc0) == 0x80) UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_iterate( - const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_int32_t *dst + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_int32_t *dst ) { - utf8proc_uint32_t uc; - const utf8proc_uint8_t *end; - - *dst = -1; - if (!strlen) return 0; - end = str + ((strlen < 0) ? 4 : strlen); - uc = *str++; - if (uc < 0x80) { - *dst = uc; - return 1; - } - // Must be between 0xc2 and 0xf4 inclusive to be valid - if ((uc - 0xc2) > (0xf4-0xc2)) return UTF8PROC_ERROR_INVALIDUTF8; - if (uc < 0xe0) { // 2-byte sequence - // Must have valid continuation character - if (str >= end || !utf_cont(*str)) return UTF8PROC_ERROR_INVALIDUTF8; - *dst = ((uc & 0x1f)<<6) | (*str & 0x3f); - return 2; - } - if (uc < 0xf0) { // 3-byte sequence - if ((str + 1 >= end) || !utf_cont(*str) || !utf_cont(str[1])) - return UTF8PROC_ERROR_INVALIDUTF8; - // Check for surrogate chars - if (uc == 0xed && *str > 0x9f) - return UTF8PROC_ERROR_INVALIDUTF8; - uc = ((uc & 0xf)<<12) | ((*str & 0x3f)<<6) | (str[1] & 0x3f); - if (uc < 0x800) - return UTF8PROC_ERROR_INVALIDUTF8; - *dst = uc; - return 3; - } - // 4-byte sequence - // Must have 3 valid continuation characters - if ((str + 2 >= end) || !utf_cont(*str) || !utf_cont(str[1]) || !utf_cont(str[2])) - return UTF8PROC_ERROR_INVALIDUTF8; - // Make sure in correct range (0x10000 - 0x10ffff) - if (uc == 0xf0) { - if (*str < 0x90) return UTF8PROC_ERROR_INVALIDUTF8; - } else if (uc == 0xf4) { - if (*str > 0x8f) return UTF8PROC_ERROR_INVALIDUTF8; - } - *dst = ((uc & 7)<<18) | ((*str & 0x3f)<<12) | ((str[1] & 0x3f)<<6) | (str[2] & 0x3f); - return 4; + utf8proc_int32_t uc; + const utf8proc_uint8_t *end; + + *dst = -1; + if (!strlen) return 0; + end = str + ((strlen < 0) ? 4 : strlen); + uc = *str++; + if (uc < 0x80) { + *dst = uc; + return 1; + } + // Must be between 0xc2 and 0xf4 inclusive to be valid + if ((utf8proc_uint32_t)(uc - 0xc2) > (0xf4-0xc2)) return UTF8PROC_ERROR_INVALIDUTF8; + if (uc < 0xe0) { // 2-byte sequence + // Must have valid continuation character + if (str >= end || !utf_cont(*str)) return UTF8PROC_ERROR_INVALIDUTF8; + *dst = ((uc & 0x1f)<<6) | (*str & 0x3f); + return 2; + } + if (uc < 0xf0) { // 3-byte sequence + if ((str + 1 >= end) || !utf_cont(*str) || !utf_cont(str[1])) + return UTF8PROC_ERROR_INVALIDUTF8; + // Check for surrogate chars + if (uc == 0xed && *str > 0x9f) + return UTF8PROC_ERROR_INVALIDUTF8; + uc = ((uc & 0xf)<<12) | ((*str & 0x3f)<<6) | (str[1] & 0x3f); + if (uc < 0x800) + return UTF8PROC_ERROR_INVALIDUTF8; + *dst = uc; + return 3; + } + // 4-byte sequence + // Must have 3 valid continuation characters + if ((str + 2 >= end) || !utf_cont(*str) || !utf_cont(str[1]) || !utf_cont(str[2])) + return UTF8PROC_ERROR_INVALIDUTF8; + // Make sure in correct range (0x10000 - 0x10ffff) + if (uc == 0xf0) { + if (*str < 0x90) return UTF8PROC_ERROR_INVALIDUTF8; + } else if (uc == 0xf4) { + if (*str > 0x8f) return UTF8PROC_ERROR_INVALIDUTF8; + } + *dst = ((uc & 7)<<18) | ((*str & 0x3f)<<12) | ((str[1] & 0x3f)<<6) | (str[2] & 0x3f); + return 4; } UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_codepoint_valid(utf8proc_int32_t uc) { - return (((utf8proc_uint32_t)uc)-0xd800 > 0x07ff) && ((utf8proc_uint32_t)uc < 0x110000); + return (((utf8proc_uint32_t)uc)-0xd800 > 0x07ff) && ((utf8proc_uint32_t)uc < 0x110000); } UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_encode_char(utf8proc_int32_t uc, utf8proc_uint8_t *dst) { - if (uc < 0x00) { - return 0; - } else if (uc < 0x80) { - dst[0] = (utf8proc_uint8_t) uc; - return 1; - } else if (uc < 0x800) { - dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6)); - dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); - return 2; - // Note: we allow encoding 0xd800-0xdfff here, so as not to change - // the API, however, these are actually invalid in UTF-8 - } else if (uc < 0x10000) { - dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12)); - dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); - dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); - return 3; - } else if (uc < 0x110000) { - dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18)); - dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F)); - dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); - dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); - return 4; - } else return 0; + if (uc < 0x00) { + return 0; + } else if (uc < 0x80) { + dst[0] = (utf8proc_uint8_t) uc; + return 1; + } else if (uc < 0x800) { + dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6)); + dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 2; + // Note: we allow encoding 0xd800-0xdfff here, so as not to change + // the API, however, these are actually invalid in UTF-8 + } else if (uc < 0x10000) { + dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 3; + } else if (uc < 0x110000) { + dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 4; + } else return 0; } /* internal version used for inserting 0xff bytes between graphemes */ static utf8proc_ssize_t charbound_encode_char(utf8proc_int32_t uc, utf8proc_uint8_t *dst) { - if (uc < 0x00) { - if (uc == -1) { /* internal value used for grapheme breaks */ - dst[0] = (utf8proc_uint8_t)0xFF; - return 1; - } - return 0; - } else if (uc < 0x80) { - dst[0] = (utf8proc_uint8_t)uc; - return 1; - } else if (uc < 0x800) { - dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6)); - dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); - return 2; - } else if (uc < 0x10000) { - dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12)); - dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); - dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); - return 3; - } else if (uc < 0x110000) { - dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18)); - dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F)); - dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); - dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); - return 4; - } else return 0; + if (uc < 0x00) { + if (uc == -1) { /* internal value used for grapheme breaks */ + dst[0] = (utf8proc_uint8_t)0xFF; + return 1; + } + return 0; + } else if (uc < 0x80) { + dst[0] = (utf8proc_uint8_t)uc; + return 1; + } else if (uc < 0x800) { + dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6)); + dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 2; + } else if (uc < 0x10000) { + dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 3; + } else if (uc < 0x110000) { + dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 4; + } else return 0; } /* internal "unsafe" version that does not check whether uc is in range */ static const utf8proc_property_t *unsafe_get_property(utf8proc_int32_t uc) { - /* ASSERT: uc >= 0 && uc < 0x110000 */ - return utf8proc_properties + ( - utf8proc_stage2table[ - utf8proc_stage1table[uc >> 8] + (uc & 0xFF) - ] - ); + /* ASSERT: uc >= 0 && uc < 0x110000 */ + return utf8proc_properties + ( + utf8proc_stage2table[ + utf8proc_stage1table[uc >> 8] + (uc & 0xFF) + ] + ); } UTF8PROC_DLLEXPORT const utf8proc_property_t *utf8proc_get_property(utf8proc_int32_t uc) { - return uc < 0 || uc >= 0x110000 ? utf8proc_properties : unsafe_get_property(uc); + return uc < 0 || uc >= 0x110000 ? utf8proc_properties : unsafe_get_property(uc); } /* return whether there is a grapheme break between boundclasses lbc and tbc - (according to the definition of extended grapheme clusters) + (according to the definition of extended grapheme clusters) - Rule numbering refers to TR29 Version 29 (Unicode 9.0.0): - http://www.unicode.org/reports/tr29/tr29-29.html + Rule numbering refers to TR29 Version 29 (Unicode 9.0.0): + http://www.unicode.org/reports/tr29/tr29-29.html - CAVEATS: - Please note that evaluation of GB10 (grapheme breaks between emoji zwj sequences) - and GB 12/13 (regional indicator code points) require knowledge of previous characters - and are thus not handled by this function. This may result in an incorrect break before - an E_Modifier class codepoint and an incorrectly missing break between two - REGIONAL_INDICATOR class code points if such support does not exist in the caller. + CAVEATS: + Please note that evaluation of GB10 (grapheme breaks between emoji zwj sequences) + and GB 12/13 (regional indicator code points) require knowledge of previous characters + and are thus not handled by this function. This may result in an incorrect break before + an E_Modifier class codepoint and an incorrectly missing break between two + REGIONAL_INDICATOR class code points if such support does not exist in the caller. - See the special support in grapheme_break_extended, for required bookkeeping by the caller. + See the special support in grapheme_break_extended, for required bookkeeping by the caller. */ static utf8proc_bool grapheme_break_simple(int lbc, int tbc) { - return - (lbc == UTF8PROC_BOUNDCLASS_START) ? true : // GB1 - (lbc == UTF8PROC_BOUNDCLASS_CR && // GB3 - tbc == UTF8PROC_BOUNDCLASS_LF) ? false : // --- - (lbc >= UTF8PROC_BOUNDCLASS_CR && lbc <= UTF8PROC_BOUNDCLASS_CONTROL) ? true : // GB4 - (tbc >= UTF8PROC_BOUNDCLASS_CR && tbc <= UTF8PROC_BOUNDCLASS_CONTROL) ? true : // GB5 - (lbc == UTF8PROC_BOUNDCLASS_L && // GB6 - (tbc == UTF8PROC_BOUNDCLASS_L || // --- - tbc == UTF8PROC_BOUNDCLASS_V || // --- - tbc == UTF8PROC_BOUNDCLASS_LV || // --- - tbc == UTF8PROC_BOUNDCLASS_LVT)) ? false : // --- - ((lbc == UTF8PROC_BOUNDCLASS_LV || // GB7 - lbc == UTF8PROC_BOUNDCLASS_V) && // --- - (tbc == UTF8PROC_BOUNDCLASS_V || // --- - tbc == UTF8PROC_BOUNDCLASS_T)) ? false : // --- - ((lbc == UTF8PROC_BOUNDCLASS_LVT || // GB8 - lbc == UTF8PROC_BOUNDCLASS_T) && // --- - tbc == UTF8PROC_BOUNDCLASS_T) ? false : // --- - (tbc == UTF8PROC_BOUNDCLASS_EXTEND || // GB9 - tbc == UTF8PROC_BOUNDCLASS_ZWJ || // --- - tbc == UTF8PROC_BOUNDCLASS_SPACINGMARK || // GB9a - lbc == UTF8PROC_BOUNDCLASS_PREPEND) ? false : // GB9b - (lbc == UTF8PROC_BOUNDCLASS_E_ZWG && // GB11 (requires additional handling below) - tbc == UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC) ? false : // ---- - (lbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR && // GB12/13 (requires additional handling below) - tbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR) ? false : // ---- - true; // GB999 -} - -utf8proc_bool grapheme_break_extended(int lbc, int tbc, utf8proc_int32_t *state) + return + (lbc == UTF8PROC_BOUNDCLASS_START) ? true : // GB1 + (lbc == UTF8PROC_BOUNDCLASS_CR && // GB3 + tbc == UTF8PROC_BOUNDCLASS_LF) ? false : // --- + (lbc >= UTF8PROC_BOUNDCLASS_CR && lbc <= UTF8PROC_BOUNDCLASS_CONTROL) ? true : // GB4 + (tbc >= UTF8PROC_BOUNDCLASS_CR && tbc <= UTF8PROC_BOUNDCLASS_CONTROL) ? true : // GB5 + (lbc == UTF8PROC_BOUNDCLASS_L && // GB6 + (tbc == UTF8PROC_BOUNDCLASS_L || // --- + tbc == UTF8PROC_BOUNDCLASS_V || // --- + tbc == UTF8PROC_BOUNDCLASS_LV || // --- + tbc == UTF8PROC_BOUNDCLASS_LVT)) ? false : // --- + ((lbc == UTF8PROC_BOUNDCLASS_LV || // GB7 + lbc == UTF8PROC_BOUNDCLASS_V) && // --- + (tbc == UTF8PROC_BOUNDCLASS_V || // --- + tbc == UTF8PROC_BOUNDCLASS_T)) ? false : // --- + ((lbc == UTF8PROC_BOUNDCLASS_LVT || // GB8 + lbc == UTF8PROC_BOUNDCLASS_T) && // --- + tbc == UTF8PROC_BOUNDCLASS_T) ? false : // --- + (tbc == UTF8PROC_BOUNDCLASS_EXTEND || // GB9 + tbc == UTF8PROC_BOUNDCLASS_ZWJ || // --- + tbc == UTF8PROC_BOUNDCLASS_SPACINGMARK || // GB9a + lbc == UTF8PROC_BOUNDCLASS_PREPEND) ? false : // GB9b + (lbc == UTF8PROC_BOUNDCLASS_E_ZWG && // GB11 (requires additional handling below) + tbc == UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC) ? false : // ---- + (lbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR && // GB12/13 (requires additional handling below) + tbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR) ? false : // ---- + true; // GB999 +} + +static utf8proc_bool grapheme_break_extended(int lbc, int tbc, int licb, int ticb, utf8proc_int32_t *state) { - int lbc_override = ((state && *state != UTF8PROC_BOUNDCLASS_START) - ? *state : lbc); - utf8proc_bool break_permitted = grapheme_break_simple(lbc_override, tbc); - if (state) { - // Special support for GB 12/13 made possible by GB999. After two RI - // class codepoints we want to force a break. Do this by resetting the - // second RI's bound class to UTF8PROC_BOUNDCLASS_OTHER, to force a break - // after that character according to GB999 (unless of course such a break is - // forbidden by a different rule such as GB9). - if (*state == tbc && tbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR) - *state = UTF8PROC_BOUNDCLASS_OTHER; - // Special support for GB11 (emoji extend* zwj / emoji) - else if (*state == UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC) { - if (tbc == UTF8PROC_BOUNDCLASS_EXTEND) // fold EXTEND codepoints into emoji - *state = UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC; - else if (tbc == UTF8PROC_BOUNDCLASS_ZWJ) - *state = UTF8PROC_BOUNDCLASS_E_ZWG; // state to record emoji+zwg combo - else - *state = tbc; - } - else - *state = tbc; - } - return break_permitted; + if (state) { + int state_bc, state_icb; /* boundclass and indic_conjunct_break state */ + if (*state == 0) { /* state initialization */ + state_bc = lbc; + state_icb = licb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT ? licb : UTF8PROC_INDIC_CONJUNCT_BREAK_NONE; + } + else { /* lbc and licb are already encoded in *state */ + state_bc = *state & 0xff; // 1st byte of state is bound class + state_icb = *state >> 8; // 2nd byte of state is indic conjunct break + } + + utf8proc_bool break_permitted = grapheme_break_simple(state_bc, tbc) && + !(state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER + && ticb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT); // GB9c + + // Special support for GB9c. Don't break between two consonants + // separated 1+ linker characters and 0+ extend characters in any order. + // After a consonant, we enter LINKER state after at least one linker. + if (ticb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT + || state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT + || state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND) + state_icb = ticb; + else if (state_icb == UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER) + state_icb = ticb == UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND ? + UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER : ticb; + + // Special support for GB 12/13 made possible by GB999. After two RI + // class codepoints we want to force a break. Do this by resetting the + // second RI's bound class to UTF8PROC_BOUNDCLASS_OTHER, to force a break + // after that character according to GB999 (unless of course such a break is + // forbidden by a different rule such as GB9). + if (state_bc == tbc && tbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR) + state_bc = UTF8PROC_BOUNDCLASS_OTHER; + // Special support for GB11 (emoji extend* zwj / emoji) + else if (state_bc == UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC) { + if (tbc == UTF8PROC_BOUNDCLASS_EXTEND) // fold EXTEND codepoints into emoji + state_bc = UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC; + else if (tbc == UTF8PROC_BOUNDCLASS_ZWJ) + state_bc = UTF8PROC_BOUNDCLASS_E_ZWG; // state to record emoji+zwg combo + else + state_bc = tbc; + } + else + state_bc = tbc; + + *state = state_bc + (state_icb << 8); + return break_permitted; + } + else + return grapheme_break_simple(lbc, tbc); } UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break_stateful( - utf8proc_int32_t c1, utf8proc_int32_t c2, utf8proc_int32_t *state) { + utf8proc_int32_t c1, utf8proc_int32_t c2, utf8proc_int32_t *state) { - return grapheme_break_extended(utf8proc_get_property(c1)->boundclass, - utf8proc_get_property(c2)->boundclass, - state); + const utf8proc_property_t *p1 = utf8proc_get_property(c1); + const utf8proc_property_t *p2 = utf8proc_get_property(c2); + return grapheme_break_extended(p1->boundclass, + p2->boundclass, + p1->indic_conjunct_break, + p2->indic_conjunct_break, + state); } UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break( - utf8proc_int32_t c1, utf8proc_int32_t c2) { - return utf8proc_grapheme_break_stateful(c1, c2, NULL); -} - -// from http://www.zedwood.com/article/cpp-utf8-char-to-codepoint -UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_codepoint(const char *u_input, int &sz) { - auto u = (const unsigned char *) u_input; - unsigned char u0 = u[0]; - if (u0<=127) { - sz = 1; - return u0; - } - unsigned char u1 = u[1]; - if (u0>=192 && u0<=223) { - sz = 2; - return (u0-192)*64 + (u1-128); - } - if (u[0]==0xed && (u[1] & 0xa0) == 0xa0) { - return -1; //code points, 0xd800 to 0xdfff - } - unsigned char u2 = u[2]; - if (u0>=224 && u0<=239) { - sz = 3; - return (u0-224)*4096 + (u1-128)*64 + (u2-128); - } - unsigned char u3 = u[3]; - if (u0>=240 && u0<=247) { - sz = 4; - return (u0-240)*262144 + (u1-128)*4096 + (u2-128)*64 + (u3-128); - } - return -1; -} - -bool utf8proc_codepoint_to_utf8(int cp, int &sz, char *c) { - if (cp<=0x7F) { - sz = 1; - c[0] = cp; - } else if(cp<=0x7FF) { - sz = 2; - c[0] = (cp>>6)+192; - c[1] = (cp&63)+128; - } else if(0xd800<=cp && cp<=0xdfff) { - sz = -1; - // invalid block of utf - return false; - } else if(cp<=0xFFFF) { - sz = 3; - c[0] = (cp>>12)+224; - c[1]= ((cp>>6)&63)+128; - c[2]=(cp&63)+128; - } else if(cp<=0x10FFFF) { - sz = 4; - c[0] = (cp>>18)+240; - c[1] = ((cp>>12)&63)+128; - c[2] = ((cp>>6)&63)+128; - c[3]=(cp&63)+128; - } else { - sz = -1; - return false; - } - return true; -} - -int utf8proc_codepoint_length(int cp) { - if (cp<=0x7F) { - return 1; - } else if(cp<=0x7FF) { - return 2; - } else if(0xd800<=cp && cp<=0xdfff) { - return -1; - } else if(cp<=0xFFFF) { - return 3; - } else if(cp<=0x10FFFF) { - return 4; - } - return -1; -} - -size_t utf8proc_next_grapheme(const char *s, size_t len, size_t cpos) { - int sz; - int boundclass = UTF8PROC_BOUNDCLASS_START; - int initial = utf8proc_get_property(utf8proc_codepoint(s + cpos, sz))->boundclass; - grapheme_break_extended(boundclass, initial, &boundclass); - while(true) { - cpos += sz; - if (cpos >= len) { - return cpos; - } - int next = utf8proc_get_property(utf8proc_codepoint(s + cpos, sz))->boundclass; - if (grapheme_break_extended(boundclass, next, &boundclass)) { - return cpos; - } - } + utf8proc_int32_t c1, utf8proc_int32_t c2) { + return utf8proc_grapheme_break_stateful(c1, c2, NULL); } static utf8proc_int32_t seqindex_decode_entry(const utf8proc_uint16_t **entry) { - utf8proc_int32_t entry_cp = **entry; - if ((entry_cp & 0xF800) == 0xD800) { - *entry = *entry + 1; - entry_cp = ((entry_cp & 0x03FF) << 10) | (**entry & 0x03FF); - entry_cp += 0x10000; - } - return entry_cp; + utf8proc_int32_t entry_cp = **entry; + if ((entry_cp & 0xF800) == 0xD800) { + *entry = *entry + 1; + entry_cp = ((entry_cp & 0x03FF) << 10) | (**entry & 0x03FF); + entry_cp += 0x10000; + } + return entry_cp; } static utf8proc_int32_t seqindex_decode_index(const utf8proc_uint32_t seqindex) { - const utf8proc_uint16_t *entry = &utf8proc_sequences[seqindex]; - return seqindex_decode_entry(&entry); + const utf8proc_uint16_t *entry = &utf8proc_sequences[seqindex]; + return seqindex_decode_entry(&entry); } static utf8proc_ssize_t seqindex_write_char_decomposed(utf8proc_uint16_t seqindex, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) { - utf8proc_ssize_t written = 0; - const utf8proc_uint16_t *entry = &utf8proc_sequences[seqindex & 0x1FFF]; - int len = seqindex >> 13; - if (len >= 7) { - len = *entry; - entry++; - } - for (; len >= 0; entry++, len--) { - utf8proc_int32_t entry_cp = seqindex_decode_entry(&entry); - utf8proc_int32_t *dst_ptr = dst ? dst + written : nullptr; - written += utf8proc_decompose_char(entry_cp, dst_ptr, - (bufsize > written) ? (bufsize - written) : 0, options, - last_boundclass); - if (written < 0) return UTF8PROC_ERROR_OVERFLOW; - } - return written; + utf8proc_ssize_t written = 0; + const utf8proc_uint16_t *entry = &utf8proc_sequences[seqindex & 0x3FFF]; + int len = seqindex >> 14; + if (len >= 3) { + len = *entry; + entry++; + } + for (; len >= 0; entry++, len--) { + utf8proc_int32_t entry_cp = seqindex_decode_entry(&entry); + + written += utf8proc_decompose_char(entry_cp, dst ? dst+written : nullptr, + (bufsize > written) ? (bufsize - written) : 0, options, + last_boundclass); + if (written < 0) return UTF8PROC_ERROR_OVERFLOW; + } + return written; } UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_tolower(utf8proc_int32_t c) { - utf8proc_int32_t cl = utf8proc_get_property(c)->lowercase_seqindex; - return cl != UINT16_MAX ? seqindex_decode_index(cl) : c; + utf8proc_int32_t cl = utf8proc_get_property(c)->lowercase_seqindex; + return cl != UINT16_MAX ? seqindex_decode_index((utf8proc_uint32_t)cl) : c; } UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_toupper(utf8proc_int32_t c) { - utf8proc_int32_t cu = utf8proc_get_property(c)->uppercase_seqindex; - return cu != UINT16_MAX ? seqindex_decode_index(cu) : c; + utf8proc_int32_t cu = utf8proc_get_property(c)->uppercase_seqindex; + return cu != UINT16_MAX ? seqindex_decode_index((utf8proc_uint32_t)cu) : c; } UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_totitle(utf8proc_int32_t c) { - utf8proc_int32_t cu = utf8proc_get_property(c)->titlecase_seqindex; - return cu != UINT16_MAX ? seqindex_decode_index(cu) : c; + utf8proc_int32_t cu = utf8proc_get_property(c)->titlecase_seqindex; + return cu != UINT16_MAX ? seqindex_decode_index((utf8proc_uint32_t)cu) : c; +} + +UTF8PROC_DLLEXPORT int utf8proc_islower(utf8proc_int32_t c) +{ + const utf8proc_property_t *p = utf8proc_get_property(c); + return p->lowercase_seqindex != p->uppercase_seqindex && p->lowercase_seqindex == UINT16_MAX; +} + +UTF8PROC_DLLEXPORT int utf8proc_isupper(utf8proc_int32_t c) +{ + const utf8proc_property_t *p = utf8proc_get_property(c); + return p->lowercase_seqindex != p->uppercase_seqindex && p->uppercase_seqindex == UINT16_MAX && p->category != UTF8PROC_CATEGORY_LT; } /* return a character width analogous to wcwidth (except portable and - hopefully less buggy than most system wcwidth functions). */ + hopefully less buggy than most system wcwidth functions). */ UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t c) { - return utf8proc_get_property(c)->charwidth; + return utf8proc_get_property(c)->charwidth; } UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_t c) { - return (utf8proc_category_t)utf8proc_get_property(c)->category; + return (utf8proc_category_t) utf8proc_get_property(c)->category; } UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) { - static const char s[][3] = {"Cn","Lu","Ll","Lt","Lm","Lo","Mn","Mc","Me","Nd","Nl","No","Pc","Pd","Ps","Pe","Pi","Pf","Po","Sm","Sc","Sk","So","Zs","Zl","Zp","Cc","Cf","Cs","Co"}; - return s[utf8proc_category(c)]; + static const char s[][3] = {"Cn","Lu","Ll","Lt","Lm","Lo","Mn","Mc","Me","Nd","Nl","No","Pc","Pd","Ps","Pe","Pi","Pf","Po","Sm","Sc","Sk","So","Zs","Zl","Zp","Cc","Cf","Cs","Co"}; + return s[utf8proc_category(c)]; } #define utf8proc_decompose_lump(replacement_uc) \ - return utf8proc_decompose_char((replacement_uc), dst, bufsize, \ - (utf8proc_option_t) (options & ~UTF8PROC_LUMP), last_boundclass) +return utf8proc_decompose_char((replacement_uc), dst, bufsize, \ +(utf8proc_option_t)(options & ~(unsigned int)UTF8PROC_LUMP), last_boundclass) UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) { - const utf8proc_property_t *property; - utf8proc_propval_t category; - utf8proc_int32_t hangul_sindex; - if (uc < 0 || uc >= 0x110000) return UTF8PROC_ERROR_NOTASSIGNED; - property = unsafe_get_property(uc); - category = property->category; - hangul_sindex = uc - UTF8PROC_HANGUL_SBASE; - if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) { - if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT) { - utf8proc_int32_t hangul_tindex; - if (bufsize >= 1) { - dst[0] = UTF8PROC_HANGUL_LBASE + - hangul_sindex / UTF8PROC_HANGUL_NCOUNT; - if (bufsize >= 2) dst[1] = UTF8PROC_HANGUL_VBASE + - (hangul_sindex % UTF8PROC_HANGUL_NCOUNT) / UTF8PROC_HANGUL_TCOUNT; - } - hangul_tindex = hangul_sindex % UTF8PROC_HANGUL_TCOUNT; - if (!hangul_tindex) return 2; - if (bufsize >= 3) dst[2] = UTF8PROC_HANGUL_TBASE + hangul_tindex; - return 3; - } - } - if (options & UTF8PROC_REJECTNA) { - if (!category) return UTF8PROC_ERROR_NOTASSIGNED; - } - if (options & UTF8PROC_IGNORE) { - if (property->ignorable) return 0; - } - if (options & UTF8PROC_STRIPNA) { - if (!category) return 0; - } - if (options & UTF8PROC_LUMP) { - if (category == UTF8PROC_CATEGORY_ZS) utf8proc_decompose_lump(0x0020); - if (uc == 0x2018 || uc == 0x2019 || uc == 0x02BC || uc == 0x02C8) - utf8proc_decompose_lump(0x0027); - if (category == UTF8PROC_CATEGORY_PD || uc == 0x2212) - utf8proc_decompose_lump(0x002D); - if (uc == 0x2044 || uc == 0x2215) utf8proc_decompose_lump(0x002F); - if (uc == 0x2236) utf8proc_decompose_lump(0x003A); - if (uc == 0x2039 || uc == 0x2329 || uc == 0x3008) - utf8proc_decompose_lump(0x003C); - if (uc == 0x203A || uc == 0x232A || uc == 0x3009) - utf8proc_decompose_lump(0x003E); - if (uc == 0x2216) utf8proc_decompose_lump(0x005C); - if (uc == 0x02C4 || uc == 0x02C6 || uc == 0x2038 || uc == 0x2303) - utf8proc_decompose_lump(0x005E); - if (category == UTF8PROC_CATEGORY_PC || uc == 0x02CD) - utf8proc_decompose_lump(0x005F); - if (uc == 0x02CB) utf8proc_decompose_lump(0x0060); - if (uc == 0x2223) utf8proc_decompose_lump(0x007C); - if (uc == 0x223C) utf8proc_decompose_lump(0x007E); - if ((options & UTF8PROC_NLF2LS) && (options & UTF8PROC_NLF2PS)) { - if (category == UTF8PROC_CATEGORY_ZL || - category == UTF8PROC_CATEGORY_ZP) - utf8proc_decompose_lump(0x000A); - } - } - if (options & UTF8PROC_STRIPMARK) { - if (category == UTF8PROC_CATEGORY_MN || - category == UTF8PROC_CATEGORY_MC || - category == UTF8PROC_CATEGORY_ME) return 0; - } - if (options & UTF8PROC_CASEFOLD) { - if (property->casefold_seqindex != UINT16_MAX) { - return seqindex_write_char_decomposed(property->casefold_seqindex, dst, bufsize, options, last_boundclass); - } - } - if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) { - if (property->decomp_seqindex != UINT16_MAX && - (!property->decomp_type || (options & UTF8PROC_COMPAT))) { - return seqindex_write_char_decomposed(property->decomp_seqindex, dst, bufsize, options, last_boundclass); - } - } - if (options & UTF8PROC_CHARBOUND) { - utf8proc_bool boundary; - int tbc = property->boundclass; - boundary = grapheme_break_extended(*last_boundclass, tbc, last_boundclass); - if (boundary) { - if (bufsize >= 1) dst[0] = -1; /* sentinel value for grapheme break */ - if (bufsize >= 2) dst[1] = uc; - return 2; - } - } - if (bufsize >= 1) *dst = uc; - return 1; + const utf8proc_property_t *property; + utf8proc_propval_t category; + utf8proc_int32_t hangul_sindex; + if (uc < 0 || uc >= 0x110000) return UTF8PROC_ERROR_NOTASSIGNED; + property = unsafe_get_property(uc); + category = property->category; + hangul_sindex = uc - UTF8PROC_HANGUL_SBASE; + if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) { + if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT) { + utf8proc_int32_t hangul_tindex; + if (bufsize >= 1) { + dst[0] = UTF8PROC_HANGUL_LBASE + + hangul_sindex / UTF8PROC_HANGUL_NCOUNT; + if (bufsize >= 2) dst[1] = UTF8PROC_HANGUL_VBASE + + (hangul_sindex % UTF8PROC_HANGUL_NCOUNT) / UTF8PROC_HANGUL_TCOUNT; + } + hangul_tindex = hangul_sindex % UTF8PROC_HANGUL_TCOUNT; + if (!hangul_tindex) return 2; + if (bufsize >= 3) dst[2] = UTF8PROC_HANGUL_TBASE + hangul_tindex; + return 3; + } + } + if (options & UTF8PROC_REJECTNA) { + if (!category) return UTF8PROC_ERROR_NOTASSIGNED; + } + if (options & UTF8PROC_IGNORE) { + if (property->ignorable) return 0; + } + if (options & UTF8PROC_STRIPNA) { + if (!category) return 0; + } + if (options & UTF8PROC_LUMP) { + if (category == UTF8PROC_CATEGORY_ZS) utf8proc_decompose_lump(0x0020); + if (uc == 0x2018 || uc == 0x2019 || uc == 0x02BC || uc == 0x02C8) + utf8proc_decompose_lump(0x0027); + if (category == UTF8PROC_CATEGORY_PD || uc == 0x2212) + utf8proc_decompose_lump(0x002D); + if (uc == 0x2044 || uc == 0x2215) utf8proc_decompose_lump(0x002F); + if (uc == 0x2236) utf8proc_decompose_lump(0x003A); + if (uc == 0x2039 || uc == 0x2329 || uc == 0x3008) + utf8proc_decompose_lump(0x003C); + if (uc == 0x203A || uc == 0x232A || uc == 0x3009) + utf8proc_decompose_lump(0x003E); + if (uc == 0x2216) utf8proc_decompose_lump(0x005C); + if (uc == 0x02C4 || uc == 0x02C6 || uc == 0x2038 || uc == 0x2303) + utf8proc_decompose_lump(0x005E); + if (category == UTF8PROC_CATEGORY_PC || uc == 0x02CD) + utf8proc_decompose_lump(0x005F); + if (uc == 0x02CB) utf8proc_decompose_lump(0x0060); + if (uc == 0x2223) utf8proc_decompose_lump(0x007C); + if (uc == 0x223C) utf8proc_decompose_lump(0x007E); + if ((options & UTF8PROC_NLF2LS) && (options & UTF8PROC_NLF2PS)) { + if (category == UTF8PROC_CATEGORY_ZL || + category == UTF8PROC_CATEGORY_ZP) + utf8proc_decompose_lump(0x000A); + } + } + if (options & UTF8PROC_STRIPMARK) { + if (category == UTF8PROC_CATEGORY_MN || + category == UTF8PROC_CATEGORY_MC || + category == UTF8PROC_CATEGORY_ME) return 0; + } + if (options & UTF8PROC_CASEFOLD) { + if (property->casefold_seqindex != UINT16_MAX) { + return seqindex_write_char_decomposed(property->casefold_seqindex, dst, bufsize, options, last_boundclass); + } + } + if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) { + if (property->decomp_seqindex != UINT16_MAX && + (!property->decomp_type || (options & UTF8PROC_COMPAT))) { + return seqindex_write_char_decomposed(property->decomp_seqindex, dst, bufsize, options, last_boundclass); + } + } + if (options & UTF8PROC_CHARBOUND) { + utf8proc_bool boundary; + boundary = grapheme_break_extended(0, property->boundclass, 0, property->indic_conjunct_break, + last_boundclass); + if (boundary) { + if (bufsize >= 1) dst[0] = -1; /* sentinel value for grapheme break */ + if (bufsize >= 2) dst[1] = uc; + return 2; + } + } + if (bufsize >= 1) *dst = uc; + return 1; } UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose( - const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, - utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, + utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options ) { - return utf8proc_decompose_custom(str, strlen, buffer, bufsize, options, NULL, NULL); + return utf8proc_decompose_custom(str, strlen, buffer, bufsize, options, NULL, NULL); } UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom( - const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, - utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options, - utf8proc_custom_func custom_func, void *custom_data + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, + utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options, + utf8proc_custom_func custom_func, void *custom_data ) { - /* strlen will be ignored, if UTF8PROC_NULLTERM is set in options */ - utf8proc_ssize_t wpos = 0; - if ((options & UTF8PROC_COMPOSE) && (options & UTF8PROC_DECOMPOSE)) - return UTF8PROC_ERROR_INVALIDOPTS; - if ((options & UTF8PROC_STRIPMARK) && - !(options & UTF8PROC_COMPOSE) && !(options & UTF8PROC_DECOMPOSE)) - return UTF8PROC_ERROR_INVALIDOPTS; - { - utf8proc_int32_t uc; - utf8proc_ssize_t rpos = 0; - utf8proc_ssize_t decomp_result; - int boundclass = UTF8PROC_BOUNDCLASS_START; - while (1) { - if (options & UTF8PROC_NULLTERM) { - rpos += utf8proc_iterate(str + rpos, -1, &uc); - /* checking of return value is not necessary, - as 'uc' is < 0 in case of error */ - if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8; - if (rpos < 0) return UTF8PROC_ERROR_OVERFLOW; - if (uc == 0) break; - } else { - if (rpos >= strlen) break; - rpos += utf8proc_iterate(str + rpos, strlen - rpos, &uc); - if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8; - } - if (custom_func != NULL) { - uc = custom_func(uc, custom_data); /* user-specified custom mapping */ - } - utf8proc_int32_t *target_buffer = buffer ? buffer + wpos : nullptr; - decomp_result = utf8proc_decompose_char( - uc, target_buffer, (bufsize > wpos) ? (bufsize - wpos) : 0, options, - &boundclass - ); - if (decomp_result < 0) return decomp_result; - wpos += decomp_result; - /* prohibiting integer overflows due to too long strings: */ - if (wpos < 0 || - wpos > (utf8proc_ssize_t)(SSIZE_MAX/sizeof(utf8proc_int32_t)/2)) - return UTF8PROC_ERROR_OVERFLOW; - } - } - if ((options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) && bufsize >= wpos) { - utf8proc_ssize_t pos = 0; - while (pos < wpos-1) { - utf8proc_int32_t uc1, uc2; - const utf8proc_property_t *property1, *property2; - uc1 = buffer[pos]; - uc2 = buffer[pos+1]; - property1 = unsafe_get_property(uc1); - property2 = unsafe_get_property(uc2); - if (property1->combining_class > property2->combining_class && - property2->combining_class > 0) { - buffer[pos] = uc2; - buffer[pos+1] = uc1; - if (pos > 0) pos--; else pos++; - } else { - pos++; - } - } - } - return wpos; + /* strlen will be ignored, if UTF8PROC_NULLTERM is set in options */ + utf8proc_ssize_t wpos = 0; + if ((options & UTF8PROC_COMPOSE) && (options & UTF8PROC_DECOMPOSE)) + return UTF8PROC_ERROR_INVALIDOPTS; + if ((options & UTF8PROC_STRIPMARK) && + !(options & UTF8PROC_COMPOSE) && !(options & UTF8PROC_DECOMPOSE)) + return UTF8PROC_ERROR_INVALIDOPTS; + { + utf8proc_int32_t uc; + utf8proc_ssize_t rpos = 0; + utf8proc_ssize_t decomp_result; + int boundclass = UTF8PROC_BOUNDCLASS_START; + while (1) { + if (options & UTF8PROC_NULLTERM) { + rpos += utf8proc_iterate(str + rpos, -1, &uc); + /* checking of return value is not necessary, + as 'uc' is < 0 in case of error */ + if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8; + if (rpos < 0) return UTF8PROC_ERROR_OVERFLOW; + if (uc == 0) break; + } else { + if (rpos >= strlen) break; + rpos += utf8proc_iterate(str + rpos, strlen - rpos, &uc); + if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8; + } + if (custom_func != NULL) { + uc = custom_func(uc, custom_data); /* user-specified custom mapping */ + } + decomp_result = utf8proc_decompose_char( + uc, buffer ? buffer + wpos : nullptr, (bufsize > wpos) ? (bufsize - wpos) : 0, options, + &boundclass + ); + if (decomp_result < 0) return decomp_result; + wpos += decomp_result; + /* prohibiting integer overflows due to too long strings: */ + if (wpos < 0 || + wpos > (utf8proc_ssize_t)(SSIZE_MAX/sizeof(utf8proc_int32_t)/2)) + return UTF8PROC_ERROR_OVERFLOW; + } + } + if ((options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) && bufsize >= wpos) { + utf8proc_ssize_t pos = 0; + while (pos < wpos-1) { + utf8proc_int32_t uc1, uc2; + const utf8proc_property_t *property1, *property2; + uc1 = buffer[pos]; + uc2 = buffer[pos+1]; + property1 = unsafe_get_property(uc1); + property2 = unsafe_get_property(uc2); + if (property1->combining_class > property2->combining_class && + property2->combining_class > 0) { + buffer[pos] = uc2; + buffer[pos+1] = uc1; + if (pos > 0) pos--; else pos++; + } else { + pos++; + } + } + } + return wpos; } UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) { - /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored */ - if (options & (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS | UTF8PROC_STRIPCC)) { - utf8proc_ssize_t rpos; - utf8proc_ssize_t wpos = 0; - utf8proc_int32_t uc; - for (rpos = 0; rpos < length; rpos++) { - uc = buffer[rpos]; - if (uc == 0x000D && rpos < length-1 && buffer[rpos+1] == 0x000A) rpos++; - if (uc == 0x000A || uc == 0x000D || uc == 0x0085 || - ((options & UTF8PROC_STRIPCC) && (uc == 0x000B || uc == 0x000C))) { - if (options & UTF8PROC_NLF2LS) { - if (options & UTF8PROC_NLF2PS) { - buffer[wpos++] = 0x000A; - } else { - buffer[wpos++] = 0x2028; - } - } else { - if (options & UTF8PROC_NLF2PS) { - buffer[wpos++] = 0x2029; - } else { - buffer[wpos++] = 0x0020; - } - } - } else if ((options & UTF8PROC_STRIPCC) && - (uc < 0x0020 || (uc >= 0x007F && uc < 0x00A0))) { - if (uc == 0x0009) buffer[wpos++] = 0x0020; - } else { - buffer[wpos++] = uc; - } - } - length = wpos; - } - if (options & UTF8PROC_COMPOSE) { - utf8proc_int32_t *starter = NULL; - utf8proc_int32_t current_char; - const utf8proc_property_t *starter_property = NULL, *current_property; - utf8proc_propval_t max_combining_class = -1; - utf8proc_ssize_t rpos; - utf8proc_ssize_t wpos = 0; - utf8proc_int32_t composition; - for (rpos = 0; rpos < length; rpos++) { - current_char = buffer[rpos]; - current_property = unsafe_get_property(current_char); - if (starter && current_property->combining_class > max_combining_class) { - /* combination perhaps possible */ - utf8proc_int32_t hangul_lindex; - utf8proc_int32_t hangul_sindex; - hangul_lindex = *starter - UTF8PROC_HANGUL_LBASE; - if (hangul_lindex >= 0 && hangul_lindex < UTF8PROC_HANGUL_LCOUNT) { - utf8proc_int32_t hangul_vindex; - hangul_vindex = current_char - UTF8PROC_HANGUL_VBASE; - if (hangul_vindex >= 0 && hangul_vindex < UTF8PROC_HANGUL_VCOUNT) { - *starter = UTF8PROC_HANGUL_SBASE + - (hangul_lindex * UTF8PROC_HANGUL_VCOUNT + hangul_vindex) * - UTF8PROC_HANGUL_TCOUNT; - starter_property = NULL; - continue; - } - } - hangul_sindex = *starter - UTF8PROC_HANGUL_SBASE; - if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT && - (hangul_sindex % UTF8PROC_HANGUL_TCOUNT) == 0) { - utf8proc_int32_t hangul_tindex; - hangul_tindex = current_char - UTF8PROC_HANGUL_TBASE; - if (hangul_tindex >= 0 && hangul_tindex < UTF8PROC_HANGUL_TCOUNT) { - *starter += hangul_tindex; - starter_property = NULL; - continue; - } - } - if (!starter_property) { - starter_property = unsafe_get_property(*starter); - } - if (starter_property->comb_index < 0x8000 && - current_property->comb_index != UINT16_MAX && - current_property->comb_index >= 0x8000) { - int sidx = starter_property->comb_index; - int idx = current_property->comb_index & 0x3FFF; - if (idx >= utf8proc_combinations[sidx] && idx <= utf8proc_combinations[sidx + 1] ) { - idx += sidx + 2 - utf8proc_combinations[sidx]; - if (current_property->comb_index & 0x4000) { - composition = (utf8proc_combinations[idx] << 16) | utf8proc_combinations[idx+1]; - } else - composition = utf8proc_combinations[idx]; - - if (composition > 0 && (!(options & UTF8PROC_STABLE) || - !(unsafe_get_property(composition)->comp_exclusion))) { - *starter = composition; - starter_property = NULL; - continue; - } - } - } - } - buffer[wpos] = current_char; - if (current_property->combining_class) { - if (current_property->combining_class > max_combining_class) { - max_combining_class = current_property->combining_class; - } - } else { - starter = buffer + wpos; - starter_property = NULL; - max_combining_class = -1; - } - wpos++; - } - length = wpos; - } - return length; + /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored */ + if (options & (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS | UTF8PROC_STRIPCC)) { + utf8proc_ssize_t rpos; + utf8proc_ssize_t wpos = 0; + utf8proc_int32_t uc; + for (rpos = 0; rpos < length; rpos++) { + uc = buffer[rpos]; + if (uc == 0x000D && rpos < length-1 && buffer[rpos+1] == 0x000A) rpos++; + if (uc == 0x000A || uc == 0x000D || uc == 0x0085 || + ((options & UTF8PROC_STRIPCC) && (uc == 0x000B || uc == 0x000C))) { + if (options & UTF8PROC_NLF2LS) { + if (options & UTF8PROC_NLF2PS) { + buffer[wpos++] = 0x000A; + } else { + buffer[wpos++] = 0x2028; + } + } else { + if (options & UTF8PROC_NLF2PS) { + buffer[wpos++] = 0x2029; + } else { + buffer[wpos++] = 0x0020; + } + } + } else if ((options & UTF8PROC_STRIPCC) && + (uc < 0x0020 || (uc >= 0x007F && uc < 0x00A0))) { + if (uc == 0x0009) buffer[wpos++] = 0x0020; + } else { + buffer[wpos++] = uc; + } + } + length = wpos; + } + if (options & UTF8PROC_COMPOSE) { + utf8proc_int32_t *starter = NULL; + utf8proc_int32_t current_char; + const utf8proc_property_t *starter_property = NULL, *current_property; + utf8proc_propval_t max_combining_class = -1; + utf8proc_ssize_t rpos; + utf8proc_ssize_t wpos = 0; + utf8proc_int32_t composition; + for (rpos = 0; rpos < length; rpos++) { + current_char = buffer[rpos]; + current_property = unsafe_get_property(current_char); + if (starter && current_property->combining_class > max_combining_class) { + /* combination perhaps possible */ + utf8proc_int32_t hangul_lindex; + utf8proc_int32_t hangul_sindex; + hangul_lindex = *starter - UTF8PROC_HANGUL_LBASE; + if (hangul_lindex >= 0 && hangul_lindex < UTF8PROC_HANGUL_LCOUNT) { + utf8proc_int32_t hangul_vindex; + hangul_vindex = current_char - UTF8PROC_HANGUL_VBASE; + if (hangul_vindex >= 0 && hangul_vindex < UTF8PROC_HANGUL_VCOUNT) { + *starter = UTF8PROC_HANGUL_SBASE + + (hangul_lindex * UTF8PROC_HANGUL_VCOUNT + hangul_vindex) * + UTF8PROC_HANGUL_TCOUNT; + starter_property = NULL; + continue; + } + } + hangul_sindex = *starter - UTF8PROC_HANGUL_SBASE; + if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT && + (hangul_sindex % UTF8PROC_HANGUL_TCOUNT) == 0) { + utf8proc_int32_t hangul_tindex; + hangul_tindex = current_char - UTF8PROC_HANGUL_TBASE; + if (hangul_tindex >= 0 && hangul_tindex < UTF8PROC_HANGUL_TCOUNT) { + *starter += hangul_tindex; + starter_property = NULL; + continue; + } + } + if (!starter_property) { + starter_property = unsafe_get_property(*starter); + } + if (starter_property->comb_index < 0x8000 && + current_property->comb_index != UINT16_MAX && + current_property->comb_index >= 0x8000) { + int sidx = starter_property->comb_index; + int idx = current_property->comb_index & 0x3FFF; + if (idx >= utf8proc_combinations[sidx] && idx <= utf8proc_combinations[sidx + 1] ) { + idx += sidx + 2 - utf8proc_combinations[sidx]; + if (current_property->comb_index & 0x4000) { + composition = (utf8proc_combinations[idx] << 16) | utf8proc_combinations[idx+1]; + } else + composition = utf8proc_combinations[idx]; + + if (composition > 0 && (!(options & UTF8PROC_STABLE) || + !(unsafe_get_property(composition)->comp_exclusion))) { + *starter = composition; + starter_property = NULL; + continue; + } + } + } + } + buffer[wpos] = current_char; + if (current_property->combining_class) { + if (current_property->combining_class > max_combining_class) { + max_combining_class = current_property->combining_class; + } + } else { + starter = buffer + wpos; + starter_property = NULL; + max_combining_class = -1; + } + wpos++; + } + length = wpos; + } + return length; } UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) { - /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored - ASSERT: 'buffer' has one spare byte of free space at the end! */ - length = utf8proc_normalize_utf32(buffer, length, options); - if (length < 0) return length; - { - utf8proc_ssize_t rpos, wpos = 0; - utf8proc_int32_t uc; - if (options & UTF8PROC_CHARBOUND) { - for (rpos = 0; rpos < length; rpos++) { - uc = buffer[rpos]; - wpos += charbound_encode_char(uc, ((utf8proc_uint8_t *)buffer) + wpos); - } - } else { - for (rpos = 0; rpos < length; rpos++) { - uc = buffer[rpos]; - wpos += utf8proc_encode_char(uc, ((utf8proc_uint8_t *)buffer) + wpos); - } - } - ((utf8proc_uint8_t *)buffer)[wpos] = 0; - return wpos; - } + /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored + ASSERT: 'buffer' has one spare byte of free space at the end! */ + length = utf8proc_normalize_utf32(buffer, length, options); + if (length < 0) return length; + { + utf8proc_ssize_t rpos, wpos = 0; + utf8proc_int32_t uc; + if (options & UTF8PROC_CHARBOUND) { + for (rpos = 0; rpos < length; rpos++) { + uc = buffer[rpos]; + wpos += charbound_encode_char(uc, ((utf8proc_uint8_t *)buffer) + wpos); + } + } else { + for (rpos = 0; rpos < length; rpos++) { + uc = buffer[rpos]; + wpos += utf8proc_encode_char(uc, ((utf8proc_uint8_t *)buffer) + wpos); + } + } + ((utf8proc_uint8_t *)buffer)[wpos] = 0; + return wpos; + } } UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map( - const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options ) { - return utf8proc_map_custom(str, strlen, dstptr, options, NULL, NULL); + return utf8proc_map_custom(str, strlen, dstptr, options, NULL, NULL); } UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom( - const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options, - utf8proc_custom_func custom_func, void *custom_data + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options, + utf8proc_custom_func custom_func, void *custom_data ) { - utf8proc_int32_t *buffer; - utf8proc_ssize_t result; - *dstptr = NULL; - result = utf8proc_decompose_custom(str, strlen, NULL, 0, options, custom_func, custom_data); - if (result < 0) return result; - buffer = (utf8proc_int32_t *) malloc(result * sizeof(utf8proc_int32_t) + 1); - if (!buffer) return UTF8PROC_ERROR_NOMEM; - result = utf8proc_decompose_custom(str, strlen, buffer, result, options, custom_func, custom_data); - if (result < 0) { - free(buffer); - return result; - } - result = utf8proc_reencode(buffer, result, options); - if (result < 0) { - free(buffer); - return result; - } - { - utf8proc_int32_t *newptr; - newptr = (utf8proc_int32_t *) realloc(buffer, (size_t)result+1); - if (newptr) buffer = newptr; - } - *dstptr = (utf8proc_uint8_t *)buffer; - return result; -} - -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str, utf8proc_ssize_t len) { - utf8proc_uint8_t *retval; - utf8proc_map(str, len, &retval, (utf8proc_option_t)(UTF8PROC_STABLE | - UTF8PROC_DECOMPOSE)); - return retval; -} - -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str, utf8proc_ssize_t len) { - utf8proc_uint8_t *retval; - utf8proc_map(str, len, &retval, (utf8proc_option_t)(UTF8PROC_STABLE | - UTF8PROC_COMPOSE)); - return retval; + utf8proc_int32_t *buffer; + utf8proc_ssize_t result; + *dstptr = NULL; + result = utf8proc_decompose_custom(str, strlen, NULL, 0, options, custom_func, custom_data); + if (result < 0) return result; + buffer = (utf8proc_int32_t *) malloc(((utf8proc_size_t)result) * sizeof(utf8proc_int32_t) + 1); + if (!buffer) return UTF8PROC_ERROR_NOMEM; + result = utf8proc_decompose_custom(str, strlen, buffer, result, options, custom_func, custom_data); + if (result < 0) { + free(buffer); + return result; + } + result = utf8proc_reencode(buffer, result, options); + if (result < 0) { + free(buffer); + return result; + } + { + utf8proc_int32_t *newptr; + newptr = (utf8proc_int32_t *) realloc(buffer, (size_t)result+1); + if (newptr) buffer = newptr; + } + *dstptr = (utf8proc_uint8_t *)buffer; + return result; +} + +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen) { + utf8proc_uint8_t *retval; + utf8proc_map(str, strlen, &retval, utf8proc_option_t(UTF8PROC_STABLE | + UTF8PROC_DECOMPOSE)); + return retval; +} + +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen) { + utf8proc_uint8_t *retval; + utf8proc_map(str, strlen, &retval, utf8proc_option_t(UTF8PROC_STABLE | + UTF8PROC_COMPOSE)); + return retval; +} + +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen) { + utf8proc_uint8_t *retval; + utf8proc_map(str, strlen, &retval, utf8proc_option_t(UTF8PROC_STABLE | + UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT)); + return retval; } UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_remove_accents(const utf8proc_uint8_t *str, utf8proc_ssize_t len) { @@ -852,25 +808,18 @@ UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_remove_accents(const utf8proc_uint return retval; } -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str, utf8proc_ssize_t len) { - utf8proc_uint8_t *retval; - utf8proc_map(str, len, &retval, (utf8proc_option_t)(UTF8PROC_STABLE | - UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT)); - return retval; +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen) { + utf8proc_uint8_t *retval; + utf8proc_map(str, strlen, &retval, utf8proc_option_t(UTF8PROC_STABLE | + UTF8PROC_COMPOSE | UTF8PROC_COMPAT)); + return retval; } -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str, utf8proc_ssize_t len) { - utf8proc_uint8_t *retval; - utf8proc_map(str, len, &retval, (utf8proc_option_t)(UTF8PROC_STABLE | - UTF8PROC_COMPOSE | UTF8PROC_COMPAT)); - return retval; -} - -UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC_Casefold(const utf8proc_uint8_t *str, utf8proc_ssize_t len) { - utf8proc_uint8_t *retval; - utf8proc_map(str, len, &retval, (utf8proc_option_t)(UTF8PROC_STABLE | - UTF8PROC_COMPOSE | UTF8PROC_COMPAT | UTF8PROC_CASEFOLD | UTF8PROC_IGNORE)); - return retval; +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC_Casefold(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen) { + utf8proc_uint8_t *retval; + utf8proc_map(str, strlen, &retval, utf8proc_option_t(UTF8PROC_STABLE | + UTF8PROC_COMPOSE | UTF8PROC_COMPAT | UTF8PROC_CASEFOLD | UTF8PROC_IGNORE)); + return retval; } } diff --git a/third_party/utf8proc/utf8proc_data.cpp b/third_party/utf8proc/utf8proc_data.cpp index 8b18c4be5fd..f2b0f5ce9b4 100644 --- a/third_party/utf8proc/utf8proc_data.cpp +++ b/third_party/utf8proc/utf8proc_data.cpp @@ -2,714 +2,922 @@ static const utf8proc_uint16_t utf8proc_sequences[] = { 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 32, 32, 776, 32, 772, - 50, 51, 32, 769, 956, 32, 807, 49, - 49, 8260, 52, 49, 8260, 50, 51, 8260, - 52, 65, 768, 224, 65, 769, 225, 65, - 770, 226, 65, 771, 227, 65, 776, 228, - 65, 778, 229, 230, 67, 807, 231, 69, - 768, 232, 69, 769, 233, 69, 770, 234, - 69, 776, 235, 73, 768, 236, 73, 769, - 237, 73, 770, 238, 73, 776, 239, 240, - 78, 771, 241, 79, 768, 242, 79, 769, - 243, 79, 770, 244, 79, 771, 245, 79, - 776, 246, 248, 85, 768, 249, 85, 769, - 250, 85, 770, 251, 85, 776, 252, 89, - 769, 253, 254, 115, 115, 97, 768, 97, - 769, 97, 770, 97, 771, 97, 776, 97, - 778, 99, 807, 101, 768, 101, 769, 101, - 770, 101, 776, 105, 768, 105, 769, 105, - 770, 105, 776, 110, 771, 111, 768, 111, - 769, 111, 770, 111, 771, 111, 776, 117, - 768, 117, 769, 117, 770, 117, 776, 121, - 769, 121, 776, 65, 772, 257, 97, 772, - 65, 774, 259, 97, 774, 65, 808, 261, - 97, 808, 67, 769, 263, 99, 769, 67, - 770, 265, 99, 770, 67, 775, 267, 99, - 775, 67, 780, 269, 99, 780, 68, 780, - 271, 100, 780, 273, 69, 772, 275, 101, - 772, 69, 774, 277, 101, 774, 69, 775, - 279, 101, 775, 69, 808, 281, 101, 808, - 69, 780, 283, 101, 780, 71, 770, 285, - 103, 770, 71, 774, 287, 103, 774, 71, - 775, 289, 103, 775, 71, 807, 291, 103, - 807, 72, 770, 293, 104, 770, 295, 73, - 771, 297, 105, 771, 73, 772, 299, 105, - 772, 73, 774, 301, 105, 774, 73, 808, - 303, 105, 808, 73, 775, 105, 775, 73, - 74, 307, 105, 106, 74, 770, 309, 106, - 770, 75, 807, 311, 107, 807, 76, 769, - 314, 108, 769, 76, 807, 316, 108, 807, - 76, 780, 318, 108, 780, 76, 183, 320, - 108, 183, 322, 78, 769, 324, 110, 769, - 78, 807, 326, 110, 807, 78, 780, 328, - 110, 780, 700, 110, 331, 79, 772, 333, - 111, 772, 79, 774, 335, 111, 774, 79, - 779, 337, 111, 779, 339, 82, 769, 341, - 114, 769, 82, 807, 343, 114, 807, 82, - 780, 345, 114, 780, 83, 769, 347, 115, - 769, 83, 770, 349, 115, 770, 83, 807, - 351, 115, 807, 83, 780, 353, 115, 780, - 84, 807, 355, 116, 807, 84, 780, 357, - 116, 780, 359, 85, 771, 361, 117, 771, - 85, 772, 363, 117, 772, 85, 774, 365, - 117, 774, 85, 778, 367, 117, 778, 85, - 779, 369, 117, 779, 85, 808, 371, 117, - 808, 87, 770, 373, 119, 770, 89, 770, - 375, 121, 770, 89, 776, 255, 90, 769, - 378, 122, 769, 90, 775, 380, 122, 775, - 90, 780, 382, 122, 780, 595, 387, 389, - 596, 392, 598, 599, 396, 477, 601, 603, - 402, 608, 611, 617, 616, 409, 623, 626, - 629, 79, 795, 417, 111, 795, 419, 421, - 640, 424, 643, 429, 648, 85, 795, 432, - 117, 795, 650, 651, 436, 438, 658, 441, - 445, 68, 381, 454, 68, 382, 100, 382, - 76, 74, 457, 76, 106, 108, 106, 78, - 74, 460, 78, 106, 110, 106, 65, 780, - 462, 97, 780, 73, 780, 464, 105, 780, - 79, 780, 466, 111, 780, 85, 780, 468, - 117, 780, 220, 772, 470, 252, 772, 220, - 769, 472, 252, 769, 220, 780, 474, 252, - 780, 220, 768, 476, 252, 768, 196, 772, - 479, 228, 772, 550, 772, 481, 551, 772, - 198, 772, 483, 230, 772, 485, 71, 780, - 487, 103, 780, 75, 780, 489, 107, 780, - 79, 808, 491, 111, 808, 490, 772, 493, - 491, 772, 439, 780, 495, 658, 780, 106, - 780, 68, 90, 499, 68, 122, 100, 122, - 71, 769, 501, 103, 769, 405, 447, 78, - 768, 505, 110, 768, 197, 769, 507, 229, - 769, 198, 769, 509, 230, 769, 216, 769, - 511, 248, 769, 65, 783, 513, 97, 783, - 65, 785, 515, 97, 785, 69, 783, 517, - 101, 783, 69, 785, 519, 101, 785, 73, - 783, 521, 105, 783, 73, 785, 523, 105, - 785, 79, 783, 525, 111, 783, 79, 785, - 527, 111, 785, 82, 783, 529, 114, 783, - 82, 785, 531, 114, 785, 85, 783, 533, - 117, 783, 85, 785, 535, 117, 785, 83, - 806, 537, 115, 806, 84, 806, 539, 116, - 806, 541, 72, 780, 543, 104, 780, 414, - 547, 549, 65, 775, 551, 97, 775, 69, - 807, 553, 101, 807, 214, 772, 555, 246, - 772, 213, 772, 557, 245, 772, 79, 775, - 559, 111, 775, 558, 772, 561, 559, 772, - 89, 772, 563, 121, 772, 11365, 572, 410, - 11366, 578, 384, 649, 652, 583, 585, 587, - 589, 591, 614, 633, 635, 641, 32, 774, - 32, 775, 32, 778, 32, 808, 32, 771, - 32, 779, 661, 768, 769, 787, 776, 769, - 953, 881, 883, 697, 887, 32, 837, 59, - 1011, 168, 769, 913, 769, 940, 183, 917, - 769, 941, 919, 769, 942, 921, 769, 943, - 927, 769, 972, 933, 769, 973, 937, 769, - 974, 970, 769, 953, 776, 769, 945, 946, - 947, 948, 949, 950, 951, 952, 954, 955, - 957, 958, 959, 960, 961, 963, 964, 965, - 966, 967, 968, 969, 921, 776, 970, 933, - 776, 971, 945, 769, 949, 769, 951, 769, - 953, 769, 971, 769, 965, 776, 769, 953, - 776, 965, 776, 959, 769, 965, 769, 969, - 769, 983, 933, 978, 769, 978, 776, 985, - 987, 989, 991, 993, 995, 997, 999, 1001, - 1003, 1005, 1007, 962, 920, 1016, 931, 1010, - 1019, 891, 892, 893, 1045, 768, 1104, 1045, - 776, 1105, 1106, 1043, 769, 1107, 1108, 1109, - 1110, 1030, 776, 1111, 1112, 1113, 1114, 1115, - 1050, 769, 1116, 1048, 768, 1117, 1059, 774, - 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077, - 1078, 1079, 1080, 1048, 774, 1081, 1082, 1083, - 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, - 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, - 1100, 1101, 1102, 1103, 1080, 774, 1077, 768, - 1077, 776, 1075, 769, 1110, 776, 1082, 769, - 1080, 768, 1091, 774, 1121, 1123, 1125, 1127, - 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1140, - 783, 1143, 1141, 783, 1145, 1147, 1149, 1151, - 1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, - 1177, 1179, 1181, 1183, 1185, 1187, 1189, 1191, - 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, - 1209, 1211, 1213, 1215, 1231, 1046, 774, 1218, - 1078, 774, 1220, 1222, 1224, 1226, 1228, 1230, - 1040, 774, 1233, 1072, 774, 1040, 776, 1235, - 1072, 776, 1237, 1045, 774, 1239, 1077, 774, - 1241, 1240, 776, 1243, 1241, 776, 1046, 776, - 1245, 1078, 776, 1047, 776, 1247, 1079, 776, - 1249, 1048, 772, 1251, 1080, 772, 1048, 776, - 1253, 1080, 776, 1054, 776, 1255, 1086, 776, - 1257, 1256, 776, 1259, 1257, 776, 1069, 776, - 1261, 1101, 776, 1059, 772, 1263, 1091, 772, - 1059, 776, 1265, 1091, 776, 1059, 779, 1267, - 1091, 779, 1063, 776, 1269, 1095, 776, 1271, - 1067, 776, 1273, 1099, 776, 1275, 1277, 1279, - 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, - 1297, 1299, 1301, 1303, 1305, 1307, 1309, 1311, - 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327, - 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, - 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, - 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, - 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, - 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, - 1575, 1619, 1575, 1620, 1608, 1620, 1575, 1621, - 1610, 1620, 1575, 1652, 1608, 1652, 1735, 1652, - 1610, 1652, 1749, 1620, 1729, 1620, 1746, 1620, - 2344, 2364, 2352, 2364, 2355, 2364, 2325, 2364, - 2326, 2364, 2327, 2364, 2332, 2364, 2337, 2364, - 2338, 2364, 2347, 2364, 2351, 2364, 2503, 2494, - 2503, 2519, 2465, 2492, 2466, 2492, 2479, 2492, - 2610, 2620, 2616, 2620, 2582, 2620, 2583, 2620, - 2588, 2620, 2603, 2620, 2887, 2902, 2887, 2878, - 2887, 2903, 2849, 2876, 2850, 2876, 2962, 3031, - 3014, 3006, 3015, 3006, 3014, 3031, 3142, 3158, - 3263, 3285, 3270, 3285, 3270, 3286, 3270, 3266, - 3274, 3285, 3398, 3390, 3399, 3390, 3398, 3415, - 3545, 3530, 3545, 3535, 3548, 3530, 3545, 3551, - 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, - 3851, 3906, 4023, 3916, 4023, 3921, 4023, 3926, - 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, - 3956, 4018, 3968, 4018, 3969, 4019, 3968, 4019, - 3969, 3953, 3968, 3986, 4023, 3996, 4023, 4001, - 4023, 4006, 4023, 4011, 4023, 3984, 4021, 4133, - 4142, 11520, 11521, 11522, 11523, 11524, 11525, 11526, - 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, - 11535, 11536, 11537, 11538, 11539, 11540, 11541, 11542, - 11543, 11544, 11545, 11546, 11547, 11548, 11549, 11550, - 11551, 11552, 11553, 11554, 11555, 11556, 11557, 11559, - 11565, 4316, 5104, 5105, 5106, 5107, 5108, 5109, - 6917, 6965, 6919, 6965, 6921, 6965, 6923, 6965, - 6925, 6965, 6929, 6965, 6970, 6965, 6972, 6965, - 6974, 6965, 6975, 6965, 6978, 6965, 42571, 4304, - 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, - 4313, 4314, 4315, 4317, 4318, 4319, 4320, 4321, - 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, - 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, - 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, - 4346, 4349, 4350, 4351, 65, 198, 66, 68, - 69, 398, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 546, 80, 82, 84, 85, - 87, 592, 593, 7426, 604, 7446, 7447, 7453, - 7461, 594, 597, 607, 609, 613, 618, 7547, - 669, 621, 7557, 671, 625, 624, 627, 628, - 632, 642, 427, 7452, 656, 657, 65, 805, - 7681, 97, 805, 66, 775, 7683, 98, 775, - 66, 803, 7685, 98, 803, 66, 817, 7687, - 98, 817, 199, 769, 7689, 231, 769, 68, - 775, 7691, 100, 775, 68, 803, 7693, 100, - 803, 68, 817, 7695, 100, 817, 68, 807, - 7697, 100, 807, 68, 813, 7699, 100, 813, - 274, 768, 7701, 275, 768, 274, 769, 7703, - 275, 769, 69, 813, 7705, 101, 813, 69, - 816, 7707, 101, 816, 552, 774, 7709, 553, - 774, 70, 775, 7711, 102, 775, 71, 772, - 7713, 103, 772, 72, 775, 7715, 104, 775, - 72, 803, 7717, 104, 803, 72, 776, 7719, - 104, 776, 72, 807, 7721, 104, 807, 72, - 814, 7723, 104, 814, 73, 816, 7725, 105, - 816, 207, 769, 7727, 239, 769, 75, 769, - 7729, 107, 769, 75, 803, 7731, 107, 803, - 75, 817, 7733, 107, 817, 76, 803, 7735, - 108, 803, 7734, 772, 7737, 7735, 772, 76, - 817, 7739, 108, 817, 76, 813, 7741, 108, - 813, 77, 769, 7743, 109, 769, 77, 775, - 7745, 109, 775, 77, 803, 7747, 109, 803, - 78, 775, 7749, 110, 775, 78, 803, 7751, - 110, 803, 78, 817, 7753, 110, 817, 78, - 813, 7755, 110, 813, 213, 769, 7757, 245, - 769, 213, 776, 7759, 245, 776, 332, 768, - 7761, 333, 768, 332, 769, 7763, 333, 769, - 80, 769, 7765, 112, 769, 80, 775, 7767, - 112, 775, 82, 775, 7769, 114, 775, 82, - 803, 7771, 114, 803, 7770, 772, 7773, 7771, - 772, 82, 817, 7775, 114, 817, 83, 775, - 7777, 115, 775, 83, 803, 7779, 115, 803, - 346, 775, 7781, 347, 775, 352, 775, 7783, - 353, 775, 7778, 775, 7785, 7779, 775, 84, - 775, 7787, 116, 775, 84, 803, 7789, 116, - 803, 84, 817, 7791, 116, 817, 84, 813, - 7793, 116, 813, 85, 804, 7795, 117, 804, - 85, 816, 7797, 117, 816, 85, 813, 7799, - 117, 813, 360, 769, 7801, 361, 769, 362, - 776, 7803, 363, 776, 86, 771, 7805, 118, - 771, 86, 803, 7807, 118, 803, 87, 768, - 7809, 119, 768, 87, 769, 7811, 119, 769, - 87, 776, 7813, 119, 776, 87, 775, 7815, - 119, 775, 87, 803, 7817, 119, 803, 88, - 775, 7819, 120, 775, 88, 776, 7821, 120, - 776, 89, 775, 7823, 121, 775, 90, 770, - 7825, 122, 770, 90, 803, 7827, 122, 803, - 90, 817, 7829, 122, 817, 104, 817, 116, - 776, 119, 778, 121, 778, 97, 702, 383, - 775, 65, 803, 7841, 97, 803, 65, 777, - 7843, 97, 777, 194, 769, 7845, 226, 769, - 194, 768, 7847, 226, 768, 194, 777, 7849, - 226, 777, 194, 771, 7851, 226, 771, 7840, - 770, 7853, 7841, 770, 258, 769, 7855, 259, - 769, 258, 768, 7857, 259, 768, 258, 777, - 7859, 259, 777, 258, 771, 7861, 259, 771, - 7840, 774, 7863, 7841, 774, 69, 803, 7865, - 101, 803, 69, 777, 7867, 101, 777, 69, - 771, 7869, 101, 771, 202, 769, 7871, 234, - 769, 202, 768, 7873, 234, 768, 202, 777, - 7875, 234, 777, 202, 771, 7877, 234, 771, - 7864, 770, 7879, 7865, 770, 73, 777, 7881, - 105, 777, 73, 803, 7883, 105, 803, 79, - 803, 7885, 111, 803, 79, 777, 7887, 111, - 777, 212, 769, 7889, 244, 769, 212, 768, - 7891, 244, 768, 212, 777, 7893, 244, 777, - 212, 771, 7895, 244, 771, 7884, 770, 7897, - 7885, 770, 416, 769, 7899, 417, 769, 416, - 768, 7901, 417, 768, 416, 777, 7903, 417, - 777, 416, 771, 7905, 417, 771, 416, 803, - 7907, 417, 803, 85, 803, 7909, 117, 803, - 85, 777, 7911, 117, 777, 431, 769, 7913, - 432, 769, 431, 768, 7915, 432, 768, 431, - 777, 7917, 432, 777, 431, 771, 7919, 432, - 771, 431, 803, 7921, 432, 803, 89, 768, - 7923, 121, 768, 89, 803, 7925, 121, 803, - 89, 777, 7927, 121, 777, 89, 771, 7929, - 121, 771, 7931, 7933, 7935, 945, 787, 945, - 788, 7936, 768, 7937, 768, 7936, 769, 7937, - 769, 7936, 834, 7937, 834, 913, 787, 7936, - 913, 788, 7937, 7944, 768, 7938, 7945, 768, - 7939, 7944, 769, 7940, 7945, 769, 7941, 7944, - 834, 7942, 7945, 834, 7943, 949, 787, 949, - 788, 7952, 768, 7953, 768, 7952, 769, 7953, - 769, 917, 787, 7952, 917, 788, 7953, 7960, - 768, 7954, 7961, 768, 7955, 7960, 769, 7956, - 7961, 769, 7957, 951, 787, 951, 788, 7968, - 768, 7969, 768, 7968, 769, 7969, 769, 7968, - 834, 7969, 834, 919, 787, 7968, 919, 788, - 7969, 7976, 768, 7970, 7977, 768, 7971, 7976, - 769, 7972, 7977, 769, 7973, 7976, 834, 7974, - 7977, 834, 7975, 953, 787, 953, 788, 7984, - 768, 7985, 768, 7984, 769, 7985, 769, 7984, - 834, 7985, 834, 921, 787, 7984, 921, 788, - 7985, 7992, 768, 7986, 7993, 768, 7987, 7992, - 769, 7988, 7993, 769, 7989, 7992, 834, 7990, - 7993, 834, 7991, 959, 787, 959, 788, 8000, - 768, 8001, 768, 8000, 769, 8001, 769, 927, - 787, 8000, 927, 788, 8001, 8008, 768, 8002, - 8009, 768, 8003, 8008, 769, 8004, 8009, 769, - 8005, 965, 787, 965, 788, 8016, 768, 965, - 787, 768, 8017, 768, 8016, 769, 965, 787, - 769, 8017, 769, 8016, 834, 965, 787, 834, - 8017, 834, 933, 788, 8017, 8025, 768, 8019, - 8025, 769, 8021, 8025, 834, 8023, 969, 787, - 969, 788, 8032, 768, 8033, 768, 8032, 769, - 8033, 769, 8032, 834, 8033, 834, 937, 787, - 8032, 937, 788, 8033, 8040, 768, 8034, 8041, - 768, 8035, 8040, 769, 8036, 8041, 769, 8037, - 8040, 834, 8038, 8041, 834, 8039, 945, 768, - 949, 768, 951, 768, 953, 768, 959, 768, - 965, 768, 969, 768, 7936, 837, 7936, 953, - 7937, 837, 7937, 953, 7938, 837, 7938, 953, - 7939, 837, 7939, 953, 7940, 837, 7940, 953, - 7941, 837, 7941, 953, 7942, 837, 7942, 953, - 7943, 837, 7943, 953, 7944, 837, 7945, 837, - 7946, 837, 7947, 837, 7948, 837, 7949, 837, - 7950, 837, 7951, 837, 7968, 837, 7968, 953, - 7969, 837, 7969, 953, 7970, 837, 7970, 953, - 7971, 837, 7971, 953, 7972, 837, 7972, 953, - 7973, 837, 7973, 953, 7974, 837, 7974, 953, - 7975, 837, 7975, 953, 7976, 837, 7977, 837, - 7978, 837, 7979, 837, 7980, 837, 7981, 837, - 7982, 837, 7983, 837, 8032, 837, 8032, 953, - 8033, 837, 8033, 953, 8034, 837, 8034, 953, - 8035, 837, 8035, 953, 8036, 837, 8036, 953, - 8037, 837, 8037, 953, 8038, 837, 8038, 953, - 8039, 837, 8039, 953, 8040, 837, 8041, 837, - 8042, 837, 8043, 837, 8044, 837, 8045, 837, - 8046, 837, 8047, 837, 945, 774, 945, 772, - 8048, 837, 8048, 953, 945, 837, 945, 953, - 940, 837, 940, 953, 945, 834, 8118, 837, - 945, 834, 953, 913, 774, 8112, 913, 772, - 8113, 913, 768, 8048, 902, 8049, 913, 837, - 32, 787, 32, 834, 168, 834, 8052, 837, - 8052, 953, 951, 837, 951, 953, 942, 837, - 942, 953, 951, 834, 8134, 837, 951, 834, - 953, 917, 768, 8050, 904, 8051, 919, 768, - 8052, 905, 8053, 919, 837, 8127, 768, 8127, - 769, 8127, 834, 953, 774, 953, 772, 970, - 768, 953, 776, 768, 912, 953, 834, 970, - 834, 953, 776, 834, 921, 774, 8144, 921, - 772, 8145, 921, 768, 8054, 906, 8055, 8190, - 768, 8190, 769, 8190, 834, 965, 774, 965, - 772, 971, 768, 965, 776, 768, 944, 961, - 787, 961, 788, 965, 834, 971, 834, 965, - 776, 834, 933, 774, 8160, 933, 772, 8161, - 933, 768, 8058, 910, 8059, 929, 788, 8165, - 168, 768, 901, 96, 8060, 837, 8060, 953, - 969, 837, 969, 953, 974, 837, 974, 953, - 969, 834, 8182, 837, 969, 834, 953, 927, - 768, 8056, 908, 8057, 937, 768, 8060, 911, - 8061, 937, 837, 180, 32, 788, 8194, 8195, + 120, 121, 122, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, 88, 89, 90, 32, 32, 776, + 170, 32, 772, 50, 51, 32, 769, 956, + 924, 32, 807, 49, 186, 49, 8260, 52, + 49, 8260, 50, 51, 8260, 52, 65, 768, + 224, 65, 769, 225, 65, 770, 226, 65, + 771, 227, 65, 776, 228, 65, 778, 229, + 230, 67, 807, 231, 69, 768, 232, 69, + 769, 233, 69, 770, 234, 69, 776, 235, + 73, 768, 236, 73, 769, 237, 73, 770, + 238, 73, 776, 239, 240, 78, 771, 241, + 79, 768, 242, 79, 769, 243, 79, 770, + 244, 79, 771, 245, 79, 776, 246, 248, + 85, 768, 249, 85, 769, 250, 85, 770, + 251, 85, 776, 252, 89, 769, 253, 254, + 115, 115, 7838, 97, 768, 192, 97, 769, + 193, 97, 770, 194, 97, 771, 195, 97, + 776, 196, 97, 778, 197, 198, 99, 807, + 199, 101, 768, 200, 101, 769, 201, 101, + 770, 202, 101, 776, 203, 105, 768, 204, + 105, 769, 205, 105, 770, 206, 105, 776, + 207, 208, 110, 771, 209, 111, 768, 210, + 111, 769, 211, 111, 770, 212, 111, 771, + 213, 111, 776, 214, 216, 117, 768, 217, + 117, 769, 218, 117, 770, 219, 117, 776, + 220, 121, 769, 221, 222, 121, 776, 376, + 65, 772, 257, 97, 772, 256, 65, 774, + 259, 97, 774, 258, 65, 808, 261, 97, + 808, 260, 67, 769, 263, 99, 769, 262, + 67, 770, 265, 99, 770, 264, 67, 775, + 267, 99, 775, 266, 67, 780, 269, 99, + 780, 268, 68, 780, 271, 100, 780, 270, + 273, 272, 69, 772, 275, 101, 772, 274, + 69, 774, 277, 101, 774, 276, 69, 775, + 279, 101, 775, 278, 69, 808, 281, 101, + 808, 280, 69, 780, 283, 101, 780, 282, + 71, 770, 285, 103, 770, 284, 71, 774, + 287, 103, 774, 286, 71, 775, 289, 103, + 775, 288, 71, 807, 291, 103, 807, 290, + 72, 770, 293, 104, 770, 292, 295, 294, + 73, 771, 297, 105, 771, 296, 73, 772, + 299, 105, 772, 298, 73, 774, 301, 105, + 774, 300, 73, 808, 303, 105, 808, 302, + 73, 775, 105, 775, 73, 74, 307, 105, + 106, 306, 74, 770, 309, 106, 770, 308, + 75, 807, 311, 107, 807, 310, 312, 76, + 769, 314, 108, 769, 313, 76, 807, 316, + 108, 807, 315, 76, 780, 318, 108, 780, + 317, 76, 183, 320, 108, 183, 319, 322, + 321, 78, 769, 324, 110, 769, 323, 78, + 807, 326, 110, 807, 325, 78, 780, 328, + 110, 780, 327, 700, 110, 329, 331, 330, + 79, 772, 333, 111, 772, 332, 79, 774, + 335, 111, 774, 334, 79, 779, 337, 111, + 779, 336, 339, 338, 82, 769, 341, 114, + 769, 340, 82, 807, 343, 114, 807, 342, + 82, 780, 345, 114, 780, 344, 83, 769, + 347, 115, 769, 346, 83, 770, 349, 115, + 770, 348, 83, 807, 351, 115, 807, 350, + 83, 780, 353, 115, 780, 352, 84, 807, + 355, 116, 807, 354, 84, 780, 357, 116, + 780, 356, 359, 358, 85, 771, 361, 117, + 771, 360, 85, 772, 363, 117, 772, 362, + 85, 774, 365, 117, 774, 364, 85, 778, + 367, 117, 778, 366, 85, 779, 369, 117, + 779, 368, 85, 808, 371, 117, 808, 370, + 87, 770, 373, 119, 770, 372, 89, 770, + 375, 121, 770, 374, 89, 776, 255, 90, + 769, 378, 122, 769, 377, 90, 775, 380, + 122, 775, 379, 90, 780, 382, 122, 780, + 381, 579, 595, 387, 386, 389, 388, 596, + 392, 391, 598, 599, 396, 395, 397, 477, + 601, 603, 402, 401, 608, 611, 502, 617, + 616, 409, 408, 573, 411, 623, 626, 544, + 629, 79, 795, 417, 111, 795, 416, 419, + 418, 421, 420, 640, 424, 423, 643, 426, + 427, 429, 428, 648, 85, 795, 432, 117, + 795, 431, 650, 651, 436, 435, 438, 437, + 658, 441, 440, 442, 445, 444, 446, 503, + 68, 381, 454, 453, 68, 382, 452, 100, + 382, 76, 74, 457, 456, 76, 106, 455, + 108, 106, 78, 74, 460, 459, 78, 106, + 458, 110, 106, 65, 780, 462, 97, 780, + 461, 73, 780, 464, 105, 780, 463, 79, + 780, 466, 111, 780, 465, 85, 780, 468, + 117, 780, 467, 220, 772, 470, 252, 772, + 469, 220, 769, 472, 252, 769, 471, 220, + 780, 474, 252, 780, 473, 220, 768, 476, + 252, 768, 475, 398, 196, 772, 479, 228, + 772, 478, 550, 772, 481, 551, 772, 480, + 198, 772, 483, 230, 772, 482, 485, 484, + 71, 780, 487, 103, 780, 486, 75, 780, + 489, 107, 780, 488, 79, 808, 491, 111, + 808, 490, 490, 772, 493, 491, 772, 492, + 439, 780, 495, 658, 780, 494, 106, 780, + 496, 68, 90, 499, 498, 68, 122, 497, + 100, 122, 71, 769, 501, 103, 769, 500, + 405, 447, 78, 768, 505, 110, 768, 504, + 197, 769, 507, 229, 769, 506, 198, 769, + 509, 230, 769, 508, 216, 769, 511, 248, + 769, 510, 65, 783, 513, 97, 783, 512, + 65, 785, 515, 97, 785, 514, 69, 783, + 517, 101, 783, 516, 69, 785, 519, 101, + 785, 518, 73, 783, 521, 105, 783, 520, + 73, 785, 523, 105, 785, 522, 79, 783, + 525, 111, 783, 524, 79, 785, 527, 111, + 785, 526, 82, 783, 529, 114, 783, 528, + 82, 785, 531, 114, 785, 530, 85, 783, + 533, 117, 783, 532, 85, 785, 535, 117, + 785, 534, 83, 806, 537, 115, 806, 536, + 84, 806, 539, 116, 806, 538, 541, 540, + 72, 780, 543, 104, 780, 542, 414, 545, + 547, 546, 549, 548, 65, 775, 551, 97, + 775, 550, 69, 807, 553, 101, 807, 552, + 214, 772, 555, 246, 772, 554, 213, 772, + 557, 245, 772, 556, 79, 775, 559, 111, + 775, 558, 558, 772, 561, 559, 772, 560, + 89, 772, 563, 121, 772, 562, 564, 565, + 566, 567, 568, 569, 11365, 572, 571, 410, + 11366, 11390, 11391, 578, 577, 384, 649, 652, + 583, 582, 585, 584, 587, 586, 589, 588, + 591, 590, 11375, 11373, 11376, 385, 390, 597, + 393, 394, 600, 399, 602, 400, 42923, 605, + 606, 607, 403, 42924, 610, 404, 612, 42893, + 42922, 615, 407, 406, 42926, 11362, 42925, 621, + 622, 412, 624, 11374, 413, 627, 628, 415, + 630, 631, 632, 633, 634, 635, 636, 11364, + 638, 639, 422, 641, 42949, 425, 644, 645, + 646, 42929, 430, 580, 433, 434, 581, 653, + 654, 655, 656, 657, 439, 659, 661, 662, + 663, 664, 665, 666, 667, 668, 42930, 42928, + 671, 672, 673, 674, 675, 676, 677, 678, + 679, 680, 681, 682, 683, 684, 685, 686, + 687, 688, 614, 689, 690, 691, 692, 693, + 694, 695, 696, 704, 705, 32, 774, 32, + 775, 32, 778, 32, 808, 32, 771, 32, + 779, 736, 737, 738, 739, 740, 768, 769, + 787, 776, 769, 953, 921, 881, 880, 883, + 882, 697, 887, 886, 32, 837, 890, 1021, + 1022, 1023, 59, 1011, 168, 769, 913, 769, + 940, 183, 917, 769, 941, 919, 769, 942, + 921, 769, 943, 927, 769, 972, 933, 769, + 973, 937, 769, 974, 970, 769, 953, 776, + 769, 912, 945, 946, 947, 948, 949, 950, + 951, 952, 954, 955, 957, 958, 959, 960, + 961, 963, 964, 965, 966, 967, 968, 969, + 921, 776, 970, 933, 776, 971, 945, 769, + 902, 949, 769, 904, 951, 769, 905, 953, + 769, 906, 971, 769, 965, 776, 769, 944, + 913, 914, 915, 916, 917, 918, 919, 920, + 922, 923, 925, 926, 927, 928, 929, 931, + 932, 933, 934, 935, 936, 937, 953, 776, + 938, 965, 776, 939, 959, 769, 908, 965, + 769, 910, 969, 769, 911, 983, 978, 978, + 769, 979, 978, 776, 980, 975, 985, 984, + 987, 986, 989, 988, 991, 990, 993, 992, + 995, 994, 997, 996, 999, 998, 1001, 1000, + 1003, 1002, 1005, 1004, 1007, 1006, 962, 1017, + 895, 1016, 1015, 1010, 1019, 1018, 1020, 891, + 892, 893, 1045, 768, 1104, 1045, 776, 1105, + 1106, 1043, 769, 1107, 1108, 1109, 1110, 1030, + 776, 1111, 1112, 1113, 1114, 1115, 1050, 769, + 1116, 1048, 768, 1117, 1059, 774, 1118, 1119, + 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, + 1080, 1048, 774, 1081, 1082, 1083, 1084, 1085, + 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, + 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, + 1102, 1103, 1040, 1041, 1042, 1043, 1044, 1045, + 1046, 1047, 1048, 1080, 774, 1049, 1050, 1051, + 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, + 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, + 1068, 1069, 1070, 1071, 1077, 768, 1024, 1077, + 776, 1025, 1026, 1075, 769, 1027, 1028, 1029, + 1030, 1110, 776, 1031, 1032, 1033, 1034, 1035, + 1082, 769, 1036, 1080, 768, 1037, 1091, 774, + 1038, 1039, 1121, 1120, 1123, 1122, 1125, 1124, + 1127, 1126, 1129, 1128, 1131, 1130, 1133, 1132, + 1135, 1134, 1137, 1136, 1139, 1138, 1141, 1140, + 1140, 783, 1143, 1141, 783, 1142, 1145, 1144, + 1147, 1146, 1149, 1148, 1151, 1150, 1153, 1152, + 1163, 1162, 1165, 1164, 1167, 1166, 1169, 1168, + 1171, 1170, 1173, 1172, 1175, 1174, 1177, 1176, + 1179, 1178, 1181, 1180, 1183, 1182, 1185, 1184, + 1187, 1186, 1189, 1188, 1191, 1190, 1193, 1192, + 1195, 1194, 1197, 1196, 1199, 1198, 1201, 1200, + 1203, 1202, 1205, 1204, 1207, 1206, 1209, 1208, + 1211, 1210, 1213, 1212, 1215, 1214, 1231, 1046, + 774, 1218, 1078, 774, 1217, 1220, 1219, 1222, + 1221, 1224, 1223, 1226, 1225, 1228, 1227, 1230, + 1229, 1216, 1040, 774, 1233, 1072, 774, 1232, + 1040, 776, 1235, 1072, 776, 1234, 1237, 1236, + 1045, 774, 1239, 1077, 774, 1238, 1241, 1240, + 1240, 776, 1243, 1241, 776, 1242, 1046, 776, + 1245, 1078, 776, 1244, 1047, 776, 1247, 1079, + 776, 1246, 1249, 1248, 1048, 772, 1251, 1080, + 772, 1250, 1048, 776, 1253, 1080, 776, 1252, + 1054, 776, 1255, 1086, 776, 1254, 1257, 1256, + 1256, 776, 1259, 1257, 776, 1258, 1069, 776, + 1261, 1101, 776, 1260, 1059, 772, 1263, 1091, + 772, 1262, 1059, 776, 1265, 1091, 776, 1264, + 1059, 779, 1267, 1091, 779, 1266, 1063, 776, + 1269, 1095, 776, 1268, 1271, 1270, 1067, 776, + 1273, 1099, 776, 1272, 1275, 1274, 1277, 1276, + 1279, 1278, 1281, 1280, 1283, 1282, 1285, 1284, + 1287, 1286, 1289, 1288, 1291, 1290, 1293, 1292, + 1295, 1294, 1297, 1296, 1299, 1298, 1301, 1300, + 1303, 1302, 1305, 1304, 1307, 1306, 1309, 1308, + 1311, 1310, 1313, 1312, 1315, 1314, 1317, 1316, + 1319, 1318, 1321, 1320, 1323, 1322, 1325, 1324, + 1327, 1326, 1377, 1378, 1379, 1380, 1381, 1382, + 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, + 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, + 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, + 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, + 1376, 1329, 1330, 1331, 1332, 1333, 1334, 1335, + 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, + 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, + 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, + 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1381, + 1410, 1415, 1416, 1575, 1619, 1575, 1620, 1608, + 1620, 1575, 1621, 1610, 1620, 1575, 1652, 1608, + 1652, 1735, 1652, 1610, 1652, 1749, 1620, 1729, + 1620, 1746, 1620, 2344, 2364, 2352, 2364, 2355, + 2364, 2325, 2364, 2326, 2364, 2327, 2364, 2332, + 2364, 2337, 2364, 2338, 2364, 2347, 2364, 2351, + 2364, 2503, 2494, 2503, 2519, 2465, 2492, 2466, + 2492, 2479, 2492, 2610, 2620, 2616, 2620, 2582, + 2620, 2583, 2620, 2588, 2620, 2603, 2620, 2887, + 2902, 2887, 2878, 2887, 2903, 2849, 2876, 2850, + 2876, 2962, 3031, 3014, 3006, 3015, 3006, 3014, + 3031, 3142, 3158, 3263, 3285, 3270, 3285, 3270, + 3286, 3270, 3266, 3274, 3285, 3398, 3390, 3399, + 3390, 3398, 3415, 3545, 3530, 3545, 3535, 3548, + 3530, 3545, 3551, 3661, 3634, 3789, 3762, 3755, + 3737, 3755, 3745, 3851, 3906, 4023, 3916, 4023, + 3921, 4023, 3926, 4023, 3931, 4023, 3904, 4021, + 3953, 3954, 3953, 3956, 4018, 3968, 4018, 3969, + 4019, 3968, 4019, 3969, 3953, 3968, 3986, 4023, + 3996, 4023, 4001, 4023, 4006, 4023, 4011, 4023, + 3984, 4021, 4133, 4142, 11520, 11521, 11522, 11523, + 11524, 11525, 11526, 11527, 11528, 11529, 11530, 11531, + 11532, 11533, 11534, 11535, 11536, 11537, 11538, 11539, + 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, + 11548, 11549, 11550, 11551, 11552, 11553, 11554, 11555, + 11556, 11557, 11559, 11565, 7312, 4304, 7313, 4305, + 7314, 4306, 7315, 4307, 7316, 4308, 7317, 4309, + 7318, 4310, 7319, 4311, 7320, 4312, 7321, 4313, + 7322, 4314, 7323, 4315, 7324, 4316, 7325, 4317, + 7326, 4318, 7327, 4319, 7328, 4320, 7329, 4321, + 7330, 4322, 7331, 4323, 7332, 4324, 7333, 4325, + 7334, 4326, 7335, 4327, 7336, 4328, 7337, 4329, + 7338, 4330, 7339, 4331, 7340, 4332, 7341, 4333, + 7342, 4334, 7343, 4335, 7344, 4336, 7345, 4337, + 7346, 4338, 7347, 4339, 7348, 4340, 7349, 4341, + 7350, 4342, 7351, 4343, 7352, 4344, 7353, 4345, + 7354, 4346, 4348, 7357, 4349, 7358, 4350, 7359, + 4351, 43888, 43889, 43890, 43891, 43892, 43893, 43894, + 43895, 43896, 43897, 43898, 43899, 43900, 43901, 43902, + 43903, 43904, 43905, 43906, 43907, 43908, 43909, 43910, + 43911, 43912, 43913, 43914, 43915, 43916, 43917, 43918, + 43919, 43920, 43921, 43922, 43923, 43924, 43925, 43926, + 43927, 43928, 43929, 43930, 43931, 43932, 43933, 43934, + 43935, 43936, 43937, 43938, 43939, 43940, 43941, 43942, + 43943, 43944, 43945, 43946, 43947, 43948, 43949, 43950, + 43951, 43952, 43953, 43954, 43955, 43956, 43957, 43958, + 43959, 43960, 43961, 43962, 43963, 43964, 43965, 43966, + 43967, 5112, 5113, 5114, 5115, 5116, 5117, 5104, + 5105, 5106, 5107, 5108, 5109, 6917, 6965, 6919, + 6965, 6921, 6965, 6923, 6965, 6925, 6965, 6929, + 6965, 6970, 6965, 6972, 6965, 6974, 6965, 6975, + 6965, 6978, 6965, 42571, 42570, 7424, 7425, 7426, + 7427, 7428, 7429, 7430, 7431, 7432, 7433, 7434, + 7435, 7436, 7437, 7438, 7439, 7440, 7441, 7442, + 7443, 7444, 7445, 7446, 7447, 7448, 7449, 7450, + 7451, 7452, 7453, 7454, 7455, 7456, 7457, 7458, + 7459, 7460, 7461, 7462, 7463, 7464, 7465, 7466, + 7467, 7468, 7469, 7470, 7471, 7472, 7473, 7474, + 7475, 7476, 7477, 7478, 7479, 7480, 7481, 7482, + 7483, 7484, 7485, 7486, 7487, 7488, 7489, 7490, + 7491, 592, 7492, 593, 7493, 7494, 7495, 7496, + 7497, 7498, 7499, 604, 7500, 7501, 7502, 7503, + 7504, 7505, 7506, 7507, 7508, 7509, 7510, 7511, + 7512, 7513, 7514, 7515, 7516, 7517, 7518, 7519, + 7520, 7521, 7522, 7523, 7524, 7525, 7526, 7527, + 7528, 7529, 7530, 7531, 7532, 7533, 7534, 7535, + 7536, 7537, 7538, 7539, 7540, 7541, 7542, 7543, + 7544, 42877, 7546, 7547, 7548, 11363, 7550, 7551, + 7552, 7553, 7554, 7555, 7556, 7557, 7558, 7559, + 7560, 7561, 7562, 7563, 7564, 7565, 42950, 7567, + 7568, 7569, 7570, 7571, 7572, 7573, 7574, 7575, + 7576, 7577, 7578, 594, 7579, 7580, 7581, 7582, + 7583, 7584, 7585, 609, 7586, 613, 7587, 7588, + 7589, 618, 7590, 7591, 669, 7592, 7593, 7594, + 7595, 625, 7596, 7597, 7598, 7599, 7600, 7601, + 7602, 642, 7603, 7604, 7605, 7606, 7607, 7608, + 7609, 7610, 7611, 7612, 7613, 7614, 7615, 65, + 805, 7681, 97, 805, 7680, 66, 775, 7683, + 98, 775, 7682, 66, 803, 7685, 98, 803, + 7684, 66, 817, 7687, 98, 817, 7686, 199, + 769, 7689, 231, 769, 7688, 68, 775, 7691, + 100, 775, 7690, 68, 803, 7693, 100, 803, + 7692, 68, 817, 7695, 100, 817, 7694, 68, + 807, 7697, 100, 807, 7696, 68, 813, 7699, + 100, 813, 7698, 274, 768, 7701, 275, 768, + 7700, 274, 769, 7703, 275, 769, 7702, 69, + 813, 7705, 101, 813, 7704, 69, 816, 7707, + 101, 816, 7706, 552, 774, 7709, 553, 774, + 7708, 70, 775, 7711, 102, 775, 7710, 71, + 772, 7713, 103, 772, 7712, 72, 775, 7715, + 104, 775, 7714, 72, 803, 7717, 104, 803, + 7716, 72, 776, 7719, 104, 776, 7718, 72, + 807, 7721, 104, 807, 7720, 72, 814, 7723, + 104, 814, 7722, 73, 816, 7725, 105, 816, + 7724, 207, 769, 7727, 239, 769, 7726, 75, + 769, 7729, 107, 769, 7728, 75, 803, 7731, + 107, 803, 7730, 75, 817, 7733, 107, 817, + 7732, 76, 803, 7735, 108, 803, 7734, 7734, + 772, 7737, 7735, 772, 7736, 76, 817, 7739, + 108, 817, 7738, 76, 813, 7741, 108, 813, + 7740, 77, 769, 7743, 109, 769, 7742, 77, + 775, 7745, 109, 775, 7744, 77, 803, 7747, + 109, 803, 7746, 78, 775, 7749, 110, 775, + 7748, 78, 803, 7751, 110, 803, 7750, 78, + 817, 7753, 110, 817, 7752, 78, 813, 7755, + 110, 813, 7754, 213, 769, 7757, 245, 769, + 7756, 213, 776, 7759, 245, 776, 7758, 332, + 768, 7761, 333, 768, 7760, 332, 769, 7763, + 333, 769, 7762, 80, 769, 7765, 112, 769, + 7764, 80, 775, 7767, 112, 775, 7766, 82, + 775, 7769, 114, 775, 7768, 82, 803, 7771, + 114, 803, 7770, 7770, 772, 7773, 7771, 772, + 7772, 82, 817, 7775, 114, 817, 7774, 83, + 775, 7777, 115, 775, 7776, 83, 803, 7779, + 115, 803, 7778, 346, 775, 7781, 347, 775, + 7780, 352, 775, 7783, 353, 775, 7782, 7778, + 775, 7785, 7779, 775, 7784, 84, 775, 7787, + 116, 775, 7786, 84, 803, 7789, 116, 803, + 7788, 84, 817, 7791, 116, 817, 7790, 84, + 813, 7793, 116, 813, 7792, 85, 804, 7795, + 117, 804, 7794, 85, 816, 7797, 117, 816, + 7796, 85, 813, 7799, 117, 813, 7798, 360, + 769, 7801, 361, 769, 7800, 362, 776, 7803, + 363, 776, 7802, 86, 771, 7805, 118, 771, + 7804, 86, 803, 7807, 118, 803, 7806, 87, + 768, 7809, 119, 768, 7808, 87, 769, 7811, + 119, 769, 7810, 87, 776, 7813, 119, 776, + 7812, 87, 775, 7815, 119, 775, 7814, 87, + 803, 7817, 119, 803, 7816, 88, 775, 7819, + 120, 775, 7818, 88, 776, 7821, 120, 776, + 7820, 89, 775, 7823, 121, 775, 7822, 90, + 770, 7825, 122, 770, 7824, 90, 803, 7827, + 122, 803, 7826, 90, 817, 7829, 122, 817, + 7828, 104, 817, 7830, 116, 776, 7831, 119, + 778, 7832, 121, 778, 7833, 97, 702, 7834, + 383, 775, 7836, 7837, 223, 7839, 65, 803, + 7841, 97, 803, 7840, 65, 777, 7843, 97, + 777, 7842, 194, 769, 7845, 226, 769, 7844, + 194, 768, 7847, 226, 768, 7846, 194, 777, + 7849, 226, 777, 7848, 194, 771, 7851, 226, + 771, 7850, 7840, 770, 7853, 7841, 770, 7852, + 258, 769, 7855, 259, 769, 7854, 258, 768, + 7857, 259, 768, 7856, 258, 777, 7859, 259, + 777, 7858, 258, 771, 7861, 259, 771, 7860, + 7840, 774, 7863, 7841, 774, 7862, 69, 803, + 7865, 101, 803, 7864, 69, 777, 7867, 101, + 777, 7866, 69, 771, 7869, 101, 771, 7868, + 202, 769, 7871, 234, 769, 7870, 202, 768, + 7873, 234, 768, 7872, 202, 777, 7875, 234, + 777, 7874, 202, 771, 7877, 234, 771, 7876, + 7864, 770, 7879, 7865, 770, 7878, 73, 777, + 7881, 105, 777, 7880, 73, 803, 7883, 105, + 803, 7882, 79, 803, 7885, 111, 803, 7884, + 79, 777, 7887, 111, 777, 7886, 212, 769, + 7889, 244, 769, 7888, 212, 768, 7891, 244, + 768, 7890, 212, 777, 7893, 244, 777, 7892, + 212, 771, 7895, 244, 771, 7894, 7884, 770, + 7897, 7885, 770, 7896, 416, 769, 7899, 417, + 769, 7898, 416, 768, 7901, 417, 768, 7900, + 416, 777, 7903, 417, 777, 7902, 416, 771, + 7905, 417, 771, 7904, 416, 803, 7907, 417, + 803, 7906, 85, 803, 7909, 117, 803, 7908, + 85, 777, 7911, 117, 777, 7910, 431, 769, + 7913, 432, 769, 7912, 431, 768, 7915, 432, + 768, 7914, 431, 777, 7917, 432, 777, 7916, + 431, 771, 7919, 432, 771, 7918, 431, 803, + 7921, 432, 803, 7920, 89, 768, 7923, 121, + 768, 7922, 89, 803, 7925, 121, 803, 7924, + 89, 777, 7927, 121, 777, 7926, 89, 771, + 7929, 121, 771, 7928, 7931, 7930, 7933, 7932, + 7935, 7934, 945, 787, 7944, 945, 788, 7945, + 7936, 768, 7946, 7937, 768, 7947, 7936, 769, + 7948, 7937, 769, 7949, 7936, 834, 7950, 7937, + 834, 7951, 913, 787, 7936, 913, 788, 7937, + 7944, 768, 7938, 7945, 768, 7939, 7944, 769, + 7940, 7945, 769, 7941, 7944, 834, 7942, 7945, + 834, 7943, 949, 787, 7960, 949, 788, 7961, + 7952, 768, 7962, 7953, 768, 7963, 7952, 769, + 7964, 7953, 769, 7965, 917, 787, 7952, 917, + 788, 7953, 7960, 768, 7954, 7961, 768, 7955, + 7960, 769, 7956, 7961, 769, 7957, 951, 787, + 7976, 951, 788, 7977, 7968, 768, 7978, 7969, + 768, 7979, 7968, 769, 7980, 7969, 769, 7981, + 7968, 834, 7982, 7969, 834, 7983, 919, 787, + 7968, 919, 788, 7969, 7976, 768, 7970, 7977, + 768, 7971, 7976, 769, 7972, 7977, 769, 7973, + 7976, 834, 7974, 7977, 834, 7975, 953, 787, + 7992, 953, 788, 7993, 7984, 768, 7994, 7985, + 768, 7995, 7984, 769, 7996, 7985, 769, 7997, + 7984, 834, 7998, 7985, 834, 7999, 921, 787, + 7984, 921, 788, 7985, 7992, 768, 7986, 7993, + 768, 7987, 7992, 769, 7988, 7993, 769, 7989, + 7992, 834, 7990, 7993, 834, 7991, 959, 787, + 8008, 959, 788, 8009, 8000, 768, 8010, 8001, + 768, 8011, 8000, 769, 8012, 8001, 769, 8013, + 927, 787, 8000, 927, 788, 8001, 8008, 768, + 8002, 8009, 768, 8003, 8008, 769, 8004, 8009, + 769, 8005, 965, 787, 8016, 965, 788, 8025, + 8016, 768, 965, 787, 768, 8018, 8017, 768, + 8027, 8016, 769, 965, 787, 769, 8020, 8017, + 769, 8029, 8016, 834, 965, 787, 834, 8022, + 8017, 834, 8031, 933, 788, 8017, 8025, 768, + 8019, 8025, 769, 8021, 8025, 834, 8023, 969, + 787, 8040, 969, 788, 8041, 8032, 768, 8042, + 8033, 768, 8043, 8032, 769, 8044, 8033, 769, + 8045, 8032, 834, 8046, 8033, 834, 8047, 937, + 787, 8032, 937, 788, 8033, 8040, 768, 8034, + 8041, 768, 8035, 8040, 769, 8036, 8041, 769, + 8037, 8040, 834, 8038, 8041, 834, 8039, 945, + 768, 8122, 8123, 949, 768, 8136, 8137, 951, + 768, 8138, 8139, 953, 768, 8154, 8155, 959, + 768, 8184, 8185, 965, 768, 8170, 8171, 969, + 768, 8186, 8187, 7936, 837, 7936, 953, 8072, + 7937, 837, 7937, 953, 8073, 7938, 837, 7938, + 953, 8074, 7939, 837, 7939, 953, 8075, 7940, + 837, 7940, 953, 8076, 7941, 837, 7941, 953, + 8077, 7942, 837, 7942, 953, 8078, 7943, 837, + 7943, 953, 8079, 7944, 837, 8064, 7945, 837, + 8065, 7946, 837, 8066, 7947, 837, 8067, 7948, + 837, 8068, 7949, 837, 8069, 7950, 837, 8070, + 7951, 837, 8071, 7968, 837, 7968, 953, 8088, + 7969, 837, 7969, 953, 8089, 7970, 837, 7970, + 953, 8090, 7971, 837, 7971, 953, 8091, 7972, + 837, 7972, 953, 8092, 7973, 837, 7973, 953, + 8093, 7974, 837, 7974, 953, 8094, 7975, 837, + 7975, 953, 8095, 7976, 837, 8080, 7977, 837, + 8081, 7978, 837, 8082, 7979, 837, 8083, 7980, + 837, 8084, 7981, 837, 8085, 7982, 837, 8086, + 7983, 837, 8087, 8032, 837, 8032, 953, 8104, + 8033, 837, 8033, 953, 8105, 8034, 837, 8034, + 953, 8106, 8035, 837, 8035, 953, 8107, 8036, + 837, 8036, 953, 8108, 8037, 837, 8037, 953, + 8109, 8038, 837, 8038, 953, 8110, 8039, 837, + 8039, 953, 8111, 8040, 837, 8096, 8041, 837, + 8097, 8042, 837, 8098, 8043, 837, 8099, 8044, + 837, 8100, 8045, 837, 8101, 8046, 837, 8102, + 8047, 837, 8103, 945, 774, 8120, 945, 772, + 8121, 8048, 837, 8048, 953, 8114, 945, 837, + 945, 953, 8124, 940, 837, 940, 953, 8116, + 945, 834, 8118, 8118, 837, 945, 834, 953, + 8119, 913, 774, 8112, 913, 772, 8113, 913, + 768, 8048, 8049, 913, 837, 8115, 32, 787, + 32, 834, 168, 834, 8052, 837, 8052, 953, + 8130, 951, 837, 951, 953, 8140, 942, 837, + 942, 953, 8132, 951, 834, 8134, 8134, 837, + 951, 834, 953, 8135, 917, 768, 8050, 8051, + 919, 768, 8052, 8053, 919, 837, 8131, 8127, + 768, 8127, 769, 8127, 834, 953, 774, 8152, + 953, 772, 8153, 970, 768, 953, 776, 768, + 8146, 8147, 953, 834, 8150, 970, 834, 953, + 776, 834, 8151, 921, 774, 8144, 921, 772, + 8145, 921, 768, 8054, 8055, 8190, 768, 8190, + 769, 8190, 834, 965, 774, 8168, 965, 772, + 8169, 971, 768, 965, 776, 768, 8162, 8163, + 961, 787, 8164, 961, 788, 8172, 965, 834, + 8166, 971, 834, 965, 776, 834, 8167, 933, + 774, 8160, 933, 772, 8161, 933, 768, 8058, + 8059, 929, 788, 8165, 168, 768, 901, 96, + 8060, 837, 8060, 953, 8178, 969, 837, 969, + 953, 8188, 974, 837, 974, 953, 8180, 969, + 834, 8182, 8182, 837, 969, 834, 953, 8183, + 927, 768, 8056, 8057, 937, 768, 8060, 8061, + 937, 837, 8179, 180, 32, 788, 8194, 8195, 8208, 32, 819, 46, 46, 46, 46, 46, 46, 8242, 8242, 8242, 8242, 8242, 8245, 8245, 8245, 8245, 8245, 33, 33, 32, 773, 63, - 63, 63, 33, 33, 63, 8242, 8242, 8242, - 8242, 48, 52, 53, 54, 55, 56, 57, - 43, 8722, 61, 40, 41, 82, 115, 97, - 47, 99, 97, 47, 115, 67, 176, 67, - 99, 47, 111, 99, 47, 117, 400, 176, - 70, 78, 111, 81, 83, 77, 84, 69, - 76, 84, 77, 90, 937, 197, 70, 8526, - 1488, 1489, 1490, 1491, 70, 65, 88, 915, - 928, 8721, 49, 8260, 55, 49, 8260, 57, - 49, 8260, 49, 48, 49, 8260, 51, 50, - 8260, 51, 49, 8260, 53, 50, 8260, 53, - 51, 8260, 53, 52, 8260, 53, 49, 8260, - 54, 53, 8260, 54, 49, 8260, 56, 51, - 8260, 56, 53, 8260, 56, 55, 8260, 56, - 49, 8260, 8560, 73, 73, 8561, 73, 73, - 73, 8562, 73, 86, 8563, 86, 8564, 86, - 73, 8565, 86, 73, 73, 8566, 86, 73, - 73, 73, 8567, 73, 88, 8568, 88, 8569, - 88, 73, 8570, 88, 73, 73, 8571, 8572, - 8573, 8574, 8575, 105, 105, 105, 105, 105, - 105, 118, 118, 105, 118, 105, 105, 118, - 105, 105, 105, 105, 120, 120, 105, 120, - 105, 105, 8580, 48, 8260, 51, 8592, 824, - 8594, 824, 8596, 824, 8656, 824, 8660, 824, - 8658, 824, 8707, 824, 8712, 824, 8715, 824, - 8739, 824, 8741, 824, 8747, 8747, 8747, 8747, - 8747, 8750, 8750, 8750, 8750, 8750, 8764, 824, - 8771, 824, 8773, 824, 8776, 824, 61, 824, - 8801, 824, 8781, 824, 60, 824, 62, 824, - 8804, 824, 8805, 824, 8818, 824, 8819, 824, - 8822, 824, 8823, 824, 8826, 824, 8827, 824, - 8834, 824, 8835, 824, 8838, 824, 8839, 824, - 8866, 824, 8872, 824, 8873, 824, 8875, 824, - 8828, 824, 8829, 824, 8849, 824, 8850, 824, - 8882, 824, 8883, 824, 8884, 824, 8885, 824, - 12296, 12297, 49, 48, 49, 49, 49, 50, - 49, 51, 49, 52, 49, 53, 49, 54, - 49, 55, 49, 56, 49, 57, 50, 48, - 40, 49, 41, 40, 50, 41, 40, 51, - 41, 40, 52, 41, 40, 53, 41, 40, - 54, 41, 40, 55, 41, 40, 56, 41, - 40, 57, 41, 40, 49, 48, 41, 40, - 49, 49, 41, 40, 49, 50, 41, 40, - 49, 51, 41, 40, 49, 52, 41, 40, - 49, 53, 41, 40, 49, 54, 41, 40, - 49, 55, 41, 40, 49, 56, 41, 40, - 49, 57, 41, 40, 50, 48, 41, 49, - 46, 50, 46, 51, 46, 52, 46, 53, - 46, 54, 46, 55, 46, 56, 46, 57, - 46, 49, 48, 46, 49, 49, 46, 49, - 50, 46, 49, 51, 46, 49, 52, 46, - 49, 53, 46, 49, 54, 46, 49, 55, - 46, 49, 56, 46, 49, 57, 46, 50, - 48, 46, 40, 97, 41, 40, 98, 41, - 40, 99, 41, 40, 100, 41, 40, 101, - 41, 40, 102, 41, 40, 103, 41, 40, - 104, 41, 40, 105, 41, 40, 106, 41, - 40, 107, 41, 40, 108, 41, 40, 109, - 41, 40, 110, 41, 40, 111, 41, 40, - 112, 41, 40, 113, 41, 40, 114, 41, - 40, 115, 41, 40, 116, 41, 40, 117, - 41, 40, 118, 41, 40, 119, 41, 40, - 120, 41, 40, 121, 41, 40, 122, 41, - 9424, 9425, 9426, 9427, 9428, 9429, 9430, 9431, - 9432, 9433, 9434, 9435, 9436, 9437, 9438, 9439, - 9440, 9441, 83, 9442, 9443, 9444, 9445, 9446, - 9447, 89, 9448, 9449, 8747, 8747, 8747, 8747, - 58, 58, 61, 61, 61, 61, 61, 61, - 10973, 824, 11312, 11313, 11314, 11315, 11316, 11317, - 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, - 11326, 11327, 11328, 11329, 11330, 11331, 11332, 11333, - 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, - 11342, 11343, 11344, 11345, 11346, 11347, 11348, 11349, - 11350, 11351, 11352, 11353, 11354, 11355, 11356, 11357, - 11358, 11361, 619, 7549, 637, 11368, 11370, 11372, - 11379, 11382, 575, 576, 11393, 11395, 11397, 11399, - 11401, 11403, 11405, 11407, 11409, 11411, 11413, 11415, - 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, - 11433, 11435, 11437, 11439, 11441, 11443, 11445, 11447, - 11449, 11451, 11453, 11455, 11457, 11459, 11461, 11463, - 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, - 11481, 11483, 11485, 11487, 11489, 11491, 11500, 11502, - 11507, 11617, 27597, 40863, 19968, 20008, 20022, 20031, - 20057, 20101, 20108, 20128, 20154, 20799, 20837, 20843, - 20866, 20886, 20907, 20960, 20981, 20992, 21147, 21241, - 21269, 21274, 21304, 21313, 21340, 21353, 21378, 21430, - 21448, 21475, 22231, 22303, 22763, 22786, 22794, 22805, - 22823, 22899, 23376, 23424, 23544, 23567, 23586, 23608, - 23662, 23665, 24027, 24037, 24049, 24062, 24178, 24186, - 24191, 24308, 24318, 24331, 24339, 24400, 24417, 24435, - 24515, 25096, 25142, 25163, 25903, 25908, 25991, 26007, - 26020, 26041, 26080, 26085, 26352, 26376, 26408, 27424, - 27490, 27513, 27571, 27595, 27604, 27611, 27663, 27668, - 27700, 28779, 29226, 29238, 29243, 29247, 29255, 29273, - 29275, 29356, 29572, 29577, 29916, 29926, 29976, 29983, - 29992, 30000, 30091, 30098, 30326, 30333, 30382, 30399, - 30446, 30683, 30690, 30707, 31034, 31160, 31166, 31348, - 31435, 31481, 31859, 31992, 32566, 32593, 32650, 32701, - 32769, 32780, 32786, 32819, 32895, 32905, 33251, 33258, - 33267, 33276, 33292, 33307, 33311, 33390, 33394, 33400, - 34381, 34411, 34880, 34892, 34915, 35198, 35211, 35282, - 35328, 35895, 35910, 35925, 35960, 35997, 36196, 36208, - 36275, 36523, 36554, 36763, 36784, 36789, 37009, 37193, - 37318, 37324, 37329, 38263, 38272, 38428, 38582, 38585, - 38632, 38737, 38750, 38754, 38761, 38859, 38893, 38899, - 38913, 39080, 39131, 39135, 39318, 39321, 39340, 39592, - 39640, 39647, 39717, 39727, 39730, 39740, 39770, 40165, - 40565, 40575, 40613, 40635, 40643, 40653, 40657, 40697, - 40701, 40718, 40723, 40736, 40763, 40778, 40786, 40845, - 40860, 40864, 12306, 21316, 21317, 12363, 12441, 12365, - 12441, 12367, 12441, 12369, 12441, 12371, 12441, 12373, - 12441, 12375, 12441, 12377, 12441, 12379, 12441, 12381, - 12441, 12383, 12441, 12385, 12441, 12388, 12441, 12390, - 12441, 12392, 12441, 12399, 12441, 12399, 12442, 12402, - 12441, 12402, 12442, 12405, 12441, 12405, 12442, 12408, - 12441, 12408, 12442, 12411, 12441, 12411, 12442, 12358, - 12441, 32, 12441, 32, 12442, 12445, 12441, 12424, - 12426, 12459, 12441, 12461, 12441, 12463, 12441, 12465, - 12441, 12467, 12441, 12469, 12441, 12471, 12441, 12473, - 12441, 12475, 12441, 12477, 12441, 12479, 12441, 12481, - 12441, 12484, 12441, 12486, 12441, 12488, 12441, 12495, - 12441, 12495, 12442, 12498, 12441, 12498, 12442, 12501, - 12441, 12501, 12442, 12504, 12441, 12504, 12442, 12507, - 12441, 12507, 12442, 12454, 12441, 12527, 12441, 12528, - 12441, 12529, 12441, 12530, 12441, 12541, 12441, 12467, - 12488, 4352, 4353, 4522, 4354, 4524, 4525, 4355, - 4356, 4357, 4528, 4529, 4530, 4531, 4532, 4533, - 4378, 4358, 4359, 4360, 4385, 4361, 4362, 4363, - 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4449, - 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, - 4458, 4459, 4460, 4461, 4462, 4463, 4464, 4465, - 4466, 4467, 4468, 4469, 4448, 4372, 4373, 4551, - 4552, 4556, 4558, 4563, 4567, 4569, 4380, 4573, - 4575, 4381, 4382, 4384, 4386, 4387, 4391, 4393, - 4395, 4396, 4397, 4398, 4399, 4402, 4406, 4416, - 4423, 4428, 4593, 4594, 4439, 4440, 4441, 4484, - 4485, 4488, 4497, 4498, 4500, 4510, 4513, 19977, - 22235, 19978, 20013, 19979, 30002, 19993, 19969, 22825, - 22320, 40, 4352, 41, 40, 4354, 41, 40, - 4355, 41, 40, 4357, 41, 40, 4358, 41, - 40, 4359, 41, 40, 4361, 41, 40, 4363, - 41, 40, 4364, 41, 40, 4366, 41, 40, - 4367, 41, 40, 4368, 41, 40, 4369, 41, - 40, 4370, 41, 40, 4352, 4449, 41, 40, - 4354, 4449, 41, 40, 4355, 4449, 41, 40, - 4357, 4449, 41, 40, 4358, 4449, 41, 40, - 4359, 4449, 41, 40, 4361, 4449, 41, 40, - 4363, 4449, 41, 40, 4364, 4449, 41, 40, - 4366, 4449, 41, 40, 4367, 4449, 41, 40, - 4368, 4449, 41, 40, 4369, 4449, 41, 40, - 4370, 4449, 41, 40, 4364, 4462, 41, 40, - 4363, 4457, 4364, 4453, 4523, 41, 40, 4363, - 4457, 4370, 4462, 41, 40, 19968, 41, 40, - 20108, 41, 40, 19977, 41, 40, 22235, 41, - 40, 20116, 41, 40, 20845, 41, 40, 19971, - 41, 40, 20843, 41, 40, 20061, 41, 40, - 21313, 41, 40, 26376, 41, 40, 28779, 41, - 40, 27700, 41, 40, 26408, 41, 40, 37329, - 41, 40, 22303, 41, 40, 26085, 41, 40, - 26666, 41, 40, 26377, 41, 40, 31038, 41, - 40, 21517, 41, 40, 29305, 41, 40, 36001, - 41, 40, 31069, 41, 40, 21172, 41, 40, - 20195, 41, 40, 21628, 41, 40, 23398, 41, - 40, 30435, 41, 40, 20225, 41, 40, 36039, - 41, 40, 21332, 41, 40, 31085, 41, 40, - 20241, 41, 40, 33258, 41, 40, 33267, 41, - 21839, 24188, 31631, 80, 84, 69, 50, 49, - 50, 50, 50, 51, 50, 52, 50, 53, - 50, 54, 50, 55, 50, 56, 50, 57, - 51, 48, 51, 49, 51, 50, 51, 51, - 51, 52, 51, 53, 4352, 4449, 4354, 4449, - 4355, 4449, 4357, 4449, 4358, 4449, 4359, 4449, - 4361, 4449, 4363, 4449, 4364, 4449, 4366, 4449, - 4367, 4449, 4368, 4449, 4369, 4449, 4370, 4449, - 4366, 4449, 4535, 4352, 4457, 4364, 4462, 4363, - 4468, 4363, 4462, 20116, 20845, 19971, 20061, 26666, - 26377, 31038, 21517, 29305, 36001, 31069, 21172, 31192, - 30007, 36969, 20778, 21360, 27880, 38917, 20241, 20889, - 27491, 24038, 21491, 21307, 23447, 23398, 30435, 20225, - 36039, 21332, 22812, 51, 54, 51, 55, 51, - 56, 51, 57, 52, 48, 52, 49, 52, - 50, 52, 51, 52, 52, 52, 53, 52, - 54, 52, 55, 52, 56, 52, 57, 53, - 48, 49, 26376, 50, 26376, 51, 26376, 52, - 26376, 53, 26376, 54, 26376, 55, 26376, 56, - 26376, 57, 26376, 49, 48, 26376, 49, 49, - 26376, 49, 50, 26376, 72, 103, 101, 114, - 103, 101, 86, 76, 84, 68, 12450, 12452, - 12454, 12456, 12458, 12459, 12461, 12463, 12465, 12467, - 12469, 12471, 12473, 12475, 12477, 12479, 12481, 12484, - 12486, 12488, 12490, 12491, 12492, 12493, 12494, 12495, - 12498, 12501, 12504, 12507, 12510, 12511, 12512, 12513, - 12514, 12516, 12518, 12520, 12521, 12522, 12523, 12524, - 12525, 12527, 12528, 12529, 12530, 20196, 21644, 12450, - 12497, 12540, 12488, 12450, 12523, 12501, 12449, 12450, - 12531, 12506, 12450, 12450, 12540, 12523, 12452, 12491, - 12531, 12464, 12452, 12531, 12481, 12454, 12457, 12531, - 12456, 12473, 12463, 12540, 12489, 12456, 12540, 12459, - 12540, 12458, 12531, 12473, 12458, 12540, 12512, 12459, - 12452, 12522, 12459, 12521, 12483, 12488, 12459, 12525, - 12522, 12540, 12460, 12525, 12531, 12460, 12531, 12510, - 12462, 12460, 12462, 12491, 12540, 12461, 12517, 12522, - 12540, 12462, 12523, 12480, 12540, 12461, 12525, 12461, - 12525, 12464, 12521, 12512, 12461, 12525, 12513, 12540, - 12488, 12523, 12461, 12525, 12527, 12483, 12488, 12464, - 12521, 12512, 12464, 12521, 12512, 12488, 12531, 12463, - 12523, 12476, 12452, 12525, 12463, 12525, 12540, 12493, - 12465, 12540, 12473, 12467, 12523, 12490, 12467, 12540, - 12509, 12469, 12452, 12463, 12523, 12469, 12531, 12481, - 12540, 12512, 12471, 12522, 12531, 12464, 12475, 12531, - 12481, 12475, 12531, 12488, 12480, 12540, 12473, 12487, - 12471, 12489, 12523, 12488, 12531, 12490, 12494, 12494, - 12483, 12488, 12495, 12452, 12484, 12497, 12540, 12475, - 12531, 12488, 12497, 12540, 12484, 12496, 12540, 12524, - 12523, 12500, 12450, 12473, 12488, 12523, 12500, 12463, - 12523, 12500, 12467, 12499, 12523, 12501, 12449, 12521, - 12483, 12489, 12501, 12451, 12540, 12488, 12502, 12483, - 12471, 12455, 12523, 12501, 12521, 12531, 12504, 12463, + 63, 63, 33, 33, 63, 3, 8242, 8242, + 8242, 8242, 48, 8305, 52, 53, 54, 55, + 56, 57, 43, 8722, 61, 40, 41, 8319, + 8336, 8337, 8338, 8339, 8340, 8341, 8342, 8343, + 8344, 8345, 8346, 8347, 8348, 82, 115, 97, + 47, 99, 97, 47, 115, 8450, 176, 67, + 99, 47, 111, 99, 47, 117, 8455, 176, + 70, 8458, 8459, 8460, 8461, 8462, 8463, 8464, + 8465, 8466, 8467, 8469, 78, 111, 8473, 8474, + 8475, 8476, 8477, 83, 77, 84, 69, 76, + 84, 77, 8484, 8488, 8492, 8493, 8495, 8496, + 8497, 8526, 8499, 8500, 1488, 1489, 1490, 1491, + 8505, 70, 65, 88, 8508, 8509, 8510, 8511, + 8721, 8517, 8518, 8519, 8520, 8521, 8498, 49, + 8260, 55, 49, 8260, 57, 3, 49, 8260, + 49, 48, 49, 8260, 51, 50, 8260, 51, + 49, 8260, 53, 50, 8260, 53, 51, 8260, + 53, 52, 8260, 53, 49, 8260, 54, 53, + 8260, 54, 49, 8260, 56, 51, 8260, 56, + 53, 8260, 56, 55, 8260, 56, 49, 8260, + 8560, 73, 73, 8561, 73, 73, 73, 8562, + 73, 86, 8563, 8564, 86, 73, 8565, 86, + 73, 73, 8566, 3, 86, 73, 73, 73, + 8567, 73, 88, 8568, 8569, 88, 73, 8570, + 88, 73, 73, 8571, 8572, 8573, 8574, 8575, + 8544, 105, 105, 8545, 105, 105, 105, 8546, + 105, 118, 8547, 8548, 118, 105, 8549, 118, + 105, 105, 8550, 3, 118, 105, 105, 105, + 8551, 105, 120, 8552, 8553, 120, 105, 8554, + 120, 105, 105, 8555, 8556, 8557, 8558, 8559, + 8580, 8579, 48, 8260, 51, 8592, 824, 8594, + 824, 8596, 824, 8656, 824, 8660, 824, 8658, + 824, 8707, 824, 8712, 824, 8715, 824, 8739, + 824, 8741, 824, 8747, 8747, 8747, 8747, 8747, + 8750, 8750, 8750, 8750, 8750, 8764, 824, 8771, + 824, 8773, 824, 8776, 824, 61, 824, 8801, + 824, 8781, 824, 60, 824, 62, 824, 8804, + 824, 8805, 824, 8818, 824, 8819, 824, 8822, + 824, 8823, 824, 8826, 824, 8827, 824, 8834, + 824, 8835, 824, 8838, 824, 8839, 824, 8866, + 824, 8872, 824, 8873, 824, 8875, 824, 8828, + 824, 8829, 824, 8849, 824, 8850, 824, 8882, + 824, 8883, 824, 8884, 824, 8885, 824, 12296, + 12297, 49, 48, 49, 49, 49, 50, 49, + 51, 49, 52, 49, 53, 49, 54, 49, + 55, 49, 56, 49, 57, 50, 48, 40, + 49, 41, 40, 50, 41, 40, 51, 41, + 40, 52, 41, 40, 53, 41, 40, 54, + 41, 40, 55, 41, 40, 56, 41, 40, + 57, 41, 3, 40, 49, 48, 41, 3, + 40, 49, 49, 41, 3, 40, 49, 50, + 41, 3, 40, 49, 51, 41, 3, 40, + 49, 52, 41, 3, 40, 49, 53, 41, + 3, 40, 49, 54, 41, 3, 40, 49, + 55, 41, 3, 40, 49, 56, 41, 3, + 40, 49, 57, 41, 3, 40, 50, 48, + 41, 49, 46, 50, 46, 51, 46, 52, + 46, 53, 46, 54, 46, 55, 46, 56, + 46, 57, 46, 49, 48, 46, 49, 49, + 46, 49, 50, 46, 49, 51, 46, 49, + 52, 46, 49, 53, 46, 49, 54, 46, + 49, 55, 46, 49, 56, 46, 49, 57, + 46, 50, 48, 46, 40, 97, 41, 40, + 98, 41, 40, 99, 41, 40, 100, 41, + 40, 101, 41, 40, 102, 41, 40, 103, + 41, 40, 104, 41, 40, 105, 41, 40, + 106, 41, 40, 107, 41, 40, 108, 41, + 40, 109, 41, 40, 110, 41, 40, 111, + 41, 40, 112, 41, 40, 113, 41, 40, + 114, 41, 40, 115, 41, 40, 116, 41, + 40, 117, 41, 40, 118, 41, 40, 119, + 41, 40, 120, 41, 40, 121, 41, 40, + 122, 41, 9424, 9425, 9426, 9427, 9428, 9429, + 9430, 9431, 9432, 9433, 9434, 9435, 9436, 9437, + 9438, 9439, 9440, 9441, 9442, 9443, 9444, 9445, + 9446, 9447, 9448, 9449, 9398, 9399, 9400, 9401, + 9402, 9403, 9404, 9405, 9406, 9407, 9408, 9409, + 9410, 9411, 9412, 9413, 9414, 9415, 9416, 9417, + 9418, 9419, 9420, 9421, 9422, 9423, 3, 8747, + 8747, 8747, 8747, 58, 58, 61, 61, 61, + 61, 61, 61, 10973, 824, 11312, 11313, 11314, + 11315, 11316, 11317, 11318, 11319, 11320, 11321, 11322, + 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330, + 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, + 11339, 11340, 11341, 11342, 11343, 11344, 11345, 11346, + 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354, + 11355, 11356, 11357, 11358, 11359, 11264, 11265, 11266, + 11267, 11268, 11269, 11270, 11271, 11272, 11273, 11274, + 11275, 11276, 11277, 11278, 11279, 11280, 11281, 11282, + 11283, 11284, 11285, 11286, 11287, 11288, 11289, 11290, + 11291, 11292, 11293, 11294, 11295, 11296, 11297, 11298, + 11299, 11300, 11301, 11302, 11303, 11304, 11305, 11306, + 11307, 11308, 11309, 11310, 11311, 11361, 11360, 619, + 7549, 637, 570, 574, 11368, 11367, 11370, 11369, + 11372, 11371, 11377, 11379, 11378, 11380, 11382, 11381, + 11383, 11384, 11385, 11386, 11387, 11388, 11389, 575, + 576, 11393, 11392, 11395, 11394, 11397, 11396, 11399, + 11398, 11401, 11400, 11403, 11402, 11405, 11404, 11407, + 11406, 11409, 11408, 11411, 11410, 11413, 11412, 11415, + 11414, 11417, 11416, 11419, 11418, 11421, 11420, 11423, + 11422, 11425, 11424, 11427, 11426, 11429, 11428, 11431, + 11430, 11433, 11432, 11435, 11434, 11437, 11436, 11439, + 11438, 11441, 11440, 11443, 11442, 11445, 11444, 11447, + 11446, 11449, 11448, 11451, 11450, 11453, 11452, 11455, + 11454, 11457, 11456, 11459, 11458, 11461, 11460, 11463, + 11462, 11465, 11464, 11467, 11466, 11469, 11468, 11471, + 11470, 11473, 11472, 11475, 11474, 11477, 11476, 11479, + 11478, 11481, 11480, 11483, 11482, 11485, 11484, 11487, + 11486, 11489, 11488, 11491, 11490, 11492, 11500, 11499, + 11502, 11501, 11507, 11506, 4256, 4257, 4258, 4259, + 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, + 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, + 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, + 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, + 4292, 4293, 4295, 4301, 11617, 27597, 40863, 19968, + 20008, 20022, 20031, 20057, 20101, 20108, 20128, 20154, + 20799, 20837, 20843, 20866, 20886, 20907, 20960, 20981, + 20992, 21147, 21241, 21269, 21274, 21304, 21313, 21340, + 21353, 21378, 21430, 21448, 21475, 22231, 22303, 22763, + 22786, 22794, 22805, 22823, 22899, 23376, 23424, 23544, + 23567, 23586, 23608, 23662, 23665, 24027, 24037, 24049, + 24062, 24178, 24186, 24191, 24308, 24318, 24331, 24339, + 24400, 24417, 24435, 24515, 25096, 25142, 25163, 25903, + 25908, 25991, 26007, 26020, 26041, 26080, 26085, 26352, + 26376, 26408, 27424, 27490, 27513, 27571, 27595, 27604, + 27611, 27663, 27668, 27700, 28779, 29226, 29238, 29243, + 29247, 29255, 29273, 29275, 29356, 29572, 29577, 29916, + 29926, 29976, 29983, 29992, 30000, 30091, 30098, 30326, + 30333, 30382, 30399, 30446, 30683, 30690, 30707, 31034, + 31160, 31166, 31348, 31435, 31481, 31859, 31992, 32566, + 32593, 32650, 32701, 32769, 32780, 32786, 32819, 32895, + 32905, 33251, 33258, 33267, 33276, 33292, 33307, 33311, + 33390, 33394, 33400, 34381, 34411, 34880, 34892, 34915, + 35198, 35211, 35282, 35328, 35895, 35910, 35925, 35960, + 35997, 36196, 36208, 36275, 36523, 36554, 36763, 36784, + 36789, 37009, 37193, 37318, 37324, 37329, 38263, 38272, + 38428, 38582, 38585, 38632, 38737, 38750, 38754, 38761, + 38859, 38893, 38899, 38913, 39080, 39131, 39135, 39318, + 39321, 39340, 39592, 39640, 39647, 39717, 39727, 39730, + 39740, 39770, 40165, 40565, 40575, 40613, 40635, 40643, + 40653, 40657, 40697, 40701, 40718, 40723, 40736, 40763, + 40778, 40786, 40845, 40860, 40864, 12306, 21316, 21317, + 12363, 12441, 12365, 12441, 12367, 12441, 12369, 12441, + 12371, 12441, 12373, 12441, 12375, 12441, 12377, 12441, + 12379, 12441, 12381, 12441, 12383, 12441, 12385, 12441, + 12388, 12441, 12390, 12441, 12392, 12441, 12399, 12441, + 12399, 12442, 12402, 12441, 12402, 12442, 12405, 12441, + 12405, 12442, 12408, 12441, 12408, 12442, 12411, 12441, + 12411, 12442, 12358, 12441, 32, 12441, 32, 12442, + 12445, 12441, 12424, 12426, 12459, 12441, 12461, 12441, + 12463, 12441, 12465, 12441, 12467, 12441, 12469, 12441, + 12471, 12441, 12473, 12441, 12475, 12441, 12477, 12441, + 12479, 12441, 12481, 12441, 12484, 12441, 12486, 12441, + 12488, 12441, 12495, 12441, 12495, 12442, 12498, 12441, + 12498, 12442, 12501, 12441, 12501, 12442, 12504, 12441, + 12504, 12442, 12507, 12441, 12507, 12442, 12454, 12441, + 12527, 12441, 12528, 12441, 12529, 12441, 12530, 12441, + 12541, 12441, 12467, 12488, 4352, 4353, 4522, 4354, + 4524, 4525, 4355, 4356, 4357, 4528, 4529, 4530, + 4531, 4532, 4533, 4378, 4358, 4359, 4360, 4385, + 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, + 4369, 4370, 4449, 4450, 4451, 4452, 4453, 4454, + 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, + 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4448, + 4372, 4373, 4551, 4552, 4556, 4558, 4563, 4567, + 4569, 4380, 4573, 4575, 4381, 4382, 4384, 4386, + 4387, 4391, 4393, 4395, 4396, 4397, 4398, 4399, + 4402, 4406, 4416, 4423, 4428, 4593, 4594, 4439, + 4440, 4441, 4484, 4485, 4488, 4497, 4498, 4500, + 4510, 4513, 19977, 22235, 19978, 20013, 19979, 30002, + 19993, 19969, 22825, 22320, 40, 4352, 41, 40, + 4354, 41, 40, 4355, 41, 40, 4357, 41, + 40, 4358, 41, 40, 4359, 41, 40, 4361, + 41, 40, 4363, 41, 40, 4364, 41, 40, + 4366, 41, 40, 4367, 41, 40, 4368, 41, + 40, 4369, 41, 40, 4370, 41, 3, 40, + 4352, 4449, 41, 3, 40, 4354, 4449, 41, + 3, 40, 4355, 4449, 41, 3, 40, 4357, + 4449, 41, 3, 40, 4358, 4449, 41, 3, + 40, 4359, 4449, 41, 3, 40, 4361, 4449, + 41, 3, 40, 4363, 4449, 41, 3, 40, + 4364, 4449, 41, 3, 40, 4366, 4449, 41, + 3, 40, 4367, 4449, 41, 3, 40, 4368, + 4449, 41, 3, 40, 4369, 4449, 41, 3, + 40, 4370, 4449, 41, 3, 40, 4364, 4462, + 41, 6, 40, 4363, 4457, 4364, 4453, 4523, + 41, 5, 40, 4363, 4457, 4370, 4462, 41, + 40, 19968, 41, 40, 20108, 41, 40, 19977, + 41, 40, 22235, 41, 40, 20116, 41, 40, + 20845, 41, 40, 19971, 41, 40, 20843, 41, + 40, 20061, 41, 40, 21313, 41, 40, 26376, + 41, 40, 28779, 41, 40, 27700, 41, 40, + 26408, 41, 40, 37329, 41, 40, 22303, 41, + 40, 26085, 41, 40, 26666, 41, 40, 26377, + 41, 40, 31038, 41, 40, 21517, 41, 40, + 29305, 41, 40, 36001, 41, 40, 31069, 41, + 40, 21172, 41, 40, 20195, 41, 40, 21628, + 41, 40, 23398, 41, 40, 30435, 41, 40, + 20225, 41, 40, 36039, 41, 40, 21332, 41, + 40, 31085, 41, 40, 20241, 41, 40, 33258, + 41, 40, 33267, 41, 21839, 24188, 31631, 80, + 84, 69, 50, 49, 50, 50, 50, 51, + 50, 52, 50, 53, 50, 54, 50, 55, + 50, 56, 50, 57, 51, 48, 51, 49, + 51, 50, 51, 51, 51, 52, 51, 53, + 4352, 4449, 4354, 4449, 4355, 4449, 4357, 4449, + 4358, 4449, 4359, 4449, 4361, 4449, 4363, 4449, + 4364, 4449, 4366, 4449, 4367, 4449, 4368, 4449, + 4369, 4449, 4370, 4449, 4, 4366, 4449, 4535, + 4352, 4457, 3, 4364, 4462, 4363, 4468, 4363, + 4462, 20116, 20845, 19971, 20061, 26666, 26377, 31038, + 21517, 29305, 36001, 31069, 21172, 31192, 30007, 36969, + 20778, 21360, 27880, 38917, 20241, 20889, 27491, 24038, + 21491, 21307, 23447, 23398, 30435, 20225, 36039, 21332, + 22812, 51, 54, 51, 55, 51, 56, 51, + 57, 52, 48, 52, 49, 52, 50, 52, + 51, 52, 52, 52, 53, 52, 54, 52, + 55, 52, 56, 52, 57, 53, 48, 49, + 26376, 50, 26376, 51, 26376, 52, 26376, 53, + 26376, 54, 26376, 55, 26376, 56, 26376, 57, + 26376, 49, 48, 26376, 49, 49, 26376, 49, + 50, 26376, 72, 103, 101, 114, 103, 101, + 86, 76, 84, 68, 12450, 12452, 12454, 12456, + 12458, 12459, 12461, 12463, 12465, 12467, 12469, 12471, + 12473, 12475, 12477, 12479, 12481, 12484, 12486, 12488, + 12490, 12491, 12492, 12493, 12494, 12495, 12498, 12501, + 12504, 12507, 12510, 12511, 12512, 12513, 12514, 12516, + 12518, 12520, 12521, 12522, 12523, 12524, 12525, 12527, + 12528, 12529, 12530, 20196, 21644, 3, 12450, 12497, + 12540, 12488, 3, 12450, 12523, 12501, 12449, 3, + 12450, 12531, 12506, 12450, 12450, 12540, 12523, 3, + 12452, 12491, 12531, 12464, 12452, 12531, 12481, 12454, + 12457, 12531, 4, 12456, 12473, 12463, 12540, 12489, + 3, 12456, 12540, 12459, 12540, 12458, 12531, 12473, + 12458, 12540, 12512, 12459, 12452, 12522, 3, 12459, + 12521, 12483, 12488, 3, 12459, 12525, 12522, 12540, + 12460, 12525, 12531, 12460, 12531, 12510, 12462, 12460, + 12462, 12491, 12540, 3, 12461, 12517, 12522, 12540, + 3, 12462, 12523, 12480, 12540, 12461, 12525, 4, + 12461, 12525, 12464, 12521, 12512, 5, 12461, 12525, + 12513, 12540, 12488, 12523, 4, 12461, 12525, 12527, + 12483, 12488, 12464, 12521, 12512, 4, 12464, 12521, + 12512, 12488, 12531, 4, 12463, 12523, 12476, 12452, + 12525, 3, 12463, 12525, 12540, 12493, 12465, 12540, + 12473, 12467, 12523, 12490, 12467, 12540, 12509, 3, + 12469, 12452, 12463, 12523, 4, 12469, 12531, 12481, + 12540, 12512, 3, 12471, 12522, 12531, 12464, 12475, + 12531, 12481, 12475, 12531, 12488, 12480, 12540, 12473, + 12487, 12471, 12489, 12523, 12488, 12531, 12490, 12494, + 12494, 12483, 12488, 12495, 12452, 12484, 4, 12497, + 12540, 12475, 12531, 12488, 12497, 12540, 12484, 3, + 12496, 12540, 12524, 12523, 4, 12500, 12450, 12473, + 12488, 12523, 12500, 12463, 12523, 12500, 12467, 12499, + 12523, 4, 12501, 12449, 12521, 12483, 12489, 3, + 12501, 12451, 12540, 12488, 4, 12502, 12483, 12471, + 12455, 12523, 12501, 12521, 12531, 4, 12504, 12463, 12479, 12540, 12523, 12506, 12477, 12506, 12491, 12498, 12504, 12523, 12484, 12506, 12531, 12473, 12506, 12540, - 12472, 12505, 12540, 12479, 12509, 12452, 12531, 12488, - 12508, 12523, 12488, 12507, 12531, 12509, 12531, 12489, - 12507, 12540, 12523, 12507, 12540, 12531, 12510, 12452, - 12463, 12525, 12510, 12452, 12523, 12510, 12483, 12495, - 12510, 12523, 12463, 12510, 12531, 12471, 12519, 12531, - 12511, 12463, 12525, 12531, 12511, 12522, 12511, 12522, - 12496, 12540, 12523, 12513, 12460, 12513, 12460, 12488, - 12531, 12513, 12540, 12488, 12523, 12516, 12540, 12489, - 12516, 12540, 12523, 12518, 12450, 12531, 12522, 12483, - 12488, 12523, 12522, 12521, 12523, 12500, 12540, 12523, - 12540, 12502, 12523, 12524, 12512, 12524, 12531, 12488, - 12466, 12531, 12527, 12483, 12488, 48, 28857, 49, - 28857, 50, 28857, 51, 28857, 52, 28857, 53, - 28857, 54, 28857, 55, 28857, 56, 28857, 57, - 28857, 49, 48, 28857, 49, 49, 28857, 49, - 50, 28857, 49, 51, 28857, 49, 52, 28857, - 49, 53, 28857, 49, 54, 28857, 49, 55, - 28857, 49, 56, 28857, 49, 57, 28857, 50, - 48, 28857, 50, 49, 28857, 50, 50, 28857, - 50, 51, 28857, 50, 52, 28857, 104, 80, - 97, 100, 97, 65, 85, 98, 97, 114, - 111, 86, 112, 99, 100, 109, 100, 109, - 178, 100, 109, 179, 73, 85, 24179, 25104, - 26157, 21644, 22823, 27491, 26126, 27835, 26666, 24335, - 20250, 31038, 112, 65, 110, 65, 956, 65, - 109, 65, 107, 65, 75, 66, 77, 66, - 71, 66, 99, 97, 108, 107, 99, 97, - 108, 112, 70, 110, 70, 956, 70, 956, - 103, 109, 103, 107, 103, 72, 122, 107, - 72, 122, 77, 72, 122, 71, 72, 122, - 84, 72, 122, 956, 8467, 109, 8467, 100, - 8467, 107, 8467, 102, 109, 110, 109, 956, - 109, 109, 109, 99, 109, 107, 109, 109, - 109, 178, 99, 109, 178, 109, 178, 107, - 109, 178, 109, 109, 179, 99, 109, 179, - 109, 179, 107, 109, 179, 109, 8725, 115, - 109, 8725, 115, 178, 80, 97, 107, 80, - 97, 77, 80, 97, 71, 80, 97, 114, - 97, 100, 114, 97, 100, 8725, 115, 114, - 97, 100, 8725, 115, 178, 112, 115, 110, - 115, 956, 115, 109, 115, 112, 86, 110, - 86, 956, 86, 109, 86, 107, 86, 77, - 86, 112, 87, 110, 87, 956, 87, 109, - 87, 107, 87, 77, 87, 107, 937, 77, - 937, 97, 46, 109, 46, 66, 113, 99, - 99, 99, 100, 67, 8725, 107, 103, 67, - 111, 46, 100, 66, 71, 121, 104, 97, - 72, 80, 105, 110, 75, 75, 75, 77, - 107, 116, 108, 109, 108, 110, 108, 111, - 103, 108, 120, 109, 98, 109, 105, 108, - 109, 111, 108, 80, 72, 112, 46, 109, - 46, 80, 80, 77, 80, 82, 115, 114, - 83, 118, 87, 98, 86, 8725, 109, 65, - 8725, 109, 49, 26085, 50, 26085, 51, 26085, - 52, 26085, 53, 26085, 54, 26085, 55, 26085, - 56, 26085, 57, 26085, 49, 48, 26085, 49, - 49, 26085, 49, 50, 26085, 49, 51, 26085, - 49, 52, 26085, 49, 53, 26085, 49, 54, - 26085, 49, 55, 26085, 49, 56, 26085, 49, - 57, 26085, 50, 48, 26085, 50, 49, 26085, - 50, 50, 26085, 50, 51, 26085, 50, 52, - 26085, 50, 53, 26085, 50, 54, 26085, 50, - 55, 26085, 50, 56, 26085, 50, 57, 26085, - 51, 48, 26085, 51, 49, 26085, 103, 97, - 108, 42561, 42563, 42565, 42567, 42569, 42573, 42575, - 42577, 42579, 42581, 42583, 42585, 42587, 42589, 42591, - 42593, 42595, 42597, 42599, 42601, 42603, 42605, 42625, - 42627, 42629, 42631, 42633, 42635, 42637, 42639, 42641, - 42643, 42645, 42647, 42649, 42651, 42787, 42789, 42791, - 42793, 42795, 42797, 42799, 42803, 42805, 42807, 42809, - 42811, 42813, 42815, 42817, 42819, 42821, 42823, 42825, - 42827, 42829, 42831, 42833, 42835, 42837, 42839, 42841, - 42843, 42845, 42847, 42849, 42851, 42853, 42855, 42857, - 42859, 42861, 42863, 42874, 42876, 7545, 42879, 42881, - 42883, 42885, 42887, 42892, 42897, 42899, 42903, 42905, - 42907, 42909, 42911, 42913, 42915, 42917, 42919, 42921, - 620, 670, 647, 43859, 42933, 42935, 42937, 42939, - 42941, 42943, 42947, 42900, 7566, 294, 43831, 43858, - 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, - 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, - 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, - 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, - 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, - 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, - 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, - 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, - 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, - 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, - 35912, 26356, 36040, 28369, 20018, 21477, 22865, 21895, - 22856, 25078, 30313, 32645, 34367, 34746, 35064, 37007, - 27138, 27931, 28889, 29662, 33853, 37226, 39409, 20098, - 21365, 27396, 29211, 34349, 40478, 23888, 28651, 34253, - 35172, 25289, 33240, 34847, 24266, 26391, 28010, 29436, - 37070, 20358, 20919, 21214, 25796, 27347, 29200, 30439, - 34310, 34396, 36335, 38706, 39791, 40442, 30860, 31103, - 32160, 33737, 37636, 35542, 22751, 24324, 31840, 32894, - 29282, 30922, 36034, 38647, 22744, 23650, 27155, 28122, - 28431, 32047, 32311, 38475, 21202, 32907, 20956, 20940, - 31260, 32190, 33777, 38517, 35712, 25295, 35582, 20025, - 23527, 24594, 29575, 30064, 21271, 30971, 20415, 24489, - 19981, 27852, 25976, 32034, 21443, 22622, 30465, 33865, - 35498, 27578, 27784, 25342, 33509, 25504, 30053, 20142, - 20841, 20937, 26753, 31975, 33391, 35538, 37327, 21237, - 21570, 24300, 26053, 28670, 31018, 38317, 39530, 40599, - 40654, 26310, 27511, 36706, 24180, 24976, 25088, 25754, - 28451, 29001, 29833, 31178, 32244, 32879, 36646, 34030, - 36899, 37706, 21015, 21155, 21693, 28872, 35010, 24265, - 24565, 25467, 27566, 31806, 29557, 20196, 22265, 23994, - 24604, 29618, 29801, 32666, 32838, 37428, 38646, 38728, - 38936, 20363, 31150, 37300, 38584, 24801, 20102, 20698, - 23534, 23615, 26009, 29134, 30274, 34044, 36988, 26248, - 38446, 21129, 26491, 26611, 27969, 28316, 29705, 30041, - 30827, 32016, 39006, 25134, 38520, 20523, 23833, 28138, - 36650, 24459, 24900, 26647, 38534, 21033, 21519, 23653, - 26131, 26446, 26792, 27877, 29702, 30178, 32633, 35023, - 35041, 38626, 21311, 28346, 21533, 29136, 29848, 34298, - 38563, 40023, 40607, 26519, 28107, 33256, 31520, 31890, - 29376, 28825, 35672, 20160, 33590, 21050, 20999, 24230, - 25299, 31958, 23429, 27934, 26292, 36667, 38477, 24275, - 20800, 21952, 22618, 26228, 20958, 29482, 30410, 31036, - 31070, 31077, 31119, 38742, 31934, 34322, 35576, 36920, - 37117, 39151, 39164, 39208, 40372, 37086, 38583, 20398, - 20711, 20813, 21193, 21220, 21329, 21917, 22022, 22120, - 22592, 22696, 23652, 24724, 24936, 24974, 25074, 25935, - 26082, 26257, 26757, 28023, 28186, 28450, 29038, 29227, - 29730, 30865, 31049, 31048, 31056, 31062, 31117, 31118, - 31296, 31361, 31680, 32265, 32321, 32626, 32773, 33261, - 33401, 33879, 35088, 35222, 35585, 35641, 36051, 36104, - 36790, 38627, 38911, 38971, 24693, 55376, 57070, 33304, - 20006, 20917, 20840, 20352, 20805, 20864, 21191, 21242, - 21845, 21913, 21986, 22707, 22852, 22868, 23138, 23336, - 24274, 24281, 24425, 24493, 24792, 24910, 24840, 24928, - 25140, 25540, 25628, 25682, 25942, 26395, 26454, 28379, - 28363, 28702, 30631, 29237, 29359, 29809, 29958, 30011, - 30237, 30239, 30427, 30452, 30538, 30528, 30924, 31409, - 31867, 32091, 32574, 33618, 33775, 34681, 35137, 35206, - 35519, 35531, 35565, 35722, 36664, 36978, 37273, 37494, - 38524, 38875, 38923, 39698, 55370, 56394, 55370, 56388, - 55372, 57301, 15261, 16408, 16441, 55380, 56905, 55383, - 56528, 55391, 57043, 40771, 40846, 102, 102, 102, - 105, 102, 108, 102, 102, 105, 102, 102, - 108, 383, 116, 115, 116, 1396, 1398, 1396, - 1381, 1396, 1387, 1406, 1398, 1396, 1389, 1497, + 12472, 12505, 12540, 12479, 3, 12509, 12452, 12531, + 12488, 12508, 12523, 12488, 12507, 12531, 12509, 12531, + 12489, 12507, 12540, 12523, 12507, 12540, 12531, 3, + 12510, 12452, 12463, 12525, 12510, 12452, 12523, 12510, + 12483, 12495, 12510, 12523, 12463, 4, 12510, 12531, + 12471, 12519, 12531, 3, 12511, 12463, 12525, 12531, + 12511, 12522, 4, 12511, 12522, 12496, 12540, 12523, + 12513, 12460, 3, 12513, 12460, 12488, 12531, 3, + 12513, 12540, 12488, 12523, 12516, 12540, 12489, 12516, + 12540, 12523, 12518, 12450, 12531, 3, 12522, 12483, + 12488, 12523, 12522, 12521, 12523, 12500, 12540, 3, + 12523, 12540, 12502, 12523, 12524, 12512, 4, 12524, + 12531, 12488, 12466, 12531, 12527, 12483, 12488, 48, + 28857, 49, 28857, 50, 28857, 51, 28857, 52, + 28857, 53, 28857, 54, 28857, 55, 28857, 56, + 28857, 57, 28857, 49, 48, 28857, 49, 49, + 28857, 49, 50, 28857, 49, 51, 28857, 49, + 52, 28857, 49, 53, 28857, 49, 54, 28857, + 49, 55, 28857, 49, 56, 28857, 49, 57, + 28857, 50, 48, 28857, 50, 49, 28857, 50, + 50, 28857, 50, 51, 28857, 50, 52, 28857, + 104, 80, 97, 100, 97, 65, 85, 98, + 97, 114, 111, 86, 112, 99, 100, 109, + 100, 109, 178, 100, 109, 179, 73, 85, + 24179, 25104, 26157, 21644, 22823, 27491, 26126, 27835, + 3, 26666, 24335, 20250, 31038, 112, 65, 110, + 65, 956, 65, 109, 65, 107, 65, 75, + 66, 77, 66, 71, 66, 99, 97, 108, + 3, 107, 99, 97, 108, 112, 70, 110, + 70, 956, 70, 956, 103, 109, 103, 107, + 103, 72, 122, 107, 72, 122, 77, 72, + 122, 71, 72, 122, 84, 72, 122, 956, + 8467, 109, 8467, 100, 8467, 107, 8467, 102, + 109, 110, 109, 956, 109, 109, 109, 99, + 109, 107, 109, 109, 109, 178, 99, 109, + 178, 109, 178, 107, 109, 178, 109, 109, + 179, 99, 109, 179, 109, 179, 107, 109, + 179, 109, 8725, 115, 3, 109, 8725, 115, + 178, 80, 97, 107, 80, 97, 77, 80, + 97, 71, 80, 97, 114, 97, 100, 4, + 114, 97, 100, 8725, 115, 5, 114, 97, + 100, 8725, 115, 178, 112, 115, 110, 115, + 956, 115, 109, 115, 112, 86, 110, 86, + 956, 86, 109, 86, 107, 86, 77, 86, + 112, 87, 110, 87, 956, 87, 109, 87, + 107, 87, 77, 87, 107, 937, 77, 937, + 3, 97, 46, 109, 46, 66, 113, 99, + 99, 99, 100, 3, 67, 8725, 107, 103, + 67, 111, 46, 100, 66, 71, 121, 104, + 97, 72, 80, 105, 110, 75, 75, 75, + 77, 107, 116, 108, 109, 108, 110, 108, + 111, 103, 108, 120, 109, 98, 109, 105, + 108, 109, 111, 108, 80, 72, 3, 112, + 46, 109, 46, 80, 80, 77, 80, 82, + 115, 114, 83, 118, 87, 98, 86, 8725, + 109, 65, 8725, 109, 49, 26085, 50, 26085, + 51, 26085, 52, 26085, 53, 26085, 54, 26085, + 55, 26085, 56, 26085, 57, 26085, 49, 48, + 26085, 49, 49, 26085, 49, 50, 26085, 49, + 51, 26085, 49, 52, 26085, 49, 53, 26085, + 49, 54, 26085, 49, 55, 26085, 49, 56, + 26085, 49, 57, 26085, 50, 48, 26085, 50, + 49, 26085, 50, 50, 26085, 50, 51, 26085, + 50, 52, 26085, 50, 53, 26085, 50, 54, + 26085, 50, 55, 26085, 50, 56, 26085, 50, + 57, 26085, 51, 48, 26085, 51, 49, 26085, + 103, 97, 108, 42561, 42560, 42563, 42562, 42565, + 42564, 42567, 42566, 42569, 42568, 42573, 42572, 42575, + 42574, 42577, 42576, 42579, 42578, 42581, 42580, 42583, + 42582, 42585, 42584, 42587, 42586, 42589, 42588, 42591, + 42590, 42593, 42592, 42595, 42594, 42597, 42596, 42599, + 42598, 42601, 42600, 42603, 42602, 42605, 42604, 42625, + 42624, 42627, 42626, 42629, 42628, 42631, 42630, 42633, + 42632, 42635, 42634, 42637, 42636, 42639, 42638, 42641, + 42640, 42643, 42642, 42645, 42644, 42647, 42646, 42649, + 42648, 42651, 42650, 42652, 42653, 42787, 42786, 42789, + 42788, 42791, 42790, 42793, 42792, 42795, 42794, 42797, + 42796, 42799, 42798, 42800, 42801, 42803, 42802, 42805, + 42804, 42807, 42806, 42809, 42808, 42811, 42810, 42813, + 42812, 42815, 42814, 42817, 42816, 42819, 42818, 42821, + 42820, 42823, 42822, 42825, 42824, 42827, 42826, 42829, + 42828, 42831, 42830, 42833, 42832, 42835, 42834, 42837, + 42836, 42839, 42838, 42841, 42840, 42843, 42842, 42845, + 42844, 42847, 42846, 42849, 42848, 42851, 42850, 42853, + 42852, 42855, 42854, 42857, 42856, 42859, 42858, 42861, + 42860, 42863, 42862, 42864, 42865, 42866, 42867, 42868, + 42869, 42870, 42871, 42872, 42874, 42873, 42876, 42875, + 7545, 42879, 42878, 42881, 42880, 42883, 42882, 42885, + 42884, 42887, 42886, 42892, 42891, 42894, 42897, 42896, + 42899, 42898, 42948, 42901, 42903, 42902, 42905, 42904, + 42907, 42906, 42909, 42908, 42911, 42910, 42913, 42912, + 42915, 42914, 42917, 42916, 42919, 42918, 42921, 42920, + 620, 42927, 670, 647, 43859, 42933, 42932, 42935, + 42934, 42937, 42936, 42939, 42938, 42941, 42940, 42943, + 42942, 42945, 42944, 42947, 42946, 42900, 7566, 42952, + 42951, 42954, 42953, 42961, 42960, 42963, 42965, 42967, + 42966, 42969, 42968, 42994, 42995, 42996, 42998, 42997, + 43000, 43001, 43002, 43824, 43825, 43826, 43827, 43828, + 43829, 43830, 43831, 43832, 43833, 43834, 43835, 43836, + 43837, 43838, 43839, 43840, 43841, 43842, 43843, 43844, + 43845, 43846, 43847, 43848, 43849, 43850, 43851, 43852, + 43853, 43854, 43855, 43856, 43857, 43858, 42931, 43860, + 43861, 43862, 43863, 43864, 43865, 43866, 43868, 43869, + 43870, 43871, 43872, 43873, 43874, 43875, 43876, 43877, + 43878, 43879, 43880, 43881, 5024, 5025, 5026, 5027, + 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, + 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, + 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, + 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, + 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, + 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, + 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, + 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, + 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, + 5100, 5101, 5102, 5103, 35912, 26356, 36040, 28369, + 20018, 21477, 22865, 21895, 22856, 25078, 30313, 32645, + 34367, 34746, 35064, 37007, 27138, 27931, 28889, 29662, + 33853, 37226, 39409, 20098, 21365, 27396, 29211, 34349, + 40478, 23888, 28651, 34253, 35172, 25289, 33240, 34847, + 24266, 26391, 28010, 29436, 37070, 20358, 20919, 21214, + 25796, 27347, 29200, 30439, 34310, 34396, 36335, 38706, + 39791, 40442, 30860, 31103, 32160, 33737, 37636, 35542, + 22751, 24324, 31840, 32894, 29282, 30922, 36034, 38647, + 22744, 23650, 27155, 28122, 28431, 32047, 32311, 38475, + 21202, 32907, 20956, 20940, 31260, 32190, 33777, 38517, + 35712, 25295, 35582, 20025, 23527, 24594, 29575, 30064, + 21271, 30971, 20415, 24489, 19981, 27852, 25976, 32034, + 21443, 22622, 30465, 33865, 35498, 27578, 27784, 25342, + 33509, 25504, 30053, 20142, 20841, 20937, 26753, 31975, + 33391, 35538, 37327, 21237, 21570, 24300, 26053, 28670, + 31018, 38317, 39530, 40599, 40654, 26310, 27511, 36706, + 24180, 24976, 25088, 25754, 28451, 29001, 29833, 31178, + 32244, 32879, 36646, 34030, 36899, 37706, 21015, 21155, + 21693, 28872, 35010, 24265, 24565, 25467, 27566, 31806, + 29557, 20196, 22265, 23994, 24604, 29618, 29801, 32666, + 32838, 37428, 38646, 38728, 38936, 20363, 31150, 37300, + 38584, 24801, 20102, 20698, 23534, 23615, 26009, 29134, + 30274, 34044, 36988, 26248, 38446, 21129, 26491, 26611, + 27969, 28316, 29705, 30041, 30827, 32016, 39006, 25134, + 38520, 20523, 23833, 28138, 36650, 24459, 24900, 26647, + 38534, 21033, 21519, 23653, 26131, 26446, 26792, 27877, + 29702, 30178, 32633, 35023, 35041, 38626, 21311, 28346, + 21533, 29136, 29848, 34298, 38563, 40023, 40607, 26519, + 28107, 33256, 31520, 31890, 29376, 28825, 35672, 20160, + 33590, 21050, 20999, 24230, 25299, 31958, 23429, 27934, + 26292, 36667, 38477, 24275, 20800, 21952, 22618, 26228, + 20958, 29482, 30410, 31036, 31070, 31077, 31119, 38742, + 31934, 34322, 35576, 36920, 37117, 39151, 39164, 39208, + 40372, 37086, 38583, 20398, 20711, 20813, 21193, 21220, + 21329, 21917, 22022, 22120, 22592, 22696, 23652, 24724, + 24936, 24974, 25074, 25935, 26082, 26257, 26757, 28023, + 28186, 28450, 29038, 29227, 29730, 30865, 31049, 31048, + 31056, 31062, 31117, 31118, 31296, 31361, 31680, 32265, + 32321, 32626, 32773, 33261, 33401, 33879, 35088, 35222, + 35585, 35641, 36051, 36104, 36790, 38627, 38911, 38971, + 24693, 55376, 57070, 33304, 20006, 20917, 20840, 20352, + 20805, 20864, 21191, 21242, 21845, 21913, 21986, 22707, + 22852, 22868, 23138, 23336, 24274, 24281, 24425, 24493, + 24792, 24910, 24840, 24928, 25140, 25540, 25628, 25682, + 25942, 26395, 26454, 28379, 28363, 28702, 30631, 29237, + 29359, 29809, 29958, 30011, 30237, 30239, 30427, 30452, + 30538, 30528, 30924, 31409, 31867, 32091, 32574, 33618, + 33775, 34681, 35137, 35206, 35519, 35531, 35565, 35722, + 36664, 36978, 37273, 37494, 38524, 38875, 38923, 39698, + 55370, 56394, 55370, 56388, 55372, 57301, 15261, 16408, + 16441, 55380, 56905, 55383, 56528, 55391, 57043, 40771, + 40846, 102, 102, 64256, 102, 105, 64257, 102, + 108, 64258, 102, 102, 105, 64259, 102, 102, + 108, 64260, 383, 116, 115, 116, 64261, 64262, + 1396, 1398, 64275, 1396, 1381, 64276, 1396, 1387, + 64277, 1406, 1398, 64278, 1396, 1389, 64279, 1497, 1460, 1522, 1463, 1506, 1492, 1499, 1500, 1501, 1512, 1514, 1513, 1473, 1513, 1474, 64329, 1473, 64329, 1474, 1488, 1463, 1488, 1464, 1488, 1468, @@ -804,14 +1012,15 @@ static const utf8proc_uint16_t utf8proc_sequences[] = { 1581, 1610, 1581, 1580, 1610, 1605, 1580, 1610, 1601, 1605, 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606, 1580, 1610, 1589, 1604, 1746, 1602, - 1604, 1746, 1575, 1604, 1604, 1607, 1575, 1603, - 1576, 1585, 1605, 1581, 1605, 1583, 1589, 1604, - 1593, 1605, 1585, 1587, 1608, 1604, 1593, 1604, - 1610, 1607, 1608, 1587, 1604, 1605, 1589, 1604, - 1609, 17, 1589, 1604, 1609, 32, 1575, 1604, - 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, - 1608, 1587, 1604, 1605, 7, 1580, 1604, 32, - 1580, 1604, 1575, 1604, 1607, 1585, 1740, 1575, + 1604, 1746, 3, 1575, 1604, 1604, 1607, 3, + 1575, 1603, 1576, 1585, 3, 1605, 1581, 1605, + 1583, 3, 1589, 1604, 1593, 1605, 3, 1585, + 1587, 1608, 1604, 3, 1593, 1604, 1610, 1607, + 3, 1608, 1587, 1604, 1605, 1589, 1604, 1609, + 17, 1589, 1604, 1609, 32, 1575, 1604, 1604, + 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, + 1587, 1604, 1605, 7, 1580, 1604, 32, 1580, + 1604, 1575, 1604, 1607, 3, 1585, 1740, 1575, 1604, 44, 12289, 12290, 58, 33, 63, 12310, 12311, 8230, 8229, 8212, 8211, 95, 123, 125, 12308, 12309, 12304, 12305, 12298, 12299, 12300, 12301, @@ -829,326 +1038,31 @@ static const utf8proc_uint16_t utf8proc_sequences[] = { 47, 65345, 65346, 65347, 65348, 65349, 65350, 65351, 65352, 65353, 65354, 65355, 65356, 65357, 65358, 65359, 65360, 65361, 65362, 65363, 65364, 65365, 65366, 65367, - 65368, 65369, 65370, 94, 124, 126, 10629, 10630, - 12539, 12449, 12451, 12453, 12455, 12457, 12515, 12517, - 12519, 12483, 12540, 12531, 12441, 12442, 12644, 12593, - 12594, 12595, 12596, 12597, 12598, 12599, 12600, 12601, - 12602, 12603, 12604, 12605, 12606, 12607, 12608, 12609, - 12610, 12611, 12612, 12613, 12614, 12615, 12616, 12617, - 12618, 12619, 12620, 12621, 12622, 12623, 12624, 12625, - 12626, 12627, 12628, 12629, 12630, 12631, 12632, 12633, - 12634, 12635, 12636, 12637, 12638, 12639, 12640, 12641, - 12642, 12643, 162, 163, 172, 175, 166, 165, - 8361, 9474, 8592, 8593, 8594, 8595, 9632, 9675, - 55297, 56360, 55297, 56361, 55297, 56362, 55297, 56363, - 55297, 56364, 55297, 56365, 55297, 56366, 55297, 56367, - 55297, 56368, 55297, 56369, 55297, 56370, 55297, 56371, - 55297, 56372, 55297, 56373, 55297, 56374, 55297, 56375, - 55297, 56376, 55297, 56377, 55297, 56378, 55297, 56379, - 55297, 56380, 55297, 56381, 55297, 56382, 55297, 56383, - 55297, 56384, 55297, 56385, 55297, 56386, 55297, 56387, - 55297, 56388, 55297, 56389, 55297, 56390, 55297, 56391, - 55297, 56392, 55297, 56393, 55297, 56394, 55297, 56395, - 55297, 56396, 55297, 56397, 55297, 56398, 55297, 56399, - 55297, 56536, 55297, 56537, 55297, 56538, 55297, 56539, - 55297, 56540, 55297, 56541, 55297, 56542, 55297, 56543, - 55297, 56544, 55297, 56545, 55297, 56546, 55297, 56547, - 55297, 56548, 55297, 56549, 55297, 56550, 55297, 56551, - 55297, 56552, 55297, 56553, 55297, 56554, 55297, 56555, - 55297, 56556, 55297, 56557, 55297, 56558, 55297, 56559, - 55297, 56560, 55297, 56561, 55297, 56562, 55297, 56563, - 55297, 56564, 55297, 56565, 55297, 56566, 55297, 56567, - 55297, 56568, 55297, 56569, 55297, 56570, 55297, 56571, - 55299, 56512, 55299, 56513, 55299, 56514, 55299, 56515, - 55299, 56516, 55299, 56517, 55299, 56518, 55299, 56519, - 55299, 56520, 55299, 56521, 55299, 56522, 55299, 56523, - 55299, 56524, 55299, 56525, 55299, 56526, 55299, 56527, - 55299, 56528, 55299, 56529, 55299, 56530, 55299, 56531, - 55299, 56532, 55299, 56533, 55299, 56534, 55299, 56535, - 55299, 56536, 55299, 56537, 55299, 56538, 55299, 56539, - 55299, 56540, 55299, 56541, 55299, 56542, 55299, 56543, - 55299, 56544, 55299, 56545, 55299, 56546, 55299, 56547, - 55299, 56548, 55299, 56549, 55299, 56550, 55299, 56551, - 55299, 56552, 55299, 56553, 55299, 56554, 55299, 56555, - 55299, 56556, 55299, 56557, 55299, 56558, 55299, 56559, - 55299, 56560, 55299, 56561, 55299, 56562, 55300, 56473, - 55300, 56506, 55300, 56475, 55300, 56506, 55300, 56485, - 55300, 56506, 55300, 56625, 55300, 56615, 55300, 56626, - 55300, 56615, 55300, 57159, 55300, 57150, 55300, 57159, - 55300, 57175, 55301, 56505, 55301, 56506, 55301, 56505, - 55301, 56496, 55301, 56505, 55301, 56509, 55301, 56760, - 55301, 56751, 55301, 56761, 55301, 56751, 55302, 56512, - 55302, 56513, 55302, 56514, 55302, 56515, 55302, 56516, - 55302, 56517, 55302, 56518, 55302, 56519, 55302, 56520, - 55302, 56521, 55302, 56522, 55302, 56523, 55302, 56524, - 55302, 56525, 55302, 56526, 55302, 56527, 55302, 56528, - 55302, 56529, 55302, 56530, 55302, 56531, 55302, 56532, - 55302, 56533, 55302, 56534, 55302, 56535, 55302, 56536, - 55302, 56537, 55302, 56538, 55302, 56539, 55302, 56540, - 55302, 56541, 55302, 56542, 55302, 56543, 55323, 56928, - 55323, 56929, 55323, 56930, 55323, 56931, 55323, 56932, - 55323, 56933, 55323, 56934, 55323, 56935, 55323, 56936, - 55323, 56937, 55323, 56938, 55323, 56939, 55323, 56940, - 55323, 56941, 55323, 56942, 55323, 56943, 55323, 56944, - 55323, 56945, 55323, 56946, 55323, 56947, 55323, 56948, - 55323, 56949, 55323, 56950, 55323, 56951, 55323, 56952, - 55323, 56953, 55323, 56954, 55323, 56955, 55323, 56956, - 55323, 56957, 55323, 56958, 55323, 56959, 55348, 56663, - 55348, 56677, 55348, 56664, 55348, 56677, 55348, 56671, - 55348, 56686, 55348, 56671, 55348, 56687, 55348, 56671, - 55348, 56688, 55348, 56671, 55348, 56689, 55348, 56671, - 55348, 56690, 55348, 56761, 55348, 56677, 55348, 56762, - 55348, 56677, 55348, 56763, 55348, 56686, 55348, 56764, - 55348, 56686, 55348, 56763, 55348, 56687, 55348, 56764, - 55348, 56687, 305, 567, 913, 914, 916, 917, - 918, 919, 921, 922, 923, 924, 925, 926, - 927, 929, 1012, 932, 934, 935, 936, 8711, - 8706, 1013, 977, 1008, 981, 1009, 982, 988, - 55354, 56610, 55354, 56611, 55354, 56612, 55354, 56613, - 55354, 56614, 55354, 56615, 55354, 56616, 55354, 56617, - 55354, 56618, 55354, 56619, 55354, 56620, 55354, 56621, - 55354, 56622, 55354, 56623, 55354, 56624, 55354, 56625, - 55354, 56626, 55354, 56627, 55354, 56628, 55354, 56629, - 55354, 56630, 55354, 56631, 55354, 56632, 55354, 56633, - 55354, 56634, 55354, 56635, 55354, 56636, 55354, 56637, - 55354, 56638, 55354, 56639, 55354, 56640, 55354, 56641, - 55354, 56642, 55354, 56643, 1646, 1697, 1647, 48, - 46, 48, 44, 49, 44, 50, 44, 51, - 44, 52, 44, 53, 44, 54, 44, 55, - 44, 56, 44, 57, 44, 40, 65, 41, - 40, 66, 41, 40, 67, 41, 40, 68, - 41, 40, 69, 41, 40, 70, 41, 40, - 71, 41, 40, 72, 41, 40, 73, 41, - 40, 74, 41, 40, 75, 41, 40, 76, - 41, 40, 77, 41, 40, 78, 41, 40, - 79, 41, 40, 80, 41, 40, 81, 41, - 40, 82, 41, 40, 83, 41, 40, 84, - 41, 40, 85, 41, 40, 86, 41, 40, - 87, 41, 40, 88, 41, 40, 89, 41, - 40, 90, 41, 12308, 83, 12309, 67, 68, - 87, 90, 72, 86, 83, 68, 83, 83, - 80, 80, 86, 87, 67, 77, 67, 77, - 68, 77, 82, 68, 74, 12411, 12363, 12467, - 12467, 23383, 21452, 12487, 22810, 35299, 20132, 26144, - 28961, 21069, 24460, 20877, 26032, 21021, 32066, 36009, - 22768, 21561, 28436, 25237, 25429, 36938, 25351, 25171, - 31105, 31354, 21512, 28288, 30003, 21106, 21942, 37197, - 12308, 26412, 12309, 12308, 19977, 12309, 12308, 20108, - 12309, 12308, 23433, 12309, 12308, 28857, 12309, 12308, - 25171, 12309, 12308, 30423, 12309, 12308, 21213, 12309, - 12308, 25943, 12309, 24471, 21487, 20029, 20024, 20033, - 55360, 56610, 20320, 20411, 20482, 20602, 20633, 20687, - 13470, 55361, 56890, 20820, 20836, 20855, 55361, 56604, - 13497, 20839, 55361, 56651, 20887, 20900, 20172, 20908, - 55396, 56799, 20995, 13535, 21051, 21062, 21111, 13589, - 21253, 21254, 21321, 21338, 21363, 21373, 21375, 55362, - 56876, 28784, 21450, 21471, 55362, 57187, 21483, 21489, - 21510, 21662, 21560, 21576, 21608, 21666, 21750, 21776, - 21843, 21859, 21892, 21931, 21939, 21954, 22294, 22295, - 22097, 22132, 22766, 22478, 22516, 22541, 22411, 22578, - 22577, 22700, 55365, 56548, 22770, 22775, 22790, 22818, - 22882, 55365, 57000, 55365, 57066, 23020, 23067, 23079, - 23000, 23142, 14062, 14076, 23304, 23358, 55366, 56776, - 23491, 23512, 23539, 55366, 57112, 23551, 23558, 24403, - 14209, 23648, 23744, 23693, 55367, 56804, 23875, 55367, - 56806, 23918, 23915, 23932, 24033, 24034, 14383, 24061, - 24104, 24125, 24169, 14434, 55368, 56707, 14460, 24240, - 24243, 24246, 55400, 57234, 55368, 57137, 33281, 24354, - 14535, 55372, 57016, 55384, 56794, 24418, 24427, 14563, - 24474, 24525, 24535, 24569, 24705, 14650, 14620, 55369, - 57044, 24775, 24904, 24908, 24954, 25010, 24996, 25007, - 25054, 25104, 25115, 25181, 25265, 25300, 25424, 55370, - 57100, 25405, 25340, 25448, 25475, 25572, 55370, 57329, - 25634, 25541, 25513, 14894, 25705, 25726, 25757, 25719, - 14956, 25964, 55372, 56330, 26083, 26360, 26185, 15129, - 15112, 15076, 20882, 20885, 26368, 26268, 32941, 17369, - 26401, 26462, 26451, 55372, 57283, 15177, 26618, 26501, - 26706, 55373, 56429, 26766, 26655, 26900, 26946, 27043, - 27114, 27304, 55373, 56995, 27355, 15384, 27425, 55374, - 56487, 27476, 15438, 27506, 27551, 27579, 55374, 56973, - 55367, 56587, 55374, 57082, 27726, 55375, 56508, 27839, - 27853, 27751, 27926, 27966, 28009, 28024, 28037, 55375, - 56606, 27956, 28207, 28270, 15667, 28359, 55375, 57041, - 28153, 28526, 55375, 57182, 55375, 57230, 28614, 28729, - 28699, 15766, 28746, 28797, 28791, 28845, 55361, 56613, - 28997, 55376, 56931, 29084, 55376, 57259, 29224, 29264, - 55377, 56840, 29312, 29333, 55377, 57141, 55378, 56340, - 29562, 29579, 16044, 29605, 16056, 29767, 29788, 29829, - 29898, 16155, 29988, 55379, 56374, 30014, 55379, 56466, - 55368, 56735, 30224, 55379, 57249, 55379, 57272, 55380, - 56388, 16380, 16392, 55380, 56563, 55380, 56562, 55380, - 56601, 55380, 56627, 30494, 30495, 30603, 16454, 16534, - 55381, 56349, 30798, 16611, 55381, 56870, 55381, 56986, - 55381, 57029, 31211, 16687, 31306, 31311, 55382, 56700, - 55382, 56999, 31470, 16898, 55382, 57259, 31686, 31689, - 16935, 55383, 56448, 31954, 17056, 31976, 31971, 32000, - 55383, 57222, 32099, 17153, 32199, 32258, 32325, 17204, - 55384, 56872, 55384, 56903, 17241, 55384, 57049, 32634, - 55384, 57150, 32661, 32762, 55385, 56538, 55385, 56611, - 32864, 55385, 56744, 32880, 55372, 57183, 17365, 32946, - 33027, 17419, 33086, 23221, 55385, 57255, 55385, 57269, - 55372, 57235, 55372, 57244, 33284, 36766, 17515, 33425, - 33419, 33437, 21171, 33457, 33459, 33469, 33510, 55386, - 57148, 33565, 33635, 33709, 33571, 33725, 33767, 33619, - 33738, 33740, 33756, 55387, 56374, 55387, 56683, 55387, - 56533, 17707, 34033, 34035, 34070, 55388, 57290, 34148, - 55387, 57132, 17757, 17761, 55387, 57265, 55388, 56530, - 17771, 34384, 34407, 34409, 34473, 34440, 34574, 34530, - 34600, 34667, 34694, 17879, 34785, 34817, 17913, 34912, - 55389, 56935, 35031, 35038, 17973, 35066, 13499, 55390, - 56494, 55390, 56678, 18110, 18119, 35488, 55391, 56488, - 36011, 36033, 36123, 36215, 55391, 57135, 55362, 56324, - 36299, 36284, 36336, 55362, 56542, 36564, 55393, 56786, - 55393, 56813, 37012, 37105, 37137, 55393, 57134, 37147, - 37432, 37591, 37592, 37500, 37881, 37909, 55394, 57338, - 38283, 18837, 38327, 55395, 56695, 18918, 38595, 23986, - 38691, 55396, 56645, 55396, 56858, 19054, 19062, 38880, - 55397, 56330, 19122, 55397, 56470, 38953, 55397, 56758, - 39138, 19251, 39209, 39335, 39362, 39422, 19406, 55398, - 57136, 40000, 40189, 19662, 19693, 40295, 55400, 56526, - 19704, 55400, 56581, 55400, 56846, 55400, 56977, 19798, - 40702, 40709, 40719, 40726, 55401, 56832, 7838, 192, - 193, 194, 195, 196, 199, 200, 201, 202, - 203, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, 214, 216, 217, 218, 219, - 220, 221, 222, 376, 256, 258, 260, 262, - 264, 266, 268, 270, 272, 274, 276, 278, - 280, 282, 284, 286, 288, 290, 292, 296, - 298, 300, 302, 306, 308, 310, 313, 315, - 317, 319, 321, 323, 325, 327, 330, 332, - 334, 336, 338, 340, 342, 344, 346, 348, - 350, 352, 354, 356, 358, 360, 362, 364, - 366, 368, 370, 372, 374, 377, 379, 381, - 579, 386, 388, 391, 395, 401, 502, 408, - 573, 544, 416, 418, 420, 423, 428, 431, - 435, 437, 440, 444, 503, 453, 452, 456, - 455, 459, 458, 461, 463, 465, 467, 469, - 471, 473, 475, 478, 480, 482, 484, 486, - 488, 490, 492, 494, 498, 497, 500, 504, - 506, 508, 510, 512, 514, 516, 518, 520, - 522, 524, 526, 528, 530, 532, 534, 536, - 538, 540, 542, 548, 550, 552, 554, 556, - 558, 560, 562, 571, 11390, 11391, 577, 582, - 584, 586, 588, 590, 11375, 11373, 11376, 385, - 390, 393, 394, 399, 42923, 403, 42924, 404, - 42893, 42922, 407, 406, 42926, 11362, 42925, 412, - 11374, 413, 415, 11364, 422, 42949, 425, 42929, - 430, 580, 433, 434, 581, 439, 42930, 42928, - 880, 882, 886, 1021, 1022, 1023, 938, 939, - 975, 984, 986, 990, 992, 994, 996, 998, - 1000, 1002, 1004, 1006, 1017, 895, 1015, 1018, - 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, - 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, - 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, - 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, - 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, - 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, - 1120, 1122, 1124, 1126, 1128, 1130, 1132, 1134, - 1136, 1138, 1140, 1142, 1144, 1146, 1148, 1150, - 1152, 1162, 1164, 1166, 1168, 1170, 1172, 1174, - 1176, 1178, 1180, 1182, 1184, 1186, 1188, 1190, - 1192, 1194, 1196, 1198, 1200, 1202, 1204, 1206, - 1208, 1210, 1212, 1214, 1217, 1219, 1221, 1223, - 1225, 1227, 1229, 1216, 1232, 1234, 1236, 1238, - 1240, 1242, 1244, 1246, 1248, 1250, 1252, 1254, - 1256, 1258, 1260, 1262, 1264, 1266, 1268, 1270, - 1272, 1274, 1276, 1278, 1280, 1282, 1284, 1286, - 1288, 1290, 1292, 1294, 1296, 1298, 1300, 1302, - 1304, 1306, 1308, 1310, 1312, 1314, 1316, 1318, - 1320, 1322, 1324, 1326, 1329, 1330, 1331, 1332, - 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, - 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, - 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, - 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, - 1365, 1366, 7312, 7313, 7314, 7315, 7316, 7317, - 7318, 7319, 7320, 7321, 7322, 7323, 7324, 7325, - 7326, 7327, 7328, 7329, 7330, 7331, 7332, 7333, - 7334, 7335, 7336, 7337, 7338, 7339, 7340, 7341, - 7342, 7343, 7344, 7345, 7346, 7347, 7348, 7349, - 7350, 7351, 7352, 7353, 7354, 7357, 7358, 7359, - 43888, 43889, 43890, 43891, 43892, 43893, 43894, 43895, - 43896, 43897, 43898, 43899, 43900, 43901, 43902, 43903, - 43904, 43905, 43906, 43907, 43908, 43909, 43910, 43911, - 43912, 43913, 43914, 43915, 43916, 43917, 43918, 43919, - 43920, 43921, 43922, 43923, 43924, 43925, 43926, 43927, - 43928, 43929, 43930, 43931, 43932, 43933, 43934, 43935, - 43936, 43937, 43938, 43939, 43940, 43941, 43942, 43943, - 43944, 43945, 43946, 43947, 43948, 43949, 43950, 43951, - 43952, 43953, 43954, 43955, 43956, 43957, 43958, 43959, - 43960, 43961, 43962, 43963, 43964, 43965, 43966, 43967, - 5112, 5113, 5114, 5115, 5116, 5117, 42570, 42877, - 11363, 42950, 7680, 7682, 7684, 7686, 7688, 7690, - 7692, 7694, 7696, 7698, 7700, 7702, 7704, 7706, - 7708, 7710, 7712, 7714, 7716, 7718, 7720, 7722, - 7724, 7726, 7728, 7730, 7732, 7734, 7736, 7738, - 7740, 7742, 7744, 7746, 7748, 7750, 7752, 7754, - 7756, 7758, 7760, 7762, 7764, 7766, 7768, 7770, - 7772, 7774, 7776, 7778, 7780, 7782, 7784, 7786, - 7788, 7790, 7792, 7794, 7796, 7798, 7800, 7802, - 7804, 7806, 7808, 7810, 7812, 7814, 7816, 7818, - 7820, 7822, 7824, 7826, 7828, 223, 7840, 7842, - 7844, 7846, 7848, 7850, 7852, 7854, 7856, 7858, - 7860, 7862, 7864, 7866, 7868, 7870, 7872, 7874, - 7876, 7878, 7880, 7882, 7884, 7886, 7888, 7890, - 7892, 7894, 7896, 7898, 7900, 7902, 7904, 7906, - 7908, 7910, 7912, 7914, 7916, 7918, 7920, 7922, - 7924, 7926, 7928, 7930, 7932, 7934, 7944, 7945, - 7946, 7947, 7948, 7949, 7950, 7951, 7960, 7961, - 7962, 7963, 7964, 7965, 7976, 7977, 7978, 7979, - 7980, 7981, 7982, 7983, 7992, 7993, 7994, 7995, - 7996, 7997, 7998, 7999, 8008, 8009, 8010, 8011, - 8012, 8013, 8025, 8027, 8029, 8031, 8040, 8041, - 8042, 8043, 8044, 8045, 8046, 8047, 8122, 8123, - 8136, 8137, 8138, 8139, 8154, 8155, 8184, 8185, - 8170, 8171, 8186, 8187, 8072, 8073, 8074, 8075, - 8076, 8077, 8078, 8079, 8064, 8065, 8066, 8067, - 8068, 8069, 8070, 8071, 8088, 8089, 8090, 8091, - 8092, 8093, 8094, 8095, 8080, 8081, 8082, 8083, - 8084, 8085, 8086, 8087, 8104, 8105, 8106, 8107, - 8108, 8109, 8110, 8111, 8096, 8097, 8098, 8099, - 8100, 8101, 8102, 8103, 8120, 8121, 8124, 8115, - 8140, 8131, 8152, 8153, 8168, 8169, 8172, 8188, - 8179, 8498, 8544, 8545, 8546, 8547, 8548, 8549, - 8550, 8551, 8552, 8553, 8554, 8555, 8556, 8557, - 8558, 8559, 8579, 9398, 9399, 9400, 9401, 9402, - 9403, 9404, 9405, 9406, 9407, 9408, 9409, 9410, - 9411, 9412, 9413, 9414, 9415, 9416, 9417, 9418, - 9419, 9420, 9421, 9422, 9423, 11264, 11265, 11266, - 11267, 11268, 11269, 11270, 11271, 11272, 11273, 11274, - 11275, 11276, 11277, 11278, 11279, 11280, 11281, 11282, - 11283, 11284, 11285, 11286, 11287, 11288, 11289, 11290, - 11291, 11292, 11293, 11294, 11295, 11296, 11297, 11298, - 11299, 11300, 11301, 11302, 11303, 11304, 11305, 11306, - 11307, 11308, 11309, 11310, 11360, 570, 574, 11367, - 11369, 11371, 11378, 11381, 11392, 11394, 11396, 11398, - 11400, 11402, 11404, 11406, 11408, 11410, 11412, 11414, - 11416, 11418, 11420, 11422, 11424, 11426, 11428, 11430, - 11432, 11434, 11436, 11438, 11440, 11442, 11444, 11446, - 11448, 11450, 11452, 11454, 11456, 11458, 11460, 11462, - 11464, 11466, 11468, 11470, 11472, 11474, 11476, 11478, - 11480, 11482, 11484, 11486, 11488, 11490, 11499, 11501, - 11506, 4256, 4257, 4258, 4259, 4260, 4261, 4262, - 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, - 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, - 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, - 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4295, - 4301, 42560, 42562, 42564, 42566, 42568, 42572, 42574, - 42576, 42578, 42580, 42582, 42584, 42586, 42588, 42590, - 42592, 42594, 42596, 42598, 42600, 42602, 42604, 42624, - 42626, 42628, 42630, 42632, 42634, 42636, 42638, 42640, - 42642, 42644, 42646, 42648, 42650, 42786, 42788, 42790, - 42792, 42794, 42796, 42798, 42802, 42804, 42806, 42808, - 42810, 42812, 42814, 42816, 42818, 42820, 42822, 42824, - 42826, 42828, 42830, 42832, 42834, 42836, 42838, 42840, - 42842, 42844, 42846, 42848, 42850, 42852, 42854, 42856, - 42858, 42860, 42862, 42873, 42875, 42878, 42880, 42882, - 42884, 42886, 42891, 42896, 42898, 42948, 42902, 42904, - 42906, 42908, 42910, 42912, 42914, 42916, 42918, 42920, - 42932, 42934, 42936, 42938, 42940, 42942, 42946, 42931, - 65313, 65314, 65315, 65316, 65317, 65318, 65319, 65320, - 65321, 65322, 65323, 65324, 65325, 65326, 65327, 65328, - 65329, 65330, 65331, 65332, 65333, 65334, 65335, 65336, - 65337, 65338, 55297, 56320, 55297, 56321, 55297, 56322, + 65368, 65369, 65370, 94, 65313, 65314, 65315, 65316, + 65317, 65318, 65319, 65320, 65321, 65322, 65323, 65324, + 65325, 65326, 65327, 65328, 65329, 65330, 65331, 65332, + 65333, 65334, 65335, 65336, 65337, 65338, 124, 126, + 10629, 10630, 12539, 12449, 12451, 12453, 12455, 12457, + 12515, 12517, 12519, 12483, 12540, 12531, 12441, 12442, + 12644, 12593, 12594, 12595, 12596, 12597, 12598, 12599, + 12600, 12601, 12602, 12603, 12604, 12605, 12606, 12607, + 12608, 12609, 12610, 12611, 12612, 12613, 12614, 12615, + 12616, 12617, 12618, 12619, 12620, 12621, 12622, 12623, + 12624, 12625, 12626, 12627, 12628, 12629, 12630, 12631, + 12632, 12633, 12634, 12635, 12636, 12637, 12638, 12639, + 12640, 12641, 12642, 12643, 162, 163, 172, 175, + 166, 165, 8361, 9474, 8592, 8593, 8594, 8595, + 9632, 9675, 55297, 56360, 55297, 56361, 55297, 56362, + 55297, 56363, 55297, 56364, 55297, 56365, 55297, 56366, + 55297, 56367, 55297, 56368, 55297, 56369, 55297, 56370, + 55297, 56371, 55297, 56372, 55297, 56373, 55297, 56374, + 55297, 56375, 55297, 56376, 55297, 56377, 55297, 56378, + 55297, 56379, 55297, 56380, 55297, 56381, 55297, 56382, + 55297, 56383, 55297, 56384, 55297, 56385, 55297, 56386, + 55297, 56387, 55297, 56388, 55297, 56389, 55297, 56390, + 55297, 56391, 55297, 56392, 55297, 56393, 55297, 56394, + 55297, 56395, 55297, 56396, 55297, 56397, 55297, 56398, + 55297, 56399, 55297, 56320, 55297, 56321, 55297, 56322, 55297, 56323, 55297, 56324, 55297, 56325, 55297, 56326, 55297, 56327, 55297, 56328, 55297, 56329, 55297, 56330, 55297, 56331, 55297, 56332, 55297, 56333, 55297, 56334, @@ -1158,7 +1072,16 @@ static const utf8proc_uint16_t utf8proc_sequences[] = { 55297, 56347, 55297, 56348, 55297, 56349, 55297, 56350, 55297, 56351, 55297, 56352, 55297, 56353, 55297, 56354, 55297, 56355, 55297, 56356, 55297, 56357, 55297, 56358, - 55297, 56359, 55297, 56496, 55297, 56497, 55297, 56498, + 55297, 56359, 55297, 56536, 55297, 56537, 55297, 56538, + 55297, 56539, 55297, 56540, 55297, 56541, 55297, 56542, + 55297, 56543, 55297, 56544, 55297, 56545, 55297, 56546, + 55297, 56547, 55297, 56548, 55297, 56549, 55297, 56550, + 55297, 56551, 55297, 56552, 55297, 56553, 55297, 56554, + 55297, 56555, 55297, 56556, 55297, 56557, 55297, 56558, + 55297, 56559, 55297, 56560, 55297, 56561, 55297, 56562, + 55297, 56563, 55297, 56564, 55297, 56565, 55297, 56566, + 55297, 56567, 55297, 56568, 55297, 56569, 55297, 56570, + 55297, 56571, 55297, 56496, 55297, 56497, 55297, 56498, 55297, 56499, 55297, 56500, 55297, 56501, 55297, 56502, 55297, 56503, 55297, 56504, 55297, 56505, 55297, 56506, 55297, 56507, 55297, 56508, 55297, 56509, 55297, 56510, @@ -1167,44 +1090,501 @@ static const utf8proc_uint16_t utf8proc_sequences[] = { 55297, 56519, 55297, 56520, 55297, 56521, 55297, 56522, 55297, 56523, 55297, 56524, 55297, 56525, 55297, 56526, 55297, 56527, 55297, 56528, 55297, 56529, 55297, 56530, - 55297, 56531, 55299, 56448, 55299, 56449, 55299, 56450, - 55299, 56451, 55299, 56452, 55299, 56453, 55299, 56454, - 55299, 56455, 55299, 56456, 55299, 56457, 55299, 56458, - 55299, 56459, 55299, 56460, 55299, 56461, 55299, 56462, - 55299, 56463, 55299, 56464, 55299, 56465, 55299, 56466, - 55299, 56467, 55299, 56468, 55299, 56469, 55299, 56470, - 55299, 56471, 55299, 56472, 55299, 56473, 55299, 56474, - 55299, 56475, 55299, 56476, 55299, 56477, 55299, 56478, - 55299, 56479, 55299, 56480, 55299, 56481, 55299, 56482, - 55299, 56483, 55299, 56484, 55299, 56485, 55299, 56486, - 55299, 56487, 55299, 56488, 55299, 56489, 55299, 56490, - 55299, 56491, 55299, 56492, 55299, 56493, 55299, 56494, - 55299, 56495, 55299, 56496, 55299, 56497, 55299, 56498, - 55302, 56480, 55302, 56481, 55302, 56482, 55302, 56483, - 55302, 56484, 55302, 56485, 55302, 56486, 55302, 56487, - 55302, 56488, 55302, 56489, 55302, 56490, 55302, 56491, - 55302, 56492, 55302, 56493, 55302, 56494, 55302, 56495, - 55302, 56496, 55302, 56497, 55302, 56498, 55302, 56499, - 55302, 56500, 55302, 56501, 55302, 56502, 55302, 56503, - 55302, 56504, 55302, 56505, 55302, 56506, 55302, 56507, - 55302, 56508, 55302, 56509, 55302, 56510, 55302, 56511, - 55323, 56896, 55323, 56897, 55323, 56898, 55323, 56899, - 55323, 56900, 55323, 56901, 55323, 56902, 55323, 56903, - 55323, 56904, 55323, 56905, 55323, 56906, 55323, 56907, - 55323, 56908, 55323, 56909, 55323, 56910, 55323, 56911, - 55323, 56912, 55323, 56913, 55323, 56914, 55323, 56915, - 55323, 56916, 55323, 56917, 55323, 56918, 55323, 56919, - 55323, 56920, 55323, 56921, 55323, 56922, 55323, 56923, - 55323, 56924, 55323, 56925, 55323, 56926, 55323, 56927, - 55354, 56576, 55354, 56577, 55354, 56578, 55354, 56579, - 55354, 56580, 55354, 56581, 55354, 56582, 55354, 56583, - 55354, 56584, 55354, 56585, 55354, 56586, 55354, 56587, - 55354, 56588, 55354, 56589, 55354, 56590, 55354, 56591, - 55354, 56592, 55354, 56593, 55354, 56594, 55354, 56595, - 55354, 56596, 55354, 56597, 55354, 56598, 55354, 56599, - 55354, 56600, 55354, 56601, 55354, 56602, 55354, 56603, - 55354, 56604, 55354, 56605, 55354, 56606, 55354, 56607, - 55354, 56608, 55354, 56609, }; + 55297, 56531, 55297, 56727, 55297, 56728, 55297, 56729, + 55297, 56730, 55297, 56731, 55297, 56732, 55297, 56733, + 55297, 56734, 55297, 56735, 55297, 56736, 55297, 56737, + 55297, 56739, 55297, 56740, 55297, 56741, 55297, 56742, + 55297, 56743, 55297, 56744, 55297, 56745, 55297, 56746, + 55297, 56747, 55297, 56748, 55297, 56749, 55297, 56750, + 55297, 56751, 55297, 56752, 55297, 56753, 55297, 56755, + 55297, 56756, 55297, 56757, 55297, 56758, 55297, 56759, + 55297, 56760, 55297, 56761, 55297, 56763, 55297, 56764, + 55297, 56688, 55297, 56689, 55297, 56690, 55297, 56691, + 55297, 56692, 55297, 56693, 55297, 56694, 55297, 56695, + 55297, 56696, 55297, 56697, 55297, 56698, 55297, 56700, + 55297, 56701, 55297, 56702, 55297, 56703, 55297, 56704, + 55297, 56705, 55297, 56706, 55297, 56707, 55297, 56708, + 55297, 56709, 55297, 56710, 55297, 56711, 55297, 56712, + 55297, 56713, 55297, 56714, 55297, 56716, 55297, 56717, + 55297, 56718, 55297, 56719, 55297, 56720, 55297, 56721, + 55297, 56722, 55297, 56724, 55297, 56725, 55297, 57216, + 720, 721, 55297, 57219, 55297, 57220, 55297, 57221, + 55297, 57223, 55297, 57224, 55297, 57225, 55297, 57226, + 55297, 57227, 55297, 57228, 55297, 57229, 55297, 57230, + 55297, 57231, 55297, 57232, 55297, 57233, 55297, 57234, + 55297, 57235, 55297, 57236, 55297, 57237, 55297, 57238, + 55297, 57239, 55297, 57240, 55297, 57241, 55297, 57242, + 55297, 57243, 55351, 57092, 55297, 57244, 55297, 57245, + 55297, 57246, 55351, 57093, 55297, 57247, 55297, 57248, + 55351, 57094, 55297, 57249, 55297, 57250, 55297, 57251, + 55297, 57252, 55297, 57253, 55297, 57254, 55351, 57096, + 55297, 57255, 55297, 57256, 55297, 57257, 55297, 57258, + 55297, 57259, 55297, 57260, 55297, 57261, 55297, 57262, + 55297, 57263, 55297, 57264, 55297, 57266, 55297, 57267, + 55297, 57268, 55297, 57269, 448, 55297, 57270, 449, + 55297, 57271, 450, 55297, 57272, 55351, 57098, 55297, + 57273, 55351, 57118, 55297, 57274, 55299, 56512, 55299, + 56513, 55299, 56514, 55299, 56515, 55299, 56516, 55299, + 56517, 55299, 56518, 55299, 56519, 55299, 56520, 55299, + 56521, 55299, 56522, 55299, 56523, 55299, 56524, 55299, + 56525, 55299, 56526, 55299, 56527, 55299, 56528, 55299, + 56529, 55299, 56530, 55299, 56531, 55299, 56532, 55299, + 56533, 55299, 56534, 55299, 56535, 55299, 56536, 55299, + 56537, 55299, 56538, 55299, 56539, 55299, 56540, 55299, + 56541, 55299, 56542, 55299, 56543, 55299, 56544, 55299, + 56545, 55299, 56546, 55299, 56547, 55299, 56548, 55299, + 56549, 55299, 56550, 55299, 56551, 55299, 56552, 55299, + 56553, 55299, 56554, 55299, 56555, 55299, 56556, 55299, + 56557, 55299, 56558, 55299, 56559, 55299, 56560, 55299, + 56561, 55299, 56562, 55299, 56448, 55299, 56449, 55299, + 56450, 55299, 56451, 55299, 56452, 55299, 56453, 55299, + 56454, 55299, 56455, 55299, 56456, 55299, 56457, 55299, + 56458, 55299, 56459, 55299, 56460, 55299, 56461, 55299, + 56462, 55299, 56463, 55299, 56464, 55299, 56465, 55299, + 56466, 55299, 56467, 55299, 56468, 55299, 56469, 55299, + 56470, 55299, 56471, 55299, 56472, 55299, 56473, 55299, + 56474, 55299, 56475, 55299, 56476, 55299, 56477, 55299, + 56478, 55299, 56479, 55299, 56480, 55299, 56481, 55299, + 56482, 55299, 56483, 55299, 56484, 55299, 56485, 55299, + 56486, 55299, 56487, 55299, 56488, 55299, 56489, 55299, + 56490, 55299, 56491, 55299, 56492, 55299, 56493, 55299, + 56494, 55299, 56495, 55299, 56496, 55299, 56497, 55299, + 56498, 55300, 56473, 55300, 56506, 55300, 56475, 55300, + 56506, 55300, 56485, 55300, 56506, 55300, 56625, 55300, + 56615, 55300, 56626, 55300, 56615, 55300, 57159, 55300, + 57150, 55300, 57159, 55300, 57175, 55301, 56505, 55301, + 56506, 55301, 56505, 55301, 56496, 55301, 56505, 55301, + 56509, 55301, 56760, 55301, 56751, 55301, 56761, 55301, + 56751, 55302, 56512, 55302, 56513, 55302, 56514, 55302, + 56515, 55302, 56516, 55302, 56517, 55302, 56518, 55302, + 56519, 55302, 56520, 55302, 56521, 55302, 56522, 55302, + 56523, 55302, 56524, 55302, 56525, 55302, 56526, 55302, + 56527, 55302, 56528, 55302, 56529, 55302, 56530, 55302, + 56531, 55302, 56532, 55302, 56533, 55302, 56534, 55302, + 56535, 55302, 56536, 55302, 56537, 55302, 56538, 55302, + 56539, 55302, 56540, 55302, 56541, 55302, 56542, 55302, + 56543, 55302, 56480, 55302, 56481, 55302, 56482, 55302, + 56483, 55302, 56484, 55302, 56485, 55302, 56486, 55302, + 56487, 55302, 56488, 55302, 56489, 55302, 56490, 55302, + 56491, 55302, 56492, 55302, 56493, 55302, 56494, 55302, + 56495, 55302, 56496, 55302, 56497, 55302, 56498, 55302, + 56499, 55302, 56500, 55302, 56501, 55302, 56502, 55302, + 56503, 55302, 56504, 55302, 56505, 55302, 56506, 55302, + 56507, 55302, 56508, 55302, 56509, 55302, 56510, 55302, + 56511, 55302, 56629, 55302, 56624, 55323, 56928, 55323, + 56929, 55323, 56930, 55323, 56931, 55323, 56932, 55323, + 56933, 55323, 56934, 55323, 56935, 55323, 56936, 55323, + 56937, 55323, 56938, 55323, 56939, 55323, 56940, 55323, + 56941, 55323, 56942, 55323, 56943, 55323, 56944, 55323, + 56945, 55323, 56946, 55323, 56947, 55323, 56948, 55323, + 56949, 55323, 56950, 55323, 56951, 55323, 56952, 55323, + 56953, 55323, 56954, 55323, 56955, 55323, 56956, 55323, + 56957, 55323, 56958, 55323, 56959, 55323, 56896, 55323, + 56897, 55323, 56898, 55323, 56899, 55323, 56900, 55323, + 56901, 55323, 56902, 55323, 56903, 55323, 56904, 55323, + 56905, 55323, 56906, 55323, 56907, 55323, 56908, 55323, + 56909, 55323, 56910, 55323, 56911, 55323, 56912, 55323, + 56913, 55323, 56914, 55323, 56915, 55323, 56916, 55323, + 56917, 55323, 56918, 55323, 56919, 55323, 56920, 55323, + 56921, 55323, 56922, 55323, 56923, 55323, 56924, 55323, + 56925, 55323, 56926, 55323, 56927, 55348, 56663, 55348, + 56677, 55348, 56664, 55348, 56677, 55348, 56671, 55348, + 56686, 55348, 56671, 55348, 56687, 55348, 56671, 55348, + 56688, 55348, 56671, 55348, 56689, 55348, 56671, 55348, + 56690, 55348, 56761, 55348, 56677, 55348, 56762, 55348, + 56677, 55348, 56763, 55348, 56686, 55348, 56764, 55348, + 56686, 55348, 56763, 55348, 56687, 55348, 56764, 55348, + 56687, 55349, 56320, 55349, 56321, 55349, 56322, 55349, + 56323, 55349, 56324, 55349, 56325, 55349, 56326, 55349, + 56327, 55349, 56328, 55349, 56329, 55349, 56330, 55349, + 56331, 55349, 56332, 55349, 56333, 55349, 56334, 55349, + 56335, 55349, 56336, 55349, 56337, 55349, 56338, 55349, + 56339, 55349, 56340, 55349, 56341, 55349, 56342, 55349, + 56343, 55349, 56344, 55349, 56345, 55349, 56346, 55349, + 56347, 55349, 56348, 55349, 56349, 55349, 56350, 55349, + 56351, 55349, 56352, 55349, 56353, 55349, 56354, 55349, + 56355, 55349, 56356, 55349, 56357, 55349, 56358, 55349, + 56359, 55349, 56360, 55349, 56361, 55349, 56362, 55349, + 56363, 55349, 56364, 55349, 56365, 55349, 56366, 55349, + 56367, 55349, 56368, 55349, 56369, 55349, 56370, 55349, + 56371, 55349, 56372, 55349, 56373, 55349, 56374, 55349, + 56375, 55349, 56376, 55349, 56377, 55349, 56378, 55349, + 56379, 55349, 56380, 55349, 56381, 55349, 56382, 55349, + 56383, 55349, 56384, 55349, 56385, 55349, 56386, 55349, + 56387, 55349, 56388, 55349, 56389, 55349, 56390, 55349, + 56391, 55349, 56392, 55349, 56393, 55349, 56394, 55349, + 56395, 55349, 56396, 55349, 56397, 55349, 56398, 55349, + 56399, 55349, 56400, 55349, 56401, 55349, 56402, 55349, + 56403, 55349, 56404, 55349, 56406, 55349, 56407, 55349, + 56408, 55349, 56409, 55349, 56410, 55349, 56411, 55349, + 56412, 55349, 56413, 55349, 56414, 55349, 56415, 55349, + 56416, 55349, 56417, 55349, 56418, 55349, 56419, 55349, + 56420, 55349, 56421, 55349, 56422, 55349, 56423, 55349, + 56424, 55349, 56425, 55349, 56426, 55349, 56427, 55349, + 56428, 55349, 56429, 55349, 56430, 55349, 56431, 55349, + 56432, 55349, 56433, 55349, 56434, 55349, 56435, 55349, + 56436, 55349, 56437, 55349, 56438, 55349, 56439, 55349, + 56440, 55349, 56441, 55349, 56442, 55349, 56443, 55349, + 56444, 55349, 56445, 55349, 56446, 55349, 56447, 55349, + 56448, 55349, 56449, 55349, 56450, 55349, 56451, 55349, + 56452, 55349, 56453, 55349, 56454, 55349, 56455, 55349, + 56456, 55349, 56457, 55349, 56458, 55349, 56459, 55349, + 56460, 55349, 56461, 55349, 56462, 55349, 56463, 55349, + 56464, 55349, 56465, 55349, 56466, 55349, 56467, 55349, + 56468, 55349, 56469, 55349, 56470, 55349, 56471, 55349, + 56472, 55349, 56473, 55349, 56474, 55349, 56475, 55349, + 56476, 55349, 56478, 55349, 56479, 55349, 56482, 55349, + 56485, 55349, 56486, 55349, 56489, 55349, 56490, 55349, + 56491, 55349, 56492, 55349, 56494, 55349, 56495, 55349, + 56496, 55349, 56497, 55349, 56498, 55349, 56499, 55349, + 56500, 55349, 56501, 55349, 56502, 55349, 56503, 55349, + 56504, 55349, 56505, 55349, 56507, 55349, 56509, 55349, + 56510, 55349, 56511, 55349, 56512, 55349, 56513, 55349, + 56514, 55349, 56515, 55349, 56517, 55349, 56518, 55349, + 56519, 55349, 56520, 55349, 56521, 55349, 56522, 55349, + 56523, 55349, 56524, 55349, 56525, 55349, 56526, 55349, + 56527, 55349, 56528, 55349, 56529, 55349, 56530, 55349, + 56531, 55349, 56532, 55349, 56533, 55349, 56534, 55349, + 56535, 55349, 56536, 55349, 56537, 55349, 56538, 55349, + 56539, 55349, 56540, 55349, 56541, 55349, 56542, 55349, + 56543, 55349, 56544, 55349, 56545, 55349, 56546, 55349, + 56547, 55349, 56548, 55349, 56549, 55349, 56550, 55349, + 56551, 55349, 56552, 55349, 56553, 55349, 56554, 55349, + 56555, 55349, 56556, 55349, 56557, 55349, 56558, 55349, + 56559, 55349, 56560, 55349, 56561, 55349, 56562, 55349, + 56563, 55349, 56564, 55349, 56565, 55349, 56566, 55349, + 56567, 55349, 56568, 55349, 56569, 55349, 56570, 55349, + 56571, 55349, 56572, 55349, 56573, 55349, 56574, 55349, + 56575, 55349, 56576, 55349, 56577, 55349, 56578, 55349, + 56579, 55349, 56580, 55349, 56581, 55349, 56583, 55349, + 56584, 55349, 56585, 55349, 56586, 55349, 56589, 55349, + 56590, 55349, 56591, 55349, 56592, 55349, 56593, 55349, + 56594, 55349, 56595, 55349, 56596, 55349, 56598, 55349, + 56599, 55349, 56600, 55349, 56601, 55349, 56602, 55349, + 56603, 55349, 56604, 55349, 56606, 55349, 56607, 55349, + 56608, 55349, 56609, 55349, 56610, 55349, 56611, 55349, + 56612, 55349, 56613, 55349, 56614, 55349, 56615, 55349, + 56616, 55349, 56617, 55349, 56618, 55349, 56619, 55349, + 56620, 55349, 56621, 55349, 56622, 55349, 56623, 55349, + 56624, 55349, 56625, 55349, 56626, 55349, 56627, 55349, + 56628, 55349, 56629, 55349, 56630, 55349, 56631, 55349, + 56632, 55349, 56633, 55349, 56635, 55349, 56636, 55349, + 56637, 55349, 56638, 55349, 56640, 55349, 56641, 55349, + 56642, 55349, 56643, 55349, 56644, 55349, 56646, 55349, + 56650, 55349, 56651, 55349, 56652, 55349, 56653, 55349, + 56654, 55349, 56655, 55349, 56656, 55349, 56658, 55349, + 56659, 55349, 56660, 55349, 56661, 55349, 56662, 55349, + 56663, 55349, 56664, 55349, 56665, 55349, 56666, 55349, + 56667, 55349, 56668, 55349, 56669, 55349, 56670, 55349, + 56671, 55349, 56672, 55349, 56673, 55349, 56674, 55349, + 56675, 55349, 56676, 55349, 56677, 55349, 56678, 55349, + 56679, 55349, 56680, 55349, 56681, 55349, 56682, 55349, + 56683, 55349, 56684, 55349, 56685, 55349, 56686, 55349, + 56687, 55349, 56688, 55349, 56689, 55349, 56690, 55349, + 56691, 55349, 56692, 55349, 56693, 55349, 56694, 55349, + 56695, 55349, 56696, 55349, 56697, 55349, 56698, 55349, + 56699, 55349, 56700, 55349, 56701, 55349, 56702, 55349, + 56703, 55349, 56704, 55349, 56705, 55349, 56706, 55349, + 56707, 55349, 56708, 55349, 56709, 55349, 56710, 55349, + 56711, 55349, 56712, 55349, 56713, 55349, 56714, 55349, + 56715, 55349, 56716, 55349, 56717, 55349, 56718, 55349, + 56719, 55349, 56720, 55349, 56721, 55349, 56722, 55349, + 56723, 55349, 56724, 55349, 56725, 55349, 56726, 55349, + 56727, 55349, 56728, 55349, 56729, 55349, 56730, 55349, + 56731, 55349, 56732, 55349, 56733, 55349, 56734, 55349, + 56735, 55349, 56736, 55349, 56737, 55349, 56738, 55349, + 56739, 55349, 56740, 55349, 56741, 55349, 56742, 55349, + 56743, 55349, 56744, 55349, 56745, 55349, 56746, 55349, + 56747, 55349, 56748, 55349, 56749, 55349, 56750, 55349, + 56751, 55349, 56752, 55349, 56753, 55349, 56754, 55349, + 56755, 55349, 56756, 55349, 56757, 55349, 56758, 55349, + 56759, 55349, 56760, 55349, 56761, 55349, 56762, 55349, + 56763, 55349, 56764, 55349, 56765, 55349, 56766, 55349, + 56767, 55349, 56768, 55349, 56769, 55349, 56770, 55349, + 56771, 55349, 56772, 55349, 56773, 55349, 56774, 55349, + 56775, 55349, 56776, 55349, 56777, 55349, 56778, 55349, + 56779, 55349, 56780, 55349, 56781, 55349, 56782, 55349, + 56783, 55349, 56784, 55349, 56785, 55349, 56786, 55349, + 56787, 55349, 56788, 55349, 56789, 55349, 56790, 55349, + 56791, 55349, 56792, 55349, 56793, 55349, 56794, 55349, + 56795, 55349, 56796, 55349, 56797, 55349, 56798, 55349, + 56799, 55349, 56800, 55349, 56801, 55349, 56802, 55349, + 56803, 55349, 56804, 55349, 56805, 55349, 56806, 55349, + 56807, 55349, 56808, 55349, 56809, 55349, 56810, 55349, + 56811, 55349, 56812, 55349, 56813, 55349, 56814, 55349, + 56815, 55349, 56816, 55349, 56817, 55349, 56818, 55349, + 56819, 55349, 56820, 55349, 56821, 55349, 56822, 55349, + 56823, 55349, 56824, 55349, 56825, 55349, 56826, 55349, + 56827, 55349, 56828, 55349, 56829, 55349, 56830, 55349, + 56831, 55349, 56832, 55349, 56833, 55349, 56834, 55349, + 56835, 55349, 56836, 55349, 56837, 55349, 56838, 55349, + 56839, 55349, 56840, 55349, 56841, 55349, 56842, 55349, + 56843, 55349, 56844, 55349, 56845, 55349, 56846, 55349, + 56847, 55349, 56848, 55349, 56849, 55349, 56850, 55349, + 56851, 55349, 56852, 55349, 56853, 55349, 56854, 55349, + 56855, 55349, 56856, 55349, 56857, 55349, 56858, 55349, + 56859, 55349, 56860, 55349, 56861, 55349, 56862, 55349, + 56863, 55349, 56864, 55349, 56865, 55349, 56866, 55349, + 56867, 55349, 56868, 55349, 56869, 55349, 56870, 55349, + 56871, 55349, 56872, 55349, 56873, 55349, 56874, 55349, + 56875, 55349, 56876, 55349, 56877, 55349, 56878, 55349, + 56879, 55349, 56880, 55349, 56881, 55349, 56882, 55349, + 56883, 55349, 56884, 55349, 56885, 55349, 56886, 55349, + 56887, 55349, 56888, 55349, 56889, 55349, 56890, 55349, + 56891, 55349, 56892, 55349, 56893, 55349, 56894, 55349, + 56895, 55349, 56896, 55349, 56897, 55349, 56898, 55349, + 56899, 55349, 56900, 55349, 56901, 55349, 56902, 55349, + 56903, 55349, 56904, 55349, 56905, 55349, 56906, 55349, + 56907, 55349, 56908, 55349, 56909, 55349, 56910, 55349, + 56911, 55349, 56912, 55349, 56913, 55349, 56914, 55349, + 56915, 55349, 56916, 55349, 56917, 55349, 56918, 55349, + 56919, 55349, 56920, 55349, 56921, 55349, 56922, 55349, + 56923, 55349, 56924, 55349, 56925, 55349, 56926, 55349, + 56927, 55349, 56928, 55349, 56929, 55349, 56930, 55349, + 56931, 55349, 56932, 55349, 56933, 55349, 56934, 55349, + 56935, 55349, 56936, 55349, 56937, 55349, 56938, 55349, + 56939, 55349, 56940, 55349, 56941, 55349, 56942, 55349, + 56943, 55349, 56944, 55349, 56945, 55349, 56946, 55349, + 56947, 55349, 56948, 55349, 56949, 55349, 56950, 55349, + 56951, 55349, 56952, 55349, 56953, 55349, 56954, 55349, + 56955, 55349, 56956, 55349, 56957, 55349, 56958, 55349, + 56959, 55349, 56960, 55349, 56961, 55349, 56962, 55349, + 56963, 55349, 56964, 55349, 56965, 55349, 56966, 55349, + 56967, 55349, 56968, 55349, 56969, 55349, 56970, 55349, + 56971, 55349, 56972, 55349, 56973, 55349, 56974, 55349, + 56975, 55349, 56976, 55349, 56977, 55349, 56978, 55349, + 56979, 55349, 56980, 55349, 56981, 55349, 56982, 55349, + 56983, 55349, 56984, 55349, 56985, 55349, 56986, 55349, + 56987, 55349, 56988, 55349, 56989, 55349, 56990, 55349, + 56991, 55349, 56992, 55349, 56993, 55349, 56994, 55349, + 56995, 305, 55349, 56996, 55349, 56997, 55349, 57000, + 55349, 57001, 55349, 57002, 55349, 57003, 55349, 57004, + 55349, 57005, 55349, 57006, 55349, 57007, 55349, 57008, + 55349, 57009, 55349, 57010, 55349, 57011, 55349, 57012, + 55349, 57013, 55349, 57014, 55349, 57015, 55349, 57016, + 1012, 55349, 57017, 55349, 57018, 55349, 57019, 55349, + 57020, 55349, 57021, 55349, 57022, 55349, 57023, 55349, + 57024, 8711, 55349, 57026, 55349, 57027, 55349, 57028, + 55349, 57029, 55349, 57030, 55349, 57031, 55349, 57032, + 55349, 57033, 55349, 57034, 55349, 57035, 55349, 57036, + 55349, 57037, 55349, 57038, 55349, 57039, 55349, 57040, + 55349, 57041, 55349, 57042, 55349, 57043, 55349, 57044, + 55349, 57045, 55349, 57046, 55349, 57047, 55349, 57048, + 55349, 57049, 55349, 57050, 8706, 1013, 55349, 57052, + 977, 55349, 57053, 1008, 55349, 57054, 981, 55349, + 57055, 1009, 55349, 57056, 982, 55349, 57057, 55349, + 57058, 55349, 57059, 55349, 57060, 55349, 57061, 55349, + 57062, 55349, 57063, 55349, 57064, 55349, 57065, 55349, + 57066, 55349, 57067, 55349, 57068, 55349, 57069, 55349, + 57070, 55349, 57071, 55349, 57072, 55349, 57073, 55349, + 57074, 55349, 57075, 55349, 57076, 55349, 57077, 55349, + 57078, 55349, 57079, 55349, 57080, 55349, 57081, 55349, + 57082, 55349, 57084, 55349, 57085, 55349, 57086, 55349, + 57087, 55349, 57088, 55349, 57089, 55349, 57090, 55349, + 57091, 55349, 57092, 55349, 57093, 55349, 57094, 55349, + 57095, 55349, 57096, 55349, 57097, 55349, 57098, 55349, + 57099, 55349, 57100, 55349, 57101, 55349, 57102, 55349, + 57103, 55349, 57104, 55349, 57105, 55349, 57106, 55349, + 57107, 55349, 57108, 55349, 57110, 55349, 57111, 55349, + 57112, 55349, 57113, 55349, 57114, 55349, 57115, 55349, + 57116, 55349, 57117, 55349, 57118, 55349, 57119, 55349, + 57120, 55349, 57121, 55349, 57122, 55349, 57123, 55349, + 57124, 55349, 57125, 55349, 57126, 55349, 57127, 55349, + 57128, 55349, 57129, 55349, 57130, 55349, 57131, 55349, + 57132, 55349, 57133, 55349, 57134, 55349, 57135, 55349, + 57136, 55349, 57137, 55349, 57138, 55349, 57139, 55349, + 57140, 55349, 57142, 55349, 57143, 55349, 57144, 55349, + 57145, 55349, 57146, 55349, 57147, 55349, 57148, 55349, + 57149, 55349, 57150, 55349, 57151, 55349, 57152, 55349, + 57153, 55349, 57154, 55349, 57155, 55349, 57156, 55349, + 57157, 55349, 57158, 55349, 57159, 55349, 57160, 55349, + 57161, 55349, 57162, 55349, 57163, 55349, 57164, 55349, + 57165, 55349, 57166, 55349, 57168, 55349, 57169, 55349, + 57170, 55349, 57171, 55349, 57172, 55349, 57173, 55349, + 57174, 55349, 57175, 55349, 57176, 55349, 57177, 55349, + 57178, 55349, 57179, 55349, 57180, 55349, 57181, 55349, + 57182, 55349, 57183, 55349, 57184, 55349, 57185, 55349, + 57186, 55349, 57187, 55349, 57188, 55349, 57189, 55349, + 57190, 55349, 57191, 55349, 57192, 55349, 57193, 55349, + 57194, 55349, 57195, 55349, 57196, 55349, 57197, 55349, + 57198, 55349, 57200, 55349, 57201, 55349, 57202, 55349, + 57203, 55349, 57204, 55349, 57205, 55349, 57206, 55349, + 57207, 55349, 57208, 55349, 57209, 55349, 57210, 55349, + 57211, 55349, 57212, 55349, 57213, 55349, 57214, 55349, + 57215, 55349, 57216, 55349, 57217, 55349, 57218, 55349, + 57219, 55349, 57220, 55349, 57221, 55349, 57222, 55349, + 57223, 55349, 57224, 55349, 57226, 55349, 57227, 55349, + 57228, 55349, 57229, 55349, 57230, 55349, 57231, 55349, + 57232, 55349, 57233, 55349, 57234, 55349, 57235, 55349, + 57236, 55349, 57237, 55349, 57238, 55349, 57239, 55349, + 57240, 55349, 57241, 55349, 57242, 55349, 57243, 55349, + 57244, 55349, 57245, 55349, 57246, 55349, 57247, 55349, + 57248, 55349, 57249, 55349, 57250, 55349, 57251, 55349, + 57252, 55349, 57253, 55349, 57254, 55349, 57255, 55349, + 57256, 55349, 57258, 55349, 57259, 55349, 57260, 55349, + 57261, 55349, 57262, 55349, 57263, 55349, 57264, 55349, + 57265, 55349, 57266, 55349, 57267, 55349, 57268, 55349, + 57269, 55349, 57270, 55349, 57271, 55349, 57272, 55349, + 57273, 55349, 57274, 55349, 57275, 55349, 57276, 55349, + 57277, 55349, 57278, 55349, 57279, 55349, 57280, 55349, + 57281, 55349, 57282, 55349, 57284, 55349, 57285, 55349, + 57286, 55349, 57287, 55349, 57288, 55349, 57289, 55349, + 57290, 55349, 57291, 55351, 57088, 55351, 57089, 55351, + 57090, 55351, 57091, 55351, 57095, 55351, 57097, 55351, + 57099, 55351, 57100, 55351, 57101, 55351, 57102, 55351, + 57103, 55351, 57104, 55351, 57105, 55351, 57106, 55351, + 57107, 55351, 57108, 55351, 57109, 55351, 57110, 55351, + 57111, 55351, 57112, 55351, 57113, 55351, 57114, 55351, + 57115, 55351, 57116, 55351, 57117, 55351, 57125, 55351, + 57126, 55351, 57127, 55351, 57128, 55351, 57129, 55351, + 57130, 55352, 56368, 55352, 56369, 55352, 56370, 55352, + 56371, 55352, 56372, 55352, 56373, 55352, 56374, 55352, + 56375, 55352, 56376, 55352, 56377, 55352, 56378, 55352, + 56379, 55352, 56380, 55352, 56381, 55352, 56382, 55352, + 56383, 55352, 56384, 55352, 56385, 55352, 56386, 55352, + 56387, 55352, 56388, 55352, 56389, 55352, 56390, 55352, + 56391, 55352, 56392, 55352, 56393, 55352, 56394, 55352, + 56395, 55352, 56396, 55352, 56397, 55352, 56398, 55352, + 56399, 55352, 56400, 55352, 56401, 55352, 56402, 55352, + 56403, 55352, 56404, 55352, 56405, 55352, 56406, 55352, + 56407, 55352, 56408, 55352, 56409, 55352, 56410, 55352, + 56411, 55352, 56412, 55352, 56413, 55352, 56414, 55352, + 56415, 55352, 56416, 55352, 56417, 55352, 56418, 55352, + 56419, 55352, 56420, 55352, 56421, 55352, 56422, 55352, + 56423, 55352, 56424, 55352, 56425, 55352, 56426, 55352, + 56427, 55352, 56428, 55352, 56429, 55354, 56610, 55354, + 56611, 55354, 56612, 55354, 56613, 55354, 56614, 55354, + 56615, 55354, 56616, 55354, 56617, 55354, 56618, 55354, + 56619, 55354, 56620, 55354, 56621, 55354, 56622, 55354, + 56623, 55354, 56624, 55354, 56625, 55354, 56626, 55354, + 56627, 55354, 56628, 55354, 56629, 55354, 56630, 55354, + 56631, 55354, 56632, 55354, 56633, 55354, 56634, 55354, + 56635, 55354, 56636, 55354, 56637, 55354, 56638, 55354, + 56639, 55354, 56640, 55354, 56641, 55354, 56642, 55354, + 56643, 55354, 56576, 55354, 56577, 55354, 56578, 55354, + 56579, 55354, 56580, 55354, 56581, 55354, 56582, 55354, + 56583, 55354, 56584, 55354, 56585, 55354, 56586, 55354, + 56587, 55354, 56588, 55354, 56589, 55354, 56590, 55354, + 56591, 55354, 56592, 55354, 56593, 55354, 56594, 55354, + 56595, 55354, 56596, 55354, 56597, 55354, 56598, 55354, + 56599, 55354, 56600, 55354, 56601, 55354, 56602, 55354, + 56603, 55354, 56604, 55354, 56605, 55354, 56606, 55354, + 56607, 55354, 56608, 55354, 56609, 1646, 1697, 1647, + 48, 46, 48, 44, 49, 44, 50, 44, + 51, 44, 52, 44, 53, 44, 54, 44, + 55, 44, 56, 44, 57, 44, 40, 65, + 41, 40, 66, 41, 40, 67, 41, 40, + 68, 41, 40, 69, 41, 40, 70, 41, + 40, 71, 41, 40, 72, 41, 40, 73, + 41, 40, 74, 41, 40, 75, 41, 40, + 76, 41, 40, 77, 41, 40, 78, 41, + 40, 79, 41, 40, 80, 41, 40, 81, + 41, 40, 82, 41, 40, 83, 41, 40, + 84, 41, 40, 85, 41, 40, 86, 41, + 40, 87, 41, 40, 88, 41, 40, 89, + 41, 40, 90, 41, 12308, 83, 12309, 67, + 68, 87, 90, 55356, 56624, 55356, 56625, 55356, + 56626, 55356, 56627, 55356, 56628, 55356, 56629, 55356, + 56630, 55356, 56631, 55356, 56632, 55356, 56633, 55356, + 56634, 55356, 56635, 55356, 56636, 55356, 56637, 55356, + 56638, 55356, 56639, 55356, 56640, 55356, 56641, 55356, + 56642, 55356, 56643, 55356, 56644, 55356, 56645, 55356, + 56646, 55356, 56647, 55356, 56648, 55356, 56649, 72, + 86, 83, 68, 83, 83, 80, 80, 86, + 87, 67, 55356, 56656, 55356, 56657, 55356, 56658, + 55356, 56659, 55356, 56660, 55356, 56661, 55356, 56662, + 55356, 56663, 55356, 56664, 55356, 56665, 55356, 56666, + 55356, 56667, 55356, 56668, 55356, 56669, 55356, 56670, + 55356, 56671, 55356, 56672, 55356, 56673, 55356, 56674, + 55356, 56675, 55356, 56676, 55356, 56677, 55356, 56678, + 55356, 56679, 55356, 56680, 55356, 56681, 77, 67, + 77, 68, 77, 82, 55356, 56688, 55356, 56689, + 55356, 56690, 55356, 56691, 55356, 56692, 55356, 56693, + 55356, 56694, 55356, 56695, 55356, 56696, 55356, 56697, + 55356, 56698, 55356, 56699, 55356, 56700, 55356, 56701, + 55356, 56702, 55356, 56703, 55356, 56704, 55356, 56705, + 55356, 56706, 55356, 56707, 55356, 56708, 55356, 56709, + 55356, 56710, 55356, 56711, 55356, 56712, 55356, 56713, + 68, 74, 12411, 12363, 12467, 12467, 23383, 21452, + 12487, 22810, 35299, 20132, 26144, 28961, 21069, 24460, + 20877, 26032, 21021, 32066, 36009, 22768, 21561, 28436, + 25237, 25429, 36938, 25351, 25171, 31105, 31354, 21512, + 28288, 30003, 21106, 21942, 37197, 12308, 26412, 12309, + 12308, 19977, 12309, 12308, 20108, 12309, 12308, 23433, + 12309, 12308, 28857, 12309, 12308, 25171, 12309, 12308, + 30423, 12309, 12308, 21213, 12309, 12308, 25943, 12309, + 24471, 21487, 20029, 20024, 20033, 55360, 56610, 20320, + 20411, 20482, 20602, 20633, 20687, 13470, 55361, 56890, + 20820, 20836, 20855, 55361, 56604, 13497, 20839, 55361, + 56651, 20887, 20900, 20172, 20908, 55396, 56799, 20995, + 13535, 21051, 21062, 21111, 13589, 21253, 21254, 21321, + 21338, 21363, 21373, 21375, 55362, 56876, 28784, 21450, + 21471, 55362, 57187, 21483, 21489, 21510, 21662, 21560, + 21576, 21608, 21666, 21750, 21776, 21843, 21859, 21892, + 21931, 21939, 21954, 22294, 22295, 22097, 22132, 22766, + 22478, 22516, 22541, 22411, 22578, 22577, 22700, 55365, + 56548, 22770, 22775, 22790, 22818, 22882, 55365, 57000, + 55365, 57066, 23020, 23067, 23079, 23000, 23142, 14062, + 14076, 23304, 23358, 55366, 56776, 23491, 23512, 23539, + 55366, 57112, 23551, 23558, 24403, 14209, 23648, 23744, + 23693, 55367, 56804, 23875, 55367, 56806, 23918, 23915, + 23932, 24033, 24034, 14383, 24061, 24104, 24125, 24169, + 14434, 55368, 56707, 14460, 24240, 24243, 24246, 55400, + 57234, 55368, 57137, 33281, 24354, 14535, 55372, 57016, + 55384, 56794, 24418, 24427, 14563, 24474, 24525, 24535, + 24569, 24705, 14650, 14620, 55369, 57044, 24775, 24904, + 24908, 24954, 25010, 24996, 25007, 25054, 25104, 25115, + 25181, 25265, 25300, 25424, 55370, 57100, 25405, 25340, + 25448, 25475, 25572, 55370, 57329, 25634, 25541, 25513, + 14894, 25705, 25726, 25757, 25719, 14956, 25964, 55372, + 56330, 26083, 26360, 26185, 15129, 15112, 15076, 20882, + 20885, 26368, 26268, 32941, 17369, 26401, 26462, 26451, + 55372, 57283, 15177, 26618, 26501, 26706, 55373, 56429, + 26766, 26655, 26900, 26946, 27043, 27114, 27304, 55373, + 56995, 27355, 15384, 27425, 55374, 56487, 27476, 15438, + 27506, 27551, 27579, 55374, 56973, 55367, 56587, 55374, + 57082, 27726, 55375, 56508, 27839, 27853, 27751, 27926, + 27966, 28009, 28024, 28037, 55375, 56606, 27956, 28207, + 28270, 15667, 28359, 55375, 57041, 28153, 28526, 55375, + 57182, 55375, 57230, 28614, 28729, 28699, 15766, 28746, + 28797, 28791, 28845, 55361, 56613, 28997, 55376, 56931, + 29084, 55376, 57259, 29224, 29264, 55377, 56840, 29312, + 29333, 55377, 57141, 55378, 56340, 29562, 29579, 16044, + 29605, 16056, 29767, 29788, 29829, 29898, 16155, 29988, + 55379, 56374, 30014, 55379, 56466, 55368, 56735, 30224, + 55379, 57249, 55379, 57272, 55380, 56388, 16380, 16392, + 55380, 56563, 55380, 56562, 55380, 56601, 55380, 56627, + 30494, 30495, 30603, 16454, 16534, 55381, 56349, 30798, + 16611, 55381, 56870, 55381, 56986, 55381, 57029, 31211, + 16687, 31306, 31311, 55382, 56700, 55382, 56999, 31470, + 16898, 55382, 57259, 31686, 31689, 16935, 55383, 56448, + 31954, 17056, 31976, 31971, 32000, 55383, 57222, 32099, + 17153, 32199, 32258, 32325, 17204, 55384, 56872, 55384, + 56903, 17241, 55384, 57049, 32634, 55384, 57150, 32661, + 32762, 55385, 56538, 55385, 56611, 32864, 55385, 56744, + 32880, 55372, 57183, 17365, 32946, 33027, 17419, 33086, + 23221, 55385, 57255, 55385, 57269, 55372, 57235, 55372, + 57244, 33284, 36766, 17515, 33425, 33419, 33437, 21171, + 33457, 33459, 33469, 33510, 55386, 57148, 33565, 33635, + 33709, 33571, 33725, 33767, 33619, 33738, 33740, 33756, + 55387, 56374, 55387, 56683, 55387, 56533, 17707, 34033, + 34035, 34070, 55388, 57290, 34148, 55387, 57132, 17757, + 17761, 55387, 57265, 55388, 56530, 17771, 34384, 34407, + 34409, 34473, 34440, 34574, 34530, 34600, 34667, 34694, + 17879, 34785, 34817, 17913, 34912, 55389, 56935, 35031, + 35038, 17973, 35066, 13499, 55390, 56494, 55390, 56678, + 18110, 18119, 35488, 55391, 56488, 36011, 36033, 36123, + 36215, 55391, 57135, 55362, 56324, 36299, 36284, 36336, + 55362, 56542, 36564, 55393, 56786, 55393, 56813, 37012, + 37105, 37137, 55393, 57134, 37147, 37432, 37591, 37592, + 37500, 37881, 37909, 55394, 57338, 38283, 18837, 38327, + 55395, 56695, 18918, 38595, 23986, 38691, 55396, 56645, + 55396, 56858, 19054, 19062, 38880, 55397, 56330, 19122, + 55397, 56470, 38953, 55397, 56758, 39138, 19251, 39209, + 39335, 39362, 39422, 19406, 55398, 57136, 40000, 40189, + 19662, 19693, 40295, 55400, 56526, 19704, 55400, 56581, + 55400, 56846, 55400, 56977, 19798, 40702, 40709, 40719, + 40726, 55401, 56832, }; static const utf8proc_uint16_t utf8proc_stage1table[] = { 0, 256, 512, 768, 1024, 1280, 1536, @@ -1227,51 +1607,51 @@ static const utf8proc_uint16_t utf8proc_stage1table[] = { 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, - 13824, 14080, 13312, 13312, 13312, 14336, 5376, 14592, - 14848, 15104, 15360, 15616, 15872, 16128, 16384, 16640, - 16896, 17152, 17408, 17664, 16128, 16384, 16640, 16896, - 17152, 17408, 17664, 16128, 16384, 16640, 16896, 17152, - 17408, 17664, 16128, 16384, 16640, 16896, 17152, 17408, - 17664, 16128, 16384, 16640, 16896, 17152, 17408, 17664, - 16128, 16384, 16640, 16896, 17152, 17408, 17664, 16128, + 13312, 13824, 13312, 13312, 13312, 14080, 5376, 14336, + 14592, 14848, 15104, 15360, 15616, 15872, 16128, 16384, + 16640, 16896, 17152, 17408, 15872, 16128, 16384, 16640, + 16896, 17152, 17408, 15872, 16128, 16384, 16640, 16896, + 17152, 17408, 15872, 16128, 16384, 16640, 16896, 17152, + 17408, 15872, 16128, 16384, 16640, 16896, 17152, 17408, + 15872, 16128, 16384, 16640, 16896, 17152, 17408, 15872, + 17664, 17920, 17920, 17920, 17920, 17920, 17920, 17920, 17920, 18176, 18176, 18176, 18176, 18176, 18176, 18176, - 18176, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18688, 18944, 19200, 19456, 19712, 19968, - 20224, 20480, 20736, 20992, 21248, 21504, 21760, 5376, - 22016, 22272, 22528, 22784, 23040, 23296, 23552, 23808, - 24064, 24320, 24576, 24832, 25088, 25344, 25600, 25856, - 26112, 26368, 26624, 26880, 27136, 27392, 27648, 27904, - 28160, 5376, 5376, 5376, 28416, 28672, 28928, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 5376, 5376, 5376, 5376, 29184, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 5376, 5376, 29440, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 5376, 5376, 29696, 29952, 27136, 27136, 30208, - 30464, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18432, 18688, 18944, 19200, 19456, 19712, + 19968, 20224, 20480, 20736, 20992, 21248, 21504, 5376, + 21760, 22016, 22272, 22528, 22784, 23040, 23296, 23552, + 23808, 24064, 24320, 24576, 24832, 25088, 25344, 25600, + 25856, 26112, 26368, 26624, 26880, 27136, 27392, 27648, + 27904, 5376, 5376, 5376, 28160, 28416, 28672, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 29184, 5376, 5376, 5376, 5376, 29440, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 5376, 5376, 29696, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 5376, 5376, 29952, 30208, 28928, 28928, 30464, + 30720, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, - 30720, 13312, 13312, 30976, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 13312, 31232, 31488, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 31744, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 32000, 32256, 32512, 32768, 33024, 33280, 33536, - 33792, 10240, 10240, 34048, 27136, 27136, 27136, 27136, - 27136, 34304, 34560, 34816, 27136, 27136, 27136, 27136, - 27136, 35072, 35328, 27136, 27136, 35584, 35840, 36096, - 27136, 36352, 36608, 36864, 37120, 37376, 37632, 37888, - 38144, 38400, 38656, 38912, 27136, 27136, 27136, 27136, - 27136, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 30976, 13312, 13312, 13312, 13312, 31232, 31488, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 31744, 13312, 32000, 32256, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 32512, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 32768, 33024, 33280, 33536, 33792, 34048, 34304, 34560, + 34816, 10240, 10240, 35072, 28928, 28928, 28928, 28928, + 35328, 35584, 35840, 36096, 28928, 36352, 28928, 28928, + 36608, 36864, 37120, 28928, 28928, 37376, 37632, 37888, + 28928, 38144, 38400, 38656, 38912, 39168, 39424, 39680, + 39936, 40192, 40448, 40704, 40960, 28928, 28928, 28928, + 28928, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, @@ -1291,605 +1671,596 @@ static const utf8proc_uint16_t utf8proc_stage1table[] = { 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, - 13312, 13312, 13312, 13312, 13312, 13312, 13312, 39168, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 41216, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, - 39424, 39680, 13312, 13312, 13312, 13312, 13312, 13312, + 41472, 41728, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, - 13312, 13312, 13312, 13312, 13312, 13312, 13312, 39936, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 41984, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, - 13312, 13312, 13312, 13312, 40192, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 40448, 40704, 40960, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 41216, 41472, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 27136, 27136, 27136, 27136, 27136, 27136, 27136, - 27136, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 41728, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 41728, }; + 13312, 13312, 13312, 13312, 42240, 13312, 13312, 42496, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 42752, 43008, 43264, 28928, 28928, 28928, 28928, + 28928, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 43520, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 43776, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 44032, 44288, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 28928, 28928, 28928, 28928, 28928, 28928, 28928, + 28928, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 44544, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 44544, }; static const utf8proc_uint16_t utf8proc_stage2table[] = { - 1, 2, 2, 2, 2, 2, 2, - 2, 2, 3, 4, 3, 5, 6, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 7, 7, 7, - 3, 8, 9, 9, 10, 11, 10, 9, - 9, 12, 13, 9, 14, 15, 16, 15, - 15, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 15, 9, 18, 19, 20, - 9, 9, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 12, 9, 13, 47, - 48, 47, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 12, 75, 13, 75, - 2, 2, 2, 2, 2, 2, 7, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 76, 9, 11, 11, 11, 11, 77, - 9, 78, 79, 80, 81, 75, 82, 79, - 83, 84, 85, 86, 87, 88, 89, 9, - 9, 90, 91, 92, 93, 94, 95, 96, - 9, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, - 75, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 146, 147, 148, 149, 150, - 75, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 215, 300, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 3, 2, 4, 5, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 6, 6, 6, + 2, 7, 8, 8, 9, 10, 9, 8, + 8, 11, 12, 8, 13, 14, 15, 14, + 14, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 14, 8, 17, 18, 19, + 8, 8, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 11, 8, 12, 46, + 47, 46, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 11, 74, 12, 74, + 1, 1, 1, 1, 1, 1, 6, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 75, 8, 10, 10, 10, 10, 76, + 8, 77, 78, 79, 80, 74, 81, 78, + 82, 83, 84, 85, 86, 87, 88, 8, + 8, 89, 90, 91, 92, 93, 94, 95, + 8, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, + 74, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, + 74, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - 309, 310, 311, 312, 215, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 215, 215, 327, 328, 329, - 330, 331, 332, 333, 334, 335, 336, 337, - 338, 339, 340, 215, 341, 342, 343, 215, - 344, 341, 341, 341, 341, 345, 346, 347, - 348, 349, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 430, 431, 432, 433, 434, 435, - 436, 437, 215, 438, 439, 440, 441, 442, - 443, 444, 445, 446, 447, 448, 449, 450, - 451, 452, 453, 454, 455, 215, 215, 215, - 215, 215, 215, 456, 457, 458, 459, 460, - 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 479, 480, 481, 482, 215, 483, - 484, 215, 485, 215, 486, 487, 215, 215, - 215, 488, 489, 215, 490, 215, 491, 492, - 215, 493, 494, 495, 496, 497, 215, 215, - 498, 215, 499, 500, 215, 215, 501, 215, - 215, 215, 215, 215, 215, 215, 502, 215, - 215, 503, 215, 504, 505, 215, 215, 215, - 506, 507, 508, 509, 510, 511, 215, 215, - 215, 215, 215, 512, 215, 341, 215, 215, - 215, 215, 215, 215, 215, 215, 513, 514, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 515, 516, 517, 518, 519, 520, 521, - 522, 523, 524, 524, 525, 525, 525, 525, - 525, 525, 525, 526, 526, 526, 526, 524, - 524, 524, 524, 524, 524, 524, 524, 524, - 524, 525, 525, 526, 526, 526, 526, 526, - 526, 527, 528, 529, 530, 531, 532, 526, - 526, 533, 534, 535, 536, 537, 526, 526, - 526, 526, 526, 526, 526, 524, 526, 525, - 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, - 526, 538, 539, 540, 541, 542, 543, 544, - 545, 546, 547, 548, 549, 550, 543, 543, - 551, 543, 552, 543, 553, 554, 555, 556, - 556, 556, 556, 555, 557, 556, 556, 556, - 556, 556, 558, 558, 559, 560, 561, 562, - 563, 564, 556, 556, 556, 556, 565, 566, - 556, 567, 568, 556, 556, 569, 569, 569, - 569, 570, 556, 556, 556, 556, 543, 543, - 543, 571, 572, 573, 574, 575, 576, 543, - 556, 556, 556, 543, 543, 543, 556, 556, - 577, 543, 543, 543, 556, 556, 556, 556, - 543, 555, 556, 556, 543, 578, 579, 579, - 578, 579, 579, 578, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 543, - 543, 580, 581, 582, 583, 584, 526, 585, - 586, 0, 0, 587, 588, 589, 590, 591, - 592, 0, 0, 0, 0, 88, 593, 594, - 595, 596, 597, 598, 0, 599, 0, 600, - 601, 602, 603, 604, 605, 606, 607, 608, - 609, 610, 611, 612, 613, 614, 615, 616, - 617, 618, 619, 0, 620, 621, 622, 623, - 624, 625, 626, 627, 628, 629, 630, 631, - 632, 633, 634, 635, 636, 637, 638, 639, - 640, 641, 642, 643, 644, 645, 646, 647, - 648, 649, 650, 651, 652, 653, 654, 655, - 656, 657, 658, 659, 660, 661, 662, 663, - 664, 665, 666, 667, 668, 669, 670, 671, + 309, 310, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, + 349, 345, 345, 345, 345, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, + 369, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, + 417, 418, 419, 420, 421, 422, 423, 424, + 425, 426, 427, 428, 429, 430, 431, 432, + 433, 434, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, + 449, 450, 451, 452, 453, 454, 455, 456, + 457, 458, 459, 460, 461, 462, 463, 464, + 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 483, 484, 485, 486, 487, 488, + 489, 490, 491, 492, 493, 494, 495, 496, + 497, 498, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, + 513, 514, 515, 516, 517, 518, 519, 520, + 521, 522, 523, 524, 525, 526, 527, 528, + 529, 530, 531, 532, 533, 534, 535, 536, + 537, 538, 539, 540, 541, 542, 543, 544, + 545, 546, 547, 548, 549, 550, 551, 552, + 553, 554, 555, 556, 557, 345, 558, 559, + 560, 561, 562, 563, 564, 565, 566, 567, + 568, 569, 570, 571, 572, 573, 574, 575, + 576, 577, 578, 579, 580, 581, 582, 583, + 584, 585, 586, 587, 588, 589, 590, 591, + 592, 593, 594, 594, 595, 595, 595, 595, + 595, 596, 597, 46, 46, 46, 46, 594, + 594, 594, 594, 594, 594, 594, 594, 594, + 594, 595, 595, 46, 46, 46, 46, 46, + 46, 598, 599, 600, 601, 602, 603, 46, + 46, 604, 605, 606, 607, 608, 46, 46, + 46, 46, 46, 46, 46, 594, 46, 595, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 609, 610, 611, 612, 613, 614, 615, + 616, 617, 618, 619, 620, 621, 614, 614, + 622, 614, 623, 614, 624, 625, 626, 627, + 627, 627, 627, 626, 628, 627, 627, 627, + 627, 627, 629, 629, 630, 631, 632, 633, + 634, 635, 627, 627, 627, 627, 636, 637, + 627, 638, 639, 627, 627, 640, 640, 640, + 640, 641, 627, 627, 627, 627, 614, 614, + 614, 642, 643, 644, 645, 646, 647, 614, + 627, 627, 627, 614, 614, 614, 627, 627, + 648, 614, 614, 614, 627, 627, 627, 627, + 614, 626, 627, 627, 614, 649, 650, 650, + 649, 650, 650, 649, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 614, + 614, 651, 652, 653, 654, 655, 46, 656, + 657, 0, 0, 658, 659, 660, 661, 662, + 663, 0, 0, 0, 0, 87, 664, 665, + 666, 667, 668, 669, 0, 670, 0, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, - 688, 689, 690, 691, 692, 693, 694, 695, - 696, 697, 698, 699, 700, 701, 702, 75, - 703, 704, 705, 706, 707, 215, 708, 709, - 710, 711, 712, 713, 714, 715, 716, 717, - 718, 719, 720, 721, 722, 723, 724, 725, - 726, 727, 728, 729, 730, 731, 732, 733, - 734, 735, 736, 737, 738, 739, 740, 741, - 742, 743, 744, 745, 746, 747, 748, 749, - 750, 751, 752, 753, 754, 755, 756, 757, - 758, 759, 760, 761, 762, 763, 764, 765, - 766, 767, 768, 769, 770, 771, 772, 773, + 688, 689, 690, 0, 691, 692, 693, 694, + 695, 696, 697, 698, 699, 700, 701, 702, + 703, 704, 705, 706, 707, 708, 709, 710, + 711, 712, 713, 714, 715, 716, 717, 718, + 719, 720, 721, 722, 723, 724, 725, 726, + 727, 728, 729, 730, 731, 732, 733, 734, + 735, 736, 737, 738, 739, 740, 741, 742, + 743, 744, 745, 746, 747, 748, 749, 750, + 751, 752, 753, 754, 755, 756, 757, 758, + 759, 760, 761, 762, 763, 764, 765, 766, + 767, 768, 769, 770, 771, 772, 773, 74, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, @@ -1898,17 +2269,17 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, - 838, 839, 840, 841, 543, 543, 543, 543, - 543, 842, 842, 843, 844, 845, 846, 847, - 848, 849, 850, 851, 852, 853, 854, 855, - 856, 857, 858, 859, 860, 861, 862, 863, - 864, 865, 866, 867, 868, 869, 870, 871, - 872, 873, 874, 875, 876, 877, 878, 879, - 880, 881, 882, 883, 884, 885, 886, 887, - 888, 889, 890, 891, 892, 893, 894, 895, - 896, 897, 898, 899, 900, 901, 902, 903, - 904, 905, 906, 907, 908, 909, 910, 911, - 912, 913, 914, 915, 916, 917, 918, 919, + 838, 839, 840, 841, 842, 843, 844, 845, + 846, 847, 848, 849, 850, 851, 852, 853, + 854, 855, 856, 857, 858, 859, 860, 861, + 862, 863, 864, 865, 866, 867, 868, 869, + 870, 871, 872, 873, 874, 875, 876, 877, + 878, 879, 880, 881, 882, 883, 884, 885, + 886, 887, 888, 889, 890, 891, 892, 893, + 894, 895, 896, 897, 898, 899, 900, 901, + 902, 903, 904, 905, 906, 907, 908, 909, + 910, 911, 912, 913, 614, 614, 614, 614, + 614, 914, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, @@ -1920,2614 +2291,2769 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, - 1008, 0, 1009, 1010, 1011, 1012, 1013, 1014, - 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, - 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, - 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, - 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, - 0, 0, 525, 1047, 1047, 1047, 1047, 1047, - 1047, 215, 1048, 1049, 1050, 1051, 1052, 1053, - 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, - 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, - 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, - 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, - 1086, 215, 1047, 1087, 0, 0, 77, 77, - 11, 0, 556, 543, 543, 543, 543, 556, - 543, 543, 543, 1088, 556, 543, 543, 543, - 543, 543, 543, 556, 556, 556, 556, 556, - 556, 543, 543, 556, 543, 543, 1088, 1089, - 543, 1090, 1091, 1092, 1093, 1094, 1095, 1096, - 1097, 1098, 1099, 1099, 1100, 1101, 1102, 1103, - 1104, 1105, 1106, 1107, 1105, 543, 556, 1105, - 1098, 0, 0, 0, 0, 0, 0, 0, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 0, 0, 0, 0, - 1108, 1108, 1108, 1108, 1105, 1105, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1109, 1109, 1109, 1109, 1109, 1109, 75, - 75, 1110, 10, 10, 1111, 15, 1112, 77, - 77, 543, 543, 543, 543, 543, 543, 543, - 543, 1113, 1114, 1115, 1112, 1116, 0, 1112, - 1112, 1117, 1117, 1118, 1119, 1120, 1121, 1122, - 1123, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1124, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1125, 1117, 1126, 1127, 1128, 1129, 1113, - 1114, 1115, 1130, 1131, 1132, 1133, 1134, 556, - 543, 543, 543, 543, 543, 556, 543, 543, - 556, 1135, 1135, 1135, 1135, 1135, 1135, 1135, - 1135, 1135, 1135, 10, 1136, 1136, 1112, 1117, - 1117, 1137, 1117, 1117, 1117, 1117, 1138, 1139, - 1140, 1141, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1142, 1143, 1144, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1145, 1146, 1112, 1147, 543, - 543, 543, 543, 543, 543, 543, 1109, 77, - 543, 543, 543, 543, 556, 543, 1124, 1124, - 543, 543, 77, 556, 543, 543, 556, 1117, - 1117, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 1117, 1117, 1117, 1148, 1148, - 1117, 1112, 1112, 1112, 1112, 1112, 1112, 1112, - 1112, 1112, 1112, 1112, 1112, 1112, 1112, 0, - 1149, 1117, 1150, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 543, 556, 543, 543, 556, 543, 543, - 556, 556, 556, 543, 556, 556, 543, 556, - 543, 543, 543, 556, 543, 556, 543, 556, - 543, 556, 543, 543, 0, 0, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1117, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1152, 1152, 1152, 1152, 1152, 1152, 1152, - 1152, 1152, 1152, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 543, 543, 543, 543, - 543, 543, 543, 556, 543, 1153, 1153, 77, - 9, 9, 9, 1153, 0, 0, 556, 1154, - 1154, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 543, - 543, 543, 543, 1153, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 1153, 543, 543, - 543, 1153, 543, 543, 543, 543, 543, 0, - 0, 1105, 1105, 1105, 1105, 1105, 1105, 1105, - 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 556, 556, 556, 0, 0, 1105, - 0, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 0, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 556, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 1109, 556, 543, 543, 556, - 543, 543, 556, 543, 543, 543, 556, 556, - 556, 1127, 1128, 1129, 543, 543, 543, 556, - 543, 543, 556, 556, 543, 543, 543, 543, - 543, 1151, 1151, 1151, 1155, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 1156, 1157, 341, 341, 341, 341, 341, - 341, 1158, 1159, 341, 1160, 1161, 341, 341, - 341, 341, 341, 1151, 1155, 1162, 341, 1155, - 1155, 1155, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1155, 1155, 1155, 1155, 1163, 1155, - 1155, 341, 543, 556, 543, 543, 1151, 1151, - 1151, 1164, 1165, 1166, 1167, 1168, 1169, 1170, - 1171, 341, 341, 1151, 1151, 1047, 1047, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1047, 525, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1151, 1155, 1155, 0, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 0, - 341, 341, 0, 0, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 0, 0, 0, 341, - 341, 341, 341, 0, 0, 1173, 341, 1174, - 1155, 1155, 1151, 1151, 1151, 1151, 0, 0, - 1175, 1155, 0, 0, 1176, 1177, 1163, 341, - 0, 0, 0, 0, 0, 0, 0, 0, - 1178, 0, 0, 0, 0, 1179, 1180, 0, - 1181, 341, 341, 1151, 1151, 0, 0, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 341, 341, 11, 11, 1182, 1182, 1182, - 1182, 1182, 1182, 841, 11, 341, 1047, 543, - 0, 0, 1151, 1151, 1155, 0, 341, 341, - 341, 341, 341, 341, 0, 0, 0, 0, - 341, 341, 0, 0, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 1183, 0, 341, 1184, - 0, 341, 341, 0, 0, 1173, 0, 1155, - 1155, 1155, 1151, 1151, 0, 0, 0, 0, - 1151, 1151, 0, 0, 1151, 1151, 1163, 0, - 0, 0, 1151, 0, 0, 0, 0, 0, - 0, 0, 1185, 1186, 1187, 341, 0, 1188, - 0, 0, 0, 0, 0, 0, 0, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1151, 1151, 341, 341, 341, 1151, 1047, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1151, 1151, 1155, 0, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 0, - 341, 341, 341, 0, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 0, 341, 341, - 341, 341, 341, 0, 0, 1173, 341, 1155, - 1155, 1155, 1151, 1151, 1151, 1151, 1151, 0, - 1151, 1151, 1155, 0, 1155, 1155, 1163, 0, - 0, 341, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 1151, 1151, 0, 0, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1047, 11, 0, 0, 0, 0, 0, - 0, 0, 341, 1151, 1151, 1151, 1151, 1151, - 1151, 0, 1151, 1155, 1155, 0, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 0, - 341, 341, 0, 0, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 0, 341, 341, - 341, 341, 341, 0, 0, 1173, 341, 1189, - 1151, 1155, 1151, 1151, 1151, 1151, 0, 0, - 1190, 1191, 0, 0, 1192, 1193, 1163, 0, - 0, 0, 0, 0, 0, 0, 0, 1194, - 1195, 0, 0, 0, 0, 1196, 1197, 0, - 341, 341, 341, 1151, 1151, 0, 0, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 841, 341, 1182, 1182, 1182, 1182, 1182, - 1182, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1151, 341, 0, 341, 341, - 341, 341, 341, 341, 0, 0, 0, 341, - 341, 341, 0, 1198, 341, 1199, 341, 0, - 0, 0, 341, 341, 0, 341, 0, 341, - 341, 0, 0, 0, 341, 341, 0, 0, - 0, 341, 341, 341, 0, 0, 0, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 0, 0, 0, 0, 1200, - 1155, 1151, 1155, 1155, 0, 0, 0, 1201, - 1202, 1155, 0, 1203, 1204, 1205, 1163, 0, - 0, 341, 0, 0, 0, 0, 0, 0, - 1206, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1182, 1182, 1182, 77, 77, 77, 77, - 77, 77, 11, 77, 0, 0, 0, 0, - 0, 1151, 1155, 1155, 1155, 1151, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 0, 0, 0, 341, 1151, - 1151, 1151, 1155, 1155, 1155, 1155, 0, 1207, - 1151, 1208, 0, 1151, 1151, 1151, 1163, 0, - 0, 0, 0, 0, 0, 0, 1209, 1210, - 0, 341, 341, 341, 0, 0, 0, 0, - 0, 341, 341, 1151, 1151, 0, 0, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, + 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, + 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, + 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, + 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, + 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, + 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, + 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, + 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, + 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, + 1080, 0, 1081, 1082, 1083, 1084, 1085, 1086, + 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, + 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, + 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, + 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, + 0, 0, 595, 1119, 1119, 1119, 1119, 1119, + 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, + 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, + 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, + 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, + 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, + 1159, 1160, 1119, 1161, 0, 0, 76, 76, + 10, 0, 627, 614, 614, 614, 614, 627, + 614, 614, 614, 1162, 627, 614, 614, 614, + 614, 614, 614, 627, 627, 627, 627, 627, + 627, 614, 614, 627, 614, 614, 1162, 1163, + 614, 1164, 1165, 1166, 1167, 1168, 1169, 1170, + 1171, 1172, 1173, 1173, 1174, 1175, 1176, 1177, + 1178, 1179, 1180, 1181, 1179, 614, 627, 1179, 1172, 0, 0, 0, 0, 0, 0, 0, - 1047, 1211, 1211, 1211, 1211, 1211, 1211, 1211, - 841, 341, 1151, 1155, 1155, 1047, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 0, 341, 341, - 341, 341, 341, 0, 0, 1173, 341, 1155, - 1212, 1213, 1155, 1214, 1155, 1155, 0, 1215, - 1216, 1217, 0, 1218, 1219, 1151, 1163, 0, - 0, 0, 0, 0, 0, 0, 1220, 1221, - 0, 0, 0, 0, 0, 0, 0, 341, - 0, 341, 341, 1151, 1151, 0, 0, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 0, 341, 341, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1151, 1151, 1155, 1155, 0, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1163, 1163, 341, 1222, - 1155, 1155, 1151, 1151, 1151, 1151, 0, 1223, - 1224, 1155, 0, 1225, 1226, 1227, 1163, 1228, - 841, 0, 0, 0, 0, 341, 341, 341, - 1229, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 341, 341, 341, 1151, 1151, 0, 0, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 841, 341, 341, 341, 341, 341, - 341, 0, 0, 1155, 1155, 0, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 0, 0, 0, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 0, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 0, 341, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 0, 0, 1230, 0, 0, 0, 0, - 1231, 1155, 1155, 1151, 1151, 1151, 0, 1151, - 0, 1155, 1232, 1233, 1155, 1234, 1235, 1236, - 1237, 0, 0, 0, 0, 0, 0, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 0, 0, 1155, 1155, 1047, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1151, 341, 1238, 1151, 1151, 1151, - 1151, 1239, 1239, 1163, 0, 0, 0, 0, - 11, 341, 341, 341, 341, 341, 341, 525, - 1151, 1240, 1240, 1240, 1240, 1151, 1151, 1151, - 1047, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 1047, 1047, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 341, 341, 0, 341, 0, 341, - 341, 341, 341, 341, 0, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 0, 341, 0, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1151, 341, 1241, 1151, 1151, 1151, - 1151, 1242, 1242, 1163, 1151, 1151, 341, 0, - 0, 341, 341, 341, 341, 341, 0, 525, - 0, 1243, 1243, 1243, 1243, 1151, 1151, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 1244, 1245, 341, - 341, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 841, 841, 841, 1047, 1047, 1047, - 1047, 1047, 1047, 1047, 1047, 1246, 1047, 1047, - 1047, 1047, 1047, 1047, 841, 1047, 841, 841, - 841, 556, 556, 841, 841, 841, 841, 841, - 841, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 841, 556, 841, - 556, 841, 1247, 12, 13, 12, 13, 1155, - 1155, 341, 341, 341, 1248, 341, 341, 341, - 341, 0, 341, 341, 341, 341, 1249, 341, - 341, 341, 341, 1250, 341, 341, 341, 341, - 1251, 341, 341, 341, 341, 1252, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1253, 341, 341, 341, 0, 0, - 0, 0, 1254, 1255, 1256, 1257, 1258, 1259, - 1260, 1261, 1262, 1255, 1255, 1255, 1255, 1151, - 1155, 1255, 1263, 543, 543, 1163, 1047, 543, - 543, 341, 341, 341, 341, 341, 1151, 1151, - 1151, 1151, 1151, 1151, 1264, 1151, 1151, 1151, - 1151, 0, 1151, 1151, 1151, 1151, 1265, 1151, - 1151, 1151, 1151, 1266, 1151, 1151, 1151, 1151, - 1267, 1151, 1151, 1151, 1151, 1268, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1269, 1151, 1151, 1151, 0, 841, - 841, 841, 841, 841, 841, 841, 841, 556, - 841, 841, 841, 841, 841, 841, 0, 841, - 841, 1047, 1047, 1047, 1047, 1047, 841, 841, - 841, 841, 1047, 1047, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 1270, 1271, - 341, 341, 341, 341, 1272, 1272, 1151, 1273, - 1151, 1151, 1155, 1151, 1151, 1151, 1151, 1151, - 1173, 1272, 1163, 1163, 1155, 1155, 1151, 1151, - 341, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 1047, 1047, 1047, 1047, 1047, - 1047, 341, 341, 341, 341, 341, 341, 1155, - 1155, 1151, 1151, 341, 341, 341, 341, 1151, - 1151, 1151, 341, 1272, 1272, 1272, 341, 341, - 1272, 1272, 1272, 1272, 1272, 1272, 1272, 341, - 341, 341, 1151, 1151, 1151, 1151, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 1151, 1272, 1155, 1151, 1151, - 1272, 1272, 1272, 1272, 1272, 1272, 556, 341, - 1272, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 1272, 1272, 1272, 1151, 841, - 841, 1274, 1275, 1276, 1277, 1278, 1279, 1280, - 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, - 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, - 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, - 1305, 1306, 1307, 1308, 1309, 1310, 1311, 0, - 1312, 0, 0, 0, 0, 0, 1313, 0, - 0, 1314, 1315, 1316, 1317, 1318, 1319, 1320, - 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, - 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, - 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344, - 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, - 1353, 1354, 1355, 1356, 1047, 1357, 1358, 1359, - 1360, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1362, 1363, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 0, 341, 341, 341, 341, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 0, 341, 341, 341, 341, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 0, 0, 543, 543, - 543, 1047, 1047, 1047, 1047, 1047, 1047, 1047, - 1047, 1047, 1182, 1182, 1182, 1182, 1182, 1182, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 0, 0, 0, 0, 0, - 0, 1366, 1367, 1368, 1369, 1370, 1371, 1372, - 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, - 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, - 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, - 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, - 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, - 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, - 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, - 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, - 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, - 1445, 1446, 1447, 1448, 1449, 1450, 1451, 0, - 0, 1452, 1453, 1454, 1455, 1456, 1457, 0, - 0, 1087, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 841, 1047, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 8, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 12, 13, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1047, 1047, 1047, 1458, - 1458, 1458, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 341, - 341, 341, 341, 1151, 1151, 1163, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 1151, 1151, 1163, 1047, 1047, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 1151, 1151, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 341, - 341, 341, 0, 1151, 1151, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 577, 577, 1155, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1155, - 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1151, - 1155, 1155, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1163, 1151, 1047, 1047, 1047, - 525, 1047, 1047, 1047, 11, 341, 543, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 1211, 1211, 1211, 1211, 1211, 1211, 1211, - 1211, 1211, 1211, 0, 0, 0, 0, 0, - 0, 9, 9, 9, 9, 9, 9, 1087, - 9, 9, 9, 9, 577, 577, 577, 1459, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 525, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 1151, 1151, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1089, 341, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 0, 1151, 1151, 1151, 1155, 1155, 1155, 1155, - 1151, 1151, 1155, 1155, 1155, 0, 0, 0, - 0, 1155, 1155, 1151, 1155, 1155, 1155, 1155, - 1155, 1155, 1088, 543, 556, 0, 0, 0, - 0, 77, 0, 0, 0, 9, 9, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 0, - 0, 341, 341, 341, 341, 341, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 0, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 1182, 0, 0, 0, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 543, 556, 1155, 1155, 1151, 0, 0, 1047, - 1047, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 1155, 1151, - 1155, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 0, 1163, 1272, 1151, 1272, 1272, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1155, 1155, - 1155, 1155, 1155, 1155, 1151, 1151, 543, 543, - 543, 543, 543, 543, 543, 543, 0, 0, - 556, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 1047, 1047, 1047, 1047, 1047, 1047, 1047, - 525, 1047, 1047, 1047, 1047, 1047, 1047, 0, - 0, 543, 543, 543, 543, 543, 556, 556, - 556, 556, 556, 556, 543, 543, 556, 842, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1151, 1151, 1151, 1151, 1155, 1460, 1461, - 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, - 341, 341, 1470, 1471, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 1173, 1472, 1151, - 1151, 1151, 1151, 1473, 1474, 1475, 1476, 1477, - 1478, 1479, 1480, 1481, 1482, 1483, 341, 341, - 341, 341, 341, 341, 341, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 1047, 1047, 1047, 1047, 1047, - 1047, 1047, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 543, 556, 543, 543, - 543, 543, 543, 543, 543, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 0, 0, - 0, 1151, 1151, 1155, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1155, 1151, 1151, 1151, 1151, 1155, - 1155, 1151, 1151, 1483, 1163, 1151, 1151, 341, - 341, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 1173, - 1155, 1151, 1151, 1155, 1155, 1155, 1151, 1155, - 1151, 1151, 1151, 1483, 1483, 0, 0, 0, - 0, 0, 0, 0, 0, 1047, 1047, 1047, - 1047, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 1155, 1155, 1155, - 1155, 1155, 1155, 1155, 1155, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1155, 1155, 1151, - 1173, 0, 0, 0, 1047, 1047, 1047, 1047, - 1047, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 341, 341, - 341, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 525, 525, 525, 525, 525, 525, 1047, - 1047, 1484, 1485, 1486, 1487, 1488, 1488, 1489, - 1490, 1491, 0, 0, 0, 0, 0, 0, - 0, 1492, 1493, 1494, 1495, 1496, 1497, 1498, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 0, 0, 0, 0, + 1182, 1182, 1182, 1182, 1179, 1179, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1183, 1183, 1183, 1183, 1183, 1183, 74, + 74, 1184, 9, 9, 1185, 14, 1186, 76, + 76, 614, 614, 614, 614, 614, 614, 614, + 614, 1187, 1188, 1189, 1186, 1190, 1186, 1186, + 1186, 1191, 1191, 1192, 1193, 1194, 1195, 1196, + 1197, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1198, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1199, 1191, 1200, 1201, 1202, 1203, 1187, + 1188, 1189, 1204, 1205, 1206, 1207, 1208, 627, + 614, 614, 614, 614, 614, 627, 614, 614, + 627, 1209, 1209, 1209, 1209, 1209, 1209, 1209, + 1209, 1209, 1209, 9, 1210, 1210, 1186, 1191, + 1191, 1211, 1191, 1191, 1191, 1191, 1212, 1213, + 1214, 1215, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1216, 1217, 1218, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1219, 1220, 1186, 1221, 614, + 614, 614, 614, 614, 614, 614, 1183, 76, + 614, 614, 614, 614, 627, 614, 1198, 1198, + 614, 614, 76, 627, 614, 614, 627, 1191, + 1191, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 1191, 1191, 1191, 1222, 1222, + 1191, 1186, 1186, 1186, 1186, 1186, 1186, 1186, + 1186, 1186, 1186, 1186, 1186, 1186, 1186, 0, + 1223, 1191, 1224, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 614, 627, 614, 614, 627, 614, 614, + 627, 627, 627, 614, 627, 627, 614, 627, + 614, 614, 614, 627, 614, 627, 614, 627, + 614, 627, 614, 614, 0, 0, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1191, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 614, 614, 614, 614, + 614, 614, 614, 627, 614, 1227, 1227, 76, + 8, 8, 8, 1227, 0, 0, 627, 1228, + 1228, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 614, + 614, 614, 614, 1227, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 1227, 614, 614, + 614, 1227, 614, 614, 614, 614, 614, 0, + 0, 1179, 1179, 1179, 1179, 1179, 1179, 1179, + 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 627, 627, 627, 0, 0, 1179, + 0, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 0, 0, 0, 0, + 0, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1229, 1191, 1191, 1191, 1191, 1191, 1191, + 0, 1183, 1183, 0, 0, 0, 0, 0, + 0, 614, 627, 627, 627, 614, 614, 614, + 614, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1198, 614, 614, 614, 614, 614, + 627, 627, 627, 627, 627, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 1183, 627, 614, 614, 627, + 614, 614, 627, 614, 614, 614, 627, 627, + 627, 1201, 1202, 1203, 614, 614, 614, 627, + 614, 614, 627, 627, 614, 614, 614, 614, + 614, 1225, 1225, 1225, 1230, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1232, 1233, 1231, 1231, 1231, 1231, 1231, + 1231, 1234, 1235, 1231, 1236, 1237, 1231, 1231, + 1231, 1231, 1231, 1225, 1230, 1238, 345, 1230, + 1230, 1230, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1230, 1230, 1230, 1230, 1239, 1230, + 1230, 345, 614, 627, 614, 614, 1225, 1225, + 1225, 1240, 1241, 1242, 1243, 1244, 1245, 1246, + 1247, 345, 345, 1225, 1225, 1119, 1119, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1119, 595, 345, 345, 345, 345, 345, + 345, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 345, 1225, 1230, 1230, 0, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 0, + 345, 345, 0, 0, 345, 345, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 0, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 0, 1231, 0, 0, 0, 1231, + 1231, 1231, 1231, 0, 0, 1249, 345, 1250, + 1230, 1230, 1225, 1225, 1225, 1225, 0, 0, + 1251, 1230, 0, 0, 1252, 1253, 1239, 345, + 0, 0, 0, 0, 0, 0, 0, 0, + 1254, 0, 0, 0, 0, 1255, 1256, 0, + 1257, 345, 345, 1225, 1225, 0, 0, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1231, 1231, 10, 10, 1258, 1258, 1258, + 1258, 1258, 1258, 913, 10, 345, 1119, 614, + 0, 0, 1225, 1225, 1230, 0, 345, 345, + 345, 345, 345, 345, 0, 0, 0, 0, + 345, 345, 0, 0, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 1259, 0, 345, 1260, + 0, 345, 345, 0, 0, 1249, 0, 1230, + 1230, 1230, 1225, 1225, 0, 0, 0, 0, + 1225, 1225, 0, 0, 1225, 1225, 1261, 0, + 0, 0, 1225, 0, 0, 0, 0, 0, + 0, 0, 1262, 1263, 1264, 345, 0, 1265, + 0, 0, 0, 0, 0, 0, 0, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1225, 1225, 345, 345, 345, 1225, 1119, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1225, 1225, 1230, 0, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 0, + 345, 345, 345, 0, 345, 345, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 0, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 0, 1231, 1231, 0, 1231, 1231, + 1231, 1231, 1231, 0, 0, 1249, 345, 1230, + 1230, 1230, 1225, 1225, 1225, 1225, 1225, 0, + 1225, 1225, 1230, 0, 1230, 1230, 1239, 0, + 0, 345, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 1225, 1225, 0, 0, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1119, 10, 0, 0, 0, 0, 0, + 0, 0, 1231, 1225, 1225, 1225, 1225, 1225, + 1225, 0, 1225, 1230, 1230, 0, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 0, + 345, 345, 0, 0, 345, 345, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 0, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 0, 1231, 1231, 0, 1231, 1231, + 1231, 1231, 1231, 0, 0, 1249, 345, 1266, + 1225, 1230, 1225, 1225, 1225, 1225, 0, 0, + 1267, 1268, 0, 0, 1269, 1270, 1239, 0, + 0, 0, 0, 0, 0, 0, 1225, 1271, + 1272, 0, 0, 0, 0, 1273, 1274, 0, + 1231, 345, 345, 1225, 1225, 0, 0, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 913, 1231, 1258, 1258, 1258, 1258, 1258, + 1258, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1225, 345, 0, 345, 345, + 345, 345, 345, 345, 0, 0, 0, 345, + 345, 345, 0, 1275, 345, 1276, 345, 0, + 0, 0, 345, 345, 0, 345, 0, 345, + 345, 0, 0, 0, 345, 345, 0, 0, + 0, 345, 345, 345, 0, 0, 0, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 0, 0, 0, 0, 1277, + 1230, 1225, 1230, 1230, 0, 0, 0, 1278, + 1279, 1230, 0, 1280, 1281, 1282, 1261, 0, + 0, 345, 0, 0, 0, 0, 0, 0, + 1283, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1258, 1258, 1258, 76, 76, 76, 76, + 76, 76, 10, 76, 0, 0, 0, 0, + 0, 1225, 1230, 1230, 1230, 1225, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 345, + 345, 345, 0, 345, 345, 345, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 0, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 0, 0, 1249, 345, 1225, + 1225, 1225, 1230, 1230, 1230, 1230, 0, 1284, + 1225, 1285, 0, 1225, 1225, 1225, 1239, 0, + 0, 0, 0, 0, 0, 0, 1286, 1287, + 0, 1231, 1231, 1231, 0, 0, 345, 0, + 0, 345, 345, 1225, 1225, 0, 0, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 0, 0, 0, 0, 0, 0, 0, + 1119, 1288, 1288, 1288, 1288, 1288, 1288, 1288, + 913, 345, 1225, 1230, 1230, 1119, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 345, + 345, 345, 0, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 0, 345, 345, + 345, 345, 345, 0, 0, 1249, 345, 1230, + 1289, 1290, 1230, 1291, 1230, 1230, 0, 1292, + 1293, 1294, 0, 1295, 1296, 1225, 1261, 0, + 0, 0, 0, 0, 0, 0, 1297, 1298, + 0, 0, 0, 0, 0, 0, 345, 345, + 0, 345, 345, 1225, 1225, 0, 0, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 0, 345, 345, 1230, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1225, 1225, 1230, 1230, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 345, + 345, 345, 0, 345, 345, 345, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, + 1231, 1231, 1231, 1231, 1299, 1299, 345, 1300, + 1230, 1230, 1225, 1225, 1225, 1225, 0, 1301, + 1302, 1230, 0, 1303, 1304, 1305, 1239, 1306, + 913, 0, 0, 0, 0, 345, 345, 345, + 1307, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 345, 345, 345, 1225, 1225, 0, 0, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 913, 345, 345, 345, 345, 345, + 345, 0, 1225, 1230, 1230, 0, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 0, 0, 0, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 0, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 0, 345, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 0, 0, 1308, 0, 0, 0, 0, + 1309, 1230, 1230, 1225, 1225, 1225, 0, 1225, + 0, 1230, 1310, 1311, 1230, 1312, 1313, 1314, + 1315, 0, 0, 0, 0, 0, 0, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 0, 0, 1230, 1230, 1119, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1225, 345, 1316, 1225, 1225, 1225, + 1225, 1317, 1317, 1299, 0, 0, 0, 0, + 10, 345, 345, 345, 345, 345, 345, 595, + 1225, 1318, 1318, 1318, 1318, 1225, 1225, 1225, + 1119, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1119, 1119, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 345, 345, 0, 345, 0, 345, + 345, 345, 345, 345, 0, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 0, 345, 0, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1225, 345, 1319, 1225, 1225, 1225, + 1225, 1320, 1320, 1299, 1225, 1225, 345, 0, + 0, 345, 345, 345, 345, 345, 0, 595, + 0, 1321, 1321, 1321, 1321, 1225, 1225, 1225, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 1322, 1323, 345, + 345, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 913, 913, 913, 1119, 1119, 1119, + 1119, 1119, 1119, 1119, 1119, 1324, 1119, 1119, + 1119, 1119, 1119, 1119, 913, 1119, 913, 913, + 913, 627, 627, 913, 913, 913, 913, 913, + 913, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 913, 627, 913, + 627, 913, 1325, 11, 12, 11, 12, 1230, + 1230, 345, 345, 345, 1326, 345, 345, 345, + 345, 0, 345, 345, 345, 345, 1327, 345, + 345, 345, 345, 1328, 345, 345, 345, 345, + 1329, 345, 345, 345, 345, 1330, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1331, 345, 345, 345, 0, 0, + 0, 0, 1332, 1333, 1334, 1335, 1336, 1337, + 1338, 1339, 1340, 1333, 1333, 1333, 1333, 1225, + 1230, 1333, 1341, 614, 614, 1299, 1119, 614, + 614, 345, 345, 345, 345, 345, 1225, 1225, + 1225, 1225, 1225, 1225, 1342, 1225, 1225, 1225, + 1225, 0, 1225, 1225, 1225, 1225, 1343, 1225, + 1225, 1225, 1225, 1344, 1225, 1225, 1225, 1225, + 1345, 1225, 1225, 1225, 1225, 1346, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1347, 1225, 1225, 1225, 0, 913, + 913, 913, 913, 913, 913, 913, 913, 627, + 913, 913, 913, 913, 913, 913, 0, 913, + 913, 1119, 1119, 1119, 1119, 1119, 913, 913, + 913, 913, 1119, 1119, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 1348, 1349, + 345, 345, 345, 345, 1350, 1350, 1225, 1351, + 1225, 1225, 1230, 1225, 1225, 1225, 1225, 1225, + 1249, 1350, 1299, 1299, 1230, 1230, 1225, 1225, + 345, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1119, 1119, 1119, 1119, 1119, + 1119, 345, 345, 345, 345, 345, 345, 1230, + 1230, 1225, 1225, 345, 345, 345, 345, 1225, + 1225, 1225, 345, 1350, 1350, 1350, 345, 345, + 1350, 1350, 1350, 1350, 1350, 1350, 1350, 345, + 345, 345, 1225, 1225, 1225, 1225, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 1225, 1350, 1230, 1225, 1225, + 1350, 1350, 1350, 1350, 1350, 1350, 627, 345, + 1350, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1350, 1350, 1350, 1225, 913, + 913, 1352, 1353, 1354, 1355, 1356, 1357, 1358, + 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, + 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, + 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, + 1383, 1384, 1385, 1386, 1387, 1388, 1389, 0, + 1390, 0, 0, 0, 0, 0, 1391, 0, + 0, 1392, 1393, 1394, 1395, 1396, 1397, 1398, + 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, + 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, + 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, + 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, + 1431, 1432, 1433, 1434, 1119, 1435, 1436, 1437, + 1438, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1440, 1441, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 345, 345, 345, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 0, 345, 345, 345, 345, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 345, 345, 345, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 345, 345, 345, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 0, 345, 345, 345, 345, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 345, 345, 345, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 0, 0, 614, 614, + 614, 1119, 1119, 1119, 1119, 1119, 1119, 1119, + 1119, 1119, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 0, 0, 0, 0, 0, + 0, 1444, 1445, 1446, 1447, 1448, 1449, 1450, + 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, + 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, + 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, + 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, + 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, + 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, - 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, - 1531, 1532, 1533, 1534, 0, 0, 1535, 1536, - 1537, 1047, 1047, 1047, 1047, 1047, 1047, 1047, - 1047, 0, 0, 0, 0, 0, 0, 0, - 0, 543, 543, 543, 1047, 569, 556, 556, - 556, 556, 556, 543, 543, 556, 556, 556, - 556, 543, 1155, 569, 569, 569, 569, 569, - 569, 569, 341, 341, 341, 341, 556, 341, - 341, 341, 341, 341, 341, 543, 341, 341, - 1155, 543, 543, 341, 0, 0, 0, 0, - 0, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 1538, 1539, 1540, - 525, 1541, 1542, 1543, 1544, 1545, 1546, 1547, - 1548, 1549, 1550, 1551, 525, 1552, 1553, 1554, - 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, - 1563, 1564, 1565, 1566, 1567, 1568, 1569, 525, - 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, - 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, - 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, - 1594, 1595, 1596, 1597, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 1598, 1599, 215, 215, 215, 1600, 215, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 1601, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 1602, 1603, 1604, 1605, - 1568, 1606, 1607, 1608, 1609, 1610, 1611, 1612, - 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, - 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, - 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, - 1637, 543, 543, 556, 543, 543, 543, 543, - 543, 543, 543, 556, 543, 543, 579, 1638, - 556, 558, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 555, - 1089, 1089, 556, 0, 543, 578, 556, 543, - 556, 1639, 1640, 1641, 1642, 1643, 1644, 1645, - 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, - 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, - 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, - 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, - 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, - 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, - 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, - 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, - 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, - 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, - 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, - 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, - 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, - 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, - 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, - 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, - 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, - 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, - 1790, 1791, 1792, 1793, 1794, 215, 215, 1795, - 215, 1796, 1797, 1798, 1799, 1800, 1801, 1802, - 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, - 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, - 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, - 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, - 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, - 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, - 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, - 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, - 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, - 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, - 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, - 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, - 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, - 1907, 1908, 1909, 1910, 1911, 1912, 1913, 0, - 0, 1914, 1915, 1916, 1917, 1918, 1919, 0, - 0, 1920, 1921, 1922, 1923, 1924, 1925, 1926, - 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, - 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, - 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, - 1951, 1952, 1953, 1954, 1955, 1956, 1957, 0, - 0, 1958, 1959, 1960, 1961, 1962, 1963, 0, - 0, 1964, 1965, 1966, 1967, 1968, 1969, 1970, - 1971, 0, 1972, 0, 1973, 0, 1974, 0, - 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, - 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, - 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 0, - 0, 2006, 2007, 2008, 2009, 2010, 2011, 2012, - 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, - 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, - 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, - 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, - 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, - 2053, 2054, 2055, 2056, 2057, 2058, 0, 2059, - 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, - 2068, 2069, 2070, 2071, 2072, 2073, 0, 2074, - 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, - 2083, 2084, 2085, 2086, 2087, 0, 0, 2088, - 2089, 2090, 2091, 2092, 2093, 0, 2094, 2095, - 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, - 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, - 2112, 0, 0, 2113, 2114, 2115, 0, 2116, + 1523, 1524, 1525, 1526, 1527, 1528, 1529, 0, + 0, 1530, 1531, 1532, 1533, 1534, 1535, 0, + 0, 1161, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 913, 1119, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 7, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 11, 12, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 1119, 1119, 1119, 1536, + 1536, 1536, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 1225, 1225, 1299, 1537, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 1225, 1225, 1537, 1119, 1119, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 1225, 1225, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 345, + 345, 345, 0, 1225, 1225, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 648, 648, 1230, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1225, + 1230, 1230, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1299, 1225, 1119, 1119, 1119, + 595, 1119, 1119, 1119, 10, 345, 614, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 1288, 1288, 1288, 1288, 1288, 1288, 1288, + 1288, 1288, 1288, 0, 0, 0, 0, 0, + 0, 8, 8, 8, 8, 8, 8, 1161, + 8, 8, 8, 8, 648, 648, 648, 1538, + 648, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 595, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 1225, 1225, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1163, 345, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 0, 1225, 1225, 1225, 1230, 1230, 1230, 1230, + 1225, 1225, 1230, 1230, 1230, 0, 0, 0, + 0, 1230, 1230, 1225, 1230, 1230, 1230, 1230, + 1230, 1230, 1162, 614, 627, 0, 0, 0, + 0, 76, 0, 0, 0, 8, 8, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 0, + 0, 345, 345, 345, 345, 345, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1258, 0, 0, 0, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 614, 627, 1230, 1230, 1225, 0, 0, 1119, + 1119, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 1230, 1225, + 1230, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 0, 1299, 1350, 1225, 1350, 1350, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1230, 1230, + 1230, 1230, 1230, 1230, 1225, 1225, 614, 614, + 614, 614, 614, 614, 614, 614, 0, 0, + 627, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 1119, 1119, 1119, 1119, 1119, 1119, 1119, + 595, 1119, 1119, 1119, 1119, 1119, 1119, 0, + 0, 614, 614, 614, 614, 614, 627, 627, + 627, 627, 627, 627, 614, 614, 627, 914, + 627, 627, 614, 614, 627, 627, 614, 614, + 614, 614, 614, 627, 614, 614, 614, 614, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1225, 1225, 1225, 1225, 1230, 1539, 1540, + 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, + 345, 345, 1549, 1550, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 1249, 1551, 1225, + 1225, 1225, 1225, 1552, 1553, 1554, 1555, 1556, + 1557, 1558, 1559, 1560, 1561, 1537, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1119, 1119, 1119, 1119, 1119, + 1119, 1119, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 614, 627, 614, 614, + 614, 614, 614, 614, 614, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 1119, 1119, + 0, 1225, 1225, 1230, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1230, 1225, 1225, 1225, 1225, 1230, + 1230, 1225, 1225, 1537, 1299, 1225, 1225, 345, + 345, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 1249, + 1230, 1225, 1225, 1230, 1230, 1230, 1225, 1230, + 1225, 1225, 1225, 1537, 1537, 0, 0, 0, + 0, 0, 0, 0, 0, 1119, 1119, 1119, + 1119, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1230, 1230, 1225, + 1249, 0, 0, 0, 1119, 1119, 1119, 1119, + 1119, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 345, 345, + 345, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 595, 595, 595, 595, 595, 595, 1119, + 1119, 1562, 1563, 1564, 1565, 1566, 1566, 1567, + 1568, 1569, 0, 0, 0, 0, 0, 0, + 0, 1570, 1571, 1572, 1573, 1574, 1575, 1576, + 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, + 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, + 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, + 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, + 1609, 1610, 1611, 1612, 0, 0, 1613, 1614, + 1615, 1119, 1119, 1119, 1119, 1119, 1119, 1119, + 1119, 0, 0, 0, 0, 0, 0, 0, + 0, 614, 614, 614, 1119, 640, 627, 627, + 627, 627, 627, 614, 614, 627, 627, 627, + 627, 614, 1230, 640, 640, 640, 640, 640, + 640, 640, 345, 345, 345, 345, 627, 345, + 345, 345, 345, 345, 345, 614, 345, 345, + 1230, 614, 614, 345, 0, 0, 0, 0, + 0, 1616, 1617, 1618, 1619, 1620, 1621, 1622, + 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, + 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, + 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, + 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, + 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, + 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, + 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, + 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, + 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, + 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, + 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, + 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, + 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, + 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, + 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, + 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, + 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, + 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, + 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, + 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, + 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, + 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, + 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, + 1807, 614, 614, 627, 614, 614, 614, 614, + 614, 614, 614, 627, 614, 614, 650, 1808, + 627, 629, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 626, + 1163, 1163, 627, 1809, 614, 649, 627, 614, + 627, 1810, 1811, 1812, 1813, 1814, 1815, 1816, + 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, + 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, + 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, + 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, + 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, + 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, + 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, + 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, + 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, + 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, + 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, + 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, + 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, + 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, + 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, + 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, + 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, + 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, + 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, + 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, + 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, + 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, + 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, + 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, + 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, + 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, + 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, + 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, + 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, + 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, + 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, + 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, + 2081, 2082, 2083, 2084, 2085, 2086, 2087, 0, + 0, 2088, 2089, 2090, 2091, 2092, 2093, 0, + 0, 2094, 2095, 2096, 2097, 2098, 2099, 2100, + 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, + 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, - 0, 2125, 2126, 2127, 2127, 2127, 2127, 2127, - 2128, 2127, 2127, 2127, 1459, 2129, 2130, 2131, - 2132, 1087, 2133, 1087, 1087, 1087, 1087, 9, - 2134, 2135, 2136, 2137, 2135, 2135, 2136, 2137, - 2135, 9, 9, 9, 9, 2138, 2139, 2140, - 9, 2141, 2142, 2143, 2144, 2145, 2146, 2147, - 76, 10, 10, 10, 2148, 2149, 9, 2150, - 2151, 9, 81, 93, 9, 2152, 9, 2153, - 48, 48, 9, 9, 9, 2154, 12, 13, - 2155, 2156, 2157, 9, 9, 9, 9, 9, - 9, 9, 9, 75, 9, 48, 9, 9, - 2158, 9, 9, 9, 9, 9, 9, 9, - 2127, 1459, 1459, 1459, 1459, 1459, 0, 2159, - 2160, 2161, 2162, 1459, 1459, 1459, 1459, 1459, - 1459, 2163, 2164, 0, 0, 2165, 2166, 2167, - 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, - 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, - 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, - 0, 2192, 2193, 2194, 2195, 2196, 2197, 2198, - 2199, 2200, 2201, 2202, 2203, 2204, 0, 0, - 0, 11, 11, 11, 11, 11, 11, 11, - 11, 2205, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 543, 543, 569, 569, 543, 543, 543, - 543, 569, 569, 569, 543, 543, 842, 842, - 842, 842, 543, 842, 842, 842, 569, 569, - 543, 556, 543, 569, 569, 556, 556, 556, - 556, 543, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2206, 2207, 2208, 2209, 77, 2210, 2211, - 2212, 77, 2213, 2214, 2215, 2215, 2215, 2216, - 2217, 2218, 2218, 2219, 2220, 77, 2221, 2222, - 77, 75, 2223, 2224, 2225, 2225, 2225, 77, - 77, 2226, 2227, 2228, 77, 2229, 77, 2230, - 77, 2229, 77, 2231, 2232, 2233, 2208, 84, + 2125, 2126, 2127, 2128, 2129, 2130, 2131, 0, + 0, 2132, 2133, 2134, 2135, 2136, 2137, 0, + 0, 2138, 2139, 2140, 2141, 2142, 2143, 2144, + 2145, 0, 2146, 0, 2147, 0, 2148, 0, + 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, + 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, + 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, + 2173, 2174, 2175, 2176, 2177, 2178, 2179, 0, + 0, 2180, 2181, 2182, 2183, 2184, 2185, 2186, + 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, + 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, + 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, + 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, + 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, + 2227, 2228, 2229, 2230, 2231, 2232, 0, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, - 2242, 2243, 2244, 77, 2245, 2246, 2247, 2248, - 2249, 2250, 75, 75, 75, 75, 2251, 2252, - 2234, 2253, 2254, 77, 75, 77, 77, 2255, - 841, 2256, 2257, 2258, 2259, 2260, 2261, 2262, - 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, - 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, - 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, - 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, - 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, - 2303, 1458, 1458, 1458, 2304, 2305, 1458, 1458, - 1458, 1458, 2306, 77, 77, 0, 0, 0, - 0, 2307, 75, 2308, 75, 2309, 79, 79, - 79, 79, 79, 2310, 2311, 77, 77, 77, - 77, 75, 77, 77, 75, 77, 77, 75, - 77, 77, 79, 79, 77, 77, 77, 2312, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 2313, 2314, - 2315, 2316, 77, 2317, 77, 2318, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 2319, 2319, 2320, 2321, 75, 75, - 75, 2322, 2323, 2319, 2324, 2325, 2319, 75, - 75, 75, 2319, 14, 85, 75, 2319, 2319, - 75, 75, 75, 2319, 2319, 2319, 2319, 75, - 2319, 2319, 2319, 2319, 2326, 2327, 2328, 2329, - 75, 75, 75, 75, 2319, 2330, 2331, 2319, - 2332, 2333, 2319, 2319, 2319, 75, 75, 75, - 75, 75, 2319, 75, 2319, 2334, 2319, 2319, - 2319, 2319, 2335, 2319, 2336, 2337, 2338, 2319, - 2339, 2340, 2341, 2319, 2319, 2319, 2342, 75, - 75, 75, 75, 2319, 2319, 2319, 2319, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 2319, 2343, 2344, 2345, 75, 2346, 2347, 2319, - 2319, 2319, 2319, 2319, 2319, 75, 2348, 2349, + 2242, 2243, 2244, 2245, 2246, 2247, 0, 2248, + 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, + 2257, 2258, 2259, 2260, 2261, 0, 0, 2262, + 2263, 2264, 2265, 2266, 2267, 0, 2268, 2269, + 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, + 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, + 2286, 0, 0, 2287, 2288, 2289, 0, 2290, + 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, + 0, 2299, 2300, 2301, 2301, 2301, 2301, 2301, + 2302, 2301, 2301, 2301, 1538, 2303, 2304, 2305, + 2306, 1161, 2307, 1161, 1161, 1161, 1161, 8, + 2308, 2309, 2310, 2311, 2309, 2309, 2310, 2311, + 2309, 8, 8, 8, 8, 2312, 2313, 2314, + 8, 2315, 2316, 2317, 2318, 2319, 2320, 2321, + 75, 9, 9, 9, 2322, 2323, 8, 2324, + 2325, 8, 80, 92, 8, 2326, 8, 2327, + 47, 47, 8, 8, 8, 2328, 11, 12, + 2329, 2330, 2331, 8, 8, 8, 8, 8, + 8, 8, 8, 74, 8, 47, 8, 8, + 2332, 8, 8, 8, 8, 8, 8, 8, + 2301, 1538, 1538, 1538, 1538, 1538, 0, 2333, + 2334, 2335, 2336, 1538, 1538, 1538, 1538, 1538, + 1538, 2337, 2338, 0, 0, 2339, 2340, 2341, + 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, - 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2319, - 2319, 2365, 2366, 2367, 2368, 2369, 2370, 2371, - 2372, 2373, 2374, 2319, 2319, 2319, 75, 75, - 2319, 2319, 2375, 2376, 75, 75, 75, 75, - 75, 2319, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 2377, 2319, 75, 75, 2319, - 2319, 2378, 2379, 2319, 2380, 2381, 2382, 2383, - 2384, 2319, 2319, 2385, 2386, 2387, 2388, 2319, - 2319, 2319, 75, 75, 75, 75, 75, 2319, - 2319, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 2319, 2319, 2319, 2319, 2319, 75, - 75, 2319, 2319, 75, 75, 75, 75, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2389, 2390, 2391, 2392, 2319, 2319, 2319, - 2319, 2319, 2319, 2393, 2394, 2395, 2396, 75, - 75, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 77, 77, 77, 77, 77, 77, 77, - 77, 12, 13, 12, 13, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 2397, 2397, 77, 77, 77, - 77, 2319, 2319, 77, 77, 77, 77, 77, - 77, 79, 2398, 2399, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 77, 75, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 79, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 841, 77, - 77, 77, 77, 77, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 79, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 75, 75, 75, - 75, 75, 75, 77, 77, 77, 77, 77, - 77, 77, 2397, 2397, 2397, 2397, 79, 79, - 79, 2397, 79, 79, 2397, 77, 77, 77, - 77, 79, 79, 79, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2400, 2401, 2402, 2403, 2404, 2405, 2406, - 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, + 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, + 0, 2366, 2367, 2368, 2369, 2370, 2371, 2372, + 2373, 2374, 2375, 2376, 2377, 2378, 0, 0, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 2379, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 614, 614, 640, 640, 614, 614, 614, + 614, 640, 640, 640, 614, 614, 914, 914, + 914, 914, 614, 914, 914, 914, 640, 640, + 614, 627, 614, 640, 640, 627, 627, 627, + 627, 614, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2380, 2381, 2382, 2383, 76, 2384, 2385, + 2386, 76, 2387, 2388, 2389, 2390, 2391, 2392, + 2393, 2394, 2395, 2396, 2397, 76, 2398, 2399, + 76, 74, 2400, 2401, 2402, 2403, 2404, 76, + 76, 2405, 2406, 2407, 76, 2408, 76, 2409, + 76, 2410, 76, 2411, 2412, 2413, 2414, 83, 2415, 2416, 2417, 2418, 2419, 2420, 2421, 2422, - 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, - 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, - 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, - 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, - 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, - 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, - 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, - 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, - 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, - 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, - 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, - 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, - 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, - 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, - 2535, 2536, 2537, 2538, 1211, 1211, 1211, 1211, - 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, - 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, - 1211, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 79, 79, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 79, - 75, 77, 77, 77, 77, 77, 77, 77, - 77, 79, 75, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 75, 75, 75, 2539, 2539, 2540, 2540, - 75, 79, 79, 79, 79, 79, 79, 77, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 77, 2397, 2397, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 2539, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 2397, 79, 79, 79, 79, 79, 79, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 79, 79, 79, 2397, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 2397, 79, 79, 79, 79, 79, - 79, 79, 79, 2397, 2397, 2541, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 2397, 2397, - 79, 79, 79, 79, 79, 2397, 2397, 79, - 79, 79, 79, 79, 79, 79, 79, 2397, - 79, 79, 79, 79, 79, 2397, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 2397, 79, 79, 79, 79, - 79, 79, 79, 2397, 2397, 79, 2397, 79, - 79, 79, 79, 2397, 79, 79, 2397, 79, - 79, 79, 79, 79, 79, 79, 2397, 77, - 77, 79, 79, 2397, 2397, 79, 79, 79, - 79, 79, 79, 79, 77, 79, 77, 79, - 77, 77, 77, 77, 77, 77, 79, 77, - 77, 77, 79, 77, 77, 77, 77, 77, - 77, 2397, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 79, 79, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 79, 77, 77, - 79, 77, 77, 77, 77, 2397, 77, 2397, - 77, 77, 77, 77, 2397, 2397, 2397, 77, - 2397, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 79, 79, 79, 79, - 79, 12, 13, 12, 13, 12, 13, 12, - 13, 12, 13, 12, 13, 12, 13, 1211, - 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, - 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, - 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, - 1211, 1211, 1211, 1211, 1211, 77, 2397, 2397, - 2397, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 79, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 2397, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 2397, 2319, 75, 75, 2319, 2319, 12, 13, - 75, 2319, 2319, 75, 2319, 2319, 2319, 75, - 75, 75, 75, 75, 2319, 2319, 2319, 2319, - 75, 75, 75, 75, 75, 2319, 2319, 2319, - 75, 75, 75, 2319, 2319, 2319, 2319, 12, - 13, 12, 13, 12, 13, 12, 13, 12, - 13, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 2539, 2539, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 12, 13, 12, 13, - 12, 13, 12, 13, 12, 13, 12, 13, - 12, 13, 12, 13, 12, 13, 12, 13, - 12, 13, 75, 75, 2319, 2319, 2319, 2319, - 2319, 2319, 75, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 75, 75, 75, 75, 75, 75, 75, - 75, 2319, 75, 75, 75, 75, 75, 75, - 75, 2319, 2319, 2319, 2319, 2319, 2319, 75, - 75, 75, 2319, 75, 75, 75, 75, 2319, - 2319, 2319, 2319, 2319, 75, 2319, 2319, 75, - 75, 12, 13, 12, 13, 2319, 75, 75, - 75, 75, 2319, 75, 2319, 2319, 2319, 75, - 75, 2319, 2319, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 2319, 2319, 2319, - 2319, 2319, 2319, 75, 75, 12, 13, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 2319, 2319, 2542, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 75, 2319, - 2319, 2319, 2319, 75, 75, 2319, 75, 2319, - 75, 75, 2319, 75, 2319, 2319, 2319, 2319, - 75, 75, 75, 75, 75, 2319, 2319, 75, - 75, 75, 75, 75, 75, 2319, 2319, 2319, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 2319, 2319, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 2319, 2319, 75, - 75, 75, 75, 2319, 2319, 2319, 2319, 75, - 2319, 2319, 75, 75, 2319, 2543, 2544, 2545, - 75, 75, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 75, 75, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 75, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 2319, 2319, 2319, 2319, 2319, 2319, 2319, 2319, - 75, 75, 75, 75, 75, 2546, 2547, 2319, - 75, 75, 75, 2319, 2319, 2319, 2319, 2319, - 75, 75, 75, 75, 75, 2319, 2319, 2319, - 75, 75, 75, 75, 2319, 75, 75, 75, - 2319, 2319, 2319, 2319, 2319, 75, 2319, 75, - 75, 77, 77, 77, 77, 77, 79, 79, - 79, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 2397, 2397, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 77, 77, - 75, 75, 75, 75, 75, 75, 77, 77, - 77, 2397, 77, 77, 77, 77, 2397, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 0, 0, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 2548, - 77, 2549, 2550, 2551, 2552, 2553, 2554, 2555, - 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563, - 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, - 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, - 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, - 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, - 0, 2596, 2597, 2598, 2599, 2600, 2601, 2602, - 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, - 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, - 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, - 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, - 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, - 0, 2643, 2644, 2645, 2646, 2647, 2648, 2649, - 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, - 2658, 2659, 215, 2660, 2661, 215, 2662, 2663, - 215, 215, 215, 215, 215, 2664, 2665, 2666, - 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, - 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, - 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, - 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, - 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, - 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, - 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, - 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, - 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, - 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, - 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, - 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, - 2763, 2764, 2765, 2766, 2767, 215, 77, 77, - 77, 77, 77, 77, 2768, 2769, 2770, 2771, - 543, 543, 543, 2772, 2773, 0, 0, 0, - 0, 0, 9, 9, 9, 9, 1211, 9, - 9, 2774, 2775, 2776, 2777, 2778, 2779, 2780, - 2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, - 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, - 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, - 2805, 2806, 2807, 2808, 2809, 2810, 2811, 0, - 2812, 0, 0, 0, 0, 0, 2813, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 0, 0, 0, 0, 0, 0, 0, - 2814, 1047, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1163, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 543, - 543, 9, 9, 81, 93, 81, 93, 9, - 9, 9, 81, 93, 9, 81, 93, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 1087, 9, 9, 1087, 9, 81, 93, 9, - 9, 81, 93, 12, 13, 12, 13, 12, - 13, 12, 13, 9, 9, 9, 9, 9, - 524, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 1087, 1087, 9, 9, 9, - 9, 1087, 9, 2137, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 0, 2815, 2815, 2815, 2815, - 2816, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2817, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2818, 2819, 2820, 2821, 2822, 2823, 2824, - 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, - 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, - 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, - 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, - 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, - 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, - 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, - 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, - 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, - 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, - 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, - 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, - 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, - 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, - 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, - 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, - 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, - 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, - 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, - 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, - 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, - 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, - 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, - 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, + 2423, 2424, 2425, 76, 2426, 2427, 2428, 2429, + 2430, 2431, 74, 74, 74, 74, 2432, 2433, + 2434, 2435, 2436, 76, 74, 76, 76, 2437, + 913, 2438, 2439, 2440, 2441, 2442, 2443, 2444, + 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, + 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, + 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, + 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, + 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, + 2485, 1536, 1536, 1536, 2486, 2487, 1536, 1536, + 1536, 1536, 2488, 76, 76, 0, 0, 0, + 0, 2489, 74, 2490, 74, 2491, 78, 78, + 78, 78, 78, 2492, 2493, 76, 76, 76, + 76, 74, 76, 76, 74, 76, 76, 74, + 76, 76, 78, 78, 76, 76, 76, 2494, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 2495, 2496, + 2497, 2498, 76, 2499, 76, 2500, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 2501, 2501, 2502, 2503, 74, 74, + 74, 2504, 2505, 2501, 2506, 2507, 2501, 74, + 74, 74, 2501, 13, 84, 74, 2501, 2501, + 74, 74, 74, 2501, 2501, 2501, 2501, 74, + 2501, 2501, 2501, 2501, 2508, 2509, 2510, 2511, + 74, 74, 74, 74, 2501, 2512, 2513, 2501, + 2514, 2515, 2501, 2501, 2501, 74, 74, 74, + 74, 74, 2501, 74, 2501, 2516, 2501, 2501, + 2501, 2501, 2517, 2501, 2518, 2519, 2520, 2501, + 2521, 2522, 2523, 2501, 2501, 2501, 2524, 74, + 74, 74, 74, 2501, 2501, 2501, 2501, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 2501, 2525, 2526, 2527, 74, 2528, 2529, 2501, + 2501, 2501, 2501, 2501, 2501, 74, 2530, 2531, + 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, + 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2501, + 2501, 2547, 2548, 2549, 2550, 2551, 2552, 2553, + 2554, 2555, 2556, 2501, 2501, 2501, 74, 74, + 2501, 2501, 2557, 2558, 74, 74, 74, 74, + 74, 2501, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 2559, 2501, 74, 74, 2501, + 2501, 2560, 2561, 2501, 2562, 2563, 2564, 2565, + 2566, 2501, 2501, 2567, 2568, 2569, 2570, 2501, + 2501, 2501, 74, 74, 74, 74, 74, 2501, + 2501, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 2501, 2501, 2501, 2501, 2501, 74, + 74, 2501, 2501, 74, 74, 74, 74, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2571, 2572, 2573, 2574, 2501, 2501, 2501, + 2501, 2501, 2501, 2575, 2576, 2577, 2578, 74, + 74, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 76, 76, 76, 76, 76, 76, 76, + 76, 11, 12, 11, 12, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 2579, 2579, 76, 76, 76, + 76, 2501, 2501, 76, 76, 76, 76, 76, + 76, 78, 2580, 2581, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 76, 74, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 78, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 913, 76, + 76, 76, 76, 76, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 78, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 74, 74, 74, + 74, 74, 74, 76, 76, 76, 76, 76, + 76, 76, 2579, 2579, 2579, 2579, 78, 78, + 78, 2579, 78, 78, 2579, 76, 76, 76, + 76, 78, 78, 78, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2582, 2583, 2584, 2585, 2586, 2587, 2588, + 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, + 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, + 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, + 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, + 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, + 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, + 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, + 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, + 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, + 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, + 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, + 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, + 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, + 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, + 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, + 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, + 2717, 2718, 2719, 2720, 1288, 1288, 1288, 1288, + 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, + 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, + 1288, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 78, 78, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 78, + 74, 76, 76, 76, 76, 76, 76, 76, + 76, 78, 74, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 74, 74, 74, 2721, 2721, 2722, 2722, + 74, 78, 78, 78, 78, 78, 78, 76, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 76, 2579, 2579, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 2721, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 2579, 78, 78, 78, 78, 78, 78, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 78, 78, 78, 2579, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 2579, 78, 78, 78, 78, 78, + 78, 78, 78, 2579, 2579, 2723, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 2579, 2579, + 78, 78, 78, 78, 78, 2579, 2579, 78, + 78, 78, 78, 78, 78, 78, 78, 2579, + 78, 78, 78, 78, 78, 2579, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 2579, 78, 78, 78, 78, + 78, 78, 78, 2579, 2579, 78, 2579, 78, + 78, 78, 78, 2579, 78, 78, 2579, 78, + 78, 78, 78, 78, 78, 78, 2579, 76, + 76, 78, 78, 2579, 2579, 78, 78, 78, + 78, 78, 78, 78, 76, 78, 76, 78, + 76, 76, 76, 76, 76, 76, 78, 76, + 76, 76, 78, 76, 76, 76, 76, 76, + 76, 2579, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 78, 78, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 78, 76, 76, + 78, 76, 76, 76, 76, 2579, 76, 2579, + 76, 76, 76, 76, 2579, 2579, 2579, 76, + 2579, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 78, 78, 78, 78, + 78, 11, 12, 11, 12, 11, 12, 11, + 12, 11, 12, 11, 12, 11, 12, 1288, + 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, + 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, + 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, + 1288, 1288, 1288, 1288, 1288, 76, 2579, 2579, + 2579, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 78, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 2579, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 2579, 2501, 74, 74, 2501, 2501, 11, 12, + 74, 2501, 2501, 74, 2501, 2501, 2501, 74, + 74, 74, 74, 74, 2501, 2501, 2501, 2501, + 74, 74, 74, 74, 74, 2501, 2501, 2501, + 74, 74, 74, 2501, 2501, 2501, 2501, 11, + 12, 11, 12, 11, 12, 11, 12, 11, + 12, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 2721, 2721, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 11, 12, 11, 12, + 11, 12, 11, 12, 11, 12, 11, 12, + 11, 12, 11, 12, 11, 12, 11, 12, + 11, 12, 74, 74, 2501, 2501, 2501, 2501, + 2501, 2501, 74, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 74, 74, 74, 74, 74, 74, 74, + 74, 2501, 74, 74, 74, 74, 74, 74, + 74, 2501, 2501, 2501, 2501, 2501, 2501, 74, + 74, 74, 2501, 74, 74, 74, 74, 2501, + 2501, 2501, 2501, 2501, 74, 2501, 2501, 74, + 74, 11, 12, 11, 12, 2501, 74, 74, + 74, 74, 2501, 74, 2501, 2501, 2501, 74, + 74, 2501, 2501, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 2501, 2501, 2501, + 2501, 2501, 2501, 74, 74, 11, 12, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 2501, 2501, 2724, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 74, 2501, + 2501, 2501, 2501, 74, 74, 2501, 74, 2501, + 74, 74, 2501, 74, 2501, 2501, 2501, 2501, + 74, 74, 74, 74, 74, 2501, 2501, 74, + 74, 74, 74, 74, 74, 2501, 2501, 2501, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 2501, 2501, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 2501, 2501, 74, + 74, 74, 74, 2501, 2501, 2501, 2501, 74, + 2501, 2501, 74, 74, 2501, 2725, 2726, 2727, + 74, 74, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 74, 74, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 74, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 2501, 2501, 2501, 2501, 2501, 2501, 2501, 2501, + 74, 74, 74, 74, 74, 2728, 2729, 2501, + 74, 74, 74, 2501, 2501, 2501, 2501, 2501, + 74, 74, 74, 74, 74, 2501, 2501, 2501, + 74, 74, 74, 74, 2501, 74, 74, 74, + 2501, 2501, 2501, 2501, 2501, 74, 2501, 74, + 74, 76, 76, 76, 76, 76, 78, 78, + 78, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 2579, 2579, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 76, 76, + 74, 74, 74, 74, 74, 74, 76, 76, + 76, 2579, 76, 76, 76, 76, 2579, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 0, 0, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 0, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 2730, + 76, 2731, 2732, 2733, 2734, 2735, 2736, 2737, + 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, + 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, + 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, + 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, + 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, + 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785, + 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, + 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, + 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, + 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, + 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, + 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, + 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, + 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, + 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, + 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, + 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, + 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, + 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, + 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, + 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, + 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, + 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, + 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, + 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, + 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, + 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, + 2954, 2955, 2956, 2957, 2958, 2959, 76, 76, + 76, 76, 76, 76, 2960, 2961, 2962, 2963, + 614, 614, 614, 2964, 2965, 0, 0, 0, + 0, 0, 8, 8, 8, 8, 1288, 8, + 8, 2966, 2967, 2968, 2969, 2970, 2971, 2972, + 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, + 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, + 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, + 2997, 2998, 2999, 3000, 3001, 3002, 3003, 0, + 3004, 0, 0, 0, 0, 0, 3005, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 0, 0, 0, 0, 0, 0, 0, + 3006, 1119, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1299, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 614, + 614, 8, 8, 80, 92, 80, 92, 8, + 8, 8, 80, 92, 8, 80, 92, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 1161, 8, 8, 1161, 8, 80, 92, 8, + 8, 80, 92, 11, 12, 11, 12, 11, + 12, 11, 12, 8, 8, 8, 8, 8, + 594, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 1161, 1161, 8, 8, 8, + 8, 1161, 8, 2311, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 76, 76, 8, 8, 8, 11, 12, + 11, 12, 11, 12, 11, 12, 1161, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 0, 3007, 3007, 3007, 3007, + 3008, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3009, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, - 3025, 3026, 3027, 3028, 3029, 3030, 3031, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 0, 0, 0, - 0, 3032, 3033, 3033, 3033, 2815, 3034, 3035, - 3036, 3037, 3038, 3037, 3038, 3037, 3038, 3037, - 3038, 3037, 3038, 2815, 2815, 3037, 3038, 3037, - 3038, 3037, 3038, 3037, 3038, 3039, 3040, 3041, - 3041, 2815, 3036, 3036, 3036, 3036, 3036, 3036, - 3036, 3036, 3036, 3042, 1089, 555, 1088, 3043, - 3043, 3044, 3034, 3034, 3034, 3034, 3034, 3045, - 2815, 3046, 3047, 3048, 3034, 3035, 3049, 2815, - 77, 0, 3035, 3035, 3035, 3035, 3035, 3050, - 3035, 3035, 3035, 3035, 3051, 3052, 3053, 3054, - 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, - 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, - 3071, 3072, 3073, 3074, 3035, 3075, 3076, 3077, - 3078, 3079, 3080, 3035, 3035, 3035, 3035, 3035, + 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, + 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, + 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, + 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, + 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, + 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, + 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, - 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3096, 3035, 3035, - 0, 0, 3097, 3098, 3099, 3100, 3101, 3102, - 3103, 3039, 3035, 3035, 3035, 3035, 3035, 3104, - 3035, 3035, 3035, 3035, 3105, 3106, 3107, 3108, - 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116, - 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, - 3125, 3126, 3127, 3128, 3035, 3129, 3130, 3131, - 3132, 3133, 3134, 3035, 3035, 3035, 3035, 3035, - 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, - 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3150, 3151, 3152, 3153, 3035, 3154, 3035, 3035, - 3155, 3156, 3157, 3158, 3033, 3034, 3159, 3160, - 3161, 0, 0, 0, 0, 0, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 0, 3162, 3163, 3164, 3165, 3166, 3167, - 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, - 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, - 3184, 3185, 3186, 3187, 3188, 3189, 3190, 3191, - 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, - 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, - 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, - 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, - 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, - 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, - 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, - 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, - 0, 3256, 3256, 3257, 3258, 3259, 3260, 3261, - 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, - 3270, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 0, 0, 0, 0, - 0, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3271, 3272, 3273, 3274, 3275, 3276, 3277, - 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, - 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, - 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, - 0, 3302, 3303, 3304, 3305, 3306, 3307, 3308, - 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, - 3317, 3318, 3319, 3320, 3321, 3322, 3323, 3324, - 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, - 3333, 3334, 3335, 3336, 3337, 3338, 3339, 3340, - 3341, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 3342, 3343, 3344, 3345, 3346, 3347, 3348, - 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3356, - 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, - 3365, 3366, 3367, 3368, 3369, 3370, 3371, 3372, - 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, - 3381, 3382, 3383, 3384, 3385, 3386, 3387, 3388, - 3256, 3389, 3390, 3391, 3392, 3393, 3394, 3395, - 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, - 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, - 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, - 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, - 3428, 3429, 3430, 3431, 3432, 3433, 3434, 3435, - 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, - 3444, 3445, 3446, 3447, 3448, 3449, 3450, 3451, - 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, - 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467, - 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, - 3476, 3477, 3478, 3479, 3480, 3481, 3482, 3483, - 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, - 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, + 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, + 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, + 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, + 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, + 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, + 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, + 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, + 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, + 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, + 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, + 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, + 3177, 3178, 3179, 3180, 3181, 3182, 3183, 3184, + 3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, + 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, + 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, + 3209, 3210, 3211, 3212, 3213, 3214, 3215, 3216, + 3217, 3218, 3219, 3220, 3221, 3222, 3223, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3224, 3225, 3225, 3225, 3007, 3226, 3227, + 3228, 3229, 3230, 3229, 3230, 3229, 3230, 3229, + 3230, 3229, 3230, 3007, 3007, 3229, 3230, 3229, + 3230, 3229, 3230, 3229, 3230, 3231, 3232, 3233, + 3233, 3007, 3228, 3228, 3228, 3228, 3228, 3228, + 3228, 3228, 3228, 1809, 1163, 626, 1162, 3234, + 3234, 3235, 3226, 3226, 3226, 3226, 3226, 3236, + 3007, 3237, 3238, 3239, 3226, 3227, 3240, 3007, + 76, 0, 3227, 3227, 3227, 3227, 3227, 3241, + 3227, 3227, 3227, 3227, 3242, 3243, 3244, 3245, + 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, + 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, + 3262, 3263, 3264, 3265, 3227, 3266, 3267, 3268, + 3269, 3270, 3271, 3227, 3227, 3227, 3227, 3227, + 3272, 3273, 3274, 3275, 3276, 3277, 3278, 3279, + 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3287, 3227, 3227, + 0, 0, 3288, 3289, 3290, 3291, 3292, 3293, + 3294, 3231, 3227, 3227, 3227, 3227, 3227, 3295, + 3227, 3227, 3227, 3227, 3296, 3297, 3298, 3299, + 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, + 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, + 3316, 3317, 3318, 3319, 3227, 3320, 3321, 3322, + 3323, 3324, 3325, 3227, 3227, 3227, 3227, 3227, + 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, + 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3341, 3342, 3343, 3344, 3227, 3345, 3227, 3227, + 3346, 3347, 3348, 3349, 3225, 3226, 3350, 3351, + 3352, 0, 0, 0, 0, 0, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 0, 3353, 3354, 3355, 3356, 3357, 3358, + 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, + 3367, 3368, 3369, 3370, 3371, 3372, 3373, 3374, + 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, + 3383, 3384, 3385, 3386, 3387, 3388, 3389, 3390, + 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, + 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, + 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, + 3415, 3416, 3417, 3418, 3419, 3420, 3421, 3422, + 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, + 3431, 3432, 3433, 3434, 3435, 3436, 3437, 3438, + 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, + 0, 3447, 3447, 3448, 3449, 3450, 3451, 3452, + 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, + 3461, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3007, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3462, 3463, 3464, 3465, 3466, 3467, 3468, + 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, + 3477, 3478, 3479, 3480, 3481, 3482, 3483, 3484, + 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, + 0, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, - 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, + 3532, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, - 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, - 3588, 3589, 3590, 3591, 3592, 3593, 3594, 3595, - 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, - 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, - 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, - 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, - 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, - 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, - 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, - 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, - 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, - 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, - 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, - 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, - 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, - 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, - 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, - 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, - 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, - 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, - 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, - 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, - 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, - 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, - 3772, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3034, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 0, 0, - 0, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 525, 525, 525, 525, 525, 525, 1047, - 1047, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 525, 9, 9, - 9, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 341, 341, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3773, 3774, 3775, 3776, 3777, 3778, 3779, - 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, - 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, - 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, - 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, - 3812, 3813, 3814, 3815, 3816, 3817, 3818, 341, - 543, 842, 842, 842, 9, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 9, - 524, 3819, 3820, 3821, 3822, 3823, 3824, 3825, - 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, - 3834, 3835, 3836, 3837, 3838, 3839, 3840, 3841, - 3842, 3843, 3844, 3845, 3846, 3847, 3848, 543, - 543, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 543, 543, 1047, 1047, 1047, 1047, 1047, - 1047, 0, 0, 0, 0, 0, 0, 0, - 0, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, - 524, 524, 524, 524, 524, 524, 524, 524, - 524, 526, 526, 3849, 3850, 3851, 3852, 3853, - 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, - 3862, 215, 215, 3863, 3864, 3865, 3866, 3867, - 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, - 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, - 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, - 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, - 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, - 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, - 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, - 3924, 3925, 215, 215, 215, 215, 215, 215, - 215, 215, 3926, 3927, 3928, 3929, 3930, 3931, - 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, - 3940, 524, 3941, 3941, 3942, 3943, 3944, 215, - 341, 3945, 3946, 3947, 3948, 3949, 215, 3950, - 3951, 3952, 3953, 3954, 3955, 3956, 3957, 3958, - 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, - 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, - 215, 3975, 3976, 3977, 3978, 3979, 3980, 3981, - 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, - 3990, 0, 0, 3991, 3992, 3993, 3994, 3995, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 341, 3996, 3997, 215, 341, 341, 341, 341, - 341, 341, 341, 1151, 341, 341, 341, 1163, - 341, 341, 341, 341, 1151, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1155, 1155, 1151, 1151, - 1155, 77, 77, 77, 77, 0, 0, 0, - 0, 1182, 1182, 1182, 1182, 1182, 1182, 841, - 841, 11, 84, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 9, 9, 9, - 9, 0, 0, 0, 0, 0, 0, 0, - 0, 1155, 1155, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 1155, 1155, 1155, - 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, - 1155, 1155, 1155, 1155, 1155, 1163, 1151, 0, - 0, 0, 0, 0, 0, 0, 0, 1047, - 1047, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 341, 341, 341, 341, 341, - 341, 1047, 1047, 1047, 341, 1047, 341, 341, - 1151, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 1151, - 1151, 1151, 1151, 1151, 556, 556, 556, 1047, - 1047, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1155, 1483, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1047, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 1361, 1361, - 1361, 1361, 1361, 1361, 1361, 1361, 0, 0, - 0, 1151, 1151, 1151, 1155, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1173, 1155, 1155, 1151, - 1151, 1151, 1151, 1155, 1155, 1151, 1151, 1155, - 1155, 1483, 1047, 1047, 1047, 1047, 1047, 1047, - 1047, 1047, 1047, 1047, 1047, 1047, 1047, 0, - 525, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 1047, - 1047, 341, 341, 341, 341, 341, 1151, 525, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1151, 1151, 1151, 1151, 1151, 1151, - 1155, 1155, 1151, 1151, 1155, 1155, 1151, 1151, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 1151, 341, 341, 341, - 341, 341, 341, 341, 341, 1151, 1155, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 1047, 1047, 1047, - 1047, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 525, 341, 341, 341, 341, 341, 341, - 841, 841, 841, 341, 1272, 1151, 1272, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 543, 341, 543, 543, 556, 341, 341, - 543, 543, 341, 341, 341, 341, 341, 543, - 543, 341, 543, 341, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 341, 341, 525, 1047, - 1047, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1155, 1151, 1151, 1155, - 1155, 1047, 1047, 341, 525, 525, 1155, 1163, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 341, 341, 341, 341, 341, 341, - 0, 0, 341, 341, 341, 341, 341, 341, - 0, 0, 341, 341, 341, 341, 341, 341, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 3998, 215, 215, 215, - 215, 215, 215, 215, 3941, 3999, 4000, 4001, - 4002, 215, 215, 215, 215, 215, 215, 215, - 215, 0, 0, 0, 0, 0, 0, 0, - 0, 4003, 4004, 4005, 4006, 4007, 4008, 4009, - 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, - 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, - 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, - 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, - 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049, - 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, - 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, - 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, - 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, - 4082, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1155, 1155, 1151, 1155, - 1155, 1151, 1155, 1155, 1047, 1155, 1163, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4083, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4083, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 4084, 4084, 4084, - 4084, 4084, 4084, 4084, 4084, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, - 0, 0, 0, 0, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, - 1365, 1365, 1365, 1365, 1365, 0, 0, 0, - 0, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4085, 4085, 4085, 4085, 4085, 4085, 4085, - 4085, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, - 4094, 4094, 4095, 4096, 4097, 4098, 4099, 4100, + 3447, 3580, 3581, 3582, 3583, 3584, 3585, 3586, + 3587, 3588, 3589, 3590, 3591, 3592, 3593, 3594, + 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, + 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, + 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, + 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, + 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, + 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, + 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, + 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, + 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, + 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, + 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, + 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, + 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, + 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, + 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, + 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, + 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, + 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, + 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, + 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, + 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, + 3763, 3764, 3765, 3766, 3767, 3768, 3769, 3770, + 3771, 3772, 3773, 3774, 3775, 3776, 3777, 3778, + 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, + 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, + 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, + 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, + 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, + 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, + 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, + 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, + 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, + 3851, 3852, 3853, 3854, 3855, 3856, 3857, 3858, + 3859, 3860, 3861, 3862, 3863, 3864, 3865, 3866, + 3867, 3868, 3869, 3870, 3871, 3872, 3873, 3874, + 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, + 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, + 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, + 3899, 3900, 3901, 3902, 3903, 3904, 3905, 3906, + 3907, 3908, 3909, 3910, 3911, 3912, 3913, 3914, + 3915, 3916, 3917, 3918, 3919, 3920, 3921, 3922, + 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, + 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, + 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, + 3947, 3948, 3949, 3950, 3951, 3952, 3953, 3954, + 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, + 3963, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3226, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 0, 0, + 0, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 3007, 3007, 3007, 3007, 3007, 3007, 3007, 3007, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 595, 595, 595, 595, 595, 595, 1119, + 1119, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 595, 8, 8, + 8, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 345, 345, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3964, 3965, 3966, 3967, 3968, 3969, 3970, + 3971, 3972, 3973, 3974, 3975, 3976, 3977, 3978, + 3979, 3980, 3981, 3982, 3983, 3984, 3985, 3986, + 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, + 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, + 4003, 4004, 4005, 4006, 4007, 4008, 4009, 345, + 614, 914, 914, 914, 8, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 8, + 594, 4010, 4011, 4012, 4013, 4014, 4015, 4016, + 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, + 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, + 4033, 4034, 4035, 4036, 4037, 4038, 4039, 614, + 614, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 614, 614, 1119, 1119, 1119, 1119, 1119, + 1119, 0, 0, 0, 0, 0, 0, 0, + 0, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 594, 594, 594, 594, 594, 594, 594, 594, + 594, 46, 46, 4040, 4041, 4042, 4043, 4044, + 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, + 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, + 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, + 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, + 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, + 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, + 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, - 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, - 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, - 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, - 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, - 4173, 4174, 4175, 4176, 4177, 4106, 4178, 4179, - 4180, 4181, 4182, 4183, 4184, 4185, 4186, 4187, - 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, - 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, - 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, - 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, - 4220, 4221, 4222, 4223, 4224, 4225, 4226, 4227, - 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, - 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, - 4244, 4245, 4196, 4246, 4247, 4248, 4249, 4250, - 4251, 4252, 4253, 4180, 4254, 4255, 4256, 4257, - 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, - 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, - 4106, 4274, 4275, 4276, 4277, 4278, 4279, 4280, - 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, - 4289, 4290, 4291, 4292, 4293, 4294, 4295, 4296, - 4297, 4298, 4299, 4300, 4182, 4301, 4302, 4303, - 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, - 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, - 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, - 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, - 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, - 4344, 4345, 4346, 4347, 4348, 4349, 4350, 3035, - 3035, 4351, 3035, 4352, 3035, 3035, 4353, 4354, - 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, - 3035, 4363, 3035, 4364, 3035, 3035, 4365, 4366, - 3035, 3035, 3035, 4367, 4368, 4369, 4370, 4371, - 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, - 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, - 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, - 4396, 4397, 4398, 4399, 4400, 4401, 4402, 4403, - 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, - 4235, 4412, 4413, 4414, 4415, 4416, 4417, 4417, - 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, - 4365, 4426, 4427, 4428, 4429, 4430, 4431, 0, - 0, 4432, 4433, 4434, 4435, 4436, 4437, 4438, - 4439, 4379, 4440, 4441, 4442, 4351, 4443, 4444, - 4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, - 4453, 4454, 4388, 4455, 4389, 4456, 4457, 4458, - 4459, 4460, 4352, 4127, 4461, 4462, 4463, 4197, - 4284, 4464, 4465, 4396, 4466, 4397, 4467, 4468, - 4469, 4354, 4470, 4471, 4472, 4473, 4474, 4355, - 4475, 4476, 4477, 4478, 4479, 4480, 4411, 4481, - 4482, 4235, 4483, 4415, 4484, 4485, 4486, 4487, - 4488, 4420, 4489, 4364, 4490, 4421, 4178, 4491, - 4422, 4492, 4424, 4493, 4494, 4495, 4496, 4497, - 4426, 4360, 4498, 4427, 4499, 4428, 4500, 4094, - 4501, 4502, 4503, 4504, 4505, 4506, 4507, 4508, - 4509, 4510, 4511, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4512, 4513, 4514, 4515, 4516, 4517, 4518, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4519, 4520, 4521, 4522, - 4523, 0, 0, 0, 0, 0, 4524, 4525, - 4526, 4527, 4528, 4529, 4530, 4531, 4532, 4533, + 4141, 594, 4142, 4142, 4143, 4144, 4145, 4146, + 345, 4147, 4148, 4149, 4150, 4151, 4152, 4153, + 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, + 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, + 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, + 4178, 4179, 4180, 4181, 4182, 4183, 4184, 4185, + 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, + 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, + 4202, 4203, 4204, 4205, 0, 0, 0, 0, + 0, 4206, 4207, 0, 4208, 0, 4209, 4210, + 4211, 4212, 4213, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4214, 4215, 4216, 4217, 4218, + 345, 4219, 4220, 4221, 345, 345, 345, 345, + 345, 345, 345, 1225, 345, 345, 345, 1261, + 345, 345, 345, 345, 1225, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 1230, 1230, 1225, 1225, + 1230, 76, 76, 76, 76, 1299, 0, 0, + 0, 1258, 1258, 1258, 1258, 1258, 1258, 913, + 913, 10, 83, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 8, 8, 8, + 8, 0, 0, 0, 0, 0, 0, 0, + 0, 1230, 1230, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1261, 1225, 0, + 0, 0, 0, 0, 0, 0, 0, 1119, + 1119, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 345, 345, 345, 345, 345, + 345, 1119, 1119, 1119, 345, 1119, 345, 345, + 1225, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 1225, + 1225, 1225, 1225, 1225, 627, 627, 627, 1119, + 1119, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1230, 1537, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1119, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 1439, 1439, + 1439, 1439, 1439, 1439, 1439, 1439, 0, 0, + 0, 1225, 1225, 1225, 1230, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 1249, 1230, 1230, 1225, + 1225, 1225, 1225, 1230, 1230, 1225, 1225, 1230, + 1230, 1537, 1119, 1119, 1119, 1119, 1119, 1119, + 1119, 1119, 1119, 1119, 1119, 1119, 1119, 0, + 595, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 1119, + 1119, 345, 345, 345, 345, 345, 1225, 595, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1225, 1225, 1225, 1225, 1225, 1225, + 1230, 1230, 1225, 1225, 1230, 1230, 1225, 1225, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 1225, 345, 345, 345, + 345, 345, 345, 345, 345, 1225, 1230, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 1119, 1119, 1119, + 1119, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 595, 345, 345, 345, 345, 345, 345, + 913, 913, 913, 345, 1350, 1225, 1350, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 614, 345, 614, 614, 627, 345, 345, + 614, 614, 345, 345, 345, 345, 345, 614, + 614, 345, 614, 345, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 345, 345, 595, 1119, + 1119, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 1230, 1225, 1225, 1230, + 1230, 1119, 1119, 345, 595, 595, 1230, 1299, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 345, 345, 345, 345, 345, 345, + 0, 0, 345, 345, 345, 345, 345, 345, + 0, 0, 345, 345, 345, 345, 345, 345, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 4222, 4223, 4224, 4225, 4226, 4227, 4228, + 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, + 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, + 4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, + 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, + 4261, 4262, 4263, 4264, 4142, 4265, 4266, 4267, + 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, + 4276, 4277, 4278, 46, 46, 0, 0, 0, + 0, 4279, 4280, 4281, 4282, 4283, 4284, 4285, + 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, + 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, + 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, + 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, + 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, + 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, + 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, + 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349, + 4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, + 4358, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 1230, 1230, 1225, 1230, + 1230, 1225, 1230, 1230, 1119, 1230, 1299, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4359, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4359, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 4360, 4360, 4360, + 4360, 4360, 4360, 4360, 4360, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 1442, 1442, 1442, 1442, 1442, 1442, 1442, 1442, + 0, 0, 0, 0, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 1443, 1443, 1443, + 1443, 1443, 1443, 1443, 1443, 0, 0, 0, + 0, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4361, 4361, 4361, 4361, 4361, 4361, 4361, + 4361, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, + 4370, 4370, 4371, 4372, 4373, 4374, 4375, 4376, + 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, + 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, + 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, + 4401, 4402, 4403, 4404, 4405, 4406, 4407, 4408, + 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416, + 4417, 4418, 4419, 4420, 4421, 4422, 4423, 4424, + 4425, 4426, 4427, 4428, 4429, 4430, 4431, 4432, + 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, + 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, + 4449, 4450, 4451, 4452, 4453, 4382, 4454, 4455, + 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, + 4464, 4465, 4466, 4467, 4468, 4469, 4470, 4471, + 4472, 4473, 4474, 4475, 4476, 4477, 4478, 4479, + 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, + 4488, 4489, 4490, 4491, 4492, 4493, 4494, 4495, + 4496, 4497, 4498, 4499, 4500, 4501, 4502, 4503, + 4504, 4505, 4506, 4507, 4508, 4509, 4510, 4511, + 4512, 4513, 4514, 4515, 4516, 4517, 4518, 4519, + 4520, 4521, 4472, 4522, 4523, 4524, 4525, 4526, + 4527, 4528, 4529, 4456, 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, 4548, 4549, - 0, 4550, 4551, 4552, 4553, 4554, 0, 4555, - 0, 4556, 4557, 0, 4558, 4559, 0, 4560, - 4561, 4562, 4563, 4564, 4565, 4566, 4567, 4568, - 4569, 4570, 4571, 4572, 4573, 4574, 4575, 4576, - 4577, 4578, 4579, 4580, 4581, 4582, 4583, 4584, - 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4592, - 4593, 4594, 4595, 4596, 4597, 4598, 4599, 4600, - 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, - 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, - 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, - 4625, 4626, 4627, 4628, 4629, 4630, 4631, 4632, - 4633, 4634, 4635, 4636, 4637, 4638, 4639, 4640, - 4641, 4642, 4643, 4644, 4645, 4646, 4647, 4648, - 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, - 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, - 4665, 4666, 4667, 4668, 4668, 4668, 4668, 4668, - 4668, 4668, 4668, 4668, 4668, 4668, 4668, 4668, - 4668, 4668, 4668, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4669, 4670, 4671, 4672, - 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, - 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, - 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, - 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, - 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, - 4713, 4714, 4715, 4716, 4707, 4717, 4718, 4719, - 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, - 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, - 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, - 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, - 4752, 4753, 4754, 4755, 4756, 4757, 4758, 4759, - 4760, 4761, 4762, 4763, 4764, 4765, 4766, 4767, - 4768, 4769, 4770, 4771, 4772, 4773, 4774, 4775, - 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, - 4784, 4785, 4786, 4787, 4788, 4789, 4790, 4791, - 4792, 4793, 4794, 4795, 4796, 4797, 4798, 4799, - 4800, 4801, 4802, 4803, 4804, 4805, 4806, 4807, - 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, - 4816, 4708, 4817, 4818, 4819, 4820, 4821, 4822, - 4823, 4824, 4825, 4826, 4827, 4828, 4829, 4830, - 4831, 4832, 4833, 4834, 4835, 4836, 4837, 4838, - 4839, 4840, 4841, 4842, 4843, 4844, 4845, 4846, - 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, - 4855, 4856, 4857, 4858, 4859, 4860, 4861, 4862, - 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, - 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, - 4879, 4880, 4881, 4882, 4883, 4884, 4885, 4886, - 4887, 4888, 4889, 4890, 4891, 4892, 4893, 4894, - 4895, 4896, 4897, 4898, 4899, 4900, 4901, 4902, - 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, - 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, - 4919, 4920, 4921, 4922, 4923, 4924, 4925, 4926, - 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, - 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, - 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, - 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, - 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, - 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, - 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, - 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, - 4991, 4992, 4993, 4994, 4995, 4996, 4997, 4998, - 4999, 5000, 5001, 5002, 5003, 5004, 5005, 5006, - 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, - 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, - 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, - 2137, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5031, 5032, 5033, 5034, 5035, 5036, 5037, - 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, - 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, - 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, - 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, - 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, - 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, - 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, - 5094, 0, 0, 5095, 5096, 5097, 5098, 5099, - 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, - 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, - 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, - 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, - 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, - 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, - 5148, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5149, 5150, 5151, 5152, 5153, 5154, 5155, - 5156, 5157, 5158, 5159, 5160, 5161, 77, 0, - 0, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 5162, 5163, 5164, 5165, 5166, 5167, 5168, - 5169, 5170, 5171, 0, 0, 0, 0, 0, - 0, 543, 543, 543, 543, 543, 543, 543, - 556, 556, 556, 556, 556, 556, 556, 543, - 543, 5172, 5173, 5174, 5175, 5175, 5176, 5177, + 4382, 4550, 4551, 4552, 4553, 4554, 4555, 4556, + 4557, 4558, 4559, 4560, 4561, 4562, 4563, 4564, + 4565, 4566, 4567, 4568, 4569, 4570, 4571, 4572, + 4573, 4574, 4575, 4576, 4458, 4577, 4578, 4579, + 4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, + 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, + 4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, + 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, + 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, + 4620, 4621, 4622, 4623, 4624, 4625, 4626, 3227, + 3227, 4627, 3227, 4628, 3227, 3227, 4629, 4630, + 4631, 4632, 4633, 4634, 4635, 4636, 4637, 4638, + 3227, 4639, 3227, 4640, 3227, 3227, 4641, 4642, + 3227, 3227, 3227, 4643, 4644, 4645, 4646, 4647, + 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, + 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, + 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, + 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, + 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, + 4511, 4688, 4689, 4690, 4691, 4692, 4693, 4693, + 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, + 4641, 4702, 4703, 4704, 4705, 4706, 4707, 0, + 0, 4708, 4709, 4710, 4711, 4712, 4713, 4714, + 4715, 4655, 4716, 4717, 4718, 4627, 4719, 4720, + 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, + 4729, 4730, 4664, 4731, 4665, 4732, 4733, 4734, + 4735, 4736, 4628, 4403, 4737, 4738, 4739, 4473, + 4560, 4740, 4741, 4672, 4742, 4673, 4743, 4744, + 4745, 4630, 4746, 4747, 4748, 4749, 4750, 4631, + 4751, 4752, 4753, 4754, 4755, 4756, 4687, 4757, + 4758, 4511, 4759, 4691, 4760, 4761, 4762, 4763, + 4764, 4696, 4765, 4640, 4766, 4697, 4454, 4767, + 4698, 4768, 4700, 4769, 4770, 4771, 4772, 4773, + 4702, 4636, 4774, 4703, 4775, 4704, 4776, 4370, + 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, + 4785, 4786, 4787, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4788, 4789, 4790, 4791, 4792, 4793, 4794, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4795, 4796, 4797, 4798, + 4799, 0, 0, 0, 0, 0, 4800, 4801, + 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, + 4810, 4811, 4812, 4813, 4814, 4815, 4816, 4817, + 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, + 0, 4826, 4827, 4828, 4829, 4830, 0, 4831, + 0, 4832, 4833, 0, 4834, 4835, 0, 4836, + 4837, 4838, 4839, 4840, 4841, 4842, 4843, 4844, + 4845, 4846, 4847, 4848, 4849, 4850, 4851, 4852, + 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, + 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, + 4869, 4870, 4871, 4872, 4873, 4874, 4875, 4876, + 4877, 4878, 4879, 4880, 4881, 4882, 4883, 4884, + 4885, 4886, 4887, 4888, 4889, 4890, 4891, 4892, + 4893, 4894, 4895, 4896, 4897, 4898, 4899, 4900, + 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, + 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, + 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, + 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, + 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, + 4941, 4942, 4943, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 1229, 1229, 1229, 1229, + 1229, 1229, 1229, 1229, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4944, 4945, 4946, 4947, + 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, + 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, + 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, + 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, + 4980, 4981, 4982, 4983, 4984, 4985, 4986, 4987, + 4988, 4989, 4990, 4991, 4982, 4992, 4993, 4994, + 4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, + 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, + 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, + 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, + 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, + 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, + 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, + 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, + 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, + 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, + 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, + 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, + 5091, 4983, 5092, 5093, 5094, 5095, 5096, 5097, + 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, + 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, + 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, + 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5129, + 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, + 5138, 5139, 5140, 5141, 5142, 5143, 5144, 5145, + 5146, 5147, 5148, 5149, 5150, 5151, 5152, 5153, + 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, + 5162, 5163, 5164, 5165, 5166, 5167, 5168, 5169, + 5170, 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180, 5181, 5182, 5183, 5184, 5185, - 5186, 5187, 5188, 5189, 5190, 5191, 3033, 3033, - 5192, 5193, 5194, 5194, 5194, 5194, 5195, 5195, - 5195, 5196, 5197, 5198, 0, 5199, 5200, 5201, + 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, + 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, - 0, 5218, 5219, 5220, 5221, 0, 0, 0, - 0, 5222, 5223, 5224, 1117, 5225, 0, 5226, - 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, - 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, - 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, - 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, - 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, - 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, - 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, - 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, - 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, - 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, - 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, - 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, - 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, - 5331, 5332, 5333, 5334, 5335, 5336, 5337, 5338, - 5339, 5340, 5341, 5342, 5343, 5344, 5345, 5346, - 5347, 5348, 5349, 5350, 5351, 5352, 5353, 5354, - 5355, 5356, 5357, 5358, 5359, 5360, 0, 0, - 1459, 0, 5361, 5362, 5363, 5364, 5365, 5366, - 5367, 5368, 5369, 5370, 5371, 5372, 5373, 5374, + 5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, + 5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, + 5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, + 5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, + 5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, + 5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, + 5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, + 5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, + 5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, + 5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, + 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, + 2311, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 5306, 5307, 5308, 5309, 5310, 5311, 5312, + 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, + 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, + 5329, 5330, 5331, 5332, 5333, 5334, 5335, 5336, + 5337, 5338, 5339, 5340, 5341, 5342, 5343, 5344, + 5345, 5346, 5347, 5348, 5349, 5350, 5351, 5352, + 5353, 5354, 5355, 5356, 5357, 5358, 5359, 5360, + 5361, 5362, 5363, 5364, 5365, 5366, 5367, 5368, + 5369, 0, 0, 5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5421, 5422, - 5423, 5424, 5425, 5426, 5427, 5428, 5429, 5430, - 5431, 5432, 5433, 5434, 5435, 5436, 5437, 5438, - 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, - 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, - 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, - 5463, 5464, 5465, 5466, 5467, 5468, 5469, 5470, - 5471, 5472, 5473, 5474, 5475, 5476, 5477, 5478, - 5479, 5480, 5481, 5482, 5483, 5484, 5485, 5486, - 5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, - 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, - 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, - 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, - 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, - 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, - 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, - 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, - 0, 0, 0, 5551, 5552, 5553, 5554, 5555, - 5556, 0, 0, 5557, 5558, 5559, 5560, 5561, - 5562, 0, 0, 5563, 5564, 5565, 5566, 5567, - 5568, 0, 0, 5569, 5570, 5571, 0, 0, - 0, 5572, 5573, 5574, 5575, 5576, 5577, 5578, - 0, 5579, 5580, 5581, 5582, 5583, 5584, 5585, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5586, 5586, 5586, 77, 77, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 0, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 0, 341, 341, 0, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 0, 0, 0, 0, - 0, 1047, 9, 1047, 0, 0, 0, 0, + 5423, 0, 0, 0, 0, 0, 0, 0, + 76, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5424, 5425, 5426, 5427, 5428, 5429, 5430, + 5431, 5432, 5433, 5434, 5435, 5436, 76, 76, + 76, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 5437, 5438, 5439, 5440, 5441, 5442, 5443, + 5444, 5445, 5446, 0, 0, 0, 0, 0, + 0, 614, 614, 614, 614, 614, 614, 614, + 627, 627, 627, 627, 627, 627, 627, 614, + 614, 5447, 5448, 5449, 5450, 5450, 5451, 5452, + 5453, 5454, 5455, 5456, 5457, 5458, 5459, 5460, + 5461, 5462, 5463, 5464, 5465, 5466, 3225, 3225, + 5467, 5468, 5469, 5469, 5469, 5469, 5470, 5470, + 5470, 5471, 5472, 5473, 0, 5474, 5475, 5476, + 5477, 5478, 5479, 5480, 5481, 5482, 5483, 5484, + 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, + 0, 5493, 5494, 5495, 5496, 0, 0, 0, + 0, 5497, 5498, 5499, 1191, 5500, 0, 5501, + 5502, 5503, 5504, 5505, 5506, 5507, 5508, 5509, + 5510, 5511, 5512, 5513, 5514, 5515, 5516, 5517, + 5518, 5519, 5520, 5521, 5522, 5523, 5524, 5525, + 5526, 5527, 5528, 5529, 5530, 5531, 5532, 5533, + 5534, 5535, 5536, 5537, 5538, 5539, 5540, 5541, + 5542, 5543, 5544, 5545, 5546, 5547, 5548, 5549, + 5550, 5551, 5552, 5553, 5554, 5555, 5556, 5557, + 5558, 5559, 5560, 5561, 5562, 5563, 5564, 5565, + 5566, 5567, 5568, 5569, 5570, 5571, 5572, 5573, + 5574, 5575, 5576, 5577, 5578, 5579, 5580, 5581, + 5582, 5583, 5584, 5585, 5586, 5587, 5588, 5589, + 5590, 5591, 5592, 5593, 5594, 5595, 5596, 5597, + 5598, 5599, 5600, 5601, 5602, 5603, 5604, 5605, + 5606, 5607, 5608, 5609, 5610, 5611, 5612, 5613, + 5614, 5615, 5616, 5617, 5618, 5619, 5620, 5621, + 5622, 5623, 5624, 5625, 5626, 5627, 5628, 5629, + 5630, 5631, 5632, 5633, 5634, 5635, 0, 0, + 1538, 0, 5636, 5637, 5638, 5639, 5640, 5641, + 5642, 5643, 5644, 5645, 5646, 5647, 5648, 5649, + 5650, 5651, 5652, 5653, 5654, 5655, 5656, 5657, + 5658, 5659, 5660, 5661, 5662, 5663, 5664, 5665, + 5666, 5667, 5668, 5669, 5670, 5671, 5672, 5673, + 5674, 5675, 5676, 5677, 5678, 5679, 5680, 5681, + 5682, 5683, 5684, 5685, 5686, 5687, 5688, 5689, + 5690, 5691, 5692, 5693, 5694, 5695, 5696, 5697, + 5698, 5699, 5700, 5701, 5702, 5703, 5704, 5705, + 5706, 5707, 5708, 5709, 5710, 5711, 5712, 5713, + 5714, 5715, 5716, 5717, 5718, 5719, 5720, 5721, + 5722, 5723, 5724, 5725, 5726, 5727, 5728, 5729, + 5730, 5731, 5732, 5733, 5734, 5735, 5736, 5737, + 5738, 5739, 5740, 5741, 5742, 5743, 5744, 5745, + 5746, 5747, 5748, 5749, 5750, 5751, 5752, 5753, + 5754, 5755, 5756, 5757, 5758, 5759, 5760, 5761, + 5762, 5763, 5764, 5765, 5766, 5767, 5768, 5769, + 5770, 5771, 5772, 5773, 5774, 5775, 5776, 5777, + 5778, 5779, 5780, 5781, 5782, 5783, 5784, 5785, + 5786, 5787, 5788, 5789, 5790, 5791, 5792, 5793, + 5794, 5795, 5796, 5797, 5798, 5799, 5800, 5801, + 5802, 5803, 5804, 5805, 5806, 5807, 5808, 5809, + 5810, 5811, 5812, 5813, 5814, 5815, 5816, 5817, + 5818, 5819, 5820, 5821, 5822, 5823, 5824, 5825, + 0, 0, 0, 5826, 5827, 5828, 5829, 5830, + 5831, 0, 0, 5832, 5833, 5834, 5835, 5836, + 5837, 0, 0, 5838, 5839, 5840, 5841, 5842, + 5843, 0, 0, 5844, 5845, 5846, 0, 0, + 0, 5847, 5848, 5849, 5850, 5851, 5852, 5853, + 0, 5854, 5855, 5856, 5857, 5858, 5859, 5860, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5861, 5861, 5861, 76, 76, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 0, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 0, 345, 345, 0, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 0, 0, 0, 0, + 0, 1119, 8, 1119, 0, 0, 0, 0, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 0, 0, 0, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 5862, 5862, 5862, 5862, 5862, 5862, 5862, + 5862, 5862, 5862, 5862, 5862, 5862, 5862, 5862, + 5862, 5862, 5862, 5862, 5862, 5862, 5862, 5862, + 5862, 5862, 5862, 5862, 5862, 5862, 5862, 5862, + 5862, 5862, 5862, 5862, 5862, 5862, 5862, 5862, + 5862, 5862, 5862, 5862, 5862, 5862, 5862, 5862, + 5862, 5862, 5862, 5862, 5862, 5862, 1288, 1288, + 1288, 1288, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 1288, 1288, 76, 913, 913, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 0, 0, + 0, 76, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 627, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 627, 5863, 5863, 5863, 5863, 5863, 5863, + 5863, 5863, 5863, 5863, 5863, 5863, 5863, 5863, + 5863, 5863, 5863, 5863, 5863, 5863, 5863, 5863, + 5863, 5863, 5863, 5863, 5863, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 1258, 1258, 1258, 1258, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1536, 345, 345, 345, 345, 345, + 345, 345, 345, 1536, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 614, + 614, 614, 614, 614, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 0, + 1119, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 1119, 1536, 1536, 1536, 1536, 1536, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5864, 5865, 5866, 5867, 5868, 5869, 5870, + 5871, 5872, 5873, 5874, 5875, 5876, 5877, 5878, + 5879, 5880, 5881, 5882, 5883, 5884, 5885, 5886, + 5887, 5888, 5889, 5890, 5891, 5892, 5893, 5894, + 5895, 5896, 5897, 5898, 5899, 5900, 5901, 5902, + 5903, 5904, 5905, 5906, 5907, 5908, 5909, 5910, + 5911, 5912, 5913, 5914, 5915, 5916, 5917, 5918, + 5919, 5920, 5921, 5922, 5923, 5924, 5925, 5926, + 5927, 5928, 5929, 5930, 5931, 5932, 5933, 5934, + 5935, 5936, 5937, 5938, 5939, 5940, 5941, 5942, + 5943, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 5944, 5945, 5946, 5947, 5948, 5949, 5950, + 5951, 5952, 5953, 5954, 5955, 5956, 5957, 5958, + 5959, 5960, 5961, 5962, 5963, 5964, 5965, 5966, + 5967, 5968, 5969, 5970, 5971, 5972, 5973, 5974, + 5975, 5976, 5977, 5978, 5979, 0, 0, 0, + 0, 5980, 5981, 5982, 5983, 5984, 5985, 5986, + 5987, 5988, 5989, 5990, 5991, 5992, 5993, 5994, + 5995, 5996, 5997, 5998, 5999, 6000, 6001, 6002, + 6003, 6004, 6005, 6006, 6007, 6008, 6009, 6010, + 6011, 6012, 6013, 6014, 6015, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1119, 6016, 6017, 6018, 6019, 6020, 6021, 6022, + 6023, 6024, 6025, 6026, 0, 6027, 6028, 6029, + 6030, 6031, 6032, 6033, 6034, 6035, 6036, 6037, + 6038, 6039, 6040, 6041, 0, 6042, 6043, 6044, + 6045, 6046, 6047, 6048, 0, 6049, 6050, 0, + 6051, 6052, 6053, 6054, 6055, 6056, 6057, 6058, + 6059, 6060, 6061, 0, 6062, 6063, 6064, 6065, + 6066, 6067, 6068, 6069, 6070, 6071, 6072, 6073, + 6074, 6075, 6076, 0, 6077, 6078, 6079, 6080, + 6081, 6082, 6083, 0, 6084, 6085, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6086, 6087, 6088, 6089, 6090, 6091, 0, + 6092, 6093, 6094, 6095, 6096, 6097, 6098, 6099, + 6100, 6101, 6102, 6103, 6104, 6105, 6106, 6107, + 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6115, + 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, + 6124, 6125, 6126, 6127, 6128, 6129, 6130, 6131, + 6132, 6133, 0, 6134, 6135, 6136, 6137, 6138, + 6139, 6140, 6141, 6142, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 0, + 0, 1182, 0, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 0, + 1182, 1182, 0, 0, 0, 1182, 0, 0, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 0, + 1179, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 6144, 6144, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 0, 0, 0, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 5587, 5587, 5587, 5587, 5587, 5587, 5587, - 5587, 5587, 5587, 5587, 5587, 5587, 5587, 5587, - 5587, 5587, 5587, 5587, 5587, 5587, 5587, 5587, - 5587, 5587, 5587, 5587, 5587, 5587, 5587, 5587, - 5587, 5587, 5587, 5587, 5587, 5587, 5587, 5587, - 5587, 5587, 5587, 5587, 5587, 5587, 5587, 5587, - 5587, 5587, 5587, 5587, 5587, 5587, 1211, 1211, - 1211, 1211, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 1211, 1211, 77, 841, 841, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 0, 0, 0, - 0, 77, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 556, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 556, 5588, 5588, 5588, 5588, 5588, 5588, - 5588, 5588, 5588, 5588, 5588, 5588, 5588, 5588, - 5588, 5588, 5588, 5588, 5588, 5588, 5588, 5588, - 5588, 5588, 5588, 5588, 5588, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 1182, 1182, 1182, 1182, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1458, 341, 341, 341, 341, 341, - 341, 341, 341, 1458, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 543, - 543, 543, 543, 543, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 0, - 1047, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 1047, 1458, 1458, 1458, 1458, 1458, 0, + 6143, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5589, 5590, 5591, 5592, 5593, 5594, 5595, - 5596, 5597, 5598, 5599, 5600, 5601, 5602, 5603, - 5604, 5605, 5606, 5607, 5608, 5609, 5610, 5611, - 5612, 5613, 5614, 5615, 5616, 5617, 5618, 5619, - 5620, 5621, 5622, 5623, 5624, 5625, 5626, 5627, - 5628, 5629, 5630, 5631, 5632, 5633, 5634, 5635, - 5636, 5637, 5638, 5639, 5640, 5641, 5642, 5643, - 5644, 5645, 5646, 5647, 5648, 5649, 5650, 5651, - 5652, 5653, 5654, 5655, 5656, 5657, 5658, 5659, - 5660, 5661, 5662, 5663, 5664, 5665, 5666, 5667, - 5668, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 5669, 5670, 5671, 5672, 5673, 5674, 5675, - 5676, 5677, 5678, 5679, 5680, 5681, 5682, 5683, - 5684, 5685, 5686, 5687, 5688, 5689, 5690, 5691, - 5692, 5693, 5694, 5695, 5696, 5697, 5698, 5699, - 5700, 5701, 5702, 5703, 5704, 0, 0, 0, - 0, 5705, 5706, 5707, 5708, 5709, 5710, 5711, - 5712, 5713, 5714, 5715, 5716, 5717, 5718, 5719, - 5720, 5721, 5722, 5723, 5724, 5725, 5726, 5727, - 5728, 5729, 5730, 5731, 5732, 5733, 5734, 5735, - 5736, 5737, 5738, 5739, 5740, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 0, 0, 0, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 0, 1182, 1182, 0, + 0, 0, 0, 0, 6143, 6143, 6143, 6143, + 6143, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 6143, + 6143, 6143, 6143, 6143, 6143, 0, 0, 0, + 8, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 0, 0, 0, 0, 0, + 1179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 0, 0, 0, 0, 6143, 6143, 1182, + 1182, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 0, 0, 6143, 6143, 6143, 6143, 6143, + 6143, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 1182, 1225, 1225, 1225, 0, 1225, 1225, + 0, 0, 0, 0, 0, 1225, 627, 1225, + 614, 1182, 1182, 1182, 1182, 0, 1182, 1182, + 1182, 0, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 0, + 0, 614, 640, 627, 0, 0, 0, 0, + 1299, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 6143, 0, 0, 0, 0, 0, 0, + 0, 1179, 1179, 1179, 1179, 1179, 1179, 1179, + 1179, 1179, 0, 0, 0, 0, 0, 0, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 6143, 6143, + 1179, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 6143, 6143, + 6143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 6144, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 614, 627, + 0, 0, 0, 0, 6143, 6143, 6143, 6143, + 6143, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 0, + 0, 0, 8, 8, 8, 8, 8, 8, + 8, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 0, + 0, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 0, 0, 0, 0, + 0, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 0, 0, 0, 0, 0, + 0, 0, 1179, 1179, 1179, 1179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6145, 6146, 6147, 6148, 6149, 6150, 6151, + 6152, 6153, 6154, 6155, 6156, 6157, 6158, 6159, + 6160, 6161, 6162, 6163, 6164, 6165, 6166, 6167, + 6168, 6169, 6170, 6171, 6172, 6173, 6174, 6175, + 6176, 6177, 6178, 6179, 6180, 6181, 6182, 6183, + 6184, 6185, 6186, 6187, 6188, 6189, 6190, 6191, + 6192, 6193, 6194, 6195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6196, 6197, 6198, 6199, 6200, 6201, 6202, + 6203, 6204, 6205, 6206, 6207, 6208, 6209, 6210, + 6211, 6212, 6213, 6214, 6215, 6216, 6217, 6218, + 6219, 6220, 6221, 6222, 6223, 6224, 6225, 6226, + 6227, 6228, 6229, 6230, 6231, 6232, 6233, 6234, + 6235, 6236, 6237, 6238, 6239, 6240, 6241, 6242, + 6243, 6244, 6245, 6246, 0, 0, 0, 0, + 0, 0, 0, 6143, 6143, 6143, 6143, 6143, + 6143, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 614, 614, 614, + 614, 0, 0, 0, 0, 0, 0, 0, + 0, 1209, 1209, 1209, 1209, 1209, 1209, 1209, + 1209, 1209, 1209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4538,47 +5064,12 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 0, - 0, 1108, 0, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 0, - 1108, 1108, 0, 0, 0, 1108, 0, 0, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 0, - 1105, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 5742, 5742, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 0, 0, 0, 0, 0, 0, 0, 0, - 5741, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 0, 1108, 1108, 0, - 0, 0, 0, 0, 5741, 5741, 5741, 5741, - 5741, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 5741, - 5741, 5741, 5741, 5741, 5741, 0, 0, 0, - 9, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 0, 0, 0, 0, 0, - 1105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4586,77 +5077,11 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 0, 0, 0, 0, 5741, 5741, 1108, - 1108, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 0, 0, 5741, 5741, 5741, 5741, 5741, - 5741, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 1108, 1151, 1151, 1151, 0, 1151, 1151, - 0, 0, 0, 0, 0, 1151, 556, 1151, - 543, 1108, 1108, 1108, 1108, 0, 1108, 1108, - 1108, 0, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 0, - 0, 543, 569, 556, 0, 0, 0, 0, - 1163, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 5741, 0, 0, 0, 0, 0, 0, - 0, 1105, 1105, 1105, 1105, 1105, 1105, 1105, - 1105, 1105, 0, 0, 0, 0, 0, 0, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 5741, 5741, - 1105, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 5741, 5741, - 5741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 5742, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 543, 556, - 0, 0, 0, 0, 5741, 5741, 5741, 5741, - 5741, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 0, - 0, 0, 9, 9, 9, 9, 9, 9, - 9, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 0, - 0, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 0, 0, 0, 0, - 0, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 0, 0, 0, 0, 0, - 0, 0, 1105, 1105, 1105, 1105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4665,56 +5090,131 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6247, 6247, 6247, 6247, 6247, 6247, 6247, + 6247, 6247, 6247, 6247, 6247, 6247, 6247, 6247, + 6247, 6247, 6247, 6247, 6247, 6247, 6247, 6247, + 6247, 6247, 6247, 6247, 6247, 6247, 6247, 6247, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 0, 614, 614, 1177, 0, + 0, 1182, 1182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5743, 5744, 5745, 5746, 5747, 5748, 5749, - 5750, 5751, 5752, 5753, 5754, 5755, 5756, 5757, - 5758, 5759, 5760, 5761, 5762, 5763, 5764, 5765, - 5766, 5767, 5768, 5769, 5770, 5771, 5772, 5773, - 5774, 5775, 5776, 5777, 5778, 5779, 5780, 5781, - 5782, 5783, 5784, 5785, 5786, 5787, 5788, 5789, - 5790, 5791, 5792, 5793, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5794, 5795, 5796, 5797, 5798, 5799, 5800, - 5801, 5802, 5803, 5804, 5805, 5806, 5807, 5808, - 5809, 5810, 5811, 5812, 5813, 5814, 5815, 5816, - 5817, 5818, 5819, 5820, 5821, 5822, 5823, 5824, - 5825, 5826, 5827, 5828, 5829, 5830, 5831, 5832, - 5833, 5834, 5835, 5836, 5837, 5838, 5839, 5840, - 5841, 5842, 5843, 5844, 0, 0, 0, 0, - 0, 0, 0, 5741, 5741, 5741, 5741, 5741, - 5741, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 543, 543, 543, - 543, 0, 0, 0, 0, 0, 0, 0, - 0, 1135, 1135, 1135, 1135, 1135, 1135, 1135, - 1135, 1135, 1135, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 627, 627, + 627, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 6143, 6143, + 6143, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 1182, 0, 0, 0, 0, 0, 0, 0, + 0, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 627, + 627, 614, 614, 614, 627, 614, 627, 627, + 627, 627, 6248, 6248, 6248, 6248, 1186, 1186, + 1186, 1186, 1186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 614, 627, 614, 627, 1179, + 1179, 1179, 1179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 6143, 6143, + 6143, 6143, 6143, 6143, 6143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1230, 1225, 1230, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1261, + 1119, 1119, 1119, 1119, 1119, 1119, 1119, 0, + 0, 0, 0, 1288, 1288, 1288, 1288, 1288, + 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, + 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1299, 345, 345, 1225, 1225, 345, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1299, 1225, 1225, 1230, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 6249, 6250, 6251, 6252, 345, 345, + 345, 345, 345, 345, 345, 345, 6253, 345, + 345, 345, 345, 345, 6254, 345, 345, 345, + 345, 1230, 1230, 1230, 1225, 1225, 1225, 1225, + 1230, 1230, 1261, 6255, 1119, 1119, 6256, 1119, + 1119, 1119, 1119, 1225, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6256, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 614, 614, 614, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 6257, 1225, 1225, 1225, 1225, 1230, 1225, 6258, + 6259, 1225, 6260, 6261, 1299, 1299, 0, 1248, + 1248, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1119, 1119, 1119, 1119, 345, 1230, 1230, + 345, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 1249, 1119, 1119, 345, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1225, 1225, 1230, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 1230, 1230, 1230, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1230, 1537, 345, 1306, 1306, 345, 1119, 1119, + 1119, 1119, 1225, 1249, 1225, 1225, 1119, 1230, + 1225, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 345, 1119, 345, 1119, 1119, + 1119, 0, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 0, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 1230, 1230, 1230, + 1225, 1225, 1225, 1230, 1230, 1225, 1537, 1249, + 1225, 1119, 1119, 1119, 1119, 1119, 1119, 1225, + 345, 345, 1225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4722,6 +5222,37 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 0, 345, 345, 345, 345, 0, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 0, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1119, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 1225, 1230, 1230, 1230, 1225, 1225, 1225, 1225, + 1225, 1225, 1249, 1299, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 1225, 1225, 1230, 1230, 0, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 0, + 345, 345, 0, 0, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 345, 0, 345, 345, + 345, 345, 345, 0, 1249, 1249, 345, 6262, + 1230, 1225, 1230, 1230, 1230, 1230, 0, 0, + 6263, 1230, 0, 0, 6264, 6265, 1537, 0, + 0, 345, 0, 0, 0, 0, 0, 0, + 6266, 0, 0, 0, 0, 0, 345, 345, + 345, 345, 345, 1230, 1230, 0, 0, 614, + 614, 614, 614, 614, 614, 614, 0, 0, + 0, 614, 614, 614, 614, 614, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4739,13 +5270,34 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 1230, 1230, + 1230, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1230, 1230, 1261, 1225, 1225, 1230, 1249, + 345, 345, 345, 345, 1119, 1119, 1119, 1119, + 1119, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1119, 1119, 0, 1119, 614, + 345, 345, 345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5845, 5845, 5845, 5845, 5845, 5845, 5845, - 5845, 5845, 5845, 5845, 5845, 5845, 5845, 5845, - 5845, 5845, 5845, 5845, 5845, 5845, 5845, 5845, - 5845, 5845, 5845, 5845, 5845, 5845, 5845, 5845, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 6267, 1230, 1230, 1225, 1225, 1225, 1225, + 1225, 1225, 6268, 6269, 6270, 6271, 6272, 6273, + 1225, 1225, 1230, 1261, 1249, 345, 345, 1119, + 345, 0, 0, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4762,110 +5314,69 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 5741, 5741, - 5741, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 1108, 0, 0, 0, 0, 0, 0, 0, - 0, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1117, 1117, 556, - 556, 543, 543, 543, 556, 543, 556, 556, - 556, 556, 5846, 5846, 5846, 5846, 1112, 1112, - 1112, 1112, 1112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 6274, 1230, 1230, 1225, 1225, 1225, 1225, 0, + 0, 6275, 6276, 6277, 6278, 1225, 1225, 1230, + 1261, 1249, 1119, 1119, 1119, 1119, 1119, 1119, + 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, + 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, + 1119, 345, 345, 345, 345, 1225, 1225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 1230, 1230, 1230, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1230, 1230, 1225, 1230, + 1261, 1225, 1119, 1119, 1119, 345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 1225, 1230, 1225, 1230, + 1230, 1225, 1225, 1225, 1225, 1225, 1225, 1537, + 1249, 345, 1119, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1155, 1151, 1155, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1163, - 1047, 1047, 1047, 1047, 1047, 1047, 1047, 0, - 0, 0, 0, 1211, 1211, 1211, 1211, 1211, - 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, - 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 0, 0, 1225, 1225, + 1225, 1350, 1350, 1225, 1225, 1225, 1225, 1230, + 1225, 1225, 1225, 1225, 1299, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1258, 1258, 1119, 1119, 1119, + 913, 345, 345, 345, 345, 345, 345, 345, 0, 0, 0, 0, 0, 0, 0, 0, - 1163, 1151, 1151, 1155, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 5847, 5848, 5849, 5850, 341, 341, - 341, 341, 341, 341, 341, 341, 5851, 341, - 341, 341, 341, 341, 5852, 341, 341, 341, - 341, 1155, 1155, 1155, 1151, 1151, 1151, 1151, - 1155, 1155, 1163, 5853, 1047, 1047, 5854, 1047, - 1047, 1047, 1047, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5854, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 0, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 543, 543, 543, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 5855, 1151, 1151, 1151, 1151, 1155, 1151, 5856, - 5857, 1151, 5858, 5859, 1163, 1163, 0, 1172, - 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1047, 1047, 1047, 1047, 341, 1155, 1155, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1173, 1047, 1047, 341, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1151, 1151, 1155, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1155, 1155, 1155, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1155, 1483, 341, 1228, 1228, 341, 1047, 1047, - 1047, 1047, 1151, 1173, 1151, 1151, 1047, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 341, 1047, 341, 1047, 1047, - 1047, 0, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 0, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 1155, 1155, 1155, - 1151, 1151, 1151, 1155, 1155, 1151, 1483, 1173, - 1151, 1047, 1047, 1047, 1047, 1047, 1047, 1151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4874,37 +5385,6 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 0, 341, 341, 341, 341, 0, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 0, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1047, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 1151, 1155, 1155, 1155, 1151, 1151, 1151, 1151, - 1151, 1151, 1173, 1163, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 1151, 1151, 1155, 1155, 0, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 0, - 341, 341, 0, 0, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 0, 341, 341, - 341, 341, 341, 0, 1173, 1173, 341, 5860, - 1155, 1151, 1155, 1155, 1155, 1155, 0, 0, - 5861, 1155, 0, 0, 5862, 5863, 1483, 0, - 0, 341, 0, 0, 0, 0, 0, 0, - 5864, 0, 0, 0, 0, 0, 341, 341, - 341, 341, 341, 1155, 1155, 0, 0, 543, - 543, 543, 543, 543, 543, 543, 0, 0, - 0, 543, 543, 543, 543, 543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4918,45 +5398,50 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 1230, 1230, 1230, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1230, 1261, 1249, 1119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 1155, 1155, - 1155, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1155, 1155, 1163, 1151, 1151, 1155, 1173, - 341, 341, 341, 341, 1047, 1047, 1047, 1047, - 1047, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 1047, 0, 1047, 543, - 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 5865, 1155, 1155, 1151, 1151, 1151, 1151, - 1151, 1151, 5866, 5867, 5868, 5869, 5870, 5871, - 1151, 1151, 1155, 1163, 1173, 341, 341, 1047, - 341, 0, 0, 0, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6279, 6280, 6281, 6282, 6283, 6284, 6285, + 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, + 6294, 6295, 6296, 6297, 6298, 6299, 6300, 6301, + 6302, 6303, 6304, 6305, 6306, 6307, 6308, 6309, + 6310, 6311, 6312, 6313, 6314, 6315, 6316, 6317, + 6318, 6319, 6320, 6321, 6322, 6323, 6324, 6325, + 6326, 6327, 6328, 6329, 6330, 6331, 6332, 6333, + 6334, 6335, 6336, 6337, 6338, 6339, 6340, 6341, + 6342, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 345, 345, 345, 345, 345, 345, 345, 345, + 0, 0, 345, 0, 0, 345, 345, 345, + 345, 345, 345, 345, 345, 0, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 6343, 1230, 1230, 1230, 1230, 6344, 0, + 1230, 6345, 0, 0, 1225, 1225, 1537, 1299, + 1306, 1230, 1306, 1230, 1249, 1119, 1119, 1119, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -4965,68 +5450,66 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 0, 0, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1230, 1230, 1230, 1225, 1225, 1225, + 1225, 0, 0, 1225, 1225, 1230, 1230, 1230, + 1230, 1261, 345, 1119, 345, 1230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 1225, 1225, 1225, 1225, 1225, 1225, + 6346, 6346, 1225, 1225, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 1225, 1299, 1225, 1225, + 1225, 1225, 1230, 1306, 1225, 1225, 1225, 1225, + 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, + 1299, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 1225, 1225, 1225, 1225, 1225, 1225, + 1230, 1230, 1225, 1225, 1225, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 1306, 1306, 1306, + 1306, 1306, 1306, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1230, 1225, 1299, 1119, 1119, 1119, 345, 1119, + 1119, 1119, 1119, 1119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 0, 0, 0, 0, 0, + 0, 1119, 1119, 1119, 1119, 1119, 1119, 1119, + 1119, 1119, 1119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 5872, 1155, 1155, 1151, 1151, 1151, 1151, 0, - 0, 5873, 5874, 5875, 5876, 1151, 1151, 1155, - 1163, 1173, 1047, 1047, 1047, 1047, 1047, 1047, - 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, - 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, - 1047, 341, 341, 341, 341, 1151, 1151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 1155, 1155, 1155, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1155, 1155, 1151, 1155, - 1163, 1151, 1047, 1047, 1047, 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1151, 1155, 1151, 1155, - 1155, 1151, 1151, 1151, 1151, 1151, 1151, 1483, - 1173, 341, 0, 0, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 0, 0, 1151, 1151, - 1151, 1155, 1155, 1151, 1151, 1151, 1151, 1155, - 1151, 1151, 1151, 1151, 1163, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 1182, 1182, 1047, 1047, 1047, - 841, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5043,24 +5526,60 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 1230, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 0, 1225, 1225, 1225, 1225, 1225, 1225, 1230, + 6347, 345, 1119, 1119, 1119, 1119, 1119, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 0, 0, + 0, 1119, 1119, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 0, 0, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 0, 1230, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1230, 1225, 1225, 1230, 1225, 1225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 1155, 1155, 1155, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1155, 1163, 1173, 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 0, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1225, 1225, 1225, 1225, 1225, 1225, + 0, 0, 0, 1225, 0, 1225, 1225, 0, + 1225, 1225, 1225, 1249, 1225, 1299, 1299, 1306, + 1225, 0, 0, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 0, + 345, 345, 0, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 1230, 1230, 1230, 1230, 1230, + 0, 1225, 1225, 0, 1230, 1230, 1225, 1230, + 1299, 345, 0, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5070,19 +5589,7 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5877, 5878, 5879, 5880, 5881, 5882, 5883, - 5884, 5885, 5886, 5887, 5888, 5889, 5890, 5891, - 5892, 5893, 5894, 5895, 5896, 5897, 5898, 5899, - 5900, 5901, 5902, 5903, 5904, 5905, 5906, 5907, - 5908, 5909, 5910, 5911, 5912, 5913, 5914, 5915, - 5916, 5917, 5918, 5919, 5920, 5921, 5922, 5923, - 5924, 5925, 5926, 5927, 5928, 5929, 5930, 5931, - 5932, 5933, 5934, 5935, 5936, 5937, 5938, 5939, - 5940, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5102,53 +5609,31 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 0, 0, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1155, 1155, 1155, 1151, 1151, 1151, - 1151, 0, 0, 1151, 1151, 1155, 1155, 1155, - 1155, 1163, 341, 1047, 341, 1155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 1151, 1151, 1151, 1151, 1151, 1151, - 5941, 5941, 1151, 1151, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1151, 1163, 1151, 1151, - 1151, 1151, 1155, 1228, 1151, 1151, 1151, 1151, - 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047, - 1163, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 1151, 1151, 1151, 1151, 1151, 1151, - 1155, 1155, 1151, 1151, 1151, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 1228, 1228, 1228, - 1228, 1228, 1228, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1155, 1151, 1163, 1047, 1047, 1047, 341, 1047, - 1047, 1047, 1047, 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 1225, 1225, 1230, 1230, + 1119, 1119, 0, 0, 0, 0, 0, 0, + 0, 1225, 1225, 1306, 1230, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 1230, 1230, 1225, + 1225, 1225, 1225, 1225, 0, 0, 0, 1230, + 1230, 1225, 1537, 1299, 1119, 1119, 1119, 1119, + 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, + 1119, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5159,8 +5644,36 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 76, 76, + 76, 76, 76, 76, 76, 76, 10, 10, + 10, 10, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1119, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5173,34 +5686,52 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, + 0, 1119, 1119, 1119, 1119, 1119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 1155, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 0, 1151, 1151, 1151, 1151, 1151, 1151, 1155, - 5942, 341, 1047, 1047, 1047, 1047, 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 0, 0, - 0, 1047, 1047, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 0, 0, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 0, 1155, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1155, 1151, 1151, 1155, 1151, 1151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5210,28 +5741,6 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 0, 341, 341, 0, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 1151, 1151, 1151, 1151, 1151, 1151, - 0, 0, 0, 1151, 0, 1151, 1151, 0, - 1151, 1151, 1151, 1173, 1151, 1163, 1163, 1228, - 1151, 0, 0, 0, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 0, - 341, 341, 0, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 1155, 1155, 1155, 1155, 1155, - 0, 1151, 1151, 0, 1155, 1155, 1151, 1155, - 1163, 341, 0, 0, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5270,10 +5779,6 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 1151, 1151, 1155, 1155, - 1047, 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5295,37 +5800,34 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 1119, 1119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 6348, 6348, 6348, 6348, 6348, 6348, 6348, + 6348, 6348, 6348, 6348, 6348, 6348, 6348, 6348, + 6348, 1225, 345, 345, 345, 345, 345, 345, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 77, 77, - 77, 77, 77, 77, 77, 77, 11, 11, - 11, 11, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1047, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5338,52 +5840,21 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 1458, 1458, 1458, 1458, 1458, 1458, 1458, 1458, - 0, 1047, 1047, 1047, 1047, 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5402,21 +5873,62 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 0, 5943, 5943, 5943, 5943, 5943, 5943, 5943, - 5943, 5943, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 1119, + 1119, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 0, + 0, 640, 640, 640, 640, 640, 1119, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 614, 614, 614, 614, 614, 614, 614, + 1119, 1119, 1119, 1119, 1119, 913, 913, 913, + 913, 595, 595, 595, 595, 1119, 913, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 0, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 0, 0, 0, 0, 0, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5434,19 +5946,22 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6349, 6350, 6351, 6352, 6353, 6354, 6355, + 6356, 6357, 6358, 6359, 6360, 6361, 6362, 6363, + 6364, 6365, 6366, 6367, 6368, 6369, 6370, 6371, + 6372, 6373, 6374, 6375, 6376, 6377, 6378, 6379, + 6380, 6381, 6382, 6383, 6384, 6385, 6386, 6387, + 6388, 6389, 6390, 6391, 6392, 6393, 6394, 6395, + 6396, 6397, 6398, 6399, 6400, 6401, 6402, 6403, + 6404, 6405, 6406, 6407, 6408, 6409, 6410, 6411, + 6412, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1119, 1119, 1119, 1119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5459,6 +5974,27 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 0, 0, 0, 0, + 1225, 345, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, + 1230, 0, 0, 0, 0, 0, 0, 0, + 1225, 1225, 1225, 1225, 595, 595, 595, 595, + 595, 595, 595, 595, 595, 595, 595, 595, + 595, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5466,57 +6002,82 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 1047, - 1047, 0, 0, 0, 0, 0, 0, 0, + 0, 3226, 3226, 3225, 3226, 1225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6413, 6413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 0, - 0, 569, 569, 569, 569, 569, 1047, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 543, 543, 543, 543, 543, 543, 543, - 1047, 1047, 1047, 1047, 1047, 841, 841, 841, - 841, 525, 525, 525, 525, 1047, 841, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 0, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 0, 0, 0, 0, 0, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5538,295 +6099,8 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5944, 5945, 5946, 5947, 5948, 5949, 5950, - 5951, 5952, 5953, 5954, 5955, 5956, 5957, 5958, - 5959, 5960, 5961, 5962, 5963, 5964, 5965, 5966, - 5967, 5968, 5969, 5970, 5971, 5972, 5973, 5974, - 5975, 5976, 5977, 5978, 5979, 5980, 5981, 5982, - 5983, 5984, 5985, 5986, 5987, 5988, 5989, 5990, - 5991, 5992, 5993, 5994, 5995, 5996, 5997, 5998, - 5999, 6000, 6001, 6002, 6003, 6004, 6005, 6006, - 6007, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1047, 1047, 1047, 1047, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 0, 0, 0, 0, - 1151, 341, 1155, 1155, 1155, 1155, 1155, 1155, - 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, - 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, - 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, - 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, - 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, - 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, - 1155, 0, 0, 0, 0, 0, 0, 0, - 1151, 1151, 1151, 1151, 525, 525, 525, 525, - 525, 525, 525, 525, 525, 525, 525, 525, - 525, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3034, 3034, 3033, 3034, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3035, 3035, 3035, - 3035, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 0, 0, 841, 1151, 569, - 1047, 1459, 1459, 1459, 1459, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 0, 0, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 6008, 6009, 841, 841, 841, 841, 841, 6010, - 6011, 6012, 6013, 6014, 6015, 6016, 6017, 6018, - 569, 569, 569, 841, 841, 841, 6019, 6020, - 6021, 6022, 6023, 6024, 1459, 1459, 1459, 1459, - 1459, 1459, 1459, 1459, 556, 556, 556, 556, - 556, 556, 556, 556, 841, 841, 543, 543, - 543, 543, 543, 556, 556, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 543, 543, 543, 543, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 6025, 6026, 6027, 6028, 6029, 6030, - 6031, 6032, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 543, 543, 543, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5846,26 +6120,7 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, - 1182, 1182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -5877,164 +6132,209 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3226, 3226, 3226, 3226, 0, 3226, 3226, + 3226, 3226, 3226, 3226, 3226, 0, 3226, 3226, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 0, 0, 3227, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6033, 2233, 2208, 2251, 2235, 2236, 6034, - 2215, 2218, 6035, 6036, 2219, 2238, 2221, 6037, - 2223, 2224, 2225, 6038, 6039, 6040, 6041, 6042, - 6043, 6044, 2229, 6045, 6046, 6047, 2252, 2234, - 6048, 2214, 2216, 2253, 2254, 6049, 2220, 6050, - 6051, 2239, 6052, 6053, 6054, 6055, 6056, 6057, - 6058, 6059, 6060, 6061, 6062, 6033, 2233, 2208, - 2251, 2235, 2236, 6034, 2215, 2218, 6035, 6036, - 2219, 2238, 2221, 6037, 2223, 2224, 2225, 6038, - 6039, 6040, 6041, 6042, 6043, 6044, 2229, 6045, - 6046, 6047, 2252, 2234, 6048, 2214, 0, 2253, - 2254, 6049, 2220, 6050, 6051, 2239, 6052, 6053, - 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6061, - 6062, 6033, 2233, 2208, 2251, 2235, 2236, 6034, - 2215, 2218, 6035, 6036, 2219, 2238, 2221, 6037, - 2223, 2224, 2225, 6038, 6039, 6040, 6041, 6042, - 6043, 6044, 2229, 6045, 6046, 6047, 2252, 2234, - 6048, 2214, 2216, 2253, 2254, 6049, 2220, 6050, - 6051, 2239, 6052, 6053, 6054, 6055, 6056, 6057, - 6058, 6059, 6060, 6061, 6062, 6033, 0, 2208, - 2251, 0, 0, 6034, 0, 0, 6035, 6036, - 0, 0, 2221, 6037, 2223, 2224, 0, 6038, - 6039, 6040, 6041, 6042, 6043, 6044, 2229, 6045, - 6046, 6047, 2252, 0, 6048, 0, 2216, 2253, - 2254, 6049, 2220, 6050, 6051, 0, 6052, 6053, - 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6061, - 6062, 6033, 2233, 2208, 2251, 2235, 2236, 6034, - 2215, 2218, 6035, 6036, 2219, 2238, 2221, 6037, - 2223, 2224, 2225, 6038, 6039, 6040, 6041, 6042, - 6043, 6044, 2229, 6045, 6046, 6047, 2252, 2234, - 6048, 2214, 2216, 2253, 2254, 6049, 2220, 6050, - 6051, 2239, 6052, 6053, 6054, 6055, 6056, 6057, - 6058, 6059, 6060, 6061, 6062, 6033, 2233, 0, - 2251, 2235, 2236, 6034, 0, 0, 6035, 6036, - 2219, 2238, 2221, 6037, 2223, 2224, 0, 6038, - 6039, 6040, 6041, 6042, 6043, 6044, 0, 6045, - 6046, 6047, 2252, 2234, 6048, 2214, 2216, 2253, - 2254, 6049, 2220, 6050, 6051, 2239, 6052, 6053, - 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6061, - 6062, 6033, 2233, 0, 2251, 2235, 2236, 6034, - 0, 2218, 6035, 6036, 2219, 2238, 0, 6037, - 0, 0, 0, 6038, 6039, 6040, 6041, 6042, - 6043, 6044, 0, 6045, 6046, 6047, 2252, 2234, - 6048, 2214, 2216, 2253, 2254, 6049, 2220, 6050, - 6051, 2239, 6052, 6053, 6054, 6055, 6056, 6057, - 6058, 6059, 6060, 6061, 6062, 6033, 2233, 2208, - 2251, 2235, 2236, 6034, 2215, 2218, 6035, 6036, - 2219, 2238, 2221, 6037, 2223, 2224, 2225, 6038, - 6039, 6040, 6041, 6042, 6043, 6044, 2229, 6045, - 6046, 6047, 2252, 2234, 6048, 2214, 2216, 2253, - 2254, 6049, 2220, 6050, 6051, 2239, 6052, 6053, - 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6061, - 6062, 6033, 2233, 2208, 2251, 2235, 2236, 6034, - 2215, 2218, 6035, 6036, 2219, 2238, 2221, 6037, - 2223, 2224, 2225, 6038, 6039, 6040, 6041, 6042, - 6043, 6044, 2229, 6045, 6046, 6047, 2252, 2234, - 6048, 2214, 2216, 2253, 2254, 6049, 2220, 6050, - 6051, 2239, 6052, 6053, 6054, 6055, 6056, 6057, - 6058, 6059, 6060, 6061, 6062, 6033, 2233, 2208, - 2251, 2235, 2236, 6034, 2215, 2218, 6035, 6036, - 2219, 2238, 2221, 6037, 2223, 2224, 2225, 6038, - 6039, 6040, 6041, 6042, 6043, 6044, 2229, 6045, - 6046, 6047, 2252, 2234, 6048, 2214, 2216, 2253, - 2254, 6049, 2220, 6050, 6051, 2239, 6052, 6053, - 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6061, - 6062, 6033, 2233, 2208, 2251, 2235, 2236, 6034, - 2215, 2218, 6035, 6036, 2219, 2238, 2221, 6037, - 2223, 2224, 2225, 6038, 6039, 6040, 6041, 6042, - 6043, 6044, 2229, 6045, 6046, 6047, 2252, 2234, - 6048, 2214, 2216, 2253, 2254, 6049, 2220, 6050, - 6051, 2239, 6052, 6053, 6054, 6055, 6056, 6057, - 6058, 6059, 6060, 6061, 6062, 6033, 2233, 2208, - 2251, 2235, 2236, 6034, 2215, 2218, 6035, 6036, - 2219, 2238, 2221, 6037, 2223, 2224, 2225, 6038, - 6039, 6040, 6041, 6042, 6043, 6044, 2229, 6045, - 6046, 6047, 2252, 2234, 6048, 2214, 2216, 2253, - 2254, 6049, 2220, 6050, 6051, 2239, 6052, 6053, - 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6061, - 6062, 6033, 2233, 2208, 2251, 2235, 2236, 6034, - 2215, 2218, 6035, 6036, 2219, 2238, 2221, 6037, - 2223, 2224, 2225, 6038, 6039, 6040, 6041, 6042, - 6043, 6044, 2229, 6045, 6046, 6047, 2252, 2234, - 6048, 2214, 2216, 2253, 2254, 6049, 2220, 6050, - 6051, 2239, 6052, 6053, 6054, 6055, 6056, 6057, - 6058, 6059, 6060, 6061, 6062, 6063, 6064, 0, - 0, 6065, 6066, 2248, 6067, 6068, 6069, 6070, - 6071, 6072, 6073, 6074, 6075, 6076, 6077, 6078, - 2249, 6079, 6080, 6081, 6082, 6083, 6084, 6085, - 6086, 6087, 6088, 6089, 6090, 2247, 6091, 6092, - 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6100, - 6101, 6102, 2246, 6103, 6104, 6105, 6106, 6107, - 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6115, - 6116, 6117, 6118, 6065, 6066, 2248, 6067, 6068, - 6069, 6070, 6071, 6072, 6073, 6074, 6075, 6076, - 6077, 6078, 2249, 6079, 6080, 6081, 6082, 6083, - 6084, 6085, 6086, 6087, 6088, 6089, 6090, 2247, - 6091, 6092, 6093, 6094, 6095, 6096, 6097, 6098, - 6099, 6100, 6101, 6102, 2246, 6103, 6104, 6105, - 6106, 6107, 6108, 6109, 6110, 6111, 6112, 6113, - 6114, 6115, 6116, 6117, 6118, 6065, 6066, 2248, - 6067, 6068, 6069, 6070, 6071, 6072, 6073, 6074, - 6075, 6076, 6077, 6078, 2249, 6079, 6080, 6081, - 6082, 6083, 6084, 6085, 6086, 6087, 6088, 6089, - 6090, 2247, 6091, 6092, 6093, 6094, 6095, 6096, - 6097, 6098, 6099, 6100, 6101, 6102, 2246, 6103, - 6104, 6105, 6106, 6107, 6108, 6109, 6110, 6111, - 6112, 6113, 6114, 6115, 6116, 6117, 6118, 6065, - 6066, 2248, 6067, 6068, 6069, 6070, 6071, 6072, - 6073, 6074, 6075, 6076, 6077, 6078, 2249, 6079, - 6080, 6081, 6082, 6083, 6084, 6085, 6086, 6087, - 6088, 6089, 6090, 2247, 6091, 6092, 6093, 6094, - 6095, 6096, 6097, 6098, 6099, 6100, 6101, 6102, - 2246, 6103, 6104, 6105, 6106, 6107, 6108, 6109, - 6110, 6111, 6112, 6113, 6114, 6115, 6116, 6117, - 6118, 6065, 6066, 2248, 6067, 6068, 6069, 6070, - 6071, 6072, 6073, 6074, 6075, 6076, 6077, 6078, - 2249, 6079, 6080, 6081, 6082, 6083, 6084, 6085, - 6086, 6087, 6088, 6089, 6090, 2247, 6091, 6092, - 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6100, - 6101, 6102, 2246, 6103, 6104, 6105, 6106, 6107, - 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6115, - 6116, 6117, 6118, 6119, 6120, 0, 0, 6121, - 6122, 6123, 6124, 6125, 6126, 6127, 6128, 6129, - 6130, 6121, 6122, 6123, 6124, 6125, 6126, 6127, - 6128, 6129, 6130, 6121, 6122, 6123, 6124, 6125, - 6126, 6127, 6128, 6129, 6130, 6121, 6122, 6123, - 6124, 6125, 6126, 6127, 6128, 6129, 6130, 6121, - 6122, 6123, 6124, 6125, 6126, 6127, 6128, 6129, - 6130, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 841, 841, 841, 841, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 841, 841, - 841, 841, 841, 841, 841, 841, 1151, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 1151, 841, 841, - 1047, 1047, 1047, 1047, 1047, 0, 0, 0, + 0, 0, 0, 0, 0, 3227, 3227, 3227, + 3227, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 0, 0, 913, 1225, 640, + 1119, 1538, 1538, 1538, 1538, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 0, + 0, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1151, 1151, 1151, 1151, - 1151, 0, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, - 1151, 0, 0, 0, 0, 0, 0, 0, + 0, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 0, 0, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 6414, 6415, 913, 913, 913, 913, 913, 6416, + 6417, 6418, 6419, 6420, 6421, 6422, 6423, 6424, + 640, 640, 640, 913, 913, 913, 6425, 6426, + 6427, 6428, 6429, 6430, 1538, 1538, 1538, 1538, + 1538, 1538, 1538, 1538, 627, 627, 627, 627, + 627, 627, 627, 627, 913, 913, 614, 614, + 614, 614, 614, 627, 627, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 614, 614, 614, 614, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 6431, 6432, 6433, 6434, 6435, 6436, + 6437, 6438, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 76, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 614, 614, 614, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6042,12 +6342,6 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 543, 543, 543, 543, 543, 543, 543, - 0, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 543, 543, 543, 543, 543, 543, - 543, 543, 0, 0, 543, 543, 543, 543, - 543, 543, 543, 0, 543, 543, 0, 543, - 543, 543, 543, 543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6056,9 +6350,30 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 1258, 1258, 1258, 1258, 1258, 1258, + 1258, 1258, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6074,19 +6389,158 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 0, 0, - 0, 543, 543, 543, 543, 543, 543, 543, - 525, 525, 525, 525, 525, 525, 525, 0, - 0, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 341, - 841, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6439, 6440, 6441, 6442, 6443, 6444, 6445, + 6446, 6447, 6448, 6449, 6450, 6451, 6452, 6453, + 6454, 6455, 6456, 6457, 6458, 6459, 6460, 6461, + 6462, 6463, 6464, 6465, 6466, 6467, 6468, 6469, + 6470, 6471, 6472, 6473, 6474, 6475, 6476, 6477, + 6478, 6479, 6480, 6481, 6482, 6483, 6484, 6485, + 6486, 6487, 6488, 6489, 6490, 6491, 6492, 6493, + 6494, 6495, 6496, 6497, 6498, 6499, 6500, 6501, + 6502, 6503, 6504, 6505, 6506, 6507, 6508, 6509, + 6510, 6511, 6512, 6513, 6514, 6515, 6516, 6517, + 6518, 6519, 6520, 6521, 6522, 6523, 0, 6524, + 6525, 6526, 6527, 6528, 6529, 6530, 6531, 6532, + 6533, 6534, 6535, 6536, 6537, 6538, 6539, 6540, + 6541, 6542, 6543, 6544, 6545, 6546, 6547, 6548, + 6549, 6550, 6551, 6552, 6553, 6554, 6555, 6556, + 6557, 6558, 6559, 6560, 6561, 6562, 6563, 6564, + 6565, 6566, 6567, 6568, 6569, 6570, 6571, 6572, + 6573, 6574, 6575, 6576, 6577, 6578, 6579, 6580, + 6581, 6582, 6583, 6584, 6585, 6586, 6587, 6588, + 6589, 6590, 6591, 6592, 6593, 6594, 0, 6595, + 6596, 0, 0, 6597, 0, 0, 6598, 6599, + 0, 0, 6600, 6601, 6602, 6603, 0, 6604, + 6605, 6606, 6607, 6608, 6609, 6610, 6611, 6612, + 6613, 6614, 6615, 0, 6616, 0, 6617, 6618, + 6619, 6620, 6621, 6622, 6623, 0, 6624, 6625, + 6626, 6627, 6628, 6629, 6630, 6631, 6632, 6633, + 6634, 6635, 6636, 6637, 6638, 6639, 6640, 6641, + 6642, 6643, 6644, 6645, 6646, 6647, 6648, 6649, + 6650, 6651, 6652, 6653, 6654, 6655, 6656, 6657, + 6658, 6659, 6660, 6661, 6662, 6663, 6664, 6665, + 6666, 6667, 6668, 6669, 6670, 6671, 6672, 6673, + 6674, 6675, 6676, 6677, 6678, 6679, 6680, 6681, + 6682, 6683, 6684, 6685, 6686, 6687, 6688, 0, + 6689, 6690, 6691, 6692, 0, 0, 6693, 6694, + 6695, 6696, 6697, 6698, 6699, 6700, 0, 6701, + 6702, 6703, 6704, 6705, 6706, 6707, 0, 6708, + 6709, 6710, 6711, 6712, 6713, 6714, 6715, 6716, + 6717, 6718, 6719, 6720, 6721, 6722, 6723, 6724, + 6725, 6726, 6727, 6728, 6729, 6730, 6731, 6732, + 6733, 6734, 6735, 0, 6736, 6737, 6738, 6739, + 0, 6740, 6741, 6742, 6743, 6744, 0, 6745, + 0, 0, 0, 6746, 6747, 6748, 6749, 6750, + 6751, 6752, 0, 6753, 6754, 6755, 6756, 6757, + 6758, 6759, 6760, 6761, 6762, 6763, 6764, 6765, + 6766, 6767, 6768, 6769, 6770, 6771, 6772, 6773, + 6774, 6775, 6776, 6777, 6778, 6779, 6780, 6781, + 6782, 6783, 6784, 6785, 6786, 6787, 6788, 6789, + 6790, 6791, 6792, 6793, 6794, 6795, 6796, 6797, + 6798, 6799, 6800, 6801, 6802, 6803, 6804, 6805, + 6806, 6807, 6808, 6809, 6810, 6811, 6812, 6813, + 6814, 6815, 6816, 6817, 6818, 6819, 6820, 6821, + 6822, 6823, 6824, 6825, 6826, 6827, 6828, 6829, + 6830, 6831, 6832, 6833, 6834, 6835, 6836, 6837, + 6838, 6839, 6840, 6841, 6842, 6843, 6844, 6845, + 6846, 6847, 6848, 6849, 6850, 6851, 6852, 6853, + 6854, 6855, 6856, 6857, 6858, 6859, 6860, 6861, + 6862, 6863, 6864, 6865, 6866, 6867, 6868, 6869, + 6870, 6871, 6872, 6873, 6874, 6875, 6876, 6877, + 6878, 6879, 6880, 6881, 6882, 6883, 6884, 6885, + 6886, 6887, 6888, 6889, 6890, 6891, 6892, 6893, + 6894, 6895, 6896, 6897, 6898, 6899, 6900, 6901, + 6902, 6903, 6904, 6905, 6906, 6907, 6908, 6909, + 6910, 6911, 6912, 6913, 6914, 6915, 6916, 6917, + 6918, 6919, 6920, 6921, 6922, 6923, 6924, 6925, + 6926, 6927, 6928, 6929, 6930, 6931, 6932, 6933, + 6934, 6935, 6936, 6937, 6938, 6939, 6940, 6941, + 6942, 6943, 6944, 6945, 6946, 6947, 6948, 6949, + 6950, 6951, 6952, 6953, 6954, 6955, 6956, 6957, + 6958, 6959, 6960, 6961, 6962, 6963, 6964, 6965, + 6966, 6967, 6968, 6969, 6970, 6971, 6972, 6973, + 6974, 6975, 6976, 6977, 6978, 6979, 6980, 6981, + 6982, 6983, 6984, 6985, 6986, 6987, 6988, 6989, + 6990, 6991, 6992, 6993, 6994, 6995, 6996, 6997, + 6998, 6999, 7000, 7001, 7002, 7003, 7004, 7005, + 7006, 7007, 7008, 7009, 7010, 7011, 7012, 7013, + 7014, 7015, 7016, 7017, 7018, 7019, 7020, 7021, + 7022, 7023, 7024, 7025, 7026, 7027, 7028, 7029, + 7030, 7031, 7032, 7033, 7034, 7035, 7036, 7037, + 7038, 7039, 7040, 7041, 7042, 7043, 7044, 7045, + 7046, 7047, 7048, 7049, 7050, 7051, 7052, 7053, + 7054, 7055, 7056, 7057, 7058, 7059, 7060, 7061, + 7062, 7063, 7064, 7065, 7066, 7067, 7068, 7069, + 7070, 7071, 7072, 7073, 7074, 7075, 7076, 7077, + 7078, 7079, 7080, 7081, 7082, 7083, 7084, 7085, + 7086, 7087, 7088, 7089, 7090, 7091, 7092, 0, + 0, 7093, 7094, 7095, 7096, 7097, 7098, 7099, + 7100, 7101, 7102, 7103, 7104, 7105, 7106, 7107, + 7108, 7109, 7110, 7111, 7112, 7113, 7114, 7115, + 7116, 7117, 7118, 7119, 7120, 7121, 7122, 7123, + 7124, 7125, 7126, 7127, 7128, 7129, 7130, 7131, + 7132, 7133, 7134, 7135, 7136, 7137, 7138, 7139, + 7140, 7141, 7142, 7143, 7144, 7145, 7146, 7147, + 7148, 7149, 7150, 7151, 7152, 7153, 7154, 7155, + 7156, 7157, 7158, 7159, 7160, 7161, 7162, 7163, + 7164, 7165, 7166, 7167, 7168, 7169, 7170, 7171, + 7172, 7173, 7174, 7175, 7118, 7176, 7177, 7178, + 7179, 7180, 7181, 7182, 7183, 7184, 7185, 7186, + 7187, 7188, 7189, 7190, 7191, 7192, 7193, 7194, + 7195, 7196, 7197, 7198, 7199, 7200, 7144, 7201, + 7202, 7203, 7204, 7205, 7206, 7207, 7208, 7209, + 7210, 7211, 7212, 7213, 7214, 7215, 7216, 7217, + 7218, 7219, 7220, 7221, 7222, 7223, 7224, 7225, + 7226, 7227, 7228, 7229, 7230, 7231, 7118, 7232, + 7233, 7234, 7235, 7236, 7237, 7238, 7239, 7240, + 7241, 7242, 7243, 7244, 7245, 7246, 7247, 7248, + 7249, 7250, 7251, 7252, 7253, 7254, 7255, 7256, + 7144, 7257, 7258, 7259, 7260, 7261, 7262, 7263, + 7264, 7265, 7266, 7267, 7268, 7269, 7270, 7271, + 7272, 7273, 7274, 7275, 7276, 7277, 7278, 7279, + 7280, 7281, 7282, 7283, 7284, 7285, 7286, 7287, + 7118, 7288, 7289, 7290, 7291, 7292, 7293, 7294, + 7295, 7296, 7297, 7298, 7299, 7300, 7301, 7302, + 7303, 7304, 7305, 7306, 7307, 7308, 7309, 7310, + 7311, 7312, 7144, 7313, 7314, 7315, 7316, 7317, + 7318, 7319, 7320, 7321, 7322, 7323, 7324, 7325, + 7326, 7327, 7328, 7329, 7330, 7331, 7332, 7333, + 7334, 7335, 7336, 7337, 7338, 7339, 7340, 7341, + 7342, 7343, 7118, 7344, 7345, 7346, 7347, 7348, + 7349, 7350, 7351, 7352, 7353, 7354, 7355, 7356, + 7357, 7358, 7359, 7360, 7361, 7362, 7363, 7364, + 7365, 7366, 7367, 7368, 7144, 7369, 7370, 7371, + 7372, 7373, 7374, 7375, 7376, 0, 0, 7377, + 7378, 7379, 7380, 7381, 7382, 7383, 7384, 7385, + 7386, 7377, 7378, 7379, 7380, 7381, 7382, 7383, + 7384, 7385, 7386, 7377, 7378, 7379, 7380, 7381, + 7382, 7383, 7384, 7385, 7386, 7377, 7378, 7379, + 7380, 7381, 7382, 7383, 7384, 7385, 7386, 7377, + 7378, 7379, 7380, 7381, 7382, 7383, 7384, 7385, + 7386, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 913, 913, 913, 913, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 913, 913, + 913, 913, 913, 913, 913, 913, 1225, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 1225, 913, 913, + 1119, 1119, 1119, 1119, 1119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1225, 1225, 1225, 1225, + 1225, 0, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, + 1225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6096,6 +6550,12 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7387, 7388, 7389, 7390, 7391, 7392, 7393, + 7394, 7395, 7396, 345, 7397, 7398, 7399, 7400, + 7401, 7402, 7403, 7404, 7405, 7406, 7407, 7408, + 7409, 7410, 7411, 7412, 7413, 7414, 7415, 7416, + 0, 0, 0, 0, 0, 0, 7417, 7418, + 7419, 7420, 7421, 7422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6122,71 +6582,49 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 614, 614, 614, 614, 614, 614, 614, + 0, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 614, + 614, 614, 0, 0, 614, 614, 614, 614, + 614, 614, 614, 0, 614, 614, 0, 614, + 614, 614, 614, 614, 0, 0, 0, 0, + 0, 7423, 7424, 7425, 7426, 7427, 7428, 7429, + 7430, 7431, 7432, 7433, 7434, 7435, 7436, 7437, + 7438, 7439, 7440, 7441, 7442, 7443, 7444, 7445, + 7446, 7447, 7448, 7449, 7450, 7451, 7452, 7453, + 7454, 7455, 7456, 7457, 7458, 7459, 7460, 7461, + 7462, 7463, 7464, 7465, 7466, 7467, 7468, 7469, + 7470, 7471, 7472, 7473, 7474, 7475, 7476, 7477, + 7478, 7479, 7480, 7481, 7482, 7483, 7484, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 614, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 543, 543, 543, - 543, 1172, 1172, 1172, 1172, 1172, 1172, 1172, - 1172, 1172, 1172, 0, 0, 0, 0, 0, - 11, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 0, 0, - 5741, 5741, 5741, 5741, 5741, 5741, 5741, 5741, - 5741, 556, 556, 556, 556, 556, 556, 556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6131, 6132, 6133, 6134, 6135, 6136, 6137, - 6138, 6139, 6140, 6141, 6142, 6143, 6144, 6145, - 6146, 6147, 6148, 6149, 6150, 6151, 6152, 6153, - 6154, 6155, 6156, 6157, 6158, 6159, 6160, 6161, - 6162, 6163, 6164, 6165, 6166, 6167, 6168, 6169, - 6170, 6171, 6172, 6173, 6174, 6175, 6176, 6177, - 6178, 6179, 6180, 6181, 6182, 6183, 6184, 6185, - 6186, 6187, 6188, 6189, 6190, 6191, 6192, 6193, - 6194, 6195, 6196, 6197, 6198, 543, 543, 543, - 543, 543, 543, 1173, 1153, 0, 0, 0, - 0, 1152, 1152, 1152, 1152, 1152, 1152, 1152, - 1152, 1152, 1152, 0, 0, 0, 0, 1105, - 1105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 0, 0, + 0, 614, 614, 614, 614, 614, 614, 614, + 595, 595, 595, 595, 595, 595, 595, 0, + 0, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 345, + 913, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6216,15 +6654,6 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 1148, 5846, 5846, - 5846, 1111, 5846, 5846, 5846, 5846, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6234,17 +6663,22 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 1148, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 5846, - 5846, 5846, 5846, 5846, 5846, 5846, 5846, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 614, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 614, 614, 614, + 614, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6266,620 +6700,852 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6199, 6200, 6201, 6202, 0, 6203, 6204, - 6205, 6206, 6207, 6208, 6209, 6210, 6211, 6212, - 6213, 6214, 6215, 6216, 6217, 6218, 6219, 6220, - 6221, 6222, 6223, 6224, 6225, 6226, 6227, 6228, - 6229, 0, 6200, 6201, 0, 6230, 0, 0, - 6205, 0, 6207, 6208, 6209, 6210, 6211, 6212, - 6213, 6214, 6215, 6216, 0, 6218, 6219, 6220, - 6221, 0, 6223, 0, 6225, 0, 0, 0, - 0, 0, 0, 6201, 0, 0, 0, 0, - 6205, 0, 6207, 0, 6209, 0, 6211, 6212, - 6213, 0, 6215, 6216, 0, 6218, 0, 0, - 6221, 0, 6223, 0, 6225, 0, 6227, 0, - 6229, 0, 6200, 6201, 0, 6230, 0, 0, - 6205, 6206, 6207, 6208, 0, 6210, 6211, 6212, - 6213, 6214, 6215, 6216, 0, 6218, 6219, 6220, - 6221, 0, 6223, 6224, 6225, 6226, 0, 6228, - 0, 6199, 6200, 6201, 6202, 6230, 6203, 6204, - 6205, 6206, 6207, 0, 6209, 6210, 6211, 6212, - 6213, 6214, 6215, 6216, 6217, 6218, 6219, 6220, - 6221, 6222, 6223, 6224, 6225, 0, 0, 0, - 0, 0, 6200, 6201, 6202, 0, 6203, 6204, - 6205, 6206, 6207, 0, 6209, 6210, 6211, 6212, - 6213, 6214, 6215, 6216, 6217, 6218, 6219, 6220, - 6221, 6222, 6223, 6224, 6225, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 595, 626, 626, 627, + 614, 1248, 1248, 1248, 1248, 1248, 1248, 1248, + 1248, 1248, 1248, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 345, 345, 345, 345, 345, 345, 345, + 0, 345, 345, 345, 345, 0, 345, 345, + 0, 345, 345, 345, 345, 345, 345, 345, + 345, 345, 345, 345, 345, 345, 345, 345, + 0, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, + 1182, 1182, 1182, 1182, 1182, 1182, 0, 0, + 6143, 6143, 6143, 6143, 6143, 6143, 6143, 6143, + 6143, 627, 627, 627, 627, 627, 627, 627, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7485, 7486, 7487, 7488, 7489, 7490, 7491, + 7492, 7493, 7494, 7495, 7496, 7497, 7498, 7499, + 7500, 7501, 7502, 7503, 7504, 7505, 7506, 7507, + 7508, 7509, 7510, 7511, 7512, 7513, 7514, 7515, + 7516, 7517, 7518, 7519, 7520, 7521, 7522, 7523, + 7524, 7525, 7526, 7527, 7528, 7529, 7530, 7531, + 7532, 7533, 7534, 7535, 7536, 7537, 7538, 7539, + 7540, 7541, 7542, 7543, 7544, 7545, 7546, 7547, + 7548, 7549, 7550, 7551, 7552, 614, 614, 614, + 614, 614, 614, 1249, 1227, 0, 0, 0, + 0, 1226, 1226, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 0, 0, 0, 0, 1179, + 1179, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 1222, 6248, 6248, + 6248, 1185, 6248, 6248, 6248, 6248, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 1222, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 6248, + 6248, 6248, 6248, 6248, 6248, 6248, 6248, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7553, 7554, 7555, 7556, 0, 7557, 7558, + 7559, 7560, 7561, 7562, 7563, 7564, 7565, 7566, + 7567, 7568, 7569, 7570, 7571, 7572, 7573, 7574, + 7575, 7576, 7577, 7578, 7579, 7580, 7581, 7582, + 7583, 0, 7554, 7555, 0, 7584, 0, 0, + 7559, 0, 7561, 7562, 7563, 7564, 7565, 7566, + 7567, 7568, 7569, 7570, 0, 7572, 7573, 7574, + 7575, 0, 7577, 0, 7579, 0, 0, 0, + 0, 0, 0, 7555, 0, 0, 0, 0, + 7559, 0, 7561, 0, 7563, 0, 7565, 7566, + 7567, 0, 7569, 7570, 0, 7572, 0, 0, + 7575, 0, 7577, 0, 7579, 0, 7581, 0, + 7583, 0, 7554, 7555, 0, 7584, 0, 0, + 7559, 7560, 7561, 7562, 0, 7564, 7565, 7566, + 7567, 7568, 7569, 7570, 0, 7572, 7573, 7574, + 7575, 0, 7577, 7578, 7579, 7580, 0, 7582, + 0, 7553, 7554, 7555, 7556, 7584, 7557, 7558, + 7559, 7560, 7561, 0, 7563, 7564, 7565, 7566, + 7567, 7568, 7569, 7570, 7571, 7572, 7573, 7574, + 7575, 7576, 7577, 7578, 7579, 0, 0, 0, + 0, 0, 7554, 7555, 7556, 0, 7557, 7558, + 7559, 7560, 7561, 0, 7563, 7564, 7565, 7566, + 7567, 7568, 7569, 7570, 7571, 7572, 7573, 7574, + 7575, 7576, 7577, 7578, 7579, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 74, 74, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 78, 78, 78, 78, 2579, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 0, 0, 0, + 0, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 0, 0, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 0, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 2579, 0, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7585, 7586, 7587, 7588, 7589, 7590, 7591, + 7592, 7593, 7594, 7595, 1288, 1288, 78, 78, + 78, 7596, 7597, 7598, 7599, 7600, 7601, 7602, + 7603, 7604, 7605, 7606, 7607, 7608, 7609, 7610, + 7611, 7612, 7613, 7614, 7615, 7616, 7617, 7618, + 7619, 7620, 7621, 7622, 7623, 7624, 7625, 7626, + 78, 7627, 7628, 7629, 7630, 7631, 7632, 7633, + 7634, 7635, 7636, 7637, 7638, 7639, 7640, 7641, + 7642, 7643, 7644, 7645, 7646, 7647, 7648, 7649, + 7650, 7651, 7652, 7653, 7654, 7655, 7656, 7657, + 7658, 7659, 7660, 7661, 7662, 7663, 7664, 7665, + 7666, 7667, 7668, 7669, 7670, 7671, 7672, 7673, + 7674, 7675, 7676, 7677, 7678, 7679, 7680, 7681, + 7682, 7683, 7684, 7685, 7686, 7687, 78, 78, + 78, 7688, 7689, 7690, 7691, 7692, 7693, 7694, + 7695, 7696, 7697, 7698, 7699, 7700, 7701, 7702, + 7703, 7704, 7705, 7706, 7707, 7708, 7709, 7710, + 7711, 7712, 7713, 913, 913, 913, 913, 7714, + 913, 7715, 7714, 7714, 7714, 7714, 7714, 7714, + 7714, 7714, 7714, 7714, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 913, 913, + 913, 913, 913, 913, 913, 913, 78, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7716, + 7716, 7716, 7716, 7716, 7716, 7716, 7716, 7716, + 7716, 7716, 7716, 7716, 7716, 7716, 7716, 7716, + 7716, 7716, 7716, 7716, 7716, 7716, 7716, 7716, + 7716, 7717, 7718, 7719, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7720, 7721, 7722, 7723, 7724, 7725, 7726, + 7727, 7728, 7729, 7730, 7731, 7732, 7733, 7734, + 7735, 7736, 7737, 7738, 7739, 7740, 7741, 7742, + 7743, 7744, 7745, 7746, 7747, 7748, 7749, 7750, + 7751, 7752, 7753, 7754, 7755, 7756, 7757, 7758, + 7759, 7760, 7761, 7762, 7763, 0, 0, 0, + 0, 7764, 7765, 7766, 7767, 7768, 7769, 7770, + 7771, 7772, 0, 0, 0, 0, 0, 0, + 0, 7773, 7774, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2579, 2579, 2579, 2579, 2579, 2579, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 78, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 78, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 78, 78, 78, 78, + 2579, 2579, 2579, 2579, 2579, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 78, 78, 78, 2579, 78, 78, + 78, 2579, 2579, 2579, 7775, 7775, 7775, 7775, + 7775, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 78, 2579, 78, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 78, 78, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 76, + 76, 76, 76, 76, 76, 76, 76, 78, + 78, 78, 78, 78, 2579, 2579, 2579, 2579, + 78, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 2579, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 2579, 2579, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 2579, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 78, + 78, 78, 78, 78, 78, 2579, 78, 78, + 78, 2579, 2579, 2579, 78, 78, 2579, 2579, + 2579, 0, 0, 0, 0, 2579, 2579, 2579, + 2579, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 2579, 2579, 0, 0, + 0, 78, 78, 78, 78, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 78, 78, 78, + 0, 0, 0, 0, 78, 78, 78, 78, + 78, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 78, 78, + 78, 78, 78, 0, 0, 0, 0, 0, + 0, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 0, 0, 0, + 0, 2579, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 0, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 0, 0, 0, 0, 0, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 0, 0, 0, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 0, 0, 0, 0, 0, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 0, + 0, 78, 78, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 76, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 76, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 0, + 0, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 0, 0, + 0, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 0, 0, 0, 0, 0, 0, + 0, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 0, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 0, + 0, 0, 0, 0, 0, 0, 0, 2579, + 2579, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 2579, 2579, 2579, 0, 0, 0, + 0, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 0, 0, 0, 0, 0, 0, + 0, 2579, 2579, 2579, 2579, 2579, 2579, 2579, + 2579, 2579, 0, 0, 0, 0, 0, 0, + 0, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 0, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7377, 7378, 7379, 7380, 7381, 7382, 7383, + 7384, 7385, 7386, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 75, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 79, 79, 79, 79, 2397, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 0, 0, 0, - 0, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 0, 0, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 0, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 2397, 0, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6231, 6232, 6233, 6234, 6235, 6236, 6237, - 6238, 6239, 6240, 6241, 1211, 1211, 0, 0, - 0, 6242, 6243, 6244, 6245, 6246, 6247, 6248, - 6249, 6250, 6251, 6252, 6253, 6254, 6255, 6256, - 6257, 6258, 6259, 6260, 6261, 6262, 6263, 6264, - 6265, 6266, 6267, 6268, 6269, 6270, 6271, 6272, - 79, 6273, 6274, 6275, 6276, 6277, 6278, 6279, - 6280, 6281, 6282, 6283, 6284, 6285, 6286, 6287, - 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6295, - 6296, 6297, 6298, 6299, 6300, 6301, 6302, 6303, - 6304, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 6305, 6306, 6307, 0, 0, - 0, 2541, 2541, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 2541, - 2541, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 6308, - 841, 6309, 6308, 6308, 6308, 6308, 6308, 6308, - 6308, 6308, 6308, 6308, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 841, 841, - 841, 841, 841, 841, 841, 841, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 6310, - 6310, 6310, 6310, 6310, 6310, 6310, 6310, 6310, - 6310, 6310, 6310, 6310, 6310, 6310, 6310, 6310, - 6310, 6310, 6310, 6310, 6310, 6310, 6310, 6310, - 6310, 6311, 6312, 6313, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6314, 6315, 6316, 6317, 6318, 6319, 6320, - 6321, 6322, 6323, 6324, 6325, 6326, 6327, 6328, - 6329, 6330, 6331, 6332, 6333, 6334, 6335, 6336, - 6337, 6338, 6339, 6340, 6341, 6342, 6343, 6344, - 6345, 6346, 6347, 6348, 6349, 6350, 6351, 6352, - 6353, 6354, 6355, 6356, 6357, 0, 0, 0, - 0, 6358, 6359, 6360, 6361, 6362, 6363, 6364, - 6365, 6366, 0, 0, 0, 0, 0, 0, - 0, 6367, 6368, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2397, 2397, 2397, 2397, 2397, 2397, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 79, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 79, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 79, 79, 79, 79, - 2397, 2397, 2397, 2397, 2397, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 79, 79, 79, 2397, 79, 79, - 79, 2397, 2397, 2397, 6369, 6369, 6369, 6369, - 6369, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 79, 2397, 79, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 79, 79, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 77, - 77, 77, 77, 77, 77, 77, 77, 79, - 79, 79, 79, 79, 2397, 2397, 2397, 2397, - 79, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 2397, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 2397, 2397, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 2397, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 79, - 79, 79, 79, 79, 79, 2397, 79, 79, - 79, 2397, 2397, 2397, 79, 79, 2397, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 2397, 2397, 0, 0, - 0, 79, 79, 79, 79, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 79, 79, - 79, 79, 0, 0, 0, 0, 0, 0, - 0, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 0, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 0, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2815, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2815, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 0, 2397, 2397, 2397, 2397, - 0, 0, 0, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 0, 0, 2397, 2397, - 2397, 2397, 2397, 2397, 0, 0, 0, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 0, 0, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 2397, 2397, 2397, 2397, 2397, 2397, 2397, - 2397, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 0, - 0, 2397, 2397, 2397, 2397, 0, 0, 0, - 0, 2397, 2397, 2397, 0, 0, 0, 0, - 0, 2397, 2397, 2397, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2397, 2397, 2397, 2397, 2397, 2397, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 3035, 3035, 3035, 3035, 3035, 3035, - 3035, 3035, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6370, 6371, 6372, 6373, 6374, 4373, 6375, - 6376, 6377, 6378, 4374, 6379, 6380, 6381, 4375, - 6382, 6383, 6384, 6385, 6386, 6387, 6388, 6389, - 6390, 6391, 6392, 6393, 4433, 6394, 6395, 6396, - 6397, 6398, 6399, 6400, 6401, 6402, 4438, 4376, - 4377, 4439, 6403, 6404, 4184, 6405, 4378, 6406, - 6407, 6408, 6409, 6409, 6409, 6410, 6411, 6412, - 6413, 6414, 6415, 6416, 6417, 6418, 6419, 6420, - 6421, 6422, 6423, 6424, 6425, 6426, 6427, 6427, - 4441, 6428, 6429, 6430, 6431, 4380, 6432, 6433, - 6434, 4337, 6435, 6436, 6437, 6438, 6439, 6440, - 6441, 6442, 6443, 6444, 6445, 6446, 6447, 6448, - 6449, 6450, 6451, 6452, 6453, 6454, 6455, 6456, - 6457, 6458, 6459, 6460, 6460, 6461, 6462, 6463, - 4180, 6464, 6465, 6466, 6467, 6468, 6469, 6470, - 6471, 4385, 6472, 6473, 6474, 6475, 6476, 6477, - 6478, 6479, 6480, 6481, 6482, 6483, 6484, 6485, - 6486, 6487, 6488, 6489, 6490, 6491, 6492, 4126, - 6493, 6494, 6495, 6495, 6496, 6497, 6497, 6498, - 6499, 6500, 6501, 6502, 6503, 6504, 6505, 6506, - 6507, 6508, 6509, 6510, 4386, 6511, 6512, 6513, - 6514, 4453, 6514, 6515, 4388, 6516, 6517, 6518, - 6519, 4389, 4099, 6520, 6521, 6522, 6523, 6524, - 6525, 6526, 6527, 6528, 6529, 6530, 6531, 6532, - 6533, 6534, 6535, 6536, 6537, 6538, 6539, 6540, - 6541, 4390, 6542, 6543, 6544, 6545, 6546, 6547, - 4392, 6548, 6549, 6550, 6551, 6552, 6553, 6554, - 6555, 4127, 4461, 6556, 6557, 6558, 6559, 6560, - 6561, 6562, 6563, 4393, 6564, 6565, 6566, 6567, - 4504, 6568, 6569, 6570, 6571, 6572, 6573, 6574, - 6575, 6576, 6577, 6578, 6579, 6580, 4197, 6581, - 6582, 6583, 6584, 6585, 6586, 6587, 6588, 6589, - 6590, 6591, 4394, 4284, 6592, 6593, 6594, 6595, - 6596, 6597, 6598, 6599, 4465, 6600, 6601, 6602, - 6603, 6604, 6605, 6606, 6607, 4466, 6608, 6609, - 6610, 6611, 6612, 6613, 6614, 6615, 6616, 6617, - 6618, 6619, 4468, 6620, 6621, 6622, 6623, 6624, - 6625, 6626, 6627, 6628, 6629, 6630, 6630, 6631, - 6632, 4470, 6633, 6634, 6635, 6636, 6637, 6638, - 6639, 4183, 6640, 6641, 6642, 6643, 6644, 6645, - 6646, 4476, 6647, 6648, 6649, 6650, 6651, 6652, - 6652, 4477, 4506, 6653, 6654, 6655, 6656, 6657, - 4145, 4479, 6658, 6659, 4405, 6660, 6661, 4359, - 6662, 6663, 4409, 6664, 6665, 6666, 6667, 6667, - 6668, 6669, 6670, 6671, 6672, 6673, 6674, 6675, - 6676, 6677, 6678, 6679, 6680, 6681, 6682, 6683, - 6684, 6685, 6686, 6687, 6688, 6689, 6690, 6691, - 6692, 6693, 6694, 4415, 6695, 6696, 6697, 6698, - 6699, 6700, 6701, 6702, 6703, 6704, 6705, 6706, - 6707, 6708, 6709, 6710, 6496, 6711, 6712, 6713, - 6714, 6715, 6716, 6717, 6718, 6719, 6720, 6721, - 6722, 4201, 6723, 6724, 6725, 6726, 6727, 6728, - 4418, 6729, 6730, 6731, 6732, 6733, 6734, 6735, - 6736, 6737, 6738, 6739, 6740, 6741, 6742, 6743, - 6744, 6745, 6746, 6747, 6748, 4140, 6749, 6750, - 6751, 6752, 6753, 6754, 4486, 6755, 6756, 6757, - 6758, 6759, 6760, 6761, 6762, 6763, 6764, 6765, - 6766, 6767, 6768, 6769, 6770, 6771, 6772, 6773, - 6774, 4491, 4492, 6775, 6776, 6777, 6778, 6779, - 6780, 6781, 6782, 6783, 6784, 6785, 6786, 6787, - 4493, 6788, 6789, 6790, 6791, 6792, 6793, 6794, - 6795, 6796, 6797, 6798, 6799, 6800, 6801, 6802, - 6803, 6804, 6805, 6806, 6807, 6808, 6809, 6810, - 6811, 6812, 6813, 6814, 6815, 6816, 6817, 4499, - 4499, 6818, 6819, 6820, 6821, 6822, 6823, 6824, - 6825, 6826, 6827, 4500, 6828, 6829, 6830, 6831, - 6832, 6833, 6834, 6835, 6836, 6837, 6838, 6839, - 6840, 6841, 6842, 6843, 6844, 6845, 6846, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7776, 7777, 7778, 7779, 7780, 4649, 7781, + 7782, 7783, 7784, 4650, 7785, 7786, 7787, 4651, + 7788, 7789, 7790, 7791, 7792, 7793, 7794, 7795, + 7796, 7797, 7798, 7799, 4709, 7800, 7801, 7802, + 7803, 7804, 7805, 7806, 7807, 7808, 4714, 4652, + 4653, 4715, 7809, 7810, 4460, 7811, 4654, 7812, + 7813, 7814, 7815, 7815, 7815, 7816, 7817, 7818, + 7819, 7820, 7821, 7822, 7823, 7824, 7825, 7826, + 7827, 7828, 7829, 7830, 7831, 7832, 7833, 7833, + 4717, 7834, 7835, 7836, 7837, 4656, 7838, 7839, + 7840, 4613, 7841, 7842, 7843, 7844, 7845, 7846, + 7847, 7848, 7849, 7850, 7851, 7852, 7853, 7854, + 7855, 7856, 7857, 7858, 7859, 7860, 7861, 7862, + 7863, 7864, 7865, 7866, 7866, 7867, 7868, 7869, + 4456, 7870, 7871, 7872, 7873, 7874, 7875, 7876, + 7877, 4661, 7878, 7879, 7880, 7881, 7882, 7883, + 7884, 7885, 7886, 7887, 7888, 7889, 7890, 7891, + 7892, 7893, 7894, 7895, 7896, 7897, 7898, 4402, + 7899, 7900, 7901, 7901, 7902, 7903, 7903, 7904, + 7905, 7906, 7907, 7908, 7909, 7910, 7911, 7912, + 7913, 7914, 7915, 7916, 4662, 7917, 7918, 7919, + 7920, 4729, 7920, 7921, 4664, 7922, 7923, 7924, + 7925, 4665, 4375, 7926, 7927, 7928, 7929, 7930, + 7931, 7932, 7933, 7934, 7935, 7936, 7937, 7938, + 7939, 7940, 7941, 7942, 7943, 7944, 7945, 7946, + 7947, 4666, 7948, 7949, 7950, 7951, 7952, 7953, + 4668, 7954, 7955, 7956, 7957, 7958, 7959, 7960, + 7961, 4403, 4737, 7962, 7963, 7964, 7965, 7966, + 7967, 7968, 7969, 4669, 7970, 7971, 7972, 7973, + 4780, 7974, 7975, 7976, 7977, 7978, 7979, 7980, + 7981, 7982, 7983, 7984, 7985, 7986, 4473, 7987, + 7988, 7989, 7990, 7991, 7992, 7993, 7994, 7995, + 7996, 7997, 4670, 4560, 7998, 7999, 8000, 8001, + 8002, 8003, 8004, 8005, 4741, 8006, 8007, 8008, + 8009, 8010, 8011, 8012, 8013, 4742, 8014, 8015, + 8016, 8017, 8018, 8019, 8020, 8021, 8022, 8023, + 8024, 8025, 4744, 8026, 8027, 8028, 8029, 8030, + 8031, 8032, 8033, 8034, 8035, 8036, 8036, 8037, + 8038, 4746, 8039, 8040, 8041, 8042, 8043, 8044, + 8045, 4459, 8046, 8047, 8048, 8049, 8050, 8051, + 8052, 4752, 8053, 8054, 8055, 8056, 8057, 8058, + 8058, 4753, 4782, 8059, 8060, 8061, 8062, 8063, + 4421, 4755, 8064, 8065, 4681, 8066, 8067, 4635, + 8068, 8069, 4685, 8070, 8071, 8072, 8073, 8073, + 8074, 8075, 8076, 8077, 8078, 8079, 8080, 8081, + 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, + 8090, 8091, 8092, 8093, 8094, 8095, 8096, 8097, + 8098, 8099, 8100, 4691, 8101, 8102, 8103, 8104, + 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8112, + 8113, 8114, 8115, 8116, 7902, 8117, 8118, 8119, + 8120, 8121, 8122, 8123, 8124, 8125, 8126, 8127, + 8128, 4477, 8129, 8130, 8131, 8132, 8133, 8134, + 4694, 8135, 8136, 8137, 8138, 8139, 8140, 8141, + 8142, 8143, 8144, 8145, 8146, 8147, 8148, 8149, + 8150, 8151, 8152, 8153, 8154, 4416, 8155, 8156, + 8157, 8158, 8159, 8160, 4762, 8161, 8162, 8163, + 8164, 8165, 8166, 8167, 8168, 8169, 8170, 8171, + 8172, 8173, 8174, 8175, 8176, 8177, 8178, 8179, + 8180, 4767, 4768, 8181, 8182, 8183, 8184, 8185, + 8186, 8187, 8188, 8189, 8190, 8191, 8192, 8193, + 4769, 8194, 8195, 8196, 8197, 8198, 8199, 8200, + 8201, 8202, 8203, 8204, 8205, 8206, 8207, 8208, + 8209, 8210, 8211, 8212, 8213, 8214, 8215, 8216, + 8217, 8218, 8219, 8220, 8221, 8222, 8223, 4775, + 4775, 8224, 8225, 8226, 8227, 8228, 8229, 8230, + 8231, 8232, 8233, 4776, 8234, 8235, 8236, 8237, + 8238, 8239, 8240, 8241, 8242, 8243, 8244, 8245, + 8246, 8247, 8248, 8249, 8250, 8251, 8252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6906,23 +7572,64 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1459, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 0, 0, 0, 0, + 0, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 3227, 3227, 3227, 3227, 3227, 3227, 3227, + 3227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 2129, 2129, 2129, 2129, 2129, 2129, 2129, - 2129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -6931,6927 +7638,8359 @@ static const utf8proc_uint16_t utf8proc_stage2table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 8253, 8253, 8253, 8253, 8253, 8253, 8253, + 8253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 577, 577, - 577, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 4086, - 4086, 4086, 4086, 4086, 4086, 4086, 4086, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 648, 648, 648, 648, 648, 648, 648, + 648, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 4362, + 4362, 4362, 4362, 4362, 4362, 4362, 4362, 0, 0, }; static const utf8proc_property_t utf8proc_properties[] = { - {0, 0, 0, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false,false,false,false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_S, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_LF}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CR}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5093, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5084, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5096, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 0, UINT16_MAX, 0, UINT16_MAX, 0, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1, UINT16_MAX, 1, UINT16_MAX, 2784, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2, UINT16_MAX, 2, UINT16_MAX, 49, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3, UINT16_MAX, 3, UINT16_MAX, 704, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4, UINT16_MAX, 4, UINT16_MAX, 62, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5, UINT16_MAX, 5, UINT16_MAX, 2872, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6, UINT16_MAX, 6, UINT16_MAX, 782, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7, UINT16_MAX, 7, UINT16_MAX, 808, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8, UINT16_MAX, 8, UINT16_MAX, 111, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9, UINT16_MAX, 9, UINT16_MAX, 898, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 10, UINT16_MAX, 10, UINT16_MAX, 913, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 11, UINT16_MAX, 11, UINT16_MAX, 999, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 12, UINT16_MAX, 12, UINT16_MAX, 2890, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 13, UINT16_MAX, 13, UINT16_MAX, 160, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 14, UINT16_MAX, 14, UINT16_MAX, 205, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 15, UINT16_MAX, 15, UINT16_MAX, 2982, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 16, UINT16_MAX, 16, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 17, UINT16_MAX, 17, UINT16_MAX, 1087, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 18, UINT16_MAX, 18, UINT16_MAX, 1173, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 19, UINT16_MAX, 19, UINT16_MAX, 1257, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 20, UINT16_MAX, 20, UINT16_MAX, 254, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 21, UINT16_MAX, 21, UINT16_MAX, 3042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 22, UINT16_MAX, 22, UINT16_MAX, 1337, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 23, UINT16_MAX, 23, UINT16_MAX, 3122, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 24, UINT16_MAX, 24, UINT16_MAX, 303, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 25, UINT16_MAX, 25, UINT16_MAX, 1423, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1491, UINT16_MAX, 1491, 352, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1493, UINT16_MAX, 1493, 2818, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2812, UINT16_MAX, 2812, 401, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1494, UINT16_MAX, 1494, 743, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1495, UINT16_MAX, 1495, 414, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2837, UINT16_MAX, 2837, 2875, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1497, UINT16_MAX, 1497, 795, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1498, UINT16_MAX, 1498, 853, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1499, UINT16_MAX, 1499, 463, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1500, UINT16_MAX, 1500, 901, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1501, UINT16_MAX, 1501, 956, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1502, UINT16_MAX, 1502, 1043, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1503, UINT16_MAX, 1503, 2932, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1504, UINT16_MAX, 1504, 512, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1505, UINT16_MAX, 1505, 557, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1507, UINT16_MAX, 1507, 2994, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2826, UINT16_MAX, 2826, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1508, UINT16_MAX, 1508, 1130, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 3305, UINT16_MAX, 3305, 1215, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1509, UINT16_MAX, 1509, 1296, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1510, UINT16_MAX, 1510, 606, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2908, UINT16_MAX, 2908, 3082, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1511, UINT16_MAX, 1511, 1380, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2925, UINT16_MAX, 2925, 3131, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 3312, UINT16_MAX, 3312, 655, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2834, UINT16_MAX, 2834, 1466, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_NOBREAK, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 1621, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PI, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 1, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35, 35, 7220, UINT16_MAX, 7220, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 14, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 16423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 16426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 16429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8240, 50, UINT16_MAX, 50, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8243, 53, UINT16_MAX, 53, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8246, 56, UINT16_MAX, 56, UINT16_MAX, 3143, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8249, 59, UINT16_MAX, 59, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8252, 62, UINT16_MAX, 62, UINT16_MAX, 1537, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8255, 65, UINT16_MAX, 65, UINT16_MAX, 1579, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 66, UINT16_MAX, 66, UINT16_MAX, 1549, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8259, 69, UINT16_MAX, 69, UINT16_MAX, 2852, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8262, 72, UINT16_MAX, 72, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8265, 75, UINT16_MAX, 75, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8268, 78, UINT16_MAX, 78, UINT16_MAX, 3357, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8271, 81, UINT16_MAX, 81, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8274, 84, UINT16_MAX, 84, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8277, 87, UINT16_MAX, 87, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8280, 90, UINT16_MAX, 90, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8283, 93, UINT16_MAX, 93, UINT16_MAX, 2878, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 94, UINT16_MAX, 94, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8287, 97, UINT16_MAX, 97, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8290, 100, UINT16_MAX, 100, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8293, 103, UINT16_MAX, 103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8296, 106, UINT16_MAX, 106, UINT16_MAX, 3461, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8299, 109, UINT16_MAX, 109, UINT16_MAX, 1597, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8302, 112, UINT16_MAX, 112, UINT16_MAX, 1591, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 113, UINT16_MAX, 113, UINT16_MAX, 1585, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8306, 116, UINT16_MAX, 116, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8309, 119, UINT16_MAX, 119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8312, 122, UINT16_MAX, 122, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8315, 125, UINT16_MAX, 125, UINT16_MAX, 1509, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8318, 128, UINT16_MAX, 128, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 129, UINT16_MAX, 129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8322, 8069, UINT16_MAX, 8069, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8324, UINT16_MAX, 8070, UINT16_MAX, 8070, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8326, UINT16_MAX, 8071, UINT16_MAX, 8071, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8328, UINT16_MAX, 8072, UINT16_MAX, 8072, 3192, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8330, UINT16_MAX, 8073, UINT16_MAX, 8073, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8332, UINT16_MAX, 8074, UINT16_MAX, 8074, 1540, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8334, UINT16_MAX, 2836, UINT16_MAX, 2836, 1582, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1492, UINT16_MAX, 1492, 1558, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8336, UINT16_MAX, 8075, UINT16_MAX, 8075, 2855, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8338, UINT16_MAX, 8076, UINT16_MAX, 8076, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8340, UINT16_MAX, 8077, UINT16_MAX, 8077, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8342, UINT16_MAX, 8078, UINT16_MAX, 8078, 3406, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8344, UINT16_MAX, 8079, UINT16_MAX, 8079, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8346, UINT16_MAX, 8080, UINT16_MAX, 8080, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8348, UINT16_MAX, 8081, UINT16_MAX, 8081, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8350, UINT16_MAX, 8082, UINT16_MAX, 8082, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8352, UINT16_MAX, 8083, UINT16_MAX, 8083, 2881, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8084, UINT16_MAX, 8084, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8354, UINT16_MAX, 8085, UINT16_MAX, 8085, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8356, UINT16_MAX, 8086, UINT16_MAX, 8086, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8358, UINT16_MAX, 8087, UINT16_MAX, 8087, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8360, UINT16_MAX, 8088, UINT16_MAX, 8088, 3510, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8362, UINT16_MAX, 8089, UINT16_MAX, 8089, 1606, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8364, UINT16_MAX, 8090, UINT16_MAX, 8090, 1594, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8091, UINT16_MAX, 8091, 1588, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8366, UINT16_MAX, 8092, UINT16_MAX, 8092, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8368, UINT16_MAX, 8093, UINT16_MAX, 8093, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8370, UINT16_MAX, 8094, UINT16_MAX, 8094, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8372, UINT16_MAX, 8095, UINT16_MAX, 8095, 1523, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8374, UINT16_MAX, 8096, UINT16_MAX, 8096, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8097, UINT16_MAX, 8097, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8376, UINT16_MAX, 8098, UINT16_MAX, 8098, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8378, 188, UINT16_MAX, 188, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8381, UINT16_MAX, 8099, UINT16_MAX, 8099, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8383, 193, UINT16_MAX, 193, UINT16_MAX, 3259, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8386, UINT16_MAX, 8100, UINT16_MAX, 8100, 3308, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8388, 198, UINT16_MAX, 198, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8391, UINT16_MAX, 8101, UINT16_MAX, 8101, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8393, 203, UINT16_MAX, 203, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8396, UINT16_MAX, 8102, UINT16_MAX, 8102, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8398, 208, UINT16_MAX, 208, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8401, UINT16_MAX, 8103, UINT16_MAX, 8103, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8403, 213, UINT16_MAX, 213, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8406, UINT16_MAX, 8104, UINT16_MAX, 8104, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8408, 218, UINT16_MAX, 218, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8411, UINT16_MAX, 8105, UINT16_MAX, 8105, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8413, 223, UINT16_MAX, 223, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8416, UINT16_MAX, 8106, UINT16_MAX, 8106, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 226, UINT16_MAX, 226, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8107, UINT16_MAX, 8107, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8419, 229, UINT16_MAX, 229, UINT16_MAX, 2858, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8422, UINT16_MAX, 8108, UINT16_MAX, 8108, 2862, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8424, 234, UINT16_MAX, 234, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8427, UINT16_MAX, 8109, UINT16_MAX, 8109, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8429, 239, UINT16_MAX, 239, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8432, UINT16_MAX, 8110, UINT16_MAX, 8110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8434, 244, UINT16_MAX, 244, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8437, UINT16_MAX, 8111, UINT16_MAX, 8111, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8439, 249, UINT16_MAX, 249, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8442, UINT16_MAX, 8112, UINT16_MAX, 8112, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8444, 254, UINT16_MAX, 254, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8447, UINT16_MAX, 8113, UINT16_MAX, 8113, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8449, 259, UINT16_MAX, 259, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8452, UINT16_MAX, 8114, UINT16_MAX, 8114, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8454, 264, UINT16_MAX, 264, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8457, UINT16_MAX, 8115, UINT16_MAX, 8115, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8459, 269, UINT16_MAX, 269, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8462, UINT16_MAX, 8116, UINT16_MAX, 8116, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8464, 274, UINT16_MAX, 274, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8467, UINT16_MAX, 8117, UINT16_MAX, 8117, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 277, UINT16_MAX, 277, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 5164, UINT16_MAX, 5164, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8470, 280, UINT16_MAX, 280, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8473, UINT16_MAX, 8118, UINT16_MAX, 8118, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8475, 285, UINT16_MAX, 285, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8478, UINT16_MAX, 8119, UINT16_MAX, 8119, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8480, 290, UINT16_MAX, 290, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8483, UINT16_MAX, 8120, UINT16_MAX, 8120, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8485, 295, UINT16_MAX, 295, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8488, UINT16_MAX, 8121, UINT16_MAX, 8121, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8490, 8492, UINT16_MAX, 8, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1499, UINT16_MAX, 1499, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8494, 304, UINT16_MAX, 304, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8497, UINT16_MAX, 8122, UINT16_MAX, 8122, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8499, 309, UINT16_MAX, 309, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8502, UINT16_MAX, 8123, UINT16_MAX, 8123, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8504, 314, UINT16_MAX, 314, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8507, UINT16_MAX, 8124, UINT16_MAX, 8124, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8509, 319, UINT16_MAX, 319, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8512, UINT16_MAX, 8125, UINT16_MAX, 8125, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8514, 324, UINT16_MAX, 324, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8517, UINT16_MAX, 8126, UINT16_MAX, 8126, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8519, 329, UINT16_MAX, 329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8522, UINT16_MAX, 8127, UINT16_MAX, 8127, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8524, 334, UINT16_MAX, 334, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8527, UINT16_MAX, 8128, UINT16_MAX, 8128, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 337, UINT16_MAX, 337, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8129, UINT16_MAX, 8129, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8530, 340, UINT16_MAX, 340, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8533, UINT16_MAX, 8130, UINT16_MAX, 8130, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8535, 345, UINT16_MAX, 345, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8538, UINT16_MAX, 8131, UINT16_MAX, 8131, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8540, 350, UINT16_MAX, 350, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8543, UINT16_MAX, 8132, UINT16_MAX, 8132, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8545, 8545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 355, UINT16_MAX, 355, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8133, UINT16_MAX, 8133, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8548, 358, UINT16_MAX, 358, UINT16_MAX, 2974, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8551, UINT16_MAX, 8134, UINT16_MAX, 8134, 2978, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8553, 363, UINT16_MAX, 363, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8556, UINT16_MAX, 8135, UINT16_MAX, 8135, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8558, 368, UINT16_MAX, 368, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8561, UINT16_MAX, 8136, UINT16_MAX, 8136, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 371, UINT16_MAX, 371, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8137, UINT16_MAX, 8137, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8564, 374, UINT16_MAX, 374, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8567, UINT16_MAX, 8138, UINT16_MAX, 8138, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8569, 379, UINT16_MAX, 379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8572, UINT16_MAX, 8139, UINT16_MAX, 8139, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8574, 384, UINT16_MAX, 384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8577, UINT16_MAX, 8140, UINT16_MAX, 8140, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8579, 389, UINT16_MAX, 389, UINT16_MAX, 3012, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8582, UINT16_MAX, 8141, UINT16_MAX, 8141, 3015, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8584, 394, UINT16_MAX, 394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8587, UINT16_MAX, 8142, UINT16_MAX, 8142, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8589, 399, UINT16_MAX, 399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8592, UINT16_MAX, 8143, UINT16_MAX, 8143, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8594, 404, UINT16_MAX, 404, UINT16_MAX, 3018, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8597, UINT16_MAX, 8144, UINT16_MAX, 8144, 3021, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8599, 409, UINT16_MAX, 409, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8602, UINT16_MAX, 8145, UINT16_MAX, 8145, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8604, 414, UINT16_MAX, 414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8607, UINT16_MAX, 8146, UINT16_MAX, 8146, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 417, UINT16_MAX, 417, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8147, UINT16_MAX, 8147, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8610, 420, UINT16_MAX, 420, UINT16_MAX, 3030, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8613, UINT16_MAX, 8148, UINT16_MAX, 8148, 3033, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8615, 425, UINT16_MAX, 425, UINT16_MAX, 3036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8618, UINT16_MAX, 8149, UINT16_MAX, 8149, 3039, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8620, 430, UINT16_MAX, 430, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8623, UINT16_MAX, 8150, UINT16_MAX, 8150, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8625, 435, UINT16_MAX, 435, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8628, UINT16_MAX, 8151, UINT16_MAX, 8151, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8630, 440, UINT16_MAX, 440, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8633, UINT16_MAX, 8152, UINT16_MAX, 8152, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8635, 445, UINT16_MAX, 445, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8638, UINT16_MAX, 8153, UINT16_MAX, 8153, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8640, 450, UINT16_MAX, 450, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8643, UINT16_MAX, 8154, UINT16_MAX, 8154, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8645, 455, UINT16_MAX, 455, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8648, UINT16_MAX, 8155, UINT16_MAX, 8155, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8650, 460, UINT16_MAX, 460, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8653, 463, UINT16_MAX, 463, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8656, UINT16_MAX, 8156, UINT16_MAX, 8156, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8658, 468, UINT16_MAX, 468, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8661, UINT16_MAX, 8157, UINT16_MAX, 8157, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8663, 473, UINT16_MAX, 473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8666, UINT16_MAX, 8158, UINT16_MAX, 8158, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 18, 18, 3305, UINT16_MAX, 3305, 3140, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8159, UINT16_MAX, 8159, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 476, UINT16_MAX, 476, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 477, UINT16_MAX, 477, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8160, UINT16_MAX, 8160, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 478, UINT16_MAX, 478, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8161, UINT16_MAX, 8161, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 479, UINT16_MAX, 479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 480, UINT16_MAX, 480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8162, UINT16_MAX, 8162, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 481, UINT16_MAX, 481, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 482, UINT16_MAX, 482, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 483, UINT16_MAX, 483, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8163, UINT16_MAX, 8163, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 484, UINT16_MAX, 484, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 485, UINT16_MAX, 485, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 486, UINT16_MAX, 486, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 487, UINT16_MAX, 487, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8164, UINT16_MAX, 8164, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 488, UINT16_MAX, 488, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 489, UINT16_MAX, 489, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8165, UINT16_MAX, 8165, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 490, UINT16_MAX, 490, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 491, UINT16_MAX, 491, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 492, UINT16_MAX, 492, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8166, UINT16_MAX, 8166, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8167, UINT16_MAX, 8167, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 493, UINT16_MAX, 493, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 494, UINT16_MAX, 494, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8168, UINT16_MAX, 8168, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 495, UINT16_MAX, 495, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8688, 498, UINT16_MAX, 498, UINT16_MAX, 3565, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8691, UINT16_MAX, 8169, UINT16_MAX, 8169, 3614, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 501, UINT16_MAX, 501, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8170, UINT16_MAX, 8170, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 502, UINT16_MAX, 502, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8171, UINT16_MAX, 8171, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 503, UINT16_MAX, 503, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 504, UINT16_MAX, 504, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8172, UINT16_MAX, 8172, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 505, UINT16_MAX, 505, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 506, UINT16_MAX, 506, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8173, UINT16_MAX, 8173, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 507, UINT16_MAX, 507, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8700, 510, UINT16_MAX, 510, UINT16_MAX, 3663, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8703, UINT16_MAX, 8174, UINT16_MAX, 8174, 3712, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 513, UINT16_MAX, 513, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 514, UINT16_MAX, 514, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 515, UINT16_MAX, 515, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8175, UINT16_MAX, 8175, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 516, UINT16_MAX, 516, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8176, UINT16_MAX, 8176, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 517, UINT16_MAX, 517, UINT16_MAX, 1573, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 518, UINT16_MAX, 518, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8177, UINT16_MAX, 8177, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 519, UINT16_MAX, 519, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8178, UINT16_MAX, 8178, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8179, UINT16_MAX, 8179, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8712, 522, UINT16_MAX, 522, 8180, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8715, 522, 8181, 522, 8180, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8717, UINT16_MAX, 8181, UINT16_MAX, 8180, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8719, 529, UINT16_MAX, 529, 8182, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8722, 529, 8183, 529, 8182, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8724, UINT16_MAX, 8183, UINT16_MAX, 8182, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8726, 536, UINT16_MAX, 536, 8184, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8729, 536, 8185, 536, 8184, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8731, UINT16_MAX, 8185, UINT16_MAX, 8184, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8733, 543, UINT16_MAX, 543, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8736, UINT16_MAX, 8186, UINT16_MAX, 8186, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8738, 548, UINT16_MAX, 548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8741, UINT16_MAX, 8187, UINT16_MAX, 8187, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8743, 553, UINT16_MAX, 553, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8746, UINT16_MAX, 8188, UINT16_MAX, 8188, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8748, 558, UINT16_MAX, 558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8751, UINT16_MAX, 8189, UINT16_MAX, 8189, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8753, 563, UINT16_MAX, 563, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8756, UINT16_MAX, 8190, UINT16_MAX, 8190, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8758, 568, UINT16_MAX, 568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8761, UINT16_MAX, 8191, UINT16_MAX, 8191, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8763, 573, UINT16_MAX, 573, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8766, UINT16_MAX, 8192, UINT16_MAX, 8192, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8768, 578, UINT16_MAX, 578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8771, UINT16_MAX, 8193, UINT16_MAX, 8193, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1496, UINT16_MAX, 1496, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8773, 583, UINT16_MAX, 583, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8776, UINT16_MAX, 8194, UINT16_MAX, 8194, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8778, 588, UINT16_MAX, 588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8781, UINT16_MAX, 8195, UINT16_MAX, 8195, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8783, 593, UINT16_MAX, 593, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8786, UINT16_MAX, 8196, UINT16_MAX, 8196, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 596, UINT16_MAX, 596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8197, UINT16_MAX, 8197, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8789, 599, UINT16_MAX, 599, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8792, UINT16_MAX, 8198, UINT16_MAX, 8198, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8794, 604, UINT16_MAX, 604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8797, UINT16_MAX, 8199, UINT16_MAX, 8199, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8799, 609, UINT16_MAX, 609, UINT16_MAX, 1567, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8802, UINT16_MAX, 8200, UINT16_MAX, 8200, 1570, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8804, 614, UINT16_MAX, 614, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8807, UINT16_MAX, 8201, UINT16_MAX, 8201, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8809, 619, UINT16_MAX, 619, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8812, UINT16_MAX, 8202, UINT16_MAX, 8202, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8814, 8814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8816, 626, UINT16_MAX, 626, 8203, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8819, 626, 8204, 626, 8203, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8821, UINT16_MAX, 8204, UINT16_MAX, 8203, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8823, 633, UINT16_MAX, 633, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8826, UINT16_MAX, 8205, UINT16_MAX, 8205, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 636, UINT16_MAX, 636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 637, UINT16_MAX, 637, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8830, 640, UINT16_MAX, 640, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8833, UINT16_MAX, 8206, UINT16_MAX, 8206, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8835, 645, UINT16_MAX, 645, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8838, UINT16_MAX, 8207, UINT16_MAX, 8207, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8840, 650, UINT16_MAX, 650, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8843, UINT16_MAX, 8208, UINT16_MAX, 8208, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8845, 655, UINT16_MAX, 655, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8848, UINT16_MAX, 8209, UINT16_MAX, 8209, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8850, 660, UINT16_MAX, 660, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8853, UINT16_MAX, 8210, UINT16_MAX, 8210, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8855, 665, UINT16_MAX, 665, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8858, UINT16_MAX, 8211, UINT16_MAX, 8211, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8860, 670, UINT16_MAX, 670, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8863, UINT16_MAX, 8212, UINT16_MAX, 8212, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8865, 675, UINT16_MAX, 675, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8868, UINT16_MAX, 8213, UINT16_MAX, 8213, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8870, 680, UINT16_MAX, 680, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8873, UINT16_MAX, 8214, UINT16_MAX, 8214, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8875, 685, UINT16_MAX, 685, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8878, UINT16_MAX, 8215, UINT16_MAX, 8215, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8880, 690, UINT16_MAX, 690, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8883, UINT16_MAX, 8216, UINT16_MAX, 8216, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8885, 695, UINT16_MAX, 695, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8888, UINT16_MAX, 8217, UINT16_MAX, 8217, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8890, 700, UINT16_MAX, 700, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8893, UINT16_MAX, 8218, UINT16_MAX, 8218, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8895, 705, UINT16_MAX, 705, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8898, UINT16_MAX, 8219, UINT16_MAX, 8219, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8900, 710, UINT16_MAX, 710, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8903, UINT16_MAX, 8220, UINT16_MAX, 8220, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8905, 715, UINT16_MAX, 715, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8908, UINT16_MAX, 8221, UINT16_MAX, 8221, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8910, 720, UINT16_MAX, 720, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8913, UINT16_MAX, 8222, UINT16_MAX, 8222, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8915, 725, UINT16_MAX, 725, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8918, UINT16_MAX, 8223, UINT16_MAX, 8223, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 728, UINT16_MAX, 728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8224, UINT16_MAX, 8224, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8921, 731, UINT16_MAX, 731, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8924, UINT16_MAX, 8225, UINT16_MAX, 8225, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 734, UINT16_MAX, 734, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 735, UINT16_MAX, 735, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1506, UINT16_MAX, 1506, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 736, UINT16_MAX, 736, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8226, UINT16_MAX, 8226, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8929, 739, UINT16_MAX, 739, UINT16_MAX, 1543, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8932, UINT16_MAX, 8227, UINT16_MAX, 8227, 1546, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8934, 744, UINT16_MAX, 744, UINT16_MAX, 2866, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8937, UINT16_MAX, 8228, UINT16_MAX, 8228, 2869, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8939, 749, UINT16_MAX, 749, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8942, UINT16_MAX, 8229, UINT16_MAX, 8229, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8944, 754, UINT16_MAX, 754, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8947, UINT16_MAX, 8230, UINT16_MAX, 8230, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8949, 759, UINT16_MAX, 759, UINT16_MAX, 1615, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8952, UINT16_MAX, 8231, UINT16_MAX, 8231, 1618, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8954, 764, UINT16_MAX, 764, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8957, UINT16_MAX, 8232, UINT16_MAX, 8232, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8959, 769, UINT16_MAX, 769, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8962, UINT16_MAX, 8233, UINT16_MAX, 8233, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 772, UINT16_MAX, 772, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 773, UINT16_MAX, 773, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8234, UINT16_MAX, 8234, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 774, UINT16_MAX, 774, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 775, UINT16_MAX, 775, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8235, UINT16_MAX, 8235, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8236, UINT16_MAX, 8236, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 776, UINT16_MAX, 776, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8237, UINT16_MAX, 8237, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 777, UINT16_MAX, 777, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 778, UINT16_MAX, 778, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 779, UINT16_MAX, 779, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 780, UINT16_MAX, 780, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8238, UINT16_MAX, 8238, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 781, UINT16_MAX, 781, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8239, UINT16_MAX, 8239, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 782, UINT16_MAX, 782, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8240, UINT16_MAX, 8240, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 783, UINT16_MAX, 783, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8241, UINT16_MAX, 8241, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 784, UINT16_MAX, 784, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8242, UINT16_MAX, 8242, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8243, UINT16_MAX, 8243, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8244, UINT16_MAX, 8244, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8245, UINT16_MAX, 8245, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8246, UINT16_MAX, 8246, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8247, UINT16_MAX, 8247, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8248, UINT16_MAX, 8248, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8249, UINT16_MAX, 8249, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8250, UINT16_MAX, 8250, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2821, UINT16_MAX, 2821, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8251, UINT16_MAX, 8251, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8252, UINT16_MAX, 8252, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8253, UINT16_MAX, 8253, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8254, UINT16_MAX, 8254, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8255, UINT16_MAX, 8255, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8256, UINT16_MAX, 8256, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8257, UINT16_MAX, 8257, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8258, UINT16_MAX, 8258, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8259, UINT16_MAX, 8259, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8260, UINT16_MAX, 8260, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8261, UINT16_MAX, 8261, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8262, UINT16_MAX, 8262, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8263, UINT16_MAX, 8263, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8264, UINT16_MAX, 8264, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8265, UINT16_MAX, 8265, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8266, UINT16_MAX, 8266, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8267, UINT16_MAX, 8267, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8268, UINT16_MAX, 8268, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8269, UINT16_MAX, 8269, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8270, UINT16_MAX, 8270, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8271, UINT16_MAX, 8271, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8272, UINT16_MAX, 8272, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8273, UINT16_MAX, 8273, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8274, UINT16_MAX, 8274, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8275, UINT16_MAX, 8275, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8276, UINT16_MAX, 8276, 1576, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8277, UINT16_MAX, 8277, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8278, UINT16_MAX, 8278, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 9, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 17, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 788, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 22, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 24, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8985, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8987, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8989, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8991, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 11, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 18, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 23, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32768, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32769, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32770, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32771, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32775, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32776, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32778, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32772, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32814, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32773, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32780, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32779, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32782, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32783, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32815, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32816, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 232, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32781, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32808, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32813, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32807, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32784, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32774, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32777, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32810, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32812, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32811, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32809, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32819, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32817, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 8997, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 240, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, 807, 7217, UINT16_MAX, 7217, 32818, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 233, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 234, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 808, UINT16_MAX, 808, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8279, UINT16_MAX, 8279, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 809, UINT16_MAX, 809, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8280, UINT16_MAX, 8280, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 811, UINT16_MAX, 811, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8281, UINT16_MAX, 8281, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8282, UINT16_MAX, 8282, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8283, UINT16_MAX, 8283, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8284, UINT16_MAX, 8284, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 815, UINT16_MAX, 815, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 9008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9010, 820, UINT16_MAX, 820, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9014, 824, UINT16_MAX, 824, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9017, 827, UINT16_MAX, 827, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9020, 830, UINT16_MAX, 830, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9023, 833, UINT16_MAX, 833, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9026, 836, UINT16_MAX, 836, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9029, 839, UINT16_MAX, 839, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9032, 17226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 845, UINT16_MAX, 845, UINT16_MAX, 1673, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 846, UINT16_MAX, 846, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 847, UINT16_MAX, 847, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 848, UINT16_MAX, 848, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 849, UINT16_MAX, 849, UINT16_MAX, 1726, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 850, UINT16_MAX, 850, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 851, UINT16_MAX, 851, UINT16_MAX, 1777, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 852, UINT16_MAX, 852, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 807, UINT16_MAX, 807, UINT16_MAX, 1830, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 853, UINT16_MAX, 853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 854, UINT16_MAX, 854, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 35, UINT16_MAX, 35, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 855, UINT16_MAX, 855, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 856, UINT16_MAX, 856, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 857, UINT16_MAX, 857, UINT16_MAX, 1881, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 858, UINT16_MAX, 858, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 859, UINT16_MAX, 859, UINT16_MAX, 5027, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 860, UINT16_MAX, 860, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 861, UINT16_MAX, 861, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 862, UINT16_MAX, 862, UINT16_MAX, 1932, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 863, UINT16_MAX, 863, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 864, UINT16_MAX, 864, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 865, UINT16_MAX, 865, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 866, UINT16_MAX, 866, UINT16_MAX, 1983, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9059, 869, UINT16_MAX, 869, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9062, 872, UINT16_MAX, 872, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9065, UINT16_MAX, 2603, UINT16_MAX, 2603, 4904, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9067, UINT16_MAX, 2635, UINT16_MAX, 2635, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9069, UINT16_MAX, 2640, UINT16_MAX, 2640, 4913, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9071, UINT16_MAX, 2676, UINT16_MAX, 2676, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9073, 17267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7211, UINT16_MAX, 7211, 2088, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7212, UINT16_MAX, 7212, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2846, UINT16_MAX, 2846, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7213, UINT16_MAX, 7213, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7214, UINT16_MAX, 7214, 2141, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7215, UINT16_MAX, 7215, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7216, UINT16_MAX, 7216, 2192, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 915, UINT16_MAX, 915, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7217, UINT16_MAX, 7217, 2245, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7218, UINT16_MAX, 7218, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7219, UINT16_MAX, 7219, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7220, UINT16_MAX, 7220, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7221, UINT16_MAX, 7221, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7222, UINT16_MAX, 7222, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7223, UINT16_MAX, 7223, 2401, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2847, UINT16_MAX, 2847, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7224, UINT16_MAX, 7224, 5023, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 860, 917, UINT16_MAX, 917, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 917, UINT16_MAX, 917, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7226, UINT16_MAX, 7226, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 897, UINT16_MAX, 897, 2349, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7227, UINT16_MAX, 7227, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7228, UINT16_MAX, 7228, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7229, UINT16_MAX, 7229, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2835, UINT16_MAX, 2835, 2452, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9078, UINT16_MAX, 8285, UINT16_MAX, 8285, 2036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9080, UINT16_MAX, 8286, UINT16_MAX, 8286, 2297, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9082, UINT16_MAX, 2745, UINT16_MAX, 2745, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9084, UINT16_MAX, 2714, UINT16_MAX, 2714, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9086, UINT16_MAX, 2750, UINT16_MAX, 2750, 5033, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 896, UINT16_MAX, 896, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 846, 846, 7212, UINT16_MAX, 7212, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 852, 852, 915, UINT16_MAX, 915, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2505, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 863, 863, 7227, UINT16_MAX, 7227, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 858, 858, 2847, UINT16_MAX, 2847, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8287, UINT16_MAX, 8287, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 902, UINT16_MAX, 902, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8288, UINT16_MAX, 8288, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 903, UINT16_MAX, 903, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8289, UINT16_MAX, 8289, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 904, UINT16_MAX, 904, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7238, UINT16_MAX, 7238, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 905, UINT16_MAX, 905, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8290, UINT16_MAX, 8290, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 906, UINT16_MAX, 906, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8291, UINT16_MAX, 8291, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 907, UINT16_MAX, 907, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8292, UINT16_MAX, 8292, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 908, UINT16_MAX, 908, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8293, UINT16_MAX, 8293, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 909, UINT16_MAX, 909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8294, UINT16_MAX, 8294, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 910, UINT16_MAX, 910, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8295, UINT16_MAX, 8295, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 911, UINT16_MAX, 911, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8296, UINT16_MAX, 8296, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 912, UINT16_MAX, 912, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8297, UINT16_MAX, 8297, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 913, UINT16_MAX, 913, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8298, UINT16_MAX, 8298, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 853, 853, 7218, UINT16_MAX, 7218, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 859, 859, 7224, UINT16_MAX, 7224, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 914, UINT16_MAX, 8299, UINT16_MAX, 8299, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8300, UINT16_MAX, 8300, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 915, 852, UINT16_MAX, 852, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 849, 849, 7214, UINT16_MAX, 7214, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 916, UINT16_MAX, 916, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8301, UINT16_MAX, 8301, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 917, 918, UINT16_MAX, 918, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 919, UINT16_MAX, 919, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8302, UINT16_MAX, 8302, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 920, UINT16_MAX, 920, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 921, UINT16_MAX, 921, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 922, UINT16_MAX, 922, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9115, 925, UINT16_MAX, 925, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9118, 928, UINT16_MAX, 928, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 929, UINT16_MAX, 929, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9122, 932, UINT16_MAX, 932, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 933, UINT16_MAX, 933, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 934, UINT16_MAX, 934, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 935, UINT16_MAX, 935, UINT16_MAX, 2525, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9128, 938, UINT16_MAX, 938, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 939, UINT16_MAX, 939, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 940, UINT16_MAX, 940, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 941, UINT16_MAX, 941, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 942, UINT16_MAX, 942, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9135, 945, UINT16_MAX, 945, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9138, 948, UINT16_MAX, 948, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9141, 951, UINT16_MAX, 951, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 952, UINT16_MAX, 952, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 953, UINT16_MAX, 953, UINT16_MAX, 2615, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 954, UINT16_MAX, 954, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 955, UINT16_MAX, 955, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 956, UINT16_MAX, 956, UINT16_MAX, 2522, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 957, UINT16_MAX, 957, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 958, UINT16_MAX, 958, UINT16_MAX, 2511, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 959, UINT16_MAX, 959, UINT16_MAX, 2601, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 960, UINT16_MAX, 960, UINT16_MAX, 2635, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 961, UINT16_MAX, 961, UINT16_MAX, 2531, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9154, 964, UINT16_MAX, 964, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 965, UINT16_MAX, 965, UINT16_MAX, 2528, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 966, UINT16_MAX, 966, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 967, UINT16_MAX, 967, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 968, UINT16_MAX, 968, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 969, UINT16_MAX, 969, UINT16_MAX, 2641, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 970, UINT16_MAX, 970, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 971, UINT16_MAX, 971, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 972, UINT16_MAX, 972, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 973, UINT16_MAX, 973, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 974, UINT16_MAX, 974, UINT16_MAX, 2542, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 975, UINT16_MAX, 975, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 976, UINT16_MAX, 976, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 977, UINT16_MAX, 977, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 978, UINT16_MAX, 978, UINT16_MAX, 2659, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 979, UINT16_MAX, 979, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 980, UINT16_MAX, 980, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 981, UINT16_MAX, 981, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 982, UINT16_MAX, 982, UINT16_MAX, 2665, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 983, UINT16_MAX, 983, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 984, UINT16_MAX, 984, UINT16_MAX, 2653, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 985, UINT16_MAX, 985, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 986, UINT16_MAX, 986, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8303, UINT16_MAX, 8303, 2622, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8304, UINT16_MAX, 8304, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8305, UINT16_MAX, 8305, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8306, UINT16_MAX, 8306, 2575, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8307, UINT16_MAX, 8307, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8308, UINT16_MAX, 8308, 2564, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8309, UINT16_MAX, 8309, 2608, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8310, UINT16_MAX, 8310, 2638, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8311, UINT16_MAX, 8311, 2553, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9179, UINT16_MAX, 8312, UINT16_MAX, 8312, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8313, UINT16_MAX, 8313, 2581, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8314, UINT16_MAX, 8314, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8315, UINT16_MAX, 8315, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8316, UINT16_MAX, 8316, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8317, UINT16_MAX, 8317, 2644, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8318, UINT16_MAX, 8318, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8319, UINT16_MAX, 8319, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8320, UINT16_MAX, 8320, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8321, UINT16_MAX, 8321, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8322, UINT16_MAX, 8322, 2584, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8323, UINT16_MAX, 8323, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8324, UINT16_MAX, 8324, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8325, UINT16_MAX, 8325, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8326, UINT16_MAX, 8326, 2662, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8327, UINT16_MAX, 8327, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8328, UINT16_MAX, 8328, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8329, UINT16_MAX, 8329, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8330, UINT16_MAX, 8330, 2668, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8331, UINT16_MAX, 8331, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8332, UINT16_MAX, 8332, 2656, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8333, UINT16_MAX, 8333, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8334, UINT16_MAX, 8334, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9181, UINT16_MAX, 8335, UINT16_MAX, 8335, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9183, UINT16_MAX, 8336, UINT16_MAX, 8336, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8337, UINT16_MAX, 8337, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9185, UINT16_MAX, 8338, UINT16_MAX, 8338, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8339, UINT16_MAX, 8339, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8340, UINT16_MAX, 8340, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8341, UINT16_MAX, 8341, 2578, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9187, UINT16_MAX, 8342, UINT16_MAX, 8342, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8343, UINT16_MAX, 8343, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8344, UINT16_MAX, 8344, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8345, UINT16_MAX, 8345, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8346, UINT16_MAX, 8346, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9189, UINT16_MAX, 8347, UINT16_MAX, 8347, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9191, UINT16_MAX, 8348, UINT16_MAX, 8348, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9193, UINT16_MAX, 8349, UINT16_MAX, 8349, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8350, UINT16_MAX, 8350, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1003, UINT16_MAX, 1003, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8351, UINT16_MAX, 8351, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1004, UINT16_MAX, 1004, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8352, UINT16_MAX, 8352, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1005, UINT16_MAX, 1005, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8353, UINT16_MAX, 8353, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1006, UINT16_MAX, 1006, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8354, UINT16_MAX, 8354, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1007, UINT16_MAX, 1007, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8355, UINT16_MAX, 8355, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1008, UINT16_MAX, 1008, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8356, UINT16_MAX, 8356, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1009, UINT16_MAX, 1009, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8357, UINT16_MAX, 8357, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1010, UINT16_MAX, 1010, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8358, UINT16_MAX, 8358, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1011, UINT16_MAX, 1011, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8359, UINT16_MAX, 8359, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1012, UINT16_MAX, 1012, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8360, UINT16_MAX, 8360, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1013, UINT16_MAX, 1013, UINT16_MAX, 2595, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8361, UINT16_MAX, 8361, 2598, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9206, 1016, UINT16_MAX, 1016, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9209, UINT16_MAX, 8362, UINT16_MAX, 8362, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1019, UINT16_MAX, 1019, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8363, UINT16_MAX, 8363, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1020, UINT16_MAX, 1020, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8364, UINT16_MAX, 8364, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1021, UINT16_MAX, 1021, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8365, UINT16_MAX, 8365, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1022, UINT16_MAX, 1022, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8366, UINT16_MAX, 8366, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1023, UINT16_MAX, 1023, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8367, UINT16_MAX, 8367, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ME, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1024, UINT16_MAX, 1024, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8368, UINT16_MAX, 8368, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1025, UINT16_MAX, 1025, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8369, UINT16_MAX, 8369, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1026, UINT16_MAX, 1026, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8370, UINT16_MAX, 8370, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1027, UINT16_MAX, 1027, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8371, UINT16_MAX, 8371, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1028, UINT16_MAX, 1028, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8372, UINT16_MAX, 8372, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1029, UINT16_MAX, 1029, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8373, UINT16_MAX, 8373, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1030, UINT16_MAX, 1030, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8374, UINT16_MAX, 8374, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1031, UINT16_MAX, 1031, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8375, UINT16_MAX, 8375, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1032, UINT16_MAX, 1032, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8376, UINT16_MAX, 8376, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1033, UINT16_MAX, 1033, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8377, UINT16_MAX, 8377, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1034, UINT16_MAX, 1034, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8378, UINT16_MAX, 8378, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1035, UINT16_MAX, 1035, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8379, UINT16_MAX, 8379, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1036, UINT16_MAX, 1036, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8380, UINT16_MAX, 8380, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1037, UINT16_MAX, 1037, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8381, UINT16_MAX, 8381, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1038, UINT16_MAX, 1038, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8382, UINT16_MAX, 8382, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1039, UINT16_MAX, 1039, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8383, UINT16_MAX, 8383, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1040, UINT16_MAX, 1040, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8384, UINT16_MAX, 8384, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1041, UINT16_MAX, 1041, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8385, UINT16_MAX, 8385, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1042, UINT16_MAX, 1042, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8386, UINT16_MAX, 8386, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1043, UINT16_MAX, 1043, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8387, UINT16_MAX, 8387, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1044, UINT16_MAX, 1044, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8388, UINT16_MAX, 8388, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1045, UINT16_MAX, 1045, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8389, UINT16_MAX, 8389, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1046, UINT16_MAX, 1046, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8390, UINT16_MAX, 8390, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1047, UINT16_MAX, 1047, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8391, UINT16_MAX, 8391, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1048, UINT16_MAX, 1048, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8392, UINT16_MAX, 8392, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1049, UINT16_MAX, 1049, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8393, UINT16_MAX, 8393, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1050, UINT16_MAX, 1050, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8394, UINT16_MAX, 8394, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1051, UINT16_MAX, 1051, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9244, 1054, UINT16_MAX, 1054, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9247, UINT16_MAX, 8395, UINT16_MAX, 8395, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1057, UINT16_MAX, 1057, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8396, UINT16_MAX, 8396, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1058, UINT16_MAX, 1058, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8397, UINT16_MAX, 8397, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1059, UINT16_MAX, 1059, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8398, UINT16_MAX, 8398, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1060, UINT16_MAX, 1060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8399, UINT16_MAX, 8399, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1061, UINT16_MAX, 1061, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8400, UINT16_MAX, 8400, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1062, UINT16_MAX, 1062, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8401, UINT16_MAX, 8401, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8402, UINT16_MAX, 8402, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9255, 1065, UINT16_MAX, 1065, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9258, UINT16_MAX, 8403, UINT16_MAX, 8403, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9260, 1070, UINT16_MAX, 1070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9263, UINT16_MAX, 8404, UINT16_MAX, 8404, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1073, UINT16_MAX, 1073, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8405, UINT16_MAX, 8405, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9266, 1076, UINT16_MAX, 1076, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9269, UINT16_MAX, 8406, UINT16_MAX, 8406, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1079, UINT16_MAX, 1079, UINT16_MAX, 2629, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8407, UINT16_MAX, 8407, 2632, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9272, 1082, UINT16_MAX, 1082, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9275, UINT16_MAX, 8408, UINT16_MAX, 8408, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9277, 1087, UINT16_MAX, 1087, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9280, UINT16_MAX, 8409, UINT16_MAX, 8409, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9282, 1092, UINT16_MAX, 1092, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9285, UINT16_MAX, 8410, UINT16_MAX, 8410, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1095, UINT16_MAX, 1095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8411, UINT16_MAX, 8411, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9288, 1098, UINT16_MAX, 1098, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9291, UINT16_MAX, 8412, UINT16_MAX, 8412, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9293, 1103, UINT16_MAX, 1103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9296, UINT16_MAX, 8413, UINT16_MAX, 8413, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9298, 1108, UINT16_MAX, 1108, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9301, UINT16_MAX, 8414, UINT16_MAX, 8414, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1111, UINT16_MAX, 1111, UINT16_MAX, 2647, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8415, UINT16_MAX, 8415, 2650, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9304, 1114, UINT16_MAX, 1114, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9307, UINT16_MAX, 8416, UINT16_MAX, 8416, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9309, 1119, UINT16_MAX, 1119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9312, UINT16_MAX, 8417, UINT16_MAX, 8417, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9314, 1124, UINT16_MAX, 1124, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9317, UINT16_MAX, 8418, UINT16_MAX, 8418, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9319, 1129, UINT16_MAX, 1129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9322, UINT16_MAX, 8419, UINT16_MAX, 8419, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9324, 1134, UINT16_MAX, 1134, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9327, UINT16_MAX, 8420, UINT16_MAX, 8420, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9329, 1139, UINT16_MAX, 1139, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9332, UINT16_MAX, 8421, UINT16_MAX, 8421, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1142, UINT16_MAX, 1142, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8422, UINT16_MAX, 8422, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9335, 1145, UINT16_MAX, 1145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9338, UINT16_MAX, 8423, UINT16_MAX, 8423, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1148, UINT16_MAX, 1148, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8424, UINT16_MAX, 8424, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1149, UINT16_MAX, 1149, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8425, UINT16_MAX, 8425, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1150, UINT16_MAX, 1150, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8426, UINT16_MAX, 8426, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1151, UINT16_MAX, 1151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8427, UINT16_MAX, 8427, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1152, UINT16_MAX, 1152, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8428, UINT16_MAX, 8428, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1153, UINT16_MAX, 1153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8429, UINT16_MAX, 8429, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1154, UINT16_MAX, 1154, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8430, UINT16_MAX, 8430, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1155, UINT16_MAX, 1155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8431, UINT16_MAX, 8431, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1156, UINT16_MAX, 1156, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8432, UINT16_MAX, 8432, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1157, UINT16_MAX, 1157, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8433, UINT16_MAX, 8433, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1158, UINT16_MAX, 1158, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8434, UINT16_MAX, 8434, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1159, UINT16_MAX, 1159, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8435, UINT16_MAX, 8435, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1160, UINT16_MAX, 1160, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8436, UINT16_MAX, 8436, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1161, UINT16_MAX, 1161, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8437, UINT16_MAX, 8437, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1162, UINT16_MAX, 1162, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8438, UINT16_MAX, 8438, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1163, UINT16_MAX, 1163, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8439, UINT16_MAX, 8439, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1164, UINT16_MAX, 1164, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8440, UINT16_MAX, 8440, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1165, UINT16_MAX, 1165, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8441, UINT16_MAX, 8441, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1166, UINT16_MAX, 1166, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8442, UINT16_MAX, 8442, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1167, UINT16_MAX, 1167, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8443, UINT16_MAX, 8443, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1168, UINT16_MAX, 1168, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8444, UINT16_MAX, 8444, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1169, UINT16_MAX, 1169, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8445, UINT16_MAX, 8445, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1170, UINT16_MAX, 1170, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8446, UINT16_MAX, 8446, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1171, UINT16_MAX, 1171, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8447, UINT16_MAX, 8447, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1172, UINT16_MAX, 1172, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8448, UINT16_MAX, 8448, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1173, UINT16_MAX, 1173, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8449, UINT16_MAX, 8449, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1174, UINT16_MAX, 1174, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8450, UINT16_MAX, 8450, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1175, UINT16_MAX, 1175, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1176, UINT16_MAX, 1176, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1177, UINT16_MAX, 1177, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1178, UINT16_MAX, 1178, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1179, UINT16_MAX, 1179, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1180, UINT16_MAX, 1180, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1181, UINT16_MAX, 1181, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1182, UINT16_MAX, 1182, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1183, UINT16_MAX, 1183, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1184, UINT16_MAX, 1184, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1185, UINT16_MAX, 1185, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1186, UINT16_MAX, 1186, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1187, UINT16_MAX, 1187, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1188, UINT16_MAX, 1188, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1189, UINT16_MAX, 1189, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1190, UINT16_MAX, 1190, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1191, UINT16_MAX, 1191, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1192, UINT16_MAX, 1192, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1193, UINT16_MAX, 1193, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1194, UINT16_MAX, 1194, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1195, UINT16_MAX, 1195, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1196, UINT16_MAX, 1196, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1197, UINT16_MAX, 1197, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1198, UINT16_MAX, 1198, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1199, UINT16_MAX, 1199, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1200, UINT16_MAX, 1200, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1201, UINT16_MAX, 1201, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1202, UINT16_MAX, 1202, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1203, UINT16_MAX, 1203, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1204, UINT16_MAX, 1204, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1205, UINT16_MAX, 1205, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1206, UINT16_MAX, 1206, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1207, UINT16_MAX, 1207, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1208, UINT16_MAX, 1208, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1209, UINT16_MAX, 1209, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1210, UINT16_MAX, 1210, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1211, UINT16_MAX, 1211, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1212, UINT16_MAX, 1212, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8451, UINT16_MAX, 8451, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8452, UINT16_MAX, 8452, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8453, UINT16_MAX, 8453, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8454, UINT16_MAX, 8454, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8455, UINT16_MAX, 8455, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8456, UINT16_MAX, 8456, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8457, UINT16_MAX, 8457, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8458, UINT16_MAX, 8458, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8459, UINT16_MAX, 8459, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8460, UINT16_MAX, 8460, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8461, UINT16_MAX, 8461, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8462, UINT16_MAX, 8462, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8463, UINT16_MAX, 8463, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8464, UINT16_MAX, 8464, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8465, UINT16_MAX, 8465, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8466, UINT16_MAX, 8466, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8467, UINT16_MAX, 8467, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8468, UINT16_MAX, 8468, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8469, UINT16_MAX, 8469, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8470, UINT16_MAX, 8470, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8471, UINT16_MAX, 8471, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8472, UINT16_MAX, 8472, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8473, UINT16_MAX, 8473, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8474, UINT16_MAX, 8474, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8475, UINT16_MAX, 8475, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8476, UINT16_MAX, 8476, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8477, UINT16_MAX, 8477, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8478, UINT16_MAX, 8478, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8479, UINT16_MAX, 8479, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8480, UINT16_MAX, 8480, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8481, UINT16_MAX, 8481, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8482, UINT16_MAX, 8482, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8483, UINT16_MAX, 8483, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8484, UINT16_MAX, 8484, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8485, UINT16_MAX, 8485, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8486, UINT16_MAX, 8486, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8487, UINT16_MAX, 8487, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8488, UINT16_MAX, 8488, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9405, 9405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 222, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 228, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 10, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 11, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 12, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 13, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 14, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 15, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 16, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 17, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 18, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 19, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 20, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 21, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 22, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 23, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 24, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 25, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 30, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 31, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 32, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2671, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2676, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2679, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 27, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 28, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 29, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 33, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 34, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32785, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32786, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32787, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 35, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 9417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 9419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 9421, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 9423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2685, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2688, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2682, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND}, - {UTF8PROC_CATEGORY_MN, 36, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2691, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2694, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2697, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32788, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32789, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2700, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32790, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32792, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2704, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32791, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32793, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2709, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32795, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2712, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2716, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32794, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2719, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 84, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 91, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32796, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2722, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32799, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2725, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2730, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32797, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32798, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32800, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2733, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2737, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_PREPEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32801, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32802, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32803, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2740, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2745, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32804, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MN, 103, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 107, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MN, 118, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 122, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NOBREAK, 1335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 129, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 130, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 132, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, 9546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, 9550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2748, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32805, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1376, UINT16_MAX, 1376, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1377, UINT16_MAX, 1377, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1378, UINT16_MAX, 1378, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1379, UINT16_MAX, 1379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1380, UINT16_MAX, 1380, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1381, UINT16_MAX, 1381, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1382, UINT16_MAX, 1382, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1383, UINT16_MAX, 1383, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1384, UINT16_MAX, 1384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1385, UINT16_MAX, 1385, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1386, UINT16_MAX, 1386, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1387, UINT16_MAX, 1387, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1388, UINT16_MAX, 1388, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1389, UINT16_MAX, 1389, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1390, UINT16_MAX, 1390, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1391, UINT16_MAX, 1391, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1392, UINT16_MAX, 1392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1393, UINT16_MAX, 1393, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1394, UINT16_MAX, 1394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1395, UINT16_MAX, 1395, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1396, UINT16_MAX, 1396, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1397, UINT16_MAX, 1397, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1398, UINT16_MAX, 1398, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1399, UINT16_MAX, 1399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1400, UINT16_MAX, 1400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1401, UINT16_MAX, 1401, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1402, UINT16_MAX, 1402, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1403, UINT16_MAX, 1403, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1404, UINT16_MAX, 1404, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1405, UINT16_MAX, 1405, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1406, UINT16_MAX, 1406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1407, UINT16_MAX, 1407, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1408, UINT16_MAX, 1408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1409, UINT16_MAX, 1409, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1410, UINT16_MAX, 1410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1411, UINT16_MAX, 1411, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1412, UINT16_MAX, 1412, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1413, UINT16_MAX, 1413, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1414, UINT16_MAX, 1414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1415, UINT16_MAX, 1415, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8489, UINT16_MAX, 1446, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8490, UINT16_MAX, 1447, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8491, UINT16_MAX, 1448, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8492, UINT16_MAX, 1449, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8493, UINT16_MAX, 1450, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8494, UINT16_MAX, 1451, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8495, UINT16_MAX, 1452, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8496, UINT16_MAX, 1453, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8497, UINT16_MAX, 1454, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8498, UINT16_MAX, 1455, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8499, UINT16_MAX, 1456, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8500, UINT16_MAX, 1457, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8501, UINT16_MAX, 1416, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8502, UINT16_MAX, 1458, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8503, UINT16_MAX, 1459, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8504, UINT16_MAX, 1460, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8505, UINT16_MAX, 1461, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8506, UINT16_MAX, 1462, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8507, UINT16_MAX, 1463, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8508, UINT16_MAX, 1464, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8509, UINT16_MAX, 1465, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8510, UINT16_MAX, 1466, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8511, UINT16_MAX, 1467, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8512, UINT16_MAX, 1468, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8513, UINT16_MAX, 1469, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8514, UINT16_MAX, 1470, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8515, UINT16_MAX, 1471, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8516, UINT16_MAX, 1472, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8517, UINT16_MAX, 1473, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8518, UINT16_MAX, 1474, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8519, UINT16_MAX, 1475, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8520, UINT16_MAX, 1476, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8521, UINT16_MAX, 1477, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8522, UINT16_MAX, 1478, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8523, UINT16_MAX, 1479, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8524, UINT16_MAX, 1480, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8525, UINT16_MAX, 1481, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8526, UINT16_MAX, 1482, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8527, UINT16_MAX, 1483, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8528, UINT16_MAX, 1484, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8529, UINT16_MAX, 1485, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8530, UINT16_MAX, 1486, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8531, UINT16_MAX, 1487, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8532, UINT16_MAX, 1488, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8533, UINT16_MAX, 1489, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8534, UINT16_MAX, 1490, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_L}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 2, 0, UTF8PROC_BOUNDCLASS_L}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 1, 0, UTF8PROC_BOUNDCLASS_V}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_V}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_T}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8535, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8536, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8537, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8538, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8539, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8540, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8541, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8542, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8543, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8544, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8545, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8546, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8547, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8549, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8550, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8551, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8552, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8553, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8554, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8555, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8556, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8557, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8559, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8560, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8561, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8562, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8563, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8564, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8565, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8566, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8567, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8569, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8570, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8571, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8572, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8573, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8574, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8575, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8576, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8577, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8579, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8580, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8581, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8582, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8583, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8584, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8585, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8586, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8587, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8589, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8590, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8591, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8592, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8593, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8594, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8595, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8597, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8598, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8599, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8600, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8601, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8602, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8603, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8605, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8606, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8607, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8609, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8610, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8611, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8612, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8613, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8614, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8615, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8616, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8617, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8618, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8619, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8620, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1417, 1417, UINT16_MAX, 1417, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1418, 1418, UINT16_MAX, 1418, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1419, 1419, UINT16_MAX, 1419, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1420, 1420, UINT16_MAX, 1420, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1421, 1421, UINT16_MAX, 1421, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1422, 1422, UINT16_MAX, 1422, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2751, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2754, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2757, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2760, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2763, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2766, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32806, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2769, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2772, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2775, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2778, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2781, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 9, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 955, 8305, UINT16_MAX, 8305, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 957, 8307, UINT16_MAX, 8307, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 969, 8317, UINT16_MAX, 8317, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 972, 8320, UINT16_MAX, 8320, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 973, 8321, UINT16_MAX, 8321, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 981, 8329, UINT16_MAX, 8329, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1004, 8352, UINT16_MAX, 8352, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1445, 8621, UINT16_MAX, 8621, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1446, UINT16_MAX, 1446, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1447, UINT16_MAX, 1447, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1448, UINT16_MAX, 1448, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1449, UINT16_MAX, 1449, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1450, UINT16_MAX, 1450, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1451, UINT16_MAX, 1451, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1452, UINT16_MAX, 1452, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1453, UINT16_MAX, 1453, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1454, UINT16_MAX, 1454, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1455, UINT16_MAX, 1455, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1456, UINT16_MAX, 1456, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1457, UINT16_MAX, 1457, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1416, UINT16_MAX, 1416, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1458, UINT16_MAX, 1458, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1459, UINT16_MAX, 1459, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1460, UINT16_MAX, 1460, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1461, UINT16_MAX, 1461, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1462, UINT16_MAX, 1462, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1463, UINT16_MAX, 1463, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1464, UINT16_MAX, 1464, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1465, UINT16_MAX, 1465, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1466, UINT16_MAX, 1466, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1467, UINT16_MAX, 1467, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1468, UINT16_MAX, 1468, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1469, UINT16_MAX, 1469, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1470, UINT16_MAX, 1470, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1471, UINT16_MAX, 1471, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1472, UINT16_MAX, 1472, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1473, UINT16_MAX, 1473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1474, UINT16_MAX, 1474, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1475, UINT16_MAX, 1475, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1476, UINT16_MAX, 1476, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1477, UINT16_MAX, 1477, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1478, UINT16_MAX, 1478, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1479, UINT16_MAX, 1479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1480, UINT16_MAX, 1480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1481, UINT16_MAX, 1481, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1482, UINT16_MAX, 1482, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1483, UINT16_MAX, 1483, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1484, UINT16_MAX, 1484, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1485, UINT16_MAX, 1485, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1486, UINT16_MAX, 1486, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1487, UINT16_MAX, 1487, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1488, UINT16_MAX, 1488, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1489, UINT16_MAX, 1489, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1490, UINT16_MAX, 1490, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 10, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 12, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 14, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 15, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 19, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 20, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 21, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 8, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 17, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 20, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 21, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 968, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8622, UINT16_MAX, 8622, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8623, UINT16_MAX, 8623, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8624, UINT16_MAX, 8624, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 94, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 25, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 214, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9733, 1543, UINT16_MAX, 1543, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9736, UINT16_MAX, 8625, UINT16_MAX, 8625, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9738, 1548, UINT16_MAX, 1548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9741, UINT16_MAX, 8626, UINT16_MAX, 8626, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9743, 1553, UINT16_MAX, 1553, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9746, UINT16_MAX, 8627, UINT16_MAX, 8627, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9748, 1558, UINT16_MAX, 1558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9751, UINT16_MAX, 8628, UINT16_MAX, 8628, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9753, 1563, UINT16_MAX, 1563, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9756, UINT16_MAX, 8629, UINT16_MAX, 8629, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9758, 1568, UINT16_MAX, 1568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9761, UINT16_MAX, 8630, UINT16_MAX, 8630, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9763, 1573, UINT16_MAX, 1573, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9766, UINT16_MAX, 8631, UINT16_MAX, 8631, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9768, 1578, UINT16_MAX, 1578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9771, UINT16_MAX, 8632, UINT16_MAX, 8632, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9773, 1583, UINT16_MAX, 1583, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9776, UINT16_MAX, 8633, UINT16_MAX, 8633, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9778, 1588, UINT16_MAX, 1588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9781, UINT16_MAX, 8634, UINT16_MAX, 8634, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9783, 1593, UINT16_MAX, 1593, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9786, UINT16_MAX, 8635, UINT16_MAX, 8635, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9788, 1598, UINT16_MAX, 1598, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9791, UINT16_MAX, 8636, UINT16_MAX, 8636, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9793, 1603, UINT16_MAX, 1603, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9796, UINT16_MAX, 8637, UINT16_MAX, 8637, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9798, 1608, UINT16_MAX, 1608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9801, UINT16_MAX, 8638, UINT16_MAX, 8638, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9803, 1613, UINT16_MAX, 1613, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9806, UINT16_MAX, 8639, UINT16_MAX, 8639, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9808, 1618, UINT16_MAX, 1618, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9811, UINT16_MAX, 8640, UINT16_MAX, 8640, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9813, 1623, UINT16_MAX, 1623, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9816, UINT16_MAX, 8641, UINT16_MAX, 8641, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9818, 1628, UINT16_MAX, 1628, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9821, UINT16_MAX, 8642, UINT16_MAX, 8642, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9823, 1633, UINT16_MAX, 1633, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9826, UINT16_MAX, 8643, UINT16_MAX, 8643, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9828, 1638, UINT16_MAX, 1638, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9831, UINT16_MAX, 8644, UINT16_MAX, 8644, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9833, 1643, UINT16_MAX, 1643, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9836, UINT16_MAX, 8645, UINT16_MAX, 8645, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9838, 1648, UINT16_MAX, 1648, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9841, UINT16_MAX, 8646, UINT16_MAX, 8646, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9843, 1653, UINT16_MAX, 1653, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9846, UINT16_MAX, 8647, UINT16_MAX, 8647, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9848, 1658, UINT16_MAX, 1658, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9851, UINT16_MAX, 8648, UINT16_MAX, 8648, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9853, 1663, UINT16_MAX, 1663, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9856, UINT16_MAX, 8649, UINT16_MAX, 8649, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9858, 1668, UINT16_MAX, 1668, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9861, UINT16_MAX, 8650, UINT16_MAX, 8650, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9863, 1673, UINT16_MAX, 1673, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9866, UINT16_MAX, 8651, UINT16_MAX, 8651, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9868, 1678, UINT16_MAX, 1678, UINT16_MAX, 2884, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9871, UINT16_MAX, 8652, UINT16_MAX, 8652, 2887, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9873, 1683, UINT16_MAX, 1683, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9876, UINT16_MAX, 8653, UINT16_MAX, 8653, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9878, 1688, UINT16_MAX, 1688, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9881, UINT16_MAX, 8654, UINT16_MAX, 8654, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9883, 1693, UINT16_MAX, 1693, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9886, UINT16_MAX, 8655, UINT16_MAX, 8655, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9888, 1698, UINT16_MAX, 1698, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9891, UINT16_MAX, 8656, UINT16_MAX, 8656, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9893, 1703, UINT16_MAX, 1703, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9896, UINT16_MAX, 8657, UINT16_MAX, 8657, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9898, 1708, UINT16_MAX, 1708, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9901, UINT16_MAX, 8658, UINT16_MAX, 8658, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9903, 1713, UINT16_MAX, 1713, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9906, UINT16_MAX, 8659, UINT16_MAX, 8659, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9908, 1718, UINT16_MAX, 1718, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9911, UINT16_MAX, 8660, UINT16_MAX, 8660, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9913, 1723, UINT16_MAX, 1723, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9916, UINT16_MAX, 8661, UINT16_MAX, 8661, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9918, 1728, UINT16_MAX, 1728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9921, UINT16_MAX, 8662, UINT16_MAX, 8662, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9923, 1733, UINT16_MAX, 1733, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9926, UINT16_MAX, 8663, UINT16_MAX, 8663, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9928, 1738, UINT16_MAX, 1738, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9931, UINT16_MAX, 8664, UINT16_MAX, 8664, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9933, 1743, UINT16_MAX, 1743, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9936, UINT16_MAX, 8665, UINT16_MAX, 8665, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9938, 1748, UINT16_MAX, 1748, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9941, UINT16_MAX, 8666, UINT16_MAX, 8666, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9943, 1753, UINT16_MAX, 1753, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9946, UINT16_MAX, 8667, UINT16_MAX, 8667, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9948, 1758, UINT16_MAX, 1758, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9951, UINT16_MAX, 8668, UINT16_MAX, 8668, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9953, 1763, UINT16_MAX, 1763, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9956, UINT16_MAX, 8669, UINT16_MAX, 8669, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9958, 1768, UINT16_MAX, 1768, UINT16_MAX, 3006, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9961, UINT16_MAX, 8670, UINT16_MAX, 8670, 3009, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9963, 1773, UINT16_MAX, 1773, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9966, UINT16_MAX, 8671, UINT16_MAX, 8671, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9968, 1778, UINT16_MAX, 1778, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9971, UINT16_MAX, 8672, UINT16_MAX, 8672, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9973, 1783, UINT16_MAX, 1783, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9976, UINT16_MAX, 8673, UINT16_MAX, 8673, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9978, 1788, UINT16_MAX, 1788, UINT16_MAX, 3024, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9981, UINT16_MAX, 8674, UINT16_MAX, 8674, 3027, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9983, 1793, UINT16_MAX, 1793, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9986, UINT16_MAX, 8675, UINT16_MAX, 8675, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9988, 1798, UINT16_MAX, 1798, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9991, UINT16_MAX, 8676, UINT16_MAX, 8676, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9993, 1803, UINT16_MAX, 1803, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9996, UINT16_MAX, 8677, UINT16_MAX, 8677, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9998, 1808, UINT16_MAX, 1808, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10001, UINT16_MAX, 8678, UINT16_MAX, 8678, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10003, 1813, UINT16_MAX, 1813, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10006, UINT16_MAX, 8679, UINT16_MAX, 8679, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10008, 1818, UINT16_MAX, 1818, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10011, UINT16_MAX, 8680, UINT16_MAX, 8680, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10013, 1823, UINT16_MAX, 1823, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10016, UINT16_MAX, 8681, UINT16_MAX, 8681, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10018, 1828, UINT16_MAX, 1828, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10021, UINT16_MAX, 8682, UINT16_MAX, 8682, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10023, 1833, UINT16_MAX, 1833, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10026, UINT16_MAX, 8683, UINT16_MAX, 8683, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10028, 1838, UINT16_MAX, 1838, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10031, UINT16_MAX, 8684, UINT16_MAX, 8684, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10033, 1843, UINT16_MAX, 1843, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10036, UINT16_MAX, 8685, UINT16_MAX, 8685, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10038, 1848, UINT16_MAX, 1848, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10041, UINT16_MAX, 8686, UINT16_MAX, 8686, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10043, 1853, UINT16_MAX, 1853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10046, UINT16_MAX, 8687, UINT16_MAX, 8687, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10048, 1858, UINT16_MAX, 1858, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10051, UINT16_MAX, 8688, UINT16_MAX, 8688, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10053, 1863, UINT16_MAX, 1863, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10056, UINT16_MAX, 8689, UINT16_MAX, 8689, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10058, 1868, UINT16_MAX, 1868, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10061, UINT16_MAX, 8690, UINT16_MAX, 8690, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10063, 1873, UINT16_MAX, 1873, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10066, UINT16_MAX, 8691, UINT16_MAX, 8691, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10068, 1878, UINT16_MAX, 1878, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10071, UINT16_MAX, 8692, UINT16_MAX, 8692, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10073, 1883, UINT16_MAX, 1883, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10076, UINT16_MAX, 8693, UINT16_MAX, 8693, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10078, 1888, UINT16_MAX, 1888, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10081, UINT16_MAX, 8694, UINT16_MAX, 8694, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10083, 1893, UINT16_MAX, 1893, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10086, UINT16_MAX, 8695, UINT16_MAX, 8695, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10088, 1898, UINT16_MAX, 1898, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10091, UINT16_MAX, 8696, UINT16_MAX, 8696, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10093, 1903, UINT16_MAX, 1903, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10096, UINT16_MAX, 8697, UINT16_MAX, 8697, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10098, 1908, UINT16_MAX, 1908, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10101, UINT16_MAX, 8698, UINT16_MAX, 8698, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10103, 1913, UINT16_MAX, 1913, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10106, UINT16_MAX, 8699, UINT16_MAX, 8699, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10108, 10108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10110, 10110, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10112, 10112, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10114, 10114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 10116, 10116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10118, 1783, 8673, UINT16_MAX, 8673, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8322, UINT16_MAX, 8700, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10120, 1930, UINT16_MAX, 1930, UINT16_MAX, 3241, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10123, UINT16_MAX, 8701, UINT16_MAX, 8701, 3250, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10125, 1935, UINT16_MAX, 1935, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10128, UINT16_MAX, 8702, UINT16_MAX, 8702, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10130, 1940, UINT16_MAX, 1940, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10133, UINT16_MAX, 8703, UINT16_MAX, 8703, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10135, 1945, UINT16_MAX, 1945, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10138, UINT16_MAX, 8704, UINT16_MAX, 8704, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10140, 1950, UINT16_MAX, 1950, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10143, UINT16_MAX, 8705, UINT16_MAX, 8705, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10145, 1955, UINT16_MAX, 1955, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10148, UINT16_MAX, 8706, UINT16_MAX, 8706, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10150, 1960, UINT16_MAX, 1960, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10153, UINT16_MAX, 8707, UINT16_MAX, 8707, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10155, 1965, UINT16_MAX, 1965, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10158, UINT16_MAX, 8708, UINT16_MAX, 8708, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10160, 1970, UINT16_MAX, 1970, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10163, UINT16_MAX, 8709, UINT16_MAX, 8709, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10165, 1975, UINT16_MAX, 1975, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10168, UINT16_MAX, 8710, UINT16_MAX, 8710, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10170, 1980, UINT16_MAX, 1980, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10173, UINT16_MAX, 8711, UINT16_MAX, 8711, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10175, 1985, UINT16_MAX, 1985, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10178, UINT16_MAX, 8712, UINT16_MAX, 8712, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10180, 1990, UINT16_MAX, 1990, UINT16_MAX, 3455, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10183, UINT16_MAX, 8713, UINT16_MAX, 8713, 3458, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10185, 1995, UINT16_MAX, 1995, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10188, UINT16_MAX, 8714, UINT16_MAX, 8714, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10190, 2000, UINT16_MAX, 2000, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10193, UINT16_MAX, 8715, UINT16_MAX, 8715, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10195, 2005, UINT16_MAX, 2005, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10198, UINT16_MAX, 8716, UINT16_MAX, 8716, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10200, 2010, UINT16_MAX, 2010, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10203, UINT16_MAX, 8717, UINT16_MAX, 8717, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10205, 2015, UINT16_MAX, 2015, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10208, UINT16_MAX, 8718, UINT16_MAX, 8718, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10210, 2020, UINT16_MAX, 2020, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10213, UINT16_MAX, 8719, UINT16_MAX, 8719, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10215, 2025, UINT16_MAX, 2025, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10218, UINT16_MAX, 8720, UINT16_MAX, 8720, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10220, 2030, UINT16_MAX, 2030, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10223, UINT16_MAX, 8721, UINT16_MAX, 8721, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10225, 2035, UINT16_MAX, 2035, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10228, UINT16_MAX, 8722, UINT16_MAX, 8722, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10230, 2040, UINT16_MAX, 2040, UINT16_MAX, 3559, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10233, UINT16_MAX, 8723, UINT16_MAX, 8723, 3562, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10235, 2045, UINT16_MAX, 2045, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10238, UINT16_MAX, 8724, UINT16_MAX, 8724, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10240, 2050, UINT16_MAX, 2050, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10243, UINT16_MAX, 8725, UINT16_MAX, 8725, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10245, 2055, UINT16_MAX, 2055, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10248, UINT16_MAX, 8726, UINT16_MAX, 8726, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10250, 2060, UINT16_MAX, 2060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10253, UINT16_MAX, 8727, UINT16_MAX, 8727, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10255, 2065, UINT16_MAX, 2065, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10258, UINT16_MAX, 8728, UINT16_MAX, 8728, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10260, 2070, UINT16_MAX, 2070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10263, UINT16_MAX, 8729, UINT16_MAX, 8729, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10265, 2075, UINT16_MAX, 2075, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10268, UINT16_MAX, 8730, UINT16_MAX, 8730, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10270, 2080, UINT16_MAX, 2080, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10273, UINT16_MAX, 8731, UINT16_MAX, 8731, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10275, 2085, UINT16_MAX, 2085, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10278, UINT16_MAX, 8732, UINT16_MAX, 8732, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10280, 2090, UINT16_MAX, 2090, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10283, UINT16_MAX, 8733, UINT16_MAX, 8733, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10285, 2095, UINT16_MAX, 2095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10288, UINT16_MAX, 8734, UINT16_MAX, 8734, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10290, 2100, UINT16_MAX, 2100, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10293, UINT16_MAX, 8735, UINT16_MAX, 8735, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10295, 2105, UINT16_MAX, 2105, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10298, UINT16_MAX, 8736, UINT16_MAX, 8736, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10300, 2110, UINT16_MAX, 2110, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10303, UINT16_MAX, 8737, UINT16_MAX, 8737, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10305, 2115, UINT16_MAX, 2115, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10308, UINT16_MAX, 8738, UINT16_MAX, 8738, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10310, 2120, UINT16_MAX, 2120, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10313, UINT16_MAX, 8739, UINT16_MAX, 8739, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10315, 2125, UINT16_MAX, 2125, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10318, UINT16_MAX, 8740, UINT16_MAX, 8740, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10320, 2130, UINT16_MAX, 2130, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10323, UINT16_MAX, 8741, UINT16_MAX, 8741, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10325, 2135, UINT16_MAX, 2135, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10328, UINT16_MAX, 8742, UINT16_MAX, 8742, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10330, 2140, UINT16_MAX, 2140, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10333, UINT16_MAX, 8743, UINT16_MAX, 8743, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10335, 2145, UINT16_MAX, 2145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10338, UINT16_MAX, 8744, UINT16_MAX, 8744, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10340, 2150, UINT16_MAX, 2150, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10343, UINT16_MAX, 8745, UINT16_MAX, 8745, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2153, UINT16_MAX, 2153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8746, UINT16_MAX, 8746, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2154, UINT16_MAX, 2154, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8747, UINT16_MAX, 8747, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2155, UINT16_MAX, 2155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8748, UINT16_MAX, 8748, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10348, UINT16_MAX, 8749, UINT16_MAX, 8749, 3761, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10350, UINT16_MAX, 8750, UINT16_MAX, 8750, 3814, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10352, UINT16_MAX, 8751, UINT16_MAX, 8751, 4793, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10354, UINT16_MAX, 8752, UINT16_MAX, 8752, 4796, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10356, UINT16_MAX, 8753, UINT16_MAX, 8753, 4799, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10358, UINT16_MAX, 8754, UINT16_MAX, 8754, 4802, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10360, UINT16_MAX, 8755, UINT16_MAX, 8755, 4805, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10362, UINT16_MAX, 8756, UINT16_MAX, 8756, 4808, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10364, 2174, UINT16_MAX, 2174, UINT16_MAX, 3867, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10367, 2177, UINT16_MAX, 2177, UINT16_MAX, 3920, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10370, 2180, UINT16_MAX, 2180, UINT16_MAX, 4811, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10373, 2183, UINT16_MAX, 2183, UINT16_MAX, 4814, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10376, 2186, UINT16_MAX, 2186, UINT16_MAX, 4817, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10379, 2189, UINT16_MAX, 2189, UINT16_MAX, 4820, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10382, 2192, UINT16_MAX, 2192, UINT16_MAX, 4823, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10385, 2195, UINT16_MAX, 2195, UINT16_MAX, 4826, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10388, UINT16_MAX, 8757, UINT16_MAX, 8757, 3973, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10390, UINT16_MAX, 8758, UINT16_MAX, 8758, 3977, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10392, UINT16_MAX, 8759, UINT16_MAX, 8759, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10394, UINT16_MAX, 8760, UINT16_MAX, 8760, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10396, UINT16_MAX, 8761, UINT16_MAX, 8761, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10398, UINT16_MAX, 8762, UINT16_MAX, 8762, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10400, 2210, UINT16_MAX, 2210, UINT16_MAX, 3981, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10403, 2213, UINT16_MAX, 2213, UINT16_MAX, 3985, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10406, 2216, UINT16_MAX, 2216, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10409, 2219, UINT16_MAX, 2219, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10412, 2222, UINT16_MAX, 2222, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10415, 2225, UINT16_MAX, 2225, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10418, UINT16_MAX, 8763, UINT16_MAX, 8763, 3989, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10420, UINT16_MAX, 8764, UINT16_MAX, 8764, 4042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10422, UINT16_MAX, 8765, UINT16_MAX, 8765, 4829, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10424, UINT16_MAX, 8766, UINT16_MAX, 8766, 4832, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10426, UINT16_MAX, 8767, UINT16_MAX, 8767, 4835, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10428, UINT16_MAX, 8768, UINT16_MAX, 8768, 4838, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10430, UINT16_MAX, 8769, UINT16_MAX, 8769, 4841, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10432, UINT16_MAX, 8770, UINT16_MAX, 8770, 4844, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10434, 2244, UINT16_MAX, 2244, UINT16_MAX, 4095, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10437, 2247, UINT16_MAX, 2247, UINT16_MAX, 4148, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10440, 2250, UINT16_MAX, 2250, UINT16_MAX, 4847, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10443, 2253, UINT16_MAX, 2253, UINT16_MAX, 4850, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10446, 2256, UINT16_MAX, 2256, UINT16_MAX, 4853, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10449, 2259, UINT16_MAX, 2259, UINT16_MAX, 4856, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10452, 2262, UINT16_MAX, 2262, UINT16_MAX, 4859, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10455, 2265, UINT16_MAX, 2265, UINT16_MAX, 4862, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10458, UINT16_MAX, 8771, UINT16_MAX, 8771, 4201, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10460, UINT16_MAX, 8772, UINT16_MAX, 8772, 4253, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10462, UINT16_MAX, 8773, UINT16_MAX, 8773, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10464, UINT16_MAX, 8774, UINT16_MAX, 8774, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10466, UINT16_MAX, 8775, UINT16_MAX, 8775, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10468, UINT16_MAX, 8776, UINT16_MAX, 8776, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10470, UINT16_MAX, 8777, UINT16_MAX, 8777, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10472, UINT16_MAX, 8778, UINT16_MAX, 8778, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10474, 2284, UINT16_MAX, 2284, UINT16_MAX, 4305, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10477, 2287, UINT16_MAX, 2287, UINT16_MAX, 4357, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10480, 2290, UINT16_MAX, 2290, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10483, 2293, UINT16_MAX, 2293, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10486, 2296, UINT16_MAX, 2296, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10489, 2299, UINT16_MAX, 2299, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10492, 2302, UINT16_MAX, 2302, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10495, 2305, UINT16_MAX, 2305, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10498, UINT16_MAX, 8779, UINT16_MAX, 8779, 4409, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10500, UINT16_MAX, 8780, UINT16_MAX, 8780, 4413, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10502, UINT16_MAX, 8781, UINT16_MAX, 8781, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10504, UINT16_MAX, 8782, UINT16_MAX, 8782, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10506, UINT16_MAX, 8783, UINT16_MAX, 8783, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10508, UINT16_MAX, 8784, UINT16_MAX, 8784, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10510, 2320, UINT16_MAX, 2320, UINT16_MAX, 4417, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10513, 2323, UINT16_MAX, 2323, UINT16_MAX, 4421, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10516, 2326, UINT16_MAX, 2326, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10519, 2329, UINT16_MAX, 2329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10522, 2332, UINT16_MAX, 2332, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10525, 2335, UINT16_MAX, 2335, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10528, 10528, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4425, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10530, UINT16_MAX, 8785, UINT16_MAX, 8785, 4477, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10532, 18726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10537, UINT16_MAX, 8786, UINT16_MAX, 8786, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10539, 18733, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10544, UINT16_MAX, 8787, UINT16_MAX, 8787, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10546, 18740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10551, UINT16_MAX, 8788, UINT16_MAX, 8788, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10553, 2363, UINT16_MAX, 2363, UINT16_MAX, 4529, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10556, 2366, UINT16_MAX, 2366, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10559, 2369, UINT16_MAX, 2369, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10562, 2372, UINT16_MAX, 2372, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10565, UINT16_MAX, 8789, UINT16_MAX, 8789, 4581, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10567, UINT16_MAX, 8790, UINT16_MAX, 8790, 4634, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10569, UINT16_MAX, 8791, UINT16_MAX, 8791, 4865, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10571, UINT16_MAX, 8792, UINT16_MAX, 8792, 4868, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10573, UINT16_MAX, 8793, UINT16_MAX, 8793, 4871, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10575, UINT16_MAX, 8794, UINT16_MAX, 8794, 4874, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10577, UINT16_MAX, 8795, UINT16_MAX, 8795, 4877, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10579, UINT16_MAX, 8796, UINT16_MAX, 8796, 4880, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10581, 2391, UINT16_MAX, 2391, UINT16_MAX, 4687, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10584, 2394, UINT16_MAX, 2394, UINT16_MAX, 4740, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10587, 2397, UINT16_MAX, 2397, UINT16_MAX, 4883, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10590, 2400, UINT16_MAX, 2400, UINT16_MAX, 4886, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10593, 2403, UINT16_MAX, 2403, UINT16_MAX, 4889, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10596, 2406, UINT16_MAX, 2406, UINT16_MAX, 4892, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10599, 2409, UINT16_MAX, 2409, UINT16_MAX, 4895, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10602, 2412, UINT16_MAX, 2412, UINT16_MAX, 4898, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10605, UINT16_MAX, 8797, UINT16_MAX, 8797, 4901, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 820, UINT16_MAX, 8798, UINT16_MAX, 8798, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10607, UINT16_MAX, 8799, UINT16_MAX, 8799, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 824, UINT16_MAX, 8800, UINT16_MAX, 8800, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10609, UINT16_MAX, 8801, UINT16_MAX, 8801, 4910, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 827, UINT16_MAX, 8802, UINT16_MAX, 8802, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10611, UINT16_MAX, 8803, UINT16_MAX, 8803, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 830, UINT16_MAX, 8804, UINT16_MAX, 8804, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10613, UINT16_MAX, 8805, UINT16_MAX, 8805, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 833, UINT16_MAX, 8806, UINT16_MAX, 8806, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10615, UINT16_MAX, 8807, UINT16_MAX, 8807, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 836, UINT16_MAX, 8808, UINT16_MAX, 8808, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10617, UINT16_MAX, 8809, UINT16_MAX, 8809, 5030, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 839, UINT16_MAX, 8810, UINT16_MAX, 8810, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10619, 10621, 8811, UINT16_MAX, 8811, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10623, 10625, 8812, UINT16_MAX, 8812, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10627, 10629, 8813, UINT16_MAX, 8813, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10631, 10633, 8814, UINT16_MAX, 8814, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10635, 10637, 8815, UINT16_MAX, 8815, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10639, 10641, 8816, UINT16_MAX, 8816, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10643, 10645, 8817, UINT16_MAX, 8817, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10647, 10649, 8818, UINT16_MAX, 8818, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10651, 10621, UINT16_MAX, 8819, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10653, 10625, UINT16_MAX, 8820, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10655, 10629, UINT16_MAX, 8821, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10657, 10633, UINT16_MAX, 8822, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10659, 10637, UINT16_MAX, 8823, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10661, 10641, UINT16_MAX, 8824, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10663, 10645, UINT16_MAX, 8825, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10665, 10649, UINT16_MAX, 8826, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10667, 10669, 8827, UINT16_MAX, 8827, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10671, 10673, 8828, UINT16_MAX, 8828, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10675, 10677, 8829, UINT16_MAX, 8829, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10679, 10681, 8830, UINT16_MAX, 8830, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10683, 10685, 8831, UINT16_MAX, 8831, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10687, 10689, 8832, UINT16_MAX, 8832, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10691, 10693, 8833, UINT16_MAX, 8833, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10695, 10697, 8834, UINT16_MAX, 8834, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10699, 10669, UINT16_MAX, 8835, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10701, 10673, UINT16_MAX, 8836, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10703, 10677, UINT16_MAX, 8837, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10705, 10681, UINT16_MAX, 8838, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10707, 10685, UINT16_MAX, 8839, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10709, 10689, UINT16_MAX, 8840, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10711, 10693, UINT16_MAX, 8841, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10713, 10697, UINT16_MAX, 8842, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10715, 10717, 8843, UINT16_MAX, 8843, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10719, 10721, 8844, UINT16_MAX, 8844, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10723, 10725, 8845, UINT16_MAX, 8845, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10727, 10729, 8846, UINT16_MAX, 8846, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10731, 10733, 8847, UINT16_MAX, 8847, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10735, 10737, 8848, UINT16_MAX, 8848, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10739, 10741, 8849, UINT16_MAX, 8849, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10743, 10745, 8850, UINT16_MAX, 8850, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10747, 10717, UINT16_MAX, 8851, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10749, 10721, UINT16_MAX, 8852, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10751, 10725, UINT16_MAX, 8853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10753, 10729, UINT16_MAX, 8854, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10755, 10733, UINT16_MAX, 8855, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10757, 10737, UINT16_MAX, 8856, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10759, 10741, UINT16_MAX, 8857, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10761, 10745, UINT16_MAX, 8858, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10763, UINT16_MAX, 8859, UINT16_MAX, 8859, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10765, UINT16_MAX, 8860, UINT16_MAX, 8860, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10767, 10769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10771, 10773, 8861, UINT16_MAX, 8861, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10775, 10777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10779, 10779, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4907, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10781, 18975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10786, 2596, UINT16_MAX, 2596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10789, 2599, UINT16_MAX, 2599, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10792, 2602, UINT16_MAX, 2602, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2603, 2604, UINT16_MAX, 2604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10797, 10773, UINT16_MAX, 8862, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 807, 807, 7217, UINT16_MAX, 7217, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4919, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10805, 10807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10809, 10811, 8863, UINT16_MAX, 8863, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10813, 10815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10817, 10817, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4916, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10819, 19013, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10824, 2634, UINT16_MAX, 2634, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2635, 2636, UINT16_MAX, 2636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10829, 2639, UINT16_MAX, 2639, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2640, 2641, UINT16_MAX, 2641, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10834, 10811, UINT16_MAX, 8864, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10836, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10842, UINT16_MAX, 8865, UINT16_MAX, 8865, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10844, UINT16_MAX, 8866, UINT16_MAX, 8866, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10846, 19040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 2659, 17226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10852, 10852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10854, 19048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10859, 2669, UINT16_MAX, 2669, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10862, 2672, UINT16_MAX, 2672, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10865, 2675, UINT16_MAX, 2675, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2676, 2677, UINT16_MAX, 2677, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10876, UINT16_MAX, 8867, UINT16_MAX, 8867, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10878, UINT16_MAX, 8868, UINT16_MAX, 8868, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10880, 19074, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 2693, 17267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10886, 10886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10888, UINT16_MAX, 8869, UINT16_MAX, 8869, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10890, 10890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10892, 19086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10897, 2707, UINT16_MAX, 2707, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10900, 2710, UINT16_MAX, 2710, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10903, 2713, UINT16_MAX, 2713, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2714, 2715, UINT16_MAX, 2715, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10908, 2718, UINT16_MAX, 2718, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 2721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 2722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10915, 10917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10919, 10921, 8870, UINT16_MAX, 8870, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10923, 10925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10927, 10927, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10929, 19123, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10934, 2744, UINT16_MAX, 2744, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2745, 2746, UINT16_MAX, 2746, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10939, 2749, UINT16_MAX, 2749, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2750, 2751, UINT16_MAX, 2751, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10944, 10921, UINT16_MAX, 8871, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 2754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10947, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4971, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, 2757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, 2758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_COMPAT, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_NOBREAK, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_ZWJ}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NOBREAK, 2759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10952, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PI, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 2762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10955, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19149, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ZL, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_ZP, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRE, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLE, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_PDF, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRO, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLO, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 10960, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 19154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10965, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10970, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_CS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10974, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10976, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10978, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_FSI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_PDI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, 2799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, 2800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 2801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 2802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 2803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 13, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, 2799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, 2800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 2801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 2802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 2803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 4, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 14, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 23, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 7, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 10, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 11, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 12, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 13, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 15, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 18, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 19, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 10996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11005, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 11019, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 11024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2835, 866, UINT16_MAX, 866, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1501, 10, UINT16_MAX, 10, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2836, 65, UINT16_MAX, 65, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2838, UINT16_MAX, 2838, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, 2848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8872, UINT16_MAX, 8872, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 27431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 11087, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1499, 2897, UINT16_MAX, 2897, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11090, 2900, UINT16_MAX, 2900, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19285, 2904, UINT16_MAX, 2904, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11097, 2907, UINT16_MAX, 2907, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2908, 2909, UINT16_MAX, 2909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11102, 2912, UINT16_MAX, 2912, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19297, 2916, UINT16_MAX, 2916, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 27493, 2921, UINT16_MAX, 2921, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11114, 2924, UINT16_MAX, 2924, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2925, 2926, UINT16_MAX, 2926, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11119, 2929, UINT16_MAX, 2929, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19314, 2933, UINT16_MAX, 2933, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1502, 2934, UINT16_MAX, 2934, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2812, 2935, UINT16_MAX, 2935, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1494, 2936, UINT16_MAX, 2936, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1503, 2937, UINT16_MAX, 2937, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8, UINT16_MAX, 8873, UINT16_MAX, 8873, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11130, UINT16_MAX, 8874, UINT16_MAX, 8874, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19324, UINT16_MAX, 8875, UINT16_MAX, 8875, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11135, UINT16_MAX, 8876, UINT16_MAX, 8876, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21, UINT16_MAX, 8877, UINT16_MAX, 8877, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11137, UINT16_MAX, 8878, UINT16_MAX, 8878, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19331, UINT16_MAX, 8879, UINT16_MAX, 8879, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 27526, UINT16_MAX, 8880, UINT16_MAX, 8880, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11146, UINT16_MAX, 8881, UINT16_MAX, 8881, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23, UINT16_MAX, 8882, UINT16_MAX, 8882, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11148, UINT16_MAX, 8883, UINT16_MAX, 8883, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19342, UINT16_MAX, 8884, UINT16_MAX, 8884, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11, UINT16_MAX, 8885, UINT16_MAX, 8885, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2, UINT16_MAX, 8886, UINT16_MAX, 8886, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3, UINT16_MAX, 8887, UINT16_MAX, 8887, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12, UINT16_MAX, 8888, UINT16_MAX, 8888, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2961, UINT16_MAX, 2961, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8889, UINT16_MAX, 8889, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5039, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5045, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11161, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5048, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5054, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5051, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5057, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5060, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5063, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5066, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5069, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5072, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5075, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5078, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5081, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5090, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5087, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5099, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5102, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11203, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5105, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5108, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5111, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5114, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11215, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5117, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5120, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5147, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5150, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5123, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5126, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5129, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5132, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5153, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5156, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5135, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5138, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5141, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5144, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5159, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5162, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5165, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5168, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11239, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11241, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11245, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, 3063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, 3064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27702, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27706, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27710, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27714, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1491, 3287, UINT16_MAX, 3287, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1493, 3288, UINT16_MAX, 3288, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2812, 3289, UINT16_MAX, 3289, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1494, 3290, UINT16_MAX, 3290, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1495, 3291, UINT16_MAX, 3291, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2837, 3292, UINT16_MAX, 3292, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1497, 3293, UINT16_MAX, 3293, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1498, 3294, UINT16_MAX, 3294, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1499, 3295, UINT16_MAX, 3295, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1500, 3296, UINT16_MAX, 3296, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1501, 3297, UINT16_MAX, 3297, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1502, 3298, UINT16_MAX, 3298, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1503, 3299, UINT16_MAX, 3299, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1504, 3300, UINT16_MAX, 3300, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1505, 3301, UINT16_MAX, 3301, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1507, 3302, UINT16_MAX, 3302, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2826, 3303, UINT16_MAX, 3303, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1508, 3304, UINT16_MAX, 3304, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3305, 3306, UINT16_MAX, 3306, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1509, 3307, UINT16_MAX, 3307, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1510, 3308, UINT16_MAX, 3308, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2908, 3309, UINT16_MAX, 3309, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1511, 3310, UINT16_MAX, 3310, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2925, 3311, UINT16_MAX, 3311, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3312, 3313, UINT16_MAX, 3313, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2834, 3314, UINT16_MAX, 3314, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 0, UINT16_MAX, 8890, UINT16_MAX, 8890, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1, UINT16_MAX, 8891, UINT16_MAX, 8891, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2, UINT16_MAX, 8892, UINT16_MAX, 8892, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3, UINT16_MAX, 8893, UINT16_MAX, 8893, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4, UINT16_MAX, 8894, UINT16_MAX, 8894, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5, UINT16_MAX, 8895, UINT16_MAX, 8895, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 6, UINT16_MAX, 8896, UINT16_MAX, 8896, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 7, UINT16_MAX, 8897, UINT16_MAX, 8897, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 8, UINT16_MAX, 8898, UINT16_MAX, 8898, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 9, UINT16_MAX, 8899, UINT16_MAX, 8899, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 10, UINT16_MAX, 8900, UINT16_MAX, 8900, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 11, UINT16_MAX, 8901, UINT16_MAX, 8901, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12, UINT16_MAX, 8902, UINT16_MAX, 8902, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 13, UINT16_MAX, 8903, UINT16_MAX, 8903, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 14, UINT16_MAX, 8904, UINT16_MAX, 8904, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 15, UINT16_MAX, 8905, UINT16_MAX, 8905, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 16, UINT16_MAX, 8906, UINT16_MAX, 8906, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 17, UINT16_MAX, 8907, UINT16_MAX, 8907, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 18, UINT16_MAX, 8908, UINT16_MAX, 8908, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 19, UINT16_MAX, 8909, UINT16_MAX, 8909, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20, UINT16_MAX, 8910, UINT16_MAX, 8910, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21, UINT16_MAX, 8911, UINT16_MAX, 8911, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 22, UINT16_MAX, 8912, UINT16_MAX, 8912, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 23, UINT16_MAX, 8913, UINT16_MAX, 8913, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 24, UINT16_MAX, 8914, UINT16_MAX, 8914, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 25, UINT16_MAX, 8915, UINT16_MAX, 8915, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5171, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3329, UINT16_MAX, 3329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3330, UINT16_MAX, 3330, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3331, UINT16_MAX, 3331, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3332, UINT16_MAX, 3332, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3333, UINT16_MAX, 3333, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3334, UINT16_MAX, 3334, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3335, UINT16_MAX, 3335, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3336, UINT16_MAX, 3336, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3337, UINT16_MAX, 3337, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3338, UINT16_MAX, 3338, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3339, UINT16_MAX, 3339, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3340, UINT16_MAX, 3340, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3341, UINT16_MAX, 3341, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3342, UINT16_MAX, 3342, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3343, UINT16_MAX, 3343, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3344, UINT16_MAX, 3344, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3345, UINT16_MAX, 3345, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3346, UINT16_MAX, 3346, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3347, UINT16_MAX, 3347, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3348, UINT16_MAX, 3348, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3349, UINT16_MAX, 3349, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3350, UINT16_MAX, 3350, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3351, UINT16_MAX, 3351, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3352, UINT16_MAX, 3352, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3353, UINT16_MAX, 3353, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3354, UINT16_MAX, 3354, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3355, UINT16_MAX, 3355, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3356, UINT16_MAX, 3356, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3357, UINT16_MAX, 3357, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3358, UINT16_MAX, 3358, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3359, UINT16_MAX, 3359, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3360, UINT16_MAX, 3360, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3361, UINT16_MAX, 3361, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3362, UINT16_MAX, 3362, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3363, UINT16_MAX, 3363, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3364, UINT16_MAX, 3364, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3365, UINT16_MAX, 3365, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3366, UINT16_MAX, 3366, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3367, UINT16_MAX, 3367, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3368, UINT16_MAX, 3368, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3369, UINT16_MAX, 3369, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3370, UINT16_MAX, 3370, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3371, UINT16_MAX, 3371, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3372, UINT16_MAX, 3372, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3373, UINT16_MAX, 3373, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3374, UINT16_MAX, 3374, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3375, UINT16_MAX, 3375, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8916, UINT16_MAX, 8916, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8917, UINT16_MAX, 8917, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8918, UINT16_MAX, 8918, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8919, UINT16_MAX, 8919, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8920, UINT16_MAX, 8920, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8921, UINT16_MAX, 8921, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8922, UINT16_MAX, 8922, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8923, UINT16_MAX, 8923, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8924, UINT16_MAX, 8924, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8925, UINT16_MAX, 8925, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8926, UINT16_MAX, 8926, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8927, UINT16_MAX, 8927, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8928, UINT16_MAX, 8928, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8929, UINT16_MAX, 8929, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8930, UINT16_MAX, 8930, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8931, UINT16_MAX, 8931, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8932, UINT16_MAX, 8932, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8933, UINT16_MAX, 8933, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8934, UINT16_MAX, 8934, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8935, UINT16_MAX, 8935, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8936, UINT16_MAX, 8936, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8937, UINT16_MAX, 8937, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8938, UINT16_MAX, 8938, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8939, UINT16_MAX, 8939, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8940, UINT16_MAX, 8940, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8941, UINT16_MAX, 8941, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8942, UINT16_MAX, 8942, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8943, UINT16_MAX, 8943, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8944, UINT16_MAX, 8944, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8945, UINT16_MAX, 8945, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8946, UINT16_MAX, 8946, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8947, UINT16_MAX, 8947, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8948, UINT16_MAX, 8948, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8949, UINT16_MAX, 8949, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8950, UINT16_MAX, 8950, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8951, UINT16_MAX, 8951, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8952, UINT16_MAX, 8952, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8953, UINT16_MAX, 8953, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8954, UINT16_MAX, 8954, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8955, UINT16_MAX, 8955, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8956, UINT16_MAX, 8956, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8957, UINT16_MAX, 8957, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8958, UINT16_MAX, 8958, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8959, UINT16_MAX, 8959, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8960, UINT16_MAX, 8960, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8961, UINT16_MAX, 8961, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8962, UINT16_MAX, 8962, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3376, UINT16_MAX, 3376, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8963, UINT16_MAX, 8963, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3377, UINT16_MAX, 3377, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3378, UINT16_MAX, 3378, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3379, UINT16_MAX, 3379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8964, UINT16_MAX, 8964, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8965, UINT16_MAX, 8965, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3380, UINT16_MAX, 3380, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8966, UINT16_MAX, 8966, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3381, UINT16_MAX, 3381, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8967, UINT16_MAX, 8967, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3382, UINT16_MAX, 3382, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8968, UINT16_MAX, 8968, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1513, UINT16_MAX, 1513, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1531, UINT16_MAX, 1531, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1512, UINT16_MAX, 1512, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1520, UINT16_MAX, 1520, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3383, UINT16_MAX, 3383, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8969, UINT16_MAX, 8969, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3384, UINT16_MAX, 3384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8970, UINT16_MAX, 8970, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 9, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3385, UINT16_MAX, 3385, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3386, UINT16_MAX, 3386, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3387, UINT16_MAX, 3387, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8971, UINT16_MAX, 8971, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3388, UINT16_MAX, 3388, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8972, UINT16_MAX, 8972, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3389, UINT16_MAX, 3389, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8973, UINT16_MAX, 8973, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3390, UINT16_MAX, 3390, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8974, UINT16_MAX, 8974, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3391, UINT16_MAX, 3391, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8975, UINT16_MAX, 8975, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3392, UINT16_MAX, 3392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8976, UINT16_MAX, 8976, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3393, UINT16_MAX, 3393, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8977, UINT16_MAX, 8977, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3394, UINT16_MAX, 3394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8978, UINT16_MAX, 8978, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3395, UINT16_MAX, 3395, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8979, UINT16_MAX, 8979, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3396, UINT16_MAX, 3396, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8980, UINT16_MAX, 8980, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3397, UINT16_MAX, 3397, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8981, UINT16_MAX, 8981, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3398, UINT16_MAX, 3398, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8982, UINT16_MAX, 8982, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3399, UINT16_MAX, 3399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8983, UINT16_MAX, 8983, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3400, UINT16_MAX, 3400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8984, UINT16_MAX, 8984, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3401, UINT16_MAX, 3401, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8985, UINT16_MAX, 8985, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3402, UINT16_MAX, 3402, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8986, UINT16_MAX, 8986, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3403, UINT16_MAX, 3403, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8987, UINT16_MAX, 8987, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3404, UINT16_MAX, 3404, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8988, UINT16_MAX, 8988, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3405, UINT16_MAX, 3405, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8989, UINT16_MAX, 8989, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3406, UINT16_MAX, 3406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8990, UINT16_MAX, 8990, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3407, UINT16_MAX, 3407, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8991, UINT16_MAX, 8991, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3408, UINT16_MAX, 3408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8992, UINT16_MAX, 8992, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3409, UINT16_MAX, 3409, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8993, UINT16_MAX, 8993, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3410, UINT16_MAX, 3410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8994, UINT16_MAX, 8994, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3411, UINT16_MAX, 3411, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8995, UINT16_MAX, 8995, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3412, UINT16_MAX, 3412, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8996, UINT16_MAX, 8996, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3413, UINT16_MAX, 3413, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8997, UINT16_MAX, 8997, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3414, UINT16_MAX, 3414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8998, UINT16_MAX, 8998, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3415, UINT16_MAX, 3415, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8999, UINT16_MAX, 8999, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3416, UINT16_MAX, 3416, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9000, UINT16_MAX, 9000, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3417, UINT16_MAX, 3417, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9001, UINT16_MAX, 9001, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3418, UINT16_MAX, 3418, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9002, UINT16_MAX, 9002, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3419, UINT16_MAX, 3419, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9003, UINT16_MAX, 9003, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3420, UINT16_MAX, 3420, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9004, UINT16_MAX, 9004, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3421, UINT16_MAX, 3421, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9005, UINT16_MAX, 9005, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3422, UINT16_MAX, 3422, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9006, UINT16_MAX, 9006, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3423, UINT16_MAX, 3423, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9007, UINT16_MAX, 9007, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3424, UINT16_MAX, 3424, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9008, UINT16_MAX, 9008, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3425, UINT16_MAX, 3425, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9009, UINT16_MAX, 9009, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3426, UINT16_MAX, 3426, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9010, UINT16_MAX, 9010, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3427, UINT16_MAX, 3427, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9011, UINT16_MAX, 9011, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3428, UINT16_MAX, 3428, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9012, UINT16_MAX, 9012, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3429, UINT16_MAX, 3429, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9013, UINT16_MAX, 9013, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3430, UINT16_MAX, 3430, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9014, UINT16_MAX, 9014, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3431, UINT16_MAX, 3431, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9015, UINT16_MAX, 9015, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3432, UINT16_MAX, 3432, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9016, UINT16_MAX, 9016, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3433, UINT16_MAX, 3433, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9017, UINT16_MAX, 9017, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3434, UINT16_MAX, 3434, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9018, UINT16_MAX, 9018, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3435, UINT16_MAX, 3435, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9019, UINT16_MAX, 9019, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3436, UINT16_MAX, 3436, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9020, UINT16_MAX, 9020, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3437, UINT16_MAX, 3437, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9021, UINT16_MAX, 9021, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3438, UINT16_MAX, 3438, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9022, UINT16_MAX, 9022, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3439, UINT16_MAX, 3439, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9023, UINT16_MAX, 9023, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9024, UINT16_MAX, 9024, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9025, UINT16_MAX, 9025, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9026, UINT16_MAX, 9026, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9027, UINT16_MAX, 9027, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9028, UINT16_MAX, 9028, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9029, UINT16_MAX, 9029, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9030, UINT16_MAX, 9030, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9031, UINT16_MAX, 9031, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9032, UINT16_MAX, 9032, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9033, UINT16_MAX, 9033, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9034, UINT16_MAX, 9034, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9035, UINT16_MAX, 9035, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9036, UINT16_MAX, 9036, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9037, UINT16_MAX, 9037, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9038, UINT16_MAX, 9038, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9039, UINT16_MAX, 9039, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9040, UINT16_MAX, 9040, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9041, UINT16_MAX, 9041, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9042, UINT16_MAX, 9042, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9043, UINT16_MAX, 9043, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9044, UINT16_MAX, 9044, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9045, UINT16_MAX, 9045, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9046, UINT16_MAX, 9046, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9047, UINT16_MAX, 9047, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9048, UINT16_MAX, 9048, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9049, UINT16_MAX, 9049, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9050, UINT16_MAX, 9050, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9051, UINT16_MAX, 9051, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9052, UINT16_MAX, 9052, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9053, UINT16_MAX, 9053, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9054, UINT16_MAX, 9054, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9055, UINT16_MAX, 9055, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9056, UINT16_MAX, 9056, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9057, UINT16_MAX, 9057, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9058, UINT16_MAX, 9058, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9059, UINT16_MAX, 9059, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9060, UINT16_MAX, 9060, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9061, UINT16_MAX, 9061, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9062, UINT16_MAX, 9062, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9063, UINT16_MAX, 9063, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3646, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3655, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_WIDE, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 218, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 224, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5239, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5174, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5177, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5180, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5183, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5186, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5189, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5192, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5195, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5198, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5201, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5204, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5207, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5210, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5213, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5216, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5219, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5223, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5227, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5231, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5235, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32820, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32821, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11906, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5242, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, 11908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, 11910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5310, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5245, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5248, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5251, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5254, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5257, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5260, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5263, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5266, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5269, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5272, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11930, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5275, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5278, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5281, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5284, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5287, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5290, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11942, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11944, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5294, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11948, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5298, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11950, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11952, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5302, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11954, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11956, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5306, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11958, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11960, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5313, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5316, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5319, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5322, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11962, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11964, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11966, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11968, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11970, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5325, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, 11972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, 11974, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3788, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3791, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3805, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3806, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3808, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3816, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3824, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3828, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3831, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3832, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3833, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3836, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3885, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20284, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 44957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20387, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20390, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20393, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20396, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20402, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4111, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4112, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4113, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 20498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12319, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3806, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12345, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12363, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 36943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 28756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4203, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4214, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4215, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 12467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 20661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 12472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 20666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4316, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4318, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4319, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4320, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4330, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37127, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20755, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28976, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 45371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20806, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29011, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29033, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20885, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29089, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20906, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29123, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29141, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20956, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20959, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29172, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20991, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21003, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37396, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21017, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12828, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12832, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12836, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21043, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21049, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21055, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21061, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21073, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21079, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21085, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12905, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 12907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21101, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 12915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21137, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12952, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12954, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12956, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12958, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12960, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12962, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12964, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21161, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12978, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12980, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12982, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12984, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12990, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13015, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13027, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 45814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13074, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13080, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13084, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13105, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13107, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13109, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13111, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13113, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13115, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13117, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13119, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13121, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13123, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21336, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13149, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13151, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13161, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21383, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21386, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21389, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21392, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21395, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21398, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21401, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21404, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5056, UINT16_MAX, 5056, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9064, UINT16_MAX, 9064, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5057, UINT16_MAX, 5057, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9065, UINT16_MAX, 9065, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5058, UINT16_MAX, 5058, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9066, UINT16_MAX, 9066, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5059, UINT16_MAX, 5059, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9067, UINT16_MAX, 9067, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5060, UINT16_MAX, 5060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9068, UINT16_MAX, 9068, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1445, UINT16_MAX, 1445, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8621, UINT16_MAX, 8621, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5061, UINT16_MAX, 5061, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9069, UINT16_MAX, 9069, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5062, UINT16_MAX, 5062, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9070, UINT16_MAX, 9070, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5063, UINT16_MAX, 5063, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9071, UINT16_MAX, 9071, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5064, UINT16_MAX, 5064, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9072, UINT16_MAX, 9072, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5065, UINT16_MAX, 5065, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9073, UINT16_MAX, 9073, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5066, UINT16_MAX, 5066, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9074, UINT16_MAX, 9074, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5067, UINT16_MAX, 5067, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9075, UINT16_MAX, 9075, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5068, UINT16_MAX, 5068, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9076, UINT16_MAX, 9076, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5069, UINT16_MAX, 5069, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9077, UINT16_MAX, 9077, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5070, UINT16_MAX, 5070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9078, UINT16_MAX, 9078, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5071, UINT16_MAX, 5071, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9079, UINT16_MAX, 9079, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5072, UINT16_MAX, 5072, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9080, UINT16_MAX, 9080, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5073, UINT16_MAX, 5073, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9081, UINT16_MAX, 9081, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5074, UINT16_MAX, 5074, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9082, UINT16_MAX, 9082, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5075, UINT16_MAX, 5075, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9083, UINT16_MAX, 9083, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5076, UINT16_MAX, 5076, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9084, UINT16_MAX, 9084, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5077, UINT16_MAX, 5077, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9085, UINT16_MAX, 9085, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5078, UINT16_MAX, 5078, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9086, UINT16_MAX, 9086, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5079, UINT16_MAX, 5079, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9087, UINT16_MAX, 9087, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5080, UINT16_MAX, 5080, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9088, UINT16_MAX, 9088, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5081, UINT16_MAX, 5081, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9089, UINT16_MAX, 9089, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5082, UINT16_MAX, 5082, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9090, UINT16_MAX, 9090, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5083, UINT16_MAX, 5083, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9091, UINT16_MAX, 9091, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5084, UINT16_MAX, 5084, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9092, UINT16_MAX, 9092, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5085, UINT16_MAX, 5085, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9093, UINT16_MAX, 9093, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5086, UINT16_MAX, 5086, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9094, UINT16_MAX, 9094, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5087, UINT16_MAX, 5087, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9095, UINT16_MAX, 9095, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5088, UINT16_MAX, 5088, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9096, UINT16_MAX, 9096, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5089, UINT16_MAX, 5089, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9097, UINT16_MAX, 9097, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5090, UINT16_MAX, 5090, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9098, UINT16_MAX, 9098, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5091, UINT16_MAX, 5091, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9099, UINT16_MAX, 9099, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5092, UINT16_MAX, 5092, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9100, UINT16_MAX, 9100, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5093, UINT16_MAX, 5093, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9101, UINT16_MAX, 9101, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5094, UINT16_MAX, 5094, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9102, UINT16_MAX, 9102, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5095, UINT16_MAX, 5095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9103, UINT16_MAX, 9103, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5096, UINT16_MAX, 5096, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9104, UINT16_MAX, 9104, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5097, UINT16_MAX, 5097, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9105, UINT16_MAX, 9105, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5098, UINT16_MAX, 5098, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9106, UINT16_MAX, 9106, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5099, UINT16_MAX, 5099, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9107, UINT16_MAX, 9107, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5100, UINT16_MAX, 5100, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9108, UINT16_MAX, 9108, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5101, UINT16_MAX, 5101, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9109, UINT16_MAX, 9109, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5102, UINT16_MAX, 5102, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9110, UINT16_MAX, 9110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5103, UINT16_MAX, 5103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9111, UINT16_MAX, 9111, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5104, UINT16_MAX, 5104, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9112, UINT16_MAX, 9112, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5105, UINT16_MAX, 5105, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9113, UINT16_MAX, 9113, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5106, UINT16_MAX, 5106, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9114, UINT16_MAX, 9114, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5107, UINT16_MAX, 5107, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9115, UINT16_MAX, 9115, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5108, UINT16_MAX, 5108, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9116, UINT16_MAX, 9116, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5109, UINT16_MAX, 5109, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9117, UINT16_MAX, 9117, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5110, UINT16_MAX, 5110, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9118, UINT16_MAX, 9118, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5111, UINT16_MAX, 5111, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9119, UINT16_MAX, 9119, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5112, UINT16_MAX, 5112, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9120, UINT16_MAX, 9120, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5113, UINT16_MAX, 5113, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9121, UINT16_MAX, 9121, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5114, UINT16_MAX, 5114, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9122, UINT16_MAX, 9122, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5115, UINT16_MAX, 5115, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9123, UINT16_MAX, 9123, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5116, UINT16_MAX, 5116, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9124, UINT16_MAX, 9124, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5117, UINT16_MAX, 5117, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9125, UINT16_MAX, 9125, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5118, UINT16_MAX, 5118, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9126, UINT16_MAX, 9126, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5119, UINT16_MAX, 5119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9127, UINT16_MAX, 9127, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5120, UINT16_MAX, 5120, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9128, UINT16_MAX, 9128, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5121, UINT16_MAX, 5121, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9129, UINT16_MAX, 9129, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5122, UINT16_MAX, 5122, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9130, UINT16_MAX, 9130, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5123, UINT16_MAX, 5123, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9131, UINT16_MAX, 9131, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5124, UINT16_MAX, 5124, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9132, UINT16_MAX, 9132, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5125, UINT16_MAX, 5125, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9133, UINT16_MAX, 9133, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5126, UINT16_MAX, 5126, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9134, UINT16_MAX, 9134, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5127, UINT16_MAX, 5127, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9135, UINT16_MAX, 9135, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5128, UINT16_MAX, 5128, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9136, UINT16_MAX, 9136, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5129, UINT16_MAX, 5129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9137, UINT16_MAX, 9137, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5129, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5130, UINT16_MAX, 5130, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9138, UINT16_MAX, 9138, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5131, UINT16_MAX, 5131, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9139, UINT16_MAX, 9139, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5132, UINT16_MAX, 5132, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5133, UINT16_MAX, 5133, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9140, UINT16_MAX, 9140, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5134, UINT16_MAX, 5134, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9141, UINT16_MAX, 9141, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5135, UINT16_MAX, 5135, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9142, UINT16_MAX, 9142, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5136, UINT16_MAX, 5136, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9143, UINT16_MAX, 9143, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5137, UINT16_MAX, 5137, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9144, UINT16_MAX, 9144, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5138, UINT16_MAX, 5138, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9145, UINT16_MAX, 9145, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1524, UINT16_MAX, 1524, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5139, UINT16_MAX, 5139, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9146, UINT16_MAX, 9146, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5140, UINT16_MAX, 5140, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9147, UINT16_MAX, 9147, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9148, UINT16_MAX, 9148, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5141, UINT16_MAX, 5141, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9149, UINT16_MAX, 9149, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5142, UINT16_MAX, 5142, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9150, UINT16_MAX, 9150, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5143, UINT16_MAX, 5143, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9151, UINT16_MAX, 9151, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5144, UINT16_MAX, 5144, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9152, UINT16_MAX, 9152, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5145, UINT16_MAX, 5145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9153, UINT16_MAX, 9153, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5146, UINT16_MAX, 5146, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9154, UINT16_MAX, 9154, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5147, UINT16_MAX, 5147, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9155, UINT16_MAX, 9155, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5148, UINT16_MAX, 5148, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9156, UINT16_MAX, 9156, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5149, UINT16_MAX, 5149, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9157, UINT16_MAX, 9157, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5150, UINT16_MAX, 5150, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9158, UINT16_MAX, 9158, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 785, UINT16_MAX, 785, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1515, UINT16_MAX, 1515, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1523, UINT16_MAX, 1523, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5151, UINT16_MAX, 5151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1525, UINT16_MAX, 1525, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5152, UINT16_MAX, 5152, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5153, UINT16_MAX, 5153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1527, UINT16_MAX, 1527, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5154, UINT16_MAX, 5154, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5155, UINT16_MAX, 5155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9159, UINT16_MAX, 9159, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5156, UINT16_MAX, 5156, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9160, UINT16_MAX, 9160, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5157, UINT16_MAX, 5157, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9161, UINT16_MAX, 9161, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5158, UINT16_MAX, 5158, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9162, UINT16_MAX, 9162, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5159, UINT16_MAX, 5159, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9163, UINT16_MAX, 9163, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5160, UINT16_MAX, 5160, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9164, UINT16_MAX, 9164, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5161, UINT16_MAX, 5161, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9165, UINT16_MAX, 9165, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5162, UINT16_MAX, 5162, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1536, UINT16_MAX, 1536, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5163, UINT16_MAX, 5163, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9166, UINT16_MAX, 9166, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5167, 5167, UINT16_MAX, 5167, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5168, 5168, UINT16_MAX, 5168, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5169, 5169, UINT16_MAX, 5169, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5170, 5170, UINT16_MAX, 5170, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5171, 5171, UINT16_MAX, 5171, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5172, 5172, UINT16_MAX, 5172, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5173, 5173, UINT16_MAX, 5173, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5174, 5174, UINT16_MAX, 5174, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5175, 5175, UINT16_MAX, 5175, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5176, 5176, UINT16_MAX, 5176, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5177, 5177, UINT16_MAX, 5177, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5178, 5178, UINT16_MAX, 5178, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5179, 5179, UINT16_MAX, 5179, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5180, 5180, UINT16_MAX, 5180, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5181, 5181, UINT16_MAX, 5181, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5182, 5182, UINT16_MAX, 5182, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5183, 5183, UINT16_MAX, 5183, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5184, 5184, UINT16_MAX, 5184, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5185, 5185, UINT16_MAX, 5185, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5186, 5186, UINT16_MAX, 5186, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5187, 5187, UINT16_MAX, 5187, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5188, 5188, UINT16_MAX, 5188, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5189, 5189, UINT16_MAX, 5189, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5190, 5190, UINT16_MAX, 5190, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5191, 5191, UINT16_MAX, 5191, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5192, 5192, UINT16_MAX, 5192, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5193, 5193, UINT16_MAX, 5193, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5194, 5194, UINT16_MAX, 5194, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5195, 5195, UINT16_MAX, 5195, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5196, 5196, UINT16_MAX, 5196, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5197, 5197, UINT16_MAX, 5197, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5198, 5198, UINT16_MAX, 5198, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5199, 5199, UINT16_MAX, 5199, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5200, 5200, UINT16_MAX, 5200, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5201, 5201, UINT16_MAX, 5201, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5202, 5202, UINT16_MAX, 5202, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5203, 5203, UINT16_MAX, 5203, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5204, 5204, UINT16_MAX, 5204, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5205, 5205, UINT16_MAX, 5205, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5206, 5206, UINT16_MAX, 5206, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5207, 5207, UINT16_MAX, 5207, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5208, 5208, UINT16_MAX, 5208, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5209, 5209, UINT16_MAX, 5209, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5210, 5210, UINT16_MAX, 5210, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5211, 5211, UINT16_MAX, 5211, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5212, 5212, UINT16_MAX, 5212, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5213, 5213, UINT16_MAX, 5213, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5214, 5214, UINT16_MAX, 5214, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5215, 5215, UINT16_MAX, 5215, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5216, 5216, UINT16_MAX, 5216, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5217, 5217, UINT16_MAX, 5217, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5218, 5218, UINT16_MAX, 5218, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5219, 5219, UINT16_MAX, 5219, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5220, 5220, UINT16_MAX, 5220, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5221, 5221, UINT16_MAX, 5221, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5222, 5222, UINT16_MAX, 5222, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5223, 5223, UINT16_MAX, 5223, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5224, 5224, UINT16_MAX, 5224, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5225, 5225, UINT16_MAX, 5225, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5226, 5226, UINT16_MAX, 5226, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5227, 5227, UINT16_MAX, 5227, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5228, 5228, UINT16_MAX, 5228, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5229, 5229, UINT16_MAX, 5229, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5230, 5230, UINT16_MAX, 5230, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5231, 5231, UINT16_MAX, 5231, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5232, 5232, UINT16_MAX, 5232, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5233, 5233, UINT16_MAX, 5233, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5234, 5234, UINT16_MAX, 5234, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5235, 5235, UINT16_MAX, 5235, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5236, 5236, UINT16_MAX, 5236, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5237, 5237, UINT16_MAX, 5237, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5238, 5238, UINT16_MAX, 5238, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5239, 5239, UINT16_MAX, 5239, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5240, 5240, UINT16_MAX, 5240, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5241, 5241, UINT16_MAX, 5241, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5242, 5242, UINT16_MAX, 5242, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5243, 5243, UINT16_MAX, 5243, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5244, 5244, UINT16_MAX, 5244, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5245, 5245, UINT16_MAX, 5245, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5246, 5246, UINT16_MAX, 5246, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_LV}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_LVT}, - {UTF8PROC_CATEGORY_CS, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_CO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3655, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5284, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5316, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5318, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5319, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5320, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5330, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5334, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5336, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5340, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5342, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5345, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5363, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5369, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5372, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5375, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5379, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5381, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5383, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5384, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5385, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5386, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5387, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5389, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5390, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5391, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5392, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5393, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5394, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5395, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5396, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5397, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5398, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5400, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5401, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5402, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5403, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5404, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5406, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5421, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13852, 13852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13854, 13854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13856, 13856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22050, 22050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22053, 22053, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13864, 13866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13866, 13866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13868, 13868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13870, 13870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13872, 13872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13874, 13874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13876, 13876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 26, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 2839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 2842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_FONT, 2799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13893, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13905, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13913, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13927, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13945, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13947, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13949, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13951, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_COMPAT, 13953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5788, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5788, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5791, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5791, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13995, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13995, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13997, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13997, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13999, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13999, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14001, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14001, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14003, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14003, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14005, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14005, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14007, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14007, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14007, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14009, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14009, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14009, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14074, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14080, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14084, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14088, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14098, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14100, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14106, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14110, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14112, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14118, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14120, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14124, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14136, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14150, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14152, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14156, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14168, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14170, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14172, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22390, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22393, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22396, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22402, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14218, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14110, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14118, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14120, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14168, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14170, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14074, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14080, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14084, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14098, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14100, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14106, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14112, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14124, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14136, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14150, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14152, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14172, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14319, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14319, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14088, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14088, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22702, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22714, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22723, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22732, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22735, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22753, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22816, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31017, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31021, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31025, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31029, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31033, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31037, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31041, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 63816, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 63835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 2802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 2803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 3063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 3064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 6531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 6516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 6504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 2762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 6507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 2802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 2803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 6532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, 2799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, 6535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 2801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 6539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 6540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14734, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14736, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14748, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, 2799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 6504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, 6535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 2762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 6615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 6507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1491, 6616, UINT16_MAX, 6616, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1493, 6617, UINT16_MAX, 6617, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2812, 6618, UINT16_MAX, 6618, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1494, 6619, UINT16_MAX, 6619, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1495, 6620, UINT16_MAX, 6620, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2837, 6621, UINT16_MAX, 6621, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1497, 6622, UINT16_MAX, 6622, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1498, 6623, UINT16_MAX, 6623, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1499, 6624, UINT16_MAX, 6624, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1500, 6625, UINT16_MAX, 6625, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1501, 6626, UINT16_MAX, 6626, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1502, 6627, UINT16_MAX, 6627, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1503, 6628, UINT16_MAX, 6628, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1504, 6629, UINT16_MAX, 6629, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1505, 6630, UINT16_MAX, 6630, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1507, 6631, UINT16_MAX, 6631, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2826, 6632, UINT16_MAX, 6632, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1508, 6633, UINT16_MAX, 6633, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 3305, 6634, UINT16_MAX, 6634, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1509, 6635, UINT16_MAX, 6635, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1510, 6636, UINT16_MAX, 6636, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2908, 6637, UINT16_MAX, 6637, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1511, 6638, UINT16_MAX, 6638, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2925, 6639, UINT16_MAX, 6639, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 3312, 6640, UINT16_MAX, 6640, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2834, 6641, UINT16_MAX, 6641, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 0, UINT16_MAX, 9167, UINT16_MAX, 9167, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1, UINT16_MAX, 9168, UINT16_MAX, 9168, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2, UINT16_MAX, 9169, UINT16_MAX, 9169, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 3, UINT16_MAX, 9170, UINT16_MAX, 9170, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 4, UINT16_MAX, 9171, UINT16_MAX, 9171, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 5, UINT16_MAX, 9172, UINT16_MAX, 9172, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 6, UINT16_MAX, 9173, UINT16_MAX, 9173, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 7, UINT16_MAX, 9174, UINT16_MAX, 9174, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 8, UINT16_MAX, 9175, UINT16_MAX, 9175, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 9, UINT16_MAX, 9176, UINT16_MAX, 9176, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 10, UINT16_MAX, 9177, UINT16_MAX, 9177, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 11, UINT16_MAX, 9178, UINT16_MAX, 9178, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 12, UINT16_MAX, 9179, UINT16_MAX, 9179, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 13, UINT16_MAX, 9180, UINT16_MAX, 9180, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 14, UINT16_MAX, 9181, UINT16_MAX, 9181, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 15, UINT16_MAX, 9182, UINT16_MAX, 9182, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 16, UINT16_MAX, 9183, UINT16_MAX, 9183, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 17, UINT16_MAX, 9184, UINT16_MAX, 9184, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 18, UINT16_MAX, 9185, UINT16_MAX, 9185, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 19, UINT16_MAX, 9186, UINT16_MAX, 9186, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 20, UINT16_MAX, 9187, UINT16_MAX, 9187, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 21, UINT16_MAX, 9188, UINT16_MAX, 9188, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 22, UINT16_MAX, 9189, UINT16_MAX, 9189, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 23, UINT16_MAX, 9190, UINT16_MAX, 9190, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 24, UINT16_MAX, 9191, UINT16_MAX, 9191, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 25, UINT16_MAX, 9192, UINT16_MAX, 9192, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6646, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6655, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4316, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4318, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4319, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4320, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6702, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6704, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6706, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6707, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6710, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6712, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6713, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6714, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6715, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6716, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6719, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6723, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6724, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6725, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6727, UINT16_MAX, 6727, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6729, UINT16_MAX, 6729, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6731, UINT16_MAX, 6731, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6733, UINT16_MAX, 6733, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6735, UINT16_MAX, 6735, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6737, UINT16_MAX, 6737, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6739, UINT16_MAX, 6739, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6741, UINT16_MAX, 6741, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6743, UINT16_MAX, 6743, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6745, UINT16_MAX, 6745, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6747, UINT16_MAX, 6747, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6749, UINT16_MAX, 6749, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6751, UINT16_MAX, 6751, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6753, UINT16_MAX, 6753, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6755, UINT16_MAX, 6755, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6757, UINT16_MAX, 6757, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6759, UINT16_MAX, 6759, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6761, UINT16_MAX, 6761, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6763, UINT16_MAX, 6763, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6765, UINT16_MAX, 6765, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6767, UINT16_MAX, 6767, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6769, UINT16_MAX, 6769, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6771, UINT16_MAX, 6771, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6773, UINT16_MAX, 6773, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6775, UINT16_MAX, 6775, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6777, UINT16_MAX, 6777, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6779, UINT16_MAX, 6779, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6781, UINT16_MAX, 6781, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6783, UINT16_MAX, 6783, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6785, UINT16_MAX, 6785, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6787, UINT16_MAX, 6787, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6789, UINT16_MAX, 6789, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6791, UINT16_MAX, 6791, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6793, UINT16_MAX, 6793, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6795, UINT16_MAX, 6795, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6797, UINT16_MAX, 6797, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6799, UINT16_MAX, 6799, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6801, UINT16_MAX, 6801, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6803, UINT16_MAX, 6803, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6805, UINT16_MAX, 6805, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9193, UINT16_MAX, 9193, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9195, UINT16_MAX, 9195, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9197, UINT16_MAX, 9197, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9199, UINT16_MAX, 9199, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9201, UINT16_MAX, 9201, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9203, UINT16_MAX, 9203, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9205, UINT16_MAX, 9205, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9207, UINT16_MAX, 9207, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9209, UINT16_MAX, 9209, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9211, UINT16_MAX, 9211, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9213, UINT16_MAX, 9213, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9215, UINT16_MAX, 9215, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9217, UINT16_MAX, 9217, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9219, UINT16_MAX, 9219, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9221, UINT16_MAX, 9221, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9223, UINT16_MAX, 9223, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9225, UINT16_MAX, 9225, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9227, UINT16_MAX, 9227, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9229, UINT16_MAX, 9229, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9231, UINT16_MAX, 9231, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9233, UINT16_MAX, 9233, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9235, UINT16_MAX, 9235, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9237, UINT16_MAX, 9237, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9239, UINT16_MAX, 9239, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9241, UINT16_MAX, 9241, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9243, UINT16_MAX, 9243, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9245, UINT16_MAX, 9245, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9247, UINT16_MAX, 9247, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9249, UINT16_MAX, 9249, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9251, UINT16_MAX, 9251, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9253, UINT16_MAX, 9253, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9255, UINT16_MAX, 9255, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9257, UINT16_MAX, 9257, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9259, UINT16_MAX, 9259, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9261, UINT16_MAX, 9261, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9263, UINT16_MAX, 9263, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9265, UINT16_MAX, 9265, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9267, UINT16_MAX, 9267, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9269, UINT16_MAX, 9269, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9271, UINT16_MAX, 9271, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6807, UINT16_MAX, 6807, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6809, UINT16_MAX, 6809, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6811, UINT16_MAX, 6811, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6813, UINT16_MAX, 6813, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6815, UINT16_MAX, 6815, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6817, UINT16_MAX, 6817, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6819, UINT16_MAX, 6819, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6821, UINT16_MAX, 6821, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6823, UINT16_MAX, 6823, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6825, UINT16_MAX, 6825, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6827, UINT16_MAX, 6827, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6829, UINT16_MAX, 6829, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6831, UINT16_MAX, 6831, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6833, UINT16_MAX, 6833, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6835, UINT16_MAX, 6835, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6837, UINT16_MAX, 6837, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6839, UINT16_MAX, 6839, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6841, UINT16_MAX, 6841, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6843, UINT16_MAX, 6843, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6845, UINT16_MAX, 6845, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6847, UINT16_MAX, 6847, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6849, UINT16_MAX, 6849, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6851, UINT16_MAX, 6851, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6853, UINT16_MAX, 6853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6855, UINT16_MAX, 6855, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6857, UINT16_MAX, 6857, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6859, UINT16_MAX, 6859, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6861, UINT16_MAX, 6861, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6863, UINT16_MAX, 6863, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6865, UINT16_MAX, 6865, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6867, UINT16_MAX, 6867, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6869, UINT16_MAX, 6869, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6871, UINT16_MAX, 6871, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6873, UINT16_MAX, 6873, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6875, UINT16_MAX, 6875, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6877, UINT16_MAX, 6877, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9273, UINT16_MAX, 9273, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9275, UINT16_MAX, 9275, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9277, UINT16_MAX, 9277, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9279, UINT16_MAX, 9279, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9281, UINT16_MAX, 9281, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9283, UINT16_MAX, 9283, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9285, UINT16_MAX, 9285, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9287, UINT16_MAX, 9287, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9289, UINT16_MAX, 9289, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9291, UINT16_MAX, 9291, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9293, UINT16_MAX, 9293, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9295, UINT16_MAX, 9295, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9297, UINT16_MAX, 9297, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9299, UINT16_MAX, 9299, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9301, UINT16_MAX, 9301, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9303, UINT16_MAX, 9303, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9305, UINT16_MAX, 9305, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9307, UINT16_MAX, 9307, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9309, UINT16_MAX, 9309, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9311, UINT16_MAX, 9311, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9313, UINT16_MAX, 9313, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9315, UINT16_MAX, 9315, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9317, UINT16_MAX, 9317, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9319, UINT16_MAX, 9319, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9321, UINT16_MAX, 9321, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9323, UINT16_MAX, 9323, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9325, UINT16_MAX, 9325, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9327, UINT16_MAX, 9327, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9329, UINT16_MAX, 9329, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9331, UINT16_MAX, 9331, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9333, UINT16_MAX, 9333, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9335, UINT16_MAX, 9335, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9337, UINT16_MAX, 9337, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9339, UINT16_MAX, 9339, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9341, UINT16_MAX, 9341, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9343, UINT16_MAX, 9343, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6879, UINT16_MAX, 6879, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6881, UINT16_MAX, 6881, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6883, UINT16_MAX, 6883, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6885, UINT16_MAX, 6885, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6887, UINT16_MAX, 6887, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6889, UINT16_MAX, 6889, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6891, UINT16_MAX, 6891, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6893, UINT16_MAX, 6893, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6895, UINT16_MAX, 6895, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6897, UINT16_MAX, 6897, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6899, UINT16_MAX, 6899, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6901, UINT16_MAX, 6901, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6903, UINT16_MAX, 6903, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6905, UINT16_MAX, 6905, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6907, UINT16_MAX, 6907, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6909, UINT16_MAX, 6909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6911, UINT16_MAX, 6911, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6913, UINT16_MAX, 6913, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6915, UINT16_MAX, 6915, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6917, UINT16_MAX, 6917, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6919, UINT16_MAX, 6919, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6921, UINT16_MAX, 6921, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6923, UINT16_MAX, 6923, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6925, UINT16_MAX, 6925, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6927, UINT16_MAX, 6927, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6929, UINT16_MAX, 6929, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6931, UINT16_MAX, 6931, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6933, UINT16_MAX, 6933, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6935, UINT16_MAX, 6935, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6937, UINT16_MAX, 6937, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6939, UINT16_MAX, 6939, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6941, UINT16_MAX, 6941, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6943, UINT16_MAX, 6943, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6945, UINT16_MAX, 6945, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6947, UINT16_MAX, 6947, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6949, UINT16_MAX, 6949, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6951, UINT16_MAX, 6951, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6953, UINT16_MAX, 6953, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6955, UINT16_MAX, 6955, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6957, UINT16_MAX, 6957, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6959, UINT16_MAX, 6959, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6961, UINT16_MAX, 6961, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6963, UINT16_MAX, 6963, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6965, UINT16_MAX, 6965, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6967, UINT16_MAX, 6967, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6969, UINT16_MAX, 6969, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6971, UINT16_MAX, 6971, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6973, UINT16_MAX, 6973, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6975, UINT16_MAX, 6975, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6977, UINT16_MAX, 6977, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6979, UINT16_MAX, 6979, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9345, UINT16_MAX, 9345, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9347, UINT16_MAX, 9347, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9349, UINT16_MAX, 9349, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9351, UINT16_MAX, 9351, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9353, UINT16_MAX, 9353, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9355, UINT16_MAX, 9355, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9357, UINT16_MAX, 9357, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9359, UINT16_MAX, 9359, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9361, UINT16_MAX, 9361, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9363, UINT16_MAX, 9363, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9365, UINT16_MAX, 9365, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9367, UINT16_MAX, 9367, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9369, UINT16_MAX, 9369, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9371, UINT16_MAX, 9371, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9373, UINT16_MAX, 9373, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9375, UINT16_MAX, 9375, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9377, UINT16_MAX, 9377, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9379, UINT16_MAX, 9379, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9381, UINT16_MAX, 9381, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9383, UINT16_MAX, 9383, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9385, UINT16_MAX, 9385, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9387, UINT16_MAX, 9387, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9389, UINT16_MAX, 9389, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9391, UINT16_MAX, 9391, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9393, UINT16_MAX, 9393, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9395, UINT16_MAX, 9395, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9397, UINT16_MAX, 9397, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9399, UINT16_MAX, 9399, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9401, UINT16_MAX, 9401, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9403, UINT16_MAX, 9403, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9405, UINT16_MAX, 9405, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9407, UINT16_MAX, 9407, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9409, UINT16_MAX, 9409, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9411, UINT16_MAX, 9411, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9413, UINT16_MAX, 9413, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9415, UINT16_MAX, 9415, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9417, UINT16_MAX, 9417, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9419, UINT16_MAX, 9419, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9421, UINT16_MAX, 9421, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9423, UINT16_MAX, 9423, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9425, UINT16_MAX, 9425, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9427, UINT16_MAX, 9427, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9429, UINT16_MAX, 9429, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9431, UINT16_MAX, 9431, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9433, UINT16_MAX, 9433, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9435, UINT16_MAX, 9435, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9437, UINT16_MAX, 9437, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9439, UINT16_MAX, 9439, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9441, UINT16_MAX, 9441, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9443, UINT16_MAX, 9443, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9445, UINT16_MAX, 9445, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5328, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5332, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5336, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49206, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49208, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 15185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 15189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5340, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5344, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49210, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5348, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49212, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49216, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5354, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49214, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49218, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49220, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5362, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5366, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7029, UINT16_MAX, 7029, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7031, UINT16_MAX, 7031, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7033, UINT16_MAX, 7033, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7035, UINT16_MAX, 7035, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7037, UINT16_MAX, 7037, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7039, UINT16_MAX, 7039, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7041, UINT16_MAX, 7041, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7043, UINT16_MAX, 7043, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7045, UINT16_MAX, 7045, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7047, UINT16_MAX, 7047, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7049, UINT16_MAX, 7049, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7051, UINT16_MAX, 7051, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7053, UINT16_MAX, 7053, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7055, UINT16_MAX, 7055, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7057, UINT16_MAX, 7057, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7059, UINT16_MAX, 7059, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7061, UINT16_MAX, 7061, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7063, UINT16_MAX, 7063, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7065, UINT16_MAX, 7065, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7067, UINT16_MAX, 7067, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7069, UINT16_MAX, 7069, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7071, UINT16_MAX, 7071, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7073, UINT16_MAX, 7073, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7075, UINT16_MAX, 7075, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7077, UINT16_MAX, 7077, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7079, UINT16_MAX, 7079, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7081, UINT16_MAX, 7081, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7083, UINT16_MAX, 7083, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7085, UINT16_MAX, 7085, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7087, UINT16_MAX, 7087, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7089, UINT16_MAX, 7089, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7091, UINT16_MAX, 7091, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9447, UINT16_MAX, 9447, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9449, UINT16_MAX, 9449, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9451, UINT16_MAX, 9451, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9453, UINT16_MAX, 9453, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9455, UINT16_MAX, 9455, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9457, UINT16_MAX, 9457, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9459, UINT16_MAX, 9459, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9461, UINT16_MAX, 9461, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9463, UINT16_MAX, 9463, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9465, UINT16_MAX, 9465, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9467, UINT16_MAX, 9467, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9469, UINT16_MAX, 9469, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9471, UINT16_MAX, 9471, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9473, UINT16_MAX, 9473, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9475, UINT16_MAX, 9475, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9477, UINT16_MAX, 9477, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9479, UINT16_MAX, 9479, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9481, UINT16_MAX, 9481, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9483, UINT16_MAX, 9483, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9485, UINT16_MAX, 9485, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9487, UINT16_MAX, 9487, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9489, UINT16_MAX, 9489, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9491, UINT16_MAX, 9491, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9493, UINT16_MAX, 9493, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9495, UINT16_MAX, 9495, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9497, UINT16_MAX, 9497, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9499, UINT16_MAX, 9499, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9501, UINT16_MAX, 9501, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9503, UINT16_MAX, 9503, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9505, UINT16_MAX, 9505, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9507, UINT16_MAX, 9507, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9509, UINT16_MAX, 9509, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7093, UINT16_MAX, 7093, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7095, UINT16_MAX, 7095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7097, UINT16_MAX, 7097, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7099, UINT16_MAX, 7099, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7101, UINT16_MAX, 7101, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7103, UINT16_MAX, 7103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7105, UINT16_MAX, 7105, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7107, UINT16_MAX, 7107, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7109, UINT16_MAX, 7109, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7111, UINT16_MAX, 7111, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7113, UINT16_MAX, 7113, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7115, UINT16_MAX, 7115, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7117, UINT16_MAX, 7117, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7119, UINT16_MAX, 7119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7121, UINT16_MAX, 7121, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7123, UINT16_MAX, 7123, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7125, UINT16_MAX, 7125, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7127, UINT16_MAX, 7127, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7129, UINT16_MAX, 7129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7131, UINT16_MAX, 7131, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7133, UINT16_MAX, 7133, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7135, UINT16_MAX, 7135, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7137, UINT16_MAX, 7137, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7139, UINT16_MAX, 7139, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7141, UINT16_MAX, 7141, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7143, UINT16_MAX, 7143, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7145, UINT16_MAX, 7145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7147, UINT16_MAX, 7147, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7149, UINT16_MAX, 7149, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7151, UINT16_MAX, 7151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7153, UINT16_MAX, 7153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7155, UINT16_MAX, 7155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9511, UINT16_MAX, 9511, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9513, UINT16_MAX, 9513, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9515, UINT16_MAX, 9515, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9517, UINT16_MAX, 9517, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9519, UINT16_MAX, 9519, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9521, UINT16_MAX, 9521, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9523, UINT16_MAX, 9523, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9525, UINT16_MAX, 9525, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9527, UINT16_MAX, 9527, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9529, UINT16_MAX, 9529, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9531, UINT16_MAX, 9531, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9533, UINT16_MAX, 9533, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9535, UINT16_MAX, 9535, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9537, UINT16_MAX, 9537, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9539, UINT16_MAX, 9539, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9541, UINT16_MAX, 9541, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9543, UINT16_MAX, 9543, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9545, UINT16_MAX, 9545, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9547, UINT16_MAX, 9547, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9549, UINT16_MAX, 9549, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9551, UINT16_MAX, 9551, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9553, UINT16_MAX, 9553, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9555, UINT16_MAX, 9555, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9557, UINT16_MAX, 9557, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9559, UINT16_MAX, 9559, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9561, UINT16_MAX, 9561, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9563, UINT16_MAX, 9563, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9565, UINT16_MAX, 9565, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9567, UINT16_MAX, 9567, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9569, UINT16_MAX, 9569, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9571, UINT16_MAX, 9571, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9573, UINT16_MAX, 9573, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5370, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5374, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5378, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15369, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49222, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 226, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49224, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49226, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49228, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49230, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49232, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5390, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5394, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5398, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15381, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5404, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15385, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15389, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15393, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15397, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7214, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7215, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7218, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, 7231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7239, UINT16_MAX, 7239, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7241, UINT16_MAX, 7241, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7243, UINT16_MAX, 7243, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7245, UINT16_MAX, 7245, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7247, UINT16_MAX, 7247, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7249, UINT16_MAX, 7249, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7251, UINT16_MAX, 7251, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7253, UINT16_MAX, 7253, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7255, UINT16_MAX, 7255, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7257, UINT16_MAX, 7257, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7259, UINT16_MAX, 7259, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7261, UINT16_MAX, 7261, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7263, UINT16_MAX, 7263, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7265, UINT16_MAX, 7265, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7267, UINT16_MAX, 7267, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7269, UINT16_MAX, 7269, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7271, UINT16_MAX, 7271, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7273, UINT16_MAX, 7273, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7275, UINT16_MAX, 7275, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7277, UINT16_MAX, 7277, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7279, UINT16_MAX, 7279, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7281, UINT16_MAX, 7281, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7283, UINT16_MAX, 7283, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7285, UINT16_MAX, 7285, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7287, UINT16_MAX, 7287, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7289, UINT16_MAX, 7289, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7291, UINT16_MAX, 7291, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7293, UINT16_MAX, 7293, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7295, UINT16_MAX, 7295, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7297, UINT16_MAX, 7297, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7299, UINT16_MAX, 7299, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7301, UINT16_MAX, 7301, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7303, UINT16_MAX, 7303, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7305, UINT16_MAX, 7305, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9575, UINT16_MAX, 9575, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9577, UINT16_MAX, 9577, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9579, UINT16_MAX, 9579, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9581, UINT16_MAX, 9581, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9583, UINT16_MAX, 9583, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9585, UINT16_MAX, 9585, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9587, UINT16_MAX, 9587, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9589, UINT16_MAX, 9589, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9591, UINT16_MAX, 9591, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9593, UINT16_MAX, 9593, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9595, UINT16_MAX, 9595, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9597, UINT16_MAX, 9597, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9599, UINT16_MAX, 9599, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9601, UINT16_MAX, 9601, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9603, UINT16_MAX, 9603, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9605, UINT16_MAX, 9605, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9607, UINT16_MAX, 9607, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9609, UINT16_MAX, 9609, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9611, UINT16_MAX, 9611, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9613, UINT16_MAX, 9613, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9615, UINT16_MAX, 9615, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9617, UINT16_MAX, 9617, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9619, UINT16_MAX, 9619, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9621, UINT16_MAX, 9621, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9623, UINT16_MAX, 9623, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9625, UINT16_MAX, 9625, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9627, UINT16_MAX, 9627, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9629, UINT16_MAX, 9629, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9631, UINT16_MAX, 9631, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9633, UINT16_MAX, 9633, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9635, UINT16_MAX, 9635, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9637, UINT16_MAX, 9637, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9639, UINT16_MAX, 9639, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9641, UINT16_MAX, 9641, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 7307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 5786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 7308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 7309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23716, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23719, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23725, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23728, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23731, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23734, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23755, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23788, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23791, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 15605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 15607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 23807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 15620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 15622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 15624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 5425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 7498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 7499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTEND}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7646, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7702, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7704, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7706, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7710, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7712, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7714, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7715, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7716, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7719, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7723, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7724, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7725, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7728, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7731, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7732, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7733, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7735, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7748, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7753, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7755, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7791, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7805, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7816, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7824, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7828, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7831, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7833, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7885, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7893, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7905, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7913, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7927, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7930, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7942, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7945, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7947, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7949, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7951, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7952, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7954, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7955, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7956, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7958, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7959, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7960, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7961, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7962, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7963, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7964, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7965, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7966, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7967, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7969, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7970, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7971, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7973, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7974, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7976, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7978, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7979, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7980, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7984, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7985, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7987, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7989, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7991, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7993, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7997, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7999, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8001, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8002, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8003, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8006, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8007, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8009, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8010, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8011, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8013, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8015, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8017, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8021, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8023, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8029, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8031, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8033, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8037, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8039, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8041, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8043, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8045, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8049, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8051, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8053, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8055, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3646, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8065, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 8067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {0, 0, 0, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false,false,false,false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_S, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_LF, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CR, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5093, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5084, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5096, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 0, UINT16_MAX, 0, UINT16_MAX, 0, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1, UINT16_MAX, 1, UINT16_MAX, 2784, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2, UINT16_MAX, 2, UINT16_MAX, 49, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3, UINT16_MAX, 3, UINT16_MAX, 704, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4, UINT16_MAX, 4, UINT16_MAX, 62, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5, UINT16_MAX, 5, UINT16_MAX, 2872, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6, UINT16_MAX, 6, UINT16_MAX, 782, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7, UINT16_MAX, 7, UINT16_MAX, 808, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8, UINT16_MAX, 8, UINT16_MAX, 111, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9, UINT16_MAX, 9, UINT16_MAX, 898, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 10, UINT16_MAX, 10, UINT16_MAX, 913, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 11, UINT16_MAX, 11, UINT16_MAX, 999, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 12, UINT16_MAX, 12, UINT16_MAX, 2890, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 13, UINT16_MAX, 13, UINT16_MAX, 160, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 14, UINT16_MAX, 14, UINT16_MAX, 205, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 15, UINT16_MAX, 15, UINT16_MAX, 2982, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 16, UINT16_MAX, 16, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 17, UINT16_MAX, 17, UINT16_MAX, 1087, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 18, UINT16_MAX, 18, UINT16_MAX, 1173, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 19, UINT16_MAX, 19, UINT16_MAX, 1257, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 20, UINT16_MAX, 20, UINT16_MAX, 254, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 21, UINT16_MAX, 21, UINT16_MAX, 3042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 22, UINT16_MAX, 22, UINT16_MAX, 1337, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 23, UINT16_MAX, 23, UINT16_MAX, 3122, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 24, UINT16_MAX, 24, UINT16_MAX, 303, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 25, UINT16_MAX, 25, UINT16_MAX, 1423, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 26, UINT16_MAX, 26, 352, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 27, UINT16_MAX, 27, 2818, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 28, UINT16_MAX, 28, 401, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 29, UINT16_MAX, 29, 743, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 30, UINT16_MAX, 30, 414, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 31, UINT16_MAX, 31, 2875, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 32, UINT16_MAX, 32, 795, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 33, UINT16_MAX, 33, 853, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 34, UINT16_MAX, 34, 463, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 35, UINT16_MAX, 35, 901, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 36, UINT16_MAX, 36, 956, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 37, UINT16_MAX, 37, 1043, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 38, UINT16_MAX, 38, 2932, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 39, UINT16_MAX, 39, 512, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 40, UINT16_MAX, 40, 557, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 41, UINT16_MAX, 41, 2994, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 42, UINT16_MAX, 42, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 43, UINT16_MAX, 43, 1130, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 44, UINT16_MAX, 44, 1215, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 45, UINT16_MAX, 45, 1296, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 46, UINT16_MAX, 46, 606, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 47, UINT16_MAX, 47, 3082, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 48, UINT16_MAX, 48, 1380, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 49, UINT16_MAX, 49, 3131, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 50, UINT16_MAX, 50, 655, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 51, UINT16_MAX, 51, 1466, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_NOBREAK, 52, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 16437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 1621, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 0, UINT16_MAX, 55, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PI, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 1, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 16440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 58, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 59, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 16444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 62, 62, 63, UINT16_MAX, 63, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 16448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 66, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 14, UINT16_MAX, 67, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 32836, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 32839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 32842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16461, 79, UINT16_MAX, 79, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16464, 82, UINT16_MAX, 82, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16467, 85, UINT16_MAX, 85, UINT16_MAX, 3143, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16470, 88, UINT16_MAX, 88, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16473, 91, UINT16_MAX, 91, UINT16_MAX, 1537, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16476, 94, UINT16_MAX, 94, UINT16_MAX, 1579, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 95, UINT16_MAX, 95, UINT16_MAX, 1549, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16480, 98, UINT16_MAX, 98, UINT16_MAX, 2852, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16483, 101, UINT16_MAX, 101, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16486, 104, UINT16_MAX, 104, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16489, 107, UINT16_MAX, 107, UINT16_MAX, 3357, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16492, 110, UINT16_MAX, 110, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16495, 113, UINT16_MAX, 113, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16498, 116, UINT16_MAX, 116, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16501, 119, UINT16_MAX, 119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16504, 122, UINT16_MAX, 122, UINT16_MAX, 2878, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 123, UINT16_MAX, 123, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16508, 126, UINT16_MAX, 126, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16511, 129, UINT16_MAX, 129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16514, 132, UINT16_MAX, 132, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16517, 135, UINT16_MAX, 135, UINT16_MAX, 3461, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16520, 138, UINT16_MAX, 138, UINT16_MAX, 1597, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16523, 141, UINT16_MAX, 141, UINT16_MAX, 1591, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 142, UINT16_MAX, 142, UINT16_MAX, 1585, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16527, 145, UINT16_MAX, 145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16530, 148, UINT16_MAX, 148, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16533, 151, UINT16_MAX, 151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16536, 154, UINT16_MAX, 154, UINT16_MAX, 1509, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16539, 157, UINT16_MAX, 157, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 158, UINT16_MAX, 158, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 16543, 161, UINT16_MAX, 161, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16546, UINT16_MAX, 164, UINT16_MAX, 164, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16549, UINT16_MAX, 167, UINT16_MAX, 167, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16552, UINT16_MAX, 170, UINT16_MAX, 170, 3192, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16555, UINT16_MAX, 173, UINT16_MAX, 173, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16558, UINT16_MAX, 176, UINT16_MAX, 176, 1540, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16561, UINT16_MAX, 179, UINT16_MAX, 179, 1582, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 180, UINT16_MAX, 180, 1558, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16565, UINT16_MAX, 183, UINT16_MAX, 183, 2855, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16568, UINT16_MAX, 186, UINT16_MAX, 186, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16571, UINT16_MAX, 189, UINT16_MAX, 189, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16574, UINT16_MAX, 192, UINT16_MAX, 192, 3406, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16577, UINT16_MAX, 195, UINT16_MAX, 195, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16580, UINT16_MAX, 198, UINT16_MAX, 198, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16583, UINT16_MAX, 201, UINT16_MAX, 201, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16586, UINT16_MAX, 204, UINT16_MAX, 204, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16589, UINT16_MAX, 207, UINT16_MAX, 207, 2881, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 208, UINT16_MAX, 208, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16593, UINT16_MAX, 211, UINT16_MAX, 211, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16596, UINT16_MAX, 214, UINT16_MAX, 214, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16599, UINT16_MAX, 217, UINT16_MAX, 217, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16602, UINT16_MAX, 220, UINT16_MAX, 220, 3510, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16605, UINT16_MAX, 223, UINT16_MAX, 223, 1606, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16608, UINT16_MAX, 226, UINT16_MAX, 226, 1594, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 227, UINT16_MAX, 227, 1588, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16612, UINT16_MAX, 230, UINT16_MAX, 230, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16615, UINT16_MAX, 233, UINT16_MAX, 233, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16618, UINT16_MAX, 236, UINT16_MAX, 236, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16621, UINT16_MAX, 239, UINT16_MAX, 239, 1523, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16624, UINT16_MAX, 242, UINT16_MAX, 242, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 243, UINT16_MAX, 243, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16628, UINT16_MAX, 246, UINT16_MAX, 246, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16631, 249, UINT16_MAX, 249, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16634, UINT16_MAX, 252, UINT16_MAX, 252, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16637, 255, UINT16_MAX, 255, UINT16_MAX, 3259, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16640, UINT16_MAX, 258, UINT16_MAX, 258, 3308, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16643, 261, UINT16_MAX, 261, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16646, UINT16_MAX, 264, UINT16_MAX, 264, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16649, 267, UINT16_MAX, 267, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16652, UINT16_MAX, 270, UINT16_MAX, 270, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16655, 273, UINT16_MAX, 273, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16658, UINT16_MAX, 276, UINT16_MAX, 276, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16661, 279, UINT16_MAX, 279, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16664, UINT16_MAX, 282, UINT16_MAX, 282, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16667, 285, UINT16_MAX, 285, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16670, UINT16_MAX, 288, UINT16_MAX, 288, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16673, 291, UINT16_MAX, 291, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16676, UINT16_MAX, 294, UINT16_MAX, 294, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 295, UINT16_MAX, 295, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 296, UINT16_MAX, 296, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16681, 299, UINT16_MAX, 299, UINT16_MAX, 2858, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16684, UINT16_MAX, 302, UINT16_MAX, 302, 2862, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16687, 305, UINT16_MAX, 305, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16690, UINT16_MAX, 308, UINT16_MAX, 308, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16693, 311, UINT16_MAX, 311, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16696, UINT16_MAX, 314, UINT16_MAX, 314, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16699, 317, UINT16_MAX, 317, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16702, UINT16_MAX, 320, UINT16_MAX, 320, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16705, 323, UINT16_MAX, 323, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16708, UINT16_MAX, 326, UINT16_MAX, 326, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16711, 329, UINT16_MAX, 329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16714, UINT16_MAX, 332, UINT16_MAX, 332, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16717, 335, UINT16_MAX, 335, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16720, UINT16_MAX, 338, UINT16_MAX, 338, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16723, 341, UINT16_MAX, 341, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16726, UINT16_MAX, 344, UINT16_MAX, 344, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16729, 347, UINT16_MAX, 347, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16732, UINT16_MAX, 350, UINT16_MAX, 350, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16735, 353, UINT16_MAX, 353, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16738, UINT16_MAX, 356, UINT16_MAX, 356, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 357, UINT16_MAX, 357, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 358, UINT16_MAX, 358, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16743, 361, UINT16_MAX, 361, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16746, UINT16_MAX, 364, UINT16_MAX, 364, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16749, 367, UINT16_MAX, 367, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16752, UINT16_MAX, 370, UINT16_MAX, 370, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16755, 373, UINT16_MAX, 373, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16758, UINT16_MAX, 376, UINT16_MAX, 376, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16761, 379, UINT16_MAX, 379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16764, UINT16_MAX, 382, UINT16_MAX, 382, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16767, 16769, UINT16_MAX, 8, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 34, UINT16_MAX, 34, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16771, 389, UINT16_MAX, 389, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16774, UINT16_MAX, 392, UINT16_MAX, 392, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16777, 395, UINT16_MAX, 395, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16780, UINT16_MAX, 398, UINT16_MAX, 398, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16783, 401, UINT16_MAX, 401, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16786, UINT16_MAX, 404, UINT16_MAX, 404, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 405, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16790, 408, UINT16_MAX, 408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16793, UINT16_MAX, 411, UINT16_MAX, 411, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16796, 414, UINT16_MAX, 414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16799, UINT16_MAX, 417, UINT16_MAX, 417, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16802, 420, UINT16_MAX, 420, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16805, UINT16_MAX, 423, UINT16_MAX, 423, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16808, 426, UINT16_MAX, 426, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16811, UINT16_MAX, 429, UINT16_MAX, 429, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 430, UINT16_MAX, 430, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 431, UINT16_MAX, 431, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16816, 434, UINT16_MAX, 434, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16819, UINT16_MAX, 437, UINT16_MAX, 437, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16822, 440, UINT16_MAX, 440, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16825, UINT16_MAX, 443, UINT16_MAX, 443, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16828, 446, UINT16_MAX, 446, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16831, UINT16_MAX, 449, UINT16_MAX, 449, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 16834, 16834, 452, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 453, UINT16_MAX, 453, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 454, UINT16_MAX, 454, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16839, 457, UINT16_MAX, 457, UINT16_MAX, 2974, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16842, UINT16_MAX, 460, UINT16_MAX, 460, 2978, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16845, 463, UINT16_MAX, 463, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16848, UINT16_MAX, 466, UINT16_MAX, 466, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16851, 469, UINT16_MAX, 469, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16854, UINT16_MAX, 472, UINT16_MAX, 472, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 473, UINT16_MAX, 473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 474, UINT16_MAX, 474, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16859, 477, UINT16_MAX, 477, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16862, UINT16_MAX, 480, UINT16_MAX, 480, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16865, 483, UINT16_MAX, 483, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16868, UINT16_MAX, 486, UINT16_MAX, 486, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16871, 489, UINT16_MAX, 489, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16874, UINT16_MAX, 492, UINT16_MAX, 492, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16877, 495, UINT16_MAX, 495, UINT16_MAX, 3012, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16880, UINT16_MAX, 498, UINT16_MAX, 498, 3015, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16883, 501, UINT16_MAX, 501, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16886, UINT16_MAX, 504, UINT16_MAX, 504, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16889, 507, UINT16_MAX, 507, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16892, UINT16_MAX, 510, UINT16_MAX, 510, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16895, 513, UINT16_MAX, 513, UINT16_MAX, 3018, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16898, UINT16_MAX, 516, UINT16_MAX, 516, 3021, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16901, 519, UINT16_MAX, 519, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16904, UINT16_MAX, 522, UINT16_MAX, 522, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16907, 525, UINT16_MAX, 525, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16910, UINT16_MAX, 528, UINT16_MAX, 528, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 529, UINT16_MAX, 529, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 530, UINT16_MAX, 530, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16915, 533, UINT16_MAX, 533, UINT16_MAX, 3030, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16918, UINT16_MAX, 536, UINT16_MAX, 536, 3033, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16921, 539, UINT16_MAX, 539, UINT16_MAX, 3036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16924, UINT16_MAX, 542, UINT16_MAX, 542, 3039, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16927, 545, UINT16_MAX, 545, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16930, UINT16_MAX, 548, UINT16_MAX, 548, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16933, 551, UINT16_MAX, 551, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16936, UINT16_MAX, 554, UINT16_MAX, 554, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16939, 557, UINT16_MAX, 557, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16942, UINT16_MAX, 560, UINT16_MAX, 560, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16945, 563, UINT16_MAX, 563, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16948, UINT16_MAX, 566, UINT16_MAX, 566, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16951, 569, UINT16_MAX, 569, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16954, UINT16_MAX, 572, UINT16_MAX, 572, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16957, 575, UINT16_MAX, 575, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16960, UINT16_MAX, 578, UINT16_MAX, 578, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16963, 581, UINT16_MAX, 581, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16966, 584, UINT16_MAX, 584, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16969, UINT16_MAX, 587, UINT16_MAX, 587, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16972, 590, UINT16_MAX, 590, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16975, UINT16_MAX, 593, UINT16_MAX, 593, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 16978, 596, UINT16_MAX, 596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 16981, UINT16_MAX, 599, UINT16_MAX, 599, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 18, 18, 44, UINT16_MAX, 44, 3140, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 600, UINT16_MAX, 600, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 601, UINT16_MAX, 601, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 602, UINT16_MAX, 602, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 603, UINT16_MAX, 603, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 604, UINT16_MAX, 604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 605, UINT16_MAX, 605, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 606, UINT16_MAX, 606, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 607, UINT16_MAX, 607, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 608, UINT16_MAX, 608, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 609, UINT16_MAX, 609, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 610, UINT16_MAX, 610, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 611, UINT16_MAX, 611, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 612, UINT16_MAX, 612, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 613, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 614, UINT16_MAX, 614, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 615, UINT16_MAX, 615, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 616, UINT16_MAX, 616, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 617, UINT16_MAX, 617, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 618, UINT16_MAX, 618, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 619, UINT16_MAX, 619, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 620, UINT16_MAX, 620, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 621, UINT16_MAX, 621, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 622, UINT16_MAX, 622, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 623, UINT16_MAX, 623, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 624, UINT16_MAX, 624, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 625, UINT16_MAX, 625, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 626, UINT16_MAX, 626, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 627, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 628, UINT16_MAX, 628, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 629, UINT16_MAX, 629, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 630, UINT16_MAX, 630, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 631, UINT16_MAX, 631, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17016, 634, UINT16_MAX, 634, UINT16_MAX, 3565, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17019, UINT16_MAX, 637, UINT16_MAX, 637, 3614, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 638, UINT16_MAX, 638, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 639, UINT16_MAX, 639, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 640, UINT16_MAX, 640, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 641, UINT16_MAX, 641, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 642, UINT16_MAX, 642, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 643, UINT16_MAX, 643, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 644, UINT16_MAX, 644, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 645, UINT16_MAX, 645, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 646, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 647, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 648, UINT16_MAX, 648, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 649, UINT16_MAX, 649, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 650, UINT16_MAX, 650, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17035, 653, UINT16_MAX, 653, UINT16_MAX, 3663, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17038, UINT16_MAX, 656, UINT16_MAX, 656, 3712, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 657, UINT16_MAX, 657, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 658, UINT16_MAX, 658, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 659, UINT16_MAX, 659, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 660, UINT16_MAX, 660, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 661, UINT16_MAX, 661, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 662, UINT16_MAX, 662, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 663, UINT16_MAX, 663, UINT16_MAX, 1573, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 664, UINT16_MAX, 664, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 665, UINT16_MAX, 665, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 666, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 667, UINT16_MAX, 667, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 668, UINT16_MAX, 668, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 669, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 670, UINT16_MAX, 670, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17055, 673, UINT16_MAX, 673, 674, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17059, 673, 677, 673, 674, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17062, UINT16_MAX, 677, UINT16_MAX, 674, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17064, 682, UINT16_MAX, 682, 683, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17068, 682, 686, 682, 683, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17071, UINT16_MAX, 686, UINT16_MAX, 683, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17073, 691, UINT16_MAX, 691, 692, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17077, 691, 695, 691, 692, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17080, UINT16_MAX, 695, UINT16_MAX, 692, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17082, 700, UINT16_MAX, 700, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17085, UINT16_MAX, 703, UINT16_MAX, 703, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17088, 706, UINT16_MAX, 706, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17091, UINT16_MAX, 709, UINT16_MAX, 709, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17094, 712, UINT16_MAX, 712, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17097, UINT16_MAX, 715, UINT16_MAX, 715, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17100, 718, UINT16_MAX, 718, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17103, UINT16_MAX, 721, UINT16_MAX, 721, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17106, 724, UINT16_MAX, 724, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17109, UINT16_MAX, 727, UINT16_MAX, 727, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17112, 730, UINT16_MAX, 730, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17115, UINT16_MAX, 733, UINT16_MAX, 733, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17118, 736, UINT16_MAX, 736, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17121, UINT16_MAX, 739, UINT16_MAX, 739, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17124, 742, UINT16_MAX, 742, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17127, UINT16_MAX, 745, UINT16_MAX, 745, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 746, UINT16_MAX, 746, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17131, 749, UINT16_MAX, 749, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17134, UINT16_MAX, 752, UINT16_MAX, 752, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17137, 755, UINT16_MAX, 755, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17140, UINT16_MAX, 758, UINT16_MAX, 758, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17143, 761, UINT16_MAX, 761, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17146, UINT16_MAX, 764, UINT16_MAX, 764, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 765, UINT16_MAX, 765, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 766, UINT16_MAX, 766, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17151, 769, UINT16_MAX, 769, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17154, UINT16_MAX, 772, UINT16_MAX, 772, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17157, 775, UINT16_MAX, 775, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17160, UINT16_MAX, 778, UINT16_MAX, 778, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17163, 781, UINT16_MAX, 781, UINT16_MAX, 1567, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17166, UINT16_MAX, 784, UINT16_MAX, 784, 1570, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17169, 787, UINT16_MAX, 787, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17172, UINT16_MAX, 790, UINT16_MAX, 790, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17175, 793, UINT16_MAX, 793, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17178, UINT16_MAX, 796, UINT16_MAX, 796, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17181, 17181, 799, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17184, 802, UINT16_MAX, 802, 803, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17188, 802, 806, 802, 803, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17191, UINT16_MAX, 806, UINT16_MAX, 803, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17193, 811, UINT16_MAX, 811, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17196, UINT16_MAX, 814, UINT16_MAX, 814, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 815, UINT16_MAX, 815, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 816, UINT16_MAX, 816, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17201, 819, UINT16_MAX, 819, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17204, UINT16_MAX, 822, UINT16_MAX, 822, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17207, 825, UINT16_MAX, 825, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17210, UINT16_MAX, 828, UINT16_MAX, 828, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17213, 831, UINT16_MAX, 831, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17216, UINT16_MAX, 834, UINT16_MAX, 834, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17219, 837, UINT16_MAX, 837, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17222, UINT16_MAX, 840, UINT16_MAX, 840, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17225, 843, UINT16_MAX, 843, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17228, UINT16_MAX, 846, UINT16_MAX, 846, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17231, 849, UINT16_MAX, 849, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17234, UINT16_MAX, 852, UINT16_MAX, 852, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17237, 855, UINT16_MAX, 855, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17240, UINT16_MAX, 858, UINT16_MAX, 858, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17243, 861, UINT16_MAX, 861, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17246, UINT16_MAX, 864, UINT16_MAX, 864, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17249, 867, UINT16_MAX, 867, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17252, UINT16_MAX, 870, UINT16_MAX, 870, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17255, 873, UINT16_MAX, 873, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17258, UINT16_MAX, 876, UINT16_MAX, 876, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17261, 879, UINT16_MAX, 879, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17264, UINT16_MAX, 882, UINT16_MAX, 882, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17267, 885, UINT16_MAX, 885, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17270, UINT16_MAX, 888, UINT16_MAX, 888, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17273, 891, UINT16_MAX, 891, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17276, UINT16_MAX, 894, UINT16_MAX, 894, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17279, 897, UINT16_MAX, 897, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17282, UINT16_MAX, 900, UINT16_MAX, 900, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17285, 903, UINT16_MAX, 903, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17288, UINT16_MAX, 906, UINT16_MAX, 906, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17291, 909, UINT16_MAX, 909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17294, UINT16_MAX, 912, UINT16_MAX, 912, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17297, 915, UINT16_MAX, 915, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17300, UINT16_MAX, 918, UINT16_MAX, 918, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17303, 921, UINT16_MAX, 921, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17306, UINT16_MAX, 924, UINT16_MAX, 924, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 925, UINT16_MAX, 925, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 926, UINT16_MAX, 926, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17311, 929, UINT16_MAX, 929, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17314, UINT16_MAX, 932, UINT16_MAX, 932, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 933, UINT16_MAX, 933, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 934, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 935, UINT16_MAX, 935, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 936, UINT16_MAX, 936, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 937, UINT16_MAX, 937, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 938, UINT16_MAX, 938, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17323, 941, UINT16_MAX, 941, UINT16_MAX, 1543, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17326, UINT16_MAX, 944, UINT16_MAX, 944, 1546, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17329, 947, UINT16_MAX, 947, UINT16_MAX, 2866, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17332, UINT16_MAX, 950, UINT16_MAX, 950, 2869, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17335, 953, UINT16_MAX, 953, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17338, UINT16_MAX, 956, UINT16_MAX, 956, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17341, 959, UINT16_MAX, 959, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17344, UINT16_MAX, 962, UINT16_MAX, 962, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17347, 965, UINT16_MAX, 965, UINT16_MAX, 1615, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17350, UINT16_MAX, 968, UINT16_MAX, 968, 1618, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17353, 971, UINT16_MAX, 971, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17356, UINT16_MAX, 974, UINT16_MAX, 974, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17359, 977, UINT16_MAX, 977, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17362, UINT16_MAX, 980, UINT16_MAX, 980, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 981, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 982, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 983, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 984, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 985, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 986, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 987, UINT16_MAX, 987, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 988, UINT16_MAX, 988, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 989, UINT16_MAX, 989, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 990, UINT16_MAX, 990, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 991, UINT16_MAX, 991, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 992, UINT16_MAX, 992, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 993, UINT16_MAX, 993, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 994, UINT16_MAX, 994, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 995, UINT16_MAX, 995, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 996, UINT16_MAX, 996, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 997, UINT16_MAX, 997, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 998, UINT16_MAX, 998, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 999, UINT16_MAX, 999, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1000, UINT16_MAX, 1000, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1001, UINT16_MAX, 1001, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1002, UINT16_MAX, 1002, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1003, UINT16_MAX, 1003, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1004, UINT16_MAX, 1004, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1005, UINT16_MAX, 1005, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1006, UINT16_MAX, 1006, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1007, UINT16_MAX, 1007, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1008, UINT16_MAX, 1008, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1009, UINT16_MAX, 1009, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1010, UINT16_MAX, 1010, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1011, UINT16_MAX, 1011, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1012, UINT16_MAX, 1012, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1013, UINT16_MAX, 1013, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1014, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1015, UINT16_MAX, 1015, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1016, UINT16_MAX, 1016, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1017, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1018, UINT16_MAX, 1018, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1019, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1020, UINT16_MAX, 1020, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1021, UINT16_MAX, 1021, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1022, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1023, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1024, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1025, UINT16_MAX, 1025, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1026, UINT16_MAX, 1026, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1027, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1028, UINT16_MAX, 1028, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1029, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1030, UINT16_MAX, 1030, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1031, UINT16_MAX, 1031, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1032, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1033, UINT16_MAX, 1033, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1034, UINT16_MAX, 1034, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1035, UINT16_MAX, 1035, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1036, UINT16_MAX, 1036, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1037, UINT16_MAX, 1037, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1038, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1039, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1040, UINT16_MAX, 1040, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1041, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1042, UINT16_MAX, 1042, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1043, UINT16_MAX, 1043, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1044, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1045, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1046, UINT16_MAX, 1046, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1047, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1048, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1049, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1050, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1051, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1052, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1053, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1054, UINT16_MAX, 1054, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1055, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1056, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1057, UINT16_MAX, 1057, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1058, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1059, UINT16_MAX, 1059, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1060, UINT16_MAX, 1060, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1061, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1062, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1063, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1064, UINT16_MAX, 1064, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1065, UINT16_MAX, 1065, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1066, UINT16_MAX, 1066, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1067, UINT16_MAX, 1067, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1068, UINT16_MAX, 1068, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1069, UINT16_MAX, 1069, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1070, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1071, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1072, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1073, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1074, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1075, UINT16_MAX, 1075, 1576, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1076, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1077, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1078, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1079, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1080, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1081, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1082, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1083, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1084, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1085, UINT16_MAX, 1085, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1086, UINT16_MAX, 1086, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1087, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1088, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1089, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1090, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1091, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1092, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1093, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1094, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1095, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1096, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1097, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1098, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1099, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1100, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1101, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1102, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1103, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7, UINT16_MAX, 1104, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1105, UINT16_MAX, 1106, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 9, UINT16_MAX, 1107, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 17, UINT16_MAX, 1108, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1050, UINT16_MAX, 1109, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1052, UINT16_MAX, 1110, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1058, UINT16_MAX, 1111, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 22, UINT16_MAX, 1112, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 24, UINT16_MAX, 1113, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1114, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1115, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 17510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 620, UINT16_MAX, 1128, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 11, UINT16_MAX, 1129, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 18, UINT16_MAX, 1130, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 23, UINT16_MAX, 1131, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1077, UINT16_MAX, 1132, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32768, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32769, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32770, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32771, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32775, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32776, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32778, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32772, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32814, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32773, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32780, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32779, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32782, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32783, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32815, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32816, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 232, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32781, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32808, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32813, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32807, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32784, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32774, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32777, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32810, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32812, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32811, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32809, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32819, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 1133, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 1134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32817, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 1135, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 17520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 240, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, 1138, 1139, UINT16_MAX, 1139, 32818, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 233, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 234, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1140, UINT16_MAX, 1140, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1141, UINT16_MAX, 1141, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1142, UINT16_MAX, 1142, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1143, UINT16_MAX, 1143, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 1144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1145, UINT16_MAX, 1145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1146, UINT16_MAX, 1146, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 17531, UINT16_MAX, 1149, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1150, UINT16_MAX, 1150, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1151, UINT16_MAX, 1151, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1152, UINT16_MAX, 1152, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 1153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1154, UINT16_MAX, 1154, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 17539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17541, 1159, UINT16_MAX, 1159, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 1160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17545, 1163, UINT16_MAX, 1163, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17548, 1166, UINT16_MAX, 1166, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17551, 1169, UINT16_MAX, 1169, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17554, 1172, UINT16_MAX, 1172, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17557, 1175, UINT16_MAX, 1175, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17560, 1178, UINT16_MAX, 1178, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17563, 33949, 1184, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1185, UINT16_MAX, 1185, UINT16_MAX, 1673, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1186, UINT16_MAX, 1186, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1187, UINT16_MAX, 1187, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1188, UINT16_MAX, 1188, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1189, UINT16_MAX, 1189, UINT16_MAX, 1726, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1190, UINT16_MAX, 1190, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1191, UINT16_MAX, 1191, UINT16_MAX, 1777, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1192, UINT16_MAX, 1192, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1138, UINT16_MAX, 1138, UINT16_MAX, 1830, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1193, UINT16_MAX, 1193, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1194, UINT16_MAX, 1194, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 62, UINT16_MAX, 62, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1195, UINT16_MAX, 1195, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1196, UINT16_MAX, 1196, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1197, UINT16_MAX, 1197, UINT16_MAX, 1881, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1198, UINT16_MAX, 1198, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1199, UINT16_MAX, 1199, UINT16_MAX, 5027, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1200, UINT16_MAX, 1200, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1201, UINT16_MAX, 1201, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1202, UINT16_MAX, 1202, UINT16_MAX, 1932, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1203, UINT16_MAX, 1203, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1204, UINT16_MAX, 1204, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1205, UINT16_MAX, 1205, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1206, UINT16_MAX, 1206, UINT16_MAX, 1983, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17591, 1209, UINT16_MAX, 1209, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17594, 1212, UINT16_MAX, 1212, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17597, UINT16_MAX, 1215, UINT16_MAX, 1215, 4904, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17600, UINT16_MAX, 1218, UINT16_MAX, 1218, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17603, UINT16_MAX, 1221, UINT16_MAX, 1221, 4913, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17606, UINT16_MAX, 1224, UINT16_MAX, 1224, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17609, 33995, 1230, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1231, UINT16_MAX, 1231, 2088, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1232, UINT16_MAX, 1232, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1233, UINT16_MAX, 1233, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1234, UINT16_MAX, 1234, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1235, UINT16_MAX, 1235, 2141, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1236, UINT16_MAX, 1236, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1237, UINT16_MAX, 1237, 2192, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1238, UINT16_MAX, 1238, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1139, UINT16_MAX, 1139, 2245, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1239, UINT16_MAX, 1239, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1240, UINT16_MAX, 1240, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 63, UINT16_MAX, 63, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1241, UINT16_MAX, 1241, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1242, UINT16_MAX, 1242, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1243, UINT16_MAX, 1243, 2401, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1244, UINT16_MAX, 1244, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1245, UINT16_MAX, 1245, 5023, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1200, 1246, UINT16_MAX, 1246, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1246, UINT16_MAX, 1246, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1247, UINT16_MAX, 1247, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1248, UINT16_MAX, 1248, 2349, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1249, UINT16_MAX, 1249, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1250, UINT16_MAX, 1250, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1251, UINT16_MAX, 1251, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1252, UINT16_MAX, 1252, 2452, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17637, UINT16_MAX, 1255, UINT16_MAX, 1255, 2036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17640, UINT16_MAX, 1258, UINT16_MAX, 1258, 2297, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17643, UINT16_MAX, 1261, UINT16_MAX, 1261, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17646, UINT16_MAX, 1264, UINT16_MAX, 1264, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17649, UINT16_MAX, 1267, UINT16_MAX, 1267, 5033, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1268, UINT16_MAX, 1268, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1186, 1186, 1232, UINT16_MAX, 1232, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1192, 1192, 1238, UINT16_MAX, 1238, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1248, UINT16_MAX, UINT16_MAX, 1269, UINT16_MAX, 2505, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17654, UINT16_MAX, UINT16_MAX, 1272, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17657, UINT16_MAX, UINT16_MAX, 1275, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1203, 1203, 1249, UINT16_MAX, 1249, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1198, 1198, 1244, UINT16_MAX, 1244, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1276, UINT16_MAX, 1276, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1277, UINT16_MAX, 1277, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1278, UINT16_MAX, 1278, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1279, UINT16_MAX, 1279, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1280, UINT16_MAX, 1280, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1281, UINT16_MAX, 1281, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1282, UINT16_MAX, 1282, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1283, UINT16_MAX, 1283, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1284, UINT16_MAX, 1284, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1285, UINT16_MAX, 1285, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1286, UINT16_MAX, 1286, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1287, UINT16_MAX, 1287, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1288, UINT16_MAX, 1288, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1289, UINT16_MAX, 1289, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1290, UINT16_MAX, 1290, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1291, UINT16_MAX, 1291, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1292, UINT16_MAX, 1292, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1293, UINT16_MAX, 1293, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1294, UINT16_MAX, 1294, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1295, UINT16_MAX, 1295, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1296, UINT16_MAX, 1296, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1297, UINT16_MAX, 1297, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1298, UINT16_MAX, 1298, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1299, UINT16_MAX, 1299, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1300, UINT16_MAX, 1300, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1193, 1193, 1239, UINT16_MAX, 1239, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1199, 1199, 1245, UINT16_MAX, 1245, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1301, UINT16_MAX, 1302, UINT16_MAX, 1302, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1303, UINT16_MAX, 1303, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1238, 1192, UINT16_MAX, 1192, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1189, 1189, 1235, UINT16_MAX, 1235, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1304, UINT16_MAX, 1304, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1305, UINT16_MAX, 1305, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1246, 1306, UINT16_MAX, 1306, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1307, UINT16_MAX, 1307, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1308, UINT16_MAX, 1308, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1309, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1310, UINT16_MAX, 1310, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1311, UINT16_MAX, 1311, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1312, UINT16_MAX, 1312, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17697, 1315, UINT16_MAX, 1315, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17700, 1318, UINT16_MAX, 1318, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1319, UINT16_MAX, 1319, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17704, 1322, UINT16_MAX, 1322, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1323, UINT16_MAX, 1323, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1324, UINT16_MAX, 1324, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1325, UINT16_MAX, 1325, UINT16_MAX, 2525, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17710, 1328, UINT16_MAX, 1328, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1329, UINT16_MAX, 1329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1330, UINT16_MAX, 1330, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1331, UINT16_MAX, 1331, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1332, UINT16_MAX, 1332, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17717, 1335, UINT16_MAX, 1335, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17720, 1338, UINT16_MAX, 1338, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17723, 1341, UINT16_MAX, 1341, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1342, UINT16_MAX, 1342, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1343, UINT16_MAX, 1343, UINT16_MAX, 2615, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1344, UINT16_MAX, 1344, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1345, UINT16_MAX, 1345, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1346, UINT16_MAX, 1346, UINT16_MAX, 2522, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1347, UINT16_MAX, 1347, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1348, UINT16_MAX, 1348, UINT16_MAX, 2511, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1349, UINT16_MAX, 1349, UINT16_MAX, 2601, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1350, UINT16_MAX, 1350, UINT16_MAX, 2635, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1351, UINT16_MAX, 1351, UINT16_MAX, 2531, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17736, 1354, UINT16_MAX, 1354, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1355, UINT16_MAX, 1355, UINT16_MAX, 2528, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1356, UINT16_MAX, 1356, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1357, UINT16_MAX, 1357, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1358, UINT16_MAX, 1358, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1359, UINT16_MAX, 1359, UINT16_MAX, 2641, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1360, UINT16_MAX, 1360, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1361, UINT16_MAX, 1361, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1362, UINT16_MAX, 1362, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1363, UINT16_MAX, 1363, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1364, UINT16_MAX, 1364, UINT16_MAX, 2542, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1365, UINT16_MAX, 1365, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1366, UINT16_MAX, 1366, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1367, UINT16_MAX, 1367, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1368, UINT16_MAX, 1368, UINT16_MAX, 2659, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1369, UINT16_MAX, 1369, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1370, UINT16_MAX, 1370, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1371, UINT16_MAX, 1371, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1372, UINT16_MAX, 1372, UINT16_MAX, 2665, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1373, UINT16_MAX, 1373, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1374, UINT16_MAX, 1374, UINT16_MAX, 2653, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1375, UINT16_MAX, 1375, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1376, UINT16_MAX, 1376, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1377, UINT16_MAX, 1377, 2622, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1378, UINT16_MAX, 1378, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1379, UINT16_MAX, 1379, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1380, UINT16_MAX, 1380, 2575, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1381, UINT16_MAX, 1381, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1382, UINT16_MAX, 1382, 2564, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1383, UINT16_MAX, 1383, 2608, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1384, UINT16_MAX, 1384, 2638, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1385, UINT16_MAX, 1385, 2553, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17770, UINT16_MAX, 1388, UINT16_MAX, 1388, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1389, UINT16_MAX, 1389, 2581, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1390, UINT16_MAX, 1390, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1391, UINT16_MAX, 1391, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1392, UINT16_MAX, 1392, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1393, UINT16_MAX, 1393, 2644, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1394, UINT16_MAX, 1394, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1395, UINT16_MAX, 1395, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1396, UINT16_MAX, 1396, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1397, UINT16_MAX, 1397, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1398, UINT16_MAX, 1398, 2584, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1399, UINT16_MAX, 1399, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1400, UINT16_MAX, 1400, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1401, UINT16_MAX, 1401, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1402, UINT16_MAX, 1402, 2662, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1403, UINT16_MAX, 1403, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1404, UINT16_MAX, 1404, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1405, UINT16_MAX, 1405, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1406, UINT16_MAX, 1406, 2668, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1407, UINT16_MAX, 1407, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1408, UINT16_MAX, 1408, 2656, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1409, UINT16_MAX, 1409, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1410, UINT16_MAX, 1410, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17795, UINT16_MAX, 1413, UINT16_MAX, 1413, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17798, UINT16_MAX, 1416, UINT16_MAX, 1416, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1417, UINT16_MAX, 1417, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17802, UINT16_MAX, 1420, UINT16_MAX, 1420, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1421, UINT16_MAX, 1421, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1422, UINT16_MAX, 1422, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1423, UINT16_MAX, 1423, 2578, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17808, UINT16_MAX, 1426, UINT16_MAX, 1426, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1427, UINT16_MAX, 1427, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1428, UINT16_MAX, 1428, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1429, UINT16_MAX, 1429, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1430, UINT16_MAX, 1430, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17815, UINT16_MAX, 1433, UINT16_MAX, 1433, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17818, UINT16_MAX, 1436, UINT16_MAX, 1436, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17821, UINT16_MAX, 1439, UINT16_MAX, 1439, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1440, UINT16_MAX, 1440, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1441, UINT16_MAX, 1441, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1442, UINT16_MAX, 1442, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1443, UINT16_MAX, 1443, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1444, UINT16_MAX, 1444, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1445, UINT16_MAX, 1445, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1446, UINT16_MAX, 1446, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1447, UINT16_MAX, 1447, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1448, UINT16_MAX, 1448, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1449, UINT16_MAX, 1449, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1450, UINT16_MAX, 1450, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1451, UINT16_MAX, 1451, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1452, UINT16_MAX, 1452, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1453, UINT16_MAX, 1453, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1454, UINT16_MAX, 1454, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1455, UINT16_MAX, 1455, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1456, UINT16_MAX, 1456, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1457, UINT16_MAX, 1457, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1458, UINT16_MAX, 1458, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1459, UINT16_MAX, 1459, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1460, UINT16_MAX, 1460, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1461, UINT16_MAX, 1461, UINT16_MAX, 2595, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1462, UINT16_MAX, 1462, 2598, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17847, 1465, UINT16_MAX, 1465, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17850, UINT16_MAX, 1468, UINT16_MAX, 1468, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1469, UINT16_MAX, 1469, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1470, UINT16_MAX, 1470, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1471, UINT16_MAX, 1471, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1472, UINT16_MAX, 1472, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1473, UINT16_MAX, 1473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1474, UINT16_MAX, 1474, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1475, UINT16_MAX, 1475, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1476, UINT16_MAX, 1476, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1477, UINT16_MAX, 1477, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1478, UINT16_MAX, 1478, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ME, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1479, UINT16_MAX, 1479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1480, UINT16_MAX, 1480, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1481, UINT16_MAX, 1481, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1482, UINT16_MAX, 1482, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1483, UINT16_MAX, 1483, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1484, UINT16_MAX, 1484, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1485, UINT16_MAX, 1485, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1486, UINT16_MAX, 1486, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1487, UINT16_MAX, 1487, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1488, UINT16_MAX, 1488, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1489, UINT16_MAX, 1489, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1490, UINT16_MAX, 1490, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1491, UINT16_MAX, 1491, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1492, UINT16_MAX, 1492, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1493, UINT16_MAX, 1493, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1494, UINT16_MAX, 1494, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1495, UINT16_MAX, 1495, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1496, UINT16_MAX, 1496, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1497, UINT16_MAX, 1497, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1498, UINT16_MAX, 1498, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1499, UINT16_MAX, 1499, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1500, UINT16_MAX, 1500, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1501, UINT16_MAX, 1501, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1502, UINT16_MAX, 1502, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1503, UINT16_MAX, 1503, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1504, UINT16_MAX, 1504, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1505, UINT16_MAX, 1505, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1506, UINT16_MAX, 1506, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1507, UINT16_MAX, 1507, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1508, UINT16_MAX, 1508, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1509, UINT16_MAX, 1509, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1510, UINT16_MAX, 1510, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1511, UINT16_MAX, 1511, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1512, UINT16_MAX, 1512, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1513, UINT16_MAX, 1513, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1514, UINT16_MAX, 1514, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1515, UINT16_MAX, 1515, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1516, UINT16_MAX, 1516, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1517, UINT16_MAX, 1517, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1518, UINT16_MAX, 1518, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1519, UINT16_MAX, 1519, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1520, UINT16_MAX, 1520, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1521, UINT16_MAX, 1521, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1522, UINT16_MAX, 1522, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1523, UINT16_MAX, 1523, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1524, UINT16_MAX, 1524, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1525, UINT16_MAX, 1525, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1526, UINT16_MAX, 1526, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1527, UINT16_MAX, 1527, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1528, UINT16_MAX, 1528, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1529, UINT16_MAX, 1529, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1530, UINT16_MAX, 1530, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1531, UINT16_MAX, 1531, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1532, UINT16_MAX, 1532, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1533, UINT16_MAX, 1533, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17918, 1536, UINT16_MAX, 1536, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17921, UINT16_MAX, 1539, UINT16_MAX, 1539, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1540, UINT16_MAX, 1540, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1541, UINT16_MAX, 1541, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1542, UINT16_MAX, 1542, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1543, UINT16_MAX, 1543, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1544, UINT16_MAX, 1544, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1545, UINT16_MAX, 1545, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1546, UINT16_MAX, 1546, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1547, UINT16_MAX, 1547, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1548, UINT16_MAX, 1548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1549, UINT16_MAX, 1549, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1550, UINT16_MAX, 1550, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1551, UINT16_MAX, 1551, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1552, UINT16_MAX, 1552, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17937, 1555, UINT16_MAX, 1555, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17940, UINT16_MAX, 1558, UINT16_MAX, 1558, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17943, 1561, UINT16_MAX, 1561, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17946, UINT16_MAX, 1564, UINT16_MAX, 1564, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1565, UINT16_MAX, 1565, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1566, UINT16_MAX, 1566, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17951, 1569, UINT16_MAX, 1569, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17954, UINT16_MAX, 1572, UINT16_MAX, 1572, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1573, UINT16_MAX, 1573, UINT16_MAX, 2629, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1574, UINT16_MAX, 1574, 2632, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17959, 1577, UINT16_MAX, 1577, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17962, UINT16_MAX, 1580, UINT16_MAX, 1580, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17965, 1583, UINT16_MAX, 1583, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17968, UINT16_MAX, 1586, UINT16_MAX, 1586, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17971, 1589, UINT16_MAX, 1589, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17974, UINT16_MAX, 1592, UINT16_MAX, 1592, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1593, UINT16_MAX, 1593, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1594, UINT16_MAX, 1594, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17979, 1597, UINT16_MAX, 1597, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17982, UINT16_MAX, 1600, UINT16_MAX, 1600, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17985, 1603, UINT16_MAX, 1603, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17988, UINT16_MAX, 1606, UINT16_MAX, 1606, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17991, 1609, UINT16_MAX, 1609, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 17994, UINT16_MAX, 1612, UINT16_MAX, 1612, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1613, UINT16_MAX, 1613, UINT16_MAX, 2647, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1614, UINT16_MAX, 1614, 2650, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 17999, 1617, UINT16_MAX, 1617, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18002, UINT16_MAX, 1620, UINT16_MAX, 1620, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18005, 1623, UINT16_MAX, 1623, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18008, UINT16_MAX, 1626, UINT16_MAX, 1626, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18011, 1629, UINT16_MAX, 1629, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18014, UINT16_MAX, 1632, UINT16_MAX, 1632, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18017, 1635, UINT16_MAX, 1635, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18020, UINT16_MAX, 1638, UINT16_MAX, 1638, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18023, 1641, UINT16_MAX, 1641, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18026, UINT16_MAX, 1644, UINT16_MAX, 1644, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18029, 1647, UINT16_MAX, 1647, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18032, UINT16_MAX, 1650, UINT16_MAX, 1650, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1651, UINT16_MAX, 1651, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1652, UINT16_MAX, 1652, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18037, 1655, UINT16_MAX, 1655, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18040, UINT16_MAX, 1658, UINT16_MAX, 1658, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1659, UINT16_MAX, 1659, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1660, UINT16_MAX, 1660, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1661, UINT16_MAX, 1661, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1662, UINT16_MAX, 1662, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1663, UINT16_MAX, 1663, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1664, UINT16_MAX, 1664, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1665, UINT16_MAX, 1665, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1666, UINT16_MAX, 1666, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1667, UINT16_MAX, 1667, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1668, UINT16_MAX, 1668, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1669, UINT16_MAX, 1669, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1670, UINT16_MAX, 1670, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1671, UINT16_MAX, 1671, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1672, UINT16_MAX, 1672, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1673, UINT16_MAX, 1673, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1674, UINT16_MAX, 1674, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1675, UINT16_MAX, 1675, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1676, UINT16_MAX, 1676, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1677, UINT16_MAX, 1677, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1678, UINT16_MAX, 1678, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1679, UINT16_MAX, 1679, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1680, UINT16_MAX, 1680, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1681, UINT16_MAX, 1681, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1682, UINT16_MAX, 1682, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1683, UINT16_MAX, 1683, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1684, UINT16_MAX, 1684, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1685, UINT16_MAX, 1685, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1686, UINT16_MAX, 1686, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1687, UINT16_MAX, 1687, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1688, UINT16_MAX, 1688, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1689, UINT16_MAX, 1689, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1690, UINT16_MAX, 1690, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1691, UINT16_MAX, 1691, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1692, UINT16_MAX, 1692, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1693, UINT16_MAX, 1693, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1694, UINT16_MAX, 1694, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1695, UINT16_MAX, 1695, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1696, UINT16_MAX, 1696, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1697, UINT16_MAX, 1697, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1698, UINT16_MAX, 1698, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1699, UINT16_MAX, 1699, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1700, UINT16_MAX, 1700, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1701, UINT16_MAX, 1701, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1702, UINT16_MAX, 1702, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1703, UINT16_MAX, 1703, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1704, UINT16_MAX, 1704, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1705, UINT16_MAX, 1705, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1706, UINT16_MAX, 1706, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1707, UINT16_MAX, 1707, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1708, UINT16_MAX, 1708, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1709, UINT16_MAX, 1709, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1710, UINT16_MAX, 1710, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1711, UINT16_MAX, 1711, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1712, UINT16_MAX, 1712, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1713, UINT16_MAX, 1713, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1714, UINT16_MAX, 1714, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1715, UINT16_MAX, 1715, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1716, UINT16_MAX, 1716, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1717, UINT16_MAX, 1717, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1718, UINT16_MAX, 1718, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1719, UINT16_MAX, 1719, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1720, UINT16_MAX, 1720, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1721, UINT16_MAX, 1721, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1722, UINT16_MAX, 1722, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1723, UINT16_MAX, 1723, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1724, UINT16_MAX, 1724, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1725, UINT16_MAX, 1725, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1726, UINT16_MAX, 1726, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1727, UINT16_MAX, 1727, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1728, UINT16_MAX, 1728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1729, UINT16_MAX, 1729, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1730, UINT16_MAX, 1730, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1731, UINT16_MAX, 1731, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1732, UINT16_MAX, 1732, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1733, UINT16_MAX, 1733, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1734, UINT16_MAX, 1734, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1735, UINT16_MAX, 1735, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1736, UINT16_MAX, 1736, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1737, UINT16_MAX, 1737, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1738, UINT16_MAX, 1738, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1739, UINT16_MAX, 1739, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1740, UINT16_MAX, 1740, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1741, UINT16_MAX, 1741, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1742, UINT16_MAX, 1742, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1743, UINT16_MAX, 1743, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1744, UINT16_MAX, 1744, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1745, UINT16_MAX, 1745, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1746, UINT16_MAX, 1746, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1747, UINT16_MAX, 1747, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1748, UINT16_MAX, 1748, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1749, UINT16_MAX, 1749, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1750, UINT16_MAX, 1750, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1751, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1752, UINT16_MAX, 1752, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1753, UINT16_MAX, 1753, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1754, UINT16_MAX, 1754, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1755, UINT16_MAX, 1755, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1756, UINT16_MAX, 1756, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1757, UINT16_MAX, 1757, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1758, UINT16_MAX, 1758, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1759, UINT16_MAX, 1759, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1760, UINT16_MAX, 1760, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1761, UINT16_MAX, 1761, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1762, UINT16_MAX, 1762, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1763, UINT16_MAX, 1763, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1764, UINT16_MAX, 1764, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1765, UINT16_MAX, 1765, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1766, UINT16_MAX, 1766, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1767, UINT16_MAX, 1767, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1768, UINT16_MAX, 1768, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1769, UINT16_MAX, 1769, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1770, UINT16_MAX, 1770, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1771, UINT16_MAX, 1771, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1772, UINT16_MAX, 1772, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1773, UINT16_MAX, 1773, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1774, UINT16_MAX, 1774, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1775, UINT16_MAX, 1775, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1776, UINT16_MAX, 1776, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1777, UINT16_MAX, 1777, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1778, UINT16_MAX, 1778, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1779, UINT16_MAX, 1779, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1780, UINT16_MAX, 1780, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1781, UINT16_MAX, 1781, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1782, UINT16_MAX, 1782, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1783, UINT16_MAX, 1783, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1784, UINT16_MAX, 1784, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1785, UINT16_MAX, 1785, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1786, UINT16_MAX, 1786, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1787, UINT16_MAX, 1787, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1788, UINT16_MAX, 1788, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1789, UINT16_MAX, 1789, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 18174, 18174, 1792, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1793, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 222, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 228, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 10, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 11, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 12, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 13, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 14, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 15, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 16, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 17, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 18, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 19, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 20, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 21, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 22, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 23, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 24, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 25, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 30, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 31, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 32, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 18178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 18180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 18182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 18184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 18186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2671, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2676, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2679, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 27, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 28, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 29, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 33, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 34, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32785, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32786, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32787, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 35, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 18188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 18190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 18192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 18194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 18196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2685, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 18198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2688, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 18200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2682, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 36, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2691, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2694, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2697, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32788, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_LINKER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18214, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18218, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32789, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2700, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32790, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32792, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2704, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32791, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32793, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_CONSONANT}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2709, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32795, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2712, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2716, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32794, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2719, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 84, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 91, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32796, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2722, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32799, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2725, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2730, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32797, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32798, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32800, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2733, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2737, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_PREPEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32801, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32802, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32803, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2740, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18284, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2745, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32804, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 18290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 103, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 107, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 18292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 118, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 122, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 18294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 18296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NOBREAK, 1914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 129, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 130, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 132, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, 18317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18319, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, 18321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 18335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2748, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32805, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1955, UINT16_MAX, 1955, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1956, UINT16_MAX, 1956, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1957, UINT16_MAX, 1957, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1958, UINT16_MAX, 1958, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1959, UINT16_MAX, 1959, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1960, UINT16_MAX, 1960, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1961, UINT16_MAX, 1961, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1962, UINT16_MAX, 1962, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1963, UINT16_MAX, 1963, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1964, UINT16_MAX, 1964, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1965, UINT16_MAX, 1965, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1966, UINT16_MAX, 1966, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1967, UINT16_MAX, 1967, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1968, UINT16_MAX, 1968, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1969, UINT16_MAX, 1969, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1970, UINT16_MAX, 1970, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1971, UINT16_MAX, 1971, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1972, UINT16_MAX, 1972, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1973, UINT16_MAX, 1973, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1974, UINT16_MAX, 1974, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1975, UINT16_MAX, 1975, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1976, UINT16_MAX, 1976, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1977, UINT16_MAX, 1977, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1978, UINT16_MAX, 1978, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1979, UINT16_MAX, 1979, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1980, UINT16_MAX, 1980, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1981, UINT16_MAX, 1981, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1982, UINT16_MAX, 1982, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1983, UINT16_MAX, 1983, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1984, UINT16_MAX, 1984, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1985, UINT16_MAX, 1985, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1986, UINT16_MAX, 1986, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1987, UINT16_MAX, 1987, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1988, UINT16_MAX, 1988, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1989, UINT16_MAX, 1989, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1990, UINT16_MAX, 1990, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1991, UINT16_MAX, 1991, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1992, UINT16_MAX, 1992, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1993, UINT16_MAX, 1993, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1994, UINT16_MAX, 1994, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1995, UINT16_MAX, 1996, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1997, UINT16_MAX, 1998, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1999, UINT16_MAX, 2000, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2001, UINT16_MAX, 2002, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2003, UINT16_MAX, 2004, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2005, UINT16_MAX, 2006, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2007, UINT16_MAX, 2008, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2009, UINT16_MAX, 2010, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2011, UINT16_MAX, 2012, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2013, UINT16_MAX, 2014, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2015, UINT16_MAX, 2016, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2017, UINT16_MAX, 2018, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2019, UINT16_MAX, 2020, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2021, UINT16_MAX, 2022, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2023, UINT16_MAX, 2024, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2025, UINT16_MAX, 2026, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2027, UINT16_MAX, 2028, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2029, UINT16_MAX, 2030, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2031, UINT16_MAX, 2032, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2033, UINT16_MAX, 2034, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2035, UINT16_MAX, 2036, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2037, UINT16_MAX, 2038, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2039, UINT16_MAX, 2040, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2041, UINT16_MAX, 2042, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2043, UINT16_MAX, 2044, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2045, UINT16_MAX, 2046, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2047, UINT16_MAX, 2048, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2049, UINT16_MAX, 2050, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2051, UINT16_MAX, 2052, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2053, UINT16_MAX, 2054, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2055, UINT16_MAX, 2056, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2057, UINT16_MAX, 2058, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2059, UINT16_MAX, 2060, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2061, UINT16_MAX, 2062, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2063, UINT16_MAX, 2064, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2065, UINT16_MAX, 2066, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2067, UINT16_MAX, 2068, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2069, UINT16_MAX, 2070, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2071, UINT16_MAX, 2072, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2073, UINT16_MAX, 2074, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2075, UINT16_MAX, 2076, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2077, UINT16_MAX, 2078, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2079, UINT16_MAX, 2080, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2020, UINT16_MAX, 2081, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2082, UINT16_MAX, 2083, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2084, UINT16_MAX, 2085, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2086, UINT16_MAX, 2087, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_L, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 2, 0, UTF8PROC_BOUNDCLASS_L, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 1, 0, UTF8PROC_BOUNDCLASS_V, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_V, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_T, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2088, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2089, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2090, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2091, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2092, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2093, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2094, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2096, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2097, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2098, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2099, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2100, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2101, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2102, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2104, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2105, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2106, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2107, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2108, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2109, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2110, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2111, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2112, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2113, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2114, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2115, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2116, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2117, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2118, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2120, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2121, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2122, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2123, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2124, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2125, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2126, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2127, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2128, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2130, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2131, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2132, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2133, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2134, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2135, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2136, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2137, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2138, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2139, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2140, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2141, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2142, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2143, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2144, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2146, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2147, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2148, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2149, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2150, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2152, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2154, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2156, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2157, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2158, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2159, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2160, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2161, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2162, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2163, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2164, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2165, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2166, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2167, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2168, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2169, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2170, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2171, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2172, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2173, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2174, 2174, UINT16_MAX, 2174, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2175, 2175, UINT16_MAX, 2175, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2176, 2176, UINT16_MAX, 2176, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2177, 2177, UINT16_MAX, 2177, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2178, 2178, UINT16_MAX, 2178, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2179, 2179, UINT16_MAX, 2179, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 9, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2751, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2754, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2757, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2760, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2763, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2766, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 18574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32806, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2769, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2772, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2775, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2778, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2781, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 18584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1345, 1379, UINT16_MAX, 1379, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1347, 1381, UINT16_MAX, 1381, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1359, 1393, UINT16_MAX, 1393, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1362, 1396, UINT16_MAX, 1396, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1363, 1397, UINT16_MAX, 1397, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1371, 1405, UINT16_MAX, 1405, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1443, 1444, UINT16_MAX, 1444, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2202, 2203, UINT16_MAX, 2203, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1996, UINT16_MAX, 1996, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1998, UINT16_MAX, 1998, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2000, UINT16_MAX, 2000, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2002, UINT16_MAX, 2002, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2004, UINT16_MAX, 2004, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2006, UINT16_MAX, 2006, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2008, UINT16_MAX, 2008, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2010, UINT16_MAX, 2010, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2012, UINT16_MAX, 2012, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2014, UINT16_MAX, 2014, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2016, UINT16_MAX, 2016, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2018, UINT16_MAX, 2018, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2020, UINT16_MAX, 2020, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2022, UINT16_MAX, 2022, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2024, UINT16_MAX, 2024, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2026, UINT16_MAX, 2026, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2028, UINT16_MAX, 2028, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2030, UINT16_MAX, 2030, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2032, UINT16_MAX, 2032, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2034, UINT16_MAX, 2034, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2036, UINT16_MAX, 2036, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2038, UINT16_MAX, 2038, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2040, UINT16_MAX, 2040, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2042, UINT16_MAX, 2042, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2044, UINT16_MAX, 2044, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2046, UINT16_MAX, 2046, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2048, UINT16_MAX, 2048, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2050, UINT16_MAX, 2050, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2052, UINT16_MAX, 2052, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2054, UINT16_MAX, 2054, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2056, UINT16_MAX, 2056, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2058, UINT16_MAX, 2058, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2060, UINT16_MAX, 2060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2062, UINT16_MAX, 2062, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2064, UINT16_MAX, 2064, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2066, UINT16_MAX, 2066, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2068, UINT16_MAX, 2068, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2070, UINT16_MAX, 2070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2072, UINT16_MAX, 2072, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2074, UINT16_MAX, 2074, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2076, UINT16_MAX, 2076, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2078, UINT16_MAX, 2078, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2080, UINT16_MAX, 2080, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2083, UINT16_MAX, 2083, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2085, UINT16_MAX, 2085, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2087, UINT16_MAX, 2087, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2204, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2205, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2206, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2207, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2208, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2209, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2210, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2211, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2212, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2213, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2214, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2215, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2216, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2217, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2218, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2219, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2220, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2221, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2222, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2223, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2224, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2225, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2226, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2227, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2228, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2229, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2230, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2231, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2232, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2233, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2234, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2235, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2236, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2237, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2238, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2239, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2240, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2241, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2242, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2243, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2244, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2245, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2246, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2247, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 26, UINT16_MAX, 2248, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 180, UINT16_MAX, 2249, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 27, UINT16_MAX, 2250, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2251, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 29, UINT16_MAX, 2252, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 30, UINT16_MAX, 2253, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 746, UINT16_MAX, 2254, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 32, UINT16_MAX, 2255, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 33, UINT16_MAX, 2256, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 34, UINT16_MAX, 2257, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 35, UINT16_MAX, 2258, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 36, UINT16_MAX, 2259, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 37, UINT16_MAX, 2260, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 38, UINT16_MAX, 2261, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 39, UINT16_MAX, 2262, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2263, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 40, UINT16_MAX, 2264, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 936, UINT16_MAX, 2265, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 41, UINT16_MAX, 2266, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 43, UINT16_MAX, 2267, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 45, UINT16_MAX, 2268, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 46, UINT16_MAX, 2269, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 48, UINT16_MAX, 2270, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 0, UINT16_MAX, 2271, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2272, UINT16_MAX, 2273, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2274, UINT16_MAX, 2275, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2206, UINT16_MAX, 2276, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1, UINT16_MAX, 2277, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3, UINT16_MAX, 2278, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4, UINT16_MAX, 2279, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 615, UINT16_MAX, 2280, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 616, UINT16_MAX, 2281, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2282, UINT16_MAX, 2283, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6, UINT16_MAX, 2284, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2285, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 10, UINT16_MAX, 2286, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 12, UINT16_MAX, 2287, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 453, UINT16_MAX, 2288, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 14, UINT16_MAX, 2289, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 606, UINT16_MAX, 2290, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2226, UINT16_MAX, 2291, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2227, UINT16_MAX, 2292, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 15, UINT16_MAX, 2293, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 19, UINT16_MAX, 2294, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 20, UINT16_MAX, 2295, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2233, UINT16_MAX, 2296, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 628, UINT16_MAX, 2297, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 21, UINT16_MAX, 2298, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2241, UINT16_MAX, 2299, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1186, UINT16_MAX, 2300, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1187, UINT16_MAX, 2301, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1188, UINT16_MAX, 2302, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1203, UINT16_MAX, 2303, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1204, UINT16_MAX, 2304, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 8, UINT16_MAX, 2305, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 17, UINT16_MAX, 2306, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 20, UINT16_MAX, 2307, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 21, UINT16_MAX, 2308, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1186, UINT16_MAX, 2309, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1187, UINT16_MAX, 2310, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1199, UINT16_MAX, 2311, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1203, UINT16_MAX, 2312, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1204, UINT16_MAX, 2313, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2314, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2315, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2316, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2317, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2318, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2319, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2320, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2321, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2322, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2323, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2324, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2325, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2326, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1358, UINT16_MAX, 2327, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2328, UINT16_MAX, 2328, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2329, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2330, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2331, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2332, UINT16_MAX, 2332, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2333, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2334, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2335, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2336, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2337, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2338, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2339, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2340, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2341, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2342, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2343, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2344, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2345, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2346, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2347, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2348, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2349, UINT16_MAX, 2349, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2350, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2351, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2352, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2353, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2354, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2355, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2356, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2357, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2358, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2359, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2360, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2361, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2362, UINT16_MAX, 2363, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2, UINT16_MAX, 2364, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1014, UINT16_MAX, 2365, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 123, UINT16_MAX, 2366, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2282, UINT16_MAX, 2367, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5, UINT16_MAX, 2368, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1024, UINT16_MAX, 2369, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2370, UINT16_MAX, 2371, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2372, UINT16_MAX, 2373, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 623, UINT16_MAX, 2374, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 622, UINT16_MAX, 2375, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2376, UINT16_MAX, 2377, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2330, UINT16_MAX, 2378, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2379, UINT16_MAX, 2380, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1038, UINT16_MAX, 2381, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2340, UINT16_MAX, 2382, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1087, UINT16_MAX, 2383, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2384, UINT16_MAX, 2385, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1041, UINT16_MAX, 2386, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 629, UINT16_MAX, 2387, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1044, UINT16_MAX, 2388, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1045, UINT16_MAX, 2389, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 631, UINT16_MAX, 2390, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1049, UINT16_MAX, 2391, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2392, UINT16_MAX, 2393, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 645, UINT16_MAX, 2394, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 647, UINT16_MAX, 2395, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 997, UINT16_MAX, 2396, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 657, UINT16_MAX, 2397, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2232, UINT16_MAX, 2398, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 658, UINT16_MAX, 2399, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 998, UINT16_MAX, 2400, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 25, UINT16_MAX, 2401, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1073, UINT16_MAX, 2402, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1074, UINT16_MAX, 2403, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 663, UINT16_MAX, 2404, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1192, UINT16_MAX, 2405, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 214, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 218, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18790, 2408, UINT16_MAX, 2408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18793, UINT16_MAX, 2411, UINT16_MAX, 2411, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18796, 2414, UINT16_MAX, 2414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18799, UINT16_MAX, 2417, UINT16_MAX, 2417, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18802, 2420, UINT16_MAX, 2420, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18805, UINT16_MAX, 2423, UINT16_MAX, 2423, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18808, 2426, UINT16_MAX, 2426, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18811, UINT16_MAX, 2429, UINT16_MAX, 2429, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18814, 2432, UINT16_MAX, 2432, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18817, UINT16_MAX, 2435, UINT16_MAX, 2435, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18820, 2438, UINT16_MAX, 2438, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18823, UINT16_MAX, 2441, UINT16_MAX, 2441, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18826, 2444, UINT16_MAX, 2444, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18829, UINT16_MAX, 2447, UINT16_MAX, 2447, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18832, 2450, UINT16_MAX, 2450, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18835, UINT16_MAX, 2453, UINT16_MAX, 2453, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18838, 2456, UINT16_MAX, 2456, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18841, UINT16_MAX, 2459, UINT16_MAX, 2459, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18844, 2462, UINT16_MAX, 2462, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18847, UINT16_MAX, 2465, UINT16_MAX, 2465, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18850, 2468, UINT16_MAX, 2468, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18853, UINT16_MAX, 2471, UINT16_MAX, 2471, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18856, 2474, UINT16_MAX, 2474, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18859, UINT16_MAX, 2477, UINT16_MAX, 2477, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18862, 2480, UINT16_MAX, 2480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18865, UINT16_MAX, 2483, UINT16_MAX, 2483, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18868, 2486, UINT16_MAX, 2486, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18871, UINT16_MAX, 2489, UINT16_MAX, 2489, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18874, 2492, UINT16_MAX, 2492, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18877, UINT16_MAX, 2495, UINT16_MAX, 2495, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18880, 2498, UINT16_MAX, 2498, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18883, UINT16_MAX, 2501, UINT16_MAX, 2501, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18886, 2504, UINT16_MAX, 2504, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18889, UINT16_MAX, 2507, UINT16_MAX, 2507, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18892, 2510, UINT16_MAX, 2510, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18895, UINT16_MAX, 2513, UINT16_MAX, 2513, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18898, 2516, UINT16_MAX, 2516, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18901, UINT16_MAX, 2519, UINT16_MAX, 2519, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18904, 2522, UINT16_MAX, 2522, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18907, UINT16_MAX, 2525, UINT16_MAX, 2525, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18910, 2528, UINT16_MAX, 2528, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18913, UINT16_MAX, 2531, UINT16_MAX, 2531, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18916, 2534, UINT16_MAX, 2534, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18919, UINT16_MAX, 2537, UINT16_MAX, 2537, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18922, 2540, UINT16_MAX, 2540, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18925, UINT16_MAX, 2543, UINT16_MAX, 2543, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18928, 2546, UINT16_MAX, 2546, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18931, UINT16_MAX, 2549, UINT16_MAX, 2549, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18934, 2552, UINT16_MAX, 2552, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18937, UINT16_MAX, 2555, UINT16_MAX, 2555, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18940, 2558, UINT16_MAX, 2558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18943, UINT16_MAX, 2561, UINT16_MAX, 2561, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18946, 2564, UINT16_MAX, 2564, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18949, UINT16_MAX, 2567, UINT16_MAX, 2567, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18952, 2570, UINT16_MAX, 2570, UINT16_MAX, 2884, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18955, UINT16_MAX, 2573, UINT16_MAX, 2573, 2887, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18958, 2576, UINT16_MAX, 2576, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18961, UINT16_MAX, 2579, UINT16_MAX, 2579, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18964, 2582, UINT16_MAX, 2582, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18967, UINT16_MAX, 2585, UINT16_MAX, 2585, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18970, 2588, UINT16_MAX, 2588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18973, UINT16_MAX, 2591, UINT16_MAX, 2591, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18976, 2594, UINT16_MAX, 2594, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18979, UINT16_MAX, 2597, UINT16_MAX, 2597, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18982, 2600, UINT16_MAX, 2600, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18985, UINT16_MAX, 2603, UINT16_MAX, 2603, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18988, 2606, UINT16_MAX, 2606, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18991, UINT16_MAX, 2609, UINT16_MAX, 2609, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 18994, 2612, UINT16_MAX, 2612, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 18997, UINT16_MAX, 2615, UINT16_MAX, 2615, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19000, 2618, UINT16_MAX, 2618, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19003, UINT16_MAX, 2621, UINT16_MAX, 2621, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19006, 2624, UINT16_MAX, 2624, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19009, UINT16_MAX, 2627, UINT16_MAX, 2627, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19012, 2630, UINT16_MAX, 2630, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19015, UINT16_MAX, 2633, UINT16_MAX, 2633, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19018, 2636, UINT16_MAX, 2636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19021, UINT16_MAX, 2639, UINT16_MAX, 2639, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19024, 2642, UINT16_MAX, 2642, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19027, UINT16_MAX, 2645, UINT16_MAX, 2645, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19030, 2648, UINT16_MAX, 2648, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19033, UINT16_MAX, 2651, UINT16_MAX, 2651, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19036, 2654, UINT16_MAX, 2654, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19039, UINT16_MAX, 2657, UINT16_MAX, 2657, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19042, 2660, UINT16_MAX, 2660, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19045, UINT16_MAX, 2663, UINT16_MAX, 2663, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19048, 2666, UINT16_MAX, 2666, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19051, UINT16_MAX, 2669, UINT16_MAX, 2669, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19054, 2672, UINT16_MAX, 2672, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19057, UINT16_MAX, 2675, UINT16_MAX, 2675, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19060, 2678, UINT16_MAX, 2678, UINT16_MAX, 3006, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19063, UINT16_MAX, 2681, UINT16_MAX, 2681, 3009, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19066, 2684, UINT16_MAX, 2684, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19069, UINT16_MAX, 2687, UINT16_MAX, 2687, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19072, 2690, UINT16_MAX, 2690, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19075, UINT16_MAX, 2693, UINT16_MAX, 2693, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19078, 2696, UINT16_MAX, 2696, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19081, UINT16_MAX, 2699, UINT16_MAX, 2699, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19084, 2702, UINT16_MAX, 2702, UINT16_MAX, 3024, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19087, UINT16_MAX, 2705, UINT16_MAX, 2705, 3027, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19090, 2708, UINT16_MAX, 2708, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19093, UINT16_MAX, 2711, UINT16_MAX, 2711, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19096, 2714, UINT16_MAX, 2714, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19099, UINT16_MAX, 2717, UINT16_MAX, 2717, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19102, 2720, UINT16_MAX, 2720, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19105, UINT16_MAX, 2723, UINT16_MAX, 2723, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19108, 2726, UINT16_MAX, 2726, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19111, UINT16_MAX, 2729, UINT16_MAX, 2729, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19114, 2732, UINT16_MAX, 2732, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19117, UINT16_MAX, 2735, UINT16_MAX, 2735, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19120, 2738, UINT16_MAX, 2738, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19123, UINT16_MAX, 2741, UINT16_MAX, 2741, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19126, 2744, UINT16_MAX, 2744, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19129, UINT16_MAX, 2747, UINT16_MAX, 2747, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19132, 2750, UINT16_MAX, 2750, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19135, UINT16_MAX, 2753, UINT16_MAX, 2753, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19138, 2756, UINT16_MAX, 2756, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19141, UINT16_MAX, 2759, UINT16_MAX, 2759, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19144, 2762, UINT16_MAX, 2762, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19147, UINT16_MAX, 2765, UINT16_MAX, 2765, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19150, 2768, UINT16_MAX, 2768, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19153, UINT16_MAX, 2771, UINT16_MAX, 2771, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19156, 2774, UINT16_MAX, 2774, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19159, UINT16_MAX, 2777, UINT16_MAX, 2777, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19162, 2780, UINT16_MAX, 2780, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19165, UINT16_MAX, 2783, UINT16_MAX, 2783, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19168, 2786, UINT16_MAX, 2786, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19171, UINT16_MAX, 2789, UINT16_MAX, 2789, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19174, 2792, UINT16_MAX, 2792, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19177, UINT16_MAX, 2795, UINT16_MAX, 2795, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19180, 2798, UINT16_MAX, 2798, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19183, UINT16_MAX, 2801, UINT16_MAX, 2801, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19186, 2804, UINT16_MAX, 2804, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19189, UINT16_MAX, 2807, UINT16_MAX, 2807, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19192, 2810, UINT16_MAX, 2810, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19195, UINT16_MAX, 2813, UINT16_MAX, 2813, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19198, 2816, UINT16_MAX, 2816, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19201, UINT16_MAX, 2819, UINT16_MAX, 2819, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19204, 2822, UINT16_MAX, 2822, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19207, UINT16_MAX, 2825, UINT16_MAX, 2825, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19210, 2828, UINT16_MAX, 2828, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19213, UINT16_MAX, 2831, UINT16_MAX, 2831, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19216, 2834, UINT16_MAX, 2834, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19219, UINT16_MAX, 2837, UINT16_MAX, 2837, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19222, 2840, UINT16_MAX, 2840, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19225, UINT16_MAX, 2843, UINT16_MAX, 2843, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19228, 2846, UINT16_MAX, 2846, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19231, UINT16_MAX, 2849, UINT16_MAX, 2849, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19234, 2852, UINT16_MAX, 2852, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19237, UINT16_MAX, 2855, UINT16_MAX, 2855, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19240, 19240, 2858, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19243, 19243, 2861, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19246, 19246, 2864, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19249, 19249, 2867, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19252, 19252, 2870, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19255, 2696, 2699, UINT16_MAX, 2699, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2873, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2874, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 16543, UINT16_MAX, 2875, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2876, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19261, 2879, UINT16_MAX, 2879, UINT16_MAX, 3241, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19264, UINT16_MAX, 2882, UINT16_MAX, 2882, 3250, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19267, 2885, UINT16_MAX, 2885, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19270, UINT16_MAX, 2888, UINT16_MAX, 2888, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19273, 2891, UINT16_MAX, 2891, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19276, UINT16_MAX, 2894, UINT16_MAX, 2894, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19279, 2897, UINT16_MAX, 2897, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19282, UINT16_MAX, 2900, UINT16_MAX, 2900, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19285, 2903, UINT16_MAX, 2903, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19288, UINT16_MAX, 2906, UINT16_MAX, 2906, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19291, 2909, UINT16_MAX, 2909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19294, UINT16_MAX, 2912, UINT16_MAX, 2912, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19297, 2915, UINT16_MAX, 2915, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19300, UINT16_MAX, 2918, UINT16_MAX, 2918, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19303, 2921, UINT16_MAX, 2921, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19306, UINT16_MAX, 2924, UINT16_MAX, 2924, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19309, 2927, UINT16_MAX, 2927, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19312, UINT16_MAX, 2930, UINT16_MAX, 2930, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19315, 2933, UINT16_MAX, 2933, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19318, UINT16_MAX, 2936, UINT16_MAX, 2936, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19321, 2939, UINT16_MAX, 2939, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19324, UINT16_MAX, 2942, UINT16_MAX, 2942, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19327, 2945, UINT16_MAX, 2945, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19330, UINT16_MAX, 2948, UINT16_MAX, 2948, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19333, 2951, UINT16_MAX, 2951, UINT16_MAX, 3455, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19336, UINT16_MAX, 2954, UINT16_MAX, 2954, 3458, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19339, 2957, UINT16_MAX, 2957, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19342, UINT16_MAX, 2960, UINT16_MAX, 2960, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19345, 2963, UINT16_MAX, 2963, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19348, UINT16_MAX, 2966, UINT16_MAX, 2966, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19351, 2969, UINT16_MAX, 2969, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19354, UINT16_MAX, 2972, UINT16_MAX, 2972, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19357, 2975, UINT16_MAX, 2975, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19360, UINT16_MAX, 2978, UINT16_MAX, 2978, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19363, 2981, UINT16_MAX, 2981, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19366, UINT16_MAX, 2984, UINT16_MAX, 2984, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19369, 2987, UINT16_MAX, 2987, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19372, UINT16_MAX, 2990, UINT16_MAX, 2990, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19375, 2993, UINT16_MAX, 2993, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19378, UINT16_MAX, 2996, UINT16_MAX, 2996, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19381, 2999, UINT16_MAX, 2999, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19384, UINT16_MAX, 3002, UINT16_MAX, 3002, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19387, 3005, UINT16_MAX, 3005, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19390, UINT16_MAX, 3008, UINT16_MAX, 3008, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19393, 3011, UINT16_MAX, 3011, UINT16_MAX, 3559, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19396, UINT16_MAX, 3014, UINT16_MAX, 3014, 3562, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19399, 3017, UINT16_MAX, 3017, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19402, UINT16_MAX, 3020, UINT16_MAX, 3020, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19405, 3023, UINT16_MAX, 3023, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19408, UINT16_MAX, 3026, UINT16_MAX, 3026, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19411, 3029, UINT16_MAX, 3029, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19414, UINT16_MAX, 3032, UINT16_MAX, 3032, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19417, 3035, UINT16_MAX, 3035, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19420, UINT16_MAX, 3038, UINT16_MAX, 3038, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19423, 3041, UINT16_MAX, 3041, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19426, UINT16_MAX, 3044, UINT16_MAX, 3044, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19429, 3047, UINT16_MAX, 3047, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19432, UINT16_MAX, 3050, UINT16_MAX, 3050, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19435, 3053, UINT16_MAX, 3053, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19438, UINT16_MAX, 3056, UINT16_MAX, 3056, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19441, 3059, UINT16_MAX, 3059, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19444, UINT16_MAX, 3062, UINT16_MAX, 3062, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19447, 3065, UINT16_MAX, 3065, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19450, UINT16_MAX, 3068, UINT16_MAX, 3068, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19453, 3071, UINT16_MAX, 3071, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19456, UINT16_MAX, 3074, UINT16_MAX, 3074, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19459, 3077, UINT16_MAX, 3077, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19462, UINT16_MAX, 3080, UINT16_MAX, 3080, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19465, 3083, UINT16_MAX, 3083, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19468, UINT16_MAX, 3086, UINT16_MAX, 3086, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19471, 3089, UINT16_MAX, 3089, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19474, UINT16_MAX, 3092, UINT16_MAX, 3092, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19477, 3095, UINT16_MAX, 3095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19480, UINT16_MAX, 3098, UINT16_MAX, 3098, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19483, 3101, UINT16_MAX, 3101, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19486, UINT16_MAX, 3104, UINT16_MAX, 3104, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19489, 3107, UINT16_MAX, 3107, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19492, UINT16_MAX, 3110, UINT16_MAX, 3110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19495, 3113, UINT16_MAX, 3113, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19498, UINT16_MAX, 3116, UINT16_MAX, 3116, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19501, 3119, UINT16_MAX, 3119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19504, UINT16_MAX, 3122, UINT16_MAX, 3122, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19507, 3125, UINT16_MAX, 3125, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19510, UINT16_MAX, 3128, UINT16_MAX, 3128, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19513, 3131, UINT16_MAX, 3131, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19516, UINT16_MAX, 3134, UINT16_MAX, 3134, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19519, 3137, UINT16_MAX, 3137, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19522, UINT16_MAX, 3140, UINT16_MAX, 3140, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19525, 3143, UINT16_MAX, 3143, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19528, UINT16_MAX, 3146, UINT16_MAX, 3146, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3147, UINT16_MAX, 3147, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 3148, UINT16_MAX, 3148, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3149, UINT16_MAX, 3149, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 3150, UINT16_MAX, 3150, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3151, UINT16_MAX, 3151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 3152, UINT16_MAX, 3152, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19537, UINT16_MAX, 3155, UINT16_MAX, 3155, 3761, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19540, UINT16_MAX, 3158, UINT16_MAX, 3158, 3814, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19543, UINT16_MAX, 3161, UINT16_MAX, 3161, 4793, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19546, UINT16_MAX, 3164, UINT16_MAX, 3164, 4796, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19549, UINT16_MAX, 3167, UINT16_MAX, 3167, 4799, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19552, UINT16_MAX, 3170, UINT16_MAX, 3170, 4802, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19555, UINT16_MAX, 3173, UINT16_MAX, 3173, 4805, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19558, UINT16_MAX, 3176, UINT16_MAX, 3176, 4808, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19561, 3179, UINT16_MAX, 3179, UINT16_MAX, 3867, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19564, 3182, UINT16_MAX, 3182, UINT16_MAX, 3920, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19567, 3185, UINT16_MAX, 3185, UINT16_MAX, 4811, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19570, 3188, UINT16_MAX, 3188, UINT16_MAX, 4814, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19573, 3191, UINT16_MAX, 3191, UINT16_MAX, 4817, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19576, 3194, UINT16_MAX, 3194, UINT16_MAX, 4820, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19579, 3197, UINT16_MAX, 3197, UINT16_MAX, 4823, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19582, 3200, UINT16_MAX, 3200, UINT16_MAX, 4826, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19585, UINT16_MAX, 3203, UINT16_MAX, 3203, 3973, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19588, UINT16_MAX, 3206, UINT16_MAX, 3206, 3977, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19591, UINT16_MAX, 3209, UINT16_MAX, 3209, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19594, UINT16_MAX, 3212, UINT16_MAX, 3212, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19597, UINT16_MAX, 3215, UINT16_MAX, 3215, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19600, UINT16_MAX, 3218, UINT16_MAX, 3218, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19603, 3221, UINT16_MAX, 3221, UINT16_MAX, 3981, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19606, 3224, UINT16_MAX, 3224, UINT16_MAX, 3985, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19609, 3227, UINT16_MAX, 3227, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19612, 3230, UINT16_MAX, 3230, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19615, 3233, UINT16_MAX, 3233, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19618, 3236, UINT16_MAX, 3236, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19621, UINT16_MAX, 3239, UINT16_MAX, 3239, 3989, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19624, UINT16_MAX, 3242, UINT16_MAX, 3242, 4042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19627, UINT16_MAX, 3245, UINT16_MAX, 3245, 4829, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19630, UINT16_MAX, 3248, UINT16_MAX, 3248, 4832, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19633, UINT16_MAX, 3251, UINT16_MAX, 3251, 4835, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19636, UINT16_MAX, 3254, UINT16_MAX, 3254, 4838, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19639, UINT16_MAX, 3257, UINT16_MAX, 3257, 4841, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19642, UINT16_MAX, 3260, UINT16_MAX, 3260, 4844, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19645, 3263, UINT16_MAX, 3263, UINT16_MAX, 4095, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19648, 3266, UINT16_MAX, 3266, UINT16_MAX, 4148, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19651, 3269, UINT16_MAX, 3269, UINT16_MAX, 4847, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19654, 3272, UINT16_MAX, 3272, UINT16_MAX, 4850, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19657, 3275, UINT16_MAX, 3275, UINT16_MAX, 4853, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19660, 3278, UINT16_MAX, 3278, UINT16_MAX, 4856, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19663, 3281, UINT16_MAX, 3281, UINT16_MAX, 4859, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19666, 3284, UINT16_MAX, 3284, UINT16_MAX, 4862, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19669, UINT16_MAX, 3287, UINT16_MAX, 3287, 4201, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19672, UINT16_MAX, 3290, UINT16_MAX, 3290, 4253, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19675, UINT16_MAX, 3293, UINT16_MAX, 3293, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19678, UINT16_MAX, 3296, UINT16_MAX, 3296, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19681, UINT16_MAX, 3299, UINT16_MAX, 3299, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19684, UINT16_MAX, 3302, UINT16_MAX, 3302, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19687, UINT16_MAX, 3305, UINT16_MAX, 3305, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19690, UINT16_MAX, 3308, UINT16_MAX, 3308, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19693, 3311, UINT16_MAX, 3311, UINT16_MAX, 4305, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19696, 3314, UINT16_MAX, 3314, UINT16_MAX, 4357, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19699, 3317, UINT16_MAX, 3317, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19702, 3320, UINT16_MAX, 3320, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19705, 3323, UINT16_MAX, 3323, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19708, 3326, UINT16_MAX, 3326, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19711, 3329, UINT16_MAX, 3329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19714, 3332, UINT16_MAX, 3332, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19717, UINT16_MAX, 3335, UINT16_MAX, 3335, 4409, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19720, UINT16_MAX, 3338, UINT16_MAX, 3338, 4413, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19723, UINT16_MAX, 3341, UINT16_MAX, 3341, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19726, UINT16_MAX, 3344, UINT16_MAX, 3344, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19729, UINT16_MAX, 3347, UINT16_MAX, 3347, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19732, UINT16_MAX, 3350, UINT16_MAX, 3350, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19735, 3353, UINT16_MAX, 3353, UINT16_MAX, 4417, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19738, 3356, UINT16_MAX, 3356, UINT16_MAX, 4421, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19741, 3359, UINT16_MAX, 3359, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19744, 3362, UINT16_MAX, 3362, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19747, 3365, UINT16_MAX, 3365, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19750, 3368, UINT16_MAX, 3368, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19753, 19753, 3371, UINT16_MAX, UINT16_MAX, 4425, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19756, UINT16_MAX, 3374, UINT16_MAX, 3374, 4477, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19759, 36145, 3380, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19765, UINT16_MAX, 3383, UINT16_MAX, 3383, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19768, 36154, 3389, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19774, UINT16_MAX, 3392, UINT16_MAX, 3392, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19777, 36163, 3398, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19783, UINT16_MAX, 3401, UINT16_MAX, 3401, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19786, 3404, UINT16_MAX, 3404, UINT16_MAX, 4529, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19789, 3407, UINT16_MAX, 3407, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19792, 3410, UINT16_MAX, 3410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19795, 3413, UINT16_MAX, 3413, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19798, UINT16_MAX, 3416, UINT16_MAX, 3416, 4581, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19801, UINT16_MAX, 3419, UINT16_MAX, 3419, 4634, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19804, UINT16_MAX, 3422, UINT16_MAX, 3422, 4865, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19807, UINT16_MAX, 3425, UINT16_MAX, 3425, 4868, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19810, UINT16_MAX, 3428, UINT16_MAX, 3428, 4871, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19813, UINT16_MAX, 3431, UINT16_MAX, 3431, 4874, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19816, UINT16_MAX, 3434, UINT16_MAX, 3434, 4877, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19819, UINT16_MAX, 3437, UINT16_MAX, 3437, 4880, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19822, 3440, UINT16_MAX, 3440, UINT16_MAX, 4687, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19825, 3443, UINT16_MAX, 3443, UINT16_MAX, 4740, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19828, 3446, UINT16_MAX, 3446, UINT16_MAX, 4883, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19831, 3449, UINT16_MAX, 3449, UINT16_MAX, 4886, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19834, 3452, UINT16_MAX, 3452, UINT16_MAX, 4889, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19837, 3455, UINT16_MAX, 3455, UINT16_MAX, 4892, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19840, 3458, UINT16_MAX, 3458, UINT16_MAX, 4895, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 19843, 3461, UINT16_MAX, 3461, UINT16_MAX, 4898, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19846, UINT16_MAX, 3464, UINT16_MAX, 3464, 4901, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 1159, UINT16_MAX, 3465, UINT16_MAX, 3465, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19850, UINT16_MAX, 3468, UINT16_MAX, 3468, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 1163, UINT16_MAX, 3469, UINT16_MAX, 3469, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19854, UINT16_MAX, 3472, UINT16_MAX, 3472, 4910, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 1166, UINT16_MAX, 3473, UINT16_MAX, 3473, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19858, UINT16_MAX, 3476, UINT16_MAX, 3476, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 1169, UINT16_MAX, 3477, UINT16_MAX, 3477, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19862, UINT16_MAX, 3480, UINT16_MAX, 3480, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 1172, UINT16_MAX, 3481, UINT16_MAX, 3481, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19866, UINT16_MAX, 3484, UINT16_MAX, 3484, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 1175, UINT16_MAX, 3485, UINT16_MAX, 3485, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19870, UINT16_MAX, 3488, UINT16_MAX, 3488, 5030, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 1178, UINT16_MAX, 3489, UINT16_MAX, 3489, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19874, 19876, 3494, UINT16_MAX, 3494, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19879, 19881, 3499, UINT16_MAX, 3499, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19884, 19886, 3504, UINT16_MAX, 3504, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19889, 19891, 3509, UINT16_MAX, 3509, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19894, 19896, 3514, UINT16_MAX, 3514, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19899, 19901, 3519, UINT16_MAX, 3519, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19904, 19906, 3524, UINT16_MAX, 3524, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19909, 19911, 3529, UINT16_MAX, 3529, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19914, 19876, UINT16_MAX, 3532, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19917, 19881, UINT16_MAX, 3535, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19920, 19886, UINT16_MAX, 3538, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19923, 19891, UINT16_MAX, 3541, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19926, 19896, UINT16_MAX, 3544, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19929, 19901, UINT16_MAX, 3547, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19932, 19906, UINT16_MAX, 3550, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19935, 19911, UINT16_MAX, 3553, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19938, 19940, 3558, UINT16_MAX, 3558, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19943, 19945, 3563, UINT16_MAX, 3563, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19948, 19950, 3568, UINT16_MAX, 3568, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19953, 19955, 3573, UINT16_MAX, 3573, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19958, 19960, 3578, UINT16_MAX, 3578, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19963, 19965, 3583, UINT16_MAX, 3583, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19968, 19970, 3588, UINT16_MAX, 3588, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 19973, 19975, 3593, UINT16_MAX, 3593, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19978, 19940, UINT16_MAX, 3596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19981, 19945, UINT16_MAX, 3599, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19984, 19950, UINT16_MAX, 3602, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19987, 19955, UINT16_MAX, 3605, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19990, 19960, UINT16_MAX, 3608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19993, 19965, UINT16_MAX, 3611, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19996, 19970, UINT16_MAX, 3614, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 19999, 19975, UINT16_MAX, 3617, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20002, 20004, 3622, UINT16_MAX, 3622, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20007, 20009, 3627, UINT16_MAX, 3627, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20012, 20014, 3632, UINT16_MAX, 3632, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20017, 20019, 3637, UINT16_MAX, 3637, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20022, 20024, 3642, UINT16_MAX, 3642, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20027, 20029, 3647, UINT16_MAX, 3647, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20032, 20034, 3652, UINT16_MAX, 3652, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20037, 20039, 3657, UINT16_MAX, 3657, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20042, 20004, UINT16_MAX, 3660, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20045, 20009, UINT16_MAX, 3663, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20048, 20014, UINT16_MAX, 3666, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20051, 20019, UINT16_MAX, 3669, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20054, 20024, UINT16_MAX, 3672, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20057, 20029, UINT16_MAX, 3675, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20060, 20034, UINT16_MAX, 3678, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20063, 20039, UINT16_MAX, 3681, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20066, UINT16_MAX, 3684, UINT16_MAX, 3684, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20069, UINT16_MAX, 3687, UINT16_MAX, 3687, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20072, 20074, 3692, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20077, 20079, 3697, UINT16_MAX, 3697, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20082, 20084, 3702, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20087, 20087, 3705, UINT16_MAX, UINT16_MAX, 4907, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20090, 36476, 3711, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20096, 3714, UINT16_MAX, 3714, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20099, 3717, UINT16_MAX, 3717, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20102, 3720, UINT16_MAX, 3720, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1215, 3721, UINT16_MAX, 3721, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20106, 20079, UINT16_MAX, 3724, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20109, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 1138, 1138, 1139, UINT16_MAX, 1139, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20109, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4919, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20111, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20113, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20115, 20117, 3735, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20120, 20122, 3740, UINT16_MAX, 3740, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20125, 20127, 3745, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20130, 20130, 3748, UINT16_MAX, UINT16_MAX, 4916, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20133, 36519, 3754, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20139, 3757, UINT16_MAX, 3757, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1218, 3758, UINT16_MAX, 3758, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20143, 3761, UINT16_MAX, 3761, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1221, 3762, UINT16_MAX, 3762, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20147, 20122, UINT16_MAX, 3765, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20150, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20152, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20156, UINT16_MAX, 3774, UINT16_MAX, 3774, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20159, UINT16_MAX, 3777, UINT16_MAX, 3777, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20162, 36548, 3783, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 1184, 33949, 3784, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20169, 20169, 3787, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20172, 36558, 3793, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20178, 3796, UINT16_MAX, 3796, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20181, 3799, UINT16_MAX, 3799, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20184, 3802, UINT16_MAX, 3802, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1224, 3803, UINT16_MAX, 3803, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20194, UINT16_MAX, 3812, UINT16_MAX, 3812, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20197, UINT16_MAX, 3815, UINT16_MAX, 3815, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20200, 36586, 3821, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 1230, 33995, 3822, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20207, 20207, 3825, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20210, UINT16_MAX, 3828, UINT16_MAX, 3828, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20213, 20213, 3831, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20216, 36602, 3837, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20222, 3840, UINT16_MAX, 3840, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20225, 3843, UINT16_MAX, 3843, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20228, 3846, UINT16_MAX, 3846, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1264, 3847, UINT16_MAX, 3847, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20232, 3850, UINT16_MAX, 3850, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 3853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 3854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20239, 20241, 3859, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20244, 20246, 3864, UINT16_MAX, 3864, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20249, 20251, 3869, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20254, 20254, 3872, UINT16_MAX, UINT16_MAX, 5036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 20257, 36643, 3878, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20263, 3881, UINT16_MAX, 3881, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1261, 3882, UINT16_MAX, 3882, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 20267, 3885, UINT16_MAX, 3885, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1267, 3886, UINT16_MAX, 3886, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 20271, 20246, UINT16_MAX, 3889, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 3890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4971, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, 3893, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, 3894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_COMPAT, 52, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_NOBREAK, 52, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 0, 0, UTF8PROC_BOUNDCLASS_ZWJ, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NOBREAK, 3895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PI, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZL, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZP, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRE, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLE, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_PDF, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRO, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLO, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 20288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 36674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_CS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_FSI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_PDI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 3929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8, UINT16_MAX, 3930, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 3931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 3932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 3933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 3934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 3935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 3936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, 3937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, 3938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 3939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 3940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 3941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 13, UINT16_MAX, 3942, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 3929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 66, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 58, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 59, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 3931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 3932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 3933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 3934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 3935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 3936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, 3937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, 3938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 3939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 3940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 3941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 0, UINT16_MAX, 3943, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 4, UINT16_MAX, 3944, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 14, UINT16_MAX, 3945, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 23, UINT16_MAX, 3946, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 615, UINT16_MAX, 3947, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 7, UINT16_MAX, 3948, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 10, UINT16_MAX, 3949, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 11, UINT16_MAX, 3950, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 12, UINT16_MAX, 3951, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 13, UINT16_MAX, 3952, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 15, UINT16_MAX, 3953, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 18, UINT16_MAX, 3954, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 19, UINT16_MAX, 3955, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 20340, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 3964, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36735, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1020, UINT16_MAX, UINT16_MAX, 3973, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 3976, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 3977, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 3978, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 3979, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 3980, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 357, UINT16_MAX, 3981, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 3982, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 3983, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 3984, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 3985, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 3986, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 3989, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 3990, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 3991, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 3992, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 3993, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 20378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 20383, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 4001, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1252, 1206, UINT16_MAX, 1206, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 4002, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 36, 10, UINT16_MAX, 10, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 179, 94, UINT16_MAX, 94, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 4003, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 4004, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 4005, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 4006, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 4007, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4008, UINT16_MAX, 4008, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 4009, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 4010, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 4011, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 4012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 4013, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 4014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 4015, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1198, UINT16_MAX, 4019, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1187, UINT16_MAX, 4020, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1233, UINT16_MAX, UINT16_MAX, 4021, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1244, UINT16_MAX, UINT16_MAX, 4022, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, 4023, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 4024, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 4025, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 4026, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 4027, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 4028, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4029, UINT16_MAX, 4029, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 53188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36824, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36833, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36836, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 20461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 34, 4079, UINT16_MAX, 4079, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20464, 4082, UINT16_MAX, 4082, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36851, 4086, UINT16_MAX, 4086, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20471, 4089, UINT16_MAX, 4089, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 47, 4090, UINT16_MAX, 4090, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20475, 4093, UINT16_MAX, 4093, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36862, 4097, UINT16_MAX, 4097, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53250, 4103, UINT16_MAX, 4103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20488, 4106, UINT16_MAX, 4106, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 49, 4107, UINT16_MAX, 4107, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20492, 4110, UINT16_MAX, 4110, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36879, 4114, UINT16_MAX, 4114, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37, 4115, UINT16_MAX, 4115, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28, 4116, UINT16_MAX, 4116, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 29, 4117, UINT16_MAX, 4117, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38, 4118, UINT16_MAX, 4118, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8, UINT16_MAX, 4119, UINT16_MAX, 4119, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20504, UINT16_MAX, 4122, UINT16_MAX, 4122, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36891, UINT16_MAX, 4126, UINT16_MAX, 4126, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20511, UINT16_MAX, 4129, UINT16_MAX, 4129, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21, UINT16_MAX, 4130, UINT16_MAX, 4130, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20515, UINT16_MAX, 4133, UINT16_MAX, 4133, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36902, UINT16_MAX, 4137, UINT16_MAX, 4137, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 53290, UINT16_MAX, 4143, UINT16_MAX, 4143, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20528, UINT16_MAX, 4146, UINT16_MAX, 4146, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23, UINT16_MAX, 4147, UINT16_MAX, 4147, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20532, UINT16_MAX, 4150, UINT16_MAX, 4150, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 36919, UINT16_MAX, 4154, UINT16_MAX, 4154, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11, UINT16_MAX, 4155, UINT16_MAX, 4155, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2, UINT16_MAX, 4156, UINT16_MAX, 4156, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3, UINT16_MAX, 4157, UINT16_MAX, 4157, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12, UINT16_MAX, 4158, UINT16_MAX, 4158, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4159, UINT16_MAX, 4159, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4160, UINT16_MAX, 4160, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 36929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5039, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5045, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5048, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5054, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5051, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5057, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5060, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5063, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5066, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5069, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36956, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 36961, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5072, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5075, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5078, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5081, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5090, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5087, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5099, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5102, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5105, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5108, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5111, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5114, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5117, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5120, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5147, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5150, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5123, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5126, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5129, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5132, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5153, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5156, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5135, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5138, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5141, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5144, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5159, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5162, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5165, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5168, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, 4262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, 4263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 66, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 58, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 59, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 3931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 3932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 3933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 3934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 3935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 3936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 20668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37057, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37069, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37075, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 20752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 20754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 20756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 20758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 20760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 20762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 20764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 20766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 20768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37172, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 37184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37214, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37241, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 37262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 26, 4497, UINT16_MAX, 4497, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 27, 4498, UINT16_MAX, 4498, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 28, 4499, UINT16_MAX, 4499, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 29, 4500, UINT16_MAX, 4500, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 30, 4501, UINT16_MAX, 4501, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 31, 4502, UINT16_MAX, 4502, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 32, 4503, UINT16_MAX, 4503, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 33, 4504, UINT16_MAX, 4504, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 34, 4505, UINT16_MAX, 4505, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 35, 4506, UINT16_MAX, 4506, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 36, 4507, UINT16_MAX, 4507, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 37, 4508, UINT16_MAX, 4508, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 38, 4509, UINT16_MAX, 4509, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 39, 4510, UINT16_MAX, 4510, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 40, 4511, UINT16_MAX, 4511, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 41, 4512, UINT16_MAX, 4512, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 42, 4513, UINT16_MAX, 4513, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 43, 4514, UINT16_MAX, 4514, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 44, 4515, UINT16_MAX, 4515, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 45, 4516, UINT16_MAX, 4516, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 46, 4517, UINT16_MAX, 4517, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 47, 4518, UINT16_MAX, 4518, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 48, 4519, UINT16_MAX, 4519, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 49, 4520, UINT16_MAX, 4520, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 50, 4521, UINT16_MAX, 4521, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 51, 4522, UINT16_MAX, 4522, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 0, UINT16_MAX, 4523, UINT16_MAX, 4523, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1, UINT16_MAX, 4524, UINT16_MAX, 4524, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2, UINT16_MAX, 4525, UINT16_MAX, 4525, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3, UINT16_MAX, 4526, UINT16_MAX, 4526, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4, UINT16_MAX, 4527, UINT16_MAX, 4527, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5, UINT16_MAX, 4528, UINT16_MAX, 4528, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 6, UINT16_MAX, 4529, UINT16_MAX, 4529, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 7, UINT16_MAX, 4530, UINT16_MAX, 4530, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 8, UINT16_MAX, 4531, UINT16_MAX, 4531, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 9, UINT16_MAX, 4532, UINT16_MAX, 4532, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 10, UINT16_MAX, 4533, UINT16_MAX, 4533, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 11, UINT16_MAX, 4534, UINT16_MAX, 4534, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12, UINT16_MAX, 4535, UINT16_MAX, 4535, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 13, UINT16_MAX, 4536, UINT16_MAX, 4536, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 14, UINT16_MAX, 4537, UINT16_MAX, 4537, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 15, UINT16_MAX, 4538, UINT16_MAX, 4538, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 16, UINT16_MAX, 4539, UINT16_MAX, 4539, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 17, UINT16_MAX, 4540, UINT16_MAX, 4540, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 18, UINT16_MAX, 4541, UINT16_MAX, 4541, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 19, UINT16_MAX, 4542, UINT16_MAX, 4542, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20, UINT16_MAX, 4543, UINT16_MAX, 4543, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21, UINT16_MAX, 4544, UINT16_MAX, 4544, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 22, UINT16_MAX, 4545, UINT16_MAX, 4545, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 23, UINT16_MAX, 4546, UINT16_MAX, 4546, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 24, UINT16_MAX, 4547, UINT16_MAX, 4547, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 25, UINT16_MAX, 4548, UINT16_MAX, 4548, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 3929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 20941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 37327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 20946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5171, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4564, UINT16_MAX, 4564, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4565, UINT16_MAX, 4565, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4566, UINT16_MAX, 4566, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4567, UINT16_MAX, 4567, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4568, UINT16_MAX, 4568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4569, UINT16_MAX, 4569, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4570, UINT16_MAX, 4570, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4571, UINT16_MAX, 4571, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4572, UINT16_MAX, 4572, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4573, UINT16_MAX, 4573, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4574, UINT16_MAX, 4574, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4575, UINT16_MAX, 4575, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4576, UINT16_MAX, 4576, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4577, UINT16_MAX, 4577, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4578, UINT16_MAX, 4578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4579, UINT16_MAX, 4579, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4580, UINT16_MAX, 4580, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4581, UINT16_MAX, 4581, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4582, UINT16_MAX, 4582, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4583, UINT16_MAX, 4583, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4584, UINT16_MAX, 4584, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4585, UINT16_MAX, 4585, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4586, UINT16_MAX, 4586, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4587, UINT16_MAX, 4587, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4588, UINT16_MAX, 4588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4589, UINT16_MAX, 4589, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4590, UINT16_MAX, 4590, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4591, UINT16_MAX, 4591, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4592, UINT16_MAX, 4592, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4593, UINT16_MAX, 4593, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4594, UINT16_MAX, 4594, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4595, UINT16_MAX, 4595, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4596, UINT16_MAX, 4596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4597, UINT16_MAX, 4597, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4598, UINT16_MAX, 4598, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4599, UINT16_MAX, 4599, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4600, UINT16_MAX, 4600, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4601, UINT16_MAX, 4601, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4602, UINT16_MAX, 4602, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4603, UINT16_MAX, 4603, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4604, UINT16_MAX, 4604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4605, UINT16_MAX, 4605, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4606, UINT16_MAX, 4606, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4607, UINT16_MAX, 4607, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4608, UINT16_MAX, 4608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4609, UINT16_MAX, 4609, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4610, UINT16_MAX, 4610, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4611, UINT16_MAX, 4611, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4612, UINT16_MAX, 4612, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4613, UINT16_MAX, 4613, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4614, UINT16_MAX, 4614, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4615, UINT16_MAX, 4615, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4616, UINT16_MAX, 4616, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4617, UINT16_MAX, 4617, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4618, UINT16_MAX, 4618, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4619, UINT16_MAX, 4619, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4620, UINT16_MAX, 4620, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4621, UINT16_MAX, 4621, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4622, UINT16_MAX, 4622, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4623, UINT16_MAX, 4623, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4624, UINT16_MAX, 4624, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4625, UINT16_MAX, 4625, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4626, UINT16_MAX, 4626, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4627, UINT16_MAX, 4627, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4628, UINT16_MAX, 4628, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4629, UINT16_MAX, 4629, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4630, UINT16_MAX, 4630, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4631, UINT16_MAX, 4631, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4632, UINT16_MAX, 4632, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4633, UINT16_MAX, 4633, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4634, UINT16_MAX, 4634, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4635, UINT16_MAX, 4635, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4636, UINT16_MAX, 4636, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4637, UINT16_MAX, 4637, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4638, UINT16_MAX, 4638, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4639, UINT16_MAX, 4639, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4640, UINT16_MAX, 4640, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4641, UINT16_MAX, 4641, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4642, UINT16_MAX, 4642, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4643, UINT16_MAX, 4643, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4644, UINT16_MAX, 4644, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4645, UINT16_MAX, 4645, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4646, UINT16_MAX, 4646, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4647, UINT16_MAX, 4647, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4648, UINT16_MAX, 4648, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4649, UINT16_MAX, 4649, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4650, UINT16_MAX, 4650, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4651, UINT16_MAX, 4651, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4652, UINT16_MAX, 4652, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4653, UINT16_MAX, 4653, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4654, UINT16_MAX, 4654, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4655, UINT16_MAX, 4655, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4656, UINT16_MAX, 4656, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4657, UINT16_MAX, 4657, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4658, UINT16_MAX, 4658, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4659, UINT16_MAX, 4659, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4660, UINT16_MAX, 4660, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4661, UINT16_MAX, 4661, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4662, UINT16_MAX, 4662, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4663, UINT16_MAX, 4663, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4664, UINT16_MAX, 4664, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4665, UINT16_MAX, 4665, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4666, UINT16_MAX, 4666, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4667, UINT16_MAX, 4667, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4668, UINT16_MAX, 4668, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4669, UINT16_MAX, 4669, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4670, UINT16_MAX, 4670, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4671, UINT16_MAX, 4671, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4672, UINT16_MAX, 4672, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2274, UINT16_MAX, 2274, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2384, UINT16_MAX, 2384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2272, UINT16_MAX, 2272, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2362, UINT16_MAX, 2362, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4673, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4674, UINT16_MAX, 4674, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4675, UINT16_MAX, 4675, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4676, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4677, UINT16_MAX, 4677, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4678, UINT16_MAX, 4678, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4679, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4680, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4681, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4682, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4683, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 9, UINT16_MAX, 4684, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 47, UINT16_MAX, 4685, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4686, UINT16_MAX, 4686, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4687, UINT16_MAX, 4687, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4688, UINT16_MAX, 4688, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4689, UINT16_MAX, 4689, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4690, UINT16_MAX, 4690, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4691, UINT16_MAX, 4691, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4692, UINT16_MAX, 4692, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4693, UINT16_MAX, 4693, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4694, UINT16_MAX, 4694, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4695, UINT16_MAX, 4695, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4696, UINT16_MAX, 4696, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4697, UINT16_MAX, 4697, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4698, UINT16_MAX, 4698, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4699, UINT16_MAX, 4699, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4700, UINT16_MAX, 4700, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4701, UINT16_MAX, 4701, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4702, UINT16_MAX, 4702, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4703, UINT16_MAX, 4703, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4704, UINT16_MAX, 4704, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4705, UINT16_MAX, 4705, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4706, UINT16_MAX, 4706, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4707, UINT16_MAX, 4707, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4708, UINT16_MAX, 4708, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4709, UINT16_MAX, 4709, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4710, UINT16_MAX, 4710, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4711, UINT16_MAX, 4711, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4712, UINT16_MAX, 4712, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4713, UINT16_MAX, 4713, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4714, UINT16_MAX, 4714, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4715, UINT16_MAX, 4715, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4716, UINT16_MAX, 4716, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4717, UINT16_MAX, 4717, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4718, UINT16_MAX, 4718, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4719, UINT16_MAX, 4719, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4720, UINT16_MAX, 4720, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4721, UINT16_MAX, 4721, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4722, UINT16_MAX, 4722, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4723, UINT16_MAX, 4723, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4724, UINT16_MAX, 4724, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4725, UINT16_MAX, 4725, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4726, UINT16_MAX, 4726, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4727, UINT16_MAX, 4727, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4728, UINT16_MAX, 4728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4729, UINT16_MAX, 4729, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4730, UINT16_MAX, 4730, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4731, UINT16_MAX, 4731, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4732, UINT16_MAX, 4732, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4733, UINT16_MAX, 4733, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4734, UINT16_MAX, 4734, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4735, UINT16_MAX, 4735, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4736, UINT16_MAX, 4736, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4737, UINT16_MAX, 4737, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4738, UINT16_MAX, 4738, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4739, UINT16_MAX, 4739, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4740, UINT16_MAX, 4740, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4741, UINT16_MAX, 4741, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4742, UINT16_MAX, 4742, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4743, UINT16_MAX, 4743, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4744, UINT16_MAX, 4744, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4745, UINT16_MAX, 4745, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4746, UINT16_MAX, 4746, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4747, UINT16_MAX, 4747, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4748, UINT16_MAX, 4748, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4749, UINT16_MAX, 4749, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4750, UINT16_MAX, 4750, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4751, UINT16_MAX, 4751, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4752, UINT16_MAX, 4752, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4753, UINT16_MAX, 4753, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4754, UINT16_MAX, 4754, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4755, UINT16_MAX, 4755, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4756, UINT16_MAX, 4756, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4757, UINT16_MAX, 4757, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4758, UINT16_MAX, 4758, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4759, UINT16_MAX, 4759, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4760, UINT16_MAX, 4760, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4761, UINT16_MAX, 4761, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4762, UINT16_MAX, 4762, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4763, UINT16_MAX, 4763, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4764, UINT16_MAX, 4764, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4765, UINT16_MAX, 4765, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4766, UINT16_MAX, 4766, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4767, UINT16_MAX, 4767, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4768, UINT16_MAX, 4768, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4769, UINT16_MAX, 4769, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4770, UINT16_MAX, 4770, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4771, UINT16_MAX, 4771, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4772, UINT16_MAX, 4772, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4773, UINT16_MAX, 4773, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4774, UINT16_MAX, 4774, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4775, UINT16_MAX, 4775, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4776, UINT16_MAX, 4776, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4777, UINT16_MAX, 4777, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4778, UINT16_MAX, 4778, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4779, UINT16_MAX, 4779, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4780, UINT16_MAX, 4780, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4781, UINT16_MAX, 4781, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4782, UINT16_MAX, 4782, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4783, UINT16_MAX, 4783, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4784, UINT16_MAX, 4784, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4785, UINT16_MAX, 4785, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4786, UINT16_MAX, 4786, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4787, UINT16_MAX, 4787, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4788, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4789, UINT16_MAX, 4789, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4790, UINT16_MAX, 4790, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4791, UINT16_MAX, 4791, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4792, UINT16_MAX, 4792, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4793, UINT16_MAX, 4793, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4794, UINT16_MAX, 4794, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4795, UINT16_MAX, 4795, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4796, UINT16_MAX, 4796, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4797, UINT16_MAX, 4797, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4798, UINT16_MAX, 4798, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4799, UINT16_MAX, 4799, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4800, UINT16_MAX, 4800, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4801, UINT16_MAX, 4801, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4802, UINT16_MAX, 4802, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4803, UINT16_MAX, 4803, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4804, UINT16_MAX, 4804, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4805, UINT16_MAX, 4805, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4806, UINT16_MAX, 4806, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4807, UINT16_MAX, 4807, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4808, UINT16_MAX, 4808, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4809, UINT16_MAX, 4809, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4810, UINT16_MAX, 4810, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4811, UINT16_MAX, 4811, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4812, UINT16_MAX, 4812, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4813, UINT16_MAX, 4813, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4814, UINT16_MAX, 4814, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4815, UINT16_MAX, 4815, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4816, UINT16_MAX, 4816, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4817, UINT16_MAX, 4817, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4818, UINT16_MAX, 4818, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4819, UINT16_MAX, 4819, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4820, UINT16_MAX, 4820, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4821, UINT16_MAX, 4821, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4822, UINT16_MAX, 4822, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4823, UINT16_MAX, 4823, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4824, UINT16_MAX, 4824, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4825, UINT16_MAX, 4825, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4826, UINT16_MAX, 4826, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4827, UINT16_MAX, 4827, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4828, UINT16_MAX, 4828, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4829, UINT16_MAX, 4829, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4830, UINT16_MAX, 4830, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4831, UINT16_MAX, 4831, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4832, UINT16_MAX, 4832, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4833, UINT16_MAX, 4833, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 4834, UINT16_MAX, 4834, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4836, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4885, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4893, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4905, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4906, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4913, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4927, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4930, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4942, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4944, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4945, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4947, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4948, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4949, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4950, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4951, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4952, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4954, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4955, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4956, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4958, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4959, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4960, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4961, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4962, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4963, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4964, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4965, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4966, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4967, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4968, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4969, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4970, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4971, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4973, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4974, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4976, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4977, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4978, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4979, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4980, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4982, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4984, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4985, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4987, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4989, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4990, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4991, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4993, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4995, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4997, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 4999, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5000, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5001, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5002, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5003, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5005, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5006, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5007, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5009, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5010, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5011, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5013, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5015, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5017, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5019, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5021, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5023, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5025, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5027, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5029, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5031, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5033, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5035, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5037, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5039, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5041, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5043, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5045, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5047, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5049, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5051, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_WIDE, 52, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 224, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 5052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 4861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5053, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5239, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5174, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5177, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5180, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5183, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5186, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5189, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5192, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5195, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5198, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5201, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5204, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5207, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5210, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5213, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5216, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5219, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5223, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5227, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5231, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5235, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32820, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32821, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 21491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 21493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5242, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, 21495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, 21497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5310, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5245, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5248, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5251, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5254, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5257, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5260, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5263, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5266, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5269, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5272, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5275, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5278, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5281, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5284, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5287, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5290, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5294, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5298, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5302, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5306, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5313, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5316, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5319, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5322, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 21557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5325, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, 21559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, 21561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5203, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5214, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5215, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5218, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5239, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5241, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5245, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 5272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38051, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38057, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38069, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38075, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38081, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38084, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38087, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 54547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 54552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 54560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 38294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21913, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21927, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21945, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21947, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21949, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21951, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21955, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21959, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21961, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21963, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21965, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21967, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21969, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 54739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 54745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 21982, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 22044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 22073, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 38459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 22078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 38464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5702, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5704, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5706, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5707, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5710, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5712, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5713, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5714, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5715, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5716, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5719, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5723, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5724, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5725, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5727, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5728, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5731, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5732, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5733, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5734, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5735, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5736, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54905, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54949, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54954, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54970, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54982, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 54995, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55010, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55035, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55041, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55069, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55083, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55107, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55139, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22379, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55172, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38913, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 38916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 22549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 38935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 38938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 22557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38997, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39000, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39003, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39029, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39037, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39045, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39061, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22707, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22713, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22715, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22719, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22723, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22725, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22727, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22731, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22733, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39135, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39168, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 55557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 39189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 39192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 39276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 39279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6514, UINT16_MAX, 6514, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6515, UINT16_MAX, 6515, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6516, UINT16_MAX, 6516, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6517, UINT16_MAX, 6517, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6518, UINT16_MAX, 6518, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6519, UINT16_MAX, 6519, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6520, UINT16_MAX, 6520, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6521, UINT16_MAX, 6521, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6522, UINT16_MAX, 6522, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6523, UINT16_MAX, 6523, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2202, UINT16_MAX, 2202, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2203, UINT16_MAX, 2203, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6524, UINT16_MAX, 6524, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6525, UINT16_MAX, 6525, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6526, UINT16_MAX, 6526, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6527, UINT16_MAX, 6527, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6528, UINT16_MAX, 6528, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6529, UINT16_MAX, 6529, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6530, UINT16_MAX, 6530, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6531, UINT16_MAX, 6531, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6532, UINT16_MAX, 6532, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6533, UINT16_MAX, 6533, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6534, UINT16_MAX, 6534, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6535, UINT16_MAX, 6535, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6536, UINT16_MAX, 6536, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6537, UINT16_MAX, 6537, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6538, UINT16_MAX, 6538, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6539, UINT16_MAX, 6539, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6540, UINT16_MAX, 6540, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6541, UINT16_MAX, 6541, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6542, UINT16_MAX, 6542, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6543, UINT16_MAX, 6543, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6544, UINT16_MAX, 6544, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6545, UINT16_MAX, 6545, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6546, UINT16_MAX, 6546, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6547, UINT16_MAX, 6547, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6548, UINT16_MAX, 6548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6549, UINT16_MAX, 6549, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6550, UINT16_MAX, 6550, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6551, UINT16_MAX, 6551, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6552, UINT16_MAX, 6552, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6553, UINT16_MAX, 6553, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6554, UINT16_MAX, 6554, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6555, UINT16_MAX, 6555, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6556, UINT16_MAX, 6556, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6557, UINT16_MAX, 6557, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6558, UINT16_MAX, 6558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6559, UINT16_MAX, 6559, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6560, UINT16_MAX, 6560, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6561, UINT16_MAX, 6561, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6562, UINT16_MAX, 6562, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6563, UINT16_MAX, 6563, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6564, UINT16_MAX, 6564, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6565, UINT16_MAX, 6565, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6566, UINT16_MAX, 6566, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6567, UINT16_MAX, 6567, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6568, UINT16_MAX, 6568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6569, UINT16_MAX, 6569, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6570, UINT16_MAX, 6570, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6571, UINT16_MAX, 6571, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6572, UINT16_MAX, 6572, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6573, UINT16_MAX, 6573, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6574, UINT16_MAX, 6574, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6575, UINT16_MAX, 6575, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6576, UINT16_MAX, 6576, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6577, UINT16_MAX, 6577, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6578, UINT16_MAX, 6578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6579, UINT16_MAX, 6579, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6580, UINT16_MAX, 6580, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6581, UINT16_MAX, 6581, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6582, UINT16_MAX, 6582, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6583, UINT16_MAX, 6583, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6584, UINT16_MAX, 6584, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6585, UINT16_MAX, 6585, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1371, UINT16_MAX, 6586, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1373, UINT16_MAX, 6587, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6588, UINT16_MAX, 6588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6589, UINT16_MAX, 6589, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6590, UINT16_MAX, 6590, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6591, UINT16_MAX, 6591, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6592, UINT16_MAX, 6592, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6593, UINT16_MAX, 6593, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6594, UINT16_MAX, 6594, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6595, UINT16_MAX, 6595, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6596, UINT16_MAX, 6596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6597, UINT16_MAX, 6597, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6598, UINT16_MAX, 6598, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6599, UINT16_MAX, 6599, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6600, UINT16_MAX, 6600, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6601, UINT16_MAX, 6601, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6602, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6603, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6604, UINT16_MAX, 6604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6605, UINT16_MAX, 6605, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6606, UINT16_MAX, 6606, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6607, UINT16_MAX, 6607, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6608, UINT16_MAX, 6608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6609, UINT16_MAX, 6609, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6610, UINT16_MAX, 6610, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6611, UINT16_MAX, 6611, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6612, UINT16_MAX, 6612, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6613, UINT16_MAX, 6613, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6614, UINT16_MAX, 6614, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6615, UINT16_MAX, 6615, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6616, UINT16_MAX, 6616, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6617, UINT16_MAX, 6617, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6618, UINT16_MAX, 6618, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6619, UINT16_MAX, 6619, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6620, UINT16_MAX, 6620, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6621, UINT16_MAX, 6621, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6622, UINT16_MAX, 6622, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6623, UINT16_MAX, 6623, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6624, UINT16_MAX, 6624, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6625, UINT16_MAX, 6625, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6626, UINT16_MAX, 6626, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6627, UINT16_MAX, 6627, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6628, UINT16_MAX, 6628, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6629, UINT16_MAX, 6629, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6630, UINT16_MAX, 6630, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6631, UINT16_MAX, 6631, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6632, UINT16_MAX, 6632, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6633, UINT16_MAX, 6633, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6634, UINT16_MAX, 6634, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6635, UINT16_MAX, 6635, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6636, UINT16_MAX, 6636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6637, UINT16_MAX, 6637, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6638, UINT16_MAX, 6638, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6639, UINT16_MAX, 6639, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6640, UINT16_MAX, 6640, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6641, UINT16_MAX, 6641, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6642, UINT16_MAX, 6642, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6643, UINT16_MAX, 6643, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6644, UINT16_MAX, 6644, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6645, UINT16_MAX, 6645, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6646, UINT16_MAX, 6646, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6647, UINT16_MAX, 6647, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6648, UINT16_MAX, 6648, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6649, UINT16_MAX, 6649, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6650, UINT16_MAX, 6650, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6651, UINT16_MAX, 6651, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6652, UINT16_MAX, 6652, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6653, UINT16_MAX, 6653, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6654, UINT16_MAX, 6654, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6655, UINT16_MAX, 6655, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6656, UINT16_MAX, 6656, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6657, UINT16_MAX, 6657, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6658, UINT16_MAX, 6658, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6659, UINT16_MAX, 6659, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6660, UINT16_MAX, 6660, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6661, UINT16_MAX, 6661, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6662, UINT16_MAX, 6662, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6663, UINT16_MAX, 6663, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6664, UINT16_MAX, 6664, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6665, UINT16_MAX, 6665, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6664, UINT16_MAX, 6666, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6667, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6668, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6669, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6670, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6671, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6672, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6673, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6674, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6675, UINT16_MAX, 6675, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6676, UINT16_MAX, 6676, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6677, UINT16_MAX, 6677, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6678, UINT16_MAX, 6678, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6679, UINT16_MAX, 6679, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6680, UINT16_MAX, 6680, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6681, UINT16_MAX, 6681, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6682, UINT16_MAX, 6682, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6683, UINT16_MAX, 6683, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6684, UINT16_MAX, 6684, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6685, UINT16_MAX, 6685, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6686, UINT16_MAX, 6686, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6687, UINT16_MAX, 6687, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6688, UINT16_MAX, 6688, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6689, UINT16_MAX, 6689, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6690, UINT16_MAX, 6690, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6691, UINT16_MAX, 6691, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2372, UINT16_MAX, 2372, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6692, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6693, UINT16_MAX, 6693, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6694, UINT16_MAX, 6694, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6695, UINT16_MAX, 6695, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6696, UINT16_MAX, 6696, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6697, UINT16_MAX, 6697, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6698, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6699, UINT16_MAX, 6699, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6700, UINT16_MAX, 6700, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6701, UINT16_MAX, 6701, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6702, UINT16_MAX, 6702, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6703, UINT16_MAX, 6703, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6704, UINT16_MAX, 6704, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6705, UINT16_MAX, 6705, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6706, UINT16_MAX, 6706, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6707, UINT16_MAX, 6707, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6708, UINT16_MAX, 6708, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6709, UINT16_MAX, 6709, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6710, UINT16_MAX, 6710, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6711, UINT16_MAX, 6711, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6712, UINT16_MAX, 6712, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6713, UINT16_MAX, 6713, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6714, UINT16_MAX, 6714, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6715, UINT16_MAX, 6715, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6716, UINT16_MAX, 6716, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6717, UINT16_MAX, 6717, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6718, UINT16_MAX, 6718, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1105, UINT16_MAX, 1105, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2282, UINT16_MAX, 2282, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2370, UINT16_MAX, 2370, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6719, UINT16_MAX, 6719, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2376, UINT16_MAX, 2376, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6720, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6721, UINT16_MAX, 6721, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6722, UINT16_MAX, 6722, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2379, UINT16_MAX, 2379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6723, UINT16_MAX, 6723, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6724, UINT16_MAX, 6724, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6725, UINT16_MAX, 6725, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6726, UINT16_MAX, 6726, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6727, UINT16_MAX, 6727, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6728, UINT16_MAX, 6728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6729, UINT16_MAX, 6729, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6730, UINT16_MAX, 6730, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6731, UINT16_MAX, 6731, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6732, UINT16_MAX, 6732, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6733, UINT16_MAX, 6733, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6734, UINT16_MAX, 6734, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6735, UINT16_MAX, 6735, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6736, UINT16_MAX, 6736, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6737, UINT16_MAX, 6737, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6738, UINT16_MAX, 6738, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6739, UINT16_MAX, 6739, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6740, UINT16_MAX, 6740, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2392, UINT16_MAX, 2392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6741, UINT16_MAX, 6741, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6742, UINT16_MAX, 6742, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6743, UINT16_MAX, 6743, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6744, UINT16_MAX, 6744, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6745, UINT16_MAX, 6745, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6746, UINT16_MAX, 6746, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6747, UINT16_MAX, 6747, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6748, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6749, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6750, UINT16_MAX, 6750, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6751, UINT16_MAX, 6751, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6752, UINT16_MAX, 6752, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6753, UINT16_MAX, 6753, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 28, UINT16_MAX, 6754, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 31, UINT16_MAX, 6755, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 42, UINT16_MAX, 6756, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6757, UINT16_MAX, 6757, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6758, UINT16_MAX, 6758, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 358, UINT16_MAX, 6759, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 473, UINT16_MAX, 6760, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6761, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6762, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6763, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6764, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6765, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6766, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6767, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6768, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6769, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6770, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6771, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6772, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6773, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6774, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6775, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6776, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6777, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6778, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6779, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6780, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6781, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6782, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6783, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6784, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6785, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6786, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6787, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6788, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6789, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6790, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6791, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6792, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6793, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6794, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6795, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6796, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6797, UINT16_MAX, 6797, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6798, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6799, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6800, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6801, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6802, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6803, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6804, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6592, UINT16_MAX, 6805, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6769, UINT16_MAX, 6806, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4662, UINT16_MAX, 6807, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6796, UINT16_MAX, 6808, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6809, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6810, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6811, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6812, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6813, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6814, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6815, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6816, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 6817, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1070, UINT16_MAX, 6818, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6819, 6819, UINT16_MAX, 6819, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6820, 6820, UINT16_MAX, 6820, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6821, 6821, UINT16_MAX, 6821, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6822, 6822, UINT16_MAX, 6822, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6823, 6823, UINT16_MAX, 6823, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6824, 6824, UINT16_MAX, 6824, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6825, 6825, UINT16_MAX, 6825, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6826, 6826, UINT16_MAX, 6826, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6827, 6827, UINT16_MAX, 6827, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6828, 6828, UINT16_MAX, 6828, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6829, 6829, UINT16_MAX, 6829, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6830, 6830, UINT16_MAX, 6830, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6831, 6831, UINT16_MAX, 6831, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6832, 6832, UINT16_MAX, 6832, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6833, 6833, UINT16_MAX, 6833, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6834, 6834, UINT16_MAX, 6834, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6835, 6835, UINT16_MAX, 6835, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6836, 6836, UINT16_MAX, 6836, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6837, 6837, UINT16_MAX, 6837, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6838, 6838, UINT16_MAX, 6838, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6839, 6839, UINT16_MAX, 6839, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6840, 6840, UINT16_MAX, 6840, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6841, 6841, UINT16_MAX, 6841, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6842, 6842, UINT16_MAX, 6842, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6843, 6843, UINT16_MAX, 6843, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6844, 6844, UINT16_MAX, 6844, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6845, 6845, UINT16_MAX, 6845, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6846, 6846, UINT16_MAX, 6846, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6847, 6847, UINT16_MAX, 6847, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6848, 6848, UINT16_MAX, 6848, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6849, 6849, UINT16_MAX, 6849, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6850, 6850, UINT16_MAX, 6850, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6851, 6851, UINT16_MAX, 6851, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6852, 6852, UINT16_MAX, 6852, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6853, 6853, UINT16_MAX, 6853, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6854, 6854, UINT16_MAX, 6854, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6855, 6855, UINT16_MAX, 6855, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6856, 6856, UINT16_MAX, 6856, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6857, 6857, UINT16_MAX, 6857, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6858, 6858, UINT16_MAX, 6858, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6859, 6859, UINT16_MAX, 6859, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6860, 6860, UINT16_MAX, 6860, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6861, 6861, UINT16_MAX, 6861, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6862, 6862, UINT16_MAX, 6862, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6863, 6863, UINT16_MAX, 6863, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6864, 6864, UINT16_MAX, 6864, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6865, 6865, UINT16_MAX, 6865, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6866, 6866, UINT16_MAX, 6866, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6867, 6867, UINT16_MAX, 6867, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6868, 6868, UINT16_MAX, 6868, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6869, 6869, UINT16_MAX, 6869, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6870, 6870, UINT16_MAX, 6870, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6871, 6871, UINT16_MAX, 6871, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6872, 6872, UINT16_MAX, 6872, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6873, 6873, UINT16_MAX, 6873, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6874, 6874, UINT16_MAX, 6874, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6875, 6875, UINT16_MAX, 6875, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6876, 6876, UINT16_MAX, 6876, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6877, 6877, UINT16_MAX, 6877, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6878, 6878, UINT16_MAX, 6878, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6879, 6879, UINT16_MAX, 6879, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6880, 6880, UINT16_MAX, 6880, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6881, 6881, UINT16_MAX, 6881, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6882, 6882, UINT16_MAX, 6882, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6883, 6883, UINT16_MAX, 6883, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6884, 6884, UINT16_MAX, 6884, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6885, 6885, UINT16_MAX, 6885, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6886, 6886, UINT16_MAX, 6886, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6887, 6887, UINT16_MAX, 6887, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6888, 6888, UINT16_MAX, 6888, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6889, 6889, UINT16_MAX, 6889, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6890, 6890, UINT16_MAX, 6890, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6891, 6891, UINT16_MAX, 6891, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6892, 6892, UINT16_MAX, 6892, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6893, 6893, UINT16_MAX, 6893, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6894, 6894, UINT16_MAX, 6894, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6895, 6895, UINT16_MAX, 6895, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6896, 6896, UINT16_MAX, 6896, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6897, 6897, UINT16_MAX, 6897, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6898, 6898, UINT16_MAX, 6898, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_LV, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_LVT, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CS, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6905, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6906, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6913, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6927, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6930, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6942, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6944, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6945, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4962, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6947, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6948, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6949, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6950, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6951, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6952, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6954, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6955, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6956, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5035, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6958, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6959, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6960, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6961, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6962, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6963, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6964, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6965, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6966, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6967, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6968, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6969, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6970, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6971, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6973, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6974, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6976, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6977, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6978, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6979, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6980, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6982, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6984, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6985, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6987, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6989, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6990, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6991, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6993, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6995, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6997, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 6999, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7000, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7001, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7002, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7003, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7005, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7006, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7007, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7009, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7010, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7011, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7013, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7015, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7017, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7019, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7021, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7023, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7025, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7027, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7029, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7031, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7033, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7035, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7037, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7039, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7041, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7043, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7045, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7047, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7049, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7051, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7053, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7055, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7057, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7059, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7061, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7065, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7069, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7071, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7073, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7074, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7075, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7077, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7079, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7080, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7081, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5049, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7083, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7084, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7085, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7087, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7088, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7089, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7091, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7093, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7095, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7097, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7098, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7099, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7100, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7101, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7103, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7105, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7106, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7107, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7109, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7110, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7111, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7112, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7113, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7115, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5003, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7117, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7118, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7119, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7120, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7121, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7123, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7124, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7125, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7127, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4954, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7129, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7131, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7133, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7135, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7136, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7137, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7139, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7141, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7143, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7145, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4984, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7149, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7150, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7151, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7152, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7155, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7156, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4961, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7161, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7168, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7170, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7172, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7203, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7214, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7215, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7218, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7239, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7241, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7245, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7284, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23696, 23696, 7314, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23699, 23699, 7317, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23702, 23702, 7320, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40089, 40089, 7324, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 40093, 40093, 7328, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23713, 23715, 7333, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23715, 23715, 7334, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23719, 23719, 7337, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23722, 23722, 7340, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23725, 23725, 7343, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23728, 23728, 7346, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23731, 23731, 7349, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23734, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 26, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23736, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 7354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 4011, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 4014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 7355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 7356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 7357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 7358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 7359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 7360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_FONT, 3937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23751, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23753, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23755, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23791, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23805, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 23807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_COMPAT, 23809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 7483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 7483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23906, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23930, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23942, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23944, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23948, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23950, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23952, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23954, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23956, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23958, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23960, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23962, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23964, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23966, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23968, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23970, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23974, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23976, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23978, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23980, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23982, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23984, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23990, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 23998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24000, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24002, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24006, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24010, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 40438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 40441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 40444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 40447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 40450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 40453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24074, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24080, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24084, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24088, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23906, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23964, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23966, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23974, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23976, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23984, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23990, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 23998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24000, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24002, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24010, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24098, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24100, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24106, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24110, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24112, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23890, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23930, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24118, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23942, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23948, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23950, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23952, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23954, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23956, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23958, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23960, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23962, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23968, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23970, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23978, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23980, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23982, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23984, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24120, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24006, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24010, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24124, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24112, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23984, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 40520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 40523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 40526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24145, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24149, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24151, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24155, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24161, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24145, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24149, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24151, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24155, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24161, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 24134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 23944, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23944, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 23946, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40702, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40702, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40714, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40723, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40732, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40735, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40753, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40816, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40828, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40831, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 40636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 40864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 40867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 40870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 57257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 57262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 57267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 57272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 57277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 57282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 57287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 40908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 57295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 57314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 57323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 1153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 3940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 3941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 4262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 4263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 8202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8203, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 8176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 3898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 1153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 8179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 3940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 3941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 8204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, 3937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, 8207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 3939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 8211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 8212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 8213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 24624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8245, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8245, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 7466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 7466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 8276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 8276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 8276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 8276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 24667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 24667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 8204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 8211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 8212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 3940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 3941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, 3937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 8176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, 8207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 3898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 8287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 3929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 66, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 58, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 59, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 3931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 3932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 3933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 3934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 3935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 3936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 8179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 1153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 3939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 26, 8288, UINT16_MAX, 8288, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 27, 8289, UINT16_MAX, 8289, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 28, 8290, UINT16_MAX, 8290, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 29, 8291, UINT16_MAX, 8291, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 30, 8292, UINT16_MAX, 8292, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 31, 8293, UINT16_MAX, 8293, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 32, 8294, UINT16_MAX, 8294, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 33, 8295, UINT16_MAX, 8295, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 34, 8296, UINT16_MAX, 8296, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 35, 8297, UINT16_MAX, 8297, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 36, 8298, UINT16_MAX, 8298, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 37, 8299, UINT16_MAX, 8299, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 38, 8300, UINT16_MAX, 8300, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 39, 8301, UINT16_MAX, 8301, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 40, 8302, UINT16_MAX, 8302, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 41, 8303, UINT16_MAX, 8303, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 42, 8304, UINT16_MAX, 8304, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 43, 8305, UINT16_MAX, 8305, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 44, 8306, UINT16_MAX, 8306, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 45, 8307, UINT16_MAX, 8307, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 46, 8308, UINT16_MAX, 8308, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 47, 8309, UINT16_MAX, 8309, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 48, 8310, UINT16_MAX, 8310, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 49, 8311, UINT16_MAX, 8311, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 50, 8312, UINT16_MAX, 8312, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 51, 8313, UINT16_MAX, 8313, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 3854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 0, UINT16_MAX, 8315, UINT16_MAX, 8315, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1, UINT16_MAX, 8316, UINT16_MAX, 8316, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2, UINT16_MAX, 8317, UINT16_MAX, 8317, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 3, UINT16_MAX, 8318, UINT16_MAX, 8318, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 4, UINT16_MAX, 8319, UINT16_MAX, 8319, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 5, UINT16_MAX, 8320, UINT16_MAX, 8320, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 6, UINT16_MAX, 8321, UINT16_MAX, 8321, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 7, UINT16_MAX, 8322, UINT16_MAX, 8322, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 8, UINT16_MAX, 8323, UINT16_MAX, 8323, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 9, UINT16_MAX, 8324, UINT16_MAX, 8324, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 10, UINT16_MAX, 8325, UINT16_MAX, 8325, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 11, UINT16_MAX, 8326, UINT16_MAX, 8326, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 12, UINT16_MAX, 8327, UINT16_MAX, 8327, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 13, UINT16_MAX, 8328, UINT16_MAX, 8328, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 14, UINT16_MAX, 8329, UINT16_MAX, 8329, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 15, UINT16_MAX, 8330, UINT16_MAX, 8330, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 16, UINT16_MAX, 8331, UINT16_MAX, 8331, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 17, UINT16_MAX, 8332, UINT16_MAX, 8332, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 18, UINT16_MAX, 8333, UINT16_MAX, 8333, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 19, UINT16_MAX, 8334, UINT16_MAX, 8334, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 20, UINT16_MAX, 8335, UINT16_MAX, 8335, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 21, UINT16_MAX, 8336, UINT16_MAX, 8336, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 22, UINT16_MAX, 8337, UINT16_MAX, 8337, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 23, UINT16_MAX, 8338, UINT16_MAX, 8338, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 24, UINT16_MAX, 8339, UINT16_MAX, 8339, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 25, UINT16_MAX, 8340, UINT16_MAX, 8340, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8342, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8345, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5702, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5704, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5706, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5707, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5710, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5712, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5713, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5714, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5715, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5716, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5719, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5723, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5724, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5725, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5727, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5728, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5729, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5731, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5732, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5733, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5734, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5735, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5736, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 5742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8363, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8369, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8372, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8375, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8379, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8381, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8383, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8384, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8385, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8386, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8387, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8389, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8390, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8391, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8392, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8393, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8394, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8395, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8396, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8397, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8398, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8400, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8401, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8402, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8403, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8404, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8406, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 8410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 8411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 8412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 8415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 8416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 8417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8421, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 8424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8425, UINT16_MAX, 8425, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8427, UINT16_MAX, 8427, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8429, UINT16_MAX, 8429, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8431, UINT16_MAX, 8431, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8433, UINT16_MAX, 8433, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8435, UINT16_MAX, 8435, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8437, UINT16_MAX, 8437, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8439, UINT16_MAX, 8439, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8441, UINT16_MAX, 8441, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8443, UINT16_MAX, 8443, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8445, UINT16_MAX, 8445, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8447, UINT16_MAX, 8447, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8449, UINT16_MAX, 8449, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8451, UINT16_MAX, 8451, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8453, UINT16_MAX, 8453, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8455, UINT16_MAX, 8455, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8457, UINT16_MAX, 8457, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8459, UINT16_MAX, 8459, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8461, UINT16_MAX, 8461, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8463, UINT16_MAX, 8463, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8465, UINT16_MAX, 8465, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8467, UINT16_MAX, 8467, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8469, UINT16_MAX, 8469, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8471, UINT16_MAX, 8471, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8473, UINT16_MAX, 8473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8475, UINT16_MAX, 8475, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8477, UINT16_MAX, 8477, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8479, UINT16_MAX, 8479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8481, UINT16_MAX, 8481, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8483, UINT16_MAX, 8483, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8485, UINT16_MAX, 8485, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8487, UINT16_MAX, 8487, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8489, UINT16_MAX, 8489, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8491, UINT16_MAX, 8491, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8493, UINT16_MAX, 8493, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8495, UINT16_MAX, 8495, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8497, UINT16_MAX, 8497, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8499, UINT16_MAX, 8499, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8501, UINT16_MAX, 8501, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8503, UINT16_MAX, 8503, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8505, UINT16_MAX, 8505, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8507, UINT16_MAX, 8507, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8509, UINT16_MAX, 8509, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8511, UINT16_MAX, 8511, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8513, UINT16_MAX, 8513, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8515, UINT16_MAX, 8515, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8517, UINT16_MAX, 8517, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8519, UINT16_MAX, 8519, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8521, UINT16_MAX, 8521, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8523, UINT16_MAX, 8523, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8525, UINT16_MAX, 8525, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8527, UINT16_MAX, 8527, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8529, UINT16_MAX, 8529, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8531, UINT16_MAX, 8531, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8533, UINT16_MAX, 8533, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8535, UINT16_MAX, 8535, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8537, UINT16_MAX, 8537, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8539, UINT16_MAX, 8539, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8541, UINT16_MAX, 8541, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8543, UINT16_MAX, 8543, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8545, UINT16_MAX, 8545, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8547, UINT16_MAX, 8547, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8549, UINT16_MAX, 8549, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8551, UINT16_MAX, 8551, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8553, UINT16_MAX, 8553, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8555, UINT16_MAX, 8555, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8557, UINT16_MAX, 8557, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8559, UINT16_MAX, 8559, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8561, UINT16_MAX, 8561, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8563, UINT16_MAX, 8563, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8565, UINT16_MAX, 8565, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8567, UINT16_MAX, 8567, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8569, UINT16_MAX, 8569, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8571, UINT16_MAX, 8571, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8573, UINT16_MAX, 8573, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8575, UINT16_MAX, 8575, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8577, UINT16_MAX, 8577, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8579, UINT16_MAX, 8579, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8581, UINT16_MAX, 8581, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8583, UINT16_MAX, 8583, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8585, UINT16_MAX, 8585, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8587, UINT16_MAX, 8587, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8589, UINT16_MAX, 8589, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8591, UINT16_MAX, 8591, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8593, UINT16_MAX, 8593, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8595, UINT16_MAX, 8595, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8597, UINT16_MAX, 8597, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8599, UINT16_MAX, 8599, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8601, UINT16_MAX, 8601, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8603, UINT16_MAX, 8603, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8605, UINT16_MAX, 8605, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8607, UINT16_MAX, 8607, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8609, UINT16_MAX, 8609, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8611, UINT16_MAX, 8611, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8613, UINT16_MAX, 8613, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8615, UINT16_MAX, 8615, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8617, UINT16_MAX, 8617, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8619, UINT16_MAX, 8619, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8621, UINT16_MAX, 8621, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8623, UINT16_MAX, 8623, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8625, UINT16_MAX, 8625, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8627, UINT16_MAX, 8627, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8629, UINT16_MAX, 8629, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8631, UINT16_MAX, 8631, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8633, UINT16_MAX, 8633, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8635, UINT16_MAX, 8635, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8637, UINT16_MAX, 8637, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8639, UINT16_MAX, 8639, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8641, UINT16_MAX, 8641, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8643, UINT16_MAX, 8643, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8645, UINT16_MAX, 8645, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8647, UINT16_MAX, 8647, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8649, UINT16_MAX, 8649, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8651, UINT16_MAX, 8651, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8653, UINT16_MAX, 8653, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8655, UINT16_MAX, 8655, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8657, UINT16_MAX, 8657, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8659, UINT16_MAX, 8659, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8661, UINT16_MAX, 8661, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8663, UINT16_MAX, 8663, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8665, UINT16_MAX, 8665, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8667, UINT16_MAX, 8667, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8669, UINT16_MAX, 8669, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8671, UINT16_MAX, 8671, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8673, UINT16_MAX, 8673, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8675, UINT16_MAX, 8675, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8677, UINT16_MAX, 8677, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8679, UINT16_MAX, 8679, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8681, UINT16_MAX, 8681, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8683, UINT16_MAX, 8683, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8685, UINT16_MAX, 8685, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8687, UINT16_MAX, 8687, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8689, UINT16_MAX, 8689, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8691, UINT16_MAX, 8691, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8693, UINT16_MAX, 8693, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8695, UINT16_MAX, 8695, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8697, UINT16_MAX, 8697, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8699, UINT16_MAX, 8699, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8701, UINT16_MAX, 8701, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8703, UINT16_MAX, 8703, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8705, UINT16_MAX, 8705, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8707, UINT16_MAX, 8707, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8709, UINT16_MAX, 8709, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8711, UINT16_MAX, 8711, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8713, UINT16_MAX, 8713, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8715, UINT16_MAX, 8715, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8717, UINT16_MAX, 8717, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8719, UINT16_MAX, 8719, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8721, UINT16_MAX, 8721, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8723, UINT16_MAX, 8723, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8725, UINT16_MAX, 8725, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8727, UINT16_MAX, 8727, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8729, UINT16_MAX, 8729, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8731, UINT16_MAX, 8731, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8733, UINT16_MAX, 8733, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8735, UINT16_MAX, 8735, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8737, UINT16_MAX, 8737, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8739, UINT16_MAX, 8739, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8741, UINT16_MAX, 8741, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8743, UINT16_MAX, 8743, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8745, UINT16_MAX, 8745, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8747, UINT16_MAX, 8747, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8749, UINT16_MAX, 8749, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8751, UINT16_MAX, 8751, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8753, UINT16_MAX, 8753, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8755, UINT16_MAX, 8755, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8757, UINT16_MAX, 8757, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8759, UINT16_MAX, 8759, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8761, UINT16_MAX, 8761, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8763, UINT16_MAX, 8763, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8765, UINT16_MAX, 8765, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8767, UINT16_MAX, 8767, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8769, UINT16_MAX, 8769, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8771, UINT16_MAX, 8771, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8773, UINT16_MAX, 8773, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8775, UINT16_MAX, 8775, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8777, UINT16_MAX, 8777, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8779, UINT16_MAX, 8779, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8781, UINT16_MAX, 8781, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8783, UINT16_MAX, 8783, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8785, UINT16_MAX, 8785, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8787, UINT16_MAX, 8787, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8789, UINT16_MAX, 8789, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8791, UINT16_MAX, 8791, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8793, UINT16_MAX, 8793, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8795, UINT16_MAX, 8795, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8797, UINT16_MAX, 8797, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8799, UINT16_MAX, 8799, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8801, UINT16_MAX, 8801, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8803, UINT16_MAX, 8803, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8805, UINT16_MAX, 8805, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8807, UINT16_MAX, 8807, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8809, UINT16_MAX, 8809, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8811, UINT16_MAX, 8811, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8813, UINT16_MAX, 8813, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8815, UINT16_MAX, 8815, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8817, UINT16_MAX, 8817, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8819, UINT16_MAX, 8819, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8821, UINT16_MAX, 8821, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8823, UINT16_MAX, 8823, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8825, UINT16_MAX, 8825, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8827, UINT16_MAX, 8827, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8829, UINT16_MAX, 8829, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8831, UINT16_MAX, 8831, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8833, UINT16_MAX, 8833, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8835, UINT16_MAX, 8835, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8837, UINT16_MAX, 8837, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8839, UINT16_MAX, 8839, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8841, UINT16_MAX, 8841, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8843, UINT16_MAX, 8843, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8845, UINT16_MAX, 8845, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8847, UINT16_MAX, 8847, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8849, UINT16_MAX, 8849, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8851, UINT16_MAX, 8851, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8853, UINT16_MAX, 8853, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8855, UINT16_MAX, 8855, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8857, UINT16_MAX, 8857, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8859, UINT16_MAX, 8859, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8861, UINT16_MAX, 8861, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8863, UINT16_MAX, 8863, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8865, UINT16_MAX, 8865, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8867, UINT16_MAX, 8867, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8869, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 95, UINT16_MAX, 8873, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1081, UINT16_MAX, 8875, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 601, UINT16_MAX, 8877, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1091, UINT16_MAX, 8879, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6815, UINT16_MAX, 8881, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1093, UINT16_MAX, 8883, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1092, UINT16_MAX, 8885, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 609, UINT16_MAX, 8887, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 610, UINT16_MAX, 8889, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2352, UINT16_MAX, 8891, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1017, UINT16_MAX, 8893, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1023, UINT16_MAX, 8895, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1097, UINT16_MAX, 8897, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1029, UINT16_MAX, 8899, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1027, UINT16_MAX, 8901, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 619, UINT16_MAX, 8903, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1083, UINT16_MAX, 8905, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 357, UINT16_MAX, 8907, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1084, UINT16_MAX, 8909, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1032, UINT16_MAX, 8911, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1061, UINT16_MAX, 8913, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1098, UINT16_MAX, 8915, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1099, UINT16_MAX, 8917, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6719, UINT16_MAX, 8919, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8921, UINT16_MAX, 8923, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6692, UINT16_MAX, 8925, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1039, UINT16_MAX, 8927, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8929, UINT16_MAX, 8931, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1071, UINT16_MAX, 8933, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8935, UINT16_MAX, 8937, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 142, UINT16_MAX, 8939, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1047, UINT16_MAX, 8941, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1048, UINT16_MAX, 8943, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 16, UINT16_MAX, 8945, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1051, UINT16_MAX, 8947, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8949, UINT16_MAX, 8951, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4664, UINT16_MAX, 8953, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1055, UINT16_MAX, 8955, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 642, UINT16_MAX, 8957, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1096, UINT16_MAX, 8959, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1094, UINT16_MAX, 8961, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6816, UINT16_MAX, 8963, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1095, UINT16_MAX, 8965, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 650, UINT16_MAX, 8967, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4673, UINT16_MAX, 8969, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1072, UINT16_MAX, 8971, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1089, UINT16_MAX, 8973, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1090, UINT16_MAX, 8975, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1080, UINT16_MAX, 8977, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8979, UINT16_MAX, 8980, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8982, UINT16_MAX, 8983, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8985, UINT16_MAX, 8986, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8988, UINT16_MAX, 8990, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8992, UINT16_MAX, 8994, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 8996, UINT16_MAX, 8996, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 8998, UINT16_MAX, 8998, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9000, UINT16_MAX, 9000, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9002, UINT16_MAX, 9002, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9004, UINT16_MAX, 9004, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9006, UINT16_MAX, 9006, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9008, UINT16_MAX, 9008, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9010, UINT16_MAX, 9010, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9012, UINT16_MAX, 9012, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9014, UINT16_MAX, 9014, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9016, UINT16_MAX, 9016, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9018, UINT16_MAX, 9018, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9020, UINT16_MAX, 9020, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9022, UINT16_MAX, 9022, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9024, UINT16_MAX, 9024, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9026, UINT16_MAX, 9026, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9028, UINT16_MAX, 9028, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9030, UINT16_MAX, 9030, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9032, UINT16_MAX, 9032, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9034, UINT16_MAX, 9034, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9036, UINT16_MAX, 9036, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9038, UINT16_MAX, 9038, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9040, UINT16_MAX, 9040, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9042, UINT16_MAX, 9042, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9044, UINT16_MAX, 9044, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9046, UINT16_MAX, 9046, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9048, UINT16_MAX, 9048, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9050, UINT16_MAX, 9050, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9052, UINT16_MAX, 9052, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9054, UINT16_MAX, 9054, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9056, UINT16_MAX, 9056, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9058, UINT16_MAX, 9058, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9060, UINT16_MAX, 9060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9062, UINT16_MAX, 9062, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9064, UINT16_MAX, 9064, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9066, UINT16_MAX, 9066, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9068, UINT16_MAX, 9068, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9070, UINT16_MAX, 9070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9072, UINT16_MAX, 9072, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9074, UINT16_MAX, 9074, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9076, UINT16_MAX, 9076, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9078, UINT16_MAX, 9078, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9080, UINT16_MAX, 9080, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9082, UINT16_MAX, 9082, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9084, UINT16_MAX, 9084, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9086, UINT16_MAX, 9086, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9088, UINT16_MAX, 9088, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9090, UINT16_MAX, 9090, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9092, UINT16_MAX, 9092, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9094, UINT16_MAX, 9094, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 9096, UINT16_MAX, 9096, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9098, UINT16_MAX, 9098, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9100, UINT16_MAX, 9100, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9102, UINT16_MAX, 9102, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9104, UINT16_MAX, 9104, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9106, UINT16_MAX, 9106, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9108, UINT16_MAX, 9108, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9110, UINT16_MAX, 9110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9112, UINT16_MAX, 9112, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9114, UINT16_MAX, 9114, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9116, UINT16_MAX, 9116, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9118, UINT16_MAX, 9118, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9120, UINT16_MAX, 9120, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9122, UINT16_MAX, 9122, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9124, UINT16_MAX, 9124, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9126, UINT16_MAX, 9126, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9128, UINT16_MAX, 9128, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9130, UINT16_MAX, 9130, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9132, UINT16_MAX, 9132, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9134, UINT16_MAX, 9134, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9136, UINT16_MAX, 9136, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9138, UINT16_MAX, 9138, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9140, UINT16_MAX, 9140, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9142, UINT16_MAX, 9142, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9144, UINT16_MAX, 9144, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9146, UINT16_MAX, 9146, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9148, UINT16_MAX, 9148, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9150, UINT16_MAX, 9150, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9152, UINT16_MAX, 9152, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9154, UINT16_MAX, 9154, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9156, UINT16_MAX, 9156, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9158, UINT16_MAX, 9158, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9160, UINT16_MAX, 9160, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9162, UINT16_MAX, 9162, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9164, UINT16_MAX, 9164, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9166, UINT16_MAX, 9166, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9168, UINT16_MAX, 9168, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9170, UINT16_MAX, 9170, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9172, UINT16_MAX, 9172, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9174, UINT16_MAX, 9174, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9176, UINT16_MAX, 9176, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9178, UINT16_MAX, 9178, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9180, UINT16_MAX, 9180, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9182, UINT16_MAX, 9182, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9184, UINT16_MAX, 9184, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9186, UINT16_MAX, 9186, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9188, UINT16_MAX, 9188, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9190, UINT16_MAX, 9190, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9192, UINT16_MAX, 9192, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9194, UINT16_MAX, 9194, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9196, UINT16_MAX, 9196, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9198, UINT16_MAX, 9198, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5328, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5332, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5336, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49206, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49208, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 25596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 25600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5340, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5344, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49210, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5348, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 25604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 25608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49212, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49216, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5354, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49214, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 25612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 25616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49218, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 25620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49220, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5362, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5366, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 25624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 25628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9248, UINT16_MAX, 9248, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9250, UINT16_MAX, 9250, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9252, UINT16_MAX, 9252, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9254, UINT16_MAX, 9254, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9256, UINT16_MAX, 9256, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9258, UINT16_MAX, 9258, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9260, UINT16_MAX, 9260, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9262, UINT16_MAX, 9262, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9264, UINT16_MAX, 9264, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9266, UINT16_MAX, 9266, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9268, UINT16_MAX, 9268, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9270, UINT16_MAX, 9270, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9272, UINT16_MAX, 9272, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9274, UINT16_MAX, 9274, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9276, UINT16_MAX, 9276, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9278, UINT16_MAX, 9278, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9280, UINT16_MAX, 9280, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9282, UINT16_MAX, 9282, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9284, UINT16_MAX, 9284, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9286, UINT16_MAX, 9286, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9288, UINT16_MAX, 9288, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9290, UINT16_MAX, 9290, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9292, UINT16_MAX, 9292, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9294, UINT16_MAX, 9294, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9296, UINT16_MAX, 9296, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9298, UINT16_MAX, 9298, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9300, UINT16_MAX, 9300, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9302, UINT16_MAX, 9302, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9304, UINT16_MAX, 9304, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9306, UINT16_MAX, 9306, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9308, UINT16_MAX, 9308, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9310, UINT16_MAX, 9310, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9312, UINT16_MAX, 9312, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9314, UINT16_MAX, 9314, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9316, UINT16_MAX, 9316, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9318, UINT16_MAX, 9318, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9320, UINT16_MAX, 9320, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9322, UINT16_MAX, 9322, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9324, UINT16_MAX, 9324, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9326, UINT16_MAX, 9326, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9328, UINT16_MAX, 9328, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9330, UINT16_MAX, 9330, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9332, UINT16_MAX, 9332, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9334, UINT16_MAX, 9334, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9336, UINT16_MAX, 9336, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9338, UINT16_MAX, 9338, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9340, UINT16_MAX, 9340, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9342, UINT16_MAX, 9342, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9344, UINT16_MAX, 9344, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9346, UINT16_MAX, 9346, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9348, UINT16_MAX, 9348, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9350, UINT16_MAX, 9350, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9352, UINT16_MAX, 9352, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9354, UINT16_MAX, 9354, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9356, UINT16_MAX, 9356, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9358, UINT16_MAX, 9358, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9360, UINT16_MAX, 9360, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9362, UINT16_MAX, 9362, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9364, UINT16_MAX, 9364, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9366, UINT16_MAX, 9366, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9368, UINT16_MAX, 9368, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9370, UINT16_MAX, 9370, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9372, UINT16_MAX, 9372, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9374, UINT16_MAX, 9374, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49222, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5370, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 25760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9380, UINT16_MAX, 9380, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9382, UINT16_MAX, 9382, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9384, UINT16_MAX, 9384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9386, UINT16_MAX, 9386, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9388, UINT16_MAX, 9388, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9390, UINT16_MAX, 9390, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9392, UINT16_MAX, 9392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9394, UINT16_MAX, 9394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9396, UINT16_MAX, 9396, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9398, UINT16_MAX, 9398, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9400, UINT16_MAX, 9400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9402, UINT16_MAX, 9402, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9404, UINT16_MAX, 9404, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9406, UINT16_MAX, 9406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9408, UINT16_MAX, 9408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9410, UINT16_MAX, 9410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9412, UINT16_MAX, 9412, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9414, UINT16_MAX, 9414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9416, UINT16_MAX, 9416, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9418, UINT16_MAX, 9418, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9420, UINT16_MAX, 9420, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9422, UINT16_MAX, 9422, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9424, UINT16_MAX, 9424, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9426, UINT16_MAX, 9426, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9428, UINT16_MAX, 9428, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9430, UINT16_MAX, 9430, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9432, UINT16_MAX, 9432, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9434, UINT16_MAX, 9434, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9436, UINT16_MAX, 9436, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9438, UINT16_MAX, 9438, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9440, UINT16_MAX, 9440, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9442, UINT16_MAX, 9442, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9444, UINT16_MAX, 9444, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9446, UINT16_MAX, 9446, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9448, UINT16_MAX, 9448, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9450, UINT16_MAX, 9450, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9452, UINT16_MAX, 9452, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9454, UINT16_MAX, 9454, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9456, UINT16_MAX, 9456, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9458, UINT16_MAX, 9458, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9460, UINT16_MAX, 9460, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9462, UINT16_MAX, 9462, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9464, UINT16_MAX, 9464, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9466, UINT16_MAX, 9466, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9468, UINT16_MAX, 9468, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9470, UINT16_MAX, 9470, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9472, UINT16_MAX, 9472, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9474, UINT16_MAX, 9474, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9476, UINT16_MAX, 9476, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9478, UINT16_MAX, 9478, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9480, UINT16_MAX, 9480, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9482, UINT16_MAX, 9482, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9484, UINT16_MAX, 9484, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9486, UINT16_MAX, 9486, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9488, UINT16_MAX, 9488, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9490, UINT16_MAX, 9490, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9492, UINT16_MAX, 9492, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9494, UINT16_MAX, 9494, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9496, UINT16_MAX, 9496, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9498, UINT16_MAX, 9498, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9500, UINT16_MAX, 9500, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9502, UINT16_MAX, 9502, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9504, UINT16_MAX, 9504, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9506, UINT16_MAX, 9506, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 6, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5374, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5378, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5382, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49224, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 226, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49226, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49228, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49230, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49232, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49234, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_EXTEND}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5394, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5398, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5402, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5408, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 25940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 9560, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 9562, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 9564, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 9566, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 9568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 9570, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 9572, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 9574, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 9576, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 9578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 9580, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 9582, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 9584, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 9586, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 9588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 9590, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 9592, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 9594, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 9596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 9598, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 9600, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 9602, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 9604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 9606, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 9608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 9610, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 9612, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 9614, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 9616, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 9618, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 9620, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 9622, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 9624, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 9626, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 9628, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 9630, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 9632, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 9634, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 9636, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 9638, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 9640, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 9642, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 9644, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 9646, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 9648, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 9650, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 9652, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 9654, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 9656, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 9658, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 9660, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 9662, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 9664, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 9666, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 9668, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 9670, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 9672, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 9674, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 9676, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 9678, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 9680, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 9682, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 9684, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 9686, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 9688, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 9690, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 9692, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 9694, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 9696, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 9698, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 9700, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 9702, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 9704, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 9706, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 9708, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 9710, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 9712, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 9714, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 9716, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 9718, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 9720, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 9722, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 9724, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 9726, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 9728, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 9730, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 9732, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 9734, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 9736, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 9738, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 9740, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 9742, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 9744, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 9746, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 9748, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 9750, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 9752, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 9754, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 9756, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 9758, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 9760, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 9762, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 9764, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 9766, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 9768, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 9770, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 9772, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 9774, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 9776, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 9778, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 9780, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 9782, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 9784, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 9786, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 9788, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 9790, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 9792, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 9794, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 9796, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 9798, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 9800, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 9802, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 9804, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 9806, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 9808, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 9810, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 9812, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 9814, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 9816, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 9818, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 9820, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 9822, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 9824, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 9826, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 9828, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 9830, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 9832, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 9834, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 9836, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 9838, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 9840, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 9842, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 9844, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 9846, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 9848, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 9850, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 9852, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 9854, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 9856, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 9858, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 9860, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 9862, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 9864, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 9866, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 9868, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 9870, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 9872, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 9874, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 9876, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 9878, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 9880, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 9882, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 9884, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 9886, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 9888, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 9890, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 9892, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 9894, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 9896, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 9898, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 9900, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 9902, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 9904, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 9906, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 9908, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 9910, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 9912, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 9914, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 9916, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 9918, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 9920, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 9922, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 9924, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 9926, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 9928, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 9930, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 9932, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 9934, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 9936, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 9938, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 9940, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 9942, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 9944, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 9946, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 9948, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 9950, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 9952, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 9954, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 9956, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 9958, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 9960, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 9962, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 9964, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 9966, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 9968, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 9970, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 9972, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 9974, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 9976, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 9978, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 9980, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 9982, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 9984, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 9986, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 9988, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 9990, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 9992, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 9994, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 9996, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 9998, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 10000, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 10002, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10004, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10006, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10008, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10010, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10012, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10014, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10016, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10018, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10020, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10022, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10024, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10026, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10028, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10030, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10032, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10034, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10036, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10038, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10040, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10042, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10044, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10046, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10048, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10050, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10052, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10054, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 10056, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 10058, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 10060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 10062, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 10064, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 10066, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 10068, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 10070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 10072, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 10074, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 10076, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 10078, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 10080, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 10082, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 10084, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 10086, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 10088, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 10090, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 10092, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 10094, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 10096, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10098, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10100, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10102, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10104, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10106, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10108, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10110, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10112, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10114, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10116, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10118, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10120, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10122, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10124, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10126, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10128, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10130, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10132, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10134, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10136, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10138, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10140, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10142, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10144, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10146, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10148, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 10150, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 10152, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 10154, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 10156, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 10158, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 10160, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 10162, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 10164, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 10166, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 10168, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 10170, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 10172, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 10174, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 10176, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 10178, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 10180, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 10182, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 10184, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 10186, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10188, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10190, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10192, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10194, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10196, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10198, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10200, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10202, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10204, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10206, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10208, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10210, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10212, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10214, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10216, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10218, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10220, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10222, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10224, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10226, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10228, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10230, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10232, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10234, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10236, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10238, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 10240, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 10242, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 10244, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 10246, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 10248, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 10250, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 10252, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 10254, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 10256, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 10258, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 10260, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 10262, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 10264, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 10266, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 10268, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 10270, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 10272, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 10274, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 10276, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 10278, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 10280, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 10282, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 10284, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 10286, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 10288, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 10290, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10292, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10294, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10296, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10298, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10300, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10302, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10304, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10306, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10308, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10310, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10312, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10314, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10316, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10318, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10320, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10322, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10324, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10326, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10328, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10330, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10332, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10334, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10336, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10338, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10340, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10342, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 10344, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 10346, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 10348, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 10350, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 10352, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 10354, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 10356, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 10358, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 10360, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 10362, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 10364, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 10366, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 10368, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 10370, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 10372, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 10374, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 10376, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 10378, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 10380, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 10382, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 10384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 10386, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 10388, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 10390, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 10392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 10394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10396, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10398, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10400, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10402, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10404, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10406, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10408, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10410, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10412, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10414, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10416, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10418, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10420, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10422, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10424, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10426, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10428, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10430, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10432, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10434, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10436, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10438, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10440, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10442, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10444, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10446, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 10448, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 10450, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 10452, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 10454, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 10456, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 10458, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 10460, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 10462, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 10464, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 10466, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 10468, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 10470, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 10472, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 10474, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 10476, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 10478, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 10480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 10482, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 10484, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 10486, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 10488, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 10490, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 10492, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 10494, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 10496, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 10498, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10500, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10502, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10504, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10506, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10508, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10510, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10512, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10514, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10516, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10518, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10520, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10522, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10524, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10526, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10528, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10530, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10532, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10534, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10536, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10538, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10540, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10542, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10544, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10546, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10548, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10550, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 10552, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 10554, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 10556, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 10558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 10560, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 10562, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 10564, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 10566, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 10568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 10570, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 10572, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 10574, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 10576, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 10578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 10580, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 10582, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 10584, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 10586, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 10588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 10590, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 10592, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 10594, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 10596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 10598, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 10600, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 10602, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10604, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10606, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10608, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10610, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10612, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10614, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10616, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10618, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10620, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10622, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10624, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10626, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10628, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10630, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10632, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10634, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10636, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10638, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10640, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10642, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10644, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10646, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10648, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10650, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10652, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10654, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 10656, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 10658, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 10660, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 10662, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 10664, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 10666, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 10668, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 10670, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 10672, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 10674, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 10676, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 10678, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 10680, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 10682, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 10684, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 10686, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 10688, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 10690, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 10692, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 10694, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 10696, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 10698, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 10700, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 10702, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 10704, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 10706, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10708, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10710, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10712, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10714, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10716, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10718, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10720, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10722, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10724, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10726, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10728, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10730, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10732, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10734, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10736, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10738, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10740, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10742, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10744, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10746, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10748, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10750, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10752, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10754, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10756, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10758, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 26, UINT16_MAX, UINT16_MAX, 10760, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 27, UINT16_MAX, UINT16_MAX, 10762, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 28, UINT16_MAX, UINT16_MAX, 10764, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 29, UINT16_MAX, UINT16_MAX, 10766, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 30, UINT16_MAX, UINT16_MAX, 10768, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, 10770, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, 10772, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 33, UINT16_MAX, UINT16_MAX, 10774, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 34, UINT16_MAX, UINT16_MAX, 10776, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, 10778, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 36, UINT16_MAX, UINT16_MAX, 10780, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 37, UINT16_MAX, UINT16_MAX, 10782, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, 10784, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 39, UINT16_MAX, UINT16_MAX, 10786, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 40, UINT16_MAX, UINT16_MAX, 10788, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 41, UINT16_MAX, UINT16_MAX, 10790, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 42, UINT16_MAX, UINT16_MAX, 10792, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 43, UINT16_MAX, UINT16_MAX, 10794, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 44, UINT16_MAX, UINT16_MAX, 10796, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 45, UINT16_MAX, UINT16_MAX, 10798, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 46, UINT16_MAX, UINT16_MAX, 10800, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 47, UINT16_MAX, UINT16_MAX, 10802, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 48, UINT16_MAX, UINT16_MAX, 10804, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 49, UINT16_MAX, UINT16_MAX, 10806, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 50, UINT16_MAX, UINT16_MAX, 10808, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 51, UINT16_MAX, UINT16_MAX, 10810, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, 10812, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, 10814, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, 10816, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, 10818, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, 10820, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, 10822, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, 10824, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, 10826, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, 10828, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, 10830, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, 10832, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, 10834, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, 10836, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, 10838, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, 10840, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, 10842, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, 10844, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, 10846, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, 10848, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, 10850, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, 10852, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, 10854, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, 10856, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, 10858, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, 10860, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, 10862, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10864, UINT16_MAX, 10865, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 984, UINT16_MAX, 10867, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1231, UINT16_MAX, UINT16_MAX, 10869, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1232, UINT16_MAX, UINT16_MAX, 10871, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1233, UINT16_MAX, UINT16_MAX, 10873, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1234, UINT16_MAX, UINT16_MAX, 10875, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1235, UINT16_MAX, UINT16_MAX, 10877, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1236, UINT16_MAX, UINT16_MAX, 10879, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1237, UINT16_MAX, UINT16_MAX, 10881, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1238, UINT16_MAX, UINT16_MAX, 10883, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1139, UINT16_MAX, UINT16_MAX, 10885, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1239, UINT16_MAX, UINT16_MAX, 10887, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1240, UINT16_MAX, UINT16_MAX, 10889, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 63, UINT16_MAX, UINT16_MAX, 10891, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1241, UINT16_MAX, UINT16_MAX, 10893, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1242, UINT16_MAX, UINT16_MAX, 10895, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1243, UINT16_MAX, UINT16_MAX, 10897, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1244, UINT16_MAX, UINT16_MAX, 10899, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1245, UINT16_MAX, UINT16_MAX, 10901, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10903, UINT16_MAX, UINT16_MAX, 10904, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1246, UINT16_MAX, UINT16_MAX, 10906, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1247, UINT16_MAX, UINT16_MAX, 10908, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1248, UINT16_MAX, UINT16_MAX, 10910, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1249, UINT16_MAX, UINT16_MAX, 10912, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1250, UINT16_MAX, UINT16_MAX, 10914, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1251, UINT16_MAX, UINT16_MAX, 10916, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1252, UINT16_MAX, UINT16_MAX, 10918, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1185, UINT16_MAX, 10921, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1186, UINT16_MAX, 10923, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1187, UINT16_MAX, 10925, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1188, UINT16_MAX, 10927, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1189, UINT16_MAX, 10929, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1190, UINT16_MAX, 10931, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1191, UINT16_MAX, 10933, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1192, UINT16_MAX, 10935, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1138, UINT16_MAX, 10937, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1193, UINT16_MAX, 10939, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1194, UINT16_MAX, 10941, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 62, UINT16_MAX, 10943, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1195, UINT16_MAX, 10945, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1196, UINT16_MAX, 10947, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1197, UINT16_MAX, 10949, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1198, UINT16_MAX, 10951, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1199, UINT16_MAX, 10953, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1301, UINT16_MAX, 10955, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1200, UINT16_MAX, 10957, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1201, UINT16_MAX, 10959, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1202, UINT16_MAX, 10961, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1203, UINT16_MAX, 10963, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1204, UINT16_MAX, 10965, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1205, UINT16_MAX, 10967, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1206, UINT16_MAX, 10969, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, 10971, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10972, UINT16_MAX, 10973, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10975, UINT16_MAX, 10976, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10978, UINT16_MAX, 10979, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10981, UINT16_MAX, 10982, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10984, UINT16_MAX, 10985, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10987, UINT16_MAX, 10988, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1231, UINT16_MAX, UINT16_MAX, 10990, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1232, UINT16_MAX, UINT16_MAX, 10992, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1233, UINT16_MAX, UINT16_MAX, 10994, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1234, UINT16_MAX, UINT16_MAX, 10996, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1235, UINT16_MAX, UINT16_MAX, 10998, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1236, UINT16_MAX, UINT16_MAX, 11000, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1237, UINT16_MAX, UINT16_MAX, 11002, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1238, UINT16_MAX, UINT16_MAX, 11004, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1139, UINT16_MAX, UINT16_MAX, 11006, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1239, UINT16_MAX, UINT16_MAX, 11008, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1240, UINT16_MAX, UINT16_MAX, 11010, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 63, UINT16_MAX, UINT16_MAX, 11012, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1241, UINT16_MAX, UINT16_MAX, 11014, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1242, UINT16_MAX, UINT16_MAX, 11016, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1243, UINT16_MAX, UINT16_MAX, 11018, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1244, UINT16_MAX, UINT16_MAX, 11020, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1245, UINT16_MAX, UINT16_MAX, 11022, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10903, UINT16_MAX, UINT16_MAX, 11024, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1246, UINT16_MAX, UINT16_MAX, 11026, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1247, UINT16_MAX, UINT16_MAX, 11028, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1248, UINT16_MAX, UINT16_MAX, 11030, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1249, UINT16_MAX, UINT16_MAX, 11032, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1250, UINT16_MAX, UINT16_MAX, 11034, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1251, UINT16_MAX, UINT16_MAX, 11036, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1252, UINT16_MAX, UINT16_MAX, 11038, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1185, UINT16_MAX, 11040, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1186, UINT16_MAX, 11042, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1187, UINT16_MAX, 11044, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1188, UINT16_MAX, 11046, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1189, UINT16_MAX, 11048, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1190, UINT16_MAX, 11050, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1191, UINT16_MAX, 11052, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1192, UINT16_MAX, 11054, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1138, UINT16_MAX, 11056, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1193, UINT16_MAX, 11058, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1194, UINT16_MAX, 11060, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 62, UINT16_MAX, 11062, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1195, UINT16_MAX, 11064, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1196, UINT16_MAX, 11066, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1197, UINT16_MAX, 11068, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1198, UINT16_MAX, 11070, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1199, UINT16_MAX, 11072, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1301, UINT16_MAX, 11074, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1200, UINT16_MAX, 11076, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1201, UINT16_MAX, 11078, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1202, UINT16_MAX, 11080, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1203, UINT16_MAX, 11082, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1204, UINT16_MAX, 11084, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1205, UINT16_MAX, 11086, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1206, UINT16_MAX, 11088, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10972, UINT16_MAX, 11090, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10975, UINT16_MAX, 11092, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10978, UINT16_MAX, 11094, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10981, UINT16_MAX, 11096, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10984, UINT16_MAX, 11098, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10987, UINT16_MAX, 11100, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1231, UINT16_MAX, UINT16_MAX, 11102, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1232, UINT16_MAX, UINT16_MAX, 11104, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1233, UINT16_MAX, UINT16_MAX, 11106, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1234, UINT16_MAX, UINT16_MAX, 11108, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1235, UINT16_MAX, UINT16_MAX, 11110, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1236, UINT16_MAX, UINT16_MAX, 11112, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1237, UINT16_MAX, UINT16_MAX, 11114, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1238, UINT16_MAX, UINT16_MAX, 11116, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1139, UINT16_MAX, UINT16_MAX, 11118, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1239, UINT16_MAX, UINT16_MAX, 11120, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1240, UINT16_MAX, UINT16_MAX, 11122, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 63, UINT16_MAX, UINT16_MAX, 11124, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1241, UINT16_MAX, UINT16_MAX, 11126, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1242, UINT16_MAX, UINT16_MAX, 11128, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1243, UINT16_MAX, UINT16_MAX, 11130, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1244, UINT16_MAX, UINT16_MAX, 11132, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1245, UINT16_MAX, UINT16_MAX, 11134, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10903, UINT16_MAX, UINT16_MAX, 11136, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1246, UINT16_MAX, UINT16_MAX, 11138, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1247, UINT16_MAX, UINT16_MAX, 11140, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1248, UINT16_MAX, UINT16_MAX, 11142, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1249, UINT16_MAX, UINT16_MAX, 11144, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1250, UINT16_MAX, UINT16_MAX, 11146, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1251, UINT16_MAX, UINT16_MAX, 11148, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1252, UINT16_MAX, UINT16_MAX, 11150, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1185, UINT16_MAX, 11152, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1186, UINT16_MAX, 11154, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1187, UINT16_MAX, 11156, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1188, UINT16_MAX, 11158, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1189, UINT16_MAX, 11160, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1190, UINT16_MAX, 11162, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1191, UINT16_MAX, 11164, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1192, UINT16_MAX, 11166, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1138, UINT16_MAX, 11168, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1193, UINT16_MAX, 11170, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1194, UINT16_MAX, 11172, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 62, UINT16_MAX, 11174, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1195, UINT16_MAX, 11176, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1196, UINT16_MAX, 11178, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1197, UINT16_MAX, 11180, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1198, UINT16_MAX, 11182, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1199, UINT16_MAX, 11184, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1301, UINT16_MAX, 11186, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1200, UINT16_MAX, 11188, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1201, UINT16_MAX, 11190, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1202, UINT16_MAX, 11192, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1203, UINT16_MAX, 11194, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1204, UINT16_MAX, 11196, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1205, UINT16_MAX, 11198, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1206, UINT16_MAX, 11200, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10972, UINT16_MAX, 11202, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10975, UINT16_MAX, 11204, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10978, UINT16_MAX, 11206, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10981, UINT16_MAX, 11208, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10984, UINT16_MAX, 11210, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10987, UINT16_MAX, 11212, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1231, UINT16_MAX, UINT16_MAX, 11214, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1232, UINT16_MAX, UINT16_MAX, 11216, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1233, UINT16_MAX, UINT16_MAX, 11218, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1234, UINT16_MAX, UINT16_MAX, 11220, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1235, UINT16_MAX, UINT16_MAX, 11222, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1236, UINT16_MAX, UINT16_MAX, 11224, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1237, UINT16_MAX, UINT16_MAX, 11226, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1238, UINT16_MAX, UINT16_MAX, 11228, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1139, UINT16_MAX, UINT16_MAX, 11230, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1239, UINT16_MAX, UINT16_MAX, 11232, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1240, UINT16_MAX, UINT16_MAX, 11234, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 63, UINT16_MAX, UINT16_MAX, 11236, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1241, UINT16_MAX, UINT16_MAX, 11238, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1242, UINT16_MAX, UINT16_MAX, 11240, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1243, UINT16_MAX, UINT16_MAX, 11242, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1244, UINT16_MAX, UINT16_MAX, 11244, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1245, UINT16_MAX, UINT16_MAX, 11246, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10903, UINT16_MAX, UINT16_MAX, 11248, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1246, UINT16_MAX, UINT16_MAX, 11250, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1247, UINT16_MAX, UINT16_MAX, 11252, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1248, UINT16_MAX, UINT16_MAX, 11254, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1249, UINT16_MAX, UINT16_MAX, 11256, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1250, UINT16_MAX, UINT16_MAX, 11258, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1251, UINT16_MAX, UINT16_MAX, 11260, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1252, UINT16_MAX, UINT16_MAX, 11262, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1185, UINT16_MAX, 11264, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1186, UINT16_MAX, 11266, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1187, UINT16_MAX, 11268, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1188, UINT16_MAX, 11270, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1189, UINT16_MAX, 11272, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1190, UINT16_MAX, 11274, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1191, UINT16_MAX, 11276, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1192, UINT16_MAX, 11278, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1138, UINT16_MAX, 11280, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1193, UINT16_MAX, 11282, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1194, UINT16_MAX, 11284, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 62, UINT16_MAX, 11286, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1195, UINT16_MAX, 11288, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1196, UINT16_MAX, 11290, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1197, UINT16_MAX, 11292, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1198, UINT16_MAX, 11294, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1199, UINT16_MAX, 11296, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1301, UINT16_MAX, 11298, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1200, UINT16_MAX, 11300, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1201, UINT16_MAX, 11302, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1202, UINT16_MAX, 11304, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1203, UINT16_MAX, 11306, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1204, UINT16_MAX, 11308, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1205, UINT16_MAX, 11310, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1206, UINT16_MAX, 11312, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10972, UINT16_MAX, 11314, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10975, UINT16_MAX, 11316, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10978, UINT16_MAX, 11318, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10981, UINT16_MAX, 11320, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10984, UINT16_MAX, 11322, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10987, UINT16_MAX, 11324, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1231, UINT16_MAX, UINT16_MAX, 11326, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1232, UINT16_MAX, UINT16_MAX, 11328, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1233, UINT16_MAX, UINT16_MAX, 11330, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1234, UINT16_MAX, UINT16_MAX, 11332, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1235, UINT16_MAX, UINT16_MAX, 11334, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1236, UINT16_MAX, UINT16_MAX, 11336, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1237, UINT16_MAX, UINT16_MAX, 11338, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1238, UINT16_MAX, UINT16_MAX, 11340, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1139, UINT16_MAX, UINT16_MAX, 11342, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1239, UINT16_MAX, UINT16_MAX, 11344, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1240, UINT16_MAX, UINT16_MAX, 11346, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 63, UINT16_MAX, UINT16_MAX, 11348, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1241, UINT16_MAX, UINT16_MAX, 11350, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1242, UINT16_MAX, UINT16_MAX, 11352, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1243, UINT16_MAX, UINT16_MAX, 11354, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1244, UINT16_MAX, UINT16_MAX, 11356, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1245, UINT16_MAX, UINT16_MAX, 11358, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10903, UINT16_MAX, UINT16_MAX, 11360, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1246, UINT16_MAX, UINT16_MAX, 11362, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1247, UINT16_MAX, UINT16_MAX, 11364, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1248, UINT16_MAX, UINT16_MAX, 11366, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1249, UINT16_MAX, UINT16_MAX, 11368, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1250, UINT16_MAX, UINT16_MAX, 11370, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1251, UINT16_MAX, UINT16_MAX, 11372, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1252, UINT16_MAX, UINT16_MAX, 11374, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1185, UINT16_MAX, 11376, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1186, UINT16_MAX, 11378, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1187, UINT16_MAX, 11380, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1188, UINT16_MAX, 11382, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1189, UINT16_MAX, 11384, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1190, UINT16_MAX, 11386, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1191, UINT16_MAX, 11388, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1192, UINT16_MAX, 11390, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1138, UINT16_MAX, 11392, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1193, UINT16_MAX, 11394, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1194, UINT16_MAX, 11396, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 62, UINT16_MAX, 11398, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1195, UINT16_MAX, 11400, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1196, UINT16_MAX, 11402, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1197, UINT16_MAX, 11404, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1198, UINT16_MAX, 11406, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1199, UINT16_MAX, 11408, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1301, UINT16_MAX, 11410, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1200, UINT16_MAX, 11412, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1201, UINT16_MAX, 11414, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1202, UINT16_MAX, 11416, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1203, UINT16_MAX, 11418, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1204, UINT16_MAX, 11420, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1205, UINT16_MAX, 11422, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1206, UINT16_MAX, 11424, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10972, UINT16_MAX, 11426, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10975, UINT16_MAX, 11428, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10978, UINT16_MAX, 11430, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10981, UINT16_MAX, 11432, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10984, UINT16_MAX, 11434, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10987, UINT16_MAX, 11436, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1282, UINT16_MAX, UINT16_MAX, 11438, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1281, UINT16_MAX, 11440, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 3929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 66, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 58, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 59, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 3931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 3932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 3933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 3934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 3935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 3936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11442, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11444, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11446, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11448, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8921, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8929, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8935, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11450, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8949, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11452, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11454, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11456, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11458, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11460, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11462, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11464, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11466, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11468, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11470, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11472, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11474, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11476, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11478, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11480, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11482, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11484, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11486, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11488, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11490, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8992, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11492, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11494, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11496, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11498, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11500, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 11502, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1343, UINT16_MAX, 11504, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1344, UINT16_MAX, 11506, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1345, UINT16_MAX, 11508, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1346, UINT16_MAX, 11510, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1347, UINT16_MAX, 11512, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1348, UINT16_MAX, 11514, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1349, UINT16_MAX, 11516, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1350, UINT16_MAX, 11518, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1351, UINT16_MAX, 11520, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1355, UINT16_MAX, 11522, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1356, UINT16_MAX, 11524, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1357, UINT16_MAX, 11526, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1359, UINT16_MAX, 11528, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1360, UINT16_MAX, 11530, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1361, UINT16_MAX, 11532, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1362, UINT16_MAX, 11534, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1363, UINT16_MAX, 11536, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1364, UINT16_MAX, 11538, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1365, UINT16_MAX, 11540, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1366, UINT16_MAX, 11542, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1367, UINT16_MAX, 11544, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1368, UINT16_MAX, 11546, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1369, UINT16_MAX, 11548, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1372, UINT16_MAX, 11550, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1374, UINT16_MAX, 11552, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1375, UINT16_MAX, 11554, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6566, UINT16_MAX, 11556, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1573, UINT16_MAX, 11558, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1325, UINT16_MAX, 11560, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1329, UINT16_MAX, 11562, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1613, UINT16_MAX, 11564, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1515, UINT16_MAX, 11566, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1533, UINT16_MAX, 11568, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1343, UINT16_MAX, 11570, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1344, UINT16_MAX, 11572, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1345, UINT16_MAX, 11574, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1346, UINT16_MAX, 11576, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1347, UINT16_MAX, 11578, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1348, UINT16_MAX, 11580, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1349, UINT16_MAX, 11582, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1350, UINT16_MAX, 11584, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1351, UINT16_MAX, 11586, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1355, UINT16_MAX, 11588, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1356, UINT16_MAX, 11590, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1359, UINT16_MAX, 11592, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1360, UINT16_MAX, 11594, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1362, UINT16_MAX, 11596, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1364, UINT16_MAX, 11598, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1365, UINT16_MAX, 11600, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1366, UINT16_MAX, 11602, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1367, UINT16_MAX, 11604, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1368, UINT16_MAX, 11606, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1369, UINT16_MAX, 11608, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1371, UINT16_MAX, 11610, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1372, UINT16_MAX, 11612, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1485, UINT16_MAX, 11614, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1325, UINT16_MAX, 11616, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1324, UINT16_MAX, 11618, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 1342, UINT16_MAX, 11620, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1511, UINT16_MAX, 11622, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6528, UINT16_MAX, 11624, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1517, UINT16_MAX, 11626, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11628, UINT16_MAX, 11628, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11630, UINT16_MAX, 11630, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11632, UINT16_MAX, 11632, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11634, UINT16_MAX, 11634, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11636, UINT16_MAX, 11636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11638, UINT16_MAX, 11638, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11640, UINT16_MAX, 11640, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11642, UINT16_MAX, 11642, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11644, UINT16_MAX, 11644, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11646, UINT16_MAX, 11646, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11648, UINT16_MAX, 11648, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11650, UINT16_MAX, 11650, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11652, UINT16_MAX, 11652, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11654, UINT16_MAX, 11654, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11656, UINT16_MAX, 11656, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11658, UINT16_MAX, 11658, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11660, UINT16_MAX, 11660, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11662, UINT16_MAX, 11662, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11664, UINT16_MAX, 11664, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11666, UINT16_MAX, 11666, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11668, UINT16_MAX, 11668, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11670, UINT16_MAX, 11670, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11672, UINT16_MAX, 11672, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11674, UINT16_MAX, 11674, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11676, UINT16_MAX, 11676, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11678, UINT16_MAX, 11678, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11680, UINT16_MAX, 11680, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11682, UINT16_MAX, 11682, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11684, UINT16_MAX, 11684, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11686, UINT16_MAX, 11686, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11688, UINT16_MAX, 11688, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11690, UINT16_MAX, 11690, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11692, UINT16_MAX, 11692, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 11694, UINT16_MAX, 11694, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11696, UINT16_MAX, 11696, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11698, UINT16_MAX, 11698, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11700, UINT16_MAX, 11700, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11702, UINT16_MAX, 11702, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11704, UINT16_MAX, 11704, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11706, UINT16_MAX, 11706, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11708, UINT16_MAX, 11708, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11710, UINT16_MAX, 11710, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11712, UINT16_MAX, 11712, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11714, UINT16_MAX, 11714, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11716, UINT16_MAX, 11716, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11718, UINT16_MAX, 11718, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11720, UINT16_MAX, 11720, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11722, UINT16_MAX, 11722, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11724, UINT16_MAX, 11724, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11726, UINT16_MAX, 11726, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11728, UINT16_MAX, 11728, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11730, UINT16_MAX, 11730, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11732, UINT16_MAX, 11732, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11734, UINT16_MAX, 11734, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11736, UINT16_MAX, 11736, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11738, UINT16_MAX, 11738, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11740, UINT16_MAX, 11740, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11742, UINT16_MAX, 11742, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11744, UINT16_MAX, 11744, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11746, UINT16_MAX, 11746, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11748, UINT16_MAX, 11748, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11750, UINT16_MAX, 11750, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11752, UINT16_MAX, 11752, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11754, UINT16_MAX, 11754, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11756, UINT16_MAX, 11756, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11758, UINT16_MAX, 11758, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11760, UINT16_MAX, 11760, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 11762, UINT16_MAX, 11762, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 11764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 7450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 11765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 11766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 8274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28151, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28155, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28161, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 28171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 28, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 43, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 28254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 28256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 26, UINT16_MAX, UINT16_MAX, 11874, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 27, UINT16_MAX, UINT16_MAX, 11876, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28, UINT16_MAX, UINT16_MAX, 11878, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29, UINT16_MAX, UINT16_MAX, 11880, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 30, UINT16_MAX, UINT16_MAX, 11882, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 31, UINT16_MAX, UINT16_MAX, 11884, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 32, UINT16_MAX, UINT16_MAX, 11886, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 33, UINT16_MAX, UINT16_MAX, 11888, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 34, UINT16_MAX, UINT16_MAX, 11890, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 35, UINT16_MAX, UINT16_MAX, 11892, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 36, UINT16_MAX, UINT16_MAX, 11894, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37, UINT16_MAX, UINT16_MAX, 11896, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 38, UINT16_MAX, UINT16_MAX, 11898, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 39, UINT16_MAX, UINT16_MAX, 11900, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 40, UINT16_MAX, UINT16_MAX, 11902, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 41, UINT16_MAX, UINT16_MAX, 11904, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 42, UINT16_MAX, UINT16_MAX, 11906, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 43, UINT16_MAX, UINT16_MAX, 11908, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 44, UINT16_MAX, UINT16_MAX, 11910, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 45, UINT16_MAX, UINT16_MAX, 11912, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 46, UINT16_MAX, UINT16_MAX, 11914, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 47, UINT16_MAX, UINT16_MAX, 11916, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 48, UINT16_MAX, UINT16_MAX, 11918, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 49, UINT16_MAX, UINT16_MAX, 11920, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 50, UINT16_MAX, UINT16_MAX, 11922, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 51, UINT16_MAX, UINT16_MAX, 11924, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 22717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 44700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28319, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11937, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11939, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11941, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11943, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11945, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11947, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11949, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11951, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11953, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11955, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11957, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11959, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11961, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11963, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11965, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11967, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11969, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11971, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11973, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11975, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11977, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11979, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11981, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11983, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11985, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11987, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 28373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 28375, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 28377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11995, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11997, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 11999, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12001, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12003, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12005, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12007, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12009, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12011, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12013, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12015, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12017, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12019, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12021, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12023, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12025, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12027, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12029, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12031, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12033, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12035, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12037, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12039, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12041, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12043, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 12045, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 5709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12053, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12055, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12057, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 5281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12059, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7077, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12061, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12065, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12069, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12071, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 5273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12073, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 5622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 5276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 5623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12074, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4993, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12075, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12077, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12079, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 5605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12080, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12081, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12083, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 44876, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12111, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12112, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12113, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12115, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12118, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12119, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12120, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12121, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12123, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12124, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12125, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12127, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12129, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12133, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12136, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12137, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12139, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12143, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12145, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12081, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12149, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12150, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12151, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12152, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12155, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12165, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12168, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12170, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12172, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12203, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12207, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12209, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12213, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12214, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12215, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12218, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12239, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12245, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12316, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12318, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12319, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12330, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12334, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12336, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12342, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12345, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12363, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12369, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12372, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12379, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12381, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12383, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12384, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12385, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12386, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12389, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12391, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12392, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12394, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12395, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12396, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12398, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12400, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12402, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12404, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12406, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4982, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4989, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12646, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12655, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5037, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5041, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 12680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND, UTF8PROC_INDIC_CONJUNCT_BREAK_NONE}, }; static const utf8proc_uint16_t utf8proc_combinations[] = { @@ -14807,14 +16946,15 @@ static const utf8proc_uint16_t utf8proc_combinations[] = { 1, 5307, 1, 5308, 1, 5310, 68, 69, 1, 5562, 68, 69, 1, 5563, -70, 71, 1, 53598, -70, 71, 1, 53599, -72, 81, 1, 53600, - 1, 53601, 1, 53602, 1, 53603, 1, 53604, -70, 71, 1, 53691, -70, 71, 1, 53692, -72, 75, 1, 53693, 1, 53695, -72, 75, - 1, 53694, 1, 53696, +70, 71, 1, 6456, +72, 73, 1, 53598, +72, 73, 1, 53599, +74, 83, + 1, 53600, 1, 53601, 1, 53602, 1, 53603, 1, 53604, +72, 73, 1, 53691, +72, 73, 1, 53692, +74, 77, 1, 53693, + 1, 53695, +74, 77, 1, 53694, 1, 53696, }; diff --git a/third_party/utf8proc/utf8proc_wrapper.cpp b/third_party/utf8proc/utf8proc_wrapper.cpp index 9ff3615e8a8..40db1d609bd 100644 --- a/third_party/utf8proc/utf8proc_wrapper.cpp +++ b/third_party/utf8proc/utf8proc_wrapper.cpp @@ -1,6 +1,8 @@ #include "utf8proc_wrapper.hpp" #include "utf8proc.hpp" #include "duckdb/common/assert.hpp" +#include "duckdb/common/exception.hpp" + using namespace std; namespace duckdb { @@ -21,7 +23,8 @@ namespace duckdb { // 3 U+000800 U+00FFFF 1110xxxx // 4 U+010000 U+10FFFF 11110xxx -static void AssignInvalidUTF8Reason(UnicodeInvalidReason *invalid_reason, size_t *invalid_pos, size_t pos, UnicodeInvalidReason reason) { +static void AssignInvalidUTF8Reason(UnicodeInvalidReason *invalid_reason, size_t *invalid_pos, size_t pos, + UnicodeInvalidReason reason) { if (invalid_reason) { *invalid_reason = reason; } @@ -31,16 +34,16 @@ static void AssignInvalidUTF8Reason(UnicodeInvalidReason *invalid_reason, size_t } template -static inline UnicodeType -UTF8ExtraByteLoop(const int first_pos_seq, int utf8char, size_t& i, - const char *s, const size_t len, UnicodeInvalidReason *invalid_reason, size_t *invalid_pos) { +static inline UnicodeType UTF8ExtraByteLoop(const int first_pos_seq, int utf8char, size_t &i, const char *s, + const size_t len, UnicodeInvalidReason *invalid_reason, + size_t *invalid_pos) { if ((len - i) < (nextra_bytes + 1)) { /* incomplete byte sequence */ AssignInvalidUTF8Reason(invalid_reason, invalid_pos, first_pos_seq, UnicodeInvalidReason::BYTE_MISMATCH); return UnicodeType::INVALID; } - for (size_t j = 0 ; j < nextra_bytes; j++) { - int c = (int) s[++i]; + for (size_t j = 0; j < nextra_bytes; j++) { + int c = (int)s[++i]; /* now validate the extra bytes */ if ((c & 0xC0) != 0x80) { /* extra byte is not in the format 10xxxxxx */ @@ -60,7 +63,8 @@ UTF8ExtraByteLoop(const int first_pos_seq, int utf8char, size_t& i, return UnicodeType::INVALID; } if ((utf8char & 0x1FFF800) == 0xD800) { - /* Unicode characters from U+D800 to U+DFFF are surrogate characters used by UTF-16 which are invalid in UTF-8 */ + /* Unicode characters from U+D800 to U+DFFF are surrogate characters used by UTF-16 which are invalid in UTF-8 + */ AssignInvalidUTF8Reason(invalid_reason, invalid_pos, first_pos_seq, UnicodeInvalidReason::INVALID_UNICODE); return UnicodeType::INVALID; } @@ -71,7 +75,7 @@ UnicodeType Utf8Proc::Analyze(const char *s, size_t len, UnicodeInvalidReason *i UnicodeType type = UnicodeType::ASCII; for (size_t i = 0; i < len; i++) { - int c = (int) s[i]; + int c = (int)s[i]; if ((c & 0x80) == 0) { continue; @@ -102,11 +106,11 @@ UnicodeType Utf8Proc::Analyze(const char *s, size_t len, UnicodeInvalidReason *i return type; } -void Utf8Proc::MakeValid(char *s, size_t len, char special_flag){ - D_ASSERT(special_flag <=127); +void Utf8Proc::MakeValid(char *s, size_t len, char special_flag) { + D_ASSERT(special_flag <= 127); UnicodeType type = UnicodeType::ASCII; for (size_t i = 0; i < len; i++) { - int c = (int) s[i]; + int c = (int)s[i]; if ((c & 0x80) == 0) { continue; } @@ -129,18 +133,18 @@ void Utf8Proc::MakeValid(char *s, size_t len, char special_flag){ } if (type == UnicodeType::INVALID) { for (size_t j = first_pos_seq; j <= i; j++) { - s[j] = special_flag; // Rewrite each byte of the invalid sequence - } + s[j] = special_flag; // Rewrite each byte of the invalid sequence + } type = UnicodeType::ASCII; } } - D_ASSERT(Utf8Proc::IsValid(s,len)); + D_ASSERT(Utf8Proc::IsValid(s, len)); } -char* Utf8Proc::Normalize(const char *s, size_t len) { +char *Utf8Proc::Normalize(const char *s, size_t len) { assert(s); assert(Utf8Proc::Analyze(s, len) != UnicodeType::INVALID); - return (char*) utf8proc_NFC((const utf8proc_uint8_t*) s, len); + return (char *)utf8proc_NFC((const utf8proc_uint8_t *)s, len); } bool Utf8Proc::IsValid(const char *s, size_t len) { @@ -148,7 +152,97 @@ bool Utf8Proc::IsValid(const char *s, size_t len) { } size_t Utf8Proc::NextGraphemeCluster(const char *s, size_t len, size_t cpos) { - return utf8proc_next_grapheme(s, len, cpos); + int sz; + auto prev_codepoint = Utf8Proc::UTF8ToCodepoint(s + cpos, sz); + utf8proc_int32_t state = 0; + while (true) { + cpos += sz; + if (cpos >= len) { + return cpos; + } + auto next_codepoint = Utf8Proc::UTF8ToCodepoint(s + cpos, sz); + if (utf8proc_grapheme_break_stateful(prev_codepoint, next_codepoint, &state)) { + // found a grapheme break here + return cpos; + } + // not a grapheme break, move on to next codepoint + prev_codepoint = next_codepoint; + } +} + +size_t Utf8Proc::GraphemeCount(const char *input_data, size_t input_size) { + size_t num_characters = 0; + for (auto cluster : Utf8Proc::GraphemeClusters(input_data, input_size)) { + (void)cluster; + num_characters++; + } + return num_characters; +} + +int32_t Utf8Proc::CodepointToUpper(int32_t codepoint) { + return utf8proc_toupper(codepoint); +} + +int32_t Utf8Proc::CodepointToLower(int32_t codepoint) { + return utf8proc_tolower(codepoint); +} + +GraphemeIterator::GraphemeIterator(const char *s, size_t len) : s(s), len(len) { +} + +GraphemeIterator Utf8Proc::GraphemeClusters(const char *s, size_t len) { + return GraphemeIterator(s, len); +} + +GraphemeIterator::GraphemeClusterIterator::GraphemeClusterIterator(const char *s_p, size_t len_p) : s(s_p), len(len_p) { + if (s) { + cluster.start = 0; + cluster.end = 0; + Next(); + } else { + SetInvalid(); + } +} + +void GraphemeIterator::GraphemeClusterIterator::SetInvalid() { + s = nullptr; + len = 0; + cluster.start = 0; + cluster.end = 0; +} + +bool GraphemeIterator::GraphemeClusterIterator::IsInvalid() const { + return !s; +} + +void GraphemeIterator::GraphemeClusterIterator::Next() { + if (IsInvalid()) { + throw std::runtime_error("Grapheme cluster out of bounds!"); + } + if (cluster.end >= len) { + // out of bounds + SetInvalid(); + return; + } + size_t next_pos = Utf8Proc::NextGraphemeCluster(s, len, cluster.end); + cluster.start = cluster.end; + cluster.end = next_pos; +} + +GraphemeIterator::GraphemeClusterIterator &GraphemeIterator::GraphemeClusterIterator::operator++() { + Next(); + return *this; +} +bool GraphemeIterator::GraphemeClusterIterator::operator!=(const GraphemeClusterIterator &other) const { + return !(len == other.len && s == other.s && cluster.start == other.cluster.start && + cluster.end == other.cluster.end); +} + +GraphemeCluster GraphemeIterator::GraphemeClusterIterator::operator*() const { + if (IsInvalid()) { + throw std::runtime_error("Grapheme cluster out of bounds!"); + } + return cluster; } size_t Utf8Proc::PreviousGraphemeCluster(const char *s, size_t len, size_t cpos) { @@ -156,7 +250,7 @@ size_t Utf8Proc::PreviousGraphemeCluster(const char *s, size_t len, size_t cpos) return cpos - 1; } size_t current_pos = 0; - while(true) { + while (true) { size_t new_pos = NextGraphemeCluster(s, len, current_pos); if (new_pos <= current_pos || new_pos >= cpos) { return current_pos; @@ -166,30 +260,92 @@ size_t Utf8Proc::PreviousGraphemeCluster(const char *s, size_t len, size_t cpos) } bool Utf8Proc::CodepointToUtf8(int cp, int &sz, char *c) { - return utf8proc_codepoint_to_utf8(cp, sz, c); + if (cp <= 0x7F) { + sz = 1; + c[0] = cp; + } else if (cp <= 0x7FF) { + sz = 2; + c[0] = (cp >> 6) + 192; + c[1] = (cp & 63) + 128; + } else if (0xd800 <= cp && cp <= 0xdfff) { + sz = -1; + // invalid block of utf + return false; + } else if (cp <= 0xFFFF) { + sz = 3; + c[0] = (cp >> 12) + 224; + c[1] = ((cp >> 6) & 63) + 128; + c[2] = (cp & 63) + 128; + } else if (cp <= 0x10FFFF) { + sz = 4; + c[0] = (cp >> 18) + 240; + c[1] = ((cp >> 12) & 63) + 128; + c[2] = ((cp >> 6) & 63) + 128; + c[3] = (cp & 63) + 128; + } else { + sz = -1; + return false; + } + return true; } int Utf8Proc::CodepointLength(int cp) { - return utf8proc_codepoint_length(cp); + if (cp <= 0x7F) { + return 1; + } else if (cp <= 0x7FF) { + return 2; + } else if (0xd800 <= cp && cp <= 0xdfff) { + return -1; + } else if (cp <= 0xFFFF) { + return 3; + } else if (cp <= 0x10FFFF) { + return 4; + } + return -1; } -int32_t Utf8Proc::UTF8ToCodepoint(const char *c, int &sz) { - return utf8proc_codepoint(c, sz); +int32_t Utf8Proc::UTF8ToCodepoint(const char *u_input, int &sz) { + // from http://www.zedwood.com/article/cpp-utf8-char-to-codepoint + auto u = reinterpret_cast(u_input); + unsigned char u0 = u[0]; + if (u0 <= 127) { + sz = 1; + return u0; + } + unsigned char u1 = u[1]; + if (u0 >= 192 && u0 <= 223) { + sz = 2; + return (u0 - 192) * 64 + (u1 - 128); + } + if (u[0] == 0xed && (u[1] & 0xa0) == 0xa0) { + return -1; // code points, 0xd800 to 0xdfff + } + unsigned char u2 = u[2]; + if (u0 >= 224 && u0 <= 239) { + sz = 3; + return (u0 - 224) * 4096 + (u1 - 128) * 64 + (u2 - 128); + } + unsigned char u3 = u[3]; + if (u0 >= 240 && u0 <= 247) { + sz = 4; + return (u0 - 240) * 262144 + (u1 - 128) * 4096 + (u2 - 128) * 64 + (u3 - 128); + } + return -1; } size_t Utf8Proc::RenderWidth(const char *s, size_t len, size_t pos) { - int sz; - auto codepoint = duckdb::utf8proc_codepoint(s + pos, sz); - auto properties = duckdb::utf8proc_get_property(codepoint); - return properties->charwidth; + int sz; + auto codepoint = Utf8Proc::UTF8ToCodepoint(s + pos, sz); + auto properties = duckdb::utf8proc_get_property(codepoint); + return properties->charwidth; } size_t Utf8Proc::RenderWidth(const std::string &str) { size_t render_width = 0; size_t pos = 0; - while(pos < str.size()) { + while (pos < str.size()) { int sz; - auto codepoint = duckdb::utf8proc_codepoint(str.c_str() + pos, sz); + auto codepoint = Utf8Proc::UTF8ToCodepoint(str.c_str() + pos, sz); auto properties = duckdb::utf8proc_get_property(codepoint); render_width += properties->charwidth; pos += sz; @@ -197,4 +353,4 @@ size_t Utf8Proc::RenderWidth(const std::string &str) { return render_width; } -} +} // namespace duckdb diff --git a/third_party/yyjson/CMakeLists.txt b/third_party/yyjson/CMakeLists.txt new file mode 100644 index 00000000000..bd9cae5cfd2 --- /dev/null +++ b/third_party/yyjson/CMakeLists.txt @@ -0,0 +1,17 @@ +if(POLICY CMP0063) + cmake_policy(SET CMP0063 NEW) +endif() + +add_library(duckdb_yyjson STATIC yyjson.cpp) + +target_include_directories( + duckdb_yyjson + PUBLIC $) +set_target_properties(duckdb_yyjson PROPERTIES EXPORT_NAME duckdb_duckdb_yyjson) + +install(TARGETS duckdb_yyjson + EXPORT "${DUCKDB_EXPORT_SET}" + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}") + +disable_target_warnings(duckdb_yyjson) diff --git a/third_party/yyjson/LICENSE b/third_party/yyjson/LICENSE new file mode 100644 index 00000000000..c4904d1f11a --- /dev/null +++ b/third_party/yyjson/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 YaoYuan + +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. \ No newline at end of file diff --git a/extension/json/yyjson/include/yyjson.hpp b/third_party/yyjson/include/yyjson.hpp similarity index 70% rename from extension/json/yyjson/include/yyjson.hpp rename to third_party/yyjson/include/yyjson.hpp index 1c3af3bf144..69898d15024 100644 --- a/extension/json/yyjson/include/yyjson.hpp +++ b/third_party/yyjson/include/yyjson.hpp @@ -1,15 +1,33 @@ /*============================================================================== - * Created by Yaoyuan on 2019/3/9. - * Copyright (C) 2019 Yaoyuan . - * - * Released under the MIT License: - * https://github.com/ibireme/yyjson/blob/master/LICENSE + Copyright (c) 2020 YaoYuan + + 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. *============================================================================*/ -/** @file yyjson.h */ +/** + @file yyjson.h + @date 2019-03-09 + @author YaoYuan + */ -#ifndef YYJSON_H -#define YYJSON_H +#ifndef DUCKDB_YYJSON_H +#define DUCKDB_YYJSON_H @@ -17,6 +35,7 @@ * Header Files *============================================================================*/ +#include #include #include #include @@ -25,17 +44,19 @@ #include "duckdb/common/fast_mem.hpp" +namespace duckdb_yyjson { + /*============================================================================== * Compile-time Options *============================================================================*/ /* - Define as 1 to disable JSON reader if you don't need to parse JSON. + Define as 1 to disable JSON reader if JSON parsing is not required. This will disable these functions at compile-time: + - yyjson_read() - yyjson_read_opts() - yyjson_read_file() - - yyjson_read() - yyjson_read_number() - yyjson_mut_read_number() @@ -45,7 +66,7 @@ #endif /* - Define as 1 to disable JSON writer if you don't need to serialize JSON. + Define as 1 to disable JSON writer if JSON serialization is not required. This will disable these functions at compile-time: - yyjson_write() @@ -66,6 +87,22 @@ #ifndef YYJSON_DISABLE_WRITER #endif +/* + Define as 1 to disable JSON Pointer, JSON Patch and JSON Merge Patch supports. + + This will disable these functions at compile-time: + - yyjson_ptr_xxx() + - yyjson_mut_ptr_xxx() + - yyjson_doc_ptr_xxx() + - yyjson_mut_doc_ptr_xxx() + - yyjson_patch() + - yyjson_mut_patch() + - yyjson_merge_patch() + - yyjson_mut_merge_patch() + */ +#ifndef YYJSON_DISABLE_UTILS +#endif + /* Define as 1 to disable the fast floating-point number conversion in yyjson, and use libc's `strtod/snprintf` instead. @@ -91,19 +128,36 @@ - YYJSON_WRITE_ALLOW_INF_AND_NAN - YYJSON_WRITE_ALLOW_INVALID_UNICODE - This will reduce the binary size by about 10%, and slightly improve the JSON - read/write speed. + This will reduce the binary size by about 10%, and speed up the reading and + writing speed by about 2% to 6%. */ #ifndef YYJSON_DISABLE_NON_STANDARD #endif /* - Define as 1 to disable unaligned memory access if target architecture does not - support unaligned memory access (such as some embedded processors). + Define as 1 to disable UTF-8 validation at compile time. + + If all input strings are guaranteed to be valid UTF-8 encoding (for example, + some language's String object has already validated the encoding), using this + flag can avoid redundant UTF-8 validation in yyjson. - If this value is not defined, yyjson will perform some automatic detection. - The wrong definition of this option may cause some performance degradation, - but will not cause any run-time errors. + This flag can speed up the reading and writing speed of non-ASCII encoded + strings by about 3% to 7%. + + Note: If this flag is used while passing in illegal UTF-8 strings, the + following errors may occur: + - Escaped characters may be ignored when parsing JSON strings. + - Ending quotes may be ignored when parsing JSON strings, causing the string + to be concatenated to the next value. + - When accessing `yyjson_mut_val` for serialization, the string ending may be + accessed out of bounds, causing a segmentation fault. + */ +#ifndef YYJSON_DISABLE_UTF8_VALIDATION +#endif + +/* + Define as 1 to indicate that the target architecture does not support unaligned + memory access. Please refer to the comments in the C file for details. */ #ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS #endif @@ -140,8 +194,26 @@ /** compiler version (GCC) */ #ifdef __GNUC__ # define YYJSON_GCC_VER __GNUC__ +# if defined(__GNUC_PATCHLEVEL__) +# define yyjson_gcc_available(major, minor, patch) \ + ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \ + >= (major * 10000 + minor * 100 + patch)) +# else +# define yyjson_gcc_available(major, minor, patch) \ + ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) \ + >= (major * 10000 + minor * 100 + patch)) +# endif #else # define YYJSON_GCC_VER 0 +# define yyjson_gcc_available(major, minor, patch) 0 +#endif + +/** real gcc check */ +#if !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__ICC) && \ + defined(__GNUC__) +# define YYJSON_IS_REAL_GCC 1 +#else +# define YYJSON_IS_REAL_GCC 0 #endif /** C version (STDC) */ @@ -176,6 +248,15 @@ # endif #endif +/** compiler feature check (since clang 2.6, icc 17) */ +#ifndef yyjson_has_feature +# ifdef __has_feature +# define yyjson_has_feature(x) __has_feature(x) +# else +# define yyjson_has_feature(x) 0 +# endif +#endif + /** include check (since gcc 5.0, clang 2.7, icc 16, msvc 2017 15.3) */ #ifndef yyjson_has_include # ifdef __has_include @@ -246,6 +327,31 @@ # endif #endif +/** compile-time constant check for compiler */ +#ifndef yyjson_constant_p +# if yyjson_has_builtin(__builtin_constant_p) || (YYJSON_GCC_VER >= 3) +# define YYJSON_HAS_CONSTANT_P 1 +# define yyjson_constant_p(value) __builtin_constant_p(value) +# else +# define YYJSON_HAS_CONSTANT_P 0 +# define yyjson_constant_p(value) 0 +# endif +#endif + +/** deprecate warning */ +#ifndef yyjson_deprecated +# if YYJSON_MSC_VER >= 1400 +# define yyjson_deprecated(msg) __declspec(deprecated(msg)) +# elif yyjson_has_feature(attribute_deprecated_with_message) || \ + (YYJSON_GCC_VER > 4 || (YYJSON_GCC_VER == 4 && __GNUC_MINOR__ >= 5)) +# define yyjson_deprecated(msg) __attribute__((deprecated(msg))) +# elif YYJSON_GCC_VER >= 3 +# define yyjson_deprecated(msg) __attribute__((deprecated)) +# else +# define yyjson_deprecated(msg) +# endif +#endif + /** function export */ #ifndef yyjson_api # if defined(_WIN32) @@ -374,6 +480,18 @@ # endif #endif +/** + Microsoft Visual C++ 6.0 doesn't support converting number from u64 to f64: + error C2520: conversion from unsigned __int64 to double not implemented. + */ +#ifndef YYJSON_U64_TO_F64_NO_IMPL +# if (0 < YYJSON_MSC_VER) && (YYJSON_MSC_VER <= 1200) +# define YYJSON_U64_TO_F64_NO_IMPL 1 +# else +# define YYJSON_U64_TO_F64_NO_IMPL 0 +# endif +#endif + /*============================================================================== @@ -382,18 +500,20 @@ /* extern "C" begin */ #ifdef __cplusplus -extern "C" { +// extern "C" { #endif /* warning suppress begin */ #if defined(__clang__) # pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunused-const-variable" # pragma clang diagnostic ignored "-Wunused-function" # pragma clang diagnostic ignored "-Wunused-parameter" #elif defined(__GNUC__) # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # pragma GCC diagnostic push # endif +# pragma GCC diagnostic ignored "-Wunused-const-variable" # pragma GCC diagnostic ignored "-Wunused-function" # pragma GCC diagnostic ignored "-Wunused-parameter" #elif defined(_MSC_VER) @@ -411,16 +531,16 @@ extern "C" { #define YYJSON_VERSION_MAJOR 0 /** The minor version of yyjson. */ -#define YYJSON_VERSION_MINOR 6 +#define YYJSON_VERSION_MINOR 9 /** The patch version of yyjson. */ #define YYJSON_VERSION_PATCH 0 /** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */ -#define YYJSON_VERSION_HEX 0x000600 +#define YYJSON_VERSION_HEX 0x000900 /** The version string of yyjson. */ -#define YYJSON_VERSION_STRING "0.6.0" +#define YYJSON_VERSION_STRING "0.9.0" /** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */ yyjson_api uint32_t yyjson_version(void); @@ -431,34 +551,57 @@ yyjson_api uint32_t yyjson_version(void); * JSON Types *============================================================================*/ -/** Type of JSON value (3 bit). */ +/** Type of a JSON value (3 bit). */ typedef uint8_t yyjson_type; +/** No type, invalid. */ #define YYJSON_TYPE_NONE ((uint8_t)0) /* _____000 */ +/** Raw string type, no subtype. */ #define YYJSON_TYPE_RAW ((uint8_t)1) /* _____001 */ +/** Null type: `null` literal, no subtype. */ #define YYJSON_TYPE_NULL ((uint8_t)2) /* _____010 */ +/** Boolean type, subtype: TRUE, FALSE. */ #define YYJSON_TYPE_BOOL ((uint8_t)3) /* _____011 */ +/** Number type, subtype: UINT, SINT, REAL. */ #define YYJSON_TYPE_NUM ((uint8_t)4) /* _____100 */ +/** String type, subtype: NONE, NOESC. */ #define YYJSON_TYPE_STR ((uint8_t)5) /* _____101 */ +/** Array type, no subtype. */ #define YYJSON_TYPE_ARR ((uint8_t)6) /* _____110 */ +/** Object type, no subtype. */ #define YYJSON_TYPE_OBJ ((uint8_t)7) /* _____111 */ -/** Subtype of JSON value (2 bit). */ +/** Subtype of a JSON value (2 bit). */ typedef uint8_t yyjson_subtype; +/** No subtype. */ #define YYJSON_SUBTYPE_NONE ((uint8_t)(0 << 3)) /* ___00___ */ +/** False subtype: `false` literal. */ #define YYJSON_SUBTYPE_FALSE ((uint8_t)(0 << 3)) /* ___00___ */ +/** True subtype: `true` literal. */ #define YYJSON_SUBTYPE_TRUE ((uint8_t)(1 << 3)) /* ___01___ */ +/** Unsigned integer subtype: `uint64_t`. */ #define YYJSON_SUBTYPE_UINT ((uint8_t)(0 << 3)) /* ___00___ */ +/** Signed integer subtype: `int64_t`. */ #define YYJSON_SUBTYPE_SINT ((uint8_t)(1 << 3)) /* ___01___ */ +/** Real number subtype: `double`. */ #define YYJSON_SUBTYPE_REAL ((uint8_t)(2 << 3)) /* ___10___ */ +/** String that do not need to be escaped for writing (internal use). */ +#define YYJSON_SUBTYPE_NOESC ((uint8_t)(1 << 3)) /* ___01___ */ -/** Mask and bits of JSON value tag. */ +/** The mask used to extract the type of a JSON value. */ #define YYJSON_TYPE_MASK ((uint8_t)0x07) /* _____111 */ +/** The number of bits used by the type. */ #define YYJSON_TYPE_BIT ((uint8_t)3) +/** The mask used to extract the subtype of a JSON value. */ #define YYJSON_SUBTYPE_MASK ((uint8_t)0x18) /* ___11___ */ +/** The number of bits used by the subtype. */ #define YYJSON_SUBTYPE_BIT ((uint8_t)2) +/** The mask used to extract the reserved bits of a JSON value. */ #define YYJSON_RESERVED_MASK ((uint8_t)0xE0) /* 111_____ */ +/** The number of reserved bits. */ #define YYJSON_RESERVED_BIT ((uint8_t)3) +/** The mask used to extract the tag of a JSON value. */ #define YYJSON_TAG_MASK ((uint8_t)0xFF) /* 11111111 */ +/** The number of bits used by the tag. */ #define YYJSON_TAG_BIT ((uint8_t)8) /** Padding size for JSON reader. */ @@ -490,13 +633,17 @@ typedef struct yyjson_alc { /** A pool allocator uses fixed length pre-allocated memory. - This allocator may used to avoid malloc/realloc calls. The pre-allocated memory - should be held by the caller. The maximum amount of memory required to read a - JSON can be calculated using the `yyjson_read_max_memory_usage()` function, but - the amount of memory required to write a JSON cannot be directly calculated. + This allocator may be used to avoid malloc/realloc calls. The pre-allocated + memory should be held by the caller. The maximum amount of memory required to + read a JSON can be calculated using the `yyjson_read_max_memory_usage()` + function, but the amount of memory required to write a JSON cannot be directly + calculated. - This is not a general-purpose allocator, and should only be used to read or - write single JSON document. + This is not a general-purpose allocator. It is designed to handle a single JSON + data at a time. If it is used for overly complex memory tasks, such as parsing + multiple JSON documents using the same allocator but releasing only a few of + them, it may cause memory fragmentation, resulting in performance degradation + and memory waste. @param alc The allocator to be initialized. If this parameter is NULL, the function will fail and return false. @@ -519,9 +666,31 @@ typedef struct yyjson_alc { yyjson_doc *doc = yyjson_read_opts(json, strlen(json), 0, &alc, NULL); // the memory of `doc` is on the stack @endcode + + @warning This Allocator is not thread-safe. */ yyjson_api bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, size_t size); +/** + A dynamic allocator. + + This allocator has a similar usage to the pool allocator above. However, when + there is not enough memory, this allocator will dynamically request more memory + using libc's `malloc` function, and frees it all at once when it is destroyed. + + @return A new dynamic allocator, or NULL if memory allocation failed. + @note The returned value should be freed with `yyjson_alc_dyn_free()`. + + @warning This Allocator is not thread-safe. + */ +yyjson_api yyjson_alc *yyjson_alc_dyn_new(void); + +/** + Free a dynamic allocator which is created by `yyjson_alc_dyn_new()`. + @param alc The dynamic allocator to be destroyed. + */ +yyjson_api void yyjson_alc_dyn_free(yyjson_alc *alc); + /*============================================================================== @@ -570,10 +739,10 @@ typedef uint32_t yyjson_read_flag; - Read negative integer as int64_t. - Read floating-point number as double with round-to-nearest mode. - Read integer which cannot fit in uint64_t or int64_t as double. - - Report error if real number is infinity. + - Report error if double number is infinity. - Report error if string contains invalid UTF-8 character or BOM. - Report error on trailing commas, comments, inf and nan literals. */ -static const yyjson_read_flag YYJSON_READ_NOFLAG = 0 << 0; +static const yyjson_read_flag YYJSON_READ_NOFLAG = 0; /** Read the input data in-situ. This option allows the reader to modify and use input data to store string @@ -599,7 +768,7 @@ static const yyjson_read_flag YYJSON_READ_ALLOW_COMMENTS = 1 << 3; such as 1e999, NaN, inf, -Infinity (non-standard). */ static const yyjson_read_flag YYJSON_READ_ALLOW_INF_AND_NAN = 1 << 4; -/** Read number as raw string (value with `YYJSON_TYPE_RAW` type), +/** Read all numbers as raw strings (value with `YYJSON_TYPE_RAW` type), inf/nan literal is also read as raw with `ALLOW_INF_AND_NAN` flag. */ static const yyjson_read_flag YYJSON_READ_NUMBER_AS_RAW = 1 << 5; @@ -613,6 +782,12 @@ static const yyjson_read_flag YYJSON_READ_NUMBER_AS_RAW = 1 << 5; risks. */ static const yyjson_read_flag YYJSON_READ_ALLOW_INVALID_UNICODE = 1 << 6; +/** Read big numbers as raw strings. These big numbers include integers that + cannot be represented by `int64_t` and `uint64_t`, and floating-point + numbers that cannot be represented by finite `double`. + The flag will be overridden by `YYJSON_READ_NUMBER_AS_RAW` flag. */ +static const yyjson_read_flag YYJSON_READ_BIGNUM_AS_RAW = 1 << 7; + /** Result code for JSON reader. */ @@ -630,7 +805,7 @@ static const yyjson_read_code YYJSON_READ_ERROR_MEMORY_ALLOCATION = 2; /** Input JSON string is empty. */ static const yyjson_read_code YYJSON_READ_ERROR_EMPTY_CONTENT = 3; -/** Unexpected content after document, such as `[1]abc`. */ +/** Unexpected content after document, such as `[123]abc`. */ static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CONTENT = 4; /** Unexpected ending, such as `[123`. */ @@ -726,6 +901,28 @@ yyjson_api yyjson_doc *yyjson_read_file(const char *path, const yyjson_alc *alc, yyjson_read_err *err); +/** + Read JSON from a file pointer. + + @param fp The file pointer. + The data will be read from the current position of the FILE to the end. + If this fp is NULL or invalid, the function will fail and return NULL. + @param flg The JSON read options. + Multiple options can be combined with `|` operator. 0 means no options. + @param alc The memory allocator used by JSON reader. + Pass NULL to use the libc's default allocator. + @param err A pointer to receive error information. + Pass NULL if you don't need error information. + @return A new JSON document, or NULL if an error occurs. + When it's no longer needed, it should be freed with `yyjson_doc_free()`. + + @warning On 32-bit operating system, files larger than 2GB may fail to read. + */ +yyjson_api yyjson_doc *yyjson_read_fp(FILE *fp, + yyjson_read_flag flg, + const yyjson_alc *alc, + yyjson_read_err *err); + /** Read a JSON string. @@ -744,7 +941,8 @@ yyjson_api_inline yyjson_doc *yyjson_read(const char *dat, size_t len, yyjson_read_flag flg) { flg &= ~YYJSON_READ_INSITU; /* const string cannot be modified */ - return yyjson_read_opts((char *)dat, len, flg, NULL, NULL); + return yyjson_read_opts((char *)(void *)(size_t)(const void *)dat, + len, flg, NULL, NULL); } /** @@ -816,7 +1014,7 @@ yyjson_api_inline size_t yyjson_read_max_memory_usage(size_t len, The value will hold either UINT or SINT or REAL number; @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. - Suppors `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`. + Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`. @param alc The memory allocator used for long number. It is only used when the built-in floating point reader is disabled. Pass NULL to use the libc's default allocator. @@ -843,7 +1041,7 @@ yyjson_api const char *yyjson_read_number(const char *dat, The value will hold either UINT or SINT or REAL number; @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. - Suppors `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`. + Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`. @param alc The memory allocator used for long number. It is only used when the built-in floating point reader is disabled. Pass NULL to use the libc's default allocator. @@ -873,7 +1071,7 @@ typedef uint32_t yyjson_write_flag; - Report error on inf or nan number. - Report error on invalid UTF-8 string. - Do not escape unicode or slash. */ -static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0 << 0; +static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0; /** Write JSON pretty with 4 space indent. */ static const yyjson_write_flag YYJSON_WRITE_PRETTY = 1 << 0; @@ -902,6 +1100,10 @@ static const yyjson_write_flag YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5; This flag will override `YYJSON_WRITE_PRETTY` flag. */ static const yyjson_write_flag YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6; +/** Adds a newline character `\n` at the end of the JSON. + This can be helpful for text editors or NDJSON. */ +static const yyjson_write_flag YYJSON_WRITE_NEWLINE_AT_END = 1 << 7; + /** Result code for JSON writer */ @@ -957,8 +1159,8 @@ typedef struct yyjson_write_err { Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. - @param len A pointer to receive output length in bytes. - Pass NULL if you don't need length information. + @param len A pointer to receive output length in bytes (not including the + null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. @@ -999,6 +1201,30 @@ yyjson_api bool yyjson_write_file(const char *path, const yyjson_alc *alc, yyjson_write_err *err); +/** + Write a document to file pointer with options. + + @param fp The file pointer. + The data will be written to the current position of the file. + If this fp is NULL or invalid, the function will fail and return false. + @param doc The JSON document. + If this doc is NULL or has no root, the function will fail and return false. + @param flg The JSON write options. + Multiple options can be combined with `|` operator. 0 means no options. + @param alc The memory allocator used by JSON writer. + Pass NULL to use the libc's default allocator. + @param err A pointer to receive error information. + Pass NULL if you don't need error information. + @return true if successful, false if an error occurs. + + @warning On 32-bit operating system, files larger than 2GB may fail to write. + */ +yyjson_api bool yyjson_write_fp(FILE *fp, + const yyjson_doc *doc, + yyjson_write_flag flg, + const yyjson_alc *alc, + yyjson_write_err *err); + /** Write a document to JSON string. @@ -1008,8 +1234,8 @@ yyjson_api bool yyjson_write_file(const char *path, If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. - @param len A pointer to receive output length in bytes. - Pass NULL if you don't need length information. + @param len A pointer to receive output length in bytes (not including the + null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). @@ -1035,8 +1261,8 @@ yyjson_api_inline char *yyjson_write(const yyjson_doc *doc, Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. - @param len A pointer to receive output length in bytes. - Pass NULL if you don't need length information. + @param len A pointer to receive output length in bytes (not including the + null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. @@ -1078,6 +1304,30 @@ yyjson_api bool yyjson_mut_write_file(const char *path, const yyjson_alc *alc, yyjson_write_err *err); +/** + Write a document to file pointer with options. + + @param fp The file pointer. + The data will be written to the current position of the file. + If this fp is NULL or invalid, the function will fail and return false. + @param doc The mutable JSON document. + If this doc is NULL or has no root, the function will fail and return false. + @param flg The JSON write options. + Multiple options can be combined with `|` operator. 0 means no options. + @param alc The memory allocator used by JSON writer. + Pass NULL to use the libc's default allocator. + @param err A pointer to receive error information. + Pass NULL if you don't need error information. + @return true if successful, false if an error occurs. + + @warning On 32-bit operating system, files larger than 2GB may fail to write. + */ +yyjson_api bool yyjson_mut_write_fp(FILE *fp, + const yyjson_mut_doc *doc, + yyjson_write_flag flg, + const yyjson_alc *alc, + yyjson_write_err *err); + /** Write a document to JSON string. @@ -1088,8 +1338,8 @@ yyjson_api bool yyjson_mut_write_file(const char *path, If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. - @param len A pointer to receive output length in bytes. - Pass NULL if you don't need length information. + @param len A pointer to receive output length in bytes (not including the + null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). @@ -1118,8 +1368,8 @@ yyjson_api_inline char *yyjson_mut_write(const yyjson_mut_doc *doc, Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. - @param len A pointer to receive output length in bytes. - Pass NULL if you don't need length information. + @param len A pointer to receive output length in bytes (not including the + null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. @@ -1160,6 +1410,30 @@ yyjson_api bool yyjson_val_write_file(const char *path, const yyjson_alc *alc, yyjson_write_err *err); +/** + Write a value to file pointer with options. + + @param fp The file pointer. + The data will be written to the current position of the file. + If this path is NULL or invalid, the function will fail and return false. + @param val The JSON root value. + If this parameter is NULL, the function will fail and return NULL. + @param flg The JSON write options. + Multiple options can be combined with `|` operator. 0 means no options. + @param alc The memory allocator used by JSON writer. + Pass NULL to use the libc's default allocator. + @param err A pointer to receive error information. + Pass NULL if you don't need error information. + @return true if successful, false if an error occurs. + + @warning On 32-bit operating system, files larger than 2GB may fail to write. + */ +yyjson_api bool yyjson_val_write_fp(FILE *fp, + const yyjson_val *val, + yyjson_write_flag flg, + const yyjson_alc *alc, + yyjson_write_err *err); + /** Write a value to JSON string. @@ -1169,8 +1443,8 @@ yyjson_api bool yyjson_val_write_file(const char *path, If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. - @param len A pointer to receive output length in bytes. - Pass NULL if you don't need length information. + @param len A pointer to receive output length in bytes (not including the + null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). @@ -1194,8 +1468,8 @@ yyjson_api_inline char *yyjson_val_write(const yyjson_val *val, Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. - @param len A pointer to receive output length in bytes. - Pass NULL if you don't need length information. + @param len A pointer to receive output length in bytes (not including the + null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. @@ -1237,6 +1511,30 @@ yyjson_api bool yyjson_mut_val_write_file(const char *path, const yyjson_alc *alc, yyjson_write_err *err); +/** + Write a value to JSON file with options. + + @param fp The file pointer. + The data will be written to the current position of the file. + If this path is NULL or invalid, the function will fail and return false. + @param val The mutable JSON root value. + If this parameter is NULL, the function will fail and return NULL. + @param flg The JSON write options. + Multiple options can be combined with `|` operator. 0 means no options. + @param alc The memory allocator used by JSON writer. + Pass NULL to use the libc's default allocator. + @param err A pointer to receive error information. + Pass NULL if you don't need error information. + @return true if successful, false if an error occurs. + + @warning On 32-bit operating system, files larger than 2GB may fail to write. + */ +yyjson_api bool yyjson_mut_val_write_fp(FILE *fp, + const yyjson_mut_val *val, + yyjson_write_flag flg, + const yyjson_alc *alc, + yyjson_write_err *err); + /** Write a value to JSON string. @@ -1247,8 +1545,8 @@ yyjson_api bool yyjson_mut_val_write_file(const char *path, If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. - @param len A pointer to receive output length in bytes. - Pass NULL if you don't need length information. + @param len A pointer to receive output length in bytes (not including the + null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). @@ -1393,6 +1691,10 @@ yyjson_api_inline int yyjson_get_int(yyjson_val *val); Returns 0.0 if `val` is NULL or type is not real(double). */ yyjson_api_inline double yyjson_get_real(yyjson_val *val); +/** Returns the content and typecast to `double` if the value is number. + Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */ +yyjson_api_inline double yyjson_get_num(yyjson_val *val); + /** Returns the content if the value is string. Returns NULL if `val` is NULL or type is not string. */ yyjson_api_inline const char *yyjson_get_str(yyjson_val *val); @@ -1412,7 +1714,10 @@ yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str, size_t len); /** Returns whether two JSON values are equal (deep compare). - Returns false if input is NULL. */ + Returns false if input is NULL. + @note the result may be inaccurate if object has duplicate keys. + @warning This function is recursive and may cause a stack overflow + if the object level is too deep. */ yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs); /** Set the value to raw. @@ -1500,14 +1805,17 @@ yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr); @par Example @code yyjson_val *val; - yyjson_arr_iter iter; - yyjson_arr_iter_init(arr, &iter); + yyjson_arr_iter iter = yyjson_arr_iter_with(arr); while ((val = yyjson_arr_iter_next(&iter))) { your_func(val); } @endcode */ -typedef struct yyjson_arr_iter yyjson_arr_iter; +typedef struct yyjson_arr_iter { + size_t idx; /**< next value's index */ + size_t max; /**< maximum index (arr.size) */ + yyjson_val *cur; /**< next value */ +} yyjson_arr_iter; /** Initialize an iterator for this array. @@ -1523,6 +1831,17 @@ typedef struct yyjson_arr_iter yyjson_arr_iter; yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr, yyjson_arr_iter *iter); +/** + Create an iterator with an array , same as `yyjson_arr_iter_init()`. + + @param arr The array to be iterated over. + If this parameter is NULL or not an array, an empty iterator will returned. + @return A new iterator for the array. + + @note The iterator does not need to be destroyed. + */ +yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr); + /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. @@ -1598,8 +1917,7 @@ yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, const char *key, @par Example @code yyjson_val *key, *val; - yyjson_obj_iter iter; - yyjson_obj_iter_init(obj, &iter); + yyjson_obj_iter iter = yyjson_obj_iter_with(obj); while ((key = yyjson_obj_iter_next(&iter))) { val = yyjson_obj_iter_get_val(key); your_func(key, val); @@ -1611,14 +1929,18 @@ yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, const char *key, @code // {"k1":1, "k2": 3, "k3": 3} yyjson_val *key, *val; - yyjson_obj_iter iter; - yyjson_obj_iter_init(obj, &iter); + yyjson_obj_iter iter = yyjson_obj_iter_with(obj); yyjson_val *v1 = yyjson_obj_iter_get(&iter, "k1"); yyjson_val *v3 = yyjson_obj_iter_get(&iter, "k3"); @endcode @see yyjson_obj_iter_get() and yyjson_obj_iter_getn() */ -typedef struct yyjson_obj_iter yyjson_obj_iter; +typedef struct yyjson_obj_iter { + size_t idx; /**< next key's index */ + size_t max; /**< maximum key index (obj.size) */ + yyjson_val *cur; /**< next key */ + yyjson_val *obj; /**< the object being iterated */ +} yyjson_obj_iter; /** Initialize an iterator for this object. @@ -1634,6 +1956,17 @@ typedef struct yyjson_obj_iter yyjson_obj_iter; yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj, yyjson_obj_iter *iter); +/** + Create an iterator with an object, same as `yyjson_obj_iter_init()`. + + @param obj The object to be iterated over. + If this parameter is NULL or not an object, an empty iterator will returned. + @return A new iterator for the object. + + @note The iterator does not need to be destroyed. + */ +yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj); + /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. @@ -1730,6 +2063,38 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc); yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc, yyjson_mut_val *root); +/** + Set the string pool size for a mutable document. + This function does not allocate memory immediately, but uses the size when + the next memory allocation is needed. + + If the caller knows the approximate bytes of strings that the document needs to + store (e.g. copy string with `yyjson_mut_strcpy` function), setting a larger + size can avoid multiple memory allocations and improve performance. + + @param doc The mutable document. + @param len The desired string pool size in bytes (total string length). + @return true if successful, false if size is 0 or overflow. + */ +yyjson_api bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc, + size_t len); + +/** + Set the value pool size for a mutable document. + This function does not allocate memory immediately, but uses the size when + the next memory allocation is needed. + + If the caller knows the approximate number of values that the document needs to + store (e.g. create new value with `yyjson_mut_xxx` functions), setting a larger + size can avoid multiple memory allocations and improve performance. + + @param doc The mutable document. + @param count The desired value pool size (number of `yyjson_mut_val`). + @return true if successful, false if size is 0 or overflow. + */ +yyjson_api bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc, + size_t count); + /** Release the JSON document and free the memory. After calling this function, the `doc` and all values from the `doc` are no longer available. This function will do nothing if the `doc` is NULL. */ @@ -1896,6 +2261,10 @@ yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val); Returns 0.0 if `val` is NULL or type is not real(double). */ yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val); +/** Returns the content and typecast to `double` if the value is number. + Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */ +yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val); + /** Returns the content if the value is string. Returns NULL if `val` is NULL or type is not string. */ yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val); @@ -1918,7 +2287,7 @@ yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val, /** Returns whether two JSON values are equal (deep compare). Returns false if input is NULL. - + @note the result may be inaccurate if object has duplicate keys. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs, @@ -2113,8 +2482,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last(yyjson_mut_val *arr); @par Example @code yyjson_mut_val *val; - yyjson_mut_arr_iter iter; - yyjson_mut_arr_iter_init(arr, &iter); + yyjson_mut_arr_iter iter = yyjson_mut_arr_iter_with(arr); while ((val = yyjson_mut_arr_iter_next(&iter))) { your_func(val); if (your_val_is_unused(val)) { @@ -2123,7 +2491,13 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last(yyjson_mut_val *arr); } @endcode */ -typedef struct yyjson_mut_arr_iter yyjson_mut_arr_iter; +typedef struct yyjson_mut_arr_iter { + size_t idx; /**< next value's index */ + size_t max; /**< maximum index (arr.size) */ + yyjson_mut_val *cur; /**< current value */ + yyjson_mut_val *pre; /**< previous value */ + yyjson_mut_val *arr; /**< the array being iterated */ +} yyjson_mut_arr_iter; /** Initialize an iterator for this array. @@ -2139,6 +2513,18 @@ typedef struct yyjson_mut_arr_iter yyjson_mut_arr_iter; yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr, yyjson_mut_arr_iter *iter); +/** + Create an iterator with an array , same as `yyjson_mut_arr_iter_init()`. + + @param arr The array to be iterated over. + If this parameter is NULL or not an array, an empty iterator will returned. + @return A new iterator for the array. + + @note The iterator does not need to be destroyed. + */ +yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with( + yyjson_mut_val *arr); + /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. @@ -2886,8 +3272,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj, @par Example @code yyjson_mut_val *key, *val; - yyjson_mut_obj_iter iter; - yyjson_mut_obj_iter_init(obj, &iter); + yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj); while ((key = yyjson_mut_obj_iter_next(&iter))) { val = yyjson_mut_obj_iter_get_val(key); your_func(key, val); @@ -2902,14 +3287,19 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj, @code // {"k1":1, "k2": 3, "k3": 3} yyjson_mut_val *key, *val; - yyjson_mut_obj_iter iter; - yyjson_mut_obj_iter_init(obj, &iter); + yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj); yyjson_mut_val *v1 = yyjson_mut_obj_iter_get(&iter, "k1"); yyjson_mut_val *v3 = yyjson_mut_obj_iter_get(&iter, "k3"); @endcode @see `yyjson_mut_obj_iter_get()` and `yyjson_mut_obj_iter_getn()` */ -typedef struct yyjson_mut_obj_iter yyjson_mut_obj_iter; +typedef struct yyjson_mut_obj_iter { + size_t idx; /**< next key's index */ + size_t max; /**< maximum key index (obj.size) */ + yyjson_mut_val *cur; /**< current key */ + yyjson_mut_val *pre; /**< previous key */ + yyjson_mut_val *obj; /**< the object being iterated */ +} yyjson_mut_obj_iter; /** Initialize an iterator for this object. @@ -2925,6 +3315,18 @@ typedef struct yyjson_mut_obj_iter yyjson_mut_obj_iter; yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj, yyjson_mut_obj_iter *iter); +/** + Create an iterator with an object, same as `yyjson_obj_iter_init()`. + + @param obj The object to be iterated over. + If this parameter is NULL or not an object, an empty iterator will returned. + @return A new iterator for the object. + + @note The iterator does not need to be destroyed. + */ +yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with( + yyjson_mut_val *obj); + /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. @@ -2947,7 +3349,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val( yyjson_mut_val *key); /** - Removes and returns current key-value pair in the iteration. + Removes current key-value pair in the iteration, returns the removed value. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove( @@ -3184,7 +3586,7 @@ yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3194,7 +3596,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3204,7 +3606,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3214,7 +3616,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3224,7 +3626,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3234,7 +3636,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3244,7 +3646,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3254,7 +3656,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3264,7 +3666,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc, The `key` and `val` should be null-terminated UTF-8 strings. This function allows duplicated key in one object. - @warning The key/value string are not copied, you should keep these strings + @warning The key/value strings are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3276,7 +3678,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc, The `len` should be the length of the `val`, in bytes. This function allows duplicated key in one object. - @warning The key/value string are not copied, you should keep these strings + @warning The key/value strings are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3288,7 +3690,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc, The value string is copied. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3301,18 +3703,44 @@ yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc, The `len` should be the length of the `val`, in bytes. This function allows duplicated key in one object. - @warning The key/value string are not copied, you should keep these strings + @warning The key strings are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val, size_t len); +/** + Creates and adds a new array to the target object. + The `key` should be a null-terminated UTF-8 string. + This function allows duplicated key in one object. + + @warning The key string is not copied, you should keep these strings + unmodified for the lifetime of this JSON document. + @return The new array, or NULL on error. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *key); + +/** + Creates and adds a new object to the target object. + The `key` should be a null-terminated UTF-8 string. + This function allows duplicated key in one object. + + @warning The key string is not copied, you should keep these strings + unmodified for the lifetime of this JSON document. + @return The new object, or NULL on error. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *key); + /** Adds a JSON value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3369,98 +3797,683 @@ yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc, /*============================================================================== - * JSON Pointer API + * JSON Pointer API (RFC 6901) * https://tools.ietf.org/html/rfc6901 *============================================================================*/ -/** Get a JSON value with JSON Pointer (RFC 6901). - The `ptr` should be a null-terminated UTF-8 string. - - Returns NULL if there's no matched value. - Returns NULL if `val/ptr` is NULL or `val` is not object. */ -yyjson_api_inline yyjson_val *yyjson_get_pointer(yyjson_val *val, - const char *ptr); +/** JSON Pointer error code. */ +typedef uint32_t yyjson_ptr_code; -/** Get a JSON value with JSON Pointer (RFC 6901). - The `ptr` should be a UTF-8 string, null-terminator is not required. - The `len` should be the length of the `ptr`, in bytes. - - Returns NULL if there's no matched value. - Returns NULL if `val/ptr` is NULL or `val` is not object. */ -yyjson_api_inline yyjson_val *yyjson_get_pointern(yyjson_val *val, - const char *ptr, - size_t len); +/** No JSON pointer error. */ +static const yyjson_ptr_code YYJSON_PTR_ERR_NONE = 0; -/** Get a JSON value with JSON Pointer (RFC 6901). - The `ptr` should be a null-terminated UTF-8 string. - - Returns NULL if there's no matched value. */ -yyjson_api_inline yyjson_val *yyjson_doc_get_pointer(yyjson_doc *doc, - const char *ptr); +/** Invalid input parameter, such as NULL input. */ +static const yyjson_ptr_code YYJSON_PTR_ERR_PARAMETER = 1; -/** Get a JSON value with JSON Pointer (RFC 6901). - The `ptr` should be a UTF-8 string, null-terminator is not required. - The `len` should be the length of the `ptr`, in bytes. - - Returns NULL if there's no matched value. */ -yyjson_api_inline yyjson_val *yyjson_doc_get_pointern(yyjson_doc *doc, - const char *ptr, - size_t len); +/** JSON pointer syntax error, such as invalid escape, token no prefix. */ +static const yyjson_ptr_code YYJSON_PTR_ERR_SYNTAX = 2; -/** Get a JSON value with JSON Pointer (RFC 6901). - The `ptr` should be a null-terminated UTF-8 string. - - Returns NULL if there's no matched value. */ -yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointer(yyjson_mut_val *val, - const char *ptr); +/** JSON pointer resolve failed, such as index out of range, key not found. */ +static const yyjson_ptr_code YYJSON_PTR_ERR_RESOLVE = 3; -/** Get a JSON value with JSON Pointer (RFC 6901). - The `ptr` should be a UTF-8 string, null-terminator is not required. - The `len` should be the length of the `ptr`, in bytes. - - Returns NULL if there's no matched value. */ -yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointern(yyjson_mut_val *val, - const char *ptr, - size_t len); +/** Document's root is NULL, but it is required for the function call. */ +static const yyjson_ptr_code YYJSON_PTR_ERR_NULL_ROOT = 4; -/** Get a JSON value with JSON Pointer (RFC 6901). - The `ptr` should be a null-terminated UTF-8 string. - - Returns NULL if there's no matched value. */ -yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointer( - yyjson_mut_doc *doc, const char *ptr); +/** Cannot set root as the target is not a document. */ +static const yyjson_ptr_code YYJSON_PTR_ERR_SET_ROOT = 5; -/** Get a JSON value with JSON Pointer (RFC 6901). - The `ptr` should be a UTF-8 string, null-terminator is not required. - The `len` should be the length of the `ptr`, in bytes. - - Returns NULL if there's no matched value. */ -yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointern( - yyjson_mut_doc *doc, const char *ptr, size_t len); +/** The memory allocation failed and a new value could not be created. */ +static const yyjson_ptr_code YYJSON_PTR_ERR_MEMORY_ALLOCATION = 6; +/** Error information for JSON pointer. */ +typedef struct yyjson_ptr_err { + /** Error code, see `yyjson_ptr_code` for all possible values. */ + yyjson_ptr_code code; + /** Error message, constant, no need to free (NULL if no error). */ + const char *msg; + /** Error byte position for input JSON pointer (0 if no error). */ + size_t pos; +} yyjson_ptr_err; +/** + A context for JSON pointer operation. + + This struct stores the context of JSON Pointer operation result. The struct + can be used with three helper functions: `ctx_append()`, `ctx_replace()`, and + `ctx_remove()`, which perform the corresponding operations on the container + without re-parsing the JSON Pointer. + + For example: + @code + // doc before: {"a":[0,1,null]} + // ptr: "/a/2" + val = yyjson_mut_doc_ptr_getx(doc, ptr, strlen(ptr), &ctx, &err); + if (yyjson_is_null(val)) { + yyjson_ptr_ctx_remove(&ctx); + } + // doc after: {"a":[0,1]} + @endcode + */ +typedef struct yyjson_ptr_ctx { + /** + The container (parent) of the target value. It can be either an array or + an object. If the target location has no value, but all its parent + containers exist, and the target location can be used to insert a new + value, then `ctn` is the parent container of the target location. + Otherwise, `ctn` is NULL. + */ + yyjson_mut_val *ctn; + /** + The previous sibling of the target value. It can be either a value in an + array or a key in an object. As the container is a `circular linked list` + of elements, `pre` is the previous node of the target value. If the + operation is `add` or `set`, then `pre` is the previous node of the new + value, not the original target value. If the target value does not exist, + `pre` is NULL. + */ + yyjson_mut_val *pre; + /** + The removed value if the operation is `set`, `replace` or `remove`. It can + be used to restore the original state of the document if needed. + */ + yyjson_mut_val *old; +} yyjson_ptr_ctx; -/*============================================================================== - * JSON Merge-Patch API - * https://tools.ietf.org/html/rfc7386 - *============================================================================*/ +/** + Get value by a JSON Pointer. + @param doc The JSON document to be queried. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @return The value referenced by the JSON pointer. + NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc, + const char *ptr); -/** Creates and returns a merge-patched JSON value (RFC 7386). - The memory of the returned value is allocated by the `doc`. - Returns NULL if the patch could not be applied. - - @warning This function is recursive and may cause a stack overflow if the - object level is too deep. */ +/** + Get value by a JSON Pointer. + @param doc The JSON document to be queried. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @return The value referenced by the JSON pointer. + NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc, + const char *ptr, size_t len); + +/** + Get value by a JSON Pointer. + @param doc The JSON document to be queried. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param err A pointer to store the error information, or NULL if not needed. + @return The value referenced by the JSON pointer. + NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc, + const char *ptr, size_t len, + yyjson_ptr_err *err); + +/** + Get value by a JSON Pointer. + @param val The JSON value to be queried. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @return The value referenced by the JSON pointer. + NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val, + const char *ptr); + +/** + Get value by a JSON Pointer. + @param val The JSON value to be queried. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @return The value referenced by the JSON pointer. + NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val, + const char *ptr, size_t len); + +/** + Get value by a JSON Pointer. + @param val The JSON value to be queried. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param err A pointer to store the error information, or NULL if not needed. + @return The value referenced by the JSON pointer. + NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val, + const char *ptr, size_t len, + yyjson_ptr_err *err); + +/** + Get value by a JSON Pointer. + @param doc The JSON document to be queried. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @return The value referenced by the JSON pointer. + NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc, + const char *ptr); + +/** + Get value by a JSON Pointer. + @param doc The JSON document to be queried. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @return The value referenced by the JSON pointer. + NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc, + const char *ptr, + size_t len); + +/** + Get value by a JSON Pointer. + @param doc The JSON document to be queried. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param ctx A pointer to store the result context, or NULL if not needed. + @param err A pointer to store the error information, or NULL if not needed. + @return The value referenced by the JSON pointer. + NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc, + const char *ptr, + size_t len, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err); + +/** + Get value by a JSON Pointer. + @param val The JSON value to be queried. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @return The value referenced by the JSON pointer. + NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val, + const char *ptr); + +/** + Get value by a JSON Pointer. + @param val The JSON value to be queried. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @return The value referenced by the JSON pointer. + NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val, + const char *ptr, + size_t len); + +/** + Get value by a JSON Pointer. + @param val The JSON value to be queried. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param ctx A pointer to store the result context, or NULL if not needed. + @param err A pointer to store the error information, or NULL if not needed. + @return The value referenced by the JSON pointer. + NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val, + const char *ptr, + size_t len, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err); + +/** + Add (insert) value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @param new_val The value to be added. + @return true if JSON pointer is valid and new value is added, false otherwise. + @note The parent nodes will be created if they do not exist. + */ +yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc, + const char *ptr, + yyjson_mut_val *new_val); + +/** + Add (insert) value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param new_val The value to be added. + @return true if JSON pointer is valid and new value is added, false otherwise. + @note The parent nodes will be created if they do not exist. + */ +yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc, + const char *ptr, size_t len, + yyjson_mut_val *new_val); + +/** + Add (insert) value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param new_val The value to be added. + @param create_parent Whether to create parent nodes if not exist. + @param ctx A pointer to store the result context, or NULL if not needed. + @param err A pointer to store the error information, or NULL if not needed. + @return true if JSON pointer is valid and new value is added, false otherwise. + */ +yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + bool create_parent, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err); + +/** + Add (insert) value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @param doc Only used to create new values when needed. + @param new_val The value to be added. + @return true if JSON pointer is valid and new value is added, false otherwise. + @note The parent nodes will be created if they do not exist. + */ +yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val, + const char *ptr, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc); + +/** + Add (insert) value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param doc Only used to create new values when needed. + @param new_val The value to be added. + @return true if JSON pointer is valid and new value is added, false otherwise. + @note The parent nodes will be created if they do not exist. + */ +yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc); + +/** + Add (insert) value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param doc Only used to create new values when needed. + @param new_val The value to be added. + @param create_parent Whether to create parent nodes if not exist. + @param ctx A pointer to store the result context, or NULL if not needed. + @param err A pointer to store the error information, or NULL if not needed. + @return true if JSON pointer is valid and new value is added, false otherwise. + */ +yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc, + bool create_parent, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err); + +/** + Set value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @param new_val The value to be set, pass NULL to remove. + @return true if JSON pointer is valid and new value is set, false otherwise. + @note The parent nodes will be created if they do not exist. + If the target value already exists, it will be replaced by the new value. + */ +yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc, + const char *ptr, + yyjson_mut_val *new_val); + +/** + Set value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param new_val The value to be set, pass NULL to remove. + @return true if JSON pointer is valid and new value is set, false otherwise. + @note The parent nodes will be created if they do not exist. + If the target value already exists, it will be replaced by the new value. + */ +yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc, + const char *ptr, size_t len, + yyjson_mut_val *new_val); + +/** + Set value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param new_val The value to be set, pass NULL to remove. + @param create_parent Whether to create parent nodes if not exist. + @param ctx A pointer to store the result context, or NULL if not needed. + @param err A pointer to store the error information, or NULL if not needed. + @return true if JSON pointer is valid and new value is set, false otherwise. + @note If the target value already exists, it will be replaced by the new value. + */ +yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + bool create_parent, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err); + +/** + Set value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @param new_val The value to be set, pass NULL to remove. + @param doc Only used to create new values when needed. + @return true if JSON pointer is valid and new value is set, false otherwise. + @note The parent nodes will be created if they do not exist. + If the target value already exists, it will be replaced by the new value. + */ +yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val, + const char *ptr, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc); + +/** + Set value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param new_val The value to be set, pass NULL to remove. + @param doc Only used to create new values when needed. + @return true if JSON pointer is valid and new value is set, false otherwise. + @note The parent nodes will be created if they do not exist. + If the target value already exists, it will be replaced by the new value. + */ +yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc); + +/** + Set value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param new_val The value to be set, pass NULL to remove. + @param doc Only used to create new values when needed. + @param create_parent Whether to create parent nodes if not exist. + @param ctx A pointer to store the result context, or NULL if not needed. + @param err A pointer to store the error information, or NULL if not needed. + @return true if JSON pointer is valid and new value is set, false otherwise. + @note If the target value already exists, it will be replaced by the new value. + */ +yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc, + bool create_parent, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err); + +/** + Replace value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @param new_val The new value to replace the old one. + @return The old value that was replaced, or NULL if not found. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace( + yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val); + +/** + Replace value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param new_val The new value to replace the old one. + @return The old value that was replaced, or NULL if not found. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen( + yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val); + +/** + Replace value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param new_val The new value to replace the old one. + @param ctx A pointer to store the result context, or NULL if not needed. + @param err A pointer to store the error information, or NULL if not needed. + @return The old value that was replaced, or NULL if not found. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex( + yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, + yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); + +/** + Replace value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @param new_val The new value to replace the old one. + @return The old value that was replaced, or NULL if not found. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace( + yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val); + +/** + Replace value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param new_val The new value to replace the old one. + @return The old value that was replaced, or NULL if not found. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen( + yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val); + +/** + Replace value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param new_val The new value to replace the old one. + @param ctx A pointer to store the result context, or NULL if not needed. + @param err A pointer to store the error information, or NULL if not needed. + @return The old value that was replaced, or NULL if not found. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex( + yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, + yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); + +/** + Remove value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @return The removed value, or NULL on error. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove( + yyjson_mut_doc *doc, const char *ptr); + +/** + Remove value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @return The removed value, or NULL on error. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen( + yyjson_mut_doc *doc, const char *ptr, size_t len); + +/** + Remove value by a JSON pointer. + @param doc The target JSON document. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param ctx A pointer to store the result context, or NULL if not needed. + @param err A pointer to store the error information, or NULL if not needed. + @return The removed value, or NULL on error. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex( + yyjson_mut_doc *doc, const char *ptr, size_t len, + yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); + +/** + Remove value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8 with null-terminator). + @return The removed value, or NULL on error. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val, + const char *ptr); + +/** + Remove value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @return The removed value, or NULL on error. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val, + const char *ptr, + size_t len); + +/** + Remove value by a JSON pointer. + @param val The target JSON value. + @param ptr The JSON pointer string (UTF-8, null-terminator is not required). + @param len The length of `ptr` in bytes. + @param ctx A pointer to store the result context, or NULL if not needed. + @param err A pointer to store the error information, or NULL if not needed. + @return The removed value, or NULL on error. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val, + const char *ptr, + size_t len, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err); + +/** + Append value by JSON pointer context. + @param ctx The context from the `yyjson_mut_ptr_xxx()` calls. + @param key New key if `ctx->ctn` is object, or NULL if `ctx->ctn` is array. + @param val New value to be added. + @return true on success or false on fail. + */ +yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx, + yyjson_mut_val *key, + yyjson_mut_val *val); + +/** + Replace value by JSON pointer context. + @param ctx The context from the `yyjson_mut_ptr_xxx()` calls. + @param val New value to be replaced. + @return true on success or false on fail. + @note If success, the old value will be returned via `ctx->old`. + */ +yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx, + yyjson_mut_val *val); + +/** + Remove value by JSON pointer context. + @param ctx The context from the `yyjson_mut_ptr_xxx()` calls. + @return true on success or false on fail. + @note If success, the old value will be returned via `ctx->old`. + */ +yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx); + + + +/*============================================================================== + * JSON Patch API (RFC 6902) + * https://tools.ietf.org/html/rfc6902 + *============================================================================*/ + +/** Result code for JSON patch. */ +typedef uint32_t yyjson_patch_code; + +/** Success, no error. */ +static const yyjson_patch_code YYJSON_PATCH_SUCCESS = 0; + +/** Invalid parameter, such as NULL input or non-array patch. */ +static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_PARAMETER = 1; + +/** Memory allocation failure occurs. */ +static const yyjson_patch_code YYJSON_PATCH_ERROR_MEMORY_ALLOCATION = 2; + +/** JSON patch operation is not object type. */ +static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_OPERATION = 3; + +/** JSON patch operation is missing a required key. */ +static const yyjson_patch_code YYJSON_PATCH_ERROR_MISSING_KEY = 4; + +/** JSON patch operation member is invalid. */ +static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_MEMBER = 5; + +/** JSON patch operation `test` not equal. */ +static const yyjson_patch_code YYJSON_PATCH_ERROR_EQUAL = 6; + +/** JSON patch operation failed on JSON pointer. */ +static const yyjson_patch_code YYJSON_PATCH_ERROR_POINTER = 7; + +/** Error information for JSON patch. */ +typedef struct yyjson_patch_err { + /** Error code, see `yyjson_patch_code` for all possible values. */ + yyjson_patch_code code; + /** Index of the error operation (0 if no error). */ + size_t idx; + /** Error message, constant, no need to free (NULL if no error). */ + const char *msg; + /** JSON pointer error if `code == YYJSON_PATCH_ERROR_POINTER`. */ + yyjson_ptr_err ptr; +} yyjson_patch_err; + +/** + Creates and returns a patched JSON value (RFC 6902). + The memory of the returned value is allocated by the `doc`. + The `err` is used to receive error information, pass NULL if not needed. + Returns NULL if the patch could not be applied. + */ +yyjson_api yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc, + yyjson_val *orig, + yyjson_val *patch, + yyjson_patch_err *err); + +/** + Creates and returns a patched JSON value (RFC 6902). + The memory of the returned value is allocated by the `doc`. + The `err` is used to receive error information, pass NULL if not needed. + Returns NULL if the patch could not be applied. + */ +yyjson_api yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc, + yyjson_mut_val *orig, + yyjson_mut_val *patch, + yyjson_patch_err *err); + + + +/*============================================================================== + * JSON Merge-Patch API (RFC 7386) + * https://tools.ietf.org/html/rfc7386 + *============================================================================*/ + +/** + Creates and returns a merge-patched JSON value (RFC 7386). + The memory of the returned value is allocated by the `doc`. + Returns NULL if the patch could not be applied. + + @warning This function is recursive and may cause a stack overflow if the + object level is too deep. + */ yyjson_api yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc, yyjson_val *orig, yyjson_val *patch); -/** Creates and returns a merge-patched JSON value (RFC 7386). - The memory of the returned value is allocated by the `doc`. - Returns NULL if the patch could not be applied. - - @warning This function is recursive and may cause a stack overflow if the - object level is too deep. */ +/** + Creates and returns a merge-patched JSON value (RFC 7386). + The memory of the returned value is allocated by the `doc`. + Returns NULL if the patch could not be applied. + + @warning This function is recursive and may cause a stack overflow if the + object level is too deep. + */ yyjson_api yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc, yyjson_mut_val *orig, yyjson_mut_val *patch); @@ -3508,6 +4521,58 @@ struct yyjson_doc { * Unsafe JSON Value API (Implementation) *============================================================================*/ +/* + Whether the string does not need to be escaped for serialization. + This function is used to optimize the writing speed of small constant strings. + This function works only if the compiler can evaluate it at compile time. + + Clang supports it since v8.0, + earlier versions do not support constant_p(strlen) and return false. + GCC supports it since at least v4.4, + earlier versions may compile it as run-time instructions. + ICC supports it since at least v16, + earlier versions are uncertain. + + @param str The C string. + @param len The returnd value from strlen(str). + */ +yyjson_api_inline bool unsafe_yyjson_is_str_noesc(const char *str, size_t len) { +#if YYJSON_HAS_CONSTANT_P && \ + (!YYJSON_IS_REAL_GCC || yyjson_gcc_available(4, 4, 0)) + if (yyjson_constant_p(len) && len <= 32) { + /* + Same as the following loop: + + for (size_t i = 0; i < len; i++) { + char c = str[i]; + if (c < ' ' || c > '~' || c == '"' || c == '\\') return false; + } + + GCC evaluates it at compile time only if the string length is within 17 + and -O3 (which turns on the -fpeel-loops flag) is used. + So the loop is unrolled for GCC. + */ +# define yyjson_repeat32_incr(x) \ + x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \ + x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) \ + x(16) x(17) x(18) x(19) x(20) x(21) x(22) x(23) \ + x(24) x(25) x(26) x(27) x(28) x(29) x(30) x(31) +# define yyjson_check_char_noesc(i) \ + if (i < len) { \ + char c = str[i]; \ + if (c < ' ' || c > '~' || c == '"' || c == '\\') return false; } + yyjson_repeat32_incr(yyjson_check_char_noesc) +# undef yyjson_repeat32_incr +# undef yyjson_check_char_noesc + return true; + } +#else + (void)str; + (void)len; +#endif + return false; +} + yyjson_api_inline yyjson_type unsafe_yyjson_get_type(void *val) { uint8_t tag = (uint8_t)((yyjson_val *)val)->tag; return (yyjson_type)(tag & YYJSON_TYPE_MASK); @@ -3618,6 +4683,28 @@ yyjson_api_inline double unsafe_yyjson_get_real(void *val) { return ((yyjson_val *)val)->uni.f64; } +yyjson_api_inline double unsafe_yyjson_get_num(void *val) { + uint8_t tag = unsafe_yyjson_get_tag(val); + if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL)) { + return ((yyjson_val *)val)->uni.f64; + } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT)) { + return (double)((yyjson_val *)val)->uni.i64; + } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT)) { +#if YYJSON_U64_TO_F64_NO_IMPL + uint64_t msb = ((uint64_t)1) << 63; + uint64_t num = ((yyjson_val *)val)->uni.u64; + if ((num & msb) == 0) { + return (double)(int64_t)num; + } else { + return ((double)(int64_t)((num >> 1) | (num & 1))) * (double)2.0; + } +#else + return (double)((yyjson_val *)val)->uni.u64; +#endif + } + return 0.0; +} + yyjson_api_inline const char *unsafe_yyjson_get_str(void *val) { return ((yyjson_val *)val)->uni.str; } @@ -3639,9 +4726,8 @@ yyjson_api_inline yyjson_val *unsafe_yyjson_get_next(yyjson_val *val) { yyjson_api_inline bool unsafe_yyjson_equals_strn(void *val, const char *str, size_t len) { - uint64_t tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; - return ((yyjson_val *)val)->tag == tag && - duckdb::FastMemcmp(((yyjson_val *)val)->uni.str, str, len) == 0; + return unsafe_yyjson_get_len(val) == len && + memcmp(((yyjson_val *)val)->uni.str, str, len) == 0; } yyjson_api_inline bool unsafe_yyjson_equals_str(void *val, const char *str) { @@ -3656,18 +4742,18 @@ yyjson_api_inline void unsafe_yyjson_set_type(void *val, yyjson_type type, ((yyjson_val *)val)->tag = new_tag; } -yyjson_api_inline void unsafe_yyjson_set_tag(void *val, uint8_t tag) { - uint64_t new_tag = ((yyjson_val *)val)->tag; - new_tag = (new_tag & (~(uint64_t)YYJSON_TAG_MASK)) | (uint64_t)tag; - ((yyjson_val *)val)->tag = new_tag; -} - yyjson_api_inline void unsafe_yyjson_set_len(void *val, size_t len) { uint64_t tag = ((yyjson_val *)val)->tag & YYJSON_TAG_MASK; tag |= (uint64_t)len << YYJSON_TAG_BIT; ((yyjson_val *)val)->tag = tag; } +yyjson_api_inline void unsafe_yyjson_inc_len(void *val) { + uint64_t tag = ((yyjson_val *)val)->tag; + tag += (uint64_t)(1 << YYJSON_TAG_BIT); + ((yyjson_val *)val)->tag = tag; +} + yyjson_api_inline void unsafe_yyjson_set_raw(void *val, const char *raw, size_t len) { unsafe_yyjson_set_type(val, YYJSON_TYPE_RAW, YYJSON_SUBTYPE_NONE); @@ -3705,13 +4791,16 @@ yyjson_api_inline void unsafe_yyjson_set_real(void *val, double num) { } yyjson_api_inline void unsafe_yyjson_set_str(void *val, const char *str) { - unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, YYJSON_SUBTYPE_NONE); - unsafe_yyjson_set_len(val, strlen(str)); + size_t len = strlen(str); + bool noesc = unsafe_yyjson_is_str_noesc(str, len); + yyjson_subtype sub = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE; + unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, sub); + unsafe_yyjson_set_len(val, len); ((yyjson_val *)val)->uni.str = str; } yyjson_api_inline void unsafe_yyjson_set_strn(void *val, const char *str, - size_t len) { + size_t len) { unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, len); ((yyjson_val *)val)->uni.str = str; @@ -3748,6 +4837,7 @@ yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc) { yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc) { if (doc) { yyjson_alc alc = doc->alc; + memset(&doc->alc, 0, sizeof(alc)); if (doc->str_pool) alc.free(alc.ctx, doc->str_pool); alc.free(alc.ctx, doc); } @@ -3838,6 +4928,7 @@ yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val) { case YYJSON_TYPE_RAW | YYJSON_SUBTYPE_NONE: return "raw"; case YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE: return "null"; case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: return "string"; + case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC: return "string"; case YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE: return "array"; case YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE: return "object"; case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE: return "true"; @@ -3873,6 +4964,10 @@ yyjson_api_inline double yyjson_get_real(yyjson_val *val) { return yyjson_is_real(val) ? unsafe_yyjson_get_real(val) : 0.0; } +yyjson_api_inline double yyjson_get_num(yyjson_val *val) { + return val ? unsafe_yyjson_get_num(val) : 0.0; +} + yyjson_api_inline const char *yyjson_get_str(yyjson_val *val) { return yyjson_is_str(val) ? unsafe_yyjson_get_str(val) : NULL; } @@ -3883,7 +4978,8 @@ yyjson_api_inline size_t yyjson_get_len(yyjson_val *val) { yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str) { if (yyjson_likely(val && str)) { - return unsafe_yyjson_equals_str(val, str); + return unsafe_yyjson_is_str(val) && + unsafe_yyjson_equals_str(val, str); } return false; } @@ -3891,7 +4987,8 @@ yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str) { yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str, size_t len) { if (yyjson_likely(val && str)) { - return unsafe_yyjson_equals_strn(val, str, len); + return unsafe_yyjson_is_str(val) && + unsafe_yyjson_equals_strn(val, str, len); } return false; } @@ -4017,12 +5114,6 @@ yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr) { * JSON Array Iterator API (Implementation) *============================================================================*/ -struct yyjson_arr_iter { - size_t idx; /**< current index, from 0 */ - size_t max; /**< maximum index, idx < max */ - yyjson_val *cur; /**< current value */ -}; - yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr, yyjson_arr_iter *iter) { if (yyjson_likely(yyjson_is_arr(arr) && iter)) { @@ -4035,6 +5126,12 @@ yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr, return false; } +yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr) { + yyjson_arr_iter iter; + yyjson_arr_iter_init(arr, &iter); + return iter; +} + yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter) { return iter ? iter->idx < iter->max : false; } @@ -4068,15 +5165,11 @@ yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj, yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, const char *_key, size_t key_len) { - uint64_t tag = (((uint64_t)key_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; if (yyjson_likely(yyjson_is_obj(obj) && _key)) { size_t len = unsafe_yyjson_get_len(obj); yyjson_val *key = unsafe_yyjson_get_first(obj); while (len-- > 0) { - if (key->tag == tag && - duckdb::FastMemcmp(key->uni.ptr, _key, key_len) == 0) { - return key + 1; - } + if (unsafe_yyjson_equals_strn(key, _key, key_len)) return key + 1; key = unsafe_yyjson_get_next(key + 1); } } @@ -4089,13 +5182,6 @@ yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, * JSON Object Iterator API (Implementation) *============================================================================*/ -struct yyjson_obj_iter { - size_t idx; /**< current key index, from 0 */ - size_t max; /**< maximum key index, idx < max */ - yyjson_val *cur; /**< current key */ - yyjson_val *obj; /**< the object being iterated */ -}; - yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj, yyjson_obj_iter *iter) { if (yyjson_likely(yyjson_is_obj(obj) && iter)) { @@ -4109,6 +5195,12 @@ yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj, return false; } +yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj) { + yyjson_obj_iter iter; + yyjson_obj_iter_init(obj, &iter); + return iter; +} + yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter) { return iter ? iter->idx < iter->max : false; } @@ -4145,8 +5237,7 @@ yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter, } while (idx++ < max) { yyjson_val *next = unsafe_yyjson_get_next(cur + 1); - if (unsafe_yyjson_get_len(cur) == key_len && - duckdb::FastMemcmp(cur->uni.str, key, key_len) == 0) { + if (unsafe_yyjson_equals_strn(cur, key, key_len)) { iter->idx = idx; iter->cur = next; return cur + 1; @@ -4183,8 +5274,9 @@ struct yyjson_mut_val { A memory chunk in string memory pool. */ typedef struct yyjson_str_chunk { - struct yyjson_str_chunk *next; - /* flexible array member here */ + struct yyjson_str_chunk *next; /* next chunk linked list */ + size_t chunk_size; /* chunk size in bytes */ + /* char str[]; flexible array member */ } yyjson_str_chunk; /** @@ -4200,10 +5292,13 @@ typedef struct yyjson_str_pool { /** A memory chunk in value memory pool. + `sizeof(yyjson_val_chunk)` should not larger than `sizeof(yyjson_mut_val)`. */ typedef struct yyjson_val_chunk { - struct yyjson_val_chunk *next; - /* flexible array member here */ + struct yyjson_val_chunk *next; /* next chunk linked list */ + size_t chunk_size; /* chunk size in bytes */ + /* char pad[sizeof(yyjson_mut_val) - sizeof(yyjson_val_chunk)]; padding */ + /* yyjson_mut_val vals[]; flexible array member */ } yyjson_val_chunk; /** @@ -4234,21 +5329,26 @@ yyjson_api bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool, const yyjson_alc *alc, size_t count); -yyjson_api_inline char *unsafe_yyjson_mut_strncpy(yyjson_mut_doc *doc, - const char *str, size_t len) { +/* Allocate memory for string. */ +yyjson_api_inline char *unsafe_yyjson_mut_str_alc(yyjson_mut_doc *doc, + size_t len) { char *mem; const yyjson_alc *alc = &doc->alc; yyjson_str_pool *pool = &doc->str_pool; - - if (!str) return NULL; if (yyjson_unlikely((size_t)(pool->end - pool->cur) <= len)) { if (yyjson_unlikely(!unsafe_yyjson_str_pool_grow(pool, alc, len + 1))) { return NULL; } } - mem = pool->cur; pool->cur = mem + len + 1; + return mem; +} + +yyjson_api_inline char *unsafe_yyjson_mut_strncpy(yyjson_mut_doc *doc, + const char *str, size_t len) { + char *mem = unsafe_yyjson_mut_str_alc(doc, len); + if (yyjson_unlikely(!mem)) return NULL; memcpy((void *)mem, (const void *)str, len); mem[len] = '\0'; return mem; @@ -4264,7 +5364,6 @@ yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_val(yyjson_mut_doc *doc, return NULL; } } - val = pool->cur; pool->cur += count; return val; @@ -4393,6 +5492,10 @@ yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val) { return yyjson_get_real((yyjson_val *)val); } +yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val) { + return yyjson_get_num((yyjson_val *)val); +} + yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val) { return yyjson_get_str((yyjson_val *)val); } @@ -4574,6 +5677,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc, if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { + _val = !!_val; val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3); return val; } @@ -4627,7 +5731,18 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc, yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc, const char *str) { - if (yyjson_likely(str)) return yyjson_mut_strn(doc, str, strlen(str)); + if (yyjson_likely(doc && str)) { + size_t len = strlen(str); + bool noesc = unsafe_yyjson_is_str_noesc(str, len); + yyjson_subtype sub = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE; + yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); + if (yyjson_likely(val)) { + val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | + (uint64_t)(YYJSON_TYPE_STR | sub); + val->uni.str = str; + return val; + } + } return NULL; } @@ -4647,7 +5762,19 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc, yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc, const char *str) { - if (yyjson_likely(str)) return yyjson_mut_strncpy(doc, str, strlen(str)); + if (yyjson_likely(doc && str)) { + size_t len = strlen(str); + bool noesc = unsafe_yyjson_is_str_noesc(str, len); + yyjson_subtype sub = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE; + yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); + char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len); + if (yyjson_likely(val && new_str)) { + val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | + (uint64_t)(YYJSON_TYPE_STR | sub); + val->uni.str = new_str; + return val; + } + } return NULL; } @@ -4708,14 +5835,6 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last( * Mutable JSON Array Iterator API (Implementation) *============================================================================*/ -struct yyjson_mut_arr_iter { - size_t idx; /**< current index, from 0 */ - size_t max; /**< maximum index, idx < max */ - yyjson_mut_val *cur; /**< current value */ - yyjson_mut_val *pre; /**< previous value */ - yyjson_mut_val *arr; /**< the array being iterated */ -}; - yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr, yyjson_mut_arr_iter *iter) { if (yyjson_likely(yyjson_mut_is_arr(arr) && iter)) { @@ -4730,6 +5849,13 @@ yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr, return false; } +yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with( + yyjson_mut_val *arr) { + yyjson_mut_arr_iter iter; + yyjson_mut_arr_iter_init(arr, &iter); + return iter; +} + yyjson_api_inline bool yyjson_mut_arr_iter_has_next(yyjson_mut_arr_iter *iter) { return iter ? iter->idx < iter->max : false; } @@ -4804,7 +5930,8 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc) { yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool( yyjson_mut_doc *doc, const bool *vals, size_t count) { yyjson_mut_arr_with_func({ - val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)vals[i] << 3); + bool _val = !!vals[i]; + val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3); }); } @@ -5327,15 +6454,11 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj, yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj, const char *_key, size_t key_len) { - uint64_t tag = (((uint64_t)key_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; size_t len = yyjson_mut_obj_size(obj); if (yyjson_likely(len && _key)) { yyjson_mut_val *key = ((yyjson_mut_val *)obj->uni.ptr)->next->next; while (len-- > 0) { - if (key->tag == tag && - duckdb::FastMemcmp(key->uni.ptr, _key, key_len) == 0) { - return key->next; - } + if (unsafe_yyjson_equals_strn(key, _key, key_len)) return key->next; key = key->next->next; } } @@ -5348,14 +6471,6 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj, * Mutable JSON Object Iterator API (Implementation) *============================================================================*/ -struct yyjson_mut_obj_iter { - size_t idx; /**< current key index, from 0 */ - size_t max; /**< maximum key index, idx < max */ - yyjson_mut_val *cur; /**< current key */ - yyjson_mut_val *pre; /**< previous key */ - yyjson_mut_val *obj; /**< the object being iterated */ -}; - yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj, yyjson_mut_obj_iter *iter) { if (yyjson_likely(yyjson_mut_is_obj(obj) && iter)) { @@ -5370,6 +6485,13 @@ yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj, return false; } +yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with( + yyjson_mut_val *obj) { + yyjson_mut_obj_iter iter; + yyjson_mut_obj_iter_init(obj, &iter); + return iter; +} + yyjson_api_inline bool yyjson_mut_obj_iter_has_next(yyjson_mut_obj_iter *iter) { return iter ? iter->idx < iter->max : false; } @@ -5402,8 +6524,8 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove( iter->max--; unsafe_yyjson_set_len(iter->obj, iter->max); prev->next->next = next; - iter->cur = next; - return cur; + iter->cur = prev; + return cur->next; } return NULL; } @@ -5422,8 +6544,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn( while (idx++ < max) { pre = cur; cur = cur->next->next; - if (unsafe_yyjson_get_len(cur) == key_len && - duckdb::FastMemcmp(cur->uni.str, key, key_len) == 0) { + if (unsafe_yyjson_equals_strn(cur, key, key_len)) { iter->idx += idx; if (iter->idx > max) iter->idx -= max + 1; iter->pre = pre; @@ -5539,7 +6660,7 @@ yyjson_api_inline void unsafe_yyjson_mut_obj_add(yyjson_mut_val *obj, } yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_obj_remove( - yyjson_mut_val *obj, const char *key, size_t key_len, uint64_t key_tag) { + yyjson_mut_val *obj, const char *key, size_t key_len) { size_t obj_len = unsafe_yyjson_get_len(obj); if (obj_len) { yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr; @@ -5547,8 +6668,7 @@ yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_obj_remove( yyjson_mut_val *removed_item = NULL; size_t i; for (i = 0; i < obj_len; i++) { - if (key_tag == cur_key->tag && - duckdb::FastMemcmp(key, cur_key->uni.ptr, key_len) == 0) { + if (unsafe_yyjson_equals_strn(cur_key, key, key_len)) { if (!removed_item) removed_item = cur_key->next; cur_key = cur_key->next->next; pre_key->next->next = cur_key; @@ -5577,8 +6697,7 @@ yyjson_api_inline bool unsafe_yyjson_mut_obj_replace(yyjson_mut_val *obj, yyjson_mut_val *cur_key = pre_key->next->next; size_t i; for (i = 0; i < obj_len; i++) { - if (key->tag == cur_key->tag && - duckdb::FastMemcmp(key->uni.str, cur_key->uni.ptr, key_len) == 0) { + if (unsafe_yyjson_equals_strn(cur_key, key->uni.str, key_len)) { cur_key->next->tag = val->tag; cur_key->next->uni.u64 = val->uni.u64; return true; @@ -5611,17 +6730,27 @@ yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj, yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val) { - if (yyjson_likely(yyjson_mut_is_obj(obj) && - yyjson_mut_is_str(key))) { - unsafe_yyjson_mut_obj_remove(obj, key->uni.str, - unsafe_yyjson_get_len(key), key->tag); - if (yyjson_likely(val)) { - unsafe_yyjson_mut_obj_add(obj, key, val, - unsafe_yyjson_get_len(obj)); + bool replaced = false; + size_t key_len; + yyjson_mut_obj_iter iter; + yyjson_mut_val *cur_key; + if (yyjson_unlikely(!yyjson_mut_is_obj(obj) || + !yyjson_mut_is_str(key))) return false; + key_len = unsafe_yyjson_get_len(key); + yyjson_mut_obj_iter_init(obj, &iter); + while ((cur_key = yyjson_mut_obj_iter_next(&iter)) != 0) { + if (unsafe_yyjson_equals_strn(cur_key, key->uni.str, key_len)) { + if (!replaced && val) { + replaced = true; + val->next = cur_key->next->next; + cur_key->next = val; + } else { + yyjson_mut_obj_iter_remove(&iter); + } } - return true; } - return false; + if (!replaced && val) unsafe_yyjson_mut_obj_add(obj, key, val, iter.max); + return true; } yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj, @@ -5650,8 +6779,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj, yyjson_mut_val *key) { if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key))) { return unsafe_yyjson_mut_obj_remove(obj, key->uni.str, - unsafe_yyjson_get_len(key), - key->tag); + unsafe_yyjson_get_len(key)); } return NULL; } @@ -5660,8 +6788,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key( yyjson_mut_val *obj, const char *key) { if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) { size_t key_len = strlen(key); - uint64_t tag = ((uint64_t)key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; - return unsafe_yyjson_mut_obj_remove(obj, key, key_len, tag); + return unsafe_yyjson_mut_obj_remove(obj, key, key_len); } return NULL; } @@ -5669,8 +6796,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key( yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn( yyjson_mut_val *obj, const char *key, size_t key_len) { if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) { - uint64_t tag = ((uint64_t)key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; - return unsafe_yyjson_mut_obj_remove(obj, key, key_len, tag); + return unsafe_yyjson_mut_obj_remove(obj, key, key_len); } return NULL; } @@ -5715,7 +6841,10 @@ yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj, if (yyjson_likely(key)) { \ size_t len = unsafe_yyjson_get_len(obj); \ yyjson_mut_val *val = key + 1; \ - key->tag = YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE; \ + size_t key_len = strlen(_key); \ + bool noesc = unsafe_yyjson_is_str_noesc(_key, key_len); \ + key->tag = YYJSON_TYPE_STR; \ + key->tag |= noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE; \ key->tag |= (uint64_t)strlen(_key) << YYJSON_TAG_BIT; \ key->uni.str = _key; \ func \ @@ -5754,6 +6883,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc, const char *_key, bool _val) { yyjson_mut_obj_add_func({ + _val = !!_val; val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)(_val) << 3); }); } @@ -5804,7 +6934,10 @@ yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc, const char *_val) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ + size_t val_len = strlen(_val); + bool val_noesc = unsafe_yyjson_is_str_noesc(_val, val_len); val->tag = ((uint64_t)strlen(_val) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; + val->tag |= val_noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE; val->uni.str = _val; }); } @@ -5847,6 +6980,22 @@ yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc, }); } +yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *_key) { + yyjson_mut_val *key = yyjson_mut_str(doc, _key); + yyjson_mut_val *val = yyjson_mut_arr(doc); + return yyjson_mut_obj_add(obj, key, val) ? val : NULL; +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *_key) { + yyjson_mut_val *key = yyjson_mut_str(doc, _key); + yyjson_mut_val *val = yyjson_mut_obj(doc); + return yyjson_mut_obj_add(obj, key, val) ? val : NULL; +} + yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, @@ -5870,8 +7019,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn( yyjson_mut_val *val_removed = NULL; yyjson_mut_obj_iter_init(obj, &iter); while ((key = yyjson_mut_obj_iter_next(&iter)) != NULL) { - if (unsafe_yyjson_get_len(key) == _len && - duckdb::FastMemcmp(key->uni.str, _key, _len) == 0) { + if (unsafe_yyjson_equals_strn(key, _key, _len)) { if (!val_removed) val_removed = key->next; yyjson_mut_obj_iter_remove(&iter); } @@ -5919,65 +7067,842 @@ yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc, * JSON Pointer API (Implementation) *============================================================================*/ -/* `val` not null, `ptr` start with '/', `len` > 0. */ -yyjson_api yyjson_val *unsafe_yyjson_get_pointer(yyjson_val *val, - const char *ptr, - size_t len); +#define yyjson_ptr_set_err(_code, _msg) do { \ + if (err) { \ + err->code = YYJSON_PTR_ERR_##_code; \ + err->msg = _msg; \ + err->pos = 0; \ + } \ +} while(false) + +/* require: val != NULL, *ptr == '/', len > 0 */ +yyjson_api yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val, + const char *ptr, size_t len, + yyjson_ptr_err *err); -/* `val` not null, `ptr` start with '/', `len` > 0. */ -yyjson_api yyjson_mut_val *unsafe_yyjson_mut_get_pointer(yyjson_mut_val *val, +/* require: val != NULL, *ptr == '/', len > 0 */ +yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_getx(yyjson_mut_val *val, + const char *ptr, + size_t len, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err); + +/* require: val/new_val/doc != NULL, *ptr == '/', len > 0 */ +yyjson_api bool unsafe_yyjson_mut_ptr_putx(yyjson_mut_val *val, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc, + bool create_parent, bool insert_new, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err); + +/* require: val/err != NULL, *ptr == '/', len > 0 */ +yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex( + yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, + yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); + +/* require: val/err != NULL, *ptr == '/', len > 0 */ +yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_removex(yyjson_mut_val *val, const char *ptr, - size_t len); + size_t len, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err); -yyjson_api_inline yyjson_val *yyjson_get_pointern(yyjson_val *val, - const char *ptr, - size_t len) { - if (!val || !ptr) return NULL; - if (len == 0) return val; - if (*ptr != '/') return NULL; - return unsafe_yyjson_get_pointer(val, ptr, len); +yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc, + const char *ptr) { + if (yyjson_unlikely(!ptr)) return NULL; + return yyjson_doc_ptr_getn(doc, ptr, strlen(ptr)); } -yyjson_api_inline yyjson_val *yyjson_get_pointer(yyjson_val *val, - const char *ptr) { - if (!val || !ptr) return NULL; - return yyjson_get_pointern(val, ptr, strlen(ptr)); +yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc, + const char *ptr, size_t len) { + return yyjson_doc_ptr_getx(doc, ptr, len, NULL); } -yyjson_api_inline yyjson_val *yyjson_doc_get_pointern(yyjson_doc *doc, +yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc, + const char *ptr, size_t len, + yyjson_ptr_err *err) { + yyjson_ptr_set_err(NONE, NULL); + if (yyjson_unlikely(!doc || !ptr)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return NULL; + } + if (yyjson_unlikely(!doc->root)) { + yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); + return NULL; + } + if (yyjson_unlikely(len == 0)) { + return doc->root; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return NULL; + } + return unsafe_yyjson_ptr_getx(doc->root, ptr, len, err); +} + +yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val, + const char *ptr) { + if (yyjson_unlikely(!ptr)) return NULL; + return yyjson_ptr_getn(val, ptr, strlen(ptr)); +} + +yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val, + const char *ptr, size_t len) { + return yyjson_ptr_getx(val, ptr, len, NULL); +} + +yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val, + const char *ptr, size_t len, + yyjson_ptr_err *err) { + yyjson_ptr_set_err(NONE, NULL); + if (yyjson_unlikely(!val || !ptr)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return NULL; + } + if (yyjson_unlikely(len == 0)) { + return val; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return NULL; + } + return unsafe_yyjson_ptr_getx(val, ptr, len, err); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc, + const char *ptr) { + if (!ptr) return NULL; + return yyjson_mut_doc_ptr_getn(doc, ptr, strlen(ptr)); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc, + const char *ptr, + size_t len) { + return yyjson_mut_doc_ptr_getx(doc, ptr, len, NULL, NULL); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc, + const char *ptr, + size_t len, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err) { + yyjson_ptr_set_err(NONE, NULL); + if (ctx) memset(ctx, 0, sizeof(*ctx)); + + if (yyjson_unlikely(!doc || !ptr)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return NULL; + } + if (yyjson_unlikely(!doc->root)) { + yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); + return NULL; + } + if (yyjson_unlikely(len == 0)) { + return doc->root; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return NULL; + } + return unsafe_yyjson_mut_ptr_getx(doc->root, ptr, len, ctx, err); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val, + const char *ptr) { + if (!ptr) return NULL; + return yyjson_mut_ptr_getn(val, ptr, strlen(ptr)); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val, const char *ptr, size_t len) { - return yyjson_get_pointern(doc ? doc->root : NULL, ptr, len); + return yyjson_mut_ptr_getx(val, ptr, len, NULL, NULL); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val, + const char *ptr, + size_t len, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err) { + yyjson_ptr_set_err(NONE, NULL); + if (ctx) memset(ctx, 0, sizeof(*ctx)); + + if (yyjson_unlikely(!val || !ptr)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return NULL; + } + if (yyjson_unlikely(len == 0)) { + return val; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return NULL; + } + return unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); +} + +yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc, + const char *ptr, + yyjson_mut_val *new_val) { + if (yyjson_unlikely(!ptr)) return false; + return yyjson_mut_doc_ptr_addn(doc, ptr, strlen(ptr), new_val); +} + +yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc, + const char *ptr, + size_t len, + yyjson_mut_val *new_val) { + return yyjson_mut_doc_ptr_addx(doc, ptr, len, new_val, true, NULL, NULL); +} + +yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + bool create_parent, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err) { + yyjson_ptr_set_err(NONE, NULL); + if (ctx) memset(ctx, 0, sizeof(*ctx)); + + if (yyjson_unlikely(!doc || !ptr || !new_val)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return false; + } + if (yyjson_unlikely(len == 0)) { + if (doc->root) { + yyjson_ptr_set_err(SET_ROOT, "cannot set document's root"); + return false; + } else { + doc->root = new_val; + return true; + } + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return false; + } + if (yyjson_unlikely(!doc->root && !create_parent)) { + yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); + return false; + } + if (yyjson_unlikely(!doc->root)) { + yyjson_mut_val *root = yyjson_mut_obj(doc); + if (yyjson_unlikely(!root)) { + yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value"); + return false; + } + if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc, + create_parent, true, ctx, err)) { + doc->root = root; + return true; + } + return false; + } + return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc, + create_parent, true, ctx, err); +} + +yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val, + const char *ptr, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc) { + if (yyjson_unlikely(!ptr)) return false; + return yyjson_mut_ptr_addn(val, ptr, strlen(ptr), new_val, doc); +} + +yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc) { + return yyjson_mut_ptr_addx(val, ptr, len, new_val, doc, true, NULL, NULL); +} + +yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc, + bool create_parent, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err) { + yyjson_ptr_set_err(NONE, NULL); + if (ctx) memset(ctx, 0, sizeof(*ctx)); + + if (yyjson_unlikely(!val || !ptr || !new_val || !doc)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return false; + } + if (yyjson_unlikely(len == 0)) { + yyjson_ptr_set_err(SET_ROOT, "cannot set root"); + return false; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return false; + } + return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val, + doc, create_parent, true, ctx, err); +} + +yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc, + const char *ptr, + yyjson_mut_val *new_val) { + if (yyjson_unlikely(!ptr)) return false; + return yyjson_mut_doc_ptr_setn(doc, ptr, strlen(ptr), new_val); +} + +yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc, + const char *ptr, size_t len, + yyjson_mut_val *new_val) { + return yyjson_mut_doc_ptr_setx(doc, ptr, len, new_val, true, NULL, NULL); +} + +yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + bool create_parent, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err) { + yyjson_ptr_set_err(NONE, NULL); + if (ctx) memset(ctx, 0, sizeof(*ctx)); + + if (yyjson_unlikely(!doc || !ptr)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return false; + } + if (yyjson_unlikely(len == 0)) { + if (ctx) ctx->old = doc->root; + doc->root = new_val; + return true; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return false; + } + if (!new_val) { + if (!doc->root) { + yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved"); + return false; + } + return !!unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err); + } + if (yyjson_unlikely(!doc->root && !create_parent)) { + yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); + return false; + } + if (yyjson_unlikely(!doc->root)) { + yyjson_mut_val *root = yyjson_mut_obj(doc); + if (yyjson_unlikely(!root)) { + yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value"); + return false; + } + if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc, + create_parent, false, ctx, err)) { + doc->root = root; + return true; + } + return false; + } + return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc, + create_parent, false, ctx, err); +} + +yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val, + const char *ptr, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc) { + if (yyjson_unlikely(!ptr)) return false; + return yyjson_mut_ptr_setn(val, ptr, strlen(ptr), new_val, doc); +} + +yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc) { + return yyjson_mut_ptr_setx(val, ptr, len, new_val, doc, true, NULL, NULL); +} + +yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val, + const char *ptr, size_t len, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc, + bool create_parent, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err) { + yyjson_ptr_set_err(NONE, NULL); + if (ctx) memset(ctx, 0, sizeof(*ctx)); + + if (yyjson_unlikely(!val || !ptr || !doc)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return false; + } + if (yyjson_unlikely(len == 0)) { + yyjson_ptr_set_err(SET_ROOT, "cannot set root"); + return false; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return false; + } + if (!new_val) { + return !!unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err); + } + return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val, doc, + create_parent, false, ctx, err); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace( + yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val) { + if (!ptr) return NULL; + return yyjson_mut_doc_ptr_replacen(doc, ptr, strlen(ptr), new_val); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen( + yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val) { + return yyjson_mut_doc_ptr_replacex(doc, ptr, len, new_val, NULL, NULL); } +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex( + yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, + yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { + + yyjson_ptr_set_err(NONE, NULL); + if (ctx) memset(ctx, 0, sizeof(*ctx)); + + if (yyjson_unlikely(!doc || !ptr || !new_val)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return NULL; + } + if (yyjson_unlikely(len == 0)) { + yyjson_mut_val *root = doc->root; + if (yyjson_unlikely(!root)) { + yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved"); + return NULL; + } + if (ctx) ctx->old = root; + doc->root = new_val; + return root; + } + if (yyjson_unlikely(!doc->root)) { + yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); + return NULL; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return NULL; + } + return unsafe_yyjson_mut_ptr_replacex(doc->root, ptr, len, new_val, + ctx, err); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace( + yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val) { + if (!ptr) return NULL; + return yyjson_mut_ptr_replacen(val, ptr, strlen(ptr), new_val); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen( + yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val) { + return yyjson_mut_ptr_replacex(val, ptr, len, new_val, NULL, NULL); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex( + yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, + yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { + + yyjson_ptr_set_err(NONE, NULL); + if (ctx) memset(ctx, 0, sizeof(*ctx)); + + if (yyjson_unlikely(!val || !ptr || !new_val)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return NULL; + } + if (yyjson_unlikely(len == 0)) { + yyjson_ptr_set_err(SET_ROOT, "cannot set root"); + return NULL; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return NULL; + } + return unsafe_yyjson_mut_ptr_replacex(val, ptr, len, new_val, ctx, err); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove( + yyjson_mut_doc *doc, const char *ptr) { + if (!ptr) return NULL; + return yyjson_mut_doc_ptr_removen(doc, ptr, strlen(ptr)); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen( + yyjson_mut_doc *doc, const char *ptr, size_t len) { + return yyjson_mut_doc_ptr_removex(doc, ptr, len, NULL, NULL); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex( + yyjson_mut_doc *doc, const char *ptr, size_t len, + yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { + + yyjson_ptr_set_err(NONE, NULL); + if (ctx) memset(ctx, 0, sizeof(*ctx)); + + if (yyjson_unlikely(!doc || !ptr)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return NULL; + } + if (yyjson_unlikely(!doc->root)) { + yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); + return NULL; + } + if (yyjson_unlikely(len == 0)) { + yyjson_mut_val *root = doc->root; + if (ctx) ctx->old = root; + doc->root = NULL; + return root; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return NULL; + } + return unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val, + const char *ptr) { + if (!ptr) return NULL; + return yyjson_mut_ptr_removen(val, ptr, strlen(ptr)); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val, + const char *ptr, + size_t len) { + return yyjson_mut_ptr_removex(val, ptr, len, NULL, NULL); +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val, + const char *ptr, + size_t len, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err) { + yyjson_ptr_set_err(NONE, NULL); + if (ctx) memset(ctx, 0, sizeof(*ctx)); + + if (yyjson_unlikely(!val || !ptr)) { + yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); + return NULL; + } + if (yyjson_unlikely(len == 0)) { + yyjson_ptr_set_err(SET_ROOT, "cannot set root"); + return NULL; + } + if (yyjson_unlikely(*ptr != '/')) { + yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); + return NULL; + } + return unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err); +} + +yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx, + yyjson_mut_val *key, + yyjson_mut_val *val) { + yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val; + if (!ctx || !ctx->ctn || !val) return false; + ctn = ctx->ctn; + + if (yyjson_mut_is_obj(ctn)) { + if (!key) return false; + key->next = val; + pre_key = ctx->pre; + if (unsafe_yyjson_get_len(ctn) == 0) { + val->next = key; + ctn->uni.ptr = key; + ctx->pre = key; + } else if (!pre_key) { + pre_key = (yyjson_mut_val *)ctn->uni.ptr; + pre_val = pre_key->next; + val->next = pre_val->next; + pre_val->next = key; + ctn->uni.ptr = key; + ctx->pre = pre_key; + } else { + cur_key = pre_key->next->next; + cur_val = cur_key->next; + val->next = cur_val->next; + cur_val->next = key; + if (ctn->uni.ptr == cur_key) ctn->uni.ptr = key; + ctx->pre = cur_key; + } + } else { + pre_val = ctx->pre; + if (unsafe_yyjson_get_len(ctn) == 0) { + val->next = val; + ctn->uni.ptr = val; + ctx->pre = val; + } else if (!pre_val) { + pre_val = (yyjson_mut_val *)ctn->uni.ptr; + val->next = pre_val->next; + pre_val->next = val; + ctn->uni.ptr = val; + ctx->pre = pre_val; + } else { + cur_val = pre_val->next; + val->next = cur_val->next; + cur_val->next = val; + if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val; + ctx->pre = cur_val; + } + } + unsafe_yyjson_inc_len(ctn); + return true; +} + +yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx, + yyjson_mut_val *val) { + yyjson_mut_val *ctn, *pre_key, *cur_key, *pre_val, *cur_val; + if (!ctx || !ctx->ctn || !ctx->pre || !val) return false; + ctn = ctx->ctn; + if (yyjson_mut_is_obj(ctn)) { + pre_key = ctx->pre; + pre_val = pre_key->next; + cur_key = pre_val->next; + cur_val = cur_key->next; + /* replace current value */ + cur_key->next = val; + val->next = cur_val->next; + ctx->old = cur_val; + } else { + pre_val = ctx->pre; + cur_val = pre_val->next; + /* replace current value */ + if (pre_val != cur_val) { + val->next = cur_val->next; + pre_val->next = val; + if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val; + } else { + val->next = val; + ctn->uni.ptr = val; + ctx->pre = val; + } + ctx->old = cur_val; + } + return true; +} + +yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx) { + yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val; + size_t len; + if (!ctx || !ctx->ctn || !ctx->pre) return false; + ctn = ctx->ctn; + if (yyjson_mut_is_obj(ctn)) { + pre_key = ctx->pre; + pre_val = pre_key->next; + cur_key = pre_val->next; + cur_val = cur_key->next; + /* remove current key-value */ + pre_val->next = cur_val->next; + if (ctn->uni.ptr == cur_key) ctn->uni.ptr = pre_key; + ctx->pre = NULL; + ctx->old = cur_val; + } else { + pre_val = ctx->pre; + cur_val = pre_val->next; + /* remove current key-value */ + pre_val->next = cur_val->next; + if (ctn->uni.ptr == cur_val) ctn->uni.ptr = pre_val; + ctx->pre = NULL; + ctx->old = cur_val; + } + len = unsafe_yyjson_get_len(ctn) - 1; + if (len == 0) ctn->uni.ptr = NULL; + unsafe_yyjson_set_len(ctn, len); + return true; +} + +#undef yyjson_ptr_set_err + + + +/*============================================================================== + * JSON Value at Pointer API (Implementation) + *============================================================================*/ + +/** + Set provided `value` if the JSON Pointer (RFC 6901) exists and is type bool. + Returns true if value at `ptr` exists and is the correct type, otherwise false. + */ +yyjson_api_inline bool yyjson_ptr_get_bool( + yyjson_val *root, const char *ptr, bool *value) { + yyjson_val *val = yyjson_ptr_get(root, ptr); + if (value && yyjson_is_bool(val)) { + *value = unsafe_yyjson_get_bool(val); + return true; + } else { + return false; + } +} + +/** + Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer + that fits in `uint64_t`. Returns true if successful, otherwise false. + */ +yyjson_api_inline bool yyjson_ptr_get_uint( + yyjson_val *root, const char *ptr, uint64_t *value) { + yyjson_val *val = yyjson_ptr_get(root, ptr); + if (value && val) { + uint64_t ret = val->uni.u64; + if (unsafe_yyjson_is_uint(val) || + (unsafe_yyjson_is_sint(val) && !(ret >> 63))) { + *value = ret; + return true; + } + } + return false; +} + +/** + Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer + that fits in `int64_t`. Returns true if successful, otherwise false. + */ +yyjson_api_inline bool yyjson_ptr_get_sint( + yyjson_val *root, const char *ptr, int64_t *value) { + yyjson_val *val = yyjson_ptr_get(root, ptr); + if (value && val) { + int64_t ret = val->uni.i64; + if (unsafe_yyjson_is_sint(val) || + (unsafe_yyjson_is_uint(val) && ret >= 0)) { + *value = ret; + return true; + } + } + return false; +} + +/** + Set provided `value` if the JSON Pointer (RFC 6901) exists and is type real. + Returns true if value at `ptr` exists and is the correct type, otherwise false. + */ +yyjson_api_inline bool yyjson_ptr_get_real( + yyjson_val *root, const char *ptr, double *value) { + yyjson_val *val = yyjson_ptr_get(root, ptr); + if (value && yyjson_is_real(val)) { + *value = unsafe_yyjson_get_real(val); + return true; + } else { + return false; + } +} + +/** + Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint, + uint or real. + Returns true if value at `ptr` exists and is the correct type, otherwise false. + */ +yyjson_api_inline bool yyjson_ptr_get_num( + yyjson_val *root, const char *ptr, double *value) { + yyjson_val *val = yyjson_ptr_get(root, ptr); + if (value && yyjson_is_num(val)) { + *value = unsafe_yyjson_get_num(val); + return true; + } else { + return false; + } +} + +/** + Set provided `value` if the JSON Pointer (RFC 6901) exists and is type string. + Returns true if value at `ptr` exists and is the correct type, otherwise false. + */ +yyjson_api_inline bool yyjson_ptr_get_str( + yyjson_val *root, const char *ptr, const char **value) { + yyjson_val *val = yyjson_ptr_get(root, ptr); + if (value && yyjson_is_str(val)) { + *value = unsafe_yyjson_get_str(val); + return true; + } else { + return false; + } +} + + + +/*============================================================================== + * Deprecated + *============================================================================*/ + +/** @deprecated renamed to `yyjson_doc_ptr_get` */ +yyjson_deprecated("renamed to yyjson_doc_ptr_get") yyjson_api_inline yyjson_val *yyjson_doc_get_pointer(yyjson_doc *doc, const char *ptr) { - return yyjson_get_pointer(doc ? doc->root : NULL, ptr); + return yyjson_doc_ptr_get(doc, ptr); } -yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointern(yyjson_mut_val *val, - const char *ptr, - size_t len) { - if (!val || !ptr) return NULL; - if (len == 0) return val; - if (*ptr != '/') return NULL; - return unsafe_yyjson_mut_get_pointer(val, ptr, len); +/** @deprecated renamed to `yyjson_doc_ptr_getn` */ +yyjson_deprecated("renamed to yyjson_doc_ptr_getn") +yyjson_api_inline yyjson_val *yyjson_doc_get_pointern(yyjson_doc *doc, + const char *ptr, + size_t len) { + return yyjson_doc_ptr_getn(doc, ptr, len); } -yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointer(yyjson_mut_val *val, - const char *ptr) { - if (!val || !ptr) return NULL; - return yyjson_mut_get_pointern(val, ptr, strlen(ptr)); +/** @deprecated renamed to `yyjson_mut_doc_ptr_get` */ +yyjson_deprecated("renamed to yyjson_mut_doc_ptr_get") +yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointer( + yyjson_mut_doc *doc, const char *ptr) { + return yyjson_mut_doc_ptr_get(doc, ptr); } +/** @deprecated renamed to `yyjson_mut_doc_ptr_getn` */ +yyjson_deprecated("renamed to yyjson_mut_doc_ptr_getn") yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointern( yyjson_mut_doc *doc, const char *ptr, size_t len) { - return yyjson_mut_get_pointern(doc ? doc->root : NULL, ptr, len); + return yyjson_mut_doc_ptr_getn(doc, ptr, len); } -yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointer( - yyjson_mut_doc *doc, const char *ptr) { - return yyjson_mut_get_pointer(doc ? doc->root : NULL, ptr); +/** @deprecated renamed to `yyjson_ptr_get` */ +yyjson_deprecated("renamed to yyjson_ptr_get") +yyjson_api_inline yyjson_val *yyjson_get_pointer(yyjson_val *val, + const char *ptr) { + return yyjson_ptr_get(val, ptr); +} + +/** @deprecated renamed to `yyjson_ptr_getn` */ +yyjson_deprecated("renamed to yyjson_ptr_getn") +yyjson_api_inline yyjson_val *yyjson_get_pointern(yyjson_val *val, + const char *ptr, + size_t len) { + return yyjson_ptr_getn(val, ptr, len); +} + +/** @deprecated renamed to `yyjson_mut_ptr_get` */ +yyjson_deprecated("renamed to yyjson_mut_ptr_get") +yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointer(yyjson_mut_val *val, + const char *ptr) { + return yyjson_mut_ptr_get(val, ptr); +} + +/** @deprecated renamed to `yyjson_mut_ptr_getn` */ +yyjson_deprecated("renamed to yyjson_mut_ptr_getn") +yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointern(yyjson_mut_val *val, + const char *ptr, + size_t len) { + return yyjson_mut_ptr_getn(val, ptr, len); +} + +/** @deprecated renamed to `yyjson_mut_ptr_getn` */ +yyjson_deprecated("renamed to unsafe_yyjson_ptr_getn") +yyjson_api_inline yyjson_val *unsafe_yyjson_get_pointer(yyjson_val *val, + const char *ptr, + size_t len) { + yyjson_ptr_err err; + return unsafe_yyjson_ptr_getx(val, ptr, len, &err); +} + +/** @deprecated renamed to `unsafe_yyjson_mut_ptr_getx` */ +yyjson_deprecated("renamed to unsafe_yyjson_mut_ptr_getx") +yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_get_pointer( + yyjson_mut_val *val, const char *ptr, size_t len) { + yyjson_ptr_err err; + return unsafe_yyjson_mut_ptr_getx(val, ptr, len, NULL, &err); } @@ -5997,7 +7922,9 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointer( #endif /* warning suppress end */ #ifdef __cplusplus -} +// } #endif /* extern "C" end */ -#endif /* YYJSON_H */ +} // namespace duckdb_yyjson + +#endif /* DUCKDB_YYJSON_H */ diff --git a/extension/json/yyjson/yyjson.cpp b/third_party/yyjson/yyjson.cpp similarity index 77% rename from extension/json/yyjson/yyjson.cpp rename to third_party/yyjson/yyjson.cpp index 75234ed9ebc..d8df196fdec 100644 --- a/extension/json/yyjson/yyjson.cpp +++ b/third_party/yyjson/yyjson.cpp @@ -1,19 +1,32 @@ /*============================================================================== - * Created by Yaoyuan on 2019/3/9. - * Copyright (C) 2019 Yaoyuan . - * - * Released under the MIT License: - * https://github.com/ibireme/yyjson/blob/master/LICENSE + Copyright (c) 2020 YaoYuan + + 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. *============================================================================*/ #include "yyjson.hpp" -#include #include - +namespace duckdb_yyjson { /*============================================================================== - * Compile Hint Begin + * Warning Suppress *============================================================================*/ /* warning suppress begin */ @@ -23,6 +36,7 @@ # pragma clang diagnostic ignored "-Wunused-parameter" # pragma clang diagnostic ignored "-Wunused-label" # pragma clang diagnostic ignored "-Wunused-macros" +# pragma clang diagnostic ignored "-Wunused-variable" #elif defined(__GNUC__) # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # pragma GCC diagnostic push @@ -34,6 +48,7 @@ #elif defined(_MSC_VER) # pragma warning(push) # pragma warning(disable:4100) /* unreferenced formal parameter */ +# pragma warning(disable:4101) /* unreferenced variable */ # pragma warning(disable:4102) /* unreferenced label */ # pragma warning(disable:4127) /* conditional expression is constant */ # pragma warning(disable:4706) /* assignment within conditional expression */ @@ -45,7 +60,7 @@ * Version *============================================================================*/ -yyjson_api uint32_t yyjson_version(void) { +uint32_t yyjson_version(void) { return YYJSON_VERSION_HEX; } @@ -55,32 +70,6 @@ yyjson_api uint32_t yyjson_version(void) { * Flags *============================================================================*/ -/* gcc version check */ -#if defined(__GNUC__) -# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -# define yyjson_gcc_available(major, minor, patch) \ - ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \ - >= (major * 10000 + minor * 100 + patch)) -# elif defined(__GNUC_MINOR__) -# define yyjson_gcc_available(major, minor, patch) \ - ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) \ - >= (major * 10000 + minor * 100 + patch)) -# else -# define yyjson_gcc_available(major, minor, patch) \ - ((__GNUC__ * 10000) >= (major * 10000 + minor * 100 + patch)) -# endif -#else -# define yyjson_gcc_available(major, minor, patch) 0 -#endif - -/* real gcc check */ -#if !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__ICC) && \ - defined(__GNUC__) && defined(__GNUC_MINOR__) -# define YYJSON_IS_REAL_GCC 1 -#else -# define YYJSON_IS_REAL_GCC 0 -#endif - /* msvc intrinsic */ #if YYJSON_MSC_VER >= 1400 # include @@ -145,35 +134,35 @@ yyjson_api uint32_t yyjson_version(void) { /* Correct rounding in double number computations. - + On the x86 architecture, some compilers may use x87 FPU instructions for floating-point arithmetic. The x87 FPU loads all floating point number as 80-bit double-extended precision internally, then rounds the result to original precision, which may produce inaccurate results. For a more detailed explanation, see the paper: https://arxiv.org/abs/cs/0701192 - + Here are some examples of double precision calculation error: - + 2877.0 / 1e6 == 0.002877, but x87 returns 0.0028770000000000002 43683.0 * 1e21 == 4.3683e25, but x87 returns 4.3683000000000004e25 - + Here are some examples of compiler flags to generate x87 instructions on x86: - + clang -m32 -mno-sse gcc/icc -m32 -mfpmath=387 msvc /arch:SSE or /arch:IA32 - + If we are sure that there's no similar error described above, we can define the YYJSON_DOUBLE_MATH_CORRECT as 1 to enable the fast path calculation. This is not an accurate detection, it's just try to avoid the error at compile-time. An accurate detection can be done at run-time: - + bool is_double_math_correct(void) { volatile double r = 43683.0; r *= 1e21; return r == 4.3683e25; } - + See also: utils.h in https://github.com/google/double-conversion/ */ #if !defined(FLT_EVAL_METHOD) && defined(__FLT_EVAL_METHOD__) @@ -197,52 +186,41 @@ yyjson_api uint32_t yyjson_version(void) { # define YYJSON_DOUBLE_MATH_CORRECT 1 #endif -/* - Microsoft Visual C++ 6.0 doesn't support converting number from u64 to f64: - error C2520: conversion from unsigned __int64 to double not implemented. - */ -#ifndef YYJSON_U64_TO_F64_NO_IMPL -# if (0 < YYJSON_MSC_VER) && (YYJSON_MSC_VER <= 1200) -# define YYJSON_U64_TO_F64_NO_IMPL 1 -# else -# define YYJSON_U64_TO_F64_NO_IMPL 0 -# endif -#endif - /* endian */ #if yyjson_has_include() -# include +# include /* POSIX */ #endif - #if yyjson_has_include() -# include -#elif yyjson_has_include() -# include +# include /* Linux */ #elif yyjson_has_include() -# include +# include /* BSD, Android */ +#elif yyjson_has_include() +# include /* BSD, Darwin */ #endif #define YYJSON_BIG_ENDIAN 4321 #define YYJSON_LITTLE_ENDIAN 1234 -#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ -# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#if defined(BYTE_ORDER) && BYTE_ORDER +# if defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN) # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN -# elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# elif defined(LITTLE_ENDIAN) && (BYTE_ORDER == LITTLE_ENDIAN) # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN # endif #elif defined(__BYTE_ORDER) && __BYTE_ORDER -# if __BYTE_ORDER == __BIG_ENDIAN +# if defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN -# elif __BYTE_ORDER == __LITTLE_ENDIAN +# elif defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN # endif -#elif defined(BYTE_ORDER) && BYTE_ORDER -# if BYTE_ORDER == BIG_ENDIAN +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ +# if defined(__ORDER_BIG_ENDIAN__) && \ + (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN -# elif BYTE_ORDER == LITTLE_ENDIAN +# elif defined(__ORDER_LITTLE_ENDIAN__) && \ + (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN # endif @@ -253,21 +231,16 @@ yyjson_api uint32_t yyjson_version(void) { defined(__x86_64) || defined(__x86_64__) || \ defined(__amd64) || defined(__amd64__) || \ defined(_M_AMD64) || defined(_M_X64) || \ - defined(__ia64) || defined(_IA64) || defined(__IA64__) || \ - defined(__ia64__) || defined(_M_IA64) || defined(__itanium__) || \ + defined(_M_ARM) || defined(_M_ARM64) || \ defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ - defined(__alpha) || defined(__alpha__) || defined(_M_ALPHA) || \ - defined(__riscv) || defined(__riscv__) || \ defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \ - defined(__EMSCRIPTEN__) || defined(__wasm__) + defined(__EMSCRIPTEN__) || defined(__wasm__) || \ + defined(__loongarch__) # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN #elif (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \ defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \ - defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ - defined(__ppc) || defined(__ppc__) || \ - defined(__sparc) || defined(__sparc__) || defined(__sparc64__) || \ defined(__or1k__) || defined(__OR1K__) # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN @@ -276,75 +249,54 @@ yyjson_api uint32_t yyjson_version(void) { #endif /* - Unaligned memory access detection. - - Some architectures cannot perform unaligned memory access, or unaligned memory - accesses can have a large performance penalty. Modern compilers can make some - optimizations for unaligned access. For example: https://godbolt.org/z/Ejo3Pa - - typedef struct { char c[2] } vec2; - void copy_vec2(vec2 *dst, vec2 *src) { - *dst = *src; - } - - Compiler may generate `load/store` or `move` instruction if target architecture - supports unaligned access, otherwise it may generate `call memcpy` instruction. - - We want to avoid `memcpy` calls, so we should disable unaligned access by - define `YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS` as 1 on these architectures. + This macro controls how yyjson handles unaligned memory accesses. + + By default, yyjson uses `memcpy()` for memory copying. This takes advantage of + the compiler's automatic optimizations to generate unaligned memory access + instructions when the target architecture supports it. + + However, for some older compilers or architectures where `memcpy()` isn't + optimized well and may generate unnecessary function calls, consider defining + this macro as 1. In such cases, yyjson switches to manual byte-by-byte access, + potentially improving performance. An example of the generated assembly code on + the ARM platform can be found here: https://godbolt.org/z/334jjhxPT + + As this flag has already been enabled for some common architectures in the + following code, users typically don't need to manually specify it. If users are + unsure about it, please review the generated assembly code or perform actual + benchmark to make an informed decision. */ #ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS -# if defined(i386) || defined(__i386) || defined(__i386__) || \ - defined(__i486__) || defined(__i586__) || defined(__i686__) || \ - defined(_X86_) || defined(__X86__) || defined(_M_IX86) || \ - defined(__I86__) || defined(__IA32__) || \ - defined(__THW_INTEL) || defined(__THW_INTEL__) || \ - defined(__x86_64) || defined(__x86_64__) || \ - defined(__amd64) || defined(__amd64__) || \ - defined(_M_AMD64) || defined(_M_X64) -# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* x86 */ - -# elif defined(__ia64) || defined(_IA64) || defined(__IA64__) || \ +# if defined(__ia64) || defined(_IA64) || defined(__IA64__) || \ defined(__ia64__) || defined(_M_IA64) || defined(__itanium__) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* Itanium */ - -# elif defined(__arm64) || defined(__arm64__) || \ - defined(__AARCH64EL__) || defined(__AARCH64EB__) || \ - defined(__aarch64__) || defined(_M_ARM64) -# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* ARM64 */ - -# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || \ - defined(__ARM_ARCH_5TEJ__) || defined(__ARM_ARCH_5TE__) || \ - defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6KZ__) || \ - defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6K__) +# elif (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) && \ + (defined(__GNUC__) || defined(__clang__)) && \ + (!defined(__ARM_FEATURE_UNALIGNED) || !__ARM_FEATURE_UNALIGNED) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* ARM */ - -# elif defined(__ppc64__) || defined(__PPC64__) || \ - defined(__powerpc64__) || defined(_ARCH_PPC64) || \ - defined(__ppc) || defined(__ppc__) || defined(__PPC__) || \ - defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || \ - defined(_ARCH_PPC) || defined(_M_PPC) || \ - defined(__PPCGECKO__) || defined(__PPCBROADWAY__) || defined(_XENON) -# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* PowerPC */ - +# elif defined(__sparc) || defined(__sparc__) +# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* SPARC */ +# elif defined(__mips) || defined(__mips__) || defined(__MIPS__) +# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* MIPS */ +# elif defined(__m68k__) || defined(M68000) +# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* M68K */ # else -# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* Unknown */ +# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 # endif - #endif /* Estimated initial ratio of the JSON data (data_size / value_count). For example: - + data: {"id":12345678,"name":"Harry"} data_size: 30 value_count: 5 ratio: 6 - + yyjson uses dynamic memory with a growth factor of 1.5 when reading and writing JSON, the ratios below are used to determine the initial memory size. - + A too large ratio will waste memory, and a too small ratio will cause multiple memory growths and degrade performance. Currently, these ratios are generated with some commonly used JSON datasets. @@ -354,6 +306,15 @@ yyjson_api uint32_t yyjson_version(void) { #define YYJSON_WRITER_ESTIMATED_PRETTY_RATIO 32 #define YYJSON_WRITER_ESTIMATED_MINIFY_RATIO 18 +/* The initial and maximum size of the memory pool's chunk in yyjson_mut_doc. */ +#define YYJSON_MUT_DOC_STR_POOL_INIT_SIZE 0x100 +#define YYJSON_MUT_DOC_STR_POOL_MAX_SIZE 0x10000000 +#define YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE (0x10 * sizeof(yyjson_mut_val)) +#define YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE (0x1000000 * sizeof(yyjson_mut_val)) + +/* The minimum size of the dynamic allocator's chunk. */ +#define YYJSON_ALC_DYN_MIN_SIZE 0x1000 + /* Default value for compile-time options. */ #ifndef YYJSON_DISABLE_READER #define YYJSON_DISABLE_READER 0 @@ -361,12 +322,18 @@ yyjson_api uint32_t yyjson_version(void) { #ifndef YYJSON_DISABLE_WRITER #define YYJSON_DISABLE_WRITER 0 #endif +#ifndef YYJSON_DISABLE_UTILS +#define YYJSON_DISABLE_UTILS 0 +#endif #ifndef YYJSON_DISABLE_FAST_FP_CONV #define YYJSON_DISABLE_FAST_FP_CONV 0 #endif #ifndef YYJSON_DISABLE_NON_STANDARD #define YYJSON_DISABLE_NON_STANDARD 0 #endif +#ifndef YYJSON_DISABLE_UTF8_VALIDATION +#define YYJSON_DISABLE_UTF8_VALIDATION 0 +#endif @@ -381,14 +348,15 @@ yyjson_api uint32_t yyjson_version(void) { #define repeat8(x) { x x x x x x x x } #define repeat16(x) { x x x x x x x x x x x x x x x x } -#define repeat2_incr(x) { x(0) x(1) } -#define repeat4_incr(x) { x(0) x(1) x(2) x(3) } -#define repeat8_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) } -#define repeat16_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \ - x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) } -#define repeat_in_1_18(x) { x(1) x(2) x(3) x(4) x(5) x(6) x(7) \ - x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) \ - x(16) x(17) x(18) } +#define repeat2_incr(x) { x(0) x(1) } +#define repeat4_incr(x) { x(0) x(1) x(2) x(3) } +#define repeat8_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) } +#define repeat16_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \ + x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) } + +#define repeat_in_1_18(x) { x(1) x(2) x(3) x(4) x(5) x(6) x(7) x(8) \ + x(9) x(10) x(11) x(12) x(13) x(14) x(15) x(16) \ + x(17) x(18) } /* Macros used to provide branch prediction information for compiler. */ #undef likely @@ -412,6 +380,33 @@ yyjson_api uint32_t yyjson_version(void) { #undef U64 #define U64(hi, lo) ((((u64)hi##UL) << 32U) + lo##UL) +/* Used to cast away (remove) const qualifier. */ +#define constcast(type) (type)(void *)(size_t)(const void *) + +/* flag test */ +#define has_read_flag(_flag) unlikely(read_flag_eq(flg, YYJSON_READ_##_flag)) +#define has_write_flag(_flag) unlikely(write_flag_eq(flg, YYJSON_WRITE_##_flag)) + +static_inline bool read_flag_eq(yyjson_read_flag flg, yyjson_read_flag chk) { +#if YYJSON_DISABLE_NON_STANDARD + if (chk == YYJSON_READ_ALLOW_INF_AND_NAN || + chk == YYJSON_READ_ALLOW_COMMENTS || + chk == YYJSON_READ_ALLOW_TRAILING_COMMAS || + chk == YYJSON_READ_ALLOW_INVALID_UNICODE) + return false; /* this should be evaluated at compile-time */ +#endif + return (flg & chk) != 0; +} + +static_inline bool write_flag_eq(yyjson_write_flag flg, yyjson_write_flag chk) { +#if YYJSON_DISABLE_NON_STANDARD + if (chk == YYJSON_WRITE_ALLOW_INF_AND_NAN || + chk == YYJSON_WRITE_ALLOW_INVALID_UNICODE) + return false; /* this should be evaluated at compile-time */ +#endif + return (flg & chk) != 0; +} + /*============================================================================== @@ -426,9 +421,13 @@ yyjson_api uint32_t yyjson_version(void) { #undef USIZE_MAX #define USIZE_MAX ((usize)(~(usize)0)) -/* Maximum number of digits for reading u64 safety. */ +/* Maximum number of digits for reading u32/u64/usize safety (not overflow). */ +#undef U32_SAFE_DIG +#define U32_SAFE_DIG 9 /* u32 max is 4294967295, 10 digits */ #undef U64_SAFE_DIG -#define U64_SAFE_DIG 19 +#define U64_SAFE_DIG 19 /* u64 max is 18446744073709551615, 20 digits */ +#undef USIZE_SAFE_DIG +#define USIZE_SAFE_DIG (sizeof(usize) == 8 ? U64_SAFE_DIG : U32_SAFE_DIG) @@ -511,11 +510,11 @@ __extension__ typedef unsigned __int128 u128; #endif /** 16/32/64-bit vector */ -typedef struct v16 { char c1, c2; } v16; -typedef struct v32 { char c1, c2, c3, c4; } v32; -typedef struct v64 { char c1, c2, c3, c4, c5, c6, c7, c8; } v64; +typedef struct v16 { char c[2]; } v16; +typedef struct v32 { char c[4]; } v32; +typedef struct v64 { char c[8]; } v64; -/** 16/32/64-bit vector union, used for unaligned memory access on modern CPU */ +/** 16/32/64-bit vector union */ typedef union v16_uni { v16 v; u16 u; } v16_uni; typedef union v32_uni { v32 v; u32 u; } v32_uni; typedef union v64_uni { v64 v; u64 u; } v64_uni; @@ -526,121 +525,164 @@ typedef union v64_uni { v64 v; u64 u; } v64_uni; * Load/Store Utils *============================================================================*/ -#define byte_move_idx(x) ((u8 *)dst)[x] = ((u8 *)src)[x]; +#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS + +#define byte_move_idx(x) ((char *)dst)[x] = ((const char *)src)[x]; + +static_inline void byte_copy_2(void *dst, const void *src) { + repeat2_incr(byte_move_idx) +} + +static_inline void byte_copy_4(void *dst, const void *src) { + repeat4_incr(byte_move_idx) +} + +static_inline void byte_copy_8(void *dst, const void *src) { + repeat8_incr(byte_move_idx) +} + +static_inline void byte_copy_16(void *dst, const void *src) { + repeat16_incr(byte_move_idx) +} static_inline void byte_move_2(void *dst, const void *src) { -#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS - repeat2_incr(byte_move_idx); -#else - memmove(dst, src, 2); -#endif + repeat2_incr(byte_move_idx) } static_inline void byte_move_4(void *dst, const void *src) { -#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS - repeat4_incr(byte_move_idx); -#else - memmove(dst, src, 4); -#endif + repeat4_incr(byte_move_idx) } static_inline void byte_move_8(void *dst, const void *src) { -#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS - repeat8_incr(byte_move_idx); -#else - memmove(dst, src, 8); -#endif + repeat8_incr(byte_move_idx) } static_inline void byte_move_16(void *dst, const void *src) { -#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS - repeat16_incr(byte_move_idx); -#else - memmove(dst, src, 16); -#endif + repeat16_incr(byte_move_idx) } -static_inline void byte_copy_2(void *dst, const void *src) { -#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS - repeat2_incr(byte_move_idx); +static_inline bool byte_match_2(void *buf, const char *pat) { + return + ((char *)buf)[0] == ((const char *)pat)[0] && + ((char *)buf)[1] == ((const char *)pat)[1]; +} + +static_inline bool byte_match_4(void *buf, const char *pat) { + return + ((char *)buf)[0] == ((const char *)pat)[0] && + ((char *)buf)[1] == ((const char *)pat)[1] && + ((char *)buf)[2] == ((const char *)pat)[2] && + ((char *)buf)[3] == ((const char *)pat)[3]; +} + +static_inline u16 byte_load_2(const void *src) { + v16_uni uni; + uni.v.c[0] = ((const char *)src)[0]; + uni.v.c[1] = ((const char *)src)[1]; + return uni.u; +} + +static_inline u32 byte_load_3(const void *src) { + v32_uni uni; + uni.v.c[0] = ((const char *)src)[0]; + uni.v.c[1] = ((const char *)src)[1]; + uni.v.c[2] = ((const char *)src)[2]; + uni.v.c[3] = 0; + return uni.u; +} + +static_inline u32 byte_load_4(const void *src) { + v32_uni uni; + uni.v.c[0] = ((const char *)src)[0]; + uni.v.c[1] = ((const char *)src)[1]; + uni.v.c[2] = ((const char *)src)[2]; + uni.v.c[3] = ((const char *)src)[3]; + return uni.u; +} + +#undef byte_move_expr + #else + +static_inline void byte_copy_2(void *dst, const void *src) { memcpy(dst, src, 2); -#endif } static_inline void byte_copy_4(void *dst, const void *src) { -#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS - repeat4_incr(byte_move_idx); -#else memcpy(dst, src, 4); -#endif } static_inline void byte_copy_8(void *dst, const void *src) { -#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS - repeat8_incr(byte_move_idx); -#else memcpy(dst, src, 8); -#endif } static_inline void byte_copy_16(void *dst, const void *src) { -#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS - repeat16_incr(byte_move_idx); -#else memcpy(dst, src, 16); -#endif +} + +static_inline void byte_move_2(void *dst, const void *src) { + u16 tmp; + memcpy(&tmp, src, 2); + memcpy(dst, &tmp, 2); +} + +static_inline void byte_move_4(void *dst, const void *src) { + u32 tmp; + memcpy(&tmp, src, 4); + memcpy(dst, &tmp, 4); +} + +static_inline void byte_move_8(void *dst, const void *src) { + u64 tmp; + memcpy(&tmp, src, 8); + memcpy(dst, &tmp, 8); +} + +static_inline void byte_move_16(void *dst, const void *src) { + char *pdst = (char *)dst; + const char *psrc = (const char *)src; + u64 tmp1, tmp2; + memcpy(&tmp1, psrc, 8); + memcpy(&tmp2, psrc + 8, 8); + memcpy(pdst, &tmp1, 8); + memcpy(pdst + 8, &tmp2, 8); } static_inline bool byte_match_2(void *buf, const char *pat) { -#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS - return - ((u8 *)buf)[0] == ((const u8 *)pat)[0] && - ((u8 *)buf)[1] == ((const u8 *)pat)[1]; -#else v16_uni u1, u2; - u1.v = *(const v16 *)pat; - u2.v = *(const v16 *)buf; + memcpy(&u1, buf, 2); + memcpy(&u2, pat, 2); return u1.u == u2.u; -#endif } static_inline bool byte_match_4(void *buf, const char *pat) { -#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS - return - ((u8 *)buf)[0] == ((const u8 *)pat)[0] && - ((u8 *)buf)[1] == ((const u8 *)pat)[1] && - ((u8 *)buf)[2] == ((const u8 *)pat)[2] && - ((u8 *)buf)[3] == ((const u8 *)pat)[3]; -#else v32_uni u1, u2; - u1.v = *(const v32 *)pat; - u2.v = *(const v32 *)buf; + memcpy(&u1, buf, 4); + memcpy(&u2, pat, 4); return u1.u == u2.u; -#endif } static_inline u16 byte_load_2(const void *src) { v16_uni uni; - uni.v = *(v16 *)src; + memcpy(&uni, src, 2); return uni.u; } static_inline u32 byte_load_3(const void *src) { v32_uni uni; - ((v16_uni *)&uni)->v = *(v16 *)src; - uni.v.c3 = ((char *)src)[2]; - uni.v.c4 = 0; + memcpy(&uni, src, 2); + uni.v.c[2] = ((const char *)src)[2]; + uni.v.c[3] = 0; return uni.u; } static_inline u32 byte_load_4(const void *src) { v32_uni uni; - uni.v = *(v32 *)src; + memcpy(&uni, src, 4); return uni.u; } -#undef byte_move_expr +#endif @@ -649,37 +691,20 @@ static_inline u32 byte_load_4(const void *src) { * These functions are used to detect and convert NaN and Inf numbers. *============================================================================*/ -/** - This union is used to avoid violating the strict aliasing rule in C. - `memcpy` can be used in both C and C++, but it may reduce performance without - compiler optimization. - */ -typedef union { u64 u; f64 f; } f64_uni; - /** Convert raw binary to double. */ static_inline f64 f64_from_raw(u64 u) { -#ifndef __cplusplus - f64_uni uni; - uni.u = u; - return uni.f; -#else + /* use memcpy to avoid violating the strict aliasing rule */ f64 f; memcpy(&f, &u, 8); return f; -#endif } /** Convert double to raw binary. */ static_inline u64 f64_to_raw(f64 f) { -#ifndef __cplusplus - f64_uni uni; - uni.f = f; - return uni.u; -#else + /* use memcpy to avoid violating the strict aliasing rule */ u64 u; memcpy(&u, &f, 8); return u; -#endif } /** Get raw 'infinity' with sign. */ @@ -706,7 +731,7 @@ static_inline u64 f64_raw_get_nan(bool sign) { /** Convert normalized u64 (highest bit is 1) to f64. - + Some compiler (such as Microsoft Visual C++ 6.0) do not support converting number from u64 to f64. This function will first convert u64 to i64 and then to f64, with `to nearest` rounding mode. @@ -729,8 +754,7 @@ static_inline f64 normalized_u64_to_f64(u64 val) { /** Returns whether the size is overflow after increment. */ static_inline bool size_add_is_overflow(usize size, usize add) { - usize val = size + add; - return (val < size) | (val < add); + return size > (size + add); } /** Returns whether the size is power of 2 (size should not be 0). */ @@ -765,15 +789,6 @@ static_inline void *mem_align_up(void *mem, usize align) { return mem; } -/** Align address downwards. */ -static_inline void *mem_align_down(void *mem, usize align) { - usize size; - memcpy(&size, &mem, sizeof(usize)); - size = size_align_down(size, align); - memcpy(&mem, &size, sizeof(usize)); - return mem; -} - /*============================================================================== @@ -959,6 +974,15 @@ static const yyjson_alc YYJSON_DEFAULT_ALC = { NULL }; + + +/*============================================================================== + * Null Memory Allocator + * + * This allocator is just a placeholder to ensure that the internal + * malloc/realloc/free function pointers are not null. + *============================================================================*/ + static void *null_malloc(void *ctx, usize size) { return NULL; } @@ -982,30 +1006,38 @@ static const yyjson_alc YYJSON_NULL_ALC = { /*============================================================================== * Pool Memory Allocator - * This is a simple memory allocator that uses linked list memory chunk. - * The following code will be executed only when the library user creates - * this allocator manually. + * + * This allocator is initialized with a fixed-size buffer. + * The buffer is split into multiple memory chunks for memory allocation. *============================================================================*/ -/** chunk header */ +/** memory chunk header */ typedef struct pool_chunk { - usize size; /* chunk memory size (include chunk header) */ - struct pool_chunk *next; + usize size; /* chunk memory size, include chunk header */ + struct pool_chunk *next; /* linked list, nullable */ + /* char mem[]; flexible array member */ } pool_chunk; -/** ctx header */ +/** allocator ctx header */ typedef struct pool_ctx { - usize size; /* total memory size (include ctx header) */ - pool_chunk *free_list; + usize size; /* total memory size, include ctx header */ + pool_chunk *free_list; /* linked list, nullable */ + /* pool_chunk chunks[]; flexible array member */ } pool_ctx; +/** align up the input size to chunk size */ +static_inline void pool_size_align(usize *size) { + *size = size_align_up(*size, sizeof(pool_chunk)) + sizeof(pool_chunk); +} + static void *pool_malloc(void *ctx_ptr, usize size) { + /* assert(size != 0) */ pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *next, *prev = NULL, *cur = ctx->free_list; - - if (unlikely(size == 0 || size >= ctx->size)) return NULL; - size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk); - + + if (unlikely(size >= ctx->size)) return NULL; + pool_size_align(&size); + while (cur) { if (cur->size < size) { /* not enough space, try next chunk */ @@ -1031,10 +1063,11 @@ static void *pool_malloc(void *ctx_ptr, usize size) { } static void pool_free(void *ctx_ptr, void *ptr) { + /* assert(ptr != NULL) */ pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *cur = ((pool_chunk *)ptr) - 1; pool_chunk *prev = NULL, *next = ctx->free_list; - + while (next && next < cur) { prev = next; next = next->next; @@ -1042,7 +1075,7 @@ static void pool_free(void *ctx_ptr, void *ptr) { if (prev) prev->next = cur; else ctx->free_list = cur; cur->next = next; - + if (next && ((u8 *)cur + cur->size) == (u8 *)next) { /* merge cur to higher chunk */ cur->size += next->size; @@ -1057,26 +1090,16 @@ static void pool_free(void *ctx_ptr, void *ptr) { static void *pool_realloc(void *ctx_ptr, void *ptr, usize old_size, usize size) { + /* assert(ptr != NULL && size != 0 && old_size < size) */ pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *cur = ((pool_chunk *)ptr) - 1, *prev, *next, *tmp; - usize free_size; - void *new_ptr; - - if (unlikely(size == 0 || size >= ctx->size)) return NULL; - size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk); - - /* reduce size */ - if (unlikely(size <= cur->size)) { - free_size = cur->size - size; - if (free_size >= sizeof(pool_chunk) * 2) { - tmp = (pool_chunk *)(void *)((u8 *)cur + cur->size - free_size); - tmp->size = free_size; - pool_free(ctx_ptr, (void *)(tmp + 1)); - cur->size -= free_size; - } - return ptr; - } - + + /* check size */ + if (unlikely(size >= ctx->size)) return NULL; + pool_size_align(&old_size); + pool_size_align(&size); + if (unlikely(old_size == size)) return ptr; + /* find next and prev chunk */ prev = NULL; next = ctx->free_list; @@ -1084,11 +1107,10 @@ static void *pool_realloc(void *ctx_ptr, void *ptr, prev = next; next = next->next; } - - /* merge to higher chunk if they are contiguous */ - if ((u8 *)cur + cur->size == (u8 *)next && - cur->size + next->size >= size) { - free_size = cur->size + next->size - size; + + if ((u8 *)cur + cur->size == (u8 *)next && cur->size + next->size >= size) { + /* merge to higher chunk if they are contiguous */ + usize free_size = cur->size + next->size - size; if (free_size > sizeof(pool_chunk) * 2) { tmp = (pool_chunk *)(void *)((u8 *)cur + size); if (prev) prev->next = tmp; @@ -1102,21 +1124,21 @@ static void *pool_realloc(void *ctx_ptr, void *ptr, cur->size += next->size; } return ptr; + } else { + /* fallback to malloc and memcpy */ + void *new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk)); + if (new_ptr) { + memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk)); + pool_free(ctx_ptr, ptr); + } + return new_ptr; } - - /* fallback to malloc and memcpy */ - new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk)); - if (new_ptr) { - memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk)); - pool_free(ctx_ptr, ptr); - } - return new_ptr; } bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) { pool_chunk *chunk; pool_ctx *ctx; - + if (unlikely(!alc)) return false; *alc = YYJSON_NULL_ALC; if (size < sizeof(pool_ctx) * 4) return false; @@ -1124,13 +1146,13 @@ bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) { if (unlikely(!ctx)) return false; size -= (usize)((u8 *)ctx - (u8 *)buf); size = size_align_down(size, sizeof(pool_ctx)); - + chunk = (pool_chunk *)(ctx + 1); chunk->size = size - sizeof(pool_ctx); chunk->next = NULL; ctx->size = size; ctx->free_list = chunk; - + alc->malloc = pool_malloc; alc->realloc = pool_realloc; alc->free = pool_free; @@ -1140,6 +1162,161 @@ bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) { +/*============================================================================== + * Dynamic Memory Allocator + * + * This allocator allocates memory on demand and does not immediately release + * unused memory. Instead, it places the unused memory into a freelist for + * potential reuse in the future. It is only when the entire allocator is + * destroyed that all previously allocated memory is released at once. + *============================================================================*/ + +/** memory chunk header */ +typedef struct dyn_chunk { + usize size; /* chunk size, include header */ + struct dyn_chunk *next; + /* char mem[]; flexible array member */ +} dyn_chunk; + +/** allocator ctx header */ +typedef struct { + dyn_chunk free_list; /* dummy header, sorted from small to large */ + dyn_chunk used_list; /* dummy header */ +} dyn_ctx; + +/** align up the input size to chunk size */ +static_inline bool dyn_size_align(usize *size) { + usize alc_size = *size + sizeof(dyn_chunk); + alc_size = size_align_up(alc_size, YYJSON_ALC_DYN_MIN_SIZE); + if (unlikely(alc_size < *size)) return false; /* overflow */ + *size = alc_size; + return true; +} + +/** remove a chunk from list (the chunk must already be in the list) */ +static_inline void dyn_chunk_list_remove(dyn_chunk *list, dyn_chunk *chunk) { + dyn_chunk *prev = list, *cur; + for (cur = prev->next; cur; cur = cur->next) { + if (cur == chunk) { + prev->next = cur->next; + cur->next = NULL; + return; + } + prev = cur; + } +} + +/** add a chunk to list header (the chunk must not be in the list) */ +static_inline void dyn_chunk_list_add(dyn_chunk *list, dyn_chunk *chunk) { + chunk->next = list->next; + list->next = chunk; +} + +static void *dyn_malloc(void *ctx_ptr, usize size) { + /* assert(size != 0) */ + const yyjson_alc def = YYJSON_DEFAULT_ALC; + dyn_ctx *ctx = (dyn_ctx *)ctx_ptr; + dyn_chunk *chunk, *prev, *next; + if (unlikely(!dyn_size_align(&size))) return NULL; + + /* freelist is empty, create new chunk */ + if (!ctx->free_list.next) { + chunk = (dyn_chunk *)def.malloc(def.ctx, size); + if (unlikely(!chunk)) return NULL; + chunk->size = size; + chunk->next = NULL; + dyn_chunk_list_add(&ctx->used_list, chunk); + return (void *)(chunk + 1); + } + + /* find a large enough chunk, or resize the largest chunk */ + prev = &ctx->free_list; + while (true) { + chunk = prev->next; + if (chunk->size >= size) { /* enough size, reuse this chunk */ + prev->next = chunk->next; + dyn_chunk_list_add(&ctx->used_list, chunk); + return (void *)(chunk + 1); + } + if (!chunk->next) { /* resize the largest chunk */ + chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size); + if (unlikely(!chunk)) return NULL; + prev->next = NULL; + chunk->size = size; + dyn_chunk_list_add(&ctx->used_list, chunk); + return (void *)(chunk + 1); + } + prev = chunk; + } +} + +static void *dyn_realloc(void *ctx_ptr, void *ptr, + usize old_size, usize size) { + /* assert(ptr != NULL && size != 0 && old_size < size) */ + const yyjson_alc def = YYJSON_DEFAULT_ALC; + dyn_ctx *ctx = (dyn_ctx *)ctx_ptr; + dyn_chunk *prev, *next, *new_chunk; + dyn_chunk *chunk = (dyn_chunk *)ptr - 1; + if (unlikely(!dyn_size_align(&size))) return NULL; + if (chunk->size >= size) return ptr; + + dyn_chunk_list_remove(&ctx->used_list, chunk); + new_chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size); + if (likely(new_chunk)) { + new_chunk->size = size; + chunk = new_chunk; + } + dyn_chunk_list_add(&ctx->used_list, chunk); + return new_chunk ? (void *)(new_chunk + 1) : NULL; +} + +static void dyn_free(void *ctx_ptr, void *ptr) { + /* assert(ptr != NULL) */ + dyn_ctx *ctx = (dyn_ctx *)ctx_ptr; + dyn_chunk *chunk = (dyn_chunk *)ptr - 1, *prev; + + dyn_chunk_list_remove(&ctx->used_list, chunk); + for (prev = &ctx->free_list; prev; prev = prev->next) { + if (!prev->next || prev->next->size >= chunk->size) { + chunk->next = prev->next; + prev->next = chunk; + break; + } + } +} + +yyjson_alc *yyjson_alc_dyn_new(void) { + const yyjson_alc def = YYJSON_DEFAULT_ALC; + usize hdr_len = sizeof(yyjson_alc) + sizeof(dyn_ctx); + yyjson_alc *alc = (yyjson_alc *)def.malloc(def.ctx, hdr_len); + dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1); + if (unlikely(!alc)) return NULL; + alc->malloc = dyn_malloc; + alc->realloc = dyn_realloc; + alc->free = dyn_free; + alc->ctx = alc + 1; + memset(ctx, 0, sizeof(*ctx)); + return alc; +} + +void yyjson_alc_dyn_free(yyjson_alc *alc) { + const yyjson_alc def = YYJSON_DEFAULT_ALC; + dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1); + dyn_chunk *chunk, *next; + if (unlikely(!alc)) return; + for (chunk = ctx->free_list.next; chunk; chunk = next) { + next = chunk->next; + def.free(def.ctx, chunk); + } + for (chunk = ctx->used_list.next; chunk; chunk = next) { + next = chunk->next; + def.free(def.ctx, chunk); + } + def.free(def.ctx, alc); +} + + + /*============================================================================== * JSON document and value *============================================================================*/ @@ -1167,17 +1344,26 @@ static_inline void unsafe_yyjson_val_pool_release(yyjson_val_pool *pool, bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool, const yyjson_alc *alc, usize len) { yyjson_str_chunk *chunk; - usize size = len + sizeof(yyjson_str_chunk); + usize size, max_len; + + /* create a new chunk */ + max_len = USIZE_MAX - sizeof(yyjson_str_chunk); + if (unlikely(len > max_len)) return false; + size = len + sizeof(yyjson_str_chunk); size = yyjson_max(pool->chunk_size, size); chunk = (yyjson_str_chunk *)alc->malloc(alc->ctx, size); - if (yyjson_unlikely(!chunk)) return false; - + if (unlikely(!chunk)) return false; + + /* insert the new chunk as the head of the linked list */ chunk->next = pool->chunks; + chunk->chunk_size = size; pool->chunks = chunk; pool->cur = (char *)chunk + sizeof(yyjson_str_chunk); pool->end = (char *)chunk + size; - + + /* the next chunk is twice the size of the current one */ size = yyjson_min(pool->chunk_size * 2, pool->chunk_size_max); + if (size < pool->chunk_size) size = pool->chunk_size_max; /* overflow */ pool->chunk_size = size; return true; } @@ -1185,28 +1371,48 @@ bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool, bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool, const yyjson_alc *alc, usize count) { yyjson_val_chunk *chunk; - usize size; - - if (count >= USIZE_MAX / sizeof(yyjson_mut_val) - 16) return false; + usize size, max_count; + + /* create a new chunk */ + max_count = USIZE_MAX / sizeof(yyjson_mut_val) - 1; + if (unlikely(count > max_count)) return false; size = (count + 1) * sizeof(yyjson_mut_val); size = yyjson_max(pool->chunk_size, size); chunk = (yyjson_val_chunk *)alc->malloc(alc->ctx, size); - if (yyjson_unlikely(!chunk)) return false; - + if (unlikely(!chunk)) return false; + + /* insert the new chunk as the head of the linked list */ chunk->next = pool->chunks; + chunk->chunk_size = size; pool->chunks = chunk; - pool->cur = (yyjson_mut_val *)(void *)((u8 *)chunk - + sizeof(yyjson_mut_val)); + pool->cur = (yyjson_mut_val *)(void *)((u8 *)chunk) + 1; pool->end = (yyjson_mut_val *)(void *)((u8 *)chunk + size); - + + /* the next chunk is twice the size of the current one */ size = yyjson_min(pool->chunk_size * 2, pool->chunk_size_max); + if (size < pool->chunk_size) size = pool->chunk_size_max; /* overflow */ pool->chunk_size = size; return true; } +bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc, size_t len) { + usize max_size = USIZE_MAX - sizeof(yyjson_str_chunk); + if (!doc || !len || len > max_size) return false; + doc->str_pool.chunk_size = len + sizeof(yyjson_str_chunk); + return true; +} + +bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc, size_t count) { + usize max_count = USIZE_MAX / sizeof(yyjson_mut_val) - 1; + if (!doc || !count || count > max_count) return false; + doc->val_pool.chunk_size = (count + 1) * sizeof(yyjson_mut_val); + return true; +} + void yyjson_mut_doc_free(yyjson_mut_doc *doc) { if (doc) { yyjson_alc alc = doc->alc; + memset(&doc->alc, 0, sizeof(alc)); unsafe_yyjson_str_pool_release(&doc->str_pool, &alc); unsafe_yyjson_val_pool_release(&doc->val_pool, &alc); alc.free(alc.ctx, doc); @@ -1219,20 +1425,19 @@ yyjson_mut_doc *yyjson_mut_doc_new(const yyjson_alc *alc) { doc = (yyjson_mut_doc *)alc->malloc(alc->ctx, sizeof(yyjson_mut_doc)); if (!doc) return NULL; memset(doc, 0, sizeof(yyjson_mut_doc)); - + doc->alc = *alc; - doc->str_pool.chunk_size = 0x100; - doc->str_pool.chunk_size_max = 0x10000000; - doc->val_pool.chunk_size = 0x10 * sizeof(yyjson_mut_val); - doc->val_pool.chunk_size_max = 0x1000000 * sizeof(yyjson_mut_val); + doc->str_pool.chunk_size = YYJSON_MUT_DOC_STR_POOL_INIT_SIZE; + doc->str_pool.chunk_size_max = YYJSON_MUT_DOC_STR_POOL_MAX_SIZE; + doc->val_pool.chunk_size = YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE; + doc->val_pool.chunk_size_max = YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE; return doc; } -yyjson_api yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc, - const yyjson_alc *alc) { +yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc, const yyjson_alc *alc) { yyjson_mut_doc *m_doc; yyjson_mut_val *m_val; - + if (!doc || !doc->root) return NULL; m_doc = yyjson_mut_doc_new(alc); if (!m_doc) return NULL; @@ -1245,12 +1450,14 @@ yyjson_api yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc, return m_doc; } -yyjson_api yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc, - const yyjson_alc *alc) { +yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc, + const yyjson_alc *alc) { yyjson_mut_doc *m_doc; yyjson_mut_val *m_val; - - if (!doc || !doc->root) return NULL; + + if (!doc) return NULL; + if (!doc->root) return yyjson_mut_doc_new(alc); + m_doc = yyjson_mut_doc_new(alc); if (!m_doc) return NULL; m_val = yyjson_mut_val_mut_copy(m_doc, doc->root); @@ -1262,18 +1469,17 @@ yyjson_api yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc, return m_doc; } -yyjson_api yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc, - yyjson_val *i_vals) { +yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc, + yyjson_val *i_vals) { /* The immutable object or array stores all sub-values in a contiguous memory, We copy them to another contiguous memory as mutable values, then reconnect the mutable values with the original relationship. */ - usize i_vals_len; yyjson_mut_val *m_vals, *m_val; yyjson_val *i_val, *i_end; - + if (!m_doc || !i_vals) return NULL; i_end = unsafe_yyjson_get_next(i_vals); i_vals_len = (usize)(unsafe_yyjson_get_next(i_vals) - i_vals); @@ -1281,7 +1487,7 @@ yyjson_api yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc, if (!m_vals) return NULL; i_val = i_vals; m_val = m_vals; - + for (; i_val < i_end; i_val++, m_val++) { yyjson_type type = unsafe_yyjson_get_type(i_val); m_val->tag = i_val->tag; @@ -1326,7 +1532,7 @@ yyjson_api yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc, } } } - + return m_vals; } @@ -1339,11 +1545,10 @@ static yyjson_mut_val *unsafe_yyjson_mut_val_mut_copy(yyjson_mut_doc *m_doc, second to last item, which needs to be linked to the last item to close the circle. */ - yyjson_mut_val *m_val = unsafe_yyjson_mut_val(m_doc, 1); if (unlikely(!m_val)) return NULL; m_val->tag = m_vals->tag; - + switch (unsafe_yyjson_get_type(m_vals)) { case YYJSON_TYPE_OBJ: case YYJSON_TYPE_ARR: @@ -1362,7 +1567,7 @@ static yyjson_mut_val *unsafe_yyjson_mut_val_mut_copy(yyjson_mut_doc *m_doc, prev->next = (yyjson_mut_val *)m_val->uni.ptr; } break; - + case YYJSON_TYPE_RAW: case YYJSON_TYPE_STR: { const char *str = m_vals->uni.str; @@ -1371,17 +1576,17 @@ static yyjson_mut_val *unsafe_yyjson_mut_val_mut_copy(yyjson_mut_doc *m_doc, if (!m_val->uni.str) return NULL; break; } - + default: m_val->uni = m_vals->uni; break; } - + return m_val; } -yyjson_api yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc, - yyjson_mut_val *val) { +yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc, + yyjson_mut_val *val) { if (doc && val) return unsafe_yyjson_mut_val_mut_copy(doc, val); return NULL; } @@ -1437,7 +1642,7 @@ static usize yyjson_imut_copy(yyjson_val **val_ptr, char **buf_ptr, } else if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) { char *buf = *buf_ptr; usize len = unsafe_yyjson_get_len(mval); - memcpy((void *)buf, (void *)mval->uni.str, len); + memcpy((void *)buf, (const void *)mval->uni.str, len); buf[len] = '\0'; val->tag = mval->tag; val->uni.str = buf; @@ -1452,37 +1657,37 @@ static usize yyjson_imut_copy(yyjson_val **val_ptr, char **buf_ptr, } } -yyjson_api yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *mdoc, - const yyjson_alc *alc) { +yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *mdoc, + const yyjson_alc *alc) { if (!mdoc) return NULL; return yyjson_mut_val_imut_copy(mdoc->root, alc); } -yyjson_api yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *mval, - const yyjson_alc *alc) { +yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *mval, + const yyjson_alc *alc) { usize val_num = 0, str_sum = 0, hdr_size, buf_size; yyjson_doc *doc = NULL; yyjson_val *val_hdr = NULL; - + /* This value should be NULL here. Setting a non-null value suppresses warning from the clang analyzer. */ char *str_hdr = (char *)(void *)&str_sum; if (!mval) return NULL; if (!alc) alc = &YYJSON_DEFAULT_ALC; - + /* traverse the input value to get pool size */ yyjson_mut_stat(mval, &val_num, &str_sum); - + /* create doc and val pool */ hdr_size = size_align_up(sizeof(yyjson_doc), sizeof(yyjson_val)); buf_size = hdr_size + val_num * sizeof(yyjson_val); doc = (yyjson_doc *)alc->malloc(alc->ctx, buf_size); if (!doc) return NULL; memset(doc, 0, sizeof(yyjson_doc)); - val_hdr = (yyjson_val *)((char *)(void *)doc + hdr_size); + val_hdr = (yyjson_val *)(void *)((char *)(void *)doc + hdr_size); doc->root = val_hdr; doc->alc = *alc; - + /* create str pool */ if (str_sum > 0) { str_hdr = (char *)alc->malloc(alc->ctx, str_sum); @@ -1492,7 +1697,7 @@ yyjson_api yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *mval, return NULL; } } - + /* copy vals and strs */ doc->val_read = yyjson_imut_copy(&val_hdr, &str_hdr, mval); doc->dat_read = str_sum + 1; @@ -1504,27 +1709,27 @@ static_inline bool unsafe_yyjson_num_equals(void *lhs, void *rhs) { yyjson_val_uni *runi = &((yyjson_val *)rhs)->uni; yyjson_subtype lt = unsafe_yyjson_get_subtype(lhs); yyjson_subtype rt = unsafe_yyjson_get_subtype(rhs); - if (lt == rt) - return luni->u64 == runi->u64; - if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT) + if (lt == rt) return luni->u64 == runi->u64; + if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT) { return luni->i64 >= 0 && luni->u64 == runi->u64; - if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT) + } + if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT) { return runi->i64 >= 0 && luni->u64 == runi->u64; + } return false; } static_inline bool unsafe_yyjson_str_equals(void *lhs, void *rhs) { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; - return 0 == len || - 0 == memcmp(unsafe_yyjson_get_str(lhs), - unsafe_yyjson_get_str(rhs), len); + return !memcmp(unsafe_yyjson_get_str(lhs), + unsafe_yyjson_get_str(rhs), len); } -yyjson_api bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { +bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { yyjson_type type = unsafe_yyjson_get_type(lhs); if (type != unsafe_yyjson_get_type(rhs)) return false; - + switch (type) { case YYJSON_TYPE_OBJ: { usize len = unsafe_yyjson_get_len(lhs); @@ -1536,15 +1741,15 @@ yyjson_api bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { while (len-- > 0) { rhs = yyjson_obj_iter_getn(&iter, lhs->uni.str, unsafe_yyjson_get_len(lhs)); - if (!rhs || !unsafe_yyjson_equals(lhs + 1, rhs)) - return false; + if (!rhs) return false; + if (!unsafe_yyjson_equals(lhs + 1, rhs)) return false; lhs = unsafe_yyjson_get_next(lhs + 1); } } /* yyjson allows duplicate keys, so the check may be inaccurate */ return true; } - + case YYJSON_TYPE_ARR: { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; @@ -1552,26 +1757,25 @@ yyjson_api bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { lhs = unsafe_yyjson_get_first(lhs); rhs = unsafe_yyjson_get_first(rhs); while (len-- > 0) { - if (!unsafe_yyjson_equals(lhs, rhs)) - return false; + if (!unsafe_yyjson_equals(lhs, rhs)) return false; lhs = unsafe_yyjson_get_next(lhs); rhs = unsafe_yyjson_get_next(rhs); } } return true; } - + case YYJSON_TYPE_NUM: return unsafe_yyjson_num_equals(lhs, rhs); - + case YYJSON_TYPE_RAW: case YYJSON_TYPE_STR: return unsafe_yyjson_str_equals(lhs, rhs); - + case YYJSON_TYPE_NULL: case YYJSON_TYPE_BOOL: return lhs->tag == rhs->tag; - + default: return false; } @@ -1580,7 +1784,7 @@ yyjson_api bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) { yyjson_type type = unsafe_yyjson_get_type(lhs); if (type != unsafe_yyjson_get_type(rhs)) return false; - + switch (type) { case YYJSON_TYPE_OBJ: { usize len = unsafe_yyjson_get_len(lhs); @@ -1592,15 +1796,15 @@ bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) { while (len-- > 0) { rhs = yyjson_mut_obj_iter_getn(&iter, lhs->uni.str, unsafe_yyjson_get_len(lhs)); - if (!rhs || !unsafe_yyjson_mut_equals(lhs->next, rhs)) - return false; + if (!rhs) return false; + if (!unsafe_yyjson_mut_equals(lhs->next, rhs)) return false; lhs = lhs->next->next; } } /* yyjson allows duplicate keys, so the check may be inaccurate */ return true; } - + case YYJSON_TYPE_ARR: { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; @@ -1608,231 +1812,891 @@ bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) { lhs = (yyjson_mut_val *)lhs->uni.ptr; rhs = (yyjson_mut_val *)rhs->uni.ptr; while (len-- > 0) { - if (!unsafe_yyjson_mut_equals(lhs, rhs)) - return false; + if (!unsafe_yyjson_mut_equals(lhs, rhs)) return false; lhs = lhs->next; rhs = rhs->next; } } return true; } - - case YYJSON_TYPE_NUM: - return unsafe_yyjson_num_equals(lhs, rhs); - - case YYJSON_TYPE_RAW: - case YYJSON_TYPE_STR: - return unsafe_yyjson_str_equals(lhs, rhs); - - case YYJSON_TYPE_NULL: - case YYJSON_TYPE_BOOL: - return lhs->tag == rhs->tag; - - default: - return false; + + case YYJSON_TYPE_NUM: + return unsafe_yyjson_num_equals(lhs, rhs); + + case YYJSON_TYPE_RAW: + case YYJSON_TYPE_STR: + return unsafe_yyjson_str_equals(lhs, rhs); + + case YYJSON_TYPE_NULL: + case YYJSON_TYPE_BOOL: + return lhs->tag == rhs->tag; + + default: + return false; + } +} + + + +#if !YYJSON_DISABLE_UTILS + +/*============================================================================== + * JSON Pointer API (RFC 6901) + *============================================================================*/ + +/** + Get a token from JSON pointer string. + @param ptr [in,out] + in: string that points to current token prefix `/` + out: string that points to next token prefix `/`, or string end + @param end [in] end of the entire JSON Pointer string + @param len [out] unescaped token length + @param esc [out] number of escaped characters in this token + @return head of the token, or NULL if syntax error + */ +static_inline const char *ptr_next_token(const char **ptr, const char *end, + usize *len, usize *esc) { + const char *hdr = *ptr + 1; + const char *cur = hdr; + /* skip unescaped characters */ + while (cur < end && *cur != '/' && *cur != '~') cur++; + if (likely(cur == end || *cur != '~')) { + /* no escaped characters, return */ + *ptr = cur; + *len = (usize)(cur - hdr); + *esc = 0; + return hdr; + } else { + /* handle escaped characters */ + usize esc_num = 0; + while (cur < end && *cur != '/') { + if (*cur++ == '~') { + if (cur == end || (*cur != '0' && *cur != '1')) { + *ptr = cur - 1; + return NULL; + } + esc_num++; + } + } + *ptr = cur; + *len = (usize)(cur - hdr) - esc_num; + *esc = esc_num; + return hdr; + } +} + +/** + Convert token string to index. + @param cur [in] token head + @param len [in] token length + @param idx [out] the index number, or USIZE_MAX if token is '-' + @return true if token is a valid array index + */ +static_inline bool ptr_token_to_idx(const char *cur, usize len, usize *idx) { + const char *end = cur + len; + usize num = 0, add; + if (unlikely(len == 0 || len > USIZE_SAFE_DIG)) return false; + if (*cur == '0') { + if (unlikely(len > 1)) return false; + *idx = 0; + return true; + } + if (*cur == '-') { + if (unlikely(len > 1)) return false; + *idx = USIZE_MAX; + return true; + } + for (; cur < end && (add = (usize)((u8)*cur - (u8)'0')) <= 9; cur++) { + num = num * 10 + add; + } + if (unlikely(num == 0 || cur < end)) return false; + *idx = num; + return true; +} + +/** + Compare JSON key with token. + @param key a string key (yyjson_val or yyjson_mut_val) + @param token a JSON pointer token + @param len unescaped token length + @param esc number of escaped characters in this token + @return true if `str` is equals to `token` + */ +static_inline bool ptr_token_eq(void *key, + const char *token, usize len, usize esc) { + yyjson_val *val = (yyjson_val *)key; + if (unsafe_yyjson_get_len(val) != len) return false; + if (likely(!esc)) { + return memcmp(val->uni.str, token, len) == 0; + } else { + const char *str = val->uni.str; + for (; len-- > 0; token++, str++) { + if (*token == '~') { + if (*str != (*++token == '0' ? '~' : '/')) return false; + } else { + if (*str != *token) return false; + } + } + return true; + } +} + +/** + Get a value from array by token. + @param arr an array, should not be NULL or non-array type + @param token a JSON pointer token + @param len unescaped token length + @param esc number of escaped characters in this token + @return value at index, or NULL if token is not index or index is out of range + */ +static_inline yyjson_val *ptr_arr_get(yyjson_val *arr, const char *token, + usize len, usize esc) { + yyjson_val *val = unsafe_yyjson_get_first(arr); + usize num = unsafe_yyjson_get_len(arr), idx = 0; + if (unlikely(num == 0)) return NULL; + if (unlikely(!ptr_token_to_idx(token, len, &idx))) return NULL; + if (unlikely(idx >= num)) return NULL; + if (unsafe_yyjson_arr_is_flat(arr)) { + return val + idx; + } else { + while (idx-- > 0) val = unsafe_yyjson_get_next(val); + return val; + } +} + +/** + Get a value from object by token. + @param obj [in] an object, should not be NULL or non-object type + @param token [in] a JSON pointer token + @param len [in] unescaped token length + @param esc [in] number of escaped characters in this token + @return value associated with the token, or NULL if no value + */ +static_inline yyjson_val *ptr_obj_get(yyjson_val *obj, const char *token, + usize len, usize esc) { + yyjson_val *key = unsafe_yyjson_get_first(obj); + usize num = unsafe_yyjson_get_len(obj); + if (unlikely(num == 0)) return NULL; + for (; num > 0; num--, key = unsafe_yyjson_get_next(key + 1)) { + if (ptr_token_eq(key, token, len, esc)) return key + 1; + } + return NULL; +} + +/** + Get a value from array by token. + @param arr [in] an array, should not be NULL or non-array type + @param token [in] a JSON pointer token + @param len [in] unescaped token length + @param esc [in] number of escaped characters in this token + @param pre [out] previous (sibling) value of the returned value + @param last [out] whether index is last + @return value at index, or NULL if token is not index or index is out of range + */ +static_inline yyjson_mut_val *ptr_mut_arr_get(yyjson_mut_val *arr, + const char *token, + usize len, usize esc, + yyjson_mut_val **pre, + bool *last) { + yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr; /* last (tail) */ + usize num = unsafe_yyjson_get_len(arr), idx; + if (last) *last = false; + if (pre) *pre = NULL; + if (unlikely(num == 0)) { + if (last && len == 1 && (*token == '0' || *token == '-')) *last = true; + return NULL; + } + if (unlikely(!ptr_token_to_idx(token, len, &idx))) return NULL; + if (last) *last = (idx == num || idx == USIZE_MAX); + if (unlikely(idx >= num)) return NULL; + while (idx-- > 0) val = val->next; + *pre = val; + return val->next; +} + +/** + Get a value from object by token. + @param obj [in] an object, should not be NULL or non-object type + @param token [in] a JSON pointer token + @param len [in] unescaped token length + @param esc [in] number of escaped characters in this token + @param pre [out] previous (sibling) key of the returned value's key + @return value associated with the token, or NULL if no value + */ +static_inline yyjson_mut_val *ptr_mut_obj_get(yyjson_mut_val *obj, + const char *token, + usize len, usize esc, + yyjson_mut_val **pre) { + yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr, *key; + usize num = unsafe_yyjson_get_len(obj); + if (pre) *pre = NULL; + if (unlikely(num == 0)) return NULL; + for (; num > 0; num--, pre_key = key) { + key = pre_key->next->next; + if (ptr_token_eq(key, token, len, esc)) { + *pre = pre_key; + return key->next; + } + } + return NULL; +} + +/** + Create a string value with JSON pointer token. + @param token [in] a JSON pointer token + @param len [in] unescaped token length + @param esc [in] number of escaped characters in this token + @param doc [in] used for memory allocation when creating value + @return new string value, or NULL if memory allocation failed + */ +static_inline yyjson_mut_val *ptr_new_key(const char *token, + usize len, usize esc, + yyjson_mut_doc *doc) { + const char *src = token; + if (likely(!esc)) { + return yyjson_mut_strncpy(doc, src, len); + } else { + const char *end = src + len + esc; + char *dst = unsafe_yyjson_mut_str_alc(doc, len + esc); + char *str = dst; + if (unlikely(!dst)) return NULL; + for (; src < end; src++, dst++) { + if (*src != '~') *dst = *src; + else *dst = (*++src == '0' ? '~' : '/'); + } + *dst = '\0'; + return yyjson_mut_strn(doc, str, len); + } +} + +/* macros for yyjson_ptr */ +#define return_err(_ret, _code, _pos, _msg) do { \ + if (err) { \ + err->code = YYJSON_PTR_ERR_##_code; \ + err->msg = _msg; \ + err->pos = (usize)(_pos); \ + } \ + return _ret; \ +} while (false) + +#define return_err_resolve(_ret, _pos) \ + return_err(_ret, RESOLVE, _pos, "JSON pointer cannot be resolved") +#define return_err_syntax(_ret, _pos) \ + return_err(_ret, SYNTAX, _pos, "invalid escaped character") +#define return_err_alloc(_ret) \ + return_err(_ret, MEMORY_ALLOCATION, 0, "failed to create value") + +yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val, + const char *ptr, size_t ptr_len, + yyjson_ptr_err *err) { + + const char *hdr = ptr, *end = ptr + ptr_len, *token; + usize len, esc; + yyjson_type type; + + while (true) { + token = ptr_next_token(&ptr, end, &len, &esc); + if (unlikely(!token)) return_err_syntax(NULL, ptr - hdr); + type = unsafe_yyjson_get_type(val); + if (type == YYJSON_TYPE_OBJ) { + val = ptr_obj_get(val, token, len, esc); + } else if (type == YYJSON_TYPE_ARR) { + val = ptr_arr_get(val, token, len, esc); + } else { + val = NULL; + } + if (!val) return_err_resolve(NULL, token - hdr); + if (ptr == end) return val; + } +} + +yyjson_mut_val *unsafe_yyjson_mut_ptr_getx(yyjson_mut_val *val, + const char *ptr, + size_t ptr_len, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err) { + + const char *hdr = ptr, *end = ptr + ptr_len, *token; + usize len, esc; + yyjson_mut_val *ctn, *pre = NULL; + yyjson_type type; + bool idx_is_last = false; + + while (true) { + token = ptr_next_token(&ptr, end, &len, &esc); + if (unlikely(!token)) return_err_syntax(NULL, ptr - hdr); + ctn = val; + type = unsafe_yyjson_get_type(val); + if (type == YYJSON_TYPE_OBJ) { + val = ptr_mut_obj_get(val, token, len, esc, &pre); + } else if (type == YYJSON_TYPE_ARR) { + val = ptr_mut_arr_get(val, token, len, esc, &pre, &idx_is_last); + } else { + val = NULL; + } + if (ctx && (ptr == end)) { + if (type == YYJSON_TYPE_OBJ || + (type == YYJSON_TYPE_ARR && (val || idx_is_last))) { + ctx->ctn = ctn; + ctx->pre = pre; + } + } + if (!val) return_err_resolve(NULL, token - hdr); + if (ptr == end) return val; + } +} + +bool unsafe_yyjson_mut_ptr_putx(yyjson_mut_val *val, + const char *ptr, size_t ptr_len, + yyjson_mut_val *new_val, + yyjson_mut_doc *doc, + bool create_parent, bool insert_new, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err) { + + const char *hdr = ptr, *end = ptr + ptr_len, *token; + usize token_len, esc, ctn_len; + yyjson_mut_val *ctn, *key, *pre = NULL; + yyjson_mut_val *sep_ctn = NULL, *sep_key = NULL, *sep_val = NULL; + yyjson_type ctn_type; + bool idx_is_last = false; + + /* skip exist parent nodes */ + while (true) { + token = ptr_next_token(&ptr, end, &token_len, &esc); + if (unlikely(!token)) return_err_syntax(false, ptr - hdr); + ctn = val; + ctn_type = unsafe_yyjson_get_type(ctn); + if (ctn_type == YYJSON_TYPE_OBJ) { + val = ptr_mut_obj_get(ctn, token, token_len, esc, &pre); + } else if (ctn_type == YYJSON_TYPE_ARR) { + val = ptr_mut_arr_get(ctn, token, token_len, esc, &pre, + &idx_is_last); + } else return_err_resolve(false, token - hdr); + if (!val) break; + if (ptr == end) break; /* is last token */ + } + + /* create parent nodes if not exist */ + if (unlikely(ptr != end)) { /* not last token */ + if (!create_parent) return_err_resolve(false, token - hdr); + + /* add value at last index if container is array */ + if (ctn_type == YYJSON_TYPE_ARR) { + if (!idx_is_last || !insert_new) { + return_err_resolve(false, token - hdr); + } + val = yyjson_mut_obj(doc); + if (!val) return_err_alloc(false); + + /* delay attaching until all operations are completed */ + sep_ctn = ctn; + sep_key = NULL; + sep_val = val; + + /* move to next token */ + ctn = val; + val = NULL; + ctn_type = YYJSON_TYPE_OBJ; + token = ptr_next_token(&ptr, end, &token_len, &esc); + if (unlikely(!token)) return_err_resolve(false, token - hdr); + } + + /* container is object, create parent nodes */ + while (ptr != end) { /* not last token */ + key = ptr_new_key(token, token_len, esc, doc); + if (!key) return_err_alloc(false); + val = yyjson_mut_obj(doc); + if (!val) return_err_alloc(false); + + /* delay attaching until all operations are completed */ + if (!sep_ctn) { + sep_ctn = ctn; + sep_key = key; + sep_val = val; + } else { + yyjson_mut_obj_add(ctn, key, val); + } + + /* move to next token */ + ctn = val; + val = NULL; + token = ptr_next_token(&ptr, end, &token_len, &esc); + if (unlikely(!token)) return_err_syntax(false, ptr - hdr); + } + } + + /* JSON pointer is resolved, insert or replace target value */ + ctn_len = unsafe_yyjson_get_len(ctn); + if (ctn_type == YYJSON_TYPE_OBJ) { + if (ctx) ctx->ctn = ctn; + if (!val || insert_new) { + /* insert new key-value pair */ + key = ptr_new_key(token, token_len, esc, doc); + if (unlikely(!key)) return_err_alloc(false); + if (ctx) ctx->pre = ctn_len ? (yyjson_mut_val *)ctn->uni.ptr : key; + unsafe_yyjson_mut_obj_add(ctn, key, new_val, ctn_len); + } else { + /* replace exist value */ + key = pre->next->next; + if (ctx) ctx->pre = pre; + if (ctx) ctx->old = val; + yyjson_mut_obj_put(ctn, key, new_val); + } + } else { + /* array */ + if (ctx && (val || idx_is_last)) ctx->ctn = ctn; + if (insert_new) { + /* append new value */ + if (val) { + pre->next = new_val; + new_val->next = val; + if (ctx) ctx->pre = pre; + unsafe_yyjson_set_len(ctn, ctn_len + 1); + } else if (idx_is_last) { + if (ctx) ctx->pre = ctn_len ? + (yyjson_mut_val *)ctn->uni.ptr : new_val; + yyjson_mut_arr_append(ctn, new_val); + } else { + return_err_resolve(false, token - hdr); + } + } else { + /* replace exist value */ + if (!val) return_err_resolve(false, token - hdr); + if (ctn_len > 1) { + new_val->next = val->next; + pre->next = new_val; + if (ctn->uni.ptr == val) ctn->uni.ptr = new_val; + } else { + new_val->next = new_val; + ctn->uni.ptr = new_val; + pre = new_val; + } + if (ctx) ctx->pre = pre; + if (ctx) ctx->old = val; + } + } + + /* all operations are completed, attach the new components to the target */ + if (unlikely(sep_ctn)) { + if (sep_key) yyjson_mut_obj_add(sep_ctn, sep_key, sep_val); + else yyjson_mut_arr_append(sep_ctn, sep_val); + } + return true; +} + +yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex( + yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, + yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { + + yyjson_mut_val *cur_val; + yyjson_ptr_ctx cur_ctx; + memset(&cur_ctx, 0, sizeof(cur_ctx)); + if (!ctx) ctx = &cur_ctx; + cur_val = unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); + if (!cur_val) return NULL; + + if (yyjson_mut_is_obj(ctx->ctn)) { + yyjson_mut_val *key = ctx->pre->next->next; + yyjson_mut_obj_put(ctx->ctn, key, new_val); + } else { + yyjson_ptr_ctx_replace(ctx, new_val); + } + ctx->old = cur_val; + return cur_val; +} + +yyjson_mut_val *unsafe_yyjson_mut_ptr_removex(yyjson_mut_val *val, + const char *ptr, + size_t len, + yyjson_ptr_ctx *ctx, + yyjson_ptr_err *err) { + yyjson_mut_val *cur_val; + yyjson_ptr_ctx cur_ctx; + memset(&cur_ctx, 0, sizeof(cur_ctx)); + if (!ctx) ctx = &cur_ctx; + cur_val = unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); + if (cur_val) { + if (yyjson_mut_is_obj(ctx->ctn)) { + yyjson_mut_val *key = ctx->pre->next->next; + yyjson_mut_obj_put(ctx->ctn, key, NULL); + } else { + yyjson_ptr_ctx_remove(ctx); + } + ctx->pre = NULL; + ctx->old = cur_val; } + return cur_val; } +/* macros for yyjson_ptr */ +#undef return_err +#undef return_err_resolve +#undef return_err_syntax +#undef return_err_alloc + /*============================================================================== - * JSON Pointer + * JSON Patch API (RFC 6902) *============================================================================*/ -/** - Get value from JSON array with a path segment (array index). - @param ptr Input the segment after `/`, output the end of segment. - @param end The end of entire JSON pointer. - @param arr JSON array (yyjson_val/yyjson_mut_val, based on `mut`). - @param mut Whether `arr` is mutable. - @return The matched value, or NULL if not matched. - */ -static_inline void *pointer_read_arr(const char **ptr, - const char *end, - void *arr, - bool mut) { - const char *hdr = *ptr; - const char *cur = hdr; - yyjson_val *i_arr = (yyjson_val *)arr; - yyjson_mut_val *m_arr = (yyjson_mut_val *)arr; - u64 idx = 0; - u8 add; - - /* start with 0 */ - if (cur < end && *cur == '0') { - *ptr = cur + 1; - return mut - ? (void *)yyjson_mut_arr_get_first(m_arr) - : (void *)yyjson_arr_get_first(i_arr); - } - - /* read whole number */ - if (cur + U64_SAFE_DIG < end) end = cur + U64_SAFE_DIG; - while (cur < end && (add = (u8)((u8)*cur - (u8)'0')) <= 9) { - cur++; - idx = idx * 10 + add; +/* JSON Patch operation */ +typedef enum patch_op { + PATCH_OP_ADD, /* path, value */ + PATCH_OP_REMOVE, /* path */ + PATCH_OP_REPLACE, /* path, value */ + PATCH_OP_MOVE, /* from, path */ + PATCH_OP_COPY, /* from, path */ + PATCH_OP_TEST, /* path, value */ + PATCH_OP_NONE /* invalid */ +} patch_op; + +static patch_op patch_op_get(yyjson_val *op) { + const char *str = op->uni.str; + switch (unsafe_yyjson_get_len(op)) { + case 3: + if (!memcmp(str, "add", 3)) return PATCH_OP_ADD; + return PATCH_OP_NONE; + case 4: + if (!memcmp(str, "move", 4)) return PATCH_OP_MOVE; + if (!memcmp(str, "copy", 4)) return PATCH_OP_COPY; + if (!memcmp(str, "test", 4)) return PATCH_OP_TEST; + return PATCH_OP_NONE; + case 6: + if (!memcmp(str, "remove", 6)) return PATCH_OP_REMOVE; + return PATCH_OP_NONE; + case 7: + if (!memcmp(str, "replace", 7)) return PATCH_OP_REPLACE; + return PATCH_OP_NONE; + default: + return PATCH_OP_NONE; } - if (cur == hdr || idx >= (u64)USIZE_MAX) return NULL; - *ptr = cur; - return mut - ? (void *)yyjson_mut_arr_get(m_arr, (usize)idx) - : (void *)yyjson_arr_get(i_arr, (usize)idx); } -/** - Get value from JSON object with a path segment (object key). - @param ptr Input the segment after `/`, output the end of segment. - @param end The end of entire JSON pointer. - @param obj JSON object (yyjson_val/yyjson_mut_val, based on `mut`). - @param mut `obj` is mutable. - @return The matched value, or NULL if not matched. - */ -static_inline void *pointer_read_obj(const char **ptr, - const char *end, - void *obj, - bool mut) { -#define BUF_SIZE 512 -#define is_escaped(cur) ((cur) < end && (*(cur) == '0' || *(cur) == '1')) -#define is_unescaped(cur) ((cur) < end && *(cur) != '/' && *(cur) != '~') -#define is_completed(cur) ((cur) == end || *(cur) == '/') - - const char *hdr = *ptr; - const char *cur = hdr; - yyjson_val *i_obj = (yyjson_val *)obj; - yyjson_mut_val *m_obj = (yyjson_mut_val *)obj; - yyjson_obj_iter i_iter; - yyjson_mut_obj_iter m_iter; - void *key; - - /* skip unescaped characters */ - while (is_unescaped(cur)) cur++; - if (likely(is_completed(cur))) { - usize len = (usize)(cur - hdr); - *ptr = cur; - return mut - ? (void *)yyjson_mut_obj_getn(m_obj, hdr, len) - : (void *)yyjson_obj_getn(i_obj, hdr, len); - } - - /* copy escaped characters to buffer */ - if (likely(end - hdr <= BUF_SIZE)) { - char buf[BUF_SIZE]; - char *dst = buf + (usize)(cur - hdr); - memcpy(buf, hdr, (usize)(cur - hdr)); - while (true) { - if (is_unescaped(cur)) { - *dst++ = *cur++; - } else if (is_completed(cur)) { - usize len = (usize)(dst - buf); - *ptr = cur; - return mut - ? (void *)yyjson_mut_obj_getn(m_obj, buf, len) - : (void *)yyjson_obj_getn(i_obj, buf, len); - } else { - cur++; /* skip '~' */ - if (unlikely(!is_escaped(cur))) return NULL; - *dst++ = (char)(*cur++ == '0' ? '~' : '/'); - } +/* macros for yyjson_patch */ +#define return_err(_code, _msg) do { \ + if (err->ptr.code == YYJSON_PTR_ERR_MEMORY_ALLOCATION) { \ + err->code = YYJSON_PATCH_ERROR_MEMORY_ALLOCATION; \ + err->msg = _msg; \ + memset(&err->ptr, 0, sizeof(yyjson_ptr_err)); \ + } else { \ + err->code = YYJSON_PATCH_ERROR_##_code; \ + err->msg = _msg; \ + err->idx = iter.idx ? iter.idx - 1 : 0; \ + } \ + return NULL; \ +} while (false) + +#define return_err_copy() \ + return_err(MEMORY_ALLOCATION, "failed to copy value") +#define return_err_key(_key) \ + return_err(MISSING_KEY, "missing key " _key) +#define return_err_val(_key) \ + return_err(INVALID_MEMBER, "invalid member " _key) + +#define ptr_get(_ptr) yyjson_mut_ptr_getx( \ + root, _ptr->uni.str, _ptr##_len, NULL, &err->ptr) +#define ptr_add(_ptr, _val) yyjson_mut_ptr_addx( \ + root, _ptr->uni.str, _ptr##_len, _val, doc, false, NULL, &err->ptr) +#define ptr_remove(_ptr) yyjson_mut_ptr_removex( \ + root, _ptr->uni.str, _ptr##_len, NULL, &err->ptr) +#define ptr_replace(_ptr, _val)yyjson_mut_ptr_replacex( \ + root, _ptr->uni.str, _ptr##_len, _val, NULL, &err->ptr) + +yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc, + yyjson_val *orig, + yyjson_val *patch, + yyjson_patch_err *err) { + + yyjson_mut_val *root; + yyjson_val *obj; + yyjson_arr_iter iter; + yyjson_patch_err err_tmp; + if (!err) err = &err_tmp; + memset(err, 0, sizeof(*err)); + memset(&iter, 0, sizeof(iter)); + + if (unlikely(!doc || !orig || !patch)) { + return_err(INVALID_PARAMETER, "input parameter is NULL"); + } + if (unlikely(!yyjson_is_arr(patch))) { + return_err(INVALID_PARAMETER, "input patch is not array"); + } + root = yyjson_val_mut_copy(doc, orig); + if (unlikely(!root)) return_err_copy(); + + /* iterate through the patch array */ + yyjson_arr_iter_init(patch, &iter); + while ((obj = yyjson_arr_iter_next(&iter))) { + patch_op op_enum; + yyjson_val *op, *path, *from = NULL, *value; + yyjson_mut_val *val = NULL, *test; + usize path_len, from_len = 0; + if (unlikely(!unsafe_yyjson_is_obj(obj))) { + return_err(INVALID_OPERATION, "JSON patch operation is not object"); } - } - - /* compare byte by byte */ - cur = hdr; - if (!mut) yyjson_obj_iter_init(i_obj, &i_iter); - else yyjson_mut_obj_iter_init(m_obj, &m_iter); - while ((key = mut ? (void *)yyjson_mut_obj_iter_next(&m_iter) - : (void *)yyjson_obj_iter_next(&i_iter))) { - const char *k_str = unsafe_yyjson_get_str(key); - const char *k_end = k_str + unsafe_yyjson_get_len(key); - while (k_str < k_end) { - if (is_unescaped(cur) && *k_str == *cur) { - k_str += 1; - cur += 1; - } else if (cur < end && *cur == '~' && is_escaped(cur + 1) && - *k_str == (*(cur + 1) == '0' ? '~' : '/')) { - k_str += 1; - cur += 2; - } else { + + /* get required member: op */ + op = yyjson_obj_get(obj, "op"); + if (unlikely(!op)) return_err_key("`op`"); + if (unlikely(!yyjson_is_str(op))) return_err_val("`op`"); + op_enum = patch_op_get(op); + + /* get required member: path */ + path = yyjson_obj_get(obj, "path"); + if (unlikely(!path)) return_err_key("`path`"); + if (unlikely(!yyjson_is_str(path))) return_err_val("`path`"); + path_len = unsafe_yyjson_get_len(path); + + /* get required member: value, from */ + switch ((int)op_enum) { + case PATCH_OP_ADD: case PATCH_OP_REPLACE: case PATCH_OP_TEST: + value = yyjson_obj_get(obj, "value"); + if (unlikely(!value)) return_err_key("`value`"); + val = yyjson_val_mut_copy(doc, value); + if (unlikely(!val)) return_err_copy(); + break; + case PATCH_OP_MOVE: case PATCH_OP_COPY: + from = yyjson_obj_get(obj, "from"); + if (unlikely(!from)) return_err_key("`from`"); + if (unlikely(!yyjson_is_str(from))) return_err_val("`from`"); + from_len = unsafe_yyjson_get_len(from); + break; + default: break; - } } - if (k_str == k_end && is_completed(cur)) { - *ptr = cur; - return mut - ? (void *)yyjson_mut_obj_iter_get_val((yyjson_mut_val *)key) - : (void *)yyjson_obj_iter_get_val((yyjson_val *)key); + + /* perform an operation */ + switch ((int)op_enum) { + case PATCH_OP_ADD: /* add(path, val) */ + if (unlikely(path_len == 0)) { root = val; break; } + if (unlikely(!ptr_add(path, val))) { + return_err(POINTER, "failed to add `path`"); + } + break; + case PATCH_OP_REMOVE: /* remove(path) */ + if (unlikely(!ptr_remove(path))) { + return_err(POINTER, "failed to remove `path`"); + } + break; + case PATCH_OP_REPLACE: /* replace(path, val) */ + if (unlikely(path_len == 0)) { root = val; break; } + if (unlikely(!ptr_replace(path, val))) { + return_err(POINTER, "failed to replace `path`"); + } + break; + case PATCH_OP_MOVE: /* val = remove(from), add(path, val) */ + if (unlikely(from_len == 0 && path_len == 0)) break; + val = ptr_remove(from); + if (unlikely(!val)) { + return_err(POINTER, "failed to remove `from`"); + } + if (unlikely(path_len == 0)) { root = val; break; } + if (unlikely(!ptr_add(path, val))) { + return_err(POINTER, "failed to add `path`"); + } + break; + case PATCH_OP_COPY: /* val = get(from).copy, add(path, val) */ + val = ptr_get(from); + if (unlikely(!val)) { + return_err(POINTER, "failed to get `from`"); + } + if (unlikely(path_len == 0)) { root = val; break; } + val = yyjson_mut_val_mut_copy(doc, val); + if (unlikely(!val)) return_err_copy(); + if (unlikely(!ptr_add(path, val))) { + return_err(POINTER, "failed to add `path`"); + } + break; + case PATCH_OP_TEST: /* test = get(path), test.eq(val) */ + test = ptr_get(path); + if (unlikely(!test)) { + return_err(POINTER, "failed to get `path`"); + } + if (unlikely(!yyjson_mut_equals(val, test))) { + return_err(EQUAL, "failed to test equal"); + } + break; + default: + return_err(INVALID_MEMBER, "unsupported `op`"); } } - return NULL; - -#undef BUF_SIZE -#undef is_escaped -#undef is_unescaped -#undef is_completed -} - -yyjson_api yyjson_val *unsafe_yyjson_get_pointer(yyjson_val *val, - const char *ptr, - usize len) { - const char *end = ptr + len; - ptr++; /* skip '/' */ - while (true) { - if (yyjson_is_obj(val)) { - val = (yyjson_val *)pointer_read_obj(&ptr, end, val, false); - } else if (yyjson_is_arr(val)) { - val = (yyjson_val *)pointer_read_arr(&ptr, end, val, false); - } else { - val = NULL; + return root; +} + +yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc, + yyjson_mut_val *orig, + yyjson_mut_val *patch, + yyjson_patch_err *err) { + yyjson_mut_val *root, *obj; + yyjson_mut_arr_iter iter; + yyjson_patch_err err_tmp; + if (!err) err = &err_tmp; + memset(err, 0, sizeof(*err)); + memset(&iter, 0, sizeof(iter)); + + if (unlikely(!doc || !orig || !patch)) { + return_err(INVALID_PARAMETER, "input parameter is NULL"); + } + if (unlikely(!yyjson_mut_is_arr(patch))) { + return_err(INVALID_PARAMETER, "input patch is not array"); + } + root = yyjson_mut_val_mut_copy(doc, orig); + if (unlikely(!root)) return_err_copy(); + + /* iterate through the patch array */ + yyjson_mut_arr_iter_init(patch, &iter); + while ((obj = yyjson_mut_arr_iter_next(&iter))) { + patch_op op_enum; + yyjson_mut_val *op, *path, *from = NULL, *value; + yyjson_mut_val *val = NULL, *test; + usize path_len, from_len = 0; + if (!unsafe_yyjson_is_obj(obj)) { + return_err(INVALID_OPERATION, "JSON patch operation is not object"); } - if (!val || ptr == end) return val; - if (*ptr++ != '/') return NULL; - } -} -yyjson_api yyjson_mut_val *unsafe_yyjson_mut_get_pointer(yyjson_mut_val *val, - const char *ptr, - usize len) { - const char *end = ptr + len; - ptr++; /* skip '/' */ - while (true) { - if (yyjson_mut_is_obj(val)) { - val = (yyjson_mut_val *)pointer_read_obj(&ptr, end, val, true); - } else if (yyjson_mut_is_arr(val)) { - val = (yyjson_mut_val *)pointer_read_arr(&ptr, end, val, true); - } else { - val = NULL; + /* get required member: op */ + op = yyjson_mut_obj_get(obj, "op"); + if (unlikely(!op)) return_err_key("`op`"); + if (unlikely(!yyjson_mut_is_str(op))) return_err_val("`op`"); + op_enum = patch_op_get((yyjson_val *)(void *)op); + + /* get required member: path */ + path = yyjson_mut_obj_get(obj, "path"); + if (unlikely(!path)) return_err_key("`path`"); + if (unlikely(!yyjson_mut_is_str(path))) return_err_val("`path`"); + path_len = unsafe_yyjson_get_len(path); + + /* get required member: value, from */ + switch ((int)op_enum) { + case PATCH_OP_ADD: case PATCH_OP_REPLACE: case PATCH_OP_TEST: + value = yyjson_mut_obj_get(obj, "value"); + if (unlikely(!value)) return_err_key("`value`"); + val = yyjson_mut_val_mut_copy(doc, value); + if (unlikely(!val)) return_err_copy(); + break; + case PATCH_OP_MOVE: case PATCH_OP_COPY: + from = yyjson_mut_obj_get(obj, "from"); + if (unlikely(!from)) return_err_key("`from`"); + if (unlikely(!yyjson_mut_is_str(from))) { + return_err_val("`from`"); + } + from_len = unsafe_yyjson_get_len(from); + break; + default: + break; + } + + /* perform an operation */ + switch ((int)op_enum) { + case PATCH_OP_ADD: /* add(path, val) */ + if (unlikely(path_len == 0)) { root = val; break; } + if (unlikely(!ptr_add(path, val))) { + return_err(POINTER, "failed to add `path`"); + } + break; + case PATCH_OP_REMOVE: /* remove(path) */ + if (unlikely(!ptr_remove(path))) { + return_err(POINTER, "failed to remove `path`"); + } + break; + case PATCH_OP_REPLACE: /* replace(path, val) */ + if (unlikely(path_len == 0)) { root = val; break; } + if (unlikely(!ptr_replace(path, val))) { + return_err(POINTER, "failed to replace `path`"); + } + break; + case PATCH_OP_MOVE: /* val = remove(from), add(path, val) */ + if (unlikely(from_len == 0 && path_len == 0)) break; + val = ptr_remove(from); + if (unlikely(!val)) { + return_err(POINTER, "failed to remove `from`"); + } + if (unlikely(path_len == 0)) { root = val; break; } + if (unlikely(!ptr_add(path, val))) { + return_err(POINTER, "failed to add `path`"); + } + break; + case PATCH_OP_COPY: /* val = get(from).copy, add(path, val) */ + val = ptr_get(from); + if (unlikely(!val)) { + return_err(POINTER, "failed to get `from`"); + } + if (unlikely(path_len == 0)) { root = val; break; } + val = yyjson_mut_val_mut_copy(doc, val); + if (unlikely(!val)) return_err_copy(); + if (unlikely(!ptr_add(path, val))) { + return_err(POINTER, "failed to add `path`"); + } + break; + case PATCH_OP_TEST: /* test = get(path), test.eq(val) */ + test = ptr_get(path); + if (unlikely(!test)) { + return_err(POINTER, "failed to get `path`"); + } + if (unlikely(!yyjson_mut_equals(val, test))) { + return_err(EQUAL, "failed to test equal"); + } + break; + default: + return_err(INVALID_MEMBER, "unsupported `op`"); } - if (!val || ptr == end) return val; - if (*ptr++ != '/') return NULL; } + return root; } +/* macros for yyjson_patch */ +#undef return_err +#undef return_err_copy +#undef return_err_key +#undef return_err_val +#undef ptr_get +#undef ptr_add +#undef ptr_remove +#undef ptr_replace + /*============================================================================== - * JSON Merge-Patch + * JSON Merge-Patch API (RFC 7386) *============================================================================*/ -yyjson_api yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc, - yyjson_val *orig, - yyjson_val *patch) { +yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc, + yyjson_val *orig, + yyjson_val *patch) { usize idx, max; yyjson_val *key, *orig_val, *patch_val, local_orig; yyjson_mut_val *builder, *mut_key, *mut_val, *merged_val; - + if (unlikely(!yyjson_is_obj(patch))) { return yyjson_val_mut_copy(doc, patch); } - + builder = yyjson_mut_obj(doc); if (unlikely(!builder)) return NULL; - + + memset(&local_orig, 0, sizeof(local_orig)); if (!yyjson_is_obj(orig)) { orig = &local_orig; orig->tag = builder->tag; orig->uni = builder->uni; } - + + /* If orig is contributing, copy any items not modified by the patch */ + if (orig != &local_orig) { + yyjson_obj_foreach(orig, idx, max, key, orig_val) { + patch_val = yyjson_obj_getn(patch, + unsafe_yyjson_get_str(key), + unsafe_yyjson_get_len(key)); + if (!patch_val) { + mut_key = yyjson_val_mut_copy(doc, key); + mut_val = yyjson_val_mut_copy(doc, orig_val); + if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL; + } + } + } + /* Merge items modified by the patch. */ yyjson_obj_foreach(patch, idx, max, key, patch_val) { /* null indicates the field is removed. */ @@ -1846,47 +2710,45 @@ yyjson_api yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc, merged_val = yyjson_merge_patch(doc, orig_val, patch_val); if (!yyjson_mut_obj_add(builder, mut_key, merged_val)) return NULL; } - - /* Exit early, if orig is not contributing to the final result. */ - if (orig == &local_orig) { - return builder; - } - - /* Copy over any items that weren't modified by the patch. */ - yyjson_obj_foreach(orig, idx, max, key, orig_val) { - patch_val = yyjson_obj_getn(patch, - unsafe_yyjson_get_str(key), - unsafe_yyjson_get_len(key)); - if (!patch_val) { - mut_key = yyjson_val_mut_copy(doc, key); - mut_val = yyjson_val_mut_copy(doc, orig_val); - if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL; - } - } - + return builder; } -yyjson_api yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc, - yyjson_mut_val *orig, - yyjson_mut_val *patch) { +yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc, + yyjson_mut_val *orig, + yyjson_mut_val *patch) { usize idx, max; yyjson_mut_val *key, *orig_val, *patch_val, local_orig; yyjson_mut_val *builder, *mut_key, *mut_val, *merged_val; - + if (unlikely(!yyjson_mut_is_obj(patch))) { return yyjson_mut_val_mut_copy(doc, patch); } - + builder = yyjson_mut_obj(doc); if (unlikely(!builder)) return NULL; - + + memset(&local_orig, 0, sizeof(local_orig)); if (!yyjson_mut_is_obj(orig)) { orig = &local_orig; orig->tag = builder->tag; orig->uni = builder->uni; } - + + /* If orig is contributing, copy any items not modified by the patch */ + if (orig != &local_orig) { + yyjson_mut_obj_foreach(orig, idx, max, key, orig_val) { + patch_val = yyjson_mut_obj_getn(patch, + unsafe_yyjson_get_str(key), + unsafe_yyjson_get_len(key)); + if (!patch_val) { + mut_key = yyjson_mut_val_mut_copy(doc, key); + mut_val = yyjson_mut_val_mut_copy(doc, orig_val); + if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL; + } + } + } + /* Merge items modified by the patch. */ yyjson_mut_obj_foreach(patch, idx, max, key, patch_val) { /* null indicates the field is removed. */ @@ -1900,27 +2762,12 @@ yyjson_api yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc, merged_val = yyjson_mut_merge_patch(doc, orig_val, patch_val); if (!yyjson_mut_obj_add(builder, mut_key, merged_val)) return NULL; } - - /* Exit early, if orig is not contributing to the final result. */ - if (orig == &local_orig) { - return builder; - } - - /* Copy over any items that weren't modified by the patch. */ - yyjson_mut_obj_foreach(orig, idx, max, key, orig_val) { - patch_val = yyjson_mut_obj_getn(patch, - unsafe_yyjson_get_str(key), - unsafe_yyjson_get_len(key)); - if (!patch_val) { - mut_key = yyjson_mut_val_mut_copy(doc, key); - mut_val = yyjson_mut_val_mut_copy(doc, orig_val); - if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL; - } - } - + return builder; } +#endif /* YYJSON_DISABLE_UTILS */ + /*============================================================================== @@ -2643,8 +3490,6 @@ static_inline void pow10_table_get_exp(i32 exp10, i32 *exp2) { -#if !YYJSON_DISABLE_READER - /*============================================================================== * JSON Character Matcher *============================================================================*/ @@ -2670,9 +3515,12 @@ static const char_type CHAR_TYPE_CONTAINER = 1 << 4; /** Comment character: '/'. */ static const char_type CHAR_TYPE_COMMENT = 1 << 5; -/** Line end character '\\n', '\\r', '\0'. */ +/** Line end character: '\\n', '\\r', '\0'. */ static const char_type CHAR_TYPE_LINE_END = 1 << 6; +/** Hexadecimal numeric character: [0-9a-fA-F]. */ +static const char_type CHAR_TYPE_HEX = 1 << 7; + /** Character type table (generate with misc/make_tables.c) */ static const char_type char_table[256] = { 0x44, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, @@ -2681,13 +3529,13 @@ static const char_type char_table[256] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, @@ -2734,17 +3582,22 @@ static_inline bool char_is_container(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_CONTAINER); } -/** Match a stop character in ASCII string: '"', '\', [0x00-0x1F], [0x80-0xFF]*/ +/** Match a stop character in ASCII string: '"', '\', [0x00-0x1F,0x80-0xFF]. */ static_inline bool char_is_ascii_stop(u8 c) { return char_is_type(c, (char_type)(CHAR_TYPE_ESC_ASCII | CHAR_TYPE_NON_ASCII)); } -/** Match a line end character: '\\n', '\\r', '\0'*/ +/** Match a line end character: '\\n', '\\r', '\0'. */ static_inline bool char_is_line_end(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_LINE_END); } +/** Match a hexadecimal numeric character: [0-9a-fA-F]. */ +static_inline bool char_is_hex(u8 c) { + return char_is_type(c, (char_type)CHAR_TYPE_HEX); +} + /*============================================================================== @@ -2830,6 +3683,8 @@ static_inline bool digi_is_digit_or_fp(u8 d) { +#if !YYJSON_DISABLE_READER + /*============================================================================== * Hex Character Reader * This function is used by JSON reader to read escaped characters. @@ -2879,7 +3734,7 @@ static const u8 hex_conv_table[256] = { /** Scans an escaped character sequence as a UTF-16 code unit (branchless). e.g. "\\u005C" should pass "005C" as `cur`. - + This requires the string has 4-byte zero padding. */ static_inline bool read_hex_u16(const u8 *cur, u16 *val) { @@ -2939,7 +3794,6 @@ static_inline bool read_null(u8 **ptr, yyjson_val *val) { /** Read 'Inf' or 'Infinity' literal (ignoring case). */ static_inline bool read_inf(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) { -#if !YYJSON_DISABLE_NON_STANDARD u8 *hdr = *ptr - sign; u8 *cur = *ptr; u8 **end = ptr; @@ -2968,13 +3822,11 @@ static_inline bool read_inf(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) { } return true; } -#endif return false; } /** Read 'NaN' literal (ignoring case). */ static_inline bool read_nan(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) { -#if !YYJSON_DISABLE_NON_STANDARD u8 *hdr = *ptr - sign; u8 *cur = *ptr; u8 **end = ptr; @@ -2995,7 +3847,6 @@ static_inline bool read_nan(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) { } return true; } -#endif return false; } @@ -3010,40 +3861,40 @@ static_inline bool read_inf_or_nan(bool sign, u8 **ptr, u8 **pre, /** Read a JSON number as raw string. */ static_noinline bool read_number_raw(u8 **ptr, u8 **pre, - bool ext, + yyjson_read_flag flg, yyjson_val *val, const char **msg) { - + #define return_err(_pos, _msg) do { \ *msg = _msg; \ *end = _pos; \ return false; \ } while (false) - + #define return_raw() do { \ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ val->uni.str = (const char *)hdr; \ *pre = cur; *end = cur; return true; \ } while (false) - + u8 *hdr = *ptr; u8 *cur = *ptr; u8 **end = ptr; - + /* add null-terminator for previous raw string */ if (*pre) **pre = '\0'; - + /* skip sign */ cur += (*cur == '-'); - + /* read first digit, check leading zero */ if (unlikely(!digi_is_digit(*cur))) { - if (unlikely(ext)) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { if (read_inf_or_nan(*hdr == '-', &cur, pre, val)) return_raw(); } return_err(cur, "no digit after minus sign"); } - + /* read integral part */ if (*cur == '0') { cur++; @@ -3055,7 +3906,7 @@ static_noinline bool read_number_raw(u8 **ptr, while (digi_is_digit(*cur)) cur++; if (!digi_is_fp(*cur)) return_raw(); } - + /* read fraction part */ if (*cur == '.') { cur++; @@ -3064,7 +3915,7 @@ static_noinline bool read_number_raw(u8 **ptr, } while (digi_is_digit(*cur)) cur++; } - + /* read exponent part */ if (digi_is_exp(*cur)) { cur += 1 + digi_is_sign(cur[1]); @@ -3073,16 +3924,16 @@ static_noinline bool read_number_raw(u8 **ptr, } while (digi_is_digit(*cur)) cur++; } - + return_raw(); - + #undef return_err #undef return_raw } /** Skips spaces and comments as many as possible. - + It will return false in these cases: 1. No character is skipped. The 'end' pointer is set as input cursor. 2. A multiline comment is not closed. The 'end' pointer is set as the head @@ -3125,6 +3976,115 @@ static_noinline bool skip_spaces_and_comments(u8 **ptr) { return hdr != cur; } +/** + Check truncated string. + Returns true if `cur` match `str` but is truncated. + */ +static_inline bool is_truncated_str(u8 *cur, u8 *end, + const char *str, + bool case_sensitive) { + usize len = strlen(str); + if (cur + len <= end || end <= cur) return false; + if (case_sensitive) { + return memcmp(cur, str, (usize)(end - cur)) == 0; + } + for (; cur < end; cur++, str++) { + if ((*cur != (u8)*str) && (*cur != (u8)*str - 'a' + 'A')) { + return false; + } + } + return true; +} + +/** + Check truncated JSON on parsing errors. + Returns true if the input is valid but truncated. + */ +static_noinline bool is_truncated_end(u8 *hdr, u8 *cur, u8 *end, + yyjson_read_code code, + yyjson_read_flag flg) { + if (cur >= end) return true; + if (code == YYJSON_READ_ERROR_LITERAL) { + if (is_truncated_str(cur, end, "true", true) || + is_truncated_str(cur, end, "false", true) || + is_truncated_str(cur, end, "null", true)) { + return true; + } + } + if (code == YYJSON_READ_ERROR_UNEXPECTED_CHARACTER || + code == YYJSON_READ_ERROR_INVALID_NUMBER || + code == YYJSON_READ_ERROR_LITERAL) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { + if (*cur == '-') cur++; + if (is_truncated_str(cur, end, "infinity", false) || + is_truncated_str(cur, end, "nan", false)) { + return true; + } + } + } + if (code == YYJSON_READ_ERROR_UNEXPECTED_CONTENT) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { + if (hdr + 3 <= cur && + is_truncated_str(cur - 3, end, "infinity", false)) { + return true; /* e.g. infin would be read as inf + in */ + } + } + } + if (code == YYJSON_READ_ERROR_INVALID_STRING) { + usize len = (usize)(end - cur); + + /* unicode escape sequence */ + if (*cur == '\\') { + if (len == 1) return true; + if (len <= 5) { + if (*++cur != 'u') return false; + for (++cur; cur < end; cur++) { + if (!char_is_hex(*cur)) return false; + } + return true; + } + return false; + } + + /* 2 to 4 bytes UTF-8, see `read_string()` for details. */ + if (*cur & 0x80) { + u8 c0 = cur[0], c1 = cur[1], c2 = cur[2]; + if (len == 1) { + /* 2 bytes UTF-8, truncated */ + if ((c0 & 0xE0) == 0xC0 && (c0 & 0x1E) != 0x00) return true; + /* 3 bytes UTF-8, truncated */ + if ((c0 & 0xF0) == 0xE0) return true; + /* 4 bytes UTF-8, truncated */ + if ((c0 & 0xF8) == 0xF0 && (c0 & 0x07) <= 0x04) return true; + } + if (len == 2) { + /* 3 bytes UTF-8, truncated */ + if ((c0 & 0xF0) == 0xE0 && + (c1 & 0xC0) == 0x80) { + u8 pat = (u8)(((c0 & 0x0F) << 1) | ((c1 & 0x20) >> 5)); + return 0x01 <= pat && pat != 0x1B; + } + /* 4 bytes UTF-8, truncated */ + if ((c0 & 0xF8) == 0xF0 && + (c1 & 0xC0) == 0x80) { + u8 pat = (u8)(((c0 & 0x07) << 2) | ((c1 & 0x30) >> 4)); + return 0x01 <= pat && pat <= 0x10; + } + } + if (len == 3) { + /* 4 bytes UTF-8, truncated */ + if ((c0 & 0xF8) == 0xF0 && + (c1 & 0xC0) == 0x80 && + (c2 & 0xC0) == 0x80) { + u8 pat = (u8)(((c0 & 0x07) << 2) | ((c1 & 0x30) >> 4)); + return 0x01 <= pat && pat <= 0x10; + } + } + } + } + return false; +} + #if YYJSON_HAS_IEEE_754 && !YYJSON_DISABLE_FAST_FP_CONV /* FP_READER */ @@ -3275,12 +4235,12 @@ static_inline void bigint_set_u64(bigint *big, u64 val) { /** Set a bigint with floating point number string. */ static_noinline void bigint_set_buf(bigint *big, u64 sig, i32 *exp, u8 *sig_cut, u8 *sig_end, u8 *dot_pos) { - + if (unlikely(!sig_cut)) { /* no digit cut, set significant part only */ bigint_set_u64(big, sig); return; - + } else { /* some digits were cut, read them from 'sig_cut' to 'sig_end' */ u8 *hdr = sig_cut; @@ -3290,7 +4250,7 @@ static_noinline void bigint_set_buf(bigint *big, u64 sig, i32 *exp, bool dig_big_cut = false; bool has_dot = (hdr < dot_pos) & (dot_pos < sig_end); u32 dig_len_total = U64_SAFE_DIG + (u32)(sig_end - hdr) - has_dot; - + sig -= (*sig_cut >= '5'); /* sig was rounded before */ if (dig_len_total > F64_MAX_DEC_DIG) { dig_big_cut = true; @@ -3299,7 +4259,7 @@ static_noinline void bigint_set_buf(bigint *big, u64 sig, i32 *exp, dig_len_total = (F64_MAX_DEC_DIG + 1); } *exp -= (i32)dig_len_total - U64_SAFE_DIG; - + big->used = 1; big->bits[0] = sig; while (cur < sig_end) { @@ -3363,14 +4323,14 @@ static_inline u64 diy_fp_to_ieee_raw(diy_fp fp) { i32 exp = fp.exp; u32 lz_bits; if (unlikely(fp.sig == 0)) return 0; - + lz_bits = u64_lz_bits(sig); sig <<= lz_bits; sig >>= F64_BITS - F64_SIG_FULL_BITS; exp -= (i32)lz_bits; exp += F64_BITS - F64_SIG_FULL_BITS; exp += F64_SIG_BITS; - + if (unlikely(exp >= F64_MAX_BIN_EXP)) { /* overflow */ return F64_RAW_INF; @@ -3404,7 +4364,7 @@ static const f64 f64_pow10_table[] = { /** Read a JSON number. - + 1. This function assume that the floating-point number is in IEEE-754 format. 2. This function support uint64/int64/double number. If an integer number cannot fit in uint64/int64, it will returns as a double number. If a double @@ -3413,69 +4373,83 @@ static const f64 f64_pow10_table[] = { */ static_inline bool read_number(u8 **ptr, u8 **pre, - bool ext, + yyjson_read_flag flg, yyjson_val *val, const char **msg) { - + #define return_err(_pos, _msg) do { \ *msg = _msg; \ *end = _pos; \ return false; \ } while (false) - + +#define return_0() do { \ + val->tag = YYJSON_TYPE_NUM | (u8)((u8)sign << 3); \ + val->uni.u64 = 0; \ + *end = cur; return true; \ +} while (false) + #define return_i64(_v) do { \ val->tag = YYJSON_TYPE_NUM | (u8)((u8)sign << 3); \ val->uni.u64 = (u64)(sign ? (u64)(~(_v) + 1) : (u64)(_v)); \ *end = cur; return true; \ } while (false) - + #define return_f64(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.f64 = sign ? -(f64)(_v) : (f64)(_v); \ *end = cur; return true; \ } while (false) - -#define return_f64_raw(_v) do { \ + +#define return_f64_bin(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.u64 = ((u64)sign << 63) | (u64)(_v); \ *end = cur; return true; \ } while (false) - + #define return_inf() do { \ - if (unlikely(ext)) return_f64_raw(F64_RAW_INF); \ + if (has_read_flag(BIGNUM_AS_RAW)) return_raw(); \ + if (has_read_flag(ALLOW_INF_AND_NAN)) return_f64_bin(F64_RAW_INF); \ else return_err(hdr, "number is infinity when parsed as double"); \ } while (false) - + +#define return_raw() do { \ + if (*pre) **pre = '\0'; /* add null-terminator for previous raw string */ \ + val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ + val->uni.str = (const char *)hdr; \ + *pre = cur; *end = cur; return true; \ +} while (false) + u8 *sig_cut = NULL; /* significant part cutting position for long number */ u8 *sig_end = NULL; /* significant part ending position */ u8 *dot_pos = NULL; /* decimal point position */ - + u64 sig = 0; /* significant part of the number */ i32 exp = 0; /* exponent part of the number */ - + bool exp_sign; /* temporary exponent sign from literal part */ i64 exp_sig = 0; /* temporary exponent number from significant part */ i64 exp_lit = 0; /* temporary exponent number from exponent literal part */ u64 num; /* temporary number for reading */ u8 *tmp; /* temporary cursor for reading */ - + u8 *hdr = *ptr; u8 *cur = *ptr; u8 **end = ptr; bool sign; - - /* read number as raw string if has flag */ - if (unlikely(pre)) { - return read_number_raw(ptr, pre, ext, val, msg); + + /* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */ + if (unlikely(pre && !has_read_flag(BIGNUM_AS_RAW))) { + return read_number_raw(ptr, pre, flg, val, msg); } - + sign = (*hdr == '-'); cur += sign; - + /* begin with a leading zero or non-digit */ if (unlikely(!digi_is_nonzero(*cur))) { /* 0 or non-digit char */ if (unlikely(*cur != '0')) { /* non-digit char */ - if (unlikely(ext)) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { if (read_inf_or_nan(sign, &cur, pre, val)) { *end = cur; return true; @@ -3484,7 +4458,7 @@ static_inline bool read_number(u8 **ptr, return_err(cur, "no digit after minus sign"); } /* begin with 0 */ - if (likely(!digi_is_digit_or_fp(*++cur))) return_i64(0); + if (likely(!digi_is_digit_or_fp(*++cur))) return_0(); if (likely(*cur == '.')) { dot_pos = cur++; if (unlikely(!digi_is_digit(*cur))) { @@ -3508,15 +4482,15 @@ static_inline bool read_number(u8 **ptr, } while (digi_is_digit(*++cur)); } - return_f64_raw(0); + return_f64_bin(0); } - + /* begin with non-zero digit */ sig = (u64)(*cur - '0'); - + /* Read integral part, same as the following code. - + for (int i = 1; i <= 18; i++) { num = cur[i] - '0'; if (num <= 9) sig = num + sig * 10; @@ -3526,21 +4500,22 @@ static_inline bool read_number(u8 **ptr, #define expr_intg(i) \ if (likely((num = (u64)(cur[i] - (u8)'0')) <= 9)) sig = num + sig * 10; \ else { goto digi_sepr_##i; } - repeat_in_1_18(expr_intg); + repeat_in_1_18(expr_intg) #undef expr_intg - - + + cur += 19; /* skip continuous 19 digits */ if (!digi_is_digit_or_fp(*cur)) { /* this number is an integer consisting of 19 digits */ if (sign && (sig > ((u64)1 << 63))) { /* overflow */ + if (has_read_flag(BIGNUM_AS_RAW)) return_raw(); return_f64(normalized_u64_to_f64(sig)); } return_i64(sig); } goto digi_intg_more; /* read more digits in integral part */ - - + + /* process first non-digit character */ #define expr_sepr(i) \ digi_sepr_##i: \ @@ -3550,8 +4525,8 @@ static_inline bool read_number(u8 **ptr, cur += i; sig_end = cur; goto digi_exp_more; repeat_in_1_18(expr_sepr) #undef expr_sepr - - + + /* read fraction part */ #define expr_frac(i) \ digi_frac_##i: \ @@ -3560,12 +4535,12 @@ static_inline bool read_number(u8 **ptr, else { goto digi_stop_##i; } repeat_in_1_18(expr_frac) #undef expr_frac - + cur += 20; /* skip 19 digits and 1 decimal point */ if (!digi_is_digit(*cur)) goto digi_frac_end; /* fraction part end */ goto digi_frac_more; /* read more digits in fraction part */ - - + + /* significant part end */ #define expr_stop(i) \ digi_stop_##i: \ @@ -3573,8 +4548,8 @@ static_inline bool read_number(u8 **ptr, goto digi_frac_end; repeat_in_1_18(expr_stop) #undef expr_stop - - + + /* read more digits in integral part */ digi_intg_more: if (digi_is_digit(*cur)) { @@ -3586,31 +4561,37 @@ static_inline bool read_number(u8 **ptr, sig = num + sig * 10; cur++; /* convert to double if overflow */ - if (sign) return_f64(normalized_u64_to_f64(sig)); + if (sign) { + if (has_read_flag(BIGNUM_AS_RAW)) return_raw(); + return_f64(normalized_u64_to_f64(sig)); + } return_i64(sig); } } } - + if (digi_is_exp(*cur)) { dot_pos = cur; goto digi_exp_more; } - + if (*cur == '.') { dot_pos = cur++; if (!digi_is_digit(*cur)) { return_err(cur, "no digit after decimal point"); } } - - + + /* read more digits in fraction part */ digi_frac_more: sig_cut = cur; /* too large to fit in u64, excess digits need to be cut */ sig += (*cur >= '5'); /* round */ while (digi_is_digit(*++cur)); if (!dot_pos) { + if (!digi_is_fp(*cur) && has_read_flag(BIGNUM_AS_RAW)) { + return_raw(); /* it's a large integer */ + } dot_pos = cur; if (*cur == '.') { if (!digi_is_digit(*++cur)) { @@ -3621,7 +4602,7 @@ static_inline bool read_number(u8 **ptr, } exp_sig = (i64)(dot_pos - sig_cut); exp_sig += (dot_pos < sig_cut); - + /* ignore trailing zeros */ tmp = cur - 1; while (*tmp == '0' || *tmp == '.') tmp--; @@ -3630,11 +4611,11 @@ static_inline bool read_number(u8 **ptr, } else { sig_end = cur; } - + if (digi_is_exp(*cur)) goto digi_exp_more; goto digi_exp_finish; - - + + /* fraction part end */ digi_frac_end: if (unlikely(dot_pos + 1 == cur)) { @@ -3644,15 +4625,15 @@ static_inline bool read_number(u8 **ptr, exp_sig = -(i64)((u64)(cur - dot_pos) - 1); if (likely(!digi_is_exp(*cur))) { if (unlikely(exp_sig < F64_MIN_DEC_EXP - 19)) { - return_f64_raw(0); /* underflow */ + return_f64_bin(0); /* underflow */ } exp = (i32)exp_sig; goto digi_finish; } else { goto digi_exp_more; } - - + + /* read exponent part */ digi_exp_more: exp_sign = (*++cur == '-'); @@ -3661,7 +4642,7 @@ static_inline bool read_number(u8 **ptr, return_err(cur, "no digit after exponent sign"); } while (*cur == '0') cur++; - + /* read exponent literal */ tmp = cur; while (digi_is_digit(*cur)) { @@ -3669,37 +4650,37 @@ static_inline bool read_number(u8 **ptr, } if (unlikely(cur - tmp >= U64_SAFE_DIG)) { if (exp_sign) { - return_f64_raw(0); /* underflow */ + return_f64_bin(0); /* underflow */ } else { return_inf(); /* overflow */ } } exp_sig += exp_sign ? -exp_lit : exp_lit; - - + + /* validate exponent value */ digi_exp_finish: if (unlikely(exp_sig < F64_MIN_DEC_EXP - 19)) { - return_f64_raw(0); /* underflow */ + return_f64_bin(0); /* underflow */ } if (unlikely(exp_sig > F64_MAX_DEC_EXP)) { return_inf(); /* overflow */ } exp = (i32)exp_sig; - - + + /* all digit read finished */ digi_finish: - + /* Fast path 1: - + 1. The floating-point number calculation should be accurate, see the comments of macro `YYJSON_DOUBLE_MATH_CORRECT`. 2. Correct rounding should be performed (fegetround() == FE_TONEAREST). 3. The input of floating point number calculation does not lose precision, which means: 64 - leading_zero(input) - trailing_zero(input) < 53. - + We don't check all available inputs here, because that would make the code more complicated, and not friendly to branch predictor. */ @@ -3716,10 +4697,10 @@ static_inline bool read_number(u8 **ptr, return_f64(dbl); } #endif - + /* Fast path 2: - + To keep it simple, we only accept normal number here, let the slow path to handle subnormal and infinity number. */ @@ -3729,16 +4710,16 @@ static_inline bool read_number(u8 **ptr, /* The result value is exactly equal to (sig * 10^exp), the exponent part (10^exp) can be converted to (sig2 * 2^exp2). - + The sig2 can be an infinite length number, only the highest 128 bits is cached in the pow10_sig_table. - + Now we have these bits: sig1 (normalized 64bit) : aaaaaaaa sig2 (higher 64bit) : bbbbbbbb sig2_ext (lower 64bit) : cccccccc sig2_cut (extra unknown bits) : dddddddddddd.... - + And the calculation process is: ---------------------------------------- aaaaaaaa * @@ -3752,17 +4733,17 @@ static_inline bool read_number(u8 **ptr, [hi2___][lo2___] + [unknown___________....] ---------------------------------------- - + The addition with carry may affect higher bits, but if there is a 0 in higher bits, the bits higher than 0 will not be affected. - + `lo2` + `unknown` may get a carry bit and may affect `hi2`, the max value of `hi2` is 0xFFFFFFFFFFFFFFFE, so `hi2` will not overflow. - + `lo` + `hi2` may also get a carry bit and may affect `hi`, but only the highest significant 53 bits of `hi` is needed. If there is a 0 in the lower bits of `hi`, then all the following bits can be dropped. - + To convert the result to IEEE-754 double number, we need to perform correct rounding: 1. if bit 54 is 0, round down, @@ -3770,30 +4751,30 @@ static_inline bool read_number(u8 **ptr, 3. if bit 54 is 1 and all bits beyond bit 54 are 0, round to even, as the extra bits is unknown, this case will not be handled here. */ - + u64 raw; u64 sig1, sig2, sig2_ext, hi, lo, hi2, lo2, add, bits; i32 exp2; u32 lz; bool exact = false, carry, round_up; - + /* convert (10^exp) to (sig2 * 2^exp2) */ pow10_table_get_sig(exp, &sig2, &sig2_ext); pow10_table_get_exp(exp, &exp2); - + /* normalize and multiply */ lz = u64_lz_bits(sig); sig1 = sig << lz; exp2 -= (i32)lz; u128_mul(sig1, sig2, &hi, &lo); - + /* The `hi` is in range [0x4000000000000000, 0xFFFFFFFFFFFFFFFE], To get normalized value, `hi` should be shifted to the left by 0 or 1. - + The highest significant 53 bits is used by IEEE-754 double number, and the bit 54 is used to detect rounding direction. - + The lowest (64 - 54 - 1) bits is used to check whether it contains 0. */ bits = hi & (((u64)1 << (64 - 54 - 1)) - 1); @@ -3805,7 +4786,7 @@ static_inline bool read_number(u8 **ptr, after `0`. */ exact = true; - + } else { /* (bits == 0 || bits == 0x1FF) @@ -3813,7 +4794,7 @@ static_inline bool read_number(u8 **ptr, lower bits with another 64-bit multiplication. */ u128_mul(sig1, sig2_ext, &hi2, &lo2); - + add = lo + hi2; if (add + 1 > (u64)1) { /* @@ -3828,38 +4809,38 @@ static_inline bool read_number(u8 **ptr, exact = true; } } - + if (exact) { /* normalize */ lz = hi < ((u64)1 << 63); hi <<= lz; exp2 -= (i32)lz; exp2 += 64; - + /* test the bit 54 and get rounding direction */ round_up = (hi & ((u64)1 << (64 - 54))) > (u64)0; hi += (round_up ? ((u64)1 << (64 - 54)) : (u64)0); - + /* test overflow */ if (hi < ((u64)1 << (64 - 54))) { hi = ((u64)1 << 63); exp2 += 1; } - + /* This is a normal number, convert it to IEEE-754 format. */ hi >>= F64_BITS - F64_SIG_FULL_BITS; exp2 += F64_BITS - F64_SIG_FULL_BITS + F64_SIG_BITS; exp2 += F64_EXP_BIAS; raw = ((u64)exp2 << F64_SIG_BITS) | (hi & F64_SIG_MASK); - return_f64_raw(raw); + return_f64_bin(raw); } } - + /* Slow path: read double number exactly with diyfp. 1. Use cached diyfp to get an approximation value. 2. Use bigcomp to check the approximation value if needed. - + This algorithm refers to google's double-conversion project: https://github.com/google/double-conversion */ @@ -3871,7 +4852,7 @@ static_inline bool read_number(u8 **ptr, const i32 DIY_SIG_BITS = 64; const i32 EXP_BIAS = F64_EXP_BIAS + F64_SIG_BITS; const i32 EXP_SUBNORMAL = -EXP_BIAS + 1; - + u64 fp_err; u32 bits; i32 order_of_magnitude; @@ -3879,32 +4860,32 @@ static_inline bool read_number(u8 **ptr, i32 precision_digits_count; u64 precision_bits; u64 half_way; - + u64 raw; diy_fp fp, fp_upper; bigint big_full, big_comp; i32 cmp; - + fp.sig = sig; fp.exp = 0; fp_err = sig_cut ? (u64)(ERR_ULP / 2) : (u64)0; - + /* normalize */ bits = u64_lz_bits(fp.sig); fp.sig <<= bits; fp.exp -= (i32)bits; fp_err <<= bits; - + /* multiply and add error */ fp = diy_fp_mul(fp, diy_fp_get_cached_pow10(exp)); fp_err += (u64)ERR_CACHED_POW + (fp_err != 0) + (u64)ERR_MUL_FIXED; - + /* normalize */ bits = u64_lz_bits(fp.sig); fp.sig <<= bits; fp.exp -= (i32)bits; fp_err <<= bits; - + /* effective significand */ order_of_magnitude = DIY_SIG_BITS + fp.exp; if (likely(order_of_magnitude >= EXP_SUBNORMAL + F64_SIG_FULL_BITS)) { @@ -3914,7 +4895,7 @@ static_inline bool read_number(u8 **ptr, } else { effective_significand_size = order_of_magnitude - EXP_SUBNORMAL; } - + /* precision digits count */ precision_digits_count = DIY_SIG_BITS - effective_significand_size; if (unlikely(precision_digits_count + ERR_ULP_LOG >= DIY_SIG_BITS)) { @@ -3924,27 +4905,27 @@ static_inline bool read_number(u8 **ptr, fp_err = (fp_err >> shr) + 1 + (u32)ERR_ULP; precision_digits_count -= shr; } - + /* half way */ precision_bits = fp.sig & (((u64)1 << precision_digits_count) - 1); precision_bits *= (u32)ERR_ULP; half_way = (u64)1 << (precision_digits_count - 1); half_way *= (u32)ERR_ULP; - + /* rounding */ fp.sig >>= precision_digits_count; fp.sig += (precision_bits >= half_way + fp_err); fp.exp += precision_digits_count; - + /* get IEEE double raw value */ raw = diy_fp_to_ieee_raw(fp); if (unlikely(raw == F64_RAW_INF)) return_inf(); if (likely(precision_bits <= half_way - fp_err || precision_bits >= half_way + fp_err)) { - return_f64_raw(raw); /* number is accurate */ + return_f64_bin(raw); /* number is accurate */ } /* now the number is the correct value, or the next lower value */ - + /* upper boundary */ if (raw & F64_EXP_MASK) { fp_upper.sig = (raw & F64_SIG_MASK) + ((u64)1 << F64_SIG_BITS); @@ -3957,7 +4938,7 @@ static_inline bool read_number(u8 **ptr, fp_upper.sig <<= 1; fp_upper.exp -= 1; fp_upper.sig += 1; /* add half ulp */ - + /* compare with bigint */ bigint_set_buf(&big_full, sig, &exp, sig_cut, sig_end, dot_pos); bigint_set_u64(&big_comp, fp_upper.sig); @@ -3979,17 +4960,18 @@ static_inline bool read_number(u8 **ptr, /* falls midway, round to even */ raw += (raw & 1); } - + if (unlikely(raw == F64_RAW_INF)) return_inf(); - return_f64_raw(raw); + return_f64_bin(raw); } - -#undef has_flag + #undef return_err #undef return_inf +#undef return_0 #undef return_i64 #undef return_f64 -#undef return_f64_raw +#undef return_f64_bin +#undef return_raw } @@ -4001,36 +4983,55 @@ static_inline bool read_number(u8 **ptr, This is a fallback function if the custom number reader is disabled. This function use libc's strtod() to read floating-point number. */ -static_noinline bool read_number(u8 **ptr, - u8 **pre, - bool ext, - yyjson_val *val, - const char **msg) { - +static_inline bool read_number(u8 **ptr, + u8 **pre, + yyjson_read_flag flg, + yyjson_val *val, + const char **msg) { + #define return_err(_pos, _msg) do { \ *msg = _msg; \ *end = _pos; \ return false; \ } while (false) - + +#define return_0() do { \ + val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); \ + val->uni.u64 = 0; \ + *end = cur; return true; \ +} while (false) + #define return_i64(_v) do { \ val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); \ val->uni.u64 = (u64)(sign ? (u64)(~(_v) + 1) : (u64)(_v)); \ *end = cur; return true; \ } while (false) - + #define return_f64(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.f64 = sign ? -(f64)(_v) : (f64)(_v); \ *end = cur; return true; \ } while (false) - -#define return_f64_raw(_v) do { \ + +#define return_f64_bin(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.u64 = ((u64)sign << 63) | (u64)(_v); \ *end = cur; return true; \ } while (false) - + +#define return_inf() do { \ + if (has_read_flag(BIGNUM_AS_RAW)) return_raw(); \ + if (has_read_flag(ALLOW_INF_AND_NAN)) return_f64_bin(F64_RAW_INF); \ + else return_err(hdr, "number is infinity when parsed as double"); \ +} while (false) + +#define return_raw() do { \ + if (*pre) **pre = '\0'; /* add null-terminator for previous raw string */ \ + val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ + val->uni.str = (const char *)hdr; \ + *pre = cur; *end = cur; return true; \ +} while (false) + u64 sig, num; u8 *hdr = *ptr; u8 *cur = *ptr; @@ -4038,19 +5039,19 @@ static_noinline bool read_number(u8 **ptr, u8 *dot = NULL; u8 *f64_end = NULL; bool sign; - - /* read number as raw string if has flag */ - if (unlikely(pre)) { - return read_number_raw(ptr, pre, ext, val, msg); + + /* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */ + if (unlikely(pre && !has_read_flag(BIGNUM_AS_RAW))) { + return read_number_raw(ptr, pre, flg, val, msg); } - + sign = (*hdr == '-'); cur += sign; sig = (u8)(*cur - '0'); - + /* read first digit, check leading zero */ if (unlikely(!digi_is_digit(*cur))) { - if (unlikely(ext)) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { if (read_inf_or_nan(sign, &cur, pre, val)) { *end = cur; return true; @@ -4063,17 +5064,17 @@ static_noinline bool read_number(u8 **ptr, if (unlikely(digi_is_digit(*cur))) { return_err(cur - 1, "number with leading zero is not allowed"); } - if (!digi_is_fp(*cur)) return_i64(0); + if (!digi_is_fp(*cur)) return_0(); goto read_double; } - + /* read continuous digits, up to 19 characters */ #define expr_intg(i) \ if (likely((num = (u64)(cur[i] - (u8)'0')) <= 9)) sig = num + sig * 10; \ else { cur += i; goto intg_end; } - repeat_in_1_18(expr_intg); + repeat_in_1_18(expr_intg) #undef expr_intg - + /* here are 19 continuous digits, skip them */ cur += 19; if (digi_is_digit(cur[0]) && !digi_is_digit_or_fp(cur[1])) { @@ -4083,24 +5084,31 @@ static_noinline bool read_number(u8 **ptr, (sig == (U64_MAX / 10) && num <= (U64_MAX % 10))) { sig = num + sig * 10; cur++; - if (sign) return_f64(normalized_u64_to_f64(sig)); + if (sign) { + if (has_read_flag(BIGNUM_AS_RAW)) return_raw(); + return_f64(normalized_u64_to_f64(sig)); + } return_i64(sig); } } - + intg_end: /* continuous digits ended */ if (!digi_is_digit_or_fp(*cur)) { /* this number is an integer consisting of 1 to 19 digits */ if (sign && (sig > ((u64)1 << 63))) { + if (has_read_flag(BIGNUM_AS_RAW)) return_raw(); return_f64(normalized_u64_to_f64(sig)); } return_i64(sig); } - + read_double: /* this number should be read as double */ while (digi_is_digit(*cur)) cur++; + if (!digi_is_fp(*cur) && has_read_flag(BIGNUM_AS_RAW)) { + return_raw(); /* it's a large integer */ + } if (*cur == '.') { /* skip fraction part */ dot = cur; @@ -4120,43 +5128,47 @@ static_noinline bool read_number(u8 **ptr, cur++; while (digi_is_digit(*cur)) cur++; } - + /* libc's strtod() is used to parse the floating-point number. - + Note that the decimal point character used by strtod() is locale-dependent, and the rounding direction may affected by fesetround(). - + For currently known locales, (en, zh, ja, ko, am, he, hi) use '.' as the decimal point, while other locales use ',' as the decimal point. - + Here strtod() is called twice for different locales, but if another thread happens calls setlocale() between two strtod(), parsing may still fail. */ val->uni.f64 = strtod((const char *)hdr, (char **)&f64_end); if (unlikely(f64_end != cur)) { + /* replace '.' with ',' for locale */ bool cut = (*cur == ','); - if (dot) *dot = ','; if (cut) *cur = ' '; + if (dot) *dot = ','; val->uni.f64 = strtod((const char *)hdr, (char **)&f64_end); + /* restore ',' to '.' */ if (cut) *cur = ','; + if (dot) *dot = '.'; if (unlikely(f64_end != cur)) { return_err(hdr, "strtod() failed to parse the number"); } } - if (unlikely(val->uni.f64 == HUGE_VAL || val->uni.f64 == -HUGE_VAL)) { - if (!ext) { - return_err(hdr, "number is infinity when parsed as double"); - } + if (unlikely(val->uni.f64 >= HUGE_VAL || val->uni.f64 <= -HUGE_VAL)) { + return_inf(); } val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; *end = cur; return true; - -#undef has_flag + #undef return_err +#undef return_0 #undef return_i64 #undef return_f64 +#undef return_f64_bin +#undef return_inf +#undef return_raw } #endif /* FP_READER */ @@ -4255,6 +5267,7 @@ static_inline bool read_string(u8 **ptr, const u32 b4_err0 = 0x00000004UL; const u32 b4_err1 = 0x00003003UL; #else + /* this should be evaluated at compile-time */ v32_uni b1_mask_uni = {{ 0x80, 0x00, 0x00, 0x00 }}; v32_uni b1_patt_uni = {{ 0x00, 0x00, 0x00, 0x00 }}; v32_uni b2_mask_uni = {{ 0xE0, 0xC0, 0x00, 0x00 }}; @@ -4284,7 +5297,7 @@ static_inline bool read_string(u8 **ptr, u32 b4_err0 = b4_err0_uni.u; u32 b4_err1 = b4_err1_uni.u; #endif - + #define is_valid_seq_1(uni) ( \ ((uni & b1_mask) == b1_patt) \ ) @@ -4293,84 +5306,85 @@ static_inline bool read_string(u8 **ptr, ((uni & b2_mask) == b2_patt) && \ ((uni & b2_requ)) \ ) - + #define is_valid_seq_3(uni) ( \ ((uni & b3_mask) == b3_patt) && \ ((tmp = (uni & b3_requ))) && \ ((tmp != b3_erro)) \ ) - + #define is_valid_seq_4(uni) ( \ ((uni & b4_mask) == b4_patt) && \ ((tmp = (uni & b4_requ))) && \ ((tmp & b4_err0) == 0 || (tmp & b4_err1) == 0) \ ) - + #define return_err(_end, _msg) do { \ *msg = _msg; \ *end = _end; \ return false; \ } while (false) - + u8 *cur = *ptr; u8 **end = ptr; u8 *src = ++cur, *dst, *pos; u16 hi, lo; u32 uni, tmp; - + skip_ascii: /* Most strings have no escaped characters, so we can jump them quickly. */ - + skip_ascii_begin: /* We want to make loop unrolling, as shown in the following code. Some compiler may not generate instructions as expected, so we rewrite it with explicit goto statements. We hope the compiler can generate instructions like this: https://godbolt.org/z/8vjsYq - + while (true) repeat16({ if (likely(!(char_is_ascii_stop(*src)))) src++; else break; - }); + }) */ #define expr_jump(i) \ if (likely(!char_is_ascii_stop(src[i]))) {} \ else goto skip_ascii_stop##i; - + #define expr_stop(i) \ skip_ascii_stop##i: \ src += i; \ goto skip_ascii_end; - - repeat16_incr(expr_jump); + + repeat16_incr(expr_jump) src += 16; goto skip_ascii_begin; - repeat16_incr(expr_stop); - + repeat16_incr(expr_stop) + #undef expr_jump #undef expr_stop - + skip_ascii_end: - + /* GCC may store src[i] in a register at each line of expr_jump(i) above. These instructions are useless and will degrade performance. This inline asm is a hint for gcc: "the memory has been modified, do not cache it". - + MSVC, Clang, ICC can generate expected instructions without this hint. */ #if YYJSON_IS_REAL_GCC __asm__ volatile("":"=m"(*src)); #endif if (likely(*src == '"')) { - val->tag = ((u64)(src - cur) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; + val->tag = ((u64)(src - cur) << YYJSON_TAG_BIT) | + (u64)(YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC); val->uni.str = (const char *)cur; *src = '\0'; *end = src + 1; return true; } - + skip_utf8: if (*src & 0x80) { /* non-ASCII character */ /* @@ -4381,6 +5395,21 @@ static_inline bool read_string(u8 **ptr, loop, which is more friendly to branch prediction. */ pos = src; +#if YYJSON_DISABLE_UTF8_VALIDATION + while (true) repeat8({ + if (likely((*src & 0xF0) == 0xE0)) src += 3; + else break; + }) + if (*src < 0x80) goto skip_ascii; + while (true) repeat8({ + if (likely((*src & 0xE0) == 0xC0)) src += 2; + else break; + }) + while (true) repeat8({ + if (likely((*src & 0xF8) == 0xF0)) src += 4; + else break; + }) +#else uni = byte_load_4(src); while (is_valid_seq_3(uni)) { src += 3; @@ -4395,13 +5424,14 @@ static_inline bool read_string(u8 **ptr, src += 4; uni = byte_load_4(src); } +#endif if (unlikely(pos == src)) { if (!inv) return_err(src, "invalid UTF-8 encoding in string"); ++src; } goto skip_ascii; } - + /* The escape character appears, we need to copy it. */ dst = src; copy_escape: @@ -4417,7 +5447,7 @@ static_inline bool read_string(u8 **ptr, case 't': *dst++ = '\t'; src++; break; case 'u': if (unlikely(!read_hex_u16(++src, &hi))) { - return_err(src - 2, "invalid escaped unicode in string"); + return_err(src - 2, "invalid escaped sequence in string"); } src += 4; if (likely((hi & 0xF800) != 0xD800)) { @@ -4437,9 +5467,11 @@ static_inline bool read_string(u8 **ptr, if (unlikely((hi & 0xFC00) != 0xD800)) { return_err(src - 6, "invalid high surrogate in string"); } - if (unlikely(!byte_match_2(src, "\\u")) || - unlikely(!read_hex_u16(src + 2, &lo))) { - return_err(src, "no matched low surrogate in string"); + if (unlikely(!byte_match_2(src, "\\u"))) { + return_err(src, "no low surrogate in string"); + } + if (unlikely(!read_hex_u16(src + 2, &lo))) { + return_err(src, "invalid escaped sequence in string"); } if (unlikely((lo & 0xFC00) != 0xDC00)) { return_err(src, "invalid low surrogate in string"); @@ -4466,15 +5498,15 @@ static_inline bool read_string(u8 **ptr, if (src >= lst) return_err(src, "unclosed string"); *dst++ = *src++; } - + copy_ascii: /* Copy continuous ASCII, loop unrolling, same as the following code: - + while (true) repeat16({ if (unlikely(char_is_ascii_stop(*src))) break; *dst++ = *src++; - }); + }) */ #if YYJSON_IS_REAL_GCC # define expr_jump(i) \ @@ -4485,14 +5517,18 @@ static_inline bool read_string(u8 **ptr, if (likely(!(char_is_ascii_stop(src[i])))) {} \ else { goto copy_ascii_stop_##i; } #endif - repeat16_incr(expr_jump); + repeat16_incr(expr_jump) #undef expr_jump - + byte_move_16(dst, src); src += 16; dst += 16; goto copy_ascii; - + + /* + The memory will be moved forward by at least 1 byte. So the `byte_move` + can be one byte more than needed to reduce the number of instructions. + */ copy_ascii_stop_0: goto copy_utf8; copy_ascii_stop_1: @@ -4580,30 +5616,58 @@ static_inline bool read_string(u8 **ptr, src += 15; dst += 15; goto copy_utf8; - + copy_utf8: if (*src & 0x80) { /* non-ASCII character */ pos = src; uni = byte_load_4(src); +#if YYJSON_DISABLE_UTF8_VALIDATION + while (true) repeat4({ + if ((uni & b3_mask) == b3_patt) { + byte_copy_4(dst, &uni); + dst += 3; + src += 3; + uni = byte_load_4(src); + } else break; + }) + if ((uni & b1_mask) == b1_patt) goto copy_ascii; + while (true) repeat4({ + if ((uni & b2_mask) == b2_patt) { + byte_copy_2(dst, &uni); + dst += 2; + src += 2; + uni = byte_load_4(src); + } else break; + }) + while (true) repeat4({ + if ((uni & b4_mask) == b4_patt) { + byte_copy_4(dst, &uni); + dst += 4; + src += 4; + uni = byte_load_4(src); + } else break; + }) +#else while (is_valid_seq_3(uni)) { - byte_move_4(dst, &uni); + byte_copy_4(dst, &uni); dst += 3; src += 3; uni = byte_load_4(src); } if (is_valid_seq_1(uni)) goto copy_ascii; while (is_valid_seq_2(uni)) { - byte_move_2(dst, &uni); + byte_copy_2(dst, &uni); dst += 2; src += 2; uni = byte_load_4(src); } while (is_valid_seq_4(uni)) { - byte_move_4(dst, &uni); + byte_copy_4(dst, &uni); dst += 4; src += 4; uni = byte_load_4(src); } +#endif if (unlikely(pos == src)) { if (!inv) return_err(src, "invalid UTF-8 encoding in string"); goto copy_ascii_stop_1; @@ -4611,7 +5675,7 @@ static_inline bool read_string(u8 **ptr, goto copy_ascii; } goto copy_escape; - + #undef return_err #undef is_valid_seq_1 #undef is_valid_seq_2 @@ -4636,11 +5700,9 @@ static_noinline yyjson_doc *read_root_single(u8 *hdr, yyjson_alc alc, yyjson_read_flag flg, yyjson_read_err *err) { - -#define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) - + #define return_err(_pos, _code, _msg) do { \ - if (_pos >= end) { \ + if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \ err->pos = (usize)(end - hdr); \ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ err->msg = "unexpected end of data"; \ @@ -4652,35 +5714,33 @@ static_noinline yyjson_doc *read_root_single(u8 *hdr, if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \ return NULL; \ } while (false) - + usize hdr_len; /* value count used by doc */ usize alc_num; /* value count capacity */ yyjson_val *val_hdr; /* the head of allocated values */ yyjson_val *val; /* current value */ yyjson_doc *doc; /* the JSON document, equals to val_hdr */ const char *msg; /* error message */ - + bool raw; /* read number as raw */ - bool ext; /* allow inf and nan */ bool inv; /* allow invalid unicode */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ - + hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; alc_num = hdr_len + 1; /* single value */ - + val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_num * sizeof(yyjson_val)); if (unlikely(!val_hdr)) goto fail_alloc; val = val_hdr + hdr_len; - raw = (flg & YYJSON_READ_NUMBER_AS_RAW) != 0; - ext = (flg & YYJSON_READ_ALLOW_INF_AND_NAN) != 0; - inv = (flg & YYJSON_READ_ALLOW_INVALID_UNICODE) != 0; + raw = has_read_flag(NUMBER_AS_RAW) || has_read_flag(BIGNUM_AS_RAW); + inv = has_read_flag(ALLOW_INVALID_UNICODE) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; - + if (char_is_number(*cur)) { - if (likely(read_number(&cur, pre, ext, val, &msg))) goto doc_end; + if (likely(read_number(&cur, pre, flg, val, &msg))) goto doc_end; goto fail_number; } if (*cur == '"') { @@ -4697,20 +5757,20 @@ static_noinline yyjson_doc *read_root_single(u8 *hdr, } if (*cur == 'n') { if (likely(read_null(&cur, val))) goto doc_end; - if (unlikely(ext)) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto doc_end; } goto fail_literal; } - if (unlikely(ext)) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { if (read_inf_or_nan(false, &cur, pre, val)) goto doc_end; } goto fail_character; - + doc_end: /* check invalid contents after json document */ - if (unlikely(cur < end) && !has_flag(STOP_WHEN_DONE)) { - if (has_flag(ALLOW_COMMENTS)) { + if (unlikely(cur < end) && !has_read_flag(STOP_WHEN_DONE)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (!skip_spaces_and_comments(&cur)) { if (byte_match_2(cur, "/*")) goto fail_comment; } @@ -4719,16 +5779,16 @@ static_noinline yyjson_doc *read_root_single(u8 *hdr, } if (unlikely(cur < end)) goto fail_garbage; } - + if (pre && *pre) **pre = '\0'; doc = (yyjson_doc *)val_hdr; doc->root = val_hdr + hdr_len; doc->alc = alc; doc->dat_read = (usize)(cur - hdr); doc->val_read = 1; - doc->str_pool = has_flag(INSITU) ? NULL : (char *)hdr; + doc->str_pool = has_read_flag(INSITU) ? NULL : (char *)hdr; return doc; - + fail_string: return_err(cur, INVALID_STRING, msg); fail_number: @@ -4743,8 +5803,7 @@ static_noinline yyjson_doc *read_root_single(u8 *hdr, return_err(cur, UNEXPECTED_CHARACTER, "unexpected character"); fail_garbage: return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document"); - -#undef has_flag + #undef return_err } @@ -4755,11 +5814,9 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, yyjson_alc alc, yyjson_read_flag flg, yyjson_read_err *err) { - -#define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) - + #define return_err(_pos, _code, _msg) do { \ - if (_pos >= end) { \ + if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \ err->pos = (usize)(end - hdr); \ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ err->msg = "unexpected end of data"; \ @@ -4771,13 +5828,13 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \ return NULL; \ } while (false) - + #define val_incr() do { \ val++; \ if (unlikely(val >= val_end)) { \ usize alc_old = alc_len; \ alc_len += alc_len / 2; \ - if ((alc_len >= alc_max)) goto fail_alloc; \ + if ((sizeof(usize) < 8) && (alc_len >= alc_max)) goto fail_alloc; \ val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \ alc_old * sizeof(yyjson_val), \ alc_len * sizeof(yyjson_val)); \ @@ -4788,7 +5845,7 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, val_end = val_tmp + (alc_len - 2); \ } \ } while (false) - + usize dat_len; /* data length in bytes, hint for allocator */ usize hdr_len; /* value count used by yyjson_doc */ usize alc_len; /* value count allocated */ @@ -4802,32 +5859,30 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, yyjson_val *ctn_parent; /* parent of current container */ yyjson_doc *doc; /* the JSON document, equals to val_hdr */ const char *msg; /* error message */ - + bool raw; /* read number as raw */ - bool ext; /* allow inf and nan */ bool inv; /* allow invalid unicode */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ - - dat_len = has_flag(STOP_WHEN_DONE) ? 256 : (usize)(end - cur); + + dat_len = has_read_flag(STOP_WHEN_DONE) ? 256 : (usize)(end - cur); hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; alc_max = USIZE_MAX / sizeof(yyjson_val); alc_len = hdr_len + (dat_len / YYJSON_READER_ESTIMATED_MINIFY_RATIO) + 4; alc_len = yyjson_min(alc_len, alc_max); - + val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_len * sizeof(yyjson_val)); if (unlikely(!val_hdr)) goto fail_alloc; val_end = val_hdr + (alc_len - 2); /* padding for key-value pair reading */ val = val_hdr + hdr_len; ctn = val; ctn_len = 0; - raw = (flg & YYJSON_READ_NUMBER_AS_RAW) != 0; - ext = (flg & YYJSON_READ_ALLOW_INF_AND_NAN) != 0; - inv = (flg & YYJSON_READ_ALLOW_INVALID_UNICODE) != 0; + raw = has_read_flag(NUMBER_AS_RAW) || has_read_flag(BIGNUM_AS_RAW); + inv = has_read_flag(ALLOW_INVALID_UNICODE) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; - + if (*cur++ == '{') { ctn->tag = YYJSON_TYPE_OBJ; ctn->uni.ofs = 0; @@ -4837,21 +5892,21 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, ctn->uni.ofs = 0; goto arr_val_begin; } - + arr_begin: /* save current container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | (ctn->tag & YYJSON_TAG_MASK); - + /* create a new array value, save parent container offset */ val_incr(); val->tag = YYJSON_TYPE_ARR; val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); - + /* push the new array value as current container */ ctn = val; ctn_len = 0; - + arr_val_begin: if (*cur == '{') { cur++; @@ -4864,7 +5919,7 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, if (char_is_number(*cur)) { val_incr(); ctn_len++; - if (likely(read_number(&cur, pre, ext, val, &msg))) goto arr_val_end; + if (likely(read_number(&cur, pre, flg, val, &msg))) goto arr_val_end; goto fail_number; } if (*cur == '"') { @@ -4889,7 +5944,7 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, val_incr(); ctn_len++; if (likely(read_null(&cur, val))) goto arr_val_end; - if (unlikely(ext)) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto arr_val_end; } goto fail_literal; @@ -4897,26 +5952,27 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, if (*cur == ']') { cur++; if (likely(ctn_len == 0)) goto arr_end; - if (has_flag(ALLOW_TRAILING_COMMAS)) goto arr_end; - cur--; + if (has_read_flag(ALLOW_TRAILING_COMMAS)) goto arr_end; + while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto arr_val_begin; } - if (unlikely(ext) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { + if (has_read_flag(ALLOW_INF_AND_NAN) && + (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val_incr(); ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto arr_val_end; goto fail_character; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + arr_val_end: if (*cur == ',') { cur++; @@ -4930,21 +5986,21 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, while (char_is_space(*++cur)); goto arr_val_end; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + arr_end: /* get parent container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); - + /* save the next sibling value offset */ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; if (unlikely(ctn == ctn_parent)) goto doc_end; - + /* pop parent as current container */ ctn = ctn_parent; ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); @@ -4953,7 +6009,7 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, } else { goto arr_val_end; } - + obj_begin: /* push container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | @@ -4964,7 +6020,7 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); ctn = val; ctn_len = 0; - + obj_key_begin: if (likely(*cur == '"')) { val_incr(); @@ -4975,20 +6031,20 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, if (likely(*cur == '}')) { cur++; if (likely(ctn_len == 0)) goto obj_end; - if (has_flag(ALLOW_TRAILING_COMMAS)) goto obj_end; - cur--; + if (has_read_flag(ALLOW_TRAILING_COMMAS)) goto obj_end; + while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_key_begin; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + obj_key_end: if (*cur == ':') { cur++; @@ -4998,12 +6054,12 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, while (char_is_space(*++cur)); goto obj_key_end; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + obj_val_begin: if (*cur == '"') { val++; @@ -5014,7 +6070,7 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, if (char_is_number(*cur)) { val++; ctn_len++; - if (likely(read_number(&cur, pre, ext, val, &msg))) goto obj_val_end; + if (likely(read_number(&cur, pre, flg, val, &msg))) goto obj_val_end; goto fail_number; } if (*cur == '{') { @@ -5041,7 +6097,7 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, val++; ctn_len++; if (likely(read_null(&cur, val))) goto obj_val_end; - if (unlikely(ext)) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto obj_val_end; } goto fail_literal; @@ -5050,18 +6106,19 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, while (char_is_space(*++cur)); goto obj_val_begin; } - if (unlikely(ext) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { + if (has_read_flag(ALLOW_INF_AND_NAN) && + (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val++; ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto obj_val_end; goto fail_character; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + obj_val_end: if (likely(*cur == ',')) { cur++; @@ -5075,12 +6132,12 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, while (char_is_space(*++cur)); goto obj_val_end; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + obj_end: /* pop container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); @@ -5095,27 +6152,28 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, } else { goto arr_val_end; } - + doc_end: /* check invalid contents after json document */ - if (unlikely(cur < end) && !has_flag(STOP_WHEN_DONE)) { - if (has_flag(ALLOW_COMMENTS)) { + if (unlikely(cur < end) && !has_read_flag(STOP_WHEN_DONE)) { + if (has_read_flag(ALLOW_COMMENTS)) { skip_spaces_and_comments(&cur); if (byte_match_2(cur, "/*")) goto fail_comment; + } else { + while (char_is_space(*cur)) cur++; } - else while (char_is_space(*cur)) cur++; if (unlikely(cur < end)) goto fail_garbage; } - + if (pre && *pre) **pre = '\0'; doc = (yyjson_doc *)val_hdr; doc->root = val_hdr + hdr_len; doc->alc = alc; doc->dat_read = (usize)(cur - hdr); doc->val_read = (usize)((val - doc->root) + 1); - doc->str_pool = has_flag(INSITU) ? NULL : (char *)hdr; + doc->str_pool = has_read_flag(INSITU) ? NULL : (char *)hdr; return doc; - + fail_string: return_err(cur, INVALID_STRING, msg); fail_number: @@ -5132,8 +6190,7 @@ static_inline yyjson_doc *read_root_minify(u8 *hdr, return_err(cur, UNEXPECTED_CHARACTER, "unexpected character"); fail_garbage: return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document"); - -#undef has_flag + #undef val_incr #undef return_err } @@ -5145,11 +6202,9 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, yyjson_alc alc, yyjson_read_flag flg, yyjson_read_err *err) { - -#define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) - + #define return_err(_pos, _code, _msg) do { \ - if (_pos >= end) { \ + if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \ err->pos = (usize)(end - hdr); \ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ err->msg = "unexpected end of data"; \ @@ -5161,13 +6216,13 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \ return NULL; \ } while (false) - + #define val_incr() do { \ val++; \ if (unlikely(val >= val_end)) { \ usize alc_old = alc_len; \ alc_len += alc_len / 2; \ - if ((alc_len >= alc_max)) goto fail_alloc; \ + if ((sizeof(usize) < 8) && (alc_len >= alc_max)) goto fail_alloc; \ val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \ alc_old * sizeof(yyjson_val), \ alc_len * sizeof(yyjson_val)); \ @@ -5178,7 +6233,7 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, val_end = val_tmp + (alc_len - 2); \ } \ } while (false) - + usize dat_len; /* data length in bytes, hint for allocator */ usize hdr_len; /* value count used by yyjson_doc */ usize alc_len; /* value count allocated */ @@ -5192,32 +6247,30 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, yyjson_val *ctn_parent; /* parent of current container */ yyjson_doc *doc; /* the JSON document, equals to val_hdr */ const char *msg; /* error message */ - + bool raw; /* read number as raw */ - bool ext; /* allow inf and nan */ bool inv; /* allow invalid unicode */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ - - dat_len = has_flag(STOP_WHEN_DONE) ? 256 : (usize)(end - cur); + + dat_len = has_read_flag(STOP_WHEN_DONE) ? 256 : (usize)(end - cur); hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; alc_max = USIZE_MAX / sizeof(yyjson_val); alc_len = hdr_len + (dat_len / YYJSON_READER_ESTIMATED_PRETTY_RATIO) + 4; alc_len = yyjson_min(alc_len, alc_max); - + val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_len * sizeof(yyjson_val)); if (unlikely(!val_hdr)) goto fail_alloc; val_end = val_hdr + (alc_len - 2); /* padding for key-value pair reading */ val = val_hdr + hdr_len; ctn = val; ctn_len = 0; - raw = (flg & YYJSON_READ_NUMBER_AS_RAW) != 0; - ext = (flg & YYJSON_READ_ALLOW_INF_AND_NAN) != 0; - inv = (flg & YYJSON_READ_ALLOW_INVALID_UNICODE) != 0; + raw = has_read_flag(NUMBER_AS_RAW) || has_read_flag(BIGNUM_AS_RAW); + inv = has_read_flag(ALLOW_INVALID_UNICODE) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; - + if (*cur++ == '{') { ctn->tag = YYJSON_TYPE_OBJ; ctn->uni.ofs = 0; @@ -5229,35 +6282,35 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, if (*cur == '\n') cur++; goto arr_val_begin; } - + arr_begin: /* save current container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | (ctn->tag & YYJSON_TAG_MASK); - + /* create a new array value, save parent container offset */ val_incr(); val->tag = YYJSON_TYPE_ARR; val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); - + /* push the new array value as current container */ ctn = val; ctn_len = 0; if (*cur == '\n') cur++; - + arr_val_begin: #if YYJSON_IS_REAL_GCC while (true) repeat16({ if (byte_match_2(cur, " ")) cur += 2; else break; - }); + }) #else while (true) repeat16({ if (likely(byte_match_2(cur, " "))) cur += 2; else break; - }); + }) #endif - + if (*cur == '{') { cur++; goto obj_begin; @@ -5269,7 +6322,7 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, if (char_is_number(*cur)) { val_incr(); ctn_len++; - if (likely(read_number(&cur, pre, ext, val, &msg))) goto arr_val_end; + if (likely(read_number(&cur, pre, flg, val, &msg))) goto arr_val_end; goto fail_number; } if (*cur == '"') { @@ -5294,7 +6347,7 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, val_incr(); ctn_len++; if (likely(read_null(&cur, val))) goto arr_val_end; - if (unlikely(ext)) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto arr_val_end; } goto fail_literal; @@ -5302,26 +6355,27 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, if (*cur == ']') { cur++; if (likely(ctn_len == 0)) goto arr_end; - if (has_flag(ALLOW_TRAILING_COMMAS)) goto arr_end; - cur--; + if (has_read_flag(ALLOW_TRAILING_COMMAS)) goto arr_end; + while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto arr_val_begin; } - if (unlikely(ext) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { + if (has_read_flag(ALLOW_INF_AND_NAN) && + (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val_incr(); ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto arr_val_end; goto fail_character; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + arr_val_end: if (byte_match_2(cur, ",\n")) { cur += 2; @@ -5339,21 +6393,21 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, while (char_is_space(*++cur)); goto arr_val_end; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + arr_end: /* get parent container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); - + /* save the next sibling value offset */ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; if (unlikely(ctn == ctn_parent)) goto doc_end; - + /* pop parent as current container */ ctn = ctn_parent; ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); @@ -5363,7 +6417,7 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, } else { goto arr_val_end; } - + obj_begin: /* push container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | @@ -5375,18 +6429,18 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, ctn = val; ctn_len = 0; if (*cur == '\n') cur++; - + obj_key_begin: #if YYJSON_IS_REAL_GCC while (true) repeat16({ if (byte_match_2(cur, " ")) cur += 2; else break; - }); + }) #else while (true) repeat16({ if (likely(byte_match_2(cur, " "))) cur += 2; else break; - }); + }) #endif if (likely(*cur == '"')) { val_incr(); @@ -5397,20 +6451,20 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, if (likely(*cur == '}')) { cur++; if (likely(ctn_len == 0)) goto obj_end; - if (has_flag(ALLOW_TRAILING_COMMAS)) goto obj_end; - cur--; + if (has_read_flag(ALLOW_TRAILING_COMMAS)) goto obj_end; + while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_key_begin; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + obj_key_end: if (byte_match_2(cur, ": ")) { cur += 2; @@ -5424,12 +6478,12 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, while (char_is_space(*++cur)); goto obj_key_end; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + obj_val_begin: if (*cur == '"') { val++; @@ -5440,7 +6494,7 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, if (char_is_number(*cur)) { val++; ctn_len++; - if (likely(read_number(&cur, pre, ext, val, &msg))) goto obj_val_end; + if (likely(read_number(&cur, pre, flg, val, &msg))) goto obj_val_end; goto fail_number; } if (*cur == '{') { @@ -5467,7 +6521,7 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, val++; ctn_len++; if (likely(read_null(&cur, val))) goto obj_val_end; - if (unlikely(ext)) { + if (has_read_flag(ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto obj_val_end; } goto fail_literal; @@ -5476,18 +6530,19 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, while (char_is_space(*++cur)); goto obj_val_begin; } - if (unlikely(ext) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { + if (has_read_flag(ALLOW_INF_AND_NAN) && + (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val++; ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto obj_val_end; goto fail_character; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + obj_val_end: if (byte_match_2(cur, ",\n")) { cur += 2; @@ -5505,12 +6560,12 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, while (char_is_space(*++cur)); goto obj_val_end; } - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; - + obj_end: /* pop container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); @@ -5526,27 +6581,28 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, } else { goto arr_val_end; } - + doc_end: /* check invalid contents after json document */ - if (unlikely(cur < end) && !has_flag(STOP_WHEN_DONE)) { - if (has_flag(ALLOW_COMMENTS)) { + if (unlikely(cur < end) && !has_read_flag(STOP_WHEN_DONE)) { + if (has_read_flag(ALLOW_COMMENTS)) { skip_spaces_and_comments(&cur); if (byte_match_2(cur, "/*")) goto fail_comment; + } else { + while (char_is_space(*cur)) cur++; } - else while (char_is_space(*cur)) cur++; if (unlikely(cur < end)) goto fail_garbage; } - + if (pre && *pre) **pre = '\0'; doc = (yyjson_doc *)val_hdr; doc->root = val_hdr + hdr_len; doc->alc = alc; doc->dat_read = (usize)(cur - hdr); doc->val_read = (usize)((val - val_hdr)) - hdr_len + 1; - doc->str_pool = has_flag(INSITU) ? NULL : (char *)hdr; + doc->str_pool = has_read_flag(INSITU) ? NULL : (char *)hdr; return doc; - + fail_string: return_err(cur, INVALID_STRING, msg); fail_number: @@ -5563,8 +6619,7 @@ static_inline yyjson_doc *read_root_pretty(u8 *hdr, return_err(cur, UNEXPECTED_CHARACTER, "unexpected character"); fail_garbage: return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document"); - -#undef has_flag + #undef val_incr #undef return_err } @@ -5580,29 +6635,20 @@ yyjson_doc *yyjson_read_opts(char *dat, yyjson_read_flag flg, const yyjson_alc *alc_ptr, yyjson_read_err *err) { - -#define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) - + #define return_err(_pos, _code, _msg) do { \ err->pos = (usize)(_pos); \ err->msg = _msg; \ err->code = YYJSON_READ_ERROR_##_code; \ - if (!has_flag(INSITU) && hdr) alc.free(alc.ctx, (void *)hdr); \ + if (!has_read_flag(INSITU) && hdr) alc.free(alc.ctx, (void *)hdr); \ return NULL; \ } while (false) - + yyjson_read_err dummy_err; yyjson_alc alc; yyjson_doc *doc; u8 *hdr = NULL, *end, *cur; - -#if YYJSON_DISABLE_NON_STANDARD - flg &= ~YYJSON_READ_ALLOW_TRAILING_COMMAS; - flg &= ~YYJSON_READ_ALLOW_COMMENTS; - flg &= ~YYJSON_READ_ALLOW_INF_AND_NAN; - flg &= ~YYJSON_READ_ALLOW_INVALID_UNICODE; -#endif - + /* validate input parameters */ if (!err) err = &dummy_err; if (likely(!alc_ptr)) { @@ -5616,9 +6662,9 @@ yyjson_doc *yyjson_read_opts(char *dat, if (unlikely(!len)) { return_err(0, INVALID_PARAMETER, "input length is 0"); } - + /* add 4-byte zero padding for input data if necessary */ - if (has_flag(INSITU)) { + if (has_read_flag(INSITU)) { hdr = (u8 *)dat; end = (u8 *)dat + len; cur = (u8 *)dat; @@ -5635,10 +6681,10 @@ yyjson_doc *yyjson_read_opts(char *dat, memcpy(hdr, dat, len); memset(end, 0, YYJSON_PADDING_SIZE); } - + /* skip empty contents before json document */ if (unlikely(char_is_space_or_comment(*cur))) { - if (has_flag(ALLOW_COMMENTS)) { + if (has_read_flag(ALLOW_COMMENTS)) { if (!skip_spaces_and_comments(&cur)) { return_err(cur - hdr, INVALID_COMMENT, "unclosed multiline comment"); @@ -5652,7 +6698,7 @@ yyjson_doc *yyjson_read_opts(char *dat, return_err(0, EMPTY_CONTENT, "input data is empty"); } } - + /* read json document */ if (likely(char_is_container(*cur))) { if (char_is_space(cur[1]) && char_is_space(cur[2])) { @@ -5663,7 +6709,7 @@ yyjson_doc *yyjson_read_opts(char *dat, } else { doc = read_root_single(hdr, cur, end, alc, flg, err); } - + /* check result */ if (likely(doc)) { memset(err, 0, sizeof(yyjson_read_err)); @@ -5684,11 +6730,10 @@ yyjson_doc *yyjson_read_opts(char *dat, err->msg = "UTF-16 encoding is not supported"; } } - if (!has_flag(INSITU)) alc.free(alc.ctx, (void *)hdr); + if (!has_read_flag(INSITU)) alc.free(alc.ctx, (void *)hdr); } return doc; - -#undef has_flag + #undef return_err } @@ -5696,37 +6741,65 @@ yyjson_doc *yyjson_read_file(const char *path, yyjson_read_flag flg, const yyjson_alc *alc_ptr, yyjson_read_err *err) { - #define return_err(_code, _msg) do { \ err->pos = 0; \ err->msg = _msg; \ err->code = YYJSON_READ_ERROR_##_code; \ - if (file) fclose(file); \ + return NULL; \ +} while (false) + + yyjson_read_err dummy_err; + yyjson_doc *doc; + FILE *file; + + if (!err) err = &dummy_err; + if (unlikely(!path)) return_err(INVALID_PARAMETER, "input path is NULL"); + + file = fopen_readonly(path); + if (unlikely(!file)) return_err(FILE_OPEN, "file opening failed"); + + doc = yyjson_read_fp(file, flg, alc_ptr, err); + fclose(file); + return doc; + +#undef return_err +} + +yyjson_doc *yyjson_read_fp(FILE *file, + yyjson_read_flag flg, + const yyjson_alc *alc_ptr, + yyjson_read_err *err) { +#define return_err(_code, _msg) do { \ + err->pos = 0; \ + err->msg = _msg; \ + err->code = YYJSON_READ_ERROR_##_code; \ if (buf) alc.free(alc.ctx, buf); \ return NULL; \ } while (false) - + yyjson_read_err dummy_err; yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; yyjson_doc *doc; - - FILE *file = NULL; - long file_size = 0; + + long file_size = 0, file_pos; void *buf = NULL; usize buf_size = 0; - + /* validate input parameters */ if (!err) err = &dummy_err; - if (unlikely(!path)) return_err(INVALID_PARAMETER, "input path is NULL"); - - /* open file */ - file = fopen_readonly(path); - if (file == NULL) return_err(FILE_OPEN, "file opening failed"); - - /* get file size */ - if (fseek(file, 0, SEEK_END) == 0) file_size = ftell(file); - rewind(file); - + if (unlikely(!file)) return_err(INVALID_PARAMETER, "input file is NULL"); + + /* get current position */ + file_pos = ftell(file); + if (file_pos != -1) { + /* get total file size, may fail */ + if (fseek(file, 0, SEEK_END) == 0) file_size = ftell(file); + /* reset to original position, may fail */ + if (fseek(file, file_pos, SEEK_SET) != 0) file_size = 0; + /* get file size from current postion to end */ + if (file_size > 0) file_size -= file_pos; + } + /* read file */ if (file_size > 0) { /* read the entire file in one call */ @@ -5745,7 +6818,7 @@ yyjson_doc *yyjson_read_file(const char *path, usize chunk_now = chunk_min; usize read_size; void *tmp; - + buf_size = YYJSON_PADDING_SIZE; while (true) { if (buf_size + chunk_now < buf_size) { /* overflow */ @@ -5764,13 +6837,12 @@ yyjson_doc *yyjson_read_file(const char *path, read_size = fread_safe(tmp, chunk_now, file); file_size += (long)read_size; if (read_size != chunk_now) break; - + chunk_now *= 2; if (chunk_now > chunk_max) chunk_now = chunk_max; } } - fclose(file); - + /* read JSON */ memset((u8 *)buf + file_size, 0, YYJSON_PADDING_SIZE); flg |= YYJSON_READ_INSITU; @@ -5782,7 +6854,7 @@ yyjson_doc *yyjson_read_file(const char *path, alc.free(alc.ctx, buf); return NULL; } - + #undef return_err } @@ -5797,20 +6869,19 @@ const char *yyjson_read_number(const char *dat, err->code = YYJSON_READ_ERROR_##_code; \ return NULL; \ } while (false) - - u8 *hdr = (u8 *)dat, *cur = hdr; + + u8 *hdr = constcast(u8 *)dat, *cur = hdr; bool raw; /* read number as raw */ - bool ext; /* allow inf and nan */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ const char *msg; yyjson_read_err dummy_err; - + #if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV u8 buf[128]; usize dat_len; #endif - + if (!err) err = &dummy_err; if (unlikely(!dat)) { return_err(cur, INVALID_PARAMETER, "input data is NULL"); @@ -5818,7 +6889,7 @@ const char *yyjson_read_number(const char *dat, if (unlikely(!val)) { return_err(cur, INVALID_PARAMETER, "output value is NULL"); } - + #if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV if (!alc) alc = &YYJSON_DEFAULT_ALC; dat_len = strlen(dat); @@ -5834,33 +6905,28 @@ const char *yyjson_read_number(const char *dat, } memcpy(hdr, dat, dat_len + 1); } + hdr[dat_len] = 0; #endif - -#if YYJSON_DISABLE_NON_STANDARD - ext = false; -#else - ext = (flg & YYJSON_READ_ALLOW_INF_AND_NAN) != 0; -#endif - - raw = (flg & YYJSON_READ_NUMBER_AS_RAW) != 0; + + raw = (flg & (YYJSON_READ_NUMBER_AS_RAW | YYJSON_READ_BIGNUM_AS_RAW)) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; - + #if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV - if (!read_number(&cur, pre, ext, val, &msg)) { + if (!read_number(&cur, pre, flg, val, &msg)) { if (dat_len >= sizeof(buf)) alc->free(alc->ctx, hdr); return_err(cur, INVALID_NUMBER, msg); } if (dat_len >= sizeof(buf)) alc->free(alc->ctx, hdr); - if (raw) val->uni.str = dat; + if (yyjson_is_raw(val)) val->uni.str = dat; return dat + (cur - hdr); #else - if (!read_number(&cur, pre, ext, val, &msg)) { + if (!read_number(&cur, pre, flg, val, &msg)) { return_err(cur, INVALID_NUMBER, msg); } return (const char *)cur; #endif - + #undef return_err } @@ -5920,10 +6986,10 @@ static_inline u8 *write_u32_len_8(u32 val, u8 *buf) { cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */ bb = aabb - aa * 100; /* (aabb % 100) */ dd = ccdd - cc * 100; /* (ccdd % 100) */ - ((v16 *)buf)[0] = ((const v16 *)digit_table)[aa]; - ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; - ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; - ((v16 *)buf)[3] = ((const v16 *)digit_table)[dd]; + byte_copy_2(buf + 0, digit_table + aa * 2); + byte_copy_2(buf + 2, digit_table + bb * 2); + byte_copy_2(buf + 4, digit_table + cc * 2); + byte_copy_2(buf + 6, digit_table + dd * 2); return buf + 8; } @@ -5931,41 +6997,41 @@ static_inline u8 *write_u32_len_4(u32 val, u8 *buf) { u32 aa, bb; /* 4 digits: aabb */ aa = (val * 5243) >> 19; /* (val / 100) */ bb = val - aa * 100; /* (val % 100) */ - ((v16 *)buf)[0] = ((const v16 *)digit_table)[aa]; - ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; + byte_copy_2(buf + 0, digit_table + aa * 2); + byte_copy_2(buf + 2, digit_table + bb * 2); return buf + 4; } static_inline u8 *write_u32_len_1_8(u32 val, u8 *buf) { u32 aa, bb, cc, dd, aabb, bbcc, ccdd, lz; - + if (val < 100) { /* 1-2 digits: aa */ lz = val < 10; /* leading zero: 0 or 1 */ - ((v16 *)buf)[0] = *(const v16 *)(digit_table + (val * 2 + lz)); + byte_copy_2(buf + 0, digit_table + val * 2 + lz); buf -= lz; return buf + 2; - + } else if (val < 10000) { /* 3-4 digits: aabb */ aa = (val * 5243) >> 19; /* (val / 100) */ bb = val - aa * 100; /* (val % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ - ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); + byte_copy_2(buf + 0, digit_table + aa * 2 + lz); buf -= lz; - ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; + byte_copy_2(buf + 2, digit_table + bb * 2); return buf + 4; - + } else if (val < 1000000) { /* 5-6 digits: aabbcc */ aa = (u32)(((u64)val * 429497) >> 32); /* (val / 10000) */ bbcc = val - aa * 10000; /* (val % 10000) */ bb = (bbcc * 5243) >> 19; /* (bbcc / 100) */ cc = bbcc - bb * 100; /* (bbcc % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ - ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); + byte_copy_2(buf + 0, digit_table + aa * 2 + lz); buf -= lz; - ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; - ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; + byte_copy_2(buf + 2, digit_table + bb * 2); + byte_copy_2(buf + 4, digit_table + cc * 2); return buf + 6; - + } else { /* 7-8 digits: aabbccdd */ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ ccdd = val - aabb * 10000; /* (val % 10000) */ @@ -5974,30 +7040,30 @@ static_inline u8 *write_u32_len_1_8(u32 val, u8 *buf) { bb = aabb - aa * 100; /* (aabb % 100) */ dd = ccdd - cc * 100; /* (ccdd % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ - ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); + byte_copy_2(buf + 0, digit_table + aa * 2 + lz); buf -= lz; - ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; - ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; - ((v16 *)buf)[3] = ((const v16 *)digit_table)[dd]; + byte_copy_2(buf + 2, digit_table + bb * 2); + byte_copy_2(buf + 4, digit_table + cc * 2); + byte_copy_2(buf + 6, digit_table + dd * 2); return buf + 8; } } static_inline u8 *write_u64_len_5_8(u32 val, u8 *buf) { u32 aa, bb, cc, dd, aabb, bbcc, ccdd, lz; - + if (val < 1000000) { /* 5-6 digits: aabbcc */ aa = (u32)(((u64)val * 429497) >> 32); /* (val / 10000) */ bbcc = val - aa * 10000; /* (val % 10000) */ bb = (bbcc * 5243) >> 19; /* (bbcc / 100) */ cc = bbcc - bb * 100; /* (bbcc % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ - ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); + byte_copy_2(buf + 0, digit_table + aa * 2 + lz); buf -= lz; - ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; - ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; + byte_copy_2(buf + 2, digit_table + bb * 2); + byte_copy_2(buf + 4, digit_table + cc * 2); return buf + 6; - + } else { /* 7-8 digits: aabbccdd */ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ ccdd = val - aabb * 10000; /* (val % 10000) */ @@ -6006,11 +7072,11 @@ static_inline u8 *write_u64_len_5_8(u32 val, u8 *buf) { bb = aabb - aa * 100; /* (aabb % 100) */ dd = ccdd - cc * 100; /* (ccdd % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ - ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); + byte_copy_2(buf + 0, digit_table + aa * 2 + lz); buf -= lz; - ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; - ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; - ((v16 *)buf)[3] = ((const v16 *)digit_table)[dd]; + byte_copy_2(buf + 2, digit_table + bb * 2); + byte_copy_2(buf + 4, digit_table + cc * 2); + byte_copy_2(buf + 6, digit_table + dd * 2); return buf + 8; } } @@ -6018,18 +7084,18 @@ static_inline u8 *write_u64_len_5_8(u32 val, u8 *buf) { static_inline u8 *write_u64(u64 val, u8 *buf) { u64 tmp, hgh; u32 mid, low; - + if (val < 100000000) { /* 1-8 digits */ buf = write_u32_len_1_8((u32)val, buf); return buf; - + } else if (val < (u64)100000000 * 100000000) { /* 9-16 digits */ hgh = val / 100000000; /* (val / 100000000) */ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ buf = write_u32_len_1_8((u32)hgh, buf); buf = write_u32_len_8(low, buf); return buf; - + } else { /* 17-20 digits */ tmp = val / 100000000; /* (val / 100000000) */ low = (u32)(val - tmp * 100000000); /* (val % 100000000) */ @@ -6115,7 +7181,7 @@ static_inline u8 *write_u64_len_1_to_17(u64 val, u8 *buf) { static_inline u8 *write_u64_len_15_to_17_trim(u8 *buf, u64 sig) { bool lz; /* leading zero */ u32 tz1, tz2, tz; /* trailing zero */ - + u32 abbccddee = (u32)(sig / 100000000); u32 ffgghhii = (u32)(sig - (u64)abbccddee * 100000000); u32 abbcc = abbccddee / 10000; /* (abbccddee / 10000) */ @@ -6124,15 +7190,15 @@ static_inline u8 *write_u64_len_15_to_17_trim(u8 *buf, u64 sig) { u32 a = (abb * 41) >> 12; /* (abb / 100) */ u32 bb = abb - a * 100; /* (abb % 100) */ u32 cc = abbcc - abb * 100; /* (abbcc % 100) */ - + /* write abbcc */ buf[0] = (u8)(a + '0'); buf += a > 0; lz = bb < 10 && a == 0; - ((v16 *)buf)[0] = *(const v16 *)(digit_table + (bb * 2 + lz)); + byte_copy_2(buf + 0, digit_table + bb * 2 + lz); buf -= lz; - ((v16 *)buf)[1] = ((const v16 *)digit_table)[cc]; - + byte_copy_2(buf + 2, digit_table + cc * 2); + if (ffgghhii) { u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */ u32 ee = ddee - dd * 100; /* (ddee % 100) */ @@ -6140,15 +7206,15 @@ static_inline u8 *write_u64_len_15_to_17_trim(u8 *buf, u64 sig) { u32 hhii = ffgghhii - ffgg * 10000; /* (val % 10000) */ u32 ff = (ffgg * 5243) >> 19; /* (aabb / 100) */ u32 gg = ffgg - ff * 100; /* (aabb % 100) */ - ((v16 *)buf)[2] = ((const v16 *)digit_table)[dd]; - ((v16 *)buf)[3] = ((const v16 *)digit_table)[ee]; - ((v16 *)buf)[4] = ((const v16 *)digit_table)[ff]; - ((v16 *)buf)[5] = ((const v16 *)digit_table)[gg]; + byte_copy_2(buf + 4, digit_table + dd * 2); + byte_copy_2(buf + 6, digit_table + ee * 2); + byte_copy_2(buf + 8, digit_table + ff * 2); + byte_copy_2(buf + 10, digit_table + gg * 2); if (hhii) { u32 hh = (hhii * 5243) >> 19; /* (ccdd / 100) */ u32 ii = hhii - hh * 100; /* (ccdd % 100) */ - ((v16 *)buf)[6] = ((const v16 *)digit_table)[hh]; - ((v16 *)buf)[7] = ((const v16 *)digit_table)[ii]; + byte_copy_2(buf + 12, digit_table + hh * 2); + byte_copy_2(buf + 14, digit_table + ii * 2); tz1 = dec_trailing_zero_table[hh]; tz2 = dec_trailing_zero_table[ii]; tz = ii ? tz2 : (tz1 + 2); @@ -6165,8 +7231,8 @@ static_inline u8 *write_u64_len_15_to_17_trim(u8 *buf, u64 sig) { if (ddee) { u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */ u32 ee = ddee - dd * 100; /* (ddee % 100) */ - ((v16 *)buf)[2] = ((const v16 *)digit_table)[dd]; - ((v16 *)buf)[3] = ((const v16 *)digit_table)[ee]; + byte_copy_2(buf + 4, digit_table + dd * 2); + byte_copy_2(buf + 6, digit_table + ee * 2); tz1 = dec_trailing_zero_table[dd]; tz2 = dec_trailing_zero_table[ee]; tz = ee ? tz2 : (tz1 + 2); @@ -6189,13 +7255,13 @@ static_inline u8 *write_f64_exp(i32 exp, u8 *buf) { exp = exp < 0 ? -exp : exp; if (exp < 100) { u32 lz = exp < 10; - *(v16 *)&buf[0] = *(const v16 *)(digit_table + ((u32)exp * 2 + lz)); + byte_copy_2(buf + 0, digit_table + (u32)exp * 2 + lz); return buf + 2 - lz; } else { u32 hi = ((u32)exp * 656) >> 16; /* exp / 100 */ u32 lo = (u32)exp - hi * 100; /* exp % 100 */ buf[0] = (u8)((u8)hi + (u8)'0'); - *(v16 *)&buf[1] = *(const v16 *)(digit_table + (lo * 2)); + byte_copy_2(buf + 1, digit_table + lo * 2); return buf + 3; } } @@ -6211,19 +7277,19 @@ static_inline u64 round_to_odd(u64 hi, u64 lo, u64 cp) { /** Convert double number from binary to decimal. The output significand is shortest decimal but may have trailing zeros. - + This function use the Schubfach algorithm: Raffaello Giulietti, The Schubfach way to render doubles (5th version), 2022. https://drive.google.com/file/d/1gp5xv4CAa78SVgCeWfGqqI4FfYYYuNFb https://mail.openjdk.java.net/pipermail/core-libs-dev/2021-November/083536.html https://github.com/openjdk/jdk/pull/3402 (Java implementation) https://github.com/abolz/Drachennest (C++ implementation) - + See also: Dragonbox: A New Floating-Point Binary-to-Decimal Conversion Algorithm, 2022. https://github.com/jk-jeon/dragonbox/blob/master/other_files/Dragonbox.pdf https://github.com/jk-jeon/dragonbox - + @param sig_raw The raw value of significand in IEEE 754 format. @param exp_raw The raw value of exponent in IEEE 754 format. @param sig_bin The decoded value of significand in binary. @@ -6235,41 +7301,41 @@ static_inline u64 round_to_odd(u64 hi, u64 lo, u64 cp) { static_inline void f64_bin_to_dec(u64 sig_raw, u32 exp_raw, u64 sig_bin, i32 exp_bin, u64 *sig_dec, i32 *exp_dec) { - + bool is_even, regular_spacing, u_inside, w_inside, round_up; u64 s, sp, cb, cbl, cbr, vb, vbl, vbr, pow10hi, pow10lo, upper, lower, mid; i32 k, h, exp10; - + is_even = !(sig_bin & 1); regular_spacing = (sig_raw == 0 && exp_raw > 1); - + cbl = 4 * sig_bin - 2 + regular_spacing; cb = 4 * sig_bin; cbr = 4 * sig_bin + 2; - + /* exp_bin: [-1074, 971] */ /* k = regular_spacing ? floor(log10(pow(2, exp_bin))) */ /* : floor(log10(pow(2, exp_bin) * 3.0 / 4.0)) */ /* = regular_spacing ? floor(exp_bin * log10(2)) */ /* : floor(exp_bin * log10(2) + log10(3.0 / 4.0)) */ k = (i32)(exp_bin * 315653 - (regular_spacing ? 131237 : 0)) >> 20; - + /* k: [-324, 292] */ /* h = exp_bin + floor(log2(pow(10, e))) */ /* = exp_bin + floor(log2(10) * e) */ exp10 = -k; h = exp_bin + ((exp10 * 217707) >> 16) + 1; - + pow10_table_get_sig(exp10, &pow10hi, &pow10lo); pow10lo += (exp10 < POW10_SIG_TABLE_MIN_EXACT_EXP || exp10 > POW10_SIG_TABLE_MAX_EXACT_EXP); vbl = round_to_odd(pow10hi, pow10lo, cbl << h); vb = round_to_odd(pow10hi, pow10lo, cb << h); vbr = round_to_odd(pow10hi, pow10lo, cbr << h); - + lower = vbl + !is_even; upper = vbr - !is_even; - + s = vb / 4; if (s >= 10) { sp = s / 10; @@ -6281,44 +7347,45 @@ static_inline void f64_bin_to_dec(u64 sig_raw, u32 exp_raw, return; } } - + u_inside = (lower <= 4 * s); w_inside = (upper >= 4 * s + 4); - + mid = 4 * s + 2; round_up = (vb > mid) || (vb == mid && (s & 1) != 0); - + *sig_dec = s + ((u_inside != w_inside) ? w_inside : round_up); *exp_dec = k; } /** Write a double number (requires 32 bytes buffer). - + We follows the ECMAScript specification to print floating point numbers, but with the following changes: 1. Keep the negative sign of 0.0 to preserve input information. 2. Keep decimal point to indicate the number is floating point. 3. Remove positive sign of exponent part. */ -static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { +static_inline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { u64 sig_bin, sig_dec, sig_raw; i32 exp_bin, exp_dec, sig_len, dot_pos, i, max; u32 exp_raw, hi, lo; u8 *hdr, *num_hdr, *num_end, *dot_end; bool sign; - + /* decode raw bytes from IEEE-754 double format. */ sign = (bool)(raw >> (F64_BITS - 1)); sig_raw = raw & F64_SIG_MASK; exp_raw = (u32)((raw & F64_EXP_MASK) >> F64_SIG_BITS); - + /* return inf and nan */ if (unlikely(exp_raw == ((u32)1 << F64_EXP_BITS) - 1)) { - if (flg & YYJSON_WRITE_INF_AND_NAN_AS_NULL) { + if (has_write_flag(INF_AND_NAN_AS_NULL)) { byte_copy_4(buf, "null"); return buf + 4; - } else if (flg & YYJSON_WRITE_ALLOW_INF_AND_NAN) { + } + else if (has_write_flag(ALLOW_INF_AND_NAN)) { if (sig_raw == 0) { buf[0] = '-'; buf += sign; @@ -6329,28 +7396,27 @@ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { byte_copy_4(buf, "NaN"); return buf + 3; } - } else { - return NULL; } + return NULL; } - + /* add sign for all finite double value, including 0.0 and inf */ buf[0] = '-'; buf += sign; hdr = buf; - + /* return zero */ if ((raw << 1) == 0) { byte_copy_4(buf, "0.0"); buf += 3; return buf; } - + if (likely(exp_raw != 0)) { /* normal number */ sig_bin = sig_raw | ((u64)1 << F64_SIG_BITS); exp_bin = (i32)exp_raw - F64_EXP_BIAS - F64_SIG_BITS; - + /* fast path for small integer number without fraction */ if (-F64_SIG_BITS <= exp_bin && exp_bin <= 0) { if (u64_tz_bits(sig_bin) >= (u32)-exp_bin) { @@ -6362,18 +7428,18 @@ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { return buf; } } - + /* binary to decimal */ f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec); - + /* the sig length is 15 to 17 */ sig_len = 17; sig_len -= (sig_dec < (u64)100000000 * 100000000); sig_len -= (sig_dec < (u64)100000000 * 10000000); - + /* the decimal point position relative to the first digit */ dot_pos = sig_len + exp_dec; - + if (-6 < dot_pos && dot_pos <= 21) { /* no need to write exponent part */ if (dot_pos <= 0) { @@ -6412,15 +7478,15 @@ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { buf = write_f64_exp(exp_dec, end + 1); return buf; } - + } else { /* subnormal number */ sig_bin = sig_raw; exp_bin = 1 - F64_EXP_BIAS - F64_SIG_BITS; - + /* binary to decimal */ f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec); - + /* write significand part */ buf = write_u64_len_1_to_17(sig_dec, buf + 1); hdr[0] = hdr[1]; @@ -6433,7 +7499,7 @@ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { buf += (*buf != '.'); buf[0] = 'e'; buf++; - + /* write exponent part */ buf[0] = '-'; buf++; @@ -6441,7 +7507,7 @@ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { hi = ((u32)exp_dec * 656) >> 16; /* exp / 100 */ lo = (u32)exp_dec - hi * 100; /* exp % 100 */ buf[0] = (u8)((u8)hi + (u8)'0'); - *(v16 *)&buf[1] = *(const v16 *)(digit_table + (lo * 2)); + byte_copy_2(buf + 1, digit_table + lo * 2); buf += 3; return buf; } @@ -6450,18 +7516,18 @@ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { #else /* FP_WRITER */ /** Write a double number (requires 32 bytes buffer). */ -static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { +static_inline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { /* For IEEE 754, `DBL_DECIMAL_DIG` is 17 for round-trip. For non-IEEE formats, 17 is used to avoid buffer overflow, round-trip is not guaranteed. */ -#if defined(DBL_DECIMAL_DIG) +#if defined(DBL_DECIMAL_DIG) && DBL_DECIMAL_DIG != 17 int dig = DBL_DECIMAL_DIG > 17 ? 17 : DBL_DECIMAL_DIG; #else int dig = 17; #endif - + /* The snprintf() function is locale-dependent. For currently known locales, (en, zh, ja, ko, am, he, hi) use '.' as the decimal point, while other @@ -6476,16 +7542,17 @@ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { #else int len = sprintf((char *)buf, "%.*g", dig, val); #endif - + u8 *cur = buf; if (unlikely(len < 1)) return NULL; cur += (*cur == '-'); if (unlikely(!digi_is_digit(*cur))) { /* nan, inf, or bad output */ - if (flg & YYJSON_WRITE_INF_AND_NAN_AS_NULL) { + if (has_write_flag(INF_AND_NAN_AS_NULL)) { byte_copy_4(buf, "null"); return buf + 4; - } else if (flg & YYJSON_WRITE_ALLOW_INF_AND_NAN) { + } + else if (has_write_flag(ALLOW_INF_AND_NAN)) { if (*cur == 'i') { byte_copy_8(cur, "Infinity"); cur += 8; @@ -6774,14 +7841,14 @@ static const u8 esc_single_char_table[512] = { /** Returns the encode table with options. */ static_inline const char_enc_type *get_enc_table_with_flag( yyjson_read_flag flg) { - if (unlikely(flg & YYJSON_WRITE_ESCAPE_UNICODE)) { - if (unlikely(flg & YYJSON_WRITE_ESCAPE_SLASHES)) { + if (has_write_flag(ESCAPE_UNICODE)) { + if (has_write_flag(ESCAPE_SLASHES)) { return enc_table_esc_slash; } else { return enc_table_esc; } } else { - if (unlikely(flg & YYJSON_WRITE_ESCAPE_SLASHES)) { + if (has_write_flag(ESCAPE_SLASHES)) { return enc_table_cpy_slash; } else { return enc_table_cpy; @@ -6795,6 +7862,35 @@ static_inline u8 *write_raw(u8 *cur, const u8 *raw, usize raw_len) { return cur + raw_len; } +/** + Write string no-escape. + @param cur Buffer cursor. + @param str A UTF-8 string, null-terminator is not required. + @param str_len Length of string in bytes. + @return The buffer cursor after string. + */ +static_inline u8 *write_string_noesc(u8 *cur, const u8 *str, usize str_len) { + *cur++ = '"'; + while (str_len >= 16) { + byte_copy_16(cur, str); + cur += 16; + str += 16; + str_len -= 16; + } + while (str_len >= 4) { + byte_copy_4(cur, str); + cur += 4; + str += 4; + str_len -= 4; + } + while (str_len) { + *cur++ = *str++; + str_len -= 1; + } + *cur++ = '"'; + return cur; +} + /** Write UTF-8 string (requires len * 6 + 2 bytes buffer). @param cur Buffer cursor. @@ -6808,8 +7904,8 @@ static_inline u8 *write_raw(u8 *cur, const u8 *raw, usize raw_len) { static_inline u8 *write_string(u8 *cur, bool esc, bool inv, const u8 *str, usize str_len, const char_enc_type *enc_table) { - - /* UTF-8 character mask and pattern, see `read_string` for details. */ + + /* UTF-8 character mask and pattern, see `read_string()` for details. */ #if YYJSON_ENDIAN == YYJSON_BIG_ENDIAN const u16 b2_mask = 0xE0C0UL; const u16 b2_patt = 0xC080UL; @@ -6837,6 +7933,7 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, const u32 b4_err0 = 0x00000004UL; const u32 b4_err1 = 0x00003003UL; #else + /* this should be evaluated at compile-time */ v16_uni b2_mask_uni = {{ 0xE0, 0xC0 }}; v16_uni b2_patt_uni = {{ 0xC0, 0x80 }}; v16_uni b2_requ_uni = {{ 0x1E, 0x00 }}; @@ -6862,36 +7959,36 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, u32 b4_err0 = b4_err0_uni.u; u32 b4_err1 = b4_err1_uni.u; #endif - + #define is_valid_seq_2(uni) ( \ ((uni & b2_mask) == b2_patt) && \ ((uni & b2_requ)) \ ) - + #define is_valid_seq_3(uni) ( \ ((uni & b3_mask) == b3_patt) && \ ((tmp = (uni & b3_requ))) && \ ((tmp != b3_erro)) \ ) - + #define is_valid_seq_4(uni) ( \ ((uni & b4_mask) == b4_patt) && \ ((tmp = (uni & b4_requ))) && \ ((tmp & b4_err0) == 0 || (tmp & b4_err1) == 0) \ ) - + /* The replacement character U+FFFD, used to indicate invalid character. */ - const v32 rep = { 'F', 'F', 'F', 'D' }; - const v32 pre = { '\\', 'u', '0', '0' }; - + const v32 rep = {{ 'F', 'F', 'F', 'D' }}; + const v32 pre = {{ '\\', 'u', '0', '0' }}; + const u8 *src = str; const u8 *end = str + str_len; *cur++ = '"'; - + copy_ascii: /* Copy continuous ASCII, loop unrolling, same as the following code: - + while (end > src) ( if (unlikely(enc_table[*src])) break; *cur++ = *src++; @@ -6899,37 +7996,37 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, */ #define expr_jump(i) \ if (unlikely(enc_table[src[i]])) goto stop_char_##i; - + #define expr_stop(i) \ stop_char_##i: \ memcpy(cur, src, i); \ cur += i; src += i; goto copy_utf8; - + while (end - src >= 16) { - repeat16_incr(expr_jump); + repeat16_incr(expr_jump) byte_copy_16(cur, src); cur += 16; src += 16; } - + while (end - src >= 4) { - repeat4_incr(expr_jump); + repeat4_incr(expr_jump) byte_copy_4(cur, src); cur += 4; src += 4; } - + while (end > src) { - expr_jump(0); + expr_jump(0) *cur++ = *src++; } - + *cur++ = '"'; return cur; - - repeat16_incr(expr_stop); - + + repeat16_incr(expr_stop) + #undef expr_jump #undef expr_stop - + copy_utf8: if (unlikely(src + 4 > end)) { if (end == src) goto copy_end; @@ -6942,16 +8039,27 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, } case CHAR_ENC_CPY_2: { u16 v; +#if YYJSON_DISABLE_UTF8_VALIDATION + byte_copy_2(cur, src); +#else v = byte_load_2(src); if (unlikely(!is_valid_seq_2(v))) goto err_cpy; - byte_copy_2(cur, src); +#endif cur += 2; src += 2; goto copy_utf8; } case CHAR_ENC_CPY_3: { u32 v, tmp; +#if YYJSON_DISABLE_UTF8_VALIDATION + if (likely(src + 4 <= end)) { + byte_copy_4(cur, src); + } else { + byte_copy_2(cur, src); + cur[2] = src[2]; + } +#else if (likely(src + 4 <= end)) { v = byte_load_4(src); if (unlikely(!is_valid_seq_3(v))) goto err_cpy; @@ -6961,22 +8069,26 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, if (unlikely(!is_valid_seq_3(v))) goto err_cpy; byte_copy_4(cur, &v); } +#endif cur += 3; src += 3; goto copy_utf8; } case CHAR_ENC_CPY_4: { u32 v, tmp; +#if YYJSON_DISABLE_UTF8_VALIDATION + byte_copy_4(cur, src); +#else v = byte_load_4(src); if (unlikely(!is_valid_seq_4(v))) goto err_cpy; - byte_copy_4(cur, src); +#endif cur += 4; src += 4; goto copy_utf8; } case CHAR_ENC_ESC_A: { - byte_move_2(cur, &esc_single_char_table[*src * 2]); + byte_copy_2(cur, &esc_single_char_table[*src * 2]); cur += 2; src += 1; goto copy_utf8; @@ -6990,9 +8102,10 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, } case CHAR_ENC_ESC_2: { u16 u, v; +#if !YYJSON_DISABLE_UTF8_VALIDATION v = byte_load_2(src); if (unlikely(!is_valid_seq_2(v))) goto err_esc; - +#endif u = (u16)(((u16)(src[0] & 0x1F) << 6) | ((u16)(src[1] & 0x3F) << 0)); byte_copy_2(cur + 0, &pre); @@ -7005,9 +8118,10 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, case CHAR_ENC_ESC_3: { u16 u; u32 v, tmp; +#if !YYJSON_DISABLE_UTF8_VALIDATION v = byte_load_3(src); if (unlikely(!is_valid_seq_3(v))) goto err_esc; - +#endif u = (u16)(((u16)(src[0] & 0x0F) << 12) | ((u16)(src[1] & 0x3F) << 6) | ((u16)(src[2] & 0x3F) << 0)); @@ -7020,9 +8134,10 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, } case CHAR_ENC_ESC_4: { u32 hi, lo, u, v, tmp; +#if !YYJSON_DISABLE_UTF8_VALIDATION v = byte_load_4(src); if (unlikely(!is_valid_seq_4(v))) goto err_esc; - +#endif u = ((u32)(src[0] & 0x07) << 18) | ((u32)(src[1] & 0x3F) << 12) | ((u32)(src[2] & 0x3F) << 6) | @@ -7045,20 +8160,20 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, } default: break; } - + copy_end: *cur++ = '"'; return cur; - + err_one: if (esc) goto err_esc; else goto err_cpy; - + err_cpy: if (!inv) return NULL; *cur++ = *src++; goto copy_utf8; - + err_esc: if (!inv) return NULL; byte_copy_2(cur + 0, &pre); @@ -7066,7 +8181,7 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, cur += 6; src += 1; goto copy_utf8; - + #undef is_valid_seq_2 #undef is_valid_seq_3 #undef is_valid_seq_4 @@ -7080,15 +8195,15 @@ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, /** Write null (requires 8 bytes buffer). */ static_inline u8 *write_null(u8 *cur) { - v64 v = { 'n', 'u', 'l', 'l', ',', '\n', 0, 0 }; + v64 v = {{ 'n', 'u', 'l', 'l', ',', '\n', 0, 0 }}; byte_copy_8(cur, &v); return cur + 4; } /** Write bool (requires 8 bytes buffer). */ static_inline u8 *write_bool(u8 *cur, bool val) { - v64 v0 = { 'f', 'a', 'l', 's', 'e', ',', '\n', 0 }; - v64 v1 = { 't', 'r', 'u', 'e', ',', '\n', 0, 0 }; + v64 v0 = {{ 'f', 'a', 'l', 's', 'e', ',', '\n', 0 }}; + v64 v1 = {{ 't', 'r', 'u', 'e', ',', '\n', 0, 0 }}; if (val) { byte_copy_8(cur, &v1); } else { @@ -7107,17 +8222,28 @@ static_inline u8 *write_indent(u8 *cur, usize level, usize spaces) { return cur; } +/** Write data to file pointer. */ +static bool write_dat_to_fp(FILE *fp, u8 *dat, usize len, + yyjson_write_err *err) { + if (fwrite(dat, len, 1, fp) != 1) { + err->msg = "file writing failed"; + err->code = YYJSON_WRITE_ERROR_FILE_WRITE; + return false; + } + return true; +} + /** Write data to file. */ static bool write_dat_to_file(const char *path, u8 *dat, usize len, yyjson_write_err *err) { - + #define return_err(_code, _msg) do { \ err->msg = _msg; \ err->code = YYJSON_WRITE_ERROR_##_code; \ if (file) fclose(file); \ return false; \ } while (false) - + FILE *file = fopen_writeonly(path); if (file == NULL) { return_err(FILE_OPEN, "file opening failed"); @@ -7130,7 +8256,7 @@ static bool write_dat_to_file(const char *path, u8 *dat, usize len, return_err(FILE_WRITE, "file closing failed"); } return true; - + #undef return_err } @@ -7162,7 +8288,7 @@ static_inline u8 *yyjson_write_single(yyjson_val *val, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { - + #define return_err(_code, _msg) do { \ if (hdr) alc.free(alc.ctx, (void *)hdr); \ *dat_len = 0; \ @@ -7170,80 +8296,88 @@ static_inline u8 *yyjson_write_single(yyjson_val *val, err->msg = _msg; \ return NULL; \ } while (false) - + #define incr_len(_len) do { \ hdr = (u8 *)alc.malloc(alc.ctx, _len); \ if (!hdr) goto fail_alloc; \ cur = hdr; \ } while (false) - + #define check_str_len(_len) do { \ - if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ + if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) - + u8 *hdr = NULL, *cur; usize str_len; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); - bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; - bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; - + bool cpy = (enc_table == enc_table_cpy); + bool esc = has_write_flag(ESCAPE_UNICODE) != 0; + bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0; + bool newline = has_write_flag(NEWLINE_AT_END) != 0; + const usize end_len = 2; /* '\n' and '\0' */ + switch (unsafe_yyjson_get_type(val)) { case YYJSON_TYPE_RAW: str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); - incr_len(str_len + 1); + incr_len(str_len + end_len); cur = write_raw(cur, str_ptr, str_len); break; - + case YYJSON_TYPE_STR: str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); - incr_len(str_len * 6 + 4); - cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); - if (unlikely(!cur)) goto fail_str; + incr_len(str_len * 6 + 2 + end_len); + if (likely(cpy) && unsafe_yyjson_get_subtype(val)) { + cur = write_string_noesc(cur, str_ptr, str_len); + } else { + cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); + if (unlikely(!cur)) goto fail_str; + } break; - + case YYJSON_TYPE_NUM: - incr_len(32); + incr_len(32 + end_len); cur = write_number(cur, val, flg); if (unlikely(!cur)) goto fail_num; break; - + case YYJSON_TYPE_BOOL: incr_len(8); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); break; - + case YYJSON_TYPE_NULL: incr_len(8); cur = write_null(cur); break; - + case YYJSON_TYPE_ARR: - incr_len(4); + incr_len(2 + end_len); byte_copy_2(cur, "[]"); cur += 2; break; - + case YYJSON_TYPE_OBJ: - incr_len(4); + incr_len(2 + end_len); byte_copy_2(cur, "{}"); cur += 2; break; - + default: goto fail_type; } - + + if (newline) *cur++ = '\n'; *cur = '\0'; *dat_len = (usize)(cur - hdr); memset(err, 0, sizeof(yyjson_write_err)); return hdr; - + fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: @@ -7252,7 +8386,7 @@ static_inline u8 *yyjson_write_single(yyjson_val *val, return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); - + #undef return_err #undef check_str_len #undef incr_len @@ -7265,7 +8399,7 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root, const yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { - + #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ @@ -7273,13 +8407,14 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root, if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) - + #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_write_ctx)); \ - if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ + if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \ + goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ @@ -7292,12 +8427,12 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root, hdr = tmp; \ } \ } while (false) - + #define check_str_len(_len) do { \ - if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ + if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) - + yyjson_val *val; yyjson_type val_type; usize ctn_len, ctn_len_tmp; @@ -7307,9 +8442,11 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root, usize alc_len, alc_inc, ctx_len, ext_len, str_len; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); - bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; - bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; - + bool cpy = (enc_table == enc_table_cpy); + bool esc = has_write_flag(ESCAPE_UNICODE) != 0; + bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0; + bool newline = has_write_flag(NEWLINE_AT_END) != 0; + alc_len = root->uni.ofs / sizeof(yyjson_val); alc_len = alc_len * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_write_ctx)); @@ -7318,15 +8455,15 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root, cur = hdr; end = hdr + alc_len; ctx = (yyjson_write_ctx *)(void *)end; - + doc_begin: - val = (yyjson_val *)root; + val = constcast(yyjson_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); val++; - + val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { @@ -7335,8 +8472,12 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root, str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 16); - cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); - if (unlikely(!cur)) goto fail_str; + if (likely(cpy) && unsafe_yyjson_get_subtype(val)) { + cur = write_string_noesc(cur, str_ptr, str_len); + } else { + cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); + if (unlikely(!cur)) goto fail_str; + } *cur++ = is_key ? ':' : ','; goto val_end; } @@ -7390,13 +8531,13 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root, goto val_end; } goto fail_type; - + val_end: val++; ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; goto val_begin; - + ctn_end: cur--; *cur++ = (u8)(']' | ((u8)ctn_obj << 5)); @@ -7409,13 +8550,18 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root, } else { goto ctn_end; } - + doc_end: + if (newline) { + incr_len(2); + *(cur - 1) = '\n'; + cur++; + } *--cur = '\0'; *dat_len = (usize)(cur - hdr); memset(err, 0, sizeof(yyjson_write_err)); return hdr; - + fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: @@ -7424,7 +8570,7 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root, return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); - + #undef return_err #undef incr_len #undef check_str_len @@ -7437,7 +8583,7 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, const yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { - + #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ @@ -7445,13 +8591,14 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) - + #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_write_ctx)); \ - if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ + if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \ + goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ @@ -7464,12 +8611,12 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, hdr = tmp; \ } \ } while (false) - + #define check_str_len(_len) do { \ - if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ + if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) - + yyjson_val *val; yyjson_type val_type; usize ctn_len, ctn_len_tmp; @@ -7479,10 +8626,12 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, usize alc_len, alc_inc, ctx_len, ext_len, str_len, level; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); - bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; - bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; - usize spaces = (flg & YYJSON_WRITE_PRETTY_TWO_SPACES) ? 2 : 4; - + bool cpy = (enc_table == enc_table_cpy); + bool esc = has_write_flag(ESCAPE_UNICODE) != 0; + bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0; + usize spaces = has_write_flag(PRETTY_TWO_SPACES) ? 2 : 4; + bool newline = has_write_flag(NEWLINE_AT_END) != 0; + alc_len = root->uni.ofs / sizeof(yyjson_val); alc_len = alc_len * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_write_ctx)); @@ -7491,9 +8640,9 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, cur = hdr; end = hdr + alc_len; ctx = (yyjson_write_ctx *)(void *)end; - + doc_begin: - val = (yyjson_val *)root; + val = constcast(yyjson_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; @@ -7501,7 +8650,7 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, *cur++ = '\n'; val++; level = 1; - + val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { @@ -7512,8 +8661,12 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, check_str_len(str_len); incr_len(str_len * 6 + 16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); - cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); - if (unlikely(!cur)) goto fail_str; + if (likely(cpy) && unsafe_yyjson_get_subtype(val)) { + cur = write_string_noesc(cur, str_ptr, str_len); + } else { + cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); + if (unlikely(!cur)) goto fail_str; + } *cur++ = is_key ? ':' : ','; *cur++ = is_key ? ' ' : '\n'; goto val_end; @@ -7583,13 +8736,13 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, goto val_end; } goto fail_type; - + val_end: val++; ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; goto val_begin; - + ctn_end: cur -= 2; *cur++ = '\n'; @@ -7606,13 +8759,17 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, } else { goto ctn_end; } - + doc_end: + if (newline) { + incr_len(2); + *cur++ = '\n'; + } *cur = '\0'; *dat_len = (usize)(cur - hdr); memset(err, 0, sizeof(yyjson_write_err)); return hdr; - + fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: @@ -7621,7 +8778,7 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); - + #undef return_err #undef incr_len #undef check_str_len @@ -7635,23 +8792,18 @@ char *yyjson_val_write_opts(const yyjson_val *val, yyjson_write_err dummy_err; usize dummy_dat_len; yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; - yyjson_val *root = (yyjson_val *)val; - + yyjson_val *root = constcast(yyjson_val *)val; + err = err ? err : &dummy_err; dat_len = dat_len ? dat_len : &dummy_dat_len; - -#if YYJSON_DISABLE_NON_STANDARD - flg &= ~YYJSON_WRITE_ALLOW_INF_AND_NAN; - flg &= ~YYJSON_WRITE_ALLOW_INVALID_UNICODE; -#endif - + if (unlikely(!root)) { *dat_len = 0; err->msg = "input JSON is NULL"; err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; return NULL; } - + if (!unsafe_yyjson_is_ctn(root) || unsafe_yyjson_get_len(root) == 0) { return (char *)yyjson_write_single(root, flg, alc, dat_len, err); } else if (flg & (YYJSON_WRITE_PRETTY | YYJSON_WRITE_PRETTY_TWO_SPACES)) { @@ -7678,9 +8830,9 @@ bool yyjson_val_write_file(const char *path, yyjson_write_err dummy_err; u8 *dat; usize dat_len = 0; - yyjson_val *root = (yyjson_val *)val; + yyjson_val *root = constcast(yyjson_val *)val; bool suc; - + alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; err = err ? err : &dummy_err; if (unlikely(!path || !*path)) { @@ -7688,7 +8840,7 @@ bool yyjson_val_write_file(const char *path, err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; return false; } - + dat = (u8 *)yyjson_val_write_opts(root, flg, alc_ptr, &dat_len, err); if (unlikely(!dat)) return false; suc = write_dat_to_file(path, dat, dat_len, err); @@ -7696,6 +8848,32 @@ bool yyjson_val_write_file(const char *path, return suc; } +bool yyjson_val_write_fp(FILE *fp, + const yyjson_val *val, + yyjson_write_flag flg, + const yyjson_alc *alc_ptr, + yyjson_write_err *err) { + yyjson_write_err dummy_err; + u8 *dat; + usize dat_len = 0; + yyjson_val *root = constcast(yyjson_val *)val; + bool suc; + + alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; + err = err ? err : &dummy_err; + if (unlikely(!fp)) { + err->msg = "input fp is invalid"; + err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; + return false; + } + + dat = (u8 *)yyjson_val_write_opts(root, flg, alc_ptr, &dat_len, err); + if (unlikely(!dat)) return false; + suc = write_dat_to_fp(fp, dat, dat_len, err); + alc_ptr->free(alc_ptr->ctx, dat); + return suc; +} + bool yyjson_write_file(const char *path, const yyjson_doc *doc, yyjson_write_flag flg, @@ -7705,6 +8883,15 @@ bool yyjson_write_file(const char *path, return yyjson_val_write_file(path, root, flg, alc_ptr, err); } +bool yyjson_write_fp(FILE *fp, + const yyjson_doc *doc, + yyjson_write_flag flg, + const yyjson_alc *alc_ptr, + yyjson_write_err *err) { + yyjson_val *root = doc ? doc->root : NULL; + return yyjson_val_write_fp(fp, root, flg, alc_ptr, err); +} + /*============================================================================== @@ -7732,6 +8919,21 @@ static_inline void yyjson_mut_write_ctx_get(yyjson_mut_write_ctx *ctx, *ctn = ctx->ctn; } +/** Get the estimated number of values for the mutable JSON document. */ +static_inline usize yyjson_mut_doc_estimated_val_num( + const yyjson_mut_doc *doc) { + usize sum = 0; + yyjson_val_chunk *chunk = doc->val_pool.chunks; + while (chunk) { + sum += chunk->chunk_size / sizeof(yyjson_mut_val) - 1; + if (chunk == doc->val_pool.chunks) { + sum -= (usize)(doc->val_pool.end - doc->val_pool.cur); + } + chunk = chunk->next; + } + return sum; +} + /** Write single JSON value. */ static_inline u8 *yyjson_mut_write_single(yyjson_mut_val *val, yyjson_write_flag flg, @@ -7744,11 +8946,12 @@ static_inline u8 *yyjson_mut_write_single(yyjson_mut_val *val, /** Write JSON document minify. The root of this document should be a non-empty container. */ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, + usize estimated_val_num, yyjson_write_flag flg, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { - + #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ @@ -7756,13 +8959,14 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) - + #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_mut_write_ctx)); \ - if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ + if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \ + goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ @@ -7775,12 +8979,12 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, hdr = tmp; \ } \ } while (false) - + #define check_str_len(_len) do { \ - if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ + if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) - + yyjson_mut_val *val, *ctn; yyjson_type val_type; usize ctn_len, ctn_len_tmp; @@ -7790,19 +8994,21 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, usize alc_len, alc_inc, ctx_len, ext_len, str_len; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); - bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; - bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; - - alc_len = 0 * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64; + bool cpy = (enc_table == enc_table_cpy); + bool esc = has_write_flag(ESCAPE_UNICODE) != 0; + bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0; + bool newline = has_write_flag(NEWLINE_AT_END) != 0; + + alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx)); hdr = (u8 *)alc.malloc(alc.ctx, alc_len); if (!hdr) goto fail_alloc; cur = hdr; end = hdr + alc_len; ctx = (yyjson_mut_write_ctx *)(void *)end; - + doc_begin: - val = (yyjson_mut_val *)root; + val = constcast(yyjson_mut_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; @@ -7810,7 +9016,7 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, ctn = val; val = (yyjson_mut_val *)val->uni.ptr; /* tail */ val = ctn_obj ? val->next->next : val->next; - + val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { @@ -7819,8 +9025,12 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 16); - cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); - if (unlikely(!cur)) goto fail_str; + if (likely(cpy) && unsafe_yyjson_get_subtype(val)) { + cur = write_string_noesc(cur, str_ptr, str_len); + } else { + cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); + if (unlikely(!cur)) goto fail_str; + } *cur++ = is_key ? ':' : ','; goto val_end; } @@ -7876,13 +9086,13 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, goto val_end; } goto fail_type; - + val_end: ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; val = val->next; goto val_begin; - + ctn_end: cur--; *cur++ = (u8)(']' | ((u8)ctn_obj << 5)); @@ -7896,14 +9106,19 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, } else { goto ctn_end; } - + doc_end: + if (newline) { + incr_len(2); + *(cur - 1) = '\n'; + cur++; + } *--cur = '\0'; *dat_len = (usize)(cur - hdr); err->code = YYJSON_WRITE_SUCCESS; err->msg = "success"; return hdr; - + fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: @@ -7912,7 +9127,7 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); - + #undef return_err #undef incr_len #undef check_str_len @@ -7921,11 +9136,12 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, /** Write JSON document pretty. The root of this document should be a non-empty container. */ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, + usize estimated_val_num, yyjson_write_flag flg, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { - + #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ @@ -7933,13 +9149,14 @@ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) - + #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_mut_write_ctx)); \ - if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ + if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \ + goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ @@ -7952,12 +9169,12 @@ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, hdr = tmp; \ } \ } while (false) - + #define check_str_len(_len) do { \ - if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ + if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) - + yyjson_mut_val *val, *ctn; yyjson_type val_type; usize ctn_len, ctn_len_tmp; @@ -7967,20 +9184,22 @@ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, usize alc_len, alc_inc, ctx_len, ext_len, str_len, level; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); - bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; - bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; - usize spaces = (flg & YYJSON_WRITE_PRETTY_TWO_SPACES) ? 2 : 4; - - alc_len = 0 * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64; + bool cpy = (enc_table == enc_table_cpy); + bool esc = has_write_flag(ESCAPE_UNICODE) != 0; + bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0; + usize spaces = has_write_flag(PRETTY_TWO_SPACES) ? 2 : 4; + bool newline = has_write_flag(NEWLINE_AT_END) != 0; + + alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx)); hdr = (u8 *)alc.malloc(alc.ctx, alc_len); if (!hdr) goto fail_alloc; cur = hdr; end = hdr + alc_len; ctx = (yyjson_mut_write_ctx *)(void *)end; - + doc_begin: - val = (yyjson_mut_val *)root; + val = constcast(yyjson_mut_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; @@ -7990,7 +9209,7 @@ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, val = (yyjson_mut_val *)val->uni.ptr; /* tail */ val = ctn_obj ? val->next->next : val->next; level = 1; - + val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { @@ -8001,8 +9220,12 @@ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, check_str_len(str_len); incr_len(str_len * 6 + 16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); - cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); - if (unlikely(!cur)) goto fail_str; + if (likely(cpy) && unsafe_yyjson_get_subtype(val)) { + cur = write_string_noesc(cur, str_ptr, str_len); + } else { + cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); + if (unlikely(!cur)) goto fail_str; + } *cur++ = is_key ? ':' : ','; *cur++ = is_key ? ' ' : '\n'; goto val_end; @@ -8074,13 +9297,13 @@ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, goto val_end; } goto fail_type; - + val_end: ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; val = val->next; goto val_begin; - + ctn_end: cur -= 2; *cur++ = '\n'; @@ -8098,14 +9321,18 @@ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, } else { goto ctn_end; } - + doc_end: + if (newline) { + incr_len(2); + *cur++ = '\n'; + } *cur = '\0'; *dat_len = (usize)(cur - hdr); err->code = YYJSON_WRITE_SUCCESS; err->msg = "success"; return hdr; - + fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: @@ -8114,53 +9341,68 @@ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); - + #undef return_err #undef incr_len #undef check_str_len } -char *yyjson_mut_val_write_opts(const yyjson_mut_val *val, - yyjson_write_flag flg, - const yyjson_alc *alc_ptr, - usize *dat_len, - yyjson_write_err *err) { +static char *yyjson_mut_write_opts_impl(const yyjson_mut_val *val, + usize estimated_val_num, + yyjson_write_flag flg, + const yyjson_alc *alc_ptr, + usize *dat_len, + yyjson_write_err *err) { yyjson_write_err dummy_err; usize dummy_dat_len; yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; - yyjson_mut_val *root = (yyjson_mut_val *)val; - + yyjson_mut_val *root = constcast(yyjson_mut_val *)val; + err = err ? err : &dummy_err; dat_len = dat_len ? dat_len : &dummy_dat_len; - -#if YYJSON_DISABLE_NON_STANDARD - flg &= ~YYJSON_WRITE_ALLOW_INF_AND_NAN; - flg &= ~YYJSON_WRITE_ALLOW_INVALID_UNICODE; -#endif - + if (unlikely(!root)) { *dat_len = 0; err->msg = "input JSON is NULL"; err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; return NULL; } - + if (!unsafe_yyjson_is_ctn(root) || unsafe_yyjson_get_len(root) == 0) { return (char *)yyjson_mut_write_single(root, flg, alc, dat_len, err); } else if (flg & (YYJSON_WRITE_PRETTY | YYJSON_WRITE_PRETTY_TWO_SPACES)) { - return (char *)yyjson_mut_write_pretty(root, flg, alc, dat_len, err); + return (char *)yyjson_mut_write_pretty(root, estimated_val_num, + flg, alc, dat_len, err); } else { - return (char *)yyjson_mut_write_minify(root, flg, alc, dat_len, err); + return (char *)yyjson_mut_write_minify(root, estimated_val_num, + flg, alc, dat_len, err); } } +char *yyjson_mut_val_write_opts(const yyjson_mut_val *val, + yyjson_write_flag flg, + const yyjson_alc *alc_ptr, + usize *dat_len, + yyjson_write_err *err) { + return yyjson_mut_write_opts_impl(val, 0, flg, alc_ptr, dat_len, err); +} + char *yyjson_mut_write_opts(const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { - yyjson_mut_val *root = doc ? doc->root : NULL; - return yyjson_mut_val_write_opts(root, flg, alc_ptr, dat_len, err); + yyjson_mut_val *root; + usize estimated_val_num; + if (likely(doc)) { + root = doc->root; + estimated_val_num = yyjson_mut_doc_estimated_val_num(doc); + } else { + root = NULL; + estimated_val_num = 0; + } + return yyjson_mut_write_opts_impl(root, estimated_val_num, + flg, alc_ptr, dat_len, err); } bool yyjson_mut_val_write_file(const char *path, @@ -8171,9 +9413,9 @@ bool yyjson_mut_val_write_file(const char *path, yyjson_write_err dummy_err; u8 *dat; usize dat_len = 0; - yyjson_mut_val *root = (yyjson_mut_val *)val; + yyjson_mut_val *root = constcast(yyjson_mut_val *)val; bool suc; - + alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; err = err ? err : &dummy_err; if (unlikely(!path || !*path)) { @@ -8181,13 +9423,38 @@ bool yyjson_mut_val_write_file(const char *path, err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; return false; } - + dat = (u8 *)yyjson_mut_val_write_opts(root, flg, alc_ptr, &dat_len, err); if (unlikely(!dat)) return false; suc = write_dat_to_file(path, dat, dat_len, err); alc_ptr->free(alc_ptr->ctx, dat); return suc; - +} + +bool yyjson_mut_val_write_fp(FILE *fp, + const yyjson_mut_val *val, + yyjson_write_flag flg, + const yyjson_alc *alc_ptr, + yyjson_write_err *err) { + yyjson_write_err dummy_err; + u8 *dat; + usize dat_len = 0; + yyjson_mut_val *root = constcast(yyjson_mut_val *)val; + bool suc; + + alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; + err = err ? err : &dummy_err; + if (unlikely(!fp)) { + err->msg = "input fp is invalid"; + err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; + return false; + } + + dat = (u8 *)yyjson_mut_val_write_opts(root, flg, alc_ptr, &dat_len, err); + if (unlikely(!dat)) return false; + suc = write_dat_to_fp(fp, dat, dat_len, err); + alc_ptr->free(alc_ptr->ctx, dat); + return suc; } bool yyjson_mut_write_file(const char *path, @@ -8199,13 +9466,14 @@ bool yyjson_mut_write_file(const char *path, return yyjson_mut_val_write_file(path, root, flg, alc_ptr, err); } -#endif /* YYJSON_DISABLE_WRITER */ - - - -/*============================================================================== - * Compiler Hint End - *============================================================================*/ +bool yyjson_mut_write_fp(FILE *fp, + const yyjson_mut_doc *doc, + yyjson_write_flag flg, + const yyjson_alc *alc_ptr, + yyjson_write_err *err) { + yyjson_mut_val *root = doc ? doc->root : NULL; + return yyjson_mut_val_write_fp(fp, root, flg, alc_ptr, err); +} #if defined(__clang__) # pragma clang diagnostic pop @@ -8216,3 +9484,7 @@ bool yyjson_mut_write_file(const char *path, #elif defined(_MSC_VER) # pragma warning(pop) #endif /* warning suppress end */ + +#endif /* YYJSON_DISABLE_WRITER */ + +} // namespace duckdb_yyjson diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 537ea890f71..cdbd746e172 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -2,9 +2,6 @@ if(NOT SUN AND BUILD_SHELL) add_subdirectory(sqlite3_api_wrapper) add_subdirectory(shell) endif() -if(JDBC_DRIVER) - add_subdirectory(jdbc) -endif() if(BUILD_ODBC_DRIVER) add_subdirectory(odbc) diff --git a/tools/jdbc/CMakeLists.txt b/tools/jdbc/CMakeLists.txt deleted file mode 100644 index 5be0deb773d..00000000000 --- a/tools/jdbc/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -find_package(Java 1.8) -find_package(JNI) - -cmake_minimum_required(VERSION 3.11.0) - -if(NOT JNI_FOUND OR NOT Java_FOUND) - message(FATAL_ERROR "No compatible Java/JNI found") -endif() - -include(UseJava) -project(DuckDBJDummy NONE) - -file(GLOB_RECURSE JAVA_SRC_FILES src/main/java/org/duckdb/*.java) -file(GLOB_RECURSE JAVA_TEST_FILES src/test/java/org/duckdb/*.java) - -set(CMAKE_JAVA_COMPILE_FLAGS -source 1.8 -target 1.8 -encoding utf-8) - -add_jar(duckdb_jdbc ${JAVA_SRC_FILES} META-INF/services/java.sql.Driver - GENERATE_NATIVE_HEADERS duckdb-native) -add_jar(duckdb_jdbc_tests ${JAVA_TEST_FILES} INCLUDE_JARS duckdb_jdbc) - -include_directories(../../extension/parquet/include) - -add_library(duckdb_java SHARED src/jni/duckdb_java.cpp src/jni/functions.cpp) -target_compile_options(duckdb_java PRIVATE -fexceptions) -target_link_libraries(duckdb_java duckdb-native duckdb_static parquet_extension) - -if(APPLE) - set(OS_ARCH universal) -endif() -if(OVERRIDE_JDBC_OS_ARCH) - set(OS_ARCH ${OVERRIDE_JDBC_OS_ARCH}) -endif() -string(JOIN "_" LIB_SUFFIX ".so" ${OS_NAME} ${OS_ARCH}) -set_target_properties(duckdb_java PROPERTIES SUFFIX ${LIB_SUFFIX}) -set_target_properties(duckdb_java PROPERTIES PREFIX "lib") - -add_custom_command( - OUTPUT dummy_jdbc_target - DEPENDS duckdb_java duckdb_jdbc duckdb_jdbc_tests - COMMAND ${Java_JAR_EXECUTABLE} uf duckdb_jdbc.jar -C - $ $) - -add_custom_target(jdbc ALL DEPENDS dummy_jdbc_target) diff --git a/tools/jdbc/META-INF/services/java.sql.Driver b/tools/jdbc/META-INF/services/java.sql.Driver deleted file mode 100644 index 2be982c9bb4..00000000000 --- a/tools/jdbc/META-INF/services/java.sql.Driver +++ /dev/null @@ -1 +0,0 @@ -org.duckdb.DuckDBDriver diff --git a/tools/jdbc/Makefile b/tools/jdbc/Makefile deleted file mode 100644 index b3760a3266c..00000000000 --- a/tools/jdbc/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -ifeq ($(OS),Windows_NT) - # windows is weird - SEP=";" - JARS=tools/jdbc -else - SEP=":" - JARS=build/debug/tools/jdbc -endif - -JAR=$(JARS)/duckdb_jdbc.jar -TEST_JAR=$(JARS)/duckdb_jdbc_tests.jar -CP=$(JAR)$(SEP)$(TEST_JAR) - -test_debug: ../../$(JAR) ../../$(TEST_JAR) - cd ../.. && java -cp $(CP) org.duckdb.TestDuckDBJDBC - -test_release: ../../$(subst debug,release,$(JAR)) ../../$(subst debug,release,$(TEST_JAR)) - cd ../.. && java -cp $(subst debug,release,$(CP)) org.duckdb.TestDuckDBJDBC diff --git a/tools/jdbc/README b/tools/jdbc/README new file mode 100644 index 00000000000..32a311f885e --- /dev/null +++ b/tools/jdbc/README @@ -0,0 +1 @@ +The DuckDB Java/JDBC client has moved to https://github.com/duckdb/duckdb-java \ No newline at end of file diff --git a/tools/jdbc/README.md b/tools/jdbc/README.md deleted file mode 100644 index 1ef19be422e..00000000000 --- a/tools/jdbc/README.md +++ /dev/null @@ -1,27 +0,0 @@ - -It's required to have a JDK installed to build. -Make sure the `JAVA_HOME` environment variable is set. - -If you are on a Mac and install `openjdk` via `brew` then additionally, it's required to set: -``` -export JAVA_AWT_LIBRARY=$JAVA_HOME/libexec/openjdk.jdk/Contents/Home/lib -``` -because the [`FindJNI.cmake`](https://cmake.org/cmake/help/latest/module/FindJNI.html) module doesn't look there for the `awt` library. - -### Development - -Be sure to build with `DISABLE_SANITIZER=1` and `BUILD_JDBC=1` enabled - -This will produce two jars in the build folder: -`build//tools/jdbc/duckdb_jdbc.jar` -`build//tools/jdbc/duckdb_jdbc_tests.jar` - -The tests can be ran using this command (taking a `debug` build for example) -``` -java -cp "build/debug/tools/jdbc/duckdb_jdbc_tests.jar:build/debug/tools/jdbc/duckdb_jdbc.jar" org/duckdb/TestDuckDBJDBC -``` - -This optionally takes an argument to only run a single test, for example: -``` -java -cp "build/debug/tools/jdbc/duckdb_jdbc_tests.jar:build/debug/tools/jdbc/duckdb_jdbc.jar" org/duckdb/TestDuckDBJDBC test_valid_but_local_config_throws_exception -``` diff --git a/tools/jdbc/duckdb_extension_config.cmake b/tools/jdbc/duckdb_extension_config.cmake deleted file mode 100644 index c274e07970c..00000000000 --- a/tools/jdbc/duckdb_extension_config.cmake +++ /dev/null @@ -1,8 +0,0 @@ -################################################################################ -# JDBC DuckDB extension config -################################################################################ -# -# This is the default extension configuration for JDBC builds. Basically it means that all these extensions are -# "baked in" to the python binaries. -duckdb_extension_load(parquet) -duckdb_extension_load(icu) \ No newline at end of file diff --git a/tools/jdbc/generator.py b/tools/jdbc/generator.py deleted file mode 100644 index 7860b140548..00000000000 --- a/tools/jdbc/generator.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -import header2whatever -from CppHeaderParser.CppHeaderParser import CppMethod - - -def function_hook(fn: CppMethod, config): - name = fn['name'] - params = fn['parameters'] - names = ['env'] + [f'param{i}' for i, param in enumerate(params[1:])] - return_type = fn['rtnType'].split(' ', 1)[1] - return_type = return_type.rsplit(' ', 1)[0] - - fn.update( - { - 'name': name, - 'names': ', '.join(names), - 'params': ', '.join(f'{param["type"]} {name}' for param, name in zip(params, names)), - 'return_type': return_type, - 'short_name': ( - '_duckdb_jdbc_' + name.replace('Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1', '').replace('1', '') - ), - } - ) - - -if __name__ == '__main__': - header2whatever.batch_convert('header2whatever.yaml', 'src/jni', '.') diff --git a/tools/jdbc/header2whatever.yaml b/tools/jdbc/header2whatever.yaml deleted file mode 100644 index 9225678c752..00000000000 --- a/tools/jdbc/header2whatever.yaml +++ /dev/null @@ -1,8 +0,0 @@ -- headers: - - "../../build/debug/tools/jdbc/CMakeFiles/duckdb_jdbc.dir/native_headers/org_duckdb_DuckDBNative.h" - hooks: generator.py - templates: - - src: "src/jni/functions.hpp.template" - dst: "functions.hpp" - - src: "src/jni/functions.cpp.template" - dst: "functions.cpp" diff --git a/tools/jdbc/src/jni/duckdb_java.cpp b/tools/jdbc/src/jni/duckdb_java.cpp deleted file mode 100644 index f7d3a4a9af2..00000000000 --- a/tools/jdbc/src/jni/duckdb_java.cpp +++ /dev/null @@ -1,1171 +0,0 @@ -#include "functions.hpp" -#include "duckdb.hpp" -#include "duckdb/main/client_context.hpp" -#include "duckdb/common/shared_ptr.hpp" -#include "duckdb/main/client_data.hpp" -#include "duckdb/catalog/catalog_search_path.hpp" -#include "duckdb/main/appender.hpp" -#include "duckdb/common/operator/cast_operators.hpp" -#include "duckdb/main/db_instance_cache.hpp" -#include "duckdb/common/arrow/result_arrow_wrapper.hpp" -#include "duckdb/function/table/arrow.hpp" -#include "duckdb/main/database_manager.hpp" -#include "duckdb/parser/parsed_data/create_type_info.hpp" - -using namespace duckdb; -using namespace std; - -static jint JNI_VERSION = JNI_VERSION_1_6; - -// Static global vars of cached Java classes, methods and fields -static jclass J_Charset; -static jmethodID J_Charset_decode; -static jobject J_Charset_UTF8; - -static jclass J_CharBuffer; -static jmethodID J_CharBuffer_toString; - -static jmethodID J_String_getBytes; - -static jclass J_SQLException; - -static jclass J_Bool; -static jclass J_Byte; -static jclass J_Short; -static jclass J_Int; -static jclass J_Long; -static jclass J_Float; -static jclass J_Double; -static jclass J_String; -static jclass J_Timestamp; -static jclass J_TimestampTZ; -static jclass J_Decimal; -static jclass J_ByteArray; - -static jmethodID J_Bool_booleanValue; -static jmethodID J_Byte_byteValue; -static jmethodID J_Short_shortValue; -static jmethodID J_Int_intValue; -static jmethodID J_Long_longValue; -static jmethodID J_Float_floatValue; -static jmethodID J_Double_doubleValue; -static jmethodID J_Timestamp_getMicrosEpoch; -static jmethodID J_TimestampTZ_getMicrosEpoch; -static jmethodID J_Decimal_precision; -static jmethodID J_Decimal_scale; -static jmethodID J_Decimal_scaleByPowTen; -static jmethodID J_Decimal_toPlainString; -static jmethodID J_Decimal_longValue; - -static jclass J_DuckResultSetMeta; -static jmethodID J_DuckResultSetMeta_init; - -static jclass J_DuckVector; -static jmethodID J_DuckVector_init; -static jfieldID J_DuckVector_constlen; -static jfieldID J_DuckVector_varlen; - -static jclass J_DuckArray; -static jmethodID J_DuckArray_init; - -static jclass J_DuckStruct; -static jmethodID J_DuckStruct_init; - -static jclass J_ByteBuffer; - -static jmethodID J_Map_entrySet; -static jmethodID J_Set_iterator; -static jmethodID J_Iterator_hasNext; -static jmethodID J_Iterator_next; -static jmethodID J_Entry_getKey; -static jmethodID J_Entry_getValue; - -static jclass J_UUID; -static jmethodID J_UUID_getMostSignificantBits; -static jmethodID J_UUID_getLeastSignificantBits; - -static jclass J_DuckDBDate; -static jmethodID J_DuckDBDate_getDaysSinceEpoch; - -static jmethodID J_Object_toString; - -void ThrowJNI(JNIEnv *env, const char *message) { - D_ASSERT(J_SQLException); - env->ThrowNew(J_SQLException, message); -} - -static duckdb::vector toFree; - -static jclass GetClassRef(JNIEnv *env, const string &name) { - jclass tmpLocalRef; - tmpLocalRef = env->FindClass(name.c_str()); - D_ASSERT(tmpLocalRef); - jclass globalRef = (jclass)env->NewGlobalRef(tmpLocalRef); - D_ASSERT(globalRef); - toFree.emplace_back(globalRef); - env->DeleteLocalRef(tmpLocalRef); - return globalRef; -} - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { - // Get JNIEnv from vm - JNIEnv *env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION) != JNI_OK) { - return JNI_ERR; - } - - jclass tmpLocalRef; - - tmpLocalRef = env->FindClass("java/nio/charset/Charset"); - J_Charset = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - - jmethodID forName = env->GetStaticMethodID(J_Charset, "forName", "(Ljava/lang/String;)Ljava/nio/charset/Charset;"); - J_Charset_decode = env->GetMethodID(J_Charset, "decode", "(Ljava/nio/ByteBuffer;)Ljava/nio/CharBuffer;"); - jobject charset = env->CallStaticObjectMethod(J_Charset, forName, env->NewStringUTF("UTF-8")); - J_Charset_UTF8 = env->NewGlobalRef(charset); // Prevent garbage collector from cleaning this up. - - tmpLocalRef = env->FindClass("java/nio/CharBuffer"); - J_CharBuffer = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - - J_CharBuffer_toString = env->GetMethodID(J_CharBuffer, "toString", "()Ljava/lang/String;"); - - tmpLocalRef = env->FindClass("java/sql/SQLException"); - J_SQLException = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - - tmpLocalRef = env->FindClass("java/lang/Boolean"); - J_Bool = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - tmpLocalRef = env->FindClass("java/lang/Byte"); - J_Byte = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - tmpLocalRef = env->FindClass("java/lang/Short"); - J_Short = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - tmpLocalRef = env->FindClass("java/lang/Integer"); - J_Int = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - tmpLocalRef = env->FindClass("java/lang/Long"); - J_Long = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - tmpLocalRef = env->FindClass("java/lang/Float"); - J_Float = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - tmpLocalRef = env->FindClass("java/lang/Double"); - J_Double = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - tmpLocalRef = env->FindClass("java/lang/String"); - J_String = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - tmpLocalRef = env->FindClass("org/duckdb/DuckDBTimestamp"); - J_Timestamp = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - tmpLocalRef = env->FindClass("org/duckdb/DuckDBTimestampTZ"); - J_TimestampTZ = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - - J_DuckDBDate = GetClassRef(env, "org/duckdb/DuckDBDate"); - J_DuckDBDate_getDaysSinceEpoch = env->GetMethodID(J_DuckDBDate, "getDaysSinceEpoch", "()J"); - D_ASSERT(J_DuckDBDate_getDaysSinceEpoch); - - tmpLocalRef = env->FindClass("java/math/BigDecimal"); - J_Decimal = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - tmpLocalRef = env->FindClass("[B"); - J_ByteArray = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - - tmpLocalRef = env->FindClass("java/util/Map"); - J_Map_entrySet = env->GetMethodID(tmpLocalRef, "entrySet", "()Ljava/util/Set;"); - env->DeleteLocalRef(tmpLocalRef); - - tmpLocalRef = env->FindClass("java/util/Set"); - J_Set_iterator = env->GetMethodID(tmpLocalRef, "iterator", "()Ljava/util/Iterator;"); - env->DeleteLocalRef(tmpLocalRef); - - tmpLocalRef = env->FindClass("java/util/Iterator"); - J_Iterator_hasNext = env->GetMethodID(tmpLocalRef, "hasNext", "()Z"); - J_Iterator_next = env->GetMethodID(tmpLocalRef, "next", "()Ljava/lang/Object;"); - env->DeleteLocalRef(tmpLocalRef); - - tmpLocalRef = env->FindClass("java/util/UUID"); - J_UUID = (jclass)env->NewGlobalRef(tmpLocalRef); - J_UUID_getMostSignificantBits = env->GetMethodID(J_UUID, "getMostSignificantBits", "()J"); - J_UUID_getLeastSignificantBits = env->GetMethodID(J_UUID, "getLeastSignificantBits", "()J"); - env->DeleteLocalRef(tmpLocalRef); - - tmpLocalRef = env->FindClass("org/duckdb/DuckDBArray"); - D_ASSERT(tmpLocalRef); - J_DuckArray = (jclass)env->NewGlobalRef(tmpLocalRef); - J_DuckArray_init = env->GetMethodID(J_DuckArray, "", "(Lorg/duckdb/DuckDBVector;II)V"); - D_ASSERT(J_DuckArray_init); - env->DeleteLocalRef(tmpLocalRef); - - tmpLocalRef = env->FindClass("org/duckdb/DuckDBStruct"); - D_ASSERT(tmpLocalRef); - J_DuckStruct = (jclass)env->NewGlobalRef(tmpLocalRef); - J_DuckStruct_init = - env->GetMethodID(J_DuckStruct, "", "([Ljava/lang/String;[Lorg/duckdb/DuckDBVector;ILjava/lang/String;)V"); - D_ASSERT(J_DuckStruct_init); - env->DeleteLocalRef(tmpLocalRef); - - tmpLocalRef = env->FindClass("java/util/Map$Entry"); - J_Entry_getKey = env->GetMethodID(tmpLocalRef, "getKey", "()Ljava/lang/Object;"); - J_Entry_getValue = env->GetMethodID(tmpLocalRef, "getValue", "()Ljava/lang/Object;"); - env->DeleteLocalRef(tmpLocalRef); - - J_Bool_booleanValue = env->GetMethodID(J_Bool, "booleanValue", "()Z"); - J_Byte_byteValue = env->GetMethodID(J_Byte, "byteValue", "()B"); - J_Short_shortValue = env->GetMethodID(J_Short, "shortValue", "()S"); - J_Int_intValue = env->GetMethodID(J_Int, "intValue", "()I"); - J_Long_longValue = env->GetMethodID(J_Long, "longValue", "()J"); - J_Float_floatValue = env->GetMethodID(J_Float, "floatValue", "()F"); - J_Double_doubleValue = env->GetMethodID(J_Double, "doubleValue", "()D"); - J_Timestamp_getMicrosEpoch = env->GetMethodID(J_Timestamp, "getMicrosEpoch", "()J"); - J_TimestampTZ_getMicrosEpoch = env->GetMethodID(J_TimestampTZ, "getMicrosEpoch", "()J"); - J_Decimal_precision = env->GetMethodID(J_Decimal, "precision", "()I"); - J_Decimal_scale = env->GetMethodID(J_Decimal, "scale", "()I"); - J_Decimal_scaleByPowTen = env->GetMethodID(J_Decimal, "scaleByPowerOfTen", "(I)Ljava/math/BigDecimal;"); - J_Decimal_toPlainString = env->GetMethodID(J_Decimal, "toPlainString", "()Ljava/lang/String;"); - J_Decimal_longValue = env->GetMethodID(J_Decimal, "longValue", "()J"); - - tmpLocalRef = env->FindClass("org/duckdb/DuckDBResultSetMetaData"); - J_DuckResultSetMeta = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - - J_DuckResultSetMeta_init = - env->GetMethodID(J_DuckResultSetMeta, "", - "(II[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V"); - - tmpLocalRef = env->FindClass("org/duckdb/DuckDBVector"); - J_DuckVector = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - - J_String_getBytes = env->GetMethodID(J_String, "getBytes", "(Ljava/nio/charset/Charset;)[B"); - - J_DuckVector_init = env->GetMethodID(J_DuckVector, "", "(Ljava/lang/String;I[Z)V"); - J_DuckVector_constlen = env->GetFieldID(J_DuckVector, "constlen_data", "Ljava/nio/ByteBuffer;"); - J_DuckVector_varlen = env->GetFieldID(J_DuckVector, "varlen_data", "[Ljava/lang/Object;"); - - tmpLocalRef = env->FindClass("java/nio/ByteBuffer"); - J_ByteBuffer = (jclass)env->NewGlobalRef(tmpLocalRef); - env->DeleteLocalRef(tmpLocalRef); - - tmpLocalRef = env->FindClass("java/lang/Object"); - J_Object_toString = env->GetMethodID(tmpLocalRef, "toString", "()Ljava/lang/String;"); - env->DeleteLocalRef(tmpLocalRef); - - return JNI_VERSION; -} - -JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { - // Get JNIEnv from vm - JNIEnv *env; - vm->GetEnv(reinterpret_cast(&env), JNI_VERSION); - - env->DeleteGlobalRef(J_Charset); - env->DeleteGlobalRef(J_CharBuffer); - env->DeleteGlobalRef(J_Charset_UTF8); - env->DeleteGlobalRef(J_SQLException); - env->DeleteGlobalRef(J_Bool); - env->DeleteGlobalRef(J_Byte); - env->DeleteGlobalRef(J_Short); - env->DeleteGlobalRef(J_Int); - env->DeleteGlobalRef(J_Long); - env->DeleteGlobalRef(J_Float); - env->DeleteGlobalRef(J_Double); - env->DeleteGlobalRef(J_String); - env->DeleteGlobalRef(J_Timestamp); - env->DeleteGlobalRef(J_TimestampTZ); - env->DeleteGlobalRef(J_Decimal); - env->DeleteGlobalRef(J_DuckResultSetMeta); - env->DeleteGlobalRef(J_DuckVector); - env->DeleteGlobalRef(J_ByteBuffer); - - for (auto &clazz : toFree) { - env->DeleteGlobalRef(clazz); - } -} - -static string byte_array_to_string(JNIEnv *env, jbyteArray ba_j) { - idx_t len = env->GetArrayLength(ba_j); - string ret; - ret.resize(len); - - jbyte *bytes = (jbyte *)env->GetByteArrayElements(ba_j, NULL); - - for (idx_t i = 0; i < len; i++) { - ret[i] = bytes[i]; - } - env->ReleaseByteArrayElements(ba_j, bytes, 0); - - return ret; -} - -static string jstring_to_string(JNIEnv *env, jstring string_j) { - jbyteArray bytes = (jbyteArray)env->CallObjectMethod(string_j, J_String_getBytes, J_Charset_UTF8); - return byte_array_to_string(env, bytes); -} - -static jobject decode_charbuffer_to_jstring(JNIEnv *env, const char *d_str, idx_t d_str_len) { - auto bb = env->NewDirectByteBuffer((void *)d_str, d_str_len); - auto j_cb = env->CallObjectMethod(J_Charset_UTF8, J_Charset_decode, bb); - auto j_str = env->CallObjectMethod(j_cb, J_CharBuffer_toString); - return j_str; -} - -static Value create_value_from_bigdecimal(JNIEnv *env, jobject decimal) { - jint precision = env->CallIntMethod(decimal, J_Decimal_precision); - jint scale = env->CallIntMethod(decimal, J_Decimal_scale); - - // Java BigDecimal type can have scale that exceeds the precision - // Which our DECIMAL type does not support (assert(width >= scale)) - if (scale > precision) { - precision = scale; - } - - // DECIMAL scale is unsigned, so negative values are not supported - if (scale < 0) { - throw InvalidInputException("Converting from a BigDecimal with negative scale is not supported"); - } - - Value val; - - if (precision <= 18) { // normal sizes -> avoid string processing - jobject no_point_dec = env->CallObjectMethod(decimal, J_Decimal_scaleByPowTen, scale); - jlong result = env->CallLongMethod(no_point_dec, J_Decimal_longValue); - val = Value::DECIMAL((int64_t)result, (uint8_t)precision, (uint8_t)scale); - } else if (precision <= 38) { // larger than int64 -> get string and cast - jobject str_val = env->CallObjectMethod(decimal, J_Decimal_toPlainString); - auto *str_char = env->GetStringUTFChars((jstring)str_val, 0); - val = Value(str_char); - val = val.DefaultCastAs(LogicalType::DECIMAL(precision, scale)); - env->ReleaseStringUTFChars((jstring)str_val, str_char); - } - - return val; -} - -/** - * Associates a duckdb::Connection with a duckdb::DuckDB. The DB may be shared amongst many ConnectionHolders, but the - * Connection is unique to this holder. Every Java DuckDBConnection has exactly 1 of these holders, and they are never - * shared. The holder is freed when the DuckDBConnection is closed. When the last holder sharing a DuckDB is freed, the - * DuckDB is released as well. - */ -struct ConnectionHolder { - const duckdb::shared_ptr db; - const duckdb::unique_ptr connection; - - ConnectionHolder(duckdb::shared_ptr _db) - : db(_db), connection(make_uniq(*_db)) { - } -}; - -/** - * Throws a SQLException and returns nullptr if a valid Connection can't be retrieved from the buffer. - */ -static Connection *get_connection(JNIEnv *env, jobject conn_ref_buf) { - if (!conn_ref_buf) { - throw ConnectionException("Invalid connection"); - } - auto conn_holder = (ConnectionHolder *)env->GetDirectBufferAddress(conn_ref_buf); - if (!conn_holder) { - throw ConnectionException("Invalid connection"); - } - auto conn_ref = conn_holder->connection.get(); - if (!conn_ref || !conn_ref->context) { - throw ConnectionException("Invalid connection"); - } - - return conn_ref; -} - -//! The database instance cache, used so that multiple connections to the same file point to the same database object -duckdb::DBInstanceCache instance_cache; - -static const char *const JDBC_STREAM_RESULTS = "jdbc_stream_results"; -jobject _duckdb_jdbc_startup(JNIEnv *env, jclass, jbyteArray database_j, jboolean read_only, jobject props) { - auto database = byte_array_to_string(env, database_j); - DBConfig config; - config.SetOptionByName("duckdb_api", "java"); - config.AddExtensionOption( - JDBC_STREAM_RESULTS, - "Whether to stream results. Only one ResultSet on a connection can be open at once when true", - LogicalType::BOOLEAN); - if (read_only) { - config.options.access_mode = AccessMode::READ_ONLY; - } - jobject entry_set = env->CallObjectMethod(props, J_Map_entrySet); - jobject iterator = env->CallObjectMethod(entry_set, J_Set_iterator); - - while (env->CallBooleanMethod(iterator, J_Iterator_hasNext)) { - jobject pair = env->CallObjectMethod(iterator, J_Iterator_next); - jobject key = env->CallObjectMethod(pair, J_Entry_getKey); - jobject value = env->CallObjectMethod(pair, J_Entry_getValue); - - const string &key_str = jstring_to_string(env, (jstring)env->CallObjectMethod(key, J_Object_toString)); - - const string &value_str = jstring_to_string(env, (jstring)env->CallObjectMethod(value, J_Object_toString)); - - try { - config.SetOptionByName(key_str, Value(value_str)); - } catch (const std::exception &e) { - ErrorData error(e); - throw CatalogException("Failed to set configuration option \"%s\", error: %s", key_str, error.RawMessage()); - } - } - bool cache_instance = database != ":memory:" && !database.empty(); - auto shared_db = instance_cache.GetOrCreateInstance(database, config, cache_instance); - auto conn_holder = new ConnectionHolder(shared_db); - - return env->NewDirectByteBuffer(conn_holder, 0); -} - -jobject _duckdb_jdbc_connect(JNIEnv *env, jclass, jobject conn_ref_buf) { - auto conn_ref = (ConnectionHolder *)env->GetDirectBufferAddress(conn_ref_buf); - auto conn = new ConnectionHolder(conn_ref->db); - return env->NewDirectByteBuffer(conn, 0); -} - -jstring _duckdb_jdbc_get_schema(JNIEnv *env, jclass, jobject conn_ref_buf) { - auto conn_ref = get_connection(env, conn_ref_buf); - if (!conn_ref) { - return nullptr; - } - - auto entry = ClientData::Get(*conn_ref->context).catalog_search_path->GetDefault(); - - return env->NewStringUTF(entry.schema.c_str()); -} - -static void set_catalog_search_path(JNIEnv *env, jobject conn_ref_buf, CatalogSearchEntry search_entry) { - auto conn_ref = get_connection(env, conn_ref_buf); - if (!conn_ref) { - return; - } - - conn_ref->context->RunFunctionInTransaction([&]() { - ClientData::Get(*conn_ref->context).catalog_search_path->Set(search_entry, CatalogSetPathType::SET_SCHEMA); - }); -} - -void _duckdb_jdbc_set_schema(JNIEnv *env, jclass, jobject conn_ref_buf, jstring schema) { - set_catalog_search_path(env, conn_ref_buf, CatalogSearchEntry(INVALID_CATALOG, jstring_to_string(env, schema))); -} - -void _duckdb_jdbc_set_catalog(JNIEnv *env, jclass, jobject conn_ref_buf, jstring catalog) { - set_catalog_search_path(env, conn_ref_buf, CatalogSearchEntry(jstring_to_string(env, catalog), DEFAULT_SCHEMA)); -} - -jstring _duckdb_jdbc_get_catalog(JNIEnv *env, jclass, jobject conn_ref_buf) { - auto conn_ref = get_connection(env, conn_ref_buf); - if (!conn_ref) { - return nullptr; - } - - auto entry = ClientData::Get(*conn_ref->context).catalog_search_path->GetDefault(); - if (entry.catalog == INVALID_CATALOG) { - entry.catalog = DatabaseManager::GetDefaultDatabase(*conn_ref->context); - } - - return env->NewStringUTF(entry.catalog.c_str()); -} - -void _duckdb_jdbc_set_auto_commit(JNIEnv *env, jclass, jobject conn_ref_buf, jboolean auto_commit) { - auto conn_ref = get_connection(env, conn_ref_buf); - if (!conn_ref) { - return; - } - conn_ref->context->RunFunctionInTransaction([&]() { conn_ref->SetAutoCommit(auto_commit); }); -} - -jboolean _duckdb_jdbc_get_auto_commit(JNIEnv *env, jclass, jobject conn_ref_buf) { - auto conn_ref = get_connection(env, conn_ref_buf); - if (!conn_ref) { - return false; - } - return conn_ref->IsAutoCommit(); -} - -void _duckdb_jdbc_interrupt(JNIEnv *env, jclass, jobject conn_ref_buf) { - auto conn_ref = get_connection(env, conn_ref_buf); - if (!conn_ref) { - return; - } - conn_ref->Interrupt(); -} - -void _duckdb_jdbc_disconnect(JNIEnv *env, jclass, jobject conn_ref_buf) { - auto conn_ref = (ConnectionHolder *)env->GetDirectBufferAddress(conn_ref_buf); - if (conn_ref) { - delete conn_ref; - } -} - -struct StatementHolder { - duckdb::unique_ptr stmt; -}; - -#include "utf8proc_wrapper.hpp" - -jobject _duckdb_jdbc_prepare(JNIEnv *env, jclass, jobject conn_ref_buf, jbyteArray query_j) { - auto conn_ref = get_connection(env, conn_ref_buf); - if (!conn_ref) { - return nullptr; - } - - auto query = byte_array_to_string(env, query_j); - - auto statements = conn_ref->ExtractStatements(query.c_str()); - if (statements.empty()) { - throw InvalidInputException("No statements to execute."); - } - - // if there are multiple statements, we directly execute the statements besides the last one - // we only return the result of the last statement to the user, unless one of the previous statements fails - for (idx_t i = 0; i + 1 < statements.size(); i++) { - auto res = conn_ref->Query(std::move(statements[i])); - if (res->HasError()) { - res->ThrowError(); - } - } - - auto stmt_ref = new StatementHolder(); - stmt_ref->stmt = conn_ref->Prepare(std::move(statements.back())); - if (stmt_ref->stmt->HasError()) { - string error_msg = string(stmt_ref->stmt->GetError()); - stmt_ref->stmt = nullptr; - - // No success, so it must be deleted - delete stmt_ref; - ThrowJNI(env, error_msg.c_str()); - - // Just return control flow back to JVM, as an Exception is pending anyway - return nullptr; - } - return env->NewDirectByteBuffer(stmt_ref, 0); -} - -struct ResultHolder { - duckdb::unique_ptr res; - duckdb::unique_ptr chunk; -}; - -jobject _duckdb_jdbc_execute(JNIEnv *env, jclass, jobject stmt_ref_buf, jobjectArray params) { - auto stmt_ref = (StatementHolder *)env->GetDirectBufferAddress(stmt_ref_buf); - if (!stmt_ref) { - throw InvalidInputException("Invalid statement"); - } - auto res_ref = make_uniq(); - duckdb::vector duckdb_params; - - idx_t param_len = env->GetArrayLength(params); - if (param_len != stmt_ref->stmt->n_param) { - throw InvalidInputException("Parameter count mismatch"); - } - - if (param_len > 0) { - for (idx_t i = 0; i < param_len; i++) { - auto param = env->GetObjectArrayElement(params, i); - if (param == nullptr) { - duckdb_params.push_back(Value()); - continue; - } else if (env->IsInstanceOf(param, J_Bool)) { - duckdb_params.push_back(Value::BOOLEAN(env->CallBooleanMethod(param, J_Bool_booleanValue))); - continue; - } else if (env->IsInstanceOf(param, J_Byte)) { - duckdb_params.push_back(Value::TINYINT(env->CallByteMethod(param, J_Byte_byteValue))); - continue; - } else if (env->IsInstanceOf(param, J_Short)) { - duckdb_params.push_back(Value::SMALLINT(env->CallShortMethod(param, J_Short_shortValue))); - continue; - } else if (env->IsInstanceOf(param, J_Int)) { - duckdb_params.push_back(Value::INTEGER(env->CallIntMethod(param, J_Int_intValue))); - continue; - } else if (env->IsInstanceOf(param, J_Long)) { - duckdb_params.push_back(Value::BIGINT(env->CallLongMethod(param, J_Long_longValue))); - continue; - } else if (env->IsInstanceOf(param, J_TimestampTZ)) { // Check for subclass before superclass! - duckdb_params.push_back( - Value::TIMESTAMPTZ((timestamp_t)env->CallLongMethod(param, J_TimestampTZ_getMicrosEpoch))); - continue; - } else if (env->IsInstanceOf(param, J_DuckDBDate)) { - duckdb_params.push_back( - Value::DATE((date_t)env->CallLongMethod(param, J_DuckDBDate_getDaysSinceEpoch))); - - } else if (env->IsInstanceOf(param, J_Timestamp)) { - duckdb_params.push_back( - Value::TIMESTAMP((timestamp_t)env->CallLongMethod(param, J_Timestamp_getMicrosEpoch))); - continue; - } else if (env->IsInstanceOf(param, J_Float)) { - duckdb_params.push_back(Value::FLOAT(env->CallFloatMethod(param, J_Float_floatValue))); - continue; - } else if (env->IsInstanceOf(param, J_Double)) { - duckdb_params.push_back(Value::DOUBLE(env->CallDoubleMethod(param, J_Double_doubleValue))); - continue; - } else if (env->IsInstanceOf(param, J_Decimal)) { - Value val = create_value_from_bigdecimal(env, param); - duckdb_params.push_back(val); - continue; - } else if (env->IsInstanceOf(param, J_String)) { - auto param_string = jstring_to_string(env, (jstring)param); - duckdb_params.push_back(Value(param_string)); - } else if (env->IsInstanceOf(param, J_ByteArray)) { - duckdb_params.push_back(Value::BLOB_RAW(byte_array_to_string(env, (jbyteArray)param))); - } else if (env->IsInstanceOf(param, J_UUID)) { - auto most_significant = (jlong)env->CallObjectMethod(param, J_UUID_getMostSignificantBits); - auto least_significant = (jlong)env->CallObjectMethod(param, J_UUID_getLeastSignificantBits); - duckdb_params.push_back(Value::UUID(hugeint_t(most_significant, least_significant))); - } else { - throw InvalidInputException("Unsupported parameter type"); - } - } - } - - Value result; - bool stream_results = - stmt_ref->stmt->context->TryGetCurrentSetting(JDBC_STREAM_RESULTS, result) ? result.GetValue() : false; - - res_ref->res = stmt_ref->stmt->Execute(duckdb_params, stream_results); - if (res_ref->res->HasError()) { - string error_msg = string(res_ref->res->GetError()); - res_ref->res = nullptr; - ThrowJNI(env, error_msg.c_str()); - return nullptr; - } - return env->NewDirectByteBuffer(res_ref.release(), 0); -} - -void _duckdb_jdbc_release(JNIEnv *env, jclass, jobject stmt_ref_buf) { - auto stmt_ref = (StatementHolder *)env->GetDirectBufferAddress(stmt_ref_buf); - if (stmt_ref) { - delete stmt_ref; - } -} - -void _duckdb_jdbc_free_result(JNIEnv *env, jclass, jobject res_ref_buf) { - auto res_ref = (ResultHolder *)env->GetDirectBufferAddress(res_ref_buf); - if (res_ref) { - delete res_ref; - } -} - -static std::string type_to_jduckdb_type(LogicalType logical_type) { - switch (logical_type.id()) { - case LogicalTypeId::DECIMAL: { - - uint8_t width = 0; - uint8_t scale = 0; - logical_type.GetDecimalProperties(width, scale); - std::string width_scale = std::to_string(width) + std::string(";") + std::to_string(scale); - - auto physical_type = logical_type.InternalType(); - switch (physical_type) { - case PhysicalType::INT16: { - string res = std::string("DECIMAL16;") + width_scale; - return res; - } - case PhysicalType::INT32: { - string res = std::string("DECIMAL32;") + width_scale; - return res; - } - case PhysicalType::INT64: { - string res = std::string("DECIMAL64;") + width_scale; - return res; - } - case PhysicalType::INT128: { - string res = std::string("DECIMAL128;") + width_scale; - return res; - } - default: - return std::string("no physical type found"); - } - } break; - default: - return logical_type.ToString(); - } -} - -static jobject build_meta(JNIEnv *env, size_t column_count, size_t n_param, const duckdb::vector &names, - const duckdb::vector &types, StatementProperties properties) { - auto name_array = env->NewObjectArray(column_count, J_String, nullptr); - auto type_array = env->NewObjectArray(column_count, J_String, nullptr); - auto type_detail_array = env->NewObjectArray(column_count, J_String, nullptr); - - for (idx_t col_idx = 0; col_idx < column_count; col_idx++) { - std::string col_name; - if (types[col_idx].id() == LogicalTypeId::ENUM) { - col_name = "ENUM"; - } else { - col_name = types[col_idx].ToString(); - } - - env->SetObjectArrayElement(name_array, col_idx, - decode_charbuffer_to_jstring(env, names[col_idx].c_str(), names[col_idx].length())); - env->SetObjectArrayElement(type_array, col_idx, env->NewStringUTF(col_name.c_str())); - env->SetObjectArrayElement(type_detail_array, col_idx, - env->NewStringUTF(type_to_jduckdb_type(types[col_idx]).c_str())); - } - - auto return_type = env->NewStringUTF(StatementReturnTypeToString(properties.return_type).c_str()); - - return env->NewObject(J_DuckResultSetMeta, J_DuckResultSetMeta_init, n_param, column_count, name_array, type_array, - type_detail_array, return_type); -} - -jobject _duckdb_jdbc_query_result_meta(JNIEnv *env, jclass, jobject res_ref_buf) { - auto res_ref = (ResultHolder *)env->GetDirectBufferAddress(res_ref_buf); - if (!res_ref || !res_ref->res || res_ref->res->HasError()) { - throw InvalidInputException("Invalid result set"); - } - auto &result = res_ref->res; - - auto n_param = -1; // no params now - - return build_meta(env, result->ColumnCount(), n_param, result->names, result->types, result->properties); -} - -jobject _duckdb_jdbc_prepared_statement_meta(JNIEnv *env, jclass, jobject stmt_ref_buf) { - - auto stmt_ref = (StatementHolder *)env->GetDirectBufferAddress(stmt_ref_buf); - if (!stmt_ref || !stmt_ref->stmt || stmt_ref->stmt->HasError()) { - throw InvalidInputException("Invalid statement"); - } - - auto &stmt = stmt_ref->stmt; - - return build_meta(env, stmt->ColumnCount(), stmt->n_param, stmt->GetNames(), stmt->GetTypes(), - stmt->GetStatementProperties()); -} - -jobject ProcessVector(JNIEnv *env, Connection *conn_ref, Vector &vec, idx_t row_count); - -jobjectArray _duckdb_jdbc_fetch(JNIEnv *env, jclass, jobject res_ref_buf, jobject conn_ref_buf) { - auto res_ref = (ResultHolder *)env->GetDirectBufferAddress(res_ref_buf); - if (!res_ref || !res_ref->res || res_ref->res->HasError()) { - throw InvalidInputException("Invalid result set"); - } - - auto conn_ref = get_connection(env, conn_ref_buf); - if (conn_ref == nullptr) { - return nullptr; - } - - res_ref->chunk = res_ref->res->Fetch(); - if (!res_ref->chunk) { - res_ref->chunk = make_uniq(); - } - auto row_count = res_ref->chunk->size(); - auto vec_array = (jobjectArray)env->NewObjectArray(res_ref->chunk->ColumnCount(), J_DuckVector, nullptr); - - for (idx_t col_idx = 0; col_idx < res_ref->chunk->ColumnCount(); col_idx++) { - auto &vec = res_ref->chunk->data[col_idx]; - - auto jvec = ProcessVector(env, conn_ref, vec, row_count); - - env->SetObjectArrayElement(vec_array, col_idx, jvec); - } - - return vec_array; -} -jobject ProcessVector(JNIEnv *env, Connection *conn_ref, Vector &vec, idx_t row_count) { - auto type_str = env->NewStringUTF(type_to_jduckdb_type(vec.GetType()).c_str()); - // construct nullmask - auto null_array = env->NewBooleanArray(row_count); - jboolean *null_unique_array = env->GetBooleanArrayElements(null_array, nullptr); - for (idx_t row_idx = 0; row_idx < row_count; row_idx++) { - null_unique_array[row_idx] = FlatVector::IsNull(vec, row_idx); - } - env->ReleaseBooleanArrayElements(null_array, null_unique_array, 0); - - auto jvec = env->NewObject(J_DuckVector, J_DuckVector_init, type_str, (int)row_count, null_array); - - jobject constlen_data = nullptr; - jobjectArray varlen_data = nullptr; - - // this allows us to treat aliased (usually extension) types as strings - auto type = vec.GetType(); - auto type_id = type.HasAlias() ? LogicalTypeId::UNKNOWN : type.id(); - - switch (type_id) { - case LogicalTypeId::BOOLEAN: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(bool)); - break; - case LogicalTypeId::TINYINT: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(int8_t)); - break; - case LogicalTypeId::SMALLINT: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(int16_t)); - break; - case LogicalTypeId::INTEGER: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(int32_t)); - break; - case LogicalTypeId::BIGINT: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(int64_t)); - break; - case LogicalTypeId::UTINYINT: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(uint8_t)); - break; - case LogicalTypeId::USMALLINT: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(uint16_t)); - break; - case LogicalTypeId::UINTEGER: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(uint32_t)); - break; - case LogicalTypeId::UBIGINT: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(uint64_t)); - break; - case LogicalTypeId::HUGEINT: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(hugeint_t)); - break; - case LogicalTypeId::UHUGEINT: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(uhugeint_t)); - break; - case LogicalTypeId::FLOAT: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(float)); - break; - case LogicalTypeId::DECIMAL: { - auto physical_type = vec.GetType().InternalType(); - - switch (physical_type) { - case PhysicalType::INT16: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(int16_t)); - break; - case PhysicalType::INT32: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(int32_t)); - break; - case PhysicalType::INT64: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(int64_t)); - break; - case PhysicalType::INT128: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(hugeint_t)); - break; - default: - throw InternalException("Unimplemented physical type for decimal"); - } - break; - } - case LogicalTypeId::DOUBLE: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(double)); - break; - case LogicalTypeId::DATE: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(date_t)); - break; - case LogicalTypeId::TIME: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(dtime_t)); - break; - case LogicalTypeId::TIME_TZ: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(dtime_tz_t)); - break; - case LogicalTypeId::TIMESTAMP_SEC: - case LogicalTypeId::TIMESTAMP_MS: - case LogicalTypeId::TIMESTAMP: - case LogicalTypeId::TIMESTAMP_NS: - case LogicalTypeId::TIMESTAMP_TZ: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(timestamp_t)); - break; - case LogicalTypeId::ENUM: - varlen_data = env->NewObjectArray(row_count, J_String, nullptr); - for (idx_t row_idx = 0; row_idx < row_count; row_idx++) { - if (FlatVector::IsNull(vec, row_idx)) { - continue; - } - auto d_str = vec.GetValue(row_idx).ToString(); - jstring j_str = env->NewStringUTF(d_str.c_str()); - env->SetObjectArrayElement(varlen_data, row_idx, j_str); - } - break; - case LogicalTypeId::UNION: - case LogicalTypeId::STRUCT: { - varlen_data = env->NewObjectArray(row_count, J_DuckStruct, nullptr); - - auto &entries = StructVector::GetEntries(vec); - auto columns = env->NewObjectArray(entries.size(), J_DuckVector, nullptr); - auto names = env->NewObjectArray(entries.size(), J_String, nullptr); - - for (idx_t entry_i = 0; entry_i < entries.size(); entry_i++) { - auto j_vec = ProcessVector(env, conn_ref, *entries[entry_i], row_count); - env->SetObjectArrayElement(columns, entry_i, j_vec); - env->SetObjectArrayElement(names, entry_i, - env->NewStringUTF(StructType::GetChildName(vec.GetType(), entry_i).c_str())); - } - for (idx_t row_idx = 0; row_idx < row_count; row_idx++) { - env->SetObjectArrayElement(varlen_data, row_idx, - env->NewObject(J_DuckStruct, J_DuckStruct_init, names, columns, row_idx, - env->NewStringUTF(vec.GetType().ToString().c_str()))); - } - - break; - } - case LogicalTypeId::BLOB: - varlen_data = env->NewObjectArray(row_count, J_ByteBuffer, nullptr); - - for (idx_t row_idx = 0; row_idx < row_count; row_idx++) { - if (FlatVector::IsNull(vec, row_idx)) { - continue; - } - auto &d_str = ((string_t *)FlatVector::GetData(vec))[row_idx]; - auto j_obj = env->NewDirectByteBuffer((void *)d_str.GetData(), d_str.GetSize()); - env->SetObjectArrayElement(varlen_data, row_idx, j_obj); - } - break; - case LogicalTypeId::UUID: - constlen_data = env->NewDirectByteBuffer(FlatVector::GetData(vec), row_count * sizeof(hugeint_t)); - break; - case LogicalTypeId::ARRAY: { - varlen_data = env->NewObjectArray(row_count, J_DuckArray, nullptr); - auto &array_vector = ArrayVector::GetEntry(vec); - auto total_size = row_count * ArrayType::GetSize(vec.GetType()); - auto j_vec = ProcessVector(env, conn_ref, array_vector, total_size); - - auto limit = ArrayType::GetSize(vec.GetType()); - - for (idx_t row_idx = 0; row_idx < row_count; row_idx++) { - if (FlatVector::IsNull(vec, row_idx)) { - continue; - } - - auto offset = row_idx * limit; - - auto j_obj = env->NewObject(J_DuckArray, J_DuckArray_init, j_vec, offset, limit); - - env->SetObjectArrayElement(varlen_data, row_idx, j_obj); - } - break; - } - case LogicalTypeId::MAP: - case LogicalTypeId::LIST: { - varlen_data = env->NewObjectArray(row_count, J_DuckArray, nullptr); - - auto list_entries = FlatVector::GetData(vec); - - auto list_size = ListVector::GetListSize(vec); - auto &list_vector = ListVector::GetEntry(vec); - auto j_vec = ProcessVector(env, conn_ref, list_vector, list_size); - - for (idx_t row_idx = 0; row_idx < row_count; row_idx++) { - if (FlatVector::IsNull(vec, row_idx)) { - continue; - } - - auto offset = list_entries[row_idx].offset; - auto limit = list_entries[row_idx].length; - - auto j_obj = env->NewObject(J_DuckArray, J_DuckArray_init, j_vec, offset, limit); - - env->SetObjectArrayElement(varlen_data, row_idx, j_obj); - } - break; - } - default: { - Vector string_vec(LogicalType::VARCHAR); - VectorOperations::Cast(*conn_ref->context, vec, string_vec, row_count); - vec.ReferenceAndSetType(string_vec); - // fall through on purpose - } - case LogicalTypeId::VARCHAR: - varlen_data = env->NewObjectArray(row_count, J_String, nullptr); - for (idx_t row_idx = 0; row_idx < row_count; row_idx++) { - if (FlatVector::IsNull(vec, row_idx)) { - continue; - } - auto d_str = ((string_t *)FlatVector::GetData(vec))[row_idx]; - auto j_str = decode_charbuffer_to_jstring(env, d_str.GetData(), d_str.GetSize()); - env->SetObjectArrayElement(varlen_data, row_idx, j_str); - } - break; - } - - env->SetObjectField(jvec, J_DuckVector_constlen, constlen_data); - env->SetObjectField(jvec, J_DuckVector_varlen, varlen_data); - - return jvec; -} - -jint _duckdb_jdbc_fetch_size(JNIEnv *, jclass) { - return STANDARD_VECTOR_SIZE; -} - -jobject _duckdb_jdbc_create_appender(JNIEnv *env, jclass, jobject conn_ref_buf, jbyteArray schema_name_j, - jbyteArray table_name_j) { - - auto conn_ref = get_connection(env, conn_ref_buf); - if (!conn_ref) { - return nullptr; - } - auto schema_name = byte_array_to_string(env, schema_name_j); - auto table_name = byte_array_to_string(env, table_name_j); - auto appender = new Appender(*conn_ref, schema_name, table_name); - return env->NewDirectByteBuffer(appender, 0); -} - -static Appender *get_appender(JNIEnv *env, jobject appender_ref_buf) { - auto appender_ref = (Appender *)env->GetDirectBufferAddress(appender_ref_buf); - if (!appender_ref) { - throw InvalidInputException("Invalid appender"); - } - return appender_ref; -} - -void _duckdb_jdbc_appender_begin_row(JNIEnv *env, jclass, jobject appender_ref_buf) { - get_appender(env, appender_ref_buf)->BeginRow(); -} - -void _duckdb_jdbc_appender_end_row(JNIEnv *env, jclass, jobject appender_ref_buf) { - get_appender(env, appender_ref_buf)->EndRow(); -} - -void _duckdb_jdbc_appender_flush(JNIEnv *env, jclass, jobject appender_ref_buf) { - get_appender(env, appender_ref_buf)->Flush(); -} - -void _duckdb_jdbc_appender_close(JNIEnv *env, jclass, jobject appender_ref_buf) { - auto appender = get_appender(env, appender_ref_buf); - appender->Close(); - delete appender; -} - -void _duckdb_jdbc_appender_append_boolean(JNIEnv *env, jclass, jobject appender_ref_buf, jboolean value) { - get_appender(env, appender_ref_buf)->Append((bool)value); -} - -void _duckdb_jdbc_appender_append_byte(JNIEnv *env, jclass, jobject appender_ref_buf, jbyte value) { - get_appender(env, appender_ref_buf)->Append((int8_t)value); -} - -void _duckdb_jdbc_appender_append_short(JNIEnv *env, jclass, jobject appender_ref_buf, jshort value) { - get_appender(env, appender_ref_buf)->Append((int16_t)value); -} - -void _duckdb_jdbc_appender_append_int(JNIEnv *env, jclass, jobject appender_ref_buf, jint value) { - get_appender(env, appender_ref_buf)->Append((int32_t)value); -} - -void _duckdb_jdbc_appender_append_long(JNIEnv *env, jclass, jobject appender_ref_buf, jlong value) { - get_appender(env, appender_ref_buf)->Append((int64_t)value); -} - -void _duckdb_jdbc_appender_append_float(JNIEnv *env, jclass, jobject appender_ref_buf, jfloat value) { - get_appender(env, appender_ref_buf)->Append((float)value); -} - -void _duckdb_jdbc_appender_append_double(JNIEnv *env, jclass, jobject appender_ref_buf, jdouble value) { - get_appender(env, appender_ref_buf)->Append((double)value); -} - -void _duckdb_jdbc_appender_append_timestamp(JNIEnv *env, jclass, jobject appender_ref_buf, jlong value) { - timestamp_t timestamp = timestamp_t((int64_t)value); - get_appender(env, appender_ref_buf)->Append(Value::TIMESTAMP(timestamp)); -} - -void _duckdb_jdbc_appender_append_decimal(JNIEnv *env, jclass, jobject appender_ref_buf, jobject value) { - Value val = create_value_from_bigdecimal(env, value); - get_appender(env, appender_ref_buf)->Append(val); -} - -void _duckdb_jdbc_appender_append_string(JNIEnv *env, jclass, jobject appender_ref_buf, jbyteArray value) { - if (env->IsSameObject(value, NULL)) { - get_appender(env, appender_ref_buf)->Append(nullptr); - return; - } - - auto string_value = byte_array_to_string(env, value); - get_appender(env, appender_ref_buf)->Append(string_value.c_str()); -} - -void _duckdb_jdbc_appender_append_null(JNIEnv *env, jclass, jobject appender_ref_buf) { - get_appender(env, appender_ref_buf)->Append(nullptr); -} - -jlong _duckdb_jdbc_arrow_stream(JNIEnv *env, jclass, jobject res_ref_buf, jlong batch_size) { - if (!res_ref_buf) { - throw InvalidInputException("Invalid result set"); - } - auto res_ref = (ResultHolder *)env->GetDirectBufferAddress(res_ref_buf); - if (!res_ref || !res_ref->res || res_ref->res->HasError()) { - throw InvalidInputException("Invalid result set"); - } - - auto wrapper = new ResultArrowArrayStreamWrapper(std::move(res_ref->res), batch_size); - return (jlong)&wrapper->stream; -} - -class JavaArrowTabularStreamFactory { -public: - JavaArrowTabularStreamFactory(ArrowArrayStream *stream_ptr_p) : stream_ptr(stream_ptr_p) {}; - - static duckdb::unique_ptr Produce(uintptr_t factory_p, ArrowStreamParameters ¶meters) { - - auto factory = (JavaArrowTabularStreamFactory *)factory_p; - if (!factory->stream_ptr->release) { - throw InvalidInputException("This stream has been released"); - } - auto res = make_uniq(); - res->arrow_array_stream = *factory->stream_ptr; - factory->stream_ptr->release = nullptr; - return res; - } - - static void GetSchema(uintptr_t factory_p, ArrowSchemaWrapper &schema) { - auto factory = (JavaArrowTabularStreamFactory *)factory_p; - auto stream_ptr = factory->stream_ptr; - if (!stream_ptr->release) { - throw InvalidInputException("This stream has been released"); - } - stream_ptr->get_schema(stream_ptr, &schema.arrow_schema); - auto error = stream_ptr->get_last_error(stream_ptr); - if (error != nullptr) { - throw InvalidInputException(error); - } - } - - ArrowArrayStream *stream_ptr; -}; - -void _duckdb_jdbc_arrow_register(JNIEnv *env, jclass, jobject conn_ref_buf, jlong arrow_array_stream_pointer, - jbyteArray name_j) { - - auto conn = get_connection(env, conn_ref_buf); - if (conn == nullptr) { - return; - } - auto name = byte_array_to_string(env, name_j); - - auto arrow_array_stream = (ArrowArrayStream *)(uintptr_t)arrow_array_stream_pointer; - - auto factory = new JavaArrowTabularStreamFactory(arrow_array_stream); - duckdb::vector parameters; - parameters.push_back(Value::POINTER((uintptr_t)factory)); - parameters.push_back(Value::POINTER((uintptr_t)JavaArrowTabularStreamFactory::Produce)); - parameters.push_back(Value::POINTER((uintptr_t)JavaArrowTabularStreamFactory::GetSchema)); - conn->TableFunction("arrow_scan_dumb", parameters)->CreateView(name, true, true); -} - -void _duckdb_jdbc_create_extension_type(JNIEnv *env, jclass, jobject conn_buf) { - - auto connection = get_connection(env, conn_buf); - if (!connection) { - return; - } - - connection->BeginTransaction(); - - child_list_t children = {{"hello", LogicalType::VARCHAR}, {"world", LogicalType::VARCHAR}}; - auto id = LogicalType::STRUCT(children); - auto type_name = "test_type"; - id.SetAlias(type_name); - CreateTypeInfo info(type_name, id); - - auto &catalog_name = DatabaseManager::GetDefaultDatabase(*connection->context); - auto &catalog = Catalog::GetCatalog(*connection->context, catalog_name); - catalog.CreateType(*connection->context, info); - - LogicalType byte_test_type_type = LogicalTypeId::BLOB; - byte_test_type_type.SetAlias("byte_test_type"); - CreateTypeInfo byte_test_type("byte_test_type", byte_test_type_type); - catalog.CreateType(*connection->context, byte_test_type); - - connection->Commit(); -} diff --git a/tools/jdbc/src/jni/functions.cpp b/tools/jdbc/src/jni/functions.cpp deleted file mode 100644 index a3e998a19f3..00000000000 --- a/tools/jdbc/src/jni/functions.cpp +++ /dev/null @@ -1,411 +0,0 @@ -// This file was generated by tools/jdbc/generator.py - -#include "org_duckdb_DuckDBNative.h" -#include "functions.hpp" -#include - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1startup(JNIEnv *env, jclass param0, - jbyteArray param1, jboolean param2, - jobject param3) { - try { - return _duckdb_jdbc_startup(env, param0, param1, param2, param3); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return nullptr; - } -} - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1connect(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_connect(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return nullptr; - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1auto_1commit(JNIEnv *env, jclass param0, - jobject param1, jboolean param2) { - try { - return _duckdb_jdbc_set_auto_commit(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT jboolean JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1get_1auto_1commit(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_get_auto_commit(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return false; - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1disconnect(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_disconnect(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1schema(JNIEnv *env, jclass param0, - jobject param1, jstring param2) { - try { - return _duckdb_jdbc_set_schema(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1catalog(JNIEnv *env, jclass param0, - jobject param1, jstring param2) { - try { - return _duckdb_jdbc_set_catalog(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT jstring JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1get_1schema(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_get_schema(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return nullptr; - } -} - -JNIEXPORT jstring JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1get_1catalog(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_get_catalog(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return nullptr; - } -} - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1prepare(JNIEnv *env, jclass param0, jobject param1, - jbyteArray param2) { - try { - return _duckdb_jdbc_prepare(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return nullptr; - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1release(JNIEnv *env, jclass param0, jobject param1) { - try { - return _duckdb_jdbc_release(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1query_1result_1meta(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_query_result_meta(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return nullptr; - } -} - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1prepared_1statement_1meta(JNIEnv *env, - jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_prepared_statement_meta(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return nullptr; - } -} - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1execute(JNIEnv *env, jclass param0, jobject param1, - jobjectArray param2) { - try { - return _duckdb_jdbc_execute(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return nullptr; - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1free_1result(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_free_result(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT jobjectArray JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1fetch(JNIEnv *env, jclass param0, - jobject param1, jobject param2) { - try { - return _duckdb_jdbc_fetch(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return nullptr; - } -} - -JNIEXPORT jint JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1fetch_1size(JNIEnv *env, jclass param0) { - try { - return _duckdb_jdbc_fetch_size(env, param0); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return -1; - } -} - -JNIEXPORT jlong JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1arrow_1stream(JNIEnv *env, jclass param0, - jobject param1, jlong param2) { - try { - return _duckdb_jdbc_arrow_stream(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return -1; - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1arrow_1register(JNIEnv *env, jclass param0, - jobject param1, jlong param2, - jbyteArray param3) { - try { - return _duckdb_jdbc_arrow_register(env, param0, param1, param2, param3); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1create_1appender(JNIEnv *env, jclass param0, - jobject param1, jbyteArray param2, - jbyteArray param3) { - try { - return _duckdb_jdbc_create_appender(env, param0, param1, param2, param3); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - return nullptr; - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1begin_1row(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_appender_begin_row(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1end_1row(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_appender_end_row(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1flush(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_appender_flush(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1interrupt(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_interrupt(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1close(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_appender_close(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1boolean(JNIEnv *env, jclass param0, - jobject param1, - jboolean param2) { - try { - return _duckdb_jdbc_appender_append_boolean(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1byte(JNIEnv *env, jclass param0, - jobject param1, jbyte param2) { - try { - return _duckdb_jdbc_appender_append_byte(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1short(JNIEnv *env, jclass param0, - jobject param1, - jshort param2) { - try { - return _duckdb_jdbc_appender_append_short(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1int(JNIEnv *env, jclass param0, - jobject param1, jint param2) { - try { - return _duckdb_jdbc_appender_append_int(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1long(JNIEnv *env, jclass param0, - jobject param1, jlong param2) { - try { - return _duckdb_jdbc_appender_append_long(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1float(JNIEnv *env, jclass param0, - jobject param1, - jfloat param2) { - try { - return _duckdb_jdbc_appender_append_float(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1double(JNIEnv *env, jclass param0, - jobject param1, - jdouble param2) { - try { - return _duckdb_jdbc_appender_append_double(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1string(JNIEnv *env, jclass param0, - jobject param1, - jbyteArray param2) { - try { - return _duckdb_jdbc_appender_append_string(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1timestamp(JNIEnv *env, - jclass param0, - jobject param1, - jlong param2) { - try { - return _duckdb_jdbc_appender_append_timestamp(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1decimal(JNIEnv *env, jclass param0, - jobject param1, - jobject param2) { - try { - return _duckdb_jdbc_appender_append_decimal(env, param0, param1, param2); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1null(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_appender_append_null(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1create_1extension_1type(JNIEnv *env, jclass param0, - jobject param1) { - try { - return _duckdb_jdbc_create_extension_type(env, param0, param1); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - } -} diff --git a/tools/jdbc/src/jni/functions.cpp.template b/tools/jdbc/src/jni/functions.cpp.template deleted file mode 100644 index b0ac760c9d0..00000000000 --- a/tools/jdbc/src/jni/functions.cpp.template +++ /dev/null @@ -1,24 +0,0 @@ -// This file was generated by tools/jdbc/generator.py - -#include "org_duckdb_DuckDBNative.h" -#include "functions.hpp" -#include -{% for function in header.functions %} - -JNIEXPORT {{ function.return_type or 'void' }} JNICALL {{function.name}}({{function.params}}) { - try { - return {{function.short_name}}({{function.names}}); - } catch (const std::exception &e) { - duckdb::ErrorData error(e); - ThrowJNI(env, error.Message().c_str()); - - {% if function.return_type == 'jboolean' %} - return false; - {% elif function.return_type in['jint', 'jlong'] %} - return -1; - {% elif function.return_type in['jobject', 'jstring', 'jobjectArray'] %} - return nullptr; - {% endif %} - } -} -{% endfor %} diff --git a/tools/jdbc/src/jni/functions.hpp b/tools/jdbc/src/jni/functions.hpp deleted file mode 100644 index 6adb2989068..00000000000 --- a/tools/jdbc/src/jni/functions.hpp +++ /dev/null @@ -1,204 +0,0 @@ -// This file was generated by tools/jdbc/generator.py - -#pragma once - -#include "duckdb/common/assert.hpp" -#include "duckdb/common/error_data.hpp" -#include "org_duckdb_DuckDBNative.h" -#include - -void ThrowJNI(JNIEnv *env, const char *message); - -jobject _duckdb_jdbc_startup(JNIEnv *env, jclass param0, jbyteArray param1, jboolean param2, jobject param3); - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1startup(JNIEnv *env, jclass param0, - jbyteArray param1, jboolean param2, - jobject param3); - -jobject _duckdb_jdbc_connect(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1connect(JNIEnv *env, jclass param0, - jobject param1); - -void _duckdb_jdbc_set_auto_commit(JNIEnv *env, jclass param0, jobject param1, jboolean param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1auto_1commit(JNIEnv *env, jclass param0, - jobject param1, jboolean param2); - -jboolean _duckdb_jdbc_get_auto_commit(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT jboolean JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1get_1auto_1commit(JNIEnv *env, jclass param0, - jobject param1); - -void _duckdb_jdbc_disconnect(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1disconnect(JNIEnv *env, jclass param0, - jobject param1); - -void _duckdb_jdbc_set_schema(JNIEnv *env, jclass param0, jobject param1, jstring param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1schema(JNIEnv *env, jclass param0, - jobject param1, jstring param2); - -void _duckdb_jdbc_set_catalog(JNIEnv *env, jclass param0, jobject param1, jstring param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1set_1catalog(JNIEnv *env, jclass param0, - jobject param1, jstring param2); - -jstring _duckdb_jdbc_get_schema(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT jstring JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1get_1schema(JNIEnv *env, jclass param0, - jobject param1); - -jstring _duckdb_jdbc_get_catalog(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT jstring JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1get_1catalog(JNIEnv *env, jclass param0, - jobject param1); - -jobject _duckdb_jdbc_prepare(JNIEnv *env, jclass param0, jobject param1, jbyteArray param2); - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1prepare(JNIEnv *env, jclass param0, jobject param1, - jbyteArray param2); - -void _duckdb_jdbc_release(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1release(JNIEnv *env, jclass param0, jobject param1); - -jobject _duckdb_jdbc_query_result_meta(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1query_1result_1meta(JNIEnv *env, jclass param0, - jobject param1); - -jobject _duckdb_jdbc_prepared_statement_meta(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1prepared_1statement_1meta(JNIEnv *env, - jclass param0, - jobject param1); - -jobject _duckdb_jdbc_execute(JNIEnv *env, jclass param0, jobject param1, jobjectArray param2); - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1execute(JNIEnv *env, jclass param0, jobject param1, - jobjectArray param2); - -void _duckdb_jdbc_free_result(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1free_1result(JNIEnv *env, jclass param0, - jobject param1); - -jobjectArray _duckdb_jdbc_fetch(JNIEnv *env, jclass param0, jobject param1, jobject param2); - -JNIEXPORT jobjectArray JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1fetch(JNIEnv *env, jclass param0, - jobject param1, jobject param2); - -jint _duckdb_jdbc_fetch_size(JNIEnv *env, jclass param0); - -JNIEXPORT jint JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1fetch_1size(JNIEnv *env, jclass param0); - -jlong _duckdb_jdbc_arrow_stream(JNIEnv *env, jclass param0, jobject param1, jlong param2); - -JNIEXPORT jlong JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1arrow_1stream(JNIEnv *env, jclass param0, - jobject param1, jlong param2); - -void _duckdb_jdbc_arrow_register(JNIEnv *env, jclass param0, jobject param1, jlong param2, jbyteArray param3); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1arrow_1register(JNIEnv *env, jclass param0, - jobject param1, jlong param2, - jbyteArray param3); - -jobject _duckdb_jdbc_create_appender(JNIEnv *env, jclass param0, jobject param1, jbyteArray param2, jbyteArray param3); - -JNIEXPORT jobject JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1create_1appender(JNIEnv *env, jclass param0, - jobject param1, jbyteArray param2, - jbyteArray param3); - -void _duckdb_jdbc_appender_begin_row(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1begin_1row(JNIEnv *env, jclass param0, - jobject param1); - -void _duckdb_jdbc_appender_end_row(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1end_1row(JNIEnv *env, jclass param0, - jobject param1); - -void _duckdb_jdbc_appender_flush(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1flush(JNIEnv *env, jclass param0, - jobject param1); - -void _duckdb_jdbc_interrupt(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1interrupt(JNIEnv *env, jclass param0, jobject param1); - -void _duckdb_jdbc_appender_close(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1close(JNIEnv *env, jclass param0, - jobject param1); - -void _duckdb_jdbc_appender_append_boolean(JNIEnv *env, jclass param0, jobject param1, jboolean param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1boolean(JNIEnv *env, jclass param0, - jobject param1, - jboolean param2); - -void _duckdb_jdbc_appender_append_byte(JNIEnv *env, jclass param0, jobject param1, jbyte param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1byte(JNIEnv *env, jclass param0, - jobject param1, jbyte param2); - -void _duckdb_jdbc_appender_append_short(JNIEnv *env, jclass param0, jobject param1, jshort param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1short(JNIEnv *env, jclass param0, - jobject param1, - jshort param2); - -void _duckdb_jdbc_appender_append_int(JNIEnv *env, jclass param0, jobject param1, jint param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1int(JNIEnv *env, jclass param0, - jobject param1, jint param2); - -void _duckdb_jdbc_appender_append_long(JNIEnv *env, jclass param0, jobject param1, jlong param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1long(JNIEnv *env, jclass param0, - jobject param1, jlong param2); - -void _duckdb_jdbc_appender_append_float(JNIEnv *env, jclass param0, jobject param1, jfloat param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1float(JNIEnv *env, jclass param0, - jobject param1, - jfloat param2); - -void _duckdb_jdbc_appender_append_double(JNIEnv *env, jclass param0, jobject param1, jdouble param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1double(JNIEnv *env, jclass param0, - jobject param1, - jdouble param2); - -void _duckdb_jdbc_appender_append_string(JNIEnv *env, jclass param0, jobject param1, jbyteArray param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1string(JNIEnv *env, jclass param0, - jobject param1, - jbyteArray param2); - -void _duckdb_jdbc_appender_append_timestamp(JNIEnv *env, jclass param0, jobject param1, jlong param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1timestamp(JNIEnv *env, - jclass param0, - jobject param1, - jlong param2); - -void _duckdb_jdbc_appender_append_decimal(JNIEnv *env, jclass param0, jobject param1, jobject param2); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1decimal(JNIEnv *env, jclass param0, - jobject param1, - jobject param2); - -void _duckdb_jdbc_appender_append_null(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1appender_1append_1null(JNIEnv *env, jclass param0, - jobject param1); - -void _duckdb_jdbc_create_extension_type(JNIEnv *env, jclass param0, jobject param1); - -JNIEXPORT void JNICALL Java_org_duckdb_DuckDBNative_duckdb_1jdbc_1create_1extension_1type(JNIEnv *env, jclass param0, - jobject param1); diff --git a/tools/jdbc/src/jni/functions.hpp.template b/tools/jdbc/src/jni/functions.hpp.template deleted file mode 100644 index 990cf3e50ab..00000000000 --- a/tools/jdbc/src/jni/functions.hpp.template +++ /dev/null @@ -1,16 +0,0 @@ -// This file was generated by tools/jdbc/generator.py - -#pragma once - -#include "duckdb/common/assert.hpp" -#include "duckdb/common/error_data.hpp" -#include "org_duckdb_DuckDBNative.h" -#include - -void ThrowJNI(JNIEnv* env, const char* message); -{% for function in header.functions %} - -{{function.return_type or 'void'}} {{function.short_name}}({{function.params}}); - -JNIEXPORT {{ function.return_type or 'void' }} JNICALL {{function.name}}({{function.params}}); -{% endfor %} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBAppender.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBAppender.java deleted file mode 100644 index 1a022b045cd..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBAppender.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.duckdb; - -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.sql.SQLException; -import java.time.LocalDateTime; -import java.math.BigDecimal; -import org.duckdb.DuckDBTimestamp; - -public class DuckDBAppender implements AutoCloseable { - - protected ByteBuffer appender_ref = null; - - public DuckDBAppender(DuckDBConnection con, String schemaName, String tableName) throws SQLException { - if (con == null) { - throw new SQLException("Invalid connection"); - } - appender_ref = DuckDBNative.duckdb_jdbc_create_appender( - con.conn_ref, schemaName.getBytes(StandardCharsets.UTF_8), tableName.getBytes(StandardCharsets.UTF_8)); - } - - public void beginRow() throws SQLException { - DuckDBNative.duckdb_jdbc_appender_begin_row(appender_ref); - } - - public void endRow() throws SQLException { - DuckDBNative.duckdb_jdbc_appender_end_row(appender_ref); - } - - public void flush() throws SQLException { - DuckDBNative.duckdb_jdbc_appender_flush(appender_ref); - } - - public void append(boolean value) throws SQLException { - DuckDBNative.duckdb_jdbc_appender_append_boolean(appender_ref, value); - } - - public void append(byte value) throws SQLException { - DuckDBNative.duckdb_jdbc_appender_append_byte(appender_ref, value); - } - - public void append(short value) throws SQLException { - DuckDBNative.duckdb_jdbc_appender_append_short(appender_ref, value); - } - - public void append(int value) throws SQLException { - DuckDBNative.duckdb_jdbc_appender_append_int(appender_ref, value); - } - - public void append(long value) throws SQLException { - DuckDBNative.duckdb_jdbc_appender_append_long(appender_ref, value); - } - - // New naming schema for object params to keep compatibility with calling "append(null)" - public void appendLocalDateTime(LocalDateTime value) throws SQLException { - if (value == null) { - DuckDBNative.duckdb_jdbc_appender_append_null(appender_ref); - } else { - long timeInMicros = DuckDBTimestamp.localDateTime2Micros(value); - DuckDBNative.duckdb_jdbc_appender_append_timestamp(appender_ref, timeInMicros); - } - } - - public void appendBigDecimal(BigDecimal value) throws SQLException { - if (value == null) { - DuckDBNative.duckdb_jdbc_appender_append_null(appender_ref); - } else { - DuckDBNative.duckdb_jdbc_appender_append_decimal(appender_ref, value); - } - } - - public void append(float value) throws SQLException { - DuckDBNative.duckdb_jdbc_appender_append_float(appender_ref, value); - } - - public void append(double value) throws SQLException { - DuckDBNative.duckdb_jdbc_appender_append_double(appender_ref, value); - } - - public void append(String value) throws SQLException { - if (value == null) { - DuckDBNative.duckdb_jdbc_appender_append_null(appender_ref); - } else { - DuckDBNative.duckdb_jdbc_appender_append_string(appender_ref, value.getBytes(StandardCharsets.UTF_8)); - } - } - - protected void finalize() throws Throwable { - close(); - } - - public synchronized void close() throws SQLException { - if (appender_ref != null) { - DuckDBNative.duckdb_jdbc_appender_close(appender_ref); - appender_ref = null; - } - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBArray.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBArray.java deleted file mode 100644 index 4299b8070d2..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBArray.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.duckdb; - -import java.sql.Array; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Map; - -import static org.duckdb.DuckDBResultSetMetaData.type_to_int; - -public class DuckDBArray implements Array { - private final Object[] array; - private final DuckDBVector vector; - final int offset, length; - - DuckDBArray(DuckDBVector vector, int offset, int length) throws SQLException { - this.vector = vector; - this.length = length; - this.offset = offset; - - array = new Object[length]; - for (int i = 0; i < length; i++) { - array[i] = vector.getObject(offset + i); - } - } - - @Override - public void free() throws SQLException { - // we don't own the vector, so cannot free it - } - @Override - public Object getArray() throws SQLException { - return array; - } - - @Override - public Object getArray(Map> map) throws SQLException { - return getArray(); - } - - @Override - public Object getArray(long index, int count) throws SQLException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getArray'"); - } - - @Override - public Object getArray(long index, int count, Map> map) throws SQLException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getArray'"); - } - - @Override - public int getBaseType() throws SQLException { - return type_to_int(vector.duckdb_type); - } - - @Override - public String getBaseTypeName() throws SQLException { - return vector.duckdb_type.name(); - } - - @Override - public ResultSet getResultSet() throws SQLException { - return new DuckDBArrayResultSet(vector, offset, length); - } - - @Override - public ResultSet getResultSet(Map> map) throws SQLException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getResultSet'"); - } - - @Override - public ResultSet getResultSet(long index, int count) throws SQLException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getResultSet'"); - } - - @Override - public ResultSet getResultSet(long index, int count, Map> map) throws SQLException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getResultSet'"); - } - - @Override - public String toString() { - return Arrays.toString(array); - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBArrayResultSet.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBArrayResultSet.java deleted file mode 100644 index a77305bcbd1..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBArrayResultSet.java +++ /dev/null @@ -1,1045 +0,0 @@ -package org.duckdb; - -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.sql.*; -import java.util.Calendar; -import java.util.Map; - -public class DuckDBArrayResultSet implements ResultSet { - - private DuckDBVector vector; - int offset, length; - - int currentValueIndex = -1; - boolean closed = false; - boolean wasNull = false; - - public DuckDBArrayResultSet(DuckDBVector vector, int offset, int length) { - this.vector = vector; - this.offset = offset; - this.length = length; - } - - @Override - public boolean next() { - ++currentValueIndex; - boolean hasNext = currentValueIndex >= 0 && currentValueIndex < length; - checkBounds(); - return hasNext; - } - - @Override - public void close() { - closed = true; - } - - @Override - public boolean wasNull() throws SQLException { - return wasNull; - } - - private T getValue(String columnLabel, SqlValueGetter getter) throws SQLException { - return getValue(findColumn(columnLabel), getter); - } - - private T getValue(int columnIndex, SqlValueGetter getter) throws SQLException { - if (columnIndex == 1) { - throw new IllegalArgumentException( - "The first element of Array-backed ResultSet can only be retrieved with getInt()"); - } - if (columnIndex != 2) { - throw new IllegalArgumentException("Array-backed ResultSet can only have two columns"); - } - T value = getter.getValue(offset + currentValueIndex); - - wasNull = value == null; - return value; - } - - @Override - public String getString(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getLazyString); - } - - @Override - public boolean getBoolean(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getBoolean); - } - - @Override - public byte getByte(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getByte); - } - - @Override - public short getShort(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getShort); - } - - @Override - public int getInt(int columnIndex) throws SQLException { - if (columnIndex == 1) { - wasNull = false; - return currentValueIndex + 1; - } - return getValue(columnIndex, vector::getInt); - } - - @Override - public long getLong(int columnIndex) throws SQLException { - return getInt(columnIndex); - } - - @Override - public float getFloat(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getFloat); - } - - @Override - public double getDouble(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getDouble); - } - - @Override - public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { - return getValue(columnIndex, vector::getBigDecimal); - } - - @Override - public byte[] getBytes(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getBytes"); - } - - @Override - public Date getDate(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getDate); - } - - @Override - public Time getTime(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getTime); - } - - @Override - public Timestamp getTimestamp(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getTimestamp); - } - - @Override - public InputStream getAsciiStream(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getAsciiStream"); - } - - @Override - public InputStream getUnicodeStream(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getUnicodeStream"); - } - - @Override - public InputStream getBinaryStream(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getBinaryStream"); - } - - @Override - public String getString(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getLazyString); - } - - @Override - public boolean getBoolean(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getBoolean); - } - - @Override - public byte getByte(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getByte); - } - - @Override - public short getShort(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getShort); - } - - @Override - public int getInt(String columnLabel) throws SQLException { - int columnIndex = findColumn(columnLabel); - if (columnIndex == 1) { - return currentValueIndex; - } - return getValue(columnIndex, vector::getInt); - } - - @Override - public long getLong(String columnLabel) throws SQLException { - return getInt(columnLabel); - } - - @Override - public float getFloat(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getFloat); - } - - @Override - public double getDouble(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getDouble); - } - - @Override - public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { - return getValue(columnLabel, vector::getBigDecimal); - } - - @Override - public byte[] getBytes(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getBytes"); - } - - @Override - public Date getDate(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getDate); - } - - @Override - public Time getTime(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getTime); - } - - @Override - public Timestamp getTimestamp(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getTimestamp); - } - - @Override - public InputStream getAsciiStream(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getAsciiStream"); - } - - @Override - public InputStream getUnicodeStream(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getUnicodeStream"); - } - - @Override - public InputStream getBinaryStream(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getBinaryStream"); - } - - @Override - public SQLWarning getWarnings() throws SQLException { - return null; - } - - @Override - public void clearWarnings() throws SQLException { - // do nothing - } - - @Override - public String getCursorName() throws SQLException { - throw new SQLFeatureNotSupportedException("getCursorName"); - } - - @Override - public ResultSetMetaData getMetaData() throws SQLException { - throw new SQLFeatureNotSupportedException("getMetaData"); - } - - @Override - public Object getObject(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getObject); - } - - @Override - public Object getObject(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getTimestamp); - } - - @Override - public int findColumn(String columnLabel) throws SQLException { - return Integer.parseInt(columnLabel); - } - - @Override - public Reader getCharacterStream(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getCharacterStream"); - } - - @Override - public Reader getCharacterStream(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getCharacterStream"); - } - - @Override - public BigDecimal getBigDecimal(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getBigDecimal); - } - - @Override - public BigDecimal getBigDecimal(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getBigDecimal); - } - - @Override - public boolean isBeforeFirst() throws SQLException { - return currentValueIndex < 0; - } - - @Override - public boolean isAfterLast() throws SQLException { - return currentValueIndex >= length; - } - - @Override - public boolean isFirst() throws SQLException { - return currentValueIndex == 0; - } - - @Override - public boolean isLast() throws SQLException { - return currentValueIndex == length - 1; - } - - @Override - public void beforeFirst() throws SQLException { - currentValueIndex = -1; - } - - @Override - public void afterLast() throws SQLException { - currentValueIndex = length; - } - - @Override - public boolean first() throws SQLException { - if (length > 0) { - currentValueIndex = 0; - return true; - } - return false; - } - - @Override - public boolean last() throws SQLException { - if (length > 0) { - currentValueIndex = length - 1; - return true; - } - return false; - } - - @Override - public int getRow() throws SQLException { - return currentValueIndex + 1; - } - - @Override - public boolean absolute(int row) throws SQLException { - if (row >= 0) { - currentValueIndex = row - 1; - } else { - currentValueIndex = length + row; - } - - return checkBounds(); - } - - private boolean checkBounds() { - if (currentValueIndex < -1) { - currentValueIndex = -1; - return false; - } - if (currentValueIndex > length) { - currentValueIndex = length; - return false; - } - return true; - } - @Override - public boolean relative(int rows) throws SQLException { - currentValueIndex += rows; - return checkBounds(); - } - - @Override - public boolean previous() throws SQLException { - --currentValueIndex; - return checkBounds(); - } - - @Override - public void setFetchDirection(int direction) throws SQLException { - // do nothing - } - - @Override - public int getFetchDirection() throws SQLException { - return ResultSet.FETCH_FORWARD; - } - - @Override - public void setFetchSize(int rows) throws SQLException { - // do nothing - } - - @Override - public int getFetchSize() throws SQLException { - return 0; - } - - @Override - public int getType() throws SQLException { - return ResultSet.TYPE_SCROLL_INSENSITIVE; - } - - @Override - public int getConcurrency() throws SQLException { - return ResultSet.CONCUR_READ_ONLY; - } - - @Override - public boolean rowUpdated() throws SQLException { - return false; - } - - @Override - public boolean rowInserted() throws SQLException { - return false; - } - - @Override - public boolean rowDeleted() throws SQLException { - return false; - } - - @Override - public void updateNull(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNull"); - } - - @Override - public void updateBoolean(int columnIndex, boolean x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBoolean"); - } - - @Override - public void updateByte(int columnIndex, byte x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateByte"); - } - - @Override - public void updateShort(int columnIndex, short x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateShort"); - } - - @Override - public void updateInt(int columnIndex, int x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateInt"); - } - - @Override - public void updateLong(int columnIndex, long x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateLong"); - } - - @Override - public void updateFloat(int columnIndex, float x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateFloat"); - } - - @Override - public void updateDouble(int columnIndex, double x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateDouble"); - } - - @Override - public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBigDecimal"); - } - - @Override - public void updateString(int columnIndex, String x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateString"); - } - - @Override - public void updateBytes(int columnIndex, byte[] x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBytes"); - } - - @Override - public void updateDate(int columnIndex, Date x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateDate"); - } - - @Override - public void updateTime(int columnIndex, Time x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateTime"); - } - - @Override - public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateTimestamp"); - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - @Override - public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { - throw new SQLFeatureNotSupportedException("updateObject"); - } - - @Override - public void updateObject(int columnIndex, Object x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateObject"); - } - - @Override - public void updateNull(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNull"); - } - - @Override - public void updateBoolean(String columnLabel, boolean x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBoolean"); - } - - @Override - public void updateByte(String columnLabel, byte x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateByte"); - } - - @Override - public void updateShort(String columnLabel, short x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateShort"); - } - - @Override - public void updateInt(String columnLabel, int x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateInt"); - } - - @Override - public void updateLong(String columnLabel, long x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateLong"); - } - - @Override - public void updateFloat(String columnLabel, float x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateFloat"); - } - - @Override - public void updateDouble(String columnLabel, double x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateDouble"); - } - - @Override - public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBigDecimal"); - } - - @Override - public void updateString(String columnLabel, String x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateString"); - } - - @Override - public void updateBytes(String columnLabel, byte[] x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBytes"); - } - - @Override - public void updateDate(String columnLabel, Date x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateDate"); - } - - @Override - public void updateTime(String columnLabel, Time x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateTime"); - } - - @Override - public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateTimestamp"); - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - @Override - public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { - throw new SQLFeatureNotSupportedException("updateObject"); - } - - @Override - public void updateObject(String columnLabel, Object x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateObject"); - } - - @Override - public void insertRow() throws SQLException { - throw new SQLFeatureNotSupportedException("insertRow"); - } - - @Override - public void updateRow() throws SQLException { - throw new SQLFeatureNotSupportedException("updateRow"); - } - - @Override - public void deleteRow() throws SQLException { - throw new SQLFeatureNotSupportedException("deleteRow"); - } - - @Override - public void refreshRow() throws SQLException { - throw new SQLFeatureNotSupportedException("refreshRow"); - } - - @Override - public void cancelRowUpdates() throws SQLException { - throw new SQLFeatureNotSupportedException("cancelRowUpdates"); - } - - @Override - public void moveToInsertRow() throws SQLException { - throw new SQLFeatureNotSupportedException("moveToInsertRow"); - } - - @Override - public void moveToCurrentRow() throws SQLException { - throw new SQLFeatureNotSupportedException("moveToCurrentRow"); - } - - @Override - public Statement getStatement() throws SQLException { - throw new SQLFeatureNotSupportedException("getStatement"); - } - - @Override - public Object getObject(int columnIndex, Map> map) throws SQLException { - throw new SQLFeatureNotSupportedException("getObject"); - } - - @Override - public Ref getRef(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getRef"); - } - - @Override - public Blob getBlob(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getBlob"); - } - - @Override - public Clob getClob(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getClob"); - } - - @Override - public Array getArray(int columnIndex) throws SQLException { - return getValue(columnIndex, vector::getArray); - } - - @Override - public Object getObject(String columnLabel, Map> map) throws SQLException { - return getValue(columnLabel, vector::getObject); - } - - @Override - public Ref getRef(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getRef"); - } - - @Override - public Blob getBlob(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getBlob"); - } - - @Override - public Clob getClob(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getClob"); - } - - @Override - public Array getArray(String columnLabel) throws SQLException { - return getValue(columnLabel, vector::getArray); - } - - @Override - public Date getDate(int columnIndex, Calendar cal) throws SQLException { - return getDate(columnIndex); - } - - @Override - public Date getDate(String columnLabel, Calendar cal) throws SQLException { - return getDate(columnLabel); - } - - @Override - public Time getTime(int columnIndex, Calendar cal) throws SQLException { - return getTime(columnIndex); - } - - @Override - public Time getTime(String columnLabel, Calendar cal) throws SQLException { - return getTime(columnLabel); - } - - @Override - public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { - return getTimestamp(columnIndex); - } - - @Override - public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { - return getTimestamp(columnLabel); - } - - @Override - public URL getURL(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getURL"); - } - - @Override - public URL getURL(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getURL"); - } - - @Override - public void updateRef(int columnIndex, Ref x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateRef"); - } - - @Override - public void updateRef(String columnLabel, Ref x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateRef"); - } - - @Override - public void updateBlob(int columnIndex, Blob x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - @Override - public void updateBlob(String columnLabel, Blob x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - @Override - public void updateClob(int columnIndex, Clob x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - @Override - public void updateClob(String columnLabel, Clob x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - @Override - public void updateArray(int columnIndex, Array x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateArray"); - } - - @Override - public void updateArray(String columnLabel, Array x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateArray"); - } - - @Override - public RowId getRowId(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getRowId"); - } - - @Override - public RowId getRowId(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getRowId"); - } - - @Override - public void updateRowId(int columnIndex, RowId x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateRowId"); - } - - @Override - public void updateRowId(String columnLabel, RowId x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateRowId"); - } - - @Override - public int getHoldability() throws SQLException { - throw new SQLFeatureNotSupportedException("getHoldability"); - } - - @Override - public boolean isClosed() throws SQLException { - return closed; - } - - @Override - public void updateNString(int columnIndex, String nString) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNString"); - } - - @Override - public void updateNString(String columnLabel, String nString) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNString"); - } - - @Override - public void updateNClob(int columnIndex, NClob nClob) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - @Override - public void updateNClob(String columnLabel, NClob nClob) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - @Override - public NClob getNClob(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - @Override - public NClob getNClob(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - @Override - public SQLXML getSQLXML(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getSQLXML"); - } - - @Override - public SQLXML getSQLXML(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getSQLXML"); - } - - @Override - public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { - throw new SQLFeatureNotSupportedException("updateSQLXML"); - } - - @Override - public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { - throw new SQLFeatureNotSupportedException("updateSQLXML"); - } - - @Override - public String getNString(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getNString"); - } - - @Override - public String getNString(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getNString"); - } - - @Override - public Reader getNCharacterStream(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getNCharacterStream"); - } - - @Override - public Reader getNCharacterStream(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getNCharacterStream"); - } - - @Override - public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNCharacterStream"); - } - - @Override - public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNCharacterStream"); - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - @Override - public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - @Override - public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - @Override - public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - @Override - public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - @Override - public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - @Override - public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - @Override - public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNCharacterStream"); - } - - @Override - public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNCharacterStream"); - } - - @Override - public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - @Override - public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - @Override - public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - @Override - public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - @Override - public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - @Override - public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - @Override - public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - @Override - public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - @Override - public void updateClob(int columnIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - @Override - public void updateClob(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - @Override - public void updateNClob(int columnIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - @Override - public void updateNClob(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - @Override - public T getObject(int columnIndex, Class type) throws SQLException { - throw new SQLFeatureNotSupportedException("getObject"); - } - - @Override - public T getObject(String columnLabel, Class type) throws SQLException { - throw new SQLFeatureNotSupportedException("getObject"); - } - - @Override - public T unwrap(Class iface) throws SQLException { - return JdbcUtils.unwrap(this, iface); - } - - @Override - public boolean isWrapperFor(Class iface) throws SQLException { - return iface.isInstance(this); - } -} - -/** - * Extracts a value of requested type given a column index. - * IntFunction unsuitable because of the checked exception. - * @param Type of value to extract - */ -interface SqlValueGetter { - T getValue(int index) throws SQLException; -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBColumnType.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBColumnType.java deleted file mode 100644 index ada7c0d8f39..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBColumnType.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.duckdb; - -public enum DuckDBColumnType { - BOOLEAN, - TINYINT, - SMALLINT, - INTEGER, - BIGINT, - UTINYINT, - USMALLINT, - UINTEGER, - UBIGINT, - HUGEINT, - UHUGEINT, - FLOAT, - DOUBLE, - DECIMAL, - VARCHAR, - BLOB, - TIME, - DATE, - TIMESTAMP, - TIMESTAMP_MS, - TIMESTAMP_NS, - TIMESTAMP_S, - TIMESTAMP_WITH_TIME_ZONE, - BIT, - TIME_WITH_TIME_ZONE, - INTERVAL, - LIST, - STRUCT, - ENUM, - UUID, - JSON, - MAP, - ARRAY, - UNKNOWN, - UNION; -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBColumnTypeMetaData.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBColumnTypeMetaData.java deleted file mode 100644 index 0e38cb0661d..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBColumnTypeMetaData.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.duckdb; - -public class DuckDBColumnTypeMetaData { - public final short type_size; - public final short width; - public final short scale; - - public DuckDBColumnTypeMetaData(short type_size, short width, short scale) { - this.type_size = type_size; - this.width = width; - this.scale = scale; - } - - public static DuckDBColumnTypeMetaData parseColumnTypeMetadata(String columnTypeDetail) { - String[] split_details = columnTypeDetail.split(";"); - return new DuckDBColumnTypeMetaData(Short.parseShort(split_details[0].replace("DECIMAL", "")), - Short.parseShort(split_details[1]), Short.parseShort(split_details[2])); - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBConnection.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBConnection.java deleted file mode 100644 index 1a5b0e53a89..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBConnection.java +++ /dev/null @@ -1,367 +0,0 @@ -package org.duckdb; - -import java.lang.reflect.InvocationTargetException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.sql.Array; -import java.sql.Blob; -import java.sql.CallableStatement; -import java.sql.Clob; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.NClob; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLClientInfoException; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Savepoint; -import java.sql.Statement; -import java.sql.Struct; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.Executor; - -public final class DuckDBConnection implements java.sql.Connection { - - /** Name of the DuckDB default schema. */ - public static final String DEFAULT_SCHEMA = "main"; - - ByteBuffer conn_ref; - boolean autoCommit = true; - boolean transactionRunning; - final String url; - private final boolean readOnly; - - public static DuckDBConnection newConnection(String url, boolean readOnly, Properties properties) - throws SQLException { - if (!url.startsWith("jdbc:duckdb:")) { - throw new SQLException("DuckDB JDBC URL needs to start with 'jdbc:duckdb:'"); - } - String db_dir = url.substring("jdbc:duckdb:".length()).trim(); - if (db_dir.length() == 0) { - db_dir = ":memory:"; - } - ByteBuffer nativeReference = - DuckDBNative.duckdb_jdbc_startup(db_dir.getBytes(StandardCharsets.UTF_8), readOnly, properties); - return new DuckDBConnection(nativeReference, url, readOnly); - } - - private DuckDBConnection(ByteBuffer connectionReference, String url, boolean readOnly) throws SQLException { - conn_ref = connectionReference; - this.url = url; - this.readOnly = readOnly; - DuckDBNative.duckdb_jdbc_set_auto_commit(connectionReference, true); - } - - public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) - throws SQLException { - if (isClosed()) { - throw new SQLException("Connection was closed"); - } - if (resultSetConcurrency == ResultSet.CONCUR_READ_ONLY && resultSetType == ResultSet.TYPE_FORWARD_ONLY) { - return new DuckDBPreparedStatement(this); - } - throw new SQLFeatureNotSupportedException("createStatement"); - } - - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, - int resultSetHoldability) throws SQLException { - if (isClosed()) { - throw new SQLException("Connection was closed"); - } - if (resultSetConcurrency == ResultSet.CONCUR_READ_ONLY && resultSetType == ResultSet.TYPE_FORWARD_ONLY) { - return new DuckDBPreparedStatement(this, sql); - } - throw new SQLFeatureNotSupportedException("prepareStatement"); - } - - public Statement createStatement() throws SQLException { - return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - } - - public Connection duplicate() throws SQLException { - if (isClosed()) { - throw new SQLException("Connection is closed"); - } - return new DuckDBConnection(DuckDBNative.duckdb_jdbc_connect(conn_ref), url, readOnly); - } - - public void commit() throws SQLException { - try (Statement s = createStatement()) { - s.execute("COMMIT"); - transactionRunning = false; - } - } - - public void rollback() throws SQLException { - try (Statement s = createStatement()) { - s.execute("ROLLBACK"); - transactionRunning = false; - } - } - - protected void finalize() throws Throwable { - close(); - } - - public synchronized void close() throws SQLException { - if (conn_ref != null) { - DuckDBNative.duckdb_jdbc_disconnect(conn_ref); - conn_ref = null; - } - } - - public boolean isClosed() throws SQLException { - return conn_ref == null; - } - - public boolean isValid(int timeout) throws SQLException { - if (isClosed()) { - return false; - } - // run a query just to be sure - try (Statement s = createStatement(); ResultSet rs = s.executeQuery("SELECT 42")) { - return rs.next() && rs.getInt(1) == 42; - } - } - - public SQLWarning getWarnings() throws SQLException { - return null; - } - - public void clearWarnings() throws SQLException { - } - - public void setTransactionIsolation(int level) throws SQLException { - if (level > TRANSACTION_REPEATABLE_READ) { - throw new SQLFeatureNotSupportedException("setTransactionIsolation"); - } - } - - public int getTransactionIsolation() throws SQLException { - return TRANSACTION_REPEATABLE_READ; - } - - public void setReadOnly(boolean readOnly) throws SQLException { - if (readOnly != this.readOnly) { - throw new SQLFeatureNotSupportedException("Can't change read-only status on connection level."); - } - } - - public boolean isReadOnly() { - return readOnly; - } - - public void setAutoCommit(boolean autoCommit) throws SQLException { - if (isClosed()) { - throw new SQLException("Connection was closed"); - } - - if (this.autoCommit != autoCommit) { - this.autoCommit = autoCommit; - - // A running transaction is committed if switched to auto-commit - if (transactionRunning && autoCommit) { - this.commit(); - } - } - return; - - // Native method is not working as one would expect ... uncomment maybe later - // DuckDBNative.duckdb_jdbc_set_auto_commit(conn_ref, autoCommit); - } - - public boolean getAutoCommit() throws SQLException { - if (isClosed()) { - throw new SQLException("Connection was closed"); - } - return this.autoCommit; - - // Native method is not working as one would expect ... uncomment maybe later - // return DuckDBNative.duckdb_jdbc_get_auto_commit(conn_ref); - } - - public PreparedStatement prepareStatement(String sql) throws SQLException { - return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, 0); - } - - public DatabaseMetaData getMetaData() throws SQLException { - return new DuckDBDatabaseMetaData(this); - } - - public void setCatalog(String catalog) throws SQLException { - DuckDBNative.duckdb_jdbc_set_catalog(conn_ref, catalog); - } - - public String getCatalog() throws SQLException { - return DuckDBNative.duckdb_jdbc_get_catalog(conn_ref); - } - - public void setSchema(String schema) throws SQLException { - DuckDBNative.duckdb_jdbc_set_schema(conn_ref, schema); - } - - public String getSchema() throws SQLException { - return DuckDBNative.duckdb_jdbc_get_schema(conn_ref); - } - - @Override - public T unwrap(Class iface) throws SQLException { - return JdbcUtils.unwrap(this, iface); - } - - @Override - public boolean isWrapperFor(Class iface) { - return iface.isInstance(this); - } - - public void abort(Executor executor) throws SQLException { - throw new SQLFeatureNotSupportedException("abort"); - } - - public Clob createClob() throws SQLException { - throw new SQLFeatureNotSupportedException("createClob"); - } - - public Blob createBlob() throws SQLException { - throw new SQLFeatureNotSupportedException("createBlob"); - } - - // less likely to implement this stuff - - public CallableStatement prepareCall(String sql) throws SQLException { - throw new SQLFeatureNotSupportedException("prepareCall"); - } - - public String nativeSQL(String sql) throws SQLException { - throw new SQLFeatureNotSupportedException("nativeSQL"); - } - - public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { - return createStatement(resultSetType, resultSetConcurrency, 0); - } - - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) - throws SQLException { - return prepareStatement(sql, resultSetType, resultSetConcurrency, 0); - } - - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - throw new SQLFeatureNotSupportedException("prepareCall"); - } - - public Map> getTypeMap() throws SQLException { - throw new SQLFeatureNotSupportedException("getTypeMap"); - } - - public void setTypeMap(Map> map) throws SQLException { - throw new SQLFeatureNotSupportedException("setTypeMap"); - } - - public void setHoldability(int holdability) throws SQLException { - throw new SQLFeatureNotSupportedException("setHoldability"); - } - - public int getHoldability() throws SQLException { - throw new SQLFeatureNotSupportedException("getHoldability"); - } - - public Savepoint setSavepoint() throws SQLException { - throw new SQLFeatureNotSupportedException("setSavepoint"); - } - - public Savepoint setSavepoint(String name) throws SQLException { - throw new SQLFeatureNotSupportedException("setSavepoint"); - } - - public void rollback(Savepoint savepoint) throws SQLException { - throw new SQLFeatureNotSupportedException("rollback"); - } - - public void releaseSavepoint(Savepoint savepoint) throws SQLException { - throw new SQLFeatureNotSupportedException("releaseSavepoint"); - } - - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, - int resultSetHoldability) throws SQLException { - throw new SQLFeatureNotSupportedException("prepareCall"); - } - - public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { - throw new SQLFeatureNotSupportedException("prepareStatement"); - } - - public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { - throw new SQLFeatureNotSupportedException("prepareStatement"); - } - - public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { - throw new SQLFeatureNotSupportedException("prepareStatement"); - } - - public NClob createNClob() throws SQLException { - throw new SQLFeatureNotSupportedException("createNClob"); - } - - public SQLXML createSQLXML() throws SQLException { - throw new SQLFeatureNotSupportedException("createSQLXML"); // hell no - } - - public void setClientInfo(String name, String value) throws SQLClientInfoException { - throw new SQLClientInfoException(); - } - - public void setClientInfo(Properties properties) throws SQLClientInfoException { - throw new SQLClientInfoException(); - } - - public String getClientInfo(String name) throws SQLException { - throw new SQLFeatureNotSupportedException("getClientInfo"); - } - - public Properties getClientInfo() throws SQLException { - throw new SQLFeatureNotSupportedException("getClientInfo"); - } - - public Array createArrayOf(String typeName, Object[] elements) throws SQLException { - throw new SQLFeatureNotSupportedException("createArrayOf"); - } - - public Struct createStruct(String typeName, Object[] attributes) throws SQLException { - throw new SQLFeatureNotSupportedException("createStruct"); - } - - public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { - throw new SQLFeatureNotSupportedException("setNetworkTimeout"); - } - - public int getNetworkTimeout() throws SQLException { - throw new SQLFeatureNotSupportedException("getNetworkTimeout"); - } - - public DuckDBAppender createAppender(String schemaName, String tableName) throws SQLException { - return new DuckDBAppender(this, schemaName, tableName); - } - - private static long getArrowStreamAddress(Object arrow_array_stream) { - try { - Class arrow_array_stream_class = Class.forName("org.apache.arrow.c.ArrowArrayStream"); - if (!arrow_array_stream_class.isInstance(arrow_array_stream)) { - throw new RuntimeException("Need to pass an ArrowArrayStream"); - } - return (Long) arrow_array_stream_class.getMethod("memoryAddress").invoke(arrow_array_stream); - - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | SecurityException | - ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - public void registerArrowStream(String name, Object arrow_array_stream) { - long array_stream_address = getArrowStreamAddress(arrow_array_stream); - DuckDBNative.duckdb_jdbc_arrow_register(conn_ref, array_stream_address, name.getBytes(StandardCharsets.UTF_8)); - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBDatabaseMetaData.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBDatabaseMetaData.java deleted file mode 100644 index 89bff73425f..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBDatabaseMetaData.java +++ /dev/null @@ -1,1253 +0,0 @@ -package org.duckdb; - -import javax.sql.rowset.CachedRowSet; -import javax.sql.rowset.RowSetProvider; - -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.RowIdLifetime; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.Statement; -import java.sql.Types; -import java.util.Arrays; -import java.util.Map; -import java.util.stream.Collectors; - -import static java.lang.System.lineSeparator; - -public class DuckDBDatabaseMetaData implements DatabaseMetaData { - DuckDBConnection conn; - - public DuckDBDatabaseMetaData(DuckDBConnection conn) { - this.conn = conn; - } - - @Override - public T unwrap(Class iface) throws SQLException { - return JdbcUtils.unwrap(this, iface); - } - - @Override - public boolean isWrapperFor(Class iface) { - return iface.isInstance(this); - } - - @Override - public boolean allProceduresAreCallable() throws SQLException { - return false; - } - - @Override - public boolean allTablesAreSelectable() throws SQLException { - return true; - } - - @Override - public String getURL() throws SQLException { - return conn.url; - } - - @Override - public String getUserName() throws SQLException { - return ""; - } - - @Override - public boolean isReadOnly() throws SQLException { - return conn.isReadOnly(); - } - - @Override - public boolean nullsAreSortedHigh() throws SQLException { - return true; - } - - @Override - public boolean nullsAreSortedLow() throws SQLException { - return false; - } - - @Override - public boolean nullsAreSortedAtStart() throws SQLException { - return true; - } - - @Override - public boolean nullsAreSortedAtEnd() throws SQLException { - return false; - } - - @Override - public String getDatabaseProductName() throws SQLException { - return "DuckDB"; - } - - @Override - public String getDatabaseProductVersion() throws SQLException { - try (Statement s = conn.createStatement(); ResultSet rs = s.executeQuery("PRAGMA version")) { - rs.next(); - String result = rs.getString(1); - return result; - } - } - - @Override - public String getDriverName() throws SQLException { - return "DuckDBJ"; - } - - @Override - public String getDriverVersion() throws SQLException { - return "1.0"; - } - - @Override - public int getDriverMajorVersion() { - return 1; - } - - @Override - public int getDriverMinorVersion() { - return 0; - } - - @Override - public boolean usesLocalFiles() throws SQLException { - return true; - } - - @Override - public boolean usesLocalFilePerTable() throws SQLException { - return false; - } - - @Override - public boolean supportsMixedCaseIdentifiers() throws SQLException { - return true; - } - - @Override - public boolean storesUpperCaseIdentifiers() throws SQLException { - return false; - } - - @Override - public boolean storesLowerCaseIdentifiers() throws SQLException { - return false; - } - - @Override - public boolean storesMixedCaseIdentifiers() throws SQLException { - return true; - } - - @Override - public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { - return true; - } - - @Override - public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { - return false; - } - - @Override - public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { - return false; - } - - @Override - public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { - return true; - } - - @Override - public String getIdentifierQuoteString() throws SQLException { - return "\""; - } - - @Override - public String getSQLKeywords() throws SQLException { - throw new SQLFeatureNotSupportedException("getSQLKeywords"); - } - - @Override - public String getNumericFunctions() throws SQLException { - throw new SQLFeatureNotSupportedException("getNumericFunctions"); - } - - @Override - public String getStringFunctions() throws SQLException { - throw new SQLFeatureNotSupportedException("getStringFunctions"); - } - - @Override - public String getSystemFunctions() throws SQLException { - throw new SQLFeatureNotSupportedException("getSystemFunctions"); - } - - @Override - public String getTimeDateFunctions() throws SQLException { - throw new SQLFeatureNotSupportedException("getTimeDateFunctions"); - } - - @Override - public String getSearchStringEscape() throws SQLException { - return null; - } - - @Override - public String getExtraNameCharacters() throws SQLException { - return ""; - } - - @Override - public boolean supportsAlterTableWithAddColumn() throws SQLException { - return true; - } - - @Override - public boolean supportsAlterTableWithDropColumn() throws SQLException { - return true; - } - - @Override - public boolean supportsColumnAliasing() throws SQLException { - return true; - } - - @Override - public boolean nullPlusNonNullIsNull() throws SQLException { - return true; - } - - @Override - public boolean supportsConvert() throws SQLException { - return false; - } - - @Override - public boolean supportsConvert(int fromType, int toType) throws SQLException { - return false; - } - - @Override - public boolean supportsTableCorrelationNames() throws SQLException { - return true; - } - - @Override - public boolean supportsDifferentTableCorrelationNames() throws SQLException { - return false; - } - - @Override - public boolean supportsExpressionsInOrderBy() throws SQLException { - return true; - } - - @Override - public boolean supportsOrderByUnrelated() throws SQLException { - return true; - } - - @Override - public boolean supportsGroupBy() throws SQLException { - return true; - } - - @Override - public boolean supportsGroupByUnrelated() throws SQLException { - return true; - } - - @Override - public boolean supportsGroupByBeyondSelect() throws SQLException { - return true; - } - - @Override - public boolean supportsLikeEscapeClause() throws SQLException { - return true; - } - - @Override - public boolean supportsMultipleResultSets() throws SQLException { - return false; - } - - @Override - public boolean supportsMultipleTransactions() throws SQLException { - return true; - } - - @Override - public boolean supportsNonNullableColumns() throws SQLException { - return true; - } - - @Override - public boolean supportsMinimumSQLGrammar() throws SQLException { - return true; - } - - @Override - public boolean supportsCoreSQLGrammar() throws SQLException { - return true; - } - - @Override - public boolean supportsExtendedSQLGrammar() throws SQLException { - return true; - } - - @Override - public boolean supportsANSI92EntryLevelSQL() throws SQLException { - return true; - } - - @Override - public boolean supportsANSI92IntermediateSQL() throws SQLException { - return true; - } - - @Override - public boolean supportsANSI92FullSQL() throws SQLException { - return true; - } - - @Override - public boolean supportsIntegrityEnhancementFacility() throws SQLException { - return false; - } - - @Override - public boolean supportsOuterJoins() throws SQLException { - return true; - } - - @Override - public boolean supportsFullOuterJoins() throws SQLException { - return true; - } - - @Override - public boolean supportsLimitedOuterJoins() throws SQLException { - return true; - } - - @Override - public String getSchemaTerm() throws SQLException { - return "schema"; - } - - @Override - public String getProcedureTerm() throws SQLException { - return "procedure"; - } - - @Override - public String getCatalogTerm() throws SQLException { - return "catalog"; - } - - @Override - public boolean isCatalogAtStart() throws SQLException { - return true; - } - - @Override - public String getCatalogSeparator() throws SQLException { - return "."; - } - - @Override - public boolean supportsSchemasInDataManipulation() throws SQLException { - return true; - } - - @Override - public boolean supportsSchemasInProcedureCalls() throws SQLException { - return true; - } - - @Override - public boolean supportsSchemasInTableDefinitions() throws SQLException { - return true; - } - - @Override - public boolean supportsSchemasInIndexDefinitions() throws SQLException { - return true; - } - - @Override - public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { - return false; - } - - @Override - public boolean supportsCatalogsInDataManipulation() throws SQLException { - return true; - } - - @Override - public boolean supportsCatalogsInProcedureCalls() throws SQLException { - return false; - } - - @Override - public boolean supportsCatalogsInTableDefinitions() throws SQLException { - return true; - } - - @Override - public boolean supportsCatalogsInIndexDefinitions() throws SQLException { - return true; - } - - @Override - public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { - return false; - } - - @Override - public boolean supportsPositionedDelete() throws SQLException { - return false; - } - - @Override - public boolean supportsPositionedUpdate() throws SQLException { - return false; - } - - @Override - public boolean supportsSelectForUpdate() throws SQLException { - return false; - } - - @Override - public boolean supportsStoredProcedures() throws SQLException { - return false; - } - - @Override - public boolean supportsSubqueriesInComparisons() throws SQLException { - return true; - } - - @Override - public boolean supportsSubqueriesInExists() throws SQLException { - return true; - } - - @Override - public boolean supportsSubqueriesInIns() throws SQLException { - return true; - } - - @Override - public boolean supportsSubqueriesInQuantifieds() throws SQLException { - return true; - } - - @Override - public boolean supportsCorrelatedSubqueries() throws SQLException { - return true; - } - - @Override - public boolean supportsUnion() throws SQLException { - return true; - } - - @Override - public boolean supportsUnionAll() throws SQLException { - return true; - } - - @Override - public boolean supportsOpenCursorsAcrossCommit() throws SQLException { - return false; - } - - @Override - public boolean supportsOpenCursorsAcrossRollback() throws SQLException { - return false; - } - - @Override - public boolean supportsOpenStatementsAcrossCommit() throws SQLException { - return false; - } - - @Override - public boolean supportsOpenStatementsAcrossRollback() throws SQLException { - return false; - } - - @Override - public int getMaxBinaryLiteralLength() throws SQLException { - - return 0; - } - - @Override - public int getMaxCharLiteralLength() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnsInGroupBy() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnsInIndex() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnsInOrderBy() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnsInSelect() throws SQLException { - return 0; - } - - @Override - public int getMaxColumnsInTable() throws SQLException { - return 0; - } - - @Override - public int getMaxConnections() throws SQLException { - return 0; - } - - @Override - public int getMaxCursorNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxIndexLength() throws SQLException { - return 0; - } - - @Override - public int getMaxSchemaNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxProcedureNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxCatalogNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxRowSize() throws SQLException { - return 0; - } - - @Override - public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { - return false; - } - - @Override - public int getMaxStatementLength() throws SQLException { - return 0; - } - - @Override - public int getMaxStatements() throws SQLException { - return 0; - } - - @Override - public int getMaxTableNameLength() throws SQLException { - return 0; - } - - @Override - public int getMaxTablesInSelect() throws SQLException { - return 0; - } - - @Override - public int getMaxUserNameLength() throws SQLException { - return 0; - } - - @Override - public int getDefaultTransactionIsolation() throws SQLException { - return Connection.TRANSACTION_REPEATABLE_READ; - } - - @Override - public boolean supportsTransactions() throws SQLException { - return true; - } - - @Override - public boolean supportsTransactionIsolationLevel(int level) throws SQLException { - return level < Connection.TRANSACTION_SERIALIZABLE; - } - - @Override - public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { - return true; - } - - @Override - public boolean supportsDataManipulationTransactionsOnly() throws SQLException { - return false; - } - - @Override - public boolean dataDefinitionCausesTransactionCommit() throws SQLException { - return false; - } - - @Override - public boolean dataDefinitionIgnoredInTransactions() throws SQLException { - return false; - } - - @Override - public ResultSet getCatalogs() throws SQLException { - Statement statement = conn.createStatement(); - statement.closeOnCompletion(); - return statement.executeQuery( - "SELECT DISTINCT catalog_name AS 'TABLE_CAT' FROM information_schema.schemata ORDER BY \"TABLE_CAT\""); - } - - @Override - public ResultSet getSchemas() throws SQLException { - Statement statement = conn.createStatement(); - statement.closeOnCompletion(); - return statement.executeQuery( - "SELECT schema_name AS 'TABLE_SCHEM', catalog_name AS 'TABLE_CATALOG' FROM information_schema.schemata ORDER BY \"TABLE_CATALOG\", \"TABLE_SCHEM\""); - } - - @Override - public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { - StringBuilder sb = new StringBuilder(512); - sb.append("SELECT schema_name AS 'TABLE_SCHEM', catalog_name AS 'TABLE_CATALOG'"); - sb.append(lineSeparator()); - sb.append("FROM information_schema.schemata"); - sb.append(lineSeparator()); - if (catalog != null || schemaPattern != null) { - sb.append("WHERE "); - } - - if (catalog != null) { - if (catalog.isEmpty()) { - sb.append("catalog_name IS NULL"); - } else { - sb.append("catalog_name = ?"); - } - sb.append(lineSeparator()); - } - if (schemaPattern != null) { - if (catalog != null) { - sb.append("AND "); - } - if (schemaPattern.isEmpty()) { - sb.append("schema_name IS NULL"); - } else { - sb.append("schema_name LIKE ?"); - } - sb.append(lineSeparator()); - } - sb.append("ORDER BY \"TABLE_CATALOG\", \"TABLE_SCHEM\""); - sb.append(lineSeparator()); - - PreparedStatement ps = conn.prepareStatement(sb.toString()); - int paramIndex = 0; - if (catalog != null && !catalog.isEmpty()) { - ps.setString(++paramIndex, catalog); - } - if (schemaPattern != null && !schemaPattern.isEmpty()) { - ps.setString(++paramIndex, schemaPattern); - } - ps.closeOnCompletion(); - return ps.executeQuery(); - } - - @Override - public ResultSet getTableTypes() throws SQLException { - String[] tableTypesArray = new String[] {"BASE TABLE", "LOCAL TEMPORARY", "VIEW"}; - StringBuilder stringBuilder = new StringBuilder(128); - boolean first = true; - for (String tableType : tableTypesArray) { - if (!first) { - stringBuilder.append("\nUNION ALL\n"); - } - stringBuilder.append("SELECT '"); - stringBuilder.append(tableType); - stringBuilder.append("'"); - if (first) { - stringBuilder.append(" AS 'TABLE_TYPE'"); - first = false; - } - } - stringBuilder.append("\nORDER BY TABLE_TYPE"); - Statement statement = conn.createStatement(); - statement.closeOnCompletion(); - return statement.executeQuery(stringBuilder.toString()); - } - - @Override - public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) - throws SQLException { - StringBuilder str = new StringBuilder(512); - - str.append("SELECT table_catalog AS 'TABLE_CAT'").append(lineSeparator()); - str.append(", table_schema AS 'TABLE_SCHEM'").append(lineSeparator()); - str.append(", table_name AS 'TABLE_NAME'").append(lineSeparator()); - str.append(", table_type AS 'TABLE_TYPE'").append(lineSeparator()); - str.append(", TABLE_COMMENT AS 'REMARKS'").append(lineSeparator()); - str.append(", NULL::VARCHAR AS 'TYPE_CAT'").append(lineSeparator()); - str.append(", NULL::VARCHAR AS 'TYPE_SCHEM'").append(lineSeparator()); - str.append(", NULL::VARCHAR AS 'TYPE_NAME'").append(lineSeparator()); - str.append(", NULL::VARCHAR AS 'SELF_REFERENCING_COL_NAME'").append(lineSeparator()); - str.append(", NULL::VARCHAR AS 'REF_GENERATION'").append(lineSeparator()); - str.append("FROM information_schema.tables").append(lineSeparator()); - - // tableNamePattern - a table name pattern; must match the table name as it is stored in the database - if (tableNamePattern == null) { - // non-standard behavior. - tableNamePattern = "%"; - } - str.append("WHERE table_name LIKE ?").append(lineSeparator()); - - // catalog - a catalog name; must match the catalog name as it is stored in the database; - // "" retrieves those without a catalog; - // null means that the catalog name should not be used to narrow the search - boolean hasCatalogParam = false; - if (catalog != null) { - str.append("AND table_catalog "); - if (catalog.isEmpty()) { - str.append("IS NULL").append(lineSeparator()); - } else { - str.append("= ?").append(lineSeparator()); - hasCatalogParam = true; - } - } - - // schemaPattern - a schema name pattern; must match the schema name as it is stored in the database; - // "" retrieves those without a schema; - // null means that the schema name should not be used to narrow the search - boolean hasSchemaParam = false; - if (schemaPattern != null) { - str.append("AND table_schema "); - if (schemaPattern.isEmpty()) { - str.append("IS NULL").append(lineSeparator()); - } else { - str.append("LIKE ?").append(lineSeparator()); - hasSchemaParam = true; - } - } - - if (types != null && types.length > 0) { - str.append("AND table_type IN (").append(lineSeparator()); - for (int i = 0; i < types.length; i++) { - if (i > 0) { - str.append(','); - } - str.append('?'); - } - str.append(')'); - } - - // ordered by TABLE_TYPE, TABLE_CAT, TABLE_SCHEM and TABLE_NAME. - str.append("ORDER BY table_type").append(lineSeparator()); - str.append(", table_catalog").append(lineSeparator()); - str.append(", table_schema").append(lineSeparator()); - str.append(", table_name").append(lineSeparator()); - - PreparedStatement ps = conn.prepareStatement(str.toString()); - - int paramOffset = 1; - ps.setString(paramOffset++, tableNamePattern); - - if (hasCatalogParam) { - ps.setString(paramOffset++, catalog); - } - if (hasSchemaParam) { - ps.setString(paramOffset++, schemaPattern); - } - - if (types != null && types.length > 0) { - for (int i = 0; i < types.length; i++) { - ps.setString(paramOffset + i, types[i]); - } - } - ps.closeOnCompletion(); - return ps.executeQuery(); - } - - @Override - public ResultSet getColumns(String catalogPattern, String schemaPattern, String tableNamePattern, - String columnNamePattern) throws SQLException { - if (catalogPattern == null) { - catalogPattern = "%"; - } - if (schemaPattern == null) { - schemaPattern = "%"; - } - if (tableNamePattern == null) { - tableNamePattern = "%"; - } - if (columnNamePattern == null) { - columnNamePattern = "%"; - } - - PreparedStatement ps = - conn.prepareStatement("SELECT " - + "table_catalog AS 'TABLE_CAT', " - + "table_schema AS 'TABLE_SCHEM', " - + "table_name AS 'TABLE_NAME', " - + "column_name as 'COLUMN_NAME', " + makeDataMap("c.data_type", "DATA_TYPE") + ", " - + "c.data_type AS 'TYPE_NAME', " - + "NULL AS 'COLUMN_SIZE', NULL AS 'BUFFER_LENGTH', " - + "numeric_precision AS 'DECIMAL_DIGITS', " - + "10 AS 'NUM_PREC_RADIX', " - + "CASE WHEN is_nullable = 'YES' THEN 1 else 0 END AS 'NULLABLE', " - + "COLUMN_COMMENT as 'REMARKS', " - + "column_default AS 'COLUMN_DEF', " - + "NULL AS 'SQL_DATA_TYPE', " - + "NULL AS 'SQL_DATETIME_SUB', " - + "NULL AS 'CHAR_OCTET_LENGTH', " - + "ordinal_position AS 'ORDINAL_POSITION', " - + "is_nullable AS 'IS_NULLABLE', " - + "NULL AS 'SCOPE_CATALOG', " - + "NULL AS 'SCOPE_SCHEMA', " - + "NULL AS 'SCOPE_TABLE', " - + "NULL AS 'SOURCE_DATA_TYPE', " - + "'' AS 'IS_AUTOINCREMENT', " - + "'' AS 'IS_GENERATEDCOLUMN' " - + "FROM information_schema.columns c " - + "WHERE table_catalog LIKE ? AND " - + "table_schema LIKE ? AND " - + "table_name LIKE ? AND " - + "column_name LIKE ? " - + "ORDER BY \"TABLE_CAT\",\"TABLE_SCHEM\", \"TABLE_NAME\", \"ORDINAL_POSITION\""); - ps.setString(1, catalogPattern); - ps.setString(2, schemaPattern); - ps.setString(3, tableNamePattern); - ps.setString(4, columnNamePattern); - ps.closeOnCompletion(); - return ps.executeQuery(); - } - - @Override - public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) - throws SQLException { - throw new SQLFeatureNotSupportedException("getColumnPrivileges"); - } - - @Override - public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) - throws SQLException { - throw new SQLFeatureNotSupportedException("getTablePrivileges"); - } - - @Override - public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) - throws SQLException { - Statement statement = conn.createStatement(); - statement.closeOnCompletion(); - return statement.executeQuery("SELECT NULL WHERE FALSE"); - } - - @Override - public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, - String columnNamePattern) throws SQLException { - Statement statement = conn.createStatement(); - statement.closeOnCompletion(); - return statement.executeQuery("SELECT NULL WHERE FALSE"); - } - - @Override - public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) - throws SQLException { - throw new SQLFeatureNotSupportedException("getBestRowIdentifier"); - } - - @Override - public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { - throw new SQLFeatureNotSupportedException("getVersionColumns"); - } - - @Override - public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { - StringBuilder pw = new StringBuilder(512); - pw.append("WITH constraint_columns AS (").append(lineSeparator()); - pw.append("SELECT").append(lineSeparator()); - pw.append(" database_name AS \"TABLE_CAT\"").append(lineSeparator()); - pw.append(", schema_name AS \"TABLE_SCHEM\"").append(lineSeparator()); - pw.append(", table_name AS \"TABLE_NAME\"").append(lineSeparator()); - pw.append(", unnest(constraint_column_names) AS \"COLUMN_NAME\"").append(lineSeparator()); - pw.append(", CAST(NULL AS VARCHAR) AS \"PK_NAME\"").append(lineSeparator()); - pw.append("FROM duckdb_constraints").append(lineSeparator()); - pw.append("WHERE constraint_type = 'PRIMARY KEY'").append(lineSeparator()); - // catalog param - if (catalog != null) { - if (catalog.isEmpty()) { - pw.append("AND database_name IS NULL").append(lineSeparator()); - } else { - pw.append("AND database_name = ?").append(lineSeparator()); - } - } - // schema param - if (schema != null) { - if (schema.isEmpty()) { - pw.append("AND schema_name IS NULL").append(lineSeparator()); - } else { - pw.append("AND schema_name = ?").append(lineSeparator()); - } - } - // table name param - pw.append("AND table_name = ?").append(lineSeparator()); - - pw.append(")").append(lineSeparator()); - pw.append("SELECT \"TABLE_CAT\"").append(lineSeparator()); - pw.append(", \"TABLE_SCHEM\"").append(lineSeparator()); - pw.append(", \"TABLE_NAME\"").append(lineSeparator()); - pw.append(", \"COLUMN_NAME\"").append(lineSeparator()); - pw.append(", CAST(ROW_NUMBER() OVER ").append(lineSeparator()); - pw.append("(PARTITION BY \"TABLE_CAT\", \"TABLE_SCHEM\", \"TABLE_NAME\") AS INT) AS \"KEY_SEQ\"") - .append(lineSeparator()); - pw.append(", \"PK_NAME\"").append(lineSeparator()); - pw.append("FROM constraint_columns").append(lineSeparator()); - pw.append("ORDER BY \"TABLE_CAT\", \"TABLE_SCHEM\", \"TABLE_NAME\", \"KEY_SEQ\"").append(lineSeparator()); - - int paramIndex = 1; - PreparedStatement ps = conn.prepareStatement(pw.toString()); - - if (catalog != null && !catalog.isEmpty()) { - ps.setString(paramIndex++, catalog); - } - if (schema != null && !schema.isEmpty()) { - ps.setString(paramIndex++, schema); - } - ps.setString(paramIndex++, table); - ps.closeOnCompletion(); - return ps.executeQuery(); - } - - @Override - public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { - throw new SQLFeatureNotSupportedException("getImportedKeys"); - } - - @Override - public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { - throw new SQLFeatureNotSupportedException("getExportedKeys"); - } - - @Override - public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, - String foreignCatalog, String foreignSchema, String foreignTable) - throws SQLException { - throw new SQLFeatureNotSupportedException("getCrossReference"); - } - - @Override - public ResultSet getTypeInfo() throws SQLException { - throw new SQLFeatureNotSupportedException("getTypeInfo"); - } - - @Override - public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) - throws SQLException { - throw new SQLFeatureNotSupportedException("getIndexInfo("); - } - - @Override - public boolean supportsResultSetType(int type) throws SQLException { - return type == ResultSet.TYPE_FORWARD_ONLY; - } - - @Override - public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { - return type == ResultSet.TYPE_FORWARD_ONLY && concurrency == ResultSet.CONCUR_READ_ONLY; - } - - @Override - public boolean ownUpdatesAreVisible(int type) throws SQLException { - throw new SQLFeatureNotSupportedException("ownUpdatesAreVisible"); - } - - @Override - public boolean ownDeletesAreVisible(int type) throws SQLException { - throw new SQLFeatureNotSupportedException("ownDeletesAreVisible"); - } - - @Override - public boolean ownInsertsAreVisible(int type) throws SQLException { - throw new SQLFeatureNotSupportedException("ownInsertsAreVisible"); - } - - @Override - public boolean othersUpdatesAreVisible(int type) throws SQLException { - throw new SQLFeatureNotSupportedException("othersUpdatesAreVisible"); - } - - @Override - public boolean othersDeletesAreVisible(int type) throws SQLException { - throw new SQLFeatureNotSupportedException("othersDeletesAreVisible"); - } - - @Override - public boolean othersInsertsAreVisible(int type) throws SQLException { - throw new SQLFeatureNotSupportedException("othersInsertsAreVisible"); - } - - @Override - public boolean updatesAreDetected(int type) throws SQLException { - throw new SQLFeatureNotSupportedException("updatesAreDetected"); - } - - @Override - public boolean deletesAreDetected(int type) throws SQLException { - throw new SQLFeatureNotSupportedException("deletesAreDetected"); - } - - @Override - public boolean insertsAreDetected(int type) throws SQLException { - throw new SQLFeatureNotSupportedException("insertsAreDetected"); - } - - @Override - public boolean supportsBatchUpdates() throws SQLException { - return true; - } - - @Override - public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) - throws SQLException { - throw new SQLFeatureNotSupportedException("getUDTs"); - } - - @Override - public Connection getConnection() throws SQLException { - return conn; - } - - @Override - public boolean supportsSavepoints() throws SQLException { - return false; - } - - @Override - public boolean supportsNamedParameters() throws SQLException { - return false; - } - - @Override - public boolean supportsMultipleOpenResults() throws SQLException { - return true; - } - - @Override - public boolean supportsGetGeneratedKeys() throws SQLException { - return false; - } - - @Override - public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { - throw new SQLFeatureNotSupportedException("getSuperTypes"); - } - - @Override - public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { - throw new SQLFeatureNotSupportedException("getSuperTables"); - } - - @Override - public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, - String attributeNamePattern) throws SQLException { - throw new SQLFeatureNotSupportedException("getAttributes"); - } - - @Override - public boolean supportsResultSetHoldability(int holdability) throws SQLException { - return false; - } - - @Override - public int getResultSetHoldability() throws SQLException { - throw new SQLFeatureNotSupportedException("getResultSetHoldability"); - } - - @Override - public int getDatabaseMajorVersion() throws SQLException { - return 1; - } - - @Override - public int getDatabaseMinorVersion() throws SQLException { - return 0; - } - - @Override - public int getJDBCMajorVersion() throws SQLException { - return 1; - } - - @Override - public int getJDBCMinorVersion() throws SQLException { - return 0; - } - - @Override - public int getSQLStateType() throws SQLException { - throw new SQLFeatureNotSupportedException("getSQLStateType"); - } - - @Override - public boolean locatorsUpdateCopy() throws SQLException { - throw new SQLFeatureNotSupportedException("locatorsUpdateCopy"); - } - - @Override - public boolean supportsStatementPooling() throws SQLException { - return false; - } - - @Override - public RowIdLifetime getRowIdLifetime() throws SQLException { - throw new SQLFeatureNotSupportedException("getRowIdLifetime"); - } - - @Override - public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { - return false; - } - - @Override - public boolean autoCommitFailureClosesAllResultSets() throws SQLException { - throw new SQLFeatureNotSupportedException("autoCommitFailureClosesAllResultSets"); - } - - @Override - public ResultSet getClientInfoProperties() throws SQLException { - throw new SQLFeatureNotSupportedException("getClientInfoProperties"); - } - - /** - * - * @param catalog a catalog name; must match the catalog name as it - * is stored in the database; "" retrieves those without a catalog; - * null means that the catalog name should not be used to narrow - * the search - * @param schemaPattern a schema name pattern; must match the schema name - * as it is stored in the database; "" retrieves those without a schema; - * null means that the schema name should not be used to narrow - * the search - * @param functionNamePattern a function name pattern; must match the - * function name as it is stored in the database - * FUNCTION_CAT String => function catalog (may be null) - * FUNCTION_SCHEM String => function schema (may be null) - * FUNCTION_NAME String => function name. This is the name used to invoke the function - * REMARKS String => explanatory comment on the function - * FUNCTION_TYPE short => kind of function: - * - functionResultUnknown - Cannot determine if a return value or table will be returned - * - functionNoTable- Does not return a table - * - functionReturnsTable - Returns a table - * SPECIFIC_NAME String => the name which uniquely identifies this function within its schema. This is a user - * specified, or DBMS generated, name that may be different then the FUNCTION_NAME for example with overload - * functions - */ - @Override - public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) - throws SQLException { - try (PreparedStatement statement = - conn.prepareStatement("SELECT " - + "null as FUNCTION_CAT, " - + "function_name as FUNCTION_NAME, " - + "schema_name as FUNCTION_SCHEM, " - + "description as REMARKS," - + "CASE function_type " - + "WHEN 'table' THEN " + functionReturnsTable + " " - + "WHEN 'table_macro' THEN " + functionReturnsTable + " " - + "ELSE " + functionNoTable + " " - + "END as FUNCTION_TYPE " - + "FROM duckdb_functions() " - + "WHERE function_name like ? and " - + "schema_name like ?")) { - statement.setString(1, functionNamePattern); - statement.setString(2, schemaPattern); - - CachedRowSet cachedRowSet = RowSetProvider.newFactory().createCachedRowSet(); - cachedRowSet.populate(statement.executeQuery()); - return cachedRowSet; - } - } - - @Override - public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, - String columnNamePattern) throws SQLException { - Statement statement = conn.createStatement(); - statement.closeOnCompletion(); - return statement.executeQuery("SELECT NULL WHERE FALSE"); - } - - @Override - public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, - String columnNamePattern) throws SQLException { - throw new SQLFeatureNotSupportedException("getPseudoColumns"); - } - - @Override - public boolean generatedKeyAlwaysReturned() throws SQLException { - throw new SQLFeatureNotSupportedException("generatedKeyAlwaysReturned"); - } - - static String dataMap; - static { - dataMap = makeCase( - Arrays.stream(DuckDBColumnType.values()) - .collect(Collectors.toMap(ty -> ty.name().replace("_", " "), DuckDBResultSetMetaData::type_to_int))); - } - - private static String makeCase(Map values) { - return values.entrySet() - .stream() - .map(ty -> { - T value = ty.getValue(); - return String.format("WHEN '%s' THEN %s ", ty.getKey(), - value instanceof String ? String.format("'%s'", value) : value); - }) - .collect(Collectors.joining()); - } - - /** - * @param srcColumnName - * @param destColumnName - * @return - * @see DuckDBResultSetMetaData#type_to_int(DuckDBColumnType) - */ - private static String makeDataMap(String srcColumnName, String destColumnName) { - return String.format("CASE %s %s ELSE %d END as %s", srcColumnName, dataMap, Types.JAVA_OBJECT, destColumnName); - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBDate.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBDate.java deleted file mode 100644 index c1d111ed6b1..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBDate.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.duckdb; - -import java.sql.Date; -import java.time.LocalDate; -import java.time.temporal.ChronoUnit; - -public class DuckDBDate { - private final long daysSinceEpoch; - - public DuckDBDate(Date date) { - this.daysSinceEpoch = LocalDate.ofEpochDay(0).until(date.toLocalDate(), ChronoUnit.DAYS); - } - - public long getDaysSinceEpoch() { - return daysSinceEpoch; - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBDriver.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBDriver.java deleted file mode 100644 index 5c90db5b515..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBDriver.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.duckdb; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.DriverPropertyInfo; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.util.Properties; -import java.util.logging.Logger; - -public class DuckDBDriver implements java.sql.Driver { - - public static final String DUCKDB_READONLY_PROPERTY = "duckdb.read_only"; - public static final String DUCKDB_USER_AGENT_PROPERTY = "custom_user_agent"; - public static final String JDBC_STREAM_RESULTS = "jdbc_stream_results"; - - static { - try { - DriverManager.registerDriver(new DuckDBDriver()); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - public Connection connect(String url, Properties info) throws SQLException { - if (!acceptsURL(url)) { - return null; - } - boolean read_only = false; - if (info == null) { - info = new Properties(); - } else { // make a copy because we're removing the read only property below - info = (Properties) info.clone(); - } - String prop_val = (String) info.remove(DUCKDB_READONLY_PROPERTY); - if (prop_val != null) { - String prop_clean = prop_val.trim().toLowerCase(); - read_only = prop_clean.equals("1") || prop_clean.equals("true") || prop_clean.equals("yes"); - } - info.put("duckdb_api", "jdbc"); - return DuckDBConnection.newConnection(url, read_only, info); - } - - public boolean acceptsURL(String url) throws SQLException { - return url.startsWith("jdbc:duckdb:"); - } - - public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { - DriverPropertyInfo[] ret = {}; - return ret; // no properties - } - - public int getMajorVersion() { - return 1; - } - - public int getMinorVersion() { - return 0; - } - - public boolean jdbcCompliant() { - return true; // of course! - } - - public Logger getParentLogger() throws SQLFeatureNotSupportedException { - throw new SQLFeatureNotSupportedException("no logger"); - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBNative.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBNative.java deleted file mode 100644 index 1b02145b2f6..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBNative.java +++ /dev/null @@ -1,171 +0,0 @@ -package org.duckdb; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.ByteBuffer; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.sql.SQLException; -import java.util.Properties; -import java.math.BigDecimal; - -class DuckDBNative { - static { - try { - String os_name = ""; - String os_arch; - String os_name_detect = System.getProperty("os.name").toLowerCase().trim(); - String os_arch_detect = System.getProperty("os.arch").toLowerCase().trim(); - switch (os_arch_detect) { - case "x86_64": - case "amd64": - os_arch = "amd64"; - break; - case "aarch64": - case "arm64": - os_arch = "arm64"; - break; - case "i386": - os_arch = "i386"; - break; - default: - throw new IllegalStateException("Unsupported system architecture"); - } - if (os_name_detect.startsWith("windows")) { - os_name = "windows"; - } else if (os_name_detect.startsWith("mac")) { - os_name = "osx"; - os_arch = "universal"; - } else if (os_name_detect.startsWith("linux")) { - os_name = "linux"; - } - String lib_res_name = "/libduckdb_java.so" - + "_" + os_name + "_" + os_arch; - - Path lib_file = Files.createTempFile("libduckdb_java", ".so"); - URL lib_res = DuckDBNative.class.getResource(lib_res_name); - if (lib_res == null) { - System.load( - Paths.get("../../build/debug/tools/jdbc", lib_res_name).normalize().toAbsolutePath().toString()); - } else { - try (final InputStream lib_res_input_stream = lib_res.openStream()) { - Files.copy(lib_res_input_stream, lib_file, StandardCopyOption.REPLACE_EXISTING); - } - new File(lib_file.toString()).deleteOnExit(); - System.load(lib_file.toAbsolutePath().toString()); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - // We use zero-length ByteBuffer-s as a hacky but cheap way to pass C++ pointers - // back and forth - - /* - * NB: if you change anything below, run `javah` on this class to re-generate - * the C header. CMake does this as well - */ - - // results ConnectionHolder reference object - protected static native ByteBuffer duckdb_jdbc_startup(byte[] path, boolean read_only, Properties props) - throws SQLException; - - // returns conn_ref connection reference object - protected static native ByteBuffer duckdb_jdbc_connect(ByteBuffer db_ref) throws SQLException; - - protected static native void duckdb_jdbc_set_auto_commit(ByteBuffer conn_ref, boolean auto_commit) - throws SQLException; - - protected static native boolean duckdb_jdbc_get_auto_commit(ByteBuffer conn_ref) throws SQLException; - - protected static native void duckdb_jdbc_disconnect(ByteBuffer conn_ref); - - protected static native void duckdb_jdbc_set_schema(ByteBuffer conn_ref, String schema); - - protected static native void duckdb_jdbc_set_catalog(ByteBuffer conn_ref, String catalog); - - protected static native String duckdb_jdbc_get_schema(ByteBuffer conn_ref); - - protected static native String duckdb_jdbc_get_catalog(ByteBuffer conn_ref); - - // returns stmt_ref result reference object - protected static native ByteBuffer duckdb_jdbc_prepare(ByteBuffer conn_ref, byte[] query) throws SQLException; - - protected static native void duckdb_jdbc_release(ByteBuffer stmt_ref); - - protected static native DuckDBResultSetMetaData duckdb_jdbc_query_result_meta(ByteBuffer result_ref) - throws SQLException; - - protected static native DuckDBResultSetMetaData duckdb_jdbc_prepared_statement_meta(ByteBuffer stmt_ref) - throws SQLException; - - // returns res_ref result reference object - protected static native ByteBuffer duckdb_jdbc_execute(ByteBuffer stmt_ref, Object[] params) throws SQLException; - - protected static native void duckdb_jdbc_free_result(ByteBuffer res_ref); - - protected static native DuckDBVector[] duckdb_jdbc_fetch(ByteBuffer res_ref, ByteBuffer conn_ref) - throws SQLException; - - protected static native int duckdb_jdbc_fetch_size(); - - protected static native long duckdb_jdbc_arrow_stream(ByteBuffer res_ref, long batch_size); - - protected static native void duckdb_jdbc_arrow_register(ByteBuffer conn_ref, long arrow_array_stream_pointer, - byte[] name); - - protected static native ByteBuffer duckdb_jdbc_create_appender(ByteBuffer conn_ref, byte[] schema_name, - byte[] table_name) throws SQLException; - - protected static native void duckdb_jdbc_appender_begin_row(ByteBuffer appender_ref) throws SQLException; - - protected static native void duckdb_jdbc_appender_end_row(ByteBuffer appender_ref) throws SQLException; - - protected static native void duckdb_jdbc_appender_flush(ByteBuffer appender_ref) throws SQLException; - - protected static native void duckdb_jdbc_interrupt(ByteBuffer conn_ref); - - protected static native void duckdb_jdbc_appender_close(ByteBuffer appender_ref) throws SQLException; - - protected static native void duckdb_jdbc_appender_append_boolean(ByteBuffer appender_ref, boolean value) - throws SQLException; - - protected static native void duckdb_jdbc_appender_append_byte(ByteBuffer appender_ref, byte value) - throws SQLException; - - protected static native void duckdb_jdbc_appender_append_short(ByteBuffer appender_ref, short value) - throws SQLException; - - protected static native void duckdb_jdbc_appender_append_int(ByteBuffer appender_ref, int value) - throws SQLException; - - protected static native void duckdb_jdbc_appender_append_long(ByteBuffer appender_ref, long value) - throws SQLException; - - protected static native void duckdb_jdbc_appender_append_float(ByteBuffer appender_ref, float value) - throws SQLException; - - protected static native void duckdb_jdbc_appender_append_double(ByteBuffer appender_ref, double value) - throws SQLException; - - protected static native void duckdb_jdbc_appender_append_string(ByteBuffer appender_ref, byte[] value) - throws SQLException; - - protected static native void duckdb_jdbc_appender_append_timestamp(ByteBuffer appender_ref, long value) - throws SQLException; - - protected static native void duckdb_jdbc_appender_append_decimal(ByteBuffer appender_ref, BigDecimal value) - throws SQLException; - - protected static native void duckdb_jdbc_appender_append_null(ByteBuffer appender_ref) throws SQLException; - - protected static native void duckdb_jdbc_create_extension_type(ByteBuffer conn_ref) throws SQLException; - - public static void duckdb_jdbc_create_extension_type(DuckDBConnection conn) throws SQLException { - duckdb_jdbc_create_extension_type(conn.conn_ref); - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBParameterMetaData.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBParameterMetaData.java deleted file mode 100644 index 6d55226f51b..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBParameterMetaData.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.duckdb; - -import java.sql.ParameterMetaData; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; - -public class DuckDBParameterMetaData implements ParameterMetaData { - private DuckDBResultSetMetaData meta; - - public DuckDBParameterMetaData(DuckDBResultSetMetaData meta) { - this.meta = meta; - } - - @Override - public T unwrap(Class iface) throws SQLException { - return JdbcUtils.unwrap(this, iface); - } - - @Override - public boolean isWrapperFor(Class iface) { - return iface.isInstance(this); - } - - @Override - public int getParameterCount() throws SQLException { - return meta.param_count; - } - - @Override - public int isNullable(int param) throws SQLException { - return ParameterMetaData.parameterNullableUnknown; - } - - @Override - public boolean isSigned(int param) throws SQLException { - return true; - } - - @Override - public int getPrecision(int param) throws SQLException { - throw new SQLFeatureNotSupportedException("getPrecision"); - } - - @Override - public int getScale(int param) throws SQLException { - throw new SQLFeatureNotSupportedException("getScale"); - } - - @Override - public int getParameterType(int param) throws SQLException { - // TODO Auto-generated method stub - return 0; - } - - @Override - public String getParameterTypeName(int param) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getParameterClassName(int param) throws SQLException { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getParameterMode(int param) throws SQLException { - return ParameterMetaData.parameterModeIn; - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBPreparedStatement.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBPreparedStatement.java deleted file mode 100644 index d00bb2d26bd..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBPreparedStatement.java +++ /dev/null @@ -1,943 +0,0 @@ -package org.duckdb; - -import java.io.InputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Connection; -import java.sql.Date; -import java.sql.NClob; -import java.sql.ParameterMetaData; -import java.sql.PreparedStatement; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.List; -import java.time.LocalDateTime; -import java.time.OffsetDateTime; - -import java.util.logging.Logger; -import java.util.logging.Level; - -public class DuckDBPreparedStatement implements PreparedStatement { - private static Logger logger = Logger.getLogger(DuckDBPreparedStatement.class.getName()); - - private DuckDBConnection conn; - - private ByteBuffer stmt_ref = null; - private DuckDBResultSet select_result = null; - private int update_result = 0; - private boolean returnsChangedRows = false; - private boolean returnsNothing = false; - private boolean returnsResultSet = false; - boolean closeOnCompletion = false; - private Object[] params = new Object[0]; - private DuckDBResultSetMetaData meta = null; - private final List batchedParams = new ArrayList<>(); - private final List batchedStatements = new ArrayList<>(); - private Boolean isBatch = false; - private Boolean isPreparedStatement = false; - - public DuckDBPreparedStatement(DuckDBConnection conn) throws SQLException { - if (conn == null) { - throw new SQLException("connection parameter cannot be null"); - } - this.conn = conn; - } - - public DuckDBPreparedStatement(DuckDBConnection conn, String sql) throws SQLException { - if (conn == null) { - throw new SQLException("connection parameter cannot be null"); - } - if (sql == null) { - throw new SQLException("sql query parameter cannot be null"); - } - this.conn = conn; - this.isPreparedStatement = true; - prepare(sql); - } - - private void startTransaction() throws SQLException { - if (this.conn.autoCommit || this.conn.transactionRunning) { - return; - } - - this.conn.transactionRunning = true; - - // Start transaction via Statement - try (Statement s = conn.createStatement()) { - s.execute("BEGIN TRANSACTION;"); - } - } - - private void prepare(String sql) throws SQLException { - if (isClosed()) { - throw new SQLException("Statement was closed"); - } - if (sql == null) { - throw new SQLException("sql query parameter cannot be null"); - } - - // In case the statement is reused, release old one first - if (stmt_ref != null) { - DuckDBNative.duckdb_jdbc_release(stmt_ref); - stmt_ref = null; - } - - meta = null; - params = null; - - if (select_result != null) { - select_result.close(); - } - select_result = null; - update_result = 0; - - try { - stmt_ref = DuckDBNative.duckdb_jdbc_prepare(conn.conn_ref, sql.getBytes(StandardCharsets.UTF_8)); - meta = DuckDBNative.duckdb_jdbc_prepared_statement_meta(stmt_ref); - params = new Object[0]; - } catch (SQLException e) { - // Delete stmt_ref as it might already be allocated - close(); - throw new SQLException(e); - } - } - - @Override - public boolean execute() throws SQLException { - if (isClosed()) { - throw new SQLException("Statement was closed"); - } - if (stmt_ref == null) { - throw new SQLException("Prepare something first"); - } - - ByteBuffer result_ref = null; - if (select_result != null) { - select_result.close(); - } - select_result = null; - - try { - startTransaction(); - result_ref = DuckDBNative.duckdb_jdbc_execute(stmt_ref, params); - DuckDBResultSetMetaData result_meta = DuckDBNative.duckdb_jdbc_query_result_meta(result_ref); - select_result = new DuckDBResultSet(this, result_meta, result_ref, conn.conn_ref); - returnsResultSet = result_meta.return_type.equals(StatementReturnType.QUERY_RESULT); - returnsChangedRows = result_meta.return_type.equals(StatementReturnType.CHANGED_ROWS); - returnsNothing = result_meta.return_type.equals(StatementReturnType.NOTHING); - } catch (SQLException e) { - // Delete stmt_ref as it cannot be used anymore and - // result_ref as it might be allocated - if (select_result != null) { - select_result.close(); - } else if (result_ref != null) { - DuckDBNative.duckdb_jdbc_free_result(result_ref); - result_ref = null; - } - close(); - throw e; - } - - if (returnsChangedRows) { - if (select_result.next()) { - update_result = select_result.getInt(1); - } - select_result.close(); - } - - return returnsResultSet; - } - - @Override - public ResultSet executeQuery() throws SQLException { - requireNonBatch(); - execute(); - if (!returnsResultSet) { - throw new SQLException("executeQuery() can only be used with queries that return a ResultSet"); - } - return select_result; - } - - @Override - public int executeUpdate() throws SQLException { - requireNonBatch(); - execute(); - if (!(returnsChangedRows || returnsNothing)) { - throw new SQLException( - "executeUpdate() can only be used with queries that return nothing (eg, a DDL statement), or update rows"); - } - return getUpdateCountInternal(); - } - - @Override - public boolean execute(String sql) throws SQLException { - requireNonBatch(); - prepare(sql); - return execute(); - } - - @Override - public ResultSet executeQuery(String sql) throws SQLException { - prepare(sql); - return executeQuery(); - } - - @Override - public int executeUpdate(String sql) throws SQLException { - prepare(sql); - return executeUpdate(); - } - - @Override - public ResultSetMetaData getMetaData() throws SQLException { - if (isClosed()) { - throw new SQLException("Statement was closed"); - } - if (meta == null) { - throw new SQLException("Prepare something first"); - } - return meta; - } - - @Override - public ParameterMetaData getParameterMetaData() throws SQLException { - if (isClosed()) { - throw new SQLException("Statement was closed"); - } - if (stmt_ref == null) { - throw new SQLException("Prepare something first"); - } - return new DuckDBParameterMetaData(meta); - } - - @Override - public void setObject(int parameterIndex, Object x) throws SQLException { - if (parameterIndex < 1 || parameterIndex > getParameterMetaData().getParameterCount()) { - throw new SQLException("Parameter index out of bounds"); - } - if (params.length == 0) { - params = new Object[getParameterMetaData().getParameterCount()]; - } - // Change sql.Timestamp to DuckDBTimestamp - if (x instanceof Timestamp) { - x = new DuckDBTimestamp((Timestamp) x); - } else if (x instanceof LocalDateTime) { - x = new DuckDBTimestamp((LocalDateTime) x); - } else if (x instanceof OffsetDateTime) { - x = new DuckDBTimestampTZ((OffsetDateTime) x); - } else if (x instanceof Date) { - x = new DuckDBDate((Date) x); - } - params[parameterIndex - 1] = x; - } - - @Override - public void setNull(int parameterIndex, int sqlType) throws SQLException { - setObject(parameterIndex, null); - } - - @Override - public void setBoolean(int parameterIndex, boolean x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setByte(int parameterIndex, byte x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setShort(int parameterIndex, short x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setInt(int parameterIndex, int x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setLong(int parameterIndex, long x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setFloat(int parameterIndex, float x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setDouble(int parameterIndex, double x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setString(int parameterIndex, String x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void clearParameters() throws SQLException { - params = new Object[0]; - } - - @Override - public void close() throws SQLException { - if (select_result != null) { - select_result.close(); - select_result = null; - } - if (stmt_ref != null) { - DuckDBNative.duckdb_jdbc_release(stmt_ref); - stmt_ref = null; - } - conn = null; // we use this as a check for closed-ness - } - - protected void finalize() throws Throwable { - close(); - } - - @Override - public int getMaxFieldSize() throws SQLException { - return 0; - } - - @Override - public void setMaxFieldSize(int max) throws SQLException { - logger.log(Level.FINE, "setMaxFieldSize not supported"); - } - - @Override - public int getMaxRows() throws SQLException { - return 0; - } - - @Override - public void setMaxRows(int max) throws SQLException { - } - - @Override - public void setEscapeProcessing(boolean enable) throws SQLException { - } - - @Override - public int getQueryTimeout() throws SQLException { - return 0; - } - - @Override - public void setQueryTimeout(int seconds) throws SQLException { - logger.log(Level.FINE, "setQueryTimeout not supported"); - } - - /** - * This function calls the underlying C++ interrupt function which aborts the query running on that connection. - * It is not safe to call this function when the connection is already closed. - */ - @Override - public synchronized void cancel() throws SQLException { - if (conn.conn_ref != null) { - DuckDBNative.duckdb_jdbc_interrupt(conn.conn_ref); - } - } - - @Override - public SQLWarning getWarnings() throws SQLException { - return null; - } - - @Override - public void clearWarnings() throws SQLException { - } - - @Override - public void setCursorName(String name) throws SQLException { - throw new SQLFeatureNotSupportedException("setCursorName"); - } - - /** - * The returned `ResultSet` must be closed by the user to avoid a memory leak - */ - @Override - public ResultSet getResultSet() throws SQLException { - if (isClosed()) { - throw new SQLException("Statement was closed"); - } - if (stmt_ref == null) { - throw new SQLException("Prepare something first"); - } - - if (!returnsResultSet) { - return null; - } - - // getResultSet can only be called once per result - ResultSet to_return = select_result; - this.select_result = null; - return to_return; - } - - private Integer getUpdateCountInternal() throws SQLException { - if (isClosed()) { - throw new SQLException("Statement was closed"); - } - if (stmt_ref == null) { - throw new SQLException("Prepare something first"); - } - - if (returnsResultSet || returnsNothing || select_result.isFinished()) { - return -1; - } - return update_result; - } - - @Override - public int getUpdateCount() throws SQLException { - // getUpdateCount can only be called once per result - int to_return = getUpdateCountInternal(); - update_result = -1; - return to_return; - } - - @Override - public boolean getMoreResults() throws SQLException { - return false; - } - - @Override - public void setFetchDirection(int direction) throws SQLException { - if (direction == ResultSet.FETCH_FORWARD) { - return; - } - throw new SQLFeatureNotSupportedException("setFetchDirection"); - } - - @Override - public int getFetchDirection() throws SQLException { - return ResultSet.FETCH_FORWARD; - } - - @Override - public void setFetchSize(int rows) throws SQLException { - } - - @Override - public int getFetchSize() throws SQLException { - return DuckDBNative.duckdb_jdbc_fetch_size(); - } - - @Override - public int getResultSetConcurrency() throws SQLException { - return ResultSet.CONCUR_READ_ONLY; - } - - @Override - public int getResultSetType() throws SQLException { - return ResultSet.TYPE_FORWARD_ONLY; - } - - @Override - public void addBatch(String sql) throws SQLException { - requireNonPreparedStatement(); - this.batchedStatements.add(sql); - this.isBatch = true; - } - - @Override - public void clearBatch() throws SQLException { - this.batchedParams.clear(); - this.batchedStatements.clear(); - this.isBatch = false; - } - - @Override - public int[] executeBatch() throws SQLException { - try { - if (this.isPreparedStatement) { - return executeBatchedPreparedStatement(); - } else { - return executeBatchedStatements(); - } - } finally { - clearBatch(); - } - } - - private int[] executeBatchedPreparedStatement() throws SQLException { - int[] updateCounts = new int[this.batchedParams.size()]; - for (int i = 0; i < this.batchedParams.size(); i++) { - params = this.batchedParams.get(i); - execute(); - updateCounts[i] = getUpdateCount(); - } - return updateCounts; - } - - private int[] executeBatchedStatements() throws SQLException { - int[] updateCounts = new int[this.batchedStatements.size()]; - for (int i = 0; i < this.batchedStatements.size(); i++) { - prepare(this.batchedStatements.get(i)); - execute(); - updateCounts[i] = getUpdateCount(); - } - return updateCounts; - } - - @Override - public Connection getConnection() throws SQLException { - if (isClosed()) { - throw new SQLException("Statement was closed"); - } - return conn; - } - - @Override - public boolean getMoreResults(int current) throws SQLException { - throw new SQLFeatureNotSupportedException("getMoreResults"); - } - - @Override - public ResultSet getGeneratedKeys() throws SQLException { - throw new SQLFeatureNotSupportedException("getGeneratedKeys"); - } - - @Override - public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - throw new SQLFeatureNotSupportedException("executeUpdate"); - } - - @Override - public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - throw new SQLFeatureNotSupportedException("executeUpdate"); - } - - @Override - public int executeUpdate(String sql, String[] columnNames) throws SQLException { - throw new SQLFeatureNotSupportedException("executeUpdate"); - } - - @Override - public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - throw new SQLFeatureNotSupportedException("execute"); - } - - @Override - public boolean execute(String sql, int[] columnIndexes) throws SQLException { - throw new SQLFeatureNotSupportedException("execute"); - } - - @Override - public boolean execute(String sql, String[] columnNames) throws SQLException { - throw new SQLFeatureNotSupportedException("execute"); - } - - @Override - public int getResultSetHoldability() throws SQLException { - throw new SQLFeatureNotSupportedException("getResultSetHoldability"); - } - - @Override - public boolean isClosed() throws SQLException { - return conn == null; - } - - @Override - public void setPoolable(boolean poolable) throws SQLException { - throw new SQLFeatureNotSupportedException("setPoolable"); - } - - @Override - public boolean isPoolable() throws SQLException { - throw new SQLFeatureNotSupportedException("isPoolable"); - } - - @Override - public void closeOnCompletion() throws SQLException { - if (isClosed()) - throw new SQLException("Statement is closed"); - closeOnCompletion = true; - } - - @Override - public boolean isCloseOnCompletion() throws SQLException { - if (isClosed()) - throw new SQLException("Statement is closed"); - return closeOnCompletion; - } - - @Override - public T unwrap(Class iface) throws SQLException { - return JdbcUtils.unwrap(this, iface); - } - - @Override - public boolean isWrapperFor(Class iface) { - return iface.isInstance(this); - } - - @Override - public void setBytes(int parameterIndex, byte[] x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setDate(int parameterIndex, Date x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setTime(int parameterIndex, Time x) throws SQLException { - throw new SQLFeatureNotSupportedException("setTime"); - } - - @Override - public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("setAsciiStream"); - } - - @Override - public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("setUnicodeStream"); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("setBinaryStream"); - } - - @Override - public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { - if (x == null) { - setNull(parameterIndex, targetSqlType); - return; - } - switch (targetSqlType) { - case Types.BOOLEAN: - case Types.BIT: - if (x instanceof Boolean) { - setObject(parameterIndex, x); - } else if (x instanceof Number) { - setObject(parameterIndex, ((Number) x).byteValue() == 1); - } else if (x instanceof String) { - setObject(parameterIndex, Boolean.parseBoolean((String) x)); - } else { - throw new SQLException("Can't convert value to boolean " + x.getClass().toString()); - } - break; - case Types.TINYINT: - if (x instanceof Byte) { - setObject(parameterIndex, x); - } else if (x instanceof Number) { - setObject(parameterIndex, ((Number) x).byteValue()); - } else if (x instanceof String) { - setObject(parameterIndex, Byte.parseByte((String) x)); - } else if (x instanceof Boolean) { - setObject(parameterIndex, (byte) (((Boolean) x) ? 1 : 0)); - } else { - throw new SQLException("Can't convert value to byte " + x.getClass().toString()); - } - break; - case Types.SMALLINT: - if (x instanceof Short) { - setObject(parameterIndex, x); - } else if (x instanceof Number) { - setObject(parameterIndex, ((Number) x).shortValue()); - } else if (x instanceof String) { - setObject(parameterIndex, Short.parseShort((String) x)); - } else if (x instanceof Boolean) { - setObject(parameterIndex, (short) (((Boolean) x) ? 1 : 0)); - } else { - throw new SQLException("Can't convert value to short " + x.getClass().toString()); - } - break; - case Types.INTEGER: - if (x instanceof Integer) { - setObject(parameterIndex, x); - } else if (x instanceof Number) { - setObject(parameterIndex, ((Number) x).intValue()); - } else if (x instanceof String) { - setObject(parameterIndex, Integer.parseInt((String) x)); - } else if (x instanceof Boolean) { - setObject(parameterIndex, (int) (((Boolean) x) ? 1 : 0)); - } else { - throw new SQLException("Can't convert value to int " + x.getClass().toString()); - } - break; - case Types.BIGINT: - if (x instanceof Long) { - setObject(parameterIndex, x); - } else if (x instanceof Number) { - setObject(parameterIndex, ((Number) x).longValue()); - } else if (x instanceof String) { - setObject(parameterIndex, Long.parseLong((String) x)); - } else if (x instanceof Boolean) { - setObject(parameterIndex, (long) (((Boolean) x) ? 1 : 0)); - } else { - throw new SQLException("Can't convert value to long " + x.getClass().toString()); - } - break; - case Types.REAL: - case Types.FLOAT: - if (x instanceof Float) { - setObject(parameterIndex, x); - } else if (x instanceof Number) { - setObject(parameterIndex, ((Number) x).floatValue()); - } else if (x instanceof String) { - setObject(parameterIndex, Float.parseFloat((String) x)); - } else if (x instanceof Boolean) { - setObject(parameterIndex, (float) (((Boolean) x) ? 1 : 0)); - } else { - throw new SQLException("Can't convert value to float " + x.getClass().toString()); - } - break; - case Types.DECIMAL: - if (x instanceof BigDecimal) { - setObject(parameterIndex, x); - } else if (x instanceof Double) { - setObject(parameterIndex, new BigDecimal((Double) x)); - } else if (x instanceof String) { - setObject(parameterIndex, new BigDecimal((String) x)); - } else { - throw new SQLException("Can't convert value to double " + x.getClass().toString()); - } - break; - case Types.NUMERIC: - case Types.DOUBLE: - if (x instanceof Double) { - setObject(parameterIndex, x); - } else if (x instanceof Number) { - setObject(parameterIndex, ((Number) x).doubleValue()); - } else if (x instanceof String) { - setObject(parameterIndex, Double.parseDouble((String) x)); - } else if (x instanceof Boolean) { - setObject(parameterIndex, (double) (((Boolean) x) ? 1 : 0)); - } else { - throw new SQLException("Can't convert value to double " + x.getClass().toString()); - } - break; - case Types.CHAR: - case Types.LONGVARCHAR: - case Types.VARCHAR: - if (x instanceof String) { - setObject(parameterIndex, (String) x); - } else { - setObject(parameterIndex, x.toString()); - } - break; - case Types.TIMESTAMP: - case Types.TIMESTAMP_WITH_TIMEZONE: - if (x instanceof Timestamp) { - setObject(parameterIndex, x); - } else if (x instanceof LocalDateTime) { - setObject(parameterIndex, x); - } else if (x instanceof OffsetDateTime) { - setObject(parameterIndex, x); - } else { - throw new SQLException("Can't convert value to timestamp " + x.getClass().toString()); - } - break; - default: - throw new SQLException("Unknown target type " + targetSqlType); - } - } - - @Override - public void addBatch() throws SQLException { - batchedParams.add(params); - clearParameters(); - this.isBatch = true; - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("setCharacterStream"); - } - - @Override - public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { - setObject(parameterIndex, x); - } - - @Override - public void setRef(int parameterIndex, Ref x) throws SQLException { - throw new SQLFeatureNotSupportedException("setRef"); - } - - @Override - public void setBlob(int parameterIndex, Blob x) throws SQLException { - throw new SQLFeatureNotSupportedException("setBlob"); - } - - @Override - public void setClob(int parameterIndex, Clob x) throws SQLException { - throw new SQLFeatureNotSupportedException("setClob"); - } - - @Override - public void setArray(int parameterIndex, Array x) throws SQLException { - throw new SQLFeatureNotSupportedException("setArray"); - } - - @Override - public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { - throw new SQLFeatureNotSupportedException("setDate"); - } - - @Override - public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { - throw new SQLFeatureNotSupportedException("setTime"); - } - - @Override - public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { - throw new SQLFeatureNotSupportedException("setTimestamp"); - } - - @Override - public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { - throw new SQLFeatureNotSupportedException("setNull"); - } - - @Override - public void setURL(int parameterIndex, URL x) throws SQLException { - throw new SQLFeatureNotSupportedException("setURL"); - } - - @Override - public void setRowId(int parameterIndex, RowId x) throws SQLException { - throw new SQLFeatureNotSupportedException("setRowId"); - } - - @Override - public void setNString(int parameterIndex, String value) throws SQLException { - throw new SQLFeatureNotSupportedException("setNString"); - } - - @Override - public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("setNCharacterString"); - } - - @Override - public void setNClob(int parameterIndex, NClob value) throws SQLException { - throw new SQLFeatureNotSupportedException("setNClob"); - } - - @Override - public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("setClob"); - } - - @Override - public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("setBlob"); - } - - @Override - public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("setNClob"); - } - - @Override - public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { - throw new SQLFeatureNotSupportedException("setSQLXML"); - } - - @Override - public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { - setObject(parameterIndex, x, targetSqlType); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("setAsciiStream"); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("setBinaryStream"); - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("setCharacterStream"); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("setAsciiStream"); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { - try { - setBytes(parameterIndex, JdbcUtils.readAllBytes(x)); - } catch (IOException ioe) { - throw new SQLException("Failed to read from InputStream", ioe); - } - } - - @Override - public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("setCharacterStream"); - } - - @Override - public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { - throw new SQLFeatureNotSupportedException("setNCharacterStream"); - } - - @Override - public void setClob(int parameterIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("setClob"); - } - - @Override - public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException("setBlob"); - } - - @Override - public void setNClob(int parameterIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("setNClob"); - } - - private void requireNonBatch() throws SQLException { - if (this.isBatch) { - throw new SQLException("Batched queries must be executed with executeBatch."); - } - } - - private void requireNonPreparedStatement() throws SQLException { - if (this.isPreparedStatement) { - throw new SQLException("Cannot add batched SQL statement to PreparedStatement"); - } - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBResultSet.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBResultSet.java deleted file mode 100644 index aac82d6073e..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBResultSet.java +++ /dev/null @@ -1,1301 +0,0 @@ -package org.duckdb; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.lang.reflect.InvocationTargetException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.URL; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Date; -import java.sql.NClob; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Statement; -import java.sql.Struct; -import java.sql.Time; -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; - -public class DuckDBResultSet implements ResultSet { - private final DuckDBPreparedStatement stmt; - private final DuckDBResultSetMetaData meta; - - /** - * {@code null} if this result set is closed. - */ - private ByteBuffer result_ref; - private DuckDBVector[] current_chunk = {}; - private int chunk_idx = 0; - private boolean finished = false; - private boolean was_null; - private final ByteBuffer conn_ref; - - public DuckDBResultSet(DuckDBPreparedStatement stmt, DuckDBResultSetMetaData meta, ByteBuffer result_ref, - ByteBuffer conn_ref) throws SQLException { - this.stmt = Objects.requireNonNull(stmt); - this.result_ref = Objects.requireNonNull(result_ref); - this.meta = Objects.requireNonNull(meta); - this.conn_ref = Objects.requireNonNull(conn_ref); - } - - public Statement getStatement() throws SQLException { - if (isClosed()) { - throw new SQLException("ResultSet was closed"); - } - return stmt; - } - - public ResultSetMetaData getMetaData() throws SQLException { - if (isClosed()) { - throw new SQLException("ResultSet was closed"); - } - return meta; - } - - public synchronized boolean next() throws SQLException { - if (isClosed()) { - throw new SQLException("ResultSet was closed"); - } - if (finished) { - return false; - } - chunk_idx++; - if (current_chunk.length == 0 || chunk_idx > current_chunk[0].length) { - current_chunk = DuckDBNative.duckdb_jdbc_fetch(result_ref, conn_ref); - chunk_idx = 1; - } - if (current_chunk.length == 0) { - finished = true; - return false; - } - return true; - } - - public synchronized void close() throws SQLException { - if (result_ref != null) { - DuckDBNative.duckdb_jdbc_free_result(result_ref); - // Nullness is used to determine whether we're closed - result_ref = null; - - // isCloseOnCompletion() throws if already closed, and we can't check for isClosed() because it could change - // between when we check and call isCloseOnCompletion, so access the field directly. - if (stmt.closeOnCompletion) { - stmt.close(); - } - } - } - - protected void finalize() throws Throwable { - close(); - } - - public synchronized boolean isClosed() throws SQLException { - return result_ref == null; - } - - private void check(int columnIndex) throws SQLException { - if (isClosed()) { - throw new SQLException("ResultSet was closed"); - } - if (columnIndex < 1 || columnIndex > meta.column_count) { - throw new SQLException("Column index out of bounds"); - } - } - - /** - * Export the result set as an ArrowReader - * - * @param arrow_buffer_allocator an instance of {@link org.apache.arrow.memory.BufferAllocator} - * @param arrow_batch_size batch size of arrow vectors to return - * @return an instance of {@link org.apache.arrow.vector.ipc.ArrowReader} - */ - public synchronized Object arrowExportStream(Object arrow_buffer_allocator, long arrow_batch_size) - throws SQLException { - if (isClosed()) { - throw new SQLException("Result set is closed"); - } - - try { - Class buffer_allocator_class = Class.forName("org.apache.arrow.memory.BufferAllocator"); - if (!buffer_allocator_class.isInstance(arrow_buffer_allocator)) { - throw new RuntimeException("Need to pass an Arrow BufferAllocator"); - } - Long stream_pointer = DuckDBNative.duckdb_jdbc_arrow_stream(result_ref, arrow_batch_size); - Class arrow_array_stream_class = Class.forName("org.apache.arrow.c.ArrowArrayStream"); - Object arrow_array_stream = - arrow_array_stream_class.getMethod("wrap", long.class).invoke(null, stream_pointer); - - Class c_data_class = Class.forName("org.apache.arrow.c.Data"); - - return c_data_class.getMethod("importArrayStream", buffer_allocator_class, arrow_array_stream_class) - .invoke(null, arrow_buffer_allocator, arrow_array_stream); - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | SecurityException | - ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - public Object getObject(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getObject(chunk_idx - 1); - } - - public Struct getStruct(int columnIndex) throws SQLException { - return check_and_null(columnIndex) ? null : current_chunk[columnIndex - 1].getStruct(chunk_idx - 1); - } - - public OffsetTime getOffsetTime(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getOffsetTime(chunk_idx - 1); - } - - public boolean wasNull() throws SQLException { - if (isClosed()) { - throw new SQLException("ResultSet was closed"); - } - return was_null; - } - - private boolean check_and_null(int columnIndex) throws SQLException { - check(columnIndex); - try { - was_null = current_chunk[columnIndex - 1].check_and_null(chunk_idx - 1); - } catch (ArrayIndexOutOfBoundsException e) { - throw new SQLException("No row in context", e); - } - return was_null; - } - - public JsonNode getJsonObject(int columnIndex) throws SQLException { - String result = getLazyString(columnIndex); - return result == null ? null : new JsonNode(result); - } - - public String getLazyString(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getLazyString(chunk_idx - 1); - } - - public String getString(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - - Object res = getObject(columnIndex); - if (res == null) { - return null; - } else { - return res.toString(); - } - } - - public boolean getBoolean(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return false; - } - return current_chunk[columnIndex - 1].getBoolean(chunk_idx - 1); - } - - public byte getByte(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return 0; - } - return current_chunk[columnIndex - 1].getByte(chunk_idx - 1); - } - - public short getShort(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return 0; - } - return current_chunk[columnIndex - 1].getShort(chunk_idx - 1); - } - - public int getInt(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return 0; - } - return current_chunk[columnIndex - 1].getInt(chunk_idx - 1); - } - - private short getUint8(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return 0; - } - return current_chunk[columnIndex - 1].getUint8(chunk_idx - 1); - } - - private int getUint16(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return 0; - } - return current_chunk[columnIndex - 1].getUint16(chunk_idx - 1); - } - - private long getUint32(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return 0; - } - return current_chunk[columnIndex - 1].getUint32(chunk_idx - 1); - } - - private BigInteger getUint64(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return BigInteger.ZERO; - } - return current_chunk[columnIndex - 1].getUint64(chunk_idx - 1); - } - - public long getLong(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return 0; - } - return current_chunk[columnIndex - 1].getLong(chunk_idx - 1); - } - - public BigInteger getHugeint(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return BigInteger.ZERO; - } - return current_chunk[columnIndex - 1].getHugeint(chunk_idx - 1); - } - - public BigInteger getUhugeint(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return BigInteger.ZERO; - } - return current_chunk[columnIndex - 1].getUhugeint(chunk_idx - 1); - } - - public float getFloat(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return Float.NaN; - } - return current_chunk[columnIndex - 1].getFloat(chunk_idx - 1); - } - - public double getDouble(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return Double.NaN; - } - return current_chunk[columnIndex - 1].getDouble(chunk_idx - 1); - } - - public int findColumn(String columnLabel) throws SQLException { - if (isClosed()) { - throw new SQLException("ResultSet was closed"); - } - for (int col_idx = 0; col_idx < meta.column_count; col_idx++) { - if (meta.column_names[col_idx].contentEquals(columnLabel)) { - return col_idx + 1; - } - } - throw new SQLException("Could not find column with label " + columnLabel); - } - - public String getString(String columnLabel) throws SQLException { - return getString(findColumn(columnLabel)); - } - - public boolean getBoolean(String columnLabel) throws SQLException { - return getBoolean(findColumn(columnLabel)); - } - - public byte getByte(String columnLabel) throws SQLException { - return getByte(findColumn(columnLabel)); - } - - public short getShort(String columnLabel) throws SQLException { - return getShort(findColumn(columnLabel)); - } - - public int getInt(String columnLabel) throws SQLException { - return getInt(findColumn(columnLabel)); - } - - public long getLong(String columnLabel) throws SQLException { - return getLong(findColumn(columnLabel)); - } - - public float getFloat(String columnLabel) throws SQLException { - return getFloat(findColumn(columnLabel)); - } - - public double getDouble(String columnLabel) throws SQLException { - return getDouble(findColumn(columnLabel)); - } - - public Object getObject(String columnLabel) throws SQLException { - return getObject(findColumn(columnLabel)); - } - - public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { - throw new SQLFeatureNotSupportedException("getBigDecimal"); - } - - public byte[] getBytes(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getBytes"); - } - - public Date getDate(int columnIndex) throws SQLException { - return check_and_null(columnIndex) ? null : current_chunk[columnIndex - 1].getDate(chunk_idx - 1); - } - - public Time getTime(int columnIndex) throws SQLException { - return check_and_null(columnIndex) ? null : current_chunk[columnIndex - 1].getTime(chunk_idx - 1); - } - - public Timestamp getTimestamp(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getTimestamp(chunk_idx - 1); - } - - private LocalDateTime getLocalDateTime(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getLocalDateTime(chunk_idx - 1); - } - - private OffsetDateTime getOffsetDateTime(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getOffsetDateTime(chunk_idx - 1); - } - - public UUID getUuid(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getUuid(chunk_idx - 1); - } - - public static class DuckDBBlobResult implements Blob { - - static class ByteBufferBackedInputStream extends InputStream { - - ByteBuffer buf; - - public ByteBufferBackedInputStream(ByteBuffer buf) { - this.buf = buf; - } - - public int read() throws IOException { - if (!buf.hasRemaining()) { - return -1; - } - return buf.get() & 0xFF; - } - - public int read(byte[] bytes, int off, int len) throws IOException { - if (!buf.hasRemaining()) { - return -1; - } - - len = Math.min(len, buf.remaining()); - buf.get(bytes, off, len); - return len; - } - } - - public DuckDBBlobResult(ByteBuffer buffer_p) { - buffer_p.position(0); - buffer_p.order(ByteOrder.LITTLE_ENDIAN); - this.buffer = buffer_p; - } - - public InputStream getBinaryStream() { - return getBinaryStream(0, length()); - } - - public InputStream getBinaryStream(long pos, long length) { - return new ByteBufferBackedInputStream(buffer); - } - - @Override - public byte[] getBytes(long pos, int length) throws SQLException { - if (pos < 1 || length < 0) { - throw new SQLException("Invalid position or length"); - } - byte[] bytes = new byte[length]; - buffer.position((int) pos - 1); - buffer.get(bytes, 0, length); - return bytes; - } - - public long position(Blob pattern, long start) throws SQLException { - throw new SQLFeatureNotSupportedException("position"); - } - - public long position(byte[] pattern, long start) throws SQLException { - throw new SQLFeatureNotSupportedException("position"); - } - - public long length() { - return buffer.capacity(); - } - - public void free() { - // nop - } - - public OutputStream setBinaryStream(long pos) throws SQLException { - throw new SQLFeatureNotSupportedException("setBinaryStream"); - } - - public void truncate(long length) throws SQLException { - throw new SQLFeatureNotSupportedException("truncate"); - } - - public int setBytes(long pos, byte[] bytes) throws SQLException { - throw new SQLFeatureNotSupportedException("setBytes"); - } - - public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException { - throw new SQLFeatureNotSupportedException("setBytes"); - } - - @Override - public String toString() { - return "DuckDBBlobResult{" - + "buffer=" + buffer + '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - DuckDBBlobResult that = (DuckDBBlobResult) o; - return Objects.equals(buffer, that.buffer); - } - - @Override - public int hashCode() { - return Objects.hash(buffer); - } - - private ByteBuffer buffer; - } - - public Blob getBlob(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getBlob(chunk_idx - 1); - } - - public Blob getBlob(String columnLabel) throws SQLException { - return getBlob(findColumn(columnLabel)); - } - - public InputStream getAsciiStream(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getAsciiStream"); - } - - public InputStream getUnicodeStream(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getUnicodeStream"); - } - - public InputStream getBinaryStream(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getBinaryStream"); - } - - public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { - throw new SQLFeatureNotSupportedException("getBigDecimal"); - } - - public byte[] getBytes(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getBytes"); - } - - public Date getDate(String columnLabel) throws SQLException { - return getDate(findColumn(columnLabel)); - } - - public Time getTime(String columnLabel) throws SQLException { - return getTime(findColumn(columnLabel)); - } - - public Timestamp getTimestamp(String columnLabel) throws SQLException { - return getTimestamp(findColumn(columnLabel)); - } - - public InputStream getAsciiStream(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getAsciiStream"); - } - - public InputStream getUnicodeStream(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getUnicodeStream"); - } - - public InputStream getBinaryStream(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getBinaryStream"); - } - - public SQLWarning getWarnings() throws SQLException { - throw new SQLFeatureNotSupportedException("getWarnings"); - } - - public void clearWarnings() throws SQLException { - throw new SQLFeatureNotSupportedException("clearWarnings"); - } - - public String getCursorName() throws SQLException { - throw new SQLFeatureNotSupportedException("getCursorName"); - } - - public Reader getCharacterStream(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getCharacterStream"); - } - - public Reader getCharacterStream(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getCharacterStream"); - } - - public BigDecimal getBigDecimal(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getBigDecimal(chunk_idx - 1); - } - - public BigDecimal getBigDecimal(String columnLabel) throws SQLException { - return getBigDecimal(findColumn(columnLabel)); - } - - public boolean isBeforeFirst() throws SQLException { - throw new SQLFeatureNotSupportedException("isBeforeFirst"); - } - - public boolean isAfterLast() throws SQLException { - throw new SQLFeatureNotSupportedException("isAfterLast"); - } - - public boolean isFirst() throws SQLException { - throw new SQLFeatureNotSupportedException("isFirst"); - } - - public boolean isLast() throws SQLException { - throw new SQLFeatureNotSupportedException("isLast"); - } - - public void beforeFirst() throws SQLException { - throw new SQLFeatureNotSupportedException("beforeFirst"); - } - - public void afterLast() throws SQLException { - throw new SQLFeatureNotSupportedException("afterLast"); - } - - public boolean first() throws SQLException { - throw new SQLFeatureNotSupportedException("first"); - } - - public boolean last() throws SQLException { - throw new SQLFeatureNotSupportedException("last"); - } - - public int getRow() throws SQLException { - throw new SQLFeatureNotSupportedException("getRow"); - } - - public boolean absolute(int row) throws SQLException { - throw new SQLFeatureNotSupportedException("absolute"); - } - - public boolean relative(int rows) throws SQLException { - throw new SQLFeatureNotSupportedException("relative"); - } - - public boolean previous() throws SQLException { - throw new SQLFeatureNotSupportedException("previous"); - } - - public void setFetchDirection(int direction) throws SQLException { - if (direction != ResultSet.FETCH_FORWARD && direction != ResultSet.FETCH_UNKNOWN) { - throw new SQLFeatureNotSupportedException("setFetchDirection"); - } - } - - public int getFetchDirection() throws SQLException { - return ResultSet.FETCH_FORWARD; - } - - public void setFetchSize(int rows) throws SQLException { - if (rows < 0) { - throw new SQLException("Fetch size has to be >= 0"); - } - // whatevs - } - - public int getFetchSize() throws SQLException { - return DuckDBNative.duckdb_jdbc_fetch_size(); - } - - public int getType() throws SQLException { - return ResultSet.TYPE_FORWARD_ONLY; - } - - public int getConcurrency() throws SQLException { - return ResultSet.CONCUR_READ_ONLY; - } - - public boolean rowUpdated() throws SQLException { - throw new SQLFeatureNotSupportedException("rowUpdated"); - } - - public boolean rowInserted() throws SQLException { - throw new SQLFeatureNotSupportedException("rowInserted"); - } - - public boolean rowDeleted() throws SQLException { - throw new SQLFeatureNotSupportedException("rowDeleted"); - } - - public void updateNull(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNull"); - } - - public void updateBoolean(int columnIndex, boolean x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBoolean"); - } - - public void updateByte(int columnIndex, byte x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateByte"); - } - - public void updateShort(int columnIndex, short x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateShort"); - } - - public void updateInt(int columnIndex, int x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateInt"); - } - - public void updateLong(int columnIndex, long x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateLong"); - } - - public void updateFloat(int columnIndex, float x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateFloat"); - } - - public void updateDouble(int columnIndex, double x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateDouble"); - } - - public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBigDecimal"); - } - - public void updateString(int columnIndex, String x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateString"); - } - - public void updateBytes(int columnIndex, byte[] x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBytes"); - } - - public void updateDate(int columnIndex, Date x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateDate"); - } - - public void updateTime(int columnIndex, Time x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateTime"); - } - - public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateTimestamp"); - } - - public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { - throw new SQLFeatureNotSupportedException("updateObject"); - } - - public void updateObject(int columnIndex, Object x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateObject"); - } - - public void updateNull(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNull"); - } - - public void updateBoolean(String columnLabel, boolean x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBoolean"); - } - - public void updateByte(String columnLabel, byte x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateByte"); - } - - public void updateShort(String columnLabel, short x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateShort"); - } - - public void updateInt(String columnLabel, int x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateInt"); - } - - public void updateLong(String columnLabel, long x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateLong"); - } - - public void updateFloat(String columnLabel, float x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateFloat"); - } - - public void updateDouble(String columnLabel, double x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateDouble"); - } - - public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBigDecimal"); - } - - public void updateString(String columnLabel, String x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateString"); - } - - public void updateBytes(String columnLabel, byte[] x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBytes"); - } - - public void updateDate(String columnLabel, Date x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateDate"); - } - - public void updateTime(String columnLabel, Time x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateTime"); - } - - public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateTimestamp"); - } - - public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { - throw new SQLFeatureNotSupportedException("updateObject"); - } - - public void updateObject(String columnLabel, Object x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateObject"); - } - - public void insertRow() throws SQLException { - throw new SQLFeatureNotSupportedException("insertRow"); - } - - public void updateRow() throws SQLException { - throw new SQLFeatureNotSupportedException("updateRow"); - } - - public void deleteRow() throws SQLException { - throw new SQLFeatureNotSupportedException("deleteRow"); - } - - public void refreshRow() throws SQLException { - throw new SQLFeatureNotSupportedException("refreshRow"); - } - - public void cancelRowUpdates() throws SQLException { - throw new SQLFeatureNotSupportedException("cancelRowUpdates"); - } - - public void moveToInsertRow() throws SQLException { - throw new SQLFeatureNotSupportedException("moveToInsertRow"); - } - - public void moveToCurrentRow() throws SQLException { - throw new SQLFeatureNotSupportedException("moveToCurrentRow"); - } - - public Object getObject(int columnIndex, Map> map) throws SQLException { - throw new SQLFeatureNotSupportedException("getObject"); - } - - public Ref getRef(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getRef"); - } - - public Clob getClob(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getClob"); - } - - public Array getArray(int columnIndex) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getArray(chunk_idx - 1); - } - - public Object getObject(String columnLabel, Map> map) throws SQLException { - throw new SQLFeatureNotSupportedException("getObject"); - } - - public Ref getRef(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getRef"); - } - - public Clob getClob(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getClob"); - } - - public Array getArray(String columnLabel) throws SQLException { - return getArray(findColumn(columnLabel)); - } - - public Date getDate(int columnIndex, Calendar cal) throws SQLException { - return getDate(columnIndex); - } - - public Date getDate(String columnLabel, Calendar cal) throws SQLException { - return getDate(findColumn(columnLabel), cal); - } - - public Time getTime(int columnIndex, Calendar cal) throws SQLException { - return getTime(columnIndex); - } - - public Time getTime(String columnLabel, Calendar cal) throws SQLException { - return getTime(findColumn(columnLabel), cal); - } - - public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { - if (check_and_null(columnIndex)) { - return null; - } - return current_chunk[columnIndex - 1].getTimestamp(chunk_idx - 1, cal); - } - - public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { - return getTimestamp(findColumn(columnLabel), cal); - } - - public URL getURL(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getURL"); - } - - public URL getURL(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getURL"); - } - - public void updateRef(int columnIndex, Ref x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateRef"); - } - - public void updateRef(String columnLabel, Ref x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateRef"); - } - - public void updateBlob(int columnIndex, Blob x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - public void updateBlob(String columnLabel, Blob x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - public void updateClob(int columnIndex, Clob x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - public void updateClob(String columnLabel, Clob x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - public void updateArray(int columnIndex, Array x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateArray"); - } - - public void updateArray(String columnLabel, Array x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateArray"); - } - - public RowId getRowId(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getRowId"); - } - - public RowId getRowId(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getRowId"); - } - - public void updateRowId(int columnIndex, RowId x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateRowId"); - } - - public void updateRowId(String columnLabel, RowId x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateRowId"); - } - - public int getHoldability() throws SQLException { - throw new SQLFeatureNotSupportedException("getHoldability"); - } - - public void updateNString(int columnIndex, String nString) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNString"); - } - - public void updateNString(String columnLabel, String nString) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNString"); - } - - public void updateNClob(int columnIndex, NClob nClob) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - public void updateNClob(String columnLabel, NClob nClob) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - public NClob getNClob(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getNClob"); - } - - public NClob getNClob(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getNClob"); - } - - public SQLXML getSQLXML(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getSQLXML"); - } - - public SQLXML getSQLXML(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getSQLXML"); - } - - public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { - throw new SQLFeatureNotSupportedException("updateSQLXML"); - } - - public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { - throw new SQLFeatureNotSupportedException("updateSQLXML"); - } - - public String getNString(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getNString"); - } - - public String getNString(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getNString"); - } - - public Reader getNCharacterStream(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("getNCharacterStream"); - } - - public Reader getNCharacterStream(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("getNCharacterStream"); - } - - public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNCharacterStream"); - } - - public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNCharacterStream"); - } - - public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNCharacterStream"); - } - - public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNCharacterStream"); - } - - public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateAsciiStream"); - } - - public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBinaryStream"); - } - - public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateCharacterStream"); - } - - public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException("updateBlob"); - } - - public void updateClob(int columnIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - public void updateClob(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateClob"); - } - - public void updateNClob(int columnIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - public void updateNClob(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("updateNClob"); - } - - private boolean isTimestamp(DuckDBColumnType sqlType) { - return (sqlType == DuckDBColumnType.TIMESTAMP || sqlType == DuckDBColumnType.TIMESTAMP_WITH_TIME_ZONE); - } - - public T getObject(int columnIndex, Class type) throws SQLException { - if (type == null) { - throw new SQLException("type is null"); - } - - DuckDBColumnType sqlType = meta.column_types[columnIndex - 1]; - // Missing: unsigned types like UINTEGER, more liberal casting, e.g. SMALLINT -> - // Integer - // Compare results with expected results from Javadoc - // https://docs.oracle.com/en/java/javase/17/docs/api/java.sql/java/sql/ResultSet.html - if (type == BigDecimal.class) { - if (sqlType == DuckDBColumnType.DECIMAL) { - return type.cast(getBigDecimal(columnIndex)); - } else { - throw new SQLException("Can't convert value to BigDecimal " + type.toString()); - } - } else if (type == String.class) { - if (sqlType == DuckDBColumnType.VARCHAR || sqlType == DuckDBColumnType.ENUM) { - return type.cast(getString(columnIndex)); - } else { - throw new SQLException("Can't convert value to String " + type.toString()); - } - } else if (type == Boolean.class) { - if (sqlType == DuckDBColumnType.BOOLEAN) { - return type.cast(getBoolean(columnIndex)); - } else { - throw new SQLException("Can't convert value to boolean " + type.toString()); - } - } else if (type == Short.class) { - if (sqlType == DuckDBColumnType.SMALLINT) { - return type.cast(getShort(columnIndex)); - } else { - throw new SQLException("Can't convert value to short " + type.toString()); - } - } else if (type == Integer.class) { - if (sqlType == DuckDBColumnType.INTEGER) { - return type.cast(getInt(columnIndex)); - } else if (sqlType == DuckDBColumnType.SMALLINT) { - return type.cast(getShort(columnIndex)); - } else if (sqlType == DuckDBColumnType.TINYINT) { - return type.cast(getByte(columnIndex)); - } else if (sqlType == DuckDBColumnType.USMALLINT) { - throw new SQLException("Can't convert value to integer " + type.toString()); - // return type.cast(getShort(columnIndex)); - } else if (sqlType == DuckDBColumnType.UTINYINT) { - throw new SQLException("Can't convert value to integer " + type.toString()); - // return type.cast(getShort(columnIndex)); - } else { - throw new SQLException("Can't convert value to integer " + type.toString()); - } - } else if (type == Long.class) { - if (sqlType == DuckDBColumnType.BIGINT || isTimestamp(sqlType)) { - return type.cast(getLong(columnIndex)); - } else if (sqlType == DuckDBColumnType.UINTEGER) { - throw new SQLException("Can't convert value to long " + type.toString()); - // return type.cast(getLong(columnIndex)); - } else { - throw new SQLException("Can't convert value to long " + type.toString()); - } - } else if (type == Float.class) { - if (sqlType == DuckDBColumnType.FLOAT) { - return type.cast(getFloat(columnIndex)); - } else { - throw new SQLException("Can't convert value to float " + type.toString()); - } - } else if (type == Double.class) { - if (sqlType == DuckDBColumnType.DOUBLE) { - return type.cast(getDouble(columnIndex)); - } else { - throw new SQLException("Can't convert value to float " + type.toString()); - } - } else if (type == Date.class) { - if (sqlType == DuckDBColumnType.DATE) { - return type.cast(getDate(columnIndex)); - } else { - throw new SQLException("Can't convert value to Date " + type.toString()); - } - } else if (type == Time.class) { - if (sqlType == DuckDBColumnType.TIME) { - return type.cast(getTime(columnIndex)); - } else { - throw new SQLException("Can't convert value to Time " + type.toString()); - } - } else if (type == Timestamp.class) { - if (isTimestamp(sqlType)) { - return type.cast(getTimestamp(columnIndex)); - } else { - throw new SQLException("Can't convert value to Timestamp " + type.toString()); - } - } else if (type == LocalDateTime.class) { - if (isTimestamp(sqlType)) { - return type.cast(getLocalDateTime(columnIndex)); - } else { - throw new SQLException("Can't convert value to LocalDateTime " + type.toString()); - } - } else if (type == BigInteger.class) { - if (sqlType == DuckDBColumnType.HUGEINT) { - throw new SQLException("Can't convert value to BigInteger " + type.toString()); - // return type.cast(getLocalDateTime(columnIndex)); - } else if (sqlType == DuckDBColumnType.UHUGEINT) { - throw new SQLException("Can't convert value to BigInteger " + type.toString()); - } else if (sqlType == DuckDBColumnType.UBIGINT) { - throw new SQLException("Can't convert value to BigInteger " + type.toString()); - // return type.cast(getLocalDateTime(columnIndex)); - } else { - throw new SQLException("Can't convert value to BigInteger " + type.toString()); - } - } else if (type == OffsetDateTime.class) { - if (sqlType == DuckDBColumnType.TIMESTAMP_WITH_TIME_ZONE) { - return type.cast(getOffsetDateTime(columnIndex)); - } else { - throw new SQLException("Can't convert value to OffsetDateTime " + type.toString()); - } - } else if (type == Blob.class) { - if (sqlType == DuckDBColumnType.BLOB) { - throw new SQLException("Can't convert value to Blob " + type.toString()); - // return type.cast(getLocalDateTime(columnIndex)); - } else { - throw new SQLException("Can't convert value to Blob " + type.toString()); - } - } else { - throw new SQLException("Can't convert value to " + type + " " + type.toString()); - } - } - - public T getObject(String columnLabel, Class type) throws SQLException { - throw new SQLFeatureNotSupportedException("getObject"); - } - - @Override - public T unwrap(Class iface) throws SQLException { - return JdbcUtils.unwrap(this, iface); - } - - @Override - public boolean isWrapperFor(Class iface) { - return iface.isInstance(this); - } - - boolean isFinished() { - return finished; - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBResultSetMetaData.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBResultSetMetaData.java deleted file mode 100644 index d9105ab323f..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBResultSetMetaData.java +++ /dev/null @@ -1,303 +0,0 @@ -package org.duckdb; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.sql.Types; -import java.time.LocalDate; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.UUID; - -public class DuckDBResultSetMetaData implements ResultSetMetaData { - - public DuckDBResultSetMetaData(int param_count, int column_count, String[] column_names, - String[] column_types_string, String[] column_types_details, String return_type) { - this.param_count = param_count; - this.column_count = column_count; - this.column_names = column_names; - this.return_type = StatementReturnType.valueOf(return_type); - this.column_types_string = column_types_string; - this.column_types_details = column_types_details; - ArrayList column_types_al = new ArrayList(column_count); - ArrayList column_types_meta = new ArrayList(column_count); - - for (String column_type_string : this.column_types_string) { - column_types_al.add(TypeNameToType(column_type_string)); - } - this.column_types = new DuckDBColumnType[column_count]; - this.column_types = column_types_al.toArray(this.column_types); - - for (String column_type_detail : this.column_types_details) { - if (TypeNameToType(column_type_detail) == DuckDBColumnType.DECIMAL) { - column_types_meta.add(DuckDBColumnTypeMetaData.parseColumnTypeMetadata(column_type_detail)); - } else { - column_types_meta.add(null); - } - } - this.column_types_meta = column_types_meta.toArray(new DuckDBColumnTypeMetaData[column_count]); - } - - public static DuckDBColumnType TypeNameToType(String type_name) { - if (type_name.endsWith("]")) { - // VARCHAR[] or VARCHAR[2] - return type_name.endsWith("[]") ? DuckDBColumnType.LIST : DuckDBColumnType.ARRAY; - } else if (type_name.startsWith("DECIMAL")) { - return DuckDBColumnType.DECIMAL; - } else if (type_name.equals("TIME WITH TIME ZONE")) { - return DuckDBColumnType.TIME_WITH_TIME_ZONE; - } else if (type_name.equals("TIMESTAMP WITH TIME ZONE")) { - return DuckDBColumnType.TIMESTAMP_WITH_TIME_ZONE; - } else if (type_name.startsWith("STRUCT")) { - return DuckDBColumnType.STRUCT; - } else if (type_name.startsWith("MAP")) { - return DuckDBColumnType.MAP; - } else if (type_name.startsWith("UNION")) { - return DuckDBColumnType.UNION; - } - try { - return DuckDBColumnType.valueOf(type_name); - } catch (IllegalArgumentException e) { - return DuckDBColumnType.UNKNOWN; - } - } - - protected int param_count; - protected int column_count; - protected String[] column_names; - protected String[] column_types_string; - protected String[] column_types_details; - protected DuckDBColumnType[] column_types; - protected DuckDBColumnTypeMetaData[] column_types_meta; - protected final StatementReturnType return_type; - - public StatementReturnType getReturnType() { - return return_type; - } - - public int getColumnCount() throws SQLException { - return column_count; - } - - public String getColumnLabel(int column) throws SQLException { - return getColumnName(column); - } - - public String getColumnName(int column) throws SQLException { - if (column > column_count) { - throw new SQLException("Column index out of bounds"); - } - return column_names[column - 1]; - } - - public static int type_to_int(DuckDBColumnType type) { - switch (type) { - case BOOLEAN: - return Types.BOOLEAN; - case TINYINT: - return Types.TINYINT; - case SMALLINT: - return Types.SMALLINT; - case INTEGER: - return Types.INTEGER; - case BIGINT: - return Types.BIGINT; - case LIST: - case ARRAY: - return Types.ARRAY; - case FLOAT: - return Types.FLOAT; - case DOUBLE: - return Types.DOUBLE; - case DECIMAL: - return Types.DECIMAL; - case VARCHAR: - return Types.VARCHAR; - case TIME: - return Types.TIME; - case DATE: - return Types.DATE; - case TIMESTAMP_S: - case TIMESTAMP_MS: - case TIMESTAMP: - case TIMESTAMP_NS: - return Types.TIMESTAMP; - case TIMESTAMP_WITH_TIME_ZONE: - return Types.TIMESTAMP_WITH_TIMEZONE; - case TIME_WITH_TIME_ZONE: - return Types.TIME_WITH_TIMEZONE; - case STRUCT: - return Types.STRUCT; - case BIT: - return Types.BIT; - case BLOB: - return Types.BLOB; - default: - return Types.JAVA_OBJECT; - } - } - - public int getColumnType(int column) throws SQLException { - if (column > column_count) { - throw new SQLException("Column index out of bounds"); - } - return type_to_int(column_types[column - 1]); - } - - public String getColumnClassName(int column) throws SQLException { - switch (column_types[column - 1]) { - case BOOLEAN: - return Boolean.class.getName(); - case TINYINT: - return Byte.class.getName(); - case SMALLINT: - case UTINYINT: - return Short.class.getName(); - case INTEGER: - case USMALLINT: - return Integer.class.getName(); - case BIGINT: - case UINTEGER: - return Long.class.getName(); - case HUGEINT: - case UHUGEINT: - case UBIGINT: - return BigInteger.class.getName(); - case FLOAT: - return Float.class.getName(); - case DOUBLE: - return Double.class.getName(); - case DECIMAL: - return BigDecimal.class.getName(); - case TIME: - return LocalTime.class.getName(); - case TIME_WITH_TIME_ZONE: - return OffsetTime.class.getName(); - case DATE: - return LocalDate.class.getName(); - case TIMESTAMP: - case TIMESTAMP_NS: - case TIMESTAMP_S: - case TIMESTAMP_MS: - return Timestamp.class.getName(); - case TIMESTAMP_WITH_TIME_ZONE: - return OffsetDateTime.class.getName(); - case JSON: - return JsonNode.class.getName(); - case BLOB: - return DuckDBResultSet.DuckDBBlobResult.class.getName(); - case UUID: - return UUID.class.getName(); - case LIST: - case ARRAY: - return DuckDBArray.class.getName(); - case MAP: - return HashMap.class.getName(); - case STRUCT: - return DuckDBStruct.class.getName(); - default: - return String.class.getName(); - } - } - - public String getColumnTypeName(int column) throws SQLException { - if (column > column_count) { - throw new SQLException("Column index out of bounds"); - } - return column_types_string[column - 1]; - } - - public boolean isReadOnly(int column) throws SQLException { - return true; - } - - public boolean isWritable(int column) throws SQLException { - return false; - } - - public boolean isDefinitelyWritable(int column) throws SQLException { - return false; - } - - public boolean isCaseSensitive(int column) throws SQLException { - return true; - } - - public int isNullable(int column) throws SQLException { - return columnNullable; - } - - public String getSchemaName(int column) throws SQLException { - return ""; - } - - public boolean isAutoIncrement(int column) throws SQLException { - return false; - } - - public boolean isSearchable(int column) throws SQLException { - return true; - } - - public boolean isCurrency(int column) throws SQLException { - return false; - } - - public boolean isSigned(int column) throws SQLException { - return false; - } - - public int getColumnDisplaySize(int column) throws SQLException { - return 0; // most systems will fall back to getPrecision - } - - public int getPrecision(int column) throws SQLException { - DuckDBColumnTypeMetaData typeMetaData = typeMetadataForColumn(column); - - if (typeMetaData == null) { - return 0; - } - - return typeMetaData.width; - } - - public int getScale(int column) throws SQLException { - DuckDBColumnTypeMetaData typeMetaData = typeMetadataForColumn(column); - - if (typeMetaData == null) { - return 0; - } - - return typeMetaData.scale; - } - - public String getTableName(int column) throws SQLException { - return ""; - } - - public String getCatalogName(int column) throws SQLException { - return ""; - } - - @Override - public T unwrap(Class iface) throws SQLException { - return JdbcUtils.unwrap(this, iface); - } - - @Override - public boolean isWrapperFor(Class iface) { - return iface.isInstance(this); - } - - private DuckDBColumnTypeMetaData typeMetadataForColumn(int columnIndex) throws SQLException { - if (columnIndex > column_count) { - throw new SQLException("Column index out of bounds"); - } - return column_types_meta[columnIndex - 1]; - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBStruct.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBStruct.java deleted file mode 100644 index 6d83f632129..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBStruct.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.duckdb; - -import java.sql.SQLException; -import java.sql.Struct; -import java.util.Map; -import java.util.HashMap; - -public class DuckDBStruct implements Struct { - private final Object[] attributes; - private final String[] keys; - private final DuckDBVector[] values; - private final int offset; - private final String typeName; - - DuckDBStruct(String[] keys, DuckDBVector[] values, int offset, String typeName) throws SQLException { - this.keys = keys; - this.values = values; - this.offset = offset; - this.typeName = typeName; - - attributes = new Object[this.keys.length]; - for (int i = 0; i < this.keys.length; i++) { - attributes[i] = this.values[i].getObject(this.offset); - } - } - - @Override - public String getSQLTypeName() throws SQLException { - return typeName; - } - - @Override - public Object[] getAttributes() throws SQLException { - return attributes; - } - - @Override - public Object[] getAttributes(Map> map) throws SQLException { - return getAttributes(); - } - - public Map getMap() throws SQLException { - Object[] values = getAttributes(); - Map result = new HashMap<>(); - for (int i = 0; i < values.length; i++) { - result.put(keys[i], values[i]); - } - return result; - } - - @Override - public String toString() { - Object v = null; - try { - v = getMap(); - } catch (SQLException e) { - v = e; - } - return v.toString(); - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBTimestamp.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBTimestamp.java deleted file mode 100644 index b0b8f49298f..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBTimestamp.java +++ /dev/null @@ -1,157 +0,0 @@ -package org.duckdb; - -import java.sql.Timestamp; -import java.time.ZoneOffset; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.time.temporal.ChronoUnit; - -public class DuckDBTimestamp { - static { - // LocalDateTime reference of epoch - RefLocalDateTime = LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.UTC); - } - - public DuckDBTimestamp(long timeMicros) { - this.timeMicros = timeMicros; - } - - public DuckDBTimestamp(LocalDateTime localDateTime) { - this.timeMicros = localDateTime2Micros(localDateTime); - } - - public DuckDBTimestamp(OffsetDateTime offsetDateTime) { - this.timeMicros = DuckDBTimestamp.RefLocalDateTime.until(offsetDateTime.withOffsetSameInstant(ZoneOffset.UTC), - ChronoUnit.MICROS); - } - - public DuckDBTimestamp(Timestamp sqlTimestamp) { - this.timeMicros = DuckDBTimestamp.RefLocalDateTime.until(sqlTimestamp.toLocalDateTime(), ChronoUnit.MICROS); - } - - final static LocalDateTime RefLocalDateTime; - protected long timeMicros; - - public static Timestamp toSqlTimestamp(long timeMicros) { - return Timestamp.valueOf( - LocalDateTime.ofEpochSecond(micros2seconds(timeMicros), nanosPartMicros(timeMicros), ZoneOffset.UTC)); - } - - public static Timestamp toSqlTimestampNanos(long timeNanos) { - return Timestamp.valueOf( - LocalDateTime.ofEpochSecond(nanos2seconds(timeNanos), nanosPartNanos(timeNanos), ZoneOffset.UTC)); - } - - public static LocalDateTime toLocalDateTime(long timeMicros) { - return LocalDateTime.ofEpochSecond(micros2seconds(timeMicros), nanosPartMicros(timeMicros), ZoneOffset.UTC); - } - - public static OffsetTime toOffsetTime(long timeBits) { - long timeMicros = timeBits >> 24; // High 40 bits are micros - long offset = timeBits & 0x0FFFFFF; // Low 24 bits are inverted biased offset in seconds - long max_offset = 16 * 60 * 60 - 1; // ±15:59:59 - offset = max_offset - offset; - int sign = (offset < 0) ? -1 : 1; - offset = Math.abs(offset); - - int ss = (int) offset % 60; - offset = offset / 60; - - int mm = (int) offset % 60; - int hh = (int) offset / 60; - - if (hh > 15) { - return OffsetTime.of(toLocalTime(timeMicros), ZoneOffset.UTC); - } else { - return OffsetTime.of(toLocalTime(timeMicros), - ZoneOffset.ofHoursMinutesSeconds(sign * hh, sign * mm, sign * ss)); - } - } - - private static LocalTime toLocalTime(long timeMicros) { - return LocalTime.ofNanoOfDay(timeMicros * 1000); - } - - public static OffsetDateTime toOffsetDateTime(long timeMicros) { - return OffsetDateTime.of(toLocalDateTime(timeMicros), ZoneOffset.UTC); - } - - public static Timestamp fromSecondInstant(long seconds) { - return fromMilliInstant(seconds * 1_000); - } - - public static Timestamp fromMilliInstant(long millis) { - return new Timestamp(millis); - } - - public static Timestamp fromMicroInstant(long micros) { - return Timestamp.from(Instant.ofEpochSecond(micros / 1_000_000, nanosPartMicros(micros))); - } - - public static Timestamp fromNanoInstant(long nanos) { - return Timestamp.from(Instant.ofEpochSecond(nanos / 1_000_000_000, nanosPartNanos(nanos))); - } - - public static long localDateTime2Micros(LocalDateTime localDateTime) { - return DuckDBTimestamp.RefLocalDateTime.until(localDateTime, ChronoUnit.MICROS); - } - - public Timestamp toSqlTimestamp() { - return Timestamp.valueOf(this.toLocalDateTime()); - } - - public LocalDateTime toLocalDateTime() { - return LocalDateTime.ofEpochSecond(micros2seconds(timeMicros), nanosPartMicros(timeMicros), ZoneOffset.UTC); - } - - public OffsetDateTime toOffsetDateTime() { - return OffsetDateTime.of(toLocalDateTime(this.timeMicros), ZoneOffset.UTC); - } - - public static long getMicroseconds(Timestamp sqlTimestamp) { - return DuckDBTimestamp.RefLocalDateTime.until(sqlTimestamp.toLocalDateTime(), ChronoUnit.MICROS); - } - - public long getMicrosEpoch() { - return this.timeMicros; - } - - public String toString() { - return this.toLocalDateTime().toString(); - } - - private static long micros2seconds(long micros) { - if ((micros % 1000_000L) >= 0) { - return micros / 1000_000L; - } else { - return (micros / 1000_000L) - 1; - } - } - - private static int nanosPartMicros(long micros) { - if ((micros % 1000_000L) >= 0) { - return (int) ((micros % 1000_000L) * 1000); - } else { - return (int) ((1000_000L + (micros % 1000_000L)) * 1000); - } - } - - private static long nanos2seconds(long nanos) { - if ((nanos % 1_000_000_000L) >= 0) { - return nanos / 1_000_000_000L; - } else { - return (nanos / 1_000_000_000L) - 1; - } - } - - private static int nanosPartNanos(long nanos) { - if ((nanos % 1_000_000_000L) >= 0) { - return (int) ((nanos % 1_000_000_000L)); - } else { - return (int) ((1_000_000_000L + (nanos % 1_000_000_000L))); - } - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBTimestampTZ.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBTimestampTZ.java deleted file mode 100644 index 65acd48e0e9..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBTimestampTZ.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.duckdb; - -import java.time.OffsetDateTime; - -public class DuckDBTimestampTZ extends DuckDBTimestamp { - - public DuckDBTimestampTZ(long timeMicros) { - super(timeMicros); - } - - public DuckDBTimestampTZ(OffsetDateTime offsetDateTime) { - super(offsetDateTime); - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/DuckDBVector.java b/tools/jdbc/src/main/java/org/duckdb/DuckDBVector.java deleted file mode 100644 index 5657b3baa12..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/DuckDBVector.java +++ /dev/null @@ -1,593 +0,0 @@ -package org.duckdb; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Date; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.Struct; -import java.sql.Time; -import java.sql.Timestamp; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.format.TextStyle; -import java.time.temporal.ChronoField; -import java.util.Map; -import java.util.HashMap; -import java.util.Calendar; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -class DuckDBVector { - // Constant to construct BigDecimals from hugeint_t - private final static BigDecimal ULONG_MULTIPLIER = new BigDecimal("18446744073709551616"); - private final static DateTimeFormatter ERA_FORMAT = - new DateTimeFormatterBuilder() - .appendValue(ChronoField.YEAR_OF_ERA) - .appendLiteral("-") - .appendValue(ChronoField.MONTH_OF_YEAR) - .appendLiteral("-") - .appendValue(ChronoField.DAY_OF_MONTH) - .appendOptional(new DateTimeFormatterBuilder() - .appendLiteral(" (") - .appendText(ChronoField.ERA, TextStyle.SHORT) - .appendLiteral(")") - .toFormatter()) - .toFormatter(); - - DuckDBVector(String duckdb_type, int length, boolean[] nullmask) { - super(); - this.duckdb_type = DuckDBResultSetMetaData.TypeNameToType(duckdb_type); - this.meta = this.duckdb_type == DuckDBColumnType.DECIMAL - ? DuckDBColumnTypeMetaData.parseColumnTypeMetadata(duckdb_type) - : null; - this.length = length; - this.nullmask = nullmask; - } - private final DuckDBColumnTypeMetaData meta; - protected final DuckDBColumnType duckdb_type; - final int length; - private final boolean[] nullmask; - private ByteBuffer constlen_data = null; - private Object[] varlen_data = null; - - Object getObject(int idx) throws SQLException { - if (check_and_null(idx)) { - return null; - } - switch (duckdb_type) { - case BOOLEAN: - return getBoolean(idx); - case TINYINT: - return getByte(idx); - case SMALLINT: - return getShort(idx); - case INTEGER: - return getInt(idx); - case BIGINT: - return getLong(idx); - case HUGEINT: - return getHugeint(idx); - case UHUGEINT: - return getUhugeint(idx); - case UTINYINT: - return getUint8(idx); - case USMALLINT: - return getUint16(idx); - case UINTEGER: - return getUint32(idx); - case UBIGINT: - return getUint64(idx); - case FLOAT: - return getFloat(idx); - case DOUBLE: - return getDouble(idx); - case DECIMAL: - return getBigDecimal(idx); - case TIME: - return getLocalTime(idx); - case TIME_WITH_TIME_ZONE: - return getOffsetTime(idx); - case DATE: - return getLocalDate(idx); - case TIMESTAMP: - case TIMESTAMP_NS: - case TIMESTAMP_S: - case TIMESTAMP_MS: - return getTimestamp(idx); - case TIMESTAMP_WITH_TIME_ZONE: - return getOffsetDateTime(idx); - case JSON: - return getJsonObject(idx); - case BLOB: - return getBlob(idx); - case UUID: - return getUuid(idx); - case MAP: - return getMap(idx); - case LIST: - case ARRAY: - return getArray(idx); - case STRUCT: - return getStruct(idx); - case UNION: - return getUnion(idx); - default: - return getLazyString(idx); - } - } - - LocalTime getLocalTime(int idx) { - if (check_and_null(idx)) { - return null; - } - - if (isType(DuckDBColumnType.TIME)) { - long microseconds = getbuf(idx, 8).getLong(); - long nanoseconds = TimeUnit.MICROSECONDS.toNanos(microseconds); - return LocalTime.ofNanoOfDay(nanoseconds); - } - - String lazyString = getLazyString(idx); - - return lazyString == null ? null : LocalTime.parse(lazyString); - } - - LocalDate getLocalDate(int idx) { - if (check_and_null(idx)) { - return null; - } - - if (isType(DuckDBColumnType.DATE)) { - return LocalDate.ofEpochDay(getbuf(idx, 4).getInt()); - } - - String lazyString = getLazyString(idx); - - if ("infinity".equals(lazyString)) - return LocalDate.MAX; - else if ("-infinity".equals(lazyString)) - return LocalDate.MIN; - - return lazyString == null ? null : LocalDate.from(ERA_FORMAT.parse(lazyString)); - } - - BigDecimal getBigDecimal(int idx) throws SQLException { - if (check_and_null(idx)) { - return null; - } - if (isType(DuckDBColumnType.DECIMAL)) { - switch (meta.type_size) { - case 16: - return new BigDecimal((int) getbuf(idx, 2).getShort()).scaleByPowerOfTen(meta.scale * -1); - case 32: - return new BigDecimal(getbuf(idx, 4).getInt()).scaleByPowerOfTen(meta.scale * -1); - case 64: - return new BigDecimal(getbuf(idx, 8).getLong()).scaleByPowerOfTen(meta.scale * -1); - case 128: - ByteBuffer buf = getbuf(idx, 16); - long lower = buf.getLong(); - long upper = buf.getLong(); - return new BigDecimal(upper) - .multiply(ULONG_MULTIPLIER) - .add(new BigDecimal(Long.toUnsignedString(lower))) - .scaleByPowerOfTen(meta.scale * -1); - } - } - Object o = getObject(idx); - return new BigDecimal(o.toString()); - } - - OffsetDateTime getOffsetDateTime(int idx) throws SQLException { - if (check_and_null(idx)) { - return null; - } - - if (isType(DuckDBColumnType.TIMESTAMP_WITH_TIME_ZONE)) { - return DuckDBTimestamp.toOffsetDateTime(getbuf(idx, 8).getLong()); - } - Object o = getObject(idx); - return OffsetDateTime.parse(o.toString()); - } - - Timestamp getTimestamp(int idx) throws SQLException { - if (check_and_null(idx)) { - return null; - } - - if (isType(DuckDBColumnType.TIMESTAMP) || isType(DuckDBColumnType.TIMESTAMP_WITH_TIME_ZONE)) { - return DuckDBTimestamp.toSqlTimestamp(getbuf(idx, 8).getLong()); - } - if (isType(DuckDBColumnType.TIMESTAMP_MS)) { - return DuckDBTimestamp.toSqlTimestamp(getbuf(idx, 8).getLong() * 1000); - } - if (isType(DuckDBColumnType.TIMESTAMP_NS)) { - return DuckDBTimestamp.toSqlTimestampNanos(getbuf(idx, 8).getLong()); - } - if (isType(DuckDBColumnType.TIMESTAMP_S)) { - return DuckDBTimestamp.toSqlTimestamp(getbuf(idx, 8).getLong() * 1_000_000); - } - Object o = getObject(idx); - return Timestamp.valueOf(o.toString()); - } - - UUID getUuid(int idx) throws SQLException { - if (check_and_null(idx)) { - return null; - } - - if (isType(DuckDBColumnType.UUID)) { - ByteBuffer buffer = getbuf(idx, 16); - long leastSignificantBits = buffer.getLong(); - - // Account for unsigned - long mostSignificantBits = buffer.getLong() - Long.MAX_VALUE - 1; - return new UUID(mostSignificantBits, leastSignificantBits); - } - Object o = getObject(idx); - return UUID.fromString(o.toString()); - } - - String getLazyString(int idx) { - if (check_and_null(idx)) { - return null; - } - return varlen_data[idx].toString(); - } - - Array getArray(int idx) throws SQLException { - if (check_and_null(idx)) { - return null; - } - if (isType(DuckDBColumnType.LIST) || isType(DuckDBColumnType.ARRAY)) { - return (Array) varlen_data[idx]; - } - throw new SQLFeatureNotSupportedException("getArray"); - } - - Map getMap(int idx) throws SQLException { - if (check_and_null(idx)) { - return null; - } - if (!isType(DuckDBColumnType.MAP)) { - throw new SQLFeatureNotSupportedException("getMap"); - } - - Object[] entries = (Object[]) (((Array) varlen_data[idx]).getArray()); - Map result = new HashMap<>(); - - for (Object entry : entries) { - Object[] entry_val = ((Struct) entry).getAttributes(); - result.put(entry_val[0], entry_val[1]); - } - - return result; - } - - Blob getBlob(int idx) throws SQLException { - if (check_and_null(idx)) { - return null; - } - if (isType(DuckDBColumnType.BLOB)) { - return new DuckDBResultSet.DuckDBBlobResult((ByteBuffer) varlen_data[idx]); - } - - throw new SQLFeatureNotSupportedException("getBlob"); - } - - JsonNode getJsonObject(int idx) { - if (check_and_null(idx)) { - return null; - } - String result = getLazyString(idx); - return result == null ? null : new JsonNode(result); - } - - Date getDate(int idx) { - if (check_and_null(idx)) { - return null; - } - - if (isType(DuckDBColumnType.DATE)) { - return Date.valueOf(this.getLocalDate(idx)); - } - - String string_value = getLazyString(idx); - if (string_value == null) { - return null; - } - try { - return Date.valueOf(string_value); - } catch (Exception e) { - return null; - } - } - - OffsetTime getOffsetTime(int idx) { - if (check_and_null(idx)) { - return null; - } - return DuckDBTimestamp.toOffsetTime(getbuf(idx, 8).getLong()); - } - - Time getTime(int idx) { - if (check_and_null(idx)) { - return null; - } - - if (isType(DuckDBColumnType.TIME)) { - return Time.valueOf(getLocalTime(idx)); - } - - String string_value = getLazyString(idx); - try { - return Time.valueOf(string_value); - } catch (Exception e) { - return null; - } - } - - Boolean getBoolean(int idx) throws SQLException { - if (check_and_null(idx)) { - return false; - } - if (isType(DuckDBColumnType.BOOLEAN)) { - return getbuf(idx, 1).get() == 1; - } - Object o = getObject(idx); - if (o instanceof Number) { - return ((Number) o).byteValue() == 1; - } - - return Boolean.parseBoolean(o.toString()); - } - - protected ByteBuffer getbuf(int idx, int typeWidth) { - ByteBuffer buf = constlen_data; - buf.order(ByteOrder.LITTLE_ENDIAN); - buf.position(idx * typeWidth); - return buf; - } - - protected boolean check_and_null(int idx) { - return nullmask[idx]; - } - - long getLong(int idx) throws SQLException { - if (check_and_null(idx)) { - return 0; - } - if (isType(DuckDBColumnType.BIGINT) || isType(DuckDBColumnType.TIMESTAMP) || - isType(DuckDBColumnType.TIMESTAMP_WITH_TIME_ZONE)) { - return getbuf(idx, 8).getLong(); - } - Object o = getObject(idx); - if (o instanceof Number) { - return ((Number) o).longValue(); - } - return Long.parseLong(o.toString()); - } - - int getInt(int idx) throws SQLException { - if (check_and_null(idx)) { - return 0; - } - if (isType(DuckDBColumnType.INTEGER)) { - return getbuf(idx, 4).getInt(); - } - Object o = getObject(idx); - if (o instanceof Number) { - return ((Number) o).intValue(); - } - return Integer.parseInt(o.toString()); - } - - short getUint8(int idx) throws SQLException { - if (check_and_null(idx)) { - return 0; - } - if (isType(DuckDBColumnType.UTINYINT)) { - ByteBuffer buf = ByteBuffer.allocate(2); - getbuf(idx, 1).get(buf.array(), 1, 1); - return buf.getShort(); - } - throw new SQLFeatureNotSupportedException("getUint8"); - } - - long getUint32(int idx) throws SQLException { - if (check_and_null(idx)) { - return 0; - } - if (isType(DuckDBColumnType.UINTEGER)) { - ByteBuffer buf = ByteBuffer.allocate(8); - buf.order(ByteOrder.LITTLE_ENDIAN); - getbuf(idx, 4).get(buf.array(), 0, 4); - return buf.getLong(); - } - throw new SQLFeatureNotSupportedException("getUint32"); - } - - int getUint16(int idx) throws SQLException { - if (check_and_null(idx)) { - return 0; - } - if (isType(DuckDBColumnType.USMALLINT)) { - ByteBuffer buf = ByteBuffer.allocate(4); - buf.order(ByteOrder.LITTLE_ENDIAN); - getbuf(idx, 2).get(buf.array(), 0, 2); - return buf.getInt(); - } - throw new SQLFeatureNotSupportedException("getUint16"); - } - - BigInteger getUint64(int idx) throws SQLException { - if (check_and_null(idx)) { - return BigInteger.ZERO; - } - if (isType(DuckDBColumnType.UBIGINT)) { - byte[] buf_res = new byte[16]; - byte[] buf = new byte[8]; - getbuf(idx, 8).get(buf); - for (int i = 0; i < 8; i++) { - buf_res[i + 8] = buf[7 - i]; - } - return new BigInteger(buf_res); - } - throw new SQLFeatureNotSupportedException("getUint64"); - } - - double getDouble(int idx) throws SQLException { - if (check_and_null(idx)) { - return Double.NaN; - } - if (isType(DuckDBColumnType.DOUBLE)) { - return getbuf(idx, 8).getDouble(); - } - Object o = getObject(idx); - if (o instanceof Number) { - return ((Number) o).doubleValue(); - } - return Double.parseDouble(o.toString()); - } - - byte getByte(int idx) throws SQLException { - if (check_and_null(idx)) { - return 0; - } - if (isType(DuckDBColumnType.TINYINT)) { - return getbuf(idx, 1).get(); - } - Object o = getObject(idx); - if (o instanceof Number) { - return ((Number) o).byteValue(); - } - return Byte.parseByte(o.toString()); - } - - short getShort(int idx) throws SQLException { - if (check_and_null(idx)) { - return 0; - } - if (isType(DuckDBColumnType.SMALLINT)) { - return getbuf(idx, 2).getShort(); - } - Object o = getObject(idx); - if (o instanceof Number) { - return ((Number) o).shortValue(); - } - return Short.parseShort(o.toString()); - } - - BigInteger getHugeint(int idx) throws SQLException { - if (check_and_null(idx)) { - return BigInteger.ZERO; - } - if (isType(DuckDBColumnType.HUGEINT)) { - byte[] buf = new byte[16]; - getbuf(idx, 16).get(buf); - for (int i = 0; i < 8; i++) { - byte keep = buf[i]; - buf[i] = buf[15 - i]; - buf[15 - i] = keep; - } - return new BigInteger(buf); - } - Object o = getObject(idx); - return new BigInteger(o.toString()); - } - - BigInteger getUhugeint(int idx) throws SQLException { - if (check_and_null(idx)) { - return BigInteger.ZERO; - } - if (isType(DuckDBColumnType.UHUGEINT)) { - byte[] buf = new byte[16]; - getbuf(idx, 16).get(buf); - for (int i = 0; i < 8; i++) { - byte keep = buf[i]; - buf[i] = buf[15 - i]; - buf[15 - i] = keep; - } - return new BigInteger(1, buf); - } - Object o = getObject(idx); - return new BigInteger(o.toString()); - } - - float getFloat(int idx) throws SQLException { - if (check_and_null(idx)) { - return Float.NaN; - } - if (isType(DuckDBColumnType.FLOAT)) { - return getbuf(idx, 4).getFloat(); - } - Object o = getObject(idx); - if (o instanceof Number) { - return ((Number) o).floatValue(); - } - return Float.parseFloat(o.toString()); - } - - private boolean isType(DuckDBColumnType columnType) { - return duckdb_type == columnType; - } - - Timestamp getTimestamp(int idx, Calendar cal) throws SQLException { - if (check_and_null(idx)) { - return null; - } - // Our raw data is already a proper count of units since the epoch - // So just construct the SQL Timestamp. - if (isType(DuckDBColumnType.TIMESTAMP) || isType(DuckDBColumnType.TIMESTAMP_WITH_TIME_ZONE)) { - return DuckDBTimestamp.fromMicroInstant(getbuf(idx, 8).getLong()); - } - if (isType(DuckDBColumnType.TIMESTAMP_MS)) { - return DuckDBTimestamp.fromMilliInstant(getbuf(idx, 8).getLong()); - } - if (isType(DuckDBColumnType.TIMESTAMP_NS)) { - return DuckDBTimestamp.fromNanoInstant(getbuf(idx, 8).getLong()); - } - if (isType(DuckDBColumnType.TIMESTAMP_S)) { - return DuckDBTimestamp.fromSecondInstant(getbuf(idx, 8).getLong()); - } - Object o = getObject(idx); - return Timestamp.valueOf(o.toString()); - } - - LocalDateTime getLocalDateTime(int idx) throws SQLException { - if (check_and_null(idx)) { - return null; - } - if (isType(DuckDBColumnType.TIMESTAMP) || isType(DuckDBColumnType.TIMESTAMP_WITH_TIME_ZONE)) { - return DuckDBTimestamp.toLocalDateTime(getbuf(idx, 8).getLong()); - } - Object o = getObject(idx); - return LocalDateTime.parse(o.toString()); - } - - Struct getStruct(int idx) { - return check_and_null(idx) ? null : (Struct) varlen_data[idx]; - } - - Object getUnion(int idx) throws SQLException { - if (check_and_null(idx)) - return null; - - Struct struct = getStruct(idx); - - Object[] attributes = struct.getAttributes(); - - short tag = (short) attributes[0]; - - return attributes[1 + tag]; - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/JdbcUtils.java b/tools/jdbc/src/main/java/org/duckdb/JdbcUtils.java deleted file mode 100644 index 0800fe2a8a8..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/JdbcUtils.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.duckdb; - -import java.sql.SQLException; -import java.io.InputStream; -import java.io.IOException; -import java.io.ByteArrayOutputStream; - -final class JdbcUtils { - - @SuppressWarnings("unchecked") - static T unwrap(Object obj, Class iface) throws SQLException { - if (!iface.isInstance(obj)) { - throw new SQLException(obj.getClass().getName() + " not unwrappable from " + iface.getName()); - } - return (T) obj; - } - - static byte[] readAllBytes(InputStream x) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - byte[] thing = new byte[256]; - int length; - int offset = 0; - while ((length = x.read(thing)) != -1) { - out.write(thing, offset, length); - offset += length; - } - return out.toByteArray(); - } - - private JdbcUtils() { - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/JsonNode.java b/tools/jdbc/src/main/java/org/duckdb/JsonNode.java deleted file mode 100644 index 33c8c1a8915..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/JsonNode.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.duckdb; - -import java.util.Objects; - -/** - * Basic wrapper for the JSON type - modelled after the jackson databind JsonNode - */ -public class JsonNode { - private final String source; - public JsonNode(String source) { - this.source = source; - } - public boolean isArray() { - return source.charAt(0) == '['; - } - public boolean isObject() { - return source.charAt(0) == '{'; - } - public boolean isBoolean() { - return "true".equals(source) || "false".equals(source); - } - public boolean isNull() { - return "null".equals(source); - } - public boolean isNumber() { - return Character.isDigit(source.charAt(0)); - } - public boolean isString() { - return !(isObject() || isBoolean() || isNull() || isArray() || isNumber()); - } - public String toString() { - return source; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof JsonNode)) - return false; - JsonNode jsonNode = (JsonNode) o; - return Objects.equals(source, jsonNode.source); - } - - @Override - public int hashCode() { - return Objects.hash(source); - } -} diff --git a/tools/jdbc/src/main/java/org/duckdb/StatementReturnType.java b/tools/jdbc/src/main/java/org/duckdb/StatementReturnType.java deleted file mode 100644 index 8048217eeb9..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/StatementReturnType.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.duckdb; - -public enum StatementReturnType { - QUERY_RESULT, // the statement returns a query result (e.g. for display to the user) - CHANGED_ROWS, // the statement returns a single row containing the number of changed rows (e.g. an insert stmt) - NOTHING // the statement returns nothing -} diff --git a/tools/jdbc/src/main/java/org/duckdb/package-info.java b/tools/jdbc/src/main/java/org/duckdb/package-info.java deleted file mode 100644 index 67252ebaf44..00000000000 --- a/tools/jdbc/src/main/java/org/duckdb/package-info.java +++ /dev/null @@ -1,9 +0,0 @@ -/** - * The DuckDB JDBC driver. Connect like so: - * - *
- * Class.forName("org.duckdb.DuckDBDriver");
- * Connection conn = DriverManager.getConnection("jdbc:duckdb:");
- * 
- */ -package org.duckdb; diff --git a/tools/jdbc/src/test/java/org/duckdb/TestDuckDBJDBC.java b/tools/jdbc/src/test/java/org/duckdb/TestDuckDBJDBC.java deleted file mode 100644 index 2c95b3cf57f..00000000000 --- a/tools/jdbc/src/test/java/org/duckdb/TestDuckDBJDBC.java +++ /dev/null @@ -1,4252 +0,0 @@ -package org.duckdb; - -import javax.sql.rowset.CachedRowSet; -import javax.sql.rowset.RowSetProvider; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.Date; -import java.sql.Driver; -import java.util.concurrent.Future; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Struct; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.format.ResolverStyle; -import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.ListIterator; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import java.util.TimeZone; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; - -import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME; -import static java.time.temporal.ChronoField.DAY_OF_MONTH; -import static java.time.temporal.ChronoField.MONTH_OF_YEAR; -import static java.time.temporal.ChronoField.OFFSET_SECONDS; -import static java.time.temporal.ChronoField.YEAR_OF_ERA; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; -import static org.duckdb.DuckDBDriver.DUCKDB_USER_AGENT_PROPERTY; -import static org.duckdb.DuckDBDriver.JDBC_STREAM_RESULTS; -import static org.duckdb.test.Assertions.assertEquals; -import static org.duckdb.test.Assertions.assertFalse; -import static org.duckdb.test.Assertions.assertNotNull; -import static org.duckdb.test.Assertions.assertNull; -import static org.duckdb.test.Assertions.assertThrows; -import static org.duckdb.test.Assertions.assertThrowsMaybe; -import static org.duckdb.test.Assertions.assertTrue; -import static org.duckdb.test.Assertions.fail; -import static org.duckdb.test.Runner.runTests; - -public class TestDuckDBJDBC { - - public static final String JDBC_URL = "jdbc:duckdb:"; - - private static void createTable(Connection conn) throws SQLException { - try (Statement createStmt = conn.createStatement()) { - createStmt.execute("CREATE TABLE foo as select * from range(1000000);"); - } - } - - private static void executeStatementWithThread(Statement statement, ExecutorService executor_service) - throws InterruptedException { - executor_service.submit(() -> { - try (ResultSet resultSet = statement.executeQuery("SELECT * from foo")) { - assertThrowsMaybe(() -> { - DuckDBResultSet duckdb_result_set = resultSet.unwrap(DuckDBResultSet.class); - while (duckdb_result_set.next()) { - // do nothing with the results - } - }, SQLException.class); - - } catch (Exception e) { - System.out.println("Error executing query: " + e.getMessage()); - } - }); - - Thread.sleep(10); // wait for query to start running - try { - statement.cancel(); - statement.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - public static void test_connection() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - assertTrue(conn.isValid(0)); - assertFalse(conn.isClosed()); - - Statement stmt = conn.createStatement(); - - ResultSet rs = stmt.executeQuery("SELECT 42 as a"); - assertFalse(stmt.isClosed()); - assertFalse(rs.isClosed()); - - assertTrue(rs.next()); - int res = rs.getInt(1); - assertEquals(res, 42); - assertFalse(rs.wasNull()); - - res = rs.getInt(1); - assertEquals(res, 42); - assertFalse(rs.wasNull()); - - res = rs.getInt("a"); - assertEquals(res, 42); - assertFalse(rs.wasNull()); - - assertThrows(() -> rs.getInt(0), SQLException.class); - - assertThrows(() -> rs.getInt(2), SQLException.class); - - assertThrows(() -> rs.getInt("b"), SQLException.class); - - assertFalse(rs.next()); - assertFalse(rs.next()); - - rs.close(); - rs.close(); - assertTrue(rs.isClosed()); - - assertThrows(() -> rs.getInt(1), SQLException.class); - - stmt.close(); - stmt.close(); - assertTrue(stmt.isClosed()); - - conn.close(); - conn.close(); - assertFalse(conn.isValid(0)); - assertTrue(conn.isClosed()); - - assertThrows(conn::createStatement, SQLException.class); - } - - public static void test_prepare_exception() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - assertThrows(() -> stmt.execute("this is no SQL;"), SQLException.class); - } - - public static void test_execute_exception() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - assertThrows(() -> { - ResultSet rs = stmt.executeQuery("SELECT"); - rs.next(); - }, SQLException.class); - } - - public static void test_autocommit_off() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - ResultSet rs; - - conn.setAutoCommit(false); - - stmt = conn.createStatement(); - stmt.execute("CREATE TABLE t (id INT);"); - conn.commit(); - - stmt.execute("INSERT INTO t (id) VALUES (1);"); - stmt.execute("INSERT INTO t (id) VALUES (2);"); - stmt.execute("INSERT INTO t (id) VALUES (3);"); - conn.commit(); - - rs = stmt.executeQuery("SELECT COUNT(*) FROM T"); - rs.next(); - assertEquals(rs.getInt(1), 3); - rs.close(); - - stmt.execute("INSERT INTO t (id) VALUES (4);"); - stmt.execute("INSERT INTO t (id) VALUES (5);"); - conn.rollback(); - - // After the rollback both inserts must be reverted - rs = stmt.executeQuery("SELECT COUNT(*) FROM T"); - rs.next(); - assertEquals(rs.getInt(1), 3); - - stmt.execute("INSERT INTO t (id) VALUES (6);"); - stmt.execute("INSERT INTO t (id) VALUES (7);"); - - conn.setAutoCommit(true); - - // Turning auto-commit on triggers a commit - rs = stmt.executeQuery("SELECT COUNT(*) FROM T"); - rs.next(); - assertEquals(rs.getInt(1), 5); - - // This means a rollback must not be possible now - assertThrows(conn::rollback, SQLException.class); - - stmt.execute("INSERT INTO t (id) VALUES (8);"); - rs = stmt.executeQuery("SELECT COUNT(*) FROM T"); - rs.next(); - assertEquals(rs.getInt(1), 6); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_enum() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs; - - // Test 8 bit enum + different access ways - stmt.execute("CREATE TYPE enum_test AS ENUM ('Enum1', 'enum2', '1üöñ');"); - stmt.execute("CREATE TABLE t (id INT, e1 enum_test);"); - stmt.execute("INSERT INTO t (id, e1) VALUES (1, 'Enum1');"); - stmt.execute("INSERT INTO t (id, e1) VALUES (2, 'enum2');"); - stmt.execute("INSERT INTO t (id, e1) VALUES (3, '1üöñ');"); - - PreparedStatement ps = conn.prepareStatement("SELECT e1 FROM t WHERE id = ?"); - ps.setObject(1, 1); - rs = ps.executeQuery(); - rs.next(); - assertTrue(rs.getObject(1, String.class).equals("Enum1")); - assertTrue(rs.getString(1).equals("Enum1")); - assertTrue(rs.getString("e1").equals("Enum1")); - rs.close(); - - ps.setObject(1, 2); - rs = ps.executeQuery(); - rs.next(); - assertTrue(rs.getObject(1, String.class).equals("enum2")); - assertTrue(rs.getObject(1).equals("enum2")); - rs.close(); - - ps.setObject(1, 3); - rs = ps.executeQuery(); - rs.next(); - assertTrue(rs.getObject(1, String.class).equals("1üöñ")); - assertTrue(rs.getObject(1).equals("1üöñ")); - assertTrue(rs.getObject("e1").equals("1üöñ")); - rs.close(); - - ps = conn.prepareStatement("SELECT e1 FROM t WHERE e1 = ?"); - ps.setObject(1, "1üöñ"); - rs = ps.executeQuery(); - rs.next(); - assertTrue(rs.getObject(1, String.class).equals("1üöñ")); - assertTrue(rs.getString(1).equals("1üöñ")); - assertTrue(rs.getString("e1").equals("1üöñ")); - rs.close(); - - // Test 16 bit enum - stmt.execute( - "CREATE TYPE enum_long AS ENUM ('enum0' ,'enum1' ,'enum2' ,'enum3' ,'enum4' ,'enum5' ,'enum6'" - + - ",'enum7' ,'enum8' ,'enum9' ,'enum10' ,'enum11' ,'enum12' ,'enum13' ,'enum14' ,'enum15' ,'enum16' ,'enum17'" - + - ",'enum18' ,'enum19' ,'enum20' ,'enum21' ,'enum22' ,'enum23' ,'enum24' ,'enum25' ,'enum26' ,'enum27' ,'enum28'" - + - ",'enum29' ,'enum30' ,'enum31' ,'enum32' ,'enum33' ,'enum34' ,'enum35' ,'enum36' ,'enum37' ,'enum38' ,'enum39'" - + - ",'enum40' ,'enum41' ,'enum42' ,'enum43' ,'enum44' ,'enum45' ,'enum46' ,'enum47' ,'enum48' ,'enum49' ,'enum50'" - + - ",'enum51' ,'enum52' ,'enum53' ,'enum54' ,'enum55' ,'enum56' ,'enum57' ,'enum58' ,'enum59' ,'enum60' ,'enum61'" - + - ",'enum62' ,'enum63' ,'enum64' ,'enum65' ,'enum66' ,'enum67' ,'enum68' ,'enum69' ,'enum70' ,'enum71' ,'enum72'" - + - ",'enum73' ,'enum74' ,'enum75' ,'enum76' ,'enum77' ,'enum78' ,'enum79' ,'enum80' ,'enum81' ,'enum82' ,'enum83'" - + - ",'enum84' ,'enum85' ,'enum86' ,'enum87' ,'enum88' ,'enum89' ,'enum90' ,'enum91' ,'enum92' ,'enum93' ,'enum94'" - + - ",'enum95' ,'enum96' ,'enum97' ,'enum98' ,'enum99' ,'enum100' ,'enum101' ,'enum102' ,'enum103' ,'enum104' " - + - ",'enum105' ,'enum106' ,'enum107' ,'enum108' ,'enum109' ,'enum110' ,'enum111' ,'enum112' ,'enum113' ,'enum114'" - + - ",'enum115' ,'enum116' ,'enum117' ,'enum118' ,'enum119' ,'enum120' ,'enum121' ,'enum122' ,'enum123' ,'enum124'" - + - ",'enum125' ,'enum126' ,'enum127' ,'enum128' ,'enum129' ,'enum130' ,'enum131' ,'enum132' ,'enum133' ,'enum134'" - + - ",'enum135' ,'enum136' ,'enum137' ,'enum138' ,'enum139' ,'enum140' ,'enum141' ,'enum142' ,'enum143' ,'enum144'" - + - ",'enum145' ,'enum146' ,'enum147' ,'enum148' ,'enum149' ,'enum150' ,'enum151' ,'enum152' ,'enum153' ,'enum154'" - + - ",'enum155' ,'enum156' ,'enum157' ,'enum158' ,'enum159' ,'enum160' ,'enum161' ,'enum162' ,'enum163' ,'enum164'" - + - ",'enum165' ,'enum166' ,'enum167' ,'enum168' ,'enum169' ,'enum170' ,'enum171' ,'enum172' ,'enum173' ,'enum174'" - + - ",'enum175' ,'enum176' ,'enum177' ,'enum178' ,'enum179' ,'enum180' ,'enum181' ,'enum182' ,'enum183' ,'enum184'" - + - ",'enum185' ,'enum186' ,'enum187' ,'enum188' ,'enum189' ,'enum190' ,'enum191' ,'enum192' ,'enum193' ,'enum194'" - + - ",'enum195' ,'enum196' ,'enum197' ,'enum198' ,'enum199' ,'enum200' ,'enum201' ,'enum202' ,'enum203' ,'enum204'" - + - ",'enum205' ,'enum206' ,'enum207' ,'enum208' ,'enum209' ,'enum210' ,'enum211' ,'enum212' ,'enum213' ,'enum214'" - + - ",'enum215' ,'enum216' ,'enum217' ,'enum218' ,'enum219' ,'enum220' ,'enum221' ,'enum222' ,'enum223' ,'enum224'" - + - ",'enum225' ,'enum226' ,'enum227' ,'enum228' ,'enum229' ,'enum230' ,'enum231' ,'enum232' ,'enum233' ,'enum234'" - + - ",'enum235' ,'enum236' ,'enum237' ,'enum238' ,'enum239' ,'enum240' ,'enum241' ,'enum242' ,'enum243' ,'enum244'" - + - ",'enum245' ,'enum246' ,'enum247' ,'enum248' ,'enum249' ,'enum250' ,'enum251' ,'enum252' ,'enum253' ,'enum254'" - + - ",'enum255' ,'enum256' ,'enum257' ,'enum258' ,'enum259' ,'enum260' ,'enum261' ,'enum262' ,'enum263' ,'enum264'" - + - ",'enum265' ,'enum266' ,'enum267' ,'enum268' ,'enum269' ,'enum270' ,'enum271' ,'enum272' ,'enum273' ,'enum274'" - + - ",'enum275' ,'enum276' ,'enum277' ,'enum278' ,'enum279' ,'enum280' ,'enum281' ,'enum282' ,'enum283' ,'enum284'" - + - ",'enum285' ,'enum286' ,'enum287' ,'enum288' ,'enum289' ,'enum290' ,'enum291' ,'enum292' ,'enum293' ,'enum294'" - + ",'enum295' ,'enum296' ,'enum297' ,'enum298' ,'enum299');"); - - stmt.execute("CREATE TABLE t2 (id INT, e1 enum_long);"); - stmt.execute("INSERT INTO t2 (id, e1) VALUES (1, 'enum290');"); - - ps = conn.prepareStatement("SELECT e1 FROM t2 WHERE id = ?"); - ps.setObject(1, 1); - rs = ps.executeQuery(); - rs.next(); - assertTrue(rs.getObject(1, String.class).equals("enum290")); - assertTrue(rs.getString(1).equals("enum290")); - assertTrue(rs.getString("e1").equals("enum290")); - rs.close(); - conn.close(); - } - - public static void test_timestamp_ms() throws Exception { - String expectedString = "2022-08-17 12:11:10.999"; - String sql = "SELECT '2022-08-17T12:11:10.999'::TIMESTAMP_MS as ts_ms"; - assert_timestamp_match(sql, expectedString, "TIMESTAMP_MS"); - } - - public static void test_timestamp_ns() throws Exception { - String expectedString = "2022-08-17 12:11:10.999999"; - String sql = "SELECT '2022-08-17T12:11:10.999999999'::TIMESTAMP_NS as ts_ns"; - assert_timestamp_match(sql, expectedString, "TIMESTAMP_NS"); - } - - public static void test_timestamp_s() throws Exception { - String expectedString = "2022-08-17 12:11:10"; - String sql = "SELECT '2022-08-17T12:11:10'::TIMESTAMP_S as ts_s"; - assert_timestamp_match(sql, expectedString, "TIMESTAMP_S"); - } - - private static void assert_timestamp_match(String fetchSql, String expectedString, String expectedTypeName) - throws Exception { - String originalTzProperty = System.getProperty("user.timezone"); - TimeZone originalTz = TimeZone.getDefault(); - try { - TimeZone.setDefault(TimeZone.getTimeZone("UTC")); - System.setProperty("user.timezone", "UTC"); - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs = stmt.executeQuery(fetchSql); - assertTrue(rs.next()); - Timestamp actual = rs.getTimestamp(1); - - Timestamp expected = Timestamp.valueOf(expectedString); - - assertEquals(expected.getTime(), actual.getTime()); - assertEquals(expected.getNanos(), actual.getNanos()); - - // Verify calendar variants - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles"), Locale.US); - Timestamp actual_cal = rs.getTimestamp(1, cal); - assertEquals(expected.getTime(), actual_cal.getTime()); - assertEquals(expected.getNanos(), actual_cal.getNanos()); - - assertEquals(Types.TIMESTAMP, rs.getMetaData().getColumnType(1)); - assertEquals(expectedTypeName, rs.getMetaData().getColumnTypeName(1)); - - rs.close(); - stmt.close(); - conn.close(); - } finally { - TimeZone.setDefault(originalTz); - System.setProperty("user.timezone", originalTzProperty); - } - } - - public static void test_timestamp_tz() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs; - - stmt.execute("CREATE TABLE t (id INT, t1 TIMESTAMPTZ)"); - stmt.execute("INSERT INTO t (id, t1) VALUES (1, '2022-01-01T12:11:10+02')"); - stmt.execute("INSERT INTO t (id, t1) VALUES (2, '2022-01-01T12:11:10Z')"); - - PreparedStatement ps = conn.prepareStatement("INSERT INTO T (id, t1) VALUES (?, ?)"); - - OffsetDateTime odt1 = OffsetDateTime.of(2020, 10, 7, 13, 15, 7, 12345, ZoneOffset.ofHours(7)); - OffsetDateTime odt1Rounded = OffsetDateTime.of(2020, 10, 7, 13, 15, 7, 12000, ZoneOffset.ofHours(7)); - OffsetDateTime odt2 = OffsetDateTime.of(1878, 10, 2, 1, 15, 7, 12345, ZoneOffset.ofHours(-5)); - OffsetDateTime odt2Rounded = OffsetDateTime.of(1878, 10, 2, 1, 15, 7, 13000, ZoneOffset.ofHours(-5)); - OffsetDateTime odt3 = OffsetDateTime.of(2022, 1, 1, 12, 11, 10, 0, ZoneOffset.ofHours(2)); - OffsetDateTime odt4 = OffsetDateTime.of(2022, 1, 1, 12, 11, 10, 0, ZoneOffset.ofHours(0)); - OffsetDateTime odt5 = OffsetDateTime.of(1900, 11, 27, 23, 59, 59, 0, ZoneOffset.ofHours(1)); - - ps.setObject(1, 3); - ps.setObject(2, odt1); - ps.execute(); - ps.setObject(1, 4); - ps.setObject(2, odt5, Types.TIMESTAMP_WITH_TIMEZONE); - ps.execute(); - ps.setObject(1, 5); - ps.setObject(2, odt2); - ps.execute(); - - rs = stmt.executeQuery("SELECT * FROM t ORDER BY id"); - ResultSetMetaData meta = rs.getMetaData(); - rs.next(); - assertTrue(rs.getObject(2, OffsetDateTime.class).isEqual(odt3)); - rs.next(); - assertEquals(rs.getObject(2, OffsetDateTime.class), odt4); - rs.next(); - assertTrue(rs.getObject(2, OffsetDateTime.class).isEqual(odt1Rounded)); - rs.next(); - assertTrue(rs.getObject(2, OffsetDateTime.class).isEqual(odt5)); - rs.next(); - assertTrue(rs.getObject(2, OffsetDateTime.class).isEqual(odt2Rounded)); - assertTrue(((OffsetDateTime) rs.getObject(2)).isEqual(odt2Rounded)); - - // Metadata tests - assertEquals( - Types.TIMESTAMP_WITH_TIMEZONE, - (meta.unwrap(DuckDBResultSetMetaData.class).type_to_int(DuckDBColumnType.TIMESTAMP_WITH_TIME_ZONE))); - assertTrue(OffsetDateTime.class.getName().equals(meta.getColumnClassName(2))); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_timestamp_as_long() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs; - - stmt.execute("CREATE TABLE t (id INT, t1 TIMESTAMP)"); - stmt.execute("INSERT INTO t (id, t1) VALUES (1, '2022-01-01T12:11:10')"); - stmt.execute("INSERT INTO t (id, t1) VALUES (2, '2022-01-01T12:11:11')"); - - rs = stmt.executeQuery("SELECT * FROM t ORDER BY id"); - rs.next(); - assertEquals(rs.getLong(2), 1641039070000000L); - rs.next(); - assertEquals(rs.getLong(2), 1641039071000000L); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_timestamptz_as_long() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs; - - stmt.execute("SET CALENDAR='gregorian'"); - stmt.execute("SET TIMEZONE='America/Los_Angeles'"); - stmt.execute("CREATE TABLE t (id INT, t1 TIMESTAMPTZ)"); - stmt.execute("INSERT INTO t (id, t1) VALUES (1, '2022-01-01T12:11:10Z')"); - stmt.execute("INSERT INTO t (id, t1) VALUES (2, '2022-01-01T12:11:11Z')"); - - rs = stmt.executeQuery("SELECT * FROM t ORDER BY id"); - rs.next(); - assertEquals(rs.getLong(2), 1641039070000000L); - rs.next(); - assertEquals(rs.getLong(2), 1641039071000000L); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_consecutive_timestamps() throws Exception { - long expected = 986860800000L; - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement()) { - try (ResultSet rs = stmt.executeQuery( - "select range from range(TIMESTAMP '2001-04-10', TIMESTAMP '2001-04-11', INTERVAL 30 MINUTE)")) { - while (rs.next()) { - Timestamp actual = rs.getTimestamp(1, Calendar.getInstance()); - assertEquals(expected, actual.getTime()); - expected += 30 * 60 * 1_000; - } - } - } - } - - public static void test_throw_wrong_datatype() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - ResultSet rs; - - stmt.execute("CREATE TABLE t (id INT, t1 TIMESTAMPTZ, t2 TIMESTAMP)"); - stmt.execute("INSERT INTO t (id, t1, t2) VALUES (1, '2022-01-01T12:11:10+02', '2022-01-01T12:11:10')"); - - rs = stmt.executeQuery("SELECT * FROM t"); - rs.next(); - - assertThrows(() -> rs.getShort(2), IllegalArgumentException.class); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_list_metadata() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT generate_series(2) as list");) { - ResultSetMetaData meta = rs.getMetaData(); - assertEquals(meta.getColumnCount(), 1); - assertEquals(meta.getColumnName(1), "list"); - assertEquals(meta.getColumnTypeName(1), "BIGINT[]"); - assertEquals(meta.getColumnType(1), Types.ARRAY); - } - } - - public static void test_struct_metadata() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT {'i': 42, 'j': 'a'} as struct")) { - ResultSetMetaData meta = rs.getMetaData(); - assertEquals(meta.getColumnCount(), 1); - assertEquals(meta.getColumnName(1), "struct"); - assertEquals(meta.getColumnTypeName(1), "STRUCT(i INTEGER, j VARCHAR)"); - assertEquals(meta.getColumnType(1), Types.STRUCT); - } - } - - public static void test_map_metadata() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT map([1,2],['a','b']) as map")) { - ResultSetMetaData meta = rs.getMetaData(); - assertEquals(meta.getColumnCount(), 1); - assertEquals(meta.getColumnName(1), "map"); - assertEquals(meta.getColumnTypeName(1), "MAP(INTEGER, VARCHAR)"); - assertEquals(meta.getColumnType(1), Types.JAVA_OBJECT); - } - } - - public static void test_union_metadata() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT union_value(str := 'three') as union")) { - ResultSetMetaData meta = rs.getMetaData(); - assertEquals(meta.getColumnCount(), 1); - assertEquals(meta.getColumnName(1), "union"); - assertEquals(meta.getColumnTypeName(1), "UNION(str VARCHAR)"); - assertEquals(meta.getColumnType(1), Types.JAVA_OBJECT); - } - } - - public static void test_native_duckdb_array() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); - PreparedStatement stmt = conn.prepareStatement("SELECT generate_series(1)::BIGINT[2] as \"array\""); - ResultSet rs = stmt.executeQuery()) { - ResultSetMetaData meta = rs.getMetaData(); - assertEquals(meta.getColumnCount(), 1); - assertEquals(meta.getColumnName(1), "array"); - assertEquals(meta.getColumnTypeName(1), "BIGINT[2]"); - assertEquals(meta.getColumnType(1), Types.ARRAY); - assertEquals(meta.getColumnClassName(1), DuckDBArray.class.getName()); - - assertTrue(rs.next()); - assertListsEqual(toJavaObject(rs.getObject(1)), asList(0L, 1L)); - } - } - - public static void test_result() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs; - - rs = stmt.executeQuery("SELECT CAST(42 AS INTEGER) as a, CAST(4.2 AS DOUBLE) as b"); - ResultSetMetaData meta = rs.getMetaData(); - assertEquals(meta.getColumnCount(), 2); - assertEquals(meta.getColumnName(1), "a"); - assertEquals(meta.getColumnName(2), "b"); - assertEquals(meta.getColumnTypeName(1), "INTEGER"); - assertEquals(meta.getColumnTypeName(2), "DOUBLE"); - - assertThrows(() -> meta.getColumnName(0), ArrayIndexOutOfBoundsException.class); - - assertThrows(() -> meta.getColumnTypeName(0), ArrayIndexOutOfBoundsException.class); - - assertThrows(() -> meta.getColumnName(3), SQLException.class); - - assertThrows(() -> meta.getColumnTypeName(3), SQLException.class); - - assertTrue(rs.next()); - assertEquals(rs.getInt(1), 42); - assertEquals(rs.getString(1), "42"); - assertEquals(rs.getDouble(1), 42.0, 0.001); - assertTrue(rs.getObject(1).equals(42)); - - assertEquals(rs.getInt("a"), 42); - assertEquals(rs.getString("a"), "42"); - assertEquals(rs.getDouble("a"), 42.0, 0.001); - assertTrue(rs.getObject("a").equals(42)); - - assertEquals(rs.getInt(2), 4); - assertEquals(rs.getString(2), "4.2"); - assertEquals(rs.getDouble(2), 4.2, 0.001); - assertTrue(rs.getObject(2).equals(4.2)); - - assertEquals(rs.getInt("b"), 4); - assertEquals(rs.getString("b"), "4.2"); - assertEquals(rs.getDouble("b"), 4.2, 0.001); - assertTrue(rs.getObject("b").equals(4.2)); - - assertFalse(rs.next()); - - rs.close(); - - stmt.close(); - // test duplication - Connection conn2 = conn.unwrap(DuckDBConnection.class).duplicate(); - ResultSet rs_conn2 = conn2.createStatement().executeQuery("SELECT 42"); - rs_conn2.next(); - assertEquals(42, rs_conn2.getInt(1)); - rs_conn2.close(); - conn.close(); - conn2.close(); - } - - public static void test_empty_table() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE a (i iNTEGER)"); - ResultSet rs = stmt.executeQuery("SELECT * FROM a"); - assertFalse(rs.next()); - - assertEquals(assertThrows(() -> rs.getObject(1), SQLException.class), "No row in context"); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_broken_next() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE t0(c0 INT8, c1 VARCHAR)"); - stmt.execute( - "INSERT INTO t0(c1, c0) VALUES (-315929644, 1), (-315929644, -315929644), (-634993846, -1981637379)"); - stmt.execute("INSERT INTO t0(c0, c1) VALUES (-433000283, -433000283)"); - stmt.execute("INSERT INTO t0(c0) VALUES (-995217820)"); - stmt.execute("INSERT INTO t0(c1, c0) VALUES (-315929644, -315929644)"); - - ResultSet rs = stmt.executeQuery("SELECT c0 FROM t0"); - while (rs.next()) { - assertTrue(!rs.getObject(1).equals(null)); - } - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_multiple_connections() throws Exception { - Connection conn1 = DriverManager.getConnection(JDBC_URL); - Statement stmt1 = conn1.createStatement(); - Connection conn2 = DriverManager.getConnection(JDBC_URL); - Statement stmt2 = conn2.createStatement(); - Statement stmt3 = conn2.createStatement(); - - ResultSet rs1 = stmt1.executeQuery("SELECT 42"); - assertTrue(rs1.next()); - assertEquals(42, rs1.getInt(1)); - rs1.close(); - - ResultSet rs2 = stmt2.executeQuery("SELECT 43"); - assertTrue(rs2.next()); - assertEquals(43, rs2.getInt(1)); - - ResultSet rs3 = stmt3.executeQuery("SELECT 44"); - assertTrue(rs3.next()); - assertEquals(44, rs3.getInt(1)); - rs3.close(); - - // creative closing sequence should also work - stmt2.close(); - - rs3 = stmt3.executeQuery("SELECT 44"); - assertTrue(rs3.next()); - assertEquals(44, rs3.getInt(1)); - - stmt2.close(); - rs2.close(); - rs3.close(); - - System.gc(); - System.gc(); - - // stmt1 still works - rs1 = stmt1.executeQuery("SELECT 42"); - assertTrue(rs1.next()); - assertEquals(42, rs1.getInt(1)); - rs1.close(); - - // stmt3 still works - rs3 = stmt3.executeQuery("SELECT 42"); - assertTrue(rs3.next()); - assertEquals(42, rs3.getInt(1)); - rs3.close(); - - conn2.close(); - - stmt3.close(); - - rs2 = null; - rs3 = null; - stmt2 = null; - stmt3 = null; - conn2 = null; - - System.gc(); - System.gc(); - - // stmt1 still works - rs1 = stmt1.executeQuery("SELECT 42"); - assertTrue(rs1.next()); - assertEquals(42, rs1.getInt(1)); - rs1.close(); - conn1.close(); - stmt1.close(); - } - - public static void test_duckdb_timestamp() throws Exception { - - duckdb_timestamp_test(); - - // Store default time zone - TimeZone defaultTZ = TimeZone.getDefault(); - - // Test with different time zones - TimeZone.setDefault(TimeZone.getTimeZone("America/Lima")); - duckdb_timestamp_test(); - - // Test with different time zones - TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin")); - duckdb_timestamp_test(); - - // Restore default time zone - TimeZone.setDefault(defaultTZ); - } - - public static void duckdb_timestamp_test() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - stmt.execute("CREATE TABLE a (ts TIMESTAMP)"); - - // Generate tests without database - Timestamp ts0 = Timestamp.valueOf("1970-01-01 00:00:00"); - Timestamp ts1 = Timestamp.valueOf("2021-07-29 21:13:11"); - Timestamp ts2 = Timestamp.valueOf("2021-07-29 21:13:11.123456"); - Timestamp ts3 = Timestamp.valueOf("1921-07-29 21:13:11"); - Timestamp ts4 = Timestamp.valueOf("1921-07-29 21:13:11.123456"); - - Timestamp cts0 = new DuckDBTimestamp(ts0).toSqlTimestamp(); - Timestamp cts1 = new DuckDBTimestamp(ts1).toSqlTimestamp(); - Timestamp cts2 = new DuckDBTimestamp(ts2).toSqlTimestamp(); - Timestamp cts3 = new DuckDBTimestamp(ts3).toSqlTimestamp(); - Timestamp cts4 = new DuckDBTimestamp(ts4).toSqlTimestamp(); - - assertTrue(ts0.getTime() == cts0.getTime()); - assertTrue(ts0.compareTo(cts0) == 0); - assertTrue(ts1.getTime() == cts1.getTime()); - assertTrue(ts1.compareTo(cts1) == 0); - assertTrue(ts2.getTime() == cts2.getTime()); - assertTrue(ts2.compareTo(cts2) == 0); - assertTrue(ts3.getTime() == cts3.getTime()); - assertTrue(ts3.compareTo(cts3) == 0); - assertTrue(ts4.getTime() == cts4.getTime()); - assertTrue(ts4.compareTo(cts4) == 0); - - assertTrue(DuckDBTimestamp.getMicroseconds(DuckDBTimestamp.toSqlTimestamp(5678912345L)) == 5678912345L); - - DuckDBTimestamp dts4 = new DuckDBTimestamp(ts1); - assertTrue(dts4.toSqlTimestamp().compareTo(ts1) == 0); - DuckDBTimestamp dts5 = new DuckDBTimestamp(ts2); - assertTrue(dts5.toSqlTimestamp().compareTo(ts2) == 0); - - // Insert and read a timestamp - stmt.execute("INSERT INTO a (ts) VALUES ('2005-11-02 07:59:58')"); - ResultSet rs = stmt.executeQuery("SELECT * FROM a"); - assertTrue(rs.next()); - assertEquals(rs.getObject("ts"), Timestamp.valueOf("2005-11-02 07:59:58")); - assertEquals(rs.getTimestamp("ts"), Timestamp.valueOf("2005-11-02 07:59:58")); - - rs.close(); - stmt.close(); - - PreparedStatement ps = conn.prepareStatement("SELECT COUNT(ts) FROM a WHERE ts = ?"); - ps.setTimestamp(1, Timestamp.valueOf("2005-11-02 07:59:58")); - ResultSet rs2 = ps.executeQuery(); - assertTrue(rs2.next()); - assertEquals(rs2.getInt(1), 1); - rs2.close(); - ps.close(); - - ps = conn.prepareStatement("SELECT COUNT(ts) FROM a WHERE ts = ?"); - ps.setObject(1, Timestamp.valueOf("2005-11-02 07:59:58")); - ResultSet rs3 = ps.executeQuery(); - assertTrue(rs3.next()); - assertEquals(rs3.getInt(1), 1); - rs3.close(); - ps.close(); - - ps = conn.prepareStatement("SELECT COUNT(ts) FROM a WHERE ts = ?"); - ps.setObject(1, Timestamp.valueOf("2005-11-02 07:59:58"), Types.TIMESTAMP); - ResultSet rs4 = ps.executeQuery(); - assertTrue(rs4.next()); - assertEquals(rs4.getInt(1), 1); - rs4.close(); - ps.close(); - - Statement stmt2 = conn.createStatement(); - stmt2.execute("INSERT INTO a (ts) VALUES ('1905-11-02 07:59:58.12345')"); - ps = conn.prepareStatement("SELECT COUNT(ts) FROM a WHERE ts = ?"); - ps.setTimestamp(1, Timestamp.valueOf("1905-11-02 07:59:58.12345")); - ResultSet rs5 = ps.executeQuery(); - assertTrue(rs5.next()); - assertEquals(rs5.getInt(1), 1); - rs5.close(); - ps.close(); - - ps = conn.prepareStatement("SELECT ts FROM a WHERE ts = ?"); - ps.setTimestamp(1, Timestamp.valueOf("1905-11-02 07:59:58.12345")); - ResultSet rs6 = ps.executeQuery(); - assertTrue(rs6.next()); - assertEquals(rs6.getTimestamp(1), Timestamp.valueOf("1905-11-02 07:59:58.12345")); - rs6.close(); - ps.close(); - - conn.close(); - } - - public static void test_duckdb_localdatetime() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - stmt.execute("CREATE TABLE x (ts TIMESTAMP)"); - - LocalDateTime ldt = LocalDateTime.of(2021, 1, 18, 21, 20, 7); - - PreparedStatement ps1 = conn.prepareStatement("INSERT INTO x VALUES (?)"); - ps1.setObject(1, ldt); - ps1.execute(); - ps1.close(); - - PreparedStatement ps2 = conn.prepareStatement("SELECT * FROM x"); - ResultSet rs2 = ps2.executeQuery(); - - rs2.next(); - assertEquals(rs2.getTimestamp(1), rs2.getObject(1, Timestamp.class)); - assertEquals(rs2.getObject(1, LocalDateTime.class), ldt); - - rs2.close(); - ps2.close(); - stmt.close(); - conn.close(); - } - - public static void test_duckdb_getObject_with_class() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - stmt.execute("CREATE TABLE b (vchar VARCHAR, bo BOOLEAN, sint SMALLINT, nint INTEGER, bigi BIGINT," - + " flt FLOAT, dbl DOUBLE, dte DATE, tme TIME, ts TIMESTAMP, dec16 DECIMAL(3,1)," - + " dec32 DECIMAL(9,8), dec64 DECIMAL(16,1), dec128 DECIMAL(30,10), tint TINYINT, utint UTINYINT," - + " usint USMALLINT, uint UINTEGER, ubig UBIGINT, hin HUGEINT, uhin UHUGEINT, blo BLOB)"); - stmt.execute( - "INSERT INTO b VALUES ('varchary', true, 6, 42, 666, 42.666, 666.42," - + - " '1970-01-02', '01:00:34', '1970-01-03 03:42:23', 42.2, 1.23456789, 987654321012345.6, 111112222233333.44444, " - + " -4, 200, 50001, 4000111222, 18446744073709551615, 18446744073709551616, " - + " 170141183460469231731687303715884105728, 'yeah'::BLOB)"); - - PreparedStatement ps = conn.prepareStatement("SELECT * FROM b"); - ResultSet rs = ps.executeQuery(); - - rs.next(); - assertEquals(rs.getString(1), rs.getObject(1, String.class)); - assertEquals(rs.getBoolean(2), rs.getObject(2, Boolean.class)); - assertEquals(rs.getShort(3), rs.getObject(3, Short.class)); - assertEquals(rs.getInt(4), rs.getObject(4, Integer.class)); - assertEquals(rs.getLong(5), rs.getObject(5, Long.class)); - assertEquals(rs.getFloat(6), rs.getObject(6, Float.class)); - assertEquals(rs.getDouble(7), rs.getObject(7, Double.class)); - assertEquals(rs.getDate(8), rs.getObject(8, Date.class)); - assertEquals(rs.getTime(9), rs.getObject(9, Time.class)); - assertEquals(rs.getTimestamp(10), rs.getObject(10, Timestamp.class)); - assertEquals(rs.getObject(10, LocalDateTime.class), LocalDateTime.parse("1970-01-03T03:42:23")); - assertEquals(rs.getObject(10, LocalDateTime.class), LocalDateTime.of(1970, 1, 3, 3, 42, 23)); - assertEquals(rs.getBigDecimal(11), rs.getObject(11, BigDecimal.class)); - assertEquals(rs.getBigDecimal(12), rs.getObject(12, BigDecimal.class)); - assertEquals(rs.getBigDecimal(13), rs.getObject(13, BigDecimal.class)); - assertEquals(rs.getBigDecimal(14), rs.getObject(14, BigDecimal.class)); - - // Missing implementations, should never reach assertTrue(false) - try { - rs.getObject(11, Integer.class); - assertTrue(false); - } catch (SQLException e) { - } - - try { - rs.getObject(12, Integer.class); - assertTrue(false); - } catch (SQLException e) { - } - - try { - rs.getObject(13, Integer.class); - assertTrue(false); - } catch (SQLException e) { - } - - try { - rs.getObject(14, Long.class); - assertTrue(false); - } catch (SQLException e) { - } - - try { - rs.getObject(15, BigInteger.class); - assertTrue(false); - } catch (SQLException e) { - } - - try { - rs.getObject(16, BigInteger.class); - assertTrue(false); - } catch (SQLException e) { - } - - try { - rs.getObject(16, Blob.class); - assertTrue(false); - } catch (SQLException e) { - } - - rs.close(); - ps.close(); - stmt.close(); - conn.close(); - } - - public static void test_multiple_statements_execution() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("CREATE TABLE integers(i integer);\n" - + "insert into integers select * from range(10);" - + "select * from integers;"); - int i = 0; - while (rs.next()) { - assertEquals(rs.getInt("i"), i); - i++; - } - assertEquals(i, 10); - } - - public static void test_multiple_statements_exception() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - boolean succ = false; - try { - stmt.executeQuery("CREATE TABLE integers(i integer, i boolean);\n" - + "CREATE TABLE integers2(i integer);\n" - + "insert into integers2 select * from range(10);\n" - + "select * from integers2;"); - succ = true; - } catch (Exception ex) { - assertFalse(succ); - } - } - - public static void test_bigdecimal() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - stmt.execute( - "CREATE TABLE q (id DECIMAL(3,0), dec16 DECIMAL(4,1), dec32 DECIMAL(9,4), dec64 DECIMAL(18,7), dec128 DECIMAL(38,10))"); - - PreparedStatement ps1 = - conn.prepareStatement("INSERT INTO q (id, dec16, dec32, dec64, dec128) VALUES (?, ?, ?, ?, ?)"); - ps1.setObject(1, new BigDecimal("1")); - ps1.setObject(2, new BigDecimal("999.9")); - ps1.setObject(3, new BigDecimal("99999.9999")); - ps1.setObject(4, new BigDecimal("99999999999.9999999")); - ps1.setObject(5, new BigDecimal("9999999999999999999999999999.9999999999")); - ps1.execute(); - - ps1.clearParameters(); - ps1.setBigDecimal(1, new BigDecimal("2")); - ps1.setBigDecimal(2, new BigDecimal("-999.9")); - ps1.setBigDecimal(3, new BigDecimal("-99999.9999")); - ps1.setBigDecimal(4, new BigDecimal("-99999999999.9999999")); - ps1.setBigDecimal(5, new BigDecimal("-9999999999999999999999999999.9999999999")); - ps1.execute(); - - ps1.clearParameters(); - ps1.setObject(1, new BigDecimal("3"), Types.DECIMAL); - ps1.setObject(2, new BigDecimal("-5"), Types.DECIMAL); - ps1.setObject(3, new BigDecimal("-999"), Types.DECIMAL); - ps1.setObject(4, new BigDecimal("-88888888"), Types.DECIMAL); - ps1.setObject(5, new BigDecimal("-123456789654321"), Types.DECIMAL); - ps1.execute(); - ps1.close(); - - stmt.execute("INSERT INTO q (id, dec16, dec32, dec64, dec128) VALUES (4, -0, -0, -0, -0)"); - stmt.execute("INSERT INTO q (id, dec16, dec32, dec64, dec128) VALUES (5, 0, 0, 0, 18446744073709551615)"); - stmt.execute("INSERT INTO q (id, dec16, dec32, dec64, dec128) VALUES (6, 0, 0, 0, 18446744073709551616)"); - stmt.execute("INSERT INTO q (id, dec16, dec32, dec64, dec128) VALUES (7, 0, 0, 0, -18446744073709551615)"); - stmt.execute("INSERT INTO q (id, dec16, dec32, dec64, dec128) VALUES (8, 0, 0, 0, -18446744073709551616)"); - stmt.close(); - - PreparedStatement ps = conn.prepareStatement("SELECT * FROM q ORDER BY id"); - ResultSet rs = ps.executeQuery(); - while (rs.next()) { - assertEquals(rs.getBigDecimal(1), rs.getObject(1, BigDecimal.class)); - assertEquals(rs.getBigDecimal(2), rs.getObject(2, BigDecimal.class)); - assertEquals(rs.getBigDecimal(3), rs.getObject(3, BigDecimal.class)); - assertEquals(rs.getBigDecimal(4), rs.getObject(4, BigDecimal.class)); - assertEquals(rs.getBigDecimal(5), rs.getObject(5, BigDecimal.class)); - } - - rs.close(); - - ResultSet rs2 = ps.executeQuery(); - DuckDBResultSetMetaData meta = rs2.getMetaData().unwrap(DuckDBResultSetMetaData.class); - rs2.next(); - assertEquals(rs2.getBigDecimal(1), new BigDecimal("1")); - assertEquals(rs2.getBigDecimal(2), new BigDecimal("999.9")); - assertEquals(rs2.getBigDecimal(3), new BigDecimal("99999.9999")); - assertEquals(rs2.getBigDecimal(4), new BigDecimal("99999999999.9999999")); - assertEquals(rs2.getBigDecimal(5), new BigDecimal("9999999999999999999999999999.9999999999")); - rs2.next(); - assertEquals(rs2.getBigDecimal(1), new BigDecimal("2")); - assertEquals(rs2.getBigDecimal(2), new BigDecimal("-999.9")); - assertEquals(rs2.getBigDecimal(3), new BigDecimal("-99999.9999")); - assertEquals(rs2.getBigDecimal(4), new BigDecimal("-99999999999.9999999")); - assertEquals(rs2.getBigDecimal(5), new BigDecimal("-9999999999999999999999999999.9999999999")); - rs2.next(); - assertEquals(rs2.getBigDecimal(1), new BigDecimal("3")); - assertEquals(rs2.getBigDecimal(2), new BigDecimal("-5.0")); - assertEquals(rs2.getBigDecimal(3), new BigDecimal("-999.0000")); - assertEquals(rs2.getBigDecimal(4), new BigDecimal("-88888888.0000000")); - assertEquals(rs2.getBigDecimal(5), new BigDecimal("-123456789654321.0000000000")); - rs2.next(); - assertEquals(rs2.getBigDecimal(1), new BigDecimal("4")); - assertEquals(rs2.getBigDecimal(2), new BigDecimal("-0.0")); - assertEquals(rs2.getBigDecimal(3), new BigDecimal("-0.0000")); - assertEquals(rs2.getBigDecimal(4), new BigDecimal("-0.0000000")); - assertEquals(rs2.getBigDecimal(5), new BigDecimal("-0.0000000000")); - rs2.next(); - assertEquals(rs2.getBigDecimal(1), new BigDecimal("5")); - assertEquals(rs2.getBigDecimal(5), new BigDecimal("18446744073709551615.0000000000")); - rs2.next(); - assertEquals(rs2.getBigDecimal(1), new BigDecimal("6")); - assertEquals(rs2.getBigDecimal(5), new BigDecimal("18446744073709551616.0000000000")); - rs2.next(); - assertEquals(rs2.getBigDecimal(1), new BigDecimal("7")); - assertEquals(rs2.getBigDecimal(5), new BigDecimal("-18446744073709551615.0000000000")); - rs2.next(); - assertEquals(rs2.getBigDecimal(1), new BigDecimal("8")); - assertEquals(rs2.getBigDecimal(5), new BigDecimal("-18446744073709551616.0000000000")); - rs2.close(); - - // Metadata tests - assertEquals(Types.DECIMAL, meta.type_to_int(DuckDBColumnType.DECIMAL)); - assertTrue(BigDecimal.class.getName().equals(meta.getColumnClassName(1))); - assertTrue(BigDecimal.class.getName().equals(meta.getColumnClassName(2))); - assertTrue(BigDecimal.class.getName().equals(meta.getColumnClassName(3))); - assertTrue(BigDecimal.class.getName().equals(meta.getColumnClassName(4))); - - assertEquals(3, meta.getPrecision(1)); - assertEquals(0, meta.getScale(1)); - assertEquals(4, meta.getPrecision(2)); - assertEquals(1, meta.getScale(2)); - assertEquals(9, meta.getPrecision(3)); - assertEquals(4, meta.getScale(3)); - assertEquals(18, meta.getPrecision(4)); - assertEquals(7, meta.getScale(4)); - assertEquals(38, meta.getPrecision(5)); - assertEquals(10, meta.getScale(5)); - - conn.close(); - } - - // Longer, resource intensive test - might be commented out for a quick test run - public static void test_lots_of_timestamps() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - stmt.execute("CREATE TABLE a (ts TIMESTAMP)"); - - Timestamp ts = Timestamp.valueOf("1970-01-01 01:01:01"); - - for (long i = 134234533L; i < 13423453300L; i = i + 735127) { - ts.setTime(i); - stmt.execute("INSERT INTO a (ts) VALUES ('" + ts + "')"); - } - - stmt.close(); - - for (long i = 134234533L; i < 13423453300L; i = i + 735127) { - PreparedStatement ps = conn.prepareStatement("SELECT COUNT(ts) FROM a WHERE ts = ?"); - ps.setTimestamp(1, ts); - ResultSet rs = ps.executeQuery(); - assertTrue(rs.next()); - assertEquals(rs.getInt(1), 1); - rs.close(); - ps.close(); - } - - conn.close(); - } - - public static void test_set_date() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); - PreparedStatement stmt = conn.prepareStatement("SELECT ?")) { - Date date = Date.valueOf("1969-01-01"); - stmt.setDate(1, date); - ResultSet rs = stmt.executeQuery(); - while (rs.next()) { - assertEquals(rs.getDate(1), date); - } - } - } - - public static void test_lots_of_decimals() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - // Create the table - stmt.execute("CREATE TABLE q (id DECIMAL(4,0),dec32 DECIMAL(9,4),dec64 DECIMAL(18,7),dec128 DECIMAL(38,10))"); - stmt.close(); - - // Create the INSERT prepared statement we will use - PreparedStatement ps1 = conn.prepareStatement("INSERT INTO q (id, dec32, dec64, dec128) VALUES (?, ?, ?, ?)"); - - // Create the Java decimals we will be inserting - BigDecimal id_org = new BigDecimal("1"); - BigDecimal dec32_org = new BigDecimal("99999.9999"); - BigDecimal dec64_org = new BigDecimal("99999999999.9999999"); - BigDecimal dec128_org = new BigDecimal("9999999999999999999999999999.9999999999"); - - // Insert the initial values - ps1.setObject(1, id_org); - ps1.setObject(2, dec32_org); - ps1.setObject(3, dec64_org); - ps1.setObject(4, dec128_org); - // This does not have a result set - assertFalse(ps1.execute()); - - // Create the SELECT prepared statement we will use - PreparedStatement ps2 = conn.prepareStatement("SELECT * FROM q WHERE id = ?"); - BigDecimal multiplicant = new BigDecimal("0.987"); - - BigDecimal dec32; - BigDecimal dec64; - BigDecimal dec128; - - ResultSet select_result; - - for (int i = 2; i < 10000; i++) { - ps2.setObject(1, new BigDecimal(i - 1)); - - // Verify that both the 'getObject' and the 'getBigDecimal' methods return the same value\ - - select_result = ps2.executeQuery(); - assertTrue(select_result.next()); - dec32 = select_result.getObject(2, BigDecimal.class); - dec64 = select_result.getObject(3, BigDecimal.class); - dec128 = select_result.getObject(4, BigDecimal.class); - assertEquals(dec32_org, dec32); - assertEquals(dec64_org, dec64); - assertEquals(dec128_org, dec128); - select_result.close(); - - select_result = ps2.executeQuery(); - assertTrue(select_result.next()); - dec32 = select_result.getBigDecimal(2); - dec64 = select_result.getBigDecimal(3); - dec128 = select_result.getBigDecimal(4); - assertEquals(dec32_org, dec32); - assertEquals(dec64_org, dec64); - assertEquals(dec128_org, dec128); - select_result.close(); - - // Apply the modification for the next iteration - - dec32_org = dec32_org.multiply(multiplicant).setScale(4, java.math.RoundingMode.HALF_EVEN); - dec64_org = dec64_org.multiply(multiplicant).setScale(7, java.math.RoundingMode.HALF_EVEN); - dec128_org = dec128_org.multiply(multiplicant).setScale(10, java.math.RoundingMode.HALF_EVEN); - - ps1.clearParameters(); - ps1.setObject(1, new BigDecimal(i)); - ps1.setObject(2, dec32_org); - ps1.setObject(3, dec64_org); - ps1.setObject(4, dec128_org); - assertFalse(ps1.execute()); - - ps2.clearParameters(); - } - ps1.close(); - ps2.close(); - conn.close(); - } - - public static void test_big_data() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - int rows = 10000; - stmt.execute("CREATE TABLE a (i iNTEGER)"); - for (int i = 0; i < rows; i++) { - stmt.execute("INSERT INTO a VALUES (" + i + ")"); - } - - ResultSet rs = stmt.executeQuery( - "SELECT CAST(i AS SMALLINT), CAST(i AS INTEGER), CAST(i AS BIGINT), CAST(i AS FLOAT), CAST(i AS DOUBLE), CAST(i as STRING), NULL FROM a"); - int count = 0; - while (rs.next()) { - for (int col = 1; col <= 6; col++) { - assertEquals(rs.getShort(col), (short) count); - assertFalse(rs.wasNull()); - assertEquals(rs.getInt(col), (int) count); - assertFalse(rs.wasNull()); - assertEquals(rs.getLong(col), (long) count); - assertFalse(rs.wasNull()); - assertEquals(rs.getFloat(col), (float) count, 0.001); - assertFalse(rs.wasNull()); - assertEquals(rs.getDouble(col), (double) count, 0.001); - assertFalse(rs.wasNull()); - assertEquals(Double.parseDouble(rs.getString(col)), (double) count, 0.001); - assertFalse(rs.wasNull()); - Object o = rs.getObject(col); - assertFalse(rs.wasNull()); - } - short null_short = rs.getShort(7); - assertTrue(rs.wasNull()); - int null_int = rs.getInt(7); - assertTrue(rs.wasNull()); - long null_long = rs.getLong(7); - assertTrue(rs.wasNull()); - float null_float = rs.getFloat(7); - assertTrue(rs.wasNull()); - double null_double = rs.getDouble(7); - assertTrue(rs.wasNull()); - String null_string = rs.getString(7); - assertTrue(rs.wasNull()); - Object null_object = rs.getObject(7); - assertTrue(rs.wasNull()); - - count++; - } - - assertEquals(rows, count); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_crash_bug496() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE t0(c0 BOOLEAN, c1 INT)"); - stmt.execute("CREATE INDEX i0 ON t0(c1, c0)"); - stmt.execute("INSERT INTO t0(c1) VALUES (0)"); - stmt.close(); - conn.close(); - } - - public static void test_tablepragma_bug491() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE t0(c0 INT)"); - - ResultSet rs = stmt.executeQuery("PRAGMA table_info('t0')"); - assertTrue(rs.next()); - - assertEquals(rs.getInt("cid"), 0); - assertEquals(rs.getString("name"), "c0"); - assertEquals(rs.getString("type"), "INTEGER"); - assertEquals(rs.getBoolean("notnull"), false); - rs.getString("dflt_value"); - // assertTrue(rs.wasNull()); - assertEquals(rs.getBoolean("pk"), false); - - assertFalse(rs.next()); - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_nulltruth_bug489() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE t0(c0 INT)"); - stmt.execute("INSERT INTO t0(c0) VALUES (0)"); - - ResultSet rs = stmt.executeQuery("SELECT * FROM t0 WHERE NOT(NULL OR TRUE)"); - assertFalse(rs.next()); - - rs = stmt.executeQuery("SELECT NOT(NULL OR TRUE)"); - assertTrue(rs.next()); - boolean res = rs.getBoolean(1); - assertEquals(res, false); - assertFalse(rs.wasNull()); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_empty_prepare_bug500() throws Exception { - String fileContent = "CREATE TABLE t0(c0 VARCHAR, c1 DOUBLE);\n" - + "CREATE TABLE t1(c0 DOUBLE, PRIMARY KEY(c0));\n" - + "INSERT INTO t0(c0) VALUES (0), (0), (0), (0);\n" - + "INSERT INTO t0(c0) VALUES (NULL), (NULL);\n" - + "INSERT INTO t1(c0) VALUES (0), (1);\n" - + "\n" - + "SELECT t0.c0 FROM t0, t1;"; - Connection con = DriverManager.getConnection(JDBC_URL); - for (String s : fileContent.split("\n")) { - Statement st = con.createStatement(); - try { - st.execute(s); - } catch (SQLException e) { - // e.printStackTrace(); - } - } - con.close(); - } - - public static void test_borked_string_bug539() throws Exception { - Connection con = DriverManager.getConnection(JDBC_URL); - Statement s = con.createStatement(); - s.executeUpdate("CREATE TABLE t0 (c0 VARCHAR)"); - String q = String.format("INSERT INTO t0 VALUES('%c')", 55995); - s.executeUpdate(q); - s.close(); - con.close(); - } - - public static void test_prepare_types() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - - PreparedStatement ps = conn.prepareStatement( - "SELECT CAST(? AS BOOLEAN) c1, CAST(? AS TINYINT) c2, CAST(? AS SMALLINT) c3, CAST(? AS INTEGER) c4, CAST(? AS BIGINT) c5, CAST(? AS FLOAT) c6, CAST(? AS DOUBLE) c7, CAST(? AS STRING) c8"); - ps.setBoolean(1, true); - ps.setByte(2, (byte) 42); - ps.setShort(3, (short) 43); - ps.setInt(4, 44); - ps.setLong(5, (long) 45); - ps.setFloat(6, (float) 4.6); - ps.setDouble(7, (double) 4.7); - ps.setString(8, "four eight"); - - ResultSet rs = ps.executeQuery(); - assertTrue(rs.next()); - assertEquals(rs.getBoolean(1), true); - assertEquals(rs.getByte(2), (byte) 42); - assertEquals(rs.getShort(3), (short) 43); - assertEquals(rs.getInt(4), 44); - assertEquals(rs.getLong(5), (long) 45); - assertEquals(rs.getFloat(6), 4.6, 0.001); - assertEquals(rs.getDouble(7), 4.7, 0.001); - assertEquals(rs.getString(8), "four eight"); - rs.close(); - - ps.setBoolean(1, false); - ps.setByte(2, (byte) 82); - ps.setShort(3, (short) 83); - ps.setInt(4, 84); - ps.setLong(5, (long) 85); - ps.setFloat(6, (float) 8.6); - ps.setDouble(7, (double) 8.7); - ps.setString(8, "eight eight\n\t"); - - rs = ps.executeQuery(); - assertTrue(rs.next()); - assertEquals(rs.getBoolean(1), false); - assertEquals(rs.getByte(2), (byte) 82); - assertEquals(rs.getShort(3), (short) 83); - assertEquals(rs.getInt(4), 84); - assertEquals(rs.getLong(5), (long) 85); - assertEquals(rs.getFloat(6), 8.6, 0.001); - assertEquals(rs.getDouble(7), 8.7, 0.001); - assertEquals(rs.getString(8), "eight eight\n\t"); - rs.close(); - - ps.setObject(1, false); - ps.setObject(2, (byte) 82); - ps.setObject(3, (short) 83); - ps.setObject(4, 84); - ps.setObject(5, (long) 85); - ps.setObject(6, (float) 8.6); - ps.setObject(7, (double) 8.7); - ps.setObject(8, "𫝼🔥😜䭔🟢"); - - rs = ps.executeQuery(); - assertTrue(rs.next()); - assertEquals(rs.getBoolean(1), false); - assertEquals(rs.getByte(2), (byte) 82); - assertEquals(rs.getShort(3), (short) 83); - assertEquals(rs.getInt(4), 84); - assertEquals(rs.getLong(5), (long) 85); - assertEquals(rs.getFloat(6), 8.6, 0.001); - assertEquals(rs.getDouble(7), 8.7, 0.001); - assertEquals(rs.getString(8), "𫝼🔥😜䭔🟢"); - - ps.setNull(1, 0); - ps.setNull(2, 0); - ps.setNull(3, 0); - ps.setNull(4, 0); - ps.setNull(5, 0); - ps.setNull(6, 0); - ps.setNull(7, 0); - ps.setNull(8, 0); - - rs = ps.executeQuery(); - assertTrue(rs.next()); - assertEquals(8, rs.getMetaData().getColumnCount()); - for (int c = 1; c <= rs.getMetaData().getColumnCount(); c++) { - assertNull(rs.getObject(c)); - assertTrue(rs.wasNull()); - assertNull(rs.getString(c)); - assertTrue(rs.wasNull()); - } - - rs.close(); - ps.close(); - conn.close(); - } - - public static void test_prepare_insert() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - - conn.createStatement().executeUpdate( - "create table ctstable1 (TYPE_ID int, TYPE_DESC varchar(32), primary key(TYPE_ID))"); - PreparedStatement pStmt1 = conn.prepareStatement("insert into ctstable1 values(?, ?)"); - for (int j = 1; j <= 10; j++) { - String sTypeDesc = "Type-" + j; - int newType = j; - pStmt1.setInt(1, newType); - pStmt1.setString(2, sTypeDesc); - int count = pStmt1.executeUpdate(); - assertEquals(count, 1); - } - pStmt1.close(); - - conn.createStatement().executeUpdate( - "create table ctstable2 (KEY_ID int, COF_NAME varchar(32), PRICE float, TYPE_ID int, primary key(KEY_ID) )"); - - PreparedStatement pStmt = conn.prepareStatement("insert into ctstable2 values(?, ?, ?, ?)"); - for (int i = 1; i <= 10; i++) { - // Perform the insert(s) - int newKey = i; - String newName = "xx" - + "-" + i; - float newPrice = i + (float) .00; - int newType = i % 5; - if (newType == 0) - newType = 5; - pStmt.setInt(1, newKey); - pStmt.setString(2, newName); - pStmt.setFloat(3, newPrice); - pStmt.setInt(4, newType); - pStmt.executeUpdate(); - } - - pStmt.close(); - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM ctstable1"); - assertTrue(rs.next()); - assertEquals(rs.getInt(1), 10); - rs.close(); - - stmt.executeUpdate("DELETE FROM ctstable1"); - - rs = stmt.executeQuery("SELECT COUNT(*) FROM ctstable1"); - assertTrue(rs.next()); - assertEquals(rs.getInt(1), 0); - rs.close(); - - stmt.close(); - - conn.close(); - } - - public static void test_read_only() throws Exception { - Path database_file = Files.createTempFile("duckdb-jdbc-test-", ".duckdb"); - Files.deleteIfExists(database_file); - - String jdbc_url = JDBC_URL + database_file; - Properties ro_prop = new Properties(); - ro_prop.setProperty("duckdb.read_only", "true"); - - Connection conn_rw = DriverManager.getConnection(jdbc_url); - assertFalse(conn_rw.isReadOnly()); - assertFalse(conn_rw.getMetaData().isReadOnly()); - Statement stmt = conn_rw.createStatement(); - stmt.execute("CREATE TABLE test (i INTEGER)"); - stmt.execute("INSERT INTO test VALUES (42)"); - stmt.close(); - - // Verify we can open additional write connections - // Using the Driver - try (Connection conn = DriverManager.getConnection(jdbc_url); Statement stmt1 = conn.createStatement(); - ResultSet rs1 = stmt1.executeQuery("SELECT * FROM test")) { - rs1.next(); - assertEquals(rs1.getInt(1), 42); - } - // Using the direct API - try (Connection conn = conn_rw.unwrap(DuckDBConnection.class).duplicate(); - Statement stmt1 = conn.createStatement(); ResultSet rs1 = stmt1.executeQuery("SELECT * FROM test")) { - rs1.next(); - assertEquals(rs1.getInt(1), 42); - } - - // At this time, mixing read and write connections on Windows doesn't work - // Read-only when we already have a read-write - // try (Connection conn = DriverManager.getConnection(jdbc_url, ro_prop); - // Statement stmt1 = conn.createStatement(); - // ResultSet rs1 = stmt1.executeQuery("SELECT * FROM test")) { - // rs1.next(); - // assertEquals(rs1.getInt(1), 42); - // } - - conn_rw.close(); - - try (Statement ignored = conn_rw.createStatement()) { - fail("Connection was already closed; shouldn't be able to create a statement"); - } catch (SQLException e) { - } - - try (Connection ignored = conn_rw.unwrap(DuckDBConnection.class).duplicate()) { - fail("Connection was already closed; shouldn't be able to duplicate"); - } catch (SQLException e) { - } - - // // we can create two parallel read only connections and query them, too - try (Connection conn_ro1 = DriverManager.getConnection(jdbc_url, ro_prop); - Connection conn_ro2 = DriverManager.getConnection(jdbc_url, ro_prop)) { - - assertTrue(conn_ro1.isReadOnly()); - assertTrue(conn_ro1.getMetaData().isReadOnly()); - assertTrue(conn_ro2.isReadOnly()); - assertTrue(conn_ro2.getMetaData().isReadOnly()); - - try (Statement stmt1 = conn_ro1.createStatement(); - ResultSet rs1 = stmt1.executeQuery("SELECT * FROM test")) { - rs1.next(); - assertEquals(rs1.getInt(1), 42); - } - - try (Statement stmt2 = conn_ro2.createStatement(); - ResultSet rs2 = stmt2.executeQuery("SELECT * FROM test")) { - rs2.next(); - assertEquals(rs2.getInt(1), 42); - } - } - } - - public static void test_hugeint() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs = stmt.executeQuery( - "SELECT 42::hugeint hi1, -42::hugeint hi2, 454564646545646546545646545::hugeint hi3, -454564646545646546545646545::hugeint hi4"); - assertTrue(rs.next()); - assertEquals(rs.getObject("hi1"), new BigInteger("42")); - assertEquals(rs.getObject("hi2"), new BigInteger("-42")); - assertEquals(rs.getLong("hi1"), 42L); - assertEquals(rs.getLong("hi2"), -42L); - assertEquals(rs.getObject("hi3"), new BigInteger("454564646545646546545646545")); - assertEquals(rs.getObject("hi4"), new BigInteger("-454564646545646546545646545")); - assertTrue(rs.getBigDecimal("hi1").compareTo(new BigDecimal("42")) == 0); - assertTrue(rs.getBigDecimal("hi2").compareTo(new BigDecimal("-42")) == 0); - assertTrue(rs.getBigDecimal("hi3").compareTo(new BigDecimal("454564646545646546545646545")) == 0); - assertTrue(rs.getBigDecimal("hi4").compareTo(new BigDecimal("-454564646545646546545646545")) == 0); - assertFalse(rs.next()); - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_temporal_types() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs = stmt.executeQuery( - "SELECT '2019-11-26 21:11:00'::timestamp ts, '2019-11-26'::date dt, interval '5 days' iv, '21:11:00'::time te"); - assertTrue(rs.next()); - assertEquals(rs.getObject("ts"), Timestamp.valueOf("2019-11-26 21:11:00")); - assertEquals(rs.getTimestamp("ts"), Timestamp.valueOf("2019-11-26 21:11:00")); - - assertEquals(rs.getObject("dt"), LocalDate.parse("2019-11-26")); - assertEquals(rs.getDate("dt"), Date.valueOf("2019-11-26")); - - assertEquals(rs.getObject("iv"), "5 days"); - - assertEquals(rs.getObject("te"), LocalTime.parse("21:11:00")); - assertEquals(rs.getTime("te"), Time.valueOf("21:11:00")); - - assertFalse(rs.next()); - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_calendar_types() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - // Nail down the location for test portability. - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles"), Locale.US); - - ResultSet rs = stmt.executeQuery( - "SELECT '2019-11-26 21:11:43.123456'::timestamp ts, '2019-11-26'::date dt, '21:11:00'::time te"); - assertTrue(rs.next()); - assertEquals(rs.getTimestamp("ts", cal), Timestamp.from(Instant.ofEpochSecond(1574802703, 123456000))); - - assertEquals(rs.getDate("dt", cal), Date.valueOf("2019-11-26")); - - assertEquals(rs.getTime("te", cal), Time.valueOf("21:11:00")); - - assertFalse(rs.next()); - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_temporal_nulls() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs = stmt.executeQuery("SELECT NULL::timestamp ts, NULL::date dt, NULL::time te"); - assertTrue(rs.next()); - assertNull(rs.getObject("ts")); - assertNull(rs.getTimestamp("ts")); - - assertNull(rs.getObject("dt")); - assertNull(rs.getDate("dt")); - - assertNull(rs.getObject("te")); - assertNull(rs.getTime("te")); - - assertFalse(rs.next()); - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_evil_date() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs = stmt.executeQuery("SELECT '5131-08-05 (BC)'::date d"); - - assertTrue(rs.next()); - assertEquals(rs.getDate("d"), Date.valueOf(LocalDate.of(-5130, 8, 5))); - - assertFalse(rs.next()); - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_decimal() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs = stmt.executeQuery("SELECT '1.23'::decimal(3,2) d"); - - assertTrue(rs.next()); - assertEquals(rs.getDouble("d"), 1.23); - - assertFalse(rs.next()); - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_schema_reflection() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - stmt.execute("CREATE TABLE a (i INTEGER)"); - stmt.execute("CREATE VIEW b AS SELECT i::STRING AS j FROM a"); - stmt.execute("COMMENT ON TABLE a IS 'a table'"); - stmt.execute("COMMENT ON COLUMN a.i IS 'a column'"); - stmt.execute("COMMENT ON VIEW b IS 'a view'"); - stmt.execute("COMMENT ON COLUMN b.j IS 'a column'"); - - DatabaseMetaData md = conn.getMetaData(); - ResultSet rs; - - rs = md.getCatalogs(); - assertTrue(rs.next()); - assertTrue(rs.getObject("TABLE_CAT") != null); - rs.close(); - - rs = md.getSchemas(null, "ma%"); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_SCHEM"), DuckDBConnection.DEFAULT_SCHEMA); - assertTrue(rs.getObject("TABLE_CATALOG") != null); - assertEquals(rs.getString(1), DuckDBConnection.DEFAULT_SCHEMA); - rs.close(); - - rs = md.getSchemas(null, "xxx"); - assertFalse(rs.next()); - rs.close(); - - rs = md.getTables(null, null, "%", null); - - assertTrue(rs.next()); - assertTrue(rs.getObject("TABLE_CAT") != null); - assertEquals(rs.getString("TABLE_SCHEM"), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString(2), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString("TABLE_NAME"), "a"); - assertEquals(rs.getString(3), "a"); - assertEquals(rs.getString("TABLE_TYPE"), "BASE TABLE"); - assertEquals(rs.getString(4), "BASE TABLE"); - assertEquals(rs.getObject("REMARKS"), "a table"); - assertEquals(rs.getObject(5), "a table"); - assertNull(rs.getObject("TYPE_CAT")); - assertNull(rs.getObject(6)); - assertNull(rs.getObject("TYPE_SCHEM")); - assertNull(rs.getObject(7)); - assertNull(rs.getObject("TYPE_NAME")); - assertNull(rs.getObject(8)); - assertNull(rs.getObject("SELF_REFERENCING_COL_NAME")); - assertNull(rs.getObject(9)); - assertNull(rs.getObject("REF_GENERATION")); - assertNull(rs.getObject(10)); - - assertTrue(rs.next()); - assertTrue(rs.getObject("TABLE_CAT") != null); - assertEquals(rs.getString("TABLE_SCHEM"), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString(2), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString("TABLE_NAME"), "b"); - assertEquals(rs.getString(3), "b"); - assertEquals(rs.getString("TABLE_TYPE"), "VIEW"); - assertEquals(rs.getString(4), "VIEW"); - assertEquals(rs.getObject("REMARKS"), "a view"); - assertEquals(rs.getObject(5), "a view"); - assertNull(rs.getObject("TYPE_CAT")); - assertNull(rs.getObject(6)); - assertNull(rs.getObject("TYPE_SCHEM")); - assertNull(rs.getObject(7)); - assertNull(rs.getObject("TYPE_NAME")); - assertNull(rs.getObject(8)); - assertNull(rs.getObject("SELF_REFERENCING_COL_NAME")); - assertNull(rs.getObject(9)); - assertNull(rs.getObject("REF_GENERATION")); - assertNull(rs.getObject(10)); - - assertFalse(rs.next()); - rs.close(); - - rs = md.getTables(null, DuckDBConnection.DEFAULT_SCHEMA, "a", null); - - assertTrue(rs.next()); - assertTrue(rs.getObject("TABLE_CAT") != null); - assertEquals(rs.getString("TABLE_SCHEM"), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString(2), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString("TABLE_NAME"), "a"); - assertEquals(rs.getString(3), "a"); - assertEquals(rs.getString("TABLE_TYPE"), "BASE TABLE"); - assertEquals(rs.getString(4), "BASE TABLE"); - assertEquals(rs.getObject("REMARKS"), "a table"); - assertEquals(rs.getObject(5), "a table"); - assertNull(rs.getObject("TYPE_CAT")); - assertNull(rs.getObject(6)); - assertNull(rs.getObject("TYPE_SCHEM")); - assertNull(rs.getObject(7)); - assertNull(rs.getObject("TYPE_NAME")); - assertNull(rs.getObject(8)); - assertNull(rs.getObject("SELF_REFERENCING_COL_NAME")); - assertNull(rs.getObject(9)); - assertNull(rs.getObject("REF_GENERATION")); - assertNull(rs.getObject(10)); - - rs.close(); - - rs = md.getTables(null, DuckDBConnection.DEFAULT_SCHEMA, "xxx", null); - assertFalse(rs.next()); - rs.close(); - - rs = md.getColumns(null, null, "a", null); - assertTrue(rs.next()); - assertTrue(rs.getObject("TABLE_CAT") != null); - assertEquals(rs.getString("TABLE_SCHEM"), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString(2), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString("TABLE_NAME"), "a"); - assertEquals(rs.getString(3), "a"); - assertEquals(rs.getString("COLUMN_NAME"), "i"); - assertEquals(rs.getString("REMARKS"), "a column"); - assertEquals(rs.getString(4), "i"); - assertEquals(rs.getInt("DATA_TYPE"), Types.INTEGER); - assertEquals(rs.getInt(5), Types.INTEGER); - assertEquals(rs.getString("TYPE_NAME"), "INTEGER"); - assertEquals(rs.getString(6), "INTEGER"); - assertNull(rs.getObject("COLUMN_SIZE")); - assertNull(rs.getObject(7)); - assertNull(rs.getObject("BUFFER_LENGTH")); - assertNull(rs.getObject(8)); - - // and so on but whatever - - rs.close(); - - rs = md.getColumns(null, DuckDBConnection.DEFAULT_SCHEMA, "a", "i"); - assertTrue(rs.next()); - assertTrue(rs.getObject("TABLE_CAT") != null); - ; - assertEquals(rs.getString("TABLE_SCHEM"), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString(2), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString("TABLE_NAME"), "a"); - assertEquals(rs.getString(3), "a"); - assertEquals(rs.getString("COLUMN_NAME"), "i"); - assertEquals(rs.getString(4), "i"); - assertEquals(rs.getInt("DATA_TYPE"), Types.INTEGER); - assertEquals(rs.getInt(5), Types.INTEGER); - assertEquals(rs.getString("TYPE_NAME"), "INTEGER"); - assertEquals(rs.getString(6), "INTEGER"); - assertNull(rs.getObject("COLUMN_SIZE")); - assertNull(rs.getObject(7)); - assertNull(rs.getObject("BUFFER_LENGTH")); - assertNull(rs.getObject(8)); - assertEquals(rs.getString("REMARKS"), "a column"); - - rs.close(); - - // try with catalog as well - rs = md.getColumns(conn.getCatalog(), DuckDBConnection.DEFAULT_SCHEMA, "a", "i"); - assertTrue(rs.next()); - assertTrue(rs.getObject("TABLE_CAT") != null); - assertEquals(rs.getString("TABLE_SCHEM"), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString(2), DuckDBConnection.DEFAULT_SCHEMA); - assertEquals(rs.getString("TABLE_NAME"), "a"); - assertEquals(rs.getString(3), "a"); - assertEquals(rs.getString("COLUMN_NAME"), "i"); - assertEquals(rs.getString(4), "i"); - assertEquals(rs.getInt("DATA_TYPE"), Types.INTEGER); - assertEquals(rs.getInt(5), Types.INTEGER); - assertEquals(rs.getString("TYPE_NAME"), "INTEGER"); - assertEquals(rs.getString(6), "INTEGER"); - assertNull(rs.getObject("COLUMN_SIZE")); - assertNull(rs.getObject(7)); - assertNull(rs.getObject("BUFFER_LENGTH")); - assertNull(rs.getObject(8)); - - rs.close(); - - rs = md.getColumns(null, "xxx", "a", "i"); - assertFalse(rs.next()); - rs.close(); - - rs = md.getColumns(null, DuckDBConnection.DEFAULT_SCHEMA, "xxx", "i"); - assertFalse(rs.next()); - rs.close(); - - rs = md.getColumns(null, DuckDBConnection.DEFAULT_SCHEMA, "a", "xxx"); - assertFalse(rs.next()); - rs.close(); - - conn.close(); - } - - public static void test_time_tz() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement s = conn.createStatement()) { - s.executeUpdate("create table t (i time with time zone)"); - try (ResultSet rs = conn.getMetaData().getColumns(null, "%", "t", "i");) { - rs.next(); - - assertEquals(rs.getString("TYPE_NAME"), "TIME WITH TIME ZONE"); - assertEquals(rs.getInt("DATA_TYPE"), Types.TIME_WITH_TIMEZONE); - } - - s.execute( - "INSERT INTO t VALUES ('01:01:00'), ('01:02:03+12:30:45'), ('04:05:06-03:10'), ('07:08:09+15:59:59');"); - try (ResultSet rs = s.executeQuery("SELECT * FROM t")) { - rs.next(); - assertEquals(rs.getObject(1), OffsetTime.of(LocalTime.of(1, 1), ZoneOffset.UTC)); - rs.next(); - assertEquals(rs.getObject(1), - OffsetTime.of(LocalTime.of(1, 2, 3), ZoneOffset.ofHoursMinutesSeconds(12, 30, 45))); - rs.next(); - assertEquals(rs.getObject(1), - OffsetTime.of(LocalTime.of(4, 5, 6), ZoneOffset.ofHoursMinutesSeconds(-3, -10, 0))); - rs.next(); - assertEquals(rs.getObject(1), - OffsetTime.of(LocalTime.of(7, 8, 9), ZoneOffset.ofHoursMinutesSeconds(15, 59, 59))); - } - } - } - - public static void test_get_tables_with_current_catalog() throws Exception { - ResultSet resultSet = null; - Connection conn = DriverManager.getConnection(JDBC_URL); - final String currentCatalog = conn.getCatalog(); - DatabaseMetaData databaseMetaData = conn.getMetaData(); - - Statement statement = conn.createStatement(); - statement.execute("CREATE TABLE T1(ID INT)"); - // verify that the catalog argument is supported and does not throw - try { - resultSet = databaseMetaData.getTables(currentCatalog, null, "%", null); - } catch (SQLException ex) { - assertFalse(ex.getMessage().startsWith("Actual catalog argument is not supported")); - } - assertTrue(resultSet.next(), "getTables should return exactly 1 table"); - final String returnedCatalog = resultSet.getString("TABLE_CAT"); - assertTrue( - currentCatalog.equals(returnedCatalog), - String.format("Returned catalog %s should equal current catalog %s", returnedCatalog, currentCatalog)); - assertTrue(resultSet.next() == false, "getTables should return exactly 1 table"); - - resultSet.close(); - } - - public static void test_get_tables_with_attached_catalog() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - final String currentCatalog = conn.getCatalog(); - DatabaseMetaData databaseMetaData = conn.getMetaData(); - Statement statement = conn.createStatement(); - - // create one table in the current catalog - final String TABLE_NAME1 = "T1"; - statement.execute(String.format("CREATE TABLE %s(ID INT)", TABLE_NAME1)); - - // create one table in an attached catalog - String returnedCatalog, returnedTableName; - ResultSet resultSet = null; - final String ATTACHED_CATALOG = "ATTACHED_CATALOG"; - final String TABLE_NAME2 = "T2"; - statement.execute(String.format("ATTACH '' AS \"%s\"", ATTACHED_CATALOG)); - statement.execute(String.format("CREATE TABLE %s.%s(ID INT)", ATTACHED_CATALOG, TABLE_NAME2)); - - // test if getTables can get tables from the remote catalog. - resultSet = databaseMetaData.getTables(ATTACHED_CATALOG, null, "%", null); - assertTrue(resultSet.next(), "getTables should return exactly 1 table"); - returnedCatalog = resultSet.getString("TABLE_CAT"); - assertTrue( - ATTACHED_CATALOG.equals(returnedCatalog), - String.format("Returned catalog %s should equal attached catalog %s", returnedCatalog, ATTACHED_CATALOG)); - assertTrue(resultSet.next() == false, "getTables should return exactly 1 table"); - resultSet.close(); - - // test if getTables with null catalog returns all tables. - resultSet = databaseMetaData.getTables(null, null, "%", null); - - assertTrue(resultSet.next(), "getTables should return 2 tables, got 0"); - // first table should be ATTACHED_CATALOG.T2 - returnedCatalog = resultSet.getString("TABLE_CAT"); - assertTrue( - ATTACHED_CATALOG.equals(returnedCatalog), - String.format("Returned catalog %s should equal attached catalog %s", returnedCatalog, ATTACHED_CATALOG)); - returnedTableName = resultSet.getString("TABLE_NAME"); - assertTrue(TABLE_NAME2.equals(returnedTableName), - String.format("Returned table %s should equal %s", returnedTableName, TABLE_NAME2)); - - assertTrue(resultSet.next(), "getTables should return 2 tables, got 1"); - // second table should be .T1 - returnedCatalog = resultSet.getString("TABLE_CAT"); - assertTrue( - currentCatalog.equals(returnedCatalog), - String.format("Returned catalog %s should equal current catalog %s", returnedCatalog, currentCatalog)); - returnedTableName = resultSet.getString("TABLE_NAME"); - assertTrue(TABLE_NAME1.equals(returnedTableName), - String.format("Returned table %s should equal %s", returnedTableName, TABLE_NAME1)); - - assertTrue(resultSet.next() == false, "getTables should return 2 tables, got > 2"); - resultSet.close(); - statement.close(); - conn.close(); - } - - public static void test_get_tables_param_binding_for_table_types() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - DatabaseMetaData databaseMetaData = conn.getMetaData(); - ResultSet rs = databaseMetaData.getTables(null, null, null, - new String[] {"') UNION ALL " - + "SELECT" - + " 'fake catalog'" - + ", ?" - + ", ?" - + ", 'fake table type'" - + ", 'fake remarks'" - + ", 'fake type cat'" - + ", 'fake type schem'" - + ", 'fake type name'" - + ", 'fake self referencing col name'" - + ", 'fake ref generation' -- "}); - assertFalse(rs.next()); - rs.close(); - } - - public static void test_get_table_types() throws Exception { - String[] tableTypesArray = new String[] {"BASE TABLE", "LOCAL TEMPORARY", "VIEW"}; - List tableTypesList = new ArrayList<>(asList(tableTypesArray)); - tableTypesList.sort(Comparator.naturalOrder()); - - Connection conn = DriverManager.getConnection(JDBC_URL); - DatabaseMetaData databaseMetaData = conn.getMetaData(); - ResultSet rs = databaseMetaData.getTableTypes(); - - for (int i = 0; i < tableTypesArray.length; i++) { - assertTrue(rs.next(), "Expected a row from table types resultset"); - String tableTypeFromResultSet = rs.getString("TABLE_TYPE"); - String tableTypeFromList = tableTypesList.get(i); - assertTrue(tableTypeFromList.equals(tableTypeFromResultSet), - "Error in tableTypes at row " + (i + 1) + ": " - + "value from list " + tableTypeFromList + " should equal " - + "value from resultset " + tableTypeFromResultSet); - } - } - - public static void test_get_schemas_with_params() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - String inputCatalog = conn.getCatalog(); - String inputSchema = conn.getSchema(); - DatabaseMetaData databaseMetaData = conn.getMetaData(); - ResultSet resultSet = null; - - // catalog equal to current_catalog, schema null - try { - resultSet = databaseMetaData.getSchemas(inputCatalog, null); - assertTrue(resultSet.next(), "Expected at least exactly 1 row, got 0"); - do { - String outputCatalog = resultSet.getString("TABLE_CATALOG"); - assertTrue(inputCatalog.equals(outputCatalog), - "The catalog " + outputCatalog + " from getSchemas should equal the argument catalog " + - inputCatalog); - } while (resultSet.next()); - } catch (SQLException ex) { - assertFalse(ex.getMessage().startsWith("catalog argument is not supported")); - } finally { - if (resultSet != null) { - resultSet.close(); - } - conn.close(); - } - - // catalog equal to current_catalog, schema '%' - ResultSet resultSetWithNullSchema = null; - try { - resultSet = databaseMetaData.getSchemas(inputCatalog, "%"); - resultSetWithNullSchema = databaseMetaData.getSchemas(inputCatalog, null); - assertTrue(resultSet.next(), "Expected at least exactly 1 row, got 0"); - assertTrue(resultSetWithNullSchema.next(), "Expected at least exactly 1 row, got 0"); - do { - String outputCatalog; - outputCatalog = resultSet.getString("TABLE_CATALOG"); - assertTrue(inputCatalog.equals(outputCatalog), - "The catalog " + outputCatalog + " from getSchemas should equal the argument catalog " + - inputCatalog); - outputCatalog = resultSetWithNullSchema.getString("TABLE_CATALOG"); - assertTrue(inputCatalog.equals(outputCatalog), - "The catalog " + outputCatalog + " from getSchemas should equal the argument catalog " + - inputCatalog); - String schema1 = resultSet.getString("TABLE_SCHEMA"); - String schema2 = resultSetWithNullSchema.getString("TABLE_SCHEMA"); - assertTrue(schema1.equals(schema2), "schema " + schema1 + " from getSchemas with % should equal " + - schema2 + " from getSchemas with null"); - } while (resultSet.next() && resultSetWithNullSchema.next()); - } catch (SQLException ex) { - assertFalse(ex.getMessage().startsWith("catalog argument is not supported")); - } finally { - if (resultSet != null) { - resultSet.close(); - } - conn.close(); - } - - // empty catalog - try { - resultSet = databaseMetaData.getSchemas("", null); - assertTrue(resultSet.next() == false, "Expected 0 schemas, got > 0"); - } catch (SQLException ex) { - assertFalse(ex.getMessage().startsWith("catalog argument is not supported")); - } finally { - if (resultSet != null) { - resultSet.close(); - } - conn.close(); - } - } - - public static void test_connect_wrong_url_bug848() throws Exception { - Driver d = new DuckDBDriver(); - assertNull(d.connect("jdbc:h2:", null)); - } - - public static void test_new_connection_wrong_url_bug10441() throws Exception { - assertThrows(() -> { - Connection connection = DuckDBConnection.newConnection("jdbc:duckdb@", false, new Properties()); - try { - connection.close(); - } catch (SQLException e) { - // ignored - } - }, SQLException.class); - } - - public static void test_parquet_reader() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM parquet_scan('data/parquet-testing/userdata1.parquet')"); - assertTrue(rs.next()); - assertEquals(rs.getInt(1), 1000); - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_crash_autocommit_bug939() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - PreparedStatement stmt = conn.prepareStatement("CREATE TABLE ontime(flightdate DATE)"); - conn.setAutoCommit(false); // The is the key to getting the crash to happen. - stmt.executeUpdate(); - stmt.close(); - conn.close(); - } - - public static void test_explain_bug958() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("EXPLAIN SELECT 42"); - assertTrue(rs.next()); - assertTrue(rs.getString(1) != null); - assertTrue(rs.getString(2) != null); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_appender_numbers() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - // int8, int4, int2, int1, float8, float4 - stmt.execute("CREATE TABLE numbers (a BIGINT, b INTEGER, c SMALLINT, d TINYINT, e DOUBLE, f FLOAT)"); - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "numbers"); - - for (int i = 0; i < 50; i++) { - appender.beginRow(); - appender.append(Long.MAX_VALUE - i); - appender.append(Integer.MAX_VALUE - i); - appender.append(Short.MAX_VALUE - i); - appender.append(Byte.MAX_VALUE - i); - appender.append(i); - appender.append(i); - appender.endRow(); - } - appender.close(); - - ResultSet rs = stmt.executeQuery("SELECT max(a), max(b), max(c), max(d), max(e), max(f) FROM numbers"); - assertFalse(rs.isClosed()); - assertTrue(rs.next()); - - long resA = rs.getLong(1); - assertEquals(resA, Long.MAX_VALUE); - - int resB = rs.getInt(2); - assertEquals(resB, Integer.MAX_VALUE); - - short resC = rs.getShort(3); - assertEquals(resC, Short.MAX_VALUE); - - byte resD = rs.getByte(4); - assertEquals(resD, Byte.MAX_VALUE); - - double resE = rs.getDouble(5); - assertEquals(resE, 49.0d); - - float resF = rs.getFloat(6); - assertEquals(resF, 49.0f); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_appender_date_and_time() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE date_and_time (id INT4, a TIMESTAMP)"); - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "date_and_time"); - - LocalDateTime ldt1 = LocalDateTime.now().truncatedTo(ChronoUnit.MICROS); - LocalDateTime ldt2 = LocalDateTime.of(-23434, 3, 5, 23, 2); - LocalDateTime ldt3 = LocalDateTime.of(1970, 1, 1, 0, 0); - LocalDateTime ldt4 = LocalDateTime.of(11111, 12, 31, 23, 59, 59, 999999000); - - appender.beginRow(); - appender.append(1); - appender.appendLocalDateTime(ldt1); - appender.endRow(); - appender.beginRow(); - appender.append(2); - appender.appendLocalDateTime(ldt2); - appender.endRow(); - appender.beginRow(); - appender.append(3); - appender.appendLocalDateTime(ldt3); - appender.endRow(); - appender.beginRow(); - appender.append(4); - appender.appendLocalDateTime(ldt4); - appender.endRow(); - appender.close(); - - ResultSet rs = stmt.executeQuery("SELECT a FROM date_and_time ORDER BY id"); - assertFalse(rs.isClosed()); - assertTrue(rs.next()); - - LocalDateTime res1 = (LocalDateTime) rs.getObject(1, LocalDateTime.class); - assertEquals(res1, ldt1); - assertTrue(rs.next()); - - LocalDateTime res2 = (LocalDateTime) rs.getObject(1, LocalDateTime.class); - assertEquals(res2, ldt2); - assertTrue(rs.next()); - - LocalDateTime res3 = (LocalDateTime) rs.getObject(1, LocalDateTime.class); - assertEquals(res3, ldt3); - assertTrue(rs.next()); - - LocalDateTime res4 = (LocalDateTime) rs.getObject(1, LocalDateTime.class); - assertEquals(res4, ldt4); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_appender_decimal() throws Exception { - DuckDBConnection conn = DriverManager.getConnection("jdbc:duckdb:").unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute( - "CREATE TABLE decimals (id INT4, a DECIMAL(4,2), b DECIMAL(8,4), c DECIMAL(18,6), d DECIMAL(38,20))"); - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "decimals"); - - BigDecimal bigdec16 = new BigDecimal("12.34").setScale(2); - BigDecimal bigdec32 = new BigDecimal("1234.5678").setScale(4); - BigDecimal bigdec64 = new BigDecimal("123456789012.345678").setScale(6); - BigDecimal bigdec128 = new BigDecimal("123456789012345678.90123456789012345678").setScale(20); - BigDecimal negbigdec16 = new BigDecimal("-12.34").setScale(2); - BigDecimal negbigdec32 = new BigDecimal("-1234.5678").setScale(4); - BigDecimal negbigdec64 = new BigDecimal("-123456789012.345678").setScale(6); - BigDecimal negbigdec128 = new BigDecimal("-123456789012345678.90123456789012345678").setScale(20); - BigDecimal smallbigdec16 = new BigDecimal("-1.34").setScale(2); - BigDecimal smallbigdec32 = new BigDecimal("-123.5678").setScale(4); - BigDecimal smallbigdec64 = new BigDecimal("-12345678901.345678").setScale(6); - BigDecimal smallbigdec128 = new BigDecimal("-12345678901234567.90123456789012345678").setScale(20); - BigDecimal intbigdec16 = new BigDecimal("-1").setScale(2); - BigDecimal intbigdec32 = new BigDecimal("-123").setScale(4); - BigDecimal intbigdec64 = new BigDecimal("-12345678901").setScale(6); - BigDecimal intbigdec128 = new BigDecimal("-12345678901234567").setScale(20); - BigDecimal onebigdec16 = new BigDecimal("1").setScale(2); - BigDecimal onebigdec32 = new BigDecimal("1").setScale(4); - BigDecimal onebigdec64 = new BigDecimal("1").setScale(6); - BigDecimal onebigdec128 = new BigDecimal("1").setScale(20); - - appender.beginRow(); - appender.append(1); - appender.appendBigDecimal(bigdec16); - appender.appendBigDecimal(bigdec32); - appender.appendBigDecimal(bigdec64); - appender.appendBigDecimal(bigdec128); - appender.endRow(); - appender.beginRow(); - appender.append(2); - appender.appendBigDecimal(negbigdec16); - appender.appendBigDecimal(negbigdec32); - appender.appendBigDecimal(negbigdec64); - appender.appendBigDecimal(negbigdec128); - appender.endRow(); - appender.beginRow(); - appender.append(3); - appender.appendBigDecimal(smallbigdec16); - appender.appendBigDecimal(smallbigdec32); - appender.appendBigDecimal(smallbigdec64); - appender.appendBigDecimal(smallbigdec128); - appender.endRow(); - appender.beginRow(); - appender.append(4); - appender.appendBigDecimal(intbigdec16); - appender.appendBigDecimal(intbigdec32); - appender.appendBigDecimal(intbigdec64); - appender.appendBigDecimal(intbigdec128); - appender.endRow(); - appender.beginRow(); - appender.append(5); - appender.appendBigDecimal(onebigdec16); - appender.appendBigDecimal(onebigdec32); - appender.appendBigDecimal(onebigdec64); - appender.appendBigDecimal(onebigdec128); - appender.endRow(); - appender.close(); - - ResultSet rs = stmt.executeQuery("SELECT a,b,c,d FROM decimals ORDER BY id"); - assertFalse(rs.isClosed()); - assertTrue(rs.next()); - - BigDecimal rs1 = (BigDecimal) rs.getObject(1, BigDecimal.class); - BigDecimal rs2 = (BigDecimal) rs.getObject(2, BigDecimal.class); - BigDecimal rs3 = (BigDecimal) rs.getObject(3, BigDecimal.class); - BigDecimal rs4 = (BigDecimal) rs.getObject(4, BigDecimal.class); - - assertEquals(rs1, bigdec16); - assertEquals(rs2, bigdec32); - assertEquals(rs3, bigdec64); - assertEquals(rs4, bigdec128); - assertTrue(rs.next()); - - BigDecimal nrs1 = (BigDecimal) rs.getObject(1, BigDecimal.class); - BigDecimal nrs2 = (BigDecimal) rs.getObject(2, BigDecimal.class); - BigDecimal nrs3 = (BigDecimal) rs.getObject(3, BigDecimal.class); - BigDecimal nrs4 = (BigDecimal) rs.getObject(4, BigDecimal.class); - - assertEquals(nrs1, negbigdec16); - assertEquals(nrs2, negbigdec32); - assertEquals(nrs3, negbigdec64); - assertEquals(nrs4, negbigdec128); - assertTrue(rs.next()); - - BigDecimal srs1 = (BigDecimal) rs.getObject(1, BigDecimal.class); - BigDecimal srs2 = (BigDecimal) rs.getObject(2, BigDecimal.class); - BigDecimal srs3 = (BigDecimal) rs.getObject(3, BigDecimal.class); - BigDecimal srs4 = (BigDecimal) rs.getObject(4, BigDecimal.class); - - assertEquals(srs1, smallbigdec16); - assertEquals(srs2, smallbigdec32); - assertEquals(srs3, smallbigdec64); - assertEquals(srs4, smallbigdec128); - assertTrue(rs.next()); - - BigDecimal irs1 = (BigDecimal) rs.getObject(1, BigDecimal.class); - BigDecimal irs2 = (BigDecimal) rs.getObject(2, BigDecimal.class); - BigDecimal irs3 = (BigDecimal) rs.getObject(3, BigDecimal.class); - BigDecimal irs4 = (BigDecimal) rs.getObject(4, BigDecimal.class); - - assertEquals(irs1, intbigdec16); - assertEquals(irs2, intbigdec32); - assertEquals(irs3, intbigdec64); - assertEquals(irs4, intbigdec128); - assertTrue(rs.next()); - - BigDecimal oners1 = (BigDecimal) rs.getObject(1, BigDecimal.class); - BigDecimal oners2 = (BigDecimal) rs.getObject(2, BigDecimal.class); - BigDecimal oners3 = (BigDecimal) rs.getObject(3, BigDecimal.class); - BigDecimal oners4 = (BigDecimal) rs.getObject(4, BigDecimal.class); - - assertEquals(oners1, onebigdec16); - assertEquals(oners2, onebigdec32); - assertEquals(oners3, onebigdec64); - assertEquals(oners4, onebigdec128); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_appender_decimal_wrong_scale() throws Exception { - DuckDBConnection conn = DriverManager.getConnection("jdbc:duckdb:").unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute( - "CREATE TABLE decimals (id INT4, a DECIMAL(4,2), b DECIMAL(8,4), c DECIMAL(18,6), d DECIMAL(38,20))"); - - assertThrows(() -> { - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "decimals"); - appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "decimals"); - appender.append(1); - appender.beginRow(); - appender.appendBigDecimal(new BigDecimal("121.14").setScale(2)); - }, SQLException.class); - - assertThrows(() -> { - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "decimals"); - appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "decimals"); - appender.beginRow(); - appender.append(2); - appender.appendBigDecimal(new BigDecimal("21.1").setScale(2)); - appender.appendBigDecimal(new BigDecimal("12111.1411").setScale(4)); - }, SQLException.class); - - assertThrows(() -> { - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "decimals"); - appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "decimals"); - appender.beginRow(); - appender.append(3); - appender.appendBigDecimal(new BigDecimal("21.1").setScale(2)); - appender.appendBigDecimal(new BigDecimal("21.1").setScale(4)); - appender.appendBigDecimal(new BigDecimal("1234567890123.123456").setScale(6)); - }, SQLException.class); - - stmt.close(); - conn.close(); - } - - public static void test_appender_int_string() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE data (a INTEGER, s VARCHAR)"); - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); - - for (int i = 0; i < 1000; i++) { - appender.beginRow(); - appender.append(i); - appender.append("str " + i); - appender.endRow(); - } - appender.close(); - - ResultSet rs = stmt.executeQuery("SELECT max(a), min(s) FROM data"); - assertFalse(rs.isClosed()); - - assertTrue(rs.next()); - int resA = rs.getInt(1); - assertEquals(resA, 999); - String resB = rs.getString(2); - assertEquals(resB, "str 0"); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_appender_string_with_emoji() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE data (str_value VARCHAR(10))"); - String expectedValue = "䭔\uD86D\uDF7C🔥\uD83D\uDE1C"; - try (DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data")) { - appender.beginRow(); - appender.append(expectedValue); - appender.endRow(); - } - - ResultSet rs = stmt.executeQuery("SELECT str_value FROM data"); - assertFalse(rs.isClosed()); - assertTrue(rs.next()); - - String appendedValue = rs.getString(1); - assertEquals(appendedValue, expectedValue); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_appender_table_does_not_exist() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - assertThrows(() -> { - @SuppressWarnings("unused") - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); - }, SQLException.class); - - stmt.close(); - conn.close(); - } - - public static void test_appender_table_deleted() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE data (a INTEGER)"); - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); - - appender.beginRow(); - appender.append(1); - appender.endRow(); - - stmt.execute("DROP TABLE data"); - - appender.beginRow(); - appender.append(2); - appender.endRow(); - - assertThrows(appender::close, SQLException.class); - - stmt.close(); - conn.close(); - } - - public static void test_appender_append_too_many_columns() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE data (a INTEGER)"); - stmt.close(); - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); - - assertThrows(() -> { - appender.beginRow(); - appender.append(1); - appender.append(2); - }, SQLException.class); - - conn.close(); - } - - public static void test_appender_append_too_few_columns() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE data (a INTEGER, b INTEGER)"); - stmt.close(); - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); - - assertThrows(() -> { - appender.beginRow(); - appender.append(1); - appender.endRow(); - }, SQLException.class); - - conn.close(); - } - - public static void test_appender_type_mismatch() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE data (a INTEGER)"); - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); - - assertThrows(() -> { - appender.beginRow(); - appender.append("str"); - }, SQLException.class); - - stmt.close(); - conn.close(); - } - - public static void test_appender_null_integer() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE data (a INTEGER)"); - - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); - - appender.beginRow(); - appender.append(null); - appender.endRow(); - appender.flush(); - appender.close(); - - ResultSet results = stmt.executeQuery("SELECT * FROM data"); - assertTrue(results.next()); - // java.sql.ResultSet.getInt(int) returns 0 if the value is NULL - assertEquals(0, results.getInt(1)); - assertTrue(results.wasNull()); - - results.close(); - stmt.close(); - conn.close(); - } - - public static void test_appender_null_varchar() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - stmt.execute("CREATE TABLE data (a VARCHAR)"); - - DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); - - appender.beginRow(); - appender.append(null); - appender.endRow(); - appender.flush(); - appender.close(); - - ResultSet results = stmt.executeQuery("SELECT * FROM data"); - assertTrue(results.next()); - assertNull(results.getString(1)); - assertTrue(results.wasNull()); - - results.close(); - stmt.close(); - conn.close(); - } - - public static void test_get_catalog() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - ResultSet rs = conn.getMetaData().getCatalogs(); - HashSet set = new HashSet(); - while (rs.next()) { - set.add(rs.getString(1)); - } - assertTrue(!set.isEmpty()); - rs.close(); - assertTrue(set.contains(conn.getCatalog())); - conn.close(); - } - - public static void test_set_catalog() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - - assertThrows(() -> conn.setCatalog("other"), SQLException.class); - - try (Statement stmt = conn.createStatement()) { - stmt.execute("ATTACH ':memory:' AS other;"); - } - - conn.setCatalog("other"); - assertEquals(conn.getCatalog(), "other"); - } - } - - public static void test_get_table_types_bug1258() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - stmt.execute("CREATE TABLE a1 (i INTEGER)"); - stmt.execute("CREATE TABLE a2 (i INTEGER)"); - stmt.execute("CREATE TEMPORARY TABLE b (i INTEGER)"); - stmt.execute("CREATE VIEW c AS SELECT * FROM a1"); - stmt.close(); - - ResultSet rs = conn.getMetaData().getTables(null, null, null, null); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "a1"); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "a2"); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "b"); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "c"); - assertFalse(rs.next()); - rs.close(); - - rs = conn.getMetaData().getTables(null, null, null, new String[] {}); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "a1"); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "a2"); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "b"); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "c"); - assertFalse(rs.next()); - rs.close(); - - rs = conn.getMetaData().getTables(null, null, null, new String[] {"BASE TABLE"}); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "a1"); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "a2"); - assertFalse(rs.next()); - rs.close(); - - rs = conn.getMetaData().getTables(null, null, null, new String[] {"BASE TABLE", "VIEW"}); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "a1"); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "a2"); - assertTrue(rs.next()); - assertEquals(rs.getString("TABLE_NAME"), "c"); - assertFalse(rs.next()); - rs.close(); - - rs = conn.getMetaData().getTables(null, null, null, new String[] {"XXXX"}); - assertFalse(rs.next()); - rs.close(); - - conn.close(); - } - - public static void test_utf_string_bug1271() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - ResultSet rs = stmt.executeQuery("SELECT 'Mühleisen', '🦆', '🦄ྀི123456789'"); - assertEquals(rs.getMetaData().getColumnName(1), "'Mühleisen'"); - assertEquals(rs.getMetaData().getColumnName(2), "'🦆'"); - assertEquals(rs.getMetaData().getColumnName(3), "'🦄ྀི123456789'"); - - assertTrue(rs.next()); - - assertEquals(rs.getString(1), "Mühleisen"); - assertEquals(rs.getString(2), "🦆"); - assertEquals(rs.getString(3), "🦄ྀི123456789"); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_statement_creation_bug1268() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt; - - stmt = conn.createStatement(); - stmt.close(); - - stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - stmt.close(); - - stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, 0); - stmt.close(); - - PreparedStatement pstmt; - pstmt = conn.prepareStatement("SELECT 42"); - pstmt.close(); - - pstmt = conn.prepareStatement("SELECT 42", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - pstmt.close(); - - pstmt = conn.prepareStatement("SELECT 42", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, 0); - pstmt.close(); - - conn.close(); - } - - private static String blob_to_string(Blob b) throws SQLException { - return new String(b.getBytes(1, (int) b.length()), StandardCharsets.US_ASCII); - } - - public static void test_blob_bug1090() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - String test_str1 = "asdf"; - String test_str2 = "asdxxxxxxxxxxxxxxf"; - - ResultSet rs = - stmt.executeQuery("SELECT '" + test_str1 + "'::BLOB a, NULL::BLOB b, '" + test_str2 + "'::BLOB c"); - assertTrue(rs.next()); - - assertTrue(test_str1.equals(blob_to_string(rs.getBlob(1)))); - assertTrue(test_str1.equals(blob_to_string(rs.getBlob("a")))); - - assertTrue(test_str2.equals(blob_to_string(rs.getBlob("c")))); - - rs.getBlob("a"); - assertFalse(rs.wasNull()); - - rs.getBlob("b"); - assertTrue(rs.wasNull()); - - assertEquals(blob_to_string(((Blob) rs.getObject(1))), test_str1); - assertEquals(blob_to_string(((Blob) rs.getObject("a"))), test_str1); - assertEquals(blob_to_string(((Blob) rs.getObject("c"))), test_str2); - assertNull(rs.getObject(2)); - assertNull(rs.getObject("b")); - - rs.close(); - stmt.close(); - conn.close(); - } - - public static void test_uuid() throws Exception { - // Generated by DuckDB - String testUuid = "a0a34a0a-1794-47b6-b45c-0ac68cc03702"; - - try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - DuckDBResultSet rs = stmt.executeQuery("SELECT a, NULL::UUID b, a::VARCHAR c, '" + testUuid + - "'::UUID d FROM (SELECT uuid() a)") - .unwrap(DuckDBResultSet.class)) { - assertTrue(rs.next()); - - // UUID direct - UUID a = (UUID) rs.getObject(1); - assertTrue(a != null); - assertTrue(rs.getObject("a") instanceof UUID); - assertFalse(rs.wasNull()); - - // Null handling - assertNull(rs.getObject(2)); - assertTrue(rs.wasNull()); - assertNull(rs.getObject("b")); - assertTrue(rs.wasNull()); - - // String interpreted as UUID in Java, rather than in DuckDB - assertTrue(rs.getObject(3) instanceof String); - assertEquals(rs.getUuid(3), a); - assertFalse(rs.wasNull()); - - // Verify UUID computation is correct - assertEquals(rs.getObject(4), UUID.fromString(testUuid)); - } - } - - public static void test_unsigned_integers() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - Statement stmt = conn.createStatement(); - - ResultSet rs = stmt.executeQuery( - "SELECT 201::utinyint uint8, 40001::usmallint uint16, 4000000001::uinteger uint32, 18446744073709551615::ubigint uint64"); - assertTrue(rs.next()); - - assertEquals(rs.getShort("uint8"), Short.valueOf((short) 201)); - assertEquals(rs.getObject("uint8"), Short.valueOf((short) 201)); - assertEquals(rs.getInt("uint8"), Integer.valueOf((int) 201)); - - assertEquals(rs.getInt("uint16"), Integer.valueOf((int) 40001)); - assertEquals(rs.getObject("uint16"), Integer.valueOf((int) 40001)); - assertEquals(rs.getLong("uint16"), Long.valueOf((long) 40001)); - - assertEquals(rs.getLong("uint32"), Long.valueOf((long) 4000000001L)); - assertEquals(rs.getObject("uint32"), Long.valueOf((long) 4000000001L)); - - assertEquals(rs.getObject("uint64"), new BigInteger("18446744073709551615")); - - rs.close(); - - rs = stmt.executeQuery( - "SELECT NULL::utinyint uint8, NULL::usmallint uint16, NULL::uinteger uint32, NULL::ubigint uint64"); - assertTrue(rs.next()); - - rs.getObject(1); - assertTrue(rs.wasNull()); - - rs.getObject(2); - assertTrue(rs.wasNull()); - - rs.getObject(3); - assertTrue(rs.wasNull()); - - rs.getObject(4); - assertTrue(rs.wasNull()); - - stmt.close(); - conn.close(); - } - - public static void test_get_schema() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - - assertEquals(conn.getSchema(), DuckDBConnection.DEFAULT_SCHEMA); - - try (Statement stmt = conn.createStatement()) { - stmt.execute("CREATE SCHEMA alternate_schema;"); - stmt.execute("SET search_path = \"alternate_schema\";"); - } - - assertEquals(conn.getSchema(), "alternate_schema"); - - conn.setSchema("main"); - assertEquals(conn.getSchema(), "main"); - - conn.close(); - - try { - conn.getSchema(); - fail(); - } catch (SQLException e) { - assertEquals(e.getMessage(), "Connection Error: Invalid connection"); - } - } - - /** - * @see {https://github.com/duckdb/duckdb/issues/3906} - */ - public static void test_cached_row_set() throws Exception { - CachedRowSet rowSet = RowSetProvider.newFactory().createCachedRowSet(); - rowSet.setUrl(JDBC_URL); - rowSet.setCommand("select 1"); - rowSet.execute(); - - rowSet.next(); - assertEquals(rowSet.getInt(1), 1); - } - - public static void test_json() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - - try (Statement stmt = conn.createStatement()) { - ResultSet rs = stmt.executeQuery("select [1, 5]::JSON"); - rs.next(); - assertEquals(rs.getMetaData().getColumnType(1), Types.JAVA_OBJECT); - JsonNode jsonNode = (JsonNode) rs.getObject(1); - assertTrue(jsonNode.isArray()); - assertEquals(jsonNode.toString(), "[1,5]"); - } - - try (Statement stmt = conn.createStatement()) { - ResultSet rs = stmt.executeQuery("select '{\"key\": \"value\"}'::JSON"); - rs.next(); - assertEquals(rs.getMetaData().getColumnType(1), Types.JAVA_OBJECT); - JsonNode jsonNode = (JsonNode) rs.getObject(1); - assertTrue(jsonNode.isObject()); - assertEquals(jsonNode.toString(), - "{\"key\": \"value\"}"); // this isn't valid json output, must load json extension for that - } - - try (Statement stmt = conn.createStatement()) { - ResultSet rs = stmt.executeQuery("select '\"hello\"'::JSON"); - rs.next(); - assertEquals(rs.getMetaData().getColumnType(1), Types.JAVA_OBJECT); - JsonNode jsonNode = (JsonNode) rs.getObject(1); - assertTrue(jsonNode.isString()); - assertEquals(jsonNode.toString(), "\"hello\""); - } - } - - public static void test_bug4218_prepare_types() throws Exception { - DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); - String query = "SELECT ($1 || $2)"; - conn.prepareStatement(query); - assertTrue(true); - } - - public static void test_bug532_timestamp() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - - ResultSet rs; - - stmt.execute("CREATE TABLE t0(c0 DATETIME);"); - stmt.execute("INSERT INTO t0 VALUES(DATE '1-1-1');"); - rs = stmt.executeQuery("SELECT t0.c0 FROM t0; "); - - rs.next(); - rs.getObject(1); - } - - public static void test_bug966_typeof() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("select typeof(1);"); - - rs.next(); - assertEquals(rs.getString(1), "INTEGER"); - } - - public static void test_config() throws Exception { - String memory_limit = "memory_limit"; - String threads = "threads"; - - Properties info = new Properties(); - info.put(memory_limit, "500MB"); - info.put(threads, "5"); - Connection conn = DriverManager.getConnection(JDBC_URL, info); - - assertEquals("476.8 MiB", getSetting(conn, memory_limit)); - assertEquals("5", getSetting(conn, threads)); - } - - public static void test_invalid_config() throws Exception { - Properties info = new Properties(); - info.put("invalid config name", "true"); - - String message = assertThrows(() -> DriverManager.getConnection(JDBC_URL, info), SQLException.class); - - assertTrue(message.contains("Unrecognized configuration property \"invalid config name\"")); - } - - public static void test_valid_but_local_config_throws_exception() throws Exception { - Properties info = new Properties(); - info.put("ordered_aggregate_threshold", "123"); - - String message = assertThrows(() -> DriverManager.getConnection(JDBC_URL, info), SQLException.class); - - assertTrue(message.contains("Could not set option \"ordered_aggregate_threshold\" as a global option")); - } - - private static String getSetting(Connection conn, String settingName) throws Exception { - try (PreparedStatement stmt = conn.prepareStatement("select value from duckdb_settings() where name = ?")) { - stmt.setString(1, settingName); - ResultSet rs = stmt.executeQuery(); - rs.next(); - - return rs.getString(1); - } - } - - public static void test_describe() throws Exception { - Connection conn = DriverManager.getConnection(JDBC_URL); - - try (Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE TEST (COL INT DEFAULT 42)"); - - ResultSet rs = stmt.executeQuery("DESCRIBE SELECT * FROM TEST"); - rs.next(); - assertEquals(rs.getString("column_name"), "COL"); - assertEquals(rs.getString("column_type"), "INTEGER"); - assertEquals(rs.getString("null"), "YES"); - assertNull(rs.getString("key")); - assertNull(rs.getString("default")); - assertNull(rs.getString("extra")); - } - } - - public static void test_null_bytes_in_string() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - try (PreparedStatement stmt = conn.prepareStatement("select ?::varchar")) { - stmt.setObject(1, "bob\u0000r"); - ResultSet rs = stmt.executeQuery(); - - rs.next(); - assertEquals(rs.getString(1), "bob\u0000r"); - } - } - } - - public static void test_get_functions() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - ResultSet functions = - conn.getMetaData().getFunctions(null, DuckDBConnection.DEFAULT_SCHEMA, "string_split"); - - assertTrue(functions.next()); - assertNull(functions.getObject("FUNCTION_CAT")); - assertEquals(DuckDBConnection.DEFAULT_SCHEMA, functions.getString("FUNCTION_SCHEM")); - assertEquals("string_split", functions.getString("FUNCTION_NAME")); - assertEquals(DatabaseMetaData.functionNoTable, functions.getInt("FUNCTION_TYPE")); - - assertFalse(functions.next()); - - // two items for two overloads? - functions = conn.getMetaData().getFunctions(null, DuckDBConnection.DEFAULT_SCHEMA, "read_csv_auto"); - assertTrue(functions.next()); - assertNull(functions.getObject("FUNCTION_CAT")); - assertEquals(DuckDBConnection.DEFAULT_SCHEMA, functions.getString("FUNCTION_SCHEM")); - assertEquals("read_csv_auto", functions.getString("FUNCTION_NAME")); - assertEquals(DatabaseMetaData.functionReturnsTable, functions.getInt("FUNCTION_TYPE")); - - assertTrue(functions.next()); - assertNull(functions.getObject("FUNCTION_CAT")); - assertEquals(DuckDBConnection.DEFAULT_SCHEMA, functions.getString("FUNCTION_SCHEM")); - assertEquals("read_csv_auto", functions.getString("FUNCTION_NAME")); - assertEquals(DatabaseMetaData.functionReturnsTable, functions.getInt("FUNCTION_TYPE")); - - assertFalse(functions.next()); - } - } - - public static void test_get_primary_keys() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement();) { - Object[][] testData = new Object[12][6]; - int testDataIndex = 0; - - Object[][] params = new Object[6][5]; - int paramIndex = 0; - - String catalog = conn.getCatalog(); - - for (int schemaNumber = 1; schemaNumber <= 2; schemaNumber++) { - String schemaName = "schema" + schemaNumber; - stmt.executeUpdate("CREATE SCHEMA " + schemaName); - stmt.executeUpdate("SET SCHEMA = '" + schemaName + "'"); - for (int tableNumber = 1; tableNumber <= 3; tableNumber++) { - String tableName = "table" + tableNumber; - params[paramIndex] = new Object[] {catalog, schemaName, tableName, testDataIndex, -1}; - String columns = null; - String pk = null; - for (int columnNumber = 1; columnNumber <= tableNumber; columnNumber++) { - String columnName = "column" + columnNumber; - String columnDef = columnName + " int not null"; - columns = columns == null ? columnDef : columns + "," + columnDef; - pk = pk == null ? columnName : pk + "," + columnName; - testData[testDataIndex++] = - new Object[] {catalog, schemaName, tableName, columnName, columnNumber, null}; - } - stmt.executeUpdate("CREATE TABLE " + tableName + "(" + columns + ",PRIMARY KEY(" + pk + ") )"); - params[paramIndex][4] = testDataIndex; - paramIndex += 1; - } - } - - DatabaseMetaData databaseMetaData = conn.getMetaData(); - for (paramIndex = 0; paramIndex < 6; paramIndex++) { - Object[] paramSet = params[paramIndex]; - ResultSet resultSet = - databaseMetaData.getPrimaryKeys((String) paramSet[0], (String) paramSet[1], (String) paramSet[2]); - for (testDataIndex = (int) paramSet[3]; testDataIndex < (int) paramSet[4]; testDataIndex++) { - assertTrue(resultSet.next(), "Expected a row at position " + testDataIndex); - Object[] testDataRow = testData[testDataIndex]; - for (int columnIndex = 0; columnIndex < testDataRow.length; columnIndex++) { - Object value = testDataRow[columnIndex]; - if (value == null || value instanceof String) { - String columnValue = resultSet.getString(columnIndex + 1); - assertTrue(value == null ? columnValue == null : value.equals(columnValue), - "row value " + testDataIndex + ", " + columnIndex + " " + value + - " should equal column value " + columnValue); - } else { - int testValue = ((Integer) value).intValue(); - int columnValue = resultSet.getInt(columnIndex + 1); - assertTrue(testValue == columnValue, "row value " + testDataIndex + ", " + columnIndex + - " " + testValue + " should equal column value " + - columnValue); - } - } - } - resultSet.close(); - } - - /* - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - pw.println("WITH constraint_columns as ("); - pw.println("select"); - pw.println(" database_name as \"TABLE_CAT\""); - pw.println(", schema_name as \"TABLE_SCHEM\""); - pw.println(", table_name as \"TABLE_NAME\""); - pw.println(", unnest(constraint_column_names) as \"COLUMN_NAME\""); - pw.println(", cast(null as varchar) as \"PK_NAME\""); - pw.println("from duckdb_constraints"); - pw.println("where constraint_type = 'PRIMARY KEY'"); - pw.println(")"); - pw.println("SELECT \"TABLE_CAT\""); - pw.println(", \"TABLE_SCHEM\""); - pw.println(", \"TABLE_NAME\""); - pw.println(", \"COLUMN_NAME\""); - pw.println(", cast(row_number() over "); - pw.println("(partition by \"TABLE_CAT\", \"TABLE_SCHEM\", \"TABLE_NAME\") as int) as \"KEY_SEQ\""); - pw.println(", \"PK_NAME\""); - pw.println("FROM constraint_columns"); - pw.println("ORDER BY TABLE_CAT, TABLE_SCHEM, TABLE_NAME, KEY_SEQ"); - - ResultSet resultSet = stmt.executeQuery(sw.toString()); - ResultSet resultSet = databaseMetaData.getPrimaryKeys(null, null, catalog); - for (testDataIndex = 0; testDataIndex < testData.length; testDataIndex++) { - assertTrue(resultSet.next(), "Expected a row at position " + testDataIndex); - Object[] testDataRow = testData[testDataIndex]; - for (int columnIndex = 0; columnIndex < testDataRow.length; columnIndex++) { - Object value = testDataRow[columnIndex]; - if (value == null || value instanceof String) { - String columnValue = resultSet.getString(columnIndex + 1); - assertTrue( - value == null ? columnValue == null : value.equals(columnValue), - "row value " + testDataIndex + ", " + columnIndex + " " + value + - " should equal column value "+ columnValue - ); - } else { - int testValue = ((Integer) value).intValue(); - int columnValue = resultSet.getInt(columnIndex + 1); - assertTrue( - testValue == columnValue, - "row value " + testDataIndex + ", " + columnIndex + " " + testValue + - " should equal column value " + columnValue - ); - } - } - } - */ - } catch (Exception e) { - e.printStackTrace(); - throw e; - } - } - - public static void test_instance_cache() throws Exception { - Path database_file = Files.createTempFile("duckdb-instance-cache-test-", ".duckdb"); - database_file.toFile().delete(); - - String jdbc_url = JDBC_URL + database_file.toString(); - - Connection conn = DriverManager.getConnection(jdbc_url); - Connection conn2 = DriverManager.getConnection(jdbc_url); - - conn.close(); - conn2.close(); - } - - public static void test_user_password() throws Exception { - String jdbc_url = JDBC_URL; - Properties p = new Properties(); - p.setProperty("user", "wilbur"); - p.setProperty("password", "quack"); - Connection conn = DriverManager.getConnection(jdbc_url, p); - conn.close(); - - Properties p2 = new Properties(); - p2.setProperty("User", "wilbur"); - p2.setProperty("PASSWORD", "quack"); - Connection conn2 = DriverManager.getConnection(jdbc_url, p2); - conn2.close(); - } - - public static void test_boolean_config() throws Exception { - Properties config = new Properties(); - config.put("enable_external_access", false); - try (Connection conn = DriverManager.getConnection(JDBC_URL, config); - PreparedStatement stmt = conn.prepareStatement("SELECT current_setting('enable_external_access')"); - ResultSet rs = stmt.executeQuery()) { - rs.next(); - assertEquals("false", rs.getString(1)); - } - } - - public static void test_readonly_remains_bug5593() throws Exception { - Path database_file = Files.createTempFile("duckdb-instance-cache-test-", ".duckdb"); - database_file.toFile().delete(); - String jdbc_url = JDBC_URL + database_file.toString(); - - Properties p = new Properties(); - p.setProperty("duckdb.read_only", "true"); - try { - Connection conn = DriverManager.getConnection(jdbc_url, p); - conn.close(); - } catch (Exception e) { - // nop - } - assertTrue(p.containsKey("duckdb.read_only")); - } - - public static void test_supportsLikeEscapeClause_shouldBe_true() throws Exception { - Connection connection = DriverManager.getConnection(JDBC_URL); - DatabaseMetaData databaseMetaData = connection.getMetaData(); - assertTrue(databaseMetaData.supportsLikeEscapeClause(), - "DatabaseMetaData.supportsLikeEscapeClause() should be true."); - } - - public static void test_supports_catalogs_in_table_definitions() throws Exception { - final String CATALOG_NAME = "tmp"; - final String TABLE_NAME = "t1"; - final String IS_TablesQuery = "SELECT * FROM information_schema.tables " + - String.format("WHERE table_catalog = '%s' ", CATALOG_NAME) + - String.format("AND table_name = '%s'", TABLE_NAME); - final String QUALIFIED_TABLE_NAME = CATALOG_NAME + "." + TABLE_NAME; - ResultSet resultSet = null; - try (final Connection connection = DriverManager.getConnection(JDBC_URL); - final Statement statement = connection.createStatement();) { - final DatabaseMetaData databaseMetaData = connection.getMetaData(); - statement.execute(String.format("ATTACH '' AS \"%s\"", CATALOG_NAME)); - - final boolean supportsCatalogsInTableDefinitions = databaseMetaData.supportsCatalogsInTableDefinitions(); - try { - statement.execute(String.format("CREATE TABLE %s (id int)", QUALIFIED_TABLE_NAME)); - } catch (SQLException ex) { - if (supportsCatalogsInTableDefinitions) { - fail( - "supportsCatalogsInTableDefinitions is true but CREATE TABLE in attached database is not allowed. " + - ex.getMessage()); - ex.printStackTrace(); - } - } - resultSet = statement.executeQuery(IS_TablesQuery); - assertTrue(resultSet.next(), "Expected exactly 1 row from information_schema.tables, got 0"); - assertFalse(resultSet.next()); - resultSet.close(); - - try { - statement.execute(String.format("DROP TABLE %s", QUALIFIED_TABLE_NAME)); - } catch (SQLException ex) { - if (supportsCatalogsInTableDefinitions) { - fail( - "supportsCatalogsInTableDefinitions is true but DROP TABLE in attached database is not allowed. " + - ex.getMessage()); - ex.printStackTrace(); - } - } - resultSet = statement.executeQuery(IS_TablesQuery); - assertTrue(resultSet.next() == false, "Expected exactly 0 rows from information_schema.tables, got > 0"); - resultSet.close(); - - assertTrue(supportsCatalogsInTableDefinitions, "supportsCatalogsInTableDefinitions should return true."); - } - } - - public static void test_supports_catalogs_in_data_manipulation() throws Exception { - final String CATALOG_NAME = "tmp"; - final String TABLE_NAME = "t1"; - final String COLUMN_NAME = "id"; - final String QUALIFIED_TABLE_NAME = CATALOG_NAME + "." + TABLE_NAME; - - ResultSet resultSet = null; - try (final Connection connection = DriverManager.getConnection(JDBC_URL); - final Statement statement = connection.createStatement();) { - final DatabaseMetaData databaseMetaData = connection.getMetaData(); - statement.execute(String.format("ATTACH '' AS \"%s\"", CATALOG_NAME)); - statement.execute(String.format("CREATE TABLE %s(%s int)", QUALIFIED_TABLE_NAME, COLUMN_NAME)); - - final boolean supportsCatalogsInDataManipulation = databaseMetaData.supportsCatalogsInDataManipulation(); - try { - statement.execute(String.format("INSERT INTO %s VALUES(1)", QUALIFIED_TABLE_NAME)); - resultSet = statement.executeQuery(String.format("SELECT * FROM %s", QUALIFIED_TABLE_NAME)); - assertTrue(resultSet.next(), "Expected exactly 1 row from " + QUALIFIED_TABLE_NAME + ", got 0"); - assertTrue(resultSet.getInt(COLUMN_NAME) == 1, "Value for " + COLUMN_NAME + " should be 1"); - resultSet.close(); - } catch (SQLException ex) { - if (supportsCatalogsInDataManipulation) { - fail("supportsCatalogsInDataManipulation is true but INSERT in " + QUALIFIED_TABLE_NAME + - " is not allowed." + ex.getMessage()); - ex.printStackTrace(); - } - } - - try { - statement.execute( - String.format("UPDATE %1$s SET %2$s = 2 WHERE %2$s = 1", QUALIFIED_TABLE_NAME, COLUMN_NAME)); - resultSet = statement.executeQuery(String.format("SELECT * FROM %s", QUALIFIED_TABLE_NAME)); - assertTrue(resultSet.next(), "Expected exactly 1 row from " + QUALIFIED_TABLE_NAME + ", got 0"); - assertTrue(resultSet.getInt(COLUMN_NAME) == 2, "Value for " + COLUMN_NAME + " should be 2"); - resultSet.close(); - } catch (SQLException ex) { - if (supportsCatalogsInDataManipulation) { - fail("supportsCatalogsInDataManipulation is true but UPDATE of " + QUALIFIED_TABLE_NAME + - " is not allowed. " + ex.getMessage()); - ex.printStackTrace(); - } - } - - try { - statement.execute(String.format("DELETE FROM %s WHERE %s = 2", QUALIFIED_TABLE_NAME, COLUMN_NAME)); - resultSet = statement.executeQuery(String.format("SELECT * FROM %s", QUALIFIED_TABLE_NAME)); - assertTrue(resultSet.next() == false, "Expected 0 rows from " + QUALIFIED_TABLE_NAME + ", got > 0"); - resultSet.close(); - } catch (SQLException ex) { - if (supportsCatalogsInDataManipulation) { - fail("supportsCatalogsInDataManipulation is true but UPDATE of " + QUALIFIED_TABLE_NAME + - " is not allowed. " + ex.getMessage()); - ex.printStackTrace(); - } - } - - assertTrue(supportsCatalogsInDataManipulation, "supportsCatalogsInDataManipulation should return true."); - } - } - - public static void test_supports_catalogs_in_index_definitions() throws Exception { - final String CATALOG_NAME = "tmp"; - final String TABLE_NAME = "t1"; - final String INDEX_NAME = "idx1"; - final String QUALIFIED_TABLE_NAME = CATALOG_NAME + "." + TABLE_NAME; - final String QUALIFIED_INDEX_NAME = CATALOG_NAME + "." + INDEX_NAME; - - ResultSet resultSet = null; - try (final Connection connection = DriverManager.getConnection(JDBC_URL); - final Statement statement = connection.createStatement();) { - final DatabaseMetaData databaseMetaData = connection.getMetaData(); - statement.execute(String.format("ATTACH '' AS \"%s\"", CATALOG_NAME)); - - final boolean supportsCatalogsInIndexDefinitions = databaseMetaData.supportsCatalogsInIndexDefinitions(); - try { - statement.execute(String.format("CREATE TABLE %s(id int)", QUALIFIED_TABLE_NAME)); - statement.execute(String.format("CREATE INDEX %s ON %s(id)", INDEX_NAME, QUALIFIED_TABLE_NAME)); - resultSet = statement.executeQuery( - String.format("SELECT * FROM duckdb_indexes() " - + "WHERE database_name = '%s' AND table_name = '%s' AND index_name = '%s' ", - CATALOG_NAME, TABLE_NAME, INDEX_NAME)); - assertTrue(resultSet.next(), "Expected exactly 1 row from duckdb_indexes(), got 0"); - resultSet.close(); - } catch (SQLException ex) { - if (supportsCatalogsInIndexDefinitions) { - fail("supportsCatalogsInIndexDefinitions is true but " - + "CREATE INDEX on " + QUALIFIED_TABLE_NAME + " is not allowed. " + ex.getMessage()); - ex.printStackTrace(); - } - } - - try { - statement.execute("DROP index " + QUALIFIED_INDEX_NAME); - resultSet = statement.executeQuery( - String.format("SELECT * FROM duckdb_indexes() " - + "WHERE database_name = '%s' AND table_name = '%s' AND index_name = '%s'", - CATALOG_NAME, TABLE_NAME, INDEX_NAME)); - assertFalse(resultSet.next()); - resultSet.close(); - } catch (SQLException ex) { - if (supportsCatalogsInIndexDefinitions) { - fail("supportsCatalogsInIndexDefinitions is true but DROP of " + QUALIFIED_INDEX_NAME + - " is not allowed." + ex.getMessage()); - ex.printStackTrace(); - } - } - - assertTrue(supportsCatalogsInIndexDefinitions, "supportsCatalogsInIndexDefinitions should return true."); - } - } - - public static void test_structs() throws Exception { - try (Connection connection = DriverManager.getConnection(JDBC_URL); - PreparedStatement statement = connection.prepareStatement("select {\"a\": 1}")) { - ResultSet resultSet = statement.executeQuery(); - assertTrue(resultSet.next()); - Struct struct = (Struct) resultSet.getObject(1); - assertEquals(toJavaObject(struct), mapOf("a", 1)); - assertEquals(struct.getSQLTypeName(), "STRUCT(a INTEGER)"); - } - } - - public static void test_union() throws Exception { - try (Connection connection = DriverManager.getConnection(JDBC_URL); - Statement statement = connection.createStatement()) { - statement.execute("CREATE TABLE tbl1(u UNION(num INT, str VARCHAR));"); - statement.execute("INSERT INTO tbl1 values (1) , ('two') , (union_value(str := 'three'));"); - - ResultSet rs = statement.executeQuery("select * from tbl1"); - assertTrue(rs.next()); - assertEquals(rs.getObject(1), 1); - assertTrue(rs.next()); - assertEquals(rs.getObject(1), "two"); - assertTrue(rs.next()); - assertEquals(rs.getObject(1), "three"); - } - } - - public static void test_list() throws Exception { - try (Connection connection = DriverManager.getConnection(JDBC_URL); - Statement statement = connection.createStatement()) { - try (ResultSet rs = statement.executeQuery("select [1]")) { - assertTrue(rs.next()); - assertEquals(arrayToList(rs.getArray(1)), singletonList(1)); - } - try (ResultSet rs = statement.executeQuery("select unnest([[1], [42, 69]])")) { - assertTrue(rs.next()); - assertEquals(arrayToList(rs.getArray(1)), singletonList(1)); - assertTrue(rs.next()); - assertEquals(arrayToList(rs.getArray(1)), asList(42, 69)); - } - try (ResultSet rs = statement.executeQuery("select unnest([[[42], [69]]])")) { - assertTrue(rs.next()); - - List> expected = asList(singletonList(42), singletonList(69)); - List actual = arrayToList(rs.getArray(1)); - - for (int i = 0; i < actual.size(); i++) { - assertEquals(actual.get(i), expected.get(i)); - } - } - try (ResultSet rs = statement.executeQuery("select unnest([[], [69]])")) { - assertTrue(rs.next()); - assertTrue(arrayToList(rs.getArray(1)).isEmpty()); - } - - try (ResultSet rs = statement.executeQuery("SELECT [0.0]::DECIMAL[]")) { - assertTrue(rs.next()); - assertEquals(arrayToList(rs.getArray(1)), singletonList(new BigDecimal("0.000"))); - } - } - } - - public static void test_array_resultset() throws Exception { - try (Connection connection = DriverManager.getConnection(JDBC_URL); - Statement statement = connection.createStatement()) { - try (ResultSet rs = statement.executeQuery("select [42, 69]")) { - assertTrue(rs.next()); - ResultSet arrayResultSet = rs.getArray(1).getResultSet(); - assertTrue(arrayResultSet.next()); - assertEquals(arrayResultSet.getInt(1), 1); - assertEquals(arrayResultSet.getInt(2), 42); - assertTrue(arrayResultSet.next()); - assertEquals(arrayResultSet.getInt(1), 2); - assertEquals(arrayResultSet.getInt(2), 69); - assertFalse(arrayResultSet.next()); - } - - try (ResultSet rs = statement.executeQuery("select unnest([[[], [69]]])")) { - assertTrue(rs.next()); - ResultSet arrayResultSet = rs.getArray(1).getResultSet(); - assertTrue(arrayResultSet.next()); - assertEquals(arrayResultSet.getInt(1), 1); - Array subArray = arrayResultSet.getArray(2); - assertNotNull(subArray); - ResultSet subArrayResultSet = subArray.getResultSet(); - assertFalse(subArrayResultSet.next()); // empty array - - assertTrue(arrayResultSet.next()); - assertEquals(arrayResultSet.getInt(1), 2); - Array subArray2 = arrayResultSet.getArray(2); - assertNotNull(subArray2); - ResultSet subArrayResultSet2 = subArray2.getResultSet(); - assertTrue(subArrayResultSet2.next()); - - assertEquals(subArrayResultSet2.getInt(1), 1); - assertEquals(subArrayResultSet2.getInt(2), 69); - assertFalse(arrayResultSet.next()); - } - - try (ResultSet rs = statement.executeQuery("select [42, 69]")) { - assertFalse(rs.isClosed()); - rs.close(); - assertTrue(rs.isClosed()); - } - - try (ResultSet rs = statement.executeQuery("select ['life', null, 'universe']")) { - assertTrue(rs.next()); - - ResultSet arrayResultSet = rs.getArray(1).getResultSet(); - assertTrue(arrayResultSet.isBeforeFirst()); - assertTrue(arrayResultSet.next()); - assertFalse(arrayResultSet.isBeforeFirst()); - assertEquals(arrayResultSet.getInt(1), 1); - assertEquals(arrayResultSet.getString(2), "life"); - assertFalse(arrayResultSet.wasNull()); - - assertTrue(arrayResultSet.next()); - assertEquals(arrayResultSet.getInt(1), 2); - assertFalse(arrayResultSet.wasNull()); - assertEquals(arrayResultSet.getObject(2), null); - assertTrue(arrayResultSet.wasNull()); - - assertTrue(arrayResultSet.next()); - assertEquals(arrayResultSet.getInt(1), 3); - assertFalse(arrayResultSet.wasNull()); - assertEquals(arrayResultSet.getString(2), "universe"); - assertFalse(arrayResultSet.wasNull()); - - assertFalse(arrayResultSet.isBeforeFirst()); - assertFalse(arrayResultSet.isAfterLast()); - assertFalse(arrayResultSet.next()); - assertTrue(arrayResultSet.isAfterLast()); - - arrayResultSet.first(); - assertEquals(arrayResultSet.getString(2), "life"); - assertTrue(arrayResultSet.isFirst()); - - arrayResultSet.last(); - assertEquals(arrayResultSet.getString(2), "universe"); - assertTrue(arrayResultSet.isLast()); - - assertFalse(arrayResultSet.next()); - assertTrue(arrayResultSet.isAfterLast()); - - arrayResultSet.next(); // try to move past the end - assertTrue(arrayResultSet.isAfterLast()); - - arrayResultSet.relative(-1); - assertEquals(arrayResultSet.getString(2), "universe"); - } - - try (ResultSet rs = statement.executeQuery("select UNNEST([[42], [69]])")) { - assertTrue(rs.next()); - ResultSet arrayResultSet = rs.getArray(1).getResultSet(); - assertTrue(arrayResultSet.next()); - - assertEquals(arrayResultSet.getInt(1), 1); - assertEquals(arrayResultSet.getInt(2), 42); - assertFalse(arrayResultSet.next()); - - assertTrue(rs.next()); - ResultSet arrayResultSet2 = rs.getArray(1).getResultSet(); - assertTrue(arrayResultSet2.next()); - assertEquals(arrayResultSet2.getInt(1), 1); - assertEquals(arrayResultSet2.getInt(2), 69); - assertFalse(arrayResultSet2.next()); - } - } - } - - private static List arrayToList(Array array) throws SQLException { - return arrayToList((T[]) array.getArray()); - } - - private static List arrayToList(T[] array) throws SQLException { - List out = new ArrayList<>(); - for (Object t : array) { - out.add((T) toJavaObject(t)); - } - return out; - } - - private static T toJavaObject(Object t) { - try { - if (t instanceof Array) { - t = arrayToList((Array) t); - } else if (t instanceof Struct) { - t = structToMap((DuckDBStruct) t); - } - return (T) t; - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public static void test_map() throws Exception { - try (Connection connection = DriverManager.getConnection(JDBC_URL); - PreparedStatement statement = connection.prepareStatement("select map([100, 5], ['a', 'b'])")) { - ResultSet rs = statement.executeQuery(); - assertTrue(rs.next()); - assertEquals(rs.getObject(1), mapOf(100, "a", 5, "b")); - } - } - - public static void test_getColumnClassName() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement s = conn.createStatement();) { - try (ResultSet rs = s.executeQuery("select * from test_all_types()")) { - ResultSetMetaData rsmd = rs.getMetaData(); - rs.next(); - for (int i = 1; i <= rsmd.getColumnCount(); i++) { - Object value = rs.getObject(i); - - assertEquals(rsmd.getColumnClassName(i), value.getClass().getName()); - } - } - } - } - - public static void test_update_count() throws Exception { - try (Connection connection = DriverManager.getConnection(JDBC_URL); - Statement s = connection.createStatement()) { - s.execute("create table t (i int)"); - assertEquals(s.getUpdateCount(), -1); - assertEquals(s.executeUpdate("insert into t values (1)"), 1); - assertFalse(s.execute("insert into t values (1)")); - assertEquals(s.getUpdateCount(), 1); - - // result is invalidated after a call - assertEquals(s.getUpdateCount(), -1); - } - } - - public static void test_get_result_set() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - try (PreparedStatement p = conn.prepareStatement("select 1")) { - p.executeQuery(); - try (ResultSet resultSet = p.getResultSet()) { - assertNotNull(resultSet); - } - assertNull(p.getResultSet()); // returns null after initial call - } - - try (Statement s = conn.createStatement()) { - s.execute("select 1"); - try (ResultSet resultSet = s.getResultSet()) { - assertNotNull(resultSet); - } - assertFalse(s.getMoreResults()); - assertNull(s.getResultSet()); // returns null after initial call - } - } - } - - // https://github.com/duckdb/duckdb/issues/7218 - public static void test_unknown_result_type() throws Exception { - try (Connection connection = DriverManager.getConnection(JDBC_URL); - PreparedStatement p = connection.prepareStatement( - "select generate_series.generate_series from generate_series(?, ?) order by 1")) { - p.setInt(1, 0); - p.setInt(2, 1); - - try (ResultSet rs = p.executeQuery()) { - rs.next(); - assertEquals(rs.getInt(1), 0); - rs.next(); - assertEquals(rs.getInt(1), 1); - } - } - } - - static List trio(Object... max) { - return asList(emptyList(), asList(max), null); - } - - static DuckDBResultSet.DuckDBBlobResult blobOf(String source) { - return new DuckDBResultSet.DuckDBBlobResult(ByteBuffer.wrap(source.getBytes())); - } - - private static final DateTimeFormatter FORMAT_DATE = new DateTimeFormatterBuilder() - .parseCaseInsensitive() - .appendValue(YEAR_OF_ERA) - .appendLiteral('-') - .appendValue(MONTH_OF_YEAR, 2) - .appendLiteral('-') - .appendValue(DAY_OF_MONTH, 2) - .toFormatter() - .withResolverStyle(ResolverStyle.LENIENT); - public static final DateTimeFormatter FORMAT_DATETIME = new DateTimeFormatterBuilder() - .append(FORMAT_DATE) - .appendLiteral('T') - .append(ISO_LOCAL_TIME) - .toFormatter() - .withResolverStyle(ResolverStyle.LENIENT); - public static final DateTimeFormatter FORMAT_TZ = new DateTimeFormatterBuilder() - .append(FORMAT_DATETIME) - .appendLiteral('+') - .appendValue(OFFSET_SECONDS) - .toFormatter() - .withResolverStyle(ResolverStyle.LENIENT); - - static Map mapOf(Object... pairs) { - Map result = new HashMap<>(pairs.length / 2); - for (int i = 0; i < pairs.length - 1; i += 2) { - result.put((K) pairs[i], (V) pairs[i + 1]); - } - return result; - } - - static Map> correct_answer_map = new HashMap<>(); - static { - correct_answer_map.put("int_array", trio(42, 999, null, null, -42)); - correct_answer_map.put("double_array", - trio(42.0, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, null, -42.0)); - correct_answer_map.put( - "date_array", trio(LocalDate.parse("1970-01-01"), LocalDate.parse("5881580-07-11", FORMAT_DATE), - LocalDate.parse("-5877641-06-24", FORMAT_DATE), null, LocalDate.parse("2022-05-12"))); - correct_answer_map.put("timestamp_array", trio(Timestamp.valueOf("1970-01-01 00:00:00.0"), - DuckDBTimestamp.toSqlTimestamp(9223372036854775807L), - DuckDBTimestamp.toSqlTimestamp(-9223372036854775807L), null, - Timestamp.valueOf("2022-05-12 16:23:45.0"))); - correct_answer_map.put("timestamptz_array", trio(OffsetDateTime.parse("1970-01-01T00:00Z"), - OffsetDateTime.parse("+294247-01-10T04:00:54.775807Z"), - OffsetDateTime.parse("-290308-12-21T19:59:05.224193Z"), null, - OffsetDateTime.parse("2022-05-12T23:23:45Z"))); - correct_answer_map.put("varchar_array", trio("🦆🦆🦆🦆🦆🦆", "goose", null, "")); - List numbers = asList(42, 999, null, null, -42); - correct_answer_map.put("nested_int_array", trio(emptyList(), numbers, null, emptyList(), numbers)); - Map abnull = mapOf("a", null, "b", null); - correct_answer_map.put( - "struct_of_arrays", - asList(abnull, mapOf("a", numbers, "b", asList("🦆🦆🦆🦆🦆🦆", "goose", null, "")), null)); - Map ducks = mapOf("a", 42, "b", "🦆🦆🦆🦆🦆🦆"); - correct_answer_map.put("array_of_structs", trio(abnull, ducks, null)); - correct_answer_map.put("bool", asList(false, true, null)); - correct_answer_map.put("tinyint", asList((byte) -128, (byte) 127, null)); - correct_answer_map.put("smallint", asList((short) -32768, (short) 32767, null)); - correct_answer_map.put("int", asList(-2147483648, 2147483647, null)); - correct_answer_map.put("bigint", asList(-9223372036854775808L, 9223372036854775807L, null)); - correct_answer_map.put("hugeint", asList(new BigInteger("-170141183460469231731687303715884105728"), - new BigInteger("170141183460469231731687303715884105727"), null)); - correct_answer_map.put( - "uhugeint", asList(new BigInteger("0"), new BigInteger("340282366920938463463374607431768211455"), null)); - correct_answer_map.put("utinyint", asList((short) 0, (short) 255, null)); - correct_answer_map.put("usmallint", asList(0, 65535, null)); - correct_answer_map.put("uint", asList(0L, 4294967295L, null)); - correct_answer_map.put("ubigint", asList(BigInteger.ZERO, new BigInteger("18446744073709551615"), null)); - correct_answer_map.put("time", asList(LocalTime.of(0, 0), LocalTime.parse("23:59:59.999999"), null)); - correct_answer_map.put("float", asList(-3.4028234663852886e+38f, 3.4028234663852886e+38f, null)); - correct_answer_map.put("double", asList(-1.7976931348623157e+308d, 1.7976931348623157e+308d, null)); - correct_answer_map.put("dec_4_1", asList(new BigDecimal("-999.9"), (new BigDecimal("999.9")), null)); - correct_answer_map.put("dec_9_4", asList(new BigDecimal("-99999.9999"), (new BigDecimal("99999.9999")), null)); - correct_answer_map.put( - "dec_18_6", asList(new BigDecimal("-999999999999.999999"), (new BigDecimal("999999999999.999999")), null)); - correct_answer_map.put("dec38_10", asList(new BigDecimal("-9999999999999999999999999999.9999999999"), - (new BigDecimal("9999999999999999999999999999.9999999999")), null)); - correct_answer_map.put("uuid", asList(UUID.fromString("00000000-0000-0000-0000-000000000000"), - (UUID.fromString("ffffffff-ffff-ffff-ffff-ffffffffffff")), null)); - correct_answer_map.put("varchar", asList("🦆🦆🦆🦆🦆🦆", "goo\u0000se", null)); - correct_answer_map.put("json", asList("🦆🦆🦆🦆🦆", "goose", null)); - correct_answer_map.put( - "blob", asList(blobOf("thisisalongblob\u0000withnullbytes"), blobOf("\u0000\u0000\u0000a"), null)); - correct_answer_map.put("bit", asList("0010001001011100010101011010111", "10101", null)); - correct_answer_map.put("small_enum", asList("DUCK_DUCK_ENUM", "GOOSE", null)); - correct_answer_map.put("medium_enum", asList("enum_0", "enum_299", null)); - correct_answer_map.put("large_enum", asList("enum_0", "enum_69999", null)); - correct_answer_map.put("struct", asList(abnull, ducks, null)); - correct_answer_map.put("map", - asList(mapOf(), mapOf("key1", "🦆🦆🦆🦆🦆🦆", "key2", "goose"), null)); - correct_answer_map.put("union", asList("Frank", (short) 5, null)); - correct_answer_map.put( - "time_tz", asList(OffsetTime.parse("00:00+15:59:59"), OffsetTime.parse("23:59:59.999999-15:59:59"), null)); - correct_answer_map.put("interval", asList("00:00:00", "83 years 3 months 999 days 00:16:39.999999", null)); - correct_answer_map.put("timestamp", asList(DuckDBTimestamp.toSqlTimestamp(-9223372022400000000L), - DuckDBTimestamp.toSqlTimestamp(9223372036854775807L), null)); - correct_answer_map.put("date", asList(LocalDate.of(-5877641, 6, 25), LocalDate.of(5881580, 7, 10), null)); - correct_answer_map.put("timestamp_s", - asList(Timestamp.valueOf(LocalDateTime.of(-290308, 12, 22, 0, 0)), - Timestamp.valueOf(LocalDateTime.of(294247, 1, 10, 4, 0, 54)), null)); - correct_answer_map.put("timestamp_ns", - asList(Timestamp.valueOf(LocalDateTime.parse("1677-09-21T00:12:43.145225")), - Timestamp.valueOf(LocalDateTime.parse("2262-04-11T23:47:16.854775")), null)); - correct_answer_map.put("timestamp_ms", - asList(Timestamp.valueOf(LocalDateTime.of(-290308, 12, 22, 0, 0, 0)), - Timestamp.valueOf(LocalDateTime.of(294247, 1, 10, 4, 0, 54, 775000000)), null)); - correct_answer_map.put( - "timestamp_tz", - asList(OffsetDateTime.of(LocalDateTime.of(-290308, 12, 22, 0, 0, 0), ZoneOffset.UTC), - OffsetDateTime.of(LocalDateTime.of(294247, 1, 10, 4, 0, 54, 775806000), ZoneOffset.UTC), null)); - - List int_array = asList(null, 2, 3); - List varchar_array = asList("a", null, "c"); - List int_list = asList(4, 5, 6); - List def = asList("d", "e", "f"); - - correct_answer_map.put("fixed_int_array", asList(int_array, int_list, null)); - correct_answer_map.put("fixed_varchar_array", asList(varchar_array, def, null)); - correct_answer_map.put("fixed_nested_int_array", - asList(asList(int_array, null, int_array), asList(int_list, int_array, int_list), null)); - correct_answer_map.put("fixed_nested_varchar_array", asList(asList(varchar_array, null, varchar_array), - asList(def, varchar_array, def), null)); - - correct_answer_map.put("fixed_struct_array", - asList(asList(abnull, ducks, abnull), asList(ducks, abnull, ducks), null)); - - correct_answer_map.put("struct_of_fixed_array", - asList(mapOf("a", int_array, "b", varchar_array), mapOf("a", int_list, "b", def), null)); - - correct_answer_map.put("fixed_array_of_int_list", asList(asList(emptyList(), numbers, emptyList()), - asList(numbers, emptyList(), numbers), null)); - - correct_answer_map.put("list_of_fixed_int_array", asList(asList(int_array, int_list, int_array), - asList(int_list, int_array, int_list), null)); - } - - public static void test_all_types() throws Exception { - Logger logger = Logger.getAnonymousLogger(); - String sql = - "select * EXCLUDE(time, time_tz)" - + "\n , CASE WHEN time = '24:00:00'::TIME THEN '23:59:59.999999'::TIME ELSE time END AS time" - + - "\n , CASE WHEN time_tz = '24:00:00-15:59:59'::TIMETZ THEN '23:59:59.999999-15:59:59'::TIMETZ ELSE time_tz END AS time_tz" - + "\nfrom test_all_types()"; - - try (Connection conn = DriverManager.getConnection(JDBC_URL); - PreparedStatement stmt = conn.prepareStatement(sql)) { - conn.createStatement().execute("set timezone = 'UTC'"); - - try (ResultSet rs = stmt.executeQuery()) { - ResultSetMetaData metaData = rs.getMetaData(); - - int rowIdx = 0; - while (rs.next()) { - for (int i = 0; i < metaData.getColumnCount(); i++) { - String columnName = metaData.getColumnName(i + 1); - List answers = correct_answer_map.get(columnName); - Object expected = answers.get(rowIdx); - - Object actual = toJavaObject(rs.getObject(i + 1)); - - if (actual instanceof Timestamp && expected instanceof Timestamp) { - assertEquals(((Timestamp) actual).getTime(), ((Timestamp) expected).getTime(), 500); - } else if (actual instanceof List) { - assertListsEqual((List) actual, (List) expected); - } else { - assertEquals(actual, expected); - } - } - rowIdx++; - } - } - } - } - - private static Map structToMap(DuckDBStruct actual) throws SQLException { - Map map = actual.getMap(); - Map result = new HashMap<>(); - map.forEach((key, value) -> result.put(key, toJavaObject(value))); - return result; - } - - private static void assertListsEqual(List actual, List expected) throws Exception { - assertEquals(actual.size(), expected.size()); - - ListIterator itera = actual.listIterator(); - ListIterator itere = expected.listIterator(); - - while (itera.hasNext()) { - assertEquals(itera.next(), itere.next()); - } - } - - public static void test_cancel() throws Exception { - ExecutorService service = Executors.newFixedThreadPool(1); - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement()) { - Future thread = service.submit( - () - -> assertThrows(() - -> stmt.execute("select count(*) from range(10000000) t1, range(1000000) t2;"), - SQLException.class)); - Thread.sleep(500); // wait for query to start running - stmt.cancel(); - String message = thread.get(1, TimeUnit.SECONDS); - assertEquals(message, "INTERRUPT Error: Interrupted!"); - } - } - - public static void test_prepared_statement_metadata() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); - PreparedStatement stmt = conn.prepareStatement("SELECT 'hello' as world")) { - ResultSetMetaData metadata = stmt.getMetaData(); - assertEquals(metadata.getColumnCount(), 1); - assertEquals(metadata.getColumnName(1), "world"); - assertEquals(metadata.getColumnType(1), Types.VARCHAR); - } - } - - public static void test_unbindable_query() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); - PreparedStatement stmt = conn.prepareStatement("SELECT ?, ?")) { - stmt.setString(1, "word1"); - stmt.setInt(2, 42); - - ResultSetMetaData meta = stmt.getMetaData(); - assertEquals(meta.getColumnCount(), 1); - assertEquals(meta.getColumnName(1), "unknown"); - assertEquals(meta.getColumnTypeName(1), "UNKNOWN"); - assertEquals(meta.getColumnType(1), Types.JAVA_OBJECT); - - try (ResultSet resultSet = stmt.executeQuery()) { - ResultSetMetaData metadata = resultSet.getMetaData(); - - assertEquals(metadata.getColumnCount(), 2); - - assertEquals(metadata.getColumnName(1), "$1"); - assertEquals(metadata.getColumnTypeName(1), "VARCHAR"); - assertEquals(metadata.getColumnType(1), Types.VARCHAR); - - assertEquals(metadata.getColumnName(2), "$2"); - assertEquals(metadata.getColumnTypeName(2), "INTEGER"); - assertEquals(metadata.getColumnType(2), Types.INTEGER); - - resultSet.next(); - assertEquals(resultSet.getString(1), "word1"); - assertEquals(resultSet.getInt(2), 42); - } - } - } - - public static void test_labels_with_prepped_statement() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - try (PreparedStatement stmt = conn.prepareStatement("SELECT ? as result")) { - stmt.setString(1, "Quack"); - try (ResultSet rs = stmt.executeQuery()) { - while (rs.next()) { - assertEquals(rs.getObject("result"), "Quack"); - } - } - } - } - } - - public static void test_execute_updated_on_prep_stmt() throws SQLException { - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement s = conn.createStatement()) { - s.executeUpdate("create table t (i int)"); - - try (PreparedStatement p = conn.prepareStatement("insert into t (i) select ?")) { - p.setInt(1, 1); - p.executeUpdate(); - } - } - } - - public static void test_invalid_execute_calls() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - try (Statement s = conn.createStatement()) { - s.execute("create table test (id int)"); - } - try (PreparedStatement s = conn.prepareStatement("select 1")) { - String msg = assertThrows(s::executeUpdate, SQLException.class); - assertTrue(msg.contains("can only be used with queries that return nothing") && - msg.contains("or update rows")); - } - try (PreparedStatement s = conn.prepareStatement("insert into test values (1)")) { - String msg = assertThrows(s::executeQuery, SQLException.class); - assertTrue(msg.contains("can only be used with queries that return a ResultSet")); - } - } - } - - public static void test_race() throws Exception { - try (Connection connection = DriverManager.getConnection(JDBC_URL)) { - ExecutorService executorService = Executors.newFixedThreadPool(10); - - List> tasks = Collections.nCopies(1000, () -> { - try { - try (PreparedStatement ps = connection.prepareStatement( - "SELECT count(*) FROM information_schema.tables WHERE table_name = 'test' LIMIT 1;")) { - ps.execute(); - } - } catch (SQLException e) { - throw new RuntimeException(e); - } - return null; - }); - List> results = executorService.invokeAll(tasks); - - try { - for (Future future : results) { - future.get(); - } - } catch (java.util.concurrent.ExecutionException ee) { - assertEquals( - ee.getCause().getCause().getMessage(), - "Invalid Input Error: Attempting to execute an unsuccessful or closed pending query result"); - } - } - } - - public static void test_stream_multiple_open_results() throws Exception { - Properties props = new Properties(); - props.setProperty(JDBC_STREAM_RESULTS, String.valueOf(true)); - - String QUERY = "SELECT * FROM range(100000)"; - try (Connection conn = DriverManager.getConnection(JDBC_URL, props); Statement stmt1 = conn.createStatement(); - Statement stmt2 = conn.createStatement()) { - - try (ResultSet rs1 = stmt1.executeQuery(QUERY); ResultSet ignored = stmt2.executeQuery(QUERY)) { - assertThrows(rs1::next, SQLException.class); - } - } - } - - public static void test_offset_limit() throws Exception { - try (Connection connection = DriverManager.getConnection(JDBC_URL); - Statement s = connection.createStatement()) { - s.executeUpdate("create table t (i int not null)"); - s.executeUpdate("insert into t values (1), (1), (2), (3), (3), (3)"); - - try (PreparedStatement ps = - connection.prepareStatement("select t.i from t order by t.i limit ? offset ?")) { - ps.setLong(1, 2); - ps.setLong(2, 1); - - try (ResultSet rs = ps.executeQuery()) { - assertTrue(rs.next()); - assertEquals(1, rs.getInt(1)); - assertTrue(rs.next()); - assertEquals(2, rs.getInt(1)); - assertFalse(rs.next()); - } - } - } - } - - public static void test_UUID_binding() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); - PreparedStatement statement = conn.prepareStatement("select '0b17ce61-375c-4ad8-97b3-349d96d35ab1'::UUID"); - ResultSet resultSet = statement.executeQuery()) { - resultSet.next(); - assertEquals(UUID.fromString("0b17ce61-375c-4ad8-97b3-349d96d35ab1"), resultSet.getObject(1)); - } - } - - public static void test_result_streaming() throws Exception { - Properties props = new Properties(); - props.setProperty(JDBC_STREAM_RESULTS, String.valueOf(true)); - - try (Connection conn = DriverManager.getConnection(JDBC_URL, props); - PreparedStatement stmt1 = conn.prepareStatement("SELECT * FROM range(100000)"); - ResultSet rs = stmt1.executeQuery()) { - while (rs.next()) { - rs.getInt(1); - } - assertFalse(rs.next()); // is exhausted - } - } - - public static void test_struct_use_after_free() throws Exception { - Object struct, array; - try (Connection conn = DriverManager.getConnection(JDBC_URL); - PreparedStatement stmt = conn.prepareStatement("SELECT struct_pack(hello := 2), [42]"); - ResultSet rs = stmt.executeQuery()) { - rs.next(); - struct = rs.getObject(1); - array = rs.getObject(2); - } - assertEquals(struct.toString(), "{hello=2}"); - assertEquals(array.toString(), "[42]"); - } - - public static void test_user_agent_default() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - assertEquals(getSetting(conn, "custom_user_agent"), ""); - - try (PreparedStatement stmt1 = conn.prepareStatement("PRAGMA user_agent"); - ResultSet rs = stmt1.executeQuery()) { - assertTrue(rs.next()); - assertTrue(rs.getString(1).matches("duckdb/.*(.*) jdbc")); - } - } - } - - public static void test_user_agent_custom() throws Exception { - Properties props = new Properties(); - props.setProperty(DUCKDB_USER_AGENT_PROPERTY, "CUSTOM_STRING"); - - try (Connection conn = DriverManager.getConnection(JDBC_URL, props)) { - assertEquals(getSetting(conn, "custom_user_agent"), "CUSTOM_STRING"); - - try (PreparedStatement stmt1 = conn.prepareStatement("PRAGMA user_agent"); - ResultSet rs = stmt1.executeQuery()) { - assertTrue(rs.next()); - assertTrue(rs.getString(1).matches("duckdb/.*(.*) jdbc CUSTOM_STRING")); - } - } - } - - public static void test_batch_prepared_statement() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - try (Statement s = conn.createStatement()) { - s.execute("CREATE TABLE test (x INT, y INT, z INT)"); - } - try (PreparedStatement ps = conn.prepareStatement("INSERT INTO test (x, y, z) VALUES (?, ?, ?);")) { - ps.setObject(1, 1); - ps.setObject(2, 2); - ps.setObject(3, 3); - ps.addBatch(); - - ps.setObject(1, 4); - ps.setObject(2, 5); - ps.setObject(3, 6); - ps.addBatch(); - - ps.executeBatch(); - } - try (Statement s = conn.createStatement(); ResultSet rs = s.executeQuery("SELECT * FROM test ORDER BY x")) { - rs.next(); - assertEquals(rs.getInt(1), rs.getObject(1, Integer.class)); - assertEquals(rs.getObject(1, Integer.class), 1); - - assertEquals(rs.getInt(2), rs.getObject(2, Integer.class)); - assertEquals(rs.getObject(2, Integer.class), 2); - - assertEquals(rs.getInt(3), rs.getObject(3, Integer.class)); - assertEquals(rs.getObject(3, Integer.class), 3); - - rs.next(); - assertEquals(rs.getInt(1), rs.getObject(1, Integer.class)); - assertEquals(rs.getObject(1, Integer.class), 4); - - assertEquals(rs.getInt(2), rs.getObject(2, Integer.class)); - assertEquals(rs.getObject(2, Integer.class), 5); - - assertEquals(rs.getInt(3), rs.getObject(3, Integer.class)); - assertEquals(rs.getObject(3, Integer.class), 6); - } - } - } - - public static void test_batch_statement() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - try (Statement s = conn.createStatement()) { - s.execute("CREATE TABLE test (x INT, y INT, z INT)"); - - s.addBatch("INSERT INTO test (x, y, z) VALUES (1, 2, 3);"); - s.addBatch("INSERT INTO test (x, y, z) VALUES (4, 5, 6);"); - - s.executeBatch(); - } - try (Statement s2 = conn.createStatement(); - ResultSet rs = s2.executeQuery("SELECT * FROM test ORDER BY x")) { - rs.next(); - assertEquals(rs.getInt(1), rs.getObject(1, Integer.class)); - assertEquals(rs.getObject(1, Integer.class), 1); - - assertEquals(rs.getInt(2), rs.getObject(2, Integer.class)); - assertEquals(rs.getObject(2, Integer.class), 2); - - assertEquals(rs.getInt(3), rs.getObject(3, Integer.class)); - assertEquals(rs.getObject(3, Integer.class), 3); - - rs.next(); - assertEquals(rs.getInt(1), rs.getObject(1, Integer.class)); - assertEquals(rs.getObject(1, Integer.class), 4); - - assertEquals(rs.getInt(2), rs.getObject(2, Integer.class)); - assertEquals(rs.getObject(2, Integer.class), 5); - - assertEquals(rs.getInt(3), rs.getObject(3, Integer.class)); - assertEquals(rs.getObject(3, Integer.class), 6); - } - } - } - - public static void test_execute_while_batch() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - try (Statement s = conn.createStatement()) { - s.execute("CREATE TABLE test (id INT)"); - } - try (PreparedStatement ps = conn.prepareStatement("INSERT INTO test (id) VALUES (?)")) { - ps.setObject(1, 1); - ps.addBatch(); - - String msg = - assertThrows(() -> { ps.execute("INSERT INTO test (id) VALUES (1);"); }, SQLException.class); - assertTrue(msg.contains("Batched queries must be executed with executeBatch.")); - - String msg2 = - assertThrows(() -> { ps.executeUpdate("INSERT INTO test (id) VALUES (1);"); }, SQLException.class); - assertTrue(msg2.contains("Batched queries must be executed with executeBatch.")); - - String msg3 = assertThrows(() -> { ps.executeQuery("SELECT * FROM test"); }, SQLException.class); - assertTrue(msg3.contains("Batched queries must be executed with executeBatch.")); - } - } - } - - public static void test_prepared_statement_batch_exception() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL)) { - try (Statement s = conn.createStatement()) { - s.execute("CREATE TABLE test (id INT)"); - } - try (PreparedStatement ps = conn.prepareStatement("INSERT INTO test (id) VALUES (?)")) { - String msg = assertThrows(() -> { ps.addBatch("DUMMY SQL"); }, SQLException.class); - assertTrue(msg.contains("Cannot add batched SQL statement to PreparedStatement")); - } - } - } - - public static void test_get_binary_stream() throws Exception { - try (Connection connection = DriverManager.getConnection("jdbc:duckdb:"); - PreparedStatement s = connection.prepareStatement("select ?")) { - s.setObject(1, "YWJj".getBytes()); - String out = null; - - try (ResultSet rs = s.executeQuery()) { - while (rs.next()) { - out = blob_to_string(rs.getBlob(1)); - } - } - - assertEquals(out, "YWJj"); - } - } - - public static void test_fractional_time() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); - PreparedStatement stmt = conn.prepareStatement("SELECT '01:02:03.123'::TIME"); - ResultSet rs = stmt.executeQuery()) { - assertTrue(rs.next()); - assertEquals(rs.getTime(1), Time.valueOf(LocalTime.of(1, 2, 3, 123))); - } - } - - public static void main(String[] args) throws Exception { - System.exit(runTests(args, TestDuckDBJDBC.class, TestExtensionTypes.class)); - } -} diff --git a/tools/jdbc/src/test/java/org/duckdb/TestExtensionTypes.java b/tools/jdbc/src/test/java/org/duckdb/TestExtensionTypes.java deleted file mode 100644 index aa964dbede0..00000000000 --- a/tools/jdbc/src/test/java/org/duckdb/TestExtensionTypes.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.duckdb; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.Statement; -import java.sql.Types; - -import static org.duckdb.test.Assertions.assertEquals; -import static org.duckdb.TestDuckDBJDBC.JDBC_URL; - -public class TestExtensionTypes { - - public static void test_extension_type() throws Exception { - try (Connection connection = DriverManager.getConnection(JDBC_URL); - Statement stmt = connection.createStatement()) { - - DuckDBNative.duckdb_jdbc_create_extension_type((DuckDBConnection) connection); - - try (ResultSet rs = stmt.executeQuery( - "SELECT {\"hello\": 'foo', \"world\": 'bar'}::test_type, '\\xAA'::byte_test_type")) { - rs.next(); - assertEquals(rs.getObject(1), "{'hello': foo, 'world': bar}"); - assertEquals(rs.getObject(2), "\\xAA"); - } - } - } - - public static void test_extension_type_metadata() throws Exception { - try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement();) { - DuckDBNative.duckdb_jdbc_create_extension_type((DuckDBConnection) conn); - - stmt.execute("CREATE TABLE test (foo test_type, bar byte_test_type);"); - stmt.execute("INSERT INTO test VALUES ({\"hello\": 'foo', \"world\": 'bar'}, '\\xAA');"); - - try (ResultSet rs = stmt.executeQuery("SELECT * FROM test")) { - ResultSetMetaData meta = rs.getMetaData(); - assertEquals(meta.getColumnCount(), 2); - - assertEquals(meta.getColumnName(1), "foo"); - assertEquals(meta.getColumnTypeName(1), "test_type"); - assertEquals(meta.getColumnType(1), Types.JAVA_OBJECT); - assertEquals(meta.getColumnClassName(1), "java.lang.String"); - - assertEquals(meta.getColumnName(2), "bar"); - assertEquals(meta.getColumnTypeName(2), "byte_test_type"); - assertEquals(meta.getColumnType(2), Types.JAVA_OBJECT); - assertEquals(meta.getColumnClassName(2), "java.lang.String"); - } - } - } -} diff --git a/tools/jdbc/src/test/java/org/duckdb/test/Assertions.java b/tools/jdbc/src/test/java/org/duckdb/test/Assertions.java deleted file mode 100644 index f2d82e68b3a..00000000000 --- a/tools/jdbc/src/test/java/org/duckdb/test/Assertions.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.duckdb.test; - -import org.duckdb.test.Thrower; - -import java.util.Objects; -import java.util.function.Function; - -public class Assertions { - public static void assertTrue(boolean val) throws Exception { - assertTrue(val, null); - } - - public static void assertTrue(boolean val, String message) throws Exception { - if (!val) { - throw new Exception(message); - } - } - - public static void assertFalse(boolean val) throws Exception { - assertTrue(!val); - } - - public static void assertEquals(Object actual, Object expected) throws Exception { - Function getClass = (Object a) -> a == null ? "null" : a.getClass().toString(); - - String message = String.format("\"%s\" (of %s) should equal \"%s\" (of %s)", actual, getClass.apply(actual), - expected, getClass.apply(expected)); - assertTrue(Objects.equals(actual, expected), message); - } - - public static void assertNotNull(Object a) throws Exception { - assertFalse(a == null); - } - - public static void assertNull(Object a) throws Exception { - assertEquals(a, null); - } - - public static void assertEquals(double a, double b, double epsilon) throws Exception { - assertTrue(Math.abs(a - b) < epsilon); - } - - public static void fail() throws Exception { - fail(null); - } - - public static void fail(String s) throws Exception { - throw new Exception(s); - } - - public static String assertThrows(Thrower thrower, Class exception) throws Exception { - return assertThrows(exception, thrower).getMessage(); - } - - private static Throwable assertThrows(Class exception, Thrower thrower) throws Exception { - try { - thrower.run(); - } catch (Throwable e) { - if (!exception.isAssignableFrom(e.getClass())) { - throw new Exception("Expected to throw " + exception.getName() + ", but threw " + - e.getClass().getName()); - } - return e; - } - throw new Exception("Expected to throw " + exception.getName() + ", but no exception thrown"); - } - - // Asserts we are either throwing the correct exception, or not throwing at all - public static boolean assertThrowsMaybe(Thrower thrower, Class exception) - throws Exception { - try { - thrower.run(); - return true; - } catch (Throwable e) { - if (e.getClass().equals(exception)) { - return true; - } else { - throw new Exception("Unexpected exception: " + e.getClass().getName()); - } - } - } -} diff --git a/tools/jdbc/src/test/java/org/duckdb/test/Runner.java b/tools/jdbc/src/test/java/org/duckdb/test/Runner.java deleted file mode 100644 index adae889cbda..00000000000 --- a/tools/jdbc/src/test/java/org/duckdb/test/Runner.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.duckdb.test; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -public class Runner { - static { - try { - Class.forName("org.duckdb.DuckDBDriver"); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - public static int runTests(String[] args, Class... testClasses) { - // Woo I can do reflection too, take this, JUnit! - List methods = Arrays.stream(testClasses) - .flatMap(clazz -> Arrays.stream(clazz.getMethods())) - .sorted(Comparator.comparing(Method::getName)) - .collect(Collectors.toList()); - - String specific_test = null; - if (args.length >= 1) { - specific_test = args[0]; - } - - boolean anySucceeded = false; - boolean anyFailed = false; - for (Method m : methods) { - if (m.getName().startsWith("test_")) { - if (specific_test != null && !m.getName().contains(specific_test)) { - continue; - } - System.out.print(m.getDeclaringClass().getSimpleName() + "#" + m.getName() + " "); - - LocalDateTime start = LocalDateTime.now(); - try { - m.invoke(null); - System.out.println("success in " + Duration.between(start, LocalDateTime.now()).getSeconds() + - " seconds"); - } catch (Throwable t) { - if (t instanceof InvocationTargetException) { - t = t.getCause(); - } - System.out.println("failed with " + t); - t.printStackTrace(System.out); - anyFailed = true; - } - anySucceeded = true; - } - } - if (!anySucceeded) { - System.out.println("No tests found that match " + specific_test); - return 1; - } - System.out.println(anyFailed ? "FAILED" : "OK"); - - return anyFailed ? 1 : 0; - } -} diff --git a/tools/jdbc/src/test/java/org/duckdb/test/Thrower.java b/tools/jdbc/src/test/java/org/duckdb/test/Thrower.java deleted file mode 100644 index aee40b48e05..00000000000 --- a/tools/jdbc/src/test/java/org/duckdb/test/Thrower.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.duckdb.test; - -public interface Thrower { - void run() throws Exception; -} diff --git a/tools/juliapkg/Project.toml b/tools/juliapkg/Project.toml index 6914a8f38ee..061d50a90ab 100644 --- a/tools/juliapkg/Project.toml +++ b/tools/juliapkg/Project.toml @@ -1,7 +1,7 @@ name = "DuckDB" uuid = "d2f5444f-75bc-4fdf-ac35-56f514c445e1" authors = ["Mark Raasveldt "] -version = "0.10.2" +version = "1.0.0" [deps] DBInterface = "a10d1c49-ce27-4219-8d33-6db1a4562965" @@ -14,7 +14,7 @@ WeakRefStrings = "ea10d353-3f73-51f8-a26c-33c1cb351aa5" [compat] DBInterface = "2.5" -DuckDB_jll = "0.10.2" +DuckDB_jll = "1.0.0" FixedPointDecimals = "0.4, 0.5" Tables = "1.7" WeakRefStrings = "1.4" diff --git a/tools/juliapkg/release.py b/tools/juliapkg/release.py index ba2f0d1cbdd..8d1d09fa3c1 100644 --- a/tools/juliapkg/release.py +++ b/tools/juliapkg/release.py @@ -36,7 +36,13 @@ def run_syscall(syscall, ignore_failure=False): proc = subprocess.Popen(['git', 'show-ref', '--tags'], stdout=subprocess.PIPE) tags = [x for x in proc.stdout.read().decode('utf8').split('\n') if len(x) > 0 and 'master-builds' not in x] -tags.sort(key=lambda x: int(x.split('refs/tags/')[1].split('.')[1])) + +def extract_tag(x): + keys = x.split('refs/tags/')[1].lstrip('v').split('.') + return int(keys[0]) * 10000000 + int(keys[1]) * 10000 + int(keys[2]) + + +tags.sort(key=extract_tag) # latest tag splits = tags[-1].split(' ') diff --git a/tools/juliapkg/src/appender.jl b/tools/juliapkg/src/appender.jl index 3bd070a9a86..7992973c6b0 100644 --- a/tools/juliapkg/src/appender.jl +++ b/tools/juliapkg/src/appender.jl @@ -1,6 +1,8 @@ using Dates """ + Appender(db_connection, table, [schema]) + An appender object that can be used to append rows to an existing table. * DateTime objects in Julia are stored in milliseconds since the Unix epoch but are converted to microseconds when stored in duckdb. @@ -38,9 +40,9 @@ DuckDB.close(appender) mutable struct Appender handle::duckdb_appender - function Appender(con::Connection, table::AbstractString) + function Appender(con::Connection, table::AbstractString, schema::Union{AbstractString, Nothing} = nothing) handle = Ref{duckdb_appender}() - if duckdb_appender_create(con.handle, C_NULL, table, handle) != DuckDBSuccess + if duckdb_appender_create(con.handle, something(schema, C_NULL), table, handle) != DuckDBSuccess error_ptr = duckdb_appender_error(handle) if error_ptr == C_NULL error_message = string("Opening of Appender for table \"", table, "\" failed: unknown error") @@ -54,8 +56,8 @@ mutable struct Appender finalizer(_close_appender, con) return con end - function Appender(db::DB, table::AbstractString) - return Appender(db.main_connection, table) + function Appender(db::DB, table::AbstractString, schema::Union{AbstractString, Nothing} = nothing) + return Appender(db.main_connection, table, schema) end end diff --git a/tools/juliapkg/src/result.jl b/tools/juliapkg/src/result.jl index f7e0b622d88..4c14bf54a0a 100644 --- a/tools/juliapkg/src/result.jl +++ b/tools/juliapkg/src/result.jl @@ -40,8 +40,8 @@ function _close_result(result::QueryResult) return end -mutable struct ColumnConversionData - chunks::Vector{DataChunk} +mutable struct ColumnConversionData{ChunksT <: Union{Vector{DataChunk}, Tuple{DataChunk}}} + chunks::ChunksT col_idx::Int64 logical_type::LogicalType conversion_data::Any @@ -804,6 +804,65 @@ DBInterface.close!(q::QueryResult) = _close_result(q) Base.iterate(q::QueryResult) = iterate(Tables.rows(Tables.columns(q))) Base.iterate(q::QueryResult, state) = iterate(Tables.rows(Tables.columns(q)), state) +struct QueryResultChunk + tbl::NamedTuple +end + +function Tables.columns(chunk::QueryResultChunk) + return Tables.CopiedColumns(chunk.tbl) +end + +Tables.istable(::Type{QueryResultChunk}) = true +Tables.isrowtable(::Type{QueryResultChunk}) = true +Tables.columnaccess(::Type{QueryResultChunk}) = true +Tables.schema(chunk::QueryResultChunk) = Tables.Schema(chunk.q.names, chunk.q.types) + +struct QueryResultChunkIterator + q::QueryResult + column_count::UInt64 +end + +function next_chunk(iter::QueryResultChunkIterator) + chunk = DuckDB.nextDataChunk(iter.q) + if chunk === missing + return nothing + end + + return QueryResultChunk( + NamedTuple{Tuple(iter.q.names)}(ntuple(iter.column_count) do i + logical_type = LogicalType(duckdb_column_logical_type(iter.q.handle, i)) + column_data = ColumnConversionData((chunk,), i, logical_type, nothing) + return convert_column(column_data) + end) + ) +end + +Base.iterate(iter::QueryResultChunkIterator) = iterate(iter, 0x0000000000000001) + +function Base.iterate(iter::QueryResultChunkIterator, state) + if iter.q.chunk_index != state + throw( + NotImplementedException( + "Iterating chunks more than once is not supported. " * + "(Did you iterate the result of Tables.partitions() once already, call nextDataChunk or materialise QueryResult?)" + ) + ) + end + chunk = next_chunk(iter) + if chunk === nothing + return nothing + end + return (chunk, state + 1) +end + +Base.IteratorSize(::Type{QueryResultChunkIterator}) = Base.SizeUnknown() +Base.eltype(iter::QueryResultChunkIterator) = Any + +function Tables.partitions(q::QueryResult) + column_count = duckdb_column_count(q.handle) + return QueryResultChunkIterator(q, column_count) +end + function nextDataChunk(q::QueryResult)::Union{Missing, DataChunk} if duckdb_result_is_streaming(q.handle[]) chunk_handle = duckdb_stream_fetch_chunk(q.handle[]) diff --git a/tools/juliapkg/test/test_all_types.jl b/tools/juliapkg/test/test_all_types.jl index c2e0614ff8e..7c7bdb0aca8 100644 --- a/tools/juliapkg/test/test_all_types.jl +++ b/tools/juliapkg/test/test_all_types.jl @@ -77,7 +77,7 @@ ) @test isequal( df.timestamp_ns, - [Dates.DateTime(1677, 9, 21, 0, 12, 43, 146), Dates.DateTime(2262, 4, 11, 23, 47, 16, 854), missing] + [Dates.DateTime(1677, 9, 22, 0, 0, 0, 0), Dates.DateTime(2262, 4, 11, 23, 47, 16, 854), missing] ) @test isequal( df.interval, diff --git a/tools/juliapkg/test/test_appender.jl b/tools/juliapkg/test/test_appender.jl index 0f0cefea23b..3787db00177 100644 --- a/tools/juliapkg/test/test_appender.jl +++ b/tools/juliapkg/test/test_appender.jl @@ -7,20 +7,30 @@ @test_throws DuckDB.QueryException DuckDB.Appender(con, "t") end -@testset "Appender Usage" begin +@testset "Appender Usage - Schema $(schema_provided ? "Provided" : "Not Provided")" for schema_provided in (false, true) db = DBInterface.connect(DuckDB.DB) - DBInterface.execute(db, "CREATE TABLE integers(i INTEGER)") + table_name = "integers" + if schema_provided + schema_name = "test" + full_table_name = "$(schema_name).$(table_name)" + DBInterface.execute(db, "CREATE SCHEMA $(schema_name)") + else + schema_name = nothing + full_table_name = table_name + end + + DBInterface.execute(db, "CREATE TABLE $(full_table_name)(i INTEGER)") - appender = DuckDB.Appender(db, "integers") + appender = DuckDB.Appender(db, table_name, schema_name) DuckDB.close(appender) DuckDB.close(appender) # close! - appender = DuckDB.Appender(db, "integers") + appender = DuckDB.Appender(db, table_name, schema_name) DBInterface.close!(appender) - appender = DuckDB.Appender(db, "integers") + appender = DuckDB.Appender(db, table_name, schema_name) for i in 0:9 DuckDB.append(appender, i) DuckDB.end_row(appender) @@ -28,7 +38,7 @@ end DuckDB.flush(appender) DuckDB.close(appender) - results = DBInterface.execute(db, "SELECT * FROM integers") + results = DBInterface.execute(db, "SELECT * FROM $(full_table_name)") df = DataFrame(results) @test names(df) == ["i"] @test size(df, 1) == 10 diff --git a/tools/juliapkg/test/test_basic_queries.jl b/tools/juliapkg/test/test_basic_queries.jl index 12cb68c1f57..74c1befec11 100644 --- a/tools/juliapkg/test/test_basic_queries.jl +++ b/tools/juliapkg/test/test_basic_queries.jl @@ -1,5 +1,7 @@ # test_basic_queries.jl +using Tables: partitions + @testset "Test DBInterface.execute" begin con = DBInterface.connect(DuckDB.DB) @@ -134,3 +136,13 @@ end DBInterface.close!(con) end + +@testset "Test chunked response" begin + con = DBInterface.connect(DuckDB.DB) + DBInterface.execute(con, "CREATE TABLE chunked_table AS SELECT * FROM range(2049)") + result = DBInterface.execute(con, "SELECT * FROM chunked_table ;") + chunks_it = partitions(result) + chunks = collect(chunks_it) + @test length(chunks) == 2 + DBInterface.close!(con) +end diff --git a/tools/pythonpkg/MANIFEST.in b/tools/pythonpkg/MANIFEST.in index 8370540ec3a..2e090d263f2 100644 --- a/tools/pythonpkg/MANIFEST.in +++ b/tools/pythonpkg/MANIFEST.in @@ -4,4 +4,6 @@ include duckdb_python.cpp recursive-include src *.h *.hpp *.cpp recursive-include duckdb-stubs *.pyi recursive-include duckdb -include pyproject.toml \ No newline at end of file +include scripts/optional_requirements.py +include requirements-dev.txt +include pyproject.toml diff --git a/tools/pythonpkg/duckdb-stubs/__init__.pyi b/tools/pythonpkg/duckdb-stubs/__init__.pyi index 3aee662453a..7bcb25ec6f4 100644 --- a/tools/pythonpkg/duckdb-stubs/__init__.pyi +++ b/tools/pythonpkg/duckdb-stubs/__init__.pyi @@ -250,11 +250,13 @@ def ColumnExpression(column: str) -> Expression: ... def ConstantExpression(val: Any) -> Expression: ... def CaseExpression(condition: Expression, value: Expression) -> Expression: ... def FunctionExpression(function: str, *cols: Expression) -> Expression: ... +def CoalesceOperator(*cols: Expression) -> Expression: ... class DuckDBPyConnection: def __init__(self, *args, **kwargs) -> None: ... def __enter__(self) -> DuckDBPyConnection: ... def __exit__(self, exc_type: object, exc: object, traceback: object) -> None: ... + def __del__(self) -> None: ... @property def description(self) -> Optional[List[Any]]: ... @property @@ -284,7 +286,7 @@ class DuckDBPyConnection: def row_type(self, fields: Union[Dict[str, DuckDBPyType], List[str]]) -> DuckDBPyType: ... def map_type(self, key: DuckDBPyType, value: DuckDBPyType) -> DuckDBPyType: ... def duplicate(self) -> DuckDBPyConnection: ... - def execute(self, query: object, parameters: object = None, multiple_parameter_sets: bool = False) -> DuckDBPyConnection: ... + def execute(self, query: object, parameters: object = None) -> DuckDBPyConnection: ... def executemany(self, query: object, parameters: object = None) -> DuckDBPyConnection: ... def close(self) -> None: ... def interrupt(self) -> None: ... @@ -305,6 +307,7 @@ class DuckDBPyConnection: def begin(self) -> DuckDBPyConnection: ... def commit(self) -> DuckDBPyConnection: ... def rollback(self) -> DuckDBPyConnection: ... + def checkpoint(self) -> DuckDBPyConnection: ... def append(self, table_name: str, df: pandas.DataFrame, *, by_name: bool = False) -> DuckDBPyConnection: ... def register(self, view_name: str, python_object: object) -> DuckDBPyConnection: ... def unregister(self, view_name: str) -> DuckDBPyConnection: ... @@ -451,7 +454,7 @@ class DuckDBPyRelation: file_name: str, compression: Optional[str] = None ) -> None: ... - def fetch_df_chunk(self, *args, **kwargs) -> pandas.DataFrame: ... + def fetch_df_chunk(self, vectors_per_chunk: int = 1, *, date_as_object: bool = False) -> pandas.DataFrame: ... def to_table(self, table_name: str) -> None: ... def to_view(self, view_name: str, replace: bool = ...) -> DuckDBPyRelation: ... def torch(self, connection: DuckDBPyConnection = ...) -> dict: ... @@ -588,81 +591,82 @@ def tokenize(query: str) -> List[Any]: ... # Do not edit this section manually, your changes will be overwritten! # START OF CONNECTION WRAPPER -def cursor(*, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def register_filesystem(filesystem: str, *, connection: DuckDBPyConnection) -> None: ... -def unregister_filesystem(name: str, *, connection: DuckDBPyConnection) -> None: ... -def list_filesystems(*, connection: DuckDBPyConnection) -> list: ... -def filesystem_is_registered(name: str, *, connection: DuckDBPyConnection) -> bool: ... -def create_function(name: str, function: function, parameters: Optional[List[DuckDBPyType]] = None, return_type: Optional[DuckDBPyType] = None, *, type: Optional[PythonUDFType] = PythonUDFType.NATIVE, null_handling: Optional[FunctionNullHandling] = FunctionNullHandling.DEFAULT, exception_handling: Optional[PythonExceptionHandling] = PythonExceptionHandling.DEFAULT, side_effects: bool = False, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def remove_function(name: str, *, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def sqltype(type_str: str, *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def dtype(type_str: str, *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def type(type_str: str, *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def array_type(type: DuckDBPyType, size: int, *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def list_type(type: DuckDBPyType, *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def union_type(members: DuckDBPyType, *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def string_type(collation: str = "", *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def enum_type(name: str, type: DuckDBPyType, values: List[Any], *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def decimal_type(width: int, scale: int, *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def struct_type(fields: Union[Dict[str, DuckDBPyType], List[str]], *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def row_type(fields: Union[Dict[str, DuckDBPyType], List[str]], *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def map_type(key: DuckDBPyType, value: DuckDBPyType, *, connection: DuckDBPyConnection) -> DuckDBPyType: ... -def duplicate(*, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def execute(query: object, parameters: object = None, multiple_parameter_sets: bool = False, *, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def executemany(query: object, parameters: object = None, *, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def close(*, connection: DuckDBPyConnection) -> None: ... -def interrupt(*, connection: DuckDBPyConnection) -> None: ... -def fetchone(*, connection: DuckDBPyConnection) -> Optional[tuple]: ... -def fetchmany(size: int = 1, *, connection: DuckDBPyConnection) -> List[Any]: ... -def fetchall(*, connection: DuckDBPyConnection) -> List[Any]: ... -def fetchnumpy(*, connection: DuckDBPyConnection) -> dict: ... -def fetchdf(*, date_as_object: bool = False, connection: DuckDBPyConnection) -> pandas.DataFrame: ... -def fetch_df(*, date_as_object: bool = False, connection: DuckDBPyConnection) -> pandas.DataFrame: ... -def df(*, date_as_object: bool = False, connection: DuckDBPyConnection) -> pandas.DataFrame: ... -def fetch_df_chunk(vectors_per_chunk: int = 1, *, date_as_object: bool = False, connection: DuckDBPyConnection) -> pandas.DataFrame: ... -def pl(rows_per_batch: int = 1000000, *, connection: DuckDBPyConnection) -> polars.DataFrame: ... -def fetch_arrow_table(rows_per_batch: int = 1000000, *, connection: DuckDBPyConnection) -> pyarrow.lib.Table: ... -def arrow(rows_per_batch: int = 1000000, *, connection: DuckDBPyConnection) -> pyarrow.lib.Table: ... -def fetch_record_batch(rows_per_batch: int = 1000000, *, connection: DuckDBPyConnection) -> pyarrow.lib.RecordBatchReader: ... -def torch(*, connection: DuckDBPyConnection) -> dict: ... -def tf(*, connection: DuckDBPyConnection) -> dict: ... -def begin(*, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def commit(*, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def rollback(*, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def append(table_name: str, df: pandas.DataFrame, *, by_name: bool = False, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def register(view_name: str, python_object: object, *, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def unregister(view_name: str, *, connection: DuckDBPyConnection) -> DuckDBPyConnection: ... -def table(table_name: str, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def view(view_name: str, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def values(values: List[Any], *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def table_function(name: str, parameters: object = None, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def read_json(name: str, *, columns: Optional[Dict[str,str]] = None, sample_size: Optional[int] = None, maximum_depth: Optional[int] = None, records: Optional[str] = None, format: Optional[str] = None, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def extract_statements(query: str, *, connection: DuckDBPyConnection) -> List[Statement]: ... -def sql(query: str, *, alias: str = "", params: object = None, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def query(query: str, *, alias: str = "", params: object = None, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def from_query(query: str, *, alias: str = "", params: object = None, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def read_csv(path_or_buffer: Union[str, StringIO, TextIOBase], *, header: Optional[bool | int] = None, compression: Optional[str] = None, sep: Optional[str] = None, delimiter: Optional[str] = None, dtype: Optional[Dict[str, str] | List[str]] = None, na_values: Optional[str| List[str]] = None, skiprows: Optional[int] = None, quotechar: Optional[str] = None, escapechar: Optional[str] = None, encoding: Optional[str] = None, parallel: Optional[bool] = None, date_format: Optional[str] = None, timestamp_format: Optional[str] = None, sample_size: Optional[int] = None, all_varchar: Optional[bool] = None, normalize_names: Optional[bool] = None, filename: Optional[bool] = None, null_padding: Optional[bool] = None, names: Optional[List[str]] = None, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def from_csv_auto(path_or_buffer: Union[str, StringIO, TextIOBase], *, header: Optional[bool | int] = None, compression: Optional[str] = None, sep: Optional[str] = None, delimiter: Optional[str] = None, dtype: Optional[Dict[str, str] | List[str]] = None, na_values: Optional[str| List[str]] = None, skiprows: Optional[int] = None, quotechar: Optional[str] = None, escapechar: Optional[str] = None, encoding: Optional[str] = None, parallel: Optional[bool] = None, date_format: Optional[str] = None, timestamp_format: Optional[str] = None, sample_size: Optional[int] = None, all_varchar: Optional[bool] = None, normalize_names: Optional[bool] = None, filename: Optional[bool] = None, null_padding: Optional[bool] = None, names: Optional[List[str]] = None, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def from_df(df: pandas.DataFrame, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def from_arrow(arrow_object: object, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def from_parquet(file_glob: str, binary_as_string: bool = False, *, file_row_number: bool = False, filename: bool = False, hive_partitioning: bool = False, union_by_name: bool = False, compression: Optional[str] = None, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def read_parquet(file_glob: str, binary_as_string: bool = False, *, file_row_number: bool = False, filename: bool = False, hive_partitioning: bool = False, union_by_name: bool = False, compression: Optional[str] = None, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def from_substrait(proto: str, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def get_substrait(query: str, *, enable_optimizer: bool = True, connection: DuckDBPyConnection) -> str: ... -def get_substrait_json(query: str, *, enable_optimizer: bool = True, connection: DuckDBPyConnection) -> str: ... -def from_substrait_json(json: str, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def get_table_names(query: str, *, connection: DuckDBPyConnection) -> List[str]: ... -def install_extension(extension: str, *, force_install: bool = False, connection: DuckDBPyConnection) -> None: ... -def load_extension(extension: str, *, connection: DuckDBPyConnection) -> None: ... -def project(df: pandas.DataFrame, project_expr: str, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def distinct(df: pandas.DataFrame, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def write_csv(df: pandas.DataFrame, *args: Any, connection: DuckDBPyConnection) -> None: ... -def aggregate(df: pandas.DataFrame, aggr_expr: str, group_expr: str = "", *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def alias(df: pandas.DataFrame, alias: str, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def filter(df: pandas.DataFrame, filter_expr: str, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def limit(df: pandas.DataFrame, n: int, offset: int = 0, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def order(df: pandas.DataFrame, order_expr: str, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def query_df(df: pandas.DataFrame, virtual_table_name: str, sql_query: str, *, connection: DuckDBPyConnection) -> DuckDBPyRelation: ... -def description(*, connection: DuckDBPyConnection) -> Optional[List[Any]]: ... -def rowcount(*, connection: DuckDBPyConnection) -> int: ... +def cursor(*, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def register_filesystem(filesystem: str, *, connection: DuckDBPyConnection = ...) -> None: ... +def unregister_filesystem(name: str, *, connection: DuckDBPyConnection = ...) -> None: ... +def list_filesystems(*, connection: DuckDBPyConnection = ...) -> list: ... +def filesystem_is_registered(name: str, *, connection: DuckDBPyConnection = ...) -> bool: ... +def create_function(name: str, function: function, parameters: Optional[List[DuckDBPyType]] = None, return_type: Optional[DuckDBPyType] = None, *, type: Optional[PythonUDFType] = PythonUDFType.NATIVE, null_handling: Optional[FunctionNullHandling] = FunctionNullHandling.DEFAULT, exception_handling: Optional[PythonExceptionHandling] = PythonExceptionHandling.DEFAULT, side_effects: bool = False, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def remove_function(name: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def sqltype(type_str: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def dtype(type_str: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def type(type_str: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def array_type(type: DuckDBPyType, size: int, *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def list_type(type: DuckDBPyType, *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def union_type(members: DuckDBPyType, *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def string_type(collation: str = "", *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def enum_type(name: str, type: DuckDBPyType, values: List[Any], *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def decimal_type(width: int, scale: int, *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def struct_type(fields: Union[Dict[str, DuckDBPyType], List[str]], *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def row_type(fields: Union[Dict[str, DuckDBPyType], List[str]], *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def map_type(key: DuckDBPyType, value: DuckDBPyType, *, connection: DuckDBPyConnection = ...) -> DuckDBPyType: ... +def duplicate(*, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def execute(query: object, parameters: object = None, *, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def executemany(query: object, parameters: object = None, *, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def close(*, connection: DuckDBPyConnection = ...) -> None: ... +def interrupt(*, connection: DuckDBPyConnection = ...) -> None: ... +def fetchone(*, connection: DuckDBPyConnection = ...) -> Optional[tuple]: ... +def fetchmany(size: int = 1, *, connection: DuckDBPyConnection = ...) -> List[Any]: ... +def fetchall(*, connection: DuckDBPyConnection = ...) -> List[Any]: ... +def fetchnumpy(*, connection: DuckDBPyConnection = ...) -> dict: ... +def fetchdf(*, date_as_object: bool = False, connection: DuckDBPyConnection = ...) -> pandas.DataFrame: ... +def fetch_df(*, date_as_object: bool = False, connection: DuckDBPyConnection = ...) -> pandas.DataFrame: ... +def df(*, date_as_object: bool = False, connection: DuckDBPyConnection = ...) -> pandas.DataFrame: ... +def fetch_df_chunk(vectors_per_chunk: int = 1, *, date_as_object: bool = False, connection: DuckDBPyConnection = ...) -> pandas.DataFrame: ... +def pl(rows_per_batch: int = 1000000, *, connection: DuckDBPyConnection = ...) -> polars.DataFrame: ... +def fetch_arrow_table(rows_per_batch: int = 1000000, *, connection: DuckDBPyConnection = ...) -> pyarrow.lib.Table: ... +def arrow(rows_per_batch: int = 1000000, *, connection: DuckDBPyConnection = ...) -> pyarrow.lib.Table: ... +def fetch_record_batch(rows_per_batch: int = 1000000, *, connection: DuckDBPyConnection = ...) -> pyarrow.lib.RecordBatchReader: ... +def torch(*, connection: DuckDBPyConnection = ...) -> dict: ... +def tf(*, connection: DuckDBPyConnection = ...) -> dict: ... +def begin(*, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def commit(*, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def rollback(*, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def checkpoint(*, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def append(table_name: str, df: pandas.DataFrame, *, by_name: bool = False, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def register(view_name: str, python_object: object, *, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def unregister(view_name: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyConnection: ... +def table(table_name: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def view(view_name: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def values(values: List[Any], *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def table_function(name: str, parameters: object = None, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def read_json(name: str, *, columns: Optional[Dict[str,str]] = None, sample_size: Optional[int] = None, maximum_depth: Optional[int] = None, records: Optional[str] = None, format: Optional[str] = None, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def extract_statements(query: str, *, connection: DuckDBPyConnection = ...) -> List[Statement]: ... +def sql(query: str, *, alias: str = "", params: object = None, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def query(query: str, *, alias: str = "", params: object = None, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def from_query(query: str, *, alias: str = "", params: object = None, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def read_csv(path_or_buffer: Union[str, StringIO, TextIOBase], *, header: Optional[bool | int] = None, compression: Optional[str] = None, sep: Optional[str] = None, delimiter: Optional[str] = None, dtype: Optional[Dict[str, str] | List[str]] = None, na_values: Optional[str| List[str]] = None, skiprows: Optional[int] = None, quotechar: Optional[str] = None, escapechar: Optional[str] = None, encoding: Optional[str] = None, parallel: Optional[bool] = None, date_format: Optional[str] = None, timestamp_format: Optional[str] = None, sample_size: Optional[int] = None, all_varchar: Optional[bool] = None, normalize_names: Optional[bool] = None, filename: Optional[bool] = None, null_padding: Optional[bool] = None, names: Optional[List[str]] = None, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def from_csv_auto(path_or_buffer: Union[str, StringIO, TextIOBase], *, header: Optional[bool | int] = None, compression: Optional[str] = None, sep: Optional[str] = None, delimiter: Optional[str] = None, dtype: Optional[Dict[str, str] | List[str]] = None, na_values: Optional[str| List[str]] = None, skiprows: Optional[int] = None, quotechar: Optional[str] = None, escapechar: Optional[str] = None, encoding: Optional[str] = None, parallel: Optional[bool] = None, date_format: Optional[str] = None, timestamp_format: Optional[str] = None, sample_size: Optional[int] = None, all_varchar: Optional[bool] = None, normalize_names: Optional[bool] = None, filename: Optional[bool] = None, null_padding: Optional[bool] = None, names: Optional[List[str]] = None, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def from_df(df: pandas.DataFrame, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def from_arrow(arrow_object: object, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def from_parquet(file_glob: str, binary_as_string: bool = False, *, file_row_number: bool = False, filename: bool = False, hive_partitioning: bool = False, union_by_name: bool = False, compression: Optional[str] = None, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def read_parquet(file_glob: str, binary_as_string: bool = False, *, file_row_number: bool = False, filename: bool = False, hive_partitioning: bool = False, union_by_name: bool = False, compression: Optional[str] = None, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def from_substrait(proto: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def get_substrait(query: str, *, enable_optimizer: bool = True, connection: DuckDBPyConnection = ...) -> str: ... +def get_substrait_json(query: str, *, enable_optimizer: bool = True, connection: DuckDBPyConnection = ...) -> str: ... +def from_substrait_json(json: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def get_table_names(query: str, *, connection: DuckDBPyConnection = ...) -> List[str]: ... +def install_extension(extension: str, *, force_install: bool = False, connection: DuckDBPyConnection = ...) -> None: ... +def load_extension(extension: str, *, connection: DuckDBPyConnection = ...) -> None: ... +def project(df: pandas.DataFrame, *args: str, groups: str = "", connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def distinct(df: pandas.DataFrame, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def write_csv(df: pandas.DataFrame, filename: str, *, sep: Optional[str] = None, na_rep: Optional[str] = None, header: Optional[bool] = None, quotechar: Optional[str] = None, escapechar: Optional[str] = None, date_format: Optional[str] = None, timestamp_format: Optional[str] = None, quoting: Optional[str | int] = None, encoding: Optional[str] = None, compression: Optional[str] = None, overwrite: Optional[bool] = None, per_thread_output: Optional[bool] = None, use_tmp_file: Optional[bool] = None, partition_by: Optional[List[str]] = None, connection: DuckDBPyConnection = ...) -> None: ... +def aggregate(df: pandas.DataFrame, aggr_expr: str, group_expr: str = "", *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def alias(df: pandas.DataFrame, alias: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def filter(df: pandas.DataFrame, filter_expr: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def limit(df: pandas.DataFrame, n: int, offset: int = 0, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def order(df: pandas.DataFrame, order_expr: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def query_df(df: pandas.DataFrame, virtual_table_name: str, sql_query: str, *, connection: DuckDBPyConnection = ...) -> DuckDBPyRelation: ... +def description(*, connection: DuckDBPyConnection = ...) -> Optional[List[Any]]: ... +def rowcount(*, connection: DuckDBPyConnection = ...) -> int: ... # END OF CONNECTION WRAPPER diff --git a/tools/pythonpkg/duckdb/__init__.py b/tools/pythonpkg/duckdb/__init__.py index c6683a71278..d20563722de 100644 --- a/tools/pythonpkg/duckdb/__init__.py +++ b/tools/pythonpkg/duckdb/__init__.py @@ -23,6 +23,7 @@ Expression, ConstantExpression, ColumnExpression, + CoalesceOperator, StarExpression, FunctionExpression, CaseExpression, @@ -35,6 +36,7 @@ "Expression", "ConstantExpression", "ColumnExpression", + "CoalesceOperator", "StarExpression", "FunctionExpression", "CaseExpression", @@ -55,605 +57,172 @@ # START OF CONNECTION WRAPPER -def cursor(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.cursor(**kwargs) -_exported_symbols.append('cursor') - -def register_filesystem(filesystem, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.register_filesystem(filesystem, **kwargs) -_exported_symbols.append('register_filesystem') - -def unregister_filesystem(name, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.unregister_filesystem(name, **kwargs) -_exported_symbols.append('unregister_filesystem') - -def list_filesystems(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.list_filesystems(**kwargs) -_exported_symbols.append('list_filesystems') - -def filesystem_is_registered(name, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.filesystem_is_registered(name, **kwargs) -_exported_symbols.append('filesystem_is_registered') - -def create_function(name, function, parameters = None, return_type = None, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.create_function(name, function, parameters, return_type, **kwargs) -_exported_symbols.append('create_function') - -def remove_function(name, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.remove_function(name, **kwargs) -_exported_symbols.append('remove_function') - -def sqltype(type_str, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.sqltype(type_str, **kwargs) -_exported_symbols.append('sqltype') - -def dtype(type_str, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.dtype(type_str, **kwargs) -_exported_symbols.append('dtype') - -def type(type_str, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.type(type_str, **kwargs) -_exported_symbols.append('type') - -def array_type(type, size, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.array_type(type, size, **kwargs) -_exported_symbols.append('array_type') - -def list_type(type, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.list_type(type, **kwargs) -_exported_symbols.append('list_type') - -def union_type(members, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.union_type(members, **kwargs) -_exported_symbols.append('union_type') - -def string_type(collation = "", **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.string_type(collation, **kwargs) -_exported_symbols.append('string_type') - -def enum_type(name, type, values, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.enum_type(name, type, values, **kwargs) -_exported_symbols.append('enum_type') - -def decimal_type(width, scale, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.decimal_type(width, scale, **kwargs) -_exported_symbols.append('decimal_type') - -def struct_type(fields, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.struct_type(fields, **kwargs) -_exported_symbols.append('struct_type') - -def row_type(fields, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.row_type(fields, **kwargs) -_exported_symbols.append('row_type') - -def map_type(key, value, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.map_type(key, value, **kwargs) -_exported_symbols.append('map_type') - -def duplicate(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.duplicate(**kwargs) -_exported_symbols.append('duplicate') - -def execute(query, parameters = None, multiple_parameter_sets = False, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.execute(query, parameters, multiple_parameter_sets, **kwargs) -_exported_symbols.append('execute') - -def executemany(query, parameters = None, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.executemany(query, parameters, **kwargs) -_exported_symbols.append('executemany') - -def close(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.close(**kwargs) -_exported_symbols.append('close') - -def interrupt(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.interrupt(**kwargs) -_exported_symbols.append('interrupt') - -def fetchone(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.fetchone(**kwargs) -_exported_symbols.append('fetchone') - -def fetchmany(size = 1, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.fetchmany(size, **kwargs) -_exported_symbols.append('fetchmany') - -def fetchall(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.fetchall(**kwargs) -_exported_symbols.append('fetchall') - -def fetchnumpy(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.fetchnumpy(**kwargs) -_exported_symbols.append('fetchnumpy') - -def fetchdf(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.fetchdf(**kwargs) -_exported_symbols.append('fetchdf') - -def fetch_df(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.fetch_df(**kwargs) -_exported_symbols.append('fetch_df') - -def fetch_df_chunk(vectors_per_chunk = 1, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.fetch_df_chunk(vectors_per_chunk, **kwargs) -_exported_symbols.append('fetch_df_chunk') - -def pl(rows_per_batch = 1000000, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.pl(rows_per_batch, **kwargs) -_exported_symbols.append('pl') - -def fetch_arrow_table(rows_per_batch = 1000000, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.fetch_arrow_table(rows_per_batch, **kwargs) -_exported_symbols.append('fetch_arrow_table') - -def fetch_record_batch(rows_per_batch = 1000000, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.fetch_record_batch(rows_per_batch, **kwargs) -_exported_symbols.append('fetch_record_batch') - -def torch(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.torch(**kwargs) -_exported_symbols.append('torch') - -def tf(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.tf(**kwargs) -_exported_symbols.append('tf') - -def begin(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.begin(**kwargs) -_exported_symbols.append('begin') - -def commit(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.commit(**kwargs) -_exported_symbols.append('commit') - -def rollback(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.rollback(**kwargs) -_exported_symbols.append('rollback') - -def append(table_name, df, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.append(table_name, df, **kwargs) -_exported_symbols.append('append') - -def register(view_name, python_object, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.register(view_name, python_object, **kwargs) -_exported_symbols.append('register') - -def unregister(view_name, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.unregister(view_name, **kwargs) -_exported_symbols.append('unregister') - -def table(table_name, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.table(table_name, **kwargs) -_exported_symbols.append('table') - -def view(view_name, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.view(view_name, **kwargs) -_exported_symbols.append('view') - -def values(values, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.values(values, **kwargs) -_exported_symbols.append('values') - -def table_function(name, parameters = None, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.table_function(name, parameters, **kwargs) -_exported_symbols.append('table_function') - -def read_json(name, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.read_json(name, **kwargs) -_exported_symbols.append('read_json') - -def extract_statements(query, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.extract_statements(query, **kwargs) -_exported_symbols.append('extract_statements') - -def sql(query, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.sql(query, **kwargs) -_exported_symbols.append('sql') - -def query(query, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.query(query, **kwargs) -_exported_symbols.append('query') - -def from_query(query, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_query(query, **kwargs) -_exported_symbols.append('from_query') - -def read_csv(path_or_buffer, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.read_csv(path_or_buffer, **kwargs) -_exported_symbols.append('read_csv') - -def from_csv_auto(path_or_buffer, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_csv_auto(path_or_buffer, **kwargs) -_exported_symbols.append('from_csv_auto') - -def from_df(df, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_df(df, **kwargs) -_exported_symbols.append('from_df') - -def from_arrow(arrow_object, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_arrow(arrow_object, **kwargs) -_exported_symbols.append('from_arrow') - -def from_parquet(file_glob, binary_as_string = False, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_parquet(file_glob, binary_as_string, **kwargs) -_exported_symbols.append('from_parquet') - -def read_parquet(file_glob, binary_as_string = False, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.read_parquet(file_glob, binary_as_string, **kwargs) -_exported_symbols.append('read_parquet') - -def from_substrait(proto, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_substrait(proto, **kwargs) -_exported_symbols.append('from_substrait') - -def get_substrait(query, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.get_substrait(query, **kwargs) -_exported_symbols.append('get_substrait') - -def get_substrait_json(query, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.get_substrait_json(query, **kwargs) -_exported_symbols.append('get_substrait_json') - -def from_substrait_json(json, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_substrait_json(json, **kwargs) -_exported_symbols.append('from_substrait_json') - -def get_table_names(query, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.get_table_names(query, **kwargs) -_exported_symbols.append('get_table_names') - -def install_extension(extension, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.install_extension(extension, **kwargs) -_exported_symbols.append('install_extension') - -def load_extension(extension, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.load_extension(extension, **kwargs) -_exported_symbols.append('load_extension') - -def project(df, project_expr, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_df(df).project(project_expr, **kwargs) -_exported_symbols.append('project') - -def distinct(df, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_df(df).distinct(**kwargs) -_exported_symbols.append('distinct') - -def write_csv(df, *args, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_df(df).write_csv(*args, **kwargs) -_exported_symbols.append('write_csv') - -def aggregate(df, aggr_expr, group_expr = "", **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_df(df).aggregate(aggr_expr, group_expr, **kwargs) -_exported_symbols.append('aggregate') - -def alias(df, alias, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_df(df).set_alias(alias, **kwargs) -_exported_symbols.append('alias') - -def filter(df, filter_expr, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_df(df).filter(filter_expr, **kwargs) -_exported_symbols.append('filter') - -def limit(df, n, offset = 0, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_df(df).limit(n, offset, **kwargs) -_exported_symbols.append('limit') - -def order(df, order_expr, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_df(df).order(order_expr, **kwargs) -_exported_symbols.append('order') - -def query_df(df, virtual_table_name, sql_query, **kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.from_df(df).query(virtual_table_name, sql_query, **kwargs) -_exported_symbols.append('query_df') +from .duckdb import ( + cursor, + register_filesystem, + unregister_filesystem, + list_filesystems, + filesystem_is_registered, + create_function, + remove_function, + sqltype, + dtype, + type, + array_type, + list_type, + union_type, + string_type, + enum_type, + decimal_type, + struct_type, + row_type, + map_type, + duplicate, + execute, + executemany, + close, + interrupt, + fetchone, + fetchmany, + fetchall, + fetchnumpy, + fetchdf, + fetch_df, + df, + fetch_df_chunk, + pl, + fetch_arrow_table, + arrow, + fetch_record_batch, + torch, + tf, + begin, + commit, + rollback, + checkpoint, + append, + register, + unregister, + table, + view, + values, + table_function, + read_json, + extract_statements, + sql, + query, + from_query, + read_csv, + from_csv_auto, + from_df, + from_arrow, + from_parquet, + read_parquet, + from_parquet, + read_parquet, + from_substrait, + get_substrait, + get_substrait_json, + from_substrait_json, + get_table_names, + install_extension, + load_extension, + project, + distinct, + write_csv, + aggregate, + alias, + filter, + limit, + order, + query_df, + description, + rowcount, +) -def description(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.description -_exported_symbols.append('description') +_exported_symbols.extend([ + 'cursor', + 'register_filesystem', + 'unregister_filesystem', + 'list_filesystems', + 'filesystem_is_registered', + 'create_function', + 'remove_function', + 'sqltype', + 'dtype', + 'type', + 'array_type', + 'list_type', + 'union_type', + 'string_type', + 'enum_type', + 'decimal_type', + 'struct_type', + 'row_type', + 'map_type', + 'duplicate', + 'execute', + 'executemany', + 'close', + 'interrupt', + 'fetchone', + 'fetchmany', + 'fetchall', + 'fetchnumpy', + 'fetchdf', + 'fetch_df', + 'df', + 'fetch_df_chunk', + 'pl', + 'fetch_arrow_table', + 'arrow', + 'fetch_record_batch', + 'torch', + 'tf', + 'begin', + 'commit', + 'rollback', + 'checkpoint', + 'append', + 'register', + 'unregister', + 'table', + 'view', + 'values', + 'table_function', + 'read_json', + 'extract_statements', + 'sql', + 'query', + 'from_query', + 'read_csv', + 'from_csv_auto', + 'from_df', + 'from_arrow', + 'from_parquet', + 'read_parquet', + 'from_parquet', + 'read_parquet', + 'from_substrait', + 'get_substrait', + 'get_substrait_json', + 'from_substrait_json', + 'get_table_names', + 'install_extension', + 'load_extension', + 'project', + 'distinct', + 'write_csv', + 'aggregate', + 'alias', + 'filter', + 'limit', + 'order', + 'query_df', + 'description', + 'rowcount', +]) -def rowcount(**kwargs): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.rowcount -_exported_symbols.append('rowcount') # END OF CONNECTION WRAPPER # Enums diff --git a/tools/pythonpkg/duckdb/experimental/spark/sql/dataframe.py b/tools/pythonpkg/duckdb/experimental/spark/sql/dataframe.py index bf3fe328359..b1f1aff6598 100644 --- a/tools/pythonpkg/duckdb/experimental/spark/sql/dataframe.py +++ b/tools/pythonpkg/duckdb/experimental/spark/sql/dataframe.py @@ -10,6 +10,7 @@ cast, overload, ) +import uuid import duckdb from duckdb import ColumnExpression, Expression, StarExpression @@ -903,9 +904,15 @@ def dropDuplicates(self, subset: Optional[List[str]] = None) -> "DataFrame": +-----+---+------+ """ if subset: - raise ContributionsAcceptedError + rn_col = f"tmp_col_{uuid.uuid1().hex}" + subset_str = ', '.join([f'"{c}"' for c in subset]) + window_spec = f"OVER(PARTITION BY {subset_str}) AS {rn_col}" + df = DataFrame(self.relation.row_number(window_spec, "*"), self.session) + return df.filter(f"{rn_col} = 1").drop(rn_col) + return self.distinct() + def distinct(self) -> "DataFrame": """Returns a new :class:`DataFrame` containing the distinct rows in this :class:`DataFrame`. diff --git a/tools/pythonpkg/duckdb/experimental/spark/sql/functions.py b/tools/pythonpkg/duckdb/experimental/spark/sql/functions.py index a15d64b3708..ca920cd9477 100644 --- a/tools/pythonpkg/duckdb/experimental/spark/sql/functions.py +++ b/tools/pythonpkg/duckdb/experimental/spark/sql/functions.py @@ -1,9 +1,17 @@ -from .column import Column, _get_expr -from typing import Any, Callable, overload, Union +from typing import Any, Callable, Union, overload + +from duckdb import ( + CaseExpression, + CoalesceOperator, + ColumnExpression, + ConstantExpression, + Expression, + FunctionExpression, +) -from duckdb import CaseExpression, ConstantExpression, ColumnExpression, FunctionExpression, Expression -from ._typing import ColumnOrName from ..exception import ContributionsAcceptedError +from ._typing import ColumnOrName +from .column import Column, _get_expr def _invoke_function_over_columns(name: str, *cols: "ColumnOrName") -> Column: @@ -66,7 +74,9 @@ def _inner_expr_or_val(val): def struct(*cols: Column) -> Column: - return Column(FunctionExpression('struct_pack', *[_inner_expr_or_val(x) for x in cols])) + return Column( + FunctionExpression("struct_pack", *[_inner_expr_or_val(x) for x in cols]) + ) def lit(col: Any) -> Column: @@ -93,7 +103,11 @@ def regexp_replace(str: "ColumnOrName", pattern: str, replacement: str) -> Colum [Row(d='-----')] """ return _invoke_function( - "regexp_replace", _to_column(str), ConstantExpression(pattern), ConstantExpression(replacement), ConstantExpression('g') + "regexp_replace", + _to_column(str), + ConstantExpression(pattern), + ConstantExpression(replacement), + ConstantExpression("g"), ) @@ -322,13 +336,11 @@ def count(col: "ColumnOrName") -> Column: @overload -def transform(col: "ColumnOrName", f: Callable[[Column], Column]) -> Column: - ... +def transform(col: "ColumnOrName", f: Callable[[Column], Column]) -> Column: ... @overload -def transform(col: "ColumnOrName", f: Callable[[Column, Column], Column]) -> Column: - ... +def transform(col: "ColumnOrName", f: Callable[[Column, Column], Column]) -> Column: ... def transform( @@ -417,9 +429,7 @@ def concat_ws(sep: str, *cols: "ColumnOrName") -> "Column": [Row(s='abcd-123')] """ cols = [_to_column(expr) for expr in cols] - return _invoke_function( - "concat_ws", ConstantExpression(sep), *cols - ) + return _invoke_function("concat_ws", ConstantExpression(sep), *cols) def lower(col: "ColumnOrName") -> Column: @@ -847,3 +857,690 @@ def length(col: "ColumnOrName") -> Column: [Row(length=4)] """ return _invoke_function_over_columns("length", col) + + +def coalesce(*cols: "ColumnOrName") -> Column: + """Returns the first column that is not null. + .. versionadded:: 1.4.0 + .. versionchanged:: 3.4.0 + Supports Spark Connect. + Parameters + ---------- + cols : :class:`~pyspark.sql.Column` or str + list of columns to work on. + Returns + ------- + :class:`~pyspark.sql.Column` + value of the first column that is not null. + Examples + -------- + >>> cDf = spark.createDataFrame([(None, None), (1, None), (None, 2)], ("a", "b")) + >>> cDf.show() + +----+----+ + | a| b| + +----+----+ + |NULL|NULL| + | 1|NULL| + |NULL| 2| + +----+----+ + >>> cDf.select(coalesce(cDf["a"], cDf["b"])).show() + +--------------+ + |coalesce(a, b)| + +--------------+ + | NULL| + | 1| + | 2| + +--------------+ + >>> cDf.select('*', coalesce(cDf["a"], lit(0.0))).show() + +----+----+----------------+ + | a| b|coalesce(a, 0.0)| + +----+----+----------------+ + |NULL|NULL| 0.0| + | 1|NULL| 1.0| + |NULL| 2| 0.0| + +----+----+----------------+ + """ + + cols = [_to_column(expr) for expr in cols] + return Column(CoalesceOperator(*cols)) + + +def nvl(col1: "ColumnOrName", col2: "ColumnOrName") -> Column: + """ + Returns `col2` if `col1` is null, or `col1` otherwise. + .. versionadded:: 3.5.0 + Parameters + ---------- + col1 : :class:`~pyspark.sql.Column` or str + col2 : :class:`~pyspark.sql.Column` or str + Examples + -------- + >>> df = spark.createDataFrame([(None, 8,), (1, 9,)], ["a", "b"]) + >>> df.select(nvl(df.a, df.b).alias('r')).collect() + [Row(r=8), Row(r=1)] + """ + + return coalesce(col1, col2) + + +def ifnull(col1: "ColumnOrName", col2: "ColumnOrName") -> Column: + """ + Returns `col2` if `col1` is null, or `col1` otherwise. + .. versionadded:: 3.5.0 + Parameters + ---------- + col1 : :class:`~pyspark.sql.Column` or str + col2 : :class:`~pyspark.sql.Column` or str + Examples + -------- + >>> import pyspark.sql.functions as sf + >>> df = spark.createDataFrame([(None,), (1,)], ["e"]) + >>> df.select(sf.ifnull(df.e, sf.lit(8))).show() + +------------+ + |ifnull(e, 8)| + +------------+ + | 8| + | 1| + +------------+ + """ + return coalesce(col1, col2) + + +def md5(col: "ColumnOrName") -> Column: + """Calculates the MD5 digest and returns the value as a 32 character hex string. + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target column to compute on. + + Returns + ------- + :class:`~pyspark.sql.Column` + the column for computed results. + + Examples + -------- + >>> spark.createDataFrame([('ABC',)], ['a']).select(md5('a').alias('hash')).collect() + [Row(hash='902fbdd2b1df0c4f70b4a5d23525e932')] + """ + return _invoke_function_over_columns("md5", col) + + +def sha2(col: "ColumnOrName", numBits: int) -> Column: + """Returns the hex string result of SHA-2 family of hash functions (SHA-224, SHA-256, SHA-384, + and SHA-512). The numBits indicates the desired bit length of the result, which must have a + value of 224, 256, 384, 512, or 0 (which is equivalent to 256). + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target column to compute on. + numBits : int + the desired bit length of the result, which must have a + value of 224, 256, 384, 512, or 0 (which is equivalent to 256). + + Returns + ------- + :class:`~pyspark.sql.Column` + the column for computed results. + + Examples + -------- + >>> df = spark.createDataFrame([["Alice"], ["Bob"]], ["name"]) + >>> df.withColumn("sha2", sha2(df.name, 256)).show(truncate=False) + +-----+----------------------------------------------------------------+ + |name |sha2 | + +-----+----------------------------------------------------------------+ + |Alice|3bc51062973c458d5a6f2d8d64a023246354ad7e064b1e4e009ec8a0699a3043| + |Bob |cd9fb1e148ccd8442e5aa74904cc73bf6fb54d1d54d333bd596aa9bb4bb4e961| + +-----+----------------------------------------------------------------+ + """ + + if numBits not in {224, 256, 384, 512, 0}: + raise ValueError("numBits should be one of {224, 256, 384, 512, 0}") + + if numBits == 256: + return _invoke_function_over_columns("sha256", col) + + raise ContributionsAcceptedError( + "SHA-224, SHA-384, and SHA-512 are not supported yet." + ) + + +def curdate() -> Column: + """ + Returns the current date at the start of query evaluation as a :class:`DateType` column. + All calls of current_date within the same query return the same value. + + .. versionadded:: 3.5.0 + + Returns + ------- + :class:`~pyspark.sql.Column` + current date. + + Examples + -------- + >>> import pyspark.sql.functions as sf + >>> spark.range(1).select(sf.curdate()).show() # doctest: +SKIP + +--------------+ + |current_date()| + +--------------+ + | 2022-08-26| + +--------------+ + """ + return _invoke_function("today") + + +def current_date() -> Column: + """ + Returns the current date at the start of query evaluation as a :class:`DateType` column. + All calls of current_date within the same query return the same value. + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Returns + ------- + :class:`~pyspark.sql.Column` + current date. + + Examples + -------- + >>> df = spark.range(1) + >>> df.select(current_date()).show() # doctest: +SKIP + +--------------+ + |current_date()| + +--------------+ + | 2022-08-26| + +--------------+ + """ + return curdate() + + +def now() -> Column: + """ + Returns the current timestamp at the start of query evaluation. + + .. versionadded:: 3.5.0 + + Returns + ------- + :class:`~pyspark.sql.Column` + current timestamp at the start of query evaluation. + + Examples + -------- + >>> df = spark.range(1) + >>> df.select(now()).show(truncate=False) # doctest: +SKIP + +-----------------------+ + |now() | + +-----------------------+ + |2022-08-26 21:23:22.716| + +-----------------------+ + """ + return _invoke_function("now") + + +def date_trunc(format: str, timestamp: "ColumnOrName") -> Column: + """ + Returns timestamp truncated to the unit specified by the format. + + .. versionadded:: 2.3.0 + + Parameters + ---------- + format : str + 'year', 'yyyy', 'yy', 'month', 'mon', 'mm', + 'day', 'dd', 'hour', 'minute', 'second', 'week', 'quarter' + timestamp : :class:`~pyspark.sql.Column` or str + + Examples + -------- + >>> df = spark.createDataFrame([('1997-02-28 05:02:11',)], ['t']) + >>> df.select(date_trunc('year', df.t).alias('year')).collect() + [Row(year=datetime.datetime(1997, 1, 1, 0, 0))] + >>> df.select(date_trunc('mon', df.t).alias('month')).collect() + [Row(month=datetime.datetime(1997, 2, 1, 0, 0))] + """ + format = format.lower() + if format in ["yyyy", "yy"]: + format = "year" + elif format in ["mon", "mm"]: + format = "month" + elif format == "dd": + format = "day" + elif format == "hh": + format = "hour" + return _invoke_function_over_columns("date_trunc", lit(format), timestamp) + + +def date_part(field: "ColumnOrName", source: "ColumnOrName") -> Column: + """ + Extracts a part of the date/timestamp or interval source. + + .. versionadded:: 3.5.0 + + Parameters + ---------- + field : :class:`~pyspark.sql.Column` or str + selects which part of the source should be extracted, and supported string values + are as same as the fields of the equivalent function `extract`. + source : :class:`~pyspark.sql.Column` or str + a date/timestamp or interval column from where `field` should be extracted. + + Returns + ------- + :class:`~pyspark.sql.Column` + a part of the date/timestamp or interval source. + + Examples + -------- + >>> import datetime + >>> df = spark.createDataFrame([(datetime.datetime(2015, 4, 8, 13, 8, 15),)], ['ts']) + >>> df.select( + ... date_part(lit('YEAR'), 'ts').alias('year'), + ... date_part(lit('month'), 'ts').alias('month'), + ... date_part(lit('WEEK'), 'ts').alias('week'), + ... date_part(lit('D'), 'ts').alias('day'), + ... date_part(lit('M'), 'ts').alias('minute'), + ... date_part(lit('S'), 'ts').alias('second') + ... ).collect() + [Row(year=2015, month=4, week=15, day=8, minute=8, second=Decimal('15.000000'))] + """ + return _invoke_function_over_columns("date_part", field, source) + + +def extract(field: "ColumnOrName", source: "ColumnOrName") -> Column: + """ + Extracts a part of the date/timestamp or interval source. + + .. versionadded:: 3.5.0 + + Parameters + ---------- + field : :class:`~pyspark.sql.Column` or str + selects which part of the source should be extracted. + source : :class:`~pyspark.sql.Column` or str + a date/timestamp or interval column from where `field` should be extracted. + + Returns + ------- + :class:`~pyspark.sql.Column` + a part of the date/timestamp or interval source. + + Examples + -------- + >>> import datetime + >>> df = spark.createDataFrame([(datetime.datetime(2015, 4, 8, 13, 8, 15),)], ['ts']) + >>> df.select( + ... extract(lit('YEAR'), 'ts').alias('year'), + ... extract(lit('month'), 'ts').alias('month'), + ... extract(lit('WEEK'), 'ts').alias('week'), + ... extract(lit('D'), 'ts').alias('day'), + ... extract(lit('M'), 'ts').alias('minute'), + ... extract(lit('S'), 'ts').alias('second') + ... ).collect() + [Row(year=2015, month=4, week=15, day=8, minute=8, second=Decimal('15.000000'))] + """ + return date_part(field, source) + + +def datepart(field: "ColumnOrName", source: "ColumnOrName") -> Column: + """ + Extracts a part of the date/timestamp or interval source. + + .. versionadded:: 3.5.0 + + Parameters + ---------- + field : :class:`~pyspark.sql.Column` or str + selects which part of the source should be extracted, and supported string values + are as same as the fields of the equivalent function `extract`. + source : :class:`~pyspark.sql.Column` or str + a date/timestamp or interval column from where `field` should be extracted. + + Returns + ------- + :class:`~pyspark.sql.Column` + a part of the date/timestamp or interval source. + + Examples + -------- + >>> import datetime + >>> df = spark.createDataFrame([(datetime.datetime(2015, 4, 8, 13, 8, 15),)], ['ts']) + >>> df.select( + ... datepart(lit('YEAR'), 'ts').alias('year'), + ... datepart(lit('month'), 'ts').alias('month'), + ... datepart(lit('WEEK'), 'ts').alias('week'), + ... datepart(lit('D'), 'ts').alias('day'), + ... datepart(lit('M'), 'ts').alias('minute'), + ... datepart(lit('S'), 'ts').alias('second') + ... ).collect() + [Row(year=2015, month=4, week=15, day=8, minute=8, second=Decimal('15.000000'))] + """ + return date_part(field, source) + + +def year(col: "ColumnOrName") -> Column: + """ + Extract the year of a given date/timestamp as integer. + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target date/timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + year part of the date/timestamp as integer. + + Examples + -------- + >>> df = spark.createDataFrame([('2015-04-08',)], ['dt']) + >>> df.select(year('dt').alias('year')).collect() + [Row(year=2015)] + """ + return _invoke_function_over_columns("year", col) + + +def quarter(col: "ColumnOrName") -> Column: + """ + Extract the quarter of a given date/timestamp as integer. + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target date/timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + quarter of the date/timestamp as integer. + + Examples + -------- + >>> df = spark.createDataFrame([('2015-04-08',)], ['dt']) + >>> df.select(quarter('dt').alias('quarter')).collect() + [Row(quarter=2)] + """ + return _invoke_function_over_columns("quarter", col) + + +def month(col: "ColumnOrName") -> Column: + """ + Extract the month of a given date/timestamp as integer. + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target date/timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + month part of the date/timestamp as integer. + + Examples + -------- + >>> df = spark.createDataFrame([('2015-04-08',)], ['dt']) + >>> df.select(month('dt').alias('month')).collect() + [Row(month=4)] + """ + return _invoke_function_over_columns("month", col) + + +def dayofweek(col: "ColumnOrName") -> Column: + """ + Extract the day of the week of a given date/timestamp as integer. + Ranges from 1 for a Sunday through to 7 for a Saturday + + .. versionadded:: 2.3.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target date/timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + day of the week for given date/timestamp as integer. + + Examples + -------- + >>> df = spark.createDataFrame([('2015-04-08',)], ['dt']) + >>> df.select(dayofweek('dt').alias('day')).collect() + [Row(day=4)] + """ + return _invoke_function_over_columns("dayofweek", col) + lit(1) + + +def day(col: "ColumnOrName") -> Column: + """ + Extract the day of the month of a given date/timestamp as integer. + + .. versionadded:: 3.5.0 + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target date/timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + day of the month for given date/timestamp as integer. + + Examples + -------- + >>> df = spark.createDataFrame([('2015-04-08',)], ['dt']) + >>> df.select(day('dt').alias('day')).collect() + [Row(day=8)] + """ + return _invoke_function_over_columns("day", col) + + +def dayofmonth(col: "ColumnOrName") -> Column: + """ + Extract the day of the month of a given date/timestamp as integer. + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target date/timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + day of the month for given date/timestamp as integer. + + Examples + -------- + >>> df = spark.createDataFrame([('2015-04-08',)], ['dt']) + >>> df.select(dayofmonth('dt').alias('day')).collect() + [Row(day=8)] + """ + return day(col) + + +def dayofyear(col: "ColumnOrName") -> Column: + """ + Extract the day of the year of a given date/timestamp as integer. + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target date/timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + day of the year for given date/timestamp as integer. + + Examples + -------- + >>> df = spark.createDataFrame([('2015-04-08',)], ['dt']) + >>> df.select(dayofyear('dt').alias('day')).collect() + [Row(day=98)] + """ + return _invoke_function_over_columns("dayofyear", col) + + +def hour(col: "ColumnOrName") -> Column: + """ + Extract the hours of a given timestamp as integer. + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target date/timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + hour part of the timestamp as integer. + + Examples + -------- + >>> import datetime + >>> df = spark.createDataFrame([(datetime.datetime(2015, 4, 8, 13, 8, 15),)], ['ts']) + >>> df.select(hour('ts').alias('hour')).collect() + [Row(hour=13)] + """ + return _invoke_function_over_columns("hour", col) + + +def minute(col: "ColumnOrName") -> Column: + """ + Extract the minutes of a given timestamp as integer. + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target date/timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + minutes part of the timestamp as integer. + + Examples + -------- + >>> import datetime + >>> df = spark.createDataFrame([(datetime.datetime(2015, 4, 8, 13, 8, 15),)], ['ts']) + >>> df.select(minute('ts').alias('minute')).collect() + [Row(minute=8)] + """ + return _invoke_function_over_columns("minute", col) + + +def second(col: "ColumnOrName") -> Column: + """ + Extract the seconds of a given date as integer. + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target date/timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + `seconds` part of the timestamp as integer. + + Examples + -------- + >>> import datetime + >>> df = spark.createDataFrame([(datetime.datetime(2015, 4, 8, 13, 8, 15),)], ['ts']) + >>> df.select(second('ts').alias('second')).collect() + [Row(second=15)] + """ + return _invoke_function_over_columns("second", col) + + +def weekofyear(col: "ColumnOrName") -> Column: + """ + Extract the week number of a given date as integer. + A week is considered to start on a Monday and week 1 is the first week with more than 3 days, + as defined by ISO 8601 + + .. versionadded:: 1.5.0 + + .. versionchanged:: 3.4.0 + Supports Spark Connect. + + Parameters + ---------- + col : :class:`~pyspark.sql.Column` or str + target timestamp column to work on. + + Returns + ------- + :class:`~pyspark.sql.Column` + `week` of the year for given date as integer. + + Examples + -------- + >>> df = spark.createDataFrame([('2015-04-08',)], ['dt']) + >>> df.select(weekofyear(df.dt).alias('week')).collect() + [Row(week=15)] + """ + return _invoke_function_over_columns("weekofyear", col) diff --git a/tools/pythonpkg/duckdb/experimental/spark/sql/session.py b/tools/pythonpkg/duckdb/experimental/spark/sql/session.py index c1c8fc491d2..d3cfaa68234 100644 --- a/tools/pythonpkg/duckdb/experimental/spark/sql/session.py +++ b/tools/pythonpkg/duckdb/experimental/spark/sql/session.py @@ -6,7 +6,6 @@ from pandas.core.frame import DataFrame as PandasDataFrame from ..exception import ContributionsAcceptedError - from .types import StructType, AtomicType, DataType from ..conf import SparkConf from .dataframe import DataFrame @@ -191,9 +190,20 @@ def newSession(self) -> "SparkSession": return SparkSession(self._context) def range( - self, start: int, end: Optional[int] = None, step: int = 1, numPartitions: Optional[int] = None + self, + start: int, + end: Optional[int] = None, + step: int = 1, + numPartitions: Optional[int] = None, ) -> "DataFrame": - raise ContributionsAcceptedError + if numPartitions: + raise ContributionsAcceptedError + + if end is None: + end = start + start = 0 + + return DataFrame(self.conn.table_function("range", parameters=[start, end, step]),self) def sql(self, sqlQuery: str, **kwargs: Any) -> DataFrame: if kwargs: @@ -241,7 +251,7 @@ def streams(self) -> Any: @property def udf(self) -> UDFRegistration: - return UDFRegistration() + return UDFRegistration(self) @property def version(self) -> str: diff --git a/tools/pythonpkg/duckdb/experimental/spark/sql/udf.py b/tools/pythonpkg/duckdb/experimental/spark/sql/udf.py index f2e5335a951..61d3bee904a 100644 --- a/tools/pythonpkg/duckdb/experimental/spark/sql/udf.py +++ b/tools/pythonpkg/duckdb/experimental/spark/sql/udf.py @@ -1,8 +1,36 @@ # https://sparkbyexamples.com/pyspark/pyspark-udf-user-defined-function/ +from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union + +from .types import DataType + +if TYPE_CHECKING: + from .session import SparkSession + +DataTypeOrString = Union[DataType, str] +UserDefinedFunctionLike = TypeVar("UserDefinedFunctionLike") class UDFRegistration: - def __init__(self): + def __init__(self, sparkSession: "SparkSession"): + self.sparkSession = sparkSession + + def register( + self, + name: str, + f: Union[Callable[..., Any], "UserDefinedFunctionLike"], + returnType: Optional["DataTypeOrString"] = None, + ) -> "UserDefinedFunctionLike": + self.sparkSession.conn.create_function(name, f, return_type=returnType) + + def registerJavaFunction( + self, + name: str, + javaClassName: str, + returnType: Optional["DataTypeOrString"] = None, + ) -> None: + raise NotImplementedError + + def registerJavaUDAF(self, name: str, javaClassName: str) -> None: raise NotImplementedError diff --git a/tools/pythonpkg/duckdb_python.cpp b/tools/pythonpkg/duckdb_python.cpp index d9504bfa722..bec9342d83c 100644 --- a/tools/pythonpkg/duckdb_python.cpp +++ b/tools/pythonpkg/duckdb_python.cpp @@ -71,6 +71,890 @@ static py::list PyTokenize(const string &query) { } static void InitializeConnectionMethods(py::module_ &m) { + + // START_OF_CONNECTION_METHODS + m.def( + "cursor", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Cursor(); + }, + "Create a duplicate of the current connection", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "register_filesystem", + [](AbstractFileSystem filesystem, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + conn->RegisterFilesystem(filesystem); + }, + "Register a fsspec compliant filesystem", py::arg("filesystem"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "unregister_filesystem", + [](const py::str &name, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + conn->UnregisterFilesystem(name); + }, + "Unregister a filesystem", py::arg("name"), py::kw_only(), py::arg("connection") = py::none()); + m.def( + "list_filesystems", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->ListFilesystems(); + }, + "List registered filesystems, including builtin ones", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "filesystem_is_registered", + [](const string &name, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FileSystemIsRegistered(name); + }, + "Check if a filesystem with the provided name is currently registered", py::arg("name"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "create_function", + [](const string &name, const py::function &udf, const py::object &arguments = py::none(), + const shared_ptr &return_type = nullptr, PythonUDFType type = PythonUDFType::NATIVE, + FunctionNullHandling null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING, + PythonExceptionHandling exception_handling = PythonExceptionHandling::FORWARD_ERROR, + bool side_effects = false, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->RegisterScalarUDF(name, udf, arguments, return_type, type, null_handling, exception_handling, + side_effects); + }, + "Create a DuckDB function out of the passing in Python function so it can be used in queries", py::arg("name"), + py::arg("function"), py::arg("parameters") = py::none(), py::arg("return_type") = py::none(), py::kw_only(), + py::arg("type") = PythonUDFType::NATIVE, py::arg("null_handling") = FunctionNullHandling::DEFAULT_NULL_HANDLING, + py::arg("exception_handling") = PythonExceptionHandling::FORWARD_ERROR, py::arg("side_effects") = false, + py::arg("connection") = py::none()); + m.def( + "remove_function", + [](const string &name, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->UnregisterUDF(name); + }, + "Remove a previously created function", py::arg("name"), py::kw_only(), py::arg("connection") = py::none()); + m.def( + "sqltype", + [](const string &type_str, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Type(type_str); + }, + "Create a type object by parsing the 'type_str' string", py::arg("type_str"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "dtype", + [](const string &type_str, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Type(type_str); + }, + "Create a type object by parsing the 'type_str' string", py::arg("type_str"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "type", + [](const string &type_str, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Type(type_str); + }, + "Create a type object by parsing the 'type_str' string", py::arg("type_str"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "array_type", + [](const shared_ptr &type, idx_t size, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->ArrayType(type, size); + }, + "Create an array type object of 'type'", py::arg("type").none(false), py::arg("size"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "list_type", + [](const shared_ptr &type, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->ListType(type); + }, + "Create a list type object of 'type'", py::arg("type").none(false), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "union_type", + [](const py::object &members, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->UnionType(members); + }, + "Create a union type object from 'members'", py::arg("members").none(false), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "string_type", + [](const string &collation = string(), shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->StringType(collation); + }, + "Create a string type with an optional collation", py::arg("collation") = "", py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "enum_type", + [](const string &name, const shared_ptr &type, const py::list &values_p, + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->EnumType(name, type, values_p); + }, + "Create an enum type of underlying 'type', consisting of the list of 'values'", py::arg("name"), + py::arg("type"), py::arg("values"), py::kw_only(), py::arg("connection") = py::none()); + m.def( + "decimal_type", + [](int width, int scale, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->DecimalType(width, scale); + }, + "Create a decimal type with 'width' and 'scale'", py::arg("width"), py::arg("scale"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "struct_type", + [](const py::object &fields, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->StructType(fields); + }, + "Create a struct type object from 'fields'", py::arg("fields"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "row_type", + [](const py::object &fields, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->StructType(fields); + }, + "Create a struct type object from 'fields'", py::arg("fields"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "map_type", + [](const shared_ptr &key_type, const shared_ptr &value_type, + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->MapType(key_type, value_type); + }, + "Create a map type object from 'key_type' and 'value_type'", py::arg("key").none(false), + py::arg("value").none(false), py::kw_only(), py::arg("connection") = py::none()); + m.def( + "duplicate", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Cursor(); + }, + "Create a duplicate of the current connection", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "execute", + [](const py::object &query, py::object params = py::list(), shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Execute(query, params); + }, + "Execute the given SQL query, optionally using prepared statements with parameters set", py::arg("query"), + py::arg("parameters") = py::none(), py::kw_only(), py::arg("connection") = py::none()); + m.def( + "executemany", + [](const py::object &query, py::object params = py::list(), shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->ExecuteMany(query, params); + }, + "Execute the given prepared statement multiple times using the list of parameter sets in parameters", + py::arg("query"), py::arg("parameters") = py::none(), py::kw_only(), py::arg("connection") = py::none()); + m.def( + "close", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + conn->Close(); + }, + "Close the connection", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "interrupt", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + conn->Interrupt(); + }, + "Interrupt pending operations", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "fetchone", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchOne(); + }, + "Fetch a single row from a result following execute", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "fetchmany", + [](idx_t size, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchMany(size); + }, + "Fetch the next set of rows from a result following execute", py::arg("size") = 1, py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "fetchall", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchAll(); + }, + "Fetch all rows from a result following execute", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "fetchnumpy", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchNumpy(); + }, + "Fetch a result as list of NumPy arrays following execute", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "fetchdf", + [](bool date_as_object, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchDF(date_as_object); + }, + "Fetch a result as DataFrame following execute()", py::kw_only(), py::arg("date_as_object") = false, + py::arg("connection") = py::none()); + m.def( + "fetch_df", + [](bool date_as_object, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchDF(date_as_object); + }, + "Fetch a result as DataFrame following execute()", py::kw_only(), py::arg("date_as_object") = false, + py::arg("connection") = py::none()); + m.def( + "df", + [](bool date_as_object, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchDF(date_as_object); + }, + "Fetch a result as DataFrame following execute()", py::kw_only(), py::arg("date_as_object") = false, + py::arg("connection") = py::none()); + m.def( + "fetch_df_chunk", + [](const idx_t vectors_per_chunk = 1, bool date_as_object = false, + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchDFChunk(vectors_per_chunk, date_as_object); + }, + "Fetch a chunk of the result as DataFrame following execute()", py::arg("vectors_per_chunk") = 1, py::kw_only(), + py::arg("date_as_object") = false, py::arg("connection") = py::none()); + m.def( + "pl", + [](idx_t rows_per_batch, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchPolars(rows_per_batch); + }, + "Fetch a result as Polars DataFrame following execute()", py::arg("rows_per_batch") = 1000000, py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "fetch_arrow_table", + [](idx_t rows_per_batch, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchArrow(rows_per_batch); + }, + "Fetch a result as Arrow table following execute()", py::arg("rows_per_batch") = 1000000, py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "arrow", + [](idx_t rows_per_batch, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchArrow(rows_per_batch); + }, + "Fetch a result as Arrow table following execute()", py::arg("rows_per_batch") = 1000000, py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "fetch_record_batch", + [](const idx_t rows_per_batch, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchRecordBatchReader(rows_per_batch); + }, + "Fetch an Arrow RecordBatchReader following execute()", py::arg("rows_per_batch") = 1000000, py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "torch", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchPyTorch(); + }, + "Fetch a result as dict of PyTorch Tensors following execute()", py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "tf", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FetchTF(); + }, + "Fetch a result as dict of TensorFlow Tensors following execute()", py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "begin", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Begin(); + }, + "Start a new transaction", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "commit", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Commit(); + }, + "Commit changes performed within a transaction", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "rollback", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Rollback(); + }, + "Roll back changes performed within a transaction", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "checkpoint", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Checkpoint(); + }, + "Synchronizes data in the write-ahead log (WAL) to the database data file (no-op for in-memory connections)", + py::kw_only(), py::arg("connection") = py::none()); + m.def( + "append", + [](const string &name, const PandasDataFrame &value, bool by_name, + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Append(name, value, by_name); + }, + "Append the passed DataFrame to the named table", py::arg("table_name"), py::arg("df"), py::kw_only(), + py::arg("by_name") = false, py::arg("connection") = py::none()); + m.def( + "register", + [](const string &name, const py::object &python_object, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->RegisterPythonObject(name, python_object); + }, + "Register the passed Python Object value for querying with a view", py::arg("view_name"), + py::arg("python_object"), py::kw_only(), py::arg("connection") = py::none()); + m.def( + "unregister", + [](const string &name, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->UnregisterPythonObject(name); + }, + "Unregister the view name", py::arg("view_name"), py::kw_only(), py::arg("connection") = py::none()); + m.def( + "table", + [](const string &tname, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Table(tname); + }, + "Create a relation object for the named table", py::arg("table_name"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "view", + [](const string &vname, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->View(vname); + }, + "Create a relation object for the named view", py::arg("view_name"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "values", + [](py::object params = py::none(), shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->Values(params); + }, + "Create a relation object from the passed values", py::arg("values"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "table_function", + [](const string &fname, py::object params = py::list(), shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->TableFunction(fname, params); + }, + "Create a relation object from the named table function with given parameters", py::arg("name"), + py::arg("parameters") = py::none(), py::kw_only(), py::arg("connection") = py::none()); + m.def( + "read_json", + [](const string &filename, const Optional &columns = py::none(), + const Optional &sample_size = py::none(), const Optional &maximum_depth = py::none(), + const Optional &records = py::none(), const Optional &format = py::none(), + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->ReadJSON(filename, columns, sample_size, maximum_depth, records, format); + }, + "Create a relation object from the JSON file in 'name'", py::arg("name"), py::kw_only(), + py::arg("columns") = py::none(), py::arg("sample_size") = py::none(), py::arg("maximum_depth") = py::none(), + py::arg("records") = py::none(), py::arg("format") = py::none(), py::arg("connection") = py::none()); + m.def( + "extract_statements", + [](const string &query, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->ExtractStatements(query); + }, + "Parse the query string and extract the Statement object(s) produced", py::arg("query"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "sql", + [](const py::object &query, string alias = "", py::object params = py::list(), + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->RunQuery(query, alias, params); + }, + "Run a SQL query. If it is a SELECT statement, create a relation object from the given SQL query, otherwise " + "run the query as-is.", + py::arg("query"), py::kw_only(), py::arg("alias") = "", py::arg("params") = py::none(), + py::arg("connection") = py::none()); + m.def( + "query", + [](const py::object &query, string alias = "", py::object params = py::list(), + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->RunQuery(query, alias, params); + }, + "Run a SQL query. If it is a SELECT statement, create a relation object from the given SQL query, otherwise " + "run the query as-is.", + py::arg("query"), py::kw_only(), py::arg("alias") = "", py::arg("params") = py::none(), + py::arg("connection") = py::none()); + m.def( + "from_query", + [](const py::object &query, string alias = "", py::object params = py::list(), + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->RunQuery(query, alias, params); + }, + "Run a SQL query. If it is a SELECT statement, create a relation object from the given SQL query, otherwise " + "run the query as-is.", + py::arg("query"), py::kw_only(), py::arg("alias") = "", py::arg("params") = py::none(), + py::arg("connection") = py::none()); + m.def( + "read_csv", + [](const py::object &name, const py::object &header = py::none(), const py::object &compression = py::none(), + const py::object &sep = py::none(), const py::object &delimiter = py::none(), + const py::object &dtype = py::none(), const py::object &na_values = py::none(), + const py::object &skiprows = py::none(), const py::object "echar = py::none(), + const py::object &escapechar = py::none(), const py::object &encoding = py::none(), + const py::object ¶llel = py::none(), const py::object &date_format = py::none(), + const py::object ×tamp_format = py::none(), const py::object &sample_size = py::none(), + const py::object &all_varchar = py::none(), const py::object &normalize_names = py::none(), + const py::object &filename = py::none(), const py::object &null_padding = py::none(), + const py::object &names = py::none(), shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->ReadCSV(name, header, compression, sep, delimiter, dtype, na_values, skiprows, quotechar, + escapechar, encoding, parallel, date_format, timestamp_format, sample_size, + all_varchar, normalize_names, filename, null_padding, names); + }, + "Create a relation object from the CSV file in 'name'", py::arg("path_or_buffer"), py::kw_only(), + py::arg("header") = py::none(), py::arg("compression") = py::none(), py::arg("sep") = py::none(), + py::arg("delimiter") = py::none(), py::arg("dtype") = py::none(), py::arg("na_values") = py::none(), + py::arg("skiprows") = py::none(), py::arg("quotechar") = py::none(), py::arg("escapechar") = py::none(), + py::arg("encoding") = py::none(), py::arg("parallel") = py::none(), py::arg("date_format") = py::none(), + py::arg("timestamp_format") = py::none(), py::arg("sample_size") = py::none(), + py::arg("all_varchar") = py::none(), py::arg("normalize_names") = py::none(), py::arg("filename") = py::none(), + py::arg("null_padding") = py::none(), py::arg("names") = py::none(), py::arg("connection") = py::none()); + m.def( + "from_csv_auto", + [](const py::object &name, const py::object &header = py::none(), const py::object &compression = py::none(), + const py::object &sep = py::none(), const py::object &delimiter = py::none(), + const py::object &dtype = py::none(), const py::object &na_values = py::none(), + const py::object &skiprows = py::none(), const py::object "echar = py::none(), + const py::object &escapechar = py::none(), const py::object &encoding = py::none(), + const py::object ¶llel = py::none(), const py::object &date_format = py::none(), + const py::object ×tamp_format = py::none(), const py::object &sample_size = py::none(), + const py::object &all_varchar = py::none(), const py::object &normalize_names = py::none(), + const py::object &filename = py::none(), const py::object &null_padding = py::none(), + const py::object &names = py::none(), shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->ReadCSV(name, header, compression, sep, delimiter, dtype, na_values, skiprows, quotechar, + escapechar, encoding, parallel, date_format, timestamp_format, sample_size, + all_varchar, normalize_names, filename, null_padding, names); + }, + "Create a relation object from the CSV file in 'name'", py::arg("path_or_buffer"), py::kw_only(), + py::arg("header") = py::none(), py::arg("compression") = py::none(), py::arg("sep") = py::none(), + py::arg("delimiter") = py::none(), py::arg("dtype") = py::none(), py::arg("na_values") = py::none(), + py::arg("skiprows") = py::none(), py::arg("quotechar") = py::none(), py::arg("escapechar") = py::none(), + py::arg("encoding") = py::none(), py::arg("parallel") = py::none(), py::arg("date_format") = py::none(), + py::arg("timestamp_format") = py::none(), py::arg("sample_size") = py::none(), + py::arg("all_varchar") = py::none(), py::arg("normalize_names") = py::none(), py::arg("filename") = py::none(), + py::arg("null_padding") = py::none(), py::arg("names") = py::none(), py::arg("connection") = py::none()); + m.def( + "from_df", + [](const PandasDataFrame &value, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromDF(value); + }, + "Create a relation object from the DataFrame in df", py::arg("df"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "from_arrow", + [](py::object &arrow_object, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromArrow(arrow_object); + }, + "Create a relation object from an Arrow object", py::arg("arrow_object"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "from_parquet", + [](const string &file_glob, bool binary_as_string, bool file_row_number, bool filename, bool hive_partitioning, + bool union_by_name, const py::object &compression = py::none(), + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromParquet(file_glob, binary_as_string, file_row_number, filename, hive_partitioning, + union_by_name, compression); + }, + "Create a relation object from the Parquet files in file_glob", py::arg("file_glob"), + py::arg("binary_as_string") = false, py::kw_only(), py::arg("file_row_number") = false, + py::arg("filename") = false, py::arg("hive_partitioning") = false, py::arg("union_by_name") = false, + py::arg("compression") = py::none(), py::arg("connection") = py::none()); + m.def( + "read_parquet", + [](const string &file_glob, bool binary_as_string, bool file_row_number, bool filename, bool hive_partitioning, + bool union_by_name, const py::object &compression = py::none(), + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromParquet(file_glob, binary_as_string, file_row_number, filename, hive_partitioning, + union_by_name, compression); + }, + "Create a relation object from the Parquet files in file_glob", py::arg("file_glob"), + py::arg("binary_as_string") = false, py::kw_only(), py::arg("file_row_number") = false, + py::arg("filename") = false, py::arg("hive_partitioning") = false, py::arg("union_by_name") = false, + py::arg("compression") = py::none(), py::arg("connection") = py::none()); + m.def( + "from_parquet", + [](const vector &file_globs, bool binary_as_string, bool file_row_number, bool filename, + bool hive_partitioning, bool union_by_name, const py::object &compression = py::none(), + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromParquets(file_globs, binary_as_string, file_row_number, filename, hive_partitioning, + union_by_name, compression); + }, + "Create a relation object from the Parquet files in file_globs", py::arg("file_globs"), + py::arg("binary_as_string") = false, py::kw_only(), py::arg("file_row_number") = false, + py::arg("filename") = false, py::arg("hive_partitioning") = false, py::arg("union_by_name") = false, + py::arg("compression") = py::none(), py::arg("connection") = py::none()); + m.def( + "read_parquet", + [](const vector &file_globs, bool binary_as_string, bool file_row_number, bool filename, + bool hive_partitioning, bool union_by_name, const py::object &compression = py::none(), + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromParquets(file_globs, binary_as_string, file_row_number, filename, hive_partitioning, + union_by_name, compression); + }, + "Create a relation object from the Parquet files in file_globs", py::arg("file_globs"), + py::arg("binary_as_string") = false, py::kw_only(), py::arg("file_row_number") = false, + py::arg("filename") = false, py::arg("hive_partitioning") = false, py::arg("union_by_name") = false, + py::arg("compression") = py::none(), py::arg("connection") = py::none()); + m.def( + "from_substrait", + [](py::bytes &proto, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromSubstrait(proto); + }, + "Create a query object from protobuf plan", py::arg("proto"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "get_substrait", + [](const string &query, bool enable_optimizer = true, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->GetSubstrait(query, enable_optimizer); + }, + "Serialize a query to protobuf", py::arg("query"), py::kw_only(), py::arg("enable_optimizer") = true, + py::arg("connection") = py::none()); + m.def( + "get_substrait_json", + [](const string &query, bool enable_optimizer = true, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->GetSubstraitJSON(query, enable_optimizer); + }, + "Serialize a query to protobuf on the JSON format", py::arg("query"), py::kw_only(), + py::arg("enable_optimizer") = true, py::arg("connection") = py::none()); + m.def( + "from_substrait_json", + [](const string &json, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromSubstraitJSON(json); + }, + "Create a query object from a JSON protobuf plan", py::arg("json"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "get_table_names", + [](const string &query, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->GetTableNames(query); + }, + "Extract the required table names from a query", py::arg("query"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "install_extension", + [](const string &extension, bool force_install = false, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + conn->InstallExtension(extension, force_install); + }, + "Install an extension by name", py::arg("extension"), py::kw_only(), py::arg("force_install") = false, + py::arg("connection") = py::none()); + m.def( + "load_extension", + [](const string &extension, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + conn->LoadExtension(extension); + }, + "Load an installed extension", py::arg("extension"), py::kw_only(), py::arg("connection") = py::none()); + m.def( + "project", + [](const PandasDataFrame &df, const py::args &args, const string &groups = "", + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromDF(df)->Project(args, groups); + }, + "Project the relation object by the projection in project_expr", py::arg("df"), py::kw_only(), + py::arg("groups") = "", py::arg("connection") = py::none()); + m.def( + "distinct", + [](const PandasDataFrame &df, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromDF(df)->Distinct(); + }, + "Retrieve distinct rows from this relation object", py::arg("df"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "write_csv", + [](const PandasDataFrame &df, const string &filename, const py::object &sep = py::none(), + const py::object &na_rep = py::none(), const py::object &header = py::none(), + const py::object "echar = py::none(), const py::object &escapechar = py::none(), + const py::object &date_format = py::none(), const py::object ×tamp_format = py::none(), + const py::object "ing = py::none(), const py::object &encoding = py::none(), + const py::object &compression = py::none(), const py::object &overwrite = py::none(), + const py::object &per_thread_output = py::none(), const py::object &use_tmp_file = py::none(), + const py::object &partition_by = py::none(), shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + conn->FromDF(df)->ToCSV(filename, sep, na_rep, header, quotechar, escapechar, date_format, timestamp_format, + quoting, encoding, compression, overwrite, per_thread_output, use_tmp_file, + partition_by); + }, + "Write the relation object to a CSV file in 'file_name'", py::arg("df"), py::arg("filename"), py::kw_only(), + py::arg("sep") = py::none(), py::arg("na_rep") = py::none(), py::arg("header") = py::none(), + py::arg("quotechar") = py::none(), py::arg("escapechar") = py::none(), py::arg("date_format") = py::none(), + py::arg("timestamp_format") = py::none(), py::arg("quoting") = py::none(), py::arg("encoding") = py::none(), + py::arg("compression") = py::none(), py::arg("overwrite") = py::none(), + py::arg("per_thread_output") = py::none(), py::arg("use_tmp_file") = py::none(), + py::arg("partition_by") = py::none(), py::arg("connection") = py::none()); + m.def( + "aggregate", + [](const PandasDataFrame &df, const string &expr, const string &groups = "", + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromDF(df)->Aggregate(expr, groups); + }, + "Compute the aggregate aggr_expr by the optional groups group_expr on the relation", py::arg("df"), + py::arg("aggr_expr"), py::arg("group_expr") = "", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "alias", + [](const PandasDataFrame &df, const string &expr, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromDF(df)->SetAlias(expr); + }, + "Rename the relation object to new alias", py::arg("df"), py::arg("alias"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "filter", + [](const PandasDataFrame &df, const py::object &expr, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromDF(df)->Filter(expr); + }, + "Filter the relation object by the filter in filter_expr", py::arg("df"), py::arg("filter_expr"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "limit", + [](const PandasDataFrame &df, int64_t n, int64_t offset = 0, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromDF(df)->Limit(n, offset); + }, + "Only retrieve the first n rows from this relation object, starting at offset", py::arg("df"), py::arg("n"), + py::arg("offset") = 0, py::kw_only(), py::arg("connection") = py::none()); + m.def( + "order", + [](const PandasDataFrame &df, const string &expr, shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromDF(df)->Order(expr); + }, + "Reorder the relation object by order_expr", py::arg("df"), py::arg("order_expr"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "query_df", + [](const PandasDataFrame &df, const string &view_name, const string &sql_query, + shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->FromDF(df)->Query(view_name, sql_query); + }, + "Run the given SQL query in sql_query on the view named virtual_table_name that refers to the relation object", + py::arg("df"), py::arg("virtual_table_name"), py::arg("sql_query"), py::kw_only(), + py::arg("connection") = py::none()); + m.def( + "description", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->GetDescription(); + }, + "Get result set attributes, mainly column names", py::kw_only(), py::arg("connection") = py::none()); + m.def( + "rowcount", + [](shared_ptr conn = nullptr) { + if (!conn) { + conn = DuckDBPyConnection::DefaultConnection(); + } + return conn->GetRowcount(); + }, + "Get result set row count", py::kw_only(), py::arg("connection") = py::none()); + // END_OF_CONNECTION_METHODS + // We define these "wrapper" methods manually because they are overloaded m.def( "arrow", diff --git a/tools/pythonpkg/pyproject.toml b/tools/pythonpkg/pyproject.toml index 7b3e4adba95..2b2ae2e7420 100644 --- a/tools/pythonpkg/pyproject.toml +++ b/tools/pythonpkg/pyproject.toml @@ -18,7 +18,7 @@ local_scheme = "no-local-version" dependency-versions = "latest" environment = "PIP_CONSTRAINT='build-constraints.txt'" before-build = 'pip install oldest-supported-numpy' -before-test = 'pip install --prefer-binary pandas pytest-timeout mypy "psutil>=5.9.0" "requests>=2.26" fsspec && (pip install --prefer-binary "pyarrow>=8.0" || true) && (pip install --prefer-binary "torch" || true) && (pip install --prefer-binary "polars" || true) && (pip install --prefer-binary "adbc_driver_manager" || true) && (pip install --prefer-binary "tensorflow" || true)' +before-test = 'python scripts/optional_requirements.py' test-requires = 'pytest' test-command = 'DUCKDB_PYTHON_TEST_EXTENSION_PATH={project} DUCKDB_PYTHON_TEST_EXTENSION_REQUIRED=1 python -m pytest {project}/tests --verbose' @@ -40,3 +40,7 @@ test-command = "python -m pytest {project}/tests/fast --verbose" [tool.cibuildwheel.windows] archs = ["AMD64"] test-command = "python -m pytest {project}/tests/fast --verbose" + +# See https://github.com/duckdblabs/duckdb-internal/issues/1923 for context +[tool.cibuildwheel.macos] +before-test = 'python scripts/optional_requirements.py --exclude polars --exclude tensorflow' diff --git a/tools/pythonpkg/requirements-dev.txt b/tools/pythonpkg/requirements-dev.txt index f824ec54221..a81c9657c42 100644 --- a/tools/pythonpkg/requirements-dev.txt +++ b/tools/pythonpkg/requirements-dev.txt @@ -4,9 +4,16 @@ setuptools_scm>=6.3 setuptools>=58 pytest pandas -pyarrow +pytest-timeout mypy psutil>=5.9.0 +requests>=2.26 fsspec +pyarrow>=8.0 +torch polars +adbc_driver_manager tensorflow +cxxheaderparser +pcpp + diff --git a/tools/pythonpkg/scripts/cache_data.json b/tools/pythonpkg/scripts/cache_data.json index 75ef09fa092..38fdb297dc1 100644 --- a/tools/pythonpkg/scripts/cache_data.json +++ b/tools/pythonpkg/scripts/cache_data.json @@ -252,7 +252,8 @@ "numpy.csingle", "numpy.cdouble", "numpy.clongdouble" - ] + ], + "required": false }, "numpy.core": { "type": "attribute", @@ -501,7 +502,8 @@ "name": "types", "children": [ "types.UnionType", - "types.GenericAlias" + "types.GenericAlias", + "types.BuiltinFunctionType" ] }, "types.UnionType": { @@ -516,6 +518,12 @@ "name": "GenericAlias", "children": [] }, + "types.BuiltinFunctionType": { + "type": "attribute", + "full_path": "types.BuiltinFunctionType", + "name": "BuiltinFunctionType", + "children": [] + }, "typing": { "type": "module", "full_path": "typing", @@ -543,5 +551,34 @@ "full_path": "uuid.UUID", "name": "UUID", "children": [] + }, + "collections": { + "type": "module", + "full_path": "collections", + "name": "collections", + "children": [ + "collections.abc" + ] + }, + "collections.abc": { + "type": "module", + "full_path": "collections.abc", + "name": "abc", + "children": [ + "collections.abc.Iterable", + "collections.abc.Mapping" + ] + }, + "collections.abc.Iterable": { + "type": "attribute", + "full_path": "collections.abc.Iterable", + "name": "Iterable", + "children": [] + }, + "collections.abc.Mapping": { + "type": "attribute", + "full_path": "collections.abc.Mapping", + "name": "Mapping", + "children": [] } } \ No newline at end of file diff --git a/tools/pythonpkg/scripts/connection_methods.json b/tools/pythonpkg/scripts/connection_methods.json index aaa1474839f..abbf5b0299e 100644 --- a/tools/pythonpkg/scripts/connection_methods.json +++ b/tools/pythonpkg/scripts/connection_methods.json @@ -260,11 +260,6 @@ "name": "parameters", "default": "None", "type": "object" - }, - { - "name": "multiple_parameter_sets", - "default": "False", - "type": "bool" } ], "return": "DuckDBPyConnection" @@ -431,6 +426,12 @@ "docs": "Roll back changes performed within a transaction", "return": "DuckDBPyConnection" }, + { + "name": "checkpoint", + "function": "Checkpoint", + "docs": "Synchronizes data in the write-ahead log (WAL) to the database data file (no-op for in-memory connections)", + "return": "DuckDBPyConnection" + }, { "name": "append", "function": "Append", diff --git a/tools/pythonpkg/scripts/connection_wrapper_methods.json b/tools/pythonpkg/scripts/connection_wrapper_methods.json index 74f4cf31eba..b92f0913eae 100644 --- a/tools/pythonpkg/scripts/connection_wrapper_methods.json +++ b/tools/pythonpkg/scripts/connection_wrapper_methods.json @@ -1,30 +1,116 @@ [ { "name": "project", + "function": "Project", "args": [ { - "name": "project_expr", + "name": "*args", "type": "str" } ], + "kwargs": [ + { + "name": "groups", + "type": "str", + "default": "\"\"" + } + ], + "docs": "Project the relation object by the projection in project_expr", "return": "DuckDBPyRelation" }, { "name": "distinct", + "function": "Distinct", + "docs": "Retrieve distinct rows from this relation object", "return": "DuckDBPyRelation" }, { "name": "write_csv", + "function": "ToCSV", "args": [ { - "name": "*args", - "type": "Any" + "name": "filename", + "type": "str" + } + ], + "kwargs": [ + { + "name": "sep", + "type": "Optional[str]", + "default": "None" + }, + { + "name": "na_rep", + "type": "Optional[str]", + "default": "None" + }, + { + "name": "header", + "type": "Optional[bool]", + "default": "None" + }, + { + "name": "quotechar", + "type": "Optional[str]", + "default": "None" + }, + { + "name": "escapechar", + "type": "Optional[str]", + "default": "None" + }, + { + "name": "date_format", + "type": "Optional[str]", + "default": "None" + }, + { + "name": "timestamp_format", + "type": "Optional[str]", + "default": "None" + }, + { + "name": "quoting", + "type": "Optional[str | int]", + "default": "None" + }, + { + "name": "encoding", + "type": "Optional[str]", + "default": "None" + }, + { + "name": "compression", + "type": "Optional[str]", + "default": "None" + }, + { + "name": "overwrite", + "type": "Optional[bool]", + "default": "None" + }, + { + "name": "per_thread_output", + "type": "Optional[bool]", + "default": "None" + }, + { + "name": "use_tmp_file", + "type": "Optional[bool]", + "default": "None" + }, + { + "name": "partition_by", + "type": "Optional[List[str]]", + "default": "None" } ], + "docs": "Write the relation object to a CSV file in 'file_name'", "return": "None" }, { "name": "aggregate", + "function": "Aggregate", "args": [ { "name": "aggr_expr", @@ -33,33 +119,39 @@ { "name": "group_expr", "type" : "str", - "default": "\"\"" + "default": "\"\"" } ], + "docs": "Compute the aggregate aggr_expr by the optional groups group_expr on the relation", "return": "DuckDBPyRelation" }, { "name": "alias", + "function": "SetAlias", "args": [ { "name": "alias", "type": "str" } ], + "docs": "Rename the relation object to new alias", "return": "DuckDBPyRelation" }, { "name": "filter", + "function": "Filter", "args": [ { "name": "filter_expr", "type": "str" } ], + "docs": "Filter the relation object by the filter in filter_expr", "return": "DuckDBPyRelation" }, { "name": "limit", + "function": "Limit", "args": [ { "name": "n", @@ -71,20 +163,24 @@ "default": "0" } ], + "docs": "Only retrieve the first n rows from this relation object, starting at offset", "return": "DuckDBPyRelation" }, { "name": "order", + "function": "Order", "args": [ { "name": "order_expr", "type": "str" } ], + "docs": "Reorder the relation object by order_expr", "return": "DuckDBPyRelation" }, { "name": "query_df", + "function": "Query", "args": [ { "name": "virtual_table_name", @@ -95,14 +191,19 @@ "type": "str" } ], + "docs": "Run the given SQL query in sql_query on the view named virtual_table_name that refers to the relation object", "return": "DuckDBPyRelation" }, { "name": "description", + "function": "GetDescription", + "docs": "Get result set attributes, mainly column names", "return": "Optional[List[Any]]" }, { "name": "rowcount", + "function": "GetRowcount", + "docs": "Get result set row count", "return": "int" } ] diff --git a/tools/pythonpkg/scripts/generate_connection_wrapper_methods.py b/tools/pythonpkg/scripts/generate_connection_wrapper_methods.py index ac6345212c8..2ad56508354 100644 --- a/tools/pythonpkg/scripts/generate_connection_wrapper_methods.py +++ b/tools/pythonpkg/scripts/generate_connection_wrapper_methods.py @@ -1,29 +1,65 @@ import os +import sys import json +# Requires `python3 -m pip install cxxheaderparser pcpp` +from get_cpp_methods import get_methods, FunctionParam, ConnectionMethod +from typing import List, Tuple + os.chdir(os.path.dirname(__file__)) JSON_PATH = os.path.join("connection_methods.json") +DUCKDB_PYTHON_SOURCE = os.path.join("..", "duckdb_python.cpp") + +START_MARKER = "\t// START_OF_CONNECTION_METHODS" +END_MARKER = "\t// END_OF_CONNECTION_METHODS" + +LAMBDA_FORMAT = """ + []({param_definitions}) {{ + if (!conn) {{ + conn = DuckDBPyConnection::DefaultConnection(); + }} + {opt_return}conn->{function_name}({parameter_names}); + }}""" + +PY_INIT_FORMAT = """ +from .duckdb import ( +{item_list} +) + +_exported_symbols.extend([ +{str_item_list} +]) +""" + WRAPPER_JSON_PATH = os.path.join("connection_wrapper_methods.json") + DUCKDB_INIT_FILE = os.path.join("..", "duckdb", "__init__.py") +INIT_PY_START = "# START OF CONNECTION WRAPPER" +INIT_PY_END = "# END OF CONNECTION WRAPPER" -START_MARKER = "# START OF CONNECTION WRAPPER" -END_MARKER = "# END OF CONNECTION WRAPPER" +# Read the JSON file +with open(WRAPPER_JSON_PATH, 'r') as json_file: + wrapper_methods = json.load(json_file) +# On DuckDBPyConnection these are read_only_properties, they're basically functions without requiring () to invoke +# that's not possible on 'duckdb' so it becomes a function call with no arguments (i.e duckdb.description()) +READONLY_PROPERTY_NAMES = ['description', 'rowcount'] + +# These methods are not directly DuckDBPyConnection methods, +# they first call 'FromDF' and then call a method on the created DuckDBPyRelation +SPECIAL_METHOD_NAMES = [x['name'] for x in wrapper_methods if x['name'] not in READONLY_PROPERTY_NAMES] -def generate(): - # Read the DUCKDB_INIT_FILE file - with open(DUCKDB_INIT_FILE, 'r') as source_file: - source_code = source_file.readlines() +def remove_section(content, start_marker, end_marker) -> Tuple[List[str], List[str]]: start_index = -1 end_index = -1 - for i, line in enumerate(source_code): - if line.startswith(START_MARKER): + for i, line in enumerate(content): + if line.startswith(start_marker): if start_index != -1: raise ValueError("Encountered the START_MARKER a second time, quitting!") start_index = i - elif line.startswith(END_MARKER): + elif line.startswith(end_marker): if end_index != -1: raise ValueError("Encountered the END_MARKER a second time, quitting!") end_index = i @@ -31,121 +67,163 @@ def generate(): if start_index == -1 or end_index == -1: raise ValueError("Couldn't find start or end marker in source file") - start_section = source_code[: start_index + 1] - end_section = source_code[end_index:] - # ---- Generate the definition code from the json ---- + start_section = content[: start_index + 1] + end_section = content[end_index:] + return (start_section, end_section) + - methods = [] +def generate(): + # Read the DUCKDB_PYTHON_SOURCE file + with open(DUCKDB_PYTHON_SOURCE, 'r') as source_file: + source_code = source_file.readlines() + start_section, end_section = remove_section(source_code, START_MARKER, END_MARKER) + + # Read the DUCKDB_INIT_FILE file + with open(DUCKDB_INIT_FILE, 'r') as source_file: + source_code = source_file.readlines() + py_start, py_end = remove_section(source_code, INIT_PY_START, INIT_PY_END) + + # ---- Generate the definition code from the json ---- # Read the JSON file with open(JSON_PATH, 'r') as json_file: connection_methods = json.load(json_file) - with open(WRAPPER_JSON_PATH, 'r') as json_file: - wrapper_methods = json.load(json_file) - - methods.extend(connection_methods) - methods.extend(wrapper_methods) - - # On DuckDBPyConnection these are read_only_properties, they're basically functions without requiring () to invoke - # that's not possible on 'duckdb' so it becomes a function call with no arguments (i.e duckdb.description()) - READONLY_PROPERTY_NAMES = ['description', 'rowcount'] + # Collect the definitions from the pyconnection.hpp header + + cpp_connection_defs = get_methods('DuckDBPyConnection') + cpp_relation_defs = get_methods('DuckDBPyRelation') + + DEFAULT_ARGUMENT_MAP = { + 'True': 'true', + 'False': 'false', + 'None': 'py::none()', + 'PythonUDFType.NATIVE': 'PythonUDFType::NATIVE', + 'PythonExceptionHandling.DEFAULT': 'PythonExceptionHandling::FORWARD_ERROR', + 'FunctionNullHandling.DEFAULT': 'FunctionNullHandling::DEFAULT_NULL_HANDLING', + } + + def map_default(val): + if val in DEFAULT_ARGUMENT_MAP: + return DEFAULT_ARGUMENT_MAP[val] + return val + + def create_arguments(arguments) -> list: + result = [] + for arg in arguments: + if arg['name'] == '*args': + # py::args() should not have a corresponding py::arg() + continue + argument = f"py::arg(\"{arg['name']}\")" + if 'allow_none' in arg: + value = str(arg['allow_none']).lower() + argument += f".none({value})" + # Add the default argument if present + if 'default' in arg: + default = map_default(arg['default']) + argument += f" = {default}" + result.append(argument) + return result + + def get_lambda_definition(name, definition: ConnectionMethod) -> str: + param_definitions = [] + if name in SPECIAL_METHOD_NAMES: + param_definitions.append('const PandasDataFrame &df') + param_definitions.extend([x.proto for x in definition.params]) + param_definitions.append('shared_ptr conn = nullptr') + param_definitions = ", ".join(param_definitions) - # These methods are not directly DuckDBPyConnection methods, - # they first call 'from_df' and then call a method on the created DuckDBPyRelation - SPECIAL_METHOD_NAMES = [x['name'] for x in wrapper_methods if x['name'] not in READONLY_PROPERTY_NAMES] + param_names = [x.name for x in definition.params] + param_names = ", ".join(param_names) - def generate_arguments(name, method) -> str: - arguments = [] + function_name = definition.name if name in SPECIAL_METHOD_NAMES: - # We add 'df' to these methods because they operate on a DataFrame - arguments.append('df') - - if 'args' in method: - for arg in method['args']: - res = arg['name'] - if 'default' in arg: - res += f" = {arg['default']}" - arguments.append(res) - arguments.append('**kwargs') - return ', '.join(arguments) - - def generate_parameters(name, method) -> str: - if name in READONLY_PROPERTY_NAMES: - return '' - arguments = [] + function_name = 'FromDF(df)->' + function_name + + format_dict = { + 'param_definitions': param_definitions, + 'opt_return': '' if definition.is_void else 'return ', + 'function_name': function_name, + 'parameter_names': param_names, + } + return LAMBDA_FORMAT.format_map(format_dict) + + def create_definition(name, method, lambda_def) -> str: + definition = f"m.def(\"{name}\"" + definition += ", " + definition += lambda_def + definition += ", " + definition += f"\"{method['docs']}\"" if 'args' in method: - for arg in method['args']: - arguments.append(f"{arg['name']}") - arguments.append('**kwargs') - result = ', '.join(arguments) - return '(' + result + ')' - - def generate_function_call(name) -> str: - function_call = '' - if name in SPECIAL_METHOD_NAMES: - function_call += 'from_df(df).' - - REMAPPED_FUNCTIONS = {'alias': 'set_alias', 'query_df': 'query'} - if name in REMAPPED_FUNCTIONS: - function_name = REMAPPED_FUNCTIONS[name] - else: - function_name = name - function_call += function_name - return function_call - - def create_definition(name, method) -> str: - arguments = generate_arguments(name, method) - parameters = generate_parameters(name, method) - function_call = generate_function_call(name) - - func = f""" -def {name}({arguments}): - if 'connection' in kwargs: - conn = kwargs.pop('connection') - else: - conn = duckdb.connect(":default:") - return conn.{function_call}{parameters} -_exported_symbols.append('{name}') -""" - return func - - # We have "duplicate" methods, which are overloaded - written_methods = set() + definition += ", " + arguments = create_arguments(method['args']) + definition += ', '.join(arguments) + if 'kwargs' in method: + definition += ", " + definition += "py::kw_only(), " + arguments = create_arguments(method['kwargs']) + definition += ', '.join(arguments) + definition += ");" + return definition body = [] - for method in methods: + all_names = [] + for method in connection_methods: if isinstance(method['name'], list): names = method['name'] else: names = [method['name']] - - # Artificially add 'connection' keyword argument if 'kwargs' not in method: method['kwargs'] = [] - method['kwargs'].append({'name': 'connection', 'type': 'DuckDBPyConnection'}) + method['kwargs'].append({'name': 'connection', 'type': 'Optional[DuckDBPyConnection]', 'default': 'None'}) + for name in names: + function_name = method['function'] + cpp_definition = cpp_connection_defs[function_name] + lambda_def = get_lambda_definition(name, cpp_definition) + body.append(create_definition(name, method, lambda_def)) + all_names.append(name) + for method in wrapper_methods: + if isinstance(method['name'], list): + names = method['name'] + else: + names = [method['name']] + if 'kwargs' not in method: + method['kwargs'] = [] + method['kwargs'].append({'name': 'connection', 'type': 'Optional[DuckDBPyConnection]', 'default': 'None'}) for name in names: - if name in written_methods: - continue - if name in ['arrow', 'df']: - # These methods are ambiguous and are handled in C++ code instead - continue - body.append(create_definition(name, method)) - written_methods.add(name) + function_name = method['function'] + if name in SPECIAL_METHOD_NAMES: + cpp_definition = cpp_relation_defs[function_name] + if 'args' not in method: + method['args'] = [] + method['args'].insert(0, {'name': 'df', 'type': 'DataFrame'}) + else: + cpp_definition = cpp_connection_defs[function_name] + lambda_def = get_lambda_definition(name, cpp_definition) + body.append(create_definition(name, method, lambda_def)) + all_names.append(name) # ---- End of generation code ---- - with_newlines = body + with_newlines = ['\t' + x + '\n' for x in body] # Recreate the file content by concatenating all the pieces together - new_content = start_section + with_newlines + end_section + # Write out the modified DUCKDB_PYTHON_SOURCE file + with open(DUCKDB_PYTHON_SOURCE, 'w') as source_file: + source_file.write("".join(new_content)) + item_list = '\n'.join([f'\t{name},' for name in all_names]) + str_item_list = '\n'.join([f"\t'{name}'," for name in all_names]) + imports = PY_INIT_FORMAT.format(item_list=item_list, str_item_list=str_item_list).split('\n') + imports = [x + '\n' for x in imports] + + init_py_content = py_start + imports + py_end # Write out the modified DUCKDB_INIT_FILE file with open(DUCKDB_INIT_FILE, 'w') as source_file: - source_file.write("".join(new_content)) + source_file.write("".join(init_py_content)) if __name__ == '__main__': - raise ValueError("Please use 'generate_connection_code.py' instead of running the individual script(s)") - # generate() + # raise ValueError("Please use 'generate_connection_code.py' instead of running the individual script(s)") + generate() diff --git a/tools/pythonpkg/scripts/generate_connection_wrapper_stubs.py b/tools/pythonpkg/scripts/generate_connection_wrapper_stubs.py index 51d94db3dc2..94b0e0ee4a1 100644 --- a/tools/pythonpkg/scripts/generate_connection_wrapper_stubs.py +++ b/tools/pythonpkg/scripts/generate_connection_wrapper_stubs.py @@ -96,7 +96,7 @@ def create_definition(name, method) -> str: # Artificially add 'connection' keyword argument if 'kwargs' not in method: method['kwargs'] = [] - method['kwargs'].append({'name': 'connection', 'type': 'DuckDBPyConnection'}) + method['kwargs'].append({'name': 'connection', 'type': 'DuckDBPyConnection', 'default': '...'}) for name in names: if name in written_methods: diff --git a/tools/pythonpkg/scripts/get_cpp_methods.py b/tools/pythonpkg/scripts/get_cpp_methods.py new file mode 100644 index 00000000000..e784d0546ea --- /dev/null +++ b/tools/pythonpkg/scripts/get_cpp_methods.py @@ -0,0 +1,87 @@ +# Requires `python3 -m pip install cxxheaderparser pcpp` +import os + +import cxxheaderparser.parser +import cxxheaderparser.visitor +import cxxheaderparser.preprocessor +from typing import List, Dict + +scripts_folder = os.path.dirname(os.path.abspath(__file__)) + + +class FunctionParam: + def __init__(self, name: str, proto: str): + self.proto = proto + self.name = name + + +class ConnectionMethod: + def __init__(self, name: str, params: List[FunctionParam], is_void: bool): + self.name = name + self.params = params + self.is_void = is_void + + +class Visitor: + def __init__(self, class_name: str): + self.methods_dict = {} + self.class_name = class_name + + def __getattr__(self, name): + return lambda *state: True + + def on_class_start(self, state): + name = state.class_decl.typename.segments[0].format() + return name == self.class_name + + def on_class_method(self, state, node): + name = node.name.format() + return_type = node.return_type + is_void = return_type and return_type.format() == "void" + params = [ + FunctionParam( + x.name, + x.type.format() + " " + x.name + (" = " + x.default.format() if x.default else ""), + ) + for x in node.parameters + ] + + self.methods_dict[name] = ConnectionMethod(name, params, is_void) + + +def get_methods(class_name: str) -> Dict[str, ConnectionMethod]: + CLASSES = { + "DuckDBPyConnection": os.path.join( + scripts_folder, + "..", + "src", + "include", + "duckdb_python", + "pyconnection", + "pyconnection.hpp", + ), + "DuckDBPyRelation": os.path.join(scripts_folder, "..", "src", "include", "duckdb_python", "pyrelation.hpp"), + } + # Create a dictionary to store method names and prototypes + methods_dict = {} + + path = CLASSES[class_name] + + visitor = Visitor(class_name) + preprocessor = cxxheaderparser.preprocessor.make_pcpp_preprocessor(retain_all_content=True) + tu = cxxheaderparser.parser.CxxParser( + path, + None, + visitor, + options=cxxheaderparser.parser.ParserOptions( + preprocessor=preprocessor, + ), + ) + tu.parse() + + return visitor.methods_dict + + +if __name__ == "__main__": + print("This module should not called directly, please use `make generate-files` instead") + exit(1) diff --git a/tools/pythonpkg/scripts/imports.py b/tools/pythonpkg/scripts/imports.py index 2e371c97ee2..bc5e65f5964 100644 --- a/tools/pythonpkg/scripts/imports.py +++ b/tools/pythonpkg/scripts/imports.py @@ -92,6 +92,7 @@ types.UnionType types.GenericAlias +types.BuiltinFunctionType import typing @@ -100,3 +101,9 @@ import uuid uuid.UUID + +import collections +import collections.abc + +collections.abc.Iterable +collections.abc.Mapping diff --git a/tools/pythonpkg/scripts/optional_requirements.py b/tools/pythonpkg/scripts/optional_requirements.py new file mode 100644 index 00000000000..bd3c321d262 --- /dev/null +++ b/tools/pythonpkg/scripts/optional_requirements.py @@ -0,0 +1,43 @@ +import os +import subprocess +import argparse + + +def install_package(package_name, is_optional): + try: + subprocess.run(['pip', 'install', '--prefer-binary', package_name], check=True) + except subprocess.CalledProcessError: + if is_optional: + print(f'WARNING: Failed to install (optional) "{package_name}", might require manual review') + return + raise + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Import test dependencies') + parser.add_argument('--exclude', action='append', help='Exclude a package from installation', default=[]) + + args = parser.parse_args() + + # Failing to install this package does not constitute a build failure + OPTIONAL_PACKAGES = ["pyarrow", "torch", "polars", "adbc_driver_manager", "tensorflow"] + + for package in args.exclude: + if package not in OPTIONAL_PACKAGES: + print(f"Unrecognized exclude list item '{package}', has to be one of {', '.join(OPTIONAL_PACKAGES)}") + exit(1) + + script_dir = os.path.dirname(os.path.abspath(__file__)) + requirements_path = os.path.join(script_dir, '..', 'requirements-dev.txt') + + content = open(requirements_path).read() + packages = [x for x in content.split('\n') if x != ''] + + result = [] + for package in packages: + package_name = package.replace('=', '>').replace('<', '>').split('>')[0] + if package_name in args.exclude: + print(f"Skipping {package_name}, as set by the --exclude option") + continue + is_optional = package_name in OPTIONAL_PACKAGES + install_package(package, is_optional) diff --git a/tools/pythonpkg/src/CMakeLists.txt b/tools/pythonpkg/src/CMakeLists.txt index 22e511b515d..7ab3984906c 100644 --- a/tools/pythonpkg/src/CMakeLists.txt +++ b/tools/pythonpkg/src/CMakeLists.txt @@ -25,6 +25,8 @@ add_library( pyconnection.cpp pystatement.cpp python_import_cache.cpp + python_replacement_scan.cpp + python_dependency.cpp pyrelation.cpp pyexpression.cpp dataframe.cpp diff --git a/tools/pythonpkg/src/arrow/arrow_array_stream.cpp b/tools/pythonpkg/src/arrow/arrow_array_stream.cpp index 93b77b1e0e1..5760c91e133 100644 --- a/tools/pythonpkg/src/arrow/arrow_array_stream.cpp +++ b/tools/pythonpkg/src/arrow/arrow_array_stream.cpp @@ -31,6 +31,7 @@ void VerifyArrowDatasetLoaded() { } PyArrowObjectType GetArrowType(const py::handle &obj) { + D_ASSERT(py::gil_check()); auto &import_cache = *DuckDBPyConnection::ImportCache(); // First Verify Lib Types auto table_class = import_cache.pyarrow.Table(); @@ -240,8 +241,9 @@ py::object GetScalar(Value &constant, const string &timezone_config, const Arrow return dataset_scalar(scalar(constant.GetValue(), date_type("s"))); } case LogicalTypeId::TIMESTAMP_TZ: { + auto &datetime_info = type.GetTypeInfo(); auto base_value = constant.GetValue(); - auto arrow_datetime_type = type.GetDateTimeType(); + auto arrow_datetime_type = datetime_info.GetDateTimeType(); auto time_unit_string = ConvertTimestampUnit(arrow_datetime_type); auto converted_value = ConvertTimestampTZValue(base_value, arrow_datetime_type); py::object date_type = py::module_::import("pyarrow").attr("timestamp"); @@ -366,10 +368,12 @@ py::object TransformFilterRecursive(TableFilter *filter, vector &column_ auto &struct_filter = filter->Cast(); auto &child_type = StructType::GetChildType(type.GetDuckType(), struct_filter.child_idx); auto &child_name = struct_filter.child_name; + auto &struct_type_info = type.GetTypeInfo(); + auto &struct_child_type = struct_type_info.GetChild(struct_filter.child_idx); column_ref.push_back(child_name); auto child_expr = - TransformFilterRecursive(struct_filter.child_filter.get(), column_ref, timezone_config, child_type); + TransformFilterRecursive(struct_filter.child_filter.get(), column_ref, timezone_config, struct_child_type); column_ref.pop_back(); return child_expr; diff --git a/tools/pythonpkg/src/dataframe.cpp b/tools/pythonpkg/src/dataframe.cpp index ec010aab830..7c36053b14e 100644 --- a/tools/pythonpkg/src/dataframe.cpp +++ b/tools/pythonpkg/src/dataframe.cpp @@ -46,6 +46,18 @@ bool PandasDataFrame::IsPyArrowBacked(const py::handle &df) { return false; } +py::object PandasDataFrame::ToArrowTable(const py::object &df) { + D_ASSERT(py::gil_check()); + try { + return py::module_::import("pyarrow").attr("lib").attr("Table").attr("from_pandas")(df); + } catch (py::error_already_set &) { + // We don't fetch the original Python exception because it can cause a segfault + // The cause of this is not known yet, for now we just side-step the issue. + throw InvalidInputException( + "The dataframe could not be converted to a pyarrow.lib.Table, because a Python exception occurred."); + } +} + bool PolarsDataFrame::check_(const py::handle &object) { // NOLINT auto &import_cache = *DuckDBPyConnection::ImportCache(); return py::isinstance(object, import_cache.polars.DataFrame()); diff --git a/tools/pythonpkg/src/include/duckdb_python/expression/pyexpression.hpp b/tools/pythonpkg/src/include/duckdb_python/expression/pyexpression.hpp index 2ac7bc1f91b..8e35832ac8d 100644 --- a/tools/pythonpkg/src/include/duckdb_python/expression/pyexpression.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/expression/pyexpression.hpp @@ -99,6 +99,7 @@ struct DuckDBPyExpression : public enable_shared_from_this { static shared_ptr CaseExpression(const DuckDBPyExpression &condition, const DuckDBPyExpression &value); static shared_ptr FunctionExpression(const string &function_name, const py::args &args); + static shared_ptr Coalesce(const py::args &args); public: // Internal functions (not exposed to Python) diff --git a/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/collections_module.hpp b/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/collections_module.hpp new file mode 100644 index 00000000000..4298d359110 --- /dev/null +++ b/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/collections_module.hpp @@ -0,0 +1,46 @@ + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb_python/import_cache/modules/collections_module.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb_python/import_cache/python_import_cache_item.hpp" + +namespace duckdb { + +struct CollectionsAbcCacheItem : public PythonImportCacheItem { + +public: + static constexpr const char *Name = "collections.abc"; + +public: + CollectionsAbcCacheItem() + : PythonImportCacheItem("collections.abc"), Iterable("Iterable", this), Mapping("Mapping", this) { + } + ~CollectionsAbcCacheItem() override { + } + + PythonImportCacheItem Iterable; + PythonImportCacheItem Mapping; +}; + +struct CollectionsCacheItem : public PythonImportCacheItem { + +public: + static constexpr const char *Name = "collections"; + +public: + CollectionsCacheItem() : PythonImportCacheItem("collections"), abc() { + } + ~CollectionsCacheItem() override { + } + + CollectionsAbcCacheItem abc; +}; + +} // namespace duckdb diff --git a/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/numpy_module.hpp b/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/numpy_module.hpp index a4a75ecd84d..fbfaf52cc46 100644 --- a/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/numpy_module.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/numpy_module.hpp @@ -79,6 +79,11 @@ struct NumpyCacheItem : public PythonImportCacheItem { PythonImportCacheItem csingle; PythonImportCacheItem cdouble; PythonImportCacheItem clongdouble; + +protected: + bool IsRequired() const override final { + return false; + } }; } // namespace duckdb diff --git a/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/types_module.hpp b/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/types_module.hpp index 4d469806137..58f0be007c1 100644 --- a/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/types_module.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/import_cache/modules/types_module.hpp @@ -20,13 +20,15 @@ struct TypesCacheItem : public PythonImportCacheItem { public: TypesCacheItem() - : PythonImportCacheItem("types"), UnionType("UnionType", this), GenericAlias("GenericAlias", this) { + : PythonImportCacheItem("types"), UnionType("UnionType", this), GenericAlias("GenericAlias", this), + BuiltinFunctionType("BuiltinFunctionType", this) { } ~TypesCacheItem() override { } PythonImportCacheItem UnionType; PythonImportCacheItem GenericAlias; + PythonImportCacheItem BuiltinFunctionType; }; } // namespace duckdb diff --git a/tools/pythonpkg/src/include/duckdb_python/import_cache/python_import_cache.hpp b/tools/pythonpkg/src/include/duckdb_python/import_cache/python_import_cache.hpp index 30a20c66cfa..5acab4202fc 100644 --- a/tools/pythonpkg/src/include/duckdb_python/import_cache/python_import_cache.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/import_cache/python_import_cache.hpp @@ -37,6 +37,7 @@ struct PythonImportCache { TypesCacheItem types; TypingCacheItem typing; UuidCacheItem uuid; + CollectionsCacheItem collections; public: py::handle AddCache(py::object item); diff --git a/tools/pythonpkg/src/include/duckdb_python/import_cache/python_import_cache_modules.hpp b/tools/pythonpkg/src/include/duckdb_python/import_cache/python_import_cache_modules.hpp index 7af7d9b4da1..172c0513aec 100644 --- a/tools/pythonpkg/src/include/duckdb_python/import_cache/python_import_cache_modules.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/import_cache/python_import_cache_modules.hpp @@ -12,3 +12,4 @@ #include "duckdb_python/import_cache/modules/types_module.hpp" #include "duckdb_python/import_cache/modules/typing_module.hpp" #include "duckdb_python/import_cache/modules/uuid_module.hpp" +#include "duckdb_python/import_cache/modules/collections_module.hpp" diff --git a/tools/pythonpkg/src/include/duckdb_python/numpy/numpy_type.hpp b/tools/pythonpkg/src/include/duckdb_python/numpy/numpy_type.hpp index ab26b22b7a2..982f00ecf67 100644 --- a/tools/pythonpkg/src/include/duckdb_python/numpy/numpy_type.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/numpy/numpy_type.hpp @@ -42,6 +42,7 @@ enum class NumpyNullableType : uint8_t { //! Extension Types //! ------------------------------------------------------------ CATEGORY, //! category + STRING, //! string }; struct NumpyType { diff --git a/tools/pythonpkg/src/include/duckdb_python/pandas/pandas_analyzer.hpp b/tools/pythonpkg/src/include/duckdb_python/pandas/pandas_analyzer.hpp index 306bd18b394..70098c33bb0 100644 --- a/tools/pythonpkg/src/include/duckdb_python/pandas/pandas_analyzer.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/pandas/pandas_analyzer.hpp @@ -19,12 +19,13 @@ namespace duckdb { class PandasAnalyzer { public: - PandasAnalyzer(const DBConfig &config) { + explicit PandasAnalyzer(const ClientContext &context) { analyzed_type = LogicalType::SQLNULL; - auto maximum_entry = config.options.set_variables.find("pandas_analyze_sample"); - D_ASSERT(maximum_entry != config.options.set_variables.end()); - sample_size = maximum_entry->second.GetValue(); + Value result; + auto lookup_result = context.TryGetCurrentSetting("pandas_analyze_sample", result); + D_ASSERT((bool)lookup_result); + sample_size = result.GetValue(); } public: @@ -38,7 +39,7 @@ class PandasAnalyzer { } private: - LogicalType InnerAnalyze(py::object column, bool &can_convert, bool sample = true, idx_t increment = 1); + LogicalType InnerAnalyze(py::object column, bool &can_convert, idx_t increment); uint64_t GetSampleIncrement(idx_t rows); private: diff --git a/tools/pythonpkg/src/include/duckdb_python/pybind11/dataframe.hpp b/tools/pythonpkg/src/include/duckdb_python/pybind11/dataframe.hpp index df10d766a0e..51663a877ff 100644 --- a/tools/pythonpkg/src/include/duckdb_python/pybind11/dataframe.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/pybind11/dataframe.hpp @@ -22,6 +22,7 @@ class PandasDataFrame : public py::object { public: static bool check_(const py::handle &object); // NOLINT static bool IsPyArrowBacked(const py::handle &df); + static py::object ToArrowTable(const py::object &df); }; class PolarsDataFrame : public py::object { diff --git a/tools/pythonpkg/src/include/duckdb_python/pybind11/pybind_wrapper.hpp b/tools/pythonpkg/src/include/duckdb_python/pybind11/pybind_wrapper.hpp index 56200f0bb59..4ab31a90ef2 100644 --- a/tools/pythonpkg/src/include/duckdb_python/pybind11/pybind_wrapper.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/pybind11/pybind_wrapper.hpp @@ -29,6 +29,8 @@ struct type_caster> : list_caster { std::mutex py_connection_lock; //! MemoryFileSystem used to temporarily store file-like objects for reading shared_ptr internal_object_filesystem; - case_insensitive_map_t> registered_functions; + case_insensitive_map_t> registered_functions; public: explicit DuckDBPyConnection() { @@ -113,10 +114,11 @@ struct DuckDBPyConnection : public enable_shared_from_this { shared_ptr ExecuteMany(const py::object &query, py::object params = py::list()); - unique_ptr ExecuteInternal(vector> statements, py::object params = py::list(), - bool many = false); + void ExecuteImmediately(vector> statements); + unique_ptr PrepareQuery(unique_ptr statement); + unique_ptr ExecuteInternal(PreparedStatement &prep, py::object params = py::list()); - shared_ptr Execute(const py::object &query, py::object params = py::list(), bool many = false); + shared_ptr Execute(const py::object &query, py::object params = py::list()); shared_ptr ExecuteFromString(const string &query); shared_ptr Append(const string &name, const PandasDataFrame &value, bool by_name); @@ -127,8 +129,7 @@ struct DuckDBPyConnection : public enable_shared_from_this { void LoadExtension(const string &extension); - unique_ptr RunQuery(const py::object &query, string alias = "", - const py::object ¶ms = py::none()); + unique_ptr RunQuery(const py::object &query, string alias = "", py::object params = py::list()); unique_ptr Table(const string &tname); @@ -168,6 +169,8 @@ struct DuckDBPyConnection : public enable_shared_from_this { shared_ptr Rollback(); + shared_ptr Checkpoint(); + void Close(); void Interrupt(); diff --git a/tools/pythonpkg/src/include/duckdb_python/pyfilesystem.hpp b/tools/pythonpkg/src/include/duckdb_python/pyfilesystem.hpp index 09d00fbe838..053ef49a978 100644 --- a/tools/pythonpkg/src/include/duckdb_python/pyfilesystem.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/pyfilesystem.hpp @@ -49,7 +49,7 @@ class PythonFileHandle : public FileHandle { class PythonFilesystem : public FileSystem { private: const vector protocols; - const AbstractFileSystem filesystem; + AbstractFileSystem filesystem; std::string DecodeFlags(FileOpenFlags flags); bool Exists(const string &filename, const char *func_name) const; @@ -57,6 +57,7 @@ class PythonFilesystem : public FileSystem { explicit PythonFilesystem(vector protocols, AbstractFileSystem filesystem) : protocols(std::move(protocols)), filesystem(std::move(filesystem)) { } + ~PythonFilesystem() override; protected: string GetName() const override { diff --git a/tools/pythonpkg/src/include/duckdb_python/pyrelation.hpp b/tools/pythonpkg/src/include/duckdb_python/pyrelation.hpp index be155612fed..bc814b0218a 100644 --- a/tools/pythonpkg/src/include/duckdb_python/pyrelation.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/pyrelation.hpp @@ -25,33 +25,6 @@ namespace duckdb { -struct DuckDBPyConnection; - -class PythonDependencies : public ExternalDependency { -public: - explicit PythonDependencies() : ExternalDependency(ExternalDependenciesType::PYTHON_DEPENDENCY) { - } - ~PythonDependencies() override { - py::gil_scoped_acquire gil; - py_object_list.clear(); - } - - explicit PythonDependencies(py::function map_function) - : ExternalDependency(ExternalDependenciesType::PYTHON_DEPENDENCY), map_function(std::move(map_function)) {}; - explicit PythonDependencies(unique_ptr py_object) - : ExternalDependency(ExternalDependenciesType::PYTHON_DEPENDENCY) { - py_object_list.push_back(std::move(py_object)); - }; - explicit PythonDependencies(unique_ptr py_object_original, - unique_ptr py_object_copy) - : ExternalDependency(ExternalDependenciesType::PYTHON_DEPENDENCY) { - py_object_list.push_back(std::move(py_object_original)); - py_object_list.push_back(std::move(py_object_copy)); - }; - py::function map_function; - vector> py_object_list; -}; - struct DuckDBPyRelation { public: explicit DuckDBPyRelation(shared_ptr rel); @@ -76,8 +49,7 @@ struct DuckDBPyRelation { unique_ptr ProjectFromExpression(const string &expr); unique_ptr ProjectFromTypes(const py::object &types); - unique_ptr Project(const py::args &args, const py::kwargs &kwargs = py::kwargs()); - + unique_ptr Project(const py::args &args, const string &groups = ""); unique_ptr Filter(const py::object &expr); unique_ptr FilterFromExpression(const string &expr); unique_ptr Limit(int64_t n, int64_t offset = 0); @@ -214,7 +186,7 @@ struct DuckDBPyRelation { py::dict FetchNumpyInternal(bool stream = false, idx_t vectors_per_chunk = 1); - PandasDataFrame FetchDFChunk(idx_t vectors_per_chunk, bool date_as_object); + PandasDataFrame FetchDFChunk(const idx_t vectors_per_chunk = 1, bool date_as_object = false); duckdb::pyarrow::Table ToArrowTable(idx_t batch_size); @@ -274,6 +246,8 @@ struct DuckDBPyRelation { static bool IsRelation(const py::object &object); bool CanBeRegisteredBy(Connection &con); + bool CanBeRegisteredBy(ClientContext &context); + bool CanBeRegisteredBy(shared_ptr &context); Relation &GetRel(); diff --git a/tools/pythonpkg/src/include/duckdb_python/pyresult.hpp b/tools/pythonpkg/src/include/duckdb_python/pyresult.hpp index 79c578dba8f..81c446248c5 100644 --- a/tools/pythonpkg/src/include/duckdb_python/pyresult.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/pyresult.hpp @@ -37,7 +37,7 @@ struct DuckDBPyResult { duckdb::pyarrow::Table FetchArrowTable(idx_t rows_per_batch, bool to_polars); - PandasDataFrame FetchDFChunk(idx_t vectors_per_chunk, bool date_as_object); + PandasDataFrame FetchDFChunk(const idx_t vectors_per_chunk = 1, bool date_as_object = false); py::dict FetchPyTorch(); diff --git a/tools/pythonpkg/src/include/duckdb_python/python_dependency.hpp b/tools/pythonpkg/src/include/duckdb_python/python_dependency.hpp new file mode 100644 index 00000000000..3b4281d0846 --- /dev/null +++ b/tools/pythonpkg/src/include/duckdb_python/python_dependency.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "duckdb/common/string.hpp" +#include "duckdb/common/unique_ptr.hpp" +#include "duckdb/common/case_insensitive_map.hpp" +#include "duckdb/main/external_dependencies.hpp" +#include "duckdb_python/pybind11/pybind_wrapper.hpp" +#include "duckdb_python/pybind11/registered_py_object.hpp" + +namespace duckdb { + +class PythonDependencyItem : public DependencyItem { +public: + explicit PythonDependencyItem(unique_ptr &&object); + ~PythonDependencyItem() override; + +public: + static shared_ptr Create(py::object object); + static shared_ptr Create(unique_ptr &&object); + +public: + unique_ptr object; +}; + +} // namespace duckdb diff --git a/tools/pythonpkg/src/include/duckdb_python/python_replacement_scan.hpp b/tools/pythonpkg/src/include/duckdb_python/python_replacement_scan.hpp new file mode 100644 index 00000000000..6bdd089c697 --- /dev/null +++ b/tools/pythonpkg/src/include/duckdb_python/python_replacement_scan.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "duckdb/main/client_context_state.hpp" +#include "duckdb/common/case_insensitive_map.hpp" +#include "duckdb/parser/tableref.hpp" +#include "duckdb/function/replacement_scan.hpp" + +namespace duckdb { + +struct PythonReplacementScan { +public: + static unique_ptr Replace(ClientContext &context, ReplacementScanInput &input, + optional_ptr data); +}; + +} // namespace duckdb diff --git a/tools/pythonpkg/src/numpy/numpy_bind.cpp b/tools/pythonpkg/src/numpy/numpy_bind.cpp index 05ea0dbf8a5..0ffef850312 100644 --- a/tools/pythonpkg/src/numpy/numpy_bind.cpp +++ b/tools/pythonpkg/src/numpy/numpy_bind.cpp @@ -10,7 +10,6 @@ namespace duckdb { void NumpyBind::Bind(const ClientContext &context, py::handle df, vector &bind_columns, vector &return_types, vector &names) { - auto &config = DBConfig::GetConfig(context); auto df_columns = py::list(df.attr("keys")()); auto df_types = py::list(); for (auto item : py::cast(df)) { @@ -37,8 +36,7 @@ void NumpyBind::Bind(const ClientContext &context, py::handle df, vector(py::array(column.attr("astype")("float32"))); bind_data.numpy_type.type = NumpyNullableType::FLOAT_32; duckdb_col_type = NumpyToLogicalType(bind_data.numpy_type); - } else if (bind_data.numpy_type.type == NumpyNullableType::OBJECT && - string(py::str(df_types[col_idx])) == "string") { + } else if (bind_data.numpy_type.type == NumpyNullableType::STRING) { bind_data.numpy_type.type = NumpyNullableType::CATEGORY; // here we call numpy.unique // this function call will return the unique values of a given array @@ -61,7 +59,7 @@ void NumpyBind::Bind(const ClientContext &context, py::handle df, vectorBackend() == PandasColumnBackend::NUMPY); auto &numpy_col = reinterpret_cast(*bind_data.pandas_col); auto &array = numpy_col.array; + auto stride = numpy_col.stride; switch (bind_data.numpy_type.type) { case NumpyNullableType::BOOL: @@ -276,12 +277,13 @@ void NumpyScan::Scan(PandasColumnBindData &bind_data, idx_t count, idx_t offset, }; for (idx_t row = 0; row < count; row++) { - auto source_idx = offset + row; + auto source_idx = stride / sizeof(int64_t) * (row + offset); if (src_ptr[source_idx] <= NumericLimits::Minimum()) { // pandas Not a Time (NaT) mask.SetInvalid(row); continue; } + // Direct conversion, we've already matched the numpy type with the equivalent duckdb type auto input = timestamp_t(src_ptr[source_idx]); if (Timestamp::IsFinite(input)) { @@ -298,7 +300,7 @@ void NumpyScan::Scan(PandasColumnBindData &bind_data, idx_t count, idx_t offset, auto &mask = FlatVector::Validity(out); for (idx_t row = 0; row < count; row++) { - auto source_idx = offset + row; + auto source_idx = stride / sizeof(int64_t) * (row + offset); if (src_ptr[source_idx] <= NumericLimits::Minimum()) { // pandas Not a Time (NaT) mask.SetInvalid(row); @@ -317,11 +319,13 @@ void NumpyScan::Scan(PandasColumnBindData &bind_data, idx_t count, idx_t offset, } break; } + case NumpyNullableType::STRING: case NumpyNullableType::OBJECT: { - //! We have determined the underlying logical type of this object column // Get the source pointer of the numpy array auto src_ptr = (PyObject **)array.data(); // NOLINT - if (out.GetType().id() != LogicalTypeId::VARCHAR) { + const bool is_object_col = bind_data.numpy_type.type == NumpyNullableType::OBJECT; + if (is_object_col && out.GetType().id() != LogicalTypeId::VARCHAR) { + //! We have determined the underlying logical type of this object column return NumpyScan::ScanObjectColumn(src_ptr, numpy_col.stride, count, offset, out); } @@ -338,7 +342,7 @@ void NumpyScan::Scan(PandasColumnBindData &bind_data, idx_t count, idx_t offset, // Get the pointer to the object PyObject *val = src_ptr[source_idx]; - if (bind_data.numpy_type.type == NumpyNullableType::OBJECT && !py::isinstance(val)) { + if (!py::isinstance(val)) { if (val == Py_None) { out_mask.SetInvalid(row); continue; diff --git a/tools/pythonpkg/src/numpy/type.cpp b/tools/pythonpkg/src/numpy/type.cpp index 00d86cab4df..92ac478574c 100644 --- a/tools/pythonpkg/src/numpy/type.cpp +++ b/tools/pythonpkg/src/numpy/type.cpp @@ -55,8 +55,10 @@ static NumpyNullableType ConvertNumpyTypeInternal(const string &col_type_str) { if (col_type_str == "float64" || col_type_str == "Float64") { return NumpyNullableType::FLOAT_64; } - if (col_type_str == "object" || col_type_str == "string") { - //! this better be castable to strings + if (col_type_str == "string") { + return NumpyNullableType::STRING; + } + if (col_type_str == "object") { return NumpyNullableType::OBJECT; } if (col_type_str == "timedelta64[ns]") { @@ -134,6 +136,8 @@ LogicalType NumpyToLogicalType(const NumpyType &col_type) { return LogicalType::FLOAT; case NumpyNullableType::FLOAT_64: return LogicalType::DOUBLE; + case NumpyNullableType::STRING: + return LogicalType::VARCHAR; case NumpyNullableType::OBJECT: return LogicalType::VARCHAR; case NumpyNullableType::TIMEDELTA: diff --git a/tools/pythonpkg/src/pandas/analyzer.cpp b/tools/pythonpkg/src/pandas/analyzer.cpp index 660d1fb2b3d..8c16e99becb 100644 --- a/tools/pythonpkg/src/pandas/analyzer.cpp +++ b/tools/pythonpkg/src/pandas/analyzer.cpp @@ -148,20 +148,7 @@ static bool UpgradeType(LogicalType &left, const LogicalType &right) { return true; } case LogicalTypeId::ARRAY: { - if (right.id() != left.id()) { - // Not both sides are ARRAY, not compatible - // FIXME: maybe compatible with LIST type?? - return false; - } - LogicalType child_type = LogicalType::SQLNULL; - if (!UpgradeType(child_type, ArrayType::GetChildType(left))) { - return false; - } - if (!UpgradeType(child_type, ArrayType::GetChildType(right))) { - return false; - } - left = LogicalType::ARRAY(child_type); - return true; + throw InternalException("ARRAY types are not being detected yet, this should never happen"); } case LogicalTypeId::STRUCT: { if (right.id() == LogicalTypeId::STRUCT) { @@ -205,7 +192,7 @@ static bool UpgradeType(LogicalType &left, const LogicalType &right) { return true; } case LogicalTypeId::UNION: { - throw NotImplementedException("Converting to UNION type is not supported yet"); + throw InternalException("UNION types are not being detected yet, this should never happen"); } case LogicalTypeId::MAP: { if (right.id() == LogicalTypeId::MAP) { @@ -246,7 +233,6 @@ static bool UpgradeType(LogicalType &left, const LogicalType &right) { return true; } } - return true; } LogicalType PandasAnalyzer::GetListType(py::object &ele, bool &can_convert) { @@ -446,7 +432,7 @@ LogicalType PandasAnalyzer::GetItemType(py::object ele, bool &can_convert) { LogicalType ltype; ltype = NumpyToLogicalType(extended_type); if (extended_type.type == NumpyNullableType::OBJECT) { - LogicalType converted_type = InnerAnalyze(ele, can_convert, false, 1); + LogicalType converted_type = InnerAnalyze(ele, can_convert, 1); if (can_convert) { ltype = converted_type; } @@ -464,26 +450,18 @@ LogicalType PandasAnalyzer::GetItemType(py::object ele, bool &can_convert) { //! Get the increment for the given sample size uint64_t PandasAnalyzer::GetSampleIncrement(idx_t rows) { - D_ASSERT(sample_size != 0); //! Apply the maximum auto sample = sample_size; if (sample > rows) { sample = rows; } - return rows / sample; -} - -static py::object FindFirstNonNull(const py::handle &row, idx_t offset, idx_t range) { - for (idx_t i = 0; i < range; i++) { - auto obj = row(offset + i); - if (!obj.is_none()) { - return obj; - } + if (sample == 0) { + return rows; } - return py::none(); + return rows / sample; } -LogicalType PandasAnalyzer::InnerAnalyze(py::object column, bool &can_convert, bool sample, idx_t increment) { +LogicalType PandasAnalyzer::InnerAnalyze(py::object column, bool &can_convert, idx_t increment) { idx_t rows = py::len(column); if (rows == 0) { @@ -500,14 +478,10 @@ LogicalType PandasAnalyzer::InnerAnalyze(py::object column, bool &can_convert, b } auto row = column.attr("__getitem__"); - if (sample) { - increment = GetSampleIncrement(rows); - } LogicalType item_type = LogicalType::SQLNULL; vector types; for (idx_t i = 0; i < rows; i += increment) { - auto range = MinValue(increment, rows - i); - auto obj = FindFirstNonNull(row, i, range); + auto obj = row(i); auto next_item_type = GetItemType(obj, can_convert); types.push_back(next_item_type); @@ -530,7 +504,20 @@ bool PandasAnalyzer::Analyze(py::object column) { return false; } bool can_convert = true; - LogicalType type = InnerAnalyze(std::move(column), can_convert); + idx_t increment = GetSampleIncrement(py::len(column)); + LogicalType type = InnerAnalyze(column, can_convert, increment); + + if (type == LogicalType::SQLNULL && increment > 1) { + // We did not see the whole dataset, hence we are not sure if nulls are really nulls + // as a fallback we try to identify this specific type + auto first_valid_index = column.attr("first_valid_index")(); + if (GetPythonObjectType(first_valid_index) != PythonObjectType::None) { + // This means we do have a value that is not null, figure out its type + auto row = column.attr("__getitem__"); + auto obj = row(first_valid_index); + type = GetItemType(obj, can_convert); + } + } if (can_convert) { analyzed_type = type; } diff --git a/tools/pythonpkg/src/pandas/bind.cpp b/tools/pythonpkg/src/pandas/bind.cpp index 4e78e8acf31..8f6919cb5fe 100644 --- a/tools/pythonpkg/src/pandas/bind.cpp +++ b/tools/pythonpkg/src/pandas/bind.cpp @@ -48,7 +48,6 @@ static LogicalType BindColumn(PandasBindColumn &column_p, PandasColumnBindData & LogicalType column_type; auto &column = column_p.handle; - auto &config = DBConfig::GetConfig(context); bind_data.numpy_type = ConvertNumpyType(column_p.type); bool column_has_mask = py::hasattr(column.attr("array"), "_mask"); @@ -107,7 +106,7 @@ static LogicalType BindColumn(PandasBindColumn &column_p, PandasColumnBindData & } // Analyze the inner data type of the 'object' column if (bind_data.numpy_type.type == NumpyNullableType::OBJECT) { - PandasAnalyzer analyzer(config); + PandasAnalyzer analyzer(context); if (analyzer.Analyze(column)) { column_type = analyzer.AnalyzedType(); } diff --git a/tools/pythonpkg/src/pandas/scan.cpp b/tools/pythonpkg/src/pandas/scan.cpp index 1077b05aaf7..10424faab7e 100644 --- a/tools/pythonpkg/src/pandas/scan.cpp +++ b/tools/pythonpkg/src/pandas/scan.cpp @@ -7,22 +7,24 @@ #include "duckdb_python/numpy/numpy_bind.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb_python/pandas/column/pandas_numpy_column.hpp" +#include "duckdb/parser/tableref/table_function_ref.hpp" #include "duckdb/common/atomic.hpp" namespace duckdb { -struct PandasScanFunctionData : public PyTableFunctionData { +struct PandasScanFunctionData : public TableFunctionData { PandasScanFunctionData(py::handle df, idx_t row_count, vector pandas_bind_data, - vector sql_types) + vector sql_types, shared_ptr dependency) : df(df), row_count(row_count), lines_read(0), pandas_bind_data(std::move(pandas_bind_data)), - sql_types(std::move(sql_types)) { + sql_types(std::move(sql_types)), copied_df(std::move(dependency)) { } py::handle df; idx_t row_count; atomic lines_read; vector pandas_bind_data; vector sql_types; + shared_ptr copied_df; ~PandasScanFunctionData() override { try { @@ -89,9 +91,21 @@ unique_ptr PandasScanFunction::PandasScanBind(ClientContext &conte } auto df_columns = py::list(df.attr("keys")()); + auto &ref = input.ref; + + shared_ptr dependency_item; + if (ref.external_dependency) { + // This was created during the replacement scan if this was a pandas DataFrame (see python_replacement_scan.cpp) + dependency_item = ref.external_dependency->GetDependency("copy"); + if (!dependency_item) { + // This was created during the replacement if this was a numpy scan + dependency_item = ref.external_dependency->GetDependency("data"); + } + } + auto get_fun = df.attr("__getitem__"); idx_t row_count = py::len(get_fun(df_columns[0])); - return make_uniq(df, row_count, std::move(pandas_bind_data), return_types); + return make_uniq(df, row_count, std::move(pandas_bind_data), return_types, dependency_item); } unique_ptr PandasScanFunction::PandasScanInitGlobal(ClientContext &context, diff --git a/tools/pythonpkg/src/path_like.cpp b/tools/pythonpkg/src/path_like.cpp index aa003a8fa8f..a69bcd42c78 100644 --- a/tools/pythonpkg/src/path_like.cpp +++ b/tools/pythonpkg/src/path_like.cpp @@ -71,7 +71,10 @@ PathLike PathLikeProcessor::Finalize() { // Create the dependency, which contains the logic to clean up the files in its destructor auto &fs = GetFS(); - result.dependency = make_uniq(make_uniq(fs, std::move(fs_files))); + auto dependency = make_uniq(); + auto dependency_item = PythonDependencyItem::Create(make_uniq(fs, std::move(fs_files))); + dependency->AddDependency("file_handles", std::move(dependency_item)); + result.dependency = std::move(dependency); return result; } diff --git a/tools/pythonpkg/src/pybind11/pybind_wrapper.cpp b/tools/pythonpkg/src/pybind11/pybind_wrapper.cpp index 5bbc0542889..23bf80354a1 100644 --- a/tools/pythonpkg/src/pybind11/pybind_wrapper.cpp +++ b/tools/pythonpkg/src/pybind11/pybind_wrapper.cpp @@ -1,5 +1,6 @@ #include "duckdb_python/pybind11/pybind_wrapper.hpp" #include "duckdb/common/exception.hpp" +#include "duckdb_python/pyconnection/pyconnection.hpp" namespace pybind11 { @@ -15,4 +16,24 @@ void gil_assert() { } } +// NOLINTNEXTLINE(readability-identifier-naming) +bool is_list_like(handle obj) { + if (isinstance(obj) || isinstance(obj)) { + return false; + } + if (is_dict_like(obj)) { + return false; + } + auto &import_cache = *duckdb::DuckDBPyConnection::ImportCache(); + auto iterable = import_cache.collections.abc.Iterable(); + return isinstance(obj, iterable); +} + +// NOLINTNEXTLINE(readability-identifier-naming) +bool is_dict_like(handle obj) { + auto &import_cache = *duckdb::DuckDBPyConnection::ImportCache(); + auto mapping = import_cache.collections.abc.Mapping(); + return isinstance(obj, mapping); +} + } // namespace pybind11 diff --git a/tools/pythonpkg/src/pyconnection.cpp b/tools/pythonpkg/src/pyconnection.cpp index eefe2c252a5..5702983377b 100644 --- a/tools/pythonpkg/src/pyconnection.cpp +++ b/tools/pythonpkg/src/pyconnection.cpp @@ -50,7 +50,12 @@ #include "duckdb/catalog/catalog_entry/scalar_function_catalog_entry.hpp" #include "duckdb/main/pending_query_result.hpp" #include "duckdb/parser/keyword_helper.hpp" +#include "duckdb_python/python_replacement_scan.hpp" #include "duckdb/common/shared_ptr.hpp" +#include "duckdb/main/materialized_query_result.hpp" +#include "duckdb/main/stream_query_result.hpp" +#include "duckdb/main/relation/materialized_relation.hpp" +#include "duckdb/main/relation/query_relation.hpp" #include @@ -112,17 +117,6 @@ bool DuckDBPyConnection::IsJupyter() { return DuckDBPyConnection::environment == PythonEnvironmentType::JUPYTER; } -py::object ArrowTableFromDataframe(const py::object &df) { - try { - return py::module_::import("pyarrow").attr("lib").attr("Table").attr("from_pandas")(df); - } catch (py::error_already_set &) { - // We don't fetch the original Python exception because it can cause a segfault - // The cause of this is not known yet, for now we just side-step the issue. - throw InvalidInputException( - "The dataframe could not be converted to a pyarrow.lib.Table, because a Python exception occurred."); - } -} - // NOTE: this function is generated by tools/pythonpkg/scripts/generate_connection_methods.py. // Do not edit this function manually, your changes will be overwritten! @@ -171,7 +165,7 @@ static void InitializeConnectionMethods(py::class_(udf); + auto dependency = make_uniq(); + dependency->AddDependency("function", PythonDependencyItem::Create(udf)); + registered_functions[name] = std::move(dependency); return shared_from_this(); } @@ -413,6 +411,7 @@ void DuckDBPyConnection::Initialize(py::handle &m) { connection_module.def("__enter__", &DuckDBPyConnection::Enter) .def("__exit__", &DuckDBPyConnection::Exit, py::arg("exc_type"), py::arg("exc"), py::arg("traceback")); + connection_module.def("__del__", &DuckDBPyConnection::Close); InitializeConnectionMethods(connection_module); connection_module.def_property_readonly("description", &DuckDBPyConnection::GetDescription, @@ -422,11 +421,46 @@ void DuckDBPyConnection::Initialize(py::handle &m) { DuckDBPyConnection::ImportCache(); } -shared_ptr DuckDBPyConnection::ExecuteMany(const py::object &query, py::object params) { - if (params.is_none()) { - params = py::list(); +shared_ptr DuckDBPyConnection::ExecuteMany(const py::object &query, py::object params_p) { + result.reset(); + if (params_p.is_none()) { + params_p = py::list(); + } + + auto statements = GetStatements(query); + if (statements.empty()) { + // TODO: should we throw? + return nullptr; + } + + auto last_statement = std::move(statements.back()); + statements.pop_back(); + // First immediately execute any preceding statements (if any) + // FIXME: DBAPI says to not accept an 'executemany' call with multiple statements + ExecuteImmediately(std::move(statements)); + + auto prep = PrepareQuery(std::move(last_statement)); + + if (!py::is_list_like(params_p)) { + throw InvalidInputException("executemany requires a list of parameter sets to be provided"); + } + auto outer_list = py::list(params_p); + if (outer_list.empty()) { + throw InvalidInputException("executemany requires a non-empty list of parameter sets to be provided"); } - Execute(query, std::move(params), true); + + unique_ptr query_result; + // Execute once for every set of parameters that are provided + for (auto ¶meters : outer_list) { + auto params = py::reinterpret_borrow(parameters); + query_result = ExecuteInternal(*prep, std::move(params)); + } + // Set the internal 'result' object + if (query_result) { + auto py_result = make_uniq(std::move(query_result)); + result = make_uniq(std::move(py_result)); + } + return shared_from_this(); } @@ -440,15 +474,17 @@ static std::function FinishedCondition(PendingQuer unique_ptr DuckDBPyConnection::CompletePendingQuery(PendingQueryResult &pending_query) { PendingExecutionResult execution_result; auto is_finished = FinishedCondition(pending_query); - do { - execution_result = pending_query.ExecuteTask(); + while (!is_finished(execution_result = pending_query.ExecuteTask())) { { py::gil_scoped_acquire gil; if (PyErr_CheckSignals() != 0) { throw std::runtime_error("Query interrupted"); } } - } while (!is_finished(execution_result)); + if (execution_result == PendingExecutionResult::BLOCKED) { + pending_query.WaitForTask(); + } + } if (execution_result == PendingExecutionResult::EXECUTION_ERROR) { pending_query.ThrowError(); } @@ -488,99 +524,65 @@ py::list TransformNamedParameters(const case_insensitive_map_t &named_par return new_params; } -unique_ptr DuckDBPyConnection::ExecuteInternal(vector> statements, - py::object params, bool many) { - if (!connection) { - throw ConnectionException("Connection has already been closed"); - } - if (params.is_none()) { - params = py::list(); +case_insensitive_map_t TransformPreparedParameters(PreparedStatement &prep, const py::object ¶ms) { + case_insensitive_map_t named_values; + if (py::is_list_like(params)) { + if (prep.n_param != py::len(params)) { + throw InvalidInputException("Prepared statement needs %d parameters, %d given", prep.n_param, + py::len(params)); + } + auto unnamed_values = DuckDBPyConnection::TransformPythonParamList(params); + for (idx_t i = 0; i < unnamed_values.size(); i++) { + auto &value = unnamed_values[i]; + auto identifier = std::to_string(i + 1); + named_values[identifier] = std::move(value); + } + } else if (py::is_dict_like(params)) { + auto dict = py::cast(params); + named_values = DuckDBPyConnection::TransformPythonParamDict(dict); + } else { + throw InvalidInputException("Prepared parameters can only be passed as a list or a dictionary"); } - result = nullptr; + return named_values; +} + +unique_ptr DuckDBPyConnection::PrepareQuery(unique_ptr statement) { unique_ptr prep; { py::gil_scoped_release release; - unique_lock lock(py_connection_lock); - - if (statements.empty()) { - // no statements to execute - return nullptr; - } - // if there are multiple statements, we directly execute the statements besides the last one - // we only return the result of the last statement to the user, unless one of the previous statements fails - for (idx_t i = 0; i + 1 < statements.size(); i++) { - if (statements[i]->n_param != 0) { - throw NotImplementedException( - "Prepared parameters are only supported for the last statement, please split your query up into " - "separate 'execute' calls if you want to use prepared parameters"); - } - auto pending_query = connection->PendingQuery(std::move(statements[i]), false); - auto res = CompletePendingQuery(*pending_query); - - if (res->HasError()) { - res->ThrowError(); - } - } + unique_lock lock(py_connection_lock); - prep = connection->Prepare(std::move(statements.back())); + prep = connection->Prepare(std::move(statement)); if (prep->HasError()) { prep->error.Throw(); } } + return prep; +} - // this is a list of a list of parameters in executemany - py::list params_set; - if (!many) { - params_set = py::list(1); - params_set[0] = params; - } else { - if (!py::isinstance(params)) { - throw InvalidInputException("executemany requires a list of parameter sets to be provided"); - } - auto outer_list = py::list(params); - if (outer_list.empty()) { - throw InvalidInputException("executemany requires a non-empty list of parameter sets to be provided"); - } - params_set = params; +unique_ptr DuckDBPyConnection::ExecuteInternal(PreparedStatement &prep, py::object params) { + if (!connection) { + throw ConnectionException("Connection has already been closed"); + } + if (params.is_none()) { + params = py::list(); } - // For every entry of the argument list, execute the prepared statement with said arguments - for (pybind11::handle single_query_params : params_set) { - case_insensitive_map_t named_values; - if (py::isinstance(single_query_params) || py::isinstance(single_query_params)) { - if (prep->n_param != py::len(single_query_params)) { - throw InvalidInputException("Prepared statement needs %d parameters, %d given", prep->n_param, - py::len(single_query_params)); - } - auto unnamed_values = DuckDBPyConnection::TransformPythonParamList(single_query_params); - for (idx_t i = 0; i < unnamed_values.size(); i++) { - auto &value = unnamed_values[i]; - auto identifier = std::to_string(i + 1); - named_values[identifier] = std::move(value); - } - } else if (py::isinstance(single_query_params)) { - auto dict = py::cast(single_query_params); - named_values = DuckDBPyConnection::TransformPythonParamDict(dict); - } else { - throw InvalidInputException("Prepared parameters can only be passed as a list or a dictionary"); - } - unique_ptr res; - { - py::gil_scoped_release release; - unique_lock lock(py_connection_lock); - auto pending_query = prep->PendingQuery(named_values); - res = CompletePendingQuery(*pending_query); + // Execute the prepared statement with the prepared parameters + auto named_values = TransformPreparedParameters(prep, params); + unique_ptr res; + { + py::gil_scoped_release release; + unique_lock lock(py_connection_lock); - if (res->HasError()) { - res->ThrowError(); - } - } + auto pending_query = prep.PendingQuery(named_values); + res = CompletePendingQuery(*pending_query); - if (!many) { - return res; + if (res->HasError()) { + res->ThrowError(); } } - return nullptr; + return res; } vector> DuckDBPyConnection::GetStatements(const py::object &query) { @@ -605,10 +607,25 @@ shared_ptr DuckDBPyConnection::ExecuteFromString(const strin return Execute(py::str(query)); } -shared_ptr DuckDBPyConnection::Execute(const py::object &query, py::object params, bool many) { +shared_ptr DuckDBPyConnection::Execute(const py::object &query, py::object params) { + result.reset(); + auto statements = GetStatements(query); + if (statements.empty()) { + // TODO: should we throw? + return nullptr; + } + + auto last_statement = std::move(statements.back()); + statements.pop_back(); + // First immediately execute any preceding statements (if any) + // FIXME: SQLites implementation says to not accept an 'execute' call with multiple statements + ExecuteImmediately(std::move(statements)); - auto res = ExecuteInternal(std::move(statements), std::move(params), many); + auto prep = PrepareQuery(std::move(last_statement)); + auto res = ExecuteInternal(*prep, std::move(params)); + + // Set the internal 'result' object if (res) { auto py_result = make_uniq(std::move(res)); result = make_uniq(std::move(py_result)); @@ -656,8 +673,11 @@ void DuckDBPyConnection::RegisterArrowObject(const py::object &arrow_object, con ->CreateView(name, true, true); } vector> dependencies; - dependencies.push_back( - make_shared_ptr(make_uniq(std::move(stream_factory), arrow_object))); + auto dependency = make_shared_ptr(); + auto dependency_item = + PythonDependencyItem::Create(make_uniq(std::move(stream_factory), arrow_object)); + dependency->AddDependency("object", std::move(dependency_item)); + dependencies.push_back(std::move(dependency)); connection->context->external_dependencies[name] = std::move(dependencies); } @@ -669,7 +689,7 @@ shared_ptr DuckDBPyConnection::RegisterPythonObject(const st if (DuckDBPyConnection::IsPandasDataframe(python_object)) { if (PandasDataFrame::IsPyArrowBacked(python_object)) { - auto arrow_table = ArrowTableFromDataframe(python_object); + auto arrow_table = PandasDataFrame::ToArrowTable(python_object); RegisterArrowObject(arrow_table, name); } else { auto new_df = PandasScanFunction::PandasReplaceCopiedNames(python_object); @@ -680,10 +700,12 @@ shared_ptr DuckDBPyConnection::RegisterPythonObject(const st ->CreateView(name, true, true); } - // keep a reference + auto dependency = make_shared_ptr(); + dependency->AddDependency("original", PythonDependencyItem::Create(python_object)); + dependency->AddDependency("copy", PythonDependencyItem::Create(std::move(new_df))); + vector> dependencies; - dependencies.push_back(make_shared_ptr(make_uniq(python_object), - make_uniq(new_df))); + dependencies.push_back(std::move(dependency)); connection->context->external_dependencies[name] = std::move(dependencies); } } else if (IsAcceptedArrowObject(python_object) || IsPolarsDataframe(python_object)) { @@ -727,7 +749,7 @@ unique_ptr DuckDBPyConnection::ReadJSON(const string &name, co named_parameter_map_t options; if (!py::none().is(columns)) { - if (!py::isinstance(columns)) { + if (!py::is_dict_like(columns)) { throw BinderException("read_json only accepts 'columns' as a dict[str, str]"); } py::dict columns_dict = columns; @@ -849,7 +871,7 @@ unique_ptr DuckDBPyConnection::ReadCSV( } if (!py::none().is(dtype)) { - if (py::isinstance(dtype)) { + if (py::is_dict_like(dtype)) { child_list_t struct_fields; py::dict dtype_dict = dtype; for (auto &kv : dtype_dict) { @@ -861,7 +883,7 @@ unique_ptr DuckDBPyConnection::ReadCSV( } auto dtype_struct = Value::STRUCT(std::move(struct_fields)); bind_parameters["dtypes"] = std::move(dtype_struct); - } else if (py::isinstance(dtype)) { + } else if (py::is_list_like(dtype)) { vector list_values; py::list dtype_list = dtype; for (auto &child : dtype_list) { @@ -889,7 +911,7 @@ unique_ptr DuckDBPyConnection::ReadCSV( } if (!py::none().is(names_p)) { - if (!py::isinstance(names_p)) { + if (!py::is_list_like(names_p)) { throw InvalidInputException("read_csv only accepts 'names' as a list of strings"); } vector names; @@ -905,7 +927,7 @@ unique_ptr DuckDBPyConnection::ReadCSV( if (!py::none().is(na_values)) { vector null_values; - if (!py::isinstance(na_values) && !py::isinstance(na_values)) { + if (!py::isinstance(na_values) && !py::is_list_like(na_values)) { throw InvalidInputException("read_csv only accepts 'na_values' as a string or a list of strings"); } else if (py::isinstance(na_values)) { null_values.push_back(Value(py::str(na_values))); @@ -1013,15 +1035,32 @@ unique_ptr DuckDBPyConnection::ReadCSV( auto read_csv_p = connection->ReadCSV(name, std::move(bind_parameters)); auto &read_csv = read_csv_p->Cast(); if (file_like_object_wrapper) { - D_ASSERT(!read_csv.extra_dependencies); - read_csv.extra_dependencies = std::move(file_like_object_wrapper); + read_csv.AddExternalDependency(std::move(file_like_object_wrapper)); } return make_uniq(read_csv_p->Alias(read_csv.alias)); } -unique_ptr DuckDBPyConnection::RunQuery(const py::object &query, string alias, - const py::object ¶ms) { +void DuckDBPyConnection::ExecuteImmediately(vector> statements) { + if (statements.empty()) { + return; + } + for (auto &stmt : statements) { + if (stmt->n_param != 0) { + throw NotImplementedException( + "Prepared parameters are only supported for the last statement, please split your query up into " + "separate 'execute' calls if you want to use prepared parameters"); + } + auto pending_query = connection->PendingQuery(std::move(stmt), false); + auto res = CompletePendingQuery(*pending_query); + + if (res->HasError()) { + res->ThrowError(); + } + } +} + +unique_ptr DuckDBPyConnection::RunQuery(const py::object &query, string alias, py::object params) { if (!connection) { throw ConnectionException("Connection has already been closed"); } @@ -1030,45 +1069,51 @@ unique_ptr DuckDBPyConnection::RunQuery(const py::object &quer } auto statements = GetStatements(query); - if (statements.size() == 1 && statements[0]->type == StatementType::SELECT_STATEMENT && py::none().is(params)) { - return make_uniq(connection->RelationFromQuery( - unique_ptr_cast(std::move(statements[0])), alias)); - } - - auto res = ExecuteInternal(std::move(statements), params); - if (!res) { + if (statements.empty()) { + // TODO: should we throw? return nullptr; } - if (res->properties.return_type != StatementReturnType::QUERY_RESULT) { - return nullptr; + + auto last_statement = std::move(statements.back()); + statements.pop_back(); + // First immediately execute any preceding statements (if any) + ExecuteImmediately(std::move(statements)); + + // Attempt to create a Relation for lazy execution if possible + shared_ptr relation; + if (py::none().is(params)) { + // FIXME: currently we can't create relations with prepared parameters + auto statement_type = last_statement->type; + switch (statement_type) { + case StatementType::SELECT_STATEMENT: { + auto select_statement = unique_ptr_cast(std::move(last_statement)); + relation = connection->RelationFromQuery(std::move(select_statement), alias); + break; + } + default: + break; + } } - // FIXME: we should add support for a relation object over a column data collection to make this more efficient - vector> values; - vector names = res->names; - { - py::gil_scoped_release release; - while (true) { - auto chunk = res->Fetch(); - if (res->HasError()) { - res->ThrowError(); - } - if (!chunk || chunk->size() == 0) { - break; - } - for (idx_t r = 0; r < chunk->size(); r++) { - vector row; - for (idx_t c = 0; c < chunk->ColumnCount(); c++) { - row.push_back(chunk->data[c].GetValue(r)); - } - values.push_back(std::move(row)); - } + if (!relation) { + // Could not create a relation, resort to direct execution + auto prep = PrepareQuery(std::move(last_statement)); + auto res = ExecuteInternal(*prep, std::move(params)); + if (!res) { + return nullptr; } - if (values.empty()) { - return DuckDBPyRelation::EmptyResult(connection->context, res->types, res->names); + if (res->properties.return_type != StatementReturnType::QUERY_RESULT) { + return nullptr; + } + if (res->type == QueryResultType::STREAM_RESULT) { + auto &stream_result = res->Cast(); + res = stream_result.Materialize(); } + auto &materialized_result = res->Cast(); + relation = make_shared_ptr(connection->context, materialized_result.TakeCollection(), + res->names, alias); } - return make_uniq(make_uniq(connection->context, values, names, alias)); + return make_uniq(std::move(relation)); } unique_ptr DuckDBPyConnection::Table(const string &tname) { @@ -1118,6 +1163,9 @@ unique_ptr DuckDBPyConnection::TableFunction(const string &fna if (params.is_none()) { params = py::list(); } + if (!py::is_list_like(params)) { + throw InvalidInputException("'params' has to be a list of parameters"); + } if (!connection) { throw ConnectionException("Connection has already been closed"); } @@ -1132,15 +1180,17 @@ unique_ptr DuckDBPyConnection::FromDF(const PandasDataFrame &v } string name = "df_" + StringUtil::GenerateRandomName(); if (PandasDataFrame::IsPyArrowBacked(value)) { - auto table = ArrowTableFromDataframe(value); + auto table = PandasDataFrame::ToArrowTable(value); return DuckDBPyConnection::FromArrow(table); } auto new_df = PandasScanFunction::PandasReplaceCopiedNames(value); vector params; params.emplace_back(Value::POINTER(CastPointerToValue(new_df.ptr()))); auto rel = connection->TableFunction("pandas_scan", params)->Alias(name); - rel->extra_dependencies = - make_uniq(make_uniq(value), make_uniq(new_df)); + auto dependency = make_shared_ptr(); + dependency->AddDependency("original", PythonDependencyItem::Create(value)); + dependency->AddDependency("copy", PythonDependencyItem::Create(new_df)); + rel->AddExternalDependency(std::move(dependency)); return make_uniq(std::move(rel)); } @@ -1222,8 +1272,11 @@ unique_ptr DuckDBPyConnection::FromArrow(py::object &arrow_obj Value::POINTER(CastPointerToValue(stream_factory_produce)), Value::POINTER(CastPointerToValue(stream_factory_get_schema))}) ->Alias(name); - rel->extra_dependencies = - make_uniq(make_uniq(std::move(stream_factory), arrow_object)); + auto dependency = make_shared_ptr(); + auto dependency_item = + PythonDependencyItem::Create(make_uniq(std::move(stream_factory), arrow_object)); + dependency->AddDependency("object", std::move(dependency_item)); + rel->AddExternalDependency(std::move(dependency)); return make_uniq(std::move(rel)); } @@ -1304,6 +1357,11 @@ shared_ptr DuckDBPyConnection::Rollback() { return shared_from_this(); } +shared_ptr DuckDBPyConnection::Checkpoint() { + ExecuteFromString("CHECKPOINT"); + return shared_from_this(); +} + Optional DuckDBPyConnection::GetDescription() { if (!result) { return py::none(); @@ -1320,6 +1378,7 @@ void DuckDBPyConnection::Close() { connection = nullptr; database = nullptr; temporary_views.clear(); + // https://peps.python.org/pep-0249/#Connection.close for (auto &cur : cursors) { cur->Close(); } @@ -1430,138 +1489,6 @@ duckdb::pyarrow::RecordBatchReader DuckDBPyConnection::FetchRecordBatchReader(co return result->FetchRecordBatchReader(rows_per_batch); } -static void CreateArrowScan(py::object entry, TableFunctionRef &table_function, - vector> &children, ClientProperties &client_properties) { - auto stream_factory = make_uniq(entry.ptr(), client_properties); - auto stream_factory_produce = PythonTableArrowArrayStreamFactory::Produce; - auto stream_factory_get_schema = PythonTableArrowArrayStreamFactory::GetSchema; - - children.push_back(make_uniq(Value::POINTER(CastPointerToValue(stream_factory.get())))); - children.push_back(make_uniq(Value::POINTER(CastPointerToValue(stream_factory_produce)))); - children.push_back(make_uniq(Value::POINTER(CastPointerToValue(stream_factory_get_schema)))); - - table_function.function = make_uniq("arrow_scan", std::move(children)); - table_function.external_dependency = - make_uniq(make_uniq(std::move(stream_factory), entry)); -} - -static unique_ptr TryReplacement(py::dict &dict, py::str &table_name, ClientProperties &client_properties, - py::object ¤t_frame) { - if (!dict.contains(table_name)) { - // not present in the globals - return nullptr; - } - auto entry = dict[table_name]; - auto table_function = make_uniq(); - vector> children; - NumpyObjectType numpytype; // Identify the type of accepted numpy objects. - if (DuckDBPyConnection::IsPandasDataframe(entry)) { - if (PandasDataFrame::IsPyArrowBacked(entry)) { - auto table = ArrowTableFromDataframe(entry); - CreateArrowScan(table, *table_function, children, client_properties); - } else { - auto new_df = PandasScanFunction::PandasReplaceCopiedNames(entry); - children.push_back(make_uniq(Value::POINTER(CastPointerToValue(new_df.ptr())))); - table_function->function = make_uniq("pandas_scan", std::move(children)); - table_function->external_dependency = - make_uniq(make_uniq(entry), make_uniq(new_df)); - } - - } else if (DuckDBPyConnection::IsAcceptedArrowObject(entry)) { - CreateArrowScan(entry, *table_function, children, client_properties); - } else if (DuckDBPyRelation::IsRelation(entry)) { - auto pyrel = py::cast(entry); - // create a subquery from the underlying relation object - auto select = make_uniq(); - select->node = pyrel->GetRel().GetQueryNode(); - - auto subquery = make_uniq(std::move(select)); - return std::move(subquery); - } else if (PolarsDataFrame::IsDataFrame(entry)) { - auto arrow_dataset = entry.attr("to_arrow")(); - CreateArrowScan(arrow_dataset, *table_function, children, client_properties); - } else if (PolarsDataFrame::IsLazyFrame(entry)) { - auto materialized = entry.attr("collect")(); - auto arrow_dataset = materialized.attr("to_arrow")(); - CreateArrowScan(arrow_dataset, *table_function, children, client_properties); - } else if ((numpytype = DuckDBPyConnection::IsAcceptedNumpyObject(entry)) != NumpyObjectType::INVALID) { // NOLINT - py::dict data; // we will convert all the supported format to dict{"key": np.array(value)}. - size_t idx = 0; - switch (numpytype) { - case NumpyObjectType::NDARRAY1D: - data["column0"] = entry; - break; - case NumpyObjectType::NDARRAY2D: - idx = 0; - for (auto item : py::cast(entry)) { - data[("column" + std::to_string(idx)).c_str()] = item; - idx++; - } - break; - case NumpyObjectType::LIST: - idx = 0; - for (auto item : py::cast(entry)) { - data[("column" + std::to_string(idx)).c_str()] = item; - idx++; - } - break; - case NumpyObjectType::DICT: - data = py::cast(entry); - break; - default: - throw NotImplementedException("Unsupported Numpy object"); - break; - } - children.push_back(make_uniq(Value::POINTER(CastPointerToValue(data.ptr())))); - table_function->function = make_uniq("pandas_scan", std::move(children)); - table_function->external_dependency = - make_uniq(make_uniq(entry), make_uniq(data)); - } else { - std::string location = py::cast(current_frame.attr("f_code").attr("co_filename")); - location += ":"; - location += py::cast(current_frame.attr("f_lineno")); - std::string cpp_table_name = table_name; - auto py_object_type = string(py::str(entry.get_type().attr("__name__"))); - - throw InvalidInputException( - "Python Object \"%s\" of type \"%s\" found on line \"%s\" not suitable for replacement scans.\nMake sure " - "that \"%s\" is either a pandas.DataFrame, duckdb.DuckDBPyRelation, pyarrow Table, Dataset, " - "RecordBatchReader, Scanner, or NumPy ndarrays with supported format", - cpp_table_name, py_object_type, location, cpp_table_name); - } - return std::move(table_function); -} - -static unique_ptr ScanReplacement(ClientContext &context, const string &table_name, - ReplacementScanData *data) { - py::gil_scoped_acquire acquire; - auto py_table_name = py::str(table_name); - // Here we do an exhaustive search on the frame lineage - auto current_frame = py::module::import("inspect").attr("currentframe")(); - auto client_properties = context.GetClientProperties(); - while (hasattr(current_frame, "f_locals")) { - auto local_dict = py::reinterpret_borrow(current_frame.attr("f_locals")); - // search local dictionary - if (local_dict) { - auto result = TryReplacement(local_dict, py_table_name, client_properties, current_frame); - if (result) { - return result; - } - } - // search global dictionary - auto global_dict = py::reinterpret_borrow(current_frame.attr("f_globals")); - if (global_dict) { - auto result = TryReplacement(global_dict, py_table_name, client_properties, current_frame); - if (result) { - return result; - } - } - current_frame = current_frame.attr("f_back"); - } - // Not found :( - return nullptr; -} - case_insensitive_map_t TransformPyConfigDict(const py::dict &py_config_dict) { case_insensitive_map_t config_dict; for (auto &kv : py_config_dict) { @@ -1575,9 +1502,7 @@ case_insensitive_map_t TransformPyConfigDict(const py::dict &py_config_di void CreateNewInstance(DuckDBPyConnection &res, const string &database, DBConfig &config) { // We don't cache unnamed memory instances (i.e., :memory:) bool cache_instance = database != ":memory:" && !database.empty(); - if (config.options.enable_external_access) { - config.replacement_scans.emplace_back(ScanReplacement); - } + config.replacement_scans.emplace_back(PythonReplacementScan::Replace); res.database = instance_cache.CreateInstance(database, config, cache_instance); res.connection = make_uniq(*res.database); auto &context = *res.connection->context; @@ -1660,6 +1585,9 @@ shared_ptr DuckDBPyConnection::Connect(const string &databas config.AddExtensionOption("pandas_analyze_sample", "The maximum number of rows to sample when analyzing a pandas object column.", LogicalType::UBIGINT, Value::UBIGINT(1000)); + config.AddExtensionOption("python_enable_replacements", + "Whether variables visible to the current stack should be used for replacement scans.", + LogicalType::BOOLEAN, Value::BOOLEAN(true)); if (!DuckDBPyConnection::IsJupyter()) { config_dict["duckdb_api"] = Value("python"); } else { @@ -1795,7 +1723,7 @@ NumpyObjectType DuckDBPyConnection::IsAcceptedNumpyObject(const py::object &obje default: return NumpyObjectType::INVALID; } - } else if (py::isinstance(object)) { + } else if (py::is_dict_like(object)) { int dim = -1; for (auto item : py::cast(object)) { if (!IsValidNumpyDimensions(item.second, dim)) { @@ -1803,7 +1731,7 @@ NumpyObjectType DuckDBPyConnection::IsAcceptedNumpyObject(const py::object &obje } } return NumpyObjectType::DICT; - } else if (py::isinstance(object)) { + } else if (py::is_list_like(object)) { int dim = -1; for (auto item : py::cast(object)) { if (!IsValidNumpyDimensions(item, dim)) { diff --git a/tools/pythonpkg/src/pyconnection/type_creation.cpp b/tools/pythonpkg/src/pyconnection/type_creation.cpp index 4c85790f4ee..733d30a7979 100644 --- a/tools/pythonpkg/src/pyconnection/type_creation.cpp +++ b/tools/pythonpkg/src/pyconnection/type_creation.cpp @@ -101,7 +101,7 @@ shared_ptr DuckDBPyConnection::Type(const string &type_str) { context.RunFunctionInTransaction([&result, &type_str, &context]() { result = make_shared_ptr(TransformStringToLogicalType(type_str, context)); }); - return std::move(result); + return result; } } // namespace duckdb diff --git a/tools/pythonpkg/src/pyexpression.cpp b/tools/pythonpkg/src/pyexpression.cpp index 3bc2c43ec47..d33110f862d 100644 --- a/tools/pythonpkg/src/pyexpression.cpp +++ b/tools/pythonpkg/src/pyexpression.cpp @@ -184,6 +184,27 @@ shared_ptr DuckDBPyExpression::In(const py::args &args) { return make_shared_ptr(std::move(operator_expr)); } +// COALESCE + +shared_ptr DuckDBPyExpression::Coalesce(const py::args &args) { + vector> expressions; + expressions.reserve(args.size()); + + for (auto arg : args) { + shared_ptr py_expr; + if (!py::try_cast>(arg, py_expr)) { + throw InvalidInputException("Please provide arguments of type Expression!"); + } + auto expr = py_expr->GetExpression().Copy(); + expressions.push_back(std::move(expr)); + } + if (expressions.empty()) { + throw InvalidInputException("Please provide at least one argument"); + } + auto operator_expr = make_uniq(ExpressionType::OPERATOR_COALESCE, std::move(expressions)); + return make_shared_ptr(std::move(operator_expr)); +} + shared_ptr DuckDBPyExpression::NotIn(const py::args &args) { auto in_expr = In(args); return in_expr->Not(); diff --git a/tools/pythonpkg/src/pyexpression/initialize.cpp b/tools/pythonpkg/src/pyexpression/initialize.cpp index 0cf7774837b..5f7b784459f 100644 --- a/tools/pythonpkg/src/pyexpression/initialize.cpp +++ b/tools/pythonpkg/src/pyexpression/initialize.cpp @@ -30,6 +30,10 @@ void InitializeStaticMethods(py::module_ &m) { // Function Expression docs = ""; m.def("FunctionExpression", &DuckDBPyExpression::FunctionExpression, py::arg("function_name"), docs); + + // Coalesce Operator + docs = ""; + m.def("CoalesceOperator", &DuckDBPyExpression::Coalesce, docs); } static void InitializeDunderMethods(py::class_> &m) { @@ -314,7 +318,7 @@ void DuckDBPyExpression::Initialize(py::module_ &m) { expression.def("isnotnull", &DuckDBPyExpression::IsNotNull, docs); docs = R"( - Return a IN expression comparing self to the input arguments. + Return an IN expression comparing self to the input arguments. Returns: DuckDBPyExpression: The compare IN expression diff --git a/tools/pythonpkg/src/pyfilesystem.cpp b/tools/pythonpkg/src/pyfilesystem.cpp index 48157954847..5c1ab96fedd 100644 --- a/tools/pythonpkg/src/pyfilesystem.cpp +++ b/tools/pythonpkg/src/pyfilesystem.cpp @@ -18,6 +18,15 @@ PythonFileHandle::~PythonFileHandle() { } } +PythonFilesystem::~PythonFilesystem() { + try { + PythonGILWrapper gil; + filesystem.dec_ref(); + filesystem.release(); + } catch (...) { // NOLINT + } +} + string PythonFilesystem::DecodeFlags(FileOpenFlags flags) { // see https://stackoverflow.com/a/58925279 for truth table of python file modes bool read = flags.OpenForReading(); diff --git a/tools/pythonpkg/src/pyrelation.cpp b/tools/pythonpkg/src/pyrelation.cpp index 9eb8541fbc4..bf54bdcd88b 100644 --- a/tools/pythonpkg/src/pyrelation.cpp +++ b/tools/pythonpkg/src/pyrelation.cpp @@ -35,12 +35,26 @@ DuckDBPyRelation::DuckDBPyRelation(shared_ptr rel_p) : rel(std::move(r } bool DuckDBPyRelation::CanBeRegisteredBy(Connection &con) { + return CanBeRegisteredBy(con.context); +} + +bool DuckDBPyRelation::CanBeRegisteredBy(ClientContext &context) { if (!rel) { // PyRelation without an internal relation can not be registered return false; } - auto context = rel->context.GetContext(); - return context == con.context; + auto this_context = rel->context.TryGetContext(); + if (!this_context) { + return false; + } + return &context == this_context.get(); +} + +bool DuckDBPyRelation::CanBeRegisteredBy(shared_ptr &con) { + if (!con) { + return false; + } + return CanBeRegisteredBy(*con); } DuckDBPyRelation::~DuckDBPyRelation() { @@ -62,11 +76,13 @@ DuckDBPyRelation::DuckDBPyRelation(unique_ptr result_p) : rel(nu unique_ptr DuckDBPyRelation::ProjectFromExpression(const string &expression) { auto projected_relation = make_uniq(rel->Project(expression)); - projected_relation->rel->extra_dependencies = this->rel->extra_dependencies; + for (auto &dep : this->rel->external_dependencies) { + projected_relation->rel->AddExternalDependency(dep); + } return projected_relation; } -unique_ptr DuckDBPyRelation::Project(const py::args &args, const py::kwargs &kwargs) { +unique_ptr DuckDBPyRelation::Project(const py::args &args, const string &groups) { if (!rel) { return nullptr; } @@ -89,7 +105,6 @@ unique_ptr DuckDBPyRelation::Project(const py::args &args, con expressions.push_back(std::move(expr)); } vector empty_aliases; - auto groups = kwargs.contains("groups") ? std::string(py::cast(kwargs["groups"])) : ""; if (groups.empty()) { // No groups provided return make_uniq(rel->Project(std::move(expressions), empty_aliases)); @@ -1356,10 +1371,10 @@ unique_ptr DuckDBPyRelation::Map(py::function fun, Optional(rel->TableFunction("python_map_function", params)); - auto rel_dependency = make_uniq(); - rel_dependency->map_function = std::move(fun); - rel_dependency->py_object_list.push_back(make_uniq(std::move(schema))); - relation->rel->extra_dependencies = std::move(rel_dependency); + auto rel_dependency = make_uniq(); + rel_dependency->AddDependency("map", PythonDependencyItem::Create(std::move(fun))); + rel_dependency->AddDependency("schema", PythonDependencyItem::Create(std::move(schema))); + relation->rel->AddExternalDependency(std::move(rel_dependency)); return relation; } @@ -1379,6 +1394,9 @@ string DuckDBPyRelation::ToStringInternal(const BoxRendererConfig &config, bool string DuckDBPyRelation::ToString() { BoxRendererConfig config; config.limit = 10000; + if (DuckDBPyConnection::IsJupyter()) { + config.max_width = 10000; + } return ToStringInternal(config); } @@ -1392,6 +1410,9 @@ void DuckDBPyRelation::Print(const Optional &max_width, const Optional const py::object &render_mode) { BoxRendererConfig config; config.limit = 10000; + if (DuckDBPyConnection::IsJupyter()) { + config.max_width = 10000; + } bool invalidate_cache = false; if (!py::none().is(max_width)) { @@ -1444,7 +1465,9 @@ string DuckDBPyRelation::Explain(ExplainType type) { // TODO: RelationType to a python enum py::str DuckDBPyRelation::Type() { - AssertRelation(); + if (!rel) { + return py::str("QUERY_RESULT"); + } return py::str(RelationTypeToString(rel->type)); } diff --git a/tools/pythonpkg/src/pyrelation/initialize.cpp b/tools/pythonpkg/src/pyrelation/initialize.cpp index f2754cf016b..008f172ff85 100644 --- a/tools/pythonpkg/src/pyrelation/initialize.cpp +++ b/tools/pythonpkg/src/pyrelation/initialize.cpp @@ -56,8 +56,8 @@ static void InitializeConsumers(py::class_ &m) { py::arg("date_as_object") = false) .def("to_df", &DuckDBPyRelation::FetchDF, "Execute and fetch all rows as a pandas DataFrame", py::kw_only(), py::arg("date_as_object") = false) - .def("fetch_df_chunk", &DuckDBPyRelation::FetchDFChunk, "Execute and fetch a chunk of the rows", py::kw_only(), - py::arg("vectors_per_chunk"), py::arg("date_as_object")) + .def("fetch_df_chunk", &DuckDBPyRelation::FetchDFChunk, "Execute and fetch a chunk of the rows", + py::arg("vectors_per_chunk") = 1, py::kw_only(), py::arg("date_as_object") = false) .def("arrow", &DuckDBPyRelation::ToArrowTable, "Execute and fetch all rows as an Arrow Table", py::arg("batch_size") = 1000000) .def("fetch_arrow_table", &DuckDBPyRelation::ToArrowTable, "Execute and fetch all rows as an Arrow Table", @@ -233,7 +233,8 @@ void DuckDBPyRelation::Initialize(py::handle &m) { relation_module.def("filter", &DuckDBPyRelation::Filter, "Filter the relation object by the filter in filter_expr", py::arg("filter_expr")); DefineMethod({"select", "project"}, relation_module, &DuckDBPyRelation::Project, - "Project the relation object by the projection in project_expr"); + "Project the relation object by the projection in project_expr", py::kw_only(), + py::arg("groups") = ""); DefineMethod({"select_types", "select_dtypes"}, relation_module, &DuckDBPyRelation::ProjectFromTypes, "Select columns from the relation, by filtering based on type(s)", py::arg("types")); diff --git a/tools/pythonpkg/src/python_dependency.cpp b/tools/pythonpkg/src/python_dependency.cpp new file mode 100644 index 00000000000..dc62d24856e --- /dev/null +++ b/tools/pythonpkg/src/python_dependency.cpp @@ -0,0 +1,23 @@ +#include "duckdb_python/python_dependency.hpp" +#include "duckdb/common/helper.hpp" + +namespace duckdb { + +PythonDependencyItem::PythonDependencyItem(unique_ptr &&object) : object(std::move(object)) { +} + +PythonDependencyItem::~PythonDependencyItem() { // NOLINT - cannot throw in exception + py::gil_scoped_acquire gil; + object.reset(); +} + +shared_ptr PythonDependencyItem::Create(py::object object) { + auto registered_object = make_uniq(std::move(object)); + return make_shared_ptr(std::move(registered_object)); +} + +shared_ptr PythonDependencyItem::Create(unique_ptr &&object) { + return make_shared_ptr(std::move(object)); +} + +} // namespace duckdb diff --git a/tools/pythonpkg/src/python_replacement_scan.cpp b/tools/pythonpkg/src/python_replacement_scan.cpp new file mode 100644 index 00000000000..bfa317c60b3 --- /dev/null +++ b/tools/pythonpkg/src/python_replacement_scan.cpp @@ -0,0 +1,201 @@ +#include "duckdb_python/python_replacement_scan.hpp" +#include "duckdb_python/pybind11/pybind_wrapper.hpp" +#include "duckdb/main/client_properties.hpp" +#include "duckdb_python/numpy/numpy_type.hpp" +#include "duckdb/parser/tableref/table_function_ref.hpp" +#include "duckdb_python/pyconnection/pyconnection.hpp" +#include "duckdb_python/pybind11/dataframe.hpp" +#include "duckdb/parser/expression/constant_expression.hpp" +#include "duckdb/parser/expression/function_expression.hpp" +#include "duckdb/common/typedefs.hpp" +#include "duckdb_python/pandas/pandas_scan.hpp" +#include "duckdb/parser/tableref/subqueryref.hpp" +#include "duckdb_python/pyrelation.hpp" + +namespace duckdb { + +static void CreateArrowScan(const string &name, py::object entry, TableFunctionRef &table_function, + vector> &children, ClientProperties &client_properties) { + auto stream_factory = make_uniq(entry.ptr(), client_properties); + auto stream_factory_produce = PythonTableArrowArrayStreamFactory::Produce; + auto stream_factory_get_schema = PythonTableArrowArrayStreamFactory::GetSchema; + + children.push_back(make_uniq(Value::POINTER(CastPointerToValue(stream_factory.get())))); + children.push_back(make_uniq(Value::POINTER(CastPointerToValue(stream_factory_produce)))); + children.push_back(make_uniq(Value::POINTER(CastPointerToValue(stream_factory_get_schema)))); + + table_function.function = make_uniq("arrow_scan", std::move(children)); + auto dependency = make_uniq(); + auto dependency_item = PythonDependencyItem::Create(make_uniq(std::move(stream_factory), entry)); + dependency->AddDependency("replacement_cache", std::move(dependency_item)); + table_function.external_dependency = std::move(dependency); +} + +static unique_ptr TryReplacementObject(const py::object &entry, const string &name, ClientContext &context) { + auto client_properties = context.GetClientProperties(); + auto table_function = make_uniq(); + vector> children; + NumpyObjectType numpytype; // Identify the type of accepted numpy objects. + if (DuckDBPyConnection::IsPandasDataframe(entry)) { + if (PandasDataFrame::IsPyArrowBacked(entry)) { + auto table = PandasDataFrame::ToArrowTable(entry); + CreateArrowScan(name, table, *table_function, children, client_properties); + } else { + string name = "df_" + StringUtil::GenerateRandomName(); + auto new_df = PandasScanFunction::PandasReplaceCopiedNames(entry); + children.push_back(make_uniq(Value::POINTER(CastPointerToValue(new_df.ptr())))); + table_function->function = make_uniq("pandas_scan", std::move(children)); + auto dependency = make_uniq(); + dependency->AddDependency("replacement_cache", PythonDependencyItem::Create(entry)); + dependency->AddDependency("copy", PythonDependencyItem::Create(new_df)); + table_function->external_dependency = std::move(dependency); + } + } else if (DuckDBPyConnection::IsAcceptedArrowObject(entry)) { + CreateArrowScan(name, entry, *table_function, children, client_properties); + } else if (DuckDBPyRelation::IsRelation(entry)) { + auto pyrel = py::cast(entry); + if (!pyrel->CanBeRegisteredBy(context)) { + throw InvalidInputException( + "Python Object \"%s\" of type \"DuckDBPyRelation\" not suitable for replacement scan.\nThe object was " + "created by another Connection and can therefore not be used by this Connection.", + name); + } + // create a subquery from the underlying relation object + auto select = make_uniq(); + select->node = pyrel->GetRel().GetQueryNode(); + auto subquery = make_uniq(std::move(select)); + auto dependency = make_uniq(); + dependency->AddDependency("replacement_cache", PythonDependencyItem::Create(entry)); + subquery->external_dependency = std::move(dependency); + return std::move(subquery); + } else if (PolarsDataFrame::IsDataFrame(entry)) { + auto arrow_dataset = entry.attr("to_arrow")(); + CreateArrowScan(name, arrow_dataset, *table_function, children, client_properties); + } else if (PolarsDataFrame::IsLazyFrame(entry)) { + auto materialized = entry.attr("collect")(); + auto arrow_dataset = materialized.attr("to_arrow")(); + CreateArrowScan(name, arrow_dataset, *table_function, children, client_properties); + } else if ((numpytype = DuckDBPyConnection::IsAcceptedNumpyObject(entry)) != NumpyObjectType::INVALID) { + string name = "np_" + StringUtil::GenerateRandomName(); + py::dict data; // we will convert all the supported format to dict{"key": np.array(value)}. + size_t idx = 0; + switch (numpytype) { + case NumpyObjectType::NDARRAY1D: + data["column0"] = entry; + break; + case NumpyObjectType::NDARRAY2D: + idx = 0; + for (auto item : py::cast(entry)) { + data[("column" + std::to_string(idx)).c_str()] = item; + idx++; + } + break; + case NumpyObjectType::LIST: + idx = 0; + for (auto item : py::cast(entry)) { + data[("column" + std::to_string(idx)).c_str()] = item; + idx++; + } + break; + case NumpyObjectType::DICT: + data = py::cast(entry); + break; + default: + throw NotImplementedException("Unsupported Numpy object"); + break; + } + children.push_back(make_uniq(Value::POINTER(CastPointerToValue(data.ptr())))); + table_function->function = make_uniq("pandas_scan", std::move(children)); + auto dependency = make_uniq(); + dependency->AddDependency("replacement_cache", PythonDependencyItem::Create(entry)); + dependency->AddDependency("data", PythonDependencyItem::Create(data)); + table_function->external_dependency = std::move(dependency); + } else { + // This throws an error later on! + return nullptr; + } + return std::move(table_function); +} + +static bool IsBuiltinFunction(const py::object &object) { + auto &import_cache_py = *DuckDBPyConnection::ImportCache(); + return py::isinstance(object, import_cache_py.types.BuiltinFunctionType()); +} + +static unique_ptr TryReplacement(py::dict &dict, const string &name, ClientContext &context, + py::object ¤t_frame) { + auto table_name = py::str(name); + if (!dict.contains(table_name)) { + // not present in the globals + return nullptr; + } + const py::object &entry = dict[table_name]; + + if (IsBuiltinFunction(entry)) { + return nullptr; + } + + auto result = TryReplacementObject(entry, name, context); + if (!result) { + std::string location = py::cast(current_frame.attr("f_code").attr("co_filename")); + location += ":"; + location += py::cast(current_frame.attr("f_lineno")); + std::string cpp_table_name = table_name; + auto py_object_type = string(py::str(entry.get_type().attr("__name__"))); + + throw InvalidInputException( + "Python Object \"%s\" of type \"%s\" found on line \"%s\" not suitable for replacement scans.\nMake sure " + "that \"%s\" is either a pandas.DataFrame, duckdb.DuckDBPyRelation, pyarrow Table, Dataset, " + "RecordBatchReader, Scanner, or NumPy ndarrays with supported format", + cpp_table_name, py_object_type, location, cpp_table_name); + } + return result; +} + +static unique_ptr ReplaceInternal(ClientContext &context, const string &table_name) { + Value result; + auto lookup_result = context.TryGetCurrentSetting("python_enable_replacements", result); + D_ASSERT((bool)lookup_result); + auto enabled = result.GetValue(); + + if (!enabled) { + return nullptr; + } + + py::gil_scoped_acquire acquire; + auto current_frame = py::module::import("inspect").attr("currentframe")(); + + auto local_dict = py::reinterpret_borrow(current_frame.attr("f_locals")); + // search local dictionary + if (local_dict) { + auto result = TryReplacement(local_dict, table_name, context, current_frame); + if (result) { + return result; + } + } + // search global dictionary + auto global_dict = py::reinterpret_borrow(current_frame.attr("f_globals")); + if (global_dict) { + auto result = TryReplacement(global_dict, table_name, context, current_frame); + if (result) { + return result; + } + } + return nullptr; +} + +unique_ptr PythonReplacementScan::Replace(ClientContext &context, ReplacementScanInput &input, + optional_ptr data) { + auto &table_name = input.table_name; + + auto &config = DBConfig::GetConfig(context); + if (!config.options.enable_external_access) { + return nullptr; + } + + unique_ptr result; + result = ReplaceInternal(context, table_name); + return result; +} + +} // namespace duckdb diff --git a/tools/pythonpkg/src/python_udf.cpp b/tools/pythonpkg/src/python_udf.cpp index 45f1f40c6f1..b24bfb05c95 100644 --- a/tools/pythonpkg/src/python_udf.cpp +++ b/tools/pythonpkg/src/python_udf.cpp @@ -15,6 +15,7 @@ #include "duckdb_python/numpy/numpy_scan.hpp" #include "duckdb_python/arrow/arrow_export_utils.hpp" #include "duckdb/common/types/arrow_aux_data.hpp" +#include "duckdb/parser/tableref/table_function_ref.hpp" namespace duckdb { @@ -65,7 +66,11 @@ static void ConvertPyArrowToDataChunk(const py::object &table, Vector &out, Clie vector input_types; vector input_names; - TableFunctionBindInput bind_input(children, named_params, input_types, input_names, nullptr, nullptr); + TableFunctionRef empty; + TableFunction dummy_table_function; + dummy_table_function.name = "ConvertPyArrowToDataChunk"; + TableFunctionBindInput bind_input(children, named_params, input_types, input_names, nullptr, nullptr, + dummy_table_function, empty); vector return_types; vector return_names; diff --git a/tools/pythonpkg/tests/extensions/test_extensions_loading.py b/tools/pythonpkg/tests/extensions/test_extensions_loading.py index a3ecfe3a4e6..c045e4a330c 100644 --- a/tools/pythonpkg/tests/extensions/test_extensions_loading.py +++ b/tools/pythonpkg/tests/extensions/test_extensions_loading.py @@ -1,10 +1,17 @@ import os +import platform import duckdb from pytest import raises import pytest +pytestmark = pytest.mark.skipif( + platform.system() == "Emscripten", + reason="Extensions are not supported on Emscripten", +) + + def test_extension_loading(require): if not os.getenv('DUCKDB_PYTHON_TEST_EXTENSION_REQUIRED', False): return diff --git a/tools/pythonpkg/tests/fast/api/test_connection_interrupt.py b/tools/pythonpkg/tests/fast/api/test_connection_interrupt.py index 7685a77ba66..4efd68b5991 100644 --- a/tools/pythonpkg/tests/fast/api/test_connection_interrupt.py +++ b/tools/pythonpkg/tests/fast/api/test_connection_interrupt.py @@ -1,3 +1,4 @@ +import platform import threading import time @@ -6,6 +7,10 @@ class TestConnectionInterrupt(object): + @pytest.mark.xfail( + condition=platform.system() == "Emscripten", + reason="threads not allowed on Emscripten", + ) def test_connection_interrupt(self): conn = duckdb.connect() @@ -17,7 +22,8 @@ def interrupt(): thread = threading.Thread(target=interrupt) thread.start() with pytest.raises(duckdb.InterruptException): - conn.execute("select count(*) from range(1000000000)").fetchall() + conn.execute("select count(*) from range(100000000000)").fetchall() + thread.join() def test_interrupt_closed_connection(self): conn = duckdb.connect() diff --git a/tools/pythonpkg/tests/fast/api/test_duckdb_connection.py b/tools/pythonpkg/tests/fast/api/test_duckdb_connection.py index 4d1afb7b3bf..c5f8e6375d6 100644 --- a/tools/pythonpkg/tests/fast/api/test_duckdb_connection.py +++ b/tools/pythonpkg/tests/fast/api/test_duckdb_connection.py @@ -320,6 +320,14 @@ def test_close(self): def test_interrupt(self): assert None != duckdb.interrupt + def test_wrap_shadowing(self): + pd = NumpyPandas() + import duckdb + + df = pd.DataFrame({"a": [1, 2, 3]}) + res = duckdb.sql("from df").fetchall() + assert res == [(1,), (2,), (3,)] + def test_wrap_coverage(self): con = duckdb.default_connection diff --git a/tools/pythonpkg/tests/fast/api/test_duckdb_execute.py b/tools/pythonpkg/tests/fast/api/test_duckdb_execute.py index 5e365c8fee7..ded26df0973 100644 --- a/tools/pythonpkg/tests/fast/api/test_duckdb_execute.py +++ b/tools/pythonpkg/tests/fast/api/test_duckdb_execute.py @@ -14,14 +14,38 @@ def test_execute_many_basic(self, duckdb_cursor): # This works because prepared parameter is only present in the last statement duckdb_cursor.execute( """ - delete from t where x=5; - insert into t(x) values($1); - """, + delete from t where x=5; + insert into t(x) values($1); + """, (99,), ) res = duckdb_cursor.table('t').fetchall() assert res == [(99,)] + @pytest.mark.parametrize( + 'rowcount', + [ + 50, + 2048, + 5000, + 100000, + 1000000, + 10000000, + ], + ) + def test_large_execute(self, duckdb_cursor, rowcount): + def generator(rowcount): + count = 0 + while count < rowcount: + yield min(2048, rowcount - count) + count += 2048 + + duckdb_cursor.execute(f"create table tbl as from range({rowcount})") + duckdb_cursor.execute("select * from tbl") + for rows in generator(rowcount): + tuples = duckdb_cursor.fetchmany(rows) + assert len(tuples) == rows + def test_execute_many_error(self, duckdb_cursor): duckdb_cursor.execute("create table t(x int);") @@ -31,8 +55,20 @@ def test_execute_many_error(self, duckdb_cursor): ): duckdb_cursor.execute( """ - delete from t where x=$1; - insert into t(x) values($1); - """, + delete from t where x=$1; + insert into t(x) values($1); + """, (99,), ) + + def test_execute_many_generator(self, duckdb_cursor): + to_insert = [[1], [2], [3]] + + def to_insert_from_generator(what): + for x in what: + yield x + + gen = to_insert_from_generator(to_insert) + duckdb_cursor.execute("CREATE TABLE unittest_generator (a INTEGER);") + duckdb_cursor.executemany("INSERT into unittest_generator (a) VALUES (?)", gen) + assert duckdb_cursor.table('unittest_generator').fetchall() == [(1,), (2,), (3,)] diff --git a/tools/pythonpkg/tests/fast/api/test_native_tz.py b/tools/pythonpkg/tests/fast/api/test_native_tz.py index e1d5425b4af..df4c7f22c22 100644 --- a/tools/pythonpkg/tests/fast/api/test_native_tz.py +++ b/tools/pythonpkg/tests/fast/api/test_native_tz.py @@ -70,5 +70,14 @@ def test_arrow_timestamp_timezone(self, duckdb_cursor): assert res['tz'][0].hour == 21 and res['tz'][0].minute == 52 def test_arrow_timestamp_time(self, duckdb_cursor): - with pytest.raises(duckdb.NotImplementedException, match="Unsupported Arrow type"): - duckdb_cursor.execute(f"select TimeRecStart::TIMETZ as tz from '{filename}'").arrow() + duckdb_cursor.execute("SET timezone='America/Los_Angeles';") + res1 = duckdb_cursor.execute(f"select TimeRecStart::TIMETZ as tz from '{filename}'").arrow().to_pandas() + res2 = duckdb_cursor.execute(f"select TimeRecStart::TIMETZ::TIME as tz from '{filename}'").arrow().to_pandas() + assert res1['tz'][0].hour == 21 and res1['tz'][0].minute == 52 + assert res2['tz'][0].hour == res2['tz'][0].hour and res2['tz'][0].minute == res1['tz'][0].minute + + duckdb_cursor.execute("SET timezone='UTC';") + res1 = duckdb_cursor.execute(f"select TimeRecStart::TIMETZ as tz from '{filename}'").arrow().to_pandas() + res2 = duckdb_cursor.execute(f"select TimeRecStart::TIMETZ::TIME as tz from '{filename}'").arrow().to_pandas() + assert res1['tz'][0].hour == 21 and res1['tz'][0].minute == 52 + assert res2['tz'][0].hour == res2['tz'][0].hour and res2['tz'][0].minute == res1['tz'][0].minute diff --git a/tools/pythonpkg/tests/fast/api/test_query_interrupt.py b/tools/pythonpkg/tests/fast/api/test_query_interrupt.py index 52089022af1..6334e475d27 100644 --- a/tools/pythonpkg/tests/fast/api/test_query_interrupt.py +++ b/tools/pythonpkg/tests/fast/api/test_query_interrupt.py @@ -2,6 +2,7 @@ import time import pytest +import platform import threading import _thread as thread @@ -14,16 +15,21 @@ def send_keyboard_interrupt(): class TestQueryInterruption(object): + @pytest.mark.xfail( + condition=platform.system() == "Emscripten", + reason="Emscripten builds cannot use threads", + ) def test_query_interruption(self): con = duckdb.connect() thread = threading.Thread(target=send_keyboard_interrupt) # Start the thread thread.start() try: - res = con.execute('select count(*) from range(1000000000)').fetchall() + res = con.execute('select count(*) from range(100000000000)').fetchall() except RuntimeError: # If this is not reached, we could not cancel the query before it completed # indicating that the query interruption functionality is broken assert True except KeyboardInterrupt: pytest.fail() + thread.join() diff --git a/tools/pythonpkg/tests/fast/api/test_read_csv.py b/tools/pythonpkg/tests/fast/api/test_read_csv.py index 49df1ac4f97..440ef049c18 100644 --- a/tools/pythonpkg/tests/fast/api/test_read_csv.py +++ b/tools/pythonpkg/tests/fast/api/test_read_csv.py @@ -1,11 +1,9 @@ from multiprocessing.sharedctypes import Value -import numpy import datetime -import pandas import pytest +import platform import duckdb from io import StringIO, BytesIO -from duckdb.typing import BIGINT, VARCHAR, INTEGER def TestFile(name): @@ -280,7 +278,8 @@ def test_read_pathlib_path(self, duckdb_cursor): assert res == (1, 'Action', datetime.datetime(2006, 2, 15, 4, 46, 27)) def test_read_filelike(self, duckdb_cursor): - _ = pytest.importorskip("fsspec") + pytest.importorskip("fsspec") + string = StringIO("c1,c2,c3\na,b,c") res = duckdb_cursor.read_csv(string).fetchall() assert res == [('a', 'b', 'c')] @@ -441,6 +440,7 @@ def test_read_csv_glob(self, tmp_path, create_temp_csv): res = con.sql("select * from rel order by all").fetchall() assert res == [(1,), (2,), (3,), (4,), (5,), (6,)] + @pytest.mark.xfail(condition=platform.system() == "Emscripten", reason="time zones not working") def test_read_csv_combined(self, duckdb_cursor): CSV_FILE = TestFile('stress_test.csv') COLUMNS = { @@ -469,10 +469,12 @@ def test_read_csv_combined(self, duckdb_cursor): assert rel.columns == rel2.columns assert rel.types == rel2.types - def test_read_csv_names(self): + def test_read_csv_names(self, tmp_path): + file = tmp_path / "file.csv" + file.write_text('one,two,three,four\n1,2,3,4\n1,2,3,4\n1,2,3,4') + con = duckdb.connect() - file = StringIO('one,two,three,four\n1,2,3,4\n1,2,3,4\n1,2,3,4') - rel = con.read_csv(file, names=['a', 'b', 'c']) + rel = con.read_csv(str(file), names=['a', 'b', 'c']) assert rel.columns == ['a', 'b', 'c', 'four'] with pytest.raises(duckdb.InvalidInputException, match="read_csv only accepts 'names' as a list of strings"): @@ -487,9 +489,11 @@ def test_read_csv_names(self): rel = con.read_csv(file, names=['a', 'b', 'a', 'b']) assert rel.columns == ['a', 'b', 'a', 'b'] - def test_read_csv_names_mixed_with_dtypes(self): + def test_read_csv_names_mixed_with_dtypes(self, tmp_path): + file = tmp_path / "file.csv" + file.write_text('one,two,three,four\n1,2,3,4\n1,2,3,4\n1,2,3,4') + con = duckdb.connect() - file = StringIO('one,two,three,four\n1,2,3,4\n1,2,3,4\n1,2,3,4') rel = con.read_csv( file, names=['a', 'b', 'c'], @@ -517,12 +521,18 @@ def test_read_csv_names_mixed_with_dtypes(self): }, ) - def test_read_csv_multi_file(self): + def test_read_csv_multi_file(self, tmp_path): + file1 = tmp_path / "file1.csv" + file1.write_text('one,two,three,four\n1,2,3,4\n1,2,3,4\n1,2,3,4') + + file2 = tmp_path / "file2.csv" + file2.write_text('one,two,three,four\n5,6,7,8\n5,6,7,8\n5,6,7,8') + + file3 = tmp_path / "file3.csv" + file3.write_text('one,two,three,four\n9,10,11,12\n9,10,11,12\n9,10,11,12') + con = duckdb.connect() - file1 = StringIO('one,two,three,four\n1,2,3,4\n1,2,3,4\n1,2,3,4') - file2 = StringIO('one,two,three,four\n5,6,7,8\n5,6,7,8\n5,6,7,8') - file3 = StringIO('one,two,three,four\n9,10,11,12\n9,10,11,12\n9,10,11,12') - files = [file1, file2, file3] + files = [str(file1), str(file2), str(file3)] rel = con.read_csv(files) res = rel.fetchall() assert res == [ @@ -546,13 +556,16 @@ def test_read_csv_empty_list(self): rel = con.read_csv(files) res = rel.fetchall() - def test_read_csv_list_invalid_path(self): + def test_read_csv_list_invalid_path(self, tmp_path): con = duckdb.connect() - files = [ - StringIO('one,two,three,four\n1,2,3,4\n1,2,3,4\n1,2,3,4'), - 'not_valid_path', - StringIO('one,two,three,four\n9,10,11,12\n9,10,11,12\n9,10,11,12'), - ] + + file1 = tmp_path / "file1.csv" + file1.write_text('one,two,three,four\n1,2,3,4\n1,2,3,4\n1,2,3,4') + + file3 = tmp_path / "file3.csv" + file3.write_text('one,two,three,four\n9,10,11,12\n9,10,11,12\n9,10,11,12') + + files = [str(file1), 'not_valid_path', str(file3)] with pytest.raises(duckdb.IOException, match='No files found that match the pattern "not_valid_path"'): rel = con.read_csv(files) res = rel.fetchall() diff --git a/tools/pythonpkg/tests/fast/api/test_streaming_result.py b/tools/pythonpkg/tests/fast/api/test_streaming_result.py index 4e013e873ea..e51f62e425a 100644 --- a/tools/pythonpkg/tests/fast/api/test_streaming_result.py +++ b/tools/pythonpkg/tests/fast/api/test_streaming_result.py @@ -56,11 +56,8 @@ def test_record_batch_reader(self, duckdb_cursor): res = duckdb_cursor.sql( "SELECT CASE WHEN i < 10000 THEN i ELSE concat('hello', i::VARCHAR)::INT END FROM range(100000) t(i)" ) - reader = res.fetch_arrow_reader(batch_size=16_384) - with pytest.raises(OSError): - result = [] - for batch in reader: - result += batch.to_pydict()['i'] + with pytest.raises(duckdb.ConversionException, match="Could not convert string 'hello10000' to INT32"): + reader = res.fetch_arrow_reader(batch_size=16_384) def test_9801(self, duckdb_cursor): duckdb_cursor.execute('CREATE TABLE test(id INTEGER , name VARCHAR NOT NULL);') diff --git a/tools/pythonpkg/tests/fast/api/test_to_csv.py b/tools/pythonpkg/tests/fast/api/test_to_csv.py index f7ee6c5f915..0b137327710 100644 --- a/tools/pythonpkg/tests/fast/api/test_to_csv.py +++ b/tools/pythonpkg/tests/fast/api/test_to_csv.py @@ -218,10 +218,11 @@ def test_to_csv_overwrite_not_enabled(self, pandas): ) rel = duckdb.from_df(df) rel.to_csv(temp_file_name, header=True, partition_by=["c_category_1"]) - with pytest.raises(duckdb.IOException, match="Enable OVERWRITE_OR_IGNORE option to force writing"): + with pytest.raises(duckdb.IOException, match="OVERWRITE"): rel.to_csv(temp_file_name, header=True, partition_by=["c_category_1"]) @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) + @pytest.mark.skip(reason="Skip test due to unreliablility on certain platforms") def test_to_csv_per_thread_output(self, pandas): temp_file_name = os.path.join(tempfile.mkdtemp(), next(tempfile._get_candidate_names())) num_threads = duckdb.sql("select current_setting('threads')").fetchone()[0] diff --git a/tools/pythonpkg/tests/fast/arrow/test_5547.py b/tools/pythonpkg/tests/fast/arrow/test_5547.py index 5a376ad7f57..b27b29b24d5 100644 --- a/tools/pythonpkg/tests/fast/arrow/test_5547.py +++ b/tools/pythonpkg/tests/fast/arrow/test_5547.py @@ -27,8 +27,7 @@ def test_5547(): expected = tbl.to_pandas() result = con.execute( """ - SELECT * - FROM tbl + SELECT * FROM tbl """ ).df() diff --git a/tools/pythonpkg/tests/fast/arrow/test_9443.py b/tools/pythonpkg/tests/fast/arrow/test_9443.py index 206c07b8bc9..7de04bdee17 100644 --- a/tools/pythonpkg/tests/fast/arrow/test_9443.py +++ b/tools/pythonpkg/tests/fast/arrow/test_9443.py @@ -24,5 +24,4 @@ def test_9443(self, tmp_path, duckdb_cursor): sql = f'SELECT * FROM "{temp_file}"' duckdb_cursor.execute(sql) - with pytest.raises(Exception, match='Unsupported Arrow type TIME WITH TIME ZONE'): - duckdb_cursor.fetch_record_batch() + duckdb_cursor.fetch_record_batch() diff --git a/tools/pythonpkg/tests/fast/arrow/test_arrow_list.py b/tools/pythonpkg/tests/fast/arrow/test_arrow_list.py index 51e0e1eb164..e2449fd3d72 100644 --- a/tools/pythonpkg/tests/fast/arrow/test_arrow_list.py +++ b/tools/pythonpkg/tests/fast/arrow/test_arrow_list.py @@ -1,30 +1,26 @@ import duckdb import numpy as np +import pytest -try: - import pyarrow as pa +pa = pytest.importorskip("pyarrow") - can_run = True -except: - can_run = False - -def check_equal(duckdb_conn): - true_result = duckdb_conn.execute("SELECT * from test").fetchall() - arrow_result = duckdb_conn.execute("SELECT * from testarrow").fetchall() +def check_equal(duckdb_cursor): + true_result = duckdb_cursor.execute("SELECT * from test").fetchall() + arrow_result = duckdb_cursor.execute("SELECT * from testarrow").fetchall() assert arrow_result == true_result -def create_and_register_arrow_table(column_list, duckdb_conn): +def create_and_register_arrow_table(column_list, duckdb_cursor): pydict = {name: data for (name, _, data) in column_list} arrow_schema = pa.schema([(name, dtype) for (name, dtype, _) in column_list]) res = pa.Table.from_pydict(pydict, schema=arrow_schema) - duck_from_arrow = duckdb_conn.from_arrow(res) + duck_from_arrow = duckdb_cursor.from_arrow(res) duck_from_arrow.create("testarrow") -def create_and_register_comparison_result(column_list, duckdb_conn): +def create_and_register_comparison_result(column_list, duckdb_cursor): columns = ",".join([f'{name} {dtype}' for (name, dtype, _) in column_list]) column_amount = len(column_list) assert column_amount @@ -41,15 +37,62 @@ def create_and_register_comparison_result(column_list, duckdb_conn): INSERT INTO test VALUES {row_format}; """ - duckdb_conn.execute(query, inserted_values) + duckdb_cursor.execute(query, inserted_values) + + +class ListGenerationResult: + def __init__(self, list, list_view): + self.list = list + self.list_view = list_view + + +def generate_list(child_size) -> ListGenerationResult: + input = [i for i in range(child_size)] + offsets = [] + sizes = [] + lists = [] + mask = [] + count = 0 + SIZE_MAP = [3, 1, 10, 0, 5, None] + for i in range(child_size): + if count >= child_size: + break + size = SIZE_MAP[i % len(SIZE_MAP)] + if size == None: + mask.append(True) + size = 0 + else: + mask.append(False) + size = min(size, child_size - count) + sizes.append(size) + offsets.append(count) + lists.append(input[count : count + size]) + count += size + offsets.append(count) + + # Create a regular ListArray + list_arr = pa.ListArray.from_arrays(offsets=offsets, values=input, mask=pa.array(mask, type=pa.bool_())) + + if not hasattr(pa, 'ListViewArray'): + return ListGenerationResult(list_arr, None) + + lists = list(reversed(lists)) + # Create a ListViewArray + offsets = [] + input = [] + remaining = count + for i, size in enumerate(sizes): + remaining -= size + offsets.append(remaining) + input.extend(lists[i]) + list_view_arr = pa.ListViewArray.from_arrays( + offsets=offsets, sizes=sizes, values=input, mask=pa.array(mask, type=pa.bool_()) + ) + return ListGenerationResult(list_arr, list_view_arr) class TestArrowListType(object): - def test_regular_list(self): - if not can_run: - return - duckdb_conn = duckdb.connect() - + def test_regular_list(self, duckdb_cursor): n = 5 # Amount of lists generated_size = 3 # Size of each list list_size = -1 # Argument passed to `pa._list()` @@ -61,22 +104,18 @@ def test_regular_list(self): [ ('a', list_type, data), ], - duckdb_conn, + duckdb_cursor, ) create_and_register_comparison_result( [ ('a', 'FLOAT[]', data), ], - duckdb_conn, + duckdb_cursor, ) - check_equal(duckdb_conn) - - def test_fixedsize_list(self): - if not can_run: - return - duckdb_conn = duckdb.connect() + check_equal(duckdb_cursor) + def test_fixedsize_list(self, duckdb_cursor): n = 5 # Amount of lists generated_size = 3 # Size of each list list_size = 3 # Argument passed to `pa._list()` @@ -88,13 +127,26 @@ def test_fixedsize_list(self): [ ('a', list_type, data), ], - duckdb_conn, + duckdb_cursor, ) create_and_register_comparison_result( [ ('a', f'FLOAT[{list_size}]', data), ], - duckdb_conn, + duckdb_cursor, ) - check_equal(duckdb_conn) + check_equal(duckdb_cursor) + + @pytest.mark.skipif(not hasattr(pa, 'ListViewArray'), reason='The pyarrow version does not support ListViewArrays') + @pytest.mark.parametrize('child_size', [100000]) + def test_list_view(self, duckdb_cursor, child_size): + res = generate_list(child_size) + + list_tbl = pa.Table.from_arrays([res.list], ['x']) + list_view_tbl = pa.Table.from_arrays([res.list_view], ['x']) + + assert res.list_view.to_pylist() == res.list.to_pylist() + original = duckdb_cursor.query("select * from list_tbl").fetchall() + view = duckdb_cursor.query("select * from list_view_tbl").fetchall() + assert original == view diff --git a/tools/pythonpkg/tests/fast/arrow/test_arrow_recordbatchreader.py b/tools/pythonpkg/tests/fast/arrow/test_arrow_recordbatchreader.py index 05325375a3b..0f8a701dbfe 100644 --- a/tools/pythonpkg/tests/fast/arrow/test_arrow_recordbatchreader.py +++ b/tools/pythonpkg/tests/fast/arrow/test_arrow_recordbatchreader.py @@ -1,21 +1,15 @@ import duckdb import os +import pytest -try: - import pyarrow - import pyarrow.parquet - import pyarrow.dataset - import numpy as np - - can_run = True -except: - can_run = False +pyarrow = pytest.importorskip("pyarrow") +pyarrow.parquet = pytest.importorskip("pyarrow.parquet") +pyarrow.dataset = pytest.importorskip("pyarrow.dataset") +np = pytest.importorskip("numpy") class TestArrowRecordBatchReader(object): def test_parallel_reader(self, duckdb_cursor): - if not can_run: - return duckdb_conn = duckdb.connect() duckdb_conn.execute("PRAGMA threads=4") @@ -45,8 +39,6 @@ def test_parallel_reader(self, duckdb_cursor): ) def test_parallel_reader_replacement_scans(self, duckdb_cursor): - if not can_run: - return duckdb_conn = duckdb.connect() duckdb_conn.execute("PRAGMA threads=4") @@ -67,20 +59,18 @@ def test_parallel_reader_replacement_scans(self, duckdb_cursor): assert ( duckdb_conn.execute( - "select count(*) from reader where first_name=\'Jose\' and salary > 134708.82" + "select count(*) r1 from reader where first_name=\'Jose\' and salary > 134708.82" ).fetchone()[0] == 12 ) assert ( duckdb_conn.execute( - "select count(*) from reader where first_name=\'Jose\' and salary > 134708.82" + "select count(*) r2 from reader where first_name=\'Jose\' and salary > 134708.82" ).fetchone()[0] == 0 ) def test_parallel_reader_register(self, duckdb_cursor): - if not can_run: - return duckdb_conn = duckdb.connect() duckdb_conn.execute("PRAGMA threads=4") @@ -115,8 +105,6 @@ def test_parallel_reader_register(self, duckdb_cursor): ) def test_parallel_reader_default_conn(self, duckdb_cursor): - if not can_run: - return parquet_filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data', 'userdata1.parquet') diff --git a/tools/pythonpkg/tests/fast/arrow/test_arrow_run_end_encoding.py b/tools/pythonpkg/tests/fast/arrow/test_arrow_run_end_encoding.py index 99be6ea2eea..fa271674582 100644 --- a/tools/pythonpkg/tests/fast/arrow/test_arrow_run_end_encoding.py +++ b/tools/pythonpkg/tests/fast/arrow/test_arrow_run_end_encoding.py @@ -7,6 +7,29 @@ pc = pytest.importorskip("pyarrow.compute") +def create_list_view(offsets, values): + sizes = [] + for i in range(1, len(offsets)): + assert offsets[i - 1] <= offsets[i] + size = offsets[i] - offsets[i - 1] + sizes.append(size) + # Cut off the last offset + offsets = offsets[:-1] + return pa.ListViewArray.from_arrays(offsets, sizes, values=values) + + +def create_list(offsets, values): + return pa.ListArray.from_arrays(offsets, values=values) + + +def list_constructors(): + result = [] + result.append(create_list) + if hasattr(pa, 'ListViewArray'): + result.append(create_list_view) + return result + + class TestArrowREE(object): @pytest.mark.parametrize( 'query', @@ -216,7 +239,8 @@ def test_arrow_ree_projections(self, duckdb_cursor, projection): actual = duckdb_cursor.query("select {} from res".format(projection)).fetchall() assert expected == actual - def test_arrow_ree_list(self, duckdb_cursor): + @pytest.mark.parametrize('create_list', list_constructors()) + def test_arrow_ree_list(self, duckdb_cursor, create_list): size = 1000 duckdb_cursor.query( """ @@ -252,7 +276,7 @@ def test_arrow_ree_list(self, duckdb_cursor): offset += 10 chunk_length -= 10 - new_array = pa.ListArray.from_arrays(offsets, values=ree) + new_array = create_list(offsets, ree) structured_chunks.append(new_array) structured = pa.chunked_array(structured_chunks) diff --git a/tools/pythonpkg/tests/fast/arrow/test_arrow_string_view.py b/tools/pythonpkg/tests/fast/arrow/test_arrow_string_view.py new file mode 100644 index 00000000000..909af548c65 --- /dev/null +++ b/tools/pythonpkg/tests/fast/arrow/test_arrow_string_view.py @@ -0,0 +1,153 @@ +import duckdb +import pytest +from packaging import version + +pa = pytest.importorskip('pyarrow') + +pytestmark = pytest.mark.skipif( + not hasattr(pa, 'string_view'), reason="This version of PyArrow does not support StringViews" +) + + +# Compares with manually constructed arrow tables +def RoundTripStringView(query, array): + con = duckdb.connect() + con.execute("SET produce_arrow_string_view=True") + arrow_tbl = con.execute(query).arrow() + # Assert that we spit the same as the defined array + arrow_tbl[0].validate(full=True) + assert arrow_tbl[0].combine_chunks().tolist() == array.tolist() + + # Generate an arrow table + # Create a field for the array with a specific data type + field = pa.field('str_val', pa.string_view()) + + # Create a schema for the table using the field + schema = pa.schema([field]) + + # Create a table using the schema and the array + gt_table = pa.Table.from_arrays([array], schema=schema) + arrow_table = con.execute("select * from gt_table").arrow() + assert arrow_tbl[0].combine_chunks().tolist() == array.tolist() + + +def RoundTripDuckDBInternal(query): + con = duckdb.connect() + con.execute("SET produce_arrow_string_view=True") + arrow_tbl = con.execute(query).arrow() + arrow_tbl.validate(full=True) + res = con.execute(query).fetchall() + from_arrow_res = con.execute("FROM arrow_tbl order by str").fetchall() + print(from_arrow_res) + for i in range(len(res) - 1): + assert res[i] == from_arrow_res[i] + + +class TestArrowStringView(object): + # Test Small Inlined String View + def test_inlined_string_view(self): + RoundTripStringView( + "SELECT (i*10^i)::varchar str FROM range(5) tbl(i) ", + pa.array(["0.0", "10.0", "200.0", "3000.0", "40000.0"], type=pa.string_view()), + ) + + # Test Small Inlined String View With Nulls + def test_inlined_string_view_null(self): + RoundTripStringView( + "SELECT (i*10^i)::varchar str FROM range(5) tbl(i) UNION Select NULL Order By str", + pa.array(["0.0", "10.0", "200.0", "3000.0", "40000.0", None], type=pa.string_view()), + ) + + # Test Small Not-Inlined Strings + def test_not_inlined_string_view(self): + RoundTripStringView( + "SELECT 'Imaverybigstringmuchbiggerthanfourbytes' str FROM range(5) tbl(i)", + pa.array( + [ + "Imaverybigstringmuchbiggerthanfourbytes", + "Imaverybigstringmuchbiggerthanfourbytes", + "Imaverybigstringmuchbiggerthanfourbytes", + "Imaverybigstringmuchbiggerthanfourbytes", + "Imaverybigstringmuchbiggerthanfourbytes", + ], + type=pa.string_view(), + ), + ) + + # Test Small Not-Inlined Strings with Null + def test_not_inlined_string_view_with_null(self): + RoundTripStringView( + "SELECT 'Imaverybigstringmuchbiggerthanfourbytes'||i::varchar str FROM range(5) tbl(i) UNION SELECT NULL order by str", + pa.array( + [ + "Imaverybigstringmuchbiggerthanfourbytes0", + "Imaverybigstringmuchbiggerthanfourbytes1", + "Imaverybigstringmuchbiggerthanfourbytes2", + "Imaverybigstringmuchbiggerthanfourbytes3", + "Imaverybigstringmuchbiggerthanfourbytes4", + None, + ], + type=pa.string_view(), + ), + ) + + # Test Mix of Inlined and Not-Inlined Strings with Null + def test_not_inlined_string_view(self): + RoundTripStringView( + "SELECT '8bytestr'||(i*10^i)::varchar str FROM range(5) tbl(i) UNION SELECT NULL order by str", + pa.array( + ["8bytestr0.0", "8bytestr10.0", "8bytestr200.0", "8bytestr3000.0", "8bytestr40000.0", None], + type=pa.string_view(), + ), + ) + + # Test Over-Vector Size + def test_large_string_view_inlined(self): + RoundTripDuckDBInternal('''select * from (SELECT i::varchar str FROM range(10000) tbl(i)) order by str''') + + def test_large_string_view_inlined_with_null(self): + RoundTripDuckDBInternal( + '''select * from (SELECT i::varchar str FROM range(10000) tbl(i) UNION select null) order by str''' + ) + + def test_large_string_view_not_inlined(self): + RoundTripDuckDBInternal( + '''select * from (SELECT 'Imaverybigstringmuchbiggerthanfourbytes'||i::varchar str FROM range(10000) tbl(i) UNION select null) order by str''' + ) + + def test_large_string_view_not_inlined_with_null(self): + RoundTripDuckDBInternal( + '''select * from (SELECT 'Imaverybigstringmuchbiggerthanfourbytes'||i::varchar str FROM range(10000) tbl(i) UNION select null) order by str''' + ) + + def test_large_string_view_mixed_with_null(self): + RoundTripDuckDBInternal( + '''select * from (SELECT i::varchar str FROM range(10000) tbl(i) UNION SELECT 'Imaverybigstringmuchbiggerthanfourbytes'||i::varchar str FROM range(10000) tbl(i) UNION select null) order by str''' + ) + + def test_multiple_data_buffers(self): + arr = pa.array(["Imaverybigstringmuchbiggerthanfourbytes"], type=pa.string_view()) + arr = pa.concat_arrays([arr, arr, arr, arr, arr, arr, arr, arr, arr, arr]) + RoundTripStringView( + "SELECT 'Imaverybigstringmuchbiggerthanfourbytes' str FROM range(10) tbl(i)", + arr, + ) + arr = pa.concat_arrays([arr, arr]) + RoundTripStringView( + "SELECT 'Imaverybigstringmuchbiggerthanfourbytes' str FROM range(20) tbl(i)", + arr, + ) + + def test_large_string_polars(self): + pass + # pl = pytest.importorskip('polars') + # con = duckdb.connect() + # con.execute("SET produce_arrow_string_view=True") + # query = '''select * from (SELECT i::varchar str FROM range(10000) tbl(i) UNION SELECT 'Imaverybigstringmuchbiggerthanfourbytes'||i::varchar str FROM range(10000) tbl(i) UNION select null) order by str''' + # polars_df = con.execute(query).pl() + # result = con.execute(query).fetchall() + # con.register('polars_df', polars_df) + + # result_roundtrip_pl = con.execute("select * from polars_df order by all").fetchall() + + # assert result == result_roundtrip_pl diff --git a/tools/pythonpkg/tests/fast/arrow/test_filter_pushdown.py b/tools/pythonpkg/tests/fast/arrow/test_filter_pushdown.py index cb61d4a4af1..95df94d28e1 100644 --- a/tools/pythonpkg/tests/fast/arrow/test_filter_pushdown.py +++ b/tools/pythonpkg/tests/fast/arrow/test_filter_pushdown.py @@ -855,7 +855,7 @@ def test_nested_struct_filter_pushdown(self, duckdb_cursor, create_table): ) match = re.search( - ".*ARROW_SCAN.*Filters: s\\.d\\.f=bar AND s\\.d.*\\.f IS NOT NULL.*", + ".*ARROW_SCAN.*Filters: s\\.d\\.f='bar' AND s.*\\.d\\.f IS NOT NULL.*", query_res.fetchone()[1], flags=re.DOTALL, ) diff --git a/tools/pythonpkg/tests/fast/arrow/test_nested_arrow.py b/tools/pythonpkg/tests/fast/arrow/test_nested_arrow.py index 9c6ceb06b4f..82eddf70637 100644 --- a/tools/pythonpkg/tests/fast/arrow/test_nested_arrow.py +++ b/tools/pythonpkg/tests/fast/arrow/test_nested_arrow.py @@ -1,20 +1,17 @@ import duckdb -try: - import pyarrow as pa - import pyarrow.parquet - import numpy as np - import pandas as pd - import pytest +import pytest - can_run = True -except: - can_run = False +pa = pytest.importorskip("pyarrow") +pq = pytest.importorskip("pyarrow.parquet") +np = pytest.importorskip("numpy") +pd = pytest.importorskip("pandas") def compare_results(duckdb_cursor, query): true_answer = duckdb_cursor.query(query).fetchall() - from_arrow = duckdb.from_arrow(duckdb_cursor.query(query).arrow()).fetchall() + produced_arrow = duckdb_cursor.query(query).arrow() + from_arrow = duckdb_cursor.from_arrow(produced_arrow).fetchall() assert true_answer == from_arrow @@ -22,11 +19,16 @@ def arrow_to_pandas(duckdb_cursor, query): return duckdb_cursor.query(query).arrow().to_pandas()['a'].values.tolist() +def get_use_list_view_options(): + result = [] + result.append(False) + if hasattr(pa, 'ListViewArray'): + result.append(True) + return result + + class TestArrowNested(object): def test_lists_basic(self, duckdb_cursor): - if not can_run: - return - # Test Constant List query = duckdb_cursor.query("SELECT a from (select list_value(3,5,10) as a) as t").arrow()['a'].to_numpy() assert query[0][0] == 3 @@ -42,32 +44,32 @@ def test_lists_basic(self, duckdb_cursor): assert query[0][0] == 3 assert np.isnan(query[0][1]) - def test_list_types(self, duckdb_cursor): - if not can_run: - return + @pytest.mark.parametrize('use_list_view', get_use_list_view_options()) + def test_list_types(self, duckdb_cursor, use_list_view): + duckdb_cursor.execute(f"pragma arrow_output_list_view={use_list_view};") # Large Lists - data = pyarrow.array([[1], None, [2]], type=pyarrow.large_list(pyarrow.int64())) + data = pa.array([[1], None, [2]], type=pa.large_list(pa.int64())) arrow_table = pa.Table.from_arrays([data], ['a']) - rel = duckdb.from_arrow(arrow_table) + rel = duckdb_cursor.from_arrow(arrow_table) res = rel.execute().fetchall() assert res == [([1],), (None,), ([2],)] # Fixed Size Lists - data = pyarrow.array([[1], None, [2]], type=pyarrow.list_(pyarrow.int64(), 1)) + data = pa.array([[1], None, [2]], type=pa.list_(pa.int64(), 1)) arrow_table = pa.Table.from_arrays([data], ['a']) - rel = duckdb.from_arrow(arrow_table) + rel = duckdb_cursor.from_arrow(arrow_table) res = rel.execute().fetchall() assert res == [((1,),), (None,), ((2,),)] # Complex nested structures with different list types data = [ - pyarrow.array([[1], None, [2]], type=pyarrow.list_(pyarrow.int64(), 1)), - pyarrow.array([[1], None, [2]], type=pyarrow.large_list(pyarrow.int64())), - pyarrow.array([[1, 2, 3], None, [2, 1]], type=pyarrow.list_(pyarrow.int64())), + pa.array([[1], None, [2]], type=pa.list_(pa.int64(), 1)), + pa.array([[1], None, [2]], type=pa.large_list(pa.int64())), + pa.array([[1, 2, 3], None, [2, 1]], type=pa.list_(pa.int64())), ] arrow_table = pa.Table.from_arrays([data[0], data[1], data[2]], ['a', 'b', 'c']) - rel = duckdb.from_arrow(arrow_table) + rel = duckdb_cursor.from_arrow(arrow_table) res = rel.project('a').execute().fetchall() assert res == [((1,),), (None,), ((2,),)] res = rel.project('b').execute().fetchall() @@ -78,7 +80,7 @@ def test_list_types(self, duckdb_cursor): # Struct Holding different List Types struct = [pa.StructArray.from_arrays(data, ['fixed', 'large', 'normal'])] arrow_table = pa.Table.from_arrays(struct, ['a']) - rel = duckdb.from_arrow(arrow_table) + rel = duckdb_cursor.from_arrow(arrow_table) res = rel.execute().fetchall() assert res == [ ({'fixed': (1,), 'large': [1], 'normal': [1, 2, 3]},), @@ -86,9 +88,10 @@ def test_list_types(self, duckdb_cursor): ({'fixed': (2,), 'large': [2], 'normal': [2, 1]},), ] - def test_lists_roundtrip(self, duckdb_cursor): - if not can_run: - return + @pytest.mark.parametrize('use_list_view', get_use_list_view_options()) + def test_lists_roundtrip(self, duckdb_cursor, use_list_view): + duckdb_cursor.execute(f"pragma arrow_output_list_view={use_list_view};") + # Integers compare_results(duckdb_cursor, "SELECT a from (select list_value(3,5,10) as a) as t") compare_results(duckdb_cursor, "SELECT a from (select list_value(3,5,NULL) as a) as t") @@ -129,9 +132,10 @@ def test_lists_roundtrip(self, duckdb_cursor): "SELECT list(st order by st) from (select i, case when i%10 then NULL else i::VARCHAR end as st from range(1000) tbl(i)) as t group by i%5 order by all", ) - def test_struct_roundtrip(self, duckdb_cursor): - if not can_run: - return + @pytest.mark.parametrize('use_list_view', get_use_list_view_options()) + def test_struct_roundtrip(self, duckdb_cursor, use_list_view): + duckdb_cursor.execute(f"pragma arrow_output_list_view={use_list_view};") + compare_results(duckdb_cursor, "SELECT a from (SELECT STRUCT_PACK(a := 42, b := 43) as a) as t") compare_results(duckdb_cursor, "SELECT a from (SELECT STRUCT_PACK(a := NULL, b := 43) as a) as t") compare_results(duckdb_cursor, "SELECT a from (SELECT STRUCT_PACK(a := NULL) as a) as t") @@ -143,9 +147,10 @@ def test_struct_roundtrip(self, duckdb_cursor): "SELECT a from (SELECT STRUCT_PACK(a := LIST_VALUE(1,2,3), b := i) as a FROM range(10000) tbl(i)) as t", ) - def test_map_roundtrip(self, duckdb_cursor): - if not can_run: - return + @pytest.mark.parametrize('use_list_view', get_use_list_view_options()) + def test_map_roundtrip(self, duckdb_cursor, use_list_view): + duckdb_cursor.execute(f"pragma arrow_output_list_view={use_list_view};") + compare_results( duckdb_cursor, "SELECT a from (select MAP(LIST_VALUE(1, 2, 3, 4),LIST_VALUE(10, 9, 8, 7)) as a) as t" ) @@ -171,9 +176,10 @@ def test_map_roundtrip(self, duckdb_cursor): "SELECT m from (select MAP(lsta,lstb) as m from (SELECT list(i) as lsta, list(i) as lstb from range(10000) tbl(i) group by i%5 order by all) as lst_tbl) as T", ) - def test_map_arrow_to_duckdb(self, duckdb_cursor): - if not can_run: - return + @pytest.mark.parametrize('use_list_view', get_use_list_view_options()) + def test_map_arrow_to_duckdb(self, duckdb_cursor, use_list_view): + duckdb_cursor.execute(f"pragma arrow_output_list_view={use_list_view};") + map_type = pa.map_(pa.int32(), pa.int32()) values = [[(3, 12), (3, 21)], [(5, 42)]] arrow_table = pa.table({'detail': pa.array(values, map_type)}) @@ -181,20 +187,18 @@ def test_map_arrow_to_duckdb(self, duckdb_cursor): duckdb.InvalidInputException, match="Arrow map contains duplicate key, which isn't supported by DuckDB map type", ): - rel = duckdb.from_arrow(arrow_table).fetchall() + rel = duckdb_cursor.from_arrow(arrow_table).fetchall() def test_null_map_arrow_to_duckdb(self, duckdb_cursor): - if not can_run: - return map_type = pa.map_(pa.int32(), pa.int32()) values = [None, [(5, 42)]] arrow_table = pa.table({'detail': pa.array(values, map_type)}) res = duckdb_cursor.sql("select * from arrow_table").fetchall() assert res == [(None,), ({'key': [5], 'value': [42]},)] - def test_map_arrow_to_pandas(self, duckdb_cursor): - if not can_run: - return + @pytest.mark.parametrize('use_list_view', get_use_list_view_options()) + def test_map_arrow_to_pandas(self, duckdb_cursor, use_list_view): + duckdb_cursor.execute(f"pragma arrow_output_list_view={use_list_view};") assert arrow_to_pandas( duckdb_cursor, "SELECT a from (select MAP(LIST_VALUE(1, 2, 3, 4),LIST_VALUE(10, 9, 8, 7)) as a) as t" ) == [[(1, 10), (2, 9), (3, 8), (4, 7)]] @@ -211,9 +215,10 @@ def test_map_arrow_to_pandas(self, duckdb_cursor): "SELECT MAP(LIST_VALUE({'i':1,'j':2},{'i':3,'j':4}),LIST_VALUE({'i':1,'j':2},{'i':3,'j':4})) as a", ) == [[({'i': 1, 'j': 2}, {'i': 1, 'j': 2}), ({'i': 3, 'j': 4}, {'i': 3, 'j': 4})]] - def test_frankstein_nested(self, duckdb_cursor): - if not can_run: - return + @pytest.mark.parametrize('use_list_view', get_use_list_view_options()) + def test_frankstein_nested(self, duckdb_cursor, use_list_view): + duckdb_cursor.execute(f"pragma arrow_output_list_view={use_list_view};") + # List of structs W/ Struct that is NULL entirely compare_results(duckdb_cursor, "SELECT [{'i':1,'j':2},NULL,{'i':2,'j':NULL}]") diff --git a/tools/pythonpkg/tests/fast/arrow/test_polars.py b/tools/pythonpkg/tests/fast/arrow/test_polars.py index 9dc86de43d2..78c74564e09 100644 --- a/tools/pythonpkg/tests/fast/arrow/test_polars.py +++ b/tools/pythonpkg/tests/fast/arrow/test_polars.py @@ -50,3 +50,10 @@ def test_register_polars(self, duckdb_cursor): con.register('polars_df', df.lazy()) polars_result = con.execute('select * from polars_df').pl() pl_testing.assert_frame_equal(df, polars_result) + + def test_empty_polars_dataframe(self, duckdb_cursor): + polars_empty_df = pl.DataFrame() + with pytest.raises( + duckdb.InvalidInputException, match='Provided table/dataframe must have at least one column' + ): + duckdb_cursor.sql("from polars_empty_df") diff --git a/tools/pythonpkg/tests/fast/pandas/test_df_analyze.py b/tools/pythonpkg/tests/fast/pandas/test_df_analyze.py index 578cb2fee72..114f8e3fb82 100644 --- a/tools/pythonpkg/tests/fast/pandas/test_df_analyze.py +++ b/tools/pythonpkg/tests/fast/pandas/test_df_analyze.py @@ -14,7 +14,7 @@ class TestResolveObjectColumns(object): def test_sample_low_correct(self, duckdb_cursor, pandas): print(pandas.backend) duckdb_conn = duckdb.connect() - duckdb_conn.execute("SET GLOBAL pandas_analyze_sample=3") + duckdb_conn.execute("SET pandas_analyze_sample=3") data = [1000008, 6, 9, 4, 1, 6] df = create_generic_dataframe(data, pandas) roundtripped_df = duckdb.query_df(df, "x", "select * from x", connection=duckdb_conn).df() @@ -24,7 +24,7 @@ def test_sample_low_correct(self, duckdb_cursor, pandas): @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) def test_sample_low_incorrect_detected(self, duckdb_cursor, pandas): duckdb_conn = duckdb.connect() - duckdb_conn.execute("SET GLOBAL pandas_analyze_sample=2") + duckdb_conn.execute("SET pandas_analyze_sample=2") # size of list (6) divided by 'pandas_analyze_sample' (2) is the increment used # in this case index 0 (1000008) and index 3 ([4]) are checked, which dont match data = [1000008, 6, 9, [4], 1, 6] @@ -37,7 +37,7 @@ def test_sample_low_incorrect_detected(self, duckdb_cursor, pandas): def test_sample_zero(self, duckdb_cursor, pandas): duckdb_conn = duckdb.connect() # Disable dataframe analyze - duckdb_conn.execute("SET GLOBAL pandas_analyze_sample=0") + duckdb_conn.execute("SET pandas_analyze_sample=0") data = [1000008, 6, 9, 3, 1, 6] df = create_generic_dataframe(data, pandas) roundtripped_df = duckdb.query_df(df, "x", "select * from x", connection=duckdb_conn).df() @@ -50,13 +50,21 @@ def test_sample_zero(self, duckdb_cursor, pandas): @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) def test_sample_low_incorrect_undetected(self, duckdb_cursor, pandas): duckdb_conn = duckdb.connect() - duckdb_conn.execute("SET GLOBAL pandas_analyze_sample=1") + duckdb_conn.execute("SET pandas_analyze_sample=1") data = [1000008, 6, 9, [4], [1], 6] df = create_generic_dataframe(data, pandas) # Sample size is too low to detect the mismatch, exception is raised when trying to convert with pytest.raises(duckdb.InvalidInputException, match="Failed to cast value: Unimplemented type for cast"): roundtripped_df = duckdb.query_df(df, "x", "select * from x", connection=duckdb_conn).df() + def test_reset_analyze_sample_setting(self, duckdb_cursor): + duckdb_cursor.execute("SET pandas_analyze_sample=5") + res = duckdb_cursor.execute("select current_setting('pandas_analyze_sample')").fetchall() + assert res == [(5,)] + duckdb_cursor.execute("reset pandas_analyze_sample") + res = duckdb_cursor.execute("select current_setting('pandas_analyze_sample')").fetchall() + assert res == [(1000,)] + @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) def test_10750(self, duckdb_cursor, pandas): max_row_number = 2000 diff --git a/tools/pythonpkg/tests/fast/pandas/test_df_object_resolution.py b/tools/pythonpkg/tests/fast/pandas/test_df_object_resolution.py index 1a07e47fc8f..f2b5a98a352 100644 --- a/tools/pythonpkg/tests/fast/pandas/test_df_object_resolution.py +++ b/tools/pythonpkg/tests/fast/pandas/test_df_object_resolution.py @@ -1,6 +1,7 @@ import duckdb import datetime import numpy as np +import platform import pytest import decimal import math @@ -528,6 +529,10 @@ def test_double_object_conversion(self, pandas, duckdb_cursor): assert isinstance(converted_col['0'].dtype, double_dtype.__class__) == True @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) + @pytest.mark.xfail( + condition=platform.system() == "Emscripten", + reason="older numpy raises a warning when running with Pyodide", + ) def test_numpy_object_with_stride(self, pandas, duckdb_cursor): df = pandas.DataFrame(columns=["idx", "evens", "zeros"]) diff --git a/tools/pythonpkg/tests/fast/pandas/test_pandas_category.py b/tools/pythonpkg/tests/fast/pandas/test_pandas_category.py index 848412a9910..59e28c907bd 100644 --- a/tools/pythonpkg/tests/fast/pandas/test_pandas_category.py +++ b/tools/pythonpkg/tests/fast/pandas/test_pandas_category.py @@ -104,6 +104,18 @@ def test_category_string_uint8(self, duckdb_cursor): category.append(str(i)) check_create_table(category) + def test_empty_categorical(self, duckdb_cursor): + empty_categoric_df = pd.DataFrame({'category': pd.Series(dtype='category')}) + duckdb_cursor.execute("CREATE TABLE test AS SELECT * FROM empty_categoric_df") + res = duckdb_cursor.table('test').fetchall() + assert res == [] + + with pytest.raises(duckdb.ConversionException, match="Could not convert string 'test' to UINT8"): + duckdb_cursor.execute("insert into test VALUES('test')") + duckdb_cursor.execute("insert into test VALUES(NULL)") + res = duckdb_cursor.table('test').fetchall() + assert res == [(None,)] + def test_category_fetch_df_chunk(self, duckdb_cursor): con = duckdb.connect() categories = ['foo', 'bla', None, 'zoo', 'foo', 'foo', None, 'bla'] diff --git a/tools/pythonpkg/tests/fast/pandas/test_pandas_na.py b/tools/pythonpkg/tests/fast/pandas/test_pandas_na.py index fb102f9bd1a..97705033abe 100644 --- a/tools/pythonpkg/tests/fast/pandas/test_pandas_na.py +++ b/tools/pythonpkg/tests/fast/pandas/test_pandas_na.py @@ -2,6 +2,7 @@ import datetime import duckdb import pytest +from conftest import NumpyPandas, ArrowPandas def assert_nullness(items, null_indices): @@ -13,6 +14,18 @@ def assert_nullness(items, null_indices): class TestPandasNA(object): + @pytest.mark.parametrize('rows', [100, duckdb.__standard_vector_size__, 5000, 1000000]) + @pytest.mark.parametrize('pd', [NumpyPandas(), ArrowPandas()]) + def test_pandas_string_null(self, duckdb_cursor, rows, pd): + df: pd.DataFrame = pd.DataFrame(index=np.arange(rows)) + df["string_column"] = pd.Series(dtype="string") + e_df_rel = duckdb_cursor.from_df(df) + assert e_df_rel.types == ['VARCHAR'] + roundtrip = e_df_rel.df() + assert roundtrip['string_column'].dtype == 'object' + expected = pd.DataFrame({'string_column': [None for _ in range(rows)]}) + pd.testing.assert_frame_equal(expected, roundtrip) + def test_pandas_na(self, duckdb_cursor): pd = pytest.importorskip('pandas', minversion='1.0.0', reason='Support for pandas.NA has not been added yet') # DataFrame containing a single pd.NA @@ -28,17 +41,17 @@ def test_pandas_na(self, duckdb_cursor): items = [x[0] for x in [y for y in res]] assert_nullness(items, [null_index]) - # Test if pd.NA behaves the same as np.NaN once converted + # Test if pd.NA behaves the same as np.nan once converted nan_df = pd.DataFrame( { 'a': [ 1.123, 5.23234, - np.NaN, + np.nan, 7234.0000124, 0.000000124, 0000000000000.0000001, - np.NaN, + np.nan, -2342349234.00934580345, ] } diff --git a/tools/pythonpkg/tests/fast/pandas/test_pandas_object.py b/tools/pythonpkg/tests/fast/pandas/test_pandas_object.py index ebfd2e93308..c00fcbc2293 100644 --- a/tools/pythonpkg/tests/fast/pandas/test_pandas_object.py +++ b/tools/pythonpkg/tests/fast/pandas/test_pandas_object.py @@ -6,6 +6,19 @@ class TestPandasObject(object): + def test_object_lotof_nulls(self): + # Test mostly null column + data = [None] + [1] + [None] * 10000 # Last element is 1, others are None + pandas_df = pd.DataFrame(data, columns=['c'], dtype=object) + con = duckdb.connect() + assert con.execute('FROM pandas_df where c is not null').fetchall() == [(1.0,)] + + # Test all nulls, should return varchar + data = [None] * 10000 # Last element is 1, others are None + pandas_df_2 = pd.DataFrame(data, columns=['c'], dtype=object) + assert con.execute('FROM pandas_df_2 limit 1').fetchall() == [(None,)] + assert con.execute('select typeof(c) FROM pandas_df_2 limit 1').fetchall() == [('"NULL"',)] + def test_object_to_string(self, duckdb_cursor): con = duckdb.connect(database=':memory:', read_only=False) x = pd.DataFrame([[1, 'a', 2], [1, None, 2], [1, 1.1, 2], [1, 1.1, 2], [1, 1.1, 2]]) diff --git a/tools/pythonpkg/tests/fast/pandas/test_stride.py b/tools/pythonpkg/tests/fast/pandas/test_stride.py index e8968ee793e..5efe8d56a56 100644 --- a/tools/pythonpkg/tests/fast/pandas/test_stride.py +++ b/tools/pythonpkg/tests/fast/pandas/test_stride.py @@ -1,6 +1,7 @@ import pandas as pd import duckdb import numpy as np +import datetime class TestPandasStride(object): @@ -20,6 +21,42 @@ def test_stride_fp32(self, duckdb_cursor): assert str(output_df[col].dtype) == 'float32' pd.testing.assert_frame_equal(expected_df, output_df) + def test_stride_datetime(self, duckdb_cursor): + df = pd.DataFrame({'date': pd.Series(pd.date_range("2024-01-01", freq="D", periods=100))}) + df = df.loc[::23,] + + roundtrip = duckdb_cursor.sql("select * from df").df() + expected = pd.DataFrame( + { + 'date': [ + datetime.datetime(2024, 1, 1), + datetime.datetime(2024, 1, 24), + datetime.datetime(2024, 2, 16), + datetime.datetime(2024, 3, 10), + datetime.datetime(2024, 4, 2), + ] + } + ) + pd.testing.assert_frame_equal(roundtrip, expected) + + def test_stride_timedelta(self, duckdb_cursor): + df = pd.DataFrame({'date': [datetime.timedelta(days=i) for i in range(100)]}) + df = df.loc[::23,] + + roundtrip = duckdb_cursor.sql("select * from df").df() + expected = pd.DataFrame( + { + 'date': [ + datetime.timedelta(days=0), + datetime.timedelta(days=23), + datetime.timedelta(days=46), + datetime.timedelta(days=69), + datetime.timedelta(days=92), + ] + } + ) + pd.testing.assert_frame_equal(roundtrip, expected) + def test_stride_fp64(self, duckdb_cursor): expected_df = pd.DataFrame(np.arange(20, dtype='float64').reshape(5, 4), columns=["a", "b", "c", "d"]) con = duckdb.connect() diff --git a/tools/pythonpkg/tests/fast/pandas/test_timedelta.py b/tools/pythonpkg/tests/fast/pandas/test_timedelta.py index 843c47f2df6..5c6aa4b959d 100644 --- a/tools/pythonpkg/tests/fast/pandas/test_timedelta.py +++ b/tools/pythonpkg/tests/fast/pandas/test_timedelta.py @@ -1,7 +1,7 @@ +import platform import pandas as pd import duckdb import datetime -import numpy as np import pytest @@ -47,6 +47,7 @@ def test_timedelta_negative(self, duckdb_cursor): @pytest.mark.parametrize('minutes', [0, 60]) @pytest.mark.parametrize('hours', [0, 24]) @pytest.mark.parametrize('weeks', [0, 51]) + @pytest.mark.skipif(platform.system() == "Emscripten", reason="Bind parameters are broken when running on Pyodide") def test_timedelta_coverage(self, duckdb_cursor, days, seconds, microseconds, milliseconds, minutes, hours, weeks): def create_duck_interval(days, seconds, microseconds, milliseconds, minutes, hours, weeks) -> str: instant = f""" diff --git a/tools/pythonpkg/tests/fast/pandas/test_timestamp.py b/tools/pythonpkg/tests/fast/pandas/test_timestamp.py index 51641e281a3..0a580025fa6 100644 --- a/tools/pythonpkg/tests/fast/pandas/test_timestamp.py +++ b/tools/pythonpkg/tests/fast/pandas/test_timestamp.py @@ -1,8 +1,9 @@ import duckdb -import os import datetime +import os import pytest import pandas as pd +import platform from conftest import pandas_2_or_higher @@ -64,6 +65,10 @@ def test_timestamp_timedelta(self): df_from_duck = duckdb.from_df(df).df() assert df_from_duck.equals(df) + @pytest.mark.xfail( + condition=platform.system() == "Emscripten" and os.environ.get("TZ") != "UTC", + reason="time zones other than UTC don't seem to work on Pyodide", + ) def test_timestamp_timezone(self, duckdb_cursor): rel = duckdb_cursor.query( """ diff --git a/tools/pythonpkg/tests/fast/relational_api/test_rapi_query.py b/tools/pythonpkg/tests/fast/relational_api/test_rapi_query.py index 5fdbae2f9f6..9707dc36832 100644 --- a/tools/pythonpkg/tests/fast/relational_api/test_rapi_query.py +++ b/tools/pythonpkg/tests/fast/relational_api/test_rapi_query.py @@ -1,14 +1,16 @@ import duckdb import pytest +import platform +import sys @pytest.fixture() def tbl_table(): con = duckdb.default_connection - con.execute("drop table if exists tbl") + con.execute("drop table if exists tbl CASCADE") con.execute("create table tbl (i integer)") yield - con.execute('drop table tbl') + con.execute('drop table tbl CASCADE') class TestRAPIQuery(object): @@ -117,13 +119,15 @@ def test_query_non_select_result(self, duckdb_cursor): def test_replacement_scan_recursion(self, duckdb_cursor): depth_limit = 1000 - import sys - if sys.platform.startswith('win'): - # With the default we reach a stack overflow in the CI + if sys.platform.startswith('win') or platform.system() == "Emscripten": + # With the default we reach a stack overflow in the CI for windows + # and also outside of it for Pyodide depth_limit = 250 + duckdb_cursor.execute(f"SET max_expression_depth TO {depth_limit}") - rel = duckdb_cursor.sql('select 42') - rel = duckdb_cursor.sql('select * from rel') - with pytest.raises(duckdb.BinderException, match=f'Max expression depth limit of {depth_limit} exceeded'): - duckdb_cursor.sql('select * from rel') + rel = duckdb_cursor.sql('select 42 a, 21 b') + rel = duckdb_cursor.sql('select a+a a, b+b b from rel') + other_rel = duckdb_cursor.sql('select a from rel') + res = other_rel.fetchall() + assert res == [(84,)] diff --git a/tools/pythonpkg/tests/fast/relational_api/test_table_function.py b/tools/pythonpkg/tests/fast/relational_api/test_table_function.py new file mode 100644 index 00000000000..4f4a1016bb1 --- /dev/null +++ b/tools/pythonpkg/tests/fast/relational_api/test_table_function.py @@ -0,0 +1,17 @@ +import duckdb +import pytest +import os + +script_path = os.path.dirname(__file__) + + +class TestTableFunction(object): + def test_table_function(self, duckdb_cursor): + path = os.path.join(script_path, '..', 'data/integers.csv') + rel = duckdb_cursor.table_function('read_csv', [path]) + res = rel.fetchall() + assert res == [(1, 10, 0), (2, 50, 30)] + + # Provide only a string as argument, should error, needs a list + with pytest.raises(duckdb.InvalidInputException, match=r"'params' has to be a list of parameters"): + rel = duckdb_cursor.table_function('read_csv', path) diff --git a/tools/pythonpkg/tests/fast/spark/test_spark_drop_duplicates.py b/tools/pythonpkg/tests/fast/spark/test_spark_drop_duplicates.py index 5f5c2e447c9..465af91cd66 100644 --- a/tools/pythonpkg/tests/fast/spark/test_spark_drop_duplicates.py +++ b/tools/pythonpkg/tests/fast/spark/test_spark_drop_duplicates.py @@ -1,22 +1,11 @@ import pytest -_ = pytest.importorskip("duckdb.experimental.spark") from duckdb.experimental.spark.sql.types import ( - LongType, - StructType, - BooleanType, - StructField, - StringType, - IntegerType, - LongType, Row, - ArrayType, - MapType, ) -from duckdb.experimental.spark.sql.functions import col, struct, when, lit, array_contains -import duckdb -import re + +_ = pytest.importorskip("duckdb.experimental.spark") class TestDataFrameDropDuplicates(object): @@ -61,9 +50,38 @@ def test_spark_drop_duplicates(self, spark): res2 = df2.collect() assert res2 == res - with pytest.raises(NotImplementedError): - # DuckDBPyRelation does not have 'distinct_on' support yet - dropDisDF = df.dropDuplicates(["department", "salary"]) - print("Distinct count of department & salary : " + str(dropDisDF.count())) - res = dropDisDF.collect() - print(res) + expected_subset = [ + Row(department='Finance', salary=3000), + Row(department='Finance', salary=3300), + Row(department='Finance', salary=3900), + Row(department='Marketing', salary=2000), + Row(department='Marketing', salary=3000), + Row(epartment='Sales', salary=3000), + Row(department='Sales', salary=4100), + Row(department='Sales', salary=4600), + ] + + dropDisDF = df.dropDuplicates(["department", "salary"]).sort("department", "salary") + assert dropDisDF.columns == ["employee_name", "department", "salary"] + assert dropDisDF.count() == len(expected_subset) + res = dropDisDF.select("department", "salary").collect() + assert res == expected_subset + + def test_spark_drop_duplicates_with_keywords_cols(self, spark): + data = [ + ("abc", 1, ""), + ("abc", 1, ""), + ("def", 2, ""), + ("def", 2, ""), + ("def", 2, ""), + ("def", 3, ""), + ("def", 3, ""), + ("def", 3, ""), + ("def", 3, ""), + ] + + columns = ["table", "min", "null"] + df = spark.createDataFrame(data=data, schema=columns) + + dropDisDF = df.dropDuplicates(["table", "min"]).sort("table", "min") + assert dropDisDF.count() == 3 diff --git a/tools/pythonpkg/tests/fast/spark/test_spark_functions_date.py b/tools/pythonpkg/tests/fast/spark/test_spark_functions_date.py new file mode 100644 index 00000000000..1da7c73bb07 --- /dev/null +++ b/tools/pythonpkg/tests/fast/spark/test_spark_functions_date.py @@ -0,0 +1,140 @@ +import pytest + +_ = pytest.importorskip("duckdb.experimental.spark") +from datetime import date, datetime + +from duckdb.experimental.spark.sql import functions as F +from duckdb.experimental.spark.sql.types import Row + + +class TestsSparkFunctionsDate(object): + def test_date_trunc(self, spark): + df = spark.createDataFrame( + [(datetime(2019, 1, 23, 14, 34, 9, 87539),)], + ["dt_ref"], + ) + + expected = [ + { + "year": datetime(2019, 1, 1, 0, 0, 0, 0), + "yyyy": datetime(2019, 1, 1, 0, 0, 0, 0), + "yy": datetime(2019, 1, 1, 0, 0, 0, 0), + "quarter": datetime(2019, 1, 1, 0, 0, 0, 0), + "month": datetime(2019, 1, 1, 0, 0, 0, 0), + "mon": datetime(2019, 1, 1, 0, 0, 0, 0), + "mm": datetime(2019, 1, 1, 0, 0, 0, 0), + "week": datetime(2019, 1, 21, 0, 0, 0, 0), + "day": datetime(2019, 1, 23, 0, 0, 0, 0), + "dd": datetime(2019, 1, 23, 0, 0, 0, 0), + "hour": datetime(2019, 1, 23, 14, 0, 0, 0), + "minute": datetime(2019, 1, 23, 14, 34, 0, 0), + "second": datetime(2019, 1, 23, 14, 34, 9, 0), + } + ] + + cols = list(expected[0].keys()) + gen_record = df.select(*[F.date_trunc(fmt, "dt_ref").alias(fmt) for fmt in cols]).collect()[0] + + expected_record = spark.createDataFrame( + [r.values() for r in expected], + cols, + ).collect()[0] + + assert gen_record.year.timetuple() == expected_record.year.timetuple() + assert gen_record.yyyy.timetuple() == expected_record.yyyy.timetuple() + assert gen_record.yy.timetuple() == expected_record.yy.timetuple() + assert gen_record.quarter.timetuple() == expected_record.quarter.timetuple() + assert gen_record.month.timetuple() == expected_record.month.timetuple() + assert gen_record.mon.timetuple() == expected_record.mon.timetuple() + assert gen_record.mm.timetuple() == expected_record.mm.timetuple() + assert gen_record.week.timetuple() == expected_record.week.timetuple() + assert gen_record.day.timetuple() == expected_record.day.timetuple() + assert gen_record.dd.timetuple() == expected_record.dd.timetuple() + assert gen_record.hour.timetuple() == expected_record.hour.timetuple() + assert gen_record.minute.timetuple() == expected_record.minute.timetuple() + assert gen_record.second.timetuple() == expected_record.second.timetuple() + + def test_date_part(self, spark): + df = spark.createDataFrame([(datetime(2015, 4, 8, 13, 8, 15),)], ["ts"]) + result = df.select( + F.date_part(F.lit("YEAR"), "ts").alias("year"), + F.date_part(F.lit("month"), "ts").alias("month"), + F.date_part(F.lit("WEEK"), "ts").alias("week"), + F.date_part(F.lit("D"), "ts").alias("day"), + F.date_part(F.lit("M"), "ts").alias("minute"), + F.date_part(F.lit("S"), "ts").alias("second"), + ).collect() + + expected = [Row(year=2015, month=4, week=15, day=8, minute=8, second=15)] + + assert result == expected + + def test_dayofweek(self, spark): + spark_sunday_index = 1 + spark_saturday_index = 7 + + df = spark.createDataFrame([(date(2024, 5, 12),), (date(2024, 5, 18),)], ["dt"]) + result = df.select(F.dayofweek("dt").alias("week_num")).collect() + + assert result[0].week_num == spark_sunday_index + assert result[1].week_num == spark_saturday_index + + def test_dayofmonth(self, spark): + df = spark.createDataFrame([(date(2024, 5, 12),), (date(2024, 5, 18),)], ["dt"]) + result = df.select(F.dayofmonth("dt").alias("day_num")).collect() + + assert result[0].day_num == 12 + assert result[1].day_num == 18 + + def test_dayofyear(self, spark): + df = spark.createDataFrame([(date(2024, 5, 12),), (date(2024, 5, 18),)], ["dt"]) + result = df.select(F.dayofyear("dt").alias("day_num")).collect() + + assert result[0].day_num == 133 + assert result[1].day_num == 139 + + def test_month(self, spark): + df = spark.createDataFrame([(date(2024, 5, 12),), (date(2024, 5, 18),)], ["dt"]) + result = df.select(F.month("dt").alias("month_num")).collect() + + assert result[0].month_num == 5 + assert result[1].month_num == 5 + + def test_year(self, spark): + df = spark.createDataFrame([(date(2024, 5, 12),), (date(2024, 5, 18),)], ["dt"]) + result = df.select(F.year("dt").alias("year_num")).collect() + + assert result[0].year_num == 2024 + assert result[1].year_num == 2024 + + def test_weekofyear(self, spark): + df = spark.createDataFrame([(date(2024, 5, 12),), (date(2024, 5, 18),)], ["dt"]) + result = df.select(F.weekofyear("dt").alias("week_num")).collect() + + assert result[0].week_num == 19 + assert result[1].week_num == 20 + + def test_quarter(self, spark): + df = spark.createDataFrame([(date(2024, 5, 12),), (date(2024, 5, 18),)], ["dt"]) + result = df.select(F.quarter("dt").alias("quarter_num")).collect() + + assert result[0].quarter_num == 2 + assert result[1].quarter_num == 2 + + def test_hour(self, spark): + df = spark.createDataFrame([(datetime(2024, 5, 12, 13, 30, 45),)], ["dt"]) + result = df.select(F.hour("dt").alias("hour_num")).collect() + + assert result[0].hour_num == 13 + + def test_minute(self, spark): + df = spark.createDataFrame([(datetime(2024, 5, 12, 13, 30, 45),)], ["dt"]) + result = df.select(F.minute("dt").alias("minute_num")).collect() + + assert result[0].minute_num == 30 + + def test_second(self, spark): + df = spark.createDataFrame([(datetime(2024, 5, 12, 13, 30, 45),)], ["dt"]) + result = df.select(F.second("dt").alias("second_num")).collect() + + assert result[0].second_num == 45 diff --git a/tools/pythonpkg/tests/fast/spark/test_spark_functions_hash.py b/tools/pythonpkg/tests/fast/spark/test_spark_functions_hash.py new file mode 100644 index 00000000000..2f6cff1d06d --- /dev/null +++ b/tools/pythonpkg/tests/fast/spark/test_spark_functions_hash.py @@ -0,0 +1,30 @@ +import pytest + +_ = pytest.importorskip("duckdb.experimental.spark") +from duckdb.experimental.spark.sql import functions as F + + +class TestSparkFunctionsHash(object): + def test_md5(self, spark): + data = [ + ("quack",), + ] + res = ( + spark.createDataFrame(data, ["firstColumn"]) + .withColumn("hashed_value", F.md5(F.col("firstColumn"))) + .select("hashed_value") + .collect() + ) + assert res[0].hashed_value == "cfaf278e8f522c72644cee2a753d2845" + + def test_sha256(self, spark): + data = [ + ("quack",), + ] + res = ( + spark.createDataFrame(data, ["firstColumn"]) + .withColumn("hashed_value", F.sha2(F.col("firstColumn"), 256)) + .select("hashed_value") + .collect() + ) + assert res[0].hashed_value == "82d928273d067d774889d5df4249aaf73c0b04c64f04d6ed001441ce87a0853c" diff --git a/tools/pythonpkg/tests/fast/spark/test_spark_functions_null.py b/tools/pythonpkg/tests/fast/spark/test_spark_functions_null.py new file mode 100644 index 00000000000..941678e422a --- /dev/null +++ b/tools/pythonpkg/tests/fast/spark/test_spark_functions_null.py @@ -0,0 +1,46 @@ +import pytest + +_ = pytest.importorskip("duckdb.experimental.spark") +from duckdb.experimental.spark.sql import functions as F +from duckdb.experimental.spark.sql.types import Row + + +class TestsSparkFunctionsNull(object): + def test_coalesce(self, spark): + data = [ + (None, 2), + (4, None), + ] + df = spark.createDataFrame(data, ["firstColumn", "secondColumn"]) + df = df.withColumn("coalesce_value", F.coalesce(F.col("firstColumn"), F.col("secondColumn"))) + res = df.select("coalesce_value").collect() + assert res == [ + Row(coalesce_value=2), + Row(coalesce_value=4), + ] + + def test_nvl(self, spark): + data = [ + (None, 2), + (4, None), + ] + df = spark.createDataFrame(data, ["firstColumn", "secondColumn"]) + df = df.withColumn("nvl_value", F.nvl(F.col("firstColumn"), F.col("secondColumn"))) + res = df.select("nvl_value").collect() + assert res == [ + Row(nvl_value=2), + Row(nvl_value=4), + ] + + def test_ifnull(self, spark): + data = [ + (None, 2), + (4, None), + ] + df = spark.createDataFrame(data, ["firstColumn", "secondColumn"]) + df = df.withColumn("ifnull_value", F.ifnull(F.col("firstColumn"), F.col("secondColumn"))) + res = df.select("ifnull_value").collect() + assert res == [ + Row(nvl_value=2), + Row(nvl_value=4), + ] diff --git a/tools/pythonpkg/tests/fast/spark/test_spark_numeric_functions.py b/tools/pythonpkg/tests/fast/spark/test_spark_functions_numeric.py similarity index 98% rename from tools/pythonpkg/tests/fast/spark/test_spark_numeric_functions.py rename to tools/pythonpkg/tests/fast/spark/test_spark_functions_numeric.py index 5ca507df778..71922512e93 100644 --- a/tools/pythonpkg/tests/fast/spark/test_spark_numeric_functions.py +++ b/tools/pythonpkg/tests/fast/spark/test_spark_functions_numeric.py @@ -1,11 +1,11 @@ import pytest _ = pytest.importorskip("duckdb.experimental.spark") -from duckdb.experimental.spark.sql.types import Row from duckdb.experimental.spark.sql import functions as F +from duckdb.experimental.spark.sql.types import Row -class TestNumericFunctions(object): +class TestSparkFunctionsNumeric(object): def test_greatest(self, spark): data = [ (1, 2), diff --git a/tools/pythonpkg/tests/fast/spark/test_spark_string_functions.py b/tools/pythonpkg/tests/fast/spark/test_spark_functions_string.py similarity index 98% rename from tools/pythonpkg/tests/fast/spark/test_spark_string_functions.py rename to tools/pythonpkg/tests/fast/spark/test_spark_functions_string.py index 7e45b822bb8..791b48f0164 100644 --- a/tools/pythonpkg/tests/fast/spark/test_spark_string_functions.py +++ b/tools/pythonpkg/tests/fast/spark/test_spark_functions_string.py @@ -1,11 +1,11 @@ import pytest _ = pytest.importorskip("duckdb.experimental.spark") -from duckdb.experimental.spark.sql.types import Row from duckdb.experimental.spark.sql import functions as F +from duckdb.experimental.spark.sql.types import Row -class TestStringFunctions(object): +class TestSparkFunctionsString(object): def test_length(self, spark): data = [ ("firstRowFirstColumn",), diff --git a/tools/pythonpkg/tests/fast/spark/test_spark_join.py b/tools/pythonpkg/tests/fast/spark/test_spark_join.py index e360507cbeb..f1a4a6758aa 100644 --- a/tools/pythonpkg/tests/fast/spark/test_spark_join.py +++ b/tools/pythonpkg/tests/fast/spark/test_spark_join.py @@ -44,8 +44,9 @@ def dataframe_b(spark): class TestDataFrameJoin(object): def test_inner_join(self, dataframe_a, dataframe_b): df = dataframe_a.join(dataframe_b, dataframe_a.emp_dept_id == dataframe_b.dept_id, "inner") + df = df.sort(*df.columns) res = df.collect() - assert res == [ + expected = [ Row( emp_id=1, name='Smith', @@ -102,10 +103,12 @@ def test_inner_join(self, dataframe_a, dataframe_b): dept_id=40, ), ] + assert res == expected @pytest.mark.parametrize('how', ['outer', 'fullouter', 'full', 'full_outer']) def test_outer_join(self, dataframe_a, dataframe_b, how): df = dataframe_a.join(dataframe_b, dataframe_a.emp_dept_id == dataframe_b.dept_id, how) + df = df.sort(*df.columns) res1 = df.collect() assert res1 == [ Row( @@ -190,16 +193,17 @@ def test_outer_join(self, dataframe_a, dataframe_b, how): @pytest.mark.parametrize('how', ['right', 'rightouter', 'right_outer']) def test_right_join(self, dataframe_a, dataframe_b, how): df = dataframe_a.join(dataframe_b, dataframe_a.emp_dept_id == dataframe_b.dept_id, how) + df = df.sort(*df.columns) res = df.collect() assert res == [ Row( - emp_id=4, - name='Jones', - superior_emp_id=2, - year_joined='2005', + emp_id=1, + name='Smith', + superior_emp_id=-1, + year_joined='2018', emp_dept_id='10', - gender='F', - salary=2000, + gender='M', + salary=3000, dept_name='Finance', dept_id=10, ), @@ -214,17 +218,6 @@ def test_right_join(self, dataframe_a, dataframe_b, how): dept_name='Marketing', dept_id=20, ), - Row( - emp_id=5, - name='Brown', - superior_emp_id=2, - year_joined='2010', - emp_dept_id='40', - gender='', - salary=-1, - dept_name='IT', - dept_id=40, - ), Row( emp_id=3, name='Williams', @@ -237,16 +230,27 @@ def test_right_join(self, dataframe_a, dataframe_b, how): dept_id=10, ), Row( - emp_id=1, - name='Smith', - superior_emp_id=-1, - year_joined='2018', + emp_id=4, + name='Jones', + superior_emp_id=2, + year_joined='2005', emp_dept_id='10', - gender='M', - salary=3000, + gender='F', + salary=2000, dept_name='Finance', dept_id=10, ), + Row( + emp_id=5, + name='Brown', + superior_emp_id=2, + year_joined='2010', + emp_dept_id='40', + gender='', + salary=-1, + dept_name='IT', + dept_id=40, + ), Row( emp_id=None, name=None, @@ -263,7 +267,7 @@ def test_right_join(self, dataframe_a, dataframe_b, how): @pytest.mark.parametrize('how', ['semi', 'leftsemi', 'left_semi']) def test_semi_join(self, dataframe_a, dataframe_b, how): df = dataframe_a.join(dataframe_b, dataframe_a.emp_dept_id == dataframe_b.dept_id, how) - df = df.orderBy(*df.columns) + df = df.sort(*df.columns) res = df.collect() assert res == [ Row( @@ -296,7 +300,7 @@ def test_semi_join(self, dataframe_a, dataframe_b, how): @pytest.mark.parametrize('how', ['anti', 'leftanti', 'left_anti']) def test_anti_join(self, dataframe_a, dataframe_b, how): df = dataframe_a.join(dataframe_b, dataframe_a.emp_dept_id == dataframe_b.dept_id, how) - df.orderBy(*df.columns) + df = df.sort(*df.columns) res = df.collect() assert res == [ Row(emp_id=6, name='Brown', superior_emp_id=2, year_joined='2010', emp_dept_id='50', gender='', salary=-1) diff --git a/tools/pythonpkg/tests/fast/spark/test_spark_session.py b/tools/pythonpkg/tests/fast/spark/test_spark_session.py index 3faacedd74b..a4a75a4fa0a 100644 --- a/tools/pythonpkg/tests/fast/spark/test_spark_session.py +++ b/tools/pythonpkg/tests/fast/spark/test_spark_session.py @@ -1,4 +1,8 @@ import pytest +from duckdb.experimental.spark.exception import ( + ContributionsAcceptedError, +) +from duckdb.experimental.spark.sql.types import Row _ = pytest.importorskip("duckdb.experimental.spark") from duckdb.experimental.spark.sql import SparkSession @@ -72,6 +76,18 @@ def test_table(self, spark): spark.sql('create table tbl(a varchar(10))') df = spark.table('tbl') + def test_range(self, spark): + res_1 = spark.range(3).collect() + res_2 = spark.range(3, 10, 2).collect() + res_3 = spark.range(3, 6).collect() + + assert res_1 == [Row(id=0), Row(id=1), Row(id=2)] + assert res_2 == [Row(id=3), Row(id=5), Row(id=7), Row(id=9)] + assert res_3 == [Row(id=3), Row(id=4), Row(id=5)] + + with pytest.raises(ContributionsAcceptedError): + # partition size is not supported + spark.range(0, 10, 2, 2) + def test_udf(self, spark): - with pytest.raises(NotImplementedError): - udf_registration = spark.udf + udf_registration = spark.udf diff --git a/tools/pythonpkg/tests/fast/spark/test_spark_udf.py b/tools/pythonpkg/tests/fast/spark/test_spark_udf.py new file mode 100644 index 00000000000..3b5a5d36dc3 --- /dev/null +++ b/tools/pythonpkg/tests/fast/spark/test_spark_udf.py @@ -0,0 +1,13 @@ +import pytest + +_ = pytest.importorskip("duckdb.experimental.spark") + + +class TestSparkUDF(object): + def test_udf_register(self, spark): + + def to_upper_fn(s: str) -> str: + return s.upper() + + spark.udf.register("to_upper_fn", to_upper_fn) + assert spark.sql("select to_upper_fn('quack') as vl").collect()[0].vl == "QUACK" diff --git a/tools/pythonpkg/tests/fast/spark/test_spark_union.py b/tools/pythonpkg/tests/fast/spark/test_spark_union.py index 7801dea4ada..2399785fafa 100644 --- a/tools/pythonpkg/tests/fast/spark/test_spark_union.py +++ b/tools/pythonpkg/tests/fast/spark/test_spark_union.py @@ -1,21 +1,10 @@ +import platform import pytest _ = pytest.importorskip("duckdb.experimental.spark") -from duckdb.experimental.spark.sql.types import ( - LongType, - StructType, - BooleanType, - StructField, - StringType, - IntegerType, - LongType, - Row, - ArrayType, - MapType, -) -from duckdb.experimental.spark.sql.functions import col, struct, when, lit, array_contains -from duckdb.experimental.spark.sql.functions import sum, avg, max, min, mean, count +from duckdb.experimental.spark.sql.types import Row +from duckdb.experimental.spark.sql.functions import col @pytest.fixture @@ -65,6 +54,7 @@ def test_merge_with_union(self, df, df2): res2 = unionDF.collect() assert res == res2 + @pytest.mark.xfail(condition=platform.system() == "Emscripten", reason="Broken on Pyodide") def test_merge_without_duplicates(self, df, df2): # 'sort' has been added to make the result deterministic disDF = df.union(df2).distinct().sort(col("employee_name")) diff --git a/tools/pythonpkg/tests/fast/test_alex_multithread.py b/tools/pythonpkg/tests/fast/test_alex_multithread.py index 765b8f0ab2b..92768ec0c9a 100644 --- a/tools/pythonpkg/tests/fast/test_alex_multithread.py +++ b/tools/pythonpkg/tests/fast/test_alex_multithread.py @@ -1,10 +1,16 @@ +import platform import duckdb from threading import Thread, current_thread -import pandas as pd -import os import pytest +pytestmark = pytest.mark.xfail( + condition=platform.system() == "Emscripten", + reason="Emscripten builds cannot use threads", + raises=RuntimeError, +) + + @pytest.fixture(scope="session") def tmp_database(tmp_path_factory): database = tmp_path_factory.mktemp("databases", numbered=True) / "tmp.duckdb" diff --git a/tools/pythonpkg/tests/fast/test_all_types.py b/tools/pythonpkg/tests/fast/test_all_types.py index 4a2ceb105a3..41de6e763a8 100644 --- a/tools/pythonpkg/tests/fast/test_all_types.py +++ b/tools/pythonpkg/tests/fast/test_all_types.py @@ -396,15 +396,15 @@ def test_fetchnumpy(self, cur_type): ), # Enums don't have a numpy equivalent and yield pandas Categorical. 'small_enum': pd.Categorical( - ['DUCK_DUCK_ENUM', 'GOOSE', np.NaN], + ['DUCK_DUCK_ENUM', 'GOOSE', np.nan], ordered=True, ), 'medium_enum': pd.Categorical( - ['enum_0', 'enum_299', np.NaN], + ['enum_0', 'enum_299', np.nan], ordered=True, ), 'large_enum': pd.Categorical( - ['enum_0', 'enum_69999', np.NaN], + ['enum_0', 'enum_69999', np.nan], ordered=True, ), # The following types don't have a numpy equivalent and yield diff --git a/tools/pythonpkg/tests/fast/test_expression.py b/tools/pythonpkg/tests/fast/test_expression.py index d44dd4c90bc..457449f1c57 100644 --- a/tools/pythonpkg/tests/fast/test_expression.py +++ b/tools/pythonpkg/tests/fast/test_expression.py @@ -1,10 +1,24 @@ +import platform import duckdb import pytest from duckdb.typing import INTEGER, VARCHAR, TIMESTAMP -from duckdb import Expression, ConstantExpression, ColumnExpression, StarExpression, FunctionExpression, CaseExpression +from duckdb import ( + Expression, + ConstantExpression, + ColumnExpression, + CoalesceOperator, + StarExpression, + FunctionExpression, + CaseExpression, +) from duckdb.value.constant import Value, IntegerValue import datetime +pytestmark = pytest.mark.skipif( + platform.system() == "Emscripten", + reason="Extensions are not supported on Emscripten", +) + @pytest.fixture(scope='function') def filter_rel(): @@ -64,6 +78,110 @@ def test_column_expression(self): with pytest.raises(duckdb.BinderException, match='Referenced column "d" not found'): rel2 = rel.select(column) + def test_coalesce_operator(self): + con = duckdb.connect() + + rel = con.sql( + """ + select 'unused' + """ + ) + + rel2 = rel.select(CoalesceOperator(ConstantExpression(None), ConstantExpression('hello').cast(int))) + res = rel2.explain() + assert 'COALESCE' in res + + with pytest.raises(duckdb.ConversionException, match="Could not convert string 'hello' to INT64"): + rel2.fetchall() + + con.execute( + """ + CREATE TABLE exprtest(a INTEGER, b INTEGER); + INSERT INTO exprtest VALUES (42, 10), (43, 100), (NULL, 1), (45, 0) + """ + ) + + with pytest.raises(duckdb.InvalidInputException, match='Please provide at least one argument'): + rel3 = rel.select(CoalesceOperator()) + + rel4 = rel.select(CoalesceOperator(ConstantExpression(None))) + assert rel4.fetchone() == (None,) + + rel5 = rel.select(CoalesceOperator(ConstantExpression(42))) + assert rel5.fetchone() == (42,) + + exprtest = con.table('exprtest') + rel6 = exprtest.select(CoalesceOperator(ColumnExpression("a"))) + res = rel6.fetchall() + assert res == [(42,), (43,), (None,), (45,)] + + rel7 = con.sql("select 42") + rel7 = rel7.select( + CoalesceOperator( + ConstantExpression(None), ConstantExpression(None), ConstantExpression(42), ConstantExpression(43) + ) + ) + res = rel7.fetchall() + assert res == [(42,)] + + rel7 = con.sql("select 42") + rel7 = rel7.select(CoalesceOperator(ConstantExpression(None), ConstantExpression(None), ConstantExpression(42))) + res = rel7.fetchall() + assert res == [(42,)] + + rel7 = con.sql("select 42") + rel7 = rel7.select(CoalesceOperator(ConstantExpression(None), ConstantExpression(None), ConstantExpression(43))) + res = rel7.fetchall() + assert res == [(43,)] + + rel7 = con.sql("select 42") + rel7 = rel7.select( + CoalesceOperator(ConstantExpression(None), ConstantExpression(None), ConstantExpression(None)) + ) + res = rel7.fetchall() + assert res == [(None,)] + + # These are converted tests + # See 'test_coalesce.test_slow' for the original tests + + con.execute("SET default_null_order='nulls_first';") + + rel7 = exprtest.select( + CoalesceOperator( + ConstantExpression(None), + ConstantExpression(None), + ConstantExpression(None), + ColumnExpression("a"), + ConstantExpression(None), + ColumnExpression("b"), + ) + ) + res = rel7.fetchall() + assert res == [(42,), (43,), (1,), (45,)] + + rel7 = exprtest.filter((ColumnExpression("b") == 1) | (CoalesceOperator("a", "b") == 42)).sort("a") + res = rel7.fetchall() + assert res == [(None, 1), (42, 10)] + + rel7 = exprtest.filter( + (CoalesceOperator("a", "b") == 1) | (CoalesceOperator("a", "b") == 43) | (CoalesceOperator("a", "b") == 45) + ).sort("a") + res = rel7.fetchall() + assert res == [(None, 1), (43, 100), (45, 0)] + + rel7 = exprtest.filter( + (CoalesceOperator("a", "b") == 1) + | (CoalesceOperator("a", "b") == 42) + | (CoalesceOperator("a", "b") == 43) + | (CoalesceOperator("a", "b") == 45) + ).sort("a") + res = rel7.fetchall() + assert res == [(None, 1), (42, 10), (43, 100), (45, 0)] + + rel7 = exprtest.filter((ColumnExpression("b") == 1) | (CoalesceOperator("a", "b") == 1)).sort("a") + res = rel7.fetchall() + assert res == [(None, 1)] + def test_column_expression_explain(self): con = duckdb.connect() diff --git a/tools/pythonpkg/tests/fast/test_memory_leaks.py b/tools/pythonpkg/tests/fast/test_memory_leaks.py index 228a8eace27..1d4c126603e 100644 --- a/tools/pythonpkg/tests/fast/test_memory_leaks.py +++ b/tools/pythonpkg/tests/fast/test_memory_leaks.py @@ -1,9 +1,10 @@ import gc -import duckdb import pytest -import os, psutil +import os import pandas as pd +psutil = pytest.importorskip("psutil") + @pytest.fixture def check_leaks(): diff --git a/tools/pythonpkg/tests/fast/test_multithread.py b/tools/pythonpkg/tests/fast/test_multithread.py index 195b1d1e454..1ffdfc25600 100644 --- a/tools/pythonpkg/tests/fast/test_multithread.py +++ b/tools/pythonpkg/tests/fast/test_multithread.py @@ -1,3 +1,4 @@ +import platform import duckdb import pytest import threading @@ -7,12 +8,11 @@ import os from typing import List -try: - import pyarrow as pa - can_run = True -except ImportError: - can_run = False +pytestmark = pytest.mark.xfail( + condition=platform.system() == "Emscripten", + reason="Emscripten builds cannot use threads", +) def connect_duck(duckdb_conn): @@ -251,6 +251,7 @@ def df_unregister(duckdb_conn, queue, pandas): def arrow_register_unregister(duckdb_conn, queue, pandas): # Get a new connection + pa = pytest.importorskip('pyarrow') duckdb_conn = duckdb.connect() arrow_tbl = pa.Table.from_pydict({'my_column': pa.array([1, 2, 3, 4, 5], type=pa.int64())}) try: @@ -317,6 +318,7 @@ def from_df(duckdb_conn, queue, pandas): def from_arrow(duckdb_conn, queue, pandas): # Get a new connection + pa = pytest.importorskip('pyarrow') duckdb_conn = duckdb.connect() arrow_tbl = pa.Table.from_pydict({'my_column': pa.array([1, 2, 3, 4, 5], type=pa.int64())}) try: @@ -415,15 +417,13 @@ def test_fetchdfchunk(self, duckdb_cursor, pandas): @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) def test_fetcharrow(self, duckdb_cursor, pandas): - if not can_run: - return + pytest.importorskip('pyarrow') duck_threads = DuckDBThreaded(10, fetch_arrow_query, pandas) duck_threads.multithread_test() @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) def test_fetch_record_batch(self, duckdb_cursor, pandas): - if not can_run: - return + pytest.importorskip('pyarrow') duck_threads = DuckDBThreaded(10, fetch_record_batch_query, pandas) duck_threads.multithread_test() @@ -449,8 +449,7 @@ def test_df_unregister(self, duckdb_cursor, pandas): @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) def test_arrow_register_unregister(self, duckdb_cursor, pandas): - if not can_run: - return + pytest.importorskip('pyarrow') duck_threads = DuckDBThreaded(10, arrow_register_unregister, pandas) duck_threads.multithread_test() @@ -481,8 +480,7 @@ def test_from_DF(self, duckdb_cursor, pandas): @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) def test_from_arrow(self, duckdb_cursor, pandas): - if not can_run: - return + pytest.importorskip('pyarrow') duck_threads = DuckDBThreaded(10, from_arrow, pandas) duck_threads.multithread_test() diff --git a/tools/pythonpkg/tests/fast/test_pytorch.py b/tools/pythonpkg/tests/fast/test_pytorch.py index 65566d3d2b5..98479ccdc2f 100644 --- a/tools/pythonpkg/tests/fast/test_pytorch.py +++ b/tools/pythonpkg/tests/fast/test_pytorch.py @@ -34,7 +34,8 @@ def test_pytorch(): torch.equal(duck_torch['a'], torch.tensor(duck_numpy['a'])) torch.equal(duck_torch['b'], torch.tensor(duck_numpy['b'])) - with pytest.raises(TypeError, match="can't convert"): - con = duckdb.connect() - con.execute(f"create table t( a UINTEGER)") - duck_torch = con.sql("select * from t").torch() + # Comment out test that might fail or not depending on pytorch versions + # with pytest.raises(TypeError, match="can't convert"): + # con = duckdb.connect() + # con.execute(f"create table t( a UINTEGER)") + # duck_torch = con.sql("select * from t").torch() diff --git a/tools/pythonpkg/tests/fast/test_relation.py b/tools/pythonpkg/tests/fast/test_relation.py index e08d3bed717..4d66adf8256 100644 --- a/tools/pythonpkg/tests/fast/test_relation.py +++ b/tools/pythonpkg/tests/fast/test_relation.py @@ -1,9 +1,13 @@ import duckdb import numpy as np +import platform import tempfile import os import pandas as pd import pytest +from conftest import ArrowPandas, NumpyPandas +import datetime +from duckdb import ColumnExpression from duckdb.typing import BIGINT, VARCHAR, TINYINT, BOOLEAN @@ -26,6 +30,25 @@ def test_csv_auto(self): csv_rel = duckdb.from_csv_auto(temp_file_name) assert df_rel.execute().fetchall() == csv_rel.execute().fetchall() + @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) + def test_relation_view(self, duckdb_cursor, pandas): + def create_view(duckdb_cursor): + df_in = pandas.DataFrame({'numbers': [1, 2, 3, 4, 5]}) + rel = duckdb_cursor.query("select * from df_in") + rel.to_view("my_view") + + create_view(duckdb_cursor) + with pytest.raises(duckdb.CatalogException, match="df_in does not exist"): + # The df_in object is no longer reachable + rel1 = duckdb_cursor.query("select * from df_in") + # But it **is** reachable through our 'my_view' VIEW + # Because a Relation was created that references the df_in, the 'df_in' TableRef was injected with an ExternalDependency on the dataframe object + # We then created a VIEW from that Relation, which in turn copied this 'df_in' TableRef into the ViewCatalogEntry + # Because of this, the df_in object will stay alive for as long as our 'my_view' entry exists. + rel2 = duckdb_cursor.query("select * from my_view") + res = rel2.fetchall() + assert res == [(1,), (2,), (3,), (4,), (5,)] + def test_filter_operator(self): conn = duckdb.connect() rel = get_relation(conn) @@ -69,6 +92,37 @@ def test_aggregate_operator(self): ('four', 4), ] + def test_relation_fetch_df_chunk(self, duckdb_cursor): + duckdb_cursor.execute(f"create table tbl as select * from range({duckdb.__standard_vector_size__ * 3})") + + rel = duckdb_cursor.table('tbl') + # default arguments + df1 = rel.fetch_df_chunk() + assert len(df1) == duckdb.__standard_vector_size__ + + df2 = rel.fetch_df_chunk(2) + assert len(df2) == duckdb.__standard_vector_size__ * 2 + + duckdb_cursor.execute( + f"create table dates as select (DATE '2021/02/21' + INTERVAL (i) DAYS)::DATE a from range({duckdb.__standard_vector_size__ * 4}) t(i)" + ) + + rel = duckdb_cursor.table('dates') + # default arguments + df1 = rel.fetch_df_chunk() + assert len(df1) == duckdb.__standard_vector_size__ + assert df1['a'][0].__class__ == pd.Timestamp + + # date as object + df1 = rel.fetch_df_chunk(date_as_object=True) + assert len(df1) == duckdb.__standard_vector_size__ + assert df1['a'][0].__class__ == datetime.date + + # vectors and date as object + df1 = rel.fetch_df_chunk(2, date_as_object=True) + assert len(df1) == duckdb.__standard_vector_size__ * 2 + assert df1['a'][0].__class__ == datetime.date + def test_distinct_operator(self): conn = duckdb.connect() rel = get_relation(conn) @@ -193,6 +247,36 @@ def test_df_proj(self): rel = duckdb.project(test_df, 'i') assert rel.execute().fetchall() == [(1,), (2,), (3,), (4,)] + def test_relation_lifetime(self, duckdb_cursor): + def create_relation(con): + df = pd.DataFrame({'a': [1, 2, 3]}) + return con.sql("select * from df") + + assert create_relation(duckdb_cursor).fetchall() == [(1,), (2,), (3,)] + + def create_simple_join(con): + df1 = pd.DataFrame({'a': ['a', 'b', 'c'], 'b': [1, 2, 3]}) + df2 = pd.DataFrame({'a': ['a', 'b', 'c'], 'b': [4, 5, 6]}) + + return con.sql("select * from df1 JOIN df2 USING (a, a)") + + assert create_simple_join(duckdb_cursor).fetchall() == [('a', 1, 4), ('b', 2, 5), ('c', 3, 6)] + + def create_complex_join(con): + df1 = pd.DataFrame({'a': [1], '1': [1]}) + df2 = pd.DataFrame({'a': [1], '2': [2]}) + df3 = pd.DataFrame({'a': [1], '3': [3]}) + df4 = pd.DataFrame({'a': [1], '4': [4]}) + df5 = pd.DataFrame({'a': [1], '5': [5]}) + df6 = pd.DataFrame({'a': [1], '6': [6]}) + query = "select * from df1" + for i in range(5): + query += f" JOIN df{i + 2} USING (a, a)" + return con.sql(query) + + rel = create_complex_join(duckdb_cursor) + assert rel.fetchall() == [(1, 1, 2, 3, 4, 5, 6)] + def test_project_on_types(self): con = duckdb.connect() con.sql( @@ -325,3 +409,125 @@ def test_relation_print(self): text1 = str(rel1) assert '? rows' in text1 assert '>9999 rows' in text1 + + @pytest.mark.parametrize( + 'num_rows', + [ + 1024, + 2048, + 5000, + 1000000, + pytest.param( + 10000000, + marks=pytest.mark.skipif( + condition=platform.system() == "Emscripten", + reason="Emscripten/Pyodide builds run out of memory at this scale, and error might not thrown reliably", + ), + ), + ], + ) + def test_materialized_relation(self, duckdb_cursor, num_rows): + # Anything that is not a SELECT statement becomes a materialized relation, so we use `CALL` + query = f"call repeat_row(42, 'test', 'this is a long string', true, num_rows={num_rows})" + rel = duckdb_cursor.sql(query) + res = rel.fetchone() + assert res != None + + res = rel.fetchmany(num_rows) + assert len(res) == num_rows - 1 + + res = rel.fetchmany(5) + assert len(res) == 0 + res = rel.fetchmany(5) + assert len(res) == 0 + res = rel.fetchone() + assert res == None + + rel.execute() + res = rel.fetchone() + assert res != None + + res = rel.fetchall() + assert len(res) == num_rows - 1 + res = rel.fetchall() + assert len(res) == num_rows + + rel = duckdb_cursor.sql(query) + projection = rel.select('column0') + assert projection.fetchall() == [(42,) for _ in range(num_rows)] + + filtered = rel.filter("column1 != 'test'") + assert filtered.fetchall() == [] + + with pytest.raises( + duckdb.InvalidInputException, + match=r"Invalid Input Error: 'DuckDBPyRelation.insert' can only be used on a table relation", + ): + rel.insert([1, 2, 3, 4]) + + with pytest.raises( + duckdb.NotImplementedException, match='Creating a VIEW from a MaterializedRelation is not supported' + ): + query_rel = rel.query('x', "select 42 from x where column0 != 42") + assert query_rel.fetchall() == [] + + distinct_rel = rel.distinct() + assert distinct_rel.fetchall() == [(42, 'test', 'this is a long string', True)] + + limited_rel = rel.limit(50) + assert len(limited_rel.fetchall()) == 50 + + materialized_one = duckdb_cursor.sql("call range(10)").project( + ColumnExpression('range').cast(str).alias('range') + ) + materialized_two = duckdb_cursor.sql("call repeat('a', 5)") + joined_rel = materialized_one.join(materialized_two, 'range != a') + res = joined_rel.fetchall() + assert len(res) == 50 + + relation = duckdb_cursor.sql("select a from materialized_two") + assert relation.fetchone() == ('a',) + + described = materialized_one.describe() + res = described.fetchall() + assert res == [('count', '10'), ('mean', None), ('stddev', None), ('min', '0'), ('max', '9'), ('median', None)] + + unioned_rel = materialized_one.union(materialized_two) + res = unioned_rel.fetchall() + assert res == [ + ('0',), + ('1',), + ('2',), + ('3',), + ('4',), + ('5',), + ('6',), + ('7',), + ('8',), + ('9',), + ('a',), + ('a',), + ('a',), + ('a',), + ('a',), + ] + + except_rel = unioned_rel.except_(materialized_one) + res = except_rel.fetchall() + assert res == [('a',)] + + intersect_rel = unioned_rel.intersect(materialized_one).order('range') + res = intersect_rel.fetchall() + assert res == [('0',), ('1',), ('2',), ('3',), ('4',), ('5',), ('6',), ('7',), ('8',), ('9',)] + + def test_materialized_relation_view(self, duckdb_cursor): + with pytest.raises( + duckdb.NotImplementedException, match='Creating a VIEW from a MaterializedRelation is not supported' + ): + duckdb_cursor.sql( + """ + create table tbl(a varchar); + insert into tbl values ('test') returning * + """ + ).to_view('vw') + res = duckdb_cursor.sql("select * from vw").fetchone() diff --git a/tools/pythonpkg/tests/fast/test_relation_dependency_leak.py b/tools/pythonpkg/tests/fast/test_relation_dependency_leak.py index 9763d486afd..ca5057047e5 100644 --- a/tools/pythonpkg/tests/fast/test_relation_dependency_leak.py +++ b/tools/pythonpkg/tests/fast/test_relation_dependency_leak.py @@ -1,6 +1,5 @@ -import duckdb import numpy as np -import os, psutil +import os import pytest try: @@ -12,6 +11,9 @@ from conftest import NumpyPandas, ArrowPandas +psutil = pytest.importorskip("psutil") + + def check_memory(function_to_check, pandas, duckdb_cursor): process = psutil.Process(os.getpid()) mem_usage = process.memory_info().rss / (10**9) diff --git a/tools/pythonpkg/tests/fast/test_replacement_scan.py b/tools/pythonpkg/tests/fast/test_replacement_scan.py index 2ebb7f7b52b..defb9c5d34b 100644 --- a/tools/pythonpkg/tests/fast/test_replacement_scan.py +++ b/tools/pythonpkg/tests/fast/test_replacement_scan.py @@ -2,7 +2,9 @@ import os import pytest +pa = pytest.importorskip("pyarrow") pl = pytest.importorskip("polars") +pd = pytest.importorskip("pandas") def using_table(con, to_scan, object_name): @@ -45,6 +47,32 @@ def fetch_relation(rel): return rel +global_polars_df = pl.DataFrame( + { + "A": [1], + "fruits": ["banana"], + "B": [5], + "cars": ["beetle"], + } +) + + +def from_pandas(): + df = pd.DataFrame({'a': [1, 2, 3]}) + return df + + +def from_arrow(): + schema = pa.schema([('field_1', pa.int64())]) + df = pa.RecordBatchReader.from_batches(schema, [pa.RecordBatch.from_arrays([pa.array([1, 2, 3])], schema=schema)]) + return df + + +def create_relation(conn, query: str) -> duckdb.DuckDBPyRelation: + df = pd.DataFrame({'a': [1, 2, 3]}) + return conn.sql(query) + + class TestReplacementScan(object): def test_csv_replacement(self): con = duckdb.connect() @@ -73,6 +101,43 @@ def test_table_replacement_scans(self, duckdb_cursor, get_relation, fetch_method res = rel.fetchall() assert res == [(1, 2, 3)] + def test_scan_global(self, duckdb_cursor): + duckdb_cursor.execute("set python_enable_replacements=false") + with pytest.raises(duckdb.CatalogException, match='Table with name global_polars_df does not exist'): + # We set the depth to look for global variables to 0 so it's never found + duckdb_cursor.sql("select * from global_polars_df") + duckdb_cursor.execute("set python_enable_replacements=true") + # Now the depth is 1, which is enough to locate the variable + rel = duckdb_cursor.sql("select * from global_polars_df") + res = rel.fetchone() + assert res == (1, 'banana', 5, 'beetle') + + def test_scan_local(self, duckdb_cursor): + df = pd.DataFrame({'a': [1, 2, 3]}) + + def inner_func(duckdb_cursor): + duckdb_cursor.execute("set python_enable_replacements=false") + with pytest.raises(duckdb.CatalogException, match='Table with name df does not exist'): + # We set the depth to look for local variables to 0 so it's never found + duckdb_cursor.sql("select * from df") + duckdb_cursor.execute("set python_enable_replacements=true") + with pytest.raises(duckdb.CatalogException, match='Table with name df does not exist'): + # We set the depth to look for local variables to 1 so it's still not found because it wasn't defined in this function + duckdb_cursor.sql("select * from df") + duckdb_cursor.execute("set python_enable_replacements=true") + with pytest.raises(duckdb.CatalogException, match='Table with name df does not exist'): + # Here it's still not found, because it's not visible to this frame + duckdb_cursor.sql("select * from df") + + df = pd.DataFrame({'a': [4, 5, 6]}) + duckdb_cursor.execute("set python_enable_replacements=true") + # We can find the newly defined 'df' with depth 1 + rel = duckdb_cursor.sql("select * from df") + res = rel.fetchall() + assert res == [(4,), (5,), (6,)] + + inner_func(duckdb_cursor) + def test_replacement_scan_relapi(self): con = duckdb.connect() pyrel1 = con.query('from (values (42), (84), (120)) t(i)') @@ -102,6 +167,28 @@ def test_replacement_scan_pandas_alias(self): df3 = con.query('from df1 join df2 using(i)') assert df3.fetchall() == [(1, 2, 10)] + def test_replacement_scan_after_creation(self, duckdb_cursor): + duckdb_cursor.execute("create table df (a varchar)") + duckdb_cursor.execute("insert into df values (4), (5), (6)") + rel = duckdb_cursor.sql("select * from df") + + duckdb_cursor.execute("drop table df") + df = pd.DataFrame({'b': [1, 2, 3]}) + res = rel.fetchall() + # FIXME: this should error instead, the 'df' table we relied on has been removed and replaced with a replacement scan + assert res == [(1,), (2,), (3,)] + + def test_replacement_scan_caching(self, duckdb_cursor): + def return_rel(conn): + df = pd.DataFrame({'a': [1, 2, 3]}) + rel = conn.sql("select * from df") + return rel + + rel = return_rel(duckdb_cursor) + duckdb_cursor.execute("create table df as select * from unnest([4,5,6])") + res = rel.fetchall() + assert res == [(1,), (2,), (3,)] + def test_replacement_scan_fail(self): random_object = "I love salmiak rondos" con = duckdb.connect() @@ -110,3 +197,289 @@ def test_replacement_scan_fail(self): match=r'Python Object "random_object" of type "str" found on line .* not suitable for replacement scans.', ): con.execute("select count(*) from random_object").fetchone() + + @pytest.mark.parametrize( + 'df_create', + [ + from_pandas, + from_arrow, + ], + ) + def test_cte(self, duckdb_cursor, df_create): + df = df_create() + rel = duckdb_cursor.sql("with cte as (select * from df) select * from cte") + res = rel.fetchall() + assert res == [(1,), (2,), (3,)] + + df = df_create() + query = """ + WITH cte as (select * from df) + select * from ( + WITH cte as (select * from df) + select * from ( + WITH cte as (select * from df) + select ( + select * from cte + ) from cte + ) + ) + """ + rel = duckdb_cursor.sql(query) + duckdb_cursor.execute("create table df as select * from range(4, 7)") + res = rel.fetchall() + """ + select ( + select * from cte + ) from cte + This will select the first row from the cte, and do this 3 times since we added 'from cte', and cte has 3 tuples + """ + + if df_create == from_arrow: + # Because the RecordBatchReader is destructive, it's empty after the first scan + # But we reference it multiple times, so the subsequent reads have no data to read + assert res == [(None,), (None,), (None,)] + else: + assert res == [(1,), (1,), (1,)] + + def test_cte_with_scalar_subquery(self, duckdb_cursor): + query = """ + WITH cte1 AS ( + select (select * from df) + ) + select * from cte1; + """ + rel = create_relation(duckdb_cursor, query) + res = rel.fetchall() + assert res == [(1,)] + + def test_cte_with_joins(self, duckdb_cursor): + query = """ + WITH cte1 AS ( + SELECT * FROM df + ), + cte2 AS ( + SELECT * FROM df + WHERE a > 1 + ), + cte3 AS ( + SELECT * FROM df + WHERE a < 3 + ) + SELECT * FROM ( + SELECT + cte1.*, + cte2.a AS cte2_a, + subquery.a AS cte3_a + FROM cte1 + JOIN cte2 ON cte1.a = cte2.a + JOIN ( + SELECT + df.*, + cte3.a AS cte3_a + FROM df + JOIN cte3 ON df.a = cte3.a + ) AS subquery ON cte1.a = subquery.a + ) AS main_query + WHERE main_query.a = 2 + """ + rel = create_relation(duckdb_cursor, query) + duckdb_cursor.execute("create table df as select * from range(4, 7)") + res = rel.fetchall() + assert res == [(2, 2, 2)] + + def test_same_name_cte(self, duckdb_cursor): + query = """ + WITH df AS ( + SELECT a+1 FROM df + ) + SELECT * FROM df; + """ + rel = create_relation(duckdb_cursor, query) + res = rel.fetchall() + assert res == [(1,), (2,), (3,)] + + query = """ + WITH RECURSIVE df AS ( + SELECT a+1 FROM df + ) + SELECT * FROM df; + """ + rel = create_relation(duckdb_cursor, query) + res = rel.fetchall() + assert res == [(1,), (2,), (3,)] + + def test_use_with_view(self, duckdb_cursor): + rel = create_relation(duckdb_cursor, "select * from df") + rel.create_view('v1') + + del rel + rel = duckdb_cursor.sql("select * from v1") + res = rel.fetchall() + assert res == [(1,), (2,), (3,)] + duckdb_cursor.execute("drop view v1") + + def create_view_in_func(con): + df = pd.DataFrame({"a": [1, 2, 3]}) + con.execute('CREATE VIEW v1 AS SELECT * FROM df') + + create_view_in_func(duckdb_cursor) + + # FIXME: this should be fixed in the future, likely by unifying the behavior of .sql and .execute + with pytest.raises(duckdb.CatalogException, match='Table with name df does not exist'): + rel = duckdb_cursor.sql("select * from v1") + + def test_recursive_cte(self, duckdb_cursor): + query = """ + WITH RECURSIVE + RecursiveCTE AS ( + SELECT Number from df t(Number) + UNION ALL + SELECT Number + (select a from df offset 2 limit 1) + 1 as new + FROM RecursiveCTE + WHERE new < 10 + ) + select * from RecursiveCTE; + """ + rel = create_relation(duckdb_cursor, query) + res = rel.fetchall() + assert res == [(1,), (2,), (3,), (5,), (6,), (7,), (9,)] + + # RecursiveCTE references another CTE which references the 'df' + query = """ + WITH RECURSIVE + other_cte as ( + select * from df t(c) + ), + RecursiveCTE AS ( + SELECT Number from other_cte t(Number) + UNION ALL + SELECT Number + (select c from other_cte offset 2 limit 1) + 1 as new + FROM RecursiveCTE + WHERE new < 10 + ) + select * from RecursiveCTE; + """ + rel = create_relation(duckdb_cursor, query) + res = rel.fetchall() + assert res == [(1,), (2,), (3,), (5,), (6,), (7,), (9,)] + + def test_multiple_replacements(self, duckdb_cursor): + # Sample data for Employees table + employees_data = [ + {"EmployeeID": 1, "EmployeeName": "Alice", "ManagerID": None}, + {"EmployeeID": 2, "EmployeeName": "Bob", "ManagerID": 1}, + {"EmployeeID": 3, "EmployeeName": "Charlie", "ManagerID": 1}, + {"EmployeeID": 4, "EmployeeName": "David", "ManagerID": 2}, + {"EmployeeID": 5, "EmployeeName": "Eve", "ManagerID": 2}, + ] + + # Convert list of dictionaries to pandas DataFrame + employees_df = pd.DataFrame(employees_data) + # First mention of `employees_df` has an alias, second doesn't + query = """ + SELECT + e1.EmployeeID, + e1.EmployeeName, + employees_df.ManagerID + FROM employees_df e1 + JOIN employees_df ON e1.ManagerID = employees_df.EmployeeID; + """ + rel = duckdb_cursor.sql(query) + res = rel.fetchall() + assert res == [(3, 'Charlie', None), (5, 'Eve', 1.0), (2, 'Bob', None), (4, 'David', 1.0)] + + def test_cte_at_different_levels(self, duckdb_cursor): + query = """ + SELECT * FROM ( + WITH cte1 AS ( + SELECT * FROM df + ) + SELECT + cte1.*, + cte2.a AS cte2_a, + subquery.a AS cte3_a + FROM cte1 + JOIN ( + WITH cte2 AS ( + SELECT * FROM df + WHERE a > 1 + ) + SELECT * FROM cte2 + ) AS cte2 ON cte1.a = cte2.a + JOIN ( + WITH cte3 AS ( + SELECT * FROM df + WHERE a < 3 + ) + SELECT + df.*, + cte3.a AS cte3_a + FROM ( + SELECT * FROM df + ) AS df + JOIN cte3 ON df.a = cte3.a + ) AS subquery ON cte1.a = subquery.a + ) AS main_query + WHERE main_query.a = 2 + """ + rel = create_relation(duckdb_cursor, query) + duckdb_cursor.execute("create table df as select * from range(4, 7)") + res = rel.fetchall() + assert res == [(2, 2, 2)] + + def test_replacement_disabled(self): + # Create regular connection, not disabled + con = duckdb.connect() + rel = create_relation(con, "select * from df") + res = rel.fetchall() + assert res == [(1,), (2,), (3,)] + + ## disable external access + con.execute("set enable_external_access=false") + with pytest.raises(duckdb.CatalogException, match='Table with name df does not exist!'): + rel = create_relation(con, "select * from df") + res = rel.fetchall() + with pytest.raises( + duckdb.InvalidInputException, match='Cannot change enable_external_access setting while database is running' + ): + con.execute("set enable_external_access=true") + + # Create connection with external access disabled + con = duckdb.connect(config={'enable_external_access': False}) + with pytest.raises(duckdb.CatalogException, match='Table with name df does not exist!'): + rel = create_relation(con, "select * from df") + res = rel.fetchall() + + # Create regular connection, disable inbetween creation and execution + con = duckdb.connect() + rel = create_relation(con, "select * from df") + + con.execute("set enable_external_access=false") + + # Since we cache the replacement scans as CTEs, disabling the external access inbetween creation + # and execution has no effect, we might want to change that by keeping track of which CTEs we have added + # and removing them if `enable_external_access` is set + res = rel.fetchall() + assert res == [(1,), (2,), (3,)] + + def test_replacement_of_cross_connection_relation(self): + con1 = duckdb.connect(':memory:') + con2 = duckdb.connect(':memory:') + con1.query('create table integers(i int)') + con2.query('create table integers(v varchar)') + con1.query('insert into integers values (42)') + con2.query('insert into integers values (\'xxx\')') + rel1 = con1.query('select * from integers') + with pytest.raises( + duckdb.InvalidInputException, + match=r'The object was created by another Connection and can therefore not be used by this Connection.', + ): + con2.query('from rel1') + + del con1 + + with pytest.raises( + duckdb.InvalidInputException, + match=r'The object was created by another Connection and can therefore not be used by this Connection.', + ): + con2.query('from rel1') diff --git a/tools/pythonpkg/tests/fast/test_runtime_error.py b/tools/pythonpkg/tests/fast/test_runtime_error.py index 6c6fb459b4a..9f1f5378c5e 100644 --- a/tools/pythonpkg/tests/fast/test_runtime_error.py +++ b/tools/pythonpkg/tests/fast/test_runtime_error.py @@ -58,7 +58,7 @@ def test_arrow_record_batch_reader_error(self): res.fetch_arrow_reader(1) @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) - def test_relation_fetchall_error(self, pandas): + def test_relation_cache_fetchall(self, pandas): conn = duckdb.connect() df_in = pandas.DataFrame( { @@ -69,10 +69,13 @@ def test_relation_fetchall_error(self, pandas): rel = conn.query("select * from x") del df_in with pytest.raises(duckdb.ProgrammingError, match='Table with name df_in does not exist'): + # Even when we preserve ExternalDependency objects correctly, this is not supported + # Relations only save dependencies for their immediate TableRefs, + # so the dependency of 'x' on 'df_in' is not registered in 'rel' rel.fetchall() @pytest.mark.parametrize('pandas', [NumpyPandas(), ArrowPandas()]) - def test_relation_fetchall_execute(self, pandas): + def test_relation_cache_execute(self, pandas): conn = duckdb.connect() df_in = pandas.DataFrame( { diff --git a/tools/pythonpkg/tests/fast/test_union.py b/tools/pythonpkg/tests/fast/test_union.py new file mode 100644 index 00000000000..912caff958c --- /dev/null +++ b/tools/pythonpkg/tests/fast/test_union.py @@ -0,0 +1,69 @@ +import duckdb +import pandas as pd + + +class TestUnion(object): + def test_union_by_all(self): + connection = duckdb.connect() + + connection.execute( + """ + create table tbl1 as select * from (VALUES + (1, 2, 3, 4), + (2, 3, 4, 5), + (3, 4, 5, 6)) as tbl(A, B, C, D) + """ + ) + connection.execute( + """ + create table tbl2 as select * from (VALUES + (11, 12, 13, 14, 15), + (12, 13, 14, 15, 16), + (13, 14, 15, 16, 17)) as tbl (A, B, C, D, E) + """ + ) + + query = """ + select + * + from + ( + select A, B, C, D, 0 as E from tbl1 + ) + union all ( + select * from tbl2 + ) order by all + """ + res = connection.sql(query).fetchall() + assert res == [ + (1, 2, 3, 4, 0), + (2, 3, 4, 5, 0), + (3, 4, 5, 6, 0), + (11, 12, 13, 14, 15), + (12, 13, 14, 15, 16), + (13, 14, 15, 16, 17), + ] + + df_1 = connection.execute("FROM tbl1").df() + df_2 = connection.execute("FROM tbl2").df() + + query = """ + select + * + from + ( + select A, B, C, D, 0 as E from df_1 + ) + union all ( + select * from df_2 + ) order by all + """ + res = connection.sql(query).fetchall() + assert res == [ + (1, 2, 3, 4, 0), + (2, 3, 4, 5, 0), + (3, 4, 5, 6, 0), + (11, 12, 13, 14, 15), + (12, 13, 14, 15, 16), + (13, 14, 15, 16, 17), + ] diff --git a/tools/pythonpkg/tests/fast/types/test_nan.py b/tools/pythonpkg/tests/fast/types/test_nan.py index 4aa8544382b..cae046e038d 100644 --- a/tools/pythonpkg/tests/fast/types/test_nan.py +++ b/tools/pythonpkg/tests/fast/types/test_nan.py @@ -9,9 +9,9 @@ class TestPandasNaN(object): def test_pandas_nan(self, duckdb_cursor): # create a DataFrame with some basic values - df = pandas.DataFrame([{"col1": "val1", "col2": 1.05}, {"col1": "val3", "col2": np.NaN}]) + df = pandas.DataFrame([{"col1": "val1", "col2": 1.05}, {"col1": "val3", "col2": np.nan}]) # create a new column (newcol1) that includes either NaN or values from col1 - df["newcol1"] = np.where(df["col1"] == "val1", np.NaN, df["col1"]) + df["newcol1"] = np.where(df["col1"] == "val1", np.nan, df["col1"]) # now create a new column with the current time # (FIXME: we replace the microseconds with 0 for now, because we only support milisecond resolution) current_time = datetime.datetime.now().replace(microsecond=0) diff --git a/tools/shell/linenoise/highlighting.cpp b/tools/shell/linenoise/highlighting.cpp index c4127b16fc2..9416a44284a 100644 --- a/tools/shell/linenoise/highlighting.cpp +++ b/tools/shell/linenoise/highlighting.cpp @@ -103,11 +103,11 @@ static tokenType convertToken(duckdb::SimplifiedTokenType token_type) { } } -vector Highlighting::Tokenize(char *buf, size_t len, searchMatch *match) { +vector GetParseTokens(char *buf, size_t len) { string sql(buf, len); auto parseTokens = duckdb::Parser::Tokenize(sql); - vector tokens; + vector tokens; for (auto &token : parseTokens) { highlightToken new_token; new_token.type = convertToken(token.type); @@ -127,6 +127,38 @@ vector Highlighting::Tokenize(char *buf, size_t len, searchMatch new_token.start = 0; tokens.push_back(new_token); } + return tokens; +} + +vector GetDotCommandTokens(char *buf, size_t len) { + vector tokens; + + // identifier token for the dot command itself + highlightToken dot_token; + dot_token.type = tokenType::TOKEN_KEYWORD; + dot_token.start = 0; + tokens.push_back(dot_token); + + for (idx_t i = 0; i + 1 < len; i++) { + if (Linenoise::IsSpace(buf[i])) { + highlightToken argument_token; + argument_token.type = tokenType::TOKEN_STRING_CONSTANT; + argument_token.start = i + 1; + tokens.push_back(argument_token); + } + } + return tokens; +} + +vector Highlighting::Tokenize(char *buf, size_t len, bool is_dot_command, searchMatch *match) { + vector tokens; + if (!is_dot_command) { + // SQL query - use parser to obtain tokens + tokens = GetParseTokens(buf, len); + } else { + // . command + tokens = GetDotCommandTokens(buf, len); + } if (match) { // we have a search match - insert it into the token list // we want to insert a search token with start = match_start, end = match_end diff --git a/tools/shell/linenoise/include/highlighting.hpp b/tools/shell/linenoise/include/highlighting.hpp index e9583430f6f..bb27d171845 100644 --- a/tools/shell/linenoise/include/highlighting.hpp +++ b/tools/shell/linenoise/include/highlighting.hpp @@ -42,7 +42,7 @@ class Highlighting { static const char *GetColorOption(const char *option); static void SetHighlightingColor(HighlightingType type, const char *color); - static vector Tokenize(char *buf, size_t len, searchMatch *match = nullptr); + static vector Tokenize(char *buf, size_t len, bool is_dot_command, searchMatch *match); static string HighlightText(char *buf, size_t len, size_t start_pos, size_t end_pos, const vector &tokens); }; diff --git a/tools/shell/linenoise/include/linenoise.hpp b/tools/shell/linenoise/include/linenoise.hpp index 7393734649d..c3223666bdb 100644 --- a/tools/shell/linenoise/include/linenoise.hpp +++ b/tools/shell/linenoise/include/linenoise.hpp @@ -127,6 +127,7 @@ class Linenoise { static bool IsNewline(char c); static bool IsWordBoundary(char c); static bool AllWhitespace(const char *z); + static bool IsSpace(char c); TabCompletion TabComplete() const; diff --git a/tools/shell/linenoise/linenoise.cpp b/tools/shell/linenoise/linenoise.cpp index 17ecc3e209e..73d7cc9f7e9 100644 --- a/tools/shell/linenoise/linenoise.cpp +++ b/tools/shell/linenoise/linenoise.cpp @@ -659,7 +659,7 @@ void Linenoise::EditBackspace() { } } -static bool IsSpace(char c) { +bool Linenoise::IsSpace(char c) { switch (c) { case ' ': case '\r': diff --git a/tools/shell/linenoise/rendering.cpp b/tools/shell/linenoise/rendering.cpp index 3df13de770e..57faed9f3e2 100644 --- a/tools/shell/linenoise/rendering.cpp +++ b/tools/shell/linenoise/rendering.cpp @@ -127,7 +127,9 @@ static void renderText(size_t &render_pos, char *&buf, size_t &len, size_t pos, } } if (highlight) { - auto tokens = Highlighting::Tokenize(buf, len, match); + bool is_dot_command = buf[0] == '.'; + + auto tokens = Highlighting::Tokenize(buf, len, is_dot_command, match); highlight_buffer = Highlighting::HighlightText(buf, len, start_pos, cpos, tokens); buf = (char *)highlight_buffer.c_str(); len = highlight_buffer.size(); @@ -856,8 +858,9 @@ void Linenoise::RefreshMultiLine() { vector tokens; if (Highlighting::IsEnabled()) { + bool is_dot_command = buf[0] == '.'; auto match = search_index < search_matches.size() ? &search_matches[search_index] : nullptr; - tokens = Highlighting::Tokenize(render_buf, render_len, match); + tokens = Highlighting::Tokenize(render_buf, render_len, is_dot_command, match); // add error highlighting AddErrorHighlighting(render_start, render_end, tokens); diff --git a/tools/shell/shell.c b/tools/shell/shell.c index a0afa3e2cdb..9e974fd9f07 100644 --- a/tools/shell/shell.c +++ b/tools/shell/shell.c @@ -2283,6 +2283,10 @@ static int makeDirectory( rc = SQLITE_NOMEM; }else{ int nCopy = (int)strlen(zCopy); + if(nCopy == 0) { + sqlite3_free(zCopy); + return SQLITE_ERROR; + } int i = 1; while( rc==SQLITE_OK ){ @@ -14204,7 +14208,32 @@ static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){ char zBuf[1000]; if( nLine>sizeof(zBuf)-30 ) return; - if( zLine[0]=='.' || zLine[0]=='#') return; + if (zLine[0] == '.') { + // auto-complete dot command + // look for all completions in the help file + for(size_t line_idx = 0; line_idx < ArraySize(azHelp); line_idx++) { + const char *line = azHelp[line_idx]; + if (line[0] != '.') { + continue; + } + int found_match = 1; + size_t line_pos; + for(line_pos = 0; !IsSpace(line[line_pos]) && line[line_pos] && line_pos + 1 < sizeof(zBuf); line_pos++) { + zBuf[line_pos] = line[line_pos]; + if (line_pos < nLine && line[line_pos] != zLine[line_pos]) { + // only match prefixes for auto-completion, i.e. ".sh" matches ".shell" + found_match = 0; + break; + } + } + zBuf[line_pos] = '\0'; + if (found_match && line_pos >= nLine) { + linenoiseAddCompletion(lc, zBuf); + } + } + return; + } + if(zLine[0]=='#') return; // if( i==nLine-1 ) return; zSql = sqlite3_mprintf("CALL sql_auto_complete(%Q)", zLine); sqlite3 *localDb = NULL; diff --git a/tools/shell/tests/test_http_logging.py b/tools/shell/tests/test_http_logging.py new file mode 100644 index 00000000000..5ce3b94626d --- /dev/null +++ b/tools/shell/tests/test_http_logging.py @@ -0,0 +1,38 @@ +# fmt: off + +import pytest +import subprocess +import sys +from typing import List +from conftest import ShellTest +import os + + +def test_http_logging_stderr(shell): + test = ( + ShellTest(shell) + .statement("SET enable_http_logging=true;") + .statement("install 'http://extensions.duckdb.org/v0.10.1/osx_arm64/httpfs.duckdb_extension.gzzz';") + ) + result = test.run() + result.check_stderr("HTTP Request") + result.check_stderr("HTTP Response") + + +def test_http_logging_file(shell, tmp_path): + temp_dir = tmp_path / 'http_logging_dir' + temp_dir.mkdir() + temp_file = temp_dir / 'myfile' + + test = ( + ShellTest(shell) + .statement("SET enable_http_logging=true;") + .statement(f"SET http_logging_output='{temp_file.as_posix()}'") + .statement("install 'http://extensions.duckdb.org/v0.10.1/osx_arm64/httpfs.duckdb_extension.gzzz';") + ) + result = test.run() + + with open(temp_file, 'r') as f: + file_content = f.read() + assert "HTTP Request" in file_content + assert "HTTP Response" in file_content diff --git a/tools/sqlite3_api_wrapper/sqlite3_api_wrapper.cpp b/tools/sqlite3_api_wrapper/sqlite3_api_wrapper.cpp index 05df06d3a6d..3d411b03a30 100644 --- a/tools/sqlite3_api_wrapper/sqlite3_api_wrapper.cpp +++ b/tools/sqlite3_api_wrapper/sqlite3_api_wrapper.cpp @@ -122,9 +122,9 @@ int sqlite3_open_v2(const char *filename, /* Database filename (UTF-8) */ "(e.g. duckdb -unsigned)."); pDb->db = make_uniq(filename, &config); #ifdef SHELL_INLINE_AUTOCOMPLETE - pDb->db->LoadExtension(); + pDb->db->LoadStaticExtension(); #endif - pDb->db->LoadExtension(); + pDb->db->LoadStaticExtension(); pDb->con = make_uniq(*pDb->db); } catch (const Exception &ex) { if (pDb) { diff --git a/tools/sqlite3_api_wrapper/sqlite3_udf_api/include/cast_sqlite.hpp b/tools/sqlite3_api_wrapper/sqlite3_udf_api/include/cast_sqlite.hpp index 3584bd03ac9..485628a4d2d 100644 --- a/tools/sqlite3_api_wrapper/sqlite3_udf_api/include/cast_sqlite.hpp +++ b/tools/sqlite3_api_wrapper/sqlite3_udf_api/include/cast_sqlite.hpp @@ -67,7 +67,8 @@ struct CastToVectorSQLiteValue { if (vec_data.validity.AllValid()) { for (idx_t i = 0; i < count; ++i) { - res_data[i] = OPCAST::template Operation(input_data[i]); + auto idx = vec_data.sel->get_index(i); + res_data[i] = OPCAST::template Operation(input_data[idx]); } return result; } diff --git a/tools/swift/duckdb-swift/README.md b/tools/swift/duckdb-swift/README.md index 32cda63cd4b..a190dfd1730 100644 --- a/tools/swift/duckdb-swift/README.md +++ b/tools/swift/duckdb-swift/README.md @@ -64,7 +64,7 @@ Development is managed through [the main DuckDB repository](https://github.com/d ``` 3. Generate the Unified Build files for the package: ```shell - python3 tools/swift/create-package.py tools/swift + python3 tools/swift/create_package.py tools/swift ``` 4. Open the Xcode workspace at `tools/swift/duckdb-swift/DuckDB.xcworkspace` diff --git a/tools/swift/duckdb-swift/Tests/DuckDBTests/TypeConversionTests.swift b/tools/swift/duckdb-swift/Tests/DuckDBTests/TypeConversionTests.swift index 652855eaa2f..f13c1913105 100644 --- a/tools/swift/duckdb-swift/Tests/DuckDBTests/TypeConversionTests.swift +++ b/tools/swift/duckdb-swift/Tests/DuckDBTests/TypeConversionTests.swift @@ -176,7 +176,7 @@ final class TypeConversionTests: XCTestCase { func test_extract_from_timestamp_ns() throws { let t1 = Timestamp.Components( - year: 1677, month: 09, day: 21, hour: 0, minute: 12, second: 43, microsecond: 145_225) + year: 1677, month: 09, day: 22, hour: 0, minute: 0, second: 0, microsecond: 0) let t2 = Timestamp.Components( year: 2262, month: 04, day: 11, hour: 23, minute: 47, second: 16, microsecond: 854_775) let expected = [Timestamp(components: t1), Timestamp(components: t2), nil] From 3d92c7ce25c0daf60bba0a7bbca79bebd16b884b Mon Sep 17 00:00:00 2001 From: continue revolution Date: Sat, 22 Jun 2024 22:31:42 +0800 Subject: [PATCH 07/89] Revert prev commit --- src/common/enum_util.cpp | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/src/common/enum_util.cpp b/src/common/enum_util.cpp index 52d75b3e02b..51917b3fcb8 100644 --- a/src/common/enum_util.cpp +++ b/src/common/enum_util.cpp @@ -5963,34 +5963,6 @@ SampleType EnumUtil::FromString(const char *value) { throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } -template<> -const char* EnumUtil::ToChars(SampleType value) { - switch(value) { - case SampleType::BLOCKING_SAMPLE: - return "BLOCKING_SAMPLE"; - case SampleType::RESERVOIR_SAMPLE: - return "RESERVOIR_SAMPLE"; - case SampleType::RESERVOIR_PERCENTAGE_SAMPLE: - return "RESERVOIR_PERCENTAGE_SAMPLE"; - default: - throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); - } -} - -template<> -SampleType EnumUtil::FromString(const char *value) { - if (StringUtil::Equals(value, "BLOCKING_SAMPLE")) { - return SampleType::BLOCKING_SAMPLE; - } - if (StringUtil::Equals(value, "RESERVOIR_SAMPLE")) { - return SampleType::RESERVOIR_SAMPLE; - } - if (StringUtil::Equals(value, "RESERVOIR_PERCENTAGE_SAMPLE")) { - return SampleType::RESERVOIR_PERCENTAGE_SAMPLE; - } - throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); -} - template<> const char* EnumUtil::ToChars(ScanType value) { switch(value) { From ec3d33ead689bb0fd4778118c4c951cded7bd4cb Mon Sep 17 00:00:00 2001 From: yuxuan Date: Tue, 25 Jun 2024 23:15:07 -0400 Subject: [PATCH 08/89] impl as a pushdown optimizer --- src/common/enums/optimizer_type.cpp | 1 + .../operator/scan/physical_table_scan.cpp | 8 ++++++ .../duckdb/common/enums/optimizer_type.hpp | 1 + .../duckdb/common/types/data_chunk.hpp | 12 +++++---- .../duckdb/function/table_function.hpp | 4 +++ .../duckdb/optimizer/sampling_pushdown.hpp | 25 ++++++++++++++++++ src/optimizer/CMakeLists.txt | 3 ++- src/optimizer/optimizer.cpp | 7 +++++ src/optimizer/sampling_pushdown.cpp | 26 +++++++++++++++++++ src/parallel/pipeline_executor.cpp | 10 ------- src/storage/table/row_group.cpp | 6 ++--- 11 files changed, 84 insertions(+), 19 deletions(-) create mode 100644 src/include/duckdb/optimizer/sampling_pushdown.hpp create mode 100644 src/optimizer/sampling_pushdown.cpp diff --git a/src/common/enums/optimizer_type.cpp b/src/common/enums/optimizer_type.cpp index 3a109f646c4..3f87b19e109 100644 --- a/src/common/enums/optimizer_type.cpp +++ b/src/common/enums/optimizer_type.cpp @@ -30,6 +30,7 @@ static const DefaultOptimizerType internal_optimizer_types[] = { {"compressed_materialization", OptimizerType::COMPRESSED_MATERIALIZATION}, {"duplicate_groups", OptimizerType::DUPLICATE_GROUPS}, {"reorder_filter", OptimizerType::REORDER_FILTER}, + {"sampling_pushdown", OptimizerType::SAMPLING_PUSHDOWN}, {"extension", OptimizerType::EXTENSION}, {nullptr, OptimizerType::INVALID}}; diff --git a/src/execution/operator/scan/physical_table_scan.cpp b/src/execution/operator/scan/physical_table_scan.cpp index 518cae0ccd4..96f462b88f5 100644 --- a/src/execution/operator/scan/physical_table_scan.cpp +++ b/src/execution/operator/scan/physical_table_scan.cpp @@ -86,6 +86,10 @@ SourceResultType PhysicalTableScan::GetData(ExecutionContext &context, DataChunk auto &state = input.local_state.Cast(); TableFunctionInput data(bind_data.get(), state.local_state.get(), gstate.global_state.get()); + if (function.sampling_pushdown) { + chunk.sampling_pushdown_option.do_system_sample = true; + chunk.sampling_pushdown_option.sample_rate = function.sample_rate; + } if (function.function) { function.function(context.client, data, chunk); } else { @@ -166,6 +170,10 @@ string PhysicalTableScan::ParamsToString() const { } } } + if (function.sampling_pushdown) { + result += "\n[INFOSEPARATOR]\n"; + result += StringUtil::Format("System Sample: %.2f%%", function.sample_rate * 100); + } if (!extra_info.file_filters.empty()) { result += "\n[INFOSEPARATOR]\n"; result += "File Filters: " + extra_info.file_filters; diff --git a/src/include/duckdb/common/enums/optimizer_type.hpp b/src/include/duckdb/common/enums/optimizer_type.hpp index 04223b4b7c6..fc3166140f6 100644 --- a/src/include/duckdb/common/enums/optimizer_type.hpp +++ b/src/include/duckdb/common/enums/optimizer_type.hpp @@ -34,6 +34,7 @@ enum class OptimizerType : uint32_t { COMPRESSED_MATERIALIZATION, DUPLICATE_GROUPS, REORDER_FILTER, + SAMPLING_PUSHDOWN, EXTENSION }; diff --git a/src/include/duckdb/common/types/data_chunk.hpp b/src/include/duckdb/common/types/data_chunk.hpp index 37fce1424cb..03e5e486386 100644 --- a/src/include/duckdb/common/types/data_chunk.hpp +++ b/src/include/duckdb/common/types/data_chunk.hpp @@ -41,9 +41,10 @@ class Deserializer; In addition to holding the data of the vectors, the DataChunk also owns the selection vector that underlying vectors can point to. */ -struct ChunkSampleOp { - bool do_chunk_sample = false; - double percentage = 0; + +struct SamplingPushdownOption { + bool do_system_sample = false; + double sample_rate = 0; }; class DataChunk { @@ -54,8 +55,9 @@ class DataChunk { //! The vectors owned by the DataChunk. vector data; - - ChunkSampleOp chunk_sample_op; + + //! Options for sampling pushdown + SamplingPushdownOption sampling_pushdown_option; public: inline idx_t size() const { // NOLINT diff --git a/src/include/duckdb/function/table_function.hpp b/src/include/duckdb/function/table_function.hpp index c03ed17a1f1..7e658396de6 100644 --- a/src/include/duckdb/function/table_function.hpp +++ b/src/include/duckdb/function/table_function.hpp @@ -294,6 +294,10 @@ class TableFunction : public SimpleNamedParameterFunction { // NOLINT: work-arou //! Whether or not the table function can immediately prune out filter columns that are unused in the remainder of //! the query plan, e.g., "SELECT i FROM tbl WHERE j = 42;" - j does not need to leave the table function at all bool filter_prune; + //! Whether or not the table function supports sampling pushdown. If not supported a sample will be taken after the + //! table function. + bool sampling_pushdown = false; + double sample_rate; //! Additional function info, passed to the bind shared_ptr function_info; diff --git a/src/include/duckdb/optimizer/sampling_pushdown.hpp b/src/include/duckdb/optimizer/sampling_pushdown.hpp new file mode 100644 index 00000000000..1a845682097 --- /dev/null +++ b/src/include/duckdb/optimizer/sampling_pushdown.hpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/sampling_pushdown.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/common/constants.hpp" +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb/common/unique_ptr.hpp" + +namespace duckdb { +class LocigalOperator; +class Optimizer; + +class SamplingPushdown { +public: + //! Optimize SYSTEM SAMPLING + SCAN to SAMPLE SCAN + unique_ptr Optimize(unique_ptr op); +}; + +} // namespace duckdb \ No newline at end of file diff --git a/src/optimizer/CMakeLists.txt b/src/optimizer/CMakeLists.txt index 1c036de74d1..38ccc9c76dd 100644 --- a/src/optimizer/CMakeLists.txt +++ b/src/optimizer/CMakeLists.txt @@ -29,7 +29,8 @@ add_library_unity( statistics_propagator.cpp limit_pushdown.cpp topn_optimizer.cpp - unnest_rewriter.cpp) + unnest_rewriter.cpp + sampling_pushdown.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index c8e4096d70a..20f4a3d96f0 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -25,6 +25,7 @@ #include "duckdb/optimizer/limit_pushdown.hpp" #include "duckdb/optimizer/topn_optimizer.hpp" #include "duckdb/optimizer/unnest_rewriter.hpp" +#include "duckdb/optimizer/sampling_pushdown.hpp" #include "duckdb/planner/binder.hpp" #include "duckdb/planner/planner.hpp" @@ -173,6 +174,12 @@ void Optimizer::RunBuiltInOptimizers() { plan = limit_pushdown.Optimize(std::move(plan)); }); + // perform sampling pushdown + RunOptimizer(OptimizerType::SAMPLING_PUSHDOWN, [&]() { + SamplingPushdown sampling_pushdown; + plan = sampling_pushdown.Optimize(std::move(plan)); + }); + // transform ORDER BY + LIMIT to TopN RunOptimizer(OptimizerType::TOP_N, [&]() { TopN topn; diff --git a/src/optimizer/sampling_pushdown.cpp b/src/optimizer/sampling_pushdown.cpp new file mode 100644 index 00000000000..93487c8d887 --- /dev/null +++ b/src/optimizer/sampling_pushdown.cpp @@ -0,0 +1,26 @@ +#include "duckdb/optimizer/sampling_pushdown.hpp" +#include "duckdb/planner/operator/logical_get.hpp" +#include "duckdb/planner/operator/logical_sample.hpp" +#include "duckdb/common/types/value.hpp" +namespace duckdb { + +unique_ptr SamplingPushdown::Optimize(unique_ptr op) { + if (op->type == LogicalOperatorType::LOGICAL_SAMPLE && + op->Cast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && + op->Cast().sample_options->is_percentage && + op->children[0]->Cast().function.name == "seq_scan" && + op->children[0]->type == LogicalOperatorType::LOGICAL_GET && + op->children[0]->children.empty()) { + auto &get = op->children[0]->Cast(); + // set sampling pushdown options + get.function.sampling_pushdown = true; + get.function.sample_rate = op->Cast().sample_options->sample_size.GetValue() / 100.0; + op = std::move(op->children[0]); + } + for (auto &child : op->children) { + child = Optimize(std::move(child)); + } + return op; +} + +} // namespace duckdb \ No newline at end of file diff --git a/src/parallel/pipeline_executor.cpp b/src/parallel/pipeline_executor.cpp index ba89449b06f..27c34296e70 100644 --- a/src/parallel/pipeline_executor.cpp +++ b/src/parallel/pipeline_executor.cpp @@ -463,16 +463,6 @@ SourceResultType PipelineExecutor::GetData(DataChunk &chunk, OperatorSourceInput return SourceResultType::BLOCKED; } #endif - if (pipeline.operators.size() > 0) { - auto &op = pipeline.operators[0].get(); - if (op.type == PhysicalStreamingSample::TYPE) { - auto &cast_op = op.Cast(); - if (cast_op.method == SampleMethod::CHUNK_SAMPLE) { - chunk.chunk_sample_op.do_chunk_sample = true; - chunk.chunk_sample_op.percentage = cast_op.percentage; - } - } - } return pipeline.source->GetData(context, chunk, input); } diff --git a/src/storage/table/row_group.cpp b/src/storage/table/row_group.cpp index 1cc641ca38e..c0d770e253d 100644 --- a/src/storage/table/row_group.cpp +++ b/src/storage/table/row_group.cpp @@ -459,9 +459,9 @@ void RowGroup::TemplatedScan(TransactionData transaction, CollectionScanState &s idx_t current_row = state.vector_index * STANDARD_VECTOR_SIZE; auto max_count = MinValue(STANDARD_VECTOR_SIZE, state.max_row_group_row - current_row); - // table sample blocks - if (result.chunk_sample_op.do_chunk_sample) { - if (state.random.NextRandom() > result.chunk_sample_op.percentage) { + // check if we have to sample this chunk + if (result.sampling_pushdown_option.do_system_sample) { + if (state.random.NextRandom() > result.sampling_pushdown_option.sample_rate) { NextVector(state); continue; } From 0ca906094e70fb062e88a05e67579ee96e190ae2 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Tue, 25 Jun 2024 23:26:12 -0400 Subject: [PATCH 09/89] clean up --- scripts/generate_enum_util.py | 7 +------ src/common/enum_util.cpp | 5 ----- .../operator/helper/physical_streaming_sample.cpp | 8 -------- src/execution/physical_plan/plan_sample.cpp | 1 - src/include/duckdb/common/types/data_chunk.hpp | 1 - .../operator/helper/physical_streaming_sample.hpp | 1 - src/include/duckdb/parser/parsed_data/sample_options.hpp | 2 +- src/parallel/pipeline_executor.cpp | 2 +- src/parser/transform/helpers/transform_sample.cpp | 2 -- 9 files changed, 3 insertions(+), 26 deletions(-) diff --git a/scripts/generate_enum_util.py b/scripts/generate_enum_util.py index 4c35b4b0794..5244050842f 100644 --- a/scripts/generate_enum_util.py +++ b/scripts/generate_enum_util.py @@ -31,12 +31,7 @@ "NULLS_FIRST": ["NULLS_FIRST", "NULLS FIRST"], "NULLS_LAST": ["NULLS_LAST", "NULLS LAST"], }, - "SampleMethod": { - "SYSTEM_SAMPLE": "System", - "BERNOULLI_SAMPLE": "Bernoulli", - "RESERVOIR_SAMPLE": "Reservoir", - "CHUNK_SAMPLE": "Chunk", - }, + "SampleMethod": {"SYSTEM_SAMPLE": "System", "BERNOULLI_SAMPLE": "Bernoulli", "RESERVOIR_SAMPLE": "Reservoir"}, "TableReferenceType": {"EMPTY_FROM": "EMPTY"}, } diff --git a/src/common/enum_util.cpp b/src/common/enum_util.cpp index 51917b3fcb8..7cc96e1e348 100644 --- a/src/common/enum_util.cpp +++ b/src/common/enum_util.cpp @@ -5911,8 +5911,6 @@ const char* EnumUtil::ToChars(SampleMethod value) { return "Bernoulli"; case SampleMethod::RESERVOIR_SAMPLE: return "Reservoir"; - case SampleMethod::CHUNK_SAMPLE: - return "Chunk"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } @@ -5929,9 +5927,6 @@ SampleMethod EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "Reservoir")) { return SampleMethod::RESERVOIR_SAMPLE; } - if (StringUtil::Equals(value, "Chunk")) { - return SampleMethod::CHUNK_SAMPLE; - } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } diff --git a/src/execution/operator/helper/physical_streaming_sample.cpp b/src/execution/operator/helper/physical_streaming_sample.cpp index 264b6c22a73..cda2fa251ee 100644 --- a/src/execution/operator/helper/physical_streaming_sample.cpp +++ b/src/execution/operator/helper/physical_streaming_sample.cpp @@ -49,11 +49,6 @@ void PhysicalStreamingSample::BernoulliSample(DataChunk &input, DataChunk &resul } } -void PhysicalStreamingSample::ChunkSample(DataChunk &input, DataChunk &result, OperatorState &state_p) const { - // chunk sampling: identity function - result.Reference(input); -} - unique_ptr PhysicalStreamingSample::GetOperatorState(ExecutionContext &context) const { return make_uniq(seed); } @@ -67,9 +62,6 @@ OperatorResultType PhysicalStreamingSample::Execute(ExecutionContext &context, D case SampleMethod::SYSTEM_SAMPLE: SystemSample(input, chunk, state); break; - case SampleMethod::CHUNK_SAMPLE: - ChunkSample(input, chunk, state); - break; default: throw InternalException("Unsupported sample method for streaming sample"); } diff --git a/src/execution/physical_plan/plan_sample.cpp b/src/execution/physical_plan/plan_sample.cpp index 50a9d72a5bc..e13ef8eb1f7 100644 --- a/src/execution/physical_plan/plan_sample.cpp +++ b/src/execution/physical_plan/plan_sample.cpp @@ -18,7 +18,6 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalSample &op break; case SampleMethod::SYSTEM_SAMPLE: case SampleMethod::BERNOULLI_SAMPLE: - case SampleMethod::CHUNK_SAMPLE: if (!op.sample_options->is_percentage) { throw ParserException("Sample method %s cannot be used with a discrete sample count, either switch to " "reservoir sampling or use a sample_size", diff --git a/src/include/duckdb/common/types/data_chunk.hpp b/src/include/duckdb/common/types/data_chunk.hpp index 03e5e486386..4ce27a00cc8 100644 --- a/src/include/duckdb/common/types/data_chunk.hpp +++ b/src/include/duckdb/common/types/data_chunk.hpp @@ -13,7 +13,6 @@ #include "duckdb/common/common.hpp" #include "duckdb/common/types/vector.hpp" #include "duckdb/common/winapi.hpp" -// #include "duckdb/parallel/pipeline.hpp" namespace duckdb { class Allocator; diff --git a/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp b/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp index 0009de20c8d..40445cf52ee 100644 --- a/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp +++ b/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp @@ -41,7 +41,6 @@ class PhysicalStreamingSample : public PhysicalOperator { private: void SystemSample(DataChunk &input, DataChunk &result, OperatorState &state) const; void BernoulliSample(DataChunk &input, DataChunk &result, OperatorState &state) const; - void ChunkSample(DataChunk &input, DataChunk &result, OperatorState &state) const; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/parsed_data/sample_options.hpp b/src/include/duckdb/parser/parsed_data/sample_options.hpp index 95b5b6729da..201469bcf2a 100644 --- a/src/include/duckdb/parser/parsed_data/sample_options.hpp +++ b/src/include/duckdb/parser/parsed_data/sample_options.hpp @@ -15,7 +15,7 @@ namespace duckdb { -enum class SampleMethod : uint8_t { SYSTEM_SAMPLE = 0, BERNOULLI_SAMPLE = 1, RESERVOIR_SAMPLE = 2, CHUNK_SAMPLE = 3 }; +enum class SampleMethod : uint8_t { SYSTEM_SAMPLE = 0, BERNOULLI_SAMPLE = 1, RESERVOIR_SAMPLE = 2 }; // **DEPRECATED**: Use EnumUtil directly instead. string SampleMethodToString(SampleMethod method); diff --git a/src/parallel/pipeline_executor.cpp b/src/parallel/pipeline_executor.cpp index 27c34296e70..18bb5e745f0 100644 --- a/src/parallel/pipeline_executor.cpp +++ b/src/parallel/pipeline_executor.cpp @@ -1,7 +1,6 @@ #include "duckdb/parallel/pipeline_executor.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/common/limits.hpp" -#include "duckdb/execution/operator/helper/physical_streaming_sample.hpp" #ifdef DUCKDB_DEBUG_ASYNC_SINK_SOURCE #include @@ -463,6 +462,7 @@ SourceResultType PipelineExecutor::GetData(DataChunk &chunk, OperatorSourceInput return SourceResultType::BLOCKED; } #endif + return pipeline.source->GetData(context, chunk, input); } diff --git a/src/parser/transform/helpers/transform_sample.cpp b/src/parser/transform/helpers/transform_sample.cpp index a6582f6673e..0cffebfed4a 100644 --- a/src/parser/transform/helpers/transform_sample.cpp +++ b/src/parser/transform/helpers/transform_sample.cpp @@ -13,8 +13,6 @@ static SampleMethod GetSampleMethod(const string &method) { return SampleMethod::BERNOULLI_SAMPLE; } else if (lmethod == "reservoir") { return SampleMethod::RESERVOIR_SAMPLE; - } else if (lmethod == "chunk") { - return SampleMethod::CHUNK_SAMPLE; } else { throw ParserException("Unrecognized sampling method %s, expected system, bernoulli or reservoir", method); } From ae2b3c26104721c20d20cbc8b54f6b898e426d59 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Tue, 25 Jun 2024 23:36:36 -0400 Subject: [PATCH 10/89] fix format --- src/common/enums/optimizer_type.cpp | 2 +- .../duckdb/common/types/data_chunk.hpp | 2 +- .../duckdb/optimizer/sampling_pushdown.hpp | 2 +- src/optimizer/sampling_pushdown.cpp | 29 +++++++++---------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/common/enums/optimizer_type.cpp b/src/common/enums/optimizer_type.cpp index 3f87b19e109..29416a48e9f 100644 --- a/src/common/enums/optimizer_type.cpp +++ b/src/common/enums/optimizer_type.cpp @@ -30,7 +30,7 @@ static const DefaultOptimizerType internal_optimizer_types[] = { {"compressed_materialization", OptimizerType::COMPRESSED_MATERIALIZATION}, {"duplicate_groups", OptimizerType::DUPLICATE_GROUPS}, {"reorder_filter", OptimizerType::REORDER_FILTER}, - {"sampling_pushdown", OptimizerType::SAMPLING_PUSHDOWN}, + {"sampling_pushdown", OptimizerType::SAMPLING_PUSHDOWN}, {"extension", OptimizerType::EXTENSION}, {nullptr, OptimizerType::INVALID}}; diff --git a/src/include/duckdb/common/types/data_chunk.hpp b/src/include/duckdb/common/types/data_chunk.hpp index 4ce27a00cc8..76dd97c2fe5 100644 --- a/src/include/duckdb/common/types/data_chunk.hpp +++ b/src/include/duckdb/common/types/data_chunk.hpp @@ -54,7 +54,7 @@ class DataChunk { //! The vectors owned by the DataChunk. vector data; - + //! Options for sampling pushdown SamplingPushdownOption sampling_pushdown_option; diff --git a/src/include/duckdb/optimizer/sampling_pushdown.hpp b/src/include/duckdb/optimizer/sampling_pushdown.hpp index 1a845682097..78c67a19986 100644 --- a/src/include/duckdb/optimizer/sampling_pushdown.hpp +++ b/src/include/duckdb/optimizer/sampling_pushdown.hpp @@ -22,4 +22,4 @@ class SamplingPushdown { unique_ptr Optimize(unique_ptr op); }; -} // namespace duckdb \ No newline at end of file +} // namespace duckdb diff --git a/src/optimizer/sampling_pushdown.cpp b/src/optimizer/sampling_pushdown.cpp index 93487c8d887..89cfdfd5bbf 100644 --- a/src/optimizer/sampling_pushdown.cpp +++ b/src/optimizer/sampling_pushdown.cpp @@ -5,22 +5,21 @@ namespace duckdb { unique_ptr SamplingPushdown::Optimize(unique_ptr op) { - if (op->type == LogicalOperatorType::LOGICAL_SAMPLE && - op->Cast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && - op->Cast().sample_options->is_percentage && - op->children[0]->Cast().function.name == "seq_scan" && - op->children[0]->type == LogicalOperatorType::LOGICAL_GET && - op->children[0]->children.empty()) { - auto &get = op->children[0]->Cast(); - // set sampling pushdown options - get.function.sampling_pushdown = true; - get.function.sample_rate = op->Cast().sample_options->sample_size.GetValue() / 100.0; - op = std::move(op->children[0]); - } - for (auto &child : op->children) { + if (op->type == LogicalOperatorType::LOGICAL_SAMPLE && + op->Cast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && + op->Cast().sample_options->is_percentage && + op->children[0]->Cast().function.name == "seq_scan" && + op->children[0]->type == LogicalOperatorType::LOGICAL_GET && op->children[0]->children.empty()) { + auto &get = op->children[0]->Cast(); + // set sampling pushdown options + get.function.sampling_pushdown = true; + get.function.sample_rate = op->Cast().sample_options->sample_size.GetValue() / 100.0; + op = std::move(op->children[0]); + } + for (auto &child : op->children) { child = Optimize(std::move(child)); } - return op; + return op; } -} // namespace duckdb \ No newline at end of file +} // namespace duckdb From 2a048d269c36acac1c57928c088d17740ab4c57c Mon Sep 17 00:00:00 2001 From: yuxuan Date: Wed, 26 Jun 2024 09:30:19 -0400 Subject: [PATCH 11/89] fix --- src/common/enum_util.cpp | 2 ++ src/optimizer/sampling_pushdown.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/common/enum_util.cpp b/src/common/enum_util.cpp index 7cc96e1e348..14e7615cdb9 100644 --- a/src/common/enum_util.cpp +++ b/src/common/enum_util.cpp @@ -4498,6 +4498,8 @@ const char* EnumUtil::ToChars(OptimizerType value) { return "DUPLICATE_GROUPS"; case OptimizerType::REORDER_FILTER: return "REORDER_FILTER"; + case OptimizerType::SAMPLING_PUSHDOWN: + return "SAMPLING_PUSHDOWN"; case OptimizerType::EXTENSION: return "EXTENSION"; default: diff --git a/src/optimizer/sampling_pushdown.cpp b/src/optimizer/sampling_pushdown.cpp index 89cfdfd5bbf..a33f2a8df71 100644 --- a/src/optimizer/sampling_pushdown.cpp +++ b/src/optimizer/sampling_pushdown.cpp @@ -2,14 +2,17 @@ #include "duckdb/planner/operator/logical_get.hpp" #include "duckdb/planner/operator/logical_sample.hpp" #include "duckdb/common/types/value.hpp" +#include namespace duckdb { unique_ptr SamplingPushdown::Optimize(unique_ptr op) { if (op->type == LogicalOperatorType::LOGICAL_SAMPLE && op->Cast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && op->Cast().sample_options->is_percentage && + !op->children.empty() && op->children[0]->Cast().function.name == "seq_scan" && op->children[0]->type == LogicalOperatorType::LOGICAL_GET && op->children[0]->children.empty()) { + std::cout << "Optimizing sampling pushdown" << std::endl; auto &get = op->children[0]->Cast(); // set sampling pushdown options get.function.sampling_pushdown = true; From 054ad619a96a96c2ae1d391a7c120fbcf0cf6fb6 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Wed, 26 Jun 2024 10:50:23 -0400 Subject: [PATCH 12/89] fix --- src/optimizer/sampling_pushdown.cpp | 8 ++--- test/optimizer/sampling_pushdown.test | 52 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 test/optimizer/sampling_pushdown.test diff --git a/src/optimizer/sampling_pushdown.cpp b/src/optimizer/sampling_pushdown.cpp index a33f2a8df71..bfcc927ebe9 100644 --- a/src/optimizer/sampling_pushdown.cpp +++ b/src/optimizer/sampling_pushdown.cpp @@ -2,17 +2,13 @@ #include "duckdb/planner/operator/logical_get.hpp" #include "duckdb/planner/operator/logical_sample.hpp" #include "duckdb/common/types/value.hpp" -#include namespace duckdb { unique_ptr SamplingPushdown::Optimize(unique_ptr op) { if (op->type == LogicalOperatorType::LOGICAL_SAMPLE && op->Cast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && - op->Cast().sample_options->is_percentage && - !op->children.empty() && - op->children[0]->Cast().function.name == "seq_scan" && - op->children[0]->type == LogicalOperatorType::LOGICAL_GET && op->children[0]->children.empty()) { - std::cout << "Optimizing sampling pushdown" << std::endl; + !op->children.empty() && op->children[0]->type == LogicalOperatorType::LOGICAL_GET && + op->children[0]->Cast().function.name == "seq_scan" && op->children[0]->children.empty()) { auto &get = op->children[0]->Cast(); // set sampling pushdown options get.function.sampling_pushdown = true; diff --git a/test/optimizer/sampling_pushdown.test b/test/optimizer/sampling_pushdown.test new file mode 100644 index 00000000000..9c40b4fa49e --- /dev/null +++ b/test/optimizer/sampling_pushdown.test @@ -0,0 +1,52 @@ +# name: test/optimizer/sampling_pushdown.test +# description: Test Sampling Pushdown optimization +# group: [optimizer] + +statement ok +CREATE TABLE integers1(i INTEGER, j INTEGER) + +statement ok +CREATE TABLE integers2(i INTEGER, j INTEGER) + +statement ok +INSERT INTO integers1 VALUES (1,1), (2,2), (3, 3), (4,4) + +statement ok +INSERT INTO integers2 VALUES (1,1), (2,2), (3, 3), (4,4) + + +# tablesample system + seq scan becomes sample scan +query II +EXPLAIN SELECT i FROM integers1 tablesample system(0.1%) +---- +physical_plan :.*SEQ_SCAN.*System Sample: 0.10%.* + +# using sample system + seq scan becomes sample scan +query II +EXPLAIN SELECT i FROM integers1 using sample system(0.1%) +---- +physical_plan :.*SEQ_SCAN.*System Sample: 0.10%.* + +# tablesample system + seq scan with join becomes sample scan with join +query II +EXPLAIN SELECT * FROM integers1 tablesample system(0.1%), integers2 tablesample system(0.1%) +---- +physical_plan :.*SEQ_SCAN.*System Sample: 0.10%.* + +# tablesample bernoulli: no pushdown +query II +EXPLAIN SELECT i FROM integers1 tablesample bernoulli(0.1%) +---- +physical_plan :.*Bernoulli.*SEQ_SCAN.* + +# tablesample reservoir: no pushdown +query II +EXPLAIN SELECT i FROM integers1 tablesample reservoir(0.1%) +---- +physical_plan :.*RESERVOIR_SAMPLE.*SEQ_SCAN.* + +# tablesample system after a derived table: no pushdown +query II +EXPLAIN SELECT * FROM integers1, integers2 where integers1.i = integers2.i USING SAMPLE SYSTEM(25%) +---- +physical_plan :.*System.*SEQ_SCAN.* \ No newline at end of file From 8f796d63b664fecfe8a42720e1708742969cdbeb Mon Sep 17 00:00:00 2001 From: yuxuan Date: Wed, 26 Jun 2024 10:53:33 -0400 Subject: [PATCH 13/89] fix format --- src/optimizer/sampling_pushdown.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/optimizer/sampling_pushdown.cpp b/src/optimizer/sampling_pushdown.cpp index bfcc927ebe9..3eccfb50696 100644 --- a/src/optimizer/sampling_pushdown.cpp +++ b/src/optimizer/sampling_pushdown.cpp @@ -6,8 +6,8 @@ namespace duckdb { unique_ptr SamplingPushdown::Optimize(unique_ptr op) { if (op->type == LogicalOperatorType::LOGICAL_SAMPLE && - op->Cast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && - !op->children.empty() && op->children[0]->type == LogicalOperatorType::LOGICAL_GET && + op->Cast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && !op->children.empty() && + op->children[0]->type == LogicalOperatorType::LOGICAL_GET && op->children[0]->Cast().function.name == "seq_scan" && op->children[0]->children.empty()) { auto &get = op->children[0]->Cast(); // set sampling pushdown options From 49d2633630d4a9fb6a69ca55c37e44ddb1be7dfa Mon Sep 17 00:00:00 2001 From: yuxuan Date: Wed, 26 Jun 2024 10:58:00 -0400 Subject: [PATCH 14/89] fix format --- src/common/enum_util.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/enum_util.cpp b/src/common/enum_util.cpp index 14e7615cdb9..114df1e8d51 100644 --- a/src/common/enum_util.cpp +++ b/src/common/enum_util.cpp @@ -4569,6 +4569,9 @@ OptimizerType EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "REORDER_FILTER")) { return OptimizerType::REORDER_FILTER; } + if (StringUtil::Equals(value, "SAMPLING_PUSHDOWN")) { + return OptimizerType::SAMPLING_PUSHDOWN; + } if (StringUtil::Equals(value, "EXTENSION")) { return OptimizerType::EXTENSION; } From 3b718c1fcd36790a87eef41a656029100fb028bb Mon Sep 17 00:00:00 2001 From: yuxuan Date: Wed, 26 Jun 2024 11:27:18 -0400 Subject: [PATCH 15/89] clean chunk sample --- scripts/generate_enum_util.py | 6 +----- src/common/enum_util.cpp | 5 ----- .../operator/helper/physical_streaming_sample.cpp | 8 -------- src/execution/physical_plan/plan_sample.cpp | 1 - src/include/duckdb/common/types/data_chunk.hpp | 1 - .../operator/helper/physical_streaming_sample.hpp | 1 - .../duckdb/parser/parsed_data/sample_options.hpp | 2 +- src/parallel/pipeline_executor.cpp | 12 +----------- 8 files changed, 3 insertions(+), 33 deletions(-) diff --git a/scripts/generate_enum_util.py b/scripts/generate_enum_util.py index 4c35b4b0794..aec89135481 100644 --- a/scripts/generate_enum_util.py +++ b/scripts/generate_enum_util.py @@ -32,11 +32,7 @@ "NULLS_LAST": ["NULLS_LAST", "NULLS LAST"], }, "SampleMethod": { - "SYSTEM_SAMPLE": "System", - "BERNOULLI_SAMPLE": "Bernoulli", - "RESERVOIR_SAMPLE": "Reservoir", - "CHUNK_SAMPLE": "Chunk", - }, + "SYSTEM_SAMPLE": "System", "BERNOULLI_SAMPLE": "Bernoulli", "RESERVOIR_SAMPLE": "Reservoir"}, "TableReferenceType": {"EMPTY_FROM": "EMPTY"}, } diff --git a/src/common/enum_util.cpp b/src/common/enum_util.cpp index c4b03a49f8b..114df1e8d51 100644 --- a/src/common/enum_util.cpp +++ b/src/common/enum_util.cpp @@ -5916,8 +5916,6 @@ const char* EnumUtil::ToChars(SampleMethod value) { return "Bernoulli"; case SampleMethod::RESERVOIR_SAMPLE: return "Reservoir"; - case SampleMethod::CHUNK_SAMPLE: - return "Chunk"; default: throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value)); } @@ -5934,9 +5932,6 @@ SampleMethod EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "Reservoir")) { return SampleMethod::RESERVOIR_SAMPLE; } - if (StringUtil::Equals(value, "Chunk")) { - return SampleMethod::CHUNK_SAMPLE; - } throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value)); } diff --git a/src/execution/operator/helper/physical_streaming_sample.cpp b/src/execution/operator/helper/physical_streaming_sample.cpp index 264b6c22a73..cda2fa251ee 100644 --- a/src/execution/operator/helper/physical_streaming_sample.cpp +++ b/src/execution/operator/helper/physical_streaming_sample.cpp @@ -49,11 +49,6 @@ void PhysicalStreamingSample::BernoulliSample(DataChunk &input, DataChunk &resul } } -void PhysicalStreamingSample::ChunkSample(DataChunk &input, DataChunk &result, OperatorState &state_p) const { - // chunk sampling: identity function - result.Reference(input); -} - unique_ptr PhysicalStreamingSample::GetOperatorState(ExecutionContext &context) const { return make_uniq(seed); } @@ -67,9 +62,6 @@ OperatorResultType PhysicalStreamingSample::Execute(ExecutionContext &context, D case SampleMethod::SYSTEM_SAMPLE: SystemSample(input, chunk, state); break; - case SampleMethod::CHUNK_SAMPLE: - ChunkSample(input, chunk, state); - break; default: throw InternalException("Unsupported sample method for streaming sample"); } diff --git a/src/execution/physical_plan/plan_sample.cpp b/src/execution/physical_plan/plan_sample.cpp index 50a9d72a5bc..e13ef8eb1f7 100644 --- a/src/execution/physical_plan/plan_sample.cpp +++ b/src/execution/physical_plan/plan_sample.cpp @@ -18,7 +18,6 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalSample &op break; case SampleMethod::SYSTEM_SAMPLE: case SampleMethod::BERNOULLI_SAMPLE: - case SampleMethod::CHUNK_SAMPLE: if (!op.sample_options->is_percentage) { throw ParserException("Sample method %s cannot be used with a discrete sample count, either switch to " "reservoir sampling or use a sample_size", diff --git a/src/include/duckdb/common/types/data_chunk.hpp b/src/include/duckdb/common/types/data_chunk.hpp index 3a68a1a41ed..203cc117219 100644 --- a/src/include/duckdb/common/types/data_chunk.hpp +++ b/src/include/duckdb/common/types/data_chunk.hpp @@ -13,7 +13,6 @@ #include "duckdb/common/common.hpp" #include "duckdb/common/types/vector.hpp" #include "duckdb/common/winapi.hpp" -// #include "duckdb/parallel/pipeline.hpp" namespace duckdb { class Allocator; diff --git a/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp b/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp index 0009de20c8d..40445cf52ee 100644 --- a/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp +++ b/src/include/duckdb/execution/operator/helper/physical_streaming_sample.hpp @@ -41,7 +41,6 @@ class PhysicalStreamingSample : public PhysicalOperator { private: void SystemSample(DataChunk &input, DataChunk &result, OperatorState &state) const; void BernoulliSample(DataChunk &input, DataChunk &result, OperatorState &state) const; - void ChunkSample(DataChunk &input, DataChunk &result, OperatorState &state) const; }; } // namespace duckdb diff --git a/src/include/duckdb/parser/parsed_data/sample_options.hpp b/src/include/duckdb/parser/parsed_data/sample_options.hpp index 95b5b6729da..201469bcf2a 100644 --- a/src/include/duckdb/parser/parsed_data/sample_options.hpp +++ b/src/include/duckdb/parser/parsed_data/sample_options.hpp @@ -15,7 +15,7 @@ namespace duckdb { -enum class SampleMethod : uint8_t { SYSTEM_SAMPLE = 0, BERNOULLI_SAMPLE = 1, RESERVOIR_SAMPLE = 2, CHUNK_SAMPLE = 3 }; +enum class SampleMethod : uint8_t { SYSTEM_SAMPLE = 0, BERNOULLI_SAMPLE = 1, RESERVOIR_SAMPLE = 2 }; // **DEPRECATED**: Use EnumUtil directly instead. string SampleMethodToString(SampleMethod method); diff --git a/src/parallel/pipeline_executor.cpp b/src/parallel/pipeline_executor.cpp index ba89449b06f..18bb5e745f0 100644 --- a/src/parallel/pipeline_executor.cpp +++ b/src/parallel/pipeline_executor.cpp @@ -1,7 +1,6 @@ #include "duckdb/parallel/pipeline_executor.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/common/limits.hpp" -#include "duckdb/execution/operator/helper/physical_streaming_sample.hpp" #ifdef DUCKDB_DEBUG_ASYNC_SINK_SOURCE #include @@ -463,16 +462,7 @@ SourceResultType PipelineExecutor::GetData(DataChunk &chunk, OperatorSourceInput return SourceResultType::BLOCKED; } #endif - if (pipeline.operators.size() > 0) { - auto &op = pipeline.operators[0].get(); - if (op.type == PhysicalStreamingSample::TYPE) { - auto &cast_op = op.Cast(); - if (cast_op.method == SampleMethod::CHUNK_SAMPLE) { - chunk.chunk_sample_op.do_chunk_sample = true; - chunk.chunk_sample_op.percentage = cast_op.percentage; - } - } - } + return pipeline.source->GetData(context, chunk, input); } From f064bd76574cdf2c10632e7a007deea064bc2b5d Mon Sep 17 00:00:00 2001 From: yuxuan Date: Wed, 26 Jun 2024 11:28:40 -0400 Subject: [PATCH 16/89] clean up chunk sample --- scripts/generate_enum_util.py | 3 +-- src/parser/transform/helpers/transform_sample.cpp | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/generate_enum_util.py b/scripts/generate_enum_util.py index aec89135481..5244050842f 100644 --- a/scripts/generate_enum_util.py +++ b/scripts/generate_enum_util.py @@ -31,8 +31,7 @@ "NULLS_FIRST": ["NULLS_FIRST", "NULLS FIRST"], "NULLS_LAST": ["NULLS_LAST", "NULLS LAST"], }, - "SampleMethod": { - "SYSTEM_SAMPLE": "System", "BERNOULLI_SAMPLE": "Bernoulli", "RESERVOIR_SAMPLE": "Reservoir"}, + "SampleMethod": {"SYSTEM_SAMPLE": "System", "BERNOULLI_SAMPLE": "Bernoulli", "RESERVOIR_SAMPLE": "Reservoir"}, "TableReferenceType": {"EMPTY_FROM": "EMPTY"}, } diff --git a/src/parser/transform/helpers/transform_sample.cpp b/src/parser/transform/helpers/transform_sample.cpp index a6582f6673e..0cffebfed4a 100644 --- a/src/parser/transform/helpers/transform_sample.cpp +++ b/src/parser/transform/helpers/transform_sample.cpp @@ -13,8 +13,6 @@ static SampleMethod GetSampleMethod(const string &method) { return SampleMethod::BERNOULLI_SAMPLE; } else if (lmethod == "reservoir") { return SampleMethod::RESERVOIR_SAMPLE; - } else if (lmethod == "chunk") { - return SampleMethod::CHUNK_SAMPLE; } else { throw ParserException("Unrecognized sampling method %s, expected system, bernoulli or reservoir", method); } From f3b3ebfaaf983ef1229e56c7946d335bb0c80128 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Wed, 26 Jun 2024 12:44:05 -0400 Subject: [PATCH 17/89] fix invalid sampling method and size --- src/optimizer/sampling_pushdown.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/optimizer/sampling_pushdown.cpp b/src/optimizer/sampling_pushdown.cpp index 3eccfb50696..be9a7c973be 100644 --- a/src/optimizer/sampling_pushdown.cpp +++ b/src/optimizer/sampling_pushdown.cpp @@ -6,7 +6,8 @@ namespace duckdb { unique_ptr SamplingPushdown::Optimize(unique_ptr op) { if (op->type == LogicalOperatorType::LOGICAL_SAMPLE && - op->Cast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && !op->children.empty() && + op->Cast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && + op->Cast().sample_options->is_percentage && !op->children.empty() && op->children[0]->type == LogicalOperatorType::LOGICAL_GET && op->children[0]->Cast().function.name == "seq_scan" && op->children[0]->children.empty()) { auto &get = op->children[0]->Cast(); From 30a8f33780920bc6b968332d2aea681ea5ae13c6 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Mon, 5 Aug 2024 11:18:46 -0400 Subject: [PATCH 18/89] move `sampling rate` to operators and indicate the supportness of sample pushdown in table function --- src/execution/operator/scan/physical_table_scan.cpp | 9 ++++----- src/function/table/arrow.cpp | 2 ++ src/function/table/table_scan.cpp | 2 ++ src/function/table_function.cpp | 5 +++-- src/include/duckdb/common/enums/optimizer_type.hpp | 1 - src/include/duckdb/common/extra_operator_info.hpp | 7 +++++-- src/include/duckdb/function/table_function.hpp | 3 +-- src/optimizer/sampling_pushdown.cpp | 7 +++---- 8 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/execution/operator/scan/physical_table_scan.cpp b/src/execution/operator/scan/physical_table_scan.cpp index 79467052c2f..291e8411ad7 100644 --- a/src/execution/operator/scan/physical_table_scan.cpp +++ b/src/execution/operator/scan/physical_table_scan.cpp @@ -95,9 +95,9 @@ SourceResultType PhysicalTableScan::GetData(ExecutionContext &context, DataChunk auto &state = input.local_state.Cast(); TableFunctionInput data(bind_data.get(), state.local_state.get(), gstate.global_state.get()); - if (function.sampling_pushdown) { + if (extra_info.sample_rate != 1) { chunk.sampling_pushdown_option.do_system_sample = true; - chunk.sampling_pushdown_option.sample_rate = function.sample_rate; + chunk.sampling_pushdown_option.sample_rate = extra_info.sample_rate; } if (function.function) { function.function(context.client, data, chunk); @@ -186,9 +186,8 @@ InsertionOrderPreservingMap PhysicalTableScan::ParamsToString() const { } result["Filters"] = filters_info; } - if (function.sampling_pushdown) { - result += "\n[INFOSEPARATOR]\n"; - result += StringUtil::Format("System Sample: %.2f%%", function.sample_rate * 100); + if (extra_info.sample_rate != 100) { + result["Sample Size"] = StringUtil::Format("%.2f%%", extra_info.sample_rate * 100); } if (!extra_info.file_filters.empty()) { result["File Filters"] = extra_info.file_filters; diff --git a/src/function/table/arrow.cpp b/src/function/table/arrow.cpp index 220a9d54e73..ed18bef3d3d 100644 --- a/src/function/table/arrow.cpp +++ b/src/function/table/arrow.cpp @@ -443,6 +443,7 @@ void ArrowTableFunction::RegisterFunction(BuiltinFunctions &set) { arrow.projection_pushdown = true; arrow.filter_pushdown = true; arrow.filter_prune = true; + arrow.sample_pushdown = true; set.AddFunction(arrow); TableFunction arrow_dumb("arrow_scan_dumb", {LogicalType::POINTER, LogicalType::POINTER, LogicalType::POINTER}, @@ -452,6 +453,7 @@ void ArrowTableFunction::RegisterFunction(BuiltinFunctions &set) { arrow_dumb.projection_pushdown = false; arrow_dumb.filter_pushdown = false; arrow_dumb.filter_prune = false; + arrow_dumb.sample_pushdown = false; set.AddFunction(arrow_dumb); } diff --git a/src/function/table/table_scan.cpp b/src/function/table/table_scan.cpp index 9a8aa661499..111643ad6b6 100644 --- a/src/function/table/table_scan.cpp +++ b/src/function/table/table_scan.cpp @@ -416,6 +416,7 @@ TableFunction TableScanFunction::GetIndexScanFunction() { scan_function.get_batch_index = nullptr; scan_function.projection_pushdown = true; scan_function.filter_pushdown = false; + scan_function.sample_pushdown = false; scan_function.get_bind_info = TableScanGetBindInfo; scan_function.serialize = TableScanSerialize; scan_function.deserialize = TableScanDeserialize; @@ -437,6 +438,7 @@ TableFunction TableScanFunction::GetFunction() { scan_function.projection_pushdown = true; scan_function.filter_pushdown = true; scan_function.filter_prune = true; + scan_function.sample_pushdown = true; scan_function.serialize = TableScanSerialize; scan_function.deserialize = TableScanDeserialize; return scan_function; diff --git a/src/function/table_function.cpp b/src/function/table_function.cpp index 802f89fb6ee..e53d200fbe8 100644 --- a/src/function/table_function.cpp +++ b/src/function/table_function.cpp @@ -19,7 +19,8 @@ TableFunction::TableFunction(string name, vector arguments, table_f in_out_function_final(nullptr), statistics(nullptr), dependency(nullptr), cardinality(nullptr), pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), get_batch_index(nullptr), get_bind_info(nullptr), type_pushdown(nullptr), get_multi_file_reader(nullptr), serialize(nullptr), - deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), filter_prune(false) { + deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), filter_prune(false), + sample_pushdown(false) { } TableFunction::TableFunction(const vector &arguments, table_function_t function, @@ -33,7 +34,7 @@ TableFunction::TableFunction() cardinality(nullptr), pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), get_batch_index(nullptr), get_bind_info(nullptr), type_pushdown(nullptr), get_multi_file_reader(nullptr), serialize(nullptr), deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), - filter_prune(false) { + filter_prune(false), sample_pushdown(false) { } bool TableFunction::Equal(const TableFunction &rhs) const { diff --git a/src/include/duckdb/common/enums/optimizer_type.hpp b/src/include/duckdb/common/enums/optimizer_type.hpp index b439d167dec..2e0c0222b94 100644 --- a/src/include/duckdb/common/enums/optimizer_type.hpp +++ b/src/include/duckdb/common/enums/optimizer_type.hpp @@ -36,7 +36,6 @@ enum class OptimizerType : uint32_t { DUPLICATE_GROUPS, REORDER_FILTER, SAMPLING_PUSHDOWN, - EXTENSION JOIN_FILTER_PUSHDOWN, EXTENSION, MATERIALIZED_CTE, diff --git a/src/include/duckdb/common/extra_operator_info.hpp b/src/include/duckdb/common/extra_operator_info.hpp index ceb24638a50..75f0c50ba3e 100644 --- a/src/include/duckdb/common/extra_operator_info.hpp +++ b/src/include/duckdb/common/extra_operator_info.hpp @@ -17,9 +17,10 @@ namespace duckdb { class ExtraOperatorInfo { public: - ExtraOperatorInfo() : file_filters("") { + ExtraOperatorInfo() : file_filters(""), sample_rate(1) { } - ExtraOperatorInfo(ExtraOperatorInfo &extra_info) : file_filters(extra_info.file_filters) { + ExtraOperatorInfo(ExtraOperatorInfo &extra_info) : file_filters(extra_info.file_filters), + sample_rate(extra_info.sample_rate) { if (extra_info.total_files.IsValid()) { total_files = extra_info.total_files.GetIndex(); } @@ -34,6 +35,8 @@ class ExtraOperatorInfo { optional_idx total_files; //! Size of file list after applying filters optional_idx filtered_files; + //! Sample rate that have been pushed down into the table scan + double sample_rate; }; } // namespace duckdb diff --git a/src/include/duckdb/function/table_function.hpp b/src/include/duckdb/function/table_function.hpp index 7e658396de6..a416a33d884 100644 --- a/src/include/duckdb/function/table_function.hpp +++ b/src/include/duckdb/function/table_function.hpp @@ -296,8 +296,7 @@ class TableFunction : public SimpleNamedParameterFunction { // NOLINT: work-arou bool filter_prune; //! Whether or not the table function supports sampling pushdown. If not supported a sample will be taken after the //! table function. - bool sampling_pushdown = false; - double sample_rate; + bool sample_pushdown; //! Additional function info, passed to the bind shared_ptr function_info; diff --git a/src/optimizer/sampling_pushdown.cpp b/src/optimizer/sampling_pushdown.cpp index be9a7c973be..44ef284ff10 100644 --- a/src/optimizer/sampling_pushdown.cpp +++ b/src/optimizer/sampling_pushdown.cpp @@ -9,11 +9,10 @@ unique_ptr SamplingPushdown::Optimize(unique_ptrCast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && op->Cast().sample_options->is_percentage && !op->children.empty() && op->children[0]->type == LogicalOperatorType::LOGICAL_GET && - op->children[0]->Cast().function.name == "seq_scan" && op->children[0]->children.empty()) { + op->children[0]->Cast().function.sample_pushdown && op->children[0]->children.empty()) { auto &get = op->children[0]->Cast(); - // set sampling pushdown options - get.function.sampling_pushdown = true; - get.function.sample_rate = op->Cast().sample_options->sample_size.GetValue() / 100.0; + // set sampling rate + get.extra_info.sample_rate = op->Cast().sample_options->sample_size.GetValue() / 100.0; op = std::move(op->children[0]); } for (auto &child : op->children) { From 10b669b6ed251dd6351aca18b97ad5033040f46d Mon Sep 17 00:00:00 2001 From: yuxuan Date: Mon, 5 Aug 2024 15:02:09 -0400 Subject: [PATCH 19/89] fix formats --- src/execution/operator/scan/physical_table_scan.cpp | 2 +- src/function/table_function.cpp | 6 +++--- src/include/duckdb/common/extra_operator_info.hpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/execution/operator/scan/physical_table_scan.cpp b/src/execution/operator/scan/physical_table_scan.cpp index 291e8411ad7..6366b4d6da8 100644 --- a/src/execution/operator/scan/physical_table_scan.cpp +++ b/src/execution/operator/scan/physical_table_scan.cpp @@ -186,7 +186,7 @@ InsertionOrderPreservingMap PhysicalTableScan::ParamsToString() const { } result["Filters"] = filters_info; } - if (extra_info.sample_rate != 100) { + if (extra_info.sample_rate != 1) { result["Sample Size"] = StringUtil::Format("%.2f%%", extra_info.sample_rate * 100); } if (!extra_info.file_filters.empty()) { diff --git a/src/function/table_function.cpp b/src/function/table_function.cpp index e53d200fbe8..7bdfeff92a7 100644 --- a/src/function/table_function.cpp +++ b/src/function/table_function.cpp @@ -19,7 +19,7 @@ TableFunction::TableFunction(string name, vector arguments, table_f in_out_function_final(nullptr), statistics(nullptr), dependency(nullptr), cardinality(nullptr), pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), get_batch_index(nullptr), get_bind_info(nullptr), type_pushdown(nullptr), get_multi_file_reader(nullptr), serialize(nullptr), - deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), filter_prune(false), + deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), filter_prune(false), sample_pushdown(false) { } @@ -33,8 +33,8 @@ TableFunction::TableFunction() init_local(nullptr), function(nullptr), in_out_function(nullptr), statistics(nullptr), dependency(nullptr), cardinality(nullptr), pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), get_batch_index(nullptr), get_bind_info(nullptr), type_pushdown(nullptr), get_multi_file_reader(nullptr), - serialize(nullptr), deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), - filter_prune(false), sample_pushdown(false) { + serialize(nullptr), deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), filter_prune(false), + sample_pushdown(false) { } bool TableFunction::Equal(const TableFunction &rhs) const { diff --git a/src/include/duckdb/common/extra_operator_info.hpp b/src/include/duckdb/common/extra_operator_info.hpp index 75f0c50ba3e..c686cae8655 100644 --- a/src/include/duckdb/common/extra_operator_info.hpp +++ b/src/include/duckdb/common/extra_operator_info.hpp @@ -19,8 +19,8 @@ class ExtraOperatorInfo { public: ExtraOperatorInfo() : file_filters(""), sample_rate(1) { } - ExtraOperatorInfo(ExtraOperatorInfo &extra_info) : file_filters(extra_info.file_filters), - sample_rate(extra_info.sample_rate) { + ExtraOperatorInfo(ExtraOperatorInfo &extra_info) + : file_filters(extra_info.file_filters), sample_rate(extra_info.sample_rate) { if (extra_info.total_files.IsValid()) { total_files = extra_info.total_files.GetIndex(); } From aa13c7b36827a1236afeee39055abe63155e70b4 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Mon, 5 Aug 2024 16:00:28 -0400 Subject: [PATCH 20/89] fix error --- src/common/enum_util.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/enum_util.cpp b/src/common/enum_util.cpp index ffd0992f6f4..0e2b1340b5e 100644 --- a/src/common/enum_util.cpp +++ b/src/common/enum_util.cpp @@ -4650,6 +4650,7 @@ OptimizerType EnumUtil::FromString(const char *value) { } if (StringUtil::Equals(value, "SAMPLING_PUSHDOWN")) { return OptimizerType::SAMPLING_PUSHDOWN; + } if (StringUtil::Equals(value, "JOIN_FILTER_PUSHDOWN")) { return OptimizerType::JOIN_FILTER_PUSHDOWN; } From 2df57b6e9ae5be77a00a422683d9532faf1a8a35 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Mon, 5 Aug 2024 16:13:16 -0400 Subject: [PATCH 21/89] clean up --- src/execution/operator/scan/physical_table_scan.cpp | 4 ++-- src/function/table/arrow.cpp | 4 ++-- src/function/table/table_scan.cpp | 4 ++-- src/function/table_function.cpp | 4 ++-- src/include/duckdb/common/extra_operator_info.hpp | 6 ++++-- .../duckdb/execution/operator/scan/physical_table_scan.hpp | 2 +- src/include/duckdb/function/table_function.hpp | 2 +- src/include/duckdb/planner/operator/logical_get.hpp | 2 +- src/include/duckdb/storage/table/scan_state.hpp | 1 - src/optimizer/sampling_pushdown.cpp | 3 ++- 10 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/execution/operator/scan/physical_table_scan.cpp b/src/execution/operator/scan/physical_table_scan.cpp index 6366b4d6da8..9a0da1a5a3d 100644 --- a/src/execution/operator/scan/physical_table_scan.cpp +++ b/src/execution/operator/scan/physical_table_scan.cpp @@ -95,7 +95,7 @@ SourceResultType PhysicalTableScan::GetData(ExecutionContext &context, DataChunk auto &state = input.local_state.Cast(); TableFunctionInput data(bind_data.get(), state.local_state.get(), gstate.global_state.get()); - if (extra_info.sample_rate != 1) { + if (extra_info.is_sampling_pushed_down) { chunk.sampling_pushdown_option.do_system_sample = true; chunk.sampling_pushdown_option.sample_rate = extra_info.sample_rate; } @@ -186,7 +186,7 @@ InsertionOrderPreservingMap PhysicalTableScan::ParamsToString() const { } result["Filters"] = filters_info; } - if (extra_info.sample_rate != 1) { + if (extra_info.is_sampling_pushed_down) { result["Sample Size"] = StringUtil::Format("%.2f%%", extra_info.sample_rate * 100); } if (!extra_info.file_filters.empty()) { diff --git a/src/function/table/arrow.cpp b/src/function/table/arrow.cpp index ed18bef3d3d..ac9d6e45ee9 100644 --- a/src/function/table/arrow.cpp +++ b/src/function/table/arrow.cpp @@ -443,7 +443,7 @@ void ArrowTableFunction::RegisterFunction(BuiltinFunctions &set) { arrow.projection_pushdown = true; arrow.filter_pushdown = true; arrow.filter_prune = true; - arrow.sample_pushdown = true; + arrow.sampling_pushdown = true; set.AddFunction(arrow); TableFunction arrow_dumb("arrow_scan_dumb", {LogicalType::POINTER, LogicalType::POINTER, LogicalType::POINTER}, @@ -453,7 +453,7 @@ void ArrowTableFunction::RegisterFunction(BuiltinFunctions &set) { arrow_dumb.projection_pushdown = false; arrow_dumb.filter_pushdown = false; arrow_dumb.filter_prune = false; - arrow_dumb.sample_pushdown = false; + arrow_dumb.sampling_pushdown = false; set.AddFunction(arrow_dumb); } diff --git a/src/function/table/table_scan.cpp b/src/function/table/table_scan.cpp index 111643ad6b6..7661571d99a 100644 --- a/src/function/table/table_scan.cpp +++ b/src/function/table/table_scan.cpp @@ -416,7 +416,7 @@ TableFunction TableScanFunction::GetIndexScanFunction() { scan_function.get_batch_index = nullptr; scan_function.projection_pushdown = true; scan_function.filter_pushdown = false; - scan_function.sample_pushdown = false; + scan_function.sampling_pushdown = false; scan_function.get_bind_info = TableScanGetBindInfo; scan_function.serialize = TableScanSerialize; scan_function.deserialize = TableScanDeserialize; @@ -438,7 +438,7 @@ TableFunction TableScanFunction::GetFunction() { scan_function.projection_pushdown = true; scan_function.filter_pushdown = true; scan_function.filter_prune = true; - scan_function.sample_pushdown = true; + scan_function.sampling_pushdown = true; scan_function.serialize = TableScanSerialize; scan_function.deserialize = TableScanDeserialize; return scan_function; diff --git a/src/function/table_function.cpp b/src/function/table_function.cpp index 7bdfeff92a7..c619fe577ab 100644 --- a/src/function/table_function.cpp +++ b/src/function/table_function.cpp @@ -20,7 +20,7 @@ TableFunction::TableFunction(string name, vector arguments, table_f pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), get_batch_index(nullptr), get_bind_info(nullptr), type_pushdown(nullptr), get_multi_file_reader(nullptr), serialize(nullptr), deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), filter_prune(false), - sample_pushdown(false) { + sampling_pushdown(false) { } TableFunction::TableFunction(const vector &arguments, table_function_t function, @@ -34,7 +34,7 @@ TableFunction::TableFunction() cardinality(nullptr), pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), get_batch_index(nullptr), get_bind_info(nullptr), type_pushdown(nullptr), get_multi_file_reader(nullptr), serialize(nullptr), deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), filter_prune(false), - sample_pushdown(false) { + sampling_pushdown(false) { } bool TableFunction::Equal(const TableFunction &rhs) const { diff --git a/src/include/duckdb/common/extra_operator_info.hpp b/src/include/duckdb/common/extra_operator_info.hpp index c686cae8655..988defc5d2d 100644 --- a/src/include/duckdb/common/extra_operator_info.hpp +++ b/src/include/duckdb/common/extra_operator_info.hpp @@ -17,10 +17,10 @@ namespace duckdb { class ExtraOperatorInfo { public: - ExtraOperatorInfo() : file_filters(""), sample_rate(1) { + ExtraOperatorInfo() : file_filters(""), is_sampling_pushed_down(false) { } ExtraOperatorInfo(ExtraOperatorInfo &extra_info) - : file_filters(extra_info.file_filters), sample_rate(extra_info.sample_rate) { + : file_filters(extra_info.file_filters), is_sampling_pushed_down(false) { if (extra_info.total_files.IsValid()) { total_files = extra_info.total_files.GetIndex(); } @@ -35,6 +35,8 @@ class ExtraOperatorInfo { optional_idx total_files; //! Size of file list after applying filters optional_idx filtered_files; + //! Whether sampling is pushed down into the table scan + bool is_sampling_pushed_down; //! Sample rate that have been pushed down into the table scan double sample_rate; }; diff --git a/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp b/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp index 13d6a233ecd..3827a31df61 100644 --- a/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp +++ b/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp @@ -42,7 +42,7 @@ class PhysicalTableScan : public PhysicalOperator { vector names; //! The table filters unique_ptr table_filters; - //! Currently stores info related to filters pushed down into MultiFileLists + //! Currently stores info related to filters pushed down into MultiFileLists and sample rate pushed down into the table scan ExtraOperatorInfo extra_info; //! Parameters vector parameters; diff --git a/src/include/duckdb/function/table_function.hpp b/src/include/duckdb/function/table_function.hpp index a416a33d884..d09b6abeb00 100644 --- a/src/include/duckdb/function/table_function.hpp +++ b/src/include/duckdb/function/table_function.hpp @@ -296,7 +296,7 @@ class TableFunction : public SimpleNamedParameterFunction { // NOLINT: work-arou bool filter_prune; //! Whether or not the table function supports sampling pushdown. If not supported a sample will be taken after the //! table function. - bool sample_pushdown; + bool sampling_pushdown; //! Additional function info, passed to the bind shared_ptr function_info; diff --git a/src/include/duckdb/planner/operator/logical_get.hpp b/src/include/duckdb/planner/operator/logical_get.hpp index f9525191982..a59a09f9955 100644 --- a/src/include/duckdb/planner/operator/logical_get.hpp +++ b/src/include/duckdb/planner/operator/logical_get.hpp @@ -49,7 +49,7 @@ class LogicalGet : public LogicalOperator { vector input_table_names; //! For a table-in-out function, the set of projected input columns vector projected_input; - //! Currently stores File Filters (as strings) applied by hive partitioning/complex filter pushdown + //! Currently stores File Filters (as strings) applied by hive partitioning/complex filter pushdown and sample rate pushed down into the table scan //! Stored so the can be included in explain output ExtraOperatorInfo extra_info; //! Contains a reference to dynamically generated table filters (through e.g. a join up in the tree) diff --git a/src/include/duckdb/storage/table/scan_state.hpp b/src/include/duckdb/storage/table/scan_state.hpp index ec3bc1c07a7..3f29e5645ef 100644 --- a/src/include/duckdb/storage/table/scan_state.hpp +++ b/src/include/duckdb/storage/table/scan_state.hpp @@ -14,7 +14,6 @@ #include "duckdb/storage/storage_lock.hpp" #include "duckdb/common/enums/scan_options.hpp" #include "duckdb/common/random_engine.hpp" -#include "duckdb/execution/adaptive_filter.hpp" #include "duckdb/storage/table/segment_lock.hpp" #include "duckdb/common/types/data_chunk.hpp" diff --git a/src/optimizer/sampling_pushdown.cpp b/src/optimizer/sampling_pushdown.cpp index 44ef284ff10..94ed29329ae 100644 --- a/src/optimizer/sampling_pushdown.cpp +++ b/src/optimizer/sampling_pushdown.cpp @@ -9,9 +9,10 @@ unique_ptr SamplingPushdown::Optimize(unique_ptrCast().sample_options->method == SampleMethod::SYSTEM_SAMPLE && op->Cast().sample_options->is_percentage && !op->children.empty() && op->children[0]->type == LogicalOperatorType::LOGICAL_GET && - op->children[0]->Cast().function.sample_pushdown && op->children[0]->children.empty()) { + op->children[0]->Cast().function.sampling_pushdown && op->children[0]->children.empty()) { auto &get = op->children[0]->Cast(); // set sampling rate + get.extra_info.is_sampling_pushed_down = true; get.extra_info.sample_rate = op->Cast().sample_options->sample_size.GetValue() / 100.0; op = std::move(op->children[0]); } From 44d19054af606990d3ba16be98d230aba7a1b8f5 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Mon, 5 Aug 2024 16:58:09 -0400 Subject: [PATCH 22/89] fix formats --- src/execution/operator/scan/physical_table_scan.cpp | 2 +- src/function/table/arrow.cpp | 2 +- src/include/duckdb/common/extra_operator_info.hpp | 3 ++- .../duckdb/execution/operator/scan/physical_table_scan.hpp | 3 ++- src/include/duckdb/planner/operator/logical_get.hpp | 3 ++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/execution/operator/scan/physical_table_scan.cpp b/src/execution/operator/scan/physical_table_scan.cpp index 9a0da1a5a3d..21928d8064d 100644 --- a/src/execution/operator/scan/physical_table_scan.cpp +++ b/src/execution/operator/scan/physical_table_scan.cpp @@ -187,7 +187,7 @@ InsertionOrderPreservingMap PhysicalTableScan::ParamsToString() const { result["Filters"] = filters_info; } if (extra_info.is_sampling_pushed_down) { - result["Sample Size"] = StringUtil::Format("%.2f%%", extra_info.sample_rate * 100); + result["Sample Method"] = "System: " + to_string(100 * extra_info.sample_rate) + "%"; } if (!extra_info.file_filters.empty()) { result["File Filters"] = extra_info.file_filters; diff --git a/src/function/table/arrow.cpp b/src/function/table/arrow.cpp index ac9d6e45ee9..91ddb98dfc5 100644 --- a/src/function/table/arrow.cpp +++ b/src/function/table/arrow.cpp @@ -443,7 +443,7 @@ void ArrowTableFunction::RegisterFunction(BuiltinFunctions &set) { arrow.projection_pushdown = true; arrow.filter_pushdown = true; arrow.filter_prune = true; - arrow.sampling_pushdown = true; + arrow.sampling_pushdown = false; set.AddFunction(arrow); TableFunction arrow_dumb("arrow_scan_dumb", {LogicalType::POINTER, LogicalType::POINTER, LogicalType::POINTER}, diff --git a/src/include/duckdb/common/extra_operator_info.hpp b/src/include/duckdb/common/extra_operator_info.hpp index 988defc5d2d..b120c4fc819 100644 --- a/src/include/duckdb/common/extra_operator_info.hpp +++ b/src/include/duckdb/common/extra_operator_info.hpp @@ -20,7 +20,8 @@ class ExtraOperatorInfo { ExtraOperatorInfo() : file_filters(""), is_sampling_pushed_down(false) { } ExtraOperatorInfo(ExtraOperatorInfo &extra_info) - : file_filters(extra_info.file_filters), is_sampling_pushed_down(false) { + : file_filters(extra_info.file_filters), is_sampling_pushed_down(extra_info.is_sampling_pushed_down), + sample_rate(extra_info.sample_rate) { if (extra_info.total_files.IsValid()) { total_files = extra_info.total_files.GetIndex(); } diff --git a/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp b/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp index 3827a31df61..99ef75c38f8 100644 --- a/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp +++ b/src/include/duckdb/execution/operator/scan/physical_table_scan.hpp @@ -42,7 +42,8 @@ class PhysicalTableScan : public PhysicalOperator { vector names; //! The table filters unique_ptr table_filters; - //! Currently stores info related to filters pushed down into MultiFileLists and sample rate pushed down into the table scan + //! Currently stores info related to filters pushed down into MultiFileLists and sample rate pushed down into the + //! table scan ExtraOperatorInfo extra_info; //! Parameters vector parameters; diff --git a/src/include/duckdb/planner/operator/logical_get.hpp b/src/include/duckdb/planner/operator/logical_get.hpp index a59a09f9955..3f0c0b19b35 100644 --- a/src/include/duckdb/planner/operator/logical_get.hpp +++ b/src/include/duckdb/planner/operator/logical_get.hpp @@ -49,7 +49,8 @@ class LogicalGet : public LogicalOperator { vector input_table_names; //! For a table-in-out function, the set of projected input columns vector projected_input; - //! Currently stores File Filters (as strings) applied by hive partitioning/complex filter pushdown and sample rate pushed down into the table scan + //! Currently stores File Filters (as strings) applied by hive partitioning/complex filter pushdown and sample rate + //! pushed down into the table scan //! Stored so the can be included in explain output ExtraOperatorInfo extra_info; //! Contains a reference to dynamically generated table filters (through e.g. a join up in the tree) From 04d2be6b5fa22ee6f4e920b4daa71726fdd3b525 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Mon, 5 Aug 2024 17:17:57 -0400 Subject: [PATCH 23/89] update test --- test/optimizer/sampling_pushdown.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/optimizer/sampling_pushdown.test b/test/optimizer/sampling_pushdown.test index 9c40b4fa49e..e064c9be935 100644 --- a/test/optimizer/sampling_pushdown.test +++ b/test/optimizer/sampling_pushdown.test @@ -19,19 +19,19 @@ INSERT INTO integers2 VALUES (1,1), (2,2), (3, 3), (4,4) query II EXPLAIN SELECT i FROM integers1 tablesample system(0.1%) ---- -physical_plan :.*SEQ_SCAN.*System Sample: 0.10%.* +physical_plan :.*SEQ_SCAN.*System: 0.100000%* # using sample system + seq scan becomes sample scan query II EXPLAIN SELECT i FROM integers1 using sample system(0.1%) ---- -physical_plan :.*SEQ_SCAN.*System Sample: 0.10%.* +physical_plan :.*SEQ_SCAN.*System: 0.100000%* # tablesample system + seq scan with join becomes sample scan with join query II EXPLAIN SELECT * FROM integers1 tablesample system(0.1%), integers2 tablesample system(0.1%) ---- -physical_plan :.*SEQ_SCAN.*System Sample: 0.10%.* +physical_plan :.*SEQ_SCAN.*System: 0.100000%* # tablesample bernoulli: no pushdown query II From 07dffdbab75db74370668054d0f604188748a486 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Mon, 5 Aug 2024 17:33:01 -0400 Subject: [PATCH 24/89] update test --- test/optimizer/sampling_pushdown.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/optimizer/sampling_pushdown.test b/test/optimizer/sampling_pushdown.test index e064c9be935..baa8d5d9aaa 100644 --- a/test/optimizer/sampling_pushdown.test +++ b/test/optimizer/sampling_pushdown.test @@ -19,19 +19,19 @@ INSERT INTO integers2 VALUES (1,1), (2,2), (3, 3), (4,4) query II EXPLAIN SELECT i FROM integers1 tablesample system(0.1%) ---- -physical_plan :.*SEQ_SCAN.*System: 0.100000%* +physical_plan :.*SEQ_SCAN.*System: 0.100000%.* # using sample system + seq scan becomes sample scan query II EXPLAIN SELECT i FROM integers1 using sample system(0.1%) ---- -physical_plan :.*SEQ_SCAN.*System: 0.100000%* +physical_plan :.*SEQ_SCAN.*System: 0.100000%.* # tablesample system + seq scan with join becomes sample scan with join query II EXPLAIN SELECT * FROM integers1 tablesample system(0.1%), integers2 tablesample system(0.1%) ---- -physical_plan :.*SEQ_SCAN.*System: 0.100000%* +physical_plan :.*SEQ_SCAN.*System: 0.100000%.* # tablesample bernoulli: no pushdown query II From 054f2ebf4bd6ccc8e26776675bb94bda0fdc4171 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Tue, 6 Aug 2024 11:39:51 -0400 Subject: [PATCH 25/89] fix tidy check --- src/include/duckdb/common/extra_operator_info.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/duckdb/common/extra_operator_info.hpp b/src/include/duckdb/common/extra_operator_info.hpp index b120c4fc819..f6cd436a3bb 100644 --- a/src/include/duckdb/common/extra_operator_info.hpp +++ b/src/include/duckdb/common/extra_operator_info.hpp @@ -12,6 +12,7 @@ #include #include #include "duckdb/common/operator/comparison_operators.hpp" +#include "duckdb/common/optional_idx.hpp" namespace duckdb { From a86fa248e0caeee3e60ebbb6a2e108cfb5ce7db4 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Tue, 10 Sep 2024 11:00:18 -0500 Subject: [PATCH 26/89] fix metric type errors --- src/common/enum_util.cpp | 5 +++++ src/common/enums/metric_type.cpp | 3 +++ src/include/duckdb/common/enums/metric_type.hpp | 1 + 3 files changed, 9 insertions(+) diff --git a/src/common/enum_util.cpp b/src/common/enum_util.cpp index 55030caeb9d..18e675cb362 100644 --- a/src/common/enum_util.cpp +++ b/src/common/enum_util.cpp @@ -4439,6 +4439,8 @@ const char* EnumUtil::ToChars(MetricsType value) { return "OPTIMIZER_BUILD_SIDE_PROBE_SIDE"; case MetricsType::OPTIMIZER_LIMIT_PUSHDOWN: return "OPTIMIZER_LIMIT_PUSHDOWN"; + case MetricsType::OPTIMIZER_SAMPLING_PUSHDOWN: + return "OPTIMIZER_SAMPLING_PUSHDOWN"; case MetricsType::OPTIMIZER_TOP_N: return "OPTIMIZER_TOP_N"; case MetricsType::OPTIMIZER_COMPRESSED_MATERIALIZATION: @@ -4565,6 +4567,9 @@ MetricsType EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "OPTIMIZER_LIMIT_PUSHDOWN")) { return MetricsType::OPTIMIZER_LIMIT_PUSHDOWN; } + if (StringUtil::Equals(value, "OPTIMIZER_SAMPLING_PUSHDOWN")) { + return MetricsType::OPTIMIZER_SAMPLING_PUSHDOWN; + } if (StringUtil::Equals(value, "OPTIMIZER_TOP_N")) { return MetricsType::OPTIMIZER_TOP_N; } diff --git a/src/common/enums/metric_type.cpp b/src/common/enums/metric_type.cpp index a317f2d6a8c..2f1f9f996d4 100644 --- a/src/common/enums/metric_type.cpp +++ b/src/common/enums/metric_type.cpp @@ -86,6 +86,8 @@ MetricsType MetricsUtils::GetOptimizerMetricByType(OptimizerType type) { return MetricsType::OPTIMIZER_BUILD_SIDE_PROBE_SIDE; case OptimizerType::LIMIT_PUSHDOWN: return MetricsType::OPTIMIZER_LIMIT_PUSHDOWN; + case OptimizerType::SAMPLING_PUSHDOWN: + return MetricsType::OPTIMIZER_SAMPLING_PUSHDOWN; case OptimizerType::TOP_N: return MetricsType::OPTIMIZER_TOP_N; case OptimizerType::COMPRESSED_MATERIALIZATION: @@ -176,6 +178,7 @@ bool MetricsUtils::IsOptimizerMetric(MetricsType type) { case MetricsType::OPTIMIZER_COLUMN_LIFETIME: case MetricsType::OPTIMIZER_BUILD_SIDE_PROBE_SIDE: case MetricsType::OPTIMIZER_LIMIT_PUSHDOWN: + case MetricsType::OPTIMIZER_SAMPLING_PUSHDOWN: case MetricsType::OPTIMIZER_TOP_N: case MetricsType::OPTIMIZER_COMPRESSED_MATERIALIZATION: case MetricsType::OPTIMIZER_DUPLICATE_GROUPS: diff --git a/src/include/duckdb/common/enums/metric_type.hpp b/src/include/duckdb/common/enums/metric_type.hpp index fdea7faf07d..92704909ba0 100644 --- a/src/include/duckdb/common/enums/metric_type.hpp +++ b/src/include/duckdb/common/enums/metric_type.hpp @@ -55,6 +55,7 @@ enum class MetricsType : uint8_t { OPTIMIZER_COLUMN_LIFETIME, OPTIMIZER_BUILD_SIDE_PROBE_SIDE, OPTIMIZER_LIMIT_PUSHDOWN, + OPTIMIZER_SAMPLING_PUSHDOWN, OPTIMIZER_TOP_N, OPTIMIZER_COMPRESSED_MATERIALIZATION, OPTIMIZER_DUPLICATE_GROUPS, From 410943ba144a99e0a0dca3b9b2a5e955fd40895f Mon Sep 17 00:00:00 2001 From: yuxuan Date: Tue, 10 Sep 2024 11:01:43 -0500 Subject: [PATCH 27/89] format fix --- src/function/table_function.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/function/table_function.cpp b/src/function/table_function.cpp index b8373f33c9b..c81aad9447b 100644 --- a/src/function/table_function.cpp +++ b/src/function/table_function.cpp @@ -19,8 +19,8 @@ TableFunction::TableFunction(string name, vector arguments, table_f in_out_function_final(nullptr), statistics(nullptr), dependency(nullptr), cardinality(nullptr), pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), get_batch_index(nullptr), get_bind_info(nullptr), type_pushdown(nullptr), get_multi_file_reader(nullptr), supports_pushdown_type(nullptr), - serialize(nullptr), deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), - filter_prune(false), sampling_pushdown(false) { + serialize(nullptr), deserialize(nullptr), projection_pushdown(false), filter_pushdown(false), filter_prune(false), + sampling_pushdown(false) { } TableFunction::TableFunction(const vector &arguments, table_function_t function, From 64894b62621c178c97fc49780852501fe193e6a7 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Sat, 14 Sep 2024 15:09:54 -0400 Subject: [PATCH 28/89] improve logic for sampling pushdown --- .../operator/scan/physical_table_scan.cpp | 13 +++++-------- src/function/table/arrow.cpp | 1 - src/function/table/table_scan.cpp | 2 +- .../duckdb/common/extra_operator_info.hpp | 12 +++++------- src/include/duckdb/common/types/data_chunk.hpp | 7 ------- src/include/duckdb/function/table_function.hpp | 5 +++-- src/include/duckdb/storage/table/scan_state.hpp | 16 +++++++++++++++- src/optimizer/sampling_pushdown.cpp | 5 ++--- src/storage/table/row_group.cpp | 10 ++++------ src/storage/table/scan_state.cpp | 14 +++++++++++++- 10 files changed, 48 insertions(+), 37 deletions(-) diff --git a/src/execution/operator/scan/physical_table_scan.cpp b/src/execution/operator/scan/physical_table_scan.cpp index 91cb761c187..17ae5c618f6 100644 --- a/src/execution/operator/scan/physical_table_scan.cpp +++ b/src/execution/operator/scan/physical_table_scan.cpp @@ -4,6 +4,7 @@ #include "duckdb/common/string_util.hpp" #include "duckdb/planner/expression/bound_conjunction_expression.hpp" #include "duckdb/transaction/transaction.hpp" +#include #include @@ -28,7 +29,7 @@ class TableScanGlobalSourceState : public GlobalSourceState { table_filters = op.dynamic_filters->GetFinalTableFilters(op, op.table_filters.get()); } if (op.function.init_global) { - TableFunctionInitInput input(op.bind_data.get(), op.column_ids, op.projection_ids, GetTableFilters(op)); + TableFunctionInitInput input(op.bind_data.get(), op.column_ids, op.projection_ids, GetTableFilters(op), op.extra_info.sample_options); global_state = op.function.init_global(context, input); if (global_state) { max_threads = global_state->MaxThreads(); @@ -71,7 +72,7 @@ class TableScanLocalSourceState : public LocalSourceState { const PhysicalTableScan &op) { if (op.function.init_local) { TableFunctionInitInput input(op.bind_data.get(), op.column_ids, op.projection_ids, - gstate.GetTableFilters(op)); + gstate.GetTableFilters(op), op.extra_info.sample_options); local_state = op.function.init_local(context, input, gstate.global_state.get()); } } @@ -95,10 +96,6 @@ SourceResultType PhysicalTableScan::GetData(ExecutionContext &context, DataChunk auto &state = input.local_state.Cast(); TableFunctionInput data(bind_data.get(), state.local_state.get(), gstate.global_state.get()); - if (extra_info.is_sampling_pushed_down) { - chunk.sampling_pushdown_option.do_system_sample = true; - chunk.sampling_pushdown_option.sample_rate = extra_info.sample_rate; - } if (function.function) { function.function(context.client, data, chunk); } else { @@ -188,8 +185,8 @@ InsertionOrderPreservingMap PhysicalTableScan::ParamsToString() const { } result["Filters"] = filters_info; } - if (extra_info.is_sampling_pushed_down) { - result["Sample Method"] = "System: " + to_string(100 * extra_info.sample_rate) + "%"; + if (extra_info.sample_options) { + result["Sample Method"] = "System: " + extra_info.sample_options->sample_size.ToString() + "%"; } if (!extra_info.file_filters.empty()) { result["File Filters"] = extra_info.file_filters; diff --git a/src/function/table/arrow.cpp b/src/function/table/arrow.cpp index 40cafa39ee4..3434e9e5335 100644 --- a/src/function/table/arrow.cpp +++ b/src/function/table/arrow.cpp @@ -563,7 +563,6 @@ void ArrowTableFunction::RegisterFunction(BuiltinFunctions &set) { arrow.projection_pushdown = true; arrow.filter_pushdown = true; arrow.filter_prune = true; - arrow.sampling_pushdown = false; arrow.supports_pushdown_type = ArrowPushdownType; set.AddFunction(arrow); diff --git a/src/function/table/table_scan.cpp b/src/function/table/table_scan.cpp index ed95201c798..75c8c994880 100644 --- a/src/function/table/table_scan.cpp +++ b/src/function/table/table_scan.cpp @@ -73,7 +73,7 @@ static unique_ptr TableScanInitLocal(ExecutionContext & auto storage_idx = GetStorageIndex(bind_data.table, col); col = storage_idx; } - result->scan_state.Initialize(std::move(column_ids), input.filters.get()); + result->scan_state.Initialize(std::move(column_ids), input.filters.get(), input.sample_options.get()); TableScanParallelStateNext(context.client, input.bind_data.get(), result.get(), gstate); if (input.CanRemoveFilterColumns()) { auto &tsgs = gstate->Cast(); diff --git a/src/include/duckdb/common/extra_operator_info.hpp b/src/include/duckdb/common/extra_operator_info.hpp index f6cd436a3bb..6b8b916c2b6 100644 --- a/src/include/duckdb/common/extra_operator_info.hpp +++ b/src/include/duckdb/common/extra_operator_info.hpp @@ -13,16 +13,16 @@ #include #include "duckdb/common/operator/comparison_operators.hpp" #include "duckdb/common/optional_idx.hpp" +#include "duckdb/parser/parsed_data/sample_options.hpp" namespace duckdb { class ExtraOperatorInfo { public: - ExtraOperatorInfo() : file_filters(""), is_sampling_pushed_down(false) { + ExtraOperatorInfo() : file_filters(""), sample_options(nullptr) { } ExtraOperatorInfo(ExtraOperatorInfo &extra_info) - : file_filters(extra_info.file_filters), is_sampling_pushed_down(extra_info.is_sampling_pushed_down), - sample_rate(extra_info.sample_rate) { + : file_filters(extra_info.file_filters), sample_options(extra_info.sample_options ? extra_info.sample_options->Copy() : nullptr) { if (extra_info.total_files.IsValid()) { total_files = extra_info.total_files.GetIndex(); } @@ -37,10 +37,8 @@ class ExtraOperatorInfo { optional_idx total_files; //! Size of file list after applying filters optional_idx filtered_files; - //! Whether sampling is pushed down into the table scan - bool is_sampling_pushed_down; - //! Sample rate that have been pushed down into the table scan - double sample_rate; + //! Sample options that have been pushed down into the main file list + unique_ptr sample_options; }; } // namespace duckdb diff --git a/src/include/duckdb/common/types/data_chunk.hpp b/src/include/duckdb/common/types/data_chunk.hpp index 203cc117219..4197ef1bacf 100644 --- a/src/include/duckdb/common/types/data_chunk.hpp +++ b/src/include/duckdb/common/types/data_chunk.hpp @@ -40,10 +40,6 @@ class Deserializer; In addition to holding the data of the vectors, the DataChunk also owns the selection vector that underlying vectors can point to. */ -struct SamplingPushdownOption { - bool do_system_sample = false; - double sample_rate = 0; -}; class DataChunk { public: @@ -54,9 +50,6 @@ class DataChunk { //! The vectors owned by the DataChunk. vector data; - //! Options for sampling pushdown - SamplingPushdownOption sampling_pushdown_option; - public: inline idx_t size() const { // NOLINT return count; diff --git a/src/include/duckdb/function/table_function.hpp b/src/include/duckdb/function/table_function.hpp index 71db74a3989..2cb043ee873 100644 --- a/src/include/duckdb/function/table_function.hpp +++ b/src/include/duckdb/function/table_function.hpp @@ -102,14 +102,15 @@ struct TableFunctionBindInput { struct TableFunctionInitInput { TableFunctionInitInput(optional_ptr bind_data_p, const vector &column_ids_p, - const vector &projection_ids_p, optional_ptr filters_p) - : bind_data(bind_data_p), column_ids(column_ids_p), projection_ids(projection_ids_p), filters(filters_p) { + const vector &projection_ids_p, optional_ptr filters_p, optional_ptr sample_options_p = nullptr) + : bind_data(bind_data_p), column_ids(column_ids_p), projection_ids(projection_ids_p), filters(filters_p), sample_options(sample_options_p) { } optional_ptr bind_data; const vector &column_ids; const vector projection_ids; optional_ptr filters; + optional_ptr sample_options; bool CanRemoveFilterColumns() const { if (projection_ids.empty()) { diff --git a/src/include/duckdb/storage/table/scan_state.hpp b/src/include/duckdb/storage/table/scan_state.hpp index dabe4a595fd..f7ba72d43dd 100644 --- a/src/include/duckdb/storage/table/scan_state.hpp +++ b/src/include/duckdb/storage/table/scan_state.hpp @@ -16,6 +16,7 @@ #include "duckdb/common/random_engine.hpp" #include "duckdb/storage/table/segment_lock.hpp" #include "duckdb/common/types/data_chunk.hpp" +#include "duckdb/parser/parsed_data/sample_options.hpp" namespace duckdb { class AdaptiveFilter; @@ -37,6 +38,7 @@ class RowGroupSegmentTree; class TableFilter; struct AdaptiveFilterState; struct TableScanOptions; +struct ScanSamplingInfo; struct SegmentScanState { virtual ~SegmentScanState() { @@ -195,6 +197,7 @@ class CollectionScanState { void Initialize(const vector &types); const vector &GetColumnIds(); ScanFilterInfo &GetFilterInfo(); + ScanSamplingInfo &GetSamplingInfo(); TableScanOptions &GetOptions(); bool Scan(DuckTransaction &transaction, DataChunk &result); bool ScanCommitted(DataChunk &result, TableScanType type); @@ -204,6 +207,13 @@ class CollectionScanState { TableScanState &parent; }; +struct ScanSamplingInfo { + //! Whether or not to do a system sample during scanning + bool do_system_sample; + //! The sampling rate to use + double sample_rate; +}; + struct TableScanOptions { //! Fetch rows one-at-a-time instead of using the regular scans. bool force_fetch_row = false; @@ -233,14 +243,18 @@ class TableScanState { shared_ptr checkpoint_lock; //! Filter info ScanFilterInfo filters; + //! Sampling info + ScanSamplingInfo sampling_info; public: - void Initialize(vector column_ids, optional_ptr table_filters = nullptr); + void Initialize(vector column_ids, optional_ptr table_filters = nullptr, optional_ptr table_sampling = nullptr); const vector &GetColumnIds(); ScanFilterInfo &GetFilterInfo(); + ScanSamplingInfo &GetSamplingInfo(); + private: //! The column identifiers of the scan vector column_ids; diff --git a/src/optimizer/sampling_pushdown.cpp b/src/optimizer/sampling_pushdown.cpp index 94ed29329ae..ca805e64e86 100644 --- a/src/optimizer/sampling_pushdown.cpp +++ b/src/optimizer/sampling_pushdown.cpp @@ -11,9 +11,8 @@ unique_ptr SamplingPushdown::Optimize(unique_ptrchildren[0]->type == LogicalOperatorType::LOGICAL_GET && op->children[0]->Cast().function.sampling_pushdown && op->children[0]->children.empty()) { auto &get = op->children[0]->Cast(); - // set sampling rate - get.extra_info.is_sampling_pushed_down = true; - get.extra_info.sample_rate = op->Cast().sample_options->sample_size.GetValue() / 100.0; + // set sampling option + get.extra_info.sample_options = std::move(op->Cast().sample_options); op = std::move(op->children[0]); } for (auto &child : op->children) { diff --git a/src/storage/table/row_group.cpp b/src/storage/table/row_group.cpp index 0b90913c182..841f302cb1c 100644 --- a/src/storage/table/row_group.cpp +++ b/src/storage/table/row_group.cpp @@ -481,12 +481,10 @@ void RowGroup::TemplatedScan(TransactionData transaction, CollectionScanState &s idx_t current_row = state.vector_index * STANDARD_VECTOR_SIZE; auto max_count = MinValue(STANDARD_VECTOR_SIZE, state.max_row_group_row - current_row); - // check if we have to sample this chunk - if (result.sampling_pushdown_option.do_system_sample) { - if (state.random.NextRandom() > result.sampling_pushdown_option.sample_rate) { - NextVector(state); - continue; - } + // check the sampling info if we have to sample this chunk + if (state.GetSamplingInfo().do_system_sample && state.random.NextRandom() > state.GetSamplingInfo().sample_rate) { + NextVector(state); + continue; } //! first check the zonemap if we have to scan this partition diff --git a/src/storage/table/scan_state.cpp b/src/storage/table/scan_state.cpp index 35d16478709..d6079769195 100644 --- a/src/storage/table/scan_state.cpp +++ b/src/storage/table/scan_state.cpp @@ -16,11 +16,15 @@ TableScanState::TableScanState() : table_state(*this), local_state(*this) { TableScanState::~TableScanState() { } -void TableScanState::Initialize(vector column_ids_p, optional_ptr table_filters) { +void TableScanState::Initialize(vector column_ids_p, optional_ptr table_filters, optional_ptr table_sampling) { this->column_ids = std::move(column_ids_p); if (table_filters) { filters.Initialize(*table_filters, column_ids); } + if (table_sampling) { + sampling_info.do_system_sample = table_sampling->method == SampleMethod::SYSTEM_SAMPLE; + sampling_info.sample_rate = table_sampling->sample_size.GetValue() / 100.0; + } } const vector &TableScanState::GetColumnIds() { @@ -35,6 +39,10 @@ ScanFilterInfo &TableScanState::GetFilterInfo() { return filters; } +ScanSamplingInfo &TableScanState::GetSamplingInfo() { + return sampling_info; +} + ScanFilter::ScanFilter(idx_t index, const vector &column_ids, TableFilter &filter) : scan_column_index(index), table_column_index(column_ids[index]), filter(filter), always_true(false) { } @@ -143,6 +151,10 @@ ScanFilterInfo &CollectionScanState::GetFilterInfo() { return parent.GetFilterInfo(); } +ScanSamplingInfo &CollectionScanState::GetSamplingInfo() { + return parent.GetSamplingInfo(); +} + TableScanOptions &CollectionScanState::GetOptions() { return parent.options; } From ca956d294e904f1a6b4e86b415a5c24c95f75f1c Mon Sep 17 00:00:00 2001 From: yuxuan Date: Sat, 14 Sep 2024 15:33:22 -0400 Subject: [PATCH 29/89] improve tests for sampling pushdown --- .../operator/scan/physical_table_scan.cpp | 1 - src/function/table/arrow.cpp | 1 - test/optimizer/sampling_pushdown.test | 6 +-- test/optimizer/sampling_pushdown.test_slow | 44 +++++++++++++++++++ 4 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 test/optimizer/sampling_pushdown.test_slow diff --git a/src/execution/operator/scan/physical_table_scan.cpp b/src/execution/operator/scan/physical_table_scan.cpp index 17ae5c618f6..f594538e2c3 100644 --- a/src/execution/operator/scan/physical_table_scan.cpp +++ b/src/execution/operator/scan/physical_table_scan.cpp @@ -4,7 +4,6 @@ #include "duckdb/common/string_util.hpp" #include "duckdb/planner/expression/bound_conjunction_expression.hpp" #include "duckdb/transaction/transaction.hpp" -#include #include diff --git a/src/function/table/arrow.cpp b/src/function/table/arrow.cpp index 3434e9e5335..16b5c5e45b8 100644 --- a/src/function/table/arrow.cpp +++ b/src/function/table/arrow.cpp @@ -573,7 +573,6 @@ void ArrowTableFunction::RegisterFunction(BuiltinFunctions &set) { arrow_dumb.projection_pushdown = false; arrow_dumb.filter_pushdown = false; arrow_dumb.filter_prune = false; - arrow_dumb.sampling_pushdown = false; set.AddFunction(arrow_dumb); } diff --git a/test/optimizer/sampling_pushdown.test b/test/optimizer/sampling_pushdown.test index baa8d5d9aaa..1113395d80c 100644 --- a/test/optimizer/sampling_pushdown.test +++ b/test/optimizer/sampling_pushdown.test @@ -19,19 +19,19 @@ INSERT INTO integers2 VALUES (1,1), (2,2), (3, 3), (4,4) query II EXPLAIN SELECT i FROM integers1 tablesample system(0.1%) ---- -physical_plan :.*SEQ_SCAN.*System: 0.100000%.* +physical_plan :.*SEQ_SCAN.*System: 0.1%.* # using sample system + seq scan becomes sample scan query II EXPLAIN SELECT i FROM integers1 using sample system(0.1%) ---- -physical_plan :.*SEQ_SCAN.*System: 0.100000%.* +physical_plan :.*SEQ_SCAN.*System: 0.1%.* # tablesample system + seq scan with join becomes sample scan with join query II EXPLAIN SELECT * FROM integers1 tablesample system(0.1%), integers2 tablesample system(0.1%) ---- -physical_plan :.*SEQ_SCAN.*System: 0.100000%.* +physical_plan :.*SEQ_SCAN.*System: 0.1%.* # tablesample bernoulli: no pushdown query II diff --git a/test/optimizer/sampling_pushdown.test_slow b/test/optimizer/sampling_pushdown.test_slow new file mode 100644 index 00000000000..8627fb8cc43 --- /dev/null +++ b/test/optimizer/sampling_pushdown.test_slow @@ -0,0 +1,44 @@ +# name: test/optimizer/sampling_pushdown.test_slow +# description: Test the performance of Sampling Pushdown optimization +# group: [optimizer] + +require tpch + +statement ok +CALL DBGEN(sf=0.1); + +# tablesample system + seq scan becomes sample scan +query II +EXPLAIN ANALYZE SELECT count(*) FROM lineitem tablesample system(0.1%) +---- +analyzed_plan :.*TABLE_SCAN.*System: 0.1%.* + +# using sample system + seq scan becomes sample scan +query II +EXPLAIN ANALYZE SELECT count(*) FROM lineitem using sample system(0.1%) +---- +analyzed_plan :.*TABLE_SCAN.*System: 0.1%.* + +# tablesample system + seq scan with join becomes sample scan with join +query II +EXPLAIN ANALYZE SELECT count(*) FROM lineitem tablesample system(0.1%), orders tablesample system(0.1%) +---- +analyzed_plan :.*TABLE_SCAN.*System: 0.1%.* + +# tablesample bernoulli: no pushdown +query II +EXPLAIN ANALYZE SELECT count(*) FROM lineitem tablesample bernoulli(0.1%) +---- +analyzed_plan :.*Bernoulli.*TABLE_SCAN.* + +# tablesample reservoir: no pushdown +query II +EXPLAIN ANALYZE SELECT count(*) FROM lineitem tablesample reservoir(0.1%) +---- +analyzed_plan :.*RESERVOIR_SAMPLE.*TABLE_SCAN.* + +# tablesample system after a derived table: no pushdown +query II +EXPLAIN ANALYZE SELECT count(*) FROM lineitem, orders where l_orderkey = o_orderkey USING SAMPLE SYSTEM(25%) +---- +analyzed_plan :.*System.*TABLE_SCAN.* \ No newline at end of file From 830e3ceffcb30d8c8a771d8fcc5614cb94efbe96 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Sat, 14 Sep 2024 15:36:52 -0400 Subject: [PATCH 30/89] fix format --- src/execution/operator/scan/physical_table_scan.cpp | 3 ++- src/include/duckdb/common/extra_operator_info.hpp | 3 ++- src/include/duckdb/function/table_function.hpp | 6 ++++-- src/include/duckdb/storage/table/scan_state.hpp | 3 ++- src/storage/table/row_group.cpp | 3 ++- src/storage/table/scan_state.cpp | 3 ++- 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/execution/operator/scan/physical_table_scan.cpp b/src/execution/operator/scan/physical_table_scan.cpp index f594538e2c3..5857e006ead 100644 --- a/src/execution/operator/scan/physical_table_scan.cpp +++ b/src/execution/operator/scan/physical_table_scan.cpp @@ -28,7 +28,8 @@ class TableScanGlobalSourceState : public GlobalSourceState { table_filters = op.dynamic_filters->GetFinalTableFilters(op, op.table_filters.get()); } if (op.function.init_global) { - TableFunctionInitInput input(op.bind_data.get(), op.column_ids, op.projection_ids, GetTableFilters(op), op.extra_info.sample_options); + TableFunctionInitInput input(op.bind_data.get(), op.column_ids, op.projection_ids, GetTableFilters(op), + op.extra_info.sample_options); global_state = op.function.init_global(context, input); if (global_state) { max_threads = global_state->MaxThreads(); diff --git a/src/include/duckdb/common/extra_operator_info.hpp b/src/include/duckdb/common/extra_operator_info.hpp index 6b8b916c2b6..2d7cbe3544f 100644 --- a/src/include/duckdb/common/extra_operator_info.hpp +++ b/src/include/duckdb/common/extra_operator_info.hpp @@ -22,7 +22,8 @@ class ExtraOperatorInfo { ExtraOperatorInfo() : file_filters(""), sample_options(nullptr) { } ExtraOperatorInfo(ExtraOperatorInfo &extra_info) - : file_filters(extra_info.file_filters), sample_options(extra_info.sample_options ? extra_info.sample_options->Copy() : nullptr) { + : file_filters(extra_info.file_filters), + sample_options(extra_info.sample_options ? extra_info.sample_options->Copy() : nullptr) { if (extra_info.total_files.IsValid()) { total_files = extra_info.total_files.GetIndex(); } diff --git a/src/include/duckdb/function/table_function.hpp b/src/include/duckdb/function/table_function.hpp index 2cb043ee873..3adbd267d92 100644 --- a/src/include/duckdb/function/table_function.hpp +++ b/src/include/duckdb/function/table_function.hpp @@ -102,8 +102,10 @@ struct TableFunctionBindInput { struct TableFunctionInitInput { TableFunctionInitInput(optional_ptr bind_data_p, const vector &column_ids_p, - const vector &projection_ids_p, optional_ptr filters_p, optional_ptr sample_options_p = nullptr) - : bind_data(bind_data_p), column_ids(column_ids_p), projection_ids(projection_ids_p), filters(filters_p), sample_options(sample_options_p) { + const vector &projection_ids_p, optional_ptr filters_p, + optional_ptr sample_options_p = nullptr) + : bind_data(bind_data_p), column_ids(column_ids_p), projection_ids(projection_ids_p), filters(filters_p), + sample_options(sample_options_p) { } optional_ptr bind_data; diff --git a/src/include/duckdb/storage/table/scan_state.hpp b/src/include/duckdb/storage/table/scan_state.hpp index f7ba72d43dd..3e6ea73b9a4 100644 --- a/src/include/duckdb/storage/table/scan_state.hpp +++ b/src/include/duckdb/storage/table/scan_state.hpp @@ -247,7 +247,8 @@ class TableScanState { ScanSamplingInfo sampling_info; public: - void Initialize(vector column_ids, optional_ptr table_filters = nullptr, optional_ptr table_sampling = nullptr); + void Initialize(vector column_ids, optional_ptr table_filters = nullptr, + optional_ptr table_sampling = nullptr); const vector &GetColumnIds(); diff --git a/src/storage/table/row_group.cpp b/src/storage/table/row_group.cpp index 841f302cb1c..39c5c1e0156 100644 --- a/src/storage/table/row_group.cpp +++ b/src/storage/table/row_group.cpp @@ -482,7 +482,8 @@ void RowGroup::TemplatedScan(TransactionData transaction, CollectionScanState &s auto max_count = MinValue(STANDARD_VECTOR_SIZE, state.max_row_group_row - current_row); // check the sampling info if we have to sample this chunk - if (state.GetSamplingInfo().do_system_sample && state.random.NextRandom() > state.GetSamplingInfo().sample_rate) { + if (state.GetSamplingInfo().do_system_sample && + state.random.NextRandom() > state.GetSamplingInfo().sample_rate) { NextVector(state); continue; } diff --git a/src/storage/table/scan_state.cpp b/src/storage/table/scan_state.cpp index d6079769195..dc4213d03a6 100644 --- a/src/storage/table/scan_state.cpp +++ b/src/storage/table/scan_state.cpp @@ -16,7 +16,8 @@ TableScanState::TableScanState() : table_state(*this), local_state(*this) { TableScanState::~TableScanState() { } -void TableScanState::Initialize(vector column_ids_p, optional_ptr table_filters, optional_ptr table_sampling) { +void TableScanState::Initialize(vector column_ids_p, optional_ptr table_filters, + optional_ptr table_sampling) { this->column_ids = std::move(column_ids_p); if (table_filters) { filters.Initialize(*table_filters, column_ids); From 749ebdf74041a199ae58c6a102d3bcf2c4f02cdb Mon Sep 17 00:00:00 2001 From: yuxuan Date: Sat, 14 Sep 2024 21:04:19 -0400 Subject: [PATCH 31/89] fix initialization problem --- src/function/table/table_scan.cpp | 1 - src/include/duckdb/common/types/data_chunk.hpp | 1 - src/include/duckdb/storage/table/scan_state.hpp | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/function/table/table_scan.cpp b/src/function/table/table_scan.cpp index 75c8c994880..6f1783756ec 100644 --- a/src/function/table/table_scan.cpp +++ b/src/function/table/table_scan.cpp @@ -415,7 +415,6 @@ TableFunction TableScanFunction::GetIndexScanFunction() { scan_function.get_batch_index = nullptr; scan_function.projection_pushdown = true; scan_function.filter_pushdown = false; - scan_function.sampling_pushdown = false; scan_function.get_bind_info = TableScanGetBindInfo; scan_function.serialize = TableScanSerialize; scan_function.deserialize = TableScanDeserialize; diff --git a/src/include/duckdb/common/types/data_chunk.hpp b/src/include/duckdb/common/types/data_chunk.hpp index 4197ef1bacf..58f6aced379 100644 --- a/src/include/duckdb/common/types/data_chunk.hpp +++ b/src/include/duckdb/common/types/data_chunk.hpp @@ -40,7 +40,6 @@ class Deserializer; In addition to holding the data of the vectors, the DataChunk also owns the selection vector that underlying vectors can point to. */ - class DataChunk { public: //! Creates an empty DataChunk diff --git a/src/include/duckdb/storage/table/scan_state.hpp b/src/include/duckdb/storage/table/scan_state.hpp index 3e6ea73b9a4..464dab42517 100644 --- a/src/include/duckdb/storage/table/scan_state.hpp +++ b/src/include/duckdb/storage/table/scan_state.hpp @@ -209,7 +209,7 @@ class CollectionScanState { struct ScanSamplingInfo { //! Whether or not to do a system sample during scanning - bool do_system_sample; + bool do_system_sample=false; //! The sampling rate to use double sample_rate; }; From 861454ae630bddba957c4c6cef969703db33ea63 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Sat, 14 Sep 2024 21:15:06 -0400 Subject: [PATCH 32/89] better initialization --- src/include/duckdb/common/extra_operator_info.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/duckdb/common/extra_operator_info.hpp b/src/include/duckdb/common/extra_operator_info.hpp index 2d7cbe3544f..78dd1c81461 100644 --- a/src/include/duckdb/common/extra_operator_info.hpp +++ b/src/include/duckdb/common/extra_operator_info.hpp @@ -23,7 +23,7 @@ class ExtraOperatorInfo { } ExtraOperatorInfo(ExtraOperatorInfo &extra_info) : file_filters(extra_info.file_filters), - sample_options(extra_info.sample_options ? extra_info.sample_options->Copy() : nullptr) { + sample_options(std::move(extra_info.sample_options)) { if (extra_info.total_files.IsValid()) { total_files = extra_info.total_files.GetIndex(); } @@ -38,7 +38,7 @@ class ExtraOperatorInfo { optional_idx total_files; //! Size of file list after applying filters optional_idx filtered_files; - //! Sample options that have been pushed down into the main file list + //! Sample options that have been pushed down into the table scan unique_ptr sample_options; }; From 519b299ffe3f97b0e5fe8dcb8bad2354809c6b6b Mon Sep 17 00:00:00 2001 From: yuxuan Date: Sat, 14 Sep 2024 23:55:02 -0400 Subject: [PATCH 33/89] fix format --- src/include/duckdb/common/extra_operator_info.hpp | 3 +-- src/include/duckdb/storage/table/scan_state.hpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/include/duckdb/common/extra_operator_info.hpp b/src/include/duckdb/common/extra_operator_info.hpp index 78dd1c81461..117be6c6104 100644 --- a/src/include/duckdb/common/extra_operator_info.hpp +++ b/src/include/duckdb/common/extra_operator_info.hpp @@ -22,8 +22,7 @@ class ExtraOperatorInfo { ExtraOperatorInfo() : file_filters(""), sample_options(nullptr) { } ExtraOperatorInfo(ExtraOperatorInfo &extra_info) - : file_filters(extra_info.file_filters), - sample_options(std::move(extra_info.sample_options)) { + : file_filters(extra_info.file_filters), sample_options(std::move(extra_info.sample_options)) { if (extra_info.total_files.IsValid()) { total_files = extra_info.total_files.GetIndex(); } diff --git a/src/include/duckdb/storage/table/scan_state.hpp b/src/include/duckdb/storage/table/scan_state.hpp index 464dab42517..2b8e0dfc951 100644 --- a/src/include/duckdb/storage/table/scan_state.hpp +++ b/src/include/duckdb/storage/table/scan_state.hpp @@ -209,7 +209,7 @@ class CollectionScanState { struct ScanSamplingInfo { //! Whether or not to do a system sample during scanning - bool do_system_sample=false; + bool do_system_sample = false; //! The sampling rate to use double sample_rate; }; From 48271dbe5de067d2ecc8499950ebc464ad38f7a5 Mon Sep 17 00:00:00 2001 From: yuxuan Date: Fri, 20 Sep 2024 10:57:33 -0500 Subject: [PATCH 34/89] Add sampling info to LogicalGet::ParamsToString --- src/planner/operator/logical_get.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/planner/operator/logical_get.cpp b/src/planner/operator/logical_get.cpp index 1ed160a7cd9..c5366998c68 100644 --- a/src/planner/operator/logical_get.cpp +++ b/src/planner/operator/logical_get.cpp @@ -48,6 +48,10 @@ InsertionOrderPreservingMap LogicalGet::ParamsToString() const { } result["Filters"] = filters_info; + if (extra_info.sample_options) { + result["Sample Method"] = "System: " + extra_info.sample_options->sample_size.ToString() + "%"; + } + if (!extra_info.file_filters.empty()) { result["File Filters"] = extra_info.file_filters; if (extra_info.filtered_files.IsValid() && extra_info.total_files.IsValid()) { From 239ce80d4f717e83d8221a04da633931db966b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20M=C3=BChleisen?= Date: Mon, 7 Oct 2024 15:15:13 +0200 Subject: [PATCH 35/89] first step parquet upgrade --- extension/parquet/CMakeLists.txt | 1 - extension/parquet/column_reader.cpp | 20 +- extension/parquet/column_writer.cpp | 80 +- extension/parquet/geo_parquet.cpp | 6 +- extension/parquet/include/column_reader.hpp | 14 +- extension/parquet/include/column_writer.hpp | 4 +- extension/parquet/include/geo_parquet.hpp | 6 +- .../parquet/include/parquet_decimal_utils.hpp | 4 +- .../include/parquet_file_metadata_cache.hpp | 4 +- extension/parquet/include/parquet_reader.hpp | 6 +- .../parquet/include/parquet_statistics.hpp | 6 +- extension/parquet/include/parquet_writer.hpp | 18 +- extension/parquet/parquet_config.py | 1 - extension/parquet/parquet_extension.cpp | 24 +- extension/parquet/parquet_metadata.cpp | 4 +- extension/parquet/parquet_reader.cpp | 18 +- extension/parquet/parquet_statistics.cpp | 16 +- extension/parquet/parquet_writer.cpp | 30 +- third_party/parquet/README | 5 + third_party/parquet/parquet.thrift | 1228 ++++ third_party/parquet/parquet_constants.cpp | 17 - third_party/parquet/parquet_constants.h | 24 - third_party/parquet/parquet_types.cpp | 5260 ++++++++++------- third_party/parquet/parquet_types.h | 2941 +++++---- 24 files changed, 6028 insertions(+), 3709 deletions(-) create mode 100644 third_party/parquet/README create mode 100644 third_party/parquet/parquet.thrift delete mode 100644 third_party/parquet/parquet_constants.cpp delete mode 100644 third_party/parquet/parquet_constants.h diff --git a/extension/parquet/CMakeLists.txt b/extension/parquet/CMakeLists.txt index 89af368aa85..b49659aa31e 100644 --- a/extension/parquet/CMakeLists.txt +++ b/extension/parquet/CMakeLists.txt @@ -31,7 +31,6 @@ if(NOT CLANG_TIDY) # parquet/thrift/snappy set(PARQUET_EXTENSION_FILES ${PARQUET_EXTENSION_FILES} - ../../third_party/parquet/parquet_constants.cpp ../../third_party/parquet/parquet_types.cpp ../../third_party/thrift/thrift/protocol/TProtocol.cpp ../../third_party/thrift/thrift/transport/TTransportException.cpp diff --git a/extension/parquet/column_reader.cpp b/extension/parquet/column_reader.cpp index 1b6d206329f..6b18a01b9f9 100644 --- a/extension/parquet/column_reader.cpp +++ b/extension/parquet/column_reader.cpp @@ -29,11 +29,11 @@ namespace duckdb { -using duckdb_parquet::format::CompressionCodec; -using duckdb_parquet::format::ConvertedType; -using duckdb_parquet::format::Encoding; -using duckdb_parquet::format::PageType; -using duckdb_parquet::format::Type; +using duckdb_parquet::CompressionCodec; +using duckdb_parquet::ConvertedType; +using duckdb_parquet::Encoding; +using duckdb_parquet::PageType; +using duckdb_parquet::Type; const uint64_t ParquetDecodeUtils::BITPACK_MASKS[] = {0, 1, @@ -541,12 +541,12 @@ idx_t ColumnReader::Read(uint64_t num_values, parquet_filter_t &filter, data_ptr auto read_buf = make_shared_ptr(); switch (schema.type) { - case duckdb_parquet::format::Type::INT32: + case duckdb_parquet::Type::INT32: read_buf->resize(reader.allocator, sizeof(int32_t) * (read_now - null_count)); dbp_decoder->GetBatch(read_buf->ptr, read_now - null_count); break; - case duckdb_parquet::format::Type::INT64: + case duckdb_parquet::Type::INT64: read_buf->resize(reader.allocator, sizeof(int64_t) * (read_now - null_count)); dbp_decoder->GetBatch(read_buf->ptr, read_now - null_count); break; @@ -571,11 +571,11 @@ idx_t ColumnReader::Read(uint64_t num_values, parquet_filter_t &filter, data_ptr auto read_buf = make_shared_ptr(); switch (schema.type) { - case duckdb_parquet::format::Type::FLOAT: + case duckdb_parquet::Type::FLOAT: read_buf->resize(reader.allocator, sizeof(float) * (read_now - null_count)); bss_decoder->GetBatch(read_buf->ptr, read_now - null_count); break; - case duckdb_parquet::format::Type::DOUBLE: + case duckdb_parquet::Type::DOUBLE: read_buf->resize(reader.allocator, sizeof(double) * (read_now - null_count)); bss_decoder->GetBatch(read_buf->ptr, read_now - null_count); break; @@ -1340,7 +1340,7 @@ static unique_ptr CreateDecimalReaderInternal(ParquetReader &reade template <> double ParquetDecimalUtils::ReadDecimalValue(const_data_ptr_t pointer, idx_t size, - const duckdb_parquet::format::SchemaElement &schema_ele) { + const duckdb_parquet::SchemaElement &schema_ele) { double res = 0; bool positive = (*pointer & 0x80) == 0; for (idx_t i = 0; i < size; i += 8) { diff --git a/extension/parquet/column_writer.cpp b/extension/parquet/column_writer.cpp index 1d42da053a8..59cd46471b5 100644 --- a/extension/parquet/column_writer.cpp +++ b/extension/parquet/column_writer.cpp @@ -30,15 +30,15 @@ namespace duckdb { using namespace duckdb_parquet; // NOLINT using namespace duckdb_miniz; // NOLINT -using duckdb_parquet::format::CompressionCodec; -using duckdb_parquet::format::ConvertedType; -using duckdb_parquet::format::Encoding; -using duckdb_parquet::format::FieldRepetitionType; -using duckdb_parquet::format::FileMetaData; -using duckdb_parquet::format::PageHeader; -using duckdb_parquet::format::PageType; -using ParquetRowGroup = duckdb_parquet::format::RowGroup; -using duckdb_parquet::format::Type; +using duckdb_parquet::CompressionCodec; +using duckdb_parquet::ConvertedType; +using duckdb_parquet::Encoding; +using duckdb_parquet::FieldRepetitionType; +using duckdb_parquet::FileMetaData; +using duckdb_parquet::PageHeader; +using duckdb_parquet::PageType; +using ParquetRowGroup = duckdb_parquet::RowGroup; +using duckdb_parquet::Type; #define PARQUET_DEFINE_VALID 65535 @@ -344,13 +344,13 @@ struct PageWriteInformation { class BasicColumnWriterState : public ColumnWriterState { public: - BasicColumnWriterState(duckdb_parquet::format::RowGroup &row_group, idx_t col_idx) + BasicColumnWriterState(duckdb_parquet::RowGroup &row_group, idx_t col_idx) : row_group(row_group), col_idx(col_idx) { page_info.emplace_back(); } ~BasicColumnWriterState() override = default; - duckdb_parquet::format::RowGroup &row_group; + duckdb_parquet::RowGroup &row_group; idx_t col_idx; vector page_info; vector write_info; @@ -387,7 +387,7 @@ class BasicColumnWriter : public ColumnWriter { static constexpr const idx_t STRING_LENGTH_SIZE = sizeof(uint32_t); public: - unique_ptr InitializeWriteState(duckdb_parquet::format::RowGroup &row_group) override; + unique_ptr InitializeWriteState(duckdb_parquet::RowGroup &row_group) override; void Prepare(ColumnWriterState &state, ColumnWriterState *parent, Vector &vector, idx_t count) override; void BeginWrite(ColumnWriterState &state) override; void Write(ColumnWriterState &state, Vector &vector, idx_t count) override; @@ -397,7 +397,7 @@ class BasicColumnWriter : public ColumnWriter { static void WriteLevels(WriteStream &temp_writer, const unsafe_vector &levels, idx_t max_value, idx_t start_offset, idx_t count); - virtual duckdb_parquet::format::Encoding::type GetEncoding(BasicColumnWriterState &state); + virtual duckdb_parquet::Encoding::type GetEncoding(BasicColumnWriterState &state); void NextPage(BasicColumnWriterState &state); void FlushPage(BasicColumnWriterState &state); @@ -425,17 +425,17 @@ class BasicColumnWriter : public ColumnWriter { void WriteDictionary(BasicColumnWriterState &state, unique_ptr temp_writer, idx_t row_count); virtual void FlushDictionary(BasicColumnWriterState &state, ColumnWriterStatistics *stats); - void SetParquetStatistics(BasicColumnWriterState &state, duckdb_parquet::format::ColumnChunk &column); - void RegisterToRowGroup(duckdb_parquet::format::RowGroup &row_group); + void SetParquetStatistics(BasicColumnWriterState &state, duckdb_parquet::ColumnChunk &column); + void RegisterToRowGroup(duckdb_parquet::RowGroup &row_group); }; -unique_ptr BasicColumnWriter::InitializeWriteState(duckdb_parquet::format::RowGroup &row_group) { +unique_ptr BasicColumnWriter::InitializeWriteState(duckdb_parquet::RowGroup &row_group) { auto result = make_uniq(row_group, row_group.columns.size()); RegisterToRowGroup(row_group); return std::move(result); } -void BasicColumnWriter::RegisterToRowGroup(duckdb_parquet::format::RowGroup &row_group) { +void BasicColumnWriter::RegisterToRowGroup(duckdb_parquet::RowGroup &row_group) { format::ColumnChunk column_chunk; column_chunk.__isset.meta_data = true; column_chunk.meta_data.codec = writer.GetCodec(); @@ -486,7 +486,7 @@ void BasicColumnWriter::Prepare(ColumnWriterState &state_p, ColumnWriterState *p } } -duckdb_parquet::format::Encoding::type BasicColumnWriter::GetEncoding(BasicColumnWriterState &state) { +duckdb_parquet::Encoding::type BasicColumnWriter::GetEncoding(BasicColumnWriterState &state) { return Encoding::PLAIN; } @@ -647,7 +647,7 @@ void BasicColumnWriter::Write(ColumnWriterState &state_p, Vector &vector, idx_t } void BasicColumnWriter::SetParquetStatistics(BasicColumnWriterState &state, - duckdb_parquet::format::ColumnChunk &column_chunk) { + duckdb_parquet::ColumnChunk &column_chunk) { if (max_repeat == 0) { column_chunk.meta_data.statistics.null_count = NumericCast(state.null_count); column_chunk.meta_data.statistics.__isset.null_count = true; @@ -1270,7 +1270,7 @@ class StringStatisticsState : public ColumnWriterStatistics { class StringColumnWriterState : public BasicColumnWriterState { public: - StringColumnWriterState(duckdb_parquet::format::RowGroup &row_group, idx_t col_idx) + StringColumnWriterState(duckdb_parquet::RowGroup &row_group, idx_t col_idx) : BasicColumnWriterState(row_group, col_idx) { } ~StringColumnWriterState() override = default; @@ -1320,7 +1320,7 @@ class StringColumnWriter : public BasicColumnWriter { return make_uniq(); } - unique_ptr InitializeWriteState(duckdb_parquet::format::RowGroup &row_group) override { + unique_ptr InitializeWriteState(duckdb_parquet::RowGroup &row_group) override { auto result = make_uniq(row_group, row_group.columns.size()); RegisterToRowGroup(row_group); return std::move(result); @@ -1451,7 +1451,7 @@ class StringColumnWriter : public BasicColumnWriter { } } - duckdb_parquet::format::Encoding::type GetEncoding(BasicColumnWriterState &state_p) override { + duckdb_parquet::Encoding::type GetEncoding(BasicColumnWriterState &state_p) override { auto &state = state_p.Cast(); return state.IsDictionaryEncoded() ? Encoding::RLE_DICTIONARY : Encoding::PLAIN; } @@ -1529,7 +1529,7 @@ class StringColumnWriter : public BasicColumnWriter { // GeoParquet files. class WKBColumnWriterState final : public StringColumnWriterState { public: - WKBColumnWriterState(ClientContext &context, duckdb_parquet::format::RowGroup &row_group, idx_t col_idx) + WKBColumnWriterState(ClientContext &context, duckdb_parquet::RowGroup &row_group, idx_t col_idx) : StringColumnWriterState(row_group, col_idx), geo_data(), geo_data_writer(context) { } @@ -1547,7 +1547,7 @@ class WKBColumnWriter final : public StringColumnWriter { this->writer.GetGeoParquetData().RegisterGeometryColumn(column_name); } - unique_ptr InitializeWriteState(duckdb_parquet::format::RowGroup &row_group) override { + unique_ptr InitializeWriteState(duckdb_parquet::RowGroup &row_group) override { auto result = make_uniq(context, row_group, row_group.columns.size()); RegisterToRowGroup(row_group); return std::move(result); @@ -1658,7 +1658,7 @@ class EnumColumnWriter : public BasicColumnWriter { page_state.encoder.FinishWrite(temp_writer); } - duckdb_parquet::format::Encoding::type GetEncoding(BasicColumnWriterState &state) override { + duckdb_parquet::Encoding::type GetEncoding(BasicColumnWriterState &state) override { return Encoding::RLE_DICTIONARY; } @@ -1710,7 +1710,7 @@ class StructColumnWriter : public ColumnWriter { vector> child_writers; public: - unique_ptr InitializeWriteState(duckdb_parquet::format::RowGroup &row_group) override; + unique_ptr InitializeWriteState(duckdb_parquet::RowGroup &row_group) override; bool HasAnalyze() override; void Analyze(ColumnWriterState &state, ColumnWriterState *parent, Vector &vector, idx_t count) override; void FinalizeAnalyze(ColumnWriterState &state) override; @@ -1723,17 +1723,17 @@ class StructColumnWriter : public ColumnWriter { class StructColumnWriterState : public ColumnWriterState { public: - StructColumnWriterState(duckdb_parquet::format::RowGroup &row_group, idx_t col_idx) + StructColumnWriterState(duckdb_parquet::RowGroup &row_group, idx_t col_idx) : row_group(row_group), col_idx(col_idx) { } ~StructColumnWriterState() override = default; - duckdb_parquet::format::RowGroup &row_group; + duckdb_parquet::RowGroup &row_group; idx_t col_idx; vector> child_states; }; -unique_ptr StructColumnWriter::InitializeWriteState(duckdb_parquet::format::RowGroup &row_group) { +unique_ptr StructColumnWriter::InitializeWriteState(duckdb_parquet::RowGroup &row_group) { auto result = make_uniq(row_group, row_group.columns.size()); result->child_states.reserve(child_writers.size()); @@ -1831,7 +1831,7 @@ class ListColumnWriter : public ColumnWriter { unique_ptr child_writer; public: - unique_ptr InitializeWriteState(duckdb_parquet::format::RowGroup &row_group) override; + unique_ptr InitializeWriteState(duckdb_parquet::RowGroup &row_group) override; bool HasAnalyze() override; void Analyze(ColumnWriterState &state, ColumnWriterState *parent, Vector &vector, idx_t count) override; void FinalizeAnalyze(ColumnWriterState &state) override; @@ -1844,18 +1844,18 @@ class ListColumnWriter : public ColumnWriter { class ListColumnWriterState : public ColumnWriterState { public: - ListColumnWriterState(duckdb_parquet::format::RowGroup &row_group, idx_t col_idx) + ListColumnWriterState(duckdb_parquet::RowGroup &row_group, idx_t col_idx) : row_group(row_group), col_idx(col_idx) { } ~ListColumnWriterState() override = default; - duckdb_parquet::format::RowGroup &row_group; + duckdb_parquet::RowGroup &row_group; idx_t col_idx; unique_ptr child_state; idx_t parent_index = 0; }; -unique_ptr ListColumnWriter::InitializeWriteState(duckdb_parquet::format::RowGroup &row_group) { +unique_ptr ListColumnWriter::InitializeWriteState(duckdb_parquet::RowGroup &row_group) { auto result = make_uniq(row_group, row_group.columns.size()); result->child_state = child_writer->InitializeWriteState(row_group); return std::move(result); @@ -2083,7 +2083,7 @@ void ArrayColumnWriter::Write(ColumnWriterState &state_p, Vector &vector, idx_t //===--------------------------------------------------------------------===// unique_ptr ColumnWriter::CreateWriterRecursive(ClientContext &context, - vector &schemas, + vector &schemas, ParquetWriter &writer, const LogicalType &type, const string &name, vector schema_path, optional_ptr field_ids, @@ -2107,7 +2107,7 @@ unique_ptr ColumnWriter::CreateWriterRecursive(ClientContext &cont if (type.id() == LogicalTypeId::STRUCT || type.id() == LogicalTypeId::UNION) { auto &child_types = StructType::GetChildTypes(type); // set up the schema element for this struct - duckdb_parquet::format::SchemaElement schema_element; + duckdb_parquet::SchemaElement schema_element; schema_element.repetition_type = null_type; schema_element.num_children = UnsafeNumericCast(child_types.size()); schema_element.__isset.num_children = true; @@ -2137,7 +2137,7 @@ unique_ptr ColumnWriter::CreateWriterRecursive(ClientContext &cont // set up the two schema elements for the list // for some reason we only set the converted type in the OPTIONAL element // first an OPTIONAL element - duckdb_parquet::format::SchemaElement optional_element; + duckdb_parquet::SchemaElement optional_element; optional_element.repetition_type = null_type; optional_element.num_children = 1; optional_element.converted_type = ConvertedType::LIST; @@ -2154,7 +2154,7 @@ unique_ptr ColumnWriter::CreateWriterRecursive(ClientContext &cont schema_path.push_back(name); // then a REPEATED element - duckdb_parquet::format::SchemaElement repeated_element; + duckdb_parquet::SchemaElement repeated_element; repeated_element.repetition_type = FieldRepetitionType::REPEATED; repeated_element.num_children = 1; repeated_element.__isset.num_children = true; @@ -2184,7 +2184,7 @@ unique_ptr ColumnWriter::CreateWriterRecursive(ClientContext &cont // } // } // top map element - duckdb_parquet::format::SchemaElement top_element; + duckdb_parquet::SchemaElement top_element; top_element.repetition_type = null_type; top_element.num_children = 1; top_element.converted_type = ConvertedType::MAP; @@ -2201,7 +2201,7 @@ unique_ptr ColumnWriter::CreateWriterRecursive(ClientContext &cont schema_path.push_back(name); // key_value element - duckdb_parquet::format::SchemaElement kv_element; + duckdb_parquet::SchemaElement kv_element; kv_element.repetition_type = FieldRepetitionType::REPEATED; kv_element.num_children = 2; kv_element.__isset.repetition_type = true; @@ -2229,7 +2229,7 @@ unique_ptr ColumnWriter::CreateWriterRecursive(ClientContext &cont return make_uniq(writer, schema_idx, schema_path, max_repeat, max_define, std::move(struct_writer), can_have_nulls); } - duckdb_parquet::format::SchemaElement schema_element; + duckdb_parquet::SchemaElement schema_element; schema_element.type = ParquetWriter::DuckDBTypeToParquetType(type); schema_element.repetition_type = null_type; schema_element.__isset.num_children = false; diff --git a/extension/parquet/geo_parquet.cpp b/extension/parquet/geo_parquet.cpp index 28c56991626..db08aa07b03 100644 --- a/extension/parquet/geo_parquet.cpp +++ b/extension/parquet/geo_parquet.cpp @@ -177,7 +177,7 @@ void GeoParquetColumnMetadataWriter::Update(GeoParquetColumnMetadata &meta, Vect //------------------------------------------------------------------------------ unique_ptr -GeoParquetFileMetadata::TryRead(const duckdb_parquet::format::FileMetaData &file_meta_data, ClientContext &context) { +GeoParquetFileMetadata::TryRead(const duckdb_parquet::FileMetaData &file_meta_data, ClientContext &context) { for (auto &kv : file_meta_data.key_value_metadata) { if (kv.key == "geo") { const auto geo_metadata = yyjson_read(kv.value.c_str(), kv.value.size(), 0); @@ -290,7 +290,7 @@ void GeoParquetFileMetadata::FlushColumnMeta(const string &column_name, const Ge column.bbox.Combine(meta.bbox); } -void GeoParquetFileMetadata::Write(duckdb_parquet::format::FileMetaData &file_meta_data) const { +void GeoParquetFileMetadata::Write(duckdb_parquet::FileMetaData &file_meta_data) const { yyjson_mut_doc *doc = yyjson_mut_doc_new(nullptr); yyjson_mut_val *root = yyjson_mut_obj(doc); @@ -344,7 +344,7 @@ void GeoParquetFileMetadata::Write(duckdb_parquet::format::FileMetaData &file_me } // Create a string from the JSON - duckdb_parquet::format::KeyValue kv; + duckdb_parquet::KeyValue kv; kv.__set_key("geo"); kv.__set_value(string(json, len)); diff --git a/extension/parquet/include/column_reader.hpp b/extension/parquet/include/column_reader.hpp index 0a7a17ea08d..373934fb083 100644 --- a/extension/parquet/include/column_reader.hpp +++ b/extension/parquet/include/column_reader.hpp @@ -29,12 +29,12 @@ class ParquetReader; using duckdb_apache::thrift::protocol::TProtocol; -using duckdb_parquet::format::ColumnChunk; -using duckdb_parquet::format::CompressionCodec; -using duckdb_parquet::format::FieldRepetitionType; -using duckdb_parquet::format::PageHeader; -using duckdb_parquet::format::SchemaElement; -using duckdb_parquet::format::Type; +using duckdb_parquet::ColumnChunk; +using duckdb_parquet::CompressionCodec; +using duckdb_parquet::FieldRepetitionType; +using duckdb_parquet::PageHeader; +using duckdb_parquet::SchemaElement; +using duckdb_parquet::Type; typedef std::bitset parquet_filter_t; @@ -169,7 +169,7 @@ class ColumnReader { void DecompressInternal(CompressionCodec::type codec, const_data_ptr_t src, idx_t src_size, data_ptr_t dst, idx_t dst_size); - const duckdb_parquet::format::ColumnChunk *chunk = nullptr; + const duckdb_parquet::ColumnChunk *chunk = nullptr; duckdb_apache::thrift::protocol::TProtocol *protocol; idx_t page_rows_available; diff --git a/extension/parquet/include/column_writer.hpp b/extension/parquet/include/column_writer.hpp index 65f89e596fa..b10822ef5a1 100644 --- a/extension/parquet/include/column_writer.hpp +++ b/extension/parquet/include/column_writer.hpp @@ -80,12 +80,12 @@ class ColumnWriter { public: //! Create the column writer for a specific type recursively static unique_ptr - CreateWriterRecursive(ClientContext &context, vector &schemas, + CreateWriterRecursive(ClientContext &context, vector &schemas, ParquetWriter &writer, const LogicalType &type, const string &name, vector schema_path, optional_ptr field_ids, idx_t max_repeat = 0, idx_t max_define = 1, bool can_have_nulls = true); - virtual unique_ptr InitializeWriteState(duckdb_parquet::format::RowGroup &row_group) = 0; + virtual unique_ptr InitializeWriteState(duckdb_parquet::RowGroup &row_group) = 0; //! indicates whether the write need to analyse the data before preparing it virtual bool HasAnalyze() { diff --git a/extension/parquet/include/geo_parquet.hpp b/extension/parquet/include/geo_parquet.hpp index ab04dcdf2e5..6583d040107 100644 --- a/extension/parquet/include/geo_parquet.hpp +++ b/extension/parquet/include/geo_parquet.hpp @@ -119,15 +119,15 @@ class GeoParquetFileMetadata { public: // Try to read GeoParquet metadata. Returns nullptr if not found, invalid or the required spatial extension is not // available. - static unique_ptr TryRead(const duckdb_parquet::format::FileMetaData &file_meta_data, + static unique_ptr TryRead(const duckdb_parquet::FileMetaData &file_meta_data, ClientContext &context); - void Write(duckdb_parquet::format::FileMetaData &file_meta_data) const; + void Write(duckdb_parquet::FileMetaData &file_meta_data) const; void FlushColumnMeta(const string &column_name, const GeoParquetColumnMetadata &meta); const unordered_map &GetColumnMeta() const; unique_ptr CreateColumnReader(ParquetReader &reader, const LogicalType &logical_type, - const duckdb_parquet::format::SchemaElement &s_ele, idx_t schema_idx_p, + const duckdb_parquet::SchemaElement &s_ele, idx_t schema_idx_p, idx_t max_define_p, idx_t max_repeat_p, ClientContext &context); bool IsGeometryColumn(const string &column_name) const; diff --git a/extension/parquet/include/parquet_decimal_utils.hpp b/extension/parquet/include/parquet_decimal_utils.hpp index 4f189bbcf91..cb0276aa2d5 100644 --- a/extension/parquet/include/parquet_decimal_utils.hpp +++ b/extension/parquet/include/parquet_decimal_utils.hpp @@ -17,7 +17,7 @@ class ParquetDecimalUtils { public: template static PHYSICAL_TYPE ReadDecimalValue(const_data_ptr_t pointer, idx_t size, - const duckdb_parquet::format::SchemaElement &) { + const duckdb_parquet::SchemaElement &) { PHYSICAL_TYPE res = 0; auto res_ptr = (uint8_t *)&res; @@ -54,6 +54,6 @@ class ParquetDecimalUtils { template <> double ParquetDecimalUtils::ReadDecimalValue(const_data_ptr_t pointer, idx_t size, - const duckdb_parquet::format::SchemaElement &schema_ele); + const duckdb_parquet::SchemaElement &schema_ele); } // namespace duckdb diff --git a/extension/parquet/include/parquet_file_metadata_cache.hpp b/extension/parquet/include/parquet_file_metadata_cache.hpp index 48b6448ded5..b7373056fe0 100644 --- a/extension/parquet/include/parquet_file_metadata_cache.hpp +++ b/extension/parquet/include/parquet_file_metadata_cache.hpp @@ -20,7 +20,7 @@ class ParquetFileMetadataCache : public ObjectCacheEntry { public: ParquetFileMetadataCache() : metadata(nullptr) { } - ParquetFileMetadataCache(unique_ptr file_metadata, time_t r_time, + ParquetFileMetadataCache(unique_ptr file_metadata, time_t r_time, unique_ptr geo_metadata) : metadata(std::move(file_metadata)), read_time(r_time), geo_metadata(std::move(geo_metadata)) { } @@ -28,7 +28,7 @@ class ParquetFileMetadataCache : public ObjectCacheEntry { ~ParquetFileMetadataCache() override = default; //! Parquet file metadata - unique_ptr metadata; + unique_ptr metadata; //! read time time_t read_time; diff --git a/extension/parquet/include/parquet_reader.hpp b/extension/parquet/include/parquet_reader.hpp index ef8dcaf8c57..db483adc82f 100644 --- a/extension/parquet/include/parquet_reader.hpp +++ b/extension/parquet/include/parquet_reader.hpp @@ -137,7 +137,7 @@ class ParquetReader { //! Index of the file_row_number column idx_t file_row_number_idx = DConstants::INVALID_INDEX; //! Parquet schema for the generated columns - vector generated_column_schema; + vector generated_column_schema; //! Table column names - set when using COPY tbl FROM file.parquet vector table_columns; @@ -166,7 +166,7 @@ class ParquetReader { idx_t NumRows(); idx_t NumRowGroups(); - const duckdb_parquet::format::FileMetaData *GetFileMetadata(); + const duckdb_parquet::FileMetaData *GetFileMetadata(); uint32_t Read(duckdb_apache::thrift::TBase &object, TProtocol &iprot); uint32_t ReadData(duckdb_apache::thrift::protocol::TProtocol &iprot, const data_ptr_t buffer, @@ -203,7 +203,7 @@ class ParquetReader { unique_ptr CreateReaderRecursive(ClientContext &context, idx_t depth, idx_t max_define, idx_t max_repeat, idx_t &next_schema_idx, idx_t &next_file_idx); - const duckdb_parquet::format::RowGroup &GetGroup(ParquetReaderScanState &state); + const duckdb_parquet::RowGroup &GetGroup(ParquetReaderScanState &state); uint64_t GetGroupCompressedSize(ParquetReaderScanState &state); idx_t GetGroupOffset(ParquetReaderScanState &state); // Group span is the distance between the min page offset and the max page offset plus the max page compressed size diff --git a/extension/parquet/include/parquet_statistics.hpp b/extension/parquet/include/parquet_statistics.hpp index 94ce194e2d5..e1d28e5ded6 100644 --- a/extension/parquet/include/parquet_statistics.hpp +++ b/extension/parquet/include/parquet_statistics.hpp @@ -8,8 +8,8 @@ namespace duckdb { -using duckdb_parquet::format::ColumnChunk; -using duckdb_parquet::format::SchemaElement; +using duckdb_parquet::ColumnChunk; +using duckdb_parquet::SchemaElement; struct LogicalType; class ColumnReader; @@ -19,7 +19,7 @@ struct ParquetStatisticsUtils { static unique_ptr TransformColumnStatistics(const ColumnReader &reader, const vector &columns); - static Value ConvertValue(const LogicalType &type, const duckdb_parquet::format::SchemaElement &schema_ele, + static Value ConvertValue(const LogicalType &type, const duckdb_parquet::SchemaElement &schema_ele, const std::string &stats); }; diff --git a/extension/parquet/include/parquet_writer.hpp b/extension/parquet/include/parquet_writer.hpp index 297d2efa688..ac1c67ff467 100644 --- a/extension/parquet/include/parquet_writer.hpp +++ b/extension/parquet/include/parquet_writer.hpp @@ -33,7 +33,7 @@ class Serializer; class Deserializer; struct PreparedRowGroup { - duckdb_parquet::format::RowGroup row_group; + duckdb_parquet::RowGroup row_group; vector> states; vector> heaps; }; @@ -64,7 +64,7 @@ struct FieldID { class ParquetWriter { public: ParquetWriter(ClientContext &context, FileSystem &fs, string file_name, vector types, - vector names, duckdb_parquet::format::CompressionCodec::type codec, ChildFieldIDs field_ids, + vector names, duckdb_parquet::CompressionCodec::type codec, ChildFieldIDs field_ids, const vector> &kv_metadata, shared_ptr encryption_config, double dictionary_compression_ratio_threshold, optional_idx compression_level, bool debug_use_openssl); @@ -75,16 +75,16 @@ class ParquetWriter { void Flush(ColumnDataCollection &buffer); void Finalize(); - static duckdb_parquet::format::Type::type DuckDBTypeToParquetType(const LogicalType &duckdb_type); - static void SetSchemaProperties(const LogicalType &duckdb_type, duckdb_parquet::format::SchemaElement &schema_ele); + static duckdb_parquet::Type::type DuckDBTypeToParquetType(const LogicalType &duckdb_type); + static void SetSchemaProperties(const LogicalType &duckdb_type, duckdb_parquet::SchemaElement &schema_ele); duckdb_apache::thrift::protocol::TProtocol *GetProtocol() { return protocol.get(); } - duckdb_parquet::format::CompressionCodec::type GetCodec() { + duckdb_parquet::CompressionCodec::type GetCodec() { return codec; } - duckdb_parquet::format::Type::type GetType(idx_t schema_idx) { + duckdb_parquet::Type::type GetType(idx_t schema_idx) { return file_meta_data.schema[schema_idx].type; } LogicalType GetSQLType(idx_t schema_idx) const { @@ -114,13 +114,13 @@ class ParquetWriter { GeoParquetFileMetadata &GetGeoParquetData(); static bool TryGetParquetType(const LogicalType &duckdb_type, - optional_ptr type = nullptr); + optional_ptr type = nullptr); private: string file_name; vector sql_types; vector column_names; - duckdb_parquet::format::CompressionCodec::type codec; + duckdb_parquet::CompressionCodec::type codec; ChildFieldIDs field_ids; shared_ptr encryption_config; double dictionary_compression_ratio_threshold; @@ -130,7 +130,7 @@ class ParquetWriter { unique_ptr writer; std::shared_ptr protocol; - duckdb_parquet::format::FileMetaData file_meta_data; + duckdb_parquet::FileMetaData file_meta_data; std::mutex lock; vector> column_writers; diff --git a/extension/parquet/parquet_config.py b/extension/parquet/parquet_config.py index 7b8ba00a07a..ceb9e2b9159 100644 --- a/extension/parquet/parquet_config.py +++ b/extension/parquet/parquet_config.py @@ -40,7 +40,6 @@ source_files += [ os.path.sep.join(x.split('/')) for x in [ - 'third_party/parquet/parquet_constants.cpp', 'third_party/parquet/parquet_types.cpp', 'third_party/thrift/thrift/protocol/TProtocol.cpp', 'third_party/thrift/thrift/transport/TTransportException.cpp', diff --git a/extension/parquet/parquet_extension.cpp b/extension/parquet/parquet_extension.cpp index 6158ad793a7..34f9ea53c67 100644 --- a/extension/parquet/parquet_extension.cpp +++ b/extension/parquet/parquet_extension.cpp @@ -180,7 +180,7 @@ struct ParquetReadGlobalState : public GlobalTableFunctionState { struct ParquetWriteBindData : public TableFunctionData { vector sql_types; vector column_names; - duckdb_parquet::format::CompressionCodec::type codec = duckdb_parquet::format::CompressionCodec::SNAPPY; + duckdb_parquet::CompressionCodec::type codec = duckdb_parquet::CompressionCodec::SNAPPY; vector> kv_metadata; idx_t row_group_size = Storage::ROW_GROUP_SIZE; @@ -1203,19 +1203,19 @@ unique_ptr ParquetWriteBind(ClientContext &context, CopyFunctionBi } else if (loption == "compression" || loption == "codec") { const auto roption = StringUtil::Lower(option.second[0].ToString()); if (roption == "uncompressed") { - bind_data->codec = duckdb_parquet::format::CompressionCodec::UNCOMPRESSED; + bind_data->codec = duckdb_parquet::CompressionCodec::UNCOMPRESSED; } else if (roption == "snappy") { - bind_data->codec = duckdb_parquet::format::CompressionCodec::SNAPPY; + bind_data->codec = duckdb_parquet::CompressionCodec::SNAPPY; } else if (roption == "gzip") { - bind_data->codec = duckdb_parquet::format::CompressionCodec::GZIP; + bind_data->codec = duckdb_parquet::CompressionCodec::GZIP; } else if (roption == "zstd") { - bind_data->codec = duckdb_parquet::format::CompressionCodec::ZSTD; + bind_data->codec = duckdb_parquet::CompressionCodec::ZSTD; } else if (roption == "brotli") { - bind_data->codec = duckdb_parquet::format::CompressionCodec::BROTLI; + bind_data->codec = duckdb_parquet::CompressionCodec::BROTLI; } else if (roption == "lz4" || roption == "lz4_raw") { /* LZ4 is technically another compression scheme, but deprecated and arrow also uses them * interchangeably */ - bind_data->codec = duckdb_parquet::format::CompressionCodec::LZ4_RAW; + bind_data->codec = duckdb_parquet::CompressionCodec::LZ4_RAW; } else { throw BinderException("Expected %s argument to be either [uncompressed, brotli, gzip, snappy, or zstd]", loption); @@ -1351,8 +1351,8 @@ unique_ptr ParquetWriteInitializeLocal(ExecutionContext &cont // FIXME: Have these be generated instead template <> -const char *EnumUtil::ToChars( - duckdb_parquet::format::CompressionCodec::type value) { +const char *EnumUtil::ToChars( + duckdb_parquet::CompressionCodec::type value) { switch (value) { case CompressionCodec::UNCOMPRESSED: return "UNCOMPRESSED"; @@ -1384,8 +1384,8 @@ const char *EnumUtil::ToChars( } template <> -duckdb_parquet::format::CompressionCodec::type -EnumUtil::FromString(const char *value) { +duckdb_parquet::CompressionCodec::type +EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "UNCOMPRESSED")) { return CompressionCodec::UNCOMPRESSED; } @@ -1436,7 +1436,7 @@ static unique_ptr ParquetCopyDeserialize(Deserializer &deserialize auto data = make_uniq(); data->sql_types = deserializer.ReadProperty>(100, "sql_types"); data->column_names = deserializer.ReadProperty>(101, "column_names"); - data->codec = deserializer.ReadProperty(102, "codec"); + data->codec = deserializer.ReadProperty(102, "codec"); data->row_group_size = deserializer.ReadProperty(103, "row_group_size"); data->row_group_size_bytes = deserializer.ReadProperty(104, "row_group_size_bytes"); data->kv_metadata = deserializer.ReadProperty>>(105, "kv_metadata"); diff --git a/extension/parquet/parquet_metadata.cpp b/extension/parquet/parquet_metadata.cpp index b1d70a543d3..6e629b549fa 100644 --- a/extension/parquet/parquet_metadata.cpp +++ b/extension/parquet/parquet_metadata.cpp @@ -166,7 +166,7 @@ void ParquetMetaDataOperatorData::BindMetaData(vector &return_types return_types.emplace_back(LogicalType::MAP(LogicalType::BLOB, LogicalType::BLOB)); } -Value ConvertParquetStats(const LogicalType &type, const duckdb_parquet::format::SchemaElement &schema_ele, +Value ConvertParquetStats(const LogicalType &type, const duckdb_parquet::SchemaElement &schema_ele, bool stats_is_set, const std::string &stats) { if (!stats_is_set) { return Value(LogicalType::VARCHAR); @@ -352,7 +352,7 @@ void ParquetMetaDataOperatorData::BindSchema(vector &return_types, return_types.emplace_back(LogicalType::VARCHAR); } -Value ParquetLogicalTypeToString(const duckdb_parquet::format::LogicalType &type, bool is_set) { +Value ParquetLogicalTypeToString(const duckdb_parquet::LogicalType &type, bool is_set) { if (!is_set) { return Value(); } diff --git a/extension/parquet/parquet_reader.cpp b/extension/parquet/parquet_reader.cpp index 7357767b79a..1072cada775 100644 --- a/extension/parquet/parquet_reader.cpp +++ b/extension/parquet/parquet_reader.cpp @@ -40,15 +40,15 @@ namespace duckdb { -using duckdb_parquet::format::ColumnChunk; -using duckdb_parquet::format::ConvertedType; -using duckdb_parquet::format::FieldRepetitionType; -using duckdb_parquet::format::FileCryptoMetaData; -using duckdb_parquet::format::FileMetaData; -using ParquetRowGroup = duckdb_parquet::format::RowGroup; -using duckdb_parquet::format::SchemaElement; -using duckdb_parquet::format::Statistics; -using duckdb_parquet::format::Type; +using duckdb_parquet::ColumnChunk; +using duckdb_parquet::ConvertedType; +using duckdb_parquet::FieldRepetitionType; +using duckdb_parquet::FileCryptoMetaData; +using duckdb_parquet::FileMetaData; +using ParquetRowGroup = duckdb_parquet::RowGroup; +using duckdb_parquet::SchemaElement; +using duckdb_parquet::Statistics; +using duckdb_parquet::Type; static unique_ptr CreateThriftFileProtocol(Allocator &allocator, FileHandle &file_handle, bool prefetch_mode) { diff --git a/extension/parquet/parquet_statistics.cpp b/extension/parquet/parquet_statistics.cpp index 26896c5769e..228de5a3503 100644 --- a/extension/parquet/parquet_statistics.cpp +++ b/extension/parquet/parquet_statistics.cpp @@ -14,12 +14,12 @@ namespace duckdb { -using duckdb_parquet::format::ConvertedType; -using duckdb_parquet::format::Type; +using duckdb_parquet::ConvertedType; +using duckdb_parquet::Type; static unique_ptr CreateNumericStats(const LogicalType &type, - const duckdb_parquet::format::SchemaElement &schema_ele, - const duckdb_parquet::format::Statistics &parquet_stats) { + const duckdb_parquet::SchemaElement &schema_ele, + const duckdb_parquet::Statistics &parquet_stats) { auto stats = NumericStats::CreateUnknown(type); // for reasons unknown to science, Parquet defines *both* `min` and `min_value` as well as `max` and @@ -46,7 +46,7 @@ static unique_ptr CreateNumericStats(const LogicalType &type, } Value ParquetStatisticsUtils::ConvertValue(const LogicalType &type, - const duckdb_parquet::format::SchemaElement &schema_ele, + const duckdb_parquet::SchemaElement &schema_ele, const std::string &stats) { auto stats_data = const_data_ptr_cast(stats.c_str()); switch (type.id()) { @@ -180,7 +180,7 @@ Value ParquetStatisticsUtils::ConvertValue(const LogicalType &type, throw InternalException("Time logicalType is set but unit is not defined"); } } - if (schema_ele.converted_type == duckdb_parquet::format::ConvertedType::TIME_MILLIS) { + if (schema_ele.converted_type == duckdb_parquet::ConvertedType::TIME_MILLIS) { return Value::TIME(Time::FromTimeMs(val)); } else { return Value::TIME(dtime_t(val)); @@ -234,7 +234,7 @@ Value ParquetStatisticsUtils::ConvertValue(const LogicalType &type, } else { throw InternalException("Timestamp logicalType is set but unit is not defined"); } - } else if (schema_ele.converted_type == duckdb_parquet::format::ConvertedType::TIMESTAMP_MILLIS) { + } else if (schema_ele.converted_type == duckdb_parquet::ConvertedType::TIMESTAMP_MILLIS) { timestamp_value = Timestamp::FromEpochMs(val); } else { timestamp_value = timestamp_t(val); @@ -270,7 +270,7 @@ Value ParquetStatisticsUtils::ConvertValue(const LogicalType &type, } else { throw InternalException("Timestamp (NS) logicalType is set but unit is unknown"); } - } else if (schema_ele.converted_type == duckdb_parquet::format::ConvertedType::TIMESTAMP_MILLIS) { + } else if (schema_ele.converted_type == duckdb_parquet::ConvertedType::TIMESTAMP_MILLIS) { timestamp_value = ParquetTimestampMsToTimestampNs(val); } else { timestamp_value = ParquetTimestampUsToTimestampNs(val); diff --git a/extension/parquet/parquet_writer.cpp b/extension/parquet/parquet_writer.cpp index a7a847afb0d..53aa4dc4780 100644 --- a/extension/parquet/parquet_writer.cpp +++ b/extension/parquet/parquet_writer.cpp @@ -25,16 +25,16 @@ using namespace duckdb_apache::thrift; // NOLINT using namespace duckdb_apache::thrift::protocol; // NOLINT using namespace duckdb_apache::thrift::transport; // NOLINT -using duckdb_parquet::format::CompressionCodec; -using duckdb_parquet::format::ConvertedType; -using duckdb_parquet::format::Encoding; -using duckdb_parquet::format::FieldRepetitionType; -using duckdb_parquet::format::FileCryptoMetaData; -using duckdb_parquet::format::FileMetaData; -using duckdb_parquet::format::PageHeader; -using duckdb_parquet::format::PageType; -using ParquetRowGroup = duckdb_parquet::format::RowGroup; -using duckdb_parquet::format::Type; +using duckdb_parquet::CompressionCodec; +using duckdb_parquet::ConvertedType; +using duckdb_parquet::Encoding; +using duckdb_parquet::FieldRepetitionType; +using duckdb_parquet::FileCryptoMetaData; +using duckdb_parquet::FileMetaData; +using duckdb_parquet::PageHeader; +using duckdb_parquet::PageType; +using ParquetRowGroup = duckdb_parquet::RowGroup; +using duckdb_parquet::Type; ChildFieldIDs::ChildFieldIDs() : ids(make_uniq>()) { } @@ -168,7 +168,7 @@ Type::type ParquetWriter::DuckDBTypeToParquetType(const LogicalType &duckdb_type } void ParquetWriter::SetSchemaProperties(const LogicalType &duckdb_type, - duckdb_parquet::format::SchemaElement &schema_ele) { + duckdb_parquet::SchemaElement &schema_ele) { if (duckdb_type.IsJSONType()) { schema_ele.converted_type = ConvertedType::JSON; schema_ele.__isset.converted_type = true; @@ -356,7 +356,7 @@ ParquetWriter::ParquetWriter(ClientContext &context, FileSystem &fs, string file file_meta_data.schema.resize(1); for (auto &kv_pair : kv_metadata) { - duckdb_parquet::format::KeyValue kv; + duckdb_parquet::KeyValue kv; kv.__set_key(kv_pair.first); kv.__set_value(kv_pair.second); file_meta_data.key_value_metadata.push_back(kv); @@ -380,7 +380,7 @@ ParquetWriter::ParquetWriter(ClientContext &context, FileSystem &fs, string file file_meta_data.schema[0].name = "duckdb_schema"; file_meta_data.schema[0].num_children = NumericCast(sql_types.size()); file_meta_data.schema[0].__isset.num_children = true; - file_meta_data.schema[0].repetition_type = duckdb_parquet::format::FieldRepetitionType::REQUIRED; + file_meta_data.schema[0].repetition_type = duckdb_parquet::FieldRepetitionType::REQUIRED; file_meta_data.schema[0].__isset.repetition_type = true; auto &unique_names = column_names; @@ -539,8 +539,8 @@ void ParquetWriter::Finalize() { if (encryption_config) { // Crypto metadata is written unencrypted FileCryptoMetaData crypto_metadata; - duckdb_parquet::format::AesGcmV1 aes_gcm_v1; - duckdb_parquet::format::EncryptionAlgorithm alg; + duckdb_parquet::AesGcmV1 aes_gcm_v1; + duckdb_parquet::EncryptionAlgorithm alg; alg.__set_AES_GCM_V1(aes_gcm_v1); crypto_metadata.__set_encryption_algorithm(alg); crypto_metadata.write(protocol.get()); diff --git a/third_party/parquet/README b/third_party/parquet/README new file mode 100644 index 00000000000..f4f8098b4b1 --- /dev/null +++ b/third_party/parquet/README @@ -0,0 +1,5 @@ +thrift --gen "cpp:no_ostream_operators=true,no_default_operators=true" parquet.thrift + + +// I'M SURE WHAT I AM DOING +namespace apache = duckdb_apache; diff --git a/third_party/parquet/parquet.thrift b/third_party/parquet/parquet.thrift new file mode 100644 index 00000000000..2d16c85873b --- /dev/null +++ b/third_party/parquet/parquet.thrift @@ -0,0 +1,1228 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * File format description for the parquet file format + */ +namespace cpp duckdb_parquet +namespace java org.apache.parquet.format + +/** + * Types supported by Parquet. These types are intended to be used in combination + * with the encodings to control the on disk storage format. + * For example INT16 is not included as a type since a good encoding of INT32 + * would handle this. + */ +enum Type { + BOOLEAN = 0; + INT32 = 1; + INT64 = 2; + INT96 = 3; // deprecated, only used by legacy implementations. + FLOAT = 4; + DOUBLE = 5; + BYTE_ARRAY = 6; + FIXED_LEN_BYTE_ARRAY = 7; +} + +/** + * DEPRECATED: Common types used by frameworks(e.g. hive, pig) using parquet. + * ConvertedType is superseded by LogicalType. This enum should not be extended. + * + * See LogicalTypes.md for conversion between ConvertedType and LogicalType. + */ +enum ConvertedType { + /** a BYTE_ARRAY actually contains UTF8 encoded chars */ + UTF8 = 0; + + /** a map is converted as an optional field containing a repeated key/value pair */ + MAP = 1; + + /** a key/value pair is converted into a group of two fields */ + MAP_KEY_VALUE = 2; + + /** a list is converted into an optional field containing a repeated field for its + * values */ + LIST = 3; + + /** an enum is converted into a BYTE_ARRAY field */ + ENUM = 4; + + /** + * A decimal value. + * + * This may be used to annotate BYTE_ARRAY or FIXED_LEN_BYTE_ARRAY primitive + * types. The underlying byte array stores the unscaled value encoded as two's + * complement using big-endian byte order (the most significant byte is the + * zeroth element). The value of the decimal is the value * 10^{-scale}. + * + * This must be accompanied by a (maximum) precision and a scale in the + * SchemaElement. The precision specifies the number of digits in the decimal + * and the scale stores the location of the decimal point. For example 1.23 + * would have precision 3 (3 total digits) and scale 2 (the decimal point is + * 2 digits over). + */ + DECIMAL = 5; + + /** + * A Date + * + * Stored as days since Unix epoch, encoded as the INT32 physical type. + * + */ + DATE = 6; + + /** + * A time + * + * The total number of milliseconds since midnight. The value is stored + * as an INT32 physical type. + */ + TIME_MILLIS = 7; + + /** + * A time. + * + * The total number of microseconds since midnight. The value is stored as + * an INT64 physical type. + */ + TIME_MICROS = 8; + + /** + * A date/time combination + * + * Date and time recorded as milliseconds since the Unix epoch. Recorded as + * a physical type of INT64. + */ + TIMESTAMP_MILLIS = 9; + + /** + * A date/time combination + * + * Date and time recorded as microseconds since the Unix epoch. The value is + * stored as an INT64 physical type. + */ + TIMESTAMP_MICROS = 10; + + + /** + * An unsigned integer value. + * + * The number describes the maximum number of meaningful data bits in + * the stored value. 8, 16 and 32 bit values are stored using the + * INT32 physical type. 64 bit values are stored using the INT64 + * physical type. + * + */ + UINT_8 = 11; + UINT_16 = 12; + UINT_32 = 13; + UINT_64 = 14; + + /** + * A signed integer value. + * + * The number describes the maximum number of meaningful data bits in + * the stored value. 8, 16 and 32 bit values are stored using the + * INT32 physical type. 64 bit values are stored using the INT64 + * physical type. + * + */ + INT_8 = 15; + INT_16 = 16; + INT_32 = 17; + INT_64 = 18; + + /** + * An embedded JSON document + * + * A JSON document embedded within a single UTF8 column. + */ + JSON = 19; + + /** + * An embedded BSON document + * + * A BSON document embedded within a single BYTE_ARRAY column. + */ + BSON = 20; + + /** + * An interval of time + * + * This type annotates data stored as a FIXED_LEN_BYTE_ARRAY of length 12 + * This data is composed of three separate little endian unsigned + * integers. Each stores a component of a duration of time. The first + * integer identifies the number of months associated with the duration, + * the second identifies the number of days associated with the duration + * and the third identifies the number of milliseconds associated with + * the provided duration. This duration of time is independent of any + * particular timezone or date. + */ + INTERVAL = 21; +} + +/** + * Representation of Schemas + */ +enum FieldRepetitionType { + /** This field is required (can not be null) and each row has exactly 1 value. */ + REQUIRED = 0; + + /** The field is optional (can be null) and each row has 0 or 1 values. */ + OPTIONAL = 1; + + /** The field is repeated and can contain 0 or more values */ + REPEATED = 2; +} + +/** + * A structure for capturing metadata for estimating the unencoded, + * uncompressed size of data written. This is useful for readers to estimate + * how much memory is needed to reconstruct data in their memory model and for + * fine grained filter pushdown on nested structures (the histograms contained + * in this structure can help determine the number of nulls at a particular + * nesting level and maximum length of lists). + */ +struct SizeStatistics { + /** + * The number of physical bytes stored for BYTE_ARRAY data values assuming + * no encoding. This is exclusive of the bytes needed to store the length of + * each byte array. In other words, this field is equivalent to the `(size + * of PLAIN-ENCODING the byte array values) - (4 bytes * number of values + * written)`. To determine unencoded sizes of other types readers can use + * schema information multiplied by the number of non-null and null values. + * The number of null/non-null values can be inferred from the histograms + * below. + * + * For example, if a column chunk is dictionary-encoded with dictionary + * ["a", "bc", "cde"], and a data page contains the indices [0, 0, 1, 2], + * then this value for that data page should be 7 (1 + 1 + 2 + 3). + * + * This field should only be set for types that use BYTE_ARRAY as their + * physical type. + */ + 1: optional i64 unencoded_byte_array_data_bytes; + /** + * When present, there is expected to be one element corresponding to each + * repetition (i.e. size=max repetition_level+1) where each element + * represents the number of times the repetition level was observed in the + * data. + * + * This field may be omitted if max_repetition_level is 0 without loss + * of information. + **/ + 2: optional list repetition_level_histogram; + /** + * Same as repetition_level_histogram except for definition levels. + * + * This field may be omitted if max_definition_level is 0 or 1 without + * loss of information. + **/ + 3: optional list definition_level_histogram; +} + +/** + * Statistics per row group and per page + * All fields are optional. + */ +struct Statistics { + /** + * DEPRECATED: min and max value of the column. Use min_value and max_value. + * + * Values are encoded using PLAIN encoding, except that variable-length byte + * arrays do not include a length prefix. + * + * These fields encode min and max values determined by signed comparison + * only. New files should use the correct order for a column's logical type + * and store the values in the min_value and max_value fields. + * + * To support older readers, these may be set when the column order is + * signed. + */ + 1: optional binary max; + 2: optional binary min; + /** + * Count of null values in the column. + * + * Writers SHOULD always write this field even if it is zero (i.e. no null value) + * or the column is not nullable. + * Readers MUST distinguish between null_count not being present and null_count == 0. + * If null_count is not present, readers MUST NOT assume null_count == 0. + */ + 3: optional i64 null_count; + /** count of distinct values occurring */ + 4: optional i64 distinct_count; + /** + * Lower and upper bound values for the column, determined by its ColumnOrder. + * + * These may be the actual minimum and maximum values found on a page or column + * chunk, but can also be (more compact) values that do not exist on a page or + * column chunk. For example, instead of storing "Blart Versenwald III", a writer + * may set min_value="B", max_value="C". Such more compact values must still be + * valid values within the column's logical type. + * + * Values are encoded using PLAIN encoding, except that variable-length byte + * arrays do not include a length prefix. + */ + 5: optional binary max_value; + 6: optional binary min_value; + /** If true, max_value is the actual maximum value for a column */ + 7: optional bool is_max_value_exact; + /** If true, min_value is the actual minimum value for a column */ + 8: optional bool is_min_value_exact; +} + +/** Empty structs to use as logical type annotations */ +struct StringType {} // allowed for BYTE_ARRAY, must be encoded with UTF-8 +struct UUIDType {} // allowed for FIXED[16], must encoded raw UUID bytes +struct MapType {} // see LogicalTypes.md +struct ListType {} // see LogicalTypes.md +struct EnumType {} // allowed for BYTE_ARRAY, must be encoded with UTF-8 +struct DateType {} // allowed for INT32 +struct Float16Type {} // allowed for FIXED[2], must encoded raw FLOAT16 bytes + +/** + * Logical type to annotate a column that is always null. + * + * Sometimes when discovering the schema of existing data, values are always + * null and the physical type can't be determined. This annotation signals + * the case where the physical type was guessed from all null values. + */ +struct NullType {} // allowed for any physical type, only null values stored + +/** + * Decimal logical type annotation + * + * Scale must be zero or a positive integer less than or equal to the precision. + * Precision must be a non-zero positive integer. + * + * To maintain forward-compatibility in v1, implementations using this logical + * type must also set scale and precision on the annotated SchemaElement. + * + * Allowed for physical types: INT32, INT64, FIXED_LEN_BYTE_ARRAY, and BYTE_ARRAY. + */ +struct DecimalType { + 1: required i32 scale + 2: required i32 precision +} + +/** Time units for logical types */ +struct MilliSeconds {} +struct MicroSeconds {} +struct NanoSeconds {} +union TimeUnit { + 1: MilliSeconds MILLIS + 2: MicroSeconds MICROS + 3: NanoSeconds NANOS +} + +/** + * Timestamp logical type annotation + * + * Allowed for physical types: INT64 + */ +struct TimestampType { + 1: required bool isAdjustedToUTC + 2: required TimeUnit unit +} + +/** + * Time logical type annotation + * + * Allowed for physical types: INT32 (millis), INT64 (micros, nanos) + */ +struct TimeType { + 1: required bool isAdjustedToUTC + 2: required TimeUnit unit +} + +/** + * Integer logical type annotation + * + * bitWidth must be 8, 16, 32, or 64. + * + * Allowed for physical types: INT32, INT64 + */ +struct IntType { + 1: required i8 bitWidth + 2: required bool isSigned +} + +/** + * Embedded JSON logical type annotation + * + * Allowed for physical types: BYTE_ARRAY + */ +struct JsonType { +} + +/** + * Embedded BSON logical type annotation + * + * Allowed for physical types: BYTE_ARRAY + */ +struct BsonType { +} + +/** + * LogicalType annotations to replace ConvertedType. + * + * To maintain compatibility, implementations using LogicalType for a + * SchemaElement must also set the corresponding ConvertedType (if any) + * from the following table. + */ +union LogicalType { + 1: StringType STRING // use ConvertedType UTF8 + 2: MapType MAP // use ConvertedType MAP + 3: ListType LIST // use ConvertedType LIST + 4: EnumType ENUM // use ConvertedType ENUM + 5: DecimalType DECIMAL // use ConvertedType DECIMAL + SchemaElement.{scale, precision} + 6: DateType DATE // use ConvertedType DATE + + // use ConvertedType TIME_MICROS for TIME(isAdjustedToUTC = *, unit = MICROS) + // use ConvertedType TIME_MILLIS for TIME(isAdjustedToUTC = *, unit = MILLIS) + 7: TimeType TIME + + // use ConvertedType TIMESTAMP_MICROS for TIMESTAMP(isAdjustedToUTC = *, unit = MICROS) + // use ConvertedType TIMESTAMP_MILLIS for TIMESTAMP(isAdjustedToUTC = *, unit = MILLIS) + 8: TimestampType TIMESTAMP + + // 9: reserved for INTERVAL + 10: IntType INTEGER // use ConvertedType INT_* or UINT_* + 11: NullType UNKNOWN // no compatible ConvertedType + 12: JsonType JSON // use ConvertedType JSON + 13: BsonType BSON // use ConvertedType BSON + 14: UUIDType UUID // no compatible ConvertedType + 15: Float16Type FLOAT16 // no compatible ConvertedType +} + +/** + * Represents a element inside a schema definition. + * - if it is a group (inner node) then type is undefined and num_children is defined + * - if it is a primitive type (leaf) then type is defined and num_children is undefined + * the nodes are listed in depth first traversal order. + */ +struct SchemaElement { + /** Data type for this field. Not set if the current element is a non-leaf node */ + 1: optional Type type; + + /** If type is FIXED_LEN_BYTE_ARRAY, this is the byte length of the values. + * Otherwise, if specified, this is the maximum bit length to store any of the values. + * (e.g. a low cardinality INT col could have this set to 3). Note that this is + * in the schema, and therefore fixed for the entire file. + */ + 2: optional i32 type_length; + + /** repetition of the field. The root of the schema does not have a repetition_type. + * All other nodes must have one */ + 3: optional FieldRepetitionType repetition_type; + + /** Name of the field in the schema */ + 4: required string name; + + /** Nested fields. Since thrift does not support nested fields, + * the nesting is flattened to a single list by a depth-first traversal. + * The children count is used to construct the nested relationship. + * This field is not set when the element is a primitive type + */ + 5: optional i32 num_children; + + /** + * DEPRECATED: When the schema is the result of a conversion from another model. + * Used to record the original type to help with cross conversion. + * + * This is superseded by logicalType. + */ + 6: optional ConvertedType converted_type; + + /** + * DEPRECATED: Used when this column contains decimal data. + * See the DECIMAL converted type for more details. + * + * This is superseded by using the DecimalType annotation in logicalType. + */ + 7: optional i32 scale + 8: optional i32 precision + + /** When the original schema supports field ids, this will save the + * original field id in the parquet schema + */ + 9: optional i32 field_id; + + /** + * The logical type of this SchemaElement + * + * LogicalType replaces ConvertedType, but ConvertedType is still required + * for some logical types to ensure forward-compatibility in format v1. + */ + 10: optional LogicalType logicalType +} + +/** + * Encodings supported by Parquet. Not all encodings are valid for all types. These + * enums are also used to specify the encoding of definition and repetition levels. + * See the accompanying doc for the details of the more complicated encodings. + */ +enum Encoding { + /** Default encoding. + * BOOLEAN - 1 bit per value. 0 is false; 1 is true. + * INT32 - 4 bytes per value. Stored as little-endian. + * INT64 - 8 bytes per value. Stored as little-endian. + * FLOAT - 4 bytes per value. IEEE. Stored as little-endian. + * DOUBLE - 8 bytes per value. IEEE. Stored as little-endian. + * BYTE_ARRAY - 4 byte length stored as little endian, followed by bytes. + * FIXED_LEN_BYTE_ARRAY - Just the bytes. + */ + PLAIN = 0; + + /** Group VarInt encoding for INT32/INT64. + * This encoding is deprecated. It was never used + */ + // GROUP_VAR_INT = 1; + + /** + * Deprecated: Dictionary encoding. The values in the dictionary are encoded in the + * plain type. + * in a data page use RLE_DICTIONARY instead. + * in a Dictionary page use PLAIN instead + */ + PLAIN_DICTIONARY = 2; + + /** Group packed run length encoding. Usable for definition/repetition levels + * encoding and Booleans (on one bit: 0 is false; 1 is true.) + */ + RLE = 3; + + /** Bit packed encoding. This can only be used if the data has a known max + * width. Usable for definition/repetition levels encoding. + */ + BIT_PACKED = 4; + + /** Delta encoding for integers. This can be used for int columns and works best + * on sorted data + */ + DELTA_BINARY_PACKED = 5; + + /** Encoding for byte arrays to separate the length values and the data. The lengths + * are encoded using DELTA_BINARY_PACKED + */ + DELTA_LENGTH_BYTE_ARRAY = 6; + + /** Incremental-encoded byte array. Prefix lengths are encoded using DELTA_BINARY_PACKED. + * Suffixes are stored as delta length byte arrays. + */ + DELTA_BYTE_ARRAY = 7; + + /** Dictionary encoding: the ids are encoded using the RLE encoding + */ + RLE_DICTIONARY = 8; + + /** Encoding for fixed-width data (FLOAT, DOUBLE, INT32, INT64, FIXED_LEN_BYTE_ARRAY). + K byte-streams are created where K is the size in bytes of the data type. + The individual bytes of a value are scattered to the corresponding stream and + the streams are concatenated. + This itself does not reduce the size of the data but can lead to better compression + afterwards. + + Added in 2.8 for FLOAT and DOUBLE. + Support for INT32, INT64 and FIXED_LEN_BYTE_ARRAY added in 2.11. + */ + BYTE_STREAM_SPLIT = 9; +} + +/** + * Supported compression algorithms. + * + * Codecs added in format version X.Y can be read by readers based on X.Y and later. + * Codec support may vary between readers based on the format version and + * libraries available at runtime. + * + * See Compression.md for a detailed specification of these algorithms. + */ +enum CompressionCodec { + UNCOMPRESSED = 0; + SNAPPY = 1; + GZIP = 2; + LZO = 3; + BROTLI = 4; // Added in 2.4 + LZ4 = 5; // DEPRECATED (Added in 2.4) + ZSTD = 6; // Added in 2.4 + LZ4_RAW = 7; // Added in 2.9 +} + +enum PageType { + DATA_PAGE = 0; + INDEX_PAGE = 1; + DICTIONARY_PAGE = 2; + DATA_PAGE_V2 = 3; +} + +/** + * Enum to annotate whether lists of min/max elements inside ColumnIndex + * are ordered and if so, in which direction. + */ +enum BoundaryOrder { + UNORDERED = 0; + ASCENDING = 1; + DESCENDING = 2; +} + +/** Data page header */ +struct DataPageHeader { + /** + * Number of values, including NULLs, in this data page. + * + * If a OffsetIndex is present, a page must begin at a row + * boundary (repetition_level = 0). Otherwise, pages may begin + * within a row (repetition_level > 0). + **/ + 1: required i32 num_values + + /** Encoding used for this data page **/ + 2: required Encoding encoding + + /** Encoding used for definition levels **/ + 3: required Encoding definition_level_encoding; + + /** Encoding used for repetition levels **/ + 4: required Encoding repetition_level_encoding; + + /** Optional statistics for the data in this page **/ + 5: optional Statistics statistics; +} + +struct IndexPageHeader { + // TODO +} + +/** + * The dictionary page must be placed at the first position of the column chunk + * if it is partly or completely dictionary encoded. At most one dictionary page + * can be placed in a column chunk. + **/ +struct DictionaryPageHeader { + /** Number of values in the dictionary **/ + 1: required i32 num_values; + + /** Encoding using this dictionary page **/ + 2: required Encoding encoding + + /** If true, the entries in the dictionary are sorted in ascending order **/ + 3: optional bool is_sorted; +} + +/** + * New page format allowing reading levels without decompressing the data + * Repetition and definition levels are uncompressed + * The remaining section containing the data is compressed if is_compressed is true + **/ +struct DataPageHeaderV2 { + /** Number of values, including NULLs, in this data page. **/ + 1: required i32 num_values + /** Number of NULL values, in this data page. + Number of non-null = num_values - num_nulls which is also the number of values in the data section **/ + 2: required i32 num_nulls + /** + * Number of rows in this data page. Every page must begin at a + * row boundary (repetition_level = 0): rows must **not** be + * split across page boundaries when using V2 data pages. + **/ + 3: required i32 num_rows + /** Encoding used for data in this page **/ + 4: required Encoding encoding + + // repetition levels and definition levels are always using RLE (without size in it) + + /** Length of the definition levels */ + 5: required i32 definition_levels_byte_length; + /** Length of the repetition levels */ + 6: required i32 repetition_levels_byte_length; + + /** Whether the values are compressed. + Which means the section of the page between + definition_levels_byte_length + repetition_levels_byte_length + 1 and compressed_page_size (included) + is compressed with the compression_codec. + If missing it is considered compressed */ + 7: optional bool is_compressed = true; + + /** Optional statistics for the data in this page **/ + 8: optional Statistics statistics; +} + +/** Block-based algorithm type annotation. **/ +struct SplitBlockAlgorithm {} +/** The algorithm used in Bloom filter. **/ +union BloomFilterAlgorithm { + /** Block-based Bloom filter. **/ + 1: SplitBlockAlgorithm BLOCK; +} + +/** Hash strategy type annotation. xxHash is an extremely fast non-cryptographic hash + * algorithm. It uses 64 bits version of xxHash. + **/ +struct XxHash {} + +/** + * The hash function used in Bloom filter. This function takes the hash of a column value + * using plain encoding. + **/ +union BloomFilterHash { + /** xxHash Strategy. **/ + 1: XxHash XXHASH; +} + +/** + * The compression used in the Bloom filter. + **/ +struct Uncompressed {} +union BloomFilterCompression { + 1: Uncompressed UNCOMPRESSED; +} + +/** + * Bloom filter header is stored at beginning of Bloom filter data of each column + * and followed by its bitset. + **/ +struct BloomFilterHeader { + /** The size of bitset in bytes **/ + 1: required i32 numBytes; + /** The algorithm for setting bits. **/ + 2: required BloomFilterAlgorithm algorithm; + /** The hash function used for Bloom filter. **/ + 3: required BloomFilterHash hash; + /** The compression used in the Bloom filter **/ + 4: required BloomFilterCompression compression; +} + +struct PageHeader { + /** the type of the page: indicates which of the *_header fields is set **/ + 1: required PageType type + + /** Uncompressed page size in bytes (not including this header) **/ + 2: required i32 uncompressed_page_size + + /** Compressed (and potentially encrypted) page size in bytes, not including this header **/ + 3: required i32 compressed_page_size + + /** The 32-bit CRC checksum for the page, to be be calculated as follows: + * + * - The standard CRC32 algorithm is used (with polynomial 0x04C11DB7, + * the same as in e.g. GZip). + * - All page types can have a CRC (v1 and v2 data pages, dictionary pages, + * etc.). + * - The CRC is computed on the serialization binary representation of the page + * (as written to disk), excluding the page header. For example, for v1 + * data pages, the CRC is computed on the concatenation of repetition levels, + * definition levels and column values (optionally compressed, optionally + * encrypted). + * - The CRC computation therefore takes place after any compression + * and encryption steps, if any. + * + * If enabled, this allows for disabling checksumming in HDFS if only a few + * pages need to be read. + */ + 4: optional i32 crc + + // Headers for page specific data. One only will be set. + 5: optional DataPageHeader data_page_header; + 6: optional IndexPageHeader index_page_header; + 7: optional DictionaryPageHeader dictionary_page_header; + 8: optional DataPageHeaderV2 data_page_header_v2; +} + +/** + * Wrapper struct to store key values + */ + struct KeyValue { + 1: required string key + 2: optional string value +} + +/** + * Sort order within a RowGroup of a leaf column + */ +struct SortingColumn { + /** The ordinal position of the column (in this row group) **/ + 1: required i32 column_idx + + /** If true, indicates this column is sorted in descending order. **/ + 2: required bool descending + + /** If true, nulls will come before non-null values, otherwise, + * nulls go at the end. */ + 3: required bool nulls_first +} + +/** + * statistics of a given page type and encoding + */ +struct PageEncodingStats { + + /** the page type (data/dic/...) **/ + 1: required PageType page_type; + + /** encoding of the page **/ + 2: required Encoding encoding; + + /** number of pages of this type with this encoding **/ + 3: required i32 count; + +} + +/** + * Description for column metadata + */ +struct ColumnMetaData { + /** Type of this column **/ + 1: required Type type + + /** Set of all encodings used for this column. The purpose is to validate + * whether we can decode those pages. **/ + 2: required list encodings + + /** Path in schema **/ + 3: required list path_in_schema + + /** Compression codec **/ + 4: required CompressionCodec codec + + /** Number of values in this column **/ + 5: required i64 num_values + + /** total byte size of all uncompressed pages in this column chunk (including the headers) **/ + 6: required i64 total_uncompressed_size + + /** total byte size of all compressed, and potentially encrypted, pages + * in this column chunk (including the headers) **/ + 7: required i64 total_compressed_size + + /** Optional key/value metadata **/ + 8: optional list key_value_metadata + + /** Byte offset from beginning of file to first data page **/ + 9: required i64 data_page_offset + + /** Byte offset from beginning of file to root index page **/ + 10: optional i64 index_page_offset + + /** Byte offset from the beginning of file to first (only) dictionary page **/ + 11: optional i64 dictionary_page_offset + + /** optional statistics for this column chunk */ + 12: optional Statistics statistics; + + /** Set of all encodings used for pages in this column chunk. + * This information can be used to determine if all data pages are + * dictionary encoded for example **/ + 13: optional list encoding_stats; + + /** Byte offset from beginning of file to Bloom filter data. **/ + 14: optional i64 bloom_filter_offset; + + /** Size of Bloom filter data including the serialized header, in bytes. + * Added in 2.10 so readers may not read this field from old files and + * it can be obtained after the BloomFilterHeader has been deserialized. + * Writers should write this field so readers can read the bloom filter + * in a single I/O. + */ + 15: optional i32 bloom_filter_length; + + /** + * Optional statistics to help estimate total memory when converted to in-memory + * representations. The histograms contained in these statistics can + * also be useful in some cases for more fine-grained nullability/list length + * filter pushdown. + */ + 16: optional SizeStatistics size_statistics; +} + +struct EncryptionWithFooterKey { +} + +struct EncryptionWithColumnKey { + /** Column path in schema **/ + 1: required list path_in_schema + + /** Retrieval metadata of column encryption key **/ + 2: optional binary key_metadata +} + +union ColumnCryptoMetaData { + 1: EncryptionWithFooterKey ENCRYPTION_WITH_FOOTER_KEY + 2: EncryptionWithColumnKey ENCRYPTION_WITH_COLUMN_KEY +} + +struct ColumnChunk { + /** File where column data is stored. If not set, assumed to be same file as + * metadata. This path is relative to the current file. + **/ + 1: optional string file_path + + /** Deprecated: Byte offset in file_path to the ColumnMetaData + * + * Past use of this field has been inconsistent, with some implementations + * using it to point to the ColumnMetaData and some using it to point to + * the first page in the column chunk. In many cases, the ColumnMetaData at this + * location is wrong. This field is now deprecated and should not be used. + * Writers should set this field to 0 if no ColumnMetaData has been written outside + * the footer. + */ + 2: required i64 file_offset = 0 + + /** Column metadata for this chunk. Some writers may also replicate this at the + * location pointed to by file_path/file_offset. + * Note: while marked as optional, this field is in fact required by most major + * Parquet implementations. As such, writers MUST populate this field. + **/ + 3: optional ColumnMetaData meta_data + + /** File offset of ColumnChunk's OffsetIndex **/ + 4: optional i64 offset_index_offset + + /** Size of ColumnChunk's OffsetIndex, in bytes **/ + 5: optional i32 offset_index_length + + /** File offset of ColumnChunk's ColumnIndex **/ + 6: optional i64 column_index_offset + + /** Size of ColumnChunk's ColumnIndex, in bytes **/ + 7: optional i32 column_index_length + + /** Crypto metadata of encrypted columns **/ + 8: optional ColumnCryptoMetaData crypto_metadata + + /** Encrypted column metadata for this chunk **/ + 9: optional binary encrypted_column_metadata +} + +struct RowGroup { + /** Metadata for each column chunk in this row group. + * This list must have the same order as the SchemaElement list in FileMetaData. + **/ + 1: required list columns + + /** Total byte size of all the uncompressed column data in this row group **/ + 2: required i64 total_byte_size + + /** Number of rows in this row group **/ + 3: required i64 num_rows + + /** If set, specifies a sort ordering of the rows in this RowGroup. + * The sorting columns can be a subset of all the columns. + */ + 4: optional list sorting_columns + + /** Byte offset from beginning of file to first page (data or dictionary) + * in this row group **/ + 5: optional i64 file_offset + + /** Total byte size of all compressed (and potentially encrypted) column data + * in this row group **/ + 6: optional i64 total_compressed_size + + /** Row group ordinal in the file **/ + 7: optional i16 ordinal +} + +/** Empty struct to signal the order defined by the physical or logical type */ +struct TypeDefinedOrder {} + +/** + * Union to specify the order used for the min_value and max_value fields for a + * column. This union takes the role of an enhanced enum that allows rich + * elements (which will be needed for a collation-based ordering in the future). + * + * Possible values are: + * * TypeDefinedOrder - the column uses the order defined by its logical or + * physical type (if there is no logical type). + * + * If the reader does not support the value of this union, min and max stats + * for this column should be ignored. + */ +union ColumnOrder { + + /** + * The sort orders for logical types are: + * UTF8 - unsigned byte-wise comparison + * INT8 - signed comparison + * INT16 - signed comparison + * INT32 - signed comparison + * INT64 - signed comparison + * UINT8 - unsigned comparison + * UINT16 - unsigned comparison + * UINT32 - unsigned comparison + * UINT64 - unsigned comparison + * DECIMAL - signed comparison of the represented value + * DATE - signed comparison + * TIME_MILLIS - signed comparison + * TIME_MICROS - signed comparison + * TIMESTAMP_MILLIS - signed comparison + * TIMESTAMP_MICROS - signed comparison + * INTERVAL - undefined + * JSON - unsigned byte-wise comparison + * BSON - unsigned byte-wise comparison + * ENUM - unsigned byte-wise comparison + * LIST - undefined + * MAP - undefined + * + * In the absence of logical types, the sort order is determined by the physical type: + * BOOLEAN - false, true + * INT32 - signed comparison + * INT64 - signed comparison + * INT96 (only used for legacy timestamps) - undefined + * FLOAT - signed comparison of the represented value (*) + * DOUBLE - signed comparison of the represented value (*) + * BYTE_ARRAY - unsigned byte-wise comparison + * FIXED_LEN_BYTE_ARRAY - unsigned byte-wise comparison + * + * (*) Because the sorting order is not specified properly for floating + * point values (relations vs. total ordering) the following + * compatibility rules should be applied when reading statistics: + * - If the min is a NaN, it should be ignored. + * - If the max is a NaN, it should be ignored. + * - If the min is +0, the row group may contain -0 values as well. + * - If the max is -0, the row group may contain +0 values as well. + * - When looking for NaN values, min and max should be ignored. + * + * When writing statistics the following rules should be followed: + * - NaNs should not be written to min or max statistics fields. + * - If the computed max value is zero (whether negative or positive), + * `+0.0` should be written into the max statistics field. + * - If the computed min value is zero (whether negative or positive), + * `-0.0` should be written into the min statistics field. + */ + 1: TypeDefinedOrder TYPE_ORDER; +} + +struct PageLocation { + /** Offset of the page in the file **/ + 1: required i64 offset + + /** + * Size of the page, including header. Sum of compressed_page_size and header + * length + */ + 2: required i32 compressed_page_size + + /** + * Index within the RowGroup of the first row of the page. When an + * OffsetIndex is present, pages must begin on row boundaries + * (repetition_level = 0). + */ + 3: required i64 first_row_index +} + +/** + * Optional offsets for each data page in a ColumnChunk. + * + * Forms part of the page index, along with ColumnIndex. + * + * OffsetIndex may be present even if ColumnIndex is not. + */ +struct OffsetIndex { + /** + * PageLocations, ordered by increasing PageLocation.offset. It is required + * that page_locations[i].first_row_index < page_locations[i+1].first_row_index. + */ + 1: required list page_locations + /** + * Unencoded/uncompressed size for BYTE_ARRAY types. + * + * See documention for unencoded_byte_array_data_bytes in SizeStatistics for + * more details on this field. + */ + 2: optional list unencoded_byte_array_data_bytes +} + +/** + * Optional statistics for each data page in a ColumnChunk. + * + * Forms part the page index, along with OffsetIndex. + * + * If this structure is present, OffsetIndex must also be present. + * + * For each field in this structure, [i] refers to the page at + * OffsetIndex.page_locations[i] + */ +struct ColumnIndex { + /** + * A list of Boolean values to determine the validity of the corresponding + * min and max values. If true, a page contains only null values, and writers + * have to set the corresponding entries in min_values and max_values to + * byte[0], so that all lists have the same length. If false, the + * corresponding entries in min_values and max_values must be valid. + */ + 1: required list null_pages + + /** + * Two lists containing lower and upper bounds for the values of each page + * determined by the ColumnOrder of the column. These may be the actual + * minimum and maximum values found on a page, but can also be (more compact) + * values that do not exist on a page. For example, instead of storing ""Blart + * Versenwald III", a writer may set min_values[i]="B", max_values[i]="C". + * Such more compact values must still be valid values within the column's + * logical type. Readers must make sure that list entries are populated before + * using them by inspecting null_pages. + */ + 2: required list min_values + 3: required list max_values + + /** + * Stores whether both min_values and max_values are ordered and if so, in + * which direction. This allows readers to perform binary searches in both + * lists. Readers cannot assume that max_values[i] <= min_values[i+1], even + * if the lists are ordered. + */ + 4: required BoundaryOrder boundary_order + + /** + * A list containing the number of null values for each page + * + * Writers SHOULD always write this field even if no null values + * are present or the column is not nullable. + * Readers MUST distinguish between null_counts not being present + * and null_count being 0. + * If null_counts are not present, readers MUST NOT assume all + * null counts are 0. + */ + 5: optional list null_counts + + /** + * Contains repetition level histograms for each page + * concatenated together. The repetition_level_histogram field on + * SizeStatistics contains more details. + * + * When present the length should always be (number of pages * + * (max_repetition_level + 1)) elements. + * + * Element 0 is the first element of the histogram for the first page. + * Element (max_repetition_level + 1) is the first element of the histogram + * for the second page. + **/ + 6: optional list repetition_level_histograms; + /** + * Same as repetition_level_histograms except for definitions levels. + **/ + 7: optional list definition_level_histograms; +} + +struct AesGcmV1 { + /** AAD prefix **/ + 1: optional binary aad_prefix + + /** Unique file identifier part of AAD suffix **/ + 2: optional binary aad_file_unique + + /** In files encrypted with AAD prefix without storing it, + * readers must supply the prefix **/ + 3: optional bool supply_aad_prefix +} + +struct AesGcmCtrV1 { + /** AAD prefix **/ + 1: optional binary aad_prefix + + /** Unique file identifier part of AAD suffix **/ + 2: optional binary aad_file_unique + + /** In files encrypted with AAD prefix without storing it, + * readers must supply the prefix **/ + 3: optional bool supply_aad_prefix +} + +union EncryptionAlgorithm { + 1: AesGcmV1 AES_GCM_V1 + 2: AesGcmCtrV1 AES_GCM_CTR_V1 +} + +/** + * Description for file metadata + */ +struct FileMetaData { + /** Version of this file **/ + 1: required i32 version + + /** Parquet schema for this file. This schema contains metadata for all the columns. + * The schema is represented as a tree with a single root. The nodes of the tree + * are flattened to a list by doing a depth-first traversal. + * The column metadata contains the path in the schema for that column which can be + * used to map columns to nodes in the schema. + * The first element is the root **/ + 2: required list schema; + + /** Number of rows in this file **/ + 3: required i64 num_rows + + /** Row groups in this file **/ + 4: required list row_groups + + /** Optional key/value metadata **/ + 5: optional list key_value_metadata + + /** String for application that wrote this file. This should be in the format + * version (build ). + * e.g. impala version 1.0 (build 6cf94d29b2b7115df4de2c06e2ab4326d721eb55) + **/ + 6: optional string created_by + + /** + * Sort order used for the min_value and max_value fields in the Statistics + * objects and the min_values and max_values fields in the ColumnIndex + * objects of each column in this file. Sort orders are listed in the order + * matching the columns in the schema. The indexes are not necessary the same + * though, because only leaf nodes of the schema are represented in the list + * of sort orders. + * + * Without column_orders, the meaning of the min_value and max_value fields + * in the Statistics object and the ColumnIndex object is undefined. To ensure + * well-defined behaviour, if these fields are written to a Parquet file, + * column_orders must be written as well. + * + * The obsolete min and max fields in the Statistics object are always sorted + * by signed comparison regardless of column_orders. + */ + 7: optional list column_orders; + + /** + * Encryption algorithm. This field is set only in encrypted files + * with plaintext footer. Files with encrypted footer store algorithm id + * in FileCryptoMetaData structure. + */ + 8: optional EncryptionAlgorithm encryption_algorithm + + /** + * Retrieval metadata of key used for signing the footer. + * Used only in encrypted files with plaintext footer. + */ + 9: optional binary footer_signing_key_metadata +} + +/** Crypto metadata for files with encrypted footer **/ +struct FileCryptoMetaData { + /** + * Encryption algorithm. This field is only used for files + * with encrypted footer. Files with plaintext footer store algorithm id + * inside footer (FileMetaData structure). + */ + 1: required EncryptionAlgorithm encryption_algorithm + + /** Retrieval metadata of key used for encryption of footer, + * and (possibly) columns **/ + 2: optional binary key_metadata +} diff --git a/third_party/parquet/parquet_constants.cpp b/third_party/parquet/parquet_constants.cpp deleted file mode 100644 index de4420ba047..00000000000 --- a/third_party/parquet/parquet_constants.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Autogenerated by Thrift Compiler (0.11.0) - * - * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - * @generated - */ -#include "parquet_constants.h" - -namespace duckdb_parquet { namespace format { - -const parquetConstants g_parquet_constants; - -parquetConstants::parquetConstants() { -} - -}} // namespace - diff --git a/third_party/parquet/parquet_constants.h b/third_party/parquet/parquet_constants.h deleted file mode 100644 index 468309ce858..00000000000 --- a/third_party/parquet/parquet_constants.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Autogenerated by Thrift Compiler (0.11.0) - * - * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - * @generated - */ -#ifndef parquet_CONSTANTS_H -#define parquet_CONSTANTS_H - -#include "parquet_types.h" - -namespace duckdb_parquet { namespace format { - -class parquetConstants { - public: - parquetConstants(); - -}; - -extern const parquetConstants g_parquet_constants; - -}} // namespace - -#endif diff --git a/third_party/parquet/parquet_types.cpp b/third_party/parquet/parquet_types.cpp index e6eeb774d06..76cac6b0bd8 100644 --- a/third_party/parquet/parquet_types.cpp +++ b/third_party/parquet/parquet_types.cpp @@ -1,5 +1,5 @@ /** - * Autogenerated by Thrift Compiler (0.11.0) + * Autogenerated by Thrift Compiler (0.21.0) * * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING * @generated @@ -9,244 +9,664 @@ #include #include -#include "thrift/TToString.h" - -namespace duckdb_parquet { namespace format { - -std::ostream &operator<<(std::ostream &out, const Type::type &val) { - switch (val) { - case Type::BOOLEAN: - out << "BOOLEAN"; - return out; - case Type::INT32: - out << "INT32"; - return out; - case Type::INT64: - out << "INT64"; - return out; - case Type::INT96: - out << "INT96"; - return out; - case Type::FLOAT: - out << "FLOAT"; - return out; - case Type::DOUBLE: - out << "DOUBLE"; - return out; - case Type::BYTE_ARRAY: - out << "BYTE_ARRAY"; - return out; - case Type::FIXED_LEN_BYTE_ARRAY: - out << "FIXED_LEN_BYTE_ARRAY"; - return out; - // no default for compiler error on missing enum - } - out << static_cast(val); - return out; -} - -std::ostream &operator<<(std::ostream &out, const ConvertedType::type &val) { - switch (val) { - case ConvertedType::UTF8: - out << "UTF8"; - return out; - case ConvertedType::MAP: - out << "MAP"; - return out; - case ConvertedType::MAP_KEY_VALUE: - out << "MAP_KEY_VALUE"; - return out; - case ConvertedType::LIST: - out << "LIST"; - return out; - case ConvertedType::ENUM: - out << "ENUM"; - return out; - case ConvertedType::DECIMAL: - out << "DECIMAL"; - return out; - case ConvertedType::DATE: - out << "DATE"; - return out; - case ConvertedType::TIME_MILLIS: - out << "TIME_MILLIS"; - return out; - case ConvertedType::TIME_MICROS: - out << "TIME_MICROS"; - return out; - case ConvertedType::TIMESTAMP_MILLIS: - out << "TIMESTAMP_MILLIS"; - return out; - case ConvertedType::TIMESTAMP_MICROS: - out << "TIMESTAMP_MICROS"; - return out; - case ConvertedType::UINT_8: - out << "UINT_8"; - return out; - case ConvertedType::UINT_16: - out << "UINT_16"; - return out; - case ConvertedType::UINT_32: - out << "UINT_32"; - return out; - case ConvertedType::UINT_64: - out << "UINT_64"; - return out; - case ConvertedType::INT_8: - out << "INT_8"; - return out; - case ConvertedType::INT_16: - out << "INT_16"; - return out; - case ConvertedType::INT_32: - out << "INT_32"; - return out; - case ConvertedType::INT_64: - out << "INT_64"; - return out; - case ConvertedType::JSON: - out << "JSON"; - return out; - case ConvertedType::BSON: - out << "BSON"; - return out; - case ConvertedType::INTERVAL: - out << "INTERVAL"; - return out; - case ConvertedType::NULL_TYPE: - out << "NULL"; - return out; - // no default for compiler error on missing enum - } - out << static_cast(val); - return out; -} - -std::ostream &operator<<(std::ostream &out, const FieldRepetitionType::type &val) { - switch (val) { - case FieldRepetitionType::REQUIRED: - out << "REQUIRED"; - return out; - case FieldRepetitionType::OPTIONAL: - out << "OPTIONAL"; - return out; - case FieldRepetitionType::REPEATED: - out << "REPEATED"; - return out; - // no default for compiler error on missing enum - } - out << static_cast(val); - return out; -} - -std::ostream &operator<<(std::ostream &out, const Encoding::type &val) { - switch (val) { - case Encoding::PLAIN: - out << "PLAIN"; - return out; - case Encoding::PLAIN_DICTIONARY: - out << "PLAIN_DICTIONARY"; - return out; - case Encoding::RLE: - out << "RLE"; - return out; - case Encoding::BIT_PACKED: - out << "BIT_PACKED"; - return out; - case Encoding::DELTA_BINARY_PACKED: - out << "DELTA_BINARY_PACKED"; - return out; - case Encoding::DELTA_LENGTH_BYTE_ARRAY: - out << "DELTA_LENGTH_BYTE_ARRAY"; - return out; - case Encoding::DELTA_BYTE_ARRAY: - out << "DELTA_BYTE_ARRAY"; - return out; - case Encoding::RLE_DICTIONARY: - out << "RLE_DICTIONARY"; - return out; - case Encoding::BYTE_STREAM_SPLIT: - out << "BYTE_STREAM_SPLIT"; - return out; - // no default for compiler error on missing enum - } - out << static_cast(val); - return out; -} - -std::ostream &operator<<(std::ostream &out, const CompressionCodec::type &val) { - switch (val) { - case CompressionCodec::UNCOMPRESSED: - out << "UNCOMPRESSED"; - return out; - case CompressionCodec::SNAPPY: - out << "SNAPPY"; - return out; - case CompressionCodec::GZIP: - out << "GZIP"; - return out; - case CompressionCodec::LZO: - out << "LZO"; - return out; - case CompressionCodec::BROTLI: - out << "BROTLI"; - return out; - case CompressionCodec::LZ4: - out << "LZ4"; - return out; - case CompressionCodec::ZSTD: - out << "ZSTD"; - return out; - case CompressionCodec::LZ4_RAW: - out << "LZ4_RAW"; - return out; - // no default for compiler error on missing enum - } - out << static_cast(val); - return out; -} - -std::ostream &operator<<(std::ostream &out, const PageType::type &val) { - switch (val) { - case PageType::DATA_PAGE: - out << "DATA_PAGE"; - return out; - case PageType::INDEX_PAGE: - out << "INDEX_PAGE"; - return out; - case PageType::DICTIONARY_PAGE: - out << "DICTIONARY_PAGE"; - return out; - case PageType::DATA_PAGE_V2: - out << "DATA_PAGE_V2"; - return out; - // no default for compiler error on missing enum - } - out << static_cast(val); - return out; -} - -std::ostream &operator<<(std::ostream &out, const BoundaryOrder::type &val) { - switch (val) { - case BoundaryOrder::UNORDERED: - out << "UNORDERED"; - return out; - case BoundaryOrder::ASCENDING: - out << "ASCENDING"; - return out; - case BoundaryOrder::DESCENDING: - out << "DESCENDING"; - return out; - // no default for compiler error on missing enum - } - out << static_cast(val); - return out; -} - - -Statistics::~Statistics() throw() { +#include + +namespace duckdb_parquet { + +int _kTypeValues[] = { + Type::BOOLEAN, + Type::INT32, + Type::INT64, + Type::INT96, + Type::FLOAT, + Type::DOUBLE, + Type::BYTE_ARRAY, + Type::FIXED_LEN_BYTE_ARRAY +}; +const char* _kTypeNames[] = { + "BOOLEAN", + "INT32", + "INT64", + "INT96", + "FLOAT", + "DOUBLE", + "BYTE_ARRAY", + "FIXED_LEN_BYTE_ARRAY" +}; +const std::map _Type_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(8, _kTypeValues, _kTypeNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); + +int _kConvertedTypeValues[] = { + /** + * a BYTE_ARRAY actually contains UTF8 encoded chars + */ + ConvertedType::UTF8, + /** + * a map is converted as an optional field containing a repeated key/value pair + */ + ConvertedType::MAP, + /** + * a key/value pair is converted into a group of two fields + */ + ConvertedType::MAP_KEY_VALUE, + /** + * a list is converted into an optional field containing a repeated field for its + * values + */ + ConvertedType::LIST, + /** + * an enum is converted into a BYTE_ARRAY field + */ + ConvertedType::ENUM, + /** + * A decimal value. + * + * This may be used to annotate BYTE_ARRAY or FIXED_LEN_BYTE_ARRAY primitive + * types. The underlying byte array stores the unscaled value encoded as two's + * complement using big-endian byte order (the most significant byte is the + * zeroth element). The value of the decimal is the value * 10^{-scale}. + * + * This must be accompanied by a (maximum) precision and a scale in the + * SchemaElement. The precision specifies the number of digits in the decimal + * and the scale stores the location of the decimal point. For example 1.23 + * would have precision 3 (3 total digits) and scale 2 (the decimal point is + * 2 digits over). + */ + ConvertedType::DECIMAL, + /** + * A Date + * + * Stored as days since Unix epoch, encoded as the INT32 physical type. + * + */ + ConvertedType::DATE, + /** + * A time + * + * The total number of milliseconds since midnight. The value is stored + * as an INT32 physical type. + */ + ConvertedType::TIME_MILLIS, + /** + * A time. + * + * The total number of microseconds since midnight. The value is stored as + * an INT64 physical type. + */ + ConvertedType::TIME_MICROS, + /** + * A date/time combination + * + * Date and time recorded as milliseconds since the Unix epoch. Recorded as + * a physical type of INT64. + */ + ConvertedType::TIMESTAMP_MILLIS, + /** + * A date/time combination + * + * Date and time recorded as microseconds since the Unix epoch. The value is + * stored as an INT64 physical type. + */ + ConvertedType::TIMESTAMP_MICROS, + /** + * An unsigned integer value. + * + * The number describes the maximum number of meaningful data bits in + * the stored value. 8, 16 and 32 bit values are stored using the + * INT32 physical type. 64 bit values are stored using the INT64 + * physical type. + * + */ + ConvertedType::UINT_8, + ConvertedType::UINT_16, + ConvertedType::UINT_32, + ConvertedType::UINT_64, + /** + * A signed integer value. + * + * The number describes the maximum number of meaningful data bits in + * the stored value. 8, 16 and 32 bit values are stored using the + * INT32 physical type. 64 bit values are stored using the INT64 + * physical type. + * + */ + ConvertedType::INT_8, + ConvertedType::INT_16, + ConvertedType::INT_32, + ConvertedType::INT_64, + /** + * An embedded JSON document + * + * A JSON document embedded within a single UTF8 column. + */ + ConvertedType::JSON, + /** + * An embedded BSON document + * + * A BSON document embedded within a single BYTE_ARRAY column. + */ + ConvertedType::BSON, + /** + * An interval of time + * + * This type annotates data stored as a FIXED_LEN_BYTE_ARRAY of length 12 + * This data is composed of three separate little endian unsigned + * integers. Each stores a component of a duration of time. The first + * integer identifies the number of months associated with the duration, + * the second identifies the number of days associated with the duration + * and the third identifies the number of milliseconds associated with + * the provided duration. This duration of time is independent of any + * particular timezone or date. + */ + ConvertedType::INTERVAL +}; +const char* _kConvertedTypeNames[] = { + /** + * a BYTE_ARRAY actually contains UTF8 encoded chars + */ + "UTF8", + /** + * a map is converted as an optional field containing a repeated key/value pair + */ + "MAP", + /** + * a key/value pair is converted into a group of two fields + */ + "MAP_KEY_VALUE", + /** + * a list is converted into an optional field containing a repeated field for its + * values + */ + "LIST", + /** + * an enum is converted into a BYTE_ARRAY field + */ + "ENUM", + /** + * A decimal value. + * + * This may be used to annotate BYTE_ARRAY or FIXED_LEN_BYTE_ARRAY primitive + * types. The underlying byte array stores the unscaled value encoded as two's + * complement using big-endian byte order (the most significant byte is the + * zeroth element). The value of the decimal is the value * 10^{-scale}. + * + * This must be accompanied by a (maximum) precision and a scale in the + * SchemaElement. The precision specifies the number of digits in the decimal + * and the scale stores the location of the decimal point. For example 1.23 + * would have precision 3 (3 total digits) and scale 2 (the decimal point is + * 2 digits over). + */ + "DECIMAL", + /** + * A Date + * + * Stored as days since Unix epoch, encoded as the INT32 physical type. + * + */ + "DATE", + /** + * A time + * + * The total number of milliseconds since midnight. The value is stored + * as an INT32 physical type. + */ + "TIME_MILLIS", + /** + * A time. + * + * The total number of microseconds since midnight. The value is stored as + * an INT64 physical type. + */ + "TIME_MICROS", + /** + * A date/time combination + * + * Date and time recorded as milliseconds since the Unix epoch. Recorded as + * a physical type of INT64. + */ + "TIMESTAMP_MILLIS", + /** + * A date/time combination + * + * Date and time recorded as microseconds since the Unix epoch. The value is + * stored as an INT64 physical type. + */ + "TIMESTAMP_MICROS", + /** + * An unsigned integer value. + * + * The number describes the maximum number of meaningful data bits in + * the stored value. 8, 16 and 32 bit values are stored using the + * INT32 physical type. 64 bit values are stored using the INT64 + * physical type. + * + */ + "UINT_8", + "UINT_16", + "UINT_32", + "UINT_64", + /** + * A signed integer value. + * + * The number describes the maximum number of meaningful data bits in + * the stored value. 8, 16 and 32 bit values are stored using the + * INT32 physical type. 64 bit values are stored using the INT64 + * physical type. + * + */ + "INT_8", + "INT_16", + "INT_32", + "INT_64", + /** + * An embedded JSON document + * + * A JSON document embedded within a single UTF8 column. + */ + "JSON", + /** + * An embedded BSON document + * + * A BSON document embedded within a single BYTE_ARRAY column. + */ + "BSON", + /** + * An interval of time + * + * This type annotates data stored as a FIXED_LEN_BYTE_ARRAY of length 12 + * This data is composed of three separate little endian unsigned + * integers. Each stores a component of a duration of time. The first + * integer identifies the number of months associated with the duration, + * the second identifies the number of days associated with the duration + * and the third identifies the number of milliseconds associated with + * the provided duration. This duration of time is independent of any + * particular timezone or date. + */ + "INTERVAL" +}; +const std::map _ConvertedType_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(22, _kConvertedTypeValues, _kConvertedTypeNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); + +int _kFieldRepetitionTypeValues[] = { + /** + * This field is required (can not be null) and each row has exactly 1 value. + */ + FieldRepetitionType::REQUIRED, + /** + * The field is optional (can be null) and each row has 0 or 1 values. + */ + FieldRepetitionType::OPTIONAL, + /** + * The field is repeated and can contain 0 or more values + */ + FieldRepetitionType::REPEATED +}; +const char* _kFieldRepetitionTypeNames[] = { + /** + * This field is required (can not be null) and each row has exactly 1 value. + */ + "REQUIRED", + /** + * The field is optional (can be null) and each row has 0 or 1 values. + */ + "OPTIONAL", + /** + * The field is repeated and can contain 0 or more values + */ + "REPEATED" +}; +const std::map _FieldRepetitionType_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(3, _kFieldRepetitionTypeValues, _kFieldRepetitionTypeNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); + +int _kEncodingValues[] = { + /** + * Default encoding. + * BOOLEAN - 1 bit per value. 0 is false; 1 is true. + * INT32 - 4 bytes per value. Stored as little-endian. + * INT64 - 8 bytes per value. Stored as little-endian. + * FLOAT - 4 bytes per value. IEEE. Stored as little-endian. + * DOUBLE - 8 bytes per value. IEEE. Stored as little-endian. + * BYTE_ARRAY - 4 byte length stored as little endian, followed by bytes. + * FIXED_LEN_BYTE_ARRAY - Just the bytes. + */ + Encoding::PLAIN, + /** + * Deprecated: Dictionary encoding. The values in the dictionary are encoded in the + * plain type. + * in a data page use RLE_DICTIONARY instead. + * in a Dictionary page use PLAIN instead + */ + Encoding::PLAIN_DICTIONARY, + /** + * Group packed run length encoding. Usable for definition/repetition levels + * encoding and Booleans (on one bit: 0 is false; 1 is true.) + */ + Encoding::RLE, + /** + * Bit packed encoding. This can only be used if the data has a known max + * width. Usable for definition/repetition levels encoding. + */ + Encoding::BIT_PACKED, + /** + * Delta encoding for integers. This can be used for int columns and works best + * on sorted data + */ + Encoding::DELTA_BINARY_PACKED, + /** + * Encoding for byte arrays to separate the length values and the data. The lengths + * are encoded using DELTA_BINARY_PACKED + */ + Encoding::DELTA_LENGTH_BYTE_ARRAY, + /** + * Incremental-encoded byte array. Prefix lengths are encoded using DELTA_BINARY_PACKED. + * Suffixes are stored as delta length byte arrays. + */ + Encoding::DELTA_BYTE_ARRAY, + /** + * Dictionary encoding: the ids are encoded using the RLE encoding + */ + Encoding::RLE_DICTIONARY, + /** + * Encoding for fixed-width data (FLOAT, DOUBLE, INT32, INT64, FIXED_LEN_BYTE_ARRAY). + * K byte-streams are created where K is the size in bytes of the data type. + * The individual bytes of a value are scattered to the corresponding stream and + * the streams are concatenated. + * This itself does not reduce the size of the data but can lead to better compression + * afterwards. + * + * Added in 2.8 for FLOAT and DOUBLE. + * Support for INT32, INT64 and FIXED_LEN_BYTE_ARRAY added in 2.11. + */ + Encoding::BYTE_STREAM_SPLIT +}; +const char* _kEncodingNames[] = { + /** + * Default encoding. + * BOOLEAN - 1 bit per value. 0 is false; 1 is true. + * INT32 - 4 bytes per value. Stored as little-endian. + * INT64 - 8 bytes per value. Stored as little-endian. + * FLOAT - 4 bytes per value. IEEE. Stored as little-endian. + * DOUBLE - 8 bytes per value. IEEE. Stored as little-endian. + * BYTE_ARRAY - 4 byte length stored as little endian, followed by bytes. + * FIXED_LEN_BYTE_ARRAY - Just the bytes. + */ + "PLAIN", + /** + * Deprecated: Dictionary encoding. The values in the dictionary are encoded in the + * plain type. + * in a data page use RLE_DICTIONARY instead. + * in a Dictionary page use PLAIN instead + */ + "PLAIN_DICTIONARY", + /** + * Group packed run length encoding. Usable for definition/repetition levels + * encoding and Booleans (on one bit: 0 is false; 1 is true.) + */ + "RLE", + /** + * Bit packed encoding. This can only be used if the data has a known max + * width. Usable for definition/repetition levels encoding. + */ + "BIT_PACKED", + /** + * Delta encoding for integers. This can be used for int columns and works best + * on sorted data + */ + "DELTA_BINARY_PACKED", + /** + * Encoding for byte arrays to separate the length values and the data. The lengths + * are encoded using DELTA_BINARY_PACKED + */ + "DELTA_LENGTH_BYTE_ARRAY", + /** + * Incremental-encoded byte array. Prefix lengths are encoded using DELTA_BINARY_PACKED. + * Suffixes are stored as delta length byte arrays. + */ + "DELTA_BYTE_ARRAY", + /** + * Dictionary encoding: the ids are encoded using the RLE encoding + */ + "RLE_DICTIONARY", + /** + * Encoding for fixed-width data (FLOAT, DOUBLE, INT32, INT64, FIXED_LEN_BYTE_ARRAY). + * K byte-streams are created where K is the size in bytes of the data type. + * The individual bytes of a value are scattered to the corresponding stream and + * the streams are concatenated. + * This itself does not reduce the size of the data but can lead to better compression + * afterwards. + * + * Added in 2.8 for FLOAT and DOUBLE. + * Support for INT32, INT64 and FIXED_LEN_BYTE_ARRAY added in 2.11. + */ + "BYTE_STREAM_SPLIT" +}; +const std::map _Encoding_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(9, _kEncodingValues, _kEncodingNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); + +int _kCompressionCodecValues[] = { + CompressionCodec::UNCOMPRESSED, + CompressionCodec::SNAPPY, + CompressionCodec::GZIP, + CompressionCodec::LZO, + CompressionCodec::BROTLI, + CompressionCodec::LZ4, + CompressionCodec::ZSTD, + CompressionCodec::LZ4_RAW +}; +const char* _kCompressionCodecNames[] = { + "UNCOMPRESSED", + "SNAPPY", + "GZIP", + "LZO", + "BROTLI", + "LZ4", + "ZSTD", + "LZ4_RAW" +}; +const std::map _CompressionCodec_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(8, _kCompressionCodecValues, _kCompressionCodecNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); + +int _kPageTypeValues[] = { + PageType::DATA_PAGE, + PageType::INDEX_PAGE, + PageType::DICTIONARY_PAGE, + PageType::DATA_PAGE_V2 +}; +const char* _kPageTypeNames[] = { + "DATA_PAGE", + "INDEX_PAGE", + "DICTIONARY_PAGE", + "DATA_PAGE_V2" +}; +const std::map _PageType_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(4, _kPageTypeValues, _kPageTypeNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); + +int _kBoundaryOrderValues[] = { + BoundaryOrder::UNORDERED, + BoundaryOrder::ASCENDING, + BoundaryOrder::DESCENDING +}; +const char* _kBoundaryOrderNames[] = { + "UNORDERED", + "ASCENDING", + "DESCENDING" +}; +const std::map _BoundaryOrder_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(3, _kBoundaryOrderValues, _kBoundaryOrderNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); + + +SizeStatistics::~SizeStatistics() noexcept { +} + +SizeStatistics::SizeStatistics() noexcept + : unencoded_byte_array_data_bytes(0) { +} + +void SizeStatistics::__set_unencoded_byte_array_data_bytes(const int64_t val) { + this->unencoded_byte_array_data_bytes = val; +__isset.unencoded_byte_array_data_bytes = true; +} + +void SizeStatistics::__set_repetition_level_histogram(const std::vector & val) { + this->repetition_level_histogram = val; +__isset.repetition_level_histogram = true; +} + +void SizeStatistics::__set_definition_level_histogram(const std::vector & val) { + this->definition_level_histogram = val; +__isset.definition_level_histogram = true; +} + +uint32_t SizeStatistics::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->unencoded_byte_array_data_bytes); + this->__isset.unencoded_byte_array_data_bytes = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->repetition_level_histogram.clear(); + uint32_t _size0; + ::apache::thrift::protocol::TType _etype3; + xfer += iprot->readListBegin(_etype3, _size0); + this->repetition_level_histogram.resize(_size0); + uint32_t _i4; + for (_i4 = 0; _i4 < _size0; ++_i4) + { + xfer += iprot->readI64(this->repetition_level_histogram[_i4]); + } + xfer += iprot->readListEnd(); + } + this->__isset.repetition_level_histogram = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->definition_level_histogram.clear(); + uint32_t _size5; + ::apache::thrift::protocol::TType _etype8; + xfer += iprot->readListBegin(_etype8, _size5); + this->definition_level_histogram.resize(_size5); + uint32_t _i9; + for (_i9 = 0; _i9 < _size5; ++_i9) + { + xfer += iprot->readI64(this->definition_level_histogram[_i9]); + } + xfer += iprot->readListEnd(); + } + this->__isset.definition_level_histogram = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t SizeStatistics::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("SizeStatistics"); + + if (this->__isset.unencoded_byte_array_data_bytes) { + xfer += oprot->writeFieldBegin("unencoded_byte_array_data_bytes", ::apache::thrift::protocol::T_I64, 1); + xfer += oprot->writeI64(this->unencoded_byte_array_data_bytes); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.repetition_level_histogram) { + xfer += oprot->writeFieldBegin("repetition_level_histogram", ::apache::thrift::protocol::T_LIST, 2); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->repetition_level_histogram.size())); + std::vector ::const_iterator _iter10; + for (_iter10 = this->repetition_level_histogram.begin(); _iter10 != this->repetition_level_histogram.end(); ++_iter10) + { + xfer += oprot->writeI64((*_iter10)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.definition_level_histogram) { + xfer += oprot->writeFieldBegin("definition_level_histogram", ::apache::thrift::protocol::T_LIST, 3); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->definition_level_histogram.size())); + std::vector ::const_iterator _iter11; + for (_iter11 = this->definition_level_histogram.begin(); _iter11 != this->definition_level_histogram.end(); ++_iter11) + { + xfer += oprot->writeI64((*_iter11)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(SizeStatistics &a, SizeStatistics &b) { + using ::std::swap; + swap(a.unencoded_byte_array_data_bytes, b.unencoded_byte_array_data_bytes); + swap(a.repetition_level_histogram, b.repetition_level_histogram); + swap(a.definition_level_histogram, b.definition_level_histogram); + swap(a.__isset, b.__isset); +} + +SizeStatistics::SizeStatistics(const SizeStatistics& other12) { + unencoded_byte_array_data_bytes = other12.unencoded_byte_array_data_bytes; + repetition_level_histogram = other12.repetition_level_histogram; + definition_level_histogram = other12.definition_level_histogram; + __isset = other12.__isset; +} +SizeStatistics& SizeStatistics::operator=(const SizeStatistics& other13) { + unencoded_byte_array_data_bytes = other13.unencoded_byte_array_data_bytes; + repetition_level_histogram = other13.repetition_level_histogram; + definition_level_histogram = other13.definition_level_histogram; + __isset = other13.__isset; + return *this; +} + +Statistics::~Statistics() noexcept { } +Statistics::Statistics() noexcept + : max(), + min(), + null_count(0), + distinct_count(0), + max_value(), + min_value(), + is_max_value_exact(0), + is_min_value_exact(0) { +} void Statistics::__set_max(const std::string& val) { this->max = val; @@ -277,36 +697,40 @@ void Statistics::__set_min_value(const std::string& val) { this->min_value = val; __isset.min_value = true; } -std::ostream& operator<<(std::ostream& out, const Statistics& obj) -{ - obj.printTo(out); - return out; + +void Statistics::__set_is_max_value_exact(const bool val) { + this->is_max_value_exact = val; +__isset.is_max_value_exact = true; } +void Statistics::__set_is_min_value_exact(const bool val) { + this->is_min_value_exact = val; +__isset.is_min_value_exact = true; +} -uint32_t Statistics::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t Statistics::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->max); this->__isset.max = true; } else { @@ -314,7 +738,7 @@ uint32_t Statistics::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->min); this->__isset.min = true; } else { @@ -322,7 +746,7 @@ uint32_t Statistics::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->null_count); this->__isset.null_count = true; } else { @@ -330,7 +754,7 @@ uint32_t Statistics::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->distinct_count); this->__isset.distinct_count = true; } else { @@ -338,7 +762,7 @@ uint32_t Statistics::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->max_value); this->__isset.max_value = true; } else { @@ -346,13 +770,29 @@ uint32_t Statistics::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 6: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->min_value); this->__isset.min_value = true; } else { xfer += iprot->skip(ftype); } break; + case 7: + if (ftype == ::apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->is_max_value_exact); + this->__isset.is_max_value_exact = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 8: + if (ftype == ::apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->is_min_value_exact); + this->__isset.is_min_value_exact = true; + } else { + xfer += iprot->skip(ftype); + } + break; default: xfer += iprot->skip(ftype); break; @@ -365,41 +805,51 @@ uint32_t Statistics::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t Statistics::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t Statistics::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("Statistics"); if (this->__isset.max) { - xfer += oprot->writeFieldBegin("max", ::duckdb_apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeFieldBegin("max", ::apache::thrift::protocol::T_STRING, 1); xfer += oprot->writeBinary(this->max); xfer += oprot->writeFieldEnd(); } if (this->__isset.min) { - xfer += oprot->writeFieldBegin("min", ::duckdb_apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeFieldBegin("min", ::apache::thrift::protocol::T_STRING, 2); xfer += oprot->writeBinary(this->min); xfer += oprot->writeFieldEnd(); } if (this->__isset.null_count) { - xfer += oprot->writeFieldBegin("null_count", ::duckdb_apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeFieldBegin("null_count", ::apache::thrift::protocol::T_I64, 3); xfer += oprot->writeI64(this->null_count); xfer += oprot->writeFieldEnd(); } if (this->__isset.distinct_count) { - xfer += oprot->writeFieldBegin("distinct_count", ::duckdb_apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeFieldBegin("distinct_count", ::apache::thrift::protocol::T_I64, 4); xfer += oprot->writeI64(this->distinct_count); xfer += oprot->writeFieldEnd(); } if (this->__isset.max_value) { - xfer += oprot->writeFieldBegin("max_value", ::duckdb_apache::thrift::protocol::T_STRING, 5); + xfer += oprot->writeFieldBegin("max_value", ::apache::thrift::protocol::T_STRING, 5); xfer += oprot->writeBinary(this->max_value); xfer += oprot->writeFieldEnd(); } if (this->__isset.min_value) { - xfer += oprot->writeFieldBegin("min_value", ::duckdb_apache::thrift::protocol::T_STRING, 6); + xfer += oprot->writeFieldBegin("min_value", ::apache::thrift::protocol::T_STRING, 6); xfer += oprot->writeBinary(this->min_value); xfer += oprot->writeFieldEnd(); } + if (this->__isset.is_max_value_exact) { + xfer += oprot->writeFieldBegin("is_max_value_exact", ::apache::thrift::protocol::T_BOOL, 7); + xfer += oprot->writeBool(this->is_max_value_exact); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.is_min_value_exact) { + xfer += oprot->writeFieldBegin("is_min_value_exact", ::apache::thrift::protocol::T_BOOL, 8); + xfer += oprot->writeBool(this->is_min_value_exact); + xfer += oprot->writeFieldEnd(); + } xfer += oprot->writeFieldStop(); xfer += oprot->writeStructEnd(); return xfer; @@ -413,68 +863,58 @@ void swap(Statistics &a, Statistics &b) { swap(a.distinct_count, b.distinct_count); swap(a.max_value, b.max_value); swap(a.min_value, b.min_value); + swap(a.is_max_value_exact, b.is_max_value_exact); + swap(a.is_min_value_exact, b.is_min_value_exact); swap(a.__isset, b.__isset); } -Statistics::Statistics(const Statistics& other0) { - max = other0.max; - min = other0.min; - null_count = other0.null_count; - distinct_count = other0.distinct_count; - max_value = other0.max_value; - min_value = other0.min_value; - __isset = other0.__isset; -} -Statistics& Statistics::operator=(const Statistics& other1) { - max = other1.max; - min = other1.min; - null_count = other1.null_count; - distinct_count = other1.distinct_count; - max_value = other1.max_value; - min_value = other1.min_value; - __isset = other1.__isset; +Statistics::Statistics(const Statistics& other14) { + max = other14.max; + min = other14.min; + null_count = other14.null_count; + distinct_count = other14.distinct_count; + max_value = other14.max_value; + min_value = other14.min_value; + is_max_value_exact = other14.is_max_value_exact; + is_min_value_exact = other14.is_min_value_exact; + __isset = other14.__isset; +} +Statistics& Statistics::operator=(const Statistics& other15) { + max = other15.max; + min = other15.min; + null_count = other15.null_count; + distinct_count = other15.distinct_count; + max_value = other15.max_value; + min_value = other15.min_value; + is_max_value_exact = other15.is_max_value_exact; + is_min_value_exact = other15.is_min_value_exact; + __isset = other15.__isset; return *this; } -void Statistics::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "Statistics("; - out << "max="; (__isset.max ? (out << to_string(max)) : (out << "")); - out << ", " << "min="; (__isset.min ? (out << to_string(min)) : (out << "")); - out << ", " << "null_count="; (__isset.null_count ? (out << to_string(null_count)) : (out << "")); - out << ", " << "distinct_count="; (__isset.distinct_count ? (out << to_string(distinct_count)) : (out << "")); - out << ", " << "max_value="; (__isset.max_value ? (out << to_string(max_value)) : (out << "")); - out << ", " << "min_value="; (__isset.min_value ? (out << to_string(min_value)) : (out << "")); - out << ")"; -} - -StringType::~StringType() throw() { +StringType::~StringType() noexcept { } -std::ostream& operator<<(std::ostream& out, const StringType& obj) -{ - obj.printTo(out); - return out; +StringType::StringType() noexcept { } +uint32_t StringType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t StringType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -486,9 +926,9 @@ uint32_t StringType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t StringType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t StringType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("StringType"); xfer += oprot->writeFieldStop(); @@ -502,47 +942,37 @@ void swap(StringType &a, StringType &b) { (void) b; } -StringType::StringType(const StringType& other2) { - (void) other2; +StringType::StringType(const StringType& other16) noexcept { + (void) other16; } -StringType& StringType::operator=(const StringType& other3) { - (void) other3; +StringType& StringType::operator=(const StringType& other17) noexcept { + (void) other17; return *this; } -void StringType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "StringType("; - out << ")"; -} - -UUIDType::~UUIDType() throw() { +UUIDType::~UUIDType() noexcept { } -std::ostream& operator<<(std::ostream& out, const UUIDType& obj) -{ - obj.printTo(out); - return out; +UUIDType::UUIDType() noexcept { } +uint32_t UUIDType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t UUIDType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -554,9 +984,9 @@ uint32_t UUIDType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t UUIDType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t UUIDType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("UUIDType"); xfer += oprot->writeFieldStop(); @@ -570,47 +1000,37 @@ void swap(UUIDType &a, UUIDType &b) { (void) b; } -UUIDType::UUIDType(const UUIDType& other4) { - (void) other4; +UUIDType::UUIDType(const UUIDType& other18) noexcept { + (void) other18; } -UUIDType& UUIDType::operator=(const UUIDType& other5) { - (void) other5; +UUIDType& UUIDType::operator=(const UUIDType& other19) noexcept { + (void) other19; return *this; } -void UUIDType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "UUIDType("; - out << ")"; -} - -MapType::~MapType() throw() { +MapType::~MapType() noexcept { } -std::ostream& operator<<(std::ostream& out, const MapType& obj) -{ - obj.printTo(out); - return out; +MapType::MapType() noexcept { } +uint32_t MapType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t MapType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -622,9 +1042,9 @@ uint32_t MapType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t MapType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t MapType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("MapType"); xfer += oprot->writeFieldStop(); @@ -638,47 +1058,37 @@ void swap(MapType &a, MapType &b) { (void) b; } -MapType::MapType(const MapType& other6) { - (void) other6; +MapType::MapType(const MapType& other20) noexcept { + (void) other20; } -MapType& MapType::operator=(const MapType& other7) { - (void) other7; +MapType& MapType::operator=(const MapType& other21) noexcept { + (void) other21; return *this; } -void MapType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "MapType("; - out << ")"; -} - -ListType::~ListType() throw() { +ListType::~ListType() noexcept { } -std::ostream& operator<<(std::ostream& out, const ListType& obj) -{ - obj.printTo(out); - return out; +ListType::ListType() noexcept { } +uint32_t ListType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t ListType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -690,9 +1100,9 @@ uint32_t ListType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t ListType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t ListType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("ListType"); xfer += oprot->writeFieldStop(); @@ -706,47 +1116,37 @@ void swap(ListType &a, ListType &b) { (void) b; } -ListType::ListType(const ListType& other8) { - (void) other8; +ListType::ListType(const ListType& other22) noexcept { + (void) other22; } -ListType& ListType::operator=(const ListType& other9) { - (void) other9; +ListType& ListType::operator=(const ListType& other23) noexcept { + (void) other23; return *this; } -void ListType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "ListType("; - out << ")"; -} - -EnumType::~EnumType() throw() { +EnumType::~EnumType() noexcept { } -std::ostream& operator<<(std::ostream& out, const EnumType& obj) -{ - obj.printTo(out); - return out; +EnumType::EnumType() noexcept { } +uint32_t EnumType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t EnumType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -758,9 +1158,9 @@ uint32_t EnumType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t EnumType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t EnumType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("EnumType"); xfer += oprot->writeFieldStop(); @@ -774,47 +1174,37 @@ void swap(EnumType &a, EnumType &b) { (void) b; } -EnumType::EnumType(const EnumType& other10) { - (void) other10; +EnumType::EnumType(const EnumType& other24) noexcept { + (void) other24; } -EnumType& EnumType::operator=(const EnumType& other11) { - (void) other11; +EnumType& EnumType::operator=(const EnumType& other25) noexcept { + (void) other25; return *this; } -void EnumType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "EnumType("; - out << ")"; -} - -DateType::~DateType() throw() { +DateType::~DateType() noexcept { } -std::ostream& operator<<(std::ostream& out, const DateType& obj) -{ - obj.printTo(out); - return out; +DateType::DateType() noexcept { } +uint32_t DateType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t DateType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -826,9 +1216,9 @@ uint32_t DateType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t DateType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t DateType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("DateType"); xfer += oprot->writeFieldStop(); @@ -842,47 +1232,95 @@ void swap(DateType &a, DateType &b) { (void) b; } -DateType::DateType(const DateType& other12) { - (void) other12; +DateType::DateType(const DateType& other26) noexcept { + (void) other26; } -DateType& DateType::operator=(const DateType& other13) { - (void) other13; +DateType& DateType::operator=(const DateType& other27) noexcept { + (void) other27; return *this; } -void DateType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "DateType("; - out << ")"; + +Float16Type::~Float16Type() noexcept { +} + +Float16Type::Float16Type() noexcept { +} + +uint32_t Float16Type::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + xfer += iprot->skip(ftype); + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t Float16Type::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("Float16Type"); + + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; } +void swap(Float16Type &a, Float16Type &b) { + using ::std::swap; + (void) a; + (void) b; +} -NullType::~NullType() throw() { +Float16Type::Float16Type(const Float16Type& other28) noexcept { + (void) other28; +} +Float16Type& Float16Type::operator=(const Float16Type& other29) noexcept { + (void) other29; + return *this; } -std::ostream& operator<<(std::ostream& out, const NullType& obj) -{ - obj.printTo(out); - return out; +NullType::~NullType() noexcept { } +NullType::NullType() noexcept { +} -uint32_t NullType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t NullType::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -894,9 +1332,9 @@ uint32_t NullType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t NullType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t NullType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("NullType"); xfer += oprot->writeFieldStop(); @@ -910,23 +1348,21 @@ void swap(NullType &a, NullType &b) { (void) b; } -NullType::NullType(const NullType& other14) { - (void) other14; +NullType::NullType(const NullType& other30) noexcept { + (void) other30; } -NullType& NullType::operator=(const NullType& other15) { - (void) other15; +NullType& NullType::operator=(const NullType& other31) noexcept { + (void) other31; return *this; } -void NullType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "NullType("; - out << ")"; -} - -DecimalType::~DecimalType() throw() { +DecimalType::~DecimalType() noexcept { } +DecimalType::DecimalType() noexcept + : scale(0), + precision(0) { +} void DecimalType::__set_scale(const int32_t val) { this->scale = val; @@ -935,24 +1371,18 @@ void DecimalType::__set_scale(const int32_t val) { void DecimalType::__set_precision(const int32_t val) { this->precision = val; } -std::ostream& operator<<(std::ostream& out, const DecimalType& obj) -{ - obj.printTo(out); - return out; -} +uint32_t DecimalType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t DecimalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_scale = false; bool isset_precision = false; @@ -960,13 +1390,13 @@ uint32_t DecimalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->scale); isset_scale = true; } else { @@ -974,7 +1404,7 @@ uint32_t DecimalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->precision); isset_precision = true; } else { @@ -997,16 +1427,16 @@ uint32_t DecimalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t DecimalType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t DecimalType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("DecimalType"); - xfer += oprot->writeFieldBegin("scale", ::duckdb_apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeFieldBegin("scale", ::apache::thrift::protocol::T_I32, 1); xfer += oprot->writeI32(this->scale); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("precision", ::duckdb_apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeFieldBegin("precision", ::apache::thrift::protocol::T_I32, 2); xfer += oprot->writeI32(this->precision); xfer += oprot->writeFieldEnd(); @@ -1021,51 +1451,39 @@ void swap(DecimalType &a, DecimalType &b) { swap(a.precision, b.precision); } -DecimalType::DecimalType(const DecimalType& other16) { - scale = other16.scale; - precision = other16.precision; +DecimalType::DecimalType(const DecimalType& other32) noexcept { + scale = other32.scale; + precision = other32.precision; } -DecimalType& DecimalType::operator=(const DecimalType& other17) { - scale = other17.scale; - precision = other17.precision; +DecimalType& DecimalType::operator=(const DecimalType& other33) noexcept { + scale = other33.scale; + precision = other33.precision; return *this; } -void DecimalType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "DecimalType("; - out << "scale=" << to_string(scale); - out << ", " << "precision=" << to_string(precision); - out << ")"; -} - -MilliSeconds::~MilliSeconds() throw() { +MilliSeconds::~MilliSeconds() noexcept { } -std::ostream& operator<<(std::ostream& out, const MilliSeconds& obj) -{ - obj.printTo(out); - return out; +MilliSeconds::MilliSeconds() noexcept { } +uint32_t MilliSeconds::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t MilliSeconds::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -1077,9 +1495,9 @@ uint32_t MilliSeconds::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t MilliSeconds::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t MilliSeconds::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("MilliSeconds"); xfer += oprot->writeFieldStop(); @@ -1093,47 +1511,37 @@ void swap(MilliSeconds &a, MilliSeconds &b) { (void) b; } -MilliSeconds::MilliSeconds(const MilliSeconds& other18) { - (void) other18; +MilliSeconds::MilliSeconds(const MilliSeconds& other34) noexcept { + (void) other34; } -MilliSeconds& MilliSeconds::operator=(const MilliSeconds& other19) { - (void) other19; +MilliSeconds& MilliSeconds::operator=(const MilliSeconds& other35) noexcept { + (void) other35; return *this; } -void MilliSeconds::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "MilliSeconds("; - out << ")"; -} - -MicroSeconds::~MicroSeconds() throw() { +MicroSeconds::~MicroSeconds() noexcept { } -std::ostream& operator<<(std::ostream& out, const MicroSeconds& obj) -{ - obj.printTo(out); - return out; +MicroSeconds::MicroSeconds() noexcept { } +uint32_t MicroSeconds::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t MicroSeconds::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -1145,9 +1553,9 @@ uint32_t MicroSeconds::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t MicroSeconds::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t MicroSeconds::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("MicroSeconds"); xfer += oprot->writeFieldStop(); @@ -1161,47 +1569,37 @@ void swap(MicroSeconds &a, MicroSeconds &b) { (void) b; } -MicroSeconds::MicroSeconds(const MicroSeconds& other20) { - (void) other20; +MicroSeconds::MicroSeconds(const MicroSeconds& other36) noexcept { + (void) other36; } -MicroSeconds& MicroSeconds::operator=(const MicroSeconds& other21) { - (void) other21; +MicroSeconds& MicroSeconds::operator=(const MicroSeconds& other37) noexcept { + (void) other37; return *this; } -void MicroSeconds::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "MicroSeconds("; - out << ")"; -} - -NanoSeconds::~NanoSeconds() throw() { +NanoSeconds::~NanoSeconds() noexcept { } -std::ostream& operator<<(std::ostream& out, const NanoSeconds& obj) -{ - obj.printTo(out); - return out; +NanoSeconds::NanoSeconds() noexcept { } +uint32_t NanoSeconds::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t NanoSeconds::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -1213,9 +1611,9 @@ uint32_t NanoSeconds::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t NanoSeconds::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t NanoSeconds::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("NanoSeconds"); xfer += oprot->writeFieldStop(); @@ -1229,23 +1627,19 @@ void swap(NanoSeconds &a, NanoSeconds &b) { (void) b; } -NanoSeconds::NanoSeconds(const NanoSeconds& other22) { - (void) other22; +NanoSeconds::NanoSeconds(const NanoSeconds& other38) noexcept { + (void) other38; } -NanoSeconds& NanoSeconds::operator=(const NanoSeconds& other23) { - (void) other23; +NanoSeconds& NanoSeconds::operator=(const NanoSeconds& other39) noexcept { + (void) other39; return *this; } -void NanoSeconds::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "NanoSeconds("; - out << ")"; -} - -TimeUnit::~TimeUnit() throw() { +TimeUnit::~TimeUnit() noexcept { } +TimeUnit::TimeUnit() noexcept { +} void TimeUnit::__set_MILLIS(const MilliSeconds& val) { this->MILLIS = val; @@ -1261,36 +1655,30 @@ void TimeUnit::__set_NANOS(const NanoSeconds& val) { this->NANOS = val; __isset.NANOS = true; } -std::ostream& operator<<(std::ostream& out, const TimeUnit& obj) -{ - obj.printTo(out); - return out; -} +uint32_t TimeUnit::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t TimeUnit::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->MILLIS.read(iprot); this->__isset.MILLIS = true; } else { @@ -1298,7 +1686,7 @@ uint32_t TimeUnit::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->MICROS.read(iprot); this->__isset.MICROS = true; } else { @@ -1306,7 +1694,7 @@ uint32_t TimeUnit::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->NANOS.read(iprot); this->__isset.NANOS = true; } else { @@ -1325,23 +1713,23 @@ uint32_t TimeUnit::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t TimeUnit::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t TimeUnit::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("TimeUnit"); if (this->__isset.MILLIS) { - xfer += oprot->writeFieldBegin("MILLIS", ::duckdb_apache::thrift::protocol::T_STRUCT, 1); + xfer += oprot->writeFieldBegin("MILLIS", ::apache::thrift::protocol::T_STRUCT, 1); xfer += this->MILLIS.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.MICROS) { - xfer += oprot->writeFieldBegin("MICROS", ::duckdb_apache::thrift::protocol::T_STRUCT, 2); + xfer += oprot->writeFieldBegin("MICROS", ::apache::thrift::protocol::T_STRUCT, 2); xfer += this->MICROS.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.NANOS) { - xfer += oprot->writeFieldBegin("NANOS", ::duckdb_apache::thrift::protocol::T_STRUCT, 3); + xfer += oprot->writeFieldBegin("NANOS", ::apache::thrift::protocol::T_STRUCT, 3); xfer += this->NANOS.write(oprot); xfer += oprot->writeFieldEnd(); } @@ -1358,32 +1746,26 @@ void swap(TimeUnit &a, TimeUnit &b) { swap(a.__isset, b.__isset); } -TimeUnit::TimeUnit(const TimeUnit& other24) { - MILLIS = other24.MILLIS; - MICROS = other24.MICROS; - NANOS = other24.NANOS; - __isset = other24.__isset; +TimeUnit::TimeUnit(const TimeUnit& other40) noexcept { + MILLIS = other40.MILLIS; + MICROS = other40.MICROS; + NANOS = other40.NANOS; + __isset = other40.__isset; } -TimeUnit& TimeUnit::operator=(const TimeUnit& other25) { - MILLIS = other25.MILLIS; - MICROS = other25.MICROS; - NANOS = other25.NANOS; - __isset = other25.__isset; +TimeUnit& TimeUnit::operator=(const TimeUnit& other41) noexcept { + MILLIS = other41.MILLIS; + MICROS = other41.MICROS; + NANOS = other41.NANOS; + __isset = other41.__isset; return *this; } -void TimeUnit::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "TimeUnit("; - out << "MILLIS="; (__isset.MILLIS ? (out << to_string(MILLIS)) : (out << "")); - out << ", " << "MICROS="; (__isset.MICROS ? (out << to_string(MICROS)) : (out << "")); - out << ", " << "NANOS="; (__isset.NANOS ? (out << to_string(NANOS)) : (out << "")); - out << ")"; -} - -TimestampType::~TimestampType() throw() { +TimestampType::~TimestampType() noexcept { } +TimestampType::TimestampType() noexcept + : isAdjustedToUTC(0) { +} void TimestampType::__set_isAdjustedToUTC(const bool val) { this->isAdjustedToUTC = val; @@ -1392,24 +1774,18 @@ void TimestampType::__set_isAdjustedToUTC(const bool val) { void TimestampType::__set_unit(const TimeUnit& val) { this->unit = val; } -std::ostream& operator<<(std::ostream& out, const TimestampType& obj) -{ - obj.printTo(out); - return out; -} +uint32_t TimestampType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t TimestampType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_isAdjustedToUTC = false; bool isset_unit = false; @@ -1417,13 +1793,13 @@ uint32_t TimestampType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_BOOL) { + if (ftype == ::apache::thrift::protocol::T_BOOL) { xfer += iprot->readBool(this->isAdjustedToUTC); isset_isAdjustedToUTC = true; } else { @@ -1431,7 +1807,7 @@ uint32_t TimestampType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->unit.read(iprot); isset_unit = true; } else { @@ -1454,16 +1830,16 @@ uint32_t TimestampType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot return xfer; } -uint32_t TimestampType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t TimestampType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("TimestampType"); - xfer += oprot->writeFieldBegin("isAdjustedToUTC", ::duckdb_apache::thrift::protocol::T_BOOL, 1); + xfer += oprot->writeFieldBegin("isAdjustedToUTC", ::apache::thrift::protocol::T_BOOL, 1); xfer += oprot->writeBool(this->isAdjustedToUTC); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("unit", ::duckdb_apache::thrift::protocol::T_STRUCT, 2); + xfer += oprot->writeFieldBegin("unit", ::apache::thrift::protocol::T_STRUCT, 2); xfer += this->unit.write(oprot); xfer += oprot->writeFieldEnd(); @@ -1478,27 +1854,22 @@ void swap(TimestampType &a, TimestampType &b) { swap(a.unit, b.unit); } -TimestampType::TimestampType(const TimestampType& other26) { - isAdjustedToUTC = other26.isAdjustedToUTC; - unit = other26.unit; +TimestampType::TimestampType(const TimestampType& other42) noexcept { + isAdjustedToUTC = other42.isAdjustedToUTC; + unit = other42.unit; } -TimestampType& TimestampType::operator=(const TimestampType& other27) { - isAdjustedToUTC = other27.isAdjustedToUTC; - unit = other27.unit; +TimestampType& TimestampType::operator=(const TimestampType& other43) noexcept { + isAdjustedToUTC = other43.isAdjustedToUTC; + unit = other43.unit; return *this; } -void TimestampType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "TimestampType("; - out << "isAdjustedToUTC=" << to_string(isAdjustedToUTC); - out << ", " << "unit=" << to_string(unit); - out << ")"; -} - -TimeType::~TimeType() throw() { +TimeType::~TimeType() noexcept { } +TimeType::TimeType() noexcept + : isAdjustedToUTC(0) { +} void TimeType::__set_isAdjustedToUTC(const bool val) { this->isAdjustedToUTC = val; @@ -1507,24 +1878,18 @@ void TimeType::__set_isAdjustedToUTC(const bool val) { void TimeType::__set_unit(const TimeUnit& val) { this->unit = val; } -std::ostream& operator<<(std::ostream& out, const TimeType& obj) -{ - obj.printTo(out); - return out; -} - -uint32_t TimeType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t TimeType::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_isAdjustedToUTC = false; bool isset_unit = false; @@ -1532,13 +1897,13 @@ uint32_t TimeType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_BOOL) { + if (ftype == ::apache::thrift::protocol::T_BOOL) { xfer += iprot->readBool(this->isAdjustedToUTC); isset_isAdjustedToUTC = true; } else { @@ -1546,7 +1911,7 @@ uint32_t TimeType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->unit.read(iprot); isset_unit = true; } else { @@ -1569,16 +1934,16 @@ uint32_t TimeType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t TimeType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t TimeType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("TimeType"); - xfer += oprot->writeFieldBegin("isAdjustedToUTC", ::duckdb_apache::thrift::protocol::T_BOOL, 1); + xfer += oprot->writeFieldBegin("isAdjustedToUTC", ::apache::thrift::protocol::T_BOOL, 1); xfer += oprot->writeBool(this->isAdjustedToUTC); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("unit", ::duckdb_apache::thrift::protocol::T_STRUCT, 2); + xfer += oprot->writeFieldBegin("unit", ::apache::thrift::protocol::T_STRUCT, 2); xfer += this->unit.write(oprot); xfer += oprot->writeFieldEnd(); @@ -1593,27 +1958,23 @@ void swap(TimeType &a, TimeType &b) { swap(a.unit, b.unit); } -TimeType::TimeType(const TimeType& other28) { - isAdjustedToUTC = other28.isAdjustedToUTC; - unit = other28.unit; +TimeType::TimeType(const TimeType& other44) noexcept { + isAdjustedToUTC = other44.isAdjustedToUTC; + unit = other44.unit; } -TimeType& TimeType::operator=(const TimeType& other29) { - isAdjustedToUTC = other29.isAdjustedToUTC; - unit = other29.unit; +TimeType& TimeType::operator=(const TimeType& other45) noexcept { + isAdjustedToUTC = other45.isAdjustedToUTC; + unit = other45.unit; return *this; } -void TimeType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "TimeType("; - out << "isAdjustedToUTC=" << to_string(isAdjustedToUTC); - out << ", " << "unit=" << to_string(unit); - out << ")"; -} - -IntType::~IntType() throw() { +IntType::~IntType() noexcept { } +IntType::IntType() noexcept + : bitWidth(0), + isSigned(0) { +} void IntType::__set_bitWidth(const int8_t val) { this->bitWidth = val; @@ -1622,24 +1983,18 @@ void IntType::__set_bitWidth(const int8_t val) { void IntType::__set_isSigned(const bool val) { this->isSigned = val; } -std::ostream& operator<<(std::ostream& out, const IntType& obj) -{ - obj.printTo(out); - return out; -} +uint32_t IntType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t IntType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_bitWidth = false; bool isset_isSigned = false; @@ -1647,13 +2002,13 @@ uint32_t IntType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_BYTE) { + if (ftype == ::apache::thrift::protocol::T_BYTE) { xfer += iprot->readByte(this->bitWidth); isset_bitWidth = true; } else { @@ -1661,7 +2016,7 @@ uint32_t IntType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_BOOL) { + if (ftype == ::apache::thrift::protocol::T_BOOL) { xfer += iprot->readBool(this->isSigned); isset_isSigned = true; } else { @@ -1684,16 +2039,16 @@ uint32_t IntType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t IntType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t IntType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("IntType"); - xfer += oprot->writeFieldBegin("bitWidth", ::duckdb_apache::thrift::protocol::T_BYTE, 1); + xfer += oprot->writeFieldBegin("bitWidth", ::apache::thrift::protocol::T_BYTE, 1); xfer += oprot->writeByte(this->bitWidth); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("isSigned", ::duckdb_apache::thrift::protocol::T_BOOL, 2); + xfer += oprot->writeFieldBegin("isSigned", ::apache::thrift::protocol::T_BOOL, 2); xfer += oprot->writeBool(this->isSigned); xfer += oprot->writeFieldEnd(); @@ -1708,51 +2063,39 @@ void swap(IntType &a, IntType &b) { swap(a.isSigned, b.isSigned); } -IntType::IntType(const IntType& other30) { - bitWidth = other30.bitWidth; - isSigned = other30.isSigned; +IntType::IntType(const IntType& other46) noexcept { + bitWidth = other46.bitWidth; + isSigned = other46.isSigned; } -IntType& IntType::operator=(const IntType& other31) { - bitWidth = other31.bitWidth; - isSigned = other31.isSigned; +IntType& IntType::operator=(const IntType& other47) noexcept { + bitWidth = other47.bitWidth; + isSigned = other47.isSigned; return *this; } -void IntType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "IntType("; - out << "bitWidth=" << to_string(bitWidth); - out << ", " << "isSigned=" << to_string(isSigned); - out << ")"; -} - -JsonType::~JsonType() throw() { +JsonType::~JsonType() noexcept { } -std::ostream& operator<<(std::ostream& out, const JsonType& obj) -{ - obj.printTo(out); - return out; +JsonType::JsonType() noexcept { } +uint32_t JsonType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t JsonType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -1764,9 +2107,9 @@ uint32_t JsonType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t JsonType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t JsonType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("JsonType"); xfer += oprot->writeFieldStop(); @@ -1780,47 +2123,37 @@ void swap(JsonType &a, JsonType &b) { (void) b; } -JsonType::JsonType(const JsonType& other32) { - (void) other32; +JsonType::JsonType(const JsonType& other48) noexcept { + (void) other48; } -JsonType& JsonType::operator=(const JsonType& other33) { - (void) other33; +JsonType& JsonType::operator=(const JsonType& other49) noexcept { + (void) other49; return *this; } -void JsonType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "JsonType("; - out << ")"; -} - -BsonType::~BsonType() throw() { +BsonType::~BsonType() noexcept { } -std::ostream& operator<<(std::ostream& out, const BsonType& obj) -{ - obj.printTo(out); - return out; +BsonType::BsonType() noexcept { } +uint32_t BsonType::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t BsonType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -1832,9 +2165,9 @@ uint32_t BsonType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t BsonType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t BsonType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("BsonType"); xfer += oprot->writeFieldStop(); @@ -1848,23 +2181,19 @@ void swap(BsonType &a, BsonType &b) { (void) b; } -BsonType::BsonType(const BsonType& other34) { - (void) other34; +BsonType::BsonType(const BsonType& other50) noexcept { + (void) other50; } -BsonType& BsonType::operator=(const BsonType& other35) { - (void) other35; +BsonType& BsonType::operator=(const BsonType& other51) noexcept { + (void) other51; return *this; } -void BsonType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "BsonType("; - out << ")"; -} - -LogicalType::~LogicalType() throw() { +LogicalType::~LogicalType() noexcept { } +LogicalType::LogicalType() noexcept { +} void LogicalType::__set_STRING(const StringType& val) { this->STRING = val; @@ -1930,36 +2259,35 @@ void LogicalType::__set_UUID(const UUIDType& val) { this->UUID = val; __isset.UUID = true; } -std::ostream& operator<<(std::ostream& out, const LogicalType& obj) -{ - obj.printTo(out); - return out; -} +void LogicalType::__set_FLOAT16(const Float16Type& val) { + this->FLOAT16 = val; +__isset.FLOAT16 = true; +} -uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t LogicalType::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->STRING.read(iprot); this->__isset.STRING = true; } else { @@ -1967,7 +2295,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->MAP.read(iprot); this->__isset.MAP = true; } else { @@ -1975,7 +2303,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->LIST.read(iprot); this->__isset.LIST = true; } else { @@ -1983,7 +2311,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->ENUM.read(iprot); this->__isset.ENUM = true; } else { @@ -1991,7 +2319,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->DECIMAL.read(iprot); this->__isset.DECIMAL = true; } else { @@ -1999,7 +2327,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 6: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->DATE.read(iprot); this->__isset.DATE = true; } else { @@ -2007,7 +2335,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 7: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->TIME.read(iprot); this->__isset.TIME = true; } else { @@ -2015,7 +2343,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 8: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->TIMESTAMP.read(iprot); this->__isset.TIMESTAMP = true; } else { @@ -2023,7 +2351,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 10: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->INTEGER.read(iprot); this->__isset.INTEGER = true; } else { @@ -2031,7 +2359,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 11: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->UNKNOWN.read(iprot); this->__isset.UNKNOWN = true; } else { @@ -2039,7 +2367,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 12: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->JSON.read(iprot); this->__isset.JSON = true; } else { @@ -2047,7 +2375,7 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 13: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->BSON.read(iprot); this->__isset.BSON = true; } else { @@ -2055,13 +2383,21 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 14: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->UUID.read(iprot); this->__isset.UUID = true; } else { xfer += iprot->skip(ftype); } break; + case 15: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->FLOAT16.read(iprot); + this->__isset.FLOAT16 = true; + } else { + xfer += iprot->skip(ftype); + } + break; default: xfer += iprot->skip(ftype); break; @@ -2074,76 +2410,81 @@ uint32_t LogicalType::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t LogicalType::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t LogicalType::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("LogicalType"); if (this->__isset.STRING) { - xfer += oprot->writeFieldBegin("STRING", ::duckdb_apache::thrift::protocol::T_STRUCT, 1); + xfer += oprot->writeFieldBegin("STRING", ::apache::thrift::protocol::T_STRUCT, 1); xfer += this->STRING.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.MAP) { - xfer += oprot->writeFieldBegin("MAP", ::duckdb_apache::thrift::protocol::T_STRUCT, 2); + xfer += oprot->writeFieldBegin("MAP", ::apache::thrift::protocol::T_STRUCT, 2); xfer += this->MAP.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.LIST) { - xfer += oprot->writeFieldBegin("LIST", ::duckdb_apache::thrift::protocol::T_STRUCT, 3); + xfer += oprot->writeFieldBegin("LIST", ::apache::thrift::protocol::T_STRUCT, 3); xfer += this->LIST.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.ENUM) { - xfer += oprot->writeFieldBegin("ENUM", ::duckdb_apache::thrift::protocol::T_STRUCT, 4); + xfer += oprot->writeFieldBegin("ENUM", ::apache::thrift::protocol::T_STRUCT, 4); xfer += this->ENUM.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.DECIMAL) { - xfer += oprot->writeFieldBegin("DECIMAL", ::duckdb_apache::thrift::protocol::T_STRUCT, 5); + xfer += oprot->writeFieldBegin("DECIMAL", ::apache::thrift::protocol::T_STRUCT, 5); xfer += this->DECIMAL.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.DATE) { - xfer += oprot->writeFieldBegin("DATE", ::duckdb_apache::thrift::protocol::T_STRUCT, 6); + xfer += oprot->writeFieldBegin("DATE", ::apache::thrift::protocol::T_STRUCT, 6); xfer += this->DATE.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.TIME) { - xfer += oprot->writeFieldBegin("TIME", ::duckdb_apache::thrift::protocol::T_STRUCT, 7); + xfer += oprot->writeFieldBegin("TIME", ::apache::thrift::protocol::T_STRUCT, 7); xfer += this->TIME.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.TIMESTAMP) { - xfer += oprot->writeFieldBegin("TIMESTAMP", ::duckdb_apache::thrift::protocol::T_STRUCT, 8); + xfer += oprot->writeFieldBegin("TIMESTAMP", ::apache::thrift::protocol::T_STRUCT, 8); xfer += this->TIMESTAMP.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.INTEGER) { - xfer += oprot->writeFieldBegin("INTEGER", ::duckdb_apache::thrift::protocol::T_STRUCT, 10); + xfer += oprot->writeFieldBegin("INTEGER", ::apache::thrift::protocol::T_STRUCT, 10); xfer += this->INTEGER.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.UNKNOWN) { - xfer += oprot->writeFieldBegin("UNKNOWN", ::duckdb_apache::thrift::protocol::T_STRUCT, 11); + xfer += oprot->writeFieldBegin("UNKNOWN", ::apache::thrift::protocol::T_STRUCT, 11); xfer += this->UNKNOWN.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.JSON) { - xfer += oprot->writeFieldBegin("JSON", ::duckdb_apache::thrift::protocol::T_STRUCT, 12); + xfer += oprot->writeFieldBegin("JSON", ::apache::thrift::protocol::T_STRUCT, 12); xfer += this->JSON.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.BSON) { - xfer += oprot->writeFieldBegin("BSON", ::duckdb_apache::thrift::protocol::T_STRUCT, 13); + xfer += oprot->writeFieldBegin("BSON", ::apache::thrift::protocol::T_STRUCT, 13); xfer += this->BSON.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.UUID) { - xfer += oprot->writeFieldBegin("UUID", ::duckdb_apache::thrift::protocol::T_STRUCT, 14); + xfer += oprot->writeFieldBegin("UUID", ::apache::thrift::protocol::T_STRUCT, 14); xfer += this->UUID.write(oprot); xfer += oprot->writeFieldEnd(); } + if (this->__isset.FLOAT16) { + xfer += oprot->writeFieldBegin("FLOAT16", ::apache::thrift::protocol::T_STRUCT, 15); + xfer += this->FLOAT16.write(oprot); + xfer += oprot->writeFieldEnd(); + } xfer += oprot->writeFieldStop(); xfer += oprot->writeStructEnd(); return xfer; @@ -2164,65 +2505,60 @@ void swap(LogicalType &a, LogicalType &b) { swap(a.JSON, b.JSON); swap(a.BSON, b.BSON); swap(a.UUID, b.UUID); + swap(a.FLOAT16, b.FLOAT16); swap(a.__isset, b.__isset); } -LogicalType::LogicalType(const LogicalType& other36) { - STRING = other36.STRING; - MAP = other36.MAP; - LIST = other36.LIST; - ENUM = other36.ENUM; - DECIMAL = other36.DECIMAL; - DATE = other36.DATE; - TIME = other36.TIME; - TIMESTAMP = other36.TIMESTAMP; - INTEGER = other36.INTEGER; - UNKNOWN = other36.UNKNOWN; - JSON = other36.JSON; - BSON = other36.BSON; - UUID = other36.UUID; - __isset = other36.__isset; -} -LogicalType& LogicalType::operator=(const LogicalType& other37) { - STRING = other37.STRING; - MAP = other37.MAP; - LIST = other37.LIST; - ENUM = other37.ENUM; - DECIMAL = other37.DECIMAL; - DATE = other37.DATE; - TIME = other37.TIME; - TIMESTAMP = other37.TIMESTAMP; - INTEGER = other37.INTEGER; - UNKNOWN = other37.UNKNOWN; - JSON = other37.JSON; - BSON = other37.BSON; - UUID = other37.UUID; - __isset = other37.__isset; - return *this; +LogicalType::LogicalType(const LogicalType& other52) noexcept { + STRING = other52.STRING; + MAP = other52.MAP; + LIST = other52.LIST; + ENUM = other52.ENUM; + DECIMAL = other52.DECIMAL; + DATE = other52.DATE; + TIME = other52.TIME; + TIMESTAMP = other52.TIMESTAMP; + INTEGER = other52.INTEGER; + UNKNOWN = other52.UNKNOWN; + JSON = other52.JSON; + BSON = other52.BSON; + UUID = other52.UUID; + FLOAT16 = other52.FLOAT16; + __isset = other52.__isset; } -void LogicalType::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "LogicalType("; - out << "STRING="; (__isset.STRING ? (out << to_string(STRING)) : (out << "")); - out << ", " << "MAP="; (__isset.MAP ? (out << to_string(MAP)) : (out << "")); - out << ", " << "LIST="; (__isset.LIST ? (out << to_string(LIST)) : (out << "")); - out << ", " << "ENUM="; (__isset.ENUM ? (out << to_string(ENUM)) : (out << "")); - out << ", " << "DECIMAL="; (__isset.DECIMAL ? (out << to_string(DECIMAL)) : (out << "")); - out << ", " << "DATE="; (__isset.DATE ? (out << to_string(DATE)) : (out << "")); - out << ", " << "TIME="; (__isset.TIME ? (out << to_string(TIME)) : (out << "")); - out << ", " << "TIMESTAMP="; (__isset.TIMESTAMP ? (out << to_string(TIMESTAMP)) : (out << "")); - out << ", " << "INTEGER="; (__isset.INTEGER ? (out << to_string(INTEGER)) : (out << "")); - out << ", " << "UNKNOWN="; (__isset.UNKNOWN ? (out << to_string(UNKNOWN)) : (out << "")); - out << ", " << "JSON="; (__isset.JSON ? (out << to_string(JSON)) : (out << "")); - out << ", " << "BSON="; (__isset.BSON ? (out << to_string(BSON)) : (out << "")); - out << ", " << "UUID="; (__isset.UUID ? (out << to_string(UUID)) : (out << "")); - out << ")"; +LogicalType& LogicalType::operator=(const LogicalType& other53) noexcept { + STRING = other53.STRING; + MAP = other53.MAP; + LIST = other53.LIST; + ENUM = other53.ENUM; + DECIMAL = other53.DECIMAL; + DATE = other53.DATE; + TIME = other53.TIME; + TIMESTAMP = other53.TIMESTAMP; + INTEGER = other53.INTEGER; + UNKNOWN = other53.UNKNOWN; + JSON = other53.JSON; + BSON = other53.BSON; + UUID = other53.UUID; + FLOAT16 = other53.FLOAT16; + __isset = other53.__isset; + return *this; } - -SchemaElement::~SchemaElement() throw() { +SchemaElement::~SchemaElement() noexcept { } +SchemaElement::SchemaElement() noexcept + : type(static_cast(0)), + type_length(0), + repetition_type(static_cast(0)), + name(), + num_children(0), + converted_type(static_cast(0)), + scale(0), + precision(0), + field_id(0) { +} void SchemaElement::__set_type(const Type::type val) { this->type = val; @@ -2272,47 +2608,41 @@ void SchemaElement::__set_logicalType(const LogicalType& val) { this->logicalType = val; __isset.logicalType = true; } -std::ostream& operator<<(std::ostream& out, const SchemaElement& obj) -{ - obj.printTo(out); - return out; -} +uint32_t SchemaElement::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t SchemaElement::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_name = false; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast38; - xfer += iprot->readI32(ecast38); - this->type = (Type::type)ecast38; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast54; + xfer += iprot->readI32(ecast54); + this->type = static_cast(ecast54); this->__isset.type = true; } else { xfer += iprot->skip(ftype); } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->type_length); this->__isset.type_length = true; } else { @@ -2320,17 +2650,17 @@ uint32_t SchemaElement::read(::duckdb_apache::thrift::protocol::TProtocol* iprot } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast39; - xfer += iprot->readI32(ecast39); - this->repetition_type = (FieldRepetitionType::type)ecast39; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast55; + xfer += iprot->readI32(ecast55); + this->repetition_type = static_cast(ecast55); this->__isset.repetition_type = true; } else { xfer += iprot->skip(ftype); } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readString(this->name); isset_name = true; } else { @@ -2338,7 +2668,7 @@ uint32_t SchemaElement::read(::duckdb_apache::thrift::protocol::TProtocol* iprot } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->num_children); this->__isset.num_children = true; } else { @@ -2346,17 +2676,17 @@ uint32_t SchemaElement::read(::duckdb_apache::thrift::protocol::TProtocol* iprot } break; case 6: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast40; - xfer += iprot->readI32(ecast40); - this->converted_type = (ConvertedType::type)ecast40; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast56; + xfer += iprot->readI32(ecast56); + this->converted_type = static_cast(ecast56); this->__isset.converted_type = true; } else { xfer += iprot->skip(ftype); } break; case 7: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->scale); this->__isset.scale = true; } else { @@ -2364,7 +2694,7 @@ uint32_t SchemaElement::read(::duckdb_apache::thrift::protocol::TProtocol* iprot } break; case 8: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->precision); this->__isset.precision = true; } else { @@ -2372,7 +2702,7 @@ uint32_t SchemaElement::read(::duckdb_apache::thrift::protocol::TProtocol* iprot } break; case 9: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->field_id); this->__isset.field_id = true; } else { @@ -2380,7 +2710,7 @@ uint32_t SchemaElement::read(::duckdb_apache::thrift::protocol::TProtocol* iprot } break; case 10: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->logicalType.read(iprot); this->__isset.logicalType = true; } else { @@ -2401,57 +2731,57 @@ uint32_t SchemaElement::read(::duckdb_apache::thrift::protocol::TProtocol* iprot return xfer; } -uint32_t SchemaElement::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t SchemaElement::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("SchemaElement"); if (this->__isset.type) { - xfer += oprot->writeFieldBegin("type", ::duckdb_apache::thrift::protocol::T_I32, 1); - xfer += oprot->writeI32((int32_t)this->type); + xfer += oprot->writeFieldBegin("type", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(static_cast(this->type)); xfer += oprot->writeFieldEnd(); } if (this->__isset.type_length) { - xfer += oprot->writeFieldBegin("type_length", ::duckdb_apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeFieldBegin("type_length", ::apache::thrift::protocol::T_I32, 2); xfer += oprot->writeI32(this->type_length); xfer += oprot->writeFieldEnd(); } if (this->__isset.repetition_type) { - xfer += oprot->writeFieldBegin("repetition_type", ::duckdb_apache::thrift::protocol::T_I32, 3); - xfer += oprot->writeI32((int32_t)this->repetition_type); + xfer += oprot->writeFieldBegin("repetition_type", ::apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeI32(static_cast(this->repetition_type)); xfer += oprot->writeFieldEnd(); } - xfer += oprot->writeFieldBegin("name", ::duckdb_apache::thrift::protocol::T_STRING, 4); + xfer += oprot->writeFieldBegin("name", ::apache::thrift::protocol::T_STRING, 4); xfer += oprot->writeString(this->name); xfer += oprot->writeFieldEnd(); if (this->__isset.num_children) { - xfer += oprot->writeFieldBegin("num_children", ::duckdb_apache::thrift::protocol::T_I32, 5); + xfer += oprot->writeFieldBegin("num_children", ::apache::thrift::protocol::T_I32, 5); xfer += oprot->writeI32(this->num_children); xfer += oprot->writeFieldEnd(); } if (this->__isset.converted_type) { - xfer += oprot->writeFieldBegin("converted_type", ::duckdb_apache::thrift::protocol::T_I32, 6); - xfer += oprot->writeI32((int32_t)this->converted_type); + xfer += oprot->writeFieldBegin("converted_type", ::apache::thrift::protocol::T_I32, 6); + xfer += oprot->writeI32(static_cast(this->converted_type)); xfer += oprot->writeFieldEnd(); } if (this->__isset.scale) { - xfer += oprot->writeFieldBegin("scale", ::duckdb_apache::thrift::protocol::T_I32, 7); + xfer += oprot->writeFieldBegin("scale", ::apache::thrift::protocol::T_I32, 7); xfer += oprot->writeI32(this->scale); xfer += oprot->writeFieldEnd(); } if (this->__isset.precision) { - xfer += oprot->writeFieldBegin("precision", ::duckdb_apache::thrift::protocol::T_I32, 8); + xfer += oprot->writeFieldBegin("precision", ::apache::thrift::protocol::T_I32, 8); xfer += oprot->writeI32(this->precision); xfer += oprot->writeFieldEnd(); } if (this->__isset.field_id) { - xfer += oprot->writeFieldBegin("field_id", ::duckdb_apache::thrift::protocol::T_I32, 9); + xfer += oprot->writeFieldBegin("field_id", ::apache::thrift::protocol::T_I32, 9); xfer += oprot->writeI32(this->field_id); xfer += oprot->writeFieldEnd(); } if (this->__isset.logicalType) { - xfer += oprot->writeFieldBegin("logicalType", ::duckdb_apache::thrift::protocol::T_STRUCT, 10); + xfer += oprot->writeFieldBegin("logicalType", ::apache::thrift::protocol::T_STRUCT, 10); xfer += this->logicalType.write(oprot); xfer += oprot->writeFieldEnd(); } @@ -2475,53 +2805,43 @@ void swap(SchemaElement &a, SchemaElement &b) { swap(a.__isset, b.__isset); } -SchemaElement::SchemaElement(const SchemaElement& other41) { - type = other41.type; - type_length = other41.type_length; - repetition_type = other41.repetition_type; - name = other41.name; - num_children = other41.num_children; - converted_type = other41.converted_type; - scale = other41.scale; - precision = other41.precision; - field_id = other41.field_id; - logicalType = other41.logicalType; - __isset = other41.__isset; +SchemaElement::SchemaElement(const SchemaElement& other57) { + type = other57.type; + type_length = other57.type_length; + repetition_type = other57.repetition_type; + name = other57.name; + num_children = other57.num_children; + converted_type = other57.converted_type; + scale = other57.scale; + precision = other57.precision; + field_id = other57.field_id; + logicalType = other57.logicalType; + __isset = other57.__isset; } -SchemaElement& SchemaElement::operator=(const SchemaElement& other42) { - type = other42.type; - type_length = other42.type_length; - repetition_type = other42.repetition_type; - name = other42.name; - num_children = other42.num_children; - converted_type = other42.converted_type; - scale = other42.scale; - precision = other42.precision; - field_id = other42.field_id; - logicalType = other42.logicalType; - __isset = other42.__isset; +SchemaElement& SchemaElement::operator=(const SchemaElement& other58) { + type = other58.type; + type_length = other58.type_length; + repetition_type = other58.repetition_type; + name = other58.name; + num_children = other58.num_children; + converted_type = other58.converted_type; + scale = other58.scale; + precision = other58.precision; + field_id = other58.field_id; + logicalType = other58.logicalType; + __isset = other58.__isset; return *this; } -void SchemaElement::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "SchemaElement("; - out << "type="; (__isset.type ? (out << to_string(type)) : (out << "")); - out << ", " << "type_length="; (__isset.type_length ? (out << to_string(type_length)) : (out << "")); - out << ", " << "repetition_type="; (__isset.repetition_type ? (out << to_string(repetition_type)) : (out << "")); - out << ", " << "name=" << to_string(name); - out << ", " << "num_children="; (__isset.num_children ? (out << to_string(num_children)) : (out << "")); - out << ", " << "converted_type="; (__isset.converted_type ? (out << to_string(converted_type)) : (out << "")); - out << ", " << "scale="; (__isset.scale ? (out << to_string(scale)) : (out << "")); - out << ", " << "precision="; (__isset.precision ? (out << to_string(precision)) : (out << "")); - out << ", " << "field_id="; (__isset.field_id ? (out << to_string(field_id)) : (out << "")); - out << ", " << "logicalType="; (__isset.logicalType ? (out << to_string(logicalType)) : (out << "")); - out << ")"; -} - -DataPageHeader::~DataPageHeader() throw() { +DataPageHeader::~DataPageHeader() noexcept { } +DataPageHeader::DataPageHeader() noexcept + : num_values(0), + encoding(static_cast(0)), + definition_level_encoding(static_cast(0)), + repetition_level_encoding(static_cast(0)) { +} void DataPageHeader::__set_num_values(const int32_t val) { this->num_values = val; @@ -2543,24 +2863,18 @@ void DataPageHeader::__set_statistics(const Statistics& val) { this->statistics = val; __isset.statistics = true; } -std::ostream& operator<<(std::ostream& out, const DataPageHeader& obj) -{ - obj.printTo(out); - return out; -} +uint32_t DataPageHeader::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t DataPageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_num_values = false; bool isset_encoding = false; @@ -2570,13 +2884,13 @@ uint32_t DataPageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* ipro while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->num_values); isset_num_values = true; } else { @@ -2584,37 +2898,37 @@ uint32_t DataPageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast43; - xfer += iprot->readI32(ecast43); - this->encoding = (Encoding::type)ecast43; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast59; + xfer += iprot->readI32(ecast59); + this->encoding = static_cast(ecast59); isset_encoding = true; } else { xfer += iprot->skip(ftype); } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast44; - xfer += iprot->readI32(ecast44); - this->definition_level_encoding = (Encoding::type)ecast44; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast60; + xfer += iprot->readI32(ecast60); + this->definition_level_encoding = static_cast(ecast60); isset_definition_level_encoding = true; } else { xfer += iprot->skip(ftype); } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast45; - xfer += iprot->readI32(ecast45); - this->repetition_level_encoding = (Encoding::type)ecast45; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast61; + xfer += iprot->readI32(ecast61); + this->repetition_level_encoding = static_cast(ecast61); isset_repetition_level_encoding = true; } else { xfer += iprot->skip(ftype); } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->statistics.read(iprot); this->__isset.statistics = true; } else { @@ -2641,29 +2955,29 @@ uint32_t DataPageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* ipro return xfer; } -uint32_t DataPageHeader::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t DataPageHeader::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("DataPageHeader"); - xfer += oprot->writeFieldBegin("num_values", ::duckdb_apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeFieldBegin("num_values", ::apache::thrift::protocol::T_I32, 1); xfer += oprot->writeI32(this->num_values); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("encoding", ::duckdb_apache::thrift::protocol::T_I32, 2); - xfer += oprot->writeI32((int32_t)this->encoding); + xfer += oprot->writeFieldBegin("encoding", ::apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeI32(static_cast(this->encoding)); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("definition_level_encoding", ::duckdb_apache::thrift::protocol::T_I32, 3); - xfer += oprot->writeI32((int32_t)this->definition_level_encoding); + xfer += oprot->writeFieldBegin("definition_level_encoding", ::apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeI32(static_cast(this->definition_level_encoding)); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("repetition_level_encoding", ::duckdb_apache::thrift::protocol::T_I32, 4); - xfer += oprot->writeI32((int32_t)this->repetition_level_encoding); + xfer += oprot->writeFieldBegin("repetition_level_encoding", ::apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(static_cast(this->repetition_level_encoding)); xfer += oprot->writeFieldEnd(); if (this->__isset.statistics) { - xfer += oprot->writeFieldBegin("statistics", ::duckdb_apache::thrift::protocol::T_STRUCT, 5); + xfer += oprot->writeFieldBegin("statistics", ::apache::thrift::protocol::T_STRUCT, 5); xfer += this->statistics.write(oprot); xfer += oprot->writeFieldEnd(); } @@ -2682,62 +2996,47 @@ void swap(DataPageHeader &a, DataPageHeader &b) { swap(a.__isset, b.__isset); } -DataPageHeader::DataPageHeader(const DataPageHeader& other46) { - num_values = other46.num_values; - encoding = other46.encoding; - definition_level_encoding = other46.definition_level_encoding; - repetition_level_encoding = other46.repetition_level_encoding; - statistics = other46.statistics; - __isset = other46.__isset; -} -DataPageHeader& DataPageHeader::operator=(const DataPageHeader& other47) { - num_values = other47.num_values; - encoding = other47.encoding; - definition_level_encoding = other47.definition_level_encoding; - repetition_level_encoding = other47.repetition_level_encoding; - statistics = other47.statistics; - __isset = other47.__isset; +DataPageHeader::DataPageHeader(const DataPageHeader& other62) { + num_values = other62.num_values; + encoding = other62.encoding; + definition_level_encoding = other62.definition_level_encoding; + repetition_level_encoding = other62.repetition_level_encoding; + statistics = other62.statistics; + __isset = other62.__isset; +} +DataPageHeader& DataPageHeader::operator=(const DataPageHeader& other63) { + num_values = other63.num_values; + encoding = other63.encoding; + definition_level_encoding = other63.definition_level_encoding; + repetition_level_encoding = other63.repetition_level_encoding; + statistics = other63.statistics; + __isset = other63.__isset; return *this; } -void DataPageHeader::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "DataPageHeader("; - out << "num_values=" << to_string(num_values); - out << ", " << "encoding=" << to_string(encoding); - out << ", " << "definition_level_encoding=" << to_string(definition_level_encoding); - out << ", " << "repetition_level_encoding=" << to_string(repetition_level_encoding); - out << ", " << "statistics="; (__isset.statistics ? (out << to_string(statistics)) : (out << "")); - out << ")"; -} - -IndexPageHeader::~IndexPageHeader() throw() { +IndexPageHeader::~IndexPageHeader() noexcept { } -std::ostream& operator<<(std::ostream& out, const IndexPageHeader& obj) -{ - obj.printTo(out); - return out; +IndexPageHeader::IndexPageHeader() noexcept { } +uint32_t IndexPageHeader::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t IndexPageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -2749,9 +3048,9 @@ uint32_t IndexPageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* ipr return xfer; } -uint32_t IndexPageHeader::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t IndexPageHeader::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("IndexPageHeader"); xfer += oprot->writeFieldStop(); @@ -2765,23 +3064,22 @@ void swap(IndexPageHeader &a, IndexPageHeader &b) { (void) b; } -IndexPageHeader::IndexPageHeader(const IndexPageHeader& other48) { - (void) other48; +IndexPageHeader::IndexPageHeader(const IndexPageHeader& other64) noexcept { + (void) other64; } -IndexPageHeader& IndexPageHeader::operator=(const IndexPageHeader& other49) { - (void) other49; +IndexPageHeader& IndexPageHeader::operator=(const IndexPageHeader& other65) noexcept { + (void) other65; return *this; } -void IndexPageHeader::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "IndexPageHeader("; - out << ")"; -} - -DictionaryPageHeader::~DictionaryPageHeader() throw() { +DictionaryPageHeader::~DictionaryPageHeader() noexcept { } +DictionaryPageHeader::DictionaryPageHeader() noexcept + : num_values(0), + encoding(static_cast(0)), + is_sorted(0) { +} void DictionaryPageHeader::__set_num_values(const int32_t val) { this->num_values = val; @@ -2795,24 +3093,18 @@ void DictionaryPageHeader::__set_is_sorted(const bool val) { this->is_sorted = val; __isset.is_sorted = true; } -std::ostream& operator<<(std::ostream& out, const DictionaryPageHeader& obj) -{ - obj.printTo(out); - return out; -} +uint32_t DictionaryPageHeader::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t DictionaryPageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_num_values = false; bool isset_encoding = false; @@ -2820,13 +3112,13 @@ uint32_t DictionaryPageHeader::read(::duckdb_apache::thrift::protocol::TProtocol while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->num_values); isset_num_values = true; } else { @@ -2834,17 +3126,17 @@ uint32_t DictionaryPageHeader::read(::duckdb_apache::thrift::protocol::TProtocol } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast50; - xfer += iprot->readI32(ecast50); - this->encoding = (Encoding::type)ecast50; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast66; + xfer += iprot->readI32(ecast66); + this->encoding = static_cast(ecast66); isset_encoding = true; } else { xfer += iprot->skip(ftype); } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_BOOL) { + if (ftype == ::apache::thrift::protocol::T_BOOL) { xfer += iprot->readBool(this->is_sorted); this->__isset.is_sorted = true; } else { @@ -2867,21 +3159,21 @@ uint32_t DictionaryPageHeader::read(::duckdb_apache::thrift::protocol::TProtocol return xfer; } -uint32_t DictionaryPageHeader::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t DictionaryPageHeader::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("DictionaryPageHeader"); - xfer += oprot->writeFieldBegin("num_values", ::duckdb_apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeFieldBegin("num_values", ::apache::thrift::protocol::T_I32, 1); xfer += oprot->writeI32(this->num_values); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("encoding", ::duckdb_apache::thrift::protocol::T_I32, 2); - xfer += oprot->writeI32((int32_t)this->encoding); + xfer += oprot->writeFieldBegin("encoding", ::apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeI32(static_cast(this->encoding)); xfer += oprot->writeFieldEnd(); if (this->__isset.is_sorted) { - xfer += oprot->writeFieldBegin("is_sorted", ::duckdb_apache::thrift::protocol::T_BOOL, 3); + xfer += oprot->writeFieldBegin("is_sorted", ::apache::thrift::protocol::T_BOOL, 3); xfer += oprot->writeBool(this->is_sorted); xfer += oprot->writeFieldEnd(); } @@ -2898,32 +3190,32 @@ void swap(DictionaryPageHeader &a, DictionaryPageHeader &b) { swap(a.__isset, b.__isset); } -DictionaryPageHeader::DictionaryPageHeader(const DictionaryPageHeader& other51) { - num_values = other51.num_values; - encoding = other51.encoding; - is_sorted = other51.is_sorted; - __isset = other51.__isset; +DictionaryPageHeader::DictionaryPageHeader(const DictionaryPageHeader& other67) noexcept { + num_values = other67.num_values; + encoding = other67.encoding; + is_sorted = other67.is_sorted; + __isset = other67.__isset; } -DictionaryPageHeader& DictionaryPageHeader::operator=(const DictionaryPageHeader& other52) { - num_values = other52.num_values; - encoding = other52.encoding; - is_sorted = other52.is_sorted; - __isset = other52.__isset; +DictionaryPageHeader& DictionaryPageHeader::operator=(const DictionaryPageHeader& other68) noexcept { + num_values = other68.num_values; + encoding = other68.encoding; + is_sorted = other68.is_sorted; + __isset = other68.__isset; return *this; } -void DictionaryPageHeader::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "DictionaryPageHeader("; - out << "num_values=" << to_string(num_values); - out << ", " << "encoding=" << to_string(encoding); - out << ", " << "is_sorted="; (__isset.is_sorted ? (out << to_string(is_sorted)) : (out << "")); - out << ")"; -} - -DataPageHeaderV2::~DataPageHeaderV2() throw() { +DataPageHeaderV2::~DataPageHeaderV2() noexcept { } +DataPageHeaderV2::DataPageHeaderV2() noexcept + : num_values(0), + num_nulls(0), + num_rows(0), + encoding(static_cast(0)), + definition_levels_byte_length(0), + repetition_levels_byte_length(0), + is_compressed(true) { +} void DataPageHeaderV2::__set_num_values(const int32_t val) { this->num_values = val; @@ -2958,24 +3250,18 @@ void DataPageHeaderV2::__set_statistics(const Statistics& val) { this->statistics = val; __isset.statistics = true; } -std::ostream& operator<<(std::ostream& out, const DataPageHeaderV2& obj) -{ - obj.printTo(out); - return out; -} - -uint32_t DataPageHeaderV2::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t DataPageHeaderV2::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_num_values = false; bool isset_num_nulls = false; @@ -2987,13 +3273,13 @@ uint32_t DataPageHeaderV2::read(::duckdb_apache::thrift::protocol::TProtocol* ip while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->num_values); isset_num_values = true; } else { @@ -3001,7 +3287,7 @@ uint32_t DataPageHeaderV2::read(::duckdb_apache::thrift::protocol::TProtocol* ip } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->num_nulls); isset_num_nulls = true; } else { @@ -3009,7 +3295,7 @@ uint32_t DataPageHeaderV2::read(::duckdb_apache::thrift::protocol::TProtocol* ip } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->num_rows); isset_num_rows = true; } else { @@ -3017,43 +3303,651 @@ uint32_t DataPageHeaderV2::read(::duckdb_apache::thrift::protocol::TProtocol* ip } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast53; - xfer += iprot->readI32(ecast53); - this->encoding = (Encoding::type)ecast53; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast69; + xfer += iprot->readI32(ecast69); + this->encoding = static_cast(ecast69); isset_encoding = true; } else { xfer += iprot->skip(ftype); } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->definition_levels_byte_length); isset_definition_levels_byte_length = true; } else { xfer += iprot->skip(ftype); } break; - case 6: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - xfer += iprot->readI32(this->repetition_levels_byte_length); - isset_repetition_levels_byte_length = true; + case 6: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->repetition_levels_byte_length); + isset_repetition_levels_byte_length = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == ::apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->is_compressed); + this->__isset.is_compressed = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 8: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->statistics.read(iprot); + this->__isset.statistics = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_num_values) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_num_nulls) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_num_rows) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_encoding) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_definition_levels_byte_length) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_repetition_levels_byte_length) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t DataPageHeaderV2::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("DataPageHeaderV2"); + + xfer += oprot->writeFieldBegin("num_values", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(this->num_values); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("num_nulls", ::apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeI32(this->num_nulls); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("num_rows", ::apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeI32(this->num_rows); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("encoding", ::apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(static_cast(this->encoding)); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("definition_levels_byte_length", ::apache::thrift::protocol::T_I32, 5); + xfer += oprot->writeI32(this->definition_levels_byte_length); + xfer += oprot->writeFieldEnd(); + + xfer += oprot->writeFieldBegin("repetition_levels_byte_length", ::apache::thrift::protocol::T_I32, 6); + xfer += oprot->writeI32(this->repetition_levels_byte_length); + xfer += oprot->writeFieldEnd(); + + if (this->__isset.is_compressed) { + xfer += oprot->writeFieldBegin("is_compressed", ::apache::thrift::protocol::T_BOOL, 7); + xfer += oprot->writeBool(this->is_compressed); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.statistics) { + xfer += oprot->writeFieldBegin("statistics", ::apache::thrift::protocol::T_STRUCT, 8); + xfer += this->statistics.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(DataPageHeaderV2 &a, DataPageHeaderV2 &b) { + using ::std::swap; + swap(a.num_values, b.num_values); + swap(a.num_nulls, b.num_nulls); + swap(a.num_rows, b.num_rows); + swap(a.encoding, b.encoding); + swap(a.definition_levels_byte_length, b.definition_levels_byte_length); + swap(a.repetition_levels_byte_length, b.repetition_levels_byte_length); + swap(a.is_compressed, b.is_compressed); + swap(a.statistics, b.statistics); + swap(a.__isset, b.__isset); +} + +DataPageHeaderV2::DataPageHeaderV2(const DataPageHeaderV2& other70) { + num_values = other70.num_values; + num_nulls = other70.num_nulls; + num_rows = other70.num_rows; + encoding = other70.encoding; + definition_levels_byte_length = other70.definition_levels_byte_length; + repetition_levels_byte_length = other70.repetition_levels_byte_length; + is_compressed = other70.is_compressed; + statistics = other70.statistics; + __isset = other70.__isset; +} +DataPageHeaderV2& DataPageHeaderV2::operator=(const DataPageHeaderV2& other71) { + num_values = other71.num_values; + num_nulls = other71.num_nulls; + num_rows = other71.num_rows; + encoding = other71.encoding; + definition_levels_byte_length = other71.definition_levels_byte_length; + repetition_levels_byte_length = other71.repetition_levels_byte_length; + is_compressed = other71.is_compressed; + statistics = other71.statistics; + __isset = other71.__isset; + return *this; +} + +SplitBlockAlgorithm::~SplitBlockAlgorithm() noexcept { +} + +SplitBlockAlgorithm::SplitBlockAlgorithm() noexcept { +} + +uint32_t SplitBlockAlgorithm::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + xfer += iprot->skip(ftype); + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t SplitBlockAlgorithm::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("SplitBlockAlgorithm"); + + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(SplitBlockAlgorithm &a, SplitBlockAlgorithm &b) { + using ::std::swap; + (void) a; + (void) b; +} + +SplitBlockAlgorithm::SplitBlockAlgorithm(const SplitBlockAlgorithm& other72) noexcept { + (void) other72; +} +SplitBlockAlgorithm& SplitBlockAlgorithm::operator=(const SplitBlockAlgorithm& other73) noexcept { + (void) other73; + return *this; +} + +BloomFilterAlgorithm::~BloomFilterAlgorithm() noexcept { +} + +BloomFilterAlgorithm::BloomFilterAlgorithm() noexcept { +} + +void BloomFilterAlgorithm::__set_BLOCK(const SplitBlockAlgorithm& val) { + this->BLOCK = val; +__isset.BLOCK = true; +} + +uint32_t BloomFilterAlgorithm::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->BLOCK.read(iprot); + this->__isset.BLOCK = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t BloomFilterAlgorithm::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("BloomFilterAlgorithm"); + + if (this->__isset.BLOCK) { + xfer += oprot->writeFieldBegin("BLOCK", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += this->BLOCK.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(BloomFilterAlgorithm &a, BloomFilterAlgorithm &b) { + using ::std::swap; + swap(a.BLOCK, b.BLOCK); + swap(a.__isset, b.__isset); +} + +BloomFilterAlgorithm::BloomFilterAlgorithm(const BloomFilterAlgorithm& other74) noexcept { + BLOCK = other74.BLOCK; + __isset = other74.__isset; +} +BloomFilterAlgorithm& BloomFilterAlgorithm::operator=(const BloomFilterAlgorithm& other75) noexcept { + BLOCK = other75.BLOCK; + __isset = other75.__isset; + return *this; +} + +XxHash::~XxHash() noexcept { +} + +XxHash::XxHash() noexcept { +} + +uint32_t XxHash::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + xfer += iprot->skip(ftype); + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t XxHash::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("XxHash"); + + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(XxHash &a, XxHash &b) { + using ::std::swap; + (void) a; + (void) b; +} + +XxHash::XxHash(const XxHash& other76) noexcept { + (void) other76; +} +XxHash& XxHash::operator=(const XxHash& other77) noexcept { + (void) other77; + return *this; +} + +BloomFilterHash::~BloomFilterHash() noexcept { +} + +BloomFilterHash::BloomFilterHash() noexcept { +} + +void BloomFilterHash::__set_XXHASH(const XxHash& val) { + this->XXHASH = val; +__isset.XXHASH = true; +} + +uint32_t BloomFilterHash::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->XXHASH.read(iprot); + this->__isset.XXHASH = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t BloomFilterHash::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("BloomFilterHash"); + + if (this->__isset.XXHASH) { + xfer += oprot->writeFieldBegin("XXHASH", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += this->XXHASH.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(BloomFilterHash &a, BloomFilterHash &b) { + using ::std::swap; + swap(a.XXHASH, b.XXHASH); + swap(a.__isset, b.__isset); +} + +BloomFilterHash::BloomFilterHash(const BloomFilterHash& other78) noexcept { + XXHASH = other78.XXHASH; + __isset = other78.__isset; +} +BloomFilterHash& BloomFilterHash::operator=(const BloomFilterHash& other79) noexcept { + XXHASH = other79.XXHASH; + __isset = other79.__isset; + return *this; +} + +Uncompressed::~Uncompressed() noexcept { +} + +Uncompressed::Uncompressed() noexcept { +} + +uint32_t Uncompressed::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + xfer += iprot->skip(ftype); + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t Uncompressed::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("Uncompressed"); + + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(Uncompressed &a, Uncompressed &b) { + using ::std::swap; + (void) a; + (void) b; +} + +Uncompressed::Uncompressed(const Uncompressed& other80) noexcept { + (void) other80; +} +Uncompressed& Uncompressed::operator=(const Uncompressed& other81) noexcept { + (void) other81; + return *this; +} + +BloomFilterCompression::~BloomFilterCompression() noexcept { +} + +BloomFilterCompression::BloomFilterCompression() noexcept { +} + +void BloomFilterCompression::__set_UNCOMPRESSED(const Uncompressed& val) { + this->UNCOMPRESSED = val; +__isset.UNCOMPRESSED = true; +} + +uint32_t BloomFilterCompression::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->UNCOMPRESSED.read(iprot); + this->__isset.UNCOMPRESSED = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t BloomFilterCompression::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("BloomFilterCompression"); + + if (this->__isset.UNCOMPRESSED) { + xfer += oprot->writeFieldBegin("UNCOMPRESSED", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += this->UNCOMPRESSED.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +void swap(BloomFilterCompression &a, BloomFilterCompression &b) { + using ::std::swap; + swap(a.UNCOMPRESSED, b.UNCOMPRESSED); + swap(a.__isset, b.__isset); +} + +BloomFilterCompression::BloomFilterCompression(const BloomFilterCompression& other82) noexcept { + UNCOMPRESSED = other82.UNCOMPRESSED; + __isset = other82.__isset; +} +BloomFilterCompression& BloomFilterCompression::operator=(const BloomFilterCompression& other83) noexcept { + UNCOMPRESSED = other83.UNCOMPRESSED; + __isset = other83.__isset; + return *this; +} + +BloomFilterHeader::~BloomFilterHeader() noexcept { +} + +BloomFilterHeader::BloomFilterHeader() noexcept + : numBytes(0) { +} + +void BloomFilterHeader::__set_numBytes(const int32_t val) { + this->numBytes = val; +} + +void BloomFilterHeader::__set_algorithm(const BloomFilterAlgorithm& val) { + this->algorithm = val; +} + +void BloomFilterHeader::__set_hash(const BloomFilterHash& val) { + this->hash = val; +} + +void BloomFilterHeader::__set_compression(const BloomFilterCompression& val) { + this->compression = val; +} + +uint32_t BloomFilterHeader::read(::apache::thrift::protocol::TProtocol* iprot) { + + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_numBytes = false; + bool isset_algorithm = false; + bool isset_hash = false; + bool isset_compression = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->numBytes); + isset_numBytes = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->algorithm.read(iprot); + isset_algorithm = true; } else { xfer += iprot->skip(ftype); } break; - case 7: - if (ftype == ::duckdb_apache::thrift::protocol::T_BOOL) { - xfer += iprot->readBool(this->is_compressed); - this->__isset.is_compressed = true; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->hash.read(iprot); + isset_hash = true; } else { xfer += iprot->skip(ftype); } break; - case 8: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { - xfer += this->statistics.read(iprot); - this->__isset.statistics = true; + case 4: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->compression.read(iprot); + isset_compression = true; } else { xfer += iprot->skip(ftype); } @@ -3067,119 +3961,74 @@ uint32_t DataPageHeaderV2::read(::duckdb_apache::thrift::protocol::TProtocol* ip xfer += iprot->readStructEnd(); - if (!isset_num_values) - throw TProtocolException(TProtocolException::INVALID_DATA); - if (!isset_num_nulls) - throw TProtocolException(TProtocolException::INVALID_DATA); - if (!isset_num_rows) + if (!isset_numBytes) throw TProtocolException(TProtocolException::INVALID_DATA); - if (!isset_encoding) + if (!isset_algorithm) throw TProtocolException(TProtocolException::INVALID_DATA); - if (!isset_definition_levels_byte_length) + if (!isset_hash) throw TProtocolException(TProtocolException::INVALID_DATA); - if (!isset_repetition_levels_byte_length) + if (!isset_compression) throw TProtocolException(TProtocolException::INVALID_DATA); return xfer; } -uint32_t DataPageHeaderV2::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t BloomFilterHeader::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); - xfer += oprot->writeStructBegin("DataPageHeaderV2"); - - xfer += oprot->writeFieldBegin("num_values", ::duckdb_apache::thrift::protocol::T_I32, 1); - xfer += oprot->writeI32(this->num_values); - xfer += oprot->writeFieldEnd(); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + xfer += oprot->writeStructBegin("BloomFilterHeader"); - xfer += oprot->writeFieldBegin("num_nulls", ::duckdb_apache::thrift::protocol::T_I32, 2); - xfer += oprot->writeI32(this->num_nulls); - xfer += oprot->writeFieldEnd(); - - xfer += oprot->writeFieldBegin("num_rows", ::duckdb_apache::thrift::protocol::T_I32, 3); - xfer += oprot->writeI32(this->num_rows); + xfer += oprot->writeFieldBegin("numBytes", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(this->numBytes); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("encoding", ::duckdb_apache::thrift::protocol::T_I32, 4); - xfer += oprot->writeI32((int32_t)this->encoding); + xfer += oprot->writeFieldBegin("algorithm", ::apache::thrift::protocol::T_STRUCT, 2); + xfer += this->algorithm.write(oprot); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("definition_levels_byte_length", ::duckdb_apache::thrift::protocol::T_I32, 5); - xfer += oprot->writeI32(this->definition_levels_byte_length); + xfer += oprot->writeFieldBegin("hash", ::apache::thrift::protocol::T_STRUCT, 3); + xfer += this->hash.write(oprot); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("repetition_levels_byte_length", ::duckdb_apache::thrift::protocol::T_I32, 6); - xfer += oprot->writeI32(this->repetition_levels_byte_length); + xfer += oprot->writeFieldBegin("compression", ::apache::thrift::protocol::T_STRUCT, 4); + xfer += this->compression.write(oprot); xfer += oprot->writeFieldEnd(); - if (this->__isset.is_compressed) { - xfer += oprot->writeFieldBegin("is_compressed", ::duckdb_apache::thrift::protocol::T_BOOL, 7); - xfer += oprot->writeBool(this->is_compressed); - xfer += oprot->writeFieldEnd(); - } - if (this->__isset.statistics) { - xfer += oprot->writeFieldBegin("statistics", ::duckdb_apache::thrift::protocol::T_STRUCT, 8); - xfer += this->statistics.write(oprot); - xfer += oprot->writeFieldEnd(); - } xfer += oprot->writeFieldStop(); xfer += oprot->writeStructEnd(); return xfer; } -void swap(DataPageHeaderV2 &a, DataPageHeaderV2 &b) { +void swap(BloomFilterHeader &a, BloomFilterHeader &b) { using ::std::swap; - swap(a.num_values, b.num_values); - swap(a.num_nulls, b.num_nulls); - swap(a.num_rows, b.num_rows); - swap(a.encoding, b.encoding); - swap(a.definition_levels_byte_length, b.definition_levels_byte_length); - swap(a.repetition_levels_byte_length, b.repetition_levels_byte_length); - swap(a.is_compressed, b.is_compressed); - swap(a.statistics, b.statistics); - swap(a.__isset, b.__isset); -} - -DataPageHeaderV2::DataPageHeaderV2(const DataPageHeaderV2& other54) { - num_values = other54.num_values; - num_nulls = other54.num_nulls; - num_rows = other54.num_rows; - encoding = other54.encoding; - definition_levels_byte_length = other54.definition_levels_byte_length; - repetition_levels_byte_length = other54.repetition_levels_byte_length; - is_compressed = other54.is_compressed; - statistics = other54.statistics; - __isset = other54.__isset; -} -DataPageHeaderV2& DataPageHeaderV2::operator=(const DataPageHeaderV2& other55) { - num_values = other55.num_values; - num_nulls = other55.num_nulls; - num_rows = other55.num_rows; - encoding = other55.encoding; - definition_levels_byte_length = other55.definition_levels_byte_length; - repetition_levels_byte_length = other55.repetition_levels_byte_length; - is_compressed = other55.is_compressed; - statistics = other55.statistics; - __isset = other55.__isset; + swap(a.numBytes, b.numBytes); + swap(a.algorithm, b.algorithm); + swap(a.hash, b.hash); + swap(a.compression, b.compression); +} + +BloomFilterHeader::BloomFilterHeader(const BloomFilterHeader& other84) noexcept { + numBytes = other84.numBytes; + algorithm = other84.algorithm; + hash = other84.hash; + compression = other84.compression; +} +BloomFilterHeader& BloomFilterHeader::operator=(const BloomFilterHeader& other85) noexcept { + numBytes = other85.numBytes; + algorithm = other85.algorithm; + hash = other85.hash; + compression = other85.compression; return *this; } -void DataPageHeaderV2::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "DataPageHeaderV2("; - out << "num_values=" << to_string(num_values); - out << ", " << "num_nulls=" << to_string(num_nulls); - out << ", " << "num_rows=" << to_string(num_rows); - out << ", " << "encoding=" << to_string(encoding); - out << ", " << "definition_levels_byte_length=" << to_string(definition_levels_byte_length); - out << ", " << "repetition_levels_byte_length=" << to_string(repetition_levels_byte_length); - out << ", " << "is_compressed="; (__isset.is_compressed ? (out << to_string(is_compressed)) : (out << "")); - out << ", " << "statistics="; (__isset.statistics ? (out << to_string(statistics)) : (out << "")); - out << ")"; -} - -PageHeader::~PageHeader() throw() { +PageHeader::~PageHeader() noexcept { } +PageHeader::PageHeader() noexcept + : type(static_cast(0)), + uncompressed_page_size(0), + compressed_page_size(0), + crc(0) { +} void PageHeader::__set_type(const PageType::type val) { this->type = val; @@ -3217,24 +4066,18 @@ void PageHeader::__set_data_page_header_v2(const DataPageHeaderV2& val) { this->data_page_header_v2 = val; __isset.data_page_header_v2 = true; } -std::ostream& operator<<(std::ostream& out, const PageHeader& obj) -{ - obj.printTo(out); - return out; -} +uint32_t PageHeader::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t PageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_type = false; bool isset_uncompressed_page_size = false; @@ -3243,23 +4086,23 @@ uint32_t PageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast56; - xfer += iprot->readI32(ecast56); - this->type = (PageType::type)ecast56; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast86; + xfer += iprot->readI32(ecast86); + this->type = static_cast(ecast86); isset_type = true; } else { xfer += iprot->skip(ftype); } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->uncompressed_page_size); isset_uncompressed_page_size = true; } else { @@ -3267,7 +4110,7 @@ uint32_t PageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->compressed_page_size); isset_compressed_page_size = true; } else { @@ -3275,7 +4118,7 @@ uint32_t PageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->crc); this->__isset.crc = true; } else { @@ -3283,7 +4126,7 @@ uint32_t PageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->data_page_header.read(iprot); this->__isset.data_page_header = true; } else { @@ -3291,7 +4134,7 @@ uint32_t PageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 6: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->index_page_header.read(iprot); this->__isset.index_page_header = true; } else { @@ -3299,7 +4142,7 @@ uint32_t PageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 7: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->dictionary_page_header.read(iprot); this->__isset.dictionary_page_header = true; } else { @@ -3307,7 +4150,7 @@ uint32_t PageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 8: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->data_page_header_v2.read(iprot); this->__isset.data_page_header_v2 = true; } else { @@ -3332,45 +4175,45 @@ uint32_t PageHeader::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t PageHeader::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t PageHeader::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("PageHeader"); - xfer += oprot->writeFieldBegin("type", ::duckdb_apache::thrift::protocol::T_I32, 1); - xfer += oprot->writeI32((int32_t)this->type); + xfer += oprot->writeFieldBegin("type", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(static_cast(this->type)); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("uncompressed_page_size", ::duckdb_apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeFieldBegin("uncompressed_page_size", ::apache::thrift::protocol::T_I32, 2); xfer += oprot->writeI32(this->uncompressed_page_size); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("compressed_page_size", ::duckdb_apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeFieldBegin("compressed_page_size", ::apache::thrift::protocol::T_I32, 3); xfer += oprot->writeI32(this->compressed_page_size); xfer += oprot->writeFieldEnd(); if (this->__isset.crc) { - xfer += oprot->writeFieldBegin("crc", ::duckdb_apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeFieldBegin("crc", ::apache::thrift::protocol::T_I32, 4); xfer += oprot->writeI32(this->crc); xfer += oprot->writeFieldEnd(); } if (this->__isset.data_page_header) { - xfer += oprot->writeFieldBegin("data_page_header", ::duckdb_apache::thrift::protocol::T_STRUCT, 5); + xfer += oprot->writeFieldBegin("data_page_header", ::apache::thrift::protocol::T_STRUCT, 5); xfer += this->data_page_header.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.index_page_header) { - xfer += oprot->writeFieldBegin("index_page_header", ::duckdb_apache::thrift::protocol::T_STRUCT, 6); + xfer += oprot->writeFieldBegin("index_page_header", ::apache::thrift::protocol::T_STRUCT, 6); xfer += this->index_page_header.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.dictionary_page_header) { - xfer += oprot->writeFieldBegin("dictionary_page_header", ::duckdb_apache::thrift::protocol::T_STRUCT, 7); + xfer += oprot->writeFieldBegin("dictionary_page_header", ::apache::thrift::protocol::T_STRUCT, 7); xfer += this->dictionary_page_header.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.data_page_header_v2) { - xfer += oprot->writeFieldBegin("data_page_header_v2", ::duckdb_apache::thrift::protocol::T_STRUCT, 8); + xfer += oprot->writeFieldBegin("data_page_header_v2", ::apache::thrift::protocol::T_STRUCT, 8); xfer += this->data_page_header_v2.write(oprot); xfer += oprot->writeFieldEnd(); } @@ -3392,47 +4235,37 @@ void swap(PageHeader &a, PageHeader &b) { swap(a.__isset, b.__isset); } -PageHeader::PageHeader(const PageHeader& other57) { - type = other57.type; - uncompressed_page_size = other57.uncompressed_page_size; - compressed_page_size = other57.compressed_page_size; - crc = other57.crc; - data_page_header = other57.data_page_header; - index_page_header = other57.index_page_header; - dictionary_page_header = other57.dictionary_page_header; - data_page_header_v2 = other57.data_page_header_v2; - __isset = other57.__isset; -} -PageHeader& PageHeader::operator=(const PageHeader& other58) { - type = other58.type; - uncompressed_page_size = other58.uncompressed_page_size; - compressed_page_size = other58.compressed_page_size; - crc = other58.crc; - data_page_header = other58.data_page_header; - index_page_header = other58.index_page_header; - dictionary_page_header = other58.dictionary_page_header; - data_page_header_v2 = other58.data_page_header_v2; - __isset = other58.__isset; +PageHeader::PageHeader(const PageHeader& other87) { + type = other87.type; + uncompressed_page_size = other87.uncompressed_page_size; + compressed_page_size = other87.compressed_page_size; + crc = other87.crc; + data_page_header = other87.data_page_header; + index_page_header = other87.index_page_header; + dictionary_page_header = other87.dictionary_page_header; + data_page_header_v2 = other87.data_page_header_v2; + __isset = other87.__isset; +} +PageHeader& PageHeader::operator=(const PageHeader& other88) { + type = other88.type; + uncompressed_page_size = other88.uncompressed_page_size; + compressed_page_size = other88.compressed_page_size; + crc = other88.crc; + data_page_header = other88.data_page_header; + index_page_header = other88.index_page_header; + dictionary_page_header = other88.dictionary_page_header; + data_page_header_v2 = other88.data_page_header_v2; + __isset = other88.__isset; return *this; } -void PageHeader::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "PageHeader("; - out << "type=" << to_string(type); - out << ", " << "uncompressed_page_size=" << to_string(uncompressed_page_size); - out << ", " << "compressed_page_size=" << to_string(compressed_page_size); - out << ", " << "crc="; (__isset.crc ? (out << to_string(crc)) : (out << "")); - out << ", " << "data_page_header="; (__isset.data_page_header ? (out << to_string(data_page_header)) : (out << "")); - out << ", " << "index_page_header="; (__isset.index_page_header ? (out << to_string(index_page_header)) : (out << "")); - out << ", " << "dictionary_page_header="; (__isset.dictionary_page_header ? (out << to_string(dictionary_page_header)) : (out << "")); - out << ", " << "data_page_header_v2="; (__isset.data_page_header_v2 ? (out << to_string(data_page_header_v2)) : (out << "")); - out << ")"; -} - -KeyValue::~KeyValue() throw() { +KeyValue::~KeyValue() noexcept { } +KeyValue::KeyValue() noexcept + : key(), + value() { +} void KeyValue::__set_key(const std::string& val) { this->key = val; @@ -3442,37 +4275,31 @@ void KeyValue::__set_value(const std::string& val) { this->value = val; __isset.value = true; } -std::ostream& operator<<(std::ostream& out, const KeyValue& obj) -{ - obj.printTo(out); - return out; -} +uint32_t KeyValue::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t KeyValue::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_key = false; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readString(this->key); isset_key = true; } else { @@ -3480,7 +4307,7 @@ uint32_t KeyValue::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readString(this->value); this->__isset.value = true; } else { @@ -3501,17 +4328,17 @@ uint32_t KeyValue::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t KeyValue::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t KeyValue::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("KeyValue"); - xfer += oprot->writeFieldBegin("key", ::duckdb_apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeFieldBegin("key", ::apache::thrift::protocol::T_STRING, 1); xfer += oprot->writeString(this->key); xfer += oprot->writeFieldEnd(); if (this->__isset.value) { - xfer += oprot->writeFieldBegin("value", ::duckdb_apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeFieldBegin("value", ::apache::thrift::protocol::T_STRING, 2); xfer += oprot->writeString(this->value); xfer += oprot->writeFieldEnd(); } @@ -3527,29 +4354,26 @@ void swap(KeyValue &a, KeyValue &b) { swap(a.__isset, b.__isset); } -KeyValue::KeyValue(const KeyValue& other59) { - key = other59.key; - value = other59.value; - __isset = other59.__isset; +KeyValue::KeyValue(const KeyValue& other89) { + key = other89.key; + value = other89.value; + __isset = other89.__isset; } -KeyValue& KeyValue::operator=(const KeyValue& other60) { - key = other60.key; - value = other60.value; - __isset = other60.__isset; +KeyValue& KeyValue::operator=(const KeyValue& other90) { + key = other90.key; + value = other90.value; + __isset = other90.__isset; return *this; } -void KeyValue::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "KeyValue("; - out << "key=" << to_string(key); - out << ", " << "value="; (__isset.value ? (out << to_string(value)) : (out << "")); - out << ")"; -} - -SortingColumn::~SortingColumn() throw() { +SortingColumn::~SortingColumn() noexcept { } +SortingColumn::SortingColumn() noexcept + : column_idx(0), + descending(0), + nulls_first(0) { +} void SortingColumn::__set_column_idx(const int32_t val) { this->column_idx = val; @@ -3562,24 +4386,18 @@ void SortingColumn::__set_descending(const bool val) { void SortingColumn::__set_nulls_first(const bool val) { this->nulls_first = val; } -std::ostream& operator<<(std::ostream& out, const SortingColumn& obj) -{ - obj.printTo(out); - return out; -} - -uint32_t SortingColumn::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t SortingColumn::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_column_idx = false; bool isset_descending = false; @@ -3588,13 +4406,13 @@ uint32_t SortingColumn::read(::duckdb_apache::thrift::protocol::TProtocol* iprot while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->column_idx); isset_column_idx = true; } else { @@ -3602,7 +4420,7 @@ uint32_t SortingColumn::read(::duckdb_apache::thrift::protocol::TProtocol* iprot } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_BOOL) { + if (ftype == ::apache::thrift::protocol::T_BOOL) { xfer += iprot->readBool(this->descending); isset_descending = true; } else { @@ -3610,7 +4428,7 @@ uint32_t SortingColumn::read(::duckdb_apache::thrift::protocol::TProtocol* iprot } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_BOOL) { + if (ftype == ::apache::thrift::protocol::T_BOOL) { xfer += iprot->readBool(this->nulls_first); isset_nulls_first = true; } else { @@ -3635,20 +4453,20 @@ uint32_t SortingColumn::read(::duckdb_apache::thrift::protocol::TProtocol* iprot return xfer; } -uint32_t SortingColumn::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t SortingColumn::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("SortingColumn"); - xfer += oprot->writeFieldBegin("column_idx", ::duckdb_apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeFieldBegin("column_idx", ::apache::thrift::protocol::T_I32, 1); xfer += oprot->writeI32(this->column_idx); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("descending", ::duckdb_apache::thrift::protocol::T_BOOL, 2); + xfer += oprot->writeFieldBegin("descending", ::apache::thrift::protocol::T_BOOL, 2); xfer += oprot->writeBool(this->descending); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("nulls_first", ::duckdb_apache::thrift::protocol::T_BOOL, 3); + xfer += oprot->writeFieldBegin("nulls_first", ::apache::thrift::protocol::T_BOOL, 3); xfer += oprot->writeBool(this->nulls_first); xfer += oprot->writeFieldEnd(); @@ -3664,30 +4482,26 @@ void swap(SortingColumn &a, SortingColumn &b) { swap(a.nulls_first, b.nulls_first); } -SortingColumn::SortingColumn(const SortingColumn& other61) { - column_idx = other61.column_idx; - descending = other61.descending; - nulls_first = other61.nulls_first; +SortingColumn::SortingColumn(const SortingColumn& other91) noexcept { + column_idx = other91.column_idx; + descending = other91.descending; + nulls_first = other91.nulls_first; } -SortingColumn& SortingColumn::operator=(const SortingColumn& other62) { - column_idx = other62.column_idx; - descending = other62.descending; - nulls_first = other62.nulls_first; +SortingColumn& SortingColumn::operator=(const SortingColumn& other92) noexcept { + column_idx = other92.column_idx; + descending = other92.descending; + nulls_first = other92.nulls_first; return *this; } -void SortingColumn::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "SortingColumn("; - out << "column_idx=" << to_string(column_idx); - out << ", " << "descending=" << to_string(descending); - out << ", " << "nulls_first=" << to_string(nulls_first); - out << ")"; -} - -PageEncodingStats::~PageEncodingStats() throw() { +PageEncodingStats::~PageEncodingStats() noexcept { } +PageEncodingStats::PageEncodingStats() noexcept + : page_type(static_cast(0)), + encoding(static_cast(0)), + count(0) { +} void PageEncodingStats::__set_page_type(const PageType::type val) { this->page_type = val; @@ -3700,24 +4514,18 @@ void PageEncodingStats::__set_encoding(const Encoding::type val) { void PageEncodingStats::__set_count(const int32_t val) { this->count = val; } -std::ostream& operator<<(std::ostream& out, const PageEncodingStats& obj) -{ - obj.printTo(out); - return out; -} +uint32_t PageEncodingStats::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t PageEncodingStats::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_page_type = false; bool isset_encoding = false; @@ -3726,33 +4534,33 @@ uint32_t PageEncodingStats::read(::duckdb_apache::thrift::protocol::TProtocol* i while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast63; - xfer += iprot->readI32(ecast63); - this->page_type = (PageType::type)ecast63; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast93; + xfer += iprot->readI32(ecast93); + this->page_type = static_cast(ecast93); isset_page_type = true; } else { xfer += iprot->skip(ftype); } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast64; - xfer += iprot->readI32(ecast64); - this->encoding = (Encoding::type)ecast64; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast94; + xfer += iprot->readI32(ecast94); + this->encoding = static_cast(ecast94); isset_encoding = true; } else { xfer += iprot->skip(ftype); } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->count); isset_count = true; } else { @@ -3777,20 +4585,20 @@ uint32_t PageEncodingStats::read(::duckdb_apache::thrift::protocol::TProtocol* i return xfer; } -uint32_t PageEncodingStats::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t PageEncodingStats::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("PageEncodingStats"); - xfer += oprot->writeFieldBegin("page_type", ::duckdb_apache::thrift::protocol::T_I32, 1); - xfer += oprot->writeI32((int32_t)this->page_type); + xfer += oprot->writeFieldBegin("page_type", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(static_cast(this->page_type)); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("encoding", ::duckdb_apache::thrift::protocol::T_I32, 2); - xfer += oprot->writeI32((int32_t)this->encoding); + xfer += oprot->writeFieldBegin("encoding", ::apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeI32(static_cast(this->encoding)); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("count", ::duckdb_apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeFieldBegin("count", ::apache::thrift::protocol::T_I32, 3); xfer += oprot->writeI32(this->count); xfer += oprot->writeFieldEnd(); @@ -3806,40 +4614,43 @@ void swap(PageEncodingStats &a, PageEncodingStats &b) { swap(a.count, b.count); } -PageEncodingStats::PageEncodingStats(const PageEncodingStats& other65) { - page_type = other65.page_type; - encoding = other65.encoding; - count = other65.count; +PageEncodingStats::PageEncodingStats(const PageEncodingStats& other95) noexcept { + page_type = other95.page_type; + encoding = other95.encoding; + count = other95.count; } -PageEncodingStats& PageEncodingStats::operator=(const PageEncodingStats& other66) { - page_type = other66.page_type; - encoding = other66.encoding; - count = other66.count; +PageEncodingStats& PageEncodingStats::operator=(const PageEncodingStats& other96) noexcept { + page_type = other96.page_type; + encoding = other96.encoding; + count = other96.count; return *this; } -void PageEncodingStats::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "PageEncodingStats("; - out << "page_type=" << to_string(page_type); - out << ", " << "encoding=" << to_string(encoding); - out << ", " << "count=" << to_string(count); - out << ")"; -} - -ColumnMetaData::~ColumnMetaData() throw() { +ColumnMetaData::~ColumnMetaData() noexcept { } +ColumnMetaData::ColumnMetaData() noexcept + : type(static_cast(0)), + codec(static_cast(0)), + num_values(0), + total_uncompressed_size(0), + total_compressed_size(0), + data_page_offset(0), + index_page_offset(0), + dictionary_page_offset(0), + bloom_filter_offset(0), + bloom_filter_length(0) { +} void ColumnMetaData::__set_type(const Type::type val) { this->type = val; } -void ColumnMetaData::__set_encodings(const duckdb::vector & val) { +void ColumnMetaData::__set_encodings(const std::vector & val) { this->encodings = val; } -void ColumnMetaData::__set_path_in_schema(const duckdb::vector & val) { +void ColumnMetaData::__set_path_in_schema(const std::vector & val) { this->path_in_schema = val; } @@ -3859,7 +4670,7 @@ void ColumnMetaData::__set_total_compressed_size(const int64_t val) { this->total_compressed_size = val; } -void ColumnMetaData::__set_key_value_metadata(const duckdb::vector & val) { +void ColumnMetaData::__set_key_value_metadata(const std::vector & val) { this->key_value_metadata = val; __isset.key_value_metadata = true; } @@ -3883,28 +4694,37 @@ void ColumnMetaData::__set_statistics(const Statistics& val) { __isset.statistics = true; } -void ColumnMetaData::__set_encoding_stats(const duckdb::vector & val) { +void ColumnMetaData::__set_encoding_stats(const std::vector & val) { this->encoding_stats = val; __isset.encoding_stats = true; } -std::ostream& operator<<(std::ostream& out, const ColumnMetaData& obj) -{ - obj.printTo(out); - return out; + +void ColumnMetaData::__set_bloom_filter_offset(const int64_t val) { + this->bloom_filter_offset = val; +__isset.bloom_filter_offset = true; +} + +void ColumnMetaData::__set_bloom_filter_length(const int32_t val) { + this->bloom_filter_length = val; +__isset.bloom_filter_length = true; } +void ColumnMetaData::__set_size_statistics(const SizeStatistics& val) { + this->size_statistics = val; +__isset.size_statistics = true; +} -uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t ColumnMetaData::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_type = false; bool isset_encodings = false; @@ -3918,35 +4738,35 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast67; - xfer += iprot->readI32(ecast67); - this->type = (Type::type)ecast67; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast97; + xfer += iprot->readI32(ecast97); + this->type = static_cast(ecast97); isset_type = true; } else { xfer += iprot->skip(ftype); } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->encodings.clear(); - uint32_t _size68; - ::duckdb_apache::thrift::protocol::TType _etype71; - xfer += iprot->readListBegin(_etype71, _size68); - this->encodings.resize(_size68); - uint32_t _i72; - for (_i72 = 0; _i72 < _size68; ++_i72) + uint32_t _size98; + ::apache::thrift::protocol::TType _etype101; + xfer += iprot->readListBegin(_etype101, _size98); + this->encodings.resize(_size98); + uint32_t _i102; + for (_i102 = 0; _i102 < _size98; ++_i102) { - int32_t ecast73; - xfer += iprot->readI32(ecast73); - this->encodings[_i72] = (Encoding::type)ecast73; + int32_t ecast103; + xfer += iprot->readI32(ecast103); + this->encodings[_i102] = static_cast(ecast103); } xfer += iprot->readListEnd(); } @@ -3956,17 +4776,17 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->path_in_schema.clear(); - uint32_t _size74; - ::duckdb_apache::thrift::protocol::TType _etype77; - xfer += iprot->readListBegin(_etype77, _size74); - this->path_in_schema.resize(_size74); - uint32_t _i78; - for (_i78 = 0; _i78 < _size74; ++_i78) + uint32_t _size104; + ::apache::thrift::protocol::TType _etype107; + xfer += iprot->readListBegin(_etype107, _size104); + this->path_in_schema.resize(_size104); + uint32_t _i108; + for (_i108 = 0; _i108 < _size104; ++_i108) { - xfer += iprot->readString(this->path_in_schema[_i78]); + xfer += iprot->readString(this->path_in_schema[_i108]); } xfer += iprot->readListEnd(); } @@ -3976,17 +4796,17 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast79; - xfer += iprot->readI32(ecast79); - this->codec = (CompressionCodec::type)ecast79; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast109; + xfer += iprot->readI32(ecast109); + this->codec = static_cast(ecast109); isset_codec = true; } else { xfer += iprot->skip(ftype); } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->num_values); isset_num_values = true; } else { @@ -3994,7 +4814,7 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 6: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->total_uncompressed_size); isset_total_uncompressed_size = true; } else { @@ -4002,7 +4822,7 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 7: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->total_compressed_size); isset_total_compressed_size = true; } else { @@ -4010,17 +4830,17 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 8: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->key_value_metadata.clear(); - uint32_t _size80; - ::duckdb_apache::thrift::protocol::TType _etype83; - xfer += iprot->readListBegin(_etype83, _size80); - this->key_value_metadata.resize(_size80); - uint32_t _i84; - for (_i84 = 0; _i84 < _size80; ++_i84) + uint32_t _size110; + ::apache::thrift::protocol::TType _etype113; + xfer += iprot->readListBegin(_etype113, _size110); + this->key_value_metadata.resize(_size110); + uint32_t _i114; + for (_i114 = 0; _i114 < _size110; ++_i114) { - xfer += this->key_value_metadata[_i84].read(iprot); + xfer += this->key_value_metadata[_i114].read(iprot); } xfer += iprot->readListEnd(); } @@ -4030,7 +4850,7 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 9: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->data_page_offset); isset_data_page_offset = true; } else { @@ -4038,7 +4858,7 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 10: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->index_page_offset); this->__isset.index_page_offset = true; } else { @@ -4046,7 +4866,7 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 11: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->dictionary_page_offset); this->__isset.dictionary_page_offset = true; } else { @@ -4054,7 +4874,7 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 12: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->statistics.read(iprot); this->__isset.statistics = true; } else { @@ -4062,17 +4882,17 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro } break; case 13: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->encoding_stats.clear(); - uint32_t _size85; - ::duckdb_apache::thrift::protocol::TType _etype88; - xfer += iprot->readListBegin(_etype88, _size85); - this->encoding_stats.resize(_size85); - uint32_t _i89; - for (_i89 = 0; _i89 < _size85; ++_i89) + uint32_t _size115; + ::apache::thrift::protocol::TType _etype118; + xfer += iprot->readListBegin(_etype118, _size115); + this->encoding_stats.resize(_size115); + uint32_t _i119; + for (_i119 = 0; _i119 < _size115; ++_i119) { - xfer += this->encoding_stats[_i89].read(iprot); + xfer += this->encoding_stats[_i119].read(iprot); } xfer += iprot->readListEnd(); } @@ -4081,6 +4901,30 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro xfer += iprot->skip(ftype); } break; + case 14: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->bloom_filter_offset); + this->__isset.bloom_filter_offset = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 15: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->bloom_filter_length); + this->__isset.bloom_filter_length = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 16: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->size_statistics.read(iprot); + this->__isset.size_statistics = true; + } else { + xfer += iprot->skip(ftype); + } + break; default: xfer += iprot->skip(ftype); break; @@ -4109,100 +4953,115 @@ uint32_t ColumnMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* ipro return xfer; } -uint32_t ColumnMetaData::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t ColumnMetaData::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("ColumnMetaData"); - xfer += oprot->writeFieldBegin("type", ::duckdb_apache::thrift::protocol::T_I32, 1); - xfer += oprot->writeI32((int32_t)this->type); + xfer += oprot->writeFieldBegin("type", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(static_cast(this->type)); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("encodings", ::duckdb_apache::thrift::protocol::T_LIST, 2); + xfer += oprot->writeFieldBegin("encodings", ::apache::thrift::protocol::T_LIST, 2); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_I32, static_cast(this->encodings.size())); - duckdb::vector ::const_iterator _iter90; - for (_iter90 = this->encodings.begin(); _iter90 != this->encodings.end(); ++_iter90) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I32, static_cast(this->encodings.size())); + std::vector ::const_iterator _iter120; + for (_iter120 = this->encodings.begin(); _iter120 != this->encodings.end(); ++_iter120) { - xfer += oprot->writeI32((int32_t)(*_iter90)); + xfer += oprot->writeI32(static_cast((*_iter120))); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("path_in_schema", ::duckdb_apache::thrift::protocol::T_LIST, 3); + xfer += oprot->writeFieldBegin("path_in_schema", ::apache::thrift::protocol::T_LIST, 3); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRING, static_cast(this->path_in_schema.size())); - duckdb::vector ::const_iterator _iter91; - for (_iter91 = this->path_in_schema.begin(); _iter91 != this->path_in_schema.end(); ++_iter91) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->path_in_schema.size())); + std::vector ::const_iterator _iter121; + for (_iter121 = this->path_in_schema.begin(); _iter121 != this->path_in_schema.end(); ++_iter121) { - xfer += oprot->writeString((*_iter91)); + xfer += oprot->writeString((*_iter121)); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("codec", ::duckdb_apache::thrift::protocol::T_I32, 4); - xfer += oprot->writeI32((int32_t)this->codec); + xfer += oprot->writeFieldBegin("codec", ::apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(static_cast(this->codec)); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("num_values", ::duckdb_apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeFieldBegin("num_values", ::apache::thrift::protocol::T_I64, 5); xfer += oprot->writeI64(this->num_values); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("total_uncompressed_size", ::duckdb_apache::thrift::protocol::T_I64, 6); + xfer += oprot->writeFieldBegin("total_uncompressed_size", ::apache::thrift::protocol::T_I64, 6); xfer += oprot->writeI64(this->total_uncompressed_size); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("total_compressed_size", ::duckdb_apache::thrift::protocol::T_I64, 7); + xfer += oprot->writeFieldBegin("total_compressed_size", ::apache::thrift::protocol::T_I64, 7); xfer += oprot->writeI64(this->total_compressed_size); xfer += oprot->writeFieldEnd(); if (this->__isset.key_value_metadata) { - xfer += oprot->writeFieldBegin("key_value_metadata", ::duckdb_apache::thrift::protocol::T_LIST, 8); + xfer += oprot->writeFieldBegin("key_value_metadata", ::apache::thrift::protocol::T_LIST, 8); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRUCT, static_cast(this->key_value_metadata.size())); - duckdb::vector ::const_iterator _iter92; - for (_iter92 = this->key_value_metadata.begin(); _iter92 != this->key_value_metadata.end(); ++_iter92) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->key_value_metadata.size())); + std::vector ::const_iterator _iter122; + for (_iter122 = this->key_value_metadata.begin(); _iter122 != this->key_value_metadata.end(); ++_iter122) { - xfer += (*_iter92).write(oprot); + xfer += (*_iter122).write(oprot); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); } - xfer += oprot->writeFieldBegin("data_page_offset", ::duckdb_apache::thrift::protocol::T_I64, 9); + xfer += oprot->writeFieldBegin("data_page_offset", ::apache::thrift::protocol::T_I64, 9); xfer += oprot->writeI64(this->data_page_offset); xfer += oprot->writeFieldEnd(); if (this->__isset.index_page_offset) { - xfer += oprot->writeFieldBegin("index_page_offset", ::duckdb_apache::thrift::protocol::T_I64, 10); + xfer += oprot->writeFieldBegin("index_page_offset", ::apache::thrift::protocol::T_I64, 10); xfer += oprot->writeI64(this->index_page_offset); xfer += oprot->writeFieldEnd(); } if (this->__isset.dictionary_page_offset) { - xfer += oprot->writeFieldBegin("dictionary_page_offset", ::duckdb_apache::thrift::protocol::T_I64, 11); + xfer += oprot->writeFieldBegin("dictionary_page_offset", ::apache::thrift::protocol::T_I64, 11); xfer += oprot->writeI64(this->dictionary_page_offset); xfer += oprot->writeFieldEnd(); } if (this->__isset.statistics) { - xfer += oprot->writeFieldBegin("statistics", ::duckdb_apache::thrift::protocol::T_STRUCT, 12); + xfer += oprot->writeFieldBegin("statistics", ::apache::thrift::protocol::T_STRUCT, 12); xfer += this->statistics.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.encoding_stats) { - xfer += oprot->writeFieldBegin("encoding_stats", ::duckdb_apache::thrift::protocol::T_LIST, 13); + xfer += oprot->writeFieldBegin("encoding_stats", ::apache::thrift::protocol::T_LIST, 13); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRUCT, static_cast(this->encoding_stats.size())); - duckdb::vector ::const_iterator _iter93; - for (_iter93 = this->encoding_stats.begin(); _iter93 != this->encoding_stats.end(); ++_iter93) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->encoding_stats.size())); + std::vector ::const_iterator _iter123; + for (_iter123 = this->encoding_stats.begin(); _iter123 != this->encoding_stats.end(); ++_iter123) { - xfer += (*_iter93).write(oprot); + xfer += (*_iter123).write(oprot); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); } + if (this->__isset.bloom_filter_offset) { + xfer += oprot->writeFieldBegin("bloom_filter_offset", ::apache::thrift::protocol::T_I64, 14); + xfer += oprot->writeI64(this->bloom_filter_offset); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.bloom_filter_length) { + xfer += oprot->writeFieldBegin("bloom_filter_length", ::apache::thrift::protocol::T_I32, 15); + xfer += oprot->writeI32(this->bloom_filter_length); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.size_statistics) { + xfer += oprot->writeFieldBegin("size_statistics", ::apache::thrift::protocol::T_STRUCT, 16); + xfer += this->size_statistics.write(oprot); + xfer += oprot->writeFieldEnd(); + } xfer += oprot->writeFieldStop(); xfer += oprot->writeStructEnd(); return xfer; @@ -4223,89 +5082,75 @@ void swap(ColumnMetaData &a, ColumnMetaData &b) { swap(a.dictionary_page_offset, b.dictionary_page_offset); swap(a.statistics, b.statistics); swap(a.encoding_stats, b.encoding_stats); + swap(a.bloom_filter_offset, b.bloom_filter_offset); + swap(a.bloom_filter_length, b.bloom_filter_length); + swap(a.size_statistics, b.size_statistics); swap(a.__isset, b.__isset); } -ColumnMetaData::ColumnMetaData(const ColumnMetaData& other94) { - type = other94.type; - encodings = other94.encodings; - path_in_schema = other94.path_in_schema; - codec = other94.codec; - num_values = other94.num_values; - total_uncompressed_size = other94.total_uncompressed_size; - total_compressed_size = other94.total_compressed_size; - key_value_metadata = other94.key_value_metadata; - data_page_offset = other94.data_page_offset; - index_page_offset = other94.index_page_offset; - dictionary_page_offset = other94.dictionary_page_offset; - statistics = other94.statistics; - encoding_stats = other94.encoding_stats; - __isset = other94.__isset; -} -ColumnMetaData& ColumnMetaData::operator=(const ColumnMetaData& other95) { - type = other95.type; - encodings = other95.encodings; - path_in_schema = other95.path_in_schema; - codec = other95.codec; - num_values = other95.num_values; - total_uncompressed_size = other95.total_uncompressed_size; - total_compressed_size = other95.total_compressed_size; - key_value_metadata = other95.key_value_metadata; - data_page_offset = other95.data_page_offset; - index_page_offset = other95.index_page_offset; - dictionary_page_offset = other95.dictionary_page_offset; - statistics = other95.statistics; - encoding_stats = other95.encoding_stats; - __isset = other95.__isset; +ColumnMetaData::ColumnMetaData(const ColumnMetaData& other124) { + type = other124.type; + encodings = other124.encodings; + path_in_schema = other124.path_in_schema; + codec = other124.codec; + num_values = other124.num_values; + total_uncompressed_size = other124.total_uncompressed_size; + total_compressed_size = other124.total_compressed_size; + key_value_metadata = other124.key_value_metadata; + data_page_offset = other124.data_page_offset; + index_page_offset = other124.index_page_offset; + dictionary_page_offset = other124.dictionary_page_offset; + statistics = other124.statistics; + encoding_stats = other124.encoding_stats; + bloom_filter_offset = other124.bloom_filter_offset; + bloom_filter_length = other124.bloom_filter_length; + size_statistics = other124.size_statistics; + __isset = other124.__isset; +} +ColumnMetaData& ColumnMetaData::operator=(const ColumnMetaData& other125) { + type = other125.type; + encodings = other125.encodings; + path_in_schema = other125.path_in_schema; + codec = other125.codec; + num_values = other125.num_values; + total_uncompressed_size = other125.total_uncompressed_size; + total_compressed_size = other125.total_compressed_size; + key_value_metadata = other125.key_value_metadata; + data_page_offset = other125.data_page_offset; + index_page_offset = other125.index_page_offset; + dictionary_page_offset = other125.dictionary_page_offset; + statistics = other125.statistics; + encoding_stats = other125.encoding_stats; + bloom_filter_offset = other125.bloom_filter_offset; + bloom_filter_length = other125.bloom_filter_length; + size_statistics = other125.size_statistics; + __isset = other125.__isset; return *this; } -void ColumnMetaData::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "ColumnMetaData("; - out << "type=" << to_string(type); - out << ", " << "encodings=" << to_string(encodings); - out << ", " << "path_in_schema=" << to_string(path_in_schema); - out << ", " << "codec=" << to_string(codec); - out << ", " << "num_values=" << to_string(num_values); - out << ", " << "total_uncompressed_size=" << to_string(total_uncompressed_size); - out << ", " << "total_compressed_size=" << to_string(total_compressed_size); - out << ", " << "key_value_metadata="; (__isset.key_value_metadata ? (out << to_string(key_value_metadata)) : (out << "")); - out << ", " << "data_page_offset=" << to_string(data_page_offset); - out << ", " << "index_page_offset="; (__isset.index_page_offset ? (out << to_string(index_page_offset)) : (out << "")); - out << ", " << "dictionary_page_offset="; (__isset.dictionary_page_offset ? (out << to_string(dictionary_page_offset)) : (out << "")); - out << ", " << "statistics="; (__isset.statistics ? (out << to_string(statistics)) : (out << "")); - out << ", " << "encoding_stats="; (__isset.encoding_stats ? (out << to_string(encoding_stats)) : (out << "")); - out << ")"; -} - -EncryptionWithFooterKey::~EncryptionWithFooterKey() throw() { +EncryptionWithFooterKey::~EncryptionWithFooterKey() noexcept { } -std::ostream& operator<<(std::ostream& out, const EncryptionWithFooterKey& obj) -{ - obj.printTo(out); - return out; +EncryptionWithFooterKey::EncryptionWithFooterKey() noexcept { } +uint32_t EncryptionWithFooterKey::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t EncryptionWithFooterKey::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -4317,9 +5162,9 @@ uint32_t EncryptionWithFooterKey::read(::duckdb_apache::thrift::protocol::TProto return xfer; } -uint32_t EncryptionWithFooterKey::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t EncryptionWithFooterKey::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("EncryptionWithFooterKey"); xfer += oprot->writeFieldStop(); @@ -4333,25 +5178,22 @@ void swap(EncryptionWithFooterKey &a, EncryptionWithFooterKey &b) { (void) b; } -EncryptionWithFooterKey::EncryptionWithFooterKey(const EncryptionWithFooterKey& other96) { - (void) other96; +EncryptionWithFooterKey::EncryptionWithFooterKey(const EncryptionWithFooterKey& other126) noexcept { + (void) other126; } -EncryptionWithFooterKey& EncryptionWithFooterKey::operator=(const EncryptionWithFooterKey& other97) { - (void) other97; +EncryptionWithFooterKey& EncryptionWithFooterKey::operator=(const EncryptionWithFooterKey& other127) noexcept { + (void) other127; return *this; } -void EncryptionWithFooterKey::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "EncryptionWithFooterKey("; - out << ")"; -} - -EncryptionWithColumnKey::~EncryptionWithColumnKey() throw() { +EncryptionWithColumnKey::~EncryptionWithColumnKey() noexcept { } +EncryptionWithColumnKey::EncryptionWithColumnKey() noexcept + : key_metadata() { +} -void EncryptionWithColumnKey::__set_path_in_schema(const duckdb::vector & val) { +void EncryptionWithColumnKey::__set_path_in_schema(const std::vector & val) { this->path_in_schema = val; } @@ -4359,47 +5201,41 @@ void EncryptionWithColumnKey::__set_key_metadata(const std::string& val) { this->key_metadata = val; __isset.key_metadata = true; } -std::ostream& operator<<(std::ostream& out, const EncryptionWithColumnKey& obj) -{ - obj.printTo(out); - return out; -} +uint32_t EncryptionWithColumnKey::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t EncryptionWithColumnKey::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_path_in_schema = false; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->path_in_schema.clear(); - uint32_t _size98; - ::duckdb_apache::thrift::protocol::TType _etype101; - xfer += iprot->readListBegin(_etype101, _size98); - this->path_in_schema.resize(_size98); - uint32_t _i102; - for (_i102 = 0; _i102 < _size98; ++_i102) + uint32_t _size128; + ::apache::thrift::protocol::TType _etype131; + xfer += iprot->readListBegin(_etype131, _size128); + this->path_in_schema.resize(_size128); + uint32_t _i132; + for (_i132 = 0; _i132 < _size128; ++_i132) { - xfer += iprot->readString(this->path_in_schema[_i102]); + xfer += iprot->readString(this->path_in_schema[_i132]); } xfer += iprot->readListEnd(); } @@ -4409,7 +5245,7 @@ uint32_t EncryptionWithColumnKey::read(::duckdb_apache::thrift::protocol::TProto } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->key_metadata); this->__isset.key_metadata = true; } else { @@ -4430,25 +5266,25 @@ uint32_t EncryptionWithColumnKey::read(::duckdb_apache::thrift::protocol::TProto return xfer; } -uint32_t EncryptionWithColumnKey::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t EncryptionWithColumnKey::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("EncryptionWithColumnKey"); - xfer += oprot->writeFieldBegin("path_in_schema", ::duckdb_apache::thrift::protocol::T_LIST, 1); + xfer += oprot->writeFieldBegin("path_in_schema", ::apache::thrift::protocol::T_LIST, 1); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRING, static_cast(this->path_in_schema.size())); - duckdb::vector ::const_iterator _iter103; - for (_iter103 = this->path_in_schema.begin(); _iter103 != this->path_in_schema.end(); ++_iter103) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->path_in_schema.size())); + std::vector ::const_iterator _iter133; + for (_iter133 = this->path_in_schema.begin(); _iter133 != this->path_in_schema.end(); ++_iter133) { - xfer += oprot->writeString((*_iter103)); + xfer += oprot->writeString((*_iter133)); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); if (this->__isset.key_metadata) { - xfer += oprot->writeFieldBegin("key_metadata", ::duckdb_apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeFieldBegin("key_metadata", ::apache::thrift::protocol::T_STRING, 2); xfer += oprot->writeBinary(this->key_metadata); xfer += oprot->writeFieldEnd(); } @@ -4464,29 +5300,23 @@ void swap(EncryptionWithColumnKey &a, EncryptionWithColumnKey &b) { swap(a.__isset, b.__isset); } -EncryptionWithColumnKey::EncryptionWithColumnKey(const EncryptionWithColumnKey& other104) { - path_in_schema = other104.path_in_schema; - key_metadata = other104.key_metadata; - __isset = other104.__isset; +EncryptionWithColumnKey::EncryptionWithColumnKey(const EncryptionWithColumnKey& other134) { + path_in_schema = other134.path_in_schema; + key_metadata = other134.key_metadata; + __isset = other134.__isset; } -EncryptionWithColumnKey& EncryptionWithColumnKey::operator=(const EncryptionWithColumnKey& other105) { - path_in_schema = other105.path_in_schema; - key_metadata = other105.key_metadata; - __isset = other105.__isset; +EncryptionWithColumnKey& EncryptionWithColumnKey::operator=(const EncryptionWithColumnKey& other135) { + path_in_schema = other135.path_in_schema; + key_metadata = other135.key_metadata; + __isset = other135.__isset; return *this; } -void EncryptionWithColumnKey::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "EncryptionWithColumnKey("; - out << "path_in_schema=" << to_string(path_in_schema); - out << ", " << "key_metadata="; (__isset.key_metadata ? (out << to_string(key_metadata)) : (out << "")); - out << ")"; -} - -ColumnCryptoMetaData::~ColumnCryptoMetaData() throw() { +ColumnCryptoMetaData::~ColumnCryptoMetaData() noexcept { } +ColumnCryptoMetaData::ColumnCryptoMetaData() noexcept { +} void ColumnCryptoMetaData::__set_ENCRYPTION_WITH_FOOTER_KEY(const EncryptionWithFooterKey& val) { this->ENCRYPTION_WITH_FOOTER_KEY = val; @@ -4497,36 +5327,30 @@ void ColumnCryptoMetaData::__set_ENCRYPTION_WITH_COLUMN_KEY(const EncryptionWith this->ENCRYPTION_WITH_COLUMN_KEY = val; __isset.ENCRYPTION_WITH_COLUMN_KEY = true; } -std::ostream& operator<<(std::ostream& out, const ColumnCryptoMetaData& obj) -{ - obj.printTo(out); - return out; -} - -uint32_t ColumnCryptoMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t ColumnCryptoMetaData::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->ENCRYPTION_WITH_FOOTER_KEY.read(iprot); this->__isset.ENCRYPTION_WITH_FOOTER_KEY = true; } else { @@ -4534,7 +5358,7 @@ uint32_t ColumnCryptoMetaData::read(::duckdb_apache::thrift::protocol::TProtocol } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->ENCRYPTION_WITH_COLUMN_KEY.read(iprot); this->__isset.ENCRYPTION_WITH_COLUMN_KEY = true; } else { @@ -4553,18 +5377,18 @@ uint32_t ColumnCryptoMetaData::read(::duckdb_apache::thrift::protocol::TProtocol return xfer; } -uint32_t ColumnCryptoMetaData::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t ColumnCryptoMetaData::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("ColumnCryptoMetaData"); if (this->__isset.ENCRYPTION_WITH_FOOTER_KEY) { - xfer += oprot->writeFieldBegin("ENCRYPTION_WITH_FOOTER_KEY", ::duckdb_apache::thrift::protocol::T_STRUCT, 1); + xfer += oprot->writeFieldBegin("ENCRYPTION_WITH_FOOTER_KEY", ::apache::thrift::protocol::T_STRUCT, 1); xfer += this->ENCRYPTION_WITH_FOOTER_KEY.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.ENCRYPTION_WITH_COLUMN_KEY) { - xfer += oprot->writeFieldBegin("ENCRYPTION_WITH_COLUMN_KEY", ::duckdb_apache::thrift::protocol::T_STRUCT, 2); + xfer += oprot->writeFieldBegin("ENCRYPTION_WITH_COLUMN_KEY", ::apache::thrift::protocol::T_STRUCT, 2); xfer += this->ENCRYPTION_WITH_COLUMN_KEY.write(oprot); xfer += oprot->writeFieldEnd(); } @@ -4580,29 +5404,30 @@ void swap(ColumnCryptoMetaData &a, ColumnCryptoMetaData &b) { swap(a.__isset, b.__isset); } -ColumnCryptoMetaData::ColumnCryptoMetaData(const ColumnCryptoMetaData& other106) { - ENCRYPTION_WITH_FOOTER_KEY = other106.ENCRYPTION_WITH_FOOTER_KEY; - ENCRYPTION_WITH_COLUMN_KEY = other106.ENCRYPTION_WITH_COLUMN_KEY; - __isset = other106.__isset; +ColumnCryptoMetaData::ColumnCryptoMetaData(const ColumnCryptoMetaData& other136) { + ENCRYPTION_WITH_FOOTER_KEY = other136.ENCRYPTION_WITH_FOOTER_KEY; + ENCRYPTION_WITH_COLUMN_KEY = other136.ENCRYPTION_WITH_COLUMN_KEY; + __isset = other136.__isset; } -ColumnCryptoMetaData& ColumnCryptoMetaData::operator=(const ColumnCryptoMetaData& other107) { - ENCRYPTION_WITH_FOOTER_KEY = other107.ENCRYPTION_WITH_FOOTER_KEY; - ENCRYPTION_WITH_COLUMN_KEY = other107.ENCRYPTION_WITH_COLUMN_KEY; - __isset = other107.__isset; +ColumnCryptoMetaData& ColumnCryptoMetaData::operator=(const ColumnCryptoMetaData& other137) { + ENCRYPTION_WITH_FOOTER_KEY = other137.ENCRYPTION_WITH_FOOTER_KEY; + ENCRYPTION_WITH_COLUMN_KEY = other137.ENCRYPTION_WITH_COLUMN_KEY; + __isset = other137.__isset; return *this; } -void ColumnCryptoMetaData::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "ColumnCryptoMetaData("; - out << "ENCRYPTION_WITH_FOOTER_KEY="; (__isset.ENCRYPTION_WITH_FOOTER_KEY ? (out << to_string(ENCRYPTION_WITH_FOOTER_KEY)) : (out << "")); - out << ", " << "ENCRYPTION_WITH_COLUMN_KEY="; (__isset.ENCRYPTION_WITH_COLUMN_KEY ? (out << to_string(ENCRYPTION_WITH_COLUMN_KEY)) : (out << "")); - out << ")"; -} - -ColumnChunk::~ColumnChunk() throw() { +ColumnChunk::~ColumnChunk() noexcept { } +ColumnChunk::ColumnChunk() noexcept + : file_path(), + file_offset(0LL), + offset_index_offset(0), + offset_index_length(0), + column_index_offset(0), + column_index_length(0), + encrypted_column_metadata() { +} void ColumnChunk::__set_file_path(const std::string& val) { this->file_path = val; @@ -4647,37 +5472,31 @@ void ColumnChunk::__set_encrypted_column_metadata(const std::string& val) { this->encrypted_column_metadata = val; __isset.encrypted_column_metadata = true; } -std::ostream& operator<<(std::ostream& out, const ColumnChunk& obj) -{ - obj.printTo(out); - return out; -} +uint32_t ColumnChunk::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t ColumnChunk::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_file_offset = false; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readString(this->file_path); this->__isset.file_path = true; } else { @@ -4685,7 +5504,7 @@ uint32_t ColumnChunk::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->file_offset); isset_file_offset = true; } else { @@ -4693,7 +5512,7 @@ uint32_t ColumnChunk::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->meta_data.read(iprot); this->__isset.meta_data = true; } else { @@ -4701,7 +5520,7 @@ uint32_t ColumnChunk::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->offset_index_offset); this->__isset.offset_index_offset = true; } else { @@ -4709,7 +5528,7 @@ uint32_t ColumnChunk::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->offset_index_length); this->__isset.offset_index_length = true; } else { @@ -4717,7 +5536,7 @@ uint32_t ColumnChunk::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 6: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->column_index_offset); this->__isset.column_index_offset = true; } else { @@ -4725,7 +5544,7 @@ uint32_t ColumnChunk::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 7: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->column_index_length); this->__isset.column_index_length = true; } else { @@ -4733,7 +5552,7 @@ uint32_t ColumnChunk::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 8: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->crypto_metadata.read(iprot); this->__isset.crypto_metadata = true; } else { @@ -4741,7 +5560,7 @@ uint32_t ColumnChunk::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 9: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->encrypted_column_metadata); this->__isset.encrypted_column_metadata = true; } else { @@ -4762,52 +5581,52 @@ uint32_t ColumnChunk::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t ColumnChunk::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t ColumnChunk::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("ColumnChunk"); if (this->__isset.file_path) { - xfer += oprot->writeFieldBegin("file_path", ::duckdb_apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeFieldBegin("file_path", ::apache::thrift::protocol::T_STRING, 1); xfer += oprot->writeString(this->file_path); xfer += oprot->writeFieldEnd(); } - xfer += oprot->writeFieldBegin("file_offset", ::duckdb_apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeFieldBegin("file_offset", ::apache::thrift::protocol::T_I64, 2); xfer += oprot->writeI64(this->file_offset); xfer += oprot->writeFieldEnd(); if (this->__isset.meta_data) { - xfer += oprot->writeFieldBegin("meta_data", ::duckdb_apache::thrift::protocol::T_STRUCT, 3); + xfer += oprot->writeFieldBegin("meta_data", ::apache::thrift::protocol::T_STRUCT, 3); xfer += this->meta_data.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.offset_index_offset) { - xfer += oprot->writeFieldBegin("offset_index_offset", ::duckdb_apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeFieldBegin("offset_index_offset", ::apache::thrift::protocol::T_I64, 4); xfer += oprot->writeI64(this->offset_index_offset); xfer += oprot->writeFieldEnd(); } if (this->__isset.offset_index_length) { - xfer += oprot->writeFieldBegin("offset_index_length", ::duckdb_apache::thrift::protocol::T_I32, 5); + xfer += oprot->writeFieldBegin("offset_index_length", ::apache::thrift::protocol::T_I32, 5); xfer += oprot->writeI32(this->offset_index_length); xfer += oprot->writeFieldEnd(); } if (this->__isset.column_index_offset) { - xfer += oprot->writeFieldBegin("column_index_offset", ::duckdb_apache::thrift::protocol::T_I64, 6); + xfer += oprot->writeFieldBegin("column_index_offset", ::apache::thrift::protocol::T_I64, 6); xfer += oprot->writeI64(this->column_index_offset); xfer += oprot->writeFieldEnd(); } if (this->__isset.column_index_length) { - xfer += oprot->writeFieldBegin("column_index_length", ::duckdb_apache::thrift::protocol::T_I32, 7); + xfer += oprot->writeFieldBegin("column_index_length", ::apache::thrift::protocol::T_I32, 7); xfer += oprot->writeI32(this->column_index_length); xfer += oprot->writeFieldEnd(); } if (this->__isset.crypto_metadata) { - xfer += oprot->writeFieldBegin("crypto_metadata", ::duckdb_apache::thrift::protocol::T_STRUCT, 8); + xfer += oprot->writeFieldBegin("crypto_metadata", ::apache::thrift::protocol::T_STRUCT, 8); xfer += this->crypto_metadata.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.encrypted_column_metadata) { - xfer += oprot->writeFieldBegin("encrypted_column_metadata", ::duckdb_apache::thrift::protocol::T_STRING, 9); + xfer += oprot->writeFieldBegin("encrypted_column_metadata", ::apache::thrift::protocol::T_STRING, 9); xfer += oprot->writeBinary(this->encrypted_column_metadata); xfer += oprot->writeFieldEnd(); } @@ -4830,52 +5649,44 @@ void swap(ColumnChunk &a, ColumnChunk &b) { swap(a.__isset, b.__isset); } -ColumnChunk::ColumnChunk(const ColumnChunk& other108) { - file_path = other108.file_path; - file_offset = other108.file_offset; - meta_data = other108.meta_data; - offset_index_offset = other108.offset_index_offset; - offset_index_length = other108.offset_index_length; - column_index_offset = other108.column_index_offset; - column_index_length = other108.column_index_length; - crypto_metadata = other108.crypto_metadata; - encrypted_column_metadata = other108.encrypted_column_metadata; - __isset = other108.__isset; -} -ColumnChunk& ColumnChunk::operator=(const ColumnChunk& other109) { - file_path = other109.file_path; - file_offset = other109.file_offset; - meta_data = other109.meta_data; - offset_index_offset = other109.offset_index_offset; - offset_index_length = other109.offset_index_length; - column_index_offset = other109.column_index_offset; - column_index_length = other109.column_index_length; - crypto_metadata = other109.crypto_metadata; - encrypted_column_metadata = other109.encrypted_column_metadata; - __isset = other109.__isset; +ColumnChunk::ColumnChunk(const ColumnChunk& other138) { + file_path = other138.file_path; + file_offset = other138.file_offset; + meta_data = other138.meta_data; + offset_index_offset = other138.offset_index_offset; + offset_index_length = other138.offset_index_length; + column_index_offset = other138.column_index_offset; + column_index_length = other138.column_index_length; + crypto_metadata = other138.crypto_metadata; + encrypted_column_metadata = other138.encrypted_column_metadata; + __isset = other138.__isset; +} +ColumnChunk& ColumnChunk::operator=(const ColumnChunk& other139) { + file_path = other139.file_path; + file_offset = other139.file_offset; + meta_data = other139.meta_data; + offset_index_offset = other139.offset_index_offset; + offset_index_length = other139.offset_index_length; + column_index_offset = other139.column_index_offset; + column_index_length = other139.column_index_length; + crypto_metadata = other139.crypto_metadata; + encrypted_column_metadata = other139.encrypted_column_metadata; + __isset = other139.__isset; return *this; } -void ColumnChunk::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "ColumnChunk("; - out << "file_path="; (__isset.file_path ? (out << to_string(file_path)) : (out << "")); - out << ", " << "file_offset=" << to_string(file_offset); - out << ", " << "meta_data="; (__isset.meta_data ? (out << to_string(meta_data)) : (out << "")); - out << ", " << "offset_index_offset="; (__isset.offset_index_offset ? (out << to_string(offset_index_offset)) : (out << "")); - out << ", " << "offset_index_length="; (__isset.offset_index_length ? (out << to_string(offset_index_length)) : (out << "")); - out << ", " << "column_index_offset="; (__isset.column_index_offset ? (out << to_string(column_index_offset)) : (out << "")); - out << ", " << "column_index_length="; (__isset.column_index_length ? (out << to_string(column_index_length)) : (out << "")); - out << ", " << "crypto_metadata="; (__isset.crypto_metadata ? (out << to_string(crypto_metadata)) : (out << "")); - out << ", " << "encrypted_column_metadata="; (__isset.encrypted_column_metadata ? (out << to_string(encrypted_column_metadata)) : (out << "")); - out << ")"; -} - -RowGroup::~RowGroup() throw() { +RowGroup::~RowGroup() noexcept { } +RowGroup::RowGroup() noexcept + : total_byte_size(0), + num_rows(0), + file_offset(0), + total_compressed_size(0), + ordinal(0) { +} -void RowGroup::__set_columns(const duckdb::vector & val) { +void RowGroup::__set_columns(const std::vector & val) { this->columns = val; } @@ -4887,7 +5698,7 @@ void RowGroup::__set_num_rows(const int64_t val) { this->num_rows = val; } -void RowGroup::__set_sorting_columns(const duckdb::vector & val) { +void RowGroup::__set_sorting_columns(const std::vector & val) { this->sorting_columns = val; __isset.sorting_columns = true; } @@ -4906,24 +5717,18 @@ void RowGroup::__set_ordinal(const int16_t val) { this->ordinal = val; __isset.ordinal = true; } -std::ostream& operator<<(std::ostream& out, const RowGroup& obj) -{ - obj.printTo(out); - return out; -} - -uint32_t RowGroup::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t RowGroup::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_columns = false; bool isset_total_byte_size = false; @@ -4932,23 +5737,23 @@ uint32_t RowGroup::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->columns.clear(); - uint32_t _size110; - ::duckdb_apache::thrift::protocol::TType _etype113; - xfer += iprot->readListBegin(_etype113, _size110); - this->columns.resize(_size110); - uint32_t _i114; - for (_i114 = 0; _i114 < _size110; ++_i114) + uint32_t _size140; + ::apache::thrift::protocol::TType _etype143; + xfer += iprot->readListBegin(_etype143, _size140); + this->columns.resize(_size140); + uint32_t _i144; + for (_i144 = 0; _i144 < _size140; ++_i144) { - xfer += this->columns[_i114].read(iprot); + xfer += this->columns[_i144].read(iprot); } xfer += iprot->readListEnd(); } @@ -4958,7 +5763,7 @@ uint32_t RowGroup::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->total_byte_size); isset_total_byte_size = true; } else { @@ -4966,7 +5771,7 @@ uint32_t RowGroup::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->num_rows); isset_num_rows = true; } else { @@ -4974,17 +5779,17 @@ uint32_t RowGroup::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->sorting_columns.clear(); - uint32_t _size115; - ::duckdb_apache::thrift::protocol::TType _etype118; - xfer += iprot->readListBegin(_etype118, _size115); - this->sorting_columns.resize(_size115); - uint32_t _i119; - for (_i119 = 0; _i119 < _size115; ++_i119) + uint32_t _size145; + ::apache::thrift::protocol::TType _etype148; + xfer += iprot->readListBegin(_etype148, _size145); + this->sorting_columns.resize(_size145); + uint32_t _i149; + for (_i149 = 0; _i149 < _size145; ++_i149) { - xfer += this->sorting_columns[_i119].read(iprot); + xfer += this->sorting_columns[_i149].read(iprot); } xfer += iprot->readListEnd(); } @@ -4994,7 +5799,7 @@ uint32_t RowGroup::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->file_offset); this->__isset.file_offset = true; } else { @@ -5002,7 +5807,7 @@ uint32_t RowGroup::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 6: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->total_compressed_size); this->__isset.total_compressed_size = true; } else { @@ -5010,7 +5815,7 @@ uint32_t RowGroup::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 7: - if (ftype == ::duckdb_apache::thrift::protocol::T_I16) { + if (ftype == ::apache::thrift::protocol::T_I16) { xfer += iprot->readI16(this->ordinal); this->__isset.ordinal = true; } else { @@ -5035,56 +5840,56 @@ uint32_t RowGroup::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t RowGroup::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t RowGroup::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("RowGroup"); - xfer += oprot->writeFieldBegin("columns", ::duckdb_apache::thrift::protocol::T_LIST, 1); + xfer += oprot->writeFieldBegin("columns", ::apache::thrift::protocol::T_LIST, 1); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRUCT, static_cast(this->columns.size())); - duckdb::vector ::const_iterator _iter120; - for (_iter120 = this->columns.begin(); _iter120 != this->columns.end(); ++_iter120) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->columns.size())); + std::vector ::const_iterator _iter150; + for (_iter150 = this->columns.begin(); _iter150 != this->columns.end(); ++_iter150) { - xfer += (*_iter120).write(oprot); + xfer += (*_iter150).write(oprot); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("total_byte_size", ::duckdb_apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeFieldBegin("total_byte_size", ::apache::thrift::protocol::T_I64, 2); xfer += oprot->writeI64(this->total_byte_size); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("num_rows", ::duckdb_apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeFieldBegin("num_rows", ::apache::thrift::protocol::T_I64, 3); xfer += oprot->writeI64(this->num_rows); xfer += oprot->writeFieldEnd(); if (this->__isset.sorting_columns) { - xfer += oprot->writeFieldBegin("sorting_columns", ::duckdb_apache::thrift::protocol::T_LIST, 4); + xfer += oprot->writeFieldBegin("sorting_columns", ::apache::thrift::protocol::T_LIST, 4); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRUCT, static_cast(this->sorting_columns.size())); - duckdb::vector ::const_iterator _iter121; - for (_iter121 = this->sorting_columns.begin(); _iter121 != this->sorting_columns.end(); ++_iter121) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->sorting_columns.size())); + std::vector ::const_iterator _iter151; + for (_iter151 = this->sorting_columns.begin(); _iter151 != this->sorting_columns.end(); ++_iter151) { - xfer += (*_iter121).write(oprot); + xfer += (*_iter151).write(oprot); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); } if (this->__isset.file_offset) { - xfer += oprot->writeFieldBegin("file_offset", ::duckdb_apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeFieldBegin("file_offset", ::apache::thrift::protocol::T_I64, 5); xfer += oprot->writeI64(this->file_offset); xfer += oprot->writeFieldEnd(); } if (this->__isset.total_compressed_size) { - xfer += oprot->writeFieldBegin("total_compressed_size", ::duckdb_apache::thrift::protocol::T_I64, 6); + xfer += oprot->writeFieldBegin("total_compressed_size", ::apache::thrift::protocol::T_I64, 6); xfer += oprot->writeI64(this->total_compressed_size); xfer += oprot->writeFieldEnd(); } if (this->__isset.ordinal) { - xfer += oprot->writeFieldBegin("ordinal", ::duckdb_apache::thrift::protocol::T_I16, 7); + xfer += oprot->writeFieldBegin("ordinal", ::apache::thrift::protocol::T_I16, 7); xfer += oprot->writeI16(this->ordinal); xfer += oprot->writeFieldEnd(); } @@ -5105,68 +5910,51 @@ void swap(RowGroup &a, RowGroup &b) { swap(a.__isset, b.__isset); } -RowGroup::RowGroup(const RowGroup& other122) { - columns = other122.columns; - total_byte_size = other122.total_byte_size; - num_rows = other122.num_rows; - sorting_columns = other122.sorting_columns; - file_offset = other122.file_offset; - total_compressed_size = other122.total_compressed_size; - ordinal = other122.ordinal; - __isset = other122.__isset; -} -RowGroup& RowGroup::operator=(const RowGroup& other123) { - columns = other123.columns; - total_byte_size = other123.total_byte_size; - num_rows = other123.num_rows; - sorting_columns = other123.sorting_columns; - file_offset = other123.file_offset; - total_compressed_size = other123.total_compressed_size; - ordinal = other123.ordinal; - __isset = other123.__isset; +RowGroup::RowGroup(const RowGroup& other152) { + columns = other152.columns; + total_byte_size = other152.total_byte_size; + num_rows = other152.num_rows; + sorting_columns = other152.sorting_columns; + file_offset = other152.file_offset; + total_compressed_size = other152.total_compressed_size; + ordinal = other152.ordinal; + __isset = other152.__isset; +} +RowGroup& RowGroup::operator=(const RowGroup& other153) { + columns = other153.columns; + total_byte_size = other153.total_byte_size; + num_rows = other153.num_rows; + sorting_columns = other153.sorting_columns; + file_offset = other153.file_offset; + total_compressed_size = other153.total_compressed_size; + ordinal = other153.ordinal; + __isset = other153.__isset; return *this; } -void RowGroup::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "RowGroup("; - out << "columns=" << to_string(columns); - out << ", " << "total_byte_size=" << to_string(total_byte_size); - out << ", " << "num_rows=" << to_string(num_rows); - out << ", " << "sorting_columns="; (__isset.sorting_columns ? (out << to_string(sorting_columns)) : (out << "")); - out << ", " << "file_offset="; (__isset.file_offset ? (out << to_string(file_offset)) : (out << "")); - out << ", " << "total_compressed_size="; (__isset.total_compressed_size ? (out << to_string(total_compressed_size)) : (out << "")); - out << ", " << "ordinal="; (__isset.ordinal ? (out << to_string(ordinal)) : (out << "")); - out << ")"; -} - -TypeDefinedOrder::~TypeDefinedOrder() throw() { +TypeDefinedOrder::~TypeDefinedOrder() noexcept { } -std::ostream& operator<<(std::ostream& out, const TypeDefinedOrder& obj) -{ - obj.printTo(out); - return out; +TypeDefinedOrder::TypeDefinedOrder() noexcept { } +uint32_t TypeDefinedOrder::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t TypeDefinedOrder::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } xfer += iprot->skip(ftype); @@ -5178,9 +5966,9 @@ uint32_t TypeDefinedOrder::read(::duckdb_apache::thrift::protocol::TProtocol* ip return xfer; } -uint32_t TypeDefinedOrder::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t TypeDefinedOrder::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("TypeDefinedOrder"); xfer += oprot->writeFieldStop(); @@ -5194,58 +5982,48 @@ void swap(TypeDefinedOrder &a, TypeDefinedOrder &b) { (void) b; } -TypeDefinedOrder::TypeDefinedOrder(const TypeDefinedOrder& other124) { - (void) other124; +TypeDefinedOrder::TypeDefinedOrder(const TypeDefinedOrder& other154) noexcept { + (void) other154; } -TypeDefinedOrder& TypeDefinedOrder::operator=(const TypeDefinedOrder& other125) { - (void) other125; +TypeDefinedOrder& TypeDefinedOrder::operator=(const TypeDefinedOrder& other155) noexcept { + (void) other155; return *this; } -void TypeDefinedOrder::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "TypeDefinedOrder("; - out << ")"; -} - -ColumnOrder::~ColumnOrder() throw() { +ColumnOrder::~ColumnOrder() noexcept { } +ColumnOrder::ColumnOrder() noexcept { +} void ColumnOrder::__set_TYPE_ORDER(const TypeDefinedOrder& val) { this->TYPE_ORDER = val; __isset.TYPE_ORDER = true; } -std::ostream& operator<<(std::ostream& out, const ColumnOrder& obj) -{ - obj.printTo(out); - return out; -} - -uint32_t ColumnOrder::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t ColumnOrder::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->TYPE_ORDER.read(iprot); this->__isset.TYPE_ORDER = true; } else { @@ -5264,13 +6042,13 @@ uint32_t ColumnOrder::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t ColumnOrder::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t ColumnOrder::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("ColumnOrder"); if (this->__isset.TYPE_ORDER) { - xfer += oprot->writeFieldBegin("TYPE_ORDER", ::duckdb_apache::thrift::protocol::T_STRUCT, 1); + xfer += oprot->writeFieldBegin("TYPE_ORDER", ::apache::thrift::protocol::T_STRUCT, 1); xfer += this->TYPE_ORDER.write(oprot); xfer += oprot->writeFieldEnd(); } @@ -5285,26 +6063,24 @@ void swap(ColumnOrder &a, ColumnOrder &b) { swap(a.__isset, b.__isset); } -ColumnOrder::ColumnOrder(const ColumnOrder& other126) { - TYPE_ORDER = other126.TYPE_ORDER; - __isset = other126.__isset; +ColumnOrder::ColumnOrder(const ColumnOrder& other156) noexcept { + TYPE_ORDER = other156.TYPE_ORDER; + __isset = other156.__isset; } -ColumnOrder& ColumnOrder::operator=(const ColumnOrder& other127) { - TYPE_ORDER = other127.TYPE_ORDER; - __isset = other127.__isset; +ColumnOrder& ColumnOrder::operator=(const ColumnOrder& other157) noexcept { + TYPE_ORDER = other157.TYPE_ORDER; + __isset = other157.__isset; return *this; } -void ColumnOrder::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "ColumnOrder("; - out << "TYPE_ORDER="; (__isset.TYPE_ORDER ? (out << to_string(TYPE_ORDER)) : (out << "")); - out << ")"; -} - -PageLocation::~PageLocation() throw() { +PageLocation::~PageLocation() noexcept { } +PageLocation::PageLocation() noexcept + : offset(0), + compressed_page_size(0), + first_row_index(0) { +} void PageLocation::__set_offset(const int64_t val) { this->offset = val; @@ -5317,24 +6093,18 @@ void PageLocation::__set_compressed_page_size(const int32_t val) { void PageLocation::__set_first_row_index(const int64_t val) { this->first_row_index = val; } -std::ostream& operator<<(std::ostream& out, const PageLocation& obj) -{ - obj.printTo(out); - return out; -} +uint32_t PageLocation::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t PageLocation::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_offset = false; bool isset_compressed_page_size = false; @@ -5343,13 +6113,13 @@ uint32_t PageLocation::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->offset); isset_offset = true; } else { @@ -5357,7 +6127,7 @@ uint32_t PageLocation::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->compressed_page_size); isset_compressed_page_size = true; } else { @@ -5365,7 +6135,7 @@ uint32_t PageLocation::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->first_row_index); isset_first_row_index = true; } else { @@ -5390,20 +6160,20 @@ uint32_t PageLocation::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t PageLocation::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t PageLocation::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("PageLocation"); - xfer += oprot->writeFieldBegin("offset", ::duckdb_apache::thrift::protocol::T_I64, 1); + xfer += oprot->writeFieldBegin("offset", ::apache::thrift::protocol::T_I64, 1); xfer += oprot->writeI64(this->offset); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("compressed_page_size", ::duckdb_apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeFieldBegin("compressed_page_size", ::apache::thrift::protocol::T_I32, 2); xfer += oprot->writeI32(this->compressed_page_size); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("first_row_index", ::duckdb_apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeFieldBegin("first_row_index", ::apache::thrift::protocol::T_I64, 3); xfer += oprot->writeI64(this->first_row_index); xfer += oprot->writeFieldEnd(); @@ -5419,75 +6189,67 @@ void swap(PageLocation &a, PageLocation &b) { swap(a.first_row_index, b.first_row_index); } -PageLocation::PageLocation(const PageLocation& other128) { - offset = other128.offset; - compressed_page_size = other128.compressed_page_size; - first_row_index = other128.first_row_index; +PageLocation::PageLocation(const PageLocation& other158) noexcept { + offset = other158.offset; + compressed_page_size = other158.compressed_page_size; + first_row_index = other158.first_row_index; } -PageLocation& PageLocation::operator=(const PageLocation& other129) { - offset = other129.offset; - compressed_page_size = other129.compressed_page_size; - first_row_index = other129.first_row_index; +PageLocation& PageLocation::operator=(const PageLocation& other159) noexcept { + offset = other159.offset; + compressed_page_size = other159.compressed_page_size; + first_row_index = other159.first_row_index; return *this; } -void PageLocation::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "PageLocation("; - out << "offset=" << to_string(offset); - out << ", " << "compressed_page_size=" << to_string(compressed_page_size); - out << ", " << "first_row_index=" << to_string(first_row_index); - out << ")"; -} - -OffsetIndex::~OffsetIndex() throw() { +OffsetIndex::~OffsetIndex() noexcept { } +OffsetIndex::OffsetIndex() noexcept { +} -void OffsetIndex::__set_page_locations(const duckdb::vector & val) { +void OffsetIndex::__set_page_locations(const std::vector & val) { this->page_locations = val; } -std::ostream& operator<<(std::ostream& out, const OffsetIndex& obj) -{ - obj.printTo(out); - return out; -} +void OffsetIndex::__set_unencoded_byte_array_data_bytes(const std::vector & val) { + this->unencoded_byte_array_data_bytes = val; +__isset.unencoded_byte_array_data_bytes = true; +} -uint32_t OffsetIndex::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t OffsetIndex::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_page_locations = false; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->page_locations.clear(); - uint32_t _size130; - ::duckdb_apache::thrift::protocol::TType _etype133; - xfer += iprot->readListBegin(_etype133, _size130); - this->page_locations.resize(_size130); - uint32_t _i134; - for (_i134 = 0; _i134 < _size130; ++_i134) + uint32_t _size160; + ::apache::thrift::protocol::TType _etype163; + xfer += iprot->readListBegin(_etype163, _size160); + this->page_locations.resize(_size160); + uint32_t _i164; + for (_i164 = 0; _i164 < _size160; ++_i164) { - xfer += this->page_locations[_i134].read(iprot); + xfer += this->page_locations[_i164].read(iprot); } xfer += iprot->readListEnd(); } @@ -5496,6 +6258,26 @@ uint32_t OffsetIndex::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) xfer += iprot->skip(ftype); } break; + case 2: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->unencoded_byte_array_data_bytes.clear(); + uint32_t _size165; + ::apache::thrift::protocol::TType _etype168; + xfer += iprot->readListBegin(_etype168, _size165); + this->unencoded_byte_array_data_bytes.resize(_size165); + uint32_t _i169; + for (_i169 = 0; _i169 < _size165; ++_i169) + { + xfer += iprot->readI64(this->unencoded_byte_array_data_bytes[_i169]); + } + xfer += iprot->readListEnd(); + } + this->__isset.unencoded_byte_array_data_bytes = true; + } else { + xfer += iprot->skip(ftype); + } + break; default: xfer += iprot->skip(ftype); break; @@ -5510,23 +6292,36 @@ uint32_t OffsetIndex::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t OffsetIndex::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t OffsetIndex::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("OffsetIndex"); - xfer += oprot->writeFieldBegin("page_locations", ::duckdb_apache::thrift::protocol::T_LIST, 1); + xfer += oprot->writeFieldBegin("page_locations", ::apache::thrift::protocol::T_LIST, 1); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRUCT, static_cast(this->page_locations.size())); - duckdb::vector ::const_iterator _iter135; - for (_iter135 = this->page_locations.begin(); _iter135 != this->page_locations.end(); ++_iter135) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->page_locations.size())); + std::vector ::const_iterator _iter170; + for (_iter170 = this->page_locations.begin(); _iter170 != this->page_locations.end(); ++_iter170) { - xfer += (*_iter135).write(oprot); + xfer += (*_iter170).write(oprot); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); + if (this->__isset.unencoded_byte_array_data_bytes) { + xfer += oprot->writeFieldBegin("unencoded_byte_array_data_bytes", ::apache::thrift::protocol::T_LIST, 2); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->unencoded_byte_array_data_bytes.size())); + std::vector ::const_iterator _iter171; + for (_iter171 = this->unencoded_byte_array_data_bytes.begin(); _iter171 != this->unencoded_byte_array_data_bytes.end(); ++_iter171) + { + xfer += oprot->writeI64((*_iter171)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } xfer += oprot->writeFieldStop(); xfer += oprot->writeStructEnd(); return xfer; @@ -5535,36 +6330,38 @@ uint32_t OffsetIndex::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) void swap(OffsetIndex &a, OffsetIndex &b) { using ::std::swap; swap(a.page_locations, b.page_locations); + swap(a.unencoded_byte_array_data_bytes, b.unencoded_byte_array_data_bytes); + swap(a.__isset, b.__isset); } -OffsetIndex::OffsetIndex(const OffsetIndex& other136) { - page_locations = other136.page_locations; +OffsetIndex::OffsetIndex(const OffsetIndex& other172) { + page_locations = other172.page_locations; + unencoded_byte_array_data_bytes = other172.unencoded_byte_array_data_bytes; + __isset = other172.__isset; } -OffsetIndex& OffsetIndex::operator=(const OffsetIndex& other137) { - page_locations = other137.page_locations; +OffsetIndex& OffsetIndex::operator=(const OffsetIndex& other173) { + page_locations = other173.page_locations; + unencoded_byte_array_data_bytes = other173.unencoded_byte_array_data_bytes; + __isset = other173.__isset; return *this; } -void OffsetIndex::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "OffsetIndex("; - out << "page_locations=" << to_string(page_locations); - out << ")"; -} - -ColumnIndex::~ColumnIndex() throw() { +ColumnIndex::~ColumnIndex() noexcept { } +ColumnIndex::ColumnIndex() noexcept + : boundary_order(static_cast(0)) { +} -void ColumnIndex::__set_null_pages(const duckdb::vector & val) { +void ColumnIndex::__set_null_pages(const std::vector & val) { this->null_pages = val; } -void ColumnIndex::__set_min_values(const duckdb::vector & val) { +void ColumnIndex::__set_min_values(const std::vector & val) { this->min_values = val; } -void ColumnIndex::__set_max_values(const duckdb::vector & val) { +void ColumnIndex::__set_max_values(const std::vector & val) { this->max_values = val; } @@ -5572,28 +6369,32 @@ void ColumnIndex::__set_boundary_order(const BoundaryOrder::type val) { this->boundary_order = val; } -void ColumnIndex::__set_null_counts(const duckdb::vector & val) { +void ColumnIndex::__set_null_counts(const std::vector & val) { this->null_counts = val; __isset.null_counts = true; } -std::ostream& operator<<(std::ostream& out, const ColumnIndex& obj) -{ - obj.printTo(out); - return out; + +void ColumnIndex::__set_repetition_level_histograms(const std::vector & val) { + this->repetition_level_histograms = val; +__isset.repetition_level_histograms = true; } +void ColumnIndex::__set_definition_level_histograms(const std::vector & val) { + this->definition_level_histograms = val; +__isset.definition_level_histograms = true; +} -uint32_t ColumnIndex::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t ColumnIndex::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_null_pages = false; bool isset_min_values = false; @@ -5603,23 +6404,23 @@ uint32_t ColumnIndex::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->null_pages.clear(); - uint32_t _size138; - ::duckdb_apache::thrift::protocol::TType _etype141; - xfer += iprot->readListBegin(_etype141, _size138); - this->null_pages.resize(_size138); - uint32_t _i142; - for (_i142 = 0; _i142 < _size138; ++_i142) + uint32_t _size174; + ::apache::thrift::protocol::TType _etype177; + xfer += iprot->readListBegin(_etype177, _size174); + this->null_pages.resize(_size174); + uint32_t _i178; + for (_i178 = 0; _i178 < _size174; ++_i178) { - xfer += iprot->readBool(this->null_pages[_i142]); + xfer += iprot->readBool(this->null_pages[_i178]); } xfer += iprot->readListEnd(); } @@ -5629,17 +6430,17 @@ uint32_t ColumnIndex::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->min_values.clear(); - uint32_t _size143; - ::duckdb_apache::thrift::protocol::TType _etype146; - xfer += iprot->readListBegin(_etype146, _size143); - this->min_values.resize(_size143); - uint32_t _i147; - for (_i147 = 0; _i147 < _size143; ++_i147) + uint32_t _size179; + ::apache::thrift::protocol::TType _etype182; + xfer += iprot->readListBegin(_etype182, _size179); + this->min_values.resize(_size179); + uint32_t _i183; + for (_i183 = 0; _i183 < _size179; ++_i183) { - xfer += iprot->readBinary(this->min_values[_i147]); + xfer += iprot->readBinary(this->min_values[_i183]); } xfer += iprot->readListEnd(); } @@ -5649,17 +6450,17 @@ uint32_t ColumnIndex::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->max_values.clear(); - uint32_t _size148; - ::duckdb_apache::thrift::protocol::TType _etype151; - xfer += iprot->readListBegin(_etype151, _size148); - this->max_values.resize(_size148); - uint32_t _i152; - for (_i152 = 0; _i152 < _size148; ++_i152) + uint32_t _size184; + ::apache::thrift::protocol::TType _etype187; + xfer += iprot->readListBegin(_etype187, _size184); + this->max_values.resize(_size184); + uint32_t _i188; + for (_i188 = 0; _i188 < _size184; ++_i188) { - xfer += iprot->readBinary(this->max_values[_i152]); + xfer += iprot->readBinary(this->max_values[_i188]); } xfer += iprot->readListEnd(); } @@ -5669,27 +6470,27 @@ uint32_t ColumnIndex::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { - int32_t ecast153; - xfer += iprot->readI32(ecast153); - this->boundary_order = (BoundaryOrder::type)ecast153; + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast189; + xfer += iprot->readI32(ecast189); + this->boundary_order = static_cast(ecast189); isset_boundary_order = true; } else { xfer += iprot->skip(ftype); } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->null_counts.clear(); - uint32_t _size154; - ::duckdb_apache::thrift::protocol::TType _etype157; - xfer += iprot->readListBegin(_etype157, _size154); - this->null_counts.resize(_size154); - uint32_t _i158; - for (_i158 = 0; _i158 < _size154; ++_i158) + uint32_t _size190; + ::apache::thrift::protocol::TType _etype193; + xfer += iprot->readListBegin(_etype193, _size190); + this->null_counts.resize(_size190); + uint32_t _i194; + for (_i194 = 0; _i194 < _size190; ++_i194) { - xfer += iprot->readI64(this->null_counts[_i158]); + xfer += iprot->readI64(this->null_counts[_i194]); } xfer += iprot->readListEnd(); } @@ -5698,6 +6499,46 @@ uint32_t ColumnIndex::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) xfer += iprot->skip(ftype); } break; + case 6: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->repetition_level_histograms.clear(); + uint32_t _size195; + ::apache::thrift::protocol::TType _etype198; + xfer += iprot->readListBegin(_etype198, _size195); + this->repetition_level_histograms.resize(_size195); + uint32_t _i199; + for (_i199 = 0; _i199 < _size195; ++_i199) + { + xfer += iprot->readI64(this->repetition_level_histograms[_i199]); + } + xfer += iprot->readListEnd(); + } + this->__isset.repetition_level_histograms = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->definition_level_histograms.clear(); + uint32_t _size200; + ::apache::thrift::protocol::TType _etype203; + xfer += iprot->readListBegin(_etype203, _size200); + this->definition_level_histograms.resize(_size200); + uint32_t _i204; + for (_i204 = 0; _i204 < _size200; ++_i204) + { + xfer += iprot->readI64(this->definition_level_histograms[_i204]); + } + xfer += iprot->readListEnd(); + } + this->__isset.definition_level_histograms = true; + } else { + xfer += iprot->skip(ftype); + } + break; default: xfer += iprot->skip(ftype); break; @@ -5718,59 +6559,85 @@ uint32_t ColumnIndex::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t ColumnIndex::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t ColumnIndex::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("ColumnIndex"); - xfer += oprot->writeFieldBegin("null_pages", ::duckdb_apache::thrift::protocol::T_LIST, 1); + xfer += oprot->writeFieldBegin("null_pages", ::apache::thrift::protocol::T_LIST, 1); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_BOOL, static_cast(this->null_pages.size())); - duckdb::vector ::const_iterator _iter159; - for (_iter159 = this->null_pages.begin(); _iter159 != this->null_pages.end(); ++_iter159) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_BOOL, static_cast(this->null_pages.size())); + std::vector ::const_iterator _iter205; + for (_iter205 = this->null_pages.begin(); _iter205 != this->null_pages.end(); ++_iter205) { - xfer += oprot->writeBool((*_iter159)); + xfer += oprot->writeBool((*_iter205)); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("min_values", ::duckdb_apache::thrift::protocol::T_LIST, 2); + xfer += oprot->writeFieldBegin("min_values", ::apache::thrift::protocol::T_LIST, 2); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRING, static_cast(this->min_values.size())); - duckdb::vector ::const_iterator _iter160; - for (_iter160 = this->min_values.begin(); _iter160 != this->min_values.end(); ++_iter160) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->min_values.size())); + std::vector ::const_iterator _iter206; + for (_iter206 = this->min_values.begin(); _iter206 != this->min_values.end(); ++_iter206) { - xfer += oprot->writeBinary((*_iter160)); + xfer += oprot->writeBinary((*_iter206)); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("max_values", ::duckdb_apache::thrift::protocol::T_LIST, 3); + xfer += oprot->writeFieldBegin("max_values", ::apache::thrift::protocol::T_LIST, 3); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRING, static_cast(this->max_values.size())); - duckdb::vector ::const_iterator _iter161; - for (_iter161 = this->max_values.begin(); _iter161 != this->max_values.end(); ++_iter161) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->max_values.size())); + std::vector ::const_iterator _iter207; + for (_iter207 = this->max_values.begin(); _iter207 != this->max_values.end(); ++_iter207) { - xfer += oprot->writeBinary((*_iter161)); + xfer += oprot->writeBinary((*_iter207)); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("boundary_order", ::duckdb_apache::thrift::protocol::T_I32, 4); - xfer += oprot->writeI32((int32_t)this->boundary_order); + xfer += oprot->writeFieldBegin("boundary_order", ::apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(static_cast(this->boundary_order)); xfer += oprot->writeFieldEnd(); if (this->__isset.null_counts) { - xfer += oprot->writeFieldBegin("null_counts", ::duckdb_apache::thrift::protocol::T_LIST, 5); + xfer += oprot->writeFieldBegin("null_counts", ::apache::thrift::protocol::T_LIST, 5); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->null_counts.size())); + std::vector ::const_iterator _iter208; + for (_iter208 = this->null_counts.begin(); _iter208 != this->null_counts.end(); ++_iter208) + { + xfer += oprot->writeI64((*_iter208)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.repetition_level_histograms) { + xfer += oprot->writeFieldBegin("repetition_level_histograms", ::apache::thrift::protocol::T_LIST, 6); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->repetition_level_histograms.size())); + std::vector ::const_iterator _iter209; + for (_iter209 = this->repetition_level_histograms.begin(); _iter209 != this->repetition_level_histograms.end(); ++_iter209) + { + xfer += oprot->writeI64((*_iter209)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.definition_level_histograms) { + xfer += oprot->writeFieldBegin("definition_level_histograms", ::apache::thrift::protocol::T_LIST, 7); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_I64, static_cast(this->null_counts.size())); - duckdb::vector ::const_iterator _iter162; - for (_iter162 = this->null_counts.begin(); _iter162 != this->null_counts.end(); ++_iter162) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->definition_level_histograms.size())); + std::vector ::const_iterator _iter210; + for (_iter210 = this->definition_level_histograms.begin(); _iter210 != this->definition_level_histograms.end(); ++_iter210) { - xfer += oprot->writeI64((*_iter162)); + xfer += oprot->writeI64((*_iter210)); } xfer += oprot->writeListEnd(); } @@ -5788,41 +6655,41 @@ void swap(ColumnIndex &a, ColumnIndex &b) { swap(a.max_values, b.max_values); swap(a.boundary_order, b.boundary_order); swap(a.null_counts, b.null_counts); + swap(a.repetition_level_histograms, b.repetition_level_histograms); + swap(a.definition_level_histograms, b.definition_level_histograms); swap(a.__isset, b.__isset); } -ColumnIndex::ColumnIndex(const ColumnIndex& other163) { - null_pages = other163.null_pages; - min_values = other163.min_values; - max_values = other163.max_values; - boundary_order = other163.boundary_order; - null_counts = other163.null_counts; - __isset = other163.__isset; -} -ColumnIndex& ColumnIndex::operator=(const ColumnIndex& other164) { - null_pages = other164.null_pages; - min_values = other164.min_values; - max_values = other164.max_values; - boundary_order = other164.boundary_order; - null_counts = other164.null_counts; - __isset = other164.__isset; +ColumnIndex::ColumnIndex(const ColumnIndex& other211) { + null_pages = other211.null_pages; + min_values = other211.min_values; + max_values = other211.max_values; + boundary_order = other211.boundary_order; + null_counts = other211.null_counts; + repetition_level_histograms = other211.repetition_level_histograms; + definition_level_histograms = other211.definition_level_histograms; + __isset = other211.__isset; +} +ColumnIndex& ColumnIndex::operator=(const ColumnIndex& other212) { + null_pages = other212.null_pages; + min_values = other212.min_values; + max_values = other212.max_values; + boundary_order = other212.boundary_order; + null_counts = other212.null_counts; + repetition_level_histograms = other212.repetition_level_histograms; + definition_level_histograms = other212.definition_level_histograms; + __isset = other212.__isset; return *this; } -void ColumnIndex::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "ColumnIndex("; - out << "null_pages=" << to_string(null_pages); - out << ", " << "min_values=" << to_string(min_values); - out << ", " << "max_values=" << to_string(max_values); - out << ", " << "boundary_order=" << to_string(boundary_order); - out << ", " << "null_counts="; (__isset.null_counts ? (out << to_string(null_counts)) : (out << "")); - out << ")"; -} - -AesGcmV1::~AesGcmV1() throw() { +AesGcmV1::~AesGcmV1() noexcept { } +AesGcmV1::AesGcmV1() noexcept + : aad_prefix(), + aad_file_unique(), + supply_aad_prefix(0) { +} void AesGcmV1::__set_aad_prefix(const std::string& val) { this->aad_prefix = val; @@ -5838,36 +6705,30 @@ void AesGcmV1::__set_supply_aad_prefix(const bool val) { this->supply_aad_prefix = val; __isset.supply_aad_prefix = true; } -std::ostream& operator<<(std::ostream& out, const AesGcmV1& obj) -{ - obj.printTo(out); - return out; -} - -uint32_t AesGcmV1::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t AesGcmV1::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->aad_prefix); this->__isset.aad_prefix = true; } else { @@ -5875,7 +6736,7 @@ uint32_t AesGcmV1::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->aad_file_unique); this->__isset.aad_file_unique = true; } else { @@ -5883,7 +6744,7 @@ uint32_t AesGcmV1::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_BOOL) { + if (ftype == ::apache::thrift::protocol::T_BOOL) { xfer += iprot->readBool(this->supply_aad_prefix); this->__isset.supply_aad_prefix = true; } else { @@ -5902,23 +6763,23 @@ uint32_t AesGcmV1::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { return xfer; } -uint32_t AesGcmV1::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t AesGcmV1::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("AesGcmV1"); if (this->__isset.aad_prefix) { - xfer += oprot->writeFieldBegin("aad_prefix", ::duckdb_apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeFieldBegin("aad_prefix", ::apache::thrift::protocol::T_STRING, 1); xfer += oprot->writeBinary(this->aad_prefix); xfer += oprot->writeFieldEnd(); } if (this->__isset.aad_file_unique) { - xfer += oprot->writeFieldBegin("aad_file_unique", ::duckdb_apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeFieldBegin("aad_file_unique", ::apache::thrift::protocol::T_STRING, 2); xfer += oprot->writeBinary(this->aad_file_unique); xfer += oprot->writeFieldEnd(); } if (this->__isset.supply_aad_prefix) { - xfer += oprot->writeFieldBegin("supply_aad_prefix", ::duckdb_apache::thrift::protocol::T_BOOL, 3); + xfer += oprot->writeFieldBegin("supply_aad_prefix", ::apache::thrift::protocol::T_BOOL, 3); xfer += oprot->writeBool(this->supply_aad_prefix); xfer += oprot->writeFieldEnd(); } @@ -5935,32 +6796,28 @@ void swap(AesGcmV1 &a, AesGcmV1 &b) { swap(a.__isset, b.__isset); } -AesGcmV1::AesGcmV1(const AesGcmV1& other165) { - aad_prefix = other165.aad_prefix; - aad_file_unique = other165.aad_file_unique; - supply_aad_prefix = other165.supply_aad_prefix; - __isset = other165.__isset; +AesGcmV1::AesGcmV1(const AesGcmV1& other213) { + aad_prefix = other213.aad_prefix; + aad_file_unique = other213.aad_file_unique; + supply_aad_prefix = other213.supply_aad_prefix; + __isset = other213.__isset; } -AesGcmV1& AesGcmV1::operator=(const AesGcmV1& other166) { - aad_prefix = other166.aad_prefix; - aad_file_unique = other166.aad_file_unique; - supply_aad_prefix = other166.supply_aad_prefix; - __isset = other166.__isset; +AesGcmV1& AesGcmV1::operator=(const AesGcmV1& other214) { + aad_prefix = other214.aad_prefix; + aad_file_unique = other214.aad_file_unique; + supply_aad_prefix = other214.supply_aad_prefix; + __isset = other214.__isset; return *this; } -void AesGcmV1::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "AesGcmV1("; - out << "aad_prefix="; (__isset.aad_prefix ? (out << to_string(aad_prefix)) : (out << "")); - out << ", " << "aad_file_unique="; (__isset.aad_file_unique ? (out << to_string(aad_file_unique)) : (out << "")); - out << ", " << "supply_aad_prefix="; (__isset.supply_aad_prefix ? (out << to_string(supply_aad_prefix)) : (out << "")); - out << ")"; -} - -AesGcmCtrV1::~AesGcmCtrV1() throw() { +AesGcmCtrV1::~AesGcmCtrV1() noexcept { } +AesGcmCtrV1::AesGcmCtrV1() noexcept + : aad_prefix(), + aad_file_unique(), + supply_aad_prefix(0) { +} void AesGcmCtrV1::__set_aad_prefix(const std::string& val) { this->aad_prefix = val; @@ -5976,36 +6833,30 @@ void AesGcmCtrV1::__set_supply_aad_prefix(const bool val) { this->supply_aad_prefix = val; __isset.supply_aad_prefix = true; } -std::ostream& operator<<(std::ostream& out, const AesGcmCtrV1& obj) -{ - obj.printTo(out); - return out; -} +uint32_t AesGcmCtrV1::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t AesGcmCtrV1::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->aad_prefix); this->__isset.aad_prefix = true; } else { @@ -6013,7 +6864,7 @@ uint32_t AesGcmCtrV1::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->aad_file_unique); this->__isset.aad_file_unique = true; } else { @@ -6021,7 +6872,7 @@ uint32_t AesGcmCtrV1::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_BOOL) { + if (ftype == ::apache::thrift::protocol::T_BOOL) { xfer += iprot->readBool(this->supply_aad_prefix); this->__isset.supply_aad_prefix = true; } else { @@ -6040,23 +6891,23 @@ uint32_t AesGcmCtrV1::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t AesGcmCtrV1::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t AesGcmCtrV1::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("AesGcmCtrV1"); if (this->__isset.aad_prefix) { - xfer += oprot->writeFieldBegin("aad_prefix", ::duckdb_apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeFieldBegin("aad_prefix", ::apache::thrift::protocol::T_STRING, 1); xfer += oprot->writeBinary(this->aad_prefix); xfer += oprot->writeFieldEnd(); } if (this->__isset.aad_file_unique) { - xfer += oprot->writeFieldBegin("aad_file_unique", ::duckdb_apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeFieldBegin("aad_file_unique", ::apache::thrift::protocol::T_STRING, 2); xfer += oprot->writeBinary(this->aad_file_unique); xfer += oprot->writeFieldEnd(); } if (this->__isset.supply_aad_prefix) { - xfer += oprot->writeFieldBegin("supply_aad_prefix", ::duckdb_apache::thrift::protocol::T_BOOL, 3); + xfer += oprot->writeFieldBegin("supply_aad_prefix", ::apache::thrift::protocol::T_BOOL, 3); xfer += oprot->writeBool(this->supply_aad_prefix); xfer += oprot->writeFieldEnd(); } @@ -6073,32 +6924,25 @@ void swap(AesGcmCtrV1 &a, AesGcmCtrV1 &b) { swap(a.__isset, b.__isset); } -AesGcmCtrV1::AesGcmCtrV1(const AesGcmCtrV1& other167) { - aad_prefix = other167.aad_prefix; - aad_file_unique = other167.aad_file_unique; - supply_aad_prefix = other167.supply_aad_prefix; - __isset = other167.__isset; +AesGcmCtrV1::AesGcmCtrV1(const AesGcmCtrV1& other215) { + aad_prefix = other215.aad_prefix; + aad_file_unique = other215.aad_file_unique; + supply_aad_prefix = other215.supply_aad_prefix; + __isset = other215.__isset; } -AesGcmCtrV1& AesGcmCtrV1::operator=(const AesGcmCtrV1& other168) { - aad_prefix = other168.aad_prefix; - aad_file_unique = other168.aad_file_unique; - supply_aad_prefix = other168.supply_aad_prefix; - __isset = other168.__isset; +AesGcmCtrV1& AesGcmCtrV1::operator=(const AesGcmCtrV1& other216) { + aad_prefix = other216.aad_prefix; + aad_file_unique = other216.aad_file_unique; + supply_aad_prefix = other216.supply_aad_prefix; + __isset = other216.__isset; return *this; } -void AesGcmCtrV1::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "AesGcmCtrV1("; - out << "aad_prefix="; (__isset.aad_prefix ? (out << to_string(aad_prefix)) : (out << "")); - out << ", " << "aad_file_unique="; (__isset.aad_file_unique ? (out << to_string(aad_file_unique)) : (out << "")); - out << ", " << "supply_aad_prefix="; (__isset.supply_aad_prefix ? (out << to_string(supply_aad_prefix)) : (out << "")); - out << ")"; -} - -EncryptionAlgorithm::~EncryptionAlgorithm() throw() { +EncryptionAlgorithm::~EncryptionAlgorithm() noexcept { } +EncryptionAlgorithm::EncryptionAlgorithm() noexcept { +} void EncryptionAlgorithm::__set_AES_GCM_V1(const AesGcmV1& val) { this->AES_GCM_V1 = val; @@ -6109,36 +6953,30 @@ void EncryptionAlgorithm::__set_AES_GCM_CTR_V1(const AesGcmCtrV1& val) { this->AES_GCM_CTR_V1 = val; __isset.AES_GCM_CTR_V1 = true; } -std::ostream& operator<<(std::ostream& out, const EncryptionAlgorithm& obj) -{ - obj.printTo(out); - return out; -} - -uint32_t EncryptionAlgorithm::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { +uint32_t EncryptionAlgorithm::read(::apache::thrift::protocol::TProtocol* iprot) { - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->AES_GCM_V1.read(iprot); this->__isset.AES_GCM_V1 = true; } else { @@ -6146,7 +6984,7 @@ uint32_t EncryptionAlgorithm::read(::duckdb_apache::thrift::protocol::TProtocol* } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->AES_GCM_CTR_V1.read(iprot); this->__isset.AES_GCM_CTR_V1 = true; } else { @@ -6165,18 +7003,18 @@ uint32_t EncryptionAlgorithm::read(::duckdb_apache::thrift::protocol::TProtocol* return xfer; } -uint32_t EncryptionAlgorithm::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t EncryptionAlgorithm::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("EncryptionAlgorithm"); if (this->__isset.AES_GCM_V1) { - xfer += oprot->writeFieldBegin("AES_GCM_V1", ::duckdb_apache::thrift::protocol::T_STRUCT, 1); + xfer += oprot->writeFieldBegin("AES_GCM_V1", ::apache::thrift::protocol::T_STRUCT, 1); xfer += this->AES_GCM_V1.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.AES_GCM_CTR_V1) { - xfer += oprot->writeFieldBegin("AES_GCM_CTR_V1", ::duckdb_apache::thrift::protocol::T_STRUCT, 2); + xfer += oprot->writeFieldBegin("AES_GCM_CTR_V1", ::apache::thrift::protocol::T_STRUCT, 2); xfer += this->AES_GCM_CTR_V1.write(oprot); xfer += oprot->writeFieldEnd(); } @@ -6192,35 +7030,33 @@ void swap(EncryptionAlgorithm &a, EncryptionAlgorithm &b) { swap(a.__isset, b.__isset); } -EncryptionAlgorithm::EncryptionAlgorithm(const EncryptionAlgorithm& other169) { - AES_GCM_V1 = other169.AES_GCM_V1; - AES_GCM_CTR_V1 = other169.AES_GCM_CTR_V1; - __isset = other169.__isset; +EncryptionAlgorithm::EncryptionAlgorithm(const EncryptionAlgorithm& other217) { + AES_GCM_V1 = other217.AES_GCM_V1; + AES_GCM_CTR_V1 = other217.AES_GCM_CTR_V1; + __isset = other217.__isset; } -EncryptionAlgorithm& EncryptionAlgorithm::operator=(const EncryptionAlgorithm& other170) { - AES_GCM_V1 = other170.AES_GCM_V1; - AES_GCM_CTR_V1 = other170.AES_GCM_CTR_V1; - __isset = other170.__isset; +EncryptionAlgorithm& EncryptionAlgorithm::operator=(const EncryptionAlgorithm& other218) { + AES_GCM_V1 = other218.AES_GCM_V1; + AES_GCM_CTR_V1 = other218.AES_GCM_CTR_V1; + __isset = other218.__isset; return *this; } -void EncryptionAlgorithm::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "EncryptionAlgorithm("; - out << "AES_GCM_V1="; (__isset.AES_GCM_V1 ? (out << to_string(AES_GCM_V1)) : (out << "")); - out << ", " << "AES_GCM_CTR_V1="; (__isset.AES_GCM_CTR_V1 ? (out << to_string(AES_GCM_CTR_V1)) : (out << "")); - out << ")"; -} - -FileMetaData::~FileMetaData() throw() { +FileMetaData::~FileMetaData() noexcept { } +FileMetaData::FileMetaData() noexcept + : version(0), + num_rows(0), + created_by(), + footer_signing_key_metadata() { +} void FileMetaData::__set_version(const int32_t val) { this->version = val; } -void FileMetaData::__set_schema(const duckdb::vector & val) { +void FileMetaData::__set_schema(const std::vector & val) { this->schema = val; } @@ -6228,11 +7064,11 @@ void FileMetaData::__set_num_rows(const int64_t val) { this->num_rows = val; } -void FileMetaData::__set_row_groups(const duckdb::vector & val) { +void FileMetaData::__set_row_groups(const std::vector & val) { this->row_groups = val; } -void FileMetaData::__set_key_value_metadata(const duckdb::vector & val) { +void FileMetaData::__set_key_value_metadata(const std::vector & val) { this->key_value_metadata = val; __isset.key_value_metadata = true; } @@ -6242,7 +7078,7 @@ void FileMetaData::__set_created_by(const std::string& val) { __isset.created_by = true; } -void FileMetaData::__set_column_orders(const duckdb::vector & val) { +void FileMetaData::__set_column_orders(const std::vector & val) { this->column_orders = val; __isset.column_orders = true; } @@ -6256,24 +7092,18 @@ void FileMetaData::__set_footer_signing_key_metadata(const std::string& val) { this->footer_signing_key_metadata = val; __isset.footer_signing_key_metadata = true; } -std::ostream& operator<<(std::ostream& out, const FileMetaData& obj) -{ - obj.printTo(out); - return out; -} +uint32_t FileMetaData::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_version = false; bool isset_schema = false; @@ -6283,13 +7113,13 @@ uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_I32) { + if (ftype == ::apache::thrift::protocol::T_I32) { xfer += iprot->readI32(this->version); isset_version = true; } else { @@ -6297,17 +7127,17 @@ uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->schema.clear(); - uint32_t _size171; - ::duckdb_apache::thrift::protocol::TType _etype174; - xfer += iprot->readListBegin(_etype174, _size171); - this->schema.resize(_size171); - uint32_t _i175; - for (_i175 = 0; _i175 < _size171; ++_i175) + uint32_t _size219; + ::apache::thrift::protocol::TType _etype222; + xfer += iprot->readListBegin(_etype222, _size219); + this->schema.resize(_size219); + uint32_t _i223; + for (_i223 = 0; _i223 < _size219; ++_i223) { - xfer += this->schema[_i175].read(iprot); + xfer += this->schema[_i223].read(iprot); } xfer += iprot->readListEnd(); } @@ -6317,7 +7147,7 @@ uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 3: - if (ftype == ::duckdb_apache::thrift::protocol::T_I64) { + if (ftype == ::apache::thrift::protocol::T_I64) { xfer += iprot->readI64(this->num_rows); isset_num_rows = true; } else { @@ -6325,17 +7155,17 @@ uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 4: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->row_groups.clear(); - uint32_t _size176; - ::duckdb_apache::thrift::protocol::TType _etype179; - xfer += iprot->readListBegin(_etype179, _size176); - this->row_groups.resize(_size176); - uint32_t _i180; - for (_i180 = 0; _i180 < _size176; ++_i180) + uint32_t _size224; + ::apache::thrift::protocol::TType _etype227; + xfer += iprot->readListBegin(_etype227, _size224); + this->row_groups.resize(_size224); + uint32_t _i228; + for (_i228 = 0; _i228 < _size224; ++_i228) { - xfer += this->row_groups[_i180].read(iprot); + xfer += this->row_groups[_i228].read(iprot); } xfer += iprot->readListEnd(); } @@ -6345,17 +7175,17 @@ uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 5: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->key_value_metadata.clear(); - uint32_t _size181; - ::duckdb_apache::thrift::protocol::TType _etype184; - xfer += iprot->readListBegin(_etype184, _size181); - this->key_value_metadata.resize(_size181); - uint32_t _i185; - for (_i185 = 0; _i185 < _size181; ++_i185) + uint32_t _size229; + ::apache::thrift::protocol::TType _etype232; + xfer += iprot->readListBegin(_etype232, _size229); + this->key_value_metadata.resize(_size229); + uint32_t _i233; + for (_i233 = 0; _i233 < _size229; ++_i233) { - xfer += this->key_value_metadata[_i185].read(iprot); + xfer += this->key_value_metadata[_i233].read(iprot); } xfer += iprot->readListEnd(); } @@ -6365,7 +7195,7 @@ uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 6: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readString(this->created_by); this->__isset.created_by = true; } else { @@ -6373,17 +7203,17 @@ uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 7: - if (ftype == ::duckdb_apache::thrift::protocol::T_LIST) { + if (ftype == ::apache::thrift::protocol::T_LIST) { { this->column_orders.clear(); - uint32_t _size186; - ::duckdb_apache::thrift::protocol::TType _etype189; - xfer += iprot->readListBegin(_etype189, _size186); - this->column_orders.resize(_size186); - uint32_t _i190; - for (_i190 = 0; _i190 < _size186; ++_i190) + uint32_t _size234; + ::apache::thrift::protocol::TType _etype237; + xfer += iprot->readListBegin(_etype237, _size234); + this->column_orders.resize(_size234); + uint32_t _i238; + for (_i238 = 0; _i238 < _size234; ++_i238) { - xfer += this->column_orders[_i190].read(iprot); + xfer += this->column_orders[_i238].read(iprot); } xfer += iprot->readListEnd(); } @@ -6393,7 +7223,7 @@ uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 8: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->encryption_algorithm.read(iprot); this->__isset.encryption_algorithm = true; } else { @@ -6401,7 +7231,7 @@ uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) } break; case 9: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->footer_signing_key_metadata); this->__isset.footer_signing_key_metadata = true; } else { @@ -6428,81 +7258,81 @@ uint32_t FileMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) return xfer; } -uint32_t FileMetaData::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t FileMetaData::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("FileMetaData"); - xfer += oprot->writeFieldBegin("version", ::duckdb_apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_I32, 1); xfer += oprot->writeI32(this->version); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("schema", ::duckdb_apache::thrift::protocol::T_LIST, 2); + xfer += oprot->writeFieldBegin("schema", ::apache::thrift::protocol::T_LIST, 2); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRUCT, static_cast(this->schema.size())); - duckdb::vector ::const_iterator _iter191; - for (_iter191 = this->schema.begin(); _iter191 != this->schema.end(); ++_iter191) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->schema.size())); + std::vector ::const_iterator _iter239; + for (_iter239 = this->schema.begin(); _iter239 != this->schema.end(); ++_iter239) { - xfer += (*_iter191).write(oprot); + xfer += (*_iter239).write(oprot); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("num_rows", ::duckdb_apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeFieldBegin("num_rows", ::apache::thrift::protocol::T_I64, 3); xfer += oprot->writeI64(this->num_rows); xfer += oprot->writeFieldEnd(); - xfer += oprot->writeFieldBegin("row_groups", ::duckdb_apache::thrift::protocol::T_LIST, 4); + xfer += oprot->writeFieldBegin("row_groups", ::apache::thrift::protocol::T_LIST, 4); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRUCT, static_cast(this->row_groups.size())); - duckdb::vector ::const_iterator _iter192; - for (_iter192 = this->row_groups.begin(); _iter192 != this->row_groups.end(); ++_iter192) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->row_groups.size())); + std::vector ::const_iterator _iter240; + for (_iter240 = this->row_groups.begin(); _iter240 != this->row_groups.end(); ++_iter240) { - xfer += (*_iter192).write(oprot); + xfer += (*_iter240).write(oprot); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); if (this->__isset.key_value_metadata) { - xfer += oprot->writeFieldBegin("key_value_metadata", ::duckdb_apache::thrift::protocol::T_LIST, 5); + xfer += oprot->writeFieldBegin("key_value_metadata", ::apache::thrift::protocol::T_LIST, 5); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRUCT, static_cast(this->key_value_metadata.size())); - duckdb::vector ::const_iterator _iter193; - for (_iter193 = this->key_value_metadata.begin(); _iter193 != this->key_value_metadata.end(); ++_iter193) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->key_value_metadata.size())); + std::vector ::const_iterator _iter241; + for (_iter241 = this->key_value_metadata.begin(); _iter241 != this->key_value_metadata.end(); ++_iter241) { - xfer += (*_iter193).write(oprot); + xfer += (*_iter241).write(oprot); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); } if (this->__isset.created_by) { - xfer += oprot->writeFieldBegin("created_by", ::duckdb_apache::thrift::protocol::T_STRING, 6); + xfer += oprot->writeFieldBegin("created_by", ::apache::thrift::protocol::T_STRING, 6); xfer += oprot->writeString(this->created_by); xfer += oprot->writeFieldEnd(); } if (this->__isset.column_orders) { - xfer += oprot->writeFieldBegin("column_orders", ::duckdb_apache::thrift::protocol::T_LIST, 7); + xfer += oprot->writeFieldBegin("column_orders", ::apache::thrift::protocol::T_LIST, 7); { - xfer += oprot->writeListBegin(::duckdb_apache::thrift::protocol::T_STRUCT, static_cast(this->column_orders.size())); - duckdb::vector ::const_iterator _iter194; - for (_iter194 = this->column_orders.begin(); _iter194 != this->column_orders.end(); ++_iter194) + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->column_orders.size())); + std::vector ::const_iterator _iter242; + for (_iter242 = this->column_orders.begin(); _iter242 != this->column_orders.end(); ++_iter242) { - xfer += (*_iter194).write(oprot); + xfer += (*_iter242).write(oprot); } xfer += oprot->writeListEnd(); } xfer += oprot->writeFieldEnd(); } if (this->__isset.encryption_algorithm) { - xfer += oprot->writeFieldBegin("encryption_algorithm", ::duckdb_apache::thrift::protocol::T_STRUCT, 8); + xfer += oprot->writeFieldBegin("encryption_algorithm", ::apache::thrift::protocol::T_STRUCT, 8); xfer += this->encryption_algorithm.write(oprot); xfer += oprot->writeFieldEnd(); } if (this->__isset.footer_signing_key_metadata) { - xfer += oprot->writeFieldBegin("footer_signing_key_metadata", ::duckdb_apache::thrift::protocol::T_STRING, 9); + xfer += oprot->writeFieldBegin("footer_signing_key_metadata", ::apache::thrift::protocol::T_STRING, 9); xfer += oprot->writeBinary(this->footer_signing_key_metadata); xfer += oprot->writeFieldEnd(); } @@ -6525,52 +7355,39 @@ void swap(FileMetaData &a, FileMetaData &b) { swap(a.__isset, b.__isset); } -FileMetaData::FileMetaData(const FileMetaData& other195) { - version = other195.version; - schema = other195.schema; - num_rows = other195.num_rows; - row_groups = other195.row_groups; - key_value_metadata = other195.key_value_metadata; - created_by = other195.created_by; - column_orders = other195.column_orders; - encryption_algorithm = other195.encryption_algorithm; - footer_signing_key_metadata = other195.footer_signing_key_metadata; - __isset = other195.__isset; -} -FileMetaData& FileMetaData::operator=(const FileMetaData& other196) { - version = other196.version; - schema = other196.schema; - num_rows = other196.num_rows; - row_groups = other196.row_groups; - key_value_metadata = other196.key_value_metadata; - created_by = other196.created_by; - column_orders = other196.column_orders; - encryption_algorithm = other196.encryption_algorithm; - footer_signing_key_metadata = other196.footer_signing_key_metadata; - __isset = other196.__isset; +FileMetaData::FileMetaData(const FileMetaData& other243) { + version = other243.version; + schema = other243.schema; + num_rows = other243.num_rows; + row_groups = other243.row_groups; + key_value_metadata = other243.key_value_metadata; + created_by = other243.created_by; + column_orders = other243.column_orders; + encryption_algorithm = other243.encryption_algorithm; + footer_signing_key_metadata = other243.footer_signing_key_metadata; + __isset = other243.__isset; +} +FileMetaData& FileMetaData::operator=(const FileMetaData& other244) { + version = other244.version; + schema = other244.schema; + num_rows = other244.num_rows; + row_groups = other244.row_groups; + key_value_metadata = other244.key_value_metadata; + created_by = other244.created_by; + column_orders = other244.column_orders; + encryption_algorithm = other244.encryption_algorithm; + footer_signing_key_metadata = other244.footer_signing_key_metadata; + __isset = other244.__isset; return *this; } -void FileMetaData::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "FileMetaData("; - out << "version=" << to_string(version); - out << ", " << "schema=" << to_string(schema); - out << ", " << "num_rows=" << to_string(num_rows); - out << ", " << "row_groups=" << to_string(row_groups); - out << ", " << "key_value_metadata="; (__isset.key_value_metadata ? (out << to_string(key_value_metadata)) : (out << "")); - out << ", " << "created_by="; (__isset.created_by ? (out << to_string(created_by)) : (out << "")); - out << ", " << "column_orders="; (__isset.column_orders ? (out << to_string(column_orders)) : (out << "")); - out << ", " << "encryption_algorithm="; (__isset.encryption_algorithm ? (out << to_string(encryption_algorithm)) : (out << "")); - out << ", " << "footer_signing_key_metadata="; (__isset.footer_signing_key_metadata ? (out << to_string(footer_signing_key_metadata)) : (out << "")); - out << ")"; +FileCryptoMetaData::~FileCryptoMetaData() noexcept { } - -FileCryptoMetaData::~FileCryptoMetaData() throw() { +FileCryptoMetaData::FileCryptoMetaData() noexcept + : key_metadata() { } - void FileCryptoMetaData::__set_encryption_algorithm(const EncryptionAlgorithm& val) { this->encryption_algorithm = val; } @@ -6579,37 +7396,31 @@ void FileCryptoMetaData::__set_key_metadata(const std::string& val) { this->key_metadata = val; __isset.key_metadata = true; } -std::ostream& operator<<(std::ostream& out, const FileCryptoMetaData& obj) -{ - obj.printTo(out); - return out; -} +uint32_t FileCryptoMetaData::read(::apache::thrift::protocol::TProtocol* iprot) { -uint32_t FileCryptoMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* iprot) { - - ::duckdb_apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); + ::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); uint32_t xfer = 0; std::string fname; - ::duckdb_apache::thrift::protocol::TType ftype; + ::apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); - using ::duckdb_apache::thrift::protocol::TProtocolException; + using ::apache::thrift::protocol::TProtocolException; bool isset_encryption_algorithm = false; while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); - if (ftype == ::duckdb_apache::thrift::protocol::T_STOP) { + if (ftype == ::apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRUCT) { + if (ftype == ::apache::thrift::protocol::T_STRUCT) { xfer += this->encryption_algorithm.read(iprot); isset_encryption_algorithm = true; } else { @@ -6617,7 +7428,7 @@ uint32_t FileCryptoMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* } break; case 2: - if (ftype == ::duckdb_apache::thrift::protocol::T_STRING) { + if (ftype == ::apache::thrift::protocol::T_STRING) { xfer += iprot->readBinary(this->key_metadata); this->__isset.key_metadata = true; } else { @@ -6638,17 +7449,17 @@ uint32_t FileCryptoMetaData::read(::duckdb_apache::thrift::protocol::TProtocol* return xfer; } -uint32_t FileCryptoMetaData::write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const { +uint32_t FileCryptoMetaData::write(::apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; - ::duckdb_apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); + ::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); xfer += oprot->writeStructBegin("FileCryptoMetaData"); - xfer += oprot->writeFieldBegin("encryption_algorithm", ::duckdb_apache::thrift::protocol::T_STRUCT, 1); + xfer += oprot->writeFieldBegin("encryption_algorithm", ::apache::thrift::protocol::T_STRUCT, 1); xfer += this->encryption_algorithm.write(oprot); xfer += oprot->writeFieldEnd(); if (this->__isset.key_metadata) { - xfer += oprot->writeFieldBegin("key_metadata", ::duckdb_apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeFieldBegin("key_metadata", ::apache::thrift::protocol::T_STRING, 2); xfer += oprot->writeBinary(this->key_metadata); xfer += oprot->writeFieldEnd(); } @@ -6664,24 +7475,15 @@ void swap(FileCryptoMetaData &a, FileCryptoMetaData &b) { swap(a.__isset, b.__isset); } -FileCryptoMetaData::FileCryptoMetaData(const FileCryptoMetaData& other197) { - encryption_algorithm = other197.encryption_algorithm; - key_metadata = other197.key_metadata; - __isset = other197.__isset; +FileCryptoMetaData::FileCryptoMetaData(const FileCryptoMetaData& other245) { + encryption_algorithm = other245.encryption_algorithm; + key_metadata = other245.key_metadata; + __isset = other245.__isset; } -FileCryptoMetaData& FileCryptoMetaData::operator=(const FileCryptoMetaData& other198) { - encryption_algorithm = other198.encryption_algorithm; - key_metadata = other198.key_metadata; - __isset = other198.__isset; +FileCryptoMetaData& FileCryptoMetaData::operator=(const FileCryptoMetaData& other246) { + encryption_algorithm = other246.encryption_algorithm; + key_metadata = other246.key_metadata; + __isset = other246.__isset; return *this; } -void FileCryptoMetaData::printTo(std::ostream& out) const { - using ::duckdb_apache::thrift::to_string; - out << "FileCryptoMetaData("; - out << "encryption_algorithm=" << to_string(encryption_algorithm); - out << ", " << "key_metadata="; (__isset.key_metadata ? (out << to_string(key_metadata)) : (out << "")); - out << ")"; -} - - -}} // namespace \ No newline at end of file +} // namespace diff --git a/third_party/parquet/parquet_types.h b/third_party/parquet/parquet_types.h index af109ee97e6..627a83a1a8c 100644 --- a/third_party/parquet/parquet_types.h +++ b/third_party/parquet/parquet_types.h @@ -1,5 +1,5 @@ /** - * Autogenerated by Thrift Compiler (0.11.0) + * Autogenerated by Thrift Compiler (0.21.0) * * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING * @generated @@ -9,20 +9,26 @@ #include -#include "duckdb/common/vector.hpp" +#include +#include +#include +#include +#include -#include "thrift/Thrift.h" -#include "thrift/TApplicationException.h" -#include "thrift/TBase.h" -#include "thrift/protocol/TProtocol.h" -#include "thrift/transport/TTransport.h" +#include +#include -#include "thrift/stdcxx.h" +// I KNOW WHAT I AM DOING +namespace apache = duckdb_apache; -#include "windows_compatibility.h" - -namespace duckdb_parquet { namespace format { +namespace duckdb_parquet { +/** + * Types supported by Parquet. These types are intended to be used in combination + * with the encodings to control the on disk storage format. + * For example INT16 is not included as a type since a good encoding of INT32 + * would handle this. + */ struct Type { enum type { BOOLEAN = 0, @@ -36,66 +42,263 @@ struct Type { }; }; +extern const std::map _Type_VALUES_TO_NAMES; + std::ostream& operator<<(std::ostream& out, const Type::type& val); +std::string to_string(const Type::type& val); + +/** + * DEPRECATED: Common types used by frameworks(e.g. hive, pig) using parquet. + * ConvertedType is superseded by LogicalType. This enum should not be extended. + * + * See LogicalTypes.md for conversion between ConvertedType and LogicalType. + */ struct ConvertedType { enum type { + /** + * a BYTE_ARRAY actually contains UTF8 encoded chars + */ UTF8 = 0, + /** + * a map is converted as an optional field containing a repeated key/value pair + */ MAP = 1, + /** + * a key/value pair is converted into a group of two fields + */ MAP_KEY_VALUE = 2, + /** + * a list is converted into an optional field containing a repeated field for its + * values + */ LIST = 3, + /** + * an enum is converted into a BYTE_ARRAY field + */ ENUM = 4, + /** + * A decimal value. + * + * This may be used to annotate BYTE_ARRAY or FIXED_LEN_BYTE_ARRAY primitive + * types. The underlying byte array stores the unscaled value encoded as two's + * complement using big-endian byte order (the most significant byte is the + * zeroth element). The value of the decimal is the value * 10^{-scale}. + * + * This must be accompanied by a (maximum) precision and a scale in the + * SchemaElement. The precision specifies the number of digits in the decimal + * and the scale stores the location of the decimal point. For example 1.23 + * would have precision 3 (3 total digits) and scale 2 (the decimal point is + * 2 digits over). + */ DECIMAL = 5, + /** + * A Date + * + * Stored as days since Unix epoch, encoded as the INT32 physical type. + * + */ DATE = 6, + /** + * A time + * + * The total number of milliseconds since midnight. The value is stored + * as an INT32 physical type. + */ TIME_MILLIS = 7, + /** + * A time. + * + * The total number of microseconds since midnight. The value is stored as + * an INT64 physical type. + */ TIME_MICROS = 8, + /** + * A date/time combination + * + * Date and time recorded as milliseconds since the Unix epoch. Recorded as + * a physical type of INT64. + */ TIMESTAMP_MILLIS = 9, + /** + * A date/time combination + * + * Date and time recorded as microseconds since the Unix epoch. The value is + * stored as an INT64 physical type. + */ TIMESTAMP_MICROS = 10, + /** + * An unsigned integer value. + * + * The number describes the maximum number of meaningful data bits in + * the stored value. 8, 16 and 32 bit values are stored using the + * INT32 physical type. 64 bit values are stored using the INT64 + * physical type. + * + */ UINT_8 = 11, UINT_16 = 12, UINT_32 = 13, UINT_64 = 14, + /** + * A signed integer value. + * + * The number describes the maximum number of meaningful data bits in + * the stored value. 8, 16 and 32 bit values are stored using the + * INT32 physical type. 64 bit values are stored using the INT64 + * physical type. + * + */ INT_8 = 15, INT_16 = 16, INT_32 = 17, INT_64 = 18, + /** + * An embedded JSON document + * + * A JSON document embedded within a single UTF8 column. + */ JSON = 19, + /** + * An embedded BSON document + * + * A BSON document embedded within a single BYTE_ARRAY column. + */ BSON = 20, - INTERVAL = 21, - NULL_TYPE = 24 + /** + * An interval of time + * + * This type annotates data stored as a FIXED_LEN_BYTE_ARRAY of length 12 + * This data is composed of three separate little endian unsigned + * integers. Each stores a component of a duration of time. The first + * integer identifies the number of months associated with the duration, + * the second identifies the number of days associated with the duration + * and the third identifies the number of milliseconds associated with + * the provided duration. This duration of time is independent of any + * particular timezone or date. + */ + INTERVAL = 21 }; }; +extern const std::map _ConvertedType_VALUES_TO_NAMES; + std::ostream& operator<<(std::ostream& out, const ConvertedType::type& val); +std::string to_string(const ConvertedType::type& val); + +/** + * Representation of Schemas + */ struct FieldRepetitionType { enum type { + /** + * This field is required (can not be null) and each row has exactly 1 value. + */ REQUIRED = 0, + /** + * The field is optional (can be null) and each row has 0 or 1 values. + */ OPTIONAL = 1, + /** + * The field is repeated and can contain 0 or more values + */ REPEATED = 2 }; }; +extern const std::map _FieldRepetitionType_VALUES_TO_NAMES; + std::ostream& operator<<(std::ostream& out, const FieldRepetitionType::type& val); +std::string to_string(const FieldRepetitionType::type& val); + +/** + * Encodings supported by Parquet. Not all encodings are valid for all types. These + * enums are also used to specify the encoding of definition and repetition levels. + * See the accompanying doc for the details of the more complicated encodings. + */ struct Encoding { enum type { + /** + * Default encoding. + * BOOLEAN - 1 bit per value. 0 is false; 1 is true. + * INT32 - 4 bytes per value. Stored as little-endian. + * INT64 - 8 bytes per value. Stored as little-endian. + * FLOAT - 4 bytes per value. IEEE. Stored as little-endian. + * DOUBLE - 8 bytes per value. IEEE. Stored as little-endian. + * BYTE_ARRAY - 4 byte length stored as little endian, followed by bytes. + * FIXED_LEN_BYTE_ARRAY - Just the bytes. + */ PLAIN = 0, + /** + * Deprecated: Dictionary encoding. The values in the dictionary are encoded in the + * plain type. + * in a data page use RLE_DICTIONARY instead. + * in a Dictionary page use PLAIN instead + */ PLAIN_DICTIONARY = 2, + /** + * Group packed run length encoding. Usable for definition/repetition levels + * encoding and Booleans (on one bit: 0 is false; 1 is true.) + */ RLE = 3, + /** + * Bit packed encoding. This can only be used if the data has a known max + * width. Usable for definition/repetition levels encoding. + */ BIT_PACKED = 4, + /** + * Delta encoding for integers. This can be used for int columns and works best + * on sorted data + */ DELTA_BINARY_PACKED = 5, + /** + * Encoding for byte arrays to separate the length values and the data. The lengths + * are encoded using DELTA_BINARY_PACKED + */ DELTA_LENGTH_BYTE_ARRAY = 6, + /** + * Incremental-encoded byte array. Prefix lengths are encoded using DELTA_BINARY_PACKED. + * Suffixes are stored as delta length byte arrays. + */ DELTA_BYTE_ARRAY = 7, + /** + * Dictionary encoding: the ids are encoded using the RLE encoding + */ RLE_DICTIONARY = 8, - BYTE_STREAM_SPLIT = 9, + /** + * Encoding for fixed-width data (FLOAT, DOUBLE, INT32, INT64, FIXED_LEN_BYTE_ARRAY). + * K byte-streams are created where K is the size in bytes of the data type. + * The individual bytes of a value are scattered to the corresponding stream and + * the streams are concatenated. + * This itself does not reduce the size of the data but can lead to better compression + * afterwards. + * + * Added in 2.8 for FLOAT and DOUBLE. + * Support for INT32, INT64 and FIXED_LEN_BYTE_ARRAY added in 2.11. + */ + BYTE_STREAM_SPLIT = 9 }; }; +extern const std::map _Encoding_VALUES_TO_NAMES; + std::ostream& operator<<(std::ostream& out, const Encoding::type& val); +std::string to_string(const Encoding::type& val); + +/** + * Supported compression algorithms. + * + * Codecs added in format version X.Y can be read by readers based on X.Y and later. + * Codec support may vary between readers based on the format version and + * libraries available at runtime. + * + * See Compression.md for a detailed specification of these algorithms. + */ struct CompressionCodec { - enum type : uint8_t { + enum type { UNCOMPRESSED = 0, SNAPPY = 1, GZIP = 2, @@ -103,12 +306,16 @@ struct CompressionCodec { BROTLI = 4, LZ4 = 5, ZSTD = 6, - LZ4_RAW = 7 + LZ4_RAW = 7 }; }; +extern const std::map _CompressionCodec_VALUES_TO_NAMES; + std::ostream& operator<<(std::ostream& out, const CompressionCodec::type& val); +std::string to_string(const CompressionCodec::type& val); + struct PageType { enum type { DATA_PAGE = 0, @@ -118,8 +325,16 @@ struct PageType { }; }; +extern const std::map _PageType_VALUES_TO_NAMES; + std::ostream& operator<<(std::ostream& out, const PageType::type& val); +std::string to_string(const PageType::type& val); + +/** + * Enum to annotate whether lists of min/max elements inside ColumnIndex + * are ordered and if so, in which direction. + */ struct BoundaryOrder { enum type { UNORDERED = 0, @@ -128,8 +343,14 @@ struct BoundaryOrder { }; }; +extern const std::map _BoundaryOrder_VALUES_TO_NAMES; + std::ostream& operator<<(std::ostream& out, const BoundaryOrder::type& val); +std::string to_string(const BoundaryOrder::type& val); + +class SizeStatistics; + class Statistics; class StringType; @@ -144,6 +365,8 @@ class EnumType; class DateType; +class Float16Type; + class NullType; class DecimalType; @@ -178,6 +401,20 @@ class DictionaryPageHeader; class DataPageHeaderV2; +class SplitBlockAlgorithm; + +class BloomFilterAlgorithm; + +class XxHash; + +class BloomFilterHash; + +class Uncompressed; + +class BloomFilterCompression; + +class BloomFilterHeader; + class PageHeader; class KeyValue; @@ -218,31 +455,158 @@ class FileMetaData; class FileCryptoMetaData; +typedef struct _SizeStatistics__isset { + _SizeStatistics__isset() : unencoded_byte_array_data_bytes(false), repetition_level_histogram(false), definition_level_histogram(false) {} + bool unencoded_byte_array_data_bytes :1; + bool repetition_level_histogram :1; + bool definition_level_histogram :1; +} _SizeStatistics__isset; + +/** + * A structure for capturing metadata for estimating the unencoded, + * uncompressed size of data written. This is useful for readers to estimate + * how much memory is needed to reconstruct data in their memory model and for + * fine grained filter pushdown on nested structures (the histograms contained + * in this structure can help determine the number of nulls at a particular + * nesting level and maximum length of lists). + */ +class SizeStatistics : public virtual ::apache::thrift::TBase { + public: + + SizeStatistics(const SizeStatistics&); + SizeStatistics& operator=(const SizeStatistics&); + SizeStatistics() noexcept; + + virtual ~SizeStatistics() noexcept; + /** + * The number of physical bytes stored for BYTE_ARRAY data values assuming + * no encoding. This is exclusive of the bytes needed to store the length of + * each byte array. In other words, this field is equivalent to the `(size + * of PLAIN-ENCODING the byte array values) - (4 bytes * number of values + * written)`. To determine unencoded sizes of other types readers can use + * schema information multiplied by the number of non-null and null values. + * The number of null/non-null values can be inferred from the histograms + * below. + * + * For example, if a column chunk is dictionary-encoded with dictionary + * ["a", "bc", "cde"], and a data page contains the indices [0, 0, 1, 2], + * then this value for that data page should be 7 (1 + 1 + 2 + 3). + * + * This field should only be set for types that use BYTE_ARRAY as their + * physical type. + */ + int64_t unencoded_byte_array_data_bytes; + /** + * When present, there is expected to be one element corresponding to each + * repetition (i.e. size=max repetition_level+1) where each element + * represents the number of times the repetition level was observed in the + * data. + * + * This field may be omitted if max_repetition_level is 0 without loss + * of information. + * + */ + std::vector repetition_level_histogram; + /** + * Same as repetition_level_histogram except for definition levels. + * + * This field may be omitted if max_definition_level is 0 or 1 without + * loss of information. + * + */ + std::vector definition_level_histogram; + + _SizeStatistics__isset __isset; + + void __set_unencoded_byte_array_data_bytes(const int64_t val); + + void __set_repetition_level_histogram(const std::vector & val); + + void __set_definition_level_histogram(const std::vector & val); + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + +}; + +void swap(SizeStatistics &a, SizeStatistics &b); + +std::ostream& operator<<(std::ostream& out, const SizeStatistics& obj); + typedef struct _Statistics__isset { - _Statistics__isset() : max(false), min(false), null_count(false), distinct_count(false), max_value(false), min_value(false) {} + _Statistics__isset() : max(false), min(false), null_count(false), distinct_count(false), max_value(false), min_value(false), is_max_value_exact(false), is_min_value_exact(false) {} bool max :1; bool min :1; bool null_count :1; bool distinct_count :1; bool max_value :1; bool min_value :1; + bool is_max_value_exact :1; + bool is_min_value_exact :1; } _Statistics__isset; -class Statistics : public virtual ::duckdb_apache::thrift::TBase { +/** + * Statistics per row group and per page + * All fields are optional. + */ +class Statistics : public virtual ::apache::thrift::TBase { public: Statistics(const Statistics&); Statistics& operator=(const Statistics&); - Statistics() : max(), min(), null_count(0), distinct_count(0), max_value(), min_value() { - } - - virtual ~Statistics() throw(); + Statistics() noexcept; + + virtual ~Statistics() noexcept; + /** + * DEPRECATED: min and max value of the column. Use min_value and max_value. + * + * Values are encoded using PLAIN encoding, except that variable-length byte + * arrays do not include a length prefix. + * + * These fields encode min and max values determined by signed comparison + * only. New files should use the correct order for a column's logical type + * and store the values in the min_value and max_value fields. + * + * To support older readers, these may be set when the column order is + * signed. + */ std::string max; std::string min; + /** + * Count of null values in the column. + * + * Writers SHOULD always write this field even if it is zero (i.e. no null value) + * or the column is not nullable. + * Readers MUST distinguish between null_count not being present and null_count == 0. + * If null_count is not present, readers MUST NOT assume null_count == 0. + */ int64_t null_count; + /** + * count of distinct values occurring + */ int64_t distinct_count; + /** + * Lower and upper bound values for the column, determined by its ColumnOrder. + * + * These may be the actual minimum and maximum values found on a page or column + * chunk, but can also be (more compact) values that do not exist on a page or + * column chunk. For example, instead of storing "Blart Versenwald III", a writer + * may set min_value="B", max_value="C". Such more compact values must still be + * valid values within the column's logical type. + * + * Values are encoded using PLAIN encoding, except that variable-length byte + * arrays do not include a length prefix. + */ std::string max_value; std::string min_value; + /** + * If true, max_value is the actual maximum value for a column + */ + bool is_max_value_exact; + /** + * If true, min_value is the actual minimum value for a column + */ + bool is_min_value_exact; _Statistics__isset __isset; @@ -258,44 +622,13 @@ class Statistics : public virtual ::duckdb_apache::thrift::TBase { void __set_min_value(const std::string& val); - bool operator == (const Statistics & rhs) const - { - if (__isset.max != rhs.__isset.max) - return false; - else if (__isset.max && !(max == rhs.max)) - return false; - if (__isset.min != rhs.__isset.min) - return false; - else if (__isset.min && !(min == rhs.min)) - return false; - if (__isset.null_count != rhs.__isset.null_count) - return false; - else if (__isset.null_count && !(null_count == rhs.null_count)) - return false; - if (__isset.distinct_count != rhs.__isset.distinct_count) - return false; - else if (__isset.distinct_count && !(distinct_count == rhs.distinct_count)) - return false; - if (__isset.max_value != rhs.__isset.max_value) - return false; - else if (__isset.max_value && !(max_value == rhs.max_value)) - return false; - if (__isset.min_value != rhs.__isset.min_value) - return false; - else if (__isset.min_value && !(min_value == rhs.min_value)) - return false; - return true; - } - bool operator != (const Statistics &rhs) const { - return !(*this == rhs); - } - - bool operator < (const Statistics & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + void __set_is_max_value_exact(const bool val); + + void __set_is_min_value_exact(const bool val); + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(Statistics &a, Statistics &b); @@ -303,30 +636,21 @@ void swap(Statistics &a, Statistics &b); std::ostream& operator<<(std::ostream& out, const Statistics& obj); -class StringType : public virtual ::duckdb_apache::thrift::TBase { +/** + * Empty structs to use as logical type annotations + */ +class StringType : public virtual ::apache::thrift::TBase { public: - StringType(const StringType&); - StringType& operator=(const StringType&); - StringType() { - } - - virtual ~StringType() throw(); + StringType(const StringType&) noexcept; + StringType& operator=(const StringType&) noexcept; + StringType() noexcept; - bool operator == (const StringType & /* rhs */) const - { - return true; - } - bool operator != (const StringType &rhs) const { - return !(*this == rhs); - } + virtual ~StringType() noexcept; - bool operator < (const StringType & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(StringType &a, StringType &b); @@ -334,30 +658,18 @@ void swap(StringType &a, StringType &b); std::ostream& operator<<(std::ostream& out, const StringType& obj); -class UUIDType : public virtual ::duckdb_apache::thrift::TBase { +class UUIDType : public virtual ::apache::thrift::TBase { public: - UUIDType(const UUIDType&); - UUIDType& operator=(const UUIDType&); - UUIDType() { - } - - virtual ~UUIDType() throw(); + UUIDType(const UUIDType&) noexcept; + UUIDType& operator=(const UUIDType&) noexcept; + UUIDType() noexcept; - bool operator == (const UUIDType & /* rhs */) const - { - return true; - } - bool operator != (const UUIDType &rhs) const { - return !(*this == rhs); - } + virtual ~UUIDType() noexcept; - bool operator < (const UUIDType & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(UUIDType &a, UUIDType &b); @@ -365,30 +677,18 @@ void swap(UUIDType &a, UUIDType &b); std::ostream& operator<<(std::ostream& out, const UUIDType& obj); -class MapType : public virtual ::duckdb_apache::thrift::TBase { +class MapType : public virtual ::apache::thrift::TBase { public: - MapType(const MapType&); - MapType& operator=(const MapType&); - MapType() { - } - - virtual ~MapType() throw(); + MapType(const MapType&) noexcept; + MapType& operator=(const MapType&) noexcept; + MapType() noexcept; - bool operator == (const MapType & /* rhs */) const - { - return true; - } - bool operator != (const MapType &rhs) const { - return !(*this == rhs); - } + virtual ~MapType() noexcept; - bool operator < (const MapType & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(MapType &a, MapType &b); @@ -396,30 +696,18 @@ void swap(MapType &a, MapType &b); std::ostream& operator<<(std::ostream& out, const MapType& obj); -class ListType : public virtual ::duckdb_apache::thrift::TBase { +class ListType : public virtual ::apache::thrift::TBase { public: - ListType(const ListType&); - ListType& operator=(const ListType&); - ListType() { - } - - virtual ~ListType() throw(); + ListType(const ListType&) noexcept; + ListType& operator=(const ListType&) noexcept; + ListType() noexcept; - bool operator == (const ListType & /* rhs */) const - { - return true; - } - bool operator != (const ListType &rhs) const { - return !(*this == rhs); - } + virtual ~ListType() noexcept; - bool operator < (const ListType & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(ListType &a, ListType &b); @@ -427,30 +715,18 @@ void swap(ListType &a, ListType &b); std::ostream& operator<<(std::ostream& out, const ListType& obj); -class EnumType : public virtual ::duckdb_apache::thrift::TBase { +class EnumType : public virtual ::apache::thrift::TBase { public: - EnumType(const EnumType&); - EnumType& operator=(const EnumType&); - EnumType() { - } - - virtual ~EnumType() throw(); + EnumType(const EnumType&) noexcept; + EnumType& operator=(const EnumType&) noexcept; + EnumType() noexcept; - bool operator == (const EnumType & /* rhs */) const - { - return true; - } - bool operator != (const EnumType &rhs) const { - return !(*this == rhs); - } + virtual ~EnumType() noexcept; - bool operator < (const EnumType & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(EnumType &a, EnumType &b); @@ -458,30 +734,18 @@ void swap(EnumType &a, EnumType &b); std::ostream& operator<<(std::ostream& out, const EnumType& obj); -class DateType : public virtual ::duckdb_apache::thrift::TBase { +class DateType : public virtual ::apache::thrift::TBase { public: - DateType(const DateType&); - DateType& operator=(const DateType&); - DateType() { - } - - virtual ~DateType() throw(); + DateType(const DateType&) noexcept; + DateType& operator=(const DateType&) noexcept; + DateType() noexcept; - bool operator == (const DateType & /* rhs */) const - { - return true; - } - bool operator != (const DateType &rhs) const { - return !(*this == rhs); - } + virtual ~DateType() noexcept; - bool operator < (const DateType & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(DateType &a, DateType &b); @@ -489,30 +753,44 @@ void swap(DateType &a, DateType &b); std::ostream& operator<<(std::ostream& out, const DateType& obj); -class NullType : public virtual ::duckdb_apache::thrift::TBase { +class Float16Type : public virtual ::apache::thrift::TBase { public: - NullType(const NullType&); - NullType& operator=(const NullType&); - NullType() { - } + Float16Type(const Float16Type&) noexcept; + Float16Type& operator=(const Float16Type&) noexcept; + Float16Type() noexcept; + + virtual ~Float16Type() noexcept; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + +}; + +void swap(Float16Type &a, Float16Type &b); - virtual ~NullType() throw(); +std::ostream& operator<<(std::ostream& out, const Float16Type& obj); - bool operator == (const NullType & /* rhs */) const - { - return true; - } - bool operator != (const NullType &rhs) const { - return !(*this == rhs); - } - bool operator < (const NullType & ) const; +/** + * Logical type to annotate a column that is always null. + * + * Sometimes when discovering the schema of existing data, values are always + * null and the physical type can't be determined. This annotation signals + * the case where the physical type was guessed from all null values. + */ +class NullType : public virtual ::apache::thrift::TBase { + public: - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; + NullType(const NullType&) noexcept; + NullType& operator=(const NullType&) noexcept; + NullType() noexcept; + + virtual ~NullType() noexcept; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - virtual void printTo(std::ostream& out) const; }; void swap(NullType &a, NullType &b); @@ -520,15 +798,25 @@ void swap(NullType &a, NullType &b); std::ostream& operator<<(std::ostream& out, const NullType& obj); -class DecimalType : public virtual ::duckdb_apache::thrift::TBase { +/** + * Decimal logical type annotation + * + * Scale must be zero or a positive integer less than or equal to the precision. + * Precision must be a non-zero positive integer. + * + * To maintain forward-compatibility in v1, implementations using this logical + * type must also set scale and precision on the annotated SchemaElement. + * + * Allowed for physical types: INT32, INT64, FIXED_LEN_BYTE_ARRAY, and BYTE_ARRAY. + */ +class DecimalType : public virtual ::apache::thrift::TBase { public: - DecimalType(const DecimalType&); - DecimalType& operator=(const DecimalType&); - DecimalType() : scale(0), precision(0) { - } + DecimalType(const DecimalType&) noexcept; + DecimalType& operator=(const DecimalType&) noexcept; + DecimalType() noexcept; - virtual ~DecimalType() throw(); + virtual ~DecimalType() noexcept; int32_t scale; int32_t precision; @@ -536,24 +824,9 @@ class DecimalType : public virtual ::duckdb_apache::thrift::TBase { void __set_precision(const int32_t val); - bool operator == (const DecimalType & rhs) const - { - if (!(scale == rhs.scale)) - return false; - if (!(precision == rhs.precision)) - return false; - return true; - } - bool operator != (const DecimalType &rhs) const { - return !(*this == rhs); - } + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - bool operator < (const DecimalType & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(DecimalType &a, DecimalType &b); @@ -561,30 +834,21 @@ void swap(DecimalType &a, DecimalType &b); std::ostream& operator<<(std::ostream& out, const DecimalType& obj); -class MilliSeconds : public virtual ::duckdb_apache::thrift::TBase { +/** + * Time units for logical types + */ +class MilliSeconds : public virtual ::apache::thrift::TBase { public: - MilliSeconds(const MilliSeconds&); - MilliSeconds& operator=(const MilliSeconds&); - MilliSeconds() { - } - - virtual ~MilliSeconds() throw(); + MilliSeconds(const MilliSeconds&) noexcept; + MilliSeconds& operator=(const MilliSeconds&) noexcept; + MilliSeconds() noexcept; - bool operator == (const MilliSeconds & /* rhs */) const - { - return true; - } - bool operator != (const MilliSeconds &rhs) const { - return !(*this == rhs); - } + virtual ~MilliSeconds() noexcept; - bool operator < (const MilliSeconds & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(MilliSeconds &a, MilliSeconds &b); @@ -592,30 +856,18 @@ void swap(MilliSeconds &a, MilliSeconds &b); std::ostream& operator<<(std::ostream& out, const MilliSeconds& obj); -class MicroSeconds : public virtual ::duckdb_apache::thrift::TBase { +class MicroSeconds : public virtual ::apache::thrift::TBase { public: - MicroSeconds(const MicroSeconds&); - MicroSeconds& operator=(const MicroSeconds&); - MicroSeconds() { - } - - virtual ~MicroSeconds() throw(); + MicroSeconds(const MicroSeconds&) noexcept; + MicroSeconds& operator=(const MicroSeconds&) noexcept; + MicroSeconds() noexcept; - bool operator == (const MicroSeconds & /* rhs */) const - { - return true; - } - bool operator != (const MicroSeconds &rhs) const { - return !(*this == rhs); - } + virtual ~MicroSeconds() noexcept; - bool operator < (const MicroSeconds & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(MicroSeconds &a, MicroSeconds &b); @@ -623,30 +875,18 @@ void swap(MicroSeconds &a, MicroSeconds &b); std::ostream& operator<<(std::ostream& out, const MicroSeconds& obj); -class NanoSeconds : public virtual ::duckdb_apache::thrift::TBase { +class NanoSeconds : public virtual ::apache::thrift::TBase { public: - NanoSeconds(const NanoSeconds&); - NanoSeconds& operator=(const NanoSeconds&); - NanoSeconds() { - } - - virtual ~NanoSeconds() throw(); + NanoSeconds(const NanoSeconds&) noexcept; + NanoSeconds& operator=(const NanoSeconds&) noexcept; + NanoSeconds() noexcept; - bool operator == (const NanoSeconds & /* rhs */) const - { - return true; - } - bool operator != (const NanoSeconds &rhs) const { - return !(*this == rhs); - } + virtual ~NanoSeconds() noexcept; - bool operator < (const NanoSeconds & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(NanoSeconds &a, NanoSeconds &b); @@ -660,15 +900,14 @@ typedef struct _TimeUnit__isset { bool NANOS :1; } _TimeUnit__isset; -class TimeUnit : public virtual ::duckdb_apache::thrift::TBase { +class TimeUnit : public virtual ::apache::thrift::TBase { public: - TimeUnit(const TimeUnit&); - TimeUnit& operator=(const TimeUnit&); - TimeUnit() { - } + TimeUnit(const TimeUnit&) noexcept; + TimeUnit& operator=(const TimeUnit&) noexcept; + TimeUnit() noexcept; - virtual ~TimeUnit() throw(); + virtual ~TimeUnit() noexcept; MilliSeconds MILLIS; MicroSeconds MICROS; NanoSeconds NANOS; @@ -681,32 +920,9 @@ class TimeUnit : public virtual ::duckdb_apache::thrift::TBase { void __set_NANOS(const NanoSeconds& val); - bool operator == (const TimeUnit & rhs) const - { - if (__isset.MILLIS != rhs.__isset.MILLIS) - return false; - else if (__isset.MILLIS && !(MILLIS == rhs.MILLIS)) - return false; - if (__isset.MICROS != rhs.__isset.MICROS) - return false; - else if (__isset.MICROS && !(MICROS == rhs.MICROS)) - return false; - if (__isset.NANOS != rhs.__isset.NANOS) - return false; - else if (__isset.NANOS && !(NANOS == rhs.NANOS)) - return false; - return true; - } - bool operator != (const TimeUnit &rhs) const { - return !(*this == rhs); - } - - bool operator < (const TimeUnit & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(TimeUnit &a, TimeUnit &b); @@ -714,15 +930,19 @@ void swap(TimeUnit &a, TimeUnit &b); std::ostream& operator<<(std::ostream& out, const TimeUnit& obj); -class TimestampType : public virtual ::duckdb_apache::thrift::TBase { +/** + * Timestamp logical type annotation + * + * Allowed for physical types: INT64 + */ +class TimestampType : public virtual ::apache::thrift::TBase { public: - TimestampType(const TimestampType&); - TimestampType& operator=(const TimestampType&); - TimestampType() : isAdjustedToUTC(0) { - } + TimestampType(const TimestampType&) noexcept; + TimestampType& operator=(const TimestampType&) noexcept; + TimestampType() noexcept; - virtual ~TimestampType() throw(); + virtual ~TimestampType() noexcept; bool isAdjustedToUTC; TimeUnit unit; @@ -730,24 +950,9 @@ class TimestampType : public virtual ::duckdb_apache::thrift::TBase { void __set_unit(const TimeUnit& val); - bool operator == (const TimestampType & rhs) const - { - if (!(isAdjustedToUTC == rhs.isAdjustedToUTC)) - return false; - if (!(unit == rhs.unit)) - return false; - return true; - } - bool operator != (const TimestampType &rhs) const { - return !(*this == rhs); - } - - bool operator < (const TimestampType & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(TimestampType &a, TimestampType &b); @@ -755,15 +960,19 @@ void swap(TimestampType &a, TimestampType &b); std::ostream& operator<<(std::ostream& out, const TimestampType& obj); -class TimeType : public virtual ::duckdb_apache::thrift::TBase { +/** + * Time logical type annotation + * + * Allowed for physical types: INT32 (millis), INT64 (micros, nanos) + */ +class TimeType : public virtual ::apache::thrift::TBase { public: - TimeType(const TimeType&); - TimeType& operator=(const TimeType&); - TimeType() : isAdjustedToUTC(0) { - } + TimeType(const TimeType&) noexcept; + TimeType& operator=(const TimeType&) noexcept; + TimeType() noexcept; - virtual ~TimeType() throw(); + virtual ~TimeType() noexcept; bool isAdjustedToUTC; TimeUnit unit; @@ -771,24 +980,9 @@ class TimeType : public virtual ::duckdb_apache::thrift::TBase { void __set_unit(const TimeUnit& val); - bool operator == (const TimeType & rhs) const - { - if (!(isAdjustedToUTC == rhs.isAdjustedToUTC)) - return false; - if (!(unit == rhs.unit)) - return false; - return true; - } - bool operator != (const TimeType &rhs) const { - return !(*this == rhs); - } - - bool operator < (const TimeType & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(TimeType &a, TimeType &b); @@ -796,15 +990,21 @@ void swap(TimeType &a, TimeType &b); std::ostream& operator<<(std::ostream& out, const TimeType& obj); -class IntType : public virtual ::duckdb_apache::thrift::TBase { +/** + * Integer logical type annotation + * + * bitWidth must be 8, 16, 32, or 64. + * + * Allowed for physical types: INT32, INT64 + */ +class IntType : public virtual ::apache::thrift::TBase { public: - IntType(const IntType&); - IntType& operator=(const IntType&); - IntType() : bitWidth(0), isSigned(0) { - } + IntType(const IntType&) noexcept; + IntType& operator=(const IntType&) noexcept; + IntType() noexcept; - virtual ~IntType() throw(); + virtual ~IntType() noexcept; int8_t bitWidth; bool isSigned; @@ -812,24 +1012,9 @@ class IntType : public virtual ::duckdb_apache::thrift::TBase { void __set_isSigned(const bool val); - bool operator == (const IntType & rhs) const - { - if (!(bitWidth == rhs.bitWidth)) - return false; - if (!(isSigned == rhs.isSigned)) - return false; - return true; - } - bool operator != (const IntType &rhs) const { - return !(*this == rhs); - } - - bool operator < (const IntType & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(IntType &a, IntType &b); @@ -837,30 +1022,23 @@ void swap(IntType &a, IntType &b); std::ostream& operator<<(std::ostream& out, const IntType& obj); -class JsonType : public virtual ::duckdb_apache::thrift::TBase { +/** + * Embedded JSON logical type annotation + * + * Allowed for physical types: BYTE_ARRAY + */ +class JsonType : public virtual ::apache::thrift::TBase { public: - JsonType(const JsonType&); - JsonType& operator=(const JsonType&); - JsonType() { - } - - virtual ~JsonType() throw(); + JsonType(const JsonType&) noexcept; + JsonType& operator=(const JsonType&) noexcept; + JsonType() noexcept; - bool operator == (const JsonType & /* rhs */) const - { - return true; - } - bool operator != (const JsonType &rhs) const { - return !(*this == rhs); - } + virtual ~JsonType() noexcept; - bool operator < (const JsonType & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(JsonType &a, JsonType &b); @@ -868,30 +1046,23 @@ void swap(JsonType &a, JsonType &b); std::ostream& operator<<(std::ostream& out, const JsonType& obj); -class BsonType : public virtual ::duckdb_apache::thrift::TBase { +/** + * Embedded BSON logical type annotation + * + * Allowed for physical types: BYTE_ARRAY + */ +class BsonType : public virtual ::apache::thrift::TBase { public: - BsonType(const BsonType&); - BsonType& operator=(const BsonType&); - BsonType() { - } - - virtual ~BsonType() throw(); - - bool operator == (const BsonType & /* rhs */) const - { - return true; - } - bool operator != (const BsonType &rhs) const { - return !(*this == rhs); - } + BsonType(const BsonType&) noexcept; + BsonType& operator=(const BsonType&) noexcept; + BsonType() noexcept; - bool operator < (const BsonType & ) const; + virtual ~BsonType() noexcept; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - virtual void printTo(std::ostream& out) const; }; void swap(BsonType &a, BsonType &b); @@ -899,7 +1070,7 @@ void swap(BsonType &a, BsonType &b); std::ostream& operator<<(std::ostream& out, const BsonType& obj); typedef struct _LogicalType__isset { - _LogicalType__isset() : STRING(false), MAP(false), LIST(false), ENUM(false), DECIMAL(false), DATE(false), TIME(false), TIMESTAMP(false), INTEGER(false), UNKNOWN(false), JSON(false), BSON(false), UUID(false) {} + _LogicalType__isset() : STRING(false), MAP(false), LIST(false), ENUM(false), DECIMAL(false), DATE(false), TIME(false), TIMESTAMP(false), INTEGER(false), UNKNOWN(false), JSON(false), BSON(false), UUID(false), FLOAT16(false) {} bool STRING :1; bool MAP :1; bool LIST :1; @@ -913,17 +1084,24 @@ typedef struct _LogicalType__isset { bool JSON :1; bool BSON :1; bool UUID :1; + bool FLOAT16 :1; } _LogicalType__isset; -class LogicalType : public virtual ::duckdb_apache::thrift::TBase { +/** + * LogicalType annotations to replace ConvertedType. + * + * To maintain compatibility, implementations using LogicalType for a + * SchemaElement must also set the corresponding ConvertedType (if any) + * from the following table. + */ +class LogicalType : public virtual ::apache::thrift::TBase { public: - LogicalType(const LogicalType&); - LogicalType& operator=(const LogicalType&); - LogicalType() { - } + LogicalType(const LogicalType&) noexcept; + LogicalType& operator=(const LogicalType&) noexcept; + LogicalType() noexcept; - virtual ~LogicalType() throw(); + virtual ~LogicalType() noexcept; StringType STRING; MapType MAP; ListType LIST; @@ -937,6 +1115,7 @@ class LogicalType : public virtual ::duckdb_apache::thrift::TBase { JsonType JSON; BsonType BSON; UUIDType UUID; + Float16Type FLOAT16; _LogicalType__isset __isset; @@ -966,72 +1145,11 @@ class LogicalType : public virtual ::duckdb_apache::thrift::TBase { void __set_UUID(const UUIDType& val); - bool operator == (const LogicalType & rhs) const - { - if (__isset.STRING != rhs.__isset.STRING) - return false; - else if (__isset.STRING && !(STRING == rhs.STRING)) - return false; - if (__isset.MAP != rhs.__isset.MAP) - return false; - else if (__isset.MAP && !(MAP == rhs.MAP)) - return false; - if (__isset.LIST != rhs.__isset.LIST) - return false; - else if (__isset.LIST && !(LIST == rhs.LIST)) - return false; - if (__isset.ENUM != rhs.__isset.ENUM) - return false; - else if (__isset.ENUM && !(ENUM == rhs.ENUM)) - return false; - if (__isset.DECIMAL != rhs.__isset.DECIMAL) - return false; - else if (__isset.DECIMAL && !(DECIMAL == rhs.DECIMAL)) - return false; - if (__isset.DATE != rhs.__isset.DATE) - return false; - else if (__isset.DATE && !(DATE == rhs.DATE)) - return false; - if (__isset.TIME != rhs.__isset.TIME) - return false; - else if (__isset.TIME && !(TIME == rhs.TIME)) - return false; - if (__isset.TIMESTAMP != rhs.__isset.TIMESTAMP) - return false; - else if (__isset.TIMESTAMP && !(TIMESTAMP == rhs.TIMESTAMP)) - return false; - if (__isset.INTEGER != rhs.__isset.INTEGER) - return false; - else if (__isset.INTEGER && !(INTEGER == rhs.INTEGER)) - return false; - if (__isset.UNKNOWN != rhs.__isset.UNKNOWN) - return false; - else if (__isset.UNKNOWN && !(UNKNOWN == rhs.UNKNOWN)) - return false; - if (__isset.JSON != rhs.__isset.JSON) - return false; - else if (__isset.JSON && !(JSON == rhs.JSON)) - return false; - if (__isset.BSON != rhs.__isset.BSON) - return false; - else if (__isset.BSON && !(BSON == rhs.BSON)) - return false; - if (__isset.UUID != rhs.__isset.UUID) - return false; - else if (__isset.UUID && !(UUID == rhs.UUID)) - return false; - return true; - } - bool operator != (const LogicalType &rhs) const { - return !(*this == rhs); - } - - bool operator < (const LogicalType & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + void __set_FLOAT16(const Float16Type& val); + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(LogicalType &a, LogicalType &b); @@ -1051,24 +1169,79 @@ typedef struct _SchemaElement__isset { bool logicalType :1; } _SchemaElement__isset; -class SchemaElement : public virtual ::duckdb_apache::thrift::TBase { +/** + * Represents a element inside a schema definition. + * - if it is a group (inner node) then type is undefined and num_children is defined + * - if it is a primitive type (leaf) then type is defined and num_children is undefined + * the nodes are listed in depth first traversal order. + */ +class SchemaElement : public virtual ::apache::thrift::TBase { public: SchemaElement(const SchemaElement&); SchemaElement& operator=(const SchemaElement&); - SchemaElement() : type((Type::type)0), type_length(0), repetition_type((FieldRepetitionType::type)0), name(), num_children(0), converted_type((ConvertedType::type)0), scale(0), precision(0), field_id(0) { - } - - virtual ~SchemaElement() throw(); + SchemaElement() noexcept; + + virtual ~SchemaElement() noexcept; + /** + * Data type for this field. Not set if the current element is a non-leaf node + * + * @see Type + */ Type::type type; + /** + * If type is FIXED_LEN_BYTE_ARRAY, this is the byte length of the values. + * Otherwise, if specified, this is the maximum bit length to store any of the values. + * (e.g. a low cardinality INT col could have this set to 3). Note that this is + * in the schema, and therefore fixed for the entire file. + */ int32_t type_length; + /** + * repetition of the field. The root of the schema does not have a repetition_type. + * All other nodes must have one + * + * @see FieldRepetitionType + */ FieldRepetitionType::type repetition_type; + /** + * Name of the field in the schema + */ std::string name; + /** + * Nested fields. Since thrift does not support nested fields, + * the nesting is flattened to a single list by a depth-first traversal. + * The children count is used to construct the nested relationship. + * This field is not set when the element is a primitive type + */ int32_t num_children; + /** + * DEPRECATED: When the schema is the result of a conversion from another model. + * Used to record the original type to help with cross conversion. + * + * This is superseded by logicalType. + * + * @see ConvertedType + */ ConvertedType::type converted_type; + /** + * DEPRECATED: Used when this column contains decimal data. + * See the DECIMAL converted type for more details. + * + * This is superseded by using the DecimalType annotation in logicalType. + */ int32_t scale; int32_t precision; + /** + * When the original schema supports field ids, this will save the + * original field id in the parquet schema + */ int32_t field_id; + /** + * The logical type of this SchemaElement + * + * LogicalType replaces ConvertedType, but ConvertedType is still required + * for some logical types to ensure forward-compatibility in format v1. + */ LogicalType logicalType; _SchemaElement__isset __isset; @@ -1093,58 +1266,9 @@ class SchemaElement : public virtual ::duckdb_apache::thrift::TBase { void __set_logicalType(const LogicalType& val); - bool operator == (const SchemaElement & rhs) const - { - if (__isset.type != rhs.__isset.type) - return false; - else if (__isset.type && !(type == rhs.type)) - return false; - if (__isset.type_length != rhs.__isset.type_length) - return false; - else if (__isset.type_length && !(type_length == rhs.type_length)) - return false; - if (__isset.repetition_type != rhs.__isset.repetition_type) - return false; - else if (__isset.repetition_type && !(repetition_type == rhs.repetition_type)) - return false; - if (!(name == rhs.name)) - return false; - if (__isset.num_children != rhs.__isset.num_children) - return false; - else if (__isset.num_children && !(num_children == rhs.num_children)) - return false; - if (__isset.converted_type != rhs.__isset.converted_type) - return false; - else if (__isset.converted_type && !(converted_type == rhs.converted_type)) - return false; - if (__isset.scale != rhs.__isset.scale) - return false; - else if (__isset.scale && !(scale == rhs.scale)) - return false; - if (__isset.precision != rhs.__isset.precision) - return false; - else if (__isset.precision && !(precision == rhs.precision)) - return false; - if (__isset.field_id != rhs.__isset.field_id) - return false; - else if (__isset.field_id && !(field_id == rhs.field_id)) - return false; - if (__isset.logicalType != rhs.__isset.logicalType) - return false; - else if (__isset.logicalType && !(logicalType == rhs.logicalType)) - return false; - return true; - } - bool operator != (const SchemaElement &rhs) const { - return !(*this == rhs); - } - - bool operator < (const SchemaElement & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(SchemaElement &a, SchemaElement &b); @@ -1156,19 +1280,47 @@ typedef struct _DataPageHeader__isset { bool statistics :1; } _DataPageHeader__isset; -class DataPageHeader : public virtual ::duckdb_apache::thrift::TBase { +/** + * Data page header + */ +class DataPageHeader : public virtual ::apache::thrift::TBase { public: DataPageHeader(const DataPageHeader&); DataPageHeader& operator=(const DataPageHeader&); - DataPageHeader() : num_values(0), encoding((Encoding::type)0), definition_level_encoding((Encoding::type)0), repetition_level_encoding((Encoding::type)0) { - } - - virtual ~DataPageHeader() throw(); + DataPageHeader() noexcept; + + virtual ~DataPageHeader() noexcept; + /** + * Number of values, including NULLs, in this data page. + * + * If a OffsetIndex is present, a page must begin at a row + * boundary (repetition_level = 0). Otherwise, pages may begin + * within a row (repetition_level > 0). + * + */ int32_t num_values; + /** + * Encoding used for this data page * + * + * @see Encoding + */ Encoding::type encoding; + /** + * Encoding used for definition levels * + * + * @see Encoding + */ Encoding::type definition_level_encoding; + /** + * Encoding used for repetition levels * + * + * @see Encoding + */ Encoding::type repetition_level_encoding; + /** + * Optional statistics for the data in this page * + */ Statistics statistics; _DataPageHeader__isset __isset; @@ -1183,32 +1335,9 @@ class DataPageHeader : public virtual ::duckdb_apache::thrift::TBase { void __set_statistics(const Statistics& val); - bool operator == (const DataPageHeader & rhs) const - { - if (!(num_values == rhs.num_values)) - return false; - if (!(encoding == rhs.encoding)) - return false; - if (!(definition_level_encoding == rhs.definition_level_encoding)) - return false; - if (!(repetition_level_encoding == rhs.repetition_level_encoding)) - return false; - if (__isset.statistics != rhs.__isset.statistics) - return false; - else if (__isset.statistics && !(statistics == rhs.statistics)) - return false; - return true; - } - bool operator != (const DataPageHeader &rhs) const { - return !(*this == rhs); - } - - bool operator < (const DataPageHeader & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(DataPageHeader &a, DataPageHeader &b); @@ -1216,30 +1345,18 @@ void swap(DataPageHeader &a, DataPageHeader &b); std::ostream& operator<<(std::ostream& out, const DataPageHeader& obj); -class IndexPageHeader : public virtual ::duckdb_apache::thrift::TBase { +class IndexPageHeader : public virtual ::apache::thrift::TBase { public: - IndexPageHeader(const IndexPageHeader&); - IndexPageHeader& operator=(const IndexPageHeader&); - IndexPageHeader() { - } - - virtual ~IndexPageHeader() throw(); + IndexPageHeader(const IndexPageHeader&) noexcept; + IndexPageHeader& operator=(const IndexPageHeader&) noexcept; + IndexPageHeader() noexcept; - bool operator == (const IndexPageHeader & /* rhs */) const - { - return true; - } - bool operator != (const IndexPageHeader &rhs) const { - return !(*this == rhs); - } + virtual ~IndexPageHeader() noexcept; - bool operator < (const IndexPageHeader & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(IndexPageHeader &a, IndexPageHeader &b); @@ -1251,17 +1368,33 @@ typedef struct _DictionaryPageHeader__isset { bool is_sorted :1; } _DictionaryPageHeader__isset; -class DictionaryPageHeader : public virtual ::duckdb_apache::thrift::TBase { +/** + * The dictionary page must be placed at the first position of the column chunk + * if it is partly or completely dictionary encoded. At most one dictionary page + * can be placed in a column chunk. + * + */ +class DictionaryPageHeader : public virtual ::apache::thrift::TBase { public: - DictionaryPageHeader(const DictionaryPageHeader&); - DictionaryPageHeader& operator=(const DictionaryPageHeader&); - DictionaryPageHeader() : num_values(0), encoding((Encoding::type)0), is_sorted(0) { - } + DictionaryPageHeader(const DictionaryPageHeader&) noexcept; + DictionaryPageHeader& operator=(const DictionaryPageHeader&) noexcept; + DictionaryPageHeader() noexcept; - virtual ~DictionaryPageHeader() throw(); + virtual ~DictionaryPageHeader() noexcept; + /** + * Number of values in the dictionary * + */ int32_t num_values; + /** + * Encoding using this dictionary page * + * + * @see Encoding + */ Encoding::type encoding; + /** + * If true, the entries in the dictionary are sorted in ascending order * + */ bool is_sorted; _DictionaryPageHeader__isset __isset; @@ -1272,28 +1405,9 @@ class DictionaryPageHeader : public virtual ::duckdb_apache::thrift::TBase { void __set_is_sorted(const bool val); - bool operator == (const DictionaryPageHeader & rhs) const - { - if (!(num_values == rhs.num_values)) - return false; - if (!(encoding == rhs.encoding)) - return false; - if (__isset.is_sorted != rhs.__isset.is_sorted) - return false; - else if (__isset.is_sorted && !(is_sorted == rhs.is_sorted)) - return false; - return true; - } - bool operator != (const DictionaryPageHeader &rhs) const { - return !(*this == rhs); - } - - bool operator < (const DictionaryPageHeader & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(DictionaryPageHeader &a, DictionaryPageHeader &b); @@ -1306,22 +1420,61 @@ typedef struct _DataPageHeaderV2__isset { bool statistics :1; } _DataPageHeaderV2__isset; -class DataPageHeaderV2 : public virtual ::duckdb_apache::thrift::TBase { +/** + * New page format allowing reading levels without decompressing the data + * Repetition and definition levels are uncompressed + * The remaining section containing the data is compressed if is_compressed is true + * + */ +class DataPageHeaderV2 : public virtual ::apache::thrift::TBase { public: DataPageHeaderV2(const DataPageHeaderV2&); DataPageHeaderV2& operator=(const DataPageHeaderV2&); - DataPageHeaderV2() : num_values(0), num_nulls(0), num_rows(0), encoding((Encoding::type)0), definition_levels_byte_length(0), repetition_levels_byte_length(0), is_compressed(true) { - } + DataPageHeaderV2() noexcept; - virtual ~DataPageHeaderV2() throw(); + virtual ~DataPageHeaderV2() noexcept; + /** + * Number of values, including NULLs, in this data page. * + */ int32_t num_values; + /** + * Number of NULL values, in this data page. + * Number of non-null = num_values - num_nulls which is also the number of values in the data section * + */ int32_t num_nulls; + /** + * Number of rows in this data page. Every page must begin at a + * row boundary (repetition_level = 0): rows must **not** be + * split across page boundaries when using V2 data pages. + * + */ int32_t num_rows; + /** + * Encoding used for data in this page * + * + * @see Encoding + */ Encoding::type encoding; + /** + * Length of the definition levels + */ int32_t definition_levels_byte_length; + /** + * Length of the repetition levels + */ int32_t repetition_levels_byte_length; + /** + * Whether the values are compressed. + * Which means the section of the page between + * definition_levels_byte_length + repetition_levels_byte_length + 1 and compressed_page_size (included) + * is compressed with the compression_codec. + * If missing it is considered compressed + */ bool is_compressed; + /** + * Optional statistics for the data in this page * + */ Statistics statistics; _DataPageHeaderV2__isset __isset; @@ -1342,46 +1495,230 @@ class DataPageHeaderV2 : public virtual ::duckdb_apache::thrift::TBase { void __set_statistics(const Statistics& val); - bool operator == (const DataPageHeaderV2 & rhs) const - { - if (!(num_values == rhs.num_values)) - return false; - if (!(num_nulls == rhs.num_nulls)) - return false; - if (!(num_rows == rhs.num_rows)) - return false; - if (!(encoding == rhs.encoding)) - return false; - if (!(definition_levels_byte_length == rhs.definition_levels_byte_length)) - return false; - if (!(repetition_levels_byte_length == rhs.repetition_levels_byte_length)) - return false; - if (__isset.is_compressed != rhs.__isset.is_compressed) - return false; - else if (__isset.is_compressed && !(is_compressed == rhs.is_compressed)) - return false; - if (__isset.statistics != rhs.__isset.statistics) - return false; - else if (__isset.statistics && !(statistics == rhs.statistics)) - return false; - return true; - } - bool operator != (const DataPageHeaderV2 &rhs) const { - return !(*this == rhs); - } - - bool operator < (const DataPageHeaderV2 & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(DataPageHeaderV2 &a, DataPageHeaderV2 &b); std::ostream& operator<<(std::ostream& out, const DataPageHeaderV2& obj); + +/** + * Block-based algorithm type annotation. * + */ +class SplitBlockAlgorithm : public virtual ::apache::thrift::TBase { + public: + + SplitBlockAlgorithm(const SplitBlockAlgorithm&) noexcept; + SplitBlockAlgorithm& operator=(const SplitBlockAlgorithm&) noexcept; + SplitBlockAlgorithm() noexcept; + + virtual ~SplitBlockAlgorithm() noexcept; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + +}; + +void swap(SplitBlockAlgorithm &a, SplitBlockAlgorithm &b); + +std::ostream& operator<<(std::ostream& out, const SplitBlockAlgorithm& obj); + +typedef struct _BloomFilterAlgorithm__isset { + _BloomFilterAlgorithm__isset() : BLOCK(false) {} + bool BLOCK :1; +} _BloomFilterAlgorithm__isset; + +/** + * The algorithm used in Bloom filter. * + */ +class BloomFilterAlgorithm : public virtual ::apache::thrift::TBase { + public: + + BloomFilterAlgorithm(const BloomFilterAlgorithm&) noexcept; + BloomFilterAlgorithm& operator=(const BloomFilterAlgorithm&) noexcept; + BloomFilterAlgorithm() noexcept; + + virtual ~BloomFilterAlgorithm() noexcept; + /** + * Block-based Bloom filter. * + */ + SplitBlockAlgorithm BLOCK; + + _BloomFilterAlgorithm__isset __isset; + + void __set_BLOCK(const SplitBlockAlgorithm& val); + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + +}; + +void swap(BloomFilterAlgorithm &a, BloomFilterAlgorithm &b); + +std::ostream& operator<<(std::ostream& out, const BloomFilterAlgorithm& obj); + + +/** + * Hash strategy type annotation. xxHash is an extremely fast non-cryptographic hash + * algorithm. It uses 64 bits version of xxHash. + * + */ +class XxHash : public virtual ::apache::thrift::TBase { + public: + + XxHash(const XxHash&) noexcept; + XxHash& operator=(const XxHash&) noexcept; + XxHash() noexcept; + + virtual ~XxHash() noexcept; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + +}; + +void swap(XxHash &a, XxHash &b); + +std::ostream& operator<<(std::ostream& out, const XxHash& obj); + +typedef struct _BloomFilterHash__isset { + _BloomFilterHash__isset() : XXHASH(false) {} + bool XXHASH :1; +} _BloomFilterHash__isset; + +/** + * The hash function used in Bloom filter. This function takes the hash of a column value + * using plain encoding. + * + */ +class BloomFilterHash : public virtual ::apache::thrift::TBase { + public: + + BloomFilterHash(const BloomFilterHash&) noexcept; + BloomFilterHash& operator=(const BloomFilterHash&) noexcept; + BloomFilterHash() noexcept; + + virtual ~BloomFilterHash() noexcept; + /** + * xxHash Strategy. * + */ + XxHash XXHASH; + + _BloomFilterHash__isset __isset; + + void __set_XXHASH(const XxHash& val); + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + +}; + +void swap(BloomFilterHash &a, BloomFilterHash &b); + +std::ostream& operator<<(std::ostream& out, const BloomFilterHash& obj); + + +/** + * The compression used in the Bloom filter. + * + */ +class Uncompressed : public virtual ::apache::thrift::TBase { + public: + + Uncompressed(const Uncompressed&) noexcept; + Uncompressed& operator=(const Uncompressed&) noexcept; + Uncompressed() noexcept; + + virtual ~Uncompressed() noexcept; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + +}; + +void swap(Uncompressed &a, Uncompressed &b); + +std::ostream& operator<<(std::ostream& out, const Uncompressed& obj); + +typedef struct _BloomFilterCompression__isset { + _BloomFilterCompression__isset() : UNCOMPRESSED(false) {} + bool UNCOMPRESSED :1; +} _BloomFilterCompression__isset; + +class BloomFilterCompression : public virtual ::apache::thrift::TBase { + public: + + BloomFilterCompression(const BloomFilterCompression&) noexcept; + BloomFilterCompression& operator=(const BloomFilterCompression&) noexcept; + BloomFilterCompression() noexcept; + + virtual ~BloomFilterCompression() noexcept; + Uncompressed UNCOMPRESSED; + + _BloomFilterCompression__isset __isset; + + void __set_UNCOMPRESSED(const Uncompressed& val); + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + +}; + +void swap(BloomFilterCompression &a, BloomFilterCompression &b); + +std::ostream& operator<<(std::ostream& out, const BloomFilterCompression& obj); + + +/** + * Bloom filter header is stored at beginning of Bloom filter data of each column + * and followed by its bitset. + * + */ +class BloomFilterHeader : public virtual ::apache::thrift::TBase { + public: + + BloomFilterHeader(const BloomFilterHeader&) noexcept; + BloomFilterHeader& operator=(const BloomFilterHeader&) noexcept; + BloomFilterHeader() noexcept; + + virtual ~BloomFilterHeader() noexcept; + /** + * The size of bitset in bytes * + */ + int32_t numBytes; + /** + * The algorithm for setting bits. * + */ + BloomFilterAlgorithm algorithm; + /** + * The hash function used for Bloom filter. * + */ + BloomFilterHash hash; + /** + * The compression used in the Bloom filter * + */ + BloomFilterCompression compression; + + void __set_numBytes(const int32_t val); + + void __set_algorithm(const BloomFilterAlgorithm& val); + + void __set_hash(const BloomFilterHash& val); + + void __set_compression(const BloomFilterCompression& val); + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + +}; + +void swap(BloomFilterHeader &a, BloomFilterHeader &b); + +std::ostream& operator<<(std::ostream& out, const BloomFilterHeader& obj); + typedef struct _PageHeader__isset { _PageHeader__isset() : crc(false), data_page_header(false), index_page_header(false), dictionary_page_header(false), data_page_header_v2(false) {} bool crc :1; @@ -1391,18 +1728,46 @@ typedef struct _PageHeader__isset { bool data_page_header_v2 :1; } _PageHeader__isset; -class PageHeader : public virtual ::duckdb_apache::thrift::TBase { +class PageHeader : public virtual ::apache::thrift::TBase { public: PageHeader(const PageHeader&); PageHeader& operator=(const PageHeader&); - PageHeader() : type((PageType::type)0), uncompressed_page_size(0), compressed_page_size(0), crc(0) { - } - - virtual ~PageHeader() throw(); + PageHeader() noexcept; + + virtual ~PageHeader() noexcept; + /** + * the type of the page: indicates which of the *_header fields is set * + * + * @see PageType + */ PageType::type type; + /** + * Uncompressed page size in bytes (not including this header) * + */ int32_t uncompressed_page_size; + /** + * Compressed (and potentially encrypted) page size in bytes, not including this header * + */ int32_t compressed_page_size; + /** + * The 32-bit CRC checksum for the page, to be be calculated as follows: + * + * - The standard CRC32 algorithm is used (with polynomial 0x04C11DB7, + * the same as in e.g. GZip). + * - All page types can have a CRC (v1 and v2 data pages, dictionary pages, + * etc.). + * - The CRC is computed on the serialization binary representation of the page + * (as written to disk), excluding the page header. For example, for v1 + * data pages, the CRC is computed on the concatenation of repetition levels, + * definition levels and column values (optionally compressed, optionally + * encrypted). + * - The CRC computation therefore takes place after any compression + * and encryption steps, if any. + * + * If enabled, this allows for disabling checksumming in HDFS if only a few + * pages need to be read. + */ int32_t crc; DataPageHeader data_page_header; IndexPageHeader index_page_header; @@ -1427,46 +1792,9 @@ class PageHeader : public virtual ::duckdb_apache::thrift::TBase { void __set_data_page_header_v2(const DataPageHeaderV2& val); - bool operator == (const PageHeader & rhs) const - { - if (!(type == rhs.type)) - return false; - if (!(uncompressed_page_size == rhs.uncompressed_page_size)) - return false; - if (!(compressed_page_size == rhs.compressed_page_size)) - return false; - if (__isset.crc != rhs.__isset.crc) - return false; - else if (__isset.crc && !(crc == rhs.crc)) - return false; - if (__isset.data_page_header != rhs.__isset.data_page_header) - return false; - else if (__isset.data_page_header && !(data_page_header == rhs.data_page_header)) - return false; - if (__isset.index_page_header != rhs.__isset.index_page_header) - return false; - else if (__isset.index_page_header && !(index_page_header == rhs.index_page_header)) - return false; - if (__isset.dictionary_page_header != rhs.__isset.dictionary_page_header) - return false; - else if (__isset.dictionary_page_header && !(dictionary_page_header == rhs.dictionary_page_header)) - return false; - if (__isset.data_page_header_v2 != rhs.__isset.data_page_header_v2) - return false; - else if (__isset.data_page_header_v2 && !(data_page_header_v2 == rhs.data_page_header_v2)) - return false; - return true; - } - bool operator != (const PageHeader &rhs) const { - return !(*this == rhs); - } - - bool operator < (const PageHeader & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(PageHeader &a, PageHeader &b); @@ -1478,15 +1806,17 @@ typedef struct _KeyValue__isset { bool value :1; } _KeyValue__isset; -class KeyValue : public virtual ::duckdb_apache::thrift::TBase { +/** + * Wrapper struct to store key values + */ +class KeyValue : public virtual ::apache::thrift::TBase { public: KeyValue(const KeyValue&); KeyValue& operator=(const KeyValue&); - KeyValue() : key(), value() { - } + KeyValue() noexcept; - virtual ~KeyValue() throw(); + virtual ~KeyValue() noexcept; std::string key; std::string value; @@ -1496,26 +1826,9 @@ class KeyValue : public virtual ::duckdb_apache::thrift::TBase { void __set_value(const std::string& val); - bool operator == (const KeyValue & rhs) const - { - if (!(key == rhs.key)) - return false; - if (__isset.value != rhs.__isset.value) - return false; - else if (__isset.value && !(value == rhs.value)) - return false; - return true; - } - bool operator != (const KeyValue &rhs) const { - return !(*this == rhs); - } - - bool operator < (const KeyValue & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(KeyValue &a, KeyValue &b); @@ -1523,17 +1836,29 @@ void swap(KeyValue &a, KeyValue &b); std::ostream& operator<<(std::ostream& out, const KeyValue& obj); -class SortingColumn : public virtual ::duckdb_apache::thrift::TBase { +/** + * Sort order within a RowGroup of a leaf column + */ +class SortingColumn : public virtual ::apache::thrift::TBase { public: - SortingColumn(const SortingColumn&); - SortingColumn& operator=(const SortingColumn&); - SortingColumn() : column_idx(0), descending(0), nulls_first(0) { - } + SortingColumn(const SortingColumn&) noexcept; + SortingColumn& operator=(const SortingColumn&) noexcept; + SortingColumn() noexcept; - virtual ~SortingColumn() throw(); + virtual ~SortingColumn() noexcept; + /** + * The ordinal position of the column (in this row group) * + */ int32_t column_idx; + /** + * If true, indicates this column is sorted in descending order. * + */ bool descending; + /** + * If true, nulls will come before non-null values, otherwise, + * nulls go at the end. + */ bool nulls_first; void __set_column_idx(const int32_t val); @@ -1542,26 +1867,9 @@ class SortingColumn : public virtual ::duckdb_apache::thrift::TBase { void __set_nulls_first(const bool val); - bool operator == (const SortingColumn & rhs) const - { - if (!(column_idx == rhs.column_idx)) - return false; - if (!(descending == rhs.descending)) - return false; - if (!(nulls_first == rhs.nulls_first)) - return false; - return true; - } - bool operator != (const SortingColumn &rhs) const { - return !(*this == rhs); - } - - bool operator < (const SortingColumn & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(SortingColumn &a, SortingColumn &b); @@ -1569,17 +1877,32 @@ void swap(SortingColumn &a, SortingColumn &b); std::ostream& operator<<(std::ostream& out, const SortingColumn& obj); -class PageEncodingStats : public virtual ::duckdb_apache::thrift::TBase { +/** + * statistics of a given page type and encoding + */ +class PageEncodingStats : public virtual ::apache::thrift::TBase { public: - PageEncodingStats(const PageEncodingStats&); - PageEncodingStats& operator=(const PageEncodingStats&); - PageEncodingStats() : page_type((PageType::type)0), encoding((Encoding::type)0), count(0) { - } + PageEncodingStats(const PageEncodingStats&) noexcept; + PageEncodingStats& operator=(const PageEncodingStats&) noexcept; + PageEncodingStats() noexcept; - virtual ~PageEncodingStats() throw(); + virtual ~PageEncodingStats() noexcept; + /** + * the page type (data/dic/...) * + * + * @see PageType + */ PageType::type page_type; + /** + * encoding of the page * + * + * @see Encoding + */ Encoding::type encoding; + /** + * number of pages of this type with this encoding * + */ int32_t count; void __set_page_type(const PageType::type val); @@ -1588,26 +1911,9 @@ class PageEncodingStats : public virtual ::duckdb_apache::thrift::TBase { void __set_count(const int32_t val); - bool operator == (const PageEncodingStats & rhs) const - { - if (!(page_type == rhs.page_type)) - return false; - if (!(encoding == rhs.encoding)) - return false; - if (!(count == rhs.count)) - return false; - return true; - } - bool operator != (const PageEncodingStats &rhs) const { - return !(*this == rhs); - } - - bool operator < (const PageEncodingStats & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(PageEncodingStats &a, PageEncodingStats &b); @@ -1615,44 +1921,115 @@ void swap(PageEncodingStats &a, PageEncodingStats &b); std::ostream& operator<<(std::ostream& out, const PageEncodingStats& obj); typedef struct _ColumnMetaData__isset { - _ColumnMetaData__isset() : key_value_metadata(false), index_page_offset(false), dictionary_page_offset(false), statistics(false), encoding_stats(false) {} + _ColumnMetaData__isset() : key_value_metadata(false), index_page_offset(false), dictionary_page_offset(false), statistics(false), encoding_stats(false), bloom_filter_offset(false), bloom_filter_length(false), size_statistics(false) {} bool key_value_metadata :1; bool index_page_offset :1; bool dictionary_page_offset :1; bool statistics :1; bool encoding_stats :1; + bool bloom_filter_offset :1; + bool bloom_filter_length :1; + bool size_statistics :1; } _ColumnMetaData__isset; -class ColumnMetaData : public virtual ::duckdb_apache::thrift::TBase { +/** + * Description for column metadata + */ +class ColumnMetaData : public virtual ::apache::thrift::TBase { public: ColumnMetaData(const ColumnMetaData&); ColumnMetaData& operator=(const ColumnMetaData&); - ColumnMetaData() : type((Type::type)0), codec((CompressionCodec::type)0), num_values(0), total_uncompressed_size(0), total_compressed_size(0), data_page_offset(0), index_page_offset(0), dictionary_page_offset(0) { - } - - virtual ~ColumnMetaData() throw(); + ColumnMetaData() noexcept; + + virtual ~ColumnMetaData() noexcept; + /** + * Type of this column * + * + * @see Type + */ Type::type type; - duckdb::vector encodings; - duckdb::vector path_in_schema; + /** + * Set of all encodings used for this column. The purpose is to validate + * whether we can decode those pages. * + */ + std::vector encodings; + /** + * Path in schema * + */ + std::vector path_in_schema; + /** + * Compression codec * + * + * @see CompressionCodec + */ CompressionCodec::type codec; + /** + * Number of values in this column * + */ int64_t num_values; + /** + * total byte size of all uncompressed pages in this column chunk (including the headers) * + */ int64_t total_uncompressed_size; + /** + * total byte size of all compressed, and potentially encrypted, pages + * in this column chunk (including the headers) * + */ int64_t total_compressed_size; - duckdb::vector key_value_metadata; + /** + * Optional key/value metadata * + */ + std::vector key_value_metadata; + /** + * Byte offset from beginning of file to first data page * + */ int64_t data_page_offset; + /** + * Byte offset from beginning of file to root index page * + */ int64_t index_page_offset; + /** + * Byte offset from the beginning of file to first (only) dictionary page * + */ int64_t dictionary_page_offset; + /** + * optional statistics for this column chunk + */ Statistics statistics; - duckdb::vector encoding_stats; + /** + * Set of all encodings used for pages in this column chunk. + * This information can be used to determine if all data pages are + * dictionary encoded for example * + */ + std::vector encoding_stats; + /** + * Byte offset from beginning of file to Bloom filter data. * + */ + int64_t bloom_filter_offset; + /** + * Size of Bloom filter data including the serialized header, in bytes. + * Added in 2.10 so readers may not read this field from old files and + * it can be obtained after the BloomFilterHeader has been deserialized. + * Writers should write this field so readers can read the bloom filter + * in a single I/O. + */ + int32_t bloom_filter_length; + /** + * Optional statistics to help estimate total memory when converted to in-memory + * representations. The histograms contained in these statistics can + * also be useful in some cases for more fine-grained nullability/list length + * filter pushdown. + */ + SizeStatistics size_statistics; _ColumnMetaData__isset __isset; void __set_type(const Type::type val); - void __set_encodings(const duckdb::vector & val); + void __set_encodings(const std::vector & val); - void __set_path_in_schema(const duckdb::vector & val); + void __set_path_in_schema(const std::vector & val); void __set_codec(const CompressionCodec::type val); @@ -1662,7 +2039,7 @@ class ColumnMetaData : public virtual ::duckdb_apache::thrift::TBase { void __set_total_compressed_size(const int64_t val); - void __set_key_value_metadata(const duckdb::vector & val); + void __set_key_value_metadata(const std::vector & val); void __set_data_page_offset(const int64_t val); @@ -1672,58 +2049,17 @@ class ColumnMetaData : public virtual ::duckdb_apache::thrift::TBase { void __set_statistics(const Statistics& val); - void __set_encoding_stats(const duckdb::vector & val); - - bool operator == (const ColumnMetaData & rhs) const - { - if (!(type == rhs.type)) - return false; - if (!(encodings == rhs.encodings)) - return false; - if (!(path_in_schema == rhs.path_in_schema)) - return false; - if (!(codec == rhs.codec)) - return false; - if (!(num_values == rhs.num_values)) - return false; - if (!(total_uncompressed_size == rhs.total_uncompressed_size)) - return false; - if (!(total_compressed_size == rhs.total_compressed_size)) - return false; - if (__isset.key_value_metadata != rhs.__isset.key_value_metadata) - return false; - else if (__isset.key_value_metadata && !(key_value_metadata == rhs.key_value_metadata)) - return false; - if (!(data_page_offset == rhs.data_page_offset)) - return false; - if (__isset.index_page_offset != rhs.__isset.index_page_offset) - return false; - else if (__isset.index_page_offset && !(index_page_offset == rhs.index_page_offset)) - return false; - if (__isset.dictionary_page_offset != rhs.__isset.dictionary_page_offset) - return false; - else if (__isset.dictionary_page_offset && !(dictionary_page_offset == rhs.dictionary_page_offset)) - return false; - if (__isset.statistics != rhs.__isset.statistics) - return false; - else if (__isset.statistics && !(statistics == rhs.statistics)) - return false; - if (__isset.encoding_stats != rhs.__isset.encoding_stats) - return false; - else if (__isset.encoding_stats && !(encoding_stats == rhs.encoding_stats)) - return false; - return true; - } - bool operator != (const ColumnMetaData &rhs) const { - return !(*this == rhs); - } - - bool operator < (const ColumnMetaData & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + void __set_encoding_stats(const std::vector & val); + + void __set_bloom_filter_offset(const int64_t val); + + void __set_bloom_filter_length(const int32_t val); + + void __set_size_statistics(const SizeStatistics& val); + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(ColumnMetaData &a, ColumnMetaData &b); @@ -1731,30 +2067,18 @@ void swap(ColumnMetaData &a, ColumnMetaData &b); std::ostream& operator<<(std::ostream& out, const ColumnMetaData& obj); -class EncryptionWithFooterKey : public virtual ::duckdb_apache::thrift::TBase { +class EncryptionWithFooterKey : public virtual ::apache::thrift::TBase { public: - EncryptionWithFooterKey(const EncryptionWithFooterKey&); - EncryptionWithFooterKey& operator=(const EncryptionWithFooterKey&); - EncryptionWithFooterKey() { - } + EncryptionWithFooterKey(const EncryptionWithFooterKey&) noexcept; + EncryptionWithFooterKey& operator=(const EncryptionWithFooterKey&) noexcept; + EncryptionWithFooterKey() noexcept; - virtual ~EncryptionWithFooterKey() throw(); + virtual ~EncryptionWithFooterKey() noexcept; - bool operator == (const EncryptionWithFooterKey & /* rhs */) const - { - return true; - } - bool operator != (const EncryptionWithFooterKey &rhs) const { - return !(*this == rhs); - } + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - bool operator < (const EncryptionWithFooterKey & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(EncryptionWithFooterKey &a, EncryptionWithFooterKey &b); @@ -1766,44 +2090,32 @@ typedef struct _EncryptionWithColumnKey__isset { bool key_metadata :1; } _EncryptionWithColumnKey__isset; -class EncryptionWithColumnKey : public virtual ::duckdb_apache::thrift::TBase { +class EncryptionWithColumnKey : public virtual ::apache::thrift::TBase { public: EncryptionWithColumnKey(const EncryptionWithColumnKey&); EncryptionWithColumnKey& operator=(const EncryptionWithColumnKey&); - EncryptionWithColumnKey() : key_metadata() { - } - - virtual ~EncryptionWithColumnKey() throw(); - duckdb::vector path_in_schema; + EncryptionWithColumnKey() noexcept; + + virtual ~EncryptionWithColumnKey() noexcept; + /** + * Column path in schema * + */ + std::vector path_in_schema; + /** + * Retrieval metadata of column encryption key * + */ std::string key_metadata; _EncryptionWithColumnKey__isset __isset; - void __set_path_in_schema(const duckdb::vector & val); + void __set_path_in_schema(const std::vector & val); void __set_key_metadata(const std::string& val); - bool operator == (const EncryptionWithColumnKey & rhs) const - { - if (!(path_in_schema == rhs.path_in_schema)) - return false; - if (__isset.key_metadata != rhs.__isset.key_metadata) - return false; - else if (__isset.key_metadata && !(key_metadata == rhs.key_metadata)) - return false; - return true; - } - bool operator != (const EncryptionWithColumnKey &rhs) const { - return !(*this == rhs); - } - - bool operator < (const EncryptionWithColumnKey & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(EncryptionWithColumnKey &a, EncryptionWithColumnKey &b); @@ -1816,15 +2128,14 @@ typedef struct _ColumnCryptoMetaData__isset { bool ENCRYPTION_WITH_COLUMN_KEY :1; } _ColumnCryptoMetaData__isset; -class ColumnCryptoMetaData : public virtual ::duckdb_apache::thrift::TBase { +class ColumnCryptoMetaData : public virtual ::apache::thrift::TBase { public: ColumnCryptoMetaData(const ColumnCryptoMetaData&); ColumnCryptoMetaData& operator=(const ColumnCryptoMetaData&); - ColumnCryptoMetaData() { - } + ColumnCryptoMetaData() noexcept; - virtual ~ColumnCryptoMetaData() throw(); + virtual ~ColumnCryptoMetaData() noexcept; EncryptionWithFooterKey ENCRYPTION_WITH_FOOTER_KEY; EncryptionWithColumnKey ENCRYPTION_WITH_COLUMN_KEY; @@ -1834,28 +2145,9 @@ class ColumnCryptoMetaData : public virtual ::duckdb_apache::thrift::TBase { void __set_ENCRYPTION_WITH_COLUMN_KEY(const EncryptionWithColumnKey& val); - bool operator == (const ColumnCryptoMetaData & rhs) const - { - if (__isset.ENCRYPTION_WITH_FOOTER_KEY != rhs.__isset.ENCRYPTION_WITH_FOOTER_KEY) - return false; - else if (__isset.ENCRYPTION_WITH_FOOTER_KEY && !(ENCRYPTION_WITH_FOOTER_KEY == rhs.ENCRYPTION_WITH_FOOTER_KEY)) - return false; - if (__isset.ENCRYPTION_WITH_COLUMN_KEY != rhs.__isset.ENCRYPTION_WITH_COLUMN_KEY) - return false; - else if (__isset.ENCRYPTION_WITH_COLUMN_KEY && !(ENCRYPTION_WITH_COLUMN_KEY == rhs.ENCRYPTION_WITH_COLUMN_KEY)) - return false; - return true; - } - bool operator != (const ColumnCryptoMetaData &rhs) const { - return !(*this == rhs); - } - - bool operator < (const ColumnCryptoMetaData & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(ColumnCryptoMetaData &a, ColumnCryptoMetaData &b); @@ -1874,23 +2166,62 @@ typedef struct _ColumnChunk__isset { bool encrypted_column_metadata :1; } _ColumnChunk__isset; -class ColumnChunk : public virtual ::duckdb_apache::thrift::TBase { +class ColumnChunk : public virtual ::apache::thrift::TBase { public: ColumnChunk(const ColumnChunk&); ColumnChunk& operator=(const ColumnChunk&); - ColumnChunk() : file_path(), file_offset(0), offset_index_offset(0), offset_index_length(0), column_index_offset(0), column_index_length(0), encrypted_column_metadata() { - } - - virtual ~ColumnChunk() throw(); + ColumnChunk() noexcept; + + virtual ~ColumnChunk() noexcept; + /** + * File where column data is stored. If not set, assumed to be same file as + * metadata. This path is relative to the current file. + * + */ std::string file_path; + /** + * Deprecated: Byte offset in file_path to the ColumnMetaData + * + * Past use of this field has been inconsistent, with some implementations + * using it to point to the ColumnMetaData and some using it to point to + * the first page in the column chunk. In many cases, the ColumnMetaData at this + * location is wrong. This field is now deprecated and should not be used. + * Writers should set this field to 0 if no ColumnMetaData has been written outside + * the footer. + */ int64_t file_offset; + /** + * Column metadata for this chunk. Some writers may also replicate this at the + * location pointed to by file_path/file_offset. + * Note: while marked as optional, this field is in fact required by most major + * Parquet implementations. As such, writers MUST populate this field. + * + */ ColumnMetaData meta_data; + /** + * File offset of ColumnChunk's OffsetIndex * + */ int64_t offset_index_offset; + /** + * Size of ColumnChunk's OffsetIndex, in bytes * + */ int32_t offset_index_length; + /** + * File offset of ColumnChunk's ColumnIndex * + */ int64_t column_index_offset; + /** + * Size of ColumnChunk's ColumnIndex, in bytes * + */ int32_t column_index_length; + /** + * Crypto metadata of encrypted columns * + */ ColumnCryptoMetaData crypto_metadata; + /** + * Encrypted column metadata for this chunk * + */ std::string encrypted_column_metadata; _ColumnChunk__isset __isset; @@ -1913,54 +2244,9 @@ class ColumnChunk : public virtual ::duckdb_apache::thrift::TBase { void __set_encrypted_column_metadata(const std::string& val); - bool operator == (const ColumnChunk & rhs) const - { - if (__isset.file_path != rhs.__isset.file_path) - return false; - else if (__isset.file_path && !(file_path == rhs.file_path)) - return false; - if (!(file_offset == rhs.file_offset)) - return false; - if (__isset.meta_data != rhs.__isset.meta_data) - return false; - else if (__isset.meta_data && !(meta_data == rhs.meta_data)) - return false; - if (__isset.offset_index_offset != rhs.__isset.offset_index_offset) - return false; - else if (__isset.offset_index_offset && !(offset_index_offset == rhs.offset_index_offset)) - return false; - if (__isset.offset_index_length != rhs.__isset.offset_index_length) - return false; - else if (__isset.offset_index_length && !(offset_index_length == rhs.offset_index_length)) - return false; - if (__isset.column_index_offset != rhs.__isset.column_index_offset) - return false; - else if (__isset.column_index_offset && !(column_index_offset == rhs.column_index_offset)) - return false; - if (__isset.column_index_length != rhs.__isset.column_index_length) - return false; - else if (__isset.column_index_length && !(column_index_length == rhs.column_index_length)) - return false; - if (__isset.crypto_metadata != rhs.__isset.crypto_metadata) - return false; - else if (__isset.crypto_metadata && !(crypto_metadata == rhs.crypto_metadata)) - return false; - if (__isset.encrypted_column_metadata != rhs.__isset.encrypted_column_metadata) - return false; - else if (__isset.encrypted_column_metadata && !(encrypted_column_metadata == rhs.encrypted_column_metadata)) - return false; - return true; - } - bool operator != (const ColumnChunk &rhs) const { - return !(*this == rhs); - } - - bool operator < (const ColumnChunk & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(ColumnChunk &a, ColumnChunk &b); @@ -1975,32 +2261,57 @@ typedef struct _RowGroup__isset { bool ordinal :1; } _RowGroup__isset; -class RowGroup : public virtual ::duckdb_apache::thrift::TBase { +class RowGroup : public virtual ::apache::thrift::TBase { public: RowGroup(const RowGroup&); RowGroup& operator=(const RowGroup&); - RowGroup() : total_byte_size(0), num_rows(0), file_offset(0), total_compressed_size(0), ordinal(0) { - } - - virtual ~RowGroup() throw(); - duckdb::vector columns; + RowGroup() noexcept; + + virtual ~RowGroup() noexcept; + /** + * Metadata for each column chunk in this row group. + * This list must have the same order as the SchemaElement list in FileMetaData. + * + */ + std::vector columns; + /** + * Total byte size of all the uncompressed column data in this row group * + */ int64_t total_byte_size; + /** + * Number of rows in this row group * + */ int64_t num_rows; - duckdb::vector sorting_columns; + /** + * If set, specifies a sort ordering of the rows in this RowGroup. + * The sorting columns can be a subset of all the columns. + */ + std::vector sorting_columns; + /** + * Byte offset from beginning of file to first page (data or dictionary) + * in this row group * + */ int64_t file_offset; + /** + * Total byte size of all compressed (and potentially encrypted) column data + * in this row group * + */ int64_t total_compressed_size; + /** + * Row group ordinal in the file * + */ int16_t ordinal; _RowGroup__isset __isset; - void __set_columns(const duckdb::vector & val); + void __set_columns(const std::vector & val); void __set_total_byte_size(const int64_t val); void __set_num_rows(const int64_t val); - void __set_sorting_columns(const duckdb::vector & val); + void __set_sorting_columns(const std::vector & val); void __set_file_offset(const int64_t val); @@ -2008,42 +2319,9 @@ class RowGroup : public virtual ::duckdb_apache::thrift::TBase { void __set_ordinal(const int16_t val); - bool operator == (const RowGroup & rhs) const - { - if (!(columns == rhs.columns)) - return false; - if (!(total_byte_size == rhs.total_byte_size)) - return false; - if (!(num_rows == rhs.num_rows)) - return false; - if (__isset.sorting_columns != rhs.__isset.sorting_columns) - return false; - else if (__isset.sorting_columns && !(sorting_columns == rhs.sorting_columns)) - return false; - if (__isset.file_offset != rhs.__isset.file_offset) - return false; - else if (__isset.file_offset && !(file_offset == rhs.file_offset)) - return false; - if (__isset.total_compressed_size != rhs.__isset.total_compressed_size) - return false; - else if (__isset.total_compressed_size && !(total_compressed_size == rhs.total_compressed_size)) - return false; - if (__isset.ordinal != rhs.__isset.ordinal) - return false; - else if (__isset.ordinal && !(ordinal == rhs.ordinal)) - return false; - return true; - } - bool operator != (const RowGroup &rhs) const { - return !(*this == rhs); - } - - bool operator < (const RowGroup & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(RowGroup &a, RowGroup &b); @@ -2051,30 +2329,21 @@ void swap(RowGroup &a, RowGroup &b); std::ostream& operator<<(std::ostream& out, const RowGroup& obj); -class TypeDefinedOrder : public virtual ::duckdb_apache::thrift::TBase { +/** + * Empty struct to signal the order defined by the physical or logical type + */ +class TypeDefinedOrder : public virtual ::apache::thrift::TBase { public: - TypeDefinedOrder(const TypeDefinedOrder&); - TypeDefinedOrder& operator=(const TypeDefinedOrder&); - TypeDefinedOrder() { - } - - virtual ~TypeDefinedOrder() throw(); - - bool operator == (const TypeDefinedOrder & /* rhs */) const - { - return true; - } - bool operator != (const TypeDefinedOrder &rhs) const { - return !(*this == rhs); - } + TypeDefinedOrder(const TypeDefinedOrder&) noexcept; + TypeDefinedOrder& operator=(const TypeDefinedOrder&) noexcept; + TypeDefinedOrder() noexcept; - bool operator < (const TypeDefinedOrder & ) const; + virtual ~TypeDefinedOrder() noexcept; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - virtual void printTo(std::ostream& out) const; }; void swap(TypeDefinedOrder &a, TypeDefinedOrder &b); @@ -2086,39 +2355,85 @@ typedef struct _ColumnOrder__isset { bool TYPE_ORDER :1; } _ColumnOrder__isset; -class ColumnOrder : public virtual ::duckdb_apache::thrift::TBase { +/** + * Union to specify the order used for the min_value and max_value fields for a + * column. This union takes the role of an enhanced enum that allows rich + * elements (which will be needed for a collation-based ordering in the future). + * + * Possible values are: + * * TypeDefinedOrder - the column uses the order defined by its logical or + * physical type (if there is no logical type). + * + * If the reader does not support the value of this union, min and max stats + * for this column should be ignored. + */ +class ColumnOrder : public virtual ::apache::thrift::TBase { public: - ColumnOrder(const ColumnOrder&); - ColumnOrder& operator=(const ColumnOrder&); - ColumnOrder() { - } - - virtual ~ColumnOrder() throw(); + ColumnOrder(const ColumnOrder&) noexcept; + ColumnOrder& operator=(const ColumnOrder&) noexcept; + ColumnOrder() noexcept; + + virtual ~ColumnOrder() noexcept; + /** + * The sort orders for logical types are: + * UTF8 - unsigned byte-wise comparison + * INT8 - signed comparison + * INT16 - signed comparison + * INT32 - signed comparison + * INT64 - signed comparison + * UINT8 - unsigned comparison + * UINT16 - unsigned comparison + * UINT32 - unsigned comparison + * UINT64 - unsigned comparison + * DECIMAL - signed comparison of the represented value + * DATE - signed comparison + * TIME_MILLIS - signed comparison + * TIME_MICROS - signed comparison + * TIMESTAMP_MILLIS - signed comparison + * TIMESTAMP_MICROS - signed comparison + * INTERVAL - undefined + * JSON - unsigned byte-wise comparison + * BSON - unsigned byte-wise comparison + * ENUM - unsigned byte-wise comparison + * LIST - undefined + * MAP - undefined + * + * In the absence of logical types, the sort order is determined by the physical type: + * BOOLEAN - false, true + * INT32 - signed comparison + * INT64 - signed comparison + * INT96 (only used for legacy timestamps) - undefined + * FLOAT - signed comparison of the represented value (*) + * DOUBLE - signed comparison of the represented value (*) + * BYTE_ARRAY - unsigned byte-wise comparison + * FIXED_LEN_BYTE_ARRAY - unsigned byte-wise comparison + * + * (*) Because the sorting order is not specified properly for floating + * point values (relations vs. total ordering) the following + * compatibility rules should be applied when reading statistics: + * - If the min is a NaN, it should be ignored. + * - If the max is a NaN, it should be ignored. + * - If the min is +0, the row group may contain -0 values as well. + * - If the max is -0, the row group may contain +0 values as well. + * - When looking for NaN values, min and max should be ignored. + * + * When writing statistics the following rules should be followed: + * - NaNs should not be written to min or max statistics fields. + * - If the computed max value is zero (whether negative or positive), + * `+0.0` should be written into the max statistics field. + * - If the computed min value is zero (whether negative or positive), + * `-0.0` should be written into the min statistics field. + */ TypeDefinedOrder TYPE_ORDER; _ColumnOrder__isset __isset; void __set_TYPE_ORDER(const TypeDefinedOrder& val); - bool operator == (const ColumnOrder & rhs) const - { - if (__isset.TYPE_ORDER != rhs.__isset.TYPE_ORDER) - return false; - else if (__isset.TYPE_ORDER && !(TYPE_ORDER == rhs.TYPE_ORDER)) - return false; - return true; - } - bool operator != (const ColumnOrder &rhs) const { - return !(*this == rhs); - } - - bool operator < (const ColumnOrder & ) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; }; void swap(ColumnOrder &a, ColumnOrder &b); @@ -2126,17 +2441,28 @@ void swap(ColumnOrder &a, ColumnOrder &b); std::ostream& operator<<(std::ostream& out, const ColumnOrder& obj); -class PageLocation : public virtual ::duckdb_apache::thrift::TBase { +class PageLocation : public virtual ::apache::thrift::TBase { public: - PageLocation(const PageLocation&); - PageLocation& operator=(const PageLocation&); - PageLocation() : offset(0), compressed_page_size(0), first_row_index(0) { - } + PageLocation(const PageLocation&) noexcept; + PageLocation& operator=(const PageLocation&) noexcept; + PageLocation() noexcept; - virtual ~PageLocation() throw(); + virtual ~PageLocation() noexcept; + /** + * Offset of the page in the file * + */ int64_t offset; + /** + * Size of the page, including header. Sum of compressed_page_size and header + * length + */ int32_t compressed_page_size; + /** + * Index within the RowGroup of the first row of the page. When an + * OffsetIndex is present, pages must begin on row boundaries + * (repetition_level = 0). + */ int64_t first_row_index; void __set_offset(const int64_t val); @@ -2145,62 +2471,57 @@ class PageLocation : public virtual ::duckdb_apache::thrift::TBase { void __set_first_row_index(const int64_t val); - bool operator == (const PageLocation & rhs) const - { - if (!(offset == rhs.offset)) - return false; - if (!(compressed_page_size == rhs.compressed_page_size)) - return false; - if (!(first_row_index == rhs.first_row_index)) - return false; - return true; - } - bool operator != (const PageLocation &rhs) const { - return !(*this == rhs); - } - - bool operator < (const PageLocation & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(PageLocation &a, PageLocation &b); std::ostream& operator<<(std::ostream& out, const PageLocation& obj); +typedef struct _OffsetIndex__isset { + _OffsetIndex__isset() : unencoded_byte_array_data_bytes(false) {} + bool unencoded_byte_array_data_bytes :1; +} _OffsetIndex__isset; -class OffsetIndex : public virtual ::duckdb_apache::thrift::TBase { +/** + * Optional offsets for each data page in a ColumnChunk. + * + * Forms part of the page index, along with ColumnIndex. + * + * OffsetIndex may be present even if ColumnIndex is not. + */ +class OffsetIndex : public virtual ::apache::thrift::TBase { public: OffsetIndex(const OffsetIndex&); OffsetIndex& operator=(const OffsetIndex&); - OffsetIndex() { - } + OffsetIndex() noexcept; - virtual ~OffsetIndex() throw(); - duckdb::vector page_locations; + virtual ~OffsetIndex() noexcept; + /** + * PageLocations, ordered by increasing PageLocation.offset. It is required + * that page_locations[i].first_row_index < page_locations[i+1].first_row_index. + */ + std::vector page_locations; + /** + * Unencoded/uncompressed size for BYTE_ARRAY types. + * + * See documention for unencoded_byte_array_data_bytes in SizeStatistics for + * more details on this field. + */ + std::vector unencoded_byte_array_data_bytes; - void __set_page_locations(const duckdb::vector & val); + _OffsetIndex__isset __isset; - bool operator == (const OffsetIndex & rhs) const - { - if (!(page_locations == rhs.page_locations)) - return false; - return true; - } - bool operator != (const OffsetIndex &rhs) const { - return !(*this == rhs); - } + void __set_page_locations(const std::vector & val); - bool operator < (const OffsetIndex & ) const; + void __set_unencoded_byte_array_data_bytes(const std::vector & val); - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; - virtual void printTo(std::ostream& out) const; }; void swap(OffsetIndex &a, OffsetIndex &b); @@ -2208,63 +2529,109 @@ void swap(OffsetIndex &a, OffsetIndex &b); std::ostream& operator<<(std::ostream& out, const OffsetIndex& obj); typedef struct _ColumnIndex__isset { - _ColumnIndex__isset() : null_counts(false) {} + _ColumnIndex__isset() : null_counts(false), repetition_level_histograms(false), definition_level_histograms(false) {} bool null_counts :1; + bool repetition_level_histograms :1; + bool definition_level_histograms :1; } _ColumnIndex__isset; -class ColumnIndex : public virtual ::duckdb_apache::thrift::TBase { +/** + * Optional statistics for each data page in a ColumnChunk. + * + * Forms part the page index, along with OffsetIndex. + * + * If this structure is present, OffsetIndex must also be present. + * + * For each field in this structure, [i] refers to the page at + * OffsetIndex.page_locations[i] + */ +class ColumnIndex : public virtual ::apache::thrift::TBase { public: ColumnIndex(const ColumnIndex&); ColumnIndex& operator=(const ColumnIndex&); - ColumnIndex() : boundary_order((BoundaryOrder::type)0) { - } - - virtual ~ColumnIndex() throw(); - duckdb::vector null_pages; - duckdb::vector min_values; - duckdb::vector max_values; + ColumnIndex() noexcept; + + virtual ~ColumnIndex() noexcept; + /** + * A list of Boolean values to determine the validity of the corresponding + * min and max values. If true, a page contains only null values, and writers + * have to set the corresponding entries in min_values and max_values to + * byte[0], so that all lists have the same length. If false, the + * corresponding entries in min_values and max_values must be valid. + */ + std::vector null_pages; + /** + * Two lists containing lower and upper bounds for the values of each page + * determined by the ColumnOrder of the column. These may be the actual + * minimum and maximum values found on a page, but can also be (more compact) + * values that do not exist on a page. For example, instead of storing ""Blart + * Versenwald III", a writer may set min_values[i]="B", max_values[i]="C". + * Such more compact values must still be valid values within the column's + * logical type. Readers must make sure that list entries are populated before + * using them by inspecting null_pages. + */ + std::vector min_values; + std::vector max_values; + /** + * Stores whether both min_values and max_values are ordered and if so, in + * which direction. This allows readers to perform binary searches in both + * lists. Readers cannot assume that max_values[i] <= min_values[i+1], even + * if the lists are ordered. + * + * @see BoundaryOrder + */ BoundaryOrder::type boundary_order; - duckdb::vector null_counts; + /** + * A list containing the number of null values for each page + * + * Writers SHOULD always write this field even if no null values + * are present or the column is not nullable. + * Readers MUST distinguish between null_counts not being present + * and null_count being 0. + * If null_counts are not present, readers MUST NOT assume all + * null counts are 0. + */ + std::vector null_counts; + /** + * Contains repetition level histograms for each page + * concatenated together. The repetition_level_histogram field on + * SizeStatistics contains more details. + * + * When present the length should always be (number of pages * + * (max_repetition_level + 1)) elements. + * + * Element 0 is the first element of the histogram for the first page. + * Element (max_repetition_level + 1) is the first element of the histogram + * for the second page. + * + */ + std::vector repetition_level_histograms; + /** + * Same as repetition_level_histograms except for definitions levels. + * + */ + std::vector definition_level_histograms; _ColumnIndex__isset __isset; - void __set_null_pages(const duckdb::vector & val); + void __set_null_pages(const std::vector & val); - void __set_min_values(const duckdb::vector & val); + void __set_min_values(const std::vector & val); - void __set_max_values(const duckdb::vector & val); + void __set_max_values(const std::vector & val); void __set_boundary_order(const BoundaryOrder::type val); - void __set_null_counts(const duckdb::vector & val); - - bool operator == (const ColumnIndex & rhs) const - { - if (!(null_pages == rhs.null_pages)) - return false; - if (!(min_values == rhs.min_values)) - return false; - if (!(max_values == rhs.max_values)) - return false; - if (!(boundary_order == rhs.boundary_order)) - return false; - if (__isset.null_counts != rhs.__isset.null_counts) - return false; - else if (__isset.null_counts && !(null_counts == rhs.null_counts)) - return false; - return true; - } - bool operator != (const ColumnIndex &rhs) const { - return !(*this == rhs); - } - - bool operator < (const ColumnIndex & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + void __set_null_counts(const std::vector & val); + + void __set_repetition_level_histograms(const std::vector & val); + + void __set_definition_level_histograms(const std::vector & val); + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(ColumnIndex &a, ColumnIndex &b); @@ -2278,17 +2645,26 @@ typedef struct _AesGcmV1__isset { bool supply_aad_prefix :1; } _AesGcmV1__isset; -class AesGcmV1 : public virtual ::duckdb_apache::thrift::TBase { +class AesGcmV1 : public virtual ::apache::thrift::TBase { public: AesGcmV1(const AesGcmV1&); AesGcmV1& operator=(const AesGcmV1&); - AesGcmV1() : aad_prefix(), aad_file_unique(), supply_aad_prefix(0) { - } + AesGcmV1() noexcept; - virtual ~AesGcmV1() throw(); + virtual ~AesGcmV1() noexcept; + /** + * AAD prefix * + */ std::string aad_prefix; + /** + * Unique file identifier part of AAD suffix * + */ std::string aad_file_unique; + /** + * In files encrypted with AAD prefix without storing it, + * readers must supply the prefix * + */ bool supply_aad_prefix; _AesGcmV1__isset __isset; @@ -2299,32 +2675,9 @@ class AesGcmV1 : public virtual ::duckdb_apache::thrift::TBase { void __set_supply_aad_prefix(const bool val); - bool operator == (const AesGcmV1 & rhs) const - { - if (__isset.aad_prefix != rhs.__isset.aad_prefix) - return false; - else if (__isset.aad_prefix && !(aad_prefix == rhs.aad_prefix)) - return false; - if (__isset.aad_file_unique != rhs.__isset.aad_file_unique) - return false; - else if (__isset.aad_file_unique && !(aad_file_unique == rhs.aad_file_unique)) - return false; - if (__isset.supply_aad_prefix != rhs.__isset.supply_aad_prefix) - return false; - else if (__isset.supply_aad_prefix && !(supply_aad_prefix == rhs.supply_aad_prefix)) - return false; - return true; - } - bool operator != (const AesGcmV1 &rhs) const { - return !(*this == rhs); - } - - bool operator < (const AesGcmV1 & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(AesGcmV1 &a, AesGcmV1 &b); @@ -2338,17 +2691,26 @@ typedef struct _AesGcmCtrV1__isset { bool supply_aad_prefix :1; } _AesGcmCtrV1__isset; -class AesGcmCtrV1 : public virtual ::duckdb_apache::thrift::TBase { +class AesGcmCtrV1 : public virtual ::apache::thrift::TBase { public: AesGcmCtrV1(const AesGcmCtrV1&); AesGcmCtrV1& operator=(const AesGcmCtrV1&); - AesGcmCtrV1() : aad_prefix(), aad_file_unique(), supply_aad_prefix(0) { - } + AesGcmCtrV1() noexcept; - virtual ~AesGcmCtrV1() throw(); + virtual ~AesGcmCtrV1() noexcept; + /** + * AAD prefix * + */ std::string aad_prefix; + /** + * Unique file identifier part of AAD suffix * + */ std::string aad_file_unique; + /** + * In files encrypted with AAD prefix without storing it, + * readers must supply the prefix * + */ bool supply_aad_prefix; _AesGcmCtrV1__isset __isset; @@ -2359,32 +2721,9 @@ class AesGcmCtrV1 : public virtual ::duckdb_apache::thrift::TBase { void __set_supply_aad_prefix(const bool val); - bool operator == (const AesGcmCtrV1 & rhs) const - { - if (__isset.aad_prefix != rhs.__isset.aad_prefix) - return false; - else if (__isset.aad_prefix && !(aad_prefix == rhs.aad_prefix)) - return false; - if (__isset.aad_file_unique != rhs.__isset.aad_file_unique) - return false; - else if (__isset.aad_file_unique && !(aad_file_unique == rhs.aad_file_unique)) - return false; - if (__isset.supply_aad_prefix != rhs.__isset.supply_aad_prefix) - return false; - else if (__isset.supply_aad_prefix && !(supply_aad_prefix == rhs.supply_aad_prefix)) - return false; - return true; - } - bool operator != (const AesGcmCtrV1 &rhs) const { - return !(*this == rhs); - } - - bool operator < (const AesGcmCtrV1 & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(AesGcmCtrV1 &a, AesGcmCtrV1 &b); @@ -2397,15 +2736,14 @@ typedef struct _EncryptionAlgorithm__isset { bool AES_GCM_CTR_V1 :1; } _EncryptionAlgorithm__isset; -class EncryptionAlgorithm : public virtual ::duckdb_apache::thrift::TBase { +class EncryptionAlgorithm : public virtual ::apache::thrift::TBase { public: EncryptionAlgorithm(const EncryptionAlgorithm&); EncryptionAlgorithm& operator=(const EncryptionAlgorithm&); - EncryptionAlgorithm() { - } + EncryptionAlgorithm() noexcept; - virtual ~EncryptionAlgorithm() throw(); + virtual ~EncryptionAlgorithm() noexcept; AesGcmV1 AES_GCM_V1; AesGcmCtrV1 AES_GCM_CTR_V1; @@ -2415,28 +2753,9 @@ class EncryptionAlgorithm : public virtual ::duckdb_apache::thrift::TBase { void __set_AES_GCM_CTR_V1(const AesGcmCtrV1& val); - bool operator == (const EncryptionAlgorithm & rhs) const - { - if (__isset.AES_GCM_V1 != rhs.__isset.AES_GCM_V1) - return false; - else if (__isset.AES_GCM_V1 && !(AES_GCM_V1 == rhs.AES_GCM_V1)) - return false; - if (__isset.AES_GCM_CTR_V1 != rhs.__isset.AES_GCM_CTR_V1) - return false; - else if (__isset.AES_GCM_CTR_V1 && !(AES_GCM_CTR_V1 == rhs.AES_GCM_CTR_V1)) - return false; - return true; - } - bool operator != (const EncryptionAlgorithm &rhs) const { - return !(*this == rhs); - } - - bool operator < (const EncryptionAlgorithm & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(EncryptionAlgorithm &a, EncryptionAlgorithm &b); @@ -2452,87 +2771,101 @@ typedef struct _FileMetaData__isset { bool footer_signing_key_metadata :1; } _FileMetaData__isset; -class FileMetaData : public virtual ::duckdb_apache::thrift::TBase { +/** + * Description for file metadata + */ +class FileMetaData : public virtual ::apache::thrift::TBase { public: FileMetaData(const FileMetaData&); FileMetaData& operator=(const FileMetaData&); - FileMetaData() : version(0), num_rows(0), created_by(), footer_signing_key_metadata() { - } + FileMetaData() noexcept; - virtual ~FileMetaData() throw(); + virtual ~FileMetaData() noexcept; + /** + * Version of this file * + */ int32_t version; - duckdb::vector schema; + /** + * Parquet schema for this file. This schema contains metadata for all the columns. + * The schema is represented as a tree with a single root. The nodes of the tree + * are flattened to a list by doing a depth-first traversal. + * The column metadata contains the path in the schema for that column which can be + * used to map columns to nodes in the schema. + * The first element is the root * + */ + std::vector schema; + /** + * Number of rows in this file * + */ int64_t num_rows; - duckdb::vector row_groups; - duckdb::vector key_value_metadata; + /** + * Row groups in this file * + */ + std::vector row_groups; + /** + * Optional key/value metadata * + */ + std::vector key_value_metadata; + /** + * String for application that wrote this file. This should be in the format + * version (build ). + * e.g. impala version 1.0 (build 6cf94d29b2b7115df4de2c06e2ab4326d721eb55) + * + */ std::string created_by; - duckdb::vector column_orders; + /** + * Sort order used for the min_value and max_value fields in the Statistics + * objects and the min_values and max_values fields in the ColumnIndex + * objects of each column in this file. Sort orders are listed in the order + * matching the columns in the schema. The indexes are not necessary the same + * though, because only leaf nodes of the schema are represented in the list + * of sort orders. + * + * Without column_orders, the meaning of the min_value and max_value fields + * in the Statistics object and the ColumnIndex object is undefined. To ensure + * well-defined behaviour, if these fields are written to a Parquet file, + * column_orders must be written as well. + * + * The obsolete min and max fields in the Statistics object are always sorted + * by signed comparison regardless of column_orders. + */ + std::vector column_orders; + /** + * Encryption algorithm. This field is set only in encrypted files + * with plaintext footer. Files with encrypted footer store algorithm id + * in FileCryptoMetaData structure. + */ EncryptionAlgorithm encryption_algorithm; + /** + * Retrieval metadata of key used for signing the footer. + * Used only in encrypted files with plaintext footer. + */ std::string footer_signing_key_metadata; _FileMetaData__isset __isset; void __set_version(const int32_t val); - void __set_schema(const duckdb::vector & val); + void __set_schema(const std::vector & val); void __set_num_rows(const int64_t val); - void __set_row_groups(const duckdb::vector & val); + void __set_row_groups(const std::vector & val); - void __set_key_value_metadata(const duckdb::vector & val); + void __set_key_value_metadata(const std::vector & val); void __set_created_by(const std::string& val); - void __set_column_orders(const duckdb::vector & val); + void __set_column_orders(const std::vector & val); void __set_encryption_algorithm(const EncryptionAlgorithm& val); void __set_footer_signing_key_metadata(const std::string& val); - bool operator == (const FileMetaData & rhs) const - { - if (!(version == rhs.version)) - return false; - if (!(schema == rhs.schema)) - return false; - if (!(num_rows == rhs.num_rows)) - return false; - if (!(row_groups == rhs.row_groups)) - return false; - if (__isset.key_value_metadata != rhs.__isset.key_value_metadata) - return false; - else if (__isset.key_value_metadata && !(key_value_metadata == rhs.key_value_metadata)) - return false; - if (__isset.created_by != rhs.__isset.created_by) - return false; - else if (__isset.created_by && !(created_by == rhs.created_by)) - return false; - if (__isset.column_orders != rhs.__isset.column_orders) - return false; - else if (__isset.column_orders && !(column_orders == rhs.column_orders)) - return false; - if (__isset.encryption_algorithm != rhs.__isset.encryption_algorithm) - return false; - else if (__isset.encryption_algorithm && !(encryption_algorithm == rhs.encryption_algorithm)) - return false; - if (__isset.footer_signing_key_metadata != rhs.__isset.footer_signing_key_metadata) - return false; - else if (__isset.footer_signing_key_metadata && !(footer_signing_key_metadata == rhs.footer_signing_key_metadata)) - return false; - return true; - } - bool operator != (const FileMetaData &rhs) const { - return !(*this == rhs); - } - - bool operator < (const FileMetaData & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(FileMetaData &a, FileMetaData &b); @@ -2544,16 +2877,27 @@ typedef struct _FileCryptoMetaData__isset { bool key_metadata :1; } _FileCryptoMetaData__isset; -class FileCryptoMetaData : public virtual ::duckdb_apache::thrift::TBase { +/** + * Crypto metadata for files with encrypted footer * + */ +class FileCryptoMetaData : public virtual ::apache::thrift::TBase { public: FileCryptoMetaData(const FileCryptoMetaData&); FileCryptoMetaData& operator=(const FileCryptoMetaData&); - FileCryptoMetaData() : key_metadata() { - } - - virtual ~FileCryptoMetaData() throw(); + FileCryptoMetaData() noexcept; + + virtual ~FileCryptoMetaData() noexcept; + /** + * Encryption algorithm. This field is only used for files + * with encrypted footer. Files with plaintext footer store algorithm id + * inside footer (FileMetaData structure). + */ EncryptionAlgorithm encryption_algorithm; + /** + * Retrieval metadata of key used for encryption of footer, + * and (possibly) columns * + */ std::string key_metadata; _FileCryptoMetaData__isset __isset; @@ -2562,32 +2906,15 @@ class FileCryptoMetaData : public virtual ::duckdb_apache::thrift::TBase { void __set_key_metadata(const std::string& val); - bool operator == (const FileCryptoMetaData & rhs) const - { - if (!(encryption_algorithm == rhs.encryption_algorithm)) - return false; - if (__isset.key_metadata != rhs.__isset.key_metadata) - return false; - else if (__isset.key_metadata && !(key_metadata == rhs.key_metadata)) - return false; - return true; - } - bool operator != (const FileCryptoMetaData &rhs) const { - return !(*this == rhs); - } - - bool operator < (const FileCryptoMetaData & ) const; - - uint32_t read(::duckdb_apache::thrift::protocol::TProtocol* iprot); - uint32_t write(::duckdb_apache::thrift::protocol::TProtocol* oprot) const; - - virtual void printTo(std::ostream& out) const; + uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + }; void swap(FileCryptoMetaData &a, FileCryptoMetaData &b); std::ostream& operator<<(std::ostream& out, const FileCryptoMetaData& obj); -}} // namespace +} // namespace #endif From f3913f9c77d4affe1d4d84c59a7a7ba7cf6ee96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20M=C3=BChleisen?= Date: Mon, 7 Oct 2024 15:48:35 +0200 Subject: [PATCH 36/89] working? --- extension/parquet/column_writer.cpp | 8 +- extension/parquet/geo_parquet.cpp | 4 +- extension/parquet/include/column_writer.hpp | 8 +- .../parquet/include/parquet_decimal_utils.hpp | 3 +- extension/parquet/parquet_extension.cpp | 6 +- extension/parquet/parquet_metadata.cpp | 4 +- extension/parquet/parquet_reader.cpp | 6 +- extension/parquet/parquet_statistics.cpp | 3 +- extension/parquet/parquet_writer.cpp | 3 +- third_party/parquet/README | 5 - third_party/parquet/generate.sh | 8 + third_party/parquet/parquet_types.cpp | 1006 ++++++++++++++++- third_party/parquet/parquet_types.h | 139 ++- third_party/parquet/windows_compatibility.h | 9 - 14 files changed, 1088 insertions(+), 124 deletions(-) delete mode 100644 third_party/parquet/README create mode 100755 third_party/parquet/generate.sh delete mode 100644 third_party/parquet/windows_compatibility.h diff --git a/extension/parquet/column_writer.cpp b/extension/parquet/column_writer.cpp index 59cd46471b5..0fef8565eec 100644 --- a/extension/parquet/column_writer.cpp +++ b/extension/parquet/column_writer.cpp @@ -436,7 +436,7 @@ unique_ptr BasicColumnWriter::InitializeWriteState(duckdb_par } void BasicColumnWriter::RegisterToRowGroup(duckdb_parquet::RowGroup &row_group) { - format::ColumnChunk column_chunk; + duckdb_parquet::ColumnChunk column_chunk; column_chunk.__isset.meta_data = true; column_chunk.meta_data.codec = writer.GetCodec(); column_chunk.meta_data.path_in_schema = schema_path; @@ -646,8 +646,7 @@ void BasicColumnWriter::Write(ColumnWriterState &state_p, Vector &vector, idx_t } } -void BasicColumnWriter::SetParquetStatistics(BasicColumnWriterState &state, - duckdb_parquet::ColumnChunk &column_chunk) { +void BasicColumnWriter::SetParquetStatistics(BasicColumnWriterState &state, duckdb_parquet::ColumnChunk &column_chunk) { if (max_repeat == 0) { column_chunk.meta_data.statistics.null_count = NumericCast(state.null_count); column_chunk.meta_data.statistics.__isset.null_count = true; @@ -1844,8 +1843,7 @@ class ListColumnWriter : public ColumnWriter { class ListColumnWriterState : public ColumnWriterState { public: - ListColumnWriterState(duckdb_parquet::RowGroup &row_group, idx_t col_idx) - : row_group(row_group), col_idx(col_idx) { + ListColumnWriterState(duckdb_parquet::RowGroup &row_group, idx_t col_idx) : row_group(row_group), col_idx(col_idx) { } ~ListColumnWriterState() override = default; diff --git a/extension/parquet/geo_parquet.cpp b/extension/parquet/geo_parquet.cpp index db08aa07b03..b806eafb941 100644 --- a/extension/parquet/geo_parquet.cpp +++ b/extension/parquet/geo_parquet.cpp @@ -176,8 +176,8 @@ void GeoParquetColumnMetadataWriter::Update(GeoParquetColumnMetadata &meta, Vect // GeoParquetFileMetadata //------------------------------------------------------------------------------ -unique_ptr -GeoParquetFileMetadata::TryRead(const duckdb_parquet::FileMetaData &file_meta_data, ClientContext &context) { +unique_ptr GeoParquetFileMetadata::TryRead(const duckdb_parquet::FileMetaData &file_meta_data, + ClientContext &context) { for (auto &kv : file_meta_data.key_value_metadata) { if (kv.key == "geo") { const auto geo_metadata = yyjson_read(kv.value.c_str(), kv.value.size(), 0); diff --git a/extension/parquet/include/column_writer.hpp b/extension/parquet/include/column_writer.hpp index b10822ef5a1..619370b6df8 100644 --- a/extension/parquet/include/column_writer.hpp +++ b/extension/parquet/include/column_writer.hpp @@ -80,10 +80,10 @@ class ColumnWriter { public: //! Create the column writer for a specific type recursively static unique_ptr - CreateWriterRecursive(ClientContext &context, vector &schemas, - ParquetWriter &writer, const LogicalType &type, const string &name, - vector schema_path, optional_ptr field_ids, idx_t max_repeat = 0, - idx_t max_define = 1, bool can_have_nulls = true); + CreateWriterRecursive(ClientContext &context, vector &schemas, ParquetWriter &writer, + const LogicalType &type, const string &name, vector schema_path, + optional_ptr field_ids, idx_t max_repeat = 0, idx_t max_define = 1, + bool can_have_nulls = true); virtual unique_ptr InitializeWriteState(duckdb_parquet::RowGroup &row_group) = 0; diff --git a/extension/parquet/include/parquet_decimal_utils.hpp b/extension/parquet/include/parquet_decimal_utils.hpp index cb0276aa2d5..119ed5672b3 100644 --- a/extension/parquet/include/parquet_decimal_utils.hpp +++ b/extension/parquet/include/parquet_decimal_utils.hpp @@ -16,8 +16,7 @@ namespace duckdb { class ParquetDecimalUtils { public: template - static PHYSICAL_TYPE ReadDecimalValue(const_data_ptr_t pointer, idx_t size, - const duckdb_parquet::SchemaElement &) { + static PHYSICAL_TYPE ReadDecimalValue(const_data_ptr_t pointer, idx_t size, const duckdb_parquet::SchemaElement &) { PHYSICAL_TYPE res = 0; auto res_ptr = (uint8_t *)&res; diff --git a/extension/parquet/parquet_extension.cpp b/extension/parquet/parquet_extension.cpp index 34f9ea53c67..416f69fd572 100644 --- a/extension/parquet/parquet_extension.cpp +++ b/extension/parquet/parquet_extension.cpp @@ -1351,8 +1351,7 @@ unique_ptr ParquetWriteInitializeLocal(ExecutionContext &cont // FIXME: Have these be generated instead template <> -const char *EnumUtil::ToChars( - duckdb_parquet::CompressionCodec::type value) { +const char *EnumUtil::ToChars(duckdb_parquet::CompressionCodec::type value) { switch (value) { case CompressionCodec::UNCOMPRESSED: return "UNCOMPRESSED"; @@ -1384,8 +1383,7 @@ const char *EnumUtil::ToChars( } template <> -duckdb_parquet::CompressionCodec::type -EnumUtil::FromString(const char *value) { +duckdb_parquet::CompressionCodec::type EnumUtil::FromString(const char *value) { if (StringUtil::Equals(value, "UNCOMPRESSED")) { return CompressionCodec::UNCOMPRESSED; } diff --git a/extension/parquet/parquet_metadata.cpp b/extension/parquet/parquet_metadata.cpp index 6e629b549fa..ee3cb3ab08b 100644 --- a/extension/parquet/parquet_metadata.cpp +++ b/extension/parquet/parquet_metadata.cpp @@ -166,8 +166,8 @@ void ParquetMetaDataOperatorData::BindMetaData(vector &return_types return_types.emplace_back(LogicalType::MAP(LogicalType::BLOB, LogicalType::BLOB)); } -Value ConvertParquetStats(const LogicalType &type, const duckdb_parquet::SchemaElement &schema_ele, - bool stats_is_set, const std::string &stats) { +Value ConvertParquetStats(const LogicalType &type, const duckdb_parquet::SchemaElement &schema_ele, bool stats_is_set, + const std::string &stats) { if (!stats_is_set) { return Value(LogicalType::VARCHAR); } diff --git a/extension/parquet/parquet_reader.cpp b/extension/parquet/parquet_reader.cpp index 1072cada775..f78dfda15fc 100644 --- a/extension/parquet/parquet_reader.cpp +++ b/extension/parquet/parquet_reader.cpp @@ -147,6 +147,10 @@ LogicalType ParquetReader::DeriveLogicalType(const SchemaElement &s_ele, bool bi } } if (s_ele.__isset.converted_type) { + // Legacy NULL type, does no longer exist, but files are still around of course + if (static_cast(s_ele.converted_type) == 24) { + return LogicalTypeId::SQLNULL; + } switch (s_ele.converted_type) { case ConvertedType::INT_8: if (s_ele.type == Type::INT32) { @@ -251,8 +255,6 @@ LogicalType ParquetReader::DeriveLogicalType(const SchemaElement &s_ele, bool bi return LogicalType::INTERVAL; case ConvertedType::JSON: return LogicalType::JSON(); - case ConvertedType::NULL_TYPE: - return LogicalTypeId::SQLNULL; case ConvertedType::MAP: case ConvertedType::MAP_KEY_VALUE: case ConvertedType::LIST: diff --git a/extension/parquet/parquet_statistics.cpp b/extension/parquet/parquet_statistics.cpp index 228de5a3503..82acbacb8eb 100644 --- a/extension/parquet/parquet_statistics.cpp +++ b/extension/parquet/parquet_statistics.cpp @@ -45,8 +45,7 @@ static unique_ptr CreateNumericStats(const LogicalType &type, return stats.ToUnique(); } -Value ParquetStatisticsUtils::ConvertValue(const LogicalType &type, - const duckdb_parquet::SchemaElement &schema_ele, +Value ParquetStatisticsUtils::ConvertValue(const LogicalType &type, const duckdb_parquet::SchemaElement &schema_ele, const std::string &stats) { auto stats_data = const_data_ptr_cast(stats.c_str()); switch (type.id()) { diff --git a/extension/parquet/parquet_writer.cpp b/extension/parquet/parquet_writer.cpp index 53aa4dc4780..64ba267cc9d 100644 --- a/extension/parquet/parquet_writer.cpp +++ b/extension/parquet/parquet_writer.cpp @@ -167,8 +167,7 @@ Type::type ParquetWriter::DuckDBTypeToParquetType(const LogicalType &duckdb_type throw NotImplementedException("Unimplemented type for Parquet \"%s\"", duckdb_type.ToString()); } -void ParquetWriter::SetSchemaProperties(const LogicalType &duckdb_type, - duckdb_parquet::SchemaElement &schema_ele) { +void ParquetWriter::SetSchemaProperties(const LogicalType &duckdb_type, duckdb_parquet::SchemaElement &schema_ele) { if (duckdb_type.IsJSONType()) { schema_ele.converted_type = ConvertedType::JSON; schema_ele.__isset.converted_type = true; diff --git a/third_party/parquet/README b/third_party/parquet/README deleted file mode 100644 index f4f8098b4b1..00000000000 --- a/third_party/parquet/README +++ /dev/null @@ -1,5 +0,0 @@ -thrift --gen "cpp:no_ostream_operators=true,no_default_operators=true" parquet.thrift - - -// I'M SURE WHAT I AM DOING -namespace apache = duckdb_apache; diff --git a/third_party/parquet/generate.sh b/third_party/parquet/generate.sh new file mode 100755 index 00000000000..bb82af9ee95 --- /dev/null +++ b/third_party/parquet/generate.sh @@ -0,0 +1,8 @@ +#!/bin/bash +rm -rf gen-cpp +thrift --gen "cpp:no_default_operators=true" parquet.thrift +cp gen-cpp/* . +sed -i .bak -e "s/std::vector/duckdb::vector/" parquet_types.* +sed -i .bak -e "s/namespace duckdb_parquet {/namespace apache = duckdb_apache;\n\nnamespace duckdb_parquet {/" parquet_types.h +rm *.bak +rm -rf gen-cpp \ No newline at end of file diff --git a/third_party/parquet/parquet_types.cpp b/third_party/parquet/parquet_types.cpp index 76cac6b0bd8..cd989782f9d 100644 --- a/third_party/parquet/parquet_types.cpp +++ b/third_party/parquet/parquet_types.cpp @@ -35,6 +35,25 @@ const char* _kTypeNames[] = { }; const std::map _Type_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(8, _kTypeValues, _kTypeNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); +std::ostream& operator<<(std::ostream& out, const Type::type& val) { + std::map::const_iterator it = _Type_VALUES_TO_NAMES.find(val); + if (it != _Type_VALUES_TO_NAMES.end()) { + out << it->second; + } else { + out << static_cast(val); + } + return out; +} + +std::string to_string(const Type::type& val) { + std::map::const_iterator it = _Type_VALUES_TO_NAMES.find(val); + if (it != _Type_VALUES_TO_NAMES.end()) { + return std::string(it->second); + } else { + return std::to_string(static_cast(val)); + } +} + int _kConvertedTypeValues[] = { /** * a BYTE_ARRAY actually contains UTF8 encoded chars @@ -285,6 +304,25 @@ const char* _kConvertedTypeNames[] = { }; const std::map _ConvertedType_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(22, _kConvertedTypeValues, _kConvertedTypeNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); +std::ostream& operator<<(std::ostream& out, const ConvertedType::type& val) { + std::map::const_iterator it = _ConvertedType_VALUES_TO_NAMES.find(val); + if (it != _ConvertedType_VALUES_TO_NAMES.end()) { + out << it->second; + } else { + out << static_cast(val); + } + return out; +} + +std::string to_string(const ConvertedType::type& val) { + std::map::const_iterator it = _ConvertedType_VALUES_TO_NAMES.find(val); + if (it != _ConvertedType_VALUES_TO_NAMES.end()) { + return std::string(it->second); + } else { + return std::to_string(static_cast(val)); + } +} + int _kFieldRepetitionTypeValues[] = { /** * This field is required (can not be null) and each row has exactly 1 value. @@ -315,6 +353,25 @@ const char* _kFieldRepetitionTypeNames[] = { }; const std::map _FieldRepetitionType_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(3, _kFieldRepetitionTypeValues, _kFieldRepetitionTypeNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); +std::ostream& operator<<(std::ostream& out, const FieldRepetitionType::type& val) { + std::map::const_iterator it = _FieldRepetitionType_VALUES_TO_NAMES.find(val); + if (it != _FieldRepetitionType_VALUES_TO_NAMES.end()) { + out << it->second; + } else { + out << static_cast(val); + } + return out; +} + +std::string to_string(const FieldRepetitionType::type& val) { + std::map::const_iterator it = _FieldRepetitionType_VALUES_TO_NAMES.find(val); + if (it != _FieldRepetitionType_VALUES_TO_NAMES.end()) { + return std::string(it->second); + } else { + return std::to_string(static_cast(val)); + } +} + int _kEncodingValues[] = { /** * Default encoding. @@ -439,6 +496,25 @@ const char* _kEncodingNames[] = { }; const std::map _Encoding_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(9, _kEncodingValues, _kEncodingNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); +std::ostream& operator<<(std::ostream& out, const Encoding::type& val) { + std::map::const_iterator it = _Encoding_VALUES_TO_NAMES.find(val); + if (it != _Encoding_VALUES_TO_NAMES.end()) { + out << it->second; + } else { + out << static_cast(val); + } + return out; +} + +std::string to_string(const Encoding::type& val) { + std::map::const_iterator it = _Encoding_VALUES_TO_NAMES.find(val); + if (it != _Encoding_VALUES_TO_NAMES.end()) { + return std::string(it->second); + } else { + return std::to_string(static_cast(val)); + } +} + int _kCompressionCodecValues[] = { CompressionCodec::UNCOMPRESSED, CompressionCodec::SNAPPY, @@ -461,6 +537,25 @@ const char* _kCompressionCodecNames[] = { }; const std::map _CompressionCodec_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(8, _kCompressionCodecValues, _kCompressionCodecNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); +std::ostream& operator<<(std::ostream& out, const CompressionCodec::type& val) { + std::map::const_iterator it = _CompressionCodec_VALUES_TO_NAMES.find(val); + if (it != _CompressionCodec_VALUES_TO_NAMES.end()) { + out << it->second; + } else { + out << static_cast(val); + } + return out; +} + +std::string to_string(const CompressionCodec::type& val) { + std::map::const_iterator it = _CompressionCodec_VALUES_TO_NAMES.find(val); + if (it != _CompressionCodec_VALUES_TO_NAMES.end()) { + return std::string(it->second); + } else { + return std::to_string(static_cast(val)); + } +} + int _kPageTypeValues[] = { PageType::DATA_PAGE, PageType::INDEX_PAGE, @@ -475,6 +570,25 @@ const char* _kPageTypeNames[] = { }; const std::map _PageType_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(4, _kPageTypeValues, _kPageTypeNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); +std::ostream& operator<<(std::ostream& out, const PageType::type& val) { + std::map::const_iterator it = _PageType_VALUES_TO_NAMES.find(val); + if (it != _PageType_VALUES_TO_NAMES.end()) { + out << it->second; + } else { + out << static_cast(val); + } + return out; +} + +std::string to_string(const PageType::type& val) { + std::map::const_iterator it = _PageType_VALUES_TO_NAMES.find(val); + if (it != _PageType_VALUES_TO_NAMES.end()) { + return std::string(it->second); + } else { + return std::to_string(static_cast(val)); + } +} + int _kBoundaryOrderValues[] = { BoundaryOrder::UNORDERED, BoundaryOrder::ASCENDING, @@ -487,6 +601,25 @@ const char* _kBoundaryOrderNames[] = { }; const std::map _BoundaryOrder_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(3, _kBoundaryOrderValues, _kBoundaryOrderNames), ::apache::thrift::TEnumIterator(-1, nullptr, nullptr)); +std::ostream& operator<<(std::ostream& out, const BoundaryOrder::type& val) { + std::map::const_iterator it = _BoundaryOrder_VALUES_TO_NAMES.find(val); + if (it != _BoundaryOrder_VALUES_TO_NAMES.end()) { + out << it->second; + } else { + out << static_cast(val); + } + return out; +} + +std::string to_string(const BoundaryOrder::type& val) { + std::map::const_iterator it = _BoundaryOrder_VALUES_TO_NAMES.find(val); + if (it != _BoundaryOrder_VALUES_TO_NAMES.end()) { + return std::string(it->second); + } else { + return std::to_string(static_cast(val)); + } +} + SizeStatistics::~SizeStatistics() noexcept { } @@ -500,15 +633,21 @@ void SizeStatistics::__set_unencoded_byte_array_data_bytes(const int64_t val) { __isset.unencoded_byte_array_data_bytes = true; } -void SizeStatistics::__set_repetition_level_histogram(const std::vector & val) { +void SizeStatistics::__set_repetition_level_histogram(const duckdb::vector & val) { this->repetition_level_histogram = val; __isset.repetition_level_histogram = true; } -void SizeStatistics::__set_definition_level_histogram(const std::vector & val) { +void SizeStatistics::__set_definition_level_histogram(const duckdb::vector & val) { this->definition_level_histogram = val; __isset.definition_level_histogram = true; } +std::ostream& operator<<(std::ostream& out, const SizeStatistics& obj) +{ + obj.printTo(out); + return out; +} + uint32_t SizeStatistics::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -605,7 +744,7 @@ uint32_t SizeStatistics::write(::apache::thrift::protocol::TProtocol* oprot) con xfer += oprot->writeFieldBegin("repetition_level_histogram", ::apache::thrift::protocol::T_LIST, 2); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->repetition_level_histogram.size())); - std::vector ::const_iterator _iter10; + duckdb::vector ::const_iterator _iter10; for (_iter10 = this->repetition_level_histogram.begin(); _iter10 != this->repetition_level_histogram.end(); ++_iter10) { xfer += oprot->writeI64((*_iter10)); @@ -618,7 +757,7 @@ uint32_t SizeStatistics::write(::apache::thrift::protocol::TProtocol* oprot) con xfer += oprot->writeFieldBegin("definition_level_histogram", ::apache::thrift::protocol::T_LIST, 3); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->definition_level_histogram.size())); - std::vector ::const_iterator _iter11; + duckdb::vector ::const_iterator _iter11; for (_iter11 = this->definition_level_histogram.begin(); _iter11 != this->definition_level_histogram.end(); ++_iter11) { xfer += oprot->writeI64((*_iter11)); @@ -653,6 +792,15 @@ SizeStatistics& SizeStatistics::operator=(const SizeStatistics& other13) { __isset = other13.__isset; return *this; } +void SizeStatistics::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "SizeStatistics("; + out << "unencoded_byte_array_data_bytes="; (__isset.unencoded_byte_array_data_bytes ? (out << to_string(unencoded_byte_array_data_bytes)) : (out << "")); + out << ", " << "repetition_level_histogram="; (__isset.repetition_level_histogram ? (out << to_string(repetition_level_histogram)) : (out << "")); + out << ", " << "definition_level_histogram="; (__isset.definition_level_histogram ? (out << to_string(definition_level_histogram)) : (out << "")); + out << ")"; +} + Statistics::~Statistics() noexcept { } @@ -707,6 +855,12 @@ void Statistics::__set_is_min_value_exact(const bool val) { this->is_min_value_exact = val; __isset.is_min_value_exact = true; } +std::ostream& operator<<(std::ostream& out, const Statistics& obj) +{ + obj.printTo(out); + return out; +} + uint32_t Statistics::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -891,12 +1045,32 @@ Statistics& Statistics::operator=(const Statistics& other15) { __isset = other15.__isset; return *this; } +void Statistics::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "Statistics("; + out << "max="; (__isset.max ? (out << to_string(max)) : (out << "")); + out << ", " << "min="; (__isset.min ? (out << to_string(min)) : (out << "")); + out << ", " << "null_count="; (__isset.null_count ? (out << to_string(null_count)) : (out << "")); + out << ", " << "distinct_count="; (__isset.distinct_count ? (out << to_string(distinct_count)) : (out << "")); + out << ", " << "max_value="; (__isset.max_value ? (out << to_string(max_value)) : (out << "")); + out << ", " << "min_value="; (__isset.min_value ? (out << to_string(min_value)) : (out << "")); + out << ", " << "is_max_value_exact="; (__isset.is_max_value_exact ? (out << to_string(is_max_value_exact)) : (out << "")); + out << ", " << "is_min_value_exact="; (__isset.is_min_value_exact ? (out << to_string(is_min_value_exact)) : (out << "")); + out << ")"; +} + StringType::~StringType() noexcept { } StringType::StringType() noexcept { } +std::ostream& operator<<(std::ostream& out, const StringType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t StringType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -949,12 +1123,24 @@ StringType& StringType::operator=(const StringType& other17) noexcept { (void) other17; return *this; } +void StringType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "StringType("; + out << ")"; +} + UUIDType::~UUIDType() noexcept { } UUIDType::UUIDType() noexcept { } +std::ostream& operator<<(std::ostream& out, const UUIDType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t UUIDType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1007,12 +1193,24 @@ UUIDType& UUIDType::operator=(const UUIDType& other19) noexcept { (void) other19; return *this; } +void UUIDType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "UUIDType("; + out << ")"; +} + MapType::~MapType() noexcept { } MapType::MapType() noexcept { } +std::ostream& operator<<(std::ostream& out, const MapType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t MapType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1065,12 +1263,24 @@ MapType& MapType::operator=(const MapType& other21) noexcept { (void) other21; return *this; } +void MapType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "MapType("; + out << ")"; +} + ListType::~ListType() noexcept { } ListType::ListType() noexcept { } +std::ostream& operator<<(std::ostream& out, const ListType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t ListType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1123,12 +1333,24 @@ ListType& ListType::operator=(const ListType& other23) noexcept { (void) other23; return *this; } +void ListType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "ListType("; + out << ")"; +} + EnumType::~EnumType() noexcept { } EnumType::EnumType() noexcept { } +std::ostream& operator<<(std::ostream& out, const EnumType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t EnumType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1181,12 +1403,24 @@ EnumType& EnumType::operator=(const EnumType& other25) noexcept { (void) other25; return *this; } +void EnumType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "EnumType("; + out << ")"; +} + DateType::~DateType() noexcept { } DateType::DateType() noexcept { } +std::ostream& operator<<(std::ostream& out, const DateType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t DateType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1239,12 +1473,24 @@ DateType& DateType::operator=(const DateType& other27) noexcept { (void) other27; return *this; } +void DateType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "DateType("; + out << ")"; +} + Float16Type::~Float16Type() noexcept { } Float16Type::Float16Type() noexcept { } +std::ostream& operator<<(std::ostream& out, const Float16Type& obj) +{ + obj.printTo(out); + return out; +} + uint32_t Float16Type::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1297,12 +1543,24 @@ Float16Type& Float16Type::operator=(const Float16Type& other29) noexcept { (void) other29; return *this; } +void Float16Type::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "Float16Type("; + out << ")"; +} + NullType::~NullType() noexcept { } NullType::NullType() noexcept { } +std::ostream& operator<<(std::ostream& out, const NullType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t NullType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1355,6 +1613,12 @@ NullType& NullType::operator=(const NullType& other31) noexcept { (void) other31; return *this; } +void NullType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "NullType("; + out << ")"; +} + DecimalType::~DecimalType() noexcept { } @@ -1371,6 +1635,12 @@ void DecimalType::__set_scale(const int32_t val) { void DecimalType::__set_precision(const int32_t val) { this->precision = val; } +std::ostream& operator<<(std::ostream& out, const DecimalType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t DecimalType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1460,12 +1730,26 @@ DecimalType& DecimalType::operator=(const DecimalType& other33) noexcept { precision = other33.precision; return *this; } +void DecimalType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "DecimalType("; + out << "scale=" << to_string(scale); + out << ", " << "precision=" << to_string(precision); + out << ")"; +} + MilliSeconds::~MilliSeconds() noexcept { } MilliSeconds::MilliSeconds() noexcept { } +std::ostream& operator<<(std::ostream& out, const MilliSeconds& obj) +{ + obj.printTo(out); + return out; +} + uint32_t MilliSeconds::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1518,12 +1802,24 @@ MilliSeconds& MilliSeconds::operator=(const MilliSeconds& other35) noexcept { (void) other35; return *this; } +void MilliSeconds::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "MilliSeconds("; + out << ")"; +} + MicroSeconds::~MicroSeconds() noexcept { } MicroSeconds::MicroSeconds() noexcept { } +std::ostream& operator<<(std::ostream& out, const MicroSeconds& obj) +{ + obj.printTo(out); + return out; +} + uint32_t MicroSeconds::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1576,12 +1872,24 @@ MicroSeconds& MicroSeconds::operator=(const MicroSeconds& other37) noexcept { (void) other37; return *this; } +void MicroSeconds::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "MicroSeconds("; + out << ")"; +} + NanoSeconds::~NanoSeconds() noexcept { } NanoSeconds::NanoSeconds() noexcept { } +std::ostream& operator<<(std::ostream& out, const NanoSeconds& obj) +{ + obj.printTo(out); + return out; +} + uint32_t NanoSeconds::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1634,6 +1942,12 @@ NanoSeconds& NanoSeconds::operator=(const NanoSeconds& other39) noexcept { (void) other39; return *this; } +void NanoSeconds::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "NanoSeconds("; + out << ")"; +} + TimeUnit::~TimeUnit() noexcept { } @@ -1655,6 +1969,12 @@ void TimeUnit::__set_NANOS(const NanoSeconds& val) { this->NANOS = val; __isset.NANOS = true; } +std::ostream& operator<<(std::ostream& out, const TimeUnit& obj) +{ + obj.printTo(out); + return out; +} + uint32_t TimeUnit::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1759,6 +2079,15 @@ TimeUnit& TimeUnit::operator=(const TimeUnit& other41) noexcept { __isset = other41.__isset; return *this; } +void TimeUnit::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "TimeUnit("; + out << "MILLIS="; (__isset.MILLIS ? (out << to_string(MILLIS)) : (out << "")); + out << ", " << "MICROS="; (__isset.MICROS ? (out << to_string(MICROS)) : (out << "")); + out << ", " << "NANOS="; (__isset.NANOS ? (out << to_string(NANOS)) : (out << "")); + out << ")"; +} + TimestampType::~TimestampType() noexcept { } @@ -1774,6 +2103,12 @@ void TimestampType::__set_isAdjustedToUTC(const bool val) { void TimestampType::__set_unit(const TimeUnit& val) { this->unit = val; } +std::ostream& operator<<(std::ostream& out, const TimestampType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t TimestampType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1863,6 +2198,14 @@ TimestampType& TimestampType::operator=(const TimestampType& other43) noexcept { unit = other43.unit; return *this; } +void TimestampType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "TimestampType("; + out << "isAdjustedToUTC=" << to_string(isAdjustedToUTC); + out << ", " << "unit=" << to_string(unit); + out << ")"; +} + TimeType::~TimeType() noexcept { } @@ -1878,6 +2221,12 @@ void TimeType::__set_isAdjustedToUTC(const bool val) { void TimeType::__set_unit(const TimeUnit& val) { this->unit = val; } +std::ostream& operator<<(std::ostream& out, const TimeType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t TimeType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -1967,6 +2316,14 @@ TimeType& TimeType::operator=(const TimeType& other45) noexcept { unit = other45.unit; return *this; } +void TimeType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "TimeType("; + out << "isAdjustedToUTC=" << to_string(isAdjustedToUTC); + out << ", " << "unit=" << to_string(unit); + out << ")"; +} + IntType::~IntType() noexcept { } @@ -1983,6 +2340,12 @@ void IntType::__set_bitWidth(const int8_t val) { void IntType::__set_isSigned(const bool val) { this->isSigned = val; } +std::ostream& operator<<(std::ostream& out, const IntType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t IntType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -2072,12 +2435,26 @@ IntType& IntType::operator=(const IntType& other47) noexcept { isSigned = other47.isSigned; return *this; } +void IntType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "IntType("; + out << "bitWidth=" << to_string(bitWidth); + out << ", " << "isSigned=" << to_string(isSigned); + out << ")"; +} + JsonType::~JsonType() noexcept { } JsonType::JsonType() noexcept { } +std::ostream& operator<<(std::ostream& out, const JsonType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t JsonType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -2130,12 +2507,24 @@ JsonType& JsonType::operator=(const JsonType& other49) noexcept { (void) other49; return *this; } +void JsonType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "JsonType("; + out << ")"; +} + BsonType::~BsonType() noexcept { } BsonType::BsonType() noexcept { } +std::ostream& operator<<(std::ostream& out, const BsonType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t BsonType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -2188,6 +2577,12 @@ BsonType& BsonType::operator=(const BsonType& other51) noexcept { (void) other51; return *this; } +void BsonType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "BsonType("; + out << ")"; +} + LogicalType::~LogicalType() noexcept { } @@ -2264,6 +2659,12 @@ void LogicalType::__set_FLOAT16(const Float16Type& val) { this->FLOAT16 = val; __isset.FLOAT16 = true; } +std::ostream& operator<<(std::ostream& out, const LogicalType& obj) +{ + obj.printTo(out); + return out; +} + uint32_t LogicalType::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -2544,6 +2945,26 @@ LogicalType& LogicalType::operator=(const LogicalType& other53) noexcept { __isset = other53.__isset; return *this; } +void LogicalType::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "LogicalType("; + out << "STRING="; (__isset.STRING ? (out << to_string(STRING)) : (out << "")); + out << ", " << "MAP="; (__isset.MAP ? (out << to_string(MAP)) : (out << "")); + out << ", " << "LIST="; (__isset.LIST ? (out << to_string(LIST)) : (out << "")); + out << ", " << "ENUM="; (__isset.ENUM ? (out << to_string(ENUM)) : (out << "")); + out << ", " << "DECIMAL="; (__isset.DECIMAL ? (out << to_string(DECIMAL)) : (out << "")); + out << ", " << "DATE="; (__isset.DATE ? (out << to_string(DATE)) : (out << "")); + out << ", " << "TIME="; (__isset.TIME ? (out << to_string(TIME)) : (out << "")); + out << ", " << "TIMESTAMP="; (__isset.TIMESTAMP ? (out << to_string(TIMESTAMP)) : (out << "")); + out << ", " << "INTEGER="; (__isset.INTEGER ? (out << to_string(INTEGER)) : (out << "")); + out << ", " << "UNKNOWN="; (__isset.UNKNOWN ? (out << to_string(UNKNOWN)) : (out << "")); + out << ", " << "JSON="; (__isset.JSON ? (out << to_string(JSON)) : (out << "")); + out << ", " << "BSON="; (__isset.BSON ? (out << to_string(BSON)) : (out << "")); + out << ", " << "UUID="; (__isset.UUID ? (out << to_string(UUID)) : (out << "")); + out << ", " << "FLOAT16="; (__isset.FLOAT16 ? (out << to_string(FLOAT16)) : (out << "")); + out << ")"; +} + SchemaElement::~SchemaElement() noexcept { } @@ -2608,6 +3029,12 @@ void SchemaElement::__set_logicalType(const LogicalType& val) { this->logicalType = val; __isset.logicalType = true; } +std::ostream& operator<<(std::ostream& out, const SchemaElement& obj) +{ + obj.printTo(out); + return out; +} + uint32_t SchemaElement::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -2832,6 +3259,22 @@ SchemaElement& SchemaElement::operator=(const SchemaElement& other58) { __isset = other58.__isset; return *this; } +void SchemaElement::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "SchemaElement("; + out << "type="; (__isset.type ? (out << to_string(type)) : (out << "")); + out << ", " << "type_length="; (__isset.type_length ? (out << to_string(type_length)) : (out << "")); + out << ", " << "repetition_type="; (__isset.repetition_type ? (out << to_string(repetition_type)) : (out << "")); + out << ", " << "name=" << to_string(name); + out << ", " << "num_children="; (__isset.num_children ? (out << to_string(num_children)) : (out << "")); + out << ", " << "converted_type="; (__isset.converted_type ? (out << to_string(converted_type)) : (out << "")); + out << ", " << "scale="; (__isset.scale ? (out << to_string(scale)) : (out << "")); + out << ", " << "precision="; (__isset.precision ? (out << to_string(precision)) : (out << "")); + out << ", " << "field_id="; (__isset.field_id ? (out << to_string(field_id)) : (out << "")); + out << ", " << "logicalType="; (__isset.logicalType ? (out << to_string(logicalType)) : (out << "")); + out << ")"; +} + DataPageHeader::~DataPageHeader() noexcept { } @@ -2863,6 +3306,12 @@ void DataPageHeader::__set_statistics(const Statistics& val) { this->statistics = val; __isset.statistics = true; } +std::ostream& operator<<(std::ostream& out, const DataPageHeader& obj) +{ + obj.printTo(out); + return out; +} + uint32_t DataPageHeader::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -3013,12 +3462,29 @@ DataPageHeader& DataPageHeader::operator=(const DataPageHeader& other63) { __isset = other63.__isset; return *this; } +void DataPageHeader::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "DataPageHeader("; + out << "num_values=" << to_string(num_values); + out << ", " << "encoding=" << to_string(encoding); + out << ", " << "definition_level_encoding=" << to_string(definition_level_encoding); + out << ", " << "repetition_level_encoding=" << to_string(repetition_level_encoding); + out << ", " << "statistics="; (__isset.statistics ? (out << to_string(statistics)) : (out << "")); + out << ")"; +} + IndexPageHeader::~IndexPageHeader() noexcept { } IndexPageHeader::IndexPageHeader() noexcept { } +std::ostream& operator<<(std::ostream& out, const IndexPageHeader& obj) +{ + obj.printTo(out); + return out; +} + uint32_t IndexPageHeader::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -3071,6 +3537,12 @@ IndexPageHeader& IndexPageHeader::operator=(const IndexPageHeader& other65) noex (void) other65; return *this; } +void IndexPageHeader::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "IndexPageHeader("; + out << ")"; +} + DictionaryPageHeader::~DictionaryPageHeader() noexcept { } @@ -3093,6 +3565,12 @@ void DictionaryPageHeader::__set_is_sorted(const bool val) { this->is_sorted = val; __isset.is_sorted = true; } +std::ostream& operator<<(std::ostream& out, const DictionaryPageHeader& obj) +{ + obj.printTo(out); + return out; +} + uint32_t DictionaryPageHeader::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -3203,6 +3681,15 @@ DictionaryPageHeader& DictionaryPageHeader::operator=(const DictionaryPageHeader __isset = other68.__isset; return *this; } +void DictionaryPageHeader::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "DictionaryPageHeader("; + out << "num_values=" << to_string(num_values); + out << ", " << "encoding=" << to_string(encoding); + out << ", " << "is_sorted="; (__isset.is_sorted ? (out << to_string(is_sorted)) : (out << "")); + out << ")"; +} + DataPageHeaderV2::~DataPageHeaderV2() noexcept { } @@ -3250,6 +3737,12 @@ void DataPageHeaderV2::__set_statistics(const Statistics& val) { this->statistics = val; __isset.statistics = true; } +std::ostream& operator<<(std::ostream& out, const DataPageHeaderV2& obj) +{ + obj.printTo(out); + return out; +} + uint32_t DataPageHeaderV2::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -3448,12 +3941,32 @@ DataPageHeaderV2& DataPageHeaderV2::operator=(const DataPageHeaderV2& other71) { __isset = other71.__isset; return *this; } +void DataPageHeaderV2::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "DataPageHeaderV2("; + out << "num_values=" << to_string(num_values); + out << ", " << "num_nulls=" << to_string(num_nulls); + out << ", " << "num_rows=" << to_string(num_rows); + out << ", " << "encoding=" << to_string(encoding); + out << ", " << "definition_levels_byte_length=" << to_string(definition_levels_byte_length); + out << ", " << "repetition_levels_byte_length=" << to_string(repetition_levels_byte_length); + out << ", " << "is_compressed="; (__isset.is_compressed ? (out << to_string(is_compressed)) : (out << "")); + out << ", " << "statistics="; (__isset.statistics ? (out << to_string(statistics)) : (out << "")); + out << ")"; +} + SplitBlockAlgorithm::~SplitBlockAlgorithm() noexcept { } SplitBlockAlgorithm::SplitBlockAlgorithm() noexcept { } +std::ostream& operator<<(std::ostream& out, const SplitBlockAlgorithm& obj) +{ + obj.printTo(out); + return out; +} + uint32_t SplitBlockAlgorithm::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -3506,6 +4019,12 @@ SplitBlockAlgorithm& SplitBlockAlgorithm::operator=(const SplitBlockAlgorithm& o (void) other73; return *this; } +void SplitBlockAlgorithm::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "SplitBlockAlgorithm("; + out << ")"; +} + BloomFilterAlgorithm::~BloomFilterAlgorithm() noexcept { } @@ -3517,6 +4036,12 @@ void BloomFilterAlgorithm::__set_BLOCK(const SplitBlockAlgorithm& val) { this->BLOCK = val; __isset.BLOCK = true; } +std::ostream& operator<<(std::ostream& out, const BloomFilterAlgorithm& obj) +{ + obj.printTo(out); + return out; +} + uint32_t BloomFilterAlgorithm::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -3589,12 +4114,25 @@ BloomFilterAlgorithm& BloomFilterAlgorithm::operator=(const BloomFilterAlgorithm __isset = other75.__isset; return *this; } +void BloomFilterAlgorithm::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "BloomFilterAlgorithm("; + out << "BLOCK="; (__isset.BLOCK ? (out << to_string(BLOCK)) : (out << "")); + out << ")"; +} + XxHash::~XxHash() noexcept { } XxHash::XxHash() noexcept { } +std::ostream& operator<<(std::ostream& out, const XxHash& obj) +{ + obj.printTo(out); + return out; +} + uint32_t XxHash::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -3647,6 +4185,12 @@ XxHash& XxHash::operator=(const XxHash& other77) noexcept { (void) other77; return *this; } +void XxHash::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "XxHash("; + out << ")"; +} + BloomFilterHash::~BloomFilterHash() noexcept { } @@ -3658,6 +4202,12 @@ void BloomFilterHash::__set_XXHASH(const XxHash& val) { this->XXHASH = val; __isset.XXHASH = true; } +std::ostream& operator<<(std::ostream& out, const BloomFilterHash& obj) +{ + obj.printTo(out); + return out; +} + uint32_t BloomFilterHash::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -3730,12 +4280,25 @@ BloomFilterHash& BloomFilterHash::operator=(const BloomFilterHash& other79) noex __isset = other79.__isset; return *this; } +void BloomFilterHash::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "BloomFilterHash("; + out << "XXHASH="; (__isset.XXHASH ? (out << to_string(XXHASH)) : (out << "")); + out << ")"; +} + Uncompressed::~Uncompressed() noexcept { } Uncompressed::Uncompressed() noexcept { } +std::ostream& operator<<(std::ostream& out, const Uncompressed& obj) +{ + obj.printTo(out); + return out; +} + uint32_t Uncompressed::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -3788,6 +4351,12 @@ Uncompressed& Uncompressed::operator=(const Uncompressed& other81) noexcept { (void) other81; return *this; } +void Uncompressed::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "Uncompressed("; + out << ")"; +} + BloomFilterCompression::~BloomFilterCompression() noexcept { } @@ -3799,6 +4368,12 @@ void BloomFilterCompression::__set_UNCOMPRESSED(const Uncompressed& val) { this->UNCOMPRESSED = val; __isset.UNCOMPRESSED = true; } +std::ostream& operator<<(std::ostream& out, const BloomFilterCompression& obj) +{ + obj.printTo(out); + return out; +} + uint32_t BloomFilterCompression::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -3871,6 +4446,13 @@ BloomFilterCompression& BloomFilterCompression::operator=(const BloomFilterCompr __isset = other83.__isset; return *this; } +void BloomFilterCompression::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "BloomFilterCompression("; + out << "UNCOMPRESSED="; (__isset.UNCOMPRESSED ? (out << to_string(UNCOMPRESSED)) : (out << "")); + out << ")"; +} + BloomFilterHeader::~BloomFilterHeader() noexcept { } @@ -3894,6 +4476,12 @@ void BloomFilterHeader::__set_hash(const BloomFilterHash& val) { void BloomFilterHeader::__set_compression(const BloomFilterCompression& val) { this->compression = val; } +std::ostream& operator<<(std::ostream& out, const BloomFilterHeader& obj) +{ + obj.printTo(out); + return out; +} + uint32_t BloomFilterHeader::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -4019,6 +4607,16 @@ BloomFilterHeader& BloomFilterHeader::operator=(const BloomFilterHeader& other85 compression = other85.compression; return *this; } +void BloomFilterHeader::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "BloomFilterHeader("; + out << "numBytes=" << to_string(numBytes); + out << ", " << "algorithm=" << to_string(algorithm); + out << ", " << "hash=" << to_string(hash); + out << ", " << "compression=" << to_string(compression); + out << ")"; +} + PageHeader::~PageHeader() noexcept { } @@ -4066,6 +4664,12 @@ void PageHeader::__set_data_page_header_v2(const DataPageHeaderV2& val) { this->data_page_header_v2 = val; __isset.data_page_header_v2 = true; } +std::ostream& operator<<(std::ostream& out, const PageHeader& obj) +{ + obj.printTo(out); + return out; +} + uint32_t PageHeader::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -4258,6 +4862,20 @@ PageHeader& PageHeader::operator=(const PageHeader& other88) { __isset = other88.__isset; return *this; } +void PageHeader::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "PageHeader("; + out << "type=" << to_string(type); + out << ", " << "uncompressed_page_size=" << to_string(uncompressed_page_size); + out << ", " << "compressed_page_size=" << to_string(compressed_page_size); + out << ", " << "crc="; (__isset.crc ? (out << to_string(crc)) : (out << "")); + out << ", " << "data_page_header="; (__isset.data_page_header ? (out << to_string(data_page_header)) : (out << "")); + out << ", " << "index_page_header="; (__isset.index_page_header ? (out << to_string(index_page_header)) : (out << "")); + out << ", " << "dictionary_page_header="; (__isset.dictionary_page_header ? (out << to_string(dictionary_page_header)) : (out << "")); + out << ", " << "data_page_header_v2="; (__isset.data_page_header_v2 ? (out << to_string(data_page_header_v2)) : (out << "")); + out << ")"; +} + KeyValue::~KeyValue() noexcept { } @@ -4275,6 +4893,12 @@ void KeyValue::__set_value(const std::string& val) { this->value = val; __isset.value = true; } +std::ostream& operator<<(std::ostream& out, const KeyValue& obj) +{ + obj.printTo(out); + return out; +} + uint32_t KeyValue::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -4365,6 +4989,14 @@ KeyValue& KeyValue::operator=(const KeyValue& other90) { __isset = other90.__isset; return *this; } +void KeyValue::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "KeyValue("; + out << "key=" << to_string(key); + out << ", " << "value="; (__isset.value ? (out << to_string(value)) : (out << "")); + out << ")"; +} + SortingColumn::~SortingColumn() noexcept { } @@ -4386,6 +5018,12 @@ void SortingColumn::__set_descending(const bool val) { void SortingColumn::__set_nulls_first(const bool val) { this->nulls_first = val; } +std::ostream& operator<<(std::ostream& out, const SortingColumn& obj) +{ + obj.printTo(out); + return out; +} + uint32_t SortingColumn::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -4493,6 +5131,15 @@ SortingColumn& SortingColumn::operator=(const SortingColumn& other92) noexcept { nulls_first = other92.nulls_first; return *this; } +void SortingColumn::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "SortingColumn("; + out << "column_idx=" << to_string(column_idx); + out << ", " << "descending=" << to_string(descending); + out << ", " << "nulls_first=" << to_string(nulls_first); + out << ")"; +} + PageEncodingStats::~PageEncodingStats() noexcept { } @@ -4514,6 +5161,12 @@ void PageEncodingStats::__set_encoding(const Encoding::type val) { void PageEncodingStats::__set_count(const int32_t val) { this->count = val; } +std::ostream& operator<<(std::ostream& out, const PageEncodingStats& obj) +{ + obj.printTo(out); + return out; +} + uint32_t PageEncodingStats::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -4625,6 +5278,15 @@ PageEncodingStats& PageEncodingStats::operator=(const PageEncodingStats& other96 count = other96.count; return *this; } +void PageEncodingStats::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "PageEncodingStats("; + out << "page_type=" << to_string(page_type); + out << ", " << "encoding=" << to_string(encoding); + out << ", " << "count=" << to_string(count); + out << ")"; +} + ColumnMetaData::~ColumnMetaData() noexcept { } @@ -4646,11 +5308,11 @@ void ColumnMetaData::__set_type(const Type::type val) { this->type = val; } -void ColumnMetaData::__set_encodings(const std::vector & val) { +void ColumnMetaData::__set_encodings(const duckdb::vector & val) { this->encodings = val; } -void ColumnMetaData::__set_path_in_schema(const std::vector & val) { +void ColumnMetaData::__set_path_in_schema(const duckdb::vector & val) { this->path_in_schema = val; } @@ -4670,7 +5332,7 @@ void ColumnMetaData::__set_total_compressed_size(const int64_t val) { this->total_compressed_size = val; } -void ColumnMetaData::__set_key_value_metadata(const std::vector & val) { +void ColumnMetaData::__set_key_value_metadata(const duckdb::vector & val) { this->key_value_metadata = val; __isset.key_value_metadata = true; } @@ -4694,7 +5356,7 @@ void ColumnMetaData::__set_statistics(const Statistics& val) { __isset.statistics = true; } -void ColumnMetaData::__set_encoding_stats(const std::vector & val) { +void ColumnMetaData::__set_encoding_stats(const duckdb::vector & val) { this->encoding_stats = val; __isset.encoding_stats = true; } @@ -4713,6 +5375,12 @@ void ColumnMetaData::__set_size_statistics(const SizeStatistics& val) { this->size_statistics = val; __isset.size_statistics = true; } +std::ostream& operator<<(std::ostream& out, const ColumnMetaData& obj) +{ + obj.printTo(out); + return out; +} + uint32_t ColumnMetaData::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -4965,7 +5633,7 @@ uint32_t ColumnMetaData::write(::apache::thrift::protocol::TProtocol* oprot) con xfer += oprot->writeFieldBegin("encodings", ::apache::thrift::protocol::T_LIST, 2); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I32, static_cast(this->encodings.size())); - std::vector ::const_iterator _iter120; + duckdb::vector ::const_iterator _iter120; for (_iter120 = this->encodings.begin(); _iter120 != this->encodings.end(); ++_iter120) { xfer += oprot->writeI32(static_cast((*_iter120))); @@ -4977,7 +5645,7 @@ uint32_t ColumnMetaData::write(::apache::thrift::protocol::TProtocol* oprot) con xfer += oprot->writeFieldBegin("path_in_schema", ::apache::thrift::protocol::T_LIST, 3); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->path_in_schema.size())); - std::vector ::const_iterator _iter121; + duckdb::vector ::const_iterator _iter121; for (_iter121 = this->path_in_schema.begin(); _iter121 != this->path_in_schema.end(); ++_iter121) { xfer += oprot->writeString((*_iter121)); @@ -5006,7 +5674,7 @@ uint32_t ColumnMetaData::write(::apache::thrift::protocol::TProtocol* oprot) con xfer += oprot->writeFieldBegin("key_value_metadata", ::apache::thrift::protocol::T_LIST, 8); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->key_value_metadata.size())); - std::vector ::const_iterator _iter122; + duckdb::vector ::const_iterator _iter122; for (_iter122 = this->key_value_metadata.begin(); _iter122 != this->key_value_metadata.end(); ++_iter122) { xfer += (*_iter122).write(oprot); @@ -5038,7 +5706,7 @@ uint32_t ColumnMetaData::write(::apache::thrift::protocol::TProtocol* oprot) con xfer += oprot->writeFieldBegin("encoding_stats", ::apache::thrift::protocol::T_LIST, 13); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->encoding_stats.size())); - std::vector ::const_iterator _iter123; + duckdb::vector ::const_iterator _iter123; for (_iter123 = this->encoding_stats.begin(); _iter123 != this->encoding_stats.end(); ++_iter123) { xfer += (*_iter123).write(oprot); @@ -5127,12 +5795,40 @@ ColumnMetaData& ColumnMetaData::operator=(const ColumnMetaData& other125) { __isset = other125.__isset; return *this; } +void ColumnMetaData::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "ColumnMetaData("; + out << "type=" << to_string(type); + out << ", " << "encodings=" << to_string(encodings); + out << ", " << "path_in_schema=" << to_string(path_in_schema); + out << ", " << "codec=" << to_string(codec); + out << ", " << "num_values=" << to_string(num_values); + out << ", " << "total_uncompressed_size=" << to_string(total_uncompressed_size); + out << ", " << "total_compressed_size=" << to_string(total_compressed_size); + out << ", " << "key_value_metadata="; (__isset.key_value_metadata ? (out << to_string(key_value_metadata)) : (out << "")); + out << ", " << "data_page_offset=" << to_string(data_page_offset); + out << ", " << "index_page_offset="; (__isset.index_page_offset ? (out << to_string(index_page_offset)) : (out << "")); + out << ", " << "dictionary_page_offset="; (__isset.dictionary_page_offset ? (out << to_string(dictionary_page_offset)) : (out << "")); + out << ", " << "statistics="; (__isset.statistics ? (out << to_string(statistics)) : (out << "")); + out << ", " << "encoding_stats="; (__isset.encoding_stats ? (out << to_string(encoding_stats)) : (out << "")); + out << ", " << "bloom_filter_offset="; (__isset.bloom_filter_offset ? (out << to_string(bloom_filter_offset)) : (out << "")); + out << ", " << "bloom_filter_length="; (__isset.bloom_filter_length ? (out << to_string(bloom_filter_length)) : (out << "")); + out << ", " << "size_statistics="; (__isset.size_statistics ? (out << to_string(size_statistics)) : (out << "")); + out << ")"; +} + EncryptionWithFooterKey::~EncryptionWithFooterKey() noexcept { } EncryptionWithFooterKey::EncryptionWithFooterKey() noexcept { } +std::ostream& operator<<(std::ostream& out, const EncryptionWithFooterKey& obj) +{ + obj.printTo(out); + return out; +} + uint32_t EncryptionWithFooterKey::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -5185,6 +5881,12 @@ EncryptionWithFooterKey& EncryptionWithFooterKey::operator=(const EncryptionWith (void) other127; return *this; } +void EncryptionWithFooterKey::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "EncryptionWithFooterKey("; + out << ")"; +} + EncryptionWithColumnKey::~EncryptionWithColumnKey() noexcept { } @@ -5193,7 +5895,7 @@ EncryptionWithColumnKey::EncryptionWithColumnKey() noexcept : key_metadata() { } -void EncryptionWithColumnKey::__set_path_in_schema(const std::vector & val) { +void EncryptionWithColumnKey::__set_path_in_schema(const duckdb::vector & val) { this->path_in_schema = val; } @@ -5201,6 +5903,12 @@ void EncryptionWithColumnKey::__set_key_metadata(const std::string& val) { this->key_metadata = val; __isset.key_metadata = true; } +std::ostream& operator<<(std::ostream& out, const EncryptionWithColumnKey& obj) +{ + obj.printTo(out); + return out; +} + uint32_t EncryptionWithColumnKey::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -5274,7 +5982,7 @@ uint32_t EncryptionWithColumnKey::write(::apache::thrift::protocol::TProtocol* o xfer += oprot->writeFieldBegin("path_in_schema", ::apache::thrift::protocol::T_LIST, 1); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->path_in_schema.size())); - std::vector ::const_iterator _iter133; + duckdb::vector ::const_iterator _iter133; for (_iter133 = this->path_in_schema.begin(); _iter133 != this->path_in_schema.end(); ++_iter133) { xfer += oprot->writeString((*_iter133)); @@ -5311,6 +6019,14 @@ EncryptionWithColumnKey& EncryptionWithColumnKey::operator=(const EncryptionWith __isset = other135.__isset; return *this; } +void EncryptionWithColumnKey::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "EncryptionWithColumnKey("; + out << "path_in_schema=" << to_string(path_in_schema); + out << ", " << "key_metadata="; (__isset.key_metadata ? (out << to_string(key_metadata)) : (out << "")); + out << ")"; +} + ColumnCryptoMetaData::~ColumnCryptoMetaData() noexcept { } @@ -5327,6 +6043,12 @@ void ColumnCryptoMetaData::__set_ENCRYPTION_WITH_COLUMN_KEY(const EncryptionWith this->ENCRYPTION_WITH_COLUMN_KEY = val; __isset.ENCRYPTION_WITH_COLUMN_KEY = true; } +std::ostream& operator<<(std::ostream& out, const ColumnCryptoMetaData& obj) +{ + obj.printTo(out); + return out; +} + uint32_t ColumnCryptoMetaData::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -5415,6 +6137,14 @@ ColumnCryptoMetaData& ColumnCryptoMetaData::operator=(const ColumnCryptoMetaData __isset = other137.__isset; return *this; } +void ColumnCryptoMetaData::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "ColumnCryptoMetaData("; + out << "ENCRYPTION_WITH_FOOTER_KEY="; (__isset.ENCRYPTION_WITH_FOOTER_KEY ? (out << to_string(ENCRYPTION_WITH_FOOTER_KEY)) : (out << "")); + out << ", " << "ENCRYPTION_WITH_COLUMN_KEY="; (__isset.ENCRYPTION_WITH_COLUMN_KEY ? (out << to_string(ENCRYPTION_WITH_COLUMN_KEY)) : (out << "")); + out << ")"; +} + ColumnChunk::~ColumnChunk() noexcept { } @@ -5472,6 +6202,12 @@ void ColumnChunk::__set_encrypted_column_metadata(const std::string& val) { this->encrypted_column_metadata = val; __isset.encrypted_column_metadata = true; } +std::ostream& operator<<(std::ostream& out, const ColumnChunk& obj) +{ + obj.printTo(out); + return out; +} + uint32_t ColumnChunk::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -5674,6 +6410,21 @@ ColumnChunk& ColumnChunk::operator=(const ColumnChunk& other139) { __isset = other139.__isset; return *this; } +void ColumnChunk::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "ColumnChunk("; + out << "file_path="; (__isset.file_path ? (out << to_string(file_path)) : (out << "")); + out << ", " << "file_offset=" << to_string(file_offset); + out << ", " << "meta_data="; (__isset.meta_data ? (out << to_string(meta_data)) : (out << "")); + out << ", " << "offset_index_offset="; (__isset.offset_index_offset ? (out << to_string(offset_index_offset)) : (out << "")); + out << ", " << "offset_index_length="; (__isset.offset_index_length ? (out << to_string(offset_index_length)) : (out << "")); + out << ", " << "column_index_offset="; (__isset.column_index_offset ? (out << to_string(column_index_offset)) : (out << "")); + out << ", " << "column_index_length="; (__isset.column_index_length ? (out << to_string(column_index_length)) : (out << "")); + out << ", " << "crypto_metadata="; (__isset.crypto_metadata ? (out << to_string(crypto_metadata)) : (out << "")); + out << ", " << "encrypted_column_metadata="; (__isset.encrypted_column_metadata ? (out << to_string(encrypted_column_metadata)) : (out << "")); + out << ")"; +} + RowGroup::~RowGroup() noexcept { } @@ -5686,7 +6437,7 @@ RowGroup::RowGroup() noexcept ordinal(0) { } -void RowGroup::__set_columns(const std::vector & val) { +void RowGroup::__set_columns(const duckdb::vector & val) { this->columns = val; } @@ -5698,7 +6449,7 @@ void RowGroup::__set_num_rows(const int64_t val) { this->num_rows = val; } -void RowGroup::__set_sorting_columns(const std::vector & val) { +void RowGroup::__set_sorting_columns(const duckdb::vector & val) { this->sorting_columns = val; __isset.sorting_columns = true; } @@ -5717,6 +6468,12 @@ void RowGroup::__set_ordinal(const int16_t val) { this->ordinal = val; __isset.ordinal = true; } +std::ostream& operator<<(std::ostream& out, const RowGroup& obj) +{ + obj.printTo(out); + return out; +} + uint32_t RowGroup::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -5848,7 +6605,7 @@ uint32_t RowGroup::write(::apache::thrift::protocol::TProtocol* oprot) const { xfer += oprot->writeFieldBegin("columns", ::apache::thrift::protocol::T_LIST, 1); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->columns.size())); - std::vector ::const_iterator _iter150; + duckdb::vector ::const_iterator _iter150; for (_iter150 = this->columns.begin(); _iter150 != this->columns.end(); ++_iter150) { xfer += (*_iter150).write(oprot); @@ -5869,7 +6626,7 @@ uint32_t RowGroup::write(::apache::thrift::protocol::TProtocol* oprot) const { xfer += oprot->writeFieldBegin("sorting_columns", ::apache::thrift::protocol::T_LIST, 4); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->sorting_columns.size())); - std::vector ::const_iterator _iter151; + duckdb::vector ::const_iterator _iter151; for (_iter151 = this->sorting_columns.begin(); _iter151 != this->sorting_columns.end(); ++_iter151) { xfer += (*_iter151).write(oprot); @@ -5931,12 +6688,31 @@ RowGroup& RowGroup::operator=(const RowGroup& other153) { __isset = other153.__isset; return *this; } +void RowGroup::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "RowGroup("; + out << "columns=" << to_string(columns); + out << ", " << "total_byte_size=" << to_string(total_byte_size); + out << ", " << "num_rows=" << to_string(num_rows); + out << ", " << "sorting_columns="; (__isset.sorting_columns ? (out << to_string(sorting_columns)) : (out << "")); + out << ", " << "file_offset="; (__isset.file_offset ? (out << to_string(file_offset)) : (out << "")); + out << ", " << "total_compressed_size="; (__isset.total_compressed_size ? (out << to_string(total_compressed_size)) : (out << "")); + out << ", " << "ordinal="; (__isset.ordinal ? (out << to_string(ordinal)) : (out << "")); + out << ")"; +} + TypeDefinedOrder::~TypeDefinedOrder() noexcept { } TypeDefinedOrder::TypeDefinedOrder() noexcept { } +std::ostream& operator<<(std::ostream& out, const TypeDefinedOrder& obj) +{ + obj.printTo(out); + return out; +} + uint32_t TypeDefinedOrder::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -5989,6 +6765,12 @@ TypeDefinedOrder& TypeDefinedOrder::operator=(const TypeDefinedOrder& other155) (void) other155; return *this; } +void TypeDefinedOrder::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "TypeDefinedOrder("; + out << ")"; +} + ColumnOrder::~ColumnOrder() noexcept { } @@ -6000,6 +6782,12 @@ void ColumnOrder::__set_TYPE_ORDER(const TypeDefinedOrder& val) { this->TYPE_ORDER = val; __isset.TYPE_ORDER = true; } +std::ostream& operator<<(std::ostream& out, const ColumnOrder& obj) +{ + obj.printTo(out); + return out; +} + uint32_t ColumnOrder::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -6072,6 +6860,13 @@ ColumnOrder& ColumnOrder::operator=(const ColumnOrder& other157) noexcept { __isset = other157.__isset; return *this; } +void ColumnOrder::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "ColumnOrder("; + out << "TYPE_ORDER="; (__isset.TYPE_ORDER ? (out << to_string(TYPE_ORDER)) : (out << "")); + out << ")"; +} + PageLocation::~PageLocation() noexcept { } @@ -6093,6 +6888,12 @@ void PageLocation::__set_compressed_page_size(const int32_t val) { void PageLocation::__set_first_row_index(const int64_t val) { this->first_row_index = val; } +std::ostream& operator<<(std::ostream& out, const PageLocation& obj) +{ + obj.printTo(out); + return out; +} + uint32_t PageLocation::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -6200,6 +7001,15 @@ PageLocation& PageLocation::operator=(const PageLocation& other159) noexcept { first_row_index = other159.first_row_index; return *this; } +void PageLocation::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "PageLocation("; + out << "offset=" << to_string(offset); + out << ", " << "compressed_page_size=" << to_string(compressed_page_size); + out << ", " << "first_row_index=" << to_string(first_row_index); + out << ")"; +} + OffsetIndex::~OffsetIndex() noexcept { } @@ -6207,14 +7017,20 @@ OffsetIndex::~OffsetIndex() noexcept { OffsetIndex::OffsetIndex() noexcept { } -void OffsetIndex::__set_page_locations(const std::vector & val) { +void OffsetIndex::__set_page_locations(const duckdb::vector & val) { this->page_locations = val; } -void OffsetIndex::__set_unencoded_byte_array_data_bytes(const std::vector & val) { +void OffsetIndex::__set_unencoded_byte_array_data_bytes(const duckdb::vector & val) { this->unencoded_byte_array_data_bytes = val; __isset.unencoded_byte_array_data_bytes = true; } +std::ostream& operator<<(std::ostream& out, const OffsetIndex& obj) +{ + obj.printTo(out); + return out; +} + uint32_t OffsetIndex::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -6300,7 +7116,7 @@ uint32_t OffsetIndex::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("page_locations", ::apache::thrift::protocol::T_LIST, 1); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->page_locations.size())); - std::vector ::const_iterator _iter170; + duckdb::vector ::const_iterator _iter170; for (_iter170 = this->page_locations.begin(); _iter170 != this->page_locations.end(); ++_iter170) { xfer += (*_iter170).write(oprot); @@ -6313,7 +7129,7 @@ uint32_t OffsetIndex::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("unencoded_byte_array_data_bytes", ::apache::thrift::protocol::T_LIST, 2); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->unencoded_byte_array_data_bytes.size())); - std::vector ::const_iterator _iter171; + duckdb::vector ::const_iterator _iter171; for (_iter171 = this->unencoded_byte_array_data_bytes.begin(); _iter171 != this->unencoded_byte_array_data_bytes.end(); ++_iter171) { xfer += oprot->writeI64((*_iter171)); @@ -6345,6 +7161,14 @@ OffsetIndex& OffsetIndex::operator=(const OffsetIndex& other173) { __isset = other173.__isset; return *this; } +void OffsetIndex::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "OffsetIndex("; + out << "page_locations=" << to_string(page_locations); + out << ", " << "unencoded_byte_array_data_bytes="; (__isset.unencoded_byte_array_data_bytes ? (out << to_string(unencoded_byte_array_data_bytes)) : (out << "")); + out << ")"; +} + ColumnIndex::~ColumnIndex() noexcept { } @@ -6353,15 +7177,15 @@ ColumnIndex::ColumnIndex() noexcept : boundary_order(static_cast(0)) { } -void ColumnIndex::__set_null_pages(const std::vector & val) { +void ColumnIndex::__set_null_pages(const duckdb::vector & val) { this->null_pages = val; } -void ColumnIndex::__set_min_values(const std::vector & val) { +void ColumnIndex::__set_min_values(const duckdb::vector & val) { this->min_values = val; } -void ColumnIndex::__set_max_values(const std::vector & val) { +void ColumnIndex::__set_max_values(const duckdb::vector & val) { this->max_values = val; } @@ -6369,20 +7193,26 @@ void ColumnIndex::__set_boundary_order(const BoundaryOrder::type val) { this->boundary_order = val; } -void ColumnIndex::__set_null_counts(const std::vector & val) { +void ColumnIndex::__set_null_counts(const duckdb::vector & val) { this->null_counts = val; __isset.null_counts = true; } -void ColumnIndex::__set_repetition_level_histograms(const std::vector & val) { +void ColumnIndex::__set_repetition_level_histograms(const duckdb::vector & val) { this->repetition_level_histograms = val; __isset.repetition_level_histograms = true; } -void ColumnIndex::__set_definition_level_histograms(const std::vector & val) { +void ColumnIndex::__set_definition_level_histograms(const duckdb::vector & val) { this->definition_level_histograms = val; __isset.definition_level_histograms = true; } +std::ostream& operator<<(std::ostream& out, const ColumnIndex& obj) +{ + obj.printTo(out); + return out; +} + uint32_t ColumnIndex::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -6567,7 +7397,7 @@ uint32_t ColumnIndex::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("null_pages", ::apache::thrift::protocol::T_LIST, 1); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_BOOL, static_cast(this->null_pages.size())); - std::vector ::const_iterator _iter205; + duckdb::vector ::const_iterator _iter205; for (_iter205 = this->null_pages.begin(); _iter205 != this->null_pages.end(); ++_iter205) { xfer += oprot->writeBool((*_iter205)); @@ -6579,7 +7409,7 @@ uint32_t ColumnIndex::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("min_values", ::apache::thrift::protocol::T_LIST, 2); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->min_values.size())); - std::vector ::const_iterator _iter206; + duckdb::vector ::const_iterator _iter206; for (_iter206 = this->min_values.begin(); _iter206 != this->min_values.end(); ++_iter206) { xfer += oprot->writeBinary((*_iter206)); @@ -6591,7 +7421,7 @@ uint32_t ColumnIndex::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("max_values", ::apache::thrift::protocol::T_LIST, 3); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->max_values.size())); - std::vector ::const_iterator _iter207; + duckdb::vector ::const_iterator _iter207; for (_iter207 = this->max_values.begin(); _iter207 != this->max_values.end(); ++_iter207) { xfer += oprot->writeBinary((*_iter207)); @@ -6608,7 +7438,7 @@ uint32_t ColumnIndex::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("null_counts", ::apache::thrift::protocol::T_LIST, 5); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->null_counts.size())); - std::vector ::const_iterator _iter208; + duckdb::vector ::const_iterator _iter208; for (_iter208 = this->null_counts.begin(); _iter208 != this->null_counts.end(); ++_iter208) { xfer += oprot->writeI64((*_iter208)); @@ -6621,7 +7451,7 @@ uint32_t ColumnIndex::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("repetition_level_histograms", ::apache::thrift::protocol::T_LIST, 6); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->repetition_level_histograms.size())); - std::vector ::const_iterator _iter209; + duckdb::vector ::const_iterator _iter209; for (_iter209 = this->repetition_level_histograms.begin(); _iter209 != this->repetition_level_histograms.end(); ++_iter209) { xfer += oprot->writeI64((*_iter209)); @@ -6634,7 +7464,7 @@ uint32_t ColumnIndex::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("definition_level_histograms", ::apache::thrift::protocol::T_LIST, 7); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_I64, static_cast(this->definition_level_histograms.size())); - std::vector ::const_iterator _iter210; + duckdb::vector ::const_iterator _iter210; for (_iter210 = this->definition_level_histograms.begin(); _iter210 != this->definition_level_histograms.end(); ++_iter210) { xfer += oprot->writeI64((*_iter210)); @@ -6681,6 +7511,19 @@ ColumnIndex& ColumnIndex::operator=(const ColumnIndex& other212) { __isset = other212.__isset; return *this; } +void ColumnIndex::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "ColumnIndex("; + out << "null_pages=" << to_string(null_pages); + out << ", " << "min_values=" << to_string(min_values); + out << ", " << "max_values=" << to_string(max_values); + out << ", " << "boundary_order=" << to_string(boundary_order); + out << ", " << "null_counts="; (__isset.null_counts ? (out << to_string(null_counts)) : (out << "")); + out << ", " << "repetition_level_histograms="; (__isset.repetition_level_histograms ? (out << to_string(repetition_level_histograms)) : (out << "")); + out << ", " << "definition_level_histograms="; (__isset.definition_level_histograms ? (out << to_string(definition_level_histograms)) : (out << "")); + out << ")"; +} + AesGcmV1::~AesGcmV1() noexcept { } @@ -6705,6 +7548,12 @@ void AesGcmV1::__set_supply_aad_prefix(const bool val) { this->supply_aad_prefix = val; __isset.supply_aad_prefix = true; } +std::ostream& operator<<(std::ostream& out, const AesGcmV1& obj) +{ + obj.printTo(out); + return out; +} + uint32_t AesGcmV1::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -6809,6 +7658,15 @@ AesGcmV1& AesGcmV1::operator=(const AesGcmV1& other214) { __isset = other214.__isset; return *this; } +void AesGcmV1::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "AesGcmV1("; + out << "aad_prefix="; (__isset.aad_prefix ? (out << to_string(aad_prefix)) : (out << "")); + out << ", " << "aad_file_unique="; (__isset.aad_file_unique ? (out << to_string(aad_file_unique)) : (out << "")); + out << ", " << "supply_aad_prefix="; (__isset.supply_aad_prefix ? (out << to_string(supply_aad_prefix)) : (out << "")); + out << ")"; +} + AesGcmCtrV1::~AesGcmCtrV1() noexcept { } @@ -6833,6 +7691,12 @@ void AesGcmCtrV1::__set_supply_aad_prefix(const bool val) { this->supply_aad_prefix = val; __isset.supply_aad_prefix = true; } +std::ostream& operator<<(std::ostream& out, const AesGcmCtrV1& obj) +{ + obj.printTo(out); + return out; +} + uint32_t AesGcmCtrV1::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -6937,6 +7801,15 @@ AesGcmCtrV1& AesGcmCtrV1::operator=(const AesGcmCtrV1& other216) { __isset = other216.__isset; return *this; } +void AesGcmCtrV1::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "AesGcmCtrV1("; + out << "aad_prefix="; (__isset.aad_prefix ? (out << to_string(aad_prefix)) : (out << "")); + out << ", " << "aad_file_unique="; (__isset.aad_file_unique ? (out << to_string(aad_file_unique)) : (out << "")); + out << ", " << "supply_aad_prefix="; (__isset.supply_aad_prefix ? (out << to_string(supply_aad_prefix)) : (out << "")); + out << ")"; +} + EncryptionAlgorithm::~EncryptionAlgorithm() noexcept { } @@ -6953,6 +7826,12 @@ void EncryptionAlgorithm::__set_AES_GCM_CTR_V1(const AesGcmCtrV1& val) { this->AES_GCM_CTR_V1 = val; __isset.AES_GCM_CTR_V1 = true; } +std::ostream& operator<<(std::ostream& out, const EncryptionAlgorithm& obj) +{ + obj.printTo(out); + return out; +} + uint32_t EncryptionAlgorithm::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -7041,6 +7920,14 @@ EncryptionAlgorithm& EncryptionAlgorithm::operator=(const EncryptionAlgorithm& o __isset = other218.__isset; return *this; } +void EncryptionAlgorithm::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "EncryptionAlgorithm("; + out << "AES_GCM_V1="; (__isset.AES_GCM_V1 ? (out << to_string(AES_GCM_V1)) : (out << "")); + out << ", " << "AES_GCM_CTR_V1="; (__isset.AES_GCM_CTR_V1 ? (out << to_string(AES_GCM_CTR_V1)) : (out << "")); + out << ")"; +} + FileMetaData::~FileMetaData() noexcept { } @@ -7056,7 +7943,7 @@ void FileMetaData::__set_version(const int32_t val) { this->version = val; } -void FileMetaData::__set_schema(const std::vector & val) { +void FileMetaData::__set_schema(const duckdb::vector & val) { this->schema = val; } @@ -7064,11 +7951,11 @@ void FileMetaData::__set_num_rows(const int64_t val) { this->num_rows = val; } -void FileMetaData::__set_row_groups(const std::vector & val) { +void FileMetaData::__set_row_groups(const duckdb::vector & val) { this->row_groups = val; } -void FileMetaData::__set_key_value_metadata(const std::vector & val) { +void FileMetaData::__set_key_value_metadata(const duckdb::vector & val) { this->key_value_metadata = val; __isset.key_value_metadata = true; } @@ -7078,7 +7965,7 @@ void FileMetaData::__set_created_by(const std::string& val) { __isset.created_by = true; } -void FileMetaData::__set_column_orders(const std::vector & val) { +void FileMetaData::__set_column_orders(const duckdb::vector & val) { this->column_orders = val; __isset.column_orders = true; } @@ -7092,6 +7979,12 @@ void FileMetaData::__set_footer_signing_key_metadata(const std::string& val) { this->footer_signing_key_metadata = val; __isset.footer_signing_key_metadata = true; } +std::ostream& operator<<(std::ostream& out, const FileMetaData& obj) +{ + obj.printTo(out); + return out; +} + uint32_t FileMetaData::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -7270,7 +8163,7 @@ uint32_t FileMetaData::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("schema", ::apache::thrift::protocol::T_LIST, 2); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->schema.size())); - std::vector ::const_iterator _iter239; + duckdb::vector ::const_iterator _iter239; for (_iter239 = this->schema.begin(); _iter239 != this->schema.end(); ++_iter239) { xfer += (*_iter239).write(oprot); @@ -7286,7 +8179,7 @@ uint32_t FileMetaData::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("row_groups", ::apache::thrift::protocol::T_LIST, 4); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->row_groups.size())); - std::vector ::const_iterator _iter240; + duckdb::vector ::const_iterator _iter240; for (_iter240 = this->row_groups.begin(); _iter240 != this->row_groups.end(); ++_iter240) { xfer += (*_iter240).write(oprot); @@ -7299,7 +8192,7 @@ uint32_t FileMetaData::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("key_value_metadata", ::apache::thrift::protocol::T_LIST, 5); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->key_value_metadata.size())); - std::vector ::const_iterator _iter241; + duckdb::vector ::const_iterator _iter241; for (_iter241 = this->key_value_metadata.begin(); _iter241 != this->key_value_metadata.end(); ++_iter241) { xfer += (*_iter241).write(oprot); @@ -7317,7 +8210,7 @@ uint32_t FileMetaData::write(::apache::thrift::protocol::TProtocol* oprot) const xfer += oprot->writeFieldBegin("column_orders", ::apache::thrift::protocol::T_LIST, 7); { xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->column_orders.size())); - std::vector ::const_iterator _iter242; + duckdb::vector ::const_iterator _iter242; for (_iter242 = this->column_orders.begin(); _iter242 != this->column_orders.end(); ++_iter242) { xfer += (*_iter242).write(oprot); @@ -7380,6 +8273,21 @@ FileMetaData& FileMetaData::operator=(const FileMetaData& other244) { __isset = other244.__isset; return *this; } +void FileMetaData::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "FileMetaData("; + out << "version=" << to_string(version); + out << ", " << "schema=" << to_string(schema); + out << ", " << "num_rows=" << to_string(num_rows); + out << ", " << "row_groups=" << to_string(row_groups); + out << ", " << "key_value_metadata="; (__isset.key_value_metadata ? (out << to_string(key_value_metadata)) : (out << "")); + out << ", " << "created_by="; (__isset.created_by ? (out << to_string(created_by)) : (out << "")); + out << ", " << "column_orders="; (__isset.column_orders ? (out << to_string(column_orders)) : (out << "")); + out << ", " << "encryption_algorithm="; (__isset.encryption_algorithm ? (out << to_string(encryption_algorithm)) : (out << "")); + out << ", " << "footer_signing_key_metadata="; (__isset.footer_signing_key_metadata ? (out << to_string(footer_signing_key_metadata)) : (out << "")); + out << ")"; +} + FileCryptoMetaData::~FileCryptoMetaData() noexcept { } @@ -7396,6 +8304,12 @@ void FileCryptoMetaData::__set_key_metadata(const std::string& val) { this->key_metadata = val; __isset.key_metadata = true; } +std::ostream& operator<<(std::ostream& out, const FileCryptoMetaData& obj) +{ + obj.printTo(out); + return out; +} + uint32_t FileCryptoMetaData::read(::apache::thrift::protocol::TProtocol* iprot) { @@ -7486,4 +8400,12 @@ FileCryptoMetaData& FileCryptoMetaData::operator=(const FileCryptoMetaData& othe __isset = other246.__isset; return *this; } +void FileCryptoMetaData::printTo(std::ostream& out) const { + using ::apache::thrift::to_string; + out << "FileCryptoMetaData("; + out << "encryption_algorithm=" << to_string(encryption_algorithm); + out << ", " << "key_metadata="; (__isset.key_metadata ? (out << to_string(key_metadata)) : (out << "")); + out << ")"; +} + } // namespace diff --git a/third_party/parquet/parquet_types.h b/third_party/parquet/parquet_types.h index 627a83a1a8c..792989420b5 100644 --- a/third_party/parquet/parquet_types.h +++ b/third_party/parquet/parquet_types.h @@ -18,7 +18,7 @@ #include #include -// I KNOW WHAT I AM DOING + namespace apache = duckdb_apache; namespace duckdb_parquet { @@ -506,7 +506,7 @@ class SizeStatistics : public virtual ::apache::thrift::TBase { * of information. * */ - std::vector repetition_level_histogram; + duckdb::vector repetition_level_histogram; /** * Same as repetition_level_histogram except for definition levels. * @@ -514,19 +514,20 @@ class SizeStatistics : public virtual ::apache::thrift::TBase { * loss of information. * */ - std::vector definition_level_histogram; + duckdb::vector definition_level_histogram; _SizeStatistics__isset __isset; void __set_unencoded_byte_array_data_bytes(const int64_t val); - void __set_repetition_level_histogram(const std::vector & val); + void __set_repetition_level_histogram(const duckdb::vector & val); - void __set_definition_level_histogram(const std::vector & val); + void __set_definition_level_histogram(const duckdb::vector & val); uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(SizeStatistics &a, SizeStatistics &b); @@ -629,6 +630,7 @@ class Statistics : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(Statistics &a, Statistics &b); @@ -651,6 +653,7 @@ class StringType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(StringType &a, StringType &b); @@ -670,6 +673,7 @@ class UUIDType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(UUIDType &a, UUIDType &b); @@ -689,6 +693,7 @@ class MapType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(MapType &a, MapType &b); @@ -708,6 +713,7 @@ class ListType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(ListType &a, ListType &b); @@ -727,6 +733,7 @@ class EnumType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(EnumType &a, EnumType &b); @@ -746,6 +753,7 @@ class DateType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(DateType &a, DateType &b); @@ -765,6 +773,7 @@ class Float16Type : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(Float16Type &a, Float16Type &b); @@ -791,6 +800,7 @@ class NullType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(NullType &a, NullType &b); @@ -827,6 +837,7 @@ class DecimalType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(DecimalType &a, DecimalType &b); @@ -849,6 +860,7 @@ class MilliSeconds : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(MilliSeconds &a, MilliSeconds &b); @@ -868,6 +880,7 @@ class MicroSeconds : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(MicroSeconds &a, MicroSeconds &b); @@ -887,6 +900,7 @@ class NanoSeconds : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(NanoSeconds &a, NanoSeconds &b); @@ -923,6 +937,7 @@ class TimeUnit : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(TimeUnit &a, TimeUnit &b); @@ -953,6 +968,7 @@ class TimestampType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(TimestampType &a, TimestampType &b); @@ -983,6 +999,7 @@ class TimeType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(TimeType &a, TimeType &b); @@ -1015,6 +1032,7 @@ class IntType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(IntType &a, IntType &b); @@ -1039,6 +1057,7 @@ class JsonType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(JsonType &a, JsonType &b); @@ -1063,6 +1082,7 @@ class BsonType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(BsonType &a, BsonType &b); @@ -1150,6 +1170,7 @@ class LogicalType : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(LogicalType &a, LogicalType &b); @@ -1269,6 +1290,7 @@ class SchemaElement : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(SchemaElement &a, SchemaElement &b); @@ -1338,6 +1360,7 @@ class DataPageHeader : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(DataPageHeader &a, DataPageHeader &b); @@ -1357,6 +1380,7 @@ class IndexPageHeader : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(IndexPageHeader &a, IndexPageHeader &b); @@ -1408,6 +1432,7 @@ class DictionaryPageHeader : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(DictionaryPageHeader &a, DictionaryPageHeader &b); @@ -1498,6 +1523,7 @@ class DataPageHeaderV2 : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(DataPageHeaderV2 &a, DataPageHeaderV2 &b); @@ -1520,6 +1546,7 @@ class SplitBlockAlgorithm : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(SplitBlockAlgorithm &a, SplitBlockAlgorithm &b); @@ -1554,6 +1581,7 @@ class BloomFilterAlgorithm : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(BloomFilterAlgorithm &a, BloomFilterAlgorithm &b); @@ -1578,6 +1606,7 @@ class XxHash : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(XxHash &a, XxHash &b); @@ -1614,6 +1643,7 @@ class BloomFilterHash : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(BloomFilterHash &a, BloomFilterHash &b); @@ -1637,6 +1667,7 @@ class Uncompressed : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(Uncompressed &a, Uncompressed &b); @@ -1665,6 +1696,7 @@ class BloomFilterCompression : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(BloomFilterCompression &a, BloomFilterCompression &b); @@ -1713,6 +1745,7 @@ class BloomFilterHeader : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(BloomFilterHeader &a, BloomFilterHeader &b); @@ -1795,6 +1828,7 @@ class PageHeader : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(PageHeader &a, PageHeader &b); @@ -1829,6 +1863,7 @@ class KeyValue : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(KeyValue &a, KeyValue &b); @@ -1870,6 +1905,7 @@ class SortingColumn : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(SortingColumn &a, SortingColumn &b); @@ -1914,6 +1950,7 @@ class PageEncodingStats : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(PageEncodingStats &a, PageEncodingStats &b); @@ -1953,11 +1990,11 @@ class ColumnMetaData : public virtual ::apache::thrift::TBase { * Set of all encodings used for this column. The purpose is to validate * whether we can decode those pages. * */ - std::vector encodings; + duckdb::vector encodings; /** * Path in schema * */ - std::vector path_in_schema; + duckdb::vector path_in_schema; /** * Compression codec * * @@ -1980,7 +2017,7 @@ class ColumnMetaData : public virtual ::apache::thrift::TBase { /** * Optional key/value metadata * */ - std::vector key_value_metadata; + duckdb::vector key_value_metadata; /** * Byte offset from beginning of file to first data page * */ @@ -2002,7 +2039,7 @@ class ColumnMetaData : public virtual ::apache::thrift::TBase { * This information can be used to determine if all data pages are * dictionary encoded for example * */ - std::vector encoding_stats; + duckdb::vector encoding_stats; /** * Byte offset from beginning of file to Bloom filter data. * */ @@ -2027,9 +2064,9 @@ class ColumnMetaData : public virtual ::apache::thrift::TBase { void __set_type(const Type::type val); - void __set_encodings(const std::vector & val); + void __set_encodings(const duckdb::vector & val); - void __set_path_in_schema(const std::vector & val); + void __set_path_in_schema(const duckdb::vector & val); void __set_codec(const CompressionCodec::type val); @@ -2039,7 +2076,7 @@ class ColumnMetaData : public virtual ::apache::thrift::TBase { void __set_total_compressed_size(const int64_t val); - void __set_key_value_metadata(const std::vector & val); + void __set_key_value_metadata(const duckdb::vector & val); void __set_data_page_offset(const int64_t val); @@ -2049,7 +2086,7 @@ class ColumnMetaData : public virtual ::apache::thrift::TBase { void __set_statistics(const Statistics& val); - void __set_encoding_stats(const std::vector & val); + void __set_encoding_stats(const duckdb::vector & val); void __set_bloom_filter_offset(const int64_t val); @@ -2060,6 +2097,7 @@ class ColumnMetaData : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(ColumnMetaData &a, ColumnMetaData &b); @@ -2079,6 +2117,7 @@ class EncryptionWithFooterKey : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(EncryptionWithFooterKey &a, EncryptionWithFooterKey &b); @@ -2101,7 +2140,7 @@ class EncryptionWithColumnKey : public virtual ::apache::thrift::TBase { /** * Column path in schema * */ - std::vector path_in_schema; + duckdb::vector path_in_schema; /** * Retrieval metadata of column encryption key * */ @@ -2109,13 +2148,14 @@ class EncryptionWithColumnKey : public virtual ::apache::thrift::TBase { _EncryptionWithColumnKey__isset __isset; - void __set_path_in_schema(const std::vector & val); + void __set_path_in_schema(const duckdb::vector & val); void __set_key_metadata(const std::string& val); uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(EncryptionWithColumnKey &a, EncryptionWithColumnKey &b); @@ -2148,6 +2188,7 @@ class ColumnCryptoMetaData : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(ColumnCryptoMetaData &a, ColumnCryptoMetaData &b); @@ -2247,6 +2288,7 @@ class ColumnChunk : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(ColumnChunk &a, ColumnChunk &b); @@ -2274,7 +2316,7 @@ class RowGroup : public virtual ::apache::thrift::TBase { * This list must have the same order as the SchemaElement list in FileMetaData. * */ - std::vector columns; + duckdb::vector columns; /** * Total byte size of all the uncompressed column data in this row group * */ @@ -2287,7 +2329,7 @@ class RowGroup : public virtual ::apache::thrift::TBase { * If set, specifies a sort ordering of the rows in this RowGroup. * The sorting columns can be a subset of all the columns. */ - std::vector sorting_columns; + duckdb::vector sorting_columns; /** * Byte offset from beginning of file to first page (data or dictionary) * in this row group * @@ -2305,13 +2347,13 @@ class RowGroup : public virtual ::apache::thrift::TBase { _RowGroup__isset __isset; - void __set_columns(const std::vector & val); + void __set_columns(const duckdb::vector & val); void __set_total_byte_size(const int64_t val); void __set_num_rows(const int64_t val); - void __set_sorting_columns(const std::vector & val); + void __set_sorting_columns(const duckdb::vector & val); void __set_file_offset(const int64_t val); @@ -2322,6 +2364,7 @@ class RowGroup : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(RowGroup &a, RowGroup &b); @@ -2344,6 +2387,7 @@ class TypeDefinedOrder : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(TypeDefinedOrder &a, TypeDefinedOrder &b); @@ -2434,6 +2478,7 @@ class ColumnOrder : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(ColumnOrder &a, ColumnOrder &b); @@ -2474,6 +2519,7 @@ class PageLocation : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(PageLocation &a, PageLocation &b); @@ -2504,24 +2550,25 @@ class OffsetIndex : public virtual ::apache::thrift::TBase { * PageLocations, ordered by increasing PageLocation.offset. It is required * that page_locations[i].first_row_index < page_locations[i+1].first_row_index. */ - std::vector page_locations; + duckdb::vector page_locations; /** * Unencoded/uncompressed size for BYTE_ARRAY types. * * See documention for unencoded_byte_array_data_bytes in SizeStatistics for * more details on this field. */ - std::vector unencoded_byte_array_data_bytes; + duckdb::vector unencoded_byte_array_data_bytes; _OffsetIndex__isset __isset; - void __set_page_locations(const std::vector & val); + void __set_page_locations(const duckdb::vector & val); - void __set_unencoded_byte_array_data_bytes(const std::vector & val); + void __set_unencoded_byte_array_data_bytes(const duckdb::vector & val); uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(OffsetIndex &a, OffsetIndex &b); @@ -2560,7 +2607,7 @@ class ColumnIndex : public virtual ::apache::thrift::TBase { * byte[0], so that all lists have the same length. If false, the * corresponding entries in min_values and max_values must be valid. */ - std::vector null_pages; + duckdb::vector null_pages; /** * Two lists containing lower and upper bounds for the values of each page * determined by the ColumnOrder of the column. These may be the actual @@ -2571,8 +2618,8 @@ class ColumnIndex : public virtual ::apache::thrift::TBase { * logical type. Readers must make sure that list entries are populated before * using them by inspecting null_pages. */ - std::vector min_values; - std::vector max_values; + duckdb::vector min_values; + duckdb::vector max_values; /** * Stores whether both min_values and max_values are ordered and if so, in * which direction. This allows readers to perform binary searches in both @@ -2592,7 +2639,7 @@ class ColumnIndex : public virtual ::apache::thrift::TBase { * If null_counts are not present, readers MUST NOT assume all * null counts are 0. */ - std::vector null_counts; + duckdb::vector null_counts; /** * Contains repetition level histograms for each page * concatenated together. The repetition_level_histogram field on @@ -2606,32 +2653,33 @@ class ColumnIndex : public virtual ::apache::thrift::TBase { * for the second page. * */ - std::vector repetition_level_histograms; + duckdb::vector repetition_level_histograms; /** * Same as repetition_level_histograms except for definitions levels. * */ - std::vector definition_level_histograms; + duckdb::vector definition_level_histograms; _ColumnIndex__isset __isset; - void __set_null_pages(const std::vector & val); + void __set_null_pages(const duckdb::vector & val); - void __set_min_values(const std::vector & val); + void __set_min_values(const duckdb::vector & val); - void __set_max_values(const std::vector & val); + void __set_max_values(const duckdb::vector & val); void __set_boundary_order(const BoundaryOrder::type val); - void __set_null_counts(const std::vector & val); + void __set_null_counts(const duckdb::vector & val); - void __set_repetition_level_histograms(const std::vector & val); + void __set_repetition_level_histograms(const duckdb::vector & val); - void __set_definition_level_histograms(const std::vector & val); + void __set_definition_level_histograms(const duckdb::vector & val); uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(ColumnIndex &a, ColumnIndex &b); @@ -2678,6 +2726,7 @@ class AesGcmV1 : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(AesGcmV1 &a, AesGcmV1 &b); @@ -2724,6 +2773,7 @@ class AesGcmCtrV1 : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(AesGcmCtrV1 &a, AesGcmCtrV1 &b); @@ -2756,6 +2806,7 @@ class EncryptionAlgorithm : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(EncryptionAlgorithm &a, EncryptionAlgorithm &b); @@ -2794,7 +2845,7 @@ class FileMetaData : public virtual ::apache::thrift::TBase { * used to map columns to nodes in the schema. * The first element is the root * */ - std::vector schema; + duckdb::vector schema; /** * Number of rows in this file * */ @@ -2802,11 +2853,11 @@ class FileMetaData : public virtual ::apache::thrift::TBase { /** * Row groups in this file * */ - std::vector row_groups; + duckdb::vector row_groups; /** * Optional key/value metadata * */ - std::vector key_value_metadata; + duckdb::vector key_value_metadata; /** * String for application that wrote this file. This should be in the format * version (build ). @@ -2830,7 +2881,7 @@ class FileMetaData : public virtual ::apache::thrift::TBase { * The obsolete min and max fields in the Statistics object are always sorted * by signed comparison regardless of column_orders. */ - std::vector column_orders; + duckdb::vector column_orders; /** * Encryption algorithm. This field is set only in encrypted files * with plaintext footer. Files with encrypted footer store algorithm id @@ -2847,17 +2898,17 @@ class FileMetaData : public virtual ::apache::thrift::TBase { void __set_version(const int32_t val); - void __set_schema(const std::vector & val); + void __set_schema(const duckdb::vector & val); void __set_num_rows(const int64_t val); - void __set_row_groups(const std::vector & val); + void __set_row_groups(const duckdb::vector & val); - void __set_key_value_metadata(const std::vector & val); + void __set_key_value_metadata(const duckdb::vector & val); void __set_created_by(const std::string& val); - void __set_column_orders(const std::vector & val); + void __set_column_orders(const duckdb::vector & val); void __set_encryption_algorithm(const EncryptionAlgorithm& val); @@ -2866,6 +2917,7 @@ class FileMetaData : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(FileMetaData &a, FileMetaData &b); @@ -2909,6 +2961,7 @@ class FileCryptoMetaData : public virtual ::apache::thrift::TBase { uint32_t read(::apache::thrift::protocol::TProtocol* iprot) override; uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const override; + virtual void printTo(std::ostream& out) const; }; void swap(FileCryptoMetaData &a, FileCryptoMetaData &b); diff --git a/third_party/parquet/windows_compatibility.h b/third_party/parquet/windows_compatibility.h deleted file mode 100644 index 6cbe6009cbb..00000000000 --- a/third_party/parquet/windows_compatibility.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#ifdef _WIN32 -#undef CREATE_NEW -#undef OPTIONAL -#undef Realloc -#undef min -#undef max -#endif \ No newline at end of file From 97c372795ad2edacee46bcf666e35aaacf0b09cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20M=C3=BChleisen?= Date: Tue, 8 Oct 2024 09:13:12 +0200 Subject: [PATCH 37/89] windows fixes --- extension/parquet/column_reader.cpp | 11 ++++++++++- third_party/parquet/generate.sh | 2 +- third_party/parquet/parquet_types.h | 1 + third_party/parquet/windows_compatibility.h | 9 +++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 third_party/parquet/windows_compatibility.h diff --git a/extension/parquet/column_reader.cpp b/extension/parquet/column_reader.cpp index f0df0518958..2d14353503b 100644 --- a/extension/parquet/column_reader.cpp +++ b/extension/parquet/column_reader.cpp @@ -237,6 +237,10 @@ void ColumnReader::PrepareRead(parquet_filter_t &filter) { block.reset(); PageHeader page_hdr; reader.Read(page_hdr, *protocol); + // some basic sanity check + if (page_hdr.compressed_page_size < 0 || page_hdr.uncompressed_page_size < 0) { + throw std::runtime_error("Page sizes can't be < 0"); + } switch (page_hdr.type) { case PageType::DATA_PAGE_V2: @@ -277,7 +281,6 @@ void ColumnReader::ResetPage() { void ColumnReader::PreparePageV2(PageHeader &page_hdr) { D_ASSERT(page_hdr.type == PageType::DATA_PAGE_V2); - auto &trans = reinterpret_cast(*protocol->getTransport()); AllocateBlock(page_hdr.uncompressed_page_size + 1); @@ -299,6 +302,10 @@ void ColumnReader::PreparePageV2(PageHeader &page_hdr) { // copy repeats & defines as-is because FOR SOME REASON they are uncompressed auto uncompressed_bytes = page_hdr.data_page_header_v2.repetition_levels_byte_length + page_hdr.data_page_header_v2.definition_levels_byte_length; + if (uncompressed_bytes > page_hdr.uncompressed_page_size) { + throw std::runtime_error("Page header inconsistency, uncompressed_page_size needs to be larger than " + "repetition_levels_byte_length + definition_levels_byte_length"); + } trans.read(block->ptr, uncompressed_bytes); auto compressed_bytes = page_hdr.compressed_page_size - uncompressed_bytes; @@ -719,6 +726,7 @@ void StringColumnReader::PrepareDeltaLengthByteArray(ResizeableBuffer &buffer) { auto string_data = FlatVector::GetData(*byte_array_data); for (idx_t i = 0; i < value_count; i++) { auto str_len = length_data[i]; + buffer.available(str_len); string_data[i] = StringVector::EmptyString(*byte_array_data, str_len); auto result_data = string_data[i].GetDataWriteable(); memcpy(result_data, buffer.ptr, length_data[i]); @@ -747,6 +755,7 @@ void StringColumnReader::PrepareDeltaByteArray(ResizeableBuffer &buffer) { auto string_data = FlatVector::GetData(*byte_array_data); for (idx_t i = 0; i < prefix_count; i++) { auto str_len = prefix_data[i] + suffix_data[i]; + buffer.available(suffix_data[i]); string_data[i] = StringVector::EmptyString(*byte_array_data, str_len); auto result_data = string_data[i].GetDataWriteable(); if (prefix_data[i] > 0) { diff --git a/third_party/parquet/generate.sh b/third_party/parquet/generate.sh index bb82af9ee95..0e84a524b83 100755 --- a/third_party/parquet/generate.sh +++ b/third_party/parquet/generate.sh @@ -3,6 +3,6 @@ rm -rf gen-cpp thrift --gen "cpp:no_default_operators=true" parquet.thrift cp gen-cpp/* . sed -i .bak -e "s/std::vector/duckdb::vector/" parquet_types.* -sed -i .bak -e "s/namespace duckdb_parquet {/namespace apache = duckdb_apache;\n\nnamespace duckdb_parquet {/" parquet_types.h +sed -i .bak -e 's/namespace duckdb_parquet {/#include "windows_compatibility.h"\nnamespace apache = duckdb_apache;\n\nnamespace duckdb_parquet {/' parquet_types.h rm *.bak rm -rf gen-cpp \ No newline at end of file diff --git a/third_party/parquet/parquet_types.h b/third_party/parquet/parquet_types.h index 792989420b5..df8cf5f17cf 100644 --- a/third_party/parquet/parquet_types.h +++ b/third_party/parquet/parquet_types.h @@ -19,6 +19,7 @@ #include +#include "windows_compatibility.h" namespace apache = duckdb_apache; namespace duckdb_parquet { diff --git a/third_party/parquet/windows_compatibility.h b/third_party/parquet/windows_compatibility.h new file mode 100644 index 00000000000..6cbe6009cbb --- /dev/null +++ b/third_party/parquet/windows_compatibility.h @@ -0,0 +1,9 @@ +#pragma once + +#ifdef _WIN32 +#undef CREATE_NEW +#undef OPTIONAL +#undef Realloc +#undef min +#undef max +#endif \ No newline at end of file From 756f353f6e01b77480a2eba5cacdc5893ba8aa55 Mon Sep 17 00:00:00 2001 From: Tishj Date: Thu, 10 Oct 2024 15:10:20 +0200 Subject: [PATCH 38/89] specialize for ArrowQueryResult in FetchArrowTable, arrow query result can't be fetched incrementally, so this banks on the fact that the query is executed and the result is then fetched in its entirety --- .../src/include/duckdb_python/pyresult.hpp | 4 - tools/pythonpkg/src/pyrelation.cpp | 10 +++ tools/pythonpkg/src/pyresult.cpp | 75 +++++++++++-------- 3 files changed, 52 insertions(+), 37 deletions(-) diff --git a/tools/pythonpkg/src/include/duckdb_python/pyresult.hpp b/tools/pythonpkg/src/include/duckdb_python/pyresult.hpp index d53d004468d..b889f108d99 100644 --- a/tools/pythonpkg/src/include/duckdb_python/pyresult.hpp +++ b/tools/pythonpkg/src/include/duckdb_python/pyresult.hpp @@ -60,12 +60,8 @@ struct DuckDBPyResult { const vector &GetTypes(); private: - py::list FetchAllArrowChunks(idx_t rows_per_batch, bool to_polars); - void FillNumpy(py::dict &res, idx_t col_idx, NumpyResultConversion &conversion, const char *name); - bool FetchArrowChunk(ChunkScanState &scan_state, py::list &batches, idx_t rows_per_batch, bool to_polars); - PandasDataFrame FrameFromNumpy(bool date_as_object, const py::handle &o); void ChangeToTZType(PandasDataFrame &df); diff --git a/tools/pythonpkg/src/pyrelation.cpp b/tools/pythonpkg/src/pyrelation.cpp index b89a8e74479..80de56d15b3 100644 --- a/tools/pythonpkg/src/pyrelation.cpp +++ b/tools/pythonpkg/src/pyrelation.cpp @@ -19,6 +19,7 @@ #include "duckdb/main/relation/value_relation.hpp" #include "duckdb/main/relation/filter_relation.hpp" #include "duckdb_python/expression/pyexpression.hpp" +#include "duckdb/common/arrow/physical_arrow_collector.hpp" namespace duckdb { @@ -934,6 +935,15 @@ duckdb::pyarrow::Table DuckDBPyRelation::ToArrowTableInternal(idx_t batch_size, if (!rel) { return py::none(); } + auto &config = ClientConfig::GetConfig(*rel->context.GetContext()); + ScopedConfigSetting scoped_setting( + config, + [&batch_size](ClientConfig &config) { + config.result_collector = [&batch_size](ClientContext &context, PreparedStatementData &data) { + return PhysicalArrowCollector::Create(context, data, batch_size); + }; + }, + [](ClientConfig &config) { config.result_collector = nullptr; }); ExecuteOrThrow(); } AssertResultOpen(); diff --git a/tools/pythonpkg/src/pyresult.cpp b/tools/pythonpkg/src/pyresult.cpp index 13d741eff06..a61bb0c7dd9 100644 --- a/tools/pythonpkg/src/pyresult.cpp +++ b/tools/pythonpkg/src/pyresult.cpp @@ -20,6 +20,7 @@ #include "duckdb/common/enums/stream_execution_result.hpp" #include "duckdb_python/arrow/arrow_export_utils.hpp" #include "duckdb/main/chunk_scan_state/query_result.hpp" +#include "duckdb/common/arrow/arrow_query_result.hpp" namespace duckdb { @@ -336,52 +337,60 @@ py::dict DuckDBPyResult::FetchTF() { return result_dict; } -bool DuckDBPyResult::FetchArrowChunk(ChunkScanState &scan_state, py::list &batches, idx_t rows_per_batch, - bool to_polars) { - ArrowArray data; - idx_t count; - auto &query_result = *result.get(); - { - D_ASSERT(py::gil_check()); - py::gil_scoped_release release; - count = ArrowUtil::FetchChunk(scan_state, query_result.client_properties, rows_per_batch, &data); - } - if (count == 0) { - return false; +duckdb::pyarrow::Table DuckDBPyResult::FetchArrowTable(idx_t rows_per_batch, bool to_polars) { + if (!result) { + throw InvalidInputException("There is no query result"); } - ArrowSchema arrow_schema; - auto names = query_result.names; + auto names = result->names; if (to_polars) { QueryResult::DeduplicateColumns(names); } - ArrowConverter::ToArrowSchema(&arrow_schema, query_result.types, names, query_result.client_properties); - TransformDuckToArrowChunk(arrow_schema, data, batches); - return true; -} -py::list DuckDBPyResult::FetchAllArrowChunks(idx_t rows_per_batch, bool to_polars) { if (!result) { throw InvalidInputException("result closed"); } auto pyarrow_lib_module = py::module::import("pyarrow").attr("lib"); py::list batches; - QueryResultChunkScanState scan_state(*result.get()); - while (FetchArrowChunk(scan_state, batches, rows_per_batch, to_polars)) { + if (result->type == QueryResultType::ARROW_RESULT) { + auto &arrow_result = result->Cast(); + auto arrays = arrow_result.ConsumeArrays(); + for (auto &array : arrays) { + ArrowSchema arrow_schema; + auto names = arrow_result.names; + if (to_polars) { + QueryResult::DeduplicateColumns(names); + } + ArrowArray data = array->arrow_array; + array->arrow_array.release = nullptr; + ArrowConverter::ToArrowSchema(&arrow_schema, arrow_result.types, names, arrow_result.client_properties); + TransformDuckToArrowChunk(arrow_schema, data, batches); + } + } else { + QueryResultChunkScanState scan_state(*result.get()); + while (true) { + ArrowArray data; + idx_t count; + auto &query_result = *result.get(); + { + D_ASSERT(py::gil_check()); + py::gil_scoped_release release; + count = ArrowUtil::FetchChunk(scan_state, query_result.client_properties, rows_per_batch, &data); + } + if (count == 0) { + break; + } + ArrowSchema arrow_schema; + auto names = query_result.names; + if (to_polars) { + QueryResult::DeduplicateColumns(names); + } + ArrowConverter::ToArrowSchema(&arrow_schema, query_result.types, names, query_result.client_properties); + TransformDuckToArrowChunk(arrow_schema, data, batches); + } } - return batches; -} -duckdb::pyarrow::Table DuckDBPyResult::FetchArrowTable(idx_t rows_per_batch, bool to_polars) { - if (!result) { - throw InvalidInputException("There is no query result"); - } - auto names = result->names; - if (to_polars) { - QueryResult::DeduplicateColumns(names); - } - return pyarrow::ToArrowTable(result->types, names, FetchAllArrowChunks(rows_per_batch, to_polars), - result->client_properties); + return pyarrow::ToArrowTable(result->types, names, std::move(batches), result->client_properties); } ArrowArrayStream DuckDBPyResult::FetchArrowArrayStream(idx_t rows_per_batch) { From 5bcee80ff82d9a497c064ad4fc8fe6a98c188806 Mon Sep 17 00:00:00 2001 From: douenergy Date: Fri, 11 Oct 2024 14:08:18 +0800 Subject: [PATCH 39/89] supoort define col names in ctas --- .../catalog_entry/table_catalog_entry.cpp | 18 ++++++++ .../catalog_entry/table_catalog_entry.hpp | 3 ++ src/parser/parsed_data/create_table_info.cpp | 1 + .../statement/transform_create_table_as.cpp | 14 +++++-- .../binder/statement/bind_create_table.cpp | 24 ++++++++++- test/sql/create/create_as.test | 42 +++++++++++++++++++ 6 files changed, 97 insertions(+), 5 deletions(-) diff --git a/src/catalog/catalog_entry/table_catalog_entry.cpp b/src/catalog/catalog_entry/table_catalog_entry.cpp index abb66b7e132..667118b7466 100644 --- a/src/catalog/catalog_entry/table_catalog_entry.cpp +++ b/src/catalog/catalog_entry/table_catalog_entry.cpp @@ -176,6 +176,24 @@ string TableCatalogEntry::ColumnsToSQL(const ColumnList &columns, const vector 0) { + ss << ", "; + } + ss << column.Name(); + } + ss << ")"; + return ss.str(); +} + string TableCatalogEntry::ToSQL() const { auto create_info = GetInfo(); return create_info->ToString(); diff --git a/src/include/duckdb/catalog/catalog_entry/table_catalog_entry.hpp b/src/include/duckdb/catalog/catalog_entry/table_catalog_entry.hpp index 0dd78f3ccb5..e0c1dd7160b 100644 --- a/src/include/duckdb/catalog/catalog_entry/table_catalog_entry.hpp +++ b/src/include/duckdb/catalog/catalog_entry/table_catalog_entry.hpp @@ -98,6 +98,9 @@ class TableCatalogEntry : public StandardEntry { DUCKDB_API static string ColumnsToSQL(const ColumnList &columns, const vector> &constraints); + //! Returns the expresioon string list of the column names e.g. (col1, col2, col3) + static string ColumnNamesToSQL(const ColumnList &columns); + //! Returns a list of segment information for this table, if exists virtual vector GetColumnSegmentInfo(); diff --git a/src/parser/parsed_data/create_table_info.cpp b/src/parser/parsed_data/create_table_info.cpp index c9df257833e..0568a8fd111 100644 --- a/src/parser/parsed_data/create_table_info.cpp +++ b/src/parser/parsed_data/create_table_info.cpp @@ -47,6 +47,7 @@ string CreateTableInfo::ToString() const { ret += QualifierToString(temporary ? "" : catalog, schema, table); if (query != nullptr) { + ret += TableCatalogEntry::ColumnNamesToSQL(columns); ret += " AS " + query->ToString(); } else { ret += TableCatalogEntry::ColumnsToSQL(columns, constraints) + ";"; diff --git a/src/parser/transform/statement/transform_create_table_as.cpp b/src/parser/transform/statement/transform_create_table_as.cpp index 6af7fe4e737..3770194a7d8 100644 --- a/src/parser/transform/statement/transform_create_table_as.cpp +++ b/src/parser/transform/statement/transform_create_table_as.cpp @@ -8,17 +8,25 @@ unique_ptr Transformer::TransformCreateTableAs(duckdb_libpgquer if (stmt.relkind == duckdb_libpgquery::PG_OBJECT_MATVIEW) { throw NotImplementedException("Materialized view not implemented"); } - if (stmt.is_select_into || stmt.into->colNames || stmt.into->options) { + if (stmt.is_select_into || stmt.into->options) { throw NotImplementedException("Unimplemented features for CREATE TABLE as"); } - auto qname = TransformQualifiedName(*stmt.into->rel); if (stmt.query->type != duckdb_libpgquery::T_PGSelectStmt) { throw ParserException("CREATE TABLE AS requires a SELECT clause"); } - auto query = TransformSelectStmt(*stmt.query, false); auto result = make_uniq(); auto info = make_uniq(); + auto qname = TransformQualifiedName(*stmt.into->rel); + auto query = TransformSelectStmt(*stmt.query, false); + + if (stmt.into->colNames) { + auto cols = TransformStringList(stmt.into->colNames); + for (idx_t i = 0; i < cols.size(); i++) { + // We really don't know the type of the columns during parsing, so we just use UNKNOWN + info->columns.AddColumn(ColumnDefinition(cols[i], LogicalType::UNKNOWN)); + } + } info->catalog = qname.catalog; info->schema = qname.schema; info->table = qname.name; diff --git a/src/planner/binder/statement/bind_create_table.cpp b/src/planner/binder/statement/bind_create_table.cpp index 7ffbaf23603..2a25b523efb 100644 --- a/src/planner/binder/statement/bind_create_table.cpp +++ b/src/planner/binder/statement/bind_create_table.cpp @@ -319,10 +319,30 @@ unique_ptr Binder::BindCreateTableInfo(unique_ptr 0) { + if (target_col_names.size() > sql_types.size()) { + throw BinderException("Target table has more colum names than query result."); + } else if (target_col_names.size() < sql_types.size()) { + // filled the target_col_names with the name of query names + for (idx_t i = target_col_names.size(); i < sql_types.size(); i++) { + target_col_names.push_back(names[i]); + } + } + ColumnList new_colums; + for (idx_t i = 0; i < target_col_names.size(); i++) { + new_colums.AddColumn(ColumnDefinition(target_col_names[i], sql_types[i])); + } + base.columns = std::move(new_colums); + } else { + for (idx_t i = 0; i < names.size(); i++) { + base.columns.AddColumn(ColumnDefinition(names[i], sql_types[i])); + } } } else { SetCatalogLookupCallback([&dependencies, &schema](CatalogEntry &entry) { diff --git a/test/sql/create/create_as.test b/test/sql/create/create_as.test index c122eefada6..f185e5c5081 100644 --- a/test/sql/create/create_as.test +++ b/test/sql/create/create_as.test @@ -64,3 +64,45 @@ CREATE TABLE tbl4 IF NOT EXISTS AS SELECT 4; statement error CREATE OR REPLACE TABLE tbl4 IF NOT EXISTS AS SELECT 4; ---- + + +### CREATE TABLE t(col1, col2) AS SELECT ... +statement ok +CREATE TABLE tbl4(col1, col2) AS SELECT 1, 'hello'; + +query II +SELECT * FROM tbl4; +---- +1 hello + + +statement ok +CREATE OR REPLACE TABLE tbl4(col1, col2) AS SELECT 2, 'duck'; + +query II +SELECT * FROM tbl4; +---- +2 duck + + +statement ok +CREATE TABLE IF NOT EXISTS tbl5(col1, col2) AS SELECT 3, 'database'; + +query II +SELECT * FROM tbl5; +---- +3 database + +#colname and query mismatch +statement ok +CREATE TABLE tbl6(col1) AS SELECT 4 ,'mismatch'; + +query II +SELECT * FROM tbl6; +---- +4 mismatch + +statement error +CREATE TABLE tbl7(col1, col2) AS SELECT 5; +---- +Binder Error: Target table has more colum names than query result. \ No newline at end of file From b68babc4896e43ad32f48678cf03daac2b2524e6 Mon Sep 17 00:00:00 2001 From: douenergy Date: Fri, 11 Oct 2024 14:15:00 +0800 Subject: [PATCH 40/89] fix typo --- .../duckdb/catalog/catalog_entry/table_catalog_entry.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/duckdb/catalog/catalog_entry/table_catalog_entry.hpp b/src/include/duckdb/catalog/catalog_entry/table_catalog_entry.hpp index e0c1dd7160b..76b24cd26f7 100644 --- a/src/include/duckdb/catalog/catalog_entry/table_catalog_entry.hpp +++ b/src/include/duckdb/catalog/catalog_entry/table_catalog_entry.hpp @@ -98,7 +98,7 @@ class TableCatalogEntry : public StandardEntry { DUCKDB_API static string ColumnsToSQL(const ColumnList &columns, const vector> &constraints); - //! Returns the expresioon string list of the column names e.g. (col1, col2, col3) + //! Returns the expression string list of the column names e.g. (col1, col2, col3) static string ColumnNamesToSQL(const ColumnList &columns); //! Returns a list of segment information for this table, if exists From 86b8f686989520063c85f37b25d17ba14c346db6 Mon Sep 17 00:00:00 2001 From: douenergy Date: Fri, 11 Oct 2024 14:41:12 +0800 Subject: [PATCH 41/89] fix linter error --- src/planner/binder/statement/bind_create_table.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/planner/binder/statement/bind_create_table.cpp b/src/planner/binder/statement/bind_create_table.cpp index 2a25b523efb..0d3bc48e532 100644 --- a/src/planner/binder/statement/bind_create_table.cpp +++ b/src/planner/binder/statement/bind_create_table.cpp @@ -325,7 +325,7 @@ unique_ptr Binder::BindCreateTableInfo(unique_ptr 0) { + if (!target_col_names.empty()) { if (target_col_names.size() > sql_types.size()) { throw BinderException("Target table has more colum names than query result."); } else if (target_col_names.size() < sql_types.size()) { From 2076a88aa2dbe172d2a3351eb22de864a605a1f0 Mon Sep 17 00:00:00 2001 From: Tishj Date: Mon, 14 Oct 2024 15:10:25 +0200 Subject: [PATCH 42/89] add all files --- third_party/zstd/CMakeLists.txt | 60 + third_party/zstd/common/debug.c | 30 + third_party/zstd/common/entropy_common.c | 340 + third_party/zstd/common/entropy_common.cpp | 219 - .../{error_private.cpp => error_private.c} | 18 +- third_party/zstd/common/fse_decompress.c | 313 + third_party/zstd/common/fse_decompress.cpp | 287 - third_party/zstd/common/pool.c | 371 + third_party/zstd/common/threading.c | 182 + third_party/zstd/common/xxhash.c | 18 + third_party/zstd/common/xxhash.cpp | 859 -- .../common/{zstd_common.cpp => zstd_common.c} | 46 +- .../{fse_compress.cpp => fse_compress.c} | 269 +- .../zstd/compress/{hist.cpp => hist.c} | 68 +- third_party/zstd/compress/huf_compress.c | 1464 ++++ third_party/zstd/compress/huf_compress.cpp | 801 -- third_party/zstd/compress/zstd_compress.c | 7153 +++++++++++++++++ third_party/zstd/compress/zstd_compress.cpp | 4283 ---------- .../zstd/compress/zstd_compress_literals.c | 235 + .../zstd/compress/zstd_compress_literals.cpp | 161 - ...equences.cpp => zstd_compress_sequences.c} | 72 +- .../zstd/compress/zstd_compress_superblock.c | 688 ++ .../compress/zstd_compress_superblock.cpp | 842 -- third_party/zstd/compress/zstd_double_fast.c | 770 ++ .../zstd/compress/zstd_double_fast.cpp | 524 -- third_party/zstd/compress/zstd_fast.c | 968 +++ third_party/zstd/compress/zstd_fast.cpp | 499 -- third_party/zstd/compress/zstd_lazy.c | 2199 +++++ third_party/zstd/compress/zstd_lazy.cpp | 1142 --- .../compress/{zstd_ldm.cpp => zstd_ldm.c} | 563 +- .../compress/{zstd_opt.cpp => zstd_opt.c} | 976 ++- third_party/zstd/compress/zstdmt_compress.c | 1882 +++++ third_party/zstd/decompress/huf_decompress.c | 1944 +++++ .../zstd/decompress/huf_decompress.cpp | 1251 --- .../zstd/decompress/huf_decompress_amd64.S | 595 ++ .../{zstd_ddict.cpp => zstd_ddict.c} | 47 +- ...{zstd_decompress.cpp => zstd_decompress.c} | 1008 ++- .../zstd/decompress/zstd_decompress_block.c | 2215 +++++ .../zstd/decompress/zstd_decompress_block.cpp | 1418 ---- third_party/zstd/deprecated/zbuff_common.c | 26 + third_party/zstd/deprecated/zbuff_compress.c | 167 + .../zstd/deprecated/zbuff_decompress.c | 77 + third_party/zstd/dict/cover.c | 1261 +++ third_party/zstd/dict/divsufsort.c | 1913 +++++ third_party/zstd/dict/fastcover.c | 766 ++ third_party/zstd/dict/zdict.c | 1133 +++ third_party/zstd/include/zstd.h | 1015 --- .../zstd/include/zstd/common/allocations.h | 55 + third_party/zstd/include/zstd/common/bits.h | 200 + .../zstd/include/zstd/common/bitstream.h | 184 +- .../zstd/include/zstd/common/compiler.h | 371 +- third_party/zstd/include/zstd/common/cpu.h | 249 + third_party/zstd/include/zstd/common/debug.h | 48 +- .../zstd/include/zstd/common/error_private.h | 107 +- third_party/zstd/include/zstd/common/fse.h | 493 +- .../zstd/include/zstd/common/fse_static.h | 421 - third_party/zstd/include/zstd/common/huf.h | 327 +- .../zstd/include/zstd/common/huf_static.h | 238 - third_party/zstd/include/zstd/common/mem.h | 216 +- third_party/zstd/include/zstd/common/pool.h | 90 + .../include/zstd/common/portability_macros.h | 158 + .../zstd/include/zstd/common/threading.h | 150 + third_party/zstd/include/zstd/common/xxhash.h | 7089 +++++++++++++++- .../zstd/include/zstd/common/xxhash_static.h | 45 - .../zstd/include/zstd/common/zstd_deps.h | 111 + .../zstd/include/zstd/common/zstd_internal.h | 336 +- .../zstd/include/zstd/common/zstd_trace.h | 163 + .../zstd/include/zstd/compress/zstd_cwksp.h | 525 -- .../zstd/include/zstd/compress/zstd_lazy.h | 63 - .../zstd/include/zstd/decompress/zstd_ddict.h | 10 +- .../zstd/decompress/zstd_decompress_block.h | 32 +- .../decompress/zstd_decompress_internal.h | 107 +- .../zstd/include/zstd/deprecated/zbuff.h | 214 + .../include/zstd/include/compress/clevels.h | 134 + .../zstd/{ => include}/compress/hist.h | 7 +- .../compress/zstd_compress_internal.h | 860 +- .../compress/zstd_compress_literals.h | 27 +- .../compress/zstd_compress_sequences.h | 11 +- .../compress/zstd_compress_superblock.h | 7 +- .../zstd/include/compress/zstd_cwksp.h | 748 ++ .../{ => include}/compress/zstd_double_fast.h | 27 +- .../zstd/{ => include}/compress/zstd_fast.h | 15 +- .../include/zstd/include/compress/zstd_lazy.h | 202 + .../zstd/{ => include}/compress/zstd_ldm.h | 23 +- .../zstd/include/compress/zstd_ldm_geartab.h | 106 + .../zstd/{ => include}/compress/zstd_opt.h | 48 +- .../zstd/include/compress/zstdmt_compress.h | 113 + .../include/zstd/include/dictBuilder/cover.h | 152 + .../zstd/include/dictBuilder/divsufsort.h | 67 + third_party/zstd/include/zstd/include/zdict.h | 474 ++ third_party/zstd/include/zstd/include/zstd.h | 3089 +++++++ .../zstd/{common => include}/zstd_errors.h | 45 +- .../zstd/include/zstd/legacy/zstd_legacy.h | 452 ++ .../zstd/include/zstd/legacy/zstd_v01.h | 94 + .../zstd/include/zstd/legacy/zstd_v02.h | 93 + .../zstd/include/zstd/legacy/zstd_v03.h | 93 + .../zstd/include/zstd/legacy/zstd_v04.h | 142 + .../zstd/include/zstd/legacy/zstd_v05.h | 162 + .../zstd/include/zstd/legacy/zstd_v06.h | 172 + .../zstd/include/zstd/legacy/zstd_v07.h | 187 + third_party/zstd/include/zstd_static.h | 1070 --- third_party/zstd/legacy/zstd_v01.c | 2127 +++++ third_party/zstd/legacy/zstd_v02.c | 3465 ++++++++ third_party/zstd/legacy/zstd_v03.c | 3105 +++++++ third_party/zstd/legacy/zstd_v04.c | 3598 +++++++++ third_party/zstd/legacy/zstd_v05.c | 4005 +++++++++ third_party/zstd/legacy/zstd_v06.c | 4106 ++++++++++ third_party/zstd/legacy/zstd_v07.c | 4490 +++++++++++ 108 files changed, 70841 insertions(+), 17815 deletions(-) create mode 100644 third_party/zstd/CMakeLists.txt create mode 100644 third_party/zstd/common/debug.c create mode 100644 third_party/zstd/common/entropy_common.c delete mode 100644 third_party/zstd/common/entropy_common.cpp rename third_party/zstd/common/{error_private.cpp => error_private.c} (73%) create mode 100644 third_party/zstd/common/fse_decompress.c delete mode 100644 third_party/zstd/common/fse_decompress.cpp create mode 100644 third_party/zstd/common/pool.c create mode 100644 third_party/zstd/common/threading.c create mode 100644 third_party/zstd/common/xxhash.c delete mode 100644 third_party/zstd/common/xxhash.cpp rename third_party/zstd/common/{zstd_common.cpp => zstd_common.c} (56%) rename third_party/zstd/compress/{fse_compress.cpp => fse_compress.c} (72%) rename third_party/zstd/compress/{hist.cpp => hist.c} (83%) create mode 100644 third_party/zstd/compress/huf_compress.c delete mode 100644 third_party/zstd/compress/huf_compress.cpp create mode 100644 third_party/zstd/compress/zstd_compress.c delete mode 100644 third_party/zstd/compress/zstd_compress.cpp create mode 100644 third_party/zstd/compress/zstd_compress_literals.c delete mode 100644 third_party/zstd/compress/zstd_compress_literals.cpp rename third_party/zstd/compress/{zstd_compress_sequences.cpp => zstd_compress_sequences.c} (88%) create mode 100644 third_party/zstd/compress/zstd_compress_superblock.c delete mode 100644 third_party/zstd/compress/zstd_compress_superblock.cpp create mode 100644 third_party/zstd/compress/zstd_double_fast.c delete mode 100644 third_party/zstd/compress/zstd_double_fast.cpp create mode 100644 third_party/zstd/compress/zstd_fast.c delete mode 100644 third_party/zstd/compress/zstd_fast.cpp create mode 100644 third_party/zstd/compress/zstd_lazy.c delete mode 100644 third_party/zstd/compress/zstd_lazy.cpp rename third_party/zstd/compress/{zstd_ldm.cpp => zstd_ldm.c} (53%) rename third_party/zstd/compress/{zstd_opt.cpp => zstd_opt.c} (53%) create mode 100644 third_party/zstd/compress/zstdmt_compress.c create mode 100644 third_party/zstd/decompress/huf_decompress.c delete mode 100644 third_party/zstd/decompress/huf_decompress.cpp create mode 100644 third_party/zstd/decompress/huf_decompress_amd64.S rename third_party/zstd/decompress/{zstd_ddict.cpp => zstd_ddict.c} (87%) rename third_party/zstd/decompress/{zstd_decompress.cpp => zstd_decompress.c} (66%) create mode 100644 third_party/zstd/decompress/zstd_decompress_block.c delete mode 100644 third_party/zstd/decompress/zstd_decompress_block.cpp create mode 100644 third_party/zstd/deprecated/zbuff_common.c create mode 100644 third_party/zstd/deprecated/zbuff_compress.c create mode 100644 third_party/zstd/deprecated/zbuff_decompress.c create mode 100644 third_party/zstd/dict/cover.c create mode 100644 third_party/zstd/dict/divsufsort.c create mode 100644 third_party/zstd/dict/fastcover.c create mode 100644 third_party/zstd/dict/zdict.c delete mode 100644 third_party/zstd/include/zstd.h create mode 100644 third_party/zstd/include/zstd/common/allocations.h create mode 100644 third_party/zstd/include/zstd/common/bits.h create mode 100644 third_party/zstd/include/zstd/common/cpu.h delete mode 100644 third_party/zstd/include/zstd/common/fse_static.h delete mode 100644 third_party/zstd/include/zstd/common/huf_static.h create mode 100644 third_party/zstd/include/zstd/common/pool.h create mode 100644 third_party/zstd/include/zstd/common/portability_macros.h create mode 100644 third_party/zstd/include/zstd/common/threading.h delete mode 100644 third_party/zstd/include/zstd/common/xxhash_static.h create mode 100644 third_party/zstd/include/zstd/common/zstd_deps.h create mode 100644 third_party/zstd/include/zstd/common/zstd_trace.h delete mode 100644 third_party/zstd/include/zstd/compress/zstd_cwksp.h delete mode 100644 third_party/zstd/include/zstd/compress/zstd_lazy.h create mode 100644 third_party/zstd/include/zstd/deprecated/zbuff.h create mode 100644 third_party/zstd/include/zstd/include/compress/clevels.h rename third_party/zstd/include/zstd/{ => include}/compress/hist.h (96%) rename third_party/zstd/include/zstd/{ => include}/compress/zstd_compress_internal.h (55%) rename third_party/zstd/include/zstd/{ => include}/compress/zstd_compress_literals.h (57%) rename third_party/zstd/include/zstd/{ => include}/compress/zstd_compress_sequences.h (89%) rename third_party/zstd/include/zstd/{ => include}/compress/zstd_compress_superblock.h (90%) create mode 100644 third_party/zstd/include/zstd/include/compress/zstd_cwksp.h rename third_party/zstd/include/zstd/{ => include}/compress/zstd_double_fast.h (55%) rename third_party/zstd/include/zstd/{ => include}/compress/zstd_fast.h (78%) create mode 100644 third_party/zstd/include/zstd/include/compress/zstd_lazy.h rename third_party/zstd/include/zstd/{ => include}/compress/zstd_ldm.h (85%) create mode 100644 third_party/zstd/include/zstd/include/compress/zstd_ldm_geartab.h rename third_party/zstd/include/zstd/{ => include}/compress/zstd_opt.h (58%) create mode 100644 third_party/zstd/include/zstd/include/compress/zstdmt_compress.h create mode 100644 third_party/zstd/include/zstd/include/dictBuilder/cover.h create mode 100644 third_party/zstd/include/zstd/include/dictBuilder/divsufsort.h create mode 100644 third_party/zstd/include/zstd/include/zdict.h create mode 100644 third_party/zstd/include/zstd/include/zstd.h rename third_party/zstd/include/zstd/{common => include}/zstd_errors.h (72%) create mode 100644 third_party/zstd/include/zstd/legacy/zstd_legacy.h create mode 100644 third_party/zstd/include/zstd/legacy/zstd_v01.h create mode 100644 third_party/zstd/include/zstd/legacy/zstd_v02.h create mode 100644 third_party/zstd/include/zstd/legacy/zstd_v03.h create mode 100644 third_party/zstd/include/zstd/legacy/zstd_v04.h create mode 100644 third_party/zstd/include/zstd/legacy/zstd_v05.h create mode 100644 third_party/zstd/include/zstd/legacy/zstd_v06.h create mode 100644 third_party/zstd/include/zstd/legacy/zstd_v07.h delete mode 100644 third_party/zstd/include/zstd_static.h create mode 100644 third_party/zstd/legacy/zstd_v01.c create mode 100644 third_party/zstd/legacy/zstd_v02.c create mode 100644 third_party/zstd/legacy/zstd_v03.c create mode 100644 third_party/zstd/legacy/zstd_v04.c create mode 100644 third_party/zstd/legacy/zstd_v05.c create mode 100644 third_party/zstd/legacy/zstd_v06.c create mode 100644 third_party/zstd/legacy/zstd_v07.c diff --git a/third_party/zstd/CMakeLists.txt b/third_party/zstd/CMakeLists.txt new file mode 100644 index 00000000000..2bc0af19547 --- /dev/null +++ b/third_party/zstd/CMakeLists.txt @@ -0,0 +1,60 @@ +if(POLICY CMP0063) + cmake_policy(SET CMP0063 NEW) +endif() + +set(ZSTD_FILES + compress/zstd_compress_superblock.c + compress/zstdmt_compress.c + compress/zstd_double_fast.c + compress/zstd_fast.c + compress/zstd_compress_sequences.c + compress/zstd_ldm.c + compress/hist.c + compress/zstd_compress.c + compress/zstd_lazy.c + compress/zstd_compress_literals.c + compress/huf_compress.c + compress/zstd_opt.c + compress/fse_compress.c + decompress/zstd_ddict.c + decompress/huf_decompress.c + decompress/zstd_decompress.c + decompress/huf_decompress_amd64.S + decompress/zstd_decompress_block.c + legacy/zstd_v05.c + legacy/zstd_v01.c + legacy/zstd_v06.c + legacy/zstd_v02.c + legacy/zstd_v07.c + legacy/zstd_v03.c + legacy/zstd_v04.c + common/entropy_common.c + common/fse_decompress.c + common/debug.c + common/xxhash.c + common/pool.c + common/threading.c + common/zstd_common.c + common/error_private.c + dict/cover.c + dict/divsufsort.c + dict/fastcover.c + dict/zdict.c + deprecated/zbuff_common.c + deprecated/zbuff_decompress.c + deprecated/zbuff_compress.c +) + +add_library(duckdb_zstd STATIC ${ZSTD_FILES}) + +target_include_directories( + duckdb_zstd + PUBLIC $) +set_target_properties(duckdb_zstd PROPERTIES EXPORT_NAME duckdb_duckdb_zstd) + +install(TARGETS duckdb_zstd + EXPORT "${DUCKDB_EXPORT_SET}" + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}") + +disable_target_warnings(duckdb_zstd) diff --git a/third_party/zstd/common/debug.c b/third_party/zstd/common/debug.c new file mode 100644 index 00000000000..9d0b7d229c1 --- /dev/null +++ b/third_party/zstd/common/debug.c @@ -0,0 +1,30 @@ +/* ****************************************************************** + * debug + * Part of FSE library + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * You can contact the author at : + * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. +****************************************************************** */ + + +/* + * This module only hosts one global variable + * which can be used to dynamically influence the verbosity of traces, + * such as DEBUGLOG and RAWLOG + */ + +#include "debug.h" + +#if !defined(ZSTD_LINUX_KERNEL) || (DEBUGLEVEL>=2) +/* We only use this when DEBUGLEVEL>=2, but we get -Werror=pedantic errors if a + * translation unit is empty. So remove this from Linux kernel builds, but + * otherwise just leave it in. + */ +int g_debuglevel = DEBUGLEVEL; +#endif diff --git a/third_party/zstd/common/entropy_common.c b/third_party/zstd/common/entropy_common.c new file mode 100644 index 00000000000..e2173afb0a8 --- /dev/null +++ b/third_party/zstd/common/entropy_common.c @@ -0,0 +1,340 @@ +/* ****************************************************************** + * Common functions of New Generation Entropy library + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * You can contact the author at : + * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy + * - Public forum : https://groups.google.com/forum/#!forum/lz4c + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. +****************************************************************** */ + +/* ************************************* +* Dependencies +***************************************/ +#include "mem.h" +#include "error_private.h" /* ERR_*, ERROR */ +#define FSE_STATIC_LINKING_ONLY /* FSE_MIN_TABLELOG */ +#include "fse.h" +#include "huf.h" +#include "bits.h" /* ZSDT_highbit32, ZSTD_countTrailingZeros32 */ + + +/*=== Version ===*/ +unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; } + + +/*=== Error Management ===*/ +unsigned FSE_isError(size_t code) { return ERR_isError(code); } +const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); } + +unsigned HUF_isError(size_t code) { return ERR_isError(code); } +const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } + + +/*-************************************************************** +* FSE NCount encoding-decoding +****************************************************************/ +FORCE_INLINE_TEMPLATE +size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + const BYTE* const istart = (const BYTE*) headerBuffer; + const BYTE* const iend = istart + hbSize; + const BYTE* ip = istart; + int nbBits; + int remaining; + int threshold; + U32 bitStream; + int bitCount; + unsigned charnum = 0; + unsigned const maxSV1 = *maxSVPtr + 1; + int previous0 = 0; + + if (hbSize < 8) { + /* This function only works when hbSize >= 8 */ + char buffer[8] = {0}; + ZSTD_memcpy(buffer, headerBuffer, hbSize); + { size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr, + buffer, sizeof(buffer)); + if (FSE_isError(countSize)) return countSize; + if (countSize > hbSize) return ERROR(corruption_detected); + return countSize; + } } + assert(hbSize >= 8); + + /* init */ + ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */ + bitStream = MEM_readLE32(ip); + nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ + if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); + bitStream >>= 4; + bitCount = 4; + *tableLogPtr = nbBits; + remaining = (1<> 1; + while (repeats >= 12) { + charnum += 3 * 12; + if (LIKELY(ip <= iend-7)) { + ip += 3; + } else { + bitCount -= (int)(8 * (iend - 7 - ip)); + bitCount &= 31; + ip = iend - 4; + } + bitStream = MEM_readLE32(ip) >> bitCount; + repeats = ZSTD_countTrailingZeros32(~bitStream | 0x80000000) >> 1; + } + charnum += 3 * repeats; + bitStream >>= 2 * repeats; + bitCount += 2 * repeats; + + /* Add the final repeat which isn't 0b11. */ + assert((bitStream & 3) < 3); + charnum += bitStream & 3; + bitCount += 2; + + /* This is an error, but break and return an error + * at the end, because returning out of a loop makes + * it harder for the compiler to optimize. + */ + if (charnum >= maxSV1) break; + + /* We don't need to set the normalized count to 0 + * because we already memset the whole buffer to 0. + */ + + if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { + assert((bitCount >> 3) <= 3); /* For first condition to work */ + ip += bitCount>>3; + bitCount &= 7; + } else { + bitCount -= (int)(8 * (iend - 4 - ip)); + bitCount &= 31; + ip = iend - 4; + } + bitStream = MEM_readLE32(ip) >> bitCount; + } + { + int const max = (2*threshold-1) - remaining; + int count; + + if ((bitStream & (threshold-1)) < (U32)max) { + count = bitStream & (threshold-1); + bitCount += nbBits-1; + } else { + count = bitStream & (2*threshold-1); + if (count >= threshold) count -= max; + bitCount += nbBits; + } + + count--; /* extra accuracy */ + /* When it matters (small blocks), this is a + * predictable branch, because we don't use -1. + */ + if (count >= 0) { + remaining -= count; + } else { + assert(count == -1); + remaining += count; + } + normalizedCounter[charnum++] = (short)count; + previous0 = !count; + + assert(threshold > 1); + if (remaining < threshold) { + /* This branch can be folded into the + * threshold update condition because we + * know that threshold > 1. + */ + if (remaining <= 1) break; + nbBits = ZSTD_highbit32(remaining) + 1; + threshold = 1 << (nbBits - 1); + } + if (charnum >= maxSV1) break; + + if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { + ip += bitCount>>3; + bitCount &= 7; + } else { + bitCount -= (int)(8 * (iend - 4 - ip)); + bitCount &= 31; + ip = iend - 4; + } + bitStream = MEM_readLE32(ip) >> bitCount; + } } + if (remaining != 1) return ERROR(corruption_detected); + /* Only possible when there are too many zeros. */ + if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall); + if (bitCount > 32) return ERROR(corruption_detected); + *maxSVPtr = charnum-1; + + ip += (bitCount+7)>>3; + return ip-istart; +} + +/* Avoids the FORCE_INLINE of the _body() function. */ +static size_t FSE_readNCount_body_default( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); +} + +#if DYNAMIC_BMI2 +BMI2_TARGET_ATTRIBUTE static size_t FSE_readNCount_body_bmi2( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); +} +#endif + +size_t FSE_readNCount_bmi2( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize, int bmi2) +{ +#if DYNAMIC_BMI2 + if (bmi2) { + return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); + } +#endif + (void)bmi2; + return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); +} + +size_t FSE_readNCount( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0); +} + + +/*! HUF_readStats() : + Read compact Huffman tree, saved by HUF_writeCTable(). + `huffWeight` is destination buffer. + `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32. + @return : size read from `src` , or an error Code . + Note : Needed by HUF_readCTable() and HUF_readDTableX?() . +*/ +size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize) +{ + U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32]; + return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* flags */ 0); +} + +FORCE_INLINE_TEMPLATE size_t +HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize, + int bmi2) +{ + U32 weightTotal; + const BYTE* ip = (const BYTE*) src; + size_t iSize; + size_t oSize; + + if (!srcSize) return ERROR(srcSize_wrong); + iSize = ip[0]; + /* ZSTD_memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ + + if (iSize >= 128) { /* special header */ + oSize = iSize - 127; + iSize = ((oSize+1)/2); + if (iSize+1 > srcSize) return ERROR(srcSize_wrong); + if (oSize >= hwSize) return ERROR(corruption_detected); + ip += 1; + { U32 n; + for (n=0; n> 4; + huffWeight[n+1] = ip[n/2] & 15; + } } } + else { /* header compressed with FSE (normal case) */ + if (iSize+1 > srcSize) return ERROR(srcSize_wrong); + /* max (hwSize-1) values decoded, as last one is implied */ + oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2); + if (FSE_isError(oSize)) return oSize; + } + + /* collect weight stats */ + ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32)); + weightTotal = 0; + { U32 n; for (n=0; n HUF_TABLELOG_MAX) return ERROR(corruption_detected); + rankStats[huffWeight[n]]++; + weightTotal += (1 << huffWeight[n]) >> 1; + } } + if (weightTotal == 0) return ERROR(corruption_detected); + + /* get last non-null symbol weight (implied, total must be 2^n) */ + { U32 const tableLog = ZSTD_highbit32(weightTotal) + 1; + if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected); + *tableLogPtr = tableLog; + /* determine last weight */ + { U32 const total = 1 << tableLog; + U32 const rest = total - weightTotal; + U32 const verif = 1 << ZSTD_highbit32(rest); + U32 const lastWeight = ZSTD_highbit32(rest) + 1; + if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ + huffWeight[oSize] = (BYTE)lastWeight; + rankStats[lastWeight]++; + } } + + /* check tree construction validity */ + if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ + + /* results */ + *nbSymbolsPtr = (U32)(oSize+1); + return iSize+1; +} + +/* Avoids the FORCE_INLINE of the _body() function. */ +static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize) +{ + return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0); +} + +#if DYNAMIC_BMI2 +static BMI2_TARGET_ATTRIBUTE size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize) +{ + return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1); +} +#endif + +size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize, + int flags) +{ +#if DYNAMIC_BMI2 + if (flags & HUF_flags_bmi2) { + return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize); + } +#endif + (void)flags; + return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize); +} diff --git a/third_party/zstd/common/entropy_common.cpp b/third_party/zstd/common/entropy_common.cpp deleted file mode 100644 index bd41d220a96..00000000000 --- a/third_party/zstd/common/entropy_common.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* ****************************************************************** - * Common functions of New Generation Entropy library - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * - * You can contact the author at : - * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy - * - Public forum : https://groups.google.com/forum/#!forum/lz4c - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. -****************************************************************** */ - -/* ************************************* -* Dependencies -***************************************/ -#include "zstd/common/mem.h" -#include "zstd/common/error_private.h" /* ERR_*, ERROR */ -#include "zstd/common/fse.h" -#include "zstd/common/fse_static.h" -#include "zstd/common/huf.h" -#include "zstd/common/huf_static.h" - -namespace duckdb_zstd { - -/*=== Version ===*/ -unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; } - - -/*=== Error Management ===*/ -unsigned FSE_isError(size_t code) { return ERR_isError(code); } -const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); } - -unsigned HUF_isError(size_t code) { return ERR_isError(code); } -const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } - - -/*-************************************************************** -* FSE NCount encoding-decoding -****************************************************************/ -size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, - const void* headerBuffer, size_t hbSize) -{ - const BYTE* const istart = (const BYTE*) headerBuffer; - const BYTE* const iend = istart + hbSize; - const BYTE* ip = istart; - int nbBits; - int remaining; - int threshold; - U32 bitStream; - int bitCount; - unsigned charnum = 0; - int previous0 = 0; - - if (hbSize < 4) { - /* This function only works when hbSize >= 4 */ - char buffer[4]; - memset(buffer, 0, sizeof(buffer)); - memcpy(buffer, headerBuffer, hbSize); - { size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr, - buffer, sizeof(buffer)); - if (FSE_isError(countSize)) return countSize; - if (countSize > hbSize) return ERROR(corruption_detected); - return countSize; - } } - assert(hbSize >= 4); - - /* init */ - memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */ - bitStream = MEM_readLE32(ip); - nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ - if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); - bitStream >>= 4; - bitCount = 4; - *tableLogPtr = nbBits; - remaining = (1<1) & (charnum<=*maxSVPtr)) { - if (previous0) { - unsigned n0 = charnum; - while ((bitStream & 0xFFFF) == 0xFFFF) { - n0 += 24; - if (ip < iend-5) { - ip += 2; - bitStream = MEM_readLE32(ip) >> bitCount; - } else { - bitStream >>= 16; - bitCount += 16; - } } - while ((bitStream & 3) == 3) { - n0 += 3; - bitStream >>= 2; - bitCount += 2; - } - n0 += bitStream & 3; - bitCount += 2; - if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall); - while (charnum < n0) normalizedCounter[charnum++] = 0; - if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { - assert((bitCount >> 3) <= 3); /* For first condition to work */ - ip += bitCount>>3; - bitCount &= 7; - bitStream = MEM_readLE32(ip) >> bitCount; - } else { - bitStream >>= 2; - } } - { int const max = (2*threshold-1) - remaining; - int count; - - if ((bitStream & (threshold-1)) < (U32)max) { - count = bitStream & (threshold-1); - bitCount += nbBits-1; - } else { - count = bitStream & (2*threshold-1); - if (count >= threshold) count -= max; - bitCount += nbBits; - } - - count--; /* extra accuracy */ - remaining -= count < 0 ? -count : count; /* -1 means +1 */ - normalizedCounter[charnum++] = (short)count; - previous0 = !count; - while (remaining < threshold) { - nbBits--; - threshold >>= 1; - } - - if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { - ip += bitCount>>3; - bitCount &= 7; - } else { - bitCount -= (int)(8 * (iend - 4 - ip)); - ip = iend - 4; - } - bitStream = MEM_readLE32(ip) >> (bitCount & 31); - } } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */ - if (remaining != 1) return ERROR(corruption_detected); - if (bitCount > 32) return ERROR(corruption_detected); - *maxSVPtr = charnum-1; - - ip += (bitCount+7)>>3; - return ip-istart; -} - - -/*! HUF_readStats() : - Read compact Huffman tree, saved by HUF_writeCTable(). - `huffWeight` is destination buffer. - `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32. - @return : size read from `src` , or an error Code . - Note : Needed by HUF_readCTable() and HUF_readDTableX?() . -*/ -size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, - U32* nbSymbolsPtr, U32* tableLogPtr, - const void* src, size_t srcSize) -{ - U32 weightTotal; - const BYTE* ip = (const BYTE*) src; - size_t iSize; - size_t oSize; - - if (!srcSize) return ERROR(srcSize_wrong); - iSize = ip[0]; - /* memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ - - if (iSize >= 128) { /* special header */ - oSize = iSize - 127; - iSize = ((oSize+1)/2); - if (iSize+1 > srcSize) return ERROR(srcSize_wrong); - if (oSize >= hwSize) return ERROR(corruption_detected); - ip += 1; - { U32 n; - for (n=0; n> 4; - huffWeight[n+1] = ip[n/2] & 15; - } } } - else { /* header compressed with FSE (normal case) */ - FSE_DTable fseWorkspace[FSE_DTABLE_SIZE_U32(6)]; /* 6 is max possible tableLog for HUF header (maybe even 5, to be tested) */ - if (iSize+1 > srcSize) return ERROR(srcSize_wrong); - oSize = FSE_decompress_wksp(huffWeight, hwSize-1, ip+1, iSize, fseWorkspace, 6); /* max (hwSize-1) values decoded, as last one is implied */ - if (FSE_isError(oSize)) return oSize; - } - - /* collect weight stats */ - memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32)); - weightTotal = 0; - { U32 n; for (n=0; n= HUF_TABLELOG_MAX) return ERROR(corruption_detected); - rankStats[huffWeight[n]]++; - weightTotal += (1 << huffWeight[n]) >> 1; - } } - if (weightTotal == 0) return ERROR(corruption_detected); - - /* get last non-null symbol weight (implied, total must be 2^n) */ - { U32 const tableLog = BIT_highbit32(weightTotal) + 1; - if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected); - *tableLogPtr = tableLog; - /* determine last weight */ - { U32 const total = 1 << tableLog; - U32 const rest = total - weightTotal; - U32 const verif = 1 << BIT_highbit32(rest); - U32 const lastWeight = BIT_highbit32(rest) + 1; - if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ - huffWeight[oSize] = (BYTE)lastWeight; - rankStats[lastWeight]++; - } } - - /* check tree construction validity */ - if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ - - /* results */ - *nbSymbolsPtr = (U32)(oSize+1); - return iSize+1; -} - -} diff --git a/third_party/zstd/common/error_private.cpp b/third_party/zstd/common/error_private.c similarity index 73% rename from third_party/zstd/common/error_private.cpp rename to third_party/zstd/common/error_private.c index 207ef006d54..075fc5ef42f 100644 --- a/third_party/zstd/common/error_private.cpp +++ b/third_party/zstd/common/error_private.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -10,9 +10,7 @@ /* The purpose of this file is to have a single list of error strings embedded in binary */ -#include "zstd/common/error_private.h" - -namespace duckdb_zstd { +#include "error_private.h" const char* ERR_getErrorString(ERR_enum code) { @@ -29,9 +27,11 @@ const char* ERR_getErrorString(ERR_enum code) case PREFIX(version_unsupported): return "Version not supported"; case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter"; case PREFIX(frameParameter_windowTooLarge): return "Frame requires too much memory for decoding"; - case PREFIX(corruption_detected): return "Corrupted block detected"; + case PREFIX(corruption_detected): return "Data corruption detected"; case PREFIX(checksum_wrong): return "Restored data doesn't match checksum"; + case PREFIX(literals_headerWrong): return "Header of Literals' block doesn't respect format specification"; case PREFIX(parameter_unsupported): return "Unsupported parameter"; + case PREFIX(parameter_combination_unsupported): return "Unsupported combination of parameters"; case PREFIX(parameter_outOfBound): return "Parameter is out of bound"; case PREFIX(init_missing): return "Context should be init first"; case PREFIX(memory_allocation): return "Allocation error : not enough memory"; @@ -40,20 +40,24 @@ const char* ERR_getErrorString(ERR_enum code) case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported"; case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large"; case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small"; + case PREFIX(stabilityCondition_notRespected): return "pledged buffer stability condition is not respected"; case PREFIX(dictionary_corrupted): return "Dictionary is corrupted"; case PREFIX(dictionary_wrong): return "Dictionary mismatch"; case PREFIX(dictionaryCreation_failed): return "Cannot create Dictionary from provided samples"; case PREFIX(dstSize_tooSmall): return "Destination buffer is too small"; case PREFIX(srcSize_wrong): return "Src size is incorrect"; case PREFIX(dstBuffer_null): return "Operation on NULL destination buffer"; + case PREFIX(noForwardProgress_destFull): return "Operation made no progress over multiple calls, due to output buffer being full"; + case PREFIX(noForwardProgress_inputEmpty): return "Operation made no progress over multiple calls, due to input being empty"; /* following error codes are not stable and may be removed or changed in a future version */ case PREFIX(frameIndex_tooLarge): return "Frame index is too large"; case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking"; case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong"; + case PREFIX(srcBuffer_wrong): return "Source buffer is wrong"; + case PREFIX(sequenceProducer_failed): return "Block-level external sequence producer returned an error code"; + case PREFIX(externalSequences_invalid): return "External sequences are not valid"; case PREFIX(maxCode): default: return notErrorCode; } #endif } - -} diff --git a/third_party/zstd/common/fse_decompress.c b/third_party/zstd/common/fse_decompress.c new file mode 100644 index 00000000000..0dcc4640d09 --- /dev/null +++ b/third_party/zstd/common/fse_decompress.c @@ -0,0 +1,313 @@ +/* ****************************************************************** + * FSE : Finite State Entropy decoder + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * You can contact the author at : + * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy + * - Public forum : https://groups.google.com/forum/#!forum/lz4c + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. +****************************************************************** */ + + +/* ************************************************************** +* Includes +****************************************************************/ +#include "debug.h" /* assert */ +#include "bitstream.h" +#include "compiler.h" +#define FSE_STATIC_LINKING_ONLY +#include "fse.h" +#include "error_private.h" +#include "zstd_deps.h" /* ZSTD_memcpy */ +#include "bits.h" /* ZSTD_highbit32 */ + + +/* ************************************************************** +* Error Management +****************************************************************/ +#define FSE_isError ERR_isError +#define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */ + + +/* ************************************************************** +* Templates +****************************************************************/ +/* + designed to be included + for type-specific functions (template emulation in C) + Objective is to write these functions only once, for improved maintenance +*/ + +/* safety checks */ +#ifndef FSE_FUNCTION_EXTENSION +# error "FSE_FUNCTION_EXTENSION must be defined" +#endif +#ifndef FSE_FUNCTION_TYPE +# error "FSE_FUNCTION_TYPE must be defined" +#endif + +/* Function names */ +#define FSE_CAT(X,Y) X##Y +#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y) +#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y) + +static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize) +{ + void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */ + FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr); + U16* symbolNext = (U16*)workSpace; + BYTE* spread = (BYTE*)(symbolNext + maxSymbolValue + 1); + + U32 const maxSV1 = maxSymbolValue + 1; + U32 const tableSize = 1 << tableLog; + U32 highThreshold = tableSize-1; + + /* Sanity Checks */ + if (FSE_BUILD_DTABLE_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(maxSymbolValue_tooLarge); + if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge); + if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); + + /* Init, lay down lowprob symbols */ + { FSE_DTableHeader DTableH; + DTableH.tableLog = (U16)tableLog; + DTableH.fastMode = 1; + { S16 const largeLimit= (S16)(1 << (tableLog-1)); + U32 s; + for (s=0; s= largeLimit) DTableH.fastMode=0; + symbolNext[s] = (U16)normalizedCounter[s]; + } } } + ZSTD_memcpy(dt, &DTableH, sizeof(DTableH)); + } + + /* Spread symbols */ + if (highThreshold == tableSize - 1) { + size_t const tableMask = tableSize-1; + size_t const step = FSE_TABLESTEP(tableSize); + /* First lay down the symbols in order. + * We use a uint64_t to lay down 8 bytes at a time. This reduces branch + * misses since small blocks generally have small table logs, so nearly + * all symbols have counts <= 8. We ensure we have 8 bytes at the end of + * our buffer to handle the over-write. + */ + { U64 const add = 0x0101010101010101ull; + size_t pos = 0; + U64 sv = 0; + U32 s; + for (s=0; s highThreshold) position = (position + step) & tableMask; /* lowprob area */ + } } + if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ + } + + /* Build Decoding table */ + { U32 u; + for (u=0; u sizeof(bitD.bitContainer)*8) /* This test must be static */ + BIT_reloadDStream(&bitD); + + op[1] = FSE_GETSYMBOL(&state2); + + if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ + { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } } + + op[2] = FSE_GETSYMBOL(&state1); + + if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ + BIT_reloadDStream(&bitD); + + op[3] = FSE_GETSYMBOL(&state2); + } + + /* tail */ + /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ + while (1) { + if (op>(omax-2)) return ERROR(dstSize_tooSmall); + *op++ = FSE_GETSYMBOL(&state1); + if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) { + *op++ = FSE_GETSYMBOL(&state2); + break; + } + + if (op>(omax-2)) return ERROR(dstSize_tooSmall); + *op++ = FSE_GETSYMBOL(&state2); + if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) { + *op++ = FSE_GETSYMBOL(&state1); + break; + } } + + assert(op >= ostart); + return (size_t)(op-ostart); +} + +typedef struct { + short ncount[FSE_MAX_SYMBOL_VALUE + 1]; +} FSE_DecompressWksp; + + +FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body( + void* dst, size_t dstCapacity, + const void* cSrc, size_t cSrcSize, + unsigned maxLog, void* workSpace, size_t wkspSize, + int bmi2) +{ + const BYTE* const istart = (const BYTE*)cSrc; + const BYTE* ip = istart; + unsigned tableLog; + unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; + FSE_DecompressWksp* const wksp = (FSE_DecompressWksp*)workSpace; + size_t const dtablePos = sizeof(FSE_DecompressWksp) / sizeof(FSE_DTable); + FSE_DTable* const dtable = (FSE_DTable*)workSpace + dtablePos; + + FSE_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0); + if (wkspSize < sizeof(*wksp)) return ERROR(GENERIC); + + /* correct offset to dtable depends on this property */ + FSE_STATIC_ASSERT(sizeof(FSE_DecompressWksp) % sizeof(FSE_DTable) == 0); + + /* normal FSE decoding mode */ + { size_t const NCountLength = + FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2); + if (FSE_isError(NCountLength)) return NCountLength; + if (tableLog > maxLog) return ERROR(tableLog_tooLarge); + assert(NCountLength <= cSrcSize); + ip += NCountLength; + cSrcSize -= NCountLength; + } + + if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge); + assert(sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog) <= wkspSize); + workSpace = (BYTE*)workSpace + sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog); + wkspSize -= sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog); + + CHECK_F( FSE_buildDTable_internal(dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) ); + + { + const void* ptr = dtable; + const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr; + const U32 fastMode = DTableH->fastMode; + + /* select fast mode (static) */ + if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 1); + return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 0); + } +} + +/* Avoids the FORCE_INLINE of the _body() function. */ +static size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize) +{ + return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 0); +} + +#if DYNAMIC_BMI2 +BMI2_TARGET_ATTRIBUTE static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize) +{ + return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1); +} +#endif + +size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2) +{ +#if DYNAMIC_BMI2 + if (bmi2) { + return FSE_decompress_wksp_body_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize); + } +#endif + (void)bmi2; + return FSE_decompress_wksp_body_default(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize); +} + +#endif /* FSE_COMMONDEFS_ONLY */ diff --git a/third_party/zstd/common/fse_decompress.cpp b/third_party/zstd/common/fse_decompress.cpp deleted file mode 100644 index 8845948e0c8..00000000000 --- a/third_party/zstd/common/fse_decompress.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* ****************************************************************** - * FSE : Finite State Entropy decoder - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. - * - * You can contact the author at : - * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy - * - Public forum : https://groups.google.com/forum/#!forum/lz4c - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. -****************************************************************** */ - - -/* ************************************************************** -* Includes -****************************************************************/ -#include /* malloc, free, qsort */ -#include /* memcpy, memset */ -#include "zstd/common/bitstream.h" -#include "zstd/common/compiler.h" -#include "zstd/common/fse.h" -#include "zstd/common/fse_static.h" -#include "zstd/common/error_private.h" - - -/* ************************************************************** -* Error Management -****************************************************************/ -// #define FSE_isError ERR_isError -#define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */ - - -/* ************************************************************** -* Templates -****************************************************************/ -/* - designed to be included - for type-specific functions (template emulation in C) - Objective is to write these functions only once, for improved maintenance -*/ - -/* safety checks */ -#ifndef FSE_FUNCTION_EXTENSION -# error "FSE_FUNCTION_EXTENSION must be defined" -#endif -#ifndef FSE_FUNCTION_TYPE -# error "FSE_FUNCTION_TYPE must be defined" -#endif - -/* Function names */ -#define FSE_CAT(X,Y) X##Y -#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y) -#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y) - -namespace duckdb_zstd { - -/* Function templates */ -FSE_DTable* FSE_createDTable (unsigned tableLog) -{ - if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; - return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) ); -} - -void FSE_freeDTable (FSE_DTable* dt) -{ - free(dt); -} - -size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) -{ - void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */ - FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr); - U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1]; - - U32 const maxSV1 = maxSymbolValue + 1; - U32 const tableSize = 1 << tableLog; - U32 highThreshold = tableSize-1; - - /* Sanity Checks */ - if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge); - if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); - - /* Init, lay down lowprob symbols */ - { FSE_DTableHeader DTableH; - DTableH.tableLog = (U16)tableLog; - DTableH.fastMode = 1; - { S16 const largeLimit= (S16)(1 << (tableLog-1)); - U32 s; - for (s=0; s= largeLimit) DTableH.fastMode=0; - symbolNext[s] = normalizedCounter[s]; - } } } - memcpy(dt, &DTableH, sizeof(DTableH)); - } - - /* Spread symbols */ - { U32 const tableMask = tableSize-1; - U32 const step = FSE_TABLESTEP(tableSize); - U32 s, position = 0; - for (s=0; s highThreshold) position = (position + step) & tableMask; /* lowprob area */ - } } - if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ - } - - /* Build Decoding table */ - { U32 u; - for (u=0; utableLog = 0; - DTableH->fastMode = 0; - - cell->newState = 0; - cell->symbol = symbolValue; - cell->nbBits = 0; - - return 0; -} - - -size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits) -{ - void* ptr = dt; - FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; - void* dPtr = dt + 1; - FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr; - const unsigned tableSize = 1 << nbBits; - const unsigned tableMask = tableSize - 1; - const unsigned maxSV1 = tableMask+1; - unsigned s; - - /* Sanity checks */ - if (nbBits < 1) return ERROR(GENERIC); /* min size */ - - /* Build Decoding Table */ - DTableH->tableLog = (U16)nbBits; - DTableH->fastMode = 1; - for (s=0; s sizeof(bitD.bitContainer)*8) /* This test must be static */ - BIT_reloadDStream(&bitD); - - op[1] = FSE_GETSYMBOL(&state2); - - if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ - { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } } - - op[2] = FSE_GETSYMBOL(&state1); - - if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ - BIT_reloadDStream(&bitD); - - op[3] = FSE_GETSYMBOL(&state2); - } - - /* tail */ - /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ - while (1) { - if (op>(omax-2)) return ERROR(dstSize_tooSmall); - *op++ = FSE_GETSYMBOL(&state1); - if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) { - *op++ = FSE_GETSYMBOL(&state2); - break; - } - - if (op>(omax-2)) return ERROR(dstSize_tooSmall); - *op++ = FSE_GETSYMBOL(&state2); - if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) { - *op++ = FSE_GETSYMBOL(&state1); - break; - } } - - return op-ostart; -} - - -size_t FSE_decompress_usingDTable(void* dst, size_t originalSize, - const void* cSrc, size_t cSrcSize, - const FSE_DTable* dt) -{ - const void* ptr = dt; - const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr; - const U32 fastMode = DTableH->fastMode; - - /* select fast mode (static) */ - if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); - return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); -} - - -size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog) -{ - const BYTE* const istart = (const BYTE*)cSrc; - const BYTE* ip = istart; - short counting[FSE_MAX_SYMBOL_VALUE+1]; - unsigned tableLog; - unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; - - /* normal FSE decoding mode */ - size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); - if (FSE_isError(NCountLength)) return NCountLength; - /* if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); */ /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */ - if (tableLog > maxLog) return ERROR(tableLog_tooLarge); - ip += NCountLength; - cSrcSize -= NCountLength; - - CHECK_F( FSE_buildDTable (workSpace, counting, maxSymbolValue, tableLog) ); - - return FSE_decompress_usingDTable (dst, dstCapacity, ip, cSrcSize, workSpace); /* always return, even if it is an error code */ -} - - -typedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; - -size_t FSE_decompress(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize) -{ - DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ - return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, dt, FSE_MAX_TABLELOG); -} - -} - -#endif /* FSE_COMMONDEFS_ONLY */ diff --git a/third_party/zstd/common/pool.c b/third_party/zstd/common/pool.c new file mode 100644 index 00000000000..3adcefc9a50 --- /dev/null +++ b/third_party/zstd/common/pool.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + +/* ====== Dependencies ======= */ +#include "../common/allocations.h" /* ZSTD_customCalloc, ZSTD_customFree */ +#include "zstd_deps.h" /* size_t */ +#include "debug.h" /* assert */ +#include "pool.h" + +/* ====== Compiler specifics ====== */ +#if defined(_MSC_VER) +# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */ +#endif + + +#ifdef ZSTD_MULTITHREAD + +#include "threading.h" /* pthread adaptation */ + +/* A job is a function and an opaque argument */ +typedef struct POOL_job_s { + POOL_function function; + void *opaque; +} POOL_job; + +struct POOL_ctx_s { + ZSTD_customMem customMem; + /* Keep track of the threads */ + ZSTD_pthread_t* threads; + size_t threadCapacity; + size_t threadLimit; + + /* The queue is a circular buffer */ + POOL_job *queue; + size_t queueHead; + size_t queueTail; + size_t queueSize; + + /* The number of threads working on jobs */ + size_t numThreadsBusy; + /* Indicates if the queue is empty */ + int queueEmpty; + + /* The mutex protects the queue */ + ZSTD_pthread_mutex_t queueMutex; + /* Condition variable for pushers to wait on when the queue is full */ + ZSTD_pthread_cond_t queuePushCond; + /* Condition variables for poppers to wait on when the queue is empty */ + ZSTD_pthread_cond_t queuePopCond; + /* Indicates if the queue is shutting down */ + int shutdown; +}; + +/* POOL_thread() : + * Work thread for the thread pool. + * Waits for jobs and executes them. + * @returns : NULL on failure else non-null. + */ +static void* POOL_thread(void* opaque) { + POOL_ctx* const ctx = (POOL_ctx*)opaque; + if (!ctx) { return NULL; } + for (;;) { + /* Lock the mutex and wait for a non-empty queue or until shutdown */ + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + + while ( ctx->queueEmpty + || (ctx->numThreadsBusy >= ctx->threadLimit) ) { + if (ctx->shutdown) { + /* even if !queueEmpty, (possible if numThreadsBusy >= threadLimit), + * a few threads will be shutdown while !queueEmpty, + * but enough threads will remain active to finish the queue */ + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + return opaque; + } + ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex); + } + /* Pop a job off the queue */ + { POOL_job const job = ctx->queue[ctx->queueHead]; + ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize; + ctx->numThreadsBusy++; + ctx->queueEmpty = (ctx->queueHead == ctx->queueTail); + /* Unlock the mutex, signal a pusher, and run the job */ + ZSTD_pthread_cond_signal(&ctx->queuePushCond); + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + + job.function(job.opaque); + + /* If the intended queue size was 0, signal after finishing job */ + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + ctx->numThreadsBusy--; + ZSTD_pthread_cond_signal(&ctx->queuePushCond); + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + } + } /* for (;;) */ + assert(0); /* Unreachable */ +} + +/* ZSTD_createThreadPool() : public access point */ +POOL_ctx* ZSTD_createThreadPool(size_t numThreads) { + return POOL_create (numThreads, 0); +} + +POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) { + return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem); +} + +POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, + ZSTD_customMem customMem) +{ + POOL_ctx* ctx; + /* Check parameters */ + if (!numThreads) { return NULL; } + /* Allocate the context and zero initialize */ + ctx = (POOL_ctx*)ZSTD_customCalloc(sizeof(POOL_ctx), customMem); + if (!ctx) { return NULL; } + /* Initialize the job queue. + * It needs one extra space since one space is wasted to differentiate + * empty and full queues. + */ + ctx->queueSize = queueSize + 1; + ctx->queue = (POOL_job*)ZSTD_customCalloc(ctx->queueSize * sizeof(POOL_job), customMem); + ctx->queueHead = 0; + ctx->queueTail = 0; + ctx->numThreadsBusy = 0; + ctx->queueEmpty = 1; + { + int error = 0; + error |= ZSTD_pthread_mutex_init(&ctx->queueMutex, NULL); + error |= ZSTD_pthread_cond_init(&ctx->queuePushCond, NULL); + error |= ZSTD_pthread_cond_init(&ctx->queuePopCond, NULL); + if (error) { POOL_free(ctx); return NULL; } + } + ctx->shutdown = 0; + /* Allocate space for the thread handles */ + ctx->threads = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), customMem); + ctx->threadCapacity = 0; + ctx->customMem = customMem; + /* Check for errors */ + if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; } + /* Initialize the threads */ + { size_t i; + for (i = 0; i < numThreads; ++i) { + if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) { + ctx->threadCapacity = i; + POOL_free(ctx); + return NULL; + } } + ctx->threadCapacity = numThreads; + ctx->threadLimit = numThreads; + } + return ctx; +} + +/*! POOL_join() : + Shutdown the queue, wake any sleeping threads, and join all of the threads. +*/ +static void POOL_join(POOL_ctx* ctx) { + /* Shut down the queue */ + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + ctx->shutdown = 1; + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + /* Wake up sleeping threads */ + ZSTD_pthread_cond_broadcast(&ctx->queuePushCond); + ZSTD_pthread_cond_broadcast(&ctx->queuePopCond); + /* Join all of the threads */ + { size_t i; + for (i = 0; i < ctx->threadCapacity; ++i) { + ZSTD_pthread_join(ctx->threads[i]); /* note : could fail */ + } } +} + +void POOL_free(POOL_ctx *ctx) { + if (!ctx) { return; } + POOL_join(ctx); + ZSTD_pthread_mutex_destroy(&ctx->queueMutex); + ZSTD_pthread_cond_destroy(&ctx->queuePushCond); + ZSTD_pthread_cond_destroy(&ctx->queuePopCond); + ZSTD_customFree(ctx->queue, ctx->customMem); + ZSTD_customFree(ctx->threads, ctx->customMem); + ZSTD_customFree(ctx, ctx->customMem); +} + +/*! POOL_joinJobs() : + * Waits for all queued jobs to finish executing. + */ +void POOL_joinJobs(POOL_ctx* ctx) { + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + while(!ctx->queueEmpty || ctx->numThreadsBusy > 0) { + ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex); + } + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); +} + +void ZSTD_freeThreadPool (ZSTD_threadPool* pool) { + POOL_free (pool); +} + +size_t POOL_sizeof(const POOL_ctx* ctx) { + if (ctx==NULL) return 0; /* supports sizeof NULL */ + return sizeof(*ctx) + + ctx->queueSize * sizeof(POOL_job) + + ctx->threadCapacity * sizeof(ZSTD_pthread_t); +} + + +/* @return : 0 on success, 1 on error */ +static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads) +{ + if (numThreads <= ctx->threadCapacity) { + if (!numThreads) return 1; + ctx->threadLimit = numThreads; + return 0; + } + /* numThreads > threadCapacity */ + { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem); + if (!threadPool) return 1; + /* replace existing thread pool */ + ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(ZSTD_pthread_t)); + ZSTD_customFree(ctx->threads, ctx->customMem); + ctx->threads = threadPool; + /* Initialize additional threads */ + { size_t threadId; + for (threadId = ctx->threadCapacity; threadId < numThreads; ++threadId) { + if (ZSTD_pthread_create(&threadPool[threadId], NULL, &POOL_thread, ctx)) { + ctx->threadCapacity = threadId; + return 1; + } } + } } + /* successfully expanded */ + ctx->threadCapacity = numThreads; + ctx->threadLimit = numThreads; + return 0; +} + +/* @return : 0 on success, 1 on error */ +int POOL_resize(POOL_ctx* ctx, size_t numThreads) +{ + int result; + if (ctx==NULL) return 1; + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + result = POOL_resize_internal(ctx, numThreads); + ZSTD_pthread_cond_broadcast(&ctx->queuePopCond); + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + return result; +} + +/** + * Returns 1 if the queue is full and 0 otherwise. + * + * When queueSize is 1 (pool was created with an intended queueSize of 0), + * then a queue is empty if there is a thread free _and_ no job is waiting. + */ +static int isQueueFull(POOL_ctx const* ctx) { + if (ctx->queueSize > 1) { + return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize); + } else { + return (ctx->numThreadsBusy == ctx->threadLimit) || + !ctx->queueEmpty; + } +} + + +static void +POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque) +{ + POOL_job job; + job.function = function; + job.opaque = opaque; + assert(ctx != NULL); + if (ctx->shutdown) return; + + ctx->queueEmpty = 0; + ctx->queue[ctx->queueTail] = job; + ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize; + ZSTD_pthread_cond_signal(&ctx->queuePopCond); +} + +void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) +{ + assert(ctx != NULL); + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + /* Wait until there is space in the queue for the new job */ + while (isQueueFull(ctx) && (!ctx->shutdown)) { + ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex); + } + POOL_add_internal(ctx, function, opaque); + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); +} + + +int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) +{ + assert(ctx != NULL); + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + if (isQueueFull(ctx)) { + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + return 0; + } + POOL_add_internal(ctx, function, opaque); + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + return 1; +} + + +#else /* ZSTD_MULTITHREAD not defined */ + +/* ========================== */ +/* No multi-threading support */ +/* ========================== */ + + +/* We don't need any data, but if it is empty, malloc() might return NULL. */ +struct POOL_ctx_s { + int dummy; +}; +static POOL_ctx g_poolCtx; + +POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) { + return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem); +} + +POOL_ctx* +POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem) +{ + (void)numThreads; + (void)queueSize; + (void)customMem; + return &g_poolCtx; +} + +void POOL_free(POOL_ctx* ctx) { + assert(!ctx || ctx == &g_poolCtx); + (void)ctx; +} + +void POOL_joinJobs(POOL_ctx* ctx){ + assert(!ctx || ctx == &g_poolCtx); + (void)ctx; +} + +int POOL_resize(POOL_ctx* ctx, size_t numThreads) { + (void)ctx; (void)numThreads; + return 0; +} + +void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) { + (void)ctx; + function(opaque); +} + +int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) { + (void)ctx; + function(opaque); + return 1; +} + +size_t POOL_sizeof(const POOL_ctx* ctx) { + if (ctx==NULL) return 0; /* supports sizeof NULL */ + assert(ctx == &g_poolCtx); + return sizeof(*ctx); +} + +#endif /* ZSTD_MULTITHREAD */ diff --git a/third_party/zstd/common/threading.c b/third_party/zstd/common/threading.c new file mode 100644 index 00000000000..25bb8b98104 --- /dev/null +++ b/third_party/zstd/common/threading.c @@ -0,0 +1,182 @@ +/** + * Copyright (c) 2016 Tino Reichardt + * All rights reserved. + * + * You can contact the author at: + * - zstdmt source repository: https://github.com/mcmilk/zstdmt + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/** + * This file will hold wrapper for systems, which do not support pthreads + */ + +#include "threading.h" + +/* create fake symbol to avoid empty translation unit warning */ +int g_ZSTD_threading_useless_symbol; + +#if defined(ZSTD_MULTITHREAD) && defined(_WIN32) + +/** + * Windows minimalist Pthread Wrapper + */ + + +/* === Dependencies === */ +#include +#include + + +/* === Implementation === */ + +typedef struct { + void* (*start_routine)(void*); + void* arg; + int initialized; + ZSTD_pthread_cond_t initialized_cond; + ZSTD_pthread_mutex_t initialized_mutex; +} ZSTD_thread_params_t; + +static unsigned __stdcall worker(void *arg) +{ + void* (*start_routine)(void*); + void* thread_arg; + + /* Initialized thread_arg and start_routine and signal main thread that we don't need it + * to wait any longer. + */ + { + ZSTD_thread_params_t* thread_param = (ZSTD_thread_params_t*)arg; + thread_arg = thread_param->arg; + start_routine = thread_param->start_routine; + + /* Signal main thread that we are running and do not depend on its memory anymore */ + ZSTD_pthread_mutex_lock(&thread_param->initialized_mutex); + thread_param->initialized = 1; + ZSTD_pthread_cond_signal(&thread_param->initialized_cond); + ZSTD_pthread_mutex_unlock(&thread_param->initialized_mutex); + } + + start_routine(thread_arg); + + return 0; +} + +int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused, + void* (*start_routine) (void*), void* arg) +{ + ZSTD_thread_params_t thread_param; + (void)unused; + + if (thread==NULL) return -1; + *thread = NULL; + + thread_param.start_routine = start_routine; + thread_param.arg = arg; + thread_param.initialized = 0; + + /* Setup thread initialization synchronization */ + if(ZSTD_pthread_cond_init(&thread_param.initialized_cond, NULL)) { + /* Should never happen on Windows */ + return -1; + } + if(ZSTD_pthread_mutex_init(&thread_param.initialized_mutex, NULL)) { + /* Should never happen on Windows */ + ZSTD_pthread_cond_destroy(&thread_param.initialized_cond); + return -1; + } + + /* Spawn thread */ + *thread = (HANDLE)_beginthreadex(NULL, 0, worker, &thread_param, 0, NULL); + if (*thread==NULL) { + ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex); + ZSTD_pthread_cond_destroy(&thread_param.initialized_cond); + return errno; + } + + /* Wait for thread to be initialized */ + ZSTD_pthread_mutex_lock(&thread_param.initialized_mutex); + while(!thread_param.initialized) { + ZSTD_pthread_cond_wait(&thread_param.initialized_cond, &thread_param.initialized_mutex); + } + ZSTD_pthread_mutex_unlock(&thread_param.initialized_mutex); + ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex); + ZSTD_pthread_cond_destroy(&thread_param.initialized_cond); + + return 0; +} + +int ZSTD_pthread_join(ZSTD_pthread_t thread) +{ + DWORD result; + + if (!thread) return 0; + + result = WaitForSingleObject(thread, INFINITE); + CloseHandle(thread); + + switch (result) { + case WAIT_OBJECT_0: + return 0; + case WAIT_ABANDONED: + return EINVAL; + default: + return GetLastError(); + } +} + +#endif /* ZSTD_MULTITHREAD */ + +#if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32) + +#define ZSTD_DEPS_NEED_MALLOC +#include "zstd_deps.h" + +int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr) +{ + assert(mutex != NULL); + *mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t)); + if (!*mutex) + return 1; + return pthread_mutex_init(*mutex, attr); +} + +int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex) +{ + assert(mutex != NULL); + if (!*mutex) + return 0; + { + int const ret = pthread_mutex_destroy(*mutex); + ZSTD_free(*mutex); + return ret; + } +} + +int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr) +{ + assert(cond != NULL); + *cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t)); + if (!*cond) + return 1; + return pthread_cond_init(*cond, attr); +} + +int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond) +{ + assert(cond != NULL); + if (!*cond) + return 0; + { + int const ret = pthread_cond_destroy(*cond); + ZSTD_free(*cond); + return ret; + } +} + +#endif diff --git a/third_party/zstd/common/xxhash.c b/third_party/zstd/common/xxhash.c new file mode 100644 index 00000000000..052cd522824 --- /dev/null +++ b/third_party/zstd/common/xxhash.c @@ -0,0 +1,18 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Copyright (c) Yann Collet - Meta Platforms, Inc + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* + * xxhash.c instantiates functions defined in xxhash.h + */ + +#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ +#define XXH_IMPLEMENTATION /* access definitions */ + +#include "xxhash.h" diff --git a/third_party/zstd/common/xxhash.cpp b/third_party/zstd/common/xxhash.cpp deleted file mode 100644 index 9ec9375220d..00000000000 --- a/third_party/zstd/common/xxhash.cpp +++ /dev/null @@ -1,859 +0,0 @@ -/* - * xxHash - Fast Hash algorithm - * Copyright (c) 2012-2020, Yann Collet, Facebook, Inc. - * - * You can contact the author at : - * - xxHash homepage: http://www.xxhash.com - * - xxHash source repository : https://github.com/Cyan4973/xxHash - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. -*/ - - -/* ************************************* -* Tuning parameters -***************************************/ -/*!XXH_FORCE_MEMORY_ACCESS : - * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. - * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. - * The below switch allow to select different access method for improved performance. - * Method 0 (default) : use `memcpy()`. Safe and portable. - * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). - * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. - * Method 2 : direct access. This method doesn't depend on compiler but violate C standard. - * It can generate buggy code on targets which do not support unaligned memory accesses. - * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) - * See http://stackoverflow.com/a/32095106/646947 for details. - * Prefer these methods in priority order (0 > 1 > 2) - */ -#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ -# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) -# define XXH_FORCE_MEMORY_ACCESS 2 -# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \ - (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) || \ - defined(__ICCARM__) -# define XXH_FORCE_MEMORY_ACCESS 1 -# endif -#endif - -/*!XXH_ACCEPT_NULL_INPUT_POINTER : - * If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer. - * When this option is enabled, xxHash output for null input pointers will be the same as a null-length input. - * By default, this option is disabled. To enable it, uncomment below define : - */ -/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */ - -/*!XXH_FORCE_NATIVE_FORMAT : - * By default, xxHash library provides endian-independent Hash values, based on little-endian convention. - * Results are therefore identical for little-endian and big-endian CPU. - * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. - * Should endian-independence be of no importance for your application, you may set the #define below to 1, - * to improve speed for Big-endian CPU. - * This option has no impact on Little_Endian CPU. - */ -#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */ -# define XXH_FORCE_NATIVE_FORMAT 0 -#endif - -/*!XXH_FORCE_ALIGN_CHECK : - * This is a minor performance trick, only useful with lots of very small keys. - * It means : check for aligned/unaligned input. - * The check costs one initial branch per hash; set to 0 when the input data - * is guaranteed to be aligned. - */ -#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ -# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) -# define XXH_FORCE_ALIGN_CHECK 0 -# else -# define XXH_FORCE_ALIGN_CHECK 1 -# endif -#endif - - -/* ************************************* -* Includes & Memory related functions -***************************************/ -/* Modify the local functions below should you wish to use some other memory routines */ -/* for malloc(), free() */ -#include -#include /* size_t */ -/* for memcpy() */ -#include - -#include "zstd/common/xxhash.h" -#include "zstd/common/xxhash_static.h" - -/* ************************************* -* Compiler Specific Options -***************************************/ -#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -# define INLINE_KEYWORD inline -#else -# define INLINE_KEYWORD -#endif - -#if defined(__GNUC__) || defined(__ICCARM__) -# define FORCE_INLINE_ATTR __attribute__((always_inline)) -#elif defined(_MSC_VER) -# define FORCE_INLINE_ATTR __forceinline -#else -# define FORCE_INLINE_ATTR -#endif - -#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR - - -/* ************************************* -* Basic Types -***************************************/ -#ifndef MEM_MODULE -# define MEM_MODULE -# if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint8_t BYTE; - typedef uint16_t U16; - typedef uint32_t U32; - typedef int32_t S32; - typedef uint64_t U64; -# else - typedef unsigned char BYTE; - typedef unsigned short U16; - typedef unsigned int U32; - typedef signed int S32; - typedef unsigned long long U64; /* if your compiler doesn't support unsigned long long, replace by another 64-bit type here. Note that xxhash.h will also need to be updated. */ -# endif -#endif - -namespace duckdb_zstd { -static void* XXH_malloc(size_t s) { return malloc(s); } -static void XXH_free (void* p) { free(p); } -static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } - -#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) - -/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ -static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; } -static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; } - -#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) - -/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ -/* currently only defined for gcc and icc */ -typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign; - -static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } -static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; } - -#else - -/* portable and safe solution. Generally efficient. - * see : http://stackoverflow.com/a/32095106/646947 - */ - -static U32 XXH_read32(const void* memPtr) -{ - U32 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -static U64 XXH_read64(const void* memPtr) -{ - U64 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ - - -/* **************************************** -* Compiler-specific Functions and Macros -******************************************/ -#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) - -/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ -#if defined(_MSC_VER) -# define XXH_rotl32(x,r) _rotl(x,r) -# define XXH_rotl64(x,r) _rotl64(x,r) -#else -#if defined(__ICCARM__) -# include -# define XXH_rotl32(x,r) __ROR(x,(32 - r)) -#else -# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) -#endif -# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) -#endif - -#if defined(_MSC_VER) /* Visual Studio */ -# define XXH_swap32 _byteswap_ulong -# define XXH_swap64 _byteswap_uint64 -#elif GCC_VERSION >= 403 -# define XXH_swap32 __builtin_bswap32 -# define XXH_swap64 __builtin_bswap64 -#else -static U32 XXH_swap32 (U32 x) -{ - return ((x << 24) & 0xff000000 ) | - ((x << 8) & 0x00ff0000 ) | - ((x >> 8) & 0x0000ff00 ) | - ((x >> 24) & 0x000000ff ); -} -static U64 XXH_swap64 (U64 x) -{ - return ((x << 56) & 0xff00000000000000ULL) | - ((x << 40) & 0x00ff000000000000ULL) | - ((x << 24) & 0x0000ff0000000000ULL) | - ((x << 8) & 0x000000ff00000000ULL) | - ((x >> 8) & 0x00000000ff000000ULL) | - ((x >> 24) & 0x0000000000ff0000ULL) | - ((x >> 40) & 0x000000000000ff00ULL) | - ((x >> 56) & 0x00000000000000ffULL); -} -#endif - - -/* ************************************* -* Architecture Macros -***************************************/ -typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; - -/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ -#ifndef XXH_CPU_LITTLE_ENDIAN - static const int g_one = 1; -# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&g_one)) -#endif - - -/* *************************** -* Memory reads -*****************************/ -typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; - -FORCE_INLINE_TEMPLATE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align) -{ - if (align==XXH_unaligned) - return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); - else - return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr); -} - -FORCE_INLINE_TEMPLATE U32 XXH_readLE32(const void* ptr, XXH_endianess endian) -{ - return XXH_readLE32_align(ptr, endian, XXH_unaligned); -} - -static U32 XXH_readBE32(const void* ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); -} - -FORCE_INLINE_TEMPLATE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align) -{ - if (align==XXH_unaligned) - return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); - else - return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr); -} - -FORCE_INLINE_TEMPLATE U64 XXH_readLE64(const void* ptr, XXH_endianess endian) -{ - return XXH_readLE64_align(ptr, endian, XXH_unaligned); -} - -static U64 XXH_readBE64(const void* ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); -} - - -/* ************************************* -* Macros -***************************************/ -#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ - - -/* ************************************* -* Constants -***************************************/ -static const U32 PRIME32_1 = 2654435761U; -static const U32 PRIME32_2 = 2246822519U; -static const U32 PRIME32_3 = 3266489917U; -static const U32 PRIME32_4 = 668265263U; -static const U32 PRIME32_5 = 374761393U; - -static const U64 PRIME64_1 = 11400714785074694791ULL; -static const U64 PRIME64_2 = 14029467366897019727ULL; -static const U64 PRIME64_3 = 1609587929392839161ULL; -static const U64 PRIME64_4 = 9650029242287828579ULL; -static const U64 PRIME64_5 = 2870177450012600261ULL; - -XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } - - -/* ************************** -* Utils -****************************/ -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* __restrict dstState, const XXH32_state_t* __restrict srcState) -{ - memcpy(dstState, srcState, sizeof(*dstState)); -} - -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* __restrict dstState, const XXH64_state_t* __restrict srcState) -{ - memcpy(dstState, srcState, sizeof(*dstState)); -} - - -/* *************************** -* Simple Hash Functions -*****************************/ - -static U32 XXH32_round(U32 seed, U32 input) -{ - seed += input * PRIME32_2; - seed = XXH_rotl32(seed, 13); - seed *= PRIME32_1; - return seed; -} - -FORCE_INLINE_TEMPLATE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* bEnd = p + len; - U32 h32; -#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (p==NULL) { - len=0; - bEnd=p=(const BYTE*)(size_t)16; - } -#endif - - if (len>=16) { - const BYTE* const limit = bEnd - 16; - U32 v1 = seed + PRIME32_1 + PRIME32_2; - U32 v2 = seed + PRIME32_2; - U32 v3 = seed + 0; - U32 v4 = seed - PRIME32_1; - - do { - v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4; - v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4; - v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4; - v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4; - } while (p<=limit); - - h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); - } else { - h32 = seed + PRIME32_5; - } - - h32 += (U32) len; - - while (p+4<=bEnd) { - h32 += XXH_get32bits(p) * PRIME32_3; - h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; - p+=4; - } - - while (p> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - - return h32; -} - - -XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed) -{ -#if 0 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH32_CREATESTATE_STATIC(state); - XXH32_reset(state, seed); - XXH32_update(state, input, len); - return XXH32_digest(state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if (XXH_FORCE_ALIGN_CHECK) { - if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); - } } - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - - -static U64 XXH64_round(U64 acc, U64 input) -{ - acc += input * PRIME64_2; - acc = XXH_rotl64(acc, 31); - acc *= PRIME64_1; - return acc; -} - -static U64 XXH64_mergeRound(U64 acc, U64 val) -{ - val = XXH64_round(0, val); - acc ^= val; - acc = acc * PRIME64_1 + PRIME64_4; - return acc; -} - -FORCE_INLINE_TEMPLATE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - U64 h64; -#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (p==NULL) { - len=0; - bEnd=p=(const BYTE*)(size_t)32; - } -#endif - - if (len>=32) { - const BYTE* const limit = bEnd - 32; - U64 v1 = seed + PRIME64_1 + PRIME64_2; - U64 v2 = seed + PRIME64_2; - U64 v3 = seed + 0; - U64 v4 = seed - PRIME64_1; - - do { - v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8; - v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8; - v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8; - v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8; - } while (p<=limit); - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); - h64 = XXH64_mergeRound(h64, v1); - h64 = XXH64_mergeRound(h64, v2); - h64 = XXH64_mergeRound(h64, v3); - h64 = XXH64_mergeRound(h64, v4); - - } else { - h64 = seed + PRIME64_5; - } - - h64 += (U64) len; - - while (p+8<=bEnd) { - U64 const k1 = XXH64_round(0, XXH_get64bits(p)); - h64 ^= k1; - h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; - p+=8; - } - - if (p+4<=bEnd) { - h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; - h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; - p+=4; - } - - while (p> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - - return h64; -} - - -XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed) -{ -#if 0 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH64_CREATESTATE_STATIC(state); - XXH64_reset(state, seed); - XXH64_update(state, input, len); - return XXH64_digest(state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if (XXH_FORCE_ALIGN_CHECK) { - if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); - } } - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - - -/* ************************************************** -* Advanced Hash Functions -****************************************************/ - -XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) -{ - return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); -} -XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -} - -XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) -{ - return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); -} -XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -} - - -/*** Hash feed ***/ - -XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed) -{ - XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */ - state.v1 = seed + PRIME32_1 + PRIME32_2; - state.v2 = seed + PRIME32_2; - state.v3 = seed + 0; - state.v4 = seed - PRIME32_1; - memcpy(statePtr, &state, sizeof(state)); - return XXH_OK; -} - - -XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed) -{ - XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */ - state.v1 = seed + PRIME64_1 + PRIME64_2; - state.v2 = seed + PRIME64_2; - state.v3 = seed + 0; - state.v4 = seed - PRIME64_1; - memcpy(statePtr, &state, sizeof(state)); - return XXH_OK; -} - - -FORCE_INLINE_TEMPLATE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (input==NULL) return XXH_ERROR; -#endif - - state->total_len_32 += (unsigned)len; - state->large_len |= (len>=16) | (state->total_len_32>=16); - - if (state->memsize + len < 16) { /* fill in tmp buffer */ - XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len); - state->memsize += (unsigned)len; - return XXH_OK; - } - - if (state->memsize) { /* some data left from previous update */ - XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize); - { const U32* p32 = state->mem32; - state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++; - state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++; - state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++; - state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); p32++; - } - p += 16-state->memsize; - state->memsize = 0; - } - - if (p <= bEnd-16) { - const BYTE* const limit = bEnd - 16; - U32 v1 = state->v1; - U32 v2 = state->v2; - U32 v3 = state->v3; - U32 v4 = state->v4; - - do { - v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4; - v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4; - v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4; - v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4; - } while (p<=limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) { - XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); - } - - return XXH_OK; -} - -XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH32_update_endian(state_in, input, len, XXH_bigEndian); -} - - - -FORCE_INLINE_TEMPLATE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian) -{ - const BYTE * p = (const BYTE*)state->mem32; - const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize; - U32 h32; - - if (state->large_len) { - h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); - } else { - h32 = state->v3 /* == seed */ + PRIME32_5; - } - - h32 += state->total_len_32; - - while (p+4<=bEnd) { - h32 += XXH_readLE32(p, endian) * PRIME32_3; - h32 = XXH_rotl32(h32, 17) * PRIME32_4; - p+=4; - } - - while (p> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - - return h32; -} - - -XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_digest_endian(state_in, XXH_littleEndian); - else - return XXH32_digest_endian(state_in, XXH_bigEndian); -} - - - -/* **** XXH64 **** */ - -FORCE_INLINE_TEMPLATE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (input==NULL) return XXH_ERROR; -#endif - - state->total_len += len; - - if (state->memsize + len < 32) { /* fill in tmp buffer */ - if (input != NULL) { - XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); - } - state->memsize += (U32)len; - return XXH_OK; - } - - if (state->memsize) { /* tmp buffer is full */ - XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize); - state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian)); - state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian)); - state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian)); - state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian)); - p += 32-state->memsize; - state->memsize = 0; - } - - if (p+32 <= bEnd) { - const BYTE* const limit = bEnd - 32; - U64 v1 = state->v1; - U64 v2 = state->v2; - U64 v3 = state->v3; - U64 v4 = state->v4; - - do { - v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8; - v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8; - v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8; - v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8; - } while (p<=limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) { - XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); - } - - return XXH_OK; -} - -XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH64_update_endian(state_in, input, len, XXH_bigEndian); -} - - - -FORCE_INLINE_TEMPLATE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian) -{ - const BYTE * p = (const BYTE*)state->mem64; - const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize; - U64 h64; - - if (state->total_len >= 32) { - U64 const v1 = state->v1; - U64 const v2 = state->v2; - U64 const v3 = state->v3; - U64 const v4 = state->v4; - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); - h64 = XXH64_mergeRound(h64, v1); - h64 = XXH64_mergeRound(h64, v2); - h64 = XXH64_mergeRound(h64, v3); - h64 = XXH64_mergeRound(h64, v4); - } else { - h64 = state->v3 + PRIME64_5; - } - - h64 += (U64) state->total_len; - - while (p+8<=bEnd) { - U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian)); - h64 ^= k1; - h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; - p+=8; - } - - if (p+4<=bEnd) { - h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1; - h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; - p+=4; - } - - while (p> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - - return h64; -} - - -XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_digest_endian(state_in, XXH_littleEndian); - else - return XXH64_digest_endian(state_in, XXH_bigEndian); -} - - -/* ************************** -* Canonical representation -****************************/ - -/*! Default XXH result types are basic unsigned 32 and 64 bits. -* The canonical representation follows human-readable write convention, aka big-endian (large digits first). -* These functions allow transformation of hash result into and from its canonical format. -* This way, hash values can be written into a file or buffer, and remain comparable across different systems and programs. -*/ - -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); - memcpy(dst, &hash, sizeof(*dst)); -} - -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); - memcpy(dst, &hash, sizeof(*dst)); -} - -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) -{ - return XXH_readBE32(src); -} - -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) -{ - return XXH_readBE64(src); -} - -} diff --git a/third_party/zstd/common/zstd_common.cpp b/third_party/zstd/common/zstd_common.c similarity index 56% rename from third_party/zstd/common/zstd_common.cpp rename to third_party/zstd/common/zstd_common.c index d7700be3bae..3f04c22abf6 100644 --- a/third_party/zstd/common/zstd_common.cpp +++ b/third_party/zstd/common/zstd_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -13,12 +13,10 @@ /*-************************************* * Dependencies ***************************************/ -#include /* malloc, calloc, free */ -#include /* memset */ -#include "zstd/common/error_private.h" -#include "zstd/common/zstd_internal.h" +#define ZSTD_DEPS_NEED_MALLOC +#include "error_private.h" +#include "zstd_internal.h" -namespace duckdb_zstd { /*-**************************************** * Version @@ -48,39 +46,3 @@ ZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); } /*! ZSTD_getErrorString() : * provides error code string from enum */ const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString(code); } - - - -/*=************************************************************** -* Custom allocator -****************************************************************/ -void* ZSTD_malloc(size_t size, ZSTD_customMem customMem) -{ - if (customMem.customAlloc) - return customMem.customAlloc(customMem.opaque, size); - return malloc(size); -} - -void* ZSTD_calloc(size_t size, ZSTD_customMem customMem) -{ - if (customMem.customAlloc) { - /* calloc implemented as malloc+memset; - * not as efficient as calloc, but next best guess for custom malloc */ - void* const ptr = customMem.customAlloc(customMem.opaque, size); - memset(ptr, 0, size); - return ptr; - } - return calloc(1, size); -} - -void ZSTD_free(void* ptr, ZSTD_customMem customMem) -{ - if (ptr!=NULL) { - if (customMem.customFree) - customMem.customFree(customMem.opaque, ptr); - else - free(ptr); - } -} - -} diff --git a/third_party/zstd/compress/fse_compress.cpp b/third_party/zstd/compress/fse_compress.c similarity index 72% rename from third_party/zstd/compress/fse_compress.cpp rename to third_party/zstd/compress/fse_compress.c index 378e2925c88..1ce3cf16ac1 100644 --- a/third_party/zstd/compress/fse_compress.cpp +++ b/third_party/zstd/compress/fse_compress.c @@ -1,6 +1,6 @@ /* ****************************************************************** * FSE : Finite State Entropy encoder - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * You can contact the author at : * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -15,22 +15,24 @@ /* ************************************************************** * Includes ****************************************************************/ -#include /* malloc, free, qsort */ -#include /* memcpy, memset */ -#include "zstd/common/compiler.h" -#include "zstd/common/mem.h" /* U32, U16, etc. */ -#include "zstd/common/debug.h" /* assert, DEBUGLOG */ -#include "zstd/compress/hist.h" /* HIST_count_wksp */ -#include "zstd/common/bitstream.h" -#include "zstd/common/fse.h" -#include "zstd/common/fse_static.h" -#include "zstd/common/error_private.h" +#include "../common/compiler.h" +#include "../common/mem.h" /* U32, U16, etc. */ +#include "../common/debug.h" /* assert, DEBUGLOG */ +#include "hist.h" /* HIST_count_wksp */ +#include "../common/bitstream.h" +#define FSE_STATIC_LINKING_ONLY +#include "../common/fse.h" +#include "../common/error_private.h" +#define ZSTD_DEPS_NEED_MALLOC +#define ZSTD_DEPS_NEED_MATH64 +#include "../common/zstd_deps.h" /* ZSTD_memset */ +#include "../common/bits.h" /* ZSTD_highbit32 */ /* ************************************************************** * Error Management ****************************************************************/ -// #define FSE_isError ERR_isError +#define FSE_isError ERR_isError /* ************************************************************** @@ -55,7 +57,6 @@ #define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y) #define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y) -namespace duckdb_zstd { /* Function templates */ @@ -75,41 +76,85 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ; FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT); U32 const step = FSE_TABLESTEP(tableSize); - U32 cumul[FSE_MAX_SYMBOL_VALUE+2]; + U32 const maxSV1 = maxSymbolValue+1; + + U16* cumul = (U16*)workSpace; /* size = maxSV1 */ + FSE_FUNCTION_TYPE* const tableSymbol = (FSE_FUNCTION_TYPE*)(cumul + (maxSV1+1)); /* size = tableSize */ - FSE_FUNCTION_TYPE* const tableSymbol = (FSE_FUNCTION_TYPE*)workSpace; U32 highThreshold = tableSize-1; + assert(((size_t)workSpace & 1) == 0); /* Must be 2 bytes-aligned */ + if (FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) > wkspSize) return ERROR(tableLog_tooLarge); /* CTable header */ - if (((size_t)1 << tableLog) * sizeof(FSE_FUNCTION_TYPE) > wkspSize) return ERROR(tableLog_tooLarge); tableU16[-2] = (U16) tableLog; tableU16[-1] = (U16) maxSymbolValue; assert(tableLog < 16); /* required for threshold strategy to work */ /* For explanations on how to distribute symbol values over the table : - * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */ + * https://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */ #ifdef __clang_analyzer__ - memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize); /* useless initialization, just to keep scan-build happy */ + ZSTD_memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize); /* useless initialization, just to keep scan-build happy */ #endif /* symbol start positions */ { U32 u; cumul[0] = 0; - for (u=1; u <= maxSymbolValue+1; u++) { + for (u=1; u <= maxSV1; u++) { if (normalizedCounter[u-1]==-1) { /* Low proba symbol */ cumul[u] = cumul[u-1] + 1; tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(u-1); } else { - cumul[u] = cumul[u-1] + normalizedCounter[u-1]; + assert(normalizedCounter[u-1] >= 0); + cumul[u] = cumul[u-1] + (U16)normalizedCounter[u-1]; + assert(cumul[u] >= cumul[u-1]); /* no overflow */ } } - cumul[maxSymbolValue+1] = tableSize+1; + cumul[maxSV1] = (U16)(tableSize+1); } /* Spread symbols */ - { U32 position = 0; + if (highThreshold == tableSize - 1) { + /* Case for no low prob count symbols. Lay down 8 bytes at a time + * to reduce branch misses since we are operating on a small block + */ + BYTE* const spread = tableSymbol + tableSize; /* size = tableSize + 8 (may write beyond tableSize) */ + { U64 const add = 0x0101010101010101ull; + size_t pos = 0; + U64 sv = 0; + U32 s; + for (s=0; s=0); + pos += (size_t)n; + } + } + /* Spread symbols across the table. Lack of lowprob symbols means that + * we don't need variable sized inner loop, so we can unroll the loop and + * reduce branch misses. + */ + { size_t position = 0; + size_t s; + size_t const unroll = 2; /* Experimentally determined optimal unroll */ + assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */ + for (s = 0; s < (size_t)tableSize; s += unroll) { + size_t u; + for (u = 0; u < unroll; ++u) { + size_t const uPosition = (position + (u * step)) & tableMask; + tableSymbol[uPosition] = spread[s + u]; + } + position = (position + (unroll * step)) & tableMask; + } + assert(position == 0); /* Must have initialized all positions */ + } + } else { + U32 position = 0; U32 symbol; - for (symbol=0; symbol<=maxSymbolValue; symbol++) { + for (symbol=0; symbol highThreshold) position = (position + step) & tableMask; /* Low proba area */ } } - assert(position==0); /* Must have initialized all positions */ } @@ -142,16 +186,17 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, case -1: case 1: symbolTT[s].deltaNbBits = (tableLog << 16) - (1< 1); + { U32 const maxBitsOut = tableLog - ZSTD_highbit32 ((U32)normalizedCounter[s]-1); + U32 const minStatePlus = (U32)normalizedCounter[s] << maxBitsOut; symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus; - symbolTT[s].deltaFindState = total - normalizedCounter[s]; - total += normalizedCounter[s]; + symbolTT[s].deltaFindState = (int)(total - (unsigned)normalizedCounter[s]); + total += (unsigned)normalizedCounter[s]; } } } } #if 0 /* debug : symbol costs */ @@ -162,31 +207,26 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, symbol, normalizedCounter[symbol], FSE_getMaxNbBits(symbolTT, symbol), (double)FSE_bitCost(symbolTT, tableLog, symbol, 8) / 256); - } - } + } } #endif return 0; } -size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) -{ - FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */ - return FSE_buildCTable_wksp(ct, normalizedCounter, maxSymbolValue, tableLog, tableSymbol, sizeof(tableSymbol)); -} - - #ifndef FSE_COMMONDEFS_ONLY - /*-************************************************************** * FSE NCount encoding ****************************************************************/ size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog) { - size_t const maxHeaderSize = (((maxSymbolValue+1) * tableLog) >> 3) + 3; + size_t const maxHeaderSize = (((maxSymbolValue+1) * tableLog + + 4 /* bitCount initialized at 4 */ + + 2 /* first two symbols may use one additional bit each */) / 8) + + 1 /* round up to whole nb bytes */ + + 2 /* additional two bytes for bitstream flush */; return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */ } @@ -215,7 +255,7 @@ FSE_writeNCount_generic (void* header, size_t headerBufferSize, /* Init */ remaining = tableSize+1; /* +1 for extra accuracy */ threshold = tableSize; - nbBits = tableLog+1; + nbBits = (int)tableLog+1; while ((symbol < alphabetSize) && (remaining>1)) { /* stops at 1 */ if (previousIs0) { @@ -234,7 +274,7 @@ FSE_writeNCount_generic (void* header, size_t headerBufferSize, } while (symbol >= start+3) { start+=3; - bitStream += 3 << bitCount; + bitStream += 3U << bitCount; bitCount += 2; } bitStream += (symbol-start) << bitCount; @@ -254,7 +294,7 @@ FSE_writeNCount_generic (void* header, size_t headerBufferSize, count++; /* +1 for extra accuracy */ if (count>=threshold) count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */ - bitStream += count << bitCount; + bitStream += (U32)count << bitCount; bitCount += nbBits; bitCount -= (count>8); out+= (bitCount+7) /8; - return (out-ostart); + assert(out >= ostart); + return (size_t)(out-ostart); } @@ -303,21 +344,11 @@ size_t FSE_writeNCount (void* buffer, size_t bufferSize, * FSE Compression Code ****************************************************************/ -FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog) -{ - size_t size; - if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; - size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32); - return (FSE_CTable*)malloc(size); -} - -void FSE_freeCTable (FSE_CTable* ct) { free(ct); } - /* provides the minimum logSize to safely represent a distribution */ static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue) { - U32 minBitsSrc = BIT_highbit32((U32)(srcSize)) + 1; - U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2; + U32 minBitsSrc = ZSTD_highbit32((U32)(srcSize)) + 1; + U32 minBitsSymbols = ZSTD_highbit32(maxSymbolValue) + 2; U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols; assert(srcSize > 1); /* Not supported, RLE should be used instead */ return minBits; @@ -325,7 +356,7 @@ static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue) unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus) { - U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus; + U32 maxBitsSrc = ZSTD_highbit32((U32)(srcSize - 1)) - minus; U32 tableLog = maxTableLog; U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue); assert(srcSize > 1); /* Not supported, RLE should be used instead */ @@ -342,11 +373,10 @@ unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 2); } - /* Secondary normalization method. To be used when primary method fails. */ -static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue) +static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue, short lowProbCount) { short const NOT_YET_ASSIGNED = -2; U32 s; @@ -363,7 +393,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, continue; } if (count[s] <= lowThreshold) { - norm[s] = -1; + norm[s] = lowProbCount; distributed++; total -= count[s]; continue; @@ -415,7 +445,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, { U64 const vStepLog = 62 - tableLog; U64 const mid = (1ULL << (vStepLog-1)) - 1; - U64 const rStep = ((((U64)1<> scale); @@ -471,7 +501,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, } } if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) { /* corner case, need another normalization method */ - size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue); + size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue, lowProbCount); if (FSE_isError(errorCode)) return errorCode; } else normalizedCounter[largest] += (short)stillToDistribute; @@ -494,40 +524,6 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, return tableLog; } - -/* fake FSE_CTable, for raw (uncompressed) input */ -size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits) -{ - const unsigned tableSize = 1 << nbBits; - const unsigned tableMask = tableSize - 1; - const unsigned maxSymbolValue = tableMask; - void* const ptr = ct; - U16* const tableU16 = ( (U16*) ptr) + 2; - void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableSize>>1); /* assumption : tableLog >= 1 */ - FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT); - unsigned s; - - /* Sanity checks */ - if (nbBits < 1) return ERROR(GENERIC); /* min size */ - - /* header */ - tableU16[-2] = (U16) nbBits; - tableU16[-1] = (U16) maxSymbolValue; - - /* Build table */ - for (s=0; s not compressible */ - if (maxCount < (srcSize >> 7)) return 0; /* Heuristic : not compressible enough */ - } - - tableLog = FSE_optimalTableLog(tableLog, srcSize, maxSymbolValue); - CHECK_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue) ); - - /* Write table description header */ - { CHECK_V_F(nc_err, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) ); - op += nc_err; - } - - /* Compress */ - CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, scratchBufferSize) ); - { CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, src, srcSize, CTable) ); - if (cSize == 0) return 0; /* not enough space for compressed data */ - op += cSize; - } - - /* check compressibility */ - if ( (size_t)(op-ostart) >= srcSize-1 ) return 0; - - return op-ostart; -} - -typedef struct { - FSE_CTable CTable_max[FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)]; - BYTE scratchBuffer[1 << FSE_MAX_TABLELOG]; -} fseWkspMax_t; - -size_t FSE_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog) -{ - fseWkspMax_t scratchBuffer; - DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */ - if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); - return FSE_compress_wksp(dst, dstCapacity, src, srcSize, maxSymbolValue, tableLog, &scratchBuffer, sizeof(scratchBuffer)); -} - -size_t FSE_compress (void* dst, size_t dstCapacity, const void* src, size_t srcSize) -{ - return FSE_compress2(dst, dstCapacity, src, srcSize, FSE_MAX_SYMBOL_VALUE, FSE_DEFAULT_TABLELOG); -} - -} - #endif /* FSE_COMMONDEFS_ONLY */ diff --git a/third_party/zstd/compress/hist.cpp b/third_party/zstd/compress/hist.c similarity index 83% rename from third_party/zstd/compress/hist.cpp rename to third_party/zstd/compress/hist.c index 0a3d04a00dd..e2fb431f03a 100644 --- a/third_party/zstd/compress/hist.cpp +++ b/third_party/zstd/compress/hist.c @@ -1,7 +1,7 @@ /* ****************************************************************** * hist : Histogram functions * part of Finite State Entropy project - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * You can contact the author at : * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -14,14 +14,12 @@ ****************************************************************** */ /* --- dependencies --- */ -#include "zstd/common/mem.h" /* U32, BYTE, etc. */ -#include "zstd/common/debug.h" /* assert, DEBUGLOG */ -#include "zstd/common/error_private.h" /* ERROR */ -#include "zstd/compress/hist.h" +#include "../common/mem.h" /* U32, BYTE, etc. */ +#include "../common/debug.h" /* assert, DEBUGLOG */ +#include "../common/error_private.h" /* ERROR */ +#include "hist.h" -namespace duckdb_zstd { - /* --- Error management --- */ unsigned HIST_isError(size_t code) { return ERR_isError(code); } @@ -36,7 +34,7 @@ unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, unsigned maxSymbolValue = *maxSymbolValuePtr; unsigned largestCount=0; - memset(count, 0, (maxSymbolValue+1) * sizeof(*count)); + ZSTD_memset(count, 0, (maxSymbolValue+1) * sizeof(*count)); if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; } while (ip= HIST_WKSP_SIZE_U32. + * `workSpace` must be a U32 table of size >= HIST_WKSP_SIZE_U32. * @return : largest histogram frequency, - * or an error code (notably when histogram would be larger than *maxSymbolValuePtr). */ + * or an error code (notably when histogram's alphabet is larger than *maxSymbolValuePtr) */ static size_t HIST_count_parallel_wksp( unsigned* count, unsigned* maxSymbolValuePtr, const void* source, size_t sourceSize, @@ -73,22 +71,21 @@ static size_t HIST_count_parallel_wksp( { const BYTE* ip = (const BYTE*)source; const BYTE* const iend = ip+sourceSize; - unsigned maxSymbolValue = *maxSymbolValuePtr; + size_t const countSize = (*maxSymbolValuePtr + 1) * sizeof(*count); unsigned max=0; U32* const Counting1 = workSpace; U32* const Counting2 = Counting1 + 256; U32* const Counting3 = Counting2 + 256; U32* const Counting4 = Counting3 + 256; - memset(workSpace, 0, 4*256*sizeof(unsigned)); - /* safety checks */ + assert(*maxSymbolValuePtr <= 255); if (!sourceSize) { - memset(count, 0, maxSymbolValue + 1); + ZSTD_memset(count, 0, countSize); *maxSymbolValuePtr = 0; return 0; } - if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */ + ZSTD_memset(workSpace, 0, 4*256*sizeof(unsigned)); /* by stripes of 16 bytes */ { U32 cached = MEM_read32(ip); ip += 4; @@ -120,21 +117,18 @@ static size_t HIST_count_parallel_wksp( /* finish last symbols */ while (ipmaxSymbolValue; s--) { - Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; - if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall); - } } - { U32 s; - if (maxSymbolValue > 255) maxSymbolValue = 255; - for (s=0; s<=maxSymbolValue; s++) { - count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s]; - if (count[s] > max) max = count[s]; + for (s=0; s<256; s++) { + Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; + if (Counting1[s] > max) max = Counting1[s]; } } - while (!count[maxSymbolValue]) maxSymbolValue--; - *maxSymbolValuePtr = maxSymbolValue; + { unsigned maxSymbolValue = 255; + while (!Counting1[maxSymbolValue]) maxSymbolValue--; + if (check && maxSymbolValue > *maxSymbolValuePtr) return ERROR(maxSymbolValue_tooSmall); + *maxSymbolValuePtr = maxSymbolValue; + ZSTD_memmove(count, Counting1, countSize); /* in case count & Counting1 are overlapping */ + } return (size_t)max; } @@ -154,14 +148,6 @@ size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace); } -/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ -size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr, - const void* source, size_t sourceSize) -{ - unsigned tmpCounters[HIST_WKSP_SIZE_U32]; - return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters)); -} - /* HIST_count_wksp() : * Same as HIST_count(), but using an externally provided scratch buffer. * `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */ @@ -177,11 +163,19 @@ size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr, return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize); } +#ifndef ZSTD_NO_UNUSED_FUNCTIONS +/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ +size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr, + const void* source, size_t sourceSize) +{ + unsigned tmpCounters[HIST_WKSP_SIZE_U32]; + return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters)); +} + size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize) { unsigned tmpCounters[HIST_WKSP_SIZE_U32]; return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters, sizeof(tmpCounters)); } - -} +#endif diff --git a/third_party/zstd/compress/huf_compress.c b/third_party/zstd/compress/huf_compress.c new file mode 100644 index 00000000000..ea000723209 --- /dev/null +++ b/third_party/zstd/compress/huf_compress.c @@ -0,0 +1,1464 @@ +/* ****************************************************************** + * Huffman encoder, part of New Generation Entropy library + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * You can contact the author at : + * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy + * - Public forum : https://groups.google.com/forum/#!forum/lz4c + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. +****************************************************************** */ + +/* ************************************************************** +* Compiler specifics +****************************************************************/ +#ifdef _MSC_VER /* Visual Studio */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +#endif + + +/* ************************************************************** +* Includes +****************************************************************/ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */ +#include "../common/compiler.h" +#include "../common/bitstream.h" +#include "hist.h" +#define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */ +#include "../common/fse.h" /* header compression */ +#include "../common/huf.h" +#include "../common/error_private.h" +#include "../common/bits.h" /* ZSTD_highbit32 */ + + +/* ************************************************************** +* Error Management +****************************************************************/ +#define HUF_isError ERR_isError +#define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */ + + +/* ************************************************************** +* Required declarations +****************************************************************/ +typedef struct nodeElt_s { + U32 count; + U16 parent; + BYTE byte; + BYTE nbBits; +} nodeElt; + + +/* ************************************************************** +* Debug Traces +****************************************************************/ + +#if DEBUGLEVEL >= 2 + +static size_t showU32(const U32* arr, size_t size) +{ + size_t u; + for (u=0; u= add) { + assert(add < align); + assert(((size_t)aligned & mask) == 0); + *workspaceSizePtr -= add; + return aligned; + } else { + *workspaceSizePtr = 0; + return NULL; + } +} + + +/* HUF_compressWeights() : + * Same as FSE_compress(), but dedicated to huff0's weights compression. + * The use case needs much less stack memory. + * Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX. + */ +#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6 + +typedef struct { + FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)]; + U32 scratchBuffer[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(HUF_TABLELOG_MAX, MAX_FSE_TABLELOG_FOR_HUFF_HEADER)]; + unsigned count[HUF_TABLELOG_MAX+1]; + S16 norm[HUF_TABLELOG_MAX+1]; +} HUF_CompressWeightsWksp; + +static size_t +HUF_compressWeights(void* dst, size_t dstSize, + const void* weightTable, size_t wtSize, + void* workspace, size_t workspaceSize) +{ + BYTE* const ostart = (BYTE*) dst; + BYTE* op = ostart; + BYTE* const oend = ostart + dstSize; + + unsigned maxSymbolValue = HUF_TABLELOG_MAX; + U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER; + HUF_CompressWeightsWksp* wksp = (HUF_CompressWeightsWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32)); + + if (workspaceSize < sizeof(HUF_CompressWeightsWksp)) return ERROR(GENERIC); + + /* init conditions */ + if (wtSize <= 1) return 0; /* Not compressible */ + + /* Scan input and build symbol stats */ + { unsigned const maxCount = HIST_count_simple(wksp->count, &maxSymbolValue, weightTable, wtSize); /* never fails */ + if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */ + if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */ + } + + tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue); + CHECK_F( FSE_normalizeCount(wksp->norm, tableLog, wksp->count, wtSize, maxSymbolValue, /* useLowProbCount */ 0) ); + + /* Write table description header */ + { CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), wksp->norm, maxSymbolValue, tableLog) ); + op += hSize; + } + + /* Compress */ + CHECK_F( FSE_buildCTable_wksp(wksp->CTable, wksp->norm, maxSymbolValue, tableLog, wksp->scratchBuffer, sizeof(wksp->scratchBuffer)) ); + { CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, wksp->CTable) ); + if (cSize == 0) return 0; /* not enough space for compressed data */ + op += cSize; + } + + return (size_t)(op-ostart); +} + +static size_t HUF_getNbBits(HUF_CElt elt) +{ + return elt & 0xFF; +} + +static size_t HUF_getNbBitsFast(HUF_CElt elt) +{ + return elt; +} + +static size_t HUF_getValue(HUF_CElt elt) +{ + return elt & ~(size_t)0xFF; +} + +static size_t HUF_getValueFast(HUF_CElt elt) +{ + return elt; +} + +static void HUF_setNbBits(HUF_CElt* elt, size_t nbBits) +{ + assert(nbBits <= HUF_TABLELOG_ABSOLUTEMAX); + *elt = nbBits; +} + +static void HUF_setValue(HUF_CElt* elt, size_t value) +{ + size_t const nbBits = HUF_getNbBits(*elt); + if (nbBits > 0) { + assert((value >> nbBits) == 0); + *elt |= value << (sizeof(HUF_CElt) * 8 - nbBits); + } +} + +HUF_CTableHeader HUF_readCTableHeader(HUF_CElt const* ctable) +{ + HUF_CTableHeader header; + ZSTD_memcpy(&header, ctable, sizeof(header)); + return header; +} + +static void HUF_writeCTableHeader(HUF_CElt* ctable, U32 tableLog, U32 maxSymbolValue) +{ + HUF_CTableHeader header; + HUF_STATIC_ASSERT(sizeof(ctable[0]) == sizeof(header)); + ZSTD_memset(&header, 0, sizeof(header)); + assert(tableLog < 256); + header.tableLog = (BYTE)tableLog; + assert(maxSymbolValue < 256); + header.maxSymbolValue = (BYTE)maxSymbolValue; + ZSTD_memcpy(ctable, &header, sizeof(header)); +} + +typedef struct { + HUF_CompressWeightsWksp wksp; + BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */ + BYTE huffWeight[HUF_SYMBOLVALUE_MAX]; +} HUF_WriteCTableWksp; + +size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, + const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, + void* workspace, size_t workspaceSize) +{ + HUF_CElt const* const ct = CTable + 1; + BYTE* op = (BYTE*)dst; + U32 n; + HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32)); + + HUF_STATIC_ASSERT(HUF_CTABLE_WORKSPACE_SIZE >= sizeof(HUF_WriteCTableWksp)); + + assert(HUF_readCTableHeader(CTable).maxSymbolValue == maxSymbolValue); + assert(HUF_readCTableHeader(CTable).tableLog == huffLog); + + /* check conditions */ + if (workspaceSize < sizeof(HUF_WriteCTableWksp)) return ERROR(GENERIC); + if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge); + + /* convert to weight */ + wksp->bitsToWeight[0] = 0; + for (n=1; nbitsToWeight[n] = (BYTE)(huffLog + 1 - n); + for (n=0; nhuffWeight[n] = wksp->bitsToWeight[HUF_getNbBits(ct[n])]; + + /* attempt weights compression by FSE */ + if (maxDstSize < 1) return ERROR(dstSize_tooSmall); + { CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, wksp->huffWeight, maxSymbolValue, &wksp->wksp, sizeof(wksp->wksp)) ); + if ((hSize>1) & (hSize < maxSymbolValue/2)) { /* FSE compressed */ + op[0] = (BYTE)hSize; + return hSize+1; + } } + + /* write raw values as 4-bits (max : 15) */ + if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */ + if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */ + op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1)); + wksp->huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */ + for (n=0; nhuffWeight[n] << 4) + wksp->huffWeight[n+1]); + return ((maxSymbolValue+1)/2) + 1; +} + + +size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights) +{ + BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */ + U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */ + U32 tableLog = 0; + U32 nbSymbols = 0; + HUF_CElt* const ct = CTable + 1; + + /* get symbol weights */ + CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize)); + *hasZeroWeights = (rankVal[0] > 0); + + /* check result */ + if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); + if (nbSymbols > *maxSymbolValuePtr+1) return ERROR(maxSymbolValue_tooSmall); + + *maxSymbolValuePtr = nbSymbols - 1; + + HUF_writeCTableHeader(CTable, tableLog, *maxSymbolValuePtr); + + /* Prepare base value per rank */ + { U32 n, nextRankStart = 0; + for (n=1; n<=tableLog; n++) { + U32 curr = nextRankStart; + nextRankStart += (rankVal[n] << (n-1)); + rankVal[n] = curr; + } } + + /* fill nbBits */ + { U32 n; for (n=0; nn=tableLog+1 */ + U16 valPerRank[HUF_TABLELOG_MAX+2] = {0}; + { U32 n; for (n=0; n0; n--) { /* start at n=tablelog <-> w=1 */ + valPerRank[n] = min; /* get starting value within each rank */ + min += nbPerRank[n]; + min >>= 1; + } } + /* assign value within rank, symbol order */ + { U32 n; for (n=0; n HUF_readCTableHeader(CTable).maxSymbolValue) + return 0; + return (U32)HUF_getNbBits(ct[symbolValue]); +} + + +/** + * HUF_setMaxHeight(): + * Try to enforce @targetNbBits on the Huffman tree described in @huffNode. + * + * It attempts to convert all nodes with nbBits > @targetNbBits + * to employ @targetNbBits instead. Then it adjusts the tree + * so that it remains a valid canonical Huffman tree. + * + * @pre The sum of the ranks of each symbol == 2^largestBits, + * where largestBits == huffNode[lastNonNull].nbBits. + * @post The sum of the ranks of each symbol == 2^largestBits, + * where largestBits is the return value (expected <= targetNbBits). + * + * @param huffNode The Huffman tree modified in place to enforce targetNbBits. + * It's presumed sorted, from most frequent to rarest symbol. + * @param lastNonNull The symbol with the lowest count in the Huffman tree. + * @param targetNbBits The allowed number of bits, which the Huffman tree + * may not respect. After this function the Huffman tree will + * respect targetNbBits. + * @return The maximum number of bits of the Huffman tree after adjustment. + */ +static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 targetNbBits) +{ + const U32 largestBits = huffNode[lastNonNull].nbBits; + /* early exit : no elt > targetNbBits, so the tree is already valid. */ + if (largestBits <= targetNbBits) return largestBits; + + DEBUGLOG(5, "HUF_setMaxHeight (targetNbBits = %u)", targetNbBits); + + /* there are several too large elements (at least >= 2) */ + { int totalCost = 0; + const U32 baseCost = 1 << (largestBits - targetNbBits); + int n = (int)lastNonNull; + + /* Adjust any ranks > targetNbBits to targetNbBits. + * Compute totalCost, which is how far the sum of the ranks is + * we are over 2^largestBits after adjust the offending ranks. + */ + while (huffNode[n].nbBits > targetNbBits) { + totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)); + huffNode[n].nbBits = (BYTE)targetNbBits; + n--; + } + /* n stops at huffNode[n].nbBits <= targetNbBits */ + assert(huffNode[n].nbBits <= targetNbBits); + /* n end at index of smallest symbol using < targetNbBits */ + while (huffNode[n].nbBits == targetNbBits) --n; + + /* renorm totalCost from 2^largestBits to 2^targetNbBits + * note : totalCost is necessarily a multiple of baseCost */ + assert(((U32)totalCost & (baseCost - 1)) == 0); + totalCost >>= (largestBits - targetNbBits); + assert(totalCost > 0); + + /* repay normalized cost */ + { U32 const noSymbol = 0xF0F0F0F0; + U32 rankLast[HUF_TABLELOG_MAX+2]; + + /* Get pos of last (smallest = lowest cum. count) symbol per rank */ + ZSTD_memset(rankLast, 0xF0, sizeof(rankLast)); + { U32 currentNbBits = targetNbBits; + int pos; + for (pos=n ; pos >= 0; pos--) { + if (huffNode[pos].nbBits >= currentNbBits) continue; + currentNbBits = huffNode[pos].nbBits; /* < targetNbBits */ + rankLast[targetNbBits-currentNbBits] = (U32)pos; + } } + + while (totalCost > 0) { + /* Try to reduce the next power of 2 above totalCost because we + * gain back half the rank. + */ + U32 nBitsToDecrease = ZSTD_highbit32((U32)totalCost) + 1; + for ( ; nBitsToDecrease > 1; nBitsToDecrease--) { + U32 const highPos = rankLast[nBitsToDecrease]; + U32 const lowPos = rankLast[nBitsToDecrease-1]; + if (highPos == noSymbol) continue; + /* Decrease highPos if no symbols of lowPos or if it is + * not cheaper to remove 2 lowPos than highPos. + */ + if (lowPos == noSymbol) break; + { U32 const highTotal = huffNode[highPos].count; + U32 const lowTotal = 2 * huffNode[lowPos].count; + if (highTotal <= lowTotal) break; + } } + /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */ + assert(rankLast[nBitsToDecrease] != noSymbol || nBitsToDecrease == 1); + /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */ + while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol)) + nBitsToDecrease++; + assert(rankLast[nBitsToDecrease] != noSymbol); + /* Increase the number of bits to gain back half the rank cost. */ + totalCost -= 1 << (nBitsToDecrease-1); + huffNode[rankLast[nBitsToDecrease]].nbBits++; + + /* Fix up the new rank. + * If the new rank was empty, this symbol is now its smallest. + * Otherwise, this symbol will be the largest in the new rank so no adjustment. + */ + if (rankLast[nBitsToDecrease-1] == noSymbol) + rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; + /* Fix up the old rank. + * If the symbol was at position 0, meaning it was the highest weight symbol in the tree, + * it must be the only symbol in its rank, so the old rank now has no symbols. + * Otherwise, since the Huffman nodes are sorted by count, the previous position is now + * the smallest node in the rank. If the previous position belongs to a different rank, + * then the rank is now empty. + */ + if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */ + rankLast[nBitsToDecrease] = noSymbol; + else { + rankLast[nBitsToDecrease]--; + if (huffNode[rankLast[nBitsToDecrease]].nbBits != targetNbBits-nBitsToDecrease) + rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */ + } + } /* while (totalCost > 0) */ + + /* If we've removed too much weight, then we have to add it back. + * To avoid overshooting again, we only adjust the smallest rank. + * We take the largest nodes from the lowest rank 0 and move them + * to rank 1. There's guaranteed to be enough rank 0 symbols because + * TODO. + */ + while (totalCost < 0) { /* Sometimes, cost correction overshoot */ + /* special case : no rank 1 symbol (using targetNbBits-1); + * let's create one from largest rank 0 (using targetNbBits). + */ + if (rankLast[1] == noSymbol) { + while (huffNode[n].nbBits == targetNbBits) n--; + huffNode[n+1].nbBits--; + assert(n >= 0); + rankLast[1] = (U32)(n+1); + totalCost++; + continue; + } + huffNode[ rankLast[1] + 1 ].nbBits--; + rankLast[1]++; + totalCost ++; + } + } /* repay normalized cost */ + } /* there are several too large elements (at least >= 2) */ + + return targetNbBits; +} + +typedef struct { + U16 base; + U16 curr; +} rankPos; + +typedef nodeElt huffNodeTable[2 * (HUF_SYMBOLVALUE_MAX + 1)]; + +/* Number of buckets available for HUF_sort() */ +#define RANK_POSITION_TABLE_SIZE 192 + +typedef struct { + huffNodeTable huffNodeTbl; + rankPos rankPosition[RANK_POSITION_TABLE_SIZE]; +} HUF_buildCTable_wksp_tables; + +/* RANK_POSITION_DISTINCT_COUNT_CUTOFF == Cutoff point in HUF_sort() buckets for which we use log2 bucketing. + * Strategy is to use as many buckets as possible for representing distinct + * counts while using the remainder to represent all "large" counts. + * + * To satisfy this requirement for 192 buckets, we can do the following: + * Let buckets 0-166 represent distinct counts of [0, 166] + * Let buckets 166 to 192 represent all remaining counts up to RANK_POSITION_MAX_COUNT_LOG using log2 bucketing. + */ +#define RANK_POSITION_MAX_COUNT_LOG 32 +#define RANK_POSITION_LOG_BUCKETS_BEGIN ((RANK_POSITION_TABLE_SIZE - 1) - RANK_POSITION_MAX_COUNT_LOG - 1 /* == 158 */) +#define RANK_POSITION_DISTINCT_COUNT_CUTOFF (RANK_POSITION_LOG_BUCKETS_BEGIN + ZSTD_highbit32(RANK_POSITION_LOG_BUCKETS_BEGIN) /* == 166 */) + +/* Return the appropriate bucket index for a given count. See definition of + * RANK_POSITION_DISTINCT_COUNT_CUTOFF for explanation of bucketing strategy. + */ +static U32 HUF_getIndex(U32 const count) { + return (count < RANK_POSITION_DISTINCT_COUNT_CUTOFF) + ? count + : ZSTD_highbit32(count) + RANK_POSITION_LOG_BUCKETS_BEGIN; +} + +/* Helper swap function for HUF_quickSortPartition() */ +static void HUF_swapNodes(nodeElt* a, nodeElt* b) { + nodeElt tmp = *a; + *a = *b; + *b = tmp; +} + +/* Returns 0 if the huffNode array is not sorted by descending count */ +MEM_STATIC int HUF_isSorted(nodeElt huffNode[], U32 const maxSymbolValue1) { + U32 i; + for (i = 1; i < maxSymbolValue1; ++i) { + if (huffNode[i].count > huffNode[i-1].count) { + return 0; + } + } + return 1; +} + +/* Insertion sort by descending order */ +HINT_INLINE void HUF_insertionSort(nodeElt huffNode[], int const low, int const high) { + int i; + int const size = high-low+1; + huffNode += low; + for (i = 1; i < size; ++i) { + nodeElt const key = huffNode[i]; + int j = i - 1; + while (j >= 0 && huffNode[j].count < key.count) { + huffNode[j + 1] = huffNode[j]; + j--; + } + huffNode[j + 1] = key; + } +} + +/* Pivot helper function for quicksort. */ +static int HUF_quickSortPartition(nodeElt arr[], int const low, int const high) { + /* Simply select rightmost element as pivot. "Better" selectors like + * median-of-three don't experimentally appear to have any benefit. + */ + U32 const pivot = arr[high].count; + int i = low - 1; + int j = low; + for ( ; j < high; j++) { + if (arr[j].count > pivot) { + i++; + HUF_swapNodes(&arr[i], &arr[j]); + } + } + HUF_swapNodes(&arr[i + 1], &arr[high]); + return i + 1; +} + +/* Classic quicksort by descending with partially iterative calls + * to reduce worst case callstack size. + */ +static void HUF_simpleQuickSort(nodeElt arr[], int low, int high) { + int const kInsertionSortThreshold = 8; + if (high - low < kInsertionSortThreshold) { + HUF_insertionSort(arr, low, high); + return; + } + while (low < high) { + int const idx = HUF_quickSortPartition(arr, low, high); + if (idx - low < high - idx) { + HUF_simpleQuickSort(arr, low, idx - 1); + low = idx + 1; + } else { + HUF_simpleQuickSort(arr, idx + 1, high); + high = idx - 1; + } + } +} + +/** + * HUF_sort(): + * Sorts the symbols [0, maxSymbolValue] by count[symbol] in decreasing order. + * This is a typical bucket sorting strategy that uses either quicksort or insertion sort to sort each bucket. + * + * @param[out] huffNode Sorted symbols by decreasing count. Only members `.count` and `.byte` are filled. + * Must have (maxSymbolValue + 1) entries. + * @param[in] count Histogram of the symbols. + * @param[in] maxSymbolValue Maximum symbol value. + * @param rankPosition This is a scratch workspace. Must have RANK_POSITION_TABLE_SIZE entries. + */ +static void HUF_sort(nodeElt huffNode[], const unsigned count[], U32 const maxSymbolValue, rankPos rankPosition[]) { + U32 n; + U32 const maxSymbolValue1 = maxSymbolValue+1; + + /* Compute base and set curr to base. + * For symbol s let lowerRank = HUF_getIndex(count[n]) and rank = lowerRank + 1. + * See HUF_getIndex to see bucketing strategy. + * We attribute each symbol to lowerRank's base value, because we want to know where + * each rank begins in the output, so for rank R we want to count ranks R+1 and above. + */ + ZSTD_memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE); + for (n = 0; n < maxSymbolValue1; ++n) { + U32 lowerRank = HUF_getIndex(count[n]); + assert(lowerRank < RANK_POSITION_TABLE_SIZE - 1); + rankPosition[lowerRank].base++; + } + + assert(rankPosition[RANK_POSITION_TABLE_SIZE - 1].base == 0); + /* Set up the rankPosition table */ + for (n = RANK_POSITION_TABLE_SIZE - 1; n > 0; --n) { + rankPosition[n-1].base += rankPosition[n].base; + rankPosition[n-1].curr = rankPosition[n-1].base; + } + + /* Insert each symbol into their appropriate bucket, setting up rankPosition table. */ + for (n = 0; n < maxSymbolValue1; ++n) { + U32 const c = count[n]; + U32 const r = HUF_getIndex(c) + 1; + U32 const pos = rankPosition[r].curr++; + assert(pos < maxSymbolValue1); + huffNode[pos].count = c; + huffNode[pos].byte = (BYTE)n; + } + + /* Sort each bucket. */ + for (n = RANK_POSITION_DISTINCT_COUNT_CUTOFF; n < RANK_POSITION_TABLE_SIZE - 1; ++n) { + int const bucketSize = rankPosition[n].curr - rankPosition[n].base; + U32 const bucketStartIdx = rankPosition[n].base; + if (bucketSize > 1) { + assert(bucketStartIdx < maxSymbolValue1); + HUF_simpleQuickSort(huffNode + bucketStartIdx, 0, bucketSize-1); + } + } + + assert(HUF_isSorted(huffNode, maxSymbolValue1)); +} + + +/** HUF_buildCTable_wksp() : + * Same as HUF_buildCTable(), but using externally allocated scratch buffer. + * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as sizeof(HUF_buildCTable_wksp_tables). + */ +#define STARTNODE (HUF_SYMBOLVALUE_MAX+1) + +/* HUF_buildTree(): + * Takes the huffNode array sorted by HUF_sort() and builds an unlimited-depth Huffman tree. + * + * @param huffNode The array sorted by HUF_sort(). Builds the Huffman tree in this array. + * @param maxSymbolValue The maximum symbol value. + * @return The smallest node in the Huffman tree (by count). + */ +static int HUF_buildTree(nodeElt* huffNode, U32 maxSymbolValue) +{ + nodeElt* const huffNode0 = huffNode - 1; + int nonNullRank; + int lowS, lowN; + int nodeNb = STARTNODE; + int n, nodeRoot; + DEBUGLOG(5, "HUF_buildTree (alphabet size = %u)", maxSymbolValue + 1); + /* init for parents */ + nonNullRank = (int)maxSymbolValue; + while(huffNode[nonNullRank].count == 0) nonNullRank--; + lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb; + huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count; + huffNode[lowS].parent = huffNode[lowS-1].parent = (U16)nodeNb; + nodeNb++; lowS-=2; + for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30); + huffNode0[0].count = (U32)(1U<<31); /* fake entry, strong barrier */ + + /* create parents */ + while (nodeNb <= nodeRoot) { + int const n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; + int const n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; + huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count; + huffNode[n1].parent = huffNode[n2].parent = (U16)nodeNb; + nodeNb++; + } + + /* distribute weights (unlimited tree height) */ + huffNode[nodeRoot].nbBits = 0; + for (n=nodeRoot-1; n>=STARTNODE; n--) + huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; + for (n=0; n<=nonNullRank; n++) + huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; + + DEBUGLOG(6, "Initial distribution of bits completed (%zu sorted symbols)", showHNodeBits(huffNode, maxSymbolValue+1)); + + return nonNullRank; +} + +/** + * HUF_buildCTableFromTree(): + * Build the CTable given the Huffman tree in huffNode. + * + * @param[out] CTable The output Huffman CTable. + * @param huffNode The Huffman tree. + * @param nonNullRank The last and smallest node in the Huffman tree. + * @param maxSymbolValue The maximum symbol value. + * @param maxNbBits The exact maximum number of bits used in the Huffman tree. + */ +static void HUF_buildCTableFromTree(HUF_CElt* CTable, nodeElt const* huffNode, int nonNullRank, U32 maxSymbolValue, U32 maxNbBits) +{ + HUF_CElt* const ct = CTable + 1; + /* fill result into ctable (val, nbBits) */ + int n; + U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0}; + U16 valPerRank[HUF_TABLELOG_MAX+1] = {0}; + int const alphabetSize = (int)(maxSymbolValue + 1); + for (n=0; n<=nonNullRank; n++) + nbPerRank[huffNode[n].nbBits]++; + /* determine starting value per rank */ + { U16 min = 0; + for (n=(int)maxNbBits; n>0; n--) { + valPerRank[n] = min; /* get starting value within each rank */ + min += nbPerRank[n]; + min >>= 1; + } } + for (n=0; nhuffNodeTbl; + nodeElt* const huffNode = huffNode0+1; + int nonNullRank; + + HUF_STATIC_ASSERT(HUF_CTABLE_WORKSPACE_SIZE == sizeof(HUF_buildCTable_wksp_tables)); + + DEBUGLOG(5, "HUF_buildCTable_wksp (alphabet size = %u)", maxSymbolValue+1); + + /* safety checks */ + if (wkspSize < sizeof(HUF_buildCTable_wksp_tables)) + return ERROR(workSpace_tooSmall); + if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; + if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) + return ERROR(maxSymbolValue_tooLarge); + ZSTD_memset(huffNode0, 0, sizeof(huffNodeTable)); + + /* sort, decreasing order */ + HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition); + DEBUGLOG(6, "sorted symbols completed (%zu symbols)", showHNodeSymbols(huffNode, maxSymbolValue+1)); + + /* build tree */ + nonNullRank = HUF_buildTree(huffNode, maxSymbolValue); + + /* determine and enforce maxTableLog */ + maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits); + if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */ + + HUF_buildCTableFromTree(CTable, huffNode, nonNullRank, maxSymbolValue, maxNbBits); + + return maxNbBits; +} + +size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) +{ + HUF_CElt const* ct = CTable + 1; + size_t nbBits = 0; + int s; + for (s = 0; s <= (int)maxSymbolValue; ++s) { + nbBits += HUF_getNbBits(ct[s]) * count[s]; + } + return nbBits >> 3; +} + +int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) { + HUF_CTableHeader header = HUF_readCTableHeader(CTable); + HUF_CElt const* ct = CTable + 1; + int bad = 0; + int s; + + assert(header.tableLog <= HUF_TABLELOG_ABSOLUTEMAX); + + if (header.maxSymbolValue < maxSymbolValue) + return 0; + + for (s = 0; s <= (int)maxSymbolValue; ++s) { + bad |= (count[s] != 0) & (HUF_getNbBits(ct[s]) == 0); + } + return !bad; +} + +size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); } + +/** HUF_CStream_t: + * Huffman uses its own BIT_CStream_t implementation. + * There are three major differences from BIT_CStream_t: + * 1. HUF_addBits() takes a HUF_CElt (size_t) which is + * the pair (nbBits, value) in the format: + * format: + * - Bits [0, 4) = nbBits + * - Bits [4, 64 - nbBits) = 0 + * - Bits [64 - nbBits, 64) = value + * 2. The bitContainer is built from the upper bits and + * right shifted. E.g. to add a new value of N bits + * you right shift the bitContainer by N, then or in + * the new value into the N upper bits. + * 3. The bitstream has two bit containers. You can add + * bits to the second container and merge them into + * the first container. + */ + +#define HUF_BITS_IN_CONTAINER (sizeof(size_t) * 8) + +typedef struct { + size_t bitContainer[2]; + size_t bitPos[2]; + + BYTE* startPtr; + BYTE* ptr; + BYTE* endPtr; +} HUF_CStream_t; + +/**! HUF_initCStream(): + * Initializes the bitstream. + * @returns 0 or an error code. + */ +static size_t HUF_initCStream(HUF_CStream_t* bitC, + void* startPtr, size_t dstCapacity) +{ + ZSTD_memset(bitC, 0, sizeof(*bitC)); + bitC->startPtr = (BYTE*)startPtr; + bitC->ptr = bitC->startPtr; + bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer[0]); + if (dstCapacity <= sizeof(bitC->bitContainer[0])) return ERROR(dstSize_tooSmall); + return 0; +} + +/*! HUF_addBits(): + * Adds the symbol stored in HUF_CElt elt to the bitstream. + * + * @param elt The element we're adding. This is a (nbBits, value) pair. + * See the HUF_CStream_t docs for the format. + * @param idx Insert into the bitstream at this idx. + * @param kFast This is a template parameter. If the bitstream is guaranteed + * to have at least 4 unused bits after this call it may be 1, + * otherwise it must be 0. HUF_addBits() is faster when fast is set. + */ +FORCE_INLINE_TEMPLATE void HUF_addBits(HUF_CStream_t* bitC, HUF_CElt elt, int idx, int kFast) +{ + assert(idx <= 1); + assert(HUF_getNbBits(elt) <= HUF_TABLELOG_ABSOLUTEMAX); + /* This is efficient on x86-64 with BMI2 because shrx + * only reads the low 6 bits of the register. The compiler + * knows this and elides the mask. When fast is set, + * every operation can use the same value loaded from elt. + */ + bitC->bitContainer[idx] >>= HUF_getNbBits(elt); + bitC->bitContainer[idx] |= kFast ? HUF_getValueFast(elt) : HUF_getValue(elt); + /* We only read the low 8 bits of bitC->bitPos[idx] so it + * doesn't matter that the high bits have noise from the value. + */ + bitC->bitPos[idx] += HUF_getNbBitsFast(elt); + assert((bitC->bitPos[idx] & 0xFF) <= HUF_BITS_IN_CONTAINER); + /* The last 4-bits of elt are dirty if fast is set, + * so we must not be overwriting bits that have already been + * inserted into the bit container. + */ +#if DEBUGLEVEL >= 1 + { + size_t const nbBits = HUF_getNbBits(elt); + size_t const dirtyBits = nbBits == 0 ? 0 : ZSTD_highbit32((U32)nbBits) + 1; + (void)dirtyBits; + /* Middle bits are 0. */ + assert(((elt >> dirtyBits) << (dirtyBits + nbBits)) == 0); + /* We didn't overwrite any bits in the bit container. */ + assert(!kFast || (bitC->bitPos[idx] & 0xFF) <= HUF_BITS_IN_CONTAINER); + (void)dirtyBits; + } +#endif +} + +FORCE_INLINE_TEMPLATE void HUF_zeroIndex1(HUF_CStream_t* bitC) +{ + bitC->bitContainer[1] = 0; + bitC->bitPos[1] = 0; +} + +/*! HUF_mergeIndex1() : + * Merges the bit container @ index 1 into the bit container @ index 0 + * and zeros the bit container @ index 1. + */ +FORCE_INLINE_TEMPLATE void HUF_mergeIndex1(HUF_CStream_t* bitC) +{ + assert((bitC->bitPos[1] & 0xFF) < HUF_BITS_IN_CONTAINER); + bitC->bitContainer[0] >>= (bitC->bitPos[1] & 0xFF); + bitC->bitContainer[0] |= bitC->bitContainer[1]; + bitC->bitPos[0] += bitC->bitPos[1]; + assert((bitC->bitPos[0] & 0xFF) <= HUF_BITS_IN_CONTAINER); +} + +/*! HUF_flushBits() : +* Flushes the bits in the bit container @ index 0. +* +* @post bitPos will be < 8. +* @param kFast If kFast is set then we must know a-priori that +* the bit container will not overflow. +*/ +FORCE_INLINE_TEMPLATE void HUF_flushBits(HUF_CStream_t* bitC, int kFast) +{ + /* The upper bits of bitPos are noisy, so we must mask by 0xFF. */ + size_t const nbBits = bitC->bitPos[0] & 0xFF; + size_t const nbBytes = nbBits >> 3; + /* The top nbBits bits of bitContainer are the ones we need. */ + size_t const bitContainer = bitC->bitContainer[0] >> (HUF_BITS_IN_CONTAINER - nbBits); + /* Mask bitPos to account for the bytes we consumed. */ + bitC->bitPos[0] &= 7; + assert(nbBits > 0); + assert(nbBits <= sizeof(bitC->bitContainer[0]) * 8); + assert(bitC->ptr <= bitC->endPtr); + MEM_writeLEST(bitC->ptr, bitContainer); + bitC->ptr += nbBytes; + assert(!kFast || bitC->ptr <= bitC->endPtr); + if (!kFast && bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr; + /* bitContainer doesn't need to be modified because the leftover + * bits are already the top bitPos bits. And we don't care about + * noise in the lower values. + */ +} + +/*! HUF_endMark() + * @returns The Huffman stream end mark: A 1-bit value = 1. + */ +static HUF_CElt HUF_endMark(void) +{ + HUF_CElt endMark; + HUF_setNbBits(&endMark, 1); + HUF_setValue(&endMark, 1); + return endMark; +} + +/*! HUF_closeCStream() : + * @return Size of CStream, in bytes, + * or 0 if it could not fit into dstBuffer */ +static size_t HUF_closeCStream(HUF_CStream_t* bitC) +{ + HUF_addBits(bitC, HUF_endMark(), /* idx */ 0, /* kFast */ 0); + HUF_flushBits(bitC, /* kFast */ 0); + { + size_t const nbBits = bitC->bitPos[0] & 0xFF; + if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */ + return (size_t)(bitC->ptr - bitC->startPtr) + (nbBits > 0); + } +} + +FORCE_INLINE_TEMPLATE void +HUF_encodeSymbol(HUF_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable, int idx, int fast) +{ + HUF_addBits(bitCPtr, CTable[symbol], idx, fast); +} + +FORCE_INLINE_TEMPLATE void +HUF_compress1X_usingCTable_internal_body_loop(HUF_CStream_t* bitC, + const BYTE* ip, size_t srcSize, + const HUF_CElt* ct, + int kUnroll, int kFastFlush, int kLastFast) +{ + /* Join to kUnroll */ + int n = (int)srcSize; + int rem = n % kUnroll; + if (rem > 0) { + for (; rem > 0; --rem) { + HUF_encodeSymbol(bitC, ip[--n], ct, 0, /* fast */ 0); + } + HUF_flushBits(bitC, kFastFlush); + } + assert(n % kUnroll == 0); + + /* Join to 2 * kUnroll */ + if (n % (2 * kUnroll)) { + int u; + for (u = 1; u < kUnroll; ++u) { + HUF_encodeSymbol(bitC, ip[n - u], ct, 0, 1); + } + HUF_encodeSymbol(bitC, ip[n - kUnroll], ct, 0, kLastFast); + HUF_flushBits(bitC, kFastFlush); + n -= kUnroll; + } + assert(n % (2 * kUnroll) == 0); + + for (; n>0; n-= 2 * kUnroll) { + /* Encode kUnroll symbols into the bitstream @ index 0. */ + int u; + for (u = 1; u < kUnroll; ++u) { + HUF_encodeSymbol(bitC, ip[n - u], ct, /* idx */ 0, /* fast */ 1); + } + HUF_encodeSymbol(bitC, ip[n - kUnroll], ct, /* idx */ 0, /* fast */ kLastFast); + HUF_flushBits(bitC, kFastFlush); + /* Encode kUnroll symbols into the bitstream @ index 1. + * This allows us to start filling the bit container + * without any data dependencies. + */ + HUF_zeroIndex1(bitC); + for (u = 1; u < kUnroll; ++u) { + HUF_encodeSymbol(bitC, ip[n - kUnroll - u], ct, /* idx */ 1, /* fast */ 1); + } + HUF_encodeSymbol(bitC, ip[n - kUnroll - kUnroll], ct, /* idx */ 1, /* fast */ kLastFast); + /* Merge bitstream @ index 1 into the bitstream @ index 0 */ + HUF_mergeIndex1(bitC); + HUF_flushBits(bitC, kFastFlush); + } + assert(n == 0); + +} + +/** + * Returns a tight upper bound on the output space needed by Huffman + * with 8 bytes buffer to handle over-writes. If the output is at least + * this large we don't need to do bounds checks during Huffman encoding. + */ +static size_t HUF_tightCompressBound(size_t srcSize, size_t tableLog) +{ + return ((srcSize * tableLog) >> 3) + 8; +} + + +FORCE_INLINE_TEMPLATE size_t +HUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize, + const void* src, size_t srcSize, + const HUF_CElt* CTable) +{ + U32 const tableLog = HUF_readCTableHeader(CTable).tableLog; + HUF_CElt const* ct = CTable + 1; + const BYTE* ip = (const BYTE*) src; + BYTE* const ostart = (BYTE*)dst; + BYTE* const oend = ostart + dstSize; + HUF_CStream_t bitC; + + /* init */ + if (dstSize < 8) return 0; /* not enough space to compress */ + { BYTE* op = ostart; + size_t const initErr = HUF_initCStream(&bitC, op, (size_t)(oend-op)); + if (HUF_isError(initErr)) return 0; } + + if (dstSize < HUF_tightCompressBound(srcSize, (size_t)tableLog) || tableLog > 11) + HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ MEM_32bits() ? 2 : 4, /* kFast */ 0, /* kLastFast */ 0); + else { + if (MEM_32bits()) { + switch (tableLog) { + case 11: + HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 2, /* kFastFlush */ 1, /* kLastFast */ 0); + break; + case 10: ZSTD_FALLTHROUGH; + case 9: ZSTD_FALLTHROUGH; + case 8: + HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 2, /* kFastFlush */ 1, /* kLastFast */ 1); + break; + case 7: ZSTD_FALLTHROUGH; + default: + HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 3, /* kFastFlush */ 1, /* kLastFast */ 1); + break; + } + } else { + switch (tableLog) { + case 11: + HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 5, /* kFastFlush */ 1, /* kLastFast */ 0); + break; + case 10: + HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 5, /* kFastFlush */ 1, /* kLastFast */ 1); + break; + case 9: + HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 6, /* kFastFlush */ 1, /* kLastFast */ 0); + break; + case 8: + HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 7, /* kFastFlush */ 1, /* kLastFast */ 0); + break; + case 7: + HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 8, /* kFastFlush */ 1, /* kLastFast */ 0); + break; + case 6: ZSTD_FALLTHROUGH; + default: + HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 9, /* kFastFlush */ 1, /* kLastFast */ 1); + break; + } + } + } + assert(bitC.ptr <= bitC.endPtr); + + return HUF_closeCStream(&bitC); +} + +#if DYNAMIC_BMI2 + +static BMI2_TARGET_ATTRIBUTE size_t +HUF_compress1X_usingCTable_internal_bmi2(void* dst, size_t dstSize, + const void* src, size_t srcSize, + const HUF_CElt* CTable) +{ + return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable); +} + +static size_t +HUF_compress1X_usingCTable_internal_default(void* dst, size_t dstSize, + const void* src, size_t srcSize, + const HUF_CElt* CTable) +{ + return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable); +} + +static size_t +HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize, + const void* src, size_t srcSize, + const HUF_CElt* CTable, const int flags) +{ + if (flags & HUF_flags_bmi2) { + return HUF_compress1X_usingCTable_internal_bmi2(dst, dstSize, src, srcSize, CTable); + } + return HUF_compress1X_usingCTable_internal_default(dst, dstSize, src, srcSize, CTable); +} + +#else + +static size_t +HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize, + const void* src, size_t srcSize, + const HUF_CElt* CTable, const int flags) +{ + (void)flags; + return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable); +} + +#endif + +size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags) +{ + return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, flags); +} + +static size_t +HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize, + const void* src, size_t srcSize, + const HUF_CElt* CTable, int flags) +{ + size_t const segmentSize = (srcSize+3)/4; /* first 3 segments */ + const BYTE* ip = (const BYTE*) src; + const BYTE* const iend = ip + srcSize; + BYTE* const ostart = (BYTE*) dst; + BYTE* const oend = ostart + dstSize; + BYTE* op = ostart; + + if (dstSize < 6 + 1 + 1 + 1 + 8) return 0; /* minimum space to compress successfully */ + if (srcSize < 12) return 0; /* no saving possible : too small input */ + op += 6; /* jumpTable */ + + assert(op <= oend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) ); + if (cSize == 0 || cSize > 65535) return 0; + MEM_writeLE16(ostart, (U16)cSize); + op += cSize; + } + + ip += segmentSize; + assert(op <= oend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) ); + if (cSize == 0 || cSize > 65535) return 0; + MEM_writeLE16(ostart+2, (U16)cSize); + op += cSize; + } + + ip += segmentSize; + assert(op <= oend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) ); + if (cSize == 0 || cSize > 65535) return 0; + MEM_writeLE16(ostart+4, (U16)cSize); + op += cSize; + } + + ip += segmentSize; + assert(op <= oend); + assert(ip <= iend); + { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, flags) ); + if (cSize == 0 || cSize > 65535) return 0; + op += cSize; + } + + return (size_t)(op-ostart); +} + +size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags) +{ + return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, flags); +} + +typedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e; + +static size_t HUF_compressCTable_internal( + BYTE* const ostart, BYTE* op, BYTE* const oend, + const void* src, size_t srcSize, + HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int flags) +{ + size_t const cSize = (nbStreams==HUF_singleStream) ? + HUF_compress1X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, flags) : + HUF_compress4X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, flags); + if (HUF_isError(cSize)) { return cSize; } + if (cSize==0) { return 0; } /* uncompressible */ + op += cSize; + /* check compressibility */ + assert(op >= ostart); + if ((size_t)(op-ostart) >= srcSize-1) { return 0; } + return (size_t)(op-ostart); +} + +typedef struct { + unsigned count[HUF_SYMBOLVALUE_MAX + 1]; + HUF_CElt CTable[HUF_CTABLE_SIZE_ST(HUF_SYMBOLVALUE_MAX)]; + union { + HUF_buildCTable_wksp_tables buildCTable_wksp; + HUF_WriteCTableWksp writeCTable_wksp; + U32 hist_wksp[HIST_WKSP_SIZE_U32]; + } wksps; +} HUF_compress_tables_t; + +#define SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE 4096 +#define SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO 10 /* Must be >= 2 */ + +unsigned HUF_cardinality(const unsigned* count, unsigned maxSymbolValue) +{ + unsigned cardinality = 0; + unsigned i; + + for (i = 0; i < maxSymbolValue + 1; i++) { + if (count[i] != 0) cardinality += 1; + } + + return cardinality; +} + +unsigned HUF_minTableLog(unsigned symbolCardinality) +{ + U32 minBitsSymbols = ZSTD_highbit32(symbolCardinality) + 1; + return minBitsSymbols; +} + +unsigned HUF_optimalTableLog( + unsigned maxTableLog, + size_t srcSize, + unsigned maxSymbolValue, + void* workSpace, size_t wkspSize, + HUF_CElt* table, + const unsigned* count, + int flags) +{ + assert(srcSize > 1); /* Not supported, RLE should be used instead */ + assert(wkspSize >= sizeof(HUF_buildCTable_wksp_tables)); + + if (!(flags & HUF_flags_optimalDepth)) { + /* cheap evaluation, based on FSE */ + return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1); + } + + { BYTE* dst = (BYTE*)workSpace + sizeof(HUF_WriteCTableWksp); + size_t dstSize = wkspSize - sizeof(HUF_WriteCTableWksp); + size_t hSize, newSize; + const unsigned symbolCardinality = HUF_cardinality(count, maxSymbolValue); + const unsigned minTableLog = HUF_minTableLog(symbolCardinality); + size_t optSize = ((size_t) ~0) - 1; + unsigned optLog = maxTableLog, optLogGuess; + + DEBUGLOG(6, "HUF_optimalTableLog: probing huf depth (srcSize=%zu)", srcSize); + + /* Search until size increases */ + for (optLogGuess = minTableLog; optLogGuess <= maxTableLog; optLogGuess++) { + DEBUGLOG(7, "checking for huffLog=%u", optLogGuess); + + { size_t maxBits = HUF_buildCTable_wksp(table, count, maxSymbolValue, optLogGuess, workSpace, wkspSize); + if (ERR_isError(maxBits)) continue; + + if (maxBits < optLogGuess && optLogGuess > minTableLog) break; + + hSize = HUF_writeCTable_wksp(dst, dstSize, table, maxSymbolValue, (U32)maxBits, workSpace, wkspSize); + } + + if (ERR_isError(hSize)) continue; + + newSize = HUF_estimateCompressedSize(table, count, maxSymbolValue) + hSize; + + if (newSize > optSize + 1) { + break; + } + + if (newSize < optSize) { + optSize = newSize; + optLog = optLogGuess; + } + } + assert(optLog <= HUF_TABLELOG_MAX); + return optLog; + } +} + +/* HUF_compress_internal() : + * `workSpace_align4` must be aligned on 4-bytes boundaries, + * and occupies the same space as a table of HUF_WORKSPACE_SIZE_U64 unsigned */ +static size_t +HUF_compress_internal (void* dst, size_t dstSize, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned huffLog, + HUF_nbStreams_e nbStreams, + void* workSpace, size_t wkspSize, + HUF_CElt* oldHufTable, HUF_repeat* repeat, int flags) +{ + HUF_compress_tables_t* const table = (HUF_compress_tables_t*)HUF_alignUpWorkspace(workSpace, &wkspSize, ZSTD_ALIGNOF(size_t)); + BYTE* const ostart = (BYTE*)dst; + BYTE* const oend = ostart + dstSize; + BYTE* op = ostart; + + DEBUGLOG(5, "HUF_compress_internal (srcSize=%zu)", srcSize); + HUF_STATIC_ASSERT(sizeof(*table) + HUF_WORKSPACE_MAX_ALIGNMENT <= HUF_WORKSPACE_SIZE); + + /* checks & inits */ + if (wkspSize < sizeof(*table)) return ERROR(workSpace_tooSmall); + if (!srcSize) return 0; /* Uncompressed */ + if (!dstSize) return 0; /* cannot fit anything within dst budget */ + if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */ + if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); + if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge); + if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX; + if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT; + + /* Heuristic : If old table is valid, use it for small inputs */ + if ((flags & HUF_flags_preferRepeat) && repeat && *repeat == HUF_repeat_valid) { + return HUF_compressCTable_internal(ostart, op, oend, + src, srcSize, + nbStreams, oldHufTable, flags); + } + + /* If uncompressible data is suspected, do a smaller sampling first */ + DEBUG_STATIC_ASSERT(SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO >= 2); + if ((flags & HUF_flags_suspectUncompressible) && srcSize >= (SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE * SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO)) { + size_t largestTotal = 0; + DEBUGLOG(5, "input suspected incompressible : sampling to check"); + { unsigned maxSymbolValueBegin = maxSymbolValue; + CHECK_V_F(largestBegin, HIST_count_simple (table->count, &maxSymbolValueBegin, (const BYTE*)src, SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) ); + largestTotal += largestBegin; + } + { unsigned maxSymbolValueEnd = maxSymbolValue; + CHECK_V_F(largestEnd, HIST_count_simple (table->count, &maxSymbolValueEnd, (const BYTE*)src + srcSize - SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE, SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) ); + largestTotal += largestEnd; + } + if (largestTotal <= ((2 * SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) >> 7)+4) return 0; /* heuristic : probably not compressible enough */ + } + + /* Scan input and build symbol stats */ + { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, table->wksps.hist_wksp, sizeof(table->wksps.hist_wksp)) ); + if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */ + if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */ + } + DEBUGLOG(6, "histogram detail completed (%zu symbols)", showU32(table->count, maxSymbolValue+1)); + + /* Check validity of previous table */ + if ( repeat + && *repeat == HUF_repeat_check + && !HUF_validateCTable(oldHufTable, table->count, maxSymbolValue)) { + *repeat = HUF_repeat_none; + } + /* Heuristic : use existing table for small inputs */ + if ((flags & HUF_flags_preferRepeat) && repeat && *repeat != HUF_repeat_none) { + return HUF_compressCTable_internal(ostart, op, oend, + src, srcSize, + nbStreams, oldHufTable, flags); + } + + /* Build Huffman Tree */ + huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue, &table->wksps, sizeof(table->wksps), table->CTable, table->count, flags); + { size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count, + maxSymbolValue, huffLog, + &table->wksps.buildCTable_wksp, sizeof(table->wksps.buildCTable_wksp)); + CHECK_F(maxBits); + huffLog = (U32)maxBits; + DEBUGLOG(6, "bit distribution completed (%zu symbols)", showCTableBits(table->CTable + 1, maxSymbolValue+1)); + } + + /* Write table description header */ + { CHECK_V_F(hSize, HUF_writeCTable_wksp(op, dstSize, table->CTable, maxSymbolValue, huffLog, + &table->wksps.writeCTable_wksp, sizeof(table->wksps.writeCTable_wksp)) ); + /* Check if using previous huffman table is beneficial */ + if (repeat && *repeat != HUF_repeat_none) { + size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue); + size_t const newSize = HUF_estimateCompressedSize(table->CTable, table->count, maxSymbolValue); + if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) { + return HUF_compressCTable_internal(ostart, op, oend, + src, srcSize, + nbStreams, oldHufTable, flags); + } } + + /* Use the new huffman table */ + if (hSize + 12ul >= srcSize) { return 0; } + op += hSize; + if (repeat) { *repeat = HUF_repeat_none; } + if (oldHufTable) + ZSTD_memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */ + } + return HUF_compressCTable_internal(ostart, op, oend, + src, srcSize, + nbStreams, table->CTable, flags); +} + +size_t HUF_compress1X_repeat (void* dst, size_t dstSize, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned huffLog, + void* workSpace, size_t wkspSize, + HUF_CElt* hufTable, HUF_repeat* repeat, int flags) +{ + DEBUGLOG(5, "HUF_compress1X_repeat (srcSize = %zu)", srcSize); + return HUF_compress_internal(dst, dstSize, src, srcSize, + maxSymbolValue, huffLog, HUF_singleStream, + workSpace, wkspSize, hufTable, + repeat, flags); +} + +/* HUF_compress4X_repeat(): + * compress input using 4 streams. + * consider skipping quickly + * reuse an existing huffman compression table */ +size_t HUF_compress4X_repeat (void* dst, size_t dstSize, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned huffLog, + void* workSpace, size_t wkspSize, + HUF_CElt* hufTable, HUF_repeat* repeat, int flags) +{ + DEBUGLOG(5, "HUF_compress4X_repeat (srcSize = %zu)", srcSize); + return HUF_compress_internal(dst, dstSize, src, srcSize, + maxSymbolValue, huffLog, HUF_fourStreams, + workSpace, wkspSize, + hufTable, repeat, flags); +} diff --git a/third_party/zstd/compress/huf_compress.cpp b/third_party/zstd/compress/huf_compress.cpp deleted file mode 100644 index a7fa092e443..00000000000 --- a/third_party/zstd/compress/huf_compress.cpp +++ /dev/null @@ -1,801 +0,0 @@ -/* ****************************************************************** - * Huffman encoder, part of New Generation Entropy library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. - * - * You can contact the author at : - * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy - * - Public forum : https://groups.google.com/forum/#!forum/lz4c - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. -****************************************************************** */ - -/* ************************************************************** -* Compiler specifics -****************************************************************/ -#ifdef _MSC_VER /* Visual Studio */ -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#endif - - -/* ************************************************************** -* Includes -****************************************************************/ -#include /* memcpy, memset */ -#include /* printf (debug) */ -#include "zstd/common/compiler.h" -#include "zstd/common/bitstream.h" -#include "zstd/compress/hist.h" -#include "zstd/common/fse.h" /* header compression */ -#include "zstd/common/fse_static.h" -#include "zstd/common/huf.h" -#include "zstd/common/huf_static.h" -#include "zstd/common/error_private.h" - - -/* ************************************************************** -* Error Management -****************************************************************/ -// #define HUF_isError ERR_isError -#define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */ - - -namespace duckdb_zstd { -/* ************************************************************** -* Utils -****************************************************************/ -unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue) -{ - return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1); -} - - -/* ******************************************************* -* HUF : Huffman block compression -*********************************************************/ -/* HUF_compressWeights() : - * Same as FSE_compress(), but dedicated to huff0's weights compression. - * The use case needs much less stack memory. - * Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX. - */ -#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6 -static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize) -{ - BYTE* const ostart = (BYTE*) dst; - BYTE* op = ostart; - BYTE* const oend = ostart + dstSize; - - unsigned maxSymbolValue = HUF_TABLELOG_MAX; - U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER; - - FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)]; - BYTE scratchBuffer[1< not compressible */ - } - - tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue); - CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) ); - - /* Write table description header */ - { CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), norm, maxSymbolValue, tableLog) ); - op += hSize; - } - - /* Compress */ - CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) ); - { CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, CTable) ); - if (cSize == 0) return 0; /* not enough space for compressed data */ - op += cSize; - } - - return (size_t)(op-ostart); -} - - -struct HUF_CElt_s { - U16 val; - BYTE nbBits; -}; /* typedef'd to HUF_CElt within "zstd/common/huf.h" */ - -/*! HUF_writeCTable() : - `CTable` : Huffman tree to save, using huf representation. - @return : size of saved CTable */ -size_t HUF_writeCTable (void* dst, size_t maxDstSize, - const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog) -{ - BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */ - BYTE huffWeight[HUF_SYMBOLVALUE_MAX]; - BYTE* op = (BYTE*)dst; - U32 n; - - /* check conditions */ - if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge); - - /* convert to weight */ - bitsToWeight[0] = 0; - for (n=1; n1) & (hSize < maxSymbolValue/2)) { /* FSE compressed */ - op[0] = (BYTE)hSize; - return hSize+1; - } } - - /* write raw values as 4-bits (max : 15) */ - if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */ - if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */ - op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1)); - huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */ - for (n=0; n HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); - if (nbSymbols > *maxSymbolValuePtr+1) return ERROR(maxSymbolValue_tooSmall); - - /* Prepare base value per rank */ - { U32 n, nextRankStart = 0; - for (n=1; n<=tableLog; n++) { - U32 current = nextRankStart; - nextRankStart += (rankVal[n] << (n-1)); - rankVal[n] = current; - } } - - /* fill nbBits */ - *hasZeroWeights = 0; - { U32 n; for (n=0; nn=tableLog+1 */ - U16 valPerRank[HUF_TABLELOG_MAX+2] = {0}; - { U32 n; for (n=0; n0; n--) { /* start at n=tablelog <-> w=1 */ - valPerRank[n] = min; /* get starting value within each rank */ - min += nbPerRank[n]; - min >>= 1; - } } - /* assign value within rank, symbol order */ - { U32 n; for (n=0; n maxNbBits */ - - /* there are several too large elements (at least >= 2) */ - { int totalCost = 0; - const U32 baseCost = 1 << (largestBits - maxNbBits); - int n = (int)lastNonNull; - - while (huffNode[n].nbBits > maxNbBits) { - totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)); - huffNode[n].nbBits = (BYTE)maxNbBits; - n --; - } /* n stops at huffNode[n].nbBits <= maxNbBits */ - while (huffNode[n].nbBits == maxNbBits) n--; /* n end at index of smallest symbol using < maxNbBits */ - - /* renorm totalCost */ - totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */ - - /* repay normalized cost */ - { U32 const noSymbol = 0xF0F0F0F0; - U32 rankLast[HUF_TABLELOG_MAX+2]; - - /* Get pos of last (smallest) symbol per rank */ - memset(rankLast, 0xF0, sizeof(rankLast)); - { U32 currentNbBits = maxNbBits; - int pos; - for (pos=n ; pos >= 0; pos--) { - if (huffNode[pos].nbBits >= currentNbBits) continue; - currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */ - rankLast[maxNbBits-currentNbBits] = (U32)pos; - } } - - while (totalCost > 0) { - U32 nBitsToDecrease = BIT_highbit32((U32)totalCost) + 1; - for ( ; nBitsToDecrease > 1; nBitsToDecrease--) { - U32 const highPos = rankLast[nBitsToDecrease]; - U32 const lowPos = rankLast[nBitsToDecrease-1]; - if (highPos == noSymbol) continue; - if (lowPos == noSymbol) break; - { U32 const highTotal = huffNode[highPos].count; - U32 const lowTotal = 2 * huffNode[lowPos].count; - if (highTotal <= lowTotal) break; - } } - /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */ - /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */ - while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol)) - nBitsToDecrease ++; - totalCost -= 1 << (nBitsToDecrease-1); - if (rankLast[nBitsToDecrease-1] == noSymbol) - rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; /* this rank is no longer empty */ - huffNode[rankLast[nBitsToDecrease]].nbBits ++; - if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */ - rankLast[nBitsToDecrease] = noSymbol; - else { - rankLast[nBitsToDecrease]--; - if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease) - rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */ - } } /* while (totalCost > 0) */ - - while (totalCost < 0) { /* Sometimes, cost correction overshoot */ - if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */ - while (huffNode[n].nbBits == maxNbBits) n--; - huffNode[n+1].nbBits--; - assert(n >= 0); - rankLast[1] = (U32)(n+1); - totalCost++; - continue; - } - huffNode[ rankLast[1] + 1 ].nbBits--; - rankLast[1]++; - totalCost ++; - } } } /* there are several too large elements (at least >= 2) */ - - return maxNbBits; -} - -typedef struct { - U32 base; - U32 current; -} rankPos; - -typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32]; - -#define RANK_POSITION_TABLE_SIZE 32 - -typedef struct { - huffNodeTable huffNodeTbl; - rankPos rankPosition[RANK_POSITION_TABLE_SIZE]; -} HUF_buildCTable_wksp_tables; - -static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rankPosition) -{ - U32 n; - - memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE); - for (n=0; n<=maxSymbolValue; n++) { - U32 r = BIT_highbit32(count[n] + 1); - rankPosition[r].base ++; - } - for (n=30; n>0; n--) rankPosition[n-1].base += rankPosition[n].base; - for (n=0; n<32; n++) rankPosition[n].current = rankPosition[n].base; - for (n=0; n<=maxSymbolValue; n++) { - U32 const c = count[n]; - U32 const r = BIT_highbit32(c+1) + 1; - U32 pos = rankPosition[r].current++; - while ((pos > rankPosition[r].base) && (c > huffNode[pos-1].count)) { - huffNode[pos] = huffNode[pos-1]; - pos--; - } - huffNode[pos].count = c; - huffNode[pos].byte = (BYTE)n; - } -} - - -/** HUF_buildCTable_wksp() : - * Same as HUF_buildCTable(), but using externally allocated scratch buffer. - * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as sizeof(HUF_buildCTable_wksp_tables). - */ -#define STARTNODE (HUF_SYMBOLVALUE_MAX+1) - -size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize) -{ - HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace; - nodeElt* const huffNode0 = wksp_tables->huffNodeTbl; - nodeElt* const huffNode = huffNode0+1; - int nonNullRank; - int lowS, lowN; - int nodeNb = STARTNODE; - int n, nodeRoot; - - /* safety checks */ - if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ - if (wkspSize < sizeof(HUF_buildCTable_wksp_tables)) - return ERROR(workSpace_tooSmall); - if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; - if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) - return ERROR(maxSymbolValue_tooLarge); - memset(huffNode0, 0, sizeof(huffNodeTable)); - - /* sort, decreasing order */ - HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition); - - /* init for parents */ - nonNullRank = (int)maxSymbolValue; - while(huffNode[nonNullRank].count == 0) nonNullRank--; - lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb; - huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count; - huffNode[lowS].parent = huffNode[lowS-1].parent = (U16)nodeNb; - nodeNb++; lowS-=2; - for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30); - huffNode0[0].count = (U32)(1U<<31); /* fake entry, strong barrier */ - - /* create parents */ - while (nodeNb <= nodeRoot) { - int const n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; - int const n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; - huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count; - huffNode[n1].parent = huffNode[n2].parent = (U16)nodeNb; - nodeNb++; - } - - /* distribute weights (unlimited tree height) */ - huffNode[nodeRoot].nbBits = 0; - for (n=nodeRoot-1; n>=STARTNODE; n--) - huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; - for (n=0; n<=nonNullRank; n++) - huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; - - /* enforce maxTableLog */ - maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits); - - /* fill result into tree (val, nbBits) */ - { U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0}; - U16 valPerRank[HUF_TABLELOG_MAX+1] = {0}; - int const alphabetSize = (int)(maxSymbolValue + 1); - if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */ - for (n=0; n<=nonNullRank; n++) - nbPerRank[huffNode[n].nbBits]++; - /* determine stating value per rank */ - { U16 min = 0; - for (n=(int)maxNbBits; n>0; n--) { - valPerRank[n] = min; /* get starting value within each rank */ - min += nbPerRank[n]; - min >>= 1; - } } - for (n=0; n> 3; -} - -int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) { - int bad = 0; - int s; - for (s = 0; s <= (int)maxSymbolValue; ++s) { - bad |= (count[s] != 0) & (CTable[s].nbBits == 0); - } - return !bad; -} - -size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); } - -FORCE_INLINE_TEMPLATE void -HUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable) -{ - BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits); -} - -#define HUF_FLUSHBITS(s) BIT_flushBits(s) - -#define HUF_FLUSHBITS_1(stream) \ - if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*2+7) HUF_FLUSHBITS(stream) - -#define HUF_FLUSHBITS_2(stream) \ - if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*4+7) HUF_FLUSHBITS(stream) - -FORCE_INLINE_TEMPLATE size_t -HUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize, - const void* src, size_t srcSize, - const HUF_CElt* CTable) -{ - const BYTE* ip = (const BYTE*) src; - BYTE* const ostart = (BYTE*)dst; - BYTE* const oend = ostart + dstSize; - BYTE* op = ostart; - size_t n; - BIT_CStream_t bitC; - - /* init */ - if (dstSize < 8) return 0; /* not enough space to compress */ - { size_t const initErr = BIT_initCStream(&bitC, op, (size_t)(oend-op)); - if (HUF_isError(initErr)) return 0; } - - n = srcSize & ~3; /* join to mod 4 */ - switch (srcSize & 3) - { - case 3 : HUF_encodeSymbol(&bitC, ip[n+ 2], CTable); - HUF_FLUSHBITS_2(&bitC); - /* fall-through */ - case 2 : HUF_encodeSymbol(&bitC, ip[n+ 1], CTable); - HUF_FLUSHBITS_1(&bitC); - /* fall-through */ - case 1 : HUF_encodeSymbol(&bitC, ip[n+ 0], CTable); - HUF_FLUSHBITS(&bitC); - /* fall-through */ - case 0 : /* fall-through */ - default: break; - } - - for (; n>0; n-=4) { /* note : n&3==0 at this stage */ - HUF_encodeSymbol(&bitC, ip[n- 1], CTable); - HUF_FLUSHBITS_1(&bitC); - HUF_encodeSymbol(&bitC, ip[n- 2], CTable); - HUF_FLUSHBITS_2(&bitC); - HUF_encodeSymbol(&bitC, ip[n- 3], CTable); - HUF_FLUSHBITS_1(&bitC); - HUF_encodeSymbol(&bitC, ip[n- 4], CTable); - HUF_FLUSHBITS(&bitC); - } - - return BIT_closeCStream(&bitC); -} - -#if DYNAMIC_BMI2 - -static TARGET_ATTRIBUTE("bmi2") size_t -HUF_compress1X_usingCTable_internal_bmi2(void* dst, size_t dstSize, - const void* src, size_t srcSize, - const HUF_CElt* CTable) -{ - return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable); -} - -static size_t -HUF_compress1X_usingCTable_internal_default(void* dst, size_t dstSize, - const void* src, size_t srcSize, - const HUF_CElt* CTable) -{ - return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable); -} - -static size_t -HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize, - const void* src, size_t srcSize, - const HUF_CElt* CTable, const int bmi2) -{ - if (bmi2) { - return HUF_compress1X_usingCTable_internal_bmi2(dst, dstSize, src, srcSize, CTable); - } - return HUF_compress1X_usingCTable_internal_default(dst, dstSize, src, srcSize, CTable); -} - -#else - -static size_t -HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize, - const void* src, size_t srcSize, - const HUF_CElt* CTable, const int bmi2) -{ - (void)bmi2; - return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable); -} - -#endif - -size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable) -{ - return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0); -} - - -static size_t -HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize, - const void* src, size_t srcSize, - const HUF_CElt* CTable, int bmi2) -{ - size_t const segmentSize = (srcSize+3)/4; /* first 3 segments */ - const BYTE* ip = (const BYTE*) src; - const BYTE* const iend = ip + srcSize; - BYTE* const ostart = (BYTE*) dst; - BYTE* const oend = ostart + dstSize; - BYTE* op = ostart; - - if (dstSize < 6 + 1 + 1 + 1 + 8) return 0; /* minimum space to compress successfully */ - if (srcSize < 12) return 0; /* no saving possible : too small input */ - op += 6; /* jumpTable */ - - assert(op <= oend); - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) ); - if (cSize==0) return 0; - assert(cSize <= 65535); - MEM_writeLE16(ostart, (U16)cSize); - op += cSize; - } - - ip += segmentSize; - assert(op <= oend); - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) ); - if (cSize==0) return 0; - assert(cSize <= 65535); - MEM_writeLE16(ostart+2, (U16)cSize); - op += cSize; - } - - ip += segmentSize; - assert(op <= oend); - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) ); - if (cSize==0) return 0; - assert(cSize <= 65535); - MEM_writeLE16(ostart+4, (U16)cSize); - op += cSize; - } - - ip += segmentSize; - assert(op <= oend); - assert(ip <= iend); - { CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, bmi2) ); - if (cSize==0) return 0; - op += cSize; - } - - return (size_t)(op-ostart); -} - -size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable) -{ - return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0); -} - -typedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e; - -static size_t HUF_compressCTable_internal( - BYTE* const ostart, BYTE* op, BYTE* const oend, - const void* src, size_t srcSize, - HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int bmi2) -{ - size_t const cSize = (nbStreams==HUF_singleStream) ? - HUF_compress1X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2) : - HUF_compress4X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2); - if (HUF_isError(cSize)) { return cSize; } - if (cSize==0) { return 0; } /* uncompressible */ - op += cSize; - /* check compressibility */ - assert(op >= ostart); - if ((size_t)(op-ostart) >= srcSize-1) { return 0; } - return (size_t)(op-ostart); -} - -typedef struct { - unsigned count[HUF_SYMBOLVALUE_MAX + 1]; - HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1]; - HUF_buildCTable_wksp_tables buildCTable_wksp; -} HUF_compress_tables_t; - -/* HUF_compress_internal() : - * `workSpace` must a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ -static size_t -HUF_compress_internal (void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - HUF_nbStreams_e nbStreams, - void* workSpace, size_t wkspSize, - HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat, - const int bmi2) -{ - HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace; - BYTE* const ostart = (BYTE*)dst; - BYTE* const oend = ostart + dstSize; - BYTE* op = ostart; - - HUF_STATIC_ASSERT(sizeof(*table) <= HUF_WORKSPACE_SIZE); - - /* checks & inits */ - if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ - if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall); - if (!srcSize) return 0; /* Uncompressed */ - if (!dstSize) return 0; /* cannot fit anything within dst budget */ - if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */ - if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); - if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge); - if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX; - if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT; - - /* Heuristic : If old table is valid, use it for small inputs */ - if (preferRepeat && repeat && *repeat == HUF_repeat_valid) { - return HUF_compressCTable_internal(ostart, op, oend, - src, srcSize, - nbStreams, oldHufTable, bmi2); - } - - /* Scan input and build symbol stats */ - { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace, wkspSize) ); - if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */ - if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */ - } - - /* Check validity of previous table */ - if ( repeat - && *repeat == HUF_repeat_check - && !HUF_validateCTable(oldHufTable, table->count, maxSymbolValue)) { - *repeat = HUF_repeat_none; - } - /* Heuristic : use existing table for small inputs */ - if (preferRepeat && repeat && *repeat != HUF_repeat_none) { - return HUF_compressCTable_internal(ostart, op, oend, - src, srcSize, - nbStreams, oldHufTable, bmi2); - } - - /* Build Huffman Tree */ - huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); - { size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count, - maxSymbolValue, huffLog, - &table->buildCTable_wksp, sizeof(table->buildCTable_wksp)); - CHECK_F(maxBits); - huffLog = (U32)maxBits; - /* Zero unused symbols in CTable, so we can check it for validity */ - memset(table->CTable + (maxSymbolValue + 1), 0, - sizeof(table->CTable) - ((maxSymbolValue + 1) * sizeof(HUF_CElt))); - } - - /* Write table description header */ - { CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, table->CTable, maxSymbolValue, huffLog) ); - /* Check if using previous huffman table is beneficial */ - if (repeat && *repeat != HUF_repeat_none) { - size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue); - size_t const newSize = HUF_estimateCompressedSize(table->CTable, table->count, maxSymbolValue); - if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) { - return HUF_compressCTable_internal(ostart, op, oend, - src, srcSize, - nbStreams, oldHufTable, bmi2); - } } - - /* Use the new huffman table */ - if (hSize + 12ul >= srcSize) { return 0; } - op += hSize; - if (repeat) { *repeat = HUF_repeat_none; } - if (oldHufTable) - memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */ - } - return HUF_compressCTable_internal(ostart, op, oend, - src, srcSize, - nbStreams, table->CTable, bmi2); -} - - -size_t HUF_compress1X_wksp (void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - void* workSpace, size_t wkspSize) -{ - return HUF_compress_internal(dst, dstSize, src, srcSize, - maxSymbolValue, huffLog, HUF_singleStream, - workSpace, wkspSize, - NULL, NULL, 0, 0 /*bmi2*/); -} - -size_t HUF_compress1X_repeat (void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - void* workSpace, size_t wkspSize, - HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2) -{ - return HUF_compress_internal(dst, dstSize, src, srcSize, - maxSymbolValue, huffLog, HUF_singleStream, - workSpace, wkspSize, hufTable, - repeat, preferRepeat, bmi2); -} - -size_t HUF_compress1X (void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog) -{ - unsigned workSpace[HUF_WORKSPACE_SIZE_U32]; - return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace)); -} - -/* HUF_compress4X_repeat(): - * compress input using 4 streams. - * provide workspace to generate compression tables */ -size_t HUF_compress4X_wksp (void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - void* workSpace, size_t wkspSize) -{ - return HUF_compress_internal(dst, dstSize, src, srcSize, - maxSymbolValue, huffLog, HUF_fourStreams, - workSpace, wkspSize, - NULL, NULL, 0, 0 /*bmi2*/); -} - -/* HUF_compress4X_repeat(): - * compress input using 4 streams. - * re-use an existing huffman compression table */ -size_t HUF_compress4X_repeat (void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - void* workSpace, size_t wkspSize, - HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2) -{ - return HUF_compress_internal(dst, dstSize, src, srcSize, - maxSymbolValue, huffLog, HUF_fourStreams, - workSpace, wkspSize, - hufTable, repeat, preferRepeat, bmi2); -} - -size_t HUF_compress2 (void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog) -{ - unsigned workSpace[HUF_WORKSPACE_SIZE_U32]; - return HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace)); -} - -size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize) -{ - return HUF_compress2(dst, maxDstSize, src, srcSize, 255, HUF_TABLELOG_DEFAULT); -} - -} diff --git a/third_party/zstd/compress/zstd_compress.c b/third_party/zstd/compress/zstd_compress.c new file mode 100644 index 00000000000..9284e2a480a --- /dev/null +++ b/third_party/zstd/compress/zstd_compress.c @@ -0,0 +1,7153 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/*-************************************* +* Dependencies +***************************************/ +#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */ +#include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */ +#include "../common/mem.h" +#include "hist.h" /* HIST_countFast_wksp */ +#define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */ +#include "../common/fse.h" +#include "../common/huf.h" +#include "zstd_compress_internal.h" +#include "zstd_compress_sequences.h" +#include "zstd_compress_literals.h" +#include "zstd_fast.h" +#include "zstd_double_fast.h" +#include "zstd_lazy.h" +#include "zstd_opt.h" +#include "zstd_ldm.h" +#include "zstd_compress_superblock.h" +#include "../common/bits.h" /* ZSTD_highbit32, ZSTD_rotateRight_U64 */ + +/* *************************************************************** +* Tuning parameters +*****************************************************************/ +/*! + * COMPRESS_HEAPMODE : + * Select how default decompression function ZSTD_compress() allocates its context, + * on stack (0, default), or into heap (1). + * Note that functions with explicit context such as ZSTD_compressCCtx() are unaffected. + */ +#ifndef ZSTD_COMPRESS_HEAPMODE +# define ZSTD_COMPRESS_HEAPMODE 0 +#endif + +/*! + * ZSTD_HASHLOG3_MAX : + * Maximum size of the hash table dedicated to find 3-bytes matches, + * in log format, aka 17 => 1 << 17 == 128Ki positions. + * This structure is only used in zstd_opt. + * Since allocation is centralized for all strategies, it has to be known here. + * The actual (selected) size of the hash table is then stored in ZSTD_matchState_t.hashLog3, + * so that zstd_opt.c doesn't need to know about this constant. + */ +#ifndef ZSTD_HASHLOG3_MAX +# define ZSTD_HASHLOG3_MAX 17 +#endif + +/*-************************************* +* Helper functions +***************************************/ +/* ZSTD_compressBound() + * Note that the result from this function is only valid for + * the one-pass compression functions. + * When employing the streaming mode, + * if flushes are frequently altering the size of blocks, + * the overhead from block headers can make the compressed data larger + * than the return value of ZSTD_compressBound(). + */ +size_t ZSTD_compressBound(size_t srcSize) { + size_t const r = ZSTD_COMPRESSBOUND(srcSize); + if (r==0) return ERROR(srcSize_wrong); + return r; +} + + +/*-************************************* +* Context memory management +***************************************/ +struct ZSTD_CDict_s { + const void* dictContent; + size_t dictContentSize; + ZSTD_dictContentType_e dictContentType; /* The dictContentType the CDict was created with */ + U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */ + ZSTD_cwksp workspace; + ZSTD_matchState_t matchState; + ZSTD_compressedBlockState_t cBlockState; + ZSTD_customMem customMem; + U32 dictID; + int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */ + ZSTD_paramSwitch_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use + * row-based matchfinder. Unless the cdict is reloaded, we will use + * the same greedy/lazy matchfinder at compression time. + */ +}; /* typedef'd to ZSTD_CDict within "zstd.h" */ + +ZSTD_CCtx* ZSTD_createCCtx(void) +{ + return ZSTD_createCCtx_advanced(ZSTD_defaultCMem); +} + +static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager) +{ + assert(cctx != NULL); + ZSTD_memset(cctx, 0, sizeof(*cctx)); + cctx->customMem = memManager; + cctx->bmi2 = ZSTD_cpuSupportsBmi2(); + { size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters); + assert(!ZSTD_isError(err)); + (void)err; + } +} + +ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem) +{ + ZSTD_STATIC_ASSERT(zcss_init==0); + ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1)); + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; + { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_customMalloc(sizeof(ZSTD_CCtx), customMem); + if (!cctx) return NULL; + ZSTD_initCCtx(cctx, customMem); + return cctx; + } +} + +ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) +{ + ZSTD_cwksp ws; + ZSTD_CCtx* cctx; + if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */ + if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */ + ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc); + + cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx)); + if (cctx == NULL) return NULL; + + ZSTD_memset(cctx, 0, sizeof(ZSTD_CCtx)); + ZSTD_cwksp_move(&cctx->workspace, &ws); + cctx->staticSize = workspaceSize; + + /* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */ + if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; + cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); + cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); + cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, ENTROPY_WORKSPACE_SIZE); + cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); + return cctx; +} + +/** + * Clears and frees all of the dictionaries in the CCtx. + */ +static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx) +{ + ZSTD_customFree(cctx->localDict.dictBuffer, cctx->customMem); + ZSTD_freeCDict(cctx->localDict.cdict); + ZSTD_memset(&cctx->localDict, 0, sizeof(cctx->localDict)); + ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); + cctx->cdict = NULL; +} + +static size_t ZSTD_sizeof_localDict(ZSTD_localDict dict) +{ + size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0; + size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict); + return bufferSize + cdictSize; +} + +static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx) +{ + assert(cctx != NULL); + assert(cctx->staticSize == 0); + ZSTD_clearAllDicts(cctx); +#ifdef ZSTD_MULTITHREAD + ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL; +#endif + ZSTD_cwksp_free(&cctx->workspace, cctx->customMem); +} + +size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx) +{ + DEBUGLOG(3, "ZSTD_freeCCtx (address: %p)", (void*)cctx); + if (cctx==NULL) return 0; /* support free on NULL */ + RETURN_ERROR_IF(cctx->staticSize, memory_allocation, + "not compatible with static CCtx"); + { int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx); + ZSTD_freeCCtxContent(cctx); + if (!cctxInWorkspace) ZSTD_customFree(cctx, cctx->customMem); + } + return 0; +} + + +static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx) +{ +#ifdef ZSTD_MULTITHREAD + return ZSTDMT_sizeof_CCtx(cctx->mtctx); +#else + (void)cctx; + return 0; +#endif +} + + +size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx) +{ + if (cctx==NULL) return 0; /* support sizeof on NULL */ + /* cctx may be in the workspace */ + return (cctx->workspace.workspace == cctx ? 0 : sizeof(*cctx)) + + ZSTD_cwksp_sizeof(&cctx->workspace) + + ZSTD_sizeof_localDict(cctx->localDict) + + ZSTD_sizeof_mtctx(cctx); +} + +size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs) +{ + return ZSTD_sizeof_CCtx(zcs); /* same object */ +} + +/* private API call, for dictBuilder only */ +const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); } + +/* Returns true if the strategy supports using a row based matchfinder */ +static int ZSTD_rowMatchFinderSupported(const ZSTD_strategy strategy) { + return (strategy >= ZSTD_greedy && strategy <= ZSTD_lazy2); +} + +/* Returns true if the strategy and useRowMatchFinder mode indicate that we will use the row based matchfinder + * for this compression. + */ +static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_paramSwitch_e mode) { + assert(mode != ZSTD_ps_auto); + return ZSTD_rowMatchFinderSupported(strategy) && (mode == ZSTD_ps_enable); +} + +/* Returns row matchfinder usage given an initial mode and cParams */ +static ZSTD_paramSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_paramSwitch_e mode, + const ZSTD_compressionParameters* const cParams) { +#if defined(ZSTD_ARCH_X86_SSE2) || defined(ZSTD_ARCH_ARM_NEON) + int const kHasSIMD128 = 1; +#else + int const kHasSIMD128 = 0; +#endif + if (mode != ZSTD_ps_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */ + mode = ZSTD_ps_disable; + if (!ZSTD_rowMatchFinderSupported(cParams->strategy)) return mode; + if (kHasSIMD128) { + if (cParams->windowLog > 14) mode = ZSTD_ps_enable; + } else { + if (cParams->windowLog > 17) mode = ZSTD_ps_enable; + } + return mode; +} + +/* Returns block splitter usage (generally speaking, when using slower/stronger compression modes) */ +static ZSTD_paramSwitch_e ZSTD_resolveBlockSplitterMode(ZSTD_paramSwitch_e mode, + const ZSTD_compressionParameters* const cParams) { + if (mode != ZSTD_ps_auto) return mode; + return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 17) ? ZSTD_ps_enable : ZSTD_ps_disable; +} + +/* Returns 1 if the arguments indicate that we should allocate a chainTable, 0 otherwise */ +static int ZSTD_allocateChainTable(const ZSTD_strategy strategy, + const ZSTD_paramSwitch_e useRowMatchFinder, + const U32 forDDSDict) { + assert(useRowMatchFinder != ZSTD_ps_auto); + /* We always should allocate a chaintable if we are allocating a matchstate for a DDS dictionary matchstate. + * We do not allocate a chaintable if we are using ZSTD_fast, or are using the row-based matchfinder. + */ + return forDDSDict || ((strategy != ZSTD_fast) && !ZSTD_rowMatchFinderUsed(strategy, useRowMatchFinder)); +} + +/* Returns ZSTD_ps_enable if compression parameters are such that we should + * enable long distance matching (wlog >= 27, strategy >= btopt). + * Returns ZSTD_ps_disable otherwise. + */ +static ZSTD_paramSwitch_e ZSTD_resolveEnableLdm(ZSTD_paramSwitch_e mode, + const ZSTD_compressionParameters* const cParams) { + if (mode != ZSTD_ps_auto) return mode; + return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27) ? ZSTD_ps_enable : ZSTD_ps_disable; +} + +static int ZSTD_resolveExternalSequenceValidation(int mode) { + return mode; +} + +/* Resolves maxBlockSize to the default if no value is present. */ +static size_t ZSTD_resolveMaxBlockSize(size_t maxBlockSize) { + if (maxBlockSize == 0) { + return ZSTD_BLOCKSIZE_MAX; + } else { + return maxBlockSize; + } +} + +static ZSTD_paramSwitch_e ZSTD_resolveExternalRepcodeSearch(ZSTD_paramSwitch_e value, int cLevel) { + if (value != ZSTD_ps_auto) return value; + if (cLevel < 10) { + return ZSTD_ps_disable; + } else { + return ZSTD_ps_enable; + } +} + +/* Returns 1 if compression parameters are such that CDict hashtable and chaintable indices are tagged. + * If so, the tags need to be removed in ZSTD_resetCCtx_byCopyingCDict. */ +static int ZSTD_CDictIndicesAreTagged(const ZSTD_compressionParameters* const cParams) { + return cParams->strategy == ZSTD_fast || cParams->strategy == ZSTD_dfast; +} + +static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( + ZSTD_compressionParameters cParams) +{ + ZSTD_CCtx_params cctxParams; + /* should not matter, as all cParams are presumed properly defined */ + ZSTD_CCtxParams_init(&cctxParams, ZSTD_CLEVEL_DEFAULT); + cctxParams.cParams = cParams; + + /* Adjust advanced params according to cParams */ + cctxParams.ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams.ldmParams.enableLdm, &cParams); + if (cctxParams.ldmParams.enableLdm == ZSTD_ps_enable) { + ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams); + assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog); + assert(cctxParams.ldmParams.hashRateLog < 32); + } + cctxParams.useBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams.useBlockSplitter, &cParams); + cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams); + cctxParams.validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams.validateSequences); + cctxParams.maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams.maxBlockSize); + cctxParams.searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams.searchForExternalRepcodes, + cctxParams.compressionLevel); + assert(!ZSTD_checkCParams(cParams)); + return cctxParams; +} + +static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced( + ZSTD_customMem customMem) +{ + ZSTD_CCtx_params* params; + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; + params = (ZSTD_CCtx_params*)ZSTD_customCalloc( + sizeof(ZSTD_CCtx_params), customMem); + if (!params) { return NULL; } + ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT); + params->customMem = customMem; + return params; +} + +ZSTD_CCtx_params* ZSTD_createCCtxParams(void) +{ + return ZSTD_createCCtxParams_advanced(ZSTD_defaultCMem); +} + +size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params) +{ + if (params == NULL) { return 0; } + ZSTD_customFree(params, params->customMem); + return 0; +} + +size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params) +{ + return ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT); +} + +size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) { + RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); + ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); + cctxParams->compressionLevel = compressionLevel; + cctxParams->fParams.contentSizeFlag = 1; + return 0; +} + +#define ZSTD_NO_CLEVEL 0 + +/** + * Initializes `cctxParams` from `params` and `compressionLevel`. + * @param compressionLevel If params are derived from a compression level then that compression level, otherwise ZSTD_NO_CLEVEL. + */ +static void +ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, + const ZSTD_parameters* params, + int compressionLevel) +{ + assert(!ZSTD_checkCParams(params->cParams)); + ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); + cctxParams->cParams = params->cParams; + cctxParams->fParams = params->fParams; + /* Should not matter, as all cParams are presumed properly defined. + * But, set it for tracing anyway. + */ + cctxParams->compressionLevel = compressionLevel; + cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, ¶ms->cParams); + cctxParams->useBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams->useBlockSplitter, ¶ms->cParams); + cctxParams->ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams->ldmParams.enableLdm, ¶ms->cParams); + cctxParams->validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams->validateSequences); + cctxParams->maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams->maxBlockSize); + cctxParams->searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams->searchForExternalRepcodes, compressionLevel); + DEBUGLOG(4, "ZSTD_CCtxParams_init_internal: useRowMatchFinder=%d, useBlockSplitter=%d ldm=%d", + cctxParams->useRowMatchFinder, cctxParams->useBlockSplitter, cctxParams->ldmParams.enableLdm); +} + +size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) +{ + RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); + FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); + ZSTD_CCtxParams_init_internal(cctxParams, ¶ms, ZSTD_NO_CLEVEL); + return 0; +} + +/** + * Sets cctxParams' cParams and fParams from params, but otherwise leaves them alone. + * @param params Validated zstd parameters. + */ +static void ZSTD_CCtxParams_setZstdParams( + ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params) +{ + assert(!ZSTD_checkCParams(params->cParams)); + cctxParams->cParams = params->cParams; + cctxParams->fParams = params->fParams; + /* Should not matter, as all cParams are presumed properly defined. + * But, set it for tracing anyway. + */ + cctxParams->compressionLevel = ZSTD_NO_CLEVEL; +} + +ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) +{ + ZSTD_bounds bounds = { 0, 0, 0 }; + + switch(param) + { + case ZSTD_c_compressionLevel: + bounds.lowerBound = ZSTD_minCLevel(); + bounds.upperBound = ZSTD_maxCLevel(); + return bounds; + + case ZSTD_c_windowLog: + bounds.lowerBound = ZSTD_WINDOWLOG_MIN; + bounds.upperBound = ZSTD_WINDOWLOG_MAX; + return bounds; + + case ZSTD_c_hashLog: + bounds.lowerBound = ZSTD_HASHLOG_MIN; + bounds.upperBound = ZSTD_HASHLOG_MAX; + return bounds; + + case ZSTD_c_chainLog: + bounds.lowerBound = ZSTD_CHAINLOG_MIN; + bounds.upperBound = ZSTD_CHAINLOG_MAX; + return bounds; + + case ZSTD_c_searchLog: + bounds.lowerBound = ZSTD_SEARCHLOG_MIN; + bounds.upperBound = ZSTD_SEARCHLOG_MAX; + return bounds; + + case ZSTD_c_minMatch: + bounds.lowerBound = ZSTD_MINMATCH_MIN; + bounds.upperBound = ZSTD_MINMATCH_MAX; + return bounds; + + case ZSTD_c_targetLength: + bounds.lowerBound = ZSTD_TARGETLENGTH_MIN; + bounds.upperBound = ZSTD_TARGETLENGTH_MAX; + return bounds; + + case ZSTD_c_strategy: + bounds.lowerBound = ZSTD_STRATEGY_MIN; + bounds.upperBound = ZSTD_STRATEGY_MAX; + return bounds; + + case ZSTD_c_contentSizeFlag: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_checksumFlag: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_dictIDFlag: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_nbWorkers: + bounds.lowerBound = 0; +#ifdef ZSTD_MULTITHREAD + bounds.upperBound = ZSTDMT_NBWORKERS_MAX; +#else + bounds.upperBound = 0; +#endif + return bounds; + + case ZSTD_c_jobSize: + bounds.lowerBound = 0; +#ifdef ZSTD_MULTITHREAD + bounds.upperBound = ZSTDMT_JOBSIZE_MAX; +#else + bounds.upperBound = 0; +#endif + return bounds; + + case ZSTD_c_overlapLog: +#ifdef ZSTD_MULTITHREAD + bounds.lowerBound = ZSTD_OVERLAPLOG_MIN; + bounds.upperBound = ZSTD_OVERLAPLOG_MAX; +#else + bounds.lowerBound = 0; + bounds.upperBound = 0; +#endif + return bounds; + + case ZSTD_c_enableDedicatedDictSearch: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_enableLongDistanceMatching: + bounds.lowerBound = (int)ZSTD_ps_auto; + bounds.upperBound = (int)ZSTD_ps_disable; + return bounds; + + case ZSTD_c_ldmHashLog: + bounds.lowerBound = ZSTD_LDM_HASHLOG_MIN; + bounds.upperBound = ZSTD_LDM_HASHLOG_MAX; + return bounds; + + case ZSTD_c_ldmMinMatch: + bounds.lowerBound = ZSTD_LDM_MINMATCH_MIN; + bounds.upperBound = ZSTD_LDM_MINMATCH_MAX; + return bounds; + + case ZSTD_c_ldmBucketSizeLog: + bounds.lowerBound = ZSTD_LDM_BUCKETSIZELOG_MIN; + bounds.upperBound = ZSTD_LDM_BUCKETSIZELOG_MAX; + return bounds; + + case ZSTD_c_ldmHashRateLog: + bounds.lowerBound = ZSTD_LDM_HASHRATELOG_MIN; + bounds.upperBound = ZSTD_LDM_HASHRATELOG_MAX; + return bounds; + + /* experimental parameters */ + case ZSTD_c_rsyncable: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_forceMaxWindow : + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_format: + ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless); + bounds.lowerBound = ZSTD_f_zstd1; + bounds.upperBound = ZSTD_f_zstd1_magicless; /* note : how to ensure at compile time that this is the highest value enum ? */ + return bounds; + + case ZSTD_c_forceAttachDict: + ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceLoad); + bounds.lowerBound = ZSTD_dictDefaultAttach; + bounds.upperBound = ZSTD_dictForceLoad; /* note : how to ensure at compile time that this is the highest value enum ? */ + return bounds; + + case ZSTD_c_literalCompressionMode: + ZSTD_STATIC_ASSERT(ZSTD_ps_auto < ZSTD_ps_enable && ZSTD_ps_enable < ZSTD_ps_disable); + bounds.lowerBound = (int)ZSTD_ps_auto; + bounds.upperBound = (int)ZSTD_ps_disable; + return bounds; + + case ZSTD_c_targetCBlockSize: + bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN; + bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX; + return bounds; + + case ZSTD_c_srcSizeHint: + bounds.lowerBound = ZSTD_SRCSIZEHINT_MIN; + bounds.upperBound = ZSTD_SRCSIZEHINT_MAX; + return bounds; + + case ZSTD_c_stableInBuffer: + case ZSTD_c_stableOutBuffer: + bounds.lowerBound = (int)ZSTD_bm_buffered; + bounds.upperBound = (int)ZSTD_bm_stable; + return bounds; + + case ZSTD_c_blockDelimiters: + bounds.lowerBound = (int)ZSTD_sf_noBlockDelimiters; + bounds.upperBound = (int)ZSTD_sf_explicitBlockDelimiters; + return bounds; + + case ZSTD_c_validateSequences: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_useBlockSplitter: + bounds.lowerBound = (int)ZSTD_ps_auto; + bounds.upperBound = (int)ZSTD_ps_disable; + return bounds; + + case ZSTD_c_useRowMatchFinder: + bounds.lowerBound = (int)ZSTD_ps_auto; + bounds.upperBound = (int)ZSTD_ps_disable; + return bounds; + + case ZSTD_c_deterministicRefPrefix: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_prefetchCDictTables: + bounds.lowerBound = (int)ZSTD_ps_auto; + bounds.upperBound = (int)ZSTD_ps_disable; + return bounds; + + case ZSTD_c_enableSeqProducerFallback: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + + case ZSTD_c_maxBlockSize: + bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN; + bounds.upperBound = ZSTD_BLOCKSIZE_MAX; + return bounds; + + case ZSTD_c_searchForExternalRepcodes: + bounds.lowerBound = (int)ZSTD_ps_auto; + bounds.upperBound = (int)ZSTD_ps_disable; + return bounds; + + default: + bounds.error = ERROR(parameter_unsupported); + return bounds; + } +} + +/* ZSTD_cParam_clampBounds: + * Clamps the value into the bounded range. + */ +static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value) +{ + ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); + if (ZSTD_isError(bounds.error)) return bounds.error; + if (*value < bounds.lowerBound) *value = bounds.lowerBound; + if (*value > bounds.upperBound) *value = bounds.upperBound; + return 0; +} + +#define BOUNDCHECK(cParam, val) \ + do { \ + RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \ + parameter_outOfBound, "Param out of bounds"); \ + } while (0) + + +static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) +{ + switch(param) + { + case ZSTD_c_compressionLevel: + case ZSTD_c_hashLog: + case ZSTD_c_chainLog: + case ZSTD_c_searchLog: + case ZSTD_c_minMatch: + case ZSTD_c_targetLength: + case ZSTD_c_strategy: + return 1; + + case ZSTD_c_format: + case ZSTD_c_windowLog: + case ZSTD_c_contentSizeFlag: + case ZSTD_c_checksumFlag: + case ZSTD_c_dictIDFlag: + case ZSTD_c_forceMaxWindow : + case ZSTD_c_nbWorkers: + case ZSTD_c_jobSize: + case ZSTD_c_overlapLog: + case ZSTD_c_rsyncable: + case ZSTD_c_enableDedicatedDictSearch: + case ZSTD_c_enableLongDistanceMatching: + case ZSTD_c_ldmHashLog: + case ZSTD_c_ldmMinMatch: + case ZSTD_c_ldmBucketSizeLog: + case ZSTD_c_ldmHashRateLog: + case ZSTD_c_forceAttachDict: + case ZSTD_c_literalCompressionMode: + case ZSTD_c_targetCBlockSize: + case ZSTD_c_srcSizeHint: + case ZSTD_c_stableInBuffer: + case ZSTD_c_stableOutBuffer: + case ZSTD_c_blockDelimiters: + case ZSTD_c_validateSequences: + case ZSTD_c_useBlockSplitter: + case ZSTD_c_useRowMatchFinder: + case ZSTD_c_deterministicRefPrefix: + case ZSTD_c_prefetchCDictTables: + case ZSTD_c_enableSeqProducerFallback: + case ZSTD_c_maxBlockSize: + case ZSTD_c_searchForExternalRepcodes: + default: + return 0; + } +} + +size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) +{ + DEBUGLOG(4, "ZSTD_CCtx_setParameter (%i, %i)", (int)param, value); + if (cctx->streamStage != zcss_init) { + if (ZSTD_isUpdateAuthorized(param)) { + cctx->cParamsChanged = 1; + } else { + RETURN_ERROR(stage_wrong, "can only set params in cctx init stage"); + } } + + switch(param) + { + case ZSTD_c_nbWorkers: + RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported, + "MT not compatible with static alloc"); + break; + + case ZSTD_c_compressionLevel: + case ZSTD_c_windowLog: + case ZSTD_c_hashLog: + case ZSTD_c_chainLog: + case ZSTD_c_searchLog: + case ZSTD_c_minMatch: + case ZSTD_c_targetLength: + case ZSTD_c_strategy: + case ZSTD_c_ldmHashRateLog: + case ZSTD_c_format: + case ZSTD_c_contentSizeFlag: + case ZSTD_c_checksumFlag: + case ZSTD_c_dictIDFlag: + case ZSTD_c_forceMaxWindow: + case ZSTD_c_forceAttachDict: + case ZSTD_c_literalCompressionMode: + case ZSTD_c_jobSize: + case ZSTD_c_overlapLog: + case ZSTD_c_rsyncable: + case ZSTD_c_enableDedicatedDictSearch: + case ZSTD_c_enableLongDistanceMatching: + case ZSTD_c_ldmHashLog: + case ZSTD_c_ldmMinMatch: + case ZSTD_c_ldmBucketSizeLog: + case ZSTD_c_targetCBlockSize: + case ZSTD_c_srcSizeHint: + case ZSTD_c_stableInBuffer: + case ZSTD_c_stableOutBuffer: + case ZSTD_c_blockDelimiters: + case ZSTD_c_validateSequences: + case ZSTD_c_useBlockSplitter: + case ZSTD_c_useRowMatchFinder: + case ZSTD_c_deterministicRefPrefix: + case ZSTD_c_prefetchCDictTables: + case ZSTD_c_enableSeqProducerFallback: + case ZSTD_c_maxBlockSize: + case ZSTD_c_searchForExternalRepcodes: + break; + + default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); + } + return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value); +} + +size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, + ZSTD_cParameter param, int value) +{ + DEBUGLOG(4, "ZSTD_CCtxParams_setParameter (%i, %i)", (int)param, value); + switch(param) + { + case ZSTD_c_format : + BOUNDCHECK(ZSTD_c_format, value); + CCtxParams->format = (ZSTD_format_e)value; + return (size_t)CCtxParams->format; + + case ZSTD_c_compressionLevel : { + FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); + if (value == 0) + CCtxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ + else + CCtxParams->compressionLevel = value; + if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel; + return 0; /* return type (size_t) cannot represent negative values */ + } + + case ZSTD_c_windowLog : + if (value!=0) /* 0 => use default */ + BOUNDCHECK(ZSTD_c_windowLog, value); + CCtxParams->cParams.windowLog = (U32)value; + return CCtxParams->cParams.windowLog; + + case ZSTD_c_hashLog : + if (value!=0) /* 0 => use default */ + BOUNDCHECK(ZSTD_c_hashLog, value); + CCtxParams->cParams.hashLog = (U32)value; + return CCtxParams->cParams.hashLog; + + case ZSTD_c_chainLog : + if (value!=0) /* 0 => use default */ + BOUNDCHECK(ZSTD_c_chainLog, value); + CCtxParams->cParams.chainLog = (U32)value; + return CCtxParams->cParams.chainLog; + + case ZSTD_c_searchLog : + if (value!=0) /* 0 => use default */ + BOUNDCHECK(ZSTD_c_searchLog, value); + CCtxParams->cParams.searchLog = (U32)value; + return (size_t)value; + + case ZSTD_c_minMatch : + if (value!=0) /* 0 => use default */ + BOUNDCHECK(ZSTD_c_minMatch, value); + CCtxParams->cParams.minMatch = (U32)value; + return CCtxParams->cParams.minMatch; + + case ZSTD_c_targetLength : + BOUNDCHECK(ZSTD_c_targetLength, value); + CCtxParams->cParams.targetLength = (U32)value; + return CCtxParams->cParams.targetLength; + + case ZSTD_c_strategy : + if (value!=0) /* 0 => use default */ + BOUNDCHECK(ZSTD_c_strategy, value); + CCtxParams->cParams.strategy = (ZSTD_strategy)value; + return (size_t)CCtxParams->cParams.strategy; + + case ZSTD_c_contentSizeFlag : + /* Content size written in frame header _when known_ (default:1) */ + DEBUGLOG(4, "set content size flag = %u", (value!=0)); + CCtxParams->fParams.contentSizeFlag = value != 0; + return (size_t)CCtxParams->fParams.contentSizeFlag; + + case ZSTD_c_checksumFlag : + /* A 32-bits content checksum will be calculated and written at end of frame (default:0) */ + CCtxParams->fParams.checksumFlag = value != 0; + return (size_t)CCtxParams->fParams.checksumFlag; + + case ZSTD_c_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */ + DEBUGLOG(4, "set dictIDFlag = %u", (value!=0)); + CCtxParams->fParams.noDictIDFlag = !value; + return !CCtxParams->fParams.noDictIDFlag; + + case ZSTD_c_forceMaxWindow : + CCtxParams->forceWindow = (value != 0); + return (size_t)CCtxParams->forceWindow; + + case ZSTD_c_forceAttachDict : { + const ZSTD_dictAttachPref_e pref = (ZSTD_dictAttachPref_e)value; + BOUNDCHECK(ZSTD_c_forceAttachDict, (int)pref); + CCtxParams->attachDictPref = pref; + return CCtxParams->attachDictPref; + } + + case ZSTD_c_literalCompressionMode : { + const ZSTD_paramSwitch_e lcm = (ZSTD_paramSwitch_e)value; + BOUNDCHECK(ZSTD_c_literalCompressionMode, (int)lcm); + CCtxParams->literalCompressionMode = lcm; + return CCtxParams->literalCompressionMode; + } + + case ZSTD_c_nbWorkers : +#ifndef ZSTD_MULTITHREAD + RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); + return 0; +#else + FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); + CCtxParams->nbWorkers = value; + return (size_t)(CCtxParams->nbWorkers); +#endif + + case ZSTD_c_jobSize : +#ifndef ZSTD_MULTITHREAD + RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); + return 0; +#else + /* Adjust to the minimum non-default value. */ + if (value != 0 && value < ZSTDMT_JOBSIZE_MIN) + value = ZSTDMT_JOBSIZE_MIN; + FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); + assert(value >= 0); + CCtxParams->jobSize = value; + return CCtxParams->jobSize; +#endif + + case ZSTD_c_overlapLog : +#ifndef ZSTD_MULTITHREAD + RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); + return 0; +#else + FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), ""); + CCtxParams->overlapLog = value; + return (size_t)CCtxParams->overlapLog; +#endif + + case ZSTD_c_rsyncable : +#ifndef ZSTD_MULTITHREAD + RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); + return 0; +#else + FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), ""); + CCtxParams->rsyncable = value; + return (size_t)CCtxParams->rsyncable; +#endif + + case ZSTD_c_enableDedicatedDictSearch : + CCtxParams->enableDedicatedDictSearch = (value!=0); + return (size_t)CCtxParams->enableDedicatedDictSearch; + + case ZSTD_c_enableLongDistanceMatching : + BOUNDCHECK(ZSTD_c_enableLongDistanceMatching, value); + CCtxParams->ldmParams.enableLdm = (ZSTD_paramSwitch_e)value; + return CCtxParams->ldmParams.enableLdm; + + case ZSTD_c_ldmHashLog : + if (value!=0) /* 0 ==> auto */ + BOUNDCHECK(ZSTD_c_ldmHashLog, value); + CCtxParams->ldmParams.hashLog = (U32)value; + return CCtxParams->ldmParams.hashLog; + + case ZSTD_c_ldmMinMatch : + if (value!=0) /* 0 ==> default */ + BOUNDCHECK(ZSTD_c_ldmMinMatch, value); + CCtxParams->ldmParams.minMatchLength = (U32)value; + return CCtxParams->ldmParams.minMatchLength; + + case ZSTD_c_ldmBucketSizeLog : + if (value!=0) /* 0 ==> default */ + BOUNDCHECK(ZSTD_c_ldmBucketSizeLog, value); + CCtxParams->ldmParams.bucketSizeLog = (U32)value; + return CCtxParams->ldmParams.bucketSizeLog; + + case ZSTD_c_ldmHashRateLog : + if (value!=0) /* 0 ==> default */ + BOUNDCHECK(ZSTD_c_ldmHashRateLog, value); + CCtxParams->ldmParams.hashRateLog = (U32)value; + return CCtxParams->ldmParams.hashRateLog; + + case ZSTD_c_targetCBlockSize : + if (value!=0) { /* 0 ==> default */ + value = MAX(value, ZSTD_TARGETCBLOCKSIZE_MIN); + BOUNDCHECK(ZSTD_c_targetCBlockSize, value); + } + CCtxParams->targetCBlockSize = (U32)value; + return CCtxParams->targetCBlockSize; + + case ZSTD_c_srcSizeHint : + if (value!=0) /* 0 ==> default */ + BOUNDCHECK(ZSTD_c_srcSizeHint, value); + CCtxParams->srcSizeHint = value; + return (size_t)CCtxParams->srcSizeHint; + + case ZSTD_c_stableInBuffer: + BOUNDCHECK(ZSTD_c_stableInBuffer, value); + CCtxParams->inBufferMode = (ZSTD_bufferMode_e)value; + return CCtxParams->inBufferMode; + + case ZSTD_c_stableOutBuffer: + BOUNDCHECK(ZSTD_c_stableOutBuffer, value); + CCtxParams->outBufferMode = (ZSTD_bufferMode_e)value; + return CCtxParams->outBufferMode; + + case ZSTD_c_blockDelimiters: + BOUNDCHECK(ZSTD_c_blockDelimiters, value); + CCtxParams->blockDelimiters = (ZSTD_sequenceFormat_e)value; + return CCtxParams->blockDelimiters; + + case ZSTD_c_validateSequences: + BOUNDCHECK(ZSTD_c_validateSequences, value); + CCtxParams->validateSequences = value; + return (size_t)CCtxParams->validateSequences; + + case ZSTD_c_useBlockSplitter: + BOUNDCHECK(ZSTD_c_useBlockSplitter, value); + CCtxParams->useBlockSplitter = (ZSTD_paramSwitch_e)value; + return CCtxParams->useBlockSplitter; + + case ZSTD_c_useRowMatchFinder: + BOUNDCHECK(ZSTD_c_useRowMatchFinder, value); + CCtxParams->useRowMatchFinder = (ZSTD_paramSwitch_e)value; + return CCtxParams->useRowMatchFinder; + + case ZSTD_c_deterministicRefPrefix: + BOUNDCHECK(ZSTD_c_deterministicRefPrefix, value); + CCtxParams->deterministicRefPrefix = !!value; + return (size_t)CCtxParams->deterministicRefPrefix; + + case ZSTD_c_prefetchCDictTables: + BOUNDCHECK(ZSTD_c_prefetchCDictTables, value); + CCtxParams->prefetchCDictTables = (ZSTD_paramSwitch_e)value; + return CCtxParams->prefetchCDictTables; + + case ZSTD_c_enableSeqProducerFallback: + BOUNDCHECK(ZSTD_c_enableSeqProducerFallback, value); + CCtxParams->enableMatchFinderFallback = value; + return (size_t)CCtxParams->enableMatchFinderFallback; + + case ZSTD_c_maxBlockSize: + if (value!=0) /* 0 ==> default */ + BOUNDCHECK(ZSTD_c_maxBlockSize, value); + CCtxParams->maxBlockSize = value; + return CCtxParams->maxBlockSize; + + case ZSTD_c_searchForExternalRepcodes: + BOUNDCHECK(ZSTD_c_searchForExternalRepcodes, value); + CCtxParams->searchForExternalRepcodes = (ZSTD_paramSwitch_e)value; + return CCtxParams->searchForExternalRepcodes; + + default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); + } +} + +size_t ZSTD_CCtx_getParameter(ZSTD_CCtx const* cctx, ZSTD_cParameter param, int* value) +{ + return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value); +} + +size_t ZSTD_CCtxParams_getParameter( + ZSTD_CCtx_params const* CCtxParams, ZSTD_cParameter param, int* value) +{ + switch(param) + { + case ZSTD_c_format : + *value = CCtxParams->format; + break; + case ZSTD_c_compressionLevel : + *value = CCtxParams->compressionLevel; + break; + case ZSTD_c_windowLog : + *value = (int)CCtxParams->cParams.windowLog; + break; + case ZSTD_c_hashLog : + *value = (int)CCtxParams->cParams.hashLog; + break; + case ZSTD_c_chainLog : + *value = (int)CCtxParams->cParams.chainLog; + break; + case ZSTD_c_searchLog : + *value = CCtxParams->cParams.searchLog; + break; + case ZSTD_c_minMatch : + *value = CCtxParams->cParams.minMatch; + break; + case ZSTD_c_targetLength : + *value = CCtxParams->cParams.targetLength; + break; + case ZSTD_c_strategy : + *value = (unsigned)CCtxParams->cParams.strategy; + break; + case ZSTD_c_contentSizeFlag : + *value = CCtxParams->fParams.contentSizeFlag; + break; + case ZSTD_c_checksumFlag : + *value = CCtxParams->fParams.checksumFlag; + break; + case ZSTD_c_dictIDFlag : + *value = !CCtxParams->fParams.noDictIDFlag; + break; + case ZSTD_c_forceMaxWindow : + *value = CCtxParams->forceWindow; + break; + case ZSTD_c_forceAttachDict : + *value = CCtxParams->attachDictPref; + break; + case ZSTD_c_literalCompressionMode : + *value = CCtxParams->literalCompressionMode; + break; + case ZSTD_c_nbWorkers : +#ifndef ZSTD_MULTITHREAD + assert(CCtxParams->nbWorkers == 0); +#endif + *value = CCtxParams->nbWorkers; + break; + case ZSTD_c_jobSize : +#ifndef ZSTD_MULTITHREAD + RETURN_ERROR(parameter_unsupported, "not compiled with multithreading"); +#else + assert(CCtxParams->jobSize <= INT_MAX); + *value = (int)CCtxParams->jobSize; + break; +#endif + case ZSTD_c_overlapLog : +#ifndef ZSTD_MULTITHREAD + RETURN_ERROR(parameter_unsupported, "not compiled with multithreading"); +#else + *value = CCtxParams->overlapLog; + break; +#endif + case ZSTD_c_rsyncable : +#ifndef ZSTD_MULTITHREAD + RETURN_ERROR(parameter_unsupported, "not compiled with multithreading"); +#else + *value = CCtxParams->rsyncable; + break; +#endif + case ZSTD_c_enableDedicatedDictSearch : + *value = CCtxParams->enableDedicatedDictSearch; + break; + case ZSTD_c_enableLongDistanceMatching : + *value = CCtxParams->ldmParams.enableLdm; + break; + case ZSTD_c_ldmHashLog : + *value = CCtxParams->ldmParams.hashLog; + break; + case ZSTD_c_ldmMinMatch : + *value = CCtxParams->ldmParams.minMatchLength; + break; + case ZSTD_c_ldmBucketSizeLog : + *value = CCtxParams->ldmParams.bucketSizeLog; + break; + case ZSTD_c_ldmHashRateLog : + *value = CCtxParams->ldmParams.hashRateLog; + break; + case ZSTD_c_targetCBlockSize : + *value = (int)CCtxParams->targetCBlockSize; + break; + case ZSTD_c_srcSizeHint : + *value = (int)CCtxParams->srcSizeHint; + break; + case ZSTD_c_stableInBuffer : + *value = (int)CCtxParams->inBufferMode; + break; + case ZSTD_c_stableOutBuffer : + *value = (int)CCtxParams->outBufferMode; + break; + case ZSTD_c_blockDelimiters : + *value = (int)CCtxParams->blockDelimiters; + break; + case ZSTD_c_validateSequences : + *value = (int)CCtxParams->validateSequences; + break; + case ZSTD_c_useBlockSplitter : + *value = (int)CCtxParams->useBlockSplitter; + break; + case ZSTD_c_useRowMatchFinder : + *value = (int)CCtxParams->useRowMatchFinder; + break; + case ZSTD_c_deterministicRefPrefix: + *value = (int)CCtxParams->deterministicRefPrefix; + break; + case ZSTD_c_prefetchCDictTables: + *value = (int)CCtxParams->prefetchCDictTables; + break; + case ZSTD_c_enableSeqProducerFallback: + *value = CCtxParams->enableMatchFinderFallback; + break; + case ZSTD_c_maxBlockSize: + *value = (int)CCtxParams->maxBlockSize; + break; + case ZSTD_c_searchForExternalRepcodes: + *value = (int)CCtxParams->searchForExternalRepcodes; + break; + default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); + } + return 0; +} + +/** ZSTD_CCtx_setParametersUsingCCtxParams() : + * just applies `params` into `cctx` + * no action is performed, parameters are merely stored. + * If ZSTDMT is enabled, parameters are pushed to cctx->mtctx. + * This is possible even if a compression is ongoing. + * In which case, new parameters will be applied on the fly, starting with next compression job. + */ +size_t ZSTD_CCtx_setParametersUsingCCtxParams( + ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params) +{ + DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams"); + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "The context is in the wrong stage!"); + RETURN_ERROR_IF(cctx->cdict, stage_wrong, + "Can't override parameters with cdict attached (some must " + "be inherited from the cdict)."); + + cctx->requestedParams = *params; + return 0; +} + +size_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams) +{ + ZSTD_STATIC_ASSERT(sizeof(cparams) == 7 * 4 /* all params are listed below */); + DEBUGLOG(4, "ZSTD_CCtx_setCParams"); + /* only update if all parameters are valid */ + FORWARD_IF_ERROR(ZSTD_checkCParams(cparams), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, cparams.windowLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_chainLog, cparams.chainLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, cparams.hashLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_searchLog, cparams.searchLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, cparams.minMatch), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetLength, cparams.targetLength), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, cparams.strategy), ""); + return 0; +} + +size_t ZSTD_CCtx_setFParams(ZSTD_CCtx* cctx, ZSTD_frameParameters fparams) +{ + ZSTD_STATIC_ASSERT(sizeof(fparams) == 3 * 4 /* all params are listed below */); + DEBUGLOG(4, "ZSTD_CCtx_setFParams"); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, fparams.contentSizeFlag != 0), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, fparams.checksumFlag != 0), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_dictIDFlag, fparams.noDictIDFlag == 0), ""); + return 0; +} + +size_t ZSTD_CCtx_setParams(ZSTD_CCtx* cctx, ZSTD_parameters params) +{ + DEBUGLOG(4, "ZSTD_CCtx_setParams"); + /* First check cParams, because we want to update all or none. */ + FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), ""); + /* Next set fParams, because this could fail if the cctx isn't in init stage. */ + FORWARD_IF_ERROR(ZSTD_CCtx_setFParams(cctx, params.fParams), ""); + /* Finally set cParams, which should succeed. */ + FORWARD_IF_ERROR(ZSTD_CCtx_setCParams(cctx, params.cParams), ""); + return 0; +} + +size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize) +{ + DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %llu bytes", pledgedSrcSize); + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't set pledgedSrcSize when not in init stage."); + cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1; + return 0; +} + +static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams( + int const compressionLevel, + size_t const dictSize); +static int ZSTD_dedicatedDictSearch_isSupported( + const ZSTD_compressionParameters* cParams); +static void ZSTD_dedicatedDictSearch_revertCParams( + ZSTD_compressionParameters* cParams); + +/** + * Initializes the local dictionary using requested parameters. + * NOTE: Initialization does not employ the pledged src size, + * because the dictionary may be used for multiple compressions. + */ +static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx) +{ + ZSTD_localDict* const dl = &cctx->localDict; + if (dl->dict == NULL) { + /* No local dictionary. */ + assert(dl->dictBuffer == NULL); + assert(dl->cdict == NULL); + assert(dl->dictSize == 0); + return 0; + } + if (dl->cdict != NULL) { + /* Local dictionary already initialized. */ + assert(cctx->cdict == dl->cdict); + return 0; + } + assert(dl->dictSize > 0); + assert(cctx->cdict == NULL); + assert(cctx->prefixDict.dict == NULL); + + dl->cdict = ZSTD_createCDict_advanced2( + dl->dict, + dl->dictSize, + ZSTD_dlm_byRef, + dl->dictContentType, + &cctx->requestedParams, + cctx->customMem); + RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed"); + cctx->cdict = dl->cdict; + return 0; +} + +size_t ZSTD_CCtx_loadDictionary_advanced( + ZSTD_CCtx* cctx, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType) +{ + DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize); + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't load a dictionary when cctx is not in init stage."); + ZSTD_clearAllDicts(cctx); /* erase any previously set dictionary */ + if (dict == NULL || dictSize == 0) /* no dictionary */ + return 0; + if (dictLoadMethod == ZSTD_dlm_byRef) { + cctx->localDict.dict = dict; + } else { + /* copy dictionary content inside CCtx to own its lifetime */ + void* dictBuffer; + RETURN_ERROR_IF(cctx->staticSize, memory_allocation, + "static CCtx can't allocate for an internal copy of dictionary"); + dictBuffer = ZSTD_customMalloc(dictSize, cctx->customMem); + RETURN_ERROR_IF(dictBuffer==NULL, memory_allocation, + "allocation failed for dictionary content"); + ZSTD_memcpy(dictBuffer, dict, dictSize); + cctx->localDict.dictBuffer = dictBuffer; /* owned ptr to free */ + cctx->localDict.dict = dictBuffer; /* read-only reference */ + } + cctx->localDict.dictSize = dictSize; + cctx->localDict.dictContentType = dictContentType; + return 0; +} + +size_t ZSTD_CCtx_loadDictionary_byReference( + ZSTD_CCtx* cctx, const void* dict, size_t dictSize) +{ + return ZSTD_CCtx_loadDictionary_advanced( + cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto); +} + +size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize) +{ + return ZSTD_CCtx_loadDictionary_advanced( + cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto); +} + + +size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) +{ + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't ref a dict when ctx not in init stage."); + /* Free the existing local cdict (if any) to save memory. */ + ZSTD_clearAllDicts(cctx); + cctx->cdict = cdict; + return 0; +} + +size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool) +{ + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't ref a pool when ctx not in init stage."); + cctx->pool = pool; + return 0; +} + +size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize) +{ + return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent); +} + +size_t ZSTD_CCtx_refPrefix_advanced( + ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType) +{ + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't ref a prefix when ctx not in init stage."); + ZSTD_clearAllDicts(cctx); + if (prefix != NULL && prefixSize > 0) { + cctx->prefixDict.dict = prefix; + cctx->prefixDict.dictSize = prefixSize; + cctx->prefixDict.dictContentType = dictContentType; + } + return 0; +} + +/*! ZSTD_CCtx_reset() : + * Also dumps dictionary */ +size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset) +{ + if ( (reset == ZSTD_reset_session_only) + || (reset == ZSTD_reset_session_and_parameters) ) { + cctx->streamStage = zcss_init; + cctx->pledgedSrcSizePlusOne = 0; + } + if ( (reset == ZSTD_reset_parameters) + || (reset == ZSTD_reset_session_and_parameters) ) { + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Reset parameters is only possible during init stage."); + ZSTD_clearAllDicts(cctx); + return ZSTD_CCtxParams_reset(&cctx->requestedParams); + } + return 0; +} + + +/** ZSTD_checkCParams() : + control CParam values remain within authorized range. + @return : 0, or an error code if one value is beyond authorized range */ +size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) +{ + BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog); + BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog); + BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog); + BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); + BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch); + BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength); + BOUNDCHECK(ZSTD_c_strategy, cParams.strategy); + return 0; +} + +/** ZSTD_clampCParams() : + * make CParam values within valid range. + * @return : valid CParams */ +static ZSTD_compressionParameters +ZSTD_clampCParams(ZSTD_compressionParameters cParams) +{ +# define CLAMP_TYPE(cParam, val, type) \ + do { \ + ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); \ + if ((int)valbounds.upperBound) val=(type)bounds.upperBound; \ + } while (0) +# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned) + CLAMP(ZSTD_c_windowLog, cParams.windowLog); + CLAMP(ZSTD_c_chainLog, cParams.chainLog); + CLAMP(ZSTD_c_hashLog, cParams.hashLog); + CLAMP(ZSTD_c_searchLog, cParams.searchLog); + CLAMP(ZSTD_c_minMatch, cParams.minMatch); + CLAMP(ZSTD_c_targetLength,cParams.targetLength); + CLAMP_TYPE(ZSTD_c_strategy,cParams.strategy, ZSTD_strategy); + return cParams; +} + +/** ZSTD_cycleLog() : + * condition for correct operation : hashLog > 1 */ +U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) +{ + U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2); + return hashLog - btScale; +} + +/** ZSTD_dictAndWindowLog() : + * Returns an adjusted window log that is large enough to fit the source and the dictionary. + * The zstd format says that the entire dictionary is valid if one byte of the dictionary + * is within the window. So the hashLog and chainLog should be large enough to reference both + * the dictionary and the window. So we must use this adjusted dictAndWindowLog when downsizing + * the hashLog and windowLog. + * NOTE: srcSize must not be ZSTD_CONTENTSIZE_UNKNOWN. + */ +static U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize) +{ + const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX; + /* No dictionary ==> No change */ + if (dictSize == 0) { + return windowLog; + } + assert(windowLog <= ZSTD_WINDOWLOG_MAX); + assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */ + { + U64 const windowSize = 1ULL << windowLog; + U64 const dictAndWindowSize = dictSize + windowSize; + /* If the window size is already large enough to fit both the source and the dictionary + * then just use the window size. Otherwise adjust so that it fits the dictionary and + * the window. + */ + if (windowSize >= dictSize + srcSize) { + return windowLog; /* Window size large enough already */ + } else if (dictAndWindowSize >= maxWindowSize) { + return ZSTD_WINDOWLOG_MAX; /* Larger than max window log */ + } else { + return ZSTD_highbit32((U32)dictAndWindowSize - 1) + 1; + } + } +} + +/** ZSTD_adjustCParams_internal() : + * optimize `cPar` for a specified input (`srcSize` and `dictSize`). + * mostly downsize to reduce memory consumption and initialization latency. + * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known. + * `mode` is the mode for parameter adjustment. See docs for `ZSTD_cParamMode_e`. + * note : `srcSize==0` means 0! + * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */ +static ZSTD_compressionParameters +ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, + unsigned long long srcSize, + size_t dictSize, + ZSTD_cParamMode_e mode, + ZSTD_paramSwitch_e useRowMatchFinder) +{ + const U64 minSrcSize = 513; /* (1<<9) + 1 */ + const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); + assert(ZSTD_checkCParams(cPar)==0); + + /* Cascade the selected strategy down to the next-highest one built into + * this binary. */ +#ifdef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR + if (cPar.strategy == ZSTD_btultra2) { + cPar.strategy = ZSTD_btultra; + } + if (cPar.strategy == ZSTD_btultra) { + cPar.strategy = ZSTD_btopt; + } +#endif +#ifdef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR + if (cPar.strategy == ZSTD_btopt) { + cPar.strategy = ZSTD_btlazy2; + } +#endif +#ifdef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR + if (cPar.strategy == ZSTD_btlazy2) { + cPar.strategy = ZSTD_lazy2; + } +#endif +#ifdef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR + if (cPar.strategy == ZSTD_lazy2) { + cPar.strategy = ZSTD_lazy; + } +#endif +#ifdef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR + if (cPar.strategy == ZSTD_lazy) { + cPar.strategy = ZSTD_greedy; + } +#endif +#ifdef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR + if (cPar.strategy == ZSTD_greedy) { + cPar.strategy = ZSTD_dfast; + } +#endif +#ifdef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR + if (cPar.strategy == ZSTD_dfast) { + cPar.strategy = ZSTD_fast; + cPar.targetLength = 0; + } +#endif + + switch (mode) { + case ZSTD_cpm_unknown: + case ZSTD_cpm_noAttachDict: + /* If we don't know the source size, don't make any + * assumptions about it. We will already have selected + * smaller parameters if a dictionary is in use. + */ + break; + case ZSTD_cpm_createCDict: + /* Assume a small source size when creating a dictionary + * with an unknown source size. + */ + if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN) + srcSize = minSrcSize; + break; + case ZSTD_cpm_attachDict: + /* Dictionary has its own dedicated parameters which have + * already been selected. We are selecting parameters + * for only the source. + */ + dictSize = 0; + break; + default: + assert(0); + break; + } + + /* resize windowLog if input is small enough, to use less memory */ + if ( (srcSize <= maxWindowResize) + && (dictSize <= maxWindowResize) ) { + U32 const tSize = (U32)(srcSize + dictSize); + static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN; + U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN : + ZSTD_highbit32(tSize-1) + 1; + if (cPar.windowLog > srcLog) cPar.windowLog = srcLog; + } + if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) { + U32 const dictAndWindowLog = ZSTD_dictAndWindowLog(cPar.windowLog, (U64)srcSize, (U64)dictSize); + U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); + if (cPar.hashLog > dictAndWindowLog+1) cPar.hashLog = dictAndWindowLog+1; + if (cycleLog > dictAndWindowLog) + cPar.chainLog -= (cycleLog - dictAndWindowLog); + } + + if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) + cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */ + + /* We can't use more than 32 bits of hash in total, so that means that we require: + * (hashLog + 8) <= 32 && (chainLog + 8) <= 32 + */ + if (mode == ZSTD_cpm_createCDict && ZSTD_CDictIndicesAreTagged(&cPar)) { + U32 const maxShortCacheHashLog = 32 - ZSTD_SHORT_CACHE_TAG_BITS; + if (cPar.hashLog > maxShortCacheHashLog) { + cPar.hashLog = maxShortCacheHashLog; + } + if (cPar.chainLog > maxShortCacheHashLog) { + cPar.chainLog = maxShortCacheHashLog; + } + } + + + /* At this point, we aren't 100% sure if we are using the row match finder. + * Unless it is explicitly disabled, conservatively assume that it is enabled. + * In this case it will only be disabled for small sources, so shrinking the + * hash log a little bit shouldn't result in any ratio loss. + */ + if (useRowMatchFinder == ZSTD_ps_auto) + useRowMatchFinder = ZSTD_ps_enable; + + /* We can't hash more than 32-bits in total. So that means that we require: + * (hashLog - rowLog + 8) <= 32 + */ + if (ZSTD_rowMatchFinderUsed(cPar.strategy, useRowMatchFinder)) { + /* Switch to 32-entry rows if searchLog is 5 (or more) */ + U32 const rowLog = BOUNDED(4, cPar.searchLog, 6); + U32 const maxRowHashLog = 32 - ZSTD_ROW_HASH_TAG_BITS; + U32 const maxHashLog = maxRowHashLog + rowLog; + assert(cPar.hashLog >= rowLog); + if (cPar.hashLog > maxHashLog) { + cPar.hashLog = maxHashLog; + } + } + + return cPar; +} + +ZSTD_compressionParameters +ZSTD_adjustCParams(ZSTD_compressionParameters cPar, + unsigned long long srcSize, + size_t dictSize) +{ + cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */ + if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN; + return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto); +} + +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode); +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode); + +static void ZSTD_overrideCParams( + ZSTD_compressionParameters* cParams, + const ZSTD_compressionParameters* overrides) +{ + if (overrides->windowLog) cParams->windowLog = overrides->windowLog; + if (overrides->hashLog) cParams->hashLog = overrides->hashLog; + if (overrides->chainLog) cParams->chainLog = overrides->chainLog; + if (overrides->searchLog) cParams->searchLog = overrides->searchLog; + if (overrides->minMatch) cParams->minMatch = overrides->minMatch; + if (overrides->targetLength) cParams->targetLength = overrides->targetLength; + if (overrides->strategy) cParams->strategy = overrides->strategy; +} + +ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( + const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) +{ + ZSTD_compressionParameters cParams; + if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { + srcSizeHint = CCtxParams->srcSizeHint; + } + cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode); + if (CCtxParams->ldmParams.enableLdm == ZSTD_ps_enable) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; + ZSTD_overrideCParams(&cParams, &CCtxParams->cParams); + assert(!ZSTD_checkCParams(cParams)); + /* srcSizeHint == 0 means 0 */ + return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode, CCtxParams->useRowMatchFinder); +} + +static size_t +ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams, + const ZSTD_paramSwitch_e useRowMatchFinder, + const U32 enableDedicatedDictSearch, + const U32 forCCtx) +{ + /* chain table size should be 0 for fast or row-hash strategies */ + size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder, enableDedicatedDictSearch && !forCCtx) + ? ((size_t)1 << cParams->chainLog) + : 0; + size_t const hSize = ((size_t)1) << cParams->hashLog; + U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; + size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0; + /* We don't use ZSTD_cwksp_alloc_size() here because the tables aren't + * surrounded by redzones in ASAN. */ + size_t const tableSpace = chainSize * sizeof(U32) + + hSize * sizeof(U32) + + h3Size * sizeof(U32); + size_t const optPotentialSpace = + ZSTD_cwksp_aligned_alloc_size((MaxML+1) * sizeof(U32)) + + ZSTD_cwksp_aligned_alloc_size((MaxLL+1) * sizeof(U32)) + + ZSTD_cwksp_aligned_alloc_size((MaxOff+1) * sizeof(U32)) + + ZSTD_cwksp_aligned_alloc_size((1<strategy, useRowMatchFinder) + ? ZSTD_cwksp_aligned_alloc_size(hSize) + : 0; + size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt)) + ? optPotentialSpace + : 0; + size_t const slackSpace = ZSTD_cwksp_slack_space_required(); + + /* tables are guaranteed to be sized in multiples of 64 bytes (or 16 uint32_t) */ + ZSTD_STATIC_ASSERT(ZSTD_HASHLOG_MIN >= 4 && ZSTD_WINDOWLOG_MIN >= 4 && ZSTD_CHAINLOG_MIN >= 4); + assert(useRowMatchFinder != ZSTD_ps_auto); + + DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u", + (U32)chainSize, (U32)hSize, (U32)h3Size); + return tableSpace + optSpace + slackSpace + lazyAdditionalSpace; +} + +/* Helper function for calculating memory requirements. + * Gives a tighter bound than ZSTD_sequenceBound() by taking minMatch into account. */ +static size_t ZSTD_maxNbSeq(size_t blockSize, unsigned minMatch, int useSequenceProducer) { + U32 const divider = (minMatch==3 || useSequenceProducer) ? 3 : 4; + return blockSize / divider; +} + +static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( + const ZSTD_compressionParameters* cParams, + const ldmParams_t* ldmParams, + const int isStatic, + const ZSTD_paramSwitch_e useRowMatchFinder, + const size_t buffInSize, + const size_t buffOutSize, + const U64 pledgedSrcSize, + int useSequenceProducer, + size_t maxBlockSize) +{ + size_t const windowSize = (size_t) BOUNDED(1ULL, 1ULL << cParams->windowLog, pledgedSrcSize); + size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(maxBlockSize), windowSize); + size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useSequenceProducer); + size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) + + ZSTD_cwksp_aligned_alloc_size(maxNbSeq * sizeof(seqDef)) + + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); + size_t const entropySpace = ZSTD_cwksp_alloc_size(ENTROPY_WORKSPACE_SIZE); + size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); + size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1); + + size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams); + size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize); + size_t const ldmSeqSpace = ldmParams->enableLdm == ZSTD_ps_enable ? + ZSTD_cwksp_aligned_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0; + + + size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) + + ZSTD_cwksp_alloc_size(buffOutSize); + + size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0; + + size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize); + size_t const externalSeqSpace = useSequenceProducer + ? ZSTD_cwksp_aligned_alloc_size(maxNbExternalSeq * sizeof(ZSTD_Sequence)) + : 0; + + size_t const neededSpace = + cctxSpace + + entropySpace + + blockStateSpace + + ldmSpace + + ldmSeqSpace + + matchStateSize + + tokenSpace + + bufferSpace + + externalSeqSpace; + + DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace); + return neededSpace; +} + +size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) +{ + ZSTD_compressionParameters const cParams = + ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + ZSTD_paramSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, + &cParams); + + RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); + /* estimateCCtxSize is for one-shot compression. So no buffers should + * be needed. However, we still allocate two 0-sized buffers, which can + * take space under ASAN. */ + return ZSTD_estimateCCtxSize_usingCCtxParams_internal( + &cParams, ¶ms->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize); +} + +size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) +{ + ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); + if (ZSTD_rowMatchFinderSupported(cParams.strategy)) { + /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */ + size_t noRowCCtxSize; + size_t rowCCtxSize; + initialParams.useRowMatchFinder = ZSTD_ps_disable; + noRowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams); + initialParams.useRowMatchFinder = ZSTD_ps_enable; + rowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams); + return MAX(noRowCCtxSize, rowCCtxSize); + } else { + return ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams); + } +} + +static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) +{ + int tier = 0; + size_t largestSize = 0; + static const unsigned long long srcSizeTiers[4] = {16 KB, 128 KB, 256 KB, ZSTD_CONTENTSIZE_UNKNOWN}; + for (; tier < 4; ++tier) { + /* Choose the set of cParams for a given level across all srcSizes that give the largest cctxSize */ + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict); + largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams(cParams), largestSize); + } + return largestSize; +} + +size_t ZSTD_estimateCCtxSize(int compressionLevel) +{ + int level; + size_t memBudget = 0; + for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) { + /* Ensure monotonically increasing memory usage as compression level increases */ + size_t const newMB = ZSTD_estimateCCtxSize_internal(level); + if (newMB > memBudget) memBudget = newMB; + } + return memBudget; +} + +size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) +{ + RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); + { ZSTD_compressionParameters const cParams = + ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), (size_t)1 << cParams.windowLog); + size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered) + ? ((size_t)1 << cParams.windowLog) + blockSize + : 0; + size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered) + ? ZSTD_compressBound(blockSize) + 1 + : 0; + ZSTD_paramSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, ¶ms->cParams); + + return ZSTD_estimateCCtxSize_usingCCtxParams_internal( + &cParams, ¶ms->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize, + ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize); + } +} + +size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) +{ + ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams); + if (ZSTD_rowMatchFinderSupported(cParams.strategy)) { + /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */ + size_t noRowCCtxSize; + size_t rowCCtxSize; + initialParams.useRowMatchFinder = ZSTD_ps_disable; + noRowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams); + initialParams.useRowMatchFinder = ZSTD_ps_enable; + rowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams); + return MAX(noRowCCtxSize, rowCCtxSize); + } else { + return ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams); + } +} + +static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) +{ + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + return ZSTD_estimateCStreamSize_usingCParams(cParams); +} + +size_t ZSTD_estimateCStreamSize(int compressionLevel) +{ + int level; + size_t memBudget = 0; + for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) { + size_t const newMB = ZSTD_estimateCStreamSize_internal(level); + if (newMB > memBudget) memBudget = newMB; + } + return memBudget; +} + +/* ZSTD_getFrameProgression(): + * tells how much data has been consumed (input) and produced (output) for current frame. + * able to count progression inside worker threads (non-blocking mode). + */ +ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx) +{ +#ifdef ZSTD_MULTITHREAD + if (cctx->appliedParams.nbWorkers > 0) { + return ZSTDMT_getFrameProgression(cctx->mtctx); + } +#endif + { ZSTD_frameProgression fp; + size_t const buffered = (cctx->inBuff == NULL) ? 0 : + cctx->inBuffPos - cctx->inToCompress; + if (buffered) assert(cctx->inBuffPos >= cctx->inToCompress); + assert(buffered <= ZSTD_BLOCKSIZE_MAX); + fp.ingested = cctx->consumedSrcSize + buffered; + fp.consumed = cctx->consumedSrcSize; + fp.produced = cctx->producedCSize; + fp.flushed = cctx->producedCSize; /* simplified; some data might still be left within streaming output buffer */ + fp.currentJobID = 0; + fp.nbActiveWorkers = 0; + return fp; +} } + +/*! ZSTD_toFlushNow() + * Only useful for multithreading scenarios currently (nbWorkers >= 1). + */ +size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx) +{ +#ifdef ZSTD_MULTITHREAD + if (cctx->appliedParams.nbWorkers > 0) { + return ZSTDMT_toFlushNow(cctx->mtctx); + } +#endif + (void)cctx; + return 0; /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */ +} + +static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1, + ZSTD_compressionParameters cParams2) +{ + (void)cParams1; + (void)cParams2; + assert(cParams1.windowLog == cParams2.windowLog); + assert(cParams1.chainLog == cParams2.chainLog); + assert(cParams1.hashLog == cParams2.hashLog); + assert(cParams1.searchLog == cParams2.searchLog); + assert(cParams1.minMatch == cParams2.minMatch); + assert(cParams1.targetLength == cParams2.targetLength); + assert(cParams1.strategy == cParams2.strategy); +} + +void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs) +{ + int i; + for (i = 0; i < ZSTD_REP_NUM; ++i) + bs->rep[i] = repStartValue[i]; + bs->entropy.huf.repeatMode = HUF_repeat_none; + bs->entropy.fse.offcode_repeatMode = FSE_repeat_none; + bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none; + bs->entropy.fse.litlength_repeatMode = FSE_repeat_none; +} + +/*! ZSTD_invalidateMatchState() + * Invalidate all the matches in the match finder tables. + * Requires nextSrc and base to be set (can be NULL). + */ +static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms) +{ + ZSTD_window_clear(&ms->window); + + ms->nextToUpdate = ms->window.dictLimit; + ms->loadedDictEnd = 0; + ms->opt.litLengthSum = 0; /* force reset of btopt stats */ + ms->dictMatchState = NULL; +} + +/** + * Controls, for this matchState reset, whether the tables need to be cleared / + * prepared for the coming compression (ZSTDcrp_makeClean), or whether the + * tables can be left unclean (ZSTDcrp_leaveDirty), because we know that a + * subsequent operation will overwrite the table space anyways (e.g., copying + * the matchState contents in from a CDict). + */ +typedef enum { + ZSTDcrp_makeClean, + ZSTDcrp_leaveDirty +} ZSTD_compResetPolicy_e; + +/** + * Controls, for this matchState reset, whether indexing can continue where it + * left off (ZSTDirp_continue), or whether it needs to be restarted from zero + * (ZSTDirp_reset). + */ +typedef enum { + ZSTDirp_continue, + ZSTDirp_reset +} ZSTD_indexResetPolicy_e; + +typedef enum { + ZSTD_resetTarget_CDict, + ZSTD_resetTarget_CCtx +} ZSTD_resetTarget_e; + +/* Mixes bits in a 64 bits in a value, based on XXH3_rrmxmx */ +static U64 ZSTD_bitmix(U64 val, U64 len) { + val ^= ZSTD_rotateRight_U64(val, 49) ^ ZSTD_rotateRight_U64(val, 24); + val *= 0x9FB21C651E98DF25ULL; + val ^= (val >> 35) + len ; + val *= 0x9FB21C651E98DF25ULL; + return val ^ (val >> 28); +} + +/* Mixes in the hashSalt and hashSaltEntropy to create a new hashSalt */ +static void ZSTD_advanceHashSalt(ZSTD_matchState_t* ms) { + ms->hashSalt = ZSTD_bitmix(ms->hashSalt, 8) ^ ZSTD_bitmix((U64) ms->hashSaltEntropy, 4); +} + +static size_t +ZSTD_reset_matchState(ZSTD_matchState_t* ms, + ZSTD_cwksp* ws, + const ZSTD_compressionParameters* cParams, + const ZSTD_paramSwitch_e useRowMatchFinder, + const ZSTD_compResetPolicy_e crp, + const ZSTD_indexResetPolicy_e forceResetIndex, + const ZSTD_resetTarget_e forWho) +{ + /* disable chain table allocation for fast or row-based strategies */ + size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder, + ms->dedicatedDictSearch && (forWho == ZSTD_resetTarget_CDict)) + ? ((size_t)1 << cParams->chainLog) + : 0; + size_t const hSize = ((size_t)1) << cParams->hashLog; + U32 const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; + size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0; + + DEBUGLOG(4, "reset indices : %u", forceResetIndex == ZSTDirp_reset); + assert(useRowMatchFinder != ZSTD_ps_auto); + if (forceResetIndex == ZSTDirp_reset) { + ZSTD_window_init(&ms->window); + ZSTD_cwksp_mark_tables_dirty(ws); + } + + ms->hashLog3 = hashLog3; + ms->lazySkipping = 0; + + ZSTD_invalidateMatchState(ms); + + assert(!ZSTD_cwksp_reserve_failed(ws)); /* check that allocation hasn't already failed */ + + ZSTD_cwksp_clear_tables(ws); + + DEBUGLOG(5, "reserving table space"); + /* table Space */ + ms->hashTable = (U32*)ZSTD_cwksp_reserve_table(ws, hSize * sizeof(U32)); + ms->chainTable = (U32*)ZSTD_cwksp_reserve_table(ws, chainSize * sizeof(U32)); + ms->hashTable3 = (U32*)ZSTD_cwksp_reserve_table(ws, h3Size * sizeof(U32)); + RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation, + "failed a workspace allocation in ZSTD_reset_matchState"); + + DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_leaveDirty); + if (crp!=ZSTDcrp_leaveDirty) { + /* reset tables only */ + ZSTD_cwksp_clean_tables(ws); + } + + if (ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)) { + /* Row match finder needs an additional table of hashes ("tags") */ + size_t const tagTableSize = hSize; + /* We want to generate a new salt in case we reset a Cctx, but we always want to use + * 0 when we reset a Cdict */ + if(forWho == ZSTD_resetTarget_CCtx) { + ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned_init_once(ws, tagTableSize); + ZSTD_advanceHashSalt(ms); + } else { + /* When we are not salting we want to always memset the memory */ + ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned(ws, tagTableSize); + ZSTD_memset(ms->tagTable, 0, tagTableSize); + ms->hashSalt = 0; + } + { /* Switch to 32-entry rows if searchLog is 5 (or more) */ + U32 const rowLog = BOUNDED(4, cParams->searchLog, 6); + assert(cParams->hashLog >= rowLog); + ms->rowHashLog = cParams->hashLog - rowLog; + } + } + + /* opt parser space */ + if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) { + DEBUGLOG(4, "reserving optimal parser space"); + ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (1<opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxLL+1) * sizeof(unsigned)); + ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxML+1) * sizeof(unsigned)); + ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxOff+1) * sizeof(unsigned)); + ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_match_t)); + ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t)); + } + + ms->cParams = *cParams; + + RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation, + "failed a workspace allocation in ZSTD_reset_matchState"); + return 0; +} + +/* ZSTD_indexTooCloseToMax() : + * minor optimization : prefer memset() rather than reduceIndex() + * which is measurably slow in some circumstances (reported for Visual Studio). + * Works when re-using a context for a lot of smallish inputs : + * if all inputs are smaller than ZSTD_INDEXOVERFLOW_MARGIN, + * memset() will be triggered before reduceIndex(). + */ +#define ZSTD_INDEXOVERFLOW_MARGIN (16 MB) +static int ZSTD_indexTooCloseToMax(ZSTD_window_t w) +{ + return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN); +} + +/** ZSTD_dictTooBig(): + * When dictionaries are larger than ZSTD_CHUNKSIZE_MAX they can't be loaded in + * one go generically. So we ensure that in that case we reset the tables to zero, + * so that we can load as much of the dictionary as possible. + */ +static int ZSTD_dictTooBig(size_t const loadedDictSize) +{ + return loadedDictSize > ZSTD_CHUNKSIZE_MAX; +} + +/*! ZSTD_resetCCtx_internal() : + * @param loadedDictSize The size of the dictionary to be loaded + * into the context, if any. If no dictionary is used, or the + * dictionary is being attached / copied, then pass 0. + * note : `params` are assumed fully validated at this stage. + */ +static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, + ZSTD_CCtx_params const* params, + U64 const pledgedSrcSize, + size_t const loadedDictSize, + ZSTD_compResetPolicy_e const crp, + ZSTD_buffered_policy_e const zbuff) +{ + ZSTD_cwksp* const ws = &zc->workspace; + DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u, useRowMatchFinder=%d useBlockSplitter=%d", + (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder, (int)params->useBlockSplitter); + assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); + + zc->isFirstBlock = 1; + + /* Set applied params early so we can modify them for LDM, + * and point params at the applied params. + */ + zc->appliedParams = *params; + params = &zc->appliedParams; + + assert(params->useRowMatchFinder != ZSTD_ps_auto); + assert(params->useBlockSplitter != ZSTD_ps_auto); + assert(params->ldmParams.enableLdm != ZSTD_ps_auto); + assert(params->maxBlockSize != 0); + if (params->ldmParams.enableLdm == ZSTD_ps_enable) { + /* Adjust long distance matching parameters */ + ZSTD_ldm_adjustParameters(&zc->appliedParams.ldmParams, ¶ms->cParams); + assert(params->ldmParams.hashLog >= params->ldmParams.bucketSizeLog); + assert(params->ldmParams.hashRateLog < 32); + } + + { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params->cParams.windowLog), pledgedSrcSize)); + size_t const blockSize = MIN(params->maxBlockSize, windowSize); + size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, ZSTD_hasExtSeqProd(params)); + size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered) + ? ZSTD_compressBound(blockSize) + 1 + : 0; + size_t const buffInSize = (zbuff == ZSTDb_buffered && params->inBufferMode == ZSTD_bm_buffered) + ? windowSize + blockSize + : 0; + size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize); + + int const indexTooClose = ZSTD_indexTooCloseToMax(zc->blockState.matchState.window); + int const dictTooBig = ZSTD_dictTooBig(loadedDictSize); + ZSTD_indexResetPolicy_e needsIndexReset = + (indexTooClose || dictTooBig || !zc->initialized) ? ZSTDirp_reset : ZSTDirp_continue; + + size_t const neededSpace = + ZSTD_estimateCCtxSize_usingCCtxParams_internal( + ¶ms->cParams, ¶ms->ldmParams, zc->staticSize != 0, params->useRowMatchFinder, + buffInSize, buffOutSize, pledgedSrcSize, ZSTD_hasExtSeqProd(params), params->maxBlockSize); + + FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!"); + + if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0); + + { /* Check if workspace is large enough, alloc a new one if needed */ + int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace; + int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace); + int resizeWorkspace = workspaceTooSmall || workspaceWasteful; + DEBUGLOG(4, "Need %zu B workspace", neededSpace); + DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize); + + if (resizeWorkspace) { + DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB", + ZSTD_cwksp_sizeof(ws) >> 10, + neededSpace >> 10); + + RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize"); + + needsIndexReset = ZSTDirp_reset; + + ZSTD_cwksp_free(ws, zc->customMem); + FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem), ""); + + DEBUGLOG(5, "reserving object space"); + /* Statically sized space. + * entropyWorkspace never moves, + * though prev/next block swap places */ + assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t))); + zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); + RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock"); + zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); + RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock"); + zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE); + RETURN_ERROR_IF(zc->entropyWorkspace == NULL, memory_allocation, "couldn't allocate entropyWorkspace"); + } } + + ZSTD_cwksp_clear(ws); + + /* init params */ + zc->blockState.matchState.cParams = params->cParams; + zc->blockState.matchState.prefetchCDictTables = params->prefetchCDictTables == ZSTD_ps_enable; + zc->pledgedSrcSizePlusOne = pledgedSrcSize+1; + zc->consumedSrcSize = 0; + zc->producedCSize = 0; + if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN) + zc->appliedParams.fParams.contentSizeFlag = 0; + DEBUGLOG(4, "pledged content size : %u ; flag : %u", + (unsigned)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag); + zc->blockSize = blockSize; + + XXH64_reset(&zc->xxhState, 0); + zc->stage = ZSTDcs_init; + zc->dictID = 0; + zc->dictContentSize = 0; + + ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock); + + FORWARD_IF_ERROR(ZSTD_reset_matchState( + &zc->blockState.matchState, + ws, + ¶ms->cParams, + params->useRowMatchFinder, + crp, + needsIndexReset, + ZSTD_resetTarget_CCtx), ""); + + zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned(ws, maxNbSeq * sizeof(seqDef)); + + /* ldm hash table */ + if (params->ldmParams.enableLdm == ZSTD_ps_enable) { + /* TODO: avoid memset? */ + size_t const ldmHSize = ((size_t)1) << params->ldmParams.hashLog; + zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t)); + ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t)); + zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq)); + zc->maxNbLdmSequences = maxNbLdmSeq; + + ZSTD_window_init(&zc->ldmState.window); + zc->ldmState.loadedDictEnd = 0; + } + + /* reserve space for block-level external sequences */ + if (ZSTD_hasExtSeqProd(params)) { + size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize); + zc->extSeqBufCapacity = maxNbExternalSeq; + zc->extSeqBuf = + (ZSTD_Sequence*)ZSTD_cwksp_reserve_aligned(ws, maxNbExternalSeq * sizeof(ZSTD_Sequence)); + } + + /* buffers */ + + /* ZSTD_wildcopy() is used to copy into the literals buffer, + * so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes. + */ + zc->seqStore.litStart = ZSTD_cwksp_reserve_buffer(ws, blockSize + WILDCOPY_OVERLENGTH); + zc->seqStore.maxNbLit = blockSize; + + zc->bufferedPolicy = zbuff; + zc->inBuffSize = buffInSize; + zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize); + zc->outBuffSize = buffOutSize; + zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize); + + /* ldm bucketOffsets table */ + if (params->ldmParams.enableLdm == ZSTD_ps_enable) { + /* TODO: avoid memset? */ + size_t const numBuckets = + ((size_t)1) << (params->ldmParams.hashLog - + params->ldmParams.bucketSizeLog); + zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, numBuckets); + ZSTD_memset(zc->ldmState.bucketOffsets, 0, numBuckets); + } + + /* sequences storage */ + ZSTD_referenceExternalSequences(zc, NULL, 0); + zc->seqStore.maxNbSeq = maxNbSeq; + zc->seqStore.llCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE)); + zc->seqStore.mlCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE)); + zc->seqStore.ofCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE)); + + DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws)); + assert(ZSTD_cwksp_estimated_space_within_bounds(ws, neededSpace)); + + zc->initialized = 1; + + return 0; + } +} + +/* ZSTD_invalidateRepCodes() : + * ensures next compression will not use repcodes from previous block. + * Note : only works with regular variant; + * do not use with extDict variant ! */ +void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) { + int i; + for (i=0; iblockState.prevCBlock->rep[i] = 0; + assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window)); +} + +/* These are the approximate sizes for each strategy past which copying the + * dictionary tables into the working context is faster than using them + * in-place. + */ +static const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = { + 8 KB, /* unused */ + 8 KB, /* ZSTD_fast */ + 16 KB, /* ZSTD_dfast */ + 32 KB, /* ZSTD_greedy */ + 32 KB, /* ZSTD_lazy */ + 32 KB, /* ZSTD_lazy2 */ + 32 KB, /* ZSTD_btlazy2 */ + 32 KB, /* ZSTD_btopt */ + 8 KB, /* ZSTD_btultra */ + 8 KB /* ZSTD_btultra2 */ +}; + +static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict, + const ZSTD_CCtx_params* params, + U64 pledgedSrcSize) +{ + size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy]; + int const dedicatedDictSearch = cdict->matchState.dedicatedDictSearch; + return dedicatedDictSearch + || ( ( pledgedSrcSize <= cutoff + || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN + || params->attachDictPref == ZSTD_dictForceAttach ) + && params->attachDictPref != ZSTD_dictForceCopy + && !params->forceWindow ); /* dictMatchState isn't correctly + * handled in _enforceMaxDist */ +} + +static size_t +ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, + const ZSTD_CDict* cdict, + ZSTD_CCtx_params params, + U64 pledgedSrcSize, + ZSTD_buffered_policy_e zbuff) +{ + DEBUGLOG(4, "ZSTD_resetCCtx_byAttachingCDict() pledgedSrcSize=%llu", + (unsigned long long)pledgedSrcSize); + { + ZSTD_compressionParameters adjusted_cdict_cParams = cdict->matchState.cParams; + unsigned const windowLog = params.cParams.windowLog; + assert(windowLog != 0); + /* Resize working context table params for input only, since the dict + * has its own tables. */ + /* pledgedSrcSize == 0 means 0! */ + + if (cdict->matchState.dedicatedDictSearch) { + ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_cParams); + } + + params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize, + cdict->dictContentSize, ZSTD_cpm_attachDict, + params.useRowMatchFinder); + params.cParams.windowLog = windowLog; + params.useRowMatchFinder = cdict->useRowMatchFinder; /* cdict overrides */ + FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, + /* loadedDictSize */ 0, + ZSTDcrp_makeClean, zbuff), ""); + assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_cParams.strategy); + } + + { const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc + - cdict->matchState.window.base); + const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit; + if (cdictLen == 0) { + /* don't even attach dictionaries with no contents */ + DEBUGLOG(4, "skipping attaching empty dictionary"); + } else { + DEBUGLOG(4, "attaching dictionary into context"); + cctx->blockState.matchState.dictMatchState = &cdict->matchState; + + /* prep working match state so dict matches never have negative indices + * when they are translated to the working context's index space. */ + if (cctx->blockState.matchState.window.dictLimit < cdictEnd) { + cctx->blockState.matchState.window.nextSrc = + cctx->blockState.matchState.window.base + cdictEnd; + ZSTD_window_clear(&cctx->blockState.matchState.window); + } + /* loadedDictEnd is expressed within the referential of the active context */ + cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit; + } } + + cctx->dictID = cdict->dictID; + cctx->dictContentSize = cdict->dictContentSize; + + /* copy block state */ + ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); + + return 0; +} + +static void ZSTD_copyCDictTableIntoCCtx(U32* dst, U32 const* src, size_t tableSize, + ZSTD_compressionParameters const* cParams) { + if (ZSTD_CDictIndicesAreTagged(cParams)){ + /* Remove tags from the CDict table if they are present. + * See docs on "short cache" in zstd_compress_internal.h for context. */ + size_t i; + for (i = 0; i < tableSize; i++) { + U32 const taggedIndex = src[i]; + U32 const index = taggedIndex >> ZSTD_SHORT_CACHE_TAG_BITS; + dst[i] = index; + } + } else { + ZSTD_memcpy(dst, src, tableSize * sizeof(U32)); + } +} + +static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, + const ZSTD_CDict* cdict, + ZSTD_CCtx_params params, + U64 pledgedSrcSize, + ZSTD_buffered_policy_e zbuff) +{ + const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams; + + assert(!cdict->matchState.dedicatedDictSearch); + DEBUGLOG(4, "ZSTD_resetCCtx_byCopyingCDict() pledgedSrcSize=%llu", + (unsigned long long)pledgedSrcSize); + + { unsigned const windowLog = params.cParams.windowLog; + assert(windowLog != 0); + /* Copy only compression parameters related to tables. */ + params.cParams = *cdict_cParams; + params.cParams.windowLog = windowLog; + params.useRowMatchFinder = cdict->useRowMatchFinder; + FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize, + /* loadedDictSize */ 0, + ZSTDcrp_leaveDirty, zbuff), ""); + assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy); + assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog); + assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog); + } + + ZSTD_cwksp_mark_tables_dirty(&cctx->workspace); + assert(params.useRowMatchFinder != ZSTD_ps_auto); + + /* copy tables */ + { size_t const chainSize = ZSTD_allocateChainTable(cdict_cParams->strategy, cdict->useRowMatchFinder, 0 /* DDS guaranteed disabled */) + ? ((size_t)1 << cdict_cParams->chainLog) + : 0; + size_t const hSize = (size_t)1 << cdict_cParams->hashLog; + + ZSTD_copyCDictTableIntoCCtx(cctx->blockState.matchState.hashTable, + cdict->matchState.hashTable, + hSize, cdict_cParams); + + /* Do not copy cdict's chainTable if cctx has parameters such that it would not use chainTable */ + if (ZSTD_allocateChainTable(cctx->appliedParams.cParams.strategy, cctx->appliedParams.useRowMatchFinder, 0 /* forDDSDict */)) { + ZSTD_copyCDictTableIntoCCtx(cctx->blockState.matchState.chainTable, + cdict->matchState.chainTable, + chainSize, cdict_cParams); + } + /* copy tag table */ + if (ZSTD_rowMatchFinderUsed(cdict_cParams->strategy, cdict->useRowMatchFinder)) { + size_t const tagTableSize = hSize; + ZSTD_memcpy(cctx->blockState.matchState.tagTable, + cdict->matchState.tagTable, + tagTableSize); + cctx->blockState.matchState.hashSalt = cdict->matchState.hashSalt; + } + } + + /* Zero the hashTable3, since the cdict never fills it */ + { int const h3log = cctx->blockState.matchState.hashLog3; + size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; + assert(cdict->matchState.hashLog3 == 0); + ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32)); + } + + ZSTD_cwksp_mark_tables_clean(&cctx->workspace); + + /* copy dictionary offsets */ + { ZSTD_matchState_t const* srcMatchState = &cdict->matchState; + ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState; + dstMatchState->window = srcMatchState->window; + dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; + dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; + } + + cctx->dictID = cdict->dictID; + cctx->dictContentSize = cdict->dictContentSize; + + /* copy block state */ + ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); + + return 0; +} + +/* We have a choice between copying the dictionary context into the working + * context, or referencing the dictionary context from the working context + * in-place. We decide here which strategy to use. */ +static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx, + const ZSTD_CDict* cdict, + const ZSTD_CCtx_params* params, + U64 pledgedSrcSize, + ZSTD_buffered_policy_e zbuff) +{ + + DEBUGLOG(4, "ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)", + (unsigned)pledgedSrcSize); + + if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) { + return ZSTD_resetCCtx_byAttachingCDict( + cctx, cdict, *params, pledgedSrcSize, zbuff); + } else { + return ZSTD_resetCCtx_byCopyingCDict( + cctx, cdict, *params, pledgedSrcSize, zbuff); + } +} + +/*! ZSTD_copyCCtx_internal() : + * Duplicate an existing context `srcCCtx` into another one `dstCCtx`. + * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()). + * The "context", in this case, refers to the hash and chain tables, + * entropy tables, and dictionary references. + * `windowLog` value is enforced if != 0, otherwise value is copied from srcCCtx. + * @return : 0, or an error code */ +static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, + const ZSTD_CCtx* srcCCtx, + ZSTD_frameParameters fParams, + U64 pledgedSrcSize, + ZSTD_buffered_policy_e zbuff) +{ + RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong, + "Can't copy a ctx that's not in init stage."); + DEBUGLOG(5, "ZSTD_copyCCtx_internal"); + ZSTD_memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); + { ZSTD_CCtx_params params = dstCCtx->requestedParams; + /* Copy only compression parameters related to tables. */ + params.cParams = srcCCtx->appliedParams.cParams; + assert(srcCCtx->appliedParams.useRowMatchFinder != ZSTD_ps_auto); + assert(srcCCtx->appliedParams.useBlockSplitter != ZSTD_ps_auto); + assert(srcCCtx->appliedParams.ldmParams.enableLdm != ZSTD_ps_auto); + params.useRowMatchFinder = srcCCtx->appliedParams.useRowMatchFinder; + params.useBlockSplitter = srcCCtx->appliedParams.useBlockSplitter; + params.ldmParams = srcCCtx->appliedParams.ldmParams; + params.fParams = fParams; + params.maxBlockSize = srcCCtx->appliedParams.maxBlockSize; + ZSTD_resetCCtx_internal(dstCCtx, ¶ms, pledgedSrcSize, + /* loadedDictSize */ 0, + ZSTDcrp_leaveDirty, zbuff); + assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog); + assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy); + assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog); + assert(dstCCtx->appliedParams.cParams.chainLog == srcCCtx->appliedParams.cParams.chainLog); + assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3); + } + + ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace); + + /* copy tables */ + { size_t const chainSize = ZSTD_allocateChainTable(srcCCtx->appliedParams.cParams.strategy, + srcCCtx->appliedParams.useRowMatchFinder, + 0 /* forDDSDict */) + ? ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog) + : 0; + size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog; + int const h3log = srcCCtx->blockState.matchState.hashLog3; + size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; + + ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable, + srcCCtx->blockState.matchState.hashTable, + hSize * sizeof(U32)); + ZSTD_memcpy(dstCCtx->blockState.matchState.chainTable, + srcCCtx->blockState.matchState.chainTable, + chainSize * sizeof(U32)); + ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable3, + srcCCtx->blockState.matchState.hashTable3, + h3Size * sizeof(U32)); + } + + ZSTD_cwksp_mark_tables_clean(&dstCCtx->workspace); + + /* copy dictionary offsets */ + { + const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState; + ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState; + dstMatchState->window = srcMatchState->window; + dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; + dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; + } + dstCCtx->dictID = srcCCtx->dictID; + dstCCtx->dictContentSize = srcCCtx->dictContentSize; + + /* copy block state */ + ZSTD_memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock)); + + return 0; +} + +/*! ZSTD_copyCCtx() : + * Duplicate an existing context `srcCCtx` into another one `dstCCtx`. + * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()). + * pledgedSrcSize==0 means "unknown". +* @return : 0, or an error code */ +size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize) +{ + ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; + ZSTD_buffered_policy_e const zbuff = srcCCtx->bufferedPolicy; + ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1); + if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; + fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN); + + return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx, + fParams, pledgedSrcSize, + zbuff); +} + + +#define ZSTD_ROWSIZE 16 +/*! ZSTD_reduceTable() : + * reduce table indexes by `reducerValue`, or squash to zero. + * PreserveMark preserves "unsorted mark" for btlazy2 strategy. + * It must be set to a clear 0/1 value, to remove branch during inlining. + * Presume table size is a multiple of ZSTD_ROWSIZE + * to help auto-vectorization */ +FORCE_INLINE_TEMPLATE void +ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerValue, int const preserveMark) +{ + int const nbRows = (int)size / ZSTD_ROWSIZE; + int cellNb = 0; + int rowNb; + /* Protect special index values < ZSTD_WINDOW_START_INDEX. */ + U32 const reducerThreshold = reducerValue + ZSTD_WINDOW_START_INDEX; + assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */ + assert(size < (1U<<31)); /* can be casted to int */ + +#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) + /* To validate that the table reuse logic is sound, and that we don't + * access table space that we haven't cleaned, we re-"poison" the table + * space every time we mark it dirty. + * + * This function however is intended to operate on those dirty tables and + * re-clean them. So when this function is used correctly, we can unpoison + * the memory it operated on. This introduces a blind spot though, since + * if we now try to operate on __actually__ poisoned memory, we will not + * detect that. */ + __msan_unpoison(table, size * sizeof(U32)); +#endif + + for (rowNb=0 ; rowNb < nbRows ; rowNb++) { + int column; + for (column=0; columncParams.hashLog; + ZSTD_reduceTable(ms->hashTable, hSize, reducerValue); + } + + if (ZSTD_allocateChainTable(params->cParams.strategy, params->useRowMatchFinder, (U32)ms->dedicatedDictSearch)) { + U32 const chainSize = (U32)1 << params->cParams.chainLog; + if (params->cParams.strategy == ZSTD_btlazy2) + ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue); + else + ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue); + } + + if (ms->hashLog3) { + U32 const h3Size = (U32)1 << ms->hashLog3; + ZSTD_reduceTable(ms->hashTable3, h3Size, reducerValue); + } +} + + +/*-******************************************************* +* Block entropic compression +*********************************************************/ + +/* See doc/zstd_compression_format.md for detailed format description */ + +int ZSTD_seqToCodes(const seqStore_t* seqStorePtr) +{ + const seqDef* const sequences = seqStorePtr->sequencesStart; + BYTE* const llCodeTable = seqStorePtr->llCode; + BYTE* const ofCodeTable = seqStorePtr->ofCode; + BYTE* const mlCodeTable = seqStorePtr->mlCode; + U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); + U32 u; + int longOffsets = 0; + assert(nbSeq <= seqStorePtr->maxNbSeq); + for (u=0; u= STREAM_ACCUMULATOR_MIN)); + if (MEM_32bits() && ofCode >= STREAM_ACCUMULATOR_MIN) + longOffsets = 1; + } + if (seqStorePtr->longLengthType==ZSTD_llt_literalLength) + llCodeTable[seqStorePtr->longLengthPos] = MaxLL; + if (seqStorePtr->longLengthType==ZSTD_llt_matchLength) + mlCodeTable[seqStorePtr->longLengthPos] = MaxML; + return longOffsets; +} + +/* ZSTD_useTargetCBlockSize(): + * Returns if target compressed block size param is being used. + * If used, compression will do best effort to make a compressed block size to be around targetCBlockSize. + * Returns 1 if true, 0 otherwise. */ +static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams) +{ + DEBUGLOG(5, "ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)", cctxParams->targetCBlockSize); + return (cctxParams->targetCBlockSize != 0); +} + +/* ZSTD_blockSplitterEnabled(): + * Returns if block splitting param is being used + * If used, compression will do best effort to split a block in order to improve compression ratio. + * At the time this function is called, the parameter must be finalized. + * Returns 1 if true, 0 otherwise. */ +static int ZSTD_blockSplitterEnabled(ZSTD_CCtx_params* cctxParams) +{ + DEBUGLOG(5, "ZSTD_blockSplitterEnabled (useBlockSplitter=%d)", cctxParams->useBlockSplitter); + assert(cctxParams->useBlockSplitter != ZSTD_ps_auto); + return (cctxParams->useBlockSplitter == ZSTD_ps_enable); +} + +/* Type returned by ZSTD_buildSequencesStatistics containing finalized symbol encoding types + * and size of the sequences statistics + */ +typedef struct { + U32 LLtype; + U32 Offtype; + U32 MLtype; + size_t size; + size_t lastCountSize; /* Accounts for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */ + int longOffsets; +} ZSTD_symbolEncodingTypeStats_t; + +/* ZSTD_buildSequencesStatistics(): + * Returns a ZSTD_symbolEncodingTypeStats_t, or a zstd error code in the `size` field. + * Modifies `nextEntropy` to have the appropriate values as a side effect. + * nbSeq must be greater than 0. + * + * entropyWkspSize must be of size at least ENTROPY_WORKSPACE_SIZE - (MaxSeq + 1)*sizeof(U32) + */ +static ZSTD_symbolEncodingTypeStats_t +ZSTD_buildSequencesStatistics( + const seqStore_t* seqStorePtr, size_t nbSeq, + const ZSTD_fseCTables_t* prevEntropy, ZSTD_fseCTables_t* nextEntropy, + BYTE* dst, const BYTE* const dstEnd, + ZSTD_strategy strategy, unsigned* countWorkspace, + void* entropyWorkspace, size_t entropyWkspSize) +{ + BYTE* const ostart = dst; + const BYTE* const oend = dstEnd; + BYTE* op = ostart; + FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable; + FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable; + FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable; + const BYTE* const ofCodeTable = seqStorePtr->ofCode; + const BYTE* const llCodeTable = seqStorePtr->llCode; + const BYTE* const mlCodeTable = seqStorePtr->mlCode; + ZSTD_symbolEncodingTypeStats_t stats; + + stats.lastCountSize = 0; + /* convert length/distances into codes */ + stats.longOffsets = ZSTD_seqToCodes(seqStorePtr); + assert(op <= oend); + assert(nbSeq != 0); /* ZSTD_selectEncodingType() divides by nbSeq */ + /* build CTable for Literal Lengths */ + { unsigned max = MaxLL; + size_t const mostFrequent = HIST_countFast_wksp(countWorkspace, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ + DEBUGLOG(5, "Building LL table"); + nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode; + stats.LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode, + countWorkspace, max, mostFrequent, nbSeq, + LLFSELog, prevEntropy->litlengthCTable, + LL_defaultNorm, LL_defaultNormLog, + ZSTD_defaultAllowed, strategy); + assert(set_basic < set_compressed && set_rle < set_compressed); + assert(!(stats.LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ + { size_t const countSize = ZSTD_buildCTable( + op, (size_t)(oend - op), + CTable_LitLength, LLFSELog, (symbolEncodingType_e)stats.LLtype, + countWorkspace, max, llCodeTable, nbSeq, + LL_defaultNorm, LL_defaultNormLog, MaxLL, + prevEntropy->litlengthCTable, + sizeof(prevEntropy->litlengthCTable), + entropyWorkspace, entropyWkspSize); + if (ZSTD_isError(countSize)) { + DEBUGLOG(3, "ZSTD_buildCTable for LitLens failed"); + stats.size = countSize; + return stats; + } + if (stats.LLtype == set_compressed) + stats.lastCountSize = countSize; + op += countSize; + assert(op <= oend); + } } + /* build CTable for Offsets */ + { unsigned max = MaxOff; + size_t const mostFrequent = HIST_countFast_wksp( + countWorkspace, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ + /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */ + ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed; + DEBUGLOG(5, "Building OF table"); + nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode; + stats.Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode, + countWorkspace, max, mostFrequent, nbSeq, + OffFSELog, prevEntropy->offcodeCTable, + OF_defaultNorm, OF_defaultNormLog, + defaultPolicy, strategy); + assert(!(stats.Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */ + { size_t const countSize = ZSTD_buildCTable( + op, (size_t)(oend - op), + CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)stats.Offtype, + countWorkspace, max, ofCodeTable, nbSeq, + OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, + prevEntropy->offcodeCTable, + sizeof(prevEntropy->offcodeCTable), + entropyWorkspace, entropyWkspSize); + if (ZSTD_isError(countSize)) { + DEBUGLOG(3, "ZSTD_buildCTable for Offsets failed"); + stats.size = countSize; + return stats; + } + if (stats.Offtype == set_compressed) + stats.lastCountSize = countSize; + op += countSize; + assert(op <= oend); + } } + /* build CTable for MatchLengths */ + { unsigned max = MaxML; + size_t const mostFrequent = HIST_countFast_wksp( + countWorkspace, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ + DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op)); + nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode; + stats.MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode, + countWorkspace, max, mostFrequent, nbSeq, + MLFSELog, prevEntropy->matchlengthCTable, + ML_defaultNorm, ML_defaultNormLog, + ZSTD_defaultAllowed, strategy); + assert(!(stats.MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ + { size_t const countSize = ZSTD_buildCTable( + op, (size_t)(oend - op), + CTable_MatchLength, MLFSELog, (symbolEncodingType_e)stats.MLtype, + countWorkspace, max, mlCodeTable, nbSeq, + ML_defaultNorm, ML_defaultNormLog, MaxML, + prevEntropy->matchlengthCTable, + sizeof(prevEntropy->matchlengthCTable), + entropyWorkspace, entropyWkspSize); + if (ZSTD_isError(countSize)) { + DEBUGLOG(3, "ZSTD_buildCTable for MatchLengths failed"); + stats.size = countSize; + return stats; + } + if (stats.MLtype == set_compressed) + stats.lastCountSize = countSize; + op += countSize; + assert(op <= oend); + } } + stats.size = (size_t)(op-ostart); + return stats; +} + +/* ZSTD_entropyCompressSeqStore_internal(): + * compresses both literals and sequences + * Returns compressed size of block, or a zstd error. + */ +#define SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO 20 +MEM_STATIC size_t +ZSTD_entropyCompressSeqStore_internal( + const seqStore_t* seqStorePtr, + const ZSTD_entropyCTables_t* prevEntropy, + ZSTD_entropyCTables_t* nextEntropy, + const ZSTD_CCtx_params* cctxParams, + void* dst, size_t dstCapacity, + void* entropyWorkspace, size_t entropyWkspSize, + const int bmi2) +{ + ZSTD_strategy const strategy = cctxParams->cParams.strategy; + unsigned* count = (unsigned*)entropyWorkspace; + FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable; + FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable; + FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable; + const seqDef* const sequences = seqStorePtr->sequencesStart; + const size_t nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart); + const BYTE* const ofCodeTable = seqStorePtr->ofCode; + const BYTE* const llCodeTable = seqStorePtr->llCode; + const BYTE* const mlCodeTable = seqStorePtr->mlCode; + BYTE* const ostart = (BYTE*)dst; + BYTE* const oend = ostart + dstCapacity; + BYTE* op = ostart; + size_t lastCountSize; + int longOffsets = 0; + + entropyWorkspace = count + (MaxSeq + 1); + entropyWkspSize -= (MaxSeq + 1) * sizeof(*count); + + DEBUGLOG(5, "ZSTD_entropyCompressSeqStore_internal (nbSeq=%zu, dstCapacity=%zu)", nbSeq, dstCapacity); + ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<= HUF_WORKSPACE_SIZE); + + /* Compress literals */ + { const BYTE* const literals = seqStorePtr->litStart; + size_t const numSequences = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart); + size_t const numLiterals = (size_t)(seqStorePtr->lit - seqStorePtr->litStart); + /* Base suspicion of uncompressibility on ratio of literals to sequences */ + unsigned const suspectUncompressible = (numSequences == 0) || (numLiterals / numSequences >= SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO); + size_t const litSize = (size_t)(seqStorePtr->lit - literals); + + size_t const cSize = ZSTD_compressLiterals( + op, dstCapacity, + literals, litSize, + entropyWorkspace, entropyWkspSize, + &prevEntropy->huf, &nextEntropy->huf, + cctxParams->cParams.strategy, + ZSTD_literalsCompressionIsDisabled(cctxParams), + suspectUncompressible, bmi2); + FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed"); + assert(cSize <= dstCapacity); + op += cSize; + } + + /* Sequences Header */ + RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/, + dstSize_tooSmall, "Can't fit seq hdr in output buf!"); + if (nbSeq < 128) { + *op++ = (BYTE)nbSeq; + } else if (nbSeq < LONGNBSEQ) { + op[0] = (BYTE)((nbSeq>>8) + 0x80); + op[1] = (BYTE)nbSeq; + op+=2; + } else { + op[0]=0xFF; + MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)); + op+=3; + } + assert(op <= oend); + if (nbSeq==0) { + /* Copy the old tables over as if we repeated them */ + ZSTD_memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse)); + return (size_t)(op - ostart); + } + { BYTE* const seqHead = op++; + /* build stats for sequences */ + const ZSTD_symbolEncodingTypeStats_t stats = + ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq, + &prevEntropy->fse, &nextEntropy->fse, + op, oend, + strategy, count, + entropyWorkspace, entropyWkspSize); + FORWARD_IF_ERROR(stats.size, "ZSTD_buildSequencesStatistics failed!"); + *seqHead = (BYTE)((stats.LLtype<<6) + (stats.Offtype<<4) + (stats.MLtype<<2)); + lastCountSize = stats.lastCountSize; + op += stats.size; + longOffsets = stats.longOffsets; + } + + { size_t const bitstreamSize = ZSTD_encodeSequences( + op, (size_t)(oend - op), + CTable_MatchLength, mlCodeTable, + CTable_OffsetBits, ofCodeTable, + CTable_LitLength, llCodeTable, + sequences, nbSeq, + longOffsets, bmi2); + FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed"); + op += bitstreamSize; + assert(op <= oend); + /* zstd versions <= 1.3.4 mistakenly report corruption when + * FSE_readNCount() receives a buffer < 4 bytes. + * Fixed by https://github.com/facebook/zstd/pull/1146. + * This can happen when the last set_compressed table present is 2 + * bytes and the bitstream is only one byte. + * In this exceedingly rare case, we will simply emit an uncompressed + * block, since it isn't worth optimizing. + */ + if (lastCountSize && (lastCountSize + bitstreamSize) < 4) { + /* lastCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */ + assert(lastCountSize + bitstreamSize == 3); + DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by " + "emitting an uncompressed block."); + return 0; + } + } + + DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart)); + return (size_t)(op - ostart); +} + +MEM_STATIC size_t +ZSTD_entropyCompressSeqStore( + const seqStore_t* seqStorePtr, + const ZSTD_entropyCTables_t* prevEntropy, + ZSTD_entropyCTables_t* nextEntropy, + const ZSTD_CCtx_params* cctxParams, + void* dst, size_t dstCapacity, + size_t srcSize, + void* entropyWorkspace, size_t entropyWkspSize, + int bmi2) +{ + size_t const cSize = ZSTD_entropyCompressSeqStore_internal( + seqStorePtr, prevEntropy, nextEntropy, cctxParams, + dst, dstCapacity, + entropyWorkspace, entropyWkspSize, bmi2); + if (cSize == 0) return 0; + /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block. + * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block. + */ + if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity)) { + DEBUGLOG(4, "not enough dstCapacity (%zu) for ZSTD_entropyCompressSeqStore_internal()=> do not compress block", dstCapacity); + return 0; /* block not compressed */ + } + FORWARD_IF_ERROR(cSize, "ZSTD_entropyCompressSeqStore_internal failed"); + + /* Check compressibility */ + { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy); + if (cSize >= maxCSize) return 0; /* block not compressed */ + } + DEBUGLOG(5, "ZSTD_entropyCompressSeqStore() cSize: %zu", cSize); + /* libzstd decoder before > v1.5.4 is not compatible with compressed blocks of size ZSTD_BLOCKSIZE_MAX exactly. + * This restriction is indirectly already fulfilled by respecting ZSTD_minGain() condition above. + */ + assert(cSize < ZSTD_BLOCKSIZE_MAX); + return cSize; +} + +/* ZSTD_selectBlockCompressor() : + * Not static, but internal use only (used by long distance matcher) + * assumption : strat is a valid strategy */ +ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e useRowMatchFinder, ZSTD_dictMode_e dictMode) +{ + static const ZSTD_blockCompressor blockCompressor[4][ZSTD_STRATEGY_MAX+1] = { + { ZSTD_compressBlock_fast /* default for 0 */, + ZSTD_compressBlock_fast, + ZSTD_COMPRESSBLOCK_DOUBLEFAST, + ZSTD_COMPRESSBLOCK_GREEDY, + ZSTD_COMPRESSBLOCK_LAZY, + ZSTD_COMPRESSBLOCK_LAZY2, + ZSTD_COMPRESSBLOCK_BTLAZY2, + ZSTD_COMPRESSBLOCK_BTOPT, + ZSTD_COMPRESSBLOCK_BTULTRA, + ZSTD_COMPRESSBLOCK_BTULTRA2 + }, + { ZSTD_compressBlock_fast_extDict /* default for 0 */, + ZSTD_compressBlock_fast_extDict, + ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT, + ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT, + ZSTD_COMPRESSBLOCK_LAZY_EXTDICT, + ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT, + ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT, + ZSTD_COMPRESSBLOCK_BTOPT_EXTDICT, + ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT, + ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT + }, + { ZSTD_compressBlock_fast_dictMatchState /* default for 0 */, + ZSTD_compressBlock_fast_dictMatchState, + ZSTD_COMPRESSBLOCK_DOUBLEFAST_DICTMATCHSTATE, + ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE, + ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE, + ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE, + ZSTD_COMPRESSBLOCK_BTLAZY2_DICTMATCHSTATE, + ZSTD_COMPRESSBLOCK_BTOPT_DICTMATCHSTATE, + ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE, + ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE + }, + { NULL /* default for 0 */, + NULL, + NULL, + ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH, + ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH, + ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH, + NULL, + NULL, + NULL, + NULL } + }; + ZSTD_blockCompressor selectedCompressor; + ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1); + + assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat)); + DEBUGLOG(4, "Selected block compressor: dictMode=%d strat=%d rowMatchfinder=%d", (int)dictMode, (int)strat, (int)useRowMatchFinder); + if (ZSTD_rowMatchFinderUsed(strat, useRowMatchFinder)) { + static const ZSTD_blockCompressor rowBasedBlockCompressors[4][3] = { + { + ZSTD_COMPRESSBLOCK_GREEDY_ROW, + ZSTD_COMPRESSBLOCK_LAZY_ROW, + ZSTD_COMPRESSBLOCK_LAZY2_ROW + }, + { + ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT_ROW, + ZSTD_COMPRESSBLOCK_LAZY_EXTDICT_ROW, + ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT_ROW + }, + { + ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE_ROW, + ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE_ROW, + ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE_ROW + }, + { + ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH_ROW, + ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH_ROW, + ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW + } + }; + DEBUGLOG(4, "Selecting a row-based matchfinder"); + assert(useRowMatchFinder != ZSTD_ps_auto); + selectedCompressor = rowBasedBlockCompressors[(int)dictMode][(int)strat - (int)ZSTD_greedy]; + } else { + selectedCompressor = blockCompressor[(int)dictMode][(int)strat]; + } + assert(selectedCompressor != NULL); + return selectedCompressor; +} + +static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr, + const BYTE* anchor, size_t lastLLSize) +{ + ZSTD_memcpy(seqStorePtr->lit, anchor, lastLLSize); + seqStorePtr->lit += lastLLSize; +} + +void ZSTD_resetSeqStore(seqStore_t* ssPtr) +{ + ssPtr->lit = ssPtr->litStart; + ssPtr->sequences = ssPtr->sequencesStart; + ssPtr->longLengthType = ZSTD_llt_none; +} + +/* ZSTD_postProcessSequenceProducerResult() : + * Validates and post-processes sequences obtained through the external matchfinder API: + * - Checks whether nbExternalSeqs represents an error condition. + * - Appends a block delimiter to outSeqs if one is not already present. + * See zstd.h for context regarding block delimiters. + * Returns the number of sequences after post-processing, or an error code. */ +static size_t ZSTD_postProcessSequenceProducerResult( + ZSTD_Sequence* outSeqs, size_t nbExternalSeqs, size_t outSeqsCapacity, size_t srcSize +) { + RETURN_ERROR_IF( + nbExternalSeqs > outSeqsCapacity, + sequenceProducer_failed, + "External sequence producer returned error code %lu", + (unsigned long)nbExternalSeqs + ); + + RETURN_ERROR_IF( + nbExternalSeqs == 0 && srcSize > 0, + sequenceProducer_failed, + "Got zero sequences from external sequence producer for a non-empty src buffer!" + ); + + if (srcSize == 0) { + ZSTD_memset(&outSeqs[0], 0, sizeof(ZSTD_Sequence)); + return 1; + } + + { + ZSTD_Sequence const lastSeq = outSeqs[nbExternalSeqs - 1]; + + /* We can return early if lastSeq is already a block delimiter. */ + if (lastSeq.offset == 0 && lastSeq.matchLength == 0) { + return nbExternalSeqs; + } + + /* This error condition is only possible if the external matchfinder + * produced an invalid parse, by definition of ZSTD_sequenceBound(). */ + RETURN_ERROR_IF( + nbExternalSeqs == outSeqsCapacity, + sequenceProducer_failed, + "nbExternalSeqs == outSeqsCapacity but lastSeq is not a block delimiter!" + ); + + /* lastSeq is not a block delimiter, so we need to append one. */ + ZSTD_memset(&outSeqs[nbExternalSeqs], 0, sizeof(ZSTD_Sequence)); + return nbExternalSeqs + 1; + } +} + +/* ZSTD_fastSequenceLengthSum() : + * Returns sum(litLen) + sum(matchLen) + lastLits for *seqBuf*. + * Similar to another function in zstd_compress.c (determine_blockSize), + * except it doesn't check for a block delimiter to end summation. + * Removing the early exit allows the compiler to auto-vectorize (https://godbolt.org/z/cY1cajz9P). + * This function can be deleted and replaced by determine_blockSize after we resolve issue #3456. */ +static size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seqBufSize) { + size_t matchLenSum, litLenSum, i; + matchLenSum = 0; + litLenSum = 0; + for (i = 0; i < seqBufSize; i++) { + litLenSum += seqBuf[i].litLength; + matchLenSum += seqBuf[i].matchLength; + } + return litLenSum + matchLenSum; +} + +typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e; + +static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) +{ + ZSTD_matchState_t* const ms = &zc->blockState.matchState; + DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize); + assert(srcSize <= ZSTD_BLOCKSIZE_MAX); + /* Assert that we have correctly flushed the ctx params into the ms's copy */ + ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams); + /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding + * additional 1. We need to revisit and change this logic to be more consistent */ + if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1+1) { + if (zc->appliedParams.cParams.strategy >= ZSTD_btopt) { + ZSTD_ldm_skipRawSeqStoreBytes(&zc->externSeqStore, srcSize); + } else { + ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch); + } + return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */ + } + ZSTD_resetSeqStore(&(zc->seqStore)); + /* required for optimal parser to read stats from dictionary */ + ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy; + /* tell the optimal parser how we expect to compress literals */ + ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode; + /* a gap between an attached dict and the current window is not safe, + * they must remain adjacent, + * and when that stops being the case, the dict must be unset */ + assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit); + + /* limited update after a very long match */ + { const BYTE* const base = ms->window.base; + const BYTE* const istart = (const BYTE*)src; + const U32 curr = (U32)(istart-base); + if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1)); /* ensure no overflow */ + if (curr > ms->nextToUpdate + 384) + ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384)); + } + + /* select and store sequences */ + { ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms); + size_t lastLLSize; + { int i; + for (i = 0; i < ZSTD_REP_NUM; ++i) + zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i]; + } + if (zc->externSeqStore.pos < zc->externSeqStore.size) { + assert(zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_disable); + + /* External matchfinder + LDM is technically possible, just not implemented yet. + * We need to revisit soon and implement it. */ + RETURN_ERROR_IF( + ZSTD_hasExtSeqProd(&zc->appliedParams), + parameter_combination_unsupported, + "Long-distance matching with external sequence producer enabled is not currently supported." + ); + + /* Updates ldmSeqStore.pos */ + lastLLSize = + ZSTD_ldm_blockCompress(&zc->externSeqStore, + ms, &zc->seqStore, + zc->blockState.nextCBlock->rep, + zc->appliedParams.useRowMatchFinder, + src, srcSize); + assert(zc->externSeqStore.pos <= zc->externSeqStore.size); + } else if (zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) { + rawSeqStore_t ldmSeqStore = kNullRawSeqStore; + + /* External matchfinder + LDM is technically possible, just not implemented yet. + * We need to revisit soon and implement it. */ + RETURN_ERROR_IF( + ZSTD_hasExtSeqProd(&zc->appliedParams), + parameter_combination_unsupported, + "Long-distance matching with external sequence producer enabled is not currently supported." + ); + + ldmSeqStore.seq = zc->ldmSequences; + ldmSeqStore.capacity = zc->maxNbLdmSequences; + /* Updates ldmSeqStore.size */ + FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore, + &zc->appliedParams.ldmParams, + src, srcSize), ""); + /* Updates ldmSeqStore.pos */ + lastLLSize = + ZSTD_ldm_blockCompress(&ldmSeqStore, + ms, &zc->seqStore, + zc->blockState.nextCBlock->rep, + zc->appliedParams.useRowMatchFinder, + src, srcSize); + assert(ldmSeqStore.pos == ldmSeqStore.size); + } else if (ZSTD_hasExtSeqProd(&zc->appliedParams)) { + assert( + zc->extSeqBufCapacity >= ZSTD_sequenceBound(srcSize) + ); + assert(zc->appliedParams.extSeqProdFunc != NULL); + + { U32 const windowSize = (U32)1 << zc->appliedParams.cParams.windowLog; + + size_t const nbExternalSeqs = (zc->appliedParams.extSeqProdFunc)( + zc->appliedParams.extSeqProdState, + zc->extSeqBuf, + zc->extSeqBufCapacity, + src, srcSize, + NULL, 0, /* dict and dictSize, currently not supported */ + zc->appliedParams.compressionLevel, + windowSize + ); + + size_t const nbPostProcessedSeqs = ZSTD_postProcessSequenceProducerResult( + zc->extSeqBuf, + nbExternalSeqs, + zc->extSeqBufCapacity, + srcSize + ); + + /* Return early if there is no error, since we don't need to worry about last literals */ + if (!ZSTD_isError(nbPostProcessedSeqs)) { + ZSTD_sequencePosition seqPos = {0,0,0}; + size_t const seqLenSum = ZSTD_fastSequenceLengthSum(zc->extSeqBuf, nbPostProcessedSeqs); + RETURN_ERROR_IF(seqLenSum > srcSize, externalSequences_invalid, "External sequences imply too large a block!"); + FORWARD_IF_ERROR( + ZSTD_copySequencesToSeqStoreExplicitBlockDelim( + zc, &seqPos, + zc->extSeqBuf, nbPostProcessedSeqs, + src, srcSize, + zc->appliedParams.searchForExternalRepcodes + ), + "Failed to copy external sequences to seqStore!" + ); + ms->ldmSeqStore = NULL; + DEBUGLOG(5, "Copied %lu sequences from external sequence producer to internal seqStore.", (unsigned long)nbExternalSeqs); + return ZSTDbss_compress; + } + + /* Propagate the error if fallback is disabled */ + if (!zc->appliedParams.enableMatchFinderFallback) { + return nbPostProcessedSeqs; + } + + /* Fallback to software matchfinder */ + { ZSTD_blockCompressor const blockCompressor = + ZSTD_selectBlockCompressor( + zc->appliedParams.cParams.strategy, + zc->appliedParams.useRowMatchFinder, + dictMode); + ms->ldmSeqStore = NULL; + DEBUGLOG( + 5, + "External sequence producer returned error code %lu. Falling back to internal parser.", + (unsigned long)nbExternalSeqs + ); + lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize); + } } + } else { /* not long range mode and no external matchfinder */ + ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor( + zc->appliedParams.cParams.strategy, + zc->appliedParams.useRowMatchFinder, + dictMode); + ms->ldmSeqStore = NULL; + lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize); + } + { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize; + ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize); + } } + return ZSTDbss_compress; +} + +static size_t ZSTD_copyBlockSequences(SeqCollector* seqCollector, const seqStore_t* seqStore, const U32 prevRepcodes[ZSTD_REP_NUM]) +{ + const seqDef* inSeqs = seqStore->sequencesStart; + const size_t nbInSequences = seqStore->sequences - inSeqs; + const size_t nbInLiterals = (size_t)(seqStore->lit - seqStore->litStart); + + ZSTD_Sequence* outSeqs = seqCollector->seqIndex == 0 ? seqCollector->seqStart : seqCollector->seqStart + seqCollector->seqIndex; + const size_t nbOutSequences = nbInSequences + 1; + size_t nbOutLiterals = 0; + repcodes_t repcodes; + size_t i; + + /* Bounds check that we have enough space for every input sequence + * and the block delimiter + */ + assert(seqCollector->seqIndex <= seqCollector->maxSequences); + RETURN_ERROR_IF( + nbOutSequences > (size_t)(seqCollector->maxSequences - seqCollector->seqIndex), + dstSize_tooSmall, + "Not enough space to copy sequences"); + + ZSTD_memcpy(&repcodes, prevRepcodes, sizeof(repcodes)); + for (i = 0; i < nbInSequences; ++i) { + U32 rawOffset; + outSeqs[i].litLength = inSeqs[i].litLength; + outSeqs[i].matchLength = inSeqs[i].mlBase + MINMATCH; + outSeqs[i].rep = 0; + + /* Handle the possible single length >= 64K + * There can only be one because we add MINMATCH to every match length, + * and blocks are at most 128K. + */ + if (i == seqStore->longLengthPos) { + if (seqStore->longLengthType == ZSTD_llt_literalLength) { + outSeqs[i].litLength += 0x10000; + } else if (seqStore->longLengthType == ZSTD_llt_matchLength) { + outSeqs[i].matchLength += 0x10000; + } + } + + /* Determine the raw offset given the offBase, which may be a repcode. */ + if (OFFBASE_IS_REPCODE(inSeqs[i].offBase)) { + const U32 repcode = OFFBASE_TO_REPCODE(inSeqs[i].offBase); + assert(repcode > 0); + outSeqs[i].rep = repcode; + if (outSeqs[i].litLength != 0) { + rawOffset = repcodes.rep[repcode - 1]; + } else { + if (repcode == 3) { + assert(repcodes.rep[0] > 1); + rawOffset = repcodes.rep[0] - 1; + } else { + rawOffset = repcodes.rep[repcode]; + } + } + } else { + rawOffset = OFFBASE_TO_OFFSET(inSeqs[i].offBase); + } + outSeqs[i].offset = rawOffset; + + /* Update repcode history for the sequence */ + ZSTD_updateRep(repcodes.rep, + inSeqs[i].offBase, + inSeqs[i].litLength == 0); + + nbOutLiterals += outSeqs[i].litLength; + } + /* Insert last literals (if any exist) in the block as a sequence with ml == off == 0. + * If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker + * for the block boundary, according to the API. + */ + assert(nbInLiterals >= nbOutLiterals); + { + const size_t lastLLSize = nbInLiterals - nbOutLiterals; + outSeqs[nbInSequences].litLength = (U32)lastLLSize; + outSeqs[nbInSequences].matchLength = 0; + outSeqs[nbInSequences].offset = 0; + assert(nbOutSequences == nbInSequences + 1); + } + seqCollector->seqIndex += nbOutSequences; + assert(seqCollector->seqIndex <= seqCollector->maxSequences); + + return 0; +} + +size_t ZSTD_sequenceBound(size_t srcSize) { + const size_t maxNbSeq = (srcSize / ZSTD_MINMATCH_MIN) + 1; + const size_t maxNbDelims = (srcSize / ZSTD_BLOCKSIZE_MAX_MIN) + 1; + return maxNbSeq + maxNbDelims; +} + +size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, + size_t outSeqsSize, const void* src, size_t srcSize) +{ + const size_t dstCapacity = ZSTD_compressBound(srcSize); + void* dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem); + SeqCollector seqCollector; + { + int targetCBlockSize; + FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_targetCBlockSize, &targetCBlockSize), ""); + RETURN_ERROR_IF(targetCBlockSize != 0, parameter_unsupported, "targetCBlockSize != 0"); + } + { + int nbWorkers; + FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_nbWorkers, &nbWorkers), ""); + RETURN_ERROR_IF(nbWorkers != 0, parameter_unsupported, "nbWorkers != 0"); + } + + RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!"); + + seqCollector.collectSequences = 1; + seqCollector.seqStart = outSeqs; + seqCollector.seqIndex = 0; + seqCollector.maxSequences = outSeqsSize; + zc->seqCollector = seqCollector; + + { + const size_t ret = ZSTD_compress2(zc, dst, dstCapacity, src, srcSize); + ZSTD_customFree(dst, ZSTD_defaultCMem); + FORWARD_IF_ERROR(ret, "ZSTD_compress2 failed"); + } + assert(zc->seqCollector.seqIndex <= ZSTD_sequenceBound(srcSize)); + return zc->seqCollector.seqIndex; +} + +size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize) { + size_t in = 0; + size_t out = 0; + for (; in < seqsSize; ++in) { + if (sequences[in].offset == 0 && sequences[in].matchLength == 0) { + if (in != seqsSize - 1) { + sequences[in+1].litLength += sequences[in].litLength; + } + } else { + sequences[out] = sequences[in]; + ++out; + } + } + return out; +} + +/* Unrolled loop to read four size_ts of input at a time. Returns 1 if is RLE, 0 if not. */ +static int ZSTD_isRLE(const BYTE* src, size_t length) { + const BYTE* ip = src; + const BYTE value = ip[0]; + const size_t valueST = (size_t)((U64)value * 0x0101010101010101ULL); + const size_t unrollSize = sizeof(size_t) * 4; + const size_t unrollMask = unrollSize - 1; + const size_t prefixLength = length & unrollMask; + size_t i; + if (length == 1) return 1; + /* Check if prefix is RLE first before using unrolled loop */ + if (prefixLength && ZSTD_count(ip+1, ip, ip+prefixLength) != prefixLength-1) { + return 0; + } + for (i = prefixLength; i != length; i += unrollSize) { + size_t u; + for (u = 0; u < unrollSize; u += sizeof(size_t)) { + if (MEM_readST(ip + i + u) != valueST) { + return 0; + } } } + return 1; +} + +/* Returns true if the given block may be RLE. + * This is just a heuristic based on the compressibility. + * It may return both false positives and false negatives. + */ +static int ZSTD_maybeRLE(seqStore_t const* seqStore) +{ + size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart); + size_t const nbLits = (size_t)(seqStore->lit - seqStore->litStart); + + return nbSeqs < 4 && nbLits < 10; +} + +static void +ZSTD_blockState_confirmRepcodesAndEntropyTables(ZSTD_blockState_t* const bs) +{ + ZSTD_compressedBlockState_t* const tmp = bs->prevCBlock; + bs->prevCBlock = bs->nextCBlock; + bs->nextCBlock = tmp; +} + +/* Writes the block header */ +static void +writeBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastBlock) +{ + U32 const cBlockHeader = cSize == 1 ? + lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) : + lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); + MEM_writeLE24(op, cBlockHeader); + DEBUGLOG(3, "writeBlockHeader: cSize: %zu blockSize: %zu lastBlock: %u", cSize, blockSize, lastBlock); +} + +/** ZSTD_buildBlockEntropyStats_literals() : + * Builds entropy for the literals. + * Stores literals block type (raw, rle, compressed, repeat) and + * huffman description table to hufMetadata. + * Requires ENTROPY_WORKSPACE_SIZE workspace + * @return : size of huffman description table, or an error code + */ +static size_t +ZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSize, + const ZSTD_hufCTables_t* prevHuf, + ZSTD_hufCTables_t* nextHuf, + ZSTD_hufCTablesMetadata_t* hufMetadata, + const int literalsCompressionIsDisabled, + void* workspace, size_t wkspSize, + int hufFlags) +{ + BYTE* const wkspStart = (BYTE*)workspace; + BYTE* const wkspEnd = wkspStart + wkspSize; + BYTE* const countWkspStart = wkspStart; + unsigned* const countWksp = (unsigned*)workspace; + const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned); + BYTE* const nodeWksp = countWkspStart + countWkspSize; + const size_t nodeWkspSize = (size_t)(wkspEnd - nodeWksp); + unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX; + unsigned huffLog = LitHufLog; + HUF_repeat repeat = prevHuf->repeatMode; + DEBUGLOG(5, "ZSTD_buildBlockEntropyStats_literals (srcSize=%zu)", srcSize); + + /* Prepare nextEntropy assuming reusing the existing table */ + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + + if (literalsCompressionIsDisabled) { + DEBUGLOG(5, "set_basic - disabled"); + hufMetadata->hType = set_basic; + return 0; + } + + /* small ? don't even attempt compression (speed opt) */ +#ifndef COMPRESS_LITERALS_SIZE_MIN +# define COMPRESS_LITERALS_SIZE_MIN 63 /* heuristic */ +#endif + { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN; + if (srcSize <= minLitSize) { + DEBUGLOG(5, "set_basic - too small"); + hufMetadata->hType = set_basic; + return 0; + } } + + /* Scan input and build symbol stats */ + { size_t const largest = + HIST_count_wksp (countWksp, &maxSymbolValue, + (const BYTE*)src, srcSize, + workspace, wkspSize); + FORWARD_IF_ERROR(largest, "HIST_count_wksp failed"); + if (largest == srcSize) { + /* only one literal symbol */ + DEBUGLOG(5, "set_rle"); + hufMetadata->hType = set_rle; + return 0; + } + if (largest <= (srcSize >> 7)+4) { + /* heuristic: likely not compressible */ + DEBUGLOG(5, "set_basic - no gain"); + hufMetadata->hType = set_basic; + return 0; + } } + + /* Validate the previous Huffman table */ + if (repeat == HUF_repeat_check + && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) { + repeat = HUF_repeat_none; + } + + /* Build Huffman Tree */ + ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable)); + huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue, nodeWksp, nodeWkspSize, nextHuf->CTable, countWksp, hufFlags); + assert(huffLog <= LitHufLog); + { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp, + maxSymbolValue, huffLog, + nodeWksp, nodeWkspSize); + FORWARD_IF_ERROR(maxBits, "HUF_buildCTable_wksp"); + huffLog = (U32)maxBits; + } + { /* Build and write the CTable */ + size_t const newCSize = HUF_estimateCompressedSize( + (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue); + size_t const hSize = HUF_writeCTable_wksp( + hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer), + (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog, + nodeWksp, nodeWkspSize); + /* Check against repeating the previous CTable */ + if (repeat != HUF_repeat_none) { + size_t const oldCSize = HUF_estimateCompressedSize( + (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue); + if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) { + DEBUGLOG(5, "set_repeat - smaller"); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + hufMetadata->hType = set_repeat; + return 0; + } } + if (newCSize + hSize >= srcSize) { + DEBUGLOG(5, "set_basic - no gains"); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + hufMetadata->hType = set_basic; + return 0; + } + DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize); + hufMetadata->hType = set_compressed; + nextHuf->repeatMode = HUF_repeat_check; + return hSize; + } +} + + +/* ZSTD_buildDummySequencesStatistics(): + * Returns a ZSTD_symbolEncodingTypeStats_t with all encoding types as set_basic, + * and updates nextEntropy to the appropriate repeatMode. + */ +static ZSTD_symbolEncodingTypeStats_t +ZSTD_buildDummySequencesStatistics(ZSTD_fseCTables_t* nextEntropy) +{ + ZSTD_symbolEncodingTypeStats_t stats = {set_basic, set_basic, set_basic, 0, 0, 0}; + nextEntropy->litlength_repeatMode = FSE_repeat_none; + nextEntropy->offcode_repeatMode = FSE_repeat_none; + nextEntropy->matchlength_repeatMode = FSE_repeat_none; + return stats; +} + +/** ZSTD_buildBlockEntropyStats_sequences() : + * Builds entropy for the sequences. + * Stores symbol compression modes and fse table to fseMetadata. + * Requires ENTROPY_WORKSPACE_SIZE wksp. + * @return : size of fse tables or error code */ +static size_t +ZSTD_buildBlockEntropyStats_sequences( + const seqStore_t* seqStorePtr, + const ZSTD_fseCTables_t* prevEntropy, + ZSTD_fseCTables_t* nextEntropy, + const ZSTD_CCtx_params* cctxParams, + ZSTD_fseCTablesMetadata_t* fseMetadata, + void* workspace, size_t wkspSize) +{ + ZSTD_strategy const strategy = cctxParams->cParams.strategy; + size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart); + BYTE* const ostart = fseMetadata->fseTablesBuffer; + BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer); + BYTE* op = ostart; + unsigned* countWorkspace = (unsigned*)workspace; + unsigned* entropyWorkspace = countWorkspace + (MaxSeq + 1); + size_t entropyWorkspaceSize = wkspSize - (MaxSeq + 1) * sizeof(*countWorkspace); + ZSTD_symbolEncodingTypeStats_t stats; + + DEBUGLOG(5, "ZSTD_buildBlockEntropyStats_sequences (nbSeq=%zu)", nbSeq); + stats = nbSeq != 0 ? ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq, + prevEntropy, nextEntropy, op, oend, + strategy, countWorkspace, + entropyWorkspace, entropyWorkspaceSize) + : ZSTD_buildDummySequencesStatistics(nextEntropy); + FORWARD_IF_ERROR(stats.size, "ZSTD_buildSequencesStatistics failed!"); + fseMetadata->llType = (symbolEncodingType_e) stats.LLtype; + fseMetadata->ofType = (symbolEncodingType_e) stats.Offtype; + fseMetadata->mlType = (symbolEncodingType_e) stats.MLtype; + fseMetadata->lastCountSize = stats.lastCountSize; + return stats.size; +} + + +/** ZSTD_buildBlockEntropyStats() : + * Builds entropy for the block. + * Requires workspace size ENTROPY_WORKSPACE_SIZE + * @return : 0 on success, or an error code + * Note : also employed in superblock + */ +size_t ZSTD_buildBlockEntropyStats( + const seqStore_t* seqStorePtr, + const ZSTD_entropyCTables_t* prevEntropy, + ZSTD_entropyCTables_t* nextEntropy, + const ZSTD_CCtx_params* cctxParams, + ZSTD_entropyCTablesMetadata_t* entropyMetadata, + void* workspace, size_t wkspSize) +{ + size_t const litSize = (size_t)(seqStorePtr->lit - seqStorePtr->litStart); + int const huf_useOptDepth = (cctxParams->cParams.strategy >= HUF_OPTIMAL_DEPTH_THRESHOLD); + int const hufFlags = huf_useOptDepth ? HUF_flags_optimalDepth : 0; + + entropyMetadata->hufMetadata.hufDesSize = + ZSTD_buildBlockEntropyStats_literals(seqStorePtr->litStart, litSize, + &prevEntropy->huf, &nextEntropy->huf, + &entropyMetadata->hufMetadata, + ZSTD_literalsCompressionIsDisabled(cctxParams), + workspace, wkspSize, hufFlags); + + FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildBlockEntropyStats_literals failed"); + entropyMetadata->fseMetadata.fseTablesSize = + ZSTD_buildBlockEntropyStats_sequences(seqStorePtr, + &prevEntropy->fse, &nextEntropy->fse, + cctxParams, + &entropyMetadata->fseMetadata, + workspace, wkspSize); + FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, "ZSTD_buildBlockEntropyStats_sequences failed"); + return 0; +} + +/* Returns the size estimate for the literals section (header + content) of a block */ +static size_t +ZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSize, + const ZSTD_hufCTables_t* huf, + const ZSTD_hufCTablesMetadata_t* hufMetadata, + void* workspace, size_t wkspSize, + int writeEntropy) +{ + unsigned* const countWksp = (unsigned*)workspace; + unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX; + size_t literalSectionHeaderSize = 3 + (litSize >= 1 KB) + (litSize >= 16 KB); + U32 singleStream = litSize < 256; + + if (hufMetadata->hType == set_basic) return litSize; + else if (hufMetadata->hType == set_rle) return 1; + else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) { + size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize); + if (ZSTD_isError(largest)) return litSize; + { size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue); + if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize; + if (!singleStream) cLitSizeEstimate += 6; /* multi-stream huffman uses 6-byte jump table */ + return cLitSizeEstimate + literalSectionHeaderSize; + } } + assert(0); /* impossible */ + return 0; +} + +/* Returns the size estimate for the FSE-compressed symbols (of, ml, ll) of a block */ +static size_t +ZSTD_estimateBlockSize_symbolType(symbolEncodingType_e type, + const BYTE* codeTable, size_t nbSeq, unsigned maxCode, + const FSE_CTable* fseCTable, + const U8* additionalBits, + short const* defaultNorm, U32 defaultNormLog, U32 defaultMax, + void* workspace, size_t wkspSize) +{ + unsigned* const countWksp = (unsigned*)workspace; + const BYTE* ctp = codeTable; + const BYTE* const ctStart = ctp; + const BYTE* const ctEnd = ctStart + nbSeq; + size_t cSymbolTypeSizeEstimateInBits = 0; + unsigned max = maxCode; + + HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */ + if (type == set_basic) { + /* We selected this encoding type, so it must be valid. */ + assert(max <= defaultMax); + (void)defaultMax; + cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max); + } else if (type == set_rle) { + cSymbolTypeSizeEstimateInBits = 0; + } else if (type == set_compressed || type == set_repeat) { + cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max); + } + if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) { + return nbSeq * 10; + } + while (ctp < ctEnd) { + if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp]; + else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */ + ctp++; + } + return cSymbolTypeSizeEstimateInBits >> 3; +} + +/* Returns the size estimate for the sequences section (header + content) of a block */ +static size_t +ZSTD_estimateBlockSize_sequences(const BYTE* ofCodeTable, + const BYTE* llCodeTable, + const BYTE* mlCodeTable, + size_t nbSeq, + const ZSTD_fseCTables_t* fseTables, + const ZSTD_fseCTablesMetadata_t* fseMetadata, + void* workspace, size_t wkspSize, + int writeEntropy) +{ + size_t sequencesSectionHeaderSize = 1 /* seqHead */ + 1 /* min seqSize size */ + (nbSeq >= 128) + (nbSeq >= LONGNBSEQ); + size_t cSeqSizeEstimate = 0; + cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, nbSeq, MaxOff, + fseTables->offcodeCTable, NULL, + OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, + workspace, wkspSize); + cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->llType, llCodeTable, nbSeq, MaxLL, + fseTables->litlengthCTable, LL_bits, + LL_defaultNorm, LL_defaultNormLog, MaxLL, + workspace, wkspSize); + cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, nbSeq, MaxML, + fseTables->matchlengthCTable, ML_bits, + ML_defaultNorm, ML_defaultNormLog, MaxML, + workspace, wkspSize); + if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize; + return cSeqSizeEstimate + sequencesSectionHeaderSize; +} + +/* Returns the size estimate for a given stream of literals, of, ll, ml */ +static size_t +ZSTD_estimateBlockSize(const BYTE* literals, size_t litSize, + const BYTE* ofCodeTable, + const BYTE* llCodeTable, + const BYTE* mlCodeTable, + size_t nbSeq, + const ZSTD_entropyCTables_t* entropy, + const ZSTD_entropyCTablesMetadata_t* entropyMetadata, + void* workspace, size_t wkspSize, + int writeLitEntropy, int writeSeqEntropy) +{ + size_t const literalsSize = ZSTD_estimateBlockSize_literal(literals, litSize, + &entropy->huf, &entropyMetadata->hufMetadata, + workspace, wkspSize, writeLitEntropy); + size_t const seqSize = ZSTD_estimateBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable, + nbSeq, &entropy->fse, &entropyMetadata->fseMetadata, + workspace, wkspSize, writeSeqEntropy); + return seqSize + literalsSize + ZSTD_blockHeaderSize; +} + +/* Builds entropy statistics and uses them for blocksize estimation. + * + * @return: estimated compressed size of the seqStore, or a zstd error. + */ +static size_t +ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, ZSTD_CCtx* zc) +{ + ZSTD_entropyCTablesMetadata_t* const entropyMetadata = &zc->blockSplitCtx.entropyMetadata; + DEBUGLOG(6, "ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize()"); + FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(seqStore, + &zc->blockState.prevCBlock->entropy, + &zc->blockState.nextCBlock->entropy, + &zc->appliedParams, + entropyMetadata, + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE), ""); + return ZSTD_estimateBlockSize( + seqStore->litStart, (size_t)(seqStore->lit - seqStore->litStart), + seqStore->ofCode, seqStore->llCode, seqStore->mlCode, + (size_t)(seqStore->sequences - seqStore->sequencesStart), + &zc->blockState.nextCBlock->entropy, + entropyMetadata, + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE, + (int)(entropyMetadata->hufMetadata.hType == set_compressed), 1); +} + +/* Returns literals bytes represented in a seqStore */ +static size_t ZSTD_countSeqStoreLiteralsBytes(const seqStore_t* const seqStore) +{ + size_t literalsBytes = 0; + size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart); + size_t i; + for (i = 0; i < nbSeqs; ++i) { + seqDef const seq = seqStore->sequencesStart[i]; + literalsBytes += seq.litLength; + if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_literalLength) { + literalsBytes += 0x10000; + } } + return literalsBytes; +} + +/* Returns match bytes represented in a seqStore */ +static size_t ZSTD_countSeqStoreMatchBytes(const seqStore_t* const seqStore) +{ + size_t matchBytes = 0; + size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart); + size_t i; + for (i = 0; i < nbSeqs; ++i) { + seqDef seq = seqStore->sequencesStart[i]; + matchBytes += seq.mlBase + MINMATCH; + if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_matchLength) { + matchBytes += 0x10000; + } } + return matchBytes; +} + +/* Derives the seqStore that is a chunk of the originalSeqStore from [startIdx, endIdx). + * Stores the result in resultSeqStore. + */ +static void ZSTD_deriveSeqStoreChunk(seqStore_t* resultSeqStore, + const seqStore_t* originalSeqStore, + size_t startIdx, size_t endIdx) +{ + *resultSeqStore = *originalSeqStore; + if (startIdx > 0) { + resultSeqStore->sequences = originalSeqStore->sequencesStart + startIdx; + resultSeqStore->litStart += ZSTD_countSeqStoreLiteralsBytes(resultSeqStore); + } + + /* Move longLengthPos into the correct position if necessary */ + if (originalSeqStore->longLengthType != ZSTD_llt_none) { + if (originalSeqStore->longLengthPos < startIdx || originalSeqStore->longLengthPos > endIdx) { + resultSeqStore->longLengthType = ZSTD_llt_none; + } else { + resultSeqStore->longLengthPos -= (U32)startIdx; + } + } + resultSeqStore->sequencesStart = originalSeqStore->sequencesStart + startIdx; + resultSeqStore->sequences = originalSeqStore->sequencesStart + endIdx; + if (endIdx == (size_t)(originalSeqStore->sequences - originalSeqStore->sequencesStart)) { + /* This accounts for possible last literals if the derived chunk reaches the end of the block */ + assert(resultSeqStore->lit == originalSeqStore->lit); + } else { + size_t const literalsBytes = ZSTD_countSeqStoreLiteralsBytes(resultSeqStore); + resultSeqStore->lit = resultSeqStore->litStart + literalsBytes; + } + resultSeqStore->llCode += startIdx; + resultSeqStore->mlCode += startIdx; + resultSeqStore->ofCode += startIdx; +} + +/** + * Returns the raw offset represented by the combination of offBase, ll0, and repcode history. + * offBase must represent a repcode in the numeric representation of ZSTD_storeSeq(). + */ +static U32 +ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offBase, const U32 ll0) +{ + U32 const adjustedRepCode = OFFBASE_TO_REPCODE(offBase) - 1 + ll0; /* [ 0 - 3 ] */ + assert(OFFBASE_IS_REPCODE(offBase)); + if (adjustedRepCode == ZSTD_REP_NUM) { + assert(ll0); + /* litlength == 0 and offCode == 2 implies selection of first repcode - 1 + * This is only valid if it results in a valid offset value, aka > 0. + * Note : it may happen that `rep[0]==1` in exceptional circumstances. + * In which case this function will return 0, which is an invalid offset. + * It's not an issue though, since this value will be + * compared and discarded within ZSTD_seqStore_resolveOffCodes(). + */ + return rep[0] - 1; + } + return rep[adjustedRepCode]; +} + +/** + * ZSTD_seqStore_resolveOffCodes() reconciles any possible divergences in offset history that may arise + * due to emission of RLE/raw blocks that disturb the offset history, + * and replaces any repcodes within the seqStore that may be invalid. + * + * dRepcodes are updated as would be on the decompression side. + * cRepcodes are updated exactly in accordance with the seqStore. + * + * Note : this function assumes seq->offBase respects the following numbering scheme : + * 0 : invalid + * 1-3 : repcode 1-3 + * 4+ : real_offset+3 + */ +static void +ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRepcodes, + const seqStore_t* const seqStore, U32 const nbSeq) +{ + U32 idx = 0; + U32 const longLitLenIdx = seqStore->longLengthType == ZSTD_llt_literalLength ? seqStore->longLengthPos : nbSeq; + for (; idx < nbSeq; ++idx) { + seqDef* const seq = seqStore->sequencesStart + idx; + U32 const ll0 = (seq->litLength == 0) && (idx != longLitLenIdx); + U32 const offBase = seq->offBase; + assert(offBase > 0); + if (OFFBASE_IS_REPCODE(offBase)) { + U32 const dRawOffset = ZSTD_resolveRepcodeToRawOffset(dRepcodes->rep, offBase, ll0); + U32 const cRawOffset = ZSTD_resolveRepcodeToRawOffset(cRepcodes->rep, offBase, ll0); + /* Adjust simulated decompression repcode history if we come across a mismatch. Replace + * the repcode with the offset it actually references, determined by the compression + * repcode history. + */ + if (dRawOffset != cRawOffset) { + seq->offBase = OFFSET_TO_OFFBASE(cRawOffset); + } + } + /* Compression repcode history is always updated with values directly from the unmodified seqStore. + * Decompression repcode history may use modified seq->offset value taken from compression repcode history. + */ + ZSTD_updateRep(dRepcodes->rep, seq->offBase, ll0); + ZSTD_updateRep(cRepcodes->rep, offBase, ll0); + } +} + +/* ZSTD_compressSeqStore_singleBlock(): + * Compresses a seqStore into a block with a block header, into the buffer dst. + * + * Returns the total size of that block (including header) or a ZSTD error code. + */ +static size_t +ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, + const seqStore_t* const seqStore, + repcodes_t* const dRep, repcodes_t* const cRep, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + U32 lastBlock, U32 isPartition) +{ + const U32 rleMaxLength = 25; + BYTE* op = (BYTE*)dst; + const BYTE* ip = (const BYTE*)src; + size_t cSize; + size_t cSeqsSize; + + /* In case of an RLE or raw block, the simulated decompression repcode history must be reset */ + repcodes_t const dRepOriginal = *dRep; + DEBUGLOG(5, "ZSTD_compressSeqStore_singleBlock"); + if (isPartition) + ZSTD_seqStore_resolveOffCodes(dRep, cRep, seqStore, (U32)(seqStore->sequences - seqStore->sequencesStart)); + + RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, "Block header doesn't fit"); + cSeqsSize = ZSTD_entropyCompressSeqStore(seqStore, + &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, + &zc->appliedParams, + op + ZSTD_blockHeaderSize, dstCapacity - ZSTD_blockHeaderSize, + srcSize, + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + zc->bmi2); + FORWARD_IF_ERROR(cSeqsSize, "ZSTD_entropyCompressSeqStore failed!"); + + if (!zc->isFirstBlock && + cSeqsSize < rleMaxLength && + ZSTD_isRLE((BYTE const*)src, srcSize)) { + /* We don't want to emit our first block as a RLE even if it qualifies because + * doing so will cause the decoder (cli only) to throw a "should consume all input error." + * This is only an issue for zstd <= v1.4.3 + */ + cSeqsSize = 1; + } + + /* Sequence collection not supported when block splitting */ + if (zc->seqCollector.collectSequences) { + FORWARD_IF_ERROR(ZSTD_copyBlockSequences(&zc->seqCollector, seqStore, dRepOriginal.rep), "copyBlockSequences failed"); + ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); + return 0; + } + + if (cSeqsSize == 0) { + cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, srcSize, lastBlock); + FORWARD_IF_ERROR(cSize, "Nocompress block failed"); + DEBUGLOG(4, "Writing out nocompress block, size: %zu", cSize); + *dRep = dRepOriginal; /* reset simulated decompression repcode history */ + } else if (cSeqsSize == 1) { + cSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, srcSize, lastBlock); + FORWARD_IF_ERROR(cSize, "RLE compress block failed"); + DEBUGLOG(4, "Writing out RLE block, size: %zu", cSize); + *dRep = dRepOriginal; /* reset simulated decompression repcode history */ + } else { + ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); + writeBlockHeader(op, cSeqsSize, srcSize, lastBlock); + cSize = ZSTD_blockHeaderSize + cSeqsSize; + DEBUGLOG(4, "Writing out compressed block, size: %zu", cSize); + } + + if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + + return cSize; +} + +/* Struct to keep track of where we are in our recursive calls. */ +typedef struct { + U32* splitLocations; /* Array of split indices */ + size_t idx; /* The current index within splitLocations being worked on */ +} seqStoreSplits; + +#define MIN_SEQUENCES_BLOCK_SPLITTING 300 + +/* Helper function to perform the recursive search for block splits. + * Estimates the cost of seqStore prior to split, and estimates the cost of splitting the sequences in half. + * If advantageous to split, then we recurse down the two sub-blocks. + * If not, or if an error occurred in estimation, then we do not recurse. + * + * Note: The recursion depth is capped by a heuristic minimum number of sequences, + * defined by MIN_SEQUENCES_BLOCK_SPLITTING. + * In theory, this means the absolute largest recursion depth is 10 == log2(maxNbSeqInBlock/MIN_SEQUENCES_BLOCK_SPLITTING). + * In practice, recursion depth usually doesn't go beyond 4. + * + * Furthermore, the number of splits is capped by ZSTD_MAX_NB_BLOCK_SPLITS. + * At ZSTD_MAX_NB_BLOCK_SPLITS == 196 with the current existing blockSize + * maximum of 128 KB, this value is actually impossible to reach. + */ +static void +ZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx, + ZSTD_CCtx* zc, const seqStore_t* origSeqStore) +{ + seqStore_t* const fullSeqStoreChunk = &zc->blockSplitCtx.fullSeqStoreChunk; + seqStore_t* const firstHalfSeqStore = &zc->blockSplitCtx.firstHalfSeqStore; + seqStore_t* const secondHalfSeqStore = &zc->blockSplitCtx.secondHalfSeqStore; + size_t estimatedOriginalSize; + size_t estimatedFirstHalfSize; + size_t estimatedSecondHalfSize; + size_t midIdx = (startIdx + endIdx)/2; + + DEBUGLOG(5, "ZSTD_deriveBlockSplitsHelper: startIdx=%zu endIdx=%zu", startIdx, endIdx); + assert(endIdx >= startIdx); + if (endIdx - startIdx < MIN_SEQUENCES_BLOCK_SPLITTING || splits->idx >= ZSTD_MAX_NB_BLOCK_SPLITS) { + DEBUGLOG(6, "ZSTD_deriveBlockSplitsHelper: Too few sequences (%zu)", endIdx - startIdx); + return; + } + ZSTD_deriveSeqStoreChunk(fullSeqStoreChunk, origSeqStore, startIdx, endIdx); + ZSTD_deriveSeqStoreChunk(firstHalfSeqStore, origSeqStore, startIdx, midIdx); + ZSTD_deriveSeqStoreChunk(secondHalfSeqStore, origSeqStore, midIdx, endIdx); + estimatedOriginalSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(fullSeqStoreChunk, zc); + estimatedFirstHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(firstHalfSeqStore, zc); + estimatedSecondHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(secondHalfSeqStore, zc); + DEBUGLOG(5, "Estimated original block size: %zu -- First half split: %zu -- Second half split: %zu", + estimatedOriginalSize, estimatedFirstHalfSize, estimatedSecondHalfSize); + if (ZSTD_isError(estimatedOriginalSize) || ZSTD_isError(estimatedFirstHalfSize) || ZSTD_isError(estimatedSecondHalfSize)) { + return; + } + if (estimatedFirstHalfSize + estimatedSecondHalfSize < estimatedOriginalSize) { + DEBUGLOG(5, "split decided at seqNb:%zu", midIdx); + ZSTD_deriveBlockSplitsHelper(splits, startIdx, midIdx, zc, origSeqStore); + splits->splitLocations[splits->idx] = (U32)midIdx; + splits->idx++; + ZSTD_deriveBlockSplitsHelper(splits, midIdx, endIdx, zc, origSeqStore); + } +} + +/* Base recursive function. + * Populates a table with intra-block partition indices that can improve compression ratio. + * + * @return: number of splits made (which equals the size of the partition table - 1). + */ +static size_t ZSTD_deriveBlockSplits(ZSTD_CCtx* zc, U32 partitions[], U32 nbSeq) +{ + seqStoreSplits splits; + splits.splitLocations = partitions; + splits.idx = 0; + if (nbSeq <= 4) { + DEBUGLOG(5, "ZSTD_deriveBlockSplits: Too few sequences to split (%u <= 4)", nbSeq); + /* Refuse to try and split anything with less than 4 sequences */ + return 0; + } + ZSTD_deriveBlockSplitsHelper(&splits, 0, nbSeq, zc, &zc->seqStore); + splits.splitLocations[splits.idx] = nbSeq; + DEBUGLOG(5, "ZSTD_deriveBlockSplits: final nb partitions: %zu", splits.idx+1); + return splits.idx; +} + +/* ZSTD_compressBlock_splitBlock(): + * Attempts to split a given block into multiple blocks to improve compression ratio. + * + * Returns combined size of all blocks (which includes headers), or a ZSTD error code. + */ +static size_t +ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, + void* dst, size_t dstCapacity, + const void* src, size_t blockSize, + U32 lastBlock, U32 nbSeq) +{ + size_t cSize = 0; + const BYTE* ip = (const BYTE*)src; + BYTE* op = (BYTE*)dst; + size_t i = 0; + size_t srcBytesTotal = 0; + U32* const partitions = zc->blockSplitCtx.partitions; /* size == ZSTD_MAX_NB_BLOCK_SPLITS */ + seqStore_t* const nextSeqStore = &zc->blockSplitCtx.nextSeqStore; + seqStore_t* const currSeqStore = &zc->blockSplitCtx.currSeqStore; + size_t const numSplits = ZSTD_deriveBlockSplits(zc, partitions, nbSeq); + + /* If a block is split and some partitions are emitted as RLE/uncompressed, then repcode history + * may become invalid. In order to reconcile potentially invalid repcodes, we keep track of two + * separate repcode histories that simulate repcode history on compression and decompression side, + * and use the histories to determine whether we must replace a particular repcode with its raw offset. + * + * 1) cRep gets updated for each partition, regardless of whether the block was emitted as uncompressed + * or RLE. This allows us to retrieve the offset value that an invalid repcode references within + * a nocompress/RLE block. + * 2) dRep gets updated only for compressed partitions, and when a repcode gets replaced, will use + * the replacement offset value rather than the original repcode to update the repcode history. + * dRep also will be the final repcode history sent to the next block. + * + * See ZSTD_seqStore_resolveOffCodes() for more details. + */ + repcodes_t dRep; + repcodes_t cRep; + ZSTD_memcpy(dRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); + ZSTD_memcpy(cRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); + ZSTD_memset(nextSeqStore, 0, sizeof(seqStore_t)); + + DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)", + (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, + (unsigned)zc->blockState.matchState.nextToUpdate); + + if (numSplits == 0) { + size_t cSizeSingleBlock = + ZSTD_compressSeqStore_singleBlock(zc, &zc->seqStore, + &dRep, &cRep, + op, dstCapacity, + ip, blockSize, + lastBlock, 0 /* isPartition */); + FORWARD_IF_ERROR(cSizeSingleBlock, "Compressing single block from splitBlock_internal() failed!"); + DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal: No splits"); + assert(zc->blockSize <= ZSTD_BLOCKSIZE_MAX); + assert(cSizeSingleBlock <= zc->blockSize + ZSTD_blockHeaderSize); + return cSizeSingleBlock; + } + + ZSTD_deriveSeqStoreChunk(currSeqStore, &zc->seqStore, 0, partitions[0]); + for (i = 0; i <= numSplits; ++i) { + size_t cSizeChunk; + U32 const lastPartition = (i == numSplits); + U32 lastBlockEntireSrc = 0; + + size_t srcBytes = ZSTD_countSeqStoreLiteralsBytes(currSeqStore) + ZSTD_countSeqStoreMatchBytes(currSeqStore); + srcBytesTotal += srcBytes; + if (lastPartition) { + /* This is the final partition, need to account for possible last literals */ + srcBytes += blockSize - srcBytesTotal; + lastBlockEntireSrc = lastBlock; + } else { + ZSTD_deriveSeqStoreChunk(nextSeqStore, &zc->seqStore, partitions[i], partitions[i+1]); + } + + cSizeChunk = ZSTD_compressSeqStore_singleBlock(zc, currSeqStore, + &dRep, &cRep, + op, dstCapacity, + ip, srcBytes, + lastBlockEntireSrc, 1 /* isPartition */); + DEBUGLOG(5, "Estimated size: %zu vs %zu : actual size", + ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(currSeqStore, zc), cSizeChunk); + FORWARD_IF_ERROR(cSizeChunk, "Compressing chunk failed!"); + + ip += srcBytes; + op += cSizeChunk; + dstCapacity -= cSizeChunk; + cSize += cSizeChunk; + *currSeqStore = *nextSeqStore; + assert(cSizeChunk <= zc->blockSize + ZSTD_blockHeaderSize); + } + /* cRep and dRep may have diverged during the compression. + * If so, we use the dRep repcodes for the next block. + */ + ZSTD_memcpy(zc->blockState.prevCBlock->rep, dRep.rep, sizeof(repcodes_t)); + return cSize; +} + +static size_t +ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, U32 lastBlock) +{ + U32 nbSeq; + size_t cSize; + DEBUGLOG(4, "ZSTD_compressBlock_splitBlock"); + assert(zc->appliedParams.useBlockSplitter == ZSTD_ps_enable); + + { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); + FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed"); + if (bss == ZSTDbss_noCompress) { + if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, "Uncompressible block"); + cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); + FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed"); + DEBUGLOG(4, "ZSTD_compressBlock_splitBlock: Nocompress block"); + return cSize; + } + nbSeq = (U32)(zc->seqStore.sequences - zc->seqStore.sequencesStart); + } + + cSize = ZSTD_compressBlock_splitBlock_internal(zc, dst, dstCapacity, src, srcSize, lastBlock, nbSeq); + FORWARD_IF_ERROR(cSize, "Splitting blocks failed!"); + return cSize; +} + +static size_t +ZSTD_compressBlock_internal(ZSTD_CCtx* zc, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, U32 frame) +{ + /* This is an estimated upper bound for the length of an rle block. + * This isn't the actual upper bound. + * Finding the real threshold needs further investigation. + */ + const U32 rleMaxLength = 25; + size_t cSize; + const BYTE* ip = (const BYTE*)src; + BYTE* op = (BYTE*)dst; + DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)", + (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, + (unsigned)zc->blockState.matchState.nextToUpdate); + + { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); + FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed"); + if (bss == ZSTDbss_noCompress) { + RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, "Uncompressible block"); + cSize = 0; + goto out; + } + } + + if (zc->seqCollector.collectSequences) { + FORWARD_IF_ERROR(ZSTD_copyBlockSequences(&zc->seqCollector, ZSTD_getSeqStore(zc), zc->blockState.prevCBlock->rep), "copyBlockSequences failed"); + ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); + return 0; + } + + /* encode sequences and literals */ + cSize = ZSTD_entropyCompressSeqStore(&zc->seqStore, + &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, + &zc->appliedParams, + dst, dstCapacity, + srcSize, + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + zc->bmi2); + + if (frame && + /* We don't want to emit our first block as a RLE even if it qualifies because + * doing so will cause the decoder (cli only) to throw a "should consume all input error." + * This is only an issue for zstd <= v1.4.3 + */ + !zc->isFirstBlock && + cSize < rleMaxLength && + ZSTD_isRLE(ip, srcSize)) + { + cSize = 1; + op[0] = ip[0]; + } + +out: + if (!ZSTD_isError(cSize) && cSize > 1) { + ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); + } + /* We check that dictionaries have offset codes available for the first + * block. After the first block, the offcode table might not have large + * enough codes to represent the offsets in the data. + */ + if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + + return cSize; +} + +static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const size_t bss, U32 lastBlock) +{ + DEBUGLOG(6, "Attempting ZSTD_compressSuperBlock()"); + if (bss == ZSTDbss_compress) { + if (/* We don't want to emit our first block as a RLE even if it qualifies because + * doing so will cause the decoder (cli only) to throw a "should consume all input error." + * This is only an issue for zstd <= v1.4.3 + */ + !zc->isFirstBlock && + ZSTD_maybeRLE(&zc->seqStore) && + ZSTD_isRLE((BYTE const*)src, srcSize)) + { + return ZSTD_rleCompressBlock(dst, dstCapacity, *(BYTE const*)src, srcSize, lastBlock); + } + /* Attempt superblock compression. + * + * Note that compressed size of ZSTD_compressSuperBlock() is not bound by the + * standard ZSTD_compressBound(). This is a problem, because even if we have + * space now, taking an extra byte now could cause us to run out of space later + * and violate ZSTD_compressBound(). + * + * Define blockBound(blockSize) = blockSize + ZSTD_blockHeaderSize. + * + * In order to respect ZSTD_compressBound() we must attempt to emit a raw + * uncompressed block in these cases: + * * cSize == 0: Return code for an uncompressed block. + * * cSize == dstSize_tooSmall: We may have expanded beyond blockBound(srcSize). + * ZSTD_noCompressBlock() will return dstSize_tooSmall if we are really out of + * output space. + * * cSize >= blockBound(srcSize): We have expanded the block too much so + * emit an uncompressed block. + */ + { size_t const cSize = + ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock); + if (cSize != ERROR(dstSize_tooSmall)) { + size_t const maxCSize = + srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy); + FORWARD_IF_ERROR(cSize, "ZSTD_compressSuperBlock failed"); + if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) { + ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState); + return cSize; + } + } + } + } /* if (bss == ZSTDbss_compress)*/ + + DEBUGLOG(6, "Resorting to ZSTD_noCompressBlock()"); + /* Superblock compression failed, attempt to emit a single no compress block. + * The decoder will be able to stream this block since it is uncompressed. + */ + return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); +} + +static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + U32 lastBlock) +{ + size_t cSize = 0; + const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); + DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)", + (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize); + FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed"); + + cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, dst, dstCapacity, src, srcSize, bss, lastBlock); + FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize_body failed"); + + if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + + return cSize; +} + +static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, + ZSTD_cwksp* ws, + ZSTD_CCtx_params const* params, + void const* ip, + void const* iend) +{ + U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy); + U32 const maxDist = (U32)1 << params->cParams.windowLog; + if (ZSTD_window_needOverflowCorrection(ms->window, cycleLog, maxDist, ms->loadedDictEnd, ip, iend)) { + U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip); + ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30); + ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30); + ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31); + ZSTD_cwksp_mark_tables_dirty(ws); + ZSTD_reduceIndex(ms, params, correction); + ZSTD_cwksp_mark_tables_clean(ws); + if (ms->nextToUpdate < correction) ms->nextToUpdate = 0; + else ms->nextToUpdate -= correction; + /* invalidate dictionaries on overflow correction */ + ms->loadedDictEnd = 0; + ms->dictMatchState = NULL; + } +} + +/*! ZSTD_compress_frameChunk() : +* Compress a chunk of data into one or multiple blocks. +* All blocks will be terminated, all input will be consumed. +* Function will issue an error if there is not enough `dstCapacity` to hold the compressed content. +* Frame is supposed already started (header already produced) +* @return : compressed size, or an error code +*/ +static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + U32 lastFrameChunk) +{ + size_t blockSize = cctx->blockSize; + size_t remaining = srcSize; + const BYTE* ip = (const BYTE*)src; + BYTE* const ostart = (BYTE*)dst; + BYTE* op = ostart; + U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog; + + assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); + + DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); + if (cctx->appliedParams.fParams.checksumFlag && srcSize) + XXH64_update(&cctx->xxhState, src, srcSize); + + while (remaining) { + ZSTD_matchState_t* const ms = &cctx->blockState.matchState; + U32 const lastBlock = lastFrameChunk & (blockSize >= remaining); + + /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding + * additional 1. We need to revisit and change this logic to be more consistent */ + RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE + 1, + dstSize_tooSmall, + "not enough space to store compressed block"); + if (remaining < blockSize) blockSize = remaining; + + ZSTD_overflowCorrectIfNeeded( + ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize); + ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState); + ZSTD_window_enforceMaxDist(&ms->window, ip, maxDist, &ms->loadedDictEnd, &ms->dictMatchState); + + /* Ensure hash/chain table insertion resumes no sooner than lowlimit */ + if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit; + + { size_t cSize; + if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) { + cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize failed"); + assert(cSize > 0); + assert(cSize <= blockSize + ZSTD_blockHeaderSize); + } else if (ZSTD_blockSplitterEnabled(&cctx->appliedParams)) { + cSize = ZSTD_compressBlock_splitBlock(cctx, op, dstCapacity, ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_splitBlock failed"); + assert(cSize > 0 || cctx->seqCollector.collectSequences == 1); + } else { + cSize = ZSTD_compressBlock_internal(cctx, + op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, + ip, blockSize, 1 /* frame */); + FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_internal failed"); + + if (cSize == 0) { /* block is not compressible */ + cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed"); + } else { + U32 const cBlockHeader = cSize == 1 ? + lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) : + lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); + MEM_writeLE24(op, cBlockHeader); + cSize += ZSTD_blockHeaderSize; + } + } /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/ + + + ip += blockSize; + assert(remaining >= blockSize); + remaining -= blockSize; + op += cSize; + assert(dstCapacity >= cSize); + dstCapacity -= cSize; + cctx->isFirstBlock = 0; + DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u", + (unsigned)cSize); + } } + + if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending; + return (size_t)(op-ostart); +} + + +static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, + const ZSTD_CCtx_params* params, U64 pledgedSrcSize, U32 dictID) +{ BYTE* const op = (BYTE*)dst; + U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */ + U32 const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */ + U32 const checksumFlag = params->fParams.checksumFlag>0; + U32 const windowSize = (U32)1 << params->cParams.windowLog; + U32 const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize); + BYTE const windowLogByte = (BYTE)((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); + U32 const fcsCode = params->fParams.contentSizeFlag ? + (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */ + BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) ); + size_t pos=0; + + assert(!(params->fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)); + RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall, + "dst buf is too small to fit worst-case frame header size."); + DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u", + !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode); + if (params->format == ZSTD_f_zstd1) { + MEM_writeLE32(dst, ZSTD_MAGICNUMBER); + pos = 4; + } + op[pos++] = frameHeaderDescriptionByte; + if (!singleSegment) op[pos++] = windowLogByte; + switch(dictIDSizeCode) + { + default: + assert(0); /* impossible */ + ZSTD_FALLTHROUGH; + case 0 : break; + case 1 : op[pos] = (BYTE)(dictID); pos++; break; + case 2 : MEM_writeLE16(op+pos, (U16)dictID); pos+=2; break; + case 3 : MEM_writeLE32(op+pos, dictID); pos+=4; break; + } + switch(fcsCode) + { + default: + assert(0); /* impossible */ + ZSTD_FALLTHROUGH; + case 0 : if (singleSegment) op[pos++] = (BYTE)(pledgedSrcSize); break; + case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break; + case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break; + case 3 : MEM_writeLE64(op+pos, (U64)(pledgedSrcSize)); pos+=8; break; + } + return pos; +} + +/* ZSTD_writeSkippableFrame_advanced() : + * Writes out a skippable frame with the specified magic number variant (16 are supported), + * from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15, and the desired source data. + * + * Returns the total number of bytes written, or a ZSTD error code. + */ +size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity, + const void* src, size_t srcSize, unsigned magicVariant) { + BYTE* op = (BYTE*)dst; + RETURN_ERROR_IF(dstCapacity < srcSize + ZSTD_SKIPPABLEHEADERSIZE /* Skippable frame overhead */, + dstSize_tooSmall, "Not enough room for skippable frame"); + RETURN_ERROR_IF(srcSize > (unsigned)0xFFFFFFFF, srcSize_wrong, "Src size too large for skippable frame"); + RETURN_ERROR_IF(magicVariant > 15, parameter_outOfBound, "Skippable frame magic number variant not supported"); + + MEM_writeLE32(op, (U32)(ZSTD_MAGIC_SKIPPABLE_START + magicVariant)); + MEM_writeLE32(op+4, (U32)srcSize); + ZSTD_memcpy(op+8, src, srcSize); + return srcSize + ZSTD_SKIPPABLEHEADERSIZE; +} + +/* ZSTD_writeLastEmptyBlock() : + * output an empty Block with end-of-frame mark to complete a frame + * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h)) + * or an error code if `dstCapacity` is too small (stage == ZSTDcs_init); + assert(nbSeq == 0 || cctx->appliedParams.ldmParams.enableLdm != ZSTD_ps_enable); + cctx->externSeqStore.seq = seq; + cctx->externSeqStore.size = nbSeq; + cctx->externSeqStore.capacity = nbSeq; + cctx->externSeqStore.pos = 0; + cctx->externSeqStore.posInSequence = 0; +} + + +static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + U32 frame, U32 lastFrameChunk) +{ + ZSTD_matchState_t* const ms = &cctx->blockState.matchState; + size_t fhSize = 0; + + DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u", + cctx->stage, (unsigned)srcSize); + RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong, + "missing init (ZSTD_compressBegin)"); + + if (frame && (cctx->stage==ZSTDcs_init)) { + fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, + cctx->pledgedSrcSizePlusOne-1, cctx->dictID); + FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed"); + assert(fhSize <= dstCapacity); + dstCapacity -= fhSize; + dst = (char*)dst + fhSize; + cctx->stage = ZSTDcs_ongoing; + } + + if (!srcSize) return fhSize; /* do not generate an empty block if no input */ + + if (!ZSTD_window_update(&ms->window, src, srcSize, ms->forceNonContiguous)) { + ms->forceNonContiguous = 0; + ms->nextToUpdate = ms->window.dictLimit; + } + if (cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) { + ZSTD_window_update(&cctx->ldmState.window, src, srcSize, /* forceNonContiguous */ 0); + } + + if (!frame) { + /* overflow check and correction for block mode */ + ZSTD_overflowCorrectIfNeeded( + ms, &cctx->workspace, &cctx->appliedParams, + src, (BYTE const*)src + srcSize); + } + + DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize); + { size_t const cSize = frame ? + ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) : + ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 /* frame */); + FORWARD_IF_ERROR(cSize, "%s", frame ? "ZSTD_compress_frameChunk failed" : "ZSTD_compressBlock_internal failed"); + cctx->consumedSrcSize += srcSize; + cctx->producedCSize += (cSize + fhSize); + assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); + if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */ + ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1); + RETURN_ERROR_IF( + cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne, + srcSize_wrong, + "error : pledgedSrcSize = %u, while realSrcSize >= %u", + (unsigned)cctx->pledgedSrcSizePlusOne-1, + (unsigned)cctx->consumedSrcSize); + } + return cSize + fhSize; + } +} + +size_t ZSTD_compressContinue_public(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + DEBUGLOG(5, "ZSTD_compressContinue (srcSize=%u)", (unsigned)srcSize); + return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 0 /* last chunk */); +} + +/* NOTE: Must just wrap ZSTD_compressContinue_public() */ +size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + return ZSTD_compressContinue_public(cctx, dst, dstCapacity, src, srcSize); +} + +static size_t ZSTD_getBlockSize_deprecated(const ZSTD_CCtx* cctx) +{ + ZSTD_compressionParameters const cParams = cctx->appliedParams.cParams; + assert(!ZSTD_checkCParams(cParams)); + return MIN(cctx->appliedParams.maxBlockSize, (size_t)1 << cParams.windowLog); +} + +/* NOTE: Must just wrap ZSTD_getBlockSize_deprecated() */ +size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx) +{ + return ZSTD_getBlockSize_deprecated(cctx); +} + +/* NOTE: Must just wrap ZSTD_compressBlock_deprecated() */ +size_t ZSTD_compressBlock_deprecated(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) +{ + DEBUGLOG(5, "ZSTD_compressBlock: srcSize = %u", (unsigned)srcSize); + { size_t const blockSizeMax = ZSTD_getBlockSize_deprecated(cctx); + RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong, "input is larger than a block"); } + + return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */); +} + +/* NOTE: Must just wrap ZSTD_compressBlock_deprecated() */ +size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) +{ + return ZSTD_compressBlock_deprecated(cctx, dst, dstCapacity, src, srcSize); +} + +/*! ZSTD_loadDictionaryContent() : + * @return : 0, or an error code + */ +static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, + ldmState_t* ls, + ZSTD_cwksp* ws, + ZSTD_CCtx_params const* params, + const void* src, size_t srcSize, + ZSTD_dictTableLoadMethod_e dtlm, + ZSTD_tableFillPurpose_e tfp) +{ + const BYTE* ip = (const BYTE*) src; + const BYTE* const iend = ip + srcSize; + int const loadLdmDict = params->ldmParams.enableLdm == ZSTD_ps_enable && ls != NULL; + + /* Assert that the ms params match the params we're being given */ + ZSTD_assertEqualCParams(params->cParams, ms->cParams); + + { /* Ensure large dictionaries can't cause index overflow */ + + /* Allow the dictionary to set indices up to exactly ZSTD_CURRENT_MAX. + * Dictionaries right at the edge will immediately trigger overflow + * correction, but I don't want to insert extra constraints here. + */ + U32 maxDictSize = ZSTD_CURRENT_MAX - ZSTD_WINDOW_START_INDEX; + + int const CDictTaggedIndices = ZSTD_CDictIndicesAreTagged(¶ms->cParams); + if (CDictTaggedIndices && tfp == ZSTD_tfp_forCDict) { + /* Some dictionary matchfinders in zstd use "short cache", + * which treats the lower ZSTD_SHORT_CACHE_TAG_BITS of each + * CDict hashtable entry as a tag rather than as part of an index. + * When short cache is used, we need to truncate the dictionary + * so that its indices don't overlap with the tag. */ + U32 const shortCacheMaxDictSize = (1u << (32 - ZSTD_SHORT_CACHE_TAG_BITS)) - ZSTD_WINDOW_START_INDEX; + maxDictSize = MIN(maxDictSize, shortCacheMaxDictSize); + assert(!loadLdmDict); + } + + /* If the dictionary is too large, only load the suffix of the dictionary. */ + if (srcSize > maxDictSize) { + ip = iend - maxDictSize; + src = ip; + srcSize = maxDictSize; + } + } + + if (srcSize > ZSTD_CHUNKSIZE_MAX) { + /* We must have cleared our windows when our source is this large. */ + assert(ZSTD_window_isEmpty(ms->window)); + if (loadLdmDict) assert(ZSTD_window_isEmpty(ls->window)); + } + ZSTD_window_update(&ms->window, src, srcSize, /* forceNonContiguous */ 0); + + DEBUGLOG(4, "ZSTD_loadDictionaryContent(): useRowMatchFinder=%d", (int)params->useRowMatchFinder); + + if (loadLdmDict) { /* Load the entire dict into LDM matchfinders. */ + ZSTD_window_update(&ls->window, src, srcSize, /* forceNonContiguous */ 0); + ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base); + ZSTD_ldm_fillHashTable(ls, ip, iend, ¶ms->ldmParams); + } + + /* If the dict is larger than we can reasonably index in our tables, only load the suffix. */ + if (params->cParams.strategy < ZSTD_btultra) { + U32 maxDictSize = 8U << MIN(MAX(params->cParams.hashLog, params->cParams.chainLog), 28); + if (srcSize > maxDictSize) { + ip = iend - maxDictSize; + src = ip; + srcSize = maxDictSize; + } + } + + ms->nextToUpdate = (U32)(ip - ms->window.base); + ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base); + ms->forceNonContiguous = params->deterministicRefPrefix; + + if (srcSize <= HASH_READ_SIZE) return 0; + + ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, iend); + + switch(params->cParams.strategy) + { + case ZSTD_fast: + ZSTD_fillHashTable(ms, iend, dtlm, tfp); + break; + case ZSTD_dfast: +#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR + ZSTD_fillDoubleHashTable(ms, iend, dtlm, tfp); +#else + assert(0); /* shouldn't be called: cparams should've been adjusted. */ +#endif + break; + + case ZSTD_greedy: + case ZSTD_lazy: + case ZSTD_lazy2: +#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) + assert(srcSize >= HASH_READ_SIZE); + if (ms->dedicatedDictSearch) { + assert(ms->chainTable != NULL); + ZSTD_dedicatedDictSearch_lazy_loadDictionary(ms, iend-HASH_READ_SIZE); + } else { + assert(params->useRowMatchFinder != ZSTD_ps_auto); + if (params->useRowMatchFinder == ZSTD_ps_enable) { + size_t const tagTableSize = ((size_t)1 << params->cParams.hashLog); + ZSTD_memset(ms->tagTable, 0, tagTableSize); + ZSTD_row_update(ms, iend-HASH_READ_SIZE); + DEBUGLOG(4, "Using row-based hash table for lazy dict"); + } else { + ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE); + DEBUGLOG(4, "Using chain-based hash table for lazy dict"); + } + } +#else + assert(0); /* shouldn't be called: cparams should've been adjusted. */ +#endif + break; + + case ZSTD_btlazy2: /* we want the dictionary table fully sorted */ + case ZSTD_btopt: + case ZSTD_btultra: + case ZSTD_btultra2: +#if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR) + assert(srcSize >= HASH_READ_SIZE); + ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend); +#else + assert(0); /* shouldn't be called: cparams should've been adjusted. */ +#endif + break; + + default: + assert(0); /* not possible : not a valid strategy id */ + } + + ms->nextToUpdate = (U32)(iend - ms->window.base); + return 0; +} + + +/* Dictionaries that assign zero probability to symbols that show up causes problems + * when FSE encoding. Mark dictionaries with zero probability symbols as FSE_repeat_check + * and only dictionaries with 100% valid symbols can be assumed valid. + */ +static FSE_repeat ZSTD_dictNCountRepeat(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) +{ + U32 s; + if (dictMaxSymbolValue < maxSymbolValue) { + return FSE_repeat_check; + } + for (s = 0; s <= maxSymbolValue; ++s) { + if (normalizedCounter[s] == 0) { + return FSE_repeat_check; + } + } + return FSE_repeat_valid; +} + +size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, + const void* const dict, size_t dictSize) +{ + short offcodeNCount[MaxOff+1]; + unsigned offcodeMaxValue = MaxOff; + const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */ + const BYTE* const dictEnd = dictPtr + dictSize; + dictPtr += 8; + bs->entropy.huf.repeatMode = HUF_repeat_check; + + { unsigned maxSymbolValue = 255; + unsigned hasZeroWeights = 1; + size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, + dictEnd-dictPtr, &hasZeroWeights); + + /* We only set the loaded table as valid if it contains all non-zero + * weights. Otherwise, we set it to check */ + if (!hasZeroWeights && maxSymbolValue == 255) + bs->entropy.huf.repeatMode = HUF_repeat_valid; + + RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, ""); + dictPtr += hufHeaderSize; + } + + { unsigned offcodeLog; + size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); + RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, ""); + RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, ""); + /* fill all offset symbols to avoid garbage at end of table */ + RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( + bs->entropy.fse.offcodeCTable, + offcodeNCount, MaxOff, offcodeLog, + workspace, HUF_WORKSPACE_SIZE)), + dictionary_corrupted, ""); + /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ + dictPtr += offcodeHeaderSize; + } + + { short matchlengthNCount[MaxML+1]; + unsigned matchlengthMaxValue = MaxML, matchlengthLog; + size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); + RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, ""); + RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, ""); + RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( + bs->entropy.fse.matchlengthCTable, + matchlengthNCount, matchlengthMaxValue, matchlengthLog, + workspace, HUF_WORKSPACE_SIZE)), + dictionary_corrupted, ""); + bs->entropy.fse.matchlength_repeatMode = ZSTD_dictNCountRepeat(matchlengthNCount, matchlengthMaxValue, MaxML); + dictPtr += matchlengthHeaderSize; + } + + { short litlengthNCount[MaxLL+1]; + unsigned litlengthMaxValue = MaxLL, litlengthLog; + size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); + RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, ""); + RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, ""); + RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( + bs->entropy.fse.litlengthCTable, + litlengthNCount, litlengthMaxValue, litlengthLog, + workspace, HUF_WORKSPACE_SIZE)), + dictionary_corrupted, ""); + bs->entropy.fse.litlength_repeatMode = ZSTD_dictNCountRepeat(litlengthNCount, litlengthMaxValue, MaxLL); + dictPtr += litlengthHeaderSize; + } + + RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, ""); + bs->rep[0] = MEM_readLE32(dictPtr+0); + bs->rep[1] = MEM_readLE32(dictPtr+4); + bs->rep[2] = MEM_readLE32(dictPtr+8); + dictPtr += 12; + + { size_t const dictContentSize = (size_t)(dictEnd - dictPtr); + U32 offcodeMax = MaxOff; + if (dictContentSize <= ((U32)-1) - 128 KB) { + U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */ + offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */ + } + /* All offset values <= dictContentSize + 128 KB must be representable for a valid table */ + bs->entropy.fse.offcode_repeatMode = ZSTD_dictNCountRepeat(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)); + + /* All repCodes must be <= dictContentSize and != 0 */ + { U32 u; + for (u=0; u<3; u++) { + RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, ""); + RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, ""); + } } } + + return dictPtr - (const BYTE*)dict; +} + +/* Dictionary format : + * See : + * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#dictionary-format + */ +/*! ZSTD_loadZstdDictionary() : + * @return : dictID, or an error code + * assumptions : magic number supposed already checked + * dictSize supposed >= 8 + */ +static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, + ZSTD_matchState_t* ms, + ZSTD_cwksp* ws, + ZSTD_CCtx_params const* params, + const void* dict, size_t dictSize, + ZSTD_dictTableLoadMethod_e dtlm, + ZSTD_tableFillPurpose_e tfp, + void* workspace) +{ + const BYTE* dictPtr = (const BYTE*)dict; + const BYTE* const dictEnd = dictPtr + dictSize; + size_t dictID; + size_t eSize; + ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<= 8); + assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); + + dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ ); + eSize = ZSTD_loadCEntropy(bs, workspace, dict, dictSize); + FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed"); + dictPtr += eSize; + + { + size_t const dictContentSize = (size_t)(dictEnd - dictPtr); + FORWARD_IF_ERROR(ZSTD_loadDictionaryContent( + ms, NULL, ws, params, dictPtr, dictContentSize, dtlm, tfp), ""); + } + return dictID; +} + +/** ZSTD_compress_insertDictionary() : +* @return : dictID, or an error code */ +static size_t +ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, + ZSTD_matchState_t* ms, + ldmState_t* ls, + ZSTD_cwksp* ws, + const ZSTD_CCtx_params* params, + const void* dict, size_t dictSize, + ZSTD_dictContentType_e dictContentType, + ZSTD_dictTableLoadMethod_e dtlm, + ZSTD_tableFillPurpose_e tfp, + void* workspace) +{ + DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize); + if ((dict==NULL) || (dictSize<8)) { + RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, ""); + return 0; + } + + ZSTD_reset_compressedBlockState(bs); + + /* dict restricted modes */ + if (dictContentType == ZSTD_dct_rawContent) + return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm, tfp); + + if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) { + if (dictContentType == ZSTD_dct_auto) { + DEBUGLOG(4, "raw content dictionary detected"); + return ZSTD_loadDictionaryContent( + ms, ls, ws, params, dict, dictSize, dtlm, tfp); + } + RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, ""); + assert(0); /* impossible */ + } + + /* dict as full zstd dictionary */ + return ZSTD_loadZstdDictionary( + bs, ms, ws, params, dict, dictSize, dtlm, tfp, workspace); +} + +#define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB) +#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6ULL) + +/*! ZSTD_compressBegin_internal() : + * Assumption : either @dict OR @cdict (or none) is non-NULL, never both + * @return : 0, or an error code */ +static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, + const void* dict, size_t dictSize, + ZSTD_dictContentType_e dictContentType, + ZSTD_dictTableLoadMethod_e dtlm, + const ZSTD_CDict* cdict, + const ZSTD_CCtx_params* params, U64 pledgedSrcSize, + ZSTD_buffered_policy_e zbuff) +{ + size_t const dictContentSize = cdict ? cdict->dictContentSize : dictSize; +#if ZSTD_TRACE + cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0; +#endif + DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog); + /* params are supposed to be fully validated at this point */ + assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); + assert(!((dict) && (cdict))); /* either dict or cdict, not both */ + if ( (cdict) + && (cdict->dictContentSize > 0) + && ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF + || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER + || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN + || cdict->compressionLevel == 0) + && (params->attachDictPref != ZSTD_dictForceLoad) ) { + return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff); + } + + FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, + dictContentSize, + ZSTDcrp_makeClean, zbuff) , ""); + { size_t const dictID = cdict ? + ZSTD_compress_insertDictionary( + cctx->blockState.prevCBlock, &cctx->blockState.matchState, + &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent, + cdict->dictContentSize, cdict->dictContentType, dtlm, + ZSTD_tfp_forCCtx, cctx->entropyWorkspace) + : ZSTD_compress_insertDictionary( + cctx->blockState.prevCBlock, &cctx->blockState.matchState, + &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize, + dictContentType, dtlm, ZSTD_tfp_forCCtx, cctx->entropyWorkspace); + FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed"); + assert(dictID <= UINT_MAX); + cctx->dictID = (U32)dictID; + cctx->dictContentSize = dictContentSize; + } + return 0; +} + +size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx, + const void* dict, size_t dictSize, + ZSTD_dictContentType_e dictContentType, + ZSTD_dictTableLoadMethod_e dtlm, + const ZSTD_CDict* cdict, + const ZSTD_CCtx_params* params, + unsigned long long pledgedSrcSize) +{ + DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog); + /* compression parameters verification and optimization */ + FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , ""); + return ZSTD_compressBegin_internal(cctx, + dict, dictSize, dictContentType, dtlm, + cdict, + params, pledgedSrcSize, + ZSTDb_not_buffered); +} + +/*! ZSTD_compressBegin_advanced() : +* @return : 0, or an error code */ +size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, + const void* dict, size_t dictSize, + ZSTD_parameters params, unsigned long long pledgedSrcSize) +{ + ZSTD_CCtx_params cctxParams; + ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, ZSTD_NO_CLEVEL); + return ZSTD_compressBegin_advanced_internal(cctx, + dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, + NULL /*cdict*/, + &cctxParams, pledgedSrcSize); +} + +static size_t +ZSTD_compressBegin_usingDict_deprecated(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) +{ + ZSTD_CCtx_params cctxParams; + { ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict); + ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel); + } + DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize); + return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL, + &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered); +} + +size_t +ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) +{ + return ZSTD_compressBegin_usingDict_deprecated(cctx, dict, dictSize, compressionLevel); +} + +size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel) +{ + return ZSTD_compressBegin_usingDict_deprecated(cctx, NULL, 0, compressionLevel); +} + + +/*! ZSTD_writeEpilogue() : +* Ends a frame. +* @return : nb of bytes written into dst (or an error code) */ +static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) +{ + BYTE* const ostart = (BYTE*)dst; + BYTE* op = ostart; + + DEBUGLOG(4, "ZSTD_writeEpilogue"); + RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing"); + + /* special case : empty frame */ + if (cctx->stage == ZSTDcs_init) { + size_t fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0); + FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed"); + dstCapacity -= fhSize; + op += fhSize; + cctx->stage = ZSTDcs_ongoing; + } + + if (cctx->stage != ZSTDcs_ending) { + /* write one last empty block, make it the "last" block */ + U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0; + ZSTD_STATIC_ASSERT(ZSTD_BLOCKHEADERSIZE == 3); + RETURN_ERROR_IF(dstCapacity<3, dstSize_tooSmall, "no room for epilogue"); + MEM_writeLE24(op, cBlockHeader24); + op += ZSTD_blockHeaderSize; + dstCapacity -= ZSTD_blockHeaderSize; + } + + if (cctx->appliedParams.fParams.checksumFlag) { + U32 const checksum = (U32) XXH64_digest(&cctx->xxhState); + RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum"); + DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum); + MEM_writeLE32(op, checksum); + op += 4; + } + + cctx->stage = ZSTDcs_created; /* return to "created but no init" status */ + return op-ostart; +} + +void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize) +{ +#if ZSTD_TRACE + if (cctx->traceCtx && ZSTD_trace_compress_end != NULL) { + int const streaming = cctx->inBuffSize > 0 || cctx->outBuffSize > 0 || cctx->appliedParams.nbWorkers > 0; + ZSTD_Trace trace; + ZSTD_memset(&trace, 0, sizeof(trace)); + trace.version = ZSTD_VERSION_NUMBER; + trace.streaming = streaming; + trace.dictionaryID = cctx->dictID; + trace.dictionarySize = cctx->dictContentSize; + trace.uncompressedSize = cctx->consumedSrcSize; + trace.compressedSize = cctx->producedCSize + extraCSize; + trace.params = &cctx->appliedParams; + trace.cctx = cctx; + ZSTD_trace_compress_end(cctx->traceCtx, &trace); + } + cctx->traceCtx = 0; +#else + (void)cctx; + (void)extraCSize; +#endif +} + +size_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + size_t endResult; + size_t const cSize = ZSTD_compressContinue_internal(cctx, + dst, dstCapacity, src, srcSize, + 1 /* frame mode */, 1 /* last chunk */); + FORWARD_IF_ERROR(cSize, "ZSTD_compressContinue_internal failed"); + endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize); + FORWARD_IF_ERROR(endResult, "ZSTD_writeEpilogue failed"); + assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); + if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */ + ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1); + DEBUGLOG(4, "end of frame : controlling src size"); + RETURN_ERROR_IF( + cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1, + srcSize_wrong, + "error : pledgedSrcSize = %u, while realSrcSize = %u", + (unsigned)cctx->pledgedSrcSizePlusOne-1, + (unsigned)cctx->consumedSrcSize); + } + ZSTD_CCtx_trace(cctx, endResult); + return cSize + endResult; +} + +/* NOTE: Must just wrap ZSTD_compressEnd_public() */ +size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + return ZSTD_compressEnd_public(cctx, dst, dstCapacity, src, srcSize); +} + +size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize, + ZSTD_parameters params) +{ + DEBUGLOG(4, "ZSTD_compress_advanced"); + FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), ""); + ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, ¶ms, ZSTD_NO_CLEVEL); + return ZSTD_compress_advanced_internal(cctx, + dst, dstCapacity, + src, srcSize, + dict, dictSize, + &cctx->simpleApiParams); +} + +/* Internal */ +size_t ZSTD_compress_advanced_internal( + ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize, + const ZSTD_CCtx_params* params) +{ + DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize); + FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, + dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL, + params, srcSize, ZSTDb_not_buffered) , ""); + return ZSTD_compressEnd_public(cctx, dst, dstCapacity, src, srcSize); +} + +size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict, size_t dictSize, + int compressionLevel) +{ + { + ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict); + assert(params.fParams.contentSizeFlag == 1); + ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel); + } + DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize); + return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctx->simpleApiParams); +} + +size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel) +{ + DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (unsigned)srcSize); + assert(cctx != NULL); + return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel); +} + +size_t ZSTD_compress(void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel) +{ + size_t result; +#if ZSTD_COMPRESS_HEAPMODE + ZSTD_CCtx* cctx = ZSTD_createCCtx(); + RETURN_ERROR_IF(!cctx, memory_allocation, "ZSTD_createCCtx failed"); + result = ZSTD_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel); + ZSTD_freeCCtx(cctx); +#else + ZSTD_CCtx ctxBody; + ZSTD_initCCtx(&ctxBody, ZSTD_defaultCMem); + result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel); + ZSTD_freeCCtxContent(&ctxBody); /* can't free ctxBody itself, as it's on stack; free only heap content */ +#endif + return result; +} + + +/* ===== Dictionary API ===== */ + +/*! ZSTD_estimateCDictSize_advanced() : + * Estimate amount of memory that will be needed to create a dictionary with following arguments */ +size_t ZSTD_estimateCDictSize_advanced( + size_t dictSize, ZSTD_compressionParameters cParams, + ZSTD_dictLoadMethod_e dictLoadMethod) +{ + DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict)); + return ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) + + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) + /* enableDedicatedDictSearch == 1 ensures that CDict estimation will not be too small + * in case we are using DDS with row-hash. */ + + ZSTD_sizeof_matchState(&cParams, ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams), + /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0) + + (dictLoadMethod == ZSTD_dlm_byRef ? 0 + : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *)))); +} + +size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel) +{ + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); +} + +size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict) +{ + if (cdict==NULL) return 0; /* support sizeof on NULL */ + DEBUGLOG(5, "sizeof(*cdict) : %u", (unsigned)sizeof(*cdict)); + /* cdict may be in the workspace */ + return (cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict)) + + ZSTD_cwksp_sizeof(&cdict->workspace); +} + +static size_t ZSTD_initCDict_internal( + ZSTD_CDict* cdict, + const void* dictBuffer, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_CCtx_params params) +{ + DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType); + assert(!ZSTD_checkCParams(params.cParams)); + cdict->matchState.cParams = params.cParams; + cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch; + if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) { + cdict->dictContent = dictBuffer; + } else { + void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*))); + RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!"); + cdict->dictContent = internalBuffer; + ZSTD_memcpy(internalBuffer, dictBuffer, dictSize); + } + cdict->dictContentSize = dictSize; + cdict->dictContentType = dictContentType; + + cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE); + + + /* Reset the state to no dictionary */ + ZSTD_reset_compressedBlockState(&cdict->cBlockState); + FORWARD_IF_ERROR(ZSTD_reset_matchState( + &cdict->matchState, + &cdict->workspace, + ¶ms.cParams, + params.useRowMatchFinder, + ZSTDcrp_makeClean, + ZSTDirp_reset, + ZSTD_resetTarget_CDict), ""); + /* (Maybe) load the dictionary + * Skips loading the dictionary if it is < 8 bytes. + */ + { params.compressionLevel = ZSTD_CLEVEL_DEFAULT; + params.fParams.contentSizeFlag = 1; + { size_t const dictID = ZSTD_compress_insertDictionary( + &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace, + ¶ms, cdict->dictContent, cdict->dictContentSize, + dictContentType, ZSTD_dtlm_full, ZSTD_tfp_forCDict, cdict->entropyWorkspace); + FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed"); + assert(dictID <= (size_t)(U32)-1); + cdict->dictID = (U32)dictID; + } + } + + return 0; +} + +static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_compressionParameters cParams, + ZSTD_paramSwitch_e useRowMatchFinder, + U32 enableDedicatedDictSearch, + ZSTD_customMem customMem) +{ + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; + + { size_t const workspaceSize = + ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) + + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) + + ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, enableDedicatedDictSearch, /* forCCtx */ 0) + + (dictLoadMethod == ZSTD_dlm_byRef ? 0 + : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*)))); + void* const workspace = ZSTD_customMalloc(workspaceSize, customMem); + ZSTD_cwksp ws; + ZSTD_CDict* cdict; + + if (!workspace) { + ZSTD_customFree(workspace, customMem); + return NULL; + } + + ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_dynamic_alloc); + + cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict)); + assert(cdict != NULL); + ZSTD_cwksp_move(&cdict->workspace, &ws); + cdict->customMem = customMem; + cdict->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */ + cdict->useRowMatchFinder = useRowMatchFinder; + return cdict; + } +} + +ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams, + ZSTD_customMem customMem) +{ + ZSTD_CCtx_params cctxParams; + ZSTD_memset(&cctxParams, 0, sizeof(cctxParams)); + ZSTD_CCtxParams_init(&cctxParams, 0); + cctxParams.cParams = cParams; + cctxParams.customMem = customMem; + return ZSTD_createCDict_advanced2( + dictBuffer, dictSize, + dictLoadMethod, dictContentType, + &cctxParams, customMem); +} + +ZSTD_CDict* ZSTD_createCDict_advanced2( + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + const ZSTD_CCtx_params* originalCctxParams, + ZSTD_customMem customMem) +{ + ZSTD_CCtx_params cctxParams = *originalCctxParams; + ZSTD_compressionParameters cParams; + ZSTD_CDict* cdict; + + DEBUGLOG(3, "ZSTD_createCDict_advanced2, mode %u", (unsigned)dictContentType); + if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + + if (cctxParams.enableDedicatedDictSearch) { + cParams = ZSTD_dedicatedDictSearch_getCParams( + cctxParams.compressionLevel, dictSize); + ZSTD_overrideCParams(&cParams, &cctxParams.cParams); + } else { + cParams = ZSTD_getCParamsFromCCtxParams( + &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + } + + if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) { + /* Fall back to non-DDSS params */ + cctxParams.enableDedicatedDictSearch = 0; + cParams = ZSTD_getCParamsFromCCtxParams( + &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + } + + DEBUGLOG(3, "ZSTD_createCDict_advanced2: DDS: %u", cctxParams.enableDedicatedDictSearch); + cctxParams.cParams = cParams; + cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams); + + cdict = ZSTD_createCDict_advanced_internal(dictSize, + dictLoadMethod, cctxParams.cParams, + cctxParams.useRowMatchFinder, cctxParams.enableDedicatedDictSearch, + customMem); + + if (!cdict || ZSTD_isError( ZSTD_initCDict_internal(cdict, + dict, dictSize, + dictLoadMethod, dictContentType, + cctxParams) )) { + ZSTD_freeCDict(cdict); + return NULL; + } + + return cdict; +} + +ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel) +{ + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize, + ZSTD_dlm_byCopy, ZSTD_dct_auto, + cParams, ZSTD_defaultCMem); + if (cdict) + cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; + return cdict; +} + +ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel) +{ + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize, + ZSTD_dlm_byRef, ZSTD_dct_auto, + cParams, ZSTD_defaultCMem); + if (cdict) + cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; + return cdict; +} + +size_t ZSTD_freeCDict(ZSTD_CDict* cdict) +{ + if (cdict==NULL) return 0; /* support free on NULL */ + { ZSTD_customMem const cMem = cdict->customMem; + int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict); + ZSTD_cwksp_free(&cdict->workspace, cMem); + if (!cdictInWorkspace) { + ZSTD_customFree(cdict, cMem); + } + return 0; + } +} + +/*! ZSTD_initStaticCDict_advanced() : + * Generate a digested dictionary in provided memory area. + * workspace: The memory area to emplace the dictionary into. + * Provided pointer must 8-bytes aligned. + * It must outlive dictionary usage. + * workspaceSize: Use ZSTD_estimateCDictSize() + * to determine how large workspace must be. + * cParams : use ZSTD_getCParams() to transform a compression level + * into its relevants cParams. + * @return : pointer to ZSTD_CDict*, or NULL if error (size too small) + * Note : there is no corresponding "free" function. + * Since workspace was allocated externally, it must be freed externally. + */ +const ZSTD_CDict* ZSTD_initStaticCDict( + void* workspace, size_t workspaceSize, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams) +{ + ZSTD_paramSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams); + /* enableDedicatedDictSearch == 1 ensures matchstate is not too small in case this CDict will be used for DDS + row hash */ + size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0); + size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) + + (dictLoadMethod == ZSTD_dlm_byRef ? 0 + : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*)))) + + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) + + matchStateSize; + ZSTD_CDict* cdict; + ZSTD_CCtx_params params; + + if ((size_t)workspace & 7) return NULL; /* 8-aligned */ + + { + ZSTD_cwksp ws; + ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc); + cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict)); + if (cdict == NULL) return NULL; + ZSTD_cwksp_move(&cdict->workspace, &ws); + } + + DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u", + (unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize)); + if (workspaceSize < neededSize) return NULL; + + ZSTD_CCtxParams_init(¶ms, 0); + params.cParams = cParams; + params.useRowMatchFinder = useRowMatchFinder; + cdict->useRowMatchFinder = useRowMatchFinder; + cdict->compressionLevel = ZSTD_NO_CLEVEL; + + if (ZSTD_isError( ZSTD_initCDict_internal(cdict, + dict, dictSize, + dictLoadMethod, dictContentType, + params) )) + return NULL; + + return cdict; +} + +ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) +{ + assert(cdict != NULL); + return cdict->matchState.cParams; +} + +/*! ZSTD_getDictID_fromCDict() : + * Provides the dictID of the dictionary loaded into `cdict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict) +{ + if (cdict==NULL) return 0; + return cdict->dictID; +} + +/* ZSTD_compressBegin_usingCDict_internal() : + * Implementation of various ZSTD_compressBegin_usingCDict* functions. + */ +static size_t ZSTD_compressBegin_usingCDict_internal( + ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, + ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize) +{ + ZSTD_CCtx_params cctxParams; + DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_internal"); + RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!"); + /* Initialize the cctxParams from the cdict */ + { + ZSTD_parameters params; + params.fParams = fParams; + params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF + || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER + || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN + || cdict->compressionLevel == 0 ) ? + ZSTD_getCParamsFromCDict(cdict) + : ZSTD_getCParams(cdict->compressionLevel, + pledgedSrcSize, + cdict->dictContentSize); + ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->compressionLevel); + } + /* Increase window log to fit the entire dictionary and source if the + * source size is known. Limit the increase to 19, which is the + * window log for compression level 1 with the largest source size. + */ + if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) { + U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19); + U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1; + cctxParams.cParams.windowLog = MAX(cctxParams.cParams.windowLog, limitedSrcLog); + } + return ZSTD_compressBegin_internal(cctx, + NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, + cdict, + &cctxParams, pledgedSrcSize, + ZSTDb_not_buffered); +} + + +/* ZSTD_compressBegin_usingCDict_advanced() : + * This function is DEPRECATED. + * cdict must be != NULL */ +size_t ZSTD_compressBegin_usingCDict_advanced( + ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, + ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize) +{ + return ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, pledgedSrcSize); +} + +/* ZSTD_compressBegin_usingCDict() : + * cdict must be != NULL */ +size_t ZSTD_compressBegin_usingCDict_deprecated(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) +{ + ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; + return ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); +} + +size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) +{ + return ZSTD_compressBegin_usingCDict_deprecated(cctx, cdict); +} + +/*! ZSTD_compress_usingCDict_internal(): + * Implementation of various ZSTD_compress_usingCDict* functions. + */ +static size_t ZSTD_compress_usingCDict_internal(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict, ZSTD_frameParameters fParams) +{ + FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, srcSize), ""); /* will check if cdict != NULL */ + return ZSTD_compressEnd_public(cctx, dst, dstCapacity, src, srcSize); +} + +/*! ZSTD_compress_usingCDict_advanced(): + * This function is DEPRECATED. + */ +size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict, ZSTD_frameParameters fParams) +{ + return ZSTD_compress_usingCDict_internal(cctx, dst, dstCapacity, src, srcSize, cdict, fParams); +} + +/*! ZSTD_compress_usingCDict() : + * Compression using a digested Dictionary. + * Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times. + * Note that compression parameters are decided at CDict creation time + * while frame parameters are hardcoded */ +size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict) +{ + ZSTD_frameParameters const fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; + return ZSTD_compress_usingCDict_internal(cctx, dst, dstCapacity, src, srcSize, cdict, fParams); +} + + + +/* ****************************************************************** +* Streaming +********************************************************************/ + +ZSTD_CStream* ZSTD_createCStream(void) +{ + DEBUGLOG(3, "ZSTD_createCStream"); + return ZSTD_createCStream_advanced(ZSTD_defaultCMem); +} + +ZSTD_CStream* ZSTD_initStaticCStream(void *workspace, size_t workspaceSize) +{ + return ZSTD_initStaticCCtx(workspace, workspaceSize); +} + +ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem) +{ /* CStream and CCtx are now same object */ + return ZSTD_createCCtx_advanced(customMem); +} + +size_t ZSTD_freeCStream(ZSTD_CStream* zcs) +{ + return ZSTD_freeCCtx(zcs); /* same object */ +} + + + +/*====== Initialization ======*/ + +size_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX; } + +size_t ZSTD_CStreamOutSize(void) +{ + return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ; +} + +static ZSTD_cParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize) +{ + if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) + return ZSTD_cpm_attachDict; + else + return ZSTD_cpm_noAttachDict; +} + +/* ZSTD_resetCStream(): + * pledgedSrcSize == 0 means "unknown" */ +size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss) +{ + /* temporary : 0 interpreted as "unknown" during transition period. + * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. + * 0 will be interpreted as "empty" in the future. + */ + U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; + DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); + return 0; +} + +/*! ZSTD_initCStream_internal() : + * Note : for lib/compress only. Used by zstdmt_compress.c. + * Assumption 1 : params are valid + * Assumption 2 : either dict, or cdict, is defined, not both */ +size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs, + const void* dict, size_t dictSize, const ZSTD_CDict* cdict, + const ZSTD_CCtx_params* params, + unsigned long long pledgedSrcSize) +{ + DEBUGLOG(4, "ZSTD_initCStream_internal"); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); + assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); + zcs->requestedParams = *params; + assert(!((dict) && (cdict))); /* either dict or cdict, not both */ + if (dict) { + FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); + } else { + /* Dictionary is cleared if !cdict */ + FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , ""); + } + return 0; +} + +/* ZSTD_initCStream_usingCDict_advanced() : + * same as ZSTD_initCStream_usingCDict(), with control over frame parameters */ +size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, + const ZSTD_CDict* cdict, + ZSTD_frameParameters fParams, + unsigned long long pledgedSrcSize) +{ + DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced"); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); + zcs->requestedParams.fParams = fParams; + FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , ""); + return 0; +} + +/* note : cdict must outlive compression session */ +size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict) +{ + DEBUGLOG(4, "ZSTD_initCStream_usingCDict"); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , ""); + return 0; +} + + +/* ZSTD_initCStream_advanced() : + * pledgedSrcSize must be exact. + * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. + * dict is loaded with default parameters ZSTD_dct_auto and ZSTD_dlm_byCopy. */ +size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, + const void* dict, size_t dictSize, + ZSTD_parameters params, unsigned long long pss) +{ + /* for compatibility with older programs relying on this behavior. + * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. + * This line will be removed in the future. + */ + U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; + DEBUGLOG(4, "ZSTD_initCStream_advanced"); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); + FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); + ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, ¶ms); + FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); + return 0; +} + +size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel) +{ + DEBUGLOG(4, "ZSTD_initCStream_usingDict"); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); + return 0; +} + +size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss) +{ + /* temporary : 0 interpreted as "unknown" during transition period. + * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. + * 0 will be interpreted as "empty" in the future. + */ + U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; + DEBUGLOG(4, "ZSTD_initCStream_srcSize"); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); + return 0; +} + +size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel) +{ + DEBUGLOG(4, "ZSTD_initCStream"); + FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , ""); + FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , ""); + return 0; +} + +/*====== Compression ======*/ + +static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx) +{ + if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) { + return cctx->blockSize - cctx->stableIn_notConsumed; + } + assert(cctx->appliedParams.inBufferMode == ZSTD_bm_buffered); + { size_t hintInSize = cctx->inBuffTarget - cctx->inBuffPos; + if (hintInSize==0) hintInSize = cctx->blockSize; + return hintInSize; + } +} + +/** ZSTD_compressStream_generic(): + * internal function for all *compressStream*() variants + * @return : hint size for next input to complete ongoing block */ +static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input, + ZSTD_EndDirective const flushMode) +{ + const char* const istart = (assert(input != NULL), (const char*)input->src); + const char* const iend = (istart != NULL) ? istart + input->size : istart; + const char* ip = (istart != NULL) ? istart + input->pos : istart; + char* const ostart = (assert(output != NULL), (char*)output->dst); + char* const oend = (ostart != NULL) ? ostart + output->size : ostart; + char* op = (ostart != NULL) ? ostart + output->pos : ostart; + U32 someMoreWork = 1; + + /* check expectations */ + DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%i, srcSize = %zu", (int)flushMode, input->size - input->pos); + assert(zcs != NULL); + if (zcs->appliedParams.inBufferMode == ZSTD_bm_stable) { + assert(input->pos >= zcs->stableIn_notConsumed); + input->pos -= zcs->stableIn_notConsumed; + if (ip) ip -= zcs->stableIn_notConsumed; + zcs->stableIn_notConsumed = 0; + } + if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) { + assert(zcs->inBuff != NULL); + assert(zcs->inBuffSize > 0); + } + if (zcs->appliedParams.outBufferMode == ZSTD_bm_buffered) { + assert(zcs->outBuff != NULL); + assert(zcs->outBuffSize > 0); + } + if (input->src == NULL) assert(input->size == 0); + assert(input->pos <= input->size); + if (output->dst == NULL) assert(output->size == 0); + assert(output->pos <= output->size); + assert((U32)flushMode <= (U32)ZSTD_e_end); + + while (someMoreWork) { + switch(zcs->streamStage) + { + case zcss_init: + RETURN_ERROR(init_missing, "call ZSTD_initCStream() first!"); + + case zcss_load: + if ( (flushMode == ZSTD_e_end) + && ( (size_t)(oend-op) >= ZSTD_compressBound(iend-ip) /* Enough output space */ + || zcs->appliedParams.outBufferMode == ZSTD_bm_stable) /* OR we are allowed to return dstSizeTooSmall */ + && (zcs->inBuffPos == 0) ) { + /* shortcut to compression pass directly into output buffer */ + size_t const cSize = ZSTD_compressEnd_public(zcs, + op, oend-op, ip, iend-ip); + DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize); + FORWARD_IF_ERROR(cSize, "ZSTD_compressEnd failed"); + ip = iend; + op += cSize; + zcs->frameEnded = 1; + ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + someMoreWork = 0; break; + } + /* complete loading into inBuffer in buffered mode */ + if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) { + size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; + size_t const loaded = ZSTD_limitCopy( + zcs->inBuff + zcs->inBuffPos, toLoad, + ip, iend-ip); + zcs->inBuffPos += loaded; + if (ip) ip += loaded; + if ( (flushMode == ZSTD_e_continue) + && (zcs->inBuffPos < zcs->inBuffTarget) ) { + /* not enough input to fill full block : stop here */ + someMoreWork = 0; break; + } + if ( (flushMode == ZSTD_e_flush) + && (zcs->inBuffPos == zcs->inToCompress) ) { + /* empty */ + someMoreWork = 0; break; + } + } else { + assert(zcs->appliedParams.inBufferMode == ZSTD_bm_stable); + if ( (flushMode == ZSTD_e_continue) + && ( (size_t)(iend - ip) < zcs->blockSize) ) { + /* can't compress a full block : stop here */ + zcs->stableIn_notConsumed = (size_t)(iend - ip); + ip = iend; /* pretend to have consumed input */ + someMoreWork = 0; break; + } + if ( (flushMode == ZSTD_e_flush) + && (ip == iend) ) { + /* empty */ + someMoreWork = 0; break; + } + } + /* compress current block (note : this stage cannot be stopped in the middle) */ + DEBUGLOG(5, "stream compression stage (flushMode==%u)", flushMode); + { int const inputBuffered = (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered); + void* cDst; + size_t cSize; + size_t oSize = oend-op; + size_t const iSize = inputBuffered ? zcs->inBuffPos - zcs->inToCompress + : MIN((size_t)(iend - ip), zcs->blockSize); + if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable) + cDst = op; /* compress into output buffer, to skip flush stage */ + else + cDst = zcs->outBuff, oSize = zcs->outBuffSize; + if (inputBuffered) { + unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend); + cSize = lastBlock ? + ZSTD_compressEnd_public(zcs, cDst, oSize, + zcs->inBuff + zcs->inToCompress, iSize) : + ZSTD_compressContinue_public(zcs, cDst, oSize, + zcs->inBuff + zcs->inToCompress, iSize); + FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); + zcs->frameEnded = lastBlock; + /* prepare next block */ + zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; + if (zcs->inBuffTarget > zcs->inBuffSize) + zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; + DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u", + (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize); + if (!lastBlock) + assert(zcs->inBuffTarget <= zcs->inBuffSize); + zcs->inToCompress = zcs->inBuffPos; + } else { /* !inputBuffered, hence ZSTD_bm_stable */ + unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip + iSize == iend); + cSize = lastBlock ? + ZSTD_compressEnd_public(zcs, cDst, oSize, ip, iSize) : + ZSTD_compressContinue_public(zcs, cDst, oSize, ip, iSize); + /* Consume the input prior to error checking to mirror buffered mode. */ + if (ip) ip += iSize; + FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); + zcs->frameEnded = lastBlock; + if (lastBlock) assert(ip == iend); + } + if (cDst == op) { /* no need to flush */ + op += cSize; + if (zcs->frameEnded) { + DEBUGLOG(5, "Frame completed directly in outBuffer"); + someMoreWork = 0; + ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + } + break; + } + zcs->outBuffContentSize = cSize; + zcs->outBuffFlushedSize = 0; + zcs->streamStage = zcss_flush; /* pass-through to flush stage */ + } + ZSTD_FALLTHROUGH; + case zcss_flush: + DEBUGLOG(5, "flush stage"); + assert(zcs->appliedParams.outBufferMode == ZSTD_bm_buffered); + { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; + size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op), + zcs->outBuff + zcs->outBuffFlushedSize, toFlush); + DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u", + (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed); + if (flushed) + op += flushed; + zcs->outBuffFlushedSize += flushed; + if (toFlush!=flushed) { + /* flush not fully completed, presumably because dst is too small */ + assert(op==oend); + someMoreWork = 0; + break; + } + zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0; + if (zcs->frameEnded) { + DEBUGLOG(5, "Frame completed on flush"); + someMoreWork = 0; + ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + break; + } + zcs->streamStage = zcss_load; + break; + } + + default: /* impossible */ + assert(0); + } + } + + input->pos = ip - istart; + output->pos = op - ostart; + if (zcs->frameEnded) return 0; + return ZSTD_nextInputSizeHint(zcs); +} + +static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx) +{ +#ifdef ZSTD_MULTITHREAD + if (cctx->appliedParams.nbWorkers >= 1) { + assert(cctx->mtctx != NULL); + return ZSTDMT_nextInputSizeHint(cctx->mtctx); + } +#endif + return ZSTD_nextInputSizeHint(cctx); + +} + +size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input) +{ + FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , ""); + return ZSTD_nextInputSizeHint_MTorST(zcs); +} + +/* After a compression call set the expected input/output buffer. + * This is validated at the start of the next compression call. + */ +static void +ZSTD_setBufferExpectations(ZSTD_CCtx* cctx, const ZSTD_outBuffer* output, const ZSTD_inBuffer* input) +{ + DEBUGLOG(5, "ZSTD_setBufferExpectations (for advanced stable in/out modes)"); + if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) { + cctx->expectedInBuffer = *input; + } + if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) { + cctx->expectedOutBufferSize = output->size - output->pos; + } +} + +/* Validate that the input/output buffers match the expectations set by + * ZSTD_setBufferExpectations. + */ +static size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx, + ZSTD_outBuffer const* output, + ZSTD_inBuffer const* input, + ZSTD_EndDirective endOp) +{ + if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) { + ZSTD_inBuffer const expect = cctx->expectedInBuffer; + if (expect.src != input->src || expect.pos != input->pos) + RETURN_ERROR(stabilityCondition_notRespected, "ZSTD_c_stableInBuffer enabled but input differs!"); + } + (void)endOp; + if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) { + size_t const outBufferSize = output->size - output->pos; + if (cctx->expectedOutBufferSize != outBufferSize) + RETURN_ERROR(stabilityCondition_notRespected, "ZSTD_c_stableOutBuffer enabled but output size differs!"); + } + return 0; +} + +static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, + ZSTD_EndDirective endOp, + size_t inSize) +{ + ZSTD_CCtx_params params = cctx->requestedParams; + ZSTD_prefixDict const prefixDict = cctx->prefixDict; + FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */ + ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ + assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ + if (cctx->cdict && !cctx->localDict.cdict) { + /* Let the cdict's compression level take priority over the requested params. + * But do not take the cdict's compression level if the "cdict" is actually a localDict + * generated from ZSTD_initLocalDict(). + */ + params.compressionLevel = cctx->cdict->compressionLevel; + } + DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage"); + if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1; /* auto-determine pledgedSrcSize */ + + { size_t const dictSize = prefixDict.dict + ? prefixDict.dictSize + : (cctx->cdict ? cctx->cdict->dictContentSize : 0); + ZSTD_cParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, ¶ms, cctx->pledgedSrcSizePlusOne - 1); + params.cParams = ZSTD_getCParamsFromCCtxParams( + ¶ms, cctx->pledgedSrcSizePlusOne-1, + dictSize, mode); + } + + params.useBlockSplitter = ZSTD_resolveBlockSplitterMode(params.useBlockSplitter, ¶ms.cParams); + params.ldmParams.enableLdm = ZSTD_resolveEnableLdm(params.ldmParams.enableLdm, ¶ms.cParams); + params.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params.useRowMatchFinder, ¶ms.cParams); + params.validateSequences = ZSTD_resolveExternalSequenceValidation(params.validateSequences); + params.maxBlockSize = ZSTD_resolveMaxBlockSize(params.maxBlockSize); + params.searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(params.searchForExternalRepcodes, params.compressionLevel); + +#ifdef ZSTD_MULTITHREAD + /* If external matchfinder is enabled, make sure to fail before checking job size (for consistency) */ + RETURN_ERROR_IF( + ZSTD_hasExtSeqProd(¶ms) && params.nbWorkers >= 1, + parameter_combination_unsupported, + "External sequence producer isn't supported with nbWorkers >= 1" + ); + + if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) { + params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */ + } + if (params.nbWorkers > 0) { +#if ZSTD_TRACE + cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0; +#endif + /* mt context creation */ + if (cctx->mtctx == NULL) { + DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u", + params.nbWorkers); + cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem, cctx->pool); + RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!"); + } + /* mt compression */ + DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); + FORWARD_IF_ERROR( ZSTDMT_initCStream_internal( + cctx->mtctx, + prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, + cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , ""); + cctx->dictID = cctx->cdict ? cctx->cdict->dictID : 0; + cctx->dictContentSize = cctx->cdict ? cctx->cdict->dictContentSize : prefixDict.dictSize; + cctx->consumedSrcSize = 0; + cctx->producedCSize = 0; + cctx->streamStage = zcss_load; + cctx->appliedParams = params; + } else +#endif /* ZSTD_MULTITHREAD */ + { U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1; + assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); + FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, + prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast, + cctx->cdict, + ¶ms, pledgedSrcSize, + ZSTDb_buffered) , ""); + assert(cctx->appliedParams.nbWorkers == 0); + cctx->inToCompress = 0; + cctx->inBuffPos = 0; + if (cctx->appliedParams.inBufferMode == ZSTD_bm_buffered) { + /* for small input: avoid automatic flush on reaching end of block, since + * it would require to add a 3-bytes null block to end frame + */ + cctx->inBuffTarget = cctx->blockSize + (cctx->blockSize == pledgedSrcSize); + } else { + cctx->inBuffTarget = 0; + } + cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0; + cctx->streamStage = zcss_load; + cctx->frameEnded = 0; + } + return 0; +} + +/* @return provides a minimum amount of data remaining to be flushed from internal buffers + */ +size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input, + ZSTD_EndDirective endOp) +{ + DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp); + /* check conditions */ + RETURN_ERROR_IF(output->pos > output->size, dstSize_tooSmall, "invalid output buffer"); + RETURN_ERROR_IF(input->pos > input->size, srcSize_wrong, "invalid input buffer"); + RETURN_ERROR_IF((U32)endOp > (U32)ZSTD_e_end, parameter_outOfBound, "invalid endDirective"); + assert(cctx != NULL); + + /* transparent initialization stage */ + if (cctx->streamStage == zcss_init) { + size_t const inputSize = input->size - input->pos; /* no obligation to start from pos==0 */ + size_t const totalInputSize = inputSize + cctx->stableIn_notConsumed; + if ( (cctx->requestedParams.inBufferMode == ZSTD_bm_stable) /* input is presumed stable, across invocations */ + && (endOp == ZSTD_e_continue) /* no flush requested, more input to come */ + && (totalInputSize < ZSTD_BLOCKSIZE_MAX) ) { /* not even reached one block yet */ + if (cctx->stableIn_notConsumed) { /* not the first time */ + /* check stable source guarantees */ + RETURN_ERROR_IF(input->src != cctx->expectedInBuffer.src, stabilityCondition_notRespected, "stableInBuffer condition not respected: wrong src pointer"); + RETURN_ERROR_IF(input->pos != cctx->expectedInBuffer.size, stabilityCondition_notRespected, "stableInBuffer condition not respected: externally modified pos"); + } + /* pretend input was consumed, to give a sense forward progress */ + input->pos = input->size; + /* save stable inBuffer, for later control, and flush/end */ + cctx->expectedInBuffer = *input; + /* but actually input wasn't consumed, so keep track of position from where compression shall resume */ + cctx->stableIn_notConsumed += inputSize; + /* don't initialize yet, wait for the first block of flush() order, for better parameters adaptation */ + return ZSTD_FRAMEHEADERSIZE_MIN(cctx->requestedParams.format); /* at least some header to produce */ + } + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, endOp, totalInputSize), "compressStream2 initialization failed"); + ZSTD_setBufferExpectations(cctx, output, input); /* Set initial buffer expectations now that we've initialized */ + } + /* end of transparent initialization stage */ + + FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), "invalid buffers"); + /* compression stage */ +#ifdef ZSTD_MULTITHREAD + if (cctx->appliedParams.nbWorkers > 0) { + size_t flushMin; + if (cctx->cParamsChanged) { + ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams); + cctx->cParamsChanged = 0; + } + if (cctx->stableIn_notConsumed) { + assert(cctx->appliedParams.inBufferMode == ZSTD_bm_stable); + /* some early data was skipped - make it available for consumption */ + assert(input->pos >= cctx->stableIn_notConsumed); + input->pos -= cctx->stableIn_notConsumed; + cctx->stableIn_notConsumed = 0; + } + for (;;) { + size_t const ipos = input->pos; + size_t const opos = output->pos; + flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp); + cctx->consumedSrcSize += (U64)(input->pos - ipos); + cctx->producedCSize += (U64)(output->pos - opos); + if ( ZSTD_isError(flushMin) + || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */ + if (flushMin == 0) + ZSTD_CCtx_trace(cctx, 0); + ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); + } + FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed"); + + if (endOp == ZSTD_e_continue) { + /* We only require some progress with ZSTD_e_continue, not maximal progress. + * We're done if we've consumed or produced any bytes, or either buffer is + * full. + */ + if (input->pos != ipos || output->pos != opos || input->pos == input->size || output->pos == output->size) + break; + } else { + assert(endOp == ZSTD_e_flush || endOp == ZSTD_e_end); + /* We require maximal progress. We're done when the flush is complete or the + * output buffer is full. + */ + if (flushMin == 0 || output->pos == output->size) + break; + } + } + DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic"); + /* Either we don't require maximum forward progress, we've finished the + * flush, or we are out of output space. + */ + assert(endOp == ZSTD_e_continue || flushMin == 0 || output->pos == output->size); + ZSTD_setBufferExpectations(cctx, output, input); + return flushMin; + } +#endif /* ZSTD_MULTITHREAD */ + FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , ""); + DEBUGLOG(5, "completed ZSTD_compressStream2"); + ZSTD_setBufferExpectations(cctx, output, input); + return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */ +} + +size_t ZSTD_compressStream2_simpleArgs ( + ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, size_t* dstPos, + const void* src, size_t srcSize, size_t* srcPos, + ZSTD_EndDirective endOp) +{ + ZSTD_outBuffer output; + ZSTD_inBuffer input; + output.dst = dst; + output.size = dstCapacity; + output.pos = *dstPos; + input.src = src; + input.size = srcSize; + input.pos = *srcPos; + /* ZSTD_compressStream2() will check validity of dstPos and srcPos */ + { size_t const cErr = ZSTD_compressStream2(cctx, &output, &input, endOp); + *dstPos = output.pos; + *srcPos = input.pos; + return cErr; + } +} + +size_t ZSTD_compress2(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + ZSTD_bufferMode_e const originalInBufferMode = cctx->requestedParams.inBufferMode; + ZSTD_bufferMode_e const originalOutBufferMode = cctx->requestedParams.outBufferMode; + DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize); + ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); + /* Enable stable input/output buffers. */ + cctx->requestedParams.inBufferMode = ZSTD_bm_stable; + cctx->requestedParams.outBufferMode = ZSTD_bm_stable; + { size_t oPos = 0; + size_t iPos = 0; + size_t const result = ZSTD_compressStream2_simpleArgs(cctx, + dst, dstCapacity, &oPos, + src, srcSize, &iPos, + ZSTD_e_end); + /* Reset to the original values. */ + cctx->requestedParams.inBufferMode = originalInBufferMode; + cctx->requestedParams.outBufferMode = originalOutBufferMode; + + FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed"); + if (result != 0) { /* compression not completed, due to lack of output space */ + assert(oPos == dstCapacity); + RETURN_ERROR(dstSize_tooSmall, ""); + } + assert(iPos == srcSize); /* all input is expected consumed */ + return oPos; + } +} + +/* ZSTD_validateSequence() : + * @offCode : is presumed to follow format required by ZSTD_storeSeq() + * @returns a ZSTD error code if sequence is not valid + */ +static size_t +ZSTD_validateSequence(U32 offCode, U32 matchLength, U32 minMatch, + size_t posInSrc, U32 windowLog, size_t dictSize, int useSequenceProducer) +{ + U32 const windowSize = 1u << windowLog; + /* posInSrc represents the amount of data the decoder would decode up to this point. + * As long as the amount of data decoded is less than or equal to window size, offsets may be + * larger than the total length of output decoded in order to reference the dict, even larger than + * window size. After output surpasses windowSize, we're limited to windowSize offsets again. + */ + size_t const offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize; + size_t const matchLenLowerBound = (minMatch == 3 || useSequenceProducer) ? 3 : 4; + RETURN_ERROR_IF(offCode > OFFSET_TO_OFFBASE(offsetBound), externalSequences_invalid, "Offset too large!"); + /* Validate maxNbSeq is large enough for the given matchLength and minMatch */ + RETURN_ERROR_IF(matchLength < matchLenLowerBound, externalSequences_invalid, "Matchlength too small for the minMatch"); + return 0; +} + +/* Returns an offset code, given a sequence's raw offset, the ongoing repcode array, and whether litLength == 0 */ +static U32 ZSTD_finalizeOffBase(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0) +{ + U32 offBase = OFFSET_TO_OFFBASE(rawOffset); + + if (!ll0 && rawOffset == rep[0]) { + offBase = REPCODE1_TO_OFFBASE; + } else if (rawOffset == rep[1]) { + offBase = REPCODE_TO_OFFBASE(2 - ll0); + } else if (rawOffset == rep[2]) { + offBase = REPCODE_TO_OFFBASE(3 - ll0); + } else if (ll0 && rawOffset == rep[0] - 1) { + offBase = REPCODE3_TO_OFFBASE; + } + return offBase; +} + +size_t +ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, + ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize, + ZSTD_paramSwitch_e externalRepSearch) +{ + U32 idx = seqPos->idx; + U32 const startIdx = idx; + BYTE const* ip = (BYTE const*)(src); + const BYTE* const iend = ip + blockSize; + repcodes_t updatedRepcodes; + U32 dictSize; + + DEBUGLOG(5, "ZSTD_copySequencesToSeqStoreExplicitBlockDelim (blockSize = %zu)", blockSize); + + if (cctx->cdict) { + dictSize = (U32)cctx->cdict->dictContentSize; + } else if (cctx->prefixDict.dict) { + dictSize = (U32)cctx->prefixDict.dictSize; + } else { + dictSize = 0; + } + ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t)); + for (; idx < inSeqsSize && (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0); ++idx) { + U32 const litLength = inSeqs[idx].litLength; + U32 const matchLength = inSeqs[idx].matchLength; + U32 offBase; + + if (externalRepSearch == ZSTD_ps_disable) { + offBase = OFFSET_TO_OFFBASE(inSeqs[idx].offset); + } else { + U32 const ll0 = (litLength == 0); + offBase = ZSTD_finalizeOffBase(inSeqs[idx].offset, updatedRepcodes.rep, ll0); + ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0); + } + + DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); + if (cctx->appliedParams.validateSequences) { + seqPos->posInSrc += litLength + matchLength; + FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc, + cctx->appliedParams.cParams.windowLog, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)), + "Sequence validation failed"); + } + RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid, + "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); + ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offBase, matchLength); + ip += matchLength + litLength; + } + + /* If we skipped repcode search while parsing, we need to update repcodes now */ + assert(externalRepSearch != ZSTD_ps_auto); + assert(idx >= startIdx); + if (externalRepSearch == ZSTD_ps_disable && idx != startIdx) { + U32* const rep = updatedRepcodes.rep; + U32 lastSeqIdx = idx - 1; /* index of last non-block-delimiter sequence */ + + if (lastSeqIdx >= startIdx + 2) { + rep[2] = inSeqs[lastSeqIdx - 2].offset; + rep[1] = inSeqs[lastSeqIdx - 1].offset; + rep[0] = inSeqs[lastSeqIdx].offset; + } else if (lastSeqIdx == startIdx + 1) { + rep[2] = rep[0]; + rep[1] = inSeqs[lastSeqIdx - 1].offset; + rep[0] = inSeqs[lastSeqIdx].offset; + } else { + assert(lastSeqIdx == startIdx); + rep[2] = rep[1]; + rep[1] = rep[0]; + rep[0] = inSeqs[lastSeqIdx].offset; + } + } + + ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t)); + + if (inSeqs[idx].litLength) { + DEBUGLOG(6, "Storing last literals of size: %u", inSeqs[idx].litLength); + ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength); + ip += inSeqs[idx].litLength; + seqPos->posInSrc += inSeqs[idx].litLength; + } + RETURN_ERROR_IF(ip != iend, externalSequences_invalid, "Blocksize doesn't agree with block delimiter!"); + seqPos->idx = idx+1; + return 0; +} + +size_t +ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch) +{ + U32 idx = seqPos->idx; + U32 startPosInSequence = seqPos->posInSequence; + U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize; + size_t dictSize; + BYTE const* ip = (BYTE const*)(src); + BYTE const* iend = ip + blockSize; /* May be adjusted if we decide to process fewer than blockSize bytes */ + repcodes_t updatedRepcodes; + U32 bytesAdjustment = 0; + U32 finalMatchSplit = 0; + + /* TODO(embg) support fast parsing mode in noBlockDelim mode */ + (void)externalRepSearch; + + if (cctx->cdict) { + dictSize = cctx->cdict->dictContentSize; + } else if (cctx->prefixDict.dict) { + dictSize = cctx->prefixDict.dictSize; + } else { + dictSize = 0; + } + DEBUGLOG(5, "ZSTD_copySequencesToSeqStoreNoBlockDelim: idx: %u PIS: %u blockSize: %zu", idx, startPosInSequence, blockSize); + DEBUGLOG(5, "Start seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength); + ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t)); + while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) { + const ZSTD_Sequence currSeq = inSeqs[idx]; + U32 litLength = currSeq.litLength; + U32 matchLength = currSeq.matchLength; + U32 const rawOffset = currSeq.offset; + U32 offBase; + + /* Modify the sequence depending on where endPosInSequence lies */ + if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) { + if (startPosInSequence >= litLength) { + startPosInSequence -= litLength; + litLength = 0; + matchLength -= startPosInSequence; + } else { + litLength -= startPosInSequence; + } + /* Move to the next sequence */ + endPosInSequence -= currSeq.litLength + currSeq.matchLength; + startPosInSequence = 0; + } else { + /* This is the final (partial) sequence we're adding from inSeqs, and endPosInSequence + does not reach the end of the match. So, we have to split the sequence */ + DEBUGLOG(6, "Require a split: diff: %u, idx: %u PIS: %u", + currSeq.litLength + currSeq.matchLength - endPosInSequence, idx, endPosInSequence); + if (endPosInSequence > litLength) { + U32 firstHalfMatchLength; + litLength = startPosInSequence >= litLength ? 0 : litLength - startPosInSequence; + firstHalfMatchLength = endPosInSequence - startPosInSequence - litLength; + if (matchLength > blockSize && firstHalfMatchLength >= cctx->appliedParams.cParams.minMatch) { + /* Only ever split the match if it is larger than the block size */ + U32 secondHalfMatchLength = currSeq.matchLength + currSeq.litLength - endPosInSequence; + if (secondHalfMatchLength < cctx->appliedParams.cParams.minMatch) { + /* Move the endPosInSequence backward so that it creates match of minMatch length */ + endPosInSequence -= cctx->appliedParams.cParams.minMatch - secondHalfMatchLength; + bytesAdjustment = cctx->appliedParams.cParams.minMatch - secondHalfMatchLength; + firstHalfMatchLength -= bytesAdjustment; + } + matchLength = firstHalfMatchLength; + /* Flag that we split the last match - after storing the sequence, exit the loop, + but keep the value of endPosInSequence */ + finalMatchSplit = 1; + } else { + /* Move the position in sequence backwards so that we don't split match, and break to store + * the last literals. We use the original currSeq.litLength as a marker for where endPosInSequence + * should go. We prefer to do this whenever it is not necessary to split the match, or if doing so + * would cause the first half of the match to be too small + */ + bytesAdjustment = endPosInSequence - currSeq.litLength; + endPosInSequence = currSeq.litLength; + break; + } + } else { + /* This sequence ends inside the literals, break to store the last literals */ + break; + } + } + /* Check if this offset can be represented with a repcode */ + { U32 const ll0 = (litLength == 0); + offBase = ZSTD_finalizeOffBase(rawOffset, updatedRepcodes.rep, ll0); + ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0); + } + + if (cctx->appliedParams.validateSequences) { + seqPos->posInSrc += litLength + matchLength; + FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc, + cctx->appliedParams.cParams.windowLog, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)), + "Sequence validation failed"); + } + DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength); + RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid, + "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); + ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offBase, matchLength); + ip += matchLength + litLength; + if (!finalMatchSplit) + idx++; /* Next Sequence */ + } + DEBUGLOG(5, "Ending seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength); + assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength); + seqPos->idx = idx; + seqPos->posInSequence = endPosInSequence; + ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t)); + + iend -= bytesAdjustment; + if (ip != iend) { + /* Store any last literals */ + U32 lastLLSize = (U32)(iend - ip); + assert(ip <= iend); + DEBUGLOG(6, "Storing last literals of size: %u", lastLLSize); + ZSTD_storeLastLiterals(&cctx->seqStore, ip, lastLLSize); + seqPos->posInSrc += lastLLSize; + } + + return bytesAdjustment; +} + +typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); +static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode) +{ + ZSTD_sequenceCopier sequenceCopier = NULL; + assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, mode)); + if (mode == ZSTD_sf_explicitBlockDelimiters) { + return ZSTD_copySequencesToSeqStoreExplicitBlockDelim; + } else if (mode == ZSTD_sf_noBlockDelimiters) { + return ZSTD_copySequencesToSeqStoreNoBlockDelim; + } + assert(sequenceCopier != NULL); + return sequenceCopier; +} + +/* Discover the size of next block by searching for the delimiter. + * Note that a block delimiter **must** exist in this mode, + * otherwise it's an input error. + * The block size retrieved will be later compared to ensure it remains within bounds */ +static size_t +blockSize_explicitDelimiter(const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD_sequencePosition seqPos) +{ + int end = 0; + size_t blockSize = 0; + size_t spos = seqPos.idx; + DEBUGLOG(6, "blockSize_explicitDelimiter : seq %zu / %zu", spos, inSeqsSize); + assert(spos <= inSeqsSize); + while (spos < inSeqsSize) { + end = (inSeqs[spos].offset == 0); + blockSize += inSeqs[spos].litLength + inSeqs[spos].matchLength; + if (end) { + if (inSeqs[spos].matchLength != 0) + RETURN_ERROR(externalSequences_invalid, "delimiter format error : both matchlength and offset must be == 0"); + break; + } + spos++; + } + if (!end) + RETURN_ERROR(externalSequences_invalid, "Reached end of sequences without finding a block delimiter"); + return blockSize; +} + +/* More a "target" block size */ +static size_t blockSize_noDelimiter(size_t blockSize, size_t remaining) +{ + int const lastBlock = (remaining <= blockSize); + return lastBlock ? remaining : blockSize; +} + +static size_t determine_blockSize(ZSTD_sequenceFormat_e mode, + size_t blockSize, size_t remaining, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD_sequencePosition seqPos) +{ + DEBUGLOG(6, "determine_blockSize : remainingSize = %zu", remaining); + if (mode == ZSTD_sf_noBlockDelimiters) + return blockSize_noDelimiter(blockSize, remaining); + { size_t const explicitBlockSize = blockSize_explicitDelimiter(inSeqs, inSeqsSize, seqPos); + FORWARD_IF_ERROR(explicitBlockSize, "Error while determining block size with explicit delimiters"); + if (explicitBlockSize > blockSize) + RETURN_ERROR(externalSequences_invalid, "sequences incorrectly define a too large block"); + if (explicitBlockSize > remaining) + RETURN_ERROR(externalSequences_invalid, "sequences define a frame longer than source"); + return explicitBlockSize; + } +} + +/* Compress, block-by-block, all of the sequences given. + * + * Returns the cumulative size of all compressed blocks (including their headers), + * otherwise a ZSTD error. + */ +static size_t +ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize) +{ + size_t cSize = 0; + size_t remaining = srcSize; + ZSTD_sequencePosition seqPos = {0, 0, 0}; + + BYTE const* ip = (BYTE const*)src; + BYTE* op = (BYTE*)dst; + ZSTD_sequenceCopier const sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters); + + DEBUGLOG(4, "ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu", srcSize, inSeqsSize); + /* Special case: empty frame */ + if (remaining == 0) { + U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1); + RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "No room for empty frame block header"); + MEM_writeLE32(op, cBlockHeader24); + op += ZSTD_blockHeaderSize; + dstCapacity -= ZSTD_blockHeaderSize; + cSize += ZSTD_blockHeaderSize; + } + + while (remaining) { + size_t compressedSeqsSize; + size_t cBlockSize; + size_t additionalByteAdjustment; + size_t blockSize = determine_blockSize(cctx->appliedParams.blockDelimiters, + cctx->blockSize, remaining, + inSeqs, inSeqsSize, seqPos); + U32 const lastBlock = (blockSize == remaining); + FORWARD_IF_ERROR(blockSize, "Error while trying to determine block size"); + assert(blockSize <= remaining); + ZSTD_resetSeqStore(&cctx->seqStore); + DEBUGLOG(5, "Working on new block. Blocksize: %zu (total:%zu)", blockSize, (ip - (const BYTE*)src) + blockSize); + + additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize, cctx->appliedParams.searchForExternalRepcodes); + FORWARD_IF_ERROR(additionalByteAdjustment, "Bad sequence copy"); + blockSize -= additionalByteAdjustment; + + /* If blocks are too small, emit as a nocompress block */ + /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding + * additional 1. We need to revisit and change this logic to be more consistent */ + if (blockSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1+1) { + cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed"); + DEBUGLOG(5, "Block too small, writing out nocompress block: cSize: %zu", cBlockSize); + cSize += cBlockSize; + ip += blockSize; + op += cBlockSize; + remaining -= blockSize; + dstCapacity -= cBlockSize; + continue; + } + + RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, "not enough dstCapacity to write a new compressed block"); + compressedSeqsSize = ZSTD_entropyCompressSeqStore(&cctx->seqStore, + &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy, + &cctx->appliedParams, + op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, + blockSize, + cctx->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + cctx->bmi2); + FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed"); + DEBUGLOG(5, "Compressed sequences size: %zu", compressedSeqsSize); + + if (!cctx->isFirstBlock && + ZSTD_maybeRLE(&cctx->seqStore) && + ZSTD_isRLE(ip, blockSize)) { + /* We don't want to emit our first block as a RLE even if it qualifies because + * doing so will cause the decoder (cli only) to throw a "should consume all input error." + * This is only an issue for zstd <= v1.4.3 + */ + compressedSeqsSize = 1; + } + + if (compressedSeqsSize == 0) { + /* ZSTD_noCompressBlock writes the block header as well */ + cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cBlockSize, "ZSTD_noCompressBlock failed"); + DEBUGLOG(5, "Writing out nocompress block, size: %zu", cBlockSize); + } else if (compressedSeqsSize == 1) { + cBlockSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cBlockSize, "ZSTD_rleCompressBlock failed"); + DEBUGLOG(5, "Writing out RLE block, size: %zu", cBlockSize); + } else { + U32 cBlockHeader; + /* Error checking and repcodes update */ + ZSTD_blockState_confirmRepcodesAndEntropyTables(&cctx->blockState); + if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + + /* Write block header into beginning of block*/ + cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3); + MEM_writeLE24(op, cBlockHeader); + cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize; + DEBUGLOG(5, "Writing out compressed block, size: %zu", cBlockSize); + } + + cSize += cBlockSize; + + if (lastBlock) { + break; + } else { + ip += blockSize; + op += cBlockSize; + remaining -= blockSize; + dstCapacity -= cBlockSize; + cctx->isFirstBlock = 0; + } + DEBUGLOG(5, "cSize running total: %zu (remaining dstCapacity=%zu)", cSize, dstCapacity); + } + + DEBUGLOG(4, "cSize final total: %zu", cSize); + return cSize; +} + +size_t ZSTD_compressSequences(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize) +{ + BYTE* op = (BYTE*)dst; + size_t cSize = 0; + size_t compressedBlocksSize = 0; + size_t frameHeaderSize = 0; + + /* Transparent initialization stage, same as compressStream2() */ + DEBUGLOG(4, "ZSTD_compressSequences (dstCapacity=%zu)", dstCapacity); + assert(cctx != NULL); + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed"); + /* Begin writing output, starting with frame header */ + frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, &cctx->appliedParams, srcSize, cctx->dictID); + op += frameHeaderSize; + dstCapacity -= frameHeaderSize; + cSize += frameHeaderSize; + if (cctx->appliedParams.fParams.checksumFlag && srcSize) { + XXH64_update(&cctx->xxhState, src, srcSize); + } + /* cSize includes block header size and compressed sequences size */ + compressedBlocksSize = ZSTD_compressSequences_internal(cctx, + op, dstCapacity, + inSeqs, inSeqsSize, + src, srcSize); + FORWARD_IF_ERROR(compressedBlocksSize, "Compressing blocks failed!"); + cSize += compressedBlocksSize; + dstCapacity -= compressedBlocksSize; + + if (cctx->appliedParams.fParams.checksumFlag) { + U32 const checksum = (U32) XXH64_digest(&cctx->xxhState); + RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum"); + DEBUGLOG(4, "Write checksum : %08X", (unsigned)checksum); + MEM_writeLE32((char*)dst + cSize, checksum); + cSize += 4; + } + + DEBUGLOG(4, "Final compressed size: %zu", cSize); + return cSize; +} + +/*====== Finalize ======*/ + +static ZSTD_inBuffer inBuffer_forEndFlush(const ZSTD_CStream* zcs) +{ + const ZSTD_inBuffer nullInput = { NULL, 0, 0 }; + const int stableInput = (zcs->appliedParams.inBufferMode == ZSTD_bm_stable); + return stableInput ? zcs->expectedInBuffer : nullInput; +} + +/*! ZSTD_flushStream() : + * @return : amount of data remaining to flush */ +size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) +{ + ZSTD_inBuffer input = inBuffer_forEndFlush(zcs); + input.size = input.pos; /* do not ingest more input during flush */ + return ZSTD_compressStream2(zcs, output, &input, ZSTD_e_flush); +} + + +size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) +{ + ZSTD_inBuffer input = inBuffer_forEndFlush(zcs); + size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end); + FORWARD_IF_ERROR(remainingToFlush , "ZSTD_compressStream2(,,ZSTD_e_end) failed"); + if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */ + /* single thread mode : attempt to calculate remaining to flush more precisely */ + { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE; + size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4); + size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize; + DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush); + return toFlush; + } +} + + +/*-===== Pre-defined compression levels =====-*/ +#include "clevels.h" + +int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } +int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; } +int ZSTD_defaultCLevel(void) { return ZSTD_CLEVEL_DEFAULT; } + +static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize) +{ + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict); + switch (cParams.strategy) { + case ZSTD_fast: + case ZSTD_dfast: + break; + case ZSTD_greedy: + case ZSTD_lazy: + case ZSTD_lazy2: + cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG; + break; + case ZSTD_btlazy2: + case ZSTD_btopt: + case ZSTD_btultra: + case ZSTD_btultra2: + break; + } + return cParams; +} + +static int ZSTD_dedicatedDictSearch_isSupported( + ZSTD_compressionParameters const* cParams) +{ + return (cParams->strategy >= ZSTD_greedy) + && (cParams->strategy <= ZSTD_lazy2) + && (cParams->hashLog > cParams->chainLog) + && (cParams->chainLog <= 24); +} + +/** + * Reverses the adjustment applied to cparams when enabling dedicated dict + * search. This is used to recover the params set to be used in the working + * context. (Otherwise, those tables would also grow.) + */ +static void ZSTD_dedicatedDictSearch_revertCParams( + ZSTD_compressionParameters* cParams) { + switch (cParams->strategy) { + case ZSTD_fast: + case ZSTD_dfast: + break; + case ZSTD_greedy: + case ZSTD_lazy: + case ZSTD_lazy2: + cParams->hashLog -= ZSTD_LAZY_DDSS_BUCKET_LOG; + if (cParams->hashLog < ZSTD_HASHLOG_MIN) { + cParams->hashLog = ZSTD_HASHLOG_MIN; + } + break; + case ZSTD_btlazy2: + case ZSTD_btopt: + case ZSTD_btultra: + case ZSTD_btultra2: + break; + } +} + +static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) +{ + switch (mode) { + case ZSTD_cpm_unknown: + case ZSTD_cpm_noAttachDict: + case ZSTD_cpm_createCDict: + break; + case ZSTD_cpm_attachDict: + dictSize = 0; + break; + default: + assert(0); + break; + } + { int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN; + size_t const addedSize = unknown && dictSize > 0 ? 500 : 0; + return unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize; + } +} + +/*! ZSTD_getCParams_internal() : + * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. + * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown. + * Use dictSize == 0 for unknown or unused. + * Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_cParamMode_e`. */ +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) +{ + U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode); + U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); + int row; + DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel); + + /* row */ + if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ + else if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */ + else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; + else row = compressionLevel; + + { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row]; + DEBUGLOG(5, "ZSTD_getCParams_internal selected tableID: %u row: %u strat: %u", tableID, row, (U32)cp.strategy); + /* acceleration factor */ + if (compressionLevel < 0) { + int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel); + cp.targetLength = (unsigned)(-clampedCompressionLevel); + } + /* refine parameters based on srcSize & dictSize */ + return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode, ZSTD_ps_auto); + } +} + +/*! ZSTD_getCParams() : + * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. + * Size values are optional, provide 0 if not known or unused */ +ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) +{ + if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; + return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown); +} + +/*! ZSTD_getParams() : + * same idea as ZSTD_getCParams() + * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). + * Fields of `ZSTD_frameParameters` are set to default values */ +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) { + ZSTD_parameters params; + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode); + DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel); + ZSTD_memset(¶ms, 0, sizeof(params)); + params.cParams = cParams; + params.fParams.contentSizeFlag = 1; + return params; +} + +/*! ZSTD_getParams() : + * same idea as ZSTD_getCParams() + * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). + * Fields of `ZSTD_frameParameters` are set to default values */ +ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { + if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; + return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown); +} + +void ZSTD_registerSequenceProducer( + ZSTD_CCtx* zc, + void* extSeqProdState, + ZSTD_sequenceProducer_F extSeqProdFunc +) { + assert(zc != NULL); + ZSTD_CCtxParams_registerSequenceProducer( + &zc->requestedParams, extSeqProdState, extSeqProdFunc + ); +} + +void ZSTD_CCtxParams_registerSequenceProducer( + ZSTD_CCtx_params* params, + void* extSeqProdState, + ZSTD_sequenceProducer_F extSeqProdFunc +) { + assert(params != NULL); + if (extSeqProdFunc != NULL) { + params->extSeqProdFunc = extSeqProdFunc; + params->extSeqProdState = extSeqProdState; + } else { + params->extSeqProdFunc = NULL; + params->extSeqProdState = NULL; + } +} diff --git a/third_party/zstd/compress/zstd_compress.cpp b/third_party/zstd/compress/zstd_compress.cpp deleted file mode 100644 index 649e5357106..00000000000 --- a/third_party/zstd/compress/zstd_compress.cpp +++ /dev/null @@ -1,4283 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - -/*-************************************* -* Dependencies -***************************************/ -#include /* INT_MAX */ -#include /* memset */ -#include "zstd/common/mem.h" -#include "zstd/compress/hist.h" /* HIST_countFast_wksp */ -#include "zstd/common/fse.h" -#include "zstd/common/fse_static.h" -#include "zstd/common/huf.h" -#include "zstd/common/huf_static.h" -#include "zstd/compress/zstd_compress_internal.h" -#include "zstd/compress/zstd_compress_sequences.h" -#include "zstd/compress/zstd_compress_literals.h" -#include "zstd/compress/zstd_fast.h" -#include "zstd/compress/zstd_double_fast.h" -#include "zstd/compress/zstd_lazy.h" -#include "zstd/compress/zstd_opt.h" -#include "zstd/compress/zstd_ldm.h" -#include "zstd/compress/zstd_compress_superblock.h" - -#if defined (MEMORY_SANITIZER) -#include -#endif - -namespace duckdb_zstd { -/*-************************************* -* Helper functions -***************************************/ -/* ZSTD_compressBound() - * Note that the result from this function is only compatible with the "normal" - * full-block strategy. - * When there are a lot of small blocks due to frequent flush in streaming mode - * the overhead of headers can make the compressed data to be larger than the - * return value of ZSTD_compressBound(). - */ -size_t ZSTD_compressBound(size_t srcSize) { - return ZSTD_COMPRESSBOUND(srcSize); -} - - -/*-************************************* -* Context memory management -***************************************/ -struct ZSTD_CDict_s { - const void* dictContent; - size_t dictContentSize; - U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */ - ZSTD_cwksp workspace; - ZSTD_matchState_t matchState; - ZSTD_compressedBlockState_t cBlockState; - ZSTD_customMem customMem; - U32 dictID; - int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */ -}; /* typedef'd to ZSTD_CDict within "zstd.h" */ - -ZSTD_CCtx* ZSTD_createCCtx(void) -{ - return ZSTD_createCCtx_advanced({NULL, NULL, NULL}); -} - -static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager) -{ - assert(cctx != NULL); - memset(cctx, 0, sizeof(*cctx)); - cctx->customMem = memManager; - cctx->bmi2 = 0; - { size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters); - assert(!ZSTD_isError(err)); - (void)err; - } -} - -ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem) -{ - ZSTD_STATIC_ASSERT(zcss_init==0); - ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1)); - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; - { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_malloc(sizeof(ZSTD_CCtx), customMem); - if (!cctx) return NULL; - ZSTD_initCCtx(cctx, customMem); - return cctx; - } -} - -ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) -{ - ZSTD_cwksp ws; - ZSTD_CCtx* cctx; - if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */ - if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */ - ZSTD_cwksp_init(&ws, workspace, workspaceSize); - - cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx)); - if (cctx == NULL) return NULL; - - memset(cctx, 0, sizeof(ZSTD_CCtx)); - ZSTD_cwksp_move(&cctx->workspace, &ws); - cctx->staticSize = workspaceSize; - - /* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */ - if (!ZSTD_cwksp_check_available(&cctx->workspace, HUF_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; - cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); - cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); - cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, HUF_WORKSPACE_SIZE); - cctx->bmi2 = 0; - return cctx; -} - -/** - * Clears and frees all of the dictionaries in the CCtx. - */ -static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx) -{ - ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem); - ZSTD_freeCDict(cctx->localDict.cdict); - memset(&cctx->localDict, 0, sizeof(cctx->localDict)); - memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); - cctx->cdict = NULL; -} - -static size_t ZSTD_sizeof_localDict(ZSTD_localDict dict) -{ - size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0; - size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict); - return bufferSize + cdictSize; -} - -static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx) -{ - assert(cctx != NULL); - assert(cctx->staticSize == 0); - ZSTD_clearAllDicts(cctx); -#ifdef ZSTD_MULTITHREAD - ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL; -#endif - ZSTD_cwksp_free(&cctx->workspace, cctx->customMem); -} - -size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx) -{ - if (cctx==NULL) return 0; /* support free on NULL */ - RETURN_ERROR_IF(cctx->staticSize, memory_allocation, - "not compatible with static CCtx"); - { - int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx); - ZSTD_freeCCtxContent(cctx); - if (!cctxInWorkspace) { - ZSTD_free(cctx, cctx->customMem); - } - } - return 0; -} - - -static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx) -{ -#ifdef ZSTD_MULTITHREAD - return ZSTDMT_sizeof_CCtx(cctx->mtctx); -#else - (void)cctx; - return 0; -#endif -} - - -size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx) -{ - if (cctx==NULL) return 0; /* support sizeof on NULL */ - /* cctx may be in the workspace */ - return (cctx->workspace.workspace == cctx ? 0 : sizeof(*cctx)) - + ZSTD_cwksp_sizeof(&cctx->workspace) - + ZSTD_sizeof_localDict(cctx->localDict) - + ZSTD_sizeof_mtctx(cctx); -} - -size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs) -{ - return ZSTD_sizeof_CCtx(zcs); /* same object */ -} - -/* private API call, for dictBuilder only */ -const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); } - -static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( - ZSTD_compressionParameters cParams) -{ - ZSTD_CCtx_params cctxParams; - memset(&cctxParams, 0, sizeof(cctxParams)); - cctxParams.cParams = cParams; - cctxParams.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */ - assert(!ZSTD_checkCParams(cParams)); - cctxParams.fParams.contentSizeFlag = 1; - return cctxParams; -} - -static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced( - ZSTD_customMem customMem) -{ - ZSTD_CCtx_params* params; - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; - params = (ZSTD_CCtx_params*)ZSTD_calloc( - sizeof(ZSTD_CCtx_params), customMem); - if (!params) { return NULL; } - params->customMem = customMem; - params->compressionLevel = ZSTD_CLEVEL_DEFAULT; - params->fParams.contentSizeFlag = 1; - return params; -} - -ZSTD_CCtx_params* ZSTD_createCCtxParams(void) -{ - return ZSTD_createCCtxParams_advanced(ZSTDInternalConstants::ZSTD_defaultCMem); -} - -size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params) -{ - if (params == NULL) { return 0; } - ZSTD_free(params, params->customMem); - return 0; -} - -size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params) -{ - return ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT); -} - -size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) { - RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); - memset(cctxParams, 0, sizeof(*cctxParams)); - cctxParams->compressionLevel = compressionLevel; - cctxParams->fParams.contentSizeFlag = 1; - return 0; -} - -size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params) -{ - RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); - FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); - memset(cctxParams, 0, sizeof(*cctxParams)); - assert(!ZSTD_checkCParams(params.cParams)); - cctxParams->cParams = params.cParams; - cctxParams->fParams = params.fParams; - cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */ - return 0; -} - -/* ZSTD_assignParamsToCCtxParams() : - * params is presumed valid at this stage */ -static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams( - const ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params) -{ - ZSTD_CCtx_params ret = *cctxParams; - assert(!ZSTD_checkCParams(params->cParams)); - ret.cParams = params->cParams; - ret.fParams = params->fParams; - ret.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */ - return ret; -} - -ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) -{ - ZSTD_bounds bounds = { 0, 0, 0 }; - - switch(param) - { - case ZSTD_c_compressionLevel: - bounds.lowerBound = ZSTD_minCLevel(); - bounds.upperBound = ZSTD_maxCLevel(); - return bounds; - - case ZSTD_c_windowLog: - bounds.lowerBound = ZSTD_WINDOWLOG_MIN; - bounds.upperBound = ZSTD_WINDOWLOG_MAX; - return bounds; - - case ZSTD_c_hashLog: - bounds.lowerBound = ZSTD_HASHLOG_MIN; - bounds.upperBound = ZSTD_HASHLOG_MAX; - return bounds; - - case ZSTD_c_chainLog: - bounds.lowerBound = ZSTD_CHAINLOG_MIN; - bounds.upperBound = ZSTD_CHAINLOG_MAX; - return bounds; - - case ZSTD_c_searchLog: - bounds.lowerBound = ZSTD_SEARCHLOG_MIN; - bounds.upperBound = ZSTD_SEARCHLOG_MAX; - return bounds; - - case ZSTD_c_minMatch: - bounds.lowerBound = ZSTD_MINMATCH_MIN; - bounds.upperBound = ZSTD_MINMATCH_MAX; - return bounds; - - case ZSTD_c_targetLength: - bounds.lowerBound = ZSTD_TARGETLENGTH_MIN; - bounds.upperBound = ZSTD_TARGETLENGTH_MAX; - return bounds; - - case ZSTD_c_strategy: - bounds.lowerBound = ZSTD_STRATEGY_MIN; - bounds.upperBound = ZSTD_STRATEGY_MAX; - return bounds; - - case ZSTD_c_contentSizeFlag: - bounds.lowerBound = 0; - bounds.upperBound = 1; - return bounds; - - case ZSTD_c_checksumFlag: - bounds.lowerBound = 0; - bounds.upperBound = 1; - return bounds; - - case ZSTD_c_dictIDFlag: - bounds.lowerBound = 0; - bounds.upperBound = 1; - return bounds; - - case ZSTD_c_nbWorkers: - bounds.lowerBound = 0; -#ifdef ZSTD_MULTITHREAD - bounds.upperBound = ZSTDMT_NBWORKERS_MAX; -#else - bounds.upperBound = 0; -#endif - return bounds; - - case ZSTD_c_jobSize: - bounds.lowerBound = 0; -#ifdef ZSTD_MULTITHREAD - bounds.upperBound = ZSTDMT_JOBSIZE_MAX; -#else - bounds.upperBound = 0; -#endif - return bounds; - - case ZSTD_c_overlapLog: -#ifdef ZSTD_MULTITHREAD - bounds.lowerBound = ZSTD_OVERLAPLOG_MIN; - bounds.upperBound = ZSTD_OVERLAPLOG_MAX; -#else - bounds.lowerBound = 0; - bounds.upperBound = 0; -#endif - return bounds; - - case ZSTD_c_enableLongDistanceMatching: - bounds.lowerBound = 0; - bounds.upperBound = 1; - return bounds; - - case ZSTD_c_ldmHashLog: - bounds.lowerBound = ZSTD_LDM_HASHLOG_MIN; - bounds.upperBound = ZSTD_LDM_HASHLOG_MAX; - return bounds; - - case ZSTD_c_ldmMinMatch: - bounds.lowerBound = ZSTD_LDM_MINMATCH_MIN; - bounds.upperBound = ZSTD_LDM_MINMATCH_MAX; - return bounds; - - case ZSTD_c_ldmBucketSizeLog: - bounds.lowerBound = ZSTD_LDM_BUCKETSIZELOG_MIN; - bounds.upperBound = ZSTD_LDM_BUCKETSIZELOG_MAX; - return bounds; - - case ZSTD_c_ldmHashRateLog: - bounds.lowerBound = ZSTD_LDM_HASHRATELOG_MIN; - bounds.upperBound = ZSTD_LDM_HASHRATELOG_MAX; - return bounds; - - /* experimental parameters */ - case ZSTD_c_rsyncable: - bounds.lowerBound = 0; - bounds.upperBound = 1; - return bounds; - - case ZSTD_c_forceMaxWindow : - bounds.lowerBound = 0; - bounds.upperBound = 1; - return bounds; - - case ZSTD_c_format: - ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless); - bounds.lowerBound = ZSTD_f_zstd1; - bounds.upperBound = ZSTD_f_zstd1_magicless; /* note : how to ensure at compile time that this is the highest value enum ? */ - return bounds; - - case ZSTD_c_forceAttachDict: - ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy); - bounds.lowerBound = ZSTD_dictDefaultAttach; - bounds.upperBound = ZSTD_dictForceLoad; /* note : how to ensure at compile time that this is the highest value enum ? */ - return bounds; - - case ZSTD_c_literalCompressionMode: - ZSTD_STATIC_ASSERT(ZSTD_lcm_auto < ZSTD_lcm_huffman && ZSTD_lcm_huffman < ZSTD_lcm_uncompressed); - bounds.lowerBound = ZSTD_lcm_auto; - bounds.upperBound = ZSTD_lcm_uncompressed; - return bounds; - - case ZSTD_c_targetCBlockSize: - bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN; - bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX; - return bounds; - - case ZSTD_c_srcSizeHint: - bounds.lowerBound = ZSTD_SRCSIZEHINT_MIN; - bounds.upperBound = ZSTD_SRCSIZEHINT_MAX; - return bounds; - - default: - bounds.error = ERROR(parameter_unsupported); - return bounds; - } -} - -/* ZSTD_cParam_clampBounds: - * Clamps the value into the bounded range. - */ -static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value) -{ - ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); - if (ZSTD_isError(bounds.error)) return bounds.error; - if (*value < bounds.lowerBound) *value = bounds.lowerBound; - if (*value > bounds.upperBound) *value = bounds.upperBound; - return 0; -} - -#define BOUNDCHECK(cParam, val) { \ - RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \ - parameter_outOfBound, "Param out of bounds"); \ -} - - -static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) -{ - switch(param) - { - case ZSTD_c_compressionLevel: - case ZSTD_c_hashLog: - case ZSTD_c_chainLog: - case ZSTD_c_searchLog: - case ZSTD_c_minMatch: - case ZSTD_c_targetLength: - case ZSTD_c_strategy: - return 1; - - case ZSTD_c_format: - case ZSTD_c_windowLog: - case ZSTD_c_contentSizeFlag: - case ZSTD_c_checksumFlag: - case ZSTD_c_dictIDFlag: - case ZSTD_c_forceMaxWindow : - case ZSTD_c_nbWorkers: - case ZSTD_c_jobSize: - case ZSTD_c_overlapLog: - case ZSTD_c_rsyncable: - case ZSTD_c_enableLongDistanceMatching: - case ZSTD_c_ldmHashLog: - case ZSTD_c_ldmMinMatch: - case ZSTD_c_ldmBucketSizeLog: - case ZSTD_c_ldmHashRateLog: - case ZSTD_c_forceAttachDict: - case ZSTD_c_literalCompressionMode: - case ZSTD_c_targetCBlockSize: - case ZSTD_c_srcSizeHint: - default: - return 0; - } -} - -size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) -{ - DEBUGLOG(4, "ZSTD_CCtx_setParameter (%i, %i)", (int)param, value); - if (cctx->streamStage != zcss_init) { - if (ZSTD_isUpdateAuthorized(param)) { - cctx->cParamsChanged = 1; - } else { - RETURN_ERROR(stage_wrong, "can only set params in ctx init stage"); - } } - - switch(param) - { - case ZSTD_c_nbWorkers: - RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported, - "MT not compatible with static alloc"); - break; - - case ZSTD_c_compressionLevel: - case ZSTD_c_windowLog: - case ZSTD_c_hashLog: - case ZSTD_c_chainLog: - case ZSTD_c_searchLog: - case ZSTD_c_minMatch: - case ZSTD_c_targetLength: - case ZSTD_c_strategy: - case ZSTD_c_ldmHashRateLog: - case ZSTD_c_format: - case ZSTD_c_contentSizeFlag: - case ZSTD_c_checksumFlag: - case ZSTD_c_dictIDFlag: - case ZSTD_c_forceMaxWindow: - case ZSTD_c_forceAttachDict: - case ZSTD_c_literalCompressionMode: - case ZSTD_c_jobSize: - case ZSTD_c_overlapLog: - case ZSTD_c_rsyncable: - case ZSTD_c_enableLongDistanceMatching: - case ZSTD_c_ldmHashLog: - case ZSTD_c_ldmMinMatch: - case ZSTD_c_ldmBucketSizeLog: - case ZSTD_c_targetCBlockSize: - case ZSTD_c_srcSizeHint: - break; - - default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); - } - return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value); -} - -size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, - ZSTD_cParameter param, int value) -{ - DEBUGLOG(4, "ZSTD_CCtxParams_setParameter (%i, %i)", (int)param, value); - switch(param) - { - case ZSTD_c_format : - BOUNDCHECK(ZSTD_c_format, value); - CCtxParams->format = (ZSTD_format_e)value; - return (size_t)CCtxParams->format; - - case ZSTD_c_compressionLevel : { - FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); - if (value) { /* 0 : does not change current level */ - CCtxParams->compressionLevel = value; - } - if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel; - return 0; /* return type (size_t) cannot represent negative values */ - } - - case ZSTD_c_windowLog : - if (value!=0) /* 0 => use default */ - BOUNDCHECK(ZSTD_c_windowLog, value); - CCtxParams->cParams.windowLog = (U32)value; - return CCtxParams->cParams.windowLog; - - case ZSTD_c_hashLog : - if (value!=0) /* 0 => use default */ - BOUNDCHECK(ZSTD_c_hashLog, value); - CCtxParams->cParams.hashLog = (U32)value; - return CCtxParams->cParams.hashLog; - - case ZSTD_c_chainLog : - if (value!=0) /* 0 => use default */ - BOUNDCHECK(ZSTD_c_chainLog, value); - CCtxParams->cParams.chainLog = (U32)value; - return CCtxParams->cParams.chainLog; - - case ZSTD_c_searchLog : - if (value!=0) /* 0 => use default */ - BOUNDCHECK(ZSTD_c_searchLog, value); - CCtxParams->cParams.searchLog = (U32)value; - return (size_t)value; - - case ZSTD_c_minMatch : - if (value!=0) /* 0 => use default */ - BOUNDCHECK(ZSTD_c_minMatch, value); - CCtxParams->cParams.minMatch = value; - return CCtxParams->cParams.minMatch; - - case ZSTD_c_targetLength : - BOUNDCHECK(ZSTD_c_targetLength, value); - CCtxParams->cParams.targetLength = value; - return CCtxParams->cParams.targetLength; - - case ZSTD_c_strategy : - if (value!=0) /* 0 => use default */ - BOUNDCHECK(ZSTD_c_strategy, value); - CCtxParams->cParams.strategy = (ZSTD_strategy)value; - return (size_t)CCtxParams->cParams.strategy; - - case ZSTD_c_contentSizeFlag : - /* Content size written in frame header _when known_ (default:1) */ - DEBUGLOG(4, "set content size flag = %u", (value!=0)); - CCtxParams->fParams.contentSizeFlag = value != 0; - return CCtxParams->fParams.contentSizeFlag; - - case ZSTD_c_checksumFlag : - /* A 32-bits content checksum will be calculated and written at end of frame (default:0) */ - CCtxParams->fParams.checksumFlag = value != 0; - return CCtxParams->fParams.checksumFlag; - - case ZSTD_c_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */ - DEBUGLOG(4, "set dictIDFlag = %u", (value!=0)); - CCtxParams->fParams.noDictIDFlag = !value; - return !CCtxParams->fParams.noDictIDFlag; - - case ZSTD_c_forceMaxWindow : - CCtxParams->forceWindow = (value != 0); - return CCtxParams->forceWindow; - - case ZSTD_c_forceAttachDict : { - const ZSTD_dictAttachPref_e pref = (ZSTD_dictAttachPref_e)value; - BOUNDCHECK(ZSTD_c_forceAttachDict, pref); - CCtxParams->attachDictPref = pref; - return CCtxParams->attachDictPref; - } - - case ZSTD_c_literalCompressionMode : { - const ZSTD_literalCompressionMode_e lcm = (ZSTD_literalCompressionMode_e)value; - BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm); - CCtxParams->literalCompressionMode = lcm; - return CCtxParams->literalCompressionMode; - } - - case ZSTD_c_nbWorkers : -#ifndef ZSTD_MULTITHREAD - RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); - return 0; -#else - FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); - CCtxParams->nbWorkers = value; - return CCtxParams->nbWorkers; -#endif - - case ZSTD_c_jobSize : -#ifndef ZSTD_MULTITHREAD - RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); - return 0; -#else - /* Adjust to the minimum non-default value. */ - if (value != 0 && value < ZSTDMT_JOBSIZE_MIN) - value = ZSTDMT_JOBSIZE_MIN; - FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); - assert(value >= 0); - CCtxParams->jobSize = value; - return CCtxParams->jobSize; -#endif - - case ZSTD_c_overlapLog : -#ifndef ZSTD_MULTITHREAD - RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); - return 0; -#else - FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), ""); - CCtxParams->overlapLog = value; - return CCtxParams->overlapLog; -#endif - - case ZSTD_c_rsyncable : -#ifndef ZSTD_MULTITHREAD - RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading"); - return 0; -#else - FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), ""); - CCtxParams->rsyncable = value; - return CCtxParams->rsyncable; -#endif - - case ZSTD_c_enableLongDistanceMatching : - CCtxParams->ldmParams.enableLdm = (value!=0); - return CCtxParams->ldmParams.enableLdm; - - case ZSTD_c_ldmHashLog : - if (value!=0) /* 0 ==> auto */ - BOUNDCHECK(ZSTD_c_ldmHashLog, value); - CCtxParams->ldmParams.hashLog = value; - return CCtxParams->ldmParams.hashLog; - - case ZSTD_c_ldmMinMatch : - if (value!=0) /* 0 ==> default */ - BOUNDCHECK(ZSTD_c_ldmMinMatch, value); - CCtxParams->ldmParams.minMatchLength = value; - return CCtxParams->ldmParams.minMatchLength; - - case ZSTD_c_ldmBucketSizeLog : - if (value!=0) /* 0 ==> default */ - BOUNDCHECK(ZSTD_c_ldmBucketSizeLog, value); - CCtxParams->ldmParams.bucketSizeLog = value; - return CCtxParams->ldmParams.bucketSizeLog; - - case ZSTD_c_ldmHashRateLog : - RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN, - parameter_outOfBound, "Param out of bounds!"); - CCtxParams->ldmParams.hashRateLog = value; - return CCtxParams->ldmParams.hashRateLog; - - case ZSTD_c_targetCBlockSize : - if (value!=0) /* 0 ==> default */ - BOUNDCHECK(ZSTD_c_targetCBlockSize, value); - CCtxParams->targetCBlockSize = value; - return CCtxParams->targetCBlockSize; - - case ZSTD_c_srcSizeHint : - if (value!=0) /* 0 ==> default */ - BOUNDCHECK(ZSTD_c_srcSizeHint, value); - CCtxParams->srcSizeHint = value; - return CCtxParams->srcSizeHint; - - default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); - } -} - -size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value) -{ - return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value); -} - -size_t ZSTD_CCtxParams_getParameter( - ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value) -{ - switch(param) - { - case ZSTD_c_format : - *value = CCtxParams->format; - break; - case ZSTD_c_compressionLevel : - *value = CCtxParams->compressionLevel; - break; - case ZSTD_c_windowLog : - *value = (int)CCtxParams->cParams.windowLog; - break; - case ZSTD_c_hashLog : - *value = (int)CCtxParams->cParams.hashLog; - break; - case ZSTD_c_chainLog : - *value = (int)CCtxParams->cParams.chainLog; - break; - case ZSTD_c_searchLog : - *value = CCtxParams->cParams.searchLog; - break; - case ZSTD_c_minMatch : - *value = CCtxParams->cParams.minMatch; - break; - case ZSTD_c_targetLength : - *value = CCtxParams->cParams.targetLength; - break; - case ZSTD_c_strategy : - *value = (unsigned)CCtxParams->cParams.strategy; - break; - case ZSTD_c_contentSizeFlag : - *value = CCtxParams->fParams.contentSizeFlag; - break; - case ZSTD_c_checksumFlag : - *value = CCtxParams->fParams.checksumFlag; - break; - case ZSTD_c_dictIDFlag : - *value = !CCtxParams->fParams.noDictIDFlag; - break; - case ZSTD_c_forceMaxWindow : - *value = CCtxParams->forceWindow; - break; - case ZSTD_c_forceAttachDict : - *value = CCtxParams->attachDictPref; - break; - case ZSTD_c_literalCompressionMode : - *value = CCtxParams->literalCompressionMode; - break; - case ZSTD_c_nbWorkers : -#ifndef ZSTD_MULTITHREAD - assert(CCtxParams->nbWorkers == 0); -#endif - *value = CCtxParams->nbWorkers; - break; - case ZSTD_c_jobSize : -#ifndef ZSTD_MULTITHREAD - RETURN_ERROR(parameter_unsupported, "not compiled with multithreading"); -#else - assert(CCtxParams->jobSize <= INT_MAX); - *value = (int)CCtxParams->jobSize; - break; -#endif - case ZSTD_c_overlapLog : -#ifndef ZSTD_MULTITHREAD - RETURN_ERROR(parameter_unsupported, "not compiled with multithreading"); -#else - *value = CCtxParams->overlapLog; - break; -#endif - case ZSTD_c_rsyncable : -#ifndef ZSTD_MULTITHREAD - RETURN_ERROR(parameter_unsupported, "not compiled with multithreading"); -#else - *value = CCtxParams->rsyncable; - break; -#endif - case ZSTD_c_enableLongDistanceMatching : - *value = CCtxParams->ldmParams.enableLdm; - break; - case ZSTD_c_ldmHashLog : - *value = CCtxParams->ldmParams.hashLog; - break; - case ZSTD_c_ldmMinMatch : - *value = CCtxParams->ldmParams.minMatchLength; - break; - case ZSTD_c_ldmBucketSizeLog : - *value = CCtxParams->ldmParams.bucketSizeLog; - break; - case ZSTD_c_ldmHashRateLog : - *value = CCtxParams->ldmParams.hashRateLog; - break; - case ZSTD_c_targetCBlockSize : - *value = (int)CCtxParams->targetCBlockSize; - break; - case ZSTD_c_srcSizeHint : - *value = (int)CCtxParams->srcSizeHint; - break; - default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); - } - return 0; -} - -/** ZSTD_CCtx_setParametersUsingCCtxParams() : - * just applies `params` into `cctx` - * no action is performed, parameters are merely stored. - * If ZSTDMT is enabled, parameters are pushed to cctx->mtctx. - * This is possible even if a compression is ongoing. - * In which case, new parameters will be applied on the fly, starting with next compression job. - */ -size_t ZSTD_CCtx_setParametersUsingCCtxParams( - ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params) -{ - DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams"); - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, - "The context is in the wrong stage!"); - RETURN_ERROR_IF(cctx->cdict, stage_wrong, - "Can't override parameters with cdict attached (some must " - "be inherited from the cdict)."); - - cctx->requestedParams = *params; - return 0; -} - -ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize) -{ - DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize); - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, - "Can't set pledgedSrcSize when not in init stage."); - cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1; - return 0; -} - -/** - * Initializes the local dict using the requested parameters. - * NOTE: This does not use the pledged src size, because it may be used for more - * than one compression. - */ -static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx) -{ - ZSTD_localDict* const dl = &cctx->localDict; - ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams( - &cctx->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN, dl->dictSize); - if (dl->dict == NULL) { - /* No local dictionary. */ - assert(dl->dictBuffer == NULL); - assert(dl->cdict == NULL); - assert(dl->dictSize == 0); - return 0; - } - if (dl->cdict != NULL) { - assert(cctx->cdict == dl->cdict); - /* Local dictionary already initialized. */ - return 0; - } - assert(dl->dictSize > 0); - assert(cctx->cdict == NULL); - assert(cctx->prefixDict.dict == NULL); - - dl->cdict = ZSTD_createCDict_advanced( - dl->dict, - dl->dictSize, - ZSTD_dlm_byRef, - dl->dictContentType, - cParams, - cctx->customMem); - RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed"); - cctx->cdict = dl->cdict; - return 0; -} - -size_t ZSTD_CCtx_loadDictionary_advanced( - ZSTD_CCtx* cctx, const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType) -{ - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, - "Can't load a dictionary when ctx is not in init stage."); - RETURN_ERROR_IF(cctx->staticSize, memory_allocation, - "no malloc for static CCtx"); - DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize); - ZSTD_clearAllDicts(cctx); /* in case one already exists */ - if (dict == NULL || dictSize == 0) /* no dictionary mode */ - return 0; - if (dictLoadMethod == ZSTD_dlm_byRef) { - cctx->localDict.dict = dict; - } else { - void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem); - RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!"); - memcpy(dictBuffer, dict, dictSize); - cctx->localDict.dictBuffer = dictBuffer; - cctx->localDict.dict = dictBuffer; - } - cctx->localDict.dictSize = dictSize; - cctx->localDict.dictContentType = dictContentType; - return 0; -} - -ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference( - ZSTD_CCtx* cctx, const void* dict, size_t dictSize) -{ - return ZSTD_CCtx_loadDictionary_advanced( - cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto); -} - -ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize) -{ - return ZSTD_CCtx_loadDictionary_advanced( - cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto); -} - - -size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) -{ - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, - "Can't ref a dict when ctx not in init stage."); - /* Free the existing local cdict (if any) to save memory. */ - ZSTD_clearAllDicts(cctx); - cctx->cdict = cdict; - return 0; -} - -size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize) -{ - return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent); -} - -size_t ZSTD_CCtx_refPrefix_advanced( - ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType) -{ - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, - "Can't ref a prefix when ctx not in init stage."); - ZSTD_clearAllDicts(cctx); - if (prefix != NULL && prefixSize > 0) { - cctx->prefixDict.dict = prefix; - cctx->prefixDict.dictSize = prefixSize; - cctx->prefixDict.dictContentType = dictContentType; - } - return 0; -} - -/*! ZSTD_CCtx_reset() : - * Also dumps dictionary */ -size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset) -{ - if ( (reset == ZSTD_reset_session_only) - || (reset == ZSTD_reset_session_and_parameters) ) { - cctx->streamStage = zcss_init; - cctx->pledgedSrcSizePlusOne = 0; - } - if ( (reset == ZSTD_reset_parameters) - || (reset == ZSTD_reset_session_and_parameters) ) { - RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, - "Can't reset parameters only when not in init stage."); - ZSTD_clearAllDicts(cctx); - return ZSTD_CCtxParams_reset(&cctx->requestedParams); - } - return 0; -} - - -/** ZSTD_checkCParams() : - control CParam values remain within authorized range. - @return : 0, or an error code if one value is beyond authorized range */ -size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) -{ - BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog); - BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog); - BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog); - BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog); - BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch); - BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength); - BOUNDCHECK(ZSTD_c_strategy, cParams.strategy); - return 0; -} - -/** ZSTD_clampCParams() : - * make CParam values within valid range. - * @return : valid CParams */ -static ZSTD_compressionParameters -ZSTD_clampCParams(ZSTD_compressionParameters cParams) -{ -# define CLAMP_TYPE(cParam, val, type) { \ - ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam); \ - if ((int)valbounds.upperBound) val=(type)bounds.upperBound; \ - } -# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned) - CLAMP(ZSTD_c_windowLog, cParams.windowLog); - CLAMP(ZSTD_c_chainLog, cParams.chainLog); - CLAMP(ZSTD_c_hashLog, cParams.hashLog); - CLAMP(ZSTD_c_searchLog, cParams.searchLog); - CLAMP(ZSTD_c_minMatch, cParams.minMatch); - CLAMP(ZSTD_c_targetLength,cParams.targetLength); - CLAMP_TYPE(ZSTD_c_strategy,cParams.strategy, ZSTD_strategy); - return cParams; -} - -/** ZSTD_cycleLog() : - * condition for correct operation : hashLog > 1 */ -U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) -{ - U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2); - return hashLog - btScale; -} - -/** ZSTD_adjustCParams_internal() : - * optimize `cPar` for a specified input (`srcSize` and `dictSize`). - * mostly downsize to reduce memory consumption and initialization latency. - * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known. - * note : `srcSize==0` means 0! - * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */ -static ZSTD_compressionParameters -ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, - unsigned long long srcSize, - size_t dictSize) -{ - static const U64 minSrcSize = 513; /* (1<<9) + 1 */ - static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); - assert(ZSTD_checkCParams(cPar)==0); - - if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN) - srcSize = minSrcSize; - - /* resize windowLog if input is small enough, to use less memory */ - if ( (srcSize < maxWindowResize) - && (dictSize < maxWindowResize) ) { - U32 const tSize = (U32)(srcSize + dictSize); - static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN; - U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN : - ZSTD_highbit32(tSize-1) + 1; - if (cPar.windowLog > srcLog) cPar.windowLog = srcLog; - } - if (cPar.hashLog > cPar.windowLog+1) cPar.hashLog = cPar.windowLog+1; - { U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); - if (cycleLog > cPar.windowLog) - cPar.chainLog -= (cycleLog - cPar.windowLog); - } - - if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) - cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */ - - return cPar; -} - -ZSTD_compressionParameters -ZSTD_adjustCParams(ZSTD_compressionParameters cPar, - unsigned long long srcSize, - size_t dictSize) -{ - cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */ - if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize); -} - -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize); -static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize); - -ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( - const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize) -{ - ZSTD_compressionParameters cParams; - if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { - srcSizeHint = CCtxParams->srcSizeHint; - } - cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize); - if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; - if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog; - if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog; - if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog; - if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog; - if (CCtxParams->cParams.minMatch) cParams.minMatch = CCtxParams->cParams.minMatch; - if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength; - if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy; - assert(!ZSTD_checkCParams(cParams)); - /* srcSizeHint == 0 means 0 */ - return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize); -} - -static size_t -ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams, - const U32 forCCtx) -{ - size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog); - size_t const hSize = ((size_t)1) << cParams->hashLog; - U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; - size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0; - /* We don't use ZSTD_cwksp_alloc_size() here because the tables aren't - * surrounded by redzones in ASAN. */ - size_t const tableSpace = chainSize * sizeof(U32) - + hSize * sizeof(U32) - + h3Size * sizeof(U32); - size_t const optPotentialSpace = - ZSTD_cwksp_alloc_size((MaxML+1) * sizeof(U32)) - + ZSTD_cwksp_alloc_size((MaxLL+1) * sizeof(U32)) - + ZSTD_cwksp_alloc_size((MaxOff+1) * sizeof(U32)) - + ZSTD_cwksp_alloc_size((1<strategy >= ZSTD_btopt)) - ? optPotentialSpace - : 0; - DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u", - (U32)chainSize, (U32)hSize, (U32)h3Size); - return tableSpace + optSpace; -} - -size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) -{ - RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); - { ZSTD_compressionParameters const cParams = - ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0); - size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); - U32 const divider = (cParams.minMatch==3) ? 3 : 4; - size_t const maxNbSeq = blockSize / divider; - size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) - + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef)) - + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); - size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE); - size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); - size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1); - - size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams); - size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq)); - - /* estimateCCtxSize is for one-shot compression. So no buffers should - * be needed. However, we still allocate two 0-sized buffers, which can - * take space under ASAN. */ - size_t const bufferSpace = ZSTD_cwksp_alloc_size(0) - + ZSTD_cwksp_alloc_size(0); - - size_t const cctxSpace = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)); - - size_t const neededSpace = - cctxSpace + - entropySpace + - blockStateSpace + - ldmSpace + - ldmSeqSpace + - matchStateSize + - tokenSpace + - bufferSpace; - - DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace); - return neededSpace; - } -} - -size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) -{ - ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams); - return ZSTD_estimateCCtxSize_usingCCtxParams(¶ms); -} - -static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) -{ - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); - return ZSTD_estimateCCtxSize_usingCParams(cParams); -} - -size_t ZSTD_estimateCCtxSize(int compressionLevel) -{ - int level; - size_t memBudget = 0; - for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) { - size_t const newMB = ZSTD_estimateCCtxSize_internal(level); - if (newMB > memBudget) memBudget = newMB; - } - return memBudget; -} - -size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) -{ - RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); - { ZSTD_compressionParameters const cParams = - ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0); - size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params); - size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); - size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize; - size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1; - size_t const streamingSize = ZSTD_cwksp_alloc_size(inBuffSize) - + ZSTD_cwksp_alloc_size(outBuffSize); - - return CCtxSize + streamingSize; - } -} - -size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) -{ - ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams); - return ZSTD_estimateCStreamSize_usingCCtxParams(¶ms); -} - -static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) -{ - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); - return ZSTD_estimateCStreamSize_usingCParams(cParams); -} - -size_t ZSTD_estimateCStreamSize(int compressionLevel) -{ - int level; - size_t memBudget = 0; - for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) { - size_t const newMB = ZSTD_estimateCStreamSize_internal(level); - if (newMB > memBudget) memBudget = newMB; - } - return memBudget; -} - -/* ZSTD_getFrameProgression(): - * tells how much data has been consumed (input) and produced (output) for current frame. - * able to count progression inside worker threads (non-blocking mode). - */ -ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx) -{ -#ifdef ZSTD_MULTITHREAD - if (cctx->appliedParams.nbWorkers > 0) { - return ZSTDMT_getFrameProgression(cctx->mtctx); - } -#endif - { ZSTD_frameProgression fp; - size_t const buffered = (cctx->inBuff == NULL) ? 0 : - cctx->inBuffPos - cctx->inToCompress; - if (buffered) assert(cctx->inBuffPos >= cctx->inToCompress); - assert(buffered <= ZSTD_BLOCKSIZE_MAX); - fp.ingested = cctx->consumedSrcSize + buffered; - fp.consumed = cctx->consumedSrcSize; - fp.produced = cctx->producedCSize; - fp.flushed = cctx->producedCSize; /* simplified; some data might still be left within streaming output buffer */ - fp.currentJobID = 0; - fp.nbActiveWorkers = 0; - return fp; -} } - -/*! ZSTD_toFlushNow() - * Only useful for multithreading scenarios currently (nbWorkers >= 1). - */ -size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx) -{ -#ifdef ZSTD_MULTITHREAD - if (cctx->appliedParams.nbWorkers > 0) { - return ZSTDMT_toFlushNow(cctx->mtctx); - } -#endif - (void)cctx; - return 0; /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */ -} - -static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1, - ZSTD_compressionParameters cParams2) -{ - (void)cParams1; - (void)cParams2; - assert(cParams1.windowLog == cParams2.windowLog); - assert(cParams1.chainLog == cParams2.chainLog); - assert(cParams1.hashLog == cParams2.hashLog); - assert(cParams1.searchLog == cParams2.searchLog); - assert(cParams1.minMatch == cParams2.minMatch); - assert(cParams1.targetLength == cParams2.targetLength); - assert(cParams1.strategy == cParams2.strategy); -} - -void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs) -{ - int i; - for (i = 0; i < ZSTD_REP_NUM; ++i) - bs->rep[i] = ZSTDInternalConstants::repStartValue[i]; - bs->entropy.huf.repeatMode = HUF_repeat_none; - bs->entropy.fse.offcode_repeatMode = FSE_repeat_none; - bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none; - bs->entropy.fse.litlength_repeatMode = FSE_repeat_none; -} - -/*! ZSTD_invalidateMatchState() - * Invalidate all the matches in the match finder tables. - * Requires nextSrc and base to be set (can be NULL). - */ -static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms) -{ - ZSTD_window_clear(&ms->window); - - ms->nextToUpdate = ms->window.dictLimit; - ms->loadedDictEnd = 0; - ms->opt.litLengthSum = 0; /* force reset of btopt stats */ - ms->dictMatchState = NULL; -} - -/** - * Indicates whether this compression proceeds directly from user-provided - * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or - * whether the context needs to buffer the input/output (ZSTDb_buffered). - */ -typedef enum { - ZSTDb_not_buffered, - ZSTDb_buffered -} ZSTD_buffered_policy_e; - -/** - * Controls, for this matchState reset, whether the tables need to be cleared / - * prepared for the coming compression (ZSTDcrp_makeClean), or whether the - * tables can be left unclean (ZSTDcrp_leaveDirty), because we know that a - * subsequent operation will overwrite the table space anyways (e.g., copying - * the matchState contents in from a CDict). - */ -typedef enum { - ZSTDcrp_makeClean, - ZSTDcrp_leaveDirty -} ZSTD_compResetPolicy_e; - -/** - * Controls, for this matchState reset, whether indexing can continue where it - * left off (ZSTDirp_continue), or whether it needs to be restarted from zero - * (ZSTDirp_reset). - */ -typedef enum { - ZSTDirp_continue, - ZSTDirp_reset -} ZSTD_indexResetPolicy_e; - -typedef enum { - ZSTD_resetTarget_CDict, - ZSTD_resetTarget_CCtx -} ZSTD_resetTarget_e; - -static size_t -ZSTD_reset_matchState(ZSTD_matchState_t* ms, - ZSTD_cwksp* ws, - const ZSTD_compressionParameters* cParams, - const ZSTD_compResetPolicy_e crp, - const ZSTD_indexResetPolicy_e forceResetIndex, - const ZSTD_resetTarget_e forWho) -{ - size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog); - size_t const hSize = ((size_t)1) << cParams->hashLog; - U32 const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0; - size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0; - - DEBUGLOG(4, "reset indices : %u", forceResetIndex == ZSTDirp_reset); - if (forceResetIndex == ZSTDirp_reset) { - ZSTD_window_init(&ms->window); - ZSTD_cwksp_mark_tables_dirty(ws); - } - - ms->hashLog3 = hashLog3; - - ZSTD_invalidateMatchState(ms); - - assert(!ZSTD_cwksp_reserve_failed(ws)); /* check that allocation hasn't already failed */ - - ZSTD_cwksp_clear_tables(ws); - - DEBUGLOG(5, "reserving table space"); - /* table Space */ - ms->hashTable = (U32*)ZSTD_cwksp_reserve_table(ws, hSize * sizeof(U32)); - ms->chainTable = (U32*)ZSTD_cwksp_reserve_table(ws, chainSize * sizeof(U32)); - ms->hashTable3 = (U32*)ZSTD_cwksp_reserve_table(ws, h3Size * sizeof(U32)); - RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation, - "failed a workspace allocation in ZSTD_reset_matchState"); - - DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_leaveDirty); - if (crp!=ZSTDcrp_leaveDirty) { - /* reset tables only */ - ZSTD_cwksp_clean_tables(ws); - } - - /* opt parser space */ - if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) { - DEBUGLOG(4, "reserving optimal parser space"); - ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (1<opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxLL+1) * sizeof(unsigned)); - ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxML+1) * sizeof(unsigned)); - ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxOff+1) * sizeof(unsigned)); - ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t)); - ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t)); - } - - ms->cParams = *cParams; - - RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation, - "failed a workspace allocation in ZSTD_reset_matchState"); - - return 0; -} - -/* ZSTD_indexTooCloseToMax() : - * minor optimization : prefer memset() rather than reduceIndex() - * which is measurably slow in some circumstances (reported for Visual Studio). - * Works when re-using a context for a lot of smallish inputs : - * if all inputs are smaller than ZSTD_INDEXOVERFLOW_MARGIN, - * memset() will be triggered before reduceIndex(). - */ -#define ZSTD_INDEXOVERFLOW_MARGIN (16 MB) -static int ZSTD_indexTooCloseToMax(ZSTD_window_t w) -{ - return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN); -} - -/*! ZSTD_resetCCtx_internal() : - note : `params` are assumed fully validated at this stage */ -static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, - ZSTD_CCtx_params params, - U64 const pledgedSrcSize, - ZSTD_compResetPolicy_e const crp, - ZSTD_buffered_policy_e const zbuff) -{ - ZSTD_cwksp* const ws = &zc->workspace; - DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u", - (U32)pledgedSrcSize, params.cParams.windowLog); - assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); - - zc->isFirstBlock = 1; - - if (params.ldmParams.enableLdm) { - /* Adjust long distance matching parameters */ - ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams); - assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog); - assert(params.ldmParams.hashRateLog < 32); - zc->ldmState.hashPower = ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength); - } - - { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize)); - size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize); - U32 const divider = (params.cParams.minMatch==3) ? 3 : 4; - size_t const maxNbSeq = blockSize / divider; - size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) - + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef)) - + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); - size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0; - size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0; - size_t const matchStateSize = ZSTD_sizeof_matchState(¶ms.cParams, /* forCCtx */ 1); - size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize); - - ZSTD_indexResetPolicy_e needsIndexReset = zc->initialized ? ZSTDirp_continue : ZSTDirp_reset; - - if (ZSTD_indexTooCloseToMax(zc->blockState.matchState.window)) { - needsIndexReset = ZSTDirp_reset; - } - - if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0); - - /* Check if workspace is large enough, alloc a new one if needed */ - { size_t const cctxSpace = zc->staticSize ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0; - size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE); - size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); - size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) + ZSTD_cwksp_alloc_size(buffOutSize); - size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams); - size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq)); - - size_t const neededSpace = - cctxSpace + - entropySpace + - blockStateSpace + - ldmSpace + - ldmSeqSpace + - matchStateSize + - tokenSpace + - bufferSpace; - - int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace; - int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace); - - DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers", - neededSpace>>10, matchStateSize>>10, bufferSpace>>10); - DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize); - - if (workspaceTooSmall || workspaceWasteful) { - DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB", - ZSTD_cwksp_sizeof(ws) >> 10, - neededSpace >> 10); - - RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize"); - - needsIndexReset = ZSTDirp_reset; - - ZSTD_cwksp_free(ws, zc->customMem); - FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem), ""); - - DEBUGLOG(5, "reserving object space"); - /* Statically sized space. - * entropyWorkspace never moves, - * though prev/next block swap places */ - assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t))); - zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); - RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock"); - zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); - RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock"); - zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, HUF_WORKSPACE_SIZE); - RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace"); - } } - - ZSTD_cwksp_clear(ws); - - /* init params */ - zc->appliedParams = params; - zc->blockState.matchState.cParams = params.cParams; - zc->pledgedSrcSizePlusOne = pledgedSrcSize+1; - zc->consumedSrcSize = 0; - zc->producedCSize = 0; - if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN) - zc->appliedParams.fParams.contentSizeFlag = 0; - DEBUGLOG(4, "pledged content size : %u ; flag : %u", - (unsigned)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag); - zc->blockSize = blockSize; - - XXH64_reset(&zc->xxhState, 0); - zc->stage = ZSTDcs_init; - zc->dictID = 0; - - ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock); - - /* ZSTD_wildcopy() is used to copy into the literals buffer, - * so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes. - */ - zc->seqStore.litStart = ZSTD_cwksp_reserve_buffer(ws, blockSize + WILDCOPY_OVERLENGTH); - zc->seqStore.maxNbLit = blockSize; - - /* buffers */ - zc->inBuffSize = buffInSize; - zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize); - zc->outBuffSize = buffOutSize; - zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize); - - /* ldm bucketOffsets table */ - if (params.ldmParams.enableLdm) { - /* TODO: avoid memset? */ - size_t const ldmBucketSize = - ((size_t)1) << (params.ldmParams.hashLog - - params.ldmParams.bucketSizeLog); - zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, ldmBucketSize); - memset(zc->ldmState.bucketOffsets, 0, ldmBucketSize); - } - - /* sequences storage */ - ZSTD_referenceExternalSequences(zc, NULL, 0); - zc->seqStore.maxNbSeq = maxNbSeq; - zc->seqStore.llCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE)); - zc->seqStore.mlCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE)); - zc->seqStore.ofCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE)); - zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned(ws, maxNbSeq * sizeof(seqDef)); - - FORWARD_IF_ERROR(ZSTD_reset_matchState( - &zc->blockState.matchState, - ws, - ¶ms.cParams, - crp, - needsIndexReset, - ZSTD_resetTarget_CCtx), ""); - - /* ldm hash table */ - if (params.ldmParams.enableLdm) { - /* TODO: avoid memset? */ - size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog; - zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t)); - memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t)); - zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq)); - zc->maxNbLdmSequences = maxNbLdmSeq; - - ZSTD_window_init(&zc->ldmState.window); - ZSTD_window_clear(&zc->ldmState.window); - zc->ldmState.loadedDictEnd = 0; - } - - DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws)); - zc->initialized = 1; - - return 0; - } -} - -/* ZSTD_invalidateRepCodes() : - * ensures next compression will not use repcodes from previous block. - * Note : only works with regular variant; - * do not use with extDict variant ! */ -void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) { - int i; - for (i=0; iblockState.prevCBlock->rep[i] = 0; - assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window)); -} - -/* These are the approximate sizes for each strategy past which copying the - * dictionary tables into the working context is faster than using them - * in-place. - */ -static const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = { - 8 KB, /* unused */ - 8 KB, /* ZSTD_fast */ - 16 KB, /* ZSTD_dfast */ - 32 KB, /* ZSTD_greedy */ - 32 KB, /* ZSTD_lazy */ - 32 KB, /* ZSTD_lazy2 */ - 32 KB, /* ZSTD_btlazy2 */ - 32 KB, /* ZSTD_btopt */ - 8 KB, /* ZSTD_btultra */ - 8 KB /* ZSTD_btultra2 */ -}; - -static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict, - const ZSTD_CCtx_params* params, - U64 pledgedSrcSize) -{ - size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy]; - return ( pledgedSrcSize <= cutoff - || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN - || params->attachDictPref == ZSTD_dictForceAttach ) - && params->attachDictPref != ZSTD_dictForceCopy - && !params->forceWindow; /* dictMatchState isn't correctly - * handled in _enforceMaxDist */ -} - -static size_t -ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, - const ZSTD_CDict* cdict, - ZSTD_CCtx_params params, - U64 pledgedSrcSize, - ZSTD_buffered_policy_e zbuff) -{ - { const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams; - unsigned const windowLog = params.cParams.windowLog; - assert(windowLog != 0); - /* Resize working context table params for input only, since the dict - * has its own tables. */ - /* pledgeSrcSize == 0 means 0! */ - params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0); - params.cParams.windowLog = windowLog; - FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, - ZSTDcrp_makeClean, zbuff), ""); - assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy); - } - - { const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc - - cdict->matchState.window.base); - const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit; - if (cdictLen == 0) { - /* don't even attach dictionaries with no contents */ - DEBUGLOG(4, "skipping attaching empty dictionary"); - } else { - DEBUGLOG(4, "attaching dictionary into context"); - cctx->blockState.matchState.dictMatchState = &cdict->matchState; - - /* prep working match state so dict matches never have negative indices - * when they are translated to the working context's index space. */ - if (cctx->blockState.matchState.window.dictLimit < cdictEnd) { - cctx->blockState.matchState.window.nextSrc = - cctx->blockState.matchState.window.base + cdictEnd; - ZSTD_window_clear(&cctx->blockState.matchState.window); - } - /* loadedDictEnd is expressed within the referential of the active context */ - cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit; - } } - - cctx->dictID = cdict->dictID; - - /* copy block state */ - memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); - - return 0; -} - -static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, - const ZSTD_CDict* cdict, - ZSTD_CCtx_params params, - U64 pledgedSrcSize, - ZSTD_buffered_policy_e zbuff) -{ - const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams; - - DEBUGLOG(4, "copying dictionary into context"); - - { unsigned const windowLog = params.cParams.windowLog; - assert(windowLog != 0); - /* Copy only compression parameters related to tables. */ - params.cParams = *cdict_cParams; - params.cParams.windowLog = windowLog; - FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, - ZSTDcrp_leaveDirty, zbuff), ""); - assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy); - assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog); - assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog); - } - - ZSTD_cwksp_mark_tables_dirty(&cctx->workspace); - - /* copy tables */ - { size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog); - size_t const hSize = (size_t)1 << cdict_cParams->hashLog; - - memcpy(cctx->blockState.matchState.hashTable, - cdict->matchState.hashTable, - hSize * sizeof(U32)); - memcpy(cctx->blockState.matchState.chainTable, - cdict->matchState.chainTable, - chainSize * sizeof(U32)); - } - - /* Zero the hashTable3, since the cdict never fills it */ - { int const h3log = cctx->blockState.matchState.hashLog3; - size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; - assert(cdict->matchState.hashLog3 == 0); - memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32)); - } - - ZSTD_cwksp_mark_tables_clean(&cctx->workspace); - - /* copy dictionary offsets */ - { ZSTD_matchState_t const* srcMatchState = &cdict->matchState; - ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState; - dstMatchState->window = srcMatchState->window; - dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; - dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; - } - - cctx->dictID = cdict->dictID; - - /* copy block state */ - memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); - - return 0; -} - -/* We have a choice between copying the dictionary context into the working - * context, or referencing the dictionary context from the working context - * in-place. We decide here which strategy to use. */ -static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx, - const ZSTD_CDict* cdict, - const ZSTD_CCtx_params* params, - U64 pledgedSrcSize, - ZSTD_buffered_policy_e zbuff) -{ - - DEBUGLOG(4, "ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)", - (unsigned)pledgedSrcSize); - - if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) { - return ZSTD_resetCCtx_byAttachingCDict( - cctx, cdict, *params, pledgedSrcSize, zbuff); - } else { - return ZSTD_resetCCtx_byCopyingCDict( - cctx, cdict, *params, pledgedSrcSize, zbuff); - } -} - -/*! ZSTD_copyCCtx_internal() : - * Duplicate an existing context `srcCCtx` into another one `dstCCtx`. - * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()). - * The "context", in this case, refers to the hash and chain tables, - * entropy tables, and dictionary references. - * `windowLog` value is enforced if != 0, otherwise value is copied from srcCCtx. - * @return : 0, or an error code */ -static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, - const ZSTD_CCtx* srcCCtx, - ZSTD_frameParameters fParams, - U64 pledgedSrcSize, - ZSTD_buffered_policy_e zbuff) -{ - DEBUGLOG(5, "ZSTD_copyCCtx_internal"); - RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong, - "Can't copy a ctx that's not in init stage."); - - memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); - { ZSTD_CCtx_params params = dstCCtx->requestedParams; - /* Copy only compression parameters related to tables. */ - params.cParams = srcCCtx->appliedParams.cParams; - params.fParams = fParams; - ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize, - ZSTDcrp_leaveDirty, zbuff); - assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog); - assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy); - assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog); - assert(dstCCtx->appliedParams.cParams.chainLog == srcCCtx->appliedParams.cParams.chainLog); - assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3); - } - - ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace); - - /* copy tables */ - { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog); - size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog; - int const h3log = srcCCtx->blockState.matchState.hashLog3; - size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; - - memcpy(dstCCtx->blockState.matchState.hashTable, - srcCCtx->blockState.matchState.hashTable, - hSize * sizeof(U32)); - memcpy(dstCCtx->blockState.matchState.chainTable, - srcCCtx->blockState.matchState.chainTable, - chainSize * sizeof(U32)); - memcpy(dstCCtx->blockState.matchState.hashTable3, - srcCCtx->blockState.matchState.hashTable3, - h3Size * sizeof(U32)); - } - - ZSTD_cwksp_mark_tables_clean(&dstCCtx->workspace); - - /* copy dictionary offsets */ - { - const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState; - ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState; - dstMatchState->window = srcMatchState->window; - dstMatchState->nextToUpdate = srcMatchState->nextToUpdate; - dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd; - } - dstCCtx->dictID = srcCCtx->dictID; - - /* copy block state */ - memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock)); - - return 0; -} - -/*! ZSTD_copyCCtx() : - * Duplicate an existing context `srcCCtx` into another one `dstCCtx`. - * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()). - * pledgedSrcSize==0 means "unknown". -* @return : 0, or an error code */ -size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize) -{ - ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; - ZSTD_buffered_policy_e const zbuff = (ZSTD_buffered_policy_e)(srcCCtx->inBuffSize>0); - ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1); - if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; - fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN); - - return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx, - fParams, pledgedSrcSize, - zbuff); -} - - -#define ZSTD_ROWSIZE 16 -/*! ZSTD_reduceTable() : - * reduce table indexes by `reducerValue`, or squash to zero. - * PreserveMark preserves "unsorted mark" for btlazy2 strategy. - * It must be set to a clear 0/1 value, to remove branch during inlining. - * Presume table size is a multiple of ZSTD_ROWSIZE - * to help auto-vectorization */ -FORCE_INLINE_TEMPLATE void -ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerValue, int const preserveMark) -{ - int const nbRows = (int)size / ZSTD_ROWSIZE; - int cellNb = 0; - int rowNb; - assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */ - assert(size < (1U<<31)); /* can be casted to int */ - -#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) - /* To validate that the table re-use logic is sound, and that we don't - * access table space that we haven't cleaned, we re-"poison" the table - * space every time we mark it dirty. - * - * This function however is intended to operate on those dirty tables and - * re-clean them. So when this function is used correctly, we can unpoison - * the memory it operated on. This introduces a blind spot though, since - * if we now try to operate on __actually__ poisoned memory, we will not - * detect that. */ - __msan_unpoison(table, size * sizeof(U32)); -#endif - - for (rowNb=0 ; rowNb < nbRows ; rowNb++) { - int column; - for (column=0; columncParams.hashLog; - ZSTD_reduceTable(ms->hashTable, hSize, reducerValue); - } - - if (params->cParams.strategy != ZSTD_fast) { - U32 const chainSize = (U32)1 << params->cParams.chainLog; - if (params->cParams.strategy == ZSTD_btlazy2) - ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue); - else - ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue); - } - - if (ms->hashLog3) { - U32 const h3Size = (U32)1 << ms->hashLog3; - ZSTD_reduceTable(ms->hashTable3, h3Size, reducerValue); - } -} - - -/*-******************************************************* -* Block entropic compression -*********************************************************/ - -/* See doc/zstd_compression_format.md for detailed format description */ - -void ZSTD_seqToCodes(const seqStore_t* seqStorePtr) -{ - const seqDef* const sequences = seqStorePtr->sequencesStart; - BYTE* const llCodeTable = seqStorePtr->llCode; - BYTE* const ofCodeTable = seqStorePtr->ofCode; - BYTE* const mlCodeTable = seqStorePtr->mlCode; - U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); - U32 u; - assert(nbSeq <= seqStorePtr->maxNbSeq); - for (u=0; ulongLengthID==1) - llCodeTable[seqStorePtr->longLengthPos] = MaxLL; - if (seqStorePtr->longLengthID==2) - mlCodeTable[seqStorePtr->longLengthPos] = MaxML; -} - -/* ZSTD_useTargetCBlockSize(): - * Returns if target compressed block size param is being used. - * If used, compression will do best effort to make a compressed block size to be around targetCBlockSize. - * Returns 1 if true, 0 otherwise. */ -static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams) -{ - DEBUGLOG(5, "ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)", cctxParams->targetCBlockSize); - return (cctxParams->targetCBlockSize != 0); -} - -/* ZSTD_compressSequences_internal(): - * actually compresses both literals and sequences */ -MEM_STATIC size_t -ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, - const ZSTD_entropyCTables_t* prevEntropy, - ZSTD_entropyCTables_t* nextEntropy, - const ZSTD_CCtx_params* cctxParams, - void* dst, size_t dstCapacity, - void* entropyWorkspace, size_t entropyWkspSize, - const int bmi2) -{ - const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN; - ZSTD_strategy const strategy = cctxParams->cParams.strategy; - unsigned count[MaxSeq+1]; - FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable; - FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable; - FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable; - U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */ - const seqDef* const sequences = seqStorePtr->sequencesStart; - const BYTE* const ofCodeTable = seqStorePtr->ofCode; - const BYTE* const llCodeTable = seqStorePtr->llCode; - const BYTE* const mlCodeTable = seqStorePtr->mlCode; - BYTE* const ostart = (BYTE*)dst; - BYTE* const oend = ostart + dstCapacity; - BYTE* op = ostart; - size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart); - BYTE* seqHead; - BYTE* lastNCount = NULL; - - DEBUGLOG(5, "ZSTD_compressSequences_internal (nbSeq=%zu)", nbSeq); - ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<litStart; - size_t const litSize = (size_t)(seqStorePtr->lit - literals); - size_t const cSize = ZSTD_compressLiterals( - &prevEntropy->huf, &nextEntropy->huf, - cctxParams->cParams.strategy, - ZSTD_disableLiteralsCompression(cctxParams), - op, dstCapacity, - literals, litSize, - entropyWorkspace, entropyWkspSize, - bmi2); - FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed"); - assert(cSize <= dstCapacity); - op += cSize; - } - - /* Sequences Header */ - RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/, - dstSize_tooSmall, "Can't fit seq hdr in output buf!"); - if (nbSeq < 128) { - *op++ = (BYTE)nbSeq; - } else if (nbSeq < LONGNBSEQ) { - op[0] = (BYTE)((nbSeq>>8) + 0x80); - op[1] = (BYTE)nbSeq; - op+=2; - } else { - op[0]=0xFF; - MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)); - op+=3; - } - assert(op <= oend); - if (nbSeq==0) { - /* Copy the old tables over as if we repeated them */ - memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse)); - return (size_t)(op - ostart); - } - - /* seqHead : flags for FSE encoding type */ - seqHead = op++; - assert(op <= oend); - - /* convert length/distances into codes */ - ZSTD_seqToCodes(seqStorePtr); - /* build CTable for Literal Lengths */ - { unsigned max = MaxLL; - size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ - DEBUGLOG(5, "Building LL table"); - nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode; - LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode, - count, max, mostFrequent, nbSeq, - LLFSELog, prevEntropy->fse.litlengthCTable, - ZSTDInternalConstants::LL_defaultNorm, ZSTDInternalConstants::LL_defaultNormLog, - ZSTD_defaultAllowed, strategy); - assert(set_basic < set_compressed && set_rle < set_compressed); - assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable( - op, (size_t)(oend - op), - CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype, - count, max, llCodeTable, nbSeq, - ZSTDInternalConstants::LL_defaultNorm, ZSTDInternalConstants::LL_defaultNormLog, MaxLL, - prevEntropy->fse.litlengthCTable, - sizeof(prevEntropy->fse.litlengthCTable), - entropyWorkspace, entropyWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed"); - if (LLtype == set_compressed) - lastNCount = op; - op += countSize; - assert(op <= oend); - } } - /* build CTable for Offsets */ - { unsigned max = MaxOff; - size_t const mostFrequent = HIST_countFast_wksp( - count, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ - /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */ - ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed; - DEBUGLOG(5, "Building OF table"); - nextEntropy->fse.offcode_repeatMode = prevEntropy->fse.offcode_repeatMode; - Offtype = ZSTD_selectEncodingType(&nextEntropy->fse.offcode_repeatMode, - count, max, mostFrequent, nbSeq, - OffFSELog, prevEntropy->fse.offcodeCTable, - ZSTDInternalConstants::OF_defaultNorm, ZSTDInternalConstants::OF_defaultNormLog, - defaultPolicy, strategy); - assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable( - op, (size_t)(oend - op), - CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype, - count, max, ofCodeTable, nbSeq, - ZSTDInternalConstants::OF_defaultNorm, ZSTDInternalConstants::OF_defaultNormLog, DefaultMaxOff, - prevEntropy->fse.offcodeCTable, - sizeof(prevEntropy->fse.offcodeCTable), - entropyWorkspace, entropyWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed"); - if (Offtype == set_compressed) - lastNCount = op; - op += countSize; - assert(op <= oend); - } } - /* build CTable for MatchLengths */ - { unsigned max = MaxML; - size_t const mostFrequent = HIST_countFast_wksp( - count, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */ - DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op)); - nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode; - MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode, - count, max, mostFrequent, nbSeq, - MLFSELog, prevEntropy->fse.matchlengthCTable, - ZSTDInternalConstants::ML_defaultNorm, ZSTDInternalConstants::ML_defaultNormLog, - ZSTD_defaultAllowed, strategy); - assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable( - op, (size_t)(oend - op), - CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype, - count, max, mlCodeTable, nbSeq, - ZSTDInternalConstants::ML_defaultNorm, ZSTDInternalConstants::ML_defaultNormLog, MaxML, - prevEntropy->fse.matchlengthCTable, - sizeof(prevEntropy->fse.matchlengthCTable), - entropyWorkspace, entropyWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed"); - if (MLtype == set_compressed) - lastNCount = op; - op += countSize; - assert(op <= oend); - } } - - *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); - - { size_t const bitstreamSize = ZSTD_encodeSequences( - op, (size_t)(oend - op), - CTable_MatchLength, mlCodeTable, - CTable_OffsetBits, ofCodeTable, - CTable_LitLength, llCodeTable, - sequences, nbSeq, - longOffsets, bmi2); - FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed"); - op += bitstreamSize; - assert(op <= oend); - /* zstd versions <= 1.3.4 mistakenly report corruption when - * FSE_readNCount() receives a buffer < 4 bytes. - * Fixed by https://github.com/facebook/zstd/pull/1146. - * This can happen when the last set_compressed table present is 2 - * bytes and the bitstream is only one byte. - * In this exceedingly rare case, we will simply emit an uncompressed - * block, since it isn't worth optimizing. - */ - if (lastNCount && (op - lastNCount) < 4) { - /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */ - assert(op - lastNCount == 3); - DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by " - "emitting an uncompressed block."); - return 0; - } - } - - DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart)); - return (size_t)(op - ostart); -} - -MEM_STATIC size_t -ZSTD_compressSequences(seqStore_t* seqStorePtr, - const ZSTD_entropyCTables_t* prevEntropy, - ZSTD_entropyCTables_t* nextEntropy, - const ZSTD_CCtx_params* cctxParams, - void* dst, size_t dstCapacity, - size_t srcSize, - void* entropyWorkspace, size_t entropyWkspSize, - int bmi2) -{ - size_t const cSize = ZSTD_compressSequences_internal( - seqStorePtr, prevEntropy, nextEntropy, cctxParams, - dst, dstCapacity, - entropyWorkspace, entropyWkspSize, bmi2); - if (cSize == 0) return 0; - /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block. - * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block. - */ - if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity)) - return 0; /* block not compressed */ - FORWARD_IF_ERROR(cSize, "ZSTD_compressSequences_internal failed"); - - /* Check compressibility */ - { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy); - if (cSize >= maxCSize) return 0; /* block not compressed */ - } - - return cSize; -} - -/* ZSTD_selectBlockCompressor() : - * Not static, but internal use only (used by long distance matcher) - * assumption : strat is a valid strategy */ -ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode) -{ - static const ZSTD_blockCompressor blockCompressor[3][ZSTD_STRATEGY_MAX+1] = { - { ZSTD_compressBlock_fast /* default for 0 */, - ZSTD_compressBlock_fast, - ZSTD_compressBlock_doubleFast, - ZSTD_compressBlock_greedy, - ZSTD_compressBlock_lazy, - ZSTD_compressBlock_lazy2, - ZSTD_compressBlock_btlazy2, - ZSTD_compressBlock_btopt, - ZSTD_compressBlock_btultra, - ZSTD_compressBlock_btultra2 }, - { ZSTD_compressBlock_fast_extDict /* default for 0 */, - ZSTD_compressBlock_fast_extDict, - ZSTD_compressBlock_doubleFast_extDict, - ZSTD_compressBlock_greedy_extDict, - ZSTD_compressBlock_lazy_extDict, - ZSTD_compressBlock_lazy2_extDict, - ZSTD_compressBlock_btlazy2_extDict, - ZSTD_compressBlock_btopt_extDict, - ZSTD_compressBlock_btultra_extDict, - ZSTD_compressBlock_btultra_extDict }, - { ZSTD_compressBlock_fast_dictMatchState /* default for 0 */, - ZSTD_compressBlock_fast_dictMatchState, - ZSTD_compressBlock_doubleFast_dictMatchState, - ZSTD_compressBlock_greedy_dictMatchState, - ZSTD_compressBlock_lazy_dictMatchState, - ZSTD_compressBlock_lazy2_dictMatchState, - ZSTD_compressBlock_btlazy2_dictMatchState, - ZSTD_compressBlock_btopt_dictMatchState, - ZSTD_compressBlock_btultra_dictMatchState, - ZSTD_compressBlock_btultra_dictMatchState } - }; - ZSTD_blockCompressor selectedCompressor; - ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1); - - assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat)); - selectedCompressor = blockCompressor[(int)dictMode][(int)strat]; - assert(selectedCompressor != NULL); - return selectedCompressor; -} - -static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr, - const BYTE* anchor, size_t lastLLSize) -{ - memcpy(seqStorePtr->lit, anchor, lastLLSize); - seqStorePtr->lit += lastLLSize; -} - -void ZSTD_resetSeqStore(seqStore_t* ssPtr) -{ - ssPtr->lit = ssPtr->litStart; - ssPtr->sequences = ssPtr->sequencesStart; - ssPtr->longLengthID = 0; -} - -typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e; - -static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) -{ - ZSTD_matchState_t* const ms = &zc->blockState.matchState; - DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize); - assert(srcSize <= ZSTD_BLOCKSIZE_MAX); - /* Assert that we have correctly flushed the ctx params into the ms's copy */ - ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams); - if (srcSize < MIN_CBLOCK_SIZE+ZSTDInternalConstants::ZSTD_blockHeaderSize+1) { - ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch); - return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */ - } - ZSTD_resetSeqStore(&(zc->seqStore)); - /* required for optimal parser to read stats from dictionary */ - ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy; - /* tell the optimal parser how we expect to compress literals */ - ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode; - /* a gap between an attached dict and the current window is not safe, - * they must remain adjacent, - * and when that stops being the case, the dict must be unset */ - assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit); - - /* limited update after a very long match */ - { const BYTE* const base = ms->window.base; - const BYTE* const istart = (const BYTE*)src; - const U32 current = (U32)(istart-base); - if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1)); /* ensure no overflow */ - if (current > ms->nextToUpdate + 384) - ms->nextToUpdate = current - MIN(192, (U32)(current - ms->nextToUpdate - 384)); - } - - /* select and store sequences */ - { ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms); - size_t lastLLSize; - { int i; - for (i = 0; i < ZSTD_REP_NUM; ++i) - zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i]; - } - if (zc->externSeqStore.pos < zc->externSeqStore.size) { - assert(!zc->appliedParams.ldmParams.enableLdm); - /* Updates ldmSeqStore.pos */ - lastLLSize = - ZSTD_ldm_blockCompress(&zc->externSeqStore, - ms, &zc->seqStore, - zc->blockState.nextCBlock->rep, - src, srcSize); - assert(zc->externSeqStore.pos <= zc->externSeqStore.size); - } else if (zc->appliedParams.ldmParams.enableLdm) { - rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0}; - - ldmSeqStore.seq = zc->ldmSequences; - ldmSeqStore.capacity = zc->maxNbLdmSequences; - /* Updates ldmSeqStore.size */ - FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore, - &zc->appliedParams.ldmParams, - src, srcSize), ""); - /* Updates ldmSeqStore.pos */ - lastLLSize = - ZSTD_ldm_blockCompress(&ldmSeqStore, - ms, &zc->seqStore, - zc->blockState.nextCBlock->rep, - src, srcSize); - assert(ldmSeqStore.pos == ldmSeqStore.size); - } else { /* not long range mode */ - ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode); - lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize); - } - { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize; - ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize); - } } - return ZSTDbss_compress; -} - -static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc) -{ - const seqStore_t* seqStore = ZSTD_getSeqStore(zc); - const seqDef* seqs = seqStore->sequencesStart; - size_t seqsSize = seqStore->sequences - seqs; - - ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex]; - size_t i; size_t position; int repIdx; - - assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences); - for (i = 0, position = 0; i < seqsSize; ++i) { - outSeqs[i].offset = seqs[i].offset; - outSeqs[i].litLength = seqs[i].litLength; - outSeqs[i].matchLength = seqs[i].matchLength + MINMATCH; - - if (i == seqStore->longLengthPos) { - if (seqStore->longLengthID == 1) { - outSeqs[i].litLength += 0x10000; - } else if (seqStore->longLengthID == 2) { - outSeqs[i].matchLength += 0x10000; - } - } - - if (outSeqs[i].offset <= ZSTD_REP_NUM) { - outSeqs[i].rep = outSeqs[i].offset; - repIdx = (unsigned int)i - outSeqs[i].offset; - - if (outSeqs[i].litLength == 0) { - if (outSeqs[i].offset < 3) { - --repIdx; - } else { - repIdx = (unsigned int)i - 1; - } - ++outSeqs[i].rep; - } - assert(repIdx >= -3); - outSeqs[i].offset = repIdx >= 0 ? outSeqs[repIdx].offset : ZSTDInternalConstants::repStartValue[-repIdx - 1]; - if (outSeqs[i].rep == 4) { - --outSeqs[i].offset; - } - } else { - outSeqs[i].offset -= ZSTD_REP_NUM; - } - - position += outSeqs[i].litLength; - outSeqs[i].matchPos = (unsigned int)position; - position += outSeqs[i].matchLength; - } - zc->seqCollector.seqIndex += seqsSize; -} - -size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, - size_t outSeqsSize, const void* src, size_t srcSize) -{ - const size_t dstCapacity = ZSTD_compressBound(srcSize); - void* dst = ZSTD_malloc(dstCapacity, ZSTDInternalConstants::ZSTD_defaultCMem); - SeqCollector seqCollector; - - RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!"); - - seqCollector.collectSequences = 1; - seqCollector.seqStart = outSeqs; - seqCollector.seqIndex = 0; - seqCollector.maxSequences = outSeqsSize; - zc->seqCollector = seqCollector; - - ZSTD_compress2(zc, dst, dstCapacity, src, srcSize); - ZSTD_free(dst, ZSTDInternalConstants::ZSTD_defaultCMem); - return zc->seqCollector.seqIndex; -} - -/* Returns true if the given block is a RLE block */ -static int ZSTD_isRLE(const BYTE *ip, size_t length) { - size_t i; - if (length < 2) return 1; - for (i = 1; i < length; ++i) { - if (ip[0] != ip[i]) return 0; - } - return 1; -} - -/* Returns true if the given block may be RLE. - * This is just a heuristic based on the compressibility. - * It may return both false positives and false negatives. - */ -static int ZSTD_maybeRLE(seqStore_t const* seqStore) -{ - size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart); - size_t const nbLits = (size_t)(seqStore->lit - seqStore->litStart); - - return nbSeqs < 4 && nbLits < 10; -} - -static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc) -{ - ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock; - zc->blockState.prevCBlock = zc->blockState.nextCBlock; - zc->blockState.nextCBlock = tmp; -} - -static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, U32 frame) -{ - /* This the upper bound for the length of an rle block. - * This isn't the actual upper bound. Finding the real threshold - * needs further investigation. - */ - const U32 rleMaxLength = 25; - size_t cSize; - const BYTE* ip = (const BYTE*)src; - BYTE* op = (BYTE*)dst; - DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)", - (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, - (unsigned)zc->blockState.matchState.nextToUpdate); - - { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); - FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed"); - if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; } - } - - if (zc->seqCollector.collectSequences) { - ZSTD_copyBlockSequences(zc); - return 0; - } - - /* encode sequences and literals */ - cSize = ZSTD_compressSequences(&zc->seqStore, - &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, - &zc->appliedParams, - dst, dstCapacity, - srcSize, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */, - zc->bmi2); - - if (frame && - /* We don't want to emit our first block as a RLE even if it qualifies because - * doing so will cause the decoder (cli only) to throw a "should consume all input error." - * This is only an issue for zstd <= v1.4.3 - */ - !zc->isFirstBlock && - cSize < rleMaxLength && - ZSTD_isRLE(ip, srcSize)) - { - cSize = 1; - op[0] = ip[0]; - } - -out: - if (!ZSTD_isError(cSize) && cSize > 1) { - ZSTD_confirmRepcodesAndEntropyTables(zc); - } - /* We check that dictionaries have offset codes available for the first - * block. After the first block, the offcode table might not have large - * enough codes to represent the offsets in the data. - */ - if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) - zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; - - return cSize; -} - -static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const size_t bss, U32 lastBlock) -{ - DEBUGLOG(6, "Attempting ZSTD_compressSuperBlock()"); - if (bss == ZSTDbss_compress) { - if (/* We don't want to emit our first block as a RLE even if it qualifies because - * doing so will cause the decoder (cli only) to throw a "should consume all input error." - * This is only an issue for zstd <= v1.4.3 - */ - !zc->isFirstBlock && - ZSTD_maybeRLE(&zc->seqStore) && - ZSTD_isRLE((BYTE const*)src, srcSize)) - { - return ZSTD_rleCompressBlock(dst, dstCapacity, *(BYTE const*)src, srcSize, lastBlock); - } - /* Attempt superblock compression. - * - * Note that compressed size of ZSTD_compressSuperBlock() is not bound by the - * standard ZSTD_compressBound(). This is a problem, because even if we have - * space now, taking an extra byte now could cause us to run out of space later - * and violate ZSTD_compressBound(). - * - * Define blockBound(blockSize) = blockSize + ZSTD_blockHeaderSize. - * - * In order to respect ZSTD_compressBound() we must attempt to emit a raw - * uncompressed block in these cases: - * * cSize == 0: Return code for an uncompressed block. - * * cSize == dstSize_tooSmall: We may have expanded beyond blockBound(srcSize). - * ZSTD_noCompressBlock() will return dstSize_tooSmall if we are really out of - * output space. - * * cSize >= blockBound(srcSize): We have expanded the block too much so - * emit an uncompressed block. - */ - { - size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock); - if (cSize != ERROR(dstSize_tooSmall)) { - size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy); - FORWARD_IF_ERROR(cSize, "ZSTD_compressSuperBlock failed"); - if (cSize != 0 && cSize < maxCSize + ZSTDInternalConstants::ZSTD_blockHeaderSize) { - ZSTD_confirmRepcodesAndEntropyTables(zc); - return cSize; - } - } - } - } - - DEBUGLOG(6, "Resorting to ZSTD_noCompressBlock()"); - /* Superblock compression failed, attempt to emit a single no compress block. - * The decoder will be able to stream this block since it is uncompressed. - */ - return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock); -} - -static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - U32 lastBlock) -{ - size_t cSize = 0; - const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize); - DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)", - (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize); - FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed"); - - cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, dst, dstCapacity, src, srcSize, bss, lastBlock); - FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize_body failed"); - - if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) - zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; - - return cSize; -} - -static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms, - ZSTD_cwksp* ws, - ZSTD_CCtx_params const* params, - void const* ip, - void const* iend) -{ - if (ZSTD_window_needOverflowCorrection(ms->window, iend)) { - U32 const maxDist = (U32)1 << params->cParams.windowLog; - U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy); - U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip); - ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30); - ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30); - ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31); - ZSTD_cwksp_mark_tables_dirty(ws); - ZSTD_reduceIndex(ms, params, correction); - ZSTD_cwksp_mark_tables_clean(ws); - if (ms->nextToUpdate < correction) ms->nextToUpdate = 0; - else ms->nextToUpdate -= correction; - /* invalidate dictionaries on overflow correction */ - ms->loadedDictEnd = 0; - ms->dictMatchState = NULL; - } -} - -/*! ZSTD_compress_frameChunk() : -* Compress a chunk of data into one or multiple blocks. -* All blocks will be terminated, all input will be consumed. -* Function will issue an error if there is not enough `dstCapacity` to hold the compressed content. -* Frame is supposed already started (header already produced) -* @return : compressed size, or an error code -*/ -static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - U32 lastFrameChunk) -{ - size_t blockSize = cctx->blockSize; - size_t remaining = srcSize; - const BYTE* ip = (const BYTE*)src; - BYTE* const ostart = (BYTE*)dst; - BYTE* op = ostart; - U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog; - - assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); - - DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); - if (cctx->appliedParams.fParams.checksumFlag && srcSize) - XXH64_update(&cctx->xxhState, src, srcSize); - - while (remaining) { - ZSTD_matchState_t* const ms = &cctx->blockState.matchState; - U32 const lastBlock = lastFrameChunk & (blockSize >= remaining); - - RETURN_ERROR_IF(dstCapacity < ZSTDInternalConstants::ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE, - dstSize_tooSmall, - "not enough space to store compressed block"); - if (remaining < blockSize) blockSize = remaining; - - ZSTD_overflowCorrectIfNeeded( - ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize); - ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState); - - /* Ensure hash/chain table insertion resumes no sooner than lowlimit */ - if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit; - - { size_t cSize; - if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) { - cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock); - FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize failed"); - assert(cSize > 0); - assert(cSize <= blockSize + ZSTDInternalConstants::ZSTD_blockHeaderSize); - } else { - cSize = ZSTD_compressBlock_internal(cctx, - op+ZSTDInternalConstants::ZSTD_blockHeaderSize, dstCapacity-ZSTDInternalConstants::ZSTD_blockHeaderSize, - ip, blockSize, 1 /* frame */); - FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_internal failed"); - - if (cSize == 0) { /* block is not compressible */ - cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); - FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed"); - } else { - U32 const cBlockHeader = cSize == 1 ? - lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) : - lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); - MEM_writeLE24(op, cBlockHeader); - cSize += ZSTDInternalConstants::ZSTD_blockHeaderSize; - } - } - - - ip += blockSize; - assert(remaining >= blockSize); - remaining -= blockSize; - op += cSize; - assert(dstCapacity >= cSize); - dstCapacity -= cSize; - cctx->isFirstBlock = 0; - DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u", - (unsigned)cSize); - } } - - if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending; - return (size_t)(op-ostart); -} - - -static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, - const ZSTD_CCtx_params* params, U64 pledgedSrcSize, U32 dictID) -{ BYTE* const op = (BYTE*)dst; - U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */ - U32 const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */ - U32 const checksumFlag = params->fParams.checksumFlag>0; - U32 const windowSize = (U32)1 << params->cParams.windowLog; - U32 const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize); - BYTE const windowLogByte = (BYTE)((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); - U32 const fcsCode = params->fParams.contentSizeFlag ? - (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */ - BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) ); - size_t pos=0; - - assert(!(params->fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)); - RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall, - "dst buf is too small to fit worst-case frame header size."); - DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u", - !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode); - - if (params->format == ZSTD_f_zstd1) { - MEM_writeLE32(dst, ZSTD_MAGICNUMBER); - pos = 4; - } - op[pos++] = frameHeaderDescriptionByte; - if (!singleSegment) op[pos++] = windowLogByte; - switch(dictIDSizeCode) - { - default: assert(0); /* impossible */ - case 0 : break; - case 1 : op[pos] = (BYTE)(dictID); pos++; break; - case 2 : MEM_writeLE16(op+pos, (U16)dictID); pos+=2; break; - case 3 : MEM_writeLE32(op+pos, dictID); pos+=4; break; - } - switch(fcsCode) - { - default: assert(0); /* impossible */ - case 0 : if (singleSegment) op[pos++] = (BYTE)(pledgedSrcSize); break; - case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break; - case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break; - case 3 : MEM_writeLE64(op+pos, (U64)(pledgedSrcSize)); pos+=8; break; - } - return pos; -} - -/* ZSTD_writeLastEmptyBlock() : - * output an empty Block with end-of-frame mark to complete a frame - * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h)) - * or an error code if `dstCapacity` is too small (stage != ZSTDcs_init, stage_wrong, - "wrong cctx stage"); - RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm, - parameter_unsupported, - "incompatible with ldm"); - cctx->externSeqStore.seq = seq; - cctx->externSeqStore.size = nbSeq; - cctx->externSeqStore.capacity = nbSeq; - cctx->externSeqStore.pos = 0; - return 0; -} - - -static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - U32 frame, U32 lastFrameChunk) -{ - ZSTD_matchState_t* const ms = &cctx->blockState.matchState; - size_t fhSize = 0; - - DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u", - cctx->stage, (unsigned)srcSize); - RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong, - "missing init (ZSTD_compressBegin)"); - - if (frame && (cctx->stage==ZSTDcs_init)) { - fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, - cctx->pledgedSrcSizePlusOne-1, cctx->dictID); - FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed"); - assert(fhSize <= dstCapacity); - dstCapacity -= fhSize; - dst = (char*)dst + fhSize; - cctx->stage = ZSTDcs_ongoing; - } - - if (!srcSize) return fhSize; /* do not generate an empty block if no input */ - - if (!ZSTD_window_update(&ms->window, src, srcSize)) { - ms->nextToUpdate = ms->window.dictLimit; - } - if (cctx->appliedParams.ldmParams.enableLdm) { - ZSTD_window_update(&cctx->ldmState.window, src, srcSize); - } - - if (!frame) { - /* overflow check and correction for block mode */ - ZSTD_overflowCorrectIfNeeded( - ms, &cctx->workspace, &cctx->appliedParams, - src, (BYTE const*)src + srcSize); - } - - DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize); - { size_t const cSize = frame ? - ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) : - ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 /* frame */); - FORWARD_IF_ERROR(cSize, "%s", frame ? "ZSTD_compress_frameChunk failed" : "ZSTD_compressBlock_internal failed"); - cctx->consumedSrcSize += srcSize; - cctx->producedCSize += (cSize + fhSize); - assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); - if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */ - ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1); - RETURN_ERROR_IF( - cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne, - srcSize_wrong, - "error : pledgedSrcSize = %u, while realSrcSize >= %u", - (unsigned)cctx->pledgedSrcSizePlusOne-1, - (unsigned)cctx->consumedSrcSize); - } - return cSize + fhSize; - } -} - -size_t ZSTD_compressContinue (ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize) -{ - DEBUGLOG(5, "ZSTD_compressContinue (srcSize=%u)", (unsigned)srcSize); - return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 0 /* last chunk */); -} - - -size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx) -{ - ZSTD_compressionParameters const cParams = cctx->appliedParams.cParams; - assert(!ZSTD_checkCParams(cParams)); - return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog); -} - -size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) -{ - DEBUGLOG(5, "ZSTD_compressBlock: srcSize = %u", (unsigned)srcSize); - { size_t const blockSizeMax = ZSTD_getBlockSize(cctx); - RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong, "input is larger than a block"); } - - return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */); -} - -/*! ZSTD_loadDictionaryContent() : - * @return : 0, or an error code - */ -static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, - ldmState_t* ls, - ZSTD_cwksp* ws, - ZSTD_CCtx_params const* params, - const void* src, size_t srcSize, - ZSTD_dictTableLoadMethod_e dtlm) -{ - const BYTE* ip = (const BYTE*) src; - const BYTE* const iend = ip + srcSize; - - ZSTD_window_update(&ms->window, src, srcSize); - ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base); - - if (params->ldmParams.enableLdm && ls != NULL) { - ZSTD_window_update(&ls->window, src, srcSize); - ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base); - } - - /* Assert that we the ms params match the params we're being given */ - ZSTD_assertEqualCParams(params->cParams, ms->cParams); - - if (srcSize <= HASH_READ_SIZE) return 0; - - while (iend - ip > HASH_READ_SIZE) { - size_t const remaining = (size_t)(iend - ip); - size_t const chunk = MIN(remaining, ZSTD_CHUNKSIZE_MAX); - const BYTE* const ichunk = ip + chunk; - - ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk); - - if (params->ldmParams.enableLdm && ls != NULL) - ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, ¶ms->ldmParams); - - switch(params->cParams.strategy) - { - case ZSTD_fast: - ZSTD_fillHashTable(ms, ichunk, dtlm); - break; - case ZSTD_dfast: - ZSTD_fillDoubleHashTable(ms, ichunk, dtlm); - break; - - case ZSTD_greedy: - case ZSTD_lazy: - case ZSTD_lazy2: - if (chunk >= HASH_READ_SIZE) - ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE); - break; - - case ZSTD_btlazy2: /* we want the dictionary table fully sorted */ - case ZSTD_btopt: - case ZSTD_btultra: - case ZSTD_btultra2: - if (chunk >= HASH_READ_SIZE) - ZSTD_updateTree(ms, ichunk-HASH_READ_SIZE, ichunk); - break; - - default: - assert(0); /* not possible : not a valid strategy id */ - } - - ip = ichunk; - } - - ms->nextToUpdate = (U32)(iend - ms->window.base); - return 0; -} - - -/* Dictionaries that assign zero probability to symbols that show up causes problems - when FSE encoding. Refuse dictionaries that assign zero probability to symbols - that we may encounter during compression. - NOTE: This behavior is not standard and could be improved in the future. */ -static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) { - U32 s; - RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted, "dict fse tables don't have all symbols"); - for (s = 0; s <= maxSymbolValue; ++s) { - RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted, "dict fse tables don't have all symbols"); - } - return 0; -} - -size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, - short* offcodeNCount, unsigned* offcodeMaxValue, - const void* const dict, size_t dictSize) -{ - const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */ - const BYTE* const dictEnd = dictPtr + dictSize; - dictPtr += 8; - bs->entropy.huf.repeatMode = HUF_repeat_check; - - { unsigned maxSymbolValue = 255; - unsigned hasZeroWeights = 1; - size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr, - dictEnd-dictPtr, &hasZeroWeights); - - /* We only set the loaded table as valid if it contains all non-zero - * weights. Otherwise, we set it to check */ - if (!hasZeroWeights) - bs->entropy.huf.repeatMode = HUF_repeat_valid; - - RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, ""); - RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted, ""); - dictPtr += hufHeaderSize; - } - - { unsigned offcodeLog; - size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); - RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, ""); - RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, ""); - /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ - /* fill all offset symbols to avoid garbage at end of table */ - RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( - bs->entropy.fse.offcodeCTable, - offcodeNCount, MaxOff, offcodeLog, - workspace, HUF_WORKSPACE_SIZE)), - dictionary_corrupted, ""); - dictPtr += offcodeHeaderSize; - } - - { short matchlengthNCount[MaxML+1]; - unsigned matchlengthMaxValue = MaxML, matchlengthLog; - size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); - RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, ""); - RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, ""); - /* Every match length code must have non-zero probability */ - FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML), ""); - RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( - bs->entropy.fse.matchlengthCTable, - matchlengthNCount, matchlengthMaxValue, matchlengthLog, - workspace, HUF_WORKSPACE_SIZE)), - dictionary_corrupted, ""); - dictPtr += matchlengthHeaderSize; - } - - { short litlengthNCount[MaxLL+1]; - unsigned litlengthMaxValue = MaxLL, litlengthLog; - size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); - RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, ""); - RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, ""); - /* Every literal length code must have non-zero probability */ - FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL), ""); - RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( - bs->entropy.fse.litlengthCTable, - litlengthNCount, litlengthMaxValue, litlengthLog, - workspace, HUF_WORKSPACE_SIZE)), - dictionary_corrupted, ""); - dictPtr += litlengthHeaderSize; - } - - RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, ""); - bs->rep[0] = MEM_readLE32(dictPtr+0); - bs->rep[1] = MEM_readLE32(dictPtr+4); - bs->rep[2] = MEM_readLE32(dictPtr+8); - dictPtr += 12; - - return dictPtr - (const BYTE*)dict; -} - -/* Dictionary format : - * See : - * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format - */ -/*! ZSTD_loadZstdDictionary() : - * @return : dictID, or an error code - * assumptions : magic number supposed already checked - * dictSize supposed >= 8 - */ -static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, - ZSTD_matchState_t* ms, - ZSTD_cwksp* ws, - ZSTD_CCtx_params const* params, - const void* dict, size_t dictSize, - ZSTD_dictTableLoadMethod_e dtlm, - void* workspace) -{ - const BYTE* dictPtr = (const BYTE*)dict; - const BYTE* const dictEnd = dictPtr + dictSize; - short offcodeNCount[MaxOff+1]; - unsigned offcodeMaxValue = MaxOff; - size_t dictID; - size_t eSize; - - ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<= 8); - assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); - - dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ ); - eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize); - FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed"); - dictPtr += eSize; - - { size_t const dictContentSize = (size_t)(dictEnd - dictPtr); - U32 offcodeMax = MaxOff; - if (dictContentSize <= ((U32)-1) - 128 KB) { - U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */ - offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */ - } - /* All offset values <= dictContentSize + 128 KB must be representable */ - FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)), ""); - /* All repCodes must be <= dictContentSize and != 0*/ - { U32 u; - for (u=0; u<3; u++) { - RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, ""); - RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, ""); - } } - - bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid; - bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid; - bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid; - FORWARD_IF_ERROR(ZSTD_loadDictionaryContent( - ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), ""); - return dictID; - } -} - -/** ZSTD_compress_insertDictionary() : -* @return : dictID, or an error code */ -static size_t -ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, - ZSTD_matchState_t* ms, - ldmState_t* ls, - ZSTD_cwksp* ws, - const ZSTD_CCtx_params* params, - const void* dict, size_t dictSize, - ZSTD_dictContentType_e dictContentType, - ZSTD_dictTableLoadMethod_e dtlm, - void* workspace) -{ - DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize); - if ((dict==NULL) || (dictSize<8)) { - RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, ""); - return 0; - } - - ZSTD_reset_compressedBlockState(bs); - - /* dict restricted modes */ - if (dictContentType == ZSTD_dct_rawContent) - return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm); - - if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) { - if (dictContentType == ZSTD_dct_auto) { - DEBUGLOG(4, "raw content dictionary detected"); - return ZSTD_loadDictionaryContent( - ms, ls, ws, params, dict, dictSize, dtlm); - } - RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, ""); - assert(0); /* impossible */ - } - - /* dict as full zstd dictionary */ - return ZSTD_loadZstdDictionary( - bs, ms, ws, params, dict, dictSize, dtlm, workspace); -} - -#define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB) -#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6) - -/*! ZSTD_compressBegin_internal() : - * @return : 0, or an error code */ -static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, - const void* dict, size_t dictSize, - ZSTD_dictContentType_e dictContentType, - ZSTD_dictTableLoadMethod_e dtlm, - const ZSTD_CDict* cdict, - const ZSTD_CCtx_params* params, U64 pledgedSrcSize, - ZSTD_buffered_policy_e zbuff) -{ - DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog); - /* params are supposed to be fully validated at this point */ - assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); - assert(!((dict) && (cdict))); /* either dict or cdict, not both */ - if ( (cdict) - && (cdict->dictContentSize > 0) - && ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF - || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER - || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN - || cdict->compressionLevel == 0) - && (params->attachDictPref != ZSTD_dictForceLoad) ) { - return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff); - } - - FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, *params, pledgedSrcSize, - ZSTDcrp_makeClean, zbuff) , ""); - { size_t const dictID = cdict ? - ZSTD_compress_insertDictionary( - cctx->blockState.prevCBlock, &cctx->blockState.matchState, - &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent, - cdict->dictContentSize, dictContentType, dtlm, - cctx->entropyWorkspace) - : ZSTD_compress_insertDictionary( - cctx->blockState.prevCBlock, &cctx->blockState.matchState, - &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize, - dictContentType, dtlm, cctx->entropyWorkspace); - FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed"); - assert(dictID <= UINT_MAX); - cctx->dictID = (U32)dictID; - } - return 0; -} - -size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx, - const void* dict, size_t dictSize, - ZSTD_dictContentType_e dictContentType, - ZSTD_dictTableLoadMethod_e dtlm, - const ZSTD_CDict* cdict, - const ZSTD_CCtx_params* params, - unsigned long long pledgedSrcSize) -{ - DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog); - /* compression parameters verification and optimization */ - FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , ""); - return ZSTD_compressBegin_internal(cctx, - dict, dictSize, dictContentType, dtlm, - cdict, - params, pledgedSrcSize, - ZSTDb_not_buffered); -} - -/*! ZSTD_compressBegin_advanced() : -* @return : 0, or an error code */ -size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, - const void* dict, size_t dictSize, - ZSTD_parameters params, unsigned long long pledgedSrcSize) -{ - ZSTD_CCtx_params const cctxParams = - ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); - return ZSTD_compressBegin_advanced_internal(cctx, - dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, - NULL /*cdict*/, - &cctxParams, pledgedSrcSize); -} - -size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) -{ - ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); - ZSTD_CCtx_params const cctxParams = - ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); - DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize); - return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL, - &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered); -} - -size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel) -{ - return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel); -} - - -/*! ZSTD_writeEpilogue() : -* Ends a frame. -* @return : nb of bytes written into dst (or an error code) */ -static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) -{ - BYTE* const ostart = (BYTE*)dst; - BYTE* op = ostart; - size_t fhSize = 0; - - DEBUGLOG(4, "ZSTD_writeEpilogue"); - RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing"); - - /* special case : empty frame */ - if (cctx->stage == ZSTDcs_init) { - fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0); - FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed"); - dstCapacity -= fhSize; - op += fhSize; - cctx->stage = ZSTDcs_ongoing; - } - - if (cctx->stage != ZSTDcs_ending) { - /* write one last empty block, make it the "last" block */ - U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0; - RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for epilogue"); - MEM_writeLE32(op, cBlockHeader24); - op += ZSTDInternalConstants::ZSTD_blockHeaderSize; - dstCapacity -= ZSTDInternalConstants::ZSTD_blockHeaderSize; - } - - if (cctx->appliedParams.fParams.checksumFlag) { - U32 const checksum = (U32) XXH64_digest(&cctx->xxhState); - RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum"); - DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum); - MEM_writeLE32(op, checksum); - op += 4; - } - - cctx->stage = ZSTDcs_created; /* return to "created but no init" status */ - return op-ostart; -} - -size_t ZSTD_compressEnd (ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize) -{ - size_t endResult; - size_t const cSize = ZSTD_compressContinue_internal(cctx, - dst, dstCapacity, src, srcSize, - 1 /* frame mode */, 1 /* last chunk */); - FORWARD_IF_ERROR(cSize, "ZSTD_compressContinue_internal failed"); - endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize); - FORWARD_IF_ERROR(endResult, "ZSTD_writeEpilogue failed"); - assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0)); - if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */ - ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1); - DEBUGLOG(4, "end of frame : controlling src size"); - RETURN_ERROR_IF( - cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1, - srcSize_wrong, - "error : pledgedSrcSize = %u, while realSrcSize = %u", - (unsigned)cctx->pledgedSrcSizePlusOne-1, - (unsigned)cctx->consumedSrcSize); - } - return cSize + endResult; -} - - -static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize, - const ZSTD_parameters* params) -{ - ZSTD_CCtx_params const cctxParams = - ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params); - DEBUGLOG(4, "ZSTD_compress_internal"); - return ZSTD_compress_advanced_internal(cctx, - dst, dstCapacity, - src, srcSize, - dict, dictSize, - &cctxParams); -} - -size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize, - ZSTD_parameters params) -{ - DEBUGLOG(4, "ZSTD_compress_advanced"); - FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), ""); - return ZSTD_compress_internal(cctx, - dst, dstCapacity, - src, srcSize, - dict, dictSize, - ¶ms); -} - -/* Internal */ -size_t ZSTD_compress_advanced_internal( - ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize, - const ZSTD_CCtx_params* params) -{ - DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize); - FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, - dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL, - params, srcSize, ZSTDb_not_buffered) , ""); - return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); -} - -size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict, size_t dictSize, - int compressionLevel) -{ - ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0); - ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); - DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize); - assert(params.fParams.contentSizeFlag == 1); - return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams); -} - -size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel) -{ - DEBUGLOG(4, "ZSTD_compressCCtx (srcSize=%u)", (unsigned)srcSize); - assert(cctx != NULL); - return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel); -} - -size_t ZSTD_compress(void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel) -{ - size_t result; - ZSTD_CCtx ctxBody; - ZSTD_initCCtx(&ctxBody, ZSTDInternalConstants::ZSTD_defaultCMem); - result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel); - ZSTD_freeCCtxContent(&ctxBody); /* can't free ctxBody itself, as it's on stack; free only heap content */ - return result; -} - - -/* ===== Dictionary API ===== */ - -/*! ZSTD_estimateCDictSize_advanced() : - * Estimate amount of memory that will be needed to create a dictionary with following arguments */ -size_t ZSTD_estimateCDictSize_advanced( - size_t dictSize, ZSTD_compressionParameters cParams, - ZSTD_dictLoadMethod_e dictLoadMethod) -{ - DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict)); - return ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) - + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) - + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0) - + (dictLoadMethod == ZSTD_dlm_byRef ? 0 - : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *)))); -} - -size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel) -{ - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); - return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); -} - -size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict) -{ - if (cdict==NULL) return 0; /* support sizeof on NULL */ - DEBUGLOG(5, "sizeof(*cdict) : %u", (unsigned)sizeof(*cdict)); - /* cdict may be in the workspace */ - return (cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict)) - + ZSTD_cwksp_sizeof(&cdict->workspace); -} - -static size_t ZSTD_initCDict_internal( - ZSTD_CDict* cdict, - const void* dictBuffer, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams) -{ - DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType); - assert(!ZSTD_checkCParams(cParams)); - cdict->matchState.cParams = cParams; - if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) { - cdict->dictContent = dictBuffer; - } else { - void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*))); - RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!"); - cdict->dictContent = internalBuffer; - memcpy(internalBuffer, dictBuffer, dictSize); - } - cdict->dictContentSize = dictSize; - - cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE); - - - /* Reset the state to no dictionary */ - ZSTD_reset_compressedBlockState(&cdict->cBlockState); - FORWARD_IF_ERROR(ZSTD_reset_matchState( - &cdict->matchState, - &cdict->workspace, - &cParams, - ZSTDcrp_makeClean, - ZSTDirp_reset, - ZSTD_resetTarget_CDict), ""); - /* (Maybe) load the dictionary - * Skips loading the dictionary if it is < 8 bytes. - */ - { ZSTD_CCtx_params params; - memset(¶ms, 0, sizeof(params)); - params.compressionLevel = ZSTD_CLEVEL_DEFAULT; - params.fParams.contentSizeFlag = 1; - params.cParams = cParams; - { size_t const dictID = ZSTD_compress_insertDictionary( - &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace, - ¶ms, cdict->dictContent, cdict->dictContentSize, - dictContentType, ZSTD_dtlm_full, cdict->entropyWorkspace); - FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed"); - assert(dictID <= (size_t)(U32)-1); - cdict->dictID = (U32)dictID; - } - } - - return 0; -} - -ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams, ZSTD_customMem customMem) -{ - DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (unsigned)dictContentType); - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; - - { size_t const workspaceSize = - ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) + - ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) + - ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0) + - (dictLoadMethod == ZSTD_dlm_byRef ? 0 - : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*)))); - void* const workspace = ZSTD_malloc(workspaceSize, customMem); - ZSTD_cwksp ws; - ZSTD_CDict* cdict; - - if (!workspace) { - ZSTD_free(workspace, customMem); - return NULL; - } - - ZSTD_cwksp_init(&ws, workspace, workspaceSize); - - cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict)); - assert(cdict != NULL); - ZSTD_cwksp_move(&cdict->workspace, &ws); - cdict->customMem = customMem; - cdict->compressionLevel = 0; /* signals advanced API usage */ - - if (ZSTD_isError( ZSTD_initCDict_internal(cdict, - dictBuffer, dictSize, - dictLoadMethod, dictContentType, - cParams) )) { - ZSTD_freeCDict(cdict); - return NULL; - } - - return cdict; - } -} - -ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel) -{ - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); - ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dict, dictSize, - ZSTD_dlm_byCopy, ZSTD_dct_auto, - cParams, ZSTDInternalConstants::ZSTD_defaultCMem); - if (cdict) - cdict->compressionLevel = compressionLevel == 0 ? ZSTD_CLEVEL_DEFAULT : compressionLevel; - return cdict; -} - -ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel) -{ - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); - return ZSTD_createCDict_advanced(dict, dictSize, - ZSTD_dlm_byRef, ZSTD_dct_auto, - cParams, ZSTDInternalConstants::ZSTD_defaultCMem); -} - -size_t ZSTD_freeCDict(ZSTD_CDict* cdict) -{ - if (cdict==NULL) return 0; /* support free on NULL */ - { ZSTD_customMem const cMem = cdict->customMem; - int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict); - ZSTD_cwksp_free(&cdict->workspace, cMem); - if (!cdictInWorkspace) { - ZSTD_free(cdict, cMem); - } - return 0; - } -} - -/*! ZSTD_initStaticCDict_advanced() : - * Generate a digested dictionary in provided memory area. - * workspace: The memory area to emplace the dictionary into. - * Provided pointer must 8-bytes aligned. - * It must outlive dictionary usage. - * workspaceSize: Use ZSTD_estimateCDictSize() - * to determine how large workspace must be. - * cParams : use ZSTD_getCParams() to transform a compression level - * into its relevants cParams. - * @return : pointer to ZSTD_CDict*, or NULL if error (size too small) - * Note : there is no corresponding "free" function. - * Since workspace was allocated externally, it must be freed externally. - */ -const ZSTD_CDict* ZSTD_initStaticCDict( - void* workspace, size_t workspaceSize, - const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams) -{ - size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0); - size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) - + (dictLoadMethod == ZSTD_dlm_byRef ? 0 - : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*)))) - + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) - + matchStateSize; - ZSTD_CDict* cdict; - - if ((size_t)workspace & 7) return NULL; /* 8-aligned */ - - { - ZSTD_cwksp ws; - ZSTD_cwksp_init(&ws, workspace, workspaceSize); - cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict)); - if (cdict == NULL) return NULL; - ZSTD_cwksp_move(&cdict->workspace, &ws); - } - - DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u", - (unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize)); - if (workspaceSize < neededSize) return NULL; - - if (ZSTD_isError( ZSTD_initCDict_internal(cdict, - dict, dictSize, - dictLoadMethod, dictContentType, - cParams) )) - return NULL; - - return cdict; -} - -ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) -{ - assert(cdict != NULL); - return cdict->matchState.cParams; -} - -/* ZSTD_compressBegin_usingCDict_advanced() : - * cdict must be != NULL */ -size_t ZSTD_compressBegin_usingCDict_advanced( - ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, - ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize) -{ - DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced"); - RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!"); - { ZSTD_CCtx_params params = cctx->requestedParams; - params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF - || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER - || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN - || cdict->compressionLevel == 0 ) - && (params.attachDictPref != ZSTD_dictForceLoad) ? - ZSTD_getCParamsFromCDict(cdict) - : ZSTD_getCParams(cdict->compressionLevel, - pledgedSrcSize, - cdict->dictContentSize); - /* Increase window log to fit the entire dictionary and source if the - * source size is known. Limit the increase to 19, which is the - * window log for compression level 1 with the largest source size. - */ - if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) { - U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19); - U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1; - params.cParams.windowLog = MAX(params.cParams.windowLog, limitedSrcLog); - } - params.fParams = fParams; - return ZSTD_compressBegin_internal(cctx, - NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, - cdict, - ¶ms, pledgedSrcSize, - ZSTDb_not_buffered); - } -} - -/* ZSTD_compressBegin_usingCDict() : - * pledgedSrcSize=0 means "unknown" - * if pledgedSrcSize>0, it will enable contentSizeFlag */ -size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) -{ - ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; - DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag); - return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN); -} - -size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict, ZSTD_frameParameters fParams) -{ - FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize), ""); /* will check if cdict != NULL */ - return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); -} - -/*! ZSTD_compress_usingCDict() : - * Compression using a digested Dictionary. - * Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times. - * Note that compression parameters are decided at CDict creation time - * while frame parameters are hardcoded */ -size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict) -{ - ZSTD_frameParameters const fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; - return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, fParams); -} - - - -/* ****************************************************************** -* Streaming -********************************************************************/ - -ZSTD_CStream* ZSTD_createCStream(void) -{ - DEBUGLOG(3, "ZSTD_createCStream"); - return ZSTD_createCStream_advanced(ZSTDInternalConstants::ZSTD_defaultCMem); -} - -ZSTD_CStream* ZSTD_initStaticCStream(void *workspace, size_t workspaceSize) -{ - return ZSTD_initStaticCCtx(workspace, workspaceSize); -} - -ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem) -{ /* CStream and CCtx are now same object */ - return ZSTD_createCCtx_advanced(customMem); -} - -size_t ZSTD_freeCStream(ZSTD_CStream* zcs) -{ - return ZSTD_freeCCtx(zcs); /* same object */ -} - - - -/*====== Initialization ======*/ - -size_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX; } - -size_t ZSTD_CStreamOutSize(void) -{ - return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTDInternalConstants::ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ; -} - -static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx, - const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType, - const ZSTD_CDict* const cdict, - ZSTD_CCtx_params params, unsigned long long const pledgedSrcSize) -{ - DEBUGLOG(4, "ZSTD_resetCStream_internal"); - /* Finalize the compression parameters */ - params.cParams = ZSTD_getCParamsFromCCtxParams(¶ms, pledgedSrcSize, dictSize); - /* params are supposed to be fully validated at this point */ - assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); - assert(!((dict) && (cdict))); /* either dict or cdict, not both */ - - FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, - dict, dictSize, dictContentType, ZSTD_dtlm_fast, - cdict, - ¶ms, pledgedSrcSize, - ZSTDb_buffered) , ""); - - cctx->inToCompress = 0; - cctx->inBuffPos = 0; - cctx->inBuffTarget = cctx->blockSize - + (cctx->blockSize == pledgedSrcSize); /* for small input: avoid automatic flush on reaching end of block, since it would require to add a 3-bytes null block to end frame */ - cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0; - cctx->streamStage = zcss_load; - cctx->frameEnded = 0; - return 0; /* ready to go */ -} - -/* ZSTD_resetCStream(): - * pledgedSrcSize == 0 means "unknown" */ -size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss) -{ - /* temporary : 0 interpreted as "unknown" during transition period. - * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. - * 0 will be interpreted as "empty" in the future. - */ - U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; - DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); - return 0; -} - -/*! ZSTD_initCStream_internal() : - * Note : for lib/compress only. Used by zstdmt_compress.c. - * Assumption 1 : params are valid - * Assumption 2 : either dict, or cdict, is defined, not both */ -size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs, - const void* dict, size_t dictSize, const ZSTD_CDict* cdict, - const ZSTD_CCtx_params* params, - unsigned long long pledgedSrcSize) -{ - DEBUGLOG(4, "ZSTD_initCStream_internal"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); - assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams))); - zcs->requestedParams = *params; - assert(!((dict) && (cdict))); /* either dict or cdict, not both */ - if (dict) { - FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); - } else { - /* Dictionary is cleared if !cdict */ - FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , ""); - } - return 0; -} - -/* ZSTD_initCStream_usingCDict_advanced() : - * same as ZSTD_initCStream_usingCDict(), with control over frame parameters */ -size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, - const ZSTD_CDict* cdict, - ZSTD_frameParameters fParams, - unsigned long long pledgedSrcSize) -{ - DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); - zcs->requestedParams.fParams = fParams; - FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , ""); - return 0; -} - -/* note : cdict must outlive compression session */ -size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict) -{ - DEBUGLOG(4, "ZSTD_initCStream_usingCDict"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , ""); - return 0; -} - - -/* ZSTD_initCStream_advanced() : - * pledgedSrcSize must be exact. - * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. - * dict is loaded with default parameters ZSTD_dct_auto and ZSTD_dlm_byCopy. */ -size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, - const void* dict, size_t dictSize, - ZSTD_parameters params, unsigned long long pss) -{ - /* for compatibility with older programs relying on this behavior. - * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN. - * This line will be removed in the future. - */ - U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; - DEBUGLOG(4, "ZSTD_initCStream_advanced"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); - FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); - zcs->requestedParams = ZSTD_assignParamsToCCtxParams(&zcs->requestedParams, ¶ms); - FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); - return 0; -} - -size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel) -{ - DEBUGLOG(4, "ZSTD_initCStream_usingDict"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , ""); - return 0; -} - -size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss) -{ - /* temporary : 0 interpreted as "unknown" during transition period. - * Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN. - * 0 will be interpreted as "empty" in the future. - */ - U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss; - DEBUGLOG(4, "ZSTD_initCStream_srcSize"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , ""); - return 0; -} - -size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel) -{ - DEBUGLOG(4, "ZSTD_initCStream"); - FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , ""); - FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , ""); - return 0; -} - -/*====== Compression ======*/ - -static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx) -{ - size_t hintInSize = cctx->inBuffTarget - cctx->inBuffPos; - if (hintInSize==0) hintInSize = cctx->blockSize; - return hintInSize; -} - -/** ZSTD_compressStream_generic(): - * internal function for all *compressStream*() variants - * non-static, because can be called from zstdmt_compress.c - * @return : hint size for next input */ -static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, - ZSTD_outBuffer* output, - ZSTD_inBuffer* input, - ZSTD_EndDirective const flushMode) -{ - const char* const istart = (const char*)input->src; - const char* const iend = input->size != 0 ? istart + input->size : istart; - const char* ip = input->pos != 0 ? istart + input->pos : istart; - char* const ostart = (char*)output->dst; - char* const oend = output->size != 0 ? ostart + output->size : ostart; - char* op = output->pos != 0 ? ostart + output->pos : ostart; - U32 someMoreWork = 1; - - /* check expectations */ - DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (unsigned)flushMode); - assert(zcs->inBuff != NULL); - assert(zcs->inBuffSize > 0); - assert(zcs->outBuff != NULL); - assert(zcs->outBuffSize > 0); - assert(output->pos <= output->size); - assert(input->pos <= input->size); - - while (someMoreWork) { - switch(zcs->streamStage) - { - case zcss_init: - RETURN_ERROR(init_missing, "call ZSTD_initCStream() first!"); - - case zcss_load: - if ( (flushMode == ZSTD_e_end) - && ((size_t)(oend-op) >= ZSTD_compressBound(iend-ip)) /* enough dstCapacity */ - && (zcs->inBuffPos == 0) ) { - /* shortcut to compression pass directly into output buffer */ - size_t const cSize = ZSTD_compressEnd(zcs, - op, oend-op, ip, iend-ip); - DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize); - FORWARD_IF_ERROR(cSize, "ZSTD_compressEnd failed"); - ip = iend; - op += cSize; - zcs->frameEnded = 1; - ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - someMoreWork = 0; break; - } - /* complete loading into inBuffer */ - { size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; - size_t const loaded = ZSTD_limitCopy( - zcs->inBuff + zcs->inBuffPos, toLoad, - ip, iend-ip); - zcs->inBuffPos += loaded; - if (loaded != 0) - ip += loaded; - if ( (flushMode == ZSTD_e_continue) - && (zcs->inBuffPos < zcs->inBuffTarget) ) { - /* not enough input to fill full block : stop here */ - someMoreWork = 0; break; - } - if ( (flushMode == ZSTD_e_flush) - && (zcs->inBuffPos == zcs->inToCompress) ) { - /* empty */ - someMoreWork = 0; break; - } - } - /* compress current block (note : this stage cannot be stopped in the middle) */ - DEBUGLOG(5, "stream compression stage (flushMode==%u)", flushMode); - { void* cDst; - size_t cSize; - size_t const iSize = zcs->inBuffPos - zcs->inToCompress; - size_t oSize = oend-op; - unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend); - if (oSize >= ZSTD_compressBound(iSize)) - cDst = op; /* compress into output buffer, to skip flush stage */ - else - cDst = zcs->outBuff, oSize = zcs->outBuffSize; - cSize = lastBlock ? - ZSTD_compressEnd(zcs, cDst, oSize, - zcs->inBuff + zcs->inToCompress, iSize) : - ZSTD_compressContinue(zcs, cDst, oSize, - zcs->inBuff + zcs->inToCompress, iSize); - FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); - zcs->frameEnded = lastBlock; - /* prepare next block */ - zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; - if (zcs->inBuffTarget > zcs->inBuffSize) - zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; - DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u", - (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize); - if (!lastBlock) - assert(zcs->inBuffTarget <= zcs->inBuffSize); - zcs->inToCompress = zcs->inBuffPos; - if (cDst == op) { /* no need to flush */ - op += cSize; - if (zcs->frameEnded) { - DEBUGLOG(5, "Frame completed directly in outBuffer"); - someMoreWork = 0; - ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - } - break; - } - zcs->outBuffContentSize = cSize; - zcs->outBuffFlushedSize = 0; - zcs->streamStage = zcss_flush; /* pass-through to flush stage */ - } - /* fall-through */ - case zcss_flush: - DEBUGLOG(5, "flush stage"); - { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; - size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op), - zcs->outBuff + zcs->outBuffFlushedSize, toFlush); - DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u", - (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed); - if (flushed) - op += flushed; - zcs->outBuffFlushedSize += flushed; - if (toFlush!=flushed) { - /* flush not fully completed, presumably because dst is too small */ - assert(op==oend); - someMoreWork = 0; - break; - } - zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0; - if (zcs->frameEnded) { - DEBUGLOG(5, "Frame completed on flush"); - someMoreWork = 0; - ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - break; - } - zcs->streamStage = zcss_load; - break; - } - - default: /* impossible */ - assert(0); - } - } - - input->pos = ip - istart; - output->pos = op - ostart; - if (zcs->frameEnded) return 0; - return ZSTD_nextInputSizeHint(zcs); -} - -static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx) -{ -#ifdef ZSTD_MULTITHREAD - if (cctx->appliedParams.nbWorkers >= 1) { - assert(cctx->mtctx != NULL); - return ZSTDMT_nextInputSizeHint(cctx->mtctx); - } -#endif - return ZSTD_nextInputSizeHint(cctx); - -} - -size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input) -{ - FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , ""); - return ZSTD_nextInputSizeHint_MTorST(zcs); -} - - -size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, - ZSTD_outBuffer* output, - ZSTD_inBuffer* input, - ZSTD_EndDirective endOp) -{ - DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp); - /* check conditions */ - RETURN_ERROR_IF(output->pos > output->size, GENERIC, "invalid buffer"); - RETURN_ERROR_IF(input->pos > input->size, GENERIC, "invalid buffer"); - assert(cctx!=NULL); - - /* transparent initialization stage */ - if (cctx->streamStage == zcss_init) { - ZSTD_CCtx_params params = cctx->requestedParams; - ZSTD_prefixDict const prefixDict = cctx->prefixDict; - FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */ - memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ - assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ - DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage"); - if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */ - params.cParams = ZSTD_getCParamsFromCCtxParams( - &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/); - - -#ifdef ZSTD_MULTITHREAD - if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) { - params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */ - } - if (params.nbWorkers > 0) { - /* mt context creation */ - if (cctx->mtctx == NULL) { - DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u", - params.nbWorkers); - cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem); - RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!"); - } - /* mt compression */ - DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); - FORWARD_IF_ERROR( ZSTDMT_initCStream_internal( - cctx->mtctx, - prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, - cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , ""); - cctx->streamStage = zcss_load; - cctx->appliedParams.nbWorkers = params.nbWorkers; - } else -#endif - { FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx, - prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, - cctx->cdict, - params, cctx->pledgedSrcSizePlusOne-1) , ""); - assert(cctx->streamStage == zcss_load); - assert(cctx->appliedParams.nbWorkers == 0); - } } - /* end of transparent initialization stage */ - - /* compression stage */ -#ifdef ZSTD_MULTITHREAD - if (cctx->appliedParams.nbWorkers > 0) { - int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end); - size_t flushMin; - assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */); - if (cctx->cParamsChanged) { - ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams); - cctx->cParamsChanged = 0; - } - do { - flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp); - if ( ZSTD_isError(flushMin) - || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */ - ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); - } - FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed"); - } while (forceMaxProgress && flushMin != 0 && output->pos < output->size); - DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic"); - /* Either we don't require maximum forward progress, we've finished the - * flush, or we are out of output space. - */ - assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size); - return flushMin; - } -#endif - FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , ""); - DEBUGLOG(5, "completed ZSTD_compressStream2"); - return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */ -} - -size_t ZSTD_compressStream2_simpleArgs ( - ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, size_t* dstPos, - const void* src, size_t srcSize, size_t* srcPos, - ZSTD_EndDirective endOp) -{ - ZSTD_outBuffer output = { dst, dstCapacity, *dstPos }; - ZSTD_inBuffer input = { src, srcSize, *srcPos }; - /* ZSTD_compressStream2() will check validity of dstPos and srcPos */ - size_t const cErr = ZSTD_compressStream2(cctx, &output, &input, endOp); - *dstPos = output.pos; - *srcPos = input.pos; - return cErr; -} - -size_t ZSTD_compress2(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize) -{ - DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize); - ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); - { size_t oPos = 0; - size_t iPos = 0; - size_t const result = ZSTD_compressStream2_simpleArgs(cctx, - dst, dstCapacity, &oPos, - src, srcSize, &iPos, - ZSTD_e_end); - FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed"); - if (result != 0) { /* compression not completed, due to lack of output space */ - assert(oPos == dstCapacity); - RETURN_ERROR(dstSize_tooSmall, ""); - } - assert(iPos == srcSize); /* all input is expected consumed */ - return oPos; - } -} - -/*====== Finalize ======*/ - -/*! ZSTD_flushStream() : - * @return : amount of data remaining to flush */ -size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) -{ - ZSTD_inBuffer input = { NULL, 0, 0 }; - return ZSTD_compressStream2(zcs, output, &input, ZSTD_e_flush); -} - - -size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output) -{ - ZSTD_inBuffer input = { NULL, 0, 0 }; - size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end); - FORWARD_IF_ERROR( remainingToFlush , "ZSTD_compressStream2 failed"); - if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */ - /* single thread mode : attempt to calculate remaining to flush more precisely */ - { size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE; - size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4); - size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize; - DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush); - return toFlush; - } -} - - -/*-===== Pre-defined compression levels =====-*/ - -#define ZSTD_MAX_CLEVEL 22 -int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } -int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; } - -static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { -{ /* "default" - for any srcSize > 256 KB */ - /* W, C, H, S, L, TL, strat */ - { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ - { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ - { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ - { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */ - { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */ - { 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */ - { 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */ - { 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */ - { 21, 19, 19, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */ - { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */ - { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */ - { 22, 21, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */ - { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */ - { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 13 */ - { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ - { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ - { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */ - { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */ - { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */ - { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */ - { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */ - { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */ - { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */ -}, -{ /* for srcSize <= 256 KB */ - /* W, C, H, S, L, T, strat */ - { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */ - { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */ - { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */ - { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/ - { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/ - { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/ - { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */ - { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ - { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ - { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ - { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/ - { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/ - { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */ - { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ - { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/ - { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/ - { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/ - { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/ - { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/ -}, -{ /* for srcSize <= 128 KB */ - /* W, C, H, S, L, T, strat */ - { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */ - { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */ - { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */ - { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */ - { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */ - { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ - { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */ - { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ - { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ - { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ - { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */ - { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */ - { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/ - { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ - { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/ - { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/ - { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/ - { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/ - { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/ -}, -{ /* for srcSize <= 16 KB */ - /* W, C, H, S, L, T, strat */ - { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ - { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */ - { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */ - { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */ - { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */ - { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/ - { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */ - { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */ - { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/ - { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/ - { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/ - { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/ - { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/ - { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/ - { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/ - { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/ - { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/ - { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/ - { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/ - { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ - { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/ - { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ - { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ -}, -}; - -/*! ZSTD_getCParams_internal() : - * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. - * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown. - * Use dictSize == 0 for unknown or unused. */ -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) -{ - int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN; - size_t const addedSize = unknown && dictSize > 0 ? 500 : 0; - U64 const rSize = unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize; - U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); - int row = compressionLevel; - DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel); - if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ - if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */ - if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; - { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row]; - if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */ - /* refine parameters based on srcSize & dictSize */ - return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); - } -} - -/*! ZSTD_getCParams() : - * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. - * Size values are optional, provide 0 if not known or unused */ -ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) -{ - if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize); -} - -/*! ZSTD_getParams() : - * same idea as ZSTD_getCParams() - * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). - * Fields of `ZSTD_frameParameters` are set to default values */ -static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { - ZSTD_parameters params; - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize); - DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel); - memset(¶ms, 0, sizeof(params)); - params.cParams = cParams; - params.fParams.contentSizeFlag = 1; - return params; -} - -/*! ZSTD_getParams() : - * same idea as ZSTD_getCParams() - * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). - * Fields of `ZSTD_frameParameters` are set to default values */ -ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { - if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize); -} - -} diff --git a/third_party/zstd/compress/zstd_compress_literals.c b/third_party/zstd/compress/zstd_compress_literals.c new file mode 100644 index 00000000000..bfd4f11abe4 --- /dev/null +++ b/third_party/zstd/compress/zstd_compress_literals.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + /*-************************************* + * Dependencies + ***************************************/ +#include "zstd_compress_literals.h" + + +/* ************************************************************** +* Debug Traces +****************************************************************/ +#if DEBUGLEVEL >= 2 + +static size_t showHexa(const void* src, size_t srcSize) +{ + const BYTE* const ip = (const BYTE*)src; + size_t u; + for (u=0; u31) + (srcSize>4095); + + DEBUGLOG(5, "ZSTD_noCompressLiterals: srcSize=%zu, dstCapacity=%zu", srcSize, dstCapacity); + + RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall, ""); + + switch(flSize) + { + case 1: /* 2 - 1 - 5 */ + ostart[0] = (BYTE)((U32)set_basic + (srcSize<<3)); + break; + case 2: /* 2 - 2 - 12 */ + MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4))); + break; + case 3: /* 2 - 2 - 20 */ + MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4))); + break; + default: /* not necessary : flSize is {1,2,3} */ + assert(0); + } + + ZSTD_memcpy(ostart + flSize, src, srcSize); + DEBUGLOG(5, "Raw (uncompressed) literals: %u -> %u", (U32)srcSize, (U32)(srcSize + flSize)); + return srcSize + flSize; +} + +static int allBytesIdentical(const void* src, size_t srcSize) +{ + assert(srcSize >= 1); + assert(src != NULL); + { const BYTE b = ((const BYTE*)src)[0]; + size_t p; + for (p=1; p31) + (srcSize>4095); + + assert(dstCapacity >= 4); (void)dstCapacity; + assert(allBytesIdentical(src, srcSize)); + + switch(flSize) + { + case 1: /* 2 - 1 - 5 */ + ostart[0] = (BYTE)((U32)set_rle + (srcSize<<3)); + break; + case 2: /* 2 - 2 - 12 */ + MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4))); + break; + case 3: /* 2 - 2 - 20 */ + MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4))); + break; + default: /* not necessary : flSize is {1,2,3} */ + assert(0); + } + + ostart[flSize] = *(const BYTE*)src; + DEBUGLOG(5, "RLE : Repeated Literal (%02X: %u times) -> %u bytes encoded", ((const BYTE*)src)[0], (U32)srcSize, (U32)flSize + 1); + return flSize+1; +} + +/* ZSTD_minLiteralsToCompress() : + * returns minimal amount of literals + * for literal compression to even be attempted. + * Minimum is made tighter as compression strategy increases. + */ +static size_t +ZSTD_minLiteralsToCompress(ZSTD_strategy strategy, HUF_repeat huf_repeat) +{ + assert((int)strategy >= 0); + assert((int)strategy <= 9); + /* btultra2 : min 8 bytes; + * then 2x larger for each successive compression strategy + * max threshold 64 bytes */ + { int const shift = MIN(9-(int)strategy, 3); + size_t const mintc = (huf_repeat == HUF_repeat_valid) ? 6 : (size_t)8 << shift; + DEBUGLOG(7, "minLiteralsToCompress = %zu", mintc); + return mintc; + } +} + +size_t ZSTD_compressLiterals ( + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + void* entropyWorkspace, size_t entropyWorkspaceSize, + const ZSTD_hufCTables_t* prevHuf, + ZSTD_hufCTables_t* nextHuf, + ZSTD_strategy strategy, + int disableLiteralCompression, + int suspectUncompressible, + int bmi2) +{ + size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB); + BYTE* const ostart = (BYTE*)dst; + U32 singleStream = srcSize < 256; + symbolEncodingType_e hType = set_compressed; + size_t cLitSize; + + DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i, srcSize=%u, dstCapacity=%zu)", + disableLiteralCompression, (U32)srcSize, dstCapacity); + + DEBUGLOG(6, "Completed literals listing (%zu bytes)", showHexa(src, srcSize)); + + /* Prepare nextEntropy assuming reusing the existing table */ + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + + if (disableLiteralCompression) + return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); + + /* if too small, don't even attempt compression (speed opt) */ + if (srcSize < ZSTD_minLiteralsToCompress(strategy, prevHuf->repeatMode)) + return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); + + RETURN_ERROR_IF(dstCapacity < lhSize+1, dstSize_tooSmall, "not enough space for compression"); + { HUF_repeat repeat = prevHuf->repeatMode; + int const flags = 0 + | (bmi2 ? HUF_flags_bmi2 : 0) + | (strategy < ZSTD_lazy && srcSize <= 1024 ? HUF_flags_preferRepeat : 0) + | (strategy >= HUF_OPTIMAL_DEPTH_THRESHOLD ? HUF_flags_optimalDepth : 0) + | (suspectUncompressible ? HUF_flags_suspectUncompressible : 0); + + typedef size_t (*huf_compress_f)(void*, size_t, const void*, size_t, unsigned, unsigned, void*, size_t, HUF_CElt*, HUF_repeat*, int); + huf_compress_f huf_compress; + if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1; + huf_compress = singleStream ? HUF_compress1X_repeat : HUF_compress4X_repeat; + cLitSize = huf_compress(ostart+lhSize, dstCapacity-lhSize, + src, srcSize, + HUF_SYMBOLVALUE_MAX, LitHufLog, + entropyWorkspace, entropyWorkspaceSize, + (HUF_CElt*)nextHuf->CTable, + &repeat, flags); + DEBUGLOG(5, "%zu literals compressed into %zu bytes (before header)", srcSize, cLitSize); + if (repeat != HUF_repeat_none) { + /* reused the existing table */ + DEBUGLOG(5, "reusing statistics from previous huffman block"); + hType = set_repeat; + } + } + + { size_t const minGain = ZSTD_minGain(srcSize, strategy); + if ((cLitSize==0) || (cLitSize >= srcSize - minGain) || ERR_isError(cLitSize)) { + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); + } } + if (cLitSize==1) { + /* A return value of 1 signals that the alphabet consists of a single symbol. + * However, in some rare circumstances, it could be the compressed size (a single byte). + * For that outcome to have a chance to happen, it's necessary that `srcSize < 8`. + * (it's also necessary to not generate statistics). + * Therefore, in such a case, actively check that all bytes are identical. */ + if ((srcSize >= 8) || allBytesIdentical(src, srcSize)) { + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize); + } } + + if (hType == set_compressed) { + /* using a newly constructed table */ + nextHuf->repeatMode = HUF_repeat_check; + } + + /* Build header */ + switch(lhSize) + { + case 3: /* 2 - 2 - 10 - 10 */ + if (!singleStream) assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS); + { U32 const lhc = hType + ((U32)(!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14); + MEM_writeLE24(ostart, lhc); + break; + } + case 4: /* 2 - 2 - 14 - 14 */ + assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS); + { U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18); + MEM_writeLE32(ostart, lhc); + break; + } + case 5: /* 2 - 2 - 18 - 18 */ + assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS); + { U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22); + MEM_writeLE32(ostart, lhc); + ostart[4] = (BYTE)(cLitSize >> 10); + break; + } + default: /* not possible : lhSize is {3,4,5} */ + assert(0); + } + DEBUGLOG(5, "Compressed literals: %u -> %u", (U32)srcSize, (U32)(lhSize+cLitSize)); + return lhSize+cLitSize; +} diff --git a/third_party/zstd/compress/zstd_compress_literals.cpp b/third_party/zstd/compress/zstd_compress_literals.cpp deleted file mode 100644 index ab9dfb45937..00000000000 --- a/third_party/zstd/compress/zstd_compress_literals.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - - /*-************************************* - * Dependencies - ***************************************/ -#include "zstd/compress/zstd_compress_literals.h" - -namespace duckdb_zstd { -size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize) -{ - BYTE* const ostart = (BYTE* const)dst; - U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); - - RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall, ""); - - switch(flSize) - { - case 1: /* 2 - 1 - 5 */ - ostart[0] = (BYTE)((U32)set_basic + (srcSize<<3)); - break; - case 2: /* 2 - 2 - 12 */ - MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4))); - break; - case 3: /* 2 - 2 - 20 */ - MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4))); - break; - default: /* not necessary : flSize is {1,2,3} */ - assert(0); - } - - memcpy(ostart + flSize, src, srcSize); - DEBUGLOG(5, "Raw literals: %u -> %u", (U32)srcSize, (U32)(srcSize + flSize)); - return srcSize + flSize; -} - -size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize) -{ - BYTE* const ostart = (BYTE* const)dst; - U32 const flSize = 1 + (srcSize>31) + (srcSize>4095); - - (void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */ - - switch(flSize) - { - case 1: /* 2 - 1 - 5 */ - ostart[0] = (BYTE)((U32)set_rle + (srcSize<<3)); - break; - case 2: /* 2 - 2 - 12 */ - MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4))); - break; - case 3: /* 2 - 2 - 20 */ - MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4))); - break; - default: /* not necessary : flSize is {1,2,3} */ - assert(0); - } - - ostart[flSize] = *(const BYTE*)src; - DEBUGLOG(5, "RLE literals: %u -> %u", (U32)srcSize, (U32)flSize + 1); - return flSize+1; -} - -size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf, - ZSTD_hufCTables_t* nextHuf, - ZSTD_strategy strategy, int disableLiteralCompression, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - void* entropyWorkspace, size_t entropyWorkspaceSize, - const int bmi2) -{ - size_t const minGain = ZSTD_minGain(srcSize, strategy); - size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB); - BYTE* const ostart = (BYTE*)dst; - U32 singleStream = srcSize < 256; - symbolEncodingType_e hType = set_compressed; - size_t cLitSize; - - DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i srcSize=%u)", - disableLiteralCompression, (U32)srcSize); - - /* Prepare nextEntropy assuming reusing the existing table */ - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); - - if (disableLiteralCompression) - return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); - - /* small ? don't even attempt compression (speed opt) */ -# define COMPRESS_LITERALS_SIZE_MIN 63 - { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN; - if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); - } - - RETURN_ERROR_IF(dstCapacity < lhSize+1, dstSize_tooSmall, "not enough space for compression"); - { HUF_repeat repeat = prevHuf->repeatMode; - int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0; - if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1; - cLitSize = singleStream ? - HUF_compress1X_repeat( - ostart+lhSize, dstCapacity-lhSize, src, srcSize, - HUF_SYMBOLVALUE_MAX, HUF_TABLELOG_DEFAULT, entropyWorkspace, entropyWorkspaceSize, - (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2) : - HUF_compress4X_repeat( - ostart+lhSize, dstCapacity-lhSize, src, srcSize, - HUF_SYMBOLVALUE_MAX, HUF_TABLELOG_DEFAULT, entropyWorkspace, entropyWorkspaceSize, - (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2); - if (repeat != HUF_repeat_none) { - /* reused the existing table */ - DEBUGLOG(5, "Reusing previous huffman table"); - hType = set_repeat; - } - } - - if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) { - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); - return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); - } - if (cLitSize==1) { - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); - return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize); - } - - if (hType == set_compressed) { - /* using a newly constructed table */ - nextHuf->repeatMode = HUF_repeat_check; - } - - /* Build header */ - switch(lhSize) - { - case 3: /* 2 - 2 - 10 - 10 */ - { U32 const lhc = hType + ((!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14); - MEM_writeLE24(ostart, lhc); - break; - } - case 4: /* 2 - 2 - 14 - 14 */ - { U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18); - MEM_writeLE32(ostart, lhc); - break; - } - case 5: /* 2 - 2 - 18 - 18 */ - { U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22); - MEM_writeLE32(ostart, lhc); - ostart[4] = (BYTE)(cLitSize >> 10); - break; - } - default: /* not possible : lhSize is {3,4,5} */ - assert(0); - } - DEBUGLOG(5, "Compressed literals: %u -> %u", (U32)srcSize, (U32)(lhSize+cLitSize)); - return lhSize+cLitSize; -} - -} diff --git a/third_party/zstd/compress/zstd_compress_sequences.cpp b/third_party/zstd/compress/zstd_compress_sequences.c similarity index 88% rename from third_party/zstd/compress/zstd_compress_sequences.cpp rename to third_party/zstd/compress/zstd_compress_sequences.c index e1cc14597c2..8872d4d354a 100644 --- a/third_party/zstd/compress/zstd_compress_sequences.cpp +++ b/third_party/zstd/compress/zstd_compress_sequences.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,9 +11,8 @@ /*-************************************* * Dependencies ***************************************/ -#include "zstd/compress/zstd_compress_sequences.h" +#include "zstd_compress_sequences.h" -namespace duckdb_zstd { /** * -log2(x / 256) lookup table for x in [0, 256). * If x == 0: Return 0 @@ -51,6 +50,19 @@ static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) { return maxSymbolValue; } +/** + * Returns true if we should use ncount=-1 else we should + * use ncount=1 for low probability symbols instead. + */ +static unsigned ZSTD_useLowProbCount(size_t const nbSeq) +{ + /* Heuristic: This should cover most blocks <= 16K and + * start to fade out after 16K to about 32K depending on + * compressibility. + */ + return nbSeq >= 2048; +} + /** * Returns the cost in bytes of encoding the normalized count header. * Returns an error if any of the helper functions return an error. @@ -61,7 +73,7 @@ static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max, BYTE wksp[FSE_NCOUNTBOUND]; S16 norm[MaxSeq + 1]; const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max); - FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max), ""); + FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max, ZSTD_useLowProbCount(nbSeq)), ""); return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog); } @@ -73,6 +85,8 @@ static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t { unsigned cost = 0; unsigned s; + + assert(total > 0); for (s = 0; s <= max; ++s) { unsigned norm = (unsigned)((256 * count[s]) / total); if (count[s] != 0 && norm == 0) @@ -152,7 +166,7 @@ ZSTD_selectEncodingType( if (mostFrequent == nbSeq) { *repeatMode = FSE_repeat_none; if (isDefaultAllowed && nbSeq <= 2) { - /* Prefer set_basic over set_rle when there are 2 or less symbols, + /* Prefer set_basic over set_rle when there are 2 or fewer symbols, * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol. * If basic encoding isn't possible, always choose RLE. */ @@ -220,6 +234,11 @@ ZSTD_selectEncodingType( return set_compressed; } +typedef struct { + S16 norm[MaxSeq + 1]; + U32 wksp[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(MaxSeq, MaxFSELog)]; +} ZSTD_BuildCTableWksp; + size_t ZSTD_buildCTable(void* dst, size_t dstCapacity, FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type, @@ -240,13 +259,13 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity, *op = codeTable[0]; return 1; case set_repeat: - memcpy(nextCTable, prevCTable, prevCTableSize); + ZSTD_memcpy(nextCTable, prevCTable, prevCTableSize); return 0; case set_basic: FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), ""); /* note : could be pre-calculated */ return 0; case set_compressed: { - S16 norm[MaxSeq + 1]; + ZSTD_BuildCTableWksp* wksp = (ZSTD_BuildCTableWksp*)entropyWorkspace; size_t nbSeq_1 = nbSeq; const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max); if (count[codeTable[nbSeq-1]] > 1) { @@ -254,10 +273,13 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity, nbSeq_1--; } assert(nbSeq_1 > 1); - FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max), ""); - { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ + assert(entropyWorkspaceSize >= sizeof(ZSTD_BuildCTableWksp)); + (void)entropyWorkspaceSize; + FORWARD_IF_ERROR(FSE_normalizeCount(wksp->norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), "FSE_normalizeCount failed"); + assert(oend >= op); + { size_t const NCountSize = FSE_writeNCount(op, (size_t)(oend - op), wksp->norm, max, tableLog); /* overflow protected */ FORWARD_IF_ERROR(NCountSize, "FSE_writeNCount failed"); - FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, entropyWorkspace, entropyWorkspaceSize), ""); + FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, wksp->norm, max, tableLog, wksp->wksp, sizeof(wksp->wksp)), "FSE_buildCTable_wksp failed"); return NCountSize; } } @@ -289,21 +311,21 @@ ZSTD_encodeSequences_body( FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]); FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]); FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]); - BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, ZSTDInternalConstants::LL_bits[llCodeTable[nbSeq-1]]); + BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]); if (MEM_32bits()) BIT_flushBits(&blockStream); - BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ZSTDInternalConstants::ML_bits[mlCodeTable[nbSeq-1]]); + BIT_addBits(&blockStream, sequences[nbSeq-1].mlBase, ML_bits[mlCodeTable[nbSeq-1]]); if (MEM_32bits()) BIT_flushBits(&blockStream); if (longOffsets) { U32 const ofBits = ofCodeTable[nbSeq-1]; unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1); if (extraBits) { - BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits); + BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, extraBits); BIT_flushBits(&blockStream); } - BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits, + BIT_addBits(&blockStream, sequences[nbSeq-1].offBase >> extraBits, ofBits - extraBits); } else { - BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]); + BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, ofCodeTable[nbSeq-1]); } BIT_flushBits(&blockStream); @@ -312,13 +334,13 @@ ZSTD_encodeSequences_body( BYTE const llCode = llCodeTable[n]; BYTE const ofCode = ofCodeTable[n]; BYTE const mlCode = mlCodeTable[n]; - U32 const llBits = ZSTDInternalConstants::LL_bits[llCode]; + U32 const llBits = LL_bits[llCode]; U32 const ofBits = ofCode; - U32 const mlBits = ZSTDInternalConstants::ML_bits[mlCode]; + U32 const mlBits = ML_bits[mlCode]; DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u", (unsigned)sequences[n].litLength, - (unsigned)sequences[n].matchLength + MINMATCH, - (unsigned)sequences[n].offset); + (unsigned)sequences[n].mlBase + MINMATCH, + (unsigned)sequences[n].offBase); /* 32b*/ /* 64b*/ /* (7)*/ /* (7)*/ FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */ @@ -329,18 +351,18 @@ ZSTD_encodeSequences_body( BIT_flushBits(&blockStream); /* (7)*/ BIT_addBits(&blockStream, sequences[n].litLength, llBits); if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream); - BIT_addBits(&blockStream, sequences[n].matchLength, mlBits); + BIT_addBits(&blockStream, sequences[n].mlBase, mlBits); if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream); if (longOffsets) { unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1); if (extraBits) { - BIT_addBits(&blockStream, sequences[n].offset, extraBits); + BIT_addBits(&blockStream, sequences[n].offBase, extraBits); BIT_flushBits(&blockStream); /* (7)*/ } - BIT_addBits(&blockStream, sequences[n].offset >> extraBits, + BIT_addBits(&blockStream, sequences[n].offBase >> extraBits, ofBits - extraBits); /* 31 */ } else { - BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */ + BIT_addBits(&blockStream, sequences[n].offBase, ofBits); /* 31 */ } BIT_flushBits(&blockStream); /* (7)*/ DEBUGLOG(7, "remaining space : %i", (int)(blockStream.endPtr - blockStream.ptr)); @@ -377,7 +399,7 @@ ZSTD_encodeSequences_default( #if DYNAMIC_BMI2 -static TARGET_ATTRIBUTE("bmi2") size_t +static BMI2_TARGET_ATTRIBUTE size_t ZSTD_encodeSequences_bmi2( void* dst, size_t dstCapacity, FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable, @@ -418,5 +440,3 @@ size_t ZSTD_encodeSequences( CTable_LitLength, llCodeTable, sequences, nbSeq, longOffsets); } - -} diff --git a/third_party/zstd/compress/zstd_compress_superblock.c b/third_party/zstd/compress/zstd_compress_superblock.c new file mode 100644 index 00000000000..628a2dccd09 --- /dev/null +++ b/third_party/zstd/compress/zstd_compress_superblock.c @@ -0,0 +1,688 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + /*-************************************* + * Dependencies + ***************************************/ +#include "zstd_compress_superblock.h" + +#include "../common/zstd_internal.h" /* ZSTD_getSequenceLength */ +#include "hist.h" /* HIST_countFast_wksp */ +#include "zstd_compress_internal.h" /* ZSTD_[huf|fse|entropy]CTablesMetadata_t */ +#include "zstd_compress_sequences.h" +#include "zstd_compress_literals.h" + +/** ZSTD_compressSubBlock_literal() : + * Compresses literals section for a sub-block. + * When we have to write the Huffman table we will sometimes choose a header + * size larger than necessary. This is because we have to pick the header size + * before we know the table size + compressed size, so we have a bound on the + * table size. If we guessed incorrectly, we fall back to uncompressed literals. + * + * We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded + * in writing the header, otherwise it is set to 0. + * + * hufMetadata->hType has literals block type info. + * If it is set_basic, all sub-blocks literals section will be Raw_Literals_Block. + * If it is set_rle, all sub-blocks literals section will be RLE_Literals_Block. + * If it is set_compressed, first sub-block's literals section will be Compressed_Literals_Block + * If it is set_compressed, first sub-block's literals section will be Treeless_Literals_Block + * and the following sub-blocks' literals sections will be Treeless_Literals_Block. + * @return : compressed size of literals section of a sub-block + * Or 0 if unable to compress. + * Or error code */ +static size_t +ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, + const ZSTD_hufCTablesMetadata_t* hufMetadata, + const BYTE* literals, size_t litSize, + void* dst, size_t dstSize, + const int bmi2, int writeEntropy, int* entropyWritten) +{ + size_t const header = writeEntropy ? 200 : 0; + size_t const lhSize = 3 + (litSize >= (1 KB - header)) + (litSize >= (16 KB - header)); + BYTE* const ostart = (BYTE*)dst; + BYTE* const oend = ostart + dstSize; + BYTE* op = ostart + lhSize; + U32 const singleStream = lhSize == 3; + symbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat; + size_t cLitSize = 0; + + DEBUGLOG(5, "ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)", litSize, lhSize, writeEntropy); + + *entropyWritten = 0; + if (litSize == 0 || hufMetadata->hType == set_basic) { + DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal"); + return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize); + } else if (hufMetadata->hType == set_rle) { + DEBUGLOG(5, "ZSTD_compressSubBlock_literal using rle literal"); + return ZSTD_compressRleLiteralsBlock(dst, dstSize, literals, litSize); + } + + assert(litSize > 0); + assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat); + + if (writeEntropy && hufMetadata->hType == set_compressed) { + ZSTD_memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize); + op += hufMetadata->hufDesSize; + cLitSize += hufMetadata->hufDesSize; + DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize); + } + + { int const flags = bmi2 ? HUF_flags_bmi2 : 0; + const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags) + : HUF_compress4X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags); + op += cSize; + cLitSize += cSize; + if (cSize == 0 || ERR_isError(cSize)) { + DEBUGLOG(5, "Failed to write entropy tables %s", ZSTD_getErrorName(cSize)); + return 0; + } + /* If we expand and we aren't writing a header then emit uncompressed */ + if (!writeEntropy && cLitSize >= litSize) { + DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal because uncompressible"); + return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize); + } + /* If we are writing headers then allow expansion that doesn't change our header size. */ + if (lhSize < (size_t)(3 + (cLitSize >= 1 KB) + (cLitSize >= 16 KB))) { + assert(cLitSize > litSize); + DEBUGLOG(5, "Literals expanded beyond allowed header size"); + return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize); + } + DEBUGLOG(5, "ZSTD_compressSubBlock_literal (cSize=%zu)", cSize); + } + + /* Build header */ + switch(lhSize) + { + case 3: /* 2 - 2 - 10 - 10 */ + { U32 const lhc = hType + ((U32)(!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14); + MEM_writeLE24(ostart, lhc); + break; + } + case 4: /* 2 - 2 - 14 - 14 */ + { U32 const lhc = hType + (2 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<18); + MEM_writeLE32(ostart, lhc); + break; + } + case 5: /* 2 - 2 - 18 - 18 */ + { U32 const lhc = hType + (3 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<22); + MEM_writeLE32(ostart, lhc); + ostart[4] = (BYTE)(cLitSize >> 10); + break; + } + default: /* not possible : lhSize is {3,4,5} */ + assert(0); + } + *entropyWritten = 1; + DEBUGLOG(5, "Compressed literals: %u -> %u", (U32)litSize, (U32)(op-ostart)); + return (size_t)(op-ostart); +} + +static size_t +ZSTD_seqDecompressedSize(seqStore_t const* seqStore, + const seqDef* sequences, size_t nbSeqs, + size_t litSize, int lastSubBlock) +{ + size_t matchLengthSum = 0; + size_t litLengthSum = 0; + size_t n; + for (n=0; nllType, fseMetadata->ofType, and fseMetadata->mlType have + * symbol compression modes for the super-block. + * The first successfully compressed block will have these in its header. + * We set entropyWritten=1 when we succeed in compressing the sequences. + * The following sub-blocks will always have repeat mode. + * @return : compressed size of sequences section of a sub-block + * Or 0 if it is unable to compress + * Or error code. */ +static size_t +ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables, + const ZSTD_fseCTablesMetadata_t* fseMetadata, + const seqDef* sequences, size_t nbSeq, + const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode, + const ZSTD_CCtx_params* cctxParams, + void* dst, size_t dstCapacity, + const int bmi2, int writeEntropy, int* entropyWritten) +{ + const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN; + BYTE* const ostart = (BYTE*)dst; + BYTE* const oend = ostart + dstCapacity; + BYTE* op = ostart; + BYTE* seqHead; + + DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (nbSeq=%zu, writeEntropy=%d, longOffsets=%d)", nbSeq, writeEntropy, longOffsets); + + *entropyWritten = 0; + /* Sequences Header */ + RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/, + dstSize_tooSmall, ""); + if (nbSeq < 128) + *op++ = (BYTE)nbSeq; + else if (nbSeq < LONGNBSEQ) + op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2; + else + op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3; + if (nbSeq==0) { + return (size_t)(op - ostart); + } + + /* seqHead : flags for FSE encoding type */ + seqHead = op++; + + DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (seqHeadSize=%u)", (unsigned)(op-ostart)); + + if (writeEntropy) { + const U32 LLtype = fseMetadata->llType; + const U32 Offtype = fseMetadata->ofType; + const U32 MLtype = fseMetadata->mlType; + DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)", fseMetadata->fseTablesSize); + *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); + ZSTD_memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize); + op += fseMetadata->fseTablesSize; + } else { + const U32 repeat = set_repeat; + *seqHead = (BYTE)((repeat<<6) + (repeat<<4) + (repeat<<2)); + } + + { size_t const bitstreamSize = ZSTD_encodeSequences( + op, (size_t)(oend - op), + fseTables->matchlengthCTable, mlCode, + fseTables->offcodeCTable, ofCode, + fseTables->litlengthCTable, llCode, + sequences, nbSeq, + longOffsets, bmi2); + FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed"); + op += bitstreamSize; + /* zstd versions <= 1.3.4 mistakenly report corruption when + * FSE_readNCount() receives a buffer < 4 bytes. + * Fixed by https://github.com/facebook/zstd/pull/1146. + * This can happen when the last set_compressed table present is 2 + * bytes and the bitstream is only one byte. + * In this exceedingly rare case, we will simply emit an uncompressed + * block, since it isn't worth optimizing. + */ +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (writeEntropy && fseMetadata->lastCountSize && fseMetadata->lastCountSize + bitstreamSize < 4) { + /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */ + assert(fseMetadata->lastCountSize + bitstreamSize == 3); + DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by " + "emitting an uncompressed block."); + return 0; + } +#endif + DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (bitstreamSize=%zu)", bitstreamSize); + } + + /* zstd versions <= 1.4.0 mistakenly report error when + * sequences section body size is less than 3 bytes. + * Fixed by https://github.com/facebook/zstd/pull/1664. + * This can happen when the previous sequences section block is compressed + * with rle mode and the current block's sequences section is compressed + * with repeat mode where sequences section body size can be 1 byte. + */ +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + if (op-seqHead < 4) { + DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.4.0 by emitting " + "an uncompressed block when sequences are < 4 bytes"); + return 0; + } +#endif + + *entropyWritten = 1; + return (size_t)(op - ostart); +} + +/** ZSTD_compressSubBlock() : + * Compresses a single sub-block. + * @return : compressed size of the sub-block + * Or 0 if it failed to compress. */ +static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy, + const ZSTD_entropyCTablesMetadata_t* entropyMetadata, + const seqDef* sequences, size_t nbSeq, + const BYTE* literals, size_t litSize, + const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode, + const ZSTD_CCtx_params* cctxParams, + void* dst, size_t dstCapacity, + const int bmi2, + int writeLitEntropy, int writeSeqEntropy, + int* litEntropyWritten, int* seqEntropyWritten, + U32 lastBlock) +{ + BYTE* const ostart = (BYTE*)dst; + BYTE* const oend = ostart + dstCapacity; + BYTE* op = ostart + ZSTD_blockHeaderSize; + DEBUGLOG(5, "ZSTD_compressSubBlock (litSize=%zu, nbSeq=%zu, writeLitEntropy=%d, writeSeqEntropy=%d, lastBlock=%d)", + litSize, nbSeq, writeLitEntropy, writeSeqEntropy, lastBlock); + { size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable, + &entropyMetadata->hufMetadata, literals, litSize, + op, (size_t)(oend-op), + bmi2, writeLitEntropy, litEntropyWritten); + FORWARD_IF_ERROR(cLitSize, "ZSTD_compressSubBlock_literal failed"); + if (cLitSize == 0) return 0; + op += cLitSize; + } + { size_t cSeqSize = ZSTD_compressSubBlock_sequences(&entropy->fse, + &entropyMetadata->fseMetadata, + sequences, nbSeq, + llCode, mlCode, ofCode, + cctxParams, + op, (size_t)(oend-op), + bmi2, writeSeqEntropy, seqEntropyWritten); + FORWARD_IF_ERROR(cSeqSize, "ZSTD_compressSubBlock_sequences failed"); + if (cSeqSize == 0) return 0; + op += cSeqSize; + } + /* Write block header */ + { size_t cSize = (size_t)(op-ostart) - ZSTD_blockHeaderSize; + U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); + MEM_writeLE24(ostart, cBlockHeader24); + } + return (size_t)(op-ostart); +} + +static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t litSize, + const ZSTD_hufCTables_t* huf, + const ZSTD_hufCTablesMetadata_t* hufMetadata, + void* workspace, size_t wkspSize, + int writeEntropy) +{ + unsigned* const countWksp = (unsigned*)workspace; + unsigned maxSymbolValue = 255; + size_t literalSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */ + + if (hufMetadata->hType == set_basic) return litSize; + else if (hufMetadata->hType == set_rle) return 1; + else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) { + size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize); + if (ZSTD_isError(largest)) return litSize; + { size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue); + if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize; + return cLitSizeEstimate + literalSectionHeaderSize; + } } + assert(0); /* impossible */ + return 0; +} + +static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type, + const BYTE* codeTable, unsigned maxCode, + size_t nbSeq, const FSE_CTable* fseCTable, + const U8* additionalBits, + short const* defaultNorm, U32 defaultNormLog, U32 defaultMax, + void* workspace, size_t wkspSize) +{ + unsigned* const countWksp = (unsigned*)workspace; + const BYTE* ctp = codeTable; + const BYTE* const ctStart = ctp; + const BYTE* const ctEnd = ctStart + nbSeq; + size_t cSymbolTypeSizeEstimateInBits = 0; + unsigned max = maxCode; + + HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */ + if (type == set_basic) { + /* We selected this encoding type, so it must be valid. */ + assert(max <= defaultMax); + cSymbolTypeSizeEstimateInBits = max <= defaultMax + ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max) + : ERROR(GENERIC); + } else if (type == set_rle) { + cSymbolTypeSizeEstimateInBits = 0; + } else if (type == set_compressed || type == set_repeat) { + cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max); + } + if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) return nbSeq * 10; + while (ctp < ctEnd) { + if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp]; + else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */ + ctp++; + } + return cSymbolTypeSizeEstimateInBits / 8; +} + +static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable, + const BYTE* llCodeTable, + const BYTE* mlCodeTable, + size_t nbSeq, + const ZSTD_fseCTables_t* fseTables, + const ZSTD_fseCTablesMetadata_t* fseMetadata, + void* workspace, size_t wkspSize, + int writeEntropy) +{ + size_t const sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */ + size_t cSeqSizeEstimate = 0; + if (nbSeq == 0) return sequencesSectionHeaderSize; + cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff, + nbSeq, fseTables->offcodeCTable, NULL, + OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, + workspace, wkspSize); + cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL, + nbSeq, fseTables->litlengthCTable, LL_bits, + LL_defaultNorm, LL_defaultNormLog, MaxLL, + workspace, wkspSize); + cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML, + nbSeq, fseTables->matchlengthCTable, ML_bits, + ML_defaultNorm, ML_defaultNormLog, MaxML, + workspace, wkspSize); + if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize; + return cSeqSizeEstimate + sequencesSectionHeaderSize; +} + +typedef struct { + size_t estLitSize; + size_t estBlockSize; +} EstimatedBlockSize; +static EstimatedBlockSize ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize, + const BYTE* ofCodeTable, + const BYTE* llCodeTable, + const BYTE* mlCodeTable, + size_t nbSeq, + const ZSTD_entropyCTables_t* entropy, + const ZSTD_entropyCTablesMetadata_t* entropyMetadata, + void* workspace, size_t wkspSize, + int writeLitEntropy, int writeSeqEntropy) +{ + EstimatedBlockSize ebs; + ebs.estLitSize = ZSTD_estimateSubBlockSize_literal(literals, litSize, + &entropy->huf, &entropyMetadata->hufMetadata, + workspace, wkspSize, writeLitEntropy); + ebs.estBlockSize = ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable, + nbSeq, &entropy->fse, &entropyMetadata->fseMetadata, + workspace, wkspSize, writeSeqEntropy); + ebs.estBlockSize += ebs.estLitSize + ZSTD_blockHeaderSize; + return ebs; +} + +static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMetadata) +{ + if (fseMetadata->llType == set_compressed || fseMetadata->llType == set_rle) + return 1; + if (fseMetadata->mlType == set_compressed || fseMetadata->mlType == set_rle) + return 1; + if (fseMetadata->ofType == set_compressed || fseMetadata->ofType == set_rle) + return 1; + return 0; +} + +static size_t countLiterals(seqStore_t const* seqStore, const seqDef* sp, size_t seqCount) +{ + size_t n, total = 0; + assert(sp != NULL); + for (n=0; n %zu bytes", seqCount, (const void*)sp, total); + return total; +} + +#define BYTESCALE 256 + +static size_t sizeBlockSequences(const seqDef* sp, size_t nbSeqs, + size_t targetBudget, size_t avgLitCost, size_t avgSeqCost, + int firstSubBlock) +{ + size_t n, budget = 0, inSize=0; + /* entropy headers */ + size_t const headerSize = (size_t)firstSubBlock * 120 * BYTESCALE; /* generous estimate */ + assert(firstSubBlock==0 || firstSubBlock==1); + budget += headerSize; + + /* first sequence => at least one sequence*/ + budget += sp[0].litLength * avgLitCost + avgSeqCost; + if (budget > targetBudget) return 1; + inSize = sp[0].litLength + (sp[0].mlBase+MINMATCH); + + /* loop over sequences */ + for (n=1; n targetBudget) + /* though continue to expand until the sub-block is deemed compressible */ + && (budget < inSize * BYTESCALE) ) + break; + } + + return n; +} + +/** ZSTD_compressSubBlock_multi() : + * Breaks super-block into multiple sub-blocks and compresses them. + * Entropy will be written into the first block. + * The following blocks use repeat_mode to compress. + * Sub-blocks are all compressed, except the last one when beneficial. + * @return : compressed size of the super block (which features multiple ZSTD blocks) + * or 0 if it failed to compress. */ +static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, + const ZSTD_compressedBlockState_t* prevCBlock, + ZSTD_compressedBlockState_t* nextCBlock, + const ZSTD_entropyCTablesMetadata_t* entropyMetadata, + const ZSTD_CCtx_params* cctxParams, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const int bmi2, U32 lastBlock, + void* workspace, size_t wkspSize) +{ + const seqDef* const sstart = seqStorePtr->sequencesStart; + const seqDef* const send = seqStorePtr->sequences; + const seqDef* sp = sstart; /* tracks progresses within seqStorePtr->sequences */ + size_t const nbSeqs = (size_t)(send - sstart); + const BYTE* const lstart = seqStorePtr->litStart; + const BYTE* const lend = seqStorePtr->lit; + const BYTE* lp = lstart; + size_t const nbLiterals = (size_t)(lend - lstart); + BYTE const* ip = (BYTE const*)src; + BYTE const* const iend = ip + srcSize; + BYTE* const ostart = (BYTE*)dst; + BYTE* const oend = ostart + dstCapacity; + BYTE* op = ostart; + const BYTE* llCodePtr = seqStorePtr->llCode; + const BYTE* mlCodePtr = seqStorePtr->mlCode; + const BYTE* ofCodePtr = seqStorePtr->ofCode; + size_t const minTarget = ZSTD_TARGETCBLOCKSIZE_MIN; /* enforce minimum size, to reduce undesirable side effects */ + size_t const targetCBlockSize = MAX(minTarget, cctxParams->targetCBlockSize); + int writeLitEntropy = (entropyMetadata->hufMetadata.hType == set_compressed); + int writeSeqEntropy = 1; + + DEBUGLOG(5, "ZSTD_compressSubBlock_multi (srcSize=%u, litSize=%u, nbSeq=%u)", + (unsigned)srcSize, (unsigned)(lend-lstart), (unsigned)(send-sstart)); + + /* let's start by a general estimation for the full block */ + if (nbSeqs > 0) { + EstimatedBlockSize const ebs = + ZSTD_estimateSubBlockSize(lp, nbLiterals, + ofCodePtr, llCodePtr, mlCodePtr, nbSeqs, + &nextCBlock->entropy, entropyMetadata, + workspace, wkspSize, + writeLitEntropy, writeSeqEntropy); + /* quick estimation */ + size_t const avgLitCost = nbLiterals ? (ebs.estLitSize * BYTESCALE) / nbLiterals : BYTESCALE; + size_t const avgSeqCost = ((ebs.estBlockSize - ebs.estLitSize) * BYTESCALE) / nbSeqs; + const size_t nbSubBlocks = MAX((ebs.estBlockSize + (targetCBlockSize/2)) / targetCBlockSize, 1); + size_t n, avgBlockBudget, blockBudgetSupp=0; + avgBlockBudget = (ebs.estBlockSize * BYTESCALE) / nbSubBlocks; + DEBUGLOG(5, "estimated fullblock size=%u bytes ; avgLitCost=%.2f ; avgSeqCost=%.2f ; targetCBlockSize=%u, nbSubBlocks=%u ; avgBlockBudget=%.0f bytes", + (unsigned)ebs.estBlockSize, (double)avgLitCost/BYTESCALE, (double)avgSeqCost/BYTESCALE, + (unsigned)targetCBlockSize, (unsigned)nbSubBlocks, (double)avgBlockBudget/BYTESCALE); + /* simplification: if estimates states that the full superblock doesn't compress, just bail out immediately + * this will result in the production of a single uncompressed block covering @srcSize.*/ + if (ebs.estBlockSize > srcSize) return 0; + + /* compress and write sub-blocks */ + assert(nbSubBlocks>0); + for (n=0; n < nbSubBlocks-1; n++) { + /* determine nb of sequences for current sub-block + nbLiterals from next sequence */ + size_t const seqCount = sizeBlockSequences(sp, (size_t)(send-sp), + avgBlockBudget + blockBudgetSupp, avgLitCost, avgSeqCost, n==0); + /* if reached last sequence : break to last sub-block (simplification) */ + assert(seqCount <= (size_t)(send-sp)); + if (sp + seqCount == send) break; + assert(seqCount > 0); + /* compress sub-block */ + { int litEntropyWritten = 0; + int seqEntropyWritten = 0; + size_t litSize = countLiterals(seqStorePtr, sp, seqCount); + const size_t decompressedSize = + ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 0); + size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata, + sp, seqCount, + lp, litSize, + llCodePtr, mlCodePtr, ofCodePtr, + cctxParams, + op, (size_t)(oend-op), + bmi2, writeLitEntropy, writeSeqEntropy, + &litEntropyWritten, &seqEntropyWritten, + 0); + FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed"); + + /* check compressibility, update state components */ + if (cSize > 0 && cSize < decompressedSize) { + DEBUGLOG(5, "Committed sub-block compressing %u bytes => %u bytes", + (unsigned)decompressedSize, (unsigned)cSize); + assert(ip + decompressedSize <= iend); + ip += decompressedSize; + lp += litSize; + op += cSize; + llCodePtr += seqCount; + mlCodePtr += seqCount; + ofCodePtr += seqCount; + /* Entropy only needs to be written once */ + if (litEntropyWritten) { + writeLitEntropy = 0; + } + if (seqEntropyWritten) { + writeSeqEntropy = 0; + } + sp += seqCount; + blockBudgetSupp = 0; + } } + /* otherwise : do not compress yet, coalesce current sub-block with following one */ + } + } /* if (nbSeqs > 0) */ + + /* write last block */ + DEBUGLOG(5, "Generate last sub-block: %u sequences remaining", (unsigned)(send - sp)); + { int litEntropyWritten = 0; + int seqEntropyWritten = 0; + size_t litSize = (size_t)(lend - lp); + size_t seqCount = (size_t)(send - sp); + const size_t decompressedSize = + ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 1); + size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata, + sp, seqCount, + lp, litSize, + llCodePtr, mlCodePtr, ofCodePtr, + cctxParams, + op, (size_t)(oend-op), + bmi2, writeLitEntropy, writeSeqEntropy, + &litEntropyWritten, &seqEntropyWritten, + lastBlock); + FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed"); + + /* update pointers, the nb of literals borrowed from next sequence must be preserved */ + if (cSize > 0 && cSize < decompressedSize) { + DEBUGLOG(5, "Last sub-block compressed %u bytes => %u bytes", + (unsigned)decompressedSize, (unsigned)cSize); + assert(ip + decompressedSize <= iend); + ip += decompressedSize; + lp += litSize; + op += cSize; + llCodePtr += seqCount; + mlCodePtr += seqCount; + ofCodePtr += seqCount; + /* Entropy only needs to be written once */ + if (litEntropyWritten) { + writeLitEntropy = 0; + } + if (seqEntropyWritten) { + writeSeqEntropy = 0; + } + sp += seqCount; + } + } + + + if (writeLitEntropy) { + DEBUGLOG(5, "Literal entropy tables were never written"); + ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf)); + } + if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) { + /* If we haven't written our entropy tables, then we've violated our contract and + * must emit an uncompressed block. + */ + DEBUGLOG(5, "Sequence entropy tables were never written => cancel, emit an uncompressed block"); + return 0; + } + + if (ip < iend) { + /* some data left : last part of the block sent uncompressed */ + size_t const rSize = (size_t)((iend - ip)); + size_t const cSize = ZSTD_noCompressBlock(op, (size_t)(oend - op), ip, rSize, lastBlock); + DEBUGLOG(5, "Generate last uncompressed sub-block of %u bytes", (unsigned)(rSize)); + FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed"); + assert(cSize != 0); + op += cSize; + /* We have to regenerate the repcodes because we've skipped some sequences */ + if (sp < send) { + const seqDef* seq; + repcodes_t rep; + ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep)); + for (seq = sstart; seq < sp; ++seq) { + ZSTD_updateRep(rep.rep, seq->offBase, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0); + } + ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep)); + } + } + + DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed all subBlocks: total compressed size = %u", + (unsigned)(op-ostart)); + return (size_t)(op-ostart); +} + +size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + unsigned lastBlock) +{ + ZSTD_entropyCTablesMetadata_t entropyMetadata; + + FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(&zc->seqStore, + &zc->blockState.prevCBlock->entropy, + &zc->blockState.nextCBlock->entropy, + &zc->appliedParams, + &entropyMetadata, + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), ""); + + return ZSTD_compressSubBlock_multi(&zc->seqStore, + zc->blockState.prevCBlock, + zc->blockState.nextCBlock, + &entropyMetadata, + &zc->appliedParams, + dst, dstCapacity, + src, srcSize, + zc->bmi2, lastBlock, + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */); +} diff --git a/third_party/zstd/compress/zstd_compress_superblock.cpp b/third_party/zstd/compress/zstd_compress_superblock.cpp deleted file mode 100644 index 559a3a0cdab..00000000000 --- a/third_party/zstd/compress/zstd_compress_superblock.cpp +++ /dev/null @@ -1,842 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - - /*-************************************* - * Dependencies - ***************************************/ -#include "zstd/compress/zstd_compress_superblock.h" - -#include "zstd/common/zstd_internal.h" /* ZSTD_getSequenceLength */ -#include "zstd/compress/hist.h" /* HIST_countFast_wksp */ -#include "zstd/compress/zstd_compress_internal.h" -#include "zstd/compress/zstd_compress_sequences.h" -#include "zstd/compress/zstd_compress_literals.h" - -namespace duckdb_zstd { -/*-************************************* -* Superblock entropy buffer structs -***************************************/ -/** ZSTD_hufCTablesMetadata_t : - * Stores Literals Block Type for a super-block in hType, and - * huffman tree description in hufDesBuffer. - * hufDesSize refers to the size of huffman tree description in bytes. - * This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */ -typedef struct { - symbolEncodingType_e hType; - BYTE hufDesBuffer[500]; /* TODO give name to this value */ - size_t hufDesSize; -} ZSTD_hufCTablesMetadata_t; - -/** ZSTD_fseCTablesMetadata_t : - * Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and - * fse tables in fseTablesBuffer. - * fseTablesSize refers to the size of fse tables in bytes. - * This metadata is populated in ZSTD_buildSuperBlockEntropy_sequences() */ -typedef struct { - symbolEncodingType_e llType; - symbolEncodingType_e ofType; - symbolEncodingType_e mlType; - BYTE fseTablesBuffer[500]; /* TODO give name to this value */ - size_t fseTablesSize; - size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */ -} ZSTD_fseCTablesMetadata_t; - -typedef struct { - ZSTD_hufCTablesMetadata_t hufMetadata; - ZSTD_fseCTablesMetadata_t fseMetadata; -} ZSTD_entropyCTablesMetadata_t; - - -/** ZSTD_buildSuperBlockEntropy_literal() : - * Builds entropy for the super-block literals. - * Stores literals block type (raw, rle, compressed, repeat) and - * huffman description table to hufMetadata. - * @return : size of huffman description table or error code */ -static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSize, - const ZSTD_hufCTables_t* prevHuf, - ZSTD_hufCTables_t* nextHuf, - ZSTD_hufCTablesMetadata_t* hufMetadata, - const int disableLiteralsCompression, - void* workspace, size_t wkspSize) -{ - BYTE* const wkspStart = (BYTE*)workspace; - BYTE* const wkspEnd = wkspStart + wkspSize; - BYTE* const countWkspStart = wkspStart; - unsigned* const countWksp = (unsigned*)workspace; - const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned); - BYTE* const nodeWksp = countWkspStart + countWkspSize; - const size_t nodeWkspSize = wkspEnd-nodeWksp; - unsigned maxSymbolValue = 255; - unsigned huffLog = HUF_TABLELOG_DEFAULT; - HUF_repeat repeat = prevHuf->repeatMode; - - DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize); - - /* Prepare nextEntropy assuming reusing the existing table */ - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); - - if (disableLiteralsCompression) { - DEBUGLOG(5, "set_basic - disabled"); - hufMetadata->hType = set_basic; - return 0; - } - - /* small ? don't even attempt compression (speed opt) */ -# define COMPRESS_LITERALS_SIZE_MIN 63 - { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN; - if (srcSize <= minLitSize) { - DEBUGLOG(5, "set_basic - too small"); - hufMetadata->hType = set_basic; - return 0; - } - } - - /* Scan input and build symbol stats */ - { size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize); - FORWARD_IF_ERROR(largest, "HIST_count_wksp failed"); - if (largest == srcSize) { - DEBUGLOG(5, "set_rle"); - hufMetadata->hType = set_rle; - return 0; - } - if (largest <= (srcSize >> 7)+4) { - DEBUGLOG(5, "set_basic - no gain"); - hufMetadata->hType = set_basic; - return 0; - } - } - - /* Validate the previous Huffman table */ - if (repeat == HUF_repeat_check && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) { - repeat = HUF_repeat_none; - } - - /* Build Huffman Tree */ - memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable)); - huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); - { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp, - maxSymbolValue, huffLog, - nodeWksp, nodeWkspSize); - FORWARD_IF_ERROR(maxBits, "HUF_buildCTable_wksp"); - huffLog = (U32)maxBits; - { /* Build and write the CTable */ - size_t const newCSize = HUF_estimateCompressedSize( - (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue); - size_t const hSize = HUF_writeCTable( - hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer), - (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog); - /* Check against repeating the previous CTable */ - if (repeat != HUF_repeat_none) { - size_t const oldCSize = HUF_estimateCompressedSize( - (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue); - if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) { - DEBUGLOG(5, "set_repeat - smaller"); - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); - hufMetadata->hType = set_repeat; - return 0; - } - } - if (newCSize + hSize >= srcSize) { - DEBUGLOG(5, "set_basic - no gains"); - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); - hufMetadata->hType = set_basic; - return 0; - } - DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize); - hufMetadata->hType = set_compressed; - nextHuf->repeatMode = HUF_repeat_check; - return hSize; - } - } -} - -/** ZSTD_buildSuperBlockEntropy_sequences() : - * Builds entropy for the super-block sequences. - * Stores symbol compression modes and fse table to fseMetadata. - * @return : size of fse tables or error code */ -static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr, - const ZSTD_fseCTables_t* prevEntropy, - ZSTD_fseCTables_t* nextEntropy, - const ZSTD_CCtx_params* cctxParams, - ZSTD_fseCTablesMetadata_t* fseMetadata, - void* workspace, size_t wkspSize) -{ - BYTE* const wkspStart = (BYTE*)workspace; - BYTE* const wkspEnd = wkspStart + wkspSize; - BYTE* const countWkspStart = wkspStart; - unsigned* const countWksp = (unsigned*)workspace; - const size_t countWkspSize = (MaxSeq + 1) * sizeof(unsigned); - BYTE* const cTableWksp = countWkspStart + countWkspSize; - const size_t cTableWkspSize = wkspEnd-cTableWksp; - ZSTD_strategy const strategy = cctxParams->cParams.strategy; - FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable; - FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable; - FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable; - const BYTE* const ofCodeTable = seqStorePtr->ofCode; - const BYTE* const llCodeTable = seqStorePtr->llCode; - const BYTE* const mlCodeTable = seqStorePtr->mlCode; - size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart; - BYTE* const ostart = fseMetadata->fseTablesBuffer; - BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer); - BYTE* op = ostart; - - assert(cTableWkspSize >= (1 << MaxFSELog) * sizeof(FSE_FUNCTION_TYPE)); - DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_sequences (nbSeq=%zu)", nbSeq); - memset(workspace, 0, wkspSize); - - fseMetadata->lastCountSize = 0; - /* convert length/distances into codes */ - ZSTD_seqToCodes(seqStorePtr); - /* build CTable for Literal Lengths */ - { U32 LLtype; - unsigned max = MaxLL; - size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, llCodeTable, nbSeq, workspace, wkspSize); /* can't fail */ - DEBUGLOG(5, "Building LL table"); - nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode; - LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode, - countWksp, max, mostFrequent, nbSeq, - LLFSELog, prevEntropy->litlengthCTable, - ZSTDInternalConstants::LL_defaultNorm, ZSTDInternalConstants::LL_defaultNormLog, - ZSTD_defaultAllowed, strategy); - assert(set_basic < set_compressed && set_rle < set_compressed); - assert(!(LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype, - countWksp, max, llCodeTable, nbSeq, ZSTDInternalConstants::LL_defaultNorm, ZSTDInternalConstants::LL_defaultNormLog, MaxLL, - prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable), - cTableWksp, cTableWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed"); - if (LLtype == set_compressed) - fseMetadata->lastCountSize = countSize; - op += countSize; - fseMetadata->llType = (symbolEncodingType_e) LLtype; - } } - /* build CTable for Offsets */ - { U32 Offtype; - unsigned max = MaxOff; - size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, ofCodeTable, nbSeq, workspace, wkspSize); /* can't fail */ - /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */ - ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed; - DEBUGLOG(5, "Building OF table"); - nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode; - Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode, - countWksp, max, mostFrequent, nbSeq, - OffFSELog, prevEntropy->offcodeCTable, - ZSTDInternalConstants::OF_defaultNorm, ZSTDInternalConstants::OF_defaultNormLog, - defaultPolicy, strategy); - assert(!(Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype, - countWksp, max, ofCodeTable, nbSeq, ZSTDInternalConstants::OF_defaultNorm, ZSTDInternalConstants::OF_defaultNormLog, DefaultMaxOff, - prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable), - cTableWksp, cTableWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed"); - if (Offtype == set_compressed) - fseMetadata->lastCountSize = countSize; - op += countSize; - fseMetadata->ofType = (symbolEncodingType_e) Offtype; - } } - /* build CTable for MatchLengths */ - { U32 MLtype; - unsigned max = MaxML; - size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, mlCodeTable, nbSeq, workspace, wkspSize); /* can't fail */ - DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op)); - nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode; - MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode, - countWksp, max, mostFrequent, nbSeq, - MLFSELog, prevEntropy->matchlengthCTable, - ZSTDInternalConstants::ML_defaultNorm, ZSTDInternalConstants::ML_defaultNormLog, - ZSTD_defaultAllowed, strategy); - assert(!(MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */ - { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype, - countWksp, max, mlCodeTable, nbSeq, ZSTDInternalConstants::ML_defaultNorm, ZSTDInternalConstants::ML_defaultNormLog, MaxML, - prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable), - cTableWksp, cTableWkspSize); - FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed"); - if (MLtype == set_compressed) - fseMetadata->lastCountSize = countSize; - op += countSize; - fseMetadata->mlType = (symbolEncodingType_e) MLtype; - } } - assert((size_t) (op-ostart) <= sizeof(fseMetadata->fseTablesBuffer)); - return op-ostart; -} - - -/** ZSTD_buildSuperBlockEntropy() : - * Builds entropy for the super-block. - * @return : 0 on success or error code */ -static size_t -ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr, - const ZSTD_entropyCTables_t* prevEntropy, - ZSTD_entropyCTables_t* nextEntropy, - const ZSTD_CCtx_params* cctxParams, - ZSTD_entropyCTablesMetadata_t* entropyMetadata, - void* workspace, size_t wkspSize) -{ - size_t const litSize = seqStorePtr->lit - seqStorePtr->litStart; - DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy"); - entropyMetadata->hufMetadata.hufDesSize = - ZSTD_buildSuperBlockEntropy_literal(seqStorePtr->litStart, litSize, - &prevEntropy->huf, &nextEntropy->huf, - &entropyMetadata->hufMetadata, - ZSTD_disableLiteralsCompression(cctxParams), - workspace, wkspSize); - FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildSuperBlockEntropy_literal failed"); - entropyMetadata->fseMetadata.fseTablesSize = - ZSTD_buildSuperBlockEntropy_sequences(seqStorePtr, - &prevEntropy->fse, &nextEntropy->fse, - cctxParams, - &entropyMetadata->fseMetadata, - workspace, wkspSize); - FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, "ZSTD_buildSuperBlockEntropy_sequences failed"); - return 0; -} - -/** ZSTD_compressSubBlock_literal() : - * Compresses literals section for a sub-block. - * When we have to write the Huffman table we will sometimes choose a header - * size larger than necessary. This is because we have to pick the header size - * before we know the table size + compressed size, so we have a bound on the - * table size. If we guessed incorrectly, we fall back to uncompressed literals. - * - * We write the header when writeEntropy=1 and set entropyWrriten=1 when we succeeded - * in writing the header, otherwise it is set to 0. - * - * hufMetadata->hType has literals block type info. - * If it is set_basic, all sub-blocks literals section will be Raw_Literals_Block. - * If it is set_rle, all sub-blocks literals section will be RLE_Literals_Block. - * If it is set_compressed, first sub-block's literals section will be Compressed_Literals_Block - * If it is set_compressed, first sub-block's literals section will be Treeless_Literals_Block - * and the following sub-blocks' literals sections will be Treeless_Literals_Block. - * @return : compressed size of literals section of a sub-block - * Or 0 if it unable to compress. - * Or error code */ -static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, - const ZSTD_hufCTablesMetadata_t* hufMetadata, - const BYTE* literals, size_t litSize, - void* dst, size_t dstSize, - const int bmi2, int writeEntropy, int* entropyWritten) -{ - size_t const header = writeEntropy ? 200 : 0; - size_t const lhSize = 3 + (litSize >= (1 KB - header)) + (litSize >= (16 KB - header)); - BYTE* const ostart = (BYTE*)dst; - BYTE* const oend = ostart + dstSize; - BYTE* op = ostart + lhSize; - U32 const singleStream = lhSize == 3; - symbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat; - size_t cLitSize = 0; - - (void)bmi2; /* TODO bmi2... */ - - DEBUGLOG(5, "ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)", litSize, lhSize, writeEntropy); - - *entropyWritten = 0; - if (litSize == 0 || hufMetadata->hType == set_basic) { - DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal"); - return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize); - } else if (hufMetadata->hType == set_rle) { - DEBUGLOG(5, "ZSTD_compressSubBlock_literal using rle literal"); - return ZSTD_compressRleLiteralsBlock(dst, dstSize, literals, litSize); - } - - assert(litSize > 0); - assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat); - - if (writeEntropy && hufMetadata->hType == set_compressed) { - memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize); - op += hufMetadata->hufDesSize; - cLitSize += hufMetadata->hufDesSize; - DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize); - } - - /* TODO bmi2 */ - { const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, oend-op, literals, litSize, hufTable) - : HUF_compress4X_usingCTable(op, oend-op, literals, litSize, hufTable); - op += cSize; - cLitSize += cSize; - if (cSize == 0 || ERR_isError(cSize)) { - DEBUGLOG(5, "Failed to write entropy tables %s", ZSTD_getErrorName(cSize)); - return 0; - } - /* If we expand and we aren't writing a header then emit uncompressed */ - if (!writeEntropy && cLitSize >= litSize) { - DEBUGLOG(5, "ZSTD_compressSubBlock_literal using raw literal because uncompressible"); - return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize); - } - /* If we are writing headers then allow expansion that doesn't change our header size. */ - if (lhSize < (size_t)(3 + (cLitSize >= 1 KB) + (cLitSize >= 16 KB))) { - assert(cLitSize > litSize); - DEBUGLOG(5, "Literals expanded beyond allowed header size"); - return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize); - } - DEBUGLOG(5, "ZSTD_compressSubBlock_literal (cSize=%zu)", cSize); - } - - /* Build header */ - switch(lhSize) - { - case 3: /* 2 - 2 - 10 - 10 */ - { U32 const lhc = hType + ((!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14); - MEM_writeLE24(ostart, lhc); - break; - } - case 4: /* 2 - 2 - 14 - 14 */ - { U32 const lhc = hType + (2 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<18); - MEM_writeLE32(ostart, lhc); - break; - } - case 5: /* 2 - 2 - 18 - 18 */ - { U32 const lhc = hType + (3 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<22); - MEM_writeLE32(ostart, lhc); - ostart[4] = (BYTE)(cLitSize >> 10); - break; - } - default: /* not possible : lhSize is {3,4,5} */ - assert(0); - } - *entropyWritten = 1; - DEBUGLOG(5, "Compressed literals: %u -> %u", (U32)litSize, (U32)(op-ostart)); - return op-ostart; -} - -static size_t ZSTD_seqDecompressedSize(seqStore_t const* seqStore, const seqDef* sequences, size_t nbSeq, size_t litSize, int lastSequence) { - const seqDef* const sstart = sequences; - const seqDef* const send = sequences + nbSeq; - const seqDef* sp = sstart; - size_t matchLengthSum = 0; - while (send-sp > 0) { - ZSTD_sequenceLength const seqLen = ZSTD_getSequenceLength(seqStore, sp); - matchLengthSum += seqLen.matchLength; - sp++; - } - return matchLengthSum + litSize; -} - -/** ZSTD_compressSubBlock_sequences() : - * Compresses sequences section for a sub-block. - * fseMetadata->llType, fseMetadata->ofType, and fseMetadata->mlType have - * symbol compression modes for the super-block. - * The first successfully compressed block will have these in its header. - * We set entropyWritten=1 when we succeed in compressing the sequences. - * The following sub-blocks will always have repeat mode. - * @return : compressed size of sequences section of a sub-block - * Or 0 if it is unable to compress - * Or error code. */ -static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables, - const ZSTD_fseCTablesMetadata_t* fseMetadata, - const seqDef* sequences, size_t nbSeq, - const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode, - const ZSTD_CCtx_params* cctxParams, - void* dst, size_t dstCapacity, - const int bmi2, int writeEntropy, int* entropyWritten) -{ - const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN; - BYTE* const ostart = (BYTE*)dst; - BYTE* const oend = ostart + dstCapacity; - BYTE* op = ostart; - BYTE* seqHead; - - DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (nbSeq=%zu, writeEntropy=%d, longOffsets=%d)", nbSeq, writeEntropy, longOffsets); - - *entropyWritten = 0; - /* Sequences Header */ - RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/, - dstSize_tooSmall, ""); - if (nbSeq < 0x7F) - *op++ = (BYTE)nbSeq; - else if (nbSeq < LONGNBSEQ) - op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2; - else - op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3; - if (nbSeq==0) { - return op - ostart; - } - - /* seqHead : flags for FSE encoding type */ - seqHead = op++; - - DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (seqHeadSize=%u)", (unsigned)(op-ostart)); - - if (writeEntropy) { - const U32 LLtype = fseMetadata->llType; - const U32 Offtype = fseMetadata->ofType; - const U32 MLtype = fseMetadata->mlType; - DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)", fseMetadata->fseTablesSize); - *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); - memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize); - op += fseMetadata->fseTablesSize; - } else { - const U32 repeat = set_repeat; - *seqHead = (BYTE)((repeat<<6) + (repeat<<4) + (repeat<<2)); - } - - { size_t const bitstreamSize = ZSTD_encodeSequences( - op, oend - op, - fseTables->matchlengthCTable, mlCode, - fseTables->offcodeCTable, ofCode, - fseTables->litlengthCTable, llCode, - sequences, nbSeq, - longOffsets, bmi2); - FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed"); - op += bitstreamSize; - /* zstd versions <= 1.3.4 mistakenly report corruption when - * FSE_readNCount() receives a buffer < 4 bytes. - * Fixed by https://github.com/facebook/zstd/pull/1146. - * This can happen when the last set_compressed table present is 2 - * bytes and the bitstream is only one byte. - * In this exceedingly rare case, we will simply emit an uncompressed - * block, since it isn't worth optimizing. - */ -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - if (writeEntropy && fseMetadata->lastCountSize && fseMetadata->lastCountSize + bitstreamSize < 4) { - /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */ - assert(fseMetadata->lastCountSize + bitstreamSize == 3); - DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by " - "emitting an uncompressed block."); - return 0; - } -#endif - DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (bitstreamSize=%zu)", bitstreamSize); - } - - /* zstd versions <= 1.4.0 mistakenly report error when - * sequences section body size is less than 3 bytes. - * Fixed by https://github.com/facebook/zstd/pull/1664. - * This can happen when the previous sequences section block is compressed - * with rle mode and the current block's sequences section is compressed - * with repeat mode where sequences section body size can be 1 byte. - */ -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - if (op-seqHead < 4) { - DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.4.0 by emitting " - "an uncompressed block when sequences are < 4 bytes"); - return 0; - } -#endif - - *entropyWritten = 1; - return op - ostart; -} - -/** ZSTD_compressSubBlock() : - * Compresses a single sub-block. - * @return : compressed size of the sub-block - * Or 0 if it failed to compress. */ -static size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy, - const ZSTD_entropyCTablesMetadata_t* entropyMetadata, - const seqDef* sequences, size_t nbSeq, - const BYTE* literals, size_t litSize, - const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode, - const ZSTD_CCtx_params* cctxParams, - void* dst, size_t dstCapacity, - const int bmi2, - int writeLitEntropy, int writeSeqEntropy, - int* litEntropyWritten, int* seqEntropyWritten, - U32 lastBlock) -{ - BYTE* const ostart = (BYTE*)dst; - BYTE* const oend = ostart + dstCapacity; - BYTE* op = ostart + ZSTDInternalConstants::ZSTD_blockHeaderSize; - DEBUGLOG(5, "ZSTD_compressSubBlock (litSize=%zu, nbSeq=%zu, writeLitEntropy=%d, writeSeqEntropy=%d, lastBlock=%d)", - litSize, nbSeq, writeLitEntropy, writeSeqEntropy, lastBlock); - { size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable, - &entropyMetadata->hufMetadata, literals, litSize, - op, oend-op, bmi2, writeLitEntropy, litEntropyWritten); - FORWARD_IF_ERROR(cLitSize, "ZSTD_compressSubBlock_literal failed"); - if (cLitSize == 0) return 0; - op += cLitSize; - } - { size_t cSeqSize = ZSTD_compressSubBlock_sequences(&entropy->fse, - &entropyMetadata->fseMetadata, - sequences, nbSeq, - llCode, mlCode, ofCode, - cctxParams, - op, oend-op, - bmi2, writeSeqEntropy, seqEntropyWritten); - FORWARD_IF_ERROR(cSeqSize, "ZSTD_compressSubBlock_sequences failed"); - if (cSeqSize == 0) return 0; - op += cSeqSize; - } - /* Write block header */ - { size_t cSize = (op-ostart)-ZSTDInternalConstants::ZSTD_blockHeaderSize; - U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3); - MEM_writeLE24(ostart, cBlockHeader24); - } - return op-ostart; -} - -static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t litSize, - const ZSTD_hufCTables_t* huf, - const ZSTD_hufCTablesMetadata_t* hufMetadata, - void* workspace, size_t wkspSize, - int writeEntropy) -{ - unsigned* const countWksp = (unsigned*)workspace; - unsigned maxSymbolValue = 255; - size_t literalSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */ - - if (hufMetadata->hType == set_basic) return litSize; - else if (hufMetadata->hType == set_rle) return 1; - else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) { - size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize); - if (ZSTD_isError(largest)) return litSize; - { size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue); - if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize; - return cLitSizeEstimate + literalSectionHeaderSize; - } } - assert(0); /* impossible */ - return 0; -} - -static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type, - const BYTE* codeTable, unsigned maxCode, - size_t nbSeq, const FSE_CTable* fseCTable, - const U32* additionalBits, - short const* defaultNorm, U32 defaultNormLog, - void* workspace, size_t wkspSize) -{ - unsigned* const countWksp = (unsigned*)workspace; - const BYTE* ctp = codeTable; - const BYTE* const ctStart = ctp; - const BYTE* const ctEnd = ctStart + nbSeq; - size_t cSymbolTypeSizeEstimateInBits = 0; - unsigned max = maxCode; - - HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */ - if (type == set_basic) { - cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max); - } else if (type == set_rle) { - cSymbolTypeSizeEstimateInBits = 0; - } else if (type == set_compressed || type == set_repeat) { - cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max); - } - if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) return nbSeq * 10; - while (ctp < ctEnd) { - if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp]; - else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */ - ctp++; - } - return cSymbolTypeSizeEstimateInBits / 8; -} - -static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable, - const BYTE* llCodeTable, - const BYTE* mlCodeTable, - size_t nbSeq, - const ZSTD_fseCTables_t* fseTables, - const ZSTD_fseCTablesMetadata_t* fseMetadata, - void* workspace, size_t wkspSize, - int writeEntropy) -{ - size_t sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */ - size_t cSeqSizeEstimate = 0; - cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff, - nbSeq, fseTables->offcodeCTable, NULL, - ZSTDInternalConstants::OF_defaultNorm, ZSTDInternalConstants::OF_defaultNormLog, - workspace, wkspSize); - cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL, - nbSeq, fseTables->litlengthCTable, ZSTDInternalConstants::LL_bits, - ZSTDInternalConstants::LL_defaultNorm, ZSTDInternalConstants::LL_defaultNormLog, - workspace, wkspSize); - cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML, - nbSeq, fseTables->matchlengthCTable, ZSTDInternalConstants::ML_bits, - ZSTDInternalConstants::ML_defaultNorm, ZSTDInternalConstants::ML_defaultNormLog, - workspace, wkspSize); - if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize; - return cSeqSizeEstimate + sequencesSectionHeaderSize; -} - -static size_t ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize, - const BYTE* ofCodeTable, - const BYTE* llCodeTable, - const BYTE* mlCodeTable, - size_t nbSeq, - const ZSTD_entropyCTables_t* entropy, - const ZSTD_entropyCTablesMetadata_t* entropyMetadata, - void* workspace, size_t wkspSize, - int writeLitEntropy, int writeSeqEntropy) { - size_t cSizeEstimate = 0; - cSizeEstimate += ZSTD_estimateSubBlockSize_literal(literals, litSize, - &entropy->huf, &entropyMetadata->hufMetadata, - workspace, wkspSize, writeLitEntropy); - cSizeEstimate += ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable, - nbSeq, &entropy->fse, &entropyMetadata->fseMetadata, - workspace, wkspSize, writeSeqEntropy); - return cSizeEstimate + ZSTDInternalConstants::ZSTD_blockHeaderSize; -} - -static int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMetadata) -{ - if (fseMetadata->llType == set_compressed || fseMetadata->llType == set_rle) - return 1; - if (fseMetadata->mlType == set_compressed || fseMetadata->mlType == set_rle) - return 1; - if (fseMetadata->ofType == set_compressed || fseMetadata->ofType == set_rle) - return 1; - return 0; -} - -/** ZSTD_compressSubBlock_multi() : - * Breaks super-block into multiple sub-blocks and compresses them. - * Entropy will be written to the first block. - * The following blocks will use repeat mode to compress. - * All sub-blocks are compressed blocks (no raw or rle blocks). - * @return : compressed size of the super block (which is multiple ZSTD blocks) - * Or 0 if it failed to compress. */ -static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, - const ZSTD_compressedBlockState_t* prevCBlock, - ZSTD_compressedBlockState_t* nextCBlock, - const ZSTD_entropyCTablesMetadata_t* entropyMetadata, - const ZSTD_CCtx_params* cctxParams, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const int bmi2, U32 lastBlock, - void* workspace, size_t wkspSize) -{ - const seqDef* const sstart = seqStorePtr->sequencesStart; - const seqDef* const send = seqStorePtr->sequences; - const seqDef* sp = sstart; - const BYTE* const lstart = seqStorePtr->litStart; - const BYTE* const lend = seqStorePtr->lit; - const BYTE* lp = lstart; - BYTE const* ip = (BYTE const*)src; - BYTE const* const iend = ip + srcSize; - BYTE* const ostart = (BYTE*)dst; - BYTE* const oend = ostart + dstCapacity; - BYTE* op = ostart; - const BYTE* llCodePtr = seqStorePtr->llCode; - const BYTE* mlCodePtr = seqStorePtr->mlCode; - const BYTE* ofCodePtr = seqStorePtr->ofCode; - size_t targetCBlockSize = cctxParams->targetCBlockSize; - size_t litSize, seqCount; - int writeLitEntropy = entropyMetadata->hufMetadata.hType == set_compressed; - int writeSeqEntropy = 1; - int lastSequence = 0; - - DEBUGLOG(5, "ZSTD_compressSubBlock_multi (litSize=%u, nbSeq=%u)", - (unsigned)(lend-lp), (unsigned)(send-sstart)); - - litSize = 0; - seqCount = 0; - do { - size_t cBlockSizeEstimate = 0; - if (sstart == send) { - lastSequence = 1; - } else { - const seqDef* const sequence = sp + seqCount; - lastSequence = sequence == send - 1; - litSize += ZSTD_getSequenceLength(seqStorePtr, sequence).litLength; - seqCount++; - } - if (lastSequence) { - assert(lp <= lend); - assert(litSize <= (size_t)(lend - lp)); - litSize = (size_t)(lend - lp); - } - /* I think there is an optimization opportunity here. - * Calling ZSTD_estimateSubBlockSize for every sequence can be wasteful - * since it recalculates estimate from scratch. - * For example, it would recount literal distribution and symbol codes everytime. - */ - cBlockSizeEstimate = ZSTD_estimateSubBlockSize(lp, litSize, ofCodePtr, llCodePtr, mlCodePtr, seqCount, - &nextCBlock->entropy, entropyMetadata, - workspace, wkspSize, writeLitEntropy, writeSeqEntropy); - if (cBlockSizeEstimate > targetCBlockSize || lastSequence) { - int litEntropyWritten = 0; - int seqEntropyWritten = 0; - const size_t decompressedSize = ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, lastSequence); - const size_t cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata, - sp, seqCount, - lp, litSize, - llCodePtr, mlCodePtr, ofCodePtr, - cctxParams, - op, oend-op, - bmi2, writeLitEntropy, writeSeqEntropy, - &litEntropyWritten, &seqEntropyWritten, - lastBlock && lastSequence); - FORWARD_IF_ERROR(cSize, "ZSTD_compressSubBlock failed"); - if (cSize > 0 && cSize < decompressedSize) { - DEBUGLOG(5, "Committed the sub-block"); - assert(ip + decompressedSize <= iend); - ip += decompressedSize; - sp += seqCount; - lp += litSize; - op += cSize; - llCodePtr += seqCount; - mlCodePtr += seqCount; - ofCodePtr += seqCount; - litSize = 0; - seqCount = 0; - /* Entropy only needs to be written once */ - if (litEntropyWritten) { - writeLitEntropy = 0; - } - if (seqEntropyWritten) { - writeSeqEntropy = 0; - } - } - } - } while (!lastSequence); - if (writeLitEntropy) { - DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten"); - memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf)); - } - if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) { - /* If we haven't written our entropy tables, then we've violated our contract and - * must emit an uncompressed block. - */ - DEBUGLOG(5, "ZSTD_compressSubBlock_multi has sequence entropy tables unwritten"); - return 0; - } - if (ip < iend) { - size_t const cSize = ZSTD_noCompressBlock(op, oend - op, ip, iend - ip, lastBlock); - DEBUGLOG(5, "ZSTD_compressSubBlock_multi last sub-block uncompressed, %zu bytes", (size_t)(iend - ip)); - FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed"); - assert(cSize != 0); - op += cSize; - /* We have to regenerate the repcodes because we've skipped some sequences */ - if (sp < send) { - seqDef const* seq; - repcodes_t rep; - memcpy(&rep, prevCBlock->rep, sizeof(rep)); - for (seq = sstart; seq < sp; ++seq) { - rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0); - } - memcpy(nextCBlock->rep, &rep, sizeof(rep)); - } - } - DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed"); - return op-ostart; -} - -size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, - void* dst, size_t dstCapacity, - void const* src, size_t srcSize, - unsigned lastBlock) { - ZSTD_entropyCTablesMetadata_t entropyMetadata; - - FORWARD_IF_ERROR(ZSTD_buildSuperBlockEntropy(&zc->seqStore, - &zc->blockState.prevCBlock->entropy, - &zc->blockState.nextCBlock->entropy, - &zc->appliedParams, - &entropyMetadata, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */), ""); - - return ZSTD_compressSubBlock_multi(&zc->seqStore, - zc->blockState.prevCBlock, - zc->blockState.nextCBlock, - &entropyMetadata, - &zc->appliedParams, - dst, dstCapacity, - src, srcSize, - zc->bmi2, lastBlock, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */); -} - -} diff --git a/third_party/zstd/compress/zstd_double_fast.c b/third_party/zstd/compress/zstd_double_fast.c new file mode 100644 index 00000000000..a4e9c50d3bf --- /dev/null +++ b/third_party/zstd/compress/zstd_double_fast.c @@ -0,0 +1,770 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#include "zstd_compress_internal.h" +#include "zstd_double_fast.h" + +#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR + +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_fillDoubleHashTableForCDict(ZSTD_matchState_t* ms, + void const* end, ZSTD_dictTableLoadMethod_e dtlm) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const hashLarge = ms->hashTable; + U32 const hBitsL = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS; + U32 const mls = cParams->minMatch; + U32* const hashSmall = ms->chainTable; + U32 const hBitsS = cParams->chainLog + ZSTD_SHORT_CACHE_TAG_BITS; + const BYTE* const base = ms->window.base; + const BYTE* ip = base + ms->nextToUpdate; + const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE; + const U32 fastHashFillStep = 3; + + /* Always insert every fastHashFillStep position into the hash tables. + * Insert the other positions into the large hash table if their entry + * is empty. + */ + for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) { + U32 const curr = (U32)(ip - base); + U32 i; + for (i = 0; i < fastHashFillStep; ++i) { + size_t const smHashAndTag = ZSTD_hashPtr(ip + i, hBitsS, mls); + size_t const lgHashAndTag = ZSTD_hashPtr(ip + i, hBitsL, 8); + if (i == 0) { + ZSTD_writeTaggedIndex(hashSmall, smHashAndTag, curr + i); + } + if (i == 0 || hashLarge[lgHashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS] == 0) { + ZSTD_writeTaggedIndex(hashLarge, lgHashAndTag, curr + i); + } + /* Only load extra positions for ZSTD_dtlm_full */ + if (dtlm == ZSTD_dtlm_fast) + break; + } } +} + +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_fillDoubleHashTableForCCtx(ZSTD_matchState_t* ms, + void const* end, ZSTD_dictTableLoadMethod_e dtlm) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const hashLarge = ms->hashTable; + U32 const hBitsL = cParams->hashLog; + U32 const mls = cParams->minMatch; + U32* const hashSmall = ms->chainTable; + U32 const hBitsS = cParams->chainLog; + const BYTE* const base = ms->window.base; + const BYTE* ip = base + ms->nextToUpdate; + const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE; + const U32 fastHashFillStep = 3; + + /* Always insert every fastHashFillStep position into the hash tables. + * Insert the other positions into the large hash table if their entry + * is empty. + */ + for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) { + U32 const curr = (U32)(ip - base); + U32 i; + for (i = 0; i < fastHashFillStep; ++i) { + size_t const smHash = ZSTD_hashPtr(ip + i, hBitsS, mls); + size_t const lgHash = ZSTD_hashPtr(ip + i, hBitsL, 8); + if (i == 0) + hashSmall[smHash] = curr + i; + if (i == 0 || hashLarge[lgHash] == 0) + hashLarge[lgHash] = curr + i; + /* Only load extra positions for ZSTD_dtlm_full */ + if (dtlm == ZSTD_dtlm_fast) + break; + } } +} + +void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, + const void* const end, + ZSTD_dictTableLoadMethod_e dtlm, + ZSTD_tableFillPurpose_e tfp) +{ + if (tfp == ZSTD_tfp_forCDict) { + ZSTD_fillDoubleHashTableForCDict(ms, end, dtlm); + } else { + ZSTD_fillDoubleHashTableForCCtx(ms, end, dtlm); + } +} + + +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_compressBlock_doubleFast_noDict_generic( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize, U32 const mls /* template */) +{ + ZSTD_compressionParameters const* cParams = &ms->cParams; + U32* const hashLong = ms->hashTable; + const U32 hBitsL = cParams->hashLog; + U32* const hashSmall = ms->chainTable; + const U32 hBitsS = cParams->chainLog; + const BYTE* const base = ms->window.base; + const BYTE* const istart = (const BYTE*)src; + const BYTE* anchor = istart; + const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); + /* presumes that, if there is a dictionary, it must be using Attach mode */ + const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); + const BYTE* const prefixLowest = base + prefixLowestIndex; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = iend - HASH_READ_SIZE; + U32 offset_1=rep[0], offset_2=rep[1]; + U32 offsetSaved1 = 0, offsetSaved2 = 0; + + size_t mLength; + U32 offset; + U32 curr; + + /* how many positions to search before increasing step size */ + const size_t kStepIncr = 1 << kSearchStrength; + /* the position at which to increment the step size if no match is found */ + const BYTE* nextStep; + size_t step; /* the current step size */ + + size_t hl0; /* the long hash at ip */ + size_t hl1; /* the long hash at ip1 */ + + U32 idxl0; /* the long match index for ip */ + U32 idxl1; /* the long match index for ip1 */ + + const BYTE* matchl0; /* the long match for ip */ + const BYTE* matchs0; /* the short match for ip */ + const BYTE* matchl1; /* the long match for ip1 */ + + const BYTE* ip = istart; /* the current position */ + const BYTE* ip1; /* the next position */ + + DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_noDict_generic"); + + /* init */ + ip += ((ip - prefixLowest) == 0); + { + U32 const current = (U32)(ip - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog); + U32 const maxRep = current - windowLow; + if (offset_2 > maxRep) offsetSaved2 = offset_2, offset_2 = 0; + if (offset_1 > maxRep) offsetSaved1 = offset_1, offset_1 = 0; + } + + /* Outer Loop: one iteration per match found and stored */ + while (1) { + step = 1; + nextStep = ip + kStepIncr; + ip1 = ip + step; + + if (ip1 > ilimit) { + goto _cleanup; + } + + hl0 = ZSTD_hashPtr(ip, hBitsL, 8); + idxl0 = hashLong[hl0]; + matchl0 = base + idxl0; + + /* Inner Loop: one iteration per search / position */ + do { + const size_t hs0 = ZSTD_hashPtr(ip, hBitsS, mls); + const U32 idxs0 = hashSmall[hs0]; + curr = (U32)(ip-base); + matchs0 = base + idxs0; + + hashLong[hl0] = hashSmall[hs0] = curr; /* update hash tables */ + + /* check noDict repcode */ + if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) { + mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4; + ip++; + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength); + goto _match_stored; + } + + hl1 = ZSTD_hashPtr(ip1, hBitsL, 8); + + if (idxl0 > prefixLowestIndex) { + /* check prefix long match */ + if (MEM_read64(matchl0) == MEM_read64(ip)) { + mLength = ZSTD_count(ip+8, matchl0+8, iend) + 8; + offset = (U32)(ip-matchl0); + while (((ip>anchor) & (matchl0>prefixLowest)) && (ip[-1] == matchl0[-1])) { ip--; matchl0--; mLength++; } /* catch up */ + goto _match_found; + } + } + + idxl1 = hashLong[hl1]; + matchl1 = base + idxl1; + + if (idxs0 > prefixLowestIndex) { + /* check prefix short match */ + if (MEM_read32(matchs0) == MEM_read32(ip)) { + goto _search_next_long; + } + } + + if (ip1 >= nextStep) { + PREFETCH_L1(ip1 + 64); + PREFETCH_L1(ip1 + 128); + step++; + nextStep += kStepIncr; + } + ip = ip1; + ip1 += step; + + hl0 = hl1; + idxl0 = idxl1; + matchl0 = matchl1; + #if defined(__aarch64__) + PREFETCH_L1(ip+256); + #endif + } while (ip1 <= ilimit); + +_cleanup: + /* If offset_1 started invalid (offsetSaved1 != 0) and became valid (offset_1 != 0), + * rotate saved offsets. See comment in ZSTD_compressBlock_fast_noDict for more context. */ + offsetSaved2 = ((offsetSaved1 != 0) && (offset_1 != 0)) ? offsetSaved1 : offsetSaved2; + + /* save reps for next block */ + rep[0] = offset_1 ? offset_1 : offsetSaved1; + rep[1] = offset_2 ? offset_2 : offsetSaved2; + + /* Return the last literals size */ + return (size_t)(iend - anchor); + +_search_next_long: + + /* check prefix long +1 match */ + if (idxl1 > prefixLowestIndex) { + if (MEM_read64(matchl1) == MEM_read64(ip1)) { + ip = ip1; + mLength = ZSTD_count(ip+8, matchl1+8, iend) + 8; + offset = (U32)(ip-matchl1); + while (((ip>anchor) & (matchl1>prefixLowest)) && (ip[-1] == matchl1[-1])) { ip--; matchl1--; mLength++; } /* catch up */ + goto _match_found; + } + } + + /* if no long +1 match, explore the short match we found */ + mLength = ZSTD_count(ip+4, matchs0+4, iend) + 4; + offset = (U32)(ip - matchs0); + while (((ip>anchor) & (matchs0>prefixLowest)) && (ip[-1] == matchs0[-1])) { ip--; matchs0--; mLength++; } /* catch up */ + + /* fall-through */ + +_match_found: /* requires ip, offset, mLength */ + offset_2 = offset_1; + offset_1 = offset; + + if (step < 4) { + /* It is unsafe to write this value back to the hashtable when ip1 is + * greater than or equal to the new ip we will have after we're done + * processing this match. Rather than perform that test directly + * (ip1 >= ip + mLength), which costs speed in practice, we do a simpler + * more predictable test. The minmatch even if we take a short match is + * 4 bytes, so as long as step, the distance between ip and ip1 + * (initially) is less than 4, we know ip1 < new ip. */ + hashLong[hl1] = (U32)(ip1 - base); + } + + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength); + +_match_stored: + /* match found */ + ip += mLength; + anchor = ip; + + if (ip <= ilimit) { + /* Complementary insertion */ + /* done after iLimit test, as candidates could be > iend-8 */ + { U32 const indexToInsert = curr+2; + hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; + hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); + hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; + hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base); + } + + /* check immediate repcode */ + while ( (ip <= ilimit) + && ( (offset_2>0) + & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) { + /* store sequence */ + size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4; + U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */ + hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base); + hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base); + ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, rLength); + ip += rLength; + anchor = ip; + continue; /* faster when present ... (?) */ + } + } + } +} + + +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize, + U32 const mls /* template */) +{ + ZSTD_compressionParameters const* cParams = &ms->cParams; + U32* const hashLong = ms->hashTable; + const U32 hBitsL = cParams->hashLog; + U32* const hashSmall = ms->chainTable; + const U32 hBitsS = cParams->chainLog; + const BYTE* const base = ms->window.base; + const BYTE* const istart = (const BYTE*)src; + const BYTE* ip = istart; + const BYTE* anchor = istart; + const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); + /* presumes that, if there is a dictionary, it must be using Attach mode */ + const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); + const BYTE* const prefixLowest = base + prefixLowestIndex; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = iend - HASH_READ_SIZE; + U32 offset_1=rep[0], offset_2=rep[1]; + + const ZSTD_matchState_t* const dms = ms->dictMatchState; + const ZSTD_compressionParameters* const dictCParams = &dms->cParams; + const U32* const dictHashLong = dms->hashTable; + const U32* const dictHashSmall = dms->chainTable; + const U32 dictStartIndex = dms->window.dictLimit; + const BYTE* const dictBase = dms->window.base; + const BYTE* const dictStart = dictBase + dictStartIndex; + const BYTE* const dictEnd = dms->window.nextSrc; + const U32 dictIndexDelta = prefixLowestIndex - (U32)(dictEnd - dictBase); + const U32 dictHBitsL = dictCParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS; + const U32 dictHBitsS = dictCParams->chainLog + ZSTD_SHORT_CACHE_TAG_BITS; + const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictStart)); + + DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_dictMatchState_generic"); + + /* if a dictionary is attached, it must be within window range */ + assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex); + + if (ms->prefetchCDictTables) { + size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32); + size_t const chainTableBytes = (((size_t)1) << dictCParams->chainLog) * sizeof(U32); + PREFETCH_AREA(dictHashLong, hashTableBytes); + PREFETCH_AREA(dictHashSmall, chainTableBytes); + } + + /* init */ + ip += (dictAndPrefixLength == 0); + + /* dictMatchState repCode checks don't currently handle repCode == 0 + * disabling. */ + assert(offset_1 <= dictAndPrefixLength); + assert(offset_2 <= dictAndPrefixLength); + + /* Main Search Loop */ + while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */ + size_t mLength; + U32 offset; + size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8); + size_t const h = ZSTD_hashPtr(ip, hBitsS, mls); + size_t const dictHashAndTagL = ZSTD_hashPtr(ip, dictHBitsL, 8); + size_t const dictHashAndTagS = ZSTD_hashPtr(ip, dictHBitsS, mls); + U32 const dictMatchIndexAndTagL = dictHashLong[dictHashAndTagL >> ZSTD_SHORT_CACHE_TAG_BITS]; + U32 const dictMatchIndexAndTagS = dictHashSmall[dictHashAndTagS >> ZSTD_SHORT_CACHE_TAG_BITS]; + int const dictTagsMatchL = ZSTD_comparePackedTags(dictMatchIndexAndTagL, dictHashAndTagL); + int const dictTagsMatchS = ZSTD_comparePackedTags(dictMatchIndexAndTagS, dictHashAndTagS); + U32 const curr = (U32)(ip-base); + U32 const matchIndexL = hashLong[h2]; + U32 matchIndexS = hashSmall[h]; + const BYTE* matchLong = base + matchIndexL; + const BYTE* match = base + matchIndexS; + const U32 repIndex = curr + 1 - offset_1; + const BYTE* repMatch = (repIndex < prefixLowestIndex) ? + dictBase + (repIndex - dictIndexDelta) : + base + repIndex; + hashLong[h2] = hashSmall[h] = curr; /* update hash tables */ + + /* check repcode */ + if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) + && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { + const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; + mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; + ip++; + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength); + goto _match_stored; + } + + if (matchIndexL > prefixLowestIndex) { + /* check prefix long match */ + if (MEM_read64(matchLong) == MEM_read64(ip)) { + mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8; + offset = (U32)(ip-matchLong); + while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */ + goto _match_found; + } + } else if (dictTagsMatchL) { + /* check dictMatchState long match */ + U32 const dictMatchIndexL = dictMatchIndexAndTagL >> ZSTD_SHORT_CACHE_TAG_BITS; + const BYTE* dictMatchL = dictBase + dictMatchIndexL; + assert(dictMatchL < dictEnd); + + if (dictMatchL > dictStart && MEM_read64(dictMatchL) == MEM_read64(ip)) { + mLength = ZSTD_count_2segments(ip+8, dictMatchL+8, iend, dictEnd, prefixLowest) + 8; + offset = (U32)(curr - dictMatchIndexL - dictIndexDelta); + while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */ + goto _match_found; + } } + + if (matchIndexS > prefixLowestIndex) { + /* check prefix short match */ + if (MEM_read32(match) == MEM_read32(ip)) { + goto _search_next_long; + } + } else if (dictTagsMatchS) { + /* check dictMatchState short match */ + U32 const dictMatchIndexS = dictMatchIndexAndTagS >> ZSTD_SHORT_CACHE_TAG_BITS; + match = dictBase + dictMatchIndexS; + matchIndexS = dictMatchIndexS + dictIndexDelta; + + if (match > dictStart && MEM_read32(match) == MEM_read32(ip)) { + goto _search_next_long; + } } + + ip += ((ip-anchor) >> kSearchStrength) + 1; +#if defined(__aarch64__) + PREFETCH_L1(ip+256); +#endif + continue; + +_search_next_long: + { size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8); + size_t const dictHashAndTagL3 = ZSTD_hashPtr(ip+1, dictHBitsL, 8); + U32 const matchIndexL3 = hashLong[hl3]; + U32 const dictMatchIndexAndTagL3 = dictHashLong[dictHashAndTagL3 >> ZSTD_SHORT_CACHE_TAG_BITS]; + int const dictTagsMatchL3 = ZSTD_comparePackedTags(dictMatchIndexAndTagL3, dictHashAndTagL3); + const BYTE* matchL3 = base + matchIndexL3; + hashLong[hl3] = curr + 1; + + /* check prefix long +1 match */ + if (matchIndexL3 > prefixLowestIndex) { + if (MEM_read64(matchL3) == MEM_read64(ip+1)) { + mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8; + ip++; + offset = (U32)(ip-matchL3); + while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */ + goto _match_found; + } + } else if (dictTagsMatchL3) { + /* check dict long +1 match */ + U32 const dictMatchIndexL3 = dictMatchIndexAndTagL3 >> ZSTD_SHORT_CACHE_TAG_BITS; + const BYTE* dictMatchL3 = dictBase + dictMatchIndexL3; + assert(dictMatchL3 < dictEnd); + if (dictMatchL3 > dictStart && MEM_read64(dictMatchL3) == MEM_read64(ip+1)) { + mLength = ZSTD_count_2segments(ip+1+8, dictMatchL3+8, iend, dictEnd, prefixLowest) + 8; + ip++; + offset = (U32)(curr + 1 - dictMatchIndexL3 - dictIndexDelta); + while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */ + goto _match_found; + } } } + + /* if no long +1 match, explore the short match we found */ + if (matchIndexS < prefixLowestIndex) { + mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4; + offset = (U32)(curr - matchIndexS); + while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ + } else { + mLength = ZSTD_count(ip+4, match+4, iend) + 4; + offset = (U32)(ip - match); + while (((ip>anchor) & (match>prefixLowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ + } + +_match_found: + offset_2 = offset_1; + offset_1 = offset; + + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength); + +_match_stored: + /* match found */ + ip += mLength; + anchor = ip; + + if (ip <= ilimit) { + /* Complementary insertion */ + /* done after iLimit test, as candidates could be > iend-8 */ + { U32 const indexToInsert = curr+2; + hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; + hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); + hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; + hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base); + } + + /* check immediate repcode */ + while (ip <= ilimit) { + U32 const current2 = (U32)(ip-base); + U32 const repIndex2 = current2 - offset_2; + const BYTE* repMatch2 = repIndex2 < prefixLowestIndex ? + dictBase + repIndex2 - dictIndexDelta : + base + repIndex2; + if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */) + && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { + const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend; + size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4; + U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ + ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2); + hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2; + hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2; + ip += repLength2; + anchor = ip; + continue; + } + break; + } + } + } /* while (ip < ilimit) */ + + /* save reps for next block */ + rep[0] = offset_1; + rep[1] = offset_2; + + /* Return the last literals size */ + return (size_t)(iend - anchor); +} + +#define ZSTD_GEN_DFAST_FN(dictMode, mls) \ + static size_t ZSTD_compressBlock_doubleFast_##dictMode##_##mls( \ + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ + void const* src, size_t srcSize) \ + { \ + return ZSTD_compressBlock_doubleFast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls); \ + } + +ZSTD_GEN_DFAST_FN(noDict, 4) +ZSTD_GEN_DFAST_FN(noDict, 5) +ZSTD_GEN_DFAST_FN(noDict, 6) +ZSTD_GEN_DFAST_FN(noDict, 7) + +ZSTD_GEN_DFAST_FN(dictMatchState, 4) +ZSTD_GEN_DFAST_FN(dictMatchState, 5) +ZSTD_GEN_DFAST_FN(dictMatchState, 6) +ZSTD_GEN_DFAST_FN(dictMatchState, 7) + + +size_t ZSTD_compressBlock_doubleFast( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + const U32 mls = ms->cParams.minMatch; + switch(mls) + { + default: /* includes case 3 */ + case 4 : + return ZSTD_compressBlock_doubleFast_noDict_4(ms, seqStore, rep, src, srcSize); + case 5 : + return ZSTD_compressBlock_doubleFast_noDict_5(ms, seqStore, rep, src, srcSize); + case 6 : + return ZSTD_compressBlock_doubleFast_noDict_6(ms, seqStore, rep, src, srcSize); + case 7 : + return ZSTD_compressBlock_doubleFast_noDict_7(ms, seqStore, rep, src, srcSize); + } +} + + +size_t ZSTD_compressBlock_doubleFast_dictMatchState( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + const U32 mls = ms->cParams.minMatch; + switch(mls) + { + default: /* includes case 3 */ + case 4 : + return ZSTD_compressBlock_doubleFast_dictMatchState_4(ms, seqStore, rep, src, srcSize); + case 5 : + return ZSTD_compressBlock_doubleFast_dictMatchState_5(ms, seqStore, rep, src, srcSize); + case 6 : + return ZSTD_compressBlock_doubleFast_dictMatchState_6(ms, seqStore, rep, src, srcSize); + case 7 : + return ZSTD_compressBlock_doubleFast_dictMatchState_7(ms, seqStore, rep, src, srcSize); + } +} + + +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_compressBlock_doubleFast_extDict_generic( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize, + U32 const mls /* template */) +{ + ZSTD_compressionParameters const* cParams = &ms->cParams; + U32* const hashLong = ms->hashTable; + U32 const hBitsL = cParams->hashLog; + U32* const hashSmall = ms->chainTable; + U32 const hBitsS = cParams->chainLog; + const BYTE* const istart = (const BYTE*)src; + const BYTE* ip = istart; + const BYTE* anchor = istart; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = iend - 8; + const BYTE* const base = ms->window.base; + const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); + const U32 lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog); + const U32 dictStartIndex = lowLimit; + const U32 dictLimit = ms->window.dictLimit; + const U32 prefixStartIndex = (dictLimit > lowLimit) ? dictLimit : lowLimit; + const BYTE* const prefixStart = base + prefixStartIndex; + const BYTE* const dictBase = ms->window.dictBase; + const BYTE* const dictStart = dictBase + dictStartIndex; + const BYTE* const dictEnd = dictBase + prefixStartIndex; + U32 offset_1=rep[0], offset_2=rep[1]; + + DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_extDict_generic (srcSize=%zu)", srcSize); + + /* if extDict is invalidated due to maxDistance, switch to "regular" variant */ + if (prefixStartIndex == dictStartIndex) + return ZSTD_compressBlock_doubleFast(ms, seqStore, rep, src, srcSize); + + /* Search Loop */ + while (ip < ilimit) { /* < instead of <=, because (ip+1) */ + const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls); + const U32 matchIndex = hashSmall[hSmall]; + const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base; + const BYTE* match = matchBase + matchIndex; + + const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8); + const U32 matchLongIndex = hashLong[hLong]; + const BYTE* const matchLongBase = matchLongIndex < prefixStartIndex ? dictBase : base; + const BYTE* matchLong = matchLongBase + matchLongIndex; + + const U32 curr = (U32)(ip-base); + const U32 repIndex = curr + 1 - offset_1; /* offset_1 expected <= curr +1 */ + const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base; + const BYTE* const repMatch = repBase + repIndex; + size_t mLength; + hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */ + + if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */ + & (offset_1 <= curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */ + && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { + const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; + mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4; + ip++; + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength); + } else { + if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) { + const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend; + const BYTE* const lowMatchPtr = matchLongIndex < prefixStartIndex ? dictStart : prefixStart; + U32 offset; + mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, prefixStart) + 8; + offset = curr - matchLongIndex; + while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */ + offset_2 = offset_1; + offset_1 = offset; + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength); + + } else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) { + size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8); + U32 const matchIndex3 = hashLong[h3]; + const BYTE* const match3Base = matchIndex3 < prefixStartIndex ? dictBase : base; + const BYTE* match3 = match3Base + matchIndex3; + U32 offset; + hashLong[h3] = curr + 1; + if ( (matchIndex3 > dictStartIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) { + const BYTE* const matchEnd = matchIndex3 < prefixStartIndex ? dictEnd : iend; + const BYTE* const lowMatchPtr = matchIndex3 < prefixStartIndex ? dictStart : prefixStart; + mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, prefixStart) + 8; + ip++; + offset = curr+1 - matchIndex3; + while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */ + } else { + const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend; + const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart; + mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4; + offset = curr - matchIndex; + while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ + } + offset_2 = offset_1; + offset_1 = offset; + ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength); + + } else { + ip += ((ip-anchor) >> kSearchStrength) + 1; + continue; + } } + + /* move to next sequence start */ + ip += mLength; + anchor = ip; + + if (ip <= ilimit) { + /* Complementary insertion */ + /* done after iLimit test, as candidates could be > iend-8 */ + { U32 const indexToInsert = curr+2; + hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; + hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); + hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; + hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base); + } + + /* check immediate repcode */ + while (ip <= ilimit) { + U32 const current2 = (U32)(ip-base); + U32 const repIndex2 = current2 - offset_2; + const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2; + if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */ + & (offset_2 <= current2 - dictStartIndex)) + && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { + const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; + size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; + U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ + ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2); + hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2; + hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2; + ip += repLength2; + anchor = ip; + continue; + } + break; + } } } + + /* save reps for next block */ + rep[0] = offset_1; + rep[1] = offset_2; + + /* Return the last literals size */ + return (size_t)(iend - anchor); +} + +ZSTD_GEN_DFAST_FN(extDict, 4) +ZSTD_GEN_DFAST_FN(extDict, 5) +ZSTD_GEN_DFAST_FN(extDict, 6) +ZSTD_GEN_DFAST_FN(extDict, 7) + +size_t ZSTD_compressBlock_doubleFast_extDict( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + U32 const mls = ms->cParams.minMatch; + switch(mls) + { + default: /* includes case 3 */ + case 4 : + return ZSTD_compressBlock_doubleFast_extDict_4(ms, seqStore, rep, src, srcSize); + case 5 : + return ZSTD_compressBlock_doubleFast_extDict_5(ms, seqStore, rep, src, srcSize); + case 6 : + return ZSTD_compressBlock_doubleFast_extDict_6(ms, seqStore, rep, src, srcSize); + case 7 : + return ZSTD_compressBlock_doubleFast_extDict_7(ms, seqStore, rep, src, srcSize); + } +} + +#endif /* ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR */ diff --git a/third_party/zstd/compress/zstd_double_fast.cpp b/third_party/zstd/compress/zstd_double_fast.cpp deleted file mode 100644 index ecc1cdb7744..00000000000 --- a/third_party/zstd/compress/zstd_double_fast.cpp +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - -#include "zstd/compress/zstd_compress_internal.h" -#include "zstd/compress/zstd_double_fast.h" - -namespace duckdb_zstd { - -void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, - void const* end, ZSTD_dictTableLoadMethod_e dtlm) -{ - const ZSTD_compressionParameters* const cParams = &ms->cParams; - U32* const hashLarge = ms->hashTable; - U32 const hBitsL = cParams->hashLog; - U32 const mls = cParams->minMatch; - U32* const hashSmall = ms->chainTable; - U32 const hBitsS = cParams->chainLog; - const BYTE* const base = ms->window.base; - const BYTE* ip = base + ms->nextToUpdate; - const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE; - const U32 fastHashFillStep = 3; - - /* Always insert every fastHashFillStep position into the hash tables. - * Insert the other positions into the large hash table if their entry - * is empty. - */ - for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) { - U32 const current = (U32)(ip - base); - U32 i; - for (i = 0; i < fastHashFillStep; ++i) { - size_t const smHash = ZSTD_hashPtr(ip + i, hBitsS, mls); - size_t const lgHash = ZSTD_hashPtr(ip + i, hBitsL, 8); - if (i == 0) - hashSmall[smHash] = current + i; - if (i == 0 || hashLarge[lgHash] == 0) - hashLarge[lgHash] = current + i; - /* Only load extra positions for ZSTD_dtlm_full */ - if (dtlm == ZSTD_dtlm_fast) - break; - } } -} - - -FORCE_INLINE_TEMPLATE -size_t ZSTD_compressBlock_doubleFast_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize, - U32 const mls /* template */, ZSTD_dictMode_e const dictMode) -{ - ZSTD_compressionParameters const* cParams = &ms->cParams; - U32* const hashLong = ms->hashTable; - const U32 hBitsL = cParams->hashLog; - U32* const hashSmall = ms->chainTable; - const U32 hBitsS = cParams->chainLog; - const BYTE* const base = ms->window.base; - const BYTE* const istart = (const BYTE*)src; - const BYTE* ip = istart; - const BYTE* anchor = istart; - const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); - /* presumes that, if there is a dictionary, it must be using Attach mode */ - const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); - const BYTE* const prefixLowest = base + prefixLowestIndex; - const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - HASH_READ_SIZE; - U32 offset_1=rep[0], offset_2=rep[1]; - U32 offsetSaved = 0; - - const ZSTD_matchState_t* const dms = ms->dictMatchState; - const ZSTD_compressionParameters* const dictCParams = - dictMode == ZSTD_dictMatchState ? - &dms->cParams : NULL; - const U32* const dictHashLong = dictMode == ZSTD_dictMatchState ? - dms->hashTable : NULL; - const U32* const dictHashSmall = dictMode == ZSTD_dictMatchState ? - dms->chainTable : NULL; - const U32 dictStartIndex = dictMode == ZSTD_dictMatchState ? - dms->window.dictLimit : 0; - const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ? - dms->window.base : NULL; - const BYTE* const dictStart = dictMode == ZSTD_dictMatchState ? - dictBase + dictStartIndex : NULL; - const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ? - dms->window.nextSrc : NULL; - const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ? - prefixLowestIndex - (U32)(dictEnd - dictBase) : - 0; - const U32 dictHBitsL = dictMode == ZSTD_dictMatchState ? - dictCParams->hashLog : hBitsL; - const U32 dictHBitsS = dictMode == ZSTD_dictMatchState ? - dictCParams->chainLog : hBitsS; - const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictStart)); - - DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_generic"); - - assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState); - - /* if a dictionary is attached, it must be within window range */ - if (dictMode == ZSTD_dictMatchState) { - assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex); - } - - /* init */ - ip += (dictAndPrefixLength == 0); - if (dictMode == ZSTD_noDict) { - U32 const current = (U32)(ip - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog); - U32 const maxRep = current - windowLow; - if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0; - if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0; - } - if (dictMode == ZSTD_dictMatchState) { - /* dictMatchState repCode checks don't currently handle repCode == 0 - * disabling. */ - assert(offset_1 <= dictAndPrefixLength); - assert(offset_2 <= dictAndPrefixLength); - } - - /* Main Search Loop */ - while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */ - size_t mLength; - U32 offset; - size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8); - size_t const h = ZSTD_hashPtr(ip, hBitsS, mls); - size_t const dictHL = ZSTD_hashPtr(ip, dictHBitsL, 8); - size_t const dictHS = ZSTD_hashPtr(ip, dictHBitsS, mls); - U32 const current = (U32)(ip-base); - U32 const matchIndexL = hashLong[h2]; - U32 matchIndexS = hashSmall[h]; - const BYTE* matchLong = base + matchIndexL; - const BYTE* match = base + matchIndexS; - const U32 repIndex = current + 1 - offset_1; - const BYTE* repMatch = (dictMode == ZSTD_dictMatchState - && repIndex < prefixLowestIndex) ? - dictBase + (repIndex - dictIndexDelta) : - base + repIndex; - hashLong[h2] = hashSmall[h] = current; /* update hash tables */ - - /* check dictMatchState repcode */ - if (dictMode == ZSTD_dictMatchState - && ((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) - && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { - const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; - mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; - ip++; - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH); - goto _match_stored; - } - - /* check noDict repcode */ - if ( dictMode == ZSTD_noDict - && ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) { - mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4; - ip++; - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH); - goto _match_stored; - } - - if (matchIndexL > prefixLowestIndex) { - /* check prefix long match */ - if (MEM_read64(matchLong) == MEM_read64(ip)) { - mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8; - offset = (U32)(ip-matchLong); - while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */ - goto _match_found; - } - } else if (dictMode == ZSTD_dictMatchState) { - /* check dictMatchState long match */ - U32 const dictMatchIndexL = dictHashLong[dictHL]; - const BYTE* dictMatchL = dictBase + dictMatchIndexL; - assert(dictMatchL < dictEnd); - - if (dictMatchL > dictStart && MEM_read64(dictMatchL) == MEM_read64(ip)) { - mLength = ZSTD_count_2segments(ip+8, dictMatchL+8, iend, dictEnd, prefixLowest) + 8; - offset = (U32)(current - dictMatchIndexL - dictIndexDelta); - while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */ - goto _match_found; - } } - - if (matchIndexS > prefixLowestIndex) { - /* check prefix short match */ - if (MEM_read32(match) == MEM_read32(ip)) { - goto _search_next_long; - } - } else if (dictMode == ZSTD_dictMatchState) { - /* check dictMatchState short match */ - U32 const dictMatchIndexS = dictHashSmall[dictHS]; - match = dictBase + dictMatchIndexS; - matchIndexS = dictMatchIndexS + dictIndexDelta; - - if (match > dictStart && MEM_read32(match) == MEM_read32(ip)) { - goto _search_next_long; - } } - - ip += ((ip-anchor) >> kSearchStrength) + 1; -#if defined(__aarch64__) - PREFETCH_L1(ip+256); -#endif - continue; - -_search_next_long: - - { size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8); - size_t const dictHLNext = ZSTD_hashPtr(ip+1, dictHBitsL, 8); - U32 const matchIndexL3 = hashLong[hl3]; - const BYTE* matchL3 = base + matchIndexL3; - hashLong[hl3] = current + 1; - - /* check prefix long +1 match */ - if (matchIndexL3 > prefixLowestIndex) { - if (MEM_read64(matchL3) == MEM_read64(ip+1)) { - mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8; - ip++; - offset = (U32)(ip-matchL3); - while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */ - goto _match_found; - } - } else if (dictMode == ZSTD_dictMatchState) { - /* check dict long +1 match */ - U32 const dictMatchIndexL3 = dictHashLong[dictHLNext]; - const BYTE* dictMatchL3 = dictBase + dictMatchIndexL3; - assert(dictMatchL3 < dictEnd); - if (dictMatchL3 > dictStart && MEM_read64(dictMatchL3) == MEM_read64(ip+1)) { - mLength = ZSTD_count_2segments(ip+1+8, dictMatchL3+8, iend, dictEnd, prefixLowest) + 8; - ip++; - offset = (U32)(current + 1 - dictMatchIndexL3 - dictIndexDelta); - while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */ - goto _match_found; - } } } - - /* if no long +1 match, explore the short match we found */ - if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) { - mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4; - offset = (U32)(current - matchIndexS); - while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ - } else { - mLength = ZSTD_count(ip+4, match+4, iend) + 4; - offset = (U32)(ip - match); - while (((ip>anchor) & (match>prefixLowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ - } - - /* fall-through */ - -_match_found: - offset_2 = offset_1; - offset_1 = offset; - - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH); - -_match_stored: - /* match found */ - ip += mLength; - anchor = ip; - - if (ip <= ilimit) { - /* Complementary insertion */ - /* done after iLimit test, as candidates could be > iend-8 */ - { U32 const indexToInsert = current+2; - hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; - hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); - hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; - hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base); - } - - /* check immediate repcode */ - if (dictMode == ZSTD_dictMatchState) { - while (ip <= ilimit) { - U32 const current2 = (U32)(ip-base); - U32 const repIndex2 = current2 - offset_2; - const BYTE* repMatch2 = dictMode == ZSTD_dictMatchState - && repIndex2 < prefixLowestIndex ? - dictBase + repIndex2 - dictIndexDelta : - base + repIndex2; - if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */) - && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { - const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend; - size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4; - U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ - ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH); - hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2; - hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2; - ip += repLength2; - anchor = ip; - continue; - } - break; - } } - - if (dictMode == ZSTD_noDict) { - while ( (ip <= ilimit) - && ( (offset_2>0) - & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) { - /* store sequence */ - size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4; - U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */ - hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base); - hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base); - ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, rLength-MINMATCH); - ip += rLength; - anchor = ip; - continue; /* faster when present ... (?) */ - } } } - } /* while (ip < ilimit) */ - - /* save reps for next block */ - rep[0] = offset_1 ? offset_1 : offsetSaved; - rep[1] = offset_2 ? offset_2 : offsetSaved; - - /* Return the last literals size */ - return (size_t)(iend - anchor); -} - - -size_t ZSTD_compressBlock_doubleFast( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - const U32 mls = ms->cParams.minMatch; - switch(mls) - { - default: /* includes case 3 */ - case 4 : - return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_noDict); - case 5 : - return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_noDict); - case 6 : - return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_noDict); - case 7 : - return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_noDict); - } -} - - -size_t ZSTD_compressBlock_doubleFast_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - const U32 mls = ms->cParams.minMatch; - switch(mls) - { - default: /* includes case 3 */ - case 4 : - return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_dictMatchState); - case 5 : - return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_dictMatchState); - case 6 : - return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_dictMatchState); - case 7 : - return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_dictMatchState); - } -} - - -static size_t ZSTD_compressBlock_doubleFast_extDict_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize, - U32 const mls /* template */) -{ - ZSTD_compressionParameters const* cParams = &ms->cParams; - U32* const hashLong = ms->hashTable; - U32 const hBitsL = cParams->hashLog; - U32* const hashSmall = ms->chainTable; - U32 const hBitsS = cParams->chainLog; - const BYTE* const istart = (const BYTE*)src; - const BYTE* ip = istart; - const BYTE* anchor = istart; - const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - 8; - const BYTE* const base = ms->window.base; - const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); - const U32 lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog); - const U32 dictStartIndex = lowLimit; - const U32 dictLimit = ms->window.dictLimit; - const U32 prefixStartIndex = (dictLimit > lowLimit) ? dictLimit : lowLimit; - const BYTE* const prefixStart = base + prefixStartIndex; - const BYTE* const dictBase = ms->window.dictBase; - const BYTE* const dictStart = dictBase + dictStartIndex; - const BYTE* const dictEnd = dictBase + prefixStartIndex; - U32 offset_1=rep[0], offset_2=rep[1]; - - DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_extDict_generic (srcSize=%zu)", srcSize); - - /* if extDict is invalidated due to maxDistance, switch to "regular" variant */ - if (prefixStartIndex == dictStartIndex) - return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, mls, ZSTD_noDict); - - /* Search Loop */ - while (ip < ilimit) { /* < instead of <=, because (ip+1) */ - const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls); - const U32 matchIndex = hashSmall[hSmall]; - const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base; - const BYTE* match = matchBase + matchIndex; - - const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8); - const U32 matchLongIndex = hashLong[hLong]; - const BYTE* const matchLongBase = matchLongIndex < prefixStartIndex ? dictBase : base; - const BYTE* matchLong = matchLongBase + matchLongIndex; - - const U32 current = (U32)(ip-base); - const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */ - const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base; - const BYTE* const repMatch = repBase + repIndex; - size_t mLength; - hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */ - - if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */ - & (repIndex > dictStartIndex)) - && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { - const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; - mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4; - ip++; - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH); - } else { - if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) { - const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend; - const BYTE* const lowMatchPtr = matchLongIndex < prefixStartIndex ? dictStart : prefixStart; - U32 offset; - mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, prefixStart) + 8; - offset = current - matchLongIndex; - while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */ - offset_2 = offset_1; - offset_1 = offset; - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH); - - } else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) { - size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8); - U32 const matchIndex3 = hashLong[h3]; - const BYTE* const match3Base = matchIndex3 < prefixStartIndex ? dictBase : base; - const BYTE* match3 = match3Base + matchIndex3; - U32 offset; - hashLong[h3] = current + 1; - if ( (matchIndex3 > dictStartIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) { - const BYTE* const matchEnd = matchIndex3 < prefixStartIndex ? dictEnd : iend; - const BYTE* const lowMatchPtr = matchIndex3 < prefixStartIndex ? dictStart : prefixStart; - mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, prefixStart) + 8; - ip++; - offset = current+1 - matchIndex3; - while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */ - } else { - const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend; - const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart; - mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4; - offset = current - matchIndex; - while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ - } - offset_2 = offset_1; - offset_1 = offset; - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH); - - } else { - ip += ((ip-anchor) >> kSearchStrength) + 1; - continue; - } } - - /* move to next sequence start */ - ip += mLength; - anchor = ip; - - if (ip <= ilimit) { - /* Complementary insertion */ - /* done after iLimit test, as candidates could be > iend-8 */ - { U32 const indexToInsert = current+2; - hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; - hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); - hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; - hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base); - } - - /* check immediate repcode */ - while (ip <= ilimit) { - U32 const current2 = (U32)(ip-base); - U32 const repIndex2 = current2 - offset_2; - const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2; - if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */ - & (repIndex2 > dictStartIndex)) - && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { - const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; - size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; - U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ - ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH); - hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2; - hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2; - ip += repLength2; - anchor = ip; - continue; - } - break; - } } } - - /* save reps for next block */ - rep[0] = offset_1; - rep[1] = offset_2; - - /* Return the last literals size */ - return (size_t)(iend - anchor); -} - - -size_t ZSTD_compressBlock_doubleFast_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - U32 const mls = ms->cParams.minMatch; - switch(mls) - { - default: /* includes case 3 */ - case 4 : - return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 4); - case 5 : - return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 5); - case 6 : - return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 6); - case 7 : - return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 7); - } -} - -} diff --git a/third_party/zstd/compress/zstd_fast.c b/third_party/zstd/compress/zstd_fast.c new file mode 100644 index 00000000000..6c4554cfca7 --- /dev/null +++ b/third_party/zstd/compress/zstd_fast.c @@ -0,0 +1,968 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#include "zstd_compress_internal.h" /* ZSTD_hashPtr, ZSTD_count, ZSTD_storeSeq */ +#include "zstd_fast.h" + +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_fillHashTableForCDict(ZSTD_matchState_t* ms, + const void* const end, + ZSTD_dictTableLoadMethod_e dtlm) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const hashTable = ms->hashTable; + U32 const hBits = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS; + U32 const mls = cParams->minMatch; + const BYTE* const base = ms->window.base; + const BYTE* ip = base + ms->nextToUpdate; + const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE; + const U32 fastHashFillStep = 3; + + /* Currently, we always use ZSTD_dtlm_full for filling CDict tables. + * Feel free to remove this assert if there's a good reason! */ + assert(dtlm == ZSTD_dtlm_full); + + /* Always insert every fastHashFillStep position into the hash table. + * Insert the other positions if their hash entry is empty. + */ + for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) { + U32 const curr = (U32)(ip - base); + { size_t const hashAndTag = ZSTD_hashPtr(ip, hBits, mls); + ZSTD_writeTaggedIndex(hashTable, hashAndTag, curr); } + + if (dtlm == ZSTD_dtlm_fast) continue; + /* Only load extra positions for ZSTD_dtlm_full */ + { U32 p; + for (p = 1; p < fastHashFillStep; ++p) { + size_t const hashAndTag = ZSTD_hashPtr(ip + p, hBits, mls); + if (hashTable[hashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS] == 0) { /* not yet filled */ + ZSTD_writeTaggedIndex(hashTable, hashAndTag, curr + p); + } } } } +} + +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_fillHashTableForCCtx(ZSTD_matchState_t* ms, + const void* const end, + ZSTD_dictTableLoadMethod_e dtlm) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const hashTable = ms->hashTable; + U32 const hBits = cParams->hashLog; + U32 const mls = cParams->minMatch; + const BYTE* const base = ms->window.base; + const BYTE* ip = base + ms->nextToUpdate; + const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE; + const U32 fastHashFillStep = 3; + + /* Currently, we always use ZSTD_dtlm_fast for filling CCtx tables. + * Feel free to remove this assert if there's a good reason! */ + assert(dtlm == ZSTD_dtlm_fast); + + /* Always insert every fastHashFillStep position into the hash table. + * Insert the other positions if their hash entry is empty. + */ + for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) { + U32 const curr = (U32)(ip - base); + size_t const hash0 = ZSTD_hashPtr(ip, hBits, mls); + hashTable[hash0] = curr; + if (dtlm == ZSTD_dtlm_fast) continue; + /* Only load extra positions for ZSTD_dtlm_full */ + { U32 p; + for (p = 1; p < fastHashFillStep; ++p) { + size_t const hash = ZSTD_hashPtr(ip + p, hBits, mls); + if (hashTable[hash] == 0) { /* not yet filled */ + hashTable[hash] = curr + p; + } } } } +} + +void ZSTD_fillHashTable(ZSTD_matchState_t* ms, + const void* const end, + ZSTD_dictTableLoadMethod_e dtlm, + ZSTD_tableFillPurpose_e tfp) +{ + if (tfp == ZSTD_tfp_forCDict) { + ZSTD_fillHashTableForCDict(ms, end, dtlm); + } else { + ZSTD_fillHashTableForCCtx(ms, end, dtlm); + } +} + + +/** + * If you squint hard enough (and ignore repcodes), the search operation at any + * given position is broken into 4 stages: + * + * 1. Hash (map position to hash value via input read) + * 2. Lookup (map hash val to index via hashtable read) + * 3. Load (map index to value at that position via input read) + * 4. Compare + * + * Each of these steps involves a memory read at an address which is computed + * from the previous step. This means these steps must be sequenced and their + * latencies are cumulative. + * + * Rather than do 1->2->3->4 sequentially for a single position before moving + * onto the next, this implementation interleaves these operations across the + * next few positions: + * + * R = Repcode Read & Compare + * H = Hash + * T = Table Lookup + * M = Match Read & Compare + * + * Pos | Time --> + * ----+------------------- + * N | ... M + * N+1 | ... TM + * N+2 | R H T M + * N+3 | H TM + * N+4 | R H T M + * N+5 | H ... + * N+6 | R ... + * + * This is very much analogous to the pipelining of execution in a CPU. And just + * like a CPU, we have to dump the pipeline when we find a match (i.e., take a + * branch). + * + * When this happens, we throw away our current state, and do the following prep + * to re-enter the loop: + * + * Pos | Time --> + * ----+------------------- + * N | H T + * N+1 | H + * + * This is also the work we do at the beginning to enter the loop initially. + */ +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_compressBlock_fast_noDict_generic( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize, + U32 const mls, U32 const hasStep) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const hashTable = ms->hashTable; + U32 const hlog = cParams->hashLog; + /* support stepSize of 0 */ + size_t const stepSize = hasStep ? (cParams->targetLength + !(cParams->targetLength) + 1) : 2; + const BYTE* const base = ms->window.base; + const BYTE* const istart = (const BYTE*)src; + const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); + const U32 prefixStartIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); + const BYTE* const prefixStart = base + prefixStartIndex; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = iend - HASH_READ_SIZE; + + const BYTE* anchor = istart; + const BYTE* ip0 = istart; + const BYTE* ip1; + const BYTE* ip2; + const BYTE* ip3; + U32 current0; + + U32 rep_offset1 = rep[0]; + U32 rep_offset2 = rep[1]; + U32 offsetSaved1 = 0, offsetSaved2 = 0; + + size_t hash0; /* hash for ip0 */ + size_t hash1; /* hash for ip1 */ + U32 idx; /* match idx for ip0 */ + U32 mval; /* src value at match idx */ + + U32 offcode; + const BYTE* match0; + size_t mLength; + + /* ip0 and ip1 are always adjacent. The targetLength skipping and + * uncompressibility acceleration is applied to every other position, + * matching the behavior of #1562. step therefore represents the gap + * between pairs of positions, from ip0 to ip2 or ip1 to ip3. */ + size_t step; + const BYTE* nextStep; + const size_t kStepIncr = (1 << (kSearchStrength - 1)); + + DEBUGLOG(5, "ZSTD_compressBlock_fast_generic"); + ip0 += (ip0 == prefixStart); + { U32 const curr = (U32)(ip0 - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog); + U32 const maxRep = curr - windowLow; + if (rep_offset2 > maxRep) offsetSaved2 = rep_offset2, rep_offset2 = 0; + if (rep_offset1 > maxRep) offsetSaved1 = rep_offset1, rep_offset1 = 0; + } + + /* start each op */ +_start: /* Requires: ip0 */ + + step = stepSize; + nextStep = ip0 + kStepIncr; + + /* calculate positions, ip0 - anchor == 0, so we skip step calc */ + ip1 = ip0 + 1; + ip2 = ip0 + step; + ip3 = ip2 + 1; + + if (ip3 >= ilimit) { + goto _cleanup; + } + + hash0 = ZSTD_hashPtr(ip0, hlog, mls); + hash1 = ZSTD_hashPtr(ip1, hlog, mls); + + idx = hashTable[hash0]; + + do { + /* load repcode match for ip[2]*/ + const U32 rval = MEM_read32(ip2 - rep_offset1); + + /* write back hash table entry */ + current0 = (U32)(ip0 - base); + hashTable[hash0] = current0; + + /* check repcode at ip[2] */ + if ((MEM_read32(ip2) == rval) & (rep_offset1 > 0)) { + ip0 = ip2; + match0 = ip0 - rep_offset1; + mLength = ip0[-1] == match0[-1]; + ip0 -= mLength; + match0 -= mLength; + offcode = REPCODE1_TO_OFFBASE; + mLength += 4; + + /* First write next hash table entry; we've already calculated it. + * This write is known to be safe because the ip1 is before the + * repcode (ip2). */ + hashTable[hash1] = (U32)(ip1 - base); + + goto _match; + } + + /* load match for ip[0] */ + if (idx >= prefixStartIndex) { + mval = MEM_read32(base + idx); + } else { + mval = MEM_read32(ip0) ^ 1; /* guaranteed to not match. */ + } + + /* check match at ip[0] */ + if (MEM_read32(ip0) == mval) { + /* found a match! */ + + /* First write next hash table entry; we've already calculated it. + * This write is known to be safe because the ip1 == ip0 + 1, so + * we know we will resume searching after ip1 */ + hashTable[hash1] = (U32)(ip1 - base); + + goto _offset; + } + + /* lookup ip[1] */ + idx = hashTable[hash1]; + + /* hash ip[2] */ + hash0 = hash1; + hash1 = ZSTD_hashPtr(ip2, hlog, mls); + + /* advance to next positions */ + ip0 = ip1; + ip1 = ip2; + ip2 = ip3; + + /* write back hash table entry */ + current0 = (U32)(ip0 - base); + hashTable[hash0] = current0; + + /* load match for ip[0] */ + if (idx >= prefixStartIndex) { + mval = MEM_read32(base + idx); + } else { + mval = MEM_read32(ip0) ^ 1; /* guaranteed to not match. */ + } + + /* check match at ip[0] */ + if (MEM_read32(ip0) == mval) { + /* found a match! */ + + /* first write next hash table entry; we've already calculated it */ + if (step <= 4) { + /* We need to avoid writing an index into the hash table >= the + * position at which we will pick up our searching after we've + * taken this match. + * + * The minimum possible match has length 4, so the earliest ip0 + * can be after we take this match will be the current ip0 + 4. + * ip1 is ip0 + step - 1. If ip1 is >= ip0 + 4, we can't safely + * write this position. + */ + hashTable[hash1] = (U32)(ip1 - base); + } + + goto _offset; + } + + /* lookup ip[1] */ + idx = hashTable[hash1]; + + /* hash ip[2] */ + hash0 = hash1; + hash1 = ZSTD_hashPtr(ip2, hlog, mls); + + /* advance to next positions */ + ip0 = ip1; + ip1 = ip2; + ip2 = ip0 + step; + ip3 = ip1 + step; + + /* calculate step */ + if (ip2 >= nextStep) { + step++; + PREFETCH_L1(ip1 + 64); + PREFETCH_L1(ip1 + 128); + nextStep += kStepIncr; + } + } while (ip3 < ilimit); + +_cleanup: + /* Note that there are probably still a couple positions we could search. + * However, it seems to be a meaningful performance hit to try to search + * them. So let's not. */ + + /* When the repcodes are outside of the prefix, we set them to zero before the loop. + * When the offsets are still zero, we need to restore them after the block to have a correct + * repcode history. If only one offset was invalid, it is easy. The tricky case is when both + * offsets were invalid. We need to figure out which offset to refill with. + * - If both offsets are zero they are in the same order. + * - If both offsets are non-zero, we won't restore the offsets from `offsetSaved[12]`. + * - If only one is zero, we need to decide which offset to restore. + * - If rep_offset1 is non-zero, then rep_offset2 must be offsetSaved1. + * - It is impossible for rep_offset2 to be non-zero. + * + * So if rep_offset1 started invalid (offsetSaved1 != 0) and became valid (rep_offset1 != 0), then + * set rep[0] = rep_offset1 and rep[1] = offsetSaved1. + */ + offsetSaved2 = ((offsetSaved1 != 0) && (rep_offset1 != 0)) ? offsetSaved1 : offsetSaved2; + + /* save reps for next block */ + rep[0] = rep_offset1 ? rep_offset1 : offsetSaved1; + rep[1] = rep_offset2 ? rep_offset2 : offsetSaved2; + + /* Return the last literals size */ + return (size_t)(iend - anchor); + +_offset: /* Requires: ip0, idx */ + + /* Compute the offset code. */ + match0 = base + idx; + rep_offset2 = rep_offset1; + rep_offset1 = (U32)(ip0-match0); + offcode = OFFSET_TO_OFFBASE(rep_offset1); + mLength = 4; + + /* Count the backwards match length. */ + while (((ip0>anchor) & (match0>prefixStart)) && (ip0[-1] == match0[-1])) { + ip0--; + match0--; + mLength++; + } + +_match: /* Requires: ip0, match0, offcode */ + + /* Count the forward length. */ + mLength += ZSTD_count(ip0 + mLength, match0 + mLength, iend); + + ZSTD_storeSeq(seqStore, (size_t)(ip0 - anchor), anchor, iend, offcode, mLength); + + ip0 += mLength; + anchor = ip0; + + /* Fill table and check for immediate repcode. */ + if (ip0 <= ilimit) { + /* Fill Table */ + assert(base+current0+2 > istart); /* check base overflow */ + hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2; /* here because current+2 could be > iend-8 */ + hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base); + + if (rep_offset2 > 0) { /* rep_offset2==0 means rep_offset2 is invalidated */ + while ( (ip0 <= ilimit) && (MEM_read32(ip0) == MEM_read32(ip0 - rep_offset2)) ) { + /* store sequence */ + size_t const rLength = ZSTD_count(ip0+4, ip0+4-rep_offset2, iend) + 4; + { U32 const tmpOff = rep_offset2; rep_offset2 = rep_offset1; rep_offset1 = tmpOff; } /* swap rep_offset2 <=> rep_offset1 */ + hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base); + ip0 += rLength; + ZSTD_storeSeq(seqStore, 0 /*litLen*/, anchor, iend, REPCODE1_TO_OFFBASE, rLength); + anchor = ip0; + continue; /* faster when present (confirmed on gcc-8) ... (?) */ + } } } + + goto _start; +} + +#define ZSTD_GEN_FAST_FN(dictMode, mls, step) \ + static size_t ZSTD_compressBlock_fast_##dictMode##_##mls##_##step( \ + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \ + void const* src, size_t srcSize) \ + { \ + return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls, step); \ + } + +ZSTD_GEN_FAST_FN(noDict, 4, 1) +ZSTD_GEN_FAST_FN(noDict, 5, 1) +ZSTD_GEN_FAST_FN(noDict, 6, 1) +ZSTD_GEN_FAST_FN(noDict, 7, 1) + +ZSTD_GEN_FAST_FN(noDict, 4, 0) +ZSTD_GEN_FAST_FN(noDict, 5, 0) +ZSTD_GEN_FAST_FN(noDict, 6, 0) +ZSTD_GEN_FAST_FN(noDict, 7, 0) + +size_t ZSTD_compressBlock_fast( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + U32 const mls = ms->cParams.minMatch; + assert(ms->dictMatchState == NULL); + if (ms->cParams.targetLength > 1) { + switch(mls) + { + default: /* includes case 3 */ + case 4 : + return ZSTD_compressBlock_fast_noDict_4_1(ms, seqStore, rep, src, srcSize); + case 5 : + return ZSTD_compressBlock_fast_noDict_5_1(ms, seqStore, rep, src, srcSize); + case 6 : + return ZSTD_compressBlock_fast_noDict_6_1(ms, seqStore, rep, src, srcSize); + case 7 : + return ZSTD_compressBlock_fast_noDict_7_1(ms, seqStore, rep, src, srcSize); + } + } else { + switch(mls) + { + default: /* includes case 3 */ + case 4 : + return ZSTD_compressBlock_fast_noDict_4_0(ms, seqStore, rep, src, srcSize); + case 5 : + return ZSTD_compressBlock_fast_noDict_5_0(ms, seqStore, rep, src, srcSize); + case 6 : + return ZSTD_compressBlock_fast_noDict_6_0(ms, seqStore, rep, src, srcSize); + case 7 : + return ZSTD_compressBlock_fast_noDict_7_0(ms, seqStore, rep, src, srcSize); + } + + } +} + +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_compressBlock_fast_dictMatchState_generic( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize, U32 const mls, U32 const hasStep) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const hashTable = ms->hashTable; + U32 const hlog = cParams->hashLog; + /* support stepSize of 0 */ + U32 const stepSize = cParams->targetLength + !(cParams->targetLength); + const BYTE* const base = ms->window.base; + const BYTE* const istart = (const BYTE*)src; + const BYTE* ip0 = istart; + const BYTE* ip1 = ip0 + stepSize; /* we assert below that stepSize >= 1 */ + const BYTE* anchor = istart; + const U32 prefixStartIndex = ms->window.dictLimit; + const BYTE* const prefixStart = base + prefixStartIndex; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = iend - HASH_READ_SIZE; + U32 offset_1=rep[0], offset_2=rep[1]; + + const ZSTD_matchState_t* const dms = ms->dictMatchState; + const ZSTD_compressionParameters* const dictCParams = &dms->cParams ; + const U32* const dictHashTable = dms->hashTable; + const U32 dictStartIndex = dms->window.dictLimit; + const BYTE* const dictBase = dms->window.base; + const BYTE* const dictStart = dictBase + dictStartIndex; + const BYTE* const dictEnd = dms->window.nextSrc; + const U32 dictIndexDelta = prefixStartIndex - (U32)(dictEnd - dictBase); + const U32 dictAndPrefixLength = (U32)(istart - prefixStart + dictEnd - dictStart); + const U32 dictHBits = dictCParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS; + + /* if a dictionary is still attached, it necessarily means that + * it is within window size. So we just check it. */ + const U32 maxDistance = 1U << cParams->windowLog; + const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); + assert(endIndex - prefixStartIndex <= maxDistance); + (void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */ + + (void)hasStep; /* not currently specialized on whether it's accelerated */ + + /* ensure there will be no underflow + * when translating a dict index into a local index */ + assert(prefixStartIndex >= (U32)(dictEnd - dictBase)); + + if (ms->prefetchCDictTables) { + size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32); + PREFETCH_AREA(dictHashTable, hashTableBytes); + } + + /* init */ + DEBUGLOG(5, "ZSTD_compressBlock_fast_dictMatchState_generic"); + ip0 += (dictAndPrefixLength == 0); + /* dictMatchState repCode checks don't currently handle repCode == 0 + * disabling. */ + assert(offset_1 <= dictAndPrefixLength); + assert(offset_2 <= dictAndPrefixLength); + + /* Outer search loop */ + assert(stepSize >= 1); + while (ip1 <= ilimit) { /* repcode check at (ip0 + 1) is safe because ip0 < ip1 */ + size_t mLength; + size_t hash0 = ZSTD_hashPtr(ip0, hlog, mls); + + size_t const dictHashAndTag0 = ZSTD_hashPtr(ip0, dictHBits, mls); + U32 dictMatchIndexAndTag = dictHashTable[dictHashAndTag0 >> ZSTD_SHORT_CACHE_TAG_BITS]; + int dictTagsMatch = ZSTD_comparePackedTags(dictMatchIndexAndTag, dictHashAndTag0); + + U32 matchIndex = hashTable[hash0]; + U32 curr = (U32)(ip0 - base); + size_t step = stepSize; + const size_t kStepIncr = 1 << kSearchStrength; + const BYTE* nextStep = ip0 + kStepIncr; + + /* Inner search loop */ + while (1) { + const BYTE* match = base + matchIndex; + const U32 repIndex = curr + 1 - offset_1; + const BYTE* repMatch = (repIndex < prefixStartIndex) ? + dictBase + (repIndex - dictIndexDelta) : + base + repIndex; + const size_t hash1 = ZSTD_hashPtr(ip1, hlog, mls); + size_t const dictHashAndTag1 = ZSTD_hashPtr(ip1, dictHBits, mls); + hashTable[hash0] = curr; /* update hash table */ + + if (((U32) ((prefixStartIndex - 1) - repIndex) >= + 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */ + && (MEM_read32(repMatch) == MEM_read32(ip0 + 1))) { + const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; + mLength = ZSTD_count_2segments(ip0 + 1 + 4, repMatch + 4, iend, repMatchEnd, prefixStart) + 4; + ip0++; + ZSTD_storeSeq(seqStore, (size_t) (ip0 - anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength); + break; + } + + if (dictTagsMatch) { + /* Found a possible dict match */ + const U32 dictMatchIndex = dictMatchIndexAndTag >> ZSTD_SHORT_CACHE_TAG_BITS; + const BYTE* dictMatch = dictBase + dictMatchIndex; + if (dictMatchIndex > dictStartIndex && + MEM_read32(dictMatch) == MEM_read32(ip0)) { + /* To replicate extDict parse behavior, we only use dict matches when the normal matchIndex is invalid */ + if (matchIndex <= prefixStartIndex) { + U32 const offset = (U32) (curr - dictMatchIndex - dictIndexDelta); + mLength = ZSTD_count_2segments(ip0 + 4, dictMatch + 4, iend, dictEnd, prefixStart) + 4; + while (((ip0 > anchor) & (dictMatch > dictStart)) + && (ip0[-1] == dictMatch[-1])) { + ip0--; + dictMatch--; + mLength++; + } /* catch up */ + offset_2 = offset_1; + offset_1 = offset; + ZSTD_storeSeq(seqStore, (size_t) (ip0 - anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength); + break; + } + } + } + + if (matchIndex > prefixStartIndex && MEM_read32(match) == MEM_read32(ip0)) { + /* found a regular match */ + U32 const offset = (U32) (ip0 - match); + mLength = ZSTD_count(ip0 + 4, match + 4, iend) + 4; + while (((ip0 > anchor) & (match > prefixStart)) + && (ip0[-1] == match[-1])) { + ip0--; + match--; + mLength++; + } /* catch up */ + offset_2 = offset_1; + offset_1 = offset; + ZSTD_storeSeq(seqStore, (size_t) (ip0 - anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength); + break; + } + + /* Prepare for next iteration */ + dictMatchIndexAndTag = dictHashTable[dictHashAndTag1 >> ZSTD_SHORT_CACHE_TAG_BITS]; + dictTagsMatch = ZSTD_comparePackedTags(dictMatchIndexAndTag, dictHashAndTag1); + matchIndex = hashTable[hash1]; + + if (ip1 >= nextStep) { + step++; + nextStep += kStepIncr; + } + ip0 = ip1; + ip1 = ip1 + step; + if (ip1 > ilimit) goto _cleanup; + + curr = (U32)(ip0 - base); + hash0 = hash1; + } /* end inner search loop */ + + /* match found */ + assert(mLength); + ip0 += mLength; + anchor = ip0; + + if (ip0 <= ilimit) { + /* Fill Table */ + assert(base+curr+2 > istart); /* check base overflow */ + hashTable[ZSTD_hashPtr(base+curr+2, hlog, mls)] = curr+2; /* here because curr+2 could be > iend-8 */ + hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base); + + /* check immediate repcode */ + while (ip0 <= ilimit) { + U32 const current2 = (U32)(ip0-base); + U32 const repIndex2 = current2 - offset_2; + const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? + dictBase - dictIndexDelta + repIndex2 : + base + repIndex2; + if ( ((U32)((prefixStartIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */) + && (MEM_read32(repMatch2) == MEM_read32(ip0))) { + const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; + size_t const repLength2 = ZSTD_count_2segments(ip0+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; + U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ + ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2); + hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = current2; + ip0 += repLength2; + anchor = ip0; + continue; + } + break; + } + } + + /* Prepare for next iteration */ + assert(ip0 == anchor); + ip1 = ip0 + stepSize; + } + +_cleanup: + /* save reps for next block */ + rep[0] = offset_1; + rep[1] = offset_2; + + /* Return the last literals size */ + return (size_t)(iend - anchor); +} + + +ZSTD_GEN_FAST_FN(dictMatchState, 4, 0) +ZSTD_GEN_FAST_FN(dictMatchState, 5, 0) +ZSTD_GEN_FAST_FN(dictMatchState, 6, 0) +ZSTD_GEN_FAST_FN(dictMatchState, 7, 0) + +size_t ZSTD_compressBlock_fast_dictMatchState( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + U32 const mls = ms->cParams.minMatch; + assert(ms->dictMatchState != NULL); + switch(mls) + { + default: /* includes case 3 */ + case 4 : + return ZSTD_compressBlock_fast_dictMatchState_4_0(ms, seqStore, rep, src, srcSize); + case 5 : + return ZSTD_compressBlock_fast_dictMatchState_5_0(ms, seqStore, rep, src, srcSize); + case 6 : + return ZSTD_compressBlock_fast_dictMatchState_6_0(ms, seqStore, rep, src, srcSize); + case 7 : + return ZSTD_compressBlock_fast_dictMatchState_7_0(ms, seqStore, rep, src, srcSize); + } +} + + +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_compressBlock_fast_extDict_generic( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize, U32 const mls, U32 const hasStep) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const hashTable = ms->hashTable; + U32 const hlog = cParams->hashLog; + /* support stepSize of 0 */ + size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1; + const BYTE* const base = ms->window.base; + const BYTE* const dictBase = ms->window.dictBase; + const BYTE* const istart = (const BYTE*)src; + const BYTE* anchor = istart; + const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); + const U32 lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog); + const U32 dictStartIndex = lowLimit; + const BYTE* const dictStart = dictBase + dictStartIndex; + const U32 dictLimit = ms->window.dictLimit; + const U32 prefixStartIndex = dictLimit < lowLimit ? lowLimit : dictLimit; + const BYTE* const prefixStart = base + prefixStartIndex; + const BYTE* const dictEnd = dictBase + prefixStartIndex; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = iend - 8; + U32 offset_1=rep[0], offset_2=rep[1]; + U32 offsetSaved1 = 0, offsetSaved2 = 0; + + const BYTE* ip0 = istart; + const BYTE* ip1; + const BYTE* ip2; + const BYTE* ip3; + U32 current0; + + + size_t hash0; /* hash for ip0 */ + size_t hash1; /* hash for ip1 */ + U32 idx; /* match idx for ip0 */ + const BYTE* idxBase; /* base pointer for idx */ + + U32 offcode; + const BYTE* match0; + size_t mLength; + const BYTE* matchEnd = 0; /* initialize to avoid warning, assert != 0 later */ + + size_t step; + const BYTE* nextStep; + const size_t kStepIncr = (1 << (kSearchStrength - 1)); + + (void)hasStep; /* not currently specialized on whether it's accelerated */ + + DEBUGLOG(5, "ZSTD_compressBlock_fast_extDict_generic (offset_1=%u)", offset_1); + + /* switch to "regular" variant if extDict is invalidated due to maxDistance */ + if (prefixStartIndex == dictStartIndex) + return ZSTD_compressBlock_fast(ms, seqStore, rep, src, srcSize); + + { U32 const curr = (U32)(ip0 - base); + U32 const maxRep = curr - dictStartIndex; + if (offset_2 >= maxRep) offsetSaved2 = offset_2, offset_2 = 0; + if (offset_1 >= maxRep) offsetSaved1 = offset_1, offset_1 = 0; + } + + /* start each op */ +_start: /* Requires: ip0 */ + + step = stepSize; + nextStep = ip0 + kStepIncr; + + /* calculate positions, ip0 - anchor == 0, so we skip step calc */ + ip1 = ip0 + 1; + ip2 = ip0 + step; + ip3 = ip2 + 1; + + if (ip3 >= ilimit) { + goto _cleanup; + } + + hash0 = ZSTD_hashPtr(ip0, hlog, mls); + hash1 = ZSTD_hashPtr(ip1, hlog, mls); + + idx = hashTable[hash0]; + idxBase = idx < prefixStartIndex ? dictBase : base; + + do { + { /* load repcode match for ip[2] */ + U32 const current2 = (U32)(ip2 - base); + U32 const repIndex = current2 - offset_1; + const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base; + U32 rval; + if ( ((U32)(prefixStartIndex - repIndex) >= 4) /* intentional underflow */ + & (offset_1 > 0) ) { + rval = MEM_read32(repBase + repIndex); + } else { + rval = MEM_read32(ip2) ^ 1; /* guaranteed to not match. */ + } + + /* write back hash table entry */ + current0 = (U32)(ip0 - base); + hashTable[hash0] = current0; + + /* check repcode at ip[2] */ + if (MEM_read32(ip2) == rval) { + ip0 = ip2; + match0 = repBase + repIndex; + matchEnd = repIndex < prefixStartIndex ? dictEnd : iend; + assert((match0 != prefixStart) & (match0 != dictStart)); + mLength = ip0[-1] == match0[-1]; + ip0 -= mLength; + match0 -= mLength; + offcode = REPCODE1_TO_OFFBASE; + mLength += 4; + goto _match; + } } + + { /* load match for ip[0] */ + U32 const mval = idx >= dictStartIndex ? + MEM_read32(idxBase + idx) : + MEM_read32(ip0) ^ 1; /* guaranteed not to match */ + + /* check match at ip[0] */ + if (MEM_read32(ip0) == mval) { + /* found a match! */ + goto _offset; + } } + + /* lookup ip[1] */ + idx = hashTable[hash1]; + idxBase = idx < prefixStartIndex ? dictBase : base; + + /* hash ip[2] */ + hash0 = hash1; + hash1 = ZSTD_hashPtr(ip2, hlog, mls); + + /* advance to next positions */ + ip0 = ip1; + ip1 = ip2; + ip2 = ip3; + + /* write back hash table entry */ + current0 = (U32)(ip0 - base); + hashTable[hash0] = current0; + + { /* load match for ip[0] */ + U32 const mval = idx >= dictStartIndex ? + MEM_read32(idxBase + idx) : + MEM_read32(ip0) ^ 1; /* guaranteed not to match */ + + /* check match at ip[0] */ + if (MEM_read32(ip0) == mval) { + /* found a match! */ + goto _offset; + } } + + /* lookup ip[1] */ + idx = hashTable[hash1]; + idxBase = idx < prefixStartIndex ? dictBase : base; + + /* hash ip[2] */ + hash0 = hash1; + hash1 = ZSTD_hashPtr(ip2, hlog, mls); + + /* advance to next positions */ + ip0 = ip1; + ip1 = ip2; + ip2 = ip0 + step; + ip3 = ip1 + step; + + /* calculate step */ + if (ip2 >= nextStep) { + step++; + PREFETCH_L1(ip1 + 64); + PREFETCH_L1(ip1 + 128); + nextStep += kStepIncr; + } + } while (ip3 < ilimit); + +_cleanup: + /* Note that there are probably still a couple positions we could search. + * However, it seems to be a meaningful performance hit to try to search + * them. So let's not. */ + + /* If offset_1 started invalid (offsetSaved1 != 0) and became valid (offset_1 != 0), + * rotate saved offsets. See comment in ZSTD_compressBlock_fast_noDict for more context. */ + offsetSaved2 = ((offsetSaved1 != 0) && (offset_1 != 0)) ? offsetSaved1 : offsetSaved2; + + /* save reps for next block */ + rep[0] = offset_1 ? offset_1 : offsetSaved1; + rep[1] = offset_2 ? offset_2 : offsetSaved2; + + /* Return the last literals size */ + return (size_t)(iend - anchor); + +_offset: /* Requires: ip0, idx, idxBase */ + + /* Compute the offset code. */ + { U32 const offset = current0 - idx; + const BYTE* const lowMatchPtr = idx < prefixStartIndex ? dictStart : prefixStart; + matchEnd = idx < prefixStartIndex ? dictEnd : iend; + match0 = idxBase + idx; + offset_2 = offset_1; + offset_1 = offset; + offcode = OFFSET_TO_OFFBASE(offset); + mLength = 4; + + /* Count the backwards match length. */ + while (((ip0>anchor) & (match0>lowMatchPtr)) && (ip0[-1] == match0[-1])) { + ip0--; + match0--; + mLength++; + } } + +_match: /* Requires: ip0, match0, offcode, matchEnd */ + + /* Count the forward length. */ + assert(matchEnd != 0); + mLength += ZSTD_count_2segments(ip0 + mLength, match0 + mLength, iend, matchEnd, prefixStart); + + ZSTD_storeSeq(seqStore, (size_t)(ip0 - anchor), anchor, iend, offcode, mLength); + + ip0 += mLength; + anchor = ip0; + + /* write next hash table entry */ + if (ip1 < ip0) { + hashTable[hash1] = (U32)(ip1 - base); + } + + /* Fill table and check for immediate repcode. */ + if (ip0 <= ilimit) { + /* Fill Table */ + assert(base+current0+2 > istart); /* check base overflow */ + hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2; /* here because current+2 could be > iend-8 */ + hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base); + + while (ip0 <= ilimit) { + U32 const repIndex2 = (U32)(ip0-base) - offset_2; + const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2; + if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (offset_2 > 0)) /* intentional underflow */ + && (MEM_read32(repMatch2) == MEM_read32(ip0)) ) { + const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; + size_t const repLength2 = ZSTD_count_2segments(ip0+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; + { U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; } /* swap offset_2 <=> offset_1 */ + ZSTD_storeSeq(seqStore, 0 /*litlen*/, anchor, iend, REPCODE1_TO_OFFBASE, repLength2); + hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base); + ip0 += repLength2; + anchor = ip0; + continue; + } + break; + } } + + goto _start; +} + +ZSTD_GEN_FAST_FN(extDict, 4, 0) +ZSTD_GEN_FAST_FN(extDict, 5, 0) +ZSTD_GEN_FAST_FN(extDict, 6, 0) +ZSTD_GEN_FAST_FN(extDict, 7, 0) + +size_t ZSTD_compressBlock_fast_extDict( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + U32 const mls = ms->cParams.minMatch; + assert(ms->dictMatchState == NULL); + switch(mls) + { + default: /* includes case 3 */ + case 4 : + return ZSTD_compressBlock_fast_extDict_4_0(ms, seqStore, rep, src, srcSize); + case 5 : + return ZSTD_compressBlock_fast_extDict_5_0(ms, seqStore, rep, src, srcSize); + case 6 : + return ZSTD_compressBlock_fast_extDict_6_0(ms, seqStore, rep, src, srcSize); + case 7 : + return ZSTD_compressBlock_fast_extDict_7_0(ms, seqStore, rep, src, srcSize); + } +} diff --git a/third_party/zstd/compress/zstd_fast.cpp b/third_party/zstd/compress/zstd_fast.cpp deleted file mode 100644 index 31da71d8576..00000000000 --- a/third_party/zstd/compress/zstd_fast.cpp +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - -#include "zstd/compress/zstd_compress_internal.h" /* ZSTD_hashPtr, ZSTD_count, ZSTD_storeSeq */ -#include "zstd/compress/zstd_fast.h" - -namespace duckdb_zstd { - -void ZSTD_fillHashTable(ZSTD_matchState_t* ms, - const void* const end, - ZSTD_dictTableLoadMethod_e dtlm) -{ - const ZSTD_compressionParameters* const cParams = &ms->cParams; - U32* const hashTable = ms->hashTable; - U32 const hBits = cParams->hashLog; - U32 const mls = cParams->minMatch; - const BYTE* const base = ms->window.base; - const BYTE* ip = base + ms->nextToUpdate; - const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE; - const U32 fastHashFillStep = 3; - - /* Always insert every fastHashFillStep position into the hash table. - * Insert the other positions if their hash entry is empty. - */ - for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) { - U32 const current = (U32)(ip - base); - size_t const hash0 = ZSTD_hashPtr(ip, hBits, mls); - hashTable[hash0] = current; - if (dtlm == ZSTD_dtlm_fast) continue; - /* Only load extra positions for ZSTD_dtlm_full */ - { U32 p; - for (p = 1; p < fastHashFillStep; ++p) { - size_t const hash = ZSTD_hashPtr(ip + p, hBits, mls); - if (hashTable[hash] == 0) { /* not yet filled */ - hashTable[hash] = current + p; - } } } } -} - - -FORCE_INLINE_TEMPLATE size_t -ZSTD_compressBlock_fast_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize, - U32 const mls) -{ - const ZSTD_compressionParameters* const cParams = &ms->cParams; - U32* const hashTable = ms->hashTable; - U32 const hlog = cParams->hashLog; - /* support stepSize of 0 */ - size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1; - const BYTE* const base = ms->window.base; - const BYTE* const istart = (const BYTE*)src; - /* We check ip0 (ip + 0) and ip1 (ip + 1) each loop */ - const BYTE* ip0 = istart; - const BYTE* ip1; - const BYTE* anchor = istart; - const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); - const U32 prefixStartIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); - const BYTE* const prefixStart = base + prefixStartIndex; - const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - HASH_READ_SIZE; - U32 offset_1=rep[0], offset_2=rep[1]; - U32 offsetSaved = 0; - - /* init */ - DEBUGLOG(5, "ZSTD_compressBlock_fast_generic"); - ip0 += (ip0 == prefixStart); - ip1 = ip0 + 1; - { U32 const current = (U32)(ip0 - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog); - U32 const maxRep = current - windowLow; - if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0; - if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0; - } - - /* Main Search Loop */ -#ifdef __INTEL_COMPILER - /* From intel 'The vector pragma indicates that the loop should be - * vectorized if it is legal to do so'. Can be used together with - * #pragma ivdep (but have opted to exclude that because intel - * warns against using it).*/ - #pragma vector always -#endif - while (ip1 < ilimit) { /* < instead of <=, because check at ip0+2 */ - size_t mLength; - BYTE const* ip2 = ip0 + 2; - size_t const h0 = ZSTD_hashPtr(ip0, hlog, mls); - U32 const val0 = MEM_read32(ip0); - size_t const h1 = ZSTD_hashPtr(ip1, hlog, mls); - U32 const val1 = MEM_read32(ip1); - U32 const current0 = (U32)(ip0-base); - U32 const current1 = (U32)(ip1-base); - U32 const matchIndex0 = hashTable[h0]; - U32 const matchIndex1 = hashTable[h1]; - BYTE const* repMatch = ip2 - offset_1; - const BYTE* match0 = base + matchIndex0; - const BYTE* match1 = base + matchIndex1; - U32 offcode; - -#if defined(__aarch64__) - PREFETCH_L1(ip0+256); -#endif - - hashTable[h0] = current0; /* update hash table */ - hashTable[h1] = current1; /* update hash table */ - - assert(ip0 + 1 == ip1); - - if ((offset_1 > 0) & (MEM_read32(repMatch) == MEM_read32(ip2))) { - mLength = (ip2[-1] == repMatch[-1]) ? 1 : 0; - ip0 = ip2 - mLength; - match0 = repMatch - mLength; - mLength += 4; - offcode = 0; - goto _match; - } - if ((matchIndex0 > prefixStartIndex) && MEM_read32(match0) == val0) { - /* found a regular match */ - goto _offset; - } - if ((matchIndex1 > prefixStartIndex) && MEM_read32(match1) == val1) { - /* found a regular match after one literal */ - ip0 = ip1; - match0 = match1; - goto _offset; - } - { size_t const step = ((size_t)(ip0-anchor) >> (kSearchStrength - 1)) + stepSize; - assert(step >= 2); - ip0 += step; - ip1 += step; - continue; - } -_offset: /* Requires: ip0, match0 */ - /* Compute the offset code */ - offset_2 = offset_1; - offset_1 = (U32)(ip0-match0); - offcode = offset_1 + ZSTD_REP_MOVE; - mLength = 4; - /* Count the backwards match length */ - while (((ip0>anchor) & (match0>prefixStart)) - && (ip0[-1] == match0[-1])) { ip0--; match0--; mLength++; } /* catch up */ - -_match: /* Requires: ip0, match0, offcode */ - /* Count the forward length */ - mLength += ZSTD_count(ip0+mLength, match0+mLength, iend); - ZSTD_storeSeq(seqStore, (size_t)(ip0-anchor), anchor, iend, offcode, mLength-MINMATCH); - /* match found */ - ip0 += mLength; - anchor = ip0; - - if (ip0 <= ilimit) { - /* Fill Table */ - assert(base+current0+2 > istart); /* check base overflow */ - hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2; /* here because current+2 could be > iend-8 */ - hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base); - - if (offset_2 > 0) { /* offset_2==0 means offset_2 is invalidated */ - while ( (ip0 <= ilimit) && (MEM_read32(ip0) == MEM_read32(ip0 - offset_2)) ) { - /* store sequence */ - size_t const rLength = ZSTD_count(ip0+4, ip0+4-offset_2, iend) + 4; - { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */ - hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base); - ip0 += rLength; - ZSTD_storeSeq(seqStore, 0 /*litLen*/, anchor, iend, 0 /*offCode*/, rLength-MINMATCH); - anchor = ip0; - continue; /* faster when present (confirmed on gcc-8) ... (?) */ - } } } - ip1 = ip0 + 1; - } - - /* save reps for next block */ - rep[0] = offset_1 ? offset_1 : offsetSaved; - rep[1] = offset_2 ? offset_2 : offsetSaved; - - /* Return the last literals size */ - return (size_t)(iend - anchor); -} - - -size_t ZSTD_compressBlock_fast( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - U32 const mls = ms->cParams.minMatch; - assert(ms->dictMatchState == NULL); - switch(mls) - { - default: /* includes case 3 */ - case 4 : - return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4); - case 5 : - return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5); - case 6 : - return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6); - case 7 : - return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7); - } -} - -FORCE_INLINE_TEMPLATE -size_t ZSTD_compressBlock_fast_dictMatchState_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize, U32 const mls) -{ - const ZSTD_compressionParameters* const cParams = &ms->cParams; - U32* const hashTable = ms->hashTable; - U32 const hlog = cParams->hashLog; - /* support stepSize of 0 */ - U32 const stepSize = cParams->targetLength + !(cParams->targetLength); - const BYTE* const base = ms->window.base; - const BYTE* const istart = (const BYTE*)src; - const BYTE* ip = istart; - const BYTE* anchor = istart; - const U32 prefixStartIndex = ms->window.dictLimit; - const BYTE* const prefixStart = base + prefixStartIndex; - const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - HASH_READ_SIZE; - U32 offset_1=rep[0], offset_2=rep[1]; - U32 offsetSaved = 0; - - const ZSTD_matchState_t* const dms = ms->dictMatchState; - const ZSTD_compressionParameters* const dictCParams = &dms->cParams ; - const U32* const dictHashTable = dms->hashTable; - const U32 dictStartIndex = dms->window.dictLimit; - const BYTE* const dictBase = dms->window.base; - const BYTE* const dictStart = dictBase + dictStartIndex; - const BYTE* const dictEnd = dms->window.nextSrc; - const U32 dictIndexDelta = prefixStartIndex - (U32)(dictEnd - dictBase); - const U32 dictAndPrefixLength = (U32)(ip - prefixStart + dictEnd - dictStart); - const U32 dictHLog = dictCParams->hashLog; - - /* if a dictionary is still attached, it necessarily means that - * it is within window size. So we just check it. */ - const U32 maxDistance = 1U << cParams->windowLog; - const U32 endIndex = (U32)((size_t)(ip - base) + srcSize); - assert(endIndex - prefixStartIndex <= maxDistance); - (void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */ - - /* ensure there will be no no underflow - * when translating a dict index into a local index */ - assert(prefixStartIndex >= (U32)(dictEnd - dictBase)); - - /* init */ - DEBUGLOG(5, "ZSTD_compressBlock_fast_dictMatchState_generic"); - ip += (dictAndPrefixLength == 0); - /* dictMatchState repCode checks don't currently handle repCode == 0 - * disabling. */ - assert(offset_1 <= dictAndPrefixLength); - assert(offset_2 <= dictAndPrefixLength); - - /* Main Search Loop */ - while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */ - size_t mLength; - size_t const h = ZSTD_hashPtr(ip, hlog, mls); - U32 const current = (U32)(ip-base); - U32 const matchIndex = hashTable[h]; - const BYTE* match = base + matchIndex; - const U32 repIndex = current + 1 - offset_1; - const BYTE* repMatch = (repIndex < prefixStartIndex) ? - dictBase + (repIndex - dictIndexDelta) : - base + repIndex; - hashTable[h] = current; /* update hash table */ - - if ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */ - && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { - const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; - mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4; - ip++; - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH); - } else if ( (matchIndex <= prefixStartIndex) ) { - size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls); - U32 const dictMatchIndex = dictHashTable[dictHash]; - const BYTE* dictMatch = dictBase + dictMatchIndex; - if (dictMatchIndex <= dictStartIndex || - MEM_read32(dictMatch) != MEM_read32(ip)) { - assert(stepSize >= 1); - ip += ((ip-anchor) >> kSearchStrength) + stepSize; - continue; - } else { - /* found a dict match */ - U32 const offset = (U32)(current-dictMatchIndex-dictIndexDelta); - mLength = ZSTD_count_2segments(ip+4, dictMatch+4, iend, dictEnd, prefixStart) + 4; - while (((ip>anchor) & (dictMatch>dictStart)) - && (ip[-1] == dictMatch[-1])) { - ip--; dictMatch--; mLength++; - } /* catch up */ - offset_2 = offset_1; - offset_1 = offset; - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH); - } - } else if (MEM_read32(match) != MEM_read32(ip)) { - /* it's not a match, and we're not going to check the dictionary */ - assert(stepSize >= 1); - ip += ((ip-anchor) >> kSearchStrength) + stepSize; - continue; - } else { - /* found a regular match */ - U32 const offset = (U32)(ip-match); - mLength = ZSTD_count(ip+4, match+4, iend) + 4; - while (((ip>anchor) & (match>prefixStart)) - && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ - offset_2 = offset_1; - offset_1 = offset; - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH); - } - - /* match found */ - ip += mLength; - anchor = ip; - - if (ip <= ilimit) { - /* Fill Table */ - assert(base+current+2 > istart); /* check base overflow */ - hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2; /* here because current+2 could be > iend-8 */ - hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base); - - /* check immediate repcode */ - while (ip <= ilimit) { - U32 const current2 = (U32)(ip-base); - U32 const repIndex2 = current2 - offset_2; - const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? - dictBase - dictIndexDelta + repIndex2 : - base + repIndex2; - if ( ((U32)((prefixStartIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */) - && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { - const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; - size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; - U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ - ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH); - hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2; - ip += repLength2; - anchor = ip; - continue; - } - break; - } - } - } - - /* save reps for next block */ - rep[0] = offset_1 ? offset_1 : offsetSaved; - rep[1] = offset_2 ? offset_2 : offsetSaved; - - /* Return the last literals size */ - return (size_t)(iend - anchor); -} - -size_t ZSTD_compressBlock_fast_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - U32 const mls = ms->cParams.minMatch; - assert(ms->dictMatchState != NULL); - switch(mls) - { - default: /* includes case 3 */ - case 4 : - return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 4); - case 5 : - return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 5); - case 6 : - return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 6); - case 7 : - return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 7); - } -} - - -static size_t ZSTD_compressBlock_fast_extDict_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize, U32 const mls) -{ - const ZSTD_compressionParameters* const cParams = &ms->cParams; - U32* const hashTable = ms->hashTable; - U32 const hlog = cParams->hashLog; - /* support stepSize of 0 */ - U32 const stepSize = cParams->targetLength + !(cParams->targetLength); - const BYTE* const base = ms->window.base; - const BYTE* const dictBase = ms->window.dictBase; - const BYTE* const istart = (const BYTE*)src; - const BYTE* ip = istart; - const BYTE* anchor = istart; - const U32 endIndex = (U32)((size_t)(istart - base) + srcSize); - const U32 lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog); - const U32 dictStartIndex = lowLimit; - const BYTE* const dictStart = dictBase + dictStartIndex; - const U32 dictLimit = ms->window.dictLimit; - const U32 prefixStartIndex = dictLimit < lowLimit ? lowLimit : dictLimit; - const BYTE* const prefixStart = base + prefixStartIndex; - const BYTE* const dictEnd = dictBase + prefixStartIndex; - const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - 8; - U32 offset_1=rep[0], offset_2=rep[1]; - - DEBUGLOG(5, "ZSTD_compressBlock_fast_extDict_generic (offset_1=%u)", offset_1); - - /* switch to "regular" variant if extDict is invalidated due to maxDistance */ - if (prefixStartIndex == dictStartIndex) - return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, mls); - - /* Search Loop */ - while (ip < ilimit) { /* < instead of <=, because (ip+1) */ - const size_t h = ZSTD_hashPtr(ip, hlog, mls); - const U32 matchIndex = hashTable[h]; - const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base; - const BYTE* match = matchBase + matchIndex; - const U32 current = (U32)(ip-base); - const U32 repIndex = current + 1 - offset_1; - const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base; - const BYTE* const repMatch = repBase + repIndex; - hashTable[h] = current; /* update hash table */ - DEBUGLOG(7, "offset_1 = %u , current = %u", offset_1, current); - assert(offset_1 <= current +1); /* check repIndex */ - - if ( (((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > dictStartIndex)) - && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { - const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; - size_t const rLength = ZSTD_count_2segments(ip+1 +4, repMatch +4, iend, repMatchEnd, prefixStart) + 4; - ip++; - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, rLength-MINMATCH); - ip += rLength; - anchor = ip; - } else { - if ( (matchIndex < dictStartIndex) || - (MEM_read32(match) != MEM_read32(ip)) ) { - assert(stepSize >= 1); - ip += ((ip-anchor) >> kSearchStrength) + stepSize; - continue; - } - { const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend; - const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart; - U32 const offset = current - matchIndex; - size_t mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4; - while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ - offset_2 = offset_1; offset_1 = offset; /* update offset history */ - ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH); - ip += mLength; - anchor = ip; - } } - - if (ip <= ilimit) { - /* Fill Table */ - hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2; - hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base); - /* check immediate repcode */ - while (ip <= ilimit) { - U32 const current2 = (U32)(ip-base); - U32 const repIndex2 = current2 - offset_2; - const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2; - if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (repIndex2 > dictStartIndex)) /* intentional overflow */ - && (MEM_read32(repMatch2) == MEM_read32(ip)) ) { - const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; - size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4; - { U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; } /* swap offset_2 <=> offset_1 */ - ZSTD_storeSeq(seqStore, 0 /*litlen*/, anchor, iend, 0 /*offcode*/, repLength2-MINMATCH); - hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2; - ip += repLength2; - anchor = ip; - continue; - } - break; - } } } - - /* save reps for next block */ - rep[0] = offset_1; - rep[1] = offset_2; - - /* Return the last literals size */ - return (size_t)(iend - anchor); -} - - -size_t ZSTD_compressBlock_fast_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - U32 const mls = ms->cParams.minMatch; - switch(mls) - { - default: /* includes case 3 */ - case 4 : - return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 4); - case 5 : - return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 5); - case 6 : - return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 6); - case 7 : - return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 7); - } -} - -} diff --git a/third_party/zstd/compress/zstd_lazy.c b/third_party/zstd/compress/zstd_lazy.c new file mode 100644 index 00000000000..67dd55fdb80 --- /dev/null +++ b/third_party/zstd/compress/zstd_lazy.c @@ -0,0 +1,2199 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#include "zstd_compress_internal.h" +#include "zstd_lazy.h" +#include "../common/bits.h" /* ZSTD_countTrailingZeros64 */ + +#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) + +#define kLazySkippingStep 8 + + +/*-************************************* +* Binary Tree search +***************************************/ + +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_updateDUBT(ZSTD_matchState_t* ms, + const BYTE* ip, const BYTE* iend, + U32 mls) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const hashTable = ms->hashTable; + U32 const hashLog = cParams->hashLog; + + U32* const bt = ms->chainTable; + U32 const btLog = cParams->chainLog - 1; + U32 const btMask = (1 << btLog) - 1; + + const BYTE* const base = ms->window.base; + U32 const target = (U32)(ip - base); + U32 idx = ms->nextToUpdate; + + if (idx != target) + DEBUGLOG(7, "ZSTD_updateDUBT, from %u to %u (dictLimit:%u)", + idx, target, ms->window.dictLimit); + assert(ip + 8 <= iend); /* condition for ZSTD_hashPtr */ + (void)iend; + + assert(idx >= ms->window.dictLimit); /* condition for valid base+idx */ + for ( ; idx < target ; idx++) { + size_t const h = ZSTD_hashPtr(base + idx, hashLog, mls); /* assumption : ip + 8 <= iend */ + U32 const matchIndex = hashTable[h]; + + U32* const nextCandidatePtr = bt + 2*(idx&btMask); + U32* const sortMarkPtr = nextCandidatePtr + 1; + + DEBUGLOG(8, "ZSTD_updateDUBT: insert %u", idx); + hashTable[h] = idx; /* Update Hash Table */ + *nextCandidatePtr = matchIndex; /* update BT like a chain */ + *sortMarkPtr = ZSTD_DUBT_UNSORTED_MARK; + } + ms->nextToUpdate = target; +} + + +/** ZSTD_insertDUBT1() : + * sort one already inserted but unsorted position + * assumption : curr >= btlow == (curr - btmask) + * doesn't fail */ +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_insertDUBT1(const ZSTD_matchState_t* ms, + U32 curr, const BYTE* inputEnd, + U32 nbCompares, U32 btLow, + const ZSTD_dictMode_e dictMode) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const bt = ms->chainTable; + U32 const btLog = cParams->chainLog - 1; + U32 const btMask = (1 << btLog) - 1; + size_t commonLengthSmaller=0, commonLengthLarger=0; + const BYTE* const base = ms->window.base; + const BYTE* const dictBase = ms->window.dictBase; + const U32 dictLimit = ms->window.dictLimit; + const BYTE* const ip = (curr>=dictLimit) ? base + curr : dictBase + curr; + const BYTE* const iend = (curr>=dictLimit) ? inputEnd : dictBase + dictLimit; + const BYTE* const dictEnd = dictBase + dictLimit; + const BYTE* const prefixStart = base + dictLimit; + const BYTE* match; + U32* smallerPtr = bt + 2*(curr&btMask); + U32* largerPtr = smallerPtr + 1; + U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */ + U32 dummy32; /* to be nullified at the end */ + U32 const windowValid = ms->window.lowLimit; + U32 const maxDistance = 1U << cParams->windowLog; + U32 const windowLow = (curr - windowValid > maxDistance) ? curr - maxDistance : windowValid; + + + DEBUGLOG(8, "ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)", + curr, dictLimit, windowLow); + assert(curr >= btLow); + assert(ip < iend); /* condition for ZSTD_count */ + + for (; nbCompares && (matchIndex > windowLow); --nbCompares) { + U32* const nextPtr = bt + 2*(matchIndex & btMask); + size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ + assert(matchIndex < curr); + /* note : all candidates are now supposed sorted, + * but it's still possible to have nextPtr[1] == ZSTD_DUBT_UNSORTED_MARK + * when a real index has the same value as ZSTD_DUBT_UNSORTED_MARK */ + + if ( (dictMode != ZSTD_extDict) + || (matchIndex+matchLength >= dictLimit) /* both in current segment*/ + || (curr < dictLimit) /* both in extDict */) { + const BYTE* const mBase = ( (dictMode != ZSTD_extDict) + || (matchIndex+matchLength >= dictLimit)) ? + base : dictBase; + assert( (matchIndex+matchLength >= dictLimit) /* might be wrong if extDict is incorrectly set to 0 */ + || (curr < dictLimit) ); + match = mBase + matchIndex; + matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); + } else { + match = dictBase + matchIndex; + matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart); + if (matchIndex+matchLength >= dictLimit) + match = base + matchIndex; /* preparation for next read of match[matchLength] */ + } + + DEBUGLOG(8, "ZSTD_insertDUBT1: comparing %u with %u : found %u common bytes ", + curr, matchIndex, (U32)matchLength); + + if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */ + break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */ + } + + if (match[matchLength] < ip[matchLength]) { /* necessarily within buffer */ + /* match is smaller than current */ + *smallerPtr = matchIndex; /* update smaller idx */ + commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ + if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop searching */ + DEBUGLOG(8, "ZSTD_insertDUBT1: %u (>btLow=%u) is smaller : next => %u", + matchIndex, btLow, nextPtr[1]); + smallerPtr = nextPtr+1; /* new "candidate" => larger than match, which was smaller than target */ + matchIndex = nextPtr[1]; /* new matchIndex, larger than previous and closer to current */ + } else { + /* match is larger than current */ + *largerPtr = matchIndex; + commonLengthLarger = matchLength; + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop searching */ + DEBUGLOG(8, "ZSTD_insertDUBT1: %u (>btLow=%u) is larger => %u", + matchIndex, btLow, nextPtr[0]); + largerPtr = nextPtr; + matchIndex = nextPtr[0]; + } } + + *smallerPtr = *largerPtr = 0; +} + + +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_DUBT_findBetterDictMatch ( + const ZSTD_matchState_t* ms, + const BYTE* const ip, const BYTE* const iend, + size_t* offsetPtr, + size_t bestLength, + U32 nbCompares, + U32 const mls, + const ZSTD_dictMode_e dictMode) +{ + const ZSTD_matchState_t * const dms = ms->dictMatchState; + const ZSTD_compressionParameters* const dmsCParams = &dms->cParams; + const U32 * const dictHashTable = dms->hashTable; + U32 const hashLog = dmsCParams->hashLog; + size_t const h = ZSTD_hashPtr(ip, hashLog, mls); + U32 dictMatchIndex = dictHashTable[h]; + + const BYTE* const base = ms->window.base; + const BYTE* const prefixStart = base + ms->window.dictLimit; + U32 const curr = (U32)(ip-base); + const BYTE* const dictBase = dms->window.base; + const BYTE* const dictEnd = dms->window.nextSrc; + U32 const dictHighLimit = (U32)(dms->window.nextSrc - dms->window.base); + U32 const dictLowLimit = dms->window.lowLimit; + U32 const dictIndexDelta = ms->window.lowLimit - dictHighLimit; + + U32* const dictBt = dms->chainTable; + U32 const btLog = dmsCParams->chainLog - 1; + U32 const btMask = (1 << btLog) - 1; + U32 const btLow = (btMask >= dictHighLimit - dictLowLimit) ? dictLowLimit : dictHighLimit - btMask; + + size_t commonLengthSmaller=0, commonLengthLarger=0; + + (void)dictMode; + assert(dictMode == ZSTD_dictMatchState); + + for (; nbCompares && (dictMatchIndex > dictLowLimit); --nbCompares) { + U32* const nextPtr = dictBt + 2*(dictMatchIndex & btMask); + size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ + const BYTE* match = dictBase + dictMatchIndex; + matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart); + if (dictMatchIndex+matchLength >= dictHighLimit) + match = base + dictMatchIndex + dictIndexDelta; /* to prepare for next usage of match[matchLength] */ + + if (matchLength > bestLength) { + U32 matchIndex = dictMatchIndex + dictIndexDelta; + if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) { + DEBUGLOG(9, "ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)", + curr, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, OFFSET_TO_OFFBASE(curr - matchIndex), dictMatchIndex, matchIndex); + bestLength = matchLength, *offsetPtr = OFFSET_TO_OFFBASE(curr - matchIndex); + } + if (ip+matchLength == iend) { /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */ + break; /* drop, to guarantee consistency (miss a little bit of compression) */ + } + } + + if (match[matchLength] < ip[matchLength]) { + if (dictMatchIndex <= btLow) { break; } /* beyond tree size, stop the search */ + commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ + dictMatchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ + } else { + /* match is larger than current */ + if (dictMatchIndex <= btLow) { break; } /* beyond tree size, stop the search */ + commonLengthLarger = matchLength; + dictMatchIndex = nextPtr[0]; + } + } + + if (bestLength >= MINMATCH) { + U32 const mIndex = curr - (U32)OFFBASE_TO_OFFSET(*offsetPtr); (void)mIndex; + DEBUGLOG(8, "ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)", + curr, (U32)bestLength, (U32)*offsetPtr, mIndex); + } + return bestLength; + +} + + +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, + const BYTE* const ip, const BYTE* const iend, + size_t* offBasePtr, + U32 const mls, + const ZSTD_dictMode_e dictMode) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const hashTable = ms->hashTable; + U32 const hashLog = cParams->hashLog; + size_t const h = ZSTD_hashPtr(ip, hashLog, mls); + U32 matchIndex = hashTable[h]; + + const BYTE* const base = ms->window.base; + U32 const curr = (U32)(ip-base); + U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog); + + U32* const bt = ms->chainTable; + U32 const btLog = cParams->chainLog - 1; + U32 const btMask = (1 << btLog) - 1; + U32 const btLow = (btMask >= curr) ? 0 : curr - btMask; + U32 const unsortLimit = MAX(btLow, windowLow); + + U32* nextCandidate = bt + 2*(matchIndex&btMask); + U32* unsortedMark = bt + 2*(matchIndex&btMask) + 1; + U32 nbCompares = 1U << cParams->searchLog; + U32 nbCandidates = nbCompares; + U32 previousCandidate = 0; + + DEBUGLOG(7, "ZSTD_DUBT_findBestMatch (%u) ", curr); + assert(ip <= iend-8); /* required for h calculation */ + assert(dictMode != ZSTD_dedicatedDictSearch); + + /* reach end of unsorted candidates list */ + while ( (matchIndex > unsortLimit) + && (*unsortedMark == ZSTD_DUBT_UNSORTED_MARK) + && (nbCandidates > 1) ) { + DEBUGLOG(8, "ZSTD_DUBT_findBestMatch: candidate %u is unsorted", + matchIndex); + *unsortedMark = previousCandidate; /* the unsortedMark becomes a reversed chain, to move up back to original position */ + previousCandidate = matchIndex; + matchIndex = *nextCandidate; + nextCandidate = bt + 2*(matchIndex&btMask); + unsortedMark = bt + 2*(matchIndex&btMask) + 1; + nbCandidates --; + } + + /* nullify last candidate if it's still unsorted + * simplification, detrimental to compression ratio, beneficial for speed */ + if ( (matchIndex > unsortLimit) + && (*unsortedMark==ZSTD_DUBT_UNSORTED_MARK) ) { + DEBUGLOG(7, "ZSTD_DUBT_findBestMatch: nullify last unsorted candidate %u", + matchIndex); + *nextCandidate = *unsortedMark = 0; + } + + /* batch sort stacked candidates */ + matchIndex = previousCandidate; + while (matchIndex) { /* will end on matchIndex == 0 */ + U32* const nextCandidateIdxPtr = bt + 2*(matchIndex&btMask) + 1; + U32 const nextCandidateIdx = *nextCandidateIdxPtr; + ZSTD_insertDUBT1(ms, matchIndex, iend, + nbCandidates, unsortLimit, dictMode); + matchIndex = nextCandidateIdx; + nbCandidates++; + } + + /* find longest match */ + { size_t commonLengthSmaller = 0, commonLengthLarger = 0; + const BYTE* const dictBase = ms->window.dictBase; + const U32 dictLimit = ms->window.dictLimit; + const BYTE* const dictEnd = dictBase + dictLimit; + const BYTE* const prefixStart = base + dictLimit; + U32* smallerPtr = bt + 2*(curr&btMask); + U32* largerPtr = bt + 2*(curr&btMask) + 1; + U32 matchEndIdx = curr + 8 + 1; + U32 dummy32; /* to be nullified at the end */ + size_t bestLength = 0; + + matchIndex = hashTable[h]; + hashTable[h] = curr; /* Update Hash Table */ + + for (; nbCompares && (matchIndex > windowLow); --nbCompares) { + U32* const nextPtr = bt + 2*(matchIndex & btMask); + size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ + const BYTE* match; + + if ((dictMode != ZSTD_extDict) || (matchIndex+matchLength >= dictLimit)) { + match = base + matchIndex; + matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); + } else { + match = dictBase + matchIndex; + matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart); + if (matchIndex+matchLength >= dictLimit) + match = base + matchIndex; /* to prepare for next usage of match[matchLength] */ + } + + if (matchLength > bestLength) { + if (matchLength > matchEndIdx - matchIndex) + matchEndIdx = matchIndex + (U32)matchLength; + if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr - matchIndex + 1) - ZSTD_highbit32((U32)*offBasePtr)) ) + bestLength = matchLength, *offBasePtr = OFFSET_TO_OFFBASE(curr - matchIndex); + if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */ + if (dictMode == ZSTD_dictMatchState) { + nbCompares = 0; /* in addition to avoiding checking any + * further in this loop, make sure we + * skip checking in the dictionary. */ + } + break; /* drop, to guarantee consistency (miss a little bit of compression) */ + } + } + + if (match[matchLength] < ip[matchLength]) { + /* match is smaller than current */ + *smallerPtr = matchIndex; /* update smaller idx */ + commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ + if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ + matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ + } else { + /* match is larger than current */ + *largerPtr = matchIndex; + commonLengthLarger = matchLength; + if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ + largerPtr = nextPtr; + matchIndex = nextPtr[0]; + } } + + *smallerPtr = *largerPtr = 0; + + assert(nbCompares <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */ + if (dictMode == ZSTD_dictMatchState && nbCompares) { + bestLength = ZSTD_DUBT_findBetterDictMatch( + ms, ip, iend, + offBasePtr, bestLength, nbCompares, + mls, dictMode); + } + + assert(matchEndIdx > curr+8); /* ensure nextToUpdate is increased */ + ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */ + if (bestLength >= MINMATCH) { + U32 const mIndex = curr - (U32)OFFBASE_TO_OFFSET(*offBasePtr); (void)mIndex; + DEBUGLOG(8, "ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)", + curr, (U32)bestLength, (U32)*offBasePtr, mIndex); + } + return bestLength; + } +} + + +/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */ +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_BtFindBestMatch( ZSTD_matchState_t* ms, + const BYTE* const ip, const BYTE* const iLimit, + size_t* offBasePtr, + const U32 mls /* template */, + const ZSTD_dictMode_e dictMode) +{ + DEBUGLOG(7, "ZSTD_BtFindBestMatch"); + if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */ + ZSTD_updateDUBT(ms, ip, iLimit, mls); + return ZSTD_DUBT_findBestMatch(ms, ip, iLimit, offBasePtr, mls, dictMode); +} + +/*********************************** +* Dedicated dict search +***********************************/ + +void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip) +{ + const BYTE* const base = ms->window.base; + U32 const target = (U32)(ip - base); + U32* const hashTable = ms->hashTable; + U32* const chainTable = ms->chainTable; + U32 const chainSize = 1 << ms->cParams.chainLog; + U32 idx = ms->nextToUpdate; + U32 const minChain = chainSize < target - idx ? target - chainSize : idx; + U32 const bucketSize = 1 << ZSTD_LAZY_DDSS_BUCKET_LOG; + U32 const cacheSize = bucketSize - 1; + U32 const chainAttempts = (1 << ms->cParams.searchLog) - cacheSize; + U32 const chainLimit = chainAttempts > 255 ? 255 : chainAttempts; + + /* We know the hashtable is oversized by a factor of `bucketSize`. + * We are going to temporarily pretend `bucketSize == 1`, keeping only a + * single entry. We will use the rest of the space to construct a temporary + * chaintable. + */ + U32 const hashLog = ms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG; + U32* const tmpHashTable = hashTable; + U32* const tmpChainTable = hashTable + ((size_t)1 << hashLog); + U32 const tmpChainSize = (U32)((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog; + U32 const tmpMinChain = tmpChainSize < target ? target - tmpChainSize : idx; + U32 hashIdx; + + assert(ms->cParams.chainLog <= 24); + assert(ms->cParams.hashLog > ms->cParams.chainLog); + assert(idx != 0); + assert(tmpMinChain <= minChain); + + /* fill conventional hash table and conventional chain table */ + for ( ; idx < target; idx++) { + U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch); + if (idx >= tmpMinChain) { + tmpChainTable[idx - tmpMinChain] = hashTable[h]; + } + tmpHashTable[h] = idx; + } + + /* sort chains into ddss chain table */ + { + U32 chainPos = 0; + for (hashIdx = 0; hashIdx < (1U << hashLog); hashIdx++) { + U32 count; + U32 countBeyondMinChain = 0; + U32 i = tmpHashTable[hashIdx]; + for (count = 0; i >= tmpMinChain && count < cacheSize; count++) { + /* skip through the chain to the first position that won't be + * in the hash cache bucket */ + if (i < minChain) { + countBeyondMinChain++; + } + i = tmpChainTable[i - tmpMinChain]; + } + if (count == cacheSize) { + for (count = 0; count < chainLimit;) { + if (i < minChain) { + if (!i || ++countBeyondMinChain > cacheSize) { + /* only allow pulling `cacheSize` number of entries + * into the cache or chainTable beyond `minChain`, + * to replace the entries pulled out of the + * chainTable into the cache. This lets us reach + * back further without increasing the total number + * of entries in the chainTable, guaranteeing the + * DDSS chain table will fit into the space + * allocated for the regular one. */ + break; + } + } + chainTable[chainPos++] = i; + count++; + if (i < tmpMinChain) { + break; + } + i = tmpChainTable[i - tmpMinChain]; + } + } else { + count = 0; + } + if (count) { + tmpHashTable[hashIdx] = ((chainPos - count) << 8) + count; + } else { + tmpHashTable[hashIdx] = 0; + } + } + assert(chainPos <= chainSize); /* I believe this is guaranteed... */ + } + + /* move chain pointers into the last entry of each hash bucket */ + for (hashIdx = (1 << hashLog); hashIdx; ) { + U32 const bucketIdx = --hashIdx << ZSTD_LAZY_DDSS_BUCKET_LOG; + U32 const chainPackedPointer = tmpHashTable[hashIdx]; + U32 i; + for (i = 0; i < cacheSize; i++) { + hashTable[bucketIdx + i] = 0; + } + hashTable[bucketIdx + bucketSize - 1] = chainPackedPointer; + } + + /* fill the buckets of the hash table */ + for (idx = ms->nextToUpdate; idx < target; idx++) { + U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch) + << ZSTD_LAZY_DDSS_BUCKET_LOG; + U32 i; + /* Shift hash cache down 1. */ + for (i = cacheSize - 1; i; i--) + hashTable[h + i] = hashTable[h + i - 1]; + hashTable[h] = idx; + } + + ms->nextToUpdate = target; +} + +/* Returns the longest match length found in the dedicated dict search structure. + * If none are longer than the argument ml, then ml will be returned. + */ +FORCE_INLINE_TEMPLATE +size_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nbAttempts, + const ZSTD_matchState_t* const dms, + const BYTE* const ip, const BYTE* const iLimit, + const BYTE* const prefixStart, const U32 curr, + const U32 dictLimit, const size_t ddsIdx) { + const U32 ddsLowestIndex = dms->window.dictLimit; + const BYTE* const ddsBase = dms->window.base; + const BYTE* const ddsEnd = dms->window.nextSrc; + const U32 ddsSize = (U32)(ddsEnd - ddsBase); + const U32 ddsIndexDelta = dictLimit - ddsSize; + const U32 bucketSize = (1 << ZSTD_LAZY_DDSS_BUCKET_LOG); + const U32 bucketLimit = nbAttempts < bucketSize - 1 ? nbAttempts : bucketSize - 1; + U32 ddsAttempt; + U32 matchIndex; + + for (ddsAttempt = 0; ddsAttempt < bucketSize - 1; ddsAttempt++) { + PREFETCH_L1(ddsBase + dms->hashTable[ddsIdx + ddsAttempt]); + } + + { + U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1]; + U32 const chainIndex = chainPackedPointer >> 8; + + PREFETCH_L1(&dms->chainTable[chainIndex]); + } + + for (ddsAttempt = 0; ddsAttempt < bucketLimit; ddsAttempt++) { + size_t currentMl=0; + const BYTE* match; + matchIndex = dms->hashTable[ddsIdx + ddsAttempt]; + match = ddsBase + matchIndex; + + if (!matchIndex) { + return ml; + } + + /* guaranteed by table construction */ + (void)ddsLowestIndex; + assert(matchIndex >= ddsLowestIndex); + assert(match+4 <= ddsEnd); + if (MEM_read32(match) == MEM_read32(ip)) { + /* assumption : matchIndex <= dictLimit-4 (by table construction) */ + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4; + } + + /* save best solution */ + if (currentMl > ml) { + ml = currentMl; + *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + ddsIndexDelta)); + if (ip+currentMl == iLimit) { + /* best possible, avoids read overflow on next attempt */ + return ml; + } + } + } + + { + U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1]; + U32 chainIndex = chainPackedPointer >> 8; + U32 const chainLength = chainPackedPointer & 0xFF; + U32 const chainAttempts = nbAttempts - ddsAttempt; + U32 const chainLimit = chainAttempts > chainLength ? chainLength : chainAttempts; + U32 chainAttempt; + + for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++) { + PREFETCH_L1(ddsBase + dms->chainTable[chainIndex + chainAttempt]); + } + + for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++, chainIndex++) { + size_t currentMl=0; + const BYTE* match; + matchIndex = dms->chainTable[chainIndex]; + match = ddsBase + matchIndex; + + /* guaranteed by table construction */ + assert(matchIndex >= ddsLowestIndex); + assert(match+4 <= ddsEnd); + if (MEM_read32(match) == MEM_read32(ip)) { + /* assumption : matchIndex <= dictLimit-4 (by table construction) */ + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4; + } + + /* save best solution */ + if (currentMl > ml) { + ml = currentMl; + *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + ddsIndexDelta)); + if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ + } + } + } + return ml; +} + + +/* ********************************* +* Hash Chain +***********************************/ +#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & (mask)] + +/* Update chains up to ip (excluded) + Assumption : always within prefix (i.e. not within extDict) */ +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +U32 ZSTD_insertAndFindFirstIndex_internal( + ZSTD_matchState_t* ms, + const ZSTD_compressionParameters* const cParams, + const BYTE* ip, U32 const mls, U32 const lazySkipping) +{ + U32* const hashTable = ms->hashTable; + const U32 hashLog = cParams->hashLog; + U32* const chainTable = ms->chainTable; + const U32 chainMask = (1 << cParams->chainLog) - 1; + const BYTE* const base = ms->window.base; + const U32 target = (U32)(ip - base); + U32 idx = ms->nextToUpdate; + + while(idx < target) { /* catch up */ + size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls); + NEXT_IN_CHAIN(idx, chainMask) = hashTable[h]; + hashTable[h] = idx; + idx++; + /* Stop inserting every position when in the lazy skipping mode. */ + if (lazySkipping) + break; + } + + ms->nextToUpdate = target; + return hashTable[ZSTD_hashPtr(ip, hashLog, mls)]; +} + +U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) { + const ZSTD_compressionParameters* const cParams = &ms->cParams; + return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch, /* lazySkipping*/ 0); +} + +/* inlining is important to hardwire a hot branch (template emulation) */ +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_HcFindBestMatch( + ZSTD_matchState_t* ms, + const BYTE* const ip, const BYTE* const iLimit, + size_t* offsetPtr, + const U32 mls, const ZSTD_dictMode_e dictMode) +{ + const ZSTD_compressionParameters* const cParams = &ms->cParams; + U32* const chainTable = ms->chainTable; + const U32 chainSize = (1 << cParams->chainLog); + const U32 chainMask = chainSize-1; + const BYTE* const base = ms->window.base; + const BYTE* const dictBase = ms->window.dictBase; + const U32 dictLimit = ms->window.dictLimit; + const BYTE* const prefixStart = base + dictLimit; + const BYTE* const dictEnd = dictBase + dictLimit; + const U32 curr = (U32)(ip-base); + const U32 maxDistance = 1U << cParams->windowLog; + const U32 lowestValid = ms->window.lowLimit; + const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; + const U32 isDictionary = (ms->loadedDictEnd != 0); + const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance; + const U32 minChain = curr > chainSize ? curr - chainSize : 0; + U32 nbAttempts = 1U << cParams->searchLog; + size_t ml=4-1; + + const ZSTD_matchState_t* const dms = ms->dictMatchState; + const U32 ddsHashLog = dictMode == ZSTD_dedicatedDictSearch + ? dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG : 0; + const size_t ddsIdx = dictMode == ZSTD_dedicatedDictSearch + ? ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG : 0; + + U32 matchIndex; + + if (dictMode == ZSTD_dedicatedDictSearch) { + const U32* entry = &dms->hashTable[ddsIdx]; + PREFETCH_L1(entry); + } + + /* HC4 match finder */ + matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls, ms->lazySkipping); + + for ( ; (matchIndex>=lowLimit) & (nbAttempts>0) ; nbAttempts--) { + size_t currentMl=0; + if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) { + const BYTE* const match = base + matchIndex; + assert(matchIndex >= dictLimit); /* ensures this is true if dictMode != ZSTD_extDict */ + /* read 4B starting from (match + ml + 1 - sizeof(U32)) */ + if (MEM_read32(match + ml - 3) == MEM_read32(ip + ml - 3)) /* potentially better */ + currentMl = ZSTD_count(ip, match, iLimit); + } else { + const BYTE* const match = dictBase + matchIndex; + assert(match+4 <= dictEnd); + if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */ + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4; + } + + /* save best solution */ + if (currentMl > ml) { + ml = currentMl; + *offsetPtr = OFFSET_TO_OFFBASE(curr - matchIndex); + if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ + } + + if (matchIndex <= minChain) break; + matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask); + } + + assert(nbAttempts <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */ + if (dictMode == ZSTD_dedicatedDictSearch) { + ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts, dms, + ip, iLimit, prefixStart, curr, dictLimit, ddsIdx); + } else if (dictMode == ZSTD_dictMatchState) { + const U32* const dmsChainTable = dms->chainTable; + const U32 dmsChainSize = (1 << dms->cParams.chainLog); + const U32 dmsChainMask = dmsChainSize - 1; + const U32 dmsLowestIndex = dms->window.dictLimit; + const BYTE* const dmsBase = dms->window.base; + const BYTE* const dmsEnd = dms->window.nextSrc; + const U32 dmsSize = (U32)(dmsEnd - dmsBase); + const U32 dmsIndexDelta = dictLimit - dmsSize; + const U32 dmsMinChain = dmsSize > dmsChainSize ? dmsSize - dmsChainSize : 0; + + matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cParams.hashLog, mls)]; + + for ( ; (matchIndex>=dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) { + size_t currentMl=0; + const BYTE* const match = dmsBase + matchIndex; + assert(match+4 <= dmsEnd); + if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */ + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4; + + /* save best solution */ + if (currentMl > ml) { + ml = currentMl; + assert(curr > matchIndex + dmsIndexDelta); + *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + dmsIndexDelta)); + if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ + } + + if (matchIndex <= dmsMinChain) break; + + matchIndex = dmsChainTable[matchIndex & dmsChainMask]; + } + } + + return ml; +} + +/* ********************************* +* (SIMD) Row-based matchfinder +***********************************/ +/* Constants for row-based hash */ +#define ZSTD_ROW_HASH_TAG_MASK ((1u << ZSTD_ROW_HASH_TAG_BITS) - 1) +#define ZSTD_ROW_HASH_MAX_ENTRIES 64 /* absolute maximum number of entries per row, for all configurations */ + +#define ZSTD_ROW_HASH_CACHE_MASK (ZSTD_ROW_HASH_CACHE_SIZE - 1) + +typedef U64 ZSTD_VecMask; /* Clarifies when we are interacting with a U64 representing a mask of matches */ + +/* ZSTD_VecMask_next(): + * Starting from the LSB, returns the idx of the next non-zero bit. + * Basically counting the nb of trailing zeroes. + */ +MEM_STATIC U32 ZSTD_VecMask_next(ZSTD_VecMask val) { + return ZSTD_countTrailingZeros64(val); +} + +/* ZSTD_row_nextIndex(): + * Returns the next index to insert at within a tagTable row, and updates the "head" + * value to reflect the update. Essentially cycles backwards from [1, {entries per row}) + */ +FORCE_INLINE_TEMPLATE U32 ZSTD_row_nextIndex(BYTE* const tagRow, U32 const rowMask) { + U32 next = (*tagRow-1) & rowMask; + next += (next == 0) ? rowMask : 0; /* skip first position */ + *tagRow = (BYTE)next; + return next; +} + +/* ZSTD_isAligned(): + * Checks that a pointer is aligned to "align" bytes which must be a power of 2. + */ +MEM_STATIC int ZSTD_isAligned(void const* ptr, size_t align) { + assert((align & (align - 1)) == 0); + return (((size_t)ptr) & (align - 1)) == 0; +} + +/* ZSTD_row_prefetch(): + * Performs prefetching for the hashTable and tagTable at a given row. + */ +FORCE_INLINE_TEMPLATE void ZSTD_row_prefetch(U32 const* hashTable, BYTE const* tagTable, U32 const relRow, U32 const rowLog) { + PREFETCH_L1(hashTable + relRow); + if (rowLog >= 5) { + PREFETCH_L1(hashTable + relRow + 16); + /* Note: prefetching more of the hash table does not appear to be beneficial for 128-entry rows */ + } + PREFETCH_L1(tagTable + relRow); + if (rowLog == 6) { + PREFETCH_L1(tagTable + relRow + 32); + } + assert(rowLog == 4 || rowLog == 5 || rowLog == 6); + assert(ZSTD_isAligned(hashTable + relRow, 64)); /* prefetched hash row always 64-byte aligned */ + assert(ZSTD_isAligned(tagTable + relRow, (size_t)1 << rowLog)); /* prefetched tagRow sits on correct multiple of bytes (32,64,128) */ +} + +/* ZSTD_row_fillHashCache(): + * Fill up the hash cache starting at idx, prefetching up to ZSTD_ROW_HASH_CACHE_SIZE entries, + * but not beyond iLimit. + */ +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_row_fillHashCache(ZSTD_matchState_t* ms, const BYTE* base, + U32 const rowLog, U32 const mls, + U32 idx, const BYTE* const iLimit) +{ + U32 const* const hashTable = ms->hashTable; + BYTE const* const tagTable = ms->tagTable; + U32 const hashLog = ms->rowHashLog; + U32 const maxElemsToPrefetch = (base + idx) > iLimit ? 0 : (U32)(iLimit - (base + idx) + 1); + U32 const lim = idx + MIN(ZSTD_ROW_HASH_CACHE_SIZE, maxElemsToPrefetch); + + for (; idx < lim; ++idx) { + U32 const hash = (U32)ZSTD_hashPtrSalted(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, ms->hashSalt); + U32 const row = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog; + ZSTD_row_prefetch(hashTable, tagTable, row, rowLog); + ms->hashCache[idx & ZSTD_ROW_HASH_CACHE_MASK] = hash; + } + + DEBUGLOG(6, "ZSTD_row_fillHashCache(): [%u %u %u %u %u %u %u %u]", ms->hashCache[0], ms->hashCache[1], + ms->hashCache[2], ms->hashCache[3], ms->hashCache[4], + ms->hashCache[5], ms->hashCache[6], ms->hashCache[7]); +} + +/* ZSTD_row_nextCachedHash(): + * Returns the hash of base + idx, and replaces the hash in the hash cache with the byte at + * base + idx + ZSTD_ROW_HASH_CACHE_SIZE. Also prefetches the appropriate rows from hashTable and tagTable. + */ +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +U32 ZSTD_row_nextCachedHash(U32* cache, U32 const* hashTable, + BYTE const* tagTable, BYTE const* base, + U32 idx, U32 const hashLog, + U32 const rowLog, U32 const mls, + U64 const hashSalt) +{ + U32 const newHash = (U32)ZSTD_hashPtrSalted(base+idx+ZSTD_ROW_HASH_CACHE_SIZE, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, hashSalt); + U32 const row = (newHash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog; + ZSTD_row_prefetch(hashTable, tagTable, row, rowLog); + { U32 const hash = cache[idx & ZSTD_ROW_HASH_CACHE_MASK]; + cache[idx & ZSTD_ROW_HASH_CACHE_MASK] = newHash; + return hash; + } +} + +/* ZSTD_row_update_internalImpl(): + * Updates the hash table with positions starting from updateStartIdx until updateEndIdx. + */ +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_row_update_internalImpl(ZSTD_matchState_t* ms, + U32 updateStartIdx, U32 const updateEndIdx, + U32 const mls, U32 const rowLog, + U32 const rowMask, U32 const useCache) +{ + U32* const hashTable = ms->hashTable; + BYTE* const tagTable = ms->tagTable; + U32 const hashLog = ms->rowHashLog; + const BYTE* const base = ms->window.base; + + DEBUGLOG(6, "ZSTD_row_update_internalImpl(): updateStartIdx=%u, updateEndIdx=%u", updateStartIdx, updateEndIdx); + for (; updateStartIdx < updateEndIdx; ++updateStartIdx) { + U32 const hash = useCache ? ZSTD_row_nextCachedHash(ms->hashCache, hashTable, tagTable, base, updateStartIdx, hashLog, rowLog, mls, ms->hashSalt) + : (U32)ZSTD_hashPtrSalted(base + updateStartIdx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, ms->hashSalt); + U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog; + U32* const row = hashTable + relRow; + BYTE* tagRow = tagTable + relRow; + U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask); + + assert(hash == ZSTD_hashPtrSalted(base + updateStartIdx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, ms->hashSalt)); + tagRow[pos] = hash & ZSTD_ROW_HASH_TAG_MASK; + row[pos] = updateStartIdx; + } +} + +/* ZSTD_row_update_internal(): + * Inserts the byte at ip into the appropriate position in the hash table, and updates ms->nextToUpdate. + * Skips sections of long matches as is necessary. + */ +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const BYTE* ip, + U32 const mls, U32 const rowLog, + U32 const rowMask, U32 const useCache) +{ + U32 idx = ms->nextToUpdate; + const BYTE* const base = ms->window.base; + const U32 target = (U32)(ip - base); + const U32 kSkipThreshold = 384; + const U32 kMaxMatchStartPositionsToUpdate = 96; + const U32 kMaxMatchEndPositionsToUpdate = 32; + + if (useCache) { + /* Only skip positions when using hash cache, i.e. + * if we are loading a dict, don't skip anything. + * If we decide to skip, then we only update a set number + * of positions at the beginning and end of the match. + */ + if (UNLIKELY(target - idx > kSkipThreshold)) { + U32 const bound = idx + kMaxMatchStartPositionsToUpdate; + ZSTD_row_update_internalImpl(ms, idx, bound, mls, rowLog, rowMask, useCache); + idx = target - kMaxMatchEndPositionsToUpdate; + ZSTD_row_fillHashCache(ms, base, rowLog, mls, idx, ip+1); + } + } + assert(target >= idx); + ZSTD_row_update_internalImpl(ms, idx, target, mls, rowLog, rowMask, useCache); + ms->nextToUpdate = target; +} + +/* ZSTD_row_update(): + * External wrapper for ZSTD_row_update_internal(). Used for filling the hashtable during dictionary + * processing. + */ +void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip) { + const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6); + const U32 rowMask = (1u << rowLog) - 1; + const U32 mls = MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */); + + DEBUGLOG(5, "ZSTD_row_update(), rowLog=%u", rowLog); + ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 0 /* don't use cache */); +} + +/* Returns the mask width of bits group of which will be set to 1. Given not all + * architectures have easy movemask instruction, this helps to iterate over + * groups of bits easier and faster. + */ +FORCE_INLINE_TEMPLATE U32 +ZSTD_row_matchMaskGroupWidth(const U32 rowEntries) +{ + assert((rowEntries == 16) || (rowEntries == 32) || rowEntries == 64); + assert(rowEntries <= ZSTD_ROW_HASH_MAX_ENTRIES); + (void)rowEntries; +#if defined(ZSTD_ARCH_ARM_NEON) + /* NEON path only works for little endian */ + if (!MEM_isLittleEndian()) { + return 1; + } + if (rowEntries == 16) { + return 4; + } + if (rowEntries == 32) { + return 2; + } + if (rowEntries == 64) { + return 1; + } +#endif + return 1; +} + +#if defined(ZSTD_ARCH_X86_SSE2) +FORCE_INLINE_TEMPLATE ZSTD_VecMask +ZSTD_row_getSSEMask(int nbChunks, const BYTE* const src, const BYTE tag, const U32 head) +{ + const __m128i comparisonMask = _mm_set1_epi8((char)tag); + int matches[4] = {0}; + int i; + assert(nbChunks == 1 || nbChunks == 2 || nbChunks == 4); + for (i=0; i> chunkSize; + do { + size_t chunk = MEM_readST(&src[i]); + chunk ^= splatChar; + chunk = (((chunk | x80) - x01) | chunk) & x80; + matches <<= chunkSize; + matches |= (chunk * extractMagic) >> shiftAmount; + i -= chunkSize; + } while (i >= 0); + } else { /* big endian: reverse bits during extraction */ + const size_t msb = xFF ^ (xFF >> 1); + const size_t extractMagic = (msb / 0x1FF) | msb; + do { + size_t chunk = MEM_readST(&src[i]); + chunk ^= splatChar; + chunk = (((chunk | x80) - x01) | chunk) & x80; + matches <<= chunkSize; + matches |= ((chunk >> 7) * extractMagic) >> shiftAmount; + i -= chunkSize; + } while (i >= 0); + } + matches = ~matches; + if (rowEntries == 16) { + return ZSTD_rotateRight_U16((U16)matches, headGrouped); + } else if (rowEntries == 32) { + return ZSTD_rotateRight_U32((U32)matches, headGrouped); + } else { + return ZSTD_rotateRight_U64((U64)matches, headGrouped); + } + } +#endif +} + +/* The high-level approach of the SIMD row based match finder is as follows: + * - Figure out where to insert the new entry: + * - Generate a hash for current input posistion and split it into a one byte of tag and `rowHashLog` bits of index. + * - The hash is salted by a value that changes on every contex reset, so when the same table is used + * we will avoid collisions that would otherwise slow us down by intorducing phantom matches. + * - The hashTable is effectively split into groups or "rows" of 15 or 31 entries of U32, and the index determines + * which row to insert into. + * - Determine the correct position within the row to insert the entry into. Each row of 15 or 31 can + * be considered as a circular buffer with a "head" index that resides in the tagTable (overall 16 or 32 bytes + * per row). + * - Use SIMD to efficiently compare the tags in the tagTable to the 1-byte tag calculated for the position and + * generate a bitfield that we can cycle through to check the collisions in the hash table. + * - Pick the longest match. + * - Insert the tag into the equivalent row and position in the tagTable. + */ +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_RowFindBestMatch( + ZSTD_matchState_t* ms, + const BYTE* const ip, const BYTE* const iLimit, + size_t* offsetPtr, + const U32 mls, const ZSTD_dictMode_e dictMode, + const U32 rowLog) +{ + U32* const hashTable = ms->hashTable; + BYTE* const tagTable = ms->tagTable; + U32* const hashCache = ms->hashCache; + const U32 hashLog = ms->rowHashLog; + const ZSTD_compressionParameters* const cParams = &ms->cParams; + const BYTE* const base = ms->window.base; + const BYTE* const dictBase = ms->window.dictBase; + const U32 dictLimit = ms->window.dictLimit; + const BYTE* const prefixStart = base + dictLimit; + const BYTE* const dictEnd = dictBase + dictLimit; + const U32 curr = (U32)(ip-base); + const U32 maxDistance = 1U << cParams->windowLog; + const U32 lowestValid = ms->window.lowLimit; + const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; + const U32 isDictionary = (ms->loadedDictEnd != 0); + const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance; + const U32 rowEntries = (1U << rowLog); + const U32 rowMask = rowEntries - 1; + const U32 cappedSearchLog = MIN(cParams->searchLog, rowLog); /* nb of searches is capped at nb entries per row */ + const U32 groupWidth = ZSTD_row_matchMaskGroupWidth(rowEntries); + const U64 hashSalt = ms->hashSalt; + U32 nbAttempts = 1U << cappedSearchLog; + size_t ml=4-1; + U32 hash; + + /* DMS/DDS variables that may be referenced laster */ + const ZSTD_matchState_t* const dms = ms->dictMatchState; + + /* Initialize the following variables to satisfy static analyzer */ + size_t ddsIdx = 0; + U32 ddsExtraAttempts = 0; /* cctx hash tables are limited in searches, but allow extra searches into DDS */ + U32 dmsTag = 0; + U32* dmsRow = NULL; + BYTE* dmsTagRow = NULL; + + if (dictMode == ZSTD_dedicatedDictSearch) { + const U32 ddsHashLog = dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG; + { /* Prefetch DDS hashtable entry */ + ddsIdx = ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG; + PREFETCH_L1(&dms->hashTable[ddsIdx]); + } + ddsExtraAttempts = cParams->searchLog > rowLog ? 1U << (cParams->searchLog - rowLog) : 0; + } + + if (dictMode == ZSTD_dictMatchState) { + /* Prefetch DMS rows */ + U32* const dmsHashTable = dms->hashTable; + BYTE* const dmsTagTable = dms->tagTable; + U32 const dmsHash = (U32)ZSTD_hashPtr(ip, dms->rowHashLog + ZSTD_ROW_HASH_TAG_BITS, mls); + U32 const dmsRelRow = (dmsHash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog; + dmsTag = dmsHash & ZSTD_ROW_HASH_TAG_MASK; + dmsTagRow = (BYTE*)(dmsTagTable + dmsRelRow); + dmsRow = dmsHashTable + dmsRelRow; + ZSTD_row_prefetch(dmsHashTable, dmsTagTable, dmsRelRow, rowLog); + } + + /* Update the hashTable and tagTable up to (but not including) ip */ + if (!ms->lazySkipping) { + ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 1 /* useCache */); + hash = ZSTD_row_nextCachedHash(hashCache, hashTable, tagTable, base, curr, hashLog, rowLog, mls, hashSalt); + } else { + /* Stop inserting every position when in the lazy skipping mode. + * The hash cache is also not kept up to date in this mode. + */ + hash = (U32)ZSTD_hashPtrSalted(ip, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, hashSalt); + ms->nextToUpdate = curr; + } + ms->hashSaltEntropy += hash; /* collect salt entropy */ + + { /* Get the hash for ip, compute the appropriate row */ + U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog; + U32 const tag = hash & ZSTD_ROW_HASH_TAG_MASK; + U32* const row = hashTable + relRow; + BYTE* tagRow = (BYTE*)(tagTable + relRow); + U32 const headGrouped = (*tagRow & rowMask) * groupWidth; + U32 matchBuffer[ZSTD_ROW_HASH_MAX_ENTRIES]; + size_t numMatches = 0; + size_t currMatch = 0; + ZSTD_VecMask matches = ZSTD_row_getMatchMask(tagRow, (BYTE)tag, headGrouped, rowEntries); + + /* Cycle through the matches and prefetch */ + for (; (matches > 0) && (nbAttempts > 0); matches &= (matches - 1)) { + U32 const matchPos = ((headGrouped + ZSTD_VecMask_next(matches)) / groupWidth) & rowMask; + U32 const matchIndex = row[matchPos]; + if(matchPos == 0) continue; + assert(numMatches < rowEntries); + if (matchIndex < lowLimit) + break; + if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) { + PREFETCH_L1(base + matchIndex); + } else { + PREFETCH_L1(dictBase + matchIndex); + } + matchBuffer[numMatches++] = matchIndex; + --nbAttempts; + } + + /* Speed opt: insert current byte into hashtable too. This allows us to avoid one iteration of the loop + in ZSTD_row_update_internal() at the next search. */ + { + U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask); + tagRow[pos] = (BYTE)tag; + row[pos] = ms->nextToUpdate++; + } + + /* Return the longest match */ + for (; currMatch < numMatches; ++currMatch) { + U32 const matchIndex = matchBuffer[currMatch]; + size_t currentMl=0; + assert(matchIndex < curr); + assert(matchIndex >= lowLimit); + + if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) { + const BYTE* const match = base + matchIndex; + assert(matchIndex >= dictLimit); /* ensures this is true if dictMode != ZSTD_extDict */ + /* read 4B starting from (match + ml + 1 - sizeof(U32)) */ + if (MEM_read32(match + ml - 3) == MEM_read32(ip + ml - 3)) /* potentially better */ + currentMl = ZSTD_count(ip, match, iLimit); + } else { + const BYTE* const match = dictBase + matchIndex; + assert(match+4 <= dictEnd); + if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */ + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4; + } + + /* Save best solution */ + if (currentMl > ml) { + ml = currentMl; + *offsetPtr = OFFSET_TO_OFFBASE(curr - matchIndex); + if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ + } + } + } + + assert(nbAttempts <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */ + if (dictMode == ZSTD_dedicatedDictSearch) { + ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts + ddsExtraAttempts, dms, + ip, iLimit, prefixStart, curr, dictLimit, ddsIdx); + } else if (dictMode == ZSTD_dictMatchState) { + /* TODO: Measure and potentially add prefetching to DMS */ + const U32 dmsLowestIndex = dms->window.dictLimit; + const BYTE* const dmsBase = dms->window.base; + const BYTE* const dmsEnd = dms->window.nextSrc; + const U32 dmsSize = (U32)(dmsEnd - dmsBase); + const U32 dmsIndexDelta = dictLimit - dmsSize; + + { U32 const headGrouped = (*dmsTagRow & rowMask) * groupWidth; + U32 matchBuffer[ZSTD_ROW_HASH_MAX_ENTRIES]; + size_t numMatches = 0; + size_t currMatch = 0; + ZSTD_VecMask matches = ZSTD_row_getMatchMask(dmsTagRow, (BYTE)dmsTag, headGrouped, rowEntries); + + for (; (matches > 0) && (nbAttempts > 0); matches &= (matches - 1)) { + U32 const matchPos = ((headGrouped + ZSTD_VecMask_next(matches)) / groupWidth) & rowMask; + U32 const matchIndex = dmsRow[matchPos]; + if(matchPos == 0) continue; + if (matchIndex < dmsLowestIndex) + break; + PREFETCH_L1(dmsBase + matchIndex); + matchBuffer[numMatches++] = matchIndex; + --nbAttempts; + } + + /* Return the longest match */ + for (; currMatch < numMatches; ++currMatch) { + U32 const matchIndex = matchBuffer[currMatch]; + size_t currentMl=0; + assert(matchIndex >= dmsLowestIndex); + assert(matchIndex < curr); + + { const BYTE* const match = dmsBase + matchIndex; + assert(match+4 <= dmsEnd); + if (MEM_read32(match) == MEM_read32(ip)) + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4; + } + + if (currentMl > ml) { + ml = currentMl; + assert(curr > matchIndex + dmsIndexDelta); + *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + dmsIndexDelta)); + if (ip+currentMl == iLimit) break; + } + } + } + } + return ml; +} + + +/** + * Generate search functions templated on (dictMode, mls, rowLog). + * These functions are outlined for code size & compilation time. + * ZSTD_searchMax() dispatches to the correct implementation function. + * + * TODO: The start of the search function involves loading and calculating a + * bunch of constants from the ZSTD_matchState_t. These computations could be + * done in an initialization function, and saved somewhere in the match state. + * Then we could pass a pointer to the saved state instead of the match state, + * and avoid duplicate computations. + * + * TODO: Move the match re-winding into searchMax. This improves compression + * ratio, and unlocks further simplifications with the next TODO. + * + * TODO: Try moving the repcode search into searchMax. After the re-winding + * and repcode search are in searchMax, there is no more logic in the match + * finder loop that requires knowledge about the dictMode. So we should be + * able to avoid force inlining it, and we can join the extDict loop with + * the single segment loop. It should go in searchMax instead of its own + * function to avoid having multiple virtual function calls per search. + */ + +#define ZSTD_BT_SEARCH_FN(dictMode, mls) ZSTD_BtFindBestMatch_##dictMode##_##mls +#define ZSTD_HC_SEARCH_FN(dictMode, mls) ZSTD_HcFindBestMatch_##dictMode##_##mls +#define ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog) ZSTD_RowFindBestMatch_##dictMode##_##mls##_##rowLog + +#define ZSTD_SEARCH_FN_ATTRS FORCE_NOINLINE + +#define GEN_ZSTD_BT_SEARCH_FN(dictMode, mls) \ + ZSTD_SEARCH_FN_ATTRS size_t ZSTD_BT_SEARCH_FN(dictMode, mls)( \ + ZSTD_matchState_t* ms, \ + const BYTE* ip, const BYTE* const iLimit, \ + size_t* offBasePtr) \ + { \ + assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \ + return ZSTD_BtFindBestMatch(ms, ip, iLimit, offBasePtr, mls, ZSTD_##dictMode); \ + } \ + +#define GEN_ZSTD_HC_SEARCH_FN(dictMode, mls) \ + ZSTD_SEARCH_FN_ATTRS size_t ZSTD_HC_SEARCH_FN(dictMode, mls)( \ + ZSTD_matchState_t* ms, \ + const BYTE* ip, const BYTE* const iLimit, \ + size_t* offsetPtr) \ + { \ + assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \ + return ZSTD_HcFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode); \ + } \ + +#define GEN_ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog) \ + ZSTD_SEARCH_FN_ATTRS size_t ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog)( \ + ZSTD_matchState_t* ms, \ + const BYTE* ip, const BYTE* const iLimit, \ + size_t* offsetPtr) \ + { \ + assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \ + assert(MAX(4, MIN(6, ms->cParams.searchLog)) == rowLog); \ + return ZSTD_RowFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode, rowLog); \ + } \ + +#define ZSTD_FOR_EACH_ROWLOG(X, dictMode, mls) \ + X(dictMode, mls, 4) \ + X(dictMode, mls, 5) \ + X(dictMode, mls, 6) + +#define ZSTD_FOR_EACH_MLS_ROWLOG(X, dictMode) \ + ZSTD_FOR_EACH_ROWLOG(X, dictMode, 4) \ + ZSTD_FOR_EACH_ROWLOG(X, dictMode, 5) \ + ZSTD_FOR_EACH_ROWLOG(X, dictMode, 6) + +#define ZSTD_FOR_EACH_MLS(X, dictMode) \ + X(dictMode, 4) \ + X(dictMode, 5) \ + X(dictMode, 6) + +#define ZSTD_FOR_EACH_DICT_MODE(X, ...) \ + X(__VA_ARGS__, noDict) \ + X(__VA_ARGS__, extDict) \ + X(__VA_ARGS__, dictMatchState) \ + X(__VA_ARGS__, dedicatedDictSearch) + +/* Generate row search fns for each combination of (dictMode, mls, rowLog) */ +ZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS_ROWLOG, GEN_ZSTD_ROW_SEARCH_FN) +/* Generate binary Tree search fns for each combination of (dictMode, mls) */ +ZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS, GEN_ZSTD_BT_SEARCH_FN) +/* Generate hash chain search fns for each combination of (dictMode, mls) */ +ZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS, GEN_ZSTD_HC_SEARCH_FN) + +typedef enum { search_hashChain=0, search_binaryTree=1, search_rowHash=2 } searchMethod_e; + +#define GEN_ZSTD_CALL_BT_SEARCH_FN(dictMode, mls) \ + case mls: \ + return ZSTD_BT_SEARCH_FN(dictMode, mls)(ms, ip, iend, offsetPtr); +#define GEN_ZSTD_CALL_HC_SEARCH_FN(dictMode, mls) \ + case mls: \ + return ZSTD_HC_SEARCH_FN(dictMode, mls)(ms, ip, iend, offsetPtr); +#define GEN_ZSTD_CALL_ROW_SEARCH_FN(dictMode, mls, rowLog) \ + case rowLog: \ + return ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog)(ms, ip, iend, offsetPtr); + +#define ZSTD_SWITCH_MLS(X, dictMode) \ + switch (mls) { \ + ZSTD_FOR_EACH_MLS(X, dictMode) \ + } + +#define ZSTD_SWITCH_ROWLOG(dictMode, mls) \ + case mls: \ + switch (rowLog) { \ + ZSTD_FOR_EACH_ROWLOG(GEN_ZSTD_CALL_ROW_SEARCH_FN, dictMode, mls) \ + } \ + ZSTD_UNREACHABLE; \ + break; + +#define ZSTD_SWITCH_SEARCH_METHOD(dictMode) \ + switch (searchMethod) { \ + case search_hashChain: \ + ZSTD_SWITCH_MLS(GEN_ZSTD_CALL_HC_SEARCH_FN, dictMode) \ + break; \ + case search_binaryTree: \ + ZSTD_SWITCH_MLS(GEN_ZSTD_CALL_BT_SEARCH_FN, dictMode) \ + break; \ + case search_rowHash: \ + ZSTD_SWITCH_MLS(ZSTD_SWITCH_ROWLOG, dictMode) \ + break; \ + } \ + ZSTD_UNREACHABLE; + +/** + * Searches for the longest match at @p ip. + * Dispatches to the correct implementation function based on the + * (searchMethod, dictMode, mls, rowLog). We use switch statements + * here instead of using an indirect function call through a function + * pointer because after Spectre and Meltdown mitigations, indirect + * function calls can be very costly, especially in the kernel. + * + * NOTE: dictMode and searchMethod should be templated, so those switch + * statements should be optimized out. Only the mls & rowLog switches + * should be left. + * + * @param ms The match state. + * @param ip The position to search at. + * @param iend The end of the input data. + * @param[out] offsetPtr Stores the match offset into this pointer. + * @param mls The minimum search length, in the range [4, 6]. + * @param rowLog The row log (if applicable), in the range [4, 6]. + * @param searchMethod The search method to use (templated). + * @param dictMode The dictMode (templated). + * + * @returns The length of the longest match found, or < mls if no match is found. + * If a match is found its offset is stored in @p offsetPtr. + */ +FORCE_INLINE_TEMPLATE size_t ZSTD_searchMax( + ZSTD_matchState_t* ms, + const BYTE* ip, + const BYTE* iend, + size_t* offsetPtr, + U32 const mls, + U32 const rowLog, + searchMethod_e const searchMethod, + ZSTD_dictMode_e const dictMode) +{ + if (dictMode == ZSTD_noDict) { + ZSTD_SWITCH_SEARCH_METHOD(noDict) + } else if (dictMode == ZSTD_extDict) { + ZSTD_SWITCH_SEARCH_METHOD(extDict) + } else if (dictMode == ZSTD_dictMatchState) { + ZSTD_SWITCH_SEARCH_METHOD(dictMatchState) + } else if (dictMode == ZSTD_dedicatedDictSearch) { + ZSTD_SWITCH_SEARCH_METHOD(dedicatedDictSearch) + } + ZSTD_UNREACHABLE; + return 0; +} + +/* ******************************* +* Common parser - lazy strategy +*********************************/ + +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_compressBlock_lazy_generic( + ZSTD_matchState_t* ms, seqStore_t* seqStore, + U32 rep[ZSTD_REP_NUM], + const void* src, size_t srcSize, + const searchMethod_e searchMethod, const U32 depth, + ZSTD_dictMode_e const dictMode) +{ + const BYTE* const istart = (const BYTE*)src; + const BYTE* ip = istart; + const BYTE* anchor = istart; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = (searchMethod == search_rowHash) ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8; + const BYTE* const base = ms->window.base; + const U32 prefixLowestIndex = ms->window.dictLimit; + const BYTE* const prefixLowest = base + prefixLowestIndex; + const U32 mls = BOUNDED(4, ms->cParams.minMatch, 6); + const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6); + + U32 offset_1 = rep[0], offset_2 = rep[1]; + U32 offsetSaved1 = 0, offsetSaved2 = 0; + + const int isDMS = dictMode == ZSTD_dictMatchState; + const int isDDS = dictMode == ZSTD_dedicatedDictSearch; + const int isDxS = isDMS || isDDS; + const ZSTD_matchState_t* const dms = ms->dictMatchState; + const U32 dictLowestIndex = isDxS ? dms->window.dictLimit : 0; + const BYTE* const dictBase = isDxS ? dms->window.base : NULL; + const BYTE* const dictLowest = isDxS ? dictBase + dictLowestIndex : NULL; + const BYTE* const dictEnd = isDxS ? dms->window.nextSrc : NULL; + const U32 dictIndexDelta = isDxS ? + prefixLowestIndex - (U32)(dictEnd - dictBase) : + 0; + const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictLowest)); + + DEBUGLOG(5, "ZSTD_compressBlock_lazy_generic (dictMode=%u) (searchFunc=%u)", (U32)dictMode, (U32)searchMethod); + ip += (dictAndPrefixLength == 0); + if (dictMode == ZSTD_noDict) { + U32 const curr = (U32)(ip - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, ms->cParams.windowLog); + U32 const maxRep = curr - windowLow; + if (offset_2 > maxRep) offsetSaved2 = offset_2, offset_2 = 0; + if (offset_1 > maxRep) offsetSaved1 = offset_1, offset_1 = 0; + } + if (isDxS) { + /* dictMatchState repCode checks don't currently handle repCode == 0 + * disabling. */ + assert(offset_1 <= dictAndPrefixLength); + assert(offset_2 <= dictAndPrefixLength); + } + + /* Reset the lazy skipping state */ + ms->lazySkipping = 0; + + if (searchMethod == search_rowHash) { + ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit); + } + + /* Match Loop */ +#if defined(__GNUC__) && defined(__x86_64__) + /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the + * code alignment is perturbed. To fix the instability align the loop on 32-bytes. + */ + __asm__(".p2align 5"); +#endif + while (ip < ilimit) { + size_t matchLength=0; + size_t offBase = REPCODE1_TO_OFFBASE; + const BYTE* start=ip+1; + DEBUGLOG(7, "search baseline (depth 0)"); + + /* check repCode */ + if (isDxS) { + const U32 repIndex = (U32)(ip - base) + 1 - offset_1; + const BYTE* repMatch = ((dictMode == ZSTD_dictMatchState || dictMode == ZSTD_dedicatedDictSearch) + && repIndex < prefixLowestIndex) ? + dictBase + (repIndex - dictIndexDelta) : + base + repIndex; + if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) + && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { + const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; + matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; + if (depth==0) goto _storeSequence; + } + } + if ( dictMode == ZSTD_noDict + && ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) { + matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4; + if (depth==0) goto _storeSequence; + } + + /* first search (depth 0) */ + { size_t offbaseFound = 999999999; + size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &offbaseFound, mls, rowLog, searchMethod, dictMode); + if (ml2 > matchLength) + matchLength = ml2, start = ip, offBase = offbaseFound; + } + + if (matchLength < 4) { + size_t const step = ((size_t)(ip-anchor) >> kSearchStrength) + 1; /* jump faster over incompressible sections */; + ip += step; + /* Enter the lazy skipping mode once we are skipping more than 8 bytes at a time. + * In this mode we stop inserting every position into our tables, and only insert + * positions that we search, which is one in step positions. + * The exact cutoff is flexible, I've just chosen a number that is reasonably high, + * so we minimize the compression ratio loss in "normal" scenarios. This mode gets + * triggered once we've gone 2KB without finding any matches. + */ + ms->lazySkipping = step > kLazySkippingStep; + continue; + } + + /* let's try to find a better solution */ + if (depth>=1) + while (ip0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) { + size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4; + int const gain2 = (int)(mlRep * 3); + int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offBase) + 1); + if ((mlRep >= 4) && (gain2 > gain1)) + matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip; + } + if (isDxS) { + const U32 repIndex = (U32)(ip - base) - offset_1; + const BYTE* repMatch = repIndex < prefixLowestIndex ? + dictBase + (repIndex - dictIndexDelta) : + base + repIndex; + if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) + && (MEM_read32(repMatch) == MEM_read32(ip)) ) { + const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; + size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; + int const gain2 = (int)(mlRep * 3); + int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offBase) + 1); + if ((mlRep >= 4) && (gain2 > gain1)) + matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip; + } + } + { size_t ofbCandidate=999999999; + size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, dictMode); + int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate)); /* raw approx */ + int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 4); + if ((ml2 >= 4) && (gain2 > gain1)) { + matchLength = ml2, offBase = ofbCandidate, start = ip; + continue; /* search a better one */ + } } + + /* let's find an even better one */ + if ((depth==2) && (ip0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) { + size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4; + int const gain2 = (int)(mlRep * 4); + int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 1); + if ((mlRep >= 4) && (gain2 > gain1)) + matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip; + } + if (isDxS) { + const U32 repIndex = (U32)(ip - base) - offset_1; + const BYTE* repMatch = repIndex < prefixLowestIndex ? + dictBase + (repIndex - dictIndexDelta) : + base + repIndex; + if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) + && (MEM_read32(repMatch) == MEM_read32(ip)) ) { + const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; + size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; + int const gain2 = (int)(mlRep * 4); + int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 1); + if ((mlRep >= 4) && (gain2 > gain1)) + matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip; + } + } + { size_t ofbCandidate=999999999; + size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, dictMode); + int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate)); /* raw approx */ + int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 7); + if ((ml2 >= 4) && (gain2 > gain1)) { + matchLength = ml2, offBase = ofbCandidate, start = ip; + continue; + } } } + break; /* nothing found : store previous solution */ + } + + /* NOTE: + * Pay attention that `start[-value]` can lead to strange undefined behavior + * notably if `value` is unsigned, resulting in a large positive `-value`. + */ + /* catch up */ + if (OFFBASE_IS_OFFSET(offBase)) { + if (dictMode == ZSTD_noDict) { + while ( ((start > anchor) & (start - OFFBASE_TO_OFFSET(offBase) > prefixLowest)) + && (start[-1] == (start-OFFBASE_TO_OFFSET(offBase))[-1]) ) /* only search for offset within prefix */ + { start--; matchLength++; } + } + if (isDxS) { + U32 const matchIndex = (U32)((size_t)(start-base) - OFFBASE_TO_OFFSET(offBase)); + const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex; + const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest; + while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */ + } + offset_2 = offset_1; offset_1 = (U32)OFFBASE_TO_OFFSET(offBase); + } + /* store sequence */ +_storeSequence: + { size_t const litLength = (size_t)(start - anchor); + ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offBase, matchLength); + anchor = ip = start + matchLength; + } + if (ms->lazySkipping) { + /* We've found a match, disable lazy skipping mode, and refill the hash cache. */ + if (searchMethod == search_rowHash) { + ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit); + } + ms->lazySkipping = 0; + } + + /* check immediate repcode */ + if (isDxS) { + while (ip <= ilimit) { + U32 const current2 = (U32)(ip-base); + U32 const repIndex = current2 - offset_2; + const BYTE* repMatch = repIndex < prefixLowestIndex ? + dictBase - dictIndexDelta + repIndex : + base + repIndex; + if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex) >= 3 /* intentional overflow */) + && (MEM_read32(repMatch) == MEM_read32(ip)) ) { + const BYTE* const repEnd2 = repIndex < prefixLowestIndex ? dictEnd : iend; + matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd2, prefixLowest) + 4; + offBase = offset_2; offset_2 = offset_1; offset_1 = (U32)offBase; /* swap offset_2 <=> offset_1 */ + ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, matchLength); + ip += matchLength; + anchor = ip; + continue; + } + break; + } + } + + if (dictMode == ZSTD_noDict) { + while ( ((ip <= ilimit) & (offset_2>0)) + && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) { + /* store sequence */ + matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4; + offBase = offset_2; offset_2 = offset_1; offset_1 = (U32)offBase; /* swap repcodes */ + ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, matchLength); + ip += matchLength; + anchor = ip; + continue; /* faster when present ... (?) */ + } } } + + /* If offset_1 started invalid (offsetSaved1 != 0) and became valid (offset_1 != 0), + * rotate saved offsets. See comment in ZSTD_compressBlock_fast_noDict for more context. */ + offsetSaved2 = ((offsetSaved1 != 0) && (offset_1 != 0)) ? offsetSaved1 : offsetSaved2; + + /* save reps for next block */ + rep[0] = offset_1 ? offset_1 : offsetSaved1; + rep[1] = offset_2 ? offset_2 : offsetSaved2; + + /* Return the last literals size */ + return (size_t)(iend - anchor); +} +#endif /* build exclusions */ + + +#ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_greedy( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_noDict); +} + +size_t ZSTD_compressBlock_greedy_dictMatchState( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dictMatchState); +} + +size_t ZSTD_compressBlock_greedy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dedicatedDictSearch); +} + +size_t ZSTD_compressBlock_greedy_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_noDict); +} + +size_t ZSTD_compressBlock_greedy_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dictMatchState); +} + +size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dedicatedDictSearch); +} +#endif + +#ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_lazy( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_noDict); +} + +size_t ZSTD_compressBlock_lazy_dictMatchState( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dictMatchState); +} + +size_t ZSTD_compressBlock_lazy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dedicatedDictSearch); +} + +size_t ZSTD_compressBlock_lazy_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_noDict); +} + +size_t ZSTD_compressBlock_lazy_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dictMatchState); +} + +size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dedicatedDictSearch); +} +#endif + +#ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_lazy2( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_noDict); +} + +size_t ZSTD_compressBlock_lazy2_dictMatchState( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dictMatchState); +} + +size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dedicatedDictSearch); +} + +size_t ZSTD_compressBlock_lazy2_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_noDict); +} + +size_t ZSTD_compressBlock_lazy2_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dictMatchState); +} + +size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dedicatedDictSearch); +} +#endif + +#ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_btlazy2( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_noDict); +} + +size_t ZSTD_compressBlock_btlazy2_dictMatchState( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_dictMatchState); +} +#endif + +#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_compressBlock_lazy_extDict_generic( + ZSTD_matchState_t* ms, seqStore_t* seqStore, + U32 rep[ZSTD_REP_NUM], + const void* src, size_t srcSize, + const searchMethod_e searchMethod, const U32 depth) +{ + const BYTE* const istart = (const BYTE*)src; + const BYTE* ip = istart; + const BYTE* anchor = istart; + const BYTE* const iend = istart + srcSize; + const BYTE* const ilimit = searchMethod == search_rowHash ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8; + const BYTE* const base = ms->window.base; + const U32 dictLimit = ms->window.dictLimit; + const BYTE* const prefixStart = base + dictLimit; + const BYTE* const dictBase = ms->window.dictBase; + const BYTE* const dictEnd = dictBase + dictLimit; + const BYTE* const dictStart = dictBase + ms->window.lowLimit; + const U32 windowLog = ms->cParams.windowLog; + const U32 mls = BOUNDED(4, ms->cParams.minMatch, 6); + const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6); + + U32 offset_1 = rep[0], offset_2 = rep[1]; + + DEBUGLOG(5, "ZSTD_compressBlock_lazy_extDict_generic (searchFunc=%u)", (U32)searchMethod); + + /* Reset the lazy skipping state */ + ms->lazySkipping = 0; + + /* init */ + ip += (ip == prefixStart); + if (searchMethod == search_rowHash) { + ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit); + } + + /* Match Loop */ +#if defined(__GNUC__) && defined(__x86_64__) + /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the + * code alignment is perturbed. To fix the instability align the loop on 32-bytes. + */ + __asm__(".p2align 5"); +#endif + while (ip < ilimit) { + size_t matchLength=0; + size_t offBase = REPCODE1_TO_OFFBASE; + const BYTE* start=ip+1; + U32 curr = (U32)(ip-base); + + /* check repCode */ + { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr+1, windowLog); + const U32 repIndex = (U32)(curr+1 - offset_1); + const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; + const BYTE* const repMatch = repBase + repIndex; + if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */ + & (offset_1 <= curr+1 - windowLow) ) /* note: we are searching at curr+1 */ + if (MEM_read32(ip+1) == MEM_read32(repMatch)) { + /* repcode detected we should take it */ + const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; + matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repEnd, prefixStart) + 4; + if (depth==0) goto _storeSequence; + } } + + /* first search (depth 0) */ + { size_t ofbCandidate = 999999999; + size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, ZSTD_extDict); + if (ml2 > matchLength) + matchLength = ml2, start = ip, offBase = ofbCandidate; + } + + if (matchLength < 4) { + size_t const step = ((size_t)(ip-anchor) >> kSearchStrength); + ip += step + 1; /* jump faster over incompressible sections */ + /* Enter the lazy skipping mode once we are skipping more than 8 bytes at a time. + * In this mode we stop inserting every position into our tables, and only insert + * positions that we search, which is one in step positions. + * The exact cutoff is flexible, I've just chosen a number that is reasonably high, + * so we minimize the compression ratio loss in "normal" scenarios. This mode gets + * triggered once we've gone 2KB without finding any matches. + */ + ms->lazySkipping = step > kLazySkippingStep; + continue; + } + + /* let's try to find a better solution */ + if (depth>=1) + while (ip= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */ + & (offset_1 <= curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */ + if (MEM_read32(ip) == MEM_read32(repMatch)) { + /* repcode detected */ + const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; + size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4; + int const gain2 = (int)(repLength * 3); + int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offBase) + 1); + if ((repLength >= 4) && (gain2 > gain1)) + matchLength = repLength, offBase = REPCODE1_TO_OFFBASE, start = ip; + } } + + /* search match, depth 1 */ + { size_t ofbCandidate = 999999999; + size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, ZSTD_extDict); + int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate)); /* raw approx */ + int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 4); + if ((ml2 >= 4) && (gain2 > gain1)) { + matchLength = ml2, offBase = ofbCandidate, start = ip; + continue; /* search a better one */ + } } + + /* let's find an even better one */ + if ((depth==2) && (ip= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */ + & (offset_1 <= curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */ + if (MEM_read32(ip) == MEM_read32(repMatch)) { + /* repcode detected */ + const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; + size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4; + int const gain2 = (int)(repLength * 4); + int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 1); + if ((repLength >= 4) && (gain2 > gain1)) + matchLength = repLength, offBase = REPCODE1_TO_OFFBASE, start = ip; + } } + + /* search match, depth 2 */ + { size_t ofbCandidate = 999999999; + size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, ZSTD_extDict); + int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate)); /* raw approx */ + int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 7); + if ((ml2 >= 4) && (gain2 > gain1)) { + matchLength = ml2, offBase = ofbCandidate, start = ip; + continue; + } } } + break; /* nothing found : store previous solution */ + } + + /* catch up */ + if (OFFBASE_IS_OFFSET(offBase)) { + U32 const matchIndex = (U32)((size_t)(start-base) - OFFBASE_TO_OFFSET(offBase)); + const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex; + const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart; + while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */ + offset_2 = offset_1; offset_1 = (U32)OFFBASE_TO_OFFSET(offBase); + } + + /* store sequence */ +_storeSequence: + { size_t const litLength = (size_t)(start - anchor); + ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offBase, matchLength); + anchor = ip = start + matchLength; + } + if (ms->lazySkipping) { + /* We've found a match, disable lazy skipping mode, and refill the hash cache. */ + if (searchMethod == search_rowHash) { + ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit); + } + ms->lazySkipping = 0; + } + + /* check immediate repcode */ + while (ip <= ilimit) { + const U32 repCurrent = (U32)(ip-base); + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, repCurrent, windowLog); + const U32 repIndex = repCurrent - offset_2; + const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; + const BYTE* const repMatch = repBase + repIndex; + if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */ + & (offset_2 <= repCurrent - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */ + if (MEM_read32(ip) == MEM_read32(repMatch)) { + /* repcode detected we should take it */ + const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; + matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4; + offBase = offset_2; offset_2 = offset_1; offset_1 = (U32)offBase; /* swap offset history */ + ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, matchLength); + ip += matchLength; + anchor = ip; + continue; /* faster when present ... (?) */ + } + break; + } } + + /* Save reps for next block */ + rep[0] = offset_1; + rep[1] = offset_2; + + /* Return the last literals size */ + return (size_t)(iend - anchor); +} +#endif /* build exclusions */ + +#ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_greedy_extDict( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0); +} + +size_t ZSTD_compressBlock_greedy_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0); +} +#endif + +#ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_lazy_extDict( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) + +{ + return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1); +} + +size_t ZSTD_compressBlock_lazy_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) + +{ + return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1); +} +#endif + +#ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_lazy2_extDict( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) + +{ + return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2); +} + +size_t ZSTD_compressBlock_lazy2_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2); +} +#endif + +#ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_btlazy2_extDict( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) + +{ + return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2); +} +#endif diff --git a/third_party/zstd/compress/zstd_lazy.cpp b/third_party/zstd/compress/zstd_lazy.cpp deleted file mode 100644 index af2d3b703cb..00000000000 --- a/third_party/zstd/compress/zstd_lazy.cpp +++ /dev/null @@ -1,1142 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - -#include "zstd/compress/zstd_compress_internal.h" -#include "zstd/compress/zstd_lazy.h" - - -/*-************************************* -* Binary Tree search -***************************************/ - -namespace duckdb_zstd { - -static void -ZSTD_updateDUBT(ZSTD_matchState_t* ms, - const BYTE* ip, const BYTE* iend, - U32 mls) -{ - const ZSTD_compressionParameters* const cParams = &ms->cParams; - U32* const hashTable = ms->hashTable; - U32 const hashLog = cParams->hashLog; - - U32* const bt = ms->chainTable; - U32 const btLog = cParams->chainLog - 1; - U32 const btMask = (1 << btLog) - 1; - - const BYTE* const base = ms->window.base; - U32 const target = (U32)(ip - base); - U32 idx = ms->nextToUpdate; - - if (idx != target) - DEBUGLOG(7, "ZSTD_updateDUBT, from %u to %u (dictLimit:%u)", - idx, target, ms->window.dictLimit); - assert(ip + 8 <= iend); /* condition for ZSTD_hashPtr */ - (void)iend; - - assert(idx >= ms->window.dictLimit); /* condition for valid base+idx */ - for ( ; idx < target ; idx++) { - size_t const h = ZSTD_hashPtr(base + idx, hashLog, mls); /* assumption : ip + 8 <= iend */ - U32 const matchIndex = hashTable[h]; - - U32* const nextCandidatePtr = bt + 2*(idx&btMask); - U32* const sortMarkPtr = nextCandidatePtr + 1; - - DEBUGLOG(8, "ZSTD_updateDUBT: insert %u", idx); - hashTable[h] = idx; /* Update Hash Table */ - *nextCandidatePtr = matchIndex; /* update BT like a chain */ - *sortMarkPtr = ZSTD_DUBT_UNSORTED_MARK; - } - ms->nextToUpdate = target; -} - - -/** ZSTD_insertDUBT1() : - * sort one already inserted but unsorted position - * assumption : current >= btlow == (current - btmask) - * doesn't fail */ -static void -ZSTD_insertDUBT1(ZSTD_matchState_t* ms, - U32 current, const BYTE* inputEnd, - U32 nbCompares, U32 btLow, - const ZSTD_dictMode_e dictMode) -{ - const ZSTD_compressionParameters* const cParams = &ms->cParams; - U32* const bt = ms->chainTable; - U32 const btLog = cParams->chainLog - 1; - U32 const btMask = (1 << btLog) - 1; - size_t commonLengthSmaller=0, commonLengthLarger=0; - const BYTE* const base = ms->window.base; - const BYTE* const dictBase = ms->window.dictBase; - const U32 dictLimit = ms->window.dictLimit; - const BYTE* const ip = (current>=dictLimit) ? base + current : dictBase + current; - const BYTE* const iend = (current>=dictLimit) ? inputEnd : dictBase + dictLimit; - const BYTE* const dictEnd = dictBase + dictLimit; - const BYTE* const prefixStart = base + dictLimit; - const BYTE* match; - U32* smallerPtr = bt + 2*(current&btMask); - U32* largerPtr = smallerPtr + 1; - U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */ - U32 dummy32; /* to be nullified at the end */ - U32 const windowValid = ms->window.lowLimit; - U32 const maxDistance = 1U << cParams->windowLog; - U32 const windowLow = (current - windowValid > maxDistance) ? current - maxDistance : windowValid; - - - DEBUGLOG(8, "ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)", - current, dictLimit, windowLow); - assert(current >= btLow); - assert(ip < iend); /* condition for ZSTD_count */ - - while (nbCompares-- && (matchIndex > windowLow)) { - U32* const nextPtr = bt + 2*(matchIndex & btMask); - size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - assert(matchIndex < current); - /* note : all candidates are now supposed sorted, - * but it's still possible to have nextPtr[1] == ZSTD_DUBT_UNSORTED_MARK - * when a real index has the same value as ZSTD_DUBT_UNSORTED_MARK */ - - if ( (dictMode != ZSTD_extDict) - || (matchIndex+matchLength >= dictLimit) /* both in current segment*/ - || (current < dictLimit) /* both in extDict */) { - const BYTE* const mBase = ( (dictMode != ZSTD_extDict) - || (matchIndex+matchLength >= dictLimit)) ? - base : dictBase; - assert( (matchIndex+matchLength >= dictLimit) /* might be wrong if extDict is incorrectly set to 0 */ - || (current < dictLimit) ); - match = mBase + matchIndex; - matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); - } else { - match = dictBase + matchIndex; - matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart); - if (matchIndex+matchLength >= dictLimit) - match = base + matchIndex; /* preparation for next read of match[matchLength] */ - } - - DEBUGLOG(8, "ZSTD_insertDUBT1: comparing %u with %u : found %u common bytes ", - current, matchIndex, (U32)matchLength); - - if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */ - break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */ - } - - if (match[matchLength] < ip[matchLength]) { /* necessarily within buffer */ - /* match is smaller than current */ - *smallerPtr = matchIndex; /* update smaller idx */ - commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ - if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop searching */ - DEBUGLOG(8, "ZSTD_insertDUBT1: %u (>btLow=%u) is smaller : next => %u", - matchIndex, btLow, nextPtr[1]); - smallerPtr = nextPtr+1; /* new "candidate" => larger than match, which was smaller than target */ - matchIndex = nextPtr[1]; /* new matchIndex, larger than previous and closer to current */ - } else { - /* match is larger than current */ - *largerPtr = matchIndex; - commonLengthLarger = matchLength; - if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop searching */ - DEBUGLOG(8, "ZSTD_insertDUBT1: %u (>btLow=%u) is larger => %u", - matchIndex, btLow, nextPtr[0]); - largerPtr = nextPtr; - matchIndex = nextPtr[0]; - } } - - *smallerPtr = *largerPtr = 0; -} - - -static size_t -ZSTD_DUBT_findBetterDictMatch ( - ZSTD_matchState_t* ms, - const BYTE* const ip, const BYTE* const iend, - size_t* offsetPtr, - size_t bestLength, - U32 nbCompares, - U32 const mls, - const ZSTD_dictMode_e dictMode) -{ - const ZSTD_matchState_t * const dms = ms->dictMatchState; - const ZSTD_compressionParameters* const dmsCParams = &dms->cParams; - const U32 * const dictHashTable = dms->hashTable; - U32 const hashLog = dmsCParams->hashLog; - size_t const h = ZSTD_hashPtr(ip, hashLog, mls); - U32 dictMatchIndex = dictHashTable[h]; - - const BYTE* const base = ms->window.base; - const BYTE* const prefixStart = base + ms->window.dictLimit; - U32 const current = (U32)(ip-base); - const BYTE* const dictBase = dms->window.base; - const BYTE* const dictEnd = dms->window.nextSrc; - U32 const dictHighLimit = (U32)(dms->window.nextSrc - dms->window.base); - U32 const dictLowLimit = dms->window.lowLimit; - U32 const dictIndexDelta = ms->window.lowLimit - dictHighLimit; - - U32* const dictBt = dms->chainTable; - U32 const btLog = dmsCParams->chainLog - 1; - U32 const btMask = (1 << btLog) - 1; - U32 const btLow = (btMask >= dictHighLimit - dictLowLimit) ? dictLowLimit : dictHighLimit - btMask; - - size_t commonLengthSmaller=0, commonLengthLarger=0; - - (void)dictMode; - assert(dictMode == ZSTD_dictMatchState); - - while (nbCompares-- && (dictMatchIndex > dictLowLimit)) { - U32* const nextPtr = dictBt + 2*(dictMatchIndex & btMask); - size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - const BYTE* match = dictBase + dictMatchIndex; - matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart); - if (dictMatchIndex+matchLength >= dictHighLimit) - match = base + dictMatchIndex + dictIndexDelta; /* to prepare for next usage of match[matchLength] */ - - if (matchLength > bestLength) { - U32 matchIndex = dictMatchIndex + dictIndexDelta; - if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) { - DEBUGLOG(9, "ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)", - current, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + current - matchIndex, dictMatchIndex, matchIndex); - bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex; - } - if (ip+matchLength == iend) { /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */ - break; /* drop, to guarantee consistency (miss a little bit of compression) */ - } - } - - if (match[matchLength] < ip[matchLength]) { - if (dictMatchIndex <= btLow) { break; } /* beyond tree size, stop the search */ - commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ - dictMatchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ - } else { - /* match is larger than current */ - if (dictMatchIndex <= btLow) { break; } /* beyond tree size, stop the search */ - commonLengthLarger = matchLength; - dictMatchIndex = nextPtr[0]; - } - } - - if (bestLength >= MINMATCH) { - U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex; - DEBUGLOG(8, "ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)", - current, (U32)bestLength, (U32)*offsetPtr, mIndex); - } - return bestLength; - -} - - -static size_t -ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, - const BYTE* const ip, const BYTE* const iend, - size_t* offsetPtr, - U32 const mls, - const ZSTD_dictMode_e dictMode) -{ - const ZSTD_compressionParameters* const cParams = &ms->cParams; - U32* const hashTable = ms->hashTable; - U32 const hashLog = cParams->hashLog; - size_t const h = ZSTD_hashPtr(ip, hashLog, mls); - U32 matchIndex = hashTable[h]; - - const BYTE* const base = ms->window.base; - U32 const current = (U32)(ip-base); - U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog); - - U32* const bt = ms->chainTable; - U32 const btLog = cParams->chainLog - 1; - U32 const btMask = (1 << btLog) - 1; - U32 const btLow = (btMask >= current) ? 0 : current - btMask; - U32 const unsortLimit = MAX(btLow, windowLow); - - U32* nextCandidate = bt + 2*(matchIndex&btMask); - U32* unsortedMark = bt + 2*(matchIndex&btMask) + 1; - U32 nbCompares = 1U << cParams->searchLog; - U32 nbCandidates = nbCompares; - U32 previousCandidate = 0; - - DEBUGLOG(7, "ZSTD_DUBT_findBestMatch (%u) ", current); - assert(ip <= iend-8); /* required for h calculation */ - - /* reach end of unsorted candidates list */ - while ( (matchIndex > unsortLimit) - && (*unsortedMark == ZSTD_DUBT_UNSORTED_MARK) - && (nbCandidates > 1) ) { - DEBUGLOG(8, "ZSTD_DUBT_findBestMatch: candidate %u is unsorted", - matchIndex); - *unsortedMark = previousCandidate; /* the unsortedMark becomes a reversed chain, to move up back to original position */ - previousCandidate = matchIndex; - matchIndex = *nextCandidate; - nextCandidate = bt + 2*(matchIndex&btMask); - unsortedMark = bt + 2*(matchIndex&btMask) + 1; - nbCandidates --; - } - - /* nullify last candidate if it's still unsorted - * simplification, detrimental to compression ratio, beneficial for speed */ - if ( (matchIndex > unsortLimit) - && (*unsortedMark==ZSTD_DUBT_UNSORTED_MARK) ) { - DEBUGLOG(7, "ZSTD_DUBT_findBestMatch: nullify last unsorted candidate %u", - matchIndex); - *nextCandidate = *unsortedMark = 0; - } - - /* batch sort stacked candidates */ - matchIndex = previousCandidate; - while (matchIndex) { /* will end on matchIndex == 0 */ - U32* const nextCandidateIdxPtr = bt + 2*(matchIndex&btMask) + 1; - U32 const nextCandidateIdx = *nextCandidateIdxPtr; - ZSTD_insertDUBT1(ms, matchIndex, iend, - nbCandidates, unsortLimit, dictMode); - matchIndex = nextCandidateIdx; - nbCandidates++; - } - - /* find longest match */ - { size_t commonLengthSmaller = 0, commonLengthLarger = 0; - const BYTE* const dictBase = ms->window.dictBase; - const U32 dictLimit = ms->window.dictLimit; - const BYTE* const dictEnd = dictBase + dictLimit; - const BYTE* const prefixStart = base + dictLimit; - U32* smallerPtr = bt + 2*(current&btMask); - U32* largerPtr = bt + 2*(current&btMask) + 1; - U32 matchEndIdx = current + 8 + 1; - U32 dummy32; /* to be nullified at the end */ - size_t bestLength = 0; - - matchIndex = hashTable[h]; - hashTable[h] = current; /* Update Hash Table */ - - while (nbCompares-- && (matchIndex > windowLow)) { - U32* const nextPtr = bt + 2*(matchIndex & btMask); - size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - const BYTE* match; - - if ((dictMode != ZSTD_extDict) || (matchIndex+matchLength >= dictLimit)) { - match = base + matchIndex; - matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); - } else { - match = dictBase + matchIndex; - matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart); - if (matchIndex+matchLength >= dictLimit) - match = base + matchIndex; /* to prepare for next usage of match[matchLength] */ - } - - if (matchLength > bestLength) { - if (matchLength > matchEndIdx - matchIndex) - matchEndIdx = matchIndex + (U32)matchLength; - if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) - bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex; - if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */ - if (dictMode == ZSTD_dictMatchState) { - nbCompares = 0; /* in addition to avoiding checking any - * further in this loop, make sure we - * skip checking in the dictionary. */ - } - break; /* drop, to guarantee consistency (miss a little bit of compression) */ - } - } - - if (match[matchLength] < ip[matchLength]) { - /* match is smaller than current */ - *smallerPtr = matchIndex; /* update smaller idx */ - commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ - if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */ - smallerPtr = nextPtr+1; /* new "smaller" => larger of match */ - matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ - } else { - /* match is larger than current */ - *largerPtr = matchIndex; - commonLengthLarger = matchLength; - if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */ - largerPtr = nextPtr; - matchIndex = nextPtr[0]; - } } - - *smallerPtr = *largerPtr = 0; - - if (dictMode == ZSTD_dictMatchState && nbCompares) { - bestLength = ZSTD_DUBT_findBetterDictMatch( - ms, ip, iend, - offsetPtr, bestLength, nbCompares, - mls, dictMode); - } - - assert(matchEndIdx > current+8); /* ensure nextToUpdate is increased */ - ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */ - if (bestLength >= MINMATCH) { - U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex; - DEBUGLOG(8, "ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)", - current, (U32)bestLength, (U32)*offsetPtr, mIndex); - } - return bestLength; - } -} - - -/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */ -FORCE_INLINE_TEMPLATE size_t -ZSTD_BtFindBestMatch( ZSTD_matchState_t* ms, - const BYTE* const ip, const BYTE* const iLimit, - size_t* offsetPtr, - const U32 mls /* template */, - const ZSTD_dictMode_e dictMode) -{ - DEBUGLOG(7, "ZSTD_BtFindBestMatch"); - if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */ - ZSTD_updateDUBT(ms, ip, iLimit, mls); - return ZSTD_DUBT_findBestMatch(ms, ip, iLimit, offsetPtr, mls, dictMode); -} - - -static size_t -ZSTD_BtFindBestMatch_selectMLS ( ZSTD_matchState_t* ms, - const BYTE* ip, const BYTE* const iLimit, - size_t* offsetPtr) -{ - switch(ms->cParams.minMatch) - { - default : /* includes case 3 */ - case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_noDict); - case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_noDict); - case 7 : - case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_noDict); - } -} - - -static size_t ZSTD_BtFindBestMatch_dictMatchState_selectMLS ( - ZSTD_matchState_t* ms, - const BYTE* ip, const BYTE* const iLimit, - size_t* offsetPtr) -{ - switch(ms->cParams.minMatch) - { - default : /* includes case 3 */ - case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_dictMatchState); - case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_dictMatchState); - case 7 : - case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_dictMatchState); - } -} - - -static size_t ZSTD_BtFindBestMatch_extDict_selectMLS ( - ZSTD_matchState_t* ms, - const BYTE* ip, const BYTE* const iLimit, - size_t* offsetPtr) -{ - switch(ms->cParams.minMatch) - { - default : /* includes case 3 */ - case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_extDict); - case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_extDict); - case 7 : - case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_extDict); - } -} - - - -/* ********************************* -* Hash Chain -***********************************/ -#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & (mask)] - -/* Update chains up to ip (excluded) - Assumption : always within prefix (i.e. not within extDict) */ -static U32 ZSTD_insertAndFindFirstIndex_internal( - ZSTD_matchState_t* ms, - const ZSTD_compressionParameters* const cParams, - const BYTE* ip, U32 const mls) -{ - U32* const hashTable = ms->hashTable; - const U32 hashLog = cParams->hashLog; - U32* const chainTable = ms->chainTable; - const U32 chainMask = (1 << cParams->chainLog) - 1; - const BYTE* const base = ms->window.base; - const U32 target = (U32)(ip - base); - U32 idx = ms->nextToUpdate; - - while(idx < target) { /* catch up */ - size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls); - NEXT_IN_CHAIN(idx, chainMask) = hashTable[h]; - hashTable[h] = idx; - idx++; - } - - ms->nextToUpdate = target; - return hashTable[ZSTD_hashPtr(ip, hashLog, mls)]; -} - -U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; - return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch); -} - - -/* inlining is important to hardwire a hot branch (template emulation) */ -FORCE_INLINE_TEMPLATE -size_t ZSTD_HcFindBestMatch_generic ( - ZSTD_matchState_t* ms, - const BYTE* const ip, const BYTE* const iLimit, - size_t* offsetPtr, - const U32 mls, const ZSTD_dictMode_e dictMode) -{ - const ZSTD_compressionParameters* const cParams = &ms->cParams; - U32* const chainTable = ms->chainTable; - const U32 chainSize = (1 << cParams->chainLog); - const U32 chainMask = chainSize-1; - const BYTE* const base = ms->window.base; - const BYTE* const dictBase = ms->window.dictBase; - const U32 dictLimit = ms->window.dictLimit; - const BYTE* const prefixStart = base + dictLimit; - const BYTE* const dictEnd = dictBase + dictLimit; - const U32 current = (U32)(ip-base); - const U32 maxDistance = 1U << cParams->windowLog; - const U32 lowestValid = ms->window.lowLimit; - const U32 withinMaxDistance = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid; - const U32 isDictionary = (ms->loadedDictEnd != 0); - const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance; - const U32 minChain = current > chainSize ? current - chainSize : 0; - U32 nbAttempts = 1U << cParams->searchLog; - size_t ml=4-1; - - /* HC4 match finder */ - U32 matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls); - - for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) { - size_t currentMl=0; - if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) { - const BYTE* const match = base + matchIndex; - assert(matchIndex >= dictLimit); /* ensures this is true if dictMode != ZSTD_extDict */ - if (match[ml] == ip[ml]) /* potentially better */ - currentMl = ZSTD_count(ip, match, iLimit); - } else { - const BYTE* const match = dictBase + matchIndex; - assert(match+4 <= dictEnd); - if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */ - currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4; - } - - /* save best solution */ - if (currentMl > ml) { - ml = currentMl; - *offsetPtr = current - matchIndex + ZSTD_REP_MOVE; - if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ - } - - if (matchIndex <= minChain) break; - matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask); - } - - if (dictMode == ZSTD_dictMatchState) { - const ZSTD_matchState_t* const dms = ms->dictMatchState; - const U32* const dmsChainTable = dms->chainTable; - const U32 dmsChainSize = (1 << dms->cParams.chainLog); - const U32 dmsChainMask = dmsChainSize - 1; - const U32 dmsLowestIndex = dms->window.dictLimit; - const BYTE* const dmsBase = dms->window.base; - const BYTE* const dmsEnd = dms->window.nextSrc; - const U32 dmsSize = (U32)(dmsEnd - dmsBase); - const U32 dmsIndexDelta = dictLimit - dmsSize; - const U32 dmsMinChain = dmsSize > dmsChainSize ? dmsSize - dmsChainSize : 0; - - matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cParams.hashLog, mls)]; - - for ( ; (matchIndex>dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) { - size_t currentMl=0; - const BYTE* const match = dmsBase + matchIndex; - assert(match+4 <= dmsEnd); - if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */ - currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4; - - /* save best solution */ - if (currentMl > ml) { - ml = currentMl; - *offsetPtr = current - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE; - if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ - } - - if (matchIndex <= dmsMinChain) break; - matchIndex = dmsChainTable[matchIndex & dmsChainMask]; - } - } - - return ml; -} - - -FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_selectMLS ( - ZSTD_matchState_t* ms, - const BYTE* ip, const BYTE* const iLimit, - size_t* offsetPtr) -{ - switch(ms->cParams.minMatch) - { - default : /* includes case 3 */ - case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_noDict); - case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_noDict); - case 7 : - case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_noDict); - } -} - - -static size_t ZSTD_HcFindBestMatch_dictMatchState_selectMLS ( - ZSTD_matchState_t* ms, - const BYTE* ip, const BYTE* const iLimit, - size_t* offsetPtr) -{ - switch(ms->cParams.minMatch) - { - default : /* includes case 3 */ - case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_dictMatchState); - case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_dictMatchState); - case 7 : - case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_dictMatchState); - } -} - - -FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS ( - ZSTD_matchState_t* ms, - const BYTE* ip, const BYTE* const iLimit, - size_t* offsetPtr) -{ - switch(ms->cParams.minMatch) - { - default : /* includes case 3 */ - case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_extDict); - case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_extDict); - case 7 : - case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_extDict); - } -} - - -/* ******************************* -* Common parser - lazy strategy -*********************************/ -typedef enum { search_hashChain, search_binaryTree } searchMethod_e; - -FORCE_INLINE_TEMPLATE size_t -ZSTD_compressBlock_lazy_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, - U32 rep[ZSTD_REP_NUM], - const void* src, size_t srcSize, - const searchMethod_e searchMethod, const U32 depth, - ZSTD_dictMode_e const dictMode) -{ - const BYTE* const istart = (const BYTE*)src; - const BYTE* ip = istart; - const BYTE* anchor = istart; - const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - 8; - const BYTE* const base = ms->window.base; - const U32 prefixLowestIndex = ms->window.dictLimit; - const BYTE* const prefixLowest = base + prefixLowestIndex; - - typedef size_t (*searchMax_f)( - ZSTD_matchState_t* ms, - const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr); - searchMax_f const searchMax = dictMode == ZSTD_dictMatchState ? - (searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_dictMatchState_selectMLS - : ZSTD_HcFindBestMatch_dictMatchState_selectMLS) : - (searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_selectMLS - : ZSTD_HcFindBestMatch_selectMLS); - U32 offset_1 = rep[0], offset_2 = rep[1], savedOffset=0; - - const ZSTD_matchState_t* const dms = ms->dictMatchState; - const U32 dictLowestIndex = dictMode == ZSTD_dictMatchState ? - dms->window.dictLimit : 0; - const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ? - dms->window.base : NULL; - const BYTE* const dictLowest = dictMode == ZSTD_dictMatchState ? - dictBase + dictLowestIndex : NULL; - const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ? - dms->window.nextSrc : NULL; - const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ? - prefixLowestIndex - (U32)(dictEnd - dictBase) : - 0; - const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictLowest)); - - DEBUGLOG(5, "ZSTD_compressBlock_lazy_generic (dictMode=%u)", (U32)dictMode); - - /* init */ - ip += (dictAndPrefixLength == 0); - if (dictMode == ZSTD_noDict) { - U32 const current = (U32)(ip - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, ms->cParams.windowLog); - U32 const maxRep = current - windowLow; - if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0; - if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0; - } - if (dictMode == ZSTD_dictMatchState) { - /* dictMatchState repCode checks don't currently handle repCode == 0 - * disabling. */ - assert(offset_1 <= dictAndPrefixLength); - assert(offset_2 <= dictAndPrefixLength); - } - - /* Match Loop */ -#if defined(__GNUC__) && defined(__x86_64__) - /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the - * code alignment is perturbed. To fix the instability align the loop on 32-bytes. - */ - __asm__(".p2align 5"); -#endif - while (ip < ilimit) { - size_t matchLength=0; - size_t offset=0; - const BYTE* start=ip+1; - - /* check repCode */ - if (dictMode == ZSTD_dictMatchState) { - const U32 repIndex = (U32)(ip - base) + 1 - offset_1; - const BYTE* repMatch = (dictMode == ZSTD_dictMatchState - && repIndex < prefixLowestIndex) ? - dictBase + (repIndex - dictIndexDelta) : - base + repIndex; - if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) - && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { - const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; - matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; - if (depth==0) goto _storeSequence; - } - } - if ( dictMode == ZSTD_noDict - && ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) { - matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4; - if (depth==0) goto _storeSequence; - } - - /* first search (depth 0) */ - { size_t offsetFound = 999999999; - size_t const ml2 = searchMax(ms, ip, iend, &offsetFound); - if (ml2 > matchLength) - matchLength = ml2, start = ip, offset=offsetFound; - } - - if (matchLength < 4) { - ip += ((ip-anchor) >> kSearchStrength) + 1; /* jump faster over incompressible sections */ - continue; - } - - /* let's try to find a better solution */ - if (depth>=1) - while (ip0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) { - size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4; - int const gain2 = (int)(mlRep * 3); - int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1); - if ((mlRep >= 4) && (gain2 > gain1)) - matchLength = mlRep, offset = 0, start = ip; - } - if (dictMode == ZSTD_dictMatchState) { - const U32 repIndex = (U32)(ip - base) - offset_1; - const BYTE* repMatch = repIndex < prefixLowestIndex ? - dictBase + (repIndex - dictIndexDelta) : - base + repIndex; - if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) - && (MEM_read32(repMatch) == MEM_read32(ip)) ) { - const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; - size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; - int const gain2 = (int)(mlRep * 3); - int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1); - if ((mlRep >= 4) && (gain2 > gain1)) - matchLength = mlRep, offset = 0, start = ip; - } - } - { size_t offset2=999999999; - size_t const ml2 = searchMax(ms, ip, iend, &offset2); - int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */ - int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4); - if ((ml2 >= 4) && (gain2 > gain1)) { - matchLength = ml2, offset = offset2, start = ip; - continue; /* search a better one */ - } } - - /* let's find an even better one */ - if ((depth==2) && (ip0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) { - size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4; - int const gain2 = (int)(mlRep * 4); - int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1); - if ((mlRep >= 4) && (gain2 > gain1)) - matchLength = mlRep, offset = 0, start = ip; - } - if (dictMode == ZSTD_dictMatchState) { - const U32 repIndex = (U32)(ip - base) - offset_1; - const BYTE* repMatch = repIndex < prefixLowestIndex ? - dictBase + (repIndex - dictIndexDelta) : - base + repIndex; - if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */) - && (MEM_read32(repMatch) == MEM_read32(ip)) ) { - const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; - size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4; - int const gain2 = (int)(mlRep * 4); - int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1); - if ((mlRep >= 4) && (gain2 > gain1)) - matchLength = mlRep, offset = 0, start = ip; - } - } - { size_t offset2=999999999; - size_t const ml2 = searchMax(ms, ip, iend, &offset2); - int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */ - int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7); - if ((ml2 >= 4) && (gain2 > gain1)) { - matchLength = ml2, offset = offset2, start = ip; - continue; - } } } - break; /* nothing found : store previous solution */ - } - - /* NOTE: - * start[-offset+ZSTD_REP_MOVE-1] is undefined behavior. - * (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which - * overflows the pointer, which is undefined behavior. - */ - /* catch up */ - if (offset) { - if (dictMode == ZSTD_noDict) { - while ( ((start > anchor) & (start - (offset-ZSTD_REP_MOVE) > prefixLowest)) - && (start[-1] == (start-(offset-ZSTD_REP_MOVE))[-1]) ) /* only search for offset within prefix */ - { start--; matchLength++; } - } - if (dictMode == ZSTD_dictMatchState) { - U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE)); - const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex; - const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest; - while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */ - } - offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE); - } - /* store sequence */ -_storeSequence: - { size_t const litLength = start - anchor; - ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offset, matchLength-MINMATCH); - anchor = ip = start + matchLength; - } - - /* check immediate repcode */ - if (dictMode == ZSTD_dictMatchState) { - while (ip <= ilimit) { - U32 const current2 = (U32)(ip-base); - U32 const repIndex = current2 - offset_2; - const BYTE* repMatch = dictMode == ZSTD_dictMatchState - && repIndex < prefixLowestIndex ? - dictBase - dictIndexDelta + repIndex : - base + repIndex; - if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex) >= 3 /* intentional overflow */) - && (MEM_read32(repMatch) == MEM_read32(ip)) ) { - const BYTE* const repEnd2 = repIndex < prefixLowestIndex ? dictEnd : iend; - matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd2, prefixLowest) + 4; - offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset_2 <=> offset_1 */ - ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, matchLength-MINMATCH); - ip += matchLength; - anchor = ip; - continue; - } - break; - } - } - - if (dictMode == ZSTD_noDict) { - while ( ((ip <= ilimit) & (offset_2>0)) - && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) { - /* store sequence */ - matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4; - offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */ - ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, matchLength-MINMATCH); - ip += matchLength; - anchor = ip; - continue; /* faster when present ... (?) */ - } } } - - /* Save reps for next block */ - rep[0] = offset_1 ? offset_1 : savedOffset; - rep[1] = offset_2 ? offset_2 : savedOffset; - - /* Return the last literals size */ - return (size_t)(iend - anchor); -} - - -size_t ZSTD_compressBlock_btlazy2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_noDict); -} - -size_t ZSTD_compressBlock_lazy2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_noDict); -} - -size_t ZSTD_compressBlock_lazy( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_noDict); -} - -size_t ZSTD_compressBlock_greedy( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_noDict); -} - -size_t ZSTD_compressBlock_btlazy2_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_dictMatchState); -} - -size_t ZSTD_compressBlock_lazy2_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dictMatchState); -} - -size_t ZSTD_compressBlock_lazy_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dictMatchState); -} - -size_t ZSTD_compressBlock_greedy_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dictMatchState); -} - - -FORCE_INLINE_TEMPLATE -size_t ZSTD_compressBlock_lazy_extDict_generic( - ZSTD_matchState_t* ms, seqStore_t* seqStore, - U32 rep[ZSTD_REP_NUM], - const void* src, size_t srcSize, - const searchMethod_e searchMethod, const U32 depth) -{ - const BYTE* const istart = (const BYTE*)src; - const BYTE* ip = istart; - const BYTE* anchor = istart; - const BYTE* const iend = istart + srcSize; - const BYTE* const ilimit = iend - 8; - const BYTE* const base = ms->window.base; - const U32 dictLimit = ms->window.dictLimit; - const BYTE* const prefixStart = base + dictLimit; - const BYTE* const dictBase = ms->window.dictBase; - const BYTE* const dictEnd = dictBase + dictLimit; - const BYTE* const dictStart = dictBase + ms->window.lowLimit; - const U32 windowLog = ms->cParams.windowLog; - - typedef size_t (*searchMax_f)( - ZSTD_matchState_t* ms, - const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr); - searchMax_f searchMax = searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_extDict_selectMLS : ZSTD_HcFindBestMatch_extDict_selectMLS; - - U32 offset_1 = rep[0], offset_2 = rep[1]; - - DEBUGLOG(5, "ZSTD_compressBlock_lazy_extDict_generic"); - - /* init */ - ip += (ip == prefixStart); - - /* Match Loop */ -#if defined(__GNUC__) && defined(__x86_64__) - /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the - * code alignment is perturbed. To fix the instability align the loop on 32-bytes. - */ - __asm__(".p2align 5"); -#endif - while (ip < ilimit) { - size_t matchLength=0; - size_t offset=0; - const BYTE* start=ip+1; - U32 current = (U32)(ip-base); - - /* check repCode */ - { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current+1, windowLog); - const U32 repIndex = (U32)(current+1 - offset_1); - const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; - const BYTE* const repMatch = repBase + repIndex; - if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ - if (MEM_read32(ip+1) == MEM_read32(repMatch)) { - /* repcode detected we should take it */ - const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; - matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repEnd, prefixStart) + 4; - if (depth==0) goto _storeSequence; - } } - - /* first search (depth 0) */ - { size_t offsetFound = 999999999; - size_t const ml2 = searchMax(ms, ip, iend, &offsetFound); - if (ml2 > matchLength) - matchLength = ml2, start = ip, offset=offsetFound; - } - - if (matchLength < 4) { - ip += ((ip-anchor) >> kSearchStrength) + 1; /* jump faster over incompressible sections */ - continue; - } - - /* let's try to find a better solution */ - if (depth>=1) - while (ip= 3) & (repIndex > windowLow)) /* intentional overflow */ - if (MEM_read32(ip) == MEM_read32(repMatch)) { - /* repcode detected */ - const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; - size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4; - int const gain2 = (int)(repLength * 3); - int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1); - if ((repLength >= 4) && (gain2 > gain1)) - matchLength = repLength, offset = 0, start = ip; - } } - - /* search match, depth 1 */ - { size_t offset2=999999999; - size_t const ml2 = searchMax(ms, ip, iend, &offset2); - int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */ - int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4); - if ((ml2 >= 4) && (gain2 > gain1)) { - matchLength = ml2, offset = offset2, start = ip; - continue; /* search a better one */ - } } - - /* let's find an even better one */ - if ((depth==2) && (ip= 3) & (repIndex > windowLow)) /* intentional overflow */ - if (MEM_read32(ip) == MEM_read32(repMatch)) { - /* repcode detected */ - const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; - size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4; - int const gain2 = (int)(repLength * 4); - int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1); - if ((repLength >= 4) && (gain2 > gain1)) - matchLength = repLength, offset = 0, start = ip; - } } - - /* search match, depth 2 */ - { size_t offset2=999999999; - size_t const ml2 = searchMax(ms, ip, iend, &offset2); - int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */ - int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7); - if ((ml2 >= 4) && (gain2 > gain1)) { - matchLength = ml2, offset = offset2, start = ip; - continue; - } } } - break; /* nothing found : store previous solution */ - } - - /* catch up */ - if (offset) { - U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE)); - const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex; - const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart; - while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */ - offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE); - } - - /* store sequence */ -_storeSequence: - { size_t const litLength = start - anchor; - ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offset, matchLength-MINMATCH); - anchor = ip = start + matchLength; - } - - /* check immediate repcode */ - while (ip <= ilimit) { - const U32 repCurrent = (U32)(ip-base); - const U32 windowLow = ZSTD_getLowestMatchIndex(ms, repCurrent, windowLog); - const U32 repIndex = repCurrent - offset_2; - const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; - const BYTE* const repMatch = repBase + repIndex; - if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ - if (MEM_read32(ip) == MEM_read32(repMatch)) { - /* repcode detected we should take it */ - const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend; - matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4; - offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset history */ - ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, matchLength-MINMATCH); - ip += matchLength; - anchor = ip; - continue; /* faster when present ... (?) */ - } - break; - } } - - /* Save reps for next block */ - rep[0] = offset_1; - rep[1] = offset_2; - - /* Return the last literals size */ - return (size_t)(iend - anchor); -} - - -size_t ZSTD_compressBlock_greedy_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) -{ - return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0); -} - -size_t ZSTD_compressBlock_lazy_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) - -{ - return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1); -} - -size_t ZSTD_compressBlock_lazy2_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) - -{ - return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2); -} - -size_t ZSTD_compressBlock_btlazy2_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize) - -{ - return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2); -} - -} diff --git a/third_party/zstd/compress/zstd_ldm.cpp b/third_party/zstd/compress/zstd_ldm.c similarity index 53% rename from third_party/zstd/compress/zstd_ldm.cpp rename to third_party/zstd/compress/zstd_ldm.c index ee2480bfb0c..17c069fe1d7 100644 --- a/third_party/zstd/compress/zstd_ldm.cpp +++ b/third_party/zstd/compress/zstd_ldm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -8,18 +8,129 @@ * You may select, at your option, one of the above-listed licenses. */ -#include "zstd/compress/zstd_ldm.h" +#include "zstd_ldm.h" -#include "zstd/common/debug.h" -#include "zstd/compress/zstd_fast.h" /* ZSTD_fillHashTable() */ -#include "zstd/compress/zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */ +#include "../common/debug.h" +#include "../common/xxhash.h" +#include "zstd_fast.h" /* ZSTD_fillHashTable() */ +#include "zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */ +#include "zstd_ldm_geartab.h" #define LDM_BUCKET_SIZE_LOG 3 #define LDM_MIN_MATCH_LENGTH 64 #define LDM_HASH_RLOG 7 -#define LDM_HASH_CHAR_OFFSET 10 -namespace duckdb_zstd { +typedef struct { + U64 rolling; + U64 stopMask; +} ldmRollingHashState_t; + +/** ZSTD_ldm_gear_init(): + * + * Initializes the rolling hash state such that it will honor the + * settings in params. */ +static void ZSTD_ldm_gear_init(ldmRollingHashState_t* state, ldmParams_t const* params) +{ + unsigned maxBitsInMask = MIN(params->minMatchLength, 64); + unsigned hashRateLog = params->hashRateLog; + + state->rolling = ~(U32)0; + + /* The choice of the splitting criterion is subject to two conditions: + * 1. it has to trigger on average every 2^(hashRateLog) bytes; + * 2. ideally, it has to depend on a window of minMatchLength bytes. + * + * In the gear hash algorithm, bit n depends on the last n bytes; + * so in order to obtain a good quality splitting criterion it is + * preferable to use bits with high weight. + * + * To match condition 1 we use a mask with hashRateLog bits set + * and, because of the previous remark, we make sure these bits + * have the highest possible weight while still respecting + * condition 2. + */ + if (hashRateLog > 0 && hashRateLog <= maxBitsInMask) { + state->stopMask = (((U64)1 << hashRateLog) - 1) << (maxBitsInMask - hashRateLog); + } else { + /* In this degenerate case we simply honor the hash rate. */ + state->stopMask = ((U64)1 << hashRateLog) - 1; + } +} + +/** ZSTD_ldm_gear_reset() + * Feeds [data, data + minMatchLength) into the hash without registering any + * splits. This effectively resets the hash state. This is used when skipping + * over data, either at the beginning of a block, or skipping sections. + */ +static void ZSTD_ldm_gear_reset(ldmRollingHashState_t* state, + BYTE const* data, size_t minMatchLength) +{ + U64 hash = state->rolling; + size_t n = 0; + +#define GEAR_ITER_ONCE() do { \ + hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \ + n += 1; \ + } while (0) + while (n + 3 < minMatchLength) { + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + } + while (n < minMatchLength) { + GEAR_ITER_ONCE(); + } +#undef GEAR_ITER_ONCE +} + +/** ZSTD_ldm_gear_feed(): + * + * Registers in the splits array all the split points found in the first + * size bytes following the data pointer. This function terminates when + * either all the data has been processed or LDM_BATCH_SIZE splits are + * present in the splits array. + * + * Precondition: The splits array must not be full. + * Returns: The number of bytes processed. */ +static size_t ZSTD_ldm_gear_feed(ldmRollingHashState_t* state, + BYTE const* data, size_t size, + size_t* splits, unsigned* numSplits) +{ + size_t n; + U64 hash, mask; + + hash = state->rolling; + mask = state->stopMask; + n = 0; + +#define GEAR_ITER_ONCE() do { \ + hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \ + n += 1; \ + if (UNLIKELY((hash & mask) == 0)) { \ + splits[*numSplits] = n; \ + *numSplits += 1; \ + if (*numSplits == LDM_BATCH_SIZE) \ + goto done; \ + } \ + } while (0) + + while (n + 3 < size) { + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + GEAR_ITER_ONCE(); + } + while (n < size) { + GEAR_ITER_ONCE(); + } + +#undef GEAR_ITER_ONCE + +done: + state->rolling = hash; + return n; +} void ZSTD_ldm_adjustParameters(ldmParams_t* params, ZSTD_compressionParameters const* cParams) @@ -29,13 +140,6 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, DEBUGLOG(4, "ZSTD_ldm_adjustParameters"); if (!params->bucketSizeLog) params->bucketSizeLog = LDM_BUCKET_SIZE_LOG; if (!params->minMatchLength) params->minMatchLength = LDM_MIN_MATCH_LENGTH; - if (cParams->strategy >= ZSTD_btopt) { - /* Get out of the way of the optimal parser */ - U32 const minMatch = MAX(cParams->targetLength, params->minMatchLength); - assert(minMatch >= ZSTD_LDM_MINMATCH_MIN); - assert(minMatch <= ZSTD_LDM_MINMATCH_MAX); - params->minMatchLength = minMatch; - } if (params->hashLog == 0) { params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - LDM_HASH_RLOG); assert(params->hashLog <= ZSTD_HASHLOG_MAX); @@ -55,47 +159,12 @@ size_t ZSTD_ldm_getTableSize(ldmParams_t params) size_t const ldmBucketSize = ((size_t)1) << (params.hashLog - ldmBucketSizeLog); size_t const totalSize = ZSTD_cwksp_alloc_size(ldmBucketSize) + ZSTD_cwksp_alloc_size(ldmHSize * sizeof(ldmEntry_t)); - return params.enableLdm ? totalSize : 0; + return params.enableLdm == ZSTD_ps_enable ? totalSize : 0; } size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize) { - return params.enableLdm ? (maxChunkSize / params.minMatchLength) : 0; -} - -/** ZSTD_ldm_getSmallHash() : - * numBits should be <= 32 - * If numBits==0, returns 0. - * @return : the most significant numBits of value. */ -static U32 ZSTD_ldm_getSmallHash(U64 value, U32 numBits) -{ - assert(numBits <= 32); - return numBits == 0 ? 0 : (U32)(value >> (64 - numBits)); -} - -/** ZSTD_ldm_getChecksum() : - * numBitsToDiscard should be <= 32 - * @return : the next most significant 32 bits after numBitsToDiscard */ -static U32 ZSTD_ldm_getChecksum(U64 hash, U32 numBitsToDiscard) -{ - assert(numBitsToDiscard <= 32); - return (hash >> (64 - 32 - numBitsToDiscard)) & 0xFFFFFFFF; -} - -/** ZSTD_ldm_getTag() ; - * Given the hash, returns the most significant numTagBits bits - * after (32 + hbits) bits. - * - * If there are not enough bits remaining, return the last - * numTagBits bits. */ -static U32 ZSTD_ldm_getTag(U64 hash, U32 hbits, U32 numTagBits) -{ - assert(numTagBits < 32 && hbits <= 32); - if (32 - hbits < numTagBits) { - return hash & (((U32)1 << numTagBits) - 1); - } else { - return (hash >> (32 - hbits - numTagBits)) & (((U32)1 << numTagBits) - 1); - } + return params.enableLdm == ZSTD_ps_enable ? (maxChunkSize / params.minMatchLength) : 0; } /** ZSTD_ldm_getBucket() : @@ -112,38 +181,12 @@ static void ZSTD_ldm_insertEntry(ldmState_t* ldmState, size_t const hash, const ldmEntry_t entry, ldmParams_t const ldmParams) { - BYTE* const bucketOffsets = ldmState->bucketOffsets; - *(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + bucketOffsets[hash]) = entry; - bucketOffsets[hash]++; - bucketOffsets[hash] &= ((U32)1 << ldmParams.bucketSizeLog) - 1; -} + BYTE* const pOffset = ldmState->bucketOffsets + hash; + unsigned const offset = *pOffset; + + *(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + offset) = entry; + *pOffset = (BYTE)((offset + 1) & ((1u << ldmParams.bucketSizeLog) - 1)); -/** ZSTD_ldm_makeEntryAndInsertByTag() : - * - * Gets the small hash, checksum, and tag from the rollingHash. - * - * If the tag matches (1 << ldmParams.hashRateLog)-1, then - * creates an ldmEntry from the offset, and inserts it into the hash table. - * - * hBits is the length of the small hash, which is the most significant hBits - * of rollingHash. The checksum is the next 32 most significant bits, followed - * by ldmParams.hashRateLog bits that make up the tag. */ -static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState, - U64 const rollingHash, - U32 const hBits, - U32 const offset, - ldmParams_t const ldmParams) -{ - U32 const tag = ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashRateLog); - U32 const tagMask = ((U32)1 << ldmParams.hashRateLog) - 1; - if (tag == tagMask) { - U32 const hash = ZSTD_ldm_getSmallHash(rollingHash, hBits); - U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits); - ldmEntry_t entry; - entry.offset = offset; - entry.checksum = checksum; - ZSTD_ldm_insertEntry(ldmState, hash, entry, ldmParams); - } } /** ZSTD_ldm_countBackwardsMatch() : @@ -152,10 +195,10 @@ static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState, * We count only bytes where pMatch >= pBase and pIn >= pAnchor. */ static size_t ZSTD_ldm_countBackwardsMatch( const BYTE* pIn, const BYTE* pAnchor, - const BYTE* pMatch, const BYTE* pBase) + const BYTE* pMatch, const BYTE* pMatchBase) { size_t matchLength = 0; - while (pIn > pAnchor && pMatch > pBase && pIn[-1] == pMatch[-1]) { + while (pIn > pAnchor && pMatch > pMatchBase && pIn[-1] == pMatch[-1]) { pIn--; pMatch--; matchLength++; @@ -163,6 +206,27 @@ static size_t ZSTD_ldm_countBackwardsMatch( return matchLength; } +/** ZSTD_ldm_countBackwardsMatch_2segments() : + * Returns the number of bytes that match backwards from pMatch, + * even with the backwards match spanning 2 different segments. + * + * On reaching `pMatchBase`, start counting from mEnd */ +static size_t ZSTD_ldm_countBackwardsMatch_2segments( + const BYTE* pIn, const BYTE* pAnchor, + const BYTE* pMatch, const BYTE* pMatchBase, + const BYTE* pExtDictStart, const BYTE* pExtDictEnd) +{ + size_t matchLength = ZSTD_ldm_countBackwardsMatch(pIn, pAnchor, pMatch, pMatchBase); + if (pMatch - matchLength != pMatchBase || pMatchBase == pExtDictStart) { + /* If backwards match is entirely in the extDict or prefix, immediately return */ + return matchLength; + } + DEBUGLOG(7, "ZSTD_ldm_countBackwardsMatch_2segments: found 2-parts backwards match (length in prefix==%zu)", matchLength); + matchLength += ZSTD_ldm_countBackwardsMatch(pIn - matchLength, pAnchor, pExtDictEnd, pExtDictStart); + DEBUGLOG(7, "final backwards match length = %zu", matchLength); + return matchLength; +} + /** ZSTD_ldm_fillFastTables() : * * Fills the relevant tables for the ZSTD_fast and ZSTD_dfast strategies. @@ -178,11 +242,15 @@ static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms, switch(ms->cParams.strategy) { case ZSTD_fast: - ZSTD_fillHashTable(ms, iend, ZSTD_dtlm_fast); + ZSTD_fillHashTable(ms, iend, ZSTD_dtlm_fast, ZSTD_tfp_forCCtx); break; case ZSTD_dfast: - ZSTD_fillDoubleHashTable(ms, iend, ZSTD_dtlm_fast); +#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR + ZSTD_fillDoubleHashTable(ms, iend, ZSTD_dtlm_fast, ZSTD_tfp_forCCtx); +#else + assert(0); /* shouldn't be called: cparams should've been adjusted. */ +#endif break; case ZSTD_greedy: @@ -200,43 +268,42 @@ static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms, return 0; } -/** ZSTD_ldm_fillLdmHashTable() : - * - * Fills hashTable from (lastHashed + 1) to iend (non-inclusive). - * lastHash is the rolling hash that corresponds to lastHashed. - * - * Returns the rolling hash corresponding to position iend-1. */ -static U64 ZSTD_ldm_fillLdmHashTable(ldmState_t* state, - U64 lastHash, const BYTE* lastHashed, - const BYTE* iend, const BYTE* base, - U32 hBits, ldmParams_t const ldmParams) -{ - U64 rollingHash = lastHash; - const BYTE* cur = lastHashed + 1; - - while (cur < iend) { - rollingHash = ZSTD_rollingHash_rotate(rollingHash, cur[-1], - cur[ldmParams.minMatchLength-1], - state->hashPower); - ZSTD_ldm_makeEntryAndInsertByTag(state, - rollingHash, hBits, - (U32)(cur - base), ldmParams); - ++cur; - } - return rollingHash; -} - void ZSTD_ldm_fillHashTable( - ldmState_t* state, const BYTE* ip, + ldmState_t* ldmState, const BYTE* ip, const BYTE* iend, ldmParams_t const* params) { + U32 const minMatchLength = params->minMatchLength; + U32 const hBits = params->hashLog - params->bucketSizeLog; + BYTE const* const base = ldmState->window.base; + BYTE const* const istart = ip; + ldmRollingHashState_t hashState; + size_t* const splits = ldmState->splitIndices; + unsigned numSplits; + DEBUGLOG(5, "ZSTD_ldm_fillHashTable"); - if ((size_t)(iend - ip) >= params->minMatchLength) { - U64 startingHash = ZSTD_rollingHash_compute(ip, params->minMatchLength); - ZSTD_ldm_fillLdmHashTable( - state, startingHash, ip, iend - params->minMatchLength, state->window.base, - params->hashLog - params->bucketSizeLog, - *params); + + ZSTD_ldm_gear_init(&hashState, params); + while (ip < iend) { + size_t hashed; + unsigned n; + + numSplits = 0; + hashed = ZSTD_ldm_gear_feed(&hashState, ip, iend - ip, splits, &numSplits); + + for (n = 0; n < numSplits; n++) { + if (ip + splits[n] >= istart + minMatchLength) { + BYTE const* const split = ip + splits[n] - minMatchLength; + U64 const xxhash = XXH64(split, minMatchLength, 0); + U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1)); + ldmEntry_t entry; + + entry.offset = (U32)(split - base); + entry.checksum = (U32)(xxhash >> 32); + ZSTD_ldm_insertEntry(ldmState, hash, entry, *params); + } + } + + ip += hashed; } } @@ -248,25 +315,24 @@ void ZSTD_ldm_fillHashTable( * (after a long match, only update tables a limited amount). */ static void ZSTD_ldm_limitTableUpdate(ZSTD_matchState_t* ms, const BYTE* anchor) { - U32 const current = (U32)(anchor - ms->window.base); - if (current > ms->nextToUpdate + 1024) { + U32 const curr = (U32)(anchor - ms->window.base); + if (curr > ms->nextToUpdate + 1024) { ms->nextToUpdate = - current - MIN(512, current - ms->nextToUpdate - 1024); + curr - MIN(512, curr - ms->nextToUpdate - 1024); } } -static size_t ZSTD_ldm_generateSequences_internal( +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_ldm_generateSequences_internal( ldmState_t* ldmState, rawSeqStore_t* rawSeqStore, ldmParams_t const* params, void const* src, size_t srcSize) { /* LDM parameters */ int const extDict = ZSTD_window_hasExtDict(ldmState->window); U32 const minMatchLength = params->minMatchLength; - U64 const hashPower = ldmState->hashPower; + U32 const entsPerBucket = 1U << params->bucketSizeLog; U32 const hBits = params->hashLog - params->bucketSizeLog; - U32 const ldmBucketSize = 1U << params->bucketSizeLog; - U32 const hashRateLog = params->hashRateLog; - U32 const ldmTagMask = (1U << params->hashRateLog) - 1; /* Prefix and extDict parameters */ U32 const dictLimit = ldmState->window.dictLimit; U32 const lowestIndex = extDict ? ldmState->window.lowLimit : dictLimit; @@ -278,45 +344,69 @@ static size_t ZSTD_ldm_generateSequences_internal( /* Input bounds */ BYTE const* const istart = (BYTE const*)src; BYTE const* const iend = istart + srcSize; - BYTE const* const ilimit = iend - MAX(minMatchLength, HASH_READ_SIZE); + BYTE const* const ilimit = iend - HASH_READ_SIZE; /* Input positions */ BYTE const* anchor = istart; BYTE const* ip = istart; - /* Rolling hash */ - BYTE const* lastHashed = NULL; - U64 rollingHash = 0; - - while (ip <= ilimit) { - size_t mLength; - U32 const current = (U32)(ip - base); - size_t forwardMatchLength = 0, backwardMatchLength = 0; - ldmEntry_t* bestEntry = NULL; - if (ip != istart) { - rollingHash = ZSTD_rollingHash_rotate(rollingHash, lastHashed[0], - lastHashed[minMatchLength], - hashPower); - } else { - rollingHash = ZSTD_rollingHash_compute(ip, minMatchLength); + /* Rolling hash state */ + ldmRollingHashState_t hashState; + /* Arrays for staged-processing */ + size_t* const splits = ldmState->splitIndices; + ldmMatchCandidate_t* const candidates = ldmState->matchCandidates; + unsigned numSplits; + + if (srcSize < minMatchLength) + return iend - anchor; + + /* Initialize the rolling hash state with the first minMatchLength bytes */ + ZSTD_ldm_gear_init(&hashState, params); + ZSTD_ldm_gear_reset(&hashState, ip, minMatchLength); + ip += minMatchLength; + + while (ip < ilimit) { + size_t hashed; + unsigned n; + + numSplits = 0; + hashed = ZSTD_ldm_gear_feed(&hashState, ip, ilimit - ip, + splits, &numSplits); + + for (n = 0; n < numSplits; n++) { + BYTE const* const split = ip + splits[n] - minMatchLength; + U64 const xxhash = XXH64(split, minMatchLength, 0); + U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1)); + + candidates[n].split = split; + candidates[n].hash = hash; + candidates[n].checksum = (U32)(xxhash >> 32); + candidates[n].bucket = ZSTD_ldm_getBucket(ldmState, hash, *params); + PREFETCH_L1(candidates[n].bucket); } - lastHashed = ip; - /* Do not insert and do not look for a match */ - if (ZSTD_ldm_getTag(rollingHash, hBits, hashRateLog) != ldmTagMask) { - ip++; - continue; - } + for (n = 0; n < numSplits; n++) { + size_t forwardMatchLength = 0, backwardMatchLength = 0, + bestMatchLength = 0, mLength; + U32 offset; + BYTE const* const split = candidates[n].split; + U32 const checksum = candidates[n].checksum; + U32 const hash = candidates[n].hash; + ldmEntry_t* const bucket = candidates[n].bucket; + ldmEntry_t const* cur; + ldmEntry_t const* bestEntry = NULL; + ldmEntry_t newEntry; + + newEntry.offset = (U32)(split - base); + newEntry.checksum = checksum; + + /* If a split point would generate a sequence overlapping with + * the previous one, we merely register it in the hash table and + * move on */ + if (split < anchor) { + ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params); + continue; + } - /* Get the best entry and compute the match lengths */ - { - ldmEntry_t* const bucket = - ZSTD_ldm_getBucket(ldmState, - ZSTD_ldm_getSmallHash(rollingHash, hBits), - *params); - ldmEntry_t* cur; - size_t bestMatchLength = 0; - U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits); - - for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) { + for (cur = bucket; cur < bucket + entsPerBucket; cur++) { size_t curForwardMatchLength, curBackwardMatchLength, curTotalMatchLength; if (cur->checksum != checksum || cur->offset <= lowestIndex) { @@ -330,30 +420,23 @@ static size_t ZSTD_ldm_generateSequences_internal( cur->offset < dictLimit ? dictEnd : iend; BYTE const* const lowMatchPtr = cur->offset < dictLimit ? dictStart : lowPrefixPtr; - - curForwardMatchLength = ZSTD_count_2segments( - ip, pMatch, iend, - matchEnd, lowPrefixPtr); + curForwardMatchLength = + ZSTD_count_2segments(split, pMatch, iend, matchEnd, lowPrefixPtr); if (curForwardMatchLength < minMatchLength) { continue; } - curBackwardMatchLength = - ZSTD_ldm_countBackwardsMatch(ip, anchor, pMatch, - lowMatchPtr); - curTotalMatchLength = curForwardMatchLength + - curBackwardMatchLength; + curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch_2segments( + split, anchor, pMatch, lowMatchPtr, dictStart, dictEnd); } else { /* !extDict */ BYTE const* const pMatch = base + cur->offset; - curForwardMatchLength = ZSTD_count(ip, pMatch, iend); + curForwardMatchLength = ZSTD_count(split, pMatch, iend); if (curForwardMatchLength < minMatchLength) { continue; } curBackwardMatchLength = - ZSTD_ldm_countBackwardsMatch(ip, anchor, pMatch, - lowPrefixPtr); - curTotalMatchLength = curForwardMatchLength + - curBackwardMatchLength; + ZSTD_ldm_countBackwardsMatch(split, anchor, pMatch, lowPrefixPtr); } + curTotalMatchLength = curForwardMatchLength + curBackwardMatchLength; if (curTotalMatchLength > bestMatchLength) { bestMatchLength = curTotalMatchLength; @@ -362,57 +445,54 @@ static size_t ZSTD_ldm_generateSequences_internal( bestEntry = cur; } } - } - /* No match found -- continue searching */ - if (bestEntry == NULL) { - ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, - hBits, current, - *params); - ip++; - continue; - } - - /* Match found */ - mLength = forwardMatchLength + backwardMatchLength; - ip -= backwardMatchLength; + /* No match found -- insert an entry into the hash table + * and process the next candidate match */ + if (bestEntry == NULL) { + ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params); + continue; + } - { - /* Store the sequence: - * ip = current - backwardMatchLength - * The match is at (bestEntry->offset - backwardMatchLength) - */ - U32 const matchIndex = bestEntry->offset; - U32 const offset = current - matchIndex; - rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size; - - /* Out of sequence storage */ - if (rawSeqStore->size == rawSeqStore->capacity) - return ERROR(dstSize_tooSmall); - seq->litLength = (U32)(ip - anchor); - seq->matchLength = (U32)mLength; - seq->offset = offset; - rawSeqStore->size++; - } + /* Match found */ + offset = (U32)(split - base) - bestEntry->offset; + mLength = forwardMatchLength + backwardMatchLength; + { + rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size; + + /* Out of sequence storage */ + if (rawSeqStore->size == rawSeqStore->capacity) + return ERROR(dstSize_tooSmall); + seq->litLength = (U32)(split - backwardMatchLength - anchor); + seq->matchLength = (U32)mLength; + seq->offset = offset; + rawSeqStore->size++; + } - /* Insert the current entry into the hash table */ - ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits, - (U32)(lastHashed - base), - *params); + /* Insert the current entry into the hash table --- it must be + * done after the previous block to avoid clobbering bestEntry */ + ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params); - assert(ip + backwardMatchLength == lastHashed); + anchor = split + forwardMatchLength; - /* Fill the hash table from lastHashed+1 to ip+mLength*/ - /* Heuristic: don't need to fill the entire table at end of block */ - if (ip + mLength <= ilimit) { - rollingHash = ZSTD_ldm_fillLdmHashTable( - ldmState, rollingHash, lastHashed, - ip + mLength, base, hBits, *params); - lastHashed = ip + mLength - 1; + /* If we find a match that ends after the data that we've hashed + * then we have a repeating, overlapping, pattern. E.g. all zeros. + * If one repetition of the pattern matches our `stopMask` then all + * repetitions will. We don't need to insert them all into out table, + * only the first one. So skip over overlapping matches. + * This is a major speed boost (20x) for compressing a single byte + * repeated, when that byte ends up in the table. + */ + if (anchor > ip + hashed) { + ZSTD_ldm_gear_reset(&hashState, anchor - minMatchLength, minMatchLength); + /* Continue the outer loop at anchor (ip + hashed == anchor). */ + ip = anchor - hashed; + break; + } } - ip += mLength; - anchor = ip; + + ip += hashed; } + return iend - anchor; } @@ -461,7 +541,7 @@ size_t ZSTD_ldm_generateSequences( assert(chunkStart < iend); /* 1. Perform overflow correction if necessary. */ - if (ZSTD_window_needOverflowCorrection(ldmState->window, chunkEnd)) { + if (ZSTD_window_needOverflowCorrection(ldmState->window, 0, maxDist, ldmState->loadedDictEnd, chunkStart, chunkEnd)) { U32 const ldmHSize = 1U << params->hashLog; U32 const correction = ZSTD_window_correctOverflow( &ldmState->window, /* cycleLog */ 0, maxDist, chunkStart); @@ -475,7 +555,7 @@ size_t ZSTD_ldm_generateSequences( * the window through early invalidation. * TODO: * Test the chunk size. * * Try invalidation after the sequence generation and test the - * the offset against maxDist directly. + * offset against maxDist directly. * * NOTE: Because of dictionaries + sequence splitting we MUST make sure * that any offset used is valid at the END of the sequence, since it may @@ -505,7 +585,9 @@ size_t ZSTD_ldm_generateSequences( return 0; } -void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) { +void +ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) +{ while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) { rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos; if (srcSize <= seq->litLength) { @@ -564,14 +646,32 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore, return sequence; } +void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) { + U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes); + while (currPos && rawSeqStore->pos < rawSeqStore->size) { + rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos]; + if (currPos >= currSeq.litLength + currSeq.matchLength) { + currPos -= currSeq.litLength + currSeq.matchLength; + rawSeqStore->pos++; + } else { + rawSeqStore->posInSequence = currPos; + break; + } + } + if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) { + rawSeqStore->posInSequence = 0; + } +} + size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_paramSwitch_e useRowMatchFinder, void const* src, size_t srcSize) { const ZSTD_compressionParameters* const cParams = &ms->cParams; unsigned const minMatch = cParams->minMatch; ZSTD_blockCompressor const blockCompressor = - ZSTD_selectBlockCompressor(cParams->strategy, ZSTD_matchState_dictMode(ms)); + ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms)); /* Input bounds */ BYTE const* const istart = (BYTE const*)src; BYTE const* const iend = istart + srcSize; @@ -579,14 +679,22 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, BYTE const* ip = istart; DEBUGLOG(5, "ZSTD_ldm_blockCompress: srcSize=%zu", srcSize); + /* If using opt parser, use LDMs only as candidates rather than always accepting them */ + if (cParams->strategy >= ZSTD_btopt) { + size_t lastLLSize; + ms->ldmSeqStore = rawSeqStore; + lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize); + ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize); + return lastLLSize; + } + assert(rawSeqStore->pos <= rawSeqStore->size); assert(rawSeqStore->size <= rawSeqStore->capacity); - /* Loop through each sequence and apply the block compressor to the lits */ + /* Loop through each sequence and apply the block compressor to the literals */ while (rawSeqStore->pos < rawSeqStore->size && ip < iend) { /* maybeSplitSequence updates rawSeqStore->pos */ rawSeq const sequence = maybeSplitSequence(rawSeqStore, (U32)(iend - ip), minMatch); - int i; /* End signal */ if (sequence.offset == 0) break; @@ -599,6 +707,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, /* Run the block compressor */ DEBUGLOG(5, "pos %u : calling block compressor on segment of size %u", (unsigned)(ip-istart), sequence.litLength); { + int i; size_t const newLitLength = blockCompressor(ms, seqStore, rep, ip, sequence.litLength); ip += sequence.litLength; @@ -608,8 +717,8 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, rep[0] = sequence.offset; /* Store the sequence */ ZSTD_storeSeq(seqStore, newLitLength, ip - newLitLength, iend, - sequence.offset + ZSTD_REP_MOVE, - sequence.matchLength - MINMATCH); + OFFSET_TO_OFFBASE(sequence.offset), + sequence.matchLength); ip += sequence.matchLength; } } @@ -619,5 +728,3 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, /* Compress the last literals */ return blockCompressor(ms, seqStore, rep, ip, iend - ip); } - -} diff --git a/third_party/zstd/compress/zstd_opt.cpp b/third_party/zstd/compress/zstd_opt.c similarity index 53% rename from third_party/zstd/compress/zstd_opt.cpp rename to third_party/zstd/compress/zstd_opt.c index 09e9bff21e4..e63073e5a4f 100644 --- a/third_party/zstd/compress/zstd_opt.cpp +++ b/third_party/zstd/compress/zstd_opt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -8,48 +8,56 @@ * You may select, at your option, one of the above-listed licenses. */ -#include "zstd/compress/zstd_compress_internal.h" -#include "zstd/compress/hist.h" -#include "zstd/compress/zstd_opt.h" +#include "zstd_compress_internal.h" +#include "hist.h" +#include "zstd_opt.h" +#if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR) #define ZSTD_LITFREQ_ADD 2 /* scaling factor for litFreq, so that frequencies adapt faster to new stats */ -#define ZSTD_FREQ_DIV 4 /* log factor when using previous stats to init next stats */ #define ZSTD_MAX_PRICE (1<<30) -#define ZSTD_PREDEF_THRESHOLD 1024 /* if srcSize < ZSTD_PREDEF_THRESHOLD, symbols' cost is assumed static, directly determined by pre-defined distributions */ +#define ZSTD_PREDEF_THRESHOLD 8 /* if srcSize < ZSTD_PREDEF_THRESHOLD, symbols' cost is assumed static, directly determined by pre-defined distributions */ /*-************************************* * Price functions for optimal parser ***************************************/ -#if 0 /* approximation at bit level */ +#if 0 /* approximation at bit level (for tests) */ # define BITCOST_ACCURACY 0 # define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY) -# define WEIGHT(stat) ((void)opt, ZSTD_bitWeight(stat)) -#elif 0 /* fractional bit accuracy */ +# define WEIGHT(stat, opt) ((void)(opt), ZSTD_bitWeight(stat)) +#elif 0 /* fractional bit accuracy (for tests) */ # define BITCOST_ACCURACY 8 # define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY) -# define WEIGHT(stat,opt) ((void)opt, ZSTD_fracWeight(stat)) +# define WEIGHT(stat,opt) ((void)(opt), ZSTD_fracWeight(stat)) #else /* opt==approx, ultra==accurate */ # define BITCOST_ACCURACY 8 # define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY) -# define WEIGHT(stat,opt) (opt ? ZSTD_fracWeight(stat) : ZSTD_bitWeight(stat)) +# define WEIGHT(stat,opt) ((opt) ? ZSTD_fracWeight(stat) : ZSTD_bitWeight(stat)) #endif -namespace duckdb_zstd { - +/* ZSTD_bitWeight() : + * provide estimated "cost" of a stat in full bits only */ MEM_STATIC U32 ZSTD_bitWeight(U32 stat) { return (ZSTD_highbit32(stat+1) * BITCOST_MULTIPLIER); } +/* ZSTD_fracWeight() : + * provide fractional-bit "cost" of a stat, + * using linear interpolation approximation */ MEM_STATIC U32 ZSTD_fracWeight(U32 rawStat) { U32 const stat = rawStat + 1; U32 const hb = ZSTD_highbit32(stat); U32 const BWeight = hb * BITCOST_MULTIPLIER; + /* Fweight was meant for "Fractional weight" + * but it's effectively a value between 1 and 2 + * using fixed point arithmetic */ U32 const FWeight = (stat << BITCOST_ACCURACY) >> hb; U32 const weight = BWeight + FWeight; assert(hb + BITCOST_ACCURACY < 31); @@ -60,7 +68,7 @@ MEM_STATIC U32 ZSTD_fracWeight(U32 rawStat) /* debugging function, * @return price in bytes as fractional value * for debug messages only */ -MEM_STATIC double ZSTD_fCost(U32 price) +MEM_STATIC double ZSTD_fCost(int price) { return (double)price / (BITCOST_MULTIPLIER*8); } @@ -68,7 +76,7 @@ MEM_STATIC double ZSTD_fCost(U32 price) static int ZSTD_compressedLiterals(optState_t const* const optPtr) { - return optPtr->literalCompressionMode != ZSTD_lcm_uncompressed; + return optPtr->literalCompressionMode != ZSTD_ps_disable; } static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel) @@ -81,25 +89,52 @@ static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel) } -/* ZSTD_downscaleStat() : - * reduce all elements in table by a factor 2^(ZSTD_FREQ_DIV+malus) - * return the resulting sum of elements */ -static U32 ZSTD_downscaleStat(unsigned* table, U32 lastEltIndex, int malus) +static U32 sum_u32(const unsigned table[], size_t nbElts) +{ + size_t n; + U32 total = 0; + for (n=0; n 0 && ZSTD_FREQ_DIV+malus < 31); + DEBUGLOG(5, "ZSTD_downscaleStats (nbElts=%u, shift=%u)", + (unsigned)lastEltIndex+1, (unsigned)shift ); + assert(shift < 30); for (s=0; s> (ZSTD_FREQ_DIV+malus)); - sum += table[s]; + unsigned const base = base1 ? 1 : (table[s]>0); + unsigned const newStat = base + (table[s] >> shift); + sum += newStat; + table[s] = newStat; } return sum; } +/* ZSTD_scaleStats() : + * reduce all elt frequencies in table if sum too large + * return the resulting sum of elements */ +static U32 ZSTD_scaleStats(unsigned* table, U32 lastEltIndex, U32 logTarget) +{ + U32 const prevsum = sum_u32(table, lastEltIndex+1); + U32 const factor = prevsum >> logTarget; + DEBUGLOG(5, "ZSTD_scaleStats (nbElts=%u, target=%u)", (unsigned)lastEltIndex+1, (unsigned)logTarget); + assert(logTarget < 30); + if (factor <= 1) return prevsum; + return ZSTD_downscaleStats(table, lastEltIndex, ZSTD_highbit32(factor), base_1guaranteed); +} + /* ZSTD_rescaleFreqs() : * if first block (detected by optPtr->litLengthSum == 0) : init statistics * take hints from dictionary if there is one - * or init from zero, using src for literals stats, or flat 1 for match symbols + * and init from zero if there is none, + * using src for literals stats, and baseline stats for sequence symbols * otherwise downscale existing stats, to be used as seed for next block. */ static void @@ -111,24 +146,28 @@ ZSTD_rescaleFreqs(optState_t* const optPtr, DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize); optPtr->priceType = zop_dynamic; - if (optPtr->litLengthSum == 0) { /* first block : init */ - if (srcSize <= ZSTD_PREDEF_THRESHOLD) { /* heuristic */ - DEBUGLOG(5, "(srcSize <= ZSTD_PREDEF_THRESHOLD) => zop_predef"); + if (optPtr->litLengthSum == 0) { /* no literals stats collected -> first block assumed -> init */ + + /* heuristic: use pre-defined stats for too small inputs */ + if (srcSize <= ZSTD_PREDEF_THRESHOLD) { + DEBUGLOG(5, "srcSize <= %i : use predefined stats", ZSTD_PREDEF_THRESHOLD); optPtr->priceType = zop_predef; } assert(optPtr->symbolCosts != NULL); if (optPtr->symbolCosts->huf.repeatMode == HUF_repeat_valid) { - /* huffman table presumed generated by dictionary */ + + /* huffman stats covering the full value set : table presumed generated by dictionary */ optPtr->priceType = zop_dynamic; if (compressedLiterals) { + /* generate literals statistics from huffman table */ unsigned lit; assert(optPtr->litFreq != NULL); optPtr->litSum = 0; for (lit=0; lit<=MaxLit; lit++) { U32 const scaleLog = 11; /* scale to 2K */ - U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit); + U32 const bitCost = HUF_getNbBitsFromCTable(optPtr->symbolCosts->huf.CTable, lit); assert(bitCost <= scaleLog); optPtr->litFreq[lit] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/; optPtr->litSum += optPtr->litFreq[lit]; @@ -170,20 +209,26 @@ ZSTD_rescaleFreqs(optState_t* const optPtr, optPtr->offCodeSum += optPtr->offCodeFreq[of]; } } - } else { /* not a dictionary */ + } else { /* first block, no dictionary */ assert(optPtr->litFreq != NULL); if (compressedLiterals) { + /* base initial cost of literals on direct frequency within src */ unsigned lit = MaxLit; HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */ - optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1); + optPtr->litSum = ZSTD_downscaleStats(optPtr->litFreq, MaxLit, 8, base_0possible); } - { unsigned ll; - for (ll=0; ll<=MaxLL; ll++) - optPtr->litLengthFreq[ll] = 1; + { unsigned const baseLLfreqs[MaxLL+1] = { + 4, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1 + }; + ZSTD_memcpy(optPtr->litLengthFreq, baseLLfreqs, sizeof(baseLLfreqs)); + optPtr->litLengthSum = sum_u32(baseLLfreqs, MaxLL+1); } - optPtr->litLengthSum = MaxLL+1; { unsigned ml; for (ml=0; ml<=MaxML; ml++) @@ -191,21 +236,25 @@ ZSTD_rescaleFreqs(optState_t* const optPtr, } optPtr->matchLengthSum = MaxML+1; - { unsigned of; - for (of=0; of<=MaxOff; of++) - optPtr->offCodeFreq[of] = 1; + { unsigned const baseOFCfreqs[MaxOff+1] = { + 6, 2, 1, 1, 2, 3, 4, 4, + 4, 3, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 + }; + ZSTD_memcpy(optPtr->offCodeFreq, baseOFCfreqs, sizeof(baseOFCfreqs)); + optPtr->offCodeSum = sum_u32(baseOFCfreqs, MaxOff+1); } - optPtr->offCodeSum = MaxOff+1; } - } else { /* new block : re-use previous statistics, scaled down */ + } else { /* new block : scale down accumulated statistics */ if (compressedLiterals) - optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1); - optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0); - optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0); - optPtr->offCodeSum = ZSTD_downscaleStat(optPtr->offCodeFreq, MaxOff, 0); + optPtr->litSum = ZSTD_scaleStats(optPtr->litFreq, MaxLit, 12); + optPtr->litLengthSum = ZSTD_scaleStats(optPtr->litLengthFreq, MaxLL, 11); + optPtr->matchLengthSum = ZSTD_scaleStats(optPtr->matchLengthFreq, MaxML, 11); + optPtr->offCodeSum = ZSTD_scaleStats(optPtr->offCodeFreq, MaxOff, 11); } ZSTD_setBasePrices(optPtr, optLevel); @@ -218,6 +267,7 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength, const optState_t* const optPtr, int optLevel) { + DEBUGLOG(8, "ZSTD_rawLiteralsCost (%u literals)", litLength); if (litLength == 0) return 0; if (!ZSTD_compressedLiterals(optPtr)) @@ -227,11 +277,14 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength, return (litLength*6) * BITCOST_MULTIPLIER; /* 6 bit per literal - no statistic used */ /* dynamic statistics */ - { U32 price = litLength * optPtr->litSumBasePrice; + { U32 price = optPtr->litSumBasePrice * litLength; + U32 const litPriceMax = optPtr->litSumBasePrice - BITCOST_MULTIPLIER; U32 u; + assert(optPtr->litSumBasePrice >= BITCOST_MULTIPLIER); for (u=0; u < litLength; u++) { - assert(WEIGHT(optPtr->litFreq[literals[u]], optLevel) <= optPtr->litSumBasePrice); /* literal cost should never be negative */ - price -= WEIGHT(optPtr->litFreq[literals[u]], optLevel); + U32 litPrice = WEIGHT(optPtr->litFreq[literals[u]], optLevel); + if (UNLIKELY(litPrice > litPriceMax)) litPrice = litPriceMax; + price -= litPrice; } return price; } @@ -241,33 +294,46 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength, * cost of literalLength symbol */ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optPtr, int optLevel) { - if (optPtr->priceType == zop_predef) return WEIGHT(litLength, optLevel); + assert(litLength <= ZSTD_BLOCKSIZE_MAX); + if (optPtr->priceType == zop_predef) + return WEIGHT(litLength, optLevel); + + /* ZSTD_LLcode() can't compute litLength price for sizes >= ZSTD_BLOCKSIZE_MAX + * because it isn't representable in the zstd format. + * So instead just pretend it would cost 1 bit more than ZSTD_BLOCKSIZE_MAX - 1. + * In such a case, the block would be all literals. + */ + if (litLength == ZSTD_BLOCKSIZE_MAX) + return BITCOST_MULTIPLIER + ZSTD_litLengthPrice(ZSTD_BLOCKSIZE_MAX - 1, optPtr, optLevel); /* dynamic statistics */ { U32 const llCode = ZSTD_LLcode(litLength); - return (ZSTDInternalConstants::LL_bits[llCode] * BITCOST_MULTIPLIER) + return (LL_bits[llCode] * BITCOST_MULTIPLIER) + optPtr->litLengthSumBasePrice - WEIGHT(optPtr->litLengthFreq[llCode], optLevel); } } /* ZSTD_getMatchPrice() : - * Provides the cost of the match part (offset + matchLength) of a sequence + * Provides the cost of the match part (offset + matchLength) of a sequence. * Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence. - * optLevel: when <2, favors small offset for decompression speed (improved cache efficiency) */ + * @offBase : sumtype, representing an offset or a repcode, and using numeric representation of ZSTD_storeSeq() + * @optLevel: when <2, favors small offset for decompression speed (improved cache efficiency) + */ FORCE_INLINE_TEMPLATE U32 -ZSTD_getMatchPrice(U32 const offset, +ZSTD_getMatchPrice(U32 const offBase, U32 const matchLength, const optState_t* const optPtr, int const optLevel) { U32 price; - U32 const offCode = ZSTD_highbit32(offset+1); + U32 const offCode = ZSTD_highbit32(offBase); U32 const mlBase = matchLength - MINMATCH; assert(matchLength >= MINMATCH); - if (optPtr->priceType == zop_predef) /* fixed scheme, do not use statistics */ - return WEIGHT(mlBase, optLevel) + ((16 + offCode) * BITCOST_MULTIPLIER); + if (optPtr->priceType == zop_predef) /* fixed scheme, does not use statistics */ + return WEIGHT(mlBase, optLevel) + + ((16 + offCode) * BITCOST_MULTIPLIER); /* emulated offset cost */ /* dynamic statistics */ price = (offCode * BITCOST_MULTIPLIER) + (optPtr->offCodeSumBasePrice - WEIGHT(optPtr->offCodeFreq[offCode], optLevel)); @@ -276,7 +342,7 @@ ZSTD_getMatchPrice(U32 const offset, /* match Length */ { U32 const mlCode = ZSTD_MLcode(mlBase); - price += (ZSTDInternalConstants::ML_bits[mlCode] * BITCOST_MULTIPLIER) + (optPtr->matchLengthSumBasePrice - WEIGHT(optPtr->matchLengthFreq[mlCode], optLevel)); + price += (ML_bits[mlCode] * BITCOST_MULTIPLIER) + (optPtr->matchLengthSumBasePrice - WEIGHT(optPtr->matchLengthFreq[mlCode], optLevel)); } price += BITCOST_MULTIPLIER / 5; /* heuristic : make matches a bit more costly to favor less sequences -> faster decompression speed */ @@ -286,10 +352,10 @@ ZSTD_getMatchPrice(U32 const offset, } /* ZSTD_updateStats() : - * assumption : literals + litLengtn <= iend */ + * assumption : literals + litLength <= iend */ static void ZSTD_updateStats(optState_t* const optPtr, U32 litLength, const BYTE* literals, - U32 offsetCode, U32 matchLength) + U32 offBase, U32 matchLength) { /* literals */ if (ZSTD_compressedLiterals(optPtr)) { @@ -305,8 +371,8 @@ static void ZSTD_updateStats(optState_t* const optPtr, optPtr->litLengthSum++; } - /* match offset code (0-2=>repCode; 3+=>offset+2) */ - { U32 const offCode = ZSTD_highbit32(offsetCode+1); + /* offset code : follows storeSeq() numeric representation */ + { U32 const offCode = ZSTD_highbit32(offBase); assert(offCode <= MaxOff); optPtr->offCodeFreq[offCode]++; optPtr->offCodeSum++; @@ -340,9 +406,11 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length) /* Update hashTable3 up to ip (excluded) Assumption : always within prefix (i.e. not within extDict) */ -static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, - U32* nextToUpdate3, - const BYTE* const ip) +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +U32 ZSTD_insertAndFindFirstIndexHash3 (const ZSTD_matchState_t* ms, + U32* nextToUpdate3, + const BYTE* const ip) { U32* const hashTable3 = ms->hashTable3; U32 const hashLog3 = ms->hashLog3; @@ -366,11 +434,15 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms, * Binary Tree search ***************************************/ /** ZSTD_insertBt1() : add one or multiple positions to tree. - * ip : assumed <= iend-8 . + * @param ip assumed <= iend-8 . + * @param target The target of ZSTD_updateTree_internal() - we are filling to this position * @return : nb of positions added */ -static U32 ZSTD_insertBt1( - ZSTD_matchState_t* ms, +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +U32 ZSTD_insertBt1( + const ZSTD_matchState_t* ms, const BYTE* const ip, const BYTE* const iend, + U32 const target, U32 const mls, const int extDict) { const ZSTD_compressionParameters* const cParams = &ms->cParams; @@ -388,32 +460,36 @@ static U32 ZSTD_insertBt1( const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; const BYTE* match; - const U32 current = (U32)(ip-base); - const U32 btLow = btMask >= current ? 0 : current - btMask; - U32* smallerPtr = bt + 2*(current&btMask); + const U32 curr = (U32)(ip-base); + const U32 btLow = btMask >= curr ? 0 : curr - btMask; + U32* smallerPtr = bt + 2*(curr&btMask); U32* largerPtr = smallerPtr + 1; U32 dummy32; /* to be nullified at the end */ - U32 const windowLow = ms->window.lowLimit; - U32 matchEndIdx = current+8+1; + /* windowLow is based on target because + * we only need positions that will be in the window at the end of the tree update. + */ + U32 const windowLow = ZSTD_getLowestMatchIndex(ms, target, cParams->windowLog); + U32 matchEndIdx = curr+8+1; size_t bestLength = 8; U32 nbCompares = 1U << cParams->searchLog; #ifdef ZSTD_C_PREDICT - U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0); - U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1); + U32 predictedSmall = *(bt + 2*((curr-1)&btMask) + 0); + U32 predictedLarge = *(bt + 2*((curr-1)&btMask) + 1); predictedSmall += (predictedSmall>0); predictedLarge += (predictedLarge>0); #endif /* ZSTD_C_PREDICT */ - DEBUGLOG(8, "ZSTD_insertBt1 (%u)", current); + DEBUGLOG(8, "ZSTD_insertBt1 (%u)", curr); + assert(curr <= target); assert(ip <= iend-8); /* required for h calculation */ - hashTable[h] = current; /* Update Hash Table */ + hashTable[h] = curr; /* Update Hash Table */ assert(windowLow > 0); - while (nbCompares-- && (matchIndex >= windowLow)) { + for (; nbCompares && (matchIndex >= windowLow); --nbCompares) { U32* const nextPtr = bt + 2*(matchIndex & btMask); size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - assert(matchIndex < current); + assert(matchIndex < curr); #ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */ const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */ @@ -476,12 +552,13 @@ static U32 ZSTD_insertBt1( *smallerPtr = *largerPtr = 0; { U32 positions = 0; if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384)); /* speed optimization */ - assert(matchEndIdx > current + 8); - return MAX(positions, matchEndIdx - (current + 8)); + assert(matchEndIdx > curr + 8); + return MAX(positions, matchEndIdx - (curr + 8)); } } FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR void ZSTD_updateTree_internal( ZSTD_matchState_t* ms, const BYTE* const ip, const BYTE* const iend, @@ -490,11 +567,11 @@ void ZSTD_updateTree_internal( const BYTE* const base = ms->window.base; U32 const target = (U32)(ip - base); U32 idx = ms->nextToUpdate; - DEBUGLOG(6, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)", + DEBUGLOG(7, "ZSTD_updateTree_internal, from %u to %u (dictMode:%u)", idx, target, dictMode); while(idx < target) { - U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict); + U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, target, mls, dictMode == ZSTD_extDict); assert(idx < (U32)(idx + forward)); idx += forward; } @@ -508,20 +585,23 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) { } FORCE_INLINE_TEMPLATE -U32 ZSTD_insertBtAndGetAllMatches ( - ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */ - ZSTD_matchState_t* ms, - U32* nextToUpdate3, - const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode, - const U32 rep[ZSTD_REP_NUM], - U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */ - const U32 lengthToBeat, - U32 const mls /* template */) +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +U32 +ZSTD_insertBtAndGetAllMatches ( + ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */ + ZSTD_matchState_t* ms, + U32* nextToUpdate3, + const BYTE* const ip, const BYTE* const iLimit, + const ZSTD_dictMode_e dictMode, + const U32 rep[ZSTD_REP_NUM], + const U32 ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */ + const U32 lengthToBeat, + const U32 mls /* template */) { const ZSTD_compressionParameters* const cParams = &ms->cParams; U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1); const BYTE* const base = ms->window.base; - U32 const current = (U32)(ip-base); + U32 const curr = (U32)(ip-base); U32 const hashLog = cParams->hashLog; U32 const minMatch = (mls==3) ? 3 : 4; U32* const hashTable = ms->hashTable; @@ -535,12 +615,12 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 const dictLimit = ms->window.dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; - U32 const btLow = (btMask >= current) ? 0 : current - btMask; - U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog); + U32 const btLow = (btMask >= curr) ? 0 : curr - btMask; + U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog); U32 const matchLow = windowLow ? windowLow : 1; - U32* smallerPtr = bt + 2*(current&btMask); - U32* largerPtr = bt + 2*(current&btMask) + 1; - U32 matchEndIdx = current+8+1; /* farthest referenced position of any match => detects repetitive patterns */ + U32* smallerPtr = bt + 2*(curr&btMask); + U32* largerPtr = bt + 2*(curr&btMask) + 1; + U32 matchEndIdx = curr+8+1; /* farthest referenced position of any match => detects repetitive patterns */ U32 dummy32; /* to be nullified at the end */ U32 mnum = 0; U32 nbCompares = 1U << cParams->searchLog; @@ -559,7 +639,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 const dmsBtLow = dictMode == ZSTD_dictMatchState && dmsBtMask < dmsHighLimit - dmsLowLimit ? dmsHighLimit - dmsBtMask : dmsLowLimit; size_t bestLength = lengthToBeat-1; - DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", current); + DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", curr); /* check repCode */ assert(ll0 <= 1); /* necessarily 1 or 0 */ @@ -567,29 +647,29 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 repCode; for (repCode = ll0; repCode < lastR; repCode++) { U32 const repOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode]; - U32 const repIndex = current - repOffset; + U32 const repIndex = curr - repOffset; U32 repLen = 0; - assert(current >= dictLimit); - if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */ + assert(curr >= dictLimit); + if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < curr-dictLimit) { /* equivalent to `curr > repIndex >= dictLimit` */ /* We must validate the repcode offset because when we're using a dictionary the * valid offset range shrinks when the dictionary goes out of bounds. */ if ((repIndex >= windowLow) & (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch))) { repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch; } - } else { /* repIndex < dictLimit || repIndex >= current */ + } else { /* repIndex < dictLimit || repIndex >= curr */ const BYTE* const repMatch = dictMode == ZSTD_dictMatchState ? dmsBase + repIndex - dmsIndexDelta : dictBase + repIndex; - assert(current >= windowLow); + assert(curr >= windowLow); if ( dictMode == ZSTD_extDict - && ( ((repOffset-1) /*intentional overflow*/ < current - windowLow) /* equivalent to `current > repIndex >= windowLow` */ + && ( ((repOffset-1) /*intentional overflow*/ < curr - windowLow) /* equivalent to `curr > repIndex >= windowLow` */ & (((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */) && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) { repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dictEnd, prefixStart) + minMatch; } if (dictMode == ZSTD_dictMatchState - && ( ((repOffset-1) /*intentional overflow*/ < current - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `current > repIndex >= dmsLowLimit` */ + && ( ((repOffset-1) /*intentional overflow*/ < curr - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `curr > repIndex >= dmsLowLimit` */ & ((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */ && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) { repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dmsEnd, prefixStart) + minMatch; @@ -599,7 +679,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( DEBUGLOG(8, "found repCode %u (ll0:%u, offset:%u) of length %u", repCode, ll0, repOffset, repLen); bestLength = repLen; - matches[mnum].off = repCode - ll0; + matches[mnum].off = REPCODE_TO_OFFBASE(repCode - ll0 + 1); /* expect value between 1 and 3 */ matches[mnum].len = (U32)repLen; mnum++; if ( (repLen > sufficient_len) @@ -611,7 +691,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( if ((mls == 3) /*static*/ && (bestLength < mls)) { U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip); if ((matchIndex3 >= matchLow) - & (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) { + & (curr - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) { size_t mlen; if ((dictMode == ZSTD_noDict) /*static*/ || (dictMode == ZSTD_dictMatchState) /*static*/ || (matchIndex3 >= dictLimit)) { const BYTE* const match = base + matchIndex3; @@ -626,26 +706,26 @@ U32 ZSTD_insertBtAndGetAllMatches ( DEBUGLOG(8, "found small match with hlog3, of length %u", (U32)mlen); bestLength = mlen; - assert(current > matchIndex3); + assert(curr > matchIndex3); assert(mnum==0); /* no prior solution */ - matches[0].off = (current - matchIndex3) + ZSTD_REP_MOVE; + matches[0].off = OFFSET_TO_OFFBASE(curr - matchIndex3); matches[0].len = (U32)mlen; mnum = 1; if ( (mlen > sufficient_len) | (ip+mlen == iLimit) ) { /* best possible length */ - ms->nextToUpdate = current+1; /* skip insertion */ + ms->nextToUpdate = curr+1; /* skip insertion */ return 1; } } } /* no dictMatchState lookup: dicts don't have a populated HC3 table */ - } + } /* if (mls == 3) */ - hashTable[h] = current; /* Update Hash Table */ + hashTable[h] = curr; /* Update Hash Table */ - while (nbCompares-- && (matchIndex >= matchLow)) { + for (; nbCompares && (matchIndex >= matchLow); --nbCompares) { U32* const nextPtr = bt + 2*(matchIndex & btMask); const BYTE* match; size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - assert(current > matchIndex); + assert(curr > matchIndex); if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) { assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */ @@ -661,21 +741,20 @@ U32 ZSTD_insertBtAndGetAllMatches ( } if (matchLength > bestLength) { - DEBUGLOG(8, "found match of length %u at distance %u (offCode=%u)", - (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE); + DEBUGLOG(8, "found match of length %u at distance %u (offBase=%u)", + (U32)matchLength, curr - matchIndex, OFFSET_TO_OFFBASE(curr - matchIndex)); assert(matchEndIdx > matchIndex); if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength; bestLength = matchLength; - matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE; + matches[mnum].off = OFFSET_TO_OFFBASE(curr - matchIndex); matches[mnum].len = (U32)matchLength; mnum++; if ( (matchLength > ZSTD_OPT_NUM) | (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */) { if (dictMode == ZSTD_dictMatchState) nbCompares = 0; /* break should also skip searching dms */ break; /* drop, to preserve bt consistency (miss a little bit of compression) */ - } - } + } } if (match[matchLength] < ip[matchLength]) { /* match smaller than current */ @@ -694,12 +773,13 @@ U32 ZSTD_insertBtAndGetAllMatches ( *smallerPtr = *largerPtr = 0; + assert(nbCompares <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */ if (dictMode == ZSTD_dictMatchState && nbCompares) { size_t const dmsH = ZSTD_hashPtr(ip, dmsHashLog, mls); U32 dictMatchIndex = dms->hashTable[dmsH]; const U32* const dmsBt = dms->chainTable; commonLengthSmaller = commonLengthLarger = 0; - while (nbCompares-- && (dictMatchIndex > dmsLowLimit)) { + for (; nbCompares && (dictMatchIndex > dmsLowLimit); --nbCompares) { const U32* const nextPtr = dmsBt + 2*(dictMatchIndex & dmsBtMask); size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ const BYTE* match = dmsBase + dictMatchIndex; @@ -709,19 +789,18 @@ U32 ZSTD_insertBtAndGetAllMatches ( if (matchLength > bestLength) { matchIndex = dictMatchIndex + dmsIndexDelta; - DEBUGLOG(8, "found dms match of length %u at distance %u (offCode=%u)", - (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE); + DEBUGLOG(8, "found dms match of length %u at distance %u (offBase=%u)", + (U32)matchLength, curr - matchIndex, OFFSET_TO_OFFBASE(curr - matchIndex)); if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength; bestLength = matchLength; - matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE; + matches[mnum].off = OFFSET_TO_OFFBASE(curr - matchIndex); matches[mnum].len = (U32)matchLength; mnum++; if ( (matchLength > ZSTD_OPT_NUM) | (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */) { break; /* drop, to guarantee consistency (miss a little bit of compression) */ - } - } + } } if (dictMatchIndex <= dmsBtLow) { break; } /* beyond tree size, stop the search */ if (match[matchLength] < ip[matchLength]) { @@ -731,52 +810,244 @@ U32 ZSTD_insertBtAndGetAllMatches ( /* match is larger than current */ commonLengthLarger = matchLength; dictMatchIndex = nextPtr[0]; - } - } - } + } } } /* if (dictMode == ZSTD_dictMatchState) */ - assert(matchEndIdx > current+8); + assert(matchEndIdx > curr+8); ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */ return mnum; } +typedef U32 (*ZSTD_getAllMatchesFn)( + ZSTD_match_t*, + ZSTD_matchState_t*, + U32*, + const BYTE*, + const BYTE*, + const U32 rep[ZSTD_REP_NUM], + U32 const ll0, + U32 const lengthToBeat); -FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches ( - ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */ - ZSTD_matchState_t* ms, - U32* nextToUpdate3, - const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode, - const U32 rep[ZSTD_REP_NUM], - U32 const ll0, - U32 const lengthToBeat) +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +U32 ZSTD_btGetAllMatches_internal( + ZSTD_match_t* matches, + ZSTD_matchState_t* ms, + U32* nextToUpdate3, + const BYTE* ip, + const BYTE* const iHighLimit, + const U32 rep[ZSTD_REP_NUM], + U32 const ll0, + U32 const lengthToBeat, + const ZSTD_dictMode_e dictMode, + const U32 mls) { - const ZSTD_compressionParameters* const cParams = &ms->cParams; - U32 const matchLengthSearch = cParams->minMatch; - DEBUGLOG(8, "ZSTD_BtGetAllMatches"); - if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */ - ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode); - switch(matchLengthSearch) - { - case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3); - default : - case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4); - case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5); - case 7 : - case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6); + assert(BOUNDED(3, ms->cParams.minMatch, 6) == mls); + DEBUGLOG(8, "ZSTD_BtGetAllMatches(dictMode=%d, mls=%u)", (int)dictMode, mls); + if (ip < ms->window.base + ms->nextToUpdate) + return 0; /* skipped area */ + ZSTD_updateTree_internal(ms, ip, iHighLimit, mls, dictMode); + return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, mls); +} + +#define ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls) ZSTD_btGetAllMatches_##dictMode##_##mls + +#define GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, mls) \ + static U32 ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls)( \ + ZSTD_match_t* matches, \ + ZSTD_matchState_t* ms, \ + U32* nextToUpdate3, \ + const BYTE* ip, \ + const BYTE* const iHighLimit, \ + const U32 rep[ZSTD_REP_NUM], \ + U32 const ll0, \ + U32 const lengthToBeat) \ + { \ + return ZSTD_btGetAllMatches_internal( \ + matches, ms, nextToUpdate3, ip, iHighLimit, \ + rep, ll0, lengthToBeat, ZSTD_##dictMode, mls); \ + } + +#define GEN_ZSTD_BT_GET_ALL_MATCHES(dictMode) \ + GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 3) \ + GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 4) \ + GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 5) \ + GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 6) + +GEN_ZSTD_BT_GET_ALL_MATCHES(noDict) +GEN_ZSTD_BT_GET_ALL_MATCHES(extDict) +GEN_ZSTD_BT_GET_ALL_MATCHES(dictMatchState) + +#define ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMode) \ + { \ + ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 3), \ + ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 4), \ + ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 5), \ + ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 6) \ } + +static ZSTD_getAllMatchesFn +ZSTD_selectBtGetAllMatches(ZSTD_matchState_t const* ms, ZSTD_dictMode_e const dictMode) +{ + ZSTD_getAllMatchesFn const getAllMatchesFns[3][4] = { + ZSTD_BT_GET_ALL_MATCHES_ARRAY(noDict), + ZSTD_BT_GET_ALL_MATCHES_ARRAY(extDict), + ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMatchState) + }; + U32 const mls = BOUNDED(3, ms->cParams.minMatch, 6); + assert((U32)dictMode < 3); + assert(mls - 3 < 4); + return getAllMatchesFns[(int)dictMode][mls - 3]; } +/************************* +* LDM helper functions * +*************************/ + +/* Struct containing info needed to make decision about ldm inclusion */ +typedef struct { + rawSeqStore_t seqStore; /* External match candidates store for this block */ + U32 startPosInBlock; /* Start position of the current match candidate */ + U32 endPosInBlock; /* End position of the current match candidate */ + U32 offset; /* Offset of the match candidate */ +} ZSTD_optLdm_t; + +/* ZSTD_optLdm_skipRawSeqStoreBytes(): + * Moves forward in @rawSeqStore by @nbBytes, + * which will update the fields 'pos' and 'posInSequence'. + */ +static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) +{ + U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes); + while (currPos && rawSeqStore->pos < rawSeqStore->size) { + rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos]; + if (currPos >= currSeq.litLength + currSeq.matchLength) { + currPos -= currSeq.litLength + currSeq.matchLength; + rawSeqStore->pos++; + } else { + rawSeqStore->posInSequence = currPos; + break; + } + } + if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) { + rawSeqStore->posInSequence = 0; + } +} -/*-******************************* -* Optimal parser -*********************************/ +/* ZSTD_opt_getNextMatchAndUpdateSeqStore(): + * Calculates the beginning and end of the next match in the current block. + * Updates 'pos' and 'posInSequence' of the ldmSeqStore. + */ +static void +ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock, + U32 blockBytesRemaining) +{ + rawSeq currSeq; + U32 currBlockEndPos; + U32 literalsBytesRemaining; + U32 matchBytesRemaining; + + /* Setting match end position to MAX to ensure we never use an LDM during this block */ + if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) { + optLdm->startPosInBlock = UINT_MAX; + optLdm->endPosInBlock = UINT_MAX; + return; + } + /* Calculate appropriate bytes left in matchLength and litLength + * after adjusting based on ldmSeqStore->posInSequence */ + currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos]; + assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength); + currBlockEndPos = currPosInBlock + blockBytesRemaining; + literalsBytesRemaining = (optLdm->seqStore.posInSequence < currSeq.litLength) ? + currSeq.litLength - (U32)optLdm->seqStore.posInSequence : + 0; + matchBytesRemaining = (literalsBytesRemaining == 0) ? + currSeq.matchLength - ((U32)optLdm->seqStore.posInSequence - currSeq.litLength) : + currSeq.matchLength; + + /* If there are more literal bytes than bytes remaining in block, no ldm is possible */ + if (literalsBytesRemaining >= blockBytesRemaining) { + optLdm->startPosInBlock = UINT_MAX; + optLdm->endPosInBlock = UINT_MAX; + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, blockBytesRemaining); + return; + } + + /* Matches may be < MINMATCH by this process. In that case, we will reject them + when we are deciding whether or not to add the ldm */ + optLdm->startPosInBlock = currPosInBlock + literalsBytesRemaining; + optLdm->endPosInBlock = optLdm->startPosInBlock + matchBytesRemaining; + optLdm->offset = currSeq.offset; + + if (optLdm->endPosInBlock > currBlockEndPos) { + /* Match ends after the block ends, we can't use the whole match */ + optLdm->endPosInBlock = currBlockEndPos; + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, currBlockEndPos - currPosInBlock); + } else { + /* Consume nb of bytes equal to size of sequence left */ + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, literalsBytesRemaining + matchBytesRemaining); + } +} + +/* ZSTD_optLdm_maybeAddMatch(): + * Adds a match if it's long enough, + * based on it's 'matchStartPosInBlock' and 'matchEndPosInBlock', + * into 'matches'. Maintains the correct ordering of 'matches'. + */ +static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches, + const ZSTD_optLdm_t* optLdm, U32 currPosInBlock) +{ + U32 const posDiff = currPosInBlock - optLdm->startPosInBlock; + /* Note: ZSTD_match_t actually contains offBase and matchLength (before subtracting MINMATCH) */ + U32 const candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff; + + /* Ensure that current block position is not outside of the match */ + if (currPosInBlock < optLdm->startPosInBlock + || currPosInBlock >= optLdm->endPosInBlock + || candidateMatchLength < MINMATCH) { + return; + } + if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) { + U32 const candidateOffBase = OFFSET_TO_OFFBASE(optLdm->offset); + DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offBase: %u matchLength %u) at block position=%u", + candidateOffBase, candidateMatchLength, currPosInBlock); + matches[*nbMatches].len = candidateMatchLength; + matches[*nbMatches].off = candidateOffBase; + (*nbMatches)++; + } +} -static U32 ZSTD_totalLen(ZSTD_optimal_t sol) +/* ZSTD_optLdm_processMatchCandidate(): + * Wrapper function to update ldm seq store and call ldm functions as necessary. + */ +static void +ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, + ZSTD_match_t* matches, U32* nbMatches, + U32 currPosInBlock, U32 remainingBytes) { - return sol.litlen + sol.mlen; + if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) { + return; + } + + if (currPosInBlock >= optLdm->endPosInBlock) { + if (currPosInBlock > optLdm->endPosInBlock) { + /* The position at which ZSTD_optLdm_processMatchCandidate() is called is not necessarily + * at the end of a match from the ldm seq store, and will often be some bytes + * over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots" + */ + U32 const posOvershoot = currPosInBlock - optLdm->endPosInBlock; + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot); + } + ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes); + } + ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock); } + +/*-******************************* +* Optimal parser +*********************************/ + #if 0 /* debug */ static void @@ -794,7 +1065,13 @@ listStats(const U32* table, int lastEltID) #endif -FORCE_INLINE_TEMPLATE size_t +#define LIT_PRICE(_p) (int)ZSTD_rawLiteralsCost(_p, 1, optStatePtr, optLevel) +#define LL_PRICE(_l) (int)ZSTD_litLengthPrice(_l, optStatePtr, optLevel) +#define LL_INCPRICE(_l) (LL_PRICE(_l) - LL_PRICE(_l-1)) + +FORCE_INLINE_TEMPLATE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], @@ -812,13 +1089,22 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, const BYTE* const prefixStart = base + ms->window.dictLimit; const ZSTD_compressionParameters* const cParams = &ms->cParams; + ZSTD_getAllMatchesFn getAllMatches = ZSTD_selectBtGetAllMatches(ms, dictMode); + U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1); U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4; U32 nextToUpdate3 = ms->nextToUpdate; ZSTD_optimal_t* const opt = optStatePtr->priceTable; ZSTD_match_t* const matches = optStatePtr->matchTable; - ZSTD_optimal_t lastSequence; + ZSTD_optimal_t lastStretch; + ZSTD_optLdm_t optLdm; + + ZSTD_memset(&lastStretch, 0, sizeof(ZSTD_optimal_t)); + + optLdm.seqStore = ms->ldmSeqStore ? *ms->ldmSeqStore : kNullRawSeqStore; + optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0; + ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip)); /* init */ DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u", @@ -834,102 +1120,141 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, /* find first match */ { U32 const litlen = (U32)(ip - anchor); U32 const ll0 = !litlen; - U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch); - if (!nbMatches) { ip++; continue; } + U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, ip, iend, rep, ll0, minMatch); + ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches, + (U32)(ip-istart), (U32)(iend-ip)); + if (!nbMatches) { + DEBUGLOG(8, "no match found at cPos %u", (unsigned)(ip-istart)); + ip++; + continue; + } + + /* Match found: let's store this solution, and eventually find more candidates. + * During this forward pass, @opt is used to store stretches, + * defined as "a match followed by N literals". + * Note how this is different from a Sequence, which is "N literals followed by a match". + * Storing stretches allows us to store different match predecessors + * for each literal position part of a literals run. */ /* initialize opt[0] */ - { U32 i ; for (i=0; i immediate encoding */ { U32 const maxML = matches[nbMatches-1].len; - U32 const maxOffset = matches[nbMatches-1].off; - DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series", - nbMatches, maxML, maxOffset, (U32)(ip-prefixStart)); + U32 const maxOffBase = matches[nbMatches-1].off; + DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffBase=%u at cPos=%u => start new series", + nbMatches, maxML, maxOffBase, (U32)(ip-prefixStart)); if (maxML > sufficient_len) { - lastSequence.litlen = litlen; - lastSequence.mlen = maxML; - lastSequence.off = maxOffset; - DEBUGLOG(6, "large match (%u>%u), immediate encoding", + lastStretch.litlen = 0; + lastStretch.mlen = maxML; + lastStretch.off = maxOffBase; + DEBUGLOG(6, "large match (%u>%u) => immediate encoding", maxML, sufficient_len); cur = 0; - last_pos = ZSTD_totalLen(lastSequence); + last_pos = maxML; goto _shortestPath; } } /* set prices for first matches starting position == 0 */ - { U32 const literalsPrice = opt[0].price + ZSTD_litLengthPrice(0, optStatePtr, optLevel); - U32 pos; + assert(opt[0].price >= 0); + { U32 pos; U32 matchNb; for (pos = 1; pos < minMatch; pos++) { - opt[pos].price = ZSTD_MAX_PRICE; /* mlen, litlen and price will be fixed during forward scanning */ + opt[pos].price = ZSTD_MAX_PRICE; + opt[pos].mlen = 0; + opt[pos].litlen = litlen + pos; } for (matchNb = 0; matchNb < nbMatches; matchNb++) { - U32 const offset = matches[matchNb].off; + U32 const offBase = matches[matchNb].off; U32 const end = matches[matchNb].len; for ( ; pos <= end ; pos++ ) { - U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel); - U32 const sequencePrice = literalsPrice + matchPrice; + int const matchPrice = (int)ZSTD_getMatchPrice(offBase, pos, optStatePtr, optLevel); + int const sequencePrice = opt[0].price + matchPrice; DEBUGLOG(7, "rPos:%u => set initial price : %.2f", pos, ZSTD_fCost(sequencePrice)); opt[pos].mlen = pos; - opt[pos].off = offset; - opt[pos].litlen = litlen; - opt[pos].price = sequencePrice; - } } + opt[pos].off = offBase; + opt[pos].litlen = 0; /* end of match */ + opt[pos].price = sequencePrice + LL_PRICE(0); + } + } last_pos = pos-1; + opt[pos].price = ZSTD_MAX_PRICE; } } /* check further positions */ for (cur = 1; cur <= last_pos; cur++) { const BYTE* const inr = ip + cur; - assert(cur < ZSTD_OPT_NUM); - DEBUGLOG(7, "cPos:%zi==rPos:%u", inr-istart, cur) + assert(cur <= ZSTD_OPT_NUM); + DEBUGLOG(7, "cPos:%zi==rPos:%u", inr-istart, cur); /* Fix current position with one literal if cheaper */ - { U32 const litlen = (opt[cur-1].mlen == 0) ? opt[cur-1].litlen + 1 : 1; + { U32 const litlen = opt[cur-1].litlen + 1; int const price = opt[cur-1].price - + ZSTD_rawLiteralsCost(ip+cur-1, 1, optStatePtr, optLevel) - + ZSTD_litLengthPrice(litlen, optStatePtr, optLevel) - - ZSTD_litLengthPrice(litlen-1, optStatePtr, optLevel); + + LIT_PRICE(ip+cur-1) + + LL_INCPRICE(litlen); assert(price < 1000000000); /* overflow check */ if (price <= opt[cur].price) { + ZSTD_optimal_t const prevMatch = opt[cur]; DEBUGLOG(7, "cPos:%zi==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)", inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), litlen, opt[cur-1].rep[0], opt[cur-1].rep[1], opt[cur-1].rep[2]); - opt[cur].mlen = 0; - opt[cur].off = 0; + opt[cur] = opt[cur-1]; opt[cur].litlen = litlen; opt[cur].price = price; + if ( (optLevel >= 1) /* additional check only for higher modes */ + && (prevMatch.litlen == 0) /* replace a match */ + && (LL_INCPRICE(1) < 0) /* ll1 is cheaper than ll0 */ + && LIKELY(ip + cur < iend) + ) { + /* check next position, in case it would be cheaper */ + int with1literal = prevMatch.price + LIT_PRICE(ip+cur) + LL_INCPRICE(1); + int withMoreLiterals = price + LIT_PRICE(ip+cur) + LL_INCPRICE(litlen+1); + DEBUGLOG(7, "then at next rPos %u : match+1lit %.2f vs %ulits %.2f", + cur+1, ZSTD_fCost(with1literal), litlen+1, ZSTD_fCost(withMoreLiterals)); + if ( (with1literal < withMoreLiterals) + && (with1literal < opt[cur+1].price) ) { + /* update offset history - before it disappears */ + U32 const prev = cur - prevMatch.mlen; + repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, prevMatch.off, opt[prev].litlen==0); + assert(cur >= prevMatch.mlen); + DEBUGLOG(7, "==> match+1lit is cheaper (%.2f < %.2f) (hist:%u,%u,%u) !", + ZSTD_fCost(with1literal), ZSTD_fCost(withMoreLiterals), + newReps.rep[0], newReps.rep[1], newReps.rep[2] ); + opt[cur+1] = prevMatch; /* mlen & offbase */ + ZSTD_memcpy(opt[cur+1].rep, &newReps, sizeof(repcodes_t)); + opt[cur+1].litlen = 1; + opt[cur+1].price = with1literal; + if (last_pos < cur+1) last_pos = cur+1; + } + } } else { - DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f) (hist:%u,%u,%u)", - inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), - opt[cur].rep[0], opt[cur].rep[1], opt[cur].rep[2]); + DEBUGLOG(7, "cPos:%zi==rPos:%u : literal would cost more (%.2f>%.2f)", + inr-istart, cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price)); } } - /* Set the repcodes of the current position. We must do it here - * because we rely on the repcodes of the 2nd to last sequence being - * correct to set the next chunks repcodes during the backward - * traversal. + /* Offset history is not updated during match comparison. + * Do it here, now that the match is selected and confirmed. */ ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(repcodes_t)); assert(cur >= opt[cur].mlen); - if (opt[cur].mlen != 0) { + if (opt[cur].litlen == 0) { + /* just finished a match => alter offset history */ U32 const prev = cur - opt[cur].mlen; - repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0); - memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t)); - } else { - memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t)); + repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, opt[cur].off, opt[prev].litlen==0); + ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t)); } /* last match must start at a minimum distance of 8 from oend */ @@ -939,33 +1264,36 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, if ( (optLevel==0) /*static_test*/ && (opt[cur+1].price <= opt[cur].price + (BITCOST_MULTIPLIER/2)) ) { - DEBUGLOG(7, "move to next rPos:%u : price is <=", cur+1); + DEBUGLOG(7, "skip current position : next rPos(%u) price is cheaper", cur+1); continue; /* skip unpromising positions; about ~+6% speed, -0.01 ratio */ } - { U32 const ll0 = (opt[cur].mlen != 0); - U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0; - U32 const previousPrice = opt[cur].price; - U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel); - U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch); + assert(opt[cur].price >= 0); + { U32 const ll0 = (opt[cur].litlen == 0); + int const previousPrice = opt[cur].price; + int const basePrice = previousPrice + LL_PRICE(0); + U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, inr, iend, opt[cur].rep, ll0, minMatch); U32 matchNb; + + ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches, + (U32)(inr-istart), (U32)(iend-inr)); + if (!nbMatches) { DEBUGLOG(7, "rPos:%u : no match found", cur); continue; } - { U32 const maxML = matches[nbMatches-1].len; - DEBUGLOG(7, "cPos:%zi==rPos:%u, found %u matches, of maxLength=%u", - inr-istart, cur, nbMatches, maxML); - - if ( (maxML > sufficient_len) - || (cur + maxML >= ZSTD_OPT_NUM) ) { - lastSequence.mlen = maxML; - lastSequence.off = matches[nbMatches-1].off; - lastSequence.litlen = litlen; - cur -= (opt[cur].mlen==0) ? opt[cur].litlen : 0; /* last sequence is actually only literals, fix cur to last match - note : may underflow, in which case, it's first sequence, and it's okay */ - last_pos = cur + ZSTD_totalLen(lastSequence); - if (cur > ZSTD_OPT_NUM) cur = 0; /* underflow => first match */ + { U32 const longestML = matches[nbMatches-1].len; + DEBUGLOG(7, "cPos:%zi==rPos:%u, found %u matches, of longest ML=%u", + inr-istart, cur, nbMatches, longestML); + + if ( (longestML > sufficient_len) + || (cur + longestML >= ZSTD_OPT_NUM) + || (ip + cur + longestML >= iend) ) { + lastStretch.mlen = longestML; + lastStretch.off = matches[nbMatches-1].off; + lastStretch.litlen = 0; + last_pos = cur + longestML; goto _shortestPath; } } @@ -976,20 +1304,25 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch; U32 mlen; - DEBUGLOG(7, "testing match %u => offCode=%4u, mlen=%2u, llen=%2u", - matchNb, matches[matchNb].off, lastML, litlen); + DEBUGLOG(7, "testing match %u => offBase=%4u, mlen=%2u, llen=%2u", + matchNb, matches[matchNb].off, lastML, opt[cur].litlen); for (mlen = lastML; mlen >= startML; mlen--) { /* scan downward */ U32 const pos = cur + mlen; - int const price = basePrice + ZSTD_getMatchPrice(offset, mlen, optStatePtr, optLevel); + int const price = basePrice + (int)ZSTD_getMatchPrice(offset, mlen, optStatePtr, optLevel); if ((pos > last_pos) || (price < opt[pos].price)) { DEBUGLOG(7, "rPos:%u (ml=%2u) => new better price (%.2f<%.2f)", pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price)); - while (last_pos < pos) { opt[last_pos+1].price = ZSTD_MAX_PRICE; last_pos++; } /* fill empty positions */ + while (last_pos < pos) { + /* fill empty positions, for future comparisons */ + last_pos++; + opt[last_pos].price = ZSTD_MAX_PRICE; + opt[last_pos].litlen = !0; /* just needs to be != 0, to mean "not an end of match" */ + } opt[pos].mlen = mlen; opt[pos].off = offset; - opt[pos].litlen = litlen; + opt[pos].litlen = 0; opt[pos].price = price; } else { DEBUGLOG(7, "rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)", @@ -997,52 +1330,86 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, if (optLevel==0) break; /* early update abort; gets ~+10% speed for about -0.01 ratio loss */ } } } } + opt[last_pos+1].price = ZSTD_MAX_PRICE; } /* for (cur = 1; cur <= last_pos; cur++) */ - lastSequence = opt[last_pos]; - cur = last_pos > ZSTD_totalLen(lastSequence) ? last_pos - ZSTD_totalLen(lastSequence) : 0; /* single sequence, and it starts before `ip` */ - assert(cur < ZSTD_OPT_NUM); /* control overflow*/ + lastStretch = opt[last_pos]; + assert(cur >= lastStretch.mlen); + cur = last_pos - lastStretch.mlen; _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */ assert(opt[0].mlen == 0); + assert(last_pos >= lastStretch.mlen); + assert(cur == last_pos - lastStretch.mlen); - /* Set the next chunk's repcodes based on the repcodes of the beginning - * of the last match, and the last sequence. This avoids us having to - * update them while traversing the sequences. - */ - if (lastSequence.mlen != 0) { - repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0); - memcpy(rep, &reps, sizeof(reps)); + if (lastStretch.mlen==0) { + /* no solution : all matches have been converted into literals */ + assert(lastStretch.litlen == (ip - anchor) + last_pos); + ip += last_pos; + continue; + } + assert(lastStretch.off > 0); + + /* Update offset history */ + if (lastStretch.litlen == 0) { + /* finishing on a match : update offset history */ + repcodes_t const reps = ZSTD_newRep(opt[cur].rep, lastStretch.off, opt[cur].litlen==0); + ZSTD_memcpy(rep, &reps, sizeof(repcodes_t)); } else { - memcpy(rep, opt[cur].rep, sizeof(repcodes_t)); + ZSTD_memcpy(rep, lastStretch.rep, sizeof(repcodes_t)); + assert(cur >= lastStretch.litlen); + cur -= lastStretch.litlen; } - { U32 const storeEnd = cur + 1; + /* Let's write the shortest path solution. + * It is stored in @opt in reverse order, + * starting from @storeEnd (==cur+2), + * effectively partially @opt overwriting. + * Content is changed too: + * - So far, @opt stored stretches, aka a match followed by literals + * - Now, it will store sequences, aka literals followed by a match + */ + { U32 const storeEnd = cur + 2; U32 storeStart = storeEnd; - U32 seqPos = cur; + U32 stretchPos = cur; DEBUGLOG(6, "start reverse traversal (last_pos:%u, cur:%u)", last_pos, cur); (void)last_pos; - assert(storeEnd < ZSTD_OPT_NUM); - DEBUGLOG(6, "last sequence copied into pos=%u (llen=%u,mlen=%u,ofc=%u)", - storeEnd, lastSequence.litlen, lastSequence.mlen, lastSequence.off); - opt[storeEnd] = lastSequence; - while (seqPos > 0) { - U32 const backDist = ZSTD_totalLen(opt[seqPos]); + assert(storeEnd < ZSTD_OPT_SIZE); + DEBUGLOG(6, "last stretch copied into pos=%u (llen=%u,mlen=%u,ofc=%u)", + storeEnd, lastStretch.litlen, lastStretch.mlen, lastStretch.off); + if (lastStretch.litlen > 0) { + /* last "sequence" is unfinished: just a bunch of literals */ + opt[storeEnd].litlen = lastStretch.litlen; + opt[storeEnd].mlen = 0; + storeStart = storeEnd-1; + opt[storeStart] = lastStretch; + } { + opt[storeEnd] = lastStretch; /* note: litlen will be fixed */ + storeStart = storeEnd; + } + while (1) { + ZSTD_optimal_t nextStretch = opt[stretchPos]; + opt[storeStart].litlen = nextStretch.litlen; + DEBUGLOG(6, "selected sequence (llen=%u,mlen=%u,ofc=%u)", + opt[storeStart].litlen, opt[storeStart].mlen, opt[storeStart].off); + if (nextStretch.mlen == 0) { + /* reaching beginning of segment */ + break; + } storeStart--; - DEBUGLOG(6, "sequence from rPos=%u copied into pos=%u (llen=%u,mlen=%u,ofc=%u)", - seqPos, storeStart, opt[seqPos].litlen, opt[seqPos].mlen, opt[seqPos].off); - opt[storeStart] = opt[seqPos]; - seqPos = (seqPos > backDist) ? seqPos - backDist : 0; + opt[storeStart] = nextStretch; /* note: litlen will be fixed */ + assert(nextStretch.litlen + nextStretch.mlen <= stretchPos); + stretchPos -= nextStretch.litlen + nextStretch.mlen; } /* save sequences */ - DEBUGLOG(6, "sending selected sequences into seqStore") + DEBUGLOG(6, "sending selected sequences into seqStore"); { U32 storePos; for (storePos=storeStart; storePos <= storeEnd; storePos++) { U32 const llen = opt[storePos].litlen; U32 const mlen = opt[storePos].mlen; - U32 const offCode = opt[storePos].off; + U32 const offBase = opt[storePos].off; U32 const advance = llen + mlen; DEBUGLOG(6, "considering seq starting at %zi, llen=%u, mlen=%u", anchor - istart, (unsigned)llen, (unsigned)mlen); @@ -1054,11 +1421,14 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, } assert(anchor + llen <= iend); - ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen); - ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH); + ZSTD_updateStats(optStatePtr, llen, anchor, offBase, mlen); + ZSTD_storeSeq(seqStore, llen, anchor, iend, offBase, mlen); anchor += advance; ip = anchor; } } + DEBUGLOG(7, "new offset history : %u, %u, %u", rep[0], rep[1], rep[2]); + + /* update all costs */ ZSTD_setBasePrices(optStatePtr, optLevel); } } /* while (ip < ilimit) */ @@ -1066,53 +1436,54 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, /* Return the last literals size */ return (size_t)(iend - anchor); } +#endif /* build exclusions */ + +#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR +static size_t ZSTD_compressBlock_opt0( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode) +{ + return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /* optLevel */, dictMode); +} +#endif +#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR +static size_t ZSTD_compressBlock_opt2( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode) +{ + return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /* optLevel */, dictMode); +} +#endif +#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btopt( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { DEBUGLOG(5, "ZSTD_compressBlock_btopt"); - return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_noDict); + return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_noDict); } +#endif -/* used in 2-pass strategy */ -static U32 ZSTD_upscaleStat(unsigned* table, U32 lastEltIndex, int bonus) -{ - U32 s, sum=0; - assert(ZSTD_FREQ_DIV+bonus >= 0); - for (s=0; slitSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0); - optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0); - optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0); - optPtr->offCodeSum = ZSTD_upscaleStat(optPtr->offCodeFreq, MaxOff, 0); -} +#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR /* ZSTD_initStats_ultra(): * make a first compression pass, just to seed stats with more accurate starting values. * only works on first block, with no dictionary and no ldm. - * this function cannot error, hence its contract must be respected. + * this function cannot error out, its narrow contract must be respected. */ -static void -ZSTD_initStats_ultra(ZSTD_matchState_t* ms, - seqStore_t* seqStore, - U32 rep[ZSTD_REP_NUM], - const void* src, size_t srcSize) +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_initStats_ultra(ZSTD_matchState_t* ms, + seqStore_t* seqStore, + U32 rep[ZSTD_REP_NUM], + const void* src, size_t srcSize) { U32 tmpRep[ZSTD_REP_NUM]; /* updated rep codes will sink here */ - memcpy(tmpRep, rep, sizeof(tmpRep)); + ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep)); DEBUGLOG(4, "ZSTD_initStats_ultra (srcSize=%zu)", srcSize); assert(ms->opt.litLengthSum == 0); /* first block */ @@ -1120,17 +1491,15 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms, assert(ms->window.dictLimit == ms->window.lowLimit); /* no dictionary */ assert(ms->window.dictLimit - ms->nextToUpdate <= 1); /* no prefix (note: intentional overflow, defined as 2-complement) */ - ZSTD_compressBlock_opt_generic(ms, seqStore, tmpRep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict); /* generate stats into ms->opt*/ + ZSTD_compressBlock_opt2(ms, seqStore, tmpRep, src, srcSize, ZSTD_noDict); /* generate stats into ms->opt*/ - /* invalidate first scan from history */ + /* invalidate first scan from history, only keep entropy stats */ ZSTD_resetSeqStore(seqStore); ms->window.base -= srcSize; ms->window.dictLimit += (U32)srcSize; ms->window.lowLimit = ms->window.dictLimit; ms->nextToUpdate = ms->window.dictLimit; - /* re-inforce weight of collected statistics */ - ZSTD_upscaleStats(&ms->opt); } size_t ZSTD_compressBlock_btultra( @@ -1138,20 +1507,20 @@ size_t ZSTD_compressBlock_btultra( const void* src, size_t srcSize) { DEBUGLOG(5, "ZSTD_compressBlock_btultra (srcSize=%zu)", srcSize); - return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict); + return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_noDict); } size_t ZSTD_compressBlock_btultra2( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { - U32 const current = (U32)((const BYTE*)src - ms->window.base); + U32 const curr = (U32)((const BYTE*)src - ms->window.base); DEBUGLOG(5, "ZSTD_compressBlock_btultra2 (srcSize=%zu)", srcSize); - /* 2-pass strategy: + /* 2-passes strategy: * this strategy makes a first pass over first block to collect statistics - * and seed next round's statistics with it. - * After 1st pass, function forgets everything, and starts a new block. + * in order to seed next round's statistics with it. + * After 1st pass, function forgets history, and starts a new block. * Consequently, this can only work if no data has been previously loaded in tables, * aka, no dictionary, no prefix, no ldm preprocessing. * The compression ratio gain is generally small (~0.5% on first block), @@ -1160,45 +1529,48 @@ size_t ZSTD_compressBlock_btultra2( if ( (ms->opt.litLengthSum==0) /* first block */ && (seqStore->sequences == seqStore->sequencesStart) /* no ldm */ && (ms->window.dictLimit == ms->window.lowLimit) /* no dictionary */ - && (current == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */ - && (srcSize > ZSTD_PREDEF_THRESHOLD) + && (curr == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */ + && (srcSize > ZSTD_PREDEF_THRESHOLD) /* input large enough to not employ default stats */ ) { ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize); } - return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict); + return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_noDict); } +#endif +#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btopt_dictMatchState( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { - return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_dictMatchState); + return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState); } -size_t ZSTD_compressBlock_btultra_dictMatchState( +size_t ZSTD_compressBlock_btopt_extDict( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { - return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_dictMatchState); + return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_extDict); } +#endif -size_t ZSTD_compressBlock_btopt_extDict( +#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_btultra_dictMatchState( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { - return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_extDict); + return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState); } size_t ZSTD_compressBlock_btultra_extDict( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { - return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_extDict); + return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_extDict); } +#endif /* note : no btultra2 variant for extDict nor dictMatchState, * because btultra2 is not meant to work with dictionaries * and is only specific for the first block (no prefix) */ - -} diff --git a/third_party/zstd/compress/zstdmt_compress.c b/third_party/zstd/compress/zstdmt_compress.c new file mode 100644 index 00000000000..86ccce31849 --- /dev/null +++ b/third_party/zstd/compress/zstdmt_compress.c @@ -0,0 +1,1882 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + +/* ====== Compiler specifics ====== */ +#if defined(_MSC_VER) +# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */ +#endif + + +/* ====== Dependencies ====== */ +#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset, INT_MAX, UINT_MAX */ +#include "../common/mem.h" /* MEM_STATIC */ +#include "../common/pool.h" /* threadpool */ +#include "../common/threading.h" /* mutex */ +#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */ +#include "zstd_ldm.h" +#include "zstdmt_compress.h" + +/* Guards code to support resizing the SeqPool. + * We will want to resize the SeqPool to save memory in the future. + * Until then, comment the code out since it is unused. + */ +#define ZSTD_RESIZE_SEQPOOL 0 + +/* ====== Debug ====== */ +#if defined(DEBUGLEVEL) && (DEBUGLEVEL>=2) \ + && !defined(_MSC_VER) \ + && !defined(__MINGW32__) + +# include +# include +# include + +# define DEBUG_PRINTHEX(l,p,n) \ + do { \ + unsigned debug_u; \ + for (debug_u=0; debug_u<(n); debug_u++) \ + RAWLOG(l, "%02X ", ((const unsigned char*)(p))[debug_u]); \ + RAWLOG(l, " \n"); \ + } while (0) + +static unsigned long long GetCurrentClockTimeMicroseconds(void) +{ + static clock_t _ticksPerSecond = 0; + if (_ticksPerSecond <= 0) _ticksPerSecond = sysconf(_SC_CLK_TCK); + + { struct tms junk; clock_t newTicks = (clock_t) times(&junk); + return ((((unsigned long long)newTicks)*(1000000))/_ticksPerSecond); +} } + +#define MUTEX_WAIT_TIME_DLEVEL 6 +#define ZSTD_PTHREAD_MUTEX_LOCK(mutex) \ + do { \ + if (DEBUGLEVEL >= MUTEX_WAIT_TIME_DLEVEL) { \ + unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds(); \ + ZSTD_pthread_mutex_lock(mutex); \ + { unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \ + unsigned long long const elapsedTime = (afterTime-beforeTime); \ + if (elapsedTime > 1000) { \ + /* or whatever threshold you like; I'm using 1 millisecond here */ \ + DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, \ + "Thread took %llu microseconds to acquire mutex %s \n", \ + elapsedTime, #mutex); \ + } } \ + } else { \ + ZSTD_pthread_mutex_lock(mutex); \ + } \ + } while (0) + +#else + +# define ZSTD_PTHREAD_MUTEX_LOCK(m) ZSTD_pthread_mutex_lock(m) +# define DEBUG_PRINTHEX(l,p,n) do { } while (0) + +#endif + + +/* ===== Buffer Pool ===== */ +/* a single Buffer Pool can be invoked from multiple threads in parallel */ + +typedef struct buffer_s { + void* start; + size_t capacity; +} buffer_t; + +static const buffer_t g_nullBuffer = { NULL, 0 }; + +typedef struct ZSTDMT_bufferPool_s { + ZSTD_pthread_mutex_t poolMutex; + size_t bufferSize; + unsigned totalBuffers; + unsigned nbBuffers; + ZSTD_customMem cMem; + buffer_t* buffers; +} ZSTDMT_bufferPool; + +static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool) +{ + DEBUGLOG(3, "ZSTDMT_freeBufferPool (address:%08X)", (U32)(size_t)bufPool); + if (!bufPool) return; /* compatibility with free on NULL */ + if (bufPool->buffers) { + unsigned u; + for (u=0; utotalBuffers; u++) { + DEBUGLOG(4, "free buffer %2u (address:%08X)", u, (U32)(size_t)bufPool->buffers[u].start); + ZSTD_customFree(bufPool->buffers[u].start, bufPool->cMem); + } + ZSTD_customFree(bufPool->buffers, bufPool->cMem); + } + ZSTD_pthread_mutex_destroy(&bufPool->poolMutex); + ZSTD_customFree(bufPool, bufPool->cMem); +} + +static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned maxNbBuffers, ZSTD_customMem cMem) +{ + ZSTDMT_bufferPool* const bufPool = + (ZSTDMT_bufferPool*)ZSTD_customCalloc(sizeof(ZSTDMT_bufferPool), cMem); + if (bufPool==NULL) return NULL; + if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) { + ZSTD_customFree(bufPool, cMem); + return NULL; + } + bufPool->buffers = (buffer_t*)ZSTD_customCalloc(maxNbBuffers * sizeof(buffer_t), cMem); + if (bufPool->buffers==NULL) { + ZSTDMT_freeBufferPool(bufPool); + return NULL; + } + bufPool->bufferSize = 64 KB; + bufPool->totalBuffers = maxNbBuffers; + bufPool->nbBuffers = 0; + bufPool->cMem = cMem; + return bufPool; +} + +/* only works at initialization, not during compression */ +static size_t ZSTDMT_sizeof_bufferPool(ZSTDMT_bufferPool* bufPool) +{ + size_t const poolSize = sizeof(*bufPool); + size_t const arraySize = bufPool->totalBuffers * sizeof(buffer_t); + unsigned u; + size_t totalBufferSize = 0; + ZSTD_pthread_mutex_lock(&bufPool->poolMutex); + for (u=0; utotalBuffers; u++) + totalBufferSize += bufPool->buffers[u].capacity; + ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); + + return poolSize + arraySize + totalBufferSize; +} + +/* ZSTDMT_setBufferSize() : + * all future buffers provided by this buffer pool will have _at least_ this size + * note : it's better for all buffers to have same size, + * as they become freely interchangeable, reducing malloc/free usages and memory fragmentation */ +static void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* const bufPool, size_t const bSize) +{ + ZSTD_pthread_mutex_lock(&bufPool->poolMutex); + DEBUGLOG(4, "ZSTDMT_setBufferSize: bSize = %u", (U32)bSize); + bufPool->bufferSize = bSize; + ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); +} + + +static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool, unsigned maxNbBuffers) +{ + if (srcBufPool==NULL) return NULL; + if (srcBufPool->totalBuffers >= maxNbBuffers) /* good enough */ + return srcBufPool; + /* need a larger buffer pool */ + { ZSTD_customMem const cMem = srcBufPool->cMem; + size_t const bSize = srcBufPool->bufferSize; /* forward parameters */ + ZSTDMT_bufferPool* newBufPool; + ZSTDMT_freeBufferPool(srcBufPool); + newBufPool = ZSTDMT_createBufferPool(maxNbBuffers, cMem); + if (newBufPool==NULL) return newBufPool; + ZSTDMT_setBufferSize(newBufPool, bSize); + return newBufPool; + } +} + +/** ZSTDMT_getBuffer() : + * assumption : bufPool must be valid + * @return : a buffer, with start pointer and size + * note: allocation may fail, in this case, start==NULL and size==0 */ +static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool) +{ + size_t const bSize = bufPool->bufferSize; + DEBUGLOG(5, "ZSTDMT_getBuffer: bSize = %u", (U32)bufPool->bufferSize); + ZSTD_pthread_mutex_lock(&bufPool->poolMutex); + if (bufPool->nbBuffers) { /* try to use an existing buffer */ + buffer_t const buf = bufPool->buffers[--(bufPool->nbBuffers)]; + size_t const availBufferSize = buf.capacity; + bufPool->buffers[bufPool->nbBuffers] = g_nullBuffer; + if ((availBufferSize >= bSize) & ((availBufferSize>>3) <= bSize)) { + /* large enough, but not too much */ + DEBUGLOG(5, "ZSTDMT_getBuffer: provide buffer %u of size %u", + bufPool->nbBuffers, (U32)buf.capacity); + ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); + return buf; + } + /* size conditions not respected : scratch this buffer, create new one */ + DEBUGLOG(5, "ZSTDMT_getBuffer: existing buffer does not meet size conditions => freeing"); + ZSTD_customFree(buf.start, bufPool->cMem); + } + ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); + /* create new buffer */ + DEBUGLOG(5, "ZSTDMT_getBuffer: create a new buffer"); + { buffer_t buffer; + void* const start = ZSTD_customMalloc(bSize, bufPool->cMem); + buffer.start = start; /* note : start can be NULL if malloc fails ! */ + buffer.capacity = (start==NULL) ? 0 : bSize; + if (start==NULL) { + DEBUGLOG(5, "ZSTDMT_getBuffer: buffer allocation failure !!"); + } else { + DEBUGLOG(5, "ZSTDMT_getBuffer: created buffer of size %u", (U32)bSize); + } + return buffer; + } +} + +#if ZSTD_RESIZE_SEQPOOL +/** ZSTDMT_resizeBuffer() : + * assumption : bufPool must be valid + * @return : a buffer that is at least the buffer pool buffer size. + * If a reallocation happens, the data in the input buffer is copied. + */ +static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer) +{ + size_t const bSize = bufPool->bufferSize; + if (buffer.capacity < bSize) { + void* const start = ZSTD_customMalloc(bSize, bufPool->cMem); + buffer_t newBuffer; + newBuffer.start = start; + newBuffer.capacity = start == NULL ? 0 : bSize; + if (start != NULL) { + assert(newBuffer.capacity >= buffer.capacity); + ZSTD_memcpy(newBuffer.start, buffer.start, buffer.capacity); + DEBUGLOG(5, "ZSTDMT_resizeBuffer: created buffer of size %u", (U32)bSize); + return newBuffer; + } + DEBUGLOG(5, "ZSTDMT_resizeBuffer: buffer allocation failure !!"); + } + return buffer; +} +#endif + +/* store buffer for later re-use, up to pool capacity */ +static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf) +{ + DEBUGLOG(5, "ZSTDMT_releaseBuffer"); + if (buf.start == NULL) return; /* compatible with release on NULL */ + ZSTD_pthread_mutex_lock(&bufPool->poolMutex); + if (bufPool->nbBuffers < bufPool->totalBuffers) { + bufPool->buffers[bufPool->nbBuffers++] = buf; /* stored for later use */ + DEBUGLOG(5, "ZSTDMT_releaseBuffer: stored buffer of size %u in slot %u", + (U32)buf.capacity, (U32)(bufPool->nbBuffers-1)); + ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); + return; + } + ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); + /* Reached bufferPool capacity (note: should not happen) */ + DEBUGLOG(5, "ZSTDMT_releaseBuffer: pool capacity reached => freeing "); + ZSTD_customFree(buf.start, bufPool->cMem); +} + +/* We need 2 output buffers per worker since each dstBuff must be flushed after it is released. + * The 3 additional buffers are as follows: + * 1 buffer for input loading + * 1 buffer for "next input" when submitting current one + * 1 buffer stuck in queue */ +#define BUF_POOL_MAX_NB_BUFFERS(nbWorkers) (2*(nbWorkers) + 3) + +/* After a worker releases its rawSeqStore, it is immediately ready for reuse. + * So we only need one seq buffer per worker. */ +#define SEQ_POOL_MAX_NB_BUFFERS(nbWorkers) (nbWorkers) + +/* ===== Seq Pool Wrapper ====== */ + +typedef ZSTDMT_bufferPool ZSTDMT_seqPool; + +static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool) +{ + return ZSTDMT_sizeof_bufferPool(seqPool); +} + +static rawSeqStore_t bufferToSeq(buffer_t buffer) +{ + rawSeqStore_t seq = kNullRawSeqStore; + seq.seq = (rawSeq*)buffer.start; + seq.capacity = buffer.capacity / sizeof(rawSeq); + return seq; +} + +static buffer_t seqToBuffer(rawSeqStore_t seq) +{ + buffer_t buffer; + buffer.start = seq.seq; + buffer.capacity = seq.capacity * sizeof(rawSeq); + return buffer; +} + +static rawSeqStore_t ZSTDMT_getSeq(ZSTDMT_seqPool* seqPool) +{ + if (seqPool->bufferSize == 0) { + return kNullRawSeqStore; + } + return bufferToSeq(ZSTDMT_getBuffer(seqPool)); +} + +#if ZSTD_RESIZE_SEQPOOL +static rawSeqStore_t ZSTDMT_resizeSeq(ZSTDMT_seqPool* seqPool, rawSeqStore_t seq) +{ + return bufferToSeq(ZSTDMT_resizeBuffer(seqPool, seqToBuffer(seq))); +} +#endif + +static void ZSTDMT_releaseSeq(ZSTDMT_seqPool* seqPool, rawSeqStore_t seq) +{ + ZSTDMT_releaseBuffer(seqPool, seqToBuffer(seq)); +} + +static void ZSTDMT_setNbSeq(ZSTDMT_seqPool* const seqPool, size_t const nbSeq) +{ + ZSTDMT_setBufferSize(seqPool, nbSeq * sizeof(rawSeq)); +} + +static ZSTDMT_seqPool* ZSTDMT_createSeqPool(unsigned nbWorkers, ZSTD_customMem cMem) +{ + ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(SEQ_POOL_MAX_NB_BUFFERS(nbWorkers), cMem); + if (seqPool == NULL) return NULL; + ZSTDMT_setNbSeq(seqPool, 0); + return seqPool; +} + +static void ZSTDMT_freeSeqPool(ZSTDMT_seqPool* seqPool) +{ + ZSTDMT_freeBufferPool(seqPool); +} + +static ZSTDMT_seqPool* ZSTDMT_expandSeqPool(ZSTDMT_seqPool* pool, U32 nbWorkers) +{ + return ZSTDMT_expandBufferPool(pool, SEQ_POOL_MAX_NB_BUFFERS(nbWorkers)); +} + + +/* ===== CCtx Pool ===== */ +/* a single CCtx Pool can be invoked from multiple threads in parallel */ + +typedef struct { + ZSTD_pthread_mutex_t poolMutex; + int totalCCtx; + int availCCtx; + ZSTD_customMem cMem; + ZSTD_CCtx** cctxs; +} ZSTDMT_CCtxPool; + +/* note : all CCtx borrowed from the pool must be reverted back to the pool _before_ freeing the pool */ +static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool) +{ + if (!pool) return; + ZSTD_pthread_mutex_destroy(&pool->poolMutex); + if (pool->cctxs) { + int cid; + for (cid=0; cidtotalCCtx; cid++) + ZSTD_freeCCtx(pool->cctxs[cid]); /* free compatible with NULL */ + ZSTD_customFree(pool->cctxs, pool->cMem); + } + ZSTD_customFree(pool, pool->cMem); +} + +/* ZSTDMT_createCCtxPool() : + * implies nbWorkers >= 1 , checked by caller ZSTDMT_createCCtx() */ +static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers, + ZSTD_customMem cMem) +{ + ZSTDMT_CCtxPool* const cctxPool = + (ZSTDMT_CCtxPool*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtxPool), cMem); + assert(nbWorkers > 0); + if (!cctxPool) return NULL; + if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) { + ZSTD_customFree(cctxPool, cMem); + return NULL; + } + cctxPool->totalCCtx = nbWorkers; + cctxPool->cctxs = (ZSTD_CCtx**)ZSTD_customCalloc(nbWorkers * sizeof(ZSTD_CCtx*), cMem); + if (!cctxPool->cctxs) { + ZSTDMT_freeCCtxPool(cctxPool); + return NULL; + } + cctxPool->cMem = cMem; + cctxPool->cctxs[0] = ZSTD_createCCtx_advanced(cMem); + if (!cctxPool->cctxs[0]) { ZSTDMT_freeCCtxPool(cctxPool); return NULL; } + cctxPool->availCCtx = 1; /* at least one cctx for single-thread mode */ + DEBUGLOG(3, "cctxPool created, with %u workers", nbWorkers); + return cctxPool; +} + +static ZSTDMT_CCtxPool* ZSTDMT_expandCCtxPool(ZSTDMT_CCtxPool* srcPool, + int nbWorkers) +{ + if (srcPool==NULL) return NULL; + if (nbWorkers <= srcPool->totalCCtx) return srcPool; /* good enough */ + /* need a larger cctx pool */ + { ZSTD_customMem const cMem = srcPool->cMem; + ZSTDMT_freeCCtxPool(srcPool); + return ZSTDMT_createCCtxPool(nbWorkers, cMem); + } +} + +/* only works during initialization phase, not during compression */ +static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool) +{ + ZSTD_pthread_mutex_lock(&cctxPool->poolMutex); + { unsigned const nbWorkers = cctxPool->totalCCtx; + size_t const poolSize = sizeof(*cctxPool); + size_t const arraySize = cctxPool->totalCCtx * sizeof(ZSTD_CCtx*); + size_t totalCCtxSize = 0; + unsigned u; + for (u=0; ucctxs[u]); + } + ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex); + assert(nbWorkers > 0); + return poolSize + arraySize + totalCCtxSize; + } +} + +static ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* cctxPool) +{ + DEBUGLOG(5, "ZSTDMT_getCCtx"); + ZSTD_pthread_mutex_lock(&cctxPool->poolMutex); + if (cctxPool->availCCtx) { + cctxPool->availCCtx--; + { ZSTD_CCtx* const cctx = cctxPool->cctxs[cctxPool->availCCtx]; + ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex); + return cctx; + } } + ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex); + DEBUGLOG(5, "create one more CCtx"); + return ZSTD_createCCtx_advanced(cctxPool->cMem); /* note : can be NULL, when creation fails ! */ +} + +static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx) +{ + if (cctx==NULL) return; /* compatibility with release on NULL */ + ZSTD_pthread_mutex_lock(&pool->poolMutex); + if (pool->availCCtx < pool->totalCCtx) + pool->cctxs[pool->availCCtx++] = cctx; + else { + /* pool overflow : should not happen, since totalCCtx==nbWorkers */ + DEBUGLOG(4, "CCtx pool overflow : free cctx"); + ZSTD_freeCCtx(cctx); + } + ZSTD_pthread_mutex_unlock(&pool->poolMutex); +} + +/* ==== Serial State ==== */ + +typedef struct { + void const* start; + size_t size; +} range_t; + +typedef struct { + /* All variables in the struct are protected by mutex. */ + ZSTD_pthread_mutex_t mutex; + ZSTD_pthread_cond_t cond; + ZSTD_CCtx_params params; + ldmState_t ldmState; + XXH64_state_t xxhState; + unsigned nextJobID; + /* Protects ldmWindow. + * Must be acquired after the main mutex when acquiring both. + */ + ZSTD_pthread_mutex_t ldmWindowMutex; + ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is updated */ + ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */ +} serialState_t; + +static int +ZSTDMT_serialState_reset(serialState_t* serialState, + ZSTDMT_seqPool* seqPool, + ZSTD_CCtx_params params, + size_t jobSize, + const void* dict, size_t const dictSize, + ZSTD_dictContentType_e dictContentType) +{ + /* Adjust parameters */ + if (params.ldmParams.enableLdm == ZSTD_ps_enable) { + DEBUGLOG(4, "LDM window size = %u KB", (1U << params.cParams.windowLog) >> 10); + ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams); + assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog); + assert(params.ldmParams.hashRateLog < 32); + } else { + ZSTD_memset(¶ms.ldmParams, 0, sizeof(params.ldmParams)); + } + serialState->nextJobID = 0; + if (params.fParams.checksumFlag) + XXH64_reset(&serialState->xxhState, 0); + if (params.ldmParams.enableLdm == ZSTD_ps_enable) { + ZSTD_customMem cMem = params.customMem; + unsigned const hashLog = params.ldmParams.hashLog; + size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t); + unsigned const bucketLog = + params.ldmParams.hashLog - params.ldmParams.bucketSizeLog; + unsigned const prevBucketLog = + serialState->params.ldmParams.hashLog - + serialState->params.ldmParams.bucketSizeLog; + size_t const numBuckets = (size_t)1 << bucketLog; + /* Size the seq pool tables */ + ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize)); + /* Reset the window */ + ZSTD_window_init(&serialState->ldmState.window); + /* Resize tables and output space if necessary. */ + if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) { + ZSTD_customFree(serialState->ldmState.hashTable, cMem); + serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_customMalloc(hashSize, cMem); + } + if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) { + ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem); + serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_customMalloc(numBuckets, cMem); + } + if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets) + return 1; + /* Zero the tables */ + ZSTD_memset(serialState->ldmState.hashTable, 0, hashSize); + ZSTD_memset(serialState->ldmState.bucketOffsets, 0, numBuckets); + + /* Update window state and fill hash table with dict */ + serialState->ldmState.loadedDictEnd = 0; + if (dictSize > 0) { + if (dictContentType == ZSTD_dct_rawContent) { + BYTE const* const dictEnd = (const BYTE*)dict + dictSize; + ZSTD_window_update(&serialState->ldmState.window, dict, dictSize, /* forceNonContiguous */ 0); + ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, ¶ms.ldmParams); + serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base); + } else { + /* don't even load anything */ + } + } + + /* Initialize serialState's copy of ldmWindow. */ + serialState->ldmWindow = serialState->ldmState.window; + } + + serialState->params = params; + serialState->params.jobSize = (U32)jobSize; + return 0; +} + +static int ZSTDMT_serialState_init(serialState_t* serialState) +{ + int initError = 0; + ZSTD_memset(serialState, 0, sizeof(*serialState)); + initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL); + initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL); + initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL); + initError |= ZSTD_pthread_cond_init(&serialState->ldmWindowCond, NULL); + return initError; +} + +static void ZSTDMT_serialState_free(serialState_t* serialState) +{ + ZSTD_customMem cMem = serialState->params.customMem; + ZSTD_pthread_mutex_destroy(&serialState->mutex); + ZSTD_pthread_cond_destroy(&serialState->cond); + ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex); + ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond); + ZSTD_customFree(serialState->ldmState.hashTable, cMem); + ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem); +} + +static void ZSTDMT_serialState_update(serialState_t* serialState, + ZSTD_CCtx* jobCCtx, rawSeqStore_t seqStore, + range_t src, unsigned jobID) +{ + /* Wait for our turn */ + ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex); + while (serialState->nextJobID < jobID) { + DEBUGLOG(5, "wait for serialState->cond"); + ZSTD_pthread_cond_wait(&serialState->cond, &serialState->mutex); + } + /* A future job may error and skip our job */ + if (serialState->nextJobID == jobID) { + /* It is now our turn, do any processing necessary */ + if (serialState->params.ldmParams.enableLdm == ZSTD_ps_enable) { + size_t error; + assert(seqStore.seq != NULL && seqStore.pos == 0 && + seqStore.size == 0 && seqStore.capacity > 0); + assert(src.size <= serialState->params.jobSize); + ZSTD_window_update(&serialState->ldmState.window, src.start, src.size, /* forceNonContiguous */ 0); + error = ZSTD_ldm_generateSequences( + &serialState->ldmState, &seqStore, + &serialState->params.ldmParams, src.start, src.size); + /* We provide a large enough buffer to never fail. */ + assert(!ZSTD_isError(error)); (void)error; + /* Update ldmWindow to match the ldmState.window and signal the main + * thread if it is waiting for a buffer. + */ + ZSTD_PTHREAD_MUTEX_LOCK(&serialState->ldmWindowMutex); + serialState->ldmWindow = serialState->ldmState.window; + ZSTD_pthread_cond_signal(&serialState->ldmWindowCond); + ZSTD_pthread_mutex_unlock(&serialState->ldmWindowMutex); + } + if (serialState->params.fParams.checksumFlag && src.size > 0) + XXH64_update(&serialState->xxhState, src.start, src.size); + } + /* Now it is the next jobs turn */ + serialState->nextJobID++; + ZSTD_pthread_cond_broadcast(&serialState->cond); + ZSTD_pthread_mutex_unlock(&serialState->mutex); + + if (seqStore.size > 0) { + ZSTD_referenceExternalSequences(jobCCtx, seqStore.seq, seqStore.size); + assert(serialState->params.ldmParams.enableLdm == ZSTD_ps_enable); + } +} + +static void ZSTDMT_serialState_ensureFinished(serialState_t* serialState, + unsigned jobID, size_t cSize) +{ + ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex); + if (serialState->nextJobID <= jobID) { + assert(ZSTD_isError(cSize)); (void)cSize; + DEBUGLOG(5, "Skipping past job %u because of error", jobID); + serialState->nextJobID = jobID + 1; + ZSTD_pthread_cond_broadcast(&serialState->cond); + + ZSTD_PTHREAD_MUTEX_LOCK(&serialState->ldmWindowMutex); + ZSTD_window_clear(&serialState->ldmWindow); + ZSTD_pthread_cond_signal(&serialState->ldmWindowCond); + ZSTD_pthread_mutex_unlock(&serialState->ldmWindowMutex); + } + ZSTD_pthread_mutex_unlock(&serialState->mutex); + +} + + +/* ------------------------------------------ */ +/* ===== Worker thread ===== */ +/* ------------------------------------------ */ + +static const range_t kNullRange = { NULL, 0 }; + +typedef struct { + size_t consumed; /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx */ + size_t cSize; /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx, then set0 by mtctx */ + ZSTD_pthread_mutex_t job_mutex; /* Thread-safe - used by mtctx and worker */ + ZSTD_pthread_cond_t job_cond; /* Thread-safe - used by mtctx and worker */ + ZSTDMT_CCtxPool* cctxPool; /* Thread-safe - used by mtctx and (all) workers */ + ZSTDMT_bufferPool* bufPool; /* Thread-safe - used by mtctx and (all) workers */ + ZSTDMT_seqPool* seqPool; /* Thread-safe - used by mtctx and (all) workers */ + serialState_t* serial; /* Thread-safe - used by mtctx and (all) workers */ + buffer_t dstBuff; /* set by worker (or mtctx), then read by worker & mtctx, then modified by mtctx => no barrier */ + range_t prefix; /* set by mtctx, then read by worker & mtctx => no barrier */ + range_t src; /* set by mtctx, then read by worker & mtctx => no barrier */ + unsigned jobID; /* set by mtctx, then read by worker => no barrier */ + unsigned firstJob; /* set by mtctx, then read by worker => no barrier */ + unsigned lastJob; /* set by mtctx, then read by worker => no barrier */ + ZSTD_CCtx_params params; /* set by mtctx, then read by worker => no barrier */ + const ZSTD_CDict* cdict; /* set by mtctx, then read by worker => no barrier */ + unsigned long long fullFrameSize; /* set by mtctx, then read by worker => no barrier */ + size_t dstFlushed; /* used only by mtctx */ + unsigned frameChecksumNeeded; /* used only by mtctx */ +} ZSTDMT_jobDescription; + +#define JOB_ERROR(e) \ + do { \ + ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex); \ + job->cSize = e; \ + ZSTD_pthread_mutex_unlock(&job->job_mutex); \ + goto _endJob; \ + } while (0) + +/* ZSTDMT_compressionJob() is a POOL_function type */ +static void ZSTDMT_compressionJob(void* jobDescription) +{ + ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription; + ZSTD_CCtx_params jobParams = job->params; /* do not modify job->params ! copy it, modify the copy */ + ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(job->cctxPool); + rawSeqStore_t rawSeqStore = ZSTDMT_getSeq(job->seqPool); + buffer_t dstBuff = job->dstBuff; + size_t lastCBlockSize = 0; + + /* resources */ + if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation)); + if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */ + dstBuff = ZSTDMT_getBuffer(job->bufPool); + if (dstBuff.start==NULL) JOB_ERROR(ERROR(memory_allocation)); + job->dstBuff = dstBuff; /* this value can be read in ZSTDMT_flush, when it copies the whole job */ + } + if (jobParams.ldmParams.enableLdm == ZSTD_ps_enable && rawSeqStore.seq == NULL) + JOB_ERROR(ERROR(memory_allocation)); + + /* Don't compute the checksum for chunks, since we compute it externally, + * but write it in the header. + */ + if (job->jobID != 0) jobParams.fParams.checksumFlag = 0; + /* Don't run LDM for the chunks, since we handle it externally */ + jobParams.ldmParams.enableLdm = ZSTD_ps_disable; + /* Correct nbWorkers to 0. */ + jobParams.nbWorkers = 0; + + + /* init */ + if (job->cdict) { + size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, job->cdict, &jobParams, job->fullFrameSize); + assert(job->firstJob); /* only allowed for first job */ + if (ZSTD_isError(initError)) JOB_ERROR(initError); + } else { /* srcStart points at reloaded section */ + U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size; + { size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob); + if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError); + } + if (!job->firstJob) { + size_t const err = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_deterministicRefPrefix, 0); + if (ZSTD_isError(err)) JOB_ERROR(err); + } + { size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, + job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */ + ZSTD_dtlm_fast, + NULL, /*cdict*/ + &jobParams, pledgedSrcSize); + if (ZSTD_isError(initError)) JOB_ERROR(initError); + } } + + /* Perform serial step as early as possible, but after CCtx initialization */ + ZSTDMT_serialState_update(job->serial, cctx, rawSeqStore, job->src, job->jobID); + + if (!job->firstJob) { /* flush and overwrite frame header when it's not first job */ + size_t const hSize = ZSTD_compressContinue_public(cctx, dstBuff.start, dstBuff.capacity, job->src.start, 0); + if (ZSTD_isError(hSize)) JOB_ERROR(hSize); + DEBUGLOG(5, "ZSTDMT_compressionJob: flush and overwrite %u bytes of frame header (not first job)", (U32)hSize); + ZSTD_invalidateRepCodes(cctx); + } + + /* compress */ + { size_t const chunkSize = 4*ZSTD_BLOCKSIZE_MAX; + int const nbChunks = (int)((job->src.size + (chunkSize-1)) / chunkSize); + const BYTE* ip = (const BYTE*) job->src.start; + BYTE* const ostart = (BYTE*)dstBuff.start; + BYTE* op = ostart; + BYTE* oend = op + dstBuff.capacity; + int chunkNb; + if (sizeof(size_t) > sizeof(int)) assert(job->src.size < ((size_t)INT_MAX) * chunkSize); /* check overflow */ + DEBUGLOG(5, "ZSTDMT_compressionJob: compress %u bytes in %i blocks", (U32)job->src.size, nbChunks); + assert(job->cSize == 0); + for (chunkNb = 1; chunkNb < nbChunks; chunkNb++) { + size_t const cSize = ZSTD_compressContinue_public(cctx, op, oend-op, ip, chunkSize); + if (ZSTD_isError(cSize)) JOB_ERROR(cSize); + ip += chunkSize; + op += cSize; assert(op < oend); + /* stats */ + ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex); + job->cSize += cSize; + job->consumed = chunkSize * chunkNb; + DEBUGLOG(5, "ZSTDMT_compressionJob: compress new block : cSize==%u bytes (total: %u)", + (U32)cSize, (U32)job->cSize); + ZSTD_pthread_cond_signal(&job->job_cond); /* warns some more data is ready to be flushed */ + ZSTD_pthread_mutex_unlock(&job->job_mutex); + } + /* last block */ + assert(chunkSize > 0); + assert((chunkSize & (chunkSize - 1)) == 0); /* chunkSize must be power of 2 for mask==(chunkSize-1) to work */ + if ((nbChunks > 0) | job->lastJob /*must output a "last block" flag*/ ) { + size_t const lastBlockSize1 = job->src.size & (chunkSize-1); + size_t const lastBlockSize = ((lastBlockSize1==0) & (job->src.size>=chunkSize)) ? chunkSize : lastBlockSize1; + size_t const cSize = (job->lastJob) ? + ZSTD_compressEnd_public(cctx, op, oend-op, ip, lastBlockSize) : + ZSTD_compressContinue_public(cctx, op, oend-op, ip, lastBlockSize); + if (ZSTD_isError(cSize)) JOB_ERROR(cSize); + lastCBlockSize = cSize; + } } + if (!job->firstJob) { + /* Double check that we don't have an ext-dict, because then our + * repcode invalidation doesn't work. + */ + assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window)); + } + ZSTD_CCtx_trace(cctx, 0); + +_endJob: + ZSTDMT_serialState_ensureFinished(job->serial, job->jobID, job->cSize); + if (job->prefix.size > 0) + DEBUGLOG(5, "Finished with prefix: %zx", (size_t)job->prefix.start); + DEBUGLOG(5, "Finished with source: %zx", (size_t)job->src.start); + /* release resources */ + ZSTDMT_releaseSeq(job->seqPool, rawSeqStore); + ZSTDMT_releaseCCtx(job->cctxPool, cctx); + /* report */ + ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex); + if (ZSTD_isError(job->cSize)) assert(lastCBlockSize == 0); + job->cSize += lastCBlockSize; + job->consumed = job->src.size; /* when job->consumed == job->src.size , compression job is presumed completed */ + ZSTD_pthread_cond_signal(&job->job_cond); + ZSTD_pthread_mutex_unlock(&job->job_mutex); +} + + +/* ------------------------------------------ */ +/* ===== Multi-threaded compression ===== */ +/* ------------------------------------------ */ + +typedef struct { + range_t prefix; /* read-only non-owned prefix buffer */ + buffer_t buffer; + size_t filled; +} inBuff_t; + +typedef struct { + BYTE* buffer; /* The round input buffer. All jobs get references + * to pieces of the buffer. ZSTDMT_tryGetInputRange() + * handles handing out job input buffers, and makes + * sure it doesn't overlap with any pieces still in use. + */ + size_t capacity; /* The capacity of buffer. */ + size_t pos; /* The position of the current inBuff in the round + * buffer. Updated past the end if the inBuff once + * the inBuff is sent to the worker thread. + * pos <= capacity. + */ +} roundBuff_t; + +static const roundBuff_t kNullRoundBuff = {NULL, 0, 0}; + +#define RSYNC_LENGTH 32 +/* Don't create chunks smaller than the zstd block size. + * This stops us from regressing compression ratio too much, + * and ensures our output fits in ZSTD_compressBound(). + * + * If this is shrunk < ZSTD_BLOCKSIZELOG_MIN then + * ZSTD_COMPRESSBOUND() will need to be updated. + */ +#define RSYNC_MIN_BLOCK_LOG ZSTD_BLOCKSIZELOG_MAX +#define RSYNC_MIN_BLOCK_SIZE (1< one job is already prepared, but pool has shortage of workers. Don't create a new job. */ + inBuff_t inBuff; + roundBuff_t roundBuff; + serialState_t serial; + rsyncState_t rsync; + unsigned jobIDMask; + unsigned doneJobID; + unsigned nextJobID; + unsigned frameEnded; + unsigned allJobsCompleted; + unsigned long long frameContentSize; + unsigned long long consumed; + unsigned long long produced; + ZSTD_customMem cMem; + ZSTD_CDict* cdictLocal; + const ZSTD_CDict* cdict; + unsigned providedFactory: 1; +}; + +static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZSTD_customMem cMem) +{ + U32 jobNb; + if (jobTable == NULL) return; + for (jobNb=0; jobNb mtctx->jobIDMask+1) { /* need more job capacity */ + ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem); + mtctx->jobIDMask = 0; + mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, mtctx->cMem); + if (mtctx->jobs==NULL) return ERROR(memory_allocation); + assert((nbJobs != 0) && ((nbJobs & (nbJobs - 1)) == 0)); /* ensure nbJobs is a power of 2 */ + mtctx->jobIDMask = nbJobs - 1; + } + return 0; +} + + +/* ZSTDMT_CCtxParam_setNbWorkers(): + * Internal use only */ +static size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers) +{ + return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers); +} + +MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool) +{ + ZSTDMT_CCtx* mtctx; + U32 nbJobs = nbWorkers + 2; + int initError; + DEBUGLOG(3, "ZSTDMT_createCCtx_advanced (nbWorkers = %u)", nbWorkers); + + if (nbWorkers < 1) return NULL; + nbWorkers = MIN(nbWorkers , ZSTDMT_NBWORKERS_MAX); + if ((cMem.customAlloc!=NULL) ^ (cMem.customFree!=NULL)) + /* invalid custom allocator */ + return NULL; + + mtctx = (ZSTDMT_CCtx*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtx), cMem); + if (!mtctx) return NULL; + ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers); + mtctx->cMem = cMem; + mtctx->allJobsCompleted = 1; + if (pool != NULL) { + mtctx->factory = pool; + mtctx->providedFactory = 1; + } + else { + mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem); + mtctx->providedFactory = 0; + } + mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem); + assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0); /* ensure nbJobs is a power of 2 */ + mtctx->jobIDMask = nbJobs - 1; + mtctx->bufPool = ZSTDMT_createBufferPool(BUF_POOL_MAX_NB_BUFFERS(nbWorkers), cMem); + mtctx->cctxPool = ZSTDMT_createCCtxPool(nbWorkers, cMem); + mtctx->seqPool = ZSTDMT_createSeqPool(nbWorkers, cMem); + initError = ZSTDMT_serialState_init(&mtctx->serial); + mtctx->roundBuff = kNullRoundBuff; + if (!mtctx->factory | !mtctx->jobs | !mtctx->bufPool | !mtctx->cctxPool | !mtctx->seqPool | initError) { + ZSTDMT_freeCCtx(mtctx); + return NULL; + } + DEBUGLOG(3, "mt_cctx created, for %u threads", nbWorkers); + return mtctx; +} + +ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool) +{ +#ifdef ZSTD_MULTITHREAD + return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem, pool); +#else + (void)nbWorkers; + (void)cMem; + (void)pool; + return NULL; +#endif +} + + +/* ZSTDMT_releaseAllJobResources() : + * note : ensure all workers are killed first ! */ +static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx) +{ + unsigned jobID; + DEBUGLOG(3, "ZSTDMT_releaseAllJobResources"); + for (jobID=0; jobID <= mtctx->jobIDMask; jobID++) { + /* Copy the mutex/cond out */ + ZSTD_pthread_mutex_t const mutex = mtctx->jobs[jobID].job_mutex; + ZSTD_pthread_cond_t const cond = mtctx->jobs[jobID].job_cond; + + DEBUGLOG(4, "job%02u: release dst address %08X", jobID, (U32)(size_t)mtctx->jobs[jobID].dstBuff.start); + ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff); + + /* Clear the job description, but keep the mutex/cond */ + ZSTD_memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID])); + mtctx->jobs[jobID].job_mutex = mutex; + mtctx->jobs[jobID].job_cond = cond; + } + mtctx->inBuff.buffer = g_nullBuffer; + mtctx->inBuff.filled = 0; + mtctx->allJobsCompleted = 1; +} + +static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx) +{ + DEBUGLOG(4, "ZSTDMT_waitForAllJobsCompleted"); + while (mtctx->doneJobID < mtctx->nextJobID) { + unsigned const jobID = mtctx->doneJobID & mtctx->jobIDMask; + ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex); + while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) { + DEBUGLOG(4, "waiting for jobCompleted signal from job %u", mtctx->doneJobID); /* we want to block when waiting for data to flush */ + ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex); + } + ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex); + mtctx->doneJobID++; + } +} + +size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx) +{ + if (mtctx==NULL) return 0; /* compatible with free on NULL */ + if (!mtctx->providedFactory) + POOL_free(mtctx->factory); /* stop and free worker threads */ + ZSTDMT_releaseAllJobResources(mtctx); /* release job resources into pools first */ + ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem); + ZSTDMT_freeBufferPool(mtctx->bufPool); + ZSTDMT_freeCCtxPool(mtctx->cctxPool); + ZSTDMT_freeSeqPool(mtctx->seqPool); + ZSTDMT_serialState_free(&mtctx->serial); + ZSTD_freeCDict(mtctx->cdictLocal); + if (mtctx->roundBuff.buffer) + ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem); + ZSTD_customFree(mtctx, mtctx->cMem); + return 0; +} + +size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx) +{ + if (mtctx == NULL) return 0; /* supports sizeof NULL */ + return sizeof(*mtctx) + + POOL_sizeof(mtctx->factory) + + ZSTDMT_sizeof_bufferPool(mtctx->bufPool) + + (mtctx->jobIDMask+1) * sizeof(ZSTDMT_jobDescription) + + ZSTDMT_sizeof_CCtxPool(mtctx->cctxPool) + + ZSTDMT_sizeof_seqPool(mtctx->seqPool) + + ZSTD_sizeof_CDict(mtctx->cdictLocal) + + mtctx->roundBuff.capacity; +} + + +/* ZSTDMT_resize() : + * @return : error code if fails, 0 on success */ +static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers) +{ + if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation); + FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) , ""); + mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, BUF_POOL_MAX_NB_BUFFERS(nbWorkers)); + if (mtctx->bufPool == NULL) return ERROR(memory_allocation); + mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers); + if (mtctx->cctxPool == NULL) return ERROR(memory_allocation); + mtctx->seqPool = ZSTDMT_expandSeqPool(mtctx->seqPool, nbWorkers); + if (mtctx->seqPool == NULL) return ERROR(memory_allocation); + ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers); + return 0; +} + + +/*! ZSTDMT_updateCParams_whileCompressing() : + * Updates a selected set of compression parameters, remaining compatible with currently active frame. + * New parameters will be applied to next compression job. */ +void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams) +{ + U32 const saved_wlog = mtctx->params.cParams.windowLog; /* Do not modify windowLog while compressing */ + int const compressionLevel = cctxParams->compressionLevel; + DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)", + compressionLevel); + mtctx->params.compressionLevel = compressionLevel; + { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + cParams.windowLog = saved_wlog; + mtctx->params.cParams = cParams; + } +} + +/* ZSTDMT_getFrameProgression(): + * tells how much data has been consumed (input) and produced (output) for current frame. + * able to count progression inside worker threads. + * Note : mutex will be acquired during statistics collection inside workers. */ +ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx) +{ + ZSTD_frameProgression fps; + DEBUGLOG(5, "ZSTDMT_getFrameProgression"); + fps.ingested = mtctx->consumed + mtctx->inBuff.filled; + fps.consumed = mtctx->consumed; + fps.produced = fps.flushed = mtctx->produced; + fps.currentJobID = mtctx->nextJobID; + fps.nbActiveWorkers = 0; + { unsigned jobNb; + unsigned lastJobNb = mtctx->nextJobID + mtctx->jobReady; assert(mtctx->jobReady <= 1); + DEBUGLOG(6, "ZSTDMT_getFrameProgression: jobs: from %u to <%u (jobReady:%u)", + mtctx->doneJobID, lastJobNb, mtctx->jobReady); + for (jobNb = mtctx->doneJobID ; jobNb < lastJobNb ; jobNb++) { + unsigned const wJobID = jobNb & mtctx->jobIDMask; + ZSTDMT_jobDescription* jobPtr = &mtctx->jobs[wJobID]; + ZSTD_pthread_mutex_lock(&jobPtr->job_mutex); + { size_t const cResult = jobPtr->cSize; + size_t const produced = ZSTD_isError(cResult) ? 0 : cResult; + size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed; + assert(flushed <= produced); + fps.ingested += jobPtr->src.size; + fps.consumed += jobPtr->consumed; + fps.produced += produced; + fps.flushed += flushed; + fps.nbActiveWorkers += (jobPtr->consumed < jobPtr->src.size); + } + ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex); + } + } + return fps; +} + + +size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx) +{ + size_t toFlush; + unsigned const jobID = mtctx->doneJobID; + assert(jobID <= mtctx->nextJobID); + if (jobID == mtctx->nextJobID) return 0; /* no active job => nothing to flush */ + + /* look into oldest non-fully-flushed job */ + { unsigned const wJobID = jobID & mtctx->jobIDMask; + ZSTDMT_jobDescription* const jobPtr = &mtctx->jobs[wJobID]; + ZSTD_pthread_mutex_lock(&jobPtr->job_mutex); + { size_t const cResult = jobPtr->cSize; + size_t const produced = ZSTD_isError(cResult) ? 0 : cResult; + size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed; + assert(flushed <= produced); + assert(jobPtr->consumed <= jobPtr->src.size); + toFlush = produced - flushed; + /* if toFlush==0, nothing is available to flush. + * However, jobID is expected to still be active: + * if jobID was already completed and fully flushed, + * ZSTDMT_flushProduced() should have already moved onto next job. + * Therefore, some input has not yet been consumed. */ + if (toFlush==0) { + assert(jobPtr->consumed < jobPtr->src.size); + } + } + ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex); + } + + return toFlush; +} + + +/* ------------------------------------------ */ +/* ===== Multi-threaded compression ===== */ +/* ------------------------------------------ */ + +static unsigned ZSTDMT_computeTargetJobLog(const ZSTD_CCtx_params* params) +{ + unsigned jobLog; + if (params->ldmParams.enableLdm == ZSTD_ps_enable) { + /* In Long Range Mode, the windowLog is typically oversized. + * In which case, it's preferable to determine the jobSize + * based on cycleLog instead. */ + jobLog = MAX(21, ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy) + 3); + } else { + jobLog = MAX(20, params->cParams.windowLog + 2); + } + return MIN(jobLog, (unsigned)ZSTDMT_JOBLOG_MAX); +} + +static int ZSTDMT_overlapLog_default(ZSTD_strategy strat) +{ + switch(strat) + { + case ZSTD_btultra2: + return 9; + case ZSTD_btultra: + case ZSTD_btopt: + return 8; + case ZSTD_btlazy2: + case ZSTD_lazy2: + return 7; + case ZSTD_lazy: + case ZSTD_greedy: + case ZSTD_dfast: + case ZSTD_fast: + default:; + } + return 6; +} + +static int ZSTDMT_overlapLog(int ovlog, ZSTD_strategy strat) +{ + assert(0 <= ovlog && ovlog <= 9); + if (ovlog == 0) return ZSTDMT_overlapLog_default(strat); + return ovlog; +} + +static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params) +{ + int const overlapRLog = 9 - ZSTDMT_overlapLog(params->overlapLog, params->cParams.strategy); + int ovLog = (overlapRLog >= 8) ? 0 : (params->cParams.windowLog - overlapRLog); + assert(0 <= overlapRLog && overlapRLog <= 8); + if (params->ldmParams.enableLdm == ZSTD_ps_enable) { + /* In Long Range Mode, the windowLog is typically oversized. + * In which case, it's preferable to determine the jobSize + * based on chainLog instead. + * Then, ovLog becomes a fraction of the jobSize, rather than windowSize */ + ovLog = MIN(params->cParams.windowLog, ZSTDMT_computeTargetJobLog(params) - 2) + - overlapRLog; + } + assert(0 <= ovLog && ovLog <= ZSTD_WINDOWLOG_MAX); + DEBUGLOG(4, "overlapLog : %i", params->overlapLog); + DEBUGLOG(4, "overlap size : %i", 1 << ovLog); + return (ovLog==0) ? 0 : (size_t)1 << ovLog; +} + +/* ====================================== */ +/* ======= Streaming API ======= */ +/* ====================================== */ + +size_t ZSTDMT_initCStream_internal( + ZSTDMT_CCtx* mtctx, + const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, + const ZSTD_CDict* cdict, ZSTD_CCtx_params params, + unsigned long long pledgedSrcSize) +{ + DEBUGLOG(4, "ZSTDMT_initCStream_internal (pledgedSrcSize=%u, nbWorkers=%u, cctxPool=%u)", + (U32)pledgedSrcSize, params.nbWorkers, mtctx->cctxPool->totalCCtx); + + /* params supposed partially fully validated at this point */ + assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); + assert(!((dict) && (cdict))); /* either dict or cdict, not both */ + + /* init */ + if (params.nbWorkers != mtctx->params.nbWorkers) + FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) , ""); + + if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN; + if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX; + + DEBUGLOG(4, "ZSTDMT_initCStream_internal: %u workers", params.nbWorkers); + + if (mtctx->allJobsCompleted == 0) { /* previous compression not correctly finished */ + ZSTDMT_waitForAllJobsCompleted(mtctx); + ZSTDMT_releaseAllJobResources(mtctx); + mtctx->allJobsCompleted = 1; + } + + mtctx->params = params; + mtctx->frameContentSize = pledgedSrcSize; + if (dict) { + ZSTD_freeCDict(mtctx->cdictLocal); + mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, + ZSTD_dlm_byCopy, dictContentType, /* note : a loadPrefix becomes an internal CDict */ + params.cParams, mtctx->cMem); + mtctx->cdict = mtctx->cdictLocal; + if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation); + } else { + ZSTD_freeCDict(mtctx->cdictLocal); + mtctx->cdictLocal = NULL; + mtctx->cdict = cdict; + } + + mtctx->targetPrefixSize = ZSTDMT_computeOverlapSize(¶ms); + DEBUGLOG(4, "overlapLog=%i => %u KB", params.overlapLog, (U32)(mtctx->targetPrefixSize>>10)); + mtctx->targetSectionSize = params.jobSize; + if (mtctx->targetSectionSize == 0) { + mtctx->targetSectionSize = 1ULL << ZSTDMT_computeTargetJobLog(¶ms); + } + assert(mtctx->targetSectionSize <= (size_t)ZSTDMT_JOBSIZE_MAX); + + if (params.rsyncable) { + /* Aim for the targetsectionSize as the average job size. */ + U32 const jobSizeKB = (U32)(mtctx->targetSectionSize >> 10); + U32 const rsyncBits = (assert(jobSizeKB >= 1), ZSTD_highbit32(jobSizeKB) + 10); + /* We refuse to create jobs < RSYNC_MIN_BLOCK_SIZE bytes, so make sure our + * expected job size is at least 4x larger. */ + assert(rsyncBits >= RSYNC_MIN_BLOCK_LOG + 2); + DEBUGLOG(4, "rsyncLog = %u", rsyncBits); + mtctx->rsync.hash = 0; + mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1; + mtctx->rsync.primePower = ZSTD_rollingHash_primePower(RSYNC_LENGTH); + } + if (mtctx->targetSectionSize < mtctx->targetPrefixSize) mtctx->targetSectionSize = mtctx->targetPrefixSize; /* job size must be >= overlap size */ + DEBUGLOG(4, "Job Size : %u KB (note : set to %u)", (U32)(mtctx->targetSectionSize>>10), (U32)params.jobSize); + DEBUGLOG(4, "inBuff Size : %u KB", (U32)(mtctx->targetSectionSize>>10)); + ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(mtctx->targetSectionSize)); + { + /* If ldm is enabled we need windowSize space. */ + size_t const windowSize = mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable ? (1U << mtctx->params.cParams.windowLog) : 0; + /* Two buffers of slack, plus extra space for the overlap + * This is the minimum slack that LDM works with. One extra because + * flush might waste up to targetSectionSize-1 bytes. Another extra + * for the overlap (if > 0), then one to fill which doesn't overlap + * with the LDM window. + */ + size_t const nbSlackBuffers = 2 + (mtctx->targetPrefixSize > 0); + size_t const slackSize = mtctx->targetSectionSize * nbSlackBuffers; + /* Compute the total size, and always have enough slack */ + size_t const nbWorkers = MAX(mtctx->params.nbWorkers, 1); + size_t const sectionsSize = mtctx->targetSectionSize * nbWorkers; + size_t const capacity = MAX(windowSize, sectionsSize) + slackSize; + if (mtctx->roundBuff.capacity < capacity) { + if (mtctx->roundBuff.buffer) + ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem); + mtctx->roundBuff.buffer = (BYTE*)ZSTD_customMalloc(capacity, mtctx->cMem); + if (mtctx->roundBuff.buffer == NULL) { + mtctx->roundBuff.capacity = 0; + return ERROR(memory_allocation); + } + mtctx->roundBuff.capacity = capacity; + } + } + DEBUGLOG(4, "roundBuff capacity : %u KB", (U32)(mtctx->roundBuff.capacity>>10)); + mtctx->roundBuff.pos = 0; + mtctx->inBuff.buffer = g_nullBuffer; + mtctx->inBuff.filled = 0; + mtctx->inBuff.prefix = kNullRange; + mtctx->doneJobID = 0; + mtctx->nextJobID = 0; + mtctx->frameEnded = 0; + mtctx->allJobsCompleted = 0; + mtctx->consumed = 0; + mtctx->produced = 0; + if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize, + dict, dictSize, dictContentType)) + return ERROR(memory_allocation); + return 0; +} + + +/* ZSTDMT_writeLastEmptyBlock() + * Write a single empty block with an end-of-frame to finish a frame. + * Job must be created from streaming variant. + * This function is always successful if expected conditions are fulfilled. + */ +static void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job) +{ + assert(job->lastJob == 1); + assert(job->src.size == 0); /* last job is empty -> will be simplified into a last empty block */ + assert(job->firstJob == 0); /* cannot be first job, as it also needs to create frame header */ + assert(job->dstBuff.start == NULL); /* invoked from streaming variant only (otherwise, dstBuff might be user's output) */ + job->dstBuff = ZSTDMT_getBuffer(job->bufPool); + if (job->dstBuff.start == NULL) { + job->cSize = ERROR(memory_allocation); + return; + } + assert(job->dstBuff.capacity >= ZSTD_blockHeaderSize); /* no buffer should ever be that small */ + job->src = kNullRange; + job->cSize = ZSTD_writeLastEmptyBlock(job->dstBuff.start, job->dstBuff.capacity); + assert(!ZSTD_isError(job->cSize)); + assert(job->consumed == 0); +} + +static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* mtctx, size_t srcSize, ZSTD_EndDirective endOp) +{ + unsigned const jobID = mtctx->nextJobID & mtctx->jobIDMask; + int const endFrame = (endOp == ZSTD_e_end); + + if (mtctx->nextJobID > mtctx->doneJobID + mtctx->jobIDMask) { + DEBUGLOG(5, "ZSTDMT_createCompressionJob: will not create new job : table is full"); + assert((mtctx->nextJobID & mtctx->jobIDMask) == (mtctx->doneJobID & mtctx->jobIDMask)); + return 0; + } + + if (!mtctx->jobReady) { + BYTE const* src = (BYTE const*)mtctx->inBuff.buffer.start; + DEBUGLOG(5, "ZSTDMT_createCompressionJob: preparing job %u to compress %u bytes with %u preload ", + mtctx->nextJobID, (U32)srcSize, (U32)mtctx->inBuff.prefix.size); + mtctx->jobs[jobID].src.start = src; + mtctx->jobs[jobID].src.size = srcSize; + assert(mtctx->inBuff.filled >= srcSize); + mtctx->jobs[jobID].prefix = mtctx->inBuff.prefix; + mtctx->jobs[jobID].consumed = 0; + mtctx->jobs[jobID].cSize = 0; + mtctx->jobs[jobID].params = mtctx->params; + mtctx->jobs[jobID].cdict = mtctx->nextJobID==0 ? mtctx->cdict : NULL; + mtctx->jobs[jobID].fullFrameSize = mtctx->frameContentSize; + mtctx->jobs[jobID].dstBuff = g_nullBuffer; + mtctx->jobs[jobID].cctxPool = mtctx->cctxPool; + mtctx->jobs[jobID].bufPool = mtctx->bufPool; + mtctx->jobs[jobID].seqPool = mtctx->seqPool; + mtctx->jobs[jobID].serial = &mtctx->serial; + mtctx->jobs[jobID].jobID = mtctx->nextJobID; + mtctx->jobs[jobID].firstJob = (mtctx->nextJobID==0); + mtctx->jobs[jobID].lastJob = endFrame; + mtctx->jobs[jobID].frameChecksumNeeded = mtctx->params.fParams.checksumFlag && endFrame && (mtctx->nextJobID>0); + mtctx->jobs[jobID].dstFlushed = 0; + + /* Update the round buffer pos and clear the input buffer to be reset */ + mtctx->roundBuff.pos += srcSize; + mtctx->inBuff.buffer = g_nullBuffer; + mtctx->inBuff.filled = 0; + /* Set the prefix */ + if (!endFrame) { + size_t const newPrefixSize = MIN(srcSize, mtctx->targetPrefixSize); + mtctx->inBuff.prefix.start = src + srcSize - newPrefixSize; + mtctx->inBuff.prefix.size = newPrefixSize; + } else { /* endFrame==1 => no need for another input buffer */ + mtctx->inBuff.prefix = kNullRange; + mtctx->frameEnded = endFrame; + if (mtctx->nextJobID == 0) { + /* single job exception : checksum is already calculated directly within worker thread */ + mtctx->params.fParams.checksumFlag = 0; + } } + + if ( (srcSize == 0) + && (mtctx->nextJobID>0)/*single job must also write frame header*/ ) { + DEBUGLOG(5, "ZSTDMT_createCompressionJob: creating a last empty block to end frame"); + assert(endOp == ZSTD_e_end); /* only possible case : need to end the frame with an empty last block */ + ZSTDMT_writeLastEmptyBlock(mtctx->jobs + jobID); + mtctx->nextJobID++; + return 0; + } + } + + DEBUGLOG(5, "ZSTDMT_createCompressionJob: posting job %u : %u bytes (end:%u, jobNb == %u (mod:%u))", + mtctx->nextJobID, + (U32)mtctx->jobs[jobID].src.size, + mtctx->jobs[jobID].lastJob, + mtctx->nextJobID, + jobID); + if (POOL_tryAdd(mtctx->factory, ZSTDMT_compressionJob, &mtctx->jobs[jobID])) { + mtctx->nextJobID++; + mtctx->jobReady = 0; + } else { + DEBUGLOG(5, "ZSTDMT_createCompressionJob: no worker available for job %u", mtctx->nextJobID); + mtctx->jobReady = 1; + } + return 0; +} + + +/*! ZSTDMT_flushProduced() : + * flush whatever data has been produced but not yet flushed in current job. + * move to next job if current one is fully flushed. + * `output` : `pos` will be updated with amount of data flushed . + * `blockToFlush` : if >0, the function will block and wait if there is no data available to flush . + * @return : amount of data remaining within internal buffer, 0 if no more, 1 if unknown but > 0, or an error code */ +static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, unsigned blockToFlush, ZSTD_EndDirective end) +{ + unsigned const wJobID = mtctx->doneJobID & mtctx->jobIDMask; + DEBUGLOG(5, "ZSTDMT_flushProduced (blocking:%u , job %u <= %u)", + blockToFlush, mtctx->doneJobID, mtctx->nextJobID); + assert(output->size >= output->pos); + + ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[wJobID].job_mutex); + if ( blockToFlush + && (mtctx->doneJobID < mtctx->nextJobID) ) { + assert(mtctx->jobs[wJobID].dstFlushed <= mtctx->jobs[wJobID].cSize); + while (mtctx->jobs[wJobID].dstFlushed == mtctx->jobs[wJobID].cSize) { /* nothing to flush */ + if (mtctx->jobs[wJobID].consumed == mtctx->jobs[wJobID].src.size) { + DEBUGLOG(5, "job %u is completely consumed (%u == %u) => don't wait for cond, there will be none", + mtctx->doneJobID, (U32)mtctx->jobs[wJobID].consumed, (U32)mtctx->jobs[wJobID].src.size); + break; + } + DEBUGLOG(5, "waiting for something to flush from job %u (currently flushed: %u bytes)", + mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed); + ZSTD_pthread_cond_wait(&mtctx->jobs[wJobID].job_cond, &mtctx->jobs[wJobID].job_mutex); /* block when nothing to flush but some to come */ + } } + + /* try to flush something */ + { size_t cSize = mtctx->jobs[wJobID].cSize; /* shared */ + size_t const srcConsumed = mtctx->jobs[wJobID].consumed; /* shared */ + size_t const srcSize = mtctx->jobs[wJobID].src.size; /* read-only, could be done after mutex lock, but no-declaration-after-statement */ + ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex); + if (ZSTD_isError(cSize)) { + DEBUGLOG(5, "ZSTDMT_flushProduced: job %u : compression error detected : %s", + mtctx->doneJobID, ZSTD_getErrorName(cSize)); + ZSTDMT_waitForAllJobsCompleted(mtctx); + ZSTDMT_releaseAllJobResources(mtctx); + return cSize; + } + /* add frame checksum if necessary (can only happen once) */ + assert(srcConsumed <= srcSize); + if ( (srcConsumed == srcSize) /* job completed -> worker no longer active */ + && mtctx->jobs[wJobID].frameChecksumNeeded ) { + U32 const checksum = (U32)XXH64_digest(&mtctx->serial.xxhState); + DEBUGLOG(4, "ZSTDMT_flushProduced: writing checksum : %08X \n", checksum); + MEM_writeLE32((char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].cSize, checksum); + cSize += 4; + mtctx->jobs[wJobID].cSize += 4; /* can write this shared value, as worker is no longer active */ + mtctx->jobs[wJobID].frameChecksumNeeded = 0; + } + + if (cSize > 0) { /* compression is ongoing or completed */ + size_t const toFlush = MIN(cSize - mtctx->jobs[wJobID].dstFlushed, output->size - output->pos); + DEBUGLOG(5, "ZSTDMT_flushProduced: Flushing %u bytes from job %u (completion:%u/%u, generated:%u)", + (U32)toFlush, mtctx->doneJobID, (U32)srcConsumed, (U32)srcSize, (U32)cSize); + assert(mtctx->doneJobID < mtctx->nextJobID); + assert(cSize >= mtctx->jobs[wJobID].dstFlushed); + assert(mtctx->jobs[wJobID].dstBuff.start != NULL); + if (toFlush > 0) { + ZSTD_memcpy((char*)output->dst + output->pos, + (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed, + toFlush); + } + output->pos += toFlush; + mtctx->jobs[wJobID].dstFlushed += toFlush; /* can write : this value is only used by mtctx */ + + if ( (srcConsumed == srcSize) /* job is completed */ + && (mtctx->jobs[wJobID].dstFlushed == cSize) ) { /* output buffer fully flushed => free this job position */ + DEBUGLOG(5, "Job %u completed (%u bytes), moving to next one", + mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed); + ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[wJobID].dstBuff); + DEBUGLOG(5, "dstBuffer released"); + mtctx->jobs[wJobID].dstBuff = g_nullBuffer; + mtctx->jobs[wJobID].cSize = 0; /* ensure this job slot is considered "not started" in future check */ + mtctx->consumed += srcSize; + mtctx->produced += cSize; + mtctx->doneJobID++; + } } + + /* return value : how many bytes left in buffer ; fake it to 1 when unknown but >0 */ + if (cSize > mtctx->jobs[wJobID].dstFlushed) return (cSize - mtctx->jobs[wJobID].dstFlushed); + if (srcSize > srcConsumed) return 1; /* current job not completely compressed */ + } + if (mtctx->doneJobID < mtctx->nextJobID) return 1; /* some more jobs ongoing */ + if (mtctx->jobReady) return 1; /* one job is ready to push, just not yet in the list */ + if (mtctx->inBuff.filled > 0) return 1; /* input is not empty, and still needs to be converted into a job */ + mtctx->allJobsCompleted = mtctx->frameEnded; /* all jobs are entirely flushed => if this one is last one, frame is completed */ + if (end == ZSTD_e_end) return !mtctx->frameEnded; /* for ZSTD_e_end, question becomes : is frame completed ? instead of : are internal buffers fully flushed ? */ + return 0; /* internal buffers fully flushed */ +} + +/** + * Returns the range of data used by the earliest job that is not yet complete. + * If the data of the first job is broken up into two segments, we cover both + * sections. + */ +static range_t ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx) +{ + unsigned const firstJobID = mtctx->doneJobID; + unsigned const lastJobID = mtctx->nextJobID; + unsigned jobID; + + for (jobID = firstJobID; jobID < lastJobID; ++jobID) { + unsigned const wJobID = jobID & mtctx->jobIDMask; + size_t consumed; + + ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[wJobID].job_mutex); + consumed = mtctx->jobs[wJobID].consumed; + ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex); + + if (consumed < mtctx->jobs[wJobID].src.size) { + range_t range = mtctx->jobs[wJobID].prefix; + if (range.size == 0) { + /* Empty prefix */ + range = mtctx->jobs[wJobID].src; + } + /* Job source in multiple segments not supported yet */ + assert(range.start <= mtctx->jobs[wJobID].src.start); + return range; + } + } + return kNullRange; +} + +/** + * Returns non-zero iff buffer and range overlap. + */ +static int ZSTDMT_isOverlapped(buffer_t buffer, range_t range) +{ + BYTE const* const bufferStart = (BYTE const*)buffer.start; + BYTE const* const rangeStart = (BYTE const*)range.start; + + if (rangeStart == NULL || bufferStart == NULL) + return 0; + + { + BYTE const* const bufferEnd = bufferStart + buffer.capacity; + BYTE const* const rangeEnd = rangeStart + range.size; + + /* Empty ranges cannot overlap */ + if (bufferStart == bufferEnd || rangeStart == rangeEnd) + return 0; + + return bufferStart < rangeEnd && rangeStart < bufferEnd; + } +} + +static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window) +{ + range_t extDict; + range_t prefix; + + DEBUGLOG(5, "ZSTDMT_doesOverlapWindow"); + extDict.start = window.dictBase + window.lowLimit; + extDict.size = window.dictLimit - window.lowLimit; + + prefix.start = window.base + window.dictLimit; + prefix.size = window.nextSrc - (window.base + window.dictLimit); + DEBUGLOG(5, "extDict [0x%zx, 0x%zx)", + (size_t)extDict.start, + (size_t)extDict.start + extDict.size); + DEBUGLOG(5, "prefix [0x%zx, 0x%zx)", + (size_t)prefix.start, + (size_t)prefix.start + prefix.size); + + return ZSTDMT_isOverlapped(buffer, extDict) + || ZSTDMT_isOverlapped(buffer, prefix); +} + +static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, buffer_t buffer) +{ + if (mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable) { + ZSTD_pthread_mutex_t* mutex = &mtctx->serial.ldmWindowMutex; + DEBUGLOG(5, "ZSTDMT_waitForLdmComplete"); + DEBUGLOG(5, "source [0x%zx, 0x%zx)", + (size_t)buffer.start, + (size_t)buffer.start + buffer.capacity); + ZSTD_PTHREAD_MUTEX_LOCK(mutex); + while (ZSTDMT_doesOverlapWindow(buffer, mtctx->serial.ldmWindow)) { + DEBUGLOG(5, "Waiting for LDM to finish..."); + ZSTD_pthread_cond_wait(&mtctx->serial.ldmWindowCond, mutex); + } + DEBUGLOG(6, "Done waiting for LDM to finish"); + ZSTD_pthread_mutex_unlock(mutex); + } +} + +/** + * Attempts to set the inBuff to the next section to fill. + * If any part of the new section is still in use we give up. + * Returns non-zero if the buffer is filled. + */ +static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx) +{ + range_t const inUse = ZSTDMT_getInputDataInUse(mtctx); + size_t const spaceLeft = mtctx->roundBuff.capacity - mtctx->roundBuff.pos; + size_t const target = mtctx->targetSectionSize; + buffer_t buffer; + + DEBUGLOG(5, "ZSTDMT_tryGetInputRange"); + assert(mtctx->inBuff.buffer.start == NULL); + assert(mtctx->roundBuff.capacity >= target); + + if (spaceLeft < target) { + /* ZSTD_invalidateRepCodes() doesn't work for extDict variants. + * Simply copy the prefix to the beginning in that case. + */ + BYTE* const start = (BYTE*)mtctx->roundBuff.buffer; + size_t const prefixSize = mtctx->inBuff.prefix.size; + + buffer.start = start; + buffer.capacity = prefixSize; + if (ZSTDMT_isOverlapped(buffer, inUse)) { + DEBUGLOG(5, "Waiting for buffer..."); + return 0; + } + ZSTDMT_waitForLdmComplete(mtctx, buffer); + ZSTD_memmove(start, mtctx->inBuff.prefix.start, prefixSize); + mtctx->inBuff.prefix.start = start; + mtctx->roundBuff.pos = prefixSize; + } + buffer.start = mtctx->roundBuff.buffer + mtctx->roundBuff.pos; + buffer.capacity = target; + + if (ZSTDMT_isOverlapped(buffer, inUse)) { + DEBUGLOG(5, "Waiting for buffer..."); + return 0; + } + assert(!ZSTDMT_isOverlapped(buffer, mtctx->inBuff.prefix)); + + ZSTDMT_waitForLdmComplete(mtctx, buffer); + + DEBUGLOG(5, "Using prefix range [%zx, %zx)", + (size_t)mtctx->inBuff.prefix.start, + (size_t)mtctx->inBuff.prefix.start + mtctx->inBuff.prefix.size); + DEBUGLOG(5, "Using source range [%zx, %zx)", + (size_t)buffer.start, + (size_t)buffer.start + buffer.capacity); + + + mtctx->inBuff.buffer = buffer; + mtctx->inBuff.filled = 0; + assert(mtctx->roundBuff.pos + buffer.capacity <= mtctx->roundBuff.capacity); + return 1; +} + +typedef struct { + size_t toLoad; /* The number of bytes to load from the input. */ + int flush; /* Boolean declaring if we must flush because we found a synchronization point. */ +} syncPoint_t; + +/** + * Searches through the input for a synchronization point. If one is found, we + * will instruct the caller to flush, and return the number of bytes to load. + * Otherwise, we will load as many bytes as possible and instruct the caller + * to continue as normal. + */ +static syncPoint_t +findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input) +{ + BYTE const* const istart = (BYTE const*)input.src + input.pos; + U64 const primePower = mtctx->rsync.primePower; + U64 const hitMask = mtctx->rsync.hitMask; + + syncPoint_t syncPoint; + U64 hash; + BYTE const* prev; + size_t pos; + + syncPoint.toLoad = MIN(input.size - input.pos, mtctx->targetSectionSize - mtctx->inBuff.filled); + syncPoint.flush = 0; + if (!mtctx->params.rsyncable) + /* Rsync is disabled. */ + return syncPoint; + if (mtctx->inBuff.filled + input.size - input.pos < RSYNC_MIN_BLOCK_SIZE) + /* We don't emit synchronization points if it would produce too small blocks. + * We don't have enough input to find a synchronization point, so don't look. + */ + return syncPoint; + if (mtctx->inBuff.filled + syncPoint.toLoad < RSYNC_LENGTH) + /* Not enough to compute the hash. + * We will miss any synchronization points in this RSYNC_LENGTH byte + * window. However, since it depends only in the internal buffers, if the + * state is already synchronized, we will remain synchronized. + * Additionally, the probability that we miss a synchronization point is + * low: RSYNC_LENGTH / targetSectionSize. + */ + return syncPoint; + /* Initialize the loop variables. */ + if (mtctx->inBuff.filled < RSYNC_MIN_BLOCK_SIZE) { + /* We don't need to scan the first RSYNC_MIN_BLOCK_SIZE positions + * because they can't possibly be a sync point. So we can start + * part way through the input buffer. + */ + pos = RSYNC_MIN_BLOCK_SIZE - mtctx->inBuff.filled; + if (pos >= RSYNC_LENGTH) { + prev = istart + pos - RSYNC_LENGTH; + hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH); + } else { + assert(mtctx->inBuff.filled >= RSYNC_LENGTH); + prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH; + hash = ZSTD_rollingHash_compute(prev + pos, (RSYNC_LENGTH - pos)); + hash = ZSTD_rollingHash_append(hash, istart, pos); + } + } else { + /* We have enough bytes buffered to initialize the hash, + * and have processed enough bytes to find a sync point. + * Start scanning at the beginning of the input. + */ + assert(mtctx->inBuff.filled >= RSYNC_MIN_BLOCK_SIZE); + assert(RSYNC_MIN_BLOCK_SIZE >= RSYNC_LENGTH); + pos = 0; + prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH; + hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH); + if ((hash & hitMask) == hitMask) { + /* We're already at a sync point so don't load any more until + * we're able to flush this sync point. + * This likely happened because the job table was full so we + * couldn't add our job. + */ + syncPoint.toLoad = 0; + syncPoint.flush = 1; + return syncPoint; + } + } + /* Starting with the hash of the previous RSYNC_LENGTH bytes, roll + * through the input. If we hit a synchronization point, then cut the + * job off, and tell the compressor to flush the job. Otherwise, load + * all the bytes and continue as normal. + * If we go too long without a synchronization point (targetSectionSize) + * then a block will be emitted anyways, but this is okay, since if we + * are already synchronized we will remain synchronized. + */ + assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash); + for (; pos < syncPoint.toLoad; ++pos) { + BYTE const toRemove = pos < RSYNC_LENGTH ? prev[pos] : istart[pos - RSYNC_LENGTH]; + /* This assert is very expensive, and Debian compiles with asserts enabled. + * So disable it for now. We can get similar coverage by checking it at the + * beginning & end of the loop. + * assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash); + */ + hash = ZSTD_rollingHash_rotate(hash, toRemove, istart[pos], primePower); + assert(mtctx->inBuff.filled + pos >= RSYNC_MIN_BLOCK_SIZE); + if ((hash & hitMask) == hitMask) { + syncPoint.toLoad = pos + 1; + syncPoint.flush = 1; + ++pos; /* for assert */ + break; + } + } + assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash); + return syncPoint; +} + +size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx) +{ + size_t hintInSize = mtctx->targetSectionSize - mtctx->inBuff.filled; + if (hintInSize==0) hintInSize = mtctx->targetSectionSize; + return hintInSize; +} + +/** ZSTDMT_compressStream_generic() : + * internal use only - exposed to be invoked from zstd_compress.c + * assumption : output and input are valid (pos <= size) + * @return : minimum amount of data remaining to flush, 0 if none */ +size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input, + ZSTD_EndDirective endOp) +{ + unsigned forwardInputProgress = 0; + DEBUGLOG(5, "ZSTDMT_compressStream_generic (endOp=%u, srcSize=%u)", + (U32)endOp, (U32)(input->size - input->pos)); + assert(output->pos <= output->size); + assert(input->pos <= input->size); + + if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) { + /* current frame being ended. Only flush/end are allowed */ + return ERROR(stage_wrong); + } + + /* fill input buffer */ + if ( (!mtctx->jobReady) + && (input->size > input->pos) ) { /* support NULL input */ + if (mtctx->inBuff.buffer.start == NULL) { + assert(mtctx->inBuff.filled == 0); /* Can't fill an empty buffer */ + if (!ZSTDMT_tryGetInputRange(mtctx)) { + /* It is only possible for this operation to fail if there are + * still compression jobs ongoing. + */ + DEBUGLOG(5, "ZSTDMT_tryGetInputRange failed"); + assert(mtctx->doneJobID != mtctx->nextJobID); + } else + DEBUGLOG(5, "ZSTDMT_tryGetInputRange completed successfully : mtctx->inBuff.buffer.start = %p", mtctx->inBuff.buffer.start); + } + if (mtctx->inBuff.buffer.start != NULL) { + syncPoint_t const syncPoint = findSynchronizationPoint(mtctx, *input); + if (syncPoint.flush && endOp == ZSTD_e_continue) { + endOp = ZSTD_e_flush; + } + assert(mtctx->inBuff.buffer.capacity >= mtctx->targetSectionSize); + DEBUGLOG(5, "ZSTDMT_compressStream_generic: adding %u bytes on top of %u to buffer of size %u", + (U32)syncPoint.toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize); + ZSTD_memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad); + input->pos += syncPoint.toLoad; + mtctx->inBuff.filled += syncPoint.toLoad; + forwardInputProgress = syncPoint.toLoad>0; + } + } + if ((input->pos < input->size) && (endOp == ZSTD_e_end)) { + /* Can't end yet because the input is not fully consumed. + * We are in one of these cases: + * - mtctx->inBuff is NULL & empty: we couldn't get an input buffer so don't create a new job. + * - We filled the input buffer: flush this job but don't end the frame. + * - We hit a synchronization point: flush this job but don't end the frame. + */ + assert(mtctx->inBuff.filled == 0 || mtctx->inBuff.filled == mtctx->targetSectionSize || mtctx->params.rsyncable); + endOp = ZSTD_e_flush; + } + + if ( (mtctx->jobReady) + || (mtctx->inBuff.filled >= mtctx->targetSectionSize) /* filled enough : let's compress */ + || ((endOp != ZSTD_e_continue) && (mtctx->inBuff.filled > 0)) /* something to flush : let's go */ + || ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */ + size_t const jobSize = mtctx->inBuff.filled; + assert(mtctx->inBuff.filled <= mtctx->targetSectionSize); + FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) , ""); + } + + /* check for potential compressed data ready to be flushed */ + { size_t const remainingToFlush = ZSTDMT_flushProduced(mtctx, output, !forwardInputProgress, endOp); /* block if there was no forward input progress */ + if (input->pos < input->size) return MAX(remainingToFlush, 1); /* input not consumed : do not end flush yet */ + DEBUGLOG(5, "end of ZSTDMT_compressStream_generic: remainingToFlush = %u", (U32)remainingToFlush); + return remainingToFlush; + } +} diff --git a/third_party/zstd/decompress/huf_decompress.c b/third_party/zstd/decompress/huf_decompress.c new file mode 100644 index 00000000000..f85dd0beea0 --- /dev/null +++ b/third_party/zstd/decompress/huf_decompress.c @@ -0,0 +1,1944 @@ +/* ****************************************************************** + * huff0 huffman decoder, + * part of Finite State Entropy library + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * You can contact the author at : + * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. +****************************************************************** */ + +/* ************************************************************** +* Dependencies +****************************************************************/ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */ +#include "../common/compiler.h" +#include "../common/bitstream.h" /* BIT_* */ +#include "../common/fse.h" /* to compress headers */ +#include "../common/huf.h" +#include "../common/error_private.h" +#include "../common/zstd_internal.h" +#include "../common/bits.h" /* ZSTD_highbit32, ZSTD_countTrailingZeros64 */ + +/* ************************************************************** +* Constants +****************************************************************/ + +#define HUF_DECODER_FAST_TABLELOG 11 + +/* ************************************************************** +* Macros +****************************************************************/ + +#ifdef HUF_DISABLE_FAST_DECODE +# define HUF_ENABLE_FAST_DECODE 0 +#else +# define HUF_ENABLE_FAST_DECODE 1 +#endif + +/* These two optional macros force the use one way or another of the two + * Huffman decompression implementations. You can't force in both directions + * at the same time. + */ +#if defined(HUF_FORCE_DECOMPRESS_X1) && \ + defined(HUF_FORCE_DECOMPRESS_X2) +#error "Cannot force the use of the X1 and X2 decoders at the same time!" +#endif + +/* When DYNAMIC_BMI2 is enabled, fast decoders are only called when bmi2 is + * supported at runtime, so we can add the BMI2 target attribute. + * When it is disabled, we will still get BMI2 if it is enabled statically. + */ +#if DYNAMIC_BMI2 +# define HUF_FAST_BMI2_ATTRS BMI2_TARGET_ATTRIBUTE +#else +# define HUF_FAST_BMI2_ATTRS +#endif + +#ifdef __cplusplus +# define HUF_EXTERN_C extern "C" +#else +# define HUF_EXTERN_C +#endif +#define HUF_ASM_DECL HUF_EXTERN_C + +#if DYNAMIC_BMI2 +# define HUF_NEED_BMI2_FUNCTION 1 +#else +# define HUF_NEED_BMI2_FUNCTION 0 +#endif + +/* ************************************************************** +* Error Management +****************************************************************/ +#define HUF_isError ERR_isError + + +/* ************************************************************** +* Byte alignment for workSpace management +****************************************************************/ +#define HUF_ALIGN(x, a) HUF_ALIGN_MASK((x), (a) - 1) +#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) + + +/* ************************************************************** +* BMI2 Variant Wrappers +****************************************************************/ +typedef size_t (*HUF_DecompressUsingDTableFn)(void *dst, size_t dstSize, + const void *cSrc, + size_t cSrcSize, + const HUF_DTable *DTable); + +#if DYNAMIC_BMI2 + +#define HUF_DGEN(fn) \ + \ + static size_t fn##_default( \ + void* dst, size_t dstSize, \ + const void* cSrc, size_t cSrcSize, \ + const HUF_DTable* DTable) \ + { \ + return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \ + } \ + \ + static BMI2_TARGET_ATTRIBUTE size_t fn##_bmi2( \ + void* dst, size_t dstSize, \ + const void* cSrc, size_t cSrcSize, \ + const HUF_DTable* DTable) \ + { \ + return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \ + } \ + \ + static size_t fn(void* dst, size_t dstSize, void const* cSrc, \ + size_t cSrcSize, HUF_DTable const* DTable, int flags) \ + { \ + if (flags & HUF_flags_bmi2) { \ + return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable); \ + } \ + return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable); \ + } + +#else + +#define HUF_DGEN(fn) \ + static size_t fn(void* dst, size_t dstSize, void const* cSrc, \ + size_t cSrcSize, HUF_DTable const* DTable, int flags) \ + { \ + (void)flags; \ + return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \ + } + +#endif + + +/*-***************************/ +/* generic DTableDesc */ +/*-***************************/ +typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc; + +static DTableDesc HUF_getDTableDesc(const HUF_DTable* table) +{ + DTableDesc dtd; + ZSTD_memcpy(&dtd, table, sizeof(dtd)); + return dtd; +} + +static size_t HUF_initFastDStream(BYTE const* ip) { + BYTE const lastByte = ip[7]; + size_t const bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0; + size_t const value = MEM_readLEST(ip) | 1; + assert(bitsConsumed <= 8); + assert(sizeof(size_t) == 8); + return value << bitsConsumed; +} + + +/** + * The input/output arguments to the Huffman fast decoding loop: + * + * ip [in/out] - The input pointers, must be updated to reflect what is consumed. + * op [in/out] - The output pointers, must be updated to reflect what is written. + * bits [in/out] - The bitstream containers, must be updated to reflect the current state. + * dt [in] - The decoding table. + * ilowest [in] - The beginning of the valid range of the input. Decoders may read + * down to this pointer. It may be below iend[0]. + * oend [in] - The end of the output stream. op[3] must not cross oend. + * iend [in] - The end of each input stream. ip[i] may cross iend[i], + * as long as it is above ilowest, but that indicates corruption. + */ +typedef struct { + BYTE const* ip[4]; + BYTE* op[4]; + U64 bits[4]; + void const* dt; + BYTE const* ilowest; + BYTE* oend; + BYTE const* iend[4]; +} HUF_DecompressFastArgs; + +typedef void (*HUF_DecompressFastLoopFn)(HUF_DecompressFastArgs*); + +/** + * Initializes args for the fast decoding loop. + * @returns 1 on success + * 0 if the fallback implementation should be used. + * Or an error code on failure. + */ +static size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* dst, size_t dstSize, void const* src, size_t srcSize, const HUF_DTable* DTable) +{ + void const* dt = DTable + 1; + U32 const dtLog = HUF_getDTableDesc(DTable).tableLog; + + const BYTE* const istart = (const BYTE*)src; + + BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize); + + /* The fast decoding loop assumes 64-bit little-endian. + * This condition is false on x32. + */ + if (!MEM_isLittleEndian() || MEM_32bits()) + return 0; + + /* Avoid nullptr addition */ + if (dstSize == 0) + return 0; + assert(dst != NULL); + + /* strict minimum : jump table + 1 byte per stream */ + if (srcSize < 10) + return ERROR(corruption_detected); + + /* Must have at least 8 bytes per stream because we don't handle initializing smaller bit containers. + * If table log is not correct at this point, fallback to the old decoder. + * On small inputs we don't have enough data to trigger the fast loop, so use the old decoder. + */ + if (dtLog != HUF_DECODER_FAST_TABLELOG) + return 0; + + /* Read the jump table. */ + { + size_t const length1 = MEM_readLE16(istart); + size_t const length2 = MEM_readLE16(istart+2); + size_t const length3 = MEM_readLE16(istart+4); + size_t const length4 = srcSize - (length1 + length2 + length3 + 6); + args->iend[0] = istart + 6; /* jumpTable */ + args->iend[1] = args->iend[0] + length1; + args->iend[2] = args->iend[1] + length2; + args->iend[3] = args->iend[2] + length3; + + /* HUF_initFastDStream() requires this, and this small of an input + * won't benefit from the ASM loop anyways. + */ + if (length1 < 8 || length2 < 8 || length3 < 8 || length4 < 8) + return 0; + if (length4 > srcSize) return ERROR(corruption_detected); /* overflow */ + } + /* ip[] contains the position that is currently loaded into bits[]. */ + args->ip[0] = args->iend[1] - sizeof(U64); + args->ip[1] = args->iend[2] - sizeof(U64); + args->ip[2] = args->iend[3] - sizeof(U64); + args->ip[3] = (BYTE const*)src + srcSize - sizeof(U64); + + /* op[] contains the output pointers. */ + args->op[0] = (BYTE*)dst; + args->op[1] = args->op[0] + (dstSize+3)/4; + args->op[2] = args->op[1] + (dstSize+3)/4; + args->op[3] = args->op[2] + (dstSize+3)/4; + + /* No point to call the ASM loop for tiny outputs. */ + if (args->op[3] >= oend) + return 0; + + /* bits[] is the bit container. + * It is read from the MSB down to the LSB. + * It is shifted left as it is read, and zeros are + * shifted in. After the lowest valid bit a 1 is + * set, so that CountTrailingZeros(bits[]) can be used + * to count how many bits we've consumed. + */ + args->bits[0] = HUF_initFastDStream(args->ip[0]); + args->bits[1] = HUF_initFastDStream(args->ip[1]); + args->bits[2] = HUF_initFastDStream(args->ip[2]); + args->bits[3] = HUF_initFastDStream(args->ip[3]); + + /* The decoders must be sure to never read beyond ilowest. + * This is lower than iend[0], but allowing decoders to read + * down to ilowest can allow an extra iteration or two in the + * fast loop. + */ + args->ilowest = istart; + + args->oend = oend; + args->dt = dt; + + return 1; +} + +static size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressFastArgs const* args, int stream, BYTE* segmentEnd) +{ + /* Validate that we haven't overwritten. */ + if (args->op[stream] > segmentEnd) + return ERROR(corruption_detected); + /* Validate that we haven't read beyond iend[]. + * Note that ip[] may be < iend[] because the MSB is + * the next bit to read, and we may have consumed 100% + * of the stream, so down to iend[i] - 8 is valid. + */ + if (args->ip[stream] < args->iend[stream] - 8) + return ERROR(corruption_detected); + + /* Construct the BIT_DStream_t. */ + assert(sizeof(size_t) == 8); + bit->bitContainer = MEM_readLEST(args->ip[stream]); + bit->bitsConsumed = ZSTD_countTrailingZeros64(args->bits[stream]); + bit->start = (const char*)args->ilowest; + bit->limitPtr = bit->start + sizeof(size_t); + bit->ptr = (const char*)args->ip[stream]; + + return 0; +} + +/* Calls X(N) for each stream 0, 1, 2, 3. */ +#define HUF_4X_FOR_EACH_STREAM(X) \ + do { \ + X(0); \ + X(1); \ + X(2); \ + X(3); \ + } while (0) + +/* Calls X(N, var) for each stream 0, 1, 2, 3. */ +#define HUF_4X_FOR_EACH_STREAM_WITH_VAR(X, var) \ + do { \ + X(0, (var)); \ + X(1, (var)); \ + X(2, (var)); \ + X(3, (var)); \ + } while (0) + + +#ifndef HUF_FORCE_DECOMPRESS_X2 + +/*-***************************/ +/* single-symbol decoding */ +/*-***************************/ +typedef struct { BYTE nbBits; BYTE byte; } HUF_DEltX1; /* single-symbol decoding */ + +/** + * Packs 4 HUF_DEltX1 structs into a U64. This is used to lay down 4 entries at + * a time. + */ +static U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) { + U64 D4; + if (MEM_isLittleEndian()) { + D4 = (U64)((symbol << 8) + nbBits); + } else { + D4 = (U64)(symbol + (nbBits << 8)); + } + assert(D4 < (1U << 16)); + D4 *= 0x0001000100010001ULL; + return D4; +} + +/** + * Increase the tableLog to targetTableLog and rescales the stats. + * If tableLog > targetTableLog this is a no-op. + * @returns New tableLog + */ +static U32 HUF_rescaleStats(BYTE* huffWeight, U32* rankVal, U32 nbSymbols, U32 tableLog, U32 targetTableLog) +{ + if (tableLog > targetTableLog) + return tableLog; + if (tableLog < targetTableLog) { + U32 const scale = targetTableLog - tableLog; + U32 s; + /* Increase the weight for all non-zero probability symbols by scale. */ + for (s = 0; s < nbSymbols; ++s) { + huffWeight[s] += (BYTE)((huffWeight[s] == 0) ? 0 : scale); + } + /* Update rankVal to reflect the new weights. + * All weights except 0 get moved to weight + scale. + * Weights [1, scale] are empty. + */ + for (s = targetTableLog; s > scale; --s) { + rankVal[s] = rankVal[s - scale]; + } + for (s = scale; s > 0; --s) { + rankVal[s] = 0; + } + } + return targetTableLog; +} + +typedef struct { + U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; + U32 rankStart[HUF_TABLELOG_ABSOLUTEMAX + 1]; + U32 statsWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32]; + BYTE symbols[HUF_SYMBOLVALUE_MAX + 1]; + BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; +} HUF_ReadDTableX1_Workspace; + +size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags) +{ + U32 tableLog = 0; + U32 nbSymbols = 0; + size_t iSize; + void* const dtPtr = DTable + 1; + HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr; + HUF_ReadDTableX1_Workspace* wksp = (HUF_ReadDTableX1_Workspace*)workSpace; + + DEBUG_STATIC_ASSERT(HUF_DECOMPRESS_WORKSPACE_SIZE >= sizeof(*wksp)); + if (sizeof(*wksp) > wkspSize) return ERROR(tableLog_tooLarge); + + DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable)); + /* ZSTD_memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ + + iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), flags); + if (HUF_isError(iSize)) return iSize; + + + /* Table header */ + { DTableDesc dtd = HUF_getDTableDesc(DTable); + U32 const maxTableLog = dtd.maxTableLog + 1; + U32 const targetTableLog = MIN(maxTableLog, HUF_DECODER_FAST_TABLELOG); + tableLog = HUF_rescaleStats(wksp->huffWeight, wksp->rankVal, nbSymbols, tableLog, targetTableLog); + if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */ + dtd.tableType = 0; + dtd.tableLog = (BYTE)tableLog; + ZSTD_memcpy(DTable, &dtd, sizeof(dtd)); + } + + /* Compute symbols and rankStart given rankVal: + * + * rankVal already contains the number of values of each weight. + * + * symbols contains the symbols ordered by weight. First are the rankVal[0] + * weight 0 symbols, followed by the rankVal[1] weight 1 symbols, and so on. + * symbols[0] is filled (but unused) to avoid a branch. + * + * rankStart contains the offset where each rank belongs in the DTable. + * rankStart[0] is not filled because there are no entries in the table for + * weight 0. + */ + { int n; + U32 nextRankStart = 0; + int const unroll = 4; + int const nLimit = (int)nbSymbols - unroll + 1; + for (n=0; n<(int)tableLog+1; n++) { + U32 const curr = nextRankStart; + nextRankStart += wksp->rankVal[n]; + wksp->rankStart[n] = curr; + } + for (n=0; n < nLimit; n += unroll) { + int u; + for (u=0; u < unroll; ++u) { + size_t const w = wksp->huffWeight[n+u]; + wksp->symbols[wksp->rankStart[w]++] = (BYTE)(n+u); + } + } + for (; n < (int)nbSymbols; ++n) { + size_t const w = wksp->huffWeight[n]; + wksp->symbols[wksp->rankStart[w]++] = (BYTE)n; + } + } + + /* fill DTable + * We fill all entries of each weight in order. + * That way length is a constant for each iteration of the outer loop. + * We can switch based on the length to a different inner loop which is + * optimized for that particular case. + */ + { U32 w; + int symbol = wksp->rankVal[0]; + int rankStart = 0; + for (w=1; wrankVal[w]; + int const length = (1 << w) >> 1; + int uStart = rankStart; + BYTE const nbBits = (BYTE)(tableLog + 1 - w); + int s; + int u; + switch (length) { + case 1: + for (s=0; ssymbols[symbol + s]; + D.nbBits = nbBits; + dt[uStart] = D; + uStart += 1; + } + break; + case 2: + for (s=0; ssymbols[symbol + s]; + D.nbBits = nbBits; + dt[uStart+0] = D; + dt[uStart+1] = D; + uStart += 2; + } + break; + case 4: + for (s=0; ssymbols[symbol + s], nbBits); + MEM_write64(dt + uStart, D4); + uStart += 4; + } + break; + case 8: + for (s=0; ssymbols[symbol + s], nbBits); + MEM_write64(dt + uStart, D4); + MEM_write64(dt + uStart + 4, D4); + uStart += 8; + } + break; + default: + for (s=0; ssymbols[symbol + s], nbBits); + for (u=0; u < length; u += 16) { + MEM_write64(dt + uStart + u + 0, D4); + MEM_write64(dt + uStart + u + 4, D4); + MEM_write64(dt + uStart + u + 8, D4); + MEM_write64(dt + uStart + u + 12, D4); + } + assert(u == length); + uStart += length; + } + break; + } + symbol += symbolCount; + rankStart += symbolCount * length; + } + } + return iSize; +} + +FORCE_INLINE_TEMPLATE BYTE +HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog) +{ + size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */ + BYTE const c = dt[val].byte; + BIT_skipBits(Dstream, dt[val].nbBits); + return c; +} + +#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \ + do { *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog); } while (0) + +#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr) \ + do { \ + if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \ + HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \ + } while (0) + +#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr) \ + do { \ + if (MEM_64bits()) \ + HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \ + } while (0) + +HINT_INLINE size_t +HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog) +{ + BYTE* const pStart = p; + + /* up to 4 symbols at a time */ + if ((pEnd - p) > 3) { + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) { + HUF_DECODE_SYMBOLX1_2(p, bitDPtr); + HUF_DECODE_SYMBOLX1_1(p, bitDPtr); + HUF_DECODE_SYMBOLX1_2(p, bitDPtr); + HUF_DECODE_SYMBOLX1_0(p, bitDPtr); + } + } else { + BIT_reloadDStream(bitDPtr); + } + + /* [0-3] symbols remaining */ + if (MEM_32bits()) + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd)) + HUF_DECODE_SYMBOLX1_0(p, bitDPtr); + + /* no more data to retrieve from bitstream, no need to reload */ + while (p < pEnd) + HUF_DECODE_SYMBOLX1_0(p, bitDPtr); + + return (size_t)(pEnd-pStart); +} + +FORCE_INLINE_TEMPLATE size_t +HUF_decompress1X1_usingDTable_internal_body( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + BYTE* op = (BYTE*)dst; + BYTE* const oend = ZSTD_maybeNullPtrAdd(op, dstSize); + const void* dtPtr = DTable + 1; + const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr; + BIT_DStream_t bitD; + DTableDesc const dtd = HUF_getDTableDesc(DTable); + U32 const dtLog = dtd.tableLog; + + CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) ); + + HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog); + + if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected); + + return dstSize; +} + +/* HUF_decompress4X1_usingDTable_internal_body(): + * Conditions : + * @dstSize >= 6 + */ +FORCE_INLINE_TEMPLATE size_t +HUF_decompress4X1_usingDTable_internal_body( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + /* Check */ + if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ + if (dstSize < 6) return ERROR(corruption_detected); /* stream 4-split doesn't work */ + + { const BYTE* const istart = (const BYTE*) cSrc; + BYTE* const ostart = (BYTE*) dst; + BYTE* const oend = ostart + dstSize; + BYTE* const olimit = oend - 3; + const void* const dtPtr = DTable + 1; + const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr; + + /* Init */ + BIT_DStream_t bitD1; + BIT_DStream_t bitD2; + BIT_DStream_t bitD3; + BIT_DStream_t bitD4; + size_t const length1 = MEM_readLE16(istart); + size_t const length2 = MEM_readLE16(istart+2); + size_t const length3 = MEM_readLE16(istart+4); + size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6); + const BYTE* const istart1 = istart + 6; /* jumpTable */ + const BYTE* const istart2 = istart1 + length1; + const BYTE* const istart3 = istart2 + length2; + const BYTE* const istart4 = istart3 + length3; + const size_t segmentSize = (dstSize+3) / 4; + BYTE* const opStart2 = ostart + segmentSize; + BYTE* const opStart3 = opStart2 + segmentSize; + BYTE* const opStart4 = opStart3 + segmentSize; + BYTE* op1 = ostart; + BYTE* op2 = opStart2; + BYTE* op3 = opStart3; + BYTE* op4 = opStart4; + DTableDesc const dtd = HUF_getDTableDesc(DTable); + U32 const dtLog = dtd.tableLog; + U32 endSignal = 1; + + if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ + if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */ + assert(dstSize >= 6); /* validated above */ + CHECK_F( BIT_initDStream(&bitD1, istart1, length1) ); + CHECK_F( BIT_initDStream(&bitD2, istart2, length2) ); + CHECK_F( BIT_initDStream(&bitD3, istart3, length3) ); + CHECK_F( BIT_initDStream(&bitD4, istart4, length4) ); + + /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */ + if ((size_t)(oend - op4) >= sizeof(size_t)) { + for ( ; (endSignal) & (op4 < olimit) ; ) { + HUF_DECODE_SYMBOLX1_2(op1, &bitD1); + HUF_DECODE_SYMBOLX1_2(op2, &bitD2); + HUF_DECODE_SYMBOLX1_2(op3, &bitD3); + HUF_DECODE_SYMBOLX1_2(op4, &bitD4); + HUF_DECODE_SYMBOLX1_1(op1, &bitD1); + HUF_DECODE_SYMBOLX1_1(op2, &bitD2); + HUF_DECODE_SYMBOLX1_1(op3, &bitD3); + HUF_DECODE_SYMBOLX1_1(op4, &bitD4); + HUF_DECODE_SYMBOLX1_2(op1, &bitD1); + HUF_DECODE_SYMBOLX1_2(op2, &bitD2); + HUF_DECODE_SYMBOLX1_2(op3, &bitD3); + HUF_DECODE_SYMBOLX1_2(op4, &bitD4); + HUF_DECODE_SYMBOLX1_0(op1, &bitD1); + HUF_DECODE_SYMBOLX1_0(op2, &bitD2); + HUF_DECODE_SYMBOLX1_0(op3, &bitD3); + HUF_DECODE_SYMBOLX1_0(op4, &bitD4); + endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished; + } + } + + /* check corruption */ + /* note : should not be necessary : op# advance in lock step, and we control op4. + * but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */ + if (op1 > opStart2) return ERROR(corruption_detected); + if (op2 > opStart3) return ERROR(corruption_detected); + if (op3 > opStart4) return ERROR(corruption_detected); + /* note : op4 supposed already verified within main loop */ + + /* finish bitStreams one by one */ + HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog); + HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog); + HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog); + HUF_decodeStreamX1(op4, &bitD4, oend, dt, dtLog); + + /* check */ + { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); + if (!endCheck) return ERROR(corruption_detected); } + + /* decoded size */ + return dstSize; + } +} + +#if HUF_NEED_BMI2_FUNCTION +static BMI2_TARGET_ATTRIBUTE +size_t HUF_decompress4X1_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc, + size_t cSrcSize, HUF_DTable const* DTable) { + return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable); +} +#endif + +static +size_t HUF_decompress4X1_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc, + size_t cSrcSize, HUF_DTable const* DTable) { + return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable); +} + +#if ZSTD_ENABLE_ASM_X86_64_BMI2 + +HUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_fast_asm_loop(HUF_DecompressFastArgs* args) ZSTDLIB_HIDDEN; + +#endif + +static HUF_FAST_BMI2_ATTRS +void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args) +{ + U64 bits[4]; + BYTE const* ip[4]; + BYTE* op[4]; + U16 const* const dtable = (U16 const*)args->dt; + BYTE* const oend = args->oend; + BYTE const* const ilowest = args->ilowest; + + /* Copy the arguments to local variables */ + ZSTD_memcpy(&bits, &args->bits, sizeof(bits)); + ZSTD_memcpy((void*)(&ip), &args->ip, sizeof(ip)); + ZSTD_memcpy(&op, &args->op, sizeof(op)); + + assert(MEM_isLittleEndian()); + assert(!MEM_32bits()); + + for (;;) { + BYTE* olimit; + int stream; + + /* Assert loop preconditions */ +#ifndef NDEBUG + for (stream = 0; stream < 4; ++stream) { + assert(op[stream] <= (stream == 3 ? oend : op[stream + 1])); + assert(ip[stream] >= ilowest); + } +#endif + /* Compute olimit */ + { + /* Each iteration produces 5 output symbols per stream */ + size_t const oiters = (size_t)(oend - op[3]) / 5; + /* Each iteration consumes up to 11 bits * 5 = 55 bits < 7 bytes + * per stream. + */ + size_t const iiters = (size_t)(ip[0] - ilowest) / 7; + /* We can safely run iters iterations before running bounds checks */ + size_t const iters = MIN(oiters, iiters); + size_t const symbols = iters * 5; + + /* We can simply check that op[3] < olimit, instead of checking all + * of our bounds, since we can't hit the other bounds until we've run + * iters iterations, which only happens when op[3] == olimit. + */ + olimit = op[3] + symbols; + + /* Exit fast decoding loop once we reach the end. */ + if (op[3] == olimit) + break; + + /* Exit the decoding loop if any input pointer has crossed the + * previous one. This indicates corruption, and a precondition + * to our loop is that ip[i] >= ip[0]. + */ + for (stream = 1; stream < 4; ++stream) { + if (ip[stream] < ip[stream - 1]) + goto _out; + } + } + +#ifndef NDEBUG + for (stream = 1; stream < 4; ++stream) { + assert(ip[stream] >= ip[stream - 1]); + } +#endif + +#define HUF_4X1_DECODE_SYMBOL(_stream, _symbol) \ + do { \ + int const index = (int)(bits[(_stream)] >> 53); \ + int const entry = (int)dtable[index]; \ + bits[(_stream)] <<= (entry & 0x3F); \ + op[(_stream)][(_symbol)] = (BYTE)((entry >> 8) & 0xFF); \ + } while (0) + +#define HUF_4X1_RELOAD_STREAM(_stream) \ + do { \ + int const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \ + int const nbBits = ctz & 7; \ + int const nbBytes = ctz >> 3; \ + op[(_stream)] += 5; \ + ip[(_stream)] -= nbBytes; \ + bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1; \ + bits[(_stream)] <<= nbBits; \ + } while (0) + + /* Manually unroll the loop because compilers don't consistently + * unroll the inner loops, which destroys performance. + */ + do { + /* Decode 5 symbols in each of the 4 streams */ + HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 0); + HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 1); + HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 2); + HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 3); + HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 4); + + /* Reload each of the 4 the bitstreams */ + HUF_4X_FOR_EACH_STREAM(HUF_4X1_RELOAD_STREAM); + } while (op[3] < olimit); + +#undef HUF_4X1_DECODE_SYMBOL +#undef HUF_4X1_RELOAD_STREAM + } + +_out: + + /* Save the final values of each of the state variables back to args. */ + ZSTD_memcpy(&args->bits, &bits, sizeof(bits)); + ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip)); + ZSTD_memcpy(&args->op, &op, sizeof(op)); +} + +/** + * @returns @p dstSize on success (>= 6) + * 0 if the fallback implementation should be used + * An error if an error occurred + */ +static HUF_FAST_BMI2_ATTRS +size_t +HUF_decompress4X1_usingDTable_internal_fast( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable, + HUF_DecompressFastLoopFn loopFn) +{ + void const* dt = DTable + 1; + BYTE const* const ilowest = (BYTE const*)cSrc; + BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize); + HUF_DecompressFastArgs args; + { size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable); + FORWARD_IF_ERROR(ret, "Failed to init fast loop args"); + if (ret == 0) + return 0; + } + + assert(args.ip[0] >= args.ilowest); + loopFn(&args); + + /* Our loop guarantees that ip[] >= ilowest and that we haven't + * overwritten any op[]. + */ + assert(args.ip[0] >= ilowest); + assert(args.ip[0] >= ilowest); + assert(args.ip[1] >= ilowest); + assert(args.ip[2] >= ilowest); + assert(args.ip[3] >= ilowest); + assert(args.op[3] <= oend); + + assert(ilowest == args.ilowest); + assert(ilowest + 6 == args.iend[0]); + (void)ilowest; + + /* finish bit streams one by one. */ + { size_t const segmentSize = (dstSize+3) / 4; + BYTE* segmentEnd = (BYTE*)dst; + int i; + for (i = 0; i < 4; ++i) { + BIT_DStream_t bit; + if (segmentSize <= (size_t)(oend - segmentEnd)) + segmentEnd += segmentSize; + else + segmentEnd = oend; + FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), "corruption"); + /* Decompress and validate that we've produced exactly the expected length. */ + args.op[i] += HUF_decodeStreamX1(args.op[i], &bit, segmentEnd, (HUF_DEltX1 const*)dt, HUF_DECODER_FAST_TABLELOG); + if (args.op[i] != segmentEnd) return ERROR(corruption_detected); + } + } + + /* decoded size */ + assert(dstSize != 0); + return dstSize; +} + +HUF_DGEN(HUF_decompress1X1_usingDTable_internal) + +static size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc, + size_t cSrcSize, HUF_DTable const* DTable, int flags) +{ + HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X1_usingDTable_internal_default; + HUF_DecompressFastLoopFn loopFn = HUF_decompress4X1_usingDTable_internal_fast_c_loop; + +#if DYNAMIC_BMI2 + if (flags & HUF_flags_bmi2) { + fallbackFn = HUF_decompress4X1_usingDTable_internal_bmi2; +# if ZSTD_ENABLE_ASM_X86_64_BMI2 + if (!(flags & HUF_flags_disableAsm)) { + loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop; + } +# endif + } else { + return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable); + } +#endif + +#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__) + if (!(flags & HUF_flags_disableAsm)) { + loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop; + } +#endif + + if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) { + size_t const ret = HUF_decompress4X1_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn); + if (ret != 0) + return ret; + } + return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable); +} + +static size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize, int flags) +{ + const BYTE* ip = (const BYTE*) cSrc; + + size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags); + if (HUF_isError(hSize)) return hSize; + if (hSize >= cSrcSize) return ERROR(srcSize_wrong); + ip += hSize; cSrcSize -= hSize; + + return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags); +} + +#endif /* HUF_FORCE_DECOMPRESS_X2 */ + + +#ifndef HUF_FORCE_DECOMPRESS_X1 + +/* *************************/ +/* double-symbols decoding */ +/* *************************/ + +typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2; /* double-symbols decoding */ +typedef struct { BYTE symbol; } sortedSymbol_t; +typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1]; +typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX]; + +/** + * Constructs a HUF_DEltX2 in a U32. + */ +static U32 HUF_buildDEltX2U32(U32 symbol, U32 nbBits, U32 baseSeq, int level) +{ + U32 seq; + DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, sequence) == 0); + DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, nbBits) == 2); + DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, length) == 3); + DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U32)); + if (MEM_isLittleEndian()) { + seq = level == 1 ? symbol : (baseSeq + (symbol << 8)); + return seq + (nbBits << 16) + ((U32)level << 24); + } else { + seq = level == 1 ? (symbol << 8) : ((baseSeq << 8) + symbol); + return (seq << 16) + (nbBits << 8) + (U32)level; + } +} + +/** + * Constructs a HUF_DEltX2. + */ +static HUF_DEltX2 HUF_buildDEltX2(U32 symbol, U32 nbBits, U32 baseSeq, int level) +{ + HUF_DEltX2 DElt; + U32 const val = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level); + DEBUG_STATIC_ASSERT(sizeof(DElt) == sizeof(val)); + ZSTD_memcpy(&DElt, &val, sizeof(val)); + return DElt; +} + +/** + * Constructs 2 HUF_DEltX2s and packs them into a U64. + */ +static U64 HUF_buildDEltX2U64(U32 symbol, U32 nbBits, U16 baseSeq, int level) +{ + U32 DElt = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level); + return (U64)DElt + ((U64)DElt << 32); +} + +/** + * Fills the DTable rank with all the symbols from [begin, end) that are each + * nbBits long. + * + * @param DTableRank The start of the rank in the DTable. + * @param begin The first symbol to fill (inclusive). + * @param end The last symbol to fill (exclusive). + * @param nbBits Each symbol is nbBits long. + * @param tableLog The table log. + * @param baseSeq If level == 1 { 0 } else { the first level symbol } + * @param level The level in the table. Must be 1 or 2. + */ +static void HUF_fillDTableX2ForWeight( + HUF_DEltX2* DTableRank, + sortedSymbol_t const* begin, sortedSymbol_t const* end, + U32 nbBits, U32 tableLog, + U16 baseSeq, int const level) +{ + U32 const length = 1U << ((tableLog - nbBits) & 0x1F /* quiet static-analyzer */); + const sortedSymbol_t* ptr; + assert(level >= 1 && level <= 2); + switch (length) { + case 1: + for (ptr = begin; ptr != end; ++ptr) { + HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level); + *DTableRank++ = DElt; + } + break; + case 2: + for (ptr = begin; ptr != end; ++ptr) { + HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level); + DTableRank[0] = DElt; + DTableRank[1] = DElt; + DTableRank += 2; + } + break; + case 4: + for (ptr = begin; ptr != end; ++ptr) { + U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level); + ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2)); + DTableRank += 4; + } + break; + case 8: + for (ptr = begin; ptr != end; ++ptr) { + U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level); + ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2)); + DTableRank += 8; + } + break; + default: + for (ptr = begin; ptr != end; ++ptr) { + U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level); + HUF_DEltX2* const DTableRankEnd = DTableRank + length; + for (; DTableRank != DTableRankEnd; DTableRank += 8) { + ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2)); + } + } + break; + } +} + +/* HUF_fillDTableX2Level2() : + * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */ +static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 targetLog, const U32 consumedBits, + const U32* rankVal, const int minWeight, const int maxWeight1, + const sortedSymbol_t* sortedSymbols, U32 const* rankStart, + U32 nbBitsBaseline, U16 baseSeq) +{ + /* Fill skipped values (all positions up to rankVal[minWeight]). + * These are positions only get a single symbol because the combined weight + * is too large. + */ + if (minWeight>1) { + U32 const length = 1U << ((targetLog - consumedBits) & 0x1F /* quiet static-analyzer */); + U64 const DEltX2 = HUF_buildDEltX2U64(baseSeq, consumedBits, /* baseSeq */ 0, /* level */ 1); + int const skipSize = rankVal[minWeight]; + assert(length > 1); + assert((U32)skipSize < length); + switch (length) { + case 2: + assert(skipSize == 1); + ZSTD_memcpy(DTable, &DEltX2, sizeof(DEltX2)); + break; + case 4: + assert(skipSize <= 4); + ZSTD_memcpy(DTable + 0, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTable + 2, &DEltX2, sizeof(DEltX2)); + break; + default: + { + int i; + for (i = 0; i < skipSize; i += 8) { + ZSTD_memcpy(DTable + i + 0, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTable + i + 2, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTable + i + 4, &DEltX2, sizeof(DEltX2)); + ZSTD_memcpy(DTable + i + 6, &DEltX2, sizeof(DEltX2)); + } + } + } + } + + /* Fill each of the second level symbols by weight. */ + { + int w; + for (w = minWeight; w < maxWeight1; ++w) { + int const begin = rankStart[w]; + int const end = rankStart[w+1]; + U32 const nbBits = nbBitsBaseline - w; + U32 const totalBits = nbBits + consumedBits; + HUF_fillDTableX2ForWeight( + DTable + rankVal[w], + sortedSymbols + begin, sortedSymbols + end, + totalBits, targetLog, + baseSeq, /* level */ 2); + } + } +} + +static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog, + const sortedSymbol_t* sortedList, + const U32* rankStart, rankValCol_t* rankValOrigin, const U32 maxWeight, + const U32 nbBitsBaseline) +{ + U32* const rankVal = rankValOrigin[0]; + const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */ + const U32 minBits = nbBitsBaseline - maxWeight; + int w; + int const wEnd = (int)maxWeight + 1; + + /* Fill DTable in order of weight. */ + for (w = 1; w < wEnd; ++w) { + int const begin = (int)rankStart[w]; + int const end = (int)rankStart[w+1]; + U32 const nbBits = nbBitsBaseline - w; + + if (targetLog-nbBits >= minBits) { + /* Enough room for a second symbol. */ + int start = rankVal[w]; + U32 const length = 1U << ((targetLog - nbBits) & 0x1F /* quiet static-analyzer */); + int minWeight = nbBits + scaleLog; + int s; + if (minWeight < 1) minWeight = 1; + /* Fill the DTable for every symbol of weight w. + * These symbols get at least 1 second symbol. + */ + for (s = begin; s != end; ++s) { + HUF_fillDTableX2Level2( + DTable + start, targetLog, nbBits, + rankValOrigin[nbBits], minWeight, wEnd, + sortedList, rankStart, + nbBitsBaseline, sortedList[s].symbol); + start += length; + } + } else { + /* Only a single symbol. */ + HUF_fillDTableX2ForWeight( + DTable + rankVal[w], + sortedList + begin, sortedList + end, + nbBits, targetLog, + /* baseSeq */ 0, /* level */ 1); + } + } +} + +typedef struct { + rankValCol_t rankVal[HUF_TABLELOG_MAX]; + U32 rankStats[HUF_TABLELOG_MAX + 1]; + U32 rankStart0[HUF_TABLELOG_MAX + 3]; + sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1]; + BYTE weightList[HUF_SYMBOLVALUE_MAX + 1]; + U32 calleeWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32]; +} HUF_ReadDTableX2_Workspace; + +size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize, int flags) +{ + U32 tableLog, maxW, nbSymbols; + DTableDesc dtd = HUF_getDTableDesc(DTable); + U32 maxTableLog = dtd.maxTableLog; + size_t iSize; + void* dtPtr = DTable+1; /* force compiler to avoid strict-aliasing */ + HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr; + U32 *rankStart; + + HUF_ReadDTableX2_Workspace* const wksp = (HUF_ReadDTableX2_Workspace*)workSpace; + + if (sizeof(*wksp) > wkspSize) return ERROR(GENERIC); + + rankStart = wksp->rankStart0 + 1; + ZSTD_memset(wksp->rankStats, 0, sizeof(wksp->rankStats)); + ZSTD_memset(wksp->rankStart0, 0, sizeof(wksp->rankStart0)); + + DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */ + if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); + /* ZSTD_memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ + + iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), flags); + if (HUF_isError(iSize)) return iSize; + + /* check result */ + if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */ + if (tableLog <= HUF_DECODER_FAST_TABLELOG && maxTableLog > HUF_DECODER_FAST_TABLELOG) maxTableLog = HUF_DECODER_FAST_TABLELOG; + + /* find maxWeight */ + for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */ + + /* Get start index of each weight */ + { U32 w, nextRankStart = 0; + for (w=1; wrankStats[w]; + rankStart[w] = curr; + } + rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/ + rankStart[maxW+1] = nextRankStart; + } + + /* sort symbols by weight */ + { U32 s; + for (s=0; sweightList[s]; + U32 const r = rankStart[w]++; + wksp->sortedSymbol[r].symbol = (BYTE)s; + } + rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */ + } + + /* Build rankVal */ + { U32* const rankVal0 = wksp->rankVal[0]; + { int const rescale = (maxTableLog-tableLog) - 1; /* tableLog <= maxTableLog */ + U32 nextRankVal = 0; + U32 w; + for (w=1; wrankStats[w] << (w+rescale); + rankVal0[w] = curr; + } } + { U32 const minBits = tableLog+1 - maxW; + U32 consumed; + for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) { + U32* const rankValPtr = wksp->rankVal[consumed]; + U32 w; + for (w = 1; w < maxW+1; w++) { + rankValPtr[w] = rankVal0[w] >> consumed; + } } } } + + HUF_fillDTableX2(dt, maxTableLog, + wksp->sortedSymbol, + wksp->rankStart0, wksp->rankVal, maxW, + tableLog+1); + + dtd.tableLog = (BYTE)maxTableLog; + dtd.tableType = 1; + ZSTD_memcpy(DTable, &dtd, sizeof(dtd)); + return iSize; +} + + +FORCE_INLINE_TEMPLATE U32 +HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog) +{ + size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ + ZSTD_memcpy(op, &dt[val].sequence, 2); + BIT_skipBits(DStream, dt[val].nbBits); + return dt[val].length; +} + +FORCE_INLINE_TEMPLATE U32 +HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog) +{ + size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ + ZSTD_memcpy(op, &dt[val].sequence, 1); + if (dt[val].length==1) { + BIT_skipBits(DStream, dt[val].nbBits); + } else { + if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) { + BIT_skipBits(DStream, dt[val].nbBits); + if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8)) + /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ + DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8); + } + } + return 1; +} + +#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \ + do { ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); } while (0) + +#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \ + do { \ + if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \ + ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \ + } while (0) + +#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \ + do { \ + if (MEM_64bits()) \ + ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \ + } while (0) + +HINT_INLINE size_t +HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, + const HUF_DEltX2* const dt, const U32 dtLog) +{ + BYTE* const pStart = p; + + /* up to 8 symbols at a time */ + if ((size_t)(pEnd - p) >= sizeof(bitDPtr->bitContainer)) { + if (dtLog <= 11 && MEM_64bits()) { + /* up to 10 symbols at a time */ + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-9)) { + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + } + } else { + /* up to 8 symbols at a time */ + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) { + HUF_DECODE_SYMBOLX2_2(p, bitDPtr); + HUF_DECODE_SYMBOLX2_1(p, bitDPtr); + HUF_DECODE_SYMBOLX2_2(p, bitDPtr); + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + } + } + } else { + BIT_reloadDStream(bitDPtr); + } + + /* closer to end : up to 2 symbols at a time */ + if ((size_t)(pEnd - p) >= 2) { + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2)) + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + + while (p <= pEnd-2) + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); /* no need to reload : reached the end of DStream */ + } + + if (p < pEnd) + p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog); + + return p-pStart; +} + +FORCE_INLINE_TEMPLATE size_t +HUF_decompress1X2_usingDTable_internal_body( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + BIT_DStream_t bitD; + + /* Init */ + CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) ); + + /* decode */ + { BYTE* const ostart = (BYTE*) dst; + BYTE* const oend = ZSTD_maybeNullPtrAdd(ostart, dstSize); + const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */ + const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr; + DTableDesc const dtd = HUF_getDTableDesc(DTable); + HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog); + } + + /* check */ + if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected); + + /* decoded size */ + return dstSize; +} + +/* HUF_decompress4X2_usingDTable_internal_body(): + * Conditions: + * @dstSize >= 6 + */ +FORCE_INLINE_TEMPLATE size_t +HUF_decompress4X2_usingDTable_internal_body( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable) +{ + if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ + if (dstSize < 6) return ERROR(corruption_detected); /* stream 4-split doesn't work */ + + { const BYTE* const istart = (const BYTE*) cSrc; + BYTE* const ostart = (BYTE*) dst; + BYTE* const oend = ostart + dstSize; + BYTE* const olimit = oend - (sizeof(size_t)-1); + const void* const dtPtr = DTable+1; + const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr; + + /* Init */ + BIT_DStream_t bitD1; + BIT_DStream_t bitD2; + BIT_DStream_t bitD3; + BIT_DStream_t bitD4; + size_t const length1 = MEM_readLE16(istart); + size_t const length2 = MEM_readLE16(istart+2); + size_t const length3 = MEM_readLE16(istart+4); + size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6); + const BYTE* const istart1 = istart + 6; /* jumpTable */ + const BYTE* const istart2 = istart1 + length1; + const BYTE* const istart3 = istart2 + length2; + const BYTE* const istart4 = istart3 + length3; + size_t const segmentSize = (dstSize+3) / 4; + BYTE* const opStart2 = ostart + segmentSize; + BYTE* const opStart3 = opStart2 + segmentSize; + BYTE* const opStart4 = opStart3 + segmentSize; + BYTE* op1 = ostart; + BYTE* op2 = opStart2; + BYTE* op3 = opStart3; + BYTE* op4 = opStart4; + U32 endSignal = 1; + DTableDesc const dtd = HUF_getDTableDesc(DTable); + U32 const dtLog = dtd.tableLog; + + if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ + if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */ + assert(dstSize >= 6 /* validated above */); + CHECK_F( BIT_initDStream(&bitD1, istart1, length1) ); + CHECK_F( BIT_initDStream(&bitD2, istart2, length2) ); + CHECK_F( BIT_initDStream(&bitD3, istart3, length3) ); + CHECK_F( BIT_initDStream(&bitD4, istart4, length4) ); + + /* 16-32 symbols per loop (4-8 symbols per stream) */ + if ((size_t)(oend - op4) >= sizeof(size_t)) { + for ( ; (endSignal) & (op4 < olimit); ) { +#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) + HUF_DECODE_SYMBOLX2_2(op1, &bitD1); + HUF_DECODE_SYMBOLX2_1(op1, &bitD1); + HUF_DECODE_SYMBOLX2_2(op1, &bitD1); + HUF_DECODE_SYMBOLX2_0(op1, &bitD1); + HUF_DECODE_SYMBOLX2_2(op2, &bitD2); + HUF_DECODE_SYMBOLX2_1(op2, &bitD2); + HUF_DECODE_SYMBOLX2_2(op2, &bitD2); + HUF_DECODE_SYMBOLX2_0(op2, &bitD2); + endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished; + HUF_DECODE_SYMBOLX2_2(op3, &bitD3); + HUF_DECODE_SYMBOLX2_1(op3, &bitD3); + HUF_DECODE_SYMBOLX2_2(op3, &bitD3); + HUF_DECODE_SYMBOLX2_0(op3, &bitD3); + HUF_DECODE_SYMBOLX2_2(op4, &bitD4); + HUF_DECODE_SYMBOLX2_1(op4, &bitD4); + HUF_DECODE_SYMBOLX2_2(op4, &bitD4); + HUF_DECODE_SYMBOLX2_0(op4, &bitD4); + endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished; + endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished; +#else + HUF_DECODE_SYMBOLX2_2(op1, &bitD1); + HUF_DECODE_SYMBOLX2_2(op2, &bitD2); + HUF_DECODE_SYMBOLX2_2(op3, &bitD3); + HUF_DECODE_SYMBOLX2_2(op4, &bitD4); + HUF_DECODE_SYMBOLX2_1(op1, &bitD1); + HUF_DECODE_SYMBOLX2_1(op2, &bitD2); + HUF_DECODE_SYMBOLX2_1(op3, &bitD3); + HUF_DECODE_SYMBOLX2_1(op4, &bitD4); + HUF_DECODE_SYMBOLX2_2(op1, &bitD1); + HUF_DECODE_SYMBOLX2_2(op2, &bitD2); + HUF_DECODE_SYMBOLX2_2(op3, &bitD3); + HUF_DECODE_SYMBOLX2_2(op4, &bitD4); + HUF_DECODE_SYMBOLX2_0(op1, &bitD1); + HUF_DECODE_SYMBOLX2_0(op2, &bitD2); + HUF_DECODE_SYMBOLX2_0(op3, &bitD3); + HUF_DECODE_SYMBOLX2_0(op4, &bitD4); + endSignal = (U32)LIKELY((U32) + (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished) + & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished) + & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished) + & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished)); +#endif + } + } + + /* check corruption */ + if (op1 > opStart2) return ERROR(corruption_detected); + if (op2 > opStart3) return ERROR(corruption_detected); + if (op3 > opStart4) return ERROR(corruption_detected); + /* note : op4 already verified within main loop */ + + /* finish bitStreams one by one */ + HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog); + HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog); + HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog); + HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog); + + /* check */ + { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); + if (!endCheck) return ERROR(corruption_detected); } + + /* decoded size */ + return dstSize; + } +} + +#if HUF_NEED_BMI2_FUNCTION +static BMI2_TARGET_ATTRIBUTE +size_t HUF_decompress4X2_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc, + size_t cSrcSize, HUF_DTable const* DTable) { + return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable); +} +#endif + +static +size_t HUF_decompress4X2_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc, + size_t cSrcSize, HUF_DTable const* DTable) { + return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable); +} + +#if ZSTD_ENABLE_ASM_X86_64_BMI2 + +HUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_fast_asm_loop(HUF_DecompressFastArgs* args) ZSTDLIB_HIDDEN; + +#endif + +static HUF_FAST_BMI2_ATTRS +void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args) +{ + U64 bits[4]; + BYTE const* ip[4]; + BYTE* op[4]; + BYTE* oend[4]; + HUF_DEltX2 const* const dtable = (HUF_DEltX2 const*)args->dt; + BYTE const* const ilowest = args->ilowest; + + /* Copy the arguments to local registers. */ + ZSTD_memcpy(&bits, &args->bits, sizeof(bits)); + ZSTD_memcpy((void*)(&ip), &args->ip, sizeof(ip)); + ZSTD_memcpy(&op, &args->op, sizeof(op)); + + oend[0] = op[1]; + oend[1] = op[2]; + oend[2] = op[3]; + oend[3] = args->oend; + + assert(MEM_isLittleEndian()); + assert(!MEM_32bits()); + + for (;;) { + BYTE* olimit; + int stream; + + /* Assert loop preconditions */ +#ifndef NDEBUG + for (stream = 0; stream < 4; ++stream) { + assert(op[stream] <= oend[stream]); + assert(ip[stream] >= ilowest); + } +#endif + /* Compute olimit */ + { + /* Each loop does 5 table lookups for each of the 4 streams. + * Each table lookup consumes up to 11 bits of input, and produces + * up to 2 bytes of output. + */ + /* We can consume up to 7 bytes of input per iteration per stream. + * We also know that each input pointer is >= ip[0]. So we can run + * iters loops before running out of input. + */ + size_t iters = (size_t)(ip[0] - ilowest) / 7; + /* Each iteration can produce up to 10 bytes of output per stream. + * Each output stream my advance at different rates. So take the + * minimum number of safe iterations among all the output streams. + */ + for (stream = 0; stream < 4; ++stream) { + size_t const oiters = (size_t)(oend[stream] - op[stream]) / 10; + iters = MIN(iters, oiters); + } + + /* Each iteration produces at least 5 output symbols. So until + * op[3] crosses olimit, we know we haven't executed iters + * iterations yet. This saves us maintaining an iters counter, + * at the expense of computing the remaining # of iterations + * more frequently. + */ + olimit = op[3] + (iters * 5); + + /* Exit the fast decoding loop once we reach the end. */ + if (op[3] == olimit) + break; + + /* Exit the decoding loop if any input pointer has crossed the + * previous one. This indicates corruption, and a precondition + * to our loop is that ip[i] >= ip[0]. + */ + for (stream = 1; stream < 4; ++stream) { + if (ip[stream] < ip[stream - 1]) + goto _out; + } + } + +#ifndef NDEBUG + for (stream = 1; stream < 4; ++stream) { + assert(ip[stream] >= ip[stream - 1]); + } +#endif + +#define HUF_4X2_DECODE_SYMBOL(_stream, _decode3) \ + do { \ + if ((_decode3) || (_stream) != 3) { \ + int const index = (int)(bits[(_stream)] >> 53); \ + HUF_DEltX2 const entry = dtable[index]; \ + MEM_write16(op[(_stream)], entry.sequence); \ + bits[(_stream)] <<= (entry.nbBits) & 0x3F; \ + op[(_stream)] += (entry.length); \ + } \ + } while (0) + +#define HUF_4X2_RELOAD_STREAM(_stream) \ + do { \ + HUF_4X2_DECODE_SYMBOL(3, 1); \ + { \ + int const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \ + int const nbBits = ctz & 7; \ + int const nbBytes = ctz >> 3; \ + ip[(_stream)] -= nbBytes; \ + bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1; \ + bits[(_stream)] <<= nbBits; \ + } \ + } while (0) + + /* Manually unroll the loop because compilers don't consistently + * unroll the inner loops, which destroys performance. + */ + do { + /* Decode 5 symbols from each of the first 3 streams. + * The final stream will be decoded during the reload phase + * to reduce register pressure. + */ + HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0); + HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0); + HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0); + HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0); + HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0); + + /* Decode one symbol from the final stream */ + HUF_4X2_DECODE_SYMBOL(3, 1); + + /* Decode 4 symbols from the final stream & reload bitstreams. + * The final stream is reloaded last, meaning that all 5 symbols + * are decoded from the final stream before it is reloaded. + */ + HUF_4X_FOR_EACH_STREAM(HUF_4X2_RELOAD_STREAM); + } while (op[3] < olimit); + } + +#undef HUF_4X2_DECODE_SYMBOL +#undef HUF_4X2_RELOAD_STREAM + +_out: + + /* Save the final values of each of the state variables back to args. */ + ZSTD_memcpy(&args->bits, &bits, sizeof(bits)); + ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip)); + ZSTD_memcpy(&args->op, &op, sizeof(op)); +} + + +static HUF_FAST_BMI2_ATTRS size_t +HUF_decompress4X2_usingDTable_internal_fast( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const HUF_DTable* DTable, + HUF_DecompressFastLoopFn loopFn) { + void const* dt = DTable + 1; + const BYTE* const ilowest = (const BYTE*)cSrc; + BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize); + HUF_DecompressFastArgs args; + { + size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable); + FORWARD_IF_ERROR(ret, "Failed to init asm args"); + if (ret == 0) + return 0; + } + + assert(args.ip[0] >= args.ilowest); + loopFn(&args); + + /* note : op4 already verified within main loop */ + assert(args.ip[0] >= ilowest); + assert(args.ip[1] >= ilowest); + assert(args.ip[2] >= ilowest); + assert(args.ip[3] >= ilowest); + assert(args.op[3] <= oend); + + assert(ilowest == args.ilowest); + assert(ilowest + 6 == args.iend[0]); + (void)ilowest; + + /* finish bitStreams one by one */ + { + size_t const segmentSize = (dstSize+3) / 4; + BYTE* segmentEnd = (BYTE*)dst; + int i; + for (i = 0; i < 4; ++i) { + BIT_DStream_t bit; + if (segmentSize <= (size_t)(oend - segmentEnd)) + segmentEnd += segmentSize; + else + segmentEnd = oend; + FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), "corruption"); + args.op[i] += HUF_decodeStreamX2(args.op[i], &bit, segmentEnd, (HUF_DEltX2 const*)dt, HUF_DECODER_FAST_TABLELOG); + if (args.op[i] != segmentEnd) + return ERROR(corruption_detected); + } + } + + /* decoded size */ + return dstSize; +} + +static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc, + size_t cSrcSize, HUF_DTable const* DTable, int flags) +{ + HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X2_usingDTable_internal_default; + HUF_DecompressFastLoopFn loopFn = HUF_decompress4X2_usingDTable_internal_fast_c_loop; + +#if DYNAMIC_BMI2 + if (flags & HUF_flags_bmi2) { + fallbackFn = HUF_decompress4X2_usingDTable_internal_bmi2; +# if ZSTD_ENABLE_ASM_X86_64_BMI2 + if (!(flags & HUF_flags_disableAsm)) { + loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop; + } +# endif + } else { + return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable); + } +#endif + +#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__) + if (!(flags & HUF_flags_disableAsm)) { + loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop; + } +#endif + + if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) { + size_t const ret = HUF_decompress4X2_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn); + if (ret != 0) + return ret; + } + return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable); +} + +HUF_DGEN(HUF_decompress1X2_usingDTable_internal) + +size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize, int flags) +{ + const BYTE* ip = (const BYTE*) cSrc; + + size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize, + workSpace, wkspSize, flags); + if (HUF_isError(hSize)) return hSize; + if (hSize >= cSrcSize) return ERROR(srcSize_wrong); + ip += hSize; cSrcSize -= hSize; + + return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, flags); +} + +static size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize, int flags) +{ + const BYTE* ip = (const BYTE*) cSrc; + + size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize, + workSpace, wkspSize, flags); + if (HUF_isError(hSize)) return hSize; + if (hSize >= cSrcSize) return ERROR(srcSize_wrong); + ip += hSize; cSrcSize -= hSize; + + return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags); +} + +#endif /* HUF_FORCE_DECOMPRESS_X1 */ + + +/* ***********************************/ +/* Universal decompression selectors */ +/* ***********************************/ + + +#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2) +typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t; +static const algo_time_t algoTime[16 /* Quantization */][2 /* single, double */] = +{ + /* single, double, quad */ + {{0,0}, {1,1}}, /* Q==0 : impossible */ + {{0,0}, {1,1}}, /* Q==1 : impossible */ + {{ 150,216}, { 381,119}}, /* Q == 2 : 12-18% */ + {{ 170,205}, { 514,112}}, /* Q == 3 : 18-25% */ + {{ 177,199}, { 539,110}}, /* Q == 4 : 25-32% */ + {{ 197,194}, { 644,107}}, /* Q == 5 : 32-38% */ + {{ 221,192}, { 735,107}}, /* Q == 6 : 38-44% */ + {{ 256,189}, { 881,106}}, /* Q == 7 : 44-50% */ + {{ 359,188}, {1167,109}}, /* Q == 8 : 50-56% */ + {{ 582,187}, {1570,114}}, /* Q == 9 : 56-62% */ + {{ 688,187}, {1712,122}}, /* Q ==10 : 62-69% */ + {{ 825,186}, {1965,136}}, /* Q ==11 : 69-75% */ + {{ 976,185}, {2131,150}}, /* Q ==12 : 75-81% */ + {{1180,186}, {2070,175}}, /* Q ==13 : 81-87% */ + {{1377,185}, {1731,202}}, /* Q ==14 : 87-93% */ + {{1412,185}, {1695,202}}, /* Q ==15 : 93-99% */ +}; +#endif + +/** HUF_selectDecoder() : + * Tells which decoder is likely to decode faster, + * based on a set of pre-computed metrics. + * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 . + * Assumption : 0 < dstSize <= 128 KB */ +U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize) +{ + assert(dstSize > 0); + assert(dstSize <= 128*1024); +#if defined(HUF_FORCE_DECOMPRESS_X1) + (void)dstSize; + (void)cSrcSize; + return 0; +#elif defined(HUF_FORCE_DECOMPRESS_X2) + (void)dstSize; + (void)cSrcSize; + return 1; +#else + /* decoder timing evaluation */ + { U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize); /* Q < 16 */ + U32 const D256 = (U32)(dstSize >> 8); + U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256); + U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256); + DTime1 += DTime1 >> 5; /* small advantage to algorithm using less memory, to reduce cache eviction */ + return DTime1 < DTime0; + } +#endif +} + +size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + void* workSpace, size_t wkspSize, int flags) +{ + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ + if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ + if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); +#if defined(HUF_FORCE_DECOMPRESS_X1) + (void)algoNb; + assert(algoNb == 0); + return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc, + cSrcSize, workSpace, wkspSize, flags); +#elif defined(HUF_FORCE_DECOMPRESS_X2) + (void)algoNb; + assert(algoNb == 1); + return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc, + cSrcSize, workSpace, wkspSize, flags); +#else + return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc, + cSrcSize, workSpace, wkspSize, flags): + HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc, + cSrcSize, workSpace, wkspSize, flags); +#endif + } +} + + +size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags) +{ + DTableDesc const dtd = HUF_getDTableDesc(DTable); +#if defined(HUF_FORCE_DECOMPRESS_X1) + (void)dtd; + assert(dtd.tableType == 0); + return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags); +#elif defined(HUF_FORCE_DECOMPRESS_X2) + (void)dtd; + assert(dtd.tableType == 1); + return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags); +#else + return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) : + HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags); +#endif +} + +#ifndef HUF_FORCE_DECOMPRESS_X2 +size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags) +{ + const BYTE* ip = (const BYTE*) cSrc; + + size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags); + if (HUF_isError(hSize)) return hSize; + if (hSize >= cSrcSize) return ERROR(srcSize_wrong); + ip += hSize; cSrcSize -= hSize; + + return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags); +} +#endif + +size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags) +{ + DTableDesc const dtd = HUF_getDTableDesc(DTable); +#if defined(HUF_FORCE_DECOMPRESS_X1) + (void)dtd; + assert(dtd.tableType == 0); + return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags); +#elif defined(HUF_FORCE_DECOMPRESS_X2) + (void)dtd; + assert(dtd.tableType == 1); + return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags); +#else + return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) : + HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags); +#endif +} + +size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags) +{ + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize == 0) return ERROR(corruption_detected); + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); +#if defined(HUF_FORCE_DECOMPRESS_X1) + (void)algoNb; + assert(algoNb == 0); + return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags); +#elif defined(HUF_FORCE_DECOMPRESS_X2) + (void)algoNb; + assert(algoNb == 1); + return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags); +#else + return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags) : + HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags); +#endif + } +} diff --git a/third_party/zstd/decompress/huf_decompress.cpp b/third_party/zstd/decompress/huf_decompress.cpp deleted file mode 100644 index 3c9a8cdff76..00000000000 --- a/third_party/zstd/decompress/huf_decompress.cpp +++ /dev/null @@ -1,1251 +0,0 @@ -/* ****************************************************************** - * huff0 huffman decoder, - * part of Finite State Entropy library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. - * - * You can contact the author at : - * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. -****************************************************************** */ - -/* ************************************************************** -* Dependencies -****************************************************************/ -#include /* memcpy, memset */ -#include "zstd/common/compiler.h" -#include "zstd/common/bitstream.h" /* BIT_* */ -#include "zstd/common/fse.h" /* to compress headers */ -#include "zstd/common/huf.h" -#include "zstd/common/huf_static.h" -#include "zstd/common/error_private.h" - -namespace duckdb_zstd { -/* ************************************************************** -* Macros -****************************************************************/ - -/* These two optional macros force the use one way or another of the two - * Huffman decompression implementations. You can't force in both directions - * at the same time. - */ -#if defined(HUF_FORCE_DECOMPRESS_X1) && \ - defined(HUF_FORCE_DECOMPRESS_X2) -#error "Cannot force the use of the X1 and X2 decoders at the same time!" -#endif - - -/* ************************************************************** -* Error Management -****************************************************************/ -// #define HUF_isError ERR_isError - - -/* ************************************************************** -* Byte alignment for workSpace management -****************************************************************/ -#define HUF_ALIGN(x, a) HUF_ALIGN_MASK((x), (a) - 1) -#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) - - -/* ************************************************************** -* BMI2 Variant Wrappers -****************************************************************/ -#if DYNAMIC_BMI2 - -#define HUF_DGEN(fn) \ - \ - static size_t fn##_default( \ - void* dst, size_t dstSize, \ - const void* cSrc, size_t cSrcSize, \ - const HUF_DTable* DTable) \ - { \ - return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \ - } \ - \ - static TARGET_ATTRIBUTE("bmi2") size_t fn##_bmi2( \ - void* dst, size_t dstSize, \ - const void* cSrc, size_t cSrcSize, \ - const HUF_DTable* DTable) \ - { \ - return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \ - } \ - \ - static size_t fn(void* dst, size_t dstSize, void const* cSrc, \ - size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \ - { \ - if (bmi2) { \ - return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable); \ - } \ - return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable); \ - } - -#else - -#define HUF_DGEN(fn) \ - static size_t fn(void* dst, size_t dstSize, void const* cSrc, \ - size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \ - { \ - (void)bmi2; \ - return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \ - } - -#endif - - -/*-***************************/ -/* generic DTableDesc */ -/*-***************************/ -typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc; - -static DTableDesc HUF_getDTableDesc(const HUF_DTable* table) -{ - DTableDesc dtd; - memcpy(&dtd, table, sizeof(dtd)); - return dtd; -} - - -#ifndef HUF_FORCE_DECOMPRESS_X2 - -/*-***************************/ -/* single-symbol decoding */ -/*-***************************/ -typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1; /* single-symbol decoding */ - -size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize) -{ - U32 tableLog = 0; - U32 nbSymbols = 0; - size_t iSize; - void* const dtPtr = DTable + 1; - HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr; - - U32* rankVal; - BYTE* huffWeight; - size_t spaceUsed32 = 0; - - rankVal = (U32 *)workSpace + spaceUsed32; - spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1; - huffWeight = (BYTE *)((U32 *)workSpace + spaceUsed32); - spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2; - - if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge); - - DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable)); - /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ - - iSize = HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); - if (HUF_isError(iSize)) return iSize; - - /* Table header */ - { DTableDesc dtd = HUF_getDTableDesc(DTable); - if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */ - dtd.tableType = 0; - dtd.tableLog = (BYTE)tableLog; - memcpy(DTable, &dtd, sizeof(dtd)); - } - - /* Calculate starting value for each rank */ - { U32 n, nextRankStart = 0; - for (n=1; n> 1; - size_t const uStart = rankVal[w]; - size_t const uEnd = uStart + length; - size_t u; - HUF_DEltX1 D; - D.byte = (BYTE)n; - D.nbBits = (BYTE)(tableLog + 1 - w); - rankVal[w] = (U32)uEnd; - if (length < 4) { - /* Use length in the loop bound so the compiler knows it is short. */ - for (u = 0; u < length; ++u) - dt[uStart + u] = D; - } else { - /* Unroll the loop 4 times, we know it is a power of 2. */ - for (u = uStart; u < uEnd; u += 4) { - dt[u + 0] = D; - dt[u + 1] = D; - dt[u + 2] = D; - dt[u + 3] = D; - } } } } - return iSize; -} - -size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_readDTableX1_wksp(DTable, src, srcSize, - workSpace, sizeof(workSpace)); -} - -FORCE_INLINE_TEMPLATE BYTE -HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog) -{ - size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */ - BYTE const c = dt[val].byte; - BIT_skipBits(Dstream, dt[val].nbBits); - return c; -} - -#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \ - *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog) - -#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr) \ - if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \ - HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) - -#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr) \ - if (MEM_64bits()) \ - HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) - -HINT_INLINE size_t -HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog) -{ - BYTE* const pStart = p; - - /* up to 4 symbols at a time */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) { - HUF_DECODE_SYMBOLX1_2(p, bitDPtr); - HUF_DECODE_SYMBOLX1_1(p, bitDPtr); - HUF_DECODE_SYMBOLX1_2(p, bitDPtr); - HUF_DECODE_SYMBOLX1_0(p, bitDPtr); - } - - /* [0-3] symbols remaining */ - if (MEM_32bits()) - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd)) - HUF_DECODE_SYMBOLX1_0(p, bitDPtr); - - /* no more data to retrieve from bitstream, no need to reload */ - while (p < pEnd) - HUF_DECODE_SYMBOLX1_0(p, bitDPtr); - - return pEnd-pStart; -} - -FORCE_INLINE_TEMPLATE size_t -HUF_decompress1X1_usingDTable_internal_body( - void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - const HUF_DTable* DTable) -{ - BYTE* op = (BYTE*)dst; - BYTE* const oend = op + dstSize; - const void* dtPtr = DTable + 1; - const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr; - BIT_DStream_t bitD; - DTableDesc const dtd = HUF_getDTableDesc(DTable); - U32 const dtLog = dtd.tableLog; - - CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) ); - - HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog); - - if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected); - - return dstSize; -} - -FORCE_INLINE_TEMPLATE size_t -HUF_decompress4X1_usingDTable_internal_body( - void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - const HUF_DTable* DTable) -{ - /* Check */ - if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ - - { const BYTE* const istart = (const BYTE*) cSrc; - BYTE* const ostart = (BYTE*) dst; - BYTE* const oend = ostart + dstSize; - BYTE* const olimit = oend - 3; - const void* const dtPtr = DTable + 1; - const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr; - - /* Init */ - BIT_DStream_t bitD1; - BIT_DStream_t bitD2; - BIT_DStream_t bitD3; - BIT_DStream_t bitD4; - size_t const length1 = MEM_readLE16(istart); - size_t const length2 = MEM_readLE16(istart+2); - size_t const length3 = MEM_readLE16(istart+4); - size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6); - const BYTE* const istart1 = istart + 6; /* jumpTable */ - const BYTE* const istart2 = istart1 + length1; - const BYTE* const istart3 = istart2 + length2; - const BYTE* const istart4 = istart3 + length3; - const size_t segmentSize = (dstSize+3) / 4; - BYTE* const opStart2 = ostart + segmentSize; - BYTE* const opStart3 = opStart2 + segmentSize; - BYTE* const opStart4 = opStart3 + segmentSize; - BYTE* op1 = ostart; - BYTE* op2 = opStart2; - BYTE* op3 = opStart3; - BYTE* op4 = opStart4; - DTableDesc const dtd = HUF_getDTableDesc(DTable); - U32 const dtLog = dtd.tableLog; - U32 endSignal = 1; - - if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ - CHECK_F( BIT_initDStream(&bitD1, istart1, length1) ); - CHECK_F( BIT_initDStream(&bitD2, istart2, length2) ); - CHECK_F( BIT_initDStream(&bitD3, istart3, length3) ); - CHECK_F( BIT_initDStream(&bitD4, istart4, length4) ); - - /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */ - for ( ; (endSignal) & (op4 < olimit) ; ) { - HUF_DECODE_SYMBOLX1_2(op1, &bitD1); - HUF_DECODE_SYMBOLX1_2(op2, &bitD2); - HUF_DECODE_SYMBOLX1_2(op3, &bitD3); - HUF_DECODE_SYMBOLX1_2(op4, &bitD4); - HUF_DECODE_SYMBOLX1_1(op1, &bitD1); - HUF_DECODE_SYMBOLX1_1(op2, &bitD2); - HUF_DECODE_SYMBOLX1_1(op3, &bitD3); - HUF_DECODE_SYMBOLX1_1(op4, &bitD4); - HUF_DECODE_SYMBOLX1_2(op1, &bitD1); - HUF_DECODE_SYMBOLX1_2(op2, &bitD2); - HUF_DECODE_SYMBOLX1_2(op3, &bitD3); - HUF_DECODE_SYMBOLX1_2(op4, &bitD4); - HUF_DECODE_SYMBOLX1_0(op1, &bitD1); - HUF_DECODE_SYMBOLX1_0(op2, &bitD2); - HUF_DECODE_SYMBOLX1_0(op3, &bitD3); - HUF_DECODE_SYMBOLX1_0(op4, &bitD4); - endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished; - endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished; - endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished; - endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished; - } - - /* check corruption */ - /* note : should not be necessary : op# advance in lock step, and we control op4. - * but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */ - if (op1 > opStart2) return ERROR(corruption_detected); - if (op2 > opStart3) return ERROR(corruption_detected); - if (op3 > opStart4) return ERROR(corruption_detected); - /* note : op4 supposed already verified within main loop */ - - /* finish bitStreams one by one */ - HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog); - HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog); - HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog); - HUF_decodeStreamX1(op4, &bitD4, oend, dt, dtLog); - - /* check */ - { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); - if (!endCheck) return ERROR(corruption_detected); } - - /* decoded size */ - return dstSize; - } -} - - -typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize, - const void *cSrc, - size_t cSrcSize, - const HUF_DTable *DTable); - -HUF_DGEN(HUF_decompress1X1_usingDTable_internal) -HUF_DGEN(HUF_decompress4X1_usingDTable_internal) - - - -size_t HUF_decompress1X1_usingDTable( - void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - const HUF_DTable* DTable) -{ - DTableDesc dtd = HUF_getDTableDesc(DTable); - if (dtd.tableType != 0) return ERROR(GENERIC); - return HUF_decompress1X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); -} - -size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - void* workSpace, size_t wkspSize) -{ - const BYTE* ip = (const BYTE*) cSrc; - - size_t const hSize = HUF_readDTableX1_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize); - if (HUF_isError(hSize)) return hSize; - if (hSize >= cSrcSize) return ERROR(srcSize_wrong); - ip += hSize; cSrcSize -= hSize; - - return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0); -} - - -size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - -size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); - return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize); -} - -size_t HUF_decompress4X1_usingDTable( - void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - const HUF_DTable* DTable) -{ - DTableDesc dtd = HUF_getDTableDesc(DTable); - if (dtd.tableType != 0) return ERROR(GENERIC); - return HUF_decompress4X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); -} - -static size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - void* workSpace, size_t wkspSize, int bmi2) -{ - const BYTE* ip = (const BYTE*) cSrc; - - size_t const hSize = HUF_readDTableX1_wksp (dctx, cSrc, cSrcSize, - workSpace, wkspSize); - if (HUF_isError(hSize)) return hSize; - if (hSize >= cSrcSize) return ERROR(srcSize_wrong); - ip += hSize; cSrcSize -= hSize; - - return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2); -} - -size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - void* workSpace, size_t wkspSize) -{ - return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, 0); -} - - -size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} -size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); - return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - -#endif /* HUF_FORCE_DECOMPRESS_X2 */ - - -#ifndef HUF_FORCE_DECOMPRESS_X1 - -/* *************************/ -/* double-symbols decoding */ -/* *************************/ - -typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2; /* double-symbols decoding */ -typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t; -typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1]; -typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX]; - - -/* HUF_fillDTableX2Level2() : - * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */ -static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed, - const U32* rankValOrigin, const int minWeight, - const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, - U32 nbBitsBaseline, U16 baseSeq) -{ - HUF_DEltX2 DElt; - U32 rankVal[HUF_TABLELOG_MAX + 1]; - - /* get pre-calculated rankVal */ - memcpy(rankVal, rankValOrigin, sizeof(rankVal)); - - /* fill skipped values */ - if (minWeight>1) { - U32 i, skipSize = rankVal[minWeight]; - MEM_writeLE16(&(DElt.sequence), baseSeq); - DElt.nbBits = (BYTE)(consumed); - DElt.length = 1; - for (i = 0; i < skipSize; i++) - DTable[i] = DElt; - } - - /* fill DTable */ - { U32 s; for (s=0; s= 1 */ - - rankVal[weight] += length; - } } -} - - -static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog, - const sortedSymbol_t* sortedList, const U32 sortedListSize, - const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight, - const U32 nbBitsBaseline) -{ - U32 rankVal[HUF_TABLELOG_MAX + 1]; - const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */ - const U32 minBits = nbBitsBaseline - maxWeight; - U32 s; - - memcpy(rankVal, rankValOrigin, sizeof(rankVal)); - - /* fill DTable */ - for (s=0; s= minBits) { /* enough room for a second symbol */ - U32 sortedRank; - int minWeight = nbBits + scaleLog; - if (minWeight < 1) minWeight = 1; - sortedRank = rankStart[minWeight]; - HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits, - rankValOrigin[nbBits], minWeight, - sortedList+sortedRank, sortedListSize-sortedRank, - nbBitsBaseline, symbol); - } else { - HUF_DEltX2 DElt; - MEM_writeLE16(&(DElt.sequence), symbol); - DElt.nbBits = (BYTE)(nbBits); - DElt.length = 1; - { U32 const end = start + length; - U32 u; - for (u = start; u < end; u++) DTable[u] = DElt; - } } - rankVal[weight] += length; - } -} - -size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, - const void* src, size_t srcSize, - void* workSpace, size_t wkspSize) -{ - U32 tableLog, maxW, sizeOfSort, nbSymbols; - DTableDesc dtd = HUF_getDTableDesc(DTable); - U32 const maxTableLog = dtd.maxTableLog; - size_t iSize; - void* dtPtr = DTable+1; /* force compiler to avoid strict-aliasing */ - HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr; - U32 *rankStart; - - rankValCol_t* rankVal; - U32* rankStats; - U32* rankStart0; - sortedSymbol_t* sortedSymbol; - BYTE* weightList; - size_t spaceUsed32 = 0; - - rankVal = (rankValCol_t *)((U32 *)workSpace + spaceUsed32); - spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2; - rankStats = (U32 *)workSpace + spaceUsed32; - spaceUsed32 += HUF_TABLELOG_MAX + 1; - rankStart0 = (U32 *)workSpace + spaceUsed32; - spaceUsed32 += HUF_TABLELOG_MAX + 2; - sortedSymbol = (sortedSymbol_t *)workSpace + (spaceUsed32 * sizeof(U32)) / sizeof(sortedSymbol_t); - spaceUsed32 += HUF_ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2; - weightList = (BYTE *)((U32 *)workSpace + spaceUsed32); - spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2; - - if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge); - - rankStart = rankStart0 + 1; - memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1)); - - DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */ - if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); - /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ - - iSize = HUF_readStats(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); - if (HUF_isError(iSize)) return iSize; - - /* check result */ - if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */ - - /* find maxWeight */ - for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */ - - /* Get start index of each weight */ - { U32 w, nextRankStart = 0; - for (w=1; w> consumed; - } } } } - - HUF_fillDTableX2(dt, maxTableLog, - sortedSymbol, sizeOfSort, - rankStart0, rankVal, maxW, - tableLog+1); - - dtd.tableLog = (BYTE)maxTableLog; - dtd.tableType = 1; - memcpy(DTable, &dtd, sizeof(dtd)); - return iSize; -} - -size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_readDTableX2_wksp(DTable, src, srcSize, - workSpace, sizeof(workSpace)); -} - - -FORCE_INLINE_TEMPLATE U32 -HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog) -{ - size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - memcpy(op, dt+val, 2); - BIT_skipBits(DStream, dt[val].nbBits); - return dt[val].length; -} - -FORCE_INLINE_TEMPLATE U32 -HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog) -{ - size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - memcpy(op, dt+val, 1); - if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits); - else { - if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) { - BIT_skipBits(DStream, dt[val].nbBits); - if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8)) - /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ - DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8); - } } - return 1; -} - -#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \ - ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog) - -#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \ - if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \ - ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog) - -#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \ - if (MEM_64bits()) \ - ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog) - -HINT_INLINE size_t -HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, - const HUF_DEltX2* const dt, const U32 dtLog) -{ - BYTE* const pStart = p; - - /* up to 8 symbols at a time */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) { - HUF_DECODE_SYMBOLX2_2(p, bitDPtr); - HUF_DECODE_SYMBOLX2_1(p, bitDPtr); - HUF_DECODE_SYMBOLX2_2(p, bitDPtr); - HUF_DECODE_SYMBOLX2_0(p, bitDPtr); - } - - /* closer to end : up to 2 symbols at a time */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2)) - HUF_DECODE_SYMBOLX2_0(p, bitDPtr); - - while (p <= pEnd-2) - HUF_DECODE_SYMBOLX2_0(p, bitDPtr); /* no need to reload : reached the end of DStream */ - - if (p < pEnd) - p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog); - - return p-pStart; -} - -FORCE_INLINE_TEMPLATE size_t -HUF_decompress1X2_usingDTable_internal_body( - void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - const HUF_DTable* DTable) -{ - BIT_DStream_t bitD; - - /* Init */ - CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) ); - - /* decode */ - { BYTE* const ostart = (BYTE*) dst; - BYTE* const oend = ostart + dstSize; - const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */ - const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr; - DTableDesc const dtd = HUF_getDTableDesc(DTable); - HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog); - } - - /* check */ - if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected); - - /* decoded size */ - return dstSize; -} - -FORCE_INLINE_TEMPLATE size_t -HUF_decompress4X2_usingDTable_internal_body( - void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - const HUF_DTable* DTable) -{ - if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ - - { const BYTE* const istart = (const BYTE*) cSrc; - BYTE* const ostart = (BYTE*) dst; - BYTE* const oend = ostart + dstSize; - BYTE* const olimit = oend - (sizeof(size_t)-1); - const void* const dtPtr = DTable+1; - const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr; - - /* Init */ - BIT_DStream_t bitD1; - BIT_DStream_t bitD2; - BIT_DStream_t bitD3; - BIT_DStream_t bitD4; - size_t const length1 = MEM_readLE16(istart); - size_t const length2 = MEM_readLE16(istart+2); - size_t const length3 = MEM_readLE16(istart+4); - size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6); - const BYTE* const istart1 = istart + 6; /* jumpTable */ - const BYTE* const istart2 = istart1 + length1; - const BYTE* const istart3 = istart2 + length2; - const BYTE* const istart4 = istart3 + length3; - size_t const segmentSize = (dstSize+3) / 4; - BYTE* const opStart2 = ostart + segmentSize; - BYTE* const opStart3 = opStart2 + segmentSize; - BYTE* const opStart4 = opStart3 + segmentSize; - BYTE* op1 = ostart; - BYTE* op2 = opStart2; - BYTE* op3 = opStart3; - BYTE* op4 = opStart4; - U32 endSignal = 1; - DTableDesc const dtd = HUF_getDTableDesc(DTable); - U32 const dtLog = dtd.tableLog; - - if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ - CHECK_F( BIT_initDStream(&bitD1, istart1, length1) ); - CHECK_F( BIT_initDStream(&bitD2, istart2, length2) ); - CHECK_F( BIT_initDStream(&bitD3, istart3, length3) ); - CHECK_F( BIT_initDStream(&bitD4, istart4, length4) ); - - /* 16-32 symbols per loop (4-8 symbols per stream) */ - for ( ; (endSignal) & (op4 < olimit); ) { -#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) - HUF_DECODE_SYMBOLX2_2(op1, &bitD1); - HUF_DECODE_SYMBOLX2_1(op1, &bitD1); - HUF_DECODE_SYMBOLX2_2(op1, &bitD1); - HUF_DECODE_SYMBOLX2_0(op1, &bitD1); - HUF_DECODE_SYMBOLX2_2(op2, &bitD2); - HUF_DECODE_SYMBOLX2_1(op2, &bitD2); - HUF_DECODE_SYMBOLX2_2(op2, &bitD2); - HUF_DECODE_SYMBOLX2_0(op2, &bitD2); - endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished; - endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished; - HUF_DECODE_SYMBOLX2_2(op3, &bitD3); - HUF_DECODE_SYMBOLX2_1(op3, &bitD3); - HUF_DECODE_SYMBOLX2_2(op3, &bitD3); - HUF_DECODE_SYMBOLX2_0(op3, &bitD3); - HUF_DECODE_SYMBOLX2_2(op4, &bitD4); - HUF_DECODE_SYMBOLX2_1(op4, &bitD4); - HUF_DECODE_SYMBOLX2_2(op4, &bitD4); - HUF_DECODE_SYMBOLX2_0(op4, &bitD4); - endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished; - endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished; -#else - HUF_DECODE_SYMBOLX2_2(op1, &bitD1); - HUF_DECODE_SYMBOLX2_2(op2, &bitD2); - HUF_DECODE_SYMBOLX2_2(op3, &bitD3); - HUF_DECODE_SYMBOLX2_2(op4, &bitD4); - HUF_DECODE_SYMBOLX2_1(op1, &bitD1); - HUF_DECODE_SYMBOLX2_1(op2, &bitD2); - HUF_DECODE_SYMBOLX2_1(op3, &bitD3); - HUF_DECODE_SYMBOLX2_1(op4, &bitD4); - HUF_DECODE_SYMBOLX2_2(op1, &bitD1); - HUF_DECODE_SYMBOLX2_2(op2, &bitD2); - HUF_DECODE_SYMBOLX2_2(op3, &bitD3); - HUF_DECODE_SYMBOLX2_2(op4, &bitD4); - HUF_DECODE_SYMBOLX2_0(op1, &bitD1); - HUF_DECODE_SYMBOLX2_0(op2, &bitD2); - HUF_DECODE_SYMBOLX2_0(op3, &bitD3); - HUF_DECODE_SYMBOLX2_0(op4, &bitD4); - endSignal = (U32)LIKELY( - (U32)(BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished) - & (U32)(BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished) - & (U32)(BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished) - & (U32)(BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished)); -#endif - } - - /* check corruption */ - if (op1 > opStart2) return ERROR(corruption_detected); - if (op2 > opStart3) return ERROR(corruption_detected); - if (op3 > opStart4) return ERROR(corruption_detected); - /* note : op4 already verified within main loop */ - - /* finish bitStreams one by one */ - HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog); - HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog); - HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog); - HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog); - - /* check */ - { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); - if (!endCheck) return ERROR(corruption_detected); } - - /* decoded size */ - return dstSize; - } -} - -HUF_DGEN(HUF_decompress1X2_usingDTable_internal) -HUF_DGEN(HUF_decompress4X2_usingDTable_internal) - -size_t HUF_decompress1X2_usingDTable( - void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - const HUF_DTable* DTable) -{ - DTableDesc dtd = HUF_getDTableDesc(DTable); - if (dtd.tableType != 1) return ERROR(GENERIC); - return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); -} - -size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - void* workSpace, size_t wkspSize) -{ - const BYTE* ip = (const BYTE*) cSrc; - - size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize, - workSpace, wkspSize); - if (HUF_isError(hSize)) return hSize; - if (hSize >= cSrcSize) return ERROR(srcSize_wrong); - ip += hSize; cSrcSize -= hSize; - - return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0); -} - - -size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - -size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); - return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - -size_t HUF_decompress4X2_usingDTable( - void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - const HUF_DTable* DTable) -{ - DTableDesc dtd = HUF_getDTableDesc(DTable); - if (dtd.tableType != 1) return ERROR(GENERIC); - return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); -} - -static size_t HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - void* workSpace, size_t wkspSize, int bmi2) -{ - const BYTE* ip = (const BYTE*) cSrc; - - size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize, - workSpace, wkspSize); - if (HUF_isError(hSize)) return hSize; - if (hSize >= cSrcSize) return ERROR(srcSize_wrong); - ip += hSize; cSrcSize -= hSize; - - return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2); -} - -size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - void* workSpace, size_t wkspSize) -{ - return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, /* bmi2 */ 0); -} - - -size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - -size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); - return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - -#endif /* HUF_FORCE_DECOMPRESS_X1 */ - - -/* ***********************************/ -/* Universal decompression selectors */ -/* ***********************************/ - -size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, - const void* cSrc, size_t cSrcSize, - const HUF_DTable* DTable) -{ - DTableDesc const dtd = HUF_getDTableDesc(DTable); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)dtd; - assert(dtd.tableType == 0); - return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)dtd; - assert(dtd.tableType == 1); - return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); -#else - return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) : - HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); -#endif -} - -size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, - const void* cSrc, size_t cSrcSize, - const HUF_DTable* DTable) -{ - DTableDesc const dtd = HUF_getDTableDesc(DTable); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)dtd; - assert(dtd.tableType == 0); - return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)dtd; - assert(dtd.tableType == 1); - return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); -#else - return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) : - HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0); -#endif -} - - -#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2) -typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t; -static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] = -{ - /* single, double, quad */ - {{0,0}, {1,1}, {2,2}}, /* Q==0 : impossible */ - {{0,0}, {1,1}, {2,2}}, /* Q==1 : impossible */ - {{ 38,130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */ - {{ 448,128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */ - {{ 556,128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */ - {{ 714,128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */ - {{ 883,128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */ - {{ 897,128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */ - {{ 926,128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */ - {{ 947,128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */ - {{1107,128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */ - {{1177,128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */ - {{1242,128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */ - {{1349,128}, {2644,106}, {5260,106}}, /* Q ==13 : 81-87% */ - {{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */ - {{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */ -}; -#endif - -/** HUF_selectDecoder() : - * Tells which decoder is likely to decode faster, - * based on a set of pre-computed metrics. - * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 . - * Assumption : 0 < dstSize <= 128 KB */ -U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize) -{ - assert(dstSize > 0); - assert(dstSize <= 128*1024); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)dstSize; - (void)cSrcSize; - return 0; -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)dstSize; - (void)cSrcSize; - return 1; -#else - /* decoder timing evaluation */ - { U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize); /* Q < 16 */ - U32 const D256 = (U32)(dstSize >> 8); - U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256); - U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256); - DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, to reduce cache eviction */ - return DTime1 < DTime0; - } -#endif -} - - -typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); - -size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ -#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2) - static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 }; -#endif - - /* validation checks */ - if (dstSize == 0) return ERROR(dstSize_tooSmall); - if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ - if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ - - { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)algoNb; - assert(algoNb == 0); - return HUF_decompress4X1(dst, dstSize, cSrc, cSrcSize); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)algoNb; - assert(algoNb == 1); - return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize); -#else - return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); -#endif - } -} - -size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - /* validation checks */ - if (dstSize == 0) return ERROR(dstSize_tooSmall); - if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ - if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ - - { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)algoNb; - assert(algoNb == 0); - return HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)algoNb; - assert(algoNb == 1); - return HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); -#else - return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) : - HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ; -#endif - } -} - -size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - - -size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, - size_t dstSize, const void* cSrc, - size_t cSrcSize, void* workSpace, - size_t wkspSize) -{ - /* validation checks */ - if (dstSize == 0) return ERROR(dstSize_tooSmall); - if (cSrcSize == 0) return ERROR(corruption_detected); - - { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)algoNb; - assert(algoNb == 0); - return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)algoNb; - assert(algoNb == 1); - return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize); -#else - return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, - cSrcSize, workSpace, wkspSize): - HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize); -#endif - } -} - -size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize, - void* workSpace, size_t wkspSize) -{ - /* validation checks */ - if (dstSize == 0) return ERROR(dstSize_tooSmall); - if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ - if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ - - { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)algoNb; - assert(algoNb == 0); - return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc, - cSrcSize, workSpace, wkspSize); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)algoNb; - assert(algoNb == 1); - return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc, - cSrcSize, workSpace, wkspSize); -#else - return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc, - cSrcSize, workSpace, wkspSize): - HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc, - cSrcSize, workSpace, wkspSize); -#endif - } -} - -size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - - -size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2) -{ - DTableDesc const dtd = HUF_getDTableDesc(DTable); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)dtd; - assert(dtd.tableType == 0); - return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)dtd; - assert(dtd.tableType == 1); - return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2); -#else - return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) : - HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2); -#endif -} - -#ifndef HUF_FORCE_DECOMPRESS_X2 -size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2) -{ - const BYTE* ip = (const BYTE*) cSrc; - - size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize); - if (HUF_isError(hSize)) return hSize; - if (hSize >= cSrcSize) return ERROR(srcSize_wrong); - ip += hSize; cSrcSize -= hSize; - - return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2); -} -#endif - -size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2) -{ - DTableDesc const dtd = HUF_getDTableDesc(DTable); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)dtd; - assert(dtd.tableType == 0); - return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)dtd; - assert(dtd.tableType == 1); - return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2); -#else - return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) : - HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2); -#endif -} - -size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2) -{ - /* validation checks */ - if (dstSize == 0) return ERROR(dstSize_tooSmall); - if (cSrcSize == 0) return ERROR(corruption_detected); - - { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)algoNb; - assert(algoNb == 0); - return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)algoNb; - assert(algoNb == 1); - return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2); -#else - return algoNb ? HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2) : - HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2); -#endif - } -} - -} diff --git a/third_party/zstd/decompress/huf_decompress_amd64.S b/third_party/zstd/decompress/huf_decompress_amd64.S new file mode 100644 index 00000000000..78da291ee3c --- /dev/null +++ b/third_party/zstd/decompress/huf_decompress_amd64.S @@ -0,0 +1,595 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#include "../common/portability_macros.h" + +#if defined(__ELF__) && defined(__GNUC__) +/* Stack marking + * ref: https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart + */ +.section .note.GNU-stack,"",%progbits + +#if defined(__aarch64__) +/* Mark that this assembly supports BTI & PAC, because it is empty for aarch64. + * See: https://github.com/facebook/zstd/issues/3841 + * See: https://gcc.godbolt.org/z/sqr5T4ffK + * See: https://lore.kernel.org/linux-arm-kernel/20200429211641.9279-8-broonie@kernel.org/ + * See: https://reviews.llvm.org/D62609 + */ +.pushsection .note.gnu.property, "a" +.p2align 3 +.long 4 /* size of the name - "GNU\0" */ +.long 0x10 /* size of descriptor */ +.long 0x5 /* NT_GNU_PROPERTY_TYPE_0 */ +.asciz "GNU" +.long 0xc0000000 /* pr_type - GNU_PROPERTY_AARCH64_FEATURE_1_AND */ +.long 4 /* pr_datasz - 4 bytes */ +.long 3 /* pr_data - GNU_PROPERTY_AARCH64_FEATURE_1_BTI | GNU_PROPERTY_AARCH64_FEATURE_1_PAC */ +.p2align 3 /* pr_padding - bring everything to 8 byte alignment */ +.popsection +#endif + +#endif + +#if ZSTD_ENABLE_ASM_X86_64_BMI2 + +/* Calling convention: + * + * %rdi contains the first argument: HUF_DecompressAsmArgs*. + * %rbp isn't maintained (no frame pointer). + * %rsp contains the stack pointer that grows down. + * No red-zone is assumed, only addresses >= %rsp are used. + * All register contents are preserved. + * + * TODO: Support Windows calling convention. + */ + +ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X1_usingDTable_internal_fast_asm_loop) +ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X2_usingDTable_internal_fast_asm_loop) +ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X2_usingDTable_internal_fast_asm_loop) +ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_fast_asm_loop) +.global HUF_decompress4X1_usingDTable_internal_fast_asm_loop +.global HUF_decompress4X2_usingDTable_internal_fast_asm_loop +.global _HUF_decompress4X1_usingDTable_internal_fast_asm_loop +.global _HUF_decompress4X2_usingDTable_internal_fast_asm_loop +.text + +/* Sets up register mappings for clarity. + * op[], bits[], dtable & ip[0] each get their own register. + * ip[1,2,3] & olimit alias var[]. + * %rax is a scratch register. + */ + +#define op0 rsi +#define op1 rbx +#define op2 rcx +#define op3 rdi + +#define ip0 r8 +#define ip1 r9 +#define ip2 r10 +#define ip3 r11 + +#define bits0 rbp +#define bits1 rdx +#define bits2 r12 +#define bits3 r13 +#define dtable r14 +#define olimit r15 + +/* var[] aliases ip[1,2,3] & olimit + * ip[1,2,3] are saved every iteration. + * olimit is only used in compute_olimit. + */ +#define var0 r15 +#define var1 r9 +#define var2 r10 +#define var3 r11 + +/* 32-bit var registers */ +#define vard0 r15d +#define vard1 r9d +#define vard2 r10d +#define vard3 r11d + +/* Calls X(N) for each stream 0, 1, 2, 3. */ +#define FOR_EACH_STREAM(X) \ + X(0); \ + X(1); \ + X(2); \ + X(3) + +/* Calls X(N, idx) for each stream 0, 1, 2, 3. */ +#define FOR_EACH_STREAM_WITH_INDEX(X, idx) \ + X(0, idx); \ + X(1, idx); \ + X(2, idx); \ + X(3, idx) + +/* Define both _HUF_* & HUF_* symbols because MacOS + * C symbols are prefixed with '_' & Linux symbols aren't. + */ +_HUF_decompress4X1_usingDTable_internal_fast_asm_loop: +HUF_decompress4X1_usingDTable_internal_fast_asm_loop: + ZSTD_CET_ENDBRANCH + /* Save all registers - even if they are callee saved for simplicity. */ + push %rax + push %rbx + push %rcx + push %rdx + push %rbp + push %rsi + push %rdi + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 + + /* Read HUF_DecompressAsmArgs* args from %rax */ + movq %rdi, %rax + movq 0(%rax), %ip0 + movq 8(%rax), %ip1 + movq 16(%rax), %ip2 + movq 24(%rax), %ip3 + movq 32(%rax), %op0 + movq 40(%rax), %op1 + movq 48(%rax), %op2 + movq 56(%rax), %op3 + movq 64(%rax), %bits0 + movq 72(%rax), %bits1 + movq 80(%rax), %bits2 + movq 88(%rax), %bits3 + movq 96(%rax), %dtable + push %rax /* argument */ + push 104(%rax) /* ilowest */ + push 112(%rax) /* oend */ + push %olimit /* olimit space */ + + subq $24, %rsp + +.L_4X1_compute_olimit: + /* Computes how many iterations we can do safely + * %r15, %rax may be clobbered + * rbx, rdx must be saved + * op3 & ip0 mustn't be clobbered + */ + movq %rbx, 0(%rsp) + movq %rdx, 8(%rsp) + + movq 32(%rsp), %rax /* rax = oend */ + subq %op3, %rax /* rax = oend - op3 */ + + /* r15 = (oend - op3) / 5 */ + movabsq $-3689348814741910323, %rdx + mulq %rdx + movq %rdx, %r15 + shrq $2, %r15 + + movq %ip0, %rax /* rax = ip0 */ + movq 40(%rsp), %rdx /* rdx = ilowest */ + subq %rdx, %rax /* rax = ip0 - ilowest */ + movq %rax, %rbx /* rbx = ip0 - ilowest */ + + /* rdx = (ip0 - ilowest) / 7 */ + movabsq $2635249153387078803, %rdx + mulq %rdx + subq %rdx, %rbx + shrq %rbx + addq %rbx, %rdx + shrq $2, %rdx + + /* r15 = min(%rdx, %r15) */ + cmpq %rdx, %r15 + cmova %rdx, %r15 + + /* r15 = r15 * 5 */ + leaq (%r15, %r15, 4), %r15 + + /* olimit = op3 + r15 */ + addq %op3, %olimit + + movq 8(%rsp), %rdx + movq 0(%rsp), %rbx + + /* If (op3 + 20 > olimit) */ + movq %op3, %rax /* rax = op3 */ + cmpq %rax, %olimit /* op3 == olimit */ + je .L_4X1_exit + + /* If (ip1 < ip0) go to exit */ + cmpq %ip0, %ip1 + jb .L_4X1_exit + + /* If (ip2 < ip1) go to exit */ + cmpq %ip1, %ip2 + jb .L_4X1_exit + + /* If (ip3 < ip2) go to exit */ + cmpq %ip2, %ip3 + jb .L_4X1_exit + +/* Reads top 11 bits from bits[n] + * Loads dt[bits[n]] into var[n] + */ +#define GET_NEXT_DELT(n) \ + movq $53, %var##n; \ + shrxq %var##n, %bits##n, %var##n; \ + movzwl (%dtable,%var##n,2),%vard##n + +/* var[n] must contain the DTable entry computed with GET_NEXT_DELT + * Moves var[n] to %rax + * bits[n] <<= var[n] & 63 + * op[n][idx] = %rax >> 8 + * %ah is a way to access bits [8, 16) of %rax + */ +#define DECODE_FROM_DELT(n, idx) \ + movq %var##n, %rax; \ + shlxq %var##n, %bits##n, %bits##n; \ + movb %ah, idx(%op##n) + +/* Assumes GET_NEXT_DELT has been called. + * Calls DECODE_FROM_DELT then GET_NEXT_DELT + */ +#define DECODE_AND_GET_NEXT(n, idx) \ + DECODE_FROM_DELT(n, idx); \ + GET_NEXT_DELT(n) \ + +/* // ctz & nbBytes is stored in bits[n] + * // nbBits is stored in %rax + * ctz = CTZ[bits[n]] + * nbBits = ctz & 7 + * nbBytes = ctz >> 3 + * op[n] += 5 + * ip[n] -= nbBytes + * // Note: x86-64 is little-endian ==> no bswap + * bits[n] = MEM_readST(ip[n]) | 1 + * bits[n] <<= nbBits + */ +#define RELOAD_BITS(n) \ + bsfq %bits##n, %bits##n; \ + movq %bits##n, %rax; \ + andq $7, %rax; \ + shrq $3, %bits##n; \ + leaq 5(%op##n), %op##n; \ + subq %bits##n, %ip##n; \ + movq (%ip##n), %bits##n; \ + orq $1, %bits##n; \ + shlx %rax, %bits##n, %bits##n + + /* Store clobbered variables on the stack */ + movq %olimit, 24(%rsp) + movq %ip1, 0(%rsp) + movq %ip2, 8(%rsp) + movq %ip3, 16(%rsp) + + /* Call GET_NEXT_DELT for each stream */ + FOR_EACH_STREAM(GET_NEXT_DELT) + + .p2align 6 + +.L_4X1_loop_body: + /* Decode 5 symbols in each of the 4 streams (20 total) + * Must have called GET_NEXT_DELT for each stream + */ + FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 0) + FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 1) + FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 2) + FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 3) + FOR_EACH_STREAM_WITH_INDEX(DECODE_FROM_DELT, 4) + + /* Load ip[1,2,3] from stack (var[] aliases them) + * ip[] is needed for RELOAD_BITS + * Each will be stored back to the stack after RELOAD + */ + movq 0(%rsp), %ip1 + movq 8(%rsp), %ip2 + movq 16(%rsp), %ip3 + + /* Reload each stream & fetch the next table entry + * to prepare for the next iteration + */ + RELOAD_BITS(0) + GET_NEXT_DELT(0) + + RELOAD_BITS(1) + movq %ip1, 0(%rsp) + GET_NEXT_DELT(1) + + RELOAD_BITS(2) + movq %ip2, 8(%rsp) + GET_NEXT_DELT(2) + + RELOAD_BITS(3) + movq %ip3, 16(%rsp) + GET_NEXT_DELT(3) + + /* If op3 < olimit: continue the loop */ + cmp %op3, 24(%rsp) + ja .L_4X1_loop_body + + /* Reload ip[1,2,3] from stack */ + movq 0(%rsp), %ip1 + movq 8(%rsp), %ip2 + movq 16(%rsp), %ip3 + + /* Re-compute olimit */ + jmp .L_4X1_compute_olimit + +#undef GET_NEXT_DELT +#undef DECODE_FROM_DELT +#undef DECODE +#undef RELOAD_BITS +.L_4X1_exit: + addq $24, %rsp + + /* Restore stack (oend & olimit) */ + pop %rax /* olimit */ + pop %rax /* oend */ + pop %rax /* ilowest */ + pop %rax /* arg */ + + /* Save ip / op / bits */ + movq %ip0, 0(%rax) + movq %ip1, 8(%rax) + movq %ip2, 16(%rax) + movq %ip3, 24(%rax) + movq %op0, 32(%rax) + movq %op1, 40(%rax) + movq %op2, 48(%rax) + movq %op3, 56(%rax) + movq %bits0, 64(%rax) + movq %bits1, 72(%rax) + movq %bits2, 80(%rax) + movq %bits3, 88(%rax) + + /* Restore registers */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rdi + pop %rsi + pop %rbp + pop %rdx + pop %rcx + pop %rbx + pop %rax + ret + +_HUF_decompress4X2_usingDTable_internal_fast_asm_loop: +HUF_decompress4X2_usingDTable_internal_fast_asm_loop: + ZSTD_CET_ENDBRANCH + /* Save all registers - even if they are callee saved for simplicity. */ + push %rax + push %rbx + push %rcx + push %rdx + push %rbp + push %rsi + push %rdi + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 + + movq %rdi, %rax + movq 0(%rax), %ip0 + movq 8(%rax), %ip1 + movq 16(%rax), %ip2 + movq 24(%rax), %ip3 + movq 32(%rax), %op0 + movq 40(%rax), %op1 + movq 48(%rax), %op2 + movq 56(%rax), %op3 + movq 64(%rax), %bits0 + movq 72(%rax), %bits1 + movq 80(%rax), %bits2 + movq 88(%rax), %bits3 + movq 96(%rax), %dtable + push %rax /* argument */ + push %rax /* olimit */ + push 104(%rax) /* ilowest */ + + movq 112(%rax), %rax + push %rax /* oend3 */ + + movq %op3, %rax + push %rax /* oend2 */ + + movq %op2, %rax + push %rax /* oend1 */ + + movq %op1, %rax + push %rax /* oend0 */ + + /* Scratch space */ + subq $8, %rsp + +.L_4X2_compute_olimit: + /* Computes how many iterations we can do safely + * %r15, %rax may be clobbered + * rdx must be saved + * op[1,2,3,4] & ip0 mustn't be clobbered + */ + movq %rdx, 0(%rsp) + + /* We can consume up to 7 input bytes each iteration. */ + movq %ip0, %rax /* rax = ip0 */ + movq 40(%rsp), %rdx /* rdx = ilowest */ + subq %rdx, %rax /* rax = ip0 - ilowest */ + movq %rax, %r15 /* r15 = ip0 - ilowest */ + + /* rdx = rax / 7 */ + movabsq $2635249153387078803, %rdx + mulq %rdx + subq %rdx, %r15 + shrq %r15 + addq %r15, %rdx + shrq $2, %rdx + + /* r15 = (ip0 - ilowest) / 7 */ + movq %rdx, %r15 + + /* r15 = min(r15, min(oend0 - op0, oend1 - op1, oend2 - op2, oend3 - op3) / 10) */ + movq 8(%rsp), %rax /* rax = oend0 */ + subq %op0, %rax /* rax = oend0 - op0 */ + movq 16(%rsp), %rdx /* rdx = oend1 */ + subq %op1, %rdx /* rdx = oend1 - op1 */ + + cmpq %rax, %rdx + cmova %rax, %rdx /* rdx = min(%rdx, %rax) */ + + movq 24(%rsp), %rax /* rax = oend2 */ + subq %op2, %rax /* rax = oend2 - op2 */ + + cmpq %rax, %rdx + cmova %rax, %rdx /* rdx = min(%rdx, %rax) */ + + movq 32(%rsp), %rax /* rax = oend3 */ + subq %op3, %rax /* rax = oend3 - op3 */ + + cmpq %rax, %rdx + cmova %rax, %rdx /* rdx = min(%rdx, %rax) */ + + movabsq $-3689348814741910323, %rax + mulq %rdx + shrq $3, %rdx /* rdx = rdx / 10 */ + + /* r15 = min(%rdx, %r15) */ + cmpq %rdx, %r15 + cmova %rdx, %r15 + + /* olimit = op3 + 5 * r15 */ + movq %r15, %rax + leaq (%op3, %rax, 4), %olimit + addq %rax, %olimit + + movq 0(%rsp), %rdx + + /* If (op3 + 10 > olimit) */ + movq %op3, %rax /* rax = op3 */ + cmpq %rax, %olimit /* op3 == olimit */ + je .L_4X2_exit + + /* If (ip1 < ip0) go to exit */ + cmpq %ip0, %ip1 + jb .L_4X2_exit + + /* If (ip2 < ip1) go to exit */ + cmpq %ip1, %ip2 + jb .L_4X2_exit + + /* If (ip3 < ip2) go to exit */ + cmpq %ip2, %ip3 + jb .L_4X2_exit + +#define DECODE(n, idx) \ + movq %bits##n, %rax; \ + shrq $53, %rax; \ + movzwl 0(%dtable,%rax,4),%r8d; \ + movzbl 2(%dtable,%rax,4),%r15d; \ + movzbl 3(%dtable,%rax,4),%eax; \ + movw %r8w, (%op##n); \ + shlxq %r15, %bits##n, %bits##n; \ + addq %rax, %op##n + +#define RELOAD_BITS(n) \ + bsfq %bits##n, %bits##n; \ + movq %bits##n, %rax; \ + shrq $3, %bits##n; \ + andq $7, %rax; \ + subq %bits##n, %ip##n; \ + movq (%ip##n), %bits##n; \ + orq $1, %bits##n; \ + shlxq %rax, %bits##n, %bits##n + + + movq %olimit, 48(%rsp) + + .p2align 6 + +.L_4X2_loop_body: + /* We clobber r8, so store it on the stack */ + movq %r8, 0(%rsp) + + /* Decode 5 symbols from each of the 4 streams (20 symbols total). */ + FOR_EACH_STREAM_WITH_INDEX(DECODE, 0) + FOR_EACH_STREAM_WITH_INDEX(DECODE, 1) + FOR_EACH_STREAM_WITH_INDEX(DECODE, 2) + FOR_EACH_STREAM_WITH_INDEX(DECODE, 3) + FOR_EACH_STREAM_WITH_INDEX(DECODE, 4) + + /* Reload r8 */ + movq 0(%rsp), %r8 + + FOR_EACH_STREAM(RELOAD_BITS) + + cmp %op3, 48(%rsp) + ja .L_4X2_loop_body + jmp .L_4X2_compute_olimit + +#undef DECODE +#undef RELOAD_BITS +.L_4X2_exit: + addq $8, %rsp + /* Restore stack (oend & olimit) */ + pop %rax /* oend0 */ + pop %rax /* oend1 */ + pop %rax /* oend2 */ + pop %rax /* oend3 */ + pop %rax /* ilowest */ + pop %rax /* olimit */ + pop %rax /* arg */ + + /* Save ip / op / bits */ + movq %ip0, 0(%rax) + movq %ip1, 8(%rax) + movq %ip2, 16(%rax) + movq %ip3, 24(%rax) + movq %op0, 32(%rax) + movq %op1, 40(%rax) + movq %op2, 48(%rax) + movq %op3, 56(%rax) + movq %bits0, 64(%rax) + movq %bits1, 72(%rax) + movq %bits2, 80(%rax) + movq %bits3, 88(%rax) + + /* Restore registers */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rdi + pop %rsi + pop %rbp + pop %rdx + pop %rcx + pop %rbx + pop %rax + ret + +#endif diff --git a/third_party/zstd/decompress/zstd_ddict.cpp b/third_party/zstd/decompress/zstd_ddict.c similarity index 87% rename from third_party/zstd/decompress/zstd_ddict.cpp rename to third_party/zstd/decompress/zstd_ddict.c index ecb71145f3f..309ec0d0364 100644 --- a/third_party/zstd/decompress/zstd_ddict.cpp +++ b/third_party/zstd/decompress/zstd_ddict.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -14,20 +14,21 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include /* memcpy, memmove, memset */ -#include "zstd/common/mem.h" /* low level memory routines */ -#include "zstd/common/fse.h" -#include "zstd/common/fse_static.h" -#include "zstd/common/huf.h" -#include "zstd/common/huf_static.h" -#include "zstd/decompress/zstd_decompress_internal.h" -#include "zstd/decompress/zstd_ddict.h" +#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customFree */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */ +#include "../common/cpu.h" /* bmi2 */ +#include "../common/mem.h" /* low level memory routines */ +#define FSE_STATIC_LINKING_ONLY +#include "../common/fse.h" +#include "../common/huf.h" +#include "zstd_decompress_internal.h" +#include "zstd_ddict.h" + +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) +# include "../legacy/zstd_legacy.h" +#endif -// #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) -// # include "../legacy/zstd_legacy.h" -// #endif -namespace duckdb_zstd { /*-******************************************************* * Types @@ -126,14 +127,14 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, ddict->dictContent = dict; if (!dict) dictSize = 0; } else { - void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem); + void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem); ddict->dictBuffer = internalBuffer; ddict->dictContent = internalBuffer; if (!internalBuffer) return ERROR(memory_allocation); - memcpy(internalBuffer, dict, dictSize); + ZSTD_memcpy(internalBuffer, dict, dictSize); } ddict->dictSize = dictSize; - ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ + ddict->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */ /* parse dictionary content */ FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , ""); @@ -146,9 +147,9 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, ZSTD_customMem customMem) { - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; - { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem); + { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem); if (ddict == NULL) return NULL; ddict->cMem = customMem; { size_t const initResult = ZSTD_initDDict_internal(ddict, @@ -197,7 +198,7 @@ const ZSTD_DDict* ZSTD_initStaticDDict( if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */ if (sBufferSize < neededSpace) return NULL; if (dictLoadMethod == ZSTD_dlm_byCopy) { - memcpy(ddict+1, dict, dictSize); /* local copy */ + ZSTD_memcpy(ddict+1, dict, dictSize); /* local copy */ dict = ddict+1; } if (ZSTD_isError( ZSTD_initDDict_internal(ddict, @@ -212,8 +213,8 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict) { if (ddict==NULL) return 0; /* support free on NULL */ { ZSTD_customMem const cMem = ddict->cMem; - ZSTD_free(ddict->dictBuffer, cMem); - ZSTD_free(ddict, cMem); + ZSTD_customFree(ddict->dictBuffer, cMem); + ZSTD_customFree(ddict, cMem); return 0; } } @@ -239,7 +240,5 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict) unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict) { if (ddict==NULL) return 0; - return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize); -} - + return ddict->dictID; } diff --git a/third_party/zstd/decompress/zstd_decompress.cpp b/third_party/zstd/decompress/zstd_decompress.c similarity index 66% rename from third_party/zstd/decompress/zstd_decompress.cpp rename to third_party/zstd/decompress/zstd_decompress.c index 19ebd907861..2f03cf7b0c7 100644 --- a/third_party/zstd/decompress/zstd_decompress.cpp +++ b/third_party/zstd/decompress/zstd_decompress.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -55,88 +55,165 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include /* memcpy, memmove, memset */ -#include "zstd/common/mem.h" /* low level memory routines */ -#include "zstd/common/fse.h" -#include "zstd/common/fse_static.h" -#include "zstd/common/huf.h" -#include "zstd/common/huf_static.h" -#include "zstd/common/zstd_internal.h" /* blockProperties_t */ -#include "zstd/decompress/zstd_decompress_internal.h" /* ZSTD_DCtx */ -#include "zstd/decompress/zstd_ddict.h" /* ZSTD_DDictDictContent */ -#include "zstd/decompress/zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */ - -// #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) -// # include "../legacy/zstd_legacy.h" -// #endif -namespace duckdb_zstd { -const U32 ZSTDConstants::LL_base[MaxLL+1] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 18, 20, 22, 24, 28, 32, 40, - 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, - 0x2000, 0x4000, 0x8000, 0x10000 }; - -const U32 ZSTDConstants::OF_base[MaxOff+1] = { - 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, - 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, - 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, - 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD }; - -const U32 ZSTDConstants::OF_bits[MaxOff+1] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31 }; - -const U32 ZSTDConstants::ML_base[MaxML+1] = { - 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, - 35, 37, 39, 41, 43, 47, 51, 59, - 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, - 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 }; - -const size_t ZSTDInternalConstants::ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; -const U32 ZSTDInternalConstants::LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 3, 3, - 4, 6, 7, 8, 9,10,11,12, - 13,14,15,16 }; -const S16 ZSTDInternalConstants::LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 3, 2, 1, 1, 1, 1, 1, - -1,-1,-1,-1 }; -#define LL_DEFAULTNORMLOG 6 /* for static allocation */ -const U32 ZSTDInternalConstants::LL_defaultNormLog = LL_DEFAULTNORMLOG; -const U32 ZSTDInternalConstants::ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 3, 3, - 4, 4, 5, 7, 8, 9,10,11, - 12,13,14,15,16 }; -const S16 ZSTDInternalConstants::ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1,-1,-1, - -1,-1,-1,-1,-1 }; -#define ML_DEFAULTNORMLOG 6 /* for static allocation */ -const U32 ZSTDInternalConstants::ML_defaultNormLog = ML_DEFAULTNORMLOG; - -const S16 ZSTDInternalConstants::OF_defaultNorm[DefaultMaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - -1,-1,-1,-1,-1 }; -#define OF_DEFAULTNORMLOG 5 /* for static allocation */ -const U32 ZSTDInternalConstants::OF_defaultNormLog = OF_DEFAULTNORMLOG; -const U32 ZSTDInternalConstants::repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; - -const ZSTD_customMem ZSTDInternalConstants::ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */ +#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */ +#include "../common/error_private.h" +#include "../common/zstd_internal.h" /* blockProperties_t */ +#include "../common/mem.h" /* low level memory routines */ +#include "../common/bits.h" /* ZSTD_highbit32 */ +#define FSE_STATIC_LINKING_ONLY +#include "../common/fse.h" +#include "../common/huf.h" +#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */ +#include "zstd_decompress_internal.h" /* ZSTD_DCtx */ +#include "zstd_ddict.h" /* ZSTD_DDictDictContent */ +#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */ + +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) +# include "../legacy/zstd_legacy.h" +#endif + + + +/************************************* + * Multiple DDicts Hashset internals * + *************************************/ + +#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4 +#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float. + * Currently, that means a 0.75 load factor. + * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded + * the load factor of the ddict hash set. + */ + +#define DDICT_HASHSET_TABLE_BASE_SIZE 64 +#define DDICT_HASHSET_RESIZE_FACTOR 2 + +/* Hash function to determine starting position of dict insertion within the table + * Returns an index between [0, hashSet->ddictPtrTableSize] + */ +static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) { + const U64 hash = XXH64(&dictID, sizeof(U32), 0); + /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */ + return hash & (hashSet->ddictPtrTableSize - 1); +} + +/* Adds DDict to a hashset without resizing it. + * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set. + * Returns 0 if successful, or a zstd error code if something went wrong. + */ +static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) { + const U32 dictID = ZSTD_getDictID_fromDDict(ddict); + size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID); + const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1; + RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!"); + DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx); + while (hashSet->ddictPtrTable[idx] != NULL) { + /* Replace existing ddict if inserting ddict with same dictID */ + if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) { + DEBUGLOG(4, "DictID already exists, replacing rather than adding"); + hashSet->ddictPtrTable[idx] = ddict; + return 0; + } + idx &= idxRangeMask; + idx++; + } + DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx); + hashSet->ddictPtrTable[idx] = ddict; + hashSet->ddictPtrCount++; + return 0; +} + +/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and + * rehashes all values, allocates new table, frees old table. + * Returns 0 on success, otherwise a zstd error code. + */ +static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) { + size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR; + const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem); + const ZSTD_DDict** oldTable = hashSet->ddictPtrTable; + size_t oldTableSize = hashSet->ddictPtrTableSize; + size_t i; + + DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize); + RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!"); + hashSet->ddictPtrTable = newTable; + hashSet->ddictPtrTableSize = newTableSize; + hashSet->ddictPtrCount = 0; + for (i = 0; i < oldTableSize; ++i) { + if (oldTable[i] != NULL) { + FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), ""); + } + } + ZSTD_customFree((void*)oldTable, customMem); + DEBUGLOG(4, "Finished re-hash"); + return 0; +} + +/* Fetches a DDict with the given dictID + * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL. + */ +static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) { + size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID); + const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1; + DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx); + for (;;) { + size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]); + if (currDictID == dictID || currDictID == 0) { + /* currDictID == 0 implies a NULL ddict entry */ + break; + } else { + idx &= idxRangeMask; /* Goes to start of table when we reach the end */ + idx++; + } + } + DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx); + return hashSet->ddictPtrTable[idx]; +} + +/* Allocates space for and returns a ddict hash set + * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with. + * Returns NULL if allocation failed. + */ +static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) { + ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem); + DEBUGLOG(4, "Allocating new hash set"); + if (!ret) + return NULL; + ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem); + if (!ret->ddictPtrTable) { + ZSTD_customFree(ret, customMem); + return NULL; + } + ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE; + ret->ddictPtrCount = 0; + return ret; +} + +/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself. + * Note: The ZSTD_DDict* within the table are NOT freed. + */ +static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) { + DEBUGLOG(4, "Freeing ddict hash set"); + if (hashSet && hashSet->ddictPtrTable) { + ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem); + } + if (hashSet) { + ZSTD_customFree(hashSet, customMem); + } +} + +/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set. + * Returns 0 on success, or a ZSTD error. + */ +static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) { + DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize); + if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) { + FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), ""); + } + FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), ""); + return 0; +} /*-************************************************************* * Context management @@ -160,11 +237,21 @@ static size_t ZSTD_startingInputLength(ZSTD_format_e format) return startingInputLength; } +static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx) +{ + assert(dctx->streamStage == zdss_init); + dctx->format = ZSTD_f_zstd1; + dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; + dctx->outBufferMode = ZSTD_bm_buffered; + dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum; + dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict; + dctx->disableHufAsm = 0; + dctx->maxBlockSizeParam = 0; +} + static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) { - dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */ dctx->staticSize = 0; - dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; dctx->ddict = NULL; dctx->ddictLocal = NULL; dctx->dictEnd = NULL; @@ -174,12 +261,18 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) dctx->inBuffSize = 0; dctx->outBuffSize = 0; dctx->streamStage = zdss_init; +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) dctx->legacyContext = NULL; dctx->previousLegacyVersion = 0; +#endif dctx->noForwardProgress = 0; dctx->oversizedDuration = 0; - dctx->bmi2 = 0; - dctx->outBufferMode = ZSTD_obm_buffered; + dctx->isFrameDecompression = 1; +#if DYNAMIC_BMI2 + dctx->bmi2 = ZSTD_cpuSupportsBmi2(); +#endif + dctx->ddictSet = NULL; + ZSTD_DCtx_resetParameters(dctx); #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION dctx->dictContentEndForFuzzing = NULL; #endif @@ -198,11 +291,10 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize) return dctx; } -ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem) -{ - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; +static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) { + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; - { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem); + { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem); if (!dctx) return NULL; dctx->customMem = customMem; ZSTD_initDCtx_internal(dctx); @@ -210,10 +302,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem) } } +ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem) +{ + return ZSTD_createDCtx_internal(customMem); +} + ZSTD_DCtx* ZSTD_createDCtx(void) { DEBUGLOG(3, "ZSTD_createDCtx"); - return ZSTD_createDCtx_advanced(ZSTDInternalConstants::ZSTD_defaultCMem); + return ZSTD_createDCtx_internal(ZSTD_defaultCMem); } static void ZSTD_clearDict(ZSTD_DCtx* dctx) @@ -230,13 +327,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx) RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx"); { ZSTD_customMem const cMem = dctx->customMem; ZSTD_clearDict(dctx); - ZSTD_free(dctx->inBuff, cMem); + ZSTD_customFree(dctx->inBuff, cMem); dctx->inBuff = NULL; #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) if (dctx->legacyContext) ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion); #endif - ZSTD_free(dctx, cMem); + if (dctx->ddictSet) { + ZSTD_freeDDictHashSet(dctx->ddictSet, cMem); + dctx->ddictSet = NULL; + } + ZSTD_customFree(dctx, cMem); return 0; } } @@ -245,7 +346,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx) void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) { size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx); - memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */ + ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */ +} + +/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on + * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then + * accordingly sets the ddict to be used to decompress the frame. + * + * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is. + * + * ZSTD_d_refMultipleDDicts must be enabled for this function to be called. + */ +static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) { + assert(dctx->refMultipleDDicts && dctx->ddictSet); + DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame"); + if (dctx->ddict) { + const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID); + if (frameDDict) { + DEBUGLOG(4, "DDict found!"); + ZSTD_clearDict(dctx); + dctx->dictID = dctx->fParams.dictID; + dctx->ddict = frameDDict; + dctx->dictUses = ZSTD_use_indefinitely; + } + } } @@ -271,8 +395,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size) return 0; } -static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 }; -static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; +/*! ZSTD_isSkippableFrame() : + * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame. + * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. + */ +unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size) +{ + if (size < ZSTD_FRAMEIDSIZE) return 0; + { U32 const magic = MEM_readLE32(buffer); + if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1; + } + return 0; +} + /** ZSTD_frameHeaderSize_internal() : * srcSize must be large enough to reach header size fields. * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless. @@ -308,23 +443,47 @@ size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize) * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless * @return : 0, `zfhPtr` is correctly filled, * >0, `srcSize` is too small, value is wanted `srcSize` amount, - * or an error code, which can be tested using ZSTD_isError() */ +** or an error code, which can be tested using ZSTD_isError() */ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format) { const BYTE* ip = (const BYTE*)src; size_t const minInputSize = ZSTD_startingInputLength(format); - memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */ - if (srcSize < minInputSize) return minInputSize; - RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter"); + DEBUGLOG(5, "ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu", minInputSize, srcSize); + if (srcSize > 0) { + /* note : technically could be considered an assert(), since it's an invalid entry */ + RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter : src==NULL, but srcSize>0"); + } + if (srcSize < minInputSize) { + if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) { + /* when receiving less than @minInputSize bytes, + * control these bytes at least correspond to a supported magic number + * in order to error out early if they don't. + **/ + size_t const toCopy = MIN(4, srcSize); + unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER); + assert(src != NULL); + ZSTD_memcpy(hbuf, src, toCopy); + if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) { + /* not a zstd frame : let's check if it's a skippable frame */ + MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START); + ZSTD_memcpy(hbuf, src, toCopy); + if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) { + RETURN_ERROR(prefix_unknown, + "first bytes don't correspond to any supported magic number"); + } } } + return minInputSize; + } + + ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzers may not understand that zfhPtr will be read only if return value is zero, since they are 2 different signals */ if ( (format != ZSTD_f_zstd1_magicless) && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) { if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ if (srcSize < ZSTD_SKIPPABLEHEADERSIZE) return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */ - memset(zfhPtr, 0, sizeof(*zfhPtr)); + ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE); zfhPtr->frameType = ZSTD_skippableFrame; return 0; @@ -359,7 +518,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s } switch(dictIDSizeCode) { - default: assert(0); /* impossible */ + default: + assert(0); /* impossible */ + ZSTD_FALLTHROUGH; case 0 : break; case 1 : dictID = ip[pos]; pos++; break; case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break; @@ -367,7 +528,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s } switch(fcsID) { - default: assert(0); /* impossible */ + default: + assert(0); /* impossible */ + ZSTD_FALLTHROUGH; case 0 : if (singleSegment) frameContentSize = ip[pos]; break; case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break; case 2 : frameContentSize = MEM_readLE32(ip+pos); break; @@ -396,7 +559,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1); } - /** ZSTD_getFrameContentSize() : * compatible with legacy mode * @return : decompressed size of the single frame pointed to be `src` if known, otherwise @@ -430,18 +592,52 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize) sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE); RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32, frameParameter_unsupported, ""); - { - size_t const skippableSize = skippableHeaderSize + sizeU32; + { size_t const skippableSize = skippableHeaderSize + sizeU32; RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, ""); return skippableSize; } } +/*! ZSTD_readSkippableFrame() : + * Retrieves content of a skippable frame, and writes it to dst buffer. + * + * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written, + * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested + * in the magicVariant. + * + * Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame. + * + * @return : number of bytes written or a ZSTD error. + */ +size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, + unsigned* magicVariant, /* optional, can be NULL */ + const void* src, size_t srcSize) +{ + RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, ""); + + { U32 const magicNumber = MEM_readLE32(src); + size_t skippableFrameSize = readSkippableFrameSize(src, srcSize); + size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE; + + /* check input validity */ + RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, ""); + RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, ""); + RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, ""); + + /* deliver payload */ + if (skippableContentSize > 0 && dst != NULL) + ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize); + if (magicVariant != NULL) + *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START; + return skippableContentSize; + } +} + /** ZSTD_findDecompressedSize() : - * compatible with legacy mode * `srcSize` must be the exact length of some number of ZSTD compressed and/or * skippable frames - * @return : decompressed size of the frames contained */ + * note: compatible with legacy mode + * @return : decompressed size of the frames contained */ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize) { unsigned long long totalDstSize = 0; @@ -451,9 +647,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize) if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { size_t const skippableSize = readSkippableFrameSize(src, srcSize); - if (ZSTD_isError(skippableSize)) { - return ZSTD_CONTENTSIZE_ERROR; - } + if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR; assert(skippableSize <= srcSize); src = (const BYTE *)src + skippableSize; @@ -461,17 +655,17 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize) continue; } - { unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize); - if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret; + { unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize); + if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs; - /* check for overflow */ - if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR; - totalDstSize += ret; + if (totalDstSize + fcs < totalDstSize) + return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */ + totalDstSize += fcs; } + /* skip to next frame */ { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize); - if (ZSTD_isError(frameSrcSize)) { - return ZSTD_CONTENTSIZE_ERROR; - } + if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR; + assert(frameSrcSize <= srcSize); src = (const BYTE *)src + frameSrcSize; srcSize -= frameSrcSize; @@ -501,12 +695,19 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize) /** ZSTD_decodeFrameHeader() : * `headerSize` must be the size provided by ZSTD_frameHeaderSize(). + * If multiple DDict references are enabled, also will choose the correct DDict to use. * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize) { size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format); if (ZSTD_isError(result)) return result; /* invalid header */ RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small"); + + /* Reference DDict requested by frame if dctx references multiple ddicts */ + if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) { + ZSTD_DCtx_selectFrameDDict(dctx); + } + #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* Skip the dictID check in fuzzing mode, because it makes the search * harder. @@ -514,7 +715,9 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID), dictionary_wrong, ""); #endif - if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0); + dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0; + if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0); + dctx->processedCSize += headerSize; return 0; } @@ -526,17 +729,17 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret) return frameSizeInfo; } -static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize) +static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize, ZSTD_format_e format) { ZSTD_frameSizeInfo frameSizeInfo; - memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo)); + ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo)); #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) - if (ZSTD_isLegacy(src, srcSize)) + if (format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize)) return ZSTD_findFrameSizeInfoLegacy(src, srcSize); #endif - if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE) + if (format == ZSTD_f_zstd1 && (srcSize >= ZSTD_SKIPPABLEHEADERSIZE) && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize); assert(ZSTD_isError(frameSizeInfo.compressedSize) || @@ -550,7 +753,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize ZSTD_frameHeader zfh; /* Extract Frame Header */ - { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize); + { size_t const ret = ZSTD_getFrameHeader_advanced(&zfh, src, srcSize, format); if (ZSTD_isError(ret)) return ZSTD_errorFrameSizeInfo(ret); if (ret > 0) @@ -567,11 +770,11 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize if (ZSTD_isError(cBlockSize)) return ZSTD_errorFrameSizeInfo(cBlockSize); - if (ZSTDInternalConstants::ZSTD_blockHeaderSize + cBlockSize > remainingSize) + if (ZSTD_blockHeaderSize + cBlockSize > remainingSize) return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong)); - ip += ZSTDInternalConstants::ZSTD_blockHeaderSize + cBlockSize; - remainingSize -= ZSTDInternalConstants::ZSTD_blockHeaderSize + cBlockSize; + ip += ZSTD_blockHeaderSize + cBlockSize; + remainingSize -= ZSTD_blockHeaderSize + cBlockSize; nbBlocks++; if (blockProperties.lastBlock) break; @@ -584,23 +787,26 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize ip += 4; } - frameSizeInfo.compressedSize = ip - ipstart; + frameSizeInfo.nbBlocks = nbBlocks; + frameSizeInfo.compressedSize = (size_t)(ip - ipstart); frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) ? zfh.frameContentSize - : nbBlocks * zfh.blockSizeMax; + : (unsigned long long)nbBlocks * zfh.blockSizeMax; return frameSizeInfo; } } +static size_t ZSTD_findFrameCompressedSize_advanced(const void *src, size_t srcSize, ZSTD_format_e format) { + ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, format); + return frameSizeInfo.compressedSize; +} + /** ZSTD_findFrameCompressedSize() : - * compatible with legacy mode - * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame - * `srcSize` must be at least as large as the frame contained - * @return : the compressed size of the frame starting at `src` */ + * See docs in zstd.h + * Note: compatible with legacy mode */ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) { - ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize); - return frameSizeInfo.compressedSize; + return ZSTD_findFrameCompressedSize_advanced(src, srcSize, ZSTD_f_zstd1); } /** ZSTD_decompressBound() : @@ -614,7 +820,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize) unsigned long long bound = 0; /* Iterate over each frame */ while (srcSize > 0) { - ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize); + ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1); size_t const compressedSize = frameSizeInfo.compressedSize; unsigned long long const decompressedBound = frameSizeInfo.decompressedBound; if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR) @@ -627,6 +833,48 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize) return bound; } +size_t ZSTD_decompressionMargin(void const* src, size_t srcSize) +{ + size_t margin = 0; + unsigned maxBlockSize = 0; + + /* Iterate over each frame */ + while (srcSize > 0) { + ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1); + size_t const compressedSize = frameSizeInfo.compressedSize; + unsigned long long const decompressedBound = frameSizeInfo.decompressedBound; + ZSTD_frameHeader zfh; + + FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), ""); + if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR) + return ERROR(corruption_detected); + + if (zfh.frameType == ZSTD_frame) { + /* Add the frame header to our margin */ + margin += zfh.headerSize; + /* Add the checksum to our margin */ + margin += zfh.checksumFlag ? 4 : 0; + /* Add 3 bytes per block */ + margin += 3 * frameSizeInfo.nbBlocks; + + /* Compute the max block size */ + maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax); + } else { + assert(zfh.frameType == ZSTD_skippableFrame); + /* Add the entire skippable frame size to our margin. */ + margin += compressedSize; + } + + assert(srcSize >= compressedSize); + src = (const BYTE*)src + compressedSize; + srcSize -= compressedSize; + } + + /* Add the max block size back to the margin. */ + margin += maxBlockSize; + + return margin; +} /*-************************************************************* * Frame decoding @@ -637,7 +885,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize) size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize) { DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize); - ZSTD_checkContinuity(dctx, blockStart); + ZSTD_checkContinuity(dctx, blockStart, blockSize); dctx->previousDstEnd = (const char*)blockStart + blockSize; return blockSize; } @@ -647,12 +895,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize) { DEBUGLOG(5, "ZSTD_copyRawBlock"); + RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, ""); if (dst == NULL) { if (srcSize == 0) return 0; RETURN_ERROR(dstBuffer_null, ""); } - RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, ""); - memcpy(dst, src, srcSize); + ZSTD_memmove(dst, src, srcSize); return srcSize; } @@ -660,15 +908,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, BYTE b, size_t regenSize) { + RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, ""); if (dst == NULL) { if (regenSize == 0) return 0; RETURN_ERROR(dstBuffer_null, ""); } - RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, ""); - memset(dst, b, regenSize); + ZSTD_memset(dst, b, regenSize); return regenSize; } +static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming) +{ +#if ZSTD_TRACE + if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) { + ZSTD_Trace trace; + ZSTD_memset(&trace, 0, sizeof(trace)); + trace.version = ZSTD_VERSION_NUMBER; + trace.streaming = streaming; + if (dctx->ddict) { + trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict); + trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict); + trace.dictionaryIsCold = dctx->ddictIsCold; + } + trace.uncompressedSize = (size_t)uncompressedSize; + trace.compressedSize = (size_t)compressedSize; + trace.dctx = dctx; + ZSTD_trace_decompress_end(dctx->traceCtx, &trace); + } +#else + (void)dctx; + (void)uncompressedSize; + (void)compressedSize; + (void)streaming; +#endif +} + /*! ZSTD_decompressFrame() : * @dctx must be properly initialized @@ -678,8 +952,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void** srcPtr, size_t *srcSizePtr) { - const BYTE* ip = (const BYTE*)(*srcPtr); - BYTE* const ostart = (BYTE* const)dst; + const BYTE* const istart = (const BYTE*)(*srcPtr); + const BYTE* ip = istart; + BYTE* const ostart = (BYTE*)dst; BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart; BYTE* op = ostart; size_t remainingSrcSize = *srcSizePtr; @@ -688,51 +963,77 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, /* check */ RETURN_ERROR_IF( - remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTDInternalConstants::ZSTD_blockHeaderSize, + remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize, srcSize_wrong, ""); /* Frame Header */ { size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal( ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format); if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize; - RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTDInternalConstants::ZSTD_blockHeaderSize, + RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize, srcSize_wrong, ""); FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , ""); ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize; } + /* Shrink the blockSizeMax if enabled */ + if (dctx->maxBlockSizeParam != 0) + dctx->fParams.blockSizeMax = MIN(dctx->fParams.blockSizeMax, (unsigned)dctx->maxBlockSizeParam); + /* Loop on each block */ while (1) { + BYTE* oBlockEnd = oend; size_t decodedSize; blockProperties_t blockProperties; size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties); if (ZSTD_isError(cBlockSize)) return cBlockSize; - ip += ZSTDInternalConstants::ZSTD_blockHeaderSize; - remainingSrcSize -= ZSTDInternalConstants::ZSTD_blockHeaderSize; + ip += ZSTD_blockHeaderSize; + remainingSrcSize -= ZSTD_blockHeaderSize; RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, ""); + if (ip >= op && ip < oBlockEnd) { + /* We are decompressing in-place. Limit the output pointer so that we + * don't overwrite the block that we are currently reading. This will + * fail decompression if the input & output pointers aren't spaced + * far enough apart. + * + * This is important to set, even when the pointers are far enough + * apart, because ZSTD_decompressBlock_internal() can decide to store + * literals in the output buffer, after the block it is decompressing. + * Since we don't want anything to overwrite our input, we have to tell + * ZSTD_decompressBlock_internal to never write past ip. + * + * See ZSTD_allocateLiteralsBuffer() for reference. + */ + oBlockEnd = op + (ip - op); + } + switch(blockProperties.blockType) { case bt_compressed: - decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1); + assert(dctx->isFrameDecompression == 1); + decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, not_streaming); break; case bt_raw : - decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize); + /* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */ + decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize); break; case bt_rle : - decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize); + decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize); break; case bt_reserved : default: RETURN_ERROR(corruption_detected, "invalid block type"); } - - if (ZSTD_isError(decodedSize)) return decodedSize; - if (dctx->fParams.checksumFlag) + FORWARD_IF_ERROR(decodedSize, "Block decompression failure"); + DEBUGLOG(5, "Decompressed block of dSize = %u", (unsigned)decodedSize); + if (dctx->validateChecksum) { XXH64_update(&dctx->xxhState, op, decodedSize); - if (decodedSize != 0) + } + if (decodedSize) /* support dst = NULL,0 */ { op += decodedSize; + } assert(ip != NULL); ip += cBlockSize; remainingSrcSize -= cBlockSize; @@ -744,22 +1045,27 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, corruption_detected, ""); } if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */ - U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); - U32 checkRead; RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, ""); - checkRead = MEM_readLE32(ip); - RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, ""); + if (!dctx->forceIgnoreChecksum) { + U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); + U32 checkRead; + checkRead = MEM_readLE32(ip); + RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, ""); + } ip += 4; remainingSrcSize -= 4; } - + ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0); /* Allow caller to get size read */ + DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr); *srcPtr = ip; *srcSizePtr = remainingSrcSize; - return op-ostart; + return (size_t)(op-ostart); } -static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, +static +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const void* dict, size_t dictSize, @@ -779,7 +1085,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, while (srcSize >= ZSTD_startingInputLength(dctx->format)) { #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) - if (ZSTD_isLegacy(src, srcSize)) { + if (dctx->format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize)) { size_t decodedSize; size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize); if (ZSTD_isError(frameSize)) return frameSize; @@ -789,7 +1095,16 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize); if (ZSTD_isError(decodedSize)) return decodedSize; - assert(decodedSize <=- dstCapacity); + { + unsigned long long const expectedSize = ZSTD_getFrameContentSize(src, srcSize); + RETURN_ERROR_IF(expectedSize == ZSTD_CONTENTSIZE_ERROR, corruption_detected, "Corrupted frame header!"); + if (expectedSize != ZSTD_CONTENTSIZE_UNKNOWN) { + RETURN_ERROR_IF(expectedSize != decodedSize, corruption_detected, + "Frame header size does not match decoded size!"); + } + } + + assert(decodedSize <= dstCapacity); dst = (BYTE*)dst + decodedSize; dstCapacity -= decodedSize; @@ -800,17 +1115,18 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, } #endif - { U32 const magicNumber = MEM_readLE32(src); - DEBUGLOG(4, "reading magic number %08X (expecting %08X)", - (unsigned)magicNumber, ZSTD_MAGICNUMBER); + if (dctx->format == ZSTD_f_zstd1 && srcSize >= 4) { + U32 const magicNumber = MEM_readLE32(src); + DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber); if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { + /* skippable frame detected : skip it */ size_t const skippableSize = readSkippableFrameSize(src, srcSize); - FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed"); + FORWARD_IF_ERROR(skippableSize, "invalid skippable frame"); assert(skippableSize <= srcSize); src = (const BYTE *)src + skippableSize; srcSize -= skippableSize; - continue; + continue; /* check next frame */ } } if (ddict) { @@ -821,7 +1137,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, * use this in all cases but ddict */ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), ""); } - ZSTD_checkContinuity(dctx, dst); + ZSTD_checkContinuity(dctx, dst, dstCapacity); { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity, &src, &srcSize); @@ -829,15 +1145,13 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown) && (moreThan1Frame==1), srcSize_wrong, - "at least one frame successfully completed, but following " - "bytes are garbage: it's more likely to be a srcSize error, " - "specifying more bytes than compressed size of frame(s). This " - "error message replaces ERROR(prefix_unknown), which would be " - "confusing, as the first header is actually correct. Note that " - "one could be unlucky, it might be a corruption error instead, " - "happening right at the place where we expect zstd magic " - "bytes. But this is _much_ less likely than a srcSize field " - "error."); + "At least one frame successfully completed, " + "but following bytes are garbage: " + "it's more likely to be a srcSize error, " + "specifying more input bytes than size of frame(s). " + "Note: one could be unlucky, it might be a corruption error instead, " + "happening right at the place where we expect zstd magic bytes. " + "But this is _much_ less likely than a srcSize field error."); if (ZSTD_isError(res)) return res; assert(res <= dstCapacity); if (res != 0) @@ -849,7 +1163,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed"); - return (BYTE*)dst - (BYTE*)dststart; + return (size_t)((BYTE*)dst - (BYTE*)dststart); } size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, @@ -866,7 +1180,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx) switch (dctx->dictUses) { default: assert(0 /* Impossible */); - /* fall-through */ + ZSTD_FALLTHROUGH; case ZSTD_dont_use: ZSTD_clearDict(dctx); return NULL; @@ -888,7 +1202,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr { #if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1) size_t regenSize; - ZSTD_DCtx* const dctx = ZSTD_createDCtx(); + ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem); RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!"); regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize); ZSTD_freeDCtx(dctx); @@ -908,8 +1222,8 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; } /** - * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed, - * we allow taking a partial block as the input. Currently only raw uncompressed blocks can + * Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we + * allow taking a partial block as the input. Currently only raw uncompressed blocks can * be streamed. * * For blocks that can be streamed, this allows us to reduce the latency until we produce @@ -922,7 +1236,7 @@ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t return dctx->expected; if (dctx->bType != bt_raw) return dctx->expected; - return MIN(MAX(inputSize, 1), dctx->expected); + return BOUNDED(1, inputSize, dctx->expected); } ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) { @@ -930,7 +1244,9 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) { { default: /* should not happen */ assert(0); + ZSTD_FALLTHROUGH; case ZSTDds_getFrameHeaderSize: + ZSTD_FALLTHROUGH; case ZSTDds_decodeFrameHeader: return ZSTDnit_frameHeader; case ZSTDds_decodeBlockHeader: @@ -942,6 +1258,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) { case ZSTDds_checkChecksum: return ZSTDnit_checksum; case ZSTDds_decodeSkippableHeader: + ZSTD_FALLTHROUGH; case ZSTDds_skipFrame: return ZSTDnit_skippableFrame; } @@ -958,7 +1275,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize); /* Sanity check */ RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed"); - if (dstCapacity) ZSTD_checkContinuity(dctx, dst); + ZSTD_checkContinuity(dctx, dst, dstCapacity); + + dctx->processedCSize += srcSize; switch (dctx->stage) { @@ -967,29 +1286,29 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c if (dctx->format == ZSTD_f_zstd1) { /* allows header */ assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */ if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ - memcpy(dctx->headerBuffer, src, srcSize); + ZSTD_memcpy(dctx->headerBuffer, src, srcSize); dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */ dctx->stage = ZSTDds_decodeSkippableHeader; return 0; } } dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format); if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize; - memcpy(dctx->headerBuffer, src, srcSize); + ZSTD_memcpy(dctx->headerBuffer, src, srcSize); dctx->expected = dctx->headerSize - srcSize; dctx->stage = ZSTDds_decodeFrameHeader; return 0; case ZSTDds_decodeFrameHeader: assert(src != NULL); - memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize); + ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize); FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), ""); - dctx->expected = ZSTDInternalConstants::ZSTD_blockHeaderSize; + dctx->expected = ZSTD_blockHeaderSize; dctx->stage = ZSTDds_decodeBlockHeader; return 0; case ZSTDds_decodeBlockHeader: { blockProperties_t bp; - size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTDInternalConstants::ZSTD_blockHeaderSize, &bp); + size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp); if (ZSTD_isError(cBlockSize)) return cBlockSize; RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, "Block Size Exceeds Maximum"); dctx->expected = cBlockSize; @@ -1009,7 +1328,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c dctx->stage = ZSTDds_getFrameHeaderSize; } } else { - dctx->expected = ZSTDInternalConstants::ZSTD_blockHeaderSize; /* jump to next header */ + dctx->expected = ZSTD_blockHeaderSize; /* jump to next header */ dctx->stage = ZSTDds_decodeBlockHeader; } return 0; @@ -1023,7 +1342,8 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c { case bt_compressed: DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed"); - rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1); + assert(dctx->isFrameDecompression == 1); + rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, is_streaming); dctx->expected = 0; /* Streaming not supported */ break; case bt_raw : @@ -1045,7 +1365,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum"); DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize); dctx->decodedSize += rSize; - if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize); + if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize); dctx->previousDstEnd = (char*)dst + rSize; /* Stay on the same stage until we are finished streaming the block. */ @@ -1063,22 +1383,27 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c dctx->expected = 4; dctx->stage = ZSTDds_checkChecksum; } else { + ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1); dctx->expected = 0; /* ends here */ dctx->stage = ZSTDds_getFrameHeaderSize; } } else { dctx->stage = ZSTDds_decodeBlockHeader; - dctx->expected = ZSTDInternalConstants::ZSTD_blockHeaderSize; + dctx->expected = ZSTD_blockHeaderSize; } return rSize; } case ZSTDds_checkChecksum: assert(srcSize == 4); /* guaranteed by dctx->expected */ - { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); - U32 const check32 = MEM_readLE32(src); - DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32); - RETURN_ERROR_IF(check32 != h32, checksum_wrong, ""); + { + if (dctx->validateChecksum) { + U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); + U32 const check32 = MEM_readLE32(src); + DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32); + RETURN_ERROR_IF(check32 != h32, checksum_wrong, ""); + } + ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1); dctx->expected = 0; dctx->stage = ZSTDds_getFrameHeaderSize; return 0; @@ -1087,7 +1412,8 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c case ZSTDds_decodeSkippableHeader: assert(src != NULL); assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE); - memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */ + assert(dctx->format != ZSTD_f_zstd1_magicless); + ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */ dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */ dctx->stage = ZSTDds_skipFrame; return 0; @@ -1099,7 +1425,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c default: assert(0); /* impossible */ - RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */ + RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */ } } @@ -1140,11 +1466,11 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, /* in minimal huffman, we always use X1 variants */ size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable, dictPtr, dictEnd - dictPtr, - workspace, workspaceSize); + workspace, workspaceSize, /* flags */ 0); #else size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable, - dictPtr, dictEnd - dictPtr, - workspace, workspaceSize); + dictPtr, (size_t)(dictEnd - dictPtr), + workspace, workspaceSize, /* flags */ 0); #endif RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, ""); dictPtr += hSize; @@ -1152,40 +1478,46 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, { short offcodeNCount[MaxOff+1]; unsigned offcodeMaxValue = MaxOff, offcodeLog; - size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); + size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, ""); RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->OFTable, offcodeNCount, offcodeMaxValue, - ZSTDConstants::OF_base, ZSTDConstants::OF_bits, - offcodeLog); + OF_base, OF_bits, + offcodeLog, + entropy->workspace, sizeof(entropy->workspace), + /* bmi2 */0); dictPtr += offcodeHeaderSize; } { short matchlengthNCount[MaxML+1]; unsigned matchlengthMaxValue = MaxML, matchlengthLog; - size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); + size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, ""); RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->MLTable, matchlengthNCount, matchlengthMaxValue, - ZSTDConstants::ML_base, ZSTDInternalConstants::ML_bits, - matchlengthLog); + ML_base, ML_bits, + matchlengthLog, + entropy->workspace, sizeof(entropy->workspace), + /* bmi2 */ 0); dictPtr += matchlengthHeaderSize; } { short litlengthNCount[MaxLL+1]; unsigned litlengthMaxValue = MaxLL, litlengthLog; - size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); + size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, ""); RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->LLTable, litlengthNCount, litlengthMaxValue, - ZSTDConstants::LL_base, ZSTDInternalConstants::LL_bits, - litlengthLog); + LL_base, LL_bits, + litlengthLog, + entropy->workspace, sizeof(entropy->workspace), + /* bmi2 */ 0); dictPtr += litlengthHeaderSize; } @@ -1199,7 +1531,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, entropy->rep[i] = rep; } } - return dictPtr - (const BYTE*)dict; + return (size_t)(dictPtr - (const BYTE*)dict); } static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) @@ -1223,24 +1555,27 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict return ZSTD_refDictContent(dctx, dict, dictSize); } -static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; - size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx) { assert(dctx != NULL); +#if ZSTD_TRACE + dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0; +#endif dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */ dctx->stage = ZSTDds_getFrameHeaderSize; + dctx->processedCSize = 0; dctx->decodedSize = 0; dctx->previousDstEnd = NULL; dctx->prefixStart = NULL; dctx->virtualStart = NULL; dctx->dictEnd = NULL; - dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ + dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001); /* cover both little and big endian */ dctx->litEntropy = dctx->fseEntropy = 0; dctx->dictID = 0; dctx->bType = bt_reserved; + dctx->isFrameDecompression = 1; ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue)); - memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */ + ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */ dctx->LLTptr = dctx->entropy.LLTable; dctx->MLTptr = dctx->entropy.MLTable; dctx->OFTptr = dctx->entropy.OFTable; @@ -1297,7 +1632,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize) * This could for one of the following reasons : * - The frame does not require a dictionary (most common case). * - The frame was built with dictID intentionally removed. - * Needed dictionary is a hidden information. + * Needed dictionary is a hidden piece of information. * Note : this use case also happens when using a non-conformant dictionary. * - `srcSize` is too small, and as a result, frame header could not be decoded. * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`. @@ -1306,7 +1641,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize) * ZSTD_getFrameHeader(), which will provide a more precise error code. */ unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize) { - ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 }; + ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 }; size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize); if (ZSTD_isError(hError)) return 0; return zfp.dictID; @@ -1335,7 +1670,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, ZSTD_DStream* ZSTD_createDStream(void) { DEBUGLOG(3, "ZSTD_createDStream"); - return ZSTD_createDStream_advanced(ZSTDInternalConstants::ZSTD_defaultCMem); + return ZSTD_createDCtx_internal(ZSTD_defaultCMem); } ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize) @@ -1345,7 +1680,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize) ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem) { - return ZSTD_createDCtx_advanced(customMem); + return ZSTD_createDCtx_internal(customMem); } size_t ZSTD_freeDStream(ZSTD_DStream* zds) @@ -1356,7 +1691,7 @@ size_t ZSTD_freeDStream(ZSTD_DStream* zds) /* *** Initialization *** */ -size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTDInternalConstants::ZSTD_blockHeaderSize; } +size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; } size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; } size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, @@ -1413,7 +1748,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di size_t ZSTD_initDStream(ZSTD_DStream* zds) { DEBUGLOG(4, "ZSTD_initDStream"); - return ZSTD_initDStream_usingDDict(zds, NULL); + FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), ""); + FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), ""); + return ZSTD_startingInputLength(zds->format); } /* ZSTD_initDStream_usingDDict() : @@ -1421,6 +1758,7 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds) * this function cannot fail */ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict) { + DEBUGLOG(4, "ZSTD_initDStream_usingDDict"); FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , ""); FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , ""); return ZSTD_startingInputLength(dctx->format); @@ -1431,6 +1769,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict) * this function cannot fail */ size_t ZSTD_resetDStream(ZSTD_DStream* dctx) { + DEBUGLOG(4, "ZSTD_resetDStream"); FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), ""); return ZSTD_startingInputLength(dctx->format); } @@ -1443,6 +1782,16 @@ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict) if (ddict) { dctx->ddict = ddict; dctx->dictUses = ZSTD_use_indefinitely; + if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) { + if (dctx->ddictSet == NULL) { + dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem); + if (!dctx->ddictSet) { + RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!"); + } + } + assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */ + FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), ""); + } } return 0; } @@ -1464,7 +1813,7 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize) size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format) { - return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format); + return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format); } ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam) @@ -1481,9 +1830,26 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam) ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless); return bounds; case ZSTD_d_stableOutBuffer: - bounds.lowerBound = (int)ZSTD_obm_buffered; - bounds.upperBound = (int)ZSTD_obm_stable; + bounds.lowerBound = (int)ZSTD_bm_buffered; + bounds.upperBound = (int)ZSTD_bm_stable; + return bounds; + case ZSTD_d_forceIgnoreChecksum: + bounds.lowerBound = (int)ZSTD_d_validateChecksum; + bounds.upperBound = (int)ZSTD_d_ignoreChecksum; + return bounds; + case ZSTD_d_refMultipleDDicts: + bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict; + bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts; return bounds; + case ZSTD_d_disableHuffmanAssembly: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + case ZSTD_d_maxBlockSize: + bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN; + bounds.upperBound = ZSTD_BLOCKSIZE_MAX; + return bounds; + default:; } bounds.error = ERROR(parameter_unsupported); @@ -1506,6 +1872,35 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value) RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \ } +size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value) +{ + switch (param) { + case ZSTD_d_windowLogMax: + *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize); + return 0; + case ZSTD_d_format: + *value = (int)dctx->format; + return 0; + case ZSTD_d_stableOutBuffer: + *value = (int)dctx->outBufferMode; + return 0; + case ZSTD_d_forceIgnoreChecksum: + *value = (int)dctx->forceIgnoreChecksum; + return 0; + case ZSTD_d_refMultipleDDicts: + *value = (int)dctx->refMultipleDDicts; + return 0; + case ZSTD_d_disableHuffmanAssembly: + *value = (int)dctx->disableHufAsm; + return 0; + case ZSTD_d_maxBlockSize: + *value = dctx->maxBlockSizeParam; + return 0; + default:; + } + RETURN_ERROR(parameter_unsupported, ""); +} + size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value) { RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); @@ -1521,7 +1916,26 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value return 0; case ZSTD_d_stableOutBuffer: CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value); - dctx->outBufferMode = (ZSTD_outBufferMode_e)value; + dctx->outBufferMode = (ZSTD_bufferMode_e)value; + return 0; + case ZSTD_d_forceIgnoreChecksum: + CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value); + dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value; + return 0; + case ZSTD_d_refMultipleDDicts: + CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value); + if (dctx->staticSize != 0) { + RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!"); + } + dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value; + return 0; + case ZSTD_d_disableHuffmanAssembly: + CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value); + dctx->disableHufAsm = value != 0; + return 0; + case ZSTD_d_maxBlockSize: + if (value != 0) CHECK_DBOUNDS(ZSTD_d_maxBlockSize, value); + dctx->maxBlockSizeParam = value; return 0; default:; } @@ -1534,13 +1948,13 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset) || (reset == ZSTD_reset_session_and_parameters) ) { dctx->streamStage = zdss_init; dctx->noForwardProgress = 0; + dctx->isFrameDecompression = 1; } if ( (reset == ZSTD_reset_parameters) || (reset == ZSTD_reset_session_and_parameters) ) { RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); ZSTD_clearDict(dctx); - dctx->format = ZSTD_f_zstd1; - dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; + ZSTD_DCtx_resetParameters(dctx); } return 0; } @@ -1551,10 +1965,17 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx) return ZSTD_sizeof_DCtx(dctx); } -size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize) +static size_t ZSTD_decodingBufferSize_internal(unsigned long long windowSize, unsigned long long frameContentSize, size_t blockSizeMax) { - size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX); - unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2); + size_t const blockSize = MIN((size_t)MIN(windowSize, ZSTD_BLOCKSIZE_MAX), blockSizeMax); + /* We need blockSize + WILDCOPY_OVERLENGTH worth of buffer so that if a block + * ends at windowSize + WILDCOPY_OVERLENGTH + 1 bytes, we can start writing + * the block at the beginning of the output buffer, and maintain a full window. + * + * We need another blockSize worth of buffer so that we can store split + * literals at the end of the block without overwriting the extDict window. + */ + unsigned long long const neededRBSize = windowSize + (blockSize * 2) + (WILDCOPY_OVERLENGTH * 2); unsigned long long const neededSize = MIN(frameContentSize, neededRBSize); size_t const minRBSize = (size_t) neededSize; RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize, @@ -1562,6 +1983,11 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long return minRBSize; } +size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize) +{ + return ZSTD_decodingBufferSize_internal(windowSize, frameContentSize, ZSTD_BLOCKSIZE_MAX); +} + size_t ZSTD_estimateDStreamSize(size_t windowSize) { size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX); @@ -1608,7 +2034,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* { ZSTD_outBuffer const expect = zds->expectedOutBuffer; /* No requirement when ZSTD_obm_stable is not enabled. */ - if (zds->outBufferMode != ZSTD_obm_stable) + if (zds->outBufferMode != ZSTD_bm_stable) return 0; /* Any buffer is allowed in zdss_init, this must be the same for every other call until * the context is reset. @@ -1618,7 +2044,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* /* The buffer must match our expectation exactly. */ if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size) return 0; - RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!"); + RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!"); } /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream() @@ -1630,7 +2056,7 @@ static size_t ZSTD_decompressContinueStream( ZSTD_DStream* zds, char** op, char* oend, void const* src, size_t srcSize) { int const isSkipFrame = ZSTD_isSkipFrame(zds); - if (zds->outBufferMode == ZSTD_obm_buffered) { + if (zds->outBufferMode == ZSTD_bm_buffered) { size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart; size_t const decodedSize = ZSTD_decompressContinue(zds, zds->outBuff + zds->outStart, dstSize, src, srcSize); @@ -1643,14 +2069,14 @@ static size_t ZSTD_decompressContinueStream( } } else { /* Write directly into the output buffer */ - size_t const dstSize = isSkipFrame ? 0 : oend - *op; + size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op); size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize); FORWARD_IF_ERROR(decodedSize, ""); *op += decodedSize; /* Flushing is not needed. */ zds->streamStage = zdss_read; assert(*op <= oend); - assert(zds->outBufferMode == ZSTD_obm_stable); + assert(zds->outBufferMode == ZSTD_bm_stable); } return 0; } @@ -1688,10 +2114,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB DEBUGLOG(5, "stage zdss_init => transparent reset "); zds->streamStage = zdss_loadHeader; zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0; +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) zds->legacyVersion = 0; +#endif zds->hostageByte = 0; zds->expectedOutBuffer = *output; - /* fall-through */ + ZSTD_FALLTHROUGH; case zdss_loadHeader : DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip)); @@ -1705,7 +2133,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } } #endif { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format); - DEBUGLOG(5, "header size : %u", (U32)hSize); + if (zds->refMultipleDDicts && zds->ddictSet) { + ZSTD_DCtx_selectFrameDDict(zds); + } if (ZSTD_isError(hSize)) { #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart); @@ -1733,14 +2163,19 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB assert(iend >= ip); if (toLoad > remainingInput) { /* not enough input to load full header */ if (remainingInput > 0) { - memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput); + ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput); zds->lhSize += remainingInput; } input->pos = input->size; - return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTDInternalConstants::ZSTD_blockHeaderSize; /* remaining header bytes + next block header */ + /* check first few bytes */ + FORWARD_IF_ERROR( + ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format), + "First few bytes detected incorrect" ); + /* return hint input size */ + return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */ } assert(ip != NULL); - memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad; + ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad; break; } } @@ -1748,14 +2183,15 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN && zds->fParams.frameType != ZSTD_skippableFrame && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) { - size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart); + size_t const cSize = ZSTD_findFrameCompressedSize_advanced(istart, (size_t)(iend-istart), zds->format); if (cSize <= (size_t)(iend-istart)) { /* shortcut : using single-pass mode */ - size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds)); + size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds)); if (ZSTD_isError(decompressedSize)) return decompressedSize; - DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()") + DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()"); + assert(istart != NULL); ip = istart + cSize; - op += decompressedSize; + op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */ zds->expected = 0; zds->streamStage = zdss_init; someMoreWork = 0; @@ -1763,7 +2199,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } } /* Check output buffer is large enough for ZSTD_odm_stable. */ - if (zds->outBufferMode == ZSTD_obm_stable + if (zds->outBufferMode == ZSTD_bm_stable && zds->fParams.frameType != ZSTD_skippableFrame && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) { @@ -1774,12 +2210,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB DEBUGLOG(4, "Consume header"); FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), ""); - if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ + if (zds->format == ZSTD_f_zstd1 + && (MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE); zds->stage = ZSTDds_skipFrame; } else { FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), ""); - zds->expected = ZSTDInternalConstants::ZSTD_blockHeaderSize; + zds->expected = ZSTD_blockHeaderSize; zds->stage = ZSTDds_decodeBlockHeader; } @@ -1790,11 +2227,13 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN); RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize, frameParameter_windowTooLarge, ""); + if (zds->maxBlockSizeParam != 0) + zds->fParams.blockSizeMax = MIN(zds->fParams.blockSizeMax, (unsigned)zds->maxBlockSizeParam); /* Adapt buffer sizes to frame header instructions */ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); - size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_obm_buffered - ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize) + size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered + ? ZSTD_decodingBufferSize_internal(zds->fParams.windowSize, zds->fParams.frameContentSize, zds->fParams.blockSizeMax) : 0; ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize); @@ -1815,10 +2254,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB bufferSize > zds->staticSize - sizeof(ZSTD_DCtx), memory_allocation, ""); } else { - ZSTD_free(zds->inBuff, zds->customMem); + ZSTD_customFree(zds->inBuff, zds->customMem); zds->inBuffSize = 0; zds->outBuffSize = 0; - zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem); + zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem); RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, ""); } zds->inBuffSize = neededInBuffSize; @@ -1826,11 +2265,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB zds->outBuffSize = neededOutBuffSize; } } } zds->streamStage = zdss_read; - /* fall-through */ + ZSTD_FALLTHROUGH; case zdss_read: DEBUGLOG(5, "stage zdss_read"); - { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip); + { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)); DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize); if (neededInSize==0) { /* end of frame */ zds->streamStage = zdss_init; @@ -1839,13 +2278,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), ""); + assert(ip != NULL); ip += neededInSize; /* Function modifies the stage so we must break */ break; } } if (ip==iend) { someMoreWork = 0; break; } /* no more input */ zds->streamStage = zdss_load; - /* fall-through */ + ZSTD_FALLTHROUGH; case zdss_load: { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds); @@ -1853,17 +2293,20 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB int const isSkipFrame = ZSTD_isSkipFrame(zds); size_t loadedSize; /* At this point we shouldn't be decompressing a block that we can stream. */ - assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip)); + assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip))); if (isSkipFrame) { loadedSize = MIN(toLoad, (size_t)(iend-ip)); } else { RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos, corruption_detected, "should never happen"); - loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip); + loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip)); + } + if (loadedSize != 0) { + /* ip may be NULL */ + ip += loadedSize; + zds->inPos += loadedSize; } - ip += loadedSize; - zds->inPos += loadedSize; if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */ /* decode loaded input */ @@ -1873,14 +2316,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB break; } case zdss_flush: - { size_t const toFlushSize = zds->outEnd - zds->outStart; - size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize); - op += flushedSize; + { + size_t const toFlushSize = zds->outEnd - zds->outStart; + size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize); + + op = op ? op + flushedSize : op; + zds->outStart += flushedSize; if (flushedSize == toFlushSize) { /* flush completed */ zds->streamStage = zdss_read; if ( (zds->outBuffSize < zds->fParams.frameContentSize) - && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) { + && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) { DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)", (int)(zds->outBuffSize - zds->outStart), (U32)zds->fParams.blockSizeMax); @@ -1894,7 +2340,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB default: assert(0); /* impossible */ - RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */ + RETURN_ERROR(GENERIC, "impossible to reach"); /* some compilers require default to do something */ } } /* result */ @@ -1907,8 +2353,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB if ((ip==istart) && (op==ostart)) { /* no forward progress */ zds->noForwardProgress ++; if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) { - RETURN_ERROR_IF(op==oend, dstSize_tooSmall, ""); - RETURN_ERROR_IF(ip==iend, srcSize_wrong, ""); + RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, ""); + RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, ""); assert(0); } } else { @@ -1933,7 +2379,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } return 1; } /* nextSrcSizeHint==0 */ - nextSrcSizeHint += ZSTDInternalConstants::ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */ + nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */ assert(zds->inPos <= nextSrcSizeHint); nextSrcSizeHint -= zds->inPos; /* part already loaded*/ return nextSrcSizeHint; @@ -1945,13 +2391,17 @@ size_t ZSTD_decompressStream_simpleArgs ( void* dst, size_t dstCapacity, size_t* dstPos, const void* src, size_t srcSize, size_t* srcPos) { - ZSTD_outBuffer output = { dst, dstCapacity, *dstPos }; - ZSTD_inBuffer input = { src, srcSize, *srcPos }; - /* ZSTD_compress_generic() will check validity of dstPos and srcPos */ - size_t const cErr = ZSTD_decompressStream(dctx, &output, &input); - *dstPos = output.pos; - *srcPos = input.pos; - return cErr; -} - + ZSTD_outBuffer output; + ZSTD_inBuffer input; + output.dst = dst; + output.size = dstCapacity; + output.pos = *dstPos; + input.src = src; + input.size = srcSize; + input.pos = *srcPos; + { size_t const cErr = ZSTD_decompressStream(dctx, &output, &input); + *dstPos = output.pos; + *srcPos = input.pos; + return cErr; + } } diff --git a/third_party/zstd/decompress/zstd_decompress_block.c b/third_party/zstd/decompress/zstd_decompress_block.c new file mode 100644 index 00000000000..76d7332e888 --- /dev/null +++ b/third_party/zstd/decompress/zstd_decompress_block.c @@ -0,0 +1,2215 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* zstd_decompress_block : + * this module takes care of decompressing _compressed_ block */ + +/*-******************************************************* +* Dependencies +*********************************************************/ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */ +#include "../common/compiler.h" /* prefetch */ +#include "../common/cpu.h" /* bmi2 */ +#include "../common/mem.h" /* low level memory routines */ +#define FSE_STATIC_LINKING_ONLY +#include "../common/fse.h" +#include "../common/huf.h" +#include "../common/zstd_internal.h" +#include "zstd_decompress_internal.h" /* ZSTD_DCtx */ +#include "zstd_ddict.h" /* ZSTD_DDictDictContent */ +#include "zstd_decompress_block.h" +#include "../common/bits.h" /* ZSTD_highbit32 */ + +/*_******************************************************* +* Macros +**********************************************************/ + +/* These two optional macros force the use one way or another of the two + * ZSTD_decompressSequences implementations. You can't force in both directions + * at the same time. + */ +#if defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \ + defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG) +#error "Cannot force the use of the short and the long ZSTD_decompressSequences variants!" +#endif + + +/*_******************************************************* +* Memory operations +**********************************************************/ +static void ZSTD_copy4(void* dst, const void* src) { ZSTD_memcpy(dst, src, 4); } + + +/*-************************************************************* + * Block decoding + ***************************************************************/ + +static size_t ZSTD_blockSizeMax(ZSTD_DCtx const* dctx) +{ + size_t const blockSizeMax = dctx->isFrameDecompression ? dctx->fParams.blockSizeMax : ZSTD_BLOCKSIZE_MAX; + assert(blockSizeMax <= ZSTD_BLOCKSIZE_MAX); + return blockSizeMax; +} + +/*! ZSTD_getcBlockSize() : + * Provides the size of compressed block from block header `src` */ +size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, + blockProperties_t* bpPtr) +{ + RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong, ""); + + { U32 const cBlockHeader = MEM_readLE24(src); + U32 const cSize = cBlockHeader >> 3; + bpPtr->lastBlock = cBlockHeader & 1; + bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3); + bpPtr->origSize = cSize; /* only useful for RLE */ + if (bpPtr->blockType == bt_rle) return 1; + RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected, ""); + return cSize; + } +} + +/* Allocate buffer for literals, either overlapping current dst, or split between dst and litExtraBuffer, or stored entirely within litExtraBuffer */ +static void ZSTD_allocateLiteralsBuffer(ZSTD_DCtx* dctx, void* const dst, const size_t dstCapacity, const size_t litSize, + const streaming_operation streaming, const size_t expectedWriteSize, const unsigned splitImmediately) +{ + size_t const blockSizeMax = ZSTD_blockSizeMax(dctx); + assert(litSize <= blockSizeMax); + assert(dctx->isFrameDecompression || streaming == not_streaming); + assert(expectedWriteSize <= blockSizeMax); + if (streaming == not_streaming && dstCapacity > blockSizeMax + WILDCOPY_OVERLENGTH + litSize + WILDCOPY_OVERLENGTH) { + /* If we aren't streaming, we can just put the literals after the output + * of the current block. We don't need to worry about overwriting the + * extDict of our window, because it doesn't exist. + * So if we have space after the end of the block, just put it there. + */ + dctx->litBuffer = (BYTE*)dst + blockSizeMax + WILDCOPY_OVERLENGTH; + dctx->litBufferEnd = dctx->litBuffer + litSize; + dctx->litBufferLocation = ZSTD_in_dst; + } else if (litSize <= ZSTD_LITBUFFEREXTRASIZE) { + /* Literals fit entirely within the extra buffer, put them there to avoid + * having to split the literals. + */ + dctx->litBuffer = dctx->litExtraBuffer; + dctx->litBufferEnd = dctx->litBuffer + litSize; + dctx->litBufferLocation = ZSTD_not_in_dst; + } else { + assert(blockSizeMax > ZSTD_LITBUFFEREXTRASIZE); + /* Literals must be split between the output block and the extra lit + * buffer. We fill the extra lit buffer with the tail of the literals, + * and put the rest of the literals at the end of the block, with + * WILDCOPY_OVERLENGTH of buffer room to allow for overreads. + * This MUST not write more than our maxBlockSize beyond dst, because in + * streaming mode, that could overwrite part of our extDict window. + */ + if (splitImmediately) { + /* won't fit in litExtraBuffer, so it will be split between end of dst and extra buffer */ + dctx->litBuffer = (BYTE*)dst + expectedWriteSize - litSize + ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH; + dctx->litBufferEnd = dctx->litBuffer + litSize - ZSTD_LITBUFFEREXTRASIZE; + } else { + /* initially this will be stored entirely in dst during huffman decoding, it will partially be shifted to litExtraBuffer after */ + dctx->litBuffer = (BYTE*)dst + expectedWriteSize - litSize; + dctx->litBufferEnd = (BYTE*)dst + expectedWriteSize; + } + dctx->litBufferLocation = ZSTD_split; + assert(dctx->litBufferEnd <= (BYTE*)dst + expectedWriteSize); + } +} + +/*! ZSTD_decodeLiteralsBlock() : + * Where it is possible to do so without being stomped by the output during decompression, the literals block will be stored + * in the dstBuffer. If there is room to do so, it will be stored in full in the excess dst space after where the current + * block will be output. Otherwise it will be stored at the end of the current dst blockspace, with a small portion being + * stored in dctx->litExtraBuffer to help keep it "ahead" of the current output write. + * + * @return : nb of bytes read from src (< srcSize ) + * note : symbol not declared but exposed for fullbench */ +static size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, + const void* src, size_t srcSize, /* note : srcSize < BLOCKSIZE */ + void* dst, size_t dstCapacity, const streaming_operation streaming) +{ + DEBUGLOG(5, "ZSTD_decodeLiteralsBlock"); + RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, ""); + + { const BYTE* const istart = (const BYTE*) src; + symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); + size_t const blockSizeMax = ZSTD_blockSizeMax(dctx); + + switch(litEncType) + { + case set_repeat: + DEBUGLOG(5, "set_repeat flag : re-using stats from previous compressed literals block"); + RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted, ""); + ZSTD_FALLTHROUGH; + + case set_compressed: + RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 2; here we need up to 5 for case 3"); + { size_t lhSize, litSize, litCSize; + U32 singleStream=0; + U32 const lhlCode = (istart[0] >> 2) & 3; + U32 const lhc = MEM_readLE32(istart); + size_t hufSuccess; + size_t expectedWriteSize = MIN(blockSizeMax, dstCapacity); + int const flags = 0 + | (ZSTD_DCtx_get_bmi2(dctx) ? HUF_flags_bmi2 : 0) + | (dctx->disableHufAsm ? HUF_flags_disableAsm : 0); + switch(lhlCode) + { + case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */ + /* 2 - 2 - 10 - 10 */ + singleStream = !lhlCode; + lhSize = 3; + litSize = (lhc >> 4) & 0x3FF; + litCSize = (lhc >> 14) & 0x3FF; + break; + case 2: + /* 2 - 2 - 14 - 14 */ + lhSize = 4; + litSize = (lhc >> 4) & 0x3FFF; + litCSize = lhc >> 18; + break; + case 3: + /* 2 - 2 - 18 - 18 */ + lhSize = 5; + litSize = (lhc >> 4) & 0x3FFFF; + litCSize = (lhc >> 22) + ((size_t)istart[4] << 10); + break; + } + RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, "NULL not handled"); + RETURN_ERROR_IF(litSize > blockSizeMax, corruption_detected, ""); + if (!singleStream) + RETURN_ERROR_IF(litSize < MIN_LITERALS_FOR_4_STREAMS, literals_headerWrong, + "Not enough literals (%zu) for the 4-streams mode (min %u)", + litSize, MIN_LITERALS_FOR_4_STREAMS); + RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, ""); + RETURN_ERROR_IF(expectedWriteSize < litSize , dstSize_tooSmall, ""); + ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 0); + + /* prefetch huffman table if cold */ + if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) { + PREFETCH_AREA(dctx->HUFptr, sizeof(dctx->entropy.hufTable)); + } + + if (litEncType==set_repeat) { + if (singleStream) { + hufSuccess = HUF_decompress1X_usingDTable( + dctx->litBuffer, litSize, istart+lhSize, litCSize, + dctx->HUFptr, flags); + } else { + assert(litSize >= MIN_LITERALS_FOR_4_STREAMS); + hufSuccess = HUF_decompress4X_usingDTable( + dctx->litBuffer, litSize, istart+lhSize, litCSize, + dctx->HUFptr, flags); + } + } else { + if (singleStream) { +#if defined(HUF_FORCE_DECOMPRESS_X2) + hufSuccess = HUF_decompress1X_DCtx_wksp( + dctx->entropy.hufTable, dctx->litBuffer, litSize, + istart+lhSize, litCSize, dctx->workspace, + sizeof(dctx->workspace), flags); +#else + hufSuccess = HUF_decompress1X1_DCtx_wksp( + dctx->entropy.hufTable, dctx->litBuffer, litSize, + istart+lhSize, litCSize, dctx->workspace, + sizeof(dctx->workspace), flags); +#endif + } else { + hufSuccess = HUF_decompress4X_hufOnly_wksp( + dctx->entropy.hufTable, dctx->litBuffer, litSize, + istart+lhSize, litCSize, dctx->workspace, + sizeof(dctx->workspace), flags); + } + } + if (dctx->litBufferLocation == ZSTD_split) + { + assert(litSize > ZSTD_LITBUFFEREXTRASIZE); + ZSTD_memcpy(dctx->litExtraBuffer, dctx->litBufferEnd - ZSTD_LITBUFFEREXTRASIZE, ZSTD_LITBUFFEREXTRASIZE); + ZSTD_memmove(dctx->litBuffer + ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH, dctx->litBuffer, litSize - ZSTD_LITBUFFEREXTRASIZE); + dctx->litBuffer += ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH; + dctx->litBufferEnd -= WILDCOPY_OVERLENGTH; + assert(dctx->litBufferEnd <= (BYTE*)dst + blockSizeMax); + } + + RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected, ""); + + dctx->litPtr = dctx->litBuffer; + dctx->litSize = litSize; + dctx->litEntropy = 1; + if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable; + return litCSize + lhSize; + } + + case set_basic: + { size_t litSize, lhSize; + U32 const lhlCode = ((istart[0]) >> 2) & 3; + size_t expectedWriteSize = MIN(blockSizeMax, dstCapacity); + switch(lhlCode) + { + case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */ + lhSize = 1; + litSize = istart[0] >> 3; + break; + case 1: + lhSize = 2; + litSize = MEM_readLE16(istart) >> 4; + break; + case 3: + lhSize = 3; + RETURN_ERROR_IF(srcSize<3, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 2; here we need lhSize = 3"); + litSize = MEM_readLE24(istart) >> 4; + break; + } + + RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, "NULL not handled"); + RETURN_ERROR_IF(litSize > blockSizeMax, corruption_detected, ""); + RETURN_ERROR_IF(expectedWriteSize < litSize, dstSize_tooSmall, ""); + ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 1); + if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */ + RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, ""); + if (dctx->litBufferLocation == ZSTD_split) + { + ZSTD_memcpy(dctx->litBuffer, istart + lhSize, litSize - ZSTD_LITBUFFEREXTRASIZE); + ZSTD_memcpy(dctx->litExtraBuffer, istart + lhSize + litSize - ZSTD_LITBUFFEREXTRASIZE, ZSTD_LITBUFFEREXTRASIZE); + } + else + { + ZSTD_memcpy(dctx->litBuffer, istart + lhSize, litSize); + } + dctx->litPtr = dctx->litBuffer; + dctx->litSize = litSize; + return lhSize+litSize; + } + /* direct reference into compressed stream */ + dctx->litPtr = istart+lhSize; + dctx->litSize = litSize; + dctx->litBufferEnd = dctx->litPtr + litSize; + dctx->litBufferLocation = ZSTD_not_in_dst; + return lhSize+litSize; + } + + case set_rle: + { U32 const lhlCode = ((istart[0]) >> 2) & 3; + size_t litSize, lhSize; + size_t expectedWriteSize = MIN(blockSizeMax, dstCapacity); + switch(lhlCode) + { + case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */ + lhSize = 1; + litSize = istart[0] >> 3; + break; + case 1: + lhSize = 2; + RETURN_ERROR_IF(srcSize<3, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 2; here we need lhSize+1 = 3"); + litSize = MEM_readLE16(istart) >> 4; + break; + case 3: + lhSize = 3; + RETURN_ERROR_IF(srcSize<4, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 2; here we need lhSize+1 = 4"); + litSize = MEM_readLE24(istart) >> 4; + break; + } + RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, "NULL not handled"); + RETURN_ERROR_IF(litSize > blockSizeMax, corruption_detected, ""); + RETURN_ERROR_IF(expectedWriteSize < litSize, dstSize_tooSmall, ""); + ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 1); + if (dctx->litBufferLocation == ZSTD_split) + { + ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize - ZSTD_LITBUFFEREXTRASIZE); + ZSTD_memset(dctx->litExtraBuffer, istart[lhSize], ZSTD_LITBUFFEREXTRASIZE); + } + else + { + ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize); + } + dctx->litPtr = dctx->litBuffer; + dctx->litSize = litSize; + return lhSize+1; + } + default: + RETURN_ERROR(corruption_detected, "impossible"); + } + } +} + +/* Hidden declaration for fullbench */ +size_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx, + const void* src, size_t srcSize, + void* dst, size_t dstCapacity); +size_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx, + const void* src, size_t srcSize, + void* dst, size_t dstCapacity) +{ + dctx->isFrameDecompression = 0; + return ZSTD_decodeLiteralsBlock(dctx, src, srcSize, dst, dstCapacity, not_streaming); +} + +/* Default FSE distribution tables. + * These are pre-calculated FSE decoding tables using default distributions as defined in specification : + * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#default-distributions + * They were generated programmatically with following method : + * - start from default distributions, present in /lib/common/zstd_internal.h + * - generate tables normally, using ZSTD_buildFSETable() + * - printout the content of tables + * - pretify output, report below, test with fuzzer to ensure it's correct */ + +/* Default FSE distribution table for Literal Lengths */ +static const ZSTD_seqSymbol LL_defaultDTable[(1<tableLog = 0; + DTableH->fastMode = 0; + + cell->nbBits = 0; + cell->nextState = 0; + assert(nbAddBits < 255); + cell->nbAdditionalBits = nbAddBits; + cell->baseValue = baseValue; +} + + +/* ZSTD_buildFSETable() : + * generate FSE decoding table for one symbol (ll, ml or off) + * cannot fail if input is valid => + * all inputs are presumed validated at this stage */ +FORCE_INLINE_TEMPLATE +void ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt, + const short* normalizedCounter, unsigned maxSymbolValue, + const U32* baseValue, const U8* nbAdditionalBits, + unsigned tableLog, void* wksp, size_t wkspSize) +{ + ZSTD_seqSymbol* const tableDecode = dt+1; + U32 const maxSV1 = maxSymbolValue + 1; + U32 const tableSize = 1 << tableLog; + + U16* symbolNext = (U16*)wksp; + BYTE* spread = (BYTE*)(symbolNext + MaxSeq + 1); + U32 highThreshold = tableSize - 1; + + + /* Sanity Checks */ + assert(maxSymbolValue <= MaxSeq); + assert(tableLog <= MaxFSELog); + assert(wkspSize >= ZSTD_BUILD_FSE_TABLE_WKSP_SIZE); + (void)wkspSize; + /* Init, lay down lowprob symbols */ + { ZSTD_seqSymbol_header DTableH; + DTableH.tableLog = tableLog; + DTableH.fastMode = 1; + { S16 const largeLimit= (S16)(1 << (tableLog-1)); + U32 s; + for (s=0; s= largeLimit) DTableH.fastMode=0; + assert(normalizedCounter[s]>=0); + symbolNext[s] = (U16)normalizedCounter[s]; + } } } + ZSTD_memcpy(dt, &DTableH, sizeof(DTableH)); + } + + /* Spread symbols */ + assert(tableSize <= 512); + /* Specialized symbol spreading for the case when there are + * no low probability (-1 count) symbols. When compressing + * small blocks we avoid low probability symbols to hit this + * case, since header decoding speed matters more. + */ + if (highThreshold == tableSize - 1) { + size_t const tableMask = tableSize-1; + size_t const step = FSE_TABLESTEP(tableSize); + /* First lay down the symbols in order. + * We use a uint64_t to lay down 8 bytes at a time. This reduces branch + * misses since small blocks generally have small table logs, so nearly + * all symbols have counts <= 8. We ensure we have 8 bytes at the end of + * our buffer to handle the over-write. + */ + { + U64 const add = 0x0101010101010101ull; + size_t pos = 0; + U64 sv = 0; + U32 s; + for (s=0; s=0); + pos += (size_t)n; + } + } + /* Now we spread those positions across the table. + * The benefit of doing it in two stages is that we avoid the + * variable size inner loop, which caused lots of branch misses. + * Now we can run through all the positions without any branch misses. + * We unroll the loop twice, since that is what empirically worked best. + */ + { + size_t position = 0; + size_t s; + size_t const unroll = 2; + assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */ + for (s = 0; s < (size_t)tableSize; s += unroll) { + size_t u; + for (u = 0; u < unroll; ++u) { + size_t const uPosition = (position + (u * step)) & tableMask; + tableDecode[uPosition].baseValue = spread[s + u]; + } + position = (position + (unroll * step)) & tableMask; + } + assert(position == 0); + } + } else { + U32 const tableMask = tableSize-1; + U32 const step = FSE_TABLESTEP(tableSize); + U32 s, position = 0; + for (s=0; s highThreshold)) position = (position + step) & tableMask; /* lowprob area */ + } } + assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ + } + + /* Build Decoding table */ + { + U32 u; + for (u=0; u max, corruption_detected, ""); + { U32 const symbol = *(const BYTE*)src; + U32 const baseline = baseValue[symbol]; + U8 const nbBits = nbAdditionalBits[symbol]; + ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits); + } + *DTablePtr = DTableSpace; + return 1; + case set_basic : + *DTablePtr = defaultTable; + return 0; + case set_repeat: + RETURN_ERROR_IF(!flagRepeatTable, corruption_detected, ""); + /* prefetch FSE table if used */ + if (ddictIsCold && (nbSeq > 24 /* heuristic */)) { + const void* const pStart = *DTablePtr; + size_t const pSize = sizeof(ZSTD_seqSymbol) * (SEQSYMBOL_TABLE_SIZE(maxLog)); + PREFETCH_AREA(pStart, pSize); + } + return 0; + case set_compressed : + { unsigned tableLog; + S16 norm[MaxSeq+1]; + size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize); + RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected, ""); + RETURN_ERROR_IF(tableLog > maxLog, corruption_detected, ""); + ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog, wksp, wkspSize, bmi2); + *DTablePtr = DTableSpace; + return headerSize; + } + default : + assert(0); + RETURN_ERROR(GENERIC, "impossible"); + } +} + +size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, + const void* src, size_t srcSize) +{ + const BYTE* const istart = (const BYTE*)src; + const BYTE* const iend = istart + srcSize; + const BYTE* ip = istart; + int nbSeq; + DEBUGLOG(5, "ZSTD_decodeSeqHeaders"); + + /* check */ + RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong, ""); + + /* SeqHead */ + nbSeq = *ip++; + if (nbSeq > 0x7F) { + if (nbSeq == 0xFF) { + RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong, ""); + nbSeq = MEM_readLE16(ip) + LONGNBSEQ; + ip+=2; + } else { + RETURN_ERROR_IF(ip >= iend, srcSize_wrong, ""); + nbSeq = ((nbSeq-0x80)<<8) + *ip++; + } + } + *nbSeqPtr = nbSeq; + + if (nbSeq == 0) { + /* No sequence : section ends immediately */ + RETURN_ERROR_IF(ip != iend, corruption_detected, + "extraneous data present in the Sequences section"); + return (size_t)(ip - istart); + } + + /* FSE table descriptors */ + RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong, ""); /* minimum possible size: 1 byte for symbol encoding types */ + RETURN_ERROR_IF(*ip & 3, corruption_detected, ""); /* The last field, Reserved, must be all-zeroes. */ + { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6); + symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3); + symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3); + ip++; + + /* Build DTables */ + { size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr, + LLtype, MaxLL, LLFSELog, + ip, iend-ip, + LL_base, LL_bits, + LL_defaultDTable, dctx->fseEntropy, + dctx->ddictIsCold, nbSeq, + dctx->workspace, sizeof(dctx->workspace), + ZSTD_DCtx_get_bmi2(dctx)); + RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, "ZSTD_buildSeqTable failed"); + ip += llhSize; + } + + { size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr, + OFtype, MaxOff, OffFSELog, + ip, iend-ip, + OF_base, OF_bits, + OF_defaultDTable, dctx->fseEntropy, + dctx->ddictIsCold, nbSeq, + dctx->workspace, sizeof(dctx->workspace), + ZSTD_DCtx_get_bmi2(dctx)); + RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, "ZSTD_buildSeqTable failed"); + ip += ofhSize; + } + + { size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr, + MLtype, MaxML, MLFSELog, + ip, iend-ip, + ML_base, ML_bits, + ML_defaultDTable, dctx->fseEntropy, + dctx->ddictIsCold, nbSeq, + dctx->workspace, sizeof(dctx->workspace), + ZSTD_DCtx_get_bmi2(dctx)); + RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, "ZSTD_buildSeqTable failed"); + ip += mlhSize; + } + } + + return ip-istart; +} + + +typedef struct { + size_t litLength; + size_t matchLength; + size_t offset; +} seq_t; + +typedef struct { + size_t state; + const ZSTD_seqSymbol* table; +} ZSTD_fseState; + +typedef struct { + BIT_DStream_t DStream; + ZSTD_fseState stateLL; + ZSTD_fseState stateOffb; + ZSTD_fseState stateML; + size_t prevOffset[ZSTD_REP_NUM]; +} seqState_t; + +/*! ZSTD_overlapCopy8() : + * Copies 8 bytes from ip to op and updates op and ip where ip <= op. + * If the offset is < 8 then the offset is spread to at least 8 bytes. + * + * Precondition: *ip <= *op + * Postcondition: *op - *op >= 8 + */ +HINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset) { + assert(*ip <= *op); + if (offset < 8) { + /* close range match, overlap */ + static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */ + static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */ + int const sub2 = dec64table[offset]; + (*op)[0] = (*ip)[0]; + (*op)[1] = (*ip)[1]; + (*op)[2] = (*ip)[2]; + (*op)[3] = (*ip)[3]; + *ip += dec32table[offset]; + ZSTD_copy4(*op+4, *ip); + *ip -= sub2; + } else { + ZSTD_copy8(*op, *ip); + } + *ip += 8; + *op += 8; + assert(*op - *ip >= 8); +} + +/*! ZSTD_safecopy() : + * Specialized version of memcpy() that is allowed to READ up to WILDCOPY_OVERLENGTH past the input buffer + * and write up to 16 bytes past oend_w (op >= oend_w is allowed). + * This function is only called in the uncommon case where the sequence is near the end of the block. It + * should be fast for a single long sequence, but can be slow for several short sequences. + * + * @param ovtype controls the overlap detection + * - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart. + * - ZSTD_overlap_src_before_dst: The src and dst may overlap and may be any distance apart. + * The src buffer must be before the dst buffer. + */ +static void ZSTD_safecopy(BYTE* op, const BYTE* const oend_w, BYTE const* ip, ptrdiff_t length, ZSTD_overlap_e ovtype) { + ptrdiff_t const diff = op - ip; + BYTE* const oend = op + length; + + assert((ovtype == ZSTD_no_overlap && (diff <= -8 || diff >= 8 || op >= oend_w)) || + (ovtype == ZSTD_overlap_src_before_dst && diff >= 0)); + + if (length < 8) { + /* Handle short lengths. */ + while (op < oend) *op++ = *ip++; + return; + } + if (ovtype == ZSTD_overlap_src_before_dst) { + /* Copy 8 bytes and ensure the offset >= 8 when there can be overlap. */ + assert(length >= 8); + ZSTD_overlapCopy8(&op, &ip, diff); + length -= 8; + assert(op - ip >= 8); + assert(op <= oend); + } + + if (oend <= oend_w) { + /* No risk of overwrite. */ + ZSTD_wildcopy(op, ip, length, ovtype); + return; + } + if (op <= oend_w) { + /* Wildcopy until we get close to the end. */ + assert(oend > oend_w); + ZSTD_wildcopy(op, ip, oend_w - op, ovtype); + ip += oend_w - op; + op += oend_w - op; + } + /* Handle the leftovers. */ + while (op < oend) *op++ = *ip++; +} + +/* ZSTD_safecopyDstBeforeSrc(): + * This version allows overlap with dst before src, or handles the non-overlap case with dst after src + * Kept separate from more common ZSTD_safecopy case to avoid performance impact to the safecopy common case */ +static void ZSTD_safecopyDstBeforeSrc(BYTE* op, const BYTE* ip, ptrdiff_t length) { + ptrdiff_t const diff = op - ip; + BYTE* const oend = op + length; + + if (length < 8 || diff > -8) { + /* Handle short lengths, close overlaps, and dst not before src. */ + while (op < oend) *op++ = *ip++; + return; + } + + if (op <= oend - WILDCOPY_OVERLENGTH && diff < -WILDCOPY_VECLEN) { + ZSTD_wildcopy(op, ip, oend - WILDCOPY_OVERLENGTH - op, ZSTD_no_overlap); + ip += oend - WILDCOPY_OVERLENGTH - op; + op += oend - WILDCOPY_OVERLENGTH - op; + } + + /* Handle the leftovers. */ + while (op < oend) *op++ = *ip++; +} + +/* ZSTD_execSequenceEnd(): + * This version handles cases that are near the end of the output buffer. It requires + * more careful checks to make sure there is no overflow. By separating out these hard + * and unlikely cases, we can speed up the common cases. + * + * NOTE: This function needs to be fast for a single long sequence, but doesn't need + * to be optimized for many small sequences, since those fall into ZSTD_execSequence(). + */ +FORCE_NOINLINE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_execSequenceEnd(BYTE* op, + BYTE* const oend, seq_t sequence, + const BYTE** litPtr, const BYTE* const litLimit, + const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd) +{ + BYTE* const oLitEnd = op + sequence.litLength; + size_t const sequenceLength = sequence.litLength + sequence.matchLength; + const BYTE* const iLitEnd = *litPtr + sequence.litLength; + const BYTE* match = oLitEnd - sequence.offset; + BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; + + /* bounds checks : careful of address space overflow in 32-bit mode */ + RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, "last match must fit within dstBuffer"); + RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, "try to read beyond literal buffer"); + assert(op < op + sequenceLength); + assert(oLitEnd < op + sequenceLength); + + /* copy literals */ + ZSTD_safecopy(op, oend_w, *litPtr, sequence.litLength, ZSTD_no_overlap); + op = oLitEnd; + *litPtr = iLitEnd; + + /* copy Match */ + if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { + /* offset beyond prefix */ + RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, ""); + match = dictEnd - (prefixStart - match); + if (match + sequence.matchLength <= dictEnd) { + ZSTD_memmove(oLitEnd, match, sequence.matchLength); + return sequenceLength; + } + /* span extDict & currentPrefixSegment */ + { size_t const length1 = dictEnd - match; + ZSTD_memmove(oLitEnd, match, length1); + op = oLitEnd + length1; + sequence.matchLength -= length1; + match = prefixStart; + } + } + ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst); + return sequenceLength; +} + +/* ZSTD_execSequenceEndSplitLitBuffer(): + * This version is intended to be used during instances where the litBuffer is still split. It is kept separate to avoid performance impact for the good case. + */ +FORCE_NOINLINE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_execSequenceEndSplitLitBuffer(BYTE* op, + BYTE* const oend, const BYTE* const oend_w, seq_t sequence, + const BYTE** litPtr, const BYTE* const litLimit, + const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd) +{ + BYTE* const oLitEnd = op + sequence.litLength; + size_t const sequenceLength = sequence.litLength + sequence.matchLength; + const BYTE* const iLitEnd = *litPtr + sequence.litLength; + const BYTE* match = oLitEnd - sequence.offset; + + + /* bounds checks : careful of address space overflow in 32-bit mode */ + RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, "last match must fit within dstBuffer"); + RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, "try to read beyond literal buffer"); + assert(op < op + sequenceLength); + assert(oLitEnd < op + sequenceLength); + + /* copy literals */ + RETURN_ERROR_IF(op > *litPtr && op < *litPtr + sequence.litLength, dstSize_tooSmall, "output should not catch up to and overwrite literal buffer"); + ZSTD_safecopyDstBeforeSrc(op, *litPtr, sequence.litLength); + op = oLitEnd; + *litPtr = iLitEnd; + + /* copy Match */ + if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { + /* offset beyond prefix */ + RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, ""); + match = dictEnd - (prefixStart - match); + if (match + sequence.matchLength <= dictEnd) { + ZSTD_memmove(oLitEnd, match, sequence.matchLength); + return sequenceLength; + } + /* span extDict & currentPrefixSegment */ + { size_t const length1 = dictEnd - match; + ZSTD_memmove(oLitEnd, match, length1); + op = oLitEnd + length1; + sequence.matchLength -= length1; + match = prefixStart; + } + } + ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst); + return sequenceLength; +} + +HINT_INLINE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_execSequence(BYTE* op, + BYTE* const oend, seq_t sequence, + const BYTE** litPtr, const BYTE* const litLimit, + const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd) +{ + BYTE* const oLitEnd = op + sequence.litLength; + size_t const sequenceLength = sequence.litLength + sequence.matchLength; + BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ + BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; /* risk : address space underflow on oend=NULL */ + const BYTE* const iLitEnd = *litPtr + sequence.litLength; + const BYTE* match = oLitEnd - sequence.offset; + + assert(op != NULL /* Precondition */); + assert(oend_w < oend /* No underflow */); + +#if defined(__aarch64__) + /* prefetch sequence starting from match that will be used for copy later */ + PREFETCH_L1(match); +#endif + /* Handle edge cases in a slow path: + * - Read beyond end of literals + * - Match end is within WILDCOPY_OVERLIMIT of oend + * - 32-bit mode and the match length overflows + */ + if (UNLIKELY( + iLitEnd > litLimit || + oMatchEnd > oend_w || + (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH))) + return ZSTD_execSequenceEnd(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd); + + /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */ + assert(op <= oLitEnd /* No overflow */); + assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */); + assert(oMatchEnd <= oend /* No underflow */); + assert(iLitEnd <= litLimit /* Literal length is in bounds */); + assert(oLitEnd <= oend_w /* Can wildcopy literals */); + assert(oMatchEnd <= oend_w /* Can wildcopy matches */); + + /* Copy Literals: + * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9. + * We likely don't need the full 32-byte wildcopy. + */ + assert(WILDCOPY_OVERLENGTH >= 16); + ZSTD_copy16(op, (*litPtr)); + if (UNLIKELY(sequence.litLength > 16)) { + ZSTD_wildcopy(op + 16, (*litPtr) + 16, sequence.litLength - 16, ZSTD_no_overlap); + } + op = oLitEnd; + *litPtr = iLitEnd; /* update for next sequence */ + + /* Copy Match */ + if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { + /* offset beyond prefix -> go into extDict */ + RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, ""); + match = dictEnd + (match - prefixStart); + if (match + sequence.matchLength <= dictEnd) { + ZSTD_memmove(oLitEnd, match, sequence.matchLength); + return sequenceLength; + } + /* span extDict & currentPrefixSegment */ + { size_t const length1 = dictEnd - match; + ZSTD_memmove(oLitEnd, match, length1); + op = oLitEnd + length1; + sequence.matchLength -= length1; + match = prefixStart; + } + } + /* Match within prefix of 1 or more bytes */ + assert(op <= oMatchEnd); + assert(oMatchEnd <= oend_w); + assert(match >= prefixStart); + assert(sequence.matchLength >= 1); + + /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy + * without overlap checking. + */ + if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) { + /* We bet on a full wildcopy for matches, since we expect matches to be + * longer than literals (in general). In silesia, ~10% of matches are longer + * than 16 bytes. + */ + ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap); + return sequenceLength; + } + assert(sequence.offset < WILDCOPY_VECLEN); + + /* Copy 8 bytes and spread the offset to be >= 8. */ + ZSTD_overlapCopy8(&op, &match, sequence.offset); + + /* If the match length is > 8 bytes, then continue with the wildcopy. */ + if (sequence.matchLength > 8) { + assert(op < oMatchEnd); + ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8, ZSTD_overlap_src_before_dst); + } + return sequenceLength; +} + +HINT_INLINE +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +size_t ZSTD_execSequenceSplitLitBuffer(BYTE* op, + BYTE* const oend, const BYTE* const oend_w, seq_t sequence, + const BYTE** litPtr, const BYTE* const litLimit, + const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd) +{ + BYTE* const oLitEnd = op + sequence.litLength; + size_t const sequenceLength = sequence.litLength + sequence.matchLength; + BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ + const BYTE* const iLitEnd = *litPtr + sequence.litLength; + const BYTE* match = oLitEnd - sequence.offset; + + assert(op != NULL /* Precondition */); + assert(oend_w < oend /* No underflow */); + /* Handle edge cases in a slow path: + * - Read beyond end of literals + * - Match end is within WILDCOPY_OVERLIMIT of oend + * - 32-bit mode and the match length overflows + */ + if (UNLIKELY( + iLitEnd > litLimit || + oMatchEnd > oend_w || + (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH))) + return ZSTD_execSequenceEndSplitLitBuffer(op, oend, oend_w, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd); + + /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */ + assert(op <= oLitEnd /* No overflow */); + assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */); + assert(oMatchEnd <= oend /* No underflow */); + assert(iLitEnd <= litLimit /* Literal length is in bounds */); + assert(oLitEnd <= oend_w /* Can wildcopy literals */); + assert(oMatchEnd <= oend_w /* Can wildcopy matches */); + + /* Copy Literals: + * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9. + * We likely don't need the full 32-byte wildcopy. + */ + assert(WILDCOPY_OVERLENGTH >= 16); + ZSTD_copy16(op, (*litPtr)); + if (UNLIKELY(sequence.litLength > 16)) { + ZSTD_wildcopy(op+16, (*litPtr)+16, sequence.litLength-16, ZSTD_no_overlap); + } + op = oLitEnd; + *litPtr = iLitEnd; /* update for next sequence */ + + /* Copy Match */ + if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { + /* offset beyond prefix -> go into extDict */ + RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, ""); + match = dictEnd + (match - prefixStart); + if (match + sequence.matchLength <= dictEnd) { + ZSTD_memmove(oLitEnd, match, sequence.matchLength); + return sequenceLength; + } + /* span extDict & currentPrefixSegment */ + { size_t const length1 = dictEnd - match; + ZSTD_memmove(oLitEnd, match, length1); + op = oLitEnd + length1; + sequence.matchLength -= length1; + match = prefixStart; + } } + /* Match within prefix of 1 or more bytes */ + assert(op <= oMatchEnd); + assert(oMatchEnd <= oend_w); + assert(match >= prefixStart); + assert(sequence.matchLength >= 1); + + /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy + * without overlap checking. + */ + if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) { + /* We bet on a full wildcopy for matches, since we expect matches to be + * longer than literals (in general). In silesia, ~10% of matches are longer + * than 16 bytes. + */ + ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap); + return sequenceLength; + } + assert(sequence.offset < WILDCOPY_VECLEN); + + /* Copy 8 bytes and spread the offset to be >= 8. */ + ZSTD_overlapCopy8(&op, &match, sequence.offset); + + /* If the match length is > 8 bytes, then continue with the wildcopy. */ + if (sequence.matchLength > 8) { + assert(op < oMatchEnd); + ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8, ZSTD_overlap_src_before_dst); + } + return sequenceLength; +} + + +static void +ZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt) +{ + const void* ptr = dt; + const ZSTD_seqSymbol_header* const DTableH = (const ZSTD_seqSymbol_header*)ptr; + DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); + DEBUGLOG(6, "ZSTD_initFseState : val=%u using %u bits", + (U32)DStatePtr->state, DTableH->tableLog); + BIT_reloadDStream(bitD); + DStatePtr->table = dt + 1; +} + +FORCE_INLINE_TEMPLATE void +ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, U16 nextState, U32 nbBits) +{ + size_t const lowBits = BIT_readBits(bitD, nbBits); + DStatePtr->state = nextState + lowBits; +} + +/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum + * offset bits. But we can only read at most STREAM_ACCUMULATOR_MIN_32 + * bits before reloading. This value is the maximum number of bytes we read + * after reloading when we are decoding long offsets. + */ +#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \ + (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \ + ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \ + : 0) + +typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e; + +/** + * ZSTD_decodeSequence(): + * @p longOffsets : tells the decoder to reload more bit while decoding large offsets + * only used in 32-bit mode + * @return : Sequence (litL + matchL + offset) + */ +FORCE_INLINE_TEMPLATE seq_t +ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const int isLastSeq) +{ + seq_t seq; + /* + * ZSTD_seqSymbol is a 64 bits wide structure. + * It can be loaded in one operation + * and its fields extracted by simply shifting or bit-extracting on aarch64. + * GCC doesn't recognize this and generates more unnecessary ldr/ldrb/ldrh + * operations that cause performance drop. This can be avoided by using this + * ZSTD_memcpy hack. + */ +#if defined(__aarch64__) && (defined(__GNUC__) && !defined(__clang__)) + ZSTD_seqSymbol llDInfoS, mlDInfoS, ofDInfoS; + ZSTD_seqSymbol* const llDInfo = &llDInfoS; + ZSTD_seqSymbol* const mlDInfo = &mlDInfoS; + ZSTD_seqSymbol* const ofDInfo = &ofDInfoS; + ZSTD_memcpy(llDInfo, seqState->stateLL.table + seqState->stateLL.state, sizeof(ZSTD_seqSymbol)); + ZSTD_memcpy(mlDInfo, seqState->stateML.table + seqState->stateML.state, sizeof(ZSTD_seqSymbol)); + ZSTD_memcpy(ofDInfo, seqState->stateOffb.table + seqState->stateOffb.state, sizeof(ZSTD_seqSymbol)); +#else + const ZSTD_seqSymbol* const llDInfo = seqState->stateLL.table + seqState->stateLL.state; + const ZSTD_seqSymbol* const mlDInfo = seqState->stateML.table + seqState->stateML.state; + const ZSTD_seqSymbol* const ofDInfo = seqState->stateOffb.table + seqState->stateOffb.state; +#endif + seq.matchLength = mlDInfo->baseValue; + seq.litLength = llDInfo->baseValue; + { U32 const ofBase = ofDInfo->baseValue; + BYTE const llBits = llDInfo->nbAdditionalBits; + BYTE const mlBits = mlDInfo->nbAdditionalBits; + BYTE const ofBits = ofDInfo->nbAdditionalBits; + BYTE const totalBits = llBits+mlBits+ofBits; + + U16 const llNext = llDInfo->nextState; + U16 const mlNext = mlDInfo->nextState; + U16 const ofNext = ofDInfo->nextState; + U32 const llnbBits = llDInfo->nbBits; + U32 const mlnbBits = mlDInfo->nbBits; + U32 const ofnbBits = ofDInfo->nbBits; + + assert(llBits <= MaxLLBits); + assert(mlBits <= MaxMLBits); + assert(ofBits <= MaxOff); + /* + * As gcc has better branch and block analyzers, sometimes it is only + * valuable to mark likeliness for clang, it gives around 3-4% of + * performance. + */ + + /* sequence */ + { size_t offset; + if (ofBits > 1) { + ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1); + ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5); + ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 > LONG_OFFSETS_MAX_EXTRA_BITS_32); + ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 - LONG_OFFSETS_MAX_EXTRA_BITS_32 >= MaxMLBits); + if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) { + /* Always read extra bits, this keeps the logic simple, + * avoids branches, and avoids accidentally reading 0 bits. + */ + U32 const extraBits = LONG_OFFSETS_MAX_EXTRA_BITS_32; + offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits); + BIT_reloadDStream(&seqState->DStream); + offset += BIT_readBitsFast(&seqState->DStream, extraBits); + } else { + offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */ + if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); + } + seqState->prevOffset[2] = seqState->prevOffset[1]; + seqState->prevOffset[1] = seqState->prevOffset[0]; + seqState->prevOffset[0] = offset; + } else { + U32 const ll0 = (llDInfo->baseValue == 0); + if (LIKELY((ofBits == 0))) { + offset = seqState->prevOffset[ll0]; + seqState->prevOffset[1] = seqState->prevOffset[!ll0]; + seqState->prevOffset[0] = offset; + } else { + offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1); + { size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; + temp -= !temp; /* 0 is not valid: input corrupted => force offset to -1 => corruption detected at execSequence */ + if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1]; + seqState->prevOffset[1] = seqState->prevOffset[0]; + seqState->prevOffset[0] = offset = temp; + } } } + seq.offset = offset; + } + + if (mlBits > 0) + seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/); + + if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32)) + BIT_reloadDStream(&seqState->DStream); + if (MEM_64bits() && UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog))) + BIT_reloadDStream(&seqState->DStream); + /* Ensure there are enough bits to read the rest of data in 64-bit mode. */ + ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64); + + if (llBits > 0) + seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/); + + if (MEM_32bits()) + BIT_reloadDStream(&seqState->DStream); + + DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u", + (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset); + + if (!isLastSeq) { + /* don't update FSE state for last Sequence */ + ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llNext, llnbBits); /* <= 9 bits */ + ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlNext, mlnbBits); /* <= 9 bits */ + if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ + ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofNext, ofnbBits); /* <= 8 bits */ + BIT_reloadDStream(&seqState->DStream); + } + } + + return seq; +} + +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) +#if DEBUGLEVEL >= 1 +static int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd) +{ + size_t const windowSize = dctx->fParams.windowSize; + /* No dictionary used. */ + if (dctx->dictContentEndForFuzzing == NULL) return 0; + /* Dictionary is our prefix. */ + if (prefixStart == dctx->dictContentBeginForFuzzing) return 1; + /* Dictionary is not our ext-dict. */ + if (dctx->dictEnd != dctx->dictContentEndForFuzzing) return 0; + /* Dictionary is not within our window size. */ + if ((size_t)(oLitEnd - prefixStart) >= windowSize) return 0; + /* Dictionary is active. */ + return 1; +} +#endif + +static void ZSTD_assertValidSequence( + ZSTD_DCtx const* dctx, + BYTE const* op, BYTE const* oend, + seq_t const seq, + BYTE const* prefixStart, BYTE const* virtualStart) +{ +#if DEBUGLEVEL >= 1 + if (dctx->isFrameDecompression) { + size_t const windowSize = dctx->fParams.windowSize; + size_t const sequenceSize = seq.litLength + seq.matchLength; + BYTE const* const oLitEnd = op + seq.litLength; + DEBUGLOG(6, "Checking sequence: litL=%u matchL=%u offset=%u", + (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset); + assert(op <= oend); + assert((size_t)(oend - op) >= sequenceSize); + assert(sequenceSize <= ZSTD_blockSizeMax(dctx)); + if (ZSTD_dictionaryIsActive(dctx, prefixStart, oLitEnd)) { + size_t const dictSize = (size_t)((char const*)dctx->dictContentEndForFuzzing - (char const*)dctx->dictContentBeginForFuzzing); + /* Offset must be within the dictionary. */ + assert(seq.offset <= (size_t)(oLitEnd - virtualStart)); + assert(seq.offset <= windowSize + dictSize); + } else { + /* Offset must be within our window. */ + assert(seq.offset <= windowSize); + } + } +#else + (void)dctx, (void)op, (void)oend, (void)seq, (void)prefixStart, (void)virtualStart; +#endif +} +#endif + +#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG + + +FORCE_INLINE_TEMPLATE size_t +DONT_VECTORIZE +ZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + const BYTE* ip = (const BYTE*)seqStart; + const BYTE* const iend = ip + seqSize; + BYTE* const ostart = (BYTE*)dst; + BYTE* const oend = ZSTD_maybeNullPtrAdd(ostart, maxDstSize); + BYTE* op = ostart; + const BYTE* litPtr = dctx->litPtr; + const BYTE* litBufferEnd = dctx->litBufferEnd; + const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart); + const BYTE* const vBase = (const BYTE*) (dctx->virtualStart); + const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); + DEBUGLOG(5, "ZSTD_decompressSequences_bodySplitLitBuffer (%i seqs)", nbSeq); + + /* Literals are split between internal buffer & output buffer */ + if (nbSeq) { + seqState_t seqState; + dctx->fseEntropy = 1; + { U32 i; for (i=0; ientropy.rep[i]; } + RETURN_ERROR_IF( + ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)), + corruption_detected, ""); + ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); + ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); + ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); + assert(dst != NULL); + + ZSTD_STATIC_ASSERT( + BIT_DStream_unfinished < BIT_DStream_completed && + BIT_DStream_endOfBuffer < BIT_DStream_completed && + BIT_DStream_completed < BIT_DStream_overflow); + + /* decompress without overrunning litPtr begins */ + { seq_t sequence = {0,0,0}; /* some static analyzer believe that @sequence is not initialized (it necessarily is, since for(;;) loop as at least one iteration) */ + /* Align the decompression loop to 32 + 16 bytes. + * + * zstd compiled with gcc-9 on an Intel i9-9900k shows 10% decompression + * speed swings based on the alignment of the decompression loop. This + * performance swing is caused by parts of the decompression loop falling + * out of the DSB. The entire decompression loop should fit in the DSB, + * when it can't we get much worse performance. You can measure if you've + * hit the good case or the bad case with this perf command for some + * compressed file test.zst: + * + * perf stat -e cycles -e instructions -e idq.all_dsb_cycles_any_uops \ + * -e idq.all_mite_cycles_any_uops -- ./zstd -tq test.zst + * + * If you see most cycles served out of the MITE you've hit the bad case. + * If you see most cycles served out of the DSB you've hit the good case. + * If it is pretty even then you may be in an okay case. + * + * This issue has been reproduced on the following CPUs: + * - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9 + * Use Instruments->Counters to get DSB/MITE cycles. + * I never got performance swings, but I was able to + * go from the good case of mostly DSB to half of the + * cycles served from MITE. + * - Coffeelake: Intel i9-9900k + * - Coffeelake: Intel i7-9700k + * + * I haven't been able to reproduce the instability or DSB misses on any + * of the following CPUS: + * - Haswell + * - Broadwell: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GH + * - Skylake + * + * Alignment is done for each of the three major decompression loops: + * - ZSTD_decompressSequences_bodySplitLitBuffer - presplit section of the literal buffer + * - ZSTD_decompressSequences_bodySplitLitBuffer - postsplit section of the literal buffer + * - ZSTD_decompressSequences_body + * Alignment choices are made to minimize large swings on bad cases and influence on performance + * from changes external to this code, rather than to overoptimize on the current commit. + * + * If you are seeing performance stability this script can help test. + * It tests on 4 commits in zstd where I saw performance change. + * + * https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4 + */ +#if defined(__GNUC__) && defined(__x86_64__) + __asm__(".p2align 6"); +# if __GNUC__ >= 7 + /* good for gcc-7, gcc-9, and gcc-11 */ + __asm__("nop"); + __asm__(".p2align 5"); + __asm__("nop"); + __asm__(".p2align 4"); +# if __GNUC__ == 8 || __GNUC__ == 10 + /* good for gcc-8 and gcc-10 */ + __asm__("nop"); + __asm__(".p2align 3"); +# endif +# endif +#endif + + /* Handle the initial state where litBuffer is currently split between dst and litExtraBuffer */ + for ( ; nbSeq; nbSeq--) { + sequence = ZSTD_decodeSequence(&seqState, isLongOffset, nbSeq==1); + if (litPtr + sequence.litLength > dctx->litBufferEnd) break; + { size_t const oneSeqSize = ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequence.litLength - WILDCOPY_OVERLENGTH, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + assert(!ZSTD_isError(oneSeqSize)); + ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase); +#endif + if (UNLIKELY(ZSTD_isError(oneSeqSize))) + return oneSeqSize; + DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); + op += oneSeqSize; + } } + DEBUGLOG(6, "reached: (litPtr + sequence.litLength > dctx->litBufferEnd)"); + + /* If there are more sequences, they will need to read literals from litExtraBuffer; copy over the remainder from dst and update litPtr and litEnd */ + if (nbSeq > 0) { + const size_t leftoverLit = dctx->litBufferEnd - litPtr; + DEBUGLOG(6, "There are %i sequences left, and %zu/%zu literals left in buffer", nbSeq, leftoverLit, sequence.litLength); + if (leftoverLit) { + RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer"); + ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit); + sequence.litLength -= leftoverLit; + op += leftoverLit; + } + litPtr = dctx->litExtraBuffer; + litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE; + dctx->litBufferLocation = ZSTD_not_in_dst; + { size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + assert(!ZSTD_isError(oneSeqSize)); + ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase); +#endif + if (UNLIKELY(ZSTD_isError(oneSeqSize))) + return oneSeqSize; + DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); + op += oneSeqSize; + } + nbSeq--; + } + } + + if (nbSeq > 0) { + /* there is remaining lit from extra buffer */ + +#if defined(__GNUC__) && defined(__x86_64__) + __asm__(".p2align 6"); + __asm__("nop"); +# if __GNUC__ != 7 + /* worse for gcc-7 better for gcc-8, gcc-9, and gcc-10 and clang */ + __asm__(".p2align 4"); + __asm__("nop"); + __asm__(".p2align 3"); +# elif __GNUC__ >= 11 + __asm__(".p2align 3"); +# else + __asm__(".p2align 5"); + __asm__("nop"); + __asm__(".p2align 3"); +# endif +#endif + + for ( ; nbSeq ; nbSeq--) { + seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, nbSeq==1); + size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + assert(!ZSTD_isError(oneSeqSize)); + ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase); +#endif + if (UNLIKELY(ZSTD_isError(oneSeqSize))) + return oneSeqSize; + DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); + op += oneSeqSize; + } + } + + /* check if reached exact end */ + DEBUGLOG(5, "ZSTD_decompressSequences_bodySplitLitBuffer: after decode loop, remaining nbSeq : %i", nbSeq); + RETURN_ERROR_IF(nbSeq, corruption_detected, ""); + DEBUGLOG(5, "bitStream : start=%p, ptr=%p, bitsConsumed=%u", seqState.DStream.start, seqState.DStream.ptr, seqState.DStream.bitsConsumed); + RETURN_ERROR_IF(!BIT_endOfDStream(&seqState.DStream), corruption_detected, ""); + /* save reps for next block */ + { U32 i; for (i=0; ientropy.rep[i] = (U32)(seqState.prevOffset[i]); } + } + + /* last literal segment */ + if (dctx->litBufferLocation == ZSTD_split) { + /* split hasn't been reached yet, first get dst then copy litExtraBuffer */ + size_t const lastLLSize = (size_t)(litBufferEnd - litPtr); + DEBUGLOG(6, "copy last literals from segment : %u", (U32)lastLLSize); + RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, ""); + if (op != NULL) { + ZSTD_memmove(op, litPtr, lastLLSize); + op += lastLLSize; + } + litPtr = dctx->litExtraBuffer; + litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE; + dctx->litBufferLocation = ZSTD_not_in_dst; + } + /* copy last literals from internal buffer */ + { size_t const lastLLSize = (size_t)(litBufferEnd - litPtr); + DEBUGLOG(6, "copy last literals from internal buffer : %u", (U32)lastLLSize); + RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); + if (op != NULL) { + ZSTD_memcpy(op, litPtr, lastLLSize); + op += lastLLSize; + } } + + DEBUGLOG(6, "decoded block of size %u bytes", (U32)(op - ostart)); + return (size_t)(op - ostart); +} + +FORCE_INLINE_TEMPLATE size_t +DONT_VECTORIZE +ZSTD_decompressSequences_body(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + const BYTE* ip = (const BYTE*)seqStart; + const BYTE* const iend = ip + seqSize; + BYTE* const ostart = (BYTE*)dst; + BYTE* const oend = dctx->litBufferLocation == ZSTD_not_in_dst ? ZSTD_maybeNullPtrAdd(ostart, maxDstSize) : dctx->litBuffer; + BYTE* op = ostart; + const BYTE* litPtr = dctx->litPtr; + const BYTE* const litEnd = litPtr + dctx->litSize; + const BYTE* const prefixStart = (const BYTE*)(dctx->prefixStart); + const BYTE* const vBase = (const BYTE*)(dctx->virtualStart); + const BYTE* const dictEnd = (const BYTE*)(dctx->dictEnd); + DEBUGLOG(5, "ZSTD_decompressSequences_body: nbSeq = %d", nbSeq); + + /* Regen sequences */ + if (nbSeq) { + seqState_t seqState; + dctx->fseEntropy = 1; + { U32 i; for (i = 0; i < ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; } + RETURN_ERROR_IF( + ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend - ip)), + corruption_detected, ""); + ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); + ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); + ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); + assert(dst != NULL); + +#if defined(__GNUC__) && defined(__x86_64__) + __asm__(".p2align 6"); + __asm__("nop"); +# if __GNUC__ >= 7 + __asm__(".p2align 5"); + __asm__("nop"); + __asm__(".p2align 3"); +# else + __asm__(".p2align 4"); + __asm__("nop"); + __asm__(".p2align 3"); +# endif +#endif + + for ( ; nbSeq ; nbSeq--) { + seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, nbSeq==1); + size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + assert(!ZSTD_isError(oneSeqSize)); + ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase); +#endif + if (UNLIKELY(ZSTD_isError(oneSeqSize))) + return oneSeqSize; + DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); + op += oneSeqSize; + } + + /* check if reached exact end */ + assert(nbSeq == 0); + RETURN_ERROR_IF(!BIT_endOfDStream(&seqState.DStream), corruption_detected, ""); + /* save reps for next block */ + { U32 i; for (i=0; ientropy.rep[i] = (U32)(seqState.prevOffset[i]); } + } + + /* last literal segment */ + { size_t const lastLLSize = (size_t)(litEnd - litPtr); + DEBUGLOG(6, "copy last literals : %u", (U32)lastLLSize); + RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); + if (op != NULL) { + ZSTD_memcpy(op, litPtr, lastLLSize); + op += lastLLSize; + } } + + DEBUGLOG(6, "decoded block of size %u bytes", (U32)(op - ostart)); + return (size_t)(op - ostart); +} + +static size_t +ZSTD_decompressSequences_default(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} + +static size_t +ZSTD_decompressSequencesSplitLitBuffer_default(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + return ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} +#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */ + +#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT + +FORCE_INLINE_TEMPLATE + +size_t ZSTD_prefetchMatch(size_t prefetchPos, seq_t const sequence, + const BYTE* const prefixStart, const BYTE* const dictEnd) +{ + prefetchPos += sequence.litLength; + { const BYTE* const matchBase = (sequence.offset > prefetchPos) ? dictEnd : prefixStart; + /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted. + * No consequence though : memory address is only used for prefetching, not for dereferencing */ + const BYTE* const match = ZSTD_wrappedPtrSub(ZSTD_wrappedPtrAdd(matchBase, prefetchPos), sequence.offset); + PREFETCH_L1(match); PREFETCH_L1(match+CACHELINE_SIZE); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */ + } + return prefetchPos + sequence.matchLength; +} + +/* This decoding function employs prefetching + * to reduce latency impact of cache misses. + * It's generally employed when block contains a significant portion of long-distance matches + * or when coupled with a "cold" dictionary */ +FORCE_INLINE_TEMPLATE size_t +ZSTD_decompressSequencesLong_body( + ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + const BYTE* ip = (const BYTE*)seqStart; + const BYTE* const iend = ip + seqSize; + BYTE* const ostart = (BYTE*)dst; + BYTE* const oend = dctx->litBufferLocation == ZSTD_in_dst ? dctx->litBuffer : ZSTD_maybeNullPtrAdd(ostart, maxDstSize); + BYTE* op = ostart; + const BYTE* litPtr = dctx->litPtr; + const BYTE* litBufferEnd = dctx->litBufferEnd; + const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart); + const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart); + const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); + + /* Regen sequences */ + if (nbSeq) { +#define STORED_SEQS 8 +#define STORED_SEQS_MASK (STORED_SEQS-1) +#define ADVANCED_SEQS STORED_SEQS + seq_t sequences[STORED_SEQS]; + int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS); + seqState_t seqState; + int seqNb; + size_t prefetchPos = (size_t)(op-prefixStart); /* track position relative to prefixStart */ + + dctx->fseEntropy = 1; + { int i; for (i=0; ientropy.rep[i]; } + assert(dst != NULL); + assert(iend >= ip); + RETURN_ERROR_IF( + ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)), + corruption_detected, ""); + ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); + ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); + ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); + + /* prepare in advance */ + for (seqNb=0; seqNblitBufferLocation == ZSTD_split && litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength > dctx->litBufferEnd) { + /* lit buffer is reaching split point, empty out the first buffer and transition to litExtraBuffer */ + const size_t leftoverLit = dctx->litBufferEnd - litPtr; + if (leftoverLit) + { + RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer"); + ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit); + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength -= leftoverLit; + op += leftoverLit; + } + litPtr = dctx->litExtraBuffer; + litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE; + dctx->litBufferLocation = ZSTD_not_in_dst; + { size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + assert(!ZSTD_isError(oneSeqSize)); + ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart); +#endif + if (ZSTD_isError(oneSeqSize)) return oneSeqSize; + + prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd); + sequences[seqNb & STORED_SEQS_MASK] = sequence; + op += oneSeqSize; + } } + else + { + /* lit buffer is either wholly contained in first or second split, or not split at all*/ + size_t const oneSeqSize = dctx->litBufferLocation == ZSTD_split ? + ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength - WILDCOPY_OVERLENGTH, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd) : + ZSTD_execSequence(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + assert(!ZSTD_isError(oneSeqSize)); + ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart); +#endif + if (ZSTD_isError(oneSeqSize)) return oneSeqSize; + + prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd); + sequences[seqNb & STORED_SEQS_MASK] = sequence; + op += oneSeqSize; + } + } + RETURN_ERROR_IF(!BIT_endOfDStream(&seqState.DStream), corruption_detected, ""); + + /* finish queue */ + seqNb -= seqAdvance; + for ( ; seqNblitBufferLocation == ZSTD_split && litPtr + sequence->litLength > dctx->litBufferEnd) { + const size_t leftoverLit = dctx->litBufferEnd - litPtr; + if (leftoverLit) { + RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer"); + ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit); + sequence->litLength -= leftoverLit; + op += leftoverLit; + } + litPtr = dctx->litExtraBuffer; + litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE; + dctx->litBufferLocation = ZSTD_not_in_dst; + { size_t const oneSeqSize = ZSTD_execSequence(op, oend, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + assert(!ZSTD_isError(oneSeqSize)); + ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart); +#endif + if (ZSTD_isError(oneSeqSize)) return oneSeqSize; + op += oneSeqSize; + } + } + else + { + size_t const oneSeqSize = dctx->litBufferLocation == ZSTD_split ? + ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequence->litLength - WILDCOPY_OVERLENGTH, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd) : + ZSTD_execSequence(op, oend, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) + assert(!ZSTD_isError(oneSeqSize)); + ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart); +#endif + if (ZSTD_isError(oneSeqSize)) return oneSeqSize; + op += oneSeqSize; + } + } + + /* save reps for next block */ + { U32 i; for (i=0; ientropy.rep[i] = (U32)(seqState.prevOffset[i]); } + } + + /* last literal segment */ + if (dctx->litBufferLocation == ZSTD_split) { /* first deplete literal buffer in dst, then copy litExtraBuffer */ + size_t const lastLLSize = litBufferEnd - litPtr; + RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, ""); + if (op != NULL) { + ZSTD_memmove(op, litPtr, lastLLSize); + op += lastLLSize; + } + litPtr = dctx->litExtraBuffer; + litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE; + } + { size_t const lastLLSize = litBufferEnd - litPtr; + RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); + if (op != NULL) { + ZSTD_memmove(op, litPtr, lastLLSize); + op += lastLLSize; + } + } + + return (size_t)(op - ostart); +} + +static size_t +ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} +#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */ + + + +#if DYNAMIC_BMI2 + +#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG +static BMI2_TARGET_ATTRIBUTE size_t +DONT_VECTORIZE +ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} +static BMI2_TARGET_ATTRIBUTE size_t +DONT_VECTORIZE +ZSTD_decompressSequencesSplitLitBuffer_bmi2(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + return ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} +#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */ + +#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT +static BMI2_TARGET_ATTRIBUTE size_t +ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} +#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */ + +#endif /* DYNAMIC_BMI2 */ + +typedef size_t (*ZSTD_decompressSequences_t)( + ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset); + +#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG +static size_t +ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + DEBUGLOG(5, "ZSTD_decompressSequences"); +#if DYNAMIC_BMI2 + if (ZSTD_DCtx_get_bmi2(dctx)) { + return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); + } +#endif + return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} +static size_t +ZSTD_decompressSequencesSplitLitBuffer(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + DEBUGLOG(5, "ZSTD_decompressSequencesSplitLitBuffer"); +#if DYNAMIC_BMI2 + if (ZSTD_DCtx_get_bmi2(dctx)) { + return ZSTD_decompressSequencesSplitLitBuffer_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); + } +#endif + return ZSTD_decompressSequencesSplitLitBuffer_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} +#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */ + + +#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT +/* ZSTD_decompressSequencesLong() : + * decompression function triggered when a minimum share of offsets is considered "long", + * aka out of cache. + * note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes meaning "farther than memory cache distance". + * This function will try to mitigate main memory latency through the use of prefetching */ +static size_t +ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx, + void* dst, size_t maxDstSize, + const void* seqStart, size_t seqSize, int nbSeq, + const ZSTD_longOffset_e isLongOffset) +{ + DEBUGLOG(5, "ZSTD_decompressSequencesLong"); +#if DYNAMIC_BMI2 + if (ZSTD_DCtx_get_bmi2(dctx)) { + return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); + } +#endif + return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset); +} +#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */ + + +/** + * @returns The total size of the history referenceable by zstd, including + * both the prefix and the extDict. At @p op any offset larger than this + * is invalid. + */ +static size_t ZSTD_totalHistorySize(BYTE* op, BYTE const* virtualStart) +{ + return (size_t)(op - virtualStart); +} + +typedef struct { + unsigned longOffsetShare; + unsigned maxNbAdditionalBits; +} ZSTD_OffsetInfo; + +/* ZSTD_getOffsetInfo() : + * condition : offTable must be valid + * @return : "share" of long offsets (arbitrarily defined as > (1<<23)) + * compared to maximum possible of (1< 22) info.longOffsetShare += 1; + } + + assert(tableLog <= OffFSELog); + info.longOffsetShare <<= (OffFSELog - tableLog); /* scale to OffFSELog */ + } + + return info; +} + +/** + * @returns The maximum offset we can decode in one read of our bitstream, without + * reloading more bits in the middle of the offset bits read. Any offsets larger + * than this must use the long offset decoder. + */ +static size_t ZSTD_maxShortOffset(void) +{ + if (MEM_64bits()) { + /* We can decode any offset without reloading bits. + * This might change if the max window size grows. + */ + ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31); + return (size_t)-1; + } else { + /* The maximum offBase is (1 << (STREAM_ACCUMULATOR_MIN + 1)) - 1. + * This offBase would require STREAM_ACCUMULATOR_MIN extra bits. + * Then we have to subtract ZSTD_REP_NUM to get the maximum possible offset. + */ + size_t const maxOffbase = ((size_t)1 << (STREAM_ACCUMULATOR_MIN + 1)) - 1; + size_t const maxOffset = maxOffbase - ZSTD_REP_NUM; + assert(ZSTD_highbit32((U32)maxOffbase) == STREAM_ACCUMULATOR_MIN); + return maxOffset; + } +} + +size_t +ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, const streaming_operation streaming) +{ /* blockType == blockCompressed */ + const BYTE* ip = (const BYTE*)src; + DEBUGLOG(5, "ZSTD_decompressBlock_internal (cSize : %u)", (unsigned)srcSize); + + /* Note : the wording of the specification + * allows compressed block to be sized exactly ZSTD_blockSizeMax(dctx). + * This generally does not happen, as it makes little sense, + * since an uncompressed block would feature same size and have no decompression cost. + * Also, note that decoder from reference libzstd before < v1.5.4 + * would consider this edge case as an error. + * As a consequence, avoid generating compressed blocks of size ZSTD_blockSizeMax(dctx) + * for broader compatibility with the deployed ecosystem of zstd decoders */ + RETURN_ERROR_IF(srcSize > ZSTD_blockSizeMax(dctx), srcSize_wrong, ""); + + /* Decode literals section */ + { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize, dst, dstCapacity, streaming); + DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : cSize=%u, nbLiterals=%zu", (U32)litCSize, dctx->litSize); + if (ZSTD_isError(litCSize)) return litCSize; + ip += litCSize; + srcSize -= litCSize; + } + + /* Build Decoding Tables */ + { + /* Compute the maximum block size, which must also work when !frame and fParams are unset. + * Additionally, take the min with dstCapacity to ensure that the totalHistorySize fits in a size_t. + */ + size_t const blockSizeMax = MIN(dstCapacity, ZSTD_blockSizeMax(dctx)); + size_t const totalHistorySize = ZSTD_totalHistorySize(ZSTD_maybeNullPtrAdd((BYTE*)dst, blockSizeMax), (BYTE const*)dctx->virtualStart); + /* isLongOffset must be true if there are long offsets. + * Offsets are long if they are larger than ZSTD_maxShortOffset(). + * We don't expect that to be the case in 64-bit mode. + * + * We check here to see if our history is large enough to allow long offsets. + * If it isn't, then we can't possible have (valid) long offsets. If the offset + * is invalid, then it is okay to read it incorrectly. + * + * If isLongOffsets is true, then we will later check our decoding table to see + * if it is even possible to generate long offsets. + */ + ZSTD_longOffset_e isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (totalHistorySize > ZSTD_maxShortOffset())); + /* These macros control at build-time which decompressor implementation + * we use. If neither is defined, we do some inspection and dispatch at + * runtime. + */ +#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \ + !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG) + int usePrefetchDecoder = dctx->ddictIsCold; +#else + /* Set to 1 to avoid computing offset info if we don't need to. + * Otherwise this value is ignored. + */ + int usePrefetchDecoder = 1; +#endif + int nbSeq; + size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize); + if (ZSTD_isError(seqHSize)) return seqHSize; + ip += seqHSize; + srcSize -= seqHSize; + + RETURN_ERROR_IF((dst == NULL || dstCapacity == 0) && nbSeq > 0, dstSize_tooSmall, "NULL not handled"); + RETURN_ERROR_IF(MEM_64bits() && sizeof(size_t) == sizeof(void*) && (size_t)(-1) - (size_t)dst < (size_t)(1 << 20), dstSize_tooSmall, + "invalid dst"); + + /* If we could potentially have long offsets, or we might want to use the prefetch decoder, + * compute information about the share of long offsets, and the maximum nbAdditionalBits. + * NOTE: could probably use a larger nbSeq limit + */ + if (isLongOffset || (!usePrefetchDecoder && (totalHistorySize > (1u << 24)) && (nbSeq > 8))) { + ZSTD_OffsetInfo const info = ZSTD_getOffsetInfo(dctx->OFTptr, nbSeq); + if (isLongOffset && info.maxNbAdditionalBits <= STREAM_ACCUMULATOR_MIN) { + /* If isLongOffset, but the maximum number of additional bits that we see in our table is small + * enough, then we know it is impossible to have too long an offset in this block, so we can + * use the regular offset decoder. + */ + isLongOffset = ZSTD_lo_isRegularOffset; + } + if (!usePrefetchDecoder) { + U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */ + usePrefetchDecoder = (info.longOffsetShare >= minShare); + } + } + + dctx->ddictIsCold = 0; + +#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \ + !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG) + if (usePrefetchDecoder) { +#else + (void)usePrefetchDecoder; + { +#endif +#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT + return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset); +#endif + } + +#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG + /* else */ + if (dctx->litBufferLocation == ZSTD_split) + return ZSTD_decompressSequencesSplitLitBuffer(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset); + else + return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset); +#endif + } +} + + +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize) +{ + if (dst != dctx->previousDstEnd && dstSize > 0) { /* not contiguous */ + dctx->dictEnd = dctx->previousDstEnd; + dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart)); + dctx->prefixStart = dst; + dctx->previousDstEnd = dst; + } +} + + +size_t ZSTD_decompressBlock_deprecated(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + size_t dSize; + dctx->isFrameDecompression = 0; + ZSTD_checkContinuity(dctx, dst, dstCapacity); + dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, not_streaming); + FORWARD_IF_ERROR(dSize, ""); + dctx->previousDstEnd = (char*)dst + dSize; + return dSize; +} + + +/* NOTE: Must just wrap ZSTD_decompressBlock_deprecated() */ +size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize) +{ + return ZSTD_decompressBlock_deprecated(dctx, dst, dstCapacity, src, srcSize); +} diff --git a/third_party/zstd/decompress/zstd_decompress_block.cpp b/third_party/zstd/decompress/zstd_decompress_block.cpp deleted file mode 100644 index f7574918ec3..00000000000 --- a/third_party/zstd/decompress/zstd_decompress_block.cpp +++ /dev/null @@ -1,1418 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - -/* zstd_decompress_block : - * this module takes care of decompressing _compressed_ block */ - -/*-******************************************************* -* Dependencies -*********************************************************/ -#include /* memcpy, memmove, memset */ -#include "zstd/common/compiler.h" /* prefetch */ -#include "zstd/common/mem.h" /* low level memory routines */ -#include "zstd/common/fse.h" -#include "zstd/common/fse_static.h" -#include "zstd/common/huf.h" -#include "zstd/common/huf_static.h" -#include "zstd/common/zstd_internal.h" -#include "zstd/decompress/zstd_decompress_internal.h" /* ZSTD_DCtx */ -#include "zstd/decompress/zstd_ddict.h" /* ZSTD_DDictDictContent */ -#include "zstd/decompress/zstd_decompress_block.h" -namespace duckdb_zstd { -/*_******************************************************* -* Macros -**********************************************************/ - -/* These two optional macros force the use one way or another of the two - * ZSTD_decompressSequences implementations. You can't force in both directions - * at the same time. - */ -#if defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \ - defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG) -#error "Cannot force the use of the short and the long ZSTD_decompressSequences variants!" -#endif - - -/*_******************************************************* -* Memory operations -**********************************************************/ -static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); } - - -/*-************************************************************* - * Block decoding - ***************************************************************/ - -/*! ZSTD_getcBlockSize() : - * Provides the size of compressed block from block header `src` */ -size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, - blockProperties_t* bpPtr) -{ - RETURN_ERROR_IF(srcSize < ZSTDInternalConstants::ZSTD_blockHeaderSize, srcSize_wrong, ""); - - { U32 const cBlockHeader = MEM_readLE24(src); - U32 const cSize = cBlockHeader >> 3; - bpPtr->lastBlock = cBlockHeader & 1; - bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3); - bpPtr->origSize = cSize; /* only useful for RLE */ - if (bpPtr->blockType == bt_rle) return 1; - RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected, ""); - return cSize; - } -} - - -/* Hidden declaration for fullbench */ -size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, - const void* src, size_t srcSize); -/*! ZSTD_decodeLiteralsBlock() : - * @return : nb of bytes read from src (< srcSize ) - * note : symbol not declared but exposed for fullbench */ -size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, - const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */ -{ - DEBUGLOG(5, "ZSTD_decodeLiteralsBlock"); - RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, ""); - - { const BYTE* const istart = (const BYTE*) src; - symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); - - switch(litEncType) - { - case set_repeat: - DEBUGLOG(5, "set_repeat flag : re-using stats from previous compressed literals block"); - RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted, ""); - /* fall-through */ - - case set_compressed: - RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3"); - { size_t lhSize, litSize, litCSize; - U32 singleStream=0; - U32 const lhlCode = (istart[0] >> 2) & 3; - U32 const lhc = MEM_readLE32(istart); - size_t hufSuccess; - switch(lhlCode) - { - case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */ - /* 2 - 2 - 10 - 10 */ - singleStream = !lhlCode; - lhSize = 3; - litSize = (lhc >> 4) & 0x3FF; - litCSize = (lhc >> 14) & 0x3FF; - break; - case 2: - /* 2 - 2 - 14 - 14 */ - lhSize = 4; - litSize = (lhc >> 4) & 0x3FFF; - litCSize = lhc >> 18; - break; - case 3: - /* 2 - 2 - 18 - 18 */ - lhSize = 5; - litSize = (lhc >> 4) & 0x3FFFF; - litCSize = (lhc >> 22) + ((size_t)istart[4] << 10); - break; - } - RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, ""); - RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, ""); - - /* prefetch huffman table if cold */ - if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) { - PREFETCH_AREA(dctx->HUFptr, sizeof(dctx->entropy.hufTable)); - } - - if (litEncType==set_repeat) { - if (singleStream) { - hufSuccess = HUF_decompress1X_usingDTable_bmi2( - dctx->litBuffer, litSize, istart+lhSize, litCSize, - dctx->HUFptr, dctx->bmi2); - } else { - hufSuccess = HUF_decompress4X_usingDTable_bmi2( - dctx->litBuffer, litSize, istart+lhSize, litCSize, - dctx->HUFptr, dctx->bmi2); - } - } else { - if (singleStream) { -#if defined(HUF_FORCE_DECOMPRESS_X2) - hufSuccess = HUF_decompress1X_DCtx_wksp( - dctx->entropy.hufTable, dctx->litBuffer, litSize, - istart+lhSize, litCSize, dctx->workspace, - sizeof(dctx->workspace)); -#else - hufSuccess = HUF_decompress1X1_DCtx_wksp_bmi2( - dctx->entropy.hufTable, dctx->litBuffer, litSize, - istart+lhSize, litCSize, dctx->workspace, - sizeof(dctx->workspace), dctx->bmi2); -#endif - } else { - hufSuccess = HUF_decompress4X_hufOnly_wksp_bmi2( - dctx->entropy.hufTable, dctx->litBuffer, litSize, - istart+lhSize, litCSize, dctx->workspace, - sizeof(dctx->workspace), dctx->bmi2); - } - } - - RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected, ""); - - dctx->litPtr = dctx->litBuffer; - dctx->litSize = litSize; - dctx->litEntropy = 1; - if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable; - memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); - return litCSize + lhSize; - } - - case set_basic: - { size_t litSize, lhSize; - U32 const lhlCode = ((istart[0]) >> 2) & 3; - switch(lhlCode) - { - case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */ - lhSize = 1; - litSize = istart[0] >> 3; - break; - case 1: - lhSize = 2; - litSize = MEM_readLE16(istart) >> 4; - break; - case 3: - lhSize = 3; - litSize = MEM_readLE24(istart) >> 4; - break; - } - - if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */ - RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, ""); - memcpy(dctx->litBuffer, istart+lhSize, litSize); - dctx->litPtr = dctx->litBuffer; - dctx->litSize = litSize; - memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); - return lhSize+litSize; - } - /* direct reference into compressed stream */ - dctx->litPtr = istart+lhSize; - dctx->litSize = litSize; - return lhSize+litSize; - } - - case set_rle: - { U32 const lhlCode = ((istart[0]) >> 2) & 3; - size_t litSize, lhSize; - switch(lhlCode) - { - case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */ - lhSize = 1; - litSize = istart[0] >> 3; - break; - case 1: - lhSize = 2; - litSize = MEM_readLE16(istart) >> 4; - break; - case 3: - lhSize = 3; - litSize = MEM_readLE24(istart) >> 4; - RETURN_ERROR_IF(srcSize<4, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4"); - break; - } - RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, ""); - memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH); - dctx->litPtr = dctx->litBuffer; - dctx->litSize = litSize; - return lhSize+1; - } - default: - RETURN_ERROR(corruption_detected, "impossible"); - } - } -} - -/* Default FSE distribution tables. - * These are pre-calculated FSE decoding tables using default distributions as defined in specification : - * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#default-distributions - * They were generated programmatically with following method : - * - start from default distributions, present in /lib/common/zstd_internal.h - * - generate tables normally, using ZSTD_buildFSETable() - * - printout the content of tables - * - pretify output, report below, test with fuzzer to ensure it's correct */ - -/* Default FSE distribution table for Literal Lengths */ -static const ZSTD_seqSymbol LL_defaultDTable[(1<tableLog = 0; - DTableH->fastMode = 0; - - cell->nbBits = 0; - cell->nextState = 0; - assert(nbAddBits < 255); - cell->nbAdditionalBits = (BYTE)nbAddBits; - cell->baseValue = baseValue; -} - - -/* ZSTD_buildFSETable() : - * generate FSE decoding table for one symbol (ll, ml or off) - * cannot fail if input is valid => - * all inputs are presumed validated at this stage */ -void -ZSTD_buildFSETable(ZSTD_seqSymbol* dt, - const short* normalizedCounter, unsigned maxSymbolValue, - const U32* baseValue, const U32* nbAdditionalBits, - unsigned tableLog) -{ - ZSTD_seqSymbol* const tableDecode = dt+1; - U16 symbolNext[MaxSeq+1]; - - U32 const maxSV1 = maxSymbolValue + 1; - U32 const tableSize = 1 << tableLog; - U32 highThreshold = tableSize-1; - - /* Sanity Checks */ - assert(maxSymbolValue <= MaxSeq); - assert(tableLog <= MaxFSELog); - - /* Init, lay down lowprob symbols */ - { ZSTD_seqSymbol_header DTableH; - DTableH.tableLog = tableLog; - DTableH.fastMode = 1; - { S16 const largeLimit= (S16)(1 << (tableLog-1)); - U32 s; - for (s=0; s= largeLimit) DTableH.fastMode=0; - assert(normalizedCounter[s]>=0); - symbolNext[s] = (U16)normalizedCounter[s]; - } } } - memcpy(dt, &DTableH, sizeof(DTableH)); - } - - /* Spread symbols */ - { U32 const tableMask = tableSize-1; - U32 const step = FSE_TABLESTEP(tableSize); - U32 s, position = 0; - for (s=0; s highThreshold) position = (position + step) & tableMask; /* lowprob area */ - } } - assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ - } - - /* Build Decoding table */ - { U32 u; - for (u=0; u max, corruption_detected, ""); - { U32 const symbol = *(const BYTE*)src; - U32 const baseline = baseValue[symbol]; - U32 const nbBits = nbAdditionalBits[symbol]; - ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits); - } - *DTablePtr = DTableSpace; - return 1; - case set_basic : - *DTablePtr = defaultTable; - return 0; - case set_repeat: - RETURN_ERROR_IF(!flagRepeatTable, corruption_detected, ""); - /* prefetch FSE table if used */ - if (ddictIsCold && (nbSeq > 24 /* heuristic */)) { - const void* const pStart = *DTablePtr; - size_t const pSize = sizeof(ZSTD_seqSymbol) * (SEQSYMBOL_TABLE_SIZE(maxLog)); - PREFETCH_AREA(pStart, pSize); - } - return 0; - case set_compressed : - { unsigned tableLog; - S16 norm[MaxSeq+1]; - size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize); - RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected, ""); - RETURN_ERROR_IF(tableLog > maxLog, corruption_detected, ""); - ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog); - *DTablePtr = DTableSpace; - return headerSize; - } - default : - assert(0); - RETURN_ERROR(GENERIC, "impossible"); - } -} - -size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, - const void* src, size_t srcSize) -{ - const BYTE* const istart = (const BYTE* const)src; - const BYTE* const iend = istart + srcSize; - const BYTE* ip = istart; - int nbSeq; - DEBUGLOG(5, "ZSTD_decodeSeqHeaders"); - - /* check */ - RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong, ""); - - /* SeqHead */ - nbSeq = *ip++; - if (!nbSeq) { - *nbSeqPtr=0; - RETURN_ERROR_IF(srcSize != 1, srcSize_wrong, ""); - return 1; - } - if (nbSeq > 0x7F) { - if (nbSeq == 0xFF) { - RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong, ""); - nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2; - } else { - RETURN_ERROR_IF(ip >= iend, srcSize_wrong, ""); - nbSeq = ((nbSeq-0x80)<<8) + *ip++; - } - } - *nbSeqPtr = nbSeq; - - /* FSE table descriptors */ - RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong, ""); /* minimum possible size: 1 byte for symbol encoding types */ - { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6); - symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3); - symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3); - ip++; - - /* Build DTables */ - { size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr, - LLtype, MaxLL, LLFSELog, - ip, iend-ip, - ZSTDConstants::LL_base, ZSTDInternalConstants::LL_bits, - LL_defaultDTable, dctx->fseEntropy, - dctx->ddictIsCold, nbSeq); - RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, "ZSTD_buildSeqTable failed"); - ip += llhSize; - } - - { size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr, - OFtype, MaxOff, OffFSELog, - ip, iend-ip, - ZSTDConstants::OF_base, ZSTDConstants::OF_bits, - OF_defaultDTable, dctx->fseEntropy, - dctx->ddictIsCold, nbSeq); - RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, "ZSTD_buildSeqTable failed"); - ip += ofhSize; - } - - { size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr, - MLtype, MaxML, MLFSELog, - ip, iend-ip, - ZSTDConstants::ML_base, ZSTDInternalConstants::ML_bits, - ML_defaultDTable, dctx->fseEntropy, - dctx->ddictIsCold, nbSeq); - RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, "ZSTD_buildSeqTable failed"); - ip += mlhSize; - } - } - - return ip-istart; -} - - -typedef struct { - size_t litLength; - size_t matchLength; - size_t offset; - const BYTE* match; -} seq_t; - -typedef struct { - size_t state; - const ZSTD_seqSymbol* table; -} ZSTD_fseState; - -typedef struct { - BIT_DStream_t DStream; - ZSTD_fseState stateLL; - ZSTD_fseState stateOffb; - ZSTD_fseState stateML; - size_t prevOffset[ZSTD_REP_NUM]; - const BYTE* prefixStart; - const BYTE* dictEnd; - size_t pos; -} seqState_t; - -/*! ZSTD_overlapCopy8() : - * Copies 8 bytes from ip to op and updates op and ip where ip <= op. - * If the offset is < 8 then the offset is spread to at least 8 bytes. - * - * Precondition: *ip <= *op - * Postcondition: *op - *op >= 8 - */ -HINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset) { - assert(*ip <= *op); - if (offset < 8) { - /* close range match, overlap */ - static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */ - static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */ - int const sub2 = dec64table[offset]; - (*op)[0] = (*ip)[0]; - (*op)[1] = (*ip)[1]; - (*op)[2] = (*ip)[2]; - (*op)[3] = (*ip)[3]; - *ip += dec32table[offset]; - ZSTD_copy4(*op+4, *ip); - *ip -= sub2; - } else { - ZSTD_copy8(*op, *ip); - } - *ip += 8; - *op += 8; - assert(*op - *ip >= 8); -} - -/*! ZSTD_safecopy() : - * Specialized version of memcpy() that is allowed to READ up to WILDCOPY_OVERLENGTH past the input buffer - * and write up to 16 bytes past oend_w (op >= oend_w is allowed). - * This function is only called in the uncommon case where the sequence is near the end of the block. It - * should be fast for a single long sequence, but can be slow for several short sequences. - * - * @param ovtype controls the overlap detection - * - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart. - * - ZSTD_overlap_src_before_dst: The src and dst may overlap and may be any distance apart. - * The src buffer must be before the dst buffer. - */ -static void ZSTD_safecopy(BYTE* op, BYTE* const oend_w, BYTE const* ip, ptrdiff_t length, ZSTD_overlap_e ovtype) { - ptrdiff_t const diff = op - ip; - BYTE* const oend = op + length; - - assert((ovtype == ZSTD_no_overlap && (diff <= -8 || diff >= 8 || op >= oend_w)) || - (ovtype == ZSTD_overlap_src_before_dst && diff >= 0)); - - if (length < 8) { - /* Handle short lengths. */ - while (op < oend) *op++ = *ip++; - return; - } - if (ovtype == ZSTD_overlap_src_before_dst) { - /* Copy 8 bytes and ensure the offset >= 8 when there can be overlap. */ - assert(length >= 8); - ZSTD_overlapCopy8(&op, &ip, diff); - assert(op - ip >= 8); - assert(op <= oend); - } - - if (oend <= oend_w) { - /* No risk of overwrite. */ - ZSTD_wildcopy(op, ip, length, ovtype); - return; - } - if (op <= oend_w) { - /* Wildcopy until we get close to the end. */ - assert(oend > oend_w); - ZSTD_wildcopy(op, ip, oend_w - op, ovtype); - ip += oend_w - op; - op = oend_w; - } - /* Handle the leftovers. */ - while (op < oend) *op++ = *ip++; -} - -/* ZSTD_execSequenceEnd(): - * This version handles cases that are near the end of the output buffer. It requires - * more careful checks to make sure there is no overflow. By separating out these hard - * and unlikely cases, we can speed up the common cases. - * - * NOTE: This function needs to be fast for a single long sequence, but doesn't need - * to be optimized for many small sequences, since those fall into ZSTD_execSequence(). - */ -FORCE_NOINLINE -size_t ZSTD_execSequenceEnd(BYTE* op, - BYTE* const oend, seq_t sequence, - const BYTE** litPtr, const BYTE* const litLimit, - const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd) -{ - BYTE* const oLitEnd = op + sequence.litLength; - size_t const sequenceLength = sequence.litLength + sequence.matchLength; - const BYTE* const iLitEnd = *litPtr + sequence.litLength; - const BYTE* match = oLitEnd - sequence.offset; - BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; - - /* bounds checks : careful of address space overflow in 32-bit mode */ - RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, "last match must fit within dstBuffer"); - RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, "try to read beyond literal buffer"); - assert(op < op + sequenceLength); - assert(oLitEnd < op + sequenceLength); - - /* copy literals */ - ZSTD_safecopy(op, oend_w, *litPtr, sequence.litLength, ZSTD_no_overlap); - op = oLitEnd; - *litPtr = iLitEnd; - - /* copy Match */ - if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { - /* offset beyond prefix */ - RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, ""); - match = dictEnd - (prefixStart-match); - if (match + sequence.matchLength <= dictEnd) { - memmove(oLitEnd, match, sequence.matchLength); - return sequenceLength; - } - /* span extDict & currentPrefixSegment */ - { size_t const length1 = dictEnd - match; - memmove(oLitEnd, match, length1); - op = oLitEnd + length1; - sequence.matchLength -= length1; - match = prefixStart; - } } - ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst); - return sequenceLength; -} - -HINT_INLINE -size_t ZSTD_execSequence(BYTE* op, - BYTE* const oend, seq_t sequence, - const BYTE** litPtr, const BYTE* const litLimit, - const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd) -{ - BYTE* const oLitEnd = op + sequence.litLength; - size_t const sequenceLength = sequence.litLength + sequence.matchLength; - BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ - BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; /* risk : address space underflow on oend=NULL */ - const BYTE* const iLitEnd = *litPtr + sequence.litLength; - const BYTE* match = oLitEnd - sequence.offset; - - assert(op != NULL /* Precondition */); - assert(oend_w < oend /* No underflow */); - /* Handle edge cases in a slow path: - * - Read beyond end of literals - * - Match end is within WILDCOPY_OVERLIMIT of oend - * - 32-bit mode and the match length overflows - */ - if (UNLIKELY( - iLitEnd > litLimit || - oMatchEnd > oend_w || - (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH))) - return ZSTD_execSequenceEnd(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd); - - /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */ - assert(op <= oLitEnd /* No overflow */); - assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */); - assert(oMatchEnd <= oend /* No underflow */); - assert(iLitEnd <= litLimit /* Literal length is in bounds */); - assert(oLitEnd <= oend_w /* Can wildcopy literals */); - assert(oMatchEnd <= oend_w /* Can wildcopy matches */); - - /* Copy Literals: - * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9. - * We likely don't need the full 32-byte wildcopy. - */ - assert(WILDCOPY_OVERLENGTH >= 16); - ZSTD_copy16(op, (*litPtr)); - if (UNLIKELY(sequence.litLength > 16)) { - ZSTD_wildcopy(op+16, (*litPtr)+16, sequence.litLength-16, ZSTD_no_overlap); - } - op = oLitEnd; - *litPtr = iLitEnd; /* update for next sequence */ - - /* Copy Match */ - if (sequence.offset > (size_t)(oLitEnd - prefixStart)) { - /* offset beyond prefix -> go into extDict */ - RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, ""); - match = dictEnd + (match - prefixStart); - if (match + sequence.matchLength <= dictEnd) { - memmove(oLitEnd, match, sequence.matchLength); - return sequenceLength; - } - /* span extDict & currentPrefixSegment */ - { size_t const length1 = dictEnd - match; - memmove(oLitEnd, match, length1); - op = oLitEnd + length1; - sequence.matchLength -= length1; - match = prefixStart; - } } - /* Match within prefix of 1 or more bytes */ - assert(op <= oMatchEnd); - assert(oMatchEnd <= oend_w); - assert(match >= prefixStart); - assert(sequence.matchLength >= 1); - - /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy - * without overlap checking. - */ - if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) { - /* We bet on a full wildcopy for matches, since we expect matches to be - * longer than literals (in general). In silesia, ~10% of matches are longer - * than 16 bytes. - */ - ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap); - return sequenceLength; - } - assert(sequence.offset < WILDCOPY_VECLEN); - - /* Copy 8 bytes and spread the offset to be >= 8. */ - ZSTD_overlapCopy8(&op, &match, sequence.offset); - - /* If the match length is > 8 bytes, then continue with the wildcopy. */ - if (sequence.matchLength > 8) { - assert(op < oMatchEnd); - ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8, ZSTD_overlap_src_before_dst); - } - return sequenceLength; -} - -static void -ZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt) -{ - const void* ptr = dt; - const ZSTD_seqSymbol_header* const DTableH = (const ZSTD_seqSymbol_header*)ptr; - DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); - DEBUGLOG(6, "ZSTD_initFseState : val=%u using %u bits", - (U32)DStatePtr->state, DTableH->tableLog); - BIT_reloadDStream(bitD); - DStatePtr->table = dt + 1; -} - -FORCE_INLINE_TEMPLATE void -ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD) -{ - ZSTD_seqSymbol const DInfo = DStatePtr->table[DStatePtr->state]; - U32 const nbBits = DInfo.nbBits; - size_t const lowBits = BIT_readBits(bitD, nbBits); - DStatePtr->state = DInfo.nextState + lowBits; -} - -FORCE_INLINE_TEMPLATE void -ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, ZSTD_seqSymbol const DInfo) -{ - U32 const nbBits = DInfo.nbBits; - size_t const lowBits = BIT_readBits(bitD, nbBits); - DStatePtr->state = DInfo.nextState + lowBits; -} - -/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum - * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1) - * bits before reloading. This value is the maximum number of bytes we read - * after reloading when we are decoding long offsets. - */ -#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \ - (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \ - ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \ - : 0) - -typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e; -typedef enum { ZSTD_p_noPrefetch=0, ZSTD_p_prefetch=1 } ZSTD_prefetch_e; - -FORCE_INLINE_TEMPLATE seq_t -ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const ZSTD_prefetch_e prefetch) -{ - seq_t seq; - ZSTD_seqSymbol const llDInfo = seqState->stateLL.table[seqState->stateLL.state]; - ZSTD_seqSymbol const mlDInfo = seqState->stateML.table[seqState->stateML.state]; - ZSTD_seqSymbol const ofDInfo = seqState->stateOffb.table[seqState->stateOffb.state]; - U32 const llBase = llDInfo.baseValue; - U32 const mlBase = mlDInfo.baseValue; - U32 const ofBase = ofDInfo.baseValue; - BYTE const llBits = llDInfo.nbAdditionalBits; - BYTE const mlBits = mlDInfo.nbAdditionalBits; - BYTE const ofBits = ofDInfo.nbAdditionalBits; - BYTE const totalBits = llBits+mlBits+ofBits; - - /* sequence */ - { size_t offset; - if (ofBits > 1) { - ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1); - ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5); - assert(ofBits <= MaxOff); - if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) { - U32 const extraBits = ofBits - MIN(ofBits, 32 - seqState->DStream.bitsConsumed); - offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits); - BIT_reloadDStream(&seqState->DStream); - if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits); - assert(extraBits <= LONG_OFFSETS_MAX_EXTRA_BITS_32); /* to avoid another reload */ - } else { - offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */ - if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); - } - seqState->prevOffset[2] = seqState->prevOffset[1]; - seqState->prevOffset[1] = seqState->prevOffset[0]; - seqState->prevOffset[0] = offset; - } else { - U32 const ll0 = (llBase == 0); - if (LIKELY((ofBits == 0))) { - if (LIKELY(!ll0)) - offset = seqState->prevOffset[0]; - else { - offset = seqState->prevOffset[1]; - seqState->prevOffset[1] = seqState->prevOffset[0]; - seqState->prevOffset[0] = offset; - } - } else { - offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1); - { size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; - temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ - if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1]; - seqState->prevOffset[1] = seqState->prevOffset[0]; - seqState->prevOffset[0] = offset = temp; - } } } - seq.offset = offset; - } - - seq.matchLength = mlBase; - if (mlBits > 0) - seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/); - - if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32)) - BIT_reloadDStream(&seqState->DStream); - if (MEM_64bits() && UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog))) - BIT_reloadDStream(&seqState->DStream); - /* Ensure there are enough bits to read the rest of data in 64-bit mode. */ - ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64); - - seq.litLength = llBase; - if (llBits > 0) - seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/); - - if (MEM_32bits()) - BIT_reloadDStream(&seqState->DStream); - - DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u", - (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset); - - if (prefetch == ZSTD_p_prefetch) { - size_t const pos = seqState->pos + seq.litLength; - const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart; - seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted. - * No consequence though : no memory access will occur, offset is only used for prefetching */ - seqState->pos = pos + seq.matchLength; - } - - /* ANS state update - * gcc-9.0.0 does 2.5% worse with ZSTD_updateFseStateWithDInfo(). - * clang-9.2.0 does 7% worse with ZSTD_updateFseState(). - * Naturally it seems like ZSTD_updateFseStateWithDInfo() should be the - * better option, so it is the default for other compilers. But, if you - * measure that it is worse, please put up a pull request. - */ - { -#if defined(__GNUC__) && !defined(__clang__) - const int kUseUpdateFseState = 1; -#else - const int kUseUpdateFseState = 0; -#endif - if (kUseUpdateFseState) { - ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ - ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ - if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ - ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ - } else { - ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llDInfo); /* <= 9 bits */ - ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlDInfo); /* <= 9 bits */ - if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ - ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofDInfo); /* <= 8 bits */ - } - } - - return seq; -} - -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -static int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd) -{ - size_t const windowSize = dctx->fParams.windowSize; - /* No dictionary used. */ - if (dctx->dictContentEndForFuzzing == NULL) return 0; - /* Dictionary is our prefix. */ - if (prefixStart == dctx->dictContentBeginForFuzzing) return 1; - /* Dictionary is not our ext-dict. */ - if (dctx->dictEnd != dctx->dictContentEndForFuzzing) return 0; - /* Dictionary is not within our window size. */ - if ((size_t)(oLitEnd - prefixStart) >= windowSize) return 0; - /* Dictionary is active. */ - return 1; -} - -MEM_STATIC void ZSTD_assertValidSequence( - ZSTD_DCtx const* dctx, - BYTE const* op, BYTE const* oend, - seq_t const seq, - BYTE const* prefixStart, BYTE const* virtualStart) -{ - size_t const windowSize = dctx->fParams.windowSize; - size_t const sequenceSize = seq.litLength + seq.matchLength; - BYTE const* const oLitEnd = op + seq.litLength; - DEBUGLOG(6, "Checking sequence: litL=%u matchL=%u offset=%u", - (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset); - assert(op <= oend); - assert((size_t)(oend - op) >= sequenceSize); - assert(sequenceSize <= ZSTD_BLOCKSIZE_MAX); - if (ZSTD_dictionaryIsActive(dctx, prefixStart, oLitEnd)) { - size_t const dictSize = (size_t)((char const*)dctx->dictContentEndForFuzzing - (char const*)dctx->dictContentBeginForFuzzing); - /* Offset must be within the dictionary. */ - assert(seq.offset <= (size_t)(oLitEnd - virtualStart)); - assert(seq.offset <= windowSize + dictSize); - } else { - /* Offset must be within our window. */ - assert(seq.offset <= windowSize); - } -} -#endif - -#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG -FORCE_INLINE_TEMPLATE size_t -DONT_VECTORIZE -ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, - void* dst, size_t maxDstSize, - const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset, - const int frame) -{ - const BYTE* ip = (const BYTE*)seqStart; - const BYTE* const iend = ip + seqSize; - BYTE* const ostart = (BYTE* const)dst; - BYTE* const oend = ostart + maxDstSize; - BYTE* op = ostart; - const BYTE* litPtr = dctx->litPtr; - const BYTE* const litEnd = litPtr + dctx->litSize; - const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart); - const BYTE* const vBase = (const BYTE*) (dctx->virtualStart); - const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); - DEBUGLOG(5, "ZSTD_decompressSequences_body"); - (void)frame; - - /* Regen sequences */ - if (nbSeq) { - seqState_t seqState; - size_t error = 0; - dctx->fseEntropy = 1; - { U32 i; for (i=0; ientropy.rep[i]; } - RETURN_ERROR_IF( - ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)), - corruption_detected, ""); - ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); - ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); - ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); - assert(dst != NULL); - - ZSTD_STATIC_ASSERT( - BIT_DStream_unfinished < BIT_DStream_completed && - BIT_DStream_endOfBuffer < BIT_DStream_completed && - BIT_DStream_completed < BIT_DStream_overflow); - -#if defined(__GNUC__) && defined(__x86_64__) - /* Align the decompression loop to 32 + 16 bytes. - * - * zstd compiled with gcc-9 on an Intel i9-9900k shows 10% decompression - * speed swings based on the alignment of the decompression loop. This - * performance swing is caused by parts of the decompression loop falling - * out of the DSB. The entire decompression loop should fit in the DSB, - * when it can't we get much worse performance. You can measure if you've - * hit the good case or the bad case with this perf command for some - * compressed file test.zst: - * - * perf stat -e cycles -e instructions -e idq.all_dsb_cycles_any_uops \ - * -e idq.all_mite_cycles_any_uops -- ./zstd -tq test.zst - * - * If you see most cycles served out of the MITE you've hit the bad case. - * If you see most cycles served out of the DSB you've hit the good case. - * If it is pretty even then you may be in an okay case. - * - * I've been able to reproduce this issue on the following CPUs: - * - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9 - * Use Instruments->Counters to get DSB/MITE cycles. - * I never got performance swings, but I was able to - * go from the good case of mostly DSB to half of the - * cycles served from MITE. - * - Coffeelake: Intel i9-9900k - * - * I haven't been able to reproduce the instability or DSB misses on any - * of the following CPUS: - * - Haswell - * - Broadwell: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GH - * - Skylake - * - * If you are seeing performance stability this script can help test. - * It tests on 4 commits in zstd where I saw performance change. - * - * https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4 - */ - __asm__(".p2align 5"); - __asm__("nop"); - __asm__(".p2align 4"); -#endif - for ( ; ; ) { - seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch); - size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd); -#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE) - assert(!ZSTD_isError(oneSeqSize)); - if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase); -#endif - DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); - BIT_reloadDStream(&(seqState.DStream)); - /* gcc and clang both don't like early returns in this loop. - * gcc doesn't like early breaks either. - * Instead save an error and report it at the end. - * When there is an error, don't increment op, so we don't - * overwrite. - */ - if (UNLIKELY(ZSTD_isError(oneSeqSize))) error = oneSeqSize; - else op += oneSeqSize; - if (UNLIKELY(!--nbSeq)) break; - } - - /* check if reached exact end */ - DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq); - if (ZSTD_isError(error)) return error; - RETURN_ERROR_IF(nbSeq, corruption_detected, ""); - RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected, ""); - /* save reps for next block */ - { U32 i; for (i=0; ientropy.rep[i] = (U32)(seqState.prevOffset[i]); } - } - - /* last literal segment */ - { size_t const lastLLSize = litEnd - litPtr; - RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); - if (op != NULL) { - memcpy(op, litPtr, lastLLSize); - op += lastLLSize; - } - } - - return op-ostart; -} - -static size_t -ZSTD_decompressSequences_default(ZSTD_DCtx* dctx, - void* dst, size_t maxDstSize, - const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset, - const int frame) -{ - return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); -} -#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */ - -#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT -FORCE_INLINE_TEMPLATE size_t -ZSTD_decompressSequencesLong_body( - ZSTD_DCtx* dctx, - void* dst, size_t maxDstSize, - const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset, - const int frame) -{ - const BYTE* ip = (const BYTE*)seqStart; - const BYTE* const iend = ip + seqSize; - BYTE* const ostart = (BYTE* const)dst; - BYTE* const oend = ostart + maxDstSize; - BYTE* op = ostart; - const BYTE* litPtr = dctx->litPtr; - const BYTE* const litEnd = litPtr + dctx->litSize; - const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart); - const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart); - const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); - (void)frame; - - /* Regen sequences */ - if (nbSeq) { -#define STORED_SEQS 4 -#define STORED_SEQS_MASK (STORED_SEQS-1) -#define ADVANCED_SEQS 4 - seq_t sequences[STORED_SEQS]; - int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS); - seqState_t seqState; - int seqNb; - dctx->fseEntropy = 1; - { int i; for (i=0; ientropy.rep[i]; } - seqState.prefixStart = prefixStart; - seqState.pos = (size_t)(op-prefixStart); - seqState.dictEnd = dictEnd; - assert(dst != NULL); - assert(iend >= ip); - RETURN_ERROR_IF( - ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)), - corruption_detected, ""); - ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); - ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); - ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); - - /* prepare in advance */ - for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNbentropy.rep[i] = (U32)(seqState.prevOffset[i]); } - } - - /* last literal segment */ - { size_t const lastLLSize = litEnd - litPtr; - RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); - if (op != NULL) { - memcpy(op, litPtr, lastLLSize); - op += lastLLSize; - } - } - - return op-ostart; -} - -static size_t -ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx, - void* dst, size_t maxDstSize, - const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset, - const int frame) -{ - return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); -} -#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */ - - - -#if DYNAMIC_BMI2 - -#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG -#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */ - -#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT -static TARGET_ATTRIBUTE("bmi2") size_t -ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx, - void* dst, size_t maxDstSize, - const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset, - const int frame) -{ - return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); -} -#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */ - -#endif /* DYNAMIC_BMI2 */ - -typedef size_t (*ZSTD_decompressSequences_t)( - ZSTD_DCtx* dctx, - void* dst, size_t maxDstSize, - const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset, - const int frame); - -#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG -static size_t -ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, - const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset, - const int frame) -{ - DEBUGLOG(5, "ZSTD_decompressSequences"); - return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); -} -#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */ - - -#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT -/* ZSTD_decompressSequencesLong() : - * decompression function triggered when a minimum share of offsets is considered "long", - * aka out of cache. - * note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes meaning "farther than memory cache distance". - * This function will try to mitigate main memory latency through the use of prefetching */ -static size_t -ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx, - void* dst, size_t maxDstSize, - const void* seqStart, size_t seqSize, int nbSeq, - const ZSTD_longOffset_e isLongOffset, - const int frame) -{ - DEBUGLOG(5, "ZSTD_decompressSequencesLong"); -#if DYNAMIC_BMI2 - if (dctx->bmi2) { - return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); - } -#endif - return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame); -} -#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */ - - - -#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \ - !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG) -/* ZSTD_getLongOffsetsShare() : - * condition : offTable must be valid - * @return : "share" of long offsets (arbitrarily defined as > (1<<23)) - * compared to maximum possible of (1< 22) total += 1; - } - - assert(tableLog <= OffFSELog); - total <<= (OffFSELog - tableLog); /* scale to OffFSELog */ - - return total; -} -#endif - -size_t -ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, const int frame) -{ /* blockType == blockCompressed */ - const BYTE* ip = (const BYTE*)src; - /* isLongOffset must be true if there are long offsets. - * Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN. - * We don't expect that to be the case in 64-bit mode. - * In block mode, window size is not known, so we have to be conservative. - * (note: but it could be evaluated from current-lowLimit) - */ - ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN)))); - DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize); - - RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong, ""); - - /* Decode literals section */ - { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize); - DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize); - if (ZSTD_isError(litCSize)) return litCSize; - ip += litCSize; - srcSize -= litCSize; - } - - /* Build Decoding Tables */ - { - /* These macros control at build-time which decompressor implementation - * we use. If neither is defined, we do some inspection and dispatch at - * runtime. - */ -#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \ - !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG) - int usePrefetchDecoder = dctx->ddictIsCold; -#endif - int nbSeq; - size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize); - if (ZSTD_isError(seqHSize)) return seqHSize; - ip += seqHSize; - srcSize -= seqHSize; - - RETURN_ERROR_IF(dst == NULL && nbSeq > 0, dstSize_tooSmall, "NULL not handled"); - -#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \ - !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG) - if ( !usePrefetchDecoder - && (!frame || (dctx->fParams.windowSize > (1<<24))) - && (nbSeq>ADVANCED_SEQS) ) { /* could probably use a larger nbSeq limit */ - U32 const shareLongOffsets = ZSTD_getLongOffsetsShare(dctx->OFTptr); - U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */ - usePrefetchDecoder = (shareLongOffsets >= minShare); - } -#endif - - dctx->ddictIsCold = 0; - -#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \ - !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG) - if (usePrefetchDecoder) -#endif -#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT - return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame); -#endif - -#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG - /* else */ - return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame); -#endif - } -} - - -void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst) -{ - if (dst != dctx->previousDstEnd) { /* not contiguous */ - dctx->dictEnd = dctx->previousDstEnd; - dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart)); - dctx->prefixStart = dst; - dctx->previousDstEnd = dst; - } -} - - -size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize) -{ - size_t dSize; - ZSTD_checkContinuity(dctx, dst); - dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0); - dctx->previousDstEnd = (char*)dst + dSize; - return dSize; -} - -} \ No newline at end of file diff --git a/third_party/zstd/deprecated/zbuff_common.c b/third_party/zstd/deprecated/zbuff_common.c new file mode 100644 index 00000000000..5a2f2db354f --- /dev/null +++ b/third_party/zstd/deprecated/zbuff_common.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/*-************************************* +* Dependencies +***************************************/ +#include "../common/error_private.h" +#include "zbuff.h" + +/*-**************************************** +* ZBUFF Error Management (deprecated) +******************************************/ + +/*! ZBUFF_isError() : +* tells if a return value is an error code */ +unsigned ZBUFF_isError(size_t errorCode) { return ERR_isError(errorCode); } +/*! ZBUFF_getErrorName() : +* provides error code string from function result (useful for debugging) */ +const char* ZBUFF_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); } diff --git a/third_party/zstd/deprecated/zbuff_compress.c b/third_party/zstd/deprecated/zbuff_compress.c new file mode 100644 index 00000000000..1d8682150b2 --- /dev/null +++ b/third_party/zstd/deprecated/zbuff_compress.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + + +/* ************************************* +* Dependencies +***************************************/ +#define ZBUFF_STATIC_LINKING_ONLY +#include "zbuff.h" +#include "../common/error_private.h" + + +/*-*********************************************************** +* Streaming compression +* +* A ZBUFF_CCtx object is required to track streaming operation. +* Use ZBUFF_createCCtx() and ZBUFF_freeCCtx() to create/release resources. +* Use ZBUFF_compressInit() to start a new compression operation. +* ZBUFF_CCtx objects can be reused multiple times. +* +* Use ZBUFF_compressContinue() repetitively to consume your input. +* *srcSizePtr and *dstCapacityPtr can be any size. +* The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr. +* Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input. +* The content of dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters or change dst . +* @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency) +* or an error code, which can be tested using ZBUFF_isError(). +* +* ZBUFF_compressFlush() can be used to instruct ZBUFF to compress and output whatever remains within its buffer. +* Note that it will not output more than *dstCapacityPtr. +* Therefore, some content might still be left into its internal buffer if dst buffer is too small. +* @return : nb of bytes still present into internal buffer (0 if it's empty) +* or an error code, which can be tested using ZBUFF_isError(). +* +* ZBUFF_compressEnd() instructs to finish a frame. +* It will perform a flush and write frame epilogue. +* Similar to ZBUFF_compressFlush(), it may not be able to output the entire internal buffer content if *dstCapacityPtr is too small. +* @return : nb of bytes still present into internal buffer (0 if it's empty) +* or an error code, which can be tested using ZBUFF_isError(). +* +* Hint : recommended buffer sizes (not compulsory) +* input : ZSTD_BLOCKSIZE_MAX (128 KB), internal unit size, it improves latency to use this value. +* output : ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + ZBUFF_endFrameSize : ensures it's always possible to write/flush/end a full block at best speed. +* ***********************************************************/ + +ZBUFF_CCtx* ZBUFF_createCCtx(void) +{ + return ZSTD_createCStream(); +} + +ZBUFF_CCtx* ZBUFF_createCCtx_advanced(ZSTD_customMem customMem) +{ + return ZSTD_createCStream_advanced(customMem); +} + +size_t ZBUFF_freeCCtx(ZBUFF_CCtx* zbc) +{ + return ZSTD_freeCStream(zbc); +} + + +/* ====== Initialization ====== */ + +size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc, + const void* dict, size_t dictSize, + ZSTD_parameters params, unsigned long long pledgedSrcSize) +{ + if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* preserve "0 == unknown" behavior */ + FORWARD_IF_ERROR(ZSTD_CCtx_reset(zbc, ZSTD_reset_session_only), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setPledgedSrcSize(zbc, pledgedSrcSize), ""); + + FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_windowLog, params.cParams.windowLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_hashLog, params.cParams.hashLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_chainLog, params.cParams.chainLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_searchLog, params.cParams.searchLog), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_minMatch, params.cParams.minMatch), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_targetLength, params.cParams.targetLength), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_strategy, params.cParams.strategy), ""); + + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_contentSizeFlag, params.fParams.contentSizeFlag), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_checksumFlag, params.fParams.checksumFlag), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_dictIDFlag, params.fParams.noDictIDFlag), ""); + + FORWARD_IF_ERROR(ZSTD_CCtx_loadDictionary(zbc, dict, dictSize), ""); + return 0; +} + +size_t ZBUFF_compressInitDictionary(ZBUFF_CCtx* zbc, const void* dict, size_t dictSize, int compressionLevel) +{ + FORWARD_IF_ERROR(ZSTD_CCtx_reset(zbc, ZSTD_reset_session_only), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(zbc, ZSTD_c_compressionLevel, compressionLevel), ""); + FORWARD_IF_ERROR(ZSTD_CCtx_loadDictionary(zbc, dict, dictSize), ""); + return 0; +} + +size_t ZBUFF_compressInit(ZBUFF_CCtx* zbc, int compressionLevel) +{ + return ZSTD_initCStream(zbc, compressionLevel); +} + +/* ====== Compression ====== */ + + +size_t ZBUFF_compressContinue(ZBUFF_CCtx* zbc, + void* dst, size_t* dstCapacityPtr, + const void* src, size_t* srcSizePtr) +{ + size_t result; + ZSTD_outBuffer outBuff; + ZSTD_inBuffer inBuff; + outBuff.dst = dst; + outBuff.pos = 0; + outBuff.size = *dstCapacityPtr; + inBuff.src = src; + inBuff.pos = 0; + inBuff.size = *srcSizePtr; + result = ZSTD_compressStream(zbc, &outBuff, &inBuff); + *dstCapacityPtr = outBuff.pos; + *srcSizePtr = inBuff.pos; + return result; +} + + + +/* ====== Finalize ====== */ + +size_t ZBUFF_compressFlush(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr) +{ + size_t result; + ZSTD_outBuffer outBuff; + outBuff.dst = dst; + outBuff.pos = 0; + outBuff.size = *dstCapacityPtr; + result = ZSTD_flushStream(zbc, &outBuff); + *dstCapacityPtr = outBuff.pos; + return result; +} + + +size_t ZBUFF_compressEnd(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr) +{ + size_t result; + ZSTD_outBuffer outBuff; + outBuff.dst = dst; + outBuff.pos = 0; + outBuff.size = *dstCapacityPtr; + result = ZSTD_endStream(zbc, &outBuff); + *dstCapacityPtr = outBuff.pos; + return result; +} + + + +/* ************************************* +* Tool functions +***************************************/ +size_t ZBUFF_recommendedCInSize(void) { return ZSTD_CStreamInSize(); } +size_t ZBUFF_recommendedCOutSize(void) { return ZSTD_CStreamOutSize(); } diff --git a/third_party/zstd/deprecated/zbuff_decompress.c b/third_party/zstd/deprecated/zbuff_decompress.c new file mode 100644 index 00000000000..12a66af7412 --- /dev/null +++ b/third_party/zstd/deprecated/zbuff_decompress.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + + +/* ************************************* +* Dependencies +***************************************/ +#define ZSTD_DISABLE_DEPRECATE_WARNINGS /* suppress warning on ZSTD_initDStream_usingDict */ +#include "../zstd.h" /* ZSTD_CStream, ZSTD_DStream, ZSTDLIB_API */ +#define ZBUFF_STATIC_LINKING_ONLY +#include "zbuff.h" + + +ZBUFF_DCtx* ZBUFF_createDCtx(void) +{ + return ZSTD_createDStream(); +} + +ZBUFF_DCtx* ZBUFF_createDCtx_advanced(ZSTD_customMem customMem) +{ + return ZSTD_createDStream_advanced(customMem); +} + +size_t ZBUFF_freeDCtx(ZBUFF_DCtx* zbd) +{ + return ZSTD_freeDStream(zbd); +} + + +/* *** Initialization *** */ + +size_t ZBUFF_decompressInitDictionary(ZBUFF_DCtx* zbd, const void* dict, size_t dictSize) +{ + return ZSTD_initDStream_usingDict(zbd, dict, dictSize); +} + +size_t ZBUFF_decompressInit(ZBUFF_DCtx* zbd) +{ + return ZSTD_initDStream(zbd); +} + + +/* *** Decompression *** */ + +size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, + void* dst, size_t* dstCapacityPtr, + const void* src, size_t* srcSizePtr) +{ + ZSTD_outBuffer outBuff; + ZSTD_inBuffer inBuff; + size_t result; + outBuff.dst = dst; + outBuff.pos = 0; + outBuff.size = *dstCapacityPtr; + inBuff.src = src; + inBuff.pos = 0; + inBuff.size = *srcSizePtr; + result = ZSTD_decompressStream(zbd, &outBuff, &inBuff); + *dstCapacityPtr = outBuff.pos; + *srcSizePtr = inBuff.pos; + return result; +} + + +/* ************************************* +* Tool functions +***************************************/ +size_t ZBUFF_recommendedDInSize(void) { return ZSTD_DStreamInSize(); } +size_t ZBUFF_recommendedDOutSize(void) { return ZSTD_DStreamOutSize(); } diff --git a/third_party/zstd/dict/cover.c b/third_party/zstd/dict/cover.c new file mode 100644 index 00000000000..44f9029acd9 --- /dev/null +++ b/third_party/zstd/dict/cover.c @@ -0,0 +1,1261 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* ***************************************************************************** + * Constructs a dictionary using a heuristic based on the following paper: + * + * Liao, Petri, Moffat, Wirth + * Effective Construction of Relative Lempel-Ziv Dictionaries + * Published in WWW 2016. + * + * Adapted from code originally written by @ot (Giuseppe Ottaviano). + ******************************************************************************/ + +/*-************************************* +* Dependencies +***************************************/ +#include /* fprintf */ +#include /* malloc, free, qsort */ +#include /* memset */ +#include /* clock */ + +#ifndef ZDICT_STATIC_LINKING_ONLY +# define ZDICT_STATIC_LINKING_ONLY +#endif + +#include "../common/mem.h" /* read */ +#include "../common/pool.h" /* POOL_ctx */ +#include "../common/threading.h" /* ZSTD_pthread_mutex_t */ +#include "../common/zstd_internal.h" /* includes zstd.h */ +#include "../common/bits.h" /* ZSTD_highbit32 */ +#include "../zdict.h" +#include "cover.h" + +/*-************************************* +* Constants +***************************************/ +/** +* There are 32bit indexes used to ref samples, so limit samples size to 4GB +* on 64bit builds. +* For 32bit builds we choose 1 GB. +* Most 32bit platforms have 2GB user-mode addressable space and we allocate a large +* contiguous buffer, so 1GB is already a high limit. +*/ +#define COVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB)) +#define COVER_DEFAULT_SPLITPOINT 1.0 + +/*-************************************* +* Console display +***************************************/ +#ifndef LOCALDISPLAYLEVEL +static int g_displayLevel = 0; +#endif +#undef DISPLAY +#define DISPLAY(...) \ + { \ + fprintf(stderr, __VA_ARGS__); \ + fflush(stderr); \ + } +#undef LOCALDISPLAYLEVEL +#define LOCALDISPLAYLEVEL(displayLevel, l, ...) \ + if (displayLevel >= l) { \ + DISPLAY(__VA_ARGS__); \ + } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */ +#undef DISPLAYLEVEL +#define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__) + +#ifndef LOCALDISPLAYUPDATE +static const clock_t g_refreshRate = CLOCKS_PER_SEC * 15 / 100; +static clock_t g_time = 0; +#endif +#undef LOCALDISPLAYUPDATE +#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \ + if (displayLevel >= l) { \ + if ((clock() - g_time > g_refreshRate) || (displayLevel >= 4)) { \ + g_time = clock(); \ + DISPLAY(__VA_ARGS__); \ + } \ + } +#undef DISPLAYUPDATE +#define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__) + +/*-************************************* +* Hash table +*************************************** +* A small specialized hash map for storing activeDmers. +* The map does not resize, so if it becomes full it will loop forever. +* Thus, the map must be large enough to store every value. +* The map implements linear probing and keeps its load less than 0.5. +*/ + +#define MAP_EMPTY_VALUE ((U32)-1) +typedef struct COVER_map_pair_t_s { + U32 key; + U32 value; +} COVER_map_pair_t; + +typedef struct COVER_map_s { + COVER_map_pair_t *data; + U32 sizeLog; + U32 size; + U32 sizeMask; +} COVER_map_t; + +/** + * Clear the map. + */ +static void COVER_map_clear(COVER_map_t *map) { + memset(map->data, MAP_EMPTY_VALUE, map->size * sizeof(COVER_map_pair_t)); +} + +/** + * Initializes a map of the given size. + * Returns 1 on success and 0 on failure. + * The map must be destroyed with COVER_map_destroy(). + * The map is only guaranteed to be large enough to hold size elements. + */ +static int COVER_map_init(COVER_map_t *map, U32 size) { + map->sizeLog = ZSTD_highbit32(size) + 2; + map->size = (U32)1 << map->sizeLog; + map->sizeMask = map->size - 1; + map->data = (COVER_map_pair_t *)malloc(map->size * sizeof(COVER_map_pair_t)); + if (!map->data) { + map->sizeLog = 0; + map->size = 0; + return 0; + } + COVER_map_clear(map); + return 1; +} + +/** + * Internal hash function + */ +static const U32 COVER_prime4bytes = 2654435761U; +static U32 COVER_map_hash(COVER_map_t *map, U32 key) { + return (key * COVER_prime4bytes) >> (32 - map->sizeLog); +} + +/** + * Helper function that returns the index that a key should be placed into. + */ +static U32 COVER_map_index(COVER_map_t *map, U32 key) { + const U32 hash = COVER_map_hash(map, key); + U32 i; + for (i = hash;; i = (i + 1) & map->sizeMask) { + COVER_map_pair_t *pos = &map->data[i]; + if (pos->value == MAP_EMPTY_VALUE) { + return i; + } + if (pos->key == key) { + return i; + } + } +} + +/** + * Returns the pointer to the value for key. + * If key is not in the map, it is inserted and the value is set to 0. + * The map must not be full. + */ +static U32 *COVER_map_at(COVER_map_t *map, U32 key) { + COVER_map_pair_t *pos = &map->data[COVER_map_index(map, key)]; + if (pos->value == MAP_EMPTY_VALUE) { + pos->key = key; + pos->value = 0; + } + return &pos->value; +} + +/** + * Deletes key from the map if present. + */ +static void COVER_map_remove(COVER_map_t *map, U32 key) { + U32 i = COVER_map_index(map, key); + COVER_map_pair_t *del = &map->data[i]; + U32 shift = 1; + if (del->value == MAP_EMPTY_VALUE) { + return; + } + for (i = (i + 1) & map->sizeMask;; i = (i + 1) & map->sizeMask) { + COVER_map_pair_t *const pos = &map->data[i]; + /* If the position is empty we are done */ + if (pos->value == MAP_EMPTY_VALUE) { + del->value = MAP_EMPTY_VALUE; + return; + } + /* If pos can be moved to del do so */ + if (((i - COVER_map_hash(map, pos->key)) & map->sizeMask) >= shift) { + del->key = pos->key; + del->value = pos->value; + del = pos; + shift = 1; + } else { + ++shift; + } + } +} + +/** + * Destroys a map that is inited with COVER_map_init(). + */ +static void COVER_map_destroy(COVER_map_t *map) { + if (map->data) { + free(map->data); + } + map->data = NULL; + map->size = 0; +} + +/*-************************************* +* Context +***************************************/ + +typedef struct { + const BYTE *samples; + size_t *offsets; + const size_t *samplesSizes; + size_t nbSamples; + size_t nbTrainSamples; + size_t nbTestSamples; + U32 *suffix; + size_t suffixSize; + U32 *freqs; + U32 *dmerAt; + unsigned d; +} COVER_ctx_t; + +/* We need a global context for qsort... */ +static COVER_ctx_t *g_coverCtx = NULL; + +/*-************************************* +* Helper functions +***************************************/ + +/** + * Returns the sum of the sample sizes. + */ +size_t COVER_sum(const size_t *samplesSizes, unsigned nbSamples) { + size_t sum = 0; + unsigned i; + for (i = 0; i < nbSamples; ++i) { + sum += samplesSizes[i]; + } + return sum; +} + +/** + * Returns -1 if the dmer at lp is less than the dmer at rp. + * Return 0 if the dmers at lp and rp are equal. + * Returns 1 if the dmer at lp is greater than the dmer at rp. + */ +static int COVER_cmp(COVER_ctx_t *ctx, const void *lp, const void *rp) { + U32 const lhs = *(U32 const *)lp; + U32 const rhs = *(U32 const *)rp; + return memcmp(ctx->samples + lhs, ctx->samples + rhs, ctx->d); +} +/** + * Faster version for d <= 8. + */ +static int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) { + U64 const mask = (ctx->d == 8) ? (U64)-1 : (((U64)1 << (8 * ctx->d)) - 1); + U64 const lhs = MEM_readLE64(ctx->samples + *(U32 const *)lp) & mask; + U64 const rhs = MEM_readLE64(ctx->samples + *(U32 const *)rp) & mask; + if (lhs < rhs) { + return -1; + } + return (lhs > rhs); +} + +/** + * Same as COVER_cmp() except ties are broken by pointer value + * NOTE: g_coverCtx must be set to call this function. A global is required because + * qsort doesn't take an opaque pointer. + */ +static int WIN_CDECL COVER_strict_cmp(const void *lp, const void *rp) { + int result = COVER_cmp(g_coverCtx, lp, rp); + if (result == 0) { + result = lp < rp ? -1 : 1; + } + return result; +} +/** + * Faster version for d <= 8. + */ +static int WIN_CDECL COVER_strict_cmp8(const void *lp, const void *rp) { + int result = COVER_cmp8(g_coverCtx, lp, rp); + if (result == 0) { + result = lp < rp ? -1 : 1; + } + return result; +} + +/** + * Returns the first pointer in [first, last) whose element does not compare + * less than value. If no such element exists it returns last. + */ +static const size_t *COVER_lower_bound(const size_t* first, const size_t* last, + size_t value) { + size_t count = (size_t)(last - first); + assert(last >= first); + while (count != 0) { + size_t step = count / 2; + const size_t *ptr = first; + ptr += step; + if (*ptr < value) { + first = ++ptr; + count -= step + 1; + } else { + count = step; + } + } + return first; +} + +/** + * Generic groupBy function. + * Groups an array sorted by cmp into groups with equivalent values. + * Calls grp for each group. + */ +static void +COVER_groupBy(const void *data, size_t count, size_t size, COVER_ctx_t *ctx, + int (*cmp)(COVER_ctx_t *, const void *, const void *), + void (*grp)(COVER_ctx_t *, const void *, const void *)) { + const BYTE *ptr = (const BYTE *)data; + size_t num = 0; + while (num < count) { + const BYTE *grpEnd = ptr + size; + ++num; + while (num < count && cmp(ctx, ptr, grpEnd) == 0) { + grpEnd += size; + ++num; + } + grp(ctx, ptr, grpEnd); + ptr = grpEnd; + } +} + +/*-************************************* +* Cover functions +***************************************/ + +/** + * Called on each group of positions with the same dmer. + * Counts the frequency of each dmer and saves it in the suffix array. + * Fills `ctx->dmerAt`. + */ +static void COVER_group(COVER_ctx_t *ctx, const void *group, + const void *groupEnd) { + /* The group consists of all the positions with the same first d bytes. */ + const U32 *grpPtr = (const U32 *)group; + const U32 *grpEnd = (const U32 *)groupEnd; + /* The dmerId is how we will reference this dmer. + * This allows us to map the whole dmer space to a much smaller space, the + * size of the suffix array. + */ + const U32 dmerId = (U32)(grpPtr - ctx->suffix); + /* Count the number of samples this dmer shows up in */ + U32 freq = 0; + /* Details */ + const size_t *curOffsetPtr = ctx->offsets; + const size_t *offsetsEnd = ctx->offsets + ctx->nbSamples; + /* Once *grpPtr >= curSampleEnd this occurrence of the dmer is in a + * different sample than the last. + */ + size_t curSampleEnd = ctx->offsets[0]; + for (; grpPtr != grpEnd; ++grpPtr) { + /* Save the dmerId for this position so we can get back to it. */ + ctx->dmerAt[*grpPtr] = dmerId; + /* Dictionaries only help for the first reference to the dmer. + * After that zstd can reference the match from the previous reference. + * So only count each dmer once for each sample it is in. + */ + if (*grpPtr < curSampleEnd) { + continue; + } + freq += 1; + /* Binary search to find the end of the sample *grpPtr is in. + * In the common case that grpPtr + 1 == grpEnd we can skip the binary + * search because the loop is over. + */ + if (grpPtr + 1 != grpEnd) { + const size_t *sampleEndPtr = + COVER_lower_bound(curOffsetPtr, offsetsEnd, *grpPtr); + curSampleEnd = *sampleEndPtr; + curOffsetPtr = sampleEndPtr + 1; + } + } + /* At this point we are never going to look at this segment of the suffix + * array again. We take advantage of this fact to save memory. + * We store the frequency of the dmer in the first position of the group, + * which is dmerId. + */ + ctx->suffix[dmerId] = freq; +} + + +/** + * Selects the best segment in an epoch. + * Segments of are scored according to the function: + * + * Let F(d) be the frequency of dmer d. + * Let S_i be the dmer at position i of segment S which has length k. + * + * Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1}) + * + * Once the dmer d is in the dictionary we set F(d) = 0. + */ +static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs, + COVER_map_t *activeDmers, U32 begin, + U32 end, + ZDICT_cover_params_t parameters) { + /* Constants */ + const U32 k = parameters.k; + const U32 d = parameters.d; + const U32 dmersInK = k - d + 1; + /* Try each segment (activeSegment) and save the best (bestSegment) */ + COVER_segment_t bestSegment = {0, 0, 0}; + COVER_segment_t activeSegment; + /* Reset the activeDmers in the segment */ + COVER_map_clear(activeDmers); + /* The activeSegment starts at the beginning of the epoch. */ + activeSegment.begin = begin; + activeSegment.end = begin; + activeSegment.score = 0; + /* Slide the activeSegment through the whole epoch. + * Save the best segment in bestSegment. + */ + while (activeSegment.end < end) { + /* The dmerId for the dmer at the next position */ + U32 newDmer = ctx->dmerAt[activeSegment.end]; + /* The entry in activeDmers for this dmerId */ + U32 *newDmerOcc = COVER_map_at(activeDmers, newDmer); + /* If the dmer isn't already present in the segment add its score. */ + if (*newDmerOcc == 0) { + /* The paper suggest using the L-0.5 norm, but experiments show that it + * doesn't help. + */ + activeSegment.score += freqs[newDmer]; + } + /* Add the dmer to the segment */ + activeSegment.end += 1; + *newDmerOcc += 1; + + /* If the window is now too large, drop the first position */ + if (activeSegment.end - activeSegment.begin == dmersInK + 1) { + U32 delDmer = ctx->dmerAt[activeSegment.begin]; + U32 *delDmerOcc = COVER_map_at(activeDmers, delDmer); + activeSegment.begin += 1; + *delDmerOcc -= 1; + /* If this is the last occurrence of the dmer, subtract its score */ + if (*delDmerOcc == 0) { + COVER_map_remove(activeDmers, delDmer); + activeSegment.score -= freqs[delDmer]; + } + } + + /* If this segment is the best so far save it */ + if (activeSegment.score > bestSegment.score) { + bestSegment = activeSegment; + } + } + { + /* Trim off the zero frequency head and tail from the segment. */ + U32 newBegin = bestSegment.end; + U32 newEnd = bestSegment.begin; + U32 pos; + for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) { + U32 freq = freqs[ctx->dmerAt[pos]]; + if (freq != 0) { + newBegin = MIN(newBegin, pos); + newEnd = pos + 1; + } + } + bestSegment.begin = newBegin; + bestSegment.end = newEnd; + } + { + /* Zero out the frequency of each dmer covered by the chosen segment. */ + U32 pos; + for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) { + freqs[ctx->dmerAt[pos]] = 0; + } + } + return bestSegment; +} + +/** + * Check the validity of the parameters. + * Returns non-zero if the parameters are valid and 0 otherwise. + */ +static int COVER_checkParameters(ZDICT_cover_params_t parameters, + size_t maxDictSize) { + /* k and d are required parameters */ + if (parameters.d == 0 || parameters.k == 0) { + return 0; + } + /* k <= maxDictSize */ + if (parameters.k > maxDictSize) { + return 0; + } + /* d <= k */ + if (parameters.d > parameters.k) { + return 0; + } + /* 0 < splitPoint <= 1 */ + if (parameters.splitPoint <= 0 || parameters.splitPoint > 1){ + return 0; + } + return 1; +} + +/** + * Clean up a context initialized with `COVER_ctx_init()`. + */ +static void COVER_ctx_destroy(COVER_ctx_t *ctx) { + if (!ctx) { + return; + } + if (ctx->suffix) { + free(ctx->suffix); + ctx->suffix = NULL; + } + if (ctx->freqs) { + free(ctx->freqs); + ctx->freqs = NULL; + } + if (ctx->dmerAt) { + free(ctx->dmerAt); + ctx->dmerAt = NULL; + } + if (ctx->offsets) { + free(ctx->offsets); + ctx->offsets = NULL; + } +} + +/** + * Prepare a context for dictionary building. + * The context is only dependent on the parameter `d` and can be used multiple + * times. + * Returns 0 on success or error code on error. + * The context must be destroyed with `COVER_ctx_destroy()`. + */ +static size_t COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer, + const size_t *samplesSizes, unsigned nbSamples, + unsigned d, double splitPoint) +{ + const BYTE *const samples = (const BYTE *)samplesBuffer; + const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples); + /* Split samples into testing and training sets */ + const unsigned nbTrainSamples = splitPoint < 1.0 ? (unsigned)((double)nbSamples * splitPoint) : nbSamples; + const unsigned nbTestSamples = splitPoint < 1.0 ? nbSamples - nbTrainSamples : nbSamples; + const size_t trainingSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes, nbTrainSamples) : totalSamplesSize; + const size_t testSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes + nbTrainSamples, nbTestSamples) : totalSamplesSize; + /* Checks */ + if (totalSamplesSize < MAX(d, sizeof(U64)) || + totalSamplesSize >= (size_t)COVER_MAX_SAMPLES_SIZE) { + DISPLAYLEVEL(1, "Total samples size is too large (%u MB), maximum size is %u MB\n", + (unsigned)(totalSamplesSize>>20), (COVER_MAX_SAMPLES_SIZE >> 20)); + return ERROR(srcSize_wrong); + } + /* Check if there are at least 5 training samples */ + if (nbTrainSamples < 5) { + DISPLAYLEVEL(1, "Total number of training samples is %u and is invalid.", nbTrainSamples); + return ERROR(srcSize_wrong); + } + /* Check if there's testing sample */ + if (nbTestSamples < 1) { + DISPLAYLEVEL(1, "Total number of testing samples is %u and is invalid.", nbTestSamples); + return ERROR(srcSize_wrong); + } + /* Zero the context */ + memset(ctx, 0, sizeof(*ctx)); + DISPLAYLEVEL(2, "Training on %u samples of total size %u\n", nbTrainSamples, + (unsigned)trainingSamplesSize); + DISPLAYLEVEL(2, "Testing on %u samples of total size %u\n", nbTestSamples, + (unsigned)testSamplesSize); + ctx->samples = samples; + ctx->samplesSizes = samplesSizes; + ctx->nbSamples = nbSamples; + ctx->nbTrainSamples = nbTrainSamples; + ctx->nbTestSamples = nbTestSamples; + /* Partial suffix array */ + ctx->suffixSize = trainingSamplesSize - MAX(d, sizeof(U64)) + 1; + ctx->suffix = (U32 *)malloc(ctx->suffixSize * sizeof(U32)); + /* Maps index to the dmerID */ + ctx->dmerAt = (U32 *)malloc(ctx->suffixSize * sizeof(U32)); + /* The offsets of each file */ + ctx->offsets = (size_t *)malloc((nbSamples + 1) * sizeof(size_t)); + if (!ctx->suffix || !ctx->dmerAt || !ctx->offsets) { + DISPLAYLEVEL(1, "Failed to allocate scratch buffers\n"); + COVER_ctx_destroy(ctx); + return ERROR(memory_allocation); + } + ctx->freqs = NULL; + ctx->d = d; + + /* Fill offsets from the samplesSizes */ + { + U32 i; + ctx->offsets[0] = 0; + for (i = 1; i <= nbSamples; ++i) { + ctx->offsets[i] = ctx->offsets[i - 1] + samplesSizes[i - 1]; + } + } + DISPLAYLEVEL(2, "Constructing partial suffix array\n"); + { + /* suffix is a partial suffix array. + * It only sorts suffixes by their first parameters.d bytes. + * The sort is stable, so each dmer group is sorted by position in input. + */ + U32 i; + for (i = 0; i < ctx->suffixSize; ++i) { + ctx->suffix[i] = i; + } + /* qsort doesn't take an opaque pointer, so pass as a global. + * On OpenBSD qsort() is not guaranteed to be stable, their mergesort() is. + */ + g_coverCtx = ctx; +#if defined(__OpenBSD__) + mergesort(ctx->suffix, ctx->suffixSize, sizeof(U32), + (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); +#else + qsort(ctx->suffix, ctx->suffixSize, sizeof(U32), + (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); +#endif + } + DISPLAYLEVEL(2, "Computing frequencies\n"); + /* For each dmer group (group of positions with the same first d bytes): + * 1. For each position we set dmerAt[position] = dmerID. The dmerID is + * (groupBeginPtr - suffix). This allows us to go from position to + * dmerID so we can look up values in freq. + * 2. We calculate how many samples the dmer occurs in and save it in + * freqs[dmerId]. + */ + COVER_groupBy(ctx->suffix, ctx->suffixSize, sizeof(U32), ctx, + (ctx->d <= 8 ? &COVER_cmp8 : &COVER_cmp), &COVER_group); + ctx->freqs = ctx->suffix; + ctx->suffix = NULL; + return 0; +} + +void COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel) +{ + const double ratio = (double)nbDmers / (double)maxDictSize; + if (ratio >= 10) { + return; + } + LOCALDISPLAYLEVEL(displayLevel, 1, + "WARNING: The maximum dictionary size %u is too large " + "compared to the source size %u! " + "size(source)/size(dictionary) = %f, but it should be >= " + "10! This may lead to a subpar dictionary! We recommend " + "training on sources at least 10x, and preferably 100x " + "the size of the dictionary! \n", (U32)maxDictSize, + (U32)nbDmers, ratio); +} + +COVER_epoch_info_t COVER_computeEpochs(U32 maxDictSize, + U32 nbDmers, U32 k, U32 passes) +{ + const U32 minEpochSize = k * 10; + COVER_epoch_info_t epochs; + epochs.num = MAX(1, maxDictSize / k / passes); + epochs.size = nbDmers / epochs.num; + if (epochs.size >= minEpochSize) { + assert(epochs.size * epochs.num <= nbDmers); + return epochs; + } + epochs.size = MIN(minEpochSize, nbDmers); + epochs.num = nbDmers / epochs.size; + assert(epochs.size * epochs.num <= nbDmers); + return epochs; +} + +/** + * Given the prepared context build the dictionary. + */ +static size_t COVER_buildDictionary(const COVER_ctx_t *ctx, U32 *freqs, + COVER_map_t *activeDmers, void *dictBuffer, + size_t dictBufferCapacity, + ZDICT_cover_params_t parameters) { + BYTE *const dict = (BYTE *)dictBuffer; + size_t tail = dictBufferCapacity; + /* Divide the data into epochs. We will select one segment from each epoch. */ + const COVER_epoch_info_t epochs = COVER_computeEpochs( + (U32)dictBufferCapacity, (U32)ctx->suffixSize, parameters.k, 4); + const size_t maxZeroScoreRun = MAX(10, MIN(100, epochs.num >> 3)); + size_t zeroScoreRun = 0; + size_t epoch; + DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n", + (U32)epochs.num, (U32)epochs.size); + /* Loop through the epochs until there are no more segments or the dictionary + * is full. + */ + for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs.num) { + const U32 epochBegin = (U32)(epoch * epochs.size); + const U32 epochEnd = epochBegin + epochs.size; + size_t segmentSize; + /* Select a segment */ + COVER_segment_t segment = COVER_selectSegment( + ctx, freqs, activeDmers, epochBegin, epochEnd, parameters); + /* If the segment covers no dmers, then we are out of content. + * There may be new content in other epochs, for continue for some time. + */ + if (segment.score == 0) { + if (++zeroScoreRun >= maxZeroScoreRun) { + break; + } + continue; + } + zeroScoreRun = 0; + /* Trim the segment if necessary and if it is too small then we are done */ + segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail); + if (segmentSize < parameters.d) { + break; + } + /* We fill the dictionary from the back to allow the best segments to be + * referenced with the smallest offsets. + */ + tail -= segmentSize; + memcpy(dict + tail, ctx->samples + segment.begin, segmentSize); + DISPLAYUPDATE( + 2, "\r%u%% ", + (unsigned)(((dictBufferCapacity - tail) * 100) / dictBufferCapacity)); + } + DISPLAYLEVEL(2, "\r%79s\r", ""); + return tail; +} + +ZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_cover( + void *dictBuffer, size_t dictBufferCapacity, + const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, + ZDICT_cover_params_t parameters) +{ + BYTE* const dict = (BYTE*)dictBuffer; + COVER_ctx_t ctx; + COVER_map_t activeDmers; + parameters.splitPoint = 1.0; + /* Initialize global data */ + g_displayLevel = (int)parameters.zParams.notificationLevel; + /* Checks */ + if (!COVER_checkParameters(parameters, dictBufferCapacity)) { + DISPLAYLEVEL(1, "Cover parameters incorrect\n"); + return ERROR(parameter_outOfBound); + } + if (nbSamples == 0) { + DISPLAYLEVEL(1, "Cover must have at least one input file\n"); + return ERROR(srcSize_wrong); + } + if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) { + DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n", + ZDICT_DICTSIZE_MIN); + return ERROR(dstSize_tooSmall); + } + /* Initialize context and activeDmers */ + { + size_t const initVal = COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, + parameters.d, parameters.splitPoint); + if (ZSTD_isError(initVal)) { + return initVal; + } + } + COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, g_displayLevel); + if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) { + DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n"); + COVER_ctx_destroy(&ctx); + return ERROR(memory_allocation); + } + + DISPLAYLEVEL(2, "Building dictionary\n"); + { + const size_t tail = + COVER_buildDictionary(&ctx, ctx.freqs, &activeDmers, dictBuffer, + dictBufferCapacity, parameters); + const size_t dictionarySize = ZDICT_finalizeDictionary( + dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail, + samplesBuffer, samplesSizes, nbSamples, parameters.zParams); + if (!ZSTD_isError(dictionarySize)) { + DISPLAYLEVEL(2, "Constructed dictionary of size %u\n", + (unsigned)dictionarySize); + } + COVER_ctx_destroy(&ctx); + COVER_map_destroy(&activeDmers); + return dictionarySize; + } +} + + + +size_t COVER_checkTotalCompressedSize(const ZDICT_cover_params_t parameters, + const size_t *samplesSizes, const BYTE *samples, + size_t *offsets, + size_t nbTrainSamples, size_t nbSamples, + BYTE *const dict, size_t dictBufferCapacity) { + size_t totalCompressedSize = ERROR(GENERIC); + /* Pointers */ + ZSTD_CCtx *cctx; + ZSTD_CDict *cdict; + void *dst; + /* Local variables */ + size_t dstCapacity; + size_t i; + /* Allocate dst with enough space to compress the maximum sized sample */ + { + size_t maxSampleSize = 0; + i = parameters.splitPoint < 1.0 ? nbTrainSamples : 0; + for (; i < nbSamples; ++i) { + maxSampleSize = MAX(samplesSizes[i], maxSampleSize); + } + dstCapacity = ZSTD_compressBound(maxSampleSize); + dst = malloc(dstCapacity); + } + /* Create the cctx and cdict */ + cctx = ZSTD_createCCtx(); + cdict = ZSTD_createCDict(dict, dictBufferCapacity, + parameters.zParams.compressionLevel); + if (!dst || !cctx || !cdict) { + goto _compressCleanup; + } + /* Compress each sample and sum their sizes (or error) */ + totalCompressedSize = dictBufferCapacity; + i = parameters.splitPoint < 1.0 ? nbTrainSamples : 0; + for (; i < nbSamples; ++i) { + const size_t size = ZSTD_compress_usingCDict( + cctx, dst, dstCapacity, samples + offsets[i], + samplesSizes[i], cdict); + if (ZSTD_isError(size)) { + totalCompressedSize = size; + goto _compressCleanup; + } + totalCompressedSize += size; + } +_compressCleanup: + ZSTD_freeCCtx(cctx); + ZSTD_freeCDict(cdict); + if (dst) { + free(dst); + } + return totalCompressedSize; +} + + +/** + * Initialize the `COVER_best_t`. + */ +void COVER_best_init(COVER_best_t *best) { + if (best==NULL) return; /* compatible with init on NULL */ + (void)ZSTD_pthread_mutex_init(&best->mutex, NULL); + (void)ZSTD_pthread_cond_init(&best->cond, NULL); + best->liveJobs = 0; + best->dict = NULL; + best->dictSize = 0; + best->compressedSize = (size_t)-1; + memset(&best->parameters, 0, sizeof(best->parameters)); +} + +/** + * Wait until liveJobs == 0. + */ +void COVER_best_wait(COVER_best_t *best) { + if (!best) { + return; + } + ZSTD_pthread_mutex_lock(&best->mutex); + while (best->liveJobs != 0) { + ZSTD_pthread_cond_wait(&best->cond, &best->mutex); + } + ZSTD_pthread_mutex_unlock(&best->mutex); +} + +/** + * Call COVER_best_wait() and then destroy the COVER_best_t. + */ +void COVER_best_destroy(COVER_best_t *best) { + if (!best) { + return; + } + COVER_best_wait(best); + if (best->dict) { + free(best->dict); + } + ZSTD_pthread_mutex_destroy(&best->mutex); + ZSTD_pthread_cond_destroy(&best->cond); +} + +/** + * Called when a thread is about to be launched. + * Increments liveJobs. + */ +void COVER_best_start(COVER_best_t *best) { + if (!best) { + return; + } + ZSTD_pthread_mutex_lock(&best->mutex); + ++best->liveJobs; + ZSTD_pthread_mutex_unlock(&best->mutex); +} + +/** + * Called when a thread finishes executing, both on error or success. + * Decrements liveJobs and signals any waiting threads if liveJobs == 0. + * If this dictionary is the best so far save it and its parameters. + */ +void COVER_best_finish(COVER_best_t* best, + ZDICT_cover_params_t parameters, + COVER_dictSelection_t selection) +{ + void* dict = selection.dictContent; + size_t compressedSize = selection.totalCompressedSize; + size_t dictSize = selection.dictSize; + if (!best) { + return; + } + { + size_t liveJobs; + ZSTD_pthread_mutex_lock(&best->mutex); + --best->liveJobs; + liveJobs = best->liveJobs; + /* If the new dictionary is better */ + if (compressedSize < best->compressedSize) { + /* Allocate space if necessary */ + if (!best->dict || best->dictSize < dictSize) { + if (best->dict) { + free(best->dict); + } + best->dict = malloc(dictSize); + if (!best->dict) { + best->compressedSize = ERROR(GENERIC); + best->dictSize = 0; + ZSTD_pthread_cond_signal(&best->cond); + ZSTD_pthread_mutex_unlock(&best->mutex); + return; + } + } + /* Save the dictionary, parameters, and size */ + if (dict) { + memcpy(best->dict, dict, dictSize); + best->dictSize = dictSize; + best->parameters = parameters; + best->compressedSize = compressedSize; + } + } + if (liveJobs == 0) { + ZSTD_pthread_cond_broadcast(&best->cond); + } + ZSTD_pthread_mutex_unlock(&best->mutex); + } +} + +static COVER_dictSelection_t setDictSelection(BYTE* buf, size_t s, size_t csz) +{ + COVER_dictSelection_t ds; + ds.dictContent = buf; + ds.dictSize = s; + ds.totalCompressedSize = csz; + return ds; +} + +COVER_dictSelection_t COVER_dictSelectionError(size_t error) { + return setDictSelection(NULL, 0, error); +} + +unsigned COVER_dictSelectionIsError(COVER_dictSelection_t selection) { + return (ZSTD_isError(selection.totalCompressedSize) || !selection.dictContent); +} + +void COVER_dictSelectionFree(COVER_dictSelection_t selection){ + free(selection.dictContent); +} + +COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBufferCapacity, + size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples, + size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize) { + + size_t largestDict = 0; + size_t largestCompressed = 0; + BYTE* customDictContentEnd = customDictContent + dictContentSize; + + BYTE* largestDictbuffer = (BYTE*)malloc(dictBufferCapacity); + BYTE* candidateDictBuffer = (BYTE*)malloc(dictBufferCapacity); + double regressionTolerance = ((double)params.shrinkDictMaxRegression / 100.0) + 1.00; + + if (!largestDictbuffer || !candidateDictBuffer) { + free(largestDictbuffer); + free(candidateDictBuffer); + return COVER_dictSelectionError(dictContentSize); + } + + /* Initial dictionary size and compressed size */ + memcpy(largestDictbuffer, customDictContent, dictContentSize); + dictContentSize = ZDICT_finalizeDictionary( + largestDictbuffer, dictBufferCapacity, customDictContent, dictContentSize, + samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams); + + if (ZDICT_isError(dictContentSize)) { + free(largestDictbuffer); + free(candidateDictBuffer); + return COVER_dictSelectionError(dictContentSize); + } + + totalCompressedSize = COVER_checkTotalCompressedSize(params, samplesSizes, + samplesBuffer, offsets, + nbCheckSamples, nbSamples, + largestDictbuffer, dictContentSize); + + if (ZSTD_isError(totalCompressedSize)) { + free(largestDictbuffer); + free(candidateDictBuffer); + return COVER_dictSelectionError(totalCompressedSize); + } + + if (params.shrinkDict == 0) { + free(candidateDictBuffer); + return setDictSelection(largestDictbuffer, dictContentSize, totalCompressedSize); + } + + largestDict = dictContentSize; + largestCompressed = totalCompressedSize; + dictContentSize = ZDICT_DICTSIZE_MIN; + + /* Largest dict is initially at least ZDICT_DICTSIZE_MIN */ + while (dictContentSize < largestDict) { + memcpy(candidateDictBuffer, largestDictbuffer, largestDict); + dictContentSize = ZDICT_finalizeDictionary( + candidateDictBuffer, dictBufferCapacity, customDictContentEnd - dictContentSize, dictContentSize, + samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams); + + if (ZDICT_isError(dictContentSize)) { + free(largestDictbuffer); + free(candidateDictBuffer); + return COVER_dictSelectionError(dictContentSize); + + } + + totalCompressedSize = COVER_checkTotalCompressedSize(params, samplesSizes, + samplesBuffer, offsets, + nbCheckSamples, nbSamples, + candidateDictBuffer, dictContentSize); + + if (ZSTD_isError(totalCompressedSize)) { + free(largestDictbuffer); + free(candidateDictBuffer); + return COVER_dictSelectionError(totalCompressedSize); + } + + if ((double)totalCompressedSize <= (double)largestCompressed * regressionTolerance) { + free(largestDictbuffer); + return setDictSelection( candidateDictBuffer, dictContentSize, totalCompressedSize ); + } + dictContentSize *= 2; + } + dictContentSize = largestDict; + totalCompressedSize = largestCompressed; + free(candidateDictBuffer); + return setDictSelection( largestDictbuffer, dictContentSize, totalCompressedSize ); +} + +/** + * Parameters for COVER_tryParameters(). + */ +typedef struct COVER_tryParameters_data_s { + const COVER_ctx_t *ctx; + COVER_best_t *best; + size_t dictBufferCapacity; + ZDICT_cover_params_t parameters; +} COVER_tryParameters_data_t; + +/** + * Tries a set of parameters and updates the COVER_best_t with the results. + * This function is thread safe if zstd is compiled with multithreaded support. + * It takes its parameters as an *OWNING* opaque pointer to support threading. + */ +static void COVER_tryParameters(void *opaque) +{ + /* Save parameters as local variables */ + COVER_tryParameters_data_t *const data = (COVER_tryParameters_data_t*)opaque; + const COVER_ctx_t *const ctx = data->ctx; + const ZDICT_cover_params_t parameters = data->parameters; + size_t dictBufferCapacity = data->dictBufferCapacity; + size_t totalCompressedSize = ERROR(GENERIC); + /* Allocate space for hash table, dict, and freqs */ + COVER_map_t activeDmers; + BYTE* const dict = (BYTE*)malloc(dictBufferCapacity); + COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC)); + U32* const freqs = (U32*)malloc(ctx->suffixSize * sizeof(U32)); + if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) { + DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n"); + goto _cleanup; + } + if (!dict || !freqs) { + DISPLAYLEVEL(1, "Failed to allocate buffers: out of memory\n"); + goto _cleanup; + } + /* Copy the frequencies because we need to modify them */ + memcpy(freqs, ctx->freqs, ctx->suffixSize * sizeof(U32)); + /* Build the dictionary */ + { + const size_t tail = COVER_buildDictionary(ctx, freqs, &activeDmers, dict, + dictBufferCapacity, parameters); + selection = COVER_selectDict(dict + tail, dictBufferCapacity, dictBufferCapacity - tail, + ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbTrainSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets, + totalCompressedSize); + + if (COVER_dictSelectionIsError(selection)) { + DISPLAYLEVEL(1, "Failed to select dictionary\n"); + goto _cleanup; + } + } +_cleanup: + free(dict); + COVER_best_finish(data->best, parameters, selection); + free(data); + COVER_map_destroy(&activeDmers); + COVER_dictSelectionFree(selection); + free(freqs); +} + +ZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_cover( + void* dictBuffer, size_t dictBufferCapacity, const void* samplesBuffer, + const size_t* samplesSizes, unsigned nbSamples, + ZDICT_cover_params_t* parameters) +{ + /* constants */ + const unsigned nbThreads = parameters->nbThreads; + const double splitPoint = + parameters->splitPoint <= 0.0 ? COVER_DEFAULT_SPLITPOINT : parameters->splitPoint; + const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d; + const unsigned kMaxD = parameters->d == 0 ? 8 : parameters->d; + const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k; + const unsigned kMaxK = parameters->k == 0 ? 2000 : parameters->k; + const unsigned kSteps = parameters->steps == 0 ? 40 : parameters->steps; + const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1); + const unsigned kIterations = + (1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize); + const unsigned shrinkDict = 0; + /* Local variables */ + const int displayLevel = parameters->zParams.notificationLevel; + unsigned iteration = 1; + unsigned d; + unsigned k; + COVER_best_t best; + POOL_ctx *pool = NULL; + int warned = 0; + + /* Checks */ + if (splitPoint <= 0 || splitPoint > 1) { + LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect parameters\n"); + return ERROR(parameter_outOfBound); + } + if (kMinK < kMaxD || kMaxK < kMinK) { + LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect parameters\n"); + return ERROR(parameter_outOfBound); + } + if (nbSamples == 0) { + DISPLAYLEVEL(1, "Cover must have at least one input file\n"); + return ERROR(srcSize_wrong); + } + if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) { + DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n", + ZDICT_DICTSIZE_MIN); + return ERROR(dstSize_tooSmall); + } + if (nbThreads > 1) { + pool = POOL_create(nbThreads, 1); + if (!pool) { + return ERROR(memory_allocation); + } + } + /* Initialization */ + COVER_best_init(&best); + /* Turn down global display level to clean up display at level 2 and below */ + g_displayLevel = displayLevel == 0 ? 0 : displayLevel - 1; + /* Loop through d first because each new value needs a new context */ + LOCALDISPLAYLEVEL(displayLevel, 2, "Trying %u different sets of parameters\n", + kIterations); + for (d = kMinD; d <= kMaxD; d += 2) { + /* Initialize the context for this value of d */ + COVER_ctx_t ctx; + LOCALDISPLAYLEVEL(displayLevel, 3, "d=%u\n", d); + { + const size_t initVal = COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint); + if (ZSTD_isError(initVal)) { + LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n"); + COVER_best_destroy(&best); + POOL_free(pool); + return initVal; + } + } + if (!warned) { + COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.suffixSize, displayLevel); + warned = 1; + } + /* Loop through k reusing the same context */ + for (k = kMinK; k <= kMaxK; k += kStepSize) { + /* Prepare the arguments */ + COVER_tryParameters_data_t *data = (COVER_tryParameters_data_t *)malloc( + sizeof(COVER_tryParameters_data_t)); + LOCALDISPLAYLEVEL(displayLevel, 3, "k=%u\n", k); + if (!data) { + LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to allocate parameters\n"); + COVER_best_destroy(&best); + COVER_ctx_destroy(&ctx); + POOL_free(pool); + return ERROR(memory_allocation); + } + data->ctx = &ctx; + data->best = &best; + data->dictBufferCapacity = dictBufferCapacity; + data->parameters = *parameters; + data->parameters.k = k; + data->parameters.d = d; + data->parameters.splitPoint = splitPoint; + data->parameters.steps = kSteps; + data->parameters.shrinkDict = shrinkDict; + data->parameters.zParams.notificationLevel = g_displayLevel; + /* Check the parameters */ + if (!COVER_checkParameters(data->parameters, dictBufferCapacity)) { + DISPLAYLEVEL(1, "Cover parameters incorrect\n"); + free(data); + continue; + } + /* Call the function and pass ownership of data to it */ + COVER_best_start(&best); + if (pool) { + POOL_add(pool, &COVER_tryParameters, data); + } else { + COVER_tryParameters(data); + } + /* Print status */ + LOCALDISPLAYUPDATE(displayLevel, 2, "\r%u%% ", + (unsigned)((iteration * 100) / kIterations)); + ++iteration; + } + COVER_best_wait(&best); + COVER_ctx_destroy(&ctx); + } + LOCALDISPLAYLEVEL(displayLevel, 2, "\r%79s\r", ""); + /* Fill the output buffer and parameters with output of the best parameters */ + { + const size_t dictSize = best.dictSize; + if (ZSTD_isError(best.compressedSize)) { + const size_t compressedSize = best.compressedSize; + COVER_best_destroy(&best); + POOL_free(pool); + return compressedSize; + } + *parameters = best.parameters; + memcpy(dictBuffer, best.dict, dictSize); + COVER_best_destroy(&best); + POOL_free(pool); + return dictSize; + } +} diff --git a/third_party/zstd/dict/divsufsort.c b/third_party/zstd/dict/divsufsort.c new file mode 100644 index 00000000000..a2870fb3ba3 --- /dev/null +++ b/third_party/zstd/dict/divsufsort.c @@ -0,0 +1,1913 @@ +/* + * divsufsort.c for libdivsufsort-lite + * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. + * + * 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. + */ + +/*- Compiler specifics -*/ +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#endif + +#if defined(_MSC_VER) +# pragma warning(disable : 4244) +# pragma warning(disable : 4127) /* C4127 : Condition expression is constant */ +#endif + + +/*- Dependencies -*/ +#include +#include +#include + +#include "divsufsort.h" + +/*- Constants -*/ +#if defined(INLINE) +# undef INLINE +#endif +#if !defined(INLINE) +# define INLINE __inline +#endif +#if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1) +# undef ALPHABET_SIZE +#endif +#if !defined(ALPHABET_SIZE) +# define ALPHABET_SIZE (256) +#endif +#define BUCKET_A_SIZE (ALPHABET_SIZE) +#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE) +#if defined(SS_INSERTIONSORT_THRESHOLD) +# if SS_INSERTIONSORT_THRESHOLD < 1 +# undef SS_INSERTIONSORT_THRESHOLD +# define SS_INSERTIONSORT_THRESHOLD (1) +# endif +#else +# define SS_INSERTIONSORT_THRESHOLD (8) +#endif +#if defined(SS_BLOCKSIZE) +# if SS_BLOCKSIZE < 0 +# undef SS_BLOCKSIZE +# define SS_BLOCKSIZE (0) +# elif 32768 <= SS_BLOCKSIZE +# undef SS_BLOCKSIZE +# define SS_BLOCKSIZE (32767) +# endif +#else +# define SS_BLOCKSIZE (1024) +#endif +/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */ +#if SS_BLOCKSIZE == 0 +# define SS_MISORT_STACKSIZE (96) +#elif SS_BLOCKSIZE <= 4096 +# define SS_MISORT_STACKSIZE (16) +#else +# define SS_MISORT_STACKSIZE (24) +#endif +#define SS_SMERGE_STACKSIZE (32) +#define TR_INSERTIONSORT_THRESHOLD (8) +#define TR_STACKSIZE (64) + + +/*- Macros -*/ +#ifndef SWAP +# define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0) +#endif /* SWAP */ +#ifndef MIN +# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) +#endif /* MIN */ +#ifndef MAX +# define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b)) +#endif /* MAX */ +#define STACK_PUSH(_a, _b, _c, _d)\ + do {\ + assert(ssize < STACK_SIZE);\ + stack[ssize].a = (_a), stack[ssize].b = (_b),\ + stack[ssize].c = (_c), stack[ssize++].d = (_d);\ + } while(0) +#define STACK_PUSH5(_a, _b, _c, _d, _e)\ + do {\ + assert(ssize < STACK_SIZE);\ + stack[ssize].a = (_a), stack[ssize].b = (_b),\ + stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\ + } while(0) +#define STACK_POP(_a, _b, _c, _d)\ + do {\ + assert(0 <= ssize);\ + if(ssize == 0) { return; }\ + (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\ + (_c) = stack[ssize].c, (_d) = stack[ssize].d;\ + } while(0) +#define STACK_POP5(_a, _b, _c, _d, _e)\ + do {\ + assert(0 <= ssize);\ + if(ssize == 0) { return; }\ + (_a) = stack[--ssize].a, (_b) = stack[ssize].b,\ + (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\ + } while(0) +#define BUCKET_A(_c0) bucket_A[(_c0)] +#if ALPHABET_SIZE == 256 +#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)]) +#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)]) +#else +#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)]) +#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)]) +#endif + + +/*- Private Functions -*/ + +static const int lg_table[256]= { + -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) + +static INLINE +int +ss_ilg(int n) { +#if SS_BLOCKSIZE == 0 + return (n & 0xffff0000) ? + ((n & 0xff000000) ? + 24 + lg_table[(n >> 24) & 0xff] : + 16 + lg_table[(n >> 16) & 0xff]) : + ((n & 0x0000ff00) ? + 8 + lg_table[(n >> 8) & 0xff] : + 0 + lg_table[(n >> 0) & 0xff]); +#elif SS_BLOCKSIZE < 256 + return lg_table[n]; +#else + return (n & 0xff00) ? + 8 + lg_table[(n >> 8) & 0xff] : + 0 + lg_table[(n >> 0) & 0xff]; +#endif +} + +#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */ + +#if SS_BLOCKSIZE != 0 + +static const int sqq_table[256] = { + 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61, + 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89, + 90, 91, 93, 94, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109, +110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, +128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, +143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, +156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, +169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180, +181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, +192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, +202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, +212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, +221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, +230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, +239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, +247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255 +}; + +static INLINE +int +ss_isqrt(int x) { + int y, e; + + if(x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) { return SS_BLOCKSIZE; } + e = (x & 0xffff0000) ? + ((x & 0xff000000) ? + 24 + lg_table[(x >> 24) & 0xff] : + 16 + lg_table[(x >> 16) & 0xff]) : + ((x & 0x0000ff00) ? + 8 + lg_table[(x >> 8) & 0xff] : + 0 + lg_table[(x >> 0) & 0xff]); + + if(e >= 16) { + y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7); + if(e >= 24) { y = (y + 1 + x / y) >> 1; } + y = (y + 1 + x / y) >> 1; + } else if(e >= 8) { + y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1; + } else { + return sqq_table[x] >> 4; + } + + return (x < (y * y)) ? y - 1 : y; +} + +#endif /* SS_BLOCKSIZE != 0 */ + + +/*---------------------------------------------------------------------------*/ + +/* Compares two suffixes. */ +static INLINE +int +ss_compare(const unsigned char *T, + const int *p1, const int *p2, + int depth) { + const unsigned char *U1, *U2, *U1n, *U2n; + + for(U1 = T + depth + *p1, + U2 = T + depth + *p2, + U1n = T + *(p1 + 1) + 2, + U2n = T + *(p2 + 1) + 2; + (U1 < U1n) && (U2 < U2n) && (*U1 == *U2); + ++U1, ++U2) { + } + + return U1 < U1n ? + (U2 < U2n ? *U1 - *U2 : 1) : + (U2 < U2n ? -1 : 0); +} + + +/*---------------------------------------------------------------------------*/ + +#if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) + +/* Insertionsort for small size groups */ +static +void +ss_insertionsort(const unsigned char *T, const int *PA, + int *first, int *last, int depth) { + int *i, *j; + int t; + int r; + + for(i = last - 2; first <= i; --i) { + for(t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) { + do { *(j - 1) = *j; } while((++j < last) && (*j < 0)); + if(last <= j) { break; } + } + if(r == 0) { *j = ~*j; } + *(j - 1) = t; + } +} + +#endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */ + + +/*---------------------------------------------------------------------------*/ + +#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) + +static INLINE +void +ss_fixdown(const unsigned char *Td, const int *PA, + int *SA, int i, int size) { + int j, k; + int v; + int c, d, e; + + for(v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) { + d = Td[PA[SA[k = j++]]]; + if(d < (e = Td[PA[SA[j]]])) { k = j; d = e; } + if(d <= c) { break; } + } + SA[i] = v; +} + +/* Simple top-down heapsort. */ +static +void +ss_heapsort(const unsigned char *Td, const int *PA, int *SA, int size) { + int i, m; + int t; + + m = size; + if((size % 2) == 0) { + m--; + if(Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) { SWAP(SA[m], SA[m / 2]); } + } + + for(i = m / 2 - 1; 0 <= i; --i) { ss_fixdown(Td, PA, SA, i, m); } + if((size % 2) == 0) { SWAP(SA[0], SA[m]); ss_fixdown(Td, PA, SA, 0, m); } + for(i = m - 1; 0 < i; --i) { + t = SA[0], SA[0] = SA[i]; + ss_fixdown(Td, PA, SA, 0, i); + SA[i] = t; + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Returns the median of three elements. */ +static INLINE +int * +ss_median3(const unsigned char *Td, const int *PA, + int *v1, int *v2, int *v3) { + int *t; + if(Td[PA[*v1]] > Td[PA[*v2]]) { SWAP(v1, v2); } + if(Td[PA[*v2]] > Td[PA[*v3]]) { + if(Td[PA[*v1]] > Td[PA[*v3]]) { return v1; } + else { return v3; } + } + return v2; +} + +/* Returns the median of five elements. */ +static INLINE +int * +ss_median5(const unsigned char *Td, const int *PA, + int *v1, int *v2, int *v3, int *v4, int *v5) { + int *t; + if(Td[PA[*v2]] > Td[PA[*v3]]) { SWAP(v2, v3); } + if(Td[PA[*v4]] > Td[PA[*v5]]) { SWAP(v4, v5); } + if(Td[PA[*v2]] > Td[PA[*v4]]) { SWAP(v2, v4); SWAP(v3, v5); } + if(Td[PA[*v1]] > Td[PA[*v3]]) { SWAP(v1, v3); } + if(Td[PA[*v1]] > Td[PA[*v4]]) { SWAP(v1, v4); SWAP(v3, v5); } + if(Td[PA[*v3]] > Td[PA[*v4]]) { return v4; } + return v3; +} + +/* Returns the pivot element. */ +static INLINE +int * +ss_pivot(const unsigned char *Td, const int *PA, int *first, int *last) { + int *middle; + int t; + + t = last - first; + middle = first + t / 2; + + if(t <= 512) { + if(t <= 32) { + return ss_median3(Td, PA, first, middle, last - 1); + } else { + t >>= 2; + return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1); + } + } + t >>= 3; + first = ss_median3(Td, PA, first, first + t, first + (t << 1)); + middle = ss_median3(Td, PA, middle - t, middle, middle + t); + last = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1); + return ss_median3(Td, PA, first, middle, last); +} + + +/*---------------------------------------------------------------------------*/ + +/* Binary partition for substrings. */ +static INLINE +int * +ss_partition(const int *PA, + int *first, int *last, int depth) { + int *a, *b; + int t; + for(a = first - 1, b = last;;) { + for(; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) { *a = ~*a; } + for(; (a < --b) && ((PA[*b] + depth) < (PA[*b + 1] + 1));) { } + if(b <= a) { break; } + t = ~*b; + *b = *a; + *a = t; + } + if(first < a) { *first = ~*first; } + return a; +} + +/* Multikey introsort for medium size groups. */ +static +void +ss_mintrosort(const unsigned char *T, const int *PA, + int *first, int *last, + int depth) { +#define STACK_SIZE SS_MISORT_STACKSIZE + struct { int *a, *b, c; int d; } stack[STACK_SIZE]; + const unsigned char *Td; + int *a, *b, *c, *d, *e, *f; + int s, t; + int ssize; + int limit; + int v, x = 0; + + for(ssize = 0, limit = ss_ilg(last - first);;) { + + if((last - first) <= SS_INSERTIONSORT_THRESHOLD) { +#if 1 < SS_INSERTIONSORT_THRESHOLD + if(1 < (last - first)) { ss_insertionsort(T, PA, first, last, depth); } +#endif + STACK_POP(first, last, depth, limit); + continue; + } + + Td = T + depth; + if(limit-- == 0) { ss_heapsort(Td, PA, first, last - first); } + if(limit < 0) { + for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) { + if((x = Td[PA[*a]]) != v) { + if(1 < (a - first)) { break; } + v = x; + first = a; + } + } + if(Td[PA[*first] - 1] < v) { + first = ss_partition(PA, first, a, depth); + } + if((a - first) <= (last - a)) { + if(1 < (a - first)) { + STACK_PUSH(a, last, depth, -1); + last = a, depth += 1, limit = ss_ilg(a - first); + } else { + first = a, limit = -1; + } + } else { + if(1 < (last - a)) { + STACK_PUSH(first, a, depth + 1, ss_ilg(a - first)); + first = a, limit = -1; + } else { + last = a, depth += 1, limit = ss_ilg(a - first); + } + } + continue; + } + + /* choose pivot */ + a = ss_pivot(Td, PA, first, last); + v = Td[PA[*a]]; + SWAP(*first, *a); + + /* partition */ + for(b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) { } + if(((a = b) < last) && (x < v)) { + for(; (++b < last) && ((x = Td[PA[*b]]) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + } + for(c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) { } + if((b < (d = c)) && (x > v)) { + for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + for(; b < c;) { + SWAP(*b, *c); + for(; (++b < c) && ((x = Td[PA[*b]]) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + + if(a <= d) { + c = b - 1; + + if((s = a - first) > (t = b - a)) { s = t; } + for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + if((s = d - c) > (t = last - d - 1)) { s = t; } + for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + + a = first + (b - a), c = last - (d - c); + b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth); + + if((a - first) <= (last - c)) { + if((last - c) <= (c - b)) { + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + STACK_PUSH(c, last, depth, limit); + last = a; + } else if((a - first) <= (c - b)) { + STACK_PUSH(c, last, depth, limit); + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + last = a; + } else { + STACK_PUSH(c, last, depth, limit); + STACK_PUSH(first, a, depth, limit); + first = b, last = c, depth += 1, limit = ss_ilg(c - b); + } + } else { + if((a - first) <= (c - b)) { + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + STACK_PUSH(first, a, depth, limit); + first = c; + } else if((last - c) <= (c - b)) { + STACK_PUSH(first, a, depth, limit); + STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); + first = c; + } else { + STACK_PUSH(first, a, depth, limit); + STACK_PUSH(c, last, depth, limit); + first = b, last = c, depth += 1, limit = ss_ilg(c - b); + } + } + } else { + limit += 1; + if(Td[PA[*first] - 1] < v) { + first = ss_partition(PA, first, last, depth); + limit = ss_ilg(last - first); + } + depth += 1; + } + } +#undef STACK_SIZE +} + +#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */ + + +/*---------------------------------------------------------------------------*/ + +#if SS_BLOCKSIZE != 0 + +static INLINE +void +ss_blockswap(int *a, int *b, int n) { + int t; + for(; 0 < n; --n, ++a, ++b) { + t = *a, *a = *b, *b = t; + } +} + +static INLINE +void +ss_rotate(int *first, int *middle, int *last) { + int *a, *b, t; + int l, r; + l = middle - first, r = last - middle; + for(; (0 < l) && (0 < r);) { + if(l == r) { ss_blockswap(first, middle, l); break; } + if(l < r) { + a = last - 1, b = middle - 1; + t = *a; + do { + *a-- = *b, *b-- = *a; + if(b < first) { + *a = t; + last = a; + if((r -= l + 1) <= l) { break; } + a -= 1, b = middle - 1; + t = *a; + } + } while(1); + } else { + a = first, b = middle; + t = *a; + do { + *a++ = *b, *b++ = *a; + if(last <= b) { + *a = t; + first = a + 1; + if((l -= r + 1) <= r) { break; } + a += 1, b = middle; + t = *a; + } + } while(1); + } + } +} + + +/*---------------------------------------------------------------------------*/ + +static +void +ss_inplacemerge(const unsigned char *T, const int *PA, + int *first, int *middle, int *last, + int depth) { + const int *p; + int *a, *b; + int len, half; + int q, r; + int x; + + for(;;) { + if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); } + else { x = 0; p = PA + *(last - 1); } + for(a = first, len = middle - first, half = len >> 1, r = -1; + 0 < len; + len = half, half >>= 1) { + b = a + half; + q = ss_compare(T, PA + ((0 <= *b) ? *b : ~*b), p, depth); + if(q < 0) { + a = b + 1; + half -= (len & 1) ^ 1; + } else { + r = q; + } + } + if(a < middle) { + if(r == 0) { *a = ~*a; } + ss_rotate(a, middle, last); + last -= middle - a; + middle = a; + if(first == middle) { break; } + } + --last; + if(x != 0) { while(*--last < 0) { } } + if(middle == last) { break; } + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Merge-forward with internal buffer. */ +static +void +ss_mergeforward(const unsigned char *T, const int *PA, + int *first, int *middle, int *last, + int *buf, int depth) { + int *a, *b, *c, *bufend; + int t; + int r; + + bufend = buf + (middle - first) - 1; + ss_blockswap(buf, first, middle - first); + + for(t = *(a = first), b = buf, c = middle;;) { + r = ss_compare(T, PA + *b, PA + *c, depth); + if(r < 0) { + do { + *a++ = *b; + if(bufend <= b) { *bufend = t; return; } + *b++ = *a; + } while(*b < 0); + } else if(r > 0) { + do { + *a++ = *c, *c++ = *a; + if(last <= c) { + while(b < bufend) { *a++ = *b, *b++ = *a; } + *a = *b, *b = t; + return; + } + } while(*c < 0); + } else { + *c = ~*c; + do { + *a++ = *b; + if(bufend <= b) { *bufend = t; return; } + *b++ = *a; + } while(*b < 0); + + do { + *a++ = *c, *c++ = *a; + if(last <= c) { + while(b < bufend) { *a++ = *b, *b++ = *a; } + *a = *b, *b = t; + return; + } + } while(*c < 0); + } + } +} + +/* Merge-backward with internal buffer. */ +static +void +ss_mergebackward(const unsigned char *T, const int *PA, + int *first, int *middle, int *last, + int *buf, int depth) { + const int *p1, *p2; + int *a, *b, *c, *bufend; + int t; + int r; + int x; + + bufend = buf + (last - middle) - 1; + ss_blockswap(buf, middle, last - middle); + + x = 0; + if(*bufend < 0) { p1 = PA + ~*bufend; x |= 1; } + else { p1 = PA + *bufend; } + if(*(middle - 1) < 0) { p2 = PA + ~*(middle - 1); x |= 2; } + else { p2 = PA + *(middle - 1); } + for(t = *(a = last - 1), b = bufend, c = middle - 1;;) { + r = ss_compare(T, p1, p2, depth); + if(0 < r) { + if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; } + *a-- = *b; + if(b <= buf) { *buf = t; break; } + *b-- = *a; + if(*b < 0) { p1 = PA + ~*b; x |= 1; } + else { p1 = PA + *b; } + } else if(r < 0) { + if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; } + *a-- = *c, *c-- = *a; + if(c < first) { + while(buf < b) { *a-- = *b, *b-- = *a; } + *a = *b, *b = t; + break; + } + if(*c < 0) { p2 = PA + ~*c; x |= 2; } + else { p2 = PA + *c; } + } else { + if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; } + *a-- = ~*b; + if(b <= buf) { *buf = t; break; } + *b-- = *a; + if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; } + *a-- = *c, *c-- = *a; + if(c < first) { + while(buf < b) { *a-- = *b, *b-- = *a; } + *a = *b, *b = t; + break; + } + if(*b < 0) { p1 = PA + ~*b; x |= 1; } + else { p1 = PA + *b; } + if(*c < 0) { p2 = PA + ~*c; x |= 2; } + else { p2 = PA + *c; } + } + } +} + +/* D&C based merge. */ +static +void +ss_swapmerge(const unsigned char *T, const int *PA, + int *first, int *middle, int *last, + int *buf, int bufsize, int depth) { +#define STACK_SIZE SS_SMERGE_STACKSIZE +#define GETIDX(a) ((0 <= (a)) ? (a) : (~(a))) +#define MERGE_CHECK(a, b, c)\ + do {\ + if(((c) & 1) ||\ + (((c) & 2) && (ss_compare(T, PA + GETIDX(*((a) - 1)), PA + *(a), depth) == 0))) {\ + *(a) = ~*(a);\ + }\ + if(((c) & 4) && ((ss_compare(T, PA + GETIDX(*((b) - 1)), PA + *(b), depth) == 0))) {\ + *(b) = ~*(b);\ + }\ + } while(0) + struct { int *a, *b, *c; int d; } stack[STACK_SIZE]; + int *l, *r, *lm, *rm; + int m, len, half; + int ssize; + int check, next; + + for(check = 0, ssize = 0;;) { + if((last - middle) <= bufsize) { + if((first < middle) && (middle < last)) { + ss_mergebackward(T, PA, first, middle, last, buf, depth); + } + MERGE_CHECK(first, last, check); + STACK_POP(first, middle, last, check); + continue; + } + + if((middle - first) <= bufsize) { + if(first < middle) { + ss_mergeforward(T, PA, first, middle, last, buf, depth); + } + MERGE_CHECK(first, last, check); + STACK_POP(first, middle, last, check); + continue; + } + + for(m = 0, len = MIN(middle - first, last - middle), half = len >> 1; + 0 < len; + len = half, half >>= 1) { + if(ss_compare(T, PA + GETIDX(*(middle + m + half)), + PA + GETIDX(*(middle - m - half - 1)), depth) < 0) { + m += half + 1; + half -= (len & 1) ^ 1; + } + } + + if(0 < m) { + lm = middle - m, rm = middle + m; + ss_blockswap(lm, middle, m); + l = r = middle, next = 0; + if(rm < last) { + if(*rm < 0) { + *rm = ~*rm; + if(first < lm) { for(; *--l < 0;) { } next |= 4; } + next |= 1; + } else if(first < lm) { + for(; *r < 0; ++r) { } + next |= 2; + } + } + + if((l - first) <= (last - r)) { + STACK_PUSH(r, rm, last, (next & 3) | (check & 4)); + middle = lm, last = l, check = (check & 3) | (next & 4); + } else { + if((next & 2) && (r == middle)) { next ^= 6; } + STACK_PUSH(first, lm, l, (check & 3) | (next & 4)); + first = r, middle = rm, check = (next & 3) | (check & 4); + } + } else { + if(ss_compare(T, PA + GETIDX(*(middle - 1)), PA + *middle, depth) == 0) { + *middle = ~*middle; + } + MERGE_CHECK(first, last, check); + STACK_POP(first, middle, last, check); + } + } +#undef STACK_SIZE +} + +#endif /* SS_BLOCKSIZE != 0 */ + + +/*---------------------------------------------------------------------------*/ + +/* Substring sort */ +static +void +sssort(const unsigned char *T, const int *PA, + int *first, int *last, + int *buf, int bufsize, + int depth, int n, int lastsuffix) { + int *a; +#if SS_BLOCKSIZE != 0 + int *b, *middle, *curbuf; + int j, k, curbufsize, limit; +#endif + int i; + + if(lastsuffix != 0) { ++first; } + +#if SS_BLOCKSIZE == 0 + ss_mintrosort(T, PA, first, last, depth); +#else + if((bufsize < SS_BLOCKSIZE) && + (bufsize < (last - first)) && + (bufsize < (limit = ss_isqrt(last - first)))) { + if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; } + buf = middle = last - limit, bufsize = limit; + } else { + middle = last, limit = 0; + } + for(a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) { +#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE + ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth); +#elif 1 < SS_BLOCKSIZE + ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth); +#endif + curbufsize = last - (a + SS_BLOCKSIZE); + curbuf = a + SS_BLOCKSIZE; + if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; } + for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) { + ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth); + } + } +#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE + ss_mintrosort(T, PA, a, middle, depth); +#elif 1 < SS_BLOCKSIZE + ss_insertionsort(T, PA, a, middle, depth); +#endif + for(k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) { + if(i & 1) { + ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth); + a -= k; + } + } + if(limit != 0) { +#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE + ss_mintrosort(T, PA, middle, last, depth); +#elif 1 < SS_BLOCKSIZE + ss_insertionsort(T, PA, middle, last, depth); +#endif + ss_inplacemerge(T, PA, first, middle, last, depth); + } +#endif + + if(lastsuffix != 0) { + /* Insert last type B* suffix. */ + int PAi[2]; PAi[0] = PA[*(first - 1)], PAi[1] = n - 2; + for(a = first, i = *(first - 1); + (a < last) && ((*a < 0) || (0 < ss_compare(T, &(PAi[0]), PA + *a, depth))); + ++a) { + *(a - 1) = *a; + } + *(a - 1) = i; + } +} + + +/*---------------------------------------------------------------------------*/ + +static INLINE +int +tr_ilg(int n) { + return (n & 0xffff0000) ? + ((n & 0xff000000) ? + 24 + lg_table[(n >> 24) & 0xff] : + 16 + lg_table[(n >> 16) & 0xff]) : + ((n & 0x0000ff00) ? + 8 + lg_table[(n >> 8) & 0xff] : + 0 + lg_table[(n >> 0) & 0xff]); +} + + +/*---------------------------------------------------------------------------*/ + +/* Simple insertionsort for small size groups. */ +static +void +tr_insertionsort(const int *ISAd, int *first, int *last) { + int *a, *b; + int t, r; + + for(a = first + 1; a < last; ++a) { + for(t = *a, b = a - 1; 0 > (r = ISAd[t] - ISAd[*b]);) { + do { *(b + 1) = *b; } while((first <= --b) && (*b < 0)); + if(b < first) { break; } + } + if(r == 0) { *b = ~*b; } + *(b + 1) = t; + } +} + + +/*---------------------------------------------------------------------------*/ + +static INLINE +void +tr_fixdown(const int *ISAd, int *SA, int i, int size) { + int j, k; + int v; + int c, d, e; + + for(v = SA[i], c = ISAd[v]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) { + d = ISAd[SA[k = j++]]; + if(d < (e = ISAd[SA[j]])) { k = j; d = e; } + if(d <= c) { break; } + } + SA[i] = v; +} + +/* Simple top-down heapsort. */ +static +void +tr_heapsort(const int *ISAd, int *SA, int size) { + int i, m; + int t; + + m = size; + if((size % 2) == 0) { + m--; + if(ISAd[SA[m / 2]] < ISAd[SA[m]]) { SWAP(SA[m], SA[m / 2]); } + } + + for(i = m / 2 - 1; 0 <= i; --i) { tr_fixdown(ISAd, SA, i, m); } + if((size % 2) == 0) { SWAP(SA[0], SA[m]); tr_fixdown(ISAd, SA, 0, m); } + for(i = m - 1; 0 < i; --i) { + t = SA[0], SA[0] = SA[i]; + tr_fixdown(ISAd, SA, 0, i); + SA[i] = t; + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Returns the median of three elements. */ +static INLINE +int * +tr_median3(const int *ISAd, int *v1, int *v2, int *v3) { + int *t; + if(ISAd[*v1] > ISAd[*v2]) { SWAP(v1, v2); } + if(ISAd[*v2] > ISAd[*v3]) { + if(ISAd[*v1] > ISAd[*v3]) { return v1; } + else { return v3; } + } + return v2; +} + +/* Returns the median of five elements. */ +static INLINE +int * +tr_median5(const int *ISAd, + int *v1, int *v2, int *v3, int *v4, int *v5) { + int *t; + if(ISAd[*v2] > ISAd[*v3]) { SWAP(v2, v3); } + if(ISAd[*v4] > ISAd[*v5]) { SWAP(v4, v5); } + if(ISAd[*v2] > ISAd[*v4]) { SWAP(v2, v4); SWAP(v3, v5); } + if(ISAd[*v1] > ISAd[*v3]) { SWAP(v1, v3); } + if(ISAd[*v1] > ISAd[*v4]) { SWAP(v1, v4); SWAP(v3, v5); } + if(ISAd[*v3] > ISAd[*v4]) { return v4; } + return v3; +} + +/* Returns the pivot element. */ +static INLINE +int * +tr_pivot(const int *ISAd, int *first, int *last) { + int *middle; + int t; + + t = last - first; + middle = first + t / 2; + + if(t <= 512) { + if(t <= 32) { + return tr_median3(ISAd, first, middle, last - 1); + } else { + t >>= 2; + return tr_median5(ISAd, first, first + t, middle, last - 1 - t, last - 1); + } + } + t >>= 3; + first = tr_median3(ISAd, first, first + t, first + (t << 1)); + middle = tr_median3(ISAd, middle - t, middle, middle + t); + last = tr_median3(ISAd, last - 1 - (t << 1), last - 1 - t, last - 1); + return tr_median3(ISAd, first, middle, last); +} + + +/*---------------------------------------------------------------------------*/ + +typedef struct _trbudget_t trbudget_t; +struct _trbudget_t { + int chance; + int remain; + int incval; + int count; +}; + +static INLINE +void +trbudget_init(trbudget_t *budget, int chance, int incval) { + budget->chance = chance; + budget->remain = budget->incval = incval; +} + +static INLINE +int +trbudget_check(trbudget_t *budget, int size) { + if(size <= budget->remain) { budget->remain -= size; return 1; } + if(budget->chance == 0) { budget->count += size; return 0; } + budget->remain += budget->incval - size; + budget->chance -= 1; + return 1; +} + + +/*---------------------------------------------------------------------------*/ + +static INLINE +void +tr_partition(const int *ISAd, + int *first, int *middle, int *last, + int **pa, int **pb, int v) { + int *a, *b, *c, *d, *e, *f; + int t, s; + int x = 0; + + for(b = middle - 1; (++b < last) && ((x = ISAd[*b]) == v);) { } + if(((a = b) < last) && (x < v)) { + for(; (++b < last) && ((x = ISAd[*b]) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + } + for(c = last; (b < --c) && ((x = ISAd[*c]) == v);) { } + if((b < (d = c)) && (x > v)) { + for(; (b < --c) && ((x = ISAd[*c]) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + for(; b < c;) { + SWAP(*b, *c); + for(; (++b < c) && ((x = ISAd[*b]) <= v);) { + if(x == v) { SWAP(*b, *a); ++a; } + } + for(; (b < --c) && ((x = ISAd[*c]) >= v);) { + if(x == v) { SWAP(*c, *d); --d; } + } + } + + if(a <= d) { + c = b - 1; + if((s = a - first) > (t = b - a)) { s = t; } + for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + if((s = d - c) > (t = last - d - 1)) { s = t; } + for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); } + first += (b - a), last -= (d - c); + } + *pa = first, *pb = last; +} + +static +void +tr_copy(int *ISA, const int *SA, + int *first, int *a, int *b, int *last, + int depth) { + /* sort suffixes of middle partition + by using sorted order of suffixes of left and right partition. */ + int *c, *d, *e; + int s, v; + + v = b - SA - 1; + for(c = first, d = a - 1; c <= d; ++c) { + if((0 <= (s = *c - depth)) && (ISA[s] == v)) { + *++d = s; + ISA[s] = d - SA; + } + } + for(c = last - 1, e = d + 1, d = b; e < d; --c) { + if((0 <= (s = *c - depth)) && (ISA[s] == v)) { + *--d = s; + ISA[s] = d - SA; + } + } +} + +static +void +tr_partialcopy(int *ISA, const int *SA, + int *first, int *a, int *b, int *last, + int depth) { + int *c, *d, *e; + int s, v; + int rank, lastrank, newrank = -1; + + v = b - SA - 1; + lastrank = -1; + for(c = first, d = a - 1; c <= d; ++c) { + if((0 <= (s = *c - depth)) && (ISA[s] == v)) { + *++d = s; + rank = ISA[s + depth]; + if(lastrank != rank) { lastrank = rank; newrank = d - SA; } + ISA[s] = newrank; + } + } + + lastrank = -1; + for(e = d; first <= e; --e) { + rank = ISA[*e]; + if(lastrank != rank) { lastrank = rank; newrank = e - SA; } + if(newrank != rank) { ISA[*e] = newrank; } + } + + lastrank = -1; + for(c = last - 1, e = d + 1, d = b; e < d; --c) { + if((0 <= (s = *c - depth)) && (ISA[s] == v)) { + *--d = s; + rank = ISA[s + depth]; + if(lastrank != rank) { lastrank = rank; newrank = d - SA; } + ISA[s] = newrank; + } + } +} + +static +void +tr_introsort(int *ISA, const int *ISAd, + int *SA, int *first, int *last, + trbudget_t *budget) { +#define STACK_SIZE TR_STACKSIZE + struct { const int *a; int *b, *c; int d, e; }stack[STACK_SIZE]; + int *a, *b, *c; + int t; + int v, x = 0; + int incr = ISAd - ISA; + int limit, next; + int ssize, trlink = -1; + + for(ssize = 0, limit = tr_ilg(last - first);;) { + + if(limit < 0) { + if(limit == -1) { + /* tandem repeat partition */ + tr_partition(ISAd - incr, first, first, last, &a, &b, last - SA - 1); + + /* update ranks */ + if(a < last) { + for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; } + } + if(b < last) { + for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } + } + + /* push */ + if(1 < (b - a)) { + STACK_PUSH5(NULL, a, b, 0, 0); + STACK_PUSH5(ISAd - incr, first, last, -2, trlink); + trlink = ssize - 2; + } + if((a - first) <= (last - b)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink); + last = a, limit = tr_ilg(a - first); + } else if(1 < (last - b)) { + first = b, limit = tr_ilg(last - b); + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } else { + if(1 < (last - b)) { + STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink); + first = b, limit = tr_ilg(last - b); + } else if(1 < (a - first)) { + last = a, limit = tr_ilg(a - first); + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } else if(limit == -2) { + /* tandem repeat copy */ + a = stack[--ssize].b, b = stack[ssize].c; + if(stack[ssize].d == 0) { + tr_copy(ISA, SA, first, a, b, last, ISAd - ISA); + } else { + if(0 <= trlink) { stack[trlink].d = -1; } + tr_partialcopy(ISA, SA, first, a, b, last, ISAd - ISA); + } + STACK_POP5(ISAd, first, last, limit, trlink); + } else { + /* sorted partition */ + if(0 <= *first) { + a = first; + do { ISA[*a] = a - SA; } while((++a < last) && (0 <= *a)); + first = a; + } + if(first < last) { + a = first; do { *a = ~*a; } while(*++a < 0); + next = (ISA[*a] != ISAd[*a]) ? tr_ilg(a - first + 1) : -1; + if(++a < last) { for(b = first, v = a - SA - 1; b < a; ++b) { ISA[*b] = v; } } + + /* push */ + if(trbudget_check(budget, a - first)) { + if((a - first) <= (last - a)) { + STACK_PUSH5(ISAd, a, last, -3, trlink); + ISAd += incr, last = a, limit = next; + } else { + if(1 < (last - a)) { + STACK_PUSH5(ISAd + incr, first, a, next, trlink); + first = a, limit = -3; + } else { + ISAd += incr, last = a, limit = next; + } + } + } else { + if(0 <= trlink) { stack[trlink].d = -1; } + if(1 < (last - a)) { + first = a, limit = -3; + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + continue; + } + + if((last - first) <= TR_INSERTIONSORT_THRESHOLD) { + tr_insertionsort(ISAd, first, last); + limit = -3; + continue; + } + + if(limit-- == 0) { + tr_heapsort(ISAd, first, last - first); + for(a = last - 1; first < a; a = b) { + for(x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) { *b = ~*b; } + } + limit = -3; + continue; + } + + /* choose pivot */ + a = tr_pivot(ISAd, first, last); + SWAP(*first, *a); + v = ISAd[*first]; + + /* partition */ + tr_partition(ISAd, first, first + 1, last, &a, &b, v); + if((last - first) != (b - a)) { + next = (ISA[*a] != v) ? tr_ilg(b - a) : -1; + + /* update ranks */ + for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; } + if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } } + + /* push */ + if((1 < (b - a)) && (trbudget_check(budget, b - a))) { + if((a - first) <= (last - b)) { + if((last - b) <= (b - a)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + STACK_PUSH5(ISAd, b, last, limit, trlink); + last = a; + } else if(1 < (last - b)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + first = b; + } else { + ISAd += incr, first = a, last = b, limit = next; + } + } else if((a - first) <= (b - a)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd, b, last, limit, trlink); + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + last = a; + } else { + STACK_PUSH5(ISAd, b, last, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } else { + STACK_PUSH5(ISAd, b, last, limit, trlink); + STACK_PUSH5(ISAd, first, a, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } else { + if((a - first) <= (b - a)) { + if(1 < (last - b)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + STACK_PUSH5(ISAd, first, a, limit, trlink); + first = b; + } else if(1 < (a - first)) { + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + last = a; + } else { + ISAd += incr, first = a, last = b, limit = next; + } + } else if((last - b) <= (b - a)) { + if(1 < (last - b)) { + STACK_PUSH5(ISAd, first, a, limit, trlink); + STACK_PUSH5(ISAd + incr, a, b, next, trlink); + first = b; + } else { + STACK_PUSH5(ISAd, first, a, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } else { + STACK_PUSH5(ISAd, first, a, limit, trlink); + STACK_PUSH5(ISAd, b, last, limit, trlink); + ISAd += incr, first = a, last = b, limit = next; + } + } + } else { + if((1 < (b - a)) && (0 <= trlink)) { stack[trlink].d = -1; } + if((a - first) <= (last - b)) { + if(1 < (a - first)) { + STACK_PUSH5(ISAd, b, last, limit, trlink); + last = a; + } else if(1 < (last - b)) { + first = b; + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } else { + if(1 < (last - b)) { + STACK_PUSH5(ISAd, first, a, limit, trlink); + first = b; + } else if(1 < (a - first)) { + last = a; + } else { + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } + } else { + if(trbudget_check(budget, last - first)) { + limit = tr_ilg(last - first), ISAd += incr; + } else { + if(0 <= trlink) { stack[trlink].d = -1; } + STACK_POP5(ISAd, first, last, limit, trlink); + } + } + } +#undef STACK_SIZE +} + + + +/*---------------------------------------------------------------------------*/ + +/* Tandem repeat sort */ +static +void +trsort(int *ISA, int *SA, int n, int depth) { + int *ISAd; + int *first, *last; + trbudget_t budget; + int t, skip, unsorted; + + trbudget_init(&budget, tr_ilg(n) * 2 / 3, n); +/* trbudget_init(&budget, tr_ilg(n) * 3 / 4, n); */ + for(ISAd = ISA + depth; -n < *SA; ISAd += ISAd - ISA) { + first = SA; + skip = 0; + unsorted = 0; + do { + if((t = *first) < 0) { first -= t; skip += t; } + else { + if(skip != 0) { *(first + skip) = skip; skip = 0; } + last = SA + ISA[t] + 1; + if(1 < (last - first)) { + budget.count = 0; + tr_introsort(ISA, ISAd, SA, first, last, &budget); + if(budget.count != 0) { unsorted += budget.count; } + else { skip = first - last; } + } else if((last - first) == 1) { + skip = -1; + } + first = last; + } + } while(first < (SA + n)); + if(skip != 0) { *(first + skip) = skip; } + if(unsorted == 0) { break; } + } +} + + +/*---------------------------------------------------------------------------*/ + +/* Sorts suffixes of type B*. */ +static +int +sort_typeBstar(const unsigned char *T, int *SA, + int *bucket_A, int *bucket_B, + int n, int openMP) { + int *PAb, *ISAb, *buf; +#ifdef LIBBSC_OPENMP + int *curbuf; + int l; +#endif + int i, j, k, t, m, bufsize; + int c0, c1; +#ifdef LIBBSC_OPENMP + int d0, d1; +#endif + (void)openMP; + + /* Initialize bucket arrays. */ + for(i = 0; i < BUCKET_A_SIZE; ++i) { bucket_A[i] = 0; } + for(i = 0; i < BUCKET_B_SIZE; ++i) { bucket_B[i] = 0; } + + /* Count the number of occurrences of the first one or two characters of each + type A, B and B* suffix. Moreover, store the beginning position of all + type B* suffixes into the array SA. */ + for(i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) { + /* type A suffix. */ + do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1)); + if(0 <= i) { + /* type B* suffix. */ + ++BUCKET_BSTAR(c0, c1); + SA[--m] = i; + /* type B suffix. */ + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { + ++BUCKET_B(c0, c1); + } + } + } + m = n - m; +/* +note: + A type B* suffix is lexicographically smaller than a type B suffix that + begins with the same first two characters. +*/ + + /* Calculate the index of start/end point of each bucket. */ + for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) { + t = i + BUCKET_A(c0); + BUCKET_A(c0) = i + j; /* start point */ + i = t + BUCKET_B(c0, c0); + for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) { + j += BUCKET_BSTAR(c0, c1); + BUCKET_BSTAR(c0, c1) = j; /* end point */ + i += BUCKET_B(c0, c1); + } + } + + if(0 < m) { + /* Sort the type B* suffixes by their first two characters. */ + PAb = SA + n - m; ISAb = SA + m; + for(i = m - 2; 0 <= i; --i) { + t = PAb[i], c0 = T[t], c1 = T[t + 1]; + SA[--BUCKET_BSTAR(c0, c1)] = i; + } + t = PAb[m - 1], c0 = T[t], c1 = T[t + 1]; + SA[--BUCKET_BSTAR(c0, c1)] = m - 1; + + /* Sort the type B* substrings using sssort. */ +#ifdef LIBBSC_OPENMP + if (openMP) + { + buf = SA + m; + c0 = ALPHABET_SIZE - 2, c1 = ALPHABET_SIZE - 1, j = m; +#pragma omp parallel default(shared) private(bufsize, curbuf, k, l, d0, d1) + { + bufsize = (n - (2 * m)) / omp_get_num_threads(); + curbuf = buf + omp_get_thread_num() * bufsize; + k = 0; + for(;;) { + #pragma omp critical(sssort_lock) + { + if(0 < (l = j)) { + d0 = c0, d1 = c1; + do { + k = BUCKET_BSTAR(d0, d1); + if(--d1 <= d0) { + d1 = ALPHABET_SIZE - 1; + if(--d0 < 0) { break; } + } + } while(((l - k) <= 1) && (0 < (l = k))); + c0 = d0, c1 = d1, j = k; + } + } + if(l == 0) { break; } + sssort(T, PAb, SA + k, SA + l, + curbuf, bufsize, 2, n, *(SA + k) == (m - 1)); + } + } + } + else + { + buf = SA + m, bufsize = n - (2 * m); + for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) { + for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) { + i = BUCKET_BSTAR(c0, c1); + if(1 < (j - i)) { + sssort(T, PAb, SA + i, SA + j, + buf, bufsize, 2, n, *(SA + i) == (m - 1)); + } + } + } + } +#else + buf = SA + m, bufsize = n - (2 * m); + for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) { + for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) { + i = BUCKET_BSTAR(c0, c1); + if(1 < (j - i)) { + sssort(T, PAb, SA + i, SA + j, + buf, bufsize, 2, n, *(SA + i) == (m - 1)); + } + } + } +#endif + + /* Compute ranks of type B* substrings. */ + for(i = m - 1; 0 <= i; --i) { + if(0 <= SA[i]) { + j = i; + do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i])); + SA[i + 1] = i - j; + if(i <= 0) { break; } + } + j = i; + do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0); + ISAb[SA[i]] = j; + } + + /* Construct the inverse suffix array of type B* suffixes using trsort. */ + trsort(ISAb, SA, m, 1); + + /* Set the sorted order of type B* suffixes. */ + for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) { + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { } + if(0 <= i) { + t = i; + for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { } + SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t; + } + } + + /* Calculate the index of start/end point of each bucket. */ + BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */ + for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) { + i = BUCKET_A(c0 + 1) - 1; + for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) { + t = i - BUCKET_B(c0, c1); + BUCKET_B(c0, c1) = i; /* end point */ + + /* Move all type B* suffixes to the correct position. */ + for(i = t, j = BUCKET_BSTAR(c0, c1); + j <= k; + --i, --k) { SA[i] = SA[k]; } + } + BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */ + BUCKET_B(c0, c0) = i; /* end point */ + } + } + + return m; +} + +/* Constructs the suffix array by using the sorted order of type B* suffixes. */ +static +void +construct_SA(const unsigned char *T, int *SA, + int *bucket_A, int *bucket_B, + int n, int m) { + int *i, *j, *k; + int s; + int c0, c1, c2; + + if(0 < m) { + /* Construct the sorted order of type B suffixes by using + the sorted order of type B* suffixes. */ + for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) { + /* Scan the suffix array from right to left. */ + for(i = SA + BUCKET_BSTAR(c1, c1 + 1), + j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; + i <= j; + --j) { + if(0 < (s = *j)) { + assert(T[s] == c1); + assert(((s + 1) < n) && (T[s] <= T[s + 1])); + assert(T[s - 1] <= T[s]); + *j = ~s; + c0 = T[--s]; + if((0 < s) && (T[s - 1] > c0)) { s = ~s; } + if(c0 != c2) { + if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; } + k = SA + BUCKET_B(c2 = c0, c1); + } + assert(k < j); assert(k != NULL); + *k-- = s; + } else { + assert(((s == 0) && (T[s] == c1)) || (s < 0)); + *j = ~s; + } + } + } + } + + /* Construct the suffix array by using + the sorted order of type B suffixes. */ + k = SA + BUCKET_A(c2 = T[n - 1]); + *k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1); + /* Scan the suffix array from left to right. */ + for(i = SA, j = SA + n; i < j; ++i) { + if(0 < (s = *i)) { + assert(T[s - 1] >= T[s]); + c0 = T[--s]; + if((s == 0) || (T[s - 1] < c0)) { s = ~s; } + if(c0 != c2) { + BUCKET_A(c2) = k - SA; + k = SA + BUCKET_A(c2 = c0); + } + assert(i < k); + *k++ = s; + } else { + assert(s < 0); + *i = ~s; + } + } +} + +/* Constructs the burrows-wheeler transformed string directly + by using the sorted order of type B* suffixes. */ +static +int +construct_BWT(const unsigned char *T, int *SA, + int *bucket_A, int *bucket_B, + int n, int m) { + int *i, *j, *k, *orig; + int s; + int c0, c1, c2; + + if(0 < m) { + /* Construct the sorted order of type B suffixes by using + the sorted order of type B* suffixes. */ + for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) { + /* Scan the suffix array from right to left. */ + for(i = SA + BUCKET_BSTAR(c1, c1 + 1), + j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; + i <= j; + --j) { + if(0 < (s = *j)) { + assert(T[s] == c1); + assert(((s + 1) < n) && (T[s] <= T[s + 1])); + assert(T[s - 1] <= T[s]); + c0 = T[--s]; + *j = ~((int)c0); + if((0 < s) && (T[s - 1] > c0)) { s = ~s; } + if(c0 != c2) { + if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; } + k = SA + BUCKET_B(c2 = c0, c1); + } + assert(k < j); assert(k != NULL); + *k-- = s; + } else if(s != 0) { + *j = ~s; +#ifndef NDEBUG + } else { + assert(T[s] == c1); +#endif + } + } + } + } + + /* Construct the BWTed string by using + the sorted order of type B suffixes. */ + k = SA + BUCKET_A(c2 = T[n - 1]); + *k++ = (T[n - 2] < c2) ? ~((int)T[n - 2]) : (n - 1); + /* Scan the suffix array from left to right. */ + for(i = SA, j = SA + n, orig = SA; i < j; ++i) { + if(0 < (s = *i)) { + assert(T[s - 1] >= T[s]); + c0 = T[--s]; + *i = c0; + if((0 < s) && (T[s - 1] < c0)) { s = ~((int)T[s - 1]); } + if(c0 != c2) { + BUCKET_A(c2) = k - SA; + k = SA + BUCKET_A(c2 = c0); + } + assert(i < k); + *k++ = s; + } else if(s != 0) { + *i = ~s; + } else { + orig = i; + } + } + + return orig - SA; +} + +/* Constructs the burrows-wheeler transformed string directly + by using the sorted order of type B* suffixes. */ +static +int +construct_BWT_indexes(const unsigned char *T, int *SA, + int *bucket_A, int *bucket_B, + int n, int m, + unsigned char * num_indexes, int * indexes) { + int *i, *j, *k, *orig; + int s; + int c0, c1, c2; + + int mod = n / 8; + { + mod |= mod >> 1; mod |= mod >> 2; + mod |= mod >> 4; mod |= mod >> 8; + mod |= mod >> 16; mod >>= 1; + + *num_indexes = (unsigned char)((n - 1) / (mod + 1)); + } + + if(0 < m) { + /* Construct the sorted order of type B suffixes by using + the sorted order of type B* suffixes. */ + for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) { + /* Scan the suffix array from right to left. */ + for(i = SA + BUCKET_BSTAR(c1, c1 + 1), + j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; + i <= j; + --j) { + if(0 < (s = *j)) { + assert(T[s] == c1); + assert(((s + 1) < n) && (T[s] <= T[s + 1])); + assert(T[s - 1] <= T[s]); + + if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = j - SA; + + c0 = T[--s]; + *j = ~((int)c0); + if((0 < s) && (T[s - 1] > c0)) { s = ~s; } + if(c0 != c2) { + if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; } + k = SA + BUCKET_B(c2 = c0, c1); + } + assert(k < j); assert(k != NULL); + *k-- = s; + } else if(s != 0) { + *j = ~s; +#ifndef NDEBUG + } else { + assert(T[s] == c1); +#endif + } + } + } + } + + /* Construct the BWTed string by using + the sorted order of type B suffixes. */ + k = SA + BUCKET_A(c2 = T[n - 1]); + if (T[n - 2] < c2) { + if (((n - 1) & mod) == 0) indexes[(n - 1) / (mod + 1) - 1] = k - SA; + *k++ = ~((int)T[n - 2]); + } + else { + *k++ = n - 1; + } + + /* Scan the suffix array from left to right. */ + for(i = SA, j = SA + n, orig = SA; i < j; ++i) { + if(0 < (s = *i)) { + assert(T[s - 1] >= T[s]); + + if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = i - SA; + + c0 = T[--s]; + *i = c0; + if(c0 != c2) { + BUCKET_A(c2) = k - SA; + k = SA + BUCKET_A(c2 = c0); + } + assert(i < k); + if((0 < s) && (T[s - 1] < c0)) { + if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = k - SA; + *k++ = ~((int)T[s - 1]); + } else + *k++ = s; + } else if(s != 0) { + *i = ~s; + } else { + orig = i; + } + } + + return orig - SA; +} + + +/*---------------------------------------------------------------------------*/ + +/*- Function -*/ + +int +divsufsort(const unsigned char *T, int *SA, int n, int openMP) { + int *bucket_A, *bucket_B; + int m; + int err = 0; + + /* Check arguments. */ + if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; } + else if(n == 0) { return 0; } + else if(n == 1) { SA[0] = 0; return 0; } + else if(n == 2) { m = (T[0] < T[1]); SA[m ^ 1] = 0, SA[m] = 1; return 0; } + + bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int)); + bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int)); + + /* Suffixsort. */ + if((bucket_A != NULL) && (bucket_B != NULL)) { + m = sort_typeBstar(T, SA, bucket_A, bucket_B, n, openMP); + construct_SA(T, SA, bucket_A, bucket_B, n, m); + } else { + err = -2; + } + + free(bucket_B); + free(bucket_A); + + return err; +} + +int +divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP) { + int *B; + int *bucket_A, *bucket_B; + int m, pidx, i; + + /* Check arguments. */ + if((T == NULL) || (U == NULL) || (n < 0)) { return -1; } + else if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; } + + if((B = A) == NULL) { B = (int *)malloc((size_t)(n + 1) * sizeof(int)); } + bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int)); + bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int)); + + /* Burrows-Wheeler Transform. */ + if((B != NULL) && (bucket_A != NULL) && (bucket_B != NULL)) { + m = sort_typeBstar(T, B, bucket_A, bucket_B, n, openMP); + + if (num_indexes == NULL || indexes == NULL) { + pidx = construct_BWT(T, B, bucket_A, bucket_B, n, m); + } else { + pidx = construct_BWT_indexes(T, B, bucket_A, bucket_B, n, m, num_indexes, indexes); + } + + /* Copy to output string. */ + U[0] = T[n - 1]; + for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)B[i]; } + for(i += 1; i < n; ++i) { U[i] = (unsigned char)B[i]; } + pidx += 1; + } else { + pidx = -2; + } + + free(bucket_B); + free(bucket_A); + if(A == NULL) { free(B); } + + return pidx; +} diff --git a/third_party/zstd/dict/fastcover.c b/third_party/zstd/dict/fastcover.c new file mode 100644 index 00000000000..a958eb337f1 --- /dev/null +++ b/third_party/zstd/dict/fastcover.c @@ -0,0 +1,766 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/*-************************************* +* Dependencies +***************************************/ +#include /* fprintf */ +#include /* malloc, free, qsort */ +#include /* memset */ +#include /* clock */ + +#ifndef ZDICT_STATIC_LINKING_ONLY +# define ZDICT_STATIC_LINKING_ONLY +#endif + +#include "../common/mem.h" /* read */ +#include "../common/pool.h" +#include "../common/threading.h" +#include "../common/zstd_internal.h" /* includes zstd.h */ +#include "../compress/zstd_compress_internal.h" /* ZSTD_hash*() */ +#include "../zdict.h" +#include "cover.h" + + +/*-************************************* +* Constants +***************************************/ +/** +* There are 32bit indexes used to ref samples, so limit samples size to 4GB +* on 64bit builds. +* For 32bit builds we choose 1 GB. +* Most 32bit platforms have 2GB user-mode addressable space and we allocate a large +* contiguous buffer, so 1GB is already a high limit. +*/ +#define FASTCOVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB)) +#define FASTCOVER_MAX_F 31 +#define FASTCOVER_MAX_ACCEL 10 +#define FASTCOVER_DEFAULT_SPLITPOINT 0.75 +#define DEFAULT_F 20 +#define DEFAULT_ACCEL 1 + + +/*-************************************* +* Console display +***************************************/ +#ifndef LOCALDISPLAYLEVEL +static int g_displayLevel = 0; +#endif +#undef DISPLAY +#define DISPLAY(...) \ + { \ + fprintf(stderr, __VA_ARGS__); \ + fflush(stderr); \ + } +#undef LOCALDISPLAYLEVEL +#define LOCALDISPLAYLEVEL(displayLevel, l, ...) \ + if (displayLevel >= l) { \ + DISPLAY(__VA_ARGS__); \ + } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */ +#undef DISPLAYLEVEL +#define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__) + +#ifndef LOCALDISPLAYUPDATE +static const clock_t g_refreshRate = CLOCKS_PER_SEC * 15 / 100; +static clock_t g_time = 0; +#endif +#undef LOCALDISPLAYUPDATE +#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \ + if (displayLevel >= l) { \ + if ((clock() - g_time > g_refreshRate) || (displayLevel >= 4)) { \ + g_time = clock(); \ + DISPLAY(__VA_ARGS__); \ + } \ + } +#undef DISPLAYUPDATE +#define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__) + + +/*-************************************* +* Hash Functions +***************************************/ +/** + * Hash the d-byte value pointed to by p and mod 2^f into the frequency vector + */ +static size_t FASTCOVER_hashPtrToIndex(const void* p, U32 f, unsigned d) { + if (d == 6) { + return ZSTD_hash6Ptr(p, f); + } + return ZSTD_hash8Ptr(p, f); +} + + +/*-************************************* +* Acceleration +***************************************/ +typedef struct { + unsigned finalize; /* Percentage of training samples used for ZDICT_finalizeDictionary */ + unsigned skip; /* Number of dmer skipped between each dmer counted in computeFrequency */ +} FASTCOVER_accel_t; + + +static const FASTCOVER_accel_t FASTCOVER_defaultAccelParameters[FASTCOVER_MAX_ACCEL+1] = { + { 100, 0 }, /* accel = 0, should not happen because accel = 0 defaults to accel = 1 */ + { 100, 0 }, /* accel = 1 */ + { 50, 1 }, /* accel = 2 */ + { 34, 2 }, /* accel = 3 */ + { 25, 3 }, /* accel = 4 */ + { 20, 4 }, /* accel = 5 */ + { 17, 5 }, /* accel = 6 */ + { 14, 6 }, /* accel = 7 */ + { 13, 7 }, /* accel = 8 */ + { 11, 8 }, /* accel = 9 */ + { 10, 9 }, /* accel = 10 */ +}; + + +/*-************************************* +* Context +***************************************/ +typedef struct { + const BYTE *samples; + size_t *offsets; + const size_t *samplesSizes; + size_t nbSamples; + size_t nbTrainSamples; + size_t nbTestSamples; + size_t nbDmers; + U32 *freqs; + unsigned d; + unsigned f; + FASTCOVER_accel_t accelParams; +} FASTCOVER_ctx_t; + + +/*-************************************* +* Helper functions +***************************************/ +/** + * Selects the best segment in an epoch. + * Segments of are scored according to the function: + * + * Let F(d) be the frequency of all dmers with hash value d. + * Let S_i be hash value of the dmer at position i of segment S which has length k. + * + * Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1}) + * + * Once the dmer with hash value d is in the dictionary we set F(d) = 0. + */ +static COVER_segment_t FASTCOVER_selectSegment(const FASTCOVER_ctx_t *ctx, + U32 *freqs, U32 begin, U32 end, + ZDICT_cover_params_t parameters, + U16* segmentFreqs) { + /* Constants */ + const U32 k = parameters.k; + const U32 d = parameters.d; + const U32 f = ctx->f; + const U32 dmersInK = k - d + 1; + + /* Try each segment (activeSegment) and save the best (bestSegment) */ + COVER_segment_t bestSegment = {0, 0, 0}; + COVER_segment_t activeSegment; + + /* Reset the activeDmers in the segment */ + /* The activeSegment starts at the beginning of the epoch. */ + activeSegment.begin = begin; + activeSegment.end = begin; + activeSegment.score = 0; + + /* Slide the activeSegment through the whole epoch. + * Save the best segment in bestSegment. + */ + while (activeSegment.end < end) { + /* Get hash value of current dmer */ + const size_t idx = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.end, f, d); + + /* Add frequency of this index to score if this is the first occurrence of index in active segment */ + if (segmentFreqs[idx] == 0) { + activeSegment.score += freqs[idx]; + } + /* Increment end of segment and segmentFreqs*/ + activeSegment.end += 1; + segmentFreqs[idx] += 1; + /* If the window is now too large, drop the first position */ + if (activeSegment.end - activeSegment.begin == dmersInK + 1) { + /* Get hash value of the dmer to be eliminated from active segment */ + const size_t delIndex = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.begin, f, d); + segmentFreqs[delIndex] -= 1; + /* Subtract frequency of this index from score if this is the last occurrence of this index in active segment */ + if (segmentFreqs[delIndex] == 0) { + activeSegment.score -= freqs[delIndex]; + } + /* Increment start of segment */ + activeSegment.begin += 1; + } + + /* If this segment is the best so far save it */ + if (activeSegment.score > bestSegment.score) { + bestSegment = activeSegment; + } + } + + /* Zero out rest of segmentFreqs array */ + while (activeSegment.begin < end) { + const size_t delIndex = FASTCOVER_hashPtrToIndex(ctx->samples + activeSegment.begin, f, d); + segmentFreqs[delIndex] -= 1; + activeSegment.begin += 1; + } + + { + /* Zero the frequency of hash value of each dmer covered by the chosen segment. */ + U32 pos; + for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) { + const size_t i = FASTCOVER_hashPtrToIndex(ctx->samples + pos, f, d); + freqs[i] = 0; + } + } + + return bestSegment; +} + + +static int FASTCOVER_checkParameters(ZDICT_cover_params_t parameters, + size_t maxDictSize, unsigned f, + unsigned accel) { + /* k, d, and f are required parameters */ + if (parameters.d == 0 || parameters.k == 0) { + return 0; + } + /* d has to be 6 or 8 */ + if (parameters.d != 6 && parameters.d != 8) { + return 0; + } + /* k <= maxDictSize */ + if (parameters.k > maxDictSize) { + return 0; + } + /* d <= k */ + if (parameters.d > parameters.k) { + return 0; + } + /* 0 < f <= FASTCOVER_MAX_F*/ + if (f > FASTCOVER_MAX_F || f == 0) { + return 0; + } + /* 0 < splitPoint <= 1 */ + if (parameters.splitPoint <= 0 || parameters.splitPoint > 1) { + return 0; + } + /* 0 < accel <= 10 */ + if (accel > 10 || accel == 0) { + return 0; + } + return 1; +} + + +/** + * Clean up a context initialized with `FASTCOVER_ctx_init()`. + */ +static void +FASTCOVER_ctx_destroy(FASTCOVER_ctx_t* ctx) +{ + if (!ctx) return; + + free(ctx->freqs); + ctx->freqs = NULL; + + free(ctx->offsets); + ctx->offsets = NULL; +} + + +/** + * Calculate for frequency of hash value of each dmer in ctx->samples + */ +static void +FASTCOVER_computeFrequency(U32* freqs, const FASTCOVER_ctx_t* ctx) +{ + const unsigned f = ctx->f; + const unsigned d = ctx->d; + const unsigned skip = ctx->accelParams.skip; + const unsigned readLength = MAX(d, 8); + size_t i; + assert(ctx->nbTrainSamples >= 5); + assert(ctx->nbTrainSamples <= ctx->nbSamples); + for (i = 0; i < ctx->nbTrainSamples; i++) { + size_t start = ctx->offsets[i]; /* start of current dmer */ + size_t const currSampleEnd = ctx->offsets[i+1]; + while (start + readLength <= currSampleEnd) { + const size_t dmerIndex = FASTCOVER_hashPtrToIndex(ctx->samples + start, f, d); + freqs[dmerIndex]++; + start = start + skip + 1; + } + } +} + + +/** + * Prepare a context for dictionary building. + * The context is only dependent on the parameter `d` and can be used multiple + * times. + * Returns 0 on success or error code on error. + * The context must be destroyed with `FASTCOVER_ctx_destroy()`. + */ +static size_t +FASTCOVER_ctx_init(FASTCOVER_ctx_t* ctx, + const void* samplesBuffer, + const size_t* samplesSizes, unsigned nbSamples, + unsigned d, double splitPoint, unsigned f, + FASTCOVER_accel_t accelParams) +{ + const BYTE* const samples = (const BYTE*)samplesBuffer; + const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples); + /* Split samples into testing and training sets */ + const unsigned nbTrainSamples = splitPoint < 1.0 ? (unsigned)((double)nbSamples * splitPoint) : nbSamples; + const unsigned nbTestSamples = splitPoint < 1.0 ? nbSamples - nbTrainSamples : nbSamples; + const size_t trainingSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes, nbTrainSamples) : totalSamplesSize; + const size_t testSamplesSize = splitPoint < 1.0 ? COVER_sum(samplesSizes + nbTrainSamples, nbTestSamples) : totalSamplesSize; + + /* Checks */ + if (totalSamplesSize < MAX(d, sizeof(U64)) || + totalSamplesSize >= (size_t)FASTCOVER_MAX_SAMPLES_SIZE) { + DISPLAYLEVEL(1, "Total samples size is too large (%u MB), maximum size is %u MB\n", + (unsigned)(totalSamplesSize >> 20), (FASTCOVER_MAX_SAMPLES_SIZE >> 20)); + return ERROR(srcSize_wrong); + } + + /* Check if there are at least 5 training samples */ + if (nbTrainSamples < 5) { + DISPLAYLEVEL(1, "Total number of training samples is %u and is invalid\n", nbTrainSamples); + return ERROR(srcSize_wrong); + } + + /* Check if there's testing sample */ + if (nbTestSamples < 1) { + DISPLAYLEVEL(1, "Total number of testing samples is %u and is invalid.\n", nbTestSamples); + return ERROR(srcSize_wrong); + } + + /* Zero the context */ + memset(ctx, 0, sizeof(*ctx)); + DISPLAYLEVEL(2, "Training on %u samples of total size %u\n", nbTrainSamples, + (unsigned)trainingSamplesSize); + DISPLAYLEVEL(2, "Testing on %u samples of total size %u\n", nbTestSamples, + (unsigned)testSamplesSize); + + ctx->samples = samples; + ctx->samplesSizes = samplesSizes; + ctx->nbSamples = nbSamples; + ctx->nbTrainSamples = nbTrainSamples; + ctx->nbTestSamples = nbTestSamples; + ctx->nbDmers = trainingSamplesSize - MAX(d, sizeof(U64)) + 1; + ctx->d = d; + ctx->f = f; + ctx->accelParams = accelParams; + + /* The offsets of each file */ + ctx->offsets = (size_t*)calloc((nbSamples + 1), sizeof(size_t)); + if (ctx->offsets == NULL) { + DISPLAYLEVEL(1, "Failed to allocate scratch buffers \n"); + FASTCOVER_ctx_destroy(ctx); + return ERROR(memory_allocation); + } + + /* Fill offsets from the samplesSizes */ + { U32 i; + ctx->offsets[0] = 0; + assert(nbSamples >= 5); + for (i = 1; i <= nbSamples; ++i) { + ctx->offsets[i] = ctx->offsets[i - 1] + samplesSizes[i - 1]; + } + } + + /* Initialize frequency array of size 2^f */ + ctx->freqs = (U32*)calloc(((U64)1 << f), sizeof(U32)); + if (ctx->freqs == NULL) { + DISPLAYLEVEL(1, "Failed to allocate frequency table \n"); + FASTCOVER_ctx_destroy(ctx); + return ERROR(memory_allocation); + } + + DISPLAYLEVEL(2, "Computing frequencies\n"); + FASTCOVER_computeFrequency(ctx->freqs, ctx); + + return 0; +} + + +/** + * Given the prepared context build the dictionary. + */ +static size_t +FASTCOVER_buildDictionary(const FASTCOVER_ctx_t* ctx, + U32* freqs, + void* dictBuffer, size_t dictBufferCapacity, + ZDICT_cover_params_t parameters, + U16* segmentFreqs) +{ + BYTE *const dict = (BYTE *)dictBuffer; + size_t tail = dictBufferCapacity; + /* Divide the data into epochs. We will select one segment from each epoch. */ + const COVER_epoch_info_t epochs = COVER_computeEpochs( + (U32)dictBufferCapacity, (U32)ctx->nbDmers, parameters.k, 1); + const size_t maxZeroScoreRun = 10; + size_t zeroScoreRun = 0; + size_t epoch; + DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n", + (U32)epochs.num, (U32)epochs.size); + /* Loop through the epochs until there are no more segments or the dictionary + * is full. + */ + for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs.num) { + const U32 epochBegin = (U32)(epoch * epochs.size); + const U32 epochEnd = epochBegin + epochs.size; + size_t segmentSize; + /* Select a segment */ + COVER_segment_t segment = FASTCOVER_selectSegment( + ctx, freqs, epochBegin, epochEnd, parameters, segmentFreqs); + + /* If the segment covers no dmers, then we are out of content. + * There may be new content in other epochs, for continue for some time. + */ + if (segment.score == 0) { + if (++zeroScoreRun >= maxZeroScoreRun) { + break; + } + continue; + } + zeroScoreRun = 0; + + /* Trim the segment if necessary and if it is too small then we are done */ + segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail); + if (segmentSize < parameters.d) { + break; + } + + /* We fill the dictionary from the back to allow the best segments to be + * referenced with the smallest offsets. + */ + tail -= segmentSize; + memcpy(dict + tail, ctx->samples + segment.begin, segmentSize); + DISPLAYUPDATE( + 2, "\r%u%% ", + (unsigned)(((dictBufferCapacity - tail) * 100) / dictBufferCapacity)); + } + DISPLAYLEVEL(2, "\r%79s\r", ""); + return tail; +} + +/** + * Parameters for FASTCOVER_tryParameters(). + */ +typedef struct FASTCOVER_tryParameters_data_s { + const FASTCOVER_ctx_t* ctx; + COVER_best_t* best; + size_t dictBufferCapacity; + ZDICT_cover_params_t parameters; +} FASTCOVER_tryParameters_data_t; + + +/** + * Tries a set of parameters and updates the COVER_best_t with the results. + * This function is thread safe if zstd is compiled with multithreaded support. + * It takes its parameters as an *OWNING* opaque pointer to support threading. + */ +static void FASTCOVER_tryParameters(void* opaque) +{ + /* Save parameters as local variables */ + FASTCOVER_tryParameters_data_t *const data = (FASTCOVER_tryParameters_data_t*)opaque; + const FASTCOVER_ctx_t *const ctx = data->ctx; + const ZDICT_cover_params_t parameters = data->parameters; + size_t dictBufferCapacity = data->dictBufferCapacity; + size_t totalCompressedSize = ERROR(GENERIC); + /* Initialize array to keep track of frequency of dmer within activeSegment */ + U16* segmentFreqs = (U16*)calloc(((U64)1 << ctx->f), sizeof(U16)); + /* Allocate space for hash table, dict, and freqs */ + BYTE *const dict = (BYTE*)malloc(dictBufferCapacity); + COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC)); + U32* freqs = (U32*) malloc(((U64)1 << ctx->f) * sizeof(U32)); + if (!segmentFreqs || !dict || !freqs) { + DISPLAYLEVEL(1, "Failed to allocate buffers: out of memory\n"); + goto _cleanup; + } + /* Copy the frequencies because we need to modify them */ + memcpy(freqs, ctx->freqs, ((U64)1 << ctx->f) * sizeof(U32)); + /* Build the dictionary */ + { const size_t tail = FASTCOVER_buildDictionary(ctx, freqs, dict, dictBufferCapacity, + parameters, segmentFreqs); + + const unsigned nbFinalizeSamples = (unsigned)(ctx->nbTrainSamples * ctx->accelParams.finalize / 100); + selection = COVER_selectDict(dict + tail, dictBufferCapacity, dictBufferCapacity - tail, + ctx->samples, ctx->samplesSizes, nbFinalizeSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets, + totalCompressedSize); + + if (COVER_dictSelectionIsError(selection)) { + DISPLAYLEVEL(1, "Failed to select dictionary\n"); + goto _cleanup; + } + } +_cleanup: + free(dict); + COVER_best_finish(data->best, parameters, selection); + free(data); + free(segmentFreqs); + COVER_dictSelectionFree(selection); + free(freqs); +} + + +static void +FASTCOVER_convertToCoverParams(ZDICT_fastCover_params_t fastCoverParams, + ZDICT_cover_params_t* coverParams) +{ + coverParams->k = fastCoverParams.k; + coverParams->d = fastCoverParams.d; + coverParams->steps = fastCoverParams.steps; + coverParams->nbThreads = fastCoverParams.nbThreads; + coverParams->splitPoint = fastCoverParams.splitPoint; + coverParams->zParams = fastCoverParams.zParams; + coverParams->shrinkDict = fastCoverParams.shrinkDict; +} + + +static void +FASTCOVER_convertToFastCoverParams(ZDICT_cover_params_t coverParams, + ZDICT_fastCover_params_t* fastCoverParams, + unsigned f, unsigned accel) +{ + fastCoverParams->k = coverParams.k; + fastCoverParams->d = coverParams.d; + fastCoverParams->steps = coverParams.steps; + fastCoverParams->nbThreads = coverParams.nbThreads; + fastCoverParams->splitPoint = coverParams.splitPoint; + fastCoverParams->f = f; + fastCoverParams->accel = accel; + fastCoverParams->zParams = coverParams.zParams; + fastCoverParams->shrinkDict = coverParams.shrinkDict; +} + + +ZDICTLIB_STATIC_API size_t +ZDICT_trainFromBuffer_fastCover(void* dictBuffer, size_t dictBufferCapacity, + const void* samplesBuffer, + const size_t* samplesSizes, unsigned nbSamples, + ZDICT_fastCover_params_t parameters) +{ + BYTE* const dict = (BYTE*)dictBuffer; + FASTCOVER_ctx_t ctx; + ZDICT_cover_params_t coverParams; + FASTCOVER_accel_t accelParams; + /* Initialize global data */ + g_displayLevel = (int)parameters.zParams.notificationLevel; + /* Assign splitPoint and f if not provided */ + parameters.splitPoint = 1.0; + parameters.f = parameters.f == 0 ? DEFAULT_F : parameters.f; + parameters.accel = parameters.accel == 0 ? DEFAULT_ACCEL : parameters.accel; + /* Convert to cover parameter */ + memset(&coverParams, 0 , sizeof(coverParams)); + FASTCOVER_convertToCoverParams(parameters, &coverParams); + /* Checks */ + if (!FASTCOVER_checkParameters(coverParams, dictBufferCapacity, parameters.f, + parameters.accel)) { + DISPLAYLEVEL(1, "FASTCOVER parameters incorrect\n"); + return ERROR(parameter_outOfBound); + } + if (nbSamples == 0) { + DISPLAYLEVEL(1, "FASTCOVER must have at least one input file\n"); + return ERROR(srcSize_wrong); + } + if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) { + DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n", + ZDICT_DICTSIZE_MIN); + return ERROR(dstSize_tooSmall); + } + /* Assign corresponding FASTCOVER_accel_t to accelParams*/ + accelParams = FASTCOVER_defaultAccelParameters[parameters.accel]; + /* Initialize context */ + { + size_t const initVal = FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, + coverParams.d, parameters.splitPoint, parameters.f, + accelParams); + if (ZSTD_isError(initVal)) { + DISPLAYLEVEL(1, "Failed to initialize context\n"); + return initVal; + } + } + COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, g_displayLevel); + /* Build the dictionary */ + DISPLAYLEVEL(2, "Building dictionary\n"); + { + /* Initialize array to keep track of frequency of dmer within activeSegment */ + U16* segmentFreqs = (U16 *)calloc(((U64)1 << parameters.f), sizeof(U16)); + const size_t tail = FASTCOVER_buildDictionary(&ctx, ctx.freqs, dictBuffer, + dictBufferCapacity, coverParams, segmentFreqs); + const unsigned nbFinalizeSamples = (unsigned)(ctx.nbTrainSamples * ctx.accelParams.finalize / 100); + const size_t dictionarySize = ZDICT_finalizeDictionary( + dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail, + samplesBuffer, samplesSizes, nbFinalizeSamples, coverParams.zParams); + if (!ZSTD_isError(dictionarySize)) { + DISPLAYLEVEL(2, "Constructed dictionary of size %u\n", + (unsigned)dictionarySize); + } + FASTCOVER_ctx_destroy(&ctx); + free(segmentFreqs); + return dictionarySize; + } +} + + +ZDICTLIB_STATIC_API size_t +ZDICT_optimizeTrainFromBuffer_fastCover( + void* dictBuffer, size_t dictBufferCapacity, + const void* samplesBuffer, + const size_t* samplesSizes, unsigned nbSamples, + ZDICT_fastCover_params_t* parameters) +{ + ZDICT_cover_params_t coverParams; + FASTCOVER_accel_t accelParams; + /* constants */ + const unsigned nbThreads = parameters->nbThreads; + const double splitPoint = + parameters->splitPoint <= 0.0 ? FASTCOVER_DEFAULT_SPLITPOINT : parameters->splitPoint; + const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d; + const unsigned kMaxD = parameters->d == 0 ? 8 : parameters->d; + const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k; + const unsigned kMaxK = parameters->k == 0 ? 2000 : parameters->k; + const unsigned kSteps = parameters->steps == 0 ? 40 : parameters->steps; + const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1); + const unsigned kIterations = + (1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize); + const unsigned f = parameters->f == 0 ? DEFAULT_F : parameters->f; + const unsigned accel = parameters->accel == 0 ? DEFAULT_ACCEL : parameters->accel; + const unsigned shrinkDict = 0; + /* Local variables */ + const int displayLevel = (int)parameters->zParams.notificationLevel; + unsigned iteration = 1; + unsigned d; + unsigned k; + COVER_best_t best; + POOL_ctx *pool = NULL; + int warned = 0; + /* Checks */ + if (splitPoint <= 0 || splitPoint > 1) { + LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect splitPoint\n"); + return ERROR(parameter_outOfBound); + } + if (accel == 0 || accel > FASTCOVER_MAX_ACCEL) { + LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect accel\n"); + return ERROR(parameter_outOfBound); + } + if (kMinK < kMaxD || kMaxK < kMinK) { + LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect k\n"); + return ERROR(parameter_outOfBound); + } + if (nbSamples == 0) { + LOCALDISPLAYLEVEL(displayLevel, 1, "FASTCOVER must have at least one input file\n"); + return ERROR(srcSize_wrong); + } + if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) { + LOCALDISPLAYLEVEL(displayLevel, 1, "dictBufferCapacity must be at least %u\n", + ZDICT_DICTSIZE_MIN); + return ERROR(dstSize_tooSmall); + } + if (nbThreads > 1) { + pool = POOL_create(nbThreads, 1); + if (!pool) { + return ERROR(memory_allocation); + } + } + /* Initialization */ + COVER_best_init(&best); + memset(&coverParams, 0 , sizeof(coverParams)); + FASTCOVER_convertToCoverParams(*parameters, &coverParams); + accelParams = FASTCOVER_defaultAccelParameters[accel]; + /* Turn down global display level to clean up display at level 2 and below */ + g_displayLevel = displayLevel == 0 ? 0 : displayLevel - 1; + /* Loop through d first because each new value needs a new context */ + LOCALDISPLAYLEVEL(displayLevel, 2, "Trying %u different sets of parameters\n", + kIterations); + for (d = kMinD; d <= kMaxD; d += 2) { + /* Initialize the context for this value of d */ + FASTCOVER_ctx_t ctx; + LOCALDISPLAYLEVEL(displayLevel, 3, "d=%u\n", d); + { + size_t const initVal = FASTCOVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d, splitPoint, f, accelParams); + if (ZSTD_isError(initVal)) { + LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n"); + COVER_best_destroy(&best); + POOL_free(pool); + return initVal; + } + } + if (!warned) { + COVER_warnOnSmallCorpus(dictBufferCapacity, ctx.nbDmers, displayLevel); + warned = 1; + } + /* Loop through k reusing the same context */ + for (k = kMinK; k <= kMaxK; k += kStepSize) { + /* Prepare the arguments */ + FASTCOVER_tryParameters_data_t *data = (FASTCOVER_tryParameters_data_t *)malloc( + sizeof(FASTCOVER_tryParameters_data_t)); + LOCALDISPLAYLEVEL(displayLevel, 3, "k=%u\n", k); + if (!data) { + LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to allocate parameters\n"); + COVER_best_destroy(&best); + FASTCOVER_ctx_destroy(&ctx); + POOL_free(pool); + return ERROR(memory_allocation); + } + data->ctx = &ctx; + data->best = &best; + data->dictBufferCapacity = dictBufferCapacity; + data->parameters = coverParams; + data->parameters.k = k; + data->parameters.d = d; + data->parameters.splitPoint = splitPoint; + data->parameters.steps = kSteps; + data->parameters.shrinkDict = shrinkDict; + data->parameters.zParams.notificationLevel = (unsigned)g_displayLevel; + /* Check the parameters */ + if (!FASTCOVER_checkParameters(data->parameters, dictBufferCapacity, + data->ctx->f, accel)) { + DISPLAYLEVEL(1, "FASTCOVER parameters incorrect\n"); + free(data); + continue; + } + /* Call the function and pass ownership of data to it */ + COVER_best_start(&best); + if (pool) { + POOL_add(pool, &FASTCOVER_tryParameters, data); + } else { + FASTCOVER_tryParameters(data); + } + /* Print status */ + LOCALDISPLAYUPDATE(displayLevel, 2, "\r%u%% ", + (unsigned)((iteration * 100) / kIterations)); + ++iteration; + } + COVER_best_wait(&best); + FASTCOVER_ctx_destroy(&ctx); + } + LOCALDISPLAYLEVEL(displayLevel, 2, "\r%79s\r", ""); + /* Fill the output buffer and parameters with output of the best parameters */ + { + const size_t dictSize = best.dictSize; + if (ZSTD_isError(best.compressedSize)) { + const size_t compressedSize = best.compressedSize; + COVER_best_destroy(&best); + POOL_free(pool); + return compressedSize; + } + FASTCOVER_convertToFastCoverParams(best.parameters, parameters, f, accel); + memcpy(dictBuffer, best.dict, dictSize); + COVER_best_destroy(&best); + POOL_free(pool); + return dictSize; + } + +} diff --git a/third_party/zstd/dict/zdict.c b/third_party/zstd/dict/zdict.c new file mode 100644 index 00000000000..82e999e80e3 --- /dev/null +++ b/third_party/zstd/dict/zdict.c @@ -0,0 +1,1133 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + +/*-************************************** +* Tuning parameters +****************************************/ +#define MINRATIO 4 /* minimum nb of apparition to be selected in dictionary */ +#define ZDICT_MAX_SAMPLES_SIZE (2000U << 20) +#define ZDICT_MIN_SAMPLES_SIZE (ZDICT_CONTENTSIZE_MIN * MINRATIO) + + +/*-************************************** +* Compiler Options +****************************************/ +/* Unix Large Files support (>4GB) */ +#define _FILE_OFFSET_BITS 64 +#if (defined(__sun__) && (!defined(__LP64__))) /* Sun Solaris 32-bits requires specific definitions */ +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE +# endif +#elif ! defined(__LP64__) /* No point defining Large file for 64 bit */ +# ifndef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE +# endif +#endif + + +/*-************************************* +* Dependencies +***************************************/ +#include /* malloc, free */ +#include /* memset */ +#include /* fprintf, fopen, ftello64 */ +#include /* clock */ + +#ifndef ZDICT_STATIC_LINKING_ONLY +# define ZDICT_STATIC_LINKING_ONLY +#endif + +#include "../common/mem.h" /* read */ +#include "../common/fse.h" /* FSE_normalizeCount, FSE_writeNCount */ +#include "../common/huf.h" /* HUF_buildCTable, HUF_writeCTable */ +#include "../common/zstd_internal.h" /* includes zstd.h */ +#include "../common/xxhash.h" /* XXH64 */ +#include "../compress/zstd_compress_internal.h" /* ZSTD_loadCEntropy() */ +#include "../zdict.h" +#include "divsufsort.h" +#include "../common/bits.h" /* ZSTD_NbCommonBytes */ + + +/*-************************************* +* Constants +***************************************/ +#define KB *(1 <<10) +#define MB *(1 <<20) +#define GB *(1U<<30) + +#define DICTLISTSIZE_DEFAULT 10000 + +#define NOISELENGTH 32 + +static const U32 g_selectivity_default = 9; + + +/*-************************************* +* Console display +***************************************/ +#undef DISPLAY +#define DISPLAY(...) do { fprintf(stderr, __VA_ARGS__); fflush( stderr ); } while (0) +#undef DISPLAYLEVEL +#define DISPLAYLEVEL(l, ...) do { if (notificationLevel>=l) { DISPLAY(__VA_ARGS__); } } while (0) /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */ + +static clock_t ZDICT_clockSpan(clock_t nPrevious) { return clock() - nPrevious; } + +static void ZDICT_printHex(const void* ptr, size_t length) +{ + const BYTE* const b = (const BYTE*)ptr; + size_t u; + for (u=0; u126) c = '.'; /* non-printable char */ + DISPLAY("%c", c); + } +} + + +/*-******************************************************** +* Helper functions +**********************************************************/ +unsigned ZDICT_isError(size_t errorCode) { return ERR_isError(errorCode); } + +const char* ZDICT_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); } + +unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize) +{ + if (dictSize < 8) return 0; + if (MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return 0; + return MEM_readLE32((const char*)dictBuffer + 4); +} + +size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize) +{ + size_t headerSize; + if (dictSize <= 8 || MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return ERROR(dictionary_corrupted); + + { ZSTD_compressedBlockState_t* bs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t)); + U32* wksp = (U32*)malloc(HUF_WORKSPACE_SIZE); + if (!bs || !wksp) { + headerSize = ERROR(memory_allocation); + } else { + ZSTD_reset_compressedBlockState(bs); + headerSize = ZSTD_loadCEntropy(bs, wksp, dictBuffer, dictSize); + } + + free(bs); + free(wksp); + } + + return headerSize; +} + +/*-******************************************************** +* Dictionary training functions +**********************************************************/ +/*! ZDICT_count() : + Count the nb of common bytes between 2 pointers. + Note : this function presumes end of buffer followed by noisy guard band. +*/ +static size_t ZDICT_count(const void* pIn, const void* pMatch) +{ + const char* const pStart = (const char*)pIn; + for (;;) { + size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn); + if (!diff) { + pIn = (const char*)pIn+sizeof(size_t); + pMatch = (const char*)pMatch+sizeof(size_t); + continue; + } + pIn = (const char*)pIn+ZSTD_NbCommonBytes(diff); + return (size_t)((const char*)pIn - pStart); + } +} + + +typedef struct { + U32 pos; + U32 length; + U32 savings; +} dictItem; + +static void ZDICT_initDictItem(dictItem* d) +{ + d->pos = 1; + d->length = 0; + d->savings = (U32)(-1); +} + + +#define LLIMIT 64 /* heuristic determined experimentally */ +#define MINMATCHLENGTH 7 /* heuristic determined experimentally */ +static dictItem ZDICT_analyzePos( + BYTE* doneMarks, + const int* suffix, U32 start, + const void* buffer, U32 minRatio, U32 notificationLevel) +{ + U32 lengthList[LLIMIT] = {0}; + U32 cumulLength[LLIMIT] = {0}; + U32 savings[LLIMIT] = {0}; + const BYTE* b = (const BYTE*)buffer; + size_t maxLength = LLIMIT; + size_t pos = (size_t)suffix[start]; + U32 end = start; + dictItem solution; + + /* init */ + memset(&solution, 0, sizeof(solution)); + doneMarks[pos] = 1; + + /* trivial repetition cases */ + if ( (MEM_read16(b+pos+0) == MEM_read16(b+pos+2)) + ||(MEM_read16(b+pos+1) == MEM_read16(b+pos+3)) + ||(MEM_read16(b+pos+2) == MEM_read16(b+pos+4)) ) { + /* skip and mark segment */ + U16 const pattern16 = MEM_read16(b+pos+4); + U32 u, patternEnd = 6; + while (MEM_read16(b+pos+patternEnd) == pattern16) patternEnd+=2 ; + if (b[pos+patternEnd] == b[pos+patternEnd-1]) patternEnd++; + for (u=1; u= MINMATCHLENGTH); + } + + /* look backward */ + { size_t length; + do { + length = ZDICT_count(b + pos, b + *(suffix+start-1)); + if (length >=MINMATCHLENGTH) start--; + } while(length >= MINMATCHLENGTH); + } + + /* exit if not found a minimum nb of repetitions */ + if (end-start < minRatio) { + U32 idx; + for(idx=start; idx= %i at pos %7u ", (unsigned)(end-start), MINMATCHLENGTH, (unsigned)pos); + DISPLAYLEVEL(4, "\n"); + + for (mml = MINMATCHLENGTH ; ; mml++) { + BYTE currentChar = 0; + U32 currentCount = 0; + U32 currentID = refinedStart; + U32 id; + U32 selectedCount = 0; + U32 selectedID = currentID; + for (id =refinedStart; id < refinedEnd; id++) { + if (b[suffix[id] + mml] != currentChar) { + if (currentCount > selectedCount) { + selectedCount = currentCount; + selectedID = currentID; + } + currentID = id; + currentChar = b[ suffix[id] + mml]; + currentCount = 0; + } + currentCount ++; + } + if (currentCount > selectedCount) { /* for last */ + selectedCount = currentCount; + selectedID = currentID; + } + + if (selectedCount < minRatio) + break; + refinedStart = selectedID; + refinedEnd = refinedStart + selectedCount; + } + + /* evaluate gain based on new dict */ + start = refinedStart; + pos = suffix[refinedStart]; + end = start; + memset(lengthList, 0, sizeof(lengthList)); + + /* look forward */ + { size_t length; + do { + end++; + length = ZDICT_count(b + pos, b + suffix[end]); + if (length >= LLIMIT) length = LLIMIT-1; + lengthList[length]++; + } while (length >=MINMATCHLENGTH); + } + + /* look backward */ + { size_t length = MINMATCHLENGTH; + while ((length >= MINMATCHLENGTH) & (start > 0)) { + length = ZDICT_count(b + pos, b + suffix[start - 1]); + if (length >= LLIMIT) length = LLIMIT - 1; + lengthList[length]++; + if (length >= MINMATCHLENGTH) start--; + } + } + + /* largest useful length */ + memset(cumulLength, 0, sizeof(cumulLength)); + cumulLength[maxLength-1] = lengthList[maxLength-1]; + for (i=(int)(maxLength-2); i>=0; i--) + cumulLength[i] = cumulLength[i+1] + lengthList[i]; + + for (i=LLIMIT-1; i>=MINMATCHLENGTH; i--) if (cumulLength[i]>=minRatio) break; + maxLength = i; + + /* reduce maxLength in case of final into repetitive data */ + { U32 l = (U32)maxLength; + BYTE const c = b[pos + maxLength-1]; + while (b[pos+l-2]==c) l--; + maxLength = l; + } + if (maxLength < MINMATCHLENGTH) return solution; /* skip : no long-enough solution */ + + /* calculate savings */ + savings[5] = 0; + for (i=MINMATCHLENGTH; i<=(int)maxLength; i++) + savings[i] = savings[i-1] + (lengthList[i] * (i-3)); + + DISPLAYLEVEL(4, "Selected dict at position %u, of length %u : saves %u (ratio: %.2f) \n", + (unsigned)pos, (unsigned)maxLength, (unsigned)savings[maxLength], (double)savings[maxLength] / (double)maxLength); + + solution.pos = (U32)pos; + solution.length = (U32)maxLength; + solution.savings = savings[maxLength]; + + /* mark positions done */ + { U32 id; + for (id=start; id solution.length) length = solution.length; + } + pEnd = (U32)(testedPos + length); + for (p=testedPos; ppos; + const U32 eltEnd = elt.pos + elt.length; + const char* const buf = (const char*) buffer; + + /* tail overlap */ + U32 u; for (u=1; u elt.pos) && (table[u].pos <= eltEnd)) { /* overlap, existing > new */ + /* append */ + U32 const addedLength = table[u].pos - elt.pos; + table[u].length += addedLength; + table[u].pos = elt.pos; + table[u].savings += elt.savings * addedLength / elt.length; /* rough approx */ + table[u].savings += elt.length / 8; /* rough approx bonus */ + elt = table[u]; + /* sort : improve rank */ + while ((u>1) && (table[u-1].savings < elt.savings)) + table[u] = table[u-1], u--; + table[u] = elt; + return u; + } } + + /* front overlap */ + for (u=1; u= elt.pos) && (table[u].pos < elt.pos)) { /* overlap, existing < new */ + /* append */ + int const addedLength = (int)eltEnd - (int)(table[u].pos + table[u].length); + table[u].savings += elt.length / 8; /* rough approx bonus */ + if (addedLength > 0) { /* otherwise, elt fully included into existing */ + table[u].length += addedLength; + table[u].savings += elt.savings * addedLength / elt.length; /* rough approx */ + } + /* sort : improve rank */ + elt = table[u]; + while ((u>1) && (table[u-1].savings < elt.savings)) + table[u] = table[u-1], u--; + table[u] = elt; + return u; + } + + if (MEM_read64(buf + table[u].pos) == MEM_read64(buf + elt.pos + 1)) { + if (isIncluded(buf + table[u].pos, buf + elt.pos + 1, table[u].length)) { + size_t const addedLength = MAX( (int)elt.length - (int)table[u].length , 1 ); + table[u].pos = elt.pos; + table[u].savings += (U32)(elt.savings * addedLength / elt.length); + table[u].length = MIN(elt.length, table[u].length + 1); + return u; + } + } + } + + return 0; +} + + +static void ZDICT_removeDictItem(dictItem* table, U32 id) +{ + /* convention : table[0].pos stores nb of elts */ + U32 const max = table[0].pos; + U32 u; + if (!id) return; /* protection, should never happen */ + for (u=id; upos--; +} + + +static void ZDICT_insertDictItem(dictItem* table, U32 maxSize, dictItem elt, const void* buffer) +{ + /* merge if possible */ + U32 mergeId = ZDICT_tryMerge(table, elt, 0, buffer); + if (mergeId) { + U32 newMerge = 1; + while (newMerge) { + newMerge = ZDICT_tryMerge(table, table[mergeId], mergeId, buffer); + if (newMerge) ZDICT_removeDictItem(table, mergeId); + mergeId = newMerge; + } + return; + } + + /* insert */ + { U32 current; + U32 nextElt = table->pos; + if (nextElt >= maxSize) nextElt = maxSize-1; + current = nextElt-1; + while (table[current].savings < elt.savings) { + table[current+1] = table[current]; + current--; + } + table[current+1] = elt; + table->pos = nextElt+1; + } +} + + +static U32 ZDICT_dictSize(const dictItem* dictList) +{ + U32 u, dictSize = 0; + for (u=1; u=l) { \ + if (ZDICT_clockSpan(displayClock) > refreshRate) { \ + displayClock = clock(); \ + DISPLAY(__VA_ARGS__); \ + } \ + if (notificationLevel>=4) fflush(stderr); \ + } \ + } while (0) + + /* init */ + DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */ + if (!suffix0 || !reverseSuffix || !doneMarks || !filePos) { + result = ERROR(memory_allocation); + goto _cleanup; + } + if (minRatio < MINRATIO) minRatio = MINRATIO; + memset(doneMarks, 0, bufferSize+16); + + /* limit sample set size (divsufsort limitation)*/ + if (bufferSize > ZDICT_MAX_SAMPLES_SIZE) DISPLAYLEVEL(3, "sample set too large : reduced to %u MB ...\n", (unsigned)(ZDICT_MAX_SAMPLES_SIZE>>20)); + while (bufferSize > ZDICT_MAX_SAMPLES_SIZE) bufferSize -= fileSizes[--nbFiles]; + + /* sort */ + DISPLAYLEVEL(2, "sorting %u files of total size %u MB ...\n", nbFiles, (unsigned)(bufferSize>>20)); + { int const divSuftSortResult = divsufsort((const unsigned char*)buffer, suffix, (int)bufferSize, 0); + if (divSuftSortResult != 0) { result = ERROR(GENERIC); goto _cleanup; } + } + suffix[bufferSize] = (int)bufferSize; /* leads into noise */ + suffix0[0] = (int)bufferSize; /* leads into noise */ + /* build reverse suffix sort */ + { size_t pos; + for (pos=0; pos < bufferSize; pos++) + reverseSuffix[suffix[pos]] = (U32)pos; + /* note filePos tracks borders between samples. + It's not used at this stage, but planned to become useful in a later update */ + filePos[0] = 0; + for (pos=1; pos> 21); + } +} + + +typedef struct +{ + ZSTD_CDict* dict; /* dictionary */ + ZSTD_CCtx* zc; /* working context */ + void* workPlace; /* must be ZSTD_BLOCKSIZE_MAX allocated */ +} EStats_ress_t; + +#define MAXREPOFFSET 1024 + +static void ZDICT_countEStats(EStats_ress_t esr, const ZSTD_parameters* params, + unsigned* countLit, unsigned* offsetcodeCount, unsigned* matchlengthCount, unsigned* litlengthCount, U32* repOffsets, + const void* src, size_t srcSize, + U32 notificationLevel) +{ + size_t const blockSizeMax = MIN (ZSTD_BLOCKSIZE_MAX, 1 << params->cParams.windowLog); + size_t cSize; + + if (srcSize > blockSizeMax) srcSize = blockSizeMax; /* protection vs large samples */ + { size_t const errorCode = ZSTD_compressBegin_usingCDict_deprecated(esr.zc, esr.dict); + if (ZSTD_isError(errorCode)) { DISPLAYLEVEL(1, "warning : ZSTD_compressBegin_usingCDict failed \n"); return; } + + } + cSize = ZSTD_compressBlock_deprecated(esr.zc, esr.workPlace, ZSTD_BLOCKSIZE_MAX, src, srcSize); + if (ZSTD_isError(cSize)) { DISPLAYLEVEL(3, "warning : could not compress sample size %u \n", (unsigned)srcSize); return; } + + if (cSize) { /* if == 0; block is not compressible */ + const seqStore_t* const seqStorePtr = ZSTD_getSeqStore(esr.zc); + + /* literals stats */ + { const BYTE* bytePtr; + for(bytePtr = seqStorePtr->litStart; bytePtr < seqStorePtr->lit; bytePtr++) + countLit[*bytePtr]++; + } + + /* seqStats */ + { U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); + ZSTD_seqToCodes(seqStorePtr); + + { const BYTE* codePtr = seqStorePtr->ofCode; + U32 u; + for (u=0; umlCode; + U32 u; + for (u=0; ullCode; + U32 u; + for (u=0; u= 2) { /* rep offsets */ + const seqDef* const seq = seqStorePtr->sequencesStart; + U32 offset1 = seq[0].offBase - ZSTD_REP_NUM; + U32 offset2 = seq[1].offBase - ZSTD_REP_NUM; + if (offset1 >= MAXREPOFFSET) offset1 = 0; + if (offset2 >= MAXREPOFFSET) offset2 = 0; + repOffsets[offset1] += 3; + repOffsets[offset2] += 1; + } } } +} + +static size_t ZDICT_totalSampleSize(const size_t* fileSizes, unsigned nbFiles) +{ + size_t total=0; + unsigned u; + for (u=0; u0; u--) { + offsetCount_t tmp; + if (table[u-1].count >= table[u].count) break; + tmp = table[u-1]; + table[u-1] = table[u]; + table[u] = tmp; + } +} + +/* ZDICT_flatLit() : + * rewrite `countLit` to contain a mostly flat but still compressible distribution of literals. + * necessary to avoid generating a non-compressible distribution that HUF_writeCTable() cannot encode. + */ +static void ZDICT_flatLit(unsigned* countLit) +{ + int u; + for (u=1; u<256; u++) countLit[u] = 2; + countLit[0] = 4; + countLit[253] = 1; + countLit[254] = 1; +} + +#define OFFCODE_MAX 30 /* only applicable to first block */ +static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize, + int compressionLevel, + const void* srcBuffer, const size_t* fileSizes, unsigned nbFiles, + const void* dictBuffer, size_t dictBufferSize, + unsigned notificationLevel) +{ + unsigned countLit[256]; + HUF_CREATE_STATIC_CTABLE(hufTable, 255); + unsigned offcodeCount[OFFCODE_MAX+1]; + short offcodeNCount[OFFCODE_MAX+1]; + U32 offcodeMax = ZSTD_highbit32((U32)(dictBufferSize + 128 KB)); + unsigned matchLengthCount[MaxML+1]; + short matchLengthNCount[MaxML+1]; + unsigned litLengthCount[MaxLL+1]; + short litLengthNCount[MaxLL+1]; + U32 repOffset[MAXREPOFFSET]; + offsetCount_t bestRepOffset[ZSTD_REP_NUM+1]; + EStats_ress_t esr = { NULL, NULL, NULL }; + ZSTD_parameters params; + U32 u, huffLog = 11, Offlog = OffFSELog, mlLog = MLFSELog, llLog = LLFSELog, total; + size_t pos = 0, errorCode; + size_t eSize = 0; + size_t const totalSrcSize = ZDICT_totalSampleSize(fileSizes, nbFiles); + size_t const averageSampleSize = totalSrcSize / (nbFiles + !nbFiles); + BYTE* dstPtr = (BYTE*)dstBuffer; + U32 wksp[HUF_CTABLE_WORKSPACE_SIZE_U32]; + + /* init */ + DEBUGLOG(4, "ZDICT_analyzeEntropy"); + if (offcodeMax>OFFCODE_MAX) { eSize = ERROR(dictionaryCreation_failed); goto _cleanup; } /* too large dictionary */ + for (u=0; u<256; u++) countLit[u] = 1; /* any character must be described */ + for (u=0; u<=offcodeMax; u++) offcodeCount[u] = 1; + for (u=0; u<=MaxML; u++) matchLengthCount[u] = 1; + for (u=0; u<=MaxLL; u++) litLengthCount[u] = 1; + memset(repOffset, 0, sizeof(repOffset)); + repOffset[1] = repOffset[4] = repOffset[8] = 1; + memset(bestRepOffset, 0, sizeof(bestRepOffset)); + if (compressionLevel==0) compressionLevel = ZSTD_CLEVEL_DEFAULT; + params = ZSTD_getParams(compressionLevel, averageSampleSize, dictBufferSize); + + esr.dict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent, params.cParams, ZSTD_defaultCMem); + esr.zc = ZSTD_createCCtx(); + esr.workPlace = malloc(ZSTD_BLOCKSIZE_MAX); + if (!esr.dict || !esr.zc || !esr.workPlace) { + eSize = ERROR(memory_allocation); + DISPLAYLEVEL(1, "Not enough memory \n"); + goto _cleanup; + } + + /* collect stats on all samples */ + for (u=0; u= 4) { + /* writeStats */ + DISPLAYLEVEL(4, "Offset Code Frequencies : \n"); + for (u=0; u<=offcodeMax; u++) { + DISPLAYLEVEL(4, "%2u :%7u \n", u, offcodeCount[u]); + } } + + /* analyze, build stats, starting with literals */ + { size_t maxNbBits = HUF_buildCTable_wksp(hufTable, countLit, 255, huffLog, wksp, sizeof(wksp)); + if (HUF_isError(maxNbBits)) { + eSize = maxNbBits; + DISPLAYLEVEL(1, " HUF_buildCTable error \n"); + goto _cleanup; + } + if (maxNbBits==8) { /* not compressible : will fail on HUF_writeCTable() */ + DISPLAYLEVEL(2, "warning : pathological dataset : literals are not compressible : samples are noisy or too regular \n"); + ZDICT_flatLit(countLit); /* replace distribution by a fake "mostly flat but still compressible" distribution, that HUF_writeCTable() can encode */ + maxNbBits = HUF_buildCTable_wksp(hufTable, countLit, 255, huffLog, wksp, sizeof(wksp)); + assert(maxNbBits==9); + } + huffLog = (U32)maxNbBits; + } + + /* looking for most common first offsets */ + { U32 offset; + for (offset=1; offset dictBufferCapacity) { + dictContentSize = dictBufferCapacity - hSize; + } + + /* Pad the dictionary content with zeros if it is too small */ + if (dictContentSize < minContentSize) { + RETURN_ERROR_IF(hSize + minContentSize > dictBufferCapacity, dstSize_tooSmall, + "dictBufferCapacity too small to fit max repcode"); + paddingSize = minContentSize - dictContentSize; + } else { + paddingSize = 0; + } + + { + size_t const dictSize = hSize + paddingSize + dictContentSize; + + /* The dictionary consists of the header, optional padding, and the content. + * The padding comes before the content because the "best" position in the + * dictionary is the last byte. + */ + BYTE* const outDictHeader = (BYTE*)dictBuffer; + BYTE* const outDictPadding = outDictHeader + hSize; + BYTE* const outDictContent = outDictPadding + paddingSize; + + assert(dictSize <= dictBufferCapacity); + assert(outDictContent + dictContentSize == (BYTE*)dictBuffer + dictSize); + + /* First copy the customDictContent into its final location. + * `customDictContent` and `dictBuffer` may overlap, so we must + * do this before any other writes into the output buffer. + * Then copy the header & padding into the output buffer. + */ + memmove(outDictContent, customDictContent, dictContentSize); + memcpy(outDictHeader, header, hSize); + memset(outDictPadding, 0, paddingSize); + + return dictSize; + } +} + + +static size_t ZDICT_addEntropyTablesFromBuffer_advanced( + void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, + ZDICT_params_t params) +{ + int const compressionLevel = (params.compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : params.compressionLevel; + U32 const notificationLevel = params.notificationLevel; + size_t hSize = 8; + + /* calculate entropy tables */ + DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */ + DISPLAYLEVEL(2, "statistics ... \n"); + { size_t const eSize = ZDICT_analyzeEntropy((char*)dictBuffer+hSize, dictBufferCapacity-hSize, + compressionLevel, + samplesBuffer, samplesSizes, nbSamples, + (char*)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize, + notificationLevel); + if (ZDICT_isError(eSize)) return eSize; + hSize += eSize; + } + + /* add dictionary header (after entropy tables) */ + MEM_writeLE32(dictBuffer, ZSTD_MAGIC_DICTIONARY); + { U64 const randomID = XXH64((char*)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize, 0); + U32 const compliantID = (randomID % ((1U<<31)-32768)) + 32768; + U32 const dictID = params.dictID ? params.dictID : compliantID; + MEM_writeLE32((char*)dictBuffer+4, dictID); + } + + if (hSize + dictContentSize < dictBufferCapacity) + memmove((char*)dictBuffer + hSize, (char*)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize); + return MIN(dictBufferCapacity, hSize+dictContentSize); +} + +/*! ZDICT_trainFromBuffer_unsafe_legacy() : +* Warning : `samplesBuffer` must be followed by noisy guard band !!! +* @return : size of dictionary, or an error code which can be tested with ZDICT_isError() +*/ +static size_t ZDICT_trainFromBuffer_unsafe_legacy( + void* dictBuffer, size_t maxDictSize, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, + ZDICT_legacy_params_t params) +{ + U32 const dictListSize = MAX(MAX(DICTLISTSIZE_DEFAULT, nbSamples), (U32)(maxDictSize/16)); + dictItem* const dictList = (dictItem*)malloc(dictListSize * sizeof(*dictList)); + unsigned const selectivity = params.selectivityLevel == 0 ? g_selectivity_default : params.selectivityLevel; + unsigned const minRep = (selectivity > 30) ? MINRATIO : nbSamples >> selectivity; + size_t const targetDictSize = maxDictSize; + size_t const samplesBuffSize = ZDICT_totalSampleSize(samplesSizes, nbSamples); + size_t dictSize = 0; + U32 const notificationLevel = params.zParams.notificationLevel; + + /* checks */ + if (!dictList) return ERROR(memory_allocation); + if (maxDictSize < ZDICT_DICTSIZE_MIN) { free(dictList); return ERROR(dstSize_tooSmall); } /* requested dictionary size is too small */ + if (samplesBuffSize < ZDICT_MIN_SAMPLES_SIZE) { free(dictList); return ERROR(dictionaryCreation_failed); } /* not enough source to create dictionary */ + + /* init */ + ZDICT_initDictItem(dictList); + + /* build dictionary */ + ZDICT_trainBuffer_legacy(dictList, dictListSize, + samplesBuffer, samplesBuffSize, + samplesSizes, nbSamples, + minRep, notificationLevel); + + /* display best matches */ + if (params.zParams.notificationLevel>= 3) { + unsigned const nb = MIN(25, dictList[0].pos); + unsigned const dictContentSize = ZDICT_dictSize(dictList); + unsigned u; + DISPLAYLEVEL(3, "\n %u segments found, of total size %u \n", (unsigned)dictList[0].pos-1, dictContentSize); + DISPLAYLEVEL(3, "list %u best segments \n", nb-1); + for (u=1; u samplesBuffSize) || ((pos + length) > samplesBuffSize)) { + free(dictList); + return ERROR(GENERIC); /* should never happen */ + } + DISPLAYLEVEL(3, "%3u:%3u bytes at pos %8u, savings %7u bytes |", + u, length, pos, (unsigned)dictList[u].savings); + ZDICT_printHex((const char*)samplesBuffer+pos, printedLength); + DISPLAYLEVEL(3, "| \n"); + } } + + + /* create dictionary */ + { unsigned dictContentSize = ZDICT_dictSize(dictList); + if (dictContentSize < ZDICT_CONTENTSIZE_MIN) { free(dictList); return ERROR(dictionaryCreation_failed); } /* dictionary content too small */ + if (dictContentSize < targetDictSize/4) { + DISPLAYLEVEL(2, "! warning : selected content significantly smaller than requested (%u < %u) \n", dictContentSize, (unsigned)maxDictSize); + if (samplesBuffSize < 10 * targetDictSize) + DISPLAYLEVEL(2, "! consider increasing the number of samples (total size : %u MB)\n", (unsigned)(samplesBuffSize>>20)); + if (minRep > MINRATIO) { + DISPLAYLEVEL(2, "! consider increasing selectivity to produce larger dictionary (-s%u) \n", selectivity+1); + DISPLAYLEVEL(2, "! note : larger dictionaries are not necessarily better, test its efficiency on samples \n"); + } + } + + if ((dictContentSize > targetDictSize*3) && (nbSamples > 2*MINRATIO) && (selectivity>1)) { + unsigned proposedSelectivity = selectivity-1; + while ((nbSamples >> proposedSelectivity) <= MINRATIO) { proposedSelectivity--; } + DISPLAYLEVEL(2, "! note : calculated dictionary significantly larger than requested (%u > %u) \n", dictContentSize, (unsigned)maxDictSize); + DISPLAYLEVEL(2, "! consider increasing dictionary size, or produce denser dictionary (-s%u) \n", proposedSelectivity); + DISPLAYLEVEL(2, "! always test dictionary efficiency on real samples \n"); + } + + /* limit dictionary size */ + { U32 const max = dictList->pos; /* convention : nb of useful elts within dictList */ + U32 currentSize = 0; + U32 n; for (n=1; n targetDictSize) { currentSize -= dictList[n].length; break; } + } + dictList->pos = n; + dictContentSize = currentSize; + } + + /* build dict content */ + { U32 u; + BYTE* ptr = (BYTE*)dictBuffer + maxDictSize; + for (u=1; upos; u++) { + U32 l = dictList[u].length; + ptr -= l; + if (ptr<(BYTE*)dictBuffer) { free(dictList); return ERROR(GENERIC); } /* should not happen */ + memcpy(ptr, (const char*)samplesBuffer+dictList[u].pos, l); + } } + + dictSize = ZDICT_addEntropyTablesFromBuffer_advanced(dictBuffer, dictContentSize, maxDictSize, + samplesBuffer, samplesSizes, nbSamples, + params.zParams); + } + + /* clean up */ + free(dictList); + return dictSize; +} + + +/* ZDICT_trainFromBuffer_legacy() : + * issue : samplesBuffer need to be followed by a noisy guard band. + * work around : duplicate the buffer, and add the noise */ +size_t ZDICT_trainFromBuffer_legacy(void* dictBuffer, size_t dictBufferCapacity, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, + ZDICT_legacy_params_t params) +{ + size_t result; + void* newBuff; + size_t const sBuffSize = ZDICT_totalSampleSize(samplesSizes, nbSamples); + if (sBuffSize < ZDICT_MIN_SAMPLES_SIZE) return 0; /* not enough content => no dictionary */ + + newBuff = malloc(sBuffSize + NOISELENGTH); + if (!newBuff) return ERROR(memory_allocation); + + memcpy(newBuff, samplesBuffer, sBuffSize); + ZDICT_fillNoise((char*)newBuff + sBuffSize, NOISELENGTH); /* guard band, for end of buffer condition */ + + result = + ZDICT_trainFromBuffer_unsafe_legacy(dictBuffer, dictBufferCapacity, newBuff, + samplesSizes, nbSamples, params); + free(newBuff); + return result; +} + + +size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples) +{ + ZDICT_fastCover_params_t params; + DEBUGLOG(3, "ZDICT_trainFromBuffer"); + memset(¶ms, 0, sizeof(params)); + params.d = 8; + params.steps = 4; + /* Use default level since no compression level information is available */ + params.zParams.compressionLevel = ZSTD_CLEVEL_DEFAULT; +#if defined(DEBUGLEVEL) && (DEBUGLEVEL>=1) + params.zParams.notificationLevel = DEBUGLEVEL; +#endif + return ZDICT_optimizeTrainFromBuffer_fastCover(dictBuffer, dictBufferCapacity, + samplesBuffer, samplesSizes, nbSamples, + ¶ms); +} + +size_t ZDICT_addEntropyTablesFromBuffer(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples) +{ + ZDICT_params_t params; + memset(¶ms, 0, sizeof(params)); + return ZDICT_addEntropyTablesFromBuffer_advanced(dictBuffer, dictContentSize, dictBufferCapacity, + samplesBuffer, samplesSizes, nbSamples, + params); +} diff --git a/third_party/zstd/include/zstd.h b/third_party/zstd/include/zstd.h deleted file mode 100644 index ade94c2d5ca..00000000000 --- a/third_party/zstd/include/zstd.h +++ /dev/null @@ -1,1015 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ -#ifndef ZSTD_H_235446 -#define ZSTD_H_235446 - -/* ====== Dependency ======*/ -#include /* INT_MAX */ -#include /* size_t */ - - -/* ===== ZSTDLIB_API : control library symbols visibility ===== */ -#ifndef ZSTDLIB_VISIBILITY -# if defined(__GNUC__) && (__GNUC__ >= 4) -# define ZSTDLIB_VISIBILITY __attribute__ ((visibility ("default"))) -# else -# define ZSTDLIB_VISIBILITY -# endif -#endif -#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) -# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBILITY -#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) -# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ -#else -# define ZSTDLIB_API ZSTDLIB_VISIBILITY -#endif - -namespace duckdb_zstd { - -/******************************************************************************* - Introduction - - zstd, short for Zstandard, is a fast lossless compression algorithm, targeting - real-time compression scenarios at zlib-level and better compression ratios. - The zstd compression library provides in-memory compression and decompression - functions. - - The library supports regular compression levels from 1 up to ZSTD_maxCLevel(), - which is currently 22. Levels >= 20, labeled `--ultra`, should be used with - caution, as they require more memory. The library also offers negative - compression levels, which extend the range of speed vs. ratio preferences. - The lower the level, the faster the speed (at the cost of compression). - - Compression can be done in: - - a single step (described as Simple API) - - a single step, reusing a context (described as Explicit context) - - unbounded multiple steps (described as Streaming compression) - - The compression ratio achievable on small data can be highly improved using - a dictionary. Dictionary compression can be performed in: - - a single step (described as Simple dictionary API) - - a single step, reusing a dictionary (described as Bulk-processing - dictionary API) - - Advanced experimental functions can be accessed using - `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h. - - Advanced experimental APIs should never be used with a dynamically-linked - library. They are not "stable"; their definitions or signatures may change in - the future. Only static linking is allowed. -*******************************************************************************/ - -/*------ Version ------*/ -#define ZSTD_VERSION_MAJOR 1 -#define ZSTD_VERSION_MINOR 4 -#define ZSTD_VERSION_RELEASE 5 - -#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) -ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */ - -#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE -#define ZSTD_QUOTE(str) #str -#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str) -#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION) -ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */ - -/* ************************************* - * Default constant - ***************************************/ -#ifndef ZSTD_CLEVEL_DEFAULT -# define ZSTD_CLEVEL_DEFAULT 3 -#endif - -/* ************************************* - * Constants - ***************************************/ - -/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */ -#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */ -#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */ -#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */ -#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0 - -#define ZSTD_BLOCKSIZELOG_MAX 17 -#define ZSTD_BLOCKSIZE_MAX (1<= `ZSTD_compressBound(srcSize)`. - * @return : compressed size written into `dst` (<= `dstCapacity), - * or an error code if it fails (which can be tested using ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel); - -/*! ZSTD_decompress() : - * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. - * `dstCapacity` is an upper bound of originalSize to regenerate. - * If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data. - * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), - * or an errorCode if it fails (which can be tested using ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, - const void* src, size_t compressedSize); - -/*! ZSTD_getFrameContentSize() : requires v1.3.0+ - * `src` should point to the start of a ZSTD encoded frame. - * `srcSize` must be at least as large as the frame header. - * hint : any size >= `ZSTD_frameHeaderSize_max` is large enough. - * @return : - decompressed size of `src` frame content, if known - * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined - * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) - * note 1 : a 0 return value means the frame is valid but "empty". - * note 2 : decompressed size is an optional field, it may not be present, typically in streaming mode. - * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. - * In which case, it's necessary to use streaming mode to decompress data. - * Optionally, application can rely on some implicit limit, - * as ZSTD_decompress() only needs an upper bound of decompressed size. - * (For example, data could be necessarily cut into blocks <= 16 KB). - * note 3 : decompressed size is always present when compression is completed using single-pass functions, - * such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict(). - * note 4 : decompressed size can be very large (64-bits value), - * potentially larger than what local system can handle as a single memory segment. - * In which case, it's necessary to use streaming mode to decompress data. - * note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified. - * Always ensure return value fits within application's authorized limits. - * Each application can set its own limits. - * note 6 : This function replaces ZSTD_getDecompressedSize() */ -#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) -#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) -ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); - -/*! ZSTD_getDecompressedSize() : - * NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize(). - * Both functions work the same way, but ZSTD_getDecompressedSize() blends - * "empty", "unknown" and "error" results to the same return value (0), - * while ZSTD_getFrameContentSize() gives them separate return values. - * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */ -ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); - -/*! ZSTD_findFrameCompressedSize() : - * `src` should point to the start of a ZSTD frame or skippable frame. - * `srcSize` must be >= first frame size - * @return : the compressed size of the first frame starting at `src`, - * suitable to pass as `srcSize` to `ZSTD_decompress` or similar, - * or an error code if input is invalid */ -ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize); - - -/*====== Helper functions ======*/ -#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */ -ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */ -ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ -ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */ -ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */ -ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */ - - -/*************************************** -* Explicit context -***************************************/ -/*= Compression context - * When compressing many times, - * it is recommended to allocate a context just once, - * and re-use it for each successive compression operation. - * This will make workload friendlier for system's memory. - * Note : re-using context is just a speed / resource optimization. - * It doesn't change the compression ratio, which remains identical. - * Note 2 : In multi-threaded environments, - * use one different context per thread for parallel execution. - */ -typedef struct ZSTD_CCtx_s ZSTD_CCtx; -ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void); -ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); - -/*! ZSTD_compressCCtx() : - * Same as ZSTD_compress(), using an explicit ZSTD_CCtx. - * Important : in order to behave similarly to `ZSTD_compress()`, - * this function compresses at requested compression level, - * __ignoring any other parameter__ . - * If any advanced parameter was set using the advanced API, - * they will all be reset. Only `compressionLevel` remains. - */ -ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel); - -/*= Decompression context - * When decompressing many times, - * it is recommended to allocate a context only once, - * and re-use it for each successive compression operation. - * This will make workload friendlier for system's memory. - * Use one context per thread for parallel execution. */ -typedef struct ZSTD_DCtx_s ZSTD_DCtx; -ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void); -ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); - -/*! ZSTD_decompressDCtx() : - * Same as ZSTD_decompress(), - * requires an allocated ZSTD_DCtx. - * Compatible with sticky parameters. - */ -ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize); - - -/*************************************** -* Advanced compression API -***************************************/ - -/* API design : - * Parameters are pushed one by one into an existing context, - * using ZSTD_CCtx_set*() functions. - * Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame. - * "sticky" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` ! - * __They do not apply to "simple" one-shot variants such as ZSTD_compressCCtx()__ . - * - * It's possible to reset all parameters to "default" using ZSTD_CCtx_reset(). - * - * This API supercedes all other "advanced" API entry points in the experimental section. - * In the future, we expect to remove from experimental API entry points which are redundant with this API. - */ - - -/* Compression strategies, listed from fastest to strongest */ -typedef enum { ZSTD_fast=1, - ZSTD_dfast=2, - ZSTD_greedy=3, - ZSTD_lazy=4, - ZSTD_lazy2=5, - ZSTD_btlazy2=6, - ZSTD_btopt=7, - ZSTD_btultra=8, - ZSTD_btultra2=9 - /* note : new strategies _might_ be added in the future. - Only the order (from fast to strong) is guaranteed */ -} ZSTD_strategy; - - -typedef enum { - - /* compression parameters - * Note: When compressing with a ZSTD_CDict these parameters are superseded - * by the parameters used to construct the ZSTD_CDict. - * See ZSTD_CCtx_refCDict() for more info (superseded-by-cdict). */ - ZSTD_c_compressionLevel=100, /* Set compression parameters according to pre-defined cLevel table. - * Note that exact compression parameters are dynamically determined, - * depending on both compression level and srcSize (when known). - * Default level is ZSTD_CLEVEL_DEFAULT==3. - * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT. - * Note 1 : it's possible to pass a negative compression level. - * Note 2 : setting a level does not automatically set all other compression parameters - * to default. Setting this will however eventually dynamically impact the compression - * parameters which have not been manually set. The manually set - * ones will 'stick'. */ - /* Advanced compression parameters : - * It's possible to pin down compression parameters to some specific values. - * In which case, these values are no longer dynamically selected by the compressor */ - ZSTD_c_windowLog=101, /* Maximum allowed back-reference distance, expressed as power of 2. - * This will set a memory budget for streaming decompression, - * with larger values requiring more memory - * and typically compressing more. - * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX. - * Special: value 0 means "use default windowLog". - * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT - * requires explicitly allowing such size at streaming decompression stage. */ - ZSTD_c_hashLog=102, /* Size of the initial probe table, as a power of 2. - * Resulting memory usage is (1 << (hashLog+2)). - * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX. - * Larger tables improve compression ratio of strategies <= dFast, - * and improve speed of strategies > dFast. - * Special: value 0 means "use default hashLog". */ - ZSTD_c_chainLog=103, /* Size of the multi-probe search table, as a power of 2. - * Resulting memory usage is (1 << (chainLog+2)). - * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX. - * Larger tables result in better and slower compression. - * This parameter is useless for "fast" strategy. - * It's still useful when using "dfast" strategy, - * in which case it defines a secondary probe table. - * Special: value 0 means "use default chainLog". */ - ZSTD_c_searchLog=104, /* Number of search attempts, as a power of 2. - * More attempts result in better and slower compression. - * This parameter is useless for "fast" and "dFast" strategies. - * Special: value 0 means "use default searchLog". */ - ZSTD_c_minMatch=105, /* Minimum size of searched matches. - * Note that Zstandard can still find matches of smaller size, - * it just tweaks its search algorithm to look for this size and larger. - * Larger values increase compression and decompression speed, but decrease ratio. - * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX. - * Note that currently, for all strategies < btopt, effective minimum is 4. - * , for all strategies > fast, effective maximum is 6. - * Special: value 0 means "use default minMatchLength". */ - ZSTD_c_targetLength=106, /* Impact of this field depends on strategy. - * For strategies btopt, btultra & btultra2: - * Length of Match considered "good enough" to stop search. - * Larger values make compression stronger, and slower. - * For strategy fast: - * Distance between match sampling. - * Larger values make compression faster, and weaker. - * Special: value 0 means "use default targetLength". */ - ZSTD_c_strategy=107, /* See ZSTD_strategy enum definition. - * The higher the value of selected strategy, the more complex it is, - * resulting in stronger and slower compression. - * Special: value 0 means "use default strategy". */ - - /* LDM mode parameters */ - ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching. - * This parameter is designed to improve compression ratio - * for large inputs, by finding large matches at long distance. - * It increases memory usage and window size. - * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB - * except when expressly set to a different value. */ - ZSTD_c_ldmHashLog=161, /* Size of the table for long distance matching, as a power of 2. - * Larger values increase memory usage and compression ratio, - * but decrease compression speed. - * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX - * default: windowlog - 7. - * Special: value 0 means "automatically determine hashlog". */ - ZSTD_c_ldmMinMatch=162, /* Minimum match size for long distance matcher. - * Larger/too small values usually decrease compression ratio. - * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX. - * Special: value 0 means "use default value" (default: 64). */ - ZSTD_c_ldmBucketSizeLog=163, /* Log size of each bucket in the LDM hash table for collision resolution. - * Larger values improve collision resolution but decrease compression speed. - * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX. - * Special: value 0 means "use default value" (default: 3). */ - ZSTD_c_ldmHashRateLog=164, /* Frequency of inserting/looking up entries into the LDM hash table. - * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN). - * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage. - * Larger values improve compression speed. - * Deviating far from default value will likely result in a compression ratio decrease. - * Special: value 0 means "automatically determine hashRateLog". */ - - /* frame parameters */ - ZSTD_c_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1) - * Content size must be known at the beginning of compression. - * This is automatically the case when using ZSTD_compress2(), - * For streaming scenarios, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */ - ZSTD_c_checksumFlag=201, /* A 32-bits checksum of content is written at end of frame (default:0) */ - ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */ - - /* multi-threading parameters */ - /* These parameters are only useful if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD). - * They return an error otherwise. */ - ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel. - * When nbWorkers >= 1, triggers asynchronous mode when used with ZSTD_compressStream*() : - * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller, - * while compression work is performed in parallel, within worker threads. - * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end : - * in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call). - * More workers improve speed, but also increase memory usage. - * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */ - ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1. - * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads. - * 0 means default, which is dynamically determined based on compression parameters. - * Job size must be a minimum of overlap size, or 1 MB, whichever is largest. - * The minimum size is automatically and transparently enforced. */ - ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size. - * The overlap size is an amount of data reloaded from previous job at the beginning of a new job. - * It helps preserve compression ratio, while each job is compressed in parallel. - * This value is enforced only when nbWorkers >= 1. - * Larger values increase compression ratio, but decrease speed. - * Possible values range from 0 to 9 : - * - 0 means "default" : value will be determined by the library, depending on strategy - * - 1 means "no overlap" - * - 9 means "full overlap", using a full window size. - * Each intermediate rank increases/decreases load size by a factor 2 : - * 9: full window; 8: w/2; 7: w/4; 6: w/8; 5:w/16; 4: w/32; 3:w/64; 2:w/128; 1:no overlap; 0:default - * default value varies between 6 and 9, depending on strategy */ - - /* note : additional experimental parameters are also available - * within the experimental section of the API. - * At the time of this writing, they include : - * ZSTD_c_rsyncable - * ZSTD_c_format - * ZSTD_c_forceMaxWindow - * ZSTD_c_forceAttachDict - * ZSTD_c_literalCompressionMode - * ZSTD_c_targetCBlockSize - * ZSTD_c_srcSizeHint - * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. - * note : never ever use experimentalParam? names directly; - * also, the enums values themselves are unstable and can still change. - */ - ZSTD_c_experimentalParam1=500, - ZSTD_c_experimentalParam2=10, - ZSTD_c_experimentalParam3=1000, - ZSTD_c_experimentalParam4=1001, - ZSTD_c_experimentalParam5=1002, - ZSTD_c_experimentalParam6=1003, - ZSTD_c_experimentalParam7=1004 -} ZSTD_cParameter; - -typedef struct { - size_t error; - int lowerBound; - int upperBound; -} ZSTD_bounds; - -/*! ZSTD_cParam_getBounds() : - * All parameters must belong to an interval with lower and upper bounds, - * otherwise they will either trigger an error or be automatically clamped. - * @return : a structure, ZSTD_bounds, which contains - * - an error status field, which must be tested using ZSTD_isError() - * - lower and upper bounds, both inclusive - */ -ZSTDLIB_API ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam); - -/*! ZSTD_CCtx_setParameter() : - * Set one compression parameter, selected by enum ZSTD_cParameter. - * All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds(). - * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter). - * Setting a parameter is generally only possible during frame initialization (before starting compression). - * Exception : when using multi-threading mode (nbWorkers >= 1), - * the following parameters can be updated _during_ compression (within same frame): - * => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy. - * new parameters will be active for next job only (after a flush()). - * @return : an error code (which can be tested using ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value); - -/*! ZSTD_CCtx_setPledgedSrcSize() : - * Total input data size to be compressed as a single frame. - * Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag. - * This value will also be controlled at end of frame, and trigger an error if not respected. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame. - * In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN. - * ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame. - * Note 2 : pledgedSrcSize is only valid once, for the next frame. - * It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN. - * Note 3 : Whenever all input data is provided and consumed in a single round, - * for example with ZSTD_compress2(), - * or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end), - * this value is automatically overridden by srcSize instead. - */ -ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize); - -typedef enum { - ZSTD_reset_session_only = 1, - ZSTD_reset_parameters = 2, - ZSTD_reset_session_and_parameters = 3 -} ZSTD_ResetDirective; - -/*! ZSTD_CCtx_reset() : - * There are 2 different things that can be reset, independently or jointly : - * - The session : will stop compressing current frame, and make CCtx ready to start a new one. - * Useful after an error, or to interrupt any ongoing compression. - * Any internal data not yet flushed is cancelled. - * Compression parameters and dictionary remain unchanged. - * They will be used to compress next frame. - * Resetting session never fails. - * - The parameters : changes all parameters back to "default". - * This removes any reference to any dictionary too. - * Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing) - * otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError()) - * - Both : similar to resetting the session, followed by resetting parameters. - */ -ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset); - -/*! ZSTD_compress2() : - * Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API. - * ZSTD_compress2() always starts a new frame. - * Should cctx hold data from a previously unfinished frame, everything about it is forgotten. - * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() - * - The function is always blocking, returns when compression is completed. - * Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`. - * @return : compressed size written into `dst` (<= `dstCapacity), - * or an error code if it fails (which can be tested using ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize); - - -/*************************************** -* Advanced decompression API -***************************************/ - -/* The advanced API pushes parameters one by one into an existing DCtx context. - * Parameters are sticky, and remain valid for all following frames - * using the same DCtx context. - * It's possible to reset parameters to default values using ZSTD_DCtx_reset(). - * Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream(). - * Therefore, no new decompression function is necessary. - */ - -typedef enum { - - ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which - * the streaming API will refuse to allocate memory buffer - * in order to protect the host from unreasonable memory requirements. - * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. - * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT). - * Special: value 0 means "use default maximum windowLog". */ - - /* note : additional experimental parameters are also available - * within the experimental section of the API. - * At the time of this writing, they include : - * ZSTD_d_format - * ZSTD_d_stableOutBuffer - * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. - * note : never ever use experimentalParam? names directly - */ - ZSTD_d_experimentalParam1=1000, - ZSTD_d_experimentalParam2=1001 - -} ZSTD_dParameter; - -/*! ZSTD_dParam_getBounds() : - * All parameters must belong to an interval with lower and upper bounds, - * otherwise they will either trigger an error or be automatically clamped. - * @return : a structure, ZSTD_bounds, which contains - * - an error status field, which must be tested using ZSTD_isError() - * - both lower and upper bounds, inclusive - */ -ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam); - -/*! ZSTD_DCtx_setParameter() : - * Set one compression parameter, selected by enum ZSTD_dParameter. - * All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds(). - * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter). - * Setting a parameter is only possible during frame initialization (before starting decompression). - * @return : 0, or an error code (which can be tested using ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value); - -/*! ZSTD_DCtx_reset() : - * Return a DCtx to clean state. - * Session and parameters can be reset jointly or separately. - * Parameters can only be reset when no active frame is being decompressed. - * @return : 0, or an error code, which can be tested with ZSTD_isError() - */ -ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset); - - -/**************************** -* Streaming -****************************/ - -typedef struct ZSTD_inBuffer_s { - const void* src; /**< start of input buffer */ - size_t size; /**< size of input buffer */ - size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */ -} ZSTD_inBuffer; - -typedef struct ZSTD_outBuffer_s { - void* dst; /**< start of output buffer */ - size_t size; /**< size of output buffer */ - size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ -} ZSTD_outBuffer; - - - -/*-*********************************************************************** -* Streaming compression - HowTo -* -* A ZSTD_CStream object is required to track streaming operation. -* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources. -* ZSTD_CStream objects can be reused multiple times on consecutive compression operations. -* It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory. -* -* For parallel execution, use one separate ZSTD_CStream per thread. -* -* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing. -* -* Parameters are sticky : when starting a new compression on the same context, -* it will re-use the same sticky parameters as previous compression session. -* When in doubt, it's recommended to fully initialize the context before usage. -* Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(), -* ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to -* set more specific parameters, the pledged source size, or load a dictionary. -* -* Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to -* consume input stream. The function will automatically update both `pos` -* fields within `input` and `output`. -* Note that the function may not consume the entire input, for example, because -* the output buffer is already full, in which case `input.pos < input.size`. -* The caller must check if input has been entirely consumed. -* If not, the caller must make some room to receive more compressed data, -* and then present again remaining input data. -* note: ZSTD_e_continue is guaranteed to make some forward progress when called, -* but doesn't guarantee maximal forward progress. This is especially relevant -* when compressing with multiple threads. The call won't block if it can -* consume some input, but if it can't it will wait for some, but not all, -* output to be flushed. -* @return : provides a minimum amount of data remaining to be flushed from internal buffers -* or an error code, which can be tested using ZSTD_isError(). -* -* At any moment, it's possible to flush whatever data might remain stuck within internal buffer, -* using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated. -* Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0). -* In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush. -* You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the -* operation. -* note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will -* block until the flush is complete or the output buffer is full. -* @return : 0 if internal buffers are entirely flushed, -* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), -* or an error code, which can be tested using ZSTD_isError(). -* -* Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame. -* It will perform a flush and write frame epilogue. -* The epilogue is required for decoders to consider a frame completed. -* flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush. -* You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to -* start a new frame. -* note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will -* block until the flush is complete or the output buffer is full. -* @return : 0 if frame fully completed and fully flushed, -* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), -* or an error code, which can be tested using ZSTD_isError(). -* -* *******************************************************************/ - -typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */ - /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */ -/*===== ZSTD_CStream management functions =====*/ -ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void); -ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); - -/*===== Streaming compression functions =====*/ -typedef enum { - ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */ - ZSTD_e_flush=1, /* flush any data provided so far, - * it creates (at least) one new block, that can be decoded immediately on reception; - * frame will continue: any future data can still reference previously compressed data, improving compression. - * note : multithreaded compression will block to flush as much output as possible. */ - ZSTD_e_end=2 /* flush any remaining data _and_ close current frame. - * note that frame is only closed after compressed data is fully flushed (return value == 0). - * After that point, any additional data starts a new frame. - * note : each frame is independent (does not reference any content from previous frame). - : note : multithreaded compression will block to flush as much output as possible. */ -} ZSTD_EndDirective; - -/*! ZSTD_compressStream2() : - * Behaves about the same as ZSTD_compressStream, with additional control on end directive. - * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() - * - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode) - * - output->pos must be <= dstCapacity, input->pos must be <= srcSize - * - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit. - * - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller. - * - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available, - * and then immediately returns, just indicating that there is some data remaining to be flushed. - * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte. - * - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking. - * - @return provides a minimum amount of data remaining to be flushed from internal buffers - * or an error code, which can be tested using ZSTD_isError(). - * if @return != 0, flush is not fully completed, there is still some data left within internal buffers. - * This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers. - * For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed. - * - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0), - * only ZSTD_e_end or ZSTD_e_flush operations are allowed. - * Before starting a new compression job, or changing compression parameters, - * it is required to fully flush internal buffers. - */ -ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, - ZSTD_outBuffer* output, - ZSTD_inBuffer* input, - ZSTD_EndDirective endOp); - - -/* These buffer sizes are softly recommended. - * They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output. - * Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(), - * reducing the amount of memory shuffling and buffering, resulting in minor performance savings. - * - * However, note that these recommendations are from the perspective of a C caller program. - * If the streaming interface is invoked from some other language, - * especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo, - * a major performance rule is to reduce crossing such interface to an absolute minimum. - * It's not rare that performance ends being spent more into the interface, rather than compression itself. - * In which cases, prefer using large buffers, as large as practical, - * for both input and output, to reduce the nb of roundtrips. - */ -ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */ -ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */ - - -/* ***************************************************************************** - * This following is a legacy streaming API. - * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2(). - * It is redundant, but remains fully supported. - * Advanced parameters and dictionary compression can only be used through the - * new API. - ******************************************************************************/ - -/*! - * Equivalent to: - * - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) - * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); - */ -ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel); -/*! - * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue). - * NOTE: The return value is different. ZSTD_compressStream() returns a hint for - * the next read size (if non-zero and not an error). ZSTD_compressStream2() - * returns the minimum nb of bytes left to flush (if non-zero and not an error). - */ -ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input); -/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */ -ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); -/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */ -ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); - - -/*-*************************************************************************** -* Streaming decompression - HowTo -* -* A ZSTD_DStream object is required to track streaming operations. -* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources. -* ZSTD_DStream objects can be re-used multiple times. -* -* Use ZSTD_initDStream() to start a new decompression operation. -* @return : recommended first input size -* Alternatively, use advanced API to set specific properties. -* -* Use ZSTD_decompressStream() repetitively to consume your input. -* The function will update both `pos` fields. -* If `input.pos < input.size`, some input has not been consumed. -* It's up to the caller to present again remaining data. -* The function tries to flush all data decoded immediately, respecting output buffer size. -* If `output.pos < output.size`, decoder has flushed everything it could. -* But if `output.pos == output.size`, there might be some data left within internal buffers., -* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer. -* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX. -* @return : 0 when a frame is completely decoded and fully flushed, -* or an error code, which can be tested using ZSTD_isError(), -* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame : -* the return value is a suggested next input size (just a hint for better latency) -* that will never request more than the remaining frame size. -* *******************************************************************************/ - -typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */ - /* For compatibility with versions <= v1.2.0, prefer differentiating them. */ -/*===== ZSTD_DStream management functions =====*/ -ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void); -ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); - -/*===== Streaming decompression functions =====*/ - -/* This function is redundant with the advanced API and equivalent to: - * - * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); - * ZSTD_DCtx_refDDict(zds, NULL); - */ -ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds); - -ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input); - -ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */ -ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */ - - -/************************** -* Simple dictionary API -***************************/ -/*! ZSTD_compress_usingDict() : - * Compression at an explicit compression level using a Dictionary. - * A dictionary can be any arbitrary data segment (also called a prefix), - * or a buffer with specified information (see dict/zdict.h). - * Note : This function loads the dictionary, resulting in significant startup delay. - * It's intended for a dictionary used only once. - * Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */ -ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize, - int compressionLevel); - -/*! ZSTD_decompress_usingDict() : - * Decompression using a known Dictionary. - * Dictionary must be identical to the one used during compression. - * Note : This function loads the dictionary, resulting in significant startup delay. - * It's intended for a dictionary used only once. - * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */ -ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize); - - -/*********************************** - * Bulk processing dictionary API - **********************************/ -typedef struct ZSTD_CDict_s ZSTD_CDict; - -/*! ZSTD_createCDict() : - * When compressing multiple messages or blocks using the same dictionary, - * it's recommended to digest the dictionary only once, since it's a costly operation. - * ZSTD_createCDict() will create a state from digesting a dictionary. - * The resulting state can be used for future compression operations with very limited startup cost. - * ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. - * @dictBuffer can be released after ZSTD_CDict creation, because its content is copied within CDict. - * Note 1 : Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate @dictBuffer content. - * Note 2 : A ZSTD_CDict can be created from an empty @dictBuffer, - * in which case the only thing that it transports is the @compressionLevel. - * This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively, - * expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. */ -ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, - int compressionLevel); - -/*! ZSTD_freeCDict() : - * Function frees memory allocated by ZSTD_createCDict(). */ -ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict); - -/*! ZSTD_compress_usingCDict() : - * Compression using a digested Dictionary. - * Recommended when same dictionary is used multiple times. - * Note : compression level is _decided at dictionary creation time_, - * and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */ -ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict); - - -typedef struct ZSTD_DDict_s ZSTD_DDict; - -/*! ZSTD_createDDict() : - * Create a digested dictionary, ready to start decompression operation without startup delay. - * dictBuffer can be released after DDict creation, as its content is copied inside DDict. */ -ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize); - -/*! ZSTD_freeDDict() : - * Function frees memory allocated with ZSTD_createDDict() */ -ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict); - -/*! ZSTD_decompress_usingDDict() : - * Decompression using a digested Dictionary. - * Recommended when same dictionary is used multiple times. */ -ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_DDict* ddict); - - -/******************************** - * Dictionary helper functions - *******************************/ - -/*! ZSTD_getDictID_fromDict() : - * Provides the dictID stored within dictionary. - * if @return == 0, the dictionary is not conformant with Zstandard specification. - * It can still be loaded, but as a content-only dictionary. */ -ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize); - -/*! ZSTD_getDictID_fromDDict() : - * Provides the dictID of the dictionary loaded into `ddict`. - * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. - * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ -ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict); - -/*! ZSTD_getDictID_fromFrame() : - * Provides the dictID required to decompressed the frame stored within `src`. - * If @return == 0, the dictID could not be decoded. - * This could for one of the following reasons : - * - The frame does not require a dictionary to be decoded (most common case). - * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information. - * Note : this use case also happens when using a non-conformant dictionary. - * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`). - * - This is not a Zstandard frame. - * When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */ -ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); - - -/******************************************************************************* - * Advanced dictionary and prefix API - * - * This API allows dictionaries to be used with ZSTD_compress2(), - * ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and - * only reset with the context is reset with ZSTD_reset_parameters or - * ZSTD_reset_session_and_parameters. Prefixes are single-use. - ******************************************************************************/ - - -/*! ZSTD_CCtx_loadDictionary() : - * Create an internal CDict from `dict` buffer. - * Decompression will have to use same dictionary. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary, - * meaning "return to no-dictionary mode". - * Note 1 : Dictionary is sticky, it will be used for all future compressed frames. - * To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters). - * Note 2 : Loading a dictionary involves building tables. - * It's also a CPU consuming operation, with non-negligible impact on latency. - * Tables are dependent on compression parameters, and for this reason, - * compression parameters can no longer be changed after loading a dictionary. - * Note 3 :`dict` content will be copied internally. - * Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead. - * In such a case, dictionary buffer must outlive its users. - * Note 4 : Use ZSTD_CCtx_loadDictionary_advanced() - * to precisely select how dictionary content must be interpreted. */ -ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); - -/*! ZSTD_CCtx_refCDict() : - * Reference a prepared dictionary, to be used for all next compressed frames. - * Note that compression parameters are enforced from within CDict, - * and supersede any compression parameter previously set within CCtx. - * The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs. - * The ignored parameters will be used again if the CCtx is returned to no-dictionary mode. - * The dictionary will remain valid for future compressed frames using same CCtx. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Special : Referencing a NULL CDict means "return to no-dictionary mode". - * Note 1 : Currently, only one dictionary can be managed. - * Referencing a new dictionary effectively "discards" any previous one. - * Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */ -ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); - -/*! ZSTD_CCtx_refPrefix() : - * Reference a prefix (single-usage dictionary) for next compressed frame. - * A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end). - * Decompression will need same prefix to properly regenerate data. - * Compressing with a prefix is similar in outcome as performing a diff and compressing it, - * but performs much faster, especially during decompression (compression speed is tunable with compression level). - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary - * Note 1 : Prefix buffer is referenced. It **must** outlive compression. - * Its content must remain unmodified during compression. - * Note 2 : If the intention is to diff some large src data blob with some prior version of itself, - * ensure that the window size is large enough to contain the entire source. - * See ZSTD_c_windowLog. - * Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters. - * It's a CPU consuming operation, with non-negligible impact on latency. - * If there is a need to use the same prefix multiple times, consider loadDictionary instead. - * Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent). - * Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */ -ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, - const void* prefix, size_t prefixSize); - -/*! ZSTD_DCtx_loadDictionary() : - * Create an internal DDict from dict buffer, - * to be used to decompress next frames. - * The dictionary remains valid for all future frames, until explicitly invalidated. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary, - * meaning "return to no-dictionary mode". - * Note 1 : Loading a dictionary involves building tables, - * which has a non-negligible impact on CPU usage and latency. - * It's recommended to "load once, use many times", to amortize the cost - * Note 2 :`dict` content will be copied internally, so `dict` can be released after loading. - * Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead. - * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of - * how dictionary content is loaded and interpreted. - */ -ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); - -/*! ZSTD_DCtx_refDDict() : - * Reference a prepared dictionary, to be used to decompress next frames. - * The dictionary remains active for decompression of future frames using same DCtx. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Note 1 : Currently, only one dictionary can be managed. - * Referencing a new dictionary effectively "discards" any previous one. - * Special: referencing a NULL DDict means "return to no-dictionary mode". - * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx. - */ -ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); - -/*! ZSTD_DCtx_refPrefix() : - * Reference a prefix (single-usage dictionary) to decompress next frame. - * This is the reverse operation of ZSTD_CCtx_refPrefix(), - * and must use the same prefix as the one used during compression. - * Prefix is **only used once**. Reference is discarded at end of frame. - * End of frame is reached when ZSTD_decompressStream() returns 0. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - * Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary - * Note 2 : Prefix buffer is referenced. It **must** outlive decompression. - * Prefix buffer must remain unmodified up to the end of frame, - * reached when ZSTD_decompressStream() returns 0. - * Note 3 : By default, the prefix is treated as raw content (ZSTD_dct_rawContent). - * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section) - * Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost. - * A full dictionary is more costly, as it requires building tables. - */ -ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, - const void* prefix, size_t prefixSize); - -/* === Memory management === */ - -/*! ZSTD_sizeof_*() : - * These functions give the _current_ memory usage of selected object. - * Note that object memory usage can evolve (increase or decrease) over time. */ -ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); -ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx); -ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); -ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds); -ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); -ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); - -} -#endif /* ZSTD_H_235446 */ diff --git a/third_party/zstd/include/zstd/common/allocations.h b/third_party/zstd/include/zstd/common/allocations.h new file mode 100644 index 00000000000..5e899550109 --- /dev/null +++ b/third_party/zstd/include/zstd/common/allocations.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* This file provides custom allocation primitives + */ + +#define ZSTD_DEPS_NEED_MALLOC +#include "zstd_deps.h" /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */ + +#include "compiler.h" /* MEM_STATIC */ +#define ZSTD_STATIC_LINKING_ONLY +#include "../zstd.h" /* ZSTD_customMem */ + +#ifndef ZSTD_ALLOCATIONS_H +#define ZSTD_ALLOCATIONS_H + +/* custom memory allocation functions */ + +MEM_STATIC void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem) +{ + if (customMem.customAlloc) + return customMem.customAlloc(customMem.opaque, size); + return ZSTD_malloc(size); +} + +MEM_STATIC void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem) +{ + if (customMem.customAlloc) { + /* calloc implemented as malloc+memset; + * not as efficient as calloc, but next best guess for custom malloc */ + void* const ptr = customMem.customAlloc(customMem.opaque, size); + ZSTD_memset(ptr, 0, size); + return ptr; + } + return ZSTD_calloc(1, size); +} + +MEM_STATIC void ZSTD_customFree(void* ptr, ZSTD_customMem customMem) +{ + if (ptr!=NULL) { + if (customMem.customFree) + customMem.customFree(customMem.opaque, ptr); + else + ZSTD_free(ptr); + } +} + +#endif /* ZSTD_ALLOCATIONS_H */ diff --git a/third_party/zstd/include/zstd/common/bits.h b/third_party/zstd/include/zstd/common/bits.h new file mode 100644 index 00000000000..def56c474c3 --- /dev/null +++ b/third_party/zstd/include/zstd/common/bits.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_BITS_H +#define ZSTD_BITS_H + +#include "mem.h" + +MEM_STATIC unsigned ZSTD_countTrailingZeros32_fallback(U32 val) +{ + assert(val != 0); + { + static const U32 DeBruijnBytePos[32] = {0, 1, 28, 2, 29, 14, 24, 3, + 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, + 26, 12, 18, 6, 11, 5, 10, 9}; + return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> 27]; + } +} + +MEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val) +{ + assert(val != 0); +# if defined(_MSC_VER) +# if STATIC_BMI2 == 1 + return (unsigned)_tzcnt_u32(val); +# else + if (val != 0) { + unsigned long r; + _BitScanForward(&r, val); + return (unsigned)r; + } else { + /* Should not reach this code path */ + __assume(0); + } +# endif +# elif defined(__GNUC__) && (__GNUC__ >= 4) + return (unsigned)__builtin_ctz(val); +# else + return ZSTD_countTrailingZeros32_fallback(val); +# endif +} + +MEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val) { + assert(val != 0); + { + static const U32 DeBruijnClz[32] = {0, 9, 1, 10, 13, 21, 2, 29, + 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, + 19, 27, 23, 6, 26, 5, 4, 31}; + val |= val >> 1; + val |= val >> 2; + val |= val >> 4; + val |= val >> 8; + val |= val >> 16; + return 31 - DeBruijnClz[(val * 0x07C4ACDDU) >> 27]; + } +} + +MEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val) +{ + assert(val != 0); +# if defined(_MSC_VER) +# if STATIC_BMI2 == 1 + return (unsigned)_lzcnt_u32(val); +# else + if (val != 0) { + unsigned long r; + _BitScanReverse(&r, val); + return (unsigned)(31 - r); + } else { + /* Should not reach this code path */ + __assume(0); + } +# endif +# elif defined(__GNUC__) && (__GNUC__ >= 4) + return (unsigned)__builtin_clz(val); +# else + return ZSTD_countLeadingZeros32_fallback(val); +# endif +} + +MEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val) +{ + assert(val != 0); +# if defined(_MSC_VER) && defined(_WIN64) +# if STATIC_BMI2 == 1 + return (unsigned)_tzcnt_u64(val); +# else + if (val != 0) { + unsigned long r; + _BitScanForward64(&r, val); + return (unsigned)r; + } else { + /* Should not reach this code path */ + __assume(0); + } +# endif +# elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__) + return (unsigned)__builtin_ctzll(val); +# else + { + U32 mostSignificantWord = (U32)(val >> 32); + U32 leastSignificantWord = (U32)val; + if (leastSignificantWord == 0) { + return 32 + ZSTD_countTrailingZeros32(mostSignificantWord); + } else { + return ZSTD_countTrailingZeros32(leastSignificantWord); + } + } +# endif +} + +MEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val) +{ + assert(val != 0); +# if defined(_MSC_VER) && defined(_WIN64) +# if STATIC_BMI2 == 1 + return (unsigned)_lzcnt_u64(val); +# else + if (val != 0) { + unsigned long r; + _BitScanReverse64(&r, val); + return (unsigned)(63 - r); + } else { + /* Should not reach this code path */ + __assume(0); + } +# endif +# elif defined(__GNUC__) && (__GNUC__ >= 4) + return (unsigned)(__builtin_clzll(val)); +# else + { + U32 mostSignificantWord = (U32)(val >> 32); + U32 leastSignificantWord = (U32)val; + if (mostSignificantWord == 0) { + return 32 + ZSTD_countLeadingZeros32(leastSignificantWord); + } else { + return ZSTD_countLeadingZeros32(mostSignificantWord); + } + } +# endif +} + +MEM_STATIC unsigned ZSTD_NbCommonBytes(size_t val) +{ + if (MEM_isLittleEndian()) { + if (MEM_64bits()) { + return ZSTD_countTrailingZeros64((U64)val) >> 3; + } else { + return ZSTD_countTrailingZeros32((U32)val) >> 3; + } + } else { /* Big Endian CPU */ + if (MEM_64bits()) { + return ZSTD_countLeadingZeros64((U64)val) >> 3; + } else { + return ZSTD_countLeadingZeros32((U32)val) >> 3; + } + } +} + +MEM_STATIC unsigned ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */ +{ + assert(val != 0); + return 31 - ZSTD_countLeadingZeros32(val); +} + +/* ZSTD_rotateRight_*(): + * Rotates a bitfield to the right by "count" bits. + * https://en.wikipedia.org/w/index.php?title=Circular_shift&oldid=991635599#Implementing_circular_shifts + */ +MEM_STATIC +U64 ZSTD_rotateRight_U64(U64 const value, U32 count) { + assert(count < 64); + count &= 0x3F; /* for fickle pattern recognition */ + return (value >> count) | (U64)(value << ((0U - count) & 0x3F)); +} + +MEM_STATIC +U32 ZSTD_rotateRight_U32(U32 const value, U32 count) { + assert(count < 32); + count &= 0x1F; /* for fickle pattern recognition */ + return (value >> count) | (U32)(value << ((0U - count) & 0x1F)); +} + +MEM_STATIC +U16 ZSTD_rotateRight_U16(U16 const value, U32 count) { + assert(count < 16); + count &= 0x0F; /* for fickle pattern recognition */ + return (value >> count) | (U16)(value << ((0U - count) & 0x0F)); +} + +#endif /* ZSTD_BITS_H */ diff --git a/third_party/zstd/include/zstd/common/bitstream.h b/third_party/zstd/include/zstd/common/bitstream.h index 65307466685..676044989c9 100644 --- a/third_party/zstd/include/zstd/common/bitstream.h +++ b/third_party/zstd/include/zstd/common/bitstream.h @@ -1,7 +1,7 @@ /* ****************************************************************** * bitstream * Part of FSE library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * You can contact the author at : * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -14,6 +14,9 @@ #ifndef BITSTREAM_H_MODULE #define BITSTREAM_H_MODULE +#if defined (__cplusplus) +extern "C" { +#endif /* * This API consists of small unitary functions, which must be inlined for best performance. * Since link-time-optimization is not available for all compilers, @@ -23,26 +26,28 @@ /*-**************************************** * Dependencies ******************************************/ -#include "zstd/common/mem.h" /* unaligned access routines */ -#include "zstd/common/compiler.h" /* UNLIKELY() */ -#include "zstd/common/debug.h" /* assert(), DEBUGLOG(), RAWLOG() */ -#include "zstd/common/error_private.h" /* error codes and messages */ +#include "mem.h" /* unaligned access routines */ +#include "compiler.h" /* UNLIKELY() */ +#include "debug.h" /* assert(), DEBUGLOG(), RAWLOG() */ +#include "error_private.h" /* error codes and messages */ +#include "bits.h" /* ZSTD_highbit32 */ /*========================================= * Target specific =========================================*/ -#if defined(__BMI__) && defined(__GNUC__) -# include /* support for bextr (experimental) */ -#elif defined(__ICCARM__) -# include +#ifndef ZSTD_NO_INTRINSICS +# if (defined(__BMI__) || defined(__BMI2__)) && defined(__GNUC__) +# include /* support for bextr (experimental)/bzhi */ +# elif defined(__ICCARM__) +# include +# endif #endif #define STREAM_ACCUMULATOR_MIN_32 25 #define STREAM_ACCUMULATOR_MIN_64 57 #define STREAM_ACCUMULATOR_MIN ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64)) -namespace duckdb_zstd { /*-****************************************** * bitStream encoding API (write forward) @@ -85,19 +90,20 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC); /*-******************************************** * bitStream decoding API (read backward) **********************************************/ +typedef size_t BitContainerType; typedef struct { - size_t bitContainer; + BitContainerType bitContainer; unsigned bitsConsumed; const char* ptr; const char* start; const char* limitPtr; } BIT_DStream_t; -typedef enum { BIT_DStream_unfinished = 0, - BIT_DStream_endOfBuffer = 1, - BIT_DStream_completed = 2, - BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */ - /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */ +typedef enum { BIT_DStream_unfinished = 0, /* fully refilled */ + BIT_DStream_endOfBuffer = 1, /* still some bits left in bitstream */ + BIT_DStream_completed = 2, /* bitstream entirely consumed, bit-exact */ + BIT_DStream_overflow = 3 /* user requested more bits than present in bitstream */ + } BIT_DStream_status; /* result of BIT_reloadDStream() */ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize); MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits); @@ -107,7 +113,7 @@ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD); /* Start by invoking BIT_initDStream(). * A chunk of the bitStream is then stored into a local register. -* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t). +* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (BitContainerType). * You can then retrieve bitFields stored into the local register, **in reverse order**. * Local register is explicitly reloaded from memory by the BIT_reloadDStream() method. * A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished. @@ -128,38 +134,6 @@ MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC); MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits); /* faster, but works only if nbBits >= 1 */ - - -/*-************************************************************** -* Internal functions -****************************************************************/ -MEM_STATIC unsigned BIT_highbit32 (U32 val) -{ - assert(val != 0); - { -# if defined(_MSC_VER) /* Visual */ - unsigned long r=0; - return _BitScanReverse ( &r, val ) ? (unsigned)r : 0; -# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ - return __builtin_clz (val) ^ 31; -# elif defined(__ICCARM__) /* IAR Intrinsic */ - return 31 - __CLZ(val); -# else /* Software version */ - static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, - 11, 14, 16, 18, 22, 25, 3, 30, - 8, 12, 20, 28, 15, 17, 24, 7, - 19, 27, 23, 6, 26, 5, 4, 31 }; - U32 v = val; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27]; -# endif - } -} - /*===== Local Constants =====*/ static const unsigned BIT_mask[] = { 0, 1, 3, 7, 0xF, 0x1F, @@ -189,16 +163,26 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, return 0; } +FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) +{ +#if defined(STATIC_BMI2) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS) + return _bzhi_u64(bitContainer, nbBits); +#else + assert(nbBits < BIT_MASK_SIZE); + return bitContainer & BIT_mask[nbBits]; +#endif +} + /*! BIT_addBits() : * can add up to 31 bits into `bitC`. * Note : does not check for register overflow ! */ MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits) { - MEM_STATIC_ASSERT(BIT_MASK_SIZE == 32); + DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32); assert(nbBits < BIT_MASK_SIZE); assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8); - bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos; + bitC->bitContainer |= BIT_getLowerBits(value, nbBits) << bitC->bitPos; bitC->bitPos += nbBits; } @@ -268,7 +252,7 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC) */ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize) { - if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } + if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } bitD->start = (const char*)srcBuffer; bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer); @@ -277,35 +261,35 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer); bitD->bitContainer = MEM_readLEST(bitD->ptr); { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1]; - bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */ + bitD->bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */ if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ } } else { bitD->ptr = bitD->start; bitD->bitContainer = *(const BYTE*)(bitD->start); switch(srcSize) { - case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16); - /* fall-through */ + case 7: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16); + ZSTD_FALLTHROUGH; - case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24); - /* fall-through */ + case 6: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24); + ZSTD_FALLTHROUGH; - case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32); - /* fall-through */ + case 5: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32); + ZSTD_FALLTHROUGH; - case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; - /* fall-through */ + case 4: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[3]) << 24; + ZSTD_FALLTHROUGH; - case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; - /* fall-through */ + case 3: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[2]) << 16; + ZSTD_FALLTHROUGH; - case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8; - /* fall-through */ + case 2: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[1]) << 8; + ZSTD_FALLTHROUGH; default: break; } { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1]; - bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; + bitD->bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0; if (lastByte == 0) return ERROR(corruption_detected); /* endMark not present */ } bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8; @@ -314,23 +298,26 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si return srcSize; } -MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start) +FORCE_INLINE_TEMPLATE size_t BIT_getUpperBits(BitContainerType bitContainer, U32 const start) { return bitContainer >> start; } -MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) +FORCE_INLINE_TEMPLATE size_t BIT_getMiddleBits(BitContainerType bitContainer, U32 const start, U32 const nbBits) { U32 const regMask = sizeof(bitContainer)*8 - 1; /* if start > regMask, bitstream is corrupted, and result is undefined */ assert(nbBits < BIT_MASK_SIZE); + /* x86 transform & ((1 << nbBits) - 1) to bzhi instruction, it is better + * than accessing memory. When bmi2 instruction is not present, we consider + * such cpus old (pre-Haswell, 2013) and their performance is not of that + * importance. + */ +#if defined(__x86_64__) || defined(_M_X86) + return (bitContainer >> (start & regMask)) & ((((U64)1) << nbBits) - 1); +#else return (bitContainer >> (start & regMask)) & BIT_mask[nbBits]; -} - -MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) -{ - assert(nbBits < BIT_MASK_SIZE); - return bitContainer & BIT_mask[nbBits]; +#endif } /*! BIT_lookBits() : @@ -339,7 +326,7 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) * On 32-bits, maxNbBits==24. * On 64-bits, maxNbBits==56. * @return : value extracted */ -MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) +FORCE_INLINE_TEMPLATE size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) { /* arbitrate between double-shift and shift+mask */ #if 1 @@ -362,7 +349,7 @@ MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits) return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask); } -MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) +FORCE_INLINE_TEMPLATE void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) { bitD->bitsConsumed += nbBits; } @@ -371,7 +358,7 @@ MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) * Read (consume) next n bits from local register and update. * Pay attention to not read more than nbBits contained into local register. * @return : extracted value. */ -MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) +FORCE_INLINE_TEMPLATE size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) { size_t const value = BIT_lookBits(bitD, nbBits); BIT_skipBits(bitD, nbBits); @@ -379,7 +366,7 @@ MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) } /*! BIT_readBitsFast() : - * unsafe version; only works only if nbBits >= 1 */ + * unsafe version; only works if nbBits >= 1 */ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits) { size_t const value = BIT_lookBitsFast(bitD, nbBits); @@ -388,6 +375,21 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits) return value; } +/*! BIT_reloadDStream_internal() : + * Simple variant of BIT_reloadDStream(), with two conditions: + * 1. bitstream is valid : bitsConsumed <= sizeof(bitD->bitContainer)*8 + * 2. look window is valid after shifted down : bitD->ptr >= bitD->start + */ +MEM_STATIC BIT_DStream_status BIT_reloadDStream_internal(BIT_DStream_t* bitD) +{ + assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8); + bitD->ptr -= bitD->bitsConsumed >> 3; + assert(bitD->ptr >= bitD->start); + bitD->bitsConsumed &= 7; + bitD->bitContainer = MEM_readLEST(bitD->ptr); + return BIT_DStream_unfinished; +} + /*! BIT_reloadDStreamFast() : * Similar to BIT_reloadDStream(), but with two differences: * 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold! @@ -398,31 +400,35 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD) { if (UNLIKELY(bitD->ptr < bitD->limitPtr)) return BIT_DStream_overflow; - assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8); - bitD->ptr -= bitD->bitsConsumed >> 3; - bitD->bitsConsumed &= 7; - bitD->bitContainer = MEM_readLEST(bitD->ptr); - return BIT_DStream_unfinished; + return BIT_reloadDStream_internal(bitD); } /*! BIT_reloadDStream() : * Refill `bitD` from buffer previously set in BIT_initDStream() . - * This function is safe, it guarantees it will not read beyond src buffer. + * This function is safe, it guarantees it will not never beyond src buffer. * @return : status of `BIT_DStream_t` internal register. * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */ -MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD) +FORCE_INLINE_TEMPLATE BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD) { - if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */ + /* note : once in overflow mode, a bitstream remains in this mode until it's reset */ + if (UNLIKELY(bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))) { + static const BitContainerType zeroFilled = 0; + bitD->ptr = (const char*)&zeroFilled; /* aliasing is allowed for char */ + /* overflow detected, erroneous scenario or end of stream: no update */ return BIT_DStream_overflow; + } + + assert(bitD->ptr >= bitD->start); if (bitD->ptr >= bitD->limitPtr) { - return BIT_reloadDStreamFast(bitD); + return BIT_reloadDStream_internal(bitD); } if (bitD->ptr == bitD->start) { + /* reached end of bitStream => no update */ if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer; return BIT_DStream_completed; } - /* start < ptr < limitPtr */ + /* start < ptr < limitPtr => cautious update */ { U32 nbBytes = bitD->bitsConsumed >> 3; BIT_DStream_status result = BIT_DStream_unfinished; if (bitD->ptr - nbBytes < bitD->start) { @@ -444,6 +450,8 @@ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream) return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8)); } +#if defined (__cplusplus) } +#endif #endif /* BITSTREAM_H_MODULE */ diff --git a/third_party/zstd/include/zstd/common/compiler.h b/third_party/zstd/include/zstd/common/compiler.h index b94dbad1331..31880ecbe16 100644 --- a/third_party/zstd/include/zstd/common/compiler.h +++ b/third_party/zstd/include/zstd/common/compiler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,6 +11,10 @@ #ifndef ZSTD_COMPILER_H #define ZSTD_COMPILER_H +#include + +#include "portability_macros.h" + /*-******************************************************* * Compiler specifics *********************************************************/ @@ -38,12 +42,30 @@ #endif +/** + On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC). + This explicitly marks such functions as __cdecl so that the code will still compile + if a CC other than __cdecl has been made the default. +*/ +#if defined(_MSC_VER) +# define WIN_CDECL __cdecl +#else +# define WIN_CDECL +#endif + +/* UNUSED_ATTR tells the compiler it is okay if the function is unused. */ +#if defined(__GNUC__) +# define UNUSED_ATTR __attribute__((unused)) +#else +# define UNUSED_ATTR +#endif + /** * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant * parameters. They must be inlined for the compiler to eliminate the constant * branches. */ -#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR +#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR UNUSED_ATTR /** * HINT_INLINE is used to help the compiler generate better code. It is *not* * used for "templates", so it can be tweaked based on the compilers @@ -58,14 +80,28 @@ #if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5 # define HINT_INLINE static INLINE_KEYWORD #else -# define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR +# define HINT_INLINE FORCE_INLINE_TEMPLATE #endif -/* UNUSED_ATTR tells the compiler it is okay if the function is unused. */ +/* "soft" inline : + * The compiler is free to select if it's a good idea to inline or not. + * The main objective is to silence compiler warnings + * when a defined function in included but not used. + * + * Note : this macro is prefixed `MEM_` because it used to be provided by `mem.h` unit. + * Updating the prefix is probably preferable, but requires a fairly large codemod, + * since this name is used everywhere. + */ +#ifndef MEM_STATIC /* already defined in Linux Kernel mem.h */ #if defined(__GNUC__) -# define UNUSED_ATTR __attribute__((unused)) +# define MEM_STATIC static __inline UNUSED_ATTR +#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define MEM_STATIC static inline +#elif defined(_MSC_VER) +# define MEM_STATIC static __inline #else -# define UNUSED_ATTR +# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ +#endif #endif /* force no inlining */ @@ -79,67 +115,58 @@ # endif #endif + /* target attribute */ -#ifndef __has_attribute - #define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ -#endif #if defined(__GNUC__) || defined(__ICCARM__) # define TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) #else # define TARGET_ATTRIBUTE(target) #endif -/* Enable runtime BMI2 dispatch based on the CPU. - * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default. +/* Target attribute for BMI2 dynamic dispatch. + * Enable lzcnt, bmi, and bmi2. + * We test for bmi1 & bmi2. lzcnt is included in bmi1. */ -#ifndef DYNAMIC_BMI2 - #if ((defined(__clang__) && __has_attribute(__target__)) \ - || (defined(__GNUC__) \ - && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \ - && (defined(__x86_64__) || defined(_M_X86)) \ - && !defined(__BMI2__) - # define DYNAMIC_BMI2 1 - #else - # define DYNAMIC_BMI2 0 - #endif -#endif +#define BMI2_TARGET_ATTRIBUTE TARGET_ATTRIBUTE("lzcnt,bmi,bmi2") /* prefetch * can be disabled, by declaring NO_PREFETCH build macro */ #if defined(NO_PREFETCH) -# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ -# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ +# define PREFETCH_L1(ptr) do { (void)(ptr); } while (0) /* disabled */ +# define PREFETCH_L2(ptr) do { (void)(ptr); } while (0) /* disabled */ #else -# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */ +# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && !defined(_M_ARM64EC) /* _mm_prefetch() is not defined outside of x86/x64 */ # include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ # define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) # define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1) -# elif defined(__aarch64__) -# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))) -# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))) # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) # define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) # define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) +# elif defined(__aarch64__) +# define PREFETCH_L1(ptr) do { __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))); } while (0) +# define PREFETCH_L2(ptr) do { __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))); } while (0) # else -# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ -# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ +# define PREFETCH_L1(ptr) do { (void)(ptr); } while (0) /* disabled */ +# define PREFETCH_L2(ptr) do { (void)(ptr); } while (0) /* disabled */ # endif #endif /* NO_PREFETCH */ #define CACHELINE_SIZE 64 -#define PREFETCH_AREA(p, s) { \ - const char* const _ptr = (const char*)(p); \ - size_t const _size = (size_t)(s); \ - size_t _pos; \ - for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \ - PREFETCH_L2(_ptr + _pos); \ - } \ -} +#define PREFETCH_AREA(p, s) \ + do { \ + const char* const _ptr = (const char*)(p); \ + size_t const _size = (size_t)(s); \ + size_t _pos; \ + for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \ + PREFETCH_L2(_ptr + _pos); \ + } \ + } while (0) /* vectorization - * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax */ -#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) + * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax, + * and some compilers, like Intel ICC and MCST LCC, do not support it at all. */ +#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) && !defined(__LCC__) # if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5) # define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) # else @@ -155,19 +182,269 @@ * and clang, please do. */ #if defined(__GNUC__) -#ifndef LIKELY #define LIKELY(x) (__builtin_expect((x), 1)) -#endif -#ifndef UNLIKELY #define UNLIKELY(x) (__builtin_expect((x), 0)) -#endif #else -#ifndef LIKELY #define LIKELY(x) (x) -#endif -#ifndef UNLIKELY #define UNLIKELY(x) (x) #endif + +#if __has_builtin(__builtin_unreachable) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))) +# define ZSTD_UNREACHABLE do { assert(0), __builtin_unreachable(); } while (0) +#else +# define ZSTD_UNREACHABLE do { assert(0); } while (0) +#endif + +/* disable warnings */ +#ifdef _MSC_VER /* Visual Studio */ +# include /* For Visual 2005 */ +# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */ +# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ +# pragma warning(disable : 4324) /* disable: C4324: padded structure */ +#endif + +/*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/ +#ifndef STATIC_BMI2 +# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) +# ifdef __AVX2__ //MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 +# define STATIC_BMI2 1 +# endif +# elif defined(__BMI2__) && defined(__x86_64__) && defined(__GNUC__) +# define STATIC_BMI2 1 +# endif +#endif + +#ifndef STATIC_BMI2 + #define STATIC_BMI2 0 +#endif + +/* compile time determination of SIMD support */ +#if !defined(ZSTD_NO_INTRINSICS) +# if defined(__SSE2__) || defined(_M_AMD64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) +# define ZSTD_ARCH_X86_SSE2 +# endif +# if defined(__ARM_NEON) || defined(_M_ARM64) +# define ZSTD_ARCH_ARM_NEON +# endif +# +# if defined(ZSTD_ARCH_X86_SSE2) +# include +# elif defined(ZSTD_ARCH_ARM_NEON) +# include +# endif +#endif + +/* C-language Attributes are added in C23. */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute) +# define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) +#else +# define ZSTD_HAS_C_ATTRIBUTE(x) 0 +#endif + +/* Only use C++ attributes in C++. Some compilers report support for C++ + * attributes when compiling with C. + */ +#if defined(__cplusplus) && defined(__has_cpp_attribute) +# define ZSTD_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define ZSTD_HAS_CPP_ATTRIBUTE(x) 0 +#endif + +/* Define ZSTD_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute. + * - C23: https://en.cppreference.com/w/c/language/attributes/fallthrough + * - CPP17: https://en.cppreference.com/w/cpp/language/attributes/fallthrough + * - Else: __attribute__((__fallthrough__)) + */ +#ifndef ZSTD_FALLTHROUGH +# if ZSTD_HAS_C_ATTRIBUTE(fallthrough) +# define ZSTD_FALLTHROUGH [[fallthrough]] +# elif ZSTD_HAS_CPP_ATTRIBUTE(fallthrough) +# define ZSTD_FALLTHROUGH [[fallthrough]] +# elif __has_attribute(__fallthrough__) +/* Leading semicolon is to satisfy gcc-11 with -pedantic. Without the semicolon + * gcc complains about: a label can only be part of a statement and a declaration is not a statement. + */ +# define ZSTD_FALLTHROUGH ; __attribute__((__fallthrough__)) +# else +# define ZSTD_FALLTHROUGH +# endif +#endif + +/*-************************************************************** +* Alignment check +*****************************************************************/ + +/* this test was initially positioned in mem.h, + * but this file is removed (or replaced) for linux kernel + * so it's now hosted in compiler.h, + * which remains valid for both user & kernel spaces. + */ + +#ifndef ZSTD_ALIGNOF +# if defined(__GNUC__) || defined(_MSC_VER) +/* covers gcc, clang & MSVC */ +/* note : this section must come first, before C11, + * due to a limitation in the kernel source generator */ +# define ZSTD_ALIGNOF(T) __alignof(T) + +# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +/* C11 support */ +# include +# define ZSTD_ALIGNOF(T) alignof(T) + +# else +/* No known support for alignof() - imperfect backup */ +# define ZSTD_ALIGNOF(T) (sizeof(void*) < sizeof(T) ? sizeof(void*) : sizeof(T)) + +# endif +#endif /* ZSTD_ALIGNOF */ + +/*-************************************************************** +* Sanitizer +*****************************************************************/ + +/** + * Zstd relies on pointer overflow in its decompressor. + * We add this attribute to functions that rely on pointer overflow. + */ +#ifndef ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +# if __has_attribute(no_sanitize) +# if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 8 + /* gcc < 8 only has signed-integer-overlow which triggers on pointer overflow */ +# define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize("signed-integer-overflow"))) +# else + /* older versions of clang [3.7, 5.0) will warn that pointer-overflow is ignored. */ +# define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize("pointer-overflow"))) +# endif +# else +# define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +# endif +#endif + +/** + * Helper function to perform a wrapped pointer difference without trigging + * UBSAN. + * + * @returns lhs - rhs with wrapping + */ +MEM_STATIC +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +ptrdiff_t ZSTD_wrappedPtrDiff(unsigned char const* lhs, unsigned char const* rhs) +{ + return lhs - rhs; +} + +/** + * Helper function to perform a wrapped pointer add without triggering UBSAN. + * + * @return ptr + add with wrapping + */ +MEM_STATIC +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +unsigned char const* ZSTD_wrappedPtrAdd(unsigned char const* ptr, ptrdiff_t add) +{ + return ptr + add; +} + +/** + * Helper function to perform a wrapped pointer subtraction without triggering + * UBSAN. + * + * @return ptr - sub with wrapping + */ +MEM_STATIC +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +unsigned char const* ZSTD_wrappedPtrSub(unsigned char const* ptr, ptrdiff_t sub) +{ + return ptr - sub; +} + +/** + * Helper function to add to a pointer that works around C's undefined behavior + * of adding 0 to NULL. + * + * @returns `ptr + add` except it defines `NULL + 0 == NULL`. + */ +MEM_STATIC +unsigned char* ZSTD_maybeNullPtrAdd(unsigned char* ptr, ptrdiff_t add) +{ + return add > 0 ? ptr + add : ptr; +} + +/* Issue #3240 reports an ASAN failure on an llvm-mingw build. Out of an + * abundance of caution, disable our custom poisoning on mingw. */ +#ifdef __MINGW32__ +#ifndef ZSTD_ASAN_DONT_POISON_WORKSPACE +#define ZSTD_ASAN_DONT_POISON_WORKSPACE 1 +#endif +#ifndef ZSTD_MSAN_DONT_POISON_WORKSPACE +#define ZSTD_MSAN_DONT_POISON_WORKSPACE 1 +#endif +#endif + +#if ZSTD_MEMORY_SANITIZER && !defined(ZSTD_MSAN_DONT_POISON_WORKSPACE) +/* Not all platforms that support msan provide sanitizers/msan_interface.h. + * We therefore declare the functions we need ourselves, rather than trying to + * include the header file... */ +#include /* size_t */ +#define ZSTD_DEPS_NEED_STDINT +#include "zstd_deps.h" /* intptr_t */ + +/* Make memory region fully initialized (without changing its contents). */ +void __msan_unpoison(const volatile void *a, size_t size); + +/* Make memory region fully uninitialized (without changing its contents). + This is a legacy interface that does not update origin information. Use + __msan_allocated_memory() instead. */ +void __msan_poison(const volatile void *a, size_t size); + +/* Returns the offset of the first (at least partially) poisoned byte in the + memory range, or -1 if the whole range is good. */ +intptr_t __msan_test_shadow(const volatile void *x, size_t size); + +/* Print shadow and origin for the memory range to stderr in a human-readable + format. */ +void __msan_print_shadow(const volatile void *x, size_t size); +#endif + +#if ZSTD_ADDRESS_SANITIZER && !defined(ZSTD_ASAN_DONT_POISON_WORKSPACE) +/* Not all platforms that support asan provide sanitizers/asan_interface.h. + * We therefore declare the functions we need ourselves, rather than trying to + * include the header file... */ +#include /* size_t */ + +/** + * Marks a memory region ([addr, addr+size)) as unaddressable. + * + * This memory must be previously allocated by your program. Instrumented + * code is forbidden from accessing addresses in this region until it is + * unpoisoned. This function is not guaranteed to poison the entire region - + * it could poison only a subregion of [addr, addr+size) due to ASan + * alignment restrictions. + * + * \note This function is not thread-safe because no two threads can poison or + * unpoison memory in the same memory region simultaneously. + * + * \param addr Start of memory region. + * \param size Size of memory region. */ +void __asan_poison_memory_region(void const volatile *addr, size_t size); + +/** + * Marks a memory region ([addr, addr+size)) as addressable. + * + * This memory must be previously allocated by your program. Accessing + * addresses in this region is allowed until this region is poisoned again. + * This function could unpoison a super-region of [addr, addr+size) due + * to ASan alignment restrictions. + * + * \note This function is not thread-safe because no two threads can + * poison or unpoison memory in the same memory region simultaneously. + * + * \param addr Start of memory region. + * \param size Size of memory region. */ +void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #endif #endif /* ZSTD_COMPILER_H */ diff --git a/third_party/zstd/include/zstd/common/cpu.h b/third_party/zstd/include/zstd/common/cpu.h new file mode 100644 index 00000000000..0e684d9ad8e --- /dev/null +++ b/third_party/zstd/include/zstd/common/cpu.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_COMMON_CPU_H +#define ZSTD_COMMON_CPU_H + +/** + * Implementation taken from folly/CpuId.h + * https://github.com/facebook/folly/blob/master/folly/CpuId.h + */ + +#include "mem.h" + +#ifdef _MSC_VER +#include +#endif + +typedef struct { + U32 f1c; + U32 f1d; + U32 f7b; + U32 f7c; +} ZSTD_cpuid_t; + +MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) { + U32 f1c = 0; + U32 f1d = 0; + U32 f7b = 0; + U32 f7c = 0; +#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) +#if !defined(__clang__) + int reg[4]; + __cpuid((int*)reg, 0); + { + int const n = reg[0]; + if (n >= 1) { + __cpuid((int*)reg, 1); + f1c = (U32)reg[2]; + f1d = (U32)reg[3]; + } + if (n >= 7) { + __cpuidex((int*)reg, 7, 0); + f7b = (U32)reg[1]; + f7c = (U32)reg[2]; + } + } +#else + /* Clang compiler has a bug (fixed in https://reviews.llvm.org/D101338) in + * which the `__cpuid` intrinsic does not save and restore `rbx` as it needs + * to due to being a reserved register. So in that case, do the `cpuid` + * ourselves. Clang supports inline assembly anyway. + */ + U32 n; + __asm__( + "pushq %%rbx\n\t" + "cpuid\n\t" + "popq %%rbx\n\t" + : "=a"(n) + : "a"(0) + : "rcx", "rdx"); + if (n >= 1) { + U32 f1a; + __asm__( + "pushq %%rbx\n\t" + "cpuid\n\t" + "popq %%rbx\n\t" + : "=a"(f1a), "=c"(f1c), "=d"(f1d) + : "a"(1) + :); + } + if (n >= 7) { + __asm__( + "pushq %%rbx\n\t" + "cpuid\n\t" + "movq %%rbx, %%rax\n\t" + "popq %%rbx" + : "=a"(f7b), "=c"(f7c) + : "a"(7), "c"(0) + : "rdx"); + } +#endif +#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__) + /* The following block like the normal cpuid branch below, but gcc + * reserves ebx for use of its pic register so we must specially + * handle the save and restore to avoid clobbering the register + */ + U32 n; + __asm__( + "pushl %%ebx\n\t" + "cpuid\n\t" + "popl %%ebx\n\t" + : "=a"(n) + : "a"(0) + : "ecx", "edx"); + if (n >= 1) { + U32 f1a; + __asm__( + "pushl %%ebx\n\t" + "cpuid\n\t" + "popl %%ebx\n\t" + : "=a"(f1a), "=c"(f1c), "=d"(f1d) + : "a"(1)); + } + if (n >= 7) { + __asm__( + "pushl %%ebx\n\t" + "cpuid\n\t" + "movl %%ebx, %%eax\n\t" + "popl %%ebx" + : "=a"(f7b), "=c"(f7c) + : "a"(7), "c"(0) + : "edx"); + } +#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__) + U32 n; + __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx"); + if (n >= 1) { + U32 f1a; + __asm__("cpuid" : "=a"(f1a), "=c"(f1c), "=d"(f1d) : "a"(1) : "ebx"); + } + if (n >= 7) { + U32 f7a; + __asm__("cpuid" + : "=a"(f7a), "=b"(f7b), "=c"(f7c) + : "a"(7), "c"(0) + : "edx"); + } +#endif + { + ZSTD_cpuid_t cpuid; + cpuid.f1c = f1c; + cpuid.f1d = f1d; + cpuid.f7b = f7b; + cpuid.f7c = f7c; + return cpuid; + } +} + +#define X(name, r, bit) \ + MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) { \ + return ((cpuid.r) & (1U << bit)) != 0; \ + } + +/* cpuid(1): Processor Info and Feature Bits. */ +#define C(name, bit) X(name, f1c, bit) + C(sse3, 0) + C(pclmuldq, 1) + C(dtes64, 2) + C(monitor, 3) + C(dscpl, 4) + C(vmx, 5) + C(smx, 6) + C(eist, 7) + C(tm2, 8) + C(ssse3, 9) + C(cnxtid, 10) + C(fma, 12) + C(cx16, 13) + C(xtpr, 14) + C(pdcm, 15) + C(pcid, 17) + C(dca, 18) + C(sse41, 19) + C(sse42, 20) + C(x2apic, 21) + C(movbe, 22) + C(popcnt, 23) + C(tscdeadline, 24) + C(aes, 25) + C(xsave, 26) + C(osxsave, 27) + C(avx, 28) + C(f16c, 29) + C(rdrand, 30) +#undef C +#define D(name, bit) X(name, f1d, bit) + D(fpu, 0) + D(vme, 1) + D(de, 2) + D(pse, 3) + D(tsc, 4) + D(msr, 5) + D(pae, 6) + D(mce, 7) + D(cx8, 8) + D(apic, 9) + D(sep, 11) + D(mtrr, 12) + D(pge, 13) + D(mca, 14) + D(cmov, 15) + D(pat, 16) + D(pse36, 17) + D(psn, 18) + D(clfsh, 19) + D(ds, 21) + D(acpi, 22) + D(mmx, 23) + D(fxsr, 24) + D(sse, 25) + D(sse2, 26) + D(ss, 27) + D(htt, 28) + D(tm, 29) + D(pbe, 31) +#undef D + +/* cpuid(7): Extended Features. */ +#define B(name, bit) X(name, f7b, bit) + B(bmi1, 3) + B(hle, 4) + B(avx2, 5) + B(smep, 7) + B(bmi2, 8) + B(erms, 9) + B(invpcid, 10) + B(rtm, 11) + B(mpx, 14) + B(avx512f, 16) + B(avx512dq, 17) + B(rdseed, 18) + B(adx, 19) + B(smap, 20) + B(avx512ifma, 21) + B(pcommit, 22) + B(clflushopt, 23) + B(clwb, 24) + B(avx512pf, 26) + B(avx512er, 27) + B(avx512cd, 28) + B(sha, 29) + B(avx512bw, 30) + B(avx512vl, 31) +#undef B +#define C(name, bit) X(name, f7c, bit) + C(prefetchwt1, 0) + C(avx512vbmi, 1) +#undef C + +#undef X + +#endif /* ZSTD_COMMON_CPU_H */ diff --git a/third_party/zstd/include/zstd/common/debug.h b/third_party/zstd/include/zstd/common/debug.h index ac6224888d8..a16b69e5743 100644 --- a/third_party/zstd/include/zstd/common/debug.h +++ b/third_party/zstd/include/zstd/common/debug.h @@ -1,7 +1,7 @@ /* ****************************************************************** * debug * Part of FSE library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * You can contact the author at : * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -51,15 +51,6 @@ extern "C" { #endif -/* DEBUGFILE can be defined externally, - * typically through compiler command line. - * note : currently useless. - * Value must be stderr or stdout */ -#ifndef DEBUGFILE -# define DEBUGFILE stderr -#endif - - /* recommended values for DEBUGLEVEL : * 0 : release mode, no debug, all run-time checks disabled * 1 : enables assert() only, no display @@ -76,7 +67,8 @@ extern "C" { */ #if (DEBUGLEVEL>=1) -# include +# define ZSTD_DEPS_NEED_ASSERT +# include "zstd_deps.h" #else # ifndef assert /* assert may be already defined, due to prior #include */ # define assert(condition) ((void)0) /* disable assert (default) */ @@ -84,7 +76,8 @@ extern "C" { #endif #if (DEBUGLEVEL>=2) -# include +# define ZSTD_DEPS_NEED_IO +# include "zstd_deps.h" extern int g_debuglevel; /* the variable is only declared, it actually lives in debug.c, and is shared by the whole process. @@ -92,18 +85,27 @@ extern int g_debuglevel; /* the variable is only declared, It's useful when enabling very verbose levels on selective conditions (such as position in src) */ -# define RAWLOG(l, ...) { \ - if (l<=g_debuglevel) { \ - fprintf(stderr, __VA_ARGS__); \ - } } -# define DEBUGLOG(l, ...) { \ - if (l<=g_debuglevel) { \ - fprintf(stderr, __FILE__ ": " __VA_ARGS__); \ - fprintf(stderr, " \n"); \ - } } +# define RAWLOG(l, ...) \ + do { \ + if (l<=g_debuglevel) { \ + ZSTD_DEBUG_PRINT(__VA_ARGS__); \ + } \ + } while (0) + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +#define LINE_AS_STRING TOSTRING(__LINE__) + +# define DEBUGLOG(l, ...) \ + do { \ + if (l<=g_debuglevel) { \ + ZSTD_DEBUG_PRINT(__FILE__ ":" LINE_AS_STRING ": " __VA_ARGS__); \ + ZSTD_DEBUG_PRINT(" \n"); \ + } \ + } while (0) #else -# define RAWLOG(l, ...) {} /* disabled */ -# define DEBUGLOG(l, ...) {} /* disabled */ +# define RAWLOG(l, ...) do { } while (0) /* disabled */ +# define DEBUGLOG(l, ...) do { } while (0) /* disabled */ #endif diff --git a/third_party/zstd/include/zstd/common/error_private.h b/third_party/zstd/include/zstd/common/error_private.h index b1af95d1233..0156010c745 100644 --- a/third_party/zstd/include/zstd/common/error_private.h +++ b/third_party/zstd/include/zstd/common/error_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -13,13 +13,20 @@ #ifndef ERROR_H_MODULE #define ERROR_H_MODULE +#if defined (__cplusplus) +extern "C" { +#endif + + /* **************************************** * Dependencies ******************************************/ -#include /* size_t */ -#include "zstd/common/zstd_errors.h" /* enum list */ +#include "../zstd_errors.h" /* enum list */ +#include "compiler.h" +#include "debug.h" +#include "zstd_deps.h" /* size_t */ + -namespace duckdb_zstd { /* **************************************** * Compiler-specific ******************************************/ @@ -53,8 +60,13 @@ ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); } ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); } /* check and forward error code */ -#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e -#define CHECK_F(f) { CHECK_V_F(_var_err__, f); } +#define CHECK_V_F(e, f) \ + size_t const e = f; \ + do { \ + if (ERR_isError(e)) \ + return e; \ + } while (0) +#define CHECK_F(f) do { CHECK_V_F(_var_err__, f); } while (0) /*-**************************************** @@ -68,6 +80,89 @@ ERR_STATIC const char* ERR_getErrorName(size_t code) return ERR_getErrorString(ERR_getErrorCode(code)); } +/** + * Ignore: this is an internal helper. + * + * This is a helper function to help force C99-correctness during compilation. + * Under strict compilation modes, variadic macro arguments can't be empty. + * However, variadic function arguments can be. Using a function therefore lets + * us statically check that at least one (string) argument was passed, + * independent of the compilation flags. + */ +static INLINE_KEYWORD UNUSED_ATTR +void _force_has_format_string(const char *format, ...) { + (void)format; } +/** + * Ignore: this is an internal helper. + * + * We want to force this function invocation to be syntactically correct, but + * we don't want to force runtime evaluation of its arguments. + */ +#define _FORCE_HAS_FORMAT_STRING(...) \ + do { \ + if (0) { \ + _force_has_format_string(__VA_ARGS__); \ + } \ + } while (0) + +#define ERR_QUOTE(str) #str + +/** + * Return the specified error if the condition evaluates to true. + * + * In debug modes, prints additional information. + * In order to do that (particularly, printing the conditional that failed), + * this can't just wrap RETURN_ERROR(). + */ +#define RETURN_ERROR_IF(cond, err, ...) \ + do { \ + if (cond) { \ + RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \ + __FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \ + _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ + RAWLOG(3, ": " __VA_ARGS__); \ + RAWLOG(3, "\n"); \ + return ERROR(err); \ + } \ + } while (0) + +/** + * Unconditionally return the specified error. + * + * In debug modes, prints additional information. + */ +#define RETURN_ERROR(err, ...) \ + do { \ + RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \ + __FILE__, __LINE__, ERR_QUOTE(ERROR(err))); \ + _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ + RAWLOG(3, ": " __VA_ARGS__); \ + RAWLOG(3, "\n"); \ + return ERROR(err); \ + } while(0) + +/** + * If the provided expression evaluates to an error code, returns that error code. + * + * In debug modes, prints additional information. + */ +#define FORWARD_IF_ERROR(err, ...) \ + do { \ + size_t const err_code = (err); \ + if (ERR_isError(err_code)) { \ + RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \ + __FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \ + _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ + RAWLOG(3, ": " __VA_ARGS__); \ + RAWLOG(3, "\n"); \ + return err_code; \ + } \ + } while(0) + +#if defined (__cplusplus) +} +#endif + #endif /* ERROR_H_MODULE */ diff --git a/third_party/zstd/include/zstd/common/fse.h b/third_party/zstd/include/zstd/common/fse.h index 6600fee54aa..2ae128e60db 100644 --- a/third_party/zstd/include/zstd/common/fse.h +++ b/third_party/zstd/include/zstd/common/fse.h @@ -1,7 +1,7 @@ /* ****************************************************************** * FSE : Finite State Entropy codec * Public Prototypes declaration - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * You can contact the author at : * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -12,6 +12,10 @@ * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ +#if defined (__cplusplus) +extern "C" { +#endif + #ifndef FSE_H #define FSE_H @@ -19,10 +23,9 @@ /*-***************************************** * Dependencies ******************************************/ -#include /* size_t, ptrdiff_t */ +#include "zstd_deps.h" /* size_t, ptrdiff_t */ -namespace duckdb_zstd { /*-***************************************** * FSE_PUBLIC_API : control library symbols visibility ******************************************/ @@ -50,34 +53,6 @@ namespace duckdb_zstd { FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */ -/*-**************************************** -* FSE simple functions -******************************************/ -/*! FSE_compress() : - Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'. - 'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= FSE_compressBound(srcSize). - @return : size of compressed data (<= dstCapacity). - Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!! - if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead. - if FSE_isError(return), compression failed (more details using FSE_getErrorName()) -*/ -FSE_PUBLIC_API size_t FSE_compress(void* dst, size_t dstCapacity, - const void* src, size_t srcSize); - -/*! FSE_decompress(): - Decompress FSE data from buffer 'cSrc', of size 'cSrcSize', - into already allocated destination buffer 'dst', of size 'dstCapacity'. - @return : size of regenerated data (<= maxDstSize), - or an error code, which can be tested using FSE_isError() . - - ** Important ** : FSE_decompress() does not decompress non-compressible nor RLE data !!! - Why ? : making this distinction requires a header. - Header management is intentionally delegated to the user layer, which can better manage special cases. -*/ -FSE_PUBLIC_API size_t FSE_decompress(void* dst, size_t dstCapacity, - const void* cSrc, size_t cSrcSize); - - /*-***************************************** * Tool functions ******************************************/ @@ -88,20 +63,6 @@ FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return FSE_PUBLIC_API const char* FSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */ -/*-***************************************** -* FSE advanced functions -******************************************/ -/*! FSE_compress2() : - Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog' - Both parameters can be defined as '0' to mean : use default value - @return : size of compressed data - Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!! - if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression. - if FSE_isError(return), it's an error code. -*/ -FSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog); - - /*-***************************************** * FSE detailed API ******************************************/ @@ -134,10 +95,16 @@ FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize /*! FSE_normalizeCount(): normalize counts so that sum(count[]) == Power_of_2 (2^tableLog) 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1). + useLowProbCount is a boolean parameter which trades off compressed size for + faster header decoding. When it is set to 1, the compressed data will be slightly + smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be + faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0 + is a good default, since header deserialization makes a big speed difference. + Otherwise, useLowProbCount=1 is a good default, since the speed difference is small. @return : tableLog, or an errorCode, which can be tested using FSE_isError() */ FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, - const unsigned* count, size_t srcSize, unsigned maxSymbolValue); + const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount); /*! FSE_NCountWriteBound(): Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'. @@ -155,8 +122,6 @@ FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize, /*! Constructor and Destructor of FSE_CTable. Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */ typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */ -FSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog); -FSE_PUBLIC_API void FSE_freeCTable (FSE_CTable* ct); /*! FSE_buildCTable(): Builds `ct`, which must be already allocated, using FSE_createCTable(). @@ -225,23 +190,14 @@ FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize); -/*! Constructor and Destructor of FSE_DTable. - Note that its size depends on 'tableLog' */ +/*! FSE_readNCount_bmi2(): + * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise. + */ +FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter, + unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, + const void* rBuffer, size_t rBuffSize, int bmi2); + typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ -FSE_PUBLIC_API FSE_DTable* FSE_createDTable(unsigned tableLog); -FSE_PUBLIC_API void FSE_freeDTable(FSE_DTable* dt); - -/*! FSE_buildDTable(): - Builds 'dt', which must be already allocated, using FSE_createDTable(). - return : 0, or an errorCode, which can be tested using FSE_isError() */ -FSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); - -/*! FSE_decompress_usingDTable(): - Decompress compressed source `cSrc` of size `cSrcSize` using `dt` - into `dst` which must be already allocated. - @return : size of regenerated data (necessarily <= `dstCapacity`), - or an errorCode, which can be tested using FSE_isError() */ -FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt); /*! Tutorial : @@ -271,7 +227,414 @@ FSE_decompress_usingDTable() result will tell how many bytes were regenerated (< If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small) */ +#endif /* FSE_H */ + + +#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY) +#define FSE_H_FSE_STATIC_LINKING_ONLY + +/* *** Dependency *** */ +#include "bitstream.h" + + +/* ***************************************** +* Static allocation +*******************************************/ +/* FSE buffer bounds */ +#define FSE_NCOUNTBOUND 512 +#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */) +#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ + +/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */ +#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2)) +#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<(maxTableLog))) + +/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */ +#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable)) +#define FSE_DTABLE_SIZE(maxTableLog) (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable)) + + +/* ***************************************** + * FSE advanced API + ***************************************** */ + +unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus); +/**< same as FSE_optimalTableLog(), which used `minus==2` */ + +size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue); +/**< build a fake FSE_CTable, designed to compress always the same symbolValue */ + +/* FSE_buildCTable_wksp() : + * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`). + * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`. + * See FSE_buildCTable_wksp() for breakdown of workspace usage. + */ +#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (((maxSymbolValue + 2) + (1ull << (tableLog)))/2 + sizeof(U64)/sizeof(U32) /* additional 8 bytes for potential table overwrite */) +#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)) +size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); + +#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8) +#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned)) +FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); +/**< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */ + +#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + 1 + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1) +#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned)) +size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2); +/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)`. + * Set bmi2 to 1 if your CPU supports BMI2 or 0 if it doesn't */ + +typedef enum { + FSE_repeat_none, /**< Cannot use the previous table */ + FSE_repeat_check, /**< Can use the previous table but it must be checked */ + FSE_repeat_valid /**< Can use the previous table and it is assumed to be valid */ + } FSE_repeat; + +/* ***************************************** +* FSE symbol compression API +*******************************************/ +/*! + This API consists of small unitary functions, which highly benefit from being inlined. + Hence their body are included in next section. +*/ +typedef struct { + ptrdiff_t value; + const void* stateTable; + const void* symbolTT; + unsigned stateLog; +} FSE_CState_t; + +static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct); + +static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol); + +static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr); + +/**< +These functions are inner components of FSE_compress_usingCTable(). +They allow the creation of custom streams, mixing multiple tables and bit sources. + +A key property to keep in mind is that encoding and decoding are done **in reverse direction**. +So the first symbol you will encode is the last you will decode, like a LIFO stack. + +You will need a few variables to track your CStream. They are : + +FSE_CTable ct; // Provided by FSE_buildCTable() +BIT_CStream_t bitStream; // bitStream tracking structure +FSE_CState_t state; // State tracking structure (can have several) + + +The first thing to do is to init bitStream and state. + size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize); + FSE_initCState(&state, ct); + +Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError(); +You can then encode your input data, byte after byte. +FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time. +Remember decoding will be done in reverse direction. + FSE_encodeByte(&bitStream, &state, symbol); + +At any time, you can also add any bit sequence. +Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders + BIT_addBits(&bitStream, bitField, nbBits); + +The above methods don't commit data to memory, they just store it into local register, for speed. +Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t). +Writing data to memory is a manual operation, performed by the flushBits function. + BIT_flushBits(&bitStream); + +Your last FSE encoding operation shall be to flush your last state value(s). + FSE_flushState(&bitStream, &state); + +Finally, you must close the bitStream. +The function returns the size of CStream in bytes. +If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible) +If there is an error, it returns an errorCode (which can be tested using FSE_isError()). + size_t size = BIT_closeCStream(&bitStream); +*/ + + +/* ***************************************** +* FSE symbol decompression API +*******************************************/ +typedef struct { + size_t state; + const void* table; /* precise table may vary, depending on U16 */ +} FSE_DState_t; + + +static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt); + +static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); + +static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr); + +/**< +Let's now decompose FSE_decompress_usingDTable() into its unitary components. +You will decode FSE-encoded symbols from the bitStream, +and also any other bitFields you put in, **in reverse order**. + +You will need a few variables to track your bitStream. They are : + +BIT_DStream_t DStream; // Stream context +FSE_DState_t DState; // State context. Multiple ones are possible +FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable() + +The first thing to do is to init the bitStream. + errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize); + +You should then retrieve your initial state(s) +(in reverse flushing order if you have several ones) : + errorCode = FSE_initDState(&DState, &DStream, DTablePtr); + +You can then decode your data, symbol after symbol. +For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'. +Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out). + unsigned char symbol = FSE_decodeSymbol(&DState, &DStream); + +You can retrieve any bitfield you eventually stored into the bitStream (in reverse order) +Note : maximum allowed nbBits is 25, for 32-bits compatibility + size_t bitField = BIT_readBits(&DStream, nbBits); + +All above operations only read from local register (which size depends on size_t). +Refueling the register from memory is manually performed by the reload method. + endSignal = FSE_reloadDStream(&DStream); + +BIT_reloadDStream() result tells if there is still some more data to read from DStream. +BIT_DStream_unfinished : there is still some data left into the DStream. +BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled. +BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed. +BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted. + +When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop, +to properly detect the exact end of stream. +After each decoded symbol, check if DStream is fully consumed using this simple test : + BIT_reloadDStream(&DStream) >= BIT_DStream_completed + +When it's done, verify decompression is fully completed, by checking both DStream and the relevant states. +Checking if DStream has reached its end is performed by : + BIT_endOfDStream(&DStream); +Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible. + FSE_endOfDState(&DState); +*/ + + +/* ***************************************** +* FSE unsafe API +*******************************************/ +static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); +/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */ + + +/* ***************************************** +* Implementation of inlined functions +*******************************************/ +typedef struct { + int deltaFindState; + U32 deltaNbBits; +} FSE_symbolCompressionTransform; /* total 8 bytes */ + +MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct) +{ + const void* ptr = ct; + const U16* u16ptr = (const U16*) ptr; + const U32 tableLog = MEM_read16(ptr); + statePtr->value = (ptrdiff_t)1<stateTable = u16ptr+2; + statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1); + statePtr->stateLog = tableLog; } -#endif /* FSE_H */ +/*! FSE_initCState2() : +* Same as FSE_initCState(), but the first symbol to include (which will be the last to be read) +* uses the smallest state value possible, saving the cost of this symbol */ +MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol) +{ + FSE_initCState(statePtr, ct); + { const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; + const U16* stateTable = (const U16*)(statePtr->stateTable); + U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16); + statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits; + statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; + } +} + +MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol) +{ + FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; + const U16* const stateTable = (const U16*)(statePtr->stateTable); + U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16); + BIT_addBits(bitC, (size_t)statePtr->value, nbBitsOut); + statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; +} + +MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr) +{ + BIT_addBits(bitC, (size_t)statePtr->value, statePtr->stateLog); + BIT_flushBits(bitC); +} + + +/* FSE_getMaxNbBits() : + * Approximate maximum cost of a symbol, in bits. + * Fractional get rounded up (i.e. a symbol with a normalized frequency of 3 gives the same result as a frequency of 2) + * note 1 : assume symbolValue is valid (<= maxSymbolValue) + * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */ +MEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue) +{ + const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr; + return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16; +} + +/* FSE_bitCost() : + * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits) + * note 1 : assume symbolValue is valid (<= maxSymbolValue) + * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */ +MEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog) +{ + const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr; + U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16; + U32 const threshold = (minNbBits+1) << 16; + assert(tableLog < 16); + assert(accuracyLog < 31-tableLog); /* ensure enough room for renormalization double shift */ + { U32 const tableSize = 1 << tableLog; + U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize); + U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog; /* linear interpolation (very approximate) */ + U32 const bitMultiplier = 1 << accuracyLog; + assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold); + assert(normalizedDeltaFromThreshold <= bitMultiplier); + return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold; + } +} + + +/* ====== Decompression ====== */ + +typedef struct { + U16 tableLog; + U16 fastMode; +} FSE_DTableHeader; /* sizeof U32 */ + +typedef struct +{ + unsigned short newState; + unsigned char symbol; + unsigned char nbBits; +} FSE_decode_t; /* size == U32 */ + +MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt) +{ + const void* ptr = dt; + const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr; + DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); + BIT_reloadDStream(bitD); + DStatePtr->table = dt + 1; +} + +MEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr) +{ + FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + return DInfo.symbol; +} + +MEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) +{ + FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + U32 const nbBits = DInfo.nbBits; + size_t const lowBits = BIT_readBits(bitD, nbBits); + DStatePtr->state = DInfo.newState + lowBits; +} + +MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) +{ + FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + U32 const nbBits = DInfo.nbBits; + BYTE const symbol = DInfo.symbol; + size_t const lowBits = BIT_readBits(bitD, nbBits); + + DStatePtr->state = DInfo.newState + lowBits; + return symbol; +} + +/*! FSE_decodeSymbolFast() : + unsafe, only works if no symbol has a probability > 50% */ +MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) +{ + FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + U32 const nbBits = DInfo.nbBits; + BYTE const symbol = DInfo.symbol; + size_t const lowBits = BIT_readBitsFast(bitD, nbBits); + + DStatePtr->state = DInfo.newState + lowBits; + return symbol; +} + +MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) +{ + return DStatePtr->state == 0; +} + + + +#ifndef FSE_COMMONDEFS_ONLY + +/* ************************************************************** +* Tuning parameters +****************************************************************/ +/*!MEMORY_USAGE : +* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) +* Increasing memory usage improves compression ratio +* Reduced memory usage can improve speed, due to cache effect +* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ +#ifndef FSE_MAX_MEMORY_USAGE +# define FSE_MAX_MEMORY_USAGE 14 +#endif +#ifndef FSE_DEFAULT_MEMORY_USAGE +# define FSE_DEFAULT_MEMORY_USAGE 13 +#endif +#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE) +# error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE" +#endif + +/*!FSE_MAX_SYMBOL_VALUE : +* Maximum symbol value authorized. +* Required for proper stack allocation */ +#ifndef FSE_MAX_SYMBOL_VALUE +# define FSE_MAX_SYMBOL_VALUE 255 +#endif + +/* ************************************************************** +* template functions type & suffix +****************************************************************/ +#define FSE_FUNCTION_TYPE BYTE +#define FSE_FUNCTION_EXTENSION +#define FSE_DECODE_TYPE FSE_decode_t + + +#endif /* !FSE_COMMONDEFS_ONLY */ + + +/* *************************************************************** +* Constants +*****************************************************************/ +#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2) +#define FSE_MAX_TABLESIZE (1U< FSE_TABLELOG_ABSOLUTE_MAX +# error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" +#endif + +#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3) + + +#endif /* FSE_STATIC_LINKING_ONLY */ + + +#if defined (__cplusplus) +} +#endif diff --git a/third_party/zstd/include/zstd/common/fse_static.h b/third_party/zstd/include/zstd/common/fse_static.h deleted file mode 100644 index 7d8267e3e44..00000000000 --- a/third_party/zstd/include/zstd/common/fse_static.h +++ /dev/null @@ -1,421 +0,0 @@ -/* ****************************************************************** - * FSE : Finite State Entropy codec - * Public Prototypes declaration - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. - * - * You can contact the author at : - * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. -****************************************************************** */ - -#ifndef FSE_H_FSE_STATIC_LINKING_ONLY -#define FSE_H_FSE_STATIC_LINKING_ONLY - -/* *** Dependency *** */ -#include "zstd/common/bitstream.h" - -namespace duckdb_zstd { - -/* ***************************************** -* Static allocation -*******************************************/ -/* FSE buffer bounds */ -#define FSE_NCOUNTBOUND 512 -#define FSE_BLOCKBOUND(size) (size + (size>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */) -#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ - -/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */ -#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2)) -#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1< 12) ? (1 << (maxTableLog - 2)) : 1024) ) -size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); - -size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits); -/**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */ - -size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue); -/**< build a fake FSE_CTable, designed to compress always the same symbolValue */ - -/* FSE_buildCTable_wksp() : - * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`). - * `wkspSize` must be >= `(1<= BIT_DStream_completed - -When it's done, verify decompression is fully completed, by checking both DStream and the relevant states. -Checking if DStream has reached its end is performed by : - BIT_endOfDStream(&DStream); -Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible. - FSE_endOfDState(&DState); -*/ - - -/* ***************************************** -* FSE unsafe API -*******************************************/ -static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); -/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */ - - -/* ***************************************** -* Implementation of inlined functions -*******************************************/ -typedef struct { - int deltaFindState; - U32 deltaNbBits; -} FSE_symbolCompressionTransform; /* total 8 bytes */ - -MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct) -{ - const void* ptr = ct; - const U16* u16ptr = (const U16*) ptr; - const U32 tableLog = MEM_read16(ptr); - statePtr->value = (ptrdiff_t)1<stateTable = u16ptr+2; - statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1); - statePtr->stateLog = tableLog; -} - - -/*! FSE_initCState2() : -* Same as FSE_initCState(), but the first symbol to include (which will be the last to be read) -* uses the smallest state value possible, saving the cost of this symbol */ -MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol) -{ - FSE_initCState(statePtr, ct); - { const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; - const U16* stateTable = (const U16*)(statePtr->stateTable); - U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16); - statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits; - statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; - } -} - -MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol) -{ - FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; - const U16* const stateTable = (const U16*)(statePtr->stateTable); - U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16); - BIT_addBits(bitC, statePtr->value, nbBitsOut); - statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; -} - -MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr) -{ - BIT_addBits(bitC, statePtr->value, statePtr->stateLog); - BIT_flushBits(bitC); -} - - -/* FSE_getMaxNbBits() : - * Approximate maximum cost of a symbol, in bits. - * Fractional get rounded up (i.e : a symbol with a normalized frequency of 3 gives the same result as a frequency of 2) - * note 1 : assume symbolValue is valid (<= maxSymbolValue) - * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */ -MEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue) -{ - const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr; - return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16; -} - -/* FSE_bitCost() : - * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits) - * note 1 : assume symbolValue is valid (<= maxSymbolValue) - * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */ -MEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog) -{ - const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr; - U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16; - U32 const threshold = (minNbBits+1) << 16; - assert(tableLog < 16); - assert(accuracyLog < 31-tableLog); /* ensure enough room for renormalization double shift */ - { U32 const tableSize = 1 << tableLog; - U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize); - U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog; /* linear interpolation (very approximate) */ - U32 const bitMultiplier = 1 << accuracyLog; - assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold); - assert(normalizedDeltaFromThreshold <= bitMultiplier); - return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold; - } -} - - -/* ====== Decompression ====== */ - -typedef struct { - U16 tableLog; - U16 fastMode; -} FSE_DTableHeader; /* sizeof U32 */ - -typedef struct -{ - unsigned short newState; - unsigned char symbol; - unsigned char nbBits; -} FSE_decode_t; /* size == U32 */ - -MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt) -{ - const void* ptr = dt; - const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr; - DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); - BIT_reloadDStream(bitD); - DStatePtr->table = dt + 1; -} - -MEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr) -{ - FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; - return DInfo.symbol; -} - -MEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) -{ - FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; - U32 const nbBits = DInfo.nbBits; - size_t const lowBits = BIT_readBits(bitD, nbBits); - DStatePtr->state = DInfo.newState + lowBits; -} - -MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) -{ - FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; - U32 const nbBits = DInfo.nbBits; - BYTE const symbol = DInfo.symbol; - size_t const lowBits = BIT_readBits(bitD, nbBits); - - DStatePtr->state = DInfo.newState + lowBits; - return symbol; -} - -/*! FSE_decodeSymbolFast() : - unsafe, only works if no symbol has a probability > 50% */ -MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) -{ - FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; - U32 const nbBits = DInfo.nbBits; - BYTE const symbol = DInfo.symbol; - size_t const lowBits = BIT_readBitsFast(bitD, nbBits); - - DStatePtr->state = DInfo.newState + lowBits; - return symbol; -} - -MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) -{ - return DStatePtr->state == 0; -} - - - -#ifndef FSE_COMMONDEFS_ONLY - -/* ************************************************************** -* Tuning parameters -****************************************************************/ -/*!MEMORY_USAGE : -* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) -* Increasing memory usage improves compression ratio -* Reduced memory usage can improve speed, due to cache effect -* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ -#ifndef FSE_MAX_MEMORY_USAGE -# define FSE_MAX_MEMORY_USAGE 14 -#endif -#ifndef FSE_DEFAULT_MEMORY_USAGE -# define FSE_DEFAULT_MEMORY_USAGE 13 -#endif - -/*!FSE_MAX_SYMBOL_VALUE : -* Maximum symbol value authorized. -* Required for proper stack allocation */ -#ifndef FSE_MAX_SYMBOL_VALUE -# define FSE_MAX_SYMBOL_VALUE 255 -#endif - -/* ************************************************************** -* template functions type & suffix -****************************************************************/ -#define FSE_FUNCTION_TYPE BYTE -#define FSE_FUNCTION_EXTENSION -#define FSE_DECODE_TYPE FSE_decode_t - - -#endif /* !FSE_COMMONDEFS_ONLY */ - - -/* *************************************************************** -* Constants -*****************************************************************/ -#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2) -#define FSE_MAX_TABLESIZE (1U< FSE_TABLELOG_ABSOLUTE_MAX -# error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" -#endif - -#define FSE_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3) - -} - -#endif /* FSE_H_FSE_STATIC_LINKING_ONLY */ diff --git a/third_party/zstd/include/zstd/common/huf.h b/third_party/zstd/include/zstd/common/huf.h index 4bba72729d1..99bf85d6f4e 100644 --- a/third_party/zstd/include/zstd/common/huf.h +++ b/third_party/zstd/include/zstd/common/huf.h @@ -1,7 +1,7 @@ /* ****************************************************************** * huff0 huffman codec, * part of Finite State Entropy library - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * You can contact the author at : * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -12,86 +12,275 @@ * You may select, at your option, one of the above-listed licenses. ****************************************************************** */ +#if defined (__cplusplus) +extern "C" { +#endif + #ifndef HUF_H_298734234 #define HUF_H_298734234 /* *** Dependencies *** */ -#include /* size_t */ - - -/* *** library symbols visibility *** */ -/* Note : when linking with -fvisibility=hidden on gcc, or by default on Visual, - * HUF symbols remain "private" (internal symbols for library only). - * Set macro FSE_DLL_EXPORT to 1 if you want HUF symbols visible on DLL interface */ -#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4) -# define HUF_PUBLIC_API __attribute__ ((visibility ("default"))) -#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */ -# define HUF_PUBLIC_API __declspec(dllexport) -#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1) -# define HUF_PUBLIC_API __declspec(dllimport) /* not required, just to generate faster code (saves a function pointer load from IAT and an indirect jump) */ -#else -# define HUF_PUBLIC_API +#include "zstd_deps.h" /* size_t */ +#include "mem.h" /* U32 */ +#define FSE_STATIC_LINKING_ONLY +#include "fse.h" + + +/* *** Tool functions *** */ +#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */ +size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */ + +/* Error Management */ +unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */ +const char* HUF_getErrorName(size_t code); /**< provides error code string (useful for debugging) */ + + +#define HUF_WORKSPACE_SIZE ((8 << 10) + 512 /* sorting scratch space */) +#define HUF_WORKSPACE_SIZE_U64 (HUF_WORKSPACE_SIZE / sizeof(U64)) + +/* *** Constants *** */ +#define HUF_TABLELOG_MAX 12 /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_TABLELOG_ABSOLUTEMAX */ +#define HUF_TABLELOG_DEFAULT 11 /* default tableLog value when none specified */ +#define HUF_SYMBOLVALUE_MAX 255 + +#define HUF_TABLELOG_ABSOLUTEMAX 12 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ +#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX) +# error "HUF_TABLELOG_MAX is too large !" #endif -namespace duckdb_zstd { -/* ========================== */ -/* *** simple functions *** */ -/* ========================== */ +/* **************************************** +* Static allocation +******************************************/ +/* HUF buffer bounds */ +#define HUF_CTABLEBOUND 129 +#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true when incompressible is pre-filtered with fast heuristic */ +#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ + +/* static allocation of HUF's Compression Table */ +/* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */ +typedef size_t HUF_CElt; /* consider it an incomplete type */ +#define HUF_CTABLE_SIZE_ST(maxSymbolValue) ((maxSymbolValue)+2) /* Use tables of size_t, for proper alignment */ +#define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_ST(maxSymbolValue) * sizeof(size_t)) +#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \ + HUF_CElt name[HUF_CTABLE_SIZE_ST(maxSymbolValue)] /* no final ; */ + +/* static allocation of HUF's DTable */ +typedef U32 HUF_DTable; +#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog))) +#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \ + HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) } +#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \ + HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) } -/** HUF_compress() : - * Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'. - * 'dst' buffer must be already allocated. - * Compression runs faster if `dstCapacity` >= HUF_compressBound(srcSize). - * `srcSize` must be <= `HUF_BLOCKSIZE_MAX` == 128 KB. - * @return : size of compressed data (<= `dstCapacity`). - * Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!! - * if HUF_isError(return), compression failed (more details using HUF_getErrorName()) + +/* **************************************** +* Advanced decompression functions +******************************************/ + +/** + * Huffman flags bitset. + * For all flags, 0 is the default value. */ -HUF_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity, - const void* src, size_t srcSize); - -/** HUF_decompress() : - * Decompress HUF data from buffer 'cSrc', of size 'cSrcSize', - * into already allocated buffer 'dst', of minimum size 'dstSize'. - * `originalSize` : **must** be the ***exact*** size of original (uncompressed) data. - * Note : in contrast with FSE, HUF_decompress can regenerate - * RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data, - * because it knows size to regenerate (originalSize). - * @return : size of regenerated data (== originalSize), - * or an error code, which can be tested using HUF_isError() +typedef enum { + /** + * If compiled with DYNAMIC_BMI2: Set flag only if the CPU supports BMI2 at runtime. + * Otherwise: Ignored. + */ + HUF_flags_bmi2 = (1 << 0), + /** + * If set: Test possible table depths to find the one that produces the smallest header + encoded size. + * If unset: Use heuristic to find the table depth. + */ + HUF_flags_optimalDepth = (1 << 1), + /** + * If set: If the previous table can encode the input, always reuse the previous table. + * If unset: If the previous table can encode the input, reuse the previous table if it results in a smaller output. + */ + HUF_flags_preferRepeat = (1 << 2), + /** + * If set: Sample the input and check if the sample is uncompressible, if it is then don't attempt to compress. + * If unset: Always histogram the entire input. + */ + HUF_flags_suspectUncompressible = (1 << 3), + /** + * If set: Don't use assembly implementations + * If unset: Allow using assembly implementations + */ + HUF_flags_disableAsm = (1 << 4), + /** + * If set: Don't use the fast decoding loop, always use the fallback decoding loop. + * If unset: Use the fast decoding loop when possible. + */ + HUF_flags_disableFast = (1 << 5) +} HUF_flags_e; + + +/* **************************************** + * HUF detailed API + * ****************************************/ +#define HUF_OPTIMAL_DEPTH_THRESHOLD ZSTD_btultra + +/*! HUF_compress() does the following: + * 1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within "fse.h") + * 2. (optional) refine tableLog using HUF_optimalTableLog() + * 3. build Huffman table from count using HUF_buildCTable() + * 4. save Huffman table to memory buffer using HUF_writeCTable() + * 5. encode the data stream using HUF_compress4X_usingCTable() + * + * The following API allows targeting specific sub-functions for advanced tasks. + * For example, it's possible to compress several blocks using the same 'CTable', + * or to save and regenerate 'CTable' using external methods. */ -HUF_PUBLIC_API size_t HUF_decompress(void* dst, size_t originalSize, - const void* cSrc, size_t cSrcSize); +unsigned HUF_minTableLog(unsigned symbolCardinality); +unsigned HUF_cardinality(const unsigned* count, unsigned maxSymbolValue); +unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, void* workSpace, + size_t wkspSize, HUF_CElt* table, const unsigned* count, int flags); /* table is used as scratch space for building and testing tables, not a return value */ +size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, void* workspace, size_t workspaceSize); +size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags); +size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); +int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); +typedef enum { + HUF_repeat_none, /**< Cannot use the previous table */ + HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */ + HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */ + } HUF_repeat; -/* *** Tool functions *** */ -#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */ -HUF_PUBLIC_API size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */ +/** HUF_compress4X_repeat() : + * Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. + * If it uses hufTable it does not modify hufTable or repeat. + * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used. + * If preferRepeat then the old table will always be used if valid. + * If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */ +size_t HUF_compress4X_repeat(void* dst, size_t dstSize, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned tableLog, + void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */ + HUF_CElt* hufTable, HUF_repeat* repeat, int flags); -/* Error Management */ -HUF_PUBLIC_API unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */ -HUF_PUBLIC_API const char* HUF_getErrorName(size_t code); /**< provides error code string (useful for debugging) */ - - -/* *** Advanced function *** */ - -/** HUF_compress2() : - * Same as HUF_compress(), but offers control over `maxSymbolValue` and `tableLog`. - * `maxSymbolValue` must be <= HUF_SYMBOLVALUE_MAX . - * `tableLog` must be `<= HUF_TABLELOG_MAX` . */ -HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned tableLog); - -/** HUF_compress4X_wksp() : - * Same as HUF_compress2(), but uses externally allocated `workSpace`. - * `workspace` must have minimum alignment of 4, and be at least as large as HUF_WORKSPACE_SIZE */ -#define HUF_WORKSPACE_SIZE ((6 << 10) + 256) -#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32)) -HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned tableLog, - void* workSpace, size_t wkspSize); +/** HUF_buildCTable_wksp() : + * Same as HUF_buildCTable(), but using externally allocated scratch buffer. + * `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE. + */ +#define HUF_CTABLE_WORKSPACE_SIZE_U32 ((4 * (HUF_SYMBOLVALUE_MAX + 1)) + 192) +#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned)) +size_t HUF_buildCTable_wksp (HUF_CElt* tree, + const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, + void* workSpace, size_t wkspSize); + +/*! HUF_readStats() : + * Read compact Huffman tree, saved by HUF_writeCTable(). + * `huffWeight` is destination buffer. + * @return : size read from `src` , or an error Code . + * Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */ +size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, + U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize); + +/*! HUF_readStats_wksp() : + * Same as HUF_readStats() but takes an external workspace which must be + * 4-byte aligned and its size must be >= HUF_READ_STATS_WORKSPACE_SIZE. + * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0. + */ +#define HUF_READ_STATS_WORKSPACE_SIZE_U32 FSE_DECOMPRESS_WKSP_SIZE_U32(6, HUF_TABLELOG_MAX-1) +#define HUF_READ_STATS_WORKSPACE_SIZE (HUF_READ_STATS_WORKSPACE_SIZE_U32 * sizeof(unsigned)) +size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, + U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workspace, size_t wkspSize, + int flags); + +/** HUF_readCTable() : + * Loading a CTable saved with HUF_writeCTable() */ +size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights); + +/** HUF_getNbBitsFromCTable() : + * Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX + * Note 1 : If symbolValue > HUF_readCTableHeader(symbolTable).maxSymbolValue, returns 0 + * Note 2 : is not inlined, as HUF_CElt definition is private + */ +U32 HUF_getNbBitsFromCTable(const HUF_CElt* symbolTable, U32 symbolValue); + +typedef struct { + BYTE tableLog; + BYTE maxSymbolValue; + BYTE unused[sizeof(size_t) - 2]; +} HUF_CTableHeader; + +/** HUF_readCTableHeader() : + * @returns The header from the CTable specifying the tableLog and the maxSymbolValue. + */ +HUF_CTableHeader HUF_readCTableHeader(HUF_CElt const* ctable); + +/* + * HUF_decompress() does the following: + * 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics + * 2. build Huffman table from save, using HUF_readDTableX?() + * 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable() + */ + +/** HUF_selectDecoder() : + * Tells which decoder is likely to decode faster, + * based on a set of pre-computed metrics. + * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 . + * Assumption : 0 < dstSize <= 128 KB */ +U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize); + +/** + * The minimum workspace size for the `workSpace` used in + * HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp(). + * + * The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when + * HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15. + * Buffer overflow errors may potentially occur if code modifications result in + * a required workspace size greater than that specified in the following + * macro. + */ +#define HUF_DECOMPRESS_WORKSPACE_SIZE ((2 << 10) + (1 << 9)) +#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32)) + + +/* ====================== */ +/* single stream variants */ +/* ====================== */ + +size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags); +/** HUF_compress1X_repeat() : + * Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. + * If it uses hufTable it does not modify hufTable or repeat. + * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used. + * If preferRepeat then the old table will always be used if valid. + * If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */ +size_t HUF_compress1X_repeat(void* dst, size_t dstSize, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned tableLog, + void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */ + HUF_CElt* hufTable, HUF_repeat* repeat, int flags); + +size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags); +#ifndef HUF_FORCE_DECOMPRESS_X1 +size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags); /**< double-symbols decoder */ +#endif + +/* BMI2 variants. + * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0. + */ +size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags); +#ifndef HUF_FORCE_DECOMPRESS_X2 +size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags); +#endif +size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags); +size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags); +#ifndef HUF_FORCE_DECOMPRESS_X2 +size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags); +#endif +#ifndef HUF_FORCE_DECOMPRESS_X1 +size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags); +#endif #endif /* HUF_H_298734234 */ + +#if defined (__cplusplus) +} +#endif diff --git a/third_party/zstd/include/zstd/common/huf_static.h b/third_party/zstd/include/zstd/common/huf_static.h deleted file mode 100644 index 7701972e657..00000000000 --- a/third_party/zstd/include/zstd/common/huf_static.h +++ /dev/null @@ -1,238 +0,0 @@ -/* ****************************************************************** - * WARNING !! - * The following section contains advanced and experimental definitions - * which shall never be used in the context of a dynamic library, - * because they are not guaranteed to remain stable in the future. - * Only consider them in association with static linking. - * **************************************************************** */ -#ifndef HUF_H_HUF_STATIC_LINKING_ONLY -#define HUF_H_HUF_STATIC_LINKING_ONLY - -/* *** Dependencies *** */ -#include "zstd/common/mem.h" /* U32 */ - - -/* *** Constants *** */ -#define HUF_TABLELOG_MAX 12 /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */ -#define HUF_TABLELOG_DEFAULT 11 /* default tableLog value when none specified */ -#define HUF_SYMBOLVALUE_MAX 255 - -#define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ -#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX) -# error "HUF_TABLELOG_MAX is too large !" -#endif - - -/* **************************************** -* Static allocation -******************************************/ -/* HUF buffer bounds */ -#define HUF_CTABLEBOUND 129 -#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true when incompressible is pre-filtered with fast heuristic */ -#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ - -/* static allocation of HUF's Compression Table */ -#define HUF_CTABLE_SIZE_U32(maxSymbolValue) ((maxSymbolValue)+1) /* Use tables of U32, for proper alignment */ -#define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32)) -#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \ - U32 name##hb[HUF_CTABLE_SIZE_U32(maxSymbolValue)]; \ - void* name##hv = &(name##hb); \ - HUF_CElt* name = (HUF_CElt*)(name##hv) /* no final ; */ - -/* static allocation of HUF's DTable */ -typedef U32 HUF_DTable; -#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog))) -#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \ - HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) } -#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \ - HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) } - - -/* **************************************** -* Advanced decompression functions -******************************************/ -size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ -#ifndef HUF_FORCE_DECOMPRESS_X1 -size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ -#endif - -size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */ -size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */ -size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< considers RLE and uncompressed as errors */ -size_t HUF_decompress4X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ -size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */ -#ifndef HUF_FORCE_DECOMPRESS_X1 -size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ -size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */ -#endif - - -/* **************************************** - * HUF detailed API - * ****************************************/ - -/*! HUF_compress() does the following: - * 1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within "zstd/common/fse.h") - * 2. (optional) refine tableLog using HUF_optimalTableLog() - * 3. build Huffman table from count using HUF_buildCTable() - * 4. save Huffman table to memory buffer using HUF_writeCTable() - * 5. encode the data stream using HUF_compress4X_usingCTable() - * - * The following API allows targeting specific sub-functions for advanced tasks. - * For example, it's possible to compress several blocks using the same 'CTable', - * or to save and regenerate 'CTable' using external methods. - */ -unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue); -typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */ -size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */ -size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog); -size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); -size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); -int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); - -typedef enum { - HUF_repeat_none, /**< Cannot use the previous table */ - HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */ - HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */ - } HUF_repeat; -/** HUF_compress4X_repeat() : - * Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. - * If it uses hufTable it does not modify hufTable or repeat. - * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used. - * If preferRepeat then the old table will always be used if valid. */ -size_t HUF_compress4X_repeat(void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned tableLog, - void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */ - HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2); - -/** HUF_buildCTable_wksp() : - * Same as HUF_buildCTable(), but using externally allocated scratch buffer. - * `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE. - */ -#define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1) -#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned)) -size_t HUF_buildCTable_wksp (HUF_CElt* tree, - const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, - void* workSpace, size_t wkspSize); - -/*! HUF_readStats() : - * Read compact Huffman tree, saved by HUF_writeCTable(). - * `huffWeight` is destination buffer. - * @return : size read from `src` , or an error Code . - * Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */ -size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, - U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, - const void* src, size_t srcSize); - -/** HUF_readCTable() : - * Loading a CTable saved with HUF_writeCTable() */ -size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights); - -/** HUF_getNbBits() : - * Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX - * Note 1 : is not inlined, as HUF_CElt definition is private - * Note 2 : const void* used, so that it can provide a statically allocated table as argument (which uses type U32) */ -U32 HUF_getNbBits(const void* symbolTable, U32 symbolValue); - -/* - * HUF_decompress() does the following: - * 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics - * 2. build Huffman table from save, using HUF_readDTableX?() - * 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable() - */ - -/** HUF_selectDecoder() : - * Tells which decoder is likely to decode faster, - * based on a set of pre-computed metrics. - * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 . - * Assumption : 0 < dstSize <= 128 KB */ -U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize); - -/** - * The minimum workspace size for the `workSpace` used in - * HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp(). - * - * The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when - * HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15. - * Buffer overflow errors may potentially occur if code modifications result in - * a required workspace size greater than that specified in the following - * macro. - */ -#define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10) -#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32)) - -#ifndef HUF_FORCE_DECOMPRESS_X2 -size_t HUF_readDTableX1 (HUF_DTable* DTable, const void* src, size_t srcSize); -size_t HUF_readDTableX1_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize); -#endif -#ifndef HUF_FORCE_DECOMPRESS_X1 -size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize); -size_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize); -#endif - -size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); -#ifndef HUF_FORCE_DECOMPRESS_X2 -size_t HUF_decompress4X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); -#endif -#ifndef HUF_FORCE_DECOMPRESS_X1 -size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); -#endif - - -/* ====================== */ -/* single stream variants */ -/* ====================== */ - -size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog); -size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ -size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); -/** HUF_compress1X_repeat() : - * Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. - * If it uses hufTable it does not modify hufTable or repeat. - * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used. - * If preferRepeat then the old table will always be used if valid. */ -size_t HUF_compress1X_repeat(void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned tableLog, - void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */ - HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2); - -size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */ -#ifndef HUF_FORCE_DECOMPRESS_X1 -size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */ -#endif - -size_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); -size_t HUF_decompress1X_DCtx_wksp (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); -#ifndef HUF_FORCE_DECOMPRESS_X2 -size_t HUF_decompress1X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ -size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */ -#endif -#ifndef HUF_FORCE_DECOMPRESS_X1 -size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ -size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */ -#endif - -size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */ -#ifndef HUF_FORCE_DECOMPRESS_X2 -size_t HUF_decompress1X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); -#endif -#ifndef HUF_FORCE_DECOMPRESS_X1 -size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); -#endif - -/* BMI2 variants. - * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0. - */ -size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2); -#ifndef HUF_FORCE_DECOMPRESS_X2 -size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2); -#endif -size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2); -size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2); - -} - -#endif /* HUF_STATIC_LINKING_ONLY */ - diff --git a/third_party/zstd/include/zstd/common/mem.h b/third_party/zstd/include/zstd/common/mem.h index 7c7b1f32d7f..096f4be519d 100644 --- a/third_party/zstd/include/zstd/common/mem.h +++ b/third_party/zstd/include/zstd/common/mem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,11 +11,17 @@ #ifndef MEM_H_MODULE #define MEM_H_MODULE +#if defined (__cplusplus) +extern "C" { +#endif + /*-**************************************** * Dependencies ******************************************/ -#include /* size_t, ptrdiff_t */ -#include /* memcpy */ +#include /* size_t, ptrdiff_t */ +#include "compiler.h" /* __has_builtin */ +#include "debug.h" /* DEBUG_STATIC_ASSERT */ +#include "zstd_deps.h" /* ZSTD_memcpy */ /*-**************************************** @@ -25,37 +31,19 @@ # include /* _byteswap_ulong */ # include /* _byteswap_* */ #endif -#if defined(__GNUC__) -# define MEM_STATIC static __inline __attribute__((unused)) -#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -# define MEM_STATIC static inline -#elif defined(_MSC_VER) -# define MEM_STATIC static __inline -#else -# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ -#endif - -#ifndef __has_builtin -# define __has_builtin(x) 0 /* compat. with non-clang compilers */ -#endif - -/* code only tested on 32 and 64 bits systems */ -#define MEM_STATIC_ASSERT(c) { enum { MEM_static_assert = 1/(int)(!!(c)) }; } -MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); } - -/* detects whether we are being compiled under msan */ -#if defined (__has_feature) -# if __has_feature(memory_sanitizer) -# define MEMORY_SANITIZER 1 -# endif -#endif /*-************************************************************** * Basic Types *****************************************************************/ #if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include +# if defined(_AIX) +# include +# else +# include /* intptr_t */ +# endif typedef uint8_t BYTE; + typedef uint8_t U8; + typedef int8_t S8; typedef uint16_t U16; typedef int16_t S16; typedef uint32_t U32; @@ -68,6 +56,8 @@ MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (size # error "this implementation requires char to be exactly 8-bit type" #endif typedef unsigned char BYTE; + typedef unsigned char U8; + typedef signed char S8; #if USHRT_MAX != 65535 # error "this implementation requires short to be exactly 16-bit type" #endif @@ -84,28 +74,65 @@ MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (size typedef signed long long S64; #endif -namespace duckdb_zstd { /*-************************************************************** -* Memory I/O +* Memory I/O API +*****************************************************************/ +/*=== Static platform detection ===*/ +MEM_STATIC unsigned MEM_32bits(void); +MEM_STATIC unsigned MEM_64bits(void); +MEM_STATIC unsigned MEM_isLittleEndian(void); + +/*=== Native unaligned read/write ===*/ +MEM_STATIC U16 MEM_read16(const void* memPtr); +MEM_STATIC U32 MEM_read32(const void* memPtr); +MEM_STATIC U64 MEM_read64(const void* memPtr); +MEM_STATIC size_t MEM_readST(const void* memPtr); + +MEM_STATIC void MEM_write16(void* memPtr, U16 value); +MEM_STATIC void MEM_write32(void* memPtr, U32 value); +MEM_STATIC void MEM_write64(void* memPtr, U64 value); + +/*=== Little endian unaligned read/write ===*/ +MEM_STATIC U16 MEM_readLE16(const void* memPtr); +MEM_STATIC U32 MEM_readLE24(const void* memPtr); +MEM_STATIC U32 MEM_readLE32(const void* memPtr); +MEM_STATIC U64 MEM_readLE64(const void* memPtr); +MEM_STATIC size_t MEM_readLEST(const void* memPtr); + +MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val); +MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val); +MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32); +MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64); +MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val); + +/*=== Big endian unaligned read/write ===*/ +MEM_STATIC U32 MEM_readBE32(const void* memPtr); +MEM_STATIC U64 MEM_readBE64(const void* memPtr); +MEM_STATIC size_t MEM_readBEST(const void* memPtr); + +MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32); +MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64); +MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val); + +/*=== Byteswap ===*/ +MEM_STATIC U32 MEM_swap32(U32 in); +MEM_STATIC U64 MEM_swap64(U64 in); +MEM_STATIC size_t MEM_swapST(size_t in); + + +/*-************************************************************** +* Memory I/O Implementation *****************************************************************/ -/* MEM_FORCE_MEMORY_ACCESS : - * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. - * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. - * The below switch allow to select different access method for improved performance. - * Method 0 (default) : use `memcpy()`. Safe and portable. - * Method 1 : `__packed` statement. It depends on compiler extension (i.e., not portable). - * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. +/* MEM_FORCE_MEMORY_ACCESS : For accessing unaligned memory: + * Method 0 : always use `memcpy()`. Safe and portable. + * Method 1 : Use compiler extension to set unaligned access. * Method 2 : direct access. This method is portable but violate C standard. * It can generate buggy code on targets depending on alignment. - * In some circumstances, it's the only known way to get the most performance (i.e. GCC + ARMv6) - * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. - * Prefer these methods in priority order (0 > 1 > 2) + * Default : method 1 if supported, else method 0 */ #ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ -# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) -# define MEM_FORCE_MEMORY_ACCESS 2 -# elif defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__) +# ifdef __GNUC__ # define MEM_FORCE_MEMORY_ACCESS 1 # endif #endif @@ -115,8 +142,22 @@ MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; } MEM_STATIC unsigned MEM_isLittleEndian(void) { +#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + return 1; +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + return 0; +#elif defined(__clang__) && __LITTLE_ENDIAN__ + return 1; +#elif defined(__clang__) && __BIG_ENDIAN__ + return 0; +#elif defined(_MSC_VER) && (_M_AMD64 || _M_IX86) + return 1; +#elif defined(__DMC__) && defined(_M_IX86) + return 1; +#else const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ return one.c[0]; +#endif } #if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2) @@ -134,30 +175,19 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; } #elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1) -/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ -/* currently only defined for gcc and icc */ -#if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32)) - __pragma( pack(push, 1) ) - typedef struct { U16 v; } unalign16; - typedef struct { U32 v; } unalign32; - typedef struct { U64 v; } unalign64; - typedef struct { size_t v; } unalignArch; - __pragma( pack(pop) ) -#else - typedef struct { U16 v; } __attribute__((packed)) unalign16; - typedef struct { U32 v; } __attribute__((packed)) unalign32; - typedef struct { U64 v; } __attribute__((packed)) unalign64; - typedef struct { size_t v; } __attribute__((packed)) unalignArch; -#endif +typedef __attribute__((aligned(1))) U16 unalign16; +typedef __attribute__((aligned(1))) U32 unalign32; +typedef __attribute__((aligned(1))) U64 unalign64; +typedef __attribute__((aligned(1))) size_t unalignArch; -MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign16*)ptr)->v; } -MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign32*)ptr)->v; } -MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign64*)ptr)->v; } -MEM_STATIC size_t MEM_readST(const void* ptr) { return ((const unalignArch*)ptr)->v; } +MEM_STATIC U16 MEM_read16(const void* ptr) { return *(const unalign16*)ptr; } +MEM_STATIC U32 MEM_read32(const void* ptr) { return *(const unalign32*)ptr; } +MEM_STATIC U64 MEM_read64(const void* ptr) { return *(const unalign64*)ptr; } +MEM_STATIC size_t MEM_readST(const void* ptr) { return *(const unalignArch*)ptr; } -MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign16*)memPtr)->v = value; } -MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign32*)memPtr)->v = value; } -MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign64*)memPtr)->v = value; } +MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(unalign16*)memPtr = value; } +MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(unalign32*)memPtr = value; } +MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(unalign64*)memPtr = value; } #else @@ -166,41 +196,49 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign64*)memPtr)->v = MEM_STATIC U16 MEM_read16(const void* memPtr) { - U16 val; memcpy(&val, memPtr, sizeof(val)); return val; + U16 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC U32 MEM_read32(const void* memPtr) { - U32 val; memcpy(&val, memPtr, sizeof(val)); return val; + U32 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC U64 MEM_read64(const void* memPtr) { - U64 val; memcpy(&val, memPtr, sizeof(val)); return val; + U64 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC size_t MEM_readST(const void* memPtr) { - size_t val; memcpy(&val, memPtr, sizeof(val)); return val; + size_t val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC void MEM_write16(void* memPtr, U16 value) { - memcpy(memPtr, &value, sizeof(value)); + ZSTD_memcpy(memPtr, &value, sizeof(value)); } MEM_STATIC void MEM_write32(void* memPtr, U32 value) { - memcpy(memPtr, &value, sizeof(value)); + ZSTD_memcpy(memPtr, &value, sizeof(value)); } MEM_STATIC void MEM_write64(void* memPtr, U64 value) { - memcpy(memPtr, &value, sizeof(value)); + ZSTD_memcpy(memPtr, &value, sizeof(value)); } #endif /* MEM_FORCE_MEMORY_ACCESS */ +MEM_STATIC U32 MEM_swap32_fallback(U32 in) +{ + return ((in << 24) & 0xff000000 ) | + ((in << 8) & 0x00ff0000 ) | + ((in >> 8) & 0x0000ff00 ) | + ((in >> 24) & 0x000000ff ); +} + MEM_STATIC U32 MEM_swap32(U32 in) { #if defined(_MSC_VER) /* Visual Studio */ @@ -209,22 +247,13 @@ MEM_STATIC U32 MEM_swap32(U32 in) || (defined(__clang__) && __has_builtin(__builtin_bswap32)) return __builtin_bswap32(in); #else - return ((in << 24) & 0xff000000 ) | - ((in << 8) & 0x00ff0000 ) | - ((in >> 8) & 0x0000ff00 ) | - ((in >> 24) & 0x000000ff ); + return MEM_swap32_fallback(in); #endif } -MEM_STATIC U64 MEM_swap64(U64 in) +MEM_STATIC U64 MEM_swap64_fallback(U64 in) { -#if defined(_MSC_VER) /* Visual Studio */ - return _byteswap_uint64(in); -#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \ - || (defined(__clang__) && __has_builtin(__builtin_bswap64)) - return __builtin_bswap64(in); -#else - return ((in << 56) & 0xff00000000000000ULL) | + return ((in << 56) & 0xff00000000000000ULL) | ((in << 40) & 0x00ff000000000000ULL) | ((in << 24) & 0x0000ff0000000000ULL) | ((in << 8) & 0x000000ff00000000ULL) | @@ -232,6 +261,17 @@ MEM_STATIC U64 MEM_swap64(U64 in) ((in >> 24) & 0x0000000000ff0000ULL) | ((in >> 40) & 0x000000000000ff00ULL) | ((in >> 56) & 0x00000000000000ffULL); +} + +MEM_STATIC U64 MEM_swap64(U64 in) +{ +#if defined(_MSC_VER) /* Visual Studio */ + return _byteswap_uint64(in); +#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \ + || (defined(__clang__) && __has_builtin(__builtin_bswap64)) + return __builtin_bswap64(in); +#else + return MEM_swap64_fallback(in); #endif } @@ -268,7 +308,7 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) MEM_STATIC U32 MEM_readLE24(const void* memPtr) { - return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); + return (U32)MEM_readLE16(memPtr) + ((U32)(((const BYTE*)memPtr)[2]) << 16); } MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val) @@ -375,6 +415,12 @@ MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val) MEM_writeBE64(memPtr, (U64)val); } +/* code only tested on 32 and 64 bits systems */ +MEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); } + + +#if defined (__cplusplus) } +#endif #endif /* MEM_H_MODULE */ diff --git a/third_party/zstd/include/zstd/common/pool.h b/third_party/zstd/include/zstd/common/pool.h new file mode 100644 index 00000000000..cca4de73a83 --- /dev/null +++ b/third_party/zstd/include/zstd/common/pool.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef POOL_H +#define POOL_H + +#if defined (__cplusplus) +extern "C" { +#endif + + +#include "zstd_deps.h" +#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_customMem */ +#include "../zstd.h" + +typedef struct POOL_ctx_s POOL_ctx; + +/*! POOL_create() : + * Create a thread pool with at most `numThreads` threads. + * `numThreads` must be at least 1. + * The maximum number of queued jobs before blocking is `queueSize`. + * @return : POOL_ctx pointer on success, else NULL. +*/ +POOL_ctx* POOL_create(size_t numThreads, size_t queueSize); + +POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, + ZSTD_customMem customMem); + +/*! POOL_free() : + * Free a thread pool returned by POOL_create(). + */ +void POOL_free(POOL_ctx* ctx); + + +/*! POOL_joinJobs() : + * Waits for all queued jobs to finish executing. + */ +void POOL_joinJobs(POOL_ctx* ctx); + +/*! POOL_resize() : + * Expands or shrinks pool's number of threads. + * This is more efficient than releasing + creating a new context, + * since it tries to preserve and reuse existing threads. + * `numThreads` must be at least 1. + * @return : 0 when resize was successful, + * !0 (typically 1) if there is an error. + * note : only numThreads can be resized, queueSize remains unchanged. + */ +int POOL_resize(POOL_ctx* ctx, size_t numThreads); + +/*! POOL_sizeof() : + * @return threadpool memory usage + * note : compatible with NULL (returns 0 in this case) + */ +size_t POOL_sizeof(const POOL_ctx* ctx); + +/*! POOL_function : + * The function type that can be added to a thread pool. + */ +typedef void (*POOL_function)(void*); + +/*! POOL_add() : + * Add the job `function(opaque)` to the thread pool. `ctx` must be valid. + * Possibly blocks until there is room in the queue. + * Note : The function may be executed asynchronously, + * therefore, `opaque` must live until function has been completed. + */ +void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque); + + +/*! POOL_tryAdd() : + * Add the job `function(opaque)` to thread pool _if_ a queue slot is available. + * Returns immediately even if not (does not block). + * @return : 1 if successful, 0 if not. + */ +int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque); + + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/third_party/zstd/include/zstd/common/portability_macros.h b/third_party/zstd/include/zstd/common/portability_macros.h new file mode 100644 index 00000000000..e50314a78e4 --- /dev/null +++ b/third_party/zstd/include/zstd/common/portability_macros.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_PORTABILITY_MACROS_H +#define ZSTD_PORTABILITY_MACROS_H + +/** + * This header file contains macro definitions to support portability. + * This header is shared between C and ASM code, so it MUST only + * contain macro definitions. It MUST not contain any C code. + * + * This header ONLY defines macros to detect platforms/feature support. + * + */ + + +/* compat. with non-clang compilers */ +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif + +/* compat. with non-clang compilers */ +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +/* compat. with non-clang compilers */ +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + +/* detects whether we are being compiled under msan */ +#ifndef ZSTD_MEMORY_SANITIZER +# if __has_feature(memory_sanitizer) +# define ZSTD_MEMORY_SANITIZER 1 +# else +# define ZSTD_MEMORY_SANITIZER 0 +# endif +#endif + +/* detects whether we are being compiled under asan */ +#ifndef ZSTD_ADDRESS_SANITIZER +# if __has_feature(address_sanitizer) +# define ZSTD_ADDRESS_SANITIZER 1 +# elif defined(__SANITIZE_ADDRESS__) +# define ZSTD_ADDRESS_SANITIZER 1 +# else +# define ZSTD_ADDRESS_SANITIZER 0 +# endif +#endif + +/* detects whether we are being compiled under dfsan */ +#ifndef ZSTD_DATAFLOW_SANITIZER +# if __has_feature(dataflow_sanitizer) +# define ZSTD_DATAFLOW_SANITIZER 1 +# else +# define ZSTD_DATAFLOW_SANITIZER 0 +# endif +#endif + +/* Mark the internal assembly functions as hidden */ +#ifdef __ELF__ +# define ZSTD_HIDE_ASM_FUNCTION(func) .hidden func +#elif defined(__APPLE__) +# define ZSTD_HIDE_ASM_FUNCTION(func) .private_extern func +#else +# define ZSTD_HIDE_ASM_FUNCTION(func) +#endif + +/* Enable runtime BMI2 dispatch based on the CPU. + * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default. + */ +#ifndef DYNAMIC_BMI2 + #if ((defined(__clang__) && __has_attribute(__target__)) \ + || (defined(__GNUC__) \ + && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \ + && (defined(__x86_64__) || defined(_M_X64)) \ + && !defined(__BMI2__) + # define DYNAMIC_BMI2 1 + #else + # define DYNAMIC_BMI2 0 + #endif +#endif + +/** + * Only enable assembly for GNUC compatible compilers, + * because other platforms may not support GAS assembly syntax. + * + * Only enable assembly for Linux / MacOS, other platforms may + * work, but they haven't been tested. This could likely be + * extended to BSD systems. + * + * Disable assembly when MSAN is enabled, because MSAN requires + * 100% of code to be instrumented to work. + */ +#if defined(__GNUC__) +# if defined(__linux__) || defined(__linux) || defined(__APPLE__) +# if ZSTD_MEMORY_SANITIZER +# define ZSTD_ASM_SUPPORTED 0 +# elif ZSTD_DATAFLOW_SANITIZER +# define ZSTD_ASM_SUPPORTED 0 +# else +# define ZSTD_ASM_SUPPORTED 1 +# endif +# else +# define ZSTD_ASM_SUPPORTED 0 +# endif +#else +# define ZSTD_ASM_SUPPORTED 0 +#endif + +/** + * Determines whether we should enable assembly for x86-64 + * with BMI2. + * + * Enable if all of the following conditions hold: + * - ASM hasn't been explicitly disabled by defining ZSTD_DISABLE_ASM + * - Assembly is supported + * - We are compiling for x86-64 and either: + * - DYNAMIC_BMI2 is enabled + * - BMI2 is supported at compile time + */ +#if !defined(ZSTD_DISABLE_ASM) && \ + ZSTD_ASM_SUPPORTED && \ + defined(__x86_64__) && \ + (DYNAMIC_BMI2 || defined(__BMI2__)) +# define ZSTD_ENABLE_ASM_X86_64_BMI2 1 +#else +# define ZSTD_ENABLE_ASM_X86_64_BMI2 0 +#endif + +/* + * For x86 ELF targets, add .note.gnu.property section for Intel CET in + * assembly sources when CET is enabled. + * + * Additionally, any function that may be called indirectly must begin + * with ZSTD_CET_ENDBRANCH. + */ +#if defined(__ELF__) && (defined(__x86_64__) || defined(__i386__)) \ + && defined(__has_include) +# if __has_include() +# include +# define ZSTD_CET_ENDBRANCH _CET_ENDBR +# endif +#endif + +#ifndef ZSTD_CET_ENDBRANCH +# define ZSTD_CET_ENDBRANCH +#endif + +#endif /* ZSTD_PORTABILITY_MACROS_H */ diff --git a/third_party/zstd/include/zstd/common/threading.h b/third_party/zstd/include/zstd/common/threading.h new file mode 100644 index 00000000000..fb5c1c87873 --- /dev/null +++ b/third_party/zstd/include/zstd/common/threading.h @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2016 Tino Reichardt + * All rights reserved. + * + * You can contact the author at: + * - zstdmt source repository: https://github.com/mcmilk/zstdmt + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef THREADING_H_938743 +#define THREADING_H_938743 + +#include "debug.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#if defined(ZSTD_MULTITHREAD) && defined(_WIN32) + +/** + * Windows minimalist Pthread Wrapper + */ +#ifdef WINVER +# undef WINVER +#endif +#define WINVER 0x0600 + +#ifdef _WIN32_WINNT +# undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 + +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif + +#undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */ +#include +#undef ERROR +#define ERROR(name) ZSTD_ERROR(name) + + +/* mutex */ +#define ZSTD_pthread_mutex_t CRITICAL_SECTION +#define ZSTD_pthread_mutex_init(a, b) ((void)(b), InitializeCriticalSection((a)), 0) +#define ZSTD_pthread_mutex_destroy(a) DeleteCriticalSection((a)) +#define ZSTD_pthread_mutex_lock(a) EnterCriticalSection((a)) +#define ZSTD_pthread_mutex_unlock(a) LeaveCriticalSection((a)) + +/* condition variable */ +#define ZSTD_pthread_cond_t CONDITION_VARIABLE +#define ZSTD_pthread_cond_init(a, b) ((void)(b), InitializeConditionVariable((a)), 0) +#define ZSTD_pthread_cond_destroy(a) ((void)(a)) +#define ZSTD_pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE) +#define ZSTD_pthread_cond_signal(a) WakeConditionVariable((a)) +#define ZSTD_pthread_cond_broadcast(a) WakeAllConditionVariable((a)) + +/* ZSTD_pthread_create() and ZSTD_pthread_join() */ +typedef HANDLE ZSTD_pthread_t; + +int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused, + void* (*start_routine) (void*), void* arg); + +int ZSTD_pthread_join(ZSTD_pthread_t thread); + +/** + * add here more wrappers as required + */ + + +#elif defined(ZSTD_MULTITHREAD) /* posix assumed ; need a better detection method */ +/* === POSIX Systems === */ +# include + +#if DEBUGLEVEL < 1 + +#define ZSTD_pthread_mutex_t pthread_mutex_t +#define ZSTD_pthread_mutex_init(a, b) pthread_mutex_init((a), (b)) +#define ZSTD_pthread_mutex_destroy(a) pthread_mutex_destroy((a)) +#define ZSTD_pthread_mutex_lock(a) pthread_mutex_lock((a)) +#define ZSTD_pthread_mutex_unlock(a) pthread_mutex_unlock((a)) + +#define ZSTD_pthread_cond_t pthread_cond_t +#define ZSTD_pthread_cond_init(a, b) pthread_cond_init((a), (b)) +#define ZSTD_pthread_cond_destroy(a) pthread_cond_destroy((a)) +#define ZSTD_pthread_cond_wait(a, b) pthread_cond_wait((a), (b)) +#define ZSTD_pthread_cond_signal(a) pthread_cond_signal((a)) +#define ZSTD_pthread_cond_broadcast(a) pthread_cond_broadcast((a)) + +#define ZSTD_pthread_t pthread_t +#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d)) +#define ZSTD_pthread_join(a) pthread_join((a),NULL) + +#else /* DEBUGLEVEL >= 1 */ + +/* Debug implementation of threading. + * In this implementation we use pointers for mutexes and condition variables. + * This way, if we forget to init/destroy them the program will crash or ASAN + * will report leaks. + */ + +#define ZSTD_pthread_mutex_t pthread_mutex_t* +int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr); +int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex); +#define ZSTD_pthread_mutex_lock(a) pthread_mutex_lock(*(a)) +#define ZSTD_pthread_mutex_unlock(a) pthread_mutex_unlock(*(a)) + +#define ZSTD_pthread_cond_t pthread_cond_t* +int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr); +int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond); +#define ZSTD_pthread_cond_wait(a, b) pthread_cond_wait(*(a), *(b)) +#define ZSTD_pthread_cond_signal(a) pthread_cond_signal(*(a)) +#define ZSTD_pthread_cond_broadcast(a) pthread_cond_broadcast(*(a)) + +#define ZSTD_pthread_t pthread_t +#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d)) +#define ZSTD_pthread_join(a) pthread_join((a),NULL) + +#endif + +#else /* ZSTD_MULTITHREAD not defined */ +/* No multithreading support */ + +typedef int ZSTD_pthread_mutex_t; +#define ZSTD_pthread_mutex_init(a, b) ((void)(a), (void)(b), 0) +#define ZSTD_pthread_mutex_destroy(a) ((void)(a)) +#define ZSTD_pthread_mutex_lock(a) ((void)(a)) +#define ZSTD_pthread_mutex_unlock(a) ((void)(a)) + +typedef int ZSTD_pthread_cond_t; +#define ZSTD_pthread_cond_init(a, b) ((void)(a), (void)(b), 0) +#define ZSTD_pthread_cond_destroy(a) ((void)(a)) +#define ZSTD_pthread_cond_wait(a, b) ((void)(a), (void)(b)) +#define ZSTD_pthread_cond_signal(a) ((void)(a)) +#define ZSTD_pthread_cond_broadcast(a) ((void)(a)) + +/* do not use ZSTD_pthread_t */ + +#endif /* ZSTD_MULTITHREAD */ + +#if defined (__cplusplus) +} +#endif + +#endif /* THREADING_H_938743 */ diff --git a/third_party/zstd/include/zstd/common/xxhash.h b/third_party/zstd/include/zstd/common/xxhash.h index a6b7990c8bc..e59e44267c1 100644 --- a/third_party/zstd/include/zstd/common/xxhash.h +++ b/third_party/zstd/include/zstd/common/xxhash.h @@ -1,77 +1,323 @@ /* * xxHash - Extremely Fast Hash algorithm * Header File - * Copyright (c) 2012-2020, Yann Collet, Facebook, Inc. - * - * You can contact the author at : - * - xxHash source repository : https://github.com/Cyan4973/xxHash + * Copyright (c) Yann Collet - Meta Platforms, Inc * * This source code is licensed under both the BSD-style license (found in the * LICENSE file in the root directory of this source tree) and the GPLv2 (found * in the COPYING file in the root directory of this source tree). * You may select, at your option, one of the above-listed licenses. -*/ - -/* Notice extracted from xxHash homepage : - -xxHash is an extremely fast Hash algorithm, running at RAM speed limits. -It also successfully passes all tests from the SMHasher suite. - -Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) - -Name Speed Q.Score Author -xxHash 5.4 GB/s 10 -CrapWow 3.2 GB/s 2 Andrew -MumurHash 3a 2.7 GB/s 10 Austin Appleby -SpookyHash 2.0 GB/s 10 Bob Jenkins -SBox 1.4 GB/s 9 Bret Mulvey -Lookup3 1.2 GB/s 9 Bob Jenkins -SuperFastHash 1.2 GB/s 1 Paul Hsieh -CityHash64 1.05 GB/s 10 Pike & Alakuijala -FNV 0.55 GB/s 5 Fowler, Noll, Vo -CRC32 0.43 GB/s 9 -MD5-32 0.33 GB/s 10 Ronald L. Rivest -SHA1-32 0.28 GB/s 10 - -Q.Score is a measure of quality of the hash function. -It depends on successfully passing SMHasher test set. -10 is a perfect score. - -A 64-bits version, named XXH64, is available since r35. -It offers much better speed, but for 64-bits applications only. -Name Speed on 64 bits Speed on 32 bits -XXH64 13.8 GB/s 1.9 GB/s -XXH32 6.8 GB/s 6.0 GB/s -*/ + */ -#ifndef XXHASH_H_5627135585666179 -#define XXHASH_H_5627135585666179 1 +/* Local adaptations for Zstandard */ +#ifndef XXH_NO_XXH3 +# define XXH_NO_XXH3 +#endif -/* **************************** -* Definitions -******************************/ -#include /* size_t */ -namespace duckdb_zstd { -typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; +#ifndef XXH_NAMESPACE +# define XXH_NAMESPACE ZSTD_ +#endif + +/*! + * @mainpage xxHash + * + * xxHash is an extremely fast non-cryptographic hash algorithm, working at RAM speed + * limits. + * + * It is proposed in four flavors, in three families: + * 1. @ref XXH32_family + * - Classic 32-bit hash function. Simple, compact, and runs on almost all + * 32-bit and 64-bit systems. + * 2. @ref XXH64_family + * - Classic 64-bit adaptation of XXH32. Just as simple, and runs well on most + * 64-bit systems (but _not_ 32-bit systems). + * 3. @ref XXH3_family + * - Modern 64-bit and 128-bit hash function family which features improved + * strength and performance across the board, especially on smaller data. + * It benefits greatly from SIMD and 64-bit without requiring it. + * + * Benchmarks + * --- + * The reference system uses an Intel i7-9700K CPU, and runs Ubuntu x64 20.04. + * The open source benchmark program is compiled with clang v10.0 using -O3 flag. + * + * | Hash Name | ISA ext | Width | Large Data Speed | Small Data Velocity | + * | -------------------- | ------- | ----: | ---------------: | ------------------: | + * | XXH3_64bits() | @b AVX2 | 64 | 59.4 GB/s | 133.1 | + * | MeowHash | AES-NI | 128 | 58.2 GB/s | 52.5 | + * | XXH3_128bits() | @b AVX2 | 128 | 57.9 GB/s | 118.1 | + * | CLHash | PCLMUL | 64 | 37.1 GB/s | 58.1 | + * | XXH3_64bits() | @b SSE2 | 64 | 31.5 GB/s | 133.1 | + * | XXH3_128bits() | @b SSE2 | 128 | 29.6 GB/s | 118.1 | + * | RAM sequential read | | N/A | 28.0 GB/s | N/A | + * | ahash | AES-NI | 64 | 22.5 GB/s | 107.2 | + * | City64 | | 64 | 22.0 GB/s | 76.6 | + * | T1ha2 | | 64 | 22.0 GB/s | 99.0 | + * | City128 | | 128 | 21.7 GB/s | 57.7 | + * | FarmHash | AES-NI | 64 | 21.3 GB/s | 71.9 | + * | XXH64() | | 64 | 19.4 GB/s | 71.0 | + * | SpookyHash | | 64 | 19.3 GB/s | 53.2 | + * | Mum | | 64 | 18.0 GB/s | 67.0 | + * | CRC32C | SSE4.2 | 32 | 13.0 GB/s | 57.9 | + * | XXH32() | | 32 | 9.7 GB/s | 71.9 | + * | City32 | | 32 | 9.1 GB/s | 66.0 | + * | Blake3* | @b AVX2 | 256 | 4.4 GB/s | 8.1 | + * | Murmur3 | | 32 | 3.9 GB/s | 56.1 | + * | SipHash* | | 64 | 3.0 GB/s | 43.2 | + * | Blake3* | @b SSE2 | 256 | 2.4 GB/s | 8.1 | + * | HighwayHash | | 64 | 1.4 GB/s | 6.0 | + * | FNV64 | | 64 | 1.2 GB/s | 62.7 | + * | Blake2* | | 256 | 1.1 GB/s | 5.1 | + * | SHA1* | | 160 | 0.8 GB/s | 5.6 | + * | MD5* | | 128 | 0.6 GB/s | 7.8 | + * @note + * - Hashes which require a specific ISA extension are noted. SSE2 is also noted, + * even though it is mandatory on x64. + * - Hashes with an asterisk are cryptographic. Note that MD5 is non-cryptographic + * by modern standards. + * - Small data velocity is a rough average of algorithm's efficiency for small + * data. For more accurate information, see the wiki. + * - More benchmarks and strength tests are found on the wiki: + * https://github.com/Cyan4973/xxHash/wiki + * + * Usage + * ------ + * All xxHash variants use a similar API. Changing the algorithm is a trivial + * substitution. + * + * @pre + * For functions which take an input and length parameter, the following + * requirements are assumed: + * - The range from [`input`, `input + length`) is valid, readable memory. + * - The only exception is if the `length` is `0`, `input` may be `NULL`. + * - For C++, the objects must have the *TriviallyCopyable* property, as the + * functions access bytes directly as if it was an array of `unsigned char`. + * + * @anchor single_shot_example + * **Single Shot** + * + * These functions are stateless functions which hash a contiguous block of memory, + * immediately returning the result. They are the easiest and usually the fastest + * option. + * + * XXH32(), XXH64(), XXH3_64bits(), XXH3_128bits() + * + * @code{.c} + * #include + * #include "xxhash.h" + * + * // Example for a function which hashes a null terminated string with XXH32(). + * XXH32_hash_t hash_string(const char* string, XXH32_hash_t seed) + * { + * // NULL pointers are only valid if the length is zero + * size_t length = (string == NULL) ? 0 : strlen(string); + * return XXH32(string, length, seed); + * } + * @endcode + * + * + * @anchor streaming_example + * **Streaming** + * + * These groups of functions allow incremental hashing of unknown size, even + * more than what would fit in a size_t. + * + * XXH32_reset(), XXH64_reset(), XXH3_64bits_reset(), XXH3_128bits_reset() + * + * @code{.c} + * #include + * #include + * #include "xxhash.h" + * // Example for a function which hashes a FILE incrementally with XXH3_64bits(). + * XXH64_hash_t hashFile(FILE* f) + * { + * // Allocate a state struct. Do not just use malloc() or new. + * XXH3_state_t* state = XXH3_createState(); + * assert(state != NULL && "Out of memory!"); + * // Reset the state to start a new hashing session. + * XXH3_64bits_reset(state); + * char buffer[4096]; + * size_t count; + * // Read the file in chunks + * while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0) { + * // Run update() as many times as necessary to process the data + * XXH3_64bits_update(state, buffer, count); + * } + * // Retrieve the finalized hash. This will not change the state. + * XXH64_hash_t result = XXH3_64bits_digest(state); + * // Free the state. Do not use free(). + * XXH3_freeState(state); + * return result; + * } + * @endcode + * + * Streaming functions generate the xxHash value from an incremental input. + * This method is slower than single-call functions, due to state management. + * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. + * + * An XXH state must first be allocated using `XXH*_createState()`. + * + * Start a new hash by initializing the state with a seed using `XXH*_reset()`. + * + * Then, feed the hash state by calling `XXH*_update()` as many times as necessary. + * + * The function returns an error code, with 0 meaning OK, and any other value + * meaning there is an error. + * + * Finally, a hash value can be produced anytime, by using `XXH*_digest()`. + * This function returns the nn-bits hash as an int or long long. + * + * It's still possible to continue inserting input into the hash state after a + * digest, and generate new hash values later on by invoking `XXH*_digest()`. + * + * When done, release the state using `XXH*_freeState()`. + * + * + * @anchor canonical_representation_example + * **Canonical Representation** + * + * The default return values from XXH functions are unsigned 32, 64 and 128 bit + * integers. + * This the simplest and fastest format for further post-processing. + * + * However, this leaves open the question of what is the order on the byte level, + * since little and big endian conventions will store the same number differently. + * + * The canonical representation settles this issue by mandating big-endian + * convention, the same convention as human-readable numbers (large digits first). + * + * When writing hash values to storage, sending them over a network, or printing + * them, it's highly recommended to use the canonical representation to ensure + * portability across a wider range of systems, present and future. + * + * The following functions allow transformation of hash values to and from + * canonical format. + * + * XXH32_canonicalFromHash(), XXH32_hashFromCanonical(), + * XXH64_canonicalFromHash(), XXH64_hashFromCanonical(), + * XXH128_canonicalFromHash(), XXH128_hashFromCanonical(), + * + * @code{.c} + * #include + * #include "xxhash.h" + * + * // Example for a function which prints XXH32_hash_t in human readable format + * void printXxh32(XXH32_hash_t hash) + * { + * XXH32_canonical_t cano; + * XXH32_canonicalFromHash(&cano, hash); + * size_t i; + * for(i = 0; i < sizeof(cano.digest); ++i) { + * printf("%02x", cano.digest[i]); + * } + * printf("\n"); + * } + * + * // Example for a function which converts XXH32_canonical_t to XXH32_hash_t + * XXH32_hash_t convertCanonicalToXxh32(XXH32_canonical_t cano) + * { + * XXH32_hash_t hash = XXH32_hashFromCanonical(&cano); + * return hash; + * } + * @endcode + * + * + * @file xxhash.h + * xxHash prototypes and implementation + */ +#if defined (__cplusplus) +extern "C" { +#endif /* **************************** -* API modifier -******************************/ -/** XXH_PRIVATE_API -* This is useful if you want to include xxhash functions in `static` mode -* in order to inline them, and remove their symbol from the public list. -* Methodology : -* #define XXH_PRIVATE_API -* #include "zstd/common/xxhash.h" -* `xxhash.c` is automatically included. -* It's not useful to compile and link it as a separate module anymore. -*/ -#ifdef XXH_PRIVATE_API -# ifndef XXH_STATIC_LINKING_ONLY -# define XXH_STATIC_LINKING_ONLY -# endif + * INLINE mode + ******************************/ +/*! + * @defgroup public Public API + * Contains details on the public xxHash functions. + * @{ + */ +#ifdef XXH_DOXYGEN +/*! + * @brief Gives access to internal state declaration, required for static allocation. + * + * Incompatible with dynamic linking, due to risks of ABI changes. + * + * Usage: + * @code{.c} + * #define XXH_STATIC_LINKING_ONLY + * #include "xxhash.h" + * @endcode + */ +# define XXH_STATIC_LINKING_ONLY +/* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */ + +/*! + * @brief Gives access to internal definitions. + * + * Usage: + * @code{.c} + * #define XXH_STATIC_LINKING_ONLY + * #define XXH_IMPLEMENTATION + * #include "xxhash.h" + * @endcode + */ +# define XXH_IMPLEMENTATION +/* Do not undef XXH_IMPLEMENTATION for Doxygen */ + +/*! + * @brief Exposes the implementation and marks all functions as `inline`. + * + * Use these build macros to inline xxhash into the target unit. + * Inlining improves performance on small inputs, especially when the length is + * expressed as a compile-time constant: + * + * https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html + * + * It also keeps xxHash symbols private to the unit, so they are not exported. + * + * Usage: + * @code{.c} + * #define XXH_INLINE_ALL + * #include "xxhash.h" + * @endcode + * Do not compile and link xxhash.o as a separate object, as it is not useful. + */ +# define XXH_INLINE_ALL +# undef XXH_INLINE_ALL +/*! + * @brief Exposes the implementation without marking functions as inline. + */ +# define XXH_PRIVATE_API +# undef XXH_PRIVATE_API +/*! + * @brief Emulate a namespace by transparently prefixing all symbols. + * + * If you want to include _and expose_ xxHash functions from within your own + * library, but also want to avoid symbol collisions with other libraries which + * may also include xxHash, you can use @ref XXH_NAMESPACE to automatically prefix + * any public symbol from xxhash library with the value of @ref XXH_NAMESPACE + * (therefore, avoid empty or numeric values). + * + * Note that no change is required within the calling program as long as it + * includes `xxhash.h`: Regular symbol names will be automatically translated + * by this header. + */ +# define XXH_NAMESPACE /* YOUR NAME HERE */ +# undef XXH_NAMESPACE +#endif + +#if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \ + && !defined(XXH_INLINE_ALL_31684351384) + /* this section should be traversed only once */ +# define XXH_INLINE_ALL_31684351384 + /* give access to the advanced API, required to compile implementations */ +# undef XXH_STATIC_LINKING_ONLY /* avoid macro redef */ +# define XXH_STATIC_LINKING_ONLY + /* make all functions private */ +# undef XXH_PUBLIC_API # if defined(__GNUC__) # define XXH_PUBLIC_API static __inline __attribute__((unused)) # elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) @@ -79,157 +325,6696 @@ typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; # elif defined(_MSC_VER) # define XXH_PUBLIC_API static __inline # else -# define XXH_PUBLIC_API static /* this version may generate warnings for unused static functions; disable the relevant warning */ + /* note: this version may generate warnings for unused static functions */ +# define XXH_PUBLIC_API static # endif -#else -# define XXH_PUBLIC_API /* do nothing */ -#endif /* XXH_PRIVATE_API */ -/*!XXH_NAMESPACE, aka Namespace Emulation : + /* + * This part deals with the special case where a unit wants to inline xxHash, + * but "xxhash.h" has previously been included without XXH_INLINE_ALL, + * such as part of some previously included *.h header file. + * Without further action, the new include would just be ignored, + * and functions would effectively _not_ be inlined (silent failure). + * The following macros solve this situation by prefixing all inlined names, + * avoiding naming collision with previous inclusions. + */ + /* Before that, we unconditionally #undef all symbols, + * in case they were already defined with XXH_NAMESPACE. + * They will then be redefined for XXH_INLINE_ALL + */ +# undef XXH_versionNumber + /* XXH32 */ +# undef XXH32 +# undef XXH32_createState +# undef XXH32_freeState +# undef XXH32_reset +# undef XXH32_update +# undef XXH32_digest +# undef XXH32_copyState +# undef XXH32_canonicalFromHash +# undef XXH32_hashFromCanonical + /* XXH64 */ +# undef XXH64 +# undef XXH64_createState +# undef XXH64_freeState +# undef XXH64_reset +# undef XXH64_update +# undef XXH64_digest +# undef XXH64_copyState +# undef XXH64_canonicalFromHash +# undef XXH64_hashFromCanonical + /* XXH3_64bits */ +# undef XXH3_64bits +# undef XXH3_64bits_withSecret +# undef XXH3_64bits_withSeed +# undef XXH3_64bits_withSecretandSeed +# undef XXH3_createState +# undef XXH3_freeState +# undef XXH3_copyState +# undef XXH3_64bits_reset +# undef XXH3_64bits_reset_withSeed +# undef XXH3_64bits_reset_withSecret +# undef XXH3_64bits_update +# undef XXH3_64bits_digest +# undef XXH3_generateSecret + /* XXH3_128bits */ +# undef XXH128 +# undef XXH3_128bits +# undef XXH3_128bits_withSeed +# undef XXH3_128bits_withSecret +# undef XXH3_128bits_reset +# undef XXH3_128bits_reset_withSeed +# undef XXH3_128bits_reset_withSecret +# undef XXH3_128bits_reset_withSecretandSeed +# undef XXH3_128bits_update +# undef XXH3_128bits_digest +# undef XXH128_isEqual +# undef XXH128_cmp +# undef XXH128_canonicalFromHash +# undef XXH128_hashFromCanonical + /* Finally, free the namespace itself */ +# undef XXH_NAMESPACE -If you want to include _and expose_ xxHash functions from within your own library, -but also want to avoid symbol collisions with another library which also includes xxHash, + /* employ the namespace for XXH_INLINE_ALL */ +# define XXH_NAMESPACE XXH_INLINE_ + /* + * Some identifiers (enums, type names) are not symbols, + * but they must nonetheless be renamed to avoid redeclaration. + * Alternative solution: do not redeclare them. + * However, this requires some #ifdefs, and has a more dispersed impact. + * Meanwhile, renaming can be achieved in a single place. + */ +# define XXH_IPREF(Id) XXH_NAMESPACE ## Id +# define XXH_OK XXH_IPREF(XXH_OK) +# define XXH_ERROR XXH_IPREF(XXH_ERROR) +# define XXH_errorcode XXH_IPREF(XXH_errorcode) +# define XXH32_canonical_t XXH_IPREF(XXH32_canonical_t) +# define XXH64_canonical_t XXH_IPREF(XXH64_canonical_t) +# define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t) +# define XXH32_state_s XXH_IPREF(XXH32_state_s) +# define XXH32_state_t XXH_IPREF(XXH32_state_t) +# define XXH64_state_s XXH_IPREF(XXH64_state_s) +# define XXH64_state_t XXH_IPREF(XXH64_state_t) +# define XXH3_state_s XXH_IPREF(XXH3_state_s) +# define XXH3_state_t XXH_IPREF(XXH3_state_t) +# define XXH128_hash_t XXH_IPREF(XXH128_hash_t) + /* Ensure the header is parsed again, even if it was previously included */ +# undef XXHASH_H_5627135585666179 +# undef XXHASH_H_STATIC_13879238742 +#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ + +/* **************************************************************** + * Stable API + *****************************************************************/ +#ifndef XXHASH_H_5627135585666179 +#define XXHASH_H_5627135585666179 1 -you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library -with the value of XXH_NAMESPACE (so avoid to keep it NULL and avoid numeric values). +/*! @brief Marks a global symbol. */ +#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) +# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# ifdef XXH_EXPORT +# define XXH_PUBLIC_API __declspec(dllexport) +# elif XXH_IMPORT +# define XXH_PUBLIC_API __declspec(dllimport) +# endif +# else +# define XXH_PUBLIC_API /* do nothing */ +# endif +#endif -Note that no change is required within the calling program as long as it includes `xxhash.h` : -regular symbol name will be automatically translated by this header. -*/ #ifdef XXH_NAMESPACE # define XXH_CAT(A,B) A##B # define XXH_NAME2(A,B) XXH_CAT(A,B) -# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) -# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) # define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) +/* XXH32 */ +# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) # define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) -# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) # define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) -# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) # define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) -# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) # define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) -# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) # define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) -# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) # define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) -# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) # define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) -# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) # define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) +/* XXH64 */ +# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) +# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) +# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) +# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) +# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) +# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) +# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) +# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) # define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) +/* XXH3_64bits */ +# define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits) +# define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret) +# define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed) +# define XXH3_64bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecretandSeed) +# define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState) +# define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState) +# define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState) +# define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset) +# define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed) +# define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret) +# define XXH3_64bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecretandSeed) +# define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update) +# define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest) +# define XXH3_generateSecret XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret) +# define XXH3_generateSecret_fromSeed XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret_fromSeed) +/* XXH3_128bits */ +# define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128) +# define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits) +# define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed) +# define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret) +# define XXH3_128bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecretandSeed) +# define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset) +# define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed) +# define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret) +# define XXH3_128bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecretandSeed) +# define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update) +# define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest) +# define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual) +# define XXH128_cmp XXH_NAME2(XXH_NAMESPACE, XXH128_cmp) +# define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash) +# define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical) +#endif + + +/* ************************************* +* Compiler specifics +***************************************/ + +/* specific declaration modes for Windows */ +#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) +# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# ifdef XXH_EXPORT +# define XXH_PUBLIC_API __declspec(dllexport) +# elif XXH_IMPORT +# define XXH_PUBLIC_API __declspec(dllimport) +# endif +# else +# define XXH_PUBLIC_API /* do nothing */ +# endif #endif +#if defined (__GNUC__) +# define XXH_CONSTF __attribute__((const)) +# define XXH_PUREF __attribute__((pure)) +# define XXH_MALLOCF __attribute__((malloc)) +#else +# define XXH_CONSTF /* disable */ +# define XXH_PUREF +# define XXH_MALLOCF +#endif /* ************************************* * Version ***************************************/ #define XXH_VERSION_MAJOR 0 -#define XXH_VERSION_MINOR 6 +#define XXH_VERSION_MINOR 8 #define XXH_VERSION_RELEASE 2 +/*! @brief Version number, encoded as two digits each */ #define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) -XXH_PUBLIC_API unsigned XXH_versionNumber (void); + +/*! + * @brief Obtains the xxHash version. + * + * This is mostly useful when xxHash is compiled as a shared library, + * since the returned value comes from the library, as opposed to header file. + * + * @return @ref XXH_VERSION_NUMBER of the invoked library. + */ +XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void); /* **************************** -* Simple Hash Functions +* Common basic types ******************************/ -typedef unsigned int XXH32_hash_t; -typedef unsigned long long XXH64_hash_t; +#include /* size_t */ +/*! + * @brief Exit code for the streaming API. + */ +typedef enum { + XXH_OK = 0, /*!< OK */ + XXH_ERROR /*!< Error */ +} XXH_errorcode; -XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed); -XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed); +/*-********************************************************************** +* 32-bit hash +************************************************************************/ +#if defined(XXH_DOXYGEN) /* Don't show include */ /*! -XXH32() : - Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input". - The memory between input & input+length must be valid (allocated and read-accessible). - "seed" can be used to alter the result predictably. - Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s -XXH64() : - Calculate the 64-bits hash of sequence of length "len" stored at memory address "input". - "seed" can be used to alter the result predictably. - This function runs 2x faster on 64-bits systems, but slower on 32-bits systems (see benchmark). -*/ + * @brief An unsigned 32-bit integer. + * + * Not necessarily defined to `uint32_t` but functionally equivalent. + */ +typedef uint32_t XXH32_hash_t; +#elif !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# ifdef _AIX +# include +# else +# include +# endif + typedef uint32_t XXH32_hash_t; -/* **************************** -* Streaming Hash Functions -******************************/ -typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ -typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ +#else +# include +# if UINT_MAX == 0xFFFFFFFFUL + typedef unsigned int XXH32_hash_t; +# elif ULONG_MAX == 0xFFFFFFFFUL + typedef unsigned long XXH32_hash_t; +# else +# error "unsupported platform: need a 32-bit type" +# endif +#endif -/*! State allocation, compatible with dynamic libraries */ +/*! + * @} + * + * @defgroup XXH32_family XXH32 family + * @ingroup public + * Contains functions used in the classic 32-bit xxHash algorithm. + * + * @note + * XXH32 is useful for older platforms, with no or poor 64-bit performance. + * Note that the @ref XXH3_family provides competitive speed for both 32-bit + * and 64-bit systems, and offers true 64/128 bit hash results. + * + * @see @ref XXH64_family, @ref XXH3_family : Other xxHash families + * @see @ref XXH32_impl for implementation details + * @{ + */ -XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void); -XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); +/*! + * @brief Calculates the 32-bit hash of @p input using xxHash32. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 32-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 32-bit xxHash32 value. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed); -XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void); -XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); +#ifndef XXH_NO_STREAM +/*! + * @typedef struct XXH32_state_s XXH32_state_t + * @brief The opaque state struct for the XXH32 streaming API. + * + * @see XXH32_state_s for details. + */ +typedef struct XXH32_state_s XXH32_state_t; +/*! + * @brief Allocates an @ref XXH32_state_t. + * + * @return An allocated pointer of @ref XXH32_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH32_freeState(). + */ +XXH_PUBLIC_API XXH_MALLOCF XXH32_state_t* XXH32_createState(void); +/*! + * @brief Frees an @ref XXH32_state_t. + * + * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState(). + * + * @return @ref XXH_OK. + * + * @note @p statePtr must be allocated with XXH32_createState(). + * + */ +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); +/*! + * @brief Copies one @ref XXH32_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); -/* hash streaming */ +/*! + * @brief Resets an @ref XXH32_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 32-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note This function resets and seeds a state. Call it before @ref XXH32_update(). + */ +XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, XXH32_hash_t seed); -XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed); +/*! + * @brief Consumes a block of @p input to an @ref XXH32_state_t. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + */ XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); -XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); -XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); +/*! + * @brief Returns the calculated hash value from an @ref XXH32_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated 32-bit xxHash32 value from that state. + * + * @note + * Calling XXH32_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + */ +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ -/* -These functions generate the xxHash of an input provided in multiple segments. -Note that, for small input, they are slower than single-call functions, due to state management. -For small input, prefer `XXH32()` and `XXH64()` . +/******* Canonical representation *******/ -XXH state must first be allocated, using XXH*_createState() . +/*! + * @brief Canonical (big endian) representation of @ref XXH32_hash_t. + */ +typedef struct { + unsigned char digest[4]; /*!< Hash bytes, big endian */ +} XXH32_canonical_t; -Start a new hash by initializing state with a seed, using XXH*_reset(). +/*! + * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t. + * + * @param dst The @ref XXH32_canonical_t pointer to be stored to. + * @param hash The @ref XXH32_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); -Then, feed the hash state by calling XXH*_update() as many times as necessary. -Obviously, input must be allocated and read accessible. -The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. +/*! + * @brief Converts an @ref XXH32_canonical_t to a native @ref XXH32_hash_t. + * + * @param src The @ref XXH32_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); -Finally, a hash value can be produced anytime, by using XXH*_digest(). -This function returns the nn-bits hash as an int or long long. -It's still possible to continue inserting input into the hash state after a digest, -and generate some new hashes later on, by calling again XXH*_digest(). +/*! @cond Doxygen ignores this part */ +#ifdef __has_attribute +# define XXH_HAS_ATTRIBUTE(x) __has_attribute(x) +#else +# define XXH_HAS_ATTRIBUTE(x) 0 +#endif +/*! @endcond */ -When done, free XXH state space if it was allocated dynamically. -*/ +/*! @cond Doxygen ignores this part */ +/* + * C23 __STDC_VERSION__ number hasn't been specified yet. For now + * leave as `201711L` (C17 + 1). + * TODO: Update to correct value when its been specified. + */ +#define XXH_C23_VN 201711L +/*! @endcond */ +/*! @cond Doxygen ignores this part */ +/* C-language Attributes are added in C23. */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) && defined(__has_c_attribute) +# define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) +#else +# define XXH_HAS_C_ATTRIBUTE(x) 0 +#endif +/*! @endcond */ -/* ************************** -* Utils -****************************/ -#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* ! C99 */ -# define __restrict /* disable restrict */ +/*! @cond Doxygen ignores this part */ +#if defined(__cplusplus) && defined(__has_cpp_attribute) +# define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define XXH_HAS_CPP_ATTRIBUTE(x) 0 #endif +/*! @endcond */ -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* __restrict dst_state, const XXH32_state_t* __restrict src_state); -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* __restrict dst_state, const XXH64_state_t* __restrict src_state); +/*! @cond Doxygen ignores this part */ +/* + * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute + * introduced in CPP17 and C23. + * CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough + * C23 : https://en.cppreference.com/w/c/language/attributes/fallthrough + */ +#if XXH_HAS_C_ATTRIBUTE(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough) +# define XXH_FALLTHROUGH [[fallthrough]] +#elif XXH_HAS_ATTRIBUTE(__fallthrough__) +# define XXH_FALLTHROUGH __attribute__ ((__fallthrough__)) +#else +# define XXH_FALLTHROUGH /* fallthrough */ +#endif +/*! @endcond */ +/*! @cond Doxygen ignores this part */ +/* + * Define XXH_NOESCAPE for annotated pointers in public API. + * https://clang.llvm.org/docs/AttributeReference.html#noescape + * As of writing this, only supported by clang. + */ +#if XXH_HAS_ATTRIBUTE(noescape) +# define XXH_NOESCAPE __attribute__((noescape)) +#else +# define XXH_NOESCAPE +#endif +/*! @endcond */ -/* ************************** -* Canonical representation -****************************/ -/* Default result type for XXH functions are primitive unsigned 32 and 64 bits. -* The canonical representation uses human-readable write convention, aka big-endian (large digits first). -* These functions allow transformation of hash result into and from its canonical format. -* This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. -*/ -typedef struct { unsigned char digest[4]; } XXH32_canonical_t; -typedef struct { unsigned char digest[8]; } XXH64_canonical_t; -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); +/*! + * @} + * @ingroup public + * @{ + */ -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); +#ifndef XXH_NO_LONG_LONG +/*-********************************************************************** +* 64-bit hash +************************************************************************/ +#if defined(XXH_DOXYGEN) /* don't include */ +/*! + * @brief An unsigned 64-bit integer. + * + * Not necessarily defined to `uint64_t` but functionally equivalent. + */ +typedef uint64_t XXH64_hash_t; +#elif !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# ifdef _AIX +# include +# else +# include +# endif + typedef uint64_t XXH64_hash_t; +#else +# include +# if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL + /* LP64 ABI says uint64_t is unsigned long */ + typedef unsigned long XXH64_hash_t; +# else + /* the following type must have a width of 64-bit */ + typedef unsigned long long XXH64_hash_t; +# endif +#endif -} +/*! + * @} + * + * @defgroup XXH64_family XXH64 family + * @ingroup public + * @{ + * Contains functions used in the classic 64-bit xxHash algorithm. + * + * @note + * XXH3 provides competitive speed for both 32-bit and 64-bit systems, + * and offers true 64/128 bit hash results. + * It provides better speed for systems with vector processing capabilities. + */ -#endif /* XXHASH_H_5627135585666179 */ +/*! + * @brief Calculates the 64-bit hash of @p input using xxHash64. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 64-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit xxHash64 value. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); + +/******* Streaming *******/ +#ifndef XXH_NO_STREAM +/*! + * @brief The opaque state struct for the XXH64 streaming API. + * + * @see XXH64_state_s for details. + */ +typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ + +/*! + * @brief Allocates an @ref XXH64_state_t. + * + * @return An allocated pointer of @ref XXH64_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH64_freeState(). + */ +XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void); + +/*! + * @brief Frees an @ref XXH64_state_t. + * + * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState(). + * + * @return @ref XXH_OK. + * + * @note @p statePtr must be allocated with XXH64_createState(). + */ +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); + +/*! + * @brief Copies one @ref XXH64_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state); + +/*! + * @brief Resets an @ref XXH64_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note This function resets and seeds a state. Call it before @ref XXH64_update(). + */ +XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed); + +/*! + * @brief Consumes a block of @p input to an @ref XXH64_state_t. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + */ +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated hash value from an @ref XXH64_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated 64-bit xxHash64 value from that state. + * + * @note + * Calling XXH64_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ +/******* Canonical representation *******/ + +/*! + * @brief Canonical (big endian) representation of @ref XXH64_hash_t. + */ +typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t; + +/*! + * @brief Converts an @ref XXH64_hash_t to a big endian @ref XXH64_canonical_t. + * + * @param dst The @ref XXH64_canonical_t pointer to be stored to. + * @param hash The @ref XXH64_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash); + +/*! + * @brief Converts an @ref XXH64_canonical_t to a native @ref XXH64_hash_t. + * + * @param src The @ref XXH64_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src); + +#ifndef XXH_NO_XXH3 +/*! + * @} + * ************************************************************************ + * @defgroup XXH3_family XXH3 family + * @ingroup public + * @{ + * + * XXH3 is a more recent hash algorithm featuring: + * - Improved speed for both small and large inputs + * - True 64-bit and 128-bit outputs + * - SIMD acceleration + * - Improved 32-bit viability + * + * Speed analysis methodology is explained here: + * + * https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html + * + * Compared to XXH64, expect XXH3 to run approximately + * ~2x faster on large inputs and >3x faster on small ones, + * exact differences vary depending on platform. + * + * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic, + * but does not require it. + * Most 32-bit and 64-bit targets that can run XXH32 smoothly can run XXH3 + * at competitive speeds, even without vector support. Further details are + * explained in the implementation. + * + * XXH3 has a fast scalar implementation, but it also includes accelerated SIMD + * implementations for many common platforms: + * - AVX512 + * - AVX2 + * - SSE2 + * - ARM NEON + * - WebAssembly SIMD128 + * - POWER8 VSX + * - s390x ZVector + * This can be controlled via the @ref XXH_VECTOR macro, but it automatically + * selects the best version according to predefined macros. For the x86 family, an + * automatic runtime dispatcher is included separately in @ref xxh_x86dispatch.c. + * + * XXH3 implementation is portable: + * it has a generic C90 formulation that can be compiled on any platform, + * all implementations generate exactly the same hash value on all platforms. + * Starting from v0.8.0, it's also labelled "stable", meaning that + * any future version will also generate the same hash value. + * + * XXH3 offers 2 variants, _64bits and _128bits. + * + * When only 64 bits are needed, prefer invoking the _64bits variant, as it + * reduces the amount of mixing, resulting in faster speed on small inputs. + * It's also generally simpler to manipulate a scalar return type than a struct. + * + * The API supports one-shot hashing, streaming mode, and custom secrets. + */ +/*-********************************************************************** +* XXH3 64-bit variant +************************************************************************/ + +/*! + * @brief Calculates 64-bit unseeded variant of XXH3 hash of @p input. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @note + * This is equivalent to @ref XXH3_64bits_withSeed() with a seed of `0`, however + * it may have slightly better performance due to constant propagation of the + * defaults. + * + * @see + * XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Calculates 64-bit seeded variant of XXH3 hash of @p input. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @note + * seed == 0 produces the same results as @ref XXH3_64bits(). + * + * This variant generates a custom secret on the fly based on default secret + * altered using the @p seed value. + * + * While this operation is decently fast, note that it's not completely free. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); + +/*! + * The bare minimum size for a custom secret. + * + * @see + * XXH3_64bits_withSecret(), XXH3_64bits_reset_withSecret(), + * XXH3_128bits_withSecret(), XXH3_128bits_reset_withSecret(). + */ +#define XXH3_SECRET_SIZE_MIN 136 + +/*! + * @brief Calculates 64-bit variant of XXH3 with a custom "secret". + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @pre + * The memory between @p data and @p data + @p len must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p data may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * It's possible to provide any blob of bytes as a "secret" to generate the hash. + * This makes it more difficult for an external actor to prepare an intentional collision. + * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN). + * However, the quality of the secret impacts the dispersion of the hash algorithm. + * Therefore, the secret _must_ look like a bunch of random bytes. + * Avoid "trivial" or structured data such as repeated sequences or a text document. + * Whenever in doubt about the "randomness" of the blob of bytes, + * consider employing @ref XXH3_generateSecret() instead (see below). + * It will generate a proper high entropy secret derived from the blob of bytes. + * Another advantage of using XXH3_generateSecret() is that + * it guarantees that all bits within the initial blob of bytes + * will impact every bit of the output. + * This is not necessarily the case when using the blob of bytes directly + * because, when hashing _small_ inputs, only a portion of the secret is employed. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); + + +/******* Streaming *******/ +#ifndef XXH_NO_STREAM +/* + * Streaming requires state maintenance. + * This operation costs memory and CPU. + * As a consequence, streaming is slower than one-shot hashing. + * For better performance, prefer one-shot functions whenever applicable. + */ + +/*! + * @brief The opaque state struct for the XXH3 streaming API. + * + * @see XXH3_state_s for details. + */ +typedef struct XXH3_state_s XXH3_state_t; +XXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr); + +/*! + * @brief Copies one @ref XXH3_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state); + +/*! + * @brief Resets an @ref XXH3_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret with default parameters. + * - Call this function before @ref XXH3_64bits_update(). + * - Digest will be equivalent to `XXH3_64bits()`. + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); + +/*! + * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret from `seed`. + * - Call this function before @ref XXH3_64bits_update(). + * - Digest will be equivalent to `XXH3_64bits_withSeed()`. + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); + +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * `secret` is referenced, it _must outlive_ the hash streaming session. + * + * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN, + * and the quality of produced hash values depends on secret's entropy + * (secret's content should look like a bunch of random bytes). + * When in doubt about the randomness of a candidate `secret`, + * consider employing `XXH3_generateSecret()` instead (see below). + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); + +/*! + * @brief Consumes a block of @p input to an @ref XXH3_state_t. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated XXH3 64-bit hash value from that state. + * + * @note + * Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ + +/* note : canonical representation of XXH3 is the same as XXH64 + * since they both produce XXH64_hash_t values */ + + +/*-********************************************************************** +* XXH3 128-bit variant +************************************************************************/ + +/*! + * @brief The return value from 128-bit hashes. + * + * Stored in little endian order, although the fields themselves are in native + * endianness. + */ +typedef struct { + XXH64_hash_t low64; /*!< `value & 0xFFFFFFFFFFFFFFFF` */ + XXH64_hash_t high64; /*!< `value >> 64` */ +} XXH128_hash_t; + +/*! + * @brief Calculates 128-bit unseeded variant of XXH3 of @p data. + * + * @param data The block of data to be hashed, at least @p length bytes in size. + * @param len The length of @p data, in bytes. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead + * for shorter inputs. + * + * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of `0`, however + * it may have slightly better performance due to constant propagation of the + * defaults. + * + * @see XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len); +/*! @brief Calculates 128-bit seeded variant of XXH3 hash of @p data. + * + * @param data The block of data to be hashed, at least @p length bytes in size. + * @param len The length of @p data, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * @note + * seed == 0 produces the same results as @ref XXH3_64bits(). + * + * This variant generates a custom secret on the fly based on default secret + * altered using the @p seed value. + * + * While this operation is decently fast, note that it's not completely free. + * + * @see XXH3_128bits(), XXH3_128bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); +/*! + * @brief Calculates 128-bit variant of XXH3 with a custom "secret". + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * It's possible to provide any blob of bytes as a "secret" to generate the hash. + * This makes it more difficult for an external actor to prepare an intentional collision. + * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN). + * However, the quality of the secret impacts the dispersion of the hash algorithm. + * Therefore, the secret _must_ look like a bunch of random bytes. + * Avoid "trivial" or structured data such as repeated sequences or a text document. + * Whenever in doubt about the "randomness" of the blob of bytes, + * consider employing @ref XXH3_generateSecret() instead (see below). + * It will generate a proper high entropy secret derived from the blob of bytes. + * Another advantage of using XXH3_generateSecret() is that + * it guarantees that all bits within the initial blob of bytes + * will impact every bit of the output. + * This is not necessarily the case when using the blob of bytes directly + * because, when hashing _small_ inputs, only a portion of the secret is employed. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); + +/******* Streaming *******/ +#ifndef XXH_NO_STREAM +/* + * Streaming requires state maintenance. + * This operation costs memory and CPU. + * As a consequence, streaming is slower than one-shot hashing. + * For better performance, prefer one-shot functions whenever applicable. + * + * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits(). + * Use already declared XXH3_createState() and XXH3_freeState(). + * + * All reset and streaming functions have same meaning as their 64-bit counterpart. + */ + +/*! + * @brief Resets an @ref XXH3_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret with default parameters. + * - Call it before @ref XXH3_128bits_update(). + * - Digest will be equivalent to `XXH3_128bits()`. + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); + +/*! + * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret from `seed`. + * - Call it before @ref XXH3_128bits_update(). + * - Digest will be equivalent to `XXH3_128bits_withSeed()`. + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * `secret` is referenced, it _must outlive_ the hash streaming session. + * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN, + * and the quality of produced hash values depends on secret's entropy + * (secret's content should look like a bunch of random bytes). + * When in doubt about the randomness of a candidate `secret`, + * consider employing `XXH3_generateSecret()` instead (see below). + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); + +/*! + * @brief Consumes a block of @p input to an @ref XXH3_state_t. + * + * Call this to incrementally consume blocks of data. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated XXH3 128-bit hash value from that state. + * + * @note + * Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ + +/* Following helper functions make it possible to compare XXH128_hast_t values. + * Since XXH128_hash_t is a structure, this capability is not offered by the language. + * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */ + +/*! + * @brief Check equality of two XXH128_hash_t values + * + * @param h1 The 128-bit hash value. + * @param h2 Another 128-bit hash value. + * + * @return `1` if `h1` and `h2` are equal. + * @return `0` if they are not. + */ +XXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2); + +/*! + * @brief Compares two @ref XXH128_hash_t + * + * This comparator is compatible with stdlib's `qsort()`/`bsearch()`. + * + * @param h128_1 Left-hand side value + * @param h128_2 Right-hand side value + * + * @return >0 if @p h128_1 > @p h128_2 + * @return =0 if @p h128_1 == @p h128_2 + * @return <0 if @p h128_1 < @p h128_2 + */ +XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2); + + +/******* Canonical representation *******/ +typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t; + + +/*! + * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t. + * + * @param dst The @ref XXH128_canonical_t pointer to be stored to. + * @param hash The @ref XXH128_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash); + +/*! + * @brief Converts an @ref XXH128_canonical_t to a native @ref XXH128_hash_t. + * + * @param src The @ref XXH128_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src); + + +#endif /* !XXH_NO_XXH3 */ +#endif /* XXH_NO_LONG_LONG */ + +/*! + * @} + */ +#endif /* XXHASH_H_5627135585666179 */ + + + +#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) +#define XXHASH_H_STATIC_13879238742 +/* **************************************************************************** + * This section contains declarations which are not guaranteed to remain stable. + * They may change in future versions, becoming incompatible with a different + * version of the library. + * These declarations should only be used with static linking. + * Never use them in association with dynamic linking! + ***************************************************************************** */ + +/* + * These definitions are only present to allow static allocation + * of XXH states, on stack or in a struct, for example. + * Never **ever** access their members directly. + */ + +/*! + * @internal + * @brief Structure for XXH32 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is + * an opaque type. This allows fields to safely be changed. + * + * Typedef'd to @ref XXH32_state_t. + * Do not access the members of this struct directly. + * @see XXH64_state_s, XXH3_state_s + */ +struct XXH32_state_s { + XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */ + XXH32_hash_t large_len; /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */ + XXH32_hash_t v[4]; /*!< Accumulator lanes */ + XXH32_hash_t mem32[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[16]. */ + XXH32_hash_t memsize; /*!< Amount of data in @ref mem32 */ + XXH32_hash_t reserved; /*!< Reserved field. Do not read nor write to it. */ +}; /* typedef'd to XXH32_state_t */ + + +#ifndef XXH_NO_LONG_LONG /* defined when there is no 64-bit support */ + +/*! + * @internal + * @brief Structure for XXH64 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is + * an opaque type. This allows fields to safely be changed. + * + * Typedef'd to @ref XXH64_state_t. + * Do not access the members of this struct directly. + * @see XXH32_state_s, XXH3_state_s + */ +struct XXH64_state_s { + XXH64_hash_t total_len; /*!< Total length hashed. This is always 64-bit. */ + XXH64_hash_t v[4]; /*!< Accumulator lanes */ + XXH64_hash_t mem64[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */ + XXH32_hash_t memsize; /*!< Amount of data in @ref mem64 */ + XXH32_hash_t reserved32; /*!< Reserved field, needed for padding anyways*/ + XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it. */ +}; /* typedef'd to XXH64_state_t */ + +#ifndef XXH_NO_XXH3 + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */ +# include +# define XXH_ALIGN(n) alignas(n) +#elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */ +/* In C++ alignas() is a keyword */ +# define XXH_ALIGN(n) alignas(n) +#elif defined(__GNUC__) +# define XXH_ALIGN(n) __attribute__ ((aligned(n))) +#elif defined(_MSC_VER) +# define XXH_ALIGN(n) __declspec(align(n)) +#else +# define XXH_ALIGN(n) /* disabled */ +#endif + +/* Old GCC versions only accept the attribute after the type in structures. */ +#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) /* C11+ */ \ + && ! (defined(__cplusplus) && (__cplusplus >= 201103L)) /* >= C++11 */ \ + && defined(__GNUC__) +# define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align) +#else +# define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type +#endif + +/*! + * @brief The size of the internal XXH3 buffer. + * + * This is the optimal update size for incremental hashing. + * + * @see XXH3_64b_update(), XXH3_128b_update(). + */ +#define XXH3_INTERNALBUFFER_SIZE 256 + +/*! + * @internal + * @brief Default size of the secret buffer (and @ref XXH3_kSecret). + * + * This is the size used in @ref XXH3_kSecret and the seeded functions. + * + * Not to be confused with @ref XXH3_SECRET_SIZE_MIN. + */ +#define XXH3_SECRET_DEFAULT_SIZE 192 + +/*! + * @internal + * @brief Structure for XXH3 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. + * Otherwise it is an opaque type. + * Never use this definition in combination with dynamic library. + * This allows fields to safely be changed in the future. + * + * @note ** This structure has a strict alignment requirement of 64 bytes!! ** + * Do not allocate this with `malloc()` or `new`, + * it will not be sufficiently aligned. + * Use @ref XXH3_createState() and @ref XXH3_freeState(), or stack allocation. + * + * Typedef'd to @ref XXH3_state_t. + * Do never access the members of this struct directly. + * + * @see XXH3_INITSTATE() for stack initialization. + * @see XXH3_createState(), XXH3_freeState(). + * @see XXH32_state_s, XXH64_state_s + */ +struct XXH3_state_s { + XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]); + /*!< The 8 accumulators. See @ref XXH32_state_s::v and @ref XXH64_state_s::v */ + XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]); + /*!< Used to store a custom secret generated from a seed. */ + XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]); + /*!< The internal buffer. @see XXH32_state_s::mem32 */ + XXH32_hash_t bufferedSize; + /*!< The amount of memory in @ref buffer, @see XXH32_state_s::memsize */ + XXH32_hash_t useSeed; + /*!< Reserved field. Needed for padding on 64-bit. */ + size_t nbStripesSoFar; + /*!< Number or stripes processed. */ + XXH64_hash_t totalLen; + /*!< Total length hashed. 64-bit even on 32-bit targets. */ + size_t nbStripesPerBlock; + /*!< Number of stripes per block. */ + size_t secretLimit; + /*!< Size of @ref customSecret or @ref extSecret */ + XXH64_hash_t seed; + /*!< Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE() */ + XXH64_hash_t reserved64; + /*!< Reserved field. */ + const unsigned char* extSecret; + /*!< Reference to an external secret for the _withSecret variants, NULL + * for other variants. */ + /* note: there may be some padding at the end due to alignment on 64 bytes */ +}; /* typedef'd to XXH3_state_t */ + +#undef XXH_ALIGN_MEMBER + +/*! + * @brief Initializes a stack-allocated `XXH3_state_s`. + * + * When the @ref XXH3_state_t structure is merely emplaced on stack, + * it should be initialized with XXH3_INITSTATE() or a memset() + * in case its first reset uses XXH3_NNbits_reset_withSeed(). + * This init can be omitted if the first reset uses default or _withSecret mode. + * This operation isn't necessary when the state is created with XXH3_createState(). + * Note that this doesn't prepare the state for a streaming operation, + * it's still necessary to use XXH3_NNbits_reset*() afterwards. + */ +#define XXH3_INITSTATE(XXH3_state_ptr) \ + do { \ + XXH3_state_t* tmp_xxh3_state_ptr = (XXH3_state_ptr); \ + tmp_xxh3_state_ptr->seed = 0; \ + tmp_xxh3_state_ptr->extSecret = NULL; \ + } while(0) + + +/*! + * @brief Calculates the 128-bit hash of @p data using XXH3. + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param seed The 64-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p data and @p data + @p len must be valid, + * readable, contiguous memory. However, if @p len is `0`, @p data may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 128-bit XXH3 value. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); + + +/* === Experimental API === */ +/* Symbols defined below must be considered tied to a specific library version. */ + +/*! + * @brief Derive a high-entropy secret from any user-defined content, named customSeed. + * + * @param secretBuffer A writable buffer for derived high-entropy secret data. + * @param secretSize Size of secretBuffer, in bytes. Must be >= XXH3_SECRET_DEFAULT_SIZE. + * @param customSeed A user-defined content. + * @param customSeedSize Size of customSeed, in bytes. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * The generated secret can be used in combination with `*_withSecret()` functions. + * The `_withSecret()` variants are useful to provide a higher level of protection + * than 64-bit seed, as it becomes much more difficult for an external actor to + * guess how to impact the calculation logic. + * + * The function accepts as input a custom seed of any length and any content, + * and derives from it a high-entropy secret of length @p secretSize into an + * already allocated buffer @p secretBuffer. + * + * The generated secret can then be used with any `*_withSecret()` variant. + * The functions @ref XXH3_128bits_withSecret(), @ref XXH3_64bits_withSecret(), + * @ref XXH3_128bits_reset_withSecret() and @ref XXH3_64bits_reset_withSecret() + * are part of this list. They all accept a `secret` parameter + * which must be large enough for implementation reasons (>= @ref XXH3_SECRET_SIZE_MIN) + * _and_ feature very high entropy (consist of random-looking bytes). + * These conditions can be a high bar to meet, so @ref XXH3_generateSecret() can + * be employed to ensure proper quality. + * + * @p customSeed can be anything. It can have any size, even small ones, + * and its content can be anything, even "poor entropy" sources such as a bunch + * of zeroes. The resulting `secret` will nonetheless provide all required qualities. + * + * @pre + * - @p secretSize must be >= @ref XXH3_SECRET_SIZE_MIN + * - When @p customSeedSize > 0, supplying NULL as customSeed is undefined behavior. + * + * Example code: + * @code{.c} + * #include + * #include + * #include + * #define XXH_STATIC_LINKING_ONLY // expose unstable API + * #include "xxhash.h" + * // Hashes argv[2] using the entropy from argv[1]. + * int main(int argc, char* argv[]) + * { + * char secret[XXH3_SECRET_SIZE_MIN]; + * if (argv != 3) { return 1; } + * XXH3_generateSecret(secret, sizeof(secret), argv[1], strlen(argv[1])); + * XXH64_hash_t h = XXH3_64bits_withSecret( + * argv[2], strlen(argv[2]), + * secret, sizeof(secret) + * ); + * printf("%016llx\n", (unsigned long long) h); + * } + * @endcode + */ +XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize); + +/*! + * @brief Generate the same secret as the _withSeed() variants. + * + * @param secretBuffer A writable buffer of @ref XXH3_SECRET_SIZE_MIN bytes + * @param seed The 64-bit seed to alter the hash result predictably. + * + * The generated secret can be used in combination with + *`*_withSecret()` and `_withSecretandSeed()` variants. + * + * Example C++ `std::string` hash class: + * @code{.cpp} + * #include + * #define XXH_STATIC_LINKING_ONLY // expose unstable API + * #include "xxhash.h" + * // Slow, seeds each time + * class HashSlow { + * XXH64_hash_t seed; + * public: + * HashSlow(XXH64_hash_t s) : seed{s} {} + * size_t operator()(const std::string& x) const { + * return size_t{XXH3_64bits_withSeed(x.c_str(), x.length(), seed)}; + * } + * }; + * // Fast, caches the seeded secret for future uses. + * class HashFast { + * unsigned char secret[XXH3_SECRET_SIZE_MIN]; + * public: + * HashFast(XXH64_hash_t s) { + * XXH3_generateSecret_fromSeed(secret, seed); + * } + * size_t operator()(const std::string& x) const { + * return size_t{ + * XXH3_64bits_withSecret(x.c_str(), x.length(), secret, sizeof(secret)) + * }; + * } + * }; + * @endcode + */ +XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed); + +/*! + * @brief Calculates 64/128-bit seeded variant of XXH3 hash of @p data. + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * These variants generate hash values using either + * @p seed for "short" keys (< @ref XXH3_MIDSIZE_MAX = 240 bytes) + * or @p secret for "large" keys (>= @ref XXH3_MIDSIZE_MAX). + * + * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`. + * `_withSeed()` has to generate the secret on the fly for "large" keys. + * It's fast, but can be perceptible for "not so large" keys (< 1 KB). + * `_withSecret()` has to generate the masks on the fly for "small" keys, + * which requires more instructions than _withSeed() variants. + * Therefore, _withSecretandSeed variant combines the best of both worlds. + * + * When @p secret has been generated by XXH3_generateSecret_fromSeed(), + * this variant produces *exactly* the same results as `_withSeed()` variant, + * hence offering only a pure speed benefit on "large" input, + * by skipping the need to regenerate the secret for every large input. + * + * Another usage scenario is to hash the secret to a 64-bit hash value, + * for example with XXH3_64bits(), which then becomes the seed, + * and then employ both the seed and the secret in _withSecretandSeed(). + * On top of speed, an added benefit is that each bit in the secret + * has a 50% chance to swap each bit in the output, via its impact to the seed. + * + * This is not guaranteed when using the secret directly in "small data" scenarios, + * because only portions of the secret are employed for small data. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t +XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed); +/*! + * @brief Calculates 128-bit seeded variant of XXH3 hash of @p data. + * + * @param input The block of data to be hashed, at least @p len bytes in size. + * @param length The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed() + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t +XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed64); +#ifndef XXH_NO_STREAM +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed() + */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed64); +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed() + */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed64); +#endif /* !XXH_NO_STREAM */ + +#endif /* !XXH_NO_XXH3 */ +#endif /* XXH_NO_LONG_LONG */ +#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) +# define XXH_IMPLEMENTATION +#endif + +#endif /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */ + + +/* ======================================================================== */ +/* ======================================================================== */ +/* ======================================================================== */ + + +/*-********************************************************************** + * xxHash implementation + *-********************************************************************** + * xxHash's implementation used to be hosted inside xxhash.c. + * + * However, inlining requires implementation to be visible to the compiler, + * hence be included alongside the header. + * Previously, implementation was hosted inside xxhash.c, + * which was then #included when inlining was activated. + * This construction created issues with a few build and install systems, + * as it required xxhash.c to be stored in /include directory. + * + * xxHash implementation is now directly integrated within xxhash.h. + * As a consequence, xxhash.c is no longer needed in /include. + * + * xxhash.c is still available and is still useful. + * In a "normal" setup, when xxhash is not inlined, + * xxhash.h only exposes the prototypes and public symbols, + * while xxhash.c can be built into an object file xxhash.o + * which can then be linked into the final binary. + ************************************************************************/ + +#if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \ + || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387) +# define XXH_IMPLEM_13a8737387 + +/* ************************************* +* Tuning parameters +***************************************/ + +/*! + * @defgroup tuning Tuning parameters + * @{ + * + * Various macros to control xxHash's behavior. + */ +#ifdef XXH_DOXYGEN +/*! + * @brief Define this to disable 64-bit code. + * + * Useful if only using the @ref XXH32_family and you have a strict C90 compiler. + */ +# define XXH_NO_LONG_LONG +# undef XXH_NO_LONG_LONG /* don't actually */ +/*! + * @brief Controls how unaligned memory is accessed. + * + * By default, access to unaligned memory is controlled by `memcpy()`, which is + * safe and portable. + * + * Unfortunately, on some target/compiler combinations, the generated assembly + * is sub-optimal. + * + * The below switch allow selection of a different access method + * in the search for improved performance. + * + * @par Possible options: + * + * - `XXH_FORCE_MEMORY_ACCESS=0` (default): `memcpy` + * @par + * Use `memcpy()`. Safe and portable. Note that most modern compilers will + * eliminate the function call and treat it as an unaligned access. + * + * - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((aligned(1)))` + * @par + * Depends on compiler extensions and is therefore not portable. + * This method is safe _if_ your compiler supports it, + * and *generally* as fast or faster than `memcpy`. + * + * - `XXH_FORCE_MEMORY_ACCESS=2`: Direct cast + * @par + * Casts directly and dereferences. This method doesn't depend on the + * compiler, but it violates the C standard as it directly dereferences an + * unaligned pointer. It can generate buggy code on targets which do not + * support unaligned memory accesses, but in some circumstances, it's the + * only known way to get the most performance. + * + * - `XXH_FORCE_MEMORY_ACCESS=3`: Byteshift + * @par + * Also portable. This can generate the best code on old compilers which don't + * inline small `memcpy()` calls, and it might also be faster on big-endian + * systems which lack a native byteswap instruction. However, some compilers + * will emit literal byteshifts even if the target supports unaligned access. + * + * + * @warning + * Methods 1 and 2 rely on implementation-defined behavior. Use these with + * care, as what works on one compiler/platform/optimization level may cause + * another to read garbage data or even crash. + * + * See https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details. + * + * Prefer these methods in priority order (0 > 3 > 1 > 2) + */ +# define XXH_FORCE_MEMORY_ACCESS 0 + +/*! + * @def XXH_SIZE_OPT + * @brief Controls how much xxHash optimizes for size. + * + * xxHash, when compiled, tends to result in a rather large binary size. This + * is mostly due to heavy usage to forced inlining and constant folding of the + * @ref XXH3_family to increase performance. + * + * However, some developers prefer size over speed. This option can + * significantly reduce the size of the generated code. When using the `-Os` + * or `-Oz` options on GCC or Clang, this is defined to 1 by default, + * otherwise it is defined to 0. + * + * Most of these size optimizations can be controlled manually. + * + * This is a number from 0-2. + * - `XXH_SIZE_OPT` == 0: Default. xxHash makes no size optimizations. Speed + * comes first. + * - `XXH_SIZE_OPT` == 1: Default for `-Os` and `-Oz`. xxHash is more + * conservative and disables hacks that increase code size. It implies the + * options @ref XXH_NO_INLINE_HINTS == 1, @ref XXH_FORCE_ALIGN_CHECK == 0, + * and @ref XXH3_NEON_LANES == 8 if they are not already defined. + * - `XXH_SIZE_OPT` == 2: xxHash tries to make itself as small as possible. + * Performance may cry. For example, the single shot functions just use the + * streaming API. + */ +# define XXH_SIZE_OPT 0 + +/*! + * @def XXH_FORCE_ALIGN_CHECK + * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32() + * and XXH64() only). + * + * This is an important performance trick for architectures without decent + * unaligned memory access performance. + * + * It checks for input alignment, and when conditions are met, uses a "fast + * path" employing direct 32-bit/64-bit reads, resulting in _dramatically + * faster_ read speed. + * + * The check costs one initial branch per hash, which is generally negligible, + * but not zero. + * + * Moreover, it's not useful to generate an additional code path if memory + * access uses the same instruction for both aligned and unaligned + * addresses (e.g. x86 and aarch64). + * + * In these cases, the alignment check can be removed by setting this macro to 0. + * Then the code will always use unaligned memory access. + * Align check is automatically disabled on x86, x64, ARM64, and some ARM chips + * which are platforms known to offer good unaligned memory accesses performance. + * + * It is also disabled by default when @ref XXH_SIZE_OPT >= 1. + * + * This option does not affect XXH3 (only XXH32 and XXH64). + */ +# define XXH_FORCE_ALIGN_CHECK 0 + +/*! + * @def XXH_NO_INLINE_HINTS + * @brief When non-zero, sets all functions to `static`. + * + * By default, xxHash tries to force the compiler to inline almost all internal + * functions. + * + * This can usually improve performance due to reduced jumping and improved + * constant folding, but significantly increases the size of the binary which + * might not be favorable. + * + * Additionally, sometimes the forced inlining can be detrimental to performance, + * depending on the architecture. + * + * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the + * compiler full control on whether to inline or not. + * + * When not optimizing (-O0), using `-fno-inline` with GCC or Clang, or if + * @ref XXH_SIZE_OPT >= 1, this will automatically be defined. + */ +# define XXH_NO_INLINE_HINTS 0 + +/*! + * @def XXH3_INLINE_SECRET + * @brief Determines whether to inline the XXH3 withSecret code. + * + * When the secret size is known, the compiler can improve the performance + * of XXH3_64bits_withSecret() and XXH3_128bits_withSecret(). + * + * However, if the secret size is not known, it doesn't have any benefit. This + * happens when xxHash is compiled into a global symbol. Therefore, if + * @ref XXH_INLINE_ALL is *not* defined, this will be defined to 0. + * + * Additionally, this defaults to 0 on GCC 12+, which has an issue with function pointers + * that are *sometimes* force inline on -Og, and it is impossible to automatically + * detect this optimization level. + */ +# define XXH3_INLINE_SECRET 0 + +/*! + * @def XXH32_ENDJMP + * @brief Whether to use a jump for `XXH32_finalize`. + * + * For performance, `XXH32_finalize` uses multiple branches in the finalizer. + * This is generally preferable for performance, + * but depending on exact architecture, a jmp may be preferable. + * + * This setting is only possibly making a difference for very small inputs. + */ +# define XXH32_ENDJMP 0 + +/*! + * @internal + * @brief Redefines old internal names. + * + * For compatibility with code that uses xxHash's internals before the names + * were changed to improve namespacing. There is no other reason to use this. + */ +# define XXH_OLD_NAMES +# undef XXH_OLD_NAMES /* don't actually use, it is ugly. */ + +/*! + * @def XXH_NO_STREAM + * @brief Disables the streaming API. + * + * When xxHash is not inlined and the streaming functions are not used, disabling + * the streaming functions can improve code size significantly, especially with + * the @ref XXH3_family which tends to make constant folded copies of itself. + */ +# define XXH_NO_STREAM +# undef XXH_NO_STREAM /* don't actually */ +#endif /* XXH_DOXYGEN */ +/*! + * @} + */ + +#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ + /* prefer __packed__ structures (method 1) for GCC + * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy + * which for some reason does unaligned loads. */ +# if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED)) +# define XXH_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +#ifndef XXH_SIZE_OPT + /* default to 1 for -Os or -Oz */ +# if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__) +# define XXH_SIZE_OPT 1 +# else +# define XXH_SIZE_OPT 0 +# endif +#endif + +#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ + /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */ +# if XXH_SIZE_OPT >= 1 || \ + defined(__i386) || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \ + || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM) /* visual */ +# define XXH_FORCE_ALIGN_CHECK 0 +# else +# define XXH_FORCE_ALIGN_CHECK 1 +# endif +#endif + +#ifndef XXH_NO_INLINE_HINTS +# if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__) /* -O0, -fno-inline */ +# define XXH_NO_INLINE_HINTS 1 +# else +# define XXH_NO_INLINE_HINTS 0 +# endif +#endif + +#ifndef XXH3_INLINE_SECRET +# if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12) \ + || !defined(XXH_INLINE_ALL) +# define XXH3_INLINE_SECRET 0 +# else +# define XXH3_INLINE_SECRET 1 +# endif +#endif + +#ifndef XXH32_ENDJMP +/* generally preferable for performance */ +# define XXH32_ENDJMP 0 +#endif + +/*! + * @defgroup impl Implementation + * @{ + */ + + +/* ************************************* +* Includes & Memory related functions +***************************************/ +#if defined(XXH_NO_STREAM) +/* nothing */ +#elif defined(XXH_NO_STDLIB) + +/* When requesting to disable any mention of stdlib, + * the library loses the ability to invoked malloc / free. + * In practice, it means that functions like `XXH*_createState()` + * will always fail, and return NULL. + * This flag is useful in situations where + * xxhash.h is integrated into some kernel, embedded or limited environment + * without access to dynamic allocation. + */ + +static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; } +static void XXH_free(void* p) { (void)p; } + +#else + +/* + * Modify the local functions below should you wish to use + * different memory routines for malloc() and free() + */ +#include + +/*! + * @internal + * @brief Modify this function to use a different routine than malloc(). + */ +static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); } + +/*! + * @internal + * @brief Modify this function to use a different routine than free(). + */ +static void XXH_free(void* p) { free(p); } + +#endif /* XXH_NO_STDLIB */ + +#include + +/*! + * @internal + * @brief Modify this function to use a different routine than memcpy(). + */ +static void* XXH_memcpy(void* dest, const void* src, size_t size) +{ + return memcpy(dest,src,size); +} + +#include /* ULLONG_MAX */ + + +/* ************************************* +* Compiler Specific Options +***************************************/ +#ifdef _MSC_VER /* Visual Studio warning fix */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +#endif + +#if XXH_NO_INLINE_HINTS /* disable inlining hints */ +# if defined(__GNUC__) || defined(__clang__) +# define XXH_FORCE_INLINE static __attribute__((unused)) +# else +# define XXH_FORCE_INLINE static +# endif +# define XXH_NO_INLINE static +/* enable inlining hints */ +#elif defined(__GNUC__) || defined(__clang__) +# define XXH_FORCE_INLINE static __inline__ __attribute__((always_inline, unused)) +# define XXH_NO_INLINE static __attribute__((noinline)) +#elif defined(_MSC_VER) /* Visual Studio */ +# define XXH_FORCE_INLINE static __forceinline +# define XXH_NO_INLINE static __declspec(noinline) +#elif defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99 */ +# define XXH_FORCE_INLINE static inline +# define XXH_NO_INLINE static +#else +# define XXH_FORCE_INLINE static +# define XXH_NO_INLINE static +#endif + +#if XXH3_INLINE_SECRET +# define XXH3_WITH_SECRET_INLINE XXH_FORCE_INLINE +#else +# define XXH3_WITH_SECRET_INLINE XXH_NO_INLINE +#endif + + +/* ************************************* +* Debug +***************************************/ +/*! + * @ingroup tuning + * @def XXH_DEBUGLEVEL + * @brief Sets the debugging level. + * + * XXH_DEBUGLEVEL is expected to be defined externally, typically via the + * compiler's command line options. The value must be a number. + */ +#ifndef XXH_DEBUGLEVEL +# ifdef DEBUGLEVEL /* backwards compat */ +# define XXH_DEBUGLEVEL DEBUGLEVEL +# else +# define XXH_DEBUGLEVEL 0 +# endif +#endif + +#if (XXH_DEBUGLEVEL>=1) +# include /* note: can still be disabled with NDEBUG */ +# define XXH_ASSERT(c) assert(c) +#else +# if defined(__INTEL_COMPILER) +# define XXH_ASSERT(c) XXH_ASSUME((unsigned char) (c)) +# else +# define XXH_ASSERT(c) XXH_ASSUME(c) +# endif +#endif + +/* note: use after variable declarations */ +#ifndef XXH_STATIC_ASSERT +# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ +# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { _Static_assert((c),m); } while(0) +# elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */ +# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0) +# else +# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct xxh_sa { char x[(c) ? 1 : -1]; }; } while(0) +# endif +# define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c),#c) +#endif + +/*! + * @internal + * @def XXH_COMPILER_GUARD(var) + * @brief Used to prevent unwanted optimizations for @p var. + * + * It uses an empty GCC inline assembly statement with a register constraint + * which forces @p var into a general purpose register (eg eax, ebx, ecx + * on x86) and marks it as modified. + * + * This is used in a few places to avoid unwanted autovectorization (e.g. + * XXH32_round()). All vectorization we want is explicit via intrinsics, + * and _usually_ isn't wanted elsewhere. + * + * We also use it to prevent unwanted constant folding for AArch64 in + * XXH3_initCustomSecret_scalar(). + */ +#if defined(__GNUC__) || defined(__clang__) +# define XXH_COMPILER_GUARD(var) __asm__("" : "+r" (var)) +#else +# define XXH_COMPILER_GUARD(var) ((void)0) +#endif + +/* Specifically for NEON vectors which use the "w" constraint, on + * Clang. */ +#if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__) +# define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__("" : "+w" (var)) +#else +# define XXH_COMPILER_GUARD_CLANG_NEON(var) ((void)0) +#endif + +/* ************************************* +* Basic Types +***************************************/ +#if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# ifdef _AIX +# include +# else +# include +# endif + typedef uint8_t xxh_u8; +#else + typedef unsigned char xxh_u8; +#endif +typedef XXH32_hash_t xxh_u32; + +#ifdef XXH_OLD_NAMES +# warning "XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly" +# define BYTE xxh_u8 +# define U8 xxh_u8 +# define U32 xxh_u32 +#endif + +/* *** Memory access *** */ + +/*! + * @internal + * @fn xxh_u32 XXH_read32(const void* ptr) + * @brief Reads an unaligned 32-bit integer from @p ptr in native endianness. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit native endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readLE32(const void* ptr) + * @brief Reads an unaligned 32-bit little endian integer from @p ptr. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit little endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readBE32(const void* ptr) + * @brief Reads an unaligned 32-bit big endian integer from @p ptr. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit big endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align) + * @brief Like @ref XXH_readLE32(), but has an option for aligned reads. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * Note that when @ref XXH_FORCE_ALIGN_CHECK == 0, the @p align parameter is + * always @ref XXH_alignment::XXH_unaligned. + * + * @param ptr The pointer to read from. + * @param align Whether @p ptr is aligned. + * @pre + * If @p align == @ref XXH_alignment::XXH_aligned, @p ptr must be 4 byte + * aligned. + * @return The 32-bit little endian integer from the bytes at @p ptr. + */ + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) +/* + * Manual byteshift. Best for old compilers which don't inline memcpy. + * We actually directly use XXH_readLE32 and XXH_readBE32. + */ +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* + * Force direct memory access. Only works on CPU which support unaligned memory + * access in hardware. + */ +static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* + * __attribute__((aligned(1))) is supported by gcc and clang. Originally the + * documentation claimed that it only increased the alignment, but actually it + * can decrease it on gcc, clang, and icc: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, + * https://gcc.godbolt.org/z/xYez1j67Y. + */ +#ifdef XXH_OLD_NAMES +typedef union { xxh_u32 u32; } __attribute__((packed)) unalign; +#endif +static xxh_u32 XXH_read32(const void* ptr) +{ + typedef __attribute__((aligned(1))) xxh_u32 xxh_unalign32; + return *((const xxh_unalign32*)ptr); +} + +#else + +/* + * Portable and safe solution. Generally efficient. + * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html + */ +static xxh_u32 XXH_read32(const void* memPtr) +{ + xxh_u32 val; + XXH_memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + + +/* *** Endianness *** */ + +/*! + * @ingroup tuning + * @def XXH_CPU_LITTLE_ENDIAN + * @brief Whether the target is little endian. + * + * Defined to 1 if the target is little endian, or 0 if it is big endian. + * It can be defined externally, for example on the compiler command line. + * + * If it is not defined, + * a runtime check (which is usually constant folded) is used instead. + * + * @note + * This is not necessarily defined to an integer constant. + * + * @see XXH_isLittleEndian() for the runtime check. + */ +#ifndef XXH_CPU_LITTLE_ENDIAN +/* + * Try to detect endianness automatically, to avoid the nonstandard behavior + * in `XXH_isLittleEndian()` + */ +# if defined(_WIN32) /* Windows is always little endian */ \ + || defined(__LITTLE_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +# define XXH_CPU_LITTLE_ENDIAN 1 +# elif defined(__BIG_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define XXH_CPU_LITTLE_ENDIAN 0 +# else +/*! + * @internal + * @brief Runtime check for @ref XXH_CPU_LITTLE_ENDIAN. + * + * Most compilers will constant fold this. + */ +static int XXH_isLittleEndian(void) +{ + /* + * Portable and well-defined behavior. + * Don't use static: it is detrimental to performance. + */ + const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 }; + return one.c[0]; +} +# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() +# endif +#endif + + + + +/* **************************************** +* Compiler-specific Functions and Macros +******************************************/ +#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +#ifdef __has_builtin +# define XXH_HAS_BUILTIN(x) __has_builtin(x) +#else +# define XXH_HAS_BUILTIN(x) 0 +#endif + + + +/* + * C23 and future versions have standard "unreachable()". + * Once it has been implemented reliably we can add it as an + * additional case: + * + * ``` + * #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) + * # include + * # ifdef unreachable + * # define XXH_UNREACHABLE() unreachable() + * # endif + * #endif + * ``` + * + * Note C++23 also has std::unreachable() which can be detected + * as follows: + * ``` + * #if defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L) + * # include + * # define XXH_UNREACHABLE() std::unreachable() + * #endif + * ``` + * NB: `__cpp_lib_unreachable` is defined in the `` header. + * We don't use that as including `` in `extern "C"` blocks + * doesn't work on GCC12 + */ + +#if XXH_HAS_BUILTIN(__builtin_unreachable) +# define XXH_UNREACHABLE() __builtin_unreachable() + +#elif defined(_MSC_VER) +# define XXH_UNREACHABLE() __assume(0) + +#else +# define XXH_UNREACHABLE() +#endif + +#if XXH_HAS_BUILTIN(__builtin_assume) +# define XXH_ASSUME(c) __builtin_assume(c) +#else +# define XXH_ASSUME(c) if (!(c)) { XXH_UNREACHABLE(); } +#endif + +/*! + * @internal + * @def XXH_rotl32(x,r) + * @brief 32-bit rotate left. + * + * @param x The 32-bit integer to be rotated. + * @param r The number of bits to rotate. + * @pre + * @p r > 0 && @p r < 32 + * @note + * @p x and @p r may be evaluated multiple times. + * @return The rotated result. + */ +#if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \ + && XXH_HAS_BUILTIN(__builtin_rotateleft64) +# define XXH_rotl32 __builtin_rotateleft32 +# define XXH_rotl64 __builtin_rotateleft64 +/* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */ +#elif defined(_MSC_VER) +# define XXH_rotl32(x,r) _rotl(x,r) +# define XXH_rotl64(x,r) _rotl64(x,r) +#else +# define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) +# define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r)))) +#endif + +/*! + * @internal + * @fn xxh_u32 XXH_swap32(xxh_u32 x) + * @brief A 32-bit byteswap. + * + * @param x The 32-bit integer to byteswap. + * @return @p x, byteswapped. + */ +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap32 _byteswap_ulong +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap32 __builtin_bswap32 +#else +static xxh_u32 XXH_swap32 (xxh_u32 x) +{ + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} +#endif + + +/* *************************** +* Memory reads +*****************************/ + +/*! + * @internal + * @brief Enum to indicate whether a pointer is aligned. + */ +typedef enum { + XXH_aligned, /*!< Aligned */ + XXH_unaligned /*!< Possibly unaligned */ +} XXH_alignment; + +/* + * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. + * + * This is ideal for older compilers which don't inline memcpy. + */ +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) + +XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[0] + | ((xxh_u32)bytePtr[1] << 8) + | ((xxh_u32)bytePtr[2] << 16) + | ((xxh_u32)bytePtr[3] << 24); +} + +XXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[3] + | ((xxh_u32)bytePtr[2] << 8) + | ((xxh_u32)bytePtr[1] << 16) + | ((xxh_u32)bytePtr[0] << 24); +} + +#else +XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); +} + +static xxh_u32 XXH_readBE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); +} +#endif + +XXH_FORCE_INLINE xxh_u32 +XXH_readLE32_align(const void* ptr, XXH_alignment align) +{ + if (align==XXH_unaligned) { + return XXH_readLE32(ptr); + } else { + return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr); + } +} + + +/* ************************************* +* Misc +***************************************/ +/*! @ingroup public */ +XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } + + +/* ******************************************************************* +* 32-bit hash functions +*********************************************************************/ +/*! + * @} + * @defgroup XXH32_impl XXH32 implementation + * @ingroup impl + * + * Details on the XXH32 implementation. + * @{ + */ + /* #define instead of static const, to be used as initializers */ +#define XXH_PRIME32_1 0x9E3779B1U /*!< 0b10011110001101110111100110110001 */ +#define XXH_PRIME32_2 0x85EBCA77U /*!< 0b10000101111010111100101001110111 */ +#define XXH_PRIME32_3 0xC2B2AE3DU /*!< 0b11000010101100101010111000111101 */ +#define XXH_PRIME32_4 0x27D4EB2FU /*!< 0b00100111110101001110101100101111 */ +#define XXH_PRIME32_5 0x165667B1U /*!< 0b00010110010101100110011110110001 */ + +#ifdef XXH_OLD_NAMES +# define PRIME32_1 XXH_PRIME32_1 +# define PRIME32_2 XXH_PRIME32_2 +# define PRIME32_3 XXH_PRIME32_3 +# define PRIME32_4 XXH_PRIME32_4 +# define PRIME32_5 XXH_PRIME32_5 +#endif + +/*! + * @internal + * @brief Normal stripe processing routine. + * + * This shuffles the bits so that any bit from @p input impacts several bits in + * @p acc. + * + * @param acc The accumulator lane. + * @param input The stripe of input to mix. + * @return The mixed accumulator lane. + */ +static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) +{ + acc += input * XXH_PRIME32_2; + acc = XXH_rotl32(acc, 13); + acc *= XXH_PRIME32_1; +#if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) + /* + * UGLY HACK: + * A compiler fence is the only thing that prevents GCC and Clang from + * autovectorizing the XXH32 loop (pragmas and attributes don't work for some + * reason) without globally disabling SSE4.1. + * + * The reason we want to avoid vectorization is because despite working on + * 4 integers at a time, there are multiple factors slowing XXH32 down on + * SSE4: + * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on + * newer chips!) making it slightly slower to multiply four integers at + * once compared to four integers independently. Even when pmulld was + * fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE + * just to multiply unless doing a long operation. + * + * - Four instructions are required to rotate, + * movqda tmp, v // not required with VEX encoding + * pslld tmp, 13 // tmp <<= 13 + * psrld v, 19 // x >>= 19 + * por v, tmp // x |= tmp + * compared to one for scalar: + * roll v, 13 // reliably fast across the board + * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason + * + * - Instruction level parallelism is actually more beneficial here because + * the SIMD actually serializes this operation: While v1 is rotating, v2 + * can load data, while v3 can multiply. SSE forces them to operate + * together. + * + * This is also enabled on AArch64, as Clang is *very aggressive* in vectorizing + * the loop. NEON is only faster on the A53, and with the newer cores, it is less + * than half the speed. + * + * Additionally, this is used on WASM SIMD128 because it JITs to the same + * SIMD instructions and has the same issue. + */ + XXH_COMPILER_GUARD(acc); +#endif + return acc; +} + +/*! + * @internal + * @brief Mixes all bits to finalize the hash. + * + * The final mix ensures that all input bits have a chance to impact any bit in + * the output digest, resulting in an unbiased distribution. + * + * @param hash The hash to avalanche. + * @return The avalanched hash. + */ +static xxh_u32 XXH32_avalanche(xxh_u32 hash) +{ + hash ^= hash >> 15; + hash *= XXH_PRIME32_2; + hash ^= hash >> 13; + hash *= XXH_PRIME32_3; + hash ^= hash >> 16; + return hash; +} + +#define XXH_get32bits(p) XXH_readLE32_align(p, align) + +/*! + * @internal + * @brief Processes the last 0-15 bytes of @p ptr. + * + * There may be up to 15 bytes remaining to consume from the input. + * This final stage will digest them to ensure that all input bytes are present + * in the final mix. + * + * @param hash The hash to finalize. + * @param ptr The pointer to the remaining input. + * @param len The remaining length, modulo 16. + * @param align Whether @p ptr is aligned. + * @return The finalized hash. + * @see XXH64_finalize(). + */ +static XXH_PUREF xxh_u32 +XXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) +{ +#define XXH_PROCESS1 do { \ + hash += (*ptr++) * XXH_PRIME32_5; \ + hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1; \ +} while (0) + +#define XXH_PROCESS4 do { \ + hash += XXH_get32bits(ptr) * XXH_PRIME32_3; \ + ptr += 4; \ + hash = XXH_rotl32(hash, 17) * XXH_PRIME32_4; \ +} while (0) + + if (ptr==NULL) XXH_ASSERT(len == 0); + + /* Compact rerolled version; generally faster */ + if (!XXH32_ENDJMP) { + len &= 15; + while (len >= 4) { + XXH_PROCESS4; + len -= 4; + } + while (len > 0) { + XXH_PROCESS1; + --len; + } + return XXH32_avalanche(hash); + } else { + switch(len&15) /* or switch(bEnd - p) */ { + case 12: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 8: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 4: XXH_PROCESS4; + return XXH32_avalanche(hash); + + case 13: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 9: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 5: XXH_PROCESS4; + XXH_PROCESS1; + return XXH32_avalanche(hash); + + case 14: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 10: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 6: XXH_PROCESS4; + XXH_PROCESS1; + XXH_PROCESS1; + return XXH32_avalanche(hash); + + case 15: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 11: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 7: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 3: XXH_PROCESS1; + XXH_FALLTHROUGH; /* fallthrough */ + case 2: XXH_PROCESS1; + XXH_FALLTHROUGH; /* fallthrough */ + case 1: XXH_PROCESS1; + XXH_FALLTHROUGH; /* fallthrough */ + case 0: return XXH32_avalanche(hash); + } + XXH_ASSERT(0); + return hash; /* reaching this point is deemed impossible */ + } +} + +#ifdef XXH_OLD_NAMES +# define PROCESS1 XXH_PROCESS1 +# define PROCESS4 XXH_PROCESS4 +#else +# undef XXH_PROCESS1 +# undef XXH_PROCESS4 +#endif + +/*! + * @internal + * @brief The implementation for @ref XXH32(). + * + * @param input , len , seed Directly passed from @ref XXH32(). + * @param align Whether @p input is aligned. + * @return The calculated hash. + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u32 +XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align) +{ + xxh_u32 h32; + + if (input==NULL) XXH_ASSERT(len == 0); + + if (len>=16) { + const xxh_u8* const bEnd = input + len; + const xxh_u8* const limit = bEnd - 15; + xxh_u32 v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2; + xxh_u32 v2 = seed + XXH_PRIME32_2; + xxh_u32 v3 = seed + 0; + xxh_u32 v4 = seed - XXH_PRIME32_1; + + do { + v1 = XXH32_round(v1, XXH_get32bits(input)); input += 4; + v2 = XXH32_round(v2, XXH_get32bits(input)); input += 4; + v3 = XXH32_round(v3, XXH_get32bits(input)); input += 4; + v4 = XXH32_round(v4, XXH_get32bits(input)); input += 4; + } while (input < limit); + + h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); + } else { + h32 = seed + XXH_PRIME32_5; + } + + h32 += (xxh_u32)len; + + return XXH32_finalize(h32, input, len&15, align); +} + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed) +{ +#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH32_state_t state; + XXH32_reset(&state, seed); + XXH32_update(&state, (const xxh_u8*)input, len); + return XXH32_digest(&state); +#else + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ + return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); + } } + + return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); +#endif +} + + + +/******* Hash streaming *******/ +#ifndef XXH_NO_STREAM +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) +{ + return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); +} +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) +{ + XXH_memcpy(dstState, srcState, sizeof(*dstState)); +} + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed) +{ + XXH_ASSERT(statePtr != NULL); + memset(statePtr, 0, sizeof(*statePtr)); + statePtr->v[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2; + statePtr->v[1] = seed + XXH_PRIME32_2; + statePtr->v[2] = seed + 0; + statePtr->v[3] = seed - XXH_PRIME32_1; + return XXH_OK; +} + + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH_errorcode +XXH32_update(XXH32_state_t* state, const void* input, size_t len) +{ + if (input==NULL) { + XXH_ASSERT(len == 0); + return XXH_OK; + } + + { const xxh_u8* p = (const xxh_u8*)input; + const xxh_u8* const bEnd = p + len; + + state->total_len_32 += (XXH32_hash_t)len; + state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16)); + + if (state->memsize + len < 16) { /* fill in tmp buffer */ + XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, len); + state->memsize += (XXH32_hash_t)len; + return XXH_OK; + } + + if (state->memsize) { /* some data left from previous update */ + XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, 16-state->memsize); + { const xxh_u32* p32 = state->mem32; + state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p32)); p32++; + state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p32)); p32++; + state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p32)); p32++; + state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p32)); + } + p += 16-state->memsize; + state->memsize = 0; + } + + if (p <= bEnd-16) { + const xxh_u8* const limit = bEnd - 16; + + do { + state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p)); p+=4; + state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p)); p+=4; + state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p)); p+=4; + state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p)); p+=4; + } while (p<=limit); + + } + + if (p < bEnd) { + XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + } + + return XXH_OK; +} + + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state) +{ + xxh_u32 h32; + + if (state->large_len) { + h32 = XXH_rotl32(state->v[0], 1) + + XXH_rotl32(state->v[1], 7) + + XXH_rotl32(state->v[2], 12) + + XXH_rotl32(state->v[3], 18); + } else { + h32 = state->v[2] /* == seed */ + XXH_PRIME32_5; + } + + h32 += state->total_len_32; + + return XXH32_finalize(h32, (const xxh_u8*)state->mem32, state->memsize, XXH_aligned); +} +#endif /* !XXH_NO_STREAM */ + +/******* Canonical representation *******/ + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); + XXH_memcpy(dst, &hash, sizeof(*dst)); +} +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) +{ + return XXH_readBE32(src); +} + + +#ifndef XXH_NO_LONG_LONG + +/* ******************************************************************* +* 64-bit hash functions +*********************************************************************/ +/*! + * @} + * @ingroup impl + * @{ + */ +/******* Memory access *******/ + +typedef XXH64_hash_t xxh_u64; + +#ifdef XXH_OLD_NAMES +# define U64 xxh_u64 +#endif + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) +/* + * Manual byteshift. Best for old compilers which don't inline memcpy. + * We actually directly use XXH_readLE64 and XXH_readBE64. + */ +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static xxh_u64 XXH_read64(const void* memPtr) +{ + return *(const xxh_u64*) memPtr; +} + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* + * __attribute__((aligned(1))) is supported by gcc and clang. Originally the + * documentation claimed that it only increased the alignment, but actually it + * can decrease it on gcc, clang, and icc: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, + * https://gcc.godbolt.org/z/xYez1j67Y. + */ +#ifdef XXH_OLD_NAMES +typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) unalign64; +#endif +static xxh_u64 XXH_read64(const void* ptr) +{ + typedef __attribute__((aligned(1))) xxh_u64 xxh_unalign64; + return *((const xxh_unalign64*)ptr); +} + +#else + +/* + * Portable and safe solution. Generally efficient. + * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html + */ +static xxh_u64 XXH_read64(const void* memPtr) +{ + xxh_u64 val; + XXH_memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap64 _byteswap_uint64 +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap64 __builtin_bswap64 +#else +static xxh_u64 XXH_swap64(xxh_u64 x) +{ + return ((x << 56) & 0xff00000000000000ULL) | + ((x << 40) & 0x00ff000000000000ULL) | + ((x << 24) & 0x0000ff0000000000ULL) | + ((x << 8) & 0x000000ff00000000ULL) | + ((x >> 8) & 0x00000000ff000000ULL) | + ((x >> 24) & 0x0000000000ff0000ULL) | + ((x >> 40) & 0x000000000000ff00ULL) | + ((x >> 56) & 0x00000000000000ffULL); +} +#endif + + +/* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */ +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) + +XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[0] + | ((xxh_u64)bytePtr[1] << 8) + | ((xxh_u64)bytePtr[2] << 16) + | ((xxh_u64)bytePtr[3] << 24) + | ((xxh_u64)bytePtr[4] << 32) + | ((xxh_u64)bytePtr[5] << 40) + | ((xxh_u64)bytePtr[6] << 48) + | ((xxh_u64)bytePtr[7] << 56); +} + +XXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[7] + | ((xxh_u64)bytePtr[6] << 8) + | ((xxh_u64)bytePtr[5] << 16) + | ((xxh_u64)bytePtr[4] << 24) + | ((xxh_u64)bytePtr[3] << 32) + | ((xxh_u64)bytePtr[2] << 40) + | ((xxh_u64)bytePtr[1] << 48) + | ((xxh_u64)bytePtr[0] << 56); +} + +#else +XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); +} + +static xxh_u64 XXH_readBE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); +} +#endif + +XXH_FORCE_INLINE xxh_u64 +XXH_readLE64_align(const void* ptr, XXH_alignment align) +{ + if (align==XXH_unaligned) + return XXH_readLE64(ptr); + else + return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr); +} + + +/******* xxh64 *******/ +/*! + * @} + * @defgroup XXH64_impl XXH64 implementation + * @ingroup impl + * + * Details on the XXH64 implementation. + * @{ + */ +/* #define rather that static const, to be used as initializers */ +#define XXH_PRIME64_1 0x9E3779B185EBCA87ULL /*!< 0b1001111000110111011110011011000110000101111010111100101010000111 */ +#define XXH_PRIME64_2 0xC2B2AE3D27D4EB4FULL /*!< 0b1100001010110010101011100011110100100111110101001110101101001111 */ +#define XXH_PRIME64_3 0x165667B19E3779F9ULL /*!< 0b0001011001010110011001111011000110011110001101110111100111111001 */ +#define XXH_PRIME64_4 0x85EBCA77C2B2AE63ULL /*!< 0b1000010111101011110010100111011111000010101100101010111001100011 */ +#define XXH_PRIME64_5 0x27D4EB2F165667C5ULL /*!< 0b0010011111010100111010110010111100010110010101100110011111000101 */ + +#ifdef XXH_OLD_NAMES +# define PRIME64_1 XXH_PRIME64_1 +# define PRIME64_2 XXH_PRIME64_2 +# define PRIME64_3 XXH_PRIME64_3 +# define PRIME64_4 XXH_PRIME64_4 +# define PRIME64_5 XXH_PRIME64_5 +#endif + +/*! @copydoc XXH32_round */ +static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input) +{ + acc += input * XXH_PRIME64_2; + acc = XXH_rotl64(acc, 31); + acc *= XXH_PRIME64_1; +#if (defined(__AVX512F__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) + /* + * DISABLE AUTOVECTORIZATION: + * A compiler fence is used to prevent GCC and Clang from + * autovectorizing the XXH64 loop (pragmas and attributes don't work for some + * reason) without globally disabling AVX512. + * + * Autovectorization of XXH64 tends to be detrimental, + * though the exact outcome may change depending on exact cpu and compiler version. + * For information, it has been reported as detrimental for Skylake-X, + * but possibly beneficial for Zen4. + * + * The default is to disable auto-vectorization, + * but you can select to enable it instead using `XXH_ENABLE_AUTOVECTORIZE` build variable. + */ + XXH_COMPILER_GUARD(acc); +#endif + return acc; +} + +static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val) +{ + val = XXH64_round(0, val); + acc ^= val; + acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4; + return acc; +} + +/*! @copydoc XXH32_avalanche */ +static xxh_u64 XXH64_avalanche(xxh_u64 hash) +{ + hash ^= hash >> 33; + hash *= XXH_PRIME64_2; + hash ^= hash >> 29; + hash *= XXH_PRIME64_3; + hash ^= hash >> 32; + return hash; +} + + +#define XXH_get64bits(p) XXH_readLE64_align(p, align) + +/*! + * @internal + * @brief Processes the last 0-31 bytes of @p ptr. + * + * There may be up to 31 bytes remaining to consume from the input. + * This final stage will digest them to ensure that all input bytes are present + * in the final mix. + * + * @param hash The hash to finalize. + * @param ptr The pointer to the remaining input. + * @param len The remaining length, modulo 32. + * @param align Whether @p ptr is aligned. + * @return The finalized hash + * @see XXH32_finalize(). + */ +static XXH_PUREF xxh_u64 +XXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) +{ + if (ptr==NULL) XXH_ASSERT(len == 0); + len &= 31; + while (len >= 8) { + xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr)); + ptr += 8; + hash ^= k1; + hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4; + len -= 8; + } + if (len >= 4) { + hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1; + ptr += 4; + hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3; + len -= 4; + } + while (len > 0) { + hash ^= (*ptr++) * XXH_PRIME64_5; + hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1; + --len; + } + return XXH64_avalanche(hash); +} + +#ifdef XXH_OLD_NAMES +# define PROCESS1_64 XXH_PROCESS1_64 +# define PROCESS4_64 XXH_PROCESS4_64 +# define PROCESS8_64 XXH_PROCESS8_64 +#else +# undef XXH_PROCESS1_64 +# undef XXH_PROCESS4_64 +# undef XXH_PROCESS8_64 +#endif + +/*! + * @internal + * @brief The implementation for @ref XXH64(). + * + * @param input , len , seed Directly passed from @ref XXH64(). + * @param align Whether @p input is aligned. + * @return The calculated hash. + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u64 +XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align) +{ + xxh_u64 h64; + if (input==NULL) XXH_ASSERT(len == 0); + + if (len>=32) { + const xxh_u8* const bEnd = input + len; + const xxh_u8* const limit = bEnd - 31; + xxh_u64 v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2; + xxh_u64 v2 = seed + XXH_PRIME64_2; + xxh_u64 v3 = seed + 0; + xxh_u64 v4 = seed - XXH_PRIME64_1; + + do { + v1 = XXH64_round(v1, XXH_get64bits(input)); input+=8; + v2 = XXH64_round(v2, XXH_get64bits(input)); input+=8; + v3 = XXH64_round(v3, XXH_get64bits(input)); input+=8; + v4 = XXH64_round(v4, XXH_get64bits(input)); input+=8; + } while (input= 2 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH64_state_t state; + XXH64_reset(&state, seed); + XXH64_update(&state, (const xxh_u8*)input, len); + return XXH64_digest(&state); +#else + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ + return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); + } } + + return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); + +#endif +} + +/******* Hash Streaming *******/ +#ifndef XXH_NO_STREAM +/*! @ingroup XXH64_family*/ +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) +{ + return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); +} +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dstState, const XXH64_state_t* srcState) +{ + XXH_memcpy(dstState, srcState, sizeof(*dstState)); +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed) +{ + XXH_ASSERT(statePtr != NULL); + memset(statePtr, 0, sizeof(*statePtr)); + statePtr->v[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2; + statePtr->v[1] = seed + XXH_PRIME64_2; + statePtr->v[2] = seed + 0; + statePtr->v[3] = seed - XXH_PRIME64_1; + return XXH_OK; +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH_errorcode +XXH64_update (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + if (input==NULL) { + XXH_ASSERT(len == 0); + return XXH_OK; + } + + { const xxh_u8* p = (const xxh_u8*)input; + const xxh_u8* const bEnd = p + len; + + state->total_len += len; + + if (state->memsize + len < 32) { /* fill in tmp buffer */ + XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, len); + state->memsize += (xxh_u32)len; + return XXH_OK; + } + + if (state->memsize) { /* tmp buffer is full */ + XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, 32-state->memsize); + state->v[0] = XXH64_round(state->v[0], XXH_readLE64(state->mem64+0)); + state->v[1] = XXH64_round(state->v[1], XXH_readLE64(state->mem64+1)); + state->v[2] = XXH64_round(state->v[2], XXH_readLE64(state->mem64+2)); + state->v[3] = XXH64_round(state->v[3], XXH_readLE64(state->mem64+3)); + p += 32 - state->memsize; + state->memsize = 0; + } + + if (p+32 <= bEnd) { + const xxh_u8* const limit = bEnd - 32; + + do { + state->v[0] = XXH64_round(state->v[0], XXH_readLE64(p)); p+=8; + state->v[1] = XXH64_round(state->v[1], XXH_readLE64(p)); p+=8; + state->v[2] = XXH64_round(state->v[2], XXH_readLE64(p)); p+=8; + state->v[3] = XXH64_round(state->v[3], XXH_readLE64(p)); p+=8; + } while (p<=limit); + + } + + if (p < bEnd) { + XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + } + + return XXH_OK; +} + + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t* state) +{ + xxh_u64 h64; + + if (state->total_len >= 32) { + h64 = XXH_rotl64(state->v[0], 1) + XXH_rotl64(state->v[1], 7) + XXH_rotl64(state->v[2], 12) + XXH_rotl64(state->v[3], 18); + h64 = XXH64_mergeRound(h64, state->v[0]); + h64 = XXH64_mergeRound(h64, state->v[1]); + h64 = XXH64_mergeRound(h64, state->v[2]); + h64 = XXH64_mergeRound(h64, state->v[3]); + } else { + h64 = state->v[2] /*seed*/ + XXH_PRIME64_5; + } + + h64 += (xxh_u64) state->total_len; + + return XXH64_finalize(h64, (const xxh_u8*)state->mem64, (size_t)state->total_len, XXH_aligned); +} +#endif /* !XXH_NO_STREAM */ + +/******* Canonical representation *******/ + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); + XXH_memcpy(dst, &hash, sizeof(*dst)); +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src) +{ + return XXH_readBE64(src); +} + +#ifndef XXH_NO_XXH3 + +/* ********************************************************************* +* XXH3 +* New generation hash designed for speed on small keys and vectorization +************************************************************************ */ +/*! + * @} + * @defgroup XXH3_impl XXH3 implementation + * @ingroup impl + * @{ + */ + +/* === Compiler specifics === */ + +#if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */ +# define XXH_RESTRICT /* disable */ +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ +# define XXH_RESTRICT restrict +#elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \ + || (defined (__clang__)) \ + || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \ + || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300)) +/* + * There are a LOT more compilers that recognize __restrict but this + * covers the major ones. + */ +# define XXH_RESTRICT __restrict +#else +# define XXH_RESTRICT /* disable */ +#endif + +#if (defined(__GNUC__) && (__GNUC__ >= 3)) \ + || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \ + || defined(__clang__) +# define XXH_likely(x) __builtin_expect(x, 1) +# define XXH_unlikely(x) __builtin_expect(x, 0) +#else +# define XXH_likely(x) (x) +# define XXH_unlikely(x) (x) +#endif + +#ifndef XXH_HAS_INCLUDE +# ifdef __has_include +/* + * Not defined as XXH_HAS_INCLUDE(x) (function-like) because + * this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion) + */ +# define XXH_HAS_INCLUDE __has_include +# else +# define XXH_HAS_INCLUDE(x) 0 +# endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# if defined(__ARM_FEATURE_SVE) +# include +# endif +# if defined(__ARM_NEON__) || defined(__ARM_NEON) \ + || (defined(_M_ARM) && _M_ARM >= 7) \ + || defined(_M_ARM64) || defined(_M_ARM64EC) \ + || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* WASM SIMD128 via SIMDe */ +# define inline __inline__ /* circumvent a clang bug */ +# include +# undef inline +# elif defined(__AVX2__) +# include +# elif defined(__SSE2__) +# include +# endif +#endif + +#if defined(_MSC_VER) +# include +#endif + +/* + * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while + * remaining a true 64-bit/128-bit hash function. + * + * This is done by prioritizing a subset of 64-bit operations that can be + * emulated without too many steps on the average 32-bit machine. + * + * For example, these two lines seem similar, and run equally fast on 64-bit: + * + * xxh_u64 x; + * x ^= (x >> 47); // good + * x ^= (x >> 13); // bad + * + * However, to a 32-bit machine, there is a major difference. + * + * x ^= (x >> 47) looks like this: + * + * x.lo ^= (x.hi >> (47 - 32)); + * + * while x ^= (x >> 13) looks like this: + * + * // note: funnel shifts are not usually cheap. + * x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13)); + * x.hi ^= (x.hi >> 13); + * + * The first one is significantly faster than the second, simply because the + * shift is larger than 32. This means: + * - All the bits we need are in the upper 32 bits, so we can ignore the lower + * 32 bits in the shift. + * - The shift result will always fit in the lower 32 bits, and therefore, + * we can ignore the upper 32 bits in the xor. + * + * Thanks to this optimization, XXH3 only requires these features to be efficient: + * + * - Usable unaligned access + * - A 32-bit or 64-bit ALU + * - If 32-bit, a decent ADC instruction + * - A 32 or 64-bit multiply with a 64-bit result + * - For the 128-bit variant, a decent byteswap helps short inputs. + * + * The first two are already required by XXH32, and almost all 32-bit and 64-bit + * platforms which can run XXH32 can run XXH3 efficiently. + * + * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one + * notable exception. + * + * First of all, Thumb-1 lacks support for the UMULL instruction which + * performs the important long multiply. This means numerous __aeabi_lmul + * calls. + * + * Second of all, the 8 functional registers are just not enough. + * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need + * Lo registers, and this shuffling results in thousands more MOVs than A32. + * + * A32 and T32 don't have this limitation. They can access all 14 registers, + * do a 32->64 multiply with UMULL, and the flexible operand allowing free + * shifts is helpful, too. + * + * Therefore, we do a quick sanity check. + * + * If compiling Thumb-1 for a target which supports ARM instructions, we will + * emit a warning, as it is not a "sane" platform to compile for. + * + * Usually, if this happens, it is because of an accident and you probably need + * to specify -march, as you likely meant to compile for a newer architecture. + * + * Credit: large sections of the vectorial and asm source code paths + * have been contributed by @easyaspi314 + */ +#if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM) +# warning "XXH3 is highly inefficient without ARM or Thumb-2." +#endif + +/* ========================================== + * Vectorization detection + * ========================================== */ + +#ifdef XXH_DOXYGEN +/*! + * @ingroup tuning + * @brief Overrides the vectorization implementation chosen for XXH3. + * + * Can be defined to 0 to disable SIMD or any of the values mentioned in + * @ref XXH_VECTOR_TYPE. + * + * If this is not defined, it uses predefined macros to determine the best + * implementation. + */ +# define XXH_VECTOR XXH_SCALAR +/*! + * @ingroup tuning + * @brief Possible values for @ref XXH_VECTOR. + * + * Note that these are actually implemented as macros. + * + * If this is not defined, it is detected automatically. + * internal macro XXH_X86DISPATCH overrides this. + */ +enum XXH_VECTOR_TYPE /* fake enum */ { + XXH_SCALAR = 0, /*!< Portable scalar version */ + XXH_SSE2 = 1, /*!< + * SSE2 for Pentium 4, Opteron, all x86_64. + * + * @note SSE2 is also guaranteed on Windows 10, macOS, and + * Android x86. + */ + XXH_AVX2 = 2, /*!< AVX2 for Haswell and Bulldozer */ + XXH_AVX512 = 3, /*!< AVX512 for Skylake and Icelake */ + XXH_NEON = 4, /*!< + * NEON for most ARMv7-A, all AArch64, and WASM SIMD128 + * via the SIMDeverywhere polyfill provided with the + * Emscripten SDK. + */ + XXH_VSX = 5, /*!< VSX and ZVector for POWER8/z13 (64-bit) */ + XXH_SVE = 6, /*!< SVE for some ARMv8-A and ARMv9-A */ +}; +/*! + * @ingroup tuning + * @brief Selects the minimum alignment for XXH3's accumulators. + * + * When using SIMD, this should match the alignment required for said vector + * type, so, for example, 32 for AVX2. + * + * Default: Auto detected. + */ +# define XXH_ACC_ALIGN 8 +#endif + +/* Actual definition */ +#ifndef XXH_DOXYGEN +# define XXH_SCALAR 0 +# define XXH_SSE2 1 +# define XXH_AVX2 2 +# define XXH_AVX512 3 +# define XXH_NEON 4 +# define XXH_VSX 5 +# define XXH_SVE 6 +#endif + +#ifndef XXH_VECTOR /* can be defined on command line */ +# if defined(__ARM_FEATURE_SVE) +# define XXH_VECTOR XXH_SVE +# elif ( \ + defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \ + || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \ + || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* wasm simd128 via SIMDe */ \ + ) && ( \ + defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \ + ) +# define XXH_VECTOR XXH_NEON +# elif defined(__AVX512F__) +# define XXH_VECTOR XXH_AVX512 +# elif defined(__AVX2__) +# define XXH_VECTOR XXH_AVX2 +# elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) +# define XXH_VECTOR XXH_SSE2 +# elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \ + || (defined(__s390x__) && defined(__VEC__)) \ + && defined(__GNUC__) /* TODO: IBM XL */ +# define XXH_VECTOR XXH_VSX +# else +# define XXH_VECTOR XXH_SCALAR +# endif +#endif + +/* __ARM_FEATURE_SVE is only supported by GCC & Clang. */ +#if (XXH_VECTOR == XXH_SVE) && !defined(__ARM_FEATURE_SVE) +# ifdef _MSC_VER +# pragma warning(once : 4606) +# else +# warning "__ARM_FEATURE_SVE isn't supported. Use SCALAR instead." +# endif +# undef XXH_VECTOR +# define XXH_VECTOR XXH_SCALAR +#endif + +/* + * Controls the alignment of the accumulator, + * for compatibility with aligned vector loads, which are usually faster. + */ +#ifndef XXH_ACC_ALIGN +# if defined(XXH_X86DISPATCH) +# define XXH_ACC_ALIGN 64 /* for compatibility with avx512 */ +# elif XXH_VECTOR == XXH_SCALAR /* scalar */ +# define XXH_ACC_ALIGN 8 +# elif XXH_VECTOR == XXH_SSE2 /* sse2 */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_AVX2 /* avx2 */ +# define XXH_ACC_ALIGN 32 +# elif XXH_VECTOR == XXH_NEON /* neon */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_VSX /* vsx */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_AVX512 /* avx512 */ +# define XXH_ACC_ALIGN 64 +# elif XXH_VECTOR == XXH_SVE /* sve */ +# define XXH_ACC_ALIGN 64 +# endif +#endif + +#if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \ + || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512 +# define XXH_SEC_ALIGN XXH_ACC_ALIGN +#elif XXH_VECTOR == XXH_SVE +# define XXH_SEC_ALIGN XXH_ACC_ALIGN +#else +# define XXH_SEC_ALIGN 8 +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define XXH_ALIASING __attribute__((may_alias)) +#else +# define XXH_ALIASING /* nothing */ +#endif + +/* + * UGLY HACK: + * GCC usually generates the best code with -O3 for xxHash. + * + * However, when targeting AVX2, it is overzealous in its unrolling resulting + * in code roughly 3/4 the speed of Clang. + * + * There are other issues, such as GCC splitting _mm256_loadu_si256 into + * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which + * only applies to Sandy and Ivy Bridge... which don't even support AVX2. + * + * That is why when compiling the AVX2 version, it is recommended to use either + * -O2 -mavx2 -march=haswell + * or + * -O2 -mavx2 -mno-avx256-split-unaligned-load + * for decent performance, or to use Clang instead. + * + * Fortunately, we can control the first one with a pragma that forces GCC into + * -O2, but the other one we can't control without "failed to inline always + * inline function due to target mismatch" warnings. + */ +#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \ + && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ + && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */ +# pragma GCC push_options +# pragma GCC optimize("-O2") +#endif + +#if XXH_VECTOR == XXH_NEON + +/* + * UGLY HACK: While AArch64 GCC on Linux does not seem to care, on macOS, GCC -O3 + * optimizes out the entire hashLong loop because of the aliasing violation. + * + * However, GCC is also inefficient at load-store optimization with vld1q/vst1q, + * so the only option is to mark it as aliasing. + */ +typedef uint64x2_t xxh_aliasing_uint64x2_t XXH_ALIASING; + +/*! + * @internal + * @brief `vld1q_u64` but faster and alignment-safe. + * + * On AArch64, unaligned access is always safe, but on ARMv7-a, it is only + * *conditionally* safe (`vld1` has an alignment bit like `movdq[ua]` in x86). + * + * GCC for AArch64 sees `vld1q_u8` as an intrinsic instead of a load, so it + * prohibits load-store optimizations. Therefore, a direct dereference is used. + * + * Otherwise, `vld1q_u8` is used with `vreinterpretq_u8_u64` to do a safe + * unaligned load. + */ +#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) +XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */ +{ + return *(xxh_aliasing_uint64x2_t const *)ptr; +} +#else +XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) +{ + return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr)); +} +#endif + +/*! + * @internal + * @brief `vmlal_u32` on low and high halves of a vector. + * + * This is a workaround for AArch64 GCC < 11 which implemented arm_neon.h with + * inline assembly and were therefore incapable of merging the `vget_{low, high}_u32` + * with `vmlal_u32`. + */ +#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 11 +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + /* Inline assembly is the only way */ + __asm__("umlal %0.2d, %1.2s, %2.2s" : "+w" (acc) : "w" (lhs), "w" (rhs)); + return acc; +} +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + /* This intrinsic works as expected */ + return vmlal_high_u32(acc, lhs, rhs); +} +#else +/* Portable intrinsic versions */ +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + return vmlal_u32(acc, vget_low_u32(lhs), vget_low_u32(rhs)); +} +/*! @copydoc XXH_vmlal_low_u32 + * Assume the compiler converts this to vmlal_high_u32 on aarch64 */ +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + return vmlal_u32(acc, vget_high_u32(lhs), vget_high_u32(rhs)); +} +#endif + +/*! + * @ingroup tuning + * @brief Controls the NEON to scalar ratio for XXH3 + * + * This can be set to 2, 4, 6, or 8. + * + * ARM Cortex CPUs are _very_ sensitive to how their pipelines are used. + * + * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but only 2 of those + * can be NEON. If you are only using NEON instructions, you are only using 2/3 of the CPU + * bandwidth. + * + * This is even more noticeable on the more advanced cores like the Cortex-A76 which + * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once. + * + * Therefore, to make the most out of the pipeline, it is beneficial to run 6 NEON lanes + * and 2 scalar lanes, which is chosen by default. + * + * This does not apply to Apple processors or 32-bit processors, which run better with + * full NEON. These will default to 8. Additionally, size-optimized builds run 8 lanes. + * + * This change benefits CPUs with large micro-op buffers without negatively affecting + * most other CPUs: + * + * | Chipset | Dispatch type | NEON only | 6:2 hybrid | Diff. | + * |:----------------------|:--------------------|----------:|-----------:|------:| + * | Snapdragon 730 (A76) | 2 NEON/8 micro-ops | 8.8 GB/s | 10.1 GB/s | ~16% | + * | Snapdragon 835 (A73) | 2 NEON/3 micro-ops | 5.1 GB/s | 5.3 GB/s | ~5% | + * | Marvell PXA1928 (A53) | In-order dual-issue | 1.9 GB/s | 1.9 GB/s | 0% | + * | Apple M1 | 4 NEON/8 micro-ops | 37.3 GB/s | 36.1 GB/s | ~-3% | + * + * It also seems to fix some bad codegen on GCC, making it almost as fast as clang. + * + * When using WASM SIMD128, if this is 2 or 6, SIMDe will scalarize 2 of the lanes meaning + * it effectively becomes worse 4. + * + * @see XXH3_accumulate_512_neon() + */ +# ifndef XXH3_NEON_LANES +# if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \ + && !defined(__APPLE__) && XXH_SIZE_OPT <= 0 +# define XXH3_NEON_LANES 6 +# else +# define XXH3_NEON_LANES XXH_ACC_NB +# endif +# endif +#endif /* XXH_VECTOR == XXH_NEON */ + +/* + * VSX and Z Vector helpers. + * + * This is very messy, and any pull requests to clean this up are welcome. + * + * There are a lot of problems with supporting VSX and s390x, due to + * inconsistent intrinsics, spotty coverage, and multiple endiannesses. + */ +#if XXH_VECTOR == XXH_VSX +/* Annoyingly, these headers _may_ define three macros: `bool`, `vector`, + * and `pixel`. This is a problem for obvious reasons. + * + * These keywords are unnecessary; the spec literally says they are + * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd + * after including the header. + * + * We use pragma push_macro/pop_macro to keep the namespace clean. */ +# pragma push_macro("bool") +# pragma push_macro("vector") +# pragma push_macro("pixel") +/* silence potential macro redefined warnings */ +# undef bool +# undef vector +# undef pixel + +# if defined(__s390x__) +# include +# else +# include +# endif + +/* Restore the original macro values, if applicable. */ +# pragma pop_macro("pixel") +# pragma pop_macro("vector") +# pragma pop_macro("bool") + +typedef __vector unsigned long long xxh_u64x2; +typedef __vector unsigned char xxh_u8x16; +typedef __vector unsigned xxh_u32x4; + +/* + * UGLY HACK: Similar to aarch64 macOS GCC, s390x GCC has the same aliasing issue. + */ +typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING; + +# ifndef XXH_VSX_BE +# if defined(__BIG_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define XXH_VSX_BE 1 +# elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__ +# warning "-maltivec=be is not recommended. Please use native endianness." +# define XXH_VSX_BE 1 +# else +# define XXH_VSX_BE 0 +# endif +# endif /* !defined(XXH_VSX_BE) */ + +# if XXH_VSX_BE +# if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__)) +# define XXH_vec_revb vec_revb +# else +/*! + * A polyfill for POWER9's vec_revb(). + */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val) +{ + xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + return vec_perm(val, val, vByteSwap); +} +# endif +# endif /* XXH_VSX_BE */ + +/*! + * Performs an unaligned vector load and byte swaps it on big endian. + */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr) +{ + xxh_u64x2 ret; + XXH_memcpy(&ret, ptr, sizeof(xxh_u64x2)); +# if XXH_VSX_BE + ret = XXH_vec_revb(ret); +# endif + return ret; +} + +/* + * vec_mulo and vec_mule are very problematic intrinsics on PowerPC + * + * These intrinsics weren't added until GCC 8, despite existing for a while, + * and they are endian dependent. Also, their meaning swap depending on version. + * */ +# if defined(__s390x__) + /* s390x is always big endian, no issue on this platform */ +# define XXH_vec_mulo vec_mulo +# define XXH_vec_mule vec_mule +# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) && !defined(__ibmxl__) +/* Clang has a better way to control this, we can just use the builtin which doesn't swap. */ + /* The IBM XL Compiler (which defined __clang__) only implements the vec_* operations */ +# define XXH_vec_mulo __builtin_altivec_vmulouw +# define XXH_vec_mule __builtin_altivec_vmuleuw +# else +/* gcc needs inline assembly */ +/* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b) +{ + xxh_u64x2 result; + __asm__("vmulouw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); + return result; +} +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) +{ + xxh_u64x2 result; + __asm__("vmuleuw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); + return result; +} +# endif /* XXH_vec_mulo, XXH_vec_mule */ +#endif /* XXH_VECTOR == XXH_VSX */ + +#if XXH_VECTOR == XXH_SVE +#define ACCRND(acc, offset) \ +do { \ + svuint64_t input_vec = svld1_u64(mask, xinput + offset); \ + svuint64_t secret_vec = svld1_u64(mask, xsecret + offset); \ + svuint64_t mixed = sveor_u64_x(mask, secret_vec, input_vec); \ + svuint64_t swapped = svtbl_u64(input_vec, kSwap); \ + svuint64_t mixed_lo = svextw_u64_x(mask, mixed); \ + svuint64_t mixed_hi = svlsr_n_u64_x(mask, mixed, 32); \ + svuint64_t mul = svmad_u64_x(mask, mixed_lo, mixed_hi, swapped); \ + acc = svadd_u64_x(mask, acc, mul); \ +} while (0) +#endif /* XXH_VECTOR == XXH_SVE */ + +/* prefetch + * can be disabled, by declaring XXH_NO_PREFETCH build macro */ +#if defined(XXH_NO_PREFETCH) +# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ +#else +# if XXH_SIZE_OPT >= 1 +# define XXH_PREFETCH(ptr) (void)(ptr) +# elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */ +# include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ +# define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) +# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) +# define XXH_PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) +# else +# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ +# endif +#endif /* XXH_NO_PREFETCH */ + + +/* ========================================== + * XXH3 default settings + * ========================================== */ + +#define XXH_SECRET_DEFAULT_SIZE 192 /* minimum XXH3_SECRET_SIZE_MIN */ + +#if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN) +# error "default keyset is not large enough" +#endif + +/*! Pseudorandom secret taken directly from FARSH. */ +XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = { + 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c, + 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f, + 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21, + 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c, + 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3, + 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8, + 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d, + 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64, + 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb, + 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e, + 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce, + 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e, +}; + +static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!< 0b0001011001010110011001111001000110011110001101110111100111111001 */ +static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!< 0b1001111110110010000111000110010100011110100110001101111100100101 */ + +#ifdef XXH_OLD_NAMES +# define kSecret XXH3_kSecret +#endif + +#ifdef XXH_DOXYGEN +/*! + * @brief Calculates a 32-bit to 64-bit long multiply. + * + * Implemented as a macro. + * + * Wraps `__emulu` on MSVC x86 because it tends to call `__allmul` when it doesn't + * need to (but it shouldn't need to anyways, it is about 7 instructions to do + * a 64x64 multiply...). Since we know that this will _always_ emit `MULL`, we + * use that instead of the normal method. + * + * If you are compiling for platforms like Thumb-1 and don't have a better option, + * you may also want to write your own long multiply routine here. + * + * @param x, y Numbers to be multiplied + * @return 64-bit product of the low 32 bits of @p x and @p y. + */ +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64(xxh_u64 x, xxh_u64 y) +{ + return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF); +} +#elif defined(_MSC_VER) && defined(_M_IX86) +# define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y)) +#else +/* + * Downcast + upcast is usually better than masking on older compilers like + * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers. + * + * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands + * and perform a full 64x64 multiply -- entirely redundant on 32-bit. + */ +# define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y)) +#endif + +/*! + * @brief Calculates a 64->128-bit long multiply. + * + * Uses `__uint128_t` and `_umul128` if available, otherwise uses a scalar + * version. + * + * @param lhs , rhs The 64-bit integers to be multiplied + * @return The 128-bit result represented in an @ref XXH128_hash_t. + */ +static XXH128_hash_t +XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs) +{ + /* + * GCC/Clang __uint128_t method. + * + * On most 64-bit targets, GCC and Clang define a __uint128_t type. + * This is usually the best way as it usually uses a native long 64-bit + * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64. + * + * Usually. + * + * Despite being a 32-bit platform, Clang (and emscripten) define this type + * despite not having the arithmetic for it. This results in a laggy + * compiler builtin call which calculates a full 128-bit multiply. + * In that case it is best to use the portable one. + * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677 + */ +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \ + && defined(__SIZEOF_INT128__) \ + || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128) + + __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs; + XXH128_hash_t r128; + r128.low64 = (xxh_u64)(product); + r128.high64 = (xxh_u64)(product >> 64); + return r128; + + /* + * MSVC for x64's _umul128 method. + * + * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct); + * + * This compiles to single operand MUL on x64. + */ +#elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC) + +#ifndef _MSC_VER +# pragma intrinsic(_umul128) +#endif + xxh_u64 product_high; + xxh_u64 const product_low = _umul128(lhs, rhs, &product_high); + XXH128_hash_t r128; + r128.low64 = product_low; + r128.high64 = product_high; + return r128; + + /* + * MSVC for ARM64's __umulh method. + * + * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method. + */ +#elif defined(_M_ARM64) || defined(_M_ARM64EC) + +#ifndef _MSC_VER +# pragma intrinsic(__umulh) +#endif + XXH128_hash_t r128; + r128.low64 = lhs * rhs; + r128.high64 = __umulh(lhs, rhs); + return r128; + +#else + /* + * Portable scalar method. Optimized for 32-bit and 64-bit ALUs. + * + * This is a fast and simple grade school multiply, which is shown below + * with base 10 arithmetic instead of base 0x100000000. + * + * 9 3 // D2 lhs = 93 + * x 7 5 // D2 rhs = 75 + * ---------- + * 1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15 + * 4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45 + * 2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21 + * + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63 + * --------- + * 2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27 + * + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67 + * --------- + * 6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975 + * + * The reasons for adding the products like this are: + * 1. It avoids manual carry tracking. Just like how + * (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX. + * This avoids a lot of complexity. + * + * 2. It hints for, and on Clang, compiles to, the powerful UMAAL + * instruction available in ARM's Digital Signal Processing extension + * in 32-bit ARMv6 and later, which is shown below: + * + * void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm) + * { + * xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm; + * *RdLo = (xxh_u32)(product & 0xFFFFFFFF); + * *RdHi = (xxh_u32)(product >> 32); + * } + * + * This instruction was designed for efficient long multiplication, and + * allows this to be calculated in only 4 instructions at speeds + * comparable to some 64-bit ALUs. + * + * 3. It isn't terrible on other platforms. Usually this will be a couple + * of 32-bit ADD/ADCs. + */ + + /* First calculate all of the cross products. */ + xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF); + xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF); + xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32); + xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32); + + /* Now add the products together. These will never overflow. */ + xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi; + xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32) + hi_hi; + xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF); + + XXH128_hash_t r128; + r128.low64 = lower; + r128.high64 = upper; + return r128; +#endif +} + +/*! + * @brief Calculates a 64-bit to 128-bit multiply, then XOR folds it. + * + * The reason for the separate function is to prevent passing too many structs + * around by value. This will hopefully inline the multiply, but we don't force it. + * + * @param lhs , rhs The 64-bit integers to multiply + * @return The low 64 bits of the product XOR'd by the high 64 bits. + * @see XXH_mult64to128() + */ +static xxh_u64 +XXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs) +{ + XXH128_hash_t product = XXH_mult64to128(lhs, rhs); + return product.low64 ^ product.high64; +} + +/*! Seems to produce slightly better code on GCC for some reason. */ +XXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift) +{ + XXH_ASSERT(0 <= shift && shift < 64); + return v64 ^ (v64 >> shift); +} + +/* + * This is a fast avalanche stage, + * suitable when input bits are already partially mixed + */ +static XXH64_hash_t XXH3_avalanche(xxh_u64 h64) +{ + h64 = XXH_xorshift64(h64, 37); + h64 *= PRIME_MX1; + h64 = XXH_xorshift64(h64, 32); + return h64; +} + +/* + * This is a stronger avalanche, + * inspired by Pelle Evensen's rrmxmx + * preferable when input has not been previously mixed + */ +static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len) +{ + /* this mix is inspired by Pelle Evensen's rrmxmx */ + h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24); + h64 *= PRIME_MX2; + h64 ^= (h64 >> 35) + len ; + h64 *= PRIME_MX2; + return XXH_xorshift64(h64, 28); +} + + +/* ========================================== + * Short keys + * ========================================== + * One of the shortcomings of XXH32 and XXH64 was that their performance was + * sub-optimal on short lengths. It used an iterative algorithm which strongly + * favored lengths that were a multiple of 4 or 8. + * + * Instead of iterating over individual inputs, we use a set of single shot + * functions which piece together a range of lengths and operate in constant time. + * + * Additionally, the number of multiplies has been significantly reduced. This + * reduces latency, especially when emulating 64-bit multiplies on 32-bit. + * + * Depending on the platform, this may or may not be faster than XXH32, but it + * is almost guaranteed to be faster than XXH64. + */ + +/* + * At very short lengths, there isn't enough input to fully hide secrets, or use + * the entire secret. + * + * There is also only a limited amount of mixing we can do before significantly + * impacting performance. + * + * Therefore, we use different sections of the secret and always mix two secret + * samples with an XOR. This should have no effect on performance on the + * seedless or withSeed variants because everything _should_ be constant folded + * by modern compilers. + * + * The XOR mixing hides individual parts of the secret and increases entropy. + * + * This adds an extra layer of strength for custom secrets. + */ +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(1 <= len && len <= 3); + XXH_ASSERT(secret != NULL); + /* + * len = 1: combined = { input[0], 0x01, input[0], input[0] } + * len = 2: combined = { input[1], 0x02, input[0], input[1] } + * len = 3: combined = { input[2], 0x03, input[0], input[1] } + */ + { xxh_u8 const c1 = input[0]; + xxh_u8 const c2 = input[len >> 1]; + xxh_u8 const c3 = input[len - 1]; + xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2 << 24) + | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); + xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; + xxh_u64 const keyed = (xxh_u64)combined ^ bitflip; + return XXH64_avalanche(keyed); + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(4 <= len && len <= 8); + seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; + { xxh_u32 const input1 = XXH_readLE32(input); + xxh_u32 const input2 = XXH_readLE32(input + len - 4); + xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed; + xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32); + xxh_u64 const keyed = input64 ^ bitflip; + return XXH3_rrmxmx(keyed, len); + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(9 <= len && len <= 16); + { xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed; + xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed; + xxh_u64 const input_lo = XXH_readLE64(input) ^ bitflip1; + xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2; + xxh_u64 const acc = len + + XXH_swap64(input_lo) + input_hi + + XXH3_mul128_fold64(input_lo, input_hi); + return XXH3_avalanche(acc); + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(len <= 16); + { if (XXH_likely(len > 8)) return XXH3_len_9to16_64b(input, len, secret, seed); + if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed); + if (len) return XXH3_len_1to3_64b(input, len, secret, seed); + return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64))); + } +} + +/* + * DISCLAIMER: There are known *seed-dependent* multicollisions here due to + * multiplication by zero, affecting hashes of lengths 17 to 240. + * + * However, they are very unlikely. + * + * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all + * unseeded non-cryptographic hashes, it does not attempt to defend itself + * against specially crafted inputs, only random inputs. + * + * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes + * cancelling out the secret is taken an arbitrary number of times (addressed + * in XXH3_accumulate_512), this collision is very unlikely with random inputs + * and/or proper seeding: + * + * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a + * function that is only called up to 16 times per hash with up to 240 bytes of + * input. + * + * This is not too bad for a non-cryptographic hash function, especially with + * only 64 bit outputs. + * + * The 128-bit variant (which trades some speed for strength) is NOT affected + * by this, although it is always a good idea to use a proper seed if you care + * about strength. + */ +XXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input, + const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64) +{ +#if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ + && defined(__i386__) && defined(__SSE2__) /* x86 + SSE2 */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable like XXH32 hack */ + /* + * UGLY HACK: + * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in + * slower code. + * + * By forcing seed64 into a register, we disrupt the cost model and + * cause it to scalarize. See `XXH32_round()` + * + * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600, + * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on + * GCC 9.2, despite both emitting scalar code. + * + * GCC generates much better scalar code than Clang for the rest of XXH3, + * which is why finding a more optimal codepath is an interest. + */ + XXH_COMPILER_GUARD(seed64); +#endif + { xxh_u64 const input_lo = XXH_readLE64(input); + xxh_u64 const input_hi = XXH_readLE64(input+8); + return XXH3_mul128_fold64( + input_lo ^ (XXH_readLE64(secret) + seed64), + input_hi ^ (XXH_readLE64(secret+8) - seed64) + ); + } +} + +/* For mid range keys, XXH3 uses a Mum-hash variant. */ +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(16 < len && len <= 128); + + { xxh_u64 acc = len * XXH_PRIME64_1; +#if XXH_SIZE_OPT >= 1 + /* Smaller and cleaner, but slightly slower. */ + unsigned int i = (unsigned int)(len - 1) / 32; + do { + acc += XXH3_mix16B(input+16 * i, secret+32*i, seed); + acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed); + } while (i-- != 0); +#else + if (len > 32) { + if (len > 64) { + if (len > 96) { + acc += XXH3_mix16B(input+48, secret+96, seed); + acc += XXH3_mix16B(input+len-64, secret+112, seed); + } + acc += XXH3_mix16B(input+32, secret+64, seed); + acc += XXH3_mix16B(input+len-48, secret+80, seed); + } + acc += XXH3_mix16B(input+16, secret+32, seed); + acc += XXH3_mix16B(input+len-32, secret+48, seed); + } + acc += XXH3_mix16B(input+0, secret+0, seed); + acc += XXH3_mix16B(input+len-16, secret+16, seed); +#endif + return XXH3_avalanche(acc); + } +} + +/*! + * @brief Maximum size of "short" key in bytes. + */ +#define XXH3_MIDSIZE_MAX 240 + +XXH_NO_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + + #define XXH3_MIDSIZE_STARTOFFSET 3 + #define XXH3_MIDSIZE_LASTOFFSET 17 + + { xxh_u64 acc = len * XXH_PRIME64_1; + xxh_u64 acc_end; + unsigned int const nbRounds = (unsigned int)len / 16; + unsigned int i; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + for (i=0; i<8; i++) { + acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed); + } + /* last bytes */ + acc_end = XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed); + XXH_ASSERT(nbRounds >= 8); + acc = XXH3_avalanche(acc); +#if defined(__clang__) /* Clang */ \ + && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ + /* + * UGLY HACK: + * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86. + * In everywhere else, it uses scalar code. + * + * For 64->128-bit multiplies, even if the NEON was 100% optimal, it + * would still be slower than UMAAL (see XXH_mult64to128). + * + * Unfortunately, Clang doesn't handle the long multiplies properly and + * converts them to the nonexistent "vmulq_u64" intrinsic, which is then + * scalarized into an ugly mess of VMOV.32 instructions. + * + * This mess is difficult to avoid without turning autovectorization + * off completely, but they are usually relatively minor and/or not + * worth it to fix. + * + * This loop is the easiest to fix, as unlike XXH32, this pragma + * _actually works_ because it is a loop vectorization instead of an + * SLP vectorization. + */ + #pragma clang loop vectorize(disable) +#endif + for (i=8 ; i < nbRounds; i++) { + /* + * Prevents clang for unrolling the acc loop and interleaving with this one. + */ + XXH_COMPILER_GUARD(acc); + acc_end += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed); + } + return XXH3_avalanche(acc + acc_end); + } +} + + +/* ======= Long Keys ======= */ + +#define XXH_STRIPE_LEN 64 +#define XXH_SECRET_CONSUME_RATE 8 /* nb of secret bytes consumed at each accumulation */ +#define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64)) + +#ifdef XXH_OLD_NAMES +# define STRIPE_LEN XXH_STRIPE_LEN +# define ACC_NB XXH_ACC_NB +#endif + +#ifndef XXH_PREFETCH_DIST +# ifdef __clang__ +# define XXH_PREFETCH_DIST 320 +# else +# if (XXH_VECTOR == XXH_AVX512) +# define XXH_PREFETCH_DIST 512 +# else +# define XXH_PREFETCH_DIST 384 +# endif +# endif /* __clang__ */ +#endif /* XXH_PREFETCH_DIST */ + +/* + * These macros are to generate an XXH3_accumulate() function. + * The two arguments select the name suffix and target attribute. + * + * The name of this symbol is XXH3_accumulate_() and it calls + * XXH3_accumulate_512_(). + * + * It may be useful to hand implement this function if the compiler fails to + * optimize the inline function. + */ +#define XXH3_ACCUMULATE_TEMPLATE(name) \ +void \ +XXH3_accumulate_##name(xxh_u64* XXH_RESTRICT acc, \ + const xxh_u8* XXH_RESTRICT input, \ + const xxh_u8* XXH_RESTRICT secret, \ + size_t nbStripes) \ +{ \ + size_t n; \ + for (n = 0; n < nbStripes; n++ ) { \ + const xxh_u8* const in = input + n*XXH_STRIPE_LEN; \ + XXH_PREFETCH(in + XXH_PREFETCH_DIST); \ + XXH3_accumulate_512_##name( \ + acc, \ + in, \ + secret + n*XXH_SECRET_CONSUME_RATE); \ + } \ +} + + +XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64) +{ + if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64); + XXH_memcpy(dst, &v64, sizeof(v64)); +} + +/* Several intrinsic functions below are supposed to accept __int64 as argument, + * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ . + * However, several environments do not define __int64 type, + * requiring a workaround. + */ +#if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) + typedef int64_t xxh_i64; +#else + /* the following type must have a width of 64-bit */ + typedef long long xxh_i64; +#endif + + +/* + * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized. + * + * It is a hardened version of UMAC, based off of FARSH's implementation. + * + * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD + * implementations, and it is ridiculously fast. + * + * We harden it by mixing the original input to the accumulators as well as the product. + * + * This means that in the (relatively likely) case of a multiply by zero, the + * original input is preserved. + * + * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve + * cross-pollination, as otherwise the upper and lower halves would be + * essentially independent. + * + * This doesn't matter on 64-bit hashes since they all get merged together in + * the end, so we skip the extra step. + * + * Both XXH3_64bits and XXH3_128bits use this subroutine. + */ + +#if (XXH_VECTOR == XXH_AVX512) \ + || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0) + +#ifndef XXH_TARGET_AVX512 +# define XXH_TARGET_AVX512 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + __m512i* const xacc = (__m512i *) acc; + XXH_ASSERT((((size_t)acc) & 63) == 0); + XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); + + { + /* data_vec = input[0]; */ + __m512i const data_vec = _mm512_loadu_si512 (input); + /* key_vec = secret[0]; */ + __m512i const key_vec = _mm512_loadu_si512 (secret); + /* data_key = data_vec ^ key_vec; */ + __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m512i const data_key_lo = _mm512_srli_epi64 (data_key, 32); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m512i const product = _mm512_mul_epu32 (data_key, data_key_lo); + /* xacc[0] += swap(data_vec); */ + __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2)); + __m512i const sum = _mm512_add_epi64(*xacc, data_swap); + /* xacc[0] += product; */ + *xacc = _mm512_add_epi64(product, sum); + } +} +XXH_FORCE_INLINE XXH_TARGET_AVX512 XXH3_ACCUMULATE_TEMPLATE(avx512) + +/* + * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing. + * + * Multiplication isn't perfect, as explained by Google in HighwayHash: + * + * // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to + * // varying degrees. In descending order of goodness, bytes + * // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32. + * // As expected, the upper and lower bytes are much worse. + * + * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291 + * + * Since our algorithm uses a pseudorandom secret to add some variance into the + * mix, we don't need to (or want to) mix as often or as much as HighwayHash does. + * + * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid + * extraction. + * + * Both XXH3_64bits and XXH3_128bits use this subroutine. + */ + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 63) == 0); + XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); + { __m512i* const xacc = (__m512i*) acc; + const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1); + + /* xacc[0] ^= (xacc[0] >> 47) */ + __m512i const acc_vec = *xacc; + __m512i const shifted = _mm512_srli_epi64 (acc_vec, 47); + /* xacc[0] ^= secret; */ + __m512i const key_vec = _mm512_loadu_si512 (secret); + __m512i const data_key = _mm512_ternarylogic_epi32(key_vec, acc_vec, shifted, 0x96 /* key_vec ^ acc_vec ^ shifted */); + + /* xacc[0] *= XXH_PRIME32_1; */ + __m512i const data_key_hi = _mm512_srli_epi64 (data_key, 32); + __m512i const prod_lo = _mm512_mul_epu32 (data_key, prime32); + __m512i const prod_hi = _mm512_mul_epu32 (data_key_hi, prime32); + *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32)); + } +} + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0); + XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64); + XXH_ASSERT(((size_t)customSecret & 63) == 0); + (void)(&XXH_writeLE64); + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i); + __m512i const seed_pos = _mm512_set1_epi64((xxh_i64)seed64); + __m512i const seed = _mm512_mask_sub_epi64(seed_pos, 0xAA, _mm512_set1_epi8(0), seed_pos); + + const __m512i* const src = (const __m512i*) ((const void*) XXH3_kSecret); + __m512i* const dest = ( __m512i*) customSecret; + int i; + XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */ + XXH_ASSERT(((size_t)dest & 63) == 0); + for (i=0; i < nbRounds; ++i) { + dest[i] = _mm512_add_epi64(_mm512_load_si512(src + i), seed); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_AVX2) \ + || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0) + +#ifndef XXH_TARGET_AVX2 +# define XXH_TARGET_AVX2 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void +XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 31) == 0); + { __m256i* const xacc = (__m256i *) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xinput = (const __m256i *) input; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xsecret = (const __m256i *) secret; + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { + /* data_vec = xinput[i]; */ + __m256i const data_vec = _mm256_loadu_si256 (xinput+i); + /* key_vec = xsecret[i]; */ + __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); + /* data_key = data_vec ^ key_vec; */ + __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m256i const data_key_lo = _mm256_srli_epi64 (data_key, 32); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m256i const product = _mm256_mul_epu32 (data_key, data_key_lo); + /* xacc[i] += swap(data_vec); */ + __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2)); + __m256i const sum = _mm256_add_epi64(xacc[i], data_swap); + /* xacc[i] += product; */ + xacc[i] = _mm256_add_epi64(product, sum); + } } +} +XXH_FORCE_INLINE XXH_TARGET_AVX2 XXH3_ACCUMULATE_TEMPLATE(avx2) + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void +XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 31) == 0); + { __m256i* const xacc = (__m256i*) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xsecret = (const __m256i *) secret; + const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1); + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { + /* xacc[i] ^= (xacc[i] >> 47) */ + __m256i const acc_vec = xacc[i]; + __m256i const shifted = _mm256_srli_epi64 (acc_vec, 47); + __m256i const data_vec = _mm256_xor_si256 (acc_vec, shifted); + /* xacc[i] ^= xsecret; */ + __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); + __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); + + /* xacc[i] *= XXH_PRIME32_1; */ + __m256i const data_key_hi = _mm256_srli_epi64 (data_key, 32); + __m256i const prod_lo = _mm256_mul_epu32 (data_key, prime32); + __m256i const prod_hi = _mm256_mul_epu32 (data_key_hi, prime32); + xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32)); + } + } +} + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0); + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6); + XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64); + (void)(&XXH_writeLE64); + XXH_PREFETCH(customSecret); + { __m256i const seed = _mm256_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64, (xxh_i64)(0U - seed64), (xxh_i64)seed64); + + const __m256i* const src = (const __m256i*) ((const void*) XXH3_kSecret); + __m256i* dest = ( __m256i*) customSecret; + +# if defined(__GNUC__) || defined(__clang__) + /* + * On GCC & Clang, marking 'dest' as modified will cause the compiler: + * - do not extract the secret from sse registers in the internal loop + * - use less common registers, and avoid pushing these reg into stack + */ + XXH_COMPILER_GUARD(dest); +# endif + XXH_ASSERT(((size_t)src & 31) == 0); /* control alignment */ + XXH_ASSERT(((size_t)dest & 31) == 0); + + /* GCC -O2 need unroll loop manually */ + dest[0] = _mm256_add_epi64(_mm256_load_si256(src+0), seed); + dest[1] = _mm256_add_epi64(_mm256_load_si256(src+1), seed); + dest[2] = _mm256_add_epi64(_mm256_load_si256(src+2), seed); + dest[3] = _mm256_add_epi64(_mm256_load_si256(src+3), seed); + dest[4] = _mm256_add_epi64(_mm256_load_si256(src+4), seed); + dest[5] = _mm256_add_epi64(_mm256_load_si256(src+5), seed); + } +} + +#endif + +/* x86dispatch always generates SSE2 */ +#if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH) + +#ifndef XXH_TARGET_SSE2 +# define XXH_TARGET_SSE2 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void +XXH3_accumulate_512_sse2( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + /* SSE2 is just a half-scale version of the AVX2 version. */ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { __m128i* const xacc = (__m128i *) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xinput = (const __m128i *) input; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xsecret = (const __m128i *) secret; + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { + /* data_vec = xinput[i]; */ + __m128i const data_vec = _mm_loadu_si128 (xinput+i); + /* key_vec = xsecret[i]; */ + __m128i const key_vec = _mm_loadu_si128 (xsecret+i); + /* data_key = data_vec ^ key_vec; */ + __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m128i const product = _mm_mul_epu32 (data_key, data_key_lo); + /* xacc[i] += swap(data_vec); */ + __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2)); + __m128i const sum = _mm_add_epi64(xacc[i], data_swap); + /* xacc[i] += product; */ + xacc[i] = _mm_add_epi64(product, sum); + } } +} +XXH_FORCE_INLINE XXH_TARGET_SSE2 XXH3_ACCUMULATE_TEMPLATE(sse2) + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void +XXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { __m128i* const xacc = (__m128i*) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xsecret = (const __m128i *) secret; + const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1); + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { + /* xacc[i] ^= (xacc[i] >> 47) */ + __m128i const acc_vec = xacc[i]; + __m128i const shifted = _mm_srli_epi64 (acc_vec, 47); + __m128i const data_vec = _mm_xor_si128 (acc_vec, shifted); + /* xacc[i] ^= xsecret[i]; */ + __m128i const key_vec = _mm_loadu_si128 (xsecret+i); + __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); + + /* xacc[i] *= XXH_PRIME32_1; */ + __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + __m128i const prod_lo = _mm_mul_epu32 (data_key, prime32); + __m128i const prod_hi = _mm_mul_epu32 (data_key_hi, prime32); + xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32)); + } + } +} + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); + (void)(&XXH_writeLE64); + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i); + +# if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER < 1900 + /* MSVC 32bit mode does not support _mm_set_epi64x before 2015 */ + XXH_ALIGN(16) const xxh_i64 seed64x2[2] = { (xxh_i64)seed64, (xxh_i64)(0U - seed64) }; + __m128i const seed = _mm_load_si128((__m128i const*)seed64x2); +# else + __m128i const seed = _mm_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64); +# endif + int i; + + const void* const src16 = XXH3_kSecret; + __m128i* dst16 = (__m128i*) customSecret; +# if defined(__GNUC__) || defined(__clang__) + /* + * On GCC & Clang, marking 'dest' as modified will cause the compiler: + * - do not extract the secret from sse registers in the internal loop + * - use less common registers, and avoid pushing these reg into stack + */ + XXH_COMPILER_GUARD(dst16); +# endif + XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */ + XXH_ASSERT(((size_t)dst16 & 15) == 0); + + for (i=0; i < nbRounds; ++i) { + dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_NEON) + +/* forward declarations for the scalar routines */ +XXH_FORCE_INLINE void +XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input, + void const* XXH_RESTRICT secret, size_t lane); + +XXH_FORCE_INLINE void +XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT secret, size_t lane); + +/*! + * @internal + * @brief The bulk processing loop for NEON and WASM SIMD128. + * + * The NEON code path is actually partially scalar when running on AArch64. This + * is to optimize the pipelining and can have up to 15% speedup depending on the + * CPU, and it also mitigates some GCC codegen issues. + * + * @see XXH3_NEON_LANES for configuring this and details about this optimization. + * + * NEON's 32-bit to 64-bit long multiply takes a half vector of 32-bit + * integers instead of the other platforms which mask full 64-bit vectors, + * so the setup is more complicated than just shifting right. + * + * Additionally, there is an optimization for 4 lanes at once noted below. + * + * Since, as stated, the most optimal amount of lanes for Cortexes is 6, + * there needs to be *three* versions of the accumulate operation used + * for the remaining 2 lanes. + * + * WASM's SIMD128 uses SIMDe's arm_neon.h polyfill because the intrinsics overlap + * nearly perfectly. + */ + +XXH_FORCE_INLINE void +XXH3_accumulate_512_neon( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0); + { /* GCC for darwin arm64 does not like aliasing here */ + xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc; + /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */ + uint8_t const* xinput = (const uint8_t *) input; + uint8_t const* xsecret = (const uint8_t *) secret; + + size_t i; +#ifdef __wasm_simd128__ + /* + * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret + * is constant propagated, which results in it converting it to this + * inside the loop: + * + * a = v128.load(XXH3_kSecret + 0 + $secret_offset, offset = 0) + * b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0) + * ... + * + * This requires a full 32-bit address immediate (and therefore a 6 byte + * instruction) as well as an add for each offset. + * + * Putting an asm guard prevents it from folding (at the cost of losing + * the alignment hint), and uses the free offset in `v128.load` instead + * of adding secret_offset each time which overall reduces code size by + * about a kilobyte and improves performance. + */ + XXH_COMPILER_GUARD(xsecret); +#endif + /* Scalar lanes use the normal scalarRound routine */ + for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { + XXH3_scalarRound(acc, input, secret, i); + } + i = 0; + /* 4 NEON lanes at a time. */ + for (; i+1 < XXH3_NEON_LANES / 2; i+=2) { + /* data_vec = xinput[i]; */ + uint64x2_t data_vec_1 = XXH_vld1q_u64(xinput + (i * 16)); + uint64x2_t data_vec_2 = XXH_vld1q_u64(xinput + ((i+1) * 16)); + /* key_vec = xsecret[i]; */ + uint64x2_t key_vec_1 = XXH_vld1q_u64(xsecret + (i * 16)); + uint64x2_t key_vec_2 = XXH_vld1q_u64(xsecret + ((i+1) * 16)); + /* data_swap = swap(data_vec) */ + uint64x2_t data_swap_1 = vextq_u64(data_vec_1, data_vec_1, 1); + uint64x2_t data_swap_2 = vextq_u64(data_vec_2, data_vec_2, 1); + /* data_key = data_vec ^ key_vec; */ + uint64x2_t data_key_1 = veorq_u64(data_vec_1, key_vec_1); + uint64x2_t data_key_2 = veorq_u64(data_vec_2, key_vec_2); + + /* + * If we reinterpret the 64x2 vectors as 32x4 vectors, we can use a + * de-interleave operation for 4 lanes in 1 step with `vuzpq_u32` to + * get one vector with the low 32 bits of each lane, and one vector + * with the high 32 bits of each lane. + * + * The intrinsic returns a double vector because the original ARMv7-a + * instruction modified both arguments in place. AArch64 and SIMD128 emit + * two instructions from this intrinsic. + * + * [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ] + * [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ] + */ + uint32x4x2_t unzipped = vuzpq_u32( + vreinterpretq_u32_u64(data_key_1), + vreinterpretq_u32_u64(data_key_2) + ); + /* data_key_lo = data_key & 0xFFFFFFFF */ + uint32x4_t data_key_lo = unzipped.val[0]; + /* data_key_hi = data_key >> 32 */ + uint32x4_t data_key_hi = unzipped.val[1]; + /* + * Then, we can split the vectors horizontally and multiply which, as for most + * widening intrinsics, have a variant that works on both high half vectors + * for free on AArch64. A similar instruction is available on SIMD128. + * + * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi + */ + uint64x2_t sum_1 = XXH_vmlal_low_u32(data_swap_1, data_key_lo, data_key_hi); + uint64x2_t sum_2 = XXH_vmlal_high_u32(data_swap_2, data_key_lo, data_key_hi); + /* + * Clang reorders + * a += b * c; // umlal swap.2d, dkl.2s, dkh.2s + * c += a; // add acc.2d, acc.2d, swap.2d + * to + * c += a; // add acc.2d, acc.2d, swap.2d + * c += b * c; // umlal acc.2d, dkl.2s, dkh.2s + * + * While it would make sense in theory since the addition is faster, + * for reasons likely related to umlal being limited to certain NEON + * pipelines, this is worse. A compiler guard fixes this. + */ + XXH_COMPILER_GUARD_CLANG_NEON(sum_1); + XXH_COMPILER_GUARD_CLANG_NEON(sum_2); + /* xacc[i] = acc_vec + sum; */ + xacc[i] = vaddq_u64(xacc[i], sum_1); + xacc[i+1] = vaddq_u64(xacc[i+1], sum_2); + } + /* Operate on the remaining NEON lanes 2 at a time. */ + for (; i < XXH3_NEON_LANES / 2; i++) { + /* data_vec = xinput[i]; */ + uint64x2_t data_vec = XXH_vld1q_u64(xinput + (i * 16)); + /* key_vec = xsecret[i]; */ + uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); + /* acc_vec_2 = swap(data_vec) */ + uint64x2_t data_swap = vextq_u64(data_vec, data_vec, 1); + /* data_key = data_vec ^ key_vec; */ + uint64x2_t data_key = veorq_u64(data_vec, key_vec); + /* For two lanes, just use VMOVN and VSHRN. */ + /* data_key_lo = data_key & 0xFFFFFFFF; */ + uint32x2_t data_key_lo = vmovn_u64(data_key); + /* data_key_hi = data_key >> 32; */ + uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32); + /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */ + uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi); + /* Same Clang workaround as before */ + XXH_COMPILER_GUARD_CLANG_NEON(sum); + /* xacc[i] = acc_vec + sum; */ + xacc[i] = vaddq_u64 (xacc[i], sum); + } + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(neon) + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + + { xxh_aliasing_uint64x2_t* xacc = (xxh_aliasing_uint64x2_t*) acc; + uint8_t const* xsecret = (uint8_t const*) secret; + + size_t i; + /* WASM uses operator overloads and doesn't need these. */ +#ifndef __wasm_simd128__ + /* { prime32_1, prime32_1 } */ + uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1); + /* { 0, prime32_1, 0, prime32_1 } */ + uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32)); +#endif + + /* AArch64 uses both scalar and neon at the same time */ + for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { + XXH3_scalarScrambleRound(acc, secret, i); + } + for (i=0; i < XXH3_NEON_LANES / 2; i++) { + /* xacc[i] ^= (xacc[i] >> 47); */ + uint64x2_t acc_vec = xacc[i]; + uint64x2_t shifted = vshrq_n_u64(acc_vec, 47); + uint64x2_t data_vec = veorq_u64(acc_vec, shifted); + + /* xacc[i] ^= xsecret[i]; */ + uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); + uint64x2_t data_key = veorq_u64(data_vec, key_vec); + /* xacc[i] *= XXH_PRIME32_1 */ +#ifdef __wasm_simd128__ + /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */ + xacc[i] = data_key * XXH_PRIME32_1; +#else + /* + * Expanded version with portable NEON intrinsics + * + * lo(x) * lo(y) + (hi(x) * lo(y) << 32) + * + * prod_hi = hi(data_key) * lo(prime) << 32 + * + * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector + * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits + * and avoid the shift. + */ + uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi); + /* Extract low bits for vmlal_u32 */ + uint32x2_t data_key_lo = vmovn_u64(data_key); + /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */ + xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo); +#endif + } + } +} +#endif + +#if (XXH_VECTOR == XXH_VSX) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + /* presumed aligned */ + xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; + xxh_u8 const* const xinput = (xxh_u8 const*) input; /* no alignment restriction */ + xxh_u8 const* const xsecret = (xxh_u8 const*) secret; /* no alignment restriction */ + xxh_u64x2 const v32 = { 32, 32 }; + size_t i; + for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { + /* data_vec = xinput[i]; */ + xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + 16*i); + /* key_vec = xsecret[i]; */ + xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); + xxh_u64x2 const data_key = data_vec ^ key_vec; + /* shuffled = (data_key << 32) | (data_key >> 32); */ + xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32); + /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */ + xxh_u64x2 const product = XXH_vec_mulo((xxh_u32x4)data_key, shuffled); + /* acc_vec = xacc[i]; */ + xxh_u64x2 acc_vec = xacc[i]; + acc_vec += product; + + /* swap high and low halves */ +#ifdef __s390x__ + acc_vec += vec_permi(data_vec, data_vec, 2); +#else + acc_vec += vec_xxpermdi(data_vec, data_vec, 2); +#endif + xacc[i] = acc_vec; + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(vsx) + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + + { xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; + const xxh_u8* const xsecret = (const xxh_u8*) secret; + /* constants */ + xxh_u64x2 const v32 = { 32, 32 }; + xxh_u64x2 const v47 = { 47, 47 }; + xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 }; + size_t i; + for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { + /* xacc[i] ^= (xacc[i] >> 47); */ + xxh_u64x2 const acc_vec = xacc[i]; + xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47); + + /* xacc[i] ^= xsecret[i]; */ + xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); + xxh_u64x2 const data_key = data_vec ^ key_vec; + + /* xacc[i] *= XXH_PRIME32_1 */ + /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF); */ + xxh_u64x2 const prod_even = XXH_vec_mule((xxh_u32x4)data_key, prime); + /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32); */ + xxh_u64x2 const prod_odd = XXH_vec_mulo((xxh_u32x4)data_key, prime); + xacc[i] = prod_odd + (prod_even << v32); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_SVE) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_sve( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + uint64_t *xacc = (uint64_t *)acc; + const uint64_t *xinput = (const uint64_t *)(const void *)input; + const uint64_t *xsecret = (const uint64_t *)(const void *)secret; + svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); + uint64_t element_count = svcntd(); + if (element_count >= 8) { + svbool_t mask = svptrue_pat_b64(SV_VL8); + svuint64_t vacc = svld1_u64(mask, xacc); + ACCRND(vacc, 0); + svst1_u64(mask, xacc, vacc); + } else if (element_count == 2) { /* sve128 */ + svbool_t mask = svptrue_pat_b64(SV_VL2); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 2); + svuint64_t acc2 = svld1_u64(mask, xacc + 4); + svuint64_t acc3 = svld1_u64(mask, xacc + 6); + ACCRND(acc0, 0); + ACCRND(acc1, 2); + ACCRND(acc2, 4); + ACCRND(acc3, 6); + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 2, acc1); + svst1_u64(mask, xacc + 4, acc2); + svst1_u64(mask, xacc + 6, acc3); + } else { + svbool_t mask = svptrue_pat_b64(SV_VL4); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 4); + ACCRND(acc0, 0); + ACCRND(acc1, 4); + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 4, acc1); + } +} + +XXH_FORCE_INLINE void +XXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc, + const xxh_u8* XXH_RESTRICT input, + const xxh_u8* XXH_RESTRICT secret, + size_t nbStripes) +{ + if (nbStripes != 0) { + uint64_t *xacc = (uint64_t *)acc; + const uint64_t *xinput = (const uint64_t *)(const void *)input; + const uint64_t *xsecret = (const uint64_t *)(const void *)secret; + svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); + uint64_t element_count = svcntd(); + if (element_count >= 8) { + svbool_t mask = svptrue_pat_b64(SV_VL8); + svuint64_t vacc = svld1_u64(mask, xacc + 0); + do { + /* svprfd(svbool_t, void *, enum svfprop); */ + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(vacc, 0); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, vacc); + } else if (element_count == 2) { /* sve128 */ + svbool_t mask = svptrue_pat_b64(SV_VL2); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 2); + svuint64_t acc2 = svld1_u64(mask, xacc + 4); + svuint64_t acc3 = svld1_u64(mask, xacc + 6); + do { + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(acc0, 0); + ACCRND(acc1, 2); + ACCRND(acc2, 4); + ACCRND(acc3, 6); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 2, acc1); + svst1_u64(mask, xacc + 4, acc2); + svst1_u64(mask, xacc + 6, acc3); + } else { + svbool_t mask = svptrue_pat_b64(SV_VL4); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 4); + do { + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(acc0, 0); + ACCRND(acc1, 4); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 4, acc1); + } + } +} + +#endif + +/* scalar variants - universal */ + +#if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__)) +/* + * In XXH3_scalarRound(), GCC and Clang have a similar codegen issue, where they + * emit an excess mask and a full 64-bit multiply-add (MADD X-form). + * + * While this might not seem like much, as AArch64 is a 64-bit architecture, only + * big Cortex designs have a full 64-bit multiplier. + * + * On the little cores, the smaller 32-bit multiplier is used, and full 64-bit + * multiplies expand to 2-3 multiplies in microcode. This has a major penalty + * of up to 4 latency cycles and 2 stall cycles in the multiply pipeline. + * + * Thankfully, AArch64 still provides the 32-bit long multiply-add (UMADDL) which does + * not have this penalty and does the mask automatically. + */ +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) +{ + xxh_u64 ret; + /* note: %x = 64-bit register, %w = 32-bit register */ + __asm__("umaddl %x0, %w1, %w2, %x3" : "=r" (ret) : "r" (lhs), "r" (rhs), "r" (acc)); + return ret; +} +#else +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) +{ + return XXH_mult32to64((xxh_u32)lhs, (xxh_u32)rhs) + acc; +} +#endif + +/*! + * @internal + * @brief Scalar round for @ref XXH3_accumulate_512_scalar(). + * + * This is extracted to its own function because the NEON path uses a combination + * of NEON and scalar. + */ +XXH_FORCE_INLINE void +XXH3_scalarRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT input, + void const* XXH_RESTRICT secret, + size_t lane) +{ + xxh_u64* xacc = (xxh_u64*) acc; + xxh_u8 const* xinput = (xxh_u8 const*) input; + xxh_u8 const* xsecret = (xxh_u8 const*) secret; + XXH_ASSERT(lane < XXH_ACC_NB); + XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0); + { + xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8); + xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8); + xacc[lane ^ 1] += data_val; /* swap adjacent lanes */ + xacc[lane] = XXH_mult32to64_add64(data_key /* & 0xFFFFFFFF */, data_key >> 32, xacc[lane]); + } +} + +/*! + * @internal + * @brief Processes a 64 byte block of data using the scalar path. + */ +XXH_FORCE_INLINE void +XXH3_accumulate_512_scalar(void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + size_t i; + /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */ +#if defined(__GNUC__) && !defined(__clang__) \ + && (defined(__arm__) || defined(__thumb2__)) \ + && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \ + && XXH_SIZE_OPT <= 0 +# pragma GCC unroll 8 +#endif + for (i=0; i < XXH_ACC_NB; i++) { + XXH3_scalarRound(acc, input, secret, i); + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(scalar) + +/*! + * @internal + * @brief Scalar scramble step for @ref XXH3_scrambleAcc_scalar(). + * + * This is extracted to its own function because the NEON path uses a combination + * of NEON and scalar. + */ +XXH_FORCE_INLINE void +XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT secret, + size_t lane) +{ + xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */ + const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */ + XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0); + XXH_ASSERT(lane < XXH_ACC_NB); + { + xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8); + xxh_u64 acc64 = xacc[lane]; + acc64 = XXH_xorshift64(acc64, 47); + acc64 ^= key64; + acc64 *= XXH_PRIME32_1; + xacc[lane] = acc64; + } +} + +/*! + * @internal + * @brief Scrambles the accumulators after a large chunk has been read + */ +XXH_FORCE_INLINE void +XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + size_t i; + for (i=0; i < XXH_ACC_NB; i++) { + XXH3_scalarScrambleRound(acc, secret, i); + } +} + +XXH_FORCE_INLINE void +XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + /* + * We need a separate pointer for the hack below, + * which requires a non-const pointer. + * Any decent compiler will optimize this out otherwise. + */ + const xxh_u8* kSecretPtr = XXH3_kSecret; + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); + +#if defined(__GNUC__) && defined(__aarch64__) + /* + * UGLY HACK: + * GCC and Clang generate a bunch of MOV/MOVK pairs for aarch64, and they are + * placed sequentially, in order, at the top of the unrolled loop. + * + * While MOVK is great for generating constants (2 cycles for a 64-bit + * constant compared to 4 cycles for LDR), it fights for bandwidth with + * the arithmetic instructions. + * + * I L S + * MOVK + * MOVK + * MOVK + * MOVK + * ADD + * SUB STR + * STR + * By forcing loads from memory (as the asm line causes the compiler to assume + * that XXH3_kSecretPtr has been changed), the pipelines are used more + * efficiently: + * I L S + * LDR + * ADD LDR + * SUB STR + * STR + * + * See XXH3_NEON_LANES for details on the pipsline. + * + * XXH3_64bits_withSeed, len == 256, Snapdragon 835 + * without hack: 2654.4 MB/s + * with hack: 3202.9 MB/s + */ + XXH_COMPILER_GUARD(kSecretPtr); +#endif + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16; + int i; + for (i=0; i < nbRounds; i++) { + /* + * The asm hack causes the compiler to assume that kSecretPtr aliases with + * customSecret, and on aarch64, this prevented LDP from merging two + * loads together for free. Putting the loads together before the stores + * properly generates LDP. + */ + xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i) + seed64; + xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64; + XXH_writeLE64((xxh_u8*)customSecret + 16*i, lo); + XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi); + } } +} + + +typedef void (*XXH3_f_accumulate)(xxh_u64* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, size_t); +typedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*); +typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64); + + +#if (XXH_VECTOR == XXH_AVX512) + +#define XXH3_accumulate_512 XXH3_accumulate_512_avx512 +#define XXH3_accumulate XXH3_accumulate_avx512 +#define XXH3_scrambleAcc XXH3_scrambleAcc_avx512 +#define XXH3_initCustomSecret XXH3_initCustomSecret_avx512 + +#elif (XXH_VECTOR == XXH_AVX2) + +#define XXH3_accumulate_512 XXH3_accumulate_512_avx2 +#define XXH3_accumulate XXH3_accumulate_avx2 +#define XXH3_scrambleAcc XXH3_scrambleAcc_avx2 +#define XXH3_initCustomSecret XXH3_initCustomSecret_avx2 + +#elif (XXH_VECTOR == XXH_SSE2) + +#define XXH3_accumulate_512 XXH3_accumulate_512_sse2 +#define XXH3_accumulate XXH3_accumulate_sse2 +#define XXH3_scrambleAcc XXH3_scrambleAcc_sse2 +#define XXH3_initCustomSecret XXH3_initCustomSecret_sse2 + +#elif (XXH_VECTOR == XXH_NEON) + +#define XXH3_accumulate_512 XXH3_accumulate_512_neon +#define XXH3_accumulate XXH3_accumulate_neon +#define XXH3_scrambleAcc XXH3_scrambleAcc_neon +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#elif (XXH_VECTOR == XXH_VSX) + +#define XXH3_accumulate_512 XXH3_accumulate_512_vsx +#define XXH3_accumulate XXH3_accumulate_vsx +#define XXH3_scrambleAcc XXH3_scrambleAcc_vsx +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#elif (XXH_VECTOR == XXH_SVE) +#define XXH3_accumulate_512 XXH3_accumulate_512_sve +#define XXH3_accumulate XXH3_accumulate_sve +#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#else /* scalar */ + +#define XXH3_accumulate_512 XXH3_accumulate_512_scalar +#define XXH3_accumulate XXH3_accumulate_scalar +#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#endif + +#if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */ +# undef XXH3_initCustomSecret +# define XXH3_initCustomSecret XXH3_initCustomSecret_scalar +#endif + +XXH_FORCE_INLINE void +XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc, + const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE; + size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock; + size_t const nb_blocks = (len - 1) / block_len; + + size_t n; + + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); + + for (n = 0; n < nb_blocks; n++) { + f_acc(acc, input + n*block_len, secret, nbStripesPerBlock); + f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN); + } + + /* last partial block */ + XXH_ASSERT(len > XXH_STRIPE_LEN); + { size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN; + XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE)); + f_acc(acc, input + nb_blocks*block_len, secret, nbStripes); + + /* last stripe */ + { const xxh_u8* const p = input + len - XXH_STRIPE_LEN; +#define XXH_SECRET_LASTACC_START 7 /* not aligned on 8, last secret is different from acc & scrambler */ + XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START); + } } +} + +XXH_FORCE_INLINE xxh_u64 +XXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret) +{ + return XXH3_mul128_fold64( + acc[0] ^ XXH_readLE64(secret), + acc[1] ^ XXH_readLE64(secret+8) ); +} + +static XXH64_hash_t +XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start) +{ + xxh_u64 result64 = start; + size_t i = 0; + + for (i = 0; i < 4; i++) { + result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i); +#if defined(__clang__) /* Clang */ \ + && (defined(__arm__) || defined(__thumb__)) /* ARMv7 */ \ + && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ + /* + * UGLY HACK: + * Prevent autovectorization on Clang ARMv7-a. Exact same problem as + * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b. + * XXH3_64bits, len == 256, Snapdragon 835: + * without hack: 2063.7 MB/s + * with hack: 2560.7 MB/s + */ + XXH_COMPILER_GUARD(result64); +#endif + } + + return XXH3_avalanche(result64); +} + +#define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \ + XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 } + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len, + const void* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; + + XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc, f_scramble); + + /* converge into final hash */ + XXH_STATIC_ASSERT(sizeof(acc) == 64); + /* do not align on 8, so that the secret is different from the accumulator */ +#define XXH_SECRET_MERGEACCS_START 11 + XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + return XXH3_mergeAccs(acc, (const xxh_u8*)secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)len * XXH_PRIME64_1); +} + +/* + * It's important for performance to transmit secret's size (when it's static) + * so that the compiler can properly optimize the vectorized loop. + * This makes a big performance difference for "medium" keys (<1 KB) when using AVX instruction set. + * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE + * breaks -Og, this is XXH_NO_INLINE. + */ +XXH3_WITH_SECRET_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; + return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc); +} + +/* + * It's preferable for performance that XXH3_hashLong is not inlined, + * as it results in a smaller function for small data, easier to the instruction cache. + * Note that inside this no_inline function, we do inline the internal loop, + * and provide a statically defined secret size to allow optimization of vector loop. + */ +XXH_NO_INLINE XXH_PUREF XXH64_hash_t +XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc); +} + +/* + * XXH3_hashLong_64b_withSeed(): + * Generate a custom key based on alteration of default XXH3_kSecret with the seed, + * and then use this key for long mode hashing. + * + * This operation is decently fast but nonetheless costs a little bit of time. + * Try to avoid it whenever possible (typically when seed==0). + * + * It's important for performance that XXH3_hashLong is not inlined. Not sure + * why (uop cache maybe?), but the difference is large and easily measurable. + */ +XXH_FORCE_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len, + XXH64_hash_t seed, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble, + XXH3_f_initCustomSecret f_initSec) +{ +#if XXH_SIZE_OPT <= 0 + if (seed == 0) + return XXH3_hashLong_64b_internal(input, len, + XXH3_kSecret, sizeof(XXH3_kSecret), + f_acc, f_scramble); +#endif + { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; + f_initSec(secret, seed); + return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret), + f_acc, f_scramble); + } +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSeed(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + return XXH3_hashLong_64b_withSeed_internal(input, len, seed, + XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); +} + + +typedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t, + XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t); + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, + XXH3_hashLong64_f f_hashLong) +{ + XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); + /* + * If an action is to be taken if `secretLen` condition is not respected, + * it should be done here. + * For now, it's a contract pre-condition. + * Adding a check and a branch here would cost performance at every hash. + * Also, note that function signature doesn't offer room to return an error. + */ + if (len <= 16) + return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); + if (len <= 128) + return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen); +} + + +/* === Public entry point === */ + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length) +{ + return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSecret(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed) +{ + return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed); +} + +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) +{ + if (length <= XXH3_MIDSIZE_MAX) + return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); + return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize); +} + + +/* === XXH3 streaming === */ +#ifndef XXH_NO_STREAM +/* + * Malloc's a pointer that is always aligned to align. + * + * This must be freed with `XXH_alignedFree()`. + * + * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte + * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2 + * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON. + * + * This underalignment previously caused a rather obvious crash which went + * completely unnoticed due to XXH3_createState() not actually being tested. + * Credit to RedSpah for noticing this bug. + * + * The alignment is done manually: Functions like posix_memalign or _mm_malloc + * are avoided: To maintain portability, we would have to write a fallback + * like this anyways, and besides, testing for the existence of library + * functions without relying on external build tools is impossible. + * + * The method is simple: Overallocate, manually align, and store the offset + * to the original behind the returned pointer. + * + * Align must be a power of 2 and 8 <= align <= 128. + */ +static XXH_MALLOCF void* XXH_alignedMalloc(size_t s, size_t align) +{ + XXH_ASSERT(align <= 128 && align >= 8); /* range check */ + XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */ + XXH_ASSERT(s != 0 && s < (s + align)); /* empty/overflow */ + { /* Overallocate to make room for manual realignment and an offset byte */ + xxh_u8* base = (xxh_u8*)XXH_malloc(s + align); + if (base != NULL) { + /* + * Get the offset needed to align this pointer. + * + * Even if the returned pointer is aligned, there will always be + * at least one byte to store the offset to the original pointer. + */ + size_t offset = align - ((size_t)base & (align - 1)); /* base % align */ + /* Add the offset for the now-aligned pointer */ + xxh_u8* ptr = base + offset; + + XXH_ASSERT((size_t)ptr % align == 0); + + /* Store the offset immediately before the returned pointer. */ + ptr[-1] = (xxh_u8)offset; + return ptr; + } + return NULL; + } +} +/* + * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass + * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout. + */ +static void XXH_alignedFree(void* p) +{ + if (p != NULL) { + xxh_u8* ptr = (xxh_u8*)p; + /* Get the offset byte we added in XXH_malloc. */ + xxh_u8 offset = ptr[-1]; + /* Free the original malloc'd pointer */ + xxh_u8* base = ptr - offset; + XXH_free(base); + } +} +/*! @ingroup XXH3_family */ +/*! + * @brief Allocate an @ref XXH3_state_t. + * + * @return An allocated pointer of @ref XXH3_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH3_freeState(). + */ +XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) +{ + XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64); + if (state==NULL) return NULL; + XXH3_INITSTATE(state); + return state; +} + +/*! @ingroup XXH3_family */ +/*! + * @brief Frees an @ref XXH3_state_t. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * + * @return @ref XXH_OK. + * + * @note Must be allocated with XXH3_createState(). + */ +XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr) +{ + XXH_alignedFree(statePtr); + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API void +XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state) +{ + XXH_memcpy(dst_state, src_state, sizeof(*dst_state)); +} + +static void +XXH3_reset_internal(XXH3_state_t* statePtr, + XXH64_hash_t seed, + const void* secret, size_t secretSize) +{ + size_t const initStart = offsetof(XXH3_state_t, bufferedSize); + size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart; + XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart); + XXH_ASSERT(statePtr != NULL); + /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */ + memset((char*)statePtr + initStart, 0, initLength); + statePtr->acc[0] = XXH_PRIME32_3; + statePtr->acc[1] = XXH_PRIME64_1; + statePtr->acc[2] = XXH_PRIME64_2; + statePtr->acc[3] = XXH_PRIME64_3; + statePtr->acc[4] = XXH_PRIME64_4; + statePtr->acc[5] = XXH_PRIME32_2; + statePtr->acc[6] = XXH_PRIME64_5; + statePtr->acc[7] = XXH_PRIME32_1; + statePtr->seed = seed; + statePtr->useSeed = (seed != 0); + statePtr->extSecret = (const unsigned char*)secret; + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); + statePtr->secretLimit = secretSize - XXH_STRIPE_LEN; + statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) +{ + if (statePtr == NULL) return XXH_ERROR; + XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE); + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + if (statePtr == NULL) return XXH_ERROR; + XXH3_reset_internal(statePtr, 0, secret, secretSize); + if (secret == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) +{ + if (statePtr == NULL) return XXH_ERROR; + if (seed==0) return XXH3_64bits_reset(statePtr); + if ((seed != statePtr->seed) || (statePtr->extSecret != NULL)) + XXH3_initCustomSecret(statePtr->customSecret, seed); + XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE); + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64) +{ + if (statePtr == NULL) return XXH_ERROR; + if (secret == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; + XXH3_reset_internal(statePtr, seed64, secret, secretSize); + statePtr->useSeed = 1; /* always, even if seed64==0 */ + return XXH_OK; +} + +/*! + * @internal + * @brief Processes a large input for XXH3_update() and XXH3_digest_long(). + * + * Unlike XXH3_hashLong_internal_loop(), this can process data that overlaps a block. + * + * @param acc Pointer to the 8 accumulator lanes + * @param nbStripesSoFarPtr In/out pointer to the number of leftover stripes in the block* + * @param nbStripesPerBlock Number of stripes in a block + * @param input Input pointer + * @param nbStripes Number of stripes to process + * @param secret Secret pointer + * @param secretLimit Offset of the last block in @p secret + * @param f_acc Pointer to an XXH3_accumulate implementation + * @param f_scramble Pointer to an XXH3_scrambleAcc implementation + * @return Pointer past the end of @p input after processing + */ +XXH_FORCE_INLINE const xxh_u8 * +XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc, + size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock, + const xxh_u8* XXH_RESTRICT input, size_t nbStripes, + const xxh_u8* XXH_RESTRICT secret, size_t secretLimit, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + const xxh_u8* initialSecret = secret + *nbStripesSoFarPtr * XXH_SECRET_CONSUME_RATE; + /* Process full blocks */ + if (nbStripes >= (nbStripesPerBlock - *nbStripesSoFarPtr)) { + /* Process the initial partial block... */ + size_t nbStripesThisIter = nbStripesPerBlock - *nbStripesSoFarPtr; + + do { + /* Accumulate and scramble */ + f_acc(acc, input, initialSecret, nbStripesThisIter); + f_scramble(acc, secret + secretLimit); + input += nbStripesThisIter * XXH_STRIPE_LEN; + nbStripes -= nbStripesThisIter; + /* Then continue the loop with the full block size */ + nbStripesThisIter = nbStripesPerBlock; + initialSecret = secret; + } while (nbStripes >= nbStripesPerBlock); + *nbStripesSoFarPtr = 0; + } + /* Process a partial block */ + if (nbStripes > 0) { + f_acc(acc, input, initialSecret, nbStripes); + input += nbStripes * XXH_STRIPE_LEN; + *nbStripesSoFarPtr += nbStripes; + } + /* Return end pointer */ + return input; +} + +#ifndef XXH3_STREAM_USE_STACK +# if XXH_SIZE_OPT <= 0 && !defined(__clang__) /* clang doesn't need additional stack space */ +# define XXH3_STREAM_USE_STACK 1 +# endif +#endif +/* + * Both XXH3_64bits_update and XXH3_128bits_update use this routine. + */ +XXH_FORCE_INLINE XXH_errorcode +XXH3_update(XXH3_state_t* XXH_RESTRICT const state, + const xxh_u8* XXH_RESTRICT input, size_t len, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + if (input==NULL) { + XXH_ASSERT(len == 0); + return XXH_OK; + } + + XXH_ASSERT(state != NULL); + { const xxh_u8* const bEnd = input + len; + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; +#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 + /* For some reason, gcc and MSVC seem to suffer greatly + * when operating accumulators directly into state. + * Operating into stack space seems to enable proper optimization. + * clang, on the other hand, doesn't seem to need this trick */ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8]; + XXH_memcpy(acc, state->acc, sizeof(acc)); +#else + xxh_u64* XXH_RESTRICT const acc = state->acc; +#endif + state->totalLen += len; + XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE); + + /* small input : just fill in tmp buffer */ + if (len <= XXH3_INTERNALBUFFER_SIZE - state->bufferedSize) { + XXH_memcpy(state->buffer + state->bufferedSize, input, len); + state->bufferedSize += (XXH32_hash_t)len; + return XXH_OK; + } + + /* total input is now > XXH3_INTERNALBUFFER_SIZE */ + #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN) + XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0); /* clean multiple */ + + /* + * Internal buffer is partially filled (always, except at beginning) + * Complete it, then consume it. + */ + if (state->bufferedSize) { + size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize; + XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize); + input += loadSize; + XXH3_consumeStripes(acc, + &state->nbStripesSoFar, state->nbStripesPerBlock, + state->buffer, XXH3_INTERNALBUFFER_STRIPES, + secret, state->secretLimit, + f_acc, f_scramble); + state->bufferedSize = 0; + } + XXH_ASSERT(input < bEnd); + if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) { + size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN; + input = XXH3_consumeStripes(acc, + &state->nbStripesSoFar, state->nbStripesPerBlock, + input, nbStripes, + secret, state->secretLimit, + f_acc, f_scramble); + XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); + + } + /* Some remaining input (always) : buffer it */ + XXH_ASSERT(input < bEnd); + XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE); + XXH_ASSERT(state->bufferedSize == 0); + XXH_memcpy(state->buffer, input, (size_t)(bEnd-input)); + state->bufferedSize = (XXH32_hash_t)(bEnd-input); +#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 + /* save stack accumulators into state */ + XXH_memcpy(state->acc, acc, sizeof(acc)); +#endif + } + + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_update(state, (const xxh_u8*)input, len, + XXH3_accumulate, XXH3_scrambleAcc); +} + + +XXH_FORCE_INLINE void +XXH3_digest_long (XXH64_hash_t* acc, + const XXH3_state_t* state, + const unsigned char* secret) +{ + xxh_u8 lastStripe[XXH_STRIPE_LEN]; + const xxh_u8* lastStripePtr; + + /* + * Digest on a local copy. This way, the state remains unaltered, and it can + * continue ingesting more input afterwards. + */ + XXH_memcpy(acc, state->acc, sizeof(state->acc)); + if (state->bufferedSize >= XXH_STRIPE_LEN) { + /* Consume remaining stripes then point to remaining data in buffer */ + size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN; + size_t nbStripesSoFar = state->nbStripesSoFar; + XXH3_consumeStripes(acc, + &nbStripesSoFar, state->nbStripesPerBlock, + state->buffer, nbStripes, + secret, state->secretLimit, + XXH3_accumulate, XXH3_scrambleAcc); + lastStripePtr = state->buffer + state->bufferedSize - XXH_STRIPE_LEN; + } else { /* bufferedSize < XXH_STRIPE_LEN */ + /* Copy to temp buffer */ + size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize; + XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */ + XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize); + XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize); + lastStripePtr = lastStripe; + } + /* Last stripe */ + XXH3_accumulate_512(acc, + lastStripePtr, + secret + state->secretLimit - XXH_SECRET_LASTACC_START); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* state) +{ + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; + if (state->totalLen > XXH3_MIDSIZE_MAX) { + XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; + XXH3_digest_long(acc, state, secret); + return XXH3_mergeAccs(acc, + secret + XXH_SECRET_MERGEACCS_START, + (xxh_u64)state->totalLen * XXH_PRIME64_1); + } + /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */ + if (state->useSeed) + return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); + return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen), + secret, state->secretLimit + XXH_STRIPE_LEN); +} +#endif /* !XXH_NO_STREAM */ + + +/* ========================================== + * XXH3 128 bits (a.k.a XXH128) + * ========================================== + * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant, + * even without counting the significantly larger output size. + * + * For example, extra steps are taken to avoid the seed-dependent collisions + * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B). + * + * This strength naturally comes at the cost of some speed, especially on short + * lengths. Note that longer hashes are about as fast as the 64-bit version + * due to it using only a slight modification of the 64-bit loop. + * + * XXH128 is also more oriented towards 64-bit machines. It is still extremely + * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64). + */ + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + /* A doubled version of 1to3_64b with different constants. */ + XXH_ASSERT(input != NULL); + XXH_ASSERT(1 <= len && len <= 3); + XXH_ASSERT(secret != NULL); + /* + * len = 1: combinedl = { input[0], 0x01, input[0], input[0] } + * len = 2: combinedl = { input[1], 0x02, input[0], input[1] } + * len = 3: combinedl = { input[2], 0x03, input[0], input[1] } + */ + { xxh_u8 const c1 = input[0]; + xxh_u8 const c2 = input[len >> 1]; + xxh_u8 const c3 = input[len - 1]; + xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24) + | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); + xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13); + xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; + xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed; + xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl; + xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph; + XXH128_hash_t h128; + h128.low64 = XXH64_avalanche(keyed_lo); + h128.high64 = XXH64_avalanche(keyed_hi); + return h128; + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(4 <= len && len <= 8); + seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; + { xxh_u32 const input_lo = XXH_readLE32(input); + xxh_u32 const input_hi = XXH_readLE32(input + len - 4); + xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32); + xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed; + xxh_u64 const keyed = input_64 ^ bitflip; + + /* Shift len to the left to ensure it is even, this avoids even multiplies. */ + XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2)); + + m128.high64 += (m128.low64 << 1); + m128.low64 ^= (m128.high64 >> 3); + + m128.low64 = XXH_xorshift64(m128.low64, 35); + m128.low64 *= PRIME_MX2; + m128.low64 = XXH_xorshift64(m128.low64, 28); + m128.high64 = XXH3_avalanche(m128.high64); + return m128; + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(9 <= len && len <= 16); + { xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed; + xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed; + xxh_u64 const input_lo = XXH_readLE64(input); + xxh_u64 input_hi = XXH_readLE64(input + len - 8); + XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1); + /* + * Put len in the middle of m128 to ensure that the length gets mixed to + * both the low and high bits in the 128x64 multiply below. + */ + m128.low64 += (xxh_u64)(len - 1) << 54; + input_hi ^= bitfliph; + /* + * Add the high 32 bits of input_hi to the high 32 bits of m128, then + * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to + * the high 64 bits of m128. + * + * The best approach to this operation is different on 32-bit and 64-bit. + */ + if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */ + /* + * 32-bit optimized version, which is more readable. + * + * On 32-bit, it removes an ADC and delays a dependency between the two + * halves of m128.high64, but it generates an extra mask on 64-bit. + */ + m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2); + } else { + /* + * 64-bit optimized (albeit more confusing) version. + * + * Uses some properties of addition and multiplication to remove the mask: + * + * Let: + * a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF) + * b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000) + * c = XXH_PRIME32_2 + * + * a + (b * c) + * Inverse Property: x + y - x == y + * a + (b * (1 + c - 1)) + * Distributive Property: x * (y + z) == (x * y) + (x * z) + * a + (b * 1) + (b * (c - 1)) + * Identity Property: x * 1 == x + * a + b + (b * (c - 1)) + * + * Substitute a, b, and c: + * input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) + * + * Since input_hi.hi + input_hi.lo == input_hi, we get this: + * input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) + */ + m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1); + } + /* m128 ^= XXH_swap64(m128 >> 64); */ + m128.low64 ^= XXH_swap64(m128.high64); + + { /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */ + XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2); + h128.high64 += m128.high64 * XXH_PRIME64_2; + + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = XXH3_avalanche(h128.high64); + return h128; + } } +} + +/* + * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN + */ +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(len <= 16); + { if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed); + if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed); + if (len) return XXH3_len_1to3_128b(input, len, secret, seed); + { XXH128_hash_t h128; + xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72); + xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88); + h128.low64 = XXH64_avalanche(seed ^ bitflipl); + h128.high64 = XXH64_avalanche( seed ^ bitfliph); + return h128; + } } +} + +/* + * A bit slower than XXH3_mix16B, but handles multiply by zero better. + */ +XXH_FORCE_INLINE XXH128_hash_t +XXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2, + const xxh_u8* secret, XXH64_hash_t seed) +{ + acc.low64 += XXH3_mix16B (input_1, secret+0, seed); + acc.low64 ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8); + acc.high64 += XXH3_mix16B (input_2, secret+16, seed); + acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8); + return acc; +} + + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(16 < len && len <= 128); + + { XXH128_hash_t acc; + acc.low64 = len * XXH_PRIME64_1; + acc.high64 = 0; + +#if XXH_SIZE_OPT >= 1 + { + /* Smaller, but slightly slower. */ + unsigned int i = (unsigned int)(len - 1) / 32; + do { + acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed); + } while (i-- != 0); + } +#else + if (len > 32) { + if (len > 64) { + if (len > 96) { + acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed); + } + acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed); + } + acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed); + } + acc = XXH128_mix32B(acc, input, input+len-16, secret, seed); +#endif + { XXH128_hash_t h128; + h128.low64 = acc.low64 + acc.high64; + h128.high64 = (acc.low64 * XXH_PRIME64_1) + + (acc.high64 * XXH_PRIME64_4) + + ((len - seed) * XXH_PRIME64_2); + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); + return h128; + } + } +} + +XXH_NO_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + + { XXH128_hash_t acc; + unsigned i; + acc.low64 = len * XXH_PRIME64_1; + acc.high64 = 0; + /* + * We set as `i` as offset + 32. We do this so that unchanged + * `len` can be used as upper bound. This reaches a sweet spot + * where both x86 and aarch64 get simple agen and good codegen + * for the loop. + */ + for (i = 32; i < 160; i += 32) { + acc = XXH128_mix32B(acc, + input + i - 32, + input + i - 16, + secret + i - 32, + seed); + } + acc.low64 = XXH3_avalanche(acc.low64); + acc.high64 = XXH3_avalanche(acc.high64); + /* + * NB: `i <= len` will duplicate the last 32-bytes if + * len % 32 was zero. This is an unfortunate necessity to keep + * the hash result stable. + */ + for (i=160; i <= len; i += 32) { + acc = XXH128_mix32B(acc, + input + i - 32, + input + i - 16, + secret + XXH3_MIDSIZE_STARTOFFSET + i - 160, + seed); + } + /* last bytes */ + acc = XXH128_mix32B(acc, + input + len - 16, + input + len - 32, + secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16, + (XXH64_hash_t)0 - seed); + + { XXH128_hash_t h128; + h128.low64 = acc.low64 + acc.high64; + h128.high64 = (acc.low64 * XXH_PRIME64_1) + + (acc.high64 * XXH_PRIME64_4) + + ((len - seed) * XXH_PRIME64_2); + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); + return h128; + } + } +} + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; + + XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc, f_scramble); + + /* converge into final hash */ + XXH_STATIC_ASSERT(sizeof(acc) == 64); + XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + { XXH128_hash_t h128; + h128.low64 = XXH3_mergeAccs(acc, + secret + XXH_SECRET_MERGEACCS_START, + (xxh_u64)len * XXH_PRIME64_1); + h128.high64 = XXH3_mergeAccs(acc, + secret + secretSize + - sizeof(acc) - XXH_SECRET_MERGEACCS_START, + ~((xxh_u64)len * XXH_PRIME64_2)); + return h128; + } +} + +/* + * It's important for performance that XXH3_hashLong() is not inlined. + */ +XXH_NO_INLINE XXH_PUREF XXH128_hash_t +XXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_accumulate, XXH3_scrambleAcc); +} + +/* + * It's important for performance to pass @p secretLen (when it's static) + * to the compiler, so that it can properly optimize the vectorized loop. + * + * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE + * breaks -Og, this is XXH_NO_INLINE. + */ +XXH3_WITH_SECRET_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; + return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen, + XXH3_accumulate, XXH3_scrambleAcc); +} + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble, + XXH3_f_initCustomSecret f_initSec) +{ + if (seed64 == 0) + return XXH3_hashLong_128b_internal(input, len, + XXH3_kSecret, sizeof(XXH3_kSecret), + f_acc, f_scramble); + { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; + f_initSec(secret, seed64); + return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret), + f_acc, f_scramble); + } +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSeed(const void* input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + return XXH3_hashLong_128b_withSeed_internal(input, len, seed64, + XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); +} + +typedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t, + XXH64_hash_t, const void* XXH_RESTRICT, size_t); + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_128bits_internal(const void* input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, + XXH3_hashLong128_f f_hl128) +{ + XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); + /* + * If an action is to be taken if `secret` conditions are not respected, + * it should be done here. + * For now, it's a contract pre-condition. + * Adding a check and a branch here would cost performance at every hash. + */ + if (len <= 16) + return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); + if (len <= 128) + return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + return f_hl128(input, len, seed64, secret, secretLen); +} + + +/* === Public XXH128 API === */ + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_128bits_internal(input, len, 0, + XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_hashLong_128b_default); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSecret(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + return XXH3_128bits_internal(input, len, 0, + (const xxh_u8*)secret, secretSize, + XXH3_hashLong_128b_withSecret); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSeed(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_internal(input, len, seed, + XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_hashLong_128b_withSeed); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) +{ + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); + return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH128(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_withSeed(input, len, seed); +} + + +/* === XXH3 128-bit streaming === */ +#ifndef XXH_NO_STREAM +/* + * All initialization and update functions are identical to 64-bit streaming variant. + * The only difference is the finalization routine. + */ + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) +{ + return XXH3_64bits_reset(statePtr); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) +{ + return XXH3_64bits_reset_withSeed(statePtr, seed); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) +{ + return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_64bits_update(state, input, len); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* state) +{ + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; + if (state->totalLen > XXH3_MIDSIZE_MAX) { + XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; + XXH3_digest_long(acc, state, secret); + XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + { XXH128_hash_t h128; + h128.low64 = XXH3_mergeAccs(acc, + secret + XXH_SECRET_MERGEACCS_START, + (xxh_u64)state->totalLen * XXH_PRIME64_1); + h128.high64 = XXH3_mergeAccs(acc, + secret + state->secretLimit + XXH_STRIPE_LEN + - sizeof(acc) - XXH_SECRET_MERGEACCS_START, + ~((xxh_u64)state->totalLen * XXH_PRIME64_2)); + return h128; + } + } + /* len <= XXH3_MIDSIZE_MAX : short code */ + if (state->seed) + return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); + return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen), + secret, state->secretLimit + XXH_STRIPE_LEN); +} +#endif /* !XXH_NO_STREAM */ +/* 128-bit utility functions */ + +#include /* memcmp, memcpy */ + +/* return : 1 is equal, 0 if different */ +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2) +{ + /* note : XXH128_hash_t is compact, it has no padding byte */ + return !(memcmp(&h1, &h2, sizeof(h1))); +} + +/* This prototype is compatible with stdlib's qsort(). + * @return : >0 if *h128_1 > *h128_2 + * <0 if *h128_1 < *h128_2 + * =0 if *h128_1 == *h128_2 */ +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2) +{ + XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1; + XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2; + int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64); + /* note : bets that, in most cases, hash values are different */ + if (hcmp) return hcmp; + return (h1.low64 > h2.low64) - (h2.low64 > h1.low64); +} + + +/*====== Canonical representation ======*/ +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API void +XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) { + hash.high64 = XXH_swap64(hash.high64); + hash.low64 = XXH_swap64(hash.low64); + } + XXH_memcpy(dst, &hash.high64, sizeof(hash.high64)); + XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64)); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src) +{ + XXH128_hash_t h; + h.high64 = XXH_readBE64(src); + h.low64 = XXH_readBE64(src->digest + 8); + return h; +} + + + +/* ========================================== + * Secret generators + * ========================================== + */ +#define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x)) + +XXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128) +{ + XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 ); + XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 ); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize) +{ +#if (XXH_DEBUGLEVEL >= 1) + XXH_ASSERT(secretBuffer != NULL); + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); +#else + /* production mode, assert() are disabled */ + if (secretBuffer == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; +#endif + + if (customSeedSize == 0) { + customSeed = XXH3_kSecret; + customSeedSize = XXH_SECRET_DEFAULT_SIZE; + } +#if (XXH_DEBUGLEVEL >= 1) + XXH_ASSERT(customSeed != NULL); +#else + if (customSeed == NULL) return XXH_ERROR; +#endif + + /* Fill secretBuffer with a copy of customSeed - repeat as needed */ + { size_t pos = 0; + while (pos < secretSize) { + size_t const toCopy = XXH_MIN((secretSize - pos), customSeedSize); + memcpy((char*)secretBuffer + pos, customSeed, toCopy); + pos += toCopy; + } } + + { size_t const nbSeg16 = secretSize / 16; + size_t n; + XXH128_canonical_t scrambler; + XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0)); + for (n=0; n +#include +#include + +#if defined(__GNUC__) && __GNUC__ >= 4 +# define ZSTD_memcpy(d,s,l) __builtin_memcpy((d),(s),(l)) +# define ZSTD_memmove(d,s,l) __builtin_memmove((d),(s),(l)) +# define ZSTD_memset(p,v,l) __builtin_memset((p),(v),(l)) +#else +# define ZSTD_memcpy(d,s,l) memcpy((d),(s),(l)) +# define ZSTD_memmove(d,s,l) memmove((d),(s),(l)) +# define ZSTD_memset(p,v,l) memset((p),(v),(l)) +#endif + +#endif /* ZSTD_DEPS_COMMON */ + +/* Need: + * ZSTD_malloc() + * ZSTD_free() + * ZSTD_calloc() + */ +#ifdef ZSTD_DEPS_NEED_MALLOC +#ifndef ZSTD_DEPS_MALLOC +#define ZSTD_DEPS_MALLOC + +#include + +#define ZSTD_malloc(s) malloc(s) +#define ZSTD_calloc(n,s) calloc((n), (s)) +#define ZSTD_free(p) free((p)) + +#endif /* ZSTD_DEPS_MALLOC */ +#endif /* ZSTD_DEPS_NEED_MALLOC */ + +/* + * Provides 64-bit math support. + * Need: + * U64 ZSTD_div64(U64 dividend, U32 divisor) + */ +#ifdef ZSTD_DEPS_NEED_MATH64 +#ifndef ZSTD_DEPS_MATH64 +#define ZSTD_DEPS_MATH64 + +#define ZSTD_div64(dividend, divisor) ((dividend) / (divisor)) + +#endif /* ZSTD_DEPS_MATH64 */ +#endif /* ZSTD_DEPS_NEED_MATH64 */ + +/* Need: + * assert() + */ +#ifdef ZSTD_DEPS_NEED_ASSERT +#ifndef ZSTD_DEPS_ASSERT +#define ZSTD_DEPS_ASSERT + +#include + +#endif /* ZSTD_DEPS_ASSERT */ +#endif /* ZSTD_DEPS_NEED_ASSERT */ + +/* Need: + * ZSTD_DEBUG_PRINT() + */ +#ifdef ZSTD_DEPS_NEED_IO +#ifndef ZSTD_DEPS_IO +#define ZSTD_DEPS_IO + +#include +#define ZSTD_DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) + +#endif /* ZSTD_DEPS_IO */ +#endif /* ZSTD_DEPS_NEED_IO */ + +/* Only requested when is known to be present. + * Need: + * intptr_t + */ +#ifdef ZSTD_DEPS_NEED_STDINT +#ifndef ZSTD_DEPS_STDINT +#define ZSTD_DEPS_STDINT + +#include + +#endif /* ZSTD_DEPS_STDINT */ +#endif /* ZSTD_DEPS_NEED_STDINT */ diff --git a/third_party/zstd/include/zstd/common/zstd_internal.h b/third_party/zstd/include/zstd/common/zstd_internal.h index 93cb4585630..ecb9cfba87c 100644 --- a/third_party/zstd/include/zstd/common/zstd_internal.h +++ b/third_party/zstd/include/zstd/common/zstd_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -19,29 +19,35 @@ /*-************************************* * Dependencies ***************************************/ -#ifdef __aarch64__ -#include +#include "compiler.h" +#include "cpu.h" +#include "mem.h" +#include "debug.h" /* assert, DEBUGLOG, RAWLOG, g_debuglevel */ +#include "error_private.h" +#define ZSTD_STATIC_LINKING_ONLY +#include "../zstd.h" +#define FSE_STATIC_LINKING_ONLY +#include "fse.h" +#include "huf.h" +#ifndef XXH_STATIC_LINKING_ONLY +# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */ +#endif +#include "xxhash.h" /* XXH_reset, update, digest */ +#ifndef ZSTD_NO_TRACE +# include "zstd_trace.h" +#else +# define ZSTD_TRACE 0 +#endif + +#if defined (__cplusplus) +extern "C" { #endif -#include "zstd/common/compiler.h" -#include "zstd/common/mem.h" -#include "zstd/common/debug.h" /* assert, DEBUGLOG, RAWLOG, g_debuglevel */ -#include "zstd/common/error_private.h" -#include "zstd.h" -#include "zstd_static.h" -#include "zstd/common/fse.h" -#include "zstd/common/fse_static.h" -#include "zstd/common/huf.h" -#include "zstd/common/huf_static.h" -#include "zstd/common/xxhash.h" /* XXH_reset, update, digest */ -#include "zstd/common/xxhash_static.h" /* XXH_reset, update, digest */ - -namespace duckdb_zstd { /* ---- static assert (debug) --- */ #define ZSTD_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) #define ZSTD_isError ERR_isError /* for inlining */ -// #define FSE_isError ERR_isError -// #define HUF_isError ERR_isError +#define FSE_isError ERR_isError +#define HUF_isError ERR_isError /*-************************************* @@ -51,81 +57,7 @@ namespace duckdb_zstd { #undef MAX #define MIN(a,b) ((a)<(b) ? (a) : (b)) #define MAX(a,b) ((a)>(b) ? (a) : (b)) - -/** - * Ignore: this is an internal helper. - * - * This is a helper function to help force C99-correctness during compilation. - * Under strict compilation modes, variadic macro arguments can't be empty. - * However, variadic function arguments can be. Using a function therefore lets - * us statically check that at least one (string) argument was passed, - * independent of the compilation flags. - */ -static INLINE_KEYWORD UNUSED_ATTR -void _force_has_format_string(const char *format, ...) { - (void)format; -} - -/** - * Ignore: this is an internal helper. - * - * We want to force this function invocation to be syntactically correct, but - * we don't want to force runtime evaluation of its arguments. - */ -#define _FORCE_HAS_FORMAT_STRING(...) \ - if (0) { \ - _force_has_format_string(__VA_ARGS__); \ - } - -/** - * Return the specified error if the condition evaluates to true. - * - * In debug modes, prints additional information. - * In order to do that (particularly, printing the conditional that failed), - * this can't just wrap RETURN_ERROR(). - */ -#define RETURN_ERROR_IF(cond, err, ...) \ - if (cond) { \ - RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \ - __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \ - _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ - RAWLOG(3, ": " __VA_ARGS__); \ - RAWLOG(3, "\n"); \ - return ERROR(err); \ - } - -/** - * Unconditionally return the specified error. - * - * In debug modes, prints additional information. - */ -#define RETURN_ERROR(err, ...) \ - do { \ - RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \ - __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \ - _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ - RAWLOG(3, ": " __VA_ARGS__); \ - RAWLOG(3, "\n"); \ - return ERROR(err); \ - } while(0); - -/** - * If the provided expression evaluates to an error code, returns that error code. - * - * In debug modes, prints additional information. - */ -#define FORWARD_IF_ERROR(err, ...) \ - do { \ - size_t const err_code = (err); \ - if (ERR_isError(err_code)) { \ - RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \ - __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \ - _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ - RAWLOG(3, ": " __VA_ARGS__); \ - RAWLOG(3, "\n"); \ - return err_code; \ - } \ - } while(0); +#define BOUNDED(min,val,max) (MAX(min,MIN(val,max))) /*-************************************* @@ -134,7 +66,7 @@ void _force_has_format_string(const char *format, ...) { #define ZSTD_OPT_NUM (1<<12) #define ZSTD_REP_NUM 3 /* number of repcodes */ -#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1) +static UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; #define KB *(1 <<10) #define MB *(1 <<20) @@ -148,19 +80,21 @@ void _force_has_format_string(const char *format, ...) { #define BIT0 1 #define ZSTD_WINDOWLOG_ABSOLUTEMIN 10 +static UNUSED_ATTR const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 }; +static UNUSED_ATTR const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; #define ZSTD_FRAMEIDSIZE 4 /* magic number size */ #define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */ - +static UNUSED_ATTR const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e; #define ZSTD_FRAMECHECKSUMSIZE 4 #define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */ -#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */ +#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */) /* for a non-null block */ +#define MIN_LITERALS_FOR_4_STREAMS 6 -#define HufLog 12 typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e; #define LONGNBSEQ 0x7F00 @@ -168,6 +102,7 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy #define MINMATCH 3 #define Litbits 8 +#define LitHufLog 11 #define MaxLit ((1<= 8 || (ovtype == ZSTD_no_overlap && diff <= -WILDCOPY_VECLEN)); - if (ovtype == ZSTD_overlap_src_before_dst && diff < WILDCOPY_VECLEN) { /* Handle short offset copies. */ do { - COPY8(op, ip) + COPY8(op, ip); } while (op < oend); } else { assert(diff >= WILDCOPY_VECLEN || diff <= -WILDCOPY_VECLEN); @@ -260,20 +237,15 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e * one COPY16() in the first call. Then, do two calls per loop since * at that point it is more likely to have a high trip count. */ -#ifndef __aarch64__ - do { - COPY16(op, ip); - } - while (op < oend); -#else - COPY16(op, ip); - if (op >= oend) return; + ZSTD_copy16(op, ip); + if (16 >= length) return; + op += 16; + ip += 16; do { COPY16(op, ip); COPY16(op, ip); } while (op < oend); -#endif } } @@ -281,7 +253,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, { size_t const length = MIN(dstCapacity, srcSize); if (length > 0) { - memcpy(dst, src, length); + ZSTD_memcpy(dst, src, length); } return length; } @@ -296,28 +268,46 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, * In which case, resize it down to free some memory */ #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 +/* Controls whether the input/output buffer is buffered or stable. */ +typedef enum { + ZSTD_bm_buffered = 0, /* Buffer the input/output */ + ZSTD_bm_stable = 1 /* ZSTD_inBuffer/ZSTD_outBuffer is stable */ +} ZSTD_bufferMode_e; + /*-******************************************* * Private declarations *********************************************/ typedef struct seqDef_s { - U32 offset; + U32 offBase; /* offBase == Offset + ZSTD_REP_NUM, or repcode 1,2,3 */ U16 litLength; - U16 matchLength; + U16 mlBase; /* mlBase == matchLength - MINMATCH */ } seqDef; +/* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */ +typedef enum { + ZSTD_llt_none = 0, /* no longLengthType */ + ZSTD_llt_literalLength = 1, /* represents a long literal */ + ZSTD_llt_matchLength = 2 /* represents a long match */ +} ZSTD_longLengthType_e; + typedef struct { seqDef* sequencesStart; - seqDef* sequences; - BYTE* litStart; - BYTE* lit; - BYTE* llCode; - BYTE* mlCode; - BYTE* ofCode; + seqDef* sequences; /* ptr to end of sequences */ + BYTE* litStart; + BYTE* lit; /* ptr to end of literals */ + BYTE* llCode; + BYTE* mlCode; + BYTE* ofCode; size_t maxNbSeq; size_t maxNbLit; - U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */ - U32 longLengthPos; + + /* longLengthPos and longLengthType to allow us to represent either a single litLength or matchLength + * in the seqStore that has a value larger than U16 (if it exists). To do so, we increment + * the existing value of the litLength or matchLength by 0x10000. + */ + ZSTD_longLengthType_e longLengthType; + U32 longLengthPos; /* Index of the sequence to apply long length modification to */ } seqStore_t; typedef struct { @@ -327,19 +317,19 @@ typedef struct { /** * Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences - * indicated by longLengthPos and longLengthID, and adds MINMATCH back to matchLength. + * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength. */ MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq) { ZSTD_sequenceLength seqLen; seqLen.litLength = seq->litLength; - seqLen.matchLength = seq->matchLength + MINMATCH; + seqLen.matchLength = seq->mlBase + MINMATCH; if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) { - if (seqStore->longLengthID == 1) { - seqLen.litLength += 0xFFFF; + if (seqStore->longLengthType == ZSTD_llt_literalLength) { + seqLen.litLength += 0x10000; } - if (seqStore->longLengthID == 2) { - seqLen.matchLength += 0xFFFF; + if (seqStore->longLengthType == ZSTD_llt_matchLength) { + seqLen.matchLength += 0x10000; } } return seqLen; @@ -352,42 +342,13 @@ MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore * `decompressedBound != ZSTD_CONTENTSIZE_ERROR` */ typedef struct { + size_t nbBlocks; size_t compressedSize; unsigned long long decompressedBound; } ZSTD_frameSizeInfo; /* decompress & legacy */ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */ -void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */ - -/* custom memory allocation functions */ -void* ZSTD_malloc(size_t size, ZSTD_customMem customMem); -void* ZSTD_calloc(size_t size, ZSTD_customMem customMem); -void ZSTD_free(void* ptr, ZSTD_customMem customMem); - - -MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */ -{ - assert(val != 0); - { -# if defined(_MSC_VER) /* Visual */ - unsigned long r=0; - return _BitScanReverse(&r, val) ? (unsigned)r : 0; -# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ - return __builtin_clz (val) ^ 31; -# elif defined(__ICCARM__) /* IAR Intrinsic */ - return 31 - __CLZ(val); -# else /* Software version */ - static const U32 DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; - U32 v = val; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - return DeBruijnClz[(v * 0x07C4ACDDU) >> 27]; -# endif - } -} +int ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */ /* ZSTD_invalidateRepCodes() : @@ -405,16 +366,27 @@ typedef struct { /*! ZSTD_getcBlockSize() : * Provides the size of compressed block from block header `src` */ -/* Used by: decompress, fullbench (does not get its definition from here) */ +/* Used by: decompress, fullbench */ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr); /*! ZSTD_decodeSeqHeaders() : * decode sequence header from src */ -/* Used by: decompress, fullbench (does not get its definition from here) */ +/* Used by: zstd_decompress_block, fullbench */ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, const void* src, size_t srcSize); +/** + * @returns true iff the CPU supports dynamic BMI2 dispatch. + */ +MEM_STATIC int ZSTD_cpuSupportsBmi2(void) +{ + ZSTD_cpuid_t cpuid = ZSTD_cpuid(); + return ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid); } +#if defined (__cplusplus) +} +#endif + #endif /* ZSTD_CCOMMON_H_MODULE */ diff --git a/third_party/zstd/include/zstd/common/zstd_trace.h b/third_party/zstd/include/zstd/common/zstd_trace.h new file mode 100644 index 00000000000..da20534ebd8 --- /dev/null +++ b/third_party/zstd/include/zstd/common/zstd_trace.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_TRACE_H +#define ZSTD_TRACE_H + +#if defined (__cplusplus) +extern "C" { +#endif + +#include + +/* weak symbol support + * For now, enable conservatively: + * - Only GNUC + * - Only ELF + * - Only x86-64, i386 and aarch64 + * Also, explicitly disable on platforms known not to work so they aren't + * forgotten in the future. + */ +#if !defined(ZSTD_HAVE_WEAK_SYMBOLS) && \ + defined(__GNUC__) && defined(__ELF__) && \ + (defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86) || defined(__aarch64__)) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__MINGW32__) && \ + !defined(__CYGWIN__) && !defined(_AIX) +# define ZSTD_HAVE_WEAK_SYMBOLS 1 +#else +# define ZSTD_HAVE_WEAK_SYMBOLS 0 +#endif +#if ZSTD_HAVE_WEAK_SYMBOLS +# define ZSTD_WEAK_ATTR __attribute__((__weak__)) +#else +# define ZSTD_WEAK_ATTR +#endif + +/* Only enable tracing when weak symbols are available. */ +#ifndef ZSTD_TRACE +# define ZSTD_TRACE ZSTD_HAVE_WEAK_SYMBOLS +#endif + +#if ZSTD_TRACE + +struct ZSTD_CCtx_s; +struct ZSTD_DCtx_s; +struct ZSTD_CCtx_params_s; + +typedef struct { + /** + * ZSTD_VERSION_NUMBER + * + * This is guaranteed to be the first member of ZSTD_trace. + * Otherwise, this struct is not stable between versions. If + * the version number does not match your expectation, you + * should not interpret the rest of the struct. + */ + unsigned version; + /** + * Non-zero if streaming (de)compression is used. + */ + unsigned streaming; + /** + * The dictionary ID. + */ + unsigned dictionaryID; + /** + * Is the dictionary cold? + * Only set on decompression. + */ + unsigned dictionaryIsCold; + /** + * The dictionary size or zero if no dictionary. + */ + size_t dictionarySize; + /** + * The uncompressed size of the data. + */ + size_t uncompressedSize; + /** + * The compressed size of the data. + */ + size_t compressedSize; + /** + * The fully resolved CCtx parameters (NULL on decompression). + */ + struct ZSTD_CCtx_params_s const* params; + /** + * The ZSTD_CCtx pointer (NULL on decompression). + */ + struct ZSTD_CCtx_s const* cctx; + /** + * The ZSTD_DCtx pointer (NULL on compression). + */ + struct ZSTD_DCtx_s const* dctx; +} ZSTD_Trace; + +/** + * A tracing context. It must be 0 when tracing is disabled. + * Otherwise, any non-zero value returned by a tracing begin() + * function is presented to any subsequent calls to end(). + * + * Any non-zero value is treated as tracing is enabled and not + * interpreted by the library. + * + * Two possible uses are: + * * A timestamp for when the begin() function was called. + * * A unique key identifying the (de)compression, like the + * address of the [dc]ctx pointer if you need to track + * more information than just a timestamp. + */ +typedef unsigned long long ZSTD_TraceCtx; + +/** + * Trace the beginning of a compression call. + * @param cctx The dctx pointer for the compression. + * It can be used as a key to map begin() to end(). + * @returns Non-zero if tracing is enabled. The return value is + * passed to ZSTD_trace_compress_end(). + */ +ZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_compress_begin( + struct ZSTD_CCtx_s const* cctx); + +/** + * Trace the end of a compression call. + * @param ctx The return value of ZSTD_trace_compress_begin(). + * @param trace The zstd tracing info. + */ +ZSTD_WEAK_ATTR void ZSTD_trace_compress_end( + ZSTD_TraceCtx ctx, + ZSTD_Trace const* trace); + +/** + * Trace the beginning of a decompression call. + * @param dctx The dctx pointer for the decompression. + * It can be used as a key to map begin() to end(). + * @returns Non-zero if tracing is enabled. The return value is + * passed to ZSTD_trace_compress_end(). + */ +ZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_decompress_begin( + struct ZSTD_DCtx_s const* dctx); + +/** + * Trace the end of a decompression call. + * @param ctx The return value of ZSTD_trace_decompress_begin(). + * @param trace The zstd tracing info. + */ +ZSTD_WEAK_ATTR void ZSTD_trace_decompress_end( + ZSTD_TraceCtx ctx, + ZSTD_Trace const* trace); + +#endif /* ZSTD_TRACE */ + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_TRACE_H */ diff --git a/third_party/zstd/include/zstd/compress/zstd_cwksp.h b/third_party/zstd/include/zstd/compress/zstd_cwksp.h deleted file mode 100644 index aea4f469cc5..00000000000 --- a/third_party/zstd/include/zstd/compress/zstd_cwksp.h +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - -#ifndef ZSTD_CWKSP_H -#define ZSTD_CWKSP_H - -/*-************************************* -* Dependencies -***************************************/ -#include "zstd/common/zstd_internal.h" - -/*-************************************* -* Constants -***************************************/ - -/* Since the workspace is effectively its own little malloc implementation / - * arena, when we run under ASAN, we should similarly insert redzones between - * each internal element of the workspace, so ASAN will catch overruns that - * reach outside an object but that stay inside the workspace. - * - * This defines the size of that redzone. - */ -#ifndef ZSTD_CWKSP_ASAN_REDZONE_SIZE -#define ZSTD_CWKSP_ASAN_REDZONE_SIZE 128 -#endif - -#if defined (MEMORY_SANITIZER) -#include -#endif - -namespace duckdb_zstd { - -/*-************************************* -* Structures -***************************************/ -typedef enum { - ZSTD_cwksp_alloc_objects, - ZSTD_cwksp_alloc_buffers, - ZSTD_cwksp_alloc_aligned -} ZSTD_cwksp_alloc_phase_e; - -/** - * Zstd fits all its internal datastructures into a single continuous buffer, - * so that it only needs to perform a single OS allocation (or so that a buffer - * can be provided to it and it can perform no allocations at all). This buffer - * is called the workspace. - * - * Several optimizations complicate that process of allocating memory ranges - * from this workspace for each internal datastructure: - * - * - These different internal datastructures have different setup requirements: - * - * - The static objects need to be cleared once and can then be trivially - * reused for each compression. - * - * - Various buffers don't need to be initialized at all--they are always - * written into before they're read. - * - * - The matchstate tables have a unique requirement that they don't need - * their memory to be totally cleared, but they do need the memory to have - * some bound, i.e., a guarantee that all values in the memory they've been - * allocated is less than some maximum value (which is the starting value - * for the indices that they will then use for compression). When this - * guarantee is provided to them, they can use the memory without any setup - * work. When it can't, they have to clear the area. - * - * - These buffers also have different alignment requirements. - * - * - We would like to reuse the objects in the workspace for multiple - * compressions without having to perform any expensive reallocation or - * reinitialization work. - * - * - We would like to be able to efficiently reuse the workspace across - * multiple compressions **even when the compression parameters change** and - * we need to resize some of the objects (where possible). - * - * To attempt to manage this buffer, given these constraints, the ZSTD_cwksp - * abstraction was created. It works as follows: - * - * Workspace Layout: - * - * [ ... workspace ... ] - * [objects][tables ... ->] free space [<- ... aligned][<- ... buffers] - * - * The various objects that live in the workspace are divided into the - * following categories, and are allocated separately: - * - * - Static objects: this is optionally the enclosing ZSTD_CCtx or ZSTD_CDict, - * so that literally everything fits in a single buffer. Note: if present, - * this must be the first object in the workspace, since ZSTD_free{CCtx, - * CDict}() rely on a pointer comparison to see whether one or two frees are - * required. - * - * - Fixed size objects: these are fixed-size, fixed-count objects that are - * nonetheless "dynamically" allocated in the workspace so that we can - * control how they're initialized separately from the broader ZSTD_CCtx. - * Examples: - * - Entropy Workspace - * - 2 x ZSTD_compressedBlockState_t - * - CDict dictionary contents - * - * - Tables: these are any of several different datastructures (hash tables, - * chain tables, binary trees) that all respect a common format: they are - * uint32_t arrays, all of whose values are between 0 and (nextSrc - base). - * Their sizes depend on the cparams. - * - * - Aligned: these buffers are used for various purposes that require 4 byte - * alignment, but don't require any initialization before they're used. - * - * - Buffers: these buffers are used for various purposes that don't require - * any alignment or initialization before they're used. This means they can - * be moved around at no cost for a new compression. - * - * Allocating Memory: - * - * The various types of objects must be allocated in order, so they can be - * correctly packed into the workspace buffer. That order is: - * - * 1. Objects - * 2. Buffers - * 3. Aligned - * 4. Tables - * - * Attempts to reserve objects of different types out of order will fail. - */ -typedef struct { - void* workspace; - void* workspaceEnd; - - void* objectEnd; - void* tableEnd; - void* tableValidEnd; - void* allocStart; - - int allocFailed; - int workspaceOversizedDuration; - ZSTD_cwksp_alloc_phase_e phase; -} ZSTD_cwksp; - -/*-************************************* -* Functions -***************************************/ - -MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws); - -MEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) { - (void)ws; - assert(ws->workspace <= ws->objectEnd); - assert(ws->objectEnd <= ws->tableEnd); - assert(ws->objectEnd <= ws->tableValidEnd); - assert(ws->tableEnd <= ws->allocStart); - assert(ws->tableValidEnd <= ws->allocStart); - assert(ws->allocStart <= ws->workspaceEnd); -} - -/** - * Align must be a power of 2. - */ -MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) { - size_t const mask = align - 1; - assert((align & mask) == 0); - return (size + mask) & ~mask; -} - -/** - * Use this to determine how much space in the workspace we will consume to - * allocate this object. (Normally it should be exactly the size of the object, - * but under special conditions, like ASAN, where we pad each object, it might - * be larger.) - * - * Since tables aren't currently redzoned, you don't need to call through this - * to figure out how much space you need for the matchState tables. Everything - * else is though. - */ -MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) { -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - return size + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; -#else - return size; -#endif -} - -MEM_STATIC void ZSTD_cwksp_internal_advance_phase( - ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase) { - assert(phase >= ws->phase); - if (phase > ws->phase) { - if (ws->phase < ZSTD_cwksp_alloc_buffers && - phase >= ZSTD_cwksp_alloc_buffers) { - ws->tableValidEnd = ws->objectEnd; - } - if (ws->phase < ZSTD_cwksp_alloc_aligned && - phase >= ZSTD_cwksp_alloc_aligned) { - /* If unaligned allocations down from a too-large top have left us - * unaligned, we need to realign our alloc ptr. Technically, this - * can consume space that is unaccounted for in the neededSpace - * calculation. However, I believe this can only happen when the - * workspace is too large, and specifically when it is too large - * by a larger margin than the space that will be consumed. */ - /* TODO: cleaner, compiler warning friendly way to do this??? */ - ws->allocStart = (BYTE*)ws->allocStart - ((size_t)ws->allocStart & (sizeof(U32)-1)); - if (ws->allocStart < ws->tableValidEnd) { - ws->tableValidEnd = ws->allocStart; - } - } - ws->phase = phase; - } -} - -/** - * Returns whether this object/buffer/etc was allocated in this workspace. - */ -MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr) { - return (ptr != NULL) && (ws->workspace <= ptr) && (ptr <= ws->workspaceEnd); -} - -/** - * Internal function. Do not use directly. - */ -MEM_STATIC void* ZSTD_cwksp_reserve_internal( - ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase) { - void* alloc; - void* bottom = ws->tableEnd; - ZSTD_cwksp_internal_advance_phase(ws, phase); - alloc = (BYTE *)ws->allocStart - bytes; - -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - /* over-reserve space */ - alloc = (BYTE *)alloc - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; -#endif - - DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining", - alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes); - ZSTD_cwksp_assert_internal_consistency(ws); - assert(alloc >= bottom); - if (alloc < bottom) { - DEBUGLOG(4, "cwksp: alloc failed!"); - ws->allocFailed = 1; - return NULL; - } - if (alloc < ws->tableValidEnd) { - ws->tableValidEnd = alloc; - } - ws->allocStart = alloc; - -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on - * either size. */ - alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE; - __asan_unpoison_memory_region(alloc, bytes); -#endif - - return alloc; -} - -/** - * Reserves and returns unaligned memory. - */ -MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes) { - return (BYTE*)ZSTD_cwksp_reserve_internal(ws, bytes, ZSTD_cwksp_alloc_buffers); -} - -/** - * Reserves and returns memory sized on and aligned on sizeof(unsigned). - */ -MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) { - assert((bytes & (sizeof(U32)-1)) == 0); - return ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, sizeof(U32)), ZSTD_cwksp_alloc_aligned); -} - -/** - * Aligned on sizeof(unsigned). These buffers have the special property that - * their values remain constrained, allowing us to re-use them without - * memset()-ing them. - */ -MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) { - const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned; - void* alloc = ws->tableEnd; - void* end = (BYTE *)alloc + bytes; - void* top = ws->allocStart; - - DEBUGLOG(5, "cwksp: reserving %p table %zd bytes, %zd bytes remaining", - alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes); - assert((bytes & (sizeof(U32)-1)) == 0); - ZSTD_cwksp_internal_advance_phase(ws, phase); - ZSTD_cwksp_assert_internal_consistency(ws); - assert(end <= top); - if (end > top) { - DEBUGLOG(4, "cwksp: table alloc failed!"); - ws->allocFailed = 1; - return NULL; - } - ws->tableEnd = end; - -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - __asan_unpoison_memory_region(alloc, bytes); -#endif - - return alloc; -} - -/** - * Aligned on sizeof(void*). - */ -MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) { - size_t roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*)); - void* alloc = ws->objectEnd; - void* end = (BYTE*)alloc + roundedBytes; - -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - /* over-reserve space */ - end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; -#endif - - DEBUGLOG(5, - "cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining", - alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes); - assert(((size_t)alloc & (sizeof(void*)-1)) == 0); - assert((bytes & (sizeof(void*)-1)) == 0); - ZSTD_cwksp_assert_internal_consistency(ws); - /* we must be in the first phase, no advance is possible */ - if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) { - DEBUGLOG(4, "cwksp: object alloc failed!"); - ws->allocFailed = 1; - return NULL; - } - ws->objectEnd = end; - ws->tableEnd = end; - ws->tableValidEnd = end; - -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on - * either size. */ - alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE; - __asan_unpoison_memory_region(alloc, bytes); -#endif - - return alloc; -} - -MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) { - DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty"); - -#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) - /* To validate that the table re-use logic is sound, and that we don't - * access table space that we haven't cleaned, we re-"poison" the table - * space every time we mark it dirty. */ - { - size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd; - assert(__msan_test_shadow(ws->objectEnd, size) == -1); - __msan_poison(ws->objectEnd, size); - } -#endif - - assert(ws->tableValidEnd >= ws->objectEnd); - assert(ws->tableValidEnd <= ws->allocStart); - ws->tableValidEnd = ws->objectEnd; - ZSTD_cwksp_assert_internal_consistency(ws); -} - -MEM_STATIC void ZSTD_cwksp_mark_tables_clean(ZSTD_cwksp* ws) { - DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_clean"); - assert(ws->tableValidEnd >= ws->objectEnd); - assert(ws->tableValidEnd <= ws->allocStart); - if (ws->tableValidEnd < ws->tableEnd) { - ws->tableValidEnd = ws->tableEnd; - } - ZSTD_cwksp_assert_internal_consistency(ws); -} - -/** - * Zero the part of the allocated tables not already marked clean. - */ -MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) { - DEBUGLOG(4, "cwksp: ZSTD_cwksp_clean_tables"); - assert(ws->tableValidEnd >= ws->objectEnd); - assert(ws->tableValidEnd <= ws->allocStart); - if (ws->tableValidEnd < ws->tableEnd) { - memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd); - } - ZSTD_cwksp_mark_tables_clean(ws); -} - -/** - * Invalidates table allocations. - * All other allocations remain valid. - */ -MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) { - DEBUGLOG(4, "cwksp: clearing tables!"); - -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - { - size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd; - __asan_poison_memory_region(ws->objectEnd, size); - } -#endif - - ws->tableEnd = ws->objectEnd; - ZSTD_cwksp_assert_internal_consistency(ws); -} - -/** - * Invalidates all buffer, aligned, and table allocations. - * Object allocations remain valid. - */ -MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) { - DEBUGLOG(4, "cwksp: clearing!"); - -#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) - /* To validate that the context re-use logic is sound, and that we don't - * access stuff that this compression hasn't initialized, we re-"poison" - * the workspace (or at least the non-static, non-table parts of it) - * every time we start a new compression. */ - { - size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->tableValidEnd; - __msan_poison(ws->tableValidEnd, size); - } -#endif - -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - { - size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->objectEnd; - __asan_poison_memory_region(ws->objectEnd, size); - } -#endif - - ws->tableEnd = ws->objectEnd; - ws->allocStart = ws->workspaceEnd; - ws->allocFailed = 0; - if (ws->phase > ZSTD_cwksp_alloc_buffers) { - ws->phase = ZSTD_cwksp_alloc_buffers; - } - ZSTD_cwksp_assert_internal_consistency(ws); -} - -/** - * The provided workspace takes ownership of the buffer [start, start+size). - * Any existing values in the workspace are ignored (the previously managed - * buffer, if present, must be separately freed). - */ -MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) { - DEBUGLOG(4, "cwksp: init'ing workspace with %zd bytes", size); - assert(((size_t)start & (sizeof(void*)-1)) == 0); /* ensure correct alignment */ - ws->workspace = start; - ws->workspaceEnd = (BYTE*)start + size; - ws->objectEnd = ws->workspace; - ws->tableValidEnd = ws->objectEnd; - ws->phase = ZSTD_cwksp_alloc_objects; - ZSTD_cwksp_clear(ws); - ws->workspaceOversizedDuration = 0; - ZSTD_cwksp_assert_internal_consistency(ws); -} - -MEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) { - void* workspace = ZSTD_malloc(size, customMem); - DEBUGLOG(4, "cwksp: creating new workspace with %zd bytes", size); - RETURN_ERROR_IF(workspace == NULL, memory_allocation, "NULL pointer!"); - ZSTD_cwksp_init(ws, workspace, size); - return 0; -} - -MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) { - void *ptr = ws->workspace; - DEBUGLOG(4, "cwksp: freeing workspace"); - memset(ws, 0, sizeof(ZSTD_cwksp)); - ZSTD_free(ptr, customMem); -} - -/** - * Moves the management of a workspace from one cwksp to another. The src cwksp - * is left in an invalid state (src must be re-init()'ed before its used again). - */ -MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) { - *dst = *src; - memset(src, 0, sizeof(ZSTD_cwksp)); -} - -MEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) { - return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace); -} - -MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) { - return ws->allocFailed; -} - -/*-************************************* -* Functions Checking Free Space -***************************************/ - -MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws) { - return (size_t)((BYTE*)ws->allocStart - (BYTE*)ws->tableEnd); -} - -MEM_STATIC int ZSTD_cwksp_check_available(ZSTD_cwksp* ws, size_t additionalNeededSpace) { - return ZSTD_cwksp_available_space(ws) >= additionalNeededSpace; -} - -MEM_STATIC int ZSTD_cwksp_check_too_large(ZSTD_cwksp* ws, size_t additionalNeededSpace) { - return ZSTD_cwksp_check_available( - ws, additionalNeededSpace * ZSTD_WORKSPACETOOLARGE_FACTOR); -} - -MEM_STATIC int ZSTD_cwksp_check_wasteful(ZSTD_cwksp* ws, size_t additionalNeededSpace) { - return ZSTD_cwksp_check_too_large(ws, additionalNeededSpace) - && ws->workspaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION; -} - -MEM_STATIC void ZSTD_cwksp_bump_oversized_duration( - ZSTD_cwksp* ws, size_t additionalNeededSpace) { - if (ZSTD_cwksp_check_too_large(ws, additionalNeededSpace)) { - ws->workspaceOversizedDuration++; - } else { - ws->workspaceOversizedDuration = 0; - } -} - -} - -#endif /* ZSTD_CWKSP_H */ diff --git a/third_party/zstd/include/zstd/compress/zstd_lazy.h b/third_party/zstd/include/zstd/compress/zstd_lazy.h deleted file mode 100644 index 555edbf1be1..00000000000 --- a/third_party/zstd/include/zstd/compress/zstd_lazy.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - -#ifndef ZSTD_LAZY_H -#define ZSTD_LAZY_H - -#include "zstd/compress/zstd_compress_internal.h" - -namespace duckdb_zstd { - -U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip); - -void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */ - -size_t ZSTD_compressBlock_btlazy2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); -size_t ZSTD_compressBlock_lazy2( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); -size_t ZSTD_compressBlock_lazy( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); -size_t ZSTD_compressBlock_greedy( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); - -size_t ZSTD_compressBlock_btlazy2_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); -size_t ZSTD_compressBlock_lazy2_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); -size_t ZSTD_compressBlock_lazy_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); -size_t ZSTD_compressBlock_greedy_dictMatchState( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); - -size_t ZSTD_compressBlock_greedy_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); -size_t ZSTD_compressBlock_lazy_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); -size_t ZSTD_compressBlock_lazy2_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); -size_t ZSTD_compressBlock_btlazy2_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); - -} - -#endif /* ZSTD_LAZY_H */ diff --git a/third_party/zstd/include/zstd/decompress/zstd_ddict.h b/third_party/zstd/include/zstd/decompress/zstd_ddict.h index a95f384fb22..c4ca8877a07 100644 --- a/third_party/zstd/include/zstd/decompress/zstd_ddict.h +++ b/third_party/zstd/include/zstd/decompress/zstd_ddict.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -15,10 +15,10 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include /* size_t */ -#include "zstd.h" /* ZSTD_DDict, and several public functions */ +#include "../common/zstd_deps.h" /* size_t */ +#include "../zstd.h" /* ZSTD_DDict, and several public functions */ + -namespace duckdb_zstd { /*-******************************************************* * Interface *********************************************************/ @@ -39,6 +39,6 @@ size_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict); void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); -} + #endif /* ZSTD_DDICT_H */ diff --git a/third_party/zstd/include/zstd/decompress/zstd_decompress_block.h b/third_party/zstd/include/zstd/decompress/zstd_decompress_block.h index 46d4a2103c1..ab152404ba0 100644 --- a/third_party/zstd/include/zstd/decompress/zstd_decompress_block.h +++ b/third_party/zstd/include/zstd/decompress/zstd_decompress_block.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -15,12 +15,11 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include /* size_t */ -#include "zstd.h" /* DCtx, and some public functions */ -#include "zstd/common/zstd_internal.h" /* blockProperties_t, and some public functions */ -#include "zstd/decompress/zstd_decompress_internal.h" /* ZSTD_seqSymbol */ +#include "../common/zstd_deps.h" /* size_t */ +#include "../zstd.h" /* DCtx, and some public functions */ +#include "../common/zstd_internal.h" /* blockProperties_t, and some public functions */ +#include "zstd_decompress_internal.h" /* ZSTD_seqSymbol */ -namespace duckdb_zstd { /* === Prototypes === */ @@ -34,6 +33,12 @@ namespace duckdb_zstd { */ + /* Streaming state is used to inform allocation of the literal buffer */ +typedef enum { + not_streaming = 0, + is_streaming = 1 +} streaming_operation; + /* ZSTD_decompressBlock_internal() : * decompress block, starting at `src`, * into destination buffer `dst`. @@ -42,20 +47,27 @@ namespace duckdb_zstd { */ size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, - const void* src, size_t srcSize, const int frame); + const void* src, size_t srcSize, const streaming_operation streaming); /* ZSTD_buildFSETable() : * generate FSE decoding table for one symbol (ll, ml or off) * this function must be called with valid parameters only * (dt is large enough, normalizedCounter distribution total is a power of 2, max is within range, etc.) * in which case it cannot fail. + * The workspace must be 4-byte aligned and at least ZSTD_BUILD_FSE_TABLE_WKSP_SIZE bytes, which is + * defined in zstd_decompress_internal.h. * Internal use only. */ void ZSTD_buildFSETable(ZSTD_seqSymbol* dt, const short* normalizedCounter, unsigned maxSymbolValue, - const U32* baseValue, const U32* nbAdditionalBits, - unsigned tableLog); + const U32* baseValue, const U8* nbAdditionalBits, + unsigned tableLog, void* wksp, size_t wkspSize, + int bmi2); + +/* Internal definition of ZSTD_decompressBlock() to avoid deprecation warnings. */ +size_t ZSTD_decompressBlock_deprecated(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize); -} #endif /* ZSTD_DEC_BLOCK_H */ diff --git a/third_party/zstd/include/zstd/decompress/zstd_decompress_internal.h b/third_party/zstd/include/zstd/decompress/zstd_decompress_internal.h index 6ff422e2c2b..83a7a0115fd 100644 --- a/third_party/zstd/include/zstd/decompress/zstd_decompress_internal.h +++ b/third_party/zstd/include/zstd/decompress/zstd_decompress_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -19,20 +19,41 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include "zstd/common/mem.h" /* BYTE, U16, U32 */ -#include "zstd/common/zstd_internal.h" /* ZSTD_seqSymbol */ +#include "../common/mem.h" /* BYTE, U16, U32 */ +#include "../common/zstd_internal.h" /* constants : MaxLL, MaxML, MaxOff, LLFSELog, etc. */ + -namespace duckdb_zstd { /*-******************************************************* * Constants *********************************************************/ -struct ZSTDConstants { - static const U32 LL_base[MaxLL+1]; - static const U32 OF_base[MaxOff+1]; - static const U32 OF_bits[MaxOff+1]; - static const U32 ML_base[MaxML+1]; -}; +static UNUSED_ATTR const U32 LL_base[MaxLL+1] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 18, 20, 22, 24, 28, 32, 40, + 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, + 0x2000, 0x4000, 0x8000, 0x10000 }; + +static UNUSED_ATTR const U32 OF_base[MaxOff+1] = { + 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, + 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, + 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, + 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD }; + +static UNUSED_ATTR const U8 OF_bits[MaxOff+1] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31 }; + +static UNUSED_ATTR const U32 ML_base[MaxML+1] = { + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 37, 39, 41, 43, 47, 51, 59, + 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, + 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 }; /*-******************************************************* @@ -52,12 +73,17 @@ struct ZSTDConstants { #define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log))) +#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE (sizeof(S16) * (MaxSeq + 1) + (1u << MaxFSELog) + sizeof(U64)) +#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32 ((ZSTD_BUILD_FSE_TABLE_WKSP_SIZE + sizeof(U32) - 1) / sizeof(U32)) +#define ZSTD_HUFFDTABLE_CAPACITY_LOG 12 + typedef struct { ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */ ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */ ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */ - HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */ + HUF_DTable hufTable[HUF_DTABLE_SIZE(ZSTD_HUFFDTABLE_CAPACITY_LOG)]; /* can accommodate HUF_decompress4X */ U32 rep[ZSTD_REP_NUM]; + U32 workspace[ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32]; } ZSTD_entropyDTables_t; typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader, @@ -74,10 +100,28 @@ typedef enum { ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */ } ZSTD_dictUses_e; +/* Hashset for storing references to multiple ZSTD_DDict within ZSTD_DCtx */ +typedef struct { + const ZSTD_DDict** ddictPtrTable; + size_t ddictPtrTableSize; + size_t ddictPtrCount; +} ZSTD_DDictHashSet; + +#ifndef ZSTD_DECODER_INTERNAL_BUFFER +# define ZSTD_DECODER_INTERNAL_BUFFER (1 << 16) +#endif + +#define ZSTD_LBMIN 64 +#define ZSTD_LBMAX (128 << 10) + +/* extra buffer, compensates when dst is not large enough to store litBuffer */ +#define ZSTD_LITBUFFEREXTRASIZE BOUNDED(ZSTD_LBMIN, ZSTD_DECODER_INTERNAL_BUFFER, ZSTD_LBMAX) + typedef enum { - ZSTD_obm_buffered = 0, /* Buffer the output */ - ZSTD_obm_stable = 1 /* ZSTD_outBuffer is stable */ -} ZSTD_outBufferMode_e; + ZSTD_not_in_dst = 0, /* Stored entirely within litExtraBuffer */ + ZSTD_in_dst = 1, /* Stored entirely within dst (in memory after current output write) */ + ZSTD_split = 2 /* Split between litExtraBuffer and dst */ +} ZSTD_litLocation_e; struct ZSTD_DCtx_s { @@ -93,6 +137,7 @@ struct ZSTD_DCtx_s const void* dictEnd; /* end of previous segment */ size_t expected; ZSTD_frameHeader fParams; + U64 processedCSize; U64 decodedSize; blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */ ZSTD_dStage stage; @@ -101,12 +146,17 @@ struct ZSTD_DCtx_s XXH64_state_t xxhState; size_t headerSize; ZSTD_format_e format; + ZSTD_forceIgnoreChecksum_e forceIgnoreChecksum; /* User specified: if == 1, will ignore checksums in compressed frame. Default == 0 */ + U32 validateChecksum; /* if == 1, will validate checksum. Is == 1 if (fParams.checksumFlag == 1) and (forceIgnoreChecksum == 0). */ const BYTE* litPtr; ZSTD_customMem customMem; size_t litSize; size_t rleSize; size_t staticSize; + int isFrameDecompression; +#if DYNAMIC_BMI2 != 0 int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */ +#endif /* dictionary */ ZSTD_DDict* ddictLocal; @@ -114,6 +164,10 @@ struct ZSTD_DCtx_s U32 dictID; int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */ ZSTD_dictUses_e dictUses; + ZSTD_DDictHashSet* ddictSet; /* Hash set for multiple ddicts */ + ZSTD_refMultipleDDicts_e refMultipleDDicts; /* User specified: if == 1, will allow references to multiple DDicts. Default == 0 (disabled) */ + int disableHufAsm; + int maxBlockSizeParam; /* streaming */ ZSTD_dStreamStage streamStage; @@ -126,16 +180,21 @@ struct ZSTD_DCtx_s size_t outStart; size_t outEnd; size_t lhSize; +#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1) void* legacyContext; U32 previousLegacyVersion; U32 legacyVersion; +#endif U32 hostageByte; int noForwardProgress; - ZSTD_outBufferMode_e outBufferMode; + ZSTD_bufferMode_e outBufferMode; ZSTD_outBuffer expectedOutBuffer; /* workspace */ - BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH]; + BYTE* litBuffer; + const BYTE* litBufferEnd; + ZSTD_litLocation_e litBufferLocation; + BYTE litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE + WILDCOPY_OVERLENGTH]; /* literal buffer can be split between storage within dst and within this scratch buffer */ BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; size_t oversizedDuration; @@ -144,8 +203,21 @@ struct ZSTD_DCtx_s void const* dictContentBeginForFuzzing; void const* dictContentEndForFuzzing; #endif + + /* Tracing */ +#if ZSTD_TRACE + ZSTD_TraceCtx traceCtx; +#endif }; /* typedef'd to ZSTD_DCtx within "zstd.h" */ +MEM_STATIC int ZSTD_DCtx_get_bmi2(const struct ZSTD_DCtx_s *dctx) { +#if DYNAMIC_BMI2 != 0 + return dctx->bmi2; +#else + (void)dctx; + return 0; +#endif +} /*-******************************************************* * Shared internal functions @@ -162,8 +234,7 @@ size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, * If yes, do nothing (continue on current segment). * If not, classify previous segment as "external dictionary", and start a new segment. * This function cannot fail. */ -void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst); +void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize); -} #endif /* ZSTD_DECOMPRESS_INTERNAL_H */ diff --git a/third_party/zstd/include/zstd/deprecated/zbuff.h b/third_party/zstd/include/zstd/deprecated/zbuff.h new file mode 100644 index 00000000000..a968245b36a --- /dev/null +++ b/third_party/zstd/include/zstd/deprecated/zbuff.h @@ -0,0 +1,214 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* *************************************************************** +* NOTES/WARNINGS +******************************************************************/ +/* The streaming API defined here is deprecated. + * Consider migrating towards ZSTD_compressStream() API in `zstd.h` + * See 'lib/README.md'. + *****************************************************************/ + + +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef ZSTD_BUFFERED_H_23987 +#define ZSTD_BUFFERED_H_23987 + +/* ************************************* +* Dependencies +***************************************/ +#include /* size_t */ +#include "../zstd.h" /* ZSTD_CStream, ZSTD_DStream, ZSTDLIB_API */ + + +/* *************************************************************** +* Compiler specifics +*****************************************************************/ +/* Deprecation warnings */ +/* Should these warnings be a problem, + * it is generally possible to disable them, + * typically with -Wno-deprecated-declarations for gcc + * or _CRT_SECURE_NO_WARNINGS in Visual. + * Otherwise, it's also possible to define ZBUFF_DISABLE_DEPRECATE_WARNINGS + */ +#ifdef ZBUFF_DISABLE_DEPRECATE_WARNINGS +# define ZBUFF_DEPRECATED(message) ZSTDLIB_API /* disable deprecation warnings */ +#else +# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ +# define ZBUFF_DEPRECATED(message) [[deprecated(message)]] ZSTDLIB_API +# elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__) +# define ZBUFF_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated(message))) +# elif defined(__GNUC__) && (__GNUC__ >= 3) +# define ZBUFF_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated)) +# elif defined(_MSC_VER) +# define ZBUFF_DEPRECATED(message) ZSTDLIB_API __declspec(deprecated(message)) +# else +# pragma message("WARNING: You need to implement ZBUFF_DEPRECATED for this compiler") +# define ZBUFF_DEPRECATED(message) ZSTDLIB_API +# endif +#endif /* ZBUFF_DISABLE_DEPRECATE_WARNINGS */ + + +/* ************************************* +* Streaming functions +***************************************/ +/* This is the easier "buffered" streaming API, +* using an internal buffer to lift all restrictions on user-provided buffers +* which can be any size, any place, for both input and output. +* ZBUFF and ZSTD are 100% interoperable, +* frames created by one can be decoded by the other one */ + +typedef ZSTD_CStream ZBUFF_CCtx; +ZBUFF_DEPRECATED("use ZSTD_createCStream") ZBUFF_CCtx* ZBUFF_createCCtx(void); +ZBUFF_DEPRECATED("use ZSTD_freeCStream") size_t ZBUFF_freeCCtx(ZBUFF_CCtx* cctx); + +ZBUFF_DEPRECATED("use ZSTD_initCStream") size_t ZBUFF_compressInit(ZBUFF_CCtx* cctx, int compressionLevel); +ZBUFF_DEPRECATED("use ZSTD_initCStream_usingDict") size_t ZBUFF_compressInitDictionary(ZBUFF_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel); + +ZBUFF_DEPRECATED("use ZSTD_compressStream") size_t ZBUFF_compressContinue(ZBUFF_CCtx* cctx, void* dst, size_t* dstCapacityPtr, const void* src, size_t* srcSizePtr); +ZBUFF_DEPRECATED("use ZSTD_flushStream") size_t ZBUFF_compressFlush(ZBUFF_CCtx* cctx, void* dst, size_t* dstCapacityPtr); +ZBUFF_DEPRECATED("use ZSTD_endStream") size_t ZBUFF_compressEnd(ZBUFF_CCtx* cctx, void* dst, size_t* dstCapacityPtr); + +/*-************************************************* +* Streaming compression - howto +* +* A ZBUFF_CCtx object is required to track streaming operation. +* Use ZBUFF_createCCtx() and ZBUFF_freeCCtx() to create/release resources. +* ZBUFF_CCtx objects can be reused multiple times. +* +* Start by initializing ZBUF_CCtx. +* Use ZBUFF_compressInit() to start a new compression operation. +* Use ZBUFF_compressInitDictionary() for a compression which requires a dictionary. +* +* Use ZBUFF_compressContinue() repetitively to consume input stream. +* *srcSizePtr and *dstCapacityPtr can be any size. +* The function will report how many bytes were read or written within *srcSizePtr and *dstCapacityPtr. +* Note that it may not consume the entire input, in which case it's up to the caller to present again remaining data. +* The content of `dst` will be overwritten (up to *dstCapacityPtr) at each call, so save its content if it matters or change @dst . +* @return : a hint to preferred nb of bytes to use as input for next function call (it's just a hint, to improve latency) +* or an error code, which can be tested using ZBUFF_isError(). +* +* At any moment, it's possible to flush whatever data remains within buffer, using ZBUFF_compressFlush(). +* The nb of bytes written into `dst` will be reported into *dstCapacityPtr. +* Note that the function cannot output more than *dstCapacityPtr, +* therefore, some content might still be left into internal buffer if *dstCapacityPtr is too small. +* @return : nb of bytes still present into internal buffer (0 if it's empty) +* or an error code, which can be tested using ZBUFF_isError(). +* +* ZBUFF_compressEnd() instructs to finish a frame. +* It will perform a flush and write frame epilogue. +* The epilogue is required for decoders to consider a frame completed. +* Similar to ZBUFF_compressFlush(), it may not be able to output the entire internal buffer content if *dstCapacityPtr is too small. +* In which case, call again ZBUFF_compressFlush() to complete the flush. +* @return : nb of bytes still present into internal buffer (0 if it's empty) +* or an error code, which can be tested using ZBUFF_isError(). +* +* Hint : _recommended buffer_ sizes (not compulsory) : ZBUFF_recommendedCInSize() / ZBUFF_recommendedCOutSize() +* input : ZBUFF_recommendedCInSize==128 KB block size is the internal unit, use this value to reduce intermediate stages (better latency) +* output : ZBUFF_recommendedCOutSize==ZSTD_compressBound(128 KB) + 3 + 3 : ensures it's always possible to write/flush/end a full block. Skip some buffering. +* By using both, it ensures that input will be entirely consumed, and output will always contain the result, reducing intermediate buffering. +* **************************************************/ + + +typedef ZSTD_DStream ZBUFF_DCtx; +ZBUFF_DEPRECATED("use ZSTD_createDStream") ZBUFF_DCtx* ZBUFF_createDCtx(void); +ZBUFF_DEPRECATED("use ZSTD_freeDStream") size_t ZBUFF_freeDCtx(ZBUFF_DCtx* dctx); + +ZBUFF_DEPRECATED("use ZSTD_initDStream") size_t ZBUFF_decompressInit(ZBUFF_DCtx* dctx); +ZBUFF_DEPRECATED("use ZSTD_initDStream_usingDict") size_t ZBUFF_decompressInitDictionary(ZBUFF_DCtx* dctx, const void* dict, size_t dictSize); + +ZBUFF_DEPRECATED("use ZSTD_decompressStream") size_t ZBUFF_decompressContinue(ZBUFF_DCtx* dctx, + void* dst, size_t* dstCapacityPtr, + const void* src, size_t* srcSizePtr); + +/*-*************************************************************************** +* Streaming decompression howto +* +* A ZBUFF_DCtx object is required to track streaming operations. +* Use ZBUFF_createDCtx() and ZBUFF_freeDCtx() to create/release resources. +* Use ZBUFF_decompressInit() to start a new decompression operation, +* or ZBUFF_decompressInitDictionary() if decompression requires a dictionary. +* Note that ZBUFF_DCtx objects can be re-init multiple times. +* +* Use ZBUFF_decompressContinue() repetitively to consume your input. +* *srcSizePtr and *dstCapacityPtr can be any size. +* The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr. +* Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again. +* The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`. +* @return : 0 when a frame is completely decoded and fully flushed, +* 1 when there is still some data left within internal buffer to flush, +* >1 when more data is expected, with value being a suggested next input size (it's just a hint, which helps latency), +* or an error code, which can be tested using ZBUFF_isError(). +* +* Hint : recommended buffer sizes (not compulsory) : ZBUFF_recommendedDInSize() and ZBUFF_recommendedDOutSize() +* output : ZBUFF_recommendedDOutSize== 128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded. +* input : ZBUFF_recommendedDInSize == 128KB + 3; +* just follow indications from ZBUFF_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 . +* *******************************************************************************/ + + +/* ************************************* +* Tool functions +***************************************/ +ZBUFF_DEPRECATED("use ZSTD_isError") unsigned ZBUFF_isError(size_t errorCode); +ZBUFF_DEPRECATED("use ZSTD_getErrorName") const char* ZBUFF_getErrorName(size_t errorCode); + +/** Functions below provide recommended buffer sizes for Compression or Decompression operations. +* These sizes are just hints, they tend to offer better latency */ +ZBUFF_DEPRECATED("use ZSTD_CStreamInSize") size_t ZBUFF_recommendedCInSize(void); +ZBUFF_DEPRECATED("use ZSTD_CStreamOutSize") size_t ZBUFF_recommendedCOutSize(void); +ZBUFF_DEPRECATED("use ZSTD_DStreamInSize") size_t ZBUFF_recommendedDInSize(void); +ZBUFF_DEPRECATED("use ZSTD_DStreamOutSize") size_t ZBUFF_recommendedDOutSize(void); + +#endif /* ZSTD_BUFFERED_H_23987 */ + + +#ifdef ZBUFF_STATIC_LINKING_ONLY +#ifndef ZBUFF_STATIC_H_30298098432 +#define ZBUFF_STATIC_H_30298098432 + +/* ==================================================================================== + * The definitions in this section are considered experimental. + * They should never be used in association with a dynamic library, as they may change in the future. + * They are provided for advanced usages. + * Use them only in association with static linking. + * ==================================================================================== */ + +/*--- Dependency ---*/ +#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters, ZSTD_customMem */ +#include "../zstd.h" + + +/*--- Custom memory allocator ---*/ +/*! ZBUFF_createCCtx_advanced() : + * Create a ZBUFF compression context using external alloc and free functions */ +ZBUFF_DEPRECATED("use ZSTD_createCStream_advanced") ZBUFF_CCtx* ZBUFF_createCCtx_advanced(ZSTD_customMem customMem); + +/*! ZBUFF_createDCtx_advanced() : + * Create a ZBUFF decompression context using external alloc and free functions */ +ZBUFF_DEPRECATED("use ZSTD_createDStream_advanced") ZBUFF_DCtx* ZBUFF_createDCtx_advanced(ZSTD_customMem customMem); + + +/*--- Advanced Streaming Initialization ---*/ +ZBUFF_DEPRECATED("use ZSTD_initDStream_usingDict") size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc, + const void* dict, size_t dictSize, + ZSTD_parameters params, unsigned long long pledgedSrcSize); + + +#endif /* ZBUFF_STATIC_H_30298098432 */ +#endif /* ZBUFF_STATIC_LINKING_ONLY */ + + +#if defined (__cplusplus) +} +#endif diff --git a/third_party/zstd/include/zstd/include/compress/clevels.h b/third_party/zstd/include/zstd/include/compress/clevels.h new file mode 100644 index 00000000000..c18da465f32 --- /dev/null +++ b/third_party/zstd/include/zstd/include/compress/clevels.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_CLEVELS_H +#define ZSTD_CLEVELS_H + +#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressionParameters */ +#include "../zstd.h" + +/*-===== Pre-defined compression levels =====-*/ + +#define ZSTD_MAX_CLEVEL 22 + +#ifdef __GNUC__ +__attribute__((__unused__)) +#endif + +static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = { +{ /* "default" - for any srcSize > 256 KB */ + /* W, C, H, S, L, TL, strat */ + { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */ + { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */ + { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */ + { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */ + { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */ + { 21, 18, 19, 3, 5, 2, ZSTD_greedy }, /* level 5 */ + { 21, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6 */ + { 21, 19, 20, 4, 5, 8, ZSTD_lazy }, /* level 7 */ + { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 8 */ + { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */ + { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 10 */ + { 22, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 11 */ + { 22, 22, 23, 6, 5, 32, ZSTD_lazy2 }, /* level 12 */ + { 22, 22, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */ + { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */ + { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */ + { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */ + { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */ + { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */ + { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */ + { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */ + { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */ + { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */ +}, +{ /* for srcSize <= 256 KB */ + /* W, C, H, S, L, T, strat */ + { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */ + { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */ + { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */ + { 18, 16, 17, 3, 5, 2, ZSTD_greedy }, /* level 4.*/ + { 18, 17, 18, 5, 5, 2, ZSTD_greedy }, /* level 5.*/ + { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/ + { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */ + { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/ + { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/ + { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */ + { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ + { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/ + { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/ + { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/ + { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/ + { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/ +}, +{ /* for srcSize <= 128 KB */ + /* W, C, H, S, L, T, strat */ + { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */ + { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */ + { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */ + { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */ + { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */ + { 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */ + { 17, 16, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 17, 16, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */ + { 17, 16, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */ + { 17, 16, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */ + { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */ + { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */ + { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/ + { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/ + { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/ + { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/ + { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/ + { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/ + { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/ +}, +{ /* for srcSize <= 16 KB */ + /* W, C, H, S, L, T, strat */ + { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */ + { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */ + { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */ + { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */ + { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */ + { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/ + { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */ + { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */ + { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/ + { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/ + { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/ + { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/ + { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/ + { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/ + { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/ + { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/ + { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/ + { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/ + { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/ + { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/ + { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/ + { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/ + { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/ +}, +}; + + + +#endif /* ZSTD_CLEVELS_H */ diff --git a/third_party/zstd/include/zstd/compress/hist.h b/third_party/zstd/include/zstd/include/compress/hist.h similarity index 96% rename from third_party/zstd/include/zstd/compress/hist.h rename to third_party/zstd/include/zstd/include/compress/hist.h index 41bbbbeab61..887896b813b 100644 --- a/third_party/zstd/include/zstd/compress/hist.h +++ b/third_party/zstd/include/zstd/include/compress/hist.h @@ -1,7 +1,7 @@ /* ****************************************************************** * hist : Histogram functions * part of Finite State Entropy project - * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * You can contact the author at : * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy @@ -14,10 +14,9 @@ ****************************************************************** */ /* --- dependencies --- */ -#include /* size_t */ +#include "../common/zstd_deps.h" /* size_t */ -namespace duckdb_zstd { /* --- simple histogram functions --- */ /*! HIST_count(): @@ -74,5 +73,3 @@ size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, */ unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize); - -} diff --git a/third_party/zstd/include/zstd/compress/zstd_compress_internal.h b/third_party/zstd/include/zstd/include/compress/zstd_compress_internal.h similarity index 55% rename from third_party/zstd/include/zstd/compress/zstd_compress_internal.h rename to third_party/zstd/include/zstd/include/compress/zstd_compress_internal.h index 5e8c6e099a9..e41d7b78ec6 100644 --- a/third_party/zstd/include/zstd/compress/zstd_compress_internal.h +++ b/third_party/zstd/include/zstd/include/compress/zstd_compress_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -18,11 +18,16 @@ /*-************************************* * Dependencies ***************************************/ -#include "zstd/common/zstd_internal.h" -#include "zstd/compress/zstd_cwksp.h" -// #ifdef ZSTD_MULTITHREAD -// # include "zstdmt_compress.h" -// #endif +#include "../common/zstd_internal.h" +#include "zstd_cwksp.h" +#ifdef ZSTD_MULTITHREAD +# include "zstdmt_compress.h" +#endif +#include "../common/bits.h" /* ZSTD_highbit32, ZSTD_NbCommonBytes */ + +#if defined (__cplusplus) +extern "C" { +#endif /*-************************************* * Constants @@ -34,11 +39,10 @@ It's not a big deal though : candidate will just be sorted again. Additionally, candidate position 1 will be lost. But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss. - The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table re-use with a different strategy. + The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table reuse with a different strategy. This constant is required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */ -namespace duckdb_zstd { /*-************************************* * Context memory management ***************************************/ @@ -60,7 +64,7 @@ typedef struct { } ZSTD_localDict; typedef struct { - U32 CTable[HUF_CTABLE_SIZE_U32(255)]; + HUF_CElt CTable[HUF_CTABLE_SIZE_ST(255)]; HUF_repeat repeatMode; } ZSTD_hufCTables_t; @@ -78,29 +82,101 @@ typedef struct { ZSTD_fseCTables_t fse; } ZSTD_entropyCTables_t; +/*********************************************** +* Entropy buffer statistics structs and funcs * +***********************************************/ +/** ZSTD_hufCTablesMetadata_t : + * Stores Literals Block Type for a super-block in hType, and + * huffman tree description in hufDesBuffer. + * hufDesSize refers to the size of huffman tree description in bytes. + * This metadata is populated in ZSTD_buildBlockEntropyStats_literals() */ +typedef struct { + symbolEncodingType_e hType; + BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE]; + size_t hufDesSize; +} ZSTD_hufCTablesMetadata_t; + +/** ZSTD_fseCTablesMetadata_t : + * Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and + * fse tables in fseTablesBuffer. + * fseTablesSize refers to the size of fse tables in bytes. + * This metadata is populated in ZSTD_buildBlockEntropyStats_sequences() */ typedef struct { - U32 off; - U32 len; + symbolEncodingType_e llType; + symbolEncodingType_e ofType; + symbolEncodingType_e mlType; + BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE]; + size_t fseTablesSize; + size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */ +} ZSTD_fseCTablesMetadata_t; + +typedef struct { + ZSTD_hufCTablesMetadata_t hufMetadata; + ZSTD_fseCTablesMetadata_t fseMetadata; +} ZSTD_entropyCTablesMetadata_t; + +/** ZSTD_buildBlockEntropyStats() : + * Builds entropy for the block. + * @return : 0 on success or error code */ +size_t ZSTD_buildBlockEntropyStats( + const seqStore_t* seqStorePtr, + const ZSTD_entropyCTables_t* prevEntropy, + ZSTD_entropyCTables_t* nextEntropy, + const ZSTD_CCtx_params* cctxParams, + ZSTD_entropyCTablesMetadata_t* entropyMetadata, + void* workspace, size_t wkspSize); + +/********************************* +* Compression internals structs * +*********************************/ + +typedef struct { + U32 off; /* Offset sumtype code for the match, using ZSTD_storeSeq() format */ + U32 len; /* Raw length of match */ } ZSTD_match_t; typedef struct { - int price; - U32 off; - U32 mlen; - U32 litlen; - U32 rep[ZSTD_REP_NUM]; + U32 offset; /* Offset of sequence */ + U32 litLength; /* Length of literals prior to match */ + U32 matchLength; /* Raw length of match */ +} rawSeq; + +typedef struct { + rawSeq* seq; /* The start of the sequences */ + size_t pos; /* The index in seq where reading stopped. pos <= size. */ + size_t posInSequence; /* The position within the sequence at seq[pos] where reading + stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */ + size_t size; /* The number of sequences. <= capacity. */ + size_t capacity; /* The capacity starting from `seq` pointer */ +} rawSeqStore_t; + +typedef struct { + U32 idx; /* Index in array of ZSTD_Sequence */ + U32 posInSequence; /* Position within sequence at idx */ + size_t posInSrc; /* Number of bytes given by sequences provided so far */ +} ZSTD_sequencePosition; + +UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0}; + +typedef struct { + int price; /* price from beginning of segment to this position */ + U32 off; /* offset of previous match */ + U32 mlen; /* length of previous match */ + U32 litlen; /* nb of literals since previous match */ + U32 rep[ZSTD_REP_NUM]; /* offset history after previous match */ } ZSTD_optimal_t; typedef enum { zop_dynamic=0, zop_predef } ZSTD_OptPrice_e; +#define ZSTD_OPT_SIZE (ZSTD_OPT_NUM+3) typedef struct { /* All tables are allocated inside cctx->workspace by ZSTD_resetCCtx_internal() */ unsigned* litFreq; /* table of literals statistics, of size 256 */ unsigned* litLengthFreq; /* table of litLength statistics, of size (MaxLL+1) */ unsigned* matchLengthFreq; /* table of matchLength statistics, of size (MaxML+1) */ unsigned* offCodeFreq; /* table of offCode statistics, of size (MaxOff+1) */ - ZSTD_match_t* matchTable; /* list of found matches, of size ZSTD_OPT_NUM+1 */ - ZSTD_optimal_t* priceTable; /* All positions tracked by optimal parser, of size ZSTD_OPT_NUM+1 */ + ZSTD_match_t* matchTable; /* list of found matches, of size ZSTD_OPT_SIZE */ + ZSTD_optimal_t* priceTable; /* All positions tracked by optimal parser, of size ZSTD_OPT_SIZE */ U32 litSum; /* nb of literals */ U32 litLengthSum; /* nb of litLength codes */ @@ -112,7 +188,7 @@ typedef struct { U32 offCodeSumBasePrice; /* to compare to log2(offreq) */ ZSTD_OptPrice_e priceType; /* prices can be determined dynamically, or follow a pre-defined cost structure */ const ZSTD_entropyCTables_t* symbolCosts; /* pre-calculated dictionary statistics */ - ZSTD_literalCompressionMode_e literalCompressionMode; + ZSTD_paramSwitch_e literalCompressionMode; } optState_t; typedef struct { @@ -121,14 +197,23 @@ typedef struct { } ZSTD_compressedBlockState_t; typedef struct { - BYTE const* nextSrc; /* next block here to continue on current prefix */ - BYTE const* base; /* All regular indexes relative to this position */ - BYTE const* dictBase; /* extDict indexes relative to this position */ - U32 dictLimit; /* below that point, need extDict */ - U32 lowLimit; /* below that point, no more valid data */ + BYTE const* nextSrc; /* next block here to continue on current prefix */ + BYTE const* base; /* All regular indexes relative to this position */ + BYTE const* dictBase; /* extDict indexes relative to this position */ + U32 dictLimit; /* below that point, need extDict */ + U32 lowLimit; /* below that point, no more valid data */ + U32 nbOverflowCorrections; /* Number of times overflow correction has run since + * ZSTD_window_init(). Useful for debugging coredumps + * and for ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY. + */ } ZSTD_window_t; +#define ZSTD_WINDOW_START_INDEX 2 + typedef struct ZSTD_matchState_t ZSTD_matchState_t; + +#define ZSTD_ROW_HASH_CACHE_SIZE 8 /* Size of prefetching hash cache for row-based matchfinder */ + struct ZSTD_matchState_t { ZSTD_window_t window; /* State for window round buffer management */ U32 loadedDictEnd; /* index of end of dictionary, within context's referential. @@ -140,12 +225,38 @@ struct ZSTD_matchState_t { */ U32 nextToUpdate; /* index from which to continue table update */ U32 hashLog3; /* dispatch table for matches of len==3 : larger == faster, more memory */ + + U32 rowHashLog; /* For row-based matchfinder: Hashlog based on nb of rows in the hashTable.*/ + BYTE* tagTable; /* For row-based matchFinder: A row-based table containing the hashes and head index. */ + U32 hashCache[ZSTD_ROW_HASH_CACHE_SIZE]; /* For row-based matchFinder: a cache of hashes to improve speed */ + U64 hashSalt; /* For row-based matchFinder: salts the hash for reuse of tag table */ + U32 hashSaltEntropy; /* For row-based matchFinder: collects entropy for salt generation */ + U32* hashTable; U32* hashTable3; U32* chainTable; + + U32 forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */ + + int dedicatedDictSearch; /* Indicates whether this matchState is using the + * dedicated dictionary search structure. + */ optState_t opt; /* optimal parser state */ const ZSTD_matchState_t* dictMatchState; ZSTD_compressionParameters cParams; + const rawSeqStore_t* ldmSeqStore; + + /* Controls prefetching in some dictMatchState matchfinders. + * This behavior is controlled from the cctx ms. + * This parameter has no effect in the cdict ms. */ + int prefetchCDictTables; + + /* When == 0, lazy match finders insert every position. + * When != 0, lazy match finders only insert positions they search. + * This allows them to skip much faster over incompressible data, + * at a small cost to compression ratio. + */ + int lazySkipping; }; typedef struct { @@ -159,17 +270,26 @@ typedef struct { U32 checksum; } ldmEntry_t; +typedef struct { + BYTE const* split; + U32 hash; + U32 checksum; + ldmEntry_t* bucket; +} ldmMatchCandidate_t; + +#define LDM_BATCH_SIZE 64 + typedef struct { ZSTD_window_t window; /* State for the window round buffer management */ ldmEntry_t* hashTable; U32 loadedDictEnd; BYTE* bucketOffsets; /* Next position in bucket to insert entry */ - U64 hashPower; /* Used to compute the rolling hash. - * Depends on ldmParams.minMatchLength */ + size_t splitIndices[LDM_BATCH_SIZE]; + ldmMatchCandidate_t matchCandidates[LDM_BATCH_SIZE]; } ldmState_t; typedef struct { - U32 enableLdm; /* 1 if enable long distance matching */ + ZSTD_paramSwitch_e enableLdm; /* ZSTD_ps_enable to enable LDM. ZSTD_ps_auto by default */ U32 hashLog; /* Log size of hashTable */ U32 bucketSizeLog; /* Log bucket size for collision resolution, at most 8 */ U32 minMatchLength; /* Minimum match length */ @@ -177,19 +297,6 @@ typedef struct { U32 windowLog; /* Window log for the LDM */ } ldmParams_t; -typedef struct { - U32 offset; - U32 litLength; - U32 matchLength; -} rawSeq; - -typedef struct { - rawSeq* seq; /* The start of the sequences */ - size_t pos; /* The position where reading stopped. <= size. */ - size_t size; /* The number of sequences. <= capacity. */ - size_t capacity; /* The capacity starting from `seq` pointer */ -} rawSeqStore_t; - typedef struct { int collectSequences; ZSTD_Sequence* seqStart; @@ -213,7 +320,7 @@ struct ZSTD_CCtx_params_s { * There is no guarantee that hint is close to actual source size */ ZSTD_dictAttachPref_e attachDictPref; - ZSTD_literalCompressionMode_e literalCompressionMode; + ZSTD_paramSwitch_e literalCompressionMode; /* Multithreading: used to pass parameters to mtctx */ int nbWorkers; @@ -224,17 +331,87 @@ struct ZSTD_CCtx_params_s { /* Long distance matching parameters */ ldmParams_t ldmParams; + /* Dedicated dict search algorithm trigger */ + int enableDedicatedDictSearch; + + /* Input/output buffer modes */ + ZSTD_bufferMode_e inBufferMode; + ZSTD_bufferMode_e outBufferMode; + + /* Sequence compression API */ + ZSTD_sequenceFormat_e blockDelimiters; + int validateSequences; + + /* Block splitting */ + ZSTD_paramSwitch_e useBlockSplitter; + + /* Param for deciding whether to use row-based matchfinder */ + ZSTD_paramSwitch_e useRowMatchFinder; + + /* Always load a dictionary in ext-dict mode (not prefix mode)? */ + int deterministicRefPrefix; + /* Internal use, for createCCtxParams() and freeCCtxParams() only */ ZSTD_customMem customMem; + + /* Controls prefetching in some dictMatchState matchfinders */ + ZSTD_paramSwitch_e prefetchCDictTables; + + /* Controls whether zstd will fall back to an internal matchfinder + * if the external matchfinder returns an error code. */ + int enableMatchFinderFallback; + + /* Parameters for the external sequence producer API. + * Users set these parameters through ZSTD_registerSequenceProducer(). + * It is not possible to set these parameters individually through the public API. */ + void* extSeqProdState; + ZSTD_sequenceProducer_F extSeqProdFunc; + + /* Adjust the max block size*/ + size_t maxBlockSize; + + /* Controls repcode search in external sequence parsing */ + ZSTD_paramSwitch_e searchForExternalRepcodes; }; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */ +#define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2)) +#define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE) + +/** + * Indicates whether this compression proceeds directly from user-provided + * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or + * whether the context needs to buffer the input/output (ZSTDb_buffered). + */ +typedef enum { + ZSTDb_not_buffered, + ZSTDb_buffered +} ZSTD_buffered_policy_e; + +/** + * Struct that contains all elements of block splitter that should be allocated + * in a wksp. + */ +#define ZSTD_MAX_NB_BLOCK_SPLITS 196 +typedef struct { + seqStore_t fullSeqStoreChunk; + seqStore_t firstHalfSeqStore; + seqStore_t secondHalfSeqStore; + seqStore_t currSeqStore; + seqStore_t nextSeqStore; + + U32 partitions[ZSTD_MAX_NB_BLOCK_SPLITS]; + ZSTD_entropyCTablesMetadata_t entropyMetadata; +} ZSTD_blockSplitCtx; + struct ZSTD_CCtx_s { ZSTD_compressionStage_e stage; int cParamsChanged; /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */ int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */ ZSTD_CCtx_params requestedParams; ZSTD_CCtx_params appliedParams; + ZSTD_CCtx_params simpleApiParams; /* Param storage used by the simple API - not sticky. Must only be used in top-level simple API functions for storage. */ U32 dictID; + size_t dictContentSize; ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */ size_t blockSize; @@ -243,6 +420,7 @@ struct ZSTD_CCtx_s { unsigned long long producedCSize; XXH64_state_t xxhState; ZSTD_customMem customMem; + ZSTD_threadPool* pool; size_t staticSize; SeqCollector seqCollector; int isFirstBlock; @@ -254,7 +432,10 @@ struct ZSTD_CCtx_s { size_t maxNbLdmSequences; rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */ ZSTD_blockState_t blockState; - U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */ + U32* entropyWorkspace; /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */ + + /* Whether we are streaming or not */ + ZSTD_buffered_policy_e bufferedPolicy; /* streaming */ char* inBuff; @@ -269,6 +450,11 @@ struct ZSTD_CCtx_s { ZSTD_cStreamStage streamStage; U32 frameEnded; + /* Stable in/out buffer verification */ + ZSTD_inBuffer expectedInBuffer; + size_t stableIn_notConsumed; /* nb bytes within stable input buffer that are said to be consumed but are not */ + size_t expectedOutBufferSize; + /* Dictionary */ ZSTD_localDict localDict; const ZSTD_CDict* cdict; @@ -278,17 +464,54 @@ struct ZSTD_CCtx_s { #ifdef ZSTD_MULTITHREAD ZSTDMT_CCtx* mtctx; #endif -}; -typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e; + /* Tracing */ +#if ZSTD_TRACE + ZSTD_TraceCtx traceCtx; +#endif -typedef enum { ZSTD_noDict = 0, ZSTD_extDict = 1, ZSTD_dictMatchState = 2 } ZSTD_dictMode_e; + /* Workspace for block splitter */ + ZSTD_blockSplitCtx blockSplitCtx; + + /* Buffer for output from external sequence producer */ + ZSTD_Sequence* extSeqBuf; + size_t extSeqBufCapacity; +}; +typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e; +typedef enum { ZSTD_tfp_forCCtx, ZSTD_tfp_forCDict } ZSTD_tableFillPurpose_e; + +typedef enum { + ZSTD_noDict = 0, + ZSTD_extDict = 1, + ZSTD_dictMatchState = 2, + ZSTD_dedicatedDictSearch = 3 +} ZSTD_dictMode_e; + +typedef enum { + ZSTD_cpm_noAttachDict = 0, /* Compression with ZSTD_noDict or ZSTD_extDict. + * In this mode we use both the srcSize and the dictSize + * when selecting and adjusting parameters. + */ + ZSTD_cpm_attachDict = 1, /* Compression with ZSTD_dictMatchState or ZSTD_dedicatedDictSearch. + * In this mode we only take the srcSize into account when selecting + * and adjusting parameters. + */ + ZSTD_cpm_createCDict = 2, /* Creating a CDict. + * In this mode we take both the source size and the dictionary size + * into account when selecting and adjusting the parameters. + */ + ZSTD_cpm_unknown = 3 /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams. + * We don't know what these parameters are for. We default to the legacy + * behavior of taking both the source size and the dict size into account + * when selecting and adjusting parameters. + */ +} ZSTD_cParamMode_e; typedef size_t (*ZSTD_blockCompressor) ( ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); -ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode); +ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode); MEM_STATIC U32 ZSTD_LLcode(U32 litLength) @@ -322,31 +545,6 @@ MEM_STATIC U32 ZSTD_MLcode(U32 mlBase) return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase]; } -typedef struct repcodes_s { - U32 rep[3]; -} repcodes_t; - -MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0) -{ - repcodes_t newReps; - if (offset >= ZSTD_REP_NUM) { /* full offset */ - newReps.rep[2] = rep[1]; - newReps.rep[1] = rep[0]; - newReps.rep[0] = offset - ZSTD_REP_MOVE; - } else { /* repcode */ - U32 const repCode = offset + ll0; - if (repCode > 0) { /* note : if repCode==0, no change */ - U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode]; - newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2]; - newReps.rep[1] = rep[0]; - newReps.rep[0] = currentOffset; - } else { /* repCode == 0 */ - memcpy(&newReps, rep, sizeof(newReps)); - } - } - return newReps; -} - /* ZSTD_cParam_withinBounds: * @return 1 if value is within cParam bounds, * 0 otherwise */ @@ -362,17 +560,20 @@ MEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value) /* ZSTD_noCompressBlock() : * Writes uncompressed block to dst buffer from given src. * Returns the size of the block */ -MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock) +MEM_STATIC size_t +ZSTD_noCompressBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock) { U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3); - RETURN_ERROR_IF(srcSize + ZSTDInternalConstants::ZSTD_blockHeaderSize > dstCapacity, + DEBUGLOG(5, "ZSTD_noCompressBlock (srcSize=%zu, dstCapacity=%zu)", srcSize, dstCapacity); + RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity, dstSize_tooSmall, "dst buf too small for uncompressed block"); MEM_writeLE24(dst, cBlockHeader24); - memcpy((BYTE*)dst + ZSTDInternalConstants::ZSTD_blockHeaderSize, src, srcSize); - return ZSTDInternalConstants::ZSTD_blockHeaderSize + srcSize; + ZSTD_memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize); + return ZSTD_blockHeaderSize + srcSize; } -MEM_STATIC size_t ZSTD_rleCompressBlock (void* dst, size_t dstCapacity, BYTE src, size_t srcSize, U32 lastBlock) +MEM_STATIC size_t +ZSTD_rleCompressBlock(void* dst, size_t dstCapacity, BYTE src, size_t srcSize, U32 lastBlock) { BYTE* const op = (BYTE*)dst; U32 const cBlockHeader = lastBlock + (((U32)bt_rle)<<1) + (U32)(srcSize << 3); @@ -391,21 +592,21 @@ MEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat) { U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6; ZSTD_STATIC_ASSERT(ZSTD_btultra == 8); - assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat)); + assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, (int)strat)); return (srcSize >> minlog) + 2; } -MEM_STATIC int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams) +MEM_STATIC int ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params* cctxParams) { switch (cctxParams->literalCompressionMode) { - case ZSTD_lcm_huffman: + case ZSTD_ps_enable: return 0; - case ZSTD_lcm_uncompressed: + case ZSTD_ps_disable: return 1; default: assert(0 /* impossible: pre-validated */); - /* fall-through */ - case ZSTD_lcm_auto: + ZSTD_FALLTHROUGH; + case ZSTD_ps_auto: return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0); } } @@ -415,7 +616,9 @@ MEM_STATIC int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParam * Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single * large copies. */ -static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w) { +static void +ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w) +{ assert(iend > ilimit_w); if (ip <= ilimit_w) { ZSTD_wildcopy(op, ip, ilimit_w - ip, ZSTD_no_overlap); @@ -425,14 +628,28 @@ static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const ie while (ip < iend) *op++ = *ip++; } + +#define REPCODE1_TO_OFFBASE REPCODE_TO_OFFBASE(1) +#define REPCODE2_TO_OFFBASE REPCODE_TO_OFFBASE(2) +#define REPCODE3_TO_OFFBASE REPCODE_TO_OFFBASE(3) +#define REPCODE_TO_OFFBASE(r) (assert((r)>=1), assert((r)<=ZSTD_REP_NUM), (r)) /* accepts IDs 1,2,3 */ +#define OFFSET_TO_OFFBASE(o) (assert((o)>0), o + ZSTD_REP_NUM) +#define OFFBASE_IS_OFFSET(o) ((o) > ZSTD_REP_NUM) +#define OFFBASE_IS_REPCODE(o) ( 1 <= (o) && (o) <= ZSTD_REP_NUM) +#define OFFBASE_TO_OFFSET(o) (assert(OFFBASE_IS_OFFSET(o)), (o) - ZSTD_REP_NUM) +#define OFFBASE_TO_REPCODE(o) (assert(OFFBASE_IS_REPCODE(o)), (o)) /* returns ID 1,2,3 */ + /*! ZSTD_storeSeq() : - * Store a sequence (litlen, litPtr, offCode and mlBase) into seqStore_t. - * `offCode` : distance to match + ZSTD_REP_MOVE (values <= ZSTD_REP_MOVE are repCodes). - * `mlBase` : matchLength - MINMATCH - * Allowed to overread literals up to litLimit. + * Store a sequence (litlen, litPtr, offBase and matchLength) into seqStore_t. + * @offBase : Users should employ macros REPCODE_TO_OFFBASE() and OFFSET_TO_OFFBASE(). + * @matchLength : must be >= MINMATCH + * Allowed to over-read literals up to litLimit. */ -HINT_INLINE UNUSED_ATTR -void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* literals, const BYTE* litLimit, U32 offCode, size_t mlBase) +HINT_INLINE UNUSED_ATTR void +ZSTD_storeSeq(seqStore_t* seqStorePtr, + size_t litLength, const BYTE* literals, const BYTE* litLimit, + U32 offBase, + size_t matchLength) { BYTE const* const litLimit_w = litLimit - WILDCOPY_OVERLENGTH; BYTE const* const litEnd = literals + litLength; @@ -440,8 +657,8 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera static const BYTE* g_start = NULL; if (g_start==NULL) g_start = (const BYTE*)literals; /* note : index only works for compression within a single segment */ { U32 const pos = (U32)((const BYTE*)literals - g_start); - DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offCode%7u", - pos, (U32)litLength, (U32)mlBase+MINMATCH, (U32)offCode); + DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offBase%7u", + pos, (U32)litLength, (U32)matchLength, (U32)offBase); } #endif assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq); @@ -451,9 +668,9 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera assert(literals + litLength <= litLimit); if (litEnd <= litLimit_w) { /* Common case we can use wildcopy. - * First copy 16 bytes, because literals are likely short. - */ - assert(WILDCOPY_OVERLENGTH >= 16); + * First copy 16 bytes, because literals are likely short. + */ + ZSTD_STATIC_ASSERT(WILDCOPY_OVERLENGTH >= 16); ZSTD_copy16(seqStorePtr->lit, literals); if (litLength > 16) { ZSTD_wildcopy(seqStorePtr->lit+16, literals+16, (ptrdiff_t)litLength-16, ZSTD_no_overlap); @@ -465,95 +682,70 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera /* literal Length */ if (litLength>0xFFFF) { - assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */ - seqStorePtr->longLengthID = 1; + assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */ + seqStorePtr->longLengthType = ZSTD_llt_literalLength; seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); } seqStorePtr->sequences[0].litLength = (U16)litLength; /* match offset */ - seqStorePtr->sequences[0].offset = offCode + 1; + seqStorePtr->sequences[0].offBase = offBase; /* match Length */ - if (mlBase>0xFFFF) { - assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */ - seqStorePtr->longLengthID = 2; - seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); + assert(matchLength >= MINMATCH); + { size_t const mlBase = matchLength - MINMATCH; + if (mlBase>0xFFFF) { + assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */ + seqStorePtr->longLengthType = ZSTD_llt_matchLength; + seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); + } + seqStorePtr->sequences[0].mlBase = (U16)mlBase; } - seqStorePtr->sequences[0].matchLength = (U16)mlBase; seqStorePtr->sequences++; } - -/*-************************************* -* Match length counter -***************************************/ -static unsigned ZSTD_NbCommonBytes (size_t val) +/* ZSTD_updateRep() : + * updates in-place @rep (array of repeat offsets) + * @offBase : sum-type, using numeric representation of ZSTD_storeSeq() + */ +MEM_STATIC void +ZSTD_updateRep(U32 rep[ZSTD_REP_NUM], U32 const offBase, U32 const ll0) { - if (MEM_isLittleEndian()) { - if (MEM_64bits()) { -# if defined(_MSC_VER) && defined(_WIN64) - unsigned long r = 0; - return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0; -# elif defined(__GNUC__) && (__GNUC__ >= 4) - return (__builtin_ctzll((U64)val) >> 3); -# else - static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, - 0, 3, 1, 3, 1, 4, 2, 7, - 0, 2, 3, 6, 1, 5, 3, 5, - 1, 3, 4, 4, 2, 5, 6, 7, - 7, 0, 1, 2, 3, 3, 4, 6, - 2, 6, 5, 5, 3, 4, 5, 6, - 7, 1, 2, 4, 6, 4, 4, 5, - 7, 2, 6, 5, 7, 6, 7, 7 }; - return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; -# endif - } else { /* 32 bits */ -# if defined(_MSC_VER) - unsigned long r=0; - return _BitScanForward( &r, (U32)val ) ? (unsigned)(r >> 3) : 0; -# elif defined(__GNUC__) && (__GNUC__ >= 3) - return (__builtin_ctz((U32)val) >> 3); -# else - static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, - 3, 2, 2, 1, 3, 2, 0, 1, - 3, 3, 1, 2, 2, 2, 2, 0, - 3, 1, 2, 0, 1, 0, 1, 1 }; - return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; -# endif + if (OFFBASE_IS_OFFSET(offBase)) { /* full offset */ + rep[2] = rep[1]; + rep[1] = rep[0]; + rep[0] = OFFBASE_TO_OFFSET(offBase); + } else { /* repcode */ + U32 const repCode = OFFBASE_TO_REPCODE(offBase) - 1 + ll0; + if (repCode > 0) { /* note : if repCode==0, no change */ + U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode]; + rep[2] = (repCode >= 2) ? rep[1] : rep[2]; + rep[1] = rep[0]; + rep[0] = currentOffset; + } else { /* repCode == 0 */ + /* nothing to do */ } - } else { /* Big Endian CPU */ - if (MEM_64bits()) { -# if defined(_MSC_VER) && defined(_WIN64) - unsigned long r = 0; - return _BitScanReverse64( &r, val ) ? (unsigned)(r >> 3) : 0; -# elif defined(__GNUC__) && (__GNUC__ >= 4) - return (__builtin_clzll(val) >> 3); -# else - unsigned r; - const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */ - if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; } - if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } - r += (!val); - return r; -# endif - } else { /* 32 bits */ -# if defined(_MSC_VER) - unsigned long r = 0; - return _BitScanReverse( &r, (unsigned long)val ) ? (unsigned)(r >> 3) : 0; -# elif defined(__GNUC__) && (__GNUC__ >= 3) - return (__builtin_clz((U32)val) >> 3); -# else - unsigned r; - if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } - r += (!val); - return r; -# endif - } } + } +} + +typedef struct repcodes_s { + U32 rep[3]; +} repcodes_t; + +MEM_STATIC repcodes_t +ZSTD_newRep(U32 const rep[ZSTD_REP_NUM], U32 const offBase, U32 const ll0) +{ + repcodes_t newReps; + ZSTD_memcpy(&newReps, rep, sizeof(newReps)); + ZSTD_updateRep(newReps.rep, offBase, ll0); + return newReps; } +/*-************************************* +* Match length counter +***************************************/ MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit) { const BYTE* const pStart = pIn; @@ -599,31 +791,43 @@ ZSTD_count_2segments(const BYTE* ip, const BYTE* match, * Hashes ***************************************/ static const U32 prime3bytes = 506832829U; -static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; } -MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */ +static U32 ZSTD_hash3(U32 u, U32 h, U32 s) { assert(h <= 32); return (((u << (32-24)) * prime3bytes) ^ s) >> (32-h) ; } +MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h, 0); } /* only in zstd_opt.h */ +MEM_STATIC size_t ZSTD_hash3PtrS(const void* ptr, U32 h, U32 s) { return ZSTD_hash3(MEM_readLE32(ptr), h, s); } static const U32 prime4bytes = 2654435761U; -static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; } -static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); } +static U32 ZSTD_hash4(U32 u, U32 h, U32 s) { assert(h <= 32); return ((u * prime4bytes) ^ s) >> (32-h) ; } +static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_readLE32(ptr), h, 0); } +static size_t ZSTD_hash4PtrS(const void* ptr, U32 h, U32 s) { return ZSTD_hash4(MEM_readLE32(ptr), h, s); } static const U64 prime5bytes = 889523592379ULL; -static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64-40)) * prime5bytes) >> (64-h)) ; } -static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); } +static size_t ZSTD_hash5(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u << (64-40)) * prime5bytes) ^ s) >> (64-h)) ; } +static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h, 0); } +static size_t ZSTD_hash5PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash5(MEM_readLE64(p), h, s); } static const U64 prime6bytes = 227718039650203ULL; -static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; } -static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); } +static size_t ZSTD_hash6(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u << (64-48)) * prime6bytes) ^ s) >> (64-h)) ; } +static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h, 0); } +static size_t ZSTD_hash6PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash6(MEM_readLE64(p), h, s); } static const U64 prime7bytes = 58295818150454627ULL; -static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; } -static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); } +static size_t ZSTD_hash7(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u << (64-56)) * prime7bytes) ^ s) >> (64-h)) ; } +static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h, 0); } +static size_t ZSTD_hash7PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash7(MEM_readLE64(p), h, s); } static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL; -static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; } -static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); } +static size_t ZSTD_hash8(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u) * prime8bytes) ^ s) >> (64-h)) ; } +static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h, 0); } +static size_t ZSTD_hash8PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash8(MEM_readLE64(p), h, s); } -MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls) + +MEM_STATIC FORCE_INLINE_ATTR +size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls) { + /* Although some of these hashes do support hBits up to 64, some do not. + * To be on the safe side, always avoid hBits > 32. */ + assert(hBits <= 32); + switch(mls) { default: @@ -635,6 +839,24 @@ MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls) } } +MEM_STATIC FORCE_INLINE_ATTR +size_t ZSTD_hashPtrSalted(const void* p, U32 hBits, U32 mls, const U64 hashSalt) { + /* Although some of these hashes do support hBits up to 64, some do not. + * To be on the safe side, always avoid hBits > 32. */ + assert(hBits <= 32); + + switch(mls) + { + default: + case 4: return ZSTD_hash4PtrS(p, hBits, (U32)hashSalt); + case 5: return ZSTD_hash5PtrS(p, hBits, hashSalt); + case 6: return ZSTD_hash6PtrS(p, hBits, hashSalt); + case 7: return ZSTD_hash7PtrS(p, hBits, hashSalt); + case 8: return ZSTD_hash8PtrS(p, hBits, hashSalt); + } +} + + /** ZSTD_ipow() : * Return base^exponent. */ @@ -719,6 +941,13 @@ MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window) window->dictLimit = end; } +MEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window) +{ + return window.dictLimit == ZSTD_WINDOW_START_INDEX && + window.lowLimit == ZSTD_WINDOW_START_INDEX && + (window.nextSrc - window.base) == ZSTD_WINDOW_START_INDEX; +} + /** * ZSTD_window_hasExtDict(): * Returns non-zero if the window has a non-empty extDict. @@ -738,20 +967,76 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms) return ZSTD_window_hasExtDict(ms->window) ? ZSTD_extDict : ms->dictMatchState != NULL ? - ZSTD_dictMatchState : + (ms->dictMatchState->dedicatedDictSearch ? ZSTD_dedicatedDictSearch : ZSTD_dictMatchState) : ZSTD_noDict; } +/* Defining this macro to non-zero tells zstd to run the overflow correction + * code much more frequently. This is very inefficient, and should only be + * used for tests and fuzzers. + */ +#ifndef ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY +# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +# define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 1 +# else +# define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 0 +# endif +#endif + +/** + * ZSTD_window_canOverflowCorrect(): + * Returns non-zero if the indices are large enough for overflow correction + * to work correctly without impacting compression ratio. + */ +MEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window, + U32 cycleLog, + U32 maxDist, + U32 loadedDictEnd, + void const* src) +{ + U32 const cycleSize = 1u << cycleLog; + U32 const curr = (U32)((BYTE const*)src - window.base); + U32 const minIndexToOverflowCorrect = cycleSize + + MAX(maxDist, cycleSize) + + ZSTD_WINDOW_START_INDEX; + + /* Adjust the min index to backoff the overflow correction frequency, + * so we don't waste too much CPU in overflow correction. If this + * computation overflows we don't really care, we just need to make + * sure it is at least minIndexToOverflowCorrect. + */ + U32 const adjustment = window.nbOverflowCorrections + 1; + U32 const adjustedIndex = MAX(minIndexToOverflowCorrect * adjustment, + minIndexToOverflowCorrect); + U32 const indexLargeEnough = curr > adjustedIndex; + + /* Only overflow correct early if the dictionary is invalidated already, + * so we don't hurt compression ratio. + */ + U32 const dictionaryInvalidated = curr > maxDist + loadedDictEnd; + + return indexLargeEnough && dictionaryInvalidated; +} + /** * ZSTD_window_needOverflowCorrection(): * Returns non-zero if the indices are getting too large and need overflow * protection. */ MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window, + U32 cycleLog, + U32 maxDist, + U32 loadedDictEnd, + void const* src, void const* srcEnd) { - U32 const current = (U32)((BYTE const*)srcEnd - window.base); - return current > ZSTD_CURRENT_MAX; + U32 const curr = (U32)((BYTE const*)srcEnd - window.base); + if (ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) { + if (ZSTD_window_canOverflowCorrect(window, cycleLog, maxDist, loadedDictEnd, src)) { + return 1; + } + } + return curr > ZSTD_CURRENT_MAX; } /** @@ -762,9 +1047,10 @@ MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window, * * The least significant cycleLog bits of the indices must remain the same, * which may be 0. Every index up to maxDist in the past must be valid. - * NOTE: (maxDist & cycleMask) must be zero. */ -MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, +MEM_STATIC +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, U32 maxDist, void const* src) { /* preemptive overflow correction: @@ -786,32 +1072,52 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, * 3. (cctx->lowLimit + 1< 3<<29 + 1<base); - U32 const currentCycle0 = current & cycleMask; - /* Exclude zero so that newCurrent - maxDist >= 1. */ - U32 const currentCycle1 = currentCycle0 == 0 ? (1U << cycleLog) : currentCycle0; - U32 const newCurrent = currentCycle1 + maxDist; - U32 const correction = current - newCurrent; - assert((maxDist & cycleMask) == 0); - assert(current > newCurrent); - /* Loose bound, should be around 1<<29 (see above) */ - assert(correction > 1<<28); + U32 const cycleSize = 1u << cycleLog; + U32 const cycleMask = cycleSize - 1; + U32 const curr = (U32)((BYTE const*)src - window->base); + U32 const currentCycle = curr & cycleMask; + /* Ensure newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX. */ + U32 const currentCycleCorrection = currentCycle < ZSTD_WINDOW_START_INDEX + ? MAX(cycleSize, ZSTD_WINDOW_START_INDEX) + : 0; + U32 const newCurrent = currentCycle + + currentCycleCorrection + + MAX(maxDist, cycleSize); + U32 const correction = curr - newCurrent; + /* maxDist must be a power of two so that: + * (newCurrent & cycleMask) == (curr & cycleMask) + * This is required to not corrupt the chains / binary tree. + */ + assert((maxDist & (maxDist - 1)) == 0); + assert((curr & cycleMask) == (newCurrent & cycleMask)); + assert(curr > newCurrent); + if (!ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) { + /* Loose bound, should be around 1<<29 (see above) */ + assert(correction > 1<<28); + } window->base += correction; window->dictBase += correction; - if (window->lowLimit <= correction) window->lowLimit = 1; - else window->lowLimit -= correction; - if (window->dictLimit <= correction) window->dictLimit = 1; - else window->dictLimit -= correction; + if (window->lowLimit < correction + ZSTD_WINDOW_START_INDEX) { + window->lowLimit = ZSTD_WINDOW_START_INDEX; + } else { + window->lowLimit -= correction; + } + if (window->dictLimit < correction + ZSTD_WINDOW_START_INDEX) { + window->dictLimit = ZSTD_WINDOW_START_INDEX; + } else { + window->dictLimit -= correction; + } /* Ensure we can still reference the full window. */ assert(newCurrent >= maxDist); - assert(newCurrent - maxDist >= 1); + assert(newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX); /* Ensure that lowLimit and dictLimit didn't underflow. */ assert(window->lowLimit <= newCurrent); assert(window->dictLimit <= newCurrent); + ++window->nbOverflowCorrections; + DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction, window->lowLimit); return correction; @@ -900,10 +1206,15 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window, (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd); assert(blockEndIdx >= loadedDictEnd); - if (blockEndIdx > loadedDictEnd + maxDist) { + if (blockEndIdx > loadedDictEnd + maxDist || loadedDictEnd != window->dictLimit) { /* On reaching window size, dictionaries are invalidated. * For simplification, if window size is reached anywhere within next block, * the dictionary is invalidated for the full block. + * + * We also have to invalidate the dictionary if ZSTD_window_update() has detected + * non-contiguous segments, which means that loadedDictEnd != window->dictLimit. + * loadedDictEnd may be 0, if forceWindow is true, but in that case we never use + * dictMatchState, so setting it to NULL is not a problem. */ DEBUGLOG(6, "invalidating dictionary for current block (distance > windowSize)"); *loadedDictEndPtr = 0; @@ -915,12 +1226,14 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window, } MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) { - memset(window, 0, sizeof(*window)); - window->base = (BYTE const*)""; - window->dictBase = (BYTE const*)""; - window->dictLimit = 1; /* start from 1, so that 1st position is valid */ - window->lowLimit = 1; /* it ensures first and later CCtx usages compress the same */ - window->nextSrc = window->base + 1; /* see issue #1241 */ + ZSTD_memset(window, 0, sizeof(*window)); + window->base = (BYTE const*)" "; + window->dictBase = (BYTE const*)" "; + ZSTD_STATIC_ASSERT(ZSTD_DUBT_UNSORTED_MARK < ZSTD_WINDOW_START_INDEX); /* Start above ZSTD_DUBT_UNSORTED_MARK */ + window->dictLimit = ZSTD_WINDOW_START_INDEX; /* start from >0, so that 1st position is valid */ + window->lowLimit = ZSTD_WINDOW_START_INDEX; /* it ensures first and later CCtx usages compress the same */ + window->nextSrc = window->base + ZSTD_WINDOW_START_INDEX; /* see issue #1241 */ + window->nbOverflowCorrections = 0; } /** @@ -930,8 +1243,11 @@ MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) { * forget about the extDict. Handles overlap of the prefix and extDict. * Returns non-zero if the segment is contiguous. */ -MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window, - void const* src, size_t srcSize) +MEM_STATIC +ZSTD_ALLOW_POINTER_OVERFLOW_ATTR +U32 ZSTD_window_update(ZSTD_window_t* window, + void const* src, size_t srcSize, + int forceNonContiguous) { BYTE const* const ip = (BYTE const*)src; U32 contiguous = 1; @@ -941,7 +1257,7 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window, assert(window->base != NULL); assert(window->dictBase != NULL); /* Check if blocks follow each other */ - if (src != window->nextSrc) { + if (src != window->nextSrc || forceNonContiguous) { /* not contiguous */ size_t const distanceFromBase = (size_t)(window->nextSrc - window->base); DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit); @@ -969,25 +1285,32 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window, /** * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix. */ -MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 current, unsigned windowLog) +MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog) { - U32 const maxDistance = 1U << windowLog; - U32 const lowestValid = ms->window.lowLimit; - U32 const withinWindow = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid; - U32 const isDictionary = (ms->loadedDictEnd != 0); - U32 const matchLowest = isDictionary ? lowestValid : withinWindow; + U32 const maxDistance = 1U << windowLog; + U32 const lowestValid = ms->window.lowLimit; + U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; + U32 const isDictionary = (ms->loadedDictEnd != 0); + /* When using a dictionary the entire dictionary is valid if a single byte of the dictionary + * is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't + * valid for the entire block. So this check is sufficient to find the lowest valid match index. + */ + U32 const matchLowest = isDictionary ? lowestValid : withinWindow; return matchLowest; } /** * Returns the lowest allowed match index in the prefix. */ -MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 current, unsigned windowLog) +MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog) { U32 const maxDistance = 1U << windowLog; U32 const lowestValid = ms->window.dictLimit; - U32 const withinWindow = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid; + U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); + /* When computing the lowest prefix index we need to take the dictionary into account to handle + * the edge case where the dictionary and the source are contiguous in memory. + */ U32 const matchLowest = isDictionary ? lowestValid : withinWindow; return matchLowest; } @@ -1025,6 +1348,47 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max) #endif +/* Short Cache */ + +/* Normally, zstd matchfinders follow this flow: + * 1. Compute hash at ip + * 2. Load index from hashTable[hash] + * 3. Check if *ip == *(base + index) + * In dictionary compression, loading *(base + index) is often an L2 or even L3 miss. + * + * Short cache is an optimization which allows us to avoid step 3 most of the time + * when the data doesn't actually match. With short cache, the flow becomes: + * 1. Compute (hash, currentTag) at ip. currentTag is an 8-bit independent hash at ip. + * 2. Load (index, matchTag) from hashTable[hash]. See ZSTD_writeTaggedIndex to understand how this works. + * 3. Only if currentTag == matchTag, check *ip == *(base + index). Otherwise, continue. + * + * Currently, short cache is only implemented in CDict hashtables. Thus, its use is limited to + * dictMatchState matchfinders. + */ +#define ZSTD_SHORT_CACHE_TAG_BITS 8 +#define ZSTD_SHORT_CACHE_TAG_MASK ((1u << ZSTD_SHORT_CACHE_TAG_BITS) - 1) + +/* Helper function for ZSTD_fillHashTable and ZSTD_fillDoubleHashTable. + * Unpacks hashAndTag into (hash, tag), then packs (index, tag) into hashTable[hash]. */ +MEM_STATIC void ZSTD_writeTaggedIndex(U32* const hashTable, size_t hashAndTag, U32 index) { + size_t const hash = hashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS; + U32 const tag = (U32)(hashAndTag & ZSTD_SHORT_CACHE_TAG_MASK); + assert(index >> (32 - ZSTD_SHORT_CACHE_TAG_BITS) == 0); + hashTable[hash] = (index << ZSTD_SHORT_CACHE_TAG_BITS) | tag; +} + +/* Helper function for short cache matchfinders. + * Unpacks tag1 and tag2 from lower bits of packedTag1 and packedTag2, then checks if the tags match. */ +MEM_STATIC int ZSTD_comparePackedTags(size_t packedTag1, size_t packedTag2) { + U32 const tag1 = packedTag1 & ZSTD_SHORT_CACHE_TAG_MASK; + U32 const tag2 = packedTag2 & ZSTD_SHORT_CACHE_TAG_MASK; + return tag1 == tag2; +} + +#if defined (__cplusplus) +} +#endif + /* =============================================================== * Shared internal declarations * These prototypes may be called from sources not in lib/compress @@ -1036,7 +1400,6 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max) * assumptions : magic number supposed already checked * and dictSize >= 8 */ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, - short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize); void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs); @@ -1052,7 +1415,7 @@ void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs); * Note: srcSizeHint == 0 means 0! */ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( - const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize); + const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode); /*! ZSTD_initCStream_internal() : * Private use only. Init streaming operation. @@ -1103,16 +1466,69 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity); * This cannot be used when long range matching is enabled. * Zstd will use these sequences, and pass the literals to a secondary block * compressor. - * @return : An error code on failure. * NOTE: seqs are not verified! Invalid sequences can cause out-of-bounds memory * access and data corruption. */ -size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq); +void ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq); /** ZSTD_cycleLog() : * condition for correct operation : hashLog > 1 */ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat); +/** ZSTD_CCtx_trace() : + * Trace the end of a compression call. + */ +void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize); + +/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of + * ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter. + * Note that the block delimiter must include the last literals of the block. + */ +size_t +ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, + ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); + +/* Returns the number of bytes to move the current read position back by. + * Only non-zero if we ended up splitting a sequence. + * Otherwise, it may return a ZSTD error if something went wrong. + * + * This function will attempt to scan through blockSize bytes + * represented by the sequences in @inSeqs, + * storing any (partial) sequences. + * + * Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to + * avoid splitting a match, or to avoid splitting a match such that it would produce a match + * smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block. + */ +size_t +ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch); + +/* Returns 1 if an external sequence producer is registered, otherwise returns 0. */ +MEM_STATIC int ZSTD_hasExtSeqProd(const ZSTD_CCtx_params* params) { + return params->extSeqProdFunc != NULL; } +/* =============================================================== + * Deprecated definitions that are still used internally to avoid + * deprecation warnings. These functions are exactly equivalent to + * their public variants, but avoid the deprecation warnings. + * =============================================================== */ + +size_t ZSTD_compressBegin_usingCDict_deprecated(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); + +size_t ZSTD_compressContinue_public(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + +size_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + +size_t ZSTD_compressBlock_deprecated(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + + #endif /* ZSTD_COMPRESS_H */ diff --git a/third_party/zstd/include/zstd/compress/zstd_compress_literals.h b/third_party/zstd/include/zstd/include/compress/zstd_compress_literals.h similarity index 57% rename from third_party/zstd/include/zstd/compress/zstd_compress_literals.h rename to third_party/zstd/include/zstd/include/compress/zstd_compress_literals.h index 7082db5226e..b060c8ad218 100644 --- a/third_party/zstd/include/zstd/compress/zstd_compress_literals.h +++ b/third_party/zstd/include/zstd/include/compress/zstd_compress_literals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,22 +11,29 @@ #ifndef ZSTD_COMPRESS_LITERALS_H #define ZSTD_COMPRESS_LITERALS_H -#include "zstd/compress/zstd_compress_internal.h" /* ZSTD_hufCTables_t, ZSTD_minGain() */ +#include "zstd_compress_internal.h" /* ZSTD_hufCTables_t, ZSTD_minGain() */ -namespace duckdb_zstd { size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize); +/* ZSTD_compressRleLiteralsBlock() : + * Conditions : + * - All bytes in @src are identical + * - dstCapacity >= 4 */ size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize); -size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf, - ZSTD_hufCTables_t* nextHuf, - ZSTD_strategy strategy, int disableLiteralCompression, - void* dst, size_t dstCapacity, +/* ZSTD_compressLiterals(): + * @entropyWorkspace: must be aligned on 4-bytes boundaries + * @entropyWorkspaceSize : must be >= HUF_WORKSPACE_SIZE + * @suspectUncompressible: sampling checks, to potentially skip huffman coding + */ +size_t ZSTD_compressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize, void* entropyWorkspace, size_t entropyWorkspaceSize, - const int bmi2); - -} + const ZSTD_hufCTables_t* prevHuf, + ZSTD_hufCTables_t* nextHuf, + ZSTD_strategy strategy, int disableLiteralCompression, + int suspectUncompressible, + int bmi2); #endif /* ZSTD_COMPRESS_LITERALS_H */ diff --git a/third_party/zstd/include/zstd/compress/zstd_compress_sequences.h b/third_party/zstd/include/zstd/include/compress/zstd_compress_sequences.h similarity index 89% rename from third_party/zstd/include/zstd/compress/zstd_compress_sequences.h rename to third_party/zstd/include/zstd/include/compress/zstd_compress_sequences.h index 63e27ea6301..4a3a05da948 100644 --- a/third_party/zstd/include/zstd/compress/zstd_compress_sequences.h +++ b/third_party/zstd/include/zstd/include/compress/zstd_compress_sequences.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,10 +11,8 @@ #ifndef ZSTD_COMPRESS_SEQUENCES_H #define ZSTD_COMPRESS_SEQUENCES_H -#include "zstd/common/fse.h" /* FSE_repeat, FSE_CTable */ -#include "zstd/common/zstd_internal.h" /* symbolEncodingType_e, ZSTD_strategy */ - -namespace duckdb_zstd { +#include "../common/fse.h" /* FSE_repeat, FSE_CTable */ +#include "../common/zstd_internal.h" /* symbolEncodingType_e, ZSTD_strategy */ typedef enum { ZSTD_defaultDisallowed = 0, @@ -53,7 +51,4 @@ size_t ZSTD_fseBitCost( size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog, unsigned const* count, unsigned const max); - -} - #endif /* ZSTD_COMPRESS_SEQUENCES_H */ diff --git a/third_party/zstd/include/zstd/compress/zstd_compress_superblock.h b/third_party/zstd/include/zstd/include/compress/zstd_compress_superblock.h similarity index 90% rename from third_party/zstd/include/zstd/compress/zstd_compress_superblock.h rename to third_party/zstd/include/zstd/include/compress/zstd_compress_superblock.h index df4055036d6..8e494f0d5e6 100644 --- a/third_party/zstd/include/zstd/compress/zstd_compress_superblock.h +++ b/third_party/zstd/include/zstd/include/compress/zstd_compress_superblock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -15,9 +15,8 @@ * Dependencies ***************************************/ -#include "zstd.h" /* ZSTD_CCtx */ +#include "../zstd.h" /* ZSTD_CCtx */ -namespace duckdb_zstd { /*-************************************* * Target Compressed Block Size ***************************************/ @@ -29,7 +28,5 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, void const* src, size_t srcSize, unsigned lastBlock); -} - #endif /* ZSTD_COMPRESS_ADVANCED_H */ diff --git a/third_party/zstd/include/zstd/include/compress/zstd_cwksp.h b/third_party/zstd/include/zstd/include/compress/zstd_cwksp.h new file mode 100644 index 00000000000..3eddbd334e8 --- /dev/null +++ b/third_party/zstd/include/zstd/include/compress/zstd_cwksp.h @@ -0,0 +1,748 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_CWKSP_H +#define ZSTD_CWKSP_H + +/*-************************************* +* Dependencies +***************************************/ +#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customFree */ +#include "../common/zstd_internal.h" +#include "../common/portability_macros.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +/*-************************************* +* Constants +***************************************/ + +/* Since the workspace is effectively its own little malloc implementation / + * arena, when we run under ASAN, we should similarly insert redzones between + * each internal element of the workspace, so ASAN will catch overruns that + * reach outside an object but that stay inside the workspace. + * + * This defines the size of that redzone. + */ +#ifndef ZSTD_CWKSP_ASAN_REDZONE_SIZE +#define ZSTD_CWKSP_ASAN_REDZONE_SIZE 128 +#endif + + +/* Set our tables and aligneds to align by 64 bytes */ +#define ZSTD_CWKSP_ALIGNMENT_BYTES 64 + +/*-************************************* +* Structures +***************************************/ +typedef enum { + ZSTD_cwksp_alloc_objects, + ZSTD_cwksp_alloc_aligned_init_once, + ZSTD_cwksp_alloc_aligned, + ZSTD_cwksp_alloc_buffers +} ZSTD_cwksp_alloc_phase_e; + +/** + * Used to describe whether the workspace is statically allocated (and will not + * necessarily ever be freed), or if it's dynamically allocated and we can + * expect a well-formed caller to free this. + */ +typedef enum { + ZSTD_cwksp_dynamic_alloc, + ZSTD_cwksp_static_alloc +} ZSTD_cwksp_static_alloc_e; + +/** + * Zstd fits all its internal datastructures into a single continuous buffer, + * so that it only needs to perform a single OS allocation (or so that a buffer + * can be provided to it and it can perform no allocations at all). This buffer + * is called the workspace. + * + * Several optimizations complicate that process of allocating memory ranges + * from this workspace for each internal datastructure: + * + * - These different internal datastructures have different setup requirements: + * + * - The static objects need to be cleared once and can then be trivially + * reused for each compression. + * + * - Various buffers don't need to be initialized at all--they are always + * written into before they're read. + * + * - The matchstate tables have a unique requirement that they don't need + * their memory to be totally cleared, but they do need the memory to have + * some bound, i.e., a guarantee that all values in the memory they've been + * allocated is less than some maximum value (which is the starting value + * for the indices that they will then use for compression). When this + * guarantee is provided to them, they can use the memory without any setup + * work. When it can't, they have to clear the area. + * + * - These buffers also have different alignment requirements. + * + * - We would like to reuse the objects in the workspace for multiple + * compressions without having to perform any expensive reallocation or + * reinitialization work. + * + * - We would like to be able to efficiently reuse the workspace across + * multiple compressions **even when the compression parameters change** and + * we need to resize some of the objects (where possible). + * + * To attempt to manage this buffer, given these constraints, the ZSTD_cwksp + * abstraction was created. It works as follows: + * + * Workspace Layout: + * + * [ ... workspace ... ] + * [objects][tables ->] free space [<- buffers][<- aligned][<- init once] + * + * The various objects that live in the workspace are divided into the + * following categories, and are allocated separately: + * + * - Static objects: this is optionally the enclosing ZSTD_CCtx or ZSTD_CDict, + * so that literally everything fits in a single buffer. Note: if present, + * this must be the first object in the workspace, since ZSTD_customFree{CCtx, + * CDict}() rely on a pointer comparison to see whether one or two frees are + * required. + * + * - Fixed size objects: these are fixed-size, fixed-count objects that are + * nonetheless "dynamically" allocated in the workspace so that we can + * control how they're initialized separately from the broader ZSTD_CCtx. + * Examples: + * - Entropy Workspace + * - 2 x ZSTD_compressedBlockState_t + * - CDict dictionary contents + * + * - Tables: these are any of several different datastructures (hash tables, + * chain tables, binary trees) that all respect a common format: they are + * uint32_t arrays, all of whose values are between 0 and (nextSrc - base). + * Their sizes depend on the cparams. These tables are 64-byte aligned. + * + * - Init once: these buffers require to be initialized at least once before + * use. They should be used when we want to skip memory initialization + * while not triggering memory checkers (like Valgrind) when reading from + * from this memory without writing to it first. + * These buffers should be used carefully as they might contain data + * from previous compressions. + * Buffers are aligned to 64 bytes. + * + * - Aligned: these buffers don't require any initialization before they're + * used. The user of the buffer should make sure they write into a buffer + * location before reading from it. + * Buffers are aligned to 64 bytes. + * + * - Buffers: these buffers are used for various purposes that don't require + * any alignment or initialization before they're used. This means they can + * be moved around at no cost for a new compression. + * + * Allocating Memory: + * + * The various types of objects must be allocated in order, so they can be + * correctly packed into the workspace buffer. That order is: + * + * 1. Objects + * 2. Init once / Tables + * 3. Aligned / Tables + * 4. Buffers / Tables + * + * Attempts to reserve objects of different types out of order will fail. + */ +typedef struct { + void* workspace; + void* workspaceEnd; + + void* objectEnd; + void* tableEnd; + void* tableValidEnd; + void* allocStart; + void* initOnceStart; + + BYTE allocFailed; + int workspaceOversizedDuration; + ZSTD_cwksp_alloc_phase_e phase; + ZSTD_cwksp_static_alloc_e isStatic; +} ZSTD_cwksp; + +/*-************************************* +* Functions +***************************************/ + +MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws); +MEM_STATIC void* ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws); + +MEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) { + (void)ws; + assert(ws->workspace <= ws->objectEnd); + assert(ws->objectEnd <= ws->tableEnd); + assert(ws->objectEnd <= ws->tableValidEnd); + assert(ws->tableEnd <= ws->allocStart); + assert(ws->tableValidEnd <= ws->allocStart); + assert(ws->allocStart <= ws->workspaceEnd); + assert(ws->initOnceStart <= ZSTD_cwksp_initialAllocStart(ws)); + assert(ws->workspace <= ws->initOnceStart); +#if ZSTD_MEMORY_SANITIZER + { + intptr_t const offset = __msan_test_shadow(ws->initOnceStart, + (U8*)ZSTD_cwksp_initialAllocStart(ws) - (U8*)ws->initOnceStart); + (void)offset; +#if defined(ZSTD_MSAN_PRINT) + if(offset!=-1) { + __msan_print_shadow((U8*)ws->initOnceStart + offset - 8, 32); + } +#endif + assert(offset==-1); + }; +#endif +} + +/** + * Align must be a power of 2. + */ +MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) { + size_t const mask = align - 1; + assert((align & mask) == 0); + return (size + mask) & ~mask; +} + +/** + * Use this to determine how much space in the workspace we will consume to + * allocate this object. (Normally it should be exactly the size of the object, + * but under special conditions, like ASAN, where we pad each object, it might + * be larger.) + * + * Since tables aren't currently redzoned, you don't need to call through this + * to figure out how much space you need for the matchState tables. Everything + * else is though. + * + * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned_alloc_size(). + */ +MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) { + if (size == 0) + return 0; +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + return size + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; +#else + return size; +#endif +} + +/** + * Returns an adjusted alloc size that is the nearest larger multiple of 64 bytes. + * Used to determine the number of bytes required for a given "aligned". + */ +MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size) { + return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, ZSTD_CWKSP_ALIGNMENT_BYTES)); +} + +/** + * Returns the amount of additional space the cwksp must allocate + * for internal purposes (currently only alignment). + */ +MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) { + /* For alignment, the wksp will always allocate an additional 2*ZSTD_CWKSP_ALIGNMENT_BYTES + * bytes to align the beginning of tables section and end of buffers; + */ + size_t const slackSpace = ZSTD_CWKSP_ALIGNMENT_BYTES * 2; + return slackSpace; +} + + +/** + * Return the number of additional bytes required to align a pointer to the given number of bytes. + * alignBytes must be a power of two. + */ +MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) { + size_t const alignBytesMask = alignBytes - 1; + size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask; + assert((alignBytes & alignBytesMask) == 0); + assert(bytes < alignBytes); + return bytes; +} + +/** + * Returns the initial value for allocStart which is used to determine the position from + * which we can allocate from the end of the workspace. + */ +MEM_STATIC void* ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws) { + return (void*)((size_t)ws->workspaceEnd & ~(ZSTD_CWKSP_ALIGNMENT_BYTES-1)); +} + +/** + * Internal function. Do not use directly. + * Reserves the given number of bytes within the aligned/buffer segment of the wksp, + * which counts from the end of the wksp (as opposed to the object/table segment). + * + * Returns a pointer to the beginning of that space. + */ +MEM_STATIC void* +ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes) +{ + void* const alloc = (BYTE*)ws->allocStart - bytes; + void* const bottom = ws->tableEnd; + DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining", + alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes); + ZSTD_cwksp_assert_internal_consistency(ws); + assert(alloc >= bottom); + if (alloc < bottom) { + DEBUGLOG(4, "cwksp: alloc failed!"); + ws->allocFailed = 1; + return NULL; + } + /* the area is reserved from the end of wksp. + * If it overlaps with tableValidEnd, it voids guarantees on values' range */ + if (alloc < ws->tableValidEnd) { + ws->tableValidEnd = alloc; + } + ws->allocStart = alloc; + return alloc; +} + +/** + * Moves the cwksp to the next phase, and does any necessary allocations. + * cwksp initialization must necessarily go through each phase in order. + * Returns a 0 on success, or zstd error + */ +MEM_STATIC size_t +ZSTD_cwksp_internal_advance_phase(ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase) +{ + assert(phase >= ws->phase); + if (phase > ws->phase) { + /* Going from allocating objects to allocating initOnce / tables */ + if (ws->phase < ZSTD_cwksp_alloc_aligned_init_once && + phase >= ZSTD_cwksp_alloc_aligned_init_once) { + ws->tableValidEnd = ws->objectEnd; + ws->initOnceStart = ZSTD_cwksp_initialAllocStart(ws); + + { /* Align the start of the tables to 64 bytes. Use [0, 63] bytes */ + void *const alloc = ws->objectEnd; + size_t const bytesToAlign = ZSTD_cwksp_bytes_to_align_ptr(alloc, ZSTD_CWKSP_ALIGNMENT_BYTES); + void *const objectEnd = (BYTE *) alloc + bytesToAlign; + DEBUGLOG(5, "reserving table alignment addtl space: %zu", bytesToAlign); + RETURN_ERROR_IF(objectEnd > ws->workspaceEnd, memory_allocation, + "table phase - alignment initial allocation failed!"); + ws->objectEnd = objectEnd; + ws->tableEnd = objectEnd; /* table area starts being empty */ + if (ws->tableValidEnd < ws->tableEnd) { + ws->tableValidEnd = ws->tableEnd; + } + } + } + ws->phase = phase; + ZSTD_cwksp_assert_internal_consistency(ws); + } + return 0; +} + +/** + * Returns whether this object/buffer/etc was allocated in this workspace. + */ +MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr) +{ + return (ptr != NULL) && (ws->workspace <= ptr) && (ptr < ws->workspaceEnd); +} + +/** + * Internal function. Do not use directly. + */ +MEM_STATIC void* +ZSTD_cwksp_reserve_internal(ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase) +{ + void* alloc; + if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase)) || bytes == 0) { + return NULL; + } + +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + /* over-reserve space */ + bytes += 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; +#endif + + alloc = ZSTD_cwksp_reserve_internal_buffer_space(ws, bytes); + +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on + * either size. */ + if (alloc) { + alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE; + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + /* We need to keep the redzone poisoned while unpoisoning the bytes that + * are actually allocated. */ + __asan_unpoison_memory_region(alloc, bytes - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE); + } + } +#endif + + return alloc; +} + +/** + * Reserves and returns unaligned memory. + */ +MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes) +{ + return (BYTE*)ZSTD_cwksp_reserve_internal(ws, bytes, ZSTD_cwksp_alloc_buffers); +} + +/** + * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes). + * This memory has been initialized at least once in the past. + * This doesn't mean it has been initialized this time, and it might contain data from previous + * operations. + * The main usage is for algorithms that might need read access into uninitialized memory. + * The algorithm must maintain safety under these conditions and must make sure it doesn't + * leak any of the past data (directly or in side channels). + */ +MEM_STATIC void* ZSTD_cwksp_reserve_aligned_init_once(ZSTD_cwksp* ws, size_t bytes) +{ + size_t const alignedBytes = ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES); + void* ptr = ZSTD_cwksp_reserve_internal(ws, alignedBytes, ZSTD_cwksp_alloc_aligned_init_once); + assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); + if(ptr && ptr < ws->initOnceStart) { + /* We assume the memory following the current allocation is either: + * 1. Not usable as initOnce memory (end of workspace) + * 2. Another initOnce buffer that has been allocated before (and so was previously memset) + * 3. An ASAN redzone, in which case we don't want to write on it + * For these reasons it should be fine to not explicitly zero every byte up to ws->initOnceStart. + * Note that we assume here that MSAN and ASAN cannot run in the same time. */ + ZSTD_memset(ptr, 0, MIN((size_t)((U8*)ws->initOnceStart - (U8*)ptr), alignedBytes)); + ws->initOnceStart = ptr; + } +#if ZSTD_MEMORY_SANITIZER + assert(__msan_test_shadow(ptr, bytes) == -1); +#endif + return ptr; +} + +/** + * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes). + */ +MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) +{ + void* ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES), + ZSTD_cwksp_alloc_aligned); + assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); + return ptr; +} + +/** + * Aligned on 64 bytes. These buffers have the special property that + * their values remain constrained, allowing us to reuse them without + * memset()-ing them. + */ +MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) +{ + const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned_init_once; + void* alloc; + void* end; + void* top; + + /* We can only start allocating tables after we are done reserving space for objects at the + * start of the workspace */ + if(ws->phase < phase) { + if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase))) { + return NULL; + } + } + alloc = ws->tableEnd; + end = (BYTE *)alloc + bytes; + top = ws->allocStart; + + DEBUGLOG(5, "cwksp: reserving %p table %zd bytes, %zd bytes remaining", + alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes); + assert((bytes & (sizeof(U32)-1)) == 0); + ZSTD_cwksp_assert_internal_consistency(ws); + assert(end <= top); + if (end > top) { + DEBUGLOG(4, "cwksp: table alloc failed!"); + ws->allocFailed = 1; + return NULL; + } + ws->tableEnd = end; + +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + __asan_unpoison_memory_region(alloc, bytes); + } +#endif + + assert((bytes & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0); + assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0); + return alloc; +} + +/** + * Aligned on sizeof(void*). + * Note : should happen only once, at workspace first initialization + */ +MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) +{ + size_t const roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*)); + void* alloc = ws->objectEnd; + void* end = (BYTE*)alloc + roundedBytes; + +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + /* over-reserve space */ + end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; +#endif + + DEBUGLOG(4, + "cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining", + alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes); + assert((size_t)alloc % ZSTD_ALIGNOF(void*) == 0); + assert(bytes % ZSTD_ALIGNOF(void*) == 0); + ZSTD_cwksp_assert_internal_consistency(ws); + /* we must be in the first phase, no advance is possible */ + if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) { + DEBUGLOG(3, "cwksp: object alloc failed!"); + ws->allocFailed = 1; + return NULL; + } + ws->objectEnd = end; + ws->tableEnd = end; + ws->tableValidEnd = end; + +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on + * either size. */ + alloc = (BYTE*)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE; + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + __asan_unpoison_memory_region(alloc, bytes); + } +#endif + + return alloc; +} + +MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) +{ + DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty"); + +#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) + /* To validate that the table reuse logic is sound, and that we don't + * access table space that we haven't cleaned, we re-"poison" the table + * space every time we mark it dirty. + * Since tableValidEnd space and initOnce space may overlap we don't poison + * the initOnce portion as it break its promise. This means that this poisoning + * check isn't always applied fully. */ + { + size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd; + assert(__msan_test_shadow(ws->objectEnd, size) == -1); + if((BYTE*)ws->tableValidEnd < (BYTE*)ws->initOnceStart) { + __msan_poison(ws->objectEnd, size); + } else { + assert(ws->initOnceStart >= ws->objectEnd); + __msan_poison(ws->objectEnd, (BYTE*)ws->initOnceStart - (BYTE*)ws->objectEnd); + } + } +#endif + + assert(ws->tableValidEnd >= ws->objectEnd); + assert(ws->tableValidEnd <= ws->allocStart); + ws->tableValidEnd = ws->objectEnd; + ZSTD_cwksp_assert_internal_consistency(ws); +} + +MEM_STATIC void ZSTD_cwksp_mark_tables_clean(ZSTD_cwksp* ws) { + DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_clean"); + assert(ws->tableValidEnd >= ws->objectEnd); + assert(ws->tableValidEnd <= ws->allocStart); + if (ws->tableValidEnd < ws->tableEnd) { + ws->tableValidEnd = ws->tableEnd; + } + ZSTD_cwksp_assert_internal_consistency(ws); +} + +/** + * Zero the part of the allocated tables not already marked clean. + */ +MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) { + DEBUGLOG(4, "cwksp: ZSTD_cwksp_clean_tables"); + assert(ws->tableValidEnd >= ws->objectEnd); + assert(ws->tableValidEnd <= ws->allocStart); + if (ws->tableValidEnd < ws->tableEnd) { + ZSTD_memset(ws->tableValidEnd, 0, (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd)); + } + ZSTD_cwksp_mark_tables_clean(ws); +} + +/** + * Invalidates table allocations. + * All other allocations remain valid. + */ +MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) { + DEBUGLOG(4, "cwksp: clearing tables!"); + +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + /* We don't do this when the workspace is statically allocated, because + * when that is the case, we have no capability to hook into the end of the + * workspace's lifecycle to unpoison the memory. + */ + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd; + __asan_poison_memory_region(ws->objectEnd, size); + } +#endif + + ws->tableEnd = ws->objectEnd; + ZSTD_cwksp_assert_internal_consistency(ws); +} + +/** + * Invalidates all buffer, aligned, and table allocations. + * Object allocations remain valid. + */ +MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) { + DEBUGLOG(4, "cwksp: clearing!"); + +#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) + /* To validate that the context reuse logic is sound, and that we don't + * access stuff that this compression hasn't initialized, we re-"poison" + * the workspace except for the areas in which we expect memory reuse + * without initialization (objects, valid tables area and init once + * memory). */ + { + if((BYTE*)ws->tableValidEnd < (BYTE*)ws->initOnceStart) { + size_t size = (BYTE*)ws->initOnceStart - (BYTE*)ws->tableValidEnd; + __msan_poison(ws->tableValidEnd, size); + } + } +#endif + +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + /* We don't do this when the workspace is statically allocated, because + * when that is the case, we have no capability to hook into the end of the + * workspace's lifecycle to unpoison the memory. + */ + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->objectEnd; + __asan_poison_memory_region(ws->objectEnd, size); + } +#endif + + ws->tableEnd = ws->objectEnd; + ws->allocStart = ZSTD_cwksp_initialAllocStart(ws); + ws->allocFailed = 0; + if (ws->phase > ZSTD_cwksp_alloc_aligned_init_once) { + ws->phase = ZSTD_cwksp_alloc_aligned_init_once; + } + ZSTD_cwksp_assert_internal_consistency(ws); +} + +MEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) { + return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace); +} + +MEM_STATIC size_t ZSTD_cwksp_used(const ZSTD_cwksp* ws) { + return (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->workspace) + + (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->allocStart); +} + +/** + * The provided workspace takes ownership of the buffer [start, start+size). + * Any existing values in the workspace are ignored (the previously managed + * buffer, if present, must be separately freed). + */ +MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size, ZSTD_cwksp_static_alloc_e isStatic) { + DEBUGLOG(4, "cwksp: init'ing workspace with %zd bytes", size); + assert(((size_t)start & (sizeof(void*)-1)) == 0); /* ensure correct alignment */ + ws->workspace = start; + ws->workspaceEnd = (BYTE*)start + size; + ws->objectEnd = ws->workspace; + ws->tableValidEnd = ws->objectEnd; + ws->initOnceStart = ZSTD_cwksp_initialAllocStart(ws); + ws->phase = ZSTD_cwksp_alloc_objects; + ws->isStatic = isStatic; + ZSTD_cwksp_clear(ws); + ws->workspaceOversizedDuration = 0; + ZSTD_cwksp_assert_internal_consistency(ws); +} + +MEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) { + void* workspace = ZSTD_customMalloc(size, customMem); + DEBUGLOG(4, "cwksp: creating new workspace with %zd bytes", size); + RETURN_ERROR_IF(workspace == NULL, memory_allocation, "NULL pointer!"); + ZSTD_cwksp_init(ws, workspace, size, ZSTD_cwksp_dynamic_alloc); + return 0; +} + +MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) { + void *ptr = ws->workspace; + DEBUGLOG(4, "cwksp: freeing workspace"); +#if ZSTD_MEMORY_SANITIZER && !defined(ZSTD_MSAN_DONT_POISON_WORKSPACE) + if (ptr != NULL && customMem.customFree != NULL) { + __msan_unpoison(ptr, ZSTD_cwksp_sizeof(ws)); + } +#endif + ZSTD_memset(ws, 0, sizeof(ZSTD_cwksp)); + ZSTD_customFree(ptr, customMem); +} + +/** + * Moves the management of a workspace from one cwksp to another. The src cwksp + * is left in an invalid state (src must be re-init()'ed before it's used again). + */ +MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) { + *dst = *src; + ZSTD_memset(src, 0, sizeof(ZSTD_cwksp)); +} + +MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) { + return ws->allocFailed; +} + +/*-************************************* +* Functions Checking Free Space +***************************************/ + +/* ZSTD_alignmentSpaceWithinBounds() : + * Returns if the estimated space needed for a wksp is within an acceptable limit of the + * actual amount of space used. + */ +MEM_STATIC int ZSTD_cwksp_estimated_space_within_bounds(const ZSTD_cwksp *const ws, size_t const estimatedSpace) { + /* We have an alignment space between objects and tables between tables and buffers, so we can have up to twice + * the alignment bytes difference between estimation and actual usage */ + return (estimatedSpace - ZSTD_cwksp_slack_space_required()) <= ZSTD_cwksp_used(ws) && + ZSTD_cwksp_used(ws) <= estimatedSpace; +} + + +MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws) { + return (size_t)((BYTE*)ws->allocStart - (BYTE*)ws->tableEnd); +} + +MEM_STATIC int ZSTD_cwksp_check_available(ZSTD_cwksp* ws, size_t additionalNeededSpace) { + return ZSTD_cwksp_available_space(ws) >= additionalNeededSpace; +} + +MEM_STATIC int ZSTD_cwksp_check_too_large(ZSTD_cwksp* ws, size_t additionalNeededSpace) { + return ZSTD_cwksp_check_available( + ws, additionalNeededSpace * ZSTD_WORKSPACETOOLARGE_FACTOR); +} + +MEM_STATIC int ZSTD_cwksp_check_wasteful(ZSTD_cwksp* ws, size_t additionalNeededSpace) { + return ZSTD_cwksp_check_too_large(ws, additionalNeededSpace) + && ws->workspaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION; +} + +MEM_STATIC void ZSTD_cwksp_bump_oversized_duration( + ZSTD_cwksp* ws, size_t additionalNeededSpace) { + if (ZSTD_cwksp_check_too_large(ws, additionalNeededSpace)) { + ws->workspaceOversizedDuration++; + } else { + ws->workspaceOversizedDuration = 0; + } +} + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_CWKSP_H */ diff --git a/third_party/zstd/include/zstd/compress/zstd_double_fast.h b/third_party/zstd/include/zstd/include/compress/zstd_double_fast.h similarity index 55% rename from third_party/zstd/include/zstd/compress/zstd_double_fast.h rename to third_party/zstd/include/zstd/include/compress/zstd_double_fast.h index 7991711fab6..ce6ed8c97fd 100644 --- a/third_party/zstd/include/zstd/compress/zstd_double_fast.h +++ b/third_party/zstd/include/zstd/include/compress/zstd_double_fast.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,13 +11,19 @@ #ifndef ZSTD_DOUBLE_FAST_H #define ZSTD_DOUBLE_FAST_H -#include "zstd/common/mem.h" /* U32 */ -#include "zstd/compress/zstd_compress_internal.h" /* ZSTD_CCtx, size_t */ +#if defined (__cplusplus) +extern "C" { +#endif -namespace duckdb_zstd { +#include "../common/mem.h" /* U32 */ +#include "zstd_compress_internal.h" /* ZSTD_CCtx, size_t */ + +#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, - void const* end, ZSTD_dictTableLoadMethod_e dtlm); + void const* end, ZSTD_dictTableLoadMethod_e dtlm, + ZSTD_tableFillPurpose_e tfp); + size_t ZSTD_compressBlock_doubleFast( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); @@ -28,6 +34,17 @@ size_t ZSTD_compressBlock_doubleFast_extDict( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); +#define ZSTD_COMPRESSBLOCK_DOUBLEFAST ZSTD_compressBlock_doubleFast +#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_DICTMATCHSTATE ZSTD_compressBlock_doubleFast_dictMatchState +#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT ZSTD_compressBlock_doubleFast_extDict +#else +#define ZSTD_COMPRESSBLOCK_DOUBLEFAST NULL +#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_DICTMATCHSTATE NULL +#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT NULL +#endif /* ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR */ + +#if defined (__cplusplus) } +#endif #endif /* ZSTD_DOUBLE_FAST_H */ diff --git a/third_party/zstd/include/zstd/compress/zstd_fast.h b/third_party/zstd/include/zstd/include/compress/zstd_fast.h similarity index 78% rename from third_party/zstd/include/zstd/compress/zstd_fast.h rename to third_party/zstd/include/zstd/include/compress/zstd_fast.h index a75839a065b..9e4236b4728 100644 --- a/third_party/zstd/include/zstd/compress/zstd_fast.h +++ b/third_party/zstd/include/zstd/include/compress/zstd_fast.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,13 +11,16 @@ #ifndef ZSTD_FAST_H #define ZSTD_FAST_H -#include "zstd/common/mem.h" /* U32 */ -#include "zstd/compress/zstd_compress_internal.h" +#if defined (__cplusplus) +extern "C" { +#endif -namespace duckdb_zstd { +#include "../common/mem.h" /* U32 */ +#include "zstd_compress_internal.h" void ZSTD_fillHashTable(ZSTD_matchState_t* ms, - void const* end, ZSTD_dictTableLoadMethod_e dtlm); + void const* end, ZSTD_dictTableLoadMethod_e dtlm, + ZSTD_tableFillPurpose_e tfp); size_t ZSTD_compressBlock_fast( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); @@ -28,6 +31,8 @@ size_t ZSTD_compressBlock_fast_extDict( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); +#if defined (__cplusplus) } +#endif #endif /* ZSTD_FAST_H */ diff --git a/third_party/zstd/include/zstd/include/compress/zstd_lazy.h b/third_party/zstd/include/zstd/include/compress/zstd_lazy.h new file mode 100644 index 00000000000..3635813bddf --- /dev/null +++ b/third_party/zstd/include/zstd/include/compress/zstd_lazy.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_LAZY_H +#define ZSTD_LAZY_H + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "zstd_compress_internal.h" + +/** + * Dedicated Dictionary Search Structure bucket log. In the + * ZSTD_dedicatedDictSearch mode, the hashTable has + * 2 ** ZSTD_LAZY_DDSS_BUCKET_LOG entries in each bucket, rather than just + * one. + */ +#define ZSTD_LAZY_DDSS_BUCKET_LOG 2 + +#define ZSTD_ROW_HASH_TAG_BITS 8 /* nb bits to use for the tag */ + +#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) +U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip); +void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip); + +void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip); + +void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */ +#endif + +#ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_greedy( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_dictMatchState( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_extDict( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); + +#define ZSTD_COMPRESSBLOCK_GREEDY ZSTD_compressBlock_greedy +#define ZSTD_COMPRESSBLOCK_GREEDY_ROW ZSTD_compressBlock_greedy_row +#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE ZSTD_compressBlock_greedy_dictMatchState +#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE_ROW ZSTD_compressBlock_greedy_dictMatchState_row +#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH ZSTD_compressBlock_greedy_dedicatedDictSearch +#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH_ROW ZSTD_compressBlock_greedy_dedicatedDictSearch_row +#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT ZSTD_compressBlock_greedy_extDict +#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT_ROW ZSTD_compressBlock_greedy_extDict_row +#else +#define ZSTD_COMPRESSBLOCK_GREEDY NULL +#define ZSTD_COMPRESSBLOCK_GREEDY_ROW NULL +#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE NULL +#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE_ROW NULL +#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH NULL +#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH_ROW NULL +#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT NULL +#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT_ROW NULL +#endif + +#ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_lazy( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_dictMatchState( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_extDict( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); + +#define ZSTD_COMPRESSBLOCK_LAZY ZSTD_compressBlock_lazy +#define ZSTD_COMPRESSBLOCK_LAZY_ROW ZSTD_compressBlock_lazy_row +#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE ZSTD_compressBlock_lazy_dictMatchState +#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE_ROW ZSTD_compressBlock_lazy_dictMatchState_row +#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH ZSTD_compressBlock_lazy_dedicatedDictSearch +#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH_ROW ZSTD_compressBlock_lazy_dedicatedDictSearch_row +#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT ZSTD_compressBlock_lazy_extDict +#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT_ROW ZSTD_compressBlock_lazy_extDict_row +#else +#define ZSTD_COMPRESSBLOCK_LAZY NULL +#define ZSTD_COMPRESSBLOCK_LAZY_ROW NULL +#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE NULL +#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE_ROW NULL +#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH NULL +#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH_ROW NULL +#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT NULL +#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT_ROW NULL +#endif + +#ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_lazy2( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_dictMatchState( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_dictMatchState_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_extDict( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_extDict_row( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); + +#define ZSTD_COMPRESSBLOCK_LAZY2 ZSTD_compressBlock_lazy2 +#define ZSTD_COMPRESSBLOCK_LAZY2_ROW ZSTD_compressBlock_lazy2_row +#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE ZSTD_compressBlock_lazy2_dictMatchState +#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE_ROW ZSTD_compressBlock_lazy2_dictMatchState_row +#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH ZSTD_compressBlock_lazy2_dedicatedDictSearch +#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW ZSTD_compressBlock_lazy2_dedicatedDictSearch_row +#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT ZSTD_compressBlock_lazy2_extDict +#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT_ROW ZSTD_compressBlock_lazy2_extDict_row +#else +#define ZSTD_COMPRESSBLOCK_LAZY2 NULL +#define ZSTD_COMPRESSBLOCK_LAZY2_ROW NULL +#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE NULL +#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE_ROW NULL +#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH NULL +#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW NULL +#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT NULL +#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT_ROW NULL +#endif + +#ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_btlazy2( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_btlazy2_dictMatchState( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_btlazy2_extDict( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); + +#define ZSTD_COMPRESSBLOCK_BTLAZY2 ZSTD_compressBlock_btlazy2 +#define ZSTD_COMPRESSBLOCK_BTLAZY2_DICTMATCHSTATE ZSTD_compressBlock_btlazy2_dictMatchState +#define ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT ZSTD_compressBlock_btlazy2_extDict +#else +#define ZSTD_COMPRESSBLOCK_BTLAZY2 NULL +#define ZSTD_COMPRESSBLOCK_BTLAZY2_DICTMATCHSTATE NULL +#define ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT NULL +#endif + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_LAZY_H */ diff --git a/third_party/zstd/include/zstd/compress/zstd_ldm.h b/third_party/zstd/include/zstd/include/compress/zstd_ldm.h similarity index 85% rename from third_party/zstd/include/zstd/compress/zstd_ldm.h rename to third_party/zstd/include/zstd/include/compress/zstd_ldm.h index d2640c7761b..f147021d296 100644 --- a/third_party/zstd/include/zstd/compress/zstd_ldm.h +++ b/third_party/zstd/include/zstd/include/compress/zstd_ldm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,8 +11,12 @@ #ifndef ZSTD_LDM_H #define ZSTD_LDM_H -#include "zstd/compress/zstd_compress_internal.h" /* ldmParams_t, U32 */ -#include "zstd.h" /* ZSTD_CCtx, size_t */ +#if defined (__cplusplus) +extern "C" { +#endif + +#include "zstd_compress_internal.h" /* ldmParams_t, U32 */ +#include "../zstd.h" /* ZSTD_CCtx, size_t */ /*-************************************* * Long distance matching @@ -20,8 +24,6 @@ #define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_LIMIT_DEFAULT -namespace duckdb_zstd { - void ZSTD_ldm_fillHashTable( ldmState_t* state, const BYTE* ip, const BYTE* iend, ldmParams_t const* params); @@ -64,6 +66,7 @@ size_t ZSTD_ldm_generateSequences( */ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + ZSTD_paramSwitch_e useRowMatchFinder, void const* src, size_t srcSize); /** @@ -71,11 +74,17 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, * * Skip past `srcSize` bytes worth of sequences in `rawSeqStore`. * Avoids emitting matches less than `minMatch` bytes. - * Must be called for data with is not passed to ZSTD_ldm_blockCompress(). + * Must be called for data that is not passed to ZSTD_ldm_blockCompress(). */ void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch); +/* ZSTD_ldm_skipRawSeqStoreBytes(): + * Moves forward in rawSeqStore by nbBytes, updating fields 'pos' and 'posInSequence'. + * Not to be used in conjunction with ZSTD_ldm_skipSequences(). + * Must be called for data with is not passed to ZSTD_ldm_blockCompress(). + */ +void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes); /** ZSTD_ldm_getTableSize() : * Estimate the space needed for long distance matching tables or 0 if LDM is @@ -101,6 +110,8 @@ size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize); void ZSTD_ldm_adjustParameters(ldmParams_t* params, ZSTD_compressionParameters const* cParams); +#if defined (__cplusplus) } +#endif #endif /* ZSTD_FAST_H */ diff --git a/third_party/zstd/include/zstd/include/compress/zstd_ldm_geartab.h b/third_party/zstd/include/zstd/include/compress/zstd_ldm_geartab.h new file mode 100644 index 00000000000..ef34bc5c923 --- /dev/null +++ b/third_party/zstd/include/zstd/include/compress/zstd_ldm_geartab.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_LDM_GEARTAB_H +#define ZSTD_LDM_GEARTAB_H + +#include "../common/compiler.h" /* UNUSED_ATTR */ +#include "../common/mem.h" /* U64 */ + +static UNUSED_ATTR const U64 ZSTD_ldm_gearTab[256] = { + 0xf5b8f72c5f77775c, 0x84935f266b7ac412, 0xb647ada9ca730ccc, + 0xb065bb4b114fb1de, 0x34584e7e8c3a9fd0, 0x4e97e17c6ae26b05, + 0x3a03d743bc99a604, 0xcecd042422c4044f, 0x76de76c58524259e, + 0x9c8528f65badeaca, 0x86563706e2097529, 0x2902475fa375d889, + 0xafb32a9739a5ebe6, 0xce2714da3883e639, 0x21eaf821722e69e, + 0x37b628620b628, 0x49a8d455d88caf5, 0x8556d711e6958140, + 0x4f7ae74fc605c1f, 0x829f0c3468bd3a20, 0x4ffdc885c625179e, + 0x8473de048a3daf1b, 0x51008822b05646b2, 0x69d75d12b2d1cc5f, + 0x8c9d4a19159154bc, 0xc3cc10f4abbd4003, 0xd06ddc1cecb97391, + 0xbe48e6e7ed80302e, 0x3481db31cee03547, 0xacc3f67cdaa1d210, + 0x65cb771d8c7f96cc, 0x8eb27177055723dd, 0xc789950d44cd94be, + 0x934feadc3700b12b, 0x5e485f11edbdf182, 0x1e2e2a46fd64767a, + 0x2969ca71d82efa7c, 0x9d46e9935ebbba2e, 0xe056b67e05e6822b, + 0x94d73f55739d03a0, 0xcd7010bdb69b5a03, 0x455ef9fcd79b82f4, + 0x869cb54a8749c161, 0x38d1a4fa6185d225, 0xb475166f94bbe9bb, + 0xa4143548720959f1, 0x7aed4780ba6b26ba, 0xd0ce264439e02312, + 0x84366d746078d508, 0xa8ce973c72ed17be, 0x21c323a29a430b01, + 0x9962d617e3af80ee, 0xab0ce91d9c8cf75b, 0x530e8ee6d19a4dbc, + 0x2ef68c0cf53f5d72, 0xc03a681640a85506, 0x496e4e9f9c310967, + 0x78580472b59b14a0, 0x273824c23b388577, 0x66bf923ad45cb553, + 0x47ae1a5a2492ba86, 0x35e304569e229659, 0x4765182a46870b6f, + 0x6cbab625e9099412, 0xddac9a2e598522c1, 0x7172086e666624f2, + 0xdf5003ca503b7837, 0x88c0c1db78563d09, 0x58d51865acfc289d, + 0x177671aec65224f1, 0xfb79d8a241e967d7, 0x2be1e101cad9a49a, + 0x6625682f6e29186b, 0x399553457ac06e50, 0x35dffb4c23abb74, + 0x429db2591f54aade, 0xc52802a8037d1009, 0x6acb27381f0b25f3, + 0xf45e2551ee4f823b, 0x8b0ea2d99580c2f7, 0x3bed519cbcb4e1e1, + 0xff452823dbb010a, 0x9d42ed614f3dd267, 0x5b9313c06257c57b, + 0xa114b8008b5e1442, 0xc1fe311c11c13d4b, 0x66e8763ea34c5568, + 0x8b982af1c262f05d, 0xee8876faaa75fbb7, 0x8a62a4d0d172bb2a, + 0xc13d94a3b7449a97, 0x6dbbba9dc15d037c, 0xc786101f1d92e0f1, + 0xd78681a907a0b79b, 0xf61aaf2962c9abb9, 0x2cfd16fcd3cb7ad9, + 0x868c5b6744624d21, 0x25e650899c74ddd7, 0xba042af4a7c37463, + 0x4eb1a539465a3eca, 0xbe09dbf03b05d5ca, 0x774e5a362b5472ba, + 0x47a1221229d183cd, 0x504b0ca18ef5a2df, 0xdffbdfbde2456eb9, + 0x46cd2b2fbee34634, 0xf2aef8fe819d98c3, 0x357f5276d4599d61, + 0x24a5483879c453e3, 0x88026889192b4b9, 0x28da96671782dbec, + 0x4ef37c40588e9aaa, 0x8837b90651bc9fb3, 0xc164f741d3f0e5d6, + 0xbc135a0a704b70ba, 0x69cd868f7622ada, 0xbc37ba89e0b9c0ab, + 0x47c14a01323552f6, 0x4f00794bacee98bb, 0x7107de7d637a69d5, + 0x88af793bb6f2255e, 0xf3c6466b8799b598, 0xc288c616aa7f3b59, + 0x81ca63cf42fca3fd, 0x88d85ace36a2674b, 0xd056bd3792389e7, + 0xe55c396c4e9dd32d, 0xbefb504571e6c0a6, 0x96ab32115e91e8cc, + 0xbf8acb18de8f38d1, 0x66dae58801672606, 0x833b6017872317fb, + 0xb87c16f2d1c92864, 0xdb766a74e58b669c, 0x89659f85c61417be, + 0xc8daad856011ea0c, 0x76a4b565b6fe7eae, 0xa469d085f6237312, + 0xaaf0365683a3e96c, 0x4dbb746f8424f7b8, 0x638755af4e4acc1, + 0x3d7807f5bde64486, 0x17be6d8f5bbb7639, 0x903f0cd44dc35dc, + 0x67b672eafdf1196c, 0xa676ff93ed4c82f1, 0x521d1004c5053d9d, + 0x37ba9ad09ccc9202, 0x84e54d297aacfb51, 0xa0b4b776a143445, + 0x820d471e20b348e, 0x1874383cb83d46dc, 0x97edeec7a1efe11c, + 0xb330e50b1bdc42aa, 0x1dd91955ce70e032, 0xa514cdb88f2939d5, + 0x2791233fd90db9d3, 0x7b670a4cc50f7a9b, 0x77c07d2a05c6dfa5, + 0xe3778b6646d0a6fa, 0xb39c8eda47b56749, 0x933ed448addbef28, + 0xaf846af6ab7d0bf4, 0xe5af208eb666e49, 0x5e6622f73534cd6a, + 0x297daeca42ef5b6e, 0x862daef3d35539a6, 0xe68722498f8e1ea9, + 0x981c53093dc0d572, 0xfa09b0bfbf86fbf5, 0x30b1e96166219f15, + 0x70e7d466bdc4fb83, 0x5a66736e35f2a8e9, 0xcddb59d2b7c1baef, + 0xd6c7d247d26d8996, 0xea4e39eac8de1ba3, 0x539c8bb19fa3aff2, + 0x9f90e4c5fd508d8, 0xa34e5956fbaf3385, 0x2e2f8e151d3ef375, + 0x173691e9b83faec1, 0xb85a8d56bf016379, 0x8382381267408ae3, + 0xb90f901bbdc0096d, 0x7c6ad32933bcec65, 0x76bb5e2f2c8ad595, + 0x390f851a6cf46d28, 0xc3e6064da1c2da72, 0xc52a0c101cfa5389, + 0xd78eaf84a3fbc530, 0x3781b9e2288b997e, 0x73c2f6dea83d05c4, + 0x4228e364c5b5ed7, 0x9d7a3edf0da43911, 0x8edcfeda24686756, + 0x5e7667a7b7a9b3a1, 0x4c4f389fa143791d, 0xb08bc1023da7cddc, + 0x7ab4be3ae529b1cc, 0x754e6132dbe74ff9, 0x71635442a839df45, + 0x2f6fb1643fbe52de, 0x961e0a42cf7a8177, 0xf3b45d83d89ef2ea, + 0xee3de4cf4a6e3e9b, 0xcd6848542c3295e7, 0xe4cee1664c78662f, + 0x9947548b474c68c4, 0x25d73777a5ed8b0b, 0xc915b1d636b7fc, + 0x21c2ba75d9b0d2da, 0x5f6b5dcf608a64a1, 0xdcf333255ff9570c, + 0x633b922418ced4ee, 0xc136dde0b004b34a, 0x58cc83b05d4b2f5a, + 0x5eb424dda28e42d2, 0x62df47369739cd98, 0xb4e0b42485e4ce17, + 0x16e1f0c1f9a8d1e7, 0x8ec3916707560ebf, 0x62ba6e2df2cc9db3, + 0xcbf9f4ff77d83a16, 0x78d9d7d07d2bbcc4, 0xef554ce1e02c41f4, + 0x8d7581127eccf94d, 0xa9b53336cb3c8a05, 0x38c42c0bf45c4f91, + 0x640893cdf4488863, 0x80ec34bc575ea568, 0x39f324f5b48eaa40, + 0xe9d9ed1f8eff527f, 0x9224fc058cc5a214, 0xbaba00b04cfe7741, + 0x309a9f120fcf52af, 0xa558f3ec65626212, 0x424bec8b7adabe2f, + 0x41622513a6aea433, 0xb88da2d5324ca798, 0xd287733b245528a4, + 0x9a44697e6d68aec3, 0x7b1093be2f49bb28, 0x50bbec632e3d8aad, + 0x6cd90723e1ea8283, 0x897b9e7431b02bf3, 0x219efdcb338a7047, + 0x3b0311f0a27c0656, 0xdb17bf91c0db96e7, 0x8cd4fd6b4e85a5b2, + 0xfab071054ba6409d, 0x40d6fe831fa9dfd9, 0xaf358debad7d791e, + 0xeb8d0e25a65e3e58, 0xbbcbd3df14e08580, 0xcf751f27ecdab2b, + 0x2b4da14f2613d8f4 +}; + +#endif /* ZSTD_LDM_GEARTAB_H */ diff --git a/third_party/zstd/include/zstd/compress/zstd_opt.h b/third_party/zstd/include/zstd/include/compress/zstd_opt.h similarity index 58% rename from third_party/zstd/include/zstd/compress/zstd_opt.h rename to third_party/zstd/include/zstd/include/compress/zstd_opt.h index b0d7bc3e278..d4e71131572 100644 --- a/third_party/zstd/include/zstd/compress/zstd_opt.h +++ b/third_party/zstd/include/zstd/include/compress/zstd_opt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,34 +11,46 @@ #ifndef ZSTD_OPT_H #define ZSTD_OPT_H -#include "zstd/compress/zstd_compress_internal.h" +#if defined (__cplusplus) +extern "C" { +#endif -namespace duckdb_zstd { +#include "zstd_compress_internal.h" +#if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \ + || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR) /* used in ZSTD_loadDictionaryContent() */ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend); +#endif +#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR size_t ZSTD_compressBlock_btopt( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); -size_t ZSTD_compressBlock_btultra( +size_t ZSTD_compressBlock_btopt_dictMatchState( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); -size_t ZSTD_compressBlock_btultra2( +size_t ZSTD_compressBlock_btopt_extDict( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); +#define ZSTD_COMPRESSBLOCK_BTOPT ZSTD_compressBlock_btopt +#define ZSTD_COMPRESSBLOCK_BTOPT_DICTMATCHSTATE ZSTD_compressBlock_btopt_dictMatchState +#define ZSTD_COMPRESSBLOCK_BTOPT_EXTDICT ZSTD_compressBlock_btopt_extDict +#else +#define ZSTD_COMPRESSBLOCK_BTOPT NULL +#define ZSTD_COMPRESSBLOCK_BTOPT_DICTMATCHSTATE NULL +#define ZSTD_COMPRESSBLOCK_BTOPT_EXTDICT NULL +#endif -size_t ZSTD_compressBlock_btopt_dictMatchState( +#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR +size_t ZSTD_compressBlock_btultra( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); size_t ZSTD_compressBlock_btultra_dictMatchState( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); - -size_t ZSTD_compressBlock_btopt_extDict( - ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], - void const* src, size_t srcSize); size_t ZSTD_compressBlock_btultra_extDict( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); @@ -46,7 +58,23 @@ size_t ZSTD_compressBlock_btultra_extDict( /* note : no btultra2 variant for extDict nor dictMatchState, * because btultra2 is not meant to work with dictionaries * and is only specific for the first block (no prefix) */ +size_t ZSTD_compressBlock_btultra2( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); + +#define ZSTD_COMPRESSBLOCK_BTULTRA ZSTD_compressBlock_btultra +#define ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE ZSTD_compressBlock_btultra_dictMatchState +#define ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT ZSTD_compressBlock_btultra_extDict +#define ZSTD_COMPRESSBLOCK_BTULTRA2 ZSTD_compressBlock_btultra2 +#else +#define ZSTD_COMPRESSBLOCK_BTULTRA NULL +#define ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE NULL +#define ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT NULL +#define ZSTD_COMPRESSBLOCK_BTULTRA2 NULL +#endif +#if defined (__cplusplus) } +#endif #endif /* ZSTD_OPT_H */ diff --git a/third_party/zstd/include/zstd/include/compress/zstdmt_compress.h b/third_party/zstd/include/zstd/include/compress/zstdmt_compress.h new file mode 100644 index 00000000000..ed4dc0e99df --- /dev/null +++ b/third_party/zstd/include/zstd/include/compress/zstdmt_compress.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + #ifndef ZSTDMT_COMPRESS_H + #define ZSTDMT_COMPRESS_H + + #if defined (__cplusplus) + extern "C" { + #endif + + +/* Note : This is an internal API. + * These APIs used to be exposed with ZSTDLIB_API, + * because it used to be the only way to invoke MT compression. + * Now, you must use ZSTD_compress2 and ZSTD_compressStream2() instead. + * + * This API requires ZSTD_MULTITHREAD to be defined during compilation, + * otherwise ZSTDMT_createCCtx*() will fail. + */ + +/* === Dependencies === */ +#include "../common/zstd_deps.h" /* size_t */ +#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters */ +#include "../zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */ + + +/* === Constants === */ +#ifndef ZSTDMT_NBWORKERS_MAX /* a different value can be selected at compile time */ +# define ZSTDMT_NBWORKERS_MAX ((sizeof(void*)==4) /*32-bit*/ ? 64 : 256) +#endif +#ifndef ZSTDMT_JOBSIZE_MIN /* a different value can be selected at compile time */ +# define ZSTDMT_JOBSIZE_MIN (512 KB) +#endif +#define ZSTDMT_JOBLOG_MAX (MEM_32bits() ? 29 : 30) +#define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB)) + + +/* ======================================================== + * === Private interface, for use by ZSTD_compress.c === + * === Not exposed in libzstd. Never invoke directly === + * ======================================================== */ + +/* === Memory management === */ +typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx; +/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */ +ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, + ZSTD_customMem cMem, + ZSTD_threadPool *pool); +size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx); + +size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx); + +/* === Streaming functions === */ + +size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx); + +/*! ZSTDMT_initCStream_internal() : + * Private use only. Init streaming operation. + * expects params to be valid. + * must receive dict, or cdict, or none, but not both. + * mtctx can be freshly constructed or reused from a prior compression. + * If mtctx is reused, memory allocations from the prior compression may not be freed, + * even if they are not needed for the current compression. + * @return : 0, or an error code */ +size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* mtctx, + const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, + const ZSTD_CDict* cdict, + ZSTD_CCtx_params params, unsigned long long pledgedSrcSize); + +/*! ZSTDMT_compressStream_generic() : + * Combines ZSTDMT_compressStream() with optional ZSTDMT_flushStream() or ZSTDMT_endStream() + * depending on flush directive. + * @return : minimum amount of data still to be flushed + * 0 if fully flushed + * or an error code + * note : needs to be init using any ZSTD_initCStream*() variant */ +size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input, + ZSTD_EndDirective endOp); + + /*! ZSTDMT_toFlushNow() + * Tell how many bytes are ready to be flushed immediately. + * Probe the oldest active job (not yet entirely flushed) and check its output buffer. + * If return 0, it means there is no active job, + * or, it means oldest job is still active, but everything produced has been flushed so far, + * therefore flushing is limited by speed of oldest job. */ +size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx); + +/*! ZSTDMT_updateCParams_whileCompressing() : + * Updates only a selected set of compression parameters, to remain compatible with current frame. + * New parameters will be applied to next compression job. */ +void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams); + +/*! ZSTDMT_getFrameProgression(): + * tells how much data has been consumed (input) and produced (output) for current frame. + * able to count progression inside worker threads. + */ +ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx); + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTDMT_COMPRESS_H */ diff --git a/third_party/zstd/include/zstd/include/dictBuilder/cover.h b/third_party/zstd/include/zstd/include/dictBuilder/cover.h new file mode 100644 index 00000000000..a5d7506ef6d --- /dev/null +++ b/third_party/zstd/include/zstd/include/dictBuilder/cover.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZDICT_STATIC_LINKING_ONLY +# define ZDICT_STATIC_LINKING_ONLY +#endif + +#include "../common/threading.h" /* ZSTD_pthread_mutex_t */ +#include "../common/mem.h" /* U32, BYTE */ +#include "../zdict.h" + +/** + * COVER_best_t is used for two purposes: + * 1. Synchronizing threads. + * 2. Saving the best parameters and dictionary. + * + * All of the methods except COVER_best_init() are thread safe if zstd is + * compiled with multithreaded support. + */ +typedef struct COVER_best_s { + ZSTD_pthread_mutex_t mutex; + ZSTD_pthread_cond_t cond; + size_t liveJobs; + void *dict; + size_t dictSize; + ZDICT_cover_params_t parameters; + size_t compressedSize; +} COVER_best_t; + +/** + * A segment is a range in the source as well as the score of the segment. + */ +typedef struct { + U32 begin; + U32 end; + U32 score; +} COVER_segment_t; + +/** + *Number of epochs and size of each epoch. + */ +typedef struct { + U32 num; + U32 size; +} COVER_epoch_info_t; + +/** + * Struct used for the dictionary selection function. + */ +typedef struct COVER_dictSelection { + BYTE* dictContent; + size_t dictSize; + size_t totalCompressedSize; +} COVER_dictSelection_t; + +/** + * Computes the number of epochs and the size of each epoch. + * We will make sure that each epoch gets at least 10 * k bytes. + * + * The COVER algorithms divide the data up into epochs of equal size and + * select one segment from each epoch. + * + * @param maxDictSize The maximum allowed dictionary size. + * @param nbDmers The number of dmers we are training on. + * @param k The parameter k (segment size). + * @param passes The target number of passes over the dmer corpus. + * More passes means a better dictionary. + */ +COVER_epoch_info_t COVER_computeEpochs(U32 maxDictSize, U32 nbDmers, + U32 k, U32 passes); + +/** + * Warns the user when their corpus is too small. + */ +void COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel); + +/** + * Checks total compressed size of a dictionary + */ +size_t COVER_checkTotalCompressedSize(const ZDICT_cover_params_t parameters, + const size_t *samplesSizes, const BYTE *samples, + size_t *offsets, + size_t nbTrainSamples, size_t nbSamples, + BYTE *const dict, size_t dictBufferCapacity); + +/** + * Returns the sum of the sample sizes. + */ +size_t COVER_sum(const size_t *samplesSizes, unsigned nbSamples) ; + +/** + * Initialize the `COVER_best_t`. + */ +void COVER_best_init(COVER_best_t *best); + +/** + * Wait until liveJobs == 0. + */ +void COVER_best_wait(COVER_best_t *best); + +/** + * Call COVER_best_wait() and then destroy the COVER_best_t. + */ +void COVER_best_destroy(COVER_best_t *best); + +/** + * Called when a thread is about to be launched. + * Increments liveJobs. + */ +void COVER_best_start(COVER_best_t *best); + +/** + * Called when a thread finishes executing, both on error or success. + * Decrements liveJobs and signals any waiting threads if liveJobs == 0. + * If this dictionary is the best so far save it and its parameters. + */ +void COVER_best_finish(COVER_best_t *best, ZDICT_cover_params_t parameters, + COVER_dictSelection_t selection); +/** + * Error function for COVER_selectDict function. Checks if the return + * value is an error. + */ +unsigned COVER_dictSelectionIsError(COVER_dictSelection_t selection); + + /** + * Error function for COVER_selectDict function. Returns a struct where + * return.totalCompressedSize is a ZSTD error. + */ +COVER_dictSelection_t COVER_dictSelectionError(size_t error); + +/** + * Always call after selectDict is called to free up used memory from + * newly created dictionary. + */ +void COVER_dictSelectionFree(COVER_dictSelection_t selection); + +/** + * Called to finalize the dictionary and select one based on whether or not + * the shrink-dict flag was enabled. If enabled the dictionary used is the + * smallest dictionary within a specified regression of the compressed size + * from the largest dictionary. + */ + COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBufferCapacity, + size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples, + size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize); diff --git a/third_party/zstd/include/zstd/include/dictBuilder/divsufsort.h b/third_party/zstd/include/zstd/include/dictBuilder/divsufsort.h new file mode 100644 index 00000000000..5440994af15 --- /dev/null +++ b/third_party/zstd/include/zstd/include/dictBuilder/divsufsort.h @@ -0,0 +1,67 @@ +/* + * divsufsort.h for libdivsufsort-lite + * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. + * + * 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. + */ + +#ifndef _DIVSUFSORT_H +#define _DIVSUFSORT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/*- Prototypes -*/ + +/** + * Constructs the suffix array of a given string. + * @param T [0..n-1] The input string. + * @param SA [0..n-1] The output array of suffixes. + * @param n The length of the given string. + * @param openMP enables OpenMP optimization. + * @return 0 if no error occurred, -1 or -2 otherwise. + */ +int +divsufsort(const unsigned char *T, int *SA, int n, int openMP); + +/** + * Constructs the burrows-wheeler transformed string of a given string. + * @param T [0..n-1] The input string. + * @param U [0..n-1] The output string. (can be T) + * @param A [0..n-1] The temporary array. (can be NULL) + * @param n The length of the given string. + * @param num_indexes The length of secondary indexes array. (can be NULL) + * @param indexes The secondary indexes array. (can be NULL) + * @param openMP enables OpenMP optimization. + * @return The primary index if no error occurred, -1 or -2 otherwise. + */ +int +divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* _DIVSUFSORT_H */ diff --git a/third_party/zstd/include/zstd/include/zdict.h b/third_party/zstd/include/zstd/include/zdict.h new file mode 100644 index 00000000000..2268f948a5d --- /dev/null +++ b/third_party/zstd/include/zstd/include/zdict.h @@ -0,0 +1,474 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef ZSTD_ZDICT_H +#define ZSTD_ZDICT_H + +/*====== Dependencies ======*/ +#include /* size_t */ + + +/* ===== ZDICTLIB_API : control library symbols visibility ===== */ +#ifndef ZDICTLIB_VISIBLE + /* Backwards compatibility with old macro name */ +# ifdef ZDICTLIB_VISIBILITY +# define ZDICTLIB_VISIBLE ZDICTLIB_VISIBILITY +# elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) +# define ZDICTLIB_VISIBLE __attribute__ ((visibility ("default"))) +# else +# define ZDICTLIB_VISIBLE +# endif +#endif + +#ifndef ZDICTLIB_HIDDEN +# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) +# define ZDICTLIB_HIDDEN __attribute__ ((visibility ("hidden"))) +# else +# define ZDICTLIB_HIDDEN +# endif +#endif + +#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) +# define ZDICTLIB_API __declspec(dllexport) ZDICTLIB_VISIBLE +#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) +# define ZDICTLIB_API __declspec(dllimport) ZDICTLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define ZDICTLIB_API ZDICTLIB_VISIBLE +#endif + +/******************************************************************************* + * Zstd dictionary builder + * + * FAQ + * === + * Why should I use a dictionary? + * ------------------------------ + * + * Zstd can use dictionaries to improve compression ratio of small data. + * Traditionally small files don't compress well because there is very little + * repetition in a single sample, since it is small. But, if you are compressing + * many similar files, like a bunch of JSON records that share the same + * structure, you can train a dictionary on ahead of time on some samples of + * these files. Then, zstd can use the dictionary to find repetitions that are + * present across samples. This can vastly improve compression ratio. + * + * When is a dictionary useful? + * ---------------------------- + * + * Dictionaries are useful when compressing many small files that are similar. + * The larger a file is, the less benefit a dictionary will have. Generally, + * we don't expect dictionary compression to be effective past 100KB. And the + * smaller a file is, the more we would expect the dictionary to help. + * + * How do I use a dictionary? + * -------------------------- + * + * Simply pass the dictionary to the zstd compressor with + * `ZSTD_CCtx_loadDictionary()`. The same dictionary must then be passed to + * the decompressor, using `ZSTD_DCtx_loadDictionary()`. There are other + * more advanced functions that allow selecting some options, see zstd.h for + * complete documentation. + * + * What is a zstd dictionary? + * -------------------------- + * + * A zstd dictionary has two pieces: Its header, and its content. The header + * contains a magic number, the dictionary ID, and entropy tables. These + * entropy tables allow zstd to save on header costs in the compressed file, + * which really matters for small data. The content is just bytes, which are + * repeated content that is common across many samples. + * + * What is a raw content dictionary? + * --------------------------------- + * + * A raw content dictionary is just bytes. It doesn't have a zstd dictionary + * header, a dictionary ID, or entropy tables. Any buffer is a valid raw + * content dictionary. + * + * How do I train a dictionary? + * ---------------------------- + * + * Gather samples from your use case. These samples should be similar to each + * other. If you have several use cases, you could try to train one dictionary + * per use case. + * + * Pass those samples to `ZDICT_trainFromBuffer()` and that will train your + * dictionary. There are a few advanced versions of this function, but this + * is a great starting point. If you want to further tune your dictionary + * you could try `ZDICT_optimizeTrainFromBuffer_cover()`. If that is too slow + * you can try `ZDICT_optimizeTrainFromBuffer_fastCover()`. + * + * If the dictionary training function fails, that is likely because you + * either passed too few samples, or a dictionary would not be effective + * for your data. Look at the messages that the dictionary trainer printed, + * if it doesn't say too few samples, then a dictionary would not be effective. + * + * How large should my dictionary be? + * ---------------------------------- + * + * A reasonable dictionary size, the `dictBufferCapacity`, is about 100KB. + * The zstd CLI defaults to a 110KB dictionary. You likely don't need a + * dictionary larger than that. But, most use cases can get away with a + * smaller dictionary. The advanced dictionary builders can automatically + * shrink the dictionary for you, and select the smallest size that doesn't + * hurt compression ratio too much. See the `shrinkDict` parameter. + * A smaller dictionary can save memory, and potentially speed up + * compression. + * + * How many samples should I provide to the dictionary builder? + * ------------------------------------------------------------ + * + * We generally recommend passing ~100x the size of the dictionary + * in samples. A few thousand should suffice. Having too few samples + * can hurt the dictionaries effectiveness. Having more samples will + * only improve the dictionaries effectiveness. But having too many + * samples can slow down the dictionary builder. + * + * How do I determine if a dictionary will be effective? + * ----------------------------------------------------- + * + * Simply train a dictionary and try it out. You can use zstd's built in + * benchmarking tool to test the dictionary effectiveness. + * + * # Benchmark levels 1-3 without a dictionary + * zstd -b1e3 -r /path/to/my/files + * # Benchmark levels 1-3 with a dictionary + * zstd -b1e3 -r /path/to/my/files -D /path/to/my/dictionary + * + * When should I retrain a dictionary? + * ----------------------------------- + * + * You should retrain a dictionary when its effectiveness drops. Dictionary + * effectiveness drops as the data you are compressing changes. Generally, we do + * expect dictionaries to "decay" over time, as your data changes, but the rate + * at which they decay depends on your use case. Internally, we regularly + * retrain dictionaries, and if the new dictionary performs significantly + * better than the old dictionary, we will ship the new dictionary. + * + * I have a raw content dictionary, how do I turn it into a zstd dictionary? + * ------------------------------------------------------------------------- + * + * If you have a raw content dictionary, e.g. by manually constructing it, or + * using a third-party dictionary builder, you can turn it into a zstd + * dictionary by using `ZDICT_finalizeDictionary()`. You'll also have to + * provide some samples of the data. It will add the zstd header to the + * raw content, which contains a dictionary ID and entropy tables, which + * will improve compression ratio, and allow zstd to write the dictionary ID + * into the frame, if you so choose. + * + * Do I have to use zstd's dictionary builder? + * ------------------------------------------- + * + * No! You can construct dictionary content however you please, it is just + * bytes. It will always be valid as a raw content dictionary. If you want + * a zstd dictionary, which can improve compression ratio, use + * `ZDICT_finalizeDictionary()`. + * + * What is the attack surface of a zstd dictionary? + * ------------------------------------------------ + * + * Zstd is heavily fuzz tested, including loading fuzzed dictionaries, so + * zstd should never crash, or access out-of-bounds memory no matter what + * the dictionary is. However, if an attacker can control the dictionary + * during decompression, they can cause zstd to generate arbitrary bytes, + * just like if they controlled the compressed data. + * + ******************************************************************************/ + + +/*! ZDICT_trainFromBuffer(): + * Train a dictionary from an array of samples. + * Redirect towards ZDICT_optimizeTrainFromBuffer_fastCover() single-threaded, with d=8, steps=4, + * f=20, and accel=1. + * Samples must be stored concatenated in a single flat buffer `samplesBuffer`, + * supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order. + * The resulting dictionary will be saved into `dictBuffer`. + * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) + * or an error code, which can be tested with ZDICT_isError(). + * Note: Dictionary training will fail if there are not enough samples to construct a + * dictionary, or if most of the samples are too small (< 8 bytes being the lower limit). + * If dictionary training fails, you should use zstd without a dictionary, as the dictionary + * would've been ineffective anyways. If you believe your samples would benefit from a dictionary + * please open an issue with details, and we can look into it. + * Note: ZDICT_trainFromBuffer()'s memory usage is about 6 MB. + * Tips: In general, a reasonable dictionary has a size of ~ 100 KB. + * It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`. + * In general, it's recommended to provide a few thousands samples, though this can vary a lot. + * It's recommended that total size of all samples be about ~x100 times the target size of dictionary. + */ +ZDICTLIB_API size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity, + const void* samplesBuffer, + const size_t* samplesSizes, unsigned nbSamples); + +typedef struct { + int compressionLevel; /**< optimize for a specific zstd compression level; 0 means default */ + unsigned notificationLevel; /**< Write log to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */ + unsigned dictID; /**< force dictID value; 0 means auto mode (32-bits random value) + * NOTE: The zstd format reserves some dictionary IDs for future use. + * You may use them in private settings, but be warned that they + * may be used by zstd in a public dictionary registry in the future. + * These dictionary IDs are: + * - low range : <= 32767 + * - high range : >= (2^31) + */ +} ZDICT_params_t; + +/*! ZDICT_finalizeDictionary(): + * Given a custom content as a basis for dictionary, and a set of samples, + * finalize dictionary by adding headers and statistics according to the zstd + * dictionary format. + * + * Samples must be stored concatenated in a flat buffer `samplesBuffer`, + * supplied with an array of sizes `samplesSizes`, providing the size of each + * sample in order. The samples are used to construct the statistics, so they + * should be representative of what you will compress with this dictionary. + * + * The compression level can be set in `parameters`. You should pass the + * compression level you expect to use in production. The statistics for each + * compression level differ, so tuning the dictionary for the compression level + * can help quite a bit. + * + * You can set an explicit dictionary ID in `parameters`, or allow us to pick + * a random dictionary ID for you, but we can't guarantee no collisions. + * + * The dstDictBuffer and the dictContent may overlap, and the content will be + * appended to the end of the header. If the header + the content doesn't fit in + * maxDictSize the beginning of the content is truncated to make room, since it + * is presumed that the most profitable content is at the end of the dictionary, + * since that is the cheapest to reference. + * + * `maxDictSize` must be >= max(dictContentSize, ZSTD_DICTSIZE_MIN). + * + * @return: size of dictionary stored into `dstDictBuffer` (<= `maxDictSize`), + * or an error code, which can be tested by ZDICT_isError(). + * Note: ZDICT_finalizeDictionary() will push notifications into stderr if + * instructed to, using notificationLevel>0. + * NOTE: This function currently may fail in several edge cases including: + * * Not enough samples + * * Samples are uncompressible + * * Samples are all exactly the same + */ +ZDICTLIB_API size_t ZDICT_finalizeDictionary(void* dstDictBuffer, size_t maxDictSize, + const void* dictContent, size_t dictContentSize, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, + ZDICT_params_t parameters); + + +/*====== Helper functions ======*/ +ZDICTLIB_API unsigned ZDICT_getDictID(const void* dictBuffer, size_t dictSize); /**< extracts dictID; @return zero if error (not a valid dictionary) */ +ZDICTLIB_API size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize); /* returns dict header size; returns a ZSTD error code on failure */ +ZDICTLIB_API unsigned ZDICT_isError(size_t errorCode); +ZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode); + +#endif /* ZSTD_ZDICT_H */ + +#if defined(ZDICT_STATIC_LINKING_ONLY) && !defined(ZSTD_ZDICT_H_STATIC) +#define ZSTD_ZDICT_H_STATIC + +/* This can be overridden externally to hide static symbols. */ +#ifndef ZDICTLIB_STATIC_API +# if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) +# define ZDICTLIB_STATIC_API __declspec(dllexport) ZDICTLIB_VISIBLE +# elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) +# define ZDICTLIB_STATIC_API __declspec(dllimport) ZDICTLIB_VISIBLE +# else +# define ZDICTLIB_STATIC_API ZDICTLIB_VISIBLE +# endif +#endif + +/* ==================================================================================== + * The definitions in this section are considered experimental. + * They should never be used with a dynamic library, as they may change in the future. + * They are provided for advanced usages. + * Use them only in association with static linking. + * ==================================================================================== */ + +#define ZDICT_DICTSIZE_MIN 256 +/* Deprecated: Remove in v1.6.0 */ +#define ZDICT_CONTENTSIZE_MIN 128 + +/*! ZDICT_cover_params_t: + * k and d are the only required parameters. + * For others, value 0 means default. + */ +typedef struct { + unsigned k; /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+] */ + unsigned d; /* dmer size : constraint: 0 < d <= k : Reasonable range [6, 16] */ + unsigned steps; /* Number of steps : Only used for optimization : 0 means default (40) : Higher means more parameters checked */ + unsigned nbThreads; /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */ + double splitPoint; /* Percentage of samples used for training: Only used for optimization : the first nbSamples * splitPoint samples will be used to training, the last nbSamples * (1 - splitPoint) samples will be used for testing, 0 means default (1.0), 1.0 when all samples are used for both training and testing */ + unsigned shrinkDict; /* Train dictionaries to shrink in size starting from the minimum size and selects the smallest dictionary that is shrinkDictMaxRegression% worse than the largest dictionary. 0 means no shrinking and 1 means shrinking */ + unsigned shrinkDictMaxRegression; /* Sets shrinkDictMaxRegression so that a smaller dictionary can be at worse shrinkDictMaxRegression% worse than the max dict size dictionary. */ + ZDICT_params_t zParams; +} ZDICT_cover_params_t; + +typedef struct { + unsigned k; /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+] */ + unsigned d; /* dmer size : constraint: 0 < d <= k : Reasonable range [6, 16] */ + unsigned f; /* log of size of frequency array : constraint: 0 < f <= 31 : 1 means default(20)*/ + unsigned steps; /* Number of steps : Only used for optimization : 0 means default (40) : Higher means more parameters checked */ + unsigned nbThreads; /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */ + double splitPoint; /* Percentage of samples used for training: Only used for optimization : the first nbSamples * splitPoint samples will be used to training, the last nbSamples * (1 - splitPoint) samples will be used for testing, 0 means default (0.75), 1.0 when all samples are used for both training and testing */ + unsigned accel; /* Acceleration level: constraint: 0 < accel <= 10, higher means faster and less accurate, 0 means default(1) */ + unsigned shrinkDict; /* Train dictionaries to shrink in size starting from the minimum size and selects the smallest dictionary that is shrinkDictMaxRegression% worse than the largest dictionary. 0 means no shrinking and 1 means shrinking */ + unsigned shrinkDictMaxRegression; /* Sets shrinkDictMaxRegression so that a smaller dictionary can be at worse shrinkDictMaxRegression% worse than the max dict size dictionary. */ + + ZDICT_params_t zParams; +} ZDICT_fastCover_params_t; + +/*! ZDICT_trainFromBuffer_cover(): + * Train a dictionary from an array of samples using the COVER algorithm. + * Samples must be stored concatenated in a single flat buffer `samplesBuffer`, + * supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order. + * The resulting dictionary will be saved into `dictBuffer`. + * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) + * or an error code, which can be tested with ZDICT_isError(). + * See ZDICT_trainFromBuffer() for details on failure modes. + * Note: ZDICT_trainFromBuffer_cover() requires about 9 bytes of memory for each input byte. + * Tips: In general, a reasonable dictionary has a size of ~ 100 KB. + * It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`. + * In general, it's recommended to provide a few thousands samples, though this can vary a lot. + * It's recommended that total size of all samples be about ~x100 times the target size of dictionary. + */ +ZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_cover( + void *dictBuffer, size_t dictBufferCapacity, + const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, + ZDICT_cover_params_t parameters); + +/*! ZDICT_optimizeTrainFromBuffer_cover(): + * The same requirements as above hold for all the parameters except `parameters`. + * This function tries many parameter combinations and picks the best parameters. + * `*parameters` is filled with the best parameters found, + * dictionary constructed with those parameters is stored in `dictBuffer`. + * + * All of the parameters d, k, steps are optional. + * If d is non-zero then we don't check multiple values of d, otherwise we check d = {6, 8}. + * if steps is zero it defaults to its default value. + * If k is non-zero then we don't check multiple values of k, otherwise we check steps values in [50, 2000]. + * + * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) + * or an error code, which can be tested with ZDICT_isError(). + * On success `*parameters` contains the parameters selected. + * See ZDICT_trainFromBuffer() for details on failure modes. + * Note: ZDICT_optimizeTrainFromBuffer_cover() requires about 8 bytes of memory for each input byte and additionally another 5 bytes of memory for each byte of memory for each thread. + */ +ZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_cover( + void* dictBuffer, size_t dictBufferCapacity, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, + ZDICT_cover_params_t* parameters); + +/*! ZDICT_trainFromBuffer_fastCover(): + * Train a dictionary from an array of samples using a modified version of COVER algorithm. + * Samples must be stored concatenated in a single flat buffer `samplesBuffer`, + * supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order. + * d and k are required. + * All other parameters are optional, will use default values if not provided + * The resulting dictionary will be saved into `dictBuffer`. + * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) + * or an error code, which can be tested with ZDICT_isError(). + * See ZDICT_trainFromBuffer() for details on failure modes. + * Note: ZDICT_trainFromBuffer_fastCover() requires 6 * 2^f bytes of memory. + * Tips: In general, a reasonable dictionary has a size of ~ 100 KB. + * It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`. + * In general, it's recommended to provide a few thousands samples, though this can vary a lot. + * It's recommended that total size of all samples be about ~x100 times the target size of dictionary. + */ +ZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_fastCover(void *dictBuffer, + size_t dictBufferCapacity, const void *samplesBuffer, + const size_t *samplesSizes, unsigned nbSamples, + ZDICT_fastCover_params_t parameters); + +/*! ZDICT_optimizeTrainFromBuffer_fastCover(): + * The same requirements as above hold for all the parameters except `parameters`. + * This function tries many parameter combinations (specifically, k and d combinations) + * and picks the best parameters. `*parameters` is filled with the best parameters found, + * dictionary constructed with those parameters is stored in `dictBuffer`. + * All of the parameters d, k, steps, f, and accel are optional. + * If d is non-zero then we don't check multiple values of d, otherwise we check d = {6, 8}. + * if steps is zero it defaults to its default value. + * If k is non-zero then we don't check multiple values of k, otherwise we check steps values in [50, 2000]. + * If f is zero, default value of 20 is used. + * If accel is zero, default value of 1 is used. + * + * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) + * or an error code, which can be tested with ZDICT_isError(). + * On success `*parameters` contains the parameters selected. + * See ZDICT_trainFromBuffer() for details on failure modes. + * Note: ZDICT_optimizeTrainFromBuffer_fastCover() requires about 6 * 2^f bytes of memory for each thread. + */ +ZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer, + size_t dictBufferCapacity, const void* samplesBuffer, + const size_t* samplesSizes, unsigned nbSamples, + ZDICT_fastCover_params_t* parameters); + +typedef struct { + unsigned selectivityLevel; /* 0 means default; larger => select more => larger dictionary */ + ZDICT_params_t zParams; +} ZDICT_legacy_params_t; + +/*! ZDICT_trainFromBuffer_legacy(): + * Train a dictionary from an array of samples. + * Samples must be stored concatenated in a single flat buffer `samplesBuffer`, + * supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order. + * The resulting dictionary will be saved into `dictBuffer`. + * `parameters` is optional and can be provided with values set to 0 to mean "default". + * @return: size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) + * or an error code, which can be tested with ZDICT_isError(). + * See ZDICT_trainFromBuffer() for details on failure modes. + * Tips: In general, a reasonable dictionary has a size of ~ 100 KB. + * It's possible to select smaller or larger size, just by specifying `dictBufferCapacity`. + * In general, it's recommended to provide a few thousands samples, though this can vary a lot. + * It's recommended that total size of all samples be about ~x100 times the target size of dictionary. + * Note: ZDICT_trainFromBuffer_legacy() will send notifications into stderr if instructed to, using notificationLevel>0. + */ +ZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_legacy( + void* dictBuffer, size_t dictBufferCapacity, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples, + ZDICT_legacy_params_t parameters); + + +/* Deprecation warnings */ +/* It is generally possible to disable deprecation warnings from compiler, + for example with -Wno-deprecated-declarations for gcc + or _CRT_SECURE_NO_WARNINGS in Visual. + Otherwise, it's also possible to manually define ZDICT_DISABLE_DEPRECATE_WARNINGS */ +#ifdef ZDICT_DISABLE_DEPRECATE_WARNINGS +# define ZDICT_DEPRECATED(message) /* disable deprecation warnings */ +#else +# define ZDICT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ +# define ZDICT_DEPRECATED(message) [[deprecated(message)]] +# elif defined(__clang__) || (ZDICT_GCC_VERSION >= 405) +# define ZDICT_DEPRECATED(message) __attribute__((deprecated(message))) +# elif (ZDICT_GCC_VERSION >= 301) +# define ZDICT_DEPRECATED(message) __attribute__((deprecated)) +# elif defined(_MSC_VER) +# define ZDICT_DEPRECATED(message) __declspec(deprecated(message)) +# else +# pragma message("WARNING: You need to implement ZDICT_DEPRECATED for this compiler") +# define ZDICT_DEPRECATED(message) +# endif +#endif /* ZDICT_DISABLE_DEPRECATE_WARNINGS */ + +ZDICT_DEPRECATED("use ZDICT_finalizeDictionary() instead") +ZDICTLIB_STATIC_API +size_t ZDICT_addEntropyTablesFromBuffer(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity, + const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples); + + +#endif /* ZSTD_ZDICT_H_STATIC */ + +#if defined (__cplusplus) +} +#endif diff --git a/third_party/zstd/include/zstd/include/zstd.h b/third_party/zstd/include/zstd/include/zstd.h new file mode 100644 index 00000000000..5d1fef8a6b4 --- /dev/null +++ b/third_party/zstd/include/zstd/include/zstd.h @@ -0,0 +1,3089 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef ZSTD_H_235446 +#define ZSTD_H_235446 + +/* ====== Dependencies ======*/ +#include /* INT_MAX */ +#include /* size_t */ + + +/* ===== ZSTDLIB_API : control library symbols visibility ===== */ +#ifndef ZSTDLIB_VISIBLE + /* Backwards compatibility with old macro name */ +# ifdef ZSTDLIB_VISIBILITY +# define ZSTDLIB_VISIBLE ZSTDLIB_VISIBILITY +# elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) +# define ZSTDLIB_VISIBLE __attribute__ ((visibility ("default"))) +# else +# define ZSTDLIB_VISIBLE +# endif +#endif + +#ifndef ZSTDLIB_HIDDEN +# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) +# define ZSTDLIB_HIDDEN __attribute__ ((visibility ("hidden"))) +# else +# define ZSTDLIB_HIDDEN +# endif +#endif + +#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) +# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBLE +#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) +# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define ZSTDLIB_API ZSTDLIB_VISIBLE +#endif + +/* Deprecation warnings : + * Should these warnings be a problem, it is generally possible to disable them, + * typically with -Wno-deprecated-declarations for gcc or _CRT_SECURE_NO_WARNINGS in Visual. + * Otherwise, it's also possible to define ZSTD_DISABLE_DEPRECATE_WARNINGS. + */ +#ifdef ZSTD_DISABLE_DEPRECATE_WARNINGS +# define ZSTD_DEPRECATED(message) /* disable deprecation warnings */ +#else +# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ +# define ZSTD_DEPRECATED(message) [[deprecated(message)]] +# elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__) +# define ZSTD_DEPRECATED(message) __attribute__((deprecated(message))) +# elif defined(__GNUC__) && (__GNUC__ >= 3) +# define ZSTD_DEPRECATED(message) __attribute__((deprecated)) +# elif defined(_MSC_VER) +# define ZSTD_DEPRECATED(message) __declspec(deprecated(message)) +# else +# pragma message("WARNING: You need to implement ZSTD_DEPRECATED for this compiler") +# define ZSTD_DEPRECATED(message) +# endif +#endif /* ZSTD_DISABLE_DEPRECATE_WARNINGS */ + + +/******************************************************************************* + Introduction + + zstd, short for Zstandard, is a fast lossless compression algorithm, targeting + real-time compression scenarios at zlib-level and better compression ratios. + The zstd compression library provides in-memory compression and decompression + functions. + + The library supports regular compression levels from 1 up to ZSTD_maxCLevel(), + which is currently 22. Levels >= 20, labeled `--ultra`, should be used with + caution, as they require more memory. The library also offers negative + compression levels, which extend the range of speed vs. ratio preferences. + The lower the level, the faster the speed (at the cost of compression). + + Compression can be done in: + - a single step (described as Simple API) + - a single step, reusing a context (described as Explicit context) + - unbounded multiple steps (described as Streaming compression) + + The compression ratio achievable on small data can be highly improved using + a dictionary. Dictionary compression can be performed in: + - a single step (described as Simple dictionary API) + - a single step, reusing a dictionary (described as Bulk-processing + dictionary API) + + Advanced experimental functions can be accessed using + `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h. + + Advanced experimental APIs should never be used with a dynamically-linked + library. They are not "stable"; their definitions or signatures may change in + the future. Only static linking is allowed. +*******************************************************************************/ + +/*------ Version ------*/ +#define ZSTD_VERSION_MAJOR 1 +#define ZSTD_VERSION_MINOR 5 +#define ZSTD_VERSION_RELEASE 6 +#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) + +/*! ZSTD_versionNumber() : + * Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE). */ +ZSTDLIB_API unsigned ZSTD_versionNumber(void); + +#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE +#define ZSTD_QUOTE(str) #str +#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str) +#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION) + +/*! ZSTD_versionString() : + * Return runtime library version, like "1.4.5". Requires v1.3.0+. */ +ZSTDLIB_API const char* ZSTD_versionString(void); + +/* ************************************* + * Default constant + ***************************************/ +#ifndef ZSTD_CLEVEL_DEFAULT +# define ZSTD_CLEVEL_DEFAULT 3 +#endif + +/* ************************************* + * Constants + ***************************************/ + +/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */ +#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */ +#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */ +#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */ +#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0 + +#define ZSTD_BLOCKSIZELOG_MAX 17 +#define ZSTD_BLOCKSIZE_MAX (1<= ZSTD_compressBound(srcSize)` guarantees that zstd will have + * enough space to successfully compress the data. + * @return : compressed size written into `dst` (<= `dstCapacity), + * or an error code if it fails (which can be tested using ZSTD_isError()). */ +ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel); + +/*! ZSTD_decompress() : + * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. + * `dstCapacity` is an upper bound of originalSize to regenerate. + * If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data. + * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), + * or an errorCode if it fails (which can be tested using ZSTD_isError()). */ +ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity, + const void* src, size_t compressedSize); + +/*! ZSTD_getFrameContentSize() : requires v1.3.0+ + * `src` should point to the start of a ZSTD encoded frame. + * `srcSize` must be at least as large as the frame header. + * hint : any size >= `ZSTD_frameHeaderSize_max` is large enough. + * @return : - decompressed size of `src` frame content, if known + * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined + * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) + * note 1 : a 0 return value means the frame is valid but "empty". + * note 2 : decompressed size is an optional field, it may not be present, typically in streaming mode. + * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + * In which case, it's necessary to use streaming mode to decompress data. + * Optionally, application can rely on some implicit limit, + * as ZSTD_decompress() only needs an upper bound of decompressed size. + * (For example, data could be necessarily cut into blocks <= 16 KB). + * note 3 : decompressed size is always present when compression is completed using single-pass functions, + * such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict(). + * note 4 : decompressed size can be very large (64-bits value), + * potentially larger than what local system can handle as a single memory segment. + * In which case, it's necessary to use streaming mode to decompress data. + * note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified. + * Always ensure return value fits within application's authorized limits. + * Each application can set its own limits. + * note 6 : This function replaces ZSTD_getDecompressedSize() */ +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) +ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); + +/*! ZSTD_getDecompressedSize() : + * NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize(). + * Both functions work the same way, but ZSTD_getDecompressedSize() blends + * "empty", "unknown" and "error" results to the same return value (0), + * while ZSTD_getFrameContentSize() gives them separate return values. + * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */ +ZSTD_DEPRECATED("Replaced by ZSTD_getFrameContentSize") +ZSTDLIB_API +unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize); + +/*! ZSTD_findFrameCompressedSize() : Requires v1.4.0+ + * `src` should point to the start of a ZSTD frame or skippable frame. + * `srcSize` must be >= first frame size + * @return : the compressed size of the first frame starting at `src`, + * suitable to pass as `srcSize` to `ZSTD_decompress` or similar, + * or an error code if input is invalid */ +ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize); + + +/*====== Helper functions ======*/ +/* ZSTD_compressBound() : + * maximum compressed size in worst case single-pass scenario. + * When invoking `ZSTD_compress()` or any other one-pass compression function, + * it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize) + * as it eliminates one potential failure scenario, + * aka not enough room in dst buffer to write the compressed frame. + * Note : ZSTD_compressBound() itself can fail, if @srcSize > ZSTD_MAX_INPUT_SIZE . + * In which case, ZSTD_compressBound() will return an error code + * which can be tested using ZSTD_isError(). + * + * ZSTD_COMPRESSBOUND() : + * same as ZSTD_compressBound(), but as a macro. + * It can be used to produce constants, which can be useful for static allocation, + * for example to size a static array on stack. + * Will produce constant value 0 if srcSize too large. + */ +#define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00ULL : 0xFF00FF00U) +#define ZSTD_COMPRESSBOUND(srcSize) (((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) ? 0 : (srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */ +ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */ +/* ZSTD_isError() : + * Most ZSTD_* functions returning a size_t value can be tested for error, + * using ZSTD_isError(). + * @return 1 if error, 0 otherwise + */ +ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ +ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */ +ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed, requires v1.4.0+ */ +ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */ +ZSTDLIB_API int ZSTD_defaultCLevel(void); /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */ + + +/*************************************** +* Explicit context +***************************************/ +/*= Compression context + * When compressing many times, + * it is recommended to allocate a context just once, + * and reuse it for each successive compression operation. + * This will make workload friendlier for system's memory. + * Note : re-using context is just a speed / resource optimization. + * It doesn't change the compression ratio, which remains identical. + * Note 2 : In multi-threaded environments, + * use one different context per thread for parallel execution. + */ +typedef struct ZSTD_CCtx_s ZSTD_CCtx; +ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void); +ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /* accept NULL pointer */ + +/*! ZSTD_compressCCtx() : + * Same as ZSTD_compress(), using an explicit ZSTD_CCtx. + * Important : in order to mirror `ZSTD_compress()` behavior, + * this function compresses at the requested compression level, + * __ignoring any other advanced parameter__ . + * If any advanced parameter was set using the advanced API, + * they will all be reset. Only `compressionLevel` remains. + */ +ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + int compressionLevel); + +/*= Decompression context + * When decompressing many times, + * it is recommended to allocate a context only once, + * and reuse it for each successive compression operation. + * This will make workload friendlier for system's memory. + * Use one context per thread for parallel execution. */ +typedef struct ZSTD_DCtx_s ZSTD_DCtx; +ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void); +ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer */ + +/*! ZSTD_decompressDCtx() : + * Same as ZSTD_decompress(), + * requires an allocated ZSTD_DCtx. + * Compatible with sticky parameters (see below). + */ +ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + + +/********************************************* +* Advanced compression API (Requires v1.4.0+) +**********************************************/ + +/* API design : + * Parameters are pushed one by one into an existing context, + * using ZSTD_CCtx_set*() functions. + * Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame. + * "sticky" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` ! + * __They do not apply to one-shot variants such as ZSTD_compressCCtx()__ . + * + * It's possible to reset all parameters to "default" using ZSTD_CCtx_reset(). + * + * This API supersedes all other "advanced" API entry points in the experimental section. + * In the future, we expect to remove API entry points from experimental which are redundant with this API. + */ + + +/* Compression strategies, listed from fastest to strongest */ +typedef enum { ZSTD_fast=1, + ZSTD_dfast=2, + ZSTD_greedy=3, + ZSTD_lazy=4, + ZSTD_lazy2=5, + ZSTD_btlazy2=6, + ZSTD_btopt=7, + ZSTD_btultra=8, + ZSTD_btultra2=9 + /* note : new strategies _might_ be added in the future. + Only the order (from fast to strong) is guaranteed */ +} ZSTD_strategy; + +typedef enum { + + /* compression parameters + * Note: When compressing with a ZSTD_CDict these parameters are superseded + * by the parameters used to construct the ZSTD_CDict. + * See ZSTD_CCtx_refCDict() for more info (superseded-by-cdict). */ + ZSTD_c_compressionLevel=100, /* Set compression parameters according to pre-defined cLevel table. + * Note that exact compression parameters are dynamically determined, + * depending on both compression level and srcSize (when known). + * Default level is ZSTD_CLEVEL_DEFAULT==3. + * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT. + * Note 1 : it's possible to pass a negative compression level. + * Note 2 : setting a level does not automatically set all other compression parameters + * to default. Setting this will however eventually dynamically impact the compression + * parameters which have not been manually set. The manually set + * ones will 'stick'. */ + /* Advanced compression parameters : + * It's possible to pin down compression parameters to some specific values. + * In which case, these values are no longer dynamically selected by the compressor */ + ZSTD_c_windowLog=101, /* Maximum allowed back-reference distance, expressed as power of 2. + * This will set a memory budget for streaming decompression, + * with larger values requiring more memory + * and typically compressing more. + * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX. + * Special: value 0 means "use default windowLog". + * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT + * requires explicitly allowing such size at streaming decompression stage. */ + ZSTD_c_hashLog=102, /* Size of the initial probe table, as a power of 2. + * Resulting memory usage is (1 << (hashLog+2)). + * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX. + * Larger tables improve compression ratio of strategies <= dFast, + * and improve speed of strategies > dFast. + * Special: value 0 means "use default hashLog". */ + ZSTD_c_chainLog=103, /* Size of the multi-probe search table, as a power of 2. + * Resulting memory usage is (1 << (chainLog+2)). + * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX. + * Larger tables result in better and slower compression. + * This parameter is useless for "fast" strategy. + * It's still useful when using "dfast" strategy, + * in which case it defines a secondary probe table. + * Special: value 0 means "use default chainLog". */ + ZSTD_c_searchLog=104, /* Number of search attempts, as a power of 2. + * More attempts result in better and slower compression. + * This parameter is useless for "fast" and "dFast" strategies. + * Special: value 0 means "use default searchLog". */ + ZSTD_c_minMatch=105, /* Minimum size of searched matches. + * Note that Zstandard can still find matches of smaller size, + * it just tweaks its search algorithm to look for this size and larger. + * Larger values increase compression and decompression speed, but decrease ratio. + * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX. + * Note that currently, for all strategies < btopt, effective minimum is 4. + * , for all strategies > fast, effective maximum is 6. + * Special: value 0 means "use default minMatchLength". */ + ZSTD_c_targetLength=106, /* Impact of this field depends on strategy. + * For strategies btopt, btultra & btultra2: + * Length of Match considered "good enough" to stop search. + * Larger values make compression stronger, and slower. + * For strategy fast: + * Distance between match sampling. + * Larger values make compression faster, and weaker. + * Special: value 0 means "use default targetLength". */ + ZSTD_c_strategy=107, /* See ZSTD_strategy enum definition. + * The higher the value of selected strategy, the more complex it is, + * resulting in stronger and slower compression. + * Special: value 0 means "use default strategy". */ + + ZSTD_c_targetCBlockSize=130, /* v1.5.6+ + * Attempts to fit compressed block size into approximatively targetCBlockSize. + * Bound by ZSTD_TARGETCBLOCKSIZE_MIN and ZSTD_TARGETCBLOCKSIZE_MAX. + * Note that it's not a guarantee, just a convergence target (default:0). + * No target when targetCBlockSize == 0. + * This is helpful in low bandwidth streaming environments to improve end-to-end latency, + * when a client can make use of partial documents (a prominent example being Chrome). + * Note: this parameter is stable since v1.5.6. + * It was present as an experimental parameter in earlier versions, + * but it's not recommended using it with earlier library versions + * due to massive performance regressions. + */ + /* LDM mode parameters */ + ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching. + * This parameter is designed to improve compression ratio + * for large inputs, by finding large matches at long distance. + * It increases memory usage and window size. + * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB + * except when expressly set to a different value. + * Note: will be enabled by default if ZSTD_c_windowLog >= 128 MB and + * compression strategy >= ZSTD_btopt (== compression level 16+) */ + ZSTD_c_ldmHashLog=161, /* Size of the table for long distance matching, as a power of 2. + * Larger values increase memory usage and compression ratio, + * but decrease compression speed. + * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX + * default: windowlog - 7. + * Special: value 0 means "automatically determine hashlog". */ + ZSTD_c_ldmMinMatch=162, /* Minimum match size for long distance matcher. + * Larger/too small values usually decrease compression ratio. + * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX. + * Special: value 0 means "use default value" (default: 64). */ + ZSTD_c_ldmBucketSizeLog=163, /* Log size of each bucket in the LDM hash table for collision resolution. + * Larger values improve collision resolution but decrease compression speed. + * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX. + * Special: value 0 means "use default value" (default: 3). */ + ZSTD_c_ldmHashRateLog=164, /* Frequency of inserting/looking up entries into the LDM hash table. + * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN). + * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage. + * Larger values improve compression speed. + * Deviating far from default value will likely result in a compression ratio decrease. + * Special: value 0 means "automatically determine hashRateLog". */ + + /* frame parameters */ + ZSTD_c_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1) + * Content size must be known at the beginning of compression. + * This is automatically the case when using ZSTD_compress2(), + * For streaming scenarios, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */ + ZSTD_c_checksumFlag=201, /* A 32-bits checksum of content is written at end of frame (default:0) */ + ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */ + + /* multi-threading parameters */ + /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD). + * Otherwise, trying to set any other value than default (0) will be a no-op and return an error. + * In a situation where it's unknown if the linked library supports multi-threading or not, + * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property. + */ + ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel. + * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() : + * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller, + * while compression is performed in parallel, within worker thread(s). + * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end : + * in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call). + * More workers improve speed, but also increase memory usage. + * Default value is `0`, aka "single-threaded mode" : no worker is spawned, + * compression is performed inside Caller's thread, and all invocations are blocking */ + ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1. + * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads. + * 0 means default, which is dynamically determined based on compression parameters. + * Job size must be a minimum of overlap size, or ZSTDMT_JOBSIZE_MIN (= 512 KB), whichever is largest. + * The minimum size is automatically and transparently enforced. */ + ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size. + * The overlap size is an amount of data reloaded from previous job at the beginning of a new job. + * It helps preserve compression ratio, while each job is compressed in parallel. + * This value is enforced only when nbWorkers >= 1. + * Larger values increase compression ratio, but decrease speed. + * Possible values range from 0 to 9 : + * - 0 means "default" : value will be determined by the library, depending on strategy + * - 1 means "no overlap" + * - 9 means "full overlap", using a full window size. + * Each intermediate rank increases/decreases load size by a factor 2 : + * 9: full window; 8: w/2; 7: w/4; 6: w/8; 5:w/16; 4: w/32; 3:w/64; 2:w/128; 1:no overlap; 0:default + * default value varies between 6 and 9, depending on strategy */ + + /* note : additional experimental parameters are also available + * within the experimental section of the API. + * At the time of this writing, they include : + * ZSTD_c_rsyncable + * ZSTD_c_format + * ZSTD_c_forceMaxWindow + * ZSTD_c_forceAttachDict + * ZSTD_c_literalCompressionMode + * ZSTD_c_srcSizeHint + * ZSTD_c_enableDedicatedDictSearch + * ZSTD_c_stableInBuffer + * ZSTD_c_stableOutBuffer + * ZSTD_c_blockDelimiters + * ZSTD_c_validateSequences + * ZSTD_c_useBlockSplitter + * ZSTD_c_useRowMatchFinder + * ZSTD_c_prefetchCDictTables + * ZSTD_c_enableSeqProducerFallback + * ZSTD_c_maxBlockSize + * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. + * note : never ever use experimentalParam? names directly; + * also, the enums values themselves are unstable and can still change. + */ + ZSTD_c_experimentalParam1=500, + ZSTD_c_experimentalParam2=10, + ZSTD_c_experimentalParam3=1000, + ZSTD_c_experimentalParam4=1001, + ZSTD_c_experimentalParam5=1002, + /* was ZSTD_c_experimentalParam6=1003; is now ZSTD_c_targetCBlockSize */ + ZSTD_c_experimentalParam7=1004, + ZSTD_c_experimentalParam8=1005, + ZSTD_c_experimentalParam9=1006, + ZSTD_c_experimentalParam10=1007, + ZSTD_c_experimentalParam11=1008, + ZSTD_c_experimentalParam12=1009, + ZSTD_c_experimentalParam13=1010, + ZSTD_c_experimentalParam14=1011, + ZSTD_c_experimentalParam15=1012, + ZSTD_c_experimentalParam16=1013, + ZSTD_c_experimentalParam17=1014, + ZSTD_c_experimentalParam18=1015, + ZSTD_c_experimentalParam19=1016 +} ZSTD_cParameter; + +typedef struct { + size_t error; + int lowerBound; + int upperBound; +} ZSTD_bounds; + +/*! ZSTD_cParam_getBounds() : + * All parameters must belong to an interval with lower and upper bounds, + * otherwise they will either trigger an error or be automatically clamped. + * @return : a structure, ZSTD_bounds, which contains + * - an error status field, which must be tested using ZSTD_isError() + * - lower and upper bounds, both inclusive + */ +ZSTDLIB_API ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam); + +/*! ZSTD_CCtx_setParameter() : + * Set one compression parameter, selected by enum ZSTD_cParameter. + * All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds(). + * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter). + * Setting a parameter is generally only possible during frame initialization (before starting compression). + * Exception : when using multi-threading mode (nbWorkers >= 1), + * the following parameters can be updated _during_ compression (within same frame): + * => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy. + * new parameters will be active for next job only (after a flush()). + * @return : an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value); + +/*! ZSTD_CCtx_setPledgedSrcSize() : + * Total input data size to be compressed as a single frame. + * Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag. + * This value will also be controlled at end of frame, and trigger an error if not respected. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame. + * In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN. + * ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame. + * Note 2 : pledgedSrcSize is only valid once, for the next frame. + * It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN. + * Note 3 : Whenever all input data is provided and consumed in a single round, + * for example with ZSTD_compress2(), + * or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end), + * this value is automatically overridden by srcSize instead. + */ +ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize); + +typedef enum { + ZSTD_reset_session_only = 1, + ZSTD_reset_parameters = 2, + ZSTD_reset_session_and_parameters = 3 +} ZSTD_ResetDirective; + +/*! ZSTD_CCtx_reset() : + * There are 2 different things that can be reset, independently or jointly : + * - The session : will stop compressing current frame, and make CCtx ready to start a new one. + * Useful after an error, or to interrupt any ongoing compression. + * Any internal data not yet flushed is cancelled. + * Compression parameters and dictionary remain unchanged. + * They will be used to compress next frame. + * Resetting session never fails. + * - The parameters : changes all parameters back to "default". + * This also removes any reference to any dictionary or external sequence producer. + * Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing) + * otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError()) + * - Both : similar to resetting the session, followed by resetting parameters. + */ +ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset); + +/*! ZSTD_compress2() : + * Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API. + * (note that this entry point doesn't even expose a compression level parameter). + * ZSTD_compress2() always starts a new frame. + * Should cctx hold data from a previously unfinished frame, everything about it is forgotten. + * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() + * - The function is always blocking, returns when compression is completed. + * NOTE: Providing `dstCapacity >= ZSTD_compressBound(srcSize)` guarantees that zstd will have + * enough space to successfully compress the data, though it is possible it fails for other reasons. + * @return : compressed size written into `dst` (<= `dstCapacity), + * or an error code if it fails (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize); + + +/*********************************************** +* Advanced decompression API (Requires v1.4.0+) +************************************************/ + +/* The advanced API pushes parameters one by one into an existing DCtx context. + * Parameters are sticky, and remain valid for all following frames + * using the same DCtx context. + * It's possible to reset parameters to default values using ZSTD_DCtx_reset(). + * Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream(). + * Therefore, no new decompression function is necessary. + */ + +typedef enum { + + ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which + * the streaming API will refuse to allocate memory buffer + * in order to protect the host from unreasonable memory requirements. + * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. + * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT). + * Special: value 0 means "use default maximum windowLog". */ + + /* note : additional experimental parameters are also available + * within the experimental section of the API. + * At the time of this writing, they include : + * ZSTD_d_format + * ZSTD_d_stableOutBuffer + * ZSTD_d_forceIgnoreChecksum + * ZSTD_d_refMultipleDDicts + * ZSTD_d_disableHuffmanAssembly + * ZSTD_d_maxBlockSize + * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. + * note : never ever use experimentalParam? names directly + */ + ZSTD_d_experimentalParam1=1000, + ZSTD_d_experimentalParam2=1001, + ZSTD_d_experimentalParam3=1002, + ZSTD_d_experimentalParam4=1003, + ZSTD_d_experimentalParam5=1004, + ZSTD_d_experimentalParam6=1005 + +} ZSTD_dParameter; + +/*! ZSTD_dParam_getBounds() : + * All parameters must belong to an interval with lower and upper bounds, + * otherwise they will either trigger an error or be automatically clamped. + * @return : a structure, ZSTD_bounds, which contains + * - an error status field, which must be tested using ZSTD_isError() + * - both lower and upper bounds, inclusive + */ +ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam); + +/*! ZSTD_DCtx_setParameter() : + * Set one compression parameter, selected by enum ZSTD_dParameter. + * All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds(). + * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter). + * Setting a parameter is only possible during frame initialization (before starting decompression). + * @return : 0, or an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value); + +/*! ZSTD_DCtx_reset() : + * Return a DCtx to clean state. + * Session and parameters can be reset jointly or separately. + * Parameters can only be reset when no active frame is being decompressed. + * @return : 0, or an error code, which can be tested with ZSTD_isError() + */ +ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset); + + +/**************************** +* Streaming +****************************/ + +typedef struct ZSTD_inBuffer_s { + const void* src; /**< start of input buffer */ + size_t size; /**< size of input buffer */ + size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */ +} ZSTD_inBuffer; + +typedef struct ZSTD_outBuffer_s { + void* dst; /**< start of output buffer */ + size_t size; /**< size of output buffer */ + size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ +} ZSTD_outBuffer; + + + +/*-*********************************************************************** +* Streaming compression - HowTo +* +* A ZSTD_CStream object is required to track streaming operation. +* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources. +* ZSTD_CStream objects can be reused multiple times on consecutive compression operations. +* It is recommended to reuse ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory. +* +* For parallel execution, use one separate ZSTD_CStream per thread. +* +* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing. +* +* Parameters are sticky : when starting a new compression on the same context, +* it will reuse the same sticky parameters as previous compression session. +* When in doubt, it's recommended to fully initialize the context before usage. +* Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(), +* ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to +* set more specific parameters, the pledged source size, or load a dictionary. +* +* Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to +* consume input stream. The function will automatically update both `pos` +* fields within `input` and `output`. +* Note that the function may not consume the entire input, for example, because +* the output buffer is already full, in which case `input.pos < input.size`. +* The caller must check if input has been entirely consumed. +* If not, the caller must make some room to receive more compressed data, +* and then present again remaining input data. +* note: ZSTD_e_continue is guaranteed to make some forward progress when called, +* but doesn't guarantee maximal forward progress. This is especially relevant +* when compressing with multiple threads. The call won't block if it can +* consume some input, but if it can't it will wait for some, but not all, +* output to be flushed. +* @return : provides a minimum amount of data remaining to be flushed from internal buffers +* or an error code, which can be tested using ZSTD_isError(). +* +* At any moment, it's possible to flush whatever data might remain stuck within internal buffer, +* using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated. +* Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0). +* In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush. +* You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the +* operation. +* note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will +* block until the flush is complete or the output buffer is full. +* @return : 0 if internal buffers are entirely flushed, +* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), +* or an error code, which can be tested using ZSTD_isError(). +* +* Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame. +* It will perform a flush and write frame epilogue. +* The epilogue is required for decoders to consider a frame completed. +* flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush. +* You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to +* start a new frame. +* note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will +* block until the flush is complete or the output buffer is full. +* @return : 0 if frame fully completed and fully flushed, +* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size), +* or an error code, which can be tested using ZSTD_isError(). +* +* *******************************************************************/ + +typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */ + /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */ +/*===== ZSTD_CStream management functions =====*/ +ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void); +ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); /* accept NULL pointer */ + +/*===== Streaming compression functions =====*/ +typedef enum { + ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */ + ZSTD_e_flush=1, /* flush any data provided so far, + * it creates (at least) one new block, that can be decoded immediately on reception; + * frame will continue: any future data can still reference previously compressed data, improving compression. + * note : multithreaded compression will block to flush as much output as possible. */ + ZSTD_e_end=2 /* flush any remaining data _and_ close current frame. + * note that frame is only closed after compressed data is fully flushed (return value == 0). + * After that point, any additional data starts a new frame. + * note : each frame is independent (does not reference any content from previous frame). + : note : multithreaded compression will block to flush as much output as possible. */ +} ZSTD_EndDirective; + +/*! ZSTD_compressStream2() : Requires v1.4.0+ + * Behaves about the same as ZSTD_compressStream, with additional control on end directive. + * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*() + * - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode) + * - output->pos must be <= dstCapacity, input->pos must be <= srcSize + * - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit. + * - endOp must be a valid directive + * - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller. + * - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available, + * and then immediately returns, just indicating that there is some data remaining to be flushed. + * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte. + * - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking. + * - @return provides a minimum amount of data remaining to be flushed from internal buffers + * or an error code, which can be tested using ZSTD_isError(). + * if @return != 0, flush is not fully completed, there is still some data left within internal buffers. + * This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers. + * For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed. + * - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0), + * only ZSTD_e_end or ZSTD_e_flush operations are allowed. + * Before starting a new compression job, or changing compression parameters, + * it is required to fully flush internal buffers. + * - note: if an operation ends with an error, it may leave @cctx in an undefined state. + * Therefore, it's UB to invoke ZSTD_compressStream2() of ZSTD_compressStream() on such a state. + * In order to be re-employed after an error, a state must be reset, + * which can be done explicitly (ZSTD_CCtx_reset()), + * or is sometimes implied by methods starting a new compression job (ZSTD_initCStream(), ZSTD_compressCCtx()) + */ +ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input, + ZSTD_EndDirective endOp); + + +/* These buffer sizes are softly recommended. + * They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output. + * Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(), + * reducing the amount of memory shuffling and buffering, resulting in minor performance savings. + * + * However, note that these recommendations are from the perspective of a C caller program. + * If the streaming interface is invoked from some other language, + * especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo, + * a major performance rule is to reduce crossing such interface to an absolute minimum. + * It's not rare that performance ends being spent more into the interface, rather than compression itself. + * In which cases, prefer using large buffers, as large as practical, + * for both input and output, to reduce the nb of roundtrips. + */ +ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */ +ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */ + + +/* ***************************************************************************** + * This following is a legacy streaming API, available since v1.0+ . + * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2(). + * It is redundant, but remains fully supported. + ******************************************************************************/ + +/*! + * Equivalent to: + * + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) + * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); + * + * Note that ZSTD_initCStream() clears any previously set dictionary. Use the new API + * to compress with a dictionary. + */ +ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel); +/*! + * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue). + * NOTE: The return value is different. ZSTD_compressStream() returns a hint for + * the next read size (if non-zero and not an error). ZSTD_compressStream2() + * returns the minimum nb of bytes left to flush (if non-zero and not an error). + */ +ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input); +/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */ +ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); +/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */ +ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output); + + +/*-*************************************************************************** +* Streaming decompression - HowTo +* +* A ZSTD_DStream object is required to track streaming operations. +* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources. +* ZSTD_DStream objects can be reused multiple times. +* +* Use ZSTD_initDStream() to start a new decompression operation. +* @return : recommended first input size +* Alternatively, use advanced API to set specific properties. +* +* Use ZSTD_decompressStream() repetitively to consume your input. +* The function will update both `pos` fields. +* If `input.pos < input.size`, some input has not been consumed. +* It's up to the caller to present again remaining data. +* The function tries to flush all data decoded immediately, respecting output buffer size. +* If `output.pos < output.size`, decoder has flushed everything it could. +* But if `output.pos == output.size`, there might be some data left within internal buffers., +* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer. +* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX. +* @return : 0 when a frame is completely decoded and fully flushed, +* or an error code, which can be tested using ZSTD_isError(), +* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame : +* the return value is a suggested next input size (just a hint for better latency) +* that will never request more than the remaining frame size. +* *******************************************************************************/ + +typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */ + /* For compatibility with versions <= v1.2.0, prefer differentiating them. */ +/*===== ZSTD_DStream management functions =====*/ +ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void); +ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); /* accept NULL pointer */ + +/*===== Streaming decompression functions =====*/ + +/*! ZSTD_initDStream() : + * Initialize/reset DStream state for new decompression operation. + * Call before new decompression operation using same DStream. + * + * Note : This function is redundant with the advanced API and equivalent to: + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * ZSTD_DCtx_refDDict(zds, NULL); + */ +ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds); + +/*! ZSTD_decompressStream() : + * Streaming decompression function. + * Call repetitively to consume full input updating it as necessary. + * Function will update both input and output `pos` fields exposing current state via these fields: + * - `input.pos < input.size`, some input remaining and caller should provide remaining input + * on the next call. + * - `output.pos < output.size`, decoder finished and flushed all remaining buffers. + * - `output.pos == output.size`, potentially uncflushed data present in the internal buffers, + * call ZSTD_decompressStream() again to flush remaining data to output. + * Note : with no additional input, amount of data flushed <= ZSTD_BLOCKSIZE_MAX. + * + * @return : 0 when a frame is completely decoded and fully flushed, + * or an error code, which can be tested using ZSTD_isError(), + * or any other value > 0, which means there is some decoding or flushing to do to complete current frame. + * + * Note: when an operation returns with an error code, the @zds state may be left in undefined state. + * It's UB to invoke `ZSTD_decompressStream()` on such a state. + * In order to re-use such a state, it must be first reset, + * which can be done explicitly (`ZSTD_DCtx_reset()`), + * or is implied for operations starting some new decompression job (`ZSTD_initDStream`, `ZSTD_decompressDCtx()`, `ZSTD_decompress_usingDict()`) + */ +ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input); + +ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */ +ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */ + + +/************************** +* Simple dictionary API +***************************/ +/*! ZSTD_compress_usingDict() : + * Compression at an explicit compression level using a Dictionary. + * A dictionary can be any arbitrary data segment (also called a prefix), + * or a buffer with specified information (see zdict.h). + * Note : This function loads the dictionary, resulting in significant startup delay. + * It's intended for a dictionary used only once. + * Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */ +ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize, + int compressionLevel); + +/*! ZSTD_decompress_usingDict() : + * Decompression using a known Dictionary. + * Dictionary must be identical to the one used during compression. + * Note : This function loads the dictionary, resulting in significant startup delay. + * It's intended for a dictionary used only once. + * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */ +ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize); + + +/*********************************** + * Bulk processing dictionary API + **********************************/ +typedef struct ZSTD_CDict_s ZSTD_CDict; + +/*! ZSTD_createCDict() : + * When compressing multiple messages or blocks using the same dictionary, + * it's recommended to digest the dictionary only once, since it's a costly operation. + * ZSTD_createCDict() will create a state from digesting a dictionary. + * The resulting state can be used for future compression operations with very limited startup cost. + * ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. + * @dictBuffer can be released after ZSTD_CDict creation, because its content is copied within CDict. + * Note 1 : Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate @dictBuffer content. + * Note 2 : A ZSTD_CDict can be created from an empty @dictBuffer, + * in which case the only thing that it transports is the @compressionLevel. + * This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively, + * expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. */ +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, + int compressionLevel); + +/*! ZSTD_freeCDict() : + * Function frees memory allocated by ZSTD_createCDict(). + * If a NULL pointer is passed, no operation is performed. */ +ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict); + +/*! ZSTD_compress_usingCDict() : + * Compression using a digested Dictionary. + * Recommended when same dictionary is used multiple times. + * Note : compression level is _decided at dictionary creation time_, + * and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */ +ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict); + + +typedef struct ZSTD_DDict_s ZSTD_DDict; + +/*! ZSTD_createDDict() : + * Create a digested dictionary, ready to start decompression operation without startup delay. + * dictBuffer can be released after DDict creation, as its content is copied inside DDict. */ +ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize); + +/*! ZSTD_freeDDict() : + * Function frees memory allocated with ZSTD_createDDict() + * If a NULL pointer is passed, no operation is performed. */ +ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict); + +/*! ZSTD_decompress_usingDDict() : + * Decompression using a digested Dictionary. + * Recommended when same dictionary is used multiple times. */ +ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_DDict* ddict); + + +/******************************** + * Dictionary helper functions + *******************************/ + +/*! ZSTD_getDictID_fromDict() : Requires v1.4.0+ + * Provides the dictID stored within dictionary. + * if @return == 0, the dictionary is not conformant with Zstandard specification. + * It can still be loaded, but as a content-only dictionary. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize); + +/*! ZSTD_getDictID_fromCDict() : Requires v1.5.0+ + * Provides the dictID of the dictionary loaded into `cdict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict); + +/*! ZSTD_getDictID_fromDDict() : Requires v1.4.0+ + * Provides the dictID of the dictionary loaded into `ddict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict); + +/*! ZSTD_getDictID_fromFrame() : Requires v1.4.0+ + * Provides the dictID required to decompressed the frame stored within `src`. + * If @return == 0, the dictID could not be decoded. + * This could for one of the following reasons : + * - The frame does not require a dictionary to be decoded (most common case). + * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden piece of information. + * Note : this use case also happens when using a non-conformant dictionary. + * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`). + * - This is not a Zstandard frame. + * When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize); + + +/******************************************************************************* + * Advanced dictionary and prefix API (Requires v1.4.0+) + * + * This API allows dictionaries to be used with ZSTD_compress2(), + * ZSTD_compressStream2(), and ZSTD_decompressDCtx(). + * Dictionaries are sticky, they remain valid when same context is reused, + * they only reset when the context is reset + * with ZSTD_reset_parameters or ZSTD_reset_session_and_parameters. + * In contrast, Prefixes are single-use. + ******************************************************************************/ + + +/*! ZSTD_CCtx_loadDictionary() : Requires v1.4.0+ + * Create an internal CDict from `dict` buffer. + * Decompression will have to use same dictionary. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary, + * meaning "return to no-dictionary mode". + * Note 1 : Dictionary is sticky, it will be used for all future compressed frames, + * until parameters are reset, a new dictionary is loaded, or the dictionary + * is explicitly invalidated by loading a NULL dictionary. + * Note 2 : Loading a dictionary involves building tables. + * It's also a CPU consuming operation, with non-negligible impact on latency. + * Tables are dependent on compression parameters, and for this reason, + * compression parameters can no longer be changed after loading a dictionary. + * Note 3 :`dict` content will be copied internally. + * Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead. + * In such a case, dictionary buffer must outlive its users. + * Note 4 : Use ZSTD_CCtx_loadDictionary_advanced() + * to precisely select how dictionary content must be interpreted. + * Note 5 : This method does not benefit from LDM (long distance mode). + * If you want to employ LDM on some large dictionary content, + * prefer employing ZSTD_CCtx_refPrefix() described below. + */ +ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); + +/*! ZSTD_CCtx_refCDict() : Requires v1.4.0+ + * Reference a prepared dictionary, to be used for all future compressed frames. + * Note that compression parameters are enforced from within CDict, + * and supersede any compression parameter previously set within CCtx. + * The parameters ignored are labelled as "superseded-by-cdict" in the ZSTD_cParameter enum docs. + * The ignored parameters will be used again if the CCtx is returned to no-dictionary mode. + * The dictionary will remain valid for future compressed frames using same CCtx. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special : Referencing a NULL CDict means "return to no-dictionary mode". + * Note 1 : Currently, only one dictionary can be managed. + * Referencing a new dictionary effectively "discards" any previous one. + * Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */ +ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); + +/*! ZSTD_CCtx_refPrefix() : Requires v1.4.0+ + * Reference a prefix (single-usage dictionary) for next compressed frame. + * A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end). + * Decompression will need same prefix to properly regenerate data. + * Compressing with a prefix is similar in outcome as performing a diff and compressing it, + * but performs much faster, especially during decompression (compression speed is tunable with compression level). + * This method is compatible with LDM (long distance mode). + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary + * Note 1 : Prefix buffer is referenced. It **must** outlive compression. + * Its content must remain unmodified during compression. + * Note 2 : If the intention is to diff some large src data blob with some prior version of itself, + * ensure that the window size is large enough to contain the entire source. + * See ZSTD_c_windowLog. + * Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters. + * It's a CPU consuming operation, with non-negligible impact on latency. + * If there is a need to use the same prefix multiple times, consider loadDictionary instead. + * Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent). + * Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */ +ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, + const void* prefix, size_t prefixSize); + +/*! ZSTD_DCtx_loadDictionary() : Requires v1.4.0+ + * Create an internal DDict from dict buffer, to be used to decompress all future frames. + * The dictionary remains valid for all future frames, until explicitly invalidated, or + * a new dictionary is loaded. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary, + * meaning "return to no-dictionary mode". + * Note 1 : Loading a dictionary involves building tables, + * which has a non-negligible impact on CPU usage and latency. + * It's recommended to "load once, use many times", to amortize the cost + * Note 2 :`dict` content will be copied internally, so `dict` can be released after loading. + * Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead. + * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of + * how dictionary content is loaded and interpreted. + */ +ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); + +/*! ZSTD_DCtx_refDDict() : Requires v1.4.0+ + * Reference a prepared dictionary, to be used to decompress next frames. + * The dictionary remains active for decompression of future frames using same DCtx. + * + * If called with ZSTD_d_refMultipleDDicts enabled, repeated calls of this function + * will store the DDict references in a table, and the DDict used for decompression + * will be determined at decompression time, as per the dict ID in the frame. + * The memory for the table is allocated on the first call to refDDict, and can be + * freed with ZSTD_freeDCtx(). + * + * If called with ZSTD_d_refMultipleDDicts disabled (the default), only one dictionary + * will be managed, and referencing a dictionary effectively "discards" any previous one. + * + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Special: referencing a NULL DDict means "return to no-dictionary mode". + * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx. + */ +ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); + +/*! ZSTD_DCtx_refPrefix() : Requires v1.4.0+ + * Reference a prefix (single-usage dictionary) to decompress next frame. + * This is the reverse operation of ZSTD_CCtx_refPrefix(), + * and must use the same prefix as the one used during compression. + * Prefix is **only used once**. Reference is discarded at end of frame. + * End of frame is reached when ZSTD_decompressStream() returns 0. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary + * Note 2 : Prefix buffer is referenced. It **must** outlive decompression. + * Prefix buffer must remain unmodified up to the end of frame, + * reached when ZSTD_decompressStream() returns 0. + * Note 3 : By default, the prefix is treated as raw content (ZSTD_dct_rawContent). + * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section) + * Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost. + * A full dictionary is more costly, as it requires building tables. + */ +ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, + const void* prefix, size_t prefixSize); + +/* === Memory management === */ + +/*! ZSTD_sizeof_*() : Requires v1.4.0+ + * These functions give the _current_ memory usage of selected object. + * Note that object memory usage can evolve (increase or decrease) over time. */ +ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx); +ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx); +ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs); +ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds); +ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict); +ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); + +#endif /* ZSTD_H_235446 */ + + +/* ************************************************************************************** + * ADVANCED AND EXPERIMENTAL FUNCTIONS + **************************************************************************************** + * The definitions in the following section are considered experimental. + * They are provided for advanced scenarios. + * They should never be used with a dynamic library, as prototypes may change in the future. + * Use them only in association with static linking. + * ***************************************************************************************/ + +#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY) +#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY + +/* This can be overridden externally to hide static symbols. */ +#ifndef ZSTDLIB_STATIC_API +# if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) +# define ZSTDLIB_STATIC_API __declspec(dllexport) ZSTDLIB_VISIBLE +# elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) +# define ZSTDLIB_STATIC_API __declspec(dllimport) ZSTDLIB_VISIBLE +# else +# define ZSTDLIB_STATIC_API ZSTDLIB_VISIBLE +# endif +#endif + +/**************************************************************************************** + * experimental API (static linking only) + **************************************************************************************** + * The following symbols and constants + * are not planned to join "stable API" status in the near future. + * They can still change in future versions. + * Some of them are planned to remain in the static_only section indefinitely. + * Some of them might be removed in the future (especially when redundant with existing stable functions) + * ***************************************************************************************/ + +#define ZSTD_FRAMEHEADERSIZE_PREFIX(format) ((format) == ZSTD_f_zstd1 ? 5 : 1) /* minimum input size required to query frame header size */ +#define ZSTD_FRAMEHEADERSIZE_MIN(format) ((format) == ZSTD_f_zstd1 ? 6 : 2) +#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* can be useful for static allocation */ +#define ZSTD_SKIPPABLEHEADERSIZE 8 + +/* compression parameter bounds */ +#define ZSTD_WINDOWLOG_MAX_32 30 +#define ZSTD_WINDOWLOG_MAX_64 31 +#define ZSTD_WINDOWLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64)) +#define ZSTD_WINDOWLOG_MIN 10 +#define ZSTD_HASHLOG_MAX ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30) +#define ZSTD_HASHLOG_MIN 6 +#define ZSTD_CHAINLOG_MAX_32 29 +#define ZSTD_CHAINLOG_MAX_64 30 +#define ZSTD_CHAINLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64)) +#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN +#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1) +#define ZSTD_SEARCHLOG_MIN 1 +#define ZSTD_MINMATCH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */ +#define ZSTD_MINMATCH_MIN 3 /* only for ZSTD_btopt+, faster strategies are limited to 4 */ +#define ZSTD_TARGETLENGTH_MAX ZSTD_BLOCKSIZE_MAX +#define ZSTD_TARGETLENGTH_MIN 0 /* note : comparing this constant to an unsigned results in a tautological test */ +#define ZSTD_STRATEGY_MIN ZSTD_fast +#define ZSTD_STRATEGY_MAX ZSTD_btultra2 +#define ZSTD_BLOCKSIZE_MAX_MIN (1 << 10) /* The minimum valid max blocksize. Maximum blocksizes smaller than this make compressBound() inaccurate. */ + + +#define ZSTD_OVERLAPLOG_MIN 0 +#define ZSTD_OVERLAPLOG_MAX 9 + +#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27 /* by default, the streaming decoder will refuse any frame + * requiring larger than (1< 0: + * If litLength != 0: + * rep == 1 --> offset == repeat_offset_1 + * rep == 2 --> offset == repeat_offset_2 + * rep == 3 --> offset == repeat_offset_3 + * If litLength == 0: + * rep == 1 --> offset == repeat_offset_2 + * rep == 2 --> offset == repeat_offset_3 + * rep == 3 --> offset == repeat_offset_1 - 1 + * + * Note: This field is optional. ZSTD_generateSequences() will calculate the value of + * 'rep', but repeat offsets do not necessarily need to be calculated from an external + * sequence provider's perspective. For example, ZSTD_compressSequences() does not + * use this 'rep' field at all (as of now). + */ +} ZSTD_Sequence; + +typedef struct { + unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */ + unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ + unsigned hashLog; /**< dispatch table : larger == faster, more memory */ + unsigned searchLog; /**< nb of searches : larger == more compression, slower */ + unsigned minMatch; /**< match length searched : larger == faster decompression, sometimes less compression */ + unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */ + ZSTD_strategy strategy; /**< see ZSTD_strategy definition above */ +} ZSTD_compressionParameters; + +typedef struct { + int contentSizeFlag; /**< 1: content size will be in frame header (when known) */ + int checksumFlag; /**< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */ + int noDictIDFlag; /**< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */ +} ZSTD_frameParameters; + +typedef struct { + ZSTD_compressionParameters cParams; + ZSTD_frameParameters fParams; +} ZSTD_parameters; + +typedef enum { + ZSTD_dct_auto = 0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */ + ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */ + ZSTD_dct_fullDict = 2 /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */ +} ZSTD_dictContentType_e; + +typedef enum { + ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */ + ZSTD_dlm_byRef = 1 /**< Reference dictionary content -- the dictionary buffer must outlive its users. */ +} ZSTD_dictLoadMethod_e; + +typedef enum { + ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */ + ZSTD_f_zstd1_magicless = 1 /* Variant of zstd frame format, without initial 4-bytes magic number. + * Useful to save 4 bytes per generated frame. + * Decoder cannot recognise automatically this format, requiring this instruction. */ +} ZSTD_format_e; + +typedef enum { + /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */ + ZSTD_d_validateChecksum = 0, + ZSTD_d_ignoreChecksum = 1 +} ZSTD_forceIgnoreChecksum_e; + +typedef enum { + /* Note: this enum controls ZSTD_d_refMultipleDDicts */ + ZSTD_rmd_refSingleDDict = 0, + ZSTD_rmd_refMultipleDDicts = 1 +} ZSTD_refMultipleDDicts_e; + +typedef enum { + /* Note: this enum and the behavior it controls are effectively internal + * implementation details of the compressor. They are expected to continue + * to evolve and should be considered only in the context of extremely + * advanced performance tuning. + * + * Zstd currently supports the use of a CDict in three ways: + * + * - The contents of the CDict can be copied into the working context. This + * means that the compression can search both the dictionary and input + * while operating on a single set of internal tables. This makes + * the compression faster per-byte of input. However, the initial copy of + * the CDict's tables incurs a fixed cost at the beginning of the + * compression. For small compressions (< 8 KB), that copy can dominate + * the cost of the compression. + * + * - The CDict's tables can be used in-place. In this model, compression is + * slower per input byte, because the compressor has to search two sets of + * tables. However, this model incurs no start-up cost (as long as the + * working context's tables can be reused). For small inputs, this can be + * faster than copying the CDict's tables. + * + * - The CDict's tables are not used at all, and instead we use the working + * context alone to reload the dictionary and use params based on the source + * size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict(). + * This method is effective when the dictionary sizes are very small relative + * to the input size, and the input size is fairly large to begin with. + * + * Zstd has a simple internal heuristic that selects which strategy to use + * at the beginning of a compression. However, if experimentation shows that + * Zstd is making poor choices, it is possible to override that choice with + * this enum. + */ + ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */ + ZSTD_dictForceAttach = 1, /* Never copy the dictionary. */ + ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */ + ZSTD_dictForceLoad = 3 /* Always reload the dictionary */ +} ZSTD_dictAttachPref_e; + +typedef enum { + ZSTD_lcm_auto = 0, /**< Automatically determine the compression mode based on the compression level. + * Negative compression levels will be uncompressed, and positive compression + * levels will be compressed. */ + ZSTD_lcm_huffman = 1, /**< Always attempt Huffman compression. Uncompressed literals will still be + * emitted if Huffman compression is not profitable. */ + ZSTD_lcm_uncompressed = 2 /**< Always emit uncompressed literals. */ +} ZSTD_literalCompressionMode_e; + +typedef enum { + /* Note: This enum controls features which are conditionally beneficial. Zstd typically will make a final + * decision on whether or not to enable the feature (ZSTD_ps_auto), but setting the switch to ZSTD_ps_enable + * or ZSTD_ps_disable allow for a force enable/disable the feature. + */ + ZSTD_ps_auto = 0, /* Let the library automatically determine whether the feature shall be enabled */ + ZSTD_ps_enable = 1, /* Force-enable the feature */ + ZSTD_ps_disable = 2 /* Do not use the feature */ +} ZSTD_paramSwitch_e; + +/*************************************** +* Frame header and size functions +***************************************/ + +/*! ZSTD_findDecompressedSize() : + * `src` should point to the start of a series of ZSTD encoded and/or skippable frames + * `srcSize` must be the _exact_ size of this series + * (i.e. there should be a frame boundary at `src + srcSize`) + * @return : - decompressed size of all data in all successive frames + * - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN + * - if an error occurred: ZSTD_CONTENTSIZE_ERROR + * + * note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. + * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. + * In which case, it's necessary to use streaming mode to decompress data. + * note 2 : decompressed size is always present when compression is done with ZSTD_compress() + * note 3 : decompressed size can be very large (64-bits value), + * potentially larger than what local system can handle as a single memory segment. + * In which case, it's necessary to use streaming mode to decompress data. + * note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. + * Always ensure result fits within application's authorized limits. + * Each application can set its own limits. + * note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to + * read each contained frame header. This is fast as most of the data is skipped, + * however it does mean that all frame data must be present and valid. */ +ZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); + +/*! ZSTD_decompressBound() : + * `src` should point to the start of a series of ZSTD encoded and/or skippable frames + * `srcSize` must be the _exact_ size of this series + * (i.e. there should be a frame boundary at `src + srcSize`) + * @return : - upper-bound for the decompressed size of all data in all successive frames + * - if an error occurred: ZSTD_CONTENTSIZE_ERROR + * + * note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame. + * note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`. + * in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value. + * note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by: + * upper-bound = # blocks * min(128 KB, Window_Size) + */ +ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize); + +/*! ZSTD_frameHeaderSize() : + * srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX. + * @return : size of the Frame Header, + * or an error code (if srcSize is too small) */ +ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); + +typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e; +typedef struct { + unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */ + unsigned long long windowSize; /* can be very large, up to <= frameContentSize */ + unsigned blockSizeMax; + ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */ + unsigned headerSize; + unsigned dictID; + unsigned checksumFlag; + unsigned _reserved1; + unsigned _reserved2; +} ZSTD_frameHeader; + +/*! ZSTD_getFrameHeader() : + * decode Frame Header, or requires larger `srcSize`. + * @return : 0, `zfhPtr` is correctly filled, + * >0, `srcSize` is too small, value is wanted `srcSize` amount, + * or an error code, which can be tested using ZSTD_isError() */ +ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ +/*! ZSTD_getFrameHeader_advanced() : + * same as ZSTD_getFrameHeader(), + * with added capability to select a format (like ZSTD_f_zstd1_magicless) */ +ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format); + +/*! ZSTD_decompressionMargin() : + * Zstd supports in-place decompression, where the input and output buffers overlap. + * In this case, the output buffer must be at least (Margin + Output_Size) bytes large, + * and the input buffer must be at the end of the output buffer. + * + * _______________________ Output Buffer ________________________ + * | | + * | ____ Input Buffer ____| + * | | | + * v v v + * |---------------------------------------|-----------|----------| + * ^ ^ ^ + * |___________________ Output_Size ___________________|_ Margin _| + * + * NOTE: See also ZSTD_DECOMPRESSION_MARGIN(). + * NOTE: This applies only to single-pass decompression through ZSTD_decompress() or + * ZSTD_decompressDCtx(). + * NOTE: This function supports multi-frame input. + * + * @param src The compressed frame(s) + * @param srcSize The size of the compressed frame(s) + * @returns The decompression margin or an error that can be checked with ZSTD_isError(). + */ +ZSTDLIB_STATIC_API size_t ZSTD_decompressionMargin(const void* src, size_t srcSize); + +/*! ZSTD_DECOMPRESS_MARGIN() : + * Similar to ZSTD_decompressionMargin(), but instead of computing the margin from + * the compressed frame, compute it from the original size and the blockSizeLog. + * See ZSTD_decompressionMargin() for details. + * + * WARNING: This macro does not support multi-frame input, the input must be a single + * zstd frame. If you need that support use the function, or implement it yourself. + * + * @param originalSize The original uncompressed size of the data. + * @param blockSize The block size == MIN(windowSize, ZSTD_BLOCKSIZE_MAX). + * Unless you explicitly set the windowLog smaller than + * ZSTD_BLOCKSIZELOG_MAX you can just use ZSTD_BLOCKSIZE_MAX. + */ +#define ZSTD_DECOMPRESSION_MARGIN(originalSize, blockSize) ((size_t)( \ + ZSTD_FRAMEHEADERSIZE_MAX /* Frame header */ + \ + 4 /* checksum */ + \ + ((originalSize) == 0 ? 0 : 3 * (((originalSize) + (blockSize) - 1) / blockSize)) /* 3 bytes per block */ + \ + (blockSize) /* One block of margin */ \ + )) + +typedef enum { + ZSTD_sf_noBlockDelimiters = 0, /* Representation of ZSTD_Sequence has no block delimiters, sequences only */ + ZSTD_sf_explicitBlockDelimiters = 1 /* Representation of ZSTD_Sequence contains explicit block delimiters */ +} ZSTD_sequenceFormat_e; + +/*! ZSTD_sequenceBound() : + * `srcSize` : size of the input buffer + * @return : upper-bound for the number of sequences that can be generated + * from a buffer of srcSize bytes + * + * note : returns number of sequences - to get bytes, multiply by sizeof(ZSTD_Sequence). + */ +ZSTDLIB_STATIC_API size_t ZSTD_sequenceBound(size_t srcSize); + +/*! ZSTD_generateSequences() : + * WARNING: This function is meant for debugging and informational purposes ONLY! + * Its implementation is flawed, and it will be deleted in a future version. + * It is not guaranteed to succeed, as there are several cases where it will give + * up and fail. You should NOT use this function in production code. + * + * This function is deprecated, and will be removed in a future version. + * + * Generate sequences using ZSTD_compress2(), given a source buffer. + * + * @param zc The compression context to be used for ZSTD_compress2(). Set any + * compression parameters you need on this context. + * @param outSeqs The output sequences buffer of size @p outSeqsSize + * @param outSeqsSize The size of the output sequences buffer. + * ZSTD_sequenceBound(srcSize) is an upper bound on the number + * of sequences that can be generated. + * @param src The source buffer to generate sequences from of size @p srcSize. + * @param srcSize The size of the source buffer. + * + * Each block will end with a dummy sequence + * with offset == 0, matchLength == 0, and litLength == length of last literals. + * litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0) + * simply acts as a block delimiter. + * + * @returns The number of sequences generated, necessarily less than + * ZSTD_sequenceBound(srcSize), or an error code that can be checked + * with ZSTD_isError(). + */ +ZSTD_DEPRECATED("For debugging only, will be replaced by ZSTD_extractSequences()") +ZSTDLIB_STATIC_API size_t +ZSTD_generateSequences(ZSTD_CCtx* zc, + ZSTD_Sequence* outSeqs, size_t outSeqsSize, + const void* src, size_t srcSize); + +/*! ZSTD_mergeBlockDelimiters() : + * Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals + * by merging them into the literals of the next sequence. + * + * As such, the final generated result has no explicit representation of block boundaries, + * and the final last literals segment is not represented in the sequences. + * + * The output of this function can be fed into ZSTD_compressSequences() with CCtx + * setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters + * @return : number of sequences left after merging + */ +ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize); + +/*! ZSTD_compressSequences() : + * Compress an array of ZSTD_Sequence, associated with @src buffer, into dst. + * @src contains the entire input (not just the literals). + * If @srcSize > sum(sequence.length), the remaining bytes are considered all literals + * If a dictionary is included, then the cctx should reference the dict. (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.) + * The entire source is compressed into a single frame. + * + * The compression behavior changes based on cctx params. In particular: + * If ZSTD_c_blockDelimiters == ZSTD_sf_noBlockDelimiters, the array of ZSTD_Sequence is expected to contain + * no block delimiters (defined in ZSTD_Sequence). Block boundaries are roughly determined based on + * the block size derived from the cctx, and sequences may be split. This is the default setting. + * + * If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain + * block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided. + * + * If ZSTD_c_validateSequences == 0, this function will blindly accept the sequences provided. Invalid sequences cause undefined + * behavior. If ZSTD_c_validateSequences == 1, then if sequence is invalid (see doc/zstd_compression_format.md for + * specifics regarding offset/matchlength requirements) then the function will bail out and return an error. + * + * In addition to the two adjustable experimental params, there are other important cctx params. + * - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN. + * - ZSTD_c_compressionLevel accordingly adjusts the strength of the entropy coder, as it would in typical compression. + * - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset + * is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md + * + * Note: Repcodes are, as of now, always re-calculated within this function, so ZSTD_Sequence::rep is unused. + * Note 2: Once we integrate ability to ingest repcodes, the explicit block delims mode must respect those repcodes exactly, + * and cannot emit an RLE block that disagrees with the repcode history + * @return : final compressed size, or a ZSTD error code. + */ +ZSTDLIB_STATIC_API size_t +ZSTD_compressSequences( ZSTD_CCtx* cctx, void* dst, size_t dstSize, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize); + + +/*! ZSTD_writeSkippableFrame() : + * Generates a zstd skippable frame containing data given by src, and writes it to dst buffer. + * + * Skippable frames begin with a 4-byte magic number. There are 16 possible choices of magic number, + * ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15. + * As such, the parameter magicVariant controls the exact skippable frame magic number variant used, so + * the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant. + * + * Returns an error if destination buffer is not large enough, if the source size is not representable + * with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid). + * + * @return : number of bytes written or a ZSTD error. + */ +ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity, + const void* src, size_t srcSize, unsigned magicVariant); + +/*! ZSTD_readSkippableFrame() : + * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer. + * + * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written, + * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested + * in the magicVariant. + * + * Returns an error if destination buffer is not large enough, or if the frame is not skippable. + * + * @return : number of bytes written or a ZSTD error. + */ +ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant, + const void* src, size_t srcSize); + +/*! ZSTD_isSkippableFrame() : + * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame. + */ +ZSTDLIB_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size); + + + +/*************************************** +* Memory management +***************************************/ + +/*! ZSTD_estimate*() : + * These functions make it possible to estimate memory usage + * of a future {D,C}Ctx, before its creation. + * This is useful in combination with ZSTD_initStatic(), + * which makes it possible to employ a static buffer for ZSTD_CCtx* state. + * + * ZSTD_estimateCCtxSize() will provide a memory budget large enough + * to compress data of any size using one-shot compression ZSTD_compressCCtx() or ZSTD_compress2() + * associated with any compression level up to max specified one. + * The estimate will assume the input may be arbitrarily large, + * which is the worst case. + * + * Note that the size estimation is specific for one-shot compression, + * it is not valid for streaming (see ZSTD_estimateCStreamSize*()) + * nor other potential ways of using a ZSTD_CCtx* state. + * + * When srcSize can be bound by a known and rather "small" value, + * this knowledge can be used to provide a tighter budget estimation + * because the ZSTD_CCtx* state will need less memory for small inputs. + * This tighter estimation can be provided by employing more advanced functions + * ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(), + * and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter(). + * Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits. + * + * Note : only single-threaded compression is supported. + * ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1. + */ +ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int maxCompressionLevel); +ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); +ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params); +ZSTDLIB_STATIC_API size_t ZSTD_estimateDCtxSize(void); + +/*! ZSTD_estimateCStreamSize() : + * ZSTD_estimateCStreamSize() will provide a memory budget large enough for streaming compression + * using any compression level up to the max specified one. + * It will also consider src size to be arbitrarily "large", which is a worst case scenario. + * If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation. + * ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. + * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1. + * Note : CStream size estimation is only correct for single-threaded compression. + * ZSTD_estimateCStreamSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1. + * Note 2 : ZSTD_estimateCStreamSize* functions are not compatible with the Block-Level Sequence Producer API at this time. + * Size estimates assume that no external sequence producer is registered. + * + * ZSTD_DStream memory budget depends on frame's window Size. + * This information can be passed manually, using ZSTD_estimateDStreamSize, + * or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame(); + * Any frame requesting a window size larger than max specified one will be rejected. + * Note : if streaming is init with function ZSTD_init?Stream_usingDict(), + * an internal ?Dict will be created, which additional size is not estimated here. + * In this case, get total size by adding ZSTD_estimate?DictSize + */ +ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int maxCompressionLevel); +ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams); +ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params); +ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize(size_t maxWindowSize); +ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize); + +/*! ZSTD_estimate?DictSize() : + * ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict(). + * ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced(). + * Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller. + */ +ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel); +ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod); +ZSTDLIB_STATIC_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod); + +/*! ZSTD_initStatic*() : + * Initialize an object using a pre-allocated fixed-size buffer. + * workspace: The memory area to emplace the object into. + * Provided pointer *must be 8-bytes aligned*. + * Buffer must outlive object. + * workspaceSize: Use ZSTD_estimate*Size() to determine + * how large workspace must be to support target scenario. + * @return : pointer to object (same address as workspace, just different type), + * or NULL if error (size too small, incorrect alignment, etc.) + * Note : zstd will never resize nor malloc() when using a static buffer. + * If the object requires more memory than available, + * zstd will just error out (typically ZSTD_error_memory_allocation). + * Note 2 : there is no corresponding "free" function. + * Since workspace is allocated externally, it must be freed externally too. + * Note 3 : cParams : use ZSTD_getCParams() to convert a compression level + * into its associated cParams. + * Limitation 1 : currently not compatible with internal dictionary creation, triggered by + * ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict(). + * Limitation 2 : static cctx currently not compatible with multi-threading. + * Limitation 3 : static dctx is incompatible with legacy support. + */ +ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize); +ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */ + +ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize); +ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */ + +ZSTDLIB_STATIC_API const ZSTD_CDict* ZSTD_initStaticCDict( + void* workspace, size_t workspaceSize, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams); + +ZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_initStaticDDict( + void* workspace, size_t workspaceSize, + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType); + + +/*! Custom memory allocation : + * These prototypes make it possible to pass your own allocation/free functions. + * ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below. + * All allocation/free operations will be completed using these custom variants instead of regular ones. + */ +typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); +typedef void (*ZSTD_freeFunction) (void* opaque, void* address); +typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; +static +#ifdef __GNUC__ +__attribute__((__unused__)) +#endif +ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ + +ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); +ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); +ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem); +ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem); + +ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams, + ZSTD_customMem customMem); + +/*! Thread pool : + * These prototypes make it possible to share a thread pool among multiple compression contexts. + * This can limit resources for applications with multiple threads where each one uses + * a threaded compression mode (via ZSTD_c_nbWorkers parameter). + * ZSTD_createThreadPool creates a new thread pool with a given number of threads. + * Note that the lifetime of such pool must exist while being used. + * ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value + * to use an internal thread pool). + * ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer. + */ +typedef struct POOL_ctx_s ZSTD_threadPool; +ZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads); +ZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool); + + +/* + * This API is temporary and is expected to change or disappear in the future! + */ +ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced2( + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + const ZSTD_CCtx_params* cctxParams, + ZSTD_customMem customMem); + +ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_advanced( + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_customMem customMem); + + +/*************************************** +* Advanced compression functions +***************************************/ + +/*! ZSTD_createCDict_byReference() : + * Create a digested dictionary for compression + * Dictionary content is just referenced, not duplicated. + * As a consequence, `dictBuffer` **must** outlive CDict, + * and its content must remain unmodified throughout the lifetime of CDict. + * note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */ +ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel); + +/*! ZSTD_getCParams() : + * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. + * `estimatedSrcSize` value is optional, select 0 if not known */ +ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); + +/*! ZSTD_getParams() : + * same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`. + * All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */ +ZSTDLIB_STATIC_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); + +/*! ZSTD_checkCParams() : + * Ensure param values remain within authorized range. + * @return 0 on success, or an error code (can be checked with ZSTD_isError()) */ +ZSTDLIB_STATIC_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params); + +/*! ZSTD_adjustCParams() : + * optimize params for a given `srcSize` and `dictSize`. + * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN. + * `dictSize` must be `0` when there is no dictionary. + * cPar can be invalid : all parameters will be clamped within valid range in the @return struct. + * This function never fails (wide contract) */ +ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize); + +/*! ZSTD_CCtx_setCParams() : + * Set all parameters provided within @p cparams into the working @p cctx. + * Note : if modifying parameters during compression (MT mode only), + * note that changes to the .windowLog parameter will be ignored. + * @return 0 on success, or an error code (can be checked with ZSTD_isError()). + * On failure, no parameters are updated. + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams); + +/*! ZSTD_CCtx_setFParams() : + * Set all parameters provided within @p fparams into the working @p cctx. + * @return 0 on success, or an error code (can be checked with ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setFParams(ZSTD_CCtx* cctx, ZSTD_frameParameters fparams); + +/*! ZSTD_CCtx_setParams() : + * Set all parameters provided within @p params into the working @p cctx. + * @return 0 on success, or an error code (can be checked with ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParams(ZSTD_CCtx* cctx, ZSTD_parameters params); + +/*! ZSTD_compress_advanced() : + * Note : this function is now DEPRECATED. + * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters. + * This prototype will generate compilation warnings. */ +ZSTD_DEPRECATED("use ZSTD_compress2") +ZSTDLIB_STATIC_API +size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize, + ZSTD_parameters params); + +/*! ZSTD_compress_usingCDict_advanced() : + * Note : this function is now DEPRECATED. + * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters. + * This prototype will generate compilation warnings. */ +ZSTD_DEPRECATED("use ZSTD_compress2 with ZSTD_CCtx_loadDictionary") +ZSTDLIB_STATIC_API +size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTD_CDict* cdict, + ZSTD_frameParameters fParams); + + +/*! ZSTD_CCtx_loadDictionary_byReference() : + * Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx. + * It saves some memory, but also requires that `dict` outlives its usage within `cctx` */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); + +/*! ZSTD_CCtx_loadDictionary_advanced() : + * Same as ZSTD_CCtx_loadDictionary(), but gives finer control over + * how to load the dictionary (by copy ? by reference ?) + * and how to interpret it (automatic ? force raw mode ? full mode only ?) */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); + +/*! ZSTD_CCtx_refPrefix_advanced() : + * Same as ZSTD_CCtx_refPrefix(), but gives finer control over + * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); + +/* === experimental parameters === */ +/* these parameters can be used with ZSTD_setParameter() + * they are not guaranteed to remain supported in the future */ + + /* Enables rsyncable mode, + * which makes compressed files more rsync friendly + * by adding periodic synchronization points to the compressed data. + * The target average block size is ZSTD_c_jobSize / 2. + * It's possible to modify the job size to increase or decrease + * the granularity of the synchronization point. + * Once the jobSize is smaller than the window size, + * it will result in compression ratio degradation. + * NOTE 1: rsyncable mode only works when multithreading is enabled. + * NOTE 2: rsyncable performs poorly in combination with long range mode, + * since it will decrease the effectiveness of synchronization points, + * though mileage may vary. + * NOTE 3: Rsyncable mode limits maximum compression speed to ~400 MB/s. + * If the selected compression level is already running significantly slower, + * the overall speed won't be significantly impacted. + */ + #define ZSTD_c_rsyncable ZSTD_c_experimentalParam1 + +/* Select a compression format. + * The value must be of type ZSTD_format_e. + * See ZSTD_format_e enum definition for details */ +#define ZSTD_c_format ZSTD_c_experimentalParam2 + +/* Force back-reference distances to remain < windowSize, + * even when referencing into Dictionary content (default:0) */ +#define ZSTD_c_forceMaxWindow ZSTD_c_experimentalParam3 + +/* Controls whether the contents of a CDict + * are used in place, or copied into the working context. + * Accepts values from the ZSTD_dictAttachPref_e enum. + * See the comments on that enum for an explanation of the feature. */ +#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4 + +/* Controlled with ZSTD_paramSwitch_e enum. + * Default is ZSTD_ps_auto. + * Set to ZSTD_ps_disable to never compress literals. + * Set to ZSTD_ps_enable to always compress literals. (Note: uncompressed literals + * may still be emitted if huffman is not beneficial to use.) + * + * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use + * literals compression based on the compression parameters - specifically, + * negative compression levels do not use literal compression. + */ +#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5 + +/* User's best guess of source size. + * Hint is not valid when srcSizeHint == 0. + * There is no guarantee that hint is close to actual source size, + * but compression ratio may regress significantly if guess considerably underestimates */ +#define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7 + +/* Controls whether the new and experimental "dedicated dictionary search + * structure" can be used. This feature is still rough around the edges, be + * prepared for surprising behavior! + * + * How to use it: + * + * When using a CDict, whether to use this feature or not is controlled at + * CDict creation, and it must be set in a CCtxParams set passed into that + * construction (via ZSTD_createCDict_advanced2()). A compression will then + * use the feature or not based on how the CDict was constructed; the value of + * this param, set in the CCtx, will have no effect. + * + * However, when a dictionary buffer is passed into a CCtx, such as via + * ZSTD_CCtx_loadDictionary(), this param can be set on the CCtx to control + * whether the CDict that is created internally can use the feature or not. + * + * What it does: + * + * Normally, the internal data structures of the CDict are analogous to what + * would be stored in a CCtx after compressing the contents of a dictionary. + * To an approximation, a compression using a dictionary can then use those + * data structures to simply continue what is effectively a streaming + * compression where the simulated compression of the dictionary left off. + * Which is to say, the search structures in the CDict are normally the same + * format as in the CCtx. + * + * It is possible to do better, since the CDict is not like a CCtx: the search + * structures are written once during CDict creation, and then are only read + * after that, while the search structures in the CCtx are both read and + * written as the compression goes along. This means we can choose a search + * structure for the dictionary that is read-optimized. + * + * This feature enables the use of that different structure. + * + * Note that some of the members of the ZSTD_compressionParameters struct have + * different semantics and constraints in the dedicated search structure. It is + * highly recommended that you simply set a compression level in the CCtxParams + * you pass into the CDict creation call, and avoid messing with the cParams + * directly. + * + * Effects: + * + * This will only have any effect when the selected ZSTD_strategy + * implementation supports this feature. Currently, that's limited to + * ZSTD_greedy, ZSTD_lazy, and ZSTD_lazy2. + * + * Note that this means that the CDict tables can no longer be copied into the + * CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be + * usable. The dictionary can only be attached or reloaded. + * + * In general, you should expect compression to be faster--sometimes very much + * so--and CDict creation to be slightly slower. Eventually, we will probably + * make this mode the default. + */ +#define ZSTD_c_enableDedicatedDictSearch ZSTD_c_experimentalParam8 + +/* ZSTD_c_stableInBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells the compressor that input data presented with ZSTD_inBuffer + * will ALWAYS be the same between calls. + * Technically, the @src pointer must never be changed, + * and the @pos field can only be updated by zstd. + * However, it's possible to increase the @size field, + * allowing scenarios where more data can be appended after compressions starts. + * These conditions are checked by the compressor, + * and compression will fail if they are not respected. + * Also, data in the ZSTD_inBuffer within the range [src, src + pos) + * MUST not be modified during compression or it will result in data corruption. + * + * When this flag is enabled zstd won't allocate an input window buffer, + * because the user guarantees it can reference the ZSTD_inBuffer until + * the frame is complete. But, it will still allocate an output buffer + * large enough to fit a block (see ZSTD_c_stableOutBuffer). This will also + * avoid the memcpy() from the input buffer to the input window buffer. + * + * NOTE: So long as the ZSTD_inBuffer always points to valid memory, using + * this flag is ALWAYS memory safe, and will never access out-of-bounds + * memory. However, compression WILL fail if conditions are not respected. + * + * WARNING: The data in the ZSTD_inBuffer in the range [src, src + pos) MUST + * not be modified during compression or it will result in data corruption. + * This is because zstd needs to reference data in the ZSTD_inBuffer to find + * matches. Normally zstd maintains its own window buffer for this purpose, + * but passing this flag tells zstd to rely on user provided buffer instead. + */ +#define ZSTD_c_stableInBuffer ZSTD_c_experimentalParam9 + +/* ZSTD_c_stableOutBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells he compressor that the ZSTD_outBuffer will not be resized between + * calls. Specifically: (out.size - out.pos) will never grow. This gives the + * compressor the freedom to say: If the compressed data doesn't fit in the + * output buffer then return ZSTD_error_dstSizeTooSmall. This allows us to + * always decompress directly into the output buffer, instead of decompressing + * into an internal buffer and copying to the output buffer. + * + * When this flag is enabled zstd won't allocate an output buffer, because + * it can write directly to the ZSTD_outBuffer. It will still allocate the + * input window buffer (see ZSTD_c_stableInBuffer). + * + * Zstd will check that (out.size - out.pos) never grows and return an error + * if it does. While not strictly necessary, this should prevent surprises. + */ +#define ZSTD_c_stableOutBuffer ZSTD_c_experimentalParam10 + +/* ZSTD_c_blockDelimiters + * Default is 0 == ZSTD_sf_noBlockDelimiters. + * + * For use with sequence compression API: ZSTD_compressSequences(). + * + * Designates whether or not the given array of ZSTD_Sequence contains block delimiters + * and last literals, which are defined as sequences with offset == 0 and matchLength == 0. + * See the definition of ZSTD_Sequence for more specifics. + */ +#define ZSTD_c_blockDelimiters ZSTD_c_experimentalParam11 + +/* ZSTD_c_validateSequences + * Default is 0 == disabled. Set to 1 to enable sequence validation. + * + * For use with sequence compression API: ZSTD_compressSequences(). + * Designates whether or not we validate sequences provided to ZSTD_compressSequences() + * during function execution. + * + * Without validation, providing a sequence that does not conform to the zstd spec will cause + * undefined behavior, and may produce a corrupted block. + * + * With validation enabled, if sequence is invalid (see doc/zstd_compression_format.md for + * specifics regarding offset/matchlength requirements) then the function will bail out and + * return an error. + * + */ +#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12 + +/* ZSTD_c_useBlockSplitter + * Controlled with ZSTD_paramSwitch_e enum. + * Default is ZSTD_ps_auto. + * Set to ZSTD_ps_disable to never use block splitter. + * Set to ZSTD_ps_enable to always use block splitter. + * + * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use + * block splitting based on the compression parameters. + */ +#define ZSTD_c_useBlockSplitter ZSTD_c_experimentalParam13 + +/* ZSTD_c_useRowMatchFinder + * Controlled with ZSTD_paramSwitch_e enum. + * Default is ZSTD_ps_auto. + * Set to ZSTD_ps_disable to never use row-based matchfinder. + * Set to ZSTD_ps_enable to force usage of row-based matchfinder. + * + * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use + * the row-based matchfinder based on support for SIMD instructions and the window log. + * Note that this only pertains to compression strategies: greedy, lazy, and lazy2 + */ +#define ZSTD_c_useRowMatchFinder ZSTD_c_experimentalParam14 + +/* ZSTD_c_deterministicRefPrefix + * Default is 0 == disabled. Set to 1 to enable. + * + * Zstd produces different results for prefix compression when the prefix is + * directly adjacent to the data about to be compressed vs. when it isn't. + * This is because zstd detects that the two buffers are contiguous and it can + * use a more efficient match finding algorithm. However, this produces different + * results than when the two buffers are non-contiguous. This flag forces zstd + * to always load the prefix in non-contiguous mode, even if it happens to be + * adjacent to the data, to guarantee determinism. + * + * If you really care about determinism when using a dictionary or prefix, + * like when doing delta compression, you should select this option. It comes + * at a speed penalty of about ~2.5% if the dictionary and data happened to be + * contiguous, and is free if they weren't contiguous. We don't expect that + * intentionally making the dictionary and data contiguous will be worth the + * cost to memcpy() the data. + */ +#define ZSTD_c_deterministicRefPrefix ZSTD_c_experimentalParam15 + +/* ZSTD_c_prefetchCDictTables + * Controlled with ZSTD_paramSwitch_e enum. Default is ZSTD_ps_auto. + * + * In some situations, zstd uses CDict tables in-place rather than copying them + * into the working context. (See docs on ZSTD_dictAttachPref_e above for details). + * In such situations, compression speed is seriously impacted when CDict tables are + * "cold" (outside CPU cache). This parameter instructs zstd to prefetch CDict tables + * when they are used in-place. + * + * For sufficiently small inputs, the cost of the prefetch will outweigh the benefit. + * For sufficiently large inputs, zstd will by default memcpy() CDict tables + * into the working context, so there is no need to prefetch. This parameter is + * targeted at a middle range of input sizes, where a prefetch is cheap enough to be + * useful but memcpy() is too expensive. The exact range of input sizes where this + * makes sense is best determined by careful experimentation. + * + * Note: for this parameter, ZSTD_ps_auto is currently equivalent to ZSTD_ps_disable, + * but in the future zstd may conditionally enable this feature via an auto-detection + * heuristic for cold CDicts. + * Use ZSTD_ps_disable to opt out of prefetching under any circumstances. + */ +#define ZSTD_c_prefetchCDictTables ZSTD_c_experimentalParam16 + +/* ZSTD_c_enableSeqProducerFallback + * Allowed values are 0 (disable) and 1 (enable). The default setting is 0. + * + * Controls whether zstd will fall back to an internal sequence producer if an + * external sequence producer is registered and returns an error code. This fallback + * is block-by-block: the internal sequence producer will only be called for blocks + * where the external sequence producer returns an error code. Fallback parsing will + * follow any other cParam settings, such as compression level, the same as in a + * normal (fully-internal) compression operation. + * + * The user is strongly encouraged to read the full Block-Level Sequence Producer API + * documentation (below) before setting this parameter. */ +#define ZSTD_c_enableSeqProducerFallback ZSTD_c_experimentalParam17 + +/* ZSTD_c_maxBlockSize + * Allowed values are between 1KB and ZSTD_BLOCKSIZE_MAX (128KB). + * The default is ZSTD_BLOCKSIZE_MAX, and setting to 0 will set to the default. + * + * This parameter can be used to set an upper bound on the blocksize + * that overrides the default ZSTD_BLOCKSIZE_MAX. It cannot be used to set upper + * bounds greater than ZSTD_BLOCKSIZE_MAX or bounds lower than 1KB (will make + * compressBound() inaccurate). Only currently meant to be used for testing. + * + */ +#define ZSTD_c_maxBlockSize ZSTD_c_experimentalParam18 + +/* ZSTD_c_searchForExternalRepcodes + * This parameter affects how zstd parses external sequences, such as sequences + * provided through the compressSequences() API or from an external block-level + * sequence producer. + * + * If set to ZSTD_ps_enable, the library will check for repeated offsets in + * external sequences, even if those repcodes are not explicitly indicated in + * the "rep" field. Note that this is the only way to exploit repcode matches + * while using compressSequences() or an external sequence producer, since zstd + * currently ignores the "rep" field of external sequences. + * + * If set to ZSTD_ps_disable, the library will not exploit repeated offsets in + * external sequences, regardless of whether the "rep" field has been set. This + * reduces sequence compression overhead by about 25% while sacrificing some + * compression ratio. + * + * The default value is ZSTD_ps_auto, for which the library will enable/disable + * based on compression level. + * + * Note: for now, this param only has an effect if ZSTD_c_blockDelimiters is + * set to ZSTD_sf_explicitBlockDelimiters. That may change in the future. + */ +#define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 + +/*! ZSTD_CCtx_getParameter() : + * Get the requested compression parameter value, selected by enum ZSTD_cParameter, + * and store it into int* value. + * @return : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value); + + +/*! ZSTD_CCtx_params : + * Quick howto : + * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure + * - ZSTD_CCtxParams_setParameter() : Push parameters one by one into + * an existing ZSTD_CCtx_params structure. + * This is similar to + * ZSTD_CCtx_setParameter(). + * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to + * an existing CCtx. + * These parameters will be applied to + * all subsequent frames. + * - ZSTD_compressStream2() : Do compression using the CCtx. + * - ZSTD_freeCCtxParams() : Free the memory, accept NULL pointer. + * + * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams() + * for static allocation of CCtx for single-threaded compression. + */ +ZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void); +ZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */ + +/*! ZSTD_CCtxParams_reset() : + * Reset params to default values. + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params); + +/*! ZSTD_CCtxParams_init() : + * Initializes the compression parameters of cctxParams according to + * compression level. All other parameters are reset to their default values. + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel); + +/*! ZSTD_CCtxParams_init_advanced() : + * Initializes the compression and frame parameters of cctxParams according to + * params. All other parameters are reset to their default values. + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params); + +/*! ZSTD_CCtxParams_setParameter() : Requires v1.4.0+ + * Similar to ZSTD_CCtx_setParameter. + * Set one compression parameter, selected by enum ZSTD_cParameter. + * Parameters must be applied to a ZSTD_CCtx using + * ZSTD_CCtx_setParametersUsingCCtxParams(). + * @result : a code representing success or failure (which can be tested with + * ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value); + +/*! ZSTD_CCtxParams_getParameter() : + * Similar to ZSTD_CCtx_getParameter. + * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter. + * @result : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value); + +/*! ZSTD_CCtx_setParametersUsingCCtxParams() : + * Apply a set of ZSTD_CCtx_params to the compression context. + * This can be done even after compression is started, + * if nbWorkers==0, this will have no impact until a new compression is started. + * if nbWorkers>=1, new parameters will be picked up at next job, + * with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated). + */ +ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParametersUsingCCtxParams( + ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params); + +/*! ZSTD_compressStream2_simpleArgs() : + * Same as ZSTD_compressStream2(), + * but using only integral types as arguments. + * This variant might be helpful for binders from dynamic languages + * which have troubles handling structures containing memory pointers. + */ +ZSTDLIB_STATIC_API size_t ZSTD_compressStream2_simpleArgs ( + ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, size_t* dstPos, + const void* src, size_t srcSize, size_t* srcPos, + ZSTD_EndDirective endOp); + + +/*************************************** +* Advanced decompression functions +***************************************/ + +/*! ZSTD_isFrame() : + * Tells if the content of `buffer` starts with a valid Frame Identifier. + * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. + * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled. + * Note 3 : Skippable Frame Identifiers are considered valid. */ +ZSTDLIB_STATIC_API unsigned ZSTD_isFrame(const void* buffer, size_t size); + +/*! ZSTD_createDDict_byReference() : + * Create a digested dictionary, ready to start decompression operation without startup delay. + * Dictionary content is referenced, and therefore stays in dictBuffer. + * It is important that dictBuffer outlives DDict, + * it must remain read accessible throughout the lifetime of DDict */ +ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize); + +/*! ZSTD_DCtx_loadDictionary_byReference() : + * Same as ZSTD_DCtx_loadDictionary(), + * but references `dict` content instead of copying it into `dctx`. + * This saves memory if `dict` remains around., + * However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */ +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); + +/*! ZSTD_DCtx_loadDictionary_advanced() : + * Same as ZSTD_DCtx_loadDictionary(), + * but gives direct control over + * how to load the dictionary (by copy ? by reference ?) + * and how to interpret it (automatic ? force raw mode ? full mode only ?). */ +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); + +/*! ZSTD_DCtx_refPrefix_advanced() : + * Same as ZSTD_DCtx_refPrefix(), but gives finer control over + * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); + +/*! ZSTD_DCtx_setMaxWindowSize() : + * Refuses allocating internal buffers for frames requiring a window size larger than provided limit. + * This protects a decoder context from reserving too much memory for itself (potential attack scenario). + * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. + * By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + * @return : 0, or an error code (which can be tested using ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize); + +/*! ZSTD_DCtx_getParameter() : + * Get the requested decompression parameter value, selected by enum ZSTD_dParameter, + * and store it into int* value. + * @return : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value); + +/* ZSTD_d_format + * experimental parameter, + * allowing selection between ZSTD_format_e input compression formats + */ +#define ZSTD_d_format ZSTD_d_experimentalParam1 +/* ZSTD_d_stableOutBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells the decompressor that the ZSTD_outBuffer will ALWAYS be the same + * between calls, except for the modifications that zstd makes to pos (the + * caller must not modify pos). This is checked by the decompressor, and + * decompression will fail if it ever changes. Therefore the ZSTD_outBuffer + * MUST be large enough to fit the entire decompressed frame. This will be + * checked when the frame content size is known. The data in the ZSTD_outBuffer + * in the range [dst, dst + pos) MUST not be modified during decompression + * or you will get data corruption. + * + * When this flag is enabled zstd won't allocate an output buffer, because + * it can write directly to the ZSTD_outBuffer, but it will still allocate + * an input buffer large enough to fit any compressed block. This will also + * avoid the memcpy() from the internal output buffer to the ZSTD_outBuffer. + * If you need to avoid the input buffer allocation use the buffer-less + * streaming API. + * + * NOTE: So long as the ZSTD_outBuffer always points to valid memory, using + * this flag is ALWAYS memory safe, and will never access out-of-bounds + * memory. However, decompression WILL fail if you violate the preconditions. + * + * WARNING: The data in the ZSTD_outBuffer in the range [dst, dst + pos) MUST + * not be modified during decompression or you will get data corruption. This + * is because zstd needs to reference data in the ZSTD_outBuffer to regenerate + * matches. Normally zstd maintains its own buffer for this purpose, but passing + * this flag tells zstd to use the user provided buffer. + */ +#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2 + +/* ZSTD_d_forceIgnoreChecksum + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable + * + * Tells the decompressor to skip checksum validation during decompression, regardless + * of whether checksumming was specified during compression. This offers some + * slight performance benefits, and may be useful for debugging. + * Param has values of type ZSTD_forceIgnoreChecksum_e + */ +#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3 + +/* ZSTD_d_refMultipleDDicts + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable + * + * If enabled and dctx is allocated on the heap, then additional memory will be allocated + * to store references to multiple ZSTD_DDict. That is, multiple calls of ZSTD_refDDict() + * using a given ZSTD_DCtx, rather than overwriting the previous DDict reference, will instead + * store all references. At decompression time, the appropriate dictID is selected + * from the set of DDicts based on the dictID in the frame. + * + * Usage is simply calling ZSTD_refDDict() on multiple dict buffers. + * + * Param has values of byte ZSTD_refMultipleDDicts_e + * + * WARNING: Enabling this parameter and calling ZSTD_DCtx_refDDict(), will trigger memory + * allocation for the hash table. ZSTD_freeDCtx() also frees this memory. + * Memory is allocated as per ZSTD_DCtx::customMem. + * + * Although this function allocates memory for the table, the user is still responsible for + * memory management of the underlying ZSTD_DDict* themselves. + */ +#define ZSTD_d_refMultipleDDicts ZSTD_d_experimentalParam4 + +/* ZSTD_d_disableHuffmanAssembly + * Set to 1 to disable the Huffman assembly implementation. + * The default value is 0, which allows zstd to use the Huffman assembly + * implementation if available. + * + * This parameter can be used to disable Huffman assembly at runtime. + * If you want to disable it at compile time you can define the macro + * ZSTD_DISABLE_ASM. + */ +#define ZSTD_d_disableHuffmanAssembly ZSTD_d_experimentalParam5 + +/* ZSTD_d_maxBlockSize + * Allowed values are between 1KB and ZSTD_BLOCKSIZE_MAX (128KB). + * The default is ZSTD_BLOCKSIZE_MAX, and setting to 0 will set to the default. + * + * Forces the decompressor to reject blocks whose content size is + * larger than the configured maxBlockSize. When maxBlockSize is + * larger than the windowSize, the windowSize is used instead. + * This saves memory on the decoder when you know all blocks are small. + * + * This option is typically used in conjunction with ZSTD_c_maxBlockSize. + * + * WARNING: This causes the decoder to reject otherwise valid frames + * that have block sizes larger than the configured maxBlockSize. + */ +#define ZSTD_d_maxBlockSize ZSTD_d_experimentalParam6 + + +/*! ZSTD_DCtx_setFormat() : + * This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter(). + * Instruct the decoder context about what kind of data to decode next. + * This instruction is mandatory to decode data without a fully-formed header, + * such ZSTD_f_zstd1_magicless for example. + * @return : 0, or an error code (which can be tested using ZSTD_isError()). */ +ZSTD_DEPRECATED("use ZSTD_DCtx_setParameter() instead") +ZSTDLIB_STATIC_API +size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format); + +/*! ZSTD_decompressStream_simpleArgs() : + * Same as ZSTD_decompressStream(), + * but using only integral types as arguments. + * This can be helpful for binders from dynamic languages + * which have troubles handling structures containing memory pointers. + */ +ZSTDLIB_STATIC_API size_t ZSTD_decompressStream_simpleArgs ( + ZSTD_DCtx* dctx, + void* dst, size_t dstCapacity, size_t* dstPos, + const void* src, size_t srcSize, size_t* srcPos); + + +/******************************************************************** +* Advanced streaming functions +* Warning : most of these functions are now redundant with the Advanced API. +* Once Advanced API reaches "stable" status, +* redundant functions will be deprecated, and then at some point removed. +********************************************************************/ + +/*===== Advanced Streaming compression functions =====*/ + +/*! ZSTD_initCStream_srcSize() : + * This function is DEPRECATED, and equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) + * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * + * pledgedSrcSize must be correct. If it is not known at init time, use + * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, + * "0" also disables frame content size field. It may be enabled in the future. + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, + int compressionLevel, + unsigned long long pledgedSrcSize); + +/*! ZSTD_initCStream_usingDict() : + * This function is DEPRECATED, and is equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); + * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); + * + * Creates of an internal CDict (incompatible with static CCtx), except if + * dict == NULL or dictSize < 8, in which case no dict is used. + * Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if + * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy. + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, + const void* dict, size_t dictSize, + int compressionLevel); + +/*! ZSTD_initCStream_advanced() : + * This function is DEPRECATED, and is equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_setParams(zcs, params); + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); + * + * dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy. + * pledgedSrcSize must be correct. + * If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, + const void* dict, size_t dictSize, + ZSTD_parameters params, + unsigned long long pledgedSrcSize); + +/*! ZSTD_initCStream_usingCDict() : + * This function is DEPRECATED, and equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_refCDict(zcs, cdict); + * + * note : cdict will just be referenced, and must outlive compression session + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); + +/*! ZSTD_initCStream_usingCDict_advanced() : + * This function is DEPRECATED, and is equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_setFParams(zcs, fParams); + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * ZSTD_CCtx_refCDict(zcs, cdict); + * + * same as ZSTD_initCStream_usingCDict(), with control over frame parameters. + * pledgedSrcSize must be correct. If srcSize is not known at init time, use + * value ZSTD_CONTENTSIZE_UNKNOWN. + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, + const ZSTD_CDict* cdict, + ZSTD_frameParameters fParams, + unsigned long long pledgedSrcSize); + +/*! ZSTD_resetCStream() : + * This function is DEPRECATED, and is equivalent to: + * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); + * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); + * Note: ZSTD_resetCStream() interprets pledgedSrcSize == 0 as ZSTD_CONTENTSIZE_UNKNOWN, but + * ZSTD_CCtx_setPledgedSrcSize() does not do the same, so ZSTD_CONTENTSIZE_UNKNOWN must be + * explicitly specified. + * + * start a new frame, using same parameters from previous frame. + * This is typically useful to skip dictionary loading stage, since it will reuse it in-place. + * Note that zcs must be init at least once before using ZSTD_resetCStream(). + * If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN. + * If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end. + * For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs, + * but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead. + * @return : 0, or an error code (which can be tested using ZSTD_isError()) + * This prototype will generate compilation warnings. + */ +ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API +size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); + + +typedef struct { + unsigned long long ingested; /* nb input bytes read and buffered */ + unsigned long long consumed; /* nb input bytes actually compressed */ + unsigned long long produced; /* nb of compressed bytes generated and buffered */ + unsigned long long flushed; /* nb of compressed bytes flushed : not provided; can be tracked from caller side */ + unsigned currentJobID; /* MT only : latest started job nb */ + unsigned nbActiveWorkers; /* MT only : nb of workers actively compressing at probe time */ +} ZSTD_frameProgression; + +/* ZSTD_getFrameProgression() : + * tells how much data has been ingested (read from input) + * consumed (input actually compressed) and produced (output) for current frame. + * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed. + * Aggregates progression inside active worker threads. + */ +ZSTDLIB_STATIC_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx); + +/*! ZSTD_toFlushNow() : + * Tell how many bytes are ready to be flushed immediately. + * Useful for multithreading scenarios (nbWorkers >= 1). + * Probe the oldest active job, defined as oldest job not yet entirely flushed, + * and check its output buffer. + * @return : amount of data stored in oldest job and ready to be flushed immediately. + * if @return == 0, it means either : + * + there is no active job (could be checked with ZSTD_frameProgression()), or + * + oldest job is still actively compressing data, + * but everything it has produced has also been flushed so far, + * therefore flush speed is limited by production speed of oldest job + * irrespective of the speed of concurrent (and newer) jobs. + */ +ZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); + + +/*===== Advanced Streaming decompression functions =====*/ + +/*! + * This function is deprecated, and is equivalent to: + * + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * ZSTD_DCtx_loadDictionary(zds, dict, dictSize); + * + * note: no dictionary will be used if dict == NULL or dictSize < 8 + */ +ZSTD_DEPRECATED("use ZSTD_DCtx_reset + ZSTD_DCtx_loadDictionary, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); + +/*! + * This function is deprecated, and is equivalent to: + * + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * ZSTD_DCtx_refDDict(zds, ddict); + * + * note : ddict is referenced, it must outlive decompression session + */ +ZSTD_DEPRECATED("use ZSTD_DCtx_reset + ZSTD_DCtx_refDDict, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); + +/*! + * This function is deprecated, and is equivalent to: + * + * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); + * + * reuse decompression parameters from previous init; saves dictionary loading + */ +ZSTD_DEPRECATED("use ZSTD_DCtx_reset, see zstd.h for detailed instructions") +ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); + + +/* ********************* BLOCK-LEVEL SEQUENCE PRODUCER API ********************* + * + * *** OVERVIEW *** + * The Block-Level Sequence Producer API allows users to provide their own custom + * sequence producer which libzstd invokes to process each block. The produced list + * of sequences (literals and matches) is then post-processed by libzstd to produce + * valid compressed blocks. + * + * This block-level offload API is a more granular complement of the existing + * frame-level offload API compressSequences() (introduced in v1.5.1). It offers + * an easier migration story for applications already integrated with libzstd: the + * user application continues to invoke the same compression functions + * ZSTD_compress2() or ZSTD_compressStream2() as usual, and transparently benefits + * from the specific advantages of the external sequence producer. For example, + * the sequence producer could be tuned to take advantage of known characteristics + * of the input, to offer better speed / ratio, or could leverage hardware + * acceleration not available within libzstd itself. + * + * See contrib/externalSequenceProducer for an example program employing the + * Block-Level Sequence Producer API. + * + * *** USAGE *** + * The user is responsible for implementing a function of type + * ZSTD_sequenceProducer_F. For each block, zstd will pass the following + * arguments to the user-provided function: + * + * - sequenceProducerState: a pointer to a user-managed state for the sequence + * producer. + * + * - outSeqs, outSeqsCapacity: an output buffer for the sequence producer. + * outSeqsCapacity is guaranteed >= ZSTD_sequenceBound(srcSize). The memory + * backing outSeqs is managed by the CCtx. + * + * - src, srcSize: an input buffer for the sequence producer to parse. + * srcSize is guaranteed to be <= ZSTD_BLOCKSIZE_MAX. + * + * - dict, dictSize: a history buffer, which may be empty, which the sequence + * producer may reference as it parses the src buffer. Currently, zstd will + * always pass dictSize == 0 into external sequence producers, but this will + * change in the future. + * + * - compressionLevel: a signed integer representing the zstd compression level + * set by the user for the current operation. The sequence producer may choose + * to use this information to change its compression strategy and speed/ratio + * tradeoff. Note: the compression level does not reflect zstd parameters set + * through the advanced API. + * + * - windowSize: a size_t representing the maximum allowed offset for external + * sequences. Note that sequence offsets are sometimes allowed to exceed the + * windowSize if a dictionary is present, see doc/zstd_compression_format.md + * for details. + * + * The user-provided function shall return a size_t representing the number of + * sequences written to outSeqs. This return value will be treated as an error + * code if it is greater than outSeqsCapacity. The return value must be non-zero + * if srcSize is non-zero. The ZSTD_SEQUENCE_PRODUCER_ERROR macro is provided + * for convenience, but any value greater than outSeqsCapacity will be treated as + * an error code. + * + * If the user-provided function does not return an error code, the sequences + * written to outSeqs must be a valid parse of the src buffer. Data corruption may + * occur if the parse is not valid. A parse is defined to be valid if the + * following conditions hold: + * - The sum of matchLengths and literalLengths must equal srcSize. + * - All sequences in the parse, except for the final sequence, must have + * matchLength >= ZSTD_MINMATCH_MIN. The final sequence must have + * matchLength >= ZSTD_MINMATCH_MIN or matchLength == 0. + * - All offsets must respect the windowSize parameter as specified in + * doc/zstd_compression_format.md. + * - If the final sequence has matchLength == 0, it must also have offset == 0. + * + * zstd will only validate these conditions (and fail compression if they do not + * hold) if the ZSTD_c_validateSequences cParam is enabled. Note that sequence + * validation has a performance cost. + * + * If the user-provided function returns an error, zstd will either fall back + * to an internal sequence producer or fail the compression operation. The user can + * choose between the two behaviors by setting the ZSTD_c_enableSeqProducerFallback + * cParam. Fallback compression will follow any other cParam settings, such as + * compression level, the same as in a normal compression operation. + * + * The user shall instruct zstd to use a particular ZSTD_sequenceProducer_F + * function by calling + * ZSTD_registerSequenceProducer(cctx, + * sequenceProducerState, + * sequenceProducer) + * This setting will persist until the next parameter reset of the CCtx. + * + * The sequenceProducerState must be initialized by the user before calling + * ZSTD_registerSequenceProducer(). The user is responsible for destroying the + * sequenceProducerState. + * + * *** LIMITATIONS *** + * This API is compatible with all zstd compression APIs which respect advanced parameters. + * However, there are three limitations: + * + * First, the ZSTD_c_enableLongDistanceMatching cParam is not currently supported. + * COMPRESSION WILL FAIL if it is enabled and the user tries to compress with a block-level + * external sequence producer. + * - Note that ZSTD_c_enableLongDistanceMatching is auto-enabled by default in some + * cases (see its documentation for details). Users must explicitly set + * ZSTD_c_enableLongDistanceMatching to ZSTD_ps_disable in such cases if an external + * sequence producer is registered. + * - As of this writing, ZSTD_c_enableLongDistanceMatching is disabled by default + * whenever ZSTD_c_windowLog < 128MB, but that's subject to change. Users should + * check the docs on ZSTD_c_enableLongDistanceMatching whenever the Block-Level Sequence + * Producer API is used in conjunction with advanced settings (like ZSTD_c_windowLog). + * + * Second, history buffers are not currently supported. Concretely, zstd will always pass + * dictSize == 0 to the external sequence producer (for now). This has two implications: + * - Dictionaries are not currently supported. Compression will *not* fail if the user + * references a dictionary, but the dictionary won't have any effect. + * - Stream history is not currently supported. All advanced compression APIs, including + * streaming APIs, work with external sequence producers, but each block is treated as + * an independent chunk without history from previous blocks. + * + * Third, multi-threading within a single compression is not currently supported. In other words, + * COMPRESSION WILL FAIL if ZSTD_c_nbWorkers > 0 and an external sequence producer is registered. + * Multi-threading across compressions is fine: simply create one CCtx per thread. + * + * Long-term, we plan to overcome all three limitations. There is no technical blocker to + * overcoming them. It is purely a question of engineering effort. + */ + +#define ZSTD_SEQUENCE_PRODUCER_ERROR ((size_t)(-1)) + +typedef size_t (*ZSTD_sequenceProducer_F) ( + void* sequenceProducerState, + ZSTD_Sequence* outSeqs, size_t outSeqsCapacity, + const void* src, size_t srcSize, + const void* dict, size_t dictSize, + int compressionLevel, + size_t windowSize +); + +/*! ZSTD_registerSequenceProducer() : + * Instruct zstd to use a block-level external sequence producer function. + * + * The sequenceProducerState must be initialized by the caller, and the caller is + * responsible for managing its lifetime. This parameter is sticky across + * compressions. It will remain set until the user explicitly resets compression + * parameters. + * + * Sequence producer registration is considered to be an "advanced parameter", + * part of the "advanced API". This means it will only have an effect on compression + * APIs which respect advanced parameters, such as compress2() and compressStream2(). + * Older compression APIs such as compressCCtx(), which predate the introduction of + * "advanced parameters", will ignore any external sequence producer setting. + * + * The sequence producer can be "cleared" by registering a NULL function pointer. This + * removes all limitations described above in the "LIMITATIONS" section of the API docs. + * + * The user is strongly encouraged to read the full API documentation (above) before + * calling this function. */ +ZSTDLIB_STATIC_API void +ZSTD_registerSequenceProducer( + ZSTD_CCtx* cctx, + void* sequenceProducerState, + ZSTD_sequenceProducer_F sequenceProducer +); + +/*! ZSTD_CCtxParams_registerSequenceProducer() : + * Same as ZSTD_registerSequenceProducer(), but operates on ZSTD_CCtx_params. + * This is used for accurate size estimation with ZSTD_estimateCCtxSize_usingCCtxParams(), + * which is needed when creating a ZSTD_CCtx with ZSTD_initStaticCCtx(). + * + * If you are using the external sequence producer API in a scenario where ZSTD_initStaticCCtx() + * is required, then this function is for you. Otherwise, you probably don't need it. + * + * See tests/zstreamtest.c for example usage. */ +ZSTDLIB_STATIC_API void +ZSTD_CCtxParams_registerSequenceProducer( + ZSTD_CCtx_params* params, + void* sequenceProducerState, + ZSTD_sequenceProducer_F sequenceProducer +); + + +/********************************************************************* +* Buffer-less and synchronous inner streaming functions (DEPRECATED) +* +* This API is deprecated, and will be removed in a future version. +* It allows streaming (de)compression with user allocated buffers. +* However, it is hard to use, and not as well tested as the rest of +* our API. +* +* Please use the normal streaming API instead: ZSTD_compressStream2, +* and ZSTD_decompressStream. +* If there is functionality that you need, but it doesn't provide, +* please open an issue on our GitHub. +********************************************************************* */ + +/** + Buffer-less streaming compression (synchronous mode) + + A ZSTD_CCtx object is required to track streaming operations. + Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource. + ZSTD_CCtx object can be reused multiple times within successive compression operations. + + Start by initializing a context. + Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression. + + Then, consume your input using ZSTD_compressContinue(). + There are some important considerations to keep in mind when using this advanced function : + - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only. + - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks. + - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario. + Worst case evaluation is provided by ZSTD_compressBound(). + ZSTD_compressContinue() doesn't guarantee recover after a failed compression. + - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog). + It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks) + - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps. + In which case, it will "discard" the relevant memory section from its history. + + Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum. + It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame. + Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders. + + `ZSTD_CCtx` object can be reused (ZSTD_compressBegin()) to compress again. +*/ + +/*===== Buffer-less streaming compression functions =====*/ +ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel); +ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel); +ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */ + +ZSTD_DEPRECATED("This function will likely be removed in a future release. It is misleading and has very limited utility.") +ZSTDLIB_STATIC_API +size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */ + +ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTD_DEPRECATED("The buffer-less API is deprecated in favor of the normal streaming API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + +/* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */ +ZSTD_DEPRECATED("use advanced API to access custom parameters") +ZSTDLIB_STATIC_API +size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */ +ZSTD_DEPRECATED("use advanced API to access custom parameters") +ZSTDLIB_STATIC_API +size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */ +/** + Buffer-less streaming decompression (synchronous mode) + + A ZSTD_DCtx object is required to track streaming operations. + Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. + A ZSTD_DCtx object can be reused multiple times. + + First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader(). + Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough. + Data fragment must be large enough to ensure successful decoding. + `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough. + result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled. + >0 : `srcSize` is too small, please provide at least result bytes on next attempt. + errorCode, which can be tested using ZSTD_isError(). + + It fills a ZSTD_frameHeader structure with important information to correctly decode the frame, + such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`). + Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information. + As a consequence, check that values remain within valid application range. + For example, do not allocate memory blindly, check that `windowSize` is within expectation. + Each application can set its own limits, depending on local restrictions. + For extended interoperability, it is recommended to support `windowSize` of at least 8 MB. + + ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes. + ZSTD_decompressContinue() is very sensitive to contiguity, + if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place, + or that previous contiguous segment is large enough to properly handle maximum back-reference distance. + There are multiple ways to guarantee this condition. + + The most memory efficient way is to use a round buffer of sufficient size. + Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(), + which can return an error code if required value is too large for current system (in 32-bits mode). + In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one, + up to the moment there is not enough room left in the buffer to guarantee decoding another full block, + which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`. + At which point, decoding can resume from the beginning of the buffer. + Note that already decoded data stored in the buffer should be flushed before being overwritten. + + There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory. + + Finally, if you control the compression process, you can also ignore all buffer size rules, + as long as the encoder and decoder progress in "lock-step", + aka use exactly the same buffer sizes, break contiguity at the same place, etc. + + Once buffers are setup, start decompression, with ZSTD_decompressBegin(). + If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict(). + + Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively. + ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue(). + ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail. + + result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity). + It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item. + It can also be an error code, which can be tested with ZSTD_isError(). + + A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero. + Context can then be reset to start a new decompression. + + Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType(). + This information is not required to properly decode a frame. + + == Special case : skippable frames == + + Skippable frames allow integration of user-defined data into a flow of concatenated frames. + Skippable frames will be ignored (skipped) by decompressor. + The format of skippable frames is as follows : + a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F + b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits + c) Frame Content - any content (User Data) of length equal to Frame Size + For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame. + For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content. +*/ + +/*===== Buffer-less streaming decompression functions =====*/ + +ZSTDLIB_STATIC_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */ + +ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); +ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); +ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); + +ZSTDLIB_STATIC_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx); +ZSTDLIB_STATIC_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + +/* misc */ +ZSTD_DEPRECATED("This function will likely be removed in the next minor release. It is misleading and has very limited utility.") +ZSTDLIB_STATIC_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); +typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; +ZSTDLIB_STATIC_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx); + + + + +/* ========================================= */ +/** Block level API (DEPRECATED) */ +/* ========================================= */ + +/*! + + This API is deprecated in favor of the regular compression API. + You can get the frame header down to 2 bytes by setting: + - ZSTD_c_format = ZSTD_f_zstd1_magicless + - ZSTD_c_contentSizeFlag = 0 + - ZSTD_c_checksumFlag = 0 + - ZSTD_c_dictIDFlag = 0 + + This API is not as well tested as our normal API, so we recommend not using it. + We will be removing it in a future version. If the normal API doesn't provide + the functionality you need, please open a GitHub issue. + + Block functions produce and decode raw zstd blocks, without frame metadata. + Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes). + But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes. + + A few rules to respect : + - Compressing and decompressing require a context structure + + Use ZSTD_createCCtx() and ZSTD_createDCtx() + - It is necessary to init context before starting + + compression : any ZSTD_compressBegin*() variant, including with dictionary + + decompression : any ZSTD_decompressBegin*() variant, including with dictionary + - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB + + If input is larger than a block size, it's necessary to split input data into multiple blocks + + For inputs larger than a single block, consider using regular ZSTD_compress() instead. + Frame metadata is not that costly, and quickly becomes negligible as source size grows larger than a block. + - When a block is considered not compressible enough, ZSTD_compressBlock() result will be 0 (zero) ! + ===> In which case, nothing is produced into `dst` ! + + User __must__ test for such outcome and deal directly with uncompressed data + + A block cannot be declared incompressible if ZSTD_compressBlock() return value was != 0. + Doing so would mess up with statistics history, leading to potential data corruption. + + ZSTD_decompressBlock() _doesn't accept uncompressed data as input_ !! + + In case of multiple successive blocks, should some of them be uncompressed, + decoder must be informed of their existence in order to follow proper history. + Use ZSTD_insertBlock() for such a case. +*/ + +/*===== Raw zstd block functions =====*/ +ZSTD_DEPRECATED("The block API is deprecated in favor of the normal compression API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx); +ZSTD_DEPRECATED("The block API is deprecated in favor of the normal compression API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTD_DEPRECATED("The block API is deprecated in favor of the normal compression API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +ZSTD_DEPRECATED("The block API is deprecated in favor of the normal compression API. See docs.") +ZSTDLIB_STATIC_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */ + +#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */ + +#if defined (__cplusplus) +} +#endif diff --git a/third_party/zstd/include/zstd/common/zstd_errors.h b/third_party/zstd/include/zstd/include/zstd_errors.h similarity index 72% rename from third_party/zstd/include/zstd/common/zstd_errors.h rename to third_party/zstd/include/zstd/include/zstd_errors.h index a719982bc6a..dc75eeebad9 100644 --- a/third_party/zstd/include/zstd/common/zstd_errors.h +++ b/third_party/zstd/include/zstd/include/zstd_errors.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. + * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under both the BSD-style license (found in the @@ -11,26 +11,42 @@ #ifndef ZSTD_ERRORS_H_398273423 #define ZSTD_ERRORS_H_398273423 +#if defined (__cplusplus) +extern "C" { +#endif + /*===== dependency =====*/ #include /* size_t */ /* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */ -#ifndef ZSTDERRORLIB_VISIBILITY -# if defined(__GNUC__) && (__GNUC__ >= 4) -# define ZSTDERRORLIB_VISIBILITY __attribute__ ((visibility ("default"))) +#ifndef ZSTDERRORLIB_VISIBLE + /* Backwards compatibility with old macro name */ +# ifdef ZSTDERRORLIB_VISIBILITY +# define ZSTDERRORLIB_VISIBLE ZSTDERRORLIB_VISIBILITY +# elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) +# define ZSTDERRORLIB_VISIBLE __attribute__ ((visibility ("default"))) +# else +# define ZSTDERRORLIB_VISIBLE +# endif +#endif + +#ifndef ZSTDERRORLIB_HIDDEN +# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__) +# define ZSTDERRORLIB_HIDDEN __attribute__ ((visibility ("hidden"))) # else -# define ZSTDERRORLIB_VISIBILITY +# define ZSTDERRORLIB_HIDDEN # endif #endif + #if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) -# define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBILITY +# define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBLE #elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) -# define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +# define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ #else -# define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBILITY +# define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBLE #endif -namespace duckdb_zstd { + /*-********************************************* * Error codes list *-********************************************* @@ -54,14 +70,17 @@ typedef enum { ZSTD_error_frameParameter_windowTooLarge = 16, ZSTD_error_corruption_detected = 20, ZSTD_error_checksum_wrong = 22, + ZSTD_error_literals_headerWrong = 24, ZSTD_error_dictionary_corrupted = 30, ZSTD_error_dictionary_wrong = 32, ZSTD_error_dictionaryCreation_failed = 34, ZSTD_error_parameter_unsupported = 40, + ZSTD_error_parameter_combination_unsupported = 41, ZSTD_error_parameter_outOfBound = 42, ZSTD_error_tableLog_tooLarge = 44, ZSTD_error_maxSymbolValue_tooLarge = 46, ZSTD_error_maxSymbolValue_tooSmall = 48, + ZSTD_error_stabilityCondition_notRespected = 50, ZSTD_error_stage_wrong = 60, ZSTD_error_init_missing = 62, ZSTD_error_memory_allocation = 64, @@ -69,10 +88,15 @@ typedef enum { ZSTD_error_dstSize_tooSmall = 70, ZSTD_error_srcSize_wrong = 72, ZSTD_error_dstBuffer_null = 74, + ZSTD_error_noForwardProgress_destFull = 80, + ZSTD_error_noForwardProgress_inputEmpty = 82, /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */ ZSTD_error_frameIndex_tooLarge = 100, ZSTD_error_seekableIO = 102, ZSTD_error_dstBuffer_wrong = 104, + ZSTD_error_srcBuffer_wrong = 105, + ZSTD_error_sequenceProducer_failed = 106, + ZSTD_error_externalSequences_invalid = 107, ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */ } ZSTD_ErrorCode; @@ -82,6 +106,9 @@ typedef enum { ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code); /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */ + +#if defined (__cplusplus) } +#endif #endif /* ZSTD_ERRORS_H_398273423 */ diff --git a/third_party/zstd/include/zstd/legacy/zstd_legacy.h b/third_party/zstd/include/zstd/legacy/zstd_legacy.h new file mode 100644 index 00000000000..7a8a04e593c --- /dev/null +++ b/third_party/zstd/include/zstd/legacy/zstd_legacy.h @@ -0,0 +1,452 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_LEGACY_H +#define ZSTD_LEGACY_H + +#if defined (__cplusplus) +extern "C" { +#endif + +/* ************************************* +* Includes +***************************************/ +#include "../common/mem.h" /* MEM_STATIC */ +#include "../common/error_private.h" /* ERROR */ +#include "../common/zstd_internal.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTD_frameSizeInfo */ + +#if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0) +# undef ZSTD_LEGACY_SUPPORT +# define ZSTD_LEGACY_SUPPORT 8 +#endif + +#if (ZSTD_LEGACY_SUPPORT <= 1) +# include "zstd_v01.h" +#endif +#if (ZSTD_LEGACY_SUPPORT <= 2) +# include "zstd_v02.h" +#endif +#if (ZSTD_LEGACY_SUPPORT <= 3) +# include "zstd_v03.h" +#endif +#if (ZSTD_LEGACY_SUPPORT <= 4) +# include "zstd_v04.h" +#endif +#if (ZSTD_LEGACY_SUPPORT <= 5) +# include "zstd_v05.h" +#endif +#if (ZSTD_LEGACY_SUPPORT <= 6) +# include "zstd_v06.h" +#endif +#if (ZSTD_LEGACY_SUPPORT <= 7) +# include "zstd_v07.h" +#endif + +/** ZSTD_isLegacy() : + @return : > 0 if supported by legacy decoder. 0 otherwise. + return value is the version. +*/ +MEM_STATIC unsigned ZSTD_isLegacy(const void* src, size_t srcSize) +{ + U32 magicNumberLE; + if (srcSize<4) return 0; + magicNumberLE = MEM_readLE32(src); + switch(magicNumberLE) + { +#if (ZSTD_LEGACY_SUPPORT <= 1) + case ZSTDv01_magicNumberLE:return 1; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 2) + case ZSTDv02_magicNumber : return 2; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 3) + case ZSTDv03_magicNumber : return 3; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 4) + case ZSTDv04_magicNumber : return 4; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 5) + case ZSTDv05_MAGICNUMBER : return 5; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 6) + case ZSTDv06_MAGICNUMBER : return 6; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 7) + case ZSTDv07_MAGICNUMBER : return 7; +#endif + default : return 0; + } +} + + +MEM_STATIC unsigned long long ZSTD_getDecompressedSize_legacy(const void* src, size_t srcSize) +{ + U32 const version = ZSTD_isLegacy(src, srcSize); + if (version < 5) return 0; /* no decompressed size in frame header, or not a legacy format */ +#if (ZSTD_LEGACY_SUPPORT <= 5) + if (version==5) { + ZSTDv05_parameters fParams; + size_t const frResult = ZSTDv05_getFrameParams(&fParams, src, srcSize); + if (frResult != 0) return 0; + return fParams.srcSize; + } +#endif +#if (ZSTD_LEGACY_SUPPORT <= 6) + if (version==6) { + ZSTDv06_frameParams fParams; + size_t const frResult = ZSTDv06_getFrameParams(&fParams, src, srcSize); + if (frResult != 0) return 0; + return fParams.frameContentSize; + } +#endif +#if (ZSTD_LEGACY_SUPPORT <= 7) + if (version==7) { + ZSTDv07_frameParams fParams; + size_t const frResult = ZSTDv07_getFrameParams(&fParams, src, srcSize); + if (frResult != 0) return 0; + return fParams.frameContentSize; + } +#endif + return 0; /* should not be possible */ +} + + +MEM_STATIC size_t ZSTD_decompressLegacy( + void* dst, size_t dstCapacity, + const void* src, size_t compressedSize, + const void* dict,size_t dictSize) +{ + U32 const version = ZSTD_isLegacy(src, compressedSize); + char x; + /* Avoid passing NULL to legacy decoding. */ + if (dst == NULL) { + assert(dstCapacity == 0); + dst = &x; + } + if (src == NULL) { + assert(compressedSize == 0); + src = &x; + } + if (dict == NULL) { + assert(dictSize == 0); + dict = &x; + } + (void)dst; (void)dstCapacity; (void)dict; (void)dictSize; /* unused when ZSTD_LEGACY_SUPPORT >= 8 */ + switch(version) + { +#if (ZSTD_LEGACY_SUPPORT <= 1) + case 1 : + return ZSTDv01_decompress(dst, dstCapacity, src, compressedSize); +#endif +#if (ZSTD_LEGACY_SUPPORT <= 2) + case 2 : + return ZSTDv02_decompress(dst, dstCapacity, src, compressedSize); +#endif +#if (ZSTD_LEGACY_SUPPORT <= 3) + case 3 : + return ZSTDv03_decompress(dst, dstCapacity, src, compressedSize); +#endif +#if (ZSTD_LEGACY_SUPPORT <= 4) + case 4 : + return ZSTDv04_decompress(dst, dstCapacity, src, compressedSize); +#endif +#if (ZSTD_LEGACY_SUPPORT <= 5) + case 5 : + { size_t result; + ZSTDv05_DCtx* const zd = ZSTDv05_createDCtx(); + if (zd==NULL) return ERROR(memory_allocation); + result = ZSTDv05_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); + ZSTDv05_freeDCtx(zd); + return result; + } +#endif +#if (ZSTD_LEGACY_SUPPORT <= 6) + case 6 : + { size_t result; + ZSTDv06_DCtx* const zd = ZSTDv06_createDCtx(); + if (zd==NULL) return ERROR(memory_allocation); + result = ZSTDv06_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); + ZSTDv06_freeDCtx(zd); + return result; + } +#endif +#if (ZSTD_LEGACY_SUPPORT <= 7) + case 7 : + { size_t result; + ZSTDv07_DCtx* const zd = ZSTDv07_createDCtx(); + if (zd==NULL) return ERROR(memory_allocation); + result = ZSTDv07_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); + ZSTDv07_freeDCtx(zd); + return result; + } +#endif + default : + return ERROR(prefix_unknown); + } +} + +MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size_t srcSize) +{ + ZSTD_frameSizeInfo frameSizeInfo; + U32 const version = ZSTD_isLegacy(src, srcSize); + switch(version) + { +#if (ZSTD_LEGACY_SUPPORT <= 1) + case 1 : + ZSTDv01_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, + &frameSizeInfo.decompressedBound); + break; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 2) + case 2 : + ZSTDv02_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, + &frameSizeInfo.decompressedBound); + break; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 3) + case 3 : + ZSTDv03_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, + &frameSizeInfo.decompressedBound); + break; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 4) + case 4 : + ZSTDv04_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, + &frameSizeInfo.decompressedBound); + break; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 5) + case 5 : + ZSTDv05_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, + &frameSizeInfo.decompressedBound); + break; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 6) + case 6 : + ZSTDv06_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, + &frameSizeInfo.decompressedBound); + break; +#endif +#if (ZSTD_LEGACY_SUPPORT <= 7) + case 7 : + ZSTDv07_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, + &frameSizeInfo.decompressedBound); + break; +#endif + default : + frameSizeInfo.compressedSize = ERROR(prefix_unknown); + frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR; + break; + } + if (!ZSTD_isError(frameSizeInfo.compressedSize) && frameSizeInfo.compressedSize > srcSize) { + frameSizeInfo.compressedSize = ERROR(srcSize_wrong); + frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR; + } + /* In all cases, decompressedBound == nbBlocks * ZSTD_BLOCKSIZE_MAX. + * So we can compute nbBlocks without having to change every function. + */ + if (frameSizeInfo.decompressedBound != ZSTD_CONTENTSIZE_ERROR) { + assert((frameSizeInfo.decompressedBound & (ZSTD_BLOCKSIZE_MAX - 1)) == 0); + frameSizeInfo.nbBlocks = (size_t)(frameSizeInfo.decompressedBound / ZSTD_BLOCKSIZE_MAX); + } + return frameSizeInfo; +} + +MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, size_t srcSize) +{ + ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize); + return frameSizeInfo.compressedSize; +} + +MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version) +{ + switch(version) + { + default : + case 1 : + case 2 : + case 3 : + (void)legacyContext; + return ERROR(version_unsupported); +#if (ZSTD_LEGACY_SUPPORT <= 4) + case 4 : return ZBUFFv04_freeDCtx((ZBUFFv04_DCtx*)legacyContext); +#endif +#if (ZSTD_LEGACY_SUPPORT <= 5) + case 5 : return ZBUFFv05_freeDCtx((ZBUFFv05_DCtx*)legacyContext); +#endif +#if (ZSTD_LEGACY_SUPPORT <= 6) + case 6 : return ZBUFFv06_freeDCtx((ZBUFFv06_DCtx*)legacyContext); +#endif +#if (ZSTD_LEGACY_SUPPORT <= 7) + case 7 : return ZBUFFv07_freeDCtx((ZBUFFv07_DCtx*)legacyContext); +#endif + } +} + + +MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U32 newVersion, + const void* dict, size_t dictSize) +{ + char x; + /* Avoid passing NULL to legacy decoding. */ + if (dict == NULL) { + assert(dictSize == 0); + dict = &x; + } + DEBUGLOG(5, "ZSTD_initLegacyStream for v0.%u", newVersion); + if (prevVersion != newVersion) ZSTD_freeLegacyStreamContext(*legacyContext, prevVersion); + switch(newVersion) + { + default : + case 1 : + case 2 : + case 3 : + (void)dict; (void)dictSize; + return 0; +#if (ZSTD_LEGACY_SUPPORT <= 4) + case 4 : + { + ZBUFFv04_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv04_createDCtx() : (ZBUFFv04_DCtx*)*legacyContext; + if (dctx==NULL) return ERROR(memory_allocation); + ZBUFFv04_decompressInit(dctx); + ZBUFFv04_decompressWithDictionary(dctx, dict, dictSize); + *legacyContext = dctx; + return 0; + } +#endif +#if (ZSTD_LEGACY_SUPPORT <= 5) + case 5 : + { + ZBUFFv05_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv05_createDCtx() : (ZBUFFv05_DCtx*)*legacyContext; + if (dctx==NULL) return ERROR(memory_allocation); + ZBUFFv05_decompressInitDictionary(dctx, dict, dictSize); + *legacyContext = dctx; + return 0; + } +#endif +#if (ZSTD_LEGACY_SUPPORT <= 6) + case 6 : + { + ZBUFFv06_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv06_createDCtx() : (ZBUFFv06_DCtx*)*legacyContext; + if (dctx==NULL) return ERROR(memory_allocation); + ZBUFFv06_decompressInitDictionary(dctx, dict, dictSize); + *legacyContext = dctx; + return 0; + } +#endif +#if (ZSTD_LEGACY_SUPPORT <= 7) + case 7 : + { + ZBUFFv07_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv07_createDCtx() : (ZBUFFv07_DCtx*)*legacyContext; + if (dctx==NULL) return ERROR(memory_allocation); + ZBUFFv07_decompressInitDictionary(dctx, dict, dictSize); + *legacyContext = dctx; + return 0; + } +#endif + } +} + + + +MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version, + ZSTD_outBuffer* output, ZSTD_inBuffer* input) +{ + static char x; + /* Avoid passing NULL to legacy decoding. */ + if (output->dst == NULL) { + assert(output->size == 0); + output->dst = &x; + } + if (input->src == NULL) { + assert(input->size == 0); + input->src = &x; + } + DEBUGLOG(5, "ZSTD_decompressLegacyStream for v0.%u", version); + switch(version) + { + default : + case 1 : + case 2 : + case 3 : + (void)legacyContext; (void)output; (void)input; + return ERROR(version_unsupported); +#if (ZSTD_LEGACY_SUPPORT <= 4) + case 4 : + { + ZBUFFv04_DCtx* dctx = (ZBUFFv04_DCtx*) legacyContext; + const void* src = (const char*)input->src + input->pos; + size_t readSize = input->size - input->pos; + void* dst = (char*)output->dst + output->pos; + size_t decodedSize = output->size - output->pos; + size_t const hintSize = ZBUFFv04_decompressContinue(dctx, dst, &decodedSize, src, &readSize); + output->pos += decodedSize; + input->pos += readSize; + return hintSize; + } +#endif +#if (ZSTD_LEGACY_SUPPORT <= 5) + case 5 : + { + ZBUFFv05_DCtx* dctx = (ZBUFFv05_DCtx*) legacyContext; + const void* src = (const char*)input->src + input->pos; + size_t readSize = input->size - input->pos; + void* dst = (char*)output->dst + output->pos; + size_t decodedSize = output->size - output->pos; + size_t const hintSize = ZBUFFv05_decompressContinue(dctx, dst, &decodedSize, src, &readSize); + output->pos += decodedSize; + input->pos += readSize; + return hintSize; + } +#endif +#if (ZSTD_LEGACY_SUPPORT <= 6) + case 6 : + { + ZBUFFv06_DCtx* dctx = (ZBUFFv06_DCtx*) legacyContext; + const void* src = (const char*)input->src + input->pos; + size_t readSize = input->size - input->pos; + void* dst = (char*)output->dst + output->pos; + size_t decodedSize = output->size - output->pos; + size_t const hintSize = ZBUFFv06_decompressContinue(dctx, dst, &decodedSize, src, &readSize); + output->pos += decodedSize; + input->pos += readSize; + return hintSize; + } +#endif +#if (ZSTD_LEGACY_SUPPORT <= 7) + case 7 : + { + ZBUFFv07_DCtx* dctx = (ZBUFFv07_DCtx*) legacyContext; + const void* src = (const char*)input->src + input->pos; + size_t readSize = input->size - input->pos; + void* dst = (char*)output->dst + output->pos; + size_t decodedSize = output->size - output->pos; + size_t const hintSize = ZBUFFv07_decompressContinue(dctx, dst, &decodedSize, src, &readSize); + output->pos += decodedSize; + input->pos += readSize; + return hintSize; + } +#endif + } +} + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_LEGACY_H */ diff --git a/third_party/zstd/include/zstd/legacy/zstd_v01.h b/third_party/zstd/include/zstd/legacy/zstd_v01.h new file mode 100644 index 00000000000..6ac876954d1 --- /dev/null +++ b/third_party/zstd/include/zstd/legacy/zstd_v01.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_V01_H_28739879432 +#define ZSTD_V01_H_28739879432 + +#if defined (__cplusplus) +extern "C" { +#endif + +/* ************************************* +* Includes +***************************************/ +#include /* size_t */ + + +/* ************************************* +* Simple one-step function +***************************************/ +/** +ZSTDv01_decompress() : decompress ZSTD frames compliant with v0.1.x format + compressedSize : is the exact source size + maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated. + It must be equal or larger than originalSize, otherwise decompression will fail. + return : the number of bytes decompressed into destination buffer (originalSize) + or an errorCode if it fails (which can be tested using ZSTDv01_isError()) +*/ +size_t ZSTDv01_decompress( void* dst, size_t maxOriginalSize, + const void* src, size_t compressedSize); + + /** + ZSTDv01_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.1.x format + srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + cSize (output parameter) : the number of bytes that would be read to decompress this frame + or an error code if it fails (which can be tested using ZSTDv01_isError()) + dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame + or ZSTD_CONTENTSIZE_ERROR if an error occurs + + note : assumes `cSize` and `dBound` are _not_ NULL. + */ +void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); + +/** +ZSTDv01_isError() : tells if the result of ZSTDv01_decompress() is an error +*/ +unsigned ZSTDv01_isError(size_t code); + + +/* ************************************* +* Advanced functions +***************************************/ +typedef struct ZSTDv01_Dctx_s ZSTDv01_Dctx; +ZSTDv01_Dctx* ZSTDv01_createDCtx(void); +size_t ZSTDv01_freeDCtx(ZSTDv01_Dctx* dctx); + +size_t ZSTDv01_decompressDCtx(void* ctx, + void* dst, size_t maxOriginalSize, + const void* src, size_t compressedSize); + +/* ************************************* +* Streaming functions +***************************************/ +size_t ZSTDv01_resetDCtx(ZSTDv01_Dctx* dctx); + +size_t ZSTDv01_nextSrcSizeToDecompress(ZSTDv01_Dctx* dctx); +size_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); +/** + Use above functions alternatively. + ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue(). + ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block. + Result is the number of bytes regenerated within 'dst'. + It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header. +*/ + +/* ************************************* +* Prefix - version detection +***************************************/ +#define ZSTDv01_magicNumber 0xFD2FB51E /* Big Endian version */ +#define ZSTDv01_magicNumberLE 0x1EB52FFD /* Little Endian version */ + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_V01_H_28739879432 */ diff --git a/third_party/zstd/include/zstd/legacy/zstd_v02.h b/third_party/zstd/include/zstd/legacy/zstd_v02.h new file mode 100644 index 00000000000..dab0260ee9e --- /dev/null +++ b/third_party/zstd/include/zstd/legacy/zstd_v02.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_V02_H_4174539423 +#define ZSTD_V02_H_4174539423 + +#if defined (__cplusplus) +extern "C" { +#endif + +/* ************************************* +* Includes +***************************************/ +#include /* size_t */ + + +/* ************************************* +* Simple one-step function +***************************************/ +/** +ZSTDv02_decompress() : decompress ZSTD frames compliant with v0.2.x format + compressedSize : is the exact source size + maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated. + It must be equal or larger than originalSize, otherwise decompression will fail. + return : the number of bytes decompressed into destination buffer (originalSize) + or an errorCode if it fails (which can be tested using ZSTDv01_isError()) +*/ +size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize, + const void* src, size_t compressedSize); + + /** + ZSTDv02_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.2.x format + srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + cSize (output parameter) : the number of bytes that would be read to decompress this frame + or an error code if it fails (which can be tested using ZSTDv01_isError()) + dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame + or ZSTD_CONTENTSIZE_ERROR if an error occurs + + note : assumes `cSize` and `dBound` are _not_ NULL. + */ +void ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); + +/** +ZSTDv02_isError() : tells if the result of ZSTDv02_decompress() is an error +*/ +unsigned ZSTDv02_isError(size_t code); + + +/* ************************************* +* Advanced functions +***************************************/ +typedef struct ZSTDv02_Dctx_s ZSTDv02_Dctx; +ZSTDv02_Dctx* ZSTDv02_createDCtx(void); +size_t ZSTDv02_freeDCtx(ZSTDv02_Dctx* dctx); + +size_t ZSTDv02_decompressDCtx(void* ctx, + void* dst, size_t maxOriginalSize, + const void* src, size_t compressedSize); + +/* ************************************* +* Streaming functions +***************************************/ +size_t ZSTDv02_resetDCtx(ZSTDv02_Dctx* dctx); + +size_t ZSTDv02_nextSrcSizeToDecompress(ZSTDv02_Dctx* dctx); +size_t ZSTDv02_decompressContinue(ZSTDv02_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); +/** + Use above functions alternatively. + ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue(). + ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block. + Result is the number of bytes regenerated within 'dst'. + It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header. +*/ + +/* ************************************* +* Prefix - version detection +***************************************/ +#define ZSTDv02_magicNumber 0xFD2FB522 /* v0.2 */ + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_V02_H_4174539423 */ diff --git a/third_party/zstd/include/zstd/legacy/zstd_v03.h b/third_party/zstd/include/zstd/legacy/zstd_v03.h new file mode 100644 index 00000000000..9bf3cce6473 --- /dev/null +++ b/third_party/zstd/include/zstd/legacy/zstd_v03.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_V03_H_298734209782 +#define ZSTD_V03_H_298734209782 + +#if defined (__cplusplus) +extern "C" { +#endif + +/* ************************************* +* Includes +***************************************/ +#include /* size_t */ + + +/* ************************************* +* Simple one-step function +***************************************/ +/** +ZSTDv03_decompress() : decompress ZSTD frames compliant with v0.3.x format + compressedSize : is the exact source size + maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated. + It must be equal or larger than originalSize, otherwise decompression will fail. + return : the number of bytes decompressed into destination buffer (originalSize) + or an errorCode if it fails (which can be tested using ZSTDv01_isError()) +*/ +size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize, + const void* src, size_t compressedSize); + + /** + ZSTDv03_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.3.x format + srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + cSize (output parameter) : the number of bytes that would be read to decompress this frame + or an error code if it fails (which can be tested using ZSTDv01_isError()) + dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame + or ZSTD_CONTENTSIZE_ERROR if an error occurs + + note : assumes `cSize` and `dBound` are _not_ NULL. + */ + void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); + + /** +ZSTDv03_isError() : tells if the result of ZSTDv03_decompress() is an error +*/ +unsigned ZSTDv03_isError(size_t code); + + +/* ************************************* +* Advanced functions +***************************************/ +typedef struct ZSTDv03_Dctx_s ZSTDv03_Dctx; +ZSTDv03_Dctx* ZSTDv03_createDCtx(void); +size_t ZSTDv03_freeDCtx(ZSTDv03_Dctx* dctx); + +size_t ZSTDv03_decompressDCtx(void* ctx, + void* dst, size_t maxOriginalSize, + const void* src, size_t compressedSize); + +/* ************************************* +* Streaming functions +***************************************/ +size_t ZSTDv03_resetDCtx(ZSTDv03_Dctx* dctx); + +size_t ZSTDv03_nextSrcSizeToDecompress(ZSTDv03_Dctx* dctx); +size_t ZSTDv03_decompressContinue(ZSTDv03_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); +/** + Use above functions alternatively. + ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue(). + ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block. + Result is the number of bytes regenerated within 'dst'. + It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header. +*/ + +/* ************************************* +* Prefix - version detection +***************************************/ +#define ZSTDv03_magicNumber 0xFD2FB523 /* v0.3 */ + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_V03_H_298734209782 */ diff --git a/third_party/zstd/include/zstd/legacy/zstd_v04.h b/third_party/zstd/include/zstd/legacy/zstd_v04.h new file mode 100644 index 00000000000..640240d624d --- /dev/null +++ b/third_party/zstd/include/zstd/legacy/zstd_v04.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTD_V04_H_91868324769238 +#define ZSTD_V04_H_91868324769238 + +#if defined (__cplusplus) +extern "C" { +#endif + +/* ************************************* +* Includes +***************************************/ +#include /* size_t */ + + +/* ************************************* +* Simple one-step function +***************************************/ +/** +ZSTDv04_decompress() : decompress ZSTD frames compliant with v0.4.x format + compressedSize : is the exact source size + maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated. + It must be equal or larger than originalSize, otherwise decompression will fail. + return : the number of bytes decompressed into destination buffer (originalSize) + or an errorCode if it fails (which can be tested using ZSTDv01_isError()) +*/ +size_t ZSTDv04_decompress( void* dst, size_t maxOriginalSize, + const void* src, size_t compressedSize); + + /** + ZSTDv04_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.4.x format + srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + cSize (output parameter) : the number of bytes that would be read to decompress this frame + or an error code if it fails (which can be tested using ZSTDv01_isError()) + dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame + or ZSTD_CONTENTSIZE_ERROR if an error occurs + + note : assumes `cSize` and `dBound` are _not_ NULL. + */ + void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); + +/** +ZSTDv04_isError() : tells if the result of ZSTDv04_decompress() is an error +*/ +unsigned ZSTDv04_isError(size_t code); + + +/* ************************************* +* Advanced functions +***************************************/ +typedef struct ZSTDv04_Dctx_s ZSTDv04_Dctx; +ZSTDv04_Dctx* ZSTDv04_createDCtx(void); +size_t ZSTDv04_freeDCtx(ZSTDv04_Dctx* dctx); + +size_t ZSTDv04_decompressDCtx(ZSTDv04_Dctx* dctx, + void* dst, size_t maxOriginalSize, + const void* src, size_t compressedSize); + + +/* ************************************* +* Direct Streaming +***************************************/ +size_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx); + +size_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx); +size_t ZSTDv04_decompressContinue(ZSTDv04_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); +/** + Use above functions alternatively. + ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue(). + ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block. + Result is the number of bytes regenerated within 'dst'. + It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header. +*/ + + +/* ************************************* +* Buffered Streaming +***************************************/ +typedef struct ZBUFFv04_DCtx_s ZBUFFv04_DCtx; +ZBUFFv04_DCtx* ZBUFFv04_createDCtx(void); +size_t ZBUFFv04_freeDCtx(ZBUFFv04_DCtx* dctx); + +size_t ZBUFFv04_decompressInit(ZBUFFv04_DCtx* dctx); +size_t ZBUFFv04_decompressWithDictionary(ZBUFFv04_DCtx* dctx, const void* dict, size_t dictSize); + +size_t ZBUFFv04_decompressContinue(ZBUFFv04_DCtx* dctx, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr); + +/** ************************************************ +* Streaming decompression +* +* A ZBUFF_DCtx object is required to track streaming operation. +* Use ZBUFF_createDCtx() and ZBUFF_freeDCtx() to create/release resources. +* Use ZBUFF_decompressInit() to start a new decompression operation. +* ZBUFF_DCtx objects can be reused multiple times. +* +* Optionally, a reference to a static dictionary can be set, using ZBUFF_decompressWithDictionary() +* It must be the same content as the one set during compression phase. +* Dictionary content must remain accessible during the decompression process. +* +* Use ZBUFF_decompressContinue() repetitively to consume your input. +* *srcSizePtr and *maxDstSizePtr can be any size. +* The function will report how many bytes were read or written by modifying *srcSizePtr and *maxDstSizePtr. +* Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again. +* The content of dst will be overwritten (up to *maxDstSizePtr) at each function call, so save its content if it matters or change dst. +* @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency) +* or 0 when a frame is completely decoded +* or an error code, which can be tested using ZBUFF_isError(). +* +* Hint : recommended buffer sizes (not compulsory) : ZBUFF_recommendedDInSize / ZBUFF_recommendedDOutSize +* output : ZBUFF_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when it's decoded. +* input : ZBUFF_recommendedDInSize==128Kb+3; just follow indications from ZBUFF_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 . +* **************************************************/ +unsigned ZBUFFv04_isError(size_t errorCode); +const char* ZBUFFv04_getErrorName(size_t errorCode); + + +/** The below functions provide recommended buffer sizes for Compression or Decompression operations. +* These sizes are not compulsory, they just tend to offer better latency */ +size_t ZBUFFv04_recommendedDInSize(void); +size_t ZBUFFv04_recommendedDOutSize(void); + + +/* ************************************* +* Prefix - version detection +***************************************/ +#define ZSTDv04_magicNumber 0xFD2FB524 /* v0.4 */ + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_V04_H_91868324769238 */ diff --git a/third_party/zstd/include/zstd/legacy/zstd_v05.h b/third_party/zstd/include/zstd/legacy/zstd_v05.h new file mode 100644 index 00000000000..2dcffc92367 --- /dev/null +++ b/third_party/zstd/include/zstd/legacy/zstd_v05.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTDv05_H +#define ZSTDv05_H + +#if defined (__cplusplus) +extern "C" { +#endif + +/*-************************************* +* Dependencies +***************************************/ +#include /* size_t */ +#include "../common/mem.h" /* U64, U32 */ + + +/* ************************************* +* Simple functions +***************************************/ +/*! ZSTDv05_decompress() : + `compressedSize` : is the _exact_ size of the compressed blob, otherwise decompression will fail. + `dstCapacity` must be large enough, equal or larger than originalSize. + @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), + or an errorCode if it fails (which can be tested using ZSTDv05_isError()) */ +size_t ZSTDv05_decompress( void* dst, size_t dstCapacity, + const void* src, size_t compressedSize); + + /** + ZSTDv05_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.5.x format + srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + cSize (output parameter) : the number of bytes that would be read to decompress this frame + or an error code if it fails (which can be tested using ZSTDv01_isError()) + dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame + or ZSTD_CONTENTSIZE_ERROR if an error occurs + + note : assumes `cSize` and `dBound` are _not_ NULL. + */ +void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); + +/* ************************************* +* Helper functions +***************************************/ +/* Error Management */ +unsigned ZSTDv05_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ +const char* ZSTDv05_getErrorName(size_t code); /*!< provides readable string for an error code */ + + +/* ************************************* +* Explicit memory management +***************************************/ +/** Decompression context */ +typedef struct ZSTDv05_DCtx_s ZSTDv05_DCtx; +ZSTDv05_DCtx* ZSTDv05_createDCtx(void); +size_t ZSTDv05_freeDCtx(ZSTDv05_DCtx* dctx); /*!< @return : errorCode */ + +/** ZSTDv05_decompressDCtx() : +* Same as ZSTDv05_decompress(), but requires an already allocated ZSTDv05_DCtx (see ZSTDv05_createDCtx()) */ +size_t ZSTDv05_decompressDCtx(ZSTDv05_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + + +/*-*********************** +* Simple Dictionary API +*************************/ +/*! ZSTDv05_decompress_usingDict() : +* Decompression using a pre-defined Dictionary content (see dictBuilder). +* Dictionary must be identical to the one used during compression, otherwise regenerated data will be corrupted. +* Note : dict can be NULL, in which case, it's equivalent to ZSTDv05_decompressDCtx() */ +size_t ZSTDv05_decompress_usingDict(ZSTDv05_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize); + +/*-************************ +* Advanced Streaming API +***************************/ +typedef enum { ZSTDv05_fast, ZSTDv05_greedy, ZSTDv05_lazy, ZSTDv05_lazy2, ZSTDv05_btlazy2, ZSTDv05_opt, ZSTDv05_btopt } ZSTDv05_strategy; +typedef struct { + U64 srcSize; + U32 windowLog; /* the only useful information to retrieve */ + U32 contentLog; U32 hashLog; U32 searchLog; U32 searchLength; U32 targetLength; ZSTDv05_strategy strategy; +} ZSTDv05_parameters; +size_t ZSTDv05_getFrameParams(ZSTDv05_parameters* params, const void* src, size_t srcSize); + +size_t ZSTDv05_decompressBegin_usingDict(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize); +void ZSTDv05_copyDCtx(ZSTDv05_DCtx* dstDCtx, const ZSTDv05_DCtx* srcDCtx); +size_t ZSTDv05_nextSrcSizeToDecompress(ZSTDv05_DCtx* dctx); +size_t ZSTDv05_decompressContinue(ZSTDv05_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + + +/*-*********************** +* ZBUFF API +*************************/ +typedef struct ZBUFFv05_DCtx_s ZBUFFv05_DCtx; +ZBUFFv05_DCtx* ZBUFFv05_createDCtx(void); +size_t ZBUFFv05_freeDCtx(ZBUFFv05_DCtx* dctx); + +size_t ZBUFFv05_decompressInit(ZBUFFv05_DCtx* dctx); +size_t ZBUFFv05_decompressInitDictionary(ZBUFFv05_DCtx* dctx, const void* dict, size_t dictSize); + +size_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* dctx, + void* dst, size_t* dstCapacityPtr, + const void* src, size_t* srcSizePtr); + +/*-*************************************************************************** +* Streaming decompression +* +* A ZBUFFv05_DCtx object is required to track streaming operations. +* Use ZBUFFv05_createDCtx() and ZBUFFv05_freeDCtx() to create/release resources. +* Use ZBUFFv05_decompressInit() to start a new decompression operation, +* or ZBUFFv05_decompressInitDictionary() if decompression requires a dictionary. +* Note that ZBUFFv05_DCtx objects can be reused multiple times. +* +* Use ZBUFFv05_decompressContinue() repetitively to consume your input. +* *srcSizePtr and *dstCapacityPtr can be any size. +* The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr. +* Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again. +* The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters or change @dst. +* @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency) +* or 0 when a frame is completely decoded +* or an error code, which can be tested using ZBUFFv05_isError(). +* +* Hint : recommended buffer sizes (not compulsory) : ZBUFFv05_recommendedDInSize() / ZBUFFv05_recommendedDOutSize() +* output : ZBUFFv05_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded. +* input : ZBUFFv05_recommendedDInSize==128Kb+3; just follow indications from ZBUFFv05_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 . +* *******************************************************************************/ + + +/* ************************************* +* Tool functions +***************************************/ +unsigned ZBUFFv05_isError(size_t errorCode); +const char* ZBUFFv05_getErrorName(size_t errorCode); + +/** Functions below provide recommended buffer sizes for Compression or Decompression operations. +* These sizes are just hints, and tend to offer better latency */ +size_t ZBUFFv05_recommendedDInSize(void); +size_t ZBUFFv05_recommendedDOutSize(void); + + + +/*-************************************* +* Constants +***************************************/ +#define ZSTDv05_MAGICNUMBER 0xFD2FB525 /* v0.5 */ + + + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTDv0505_H */ diff --git a/third_party/zstd/include/zstd/legacy/zstd_v06.h b/third_party/zstd/include/zstd/legacy/zstd_v06.h new file mode 100644 index 00000000000..633891010d7 --- /dev/null +++ b/third_party/zstd/include/zstd/legacy/zstd_v06.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTDv06_H +#define ZSTDv06_H + +#if defined (__cplusplus) +extern "C" { +#endif + +/*====== Dependency ======*/ +#include /* size_t */ + + +/*====== Export for Windows ======*/ +/*! +* ZSTDv06_DLL_EXPORT : +* Enable exporting of functions when building a Windows DLL +*/ +#if defined(_WIN32) && defined(ZSTDv06_DLL_EXPORT) && (ZSTDv06_DLL_EXPORT==1) +# define ZSTDLIBv06_API __declspec(dllexport) +#else +# define ZSTDLIBv06_API +#endif + + +/* ************************************* +* Simple functions +***************************************/ +/*! ZSTDv06_decompress() : + `compressedSize` : is the _exact_ size of the compressed blob, otherwise decompression will fail. + `dstCapacity` must be large enough, equal or larger than originalSize. + @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), + or an errorCode if it fails (which can be tested using ZSTDv06_isError()) */ +ZSTDLIBv06_API size_t ZSTDv06_decompress( void* dst, size_t dstCapacity, + const void* src, size_t compressedSize); + +/** +ZSTDv06_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.6.x format + srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + cSize (output parameter) : the number of bytes that would be read to decompress this frame + or an error code if it fails (which can be tested using ZSTDv01_isError()) + dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame + or ZSTD_CONTENTSIZE_ERROR if an error occurs + + note : assumes `cSize` and `dBound` are _not_ NULL. +*/ +void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); + +/* ************************************* +* Helper functions +***************************************/ +ZSTDLIBv06_API size_t ZSTDv06_compressBound(size_t srcSize); /*!< maximum compressed size (worst case scenario) */ + +/* Error Management */ +ZSTDLIBv06_API unsigned ZSTDv06_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ +ZSTDLIBv06_API const char* ZSTDv06_getErrorName(size_t code); /*!< provides readable string for an error code */ + + +/* ************************************* +* Explicit memory management +***************************************/ +/** Decompression context */ +typedef struct ZSTDv06_DCtx_s ZSTDv06_DCtx; +ZSTDLIBv06_API ZSTDv06_DCtx* ZSTDv06_createDCtx(void); +ZSTDLIBv06_API size_t ZSTDv06_freeDCtx(ZSTDv06_DCtx* dctx); /*!< @return : errorCode */ + +/** ZSTDv06_decompressDCtx() : +* Same as ZSTDv06_decompress(), but requires an already allocated ZSTDv06_DCtx (see ZSTDv06_createDCtx()) */ +ZSTDLIBv06_API size_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + + +/*-*********************** +* Dictionary API +*************************/ +/*! ZSTDv06_decompress_usingDict() : +* Decompression using a pre-defined Dictionary content (see dictBuilder). +* Dictionary must be identical to the one used during compression, otherwise regenerated data will be corrupted. +* Note : dict can be NULL, in which case, it's equivalent to ZSTDv06_decompressDCtx() */ +ZSTDLIBv06_API size_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize); + + +/*-************************ +* Advanced Streaming API +***************************/ +struct ZSTDv06_frameParams_s { unsigned long long frameContentSize; unsigned windowLog; }; +typedef struct ZSTDv06_frameParams_s ZSTDv06_frameParams; + +ZSTDLIBv06_API size_t ZSTDv06_getFrameParams(ZSTDv06_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input */ +ZSTDLIBv06_API size_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize); +ZSTDLIBv06_API void ZSTDv06_copyDCtx(ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx); + +ZSTDLIBv06_API size_t ZSTDv06_nextSrcSizeToDecompress(ZSTDv06_DCtx* dctx); +ZSTDLIBv06_API size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + + + +/* ************************************* +* ZBUFF API +***************************************/ + +typedef struct ZBUFFv06_DCtx_s ZBUFFv06_DCtx; +ZSTDLIBv06_API ZBUFFv06_DCtx* ZBUFFv06_createDCtx(void); +ZSTDLIBv06_API size_t ZBUFFv06_freeDCtx(ZBUFFv06_DCtx* dctx); + +ZSTDLIBv06_API size_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* dctx); +ZSTDLIBv06_API size_t ZBUFFv06_decompressInitDictionary(ZBUFFv06_DCtx* dctx, const void* dict, size_t dictSize); + +ZSTDLIBv06_API size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* dctx, + void* dst, size_t* dstCapacityPtr, + const void* src, size_t* srcSizePtr); + +/*-*************************************************************************** +* Streaming decompression howto +* +* A ZBUFFv06_DCtx object is required to track streaming operations. +* Use ZBUFFv06_createDCtx() and ZBUFFv06_freeDCtx() to create/release resources. +* Use ZBUFFv06_decompressInit() to start a new decompression operation, +* or ZBUFFv06_decompressInitDictionary() if decompression requires a dictionary. +* Note that ZBUFFv06_DCtx objects can be re-init multiple times. +* +* Use ZBUFFv06_decompressContinue() repetitively to consume your input. +* *srcSizePtr and *dstCapacityPtr can be any size. +* The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr. +* Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again. +* The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`. +* @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency), +* or 0 when a frame is completely decoded, +* or an error code, which can be tested using ZBUFFv06_isError(). +* +* Hint : recommended buffer sizes (not compulsory) : ZBUFFv06_recommendedDInSize() and ZBUFFv06_recommendedDOutSize() +* output : ZBUFFv06_recommendedDOutSize== 128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded. +* input : ZBUFFv06_recommendedDInSize == 128KB + 3; +* just follow indications from ZBUFFv06_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 . +* *******************************************************************************/ + + +/* ************************************* +* Tool functions +***************************************/ +ZSTDLIBv06_API unsigned ZBUFFv06_isError(size_t errorCode); +ZSTDLIBv06_API const char* ZBUFFv06_getErrorName(size_t errorCode); + +/** Functions below provide recommended buffer sizes for Compression or Decompression operations. +* These sizes are just hints, they tend to offer better latency */ +ZSTDLIBv06_API size_t ZBUFFv06_recommendedDInSize(void); +ZSTDLIBv06_API size_t ZBUFFv06_recommendedDOutSize(void); + + +/*-************************************* +* Constants +***************************************/ +#define ZSTDv06_MAGICNUMBER 0xFD2FB526 /* v0.6 */ + + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTDv06_BUFFERED_H */ diff --git a/third_party/zstd/include/zstd/legacy/zstd_v07.h b/third_party/zstd/include/zstd/legacy/zstd_v07.h new file mode 100644 index 00000000000..1ff39041f88 --- /dev/null +++ b/third_party/zstd/include/zstd/legacy/zstd_v07.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef ZSTDv07_H_235446 +#define ZSTDv07_H_235446 + +#if defined (__cplusplus) +extern "C" { +#endif + +/*====== Dependency ======*/ +#include /* size_t */ + + +/*====== Export for Windows ======*/ +/*! +* ZSTDv07_DLL_EXPORT : +* Enable exporting of functions when building a Windows DLL +*/ +#if defined(_WIN32) && defined(ZSTDv07_DLL_EXPORT) && (ZSTDv07_DLL_EXPORT==1) +# define ZSTDLIBv07_API __declspec(dllexport) +#else +# define ZSTDLIBv07_API +#endif + + +/* ************************************* +* Simple API +***************************************/ +/*! ZSTDv07_getDecompressedSize() : +* @return : decompressed size if known, 0 otherwise. + note 1 : if `0`, follow up with ZSTDv07_getFrameParams() to know precise failure cause. + note 2 : decompressed size could be wrong or intentionally modified ! + always ensure results fit within application's authorized limits */ +unsigned long long ZSTDv07_getDecompressedSize(const void* src, size_t srcSize); + +/*! ZSTDv07_decompress() : + `compressedSize` : must be _exact_ size of compressed input, otherwise decompression will fail. + `dstCapacity` must be equal or larger than originalSize. + @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), + or an errorCode if it fails (which can be tested using ZSTDv07_isError()) */ +ZSTDLIBv07_API size_t ZSTDv07_decompress( void* dst, size_t dstCapacity, + const void* src, size_t compressedSize); + +/** +ZSTDv07_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.7.x format + srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + cSize (output parameter) : the number of bytes that would be read to decompress this frame + or an error code if it fails (which can be tested using ZSTDv01_isError()) + dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame + or ZSTD_CONTENTSIZE_ERROR if an error occurs + + note : assumes `cSize` and `dBound` are _not_ NULL. +*/ +void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); + +/*====== Helper functions ======*/ +ZSTDLIBv07_API unsigned ZSTDv07_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ +ZSTDLIBv07_API const char* ZSTDv07_getErrorName(size_t code); /*!< provides readable string from an error code */ + + +/*-************************************* +* Explicit memory management +***************************************/ +/** Decompression context */ +typedef struct ZSTDv07_DCtx_s ZSTDv07_DCtx; +ZSTDLIBv07_API ZSTDv07_DCtx* ZSTDv07_createDCtx(void); +ZSTDLIBv07_API size_t ZSTDv07_freeDCtx(ZSTDv07_DCtx* dctx); /*!< @return : errorCode */ + +/** ZSTDv07_decompressDCtx() : +* Same as ZSTDv07_decompress(), requires an allocated ZSTDv07_DCtx (see ZSTDv07_createDCtx()) */ +ZSTDLIBv07_API size_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); + + +/*-************************ +* Simple dictionary API +***************************/ +/*! ZSTDv07_decompress_usingDict() : +* Decompression using a pre-defined Dictionary content (see dictBuilder). +* Dictionary must be identical to the one used during compression. +* Note : This function load the dictionary, resulting in a significant startup time */ +ZSTDLIBv07_API size_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const void* dict,size_t dictSize); + + +/*-************************** +* Advanced Dictionary API +****************************/ +/*! ZSTDv07_createDDict() : +* Create a digested dictionary, ready to start decompression operation without startup delay. +* `dict` can be released after creation */ +typedef struct ZSTDv07_DDict_s ZSTDv07_DDict; +ZSTDLIBv07_API ZSTDv07_DDict* ZSTDv07_createDDict(const void* dict, size_t dictSize); +ZSTDLIBv07_API size_t ZSTDv07_freeDDict(ZSTDv07_DDict* ddict); + +/*! ZSTDv07_decompress_usingDDict() : +* Decompression using a pre-digested Dictionary +* Faster startup than ZSTDv07_decompress_usingDict(), recommended when same dictionary is used multiple times. */ +ZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx, + void* dst, size_t dstCapacity, + const void* src, size_t srcSize, + const ZSTDv07_DDict* ddict); + +typedef struct { + unsigned long long frameContentSize; + unsigned windowSize; + unsigned dictID; + unsigned checksumFlag; +} ZSTDv07_frameParams; + +ZSTDLIBv07_API size_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input */ + + + + +/* ************************************* +* Streaming functions +***************************************/ +typedef struct ZBUFFv07_DCtx_s ZBUFFv07_DCtx; +ZSTDLIBv07_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx(void); +ZSTDLIBv07_API size_t ZBUFFv07_freeDCtx(ZBUFFv07_DCtx* dctx); + +ZSTDLIBv07_API size_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* dctx); +ZSTDLIBv07_API size_t ZBUFFv07_decompressInitDictionary(ZBUFFv07_DCtx* dctx, const void* dict, size_t dictSize); + +ZSTDLIBv07_API size_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* dctx, + void* dst, size_t* dstCapacityPtr, + const void* src, size_t* srcSizePtr); + +/*-*************************************************************************** +* Streaming decompression howto +* +* A ZBUFFv07_DCtx object is required to track streaming operations. +* Use ZBUFFv07_createDCtx() and ZBUFFv07_freeDCtx() to create/release resources. +* Use ZBUFFv07_decompressInit() to start a new decompression operation, +* or ZBUFFv07_decompressInitDictionary() if decompression requires a dictionary. +* Note that ZBUFFv07_DCtx objects can be re-init multiple times. +* +* Use ZBUFFv07_decompressContinue() repetitively to consume your input. +* *srcSizePtr and *dstCapacityPtr can be any size. +* The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr. +* Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again. +* The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`. +* @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency), +* or 0 when a frame is completely decoded, +* or an error code, which can be tested using ZBUFFv07_isError(). +* +* Hint : recommended buffer sizes (not compulsory) : ZBUFFv07_recommendedDInSize() and ZBUFFv07_recommendedDOutSize() +* output : ZBUFFv07_recommendedDOutSize== 128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded. +* input : ZBUFFv07_recommendedDInSize == 128KB + 3; +* just follow indications from ZBUFFv07_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 . +* *******************************************************************************/ + + +/* ************************************* +* Tool functions +***************************************/ +ZSTDLIBv07_API unsigned ZBUFFv07_isError(size_t errorCode); +ZSTDLIBv07_API const char* ZBUFFv07_getErrorName(size_t errorCode); + +/** Functions below provide recommended buffer sizes for Compression or Decompression operations. +* These sizes are just hints, they tend to offer better latency */ +ZSTDLIBv07_API size_t ZBUFFv07_recommendedDInSize(void); +ZSTDLIBv07_API size_t ZBUFFv07_recommendedDOutSize(void); + + +/*-************************************* +* Constants +***************************************/ +#define ZSTDv07_MAGICNUMBER 0xFD2FB527 /* v0.7 */ + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTDv07_H_235446 */ diff --git a/third_party/zstd/include/zstd_static.h b/third_party/zstd/include/zstd_static.h deleted file mode 100644 index e4f1f3b05ef..00000000000 --- a/third_party/zstd/include/zstd_static.h +++ /dev/null @@ -1,1070 +0,0 @@ - -/* ************************************************************************************** - * ADVANCED AND EXPERIMENTAL FUNCTIONS - **************************************************************************************** - * The definitions in the following section are considered experimental. - * They are provided for advanced scenarios. - * They should never be used with a dynamic library, as prototypes may change in the future. - * Use them only in association with static linking. - * ***************************************************************************************/ - -#ifndef ZSTD_H_ZSTD_STATIC_LINKING_ONLY -#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY - -namespace duckdb_zstd { - -/**************************************************************************************** - * experimental API (static linking only) - **************************************************************************************** - * The following symbols and constants - * are not planned to join "stable API" status in the near future. - * They can still change in future versions. - * Some of them are planned to remain in the static_only section indefinitely. - * Some of them might be removed in the future (especially when redundant with existing stable functions) - * ***************************************************************************************/ - -#define ZSTD_FRAMEHEADERSIZE_PREFIX(format) ((format) == ZSTD_f_zstd1 ? 5 : 1) /* minimum input size required to query frame header size */ -#define ZSTD_FRAMEHEADERSIZE_MIN(format) ((format) == ZSTD_f_zstd1 ? 6 : 2) -#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* can be useful for static allocation */ -#define ZSTD_SKIPPABLEHEADERSIZE 8 - -/* compression parameter bounds */ -#define ZSTD_WINDOWLOG_MAX_32 30 -#define ZSTD_WINDOWLOG_MAX_64 31 -#define ZSTD_WINDOWLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64)) -#define ZSTD_WINDOWLOG_MIN 10 -#define ZSTD_HASHLOG_MAX ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30) -#define ZSTD_HASHLOG_MIN 6 -#define ZSTD_CHAINLOG_MAX_32 29 -#define ZSTD_CHAINLOG_MAX_64 30 -#define ZSTD_CHAINLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64)) -#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN -#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1) -#define ZSTD_SEARCHLOG_MIN 1 -#define ZSTD_MINMATCH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */ -#define ZSTD_MINMATCH_MIN 3 /* only for ZSTD_btopt+, faster strategies are limited to 4 */ -#define ZSTD_TARGETLENGTH_MAX ZSTD_BLOCKSIZE_MAX -#define ZSTD_TARGETLENGTH_MIN 0 /* note : comparing this constant to an unsigned results in a tautological test */ -#define ZSTD_STRATEGY_MIN ZSTD_fast -#define ZSTD_STRATEGY_MAX ZSTD_btultra2 - - -#define ZSTD_OVERLAPLOG_MIN 0 -#define ZSTD_OVERLAPLOG_MAX 9 - -#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27 /* by default, the streaming decoder will refuse any frame - * requiring larger than (1< 3, then this is seqDef.offset - 3 - * If seqDef.offset < 3, then this is the corresponding repeat offset - * But if seqDef.offset < 3 and litLength == 0, this is the - * repeat offset before the corresponding repeat offset - * And if seqDef.offset == 3 and litLength == 0, this is the - * most recent repeat offset - 1 - */ - unsigned int offset; - unsigned int litLength; /* Literal length */ - unsigned int matchLength; /* Match length */ - /* 0 when seq not rep and seqDef.offset otherwise - * when litLength == 0 this will be <= 4, otherwise <= 3 like normal - */ - unsigned int rep; -} ZSTD_Sequence; - -typedef struct { - unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */ - unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ - unsigned hashLog; /**< dispatch table : larger == faster, more memory */ - unsigned searchLog; /**< nb of searches : larger == more compression, slower */ - unsigned minMatch; /**< match length searched : larger == faster decompression, sometimes less compression */ - unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */ - ZSTD_strategy strategy; /**< see ZSTD_strategy definition above */ -} ZSTD_compressionParameters; - -typedef struct { - int contentSizeFlag; /**< 1: content size will be in frame header (when known) */ - int checksumFlag; /**< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */ - int noDictIDFlag; /**< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */ -} ZSTD_frameParameters; - -typedef struct { - ZSTD_compressionParameters cParams; - ZSTD_frameParameters fParams; -} ZSTD_parameters; - -typedef enum { - ZSTD_dct_auto = 0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */ - ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */ - ZSTD_dct_fullDict = 2 /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */ -} ZSTD_dictContentType_e; - -typedef enum { - ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */ - ZSTD_dlm_byRef = 1 /**< Reference dictionary content -- the dictionary buffer must outlive its users. */ -} ZSTD_dictLoadMethod_e; - -typedef enum { - ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */ - ZSTD_f_zstd1_magicless = 1 /* Variant of zstd frame format, without initial 4-bytes magic number. - * Useful to save 4 bytes per generated frame. - * Decoder cannot recognise automatically this format, requiring this instruction. */ -} ZSTD_format_e; - -typedef enum { - /* Note: this enum and the behavior it controls are effectively internal - * implementation details of the compressor. They are expected to continue - * to evolve and should be considered only in the context of extremely - * advanced performance tuning. - * - * Zstd currently supports the use of a CDict in three ways: - * - * - The contents of the CDict can be copied into the working context. This - * means that the compression can search both the dictionary and input - * while operating on a single set of internal tables. This makes - * the compression faster per-byte of input. However, the initial copy of - * the CDict's tables incurs a fixed cost at the beginning of the - * compression. For small compressions (< 8 KB), that copy can dominate - * the cost of the compression. - * - * - The CDict's tables can be used in-place. In this model, compression is - * slower per input byte, because the compressor has to search two sets of - * tables. However, this model incurs no start-up cost (as long as the - * working context's tables can be reused). For small inputs, this can be - * faster than copying the CDict's tables. - * - * - The CDict's tables are not used at all, and instead we use the working - * context alone to reload the dictionary and use params based on the source - * size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict(). - * This method is effective when the dictionary sizes are very small relative - * to the input size, and the input size is fairly large to begin with. - * - * Zstd has a simple internal heuristic that selects which strategy to use - * at the beginning of a compression. However, if experimentation shows that - * Zstd is making poor choices, it is possible to override that choice with - * this enum. - */ - ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */ - ZSTD_dictForceAttach = 1, /* Never copy the dictionary. */ - ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */ - ZSTD_dictForceLoad = 3 /* Always reload the dictionary */ -} ZSTD_dictAttachPref_e; - -typedef enum { - ZSTD_lcm_auto = 0, /**< Automatically determine the compression mode based on the compression level. - * Negative compression levels will be uncompressed, and positive compression - * levels will be compressed. */ - ZSTD_lcm_huffman = 1, /**< Always attempt Huffman compression. Uncompressed literals will still be - * emitted if Huffman compression is not profitable. */ - ZSTD_lcm_uncompressed = 2 /**< Always emit uncompressed literals. */ -} ZSTD_literalCompressionMode_e; - - -/*************************************** -* Frame size functions -***************************************/ - -/*! ZSTD_findDecompressedSize() : - * `src` should point to the start of a series of ZSTD encoded and/or skippable frames - * `srcSize` must be the _exact_ size of this series - * (i.e. there should be a frame boundary at `src + srcSize`) - * @return : - decompressed size of all data in all successive frames - * - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN - * - if an error occurred: ZSTD_CONTENTSIZE_ERROR - * - * note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. - * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. - * In which case, it's necessary to use streaming mode to decompress data. - * note 2 : decompressed size is always present when compression is done with ZSTD_compress() - * note 3 : decompressed size can be very large (64-bits value), - * potentially larger than what local system can handle as a single memory segment. - * In which case, it's necessary to use streaming mode to decompress data. - * note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. - * Always ensure result fits within application's authorized limits. - * Each application can set its own limits. - * note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to - * read each contained frame header. This is fast as most of the data is skipped, - * however it does mean that all frame data must be present and valid. */ -ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize); - -/*! ZSTD_decompressBound() : - * `src` should point to the start of a series of ZSTD encoded and/or skippable frames - * `srcSize` must be the _exact_ size of this series - * (i.e. there should be a frame boundary at `src + srcSize`) - * @return : - upper-bound for the decompressed size of all data in all successive frames - * - if an error occured: ZSTD_CONTENTSIZE_ERROR - * - * note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame. - * note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`. - * in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value. - * note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by: - * upper-bound = # blocks * min(128 KB, Window_Size) - */ -ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize); - -/*! ZSTD_frameHeaderSize() : - * srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX. - * @return : size of the Frame Header, - * or an error code (if srcSize is too small) */ -ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); - -/*! ZSTD_getSequences() : - * Extract sequences from the sequence store - * zc can be used to insert custom compression params. - * This function invokes ZSTD_compress2 - * @return : number of sequences extracted - */ -ZSTDLIB_API size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, - size_t outSeqsSize, const void* src, size_t srcSize); - - -/*************************************** -* Memory management -***************************************/ - -/*! ZSTD_estimate*() : - * These functions make it possible to estimate memory usage - * of a future {D,C}Ctx, before its creation. - * - * ZSTD_estimateCCtxSize() will provide a memory budget large enough - * for any compression level up to selected one. - * Note : Unlike ZSTD_estimateCStreamSize*(), this estimate - * does not include space for a window buffer. - * Therefore, the estimation is only guaranteed for single-shot compressions, not streaming. - * The estimate will assume the input may be arbitrarily large, - * which is the worst case. - * - * When srcSize can be bound by a known and rather "small" value, - * this fact can be used to provide a tighter estimation - * because the CCtx compression context will need less memory. - * This tighter estimation can be provided by more advanced functions - * ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(), - * and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter(). - * Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits. - * - * Note 2 : only single-threaded compression is supported. - * ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1. - */ -ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel); -ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams); -ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params); -ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void); - -/*! ZSTD_estimateCStreamSize() : - * ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one. - * It will also consider src size to be arbitrarily "large", which is worst case. - * If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation. - * ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel. - * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1. - * Note : CStream size estimation is only correct for single-threaded compression. - * ZSTD_DStream memory budget depends on window Size. - * This information can be passed manually, using ZSTD_estimateDStreamSize, - * or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame(); - * Note : if streaming is init with function ZSTD_init?Stream_usingDict(), - * an internal ?Dict will be created, which additional size is not estimated here. - * In this case, get total size by adding ZSTD_estimate?DictSize */ -ZSTDLIB_API size_t ZSTD_estimateCStreamSize(int compressionLevel); -ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams); -ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params); -ZSTDLIB_API size_t ZSTD_estimateDStreamSize(size_t windowSize); -ZSTDLIB_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize); - -/*! ZSTD_estimate?DictSize() : - * ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict(). - * ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced(). - * Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller. - */ -ZSTDLIB_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel); -ZSTDLIB_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod); -ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod); - -/*! ZSTD_initStatic*() : - * Initialize an object using a pre-allocated fixed-size buffer. - * workspace: The memory area to emplace the object into. - * Provided pointer *must be 8-bytes aligned*. - * Buffer must outlive object. - * workspaceSize: Use ZSTD_estimate*Size() to determine - * how large workspace must be to support target scenario. - * @return : pointer to object (same address as workspace, just different type), - * or NULL if error (size too small, incorrect alignment, etc.) - * Note : zstd will never resize nor malloc() when using a static buffer. - * If the object requires more memory than available, - * zstd will just error out (typically ZSTD_error_memory_allocation). - * Note 2 : there is no corresponding "free" function. - * Since workspace is allocated externally, it must be freed externally too. - * Note 3 : cParams : use ZSTD_getCParams() to convert a compression level - * into its associated cParams. - * Limitation 1 : currently not compatible with internal dictionary creation, triggered by - * ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict(). - * Limitation 2 : static cctx currently not compatible with multi-threading. - * Limitation 3 : static dctx is incompatible with legacy support. - */ -ZSTDLIB_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize); -ZSTDLIB_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */ - -ZSTDLIB_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize); -ZSTDLIB_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */ - -ZSTDLIB_API const ZSTD_CDict* ZSTD_initStaticCDict( - void* workspace, size_t workspaceSize, - const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams); - -ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict( - void* workspace, size_t workspaceSize, - const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType); - - -/*! Custom memory allocation : - * These prototypes make it possible to pass your own allocation/free functions. - * ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below. - * All allocation/free operations will be completed using these custom variants instead of regular ones. - */ -typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); -typedef void (*ZSTD_freeFunction) (void* opaque, void* address); -typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; - -ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); -ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); -ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem); -ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem); - -ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams, - ZSTD_customMem customMem); - -ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, - ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, - ZSTD_customMem customMem); - - - -/*************************************** -* Advanced compression functions -***************************************/ - -/*! ZSTD_createCDict_byReference() : - * Create a digested dictionary for compression - * Dictionary content is just referenced, not duplicated. - * As a consequence, `dictBuffer` **must** outlive CDict, - * and its content must remain unmodified throughout the lifetime of CDict. - * note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */ -ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel); - -/*! ZSTD_getCParams() : - * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. - * `estimatedSrcSize` value is optional, select 0 if not known */ -ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); - -/*! ZSTD_getParams() : - * same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`. - * All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */ -ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); - -/*! ZSTD_checkCParams() : - * Ensure param values remain within authorized range. - * @return 0 on success, or an error code (can be checked with ZSTD_isError()) */ -ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params); - -/*! ZSTD_adjustCParams() : - * optimize params for a given `srcSize` and `dictSize`. - * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN. - * `dictSize` must be `0` when there is no dictionary. - * cPar can be invalid : all parameters will be clamped within valid range in the @return struct. - * This function never fails (wide contract) */ -ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize); - -/*! ZSTD_compress_advanced() : - * Note : this function is now DEPRECATED. - * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters. - * This prototype will be marked as deprecated and generate compilation warning on reaching v1.5.x */ -ZSTDLIB_API size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict,size_t dictSize, - ZSTD_parameters params); - -/*! ZSTD_compress_usingCDict_advanced() : - * Note : this function is now REDUNDANT. - * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters. - * This prototype will be marked as deprecated and generate compilation warning in some future version */ -ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict, - ZSTD_frameParameters fParams); - - -/*! ZSTD_CCtx_loadDictionary_byReference() : - * Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx. - * It saves some memory, but also requires that `dict` outlives its usage within `cctx` */ -ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize); - -/*! ZSTD_CCtx_loadDictionary_advanced() : - * Same as ZSTD_CCtx_loadDictionary(), but gives finer control over - * how to load the dictionary (by copy ? by reference ?) - * and how to interpret it (automatic ? force raw mode ? full mode only ?) */ -ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); - -/*! ZSTD_CCtx_refPrefix_advanced() : - * Same as ZSTD_CCtx_refPrefix(), but gives finer control over - * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ -ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); - -/* === experimental parameters === */ -/* these parameters can be used with ZSTD_setParameter() - * they are not guaranteed to remain supported in the future */ - - /* Enables rsyncable mode, - * which makes compressed files more rsync friendly - * by adding periodic synchronization points to the compressed data. - * The target average block size is ZSTD_c_jobSize / 2. - * It's possible to modify the job size to increase or decrease - * the granularity of the synchronization point. - * Once the jobSize is smaller than the window size, - * it will result in compression ratio degradation. - * NOTE 1: rsyncable mode only works when multithreading is enabled. - * NOTE 2: rsyncable performs poorly in combination with long range mode, - * since it will decrease the effectiveness of synchronization points, - * though mileage may vary. - * NOTE 3: Rsyncable mode limits maximum compression speed to ~400 MB/s. - * If the selected compression level is already running significantly slower, - * the overall speed won't be significantly impacted. - */ - #define ZSTD_c_rsyncable ZSTD_c_experimentalParam1 - -/* Select a compression format. - * The value must be of type ZSTD_format_e. - * See ZSTD_format_e enum definition for details */ -#define ZSTD_c_format ZSTD_c_experimentalParam2 - -/* Force back-reference distances to remain < windowSize, - * even when referencing into Dictionary content (default:0) */ -#define ZSTD_c_forceMaxWindow ZSTD_c_experimentalParam3 - -/* Controls whether the contents of a CDict - * are used in place, or copied into the working context. - * Accepts values from the ZSTD_dictAttachPref_e enum. - * See the comments on that enum for an explanation of the feature. */ -#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4 - -/* Controls how the literals are compressed (default is auto). - * The value must be of type ZSTD_literalCompressionMode_e. - * See ZSTD_literalCompressionMode_t enum definition for details. - */ -#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5 - -/* Tries to fit compressed block size to be around targetCBlockSize. - * No target when targetCBlockSize == 0. - * There is no guarantee on compressed block size (default:0) */ -#define ZSTD_c_targetCBlockSize ZSTD_c_experimentalParam6 - -/* User's best guess of source size. - * Hint is not valid when srcSizeHint == 0. - * There is no guarantee that hint is close to actual source size, - * but compression ratio may regress significantly if guess considerably underestimates */ -#define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7 - -/*! ZSTD_CCtx_getParameter() : - * Get the requested compression parameter value, selected by enum ZSTD_cParameter, - * and store it into int* value. - * @return : 0, or an error code (which can be tested with ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value); - - -/*! ZSTD_CCtx_params : - * Quick howto : - * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure - * - ZSTD_CCtxParams_setParameter() : Push parameters one by one into - * an existing ZSTD_CCtx_params structure. - * This is similar to - * ZSTD_CCtx_setParameter(). - * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to - * an existing CCtx. - * These parameters will be applied to - * all subsequent frames. - * - ZSTD_compressStream2() : Do compression using the CCtx. - * - ZSTD_freeCCtxParams() : Free the memory. - * - * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams() - * for static allocation of CCtx for single-threaded compression. - */ -ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void); -ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); - -/*! ZSTD_CCtxParams_reset() : - * Reset params to default values. - */ -ZSTDLIB_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params); - -/*! ZSTD_CCtxParams_init() : - * Initializes the compression parameters of cctxParams according to - * compression level. All other parameters are reset to their default values. - */ -ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel); - -/*! ZSTD_CCtxParams_init_advanced() : - * Initializes the compression and frame parameters of cctxParams according to - * params. All other parameters are reset to their default values. - */ -ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params); - -/*! ZSTD_CCtxParams_setParameter() : - * Similar to ZSTD_CCtx_setParameter. - * Set one compression parameter, selected by enum ZSTD_cParameter. - * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams(). - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value); - -/*! ZSTD_CCtxParams_getParameter() : - * Similar to ZSTD_CCtx_getParameter. - * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter. - * @result : 0, or an error code (which can be tested with ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value); - -/*! ZSTD_CCtx_setParametersUsingCCtxParams() : - * Apply a set of ZSTD_CCtx_params to the compression context. - * This can be done even after compression is started, - * if nbWorkers==0, this will have no impact until a new compression is started. - * if nbWorkers>=1, new parameters will be picked up at next job, - * with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated). - */ -ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams( - ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params); - -/*! ZSTD_compressStream2_simpleArgs() : - * Same as ZSTD_compressStream2(), - * but using only integral types as arguments. - * This variant might be helpful for binders from dynamic languages - * which have troubles handling structures containing memory pointers. - */ -ZSTDLIB_API size_t ZSTD_compressStream2_simpleArgs ( - ZSTD_CCtx* cctx, - void* dst, size_t dstCapacity, size_t* dstPos, - const void* src, size_t srcSize, size_t* srcPos, - ZSTD_EndDirective endOp); - - -/*************************************** -* Advanced decompression functions -***************************************/ - -/*! ZSTD_isFrame() : - * Tells if the content of `buffer` starts with a valid Frame Identifier. - * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. - * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled. - * Note 3 : Skippable Frame Identifiers are considered valid. */ -ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size); - -/*! ZSTD_createDDict_byReference() : - * Create a digested dictionary, ready to start decompression operation without startup delay. - * Dictionary content is referenced, and therefore stays in dictBuffer. - * It is important that dictBuffer outlives DDict, - * it must remain read accessible throughout the lifetime of DDict */ -ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize); - -/*! ZSTD_DCtx_loadDictionary_byReference() : - * Same as ZSTD_DCtx_loadDictionary(), - * but references `dict` content instead of copying it into `dctx`. - * This saves memory if `dict` remains around., - * However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */ -ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); - -/*! ZSTD_DCtx_loadDictionary_advanced() : - * Same as ZSTD_DCtx_loadDictionary(), - * but gives direct control over - * how to load the dictionary (by copy ? by reference ?) - * and how to interpret it (automatic ? force raw mode ? full mode only ?). */ -ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType); - -/*! ZSTD_DCtx_refPrefix_advanced() : - * Same as ZSTD_DCtx_refPrefix(), but gives finer control over - * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */ -ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType); - -/*! ZSTD_DCtx_setMaxWindowSize() : - * Refuses allocating internal buffers for frames requiring a window size larger than provided limit. - * This protects a decoder context from reserving too much memory for itself (potential attack scenario). - * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode. - * By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) - * @return : 0, or an error code (which can be tested using ZSTD_isError()). - */ -ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize); - -/* ZSTD_d_format - * experimental parameter, - * allowing selection between ZSTD_format_e input compression formats - */ -#define ZSTD_d_format ZSTD_d_experimentalParam1 -/* ZSTD_d_stableOutBuffer - * Experimental parameter. - * Default is 0 == disabled. Set to 1 to enable. - * - * Tells the decompressor that the ZSTD_outBuffer will ALWAYS be the same - * between calls, except for the modifications that zstd makes to pos (the - * caller must not modify pos). This is checked by the decompressor, and - * decompression will fail if it ever changes. Therefore the ZSTD_outBuffer - * MUST be large enough to fit the entire decompressed frame. This will be - * checked when the frame content size is known. The data in the ZSTD_outBuffer - * in the range [dst, dst + pos) MUST not be modified during decompression - * or you will get data corruption. - * - * When this flags is enabled zstd won't allocate an output buffer, because - * it can write directly to the ZSTD_outBuffer, but it will still allocate - * an input buffer large enough to fit any compressed block. This will also - * avoid the memcpy() from the internal output buffer to the ZSTD_outBuffer. - * If you need to avoid the input buffer allocation use the buffer-less - * streaming API. - * - * NOTE: So long as the ZSTD_outBuffer always points to valid memory, using - * this flag is ALWAYS memory safe, and will never access out-of-bounds - * memory. However, decompression WILL fail if you violate the preconditions. - * - * WARNING: The data in the ZSTD_outBuffer in the range [dst, dst + pos) MUST - * not be modified during decompression or you will get data corruption. This - * is because zstd needs to reference data in the ZSTD_outBuffer to regenerate - * matches. Normally zstd maintains its own buffer for this purpose, but passing - * this flag tells zstd to use the user provided buffer. - */ -#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2 - -/*! ZSTD_DCtx_setFormat() : - * Instruct the decoder context about what kind of data to decode next. - * This instruction is mandatory to decode data without a fully-formed header, - * such ZSTD_f_zstd1_magicless for example. - * @return : 0, or an error code (which can be tested using ZSTD_isError()). */ -ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format); - -/*! ZSTD_decompressStream_simpleArgs() : - * Same as ZSTD_decompressStream(), - * but using only integral types as arguments. - * This can be helpful for binders from dynamic languages - * which have troubles handling structures containing memory pointers. - */ -ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs ( - ZSTD_DCtx* dctx, - void* dst, size_t dstCapacity, size_t* dstPos, - const void* src, size_t srcSize, size_t* srcPos); - - -/******************************************************************** -* Advanced streaming functions -* Warning : most of these functions are now redundant with the Advanced API. -* Once Advanced API reaches "stable" status, -* redundant functions will be deprecated, and then at some point removed. -********************************************************************/ - -/*===== Advanced Streaming compression functions =====*/ -/**! ZSTD_initCStream_srcSize() : - * This function is deprecated, and equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) - * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); - * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); - * - * pledgedSrcSize must be correct. If it is not known at init time, use - * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, - * "0" also disables frame content size field. It may be enabled in the future. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t -ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, - int compressionLevel, - unsigned long long pledgedSrcSize); - -/**! ZSTD_initCStream_usingDict() : - * This function is deprecated, and is equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); - * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); - * - * Creates of an internal CDict (incompatible with static CCtx), except if - * dict == NULL or dictSize < 8, in which case no dict is used. - * Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if - * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t -ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, - const void* dict, size_t dictSize, - int compressionLevel); - -/**! ZSTD_initCStream_advanced() : - * This function is deprecated, and is approximately equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * // Pseudocode: Set each zstd parameter and leave the rest as-is. - * for ((param, value) : params) { - * ZSTD_CCtx_setParameter(zcs, param, value); - * } - * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); - * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize); - * - * dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy. - * pledgedSrcSize must be correct. - * If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t -ZSTD_initCStream_advanced(ZSTD_CStream* zcs, - const void* dict, size_t dictSize, - ZSTD_parameters params, - unsigned long long pledgedSrcSize); - -/**! ZSTD_initCStream_usingCDict() : - * This function is deprecated, and equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * ZSTD_CCtx_refCDict(zcs, cdict); - * - * note : cdict will just be referenced, and must outlive compression session - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); - -/**! ZSTD_initCStream_usingCDict_advanced() : - * This function is DEPRECATED, and is approximately equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * // Pseudocode: Set each zstd frame parameter and leave the rest as-is. - * for ((fParam, value) : fParams) { - * ZSTD_CCtx_setParameter(zcs, fParam, value); - * } - * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); - * ZSTD_CCtx_refCDict(zcs, cdict); - * - * same as ZSTD_initCStream_usingCDict(), with control over frame parameters. - * pledgedSrcSize must be correct. If srcSize is not known at init time, use - * value ZSTD_CONTENTSIZE_UNKNOWN. - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t -ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, - const ZSTD_CDict* cdict, - ZSTD_frameParameters fParams, - unsigned long long pledgedSrcSize); - -/*! ZSTD_resetCStream() : - * This function is deprecated, and is equivalent to: - * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); - * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize); - * - * start a new frame, using same parameters from previous frame. - * This is typically useful to skip dictionary loading stage, since it will re-use it in-place. - * Note that zcs must be init at least once before using ZSTD_resetCStream(). - * If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN. - * If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end. - * For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs, - * but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead. - * @return : 0, or an error code (which can be tested using ZSTD_isError()) - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); - - -typedef struct { - unsigned long long ingested; /* nb input bytes read and buffered */ - unsigned long long consumed; /* nb input bytes actually compressed */ - unsigned long long produced; /* nb of compressed bytes generated and buffered */ - unsigned long long flushed; /* nb of compressed bytes flushed : not provided; can be tracked from caller side */ - unsigned currentJobID; /* MT only : latest started job nb */ - unsigned nbActiveWorkers; /* MT only : nb of workers actively compressing at probe time */ -} ZSTD_frameProgression; - -/* ZSTD_getFrameProgression() : - * tells how much data has been ingested (read from input) - * consumed (input actually compressed) and produced (output) for current frame. - * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed. - * Aggregates progression inside active worker threads. - */ -ZSTDLIB_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx); - -/*! ZSTD_toFlushNow() : - * Tell how many bytes are ready to be flushed immediately. - * Useful for multithreading scenarios (nbWorkers >= 1). - * Probe the oldest active job, defined as oldest job not yet entirely flushed, - * and check its output buffer. - * @return : amount of data stored in oldest job and ready to be flushed immediately. - * if @return == 0, it means either : - * + there is no active job (could be checked with ZSTD_frameProgression()), or - * + oldest job is still actively compressing data, - * but everything it has produced has also been flushed so far, - * therefore flush speed is limited by production speed of oldest job - * irrespective of the speed of concurrent (and newer) jobs. - */ -ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); - - -/*===== Advanced Streaming decompression functions =====*/ -/** - * This function is deprecated, and is equivalent to: - * - * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); - * ZSTD_DCtx_loadDictionary(zds, dict, dictSize); - * - * note: no dictionary will be used if dict == NULL or dictSize < 8 - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); - -/** - * This function is deprecated, and is equivalent to: - * - * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); - * ZSTD_DCtx_refDDict(zds, ddict); - * - * note : ddict is referenced, it must outlive decompression session - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); - -/** - * This function is deprecated, and is equivalent to: - * - * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); - * - * re-use decompression parameters from previous init; saves dictionary loading - * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x - */ -ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); - - -/********************************************************************* -* Buffer-less and synchronous inner streaming functions -* -* This is an advanced API, giving full control over buffer management, for users which need direct control over memory. -* But it's also a complex one, with several restrictions, documented below. -* Prefer normal streaming API for an easier experience. -********************************************************************* */ - -/** - Buffer-less streaming compression (synchronous mode) - - A ZSTD_CCtx object is required to track streaming operations. - Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource. - ZSTD_CCtx object can be re-used multiple times within successive compression operations. - - Start by initializing a context. - Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression, - or ZSTD_compressBegin_advanced(), for finer parameter control. - It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx() - - Then, consume your input using ZSTD_compressContinue(). - There are some important considerations to keep in mind when using this advanced function : - - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only. - - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks. - - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario. - Worst case evaluation is provided by ZSTD_compressBound(). - ZSTD_compressContinue() doesn't guarantee recover after a failed compression. - - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog). - It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks) - - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps. - In which case, it will "discard" the relevant memory section from its history. - - Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum. - It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame. - Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders. - - `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again. -*/ - -/*===== Buffer-less streaming compression functions =====*/ -ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel); -ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel); -ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */ -ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */ -ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */ -ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */ - -ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); - - -/*- - Buffer-less streaming decompression (synchronous mode) - - A ZSTD_DCtx object is required to track streaming operations. - Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. - A ZSTD_DCtx object can be re-used multiple times. - - First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader(). - Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough. - Data fragment must be large enough to ensure successful decoding. - `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough. - @result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled. - >0 : `srcSize` is too small, please provide at least @result bytes on next attempt. - errorCode, which can be tested using ZSTD_isError(). - - It fills a ZSTD_frameHeader structure with important information to correctly decode the frame, - such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`). - Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information. - As a consequence, check that values remain within valid application range. - For example, do not allocate memory blindly, check that `windowSize` is within expectation. - Each application can set its own limits, depending on local restrictions. - For extended interoperability, it is recommended to support `windowSize` of at least 8 MB. - - ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes. - ZSTD_decompressContinue() is very sensitive to contiguity, - if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place, - or that previous contiguous segment is large enough to properly handle maximum back-reference distance. - There are multiple ways to guarantee this condition. - - The most memory efficient way is to use a round buffer of sufficient size. - Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(), - which can @return an error code if required value is too large for current system (in 32-bits mode). - In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one, - up to the moment there is not enough room left in the buffer to guarantee decoding another full block, - which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`. - At which point, decoding can resume from the beginning of the buffer. - Note that already decoded data stored in the buffer should be flushed before being overwritten. - - There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory. - - Finally, if you control the compression process, you can also ignore all buffer size rules, - as long as the encoder and decoder progress in "lock-step", - aka use exactly the same buffer sizes, break contiguity at the same place, etc. - - Once buffers are setup, start decompression, with ZSTD_decompressBegin(). - If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict(). - - Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively. - ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue(). - ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail. - - @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity). - It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item. - It can also be an error code, which can be tested with ZSTD_isError(). - - A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero. - Context can then be reset to start a new decompression. - - Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType(). - This information is not required to properly decode a frame. - - == Special case : skippable frames == - - Skippable frames allow integration of user-defined data into a flow of concatenated frames. - Skippable frames will be ignored (skipped) by decompressor. - The format of skippable frames is as follows : - a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F - b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits - c) Frame Content - any content (User Data) of length equal to Frame Size - For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame. - For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content. -*/ - -/*===== Buffer-less streaming decompression functions =====*/ -typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e; -typedef struct { - unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */ - unsigned long long windowSize; /* can be very large, up to <= frameContentSize */ - unsigned blockSizeMax; - ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */ - unsigned headerSize; - unsigned dictID; - unsigned checksumFlag; -} ZSTD_frameHeader; - -/*! ZSTD_getFrameHeader() : - * decode Frame Header, or requires larger `srcSize`. - * @return : 0, `zfhPtr` is correctly filled, - * >0, `srcSize` is too small, value is wanted `srcSize` amount, - * or an error code, which can be tested using ZSTD_isError() */ -ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ -/*! ZSTD_getFrameHeader_advanced() : - * same as ZSTD_getFrameHeader(), - * with added capability to select a format (like ZSTD_f_zstd1_magicless) */ -ZSTDLIB_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format); -ZSTDLIB_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */ - -ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx); -ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize); -ZSTDLIB_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict); - -ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx); -ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); - -/* misc */ -ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx); -typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; -ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx); - - - - -/* ============================ */ -/** Block level API */ -/* ============================ */ - -/*! - Block functions produce and decode raw zstd blocks, without frame metadata. - Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes). - But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes. - - A few rules to respect : - - Compressing and decompressing require a context structure - + Use ZSTD_createCCtx() and ZSTD_createDCtx() - - It is necessary to init context before starting - + compression : any ZSTD_compressBegin*() variant, including with dictionary - + decompression : any ZSTD_decompressBegin*() variant, including with dictionary - + copyCCtx() and copyDCtx() can be used too - - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB - + If input is larger than a block size, it's necessary to split input data into multiple blocks - + For inputs larger than a single block, consider using regular ZSTD_compress() instead. - Frame metadata is not that costly, and quickly becomes negligible as source size grows larger than a block. - - When a block is considered not compressible enough, ZSTD_compressBlock() result will be 0 (zero) ! - ===> In which case, nothing is produced into `dst` ! - + User __must__ test for such outcome and deal directly with uncompressed data - + A block cannot be declared incompressible if ZSTD_compressBlock() return value was != 0. - Doing so would mess up with statistics history, leading to potential data corruption. - + ZSTD_decompressBlock() _doesn't accept uncompressed data as input_ !! - + In case of multiple successive blocks, should some of them be uncompressed, - decoder must be informed of their existence in order to follow proper history. - Use ZSTD_insertBlock() for such a case. -*/ - -/*===== Raw zstd block functions =====*/ -ZSTDLIB_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx); -ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -ZSTDLIB_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */ - -} - -#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */ diff --git a/third_party/zstd/legacy/zstd_v01.c b/third_party/zstd/legacy/zstd_v01.c new file mode 100644 index 00000000000..6cf51234a24 --- /dev/null +++ b/third_party/zstd/legacy/zstd_v01.c @@ -0,0 +1,2127 @@ +/* + * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + +/****************************************** +* Includes +******************************************/ +#include /* size_t, ptrdiff_t */ +#include "zstd_v01.h" +#include "../common/compiler.h" +#include "../common/error_private.h" + + +/****************************************** +* Static allocation +******************************************/ +/* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */ +#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) +* Increasing memory usage improves compression ratio +* Reduced memory usage can improve speed, due to cache effect +* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ +#define FSE_MAX_MEMORY_USAGE 14 +#define FSE_DEFAULT_MEMORY_USAGE 13 + +/* FSE_MAX_SYMBOL_VALUE : +* Maximum symbol value authorized. +* Required for proper stack allocation */ +#define FSE_MAX_SYMBOL_VALUE 255 + + +/**************************************************************** +* template functions type & suffix +****************************************************************/ +#define FSE_FUNCTION_TYPE BYTE +#define FSE_FUNCTION_EXTENSION + + +/**************************************************************** +* Byte symbol type +****************************************************************/ +typedef struct +{ + unsigned short newState; + unsigned char symbol; + unsigned char nbBits; +} FSE_decode_t; /* size == U32 */ + + + +/**************************************************************** +* Compiler specifics +****************************************************************/ +#ifdef _MSC_VER /* Visual Studio */ +# define FORCE_INLINE static __forceinline +# include /* For Visual 2005 */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ +#else +# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# ifdef __GNUC__ +# define FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define FORCE_INLINE static inline +# endif +# else +# define FORCE_INLINE static +# endif /* __STDC_VERSION__ */ +#endif + + +/**************************************************************** +* Includes +****************************************************************/ +#include /* malloc, free, qsort */ +#include /* memcpy, memset */ +#include /* printf (debug) */ + + +#ifndef MEM_ACCESS_MODULE +#define MEM_ACCESS_MODULE +/**************************************************************** +* Basic Types +*****************************************************************/ +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# include +typedef uint8_t BYTE; +typedef uint16_t U16; +typedef int16_t S16; +typedef uint32_t U32; +typedef int32_t S32; +typedef uint64_t U64; +typedef int64_t S64; +#else +typedef unsigned char BYTE; +typedef unsigned short U16; +typedef signed short S16; +typedef unsigned int U32; +typedef signed int S32; +typedef unsigned long long U64; +typedef signed long long S64; +#endif + +#endif /* MEM_ACCESS_MODULE */ + +/**************************************************************** +* Memory I/O +*****************************************************************/ + +static unsigned FSE_32bits(void) +{ + return sizeof(void*)==4; +} + +static unsigned FSE_isLittleEndian(void) +{ + const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + return one.c[0]; +} + +static U16 FSE_read16(const void* memPtr) +{ + U16 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static U32 FSE_read32(const void* memPtr) +{ + U32 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static U64 FSE_read64(const void* memPtr) +{ + U64 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static U16 FSE_readLE16(const void* memPtr) +{ + if (FSE_isLittleEndian()) + return FSE_read16(memPtr); + else + { + const BYTE* p = (const BYTE*)memPtr; + return (U16)(p[0] + (p[1]<<8)); + } +} + +static U32 FSE_readLE32(const void* memPtr) +{ + if (FSE_isLittleEndian()) + return FSE_read32(memPtr); + else + { + const BYTE* p = (const BYTE*)memPtr; + return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24)); + } +} + + +static U64 FSE_readLE64(const void* memPtr) +{ + if (FSE_isLittleEndian()) + return FSE_read64(memPtr); + else + { + const BYTE* p = (const BYTE*)memPtr; + return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24) + + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56)); + } +} + +static size_t FSE_readLEST(const void* memPtr) +{ + if (FSE_32bits()) + return (size_t)FSE_readLE32(memPtr); + else + return (size_t)FSE_readLE64(memPtr); +} + + + +/**************************************************************** +* Constants +*****************************************************************/ +#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2) +#define FSE_MAX_TABLESIZE (1U< FSE_TABLELOG_ABSOLUTE_MAX +#error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" +#endif + + +/**************************************************************** +* Error Management +****************************************************************/ +#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ + + +/**************************************************************** +* Complex types +****************************************************************/ +typedef struct +{ + int deltaFindState; + U32 deltaNbBits; +} FSE_symbolCompressionTransform; /* total 8 bytes */ + +typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; + +/**************************************************************** +* Internal functions +****************************************************************/ +FORCE_INLINE unsigned FSE_highbit32 (U32 val) +{ +# if defined(_MSC_VER) /* Visual */ + unsigned long r; + return _BitScanReverse(&r, val) ? (unsigned)r : 0; +# elif defined(__GNUC__) && (GCC_VERSION >= 304) /* GCC Intrinsic */ + return __builtin_clz (val) ^ 31; +# else /* Software version */ + static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; + U32 v = val; + unsigned r; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27]; + return r; +# endif +} + + +/**************************************************************** +* Templates +****************************************************************/ +/* + designed to be included + for type-specific functions (template emulation in C) + Objective is to write these functions only once, for improved maintenance +*/ + +/* safety checks */ +#ifndef FSE_FUNCTION_EXTENSION +# error "FSE_FUNCTION_EXTENSION must be defined" +#endif +#ifndef FSE_FUNCTION_TYPE +# error "FSE_FUNCTION_TYPE must be defined" +#endif + +/* Function names */ +#define FSE_CAT(X,Y) X##Y +#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y) +#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y) + + + +static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; } + +#define FSE_DECODE_TYPE FSE_decode_t + + +typedef struct { + U16 tableLog; + U16 fastMode; +} FSE_DTableHeader; /* sizeof U32 */ + +static size_t FSE_buildDTable +(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) +{ + void* ptr = dt; + FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; + FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*)(ptr) + 1; /* because dt is unsigned, 32-bits aligned on 32-bits */ + const U32 tableSize = 1 << tableLog; + const U32 tableMask = tableSize-1; + const U32 step = FSE_tableStep(tableSize); + U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1]; + U32 position = 0; + U32 highThreshold = tableSize-1; + const S16 largeLimit= (S16)(1 << (tableLog-1)); + U32 noLarge = 1; + U32 s; + + /* Sanity Checks */ + if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return (size_t)-FSE_ERROR_maxSymbolValue_tooLarge; + if (tableLog > FSE_MAX_TABLELOG) return (size_t)-FSE_ERROR_tableLog_tooLarge; + + /* Init, lay down lowprob symbols */ + DTableH[0].tableLog = (U16)tableLog; + for (s=0; s<=maxSymbolValue; s++) + { + if (normalizedCounter[s]==-1) + { + tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s; + symbolNext[s] = 1; + } + else + { + if (normalizedCounter[s] >= largeLimit) noLarge=0; + symbolNext[s] = normalizedCounter[s]; + } + } + + /* Spread symbols */ + for (s=0; s<=maxSymbolValue; s++) + { + int i; + for (i=0; i highThreshold) position = (position + step) & tableMask; /* lowprob area */ + } + } + + if (position!=0) return (size_t)-FSE_ERROR_GENERIC; /* position must reach all cells once, otherwise normalizedCounter is incorrect */ + + /* Build Decoding table */ + { + U32 i; + for (i=0; ifastMode = (U16)noLarge; + return 0; +} + + +/****************************************** +* FSE byte symbol +******************************************/ +#ifndef FSE_COMMONDEFS_ONLY + +static unsigned FSE_isError(size_t code) { return (code > (size_t)(-FSE_ERROR_maxCode)); } + +static short FSE_abs(short a) +{ + return a<0? -a : a; +} + + +/**************************************************************** +* Header bitstream management +****************************************************************/ +static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + const BYTE* const istart = (const BYTE*) headerBuffer; + const BYTE* const iend = istart + hbSize; + const BYTE* ip = istart; + int nbBits; + int remaining; + int threshold; + U32 bitStream; + int bitCount; + unsigned charnum = 0; + int previous0 = 0; + + if (hbSize < 4) return (size_t)-FSE_ERROR_srcSize_wrong; + bitStream = FSE_readLE32(ip); + nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ + if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return (size_t)-FSE_ERROR_tableLog_tooLarge; + bitStream >>= 4; + bitCount = 4; + *tableLogPtr = nbBits; + remaining = (1<1) && (charnum<=*maxSVPtr)) + { + if (previous0) + { + unsigned n0 = charnum; + while ((bitStream & 0xFFFF) == 0xFFFF) + { + n0+=24; + if (ip < iend-5) + { + ip+=2; + bitStream = FSE_readLE32(ip) >> bitCount; + } + else + { + bitStream >>= 16; + bitCount+=16; + } + } + while ((bitStream & 3) == 3) + { + n0+=3; + bitStream>>=2; + bitCount+=2; + } + n0 += bitStream & 3; + bitCount += 2; + if (n0 > *maxSVPtr) return (size_t)-FSE_ERROR_maxSymbolValue_tooSmall; + while (charnum < n0) normalizedCounter[charnum++] = 0; + if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) + { + ip += bitCount>>3; + bitCount &= 7; + bitStream = FSE_readLE32(ip) >> bitCount; + } + else + bitStream >>= 2; + } + { + const short max = (short)((2*threshold-1)-remaining); + short count; + + if ((bitStream & (threshold-1)) < (U32)max) + { + count = (short)(bitStream & (threshold-1)); + bitCount += nbBits-1; + } + else + { + count = (short)(bitStream & (2*threshold-1)); + if (count >= threshold) count -= max; + bitCount += nbBits; + } + + count--; /* extra accuracy */ + remaining -= FSE_abs(count); + normalizedCounter[charnum++] = count; + previous0 = !count; + while (remaining < threshold) + { + nbBits--; + threshold >>= 1; + } + + { + if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) + { + ip += bitCount>>3; + bitCount &= 7; + } + else + { + bitCount -= (int)(8 * (iend - 4 - ip)); + ip = iend - 4; + } + bitStream = FSE_readLE32(ip) >> (bitCount & 31); + } + } + } + if (remaining != 1) return (size_t)-FSE_ERROR_GENERIC; + *maxSVPtr = charnum-1; + + ip += (bitCount+7)>>3; + if ((size_t)(ip-istart) > hbSize) return (size_t)-FSE_ERROR_srcSize_wrong; + return ip-istart; +} + + +/********************************************************* +* Decompression (Byte symbols) +*********************************************************/ +static size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue) +{ + void* ptr = dt; + FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; + FSE_decode_t* const cell = (FSE_decode_t*)(ptr) + 1; /* because dt is unsigned */ + + DTableH->tableLog = 0; + DTableH->fastMode = 0; + + cell->newState = 0; + cell->symbol = symbolValue; + cell->nbBits = 0; + + return 0; +} + + +static size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits) +{ + void* ptr = dt; + FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; + FSE_decode_t* const dinfo = (FSE_decode_t*)(ptr) + 1; /* because dt is unsigned */ + const unsigned tableSize = 1 << nbBits; + const unsigned tableMask = tableSize - 1; + const unsigned maxSymbolValue = tableMask; + unsigned s; + + /* Sanity checks */ + if (nbBits < 1) return (size_t)-FSE_ERROR_GENERIC; /* min size */ + + /* Build Decoding Table */ + DTableH->tableLog = (U16)nbBits; + DTableH->fastMode = 1; + for (s=0; s<=maxSymbolValue; s++) + { + dinfo[s].newState = 0; + dinfo[s].symbol = (BYTE)s; + dinfo[s].nbBits = (BYTE)nbBits; + } + + return 0; +} + + +/* FSE_initDStream + * Initialize a FSE_DStream_t. + * srcBuffer must point at the beginning of an FSE block. + * The function result is the size of the FSE_block (== srcSize). + * If srcSize is too small, the function will return an errorCode; + */ +static size_t FSE_initDStream(FSE_DStream_t* bitD, const void* srcBuffer, size_t srcSize) +{ + if (srcSize < 1) return (size_t)-FSE_ERROR_srcSize_wrong; + + if (srcSize >= sizeof(size_t)) + { + U32 contain32; + bitD->start = (const char*)srcBuffer; + bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(size_t); + bitD->bitContainer = FSE_readLEST(bitD->ptr); + contain32 = ((const BYTE*)srcBuffer)[srcSize-1]; + if (contain32 == 0) return (size_t)-FSE_ERROR_GENERIC; /* stop bit not present */ + bitD->bitsConsumed = 8 - FSE_highbit32(contain32); + } + else + { + U32 contain32; + bitD->start = (const char*)srcBuffer; + bitD->ptr = bitD->start; + bitD->bitContainer = *(const BYTE*)(bitD->start); + switch(srcSize) + { + case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16); + /* fallthrough */ + case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24); + /* fallthrough */ + case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32); + /* fallthrough */ + case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24; + /* fallthrough */ + case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16; + /* fallthrough */ + case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) << 8; + /* fallthrough */ + default:; + } + contain32 = ((const BYTE*)srcBuffer)[srcSize-1]; + if (contain32 == 0) return (size_t)-FSE_ERROR_GENERIC; /* stop bit not present */ + bitD->bitsConsumed = 8 - FSE_highbit32(contain32); + bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8; + } + + return srcSize; +} + + +/*!FSE_lookBits + * Provides next n bits from the bitContainer. + * bitContainer is not modified (bits are still present for next read/look) + * On 32-bits, maxNbBits==25 + * On 64-bits, maxNbBits==57 + * return : value extracted. + */ +static size_t FSE_lookBits(FSE_DStream_t* bitD, U32 nbBits) +{ + const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1; + return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask); +} + +static size_t FSE_lookBitsFast(FSE_DStream_t* bitD, U32 nbBits) /* only if nbBits >= 1 !! */ +{ + const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1; + return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask); +} + +static void FSE_skipBits(FSE_DStream_t* bitD, U32 nbBits) +{ + bitD->bitsConsumed += nbBits; +} + + +/*!FSE_readBits + * Read next n bits from the bitContainer. + * On 32-bits, don't read more than maxNbBits==25 + * On 64-bits, don't read more than maxNbBits==57 + * Use the fast variant *only* if n >= 1. + * return : value extracted. + */ +static size_t FSE_readBits(FSE_DStream_t* bitD, U32 nbBits) +{ + size_t value = FSE_lookBits(bitD, nbBits); + FSE_skipBits(bitD, nbBits); + return value; +} + +static size_t FSE_readBitsFast(FSE_DStream_t* bitD, U32 nbBits) /* only if nbBits >= 1 !! */ +{ + size_t value = FSE_lookBitsFast(bitD, nbBits); + FSE_skipBits(bitD, nbBits); + return value; +} + +static unsigned FSE_reloadDStream(FSE_DStream_t* bitD) +{ + if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */ + return FSE_DStream_tooFar; + + if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) + { + bitD->ptr -= bitD->bitsConsumed >> 3; + bitD->bitsConsumed &= 7; + bitD->bitContainer = FSE_readLEST(bitD->ptr); + return FSE_DStream_unfinished; + } + if (bitD->ptr == bitD->start) + { + if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return FSE_DStream_endOfBuffer; + return FSE_DStream_completed; + } + { + U32 nbBytes = bitD->bitsConsumed >> 3; + U32 result = FSE_DStream_unfinished; + if (bitD->ptr - nbBytes < bitD->start) + { + nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */ + result = FSE_DStream_endOfBuffer; + } + bitD->ptr -= nbBytes; + bitD->bitsConsumed -= nbBytes*8; + bitD->bitContainer = FSE_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */ + return result; + } +} + + +static void FSE_initDState(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD, const FSE_DTable* dt) +{ + const void* ptr = dt; + const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr; + DStatePtr->state = FSE_readBits(bitD, DTableH->tableLog); + FSE_reloadDStream(bitD); + DStatePtr->table = dt + 1; +} + +static BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD) +{ + const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + const U32 nbBits = DInfo.nbBits; + BYTE symbol = DInfo.symbol; + size_t lowBits = FSE_readBits(bitD, nbBits); + + DStatePtr->state = DInfo.newState + lowBits; + return symbol; +} + +static BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD) +{ + const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + const U32 nbBits = DInfo.nbBits; + BYTE symbol = DInfo.symbol; + size_t lowBits = FSE_readBitsFast(bitD, nbBits); + + DStatePtr->state = DInfo.newState + lowBits; + return symbol; +} + +/* FSE_endOfDStream + Tells if bitD has reached end of bitStream or not */ + +static unsigned FSE_endOfDStream(const FSE_DStream_t* bitD) +{ + return ((bitD->ptr == bitD->start) && (bitD->bitsConsumed == sizeof(bitD->bitContainer)*8)); +} + +static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) +{ + return DStatePtr->state == 0; +} + + +FORCE_INLINE size_t FSE_decompress_usingDTable_generic( + void* dst, size_t maxDstSize, + const void* cSrc, size_t cSrcSize, + const FSE_DTable* dt, const unsigned fast) +{ + BYTE* const ostart = (BYTE*) dst; + BYTE* op = ostart; + BYTE* const omax = op + maxDstSize; + BYTE* const olimit = omax-3; + + FSE_DStream_t bitD; + FSE_DState_t state1; + FSE_DState_t state2; + size_t errorCode; + + /* Init */ + errorCode = FSE_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */ + if (FSE_isError(errorCode)) return errorCode; + + FSE_initDState(&state1, &bitD, dt); + FSE_initDState(&state2, &bitD, dt); + +#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) + + /* 4 symbols per loop */ + for ( ; (FSE_reloadDStream(&bitD)==FSE_DStream_unfinished) && (op sizeof(bitD.bitContainer)*8) /* This test must be static */ + FSE_reloadDStream(&bitD); + + op[1] = FSE_GETSYMBOL(&state2); + + if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ + { if (FSE_reloadDStream(&bitD) > FSE_DStream_unfinished) { op+=2; break; } } + + op[2] = FSE_GETSYMBOL(&state1); + + if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ + FSE_reloadDStream(&bitD); + + op[3] = FSE_GETSYMBOL(&state2); + } + + /* tail */ + /* note : FSE_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly FSE_DStream_completed */ + while (1) + { + if ( (FSE_reloadDStream(&bitD)>FSE_DStream_completed) || (op==omax) || (FSE_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) ) + break; + + *op++ = FSE_GETSYMBOL(&state1); + + if ( (FSE_reloadDStream(&bitD)>FSE_DStream_completed) || (op==omax) || (FSE_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) ) + break; + + *op++ = FSE_GETSYMBOL(&state2); + } + + /* end ? */ + if (FSE_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2)) + return op-ostart; + + if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall; /* dst buffer is full, but cSrc unfinished */ + + return (size_t)-FSE_ERROR_corruptionDetected; +} + + +static size_t FSE_decompress_usingDTable(void* dst, size_t originalSize, + const void* cSrc, size_t cSrcSize, + const FSE_DTable* dt) +{ + FSE_DTableHeader DTableH; + memcpy(&DTableH, dt, sizeof(DTableH)); /* memcpy() into local variable, to avoid strict aliasing warning */ + + /* select fast mode (static) */ + if (DTableH.fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); + return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); +} + + +static size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize) +{ + const BYTE* const istart = (const BYTE*)cSrc; + const BYTE* ip = istart; + short counting[FSE_MAX_SYMBOL_VALUE+1]; + DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ + unsigned tableLog; + unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; + size_t errorCode; + + if (cSrcSize<2) return (size_t)-FSE_ERROR_srcSize_wrong; /* too small input size */ + + /* normal FSE decoding mode */ + errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); + if (FSE_isError(errorCode)) return errorCode; + if (errorCode >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong; /* too small input size */ + ip += errorCode; + cSrcSize -= errorCode; + + errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog); + if (FSE_isError(errorCode)) return errorCode; + + /* always return, even if it is an error code */ + return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt); +} + + + +/* ******************************************************* +* Huff0 : Huffman block compression +*********************************************************/ +#define HUF_MAX_SYMBOL_VALUE 255 +#define HUF_DEFAULT_TABLELOG 12 /* used by default, when not specified */ +#define HUF_MAX_TABLELOG 12 /* max possible tableLog; for allocation purpose; can be modified */ +#define HUF_ABSOLUTEMAX_TABLELOG 16 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ +#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG) +# error "HUF_MAX_TABLELOG is too large !" +#endif + +typedef struct HUF_CElt_s { + U16 val; + BYTE nbBits; +} HUF_CElt ; + +typedef struct nodeElt_s { + U32 count; + U16 parent; + BYTE byte; + BYTE nbBits; +} nodeElt; + + +/* ******************************************************* +* Huff0 : Huffman block decompression +*********************************************************/ +typedef struct { + BYTE byte; + BYTE nbBits; +} HUF_DElt; + +static size_t HUF_readDTable (U16* DTable, const void* src, size_t srcSize) +{ + BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1]; + U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; /* large enough for values from 0 to 16 */ + U32 weightTotal; + U32 maxBits; + const BYTE* ip = (const BYTE*) src; + size_t iSize; + size_t oSize; + U32 n; + U32 nextRankStart; + void* ptr = DTable+1; + HUF_DElt* const dt = (HUF_DElt*)ptr; + + if (!srcSize) return (size_t)-FSE_ERROR_srcSize_wrong; + iSize = ip[0]; + + FSE_STATIC_ASSERT(sizeof(HUF_DElt) == sizeof(U16)); /* if compilation fails here, assertion is false */ + //memset(huffWeight, 0, sizeof(huffWeight)); /* should not be necessary, but some analyzer complain ... */ + if (iSize >= 128) /* special header */ + { + if (iSize >= (242)) /* RLE */ + { + static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 }; + oSize = l[iSize-242]; + memset(huffWeight, 1, sizeof(huffWeight)); + iSize = 0; + } + else /* Incompressible */ + { + oSize = iSize - 127; + iSize = ((oSize+1)/2); + if (iSize+1 > srcSize) return (size_t)-FSE_ERROR_srcSize_wrong; + ip += 1; + for (n=0; n> 4; + huffWeight[n+1] = ip[n/2] & 15; + } + } + } + else /* header compressed with FSE (normal case) */ + { + if (iSize+1 > srcSize) return (size_t)-FSE_ERROR_srcSize_wrong; + oSize = FSE_decompress(huffWeight, HUF_MAX_SYMBOL_VALUE, ip+1, iSize); /* max 255 values decoded, last one is implied */ + if (FSE_isError(oSize)) return oSize; + } + + /* collect weight stats */ + memset(rankVal, 0, sizeof(rankVal)); + weightTotal = 0; + for (n=0; n= HUF_ABSOLUTEMAX_TABLELOG) return (size_t)-FSE_ERROR_corruptionDetected; + rankVal[huffWeight[n]]++; + weightTotal += (1 << huffWeight[n]) >> 1; + } + if (weightTotal == 0) return (size_t)-FSE_ERROR_corruptionDetected; + + /* get last non-null symbol weight (implied, total must be 2^n) */ + maxBits = FSE_highbit32(weightTotal) + 1; + if (maxBits > DTable[0]) return (size_t)-FSE_ERROR_tableLog_tooLarge; /* DTable is too small */ + DTable[0] = (U16)maxBits; + { + U32 total = 1 << maxBits; + U32 rest = total - weightTotal; + U32 verif = 1 << FSE_highbit32(rest); + U32 lastWeight = FSE_highbit32(rest) + 1; + if (verif != rest) return (size_t)-FSE_ERROR_corruptionDetected; /* last value must be a clean power of 2 */ + huffWeight[oSize] = (BYTE)lastWeight; + rankVal[lastWeight]++; + } + + /* check tree construction validity */ + if ((rankVal[1] < 2) || (rankVal[1] & 1)) return (size_t)-FSE_ERROR_corruptionDetected; /* by construction : at least 2 elts of rank 1, must be even */ + + /* Prepare ranks */ + nextRankStart = 0; + for (n=1; n<=maxBits; n++) + { + U32 current = nextRankStart; + nextRankStart += (rankVal[n] << (n-1)); + rankVal[n] = current; + } + + /* fill DTable */ + for (n=0; n<=oSize; n++) + { + const U32 w = huffWeight[n]; + const U32 length = (1 << w) >> 1; + U32 i; + HUF_DElt D; + D.byte = (BYTE)n; D.nbBits = (BYTE)(maxBits + 1 - w); + for (i = rankVal[w]; i < rankVal[w] + length; i++) + dt[i] = D; + rankVal[w] += length; + } + + return iSize+1; +} + + +static BYTE HUF_decodeSymbol(FSE_DStream_t* Dstream, const HUF_DElt* dt, const U32 dtLog) +{ + const size_t val = FSE_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */ + const BYTE c = dt[val].byte; + FSE_skipBits(Dstream, dt[val].nbBits); + return c; +} + +static size_t HUF_decompress_usingDTable( /* -3% slower when non static */ + void* dst, size_t maxDstSize, + const void* cSrc, size_t cSrcSize, + const U16* DTable) +{ + if (cSrcSize < 6) return (size_t)-FSE_ERROR_srcSize_wrong; + { + BYTE* const ostart = (BYTE*) dst; + BYTE* op = ostart; + BYTE* const omax = op + maxDstSize; + BYTE* const olimit = maxDstSize < 15 ? op : omax-15; + + const void* ptr = DTable; + const HUF_DElt* const dt = (const HUF_DElt*)(ptr)+1; + const U32 dtLog = DTable[0]; + size_t errorCode; + U32 reloadStatus; + + /* Init */ + + const U16* jumpTable = (const U16*)cSrc; + const size_t length1 = FSE_readLE16(jumpTable); + const size_t length2 = FSE_readLE16(jumpTable+1); + const size_t length3 = FSE_readLE16(jumpTable+2); + const size_t length4 = cSrcSize - 6 - length1 - length2 - length3; /* check coherency !! */ + const char* const start1 = (const char*)(cSrc) + 6; + const char* const start2 = start1 + length1; + const char* const start3 = start2 + length2; + const char* const start4 = start3 + length3; + FSE_DStream_t bitD1, bitD2, bitD3, bitD4; + + if (length1+length2+length3+6 >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong; + + errorCode = FSE_initDStream(&bitD1, start1, length1); + if (FSE_isError(errorCode)) return errorCode; + errorCode = FSE_initDStream(&bitD2, start2, length2); + if (FSE_isError(errorCode)) return errorCode; + errorCode = FSE_initDStream(&bitD3, start3, length3); + if (FSE_isError(errorCode)) return errorCode; + errorCode = FSE_initDStream(&bitD4, start4, length4); + if (FSE_isError(errorCode)) return errorCode; + + reloadStatus=FSE_reloadDStream(&bitD2); + + /* 16 symbols per loop */ + for ( ; (reloadStatus12)) FSE_reloadDStream(&Dstream) + + #define HUF_DECODE_SYMBOL_2(n, Dstream) \ + op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \ + if (FSE_32bits()) FSE_reloadDStream(&Dstream) + + HUF_DECODE_SYMBOL_1( 0, bitD1); + HUF_DECODE_SYMBOL_1( 1, bitD2); + HUF_DECODE_SYMBOL_1( 2, bitD3); + HUF_DECODE_SYMBOL_1( 3, bitD4); + HUF_DECODE_SYMBOL_2( 4, bitD1); + HUF_DECODE_SYMBOL_2( 5, bitD2); + HUF_DECODE_SYMBOL_2( 6, bitD3); + HUF_DECODE_SYMBOL_2( 7, bitD4); + HUF_DECODE_SYMBOL_1( 8, bitD1); + HUF_DECODE_SYMBOL_1( 9, bitD2); + HUF_DECODE_SYMBOL_1(10, bitD3); + HUF_DECODE_SYMBOL_1(11, bitD4); + HUF_DECODE_SYMBOL_0(12, bitD1); + HUF_DECODE_SYMBOL_0(13, bitD2); + HUF_DECODE_SYMBOL_0(14, bitD3); + HUF_DECODE_SYMBOL_0(15, bitD4); + } + + if (reloadStatus!=FSE_DStream_completed) /* not complete : some bitStream might be FSE_DStream_unfinished */ + return (size_t)-FSE_ERROR_corruptionDetected; + + /* tail */ + { + /* bitTail = bitD1; */ /* *much* slower : -20% !??! */ + FSE_DStream_t bitTail; + bitTail.ptr = bitD1.ptr; + bitTail.bitsConsumed = bitD1.bitsConsumed; + bitTail.bitContainer = bitD1.bitContainer; /* required in case of FSE_DStream_endOfBuffer */ + bitTail.start = start1; + for ( ; (FSE_reloadDStream(&bitTail) < FSE_DStream_completed) && (op= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong; + ip += errorCode; + cSrcSize -= errorCode; + + return HUF_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, DTable); +} + + +#endif /* FSE_COMMONDEFS_ONLY */ + +/* + zstd - standard compression library + Copyright (C) 2014-2015, Yann Collet. + + BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - zstd source repository : https://github.com/Cyan4973/zstd + - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c +*/ + +/**************************************************************** +* Tuning parameters +*****************************************************************/ +/* MEMORY_USAGE : +* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) +* Increasing memory usage improves compression ratio +* Reduced memory usage can improve speed, due to cache effect */ +#define ZSTD_MEMORY_USAGE 17 + + +/************************************** + CPU Feature Detection +**************************************/ +/* + * Automated efficient unaligned memory access detection + * Based on known hardware architectures + * This list will be updated thanks to feedbacks + */ +#if defined(CPU_HAS_EFFICIENT_UNALIGNED_MEMORY_ACCESS) \ + || defined(__ARM_FEATURE_UNALIGNED) \ + || defined(__i386__) || defined(__x86_64__) \ + || defined(_M_IX86) || defined(_M_X64) \ + || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_8__) \ + || (defined(_M_ARM) && (_M_ARM >= 7)) +# define ZSTD_UNALIGNED_ACCESS 1 +#else +# define ZSTD_UNALIGNED_ACCESS 0 +#endif + + +/******************************************************** +* Includes +*********************************************************/ +#include /* calloc */ +#include /* memcpy, memmove */ +#include /* debug : printf */ + + +/******************************************************** +* Compiler specifics +*********************************************************/ +#ifdef __AVX2__ +# include /* AVX2 intrinsics */ +#endif + +#ifdef _MSC_VER /* Visual Studio */ +# include /* For Visual 2005 */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# pragma warning(disable : 4324) /* disable: C4324: padded structure */ +#endif + + +#ifndef MEM_ACCESS_MODULE +#define MEM_ACCESS_MODULE +/******************************************************** +* Basic Types +*********************************************************/ +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# if defined(_AIX) +# include +# else +# include /* intptr_t */ +# endif +typedef uint8_t BYTE; +typedef uint16_t U16; +typedef int16_t S16; +typedef uint32_t U32; +typedef int32_t S32; +typedef uint64_t U64; +#else +typedef unsigned char BYTE; +typedef unsigned short U16; +typedef signed short S16; +typedef unsigned int U32; +typedef signed int S32; +typedef unsigned long long U64; +#endif + +#endif /* MEM_ACCESS_MODULE */ + + +/******************************************************** +* Constants +*********************************************************/ +static const U32 ZSTD_magicNumber = 0xFD2FB51E; /* 3rd version : seqNb header */ + +#define HASH_LOG (ZSTD_MEMORY_USAGE - 2) +#define HASH_TABLESIZE (1 << HASH_LOG) +#define HASH_MASK (HASH_TABLESIZE - 1) + +#define KNUTH 2654435761 + +#define BIT7 128 +#define BIT6 64 +#define BIT5 32 +#define BIT4 16 + +#define KB *(1 <<10) +#define MB *(1 <<20) +#define GB *(1U<<30) + +#define BLOCKSIZE (128 KB) /* define, for static allocation */ + +#define WORKPLACESIZE (BLOCKSIZE*3) +#define MINMATCH 4 +#define MLbits 7 +#define LLbits 6 +#define Offbits 5 +#define MaxML ((1<>3]; +#else + U32 hashTable[HASH_TABLESIZE]; +#endif + BYTE buffer[WORKPLACESIZE]; +} cctxi_t; + + + + +/************************************** +* Error Management +**************************************/ +/* published entry point */ +unsigned ZSTDv01_isError(size_t code) { return ERR_isError(code); } + + +/************************************** +* Tool functions +**************************************/ +#define ZSTD_VERSION_MAJOR 0 /* for breaking interface changes */ +#define ZSTD_VERSION_MINOR 1 /* for new (non-breaking) interface capabilities */ +#define ZSTD_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */ +#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) + +/************************************************************** +* Decompression code +**************************************************************/ + +static size_t ZSTDv01_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr) +{ + const BYTE* const in = (const BYTE* const)src; + BYTE headerFlags; + U32 cSize; + + if (srcSize < 3) return ERROR(srcSize_wrong); + + headerFlags = *in; + cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16); + + bpPtr->blockType = (blockType_t)(headerFlags >> 6); + bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0; + + if (bpPtr->blockType == bt_end) return 0; + if (bpPtr->blockType == bt_rle) return 1; + return cSize; +} + + +static size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize) +{ + if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall); + if (srcSize > 0) { + memcpy(dst, src, srcSize); + } + return srcSize; +} + + +static size_t ZSTD_decompressLiterals(void* ctx, + void* dst, size_t maxDstSize, + const void* src, size_t srcSize) +{ + BYTE* op = (BYTE*)dst; + BYTE* const oend = op + maxDstSize; + const BYTE* ip = (const BYTE*)src; + size_t errorCode; + size_t litSize; + + /* check : minimum 2, for litSize, +1, for content */ + if (srcSize <= 3) return ERROR(corruption_detected); + + litSize = ip[1] + (ip[0]<<8); + litSize += ((ip[-3] >> 3) & 7) << 16; /* mmmmh.... */ + op = oend - litSize; + + (void)ctx; + if (litSize > maxDstSize) return ERROR(dstSize_tooSmall); + errorCode = HUF_decompress(op, litSize, ip+2, srcSize-2); + if (FSE_isError(errorCode)) return ERROR(GENERIC); + return litSize; +} + + +static size_t ZSTDv01_decodeLiteralsBlock(void* ctx, + void* dst, size_t maxDstSize, + const BYTE** litStart, size_t* litSize, + const void* src, size_t srcSize) +{ + const BYTE* const istart = (const BYTE* const)src; + const BYTE* ip = istart; + BYTE* const ostart = (BYTE* const)dst; + BYTE* const oend = ostart + maxDstSize; + blockProperties_t litbp; + + size_t litcSize = ZSTDv01_getcBlockSize(src, srcSize, &litbp); + if (ZSTDv01_isError(litcSize)) return litcSize; + if (litcSize > srcSize - ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); + ip += ZSTD_blockHeaderSize; + + switch(litbp.blockType) + { + case bt_raw: + *litStart = ip; + ip += litcSize; + *litSize = litcSize; + break; + case bt_rle: + { + size_t rleSize = litbp.origSize; + if (rleSize>maxDstSize) return ERROR(dstSize_tooSmall); + if (!srcSize) return ERROR(srcSize_wrong); + if (rleSize > 0) { + memset(oend - rleSize, *ip, rleSize); + } + *litStart = oend - rleSize; + *litSize = rleSize; + ip++; + break; + } + case bt_compressed: + { + size_t decodedLitSize = ZSTD_decompressLiterals(ctx, dst, maxDstSize, ip, litcSize); + if (ZSTDv01_isError(decodedLitSize)) return decodedLitSize; + *litStart = oend - decodedLitSize; + *litSize = decodedLitSize; + ip += litcSize; + break; + } + case bt_end: + default: + return ERROR(GENERIC); + } + + return ip-istart; +} + + +static size_t ZSTDv01_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr, + FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb, + const void* src, size_t srcSize) +{ + const BYTE* const istart = (const BYTE* const)src; + const BYTE* ip = istart; + const BYTE* const iend = istart + srcSize; + U32 LLtype, Offtype, MLtype; + U32 LLlog, Offlog, MLlog; + size_t dumpsLength; + + /* check */ + if (srcSize < 5) return ERROR(srcSize_wrong); + + /* SeqHead */ + *nbSeq = ZSTD_readLE16(ip); ip+=2; + LLtype = *ip >> 6; + Offtype = (*ip >> 4) & 3; + MLtype = (*ip >> 2) & 3; + if (*ip & 2) + { + dumpsLength = ip[2]; + dumpsLength += ip[1] << 8; + ip += 3; + } + else + { + dumpsLength = ip[1]; + dumpsLength += (ip[0] & 1) << 8; + ip += 2; + } + *dumpsPtr = ip; + ip += dumpsLength; + *dumpsLengthPtr = dumpsLength; + + /* check */ + if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */ + + /* sequences */ + { + S16 norm[MaxML+1]; /* assumption : MaxML >= MaxLL and MaxOff */ + size_t headerSize; + + /* Build DTables */ + switch(LLtype) + { + case bt_rle : + LLlog = 0; + FSE_buildDTable_rle(DTableLL, *ip++); break; + case bt_raw : + LLlog = LLbits; + FSE_buildDTable_raw(DTableLL, LLbits); break; + default : + { U32 max = MaxLL; + headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip); + if (FSE_isError(headerSize)) return ERROR(GENERIC); + if (LLlog > LLFSELog) return ERROR(corruption_detected); + ip += headerSize; + FSE_buildDTable(DTableLL, norm, max, LLlog); + } } + + switch(Offtype) + { + case bt_rle : + Offlog = 0; + if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */ + FSE_buildDTable_rle(DTableOffb, *ip++); break; + case bt_raw : + Offlog = Offbits; + FSE_buildDTable_raw(DTableOffb, Offbits); break; + default : + { U32 max = MaxOff; + headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip); + if (FSE_isError(headerSize)) return ERROR(GENERIC); + if (Offlog > OffFSELog) return ERROR(corruption_detected); + ip += headerSize; + FSE_buildDTable(DTableOffb, norm, max, Offlog); + } } + + switch(MLtype) + { + case bt_rle : + MLlog = 0; + if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */ + FSE_buildDTable_rle(DTableML, *ip++); break; + case bt_raw : + MLlog = MLbits; + FSE_buildDTable_raw(DTableML, MLbits); break; + default : + { U32 max = MaxML; + headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip); + if (FSE_isError(headerSize)) return ERROR(GENERIC); + if (MLlog > MLFSELog) return ERROR(corruption_detected); + ip += headerSize; + FSE_buildDTable(DTableML, norm, max, MLlog); + } } } + + return ip-istart; +} + + +typedef struct { + size_t litLength; + size_t offset; + size_t matchLength; +} seq_t; + +typedef struct { + FSE_DStream_t DStream; + FSE_DState_t stateLL; + FSE_DState_t stateOffb; + FSE_DState_t stateML; + size_t prevOffset; + const BYTE* dumps; + const BYTE* dumpsEnd; +} seqState_t; + + +static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) +{ + size_t litLength; + size_t prevOffset; + size_t offset; + size_t matchLength; + const BYTE* dumps = seqState->dumps; + const BYTE* const de = seqState->dumpsEnd; + + /* Literal length */ + litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); + prevOffset = litLength ? seq->offset : seqState->prevOffset; + seqState->prevOffset = seq->offset; + if (litLength == MaxLL) + { + const U32 add = dumpsstateOffb), &(seqState->DStream)); + if (ZSTD_32bits()) FSE_reloadDStream(&(seqState->DStream)); + nbBits = offsetCode - 1; + if (offsetCode==0) nbBits = 0; /* cmove */ + offset = ((size_t)1 << (nbBits & ((sizeof(offset)*8)-1))) + FSE_readBits(&(seqState->DStream), nbBits); + if (ZSTD_32bits()) FSE_reloadDStream(&(seqState->DStream)); + if (offsetCode==0) offset = prevOffset; + } + + /* MatchLength */ + matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream)); + if (matchLength == MaxML) + { + const U32 add = dumpslitLength = litLength; + seq->offset = offset; + seq->matchLength = matchLength; + seqState->dumps = dumps; +} + + +static size_t ZSTD_execSequence(BYTE* op, + seq_t sequence, + const BYTE** litPtr, const BYTE* const litLimit, + BYTE* const base, BYTE* const oend) +{ + static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */ + static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */ + const BYTE* const ostart = op; + BYTE* const oLitEnd = op + sequence.litLength; + const size_t litLength = sequence.litLength; + BYTE* const endMatch = op + litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */ + const BYTE* const litEnd = *litPtr + litLength; + + /* checks */ + size_t const seqLength = sequence.litLength + sequence.matchLength; + + if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall); + if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected); + /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */ + if (sequence.offset > (U32)(oLitEnd - base)) return ERROR(corruption_detected); + + if (endMatch > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */ + if (litEnd > litLimit) return ERROR(corruption_detected); /* overRead beyond lit buffer */ + if (sequence.matchLength > (size_t)(*litPtr-op)) return ERROR(dstSize_tooSmall); /* overwrite literal segment */ + + /* copy Literals */ + ZSTD_memmove(op, *litPtr, sequence.litLength); /* note : v0.1 seems to allow scenarios where output or input are close to end of buffer */ + + op += litLength; + *litPtr = litEnd; /* update for next sequence */ + + /* check : last match must be at a minimum distance of 8 from end of dest buffer */ + if (oend-op < 8) return ERROR(dstSize_tooSmall); + + /* copy Match */ + { + const U32 overlapRisk = (((size_t)(litEnd - endMatch)) < 12); + const BYTE* match = op - sequence.offset; /* possible underflow at op - offset ? */ + size_t qutt = 12; + U64 saved[2]; + + /* check */ + if (match < base) return ERROR(corruption_detected); + if (sequence.offset > (size_t)base) return ERROR(corruption_detected); + + /* save beginning of literal sequence, in case of write overlap */ + if (overlapRisk) + { + if ((endMatch + qutt) > oend) qutt = oend-endMatch; + memcpy(saved, endMatch, qutt); + } + + if (sequence.offset < 8) + { + const int dec64 = dec64table[sequence.offset]; + op[0] = match[0]; + op[1] = match[1]; + op[2] = match[2]; + op[3] = match[3]; + match += dec32table[sequence.offset]; + ZSTD_copy4(op+4, match); + match -= dec64; + } else { ZSTD_copy8(op, match); } + op += 8; match += 8; + + if (endMatch > oend-(16-MINMATCH)) + { + if (op < oend-8) + { + ZSTD_wildcopy(op, match, (oend-8) - op); + match += (oend-8) - op; + op = oend-8; + } + while (opLLTable; + U32* DTableML = dctx->MLTable; + U32* DTableOffb = dctx->OffTable; + BYTE* const base = (BYTE*) (dctx->base); + + /* Build Decoding Tables */ + errorCode = ZSTDv01_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength, + DTableLL, DTableML, DTableOffb, + ip, iend-ip); + if (ZSTDv01_isError(errorCode)) return errorCode; + ip += errorCode; + + /* Regen sequences */ + { + seq_t sequence; + seqState_t seqState; + + memset(&sequence, 0, sizeof(sequence)); + seqState.dumps = dumps; + seqState.dumpsEnd = dumps + dumpsLength; + seqState.prevOffset = 1; + errorCode = FSE_initDStream(&(seqState.DStream), ip, iend-ip); + if (FSE_isError(errorCode)) return ERROR(corruption_detected); + FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL); + FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb); + FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML); + + for ( ; (FSE_reloadDStream(&(seqState.DStream)) <= FSE_DStream_completed) && (nbSeq>0) ; ) + { + size_t oneSeqSize; + nbSeq--; + ZSTD_decodeSequence(&sequence, &seqState); + oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend); + if (ZSTDv01_isError(oneSeqSize)) return oneSeqSize; + op += oneSeqSize; + } + + /* check if reached exact end */ + if ( !FSE_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected); /* requested too much : data is corrupted */ + if (nbSeq<0) return ERROR(corruption_detected); /* requested too many sequences : data is corrupted */ + + /* last literal segment */ + { + size_t lastLLSize = litEnd - litPtr; + if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall); + if (lastLLSize > 0) { + if (op != litPtr) memmove(op, litPtr, lastLLSize); + op += lastLLSize; + } + } + } + + return op-ostart; +} + + +static size_t ZSTD_decompressBlock( + void* ctx, + void* dst, size_t maxDstSize, + const void* src, size_t srcSize) +{ + /* blockType == blockCompressed, srcSize is trusted */ + const BYTE* ip = (const BYTE*)src; + const BYTE* litPtr = NULL; + size_t litSize = 0; + size_t errorCode; + + /* Decode literals sub-block */ + errorCode = ZSTDv01_decodeLiteralsBlock(ctx, dst, maxDstSize, &litPtr, &litSize, src, srcSize); + if (ZSTDv01_isError(errorCode)) return errorCode; + ip += errorCode; + srcSize -= errorCode; + + return ZSTD_decompressSequences(ctx, dst, maxDstSize, ip, srcSize, litPtr, litSize); +} + + +size_t ZSTDv01_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) +{ + const BYTE* ip = (const BYTE*)src; + const BYTE* iend = ip + srcSize; + BYTE* const ostart = (BYTE* const)dst; + BYTE* op = ostart; + BYTE* const oend = ostart + maxDstSize; + size_t remainingSize = srcSize; + U32 magicNumber; + size_t errorCode=0; + blockProperties_t blockProperties; + + /* Frame Header */ + if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); + magicNumber = ZSTD_readBE32(src); + if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown); + ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize; + + /* Loop on each block */ + while (1) + { + size_t blockSize = ZSTDv01_getcBlockSize(ip, iend-ip, &blockProperties); + if (ZSTDv01_isError(blockSize)) return blockSize; + + ip += ZSTD_blockHeaderSize; + remainingSize -= ZSTD_blockHeaderSize; + if (blockSize > remainingSize) return ERROR(srcSize_wrong); + + switch(blockProperties.blockType) + { + case bt_compressed: + errorCode = ZSTD_decompressBlock(ctx, op, oend-op, ip, blockSize); + break; + case bt_raw : + errorCode = ZSTD_copyUncompressedBlock(op, oend-op, ip, blockSize); + break; + case bt_rle : + return ERROR(GENERIC); /* not yet supported */ + break; + case bt_end : + /* end of frame */ + if (remainingSize) return ERROR(srcSize_wrong); + break; + default: + return ERROR(GENERIC); + } + if (blockSize == 0) break; /* bt_end */ + + if (ZSTDv01_isError(errorCode)) return errorCode; + op += errorCode; + ip += blockSize; + remainingSize -= blockSize; + } + + return op-ostart; +} + +size_t ZSTDv01_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize) +{ + dctx_t ctx; + ctx.base = dst; + return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize); +} + +/* ZSTD_errorFrameSizeInfoLegacy() : + assumes `cSize` and `dBound` are _not_ NULL */ +static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret) +{ + *cSize = ret; + *dBound = ZSTD_CONTENTSIZE_ERROR; +} + +void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound) +{ + const BYTE* ip = (const BYTE*)src; + size_t remainingSize = srcSize; + size_t nbBlocks = 0; + U32 magicNumber; + blockProperties_t blockProperties; + + /* Frame Header */ + if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } + magicNumber = ZSTD_readBE32(src); + if (magicNumber != ZSTD_magicNumber) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown)); + return; + } + ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize; + + /* Loop on each block */ + while (1) + { + size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties); + if (ZSTDv01_isError(blockSize)) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, blockSize); + return; + } + + ip += ZSTD_blockHeaderSize; + remainingSize -= ZSTD_blockHeaderSize; + if (blockSize > remainingSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } + + if (blockSize == 0) break; /* bt_end */ + + ip += blockSize; + remainingSize -= blockSize; + nbBlocks++; + } + + *cSize = ip - (const BYTE*)src; + *dBound = nbBlocks * BLOCKSIZE; +} + +/******************************* +* Streaming Decompression API +*******************************/ + +size_t ZSTDv01_resetDCtx(ZSTDv01_Dctx* dctx) +{ + dctx->expected = ZSTD_frameHeaderSize; + dctx->phase = 0; + dctx->previousDstEnd = NULL; + dctx->base = NULL; + return 0; +} + +ZSTDv01_Dctx* ZSTDv01_createDCtx(void) +{ + ZSTDv01_Dctx* dctx = (ZSTDv01_Dctx*)malloc(sizeof(ZSTDv01_Dctx)); + if (dctx==NULL) return NULL; + ZSTDv01_resetDCtx(dctx); + return dctx; +} + +size_t ZSTDv01_freeDCtx(ZSTDv01_Dctx* dctx) +{ + free(dctx); + return 0; +} + +size_t ZSTDv01_nextSrcSizeToDecompress(ZSTDv01_Dctx* dctx) +{ + return ((dctx_t*)dctx)->expected; +} + +size_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) +{ + dctx_t* ctx = (dctx_t*)dctx; + + /* Sanity check */ + if (srcSize != ctx->expected) return ERROR(srcSize_wrong); + if (dst != ctx->previousDstEnd) /* not contiguous */ + ctx->base = dst; + + /* Decompress : frame header */ + if (ctx->phase == 0) + { + /* Check frame magic header */ + U32 magicNumber = ZSTD_readBE32(src); + if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown); + ctx->phase = 1; + ctx->expected = ZSTD_blockHeaderSize; + return 0; + } + + /* Decompress : block header */ + if (ctx->phase == 1) + { + blockProperties_t bp; + size_t blockSize = ZSTDv01_getcBlockSize(src, ZSTD_blockHeaderSize, &bp); + if (ZSTDv01_isError(blockSize)) return blockSize; + if (bp.blockType == bt_end) + { + ctx->expected = 0; + ctx->phase = 0; + } + else + { + ctx->expected = blockSize; + ctx->bType = bp.blockType; + ctx->phase = 2; + } + + return 0; + } + + /* Decompress : block content */ + { + size_t rSize; + switch(ctx->bType) + { + case bt_compressed: + rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize); + break; + case bt_raw : + rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize); + break; + case bt_rle : + return ERROR(GENERIC); /* not yet handled */ + break; + case bt_end : /* should never happen (filtered at phase 1) */ + rSize = 0; + break; + default: + return ERROR(GENERIC); + } + ctx->phase = 1; + ctx->expected = ZSTD_blockHeaderSize; + if (ZSTDv01_isError(rSize)) return rSize; + ctx->previousDstEnd = (void*)( ((char*)dst) + rSize); + return rSize; + } + +} diff --git a/third_party/zstd/legacy/zstd_v02.c b/third_party/zstd/legacy/zstd_v02.c new file mode 100644 index 00000000000..6d39b6e5b2d --- /dev/null +++ b/third_party/zstd/legacy/zstd_v02.c @@ -0,0 +1,3465 @@ +/* + * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + +#include /* size_t, ptrdiff_t */ +#include "zstd_v02.h" +#include "../common/compiler.h" +#include "../common/error_private.h" + + +/****************************************** +* Compiler-specific +******************************************/ +#if defined(_MSC_VER) /* Visual Studio */ +# include /* _byteswap_ulong */ +# include /* _byteswap_* */ +#endif + + +/* ****************************************************************** + mem.h + low-level memory access routines + Copyright (C) 2013-2015, Yann Collet. + + BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy + - Public forum : https://groups.google.com/forum/#!forum/lz4c +****************************************************************** */ +#ifndef MEM_H_MODULE +#define MEM_H_MODULE + +#if defined (__cplusplus) +extern "C" { +#endif + +/****************************************** +* Includes +******************************************/ +#include /* size_t, ptrdiff_t */ +#include /* memcpy */ + + +/**************************************************************** +* Basic Types +*****************************************************************/ +#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# if defined(_AIX) +# include +# else +# include /* intptr_t */ +# endif + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef int16_t S16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; + typedef int64_t S64; +#else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef signed short S16; + typedef unsigned int U32; + typedef signed int S32; + typedef unsigned long long U64; + typedef signed long long S64; +#endif + + +/**************************************************************** +* Memory I/O +*****************************************************************/ + +MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; } +MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; } + +MEM_STATIC unsigned MEM_isLittleEndian(void) +{ + const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + return one.c[0]; +} + +MEM_STATIC U16 MEM_read16(const void* memPtr) +{ + U16 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +MEM_STATIC U32 MEM_read32(const void* memPtr) +{ + U32 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +MEM_STATIC U64 MEM_read64(const void* memPtr) +{ + U64 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +MEM_STATIC void MEM_write16(void* memPtr, U16 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +MEM_STATIC U16 MEM_readLE16(const void* memPtr) +{ + if (MEM_isLittleEndian()) + return MEM_read16(memPtr); + else + { + const BYTE* p = (const BYTE*)memPtr; + return (U16)(p[0] + (p[1]<<8)); + } +} + +MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) +{ + if (MEM_isLittleEndian()) + { + MEM_write16(memPtr, val); + } + else + { + BYTE* p = (BYTE*)memPtr; + p[0] = (BYTE)val; + p[1] = (BYTE)(val>>8); + } +} + +MEM_STATIC U32 MEM_readLE24(const void* memPtr) +{ + return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); +} + +MEM_STATIC U32 MEM_readLE32(const void* memPtr) +{ + if (MEM_isLittleEndian()) + return MEM_read32(memPtr); + else + { + const BYTE* p = (const BYTE*)memPtr; + return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24)); + } +} + + +MEM_STATIC U64 MEM_readLE64(const void* memPtr) +{ + if (MEM_isLittleEndian()) + return MEM_read64(memPtr); + else + { + const BYTE* p = (const BYTE*)memPtr; + return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24) + + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56)); + } +} + + +MEM_STATIC size_t MEM_readLEST(const void* memPtr) +{ + if (MEM_32bits()) + return (size_t)MEM_readLE32(memPtr); + else + return (size_t)MEM_readLE64(memPtr); +} + +#if defined (__cplusplus) +} +#endif + +#endif /* MEM_H_MODULE */ + + +/* ****************************************************************** + bitstream + Part of NewGen Entropy library + header file (to include) + Copyright (C) 2013-2015, Yann Collet. + + BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + - Public forum : https://groups.google.com/forum/#!forum/lz4c +****************************************************************** */ +#ifndef BITSTREAM_H_MODULE +#define BITSTREAM_H_MODULE + +#if defined (__cplusplus) +extern "C" { +#endif + + +/* +* This API consists of small unitary functions, which highly benefit from being inlined. +* Since link-time-optimization is not available for all compilers, +* these functions are defined into a .h to be included. +*/ + + +/********************************************** +* bitStream decompression API (read backward) +**********************************************/ +typedef struct +{ + size_t bitContainer; + unsigned bitsConsumed; + const char* ptr; + const char* start; +} BIT_DStream_t; + +typedef enum { BIT_DStream_unfinished = 0, + BIT_DStream_endOfBuffer = 1, + BIT_DStream_completed = 2, + BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */ + /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */ + +MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize); +MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits); +MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD); +MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD); + + +/****************************************** +* unsafe API +******************************************/ +MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits); +/* faster, but works only if nbBits >= 1 */ + + + +/**************************************************************** +* Helper functions +****************************************************************/ +MEM_STATIC unsigned BIT_highbit32 (U32 val) +{ +# if defined(_MSC_VER) /* Visual */ + unsigned long r; + return _BitScanReverse(&r, val) ? (unsigned)r : 0; +# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ + return __builtin_clz (val) ^ 31; +# else /* Software version */ + static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; + U32 v = val; + unsigned r; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27]; + return r; +# endif +} + + + +/********************************************************** +* bitStream decoding +**********************************************************/ + +/*!BIT_initDStream +* Initialize a BIT_DStream_t. +* @bitD : a pointer to an already allocated BIT_DStream_t structure +* @srcBuffer must point at the beginning of a bitStream +* @srcSize must be the exact size of the bitStream +* @result : size of stream (== srcSize) or an errorCode if a problem is detected +*/ +MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize) +{ + if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } + + if (srcSize >= sizeof(size_t)) /* normal case */ + { + U32 contain32; + bitD->start = (const char*)srcBuffer; + bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(size_t); + bitD->bitContainer = MEM_readLEST(bitD->ptr); + contain32 = ((const BYTE*)srcBuffer)[srcSize-1]; + if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */ + bitD->bitsConsumed = 8 - BIT_highbit32(contain32); + } + else + { + U32 contain32; + bitD->start = (const char*)srcBuffer; + bitD->ptr = bitD->start; + bitD->bitContainer = *(const BYTE*)(bitD->start); + switch(srcSize) + { + case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16); + /* fallthrough */ + case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24); + /* fallthrough */ + case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32); + /* fallthrough */ + case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24; + /* fallthrough */ + case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16; + /* fallthrough */ + case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) << 8; + /* fallthrough */ + default:; + } + contain32 = ((const BYTE*)srcBuffer)[srcSize-1]; + if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */ + bitD->bitsConsumed = 8 - BIT_highbit32(contain32); + bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8; + } + + return srcSize; +} + +MEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits) +{ + const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1; + return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask); +} + +/*! BIT_lookBitsFast : +* unsafe version; only works if nbBits >= 1 */ +MEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits) +{ + const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1; + return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask); +} + +MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) +{ + bitD->bitsConsumed += nbBits; +} + +MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits) +{ + size_t value = BIT_lookBits(bitD, nbBits); + BIT_skipBits(bitD, nbBits); + return value; +} + +/*!BIT_readBitsFast : +* unsafe version; only works if nbBits >= 1 */ +MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits) +{ + size_t value = BIT_lookBitsFast(bitD, nbBits); + BIT_skipBits(bitD, nbBits); + return value; +} + +MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD) +{ + if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */ + return BIT_DStream_overflow; + + if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) + { + bitD->ptr -= bitD->bitsConsumed >> 3; + bitD->bitsConsumed &= 7; + bitD->bitContainer = MEM_readLEST(bitD->ptr); + return BIT_DStream_unfinished; + } + if (bitD->ptr == bitD->start) + { + if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer; + return BIT_DStream_completed; + } + { + U32 nbBytes = bitD->bitsConsumed >> 3; + BIT_DStream_status result = BIT_DStream_unfinished; + if (bitD->ptr - nbBytes < bitD->start) + { + nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */ + result = BIT_DStream_endOfBuffer; + } + bitD->ptr -= nbBytes; + bitD->bitsConsumed -= nbBytes*8; + bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */ + return result; + } +} + +/*! BIT_endOfDStream +* @return Tells if DStream has reached its exact end +*/ +MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream) +{ + return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8)); +} + +#if defined (__cplusplus) +} +#endif + +#endif /* BITSTREAM_H_MODULE */ +/* ****************************************************************** + Error codes and messages + Copyright (C) 2013-2015, Yann Collet + + BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + - Public forum : https://groups.google.com/forum/#!forum/lz4c +****************************************************************** */ +#ifndef ERROR_H_MODULE +#define ERROR_H_MODULE + +#if defined (__cplusplus) +extern "C" { +#endif + + +/****************************************** +* Compiler-specific +******************************************/ +#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define ERR_STATIC static inline +#elif defined(_MSC_VER) +# define ERR_STATIC static __inline +#elif defined(__GNUC__) +# define ERR_STATIC static __attribute__((unused)) +#else +# define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ +#endif + + +/****************************************** +* Error Management +******************************************/ +#define PREFIX(name) ZSTD_error_##name + +#define ERROR(name) (size_t)-PREFIX(name) + +#define ERROR_LIST(ITEM) \ + ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \ + ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \ + ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \ + ITEM(PREFIX(tableLog_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooSmall)) \ + ITEM(PREFIX(maxCode)) + +#define ERROR_GENERATE_ENUM(ENUM) ENUM, +typedef enum { ERROR_LIST(ERROR_GENERATE_ENUM) } ERR_codes; /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */ + +#define ERROR_CONVERTTOSTRING(STRING) #STRING, +#define ERROR_GENERATE_STRING(EXPR) ERROR_CONVERTTOSTRING(EXPR) +static const char* ERR_strings[] = { ERROR_LIST(ERROR_GENERATE_STRING) }; + +ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); } + +ERR_STATIC const char* ERR_getErrorName(size_t code) +{ + static const char* codeError = "Unspecified error code"; + if (ERR_isError(code)) return ERR_strings[-(int)(code)]; + return codeError; +} + + +#if defined (__cplusplus) +} +#endif + +#endif /* ERROR_H_MODULE */ +/* +Constructor and Destructor of type FSE_CTable + Note that its size depends on 'tableLog' and 'maxSymbolValue' */ +typedef unsigned FSE_CTable; /* don't allocate that. It's just a way to be more restrictive than void* */ +typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ + + +/* ****************************************************************** + FSE : Finite State Entropy coder + header file for static linking (only) + Copyright (C) 2013-2015, Yann Collet + + BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + - Public forum : https://groups.google.com/forum/#!forum/lz4c +****************************************************************** */ +#if defined (__cplusplus) +extern "C" { +#endif + + +/****************************************** +* Static allocation +******************************************/ +/* FSE buffer bounds */ +#define FSE_NCOUNTBOUND 512 +#define FSE_BLOCKBOUND(size) (size + (size>>7)) +#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ + +/* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */ +#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2)) +#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<= 1 (otherwise, result will be corrupted) */ + + +/****************************************** +* Implementation of inline functions +******************************************/ + +/* decompression */ + +typedef struct { + U16 tableLog; + U16 fastMode; +} FSE_DTableHeader; /* sizeof U32 */ + +typedef struct +{ + unsigned short newState; + unsigned char symbol; + unsigned char nbBits; +} FSE_decode_t; /* size == U32 */ + +MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt) +{ + FSE_DTableHeader DTableH; + memcpy(&DTableH, dt, sizeof(DTableH)); + DStatePtr->state = BIT_readBits(bitD, DTableH.tableLog); + BIT_reloadDStream(bitD); + DStatePtr->table = dt + 1; +} + +MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) +{ + const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + const U32 nbBits = DInfo.nbBits; + BYTE symbol = DInfo.symbol; + size_t lowBits = BIT_readBits(bitD, nbBits); + + DStatePtr->state = DInfo.newState + lowBits; + return symbol; +} + +MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) +{ + const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; + const U32 nbBits = DInfo.nbBits; + BYTE symbol = DInfo.symbol; + size_t lowBits = BIT_readBitsFast(bitD, nbBits); + + DStatePtr->state = DInfo.newState + lowBits; + return symbol; +} + +MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) +{ + return DStatePtr->state == 0; +} + + +#if defined (__cplusplus) +} +#endif +/* ****************************************************************** + Huff0 : Huffman coder, part of New Generation Entropy library + header file for static linking (only) + Copyright (C) 2013-2015, Yann Collet + + BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - Source repository : https://github.com/Cyan4973/FiniteStateEntropy + - Public forum : https://groups.google.com/forum/#!forum/lz4c +****************************************************************** */ + +#if defined (__cplusplus) +extern "C" { +#endif + +/****************************************** +* Static allocation macros +******************************************/ +/* Huff0 buffer bounds */ +#define HUF_CTABLEBOUND 129 +#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true if incompressible pre-filtered with fast heuristic */ +#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ + +/* static allocation of Huff0's DTable */ +#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1< /* size_t */ + + +/* ************************************* +* Version +***************************************/ +#define ZSTD_VERSION_MAJOR 0 /* for breaking interface changes */ +#define ZSTD_VERSION_MINOR 2 /* for new (non-breaking) interface capabilities */ +#define ZSTD_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */ +#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) + + +/* ************************************* +* Advanced functions +***************************************/ +typedef struct ZSTD_CCtx_s ZSTD_CCtx; /* incomplete type */ + +#if defined (__cplusplus) +} +#endif +/* + zstd - standard compression library + Header File for static linking only + Copyright (C) 2014-2015, Yann Collet. + + BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - zstd source repository : https://github.com/Cyan4973/zstd + - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c +*/ + +/* The objects defined into this file should be considered experimental. + * They are not labelled stable, as their prototype may change in the future. + * You can use them for tests, provide feedback, or if you can endure risk of future changes. + */ + +#if defined (__cplusplus) +extern "C" { +#endif + +/* ************************************* +* Streaming functions +***************************************/ + +typedef struct ZSTDv02_Dctx_s ZSTD_DCtx; + +/* + Use above functions alternatively. + ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue(). + ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block. + Result is the number of bytes regenerated within 'dst'. + It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header. +*/ + +/* ************************************* +* Prefix - version detection +***************************************/ +#define ZSTD_magicNumber 0xFD2FB522 /* v0.2 (current)*/ + + +#if defined (__cplusplus) +} +#endif +/* ****************************************************************** + FSE : Finite State Entropy coder + Copyright (C) 2013-2015, Yann Collet. + + BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy + - Public forum : https://groups.google.com/forum/#!forum/lz4c +****************************************************************** */ + +#ifndef FSE_COMMONDEFS_ONLY + +/**************************************************************** +* Tuning parameters +****************************************************************/ +/* MEMORY_USAGE : +* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) +* Increasing memory usage improves compression ratio +* Reduced memory usage can improve speed, due to cache effect +* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ +#define FSE_MAX_MEMORY_USAGE 14 +#define FSE_DEFAULT_MEMORY_USAGE 13 + +/* FSE_MAX_SYMBOL_VALUE : +* Maximum symbol value authorized. +* Required for proper stack allocation */ +#define FSE_MAX_SYMBOL_VALUE 255 + + +/**************************************************************** +* template functions type & suffix +****************************************************************/ +#define FSE_FUNCTION_TYPE BYTE +#define FSE_FUNCTION_EXTENSION + + +/**************************************************************** +* Byte symbol type +****************************************************************/ +#endif /* !FSE_COMMONDEFS_ONLY */ + + +/**************************************************************** +* Compiler specifics +****************************************************************/ +#ifdef _MSC_VER /* Visual Studio */ +# define FORCE_INLINE static __forceinline +# include /* For Visual 2005 */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ +#else +# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# ifdef __GNUC__ +# define FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define FORCE_INLINE static inline +# endif +# else +# define FORCE_INLINE static +# endif /* __STDC_VERSION__ */ +#endif + + +/**************************************************************** +* Includes +****************************************************************/ +#include /* malloc, free, qsort */ +#include /* memcpy, memset */ +#include /* printf (debug) */ + +/**************************************************************** +* Constants +*****************************************************************/ +#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2) +#define FSE_MAX_TABLESIZE (1U< FSE_TABLELOG_ABSOLUTE_MAX +#error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" +#endif + + +/**************************************************************** +* Error Management +****************************************************************/ +#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ + + +/**************************************************************** +* Complex types +****************************************************************/ +typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; + + +/**************************************************************** +* Templates +****************************************************************/ +/* + designed to be included + for type-specific functions (template emulation in C) + Objective is to write these functions only once, for improved maintenance +*/ + +/* safety checks */ +#ifndef FSE_FUNCTION_EXTENSION +# error "FSE_FUNCTION_EXTENSION must be defined" +#endif +#ifndef FSE_FUNCTION_TYPE +# error "FSE_FUNCTION_TYPE must be defined" +#endif + +/* Function names */ +#define FSE_CAT(X,Y) X##Y +#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y) +#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y) + + +/* Function templates */ + +#define FSE_DECODE_TYPE FSE_decode_t + +static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; } + +static size_t FSE_buildDTable +(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) +{ + void* ptr = dt+1; + FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*)ptr; + FSE_DTableHeader DTableH; + const U32 tableSize = 1 << tableLog; + const U32 tableMask = tableSize-1; + const U32 step = FSE_tableStep(tableSize); + U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1]; + U32 position = 0; + U32 highThreshold = tableSize-1; + const S16 largeLimit= (S16)(1 << (tableLog-1)); + U32 noLarge = 1; + U32 s; + + /* Sanity Checks */ + if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge); + if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); + + /* Init, lay down lowprob symbols */ + DTableH.tableLog = (U16)tableLog; + for (s=0; s<=maxSymbolValue; s++) + { + if (normalizedCounter[s]==-1) + { + tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s; + symbolNext[s] = 1; + } + else + { + if (normalizedCounter[s] >= largeLimit) noLarge=0; + symbolNext[s] = normalizedCounter[s]; + } + } + + /* Spread symbols */ + for (s=0; s<=maxSymbolValue; s++) + { + int i; + for (i=0; i highThreshold) position = (position + step) & tableMask; /* lowprob area */ + } + } + + if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ + + /* Build Decoding table */ + { + U32 i; + for (i=0; i FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); + bitStream >>= 4; + bitCount = 4; + *tableLogPtr = nbBits; + remaining = (1<1) && (charnum<=*maxSVPtr)) + { + if (previous0) + { + unsigned n0 = charnum; + while ((bitStream & 0xFFFF) == 0xFFFF) + { + n0+=24; + if (ip < iend-5) + { + ip+=2; + bitStream = MEM_readLE32(ip) >> bitCount; + } + else + { + bitStream >>= 16; + bitCount+=16; + } + } + while ((bitStream & 3) == 3) + { + n0+=3; + bitStream>>=2; + bitCount+=2; + } + n0 += bitStream & 3; + bitCount += 2; + if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall); + while (charnum < n0) normalizedCounter[charnum++] = 0; + if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) + { + ip += bitCount>>3; + bitCount &= 7; + bitStream = MEM_readLE32(ip) >> bitCount; + } + else + bitStream >>= 2; + } + { + const short max = (short)((2*threshold-1)-remaining); + short count; + + if ((bitStream & (threshold-1)) < (U32)max) + { + count = (short)(bitStream & (threshold-1)); + bitCount += nbBits-1; + } + else + { + count = (short)(bitStream & (2*threshold-1)); + if (count >= threshold) count -= max; + bitCount += nbBits; + } + + count--; /* extra accuracy */ + remaining -= FSE_abs(count); + normalizedCounter[charnum++] = count; + previous0 = !count; + while (remaining < threshold) + { + nbBits--; + threshold >>= 1; + } + + { + if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) + { + ip += bitCount>>3; + bitCount &= 7; + } + else + { + bitCount -= (int)(8 * (iend - 4 - ip)); + ip = iend - 4; + } + bitStream = MEM_readLE32(ip) >> (bitCount & 31); + } + } + } + if (remaining != 1) return ERROR(GENERIC); + *maxSVPtr = charnum-1; + + ip += (bitCount+7)>>3; + if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong); + return ip-istart; +} + + +/********************************************************* +* Decompression (Byte symbols) +*********************************************************/ +static size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue) +{ + void* ptr = dt; + FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; + FSE_decode_t* const cell = (FSE_decode_t*)(ptr) + 1; /* because dt is unsigned */ + + DTableH->tableLog = 0; + DTableH->fastMode = 0; + + cell->newState = 0; + cell->symbol = symbolValue; + cell->nbBits = 0; + + return 0; +} + + +static size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits) +{ + void* ptr = dt; + FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; + FSE_decode_t* const dinfo = (FSE_decode_t*)(ptr) + 1; /* because dt is unsigned */ + const unsigned tableSize = 1 << nbBits; + const unsigned tableMask = tableSize - 1; + const unsigned maxSymbolValue = tableMask; + unsigned s; + + /* Sanity checks */ + if (nbBits < 1) return ERROR(GENERIC); /* min size */ + + /* Build Decoding Table */ + DTableH->tableLog = (U16)nbBits; + DTableH->fastMode = 1; + for (s=0; s<=maxSymbolValue; s++) + { + dinfo[s].newState = 0; + dinfo[s].symbol = (BYTE)s; + dinfo[s].nbBits = (BYTE)nbBits; + } + + return 0; +} + +FORCE_INLINE size_t FSE_decompress_usingDTable_generic( + void* dst, size_t maxDstSize, + const void* cSrc, size_t cSrcSize, + const FSE_DTable* dt, const unsigned fast) +{ + BYTE* const ostart = (BYTE*) dst; + BYTE* op = ostart; + BYTE* const omax = op + maxDstSize; + BYTE* const olimit = omax-3; + + BIT_DStream_t bitD; + FSE_DState_t state1; + FSE_DState_t state2; + size_t errorCode; + + /* Init */ + errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */ + if (FSE_isError(errorCode)) return errorCode; + + FSE_initDState(&state1, &bitD, dt); + FSE_initDState(&state2, &bitD, dt); + +#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) + + /* 4 symbols per loop */ + for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op sizeof(bitD.bitContainer)*8) /* This test must be static */ + BIT_reloadDStream(&bitD); + + op[1] = FSE_GETSYMBOL(&state2); + + if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ + { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } } + + op[2] = FSE_GETSYMBOL(&state1); + + if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ + BIT_reloadDStream(&bitD); + + op[3] = FSE_GETSYMBOL(&state2); + } + + /* tail */ + /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ + while (1) + { + if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) ) + break; + + *op++ = FSE_GETSYMBOL(&state1); + + if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) ) + break; + + *op++ = FSE_GETSYMBOL(&state2); + } + + /* end ? */ + if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2)) + return op-ostart; + + if (op==omax) return ERROR(dstSize_tooSmall); /* dst buffer is full, but cSrc unfinished */ + + return ERROR(corruption_detected); +} + + +static size_t FSE_decompress_usingDTable(void* dst, size_t originalSize, + const void* cSrc, size_t cSrcSize, + const FSE_DTable* dt) +{ + FSE_DTableHeader DTableH; + memcpy(&DTableH, dt, sizeof(DTableH)); + + /* select fast mode (static) */ + if (DTableH.fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); + return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); +} + + +static size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize) +{ + const BYTE* const istart = (const BYTE*)cSrc; + const BYTE* ip = istart; + short counting[FSE_MAX_SYMBOL_VALUE+1]; + DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ + unsigned tableLog; + unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; + size_t errorCode; + + if (cSrcSize<2) return ERROR(srcSize_wrong); /* too small input size */ + + /* normal FSE decoding mode */ + errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); + if (FSE_isError(errorCode)) return errorCode; + if (errorCode >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size */ + ip += errorCode; + cSrcSize -= errorCode; + + errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog); + if (FSE_isError(errorCode)) return errorCode; + + /* always return, even if it is an error code */ + return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt); +} + + + +#endif /* FSE_COMMONDEFS_ONLY */ +/* ****************************************************************** + Huff0 : Huffman coder, part of New Generation Entropy library + Copyright (C) 2013-2015, Yann Collet. + + BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy + - Public forum : https://groups.google.com/forum/#!forum/lz4c +****************************************************************** */ + +/**************************************************************** +* Compiler specifics +****************************************************************/ +#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +/* inline is defined */ +#elif defined(_MSC_VER) +# define inline __inline +#else +# define inline /* disable inline */ +#endif + + +#ifdef _MSC_VER /* Visual Studio */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +#endif + + +/**************************************************************** +* Includes +****************************************************************/ +#include /* malloc, free, qsort */ +#include /* memcpy, memset */ +#include /* printf (debug) */ + +/**************************************************************** +* Error Management +****************************************************************/ +#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ + + +/****************************************** +* Helper functions +******************************************/ +static unsigned HUF_isError(size_t code) { return ERR_isError(code); } + +#define HUF_ABSOLUTEMAX_TABLELOG 16 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ +#define HUF_MAX_TABLELOG 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */ +#define HUF_DEFAULT_TABLELOG HUF_MAX_TABLELOG /* tableLog by default, when not specified */ +#define HUF_MAX_SYMBOL_VALUE 255 +#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG) +# error "HUF_MAX_TABLELOG is too large !" +#endif + + + +/********************************************************* +* Huff0 : Huffman block decompression +*********************************************************/ +typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2; /* single-symbol decoding */ + +typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4; /* double-symbols decoding */ + +typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t; + +/*! HUF_readStats + Read compact Huffman tree, saved by HUF_writeCTable + @huffWeight : destination buffer + @return : size read from `src` +*/ +static size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize) +{ + U32 weightTotal; + U32 tableLog; + const BYTE* ip = (const BYTE*) src; + size_t iSize; + size_t oSize; + U32 n; + + if (!srcSize) return ERROR(srcSize_wrong); + iSize = ip[0]; + //memset(huffWeight, 0, hwSize); /* is not necessary, even though some analyzer complain ... */ + + if (iSize >= 128) /* special header */ + { + if (iSize >= (242)) /* RLE */ + { + static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 }; + oSize = l[iSize-242]; + memset(huffWeight, 1, hwSize); + iSize = 0; + } + else /* Incompressible */ + { + oSize = iSize - 127; + iSize = ((oSize+1)/2); + if (iSize+1 > srcSize) return ERROR(srcSize_wrong); + if (oSize >= hwSize) return ERROR(corruption_detected); + ip += 1; + for (n=0; n> 4; + huffWeight[n+1] = ip[n/2] & 15; + } + } + } + else /* header compressed with FSE (normal case) */ + { + if (iSize+1 > srcSize) return ERROR(srcSize_wrong); + oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */ + if (FSE_isError(oSize)) return oSize; + } + + /* collect weight stats */ + memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32)); + weightTotal = 0; + for (n=0; n= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected); + rankStats[huffWeight[n]]++; + weightTotal += (1 << huffWeight[n]) >> 1; + } + if (weightTotal == 0) return ERROR(corruption_detected); + + /* get last non-null symbol weight (implied, total must be 2^n) */ + tableLog = BIT_highbit32(weightTotal) + 1; + if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected); + { + U32 total = 1 << tableLog; + U32 rest = total - weightTotal; + U32 verif = 1 << BIT_highbit32(rest); + U32 lastWeight = BIT_highbit32(rest) + 1; + if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ + huffWeight[oSize] = (BYTE)lastWeight; + rankStats[lastWeight]++; + } + + /* check tree construction validity */ + if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ + + /* results */ + *nbSymbolsPtr = (U32)(oSize+1); + *tableLogPtr = tableLog; + return iSize+1; +} + + +/**************************/ +/* single-symbol decoding */ +/**************************/ + +static size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize) +{ + BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1]; + U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; /* large enough for values from 0 to 16 */ + U32 tableLog = 0; + const BYTE* ip = (const BYTE*) src; + size_t iSize = ip[0]; + U32 nbSymbols = 0; + U32 n; + U32 nextRankStart; + void* ptr = DTable+1; + HUF_DEltX2* const dt = (HUF_DEltX2*)ptr; + + HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16)); /* if compilation fails here, assertion is false */ + //memset(huffWeight, 0, sizeof(huffWeight)); /* is not necessary, even though some analyzer complain ... */ + + iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); + if (HUF_isError(iSize)) return iSize; + + /* check result */ + if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge); /* DTable is too small */ + DTable[0] = (U16)tableLog; /* maybe should separate sizeof DTable, as allocated, from used size of DTable, in case of DTable re-use */ + + /* Prepare ranks */ + nextRankStart = 0; + for (n=1; n<=tableLog; n++) + { + U32 current = nextRankStart; + nextRankStart += (rankVal[n] << (n-1)); + rankVal[n] = current; + } + + /* fill DTable */ + for (n=0; n> 1; + U32 i; + HUF_DEltX2 D; + D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w); + for (i = rankVal[w]; i < rankVal[w] + length; i++) + dt[i] = D; + rankVal[w] += length; + } + + return iSize; +} + +static BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog) +{ + const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */ + const BYTE c = dt[val].byte; + BIT_skipBits(Dstream, dt[val].nbBits); + return c; +} + +#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \ + *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog) + +#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \ + if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \ + HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) + +#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \ + if (MEM_64bits()) \ + HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) + +static inline size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog) +{ + BYTE* const pStart = p; + + /* up to 4 symbols at a time */ + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4)) + { + HUF_DECODE_SYMBOLX2_2(p, bitDPtr); + HUF_DECODE_SYMBOLX2_1(p, bitDPtr); + HUF_DECODE_SYMBOLX2_2(p, bitDPtr); + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + } + + /* closer to the end */ + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd)) + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + + /* no more data to retrieve from bitstream, hence no need to reload */ + while (p < pEnd) + HUF_DECODE_SYMBOLX2_0(p, bitDPtr); + + return pEnd-pStart; +} + + +static size_t HUF_decompress4X2_usingDTable( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const U16* DTable) +{ + if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ + + { + const BYTE* const istart = (const BYTE*) cSrc; + BYTE* const ostart = (BYTE*) dst; + BYTE* const oend = ostart + dstSize; + + const void* ptr = DTable; + const HUF_DEltX2* const dt = ((const HUF_DEltX2*)ptr) +1; + const U32 dtLog = DTable[0]; + size_t errorCode; + + /* Init */ + BIT_DStream_t bitD1; + BIT_DStream_t bitD2; + BIT_DStream_t bitD3; + BIT_DStream_t bitD4; + const size_t length1 = MEM_readLE16(istart); + const size_t length2 = MEM_readLE16(istart+2); + const size_t length3 = MEM_readLE16(istart+4); + size_t length4; + const BYTE* const istart1 = istart + 6; /* jumpTable */ + const BYTE* const istart2 = istart1 + length1; + const BYTE* const istart3 = istart2 + length2; + const BYTE* const istart4 = istart3 + length3; + const size_t segmentSize = (dstSize+3) / 4; + BYTE* const opStart2 = ostart + segmentSize; + BYTE* const opStart3 = opStart2 + segmentSize; + BYTE* const opStart4 = opStart3 + segmentSize; + BYTE* op1 = ostart; + BYTE* op2 = opStart2; + BYTE* op3 = opStart3; + BYTE* op4 = opStart4; + U32 endSignal; + + length4 = cSrcSize - (length1 + length2 + length3 + 6); + if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ + errorCode = BIT_initDStream(&bitD1, istart1, length1); + if (HUF_isError(errorCode)) return errorCode; + errorCode = BIT_initDStream(&bitD2, istart2, length2); + if (HUF_isError(errorCode)) return errorCode; + errorCode = BIT_initDStream(&bitD3, istart3, length3); + if (HUF_isError(errorCode)) return errorCode; + errorCode = BIT_initDStream(&bitD4, istart4, length4); + if (HUF_isError(errorCode)) return errorCode; + + /* 16-32 symbols per loop (4-8 symbols per stream) */ + endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; ) + { + HUF_DECODE_SYMBOLX2_2(op1, &bitD1); + HUF_DECODE_SYMBOLX2_2(op2, &bitD2); + HUF_DECODE_SYMBOLX2_2(op3, &bitD3); + HUF_DECODE_SYMBOLX2_2(op4, &bitD4); + HUF_DECODE_SYMBOLX2_1(op1, &bitD1); + HUF_DECODE_SYMBOLX2_1(op2, &bitD2); + HUF_DECODE_SYMBOLX2_1(op3, &bitD3); + HUF_DECODE_SYMBOLX2_1(op4, &bitD4); + HUF_DECODE_SYMBOLX2_2(op1, &bitD1); + HUF_DECODE_SYMBOLX2_2(op2, &bitD2); + HUF_DECODE_SYMBOLX2_2(op3, &bitD3); + HUF_DECODE_SYMBOLX2_2(op4, &bitD4); + HUF_DECODE_SYMBOLX2_0(op1, &bitD1); + HUF_DECODE_SYMBOLX2_0(op2, &bitD2); + HUF_DECODE_SYMBOLX2_0(op3, &bitD3); + HUF_DECODE_SYMBOLX2_0(op4, &bitD4); + + endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + } + + /* check corruption */ + if (op1 > opStart2) return ERROR(corruption_detected); + if (op2 > opStart3) return ERROR(corruption_detected); + if (op3 > opStart4) return ERROR(corruption_detected); + /* note : op4 supposed already verified within main loop */ + + /* finish bitStreams one by one */ + HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog); + HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog); + HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog); + HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog); + + /* check */ + endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); + if (!endSignal) return ERROR(corruption_detected); + + /* decoded size */ + return dstSize; + } +} + + +static size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG); + const BYTE* ip = (const BYTE*) cSrc; + size_t errorCode; + + errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize); + if (HUF_isError(errorCode)) return errorCode; + if (errorCode >= cSrcSize) return ERROR(srcSize_wrong); + ip += errorCode; + cSrcSize -= errorCode; + + return HUF_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable); +} + + +/***************************/ +/* double-symbols decoding */ +/***************************/ + +static void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed, + const U32* rankValOrigin, const int minWeight, + const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, + U32 nbBitsBaseline, U16 baseSeq) +{ + HUF_DEltX4 DElt; + U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; + U32 s; + + /* get pre-calculated rankVal */ + memcpy(rankVal, rankValOrigin, sizeof(rankVal)); + + /* fill skipped values */ + if (minWeight>1) + { + U32 i, skipSize = rankVal[minWeight]; + MEM_writeLE16(&(DElt.sequence), baseSeq); + DElt.nbBits = (BYTE)(consumed); + DElt.length = 1; + for (i = 0; i < skipSize; i++) + DTable[i] = DElt; + } + + /* fill DTable */ + for (s=0; s= 1 */ + + rankVal[weight] += length; + } +} + +typedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1]; + +static void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog, + const sortedSymbol_t* sortedList, const U32 sortedListSize, + const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight, + const U32 nbBitsBaseline) +{ + U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; + const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */ + const U32 minBits = nbBitsBaseline - maxWeight; + U32 s; + + memcpy(rankVal, rankValOrigin, sizeof(rankVal)); + + /* fill DTable */ + for (s=0; s= minBits) /* enough room for a second symbol */ + { + U32 sortedRank; + int minWeight = nbBits + scaleLog; + if (minWeight < 1) minWeight = 1; + sortedRank = rankStart[minWeight]; + HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits, + rankValOrigin[nbBits], minWeight, + sortedList+sortedRank, sortedListSize-sortedRank, + nbBitsBaseline, symbol); + } + else + { + U32 i; + const U32 end = start + length; + HUF_DEltX4 DElt; + + MEM_writeLE16(&(DElt.sequence), symbol); + DElt.nbBits = (BYTE)(nbBits); + DElt.length = 1; + for (i = start; i < end; i++) + DTable[i] = DElt; + } + rankVal[weight] += length; + } +} + +static size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize) +{ + BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1]; + sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1]; + U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 }; + U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 }; + U32* const rankStart = rankStart0+1; + rankVal_t rankVal; + U32 tableLog, maxW, sizeOfSort, nbSymbols; + const U32 memLog = DTable[0]; + const BYTE* ip = (const BYTE*) src; + size_t iSize = ip[0]; + void* ptr = DTable; + HUF_DEltX4* const dt = ((HUF_DEltX4*)ptr) + 1; + + HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32)); /* if compilation fails here, assertion is false */ + if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge); + //memset(weightList, 0, sizeof(weightList)); /* is not necessary, even though some analyzer complain ... */ + + iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); + if (HUF_isError(iSize)) return iSize; + + /* check result */ + if (tableLog > memLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */ + + /* find maxWeight */ + for (maxW = tableLog; rankStats[maxW]==0; maxW--) + {if (!maxW) return ERROR(GENERIC); } /* necessarily finds a solution before maxW==0 */ + + /* Get start index of each weight */ + { + U32 w, nextRankStart = 0; + for (w=1; w<=maxW; w++) + { + U32 current = nextRankStart; + nextRankStart += rankStats[w]; + rankStart[w] = current; + } + rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/ + sizeOfSort = nextRankStart; + } + + /* sort symbols by weight */ + { + U32 s; + for (s=0; s> consumed; + } + } + } + + HUF_fillDTableX4(dt, memLog, + sortedSymbol, sizeOfSort, + rankStart0, rankVal, maxW, + tableLog+1); + + return iSize; +} + + +static U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog) +{ + const size_t val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ + memcpy(op, dt+val, 2); + BIT_skipBits(DStream, dt[val].nbBits); + return dt[val].length; +} + +static U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog) +{ + const size_t val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ + memcpy(op, dt+val, 1); + if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits); + else + { + if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) + { + BIT_skipBits(DStream, dt[val].nbBits); + if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8)) + DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8); /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ + } + } + return 1; +} + + +#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \ + ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) + +#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \ + if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \ + ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) + +#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \ + if (MEM_64bits()) \ + ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) + +static inline size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog) +{ + BYTE* const pStart = p; + + /* up to 8 symbols at a time */ + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd-7)) + { + HUF_DECODE_SYMBOLX4_2(p, bitDPtr); + HUF_DECODE_SYMBOLX4_1(p, bitDPtr); + HUF_DECODE_SYMBOLX4_2(p, bitDPtr); + HUF_DECODE_SYMBOLX4_0(p, bitDPtr); + } + + /* closer to the end */ + while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-2)) + HUF_DECODE_SYMBOLX4_0(p, bitDPtr); + + while (p <= pEnd-2) + HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */ + + if (p < pEnd) + p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog); + + return p-pStart; +} + + + +static size_t HUF_decompress4X4_usingDTable( + void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize, + const U32* DTable) +{ + if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ + + { + const BYTE* const istart = (const BYTE*) cSrc; + BYTE* const ostart = (BYTE*) dst; + BYTE* const oend = ostart + dstSize; + + const void* ptr = DTable; + const HUF_DEltX4* const dt = ((const HUF_DEltX4*)ptr) +1; + const U32 dtLog = DTable[0]; + size_t errorCode; + + /* Init */ + BIT_DStream_t bitD1; + BIT_DStream_t bitD2; + BIT_DStream_t bitD3; + BIT_DStream_t bitD4; + const size_t length1 = MEM_readLE16(istart); + const size_t length2 = MEM_readLE16(istart+2); + const size_t length3 = MEM_readLE16(istart+4); + size_t length4; + const BYTE* const istart1 = istart + 6; /* jumpTable */ + const BYTE* const istart2 = istart1 + length1; + const BYTE* const istart3 = istart2 + length2; + const BYTE* const istart4 = istart3 + length3; + const size_t segmentSize = (dstSize+3) / 4; + BYTE* const opStart2 = ostart + segmentSize; + BYTE* const opStart3 = opStart2 + segmentSize; + BYTE* const opStart4 = opStart3 + segmentSize; + BYTE* op1 = ostart; + BYTE* op2 = opStart2; + BYTE* op3 = opStart3; + BYTE* op4 = opStart4; + U32 endSignal; + + length4 = cSrcSize - (length1 + length2 + length3 + 6); + if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */ + errorCode = BIT_initDStream(&bitD1, istart1, length1); + if (HUF_isError(errorCode)) return errorCode; + errorCode = BIT_initDStream(&bitD2, istart2, length2); + if (HUF_isError(errorCode)) return errorCode; + errorCode = BIT_initDStream(&bitD3, istart3, length3); + if (HUF_isError(errorCode)) return errorCode; + errorCode = BIT_initDStream(&bitD4, istart4, length4); + if (HUF_isError(errorCode)) return errorCode; + + /* 16-32 symbols per loop (4-8 symbols per stream) */ + endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; ) + { + HUF_DECODE_SYMBOLX4_2(op1, &bitD1); + HUF_DECODE_SYMBOLX4_2(op2, &bitD2); + HUF_DECODE_SYMBOLX4_2(op3, &bitD3); + HUF_DECODE_SYMBOLX4_2(op4, &bitD4); + HUF_DECODE_SYMBOLX4_1(op1, &bitD1); + HUF_DECODE_SYMBOLX4_1(op2, &bitD2); + HUF_DECODE_SYMBOLX4_1(op3, &bitD3); + HUF_DECODE_SYMBOLX4_1(op4, &bitD4); + HUF_DECODE_SYMBOLX4_2(op1, &bitD1); + HUF_DECODE_SYMBOLX4_2(op2, &bitD2); + HUF_DECODE_SYMBOLX4_2(op3, &bitD3); + HUF_DECODE_SYMBOLX4_2(op4, &bitD4); + HUF_DECODE_SYMBOLX4_0(op1, &bitD1); + HUF_DECODE_SYMBOLX4_0(op2, &bitD2); + HUF_DECODE_SYMBOLX4_0(op3, &bitD3); + HUF_DECODE_SYMBOLX4_0(op4, &bitD4); + + endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); + } + + /* check corruption */ + if (op1 > opStart2) return ERROR(corruption_detected); + if (op2 > opStart3) return ERROR(corruption_detected); + if (op3 > opStart4) return ERROR(corruption_detected); + /* note : op4 supposed already verified within main loop */ + + /* finish bitStreams one by one */ + HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog); + HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog); + HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog); + HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog); + + /* check */ + endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); + if (!endSignal) return ERROR(corruption_detected); + + /* decoded size */ + return dstSize; + } +} + + +static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG); + const BYTE* ip = (const BYTE*) cSrc; + + size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize); + if (HUF_isError(hSize)) return hSize; + if (hSize >= cSrcSize) return ERROR(srcSize_wrong); + ip += hSize; + cSrcSize -= hSize; + + return HUF_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable); +} + + +/**********************************/ +/* quad-symbol decoding */ +/**********************************/ +typedef struct { BYTE nbBits; BYTE nbBytes; } HUF_DDescX6; +typedef union { BYTE byte[4]; U32 sequence; } HUF_DSeqX6; + +/* recursive, up to level 3; may benefit from